Repository: mhogrefe/malachite Branch: master Commit: 9fd25828c9ab Files: 2707 Total size: 35.5 MB Directory structure: gitextract_3ecze51d/ ├── .envrc ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── rust.yml ├── .gitignore ├── .vscode/ │ ├── launch.json │ └── tasks.json ├── COPYING ├── COPYING.LESSER ├── Cargo.toml ├── LICENSE ├── README.md ├── _config.yml ├── additional-lints.py ├── build.sh ├── docs/ │ ├── CNAME │ ├── _config.yml │ ├── _includes/ │ │ └── head-custom.html │ ├── _layouts/ │ │ └── post.html │ ├── _posts/ │ │ ├── 2022-06-05-1-intro.md │ │ ├── 2022-06-05-2-exhaustive.md │ │ ├── 2022-07-03-exhaustive.md │ │ └── 2022-07-30-denominators.md │ ├── assets/ │ │ ├── denominators/ │ │ │ ├── gap-and-bound-graph.asy │ │ │ ├── gap-graph.asy │ │ │ ├── gaps.asy │ │ │ ├── j-graph.asy │ │ │ └── sixths.asy │ │ ├── exhaustive-part-2/ │ │ │ ├── cantor-graph.asy │ │ │ ├── cantor-grid.asy │ │ │ ├── cantor-large.tex │ │ │ ├── cantor-triples-large.tex │ │ │ ├── interleave-bits-1.tex │ │ │ ├── interleave-bits-2.tex │ │ │ ├── interleave-grid-filtered.asy │ │ │ ├── interleave-grid.asy │ │ │ ├── interleave-large.tex │ │ │ ├── interleave-pairs-graph.asy │ │ │ ├── interleave-triples-bits.tex │ │ │ ├── interleave-triples-graph.asy │ │ │ └── interleave-triples-large.tex │ │ └── logo.asy │ ├── index.md │ └── performance.md ├── find_replace.py ├── flake.nix ├── katex-header.html ├── malachite/ │ ├── Cargo.toml │ ├── katex-header.html │ └── src/ │ └── lib.rs ├── malachite-base/ │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── katex-header.html │ ├── rustfmt.toml │ ├── src/ │ │ ├── bin.rs │ │ ├── bin_util/ │ │ │ ├── demo_and_bench/ │ │ │ │ ├── bools/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── not_assign.rs │ │ │ │ ├── chars/ │ │ │ │ │ ├── crement/ │ │ │ │ │ │ ├── char_to_contiguous_range.rs │ │ │ │ │ │ ├── contiguous_range_to_char.rs │ │ │ │ │ │ ├── crement.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── comparison/ │ │ │ │ │ ├── macros.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── num/ │ │ │ │ │ ├── arithmetic/ │ │ │ │ │ │ ├── abs.rs │ │ │ │ │ │ ├── abs_diff.rs │ │ │ │ │ │ ├── add_mul.rs │ │ │ │ │ │ ├── arithmetic_checked_shl.rs │ │ │ │ │ │ ├── arithmetic_checked_shr.rs │ │ │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ │ │ ├── ceiling.rs │ │ │ │ │ │ ├── checked_add_mul.rs │ │ │ │ │ │ ├── checked_square.rs │ │ │ │ │ │ ├── checked_sub_mul.rs │ │ │ │ │ │ ├── coprime_with.rs │ │ │ │ │ │ ├── div_exact.rs │ │ │ │ │ │ ├── div_mod.rs │ │ │ │ │ │ ├── div_round.rs │ │ │ │ │ │ ├── divisible_by.rs │ │ │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ │ │ ├── eq_mod.rs │ │ │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ │ │ ├── extended_gcd.rs │ │ │ │ │ │ ├── factorial.rs │ │ │ │ │ │ ├── floor.rs │ │ │ │ │ │ ├── gcd.rs │ │ │ │ │ │ ├── is_power_of_2.rs │ │ │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ │ │ ├── lcm.rs │ │ │ │ │ │ ├── log_base.rs │ │ │ │ │ │ ├── log_base_2.rs │ │ │ │ │ │ ├── log_base_power_of_2.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── mod_add.rs │ │ │ │ │ │ ├── mod_inverse.rs │ │ │ │ │ │ ├── mod_is_reduced.rs │ │ │ │ │ │ ├── mod_mul.rs │ │ │ │ │ │ ├── mod_neg.rs │ │ │ │ │ │ ├── mod_op.rs │ │ │ │ │ │ ├── mod_pow.rs │ │ │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ │ │ ├── mod_power_of_2_add.rs │ │ │ │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ │ │ │ ├── mod_power_of_2_is_reduced.rs │ │ │ │ │ │ ├── mod_power_of_2_mul.rs │ │ │ │ │ │ ├── mod_power_of_2_neg.rs │ │ │ │ │ │ ├── mod_power_of_2_pow.rs │ │ │ │ │ │ ├── mod_power_of_2_shl.rs │ │ │ │ │ │ ├── mod_power_of_2_shr.rs │ │ │ │ │ │ ├── mod_power_of_2_square.rs │ │ │ │ │ │ ├── mod_power_of_2_sub.rs │ │ │ │ │ │ ├── mod_shl.rs │ │ │ │ │ │ ├── mod_shr.rs │ │ │ │ │ │ ├── mod_square.rs │ │ │ │ │ │ ├── mod_sub.rs │ │ │ │ │ │ ├── neg.rs │ │ │ │ │ │ ├── next_power_of_2.rs │ │ │ │ │ │ ├── overflowing_abs.rs │ │ │ │ │ │ ├── overflowing_add.rs │ │ │ │ │ │ ├── overflowing_add_mul.rs │ │ │ │ │ │ ├── overflowing_div.rs │ │ │ │ │ │ ├── overflowing_mul.rs │ │ │ │ │ │ ├── overflowing_neg.rs │ │ │ │ │ │ ├── overflowing_pow.rs │ │ │ │ │ │ ├── overflowing_square.rs │ │ │ │ │ │ ├── overflowing_sub.rs │ │ │ │ │ │ ├── overflowing_sub_mul.rs │ │ │ │ │ │ ├── parity.rs │ │ │ │ │ │ ├── pow.rs │ │ │ │ │ │ ├── power_of_2.rs │ │ │ │ │ │ ├── primorial.rs │ │ │ │ │ │ ├── reciprocal.rs │ │ │ │ │ │ ├── root.rs │ │ │ │ │ │ ├── rotate.rs │ │ │ │ │ │ ├── round_to_multiple.rs │ │ │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ │ │ ├── saturating_abs.rs │ │ │ │ │ │ ├── saturating_add.rs │ │ │ │ │ │ ├── saturating_add_mul.rs │ │ │ │ │ │ ├── saturating_mul.rs │ │ │ │ │ │ ├── saturating_neg.rs │ │ │ │ │ │ ├── saturating_pow.rs │ │ │ │ │ │ ├── saturating_square.rs │ │ │ │ │ │ ├── saturating_sub.rs │ │ │ │ │ │ ├── saturating_sub_mul.rs │ │ │ │ │ │ ├── shl_round.rs │ │ │ │ │ │ ├── shr_round.rs │ │ │ │ │ │ ├── sign.rs │ │ │ │ │ │ ├── sqrt.rs │ │ │ │ │ │ ├── square.rs │ │ │ │ │ │ ├── sub_mul.rs │ │ │ │ │ │ ├── wrapping_abs.rs │ │ │ │ │ │ ├── wrapping_add.rs │ │ │ │ │ │ ├── wrapping_add_mul.rs │ │ │ │ │ │ ├── wrapping_div.rs │ │ │ │ │ │ ├── wrapping_mul.rs │ │ │ │ │ │ ├── wrapping_neg.rs │ │ │ │ │ │ ├── wrapping_pow.rs │ │ │ │ │ │ ├── wrapping_square.rs │ │ │ │ │ │ ├── wrapping_sub.rs │ │ │ │ │ │ ├── wrapping_sub_mul.rs │ │ │ │ │ │ ├── x_mul_y_to_zz.rs │ │ │ │ │ │ ├── xx_add_yy_to_zz.rs │ │ │ │ │ │ ├── xx_div_mod_y_to_qr.rs │ │ │ │ │ │ ├── xx_sub_yy_to_zz.rs │ │ │ │ │ │ ├── xxx_add_yyy_to_zzz.rs │ │ │ │ │ │ ├── xxx_sub_yyy_to_zzz.rs │ │ │ │ │ │ └── xxxx_add_yyyy_to_zzzz.rs │ │ │ │ │ ├── comparison/ │ │ │ │ │ │ ├── cmp_abs.rs │ │ │ │ │ │ ├── eq_abs.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── ord_abs_comparators.rs │ │ │ │ │ ├── conversion/ │ │ │ │ │ │ ├── digits/ │ │ │ │ │ │ │ ├── general_digits/ │ │ │ │ │ │ │ │ ├── from_digits.rs │ │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ │ └── to_digits.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ └── power_of_2_digits/ │ │ │ │ │ │ │ ├── from_power_of_2_digits.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── power_of_2_digit_iterable.rs │ │ │ │ │ │ │ └── to_power_of_2_digits.rs │ │ │ │ │ │ ├── from/ │ │ │ │ │ │ │ ├── convertible_from.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── overflowing_from.rs │ │ │ │ │ │ │ ├── rounding_from.rs │ │ │ │ │ │ │ ├── saturating_from.rs │ │ │ │ │ │ │ ├── try_from_and_exact_from.rs │ │ │ │ │ │ │ └── wrapping_from.rs │ │ │ │ │ │ ├── half/ │ │ │ │ │ │ │ ├── join_halves.rs │ │ │ │ │ │ │ ├── lower_half.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── split_in_half.rs │ │ │ │ │ │ │ └── upper_half.rs │ │ │ │ │ │ ├── is_integer.rs │ │ │ │ │ │ ├── mantissa_and_exponent/ │ │ │ │ │ │ │ ├── integer_mantissa_and_exponent.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── raw_mantissa_and_exponent.rs │ │ │ │ │ │ │ └── sci_mantissa_and_exponent.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── slice/ │ │ │ │ │ │ │ ├── from_other_type_slice.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── vec_from_other_type.rs │ │ │ │ │ │ │ └── vec_from_other_type_slice.rs │ │ │ │ │ │ └── string/ │ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ │ ├── from_string.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── options/ │ │ │ │ │ │ │ ├── from_sci_string_options.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── sci_size_options.rs │ │ │ │ │ │ │ └── to_sci_options.rs │ │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ │ └── to_string.rs │ │ │ │ │ ├── factorization/ │ │ │ │ │ │ ├── factor.rs │ │ │ │ │ │ ├── is_power.rs │ │ │ │ │ │ ├── is_prime.rs │ │ │ │ │ │ ├── is_square.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── prime_sieve.rs │ │ │ │ │ │ ├── primes.rs │ │ │ │ │ │ └── primitive_root_prime.rs │ │ │ │ │ ├── float/ │ │ │ │ │ │ ├── basic/ │ │ │ │ │ │ │ ├── abs_negative_zero.rs │ │ │ │ │ │ │ ├── from_ordered_representation.rs │ │ │ │ │ │ │ ├── is_negative_zero.rs │ │ │ │ │ │ │ ├── max_precision_for_sci_exponent.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── next_higher.rs │ │ │ │ │ │ │ ├── next_lower.rs │ │ │ │ │ │ │ ├── precision.rs │ │ │ │ │ │ │ └── to_ordered_representation.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── nice_float/ │ │ │ │ │ │ ├── cmp.rs │ │ │ │ │ │ ├── cmp_abs.rs │ │ │ │ │ │ ├── eq.rs │ │ │ │ │ │ ├── eq_abs.rs │ │ │ │ │ │ ├── from_str.rs │ │ │ │ │ │ ├── hash.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── to_string.rs │ │ │ │ │ ├── logic/ │ │ │ │ │ │ ├── bit_access/ │ │ │ │ │ │ │ ├── assign_bit.rs │ │ │ │ │ │ │ ├── clear_bit.rs │ │ │ │ │ │ │ ├── flip_bit.rs │ │ │ │ │ │ │ ├── get_bit.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ └── set_bit.rs │ │ │ │ │ │ ├── bit_block_access/ │ │ │ │ │ │ │ ├── assign_bits.rs │ │ │ │ │ │ │ ├── get_bits.rs │ │ │ │ │ │ │ └── mod.rs │ │ │ │ │ │ ├── bit_convertible/ │ │ │ │ │ │ │ ├── from_bits.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ └── to_bits.rs │ │ │ │ │ │ ├── bit_iterable.rs │ │ │ │ │ │ ├── bit_scan/ │ │ │ │ │ │ │ ├── index_of_next_false_bit.rs │ │ │ │ │ │ │ ├── index_of_next_true_bit.rs │ │ │ │ │ │ │ └── mod.rs │ │ │ │ │ │ ├── get_highest_bit.rs │ │ │ │ │ │ ├── hamming_distance.rs │ │ │ │ │ │ ├── low_mask.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── not_assign.rs │ │ │ │ │ │ └── significant_bits.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── rational_sequences/ │ │ │ │ │ ├── access/ │ │ │ │ │ │ ├── get.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── mutate.rs │ │ │ │ │ ├── basic/ │ │ │ │ │ │ ├── component_len.rs │ │ │ │ │ │ ├── is_empty.rs │ │ │ │ │ │ ├── is_finite.rs │ │ │ │ │ │ ├── iter.rs │ │ │ │ │ │ ├── len.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ ├── comparison/ │ │ │ │ │ │ ├── cmp.rs │ │ │ │ │ │ ├── eq.rs │ │ │ │ │ │ ├── hash.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ ├── conversion/ │ │ │ │ │ │ ├── clone.rs │ │ │ │ │ │ ├── from_vec.rs │ │ │ │ │ │ ├── from_vecs.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── to_vecs.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── to_string.rs │ │ │ │ ├── rounding_modes/ │ │ │ │ │ ├── clone.rs │ │ │ │ │ ├── eq.rs │ │ │ │ │ ├── from_str.rs │ │ │ │ │ ├── hash.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── neg.rs │ │ │ │ │ └── to_string.rs │ │ │ │ ├── slices/ │ │ │ │ │ ├── min_repeating_len.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── slice_leading_zeros.rs │ │ │ │ │ ├── slice_move_left.rs │ │ │ │ │ ├── slice_set_zero.rs │ │ │ │ │ ├── slice_test_zero.rs │ │ │ │ │ ├── slice_trailing_zeros.rs │ │ │ │ │ └── split_into_chunks.rs │ │ │ │ ├── strings/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── string_is_subset.rs │ │ │ │ │ ├── string_sort.rs │ │ │ │ │ └── string_unique.rs │ │ │ │ └── vecs/ │ │ │ │ ├── mod.rs │ │ │ │ ├── vec_delete_left.rs │ │ │ │ └── vec_pad_left.rs │ │ │ └── generate/ │ │ │ ├── max_base.rs │ │ │ ├── mod.rs │ │ │ ├── rle.rs │ │ │ └── tuning_manager.rs │ │ ├── bools/ │ │ │ ├── constants.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ ├── not_assign.rs │ │ │ └── random.rs │ │ ├── chars/ │ │ │ ├── constants.rs │ │ │ ├── crement.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── comparison/ │ │ │ ├── macros.rs │ │ │ ├── mod.rs │ │ │ └── traits.rs │ │ ├── iterators/ │ │ │ ├── bit_distributor.rs │ │ │ ├── comparison.rs │ │ │ ├── iterator_cache.rs │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── macros/ │ │ │ └── mod.rs │ │ ├── named/ │ │ │ └── mod.rs │ │ ├── nevers/ │ │ │ └── mod.rs │ │ ├── num/ │ │ │ ├── arithmetic/ │ │ │ │ ├── abs.rs │ │ │ │ ├── abs_diff.rs │ │ │ │ ├── add_mul.rs │ │ │ │ ├── arithmetic_checked_shl.rs │ │ │ │ ├── arithmetic_checked_shr.rs │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ ├── ceiling.rs │ │ │ │ ├── checked_abs.rs │ │ │ │ ├── checked_add.rs │ │ │ │ ├── checked_add_mul.rs │ │ │ │ ├── checked_div.rs │ │ │ │ ├── checked_mul.rs │ │ │ │ ├── checked_neg.rs │ │ │ │ ├── checked_next_power_of_2.rs │ │ │ │ ├── checked_pow.rs │ │ │ │ ├── checked_square.rs │ │ │ │ ├── checked_sub.rs │ │ │ │ ├── checked_sub_mul.rs │ │ │ │ ├── coprime_with.rs │ │ │ │ ├── div_exact.rs │ │ │ │ ├── div_mod.rs │ │ │ │ ├── div_round.rs │ │ │ │ ├── divisible_by.rs │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ ├── eq_mod.rs │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ ├── extended_gcd.rs │ │ │ │ ├── factorial.rs │ │ │ │ ├── floor.rs │ │ │ │ ├── gcd.rs │ │ │ │ ├── is_power_of_2.rs │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ ├── lcm.rs │ │ │ │ ├── log_base.rs │ │ │ │ ├── log_base_2.rs │ │ │ │ ├── log_base_power_of_2.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mod_add.rs │ │ │ │ ├── mod_inverse.rs │ │ │ │ ├── mod_is_reduced.rs │ │ │ │ ├── mod_mul.rs │ │ │ │ ├── mod_neg.rs │ │ │ │ ├── mod_op.rs │ │ │ │ ├── mod_pow.rs │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ ├── mod_power_of_2_add.rs │ │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ │ ├── mod_power_of_2_is_reduced.rs │ │ │ │ ├── mod_power_of_2_mul.rs │ │ │ │ ├── mod_power_of_2_neg.rs │ │ │ │ ├── mod_power_of_2_pow.rs │ │ │ │ ├── mod_power_of_2_shl.rs │ │ │ │ ├── mod_power_of_2_shr.rs │ │ │ │ ├── mod_power_of_2_square.rs │ │ │ │ ├── mod_power_of_2_sub.rs │ │ │ │ ├── mod_shl.rs │ │ │ │ ├── mod_shr.rs │ │ │ │ ├── mod_square.rs │ │ │ │ ├── mod_sub.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── next_power_of_2.rs │ │ │ │ ├── overflowing_abs.rs │ │ │ │ ├── overflowing_add.rs │ │ │ │ ├── overflowing_add_mul.rs │ │ │ │ ├── overflowing_div.rs │ │ │ │ ├── overflowing_mul.rs │ │ │ │ ├── overflowing_neg.rs │ │ │ │ ├── overflowing_pow.rs │ │ │ │ ├── overflowing_square.rs │ │ │ │ ├── overflowing_sub.rs │ │ │ │ ├── overflowing_sub_mul.rs │ │ │ │ ├── parity.rs │ │ │ │ ├── pow.rs │ │ │ │ ├── power_of_2.rs │ │ │ │ ├── primorial.rs │ │ │ │ ├── reciprocal.rs │ │ │ │ ├── root.rs │ │ │ │ ├── rotate.rs │ │ │ │ ├── round_to_multiple.rs │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ ├── saturating_abs.rs │ │ │ │ ├── saturating_add.rs │ │ │ │ ├── saturating_add_mul.rs │ │ │ │ ├── saturating_mul.rs │ │ │ │ ├── saturating_neg.rs │ │ │ │ ├── saturating_pow.rs │ │ │ │ ├── saturating_square.rs │ │ │ │ ├── saturating_sub.rs │ │ │ │ ├── saturating_sub_mul.rs │ │ │ │ ├── shl_round.rs │ │ │ │ ├── shr_round.rs │ │ │ │ ├── sign.rs │ │ │ │ ├── sqrt.rs │ │ │ │ ├── square.rs │ │ │ │ ├── sub_mul.rs │ │ │ │ ├── traits.rs │ │ │ │ ├── wrapping_abs.rs │ │ │ │ ├── wrapping_add.rs │ │ │ │ ├── wrapping_add_mul.rs │ │ │ │ ├── wrapping_div.rs │ │ │ │ ├── wrapping_mul.rs │ │ │ │ ├── wrapping_neg.rs │ │ │ │ ├── wrapping_pow.rs │ │ │ │ ├── wrapping_square.rs │ │ │ │ ├── wrapping_sub.rs │ │ │ │ ├── wrapping_sub_mul.rs │ │ │ │ ├── x_mul_y_to_zz.rs │ │ │ │ ├── xx_add_yy_to_zz.rs │ │ │ │ ├── xx_div_mod_y_to_qr.rs │ │ │ │ ├── xx_sub_yy_to_zz.rs │ │ │ │ ├── xxx_add_yyy_to_zzz.rs │ │ │ │ ├── xxx_sub_yyy_to_zzz.rs │ │ │ │ └── xxxx_add_yyyy_to_zzzz.rs │ │ │ ├── basic/ │ │ │ │ ├── floats.rs │ │ │ │ ├── integers.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── signeds.rs │ │ │ │ ├── traits.rs │ │ │ │ └── unsigneds.rs │ │ │ ├── comparison/ │ │ │ │ ├── cmp_abs.rs │ │ │ │ ├── eq_abs.rs │ │ │ │ ├── mod.rs │ │ │ │ └── traits.rs │ │ │ ├── conversion/ │ │ │ │ ├── digits/ │ │ │ │ │ ├── general_digits.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── power_of_2_digit_iterable.rs │ │ │ │ │ └── power_of_2_digits.rs │ │ │ │ ├── from.rs │ │ │ │ ├── half.rs │ │ │ │ ├── is_integer.rs │ │ │ │ ├── mantissa_and_exponent.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── slice.rs │ │ │ │ ├── string/ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ ├── from_string.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── options/ │ │ │ │ │ │ ├── exhaustive.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── random.rs │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ └── to_string.rs │ │ │ │ └── traits.rs │ │ │ ├── exhaustive/ │ │ │ │ └── mod.rs │ │ │ ├── factorization/ │ │ │ │ ├── factor.rs │ │ │ │ ├── is_power.rs │ │ │ │ ├── is_prime.rs │ │ │ │ ├── is_square.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── prime_sieve.rs │ │ │ │ ├── primes.rs │ │ │ │ ├── primitive_root_prime.rs │ │ │ │ └── traits.rs │ │ │ ├── float/ │ │ │ │ └── mod.rs │ │ │ ├── iterators/ │ │ │ │ └── mod.rs │ │ │ ├── logic/ │ │ │ │ ├── bit_access.rs │ │ │ │ ├── bit_block_access.rs │ │ │ │ ├── bit_convertible.rs │ │ │ │ ├── bit_iterable.rs │ │ │ │ ├── bit_scan.rs │ │ │ │ ├── count_ones.rs │ │ │ │ ├── count_zeros.rs │ │ │ │ ├── hamming_distance.rs │ │ │ │ ├── leading_zeros.rs │ │ │ │ ├── low_mask.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── not.rs │ │ │ │ ├── significant_bits.rs │ │ │ │ ├── trailing_zeros.rs │ │ │ │ └── traits.rs │ │ │ ├── macros.rs │ │ │ ├── mod.rs │ │ │ └── random/ │ │ │ ├── geometric.rs │ │ │ ├── mod.rs │ │ │ └── striped.rs │ │ ├── options/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── orderings/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── platform.rs │ │ ├── random/ │ │ │ └── mod.rs │ │ ├── rational_sequences/ │ │ │ ├── access.rs │ │ │ ├── cmp.rs │ │ │ ├── conversion.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ ├── random.rs │ │ │ └── to_string.rs │ │ ├── rounding_modes/ │ │ │ ├── exhaustive.rs │ │ │ ├── from_str.rs │ │ │ ├── mod.rs │ │ │ ├── neg.rs │ │ │ ├── random.rs │ │ │ └── to_string.rs │ │ ├── sets/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── slices/ │ │ │ └── mod.rs │ │ ├── strings/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── test_util/ │ │ │ ├── bench/ │ │ │ │ ├── bucketers.rs │ │ │ │ └── mod.rs │ │ │ ├── common/ │ │ │ │ └── mod.rs │ │ │ ├── extra_variadic/ │ │ │ │ └── mod.rs │ │ │ ├── generators/ │ │ │ │ ├── common.rs │ │ │ │ ├── exhaustive.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── random.rs │ │ │ │ └── special_random.rs │ │ │ ├── hash/ │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ ├── num/ │ │ │ │ ├── arithmetic/ │ │ │ │ │ ├── extended_gcd.rs │ │ │ │ │ ├── factorial.rs │ │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── mod_inverse.rs │ │ │ │ │ ├── mod_mul.rs │ │ │ │ │ ├── mod_pow.rs │ │ │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ │ │ └── primorial.rs │ │ │ │ ├── conversion/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── string/ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── to_string.rs │ │ │ │ ├── exhaustive/ │ │ │ │ │ └── mod.rs │ │ │ │ ├── factorization/ │ │ │ │ │ ├── factor.rs │ │ │ │ │ ├── is_prime.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── prime_sieve.rs │ │ │ │ │ └── primes.rs │ │ │ │ ├── float/ │ │ │ │ │ └── mod.rs │ │ │ │ ├── logic/ │ │ │ │ │ ├── bit_block_access.rs │ │ │ │ │ ├── bit_convertible.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── random/ │ │ │ │ ├── geometric.rs │ │ │ │ └── mod.rs │ │ │ ├── rounding_modes/ │ │ │ │ └── mod.rs │ │ │ ├── runner/ │ │ │ │ ├── cmd.rs │ │ │ │ └── mod.rs │ │ │ ├── sets/ │ │ │ │ ├── exhaustive/ │ │ │ │ │ └── mod.rs │ │ │ │ └── mod.rs │ │ │ ├── slices/ │ │ │ │ └── mod.rs │ │ │ ├── stats/ │ │ │ │ ├── common_values_map.rs │ │ │ │ ├── median.rs │ │ │ │ ├── mod.rs │ │ │ │ └── moments.rs │ │ │ └── vecs/ │ │ │ ├── exhaustive/ │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ └── random/ │ │ │ └── mod.rs │ │ ├── tuples/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ ├── unions/ │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ └── random.rs │ │ └── vecs/ │ │ ├── exhaustive.rs │ │ ├── mod.rs │ │ └── random.rs │ └── tests/ │ ├── bools/ │ │ ├── constants.rs │ │ ├── exhaustive.rs │ │ ├── not_assign.rs │ │ └── random/ │ │ ├── get_weighted_random_bool.rs │ │ ├── random_bools.rs │ │ └── weighted_random_bools.rs │ ├── chars/ │ │ ├── char_type.rs │ │ ├── constants.rs │ │ ├── crement/ │ │ │ ├── char_to_contiguous_range.rs │ │ │ ├── contiguous_range_to_char.rs │ │ │ └── crement.rs │ │ ├── exhaustive/ │ │ │ ├── ascii_chars_increasing.rs │ │ │ ├── chars_increasing.rs │ │ │ ├── exhaustive_ascii_chars.rs │ │ │ └── exhaustive_chars.rs │ │ ├── is_graphic.rs │ │ └── random/ │ │ ├── graphic_weighted_random_ascii_chars.rs │ │ ├── graphic_weighted_random_char_inclusive_range.rs │ │ ├── graphic_weighted_random_char_range.rs │ │ ├── graphic_weighted_random_chars.rs │ │ ├── random_ascii_chars.rs │ │ ├── random_char_inclusive_range.rs │ │ ├── random_char_range.rs │ │ └── random_chars.rs │ ├── comparison/ │ │ └── macros.rs │ ├── extra_variadic/ │ │ └── mod.rs │ ├── iterators/ │ │ ├── bit_distributor/ │ │ │ ├── bit_map_as_slice.rs │ │ │ ├── get_output.rs │ │ │ ├── increment_counter.rs │ │ │ ├── new.rs │ │ │ └── set_max_bits.rs │ │ ├── comparison/ │ │ │ ├── delta_directions.rs │ │ │ ├── is_strictly_ascending.rs │ │ │ ├── is_strictly_descending.rs │ │ │ ├── is_strictly_zigzagging.rs │ │ │ ├── is_weakly_ascending.rs │ │ │ ├── is_weakly_descending.rs │ │ │ └── is_weakly_zigzagging.rs │ │ ├── count_is_at_least.rs │ │ ├── count_is_at_most.rs │ │ ├── first_and_last.rs │ │ ├── is_constant.rs │ │ ├── is_unique.rs │ │ ├── iter_windows.rs │ │ ├── iterator_cache.rs │ │ ├── matching_intervals_in_iterator.rs │ │ ├── nonzero_values.rs │ │ ├── prefix_to_string.rs │ │ ├── thue_morse_sequence.rs │ │ ├── with_special_value.rs │ │ └── with_special_values.rs │ ├── lib.rs │ ├── named/ │ │ └── mod.rs │ ├── nevers/ │ │ └── nevers.rs │ ├── num/ │ │ ├── arithmetic/ │ │ │ ├── abs.rs │ │ │ ├── abs_diff.rs │ │ │ ├── add_mul.rs │ │ │ ├── arithmetic_checked_shl.rs │ │ │ ├── arithmetic_checked_shr.rs │ │ │ ├── binomial_coefficient.rs │ │ │ ├── ceiling.rs │ │ │ ├── checked_abs.rs │ │ │ ├── checked_add_mul.rs │ │ │ ├── checked_neg.rs │ │ │ ├── checked_pow.rs │ │ │ ├── checked_square.rs │ │ │ ├── checked_sub_mul.rs │ │ │ ├── coprime_with.rs │ │ │ ├── div_exact.rs │ │ │ ├── div_mod.rs │ │ │ ├── div_round.rs │ │ │ ├── divisible_by.rs │ │ │ ├── divisible_by_power_of_2.rs │ │ │ ├── eq_mod.rs │ │ │ ├── eq_mod_power_of_2.rs │ │ │ ├── extended_gcd.rs │ │ │ ├── factorial.rs │ │ │ ├── floor.rs │ │ │ ├── gcd.rs │ │ │ ├── is_power_of_2.rs │ │ │ ├── kronecker_symbol.rs │ │ │ ├── lcm.rs │ │ │ ├── log_base.rs │ │ │ ├── log_base_2.rs │ │ │ ├── log_base_power_of_2.rs │ │ │ ├── mod_add.rs │ │ │ ├── mod_inverse.rs │ │ │ ├── mod_is_reduced.rs │ │ │ ├── mod_mul.rs │ │ │ ├── mod_neg.rs │ │ │ ├── mod_op.rs │ │ │ ├── mod_pow.rs │ │ │ ├── mod_power_of_2.rs │ │ │ ├── mod_power_of_2_add.rs │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ ├── mod_power_of_2_is_reduced.rs │ │ │ ├── mod_power_of_2_mul.rs │ │ │ ├── mod_power_of_2_neg.rs │ │ │ ├── mod_power_of_2_pow.rs │ │ │ ├── mod_power_of_2_shl.rs │ │ │ ├── mod_power_of_2_shr.rs │ │ │ ├── mod_power_of_2_square.rs │ │ │ ├── mod_power_of_2_sub.rs │ │ │ ├── mod_shl.rs │ │ │ ├── mod_shr.rs │ │ │ ├── mod_square.rs │ │ │ ├── mod_sub.rs │ │ │ ├── neg.rs │ │ │ ├── next_power_of_2.rs │ │ │ ├── overflowing_abs.rs │ │ │ ├── overflowing_add.rs │ │ │ ├── overflowing_add_mul.rs │ │ │ ├── overflowing_div.rs │ │ │ ├── overflowing_mul.rs │ │ │ ├── overflowing_neg.rs │ │ │ ├── overflowing_pow.rs │ │ │ ├── overflowing_square.rs │ │ │ ├── overflowing_sub.rs │ │ │ ├── overflowing_sub_mul.rs │ │ │ ├── parity.rs │ │ │ ├── pow.rs │ │ │ ├── power_of_2.rs │ │ │ ├── primorial.rs │ │ │ ├── reciprocal.rs │ │ │ ├── root.rs │ │ │ ├── rotate.rs │ │ │ ├── round_to_multiple.rs │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ ├── saturating_abs.rs │ │ │ ├── saturating_add.rs │ │ │ ├── saturating_add_mul.rs │ │ │ ├── saturating_mul.rs │ │ │ ├── saturating_neg.rs │ │ │ ├── saturating_pow.rs │ │ │ ├── saturating_square.rs │ │ │ ├── saturating_sub.rs │ │ │ ├── saturating_sub_mul.rs │ │ │ ├── shl_round.rs │ │ │ ├── shr_round.rs │ │ │ ├── sign.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ ├── sub_mul.rs │ │ │ ├── wrapping_abs.rs │ │ │ ├── wrapping_add.rs │ │ │ ├── wrapping_add_mul.rs │ │ │ ├── wrapping_div.rs │ │ │ ├── wrapping_mul.rs │ │ │ ├── wrapping_neg.rs │ │ │ ├── wrapping_pow.rs │ │ │ ├── wrapping_square.rs │ │ │ ├── wrapping_sub.rs │ │ │ ├── wrapping_sub_mul.rs │ │ │ ├── x_mul_y_to_zz.rs │ │ │ ├── xx_add_yy_to_zz.rs │ │ │ ├── xx_div_mod_y_to_qr.rs │ │ │ ├── xx_sub_yy_to_zz.rs │ │ │ ├── xxx_add_yyy_to_zzz.rs │ │ │ ├── xxx_sub_yyy_to_zzz.rs │ │ │ └── xxxx_add_yyyy_to_zzzz.rs │ │ ├── basic/ │ │ │ └── constants.rs │ │ ├── comparison/ │ │ │ ├── cmp_abs.rs │ │ │ └── eq_abs.rs │ │ ├── conversion/ │ │ │ ├── digits/ │ │ │ │ ├── general_digits/ │ │ │ │ │ ├── from_digits.rs │ │ │ │ │ └── to_digits.rs │ │ │ │ └── power_of_2_digits/ │ │ │ │ ├── from_power_of_2_digits.rs │ │ │ │ ├── power_of_2_digit_iterable.rs │ │ │ │ └── to_power_of_2_digits.rs │ │ │ ├── froms/ │ │ │ │ ├── convertible_from.rs │ │ │ │ ├── from.rs │ │ │ │ ├── overflowing_from.rs │ │ │ │ ├── rounding_from.rs │ │ │ │ ├── saturating_from.rs │ │ │ │ ├── try_from_and_exact_from.rs │ │ │ │ └── wrapping_from.rs │ │ │ ├── half/ │ │ │ │ ├── join_halves.rs │ │ │ │ ├── lower_half.rs │ │ │ │ ├── split_in_half.rs │ │ │ │ └── upper_half.rs │ │ │ ├── is_integer.rs │ │ │ ├── mantissa_and_exponent/ │ │ │ │ ├── integer_mantissa_and_exponent.rs │ │ │ │ ├── raw_mantissa_and_exponent.rs │ │ │ │ └── sci_mantissa_and_exponent.rs │ │ │ ├── slice/ │ │ │ │ ├── from_other_type_slice.rs │ │ │ │ ├── vec_from_other_type.rs │ │ │ │ └── vec_from_other_type_slice.rs │ │ │ └── string/ │ │ │ ├── from_sci_string.rs │ │ │ ├── from_string.rs │ │ │ ├── options/ │ │ │ │ ├── from_sci_string_options.rs │ │ │ │ └── to_sci_options.rs │ │ │ ├── to_sci.rs │ │ │ └── to_string.rs │ │ ├── exhaustive/ │ │ │ ├── exhaustive_finite_primitive_floats.rs │ │ │ ├── exhaustive_natural_signeds.rs │ │ │ ├── exhaustive_negative_finite_primitive_floats.rs │ │ │ ├── exhaustive_negative_primitive_floats.rs │ │ │ ├── exhaustive_negative_signeds.rs │ │ │ ├── exhaustive_nonzero_finite_primitive_floats.rs │ │ │ ├── exhaustive_nonzero_finite_primitive_floats_in_range.rs │ │ │ ├── exhaustive_nonzero_primitive_floats.rs │ │ │ ├── exhaustive_nonzero_signeds.rs │ │ │ ├── exhaustive_positive_finite_primitive_floats.rs │ │ │ ├── exhaustive_positive_finite_primitive_floats_in_range.rs │ │ │ ├── exhaustive_positive_primitive_floats.rs │ │ │ ├── exhaustive_positive_primitive_ints.rs │ │ │ ├── exhaustive_primitive_float_inclusive_range.rs │ │ │ ├── exhaustive_primitive_float_range.rs │ │ │ ├── exhaustive_primitive_floats.rs │ │ │ ├── exhaustive_primitive_floats_with_sci_exponent.rs │ │ │ ├── exhaustive_primitive_floats_with_sci_exponent_and_precision.rs │ │ │ ├── exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range.rs │ │ │ ├── exhaustive_primitive_floats_with_sci_exponent_in_range.rs │ │ │ ├── exhaustive_signed_inclusive_range.rs │ │ │ ├── exhaustive_signed_range.rs │ │ │ ├── exhaustive_signeds.rs │ │ │ ├── exhaustive_unsigneds.rs │ │ │ ├── finite_primitive_floats_increasing.rs │ │ │ ├── negative_finite_primitive_floats_increasing.rs │ │ │ ├── negative_primitive_floats_increasing.rs │ │ │ ├── nonzero_finite_primitive_floats_increasing.rs │ │ │ ├── nonzero_primitive_floats_increasing.rs │ │ │ ├── positive_finite_primitive_floats_increasing.rs │ │ │ ├── positive_primitive_floats_increasing.rs │ │ │ ├── primitive_float_increasing_inclusive_range.rs │ │ │ ├── primitive_float_increasing_range.rs │ │ │ ├── primitive_floats_increasing.rs │ │ │ ├── primitive_int_increasing_inclusive_range.rs │ │ │ └── primitive_int_increasing_range.rs │ │ ├── factorization/ │ │ │ ├── factor.rs │ │ │ ├── is_power.rs │ │ │ ├── is_prime.rs │ │ │ ├── is_square.rs │ │ │ ├── prime_indicator_sequence.rs │ │ │ ├── prime_indicator_sequence_less_than.rs │ │ │ ├── prime_sieve.rs │ │ │ ├── primes.rs │ │ │ └── primitive_root_prime.rs │ │ ├── float/ │ │ │ ├── basic/ │ │ │ │ ├── abs_negative_zero.rs │ │ │ │ ├── from_ordered_representation.rs │ │ │ │ ├── is_negative_zero.rs │ │ │ │ ├── max_precision_for_sci_exponent.rs │ │ │ │ ├── next_higher.rs │ │ │ │ ├── next_lower.rs │ │ │ │ ├── precision.rs │ │ │ │ └── to_ordered_representation.rs │ │ │ └── nice_float/ │ │ │ ├── cmp.rs │ │ │ ├── cmp_abs.rs │ │ │ ├── eq.rs │ │ │ ├── eq_abs.rs │ │ │ ├── from_str.rs │ │ │ ├── hash.rs │ │ │ └── to_string.rs │ │ ├── iterators/ │ │ │ ├── bit_distributor_sequence.rs │ │ │ ├── iterator_to_bit_chunks.rs │ │ │ └── ruler_sequence.rs │ │ ├── logic/ │ │ │ ├── bit_access/ │ │ │ │ ├── assign_bit.rs │ │ │ │ ├── clear_bit.rs │ │ │ │ ├── flip_bit.rs │ │ │ │ ├── get_bit.rs │ │ │ │ └── set_bit.rs │ │ │ ├── bit_block_access/ │ │ │ │ ├── assign_bits.rs │ │ │ │ └── get_bits.rs │ │ │ ├── bit_convertible/ │ │ │ │ ├── from_bits.rs │ │ │ │ └── to_bits.rs │ │ │ ├── bit_iterable.rs │ │ │ ├── bit_scan/ │ │ │ │ ├── index_of_next_false_bit.rs │ │ │ │ └── index_of_next_true_bit.rs │ │ │ ├── get_highest_bit.rs │ │ │ ├── hamming_distance.rs │ │ │ ├── low_mask.rs │ │ │ ├── not_assign.rs │ │ │ └── significant_bits.rs │ │ └── random/ │ │ ├── geometric/ │ │ │ ├── geometric_random_natural_signeds.rs │ │ │ ├── geometric_random_negative_signeds.rs │ │ │ ├── geometric_random_nonzero_signeds.rs │ │ │ ├── geometric_random_positive_signeds.rs │ │ │ ├── geometric_random_positive_unsigneds.rs │ │ │ ├── geometric_random_signed_inclusive_range.rs │ │ │ ├── geometric_random_signed_range.rs │ │ │ ├── geometric_random_signeds.rs │ │ │ ├── geometric_random_unsigned_inclusive_range.rs │ │ │ ├── geometric_random_unsigned_range.rs │ │ │ ├── geometric_random_unsigneds.rs │ │ │ ├── get_geometric_random_signed_from_inclusive_range.rs │ │ │ └── mean.rs │ │ ├── random_finite_primitive_floats.rs │ │ ├── random_highest_bit_set_unsigneds.rs │ │ ├── random_natural_signeds.rs │ │ ├── random_negative_finite_primitive_floats.rs │ │ ├── random_negative_primitive_floats.rs │ │ ├── random_negative_signeds.rs │ │ ├── random_nonzero_finite_primitive_floats.rs │ │ ├── random_nonzero_primitive_floats.rs │ │ ├── random_nonzero_signeds.rs │ │ ├── random_positive_finite_primitive_floats.rs │ │ ├── random_positive_primitive_floats.rs │ │ ├── random_positive_signeds.rs │ │ ├── random_positive_unsigneds.rs │ │ ├── random_primitive_float_inclusive_range.rs │ │ ├── random_primitive_float_range.rs │ │ ├── random_primitive_floats.rs │ │ ├── random_primitive_ints.rs │ │ ├── random_signed_bit_chunks.rs │ │ ├── random_signed_inclusive_range.rs │ │ ├── random_signed_range.rs │ │ ├── random_unsigned_bit_chunks.rs │ │ ├── random_unsigned_inclusive_range.rs │ │ ├── random_unsigned_range.rs │ │ ├── random_unsigneds_less_than.rs │ │ ├── special_random_finite_primitive_floats.rs │ │ ├── special_random_negative_finite_primitive_floats.rs │ │ ├── special_random_negative_primitive_floats.rs │ │ ├── special_random_nonzero_finite_primitive_floats.rs │ │ ├── special_random_nonzero_primitive_floats.rs │ │ ├── special_random_positive_finite_primitive_floats.rs │ │ ├── special_random_positive_primitive_floats.rs │ │ ├── special_random_primitive_float_inclusive_range.rs │ │ ├── special_random_primitive_float_range.rs │ │ ├── special_random_primitive_floats.rs │ │ ├── striped/ │ │ │ ├── get_striped_bool_vec.rs │ │ │ ├── get_striped_unsigned_vec.rs │ │ │ ├── striped_bit_source.rs │ │ │ ├── striped_random_bool_vecs.rs │ │ │ ├── striped_random_bool_vecs_from_length_iterator.rs │ │ │ ├── striped_random_bool_vecs_length_inclusive_range.rs │ │ │ ├── striped_random_bool_vecs_length_range.rs │ │ │ ├── striped_random_bool_vecs_min_length.rs │ │ │ ├── striped_random_fixed_length_bool_vecs.rs │ │ │ ├── striped_random_fixed_length_unsigned_vecs.rs │ │ │ ├── striped_random_natural_signeds.rs │ │ │ ├── striped_random_negative_signeds.rs │ │ │ ├── striped_random_nonzero_signeds.rs │ │ │ ├── striped_random_positive_signeds.rs │ │ │ ├── striped_random_positive_unsigneds.rs │ │ │ ├── striped_random_signed_inclusive_range.rs │ │ │ ├── striped_random_signed_range.rs │ │ │ ├── striped_random_signeds.rs │ │ │ ├── striped_random_unsigned_bit_chunks.rs │ │ │ ├── striped_random_unsigned_inclusive_range.rs │ │ │ ├── striped_random_unsigned_range.rs │ │ │ ├── striped_random_unsigned_vecs.rs │ │ │ ├── striped_random_unsigned_vecs_from_length_iterator.rs │ │ │ ├── striped_random_unsigned_vecs_length_inclusive_range.rs │ │ │ ├── striped_random_unsigned_vecs_length_range.rs │ │ │ ├── striped_random_unsigned_vecs_min_length.rs │ │ │ └── striped_random_unsigneds.rs │ │ └── variable_range_generator/ │ │ ├── next_bit_chunk.rs │ │ ├── next_bool.rs │ │ ├── next_in_inclusive_range.rs │ │ ├── next_in_range.rs │ │ └── next_less_than.rs │ ├── options/ │ │ ├── exhaustive/ │ │ │ ├── exhaustive_options.rs │ │ │ └── exhaustive_somes.rs │ │ ├── option_from_str.rs │ │ └── random/ │ │ ├── random_options.rs │ │ └── random_somes.rs │ ├── orderings/ │ │ ├── exhaustive.rs │ │ ├── ordering_from_str.rs │ │ └── random.rs │ ├── random/ │ │ ├── fork.rs │ │ ├── from_bytes.rs │ │ ├── get_rng.rs │ │ └── next.rs │ ├── rational_sequences/ │ │ ├── access/ │ │ │ ├── get.rs │ │ │ └── mutate.rs │ │ ├── basic/ │ │ │ ├── component_len.rs │ │ │ ├── is_empty.rs │ │ │ ├── is_finite.rs │ │ │ ├── iter.rs │ │ │ └── len.rs │ │ ├── comparison/ │ │ │ ├── cmp.rs │ │ │ ├── eq.rs │ │ │ └── hash.rs │ │ ├── conversion/ │ │ │ ├── clone.rs │ │ │ ├── from_vec.rs │ │ │ ├── from_vecs.rs │ │ │ └── to_vecs.rs │ │ ├── exhaustive.rs │ │ ├── random.rs │ │ └── to_string.rs │ ├── rounding_modes/ │ │ ├── clone.rs │ │ ├── cmp.rs │ │ ├── eq.rs │ │ ├── exhaustive.rs │ │ ├── from_str.rs │ │ ├── hash.rs │ │ ├── neg.rs │ │ ├── random.rs │ │ ├── size.rs │ │ └── to_string.rs │ ├── sets/ │ │ ├── exhaustive/ │ │ │ ├── exhaustive_b_tree_sets.rs │ │ │ ├── exhaustive_b_tree_sets_fixed_length.rs │ │ │ ├── exhaustive_b_tree_sets_length_inclusive_range.rs │ │ │ ├── exhaustive_b_tree_sets_length_range.rs │ │ │ ├── exhaustive_b_tree_sets_min_length.rs │ │ │ ├── exhaustive_hash_sets.rs │ │ │ ├── exhaustive_hash_sets_fixed_length.rs │ │ │ ├── exhaustive_hash_sets_length_inclusive_range.rs │ │ │ ├── exhaustive_hash_sets_length_range.rs │ │ │ ├── exhaustive_hash_sets_min_length.rs │ │ │ ├── lex_b_tree_sets.rs │ │ │ ├── lex_b_tree_sets_fixed_length.rs │ │ │ ├── lex_b_tree_sets_length_inclusive_range.rs │ │ │ ├── lex_b_tree_sets_length_range.rs │ │ │ ├── lex_b_tree_sets_min_length.rs │ │ │ ├── lex_hash_sets.rs │ │ │ ├── lex_hash_sets_fixed_length.rs │ │ │ ├── lex_hash_sets_length_inclusive_range.rs │ │ │ ├── lex_hash_sets_length_range.rs │ │ │ ├── lex_hash_sets_min_length.rs │ │ │ ├── shortlex_b_tree_sets.rs │ │ │ ├── shortlex_b_tree_sets_length_inclusive_range.rs │ │ │ ├── shortlex_b_tree_sets_length_range.rs │ │ │ ├── shortlex_b_tree_sets_min_length.rs │ │ │ ├── shortlex_hash_sets.rs │ │ │ ├── shortlex_hash_sets_length_inclusive_range.rs │ │ │ ├── shortlex_hash_sets_length_range.rs │ │ │ └── shortlex_hash_sets_min_length.rs │ │ └── random/ │ │ ├── random_b_tree_sets.rs │ │ ├── random_b_tree_sets_fixed_length.rs │ │ ├── random_b_tree_sets_from_length_iterator.rs │ │ ├── random_b_tree_sets_length_inclusive_range.rs │ │ ├── random_b_tree_sets_length_range.rs │ │ ├── random_b_tree_sets_min_length.rs │ │ ├── random_hash_sets.rs │ │ ├── random_hash_sets_fixed_length.rs │ │ ├── random_hash_sets_from_length_iterator.rs │ │ ├── random_hash_sets_length_inclusive_range.rs │ │ ├── random_hash_sets_length_range.rs │ │ └── random_hash_sets_min_length.rs │ ├── slices/ │ │ ├── exhaustive_slice_permutations.rs │ │ ├── min_repeating_len.rs │ │ ├── random_slice_permutations.rs │ │ ├── random_values_from_slice.rs │ │ ├── slice_leading_zeros.rs │ │ ├── slice_move_left.rs │ │ ├── slice_set_zero.rs │ │ ├── slice_test_zero.rs │ │ ├── slice_trailing_zeros.rs │ │ └── split_into_chunks.rs │ ├── strings/ │ │ ├── exhaustive/ │ │ │ ├── exhaustive_fixed_length_strings.rs │ │ │ ├── exhaustive_fixed_length_strings_using_chars.rs │ │ │ ├── exhaustive_strings.rs │ │ │ ├── exhaustive_strings_using_chars.rs │ │ │ ├── lex_fixed_length_strings.rs │ │ │ ├── lex_fixed_length_strings_using_chars.rs │ │ │ ├── shortlex_strings.rs │ │ │ └── shortlex_strings_using_chars.rs │ │ ├── random/ │ │ │ ├── random_fixed_length_strings.rs │ │ │ ├── random_fixed_length_strings_using_chars.rs │ │ │ ├── random_strings.rs │ │ │ └── random_strings_using_chars.rs │ │ ├── string_is_subset.rs │ │ ├── string_sort.rs │ │ ├── string_unique.rs │ │ ├── strings_from_char_vecs.rs │ │ ├── to_binary_string.rs │ │ ├── to_debug_string.rs │ │ ├── to_lower_hex_string.rs │ │ ├── to_octal_string.rs │ │ └── to_upper_hex_string.rs │ ├── tuples/ │ │ ├── exhaustive/ │ │ │ ├── exhaustive_custom_tuples.rs │ │ │ ├── exhaustive_dependent_pairs.rs │ │ │ ├── exhaustive_ordered_unique_tuples.rs │ │ │ ├── exhaustive_tuples_1_input.rs │ │ │ ├── exhaustive_tuples_custom_output.rs │ │ │ ├── exhaustive_tuples_from_single.rs │ │ │ ├── exhaustive_unique_tuples.rs │ │ │ ├── exhaustive_units.rs │ │ │ ├── lex_custom_tuples.rs │ │ │ ├── lex_dependent_pairs.rs │ │ │ ├── lex_ordered_unique_tuples.rs │ │ │ ├── lex_tuples.rs │ │ │ ├── lex_tuples_from_single.rs │ │ │ └── lex_unique_tuples.rs │ │ ├── random/ │ │ │ ├── random_custom_tuples.rs │ │ │ ├── random_ordered_unique_tuples.rs │ │ │ ├── random_tuples.rs │ │ │ ├── random_tuples_from_single.rs │ │ │ ├── random_unique_tuples.rs │ │ │ └── random_units.rs │ │ └── singletons.rs │ ├── unions/ │ │ ├── clone.rs │ │ ├── debug.rs │ │ ├── display.rs │ │ ├── eq.rs │ │ ├── exhaustive/ │ │ │ ├── exhaustive_unions.rs │ │ │ └── lex_unions.rs │ │ ├── from_str.rs │ │ ├── ord.rs │ │ ├── random/ │ │ │ └── random_unions.rs │ │ └── unwrap.rs │ └── vecs/ │ ├── exhaustive/ │ │ ├── exhaustive_combined_k_compositions.rs │ │ ├── exhaustive_ordered_unique_vecs.rs │ │ ├── exhaustive_ordered_unique_vecs_fixed_length.rs │ │ ├── exhaustive_ordered_unique_vecs_length_inclusive_range.rs │ │ ├── exhaustive_ordered_unique_vecs_length_range.rs │ │ ├── exhaustive_ordered_unique_vecs_min_length.rs │ │ ├── exhaustive_unique_vecs.rs │ │ ├── exhaustive_unique_vecs_fixed_length.rs │ │ ├── exhaustive_unique_vecs_length_inclusive_range.rs │ │ ├── exhaustive_unique_vecs_length_range.rs │ │ ├── exhaustive_unique_vecs_min_length.rs │ │ ├── exhaustive_vecs.rs │ │ ├── exhaustive_vecs_fixed_length_from_single.rs │ │ ├── exhaustive_vecs_fixed_length_m_inputs.rs │ │ ├── exhaustive_vecs_from_length_iterator.rs │ │ ├── exhaustive_vecs_length_inclusive_range.rs │ │ ├── exhaustive_vecs_length_n.rs │ │ ├── exhaustive_vecs_length_range.rs │ │ ├── exhaustive_vecs_min_length.rs │ │ ├── lex_k_compositions.rs │ │ ├── lex_ordered_unique_vecs.rs │ │ ├── lex_ordered_unique_vecs_fixed_length.rs │ │ ├── lex_ordered_unique_vecs_length_inclusive_range.rs │ │ ├── lex_ordered_unique_vecs_length_range.rs │ │ ├── lex_ordered_unique_vecs_min_length.rs │ │ ├── lex_unique_vecs.rs │ │ ├── lex_unique_vecs_fixed_length.rs │ │ ├── lex_unique_vecs_length_inclusive_range.rs │ │ ├── lex_unique_vecs_length_range.rs │ │ ├── lex_unique_vecs_min_length.rs │ │ ├── lex_vecs_fixed_length_from_single.rs │ │ ├── lex_vecs_fixed_length_m_inputs.rs │ │ ├── lex_vecs_length_n.rs │ │ ├── next_bit_pattern.rs │ │ ├── shortlex_ordered_unique_vecs.rs │ │ ├── shortlex_ordered_unique_vecs_length_inclusive_range.rs │ │ ├── shortlex_ordered_unique_vecs_length_range.rs │ │ ├── shortlex_ordered_unique_vecs_min_length.rs │ │ ├── shortlex_unique_vecs.rs │ │ ├── shortlex_unique_vecs_length_inclusive_range.rs │ │ ├── shortlex_unique_vecs_length_range.rs │ │ ├── shortlex_unique_vecs_min_length.rs │ │ ├── shortlex_vecs.rs │ │ ├── shortlex_vecs_from_length_iterator.rs │ │ ├── shortlex_vecs_length_inclusive_range.rs │ │ ├── shortlex_vecs_length_range.rs │ │ └── shortlex_vecs_min_length.rs │ ├── exhaustive_vec_permutations.rs │ ├── random/ │ │ ├── random_ordered_unique_vecs.rs │ │ ├── random_ordered_unique_vecs_fixed_length.rs │ │ ├── random_ordered_unique_vecs_from_length_iterator.rs │ │ ├── random_ordered_unique_vecs_length_inclusive_range.rs │ │ ├── random_ordered_unique_vecs_length_range.rs │ │ ├── random_ordered_unique_vecs_min_length.rs │ │ ├── random_unique_vecs.rs │ │ ├── random_unique_vecs_fixed_length.rs │ │ ├── random_unique_vecs_from_length_iterator.rs │ │ ├── random_unique_vecs_length_inclusive_range.rs │ │ ├── random_unique_vecs_length_range.rs │ │ ├── random_unique_vecs_min_length.rs │ │ ├── random_vecs.rs │ │ ├── random_vecs_fixed_length.rs │ │ ├── random_vecs_fixed_length_from_single.rs │ │ ├── random_vecs_fixed_length_m_inputs.rs │ │ ├── random_vecs_from_length_iterator.rs │ │ ├── random_vecs_length_inclusive_range.rs │ │ ├── random_vecs_length_range.rs │ │ └── random_vecs_min_length.rs │ ├── random_values_from_vec.rs │ ├── random_vec_permutations.rs │ ├── vec_delete_left.rs │ ├── vec_from_str.rs │ └── vec_pad_left.rs ├── malachite-bigint/ │ ├── Cargo.toml │ ├── README.md │ └── src/ │ ├── bigint.rs │ ├── biguint.rs │ ├── error.rs │ ├── iter.rs │ ├── lib.rs │ ├── macros.rs │ └── num_bigint_conversion.rs ├── malachite-criterion-bench/ │ ├── Cargo.toml │ └── benches/ │ ├── bin.rs │ ├── natural_div.rs │ └── natural_mul.rs ├── malachite-float/ │ ├── Cargo.toml │ ├── README.md │ ├── katex-header.html │ ├── rustfmt.toml │ ├── src/ │ │ ├── arithmetic/ │ │ │ ├── abs.rs │ │ │ ├── add.rs │ │ │ ├── agm.rs │ │ │ ├── div.rs │ │ │ ├── is_power_of_2.rs │ │ │ ├── ln.rs │ │ │ ├── mod.rs │ │ │ ├── mul.rs │ │ │ ├── neg.rs │ │ │ ├── power_of_2.rs │ │ │ ├── reciprocal.rs │ │ │ ├── reciprocal_sqrt.rs │ │ │ ├── shl.rs │ │ │ ├── shl_round.rs │ │ │ ├── shr.rs │ │ │ ├── shr_round.rs │ │ │ ├── sign.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ └── sub.rs │ │ ├── basic/ │ │ │ ├── classification.rs │ │ │ ├── complexity.rs │ │ │ ├── constants.rs │ │ │ ├── extended.rs │ │ │ ├── get_and_set.rs │ │ │ ├── mod.rs │ │ │ └── ulp.rs │ │ ├── bin.rs │ │ ├── bin_util/ │ │ │ └── demo_and_bench/ │ │ │ ├── arithmetic/ │ │ │ │ ├── abs.rs │ │ │ │ ├── add.rs │ │ │ │ ├── agm.rs │ │ │ │ ├── div.rs │ │ │ │ ├── is_power_of_2.rs │ │ │ │ ├── ln.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mul.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── power_of_2.rs │ │ │ │ ├── reciprocal.rs │ │ │ │ ├── reciprocal_sqrt.rs │ │ │ │ ├── shl.rs │ │ │ │ ├── shl_round.rs │ │ │ │ ├── shr.rs │ │ │ │ ├── shr_round.rs │ │ │ │ ├── sign.rs │ │ │ │ ├── sqrt.rs │ │ │ │ ├── square.rs │ │ │ │ └── sub.rs │ │ │ ├── basic/ │ │ │ │ ├── classification.rs │ │ │ │ ├── complexity.rs │ │ │ │ ├── constants.rs │ │ │ │ ├── get_and_set.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── overflow_and_underflow.rs │ │ │ │ └── ulp.rs │ │ │ ├── comparison/ │ │ │ │ ├── cmp.rs │ │ │ │ ├── cmp_abs.rs │ │ │ │ ├── eq.rs │ │ │ │ ├── eq_abs.rs │ │ │ │ ├── eq_abs_integer.rs │ │ │ │ ├── eq_abs_natural.rs │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ ├── eq_abs_rational.rs │ │ │ │ ├── hash.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── partial_cmp_abs_integer.rs │ │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ │ ├── partial_cmp_abs_rational.rs │ │ │ │ ├── partial_cmp_integer.rs │ │ │ │ ├── partial_cmp_natural.rs │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ ├── partial_cmp_rational.rs │ │ │ │ ├── partial_eq_integer.rs │ │ │ │ ├── partial_eq_natural.rs │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ ├── partial_eq_primitive_int.rs │ │ │ │ └── partial_eq_rational.rs │ │ │ ├── constants/ │ │ │ │ ├── gauss_constant.rs │ │ │ │ ├── lemniscate_constant.rs │ │ │ │ ├── ln_2.rs │ │ │ │ ├── log_2_e.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── one_over_pi.rs │ │ │ │ ├── one_over_sqrt_pi.rs │ │ │ │ ├── one_over_sqrt_tau.rs │ │ │ │ ├── phi.rs │ │ │ │ ├── pi.rs │ │ │ │ ├── pi_over_2.rs │ │ │ │ ├── pi_over_3.rs │ │ │ │ ├── pi_over_4.rs │ │ │ │ ├── pi_over_6.rs │ │ │ │ ├── pi_over_8.rs │ │ │ │ ├── prime_constant.rs │ │ │ │ ├── prouhet_thue_morse_constant.rs │ │ │ │ ├── sqrt_2.rs │ │ │ │ ├── sqrt_2_over_2.rs │ │ │ │ ├── sqrt_3.rs │ │ │ │ ├── sqrt_3_over_3.rs │ │ │ │ ├── sqrt_pi.rs │ │ │ │ ├── tau.rs │ │ │ │ ├── two_over_pi.rs │ │ │ │ └── two_over_sqrt_pi.rs │ │ │ ├── conversion/ │ │ │ │ ├── clone.rs │ │ │ │ ├── from_integer.rs │ │ │ │ ├── from_natural.rs │ │ │ │ ├── from_primitive_float.rs │ │ │ │ ├── from_primitive_int.rs │ │ │ │ ├── from_rational.rs │ │ │ │ ├── integer_from_float.rs │ │ │ │ ├── integer_mantissa_and_exponent.rs │ │ │ │ ├── is_integer.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── natural_from_float.rs │ │ │ │ ├── primitive_float_from_float.rs │ │ │ │ ├── primitive_int_from_float.rs │ │ │ │ ├── rational_from_float.rs │ │ │ │ ├── raw_mantissa_and_exponent.rs │ │ │ │ ├── sci_mantissa_and_exponent.rs │ │ │ │ └── string/ │ │ │ │ ├── mod.rs │ │ │ │ └── to_string.rs │ │ │ └── mod.rs │ │ ├── comparison/ │ │ │ ├── cmp.rs │ │ │ ├── cmp_abs.rs │ │ │ ├── eq.rs │ │ │ ├── eq_abs.rs │ │ │ ├── eq_abs_integer.rs │ │ │ ├── eq_abs_natural.rs │ │ │ ├── eq_abs_primitive_float.rs │ │ │ ├── eq_abs_primitive_int.rs │ │ │ ├── eq_abs_rational.rs │ │ │ ├── hash.rs │ │ │ ├── mod.rs │ │ │ ├── partial_cmp_abs_integer.rs │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ ├── partial_cmp_abs_rational.rs │ │ │ ├── partial_cmp_integer.rs │ │ │ ├── partial_cmp_natural.rs │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ ├── partial_cmp_rational.rs │ │ │ ├── partial_eq_integer.rs │ │ │ ├── partial_eq_natural.rs │ │ │ ├── partial_eq_primitive_float.rs │ │ │ ├── partial_eq_primitive_int.rs │ │ │ └── partial_eq_rational.rs │ │ ├── constants/ │ │ │ ├── gauss_constant.rs │ │ │ ├── lemniscate_constant.rs │ │ │ ├── ln_2.rs │ │ │ ├── log_2_e.rs │ │ │ ├── mod.rs │ │ │ ├── one_over_pi.rs │ │ │ ├── one_over_sqrt_pi.rs │ │ │ ├── one_over_sqrt_tau.rs │ │ │ ├── phi.rs │ │ │ ├── pi.rs │ │ │ ├── pi_over_2.rs │ │ │ ├── pi_over_3.rs │ │ │ ├── pi_over_4.rs │ │ │ ├── pi_over_6.rs │ │ │ ├── pi_over_8.rs │ │ │ ├── prime_constant.rs │ │ │ ├── prouhet_thue_morse_constant.rs │ │ │ ├── sqrt_2.rs │ │ │ ├── sqrt_2_over_2.rs │ │ │ ├── sqrt_3.rs │ │ │ ├── sqrt_3_over_3.rs │ │ │ ├── sqrt_pi.rs │ │ │ ├── tau.rs │ │ │ ├── two_over_pi.rs │ │ │ └── two_over_sqrt_pi.rs │ │ ├── conversion/ │ │ │ ├── from_bits.rs │ │ │ ├── from_integer.rs │ │ │ ├── from_natural.rs │ │ │ ├── from_primitive_float.rs │ │ │ ├── from_primitive_int.rs │ │ │ ├── from_rational.rs │ │ │ ├── integer_from_float.rs │ │ │ ├── is_integer.rs │ │ │ ├── mantissa_and_exponent.rs │ │ │ ├── mod.rs │ │ │ ├── natural_from_float.rs │ │ │ ├── primitive_float_from_float.rs │ │ │ ├── primitive_int_from_float.rs │ │ │ ├── rational_from_float.rs │ │ │ └── string/ │ │ │ ├── from_string.rs │ │ │ ├── mod.rs │ │ │ └── to_string.rs │ │ ├── exhaustive/ │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── random/ │ │ │ └── mod.rs │ │ └── test_util/ │ │ ├── arithmetic/ │ │ │ ├── add.rs │ │ │ ├── agm.rs │ │ │ ├── div.rs │ │ │ ├── ln.rs │ │ │ ├── mod.rs │ │ │ ├── mul.rs │ │ │ ├── power_of_2.rs │ │ │ ├── reciprocal.rs │ │ │ ├── reciprocal_sqrt.rs │ │ │ ├── shl.rs │ │ │ ├── shl_round.rs │ │ │ ├── shr.rs │ │ │ ├── shr_round.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ └── sub.rs │ │ ├── bench/ │ │ │ ├── bucketers.rs │ │ │ └── mod.rs │ │ ├── common/ │ │ │ └── mod.rs │ │ ├── comparison/ │ │ │ ├── mod.rs │ │ │ └── partial_cmp_rational.rs │ │ ├── constants/ │ │ │ ├── lemniscate_constant.rs │ │ │ ├── ln_2.rs │ │ │ ├── log_2_e.rs │ │ │ ├── mod.rs │ │ │ ├── one_over_pi.rs │ │ │ ├── one_over_sqrt_pi.rs │ │ │ ├── one_over_sqrt_tau.rs │ │ │ ├── pi.rs │ │ │ ├── pi_over_3.rs │ │ │ ├── prime_constant.rs │ │ │ ├── prouhet_thue_morse_constant.rs │ │ │ ├── sqrt_2.rs │ │ │ ├── sqrt_2_over_2.rs │ │ │ ├── sqrt_3.rs │ │ │ ├── sqrt_3_over_3.rs │ │ │ └── sqrt_pi.rs │ │ ├── conversion/ │ │ │ ├── from_primitive_float.rs │ │ │ └── mod.rs │ │ ├── exhaustive/ │ │ │ └── mod.rs │ │ ├── extra_variadic/ │ │ │ └── mod.rs │ │ ├── generators/ │ │ │ ├── common.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ ├── random.rs │ │ │ └── special_random.rs │ │ ├── mod.rs │ │ └── random/ │ │ └── mod.rs │ └── tests/ │ ├── arithmetic/ │ │ ├── abs.rs │ │ ├── add.rs │ │ ├── agm.rs │ │ ├── div.rs │ │ ├── is_power_of_2.rs │ │ ├── ln.rs │ │ ├── mul.rs │ │ ├── neg.rs │ │ ├── power_of_2.rs │ │ ├── reciprocal.rs │ │ ├── reciprocal_sqrt.rs │ │ ├── shl.rs │ │ ├── shl_round.rs │ │ ├── shr.rs │ │ ├── shr_round.rs │ │ ├── sign.rs │ │ ├── sqrt.rs │ │ ├── square.rs │ │ └── sub.rs │ ├── basic/ │ │ ├── classification.rs │ │ ├── complexity.rs │ │ ├── constants.rs │ │ ├── get_and_set.rs │ │ ├── named.rs │ │ ├── overflow_and_underflow.rs │ │ ├── size.rs │ │ └── ulp.rs │ ├── comparison/ │ │ ├── cmp.rs │ │ ├── cmp_abs.rs │ │ ├── eq.rs │ │ ├── eq_abs.rs │ │ ├── eq_abs_integer.rs │ │ ├── eq_abs_natural.rs │ │ ├── eq_abs_primitive_float.rs │ │ ├── eq_abs_primitive_int.rs │ │ ├── eq_abs_rational.rs │ │ ├── hash.rs │ │ ├── partial_cmp_abs_integer.rs │ │ ├── partial_cmp_abs_natural.rs │ │ ├── partial_cmp_abs_primitive_float.rs │ │ ├── partial_cmp_abs_primitive_int.rs │ │ ├── partial_cmp_abs_rational.rs │ │ ├── partial_cmp_integer.rs │ │ ├── partial_cmp_natural.rs │ │ ├── partial_cmp_primitive_float.rs │ │ ├── partial_cmp_primitive_int.rs │ │ ├── partial_cmp_rational.rs │ │ ├── partial_eq_integer.rs │ │ ├── partial_eq_natural.rs │ │ ├── partial_eq_primitive_float.rs │ │ ├── partial_eq_primitive_int.rs │ │ └── partial_eq_rational.rs │ ├── constants/ │ │ ├── gauss_constant.rs │ │ ├── lemniscate_constant.rs │ │ ├── ln_2.rs │ │ ├── log_2_e.rs │ │ ├── one_over_pi.rs │ │ ├── one_over_sqrt_pi.rs │ │ ├── one_over_sqrt_tau.rs │ │ ├── phi.rs │ │ ├── pi.rs │ │ ├── pi_over_2.rs │ │ ├── pi_over_3.rs │ │ ├── pi_over_4.rs │ │ ├── pi_over_6.rs │ │ ├── pi_over_8.rs │ │ ├── prime_constant.rs │ │ ├── prouhet_thue_morse_constant.rs │ │ ├── sqrt_2.rs │ │ ├── sqrt_2_over_2.rs │ │ ├── sqrt_3.rs │ │ ├── sqrt_3_over_3.rs │ │ ├── sqrt_pi.rs │ │ ├── tau.rs │ │ ├── two_over_pi.rs │ │ └── two_over_sqrt_pi.rs │ ├── conversion/ │ │ ├── clone.rs │ │ ├── from_integer.rs │ │ ├── from_natural.rs │ │ ├── from_primitive_float.rs │ │ ├── from_primitive_int.rs │ │ ├── from_rational.rs │ │ ├── integer_from_float.rs │ │ ├── is_integer.rs │ │ ├── mantissa_and_exponent.rs │ │ ├── natural_from_float.rs │ │ ├── primitive_float_from_float.rs │ │ ├── primitive_int_from_float.rs │ │ └── rational_from_float.rs │ ├── exhaustive/ │ │ ├── exhaustive_finite_floats.rs │ │ ├── exhaustive_floats.rs │ │ ├── exhaustive_floats_with_precision.rs │ │ ├── exhaustive_negative_finite_floats.rs │ │ ├── exhaustive_non_negative_finite_floats.rs │ │ ├── exhaustive_non_positive_finite_floats.rs │ │ ├── exhaustive_nonzero_finite_floats.rs │ │ ├── exhaustive_positive_finite_floats.rs │ │ ├── exhaustive_positive_floats_with_precision.rs │ │ ├── exhaustive_positive_floats_with_sci_exponent.rs │ │ └── exhaustive_positive_floats_with_sci_exponent_and_precision.rs │ ├── lib.rs │ └── random/ │ ├── random_finite_floats.rs │ ├── random_floats.rs │ ├── random_negative_finite_floats.rs │ ├── random_non_negative_finite_floats.rs │ ├── random_non_positive_finite_floats.rs │ ├── random_nonzero_finite_floats.rs │ ├── random_positive_finite_floats.rs │ ├── random_positive_floats_with_precision.rs │ ├── striped_random_finite_floats.rs │ ├── striped_random_floats.rs │ ├── striped_random_negative_finite_floats.rs │ ├── striped_random_non_negative_finite_floats.rs │ ├── striped_random_non_positive_finite_floats.rs │ ├── striped_random_nonzero_finite_floats.rs │ ├── striped_random_positive_finite_floats.rs │ └── striped_random_positive_floats_with_precision.rs ├── malachite-nz/ │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── extra-tests.py │ ├── images/ │ │ └── natural-mem-layout.asy │ ├── katex-header.html │ ├── rustfmt.toml │ ├── src/ │ │ ├── bin.rs │ │ ├── bin_util/ │ │ │ ├── demo_and_bench/ │ │ │ │ ├── integer/ │ │ │ │ │ ├── arithmetic/ │ │ │ │ │ │ ├── abs.rs │ │ │ │ │ │ ├── abs_diff.rs │ │ │ │ │ │ ├── add.rs │ │ │ │ │ │ ├── add_mul.rs │ │ │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ │ │ ├── div.rs │ │ │ │ │ │ ├── div_exact.rs │ │ │ │ │ │ ├── div_mod.rs │ │ │ │ │ │ ├── div_round.rs │ │ │ │ │ │ ├── divisible_by.rs │ │ │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ │ │ ├── eq_mod.rs │ │ │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ │ │ ├── extended_gcd.rs │ │ │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── mod_op.rs │ │ │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ │ │ ├── mul.rs │ │ │ │ │ │ ├── neg.rs │ │ │ │ │ │ ├── parity.rs │ │ │ │ │ │ ├── pow.rs │ │ │ │ │ │ ├── power_of_2.rs │ │ │ │ │ │ ├── root.rs │ │ │ │ │ │ ├── round_to_multiple.rs │ │ │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ │ │ ├── shl.rs │ │ │ │ │ │ ├── shl_round.rs │ │ │ │ │ │ ├── shr.rs │ │ │ │ │ │ ├── shr_round.rs │ │ │ │ │ │ ├── sign.rs │ │ │ │ │ │ ├── sqrt.rs │ │ │ │ │ │ ├── square.rs │ │ │ │ │ │ ├── sub.rs │ │ │ │ │ │ └── sub_mul.rs │ │ │ │ │ ├── basic/ │ │ │ │ │ │ ├── from_sign_and_abs.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ ├── comparison/ │ │ │ │ │ │ ├── cmp.rs │ │ │ │ │ │ ├── cmp_abs.rs │ │ │ │ │ │ ├── eq.rs │ │ │ │ │ │ ├── eq_abs.rs │ │ │ │ │ │ ├── eq_abs_natural.rs │ │ │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ │ │ ├── hash.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ │ │ │ ├── partial_cmp_natural.rs │ │ │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ │ │ ├── partial_eq_natural.rs │ │ │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ │ │ ├── conversion/ │ │ │ │ │ │ ├── clone.rs │ │ │ │ │ │ ├── floating_point_from_integer.rs │ │ │ │ │ │ ├── from_bool.rs │ │ │ │ │ │ ├── from_floating_point.rs │ │ │ │ │ │ ├── from_natural.rs │ │ │ │ │ │ ├── from_primitive_int.rs │ │ │ │ │ │ ├── from_twos_complement_limbs.rs │ │ │ │ │ │ ├── is_integer.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── natural_from_integer.rs │ │ │ │ │ │ ├── primitive_int_from_integer.rs │ │ │ │ │ │ ├── serde.rs │ │ │ │ │ │ ├── string/ │ │ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ │ │ ├── from_string.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ │ │ └── to_string.rs │ │ │ │ │ │ └── to_twos_complement_limbs.rs │ │ │ │ │ ├── logic/ │ │ │ │ │ │ ├── and.rs │ │ │ │ │ │ ├── assign_bit.rs │ │ │ │ │ │ ├── assign_bits.rs │ │ │ │ │ │ ├── bits.rs │ │ │ │ │ │ ├── checked_count_ones.rs │ │ │ │ │ │ ├── checked_count_zeros.rs │ │ │ │ │ │ ├── checked_hamming_distance.rs │ │ │ │ │ │ ├── clear_bit.rs │ │ │ │ │ │ ├── flip_bit.rs │ │ │ │ │ │ ├── from_bits.rs │ │ │ │ │ │ ├── get_bit.rs │ │ │ │ │ │ ├── get_bits.rs │ │ │ │ │ │ ├── index_of_next_false_bit.rs │ │ │ │ │ │ ├── index_of_next_true_bit.rs │ │ │ │ │ │ ├── low_mask.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── not.rs │ │ │ │ │ │ ├── or.rs │ │ │ │ │ │ ├── set_bit.rs │ │ │ │ │ │ ├── significant_bits.rs │ │ │ │ │ │ ├── to_bits.rs │ │ │ │ │ │ ├── trailing_zeros.rs │ │ │ │ │ │ └── xor.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── natural/ │ │ │ │ ├── arithmetic/ │ │ │ │ │ ├── abs_diff.rs │ │ │ │ │ ├── add.rs │ │ │ │ │ ├── add_mul.rs │ │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ │ ├── checked_sub.rs │ │ │ │ │ ├── checked_sub_mul.rs │ │ │ │ │ ├── coprime_with.rs │ │ │ │ │ ├── div.rs │ │ │ │ │ ├── div_exact.rs │ │ │ │ │ ├── div_mod.rs │ │ │ │ │ ├── div_round.rs │ │ │ │ │ ├── divisible_by.rs │ │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ │ ├── eq_mod.rs │ │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ │ ├── extended_gcd.rs │ │ │ │ │ ├── factorial.rs │ │ │ │ │ ├── gcd.rs │ │ │ │ │ ├── is_power_of_2.rs │ │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ │ ├── lcm.rs │ │ │ │ │ ├── log_base.rs │ │ │ │ │ ├── log_base_2.rs │ │ │ │ │ ├── log_base_power_of_2.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── mod_add.rs │ │ │ │ │ ├── mod_inverse.rs │ │ │ │ │ ├── mod_is_reduced.rs │ │ │ │ │ ├── mod_mul.rs │ │ │ │ │ ├── mod_neg.rs │ │ │ │ │ ├── mod_op.rs │ │ │ │ │ ├── mod_pow.rs │ │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ │ ├── mod_power_of_2_add.rs │ │ │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ │ │ ├── mod_power_of_2_is_reduced.rs │ │ │ │ │ ├── mod_power_of_2_mul.rs │ │ │ │ │ ├── mod_power_of_2_neg.rs │ │ │ │ │ ├── mod_power_of_2_pow.rs │ │ │ │ │ ├── mod_power_of_2_shl.rs │ │ │ │ │ ├── mod_power_of_2_shr.rs │ │ │ │ │ ├── mod_power_of_2_square.rs │ │ │ │ │ ├── mod_power_of_2_sub.rs │ │ │ │ │ ├── mod_shl.rs │ │ │ │ │ ├── mod_shr.rs │ │ │ │ │ ├── mod_square.rs │ │ │ │ │ ├── mod_sub.rs │ │ │ │ │ ├── mul.rs │ │ │ │ │ ├── neg.rs │ │ │ │ │ ├── next_power_of_2.rs │ │ │ │ │ ├── parity.rs │ │ │ │ │ ├── pow.rs │ │ │ │ │ ├── power_of_2.rs │ │ │ │ │ ├── primorial.rs │ │ │ │ │ ├── root.rs │ │ │ │ │ ├── round_to_multiple.rs │ │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ │ ├── saturating_sub.rs │ │ │ │ │ ├── saturating_sub_mul.rs │ │ │ │ │ ├── shl.rs │ │ │ │ │ ├── shl_round.rs │ │ │ │ │ ├── shr.rs │ │ │ │ │ ├── shr_round.rs │ │ │ │ │ ├── sign.rs │ │ │ │ │ ├── sqrt.rs │ │ │ │ │ ├── square.rs │ │ │ │ │ ├── sub.rs │ │ │ │ │ └── sub_mul.rs │ │ │ │ ├── comparison/ │ │ │ │ │ ├── cmp.rs │ │ │ │ │ ├── eq.rs │ │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ │ ├── hash.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ │ ├── conversion/ │ │ │ │ │ ├── clone.rs │ │ │ │ │ ├── digits/ │ │ │ │ │ │ ├── from_digits.rs │ │ │ │ │ │ ├── from_power_of_2_digits.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── power_of_2_digits.rs │ │ │ │ │ │ ├── to_digits.rs │ │ │ │ │ │ └── to_power_of_2_digits.rs │ │ │ │ │ ├── floating_point_from_natural.rs │ │ │ │ │ ├── from_bool.rs │ │ │ │ │ ├── from_floating_point.rs │ │ │ │ │ ├── from_limbs.rs │ │ │ │ │ ├── from_primitive_int.rs │ │ │ │ │ ├── integer_mantissa_and_exponent.rs │ │ │ │ │ ├── is_integer.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── primitive_int_from_natural.rs │ │ │ │ │ ├── sci_mantissa_and_exponent.rs │ │ │ │ │ ├── serde.rs │ │ │ │ │ ├── string/ │ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ │ ├── from_string.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ │ └── to_string.rs │ │ │ │ │ └── to_limbs.rs │ │ │ │ ├── factorization/ │ │ │ │ │ ├── is_power.rs │ │ │ │ │ ├── is_square.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── primes.rs │ │ │ │ ├── logic/ │ │ │ │ │ ├── and.rs │ │ │ │ │ ├── assign_bit.rs │ │ │ │ │ ├── assign_bits.rs │ │ │ │ │ ├── bits.rs │ │ │ │ │ ├── clear_bit.rs │ │ │ │ │ ├── count_ones.rs │ │ │ │ │ ├── flip_bit.rs │ │ │ │ │ ├── from_bits.rs │ │ │ │ │ ├── get_bit.rs │ │ │ │ │ ├── get_bits.rs │ │ │ │ │ ├── hamming_distance.rs │ │ │ │ │ ├── index_of_next_false_bit.rs │ │ │ │ │ ├── index_of_next_true_bit.rs │ │ │ │ │ ├── low_mask.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── not.rs │ │ │ │ │ ├── or.rs │ │ │ │ │ ├── set_bit.rs │ │ │ │ │ ├── significant_bits.rs │ │ │ │ │ ├── to_bits.rs │ │ │ │ │ ├── trailing_zeros.rs │ │ │ │ │ └── xor.rs │ │ │ │ └── mod.rs │ │ │ └── generate/ │ │ │ ├── digits_data.rs │ │ │ ├── factorial_data.rs │ │ │ └── mod.rs │ │ ├── integer/ │ │ │ ├── arithmetic/ │ │ │ │ ├── abs.rs │ │ │ │ ├── abs_diff.rs │ │ │ │ ├── add.rs │ │ │ │ ├── add_mul.rs │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ ├── div.rs │ │ │ │ ├── div_exact.rs │ │ │ │ ├── div_mod.rs │ │ │ │ ├── div_round.rs │ │ │ │ ├── divisible_by.rs │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ ├── eq_mod.rs │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ ├── extended_gcd.rs │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mod_op.rs │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ ├── mul.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── parity.rs │ │ │ │ ├── pow.rs │ │ │ │ ├── power_of_2.rs │ │ │ │ ├── root.rs │ │ │ │ ├── round_to_multiple.rs │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ ├── shl.rs │ │ │ │ ├── shl_round.rs │ │ │ │ ├── shr.rs │ │ │ │ ├── shr_round.rs │ │ │ │ ├── sign.rs │ │ │ │ ├── sqrt.rs │ │ │ │ ├── square.rs │ │ │ │ ├── sub.rs │ │ │ │ └── sub_mul.rs │ │ │ ├── comparison/ │ │ │ │ ├── cmp.rs │ │ │ │ ├── cmp_abs.rs │ │ │ │ ├── cmp_abs_natural.rs │ │ │ │ ├── cmp_abs_primitive_float.rs │ │ │ │ ├── cmp_abs_primitive_int.rs │ │ │ │ ├── eq_abs.rs │ │ │ │ ├── eq_abs_natural.rs │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── partial_cmp_natural.rs │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ ├── partial_eq_natural.rs │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ ├── conversion/ │ │ │ │ ├── from_bool.rs │ │ │ │ ├── from_natural.rs │ │ │ │ ├── from_primitive_float.rs │ │ │ │ ├── from_primitive_int.rs │ │ │ │ ├── from_twos_complement_limbs.rs │ │ │ │ ├── is_integer.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── natural_from_integer.rs │ │ │ │ ├── primitive_float_from_integer.rs │ │ │ │ ├── primitive_int_from_integer.rs │ │ │ │ ├── pyo3.rs │ │ │ │ ├── serde.rs │ │ │ │ ├── string/ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ ├── from_string.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ └── to_string.rs │ │ │ │ └── to_twos_complement_limbs.rs │ │ │ ├── exhaustive/ │ │ │ │ └── mod.rs │ │ │ ├── logic/ │ │ │ │ ├── and.rs │ │ │ │ ├── bit_access.rs │ │ │ │ ├── bit_block_access.rs │ │ │ │ ├── bit_convertible.rs │ │ │ │ ├── bit_iterable.rs │ │ │ │ ├── bit_scan.rs │ │ │ │ ├── checked_count_ones.rs │ │ │ │ ├── checked_count_zeros.rs │ │ │ │ ├── checked_hamming_distance.rs │ │ │ │ ├── low_mask.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── not.rs │ │ │ │ ├── or.rs │ │ │ │ ├── significant_bits.rs │ │ │ │ ├── trailing_zeros.rs │ │ │ │ └── xor.rs │ │ │ ├── mod.rs │ │ │ └── random/ │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── natural/ │ │ │ ├── arithmetic/ │ │ │ │ ├── abs_diff.rs │ │ │ │ ├── add.rs │ │ │ │ ├── add_mul.rs │ │ │ │ ├── binomial_coefficient.rs │ │ │ │ ├── checked_sub.rs │ │ │ │ ├── checked_sub_mul.rs │ │ │ │ ├── coprime_with.rs │ │ │ │ ├── div.rs │ │ │ │ ├── div_exact.rs │ │ │ │ ├── div_mod.rs │ │ │ │ ├── div_round.rs │ │ │ │ ├── divisible_by.rs │ │ │ │ ├── divisible_by_power_of_2.rs │ │ │ │ ├── eq_mod.rs │ │ │ │ ├── eq_mod_power_of_2.rs │ │ │ │ ├── factorial.rs │ │ │ │ ├── float_add.rs │ │ │ │ ├── float_div.rs │ │ │ │ ├── float_extras.rs │ │ │ │ ├── float_mul.rs │ │ │ │ ├── float_reciprocal.rs │ │ │ │ ├── float_reciprocal_sqrt.rs │ │ │ │ ├── float_sqrt.rs │ │ │ │ ├── float_square.rs │ │ │ │ ├── float_sub.rs │ │ │ │ ├── gcd/ │ │ │ │ │ ├── extended_gcd.rs │ │ │ │ │ ├── half_gcd.rs │ │ │ │ │ ├── matrix_2_2.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── is_power_of_2.rs │ │ │ │ ├── kronecker_symbol.rs │ │ │ │ ├── lcm.rs │ │ │ │ ├── log_base.rs │ │ │ │ ├── log_base_2.rs │ │ │ │ ├── log_base_power_of_2.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mod_add.rs │ │ │ │ ├── mod_inverse.rs │ │ │ │ ├── mod_is_reduced.rs │ │ │ │ ├── mod_mul.rs │ │ │ │ ├── mod_neg.rs │ │ │ │ ├── mod_op.rs │ │ │ │ ├── mod_pow.rs │ │ │ │ ├── mod_power_of_2.rs │ │ │ │ ├── mod_power_of_2_add.rs │ │ │ │ ├── mod_power_of_2_inverse.rs │ │ │ │ ├── mod_power_of_2_is_reduced.rs │ │ │ │ ├── mod_power_of_2_mul.rs │ │ │ │ ├── mod_power_of_2_neg.rs │ │ │ │ ├── mod_power_of_2_pow.rs │ │ │ │ ├── mod_power_of_2_shl.rs │ │ │ │ ├── mod_power_of_2_shr.rs │ │ │ │ ├── mod_power_of_2_square.rs │ │ │ │ ├── mod_power_of_2_sub.rs │ │ │ │ ├── mod_shl.rs │ │ │ │ ├── mod_shr.rs │ │ │ │ ├── mod_square.rs │ │ │ │ ├── mod_sub.rs │ │ │ │ ├── mul/ │ │ │ │ │ ├── context.rs │ │ │ │ │ ├── fft.rs │ │ │ │ │ ├── limb.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── mul_low.rs │ │ │ │ │ ├── mul_mod.rs │ │ │ │ │ ├── poly_eval.rs │ │ │ │ │ ├── poly_interpolate.rs │ │ │ │ │ ├── product_of_limbs.rs │ │ │ │ │ └── toom.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── next_power_of_2.rs │ │ │ │ ├── parity.rs │ │ │ │ ├── pow.rs │ │ │ │ ├── power_of_2.rs │ │ │ │ ├── primorial.rs │ │ │ │ ├── root.rs │ │ │ │ ├── round_to_multiple.rs │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ ├── saturating_sub.rs │ │ │ │ ├── saturating_sub_mul.rs │ │ │ │ ├── shl.rs │ │ │ │ ├── shl_round.rs │ │ │ │ ├── shr.rs │ │ │ │ ├── shr_round.rs │ │ │ │ ├── sign.rs │ │ │ │ ├── sqrt.rs │ │ │ │ ├── square.rs │ │ │ │ ├── sub.rs │ │ │ │ └── sub_mul.rs │ │ │ ├── comparison/ │ │ │ │ ├── cmp.rs │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ ├── conversion/ │ │ │ │ ├── digits/ │ │ │ │ │ ├── general_digits.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── power_of_2_digit_iterable.rs │ │ │ │ │ └── power_of_2_digits.rs │ │ │ │ ├── from_bool.rs │ │ │ │ ├── from_limbs.rs │ │ │ │ ├── from_primitive_float.rs │ │ │ │ ├── from_primitive_int.rs │ │ │ │ ├── is_integer.rs │ │ │ │ ├── limb_count.rs │ │ │ │ ├── mantissa_and_exponent.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── primitive_float_from_natural.rs │ │ │ │ ├── primitive_int_from_natural.rs │ │ │ │ ├── pyo3.rs │ │ │ │ ├── serde.rs │ │ │ │ ├── string/ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ ├── from_string.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ └── to_string.rs │ │ │ │ └── to_limbs.rs │ │ │ ├── exhaustive/ │ │ │ │ └── mod.rs │ │ │ ├── factorization/ │ │ │ │ ├── is_power.rs │ │ │ │ ├── is_square.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── primes.rs │ │ │ │ └── remove_power.rs │ │ │ ├── logic/ │ │ │ │ ├── and.rs │ │ │ │ ├── bit_access.rs │ │ │ │ ├── bit_block_access.rs │ │ │ │ ├── bit_convertible.rs │ │ │ │ ├── bit_iterable.rs │ │ │ │ ├── bit_scan.rs │ │ │ │ ├── count_ones.rs │ │ │ │ ├── hamming_distance.rs │ │ │ │ ├── low_mask.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── not.rs │ │ │ │ ├── or.rs │ │ │ │ ├── significant_bits.rs │ │ │ │ ├── trailing_zeros.rs │ │ │ │ └── xor.rs │ │ │ ├── mod.rs │ │ │ └── random/ │ │ │ └── mod.rs │ │ ├── platform_32.rs │ │ ├── platform_64.rs │ │ └── test_util/ │ │ ├── bench/ │ │ │ ├── bucketers.rs │ │ │ └── mod.rs │ │ ├── common/ │ │ │ └── mod.rs │ │ ├── extra_variadic/ │ │ │ └── mod.rs │ │ ├── generators/ │ │ │ ├── common.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ ├── random.rs │ │ │ └── special_random.rs │ │ ├── integer/ │ │ │ ├── arithmetic/ │ │ │ │ ├── add.rs │ │ │ │ ├── divisible_by.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mul.rs │ │ │ │ └── sign.rs │ │ │ ├── comparison/ │ │ │ │ ├── mod.rs │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ ├── conversion/ │ │ │ │ ├── mod.rs │ │ │ │ └── to_twos_complement_limbs.rs │ │ │ ├── logic/ │ │ │ │ ├── and.rs │ │ │ │ ├── checked_count_ones.rs │ │ │ │ ├── checked_count_zeros.rs │ │ │ │ ├── checked_hamming_distance.rs │ │ │ │ ├── from_bits.rs │ │ │ │ ├── index_of_next_false_bit.rs │ │ │ │ ├── index_of_next_true_bit.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── or.rs │ │ │ │ ├── to_bits.rs │ │ │ │ ├── trailing_zeros.rs │ │ │ │ └── xor.rs │ │ │ ├── mod.rs │ │ │ └── random/ │ │ │ └── mod.rs │ │ ├── mod.rs │ │ └── natural/ │ │ ├── arithmetic/ │ │ │ ├── add.rs │ │ │ ├── binomial_coefficient.rs │ │ │ ├── checked_sub.rs │ │ │ ├── div.rs │ │ │ ├── div_exact.rs │ │ │ ├── div_mod.rs │ │ │ ├── divisible_by.rs │ │ │ ├── eq_mod.rs │ │ │ ├── extended_gcd.rs │ │ │ ├── factorial.rs │ │ │ ├── gcd.rs │ │ │ ├── kronecker_symbol.rs │ │ │ ├── log_base.rs │ │ │ ├── log_base_power_of_2.rs │ │ │ ├── mod.rs │ │ │ ├── mod_inverse.rs │ │ │ ├── mod_mul.rs │ │ │ ├── mod_op.rs │ │ │ ├── mod_pow.rs │ │ │ ├── mod_power_of_2_pow.rs │ │ │ ├── mod_power_of_2_square.rs │ │ │ ├── mul.rs │ │ │ ├── neg.rs │ │ │ ├── pow.rs │ │ │ ├── primorial.rs │ │ │ ├── root.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ └── sub.rs │ │ ├── comparison/ │ │ │ ├── cmp.rs │ │ │ ├── mod.rs │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ └── partial_eq_primitive_int.rs │ │ ├── conversion/ │ │ │ ├── mod.rs │ │ │ └── string/ │ │ │ ├── from_string.rs │ │ │ ├── mod.rs │ │ │ └── to_string.rs │ │ ├── logic/ │ │ │ ├── and.rs │ │ │ ├── count_ones.rs │ │ │ ├── from_bits.rs │ │ │ ├── get_bit.rs │ │ │ ├── hamming_distance.rs │ │ │ ├── index_of_next_false_bit.rs │ │ │ ├── index_of_next_true_bit.rs │ │ │ ├── mod.rs │ │ │ ├── or.rs │ │ │ ├── set_bit.rs │ │ │ ├── to_bits.rs │ │ │ ├── trailing_zeros.rs │ │ │ └── xor.rs │ │ ├── mod.rs │ │ └── random/ │ │ └── mod.rs │ └── tests/ │ ├── integer/ │ │ ├── arithmetic/ │ │ │ ├── abs.rs │ │ │ ├── abs_diff.rs │ │ │ ├── add.rs │ │ │ ├── add_mul.rs │ │ │ ├── binomial_coefficient.rs │ │ │ ├── div.rs │ │ │ ├── div_exact.rs │ │ │ ├── div_mod.rs │ │ │ ├── div_round.rs │ │ │ ├── divisible_by.rs │ │ │ ├── divisible_by_power_of_2.rs │ │ │ ├── eq_mod.rs │ │ │ ├── eq_mod_power_of_2.rs │ │ │ ├── extended_gcd.rs │ │ │ ├── kronecker_symbol.rs │ │ │ ├── mod_op.rs │ │ │ ├── mod_power_of_2.rs │ │ │ ├── mul.rs │ │ │ ├── neg.rs │ │ │ ├── parity.rs │ │ │ ├── pow.rs │ │ │ ├── power_of_2.rs │ │ │ ├── root.rs │ │ │ ├── round_to_multiple.rs │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ ├── shl.rs │ │ │ ├── shl_round.rs │ │ │ ├── shr.rs │ │ │ ├── shr_round.rs │ │ │ ├── sign.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ ├── sub.rs │ │ │ └── sub_mul.rs │ │ ├── basic/ │ │ │ ├── constants.rs │ │ │ ├── default.rs │ │ │ ├── from_sign_and_abs.rs │ │ │ ├── named.rs │ │ │ └── size.rs │ │ ├── comparison/ │ │ │ ├── cmp.rs │ │ │ ├── cmp_abs.rs │ │ │ ├── eq.rs │ │ │ ├── eq_abs.rs │ │ │ ├── eq_abs_natural.rs │ │ │ ├── eq_abs_primitive_float.rs │ │ │ ├── eq_abs_primitive_int.rs │ │ │ ├── hash.rs │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ ├── partial_cmp_natural.rs │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ ├── partial_eq_natural.rs │ │ │ ├── partial_eq_primitive_float.rs │ │ │ └── partial_eq_primitive_int.rs │ │ ├── conversion/ │ │ │ ├── clone.rs │ │ │ ├── from_bool.rs │ │ │ ├── from_natural.rs │ │ │ ├── from_primitive_float.rs │ │ │ ├── from_primitive_int.rs │ │ │ ├── from_twos_complement_limbs.rs │ │ │ ├── is_integer.rs │ │ │ ├── natural_from_integer.rs │ │ │ ├── primitive_float_from_integer.rs │ │ │ ├── primitive_int_from_integer.rs │ │ │ ├── serde.rs │ │ │ ├── string/ │ │ │ │ ├── from_sci_string.rs │ │ │ │ ├── from_string.rs │ │ │ │ ├── to_sci.rs │ │ │ │ └── to_string.rs │ │ │ └── to_twos_complement_limbs.rs │ │ ├── exhaustive/ │ │ │ ├── exhaustive_integer_inclusive_range.rs │ │ │ ├── exhaustive_integer_range.rs │ │ │ ├── exhaustive_integer_range_to_infinity.rs │ │ │ ├── exhaustive_integer_range_to_negative_infinity.rs │ │ │ ├── exhaustive_integers.rs │ │ │ ├── exhaustive_natural_integers.rs │ │ │ ├── exhaustive_negative_integers.rs │ │ │ ├── exhaustive_nonzero_integers.rs │ │ │ ├── exhaustive_positive_integers.rs │ │ │ ├── integer_decreasing_range_to_negative_infinity.rs │ │ │ ├── integer_increasing_inclusive_range.rs │ │ │ ├── integer_increasing_range.rs │ │ │ └── integer_increasing_range_to_infinity.rs │ │ ├── logic/ │ │ │ ├── and.rs │ │ │ ├── assign_bit.rs │ │ │ ├── assign_bits.rs │ │ │ ├── bits.rs │ │ │ ├── checked_count_ones.rs │ │ │ ├── checked_count_zeros.rs │ │ │ ├── checked_hamming_distance.rs │ │ │ ├── clear_bit.rs │ │ │ ├── flip_bit.rs │ │ │ ├── from_bits.rs │ │ │ ├── get_bit.rs │ │ │ ├── get_bits.rs │ │ │ ├── index_of_next_false_bit.rs │ │ │ ├── index_of_next_true_bit.rs │ │ │ ├── low_mask.rs │ │ │ ├── not.rs │ │ │ ├── or.rs │ │ │ ├── set_bit.rs │ │ │ ├── significant_bits.rs │ │ │ ├── to_bits.rs │ │ │ ├── trailing_zeros.rs │ │ │ └── xor.rs │ │ └── random/ │ │ ├── get_random_integer_from_range_to_infinity.rs │ │ ├── get_random_integer_from_range_to_negative_infinity.rs │ │ ├── get_striped_random_integer_from_inclusive_range.rs │ │ ├── get_striped_random_integer_from_range.rs │ │ ├── get_striped_random_integer_from_range_to_infinity.rs │ │ ├── get_striped_random_integer_from_range_to_negative_infinity.rs │ │ ├── get_uniform_random_integer_from_inclusive_range.rs │ │ ├── get_uniform_random_integer_from_range.rs │ │ ├── random_integer_inclusive_range.rs │ │ ├── random_integer_range.rs │ │ ├── random_integer_range_to_infinity.rs │ │ ├── random_integer_range_to_negative_infinity.rs │ │ ├── random_integers.rs │ │ ├── random_natural_integers.rs │ │ ├── random_negative_integers.rs │ │ ├── random_nonzero_integers.rs │ │ ├── random_positive_integers.rs │ │ ├── striped_random_integer_inclusive_range.rs │ │ ├── striped_random_integer_range.rs │ │ ├── striped_random_integer_range_to_infinity.rs │ │ ├── striped_random_integer_range_to_negative_infinity.rs │ │ ├── striped_random_integers.rs │ │ ├── striped_random_natural_integers.rs │ │ ├── striped_random_negative_integers.rs │ │ ├── striped_random_nonzero_integers.rs │ │ ├── striped_random_positive_integers.rs │ │ ├── uniform_random_integer_inclusive_range.rs │ │ └── uniform_random_integer_range.rs │ ├── lib.rs │ └── natural/ │ ├── arithmetic/ │ │ ├── abs_diff.rs │ │ ├── add.rs │ │ ├── add_mul.rs │ │ ├── binomial_coefficient.rs │ │ ├── checked_sub.rs │ │ ├── checked_sub_mul.rs │ │ ├── coprime_with.rs │ │ ├── div.rs │ │ ├── div_exact.rs │ │ ├── div_mod.rs │ │ ├── div_round.rs │ │ ├── divisible_by.rs │ │ ├── divisible_by_power_of_2.rs │ │ ├── eq_mod.rs │ │ ├── eq_mod_power_of_2.rs │ │ ├── extended_gcd.rs │ │ ├── factorial.rs │ │ ├── gcd.rs │ │ ├── is_power_of_2.rs │ │ ├── kronecker_symbol.rs │ │ ├── lcm.rs │ │ ├── log_base.rs │ │ ├── log_base_2.rs │ │ ├── log_base_power_of_2.rs │ │ ├── mod_add.rs │ │ ├── mod_inverse.rs │ │ ├── mod_is_reduced.rs │ │ ├── mod_mul.rs │ │ ├── mod_neg.rs │ │ ├── mod_op.rs │ │ ├── mod_pow.rs │ │ ├── mod_power_of_2.rs │ │ ├── mod_power_of_2_add.rs │ │ ├── mod_power_of_2_inverse.rs │ │ ├── mod_power_of_2_is_reduced.rs │ │ ├── mod_power_of_2_mul.rs │ │ ├── mod_power_of_2_neg.rs │ │ ├── mod_power_of_2_pow.rs │ │ ├── mod_power_of_2_shl.rs │ │ ├── mod_power_of_2_shr.rs │ │ ├── mod_power_of_2_square.rs │ │ ├── mod_power_of_2_sub.rs │ │ ├── mod_shl.rs │ │ ├── mod_shr.rs │ │ ├── mod_square.rs │ │ ├── mod_sub.rs │ │ ├── mul.rs │ │ ├── neg.rs │ │ ├── next_power_of_2.rs │ │ ├── parity.rs │ │ ├── pow.rs │ │ ├── power_of_2.rs │ │ ├── primorial.rs │ │ ├── root.rs │ │ ├── round_to_multiple.rs │ │ ├── round_to_multiple_of_power_of_2.rs │ │ ├── saturating_sub.rs │ │ ├── saturating_sub_mul.rs │ │ ├── shl.rs │ │ ├── shl_round.rs │ │ ├── shr.rs │ │ ├── shr_round.rs │ │ ├── sign.rs │ │ ├── sqrt.rs │ │ ├── square.rs │ │ ├── sub.rs │ │ └── sub_mul.rs │ ├── basic/ │ │ ├── constants.rs │ │ ├── default.rs │ │ ├── named.rs │ │ └── size.rs │ ├── comparison/ │ │ ├── cmp.rs │ │ ├── eq.rs │ │ ├── eq_abs_primitive_float.rs │ │ ├── eq_abs_primitive_int.rs │ │ ├── hash.rs │ │ ├── partial_cmp_abs_primitive_float.rs │ │ ├── partial_cmp_abs_primitive_int.rs │ │ ├── partial_cmp_primitive_float.rs │ │ ├── partial_cmp_primitive_int.rs │ │ ├── partial_eq_primitive_float.rs │ │ └── partial_eq_primitive_int.rs │ ├── conversion/ │ │ ├── clone.rs │ │ ├── digits/ │ │ │ ├── from_digits.rs │ │ │ ├── from_power_of_2_digits.rs │ │ │ ├── power_of_2_digits.rs │ │ │ ├── to_digits.rs │ │ │ └── to_power_of_2_digits.rs │ │ ├── from_bool.rs │ │ ├── from_limbs.rs │ │ ├── from_primitive_float.rs │ │ ├── from_primitive_int.rs │ │ ├── is_integer.rs │ │ ├── mantissa_and_exponent/ │ │ │ ├── integer_mantissa_and_exponent.rs │ │ │ └── sci_mantissa_and_exponent.rs │ │ ├── primitive_float_from_natural.rs │ │ ├── primitive_int_from_natural.rs │ │ ├── serde.rs │ │ ├── string/ │ │ │ ├── from_sci_string.rs │ │ │ ├── from_string.rs │ │ │ ├── to_sci.rs │ │ │ └── to_string.rs │ │ └── to_limbs.rs │ ├── exhaustive/ │ │ ├── exhaustive_natural_inclusive_range.rs │ │ ├── exhaustive_natural_range.rs │ │ ├── exhaustive_natural_range_to_infinity.rs │ │ ├── exhaustive_naturals.rs │ │ └── exhaustive_positive_naturals.rs │ ├── factorization/ │ │ ├── is_power.rs │ │ ├── is_square.rs │ │ └── primes.rs │ ├── logic/ │ │ ├── and.rs │ │ ├── assign_bit.rs │ │ ├── assign_bits.rs │ │ ├── bits.rs │ │ ├── clear_bit.rs │ │ ├── count_ones.rs │ │ ├── flip_bit.rs │ │ ├── from_bits.rs │ │ ├── get_bit.rs │ │ ├── get_bits.rs │ │ ├── hamming_distance.rs │ │ ├── index_of_next_false_bit.rs │ │ ├── index_of_next_true_bit.rs │ │ ├── limb_count.rs │ │ ├── low_mask.rs │ │ ├── not.rs │ │ ├── or.rs │ │ ├── set_bit.rs │ │ ├── significant_bits.rs │ │ ├── to_bits.rs │ │ ├── trailing_zeros.rs │ │ └── xor.rs │ └── random/ │ ├── get_random_natural_less_than.rs │ ├── get_random_natural_with_bits.rs │ ├── get_random_natural_with_up_to_bits.rs │ ├── get_striped_random_natural_from_inclusive_range.rs │ ├── get_striped_random_natural_from_range.rs │ ├── get_striped_random_natural_with_bits.rs │ ├── get_striped_random_natural_with_up_to_bits.rs │ ├── random_natural_inclusive_range.rs │ ├── random_natural_range.rs │ ├── random_natural_range_to_infinity.rs │ ├── random_naturals.rs │ ├── random_naturals_less_than.rs │ ├── random_positive_naturals.rs │ ├── striped_random_natural_inclusive_range.rs │ ├── striped_random_natural_range.rs │ ├── striped_random_natural_range_to_infinity.rs │ ├── striped_random_naturals.rs │ ├── striped_random_positive_naturals.rs │ ├── uniform_random_natural_inclusive_range.rs │ └── uniform_random_natural_range.rs ├── malachite-q/ │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── katex-header.html │ ├── rustfmt.toml │ ├── src/ │ │ ├── arithmetic/ │ │ │ ├── abs.rs │ │ │ ├── abs_diff.rs │ │ │ ├── add.rs │ │ │ ├── approximate.rs │ │ │ ├── ceiling.rs │ │ │ ├── denominators_in_closed_interval.rs │ │ │ ├── div.rs │ │ │ ├── floor.rs │ │ │ ├── is_power_of_2.rs │ │ │ ├── log_base.rs │ │ │ ├── log_base_2.rs │ │ │ ├── log_base_power_of_2.rs │ │ │ ├── mod.rs │ │ │ ├── mod_op.rs │ │ │ ├── mul.rs │ │ │ ├── neg.rs │ │ │ ├── next_power_of_2.rs │ │ │ ├── pow.rs │ │ │ ├── power_of_2.rs │ │ │ ├── reciprocal.rs │ │ │ ├── root.rs │ │ │ ├── round_to_multiple.rs │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ ├── shl.rs │ │ │ ├── shr.rs │ │ │ ├── sign.rs │ │ │ ├── simplest_rational_in_interval.rs │ │ │ ├── sqrt.rs │ │ │ ├── square.rs │ │ │ ├── sub.rs │ │ │ └── traits.rs │ │ ├── bin.rs │ │ ├── bin_util/ │ │ │ └── demo_and_bench/ │ │ │ ├── arithmetic/ │ │ │ │ ├── abs.rs │ │ │ │ ├── abs_diff.rs │ │ │ │ ├── add.rs │ │ │ │ ├── approximate.rs │ │ │ │ ├── ceiling.rs │ │ │ │ ├── denominators_in_closed_interval.rs │ │ │ │ ├── div.rs │ │ │ │ ├── floor.rs │ │ │ │ ├── is_power_of_2.rs │ │ │ │ ├── log_base.rs │ │ │ │ ├── log_base_2.rs │ │ │ │ ├── log_base_power_of_2.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mod_op.rs │ │ │ │ ├── mul.rs │ │ │ │ ├── neg.rs │ │ │ │ ├── next_power_of_2.rs │ │ │ │ ├── pow.rs │ │ │ │ ├── power_of_2.rs │ │ │ │ ├── reciprocal.rs │ │ │ │ ├── root.rs │ │ │ │ ├── round_to_multiple.rs │ │ │ │ ├── round_to_multiple_of_power_of_2.rs │ │ │ │ ├── shl.rs │ │ │ │ ├── shr.rs │ │ │ │ ├── sign.rs │ │ │ │ ├── simplest_rational_in_interval.rs │ │ │ │ ├── sqrt.rs │ │ │ │ ├── square.rs │ │ │ │ └── sub.rs │ │ │ ├── basic/ │ │ │ │ ├── mod.rs │ │ │ │ └── significant_bits.rs │ │ │ ├── comparison/ │ │ │ │ ├── cmp.rs │ │ │ │ ├── cmp_abs.rs │ │ │ │ ├── eq.rs │ │ │ │ ├── eq_abs.rs │ │ │ │ ├── eq_abs_integer.rs │ │ │ │ ├── eq_abs_natural.rs │ │ │ │ ├── eq_abs_primitive_float.rs │ │ │ │ ├── eq_abs_primitive_int.rs │ │ │ │ ├── hash.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── partial_cmp_abs_integer.rs │ │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ │ ├── partial_cmp_integer.rs │ │ │ │ ├── partial_cmp_natural.rs │ │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ │ ├── partial_eq_integer.rs │ │ │ │ ├── partial_eq_natural.rs │ │ │ │ ├── partial_eq_primitive_float.rs │ │ │ │ └── partial_eq_primitive_int.rs │ │ │ ├── conversion/ │ │ │ │ ├── clone.rs │ │ │ │ ├── continued_fraction/ │ │ │ │ │ ├── convergents.rs │ │ │ │ │ ├── from_continued_fraction.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── to_continued_fraction.rs │ │ │ │ ├── digits/ │ │ │ │ │ ├── from_digits.rs │ │ │ │ │ ├── from_power_of_2_digits.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── to_digits.rs │ │ │ │ │ └── to_power_of_2_digits.rs │ │ │ │ ├── from_bool.rs │ │ │ │ ├── from_float_simplest.rs │ │ │ │ ├── from_integer.rs │ │ │ │ ├── from_natural.rs │ │ │ │ ├── from_numerator_and_denominator.rs │ │ │ │ ├── from_primitive_float.rs │ │ │ │ ├── from_primitive_int.rs │ │ │ │ ├── integer_from_rational.rs │ │ │ │ ├── is_integer.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── mutate_numerator_or_denominator.rs │ │ │ │ ├── natural_from_rational.rs │ │ │ │ ├── primitive_float_from_rational.rs │ │ │ │ ├── primitive_int_from_rational.rs │ │ │ │ ├── sci_mantissa_and_exponent.rs │ │ │ │ ├── serde.rs │ │ │ │ ├── string/ │ │ │ │ │ ├── from_sci_string.rs │ │ │ │ │ ├── from_string.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── to_sci.rs │ │ │ │ │ └── to_string.rs │ │ │ │ └── to_numerator_or_denominator.rs │ │ │ └── mod.rs │ │ ├── comparison/ │ │ │ ├── cmp.rs │ │ │ ├── cmp_abs.rs │ │ │ ├── eq_abs.rs │ │ │ ├── eq_abs_integer.rs │ │ │ ├── eq_abs_natural.rs │ │ │ ├── eq_abs_primitive_float.rs │ │ │ ├── eq_abs_primitive_int.rs │ │ │ ├── mod.rs │ │ │ ├── partial_cmp_abs_integer.rs │ │ │ ├── partial_cmp_abs_natural.rs │ │ │ ├── partial_cmp_abs_primitive_float.rs │ │ │ ├── partial_cmp_abs_primitive_int.rs │ │ │ ├── partial_cmp_integer.rs │ │ │ ├── partial_cmp_natural.rs │ │ │ ├── partial_cmp_primitive_float.rs │ │ │ ├── partial_cmp_primitive_int.rs │ │ │ ├── partial_eq_integer.rs │ │ │ ├── partial_eq_natural.rs │ │ │ ├── partial_eq_primitive_float.rs │ │ │ └── partial_eq_primitive_int.rs │ │ ├── conversion/ │ │ │ ├── continued_fraction/ │ │ │ │ ├── convergents.rs │ │ │ │ ├── from_continued_fraction.rs │ │ │ │ ├── mod.rs │ │ │ │ └── to_continued_fraction.rs │ │ │ ├── digits/ │ │ │ │ ├── digits.rs │ │ │ │ ├── from_digits.rs │ │ │ │ ├── from_power_of_2_digits.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── power_of_2_digits.rs │ │ │ │ ├── to_digits.rs │ │ │ │ └── to_power_of_2_digits.rs │ │ │ ├── from_bool.rs │ │ │ ├── from_float_simplest.rs │ │ │ ├── from_integer.rs │ │ │ ├── from_natural.rs │ │ │ ├── from_numerator_and_denominator.rs │ │ │ ├── from_primitive_float.rs │ │ │ ├── from_primitive_int.rs │ │ │ ├── integer_from_rational.rs │ │ │ ├── is_integer.rs │ │ │ ├── mantissa_and_exponent.rs │ │ │ ├── mod.rs │ │ │ ├── mutate_numerator_and_denominator.rs │ │ │ ├── natural_from_rational.rs │ │ │ ├── primitive_float_from_rational.rs │ │ │ ├── primitive_int_from_rational.rs │ │ │ ├── string/ │ │ │ │ ├── from_sci_string.rs │ │ │ │ ├── from_string.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── to_sci.rs │ │ │ │ └── to_string.rs │ │ │ ├── to_numerator_and_denominator.rs │ │ │ └── traits.rs │ │ ├── exhaustive/ │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── random/ │ │ │ └── mod.rs │ │ └── test_util/ │ │ ├── arithmetic/ │ │ │ ├── add.rs │ │ │ ├── approximate.rs │ │ │ ├── div.rs │ │ │ ├── mod.rs │ │ │ ├── mod_op.rs │ │ │ ├── mul.rs │ │ │ ├── sign.rs │ │ │ ├── simplest_rational_in_interval.rs │ │ │ └── sub.rs │ │ ├── bench/ │ │ │ ├── bucketers.rs │ │ │ └── mod.rs │ │ ├── common/ │ │ │ └── mod.rs │ │ ├── conversion/ │ │ │ ├── continued_fraction/ │ │ │ │ ├── convergents.rs │ │ │ │ ├── from_continued_fraction.rs │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── extra_variadic/ │ │ │ └── mod.rs │ │ ├── generators/ │ │ │ ├── common.rs │ │ │ ├── exhaustive.rs │ │ │ ├── mod.rs │ │ │ ├── random.rs │ │ │ └── special_random.rs │ │ ├── mod.rs │ │ └── random/ │ │ └── mod.rs │ └── tests/ │ ├── arithmetic/ │ │ ├── abs.rs │ │ ├── abs_diff.rs │ │ ├── add.rs │ │ ├── approximate.rs │ │ ├── ceiling.rs │ │ ├── denominators_in_closed_interval.rs │ │ ├── div.rs │ │ ├── floor.rs │ │ ├── is_power_of_2.rs │ │ ├── log_base.rs │ │ ├── log_base_2.rs │ │ ├── log_base_power_of_2.rs │ │ ├── mod_op.rs │ │ ├── mul.rs │ │ ├── neg.rs │ │ ├── next_power_of_2.rs │ │ ├── pow.rs │ │ ├── power_of_2.rs │ │ ├── reciprocal.rs │ │ ├── root.rs │ │ ├── round_to_multiple.rs │ │ ├── round_to_multiple_of_power_of_2.rs │ │ ├── shl.rs │ │ ├── shr.rs │ │ ├── sign.rs │ │ ├── simplest_rational_in_interval.rs │ │ ├── sqrt.rs │ │ ├── square.rs │ │ └── sub.rs │ ├── basic/ │ │ ├── constants.rs │ │ ├── default.rs │ │ ├── named.rs │ │ ├── significant_bits.rs │ │ └── size.rs │ ├── comparison/ │ │ ├── cmp.rs │ │ ├── cmp_abs.rs │ │ ├── eq.rs │ │ ├── eq_abs.rs │ │ ├── eq_abs_integer.rs │ │ ├── eq_abs_natural.rs │ │ ├── eq_abs_primitive_float.rs │ │ ├── eq_abs_primitive_int.rs │ │ ├── hash.rs │ │ ├── partial_cmp_abs_integer.rs │ │ ├── partial_cmp_abs_natural.rs │ │ ├── partial_cmp_abs_primitive_float.rs │ │ ├── partial_cmp_abs_primitive_int.rs │ │ ├── partial_cmp_integer.rs │ │ ├── partial_cmp_natural.rs │ │ ├── partial_cmp_primitive_float.rs │ │ ├── partial_cmp_primitive_int.rs │ │ ├── partial_eq_integer.rs │ │ ├── partial_eq_natural.rs │ │ ├── partial_eq_primitive_float.rs │ │ └── partial_eq_primitive_int.rs │ ├── conversion/ │ │ ├── clone.rs │ │ ├── continued_fraction/ │ │ │ ├── convergents.rs │ │ │ ├── from_continued_fraction.rs │ │ │ └── to_continued_fraction.rs │ │ ├── digits/ │ │ │ ├── digits.rs │ │ │ ├── from_digits.rs │ │ │ ├── from_power_of_2_digits.rs │ │ │ ├── power_of_2_digits.rs │ │ │ ├── to_digits.rs │ │ │ └── to_power_of_2_digits.rs │ │ ├── from_bool.rs │ │ ├── from_float_simplest.rs │ │ ├── from_integer.rs │ │ ├── from_natural.rs │ │ ├── from_numerator_and_denominator.rs │ │ ├── from_primitive_float.rs │ │ ├── from_primitive_int.rs │ │ ├── integer_from_rational.rs │ │ ├── is_integer.rs │ │ ├── mutate_numerator_or_denominator.rs │ │ ├── natural_from_rational.rs │ │ ├── primitive_float_from_rational.rs │ │ ├── primitive_int_from_rational.rs │ │ ├── sci_mantissa_and_exponent.rs │ │ ├── serde.rs │ │ ├── string/ │ │ │ ├── from_sci_string.rs │ │ │ ├── from_string.rs │ │ │ ├── to_sci.rs │ │ │ └── to_string.rs │ │ └── to_numerator_or_denominator.rs │ ├── exhaustive/ │ │ ├── exhaustive_negative_rationals.rs │ │ ├── exhaustive_non_negative_rationals.rs │ │ ├── exhaustive_nonzero_rationals.rs │ │ ├── exhaustive_positive_rationals.rs │ │ ├── exhaustive_rational_inclusive_range.rs │ │ ├── exhaustive_rational_range.rs │ │ ├── exhaustive_rational_range_to_infinity.rs │ │ ├── exhaustive_rational_range_to_negative_infinity.rs │ │ ├── exhaustive_rationals.rs │ │ ├── exhaustive_rationals_with_denominator_inclusive_range.rs │ │ ├── exhaustive_rationals_with_denominator_range.rs │ │ ├── exhaustive_rationals_with_denominator_range_to_infinity.rs │ │ └── exhaustive_rationals_with_denominator_range_to_negative_infinity.rs │ ├── lib.rs │ └── random/ │ ├── random_negative_rationals.rs │ ├── random_non_negative_rationals.rs │ ├── random_nonzero_rationals.rs │ ├── random_positive_rationals.rs │ ├── random_rational_inclusive_range.rs │ ├── random_rational_range.rs │ ├── random_rational_range_to_infinity.rs │ ├── random_rational_range_to_negative_infinity.rs │ ├── random_rational_with_denominator_inclusive_range.rs │ ├── random_rational_with_denominator_range.rs │ ├── random_rational_with_denominator_range_to_infinity.rs │ ├── random_rational_with_denominator_range_to_negative_infinity.rs │ ├── random_rationals.rs │ ├── striped_random_negative_rationals.rs │ ├── striped_random_non_negative_rationals.rs │ ├── striped_random_nonzero_rationals.rs │ ├── striped_random_positive_rationals.rs │ ├── striped_random_rational_range_to_infinity.rs │ ├── striped_random_rational_range_to_negative_infinity.rs │ └── striped_random_rationals.rs ├── rundoc.sh └── superfmt.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .envrc ================================================ if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" fi use flake # vi: ft=sh ================================================ FILE: .github/FUNDING.yml ================================================ github: mhogrefe ================================================ FILE: .github/workflows/rust.yml ================================================ name: Rust on: push: branches: [ "master" ] pull_request: branches: [ "master" ] env: CARGO_TERM_COLOR: always jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build run: cargo build --verbose - name: Run tests run: cargo test --release --verbose ================================================ FILE: .gitignore ================================================ target *.bk .idea* *.iml src/integer_old.rs *.DS_Store */.vscode/* *.history/* */.history/* .direnv/ ================================================ FILE: .vscode/launch.json ================================================ { "version": "0.2.0", "configurations": [ { "name": "malachite-nz-test-util", "type": "lldb", "request": "launch", "program": "${workspaceRoot}/malachite-nz-test-util/target/debug/malachite_nz_test_util_main", "args": ["-l 10000 -m exhaustive -d demo_natural_mul"], "cwd": "${workspaceRoot}", "stopOnEntry": false, } ] } ================================================ FILE: .vscode/tasks.json ================================================ { // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "label": "malachite-base: check", "type": "shell", "command": "cargo check --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-base" } }, { "label": "malachite-base: clippy", "type": "shell", "command": "cargo clippy --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-base" } }, { "label": "malachite-base: fmt", "type": "shell", "command": "cargo fmt", "options": { "cwd": "${workspaceFolder}/malachite-base" } }, { "label": "malachite-base: doc", "type": "shell", "command": "cargo doc --no-deps", "options": { "cwd": "${workspaceFolder}/malachite-base", "env": { "RUSTDOCFLAGS": "--html-in-header katex-header.html" } } }, { "label": "malachite-base: open docs", "type": "shell", "command": "open target/doc/malachite_base/index.html", "options": { "cwd": "${workspaceFolder}/malachite-base", } }, { "label": "malachite-base-test-util: check", "type": "shell", "command": "cargo check --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-base-test-util" } }, { "label": "malachite-base-test-util: clippy", "type": "shell", "command": "cargo clippy --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-base-test-util" } }, { "label": "malachite-base-test-util: fmt", "type": "shell", "command": "cargo fmt", "options": { "cwd": "${workspaceFolder}/malachite-base-test-util" } }, { "label": "malachite-nz 32: check", "type": "shell", "command": "cargo check --all-targets --features 32_bit_limbs", "options": { "cwd": "${workspaceFolder}/malachite-nz" } }, { "label": "malachite-nz 32: clippy", "type": "shell", "command": "cargo clippy --all-targets --features 32_bit_limbs", "options": { "cwd": "${workspaceFolder}/malachite-nz" } }, { "label": "malachite-nz 64: check", "type": "shell", "command": "cargo check --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-nz" } }, { "label": "malachite-nz 64: clippy", "type": "shell", "command": "cargo clippy --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-nz" } }, { "label": "malachite-nz: fmt", "type": "shell", "command": "cargo fmt", "options": { "cwd": "${workspaceFolder}/malachite-nz" } }, { "label": "malachite-nz: doc", "type": "shell", "command": "cargo doc --no-deps", "options": { "cwd": "${workspaceFolder}/malachite-nz", "env": { "RUSTDOCFLAGS": "--html-in-header katex-header.html" } } }, { "label": "malachite-nz: open docs", "type": "shell", "command": "open target/doc/malachite_nz/index.html", "options": { "cwd": "${workspaceFolder}/malachite-nz", } }, { "label": "malachite-nz-test-util: check", "type": "shell", "command": "cargo check --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-nz-test-util" } }, { "label": "malachite-nz-test-util: clippy", "type": "shell", "command": "cargo clippy --all-targets", "options": { "cwd": "${workspaceFolder}/malachite-nz-test-util" } }, { "label": "malachite-nz-test-util: fmt", "type": "shell", "command": "cargo fmt", "options": { "cwd": "${workspaceFolder}/malachite-nz-test-util" } }, ] } ================================================ FILE: COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: COPYING.LESSER ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: Cargo.toml ================================================ [workspace] members = ['malachite', 'malachite-base', 'malachite-bigint', 'malachite-float', 'malachite-nz', 'malachite-q', 'malachite-criterion-bench'] resolver = "2" [workspace.package] edition = "2024" rust-version = "1.90.0" [workspace.dependencies] malachite-base = { version = "0.9.1", path = 'malachite-base', default-features = false } malachite-nz = { version = "0.9.1", path = 'malachite-nz', default-features = false } malachite-q = { version = "0.9.1", path = 'malachite-q', default-features = false } malachite-float = { version = "0.9.1", path = 'malachite-float', default-features = false } [profile.release] lto = "fat" strip = true codegen-units = 1 ================================================ FILE: LICENSE ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: README.md ================================================ Logo An arbitrary-precision arithmetic library for Rust. Parts of Malachite are derived from [GMP](https://gmplib.org/), [FLINT](https://www.flintlib.org/), and [MPFR](https://www.mpfr.org/). The documentation for Malachite is [here](https://docs.rs/malachite/latest/malachite/), and its crate is [here](https://crates.io/crates/malachite). Floats (arbitrary-precision floating-point numbers) are in development and are currently experimental. They are missing many important functions. However, the floating-point functions that *are* currently implemented are thoroughly tested and documented, with the exception of string conversion functions. The current floating-point string conversion functions are incomplete and will be changed in the future to match MPFR's behavior. Malachite is developed by Mikhail Hogrefe. Thanks to 43615, b4D8, coolreader18, Dasaav-dsv, Duncan Freeman, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, Kevin Phoenix, probablykasper, shekohex, skycloudd, John Vandenberg, Brandon Weeks, and Will Youmans for additional contributions. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: _config.yml ================================================ theme: jekyll-theme-cayman ================================================ FILE: additional-lints.py ================================================ import os MAX_LINE_LENGTH = 100 line_length_exceptions = set(( # long Markdown table rows and/or links ('./malachite-base/src/lib.rs', 65), ('./malachite-base/src/num/arithmetic/mod.rs', 339), ('./malachite-base/src/num/arithmetic/mod.rs', 340), ('./malachite-base/src/num/arithmetic/mod.rs', 1340), ('./malachite-base/src/num/arithmetic/mod.rs', 1580), ('./malachite-base/src/num/arithmetic/mod.rs', 1581), ('./malachite-base/src/num/arithmetic/mod.rs', 1582), ('./malachite-base/src/num/arithmetic/mod.rs', 1583), ('./malachite-base/src/num/arithmetic/primorial.rs', 85), ('./malachite-base/src/num/arithmetic/primorial.rs', 244), ('./malachite-base/src/num/arithmetic/round_to_multiple_of_power_of_2.rs', 118), ('./malachite-base/src/num/conversion/digits/power_of_2_digit_iterable.rs', 153), ('./malachite-base/src/num/conversion/digits/power_of_2_digit_iterable.rs', 155), ('./malachite-base/src/num/exhaustive/mod.rs', 1074), ('./malachite-float/src/conversion/mantissa_and_exponent.rs', 478), ('./malachite-float/src/conversion/mantissa_and_exponent.rs', 682), ('./malachite-float/src/conversion/mod.rs', 227), ('./malachite-float/src/lib.rs', 24), ('./malachite-nz/src/integer/arithmetic/mod.rs', 39), ('./malachite-nz/src/integer/arithmetic/mod.rs', 40), ('./malachite-nz/src/integer/arithmetic/mod.rs', 41), ('./malachite-nz/src/integer/arithmetic/mod.rs', 76), ('./malachite-nz/src/integer/arithmetic/mod.rs', 77), ('./malachite-nz/src/integer/arithmetic/mod.rs', 88), ('./malachite-nz/src/integer/arithmetic/mod.rs', 89), ('./malachite-nz/src/integer/arithmetic/mod.rs', 90), ('./malachite-nz/src/integer/arithmetic/mod.rs', 119), ('./malachite-nz/src/integer/arithmetic/mod.rs', 121), ('./malachite-nz/src/lib.rs', 36), ('./malachite-nz/src/lib.rs', 103), ('./malachite-nz/src/natural/arithmetic/mod.rs', 46), ('./malachite-nz/src/natural/arithmetic/mod.rs', 47), ('./malachite-nz/src/natural/arithmetic/mod.rs', 48), ('./malachite-nz/src/natural/arithmetic/mod.rs', 162), ('./malachite-nz/src/natural/arithmetic/mod.rs', 163), ('./malachite-nz/src/natural/arithmetic/mod.rs', 186), ('./malachite-nz/src/natural/arithmetic/mod.rs', 187), ('./malachite-nz/src/natural/arithmetic/mod.rs', 188), ('./malachite-nz/src/natural/arithmetic/mod.rs', 571), ('./malachite-nz/src/natural/arithmetic/mod.rs', 573), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 526), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 528), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 827), ('./malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs', 829), ('./malachite-nz/src/natural/conversion/mantissa_and_exponent.rs', 323), ('./malachite-nz/src/natural/conversion/mantissa_and_exponent.rs', 508), ('./malachite-nz/src/natural/conversion/mod.rs', 257), ('./malachite-q/src/arithmetic/mod.rs', 63), ('./malachite-q/src/arithmetic/mod.rs', 64), ('./malachite-q/src/arithmetic/mod.rs', 95), ('./malachite-q/src/arithmetic/mod.rs', 97), ('./malachite-q/src/conversion/string/from_sci_string.rs', 145), ('./malachite-q/src/conversion/string/from_sci_string.rs', 232), ('./malachite-q/src/lib.rs', 54), )) def lint(filename): i = 1 with open(filename) as f: for line in f.readlines(): line = line.rstrip() is_exception = (filename, i) in line_length_exceptions if is_exception: if len(line) <= MAX_LINE_LENGTH: raise ValueError(f'line not too long: {filename}: {i} {line}') elif len(line) > MAX_LINE_LENGTH: raise ValueError(f'line too long: {filename}: {i} {line}') i += 1 return i - 1 filename_list = [] for root, directories, filenames in os.walk('.'): for filename in filenames: filename = os.path.join(root, filename) if '/target/' not in filename and '.history' not in filename and filename.endswith('.rs'): filename_list.append(filename) filename_list.sort() line_count = 0 for filename in filename_list: line_count += lint(filename) print(f'{line_count} lines checked') ================================================ FILE: build.sh ================================================ #!/bin/bash echo "Step 1. Checking for updates" && rustup update && echo "Step 2. Updating headers" && cd ../fix-headers && cargo test --release && cd ../malachite/malachite-base && echo "Step 3. Formatting malachite-base" && bash ../superfmt.sh && echo "Step 4. Checking malachite-base lib" && cargo check --lib && echo "Step 5. Checking malachite-base lib with random" && cargo check --lib --features random && echo "Step 6. Checking all malachite-base targets with bin_build" && cargo check --all-targets --features bin_build && echo "Step 7. Checking malachite-base lib with no std" && cargo check --lib --no-default-features && echo "Step 8. Checking malachite-base lib with random and no std" && cargo check --lib --features random --no-default-features && echo "Step 9. Checking all malachite-base targets with bin_build and no std" && cargo check --all-targets --features bin_build --no-default-features && cd ../malachite-nz && echo "Step 10. Formatting malachite-nz" && bash ../superfmt.sh && echo "Step 11. Checking malachite-nz lib with 32_bit_limbs" && cargo check --lib --features 32_bit_limbs && echo "Step 12. Checking malachite-nz lib" && cargo check --lib && echo "Step 13. Checking malachite-nz lib with 32_bit_limbs and random" && cargo check --lib --features 32_bit_limbs --features random && echo "Step 14. Checking malachite-nz lib with random" && cargo check --lib --features random && echo "Step 15. Checking malachite-nz lib with 32_bit_limbs and serde" && cargo check --lib --features 32_bit_limbs --features enable_serde && echo "Step 16. Checking malachite-nz lib with serde" && cargo check --lib --features enable_serde && echo "Step 17. Checking malachite-nz lib with 32_bit_limbs, serde, and random" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random && echo "Step 18. Checking malachite-nz lib with serde and random" && cargo check --lib --features enable_serde --features random && echo "Step 19. Checking all malachite-nz targets with bin_build, 32_bit_limbs, and serde" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde && echo "Step 20. Checking all malachite-nz targets with bin_build and serde" && cargo check --all-targets --features bin_build --features enable_serde && echo "Step 21. Checking all malachite-nz targets with bin_build, 32_bit_limbs, serde, and random" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random && echo "Step 22. Checking all malachite-nz targets with bin_build, serde, and random" && cargo check --all-targets --features bin_build --features enable_serde --features random && echo "Step 23. Checking malachite-nz lib with 32_bit_limbs and no std" && cargo check --lib --features 32_bit_limbs --no-default-features && echo "Step 24. Checking malachite-nz lib with no std" && cargo check --lib --no-default-features && echo "Step 25. Checking malachite-nz lib with 32_bit_limbs and random and no std" && cargo check --lib --features 32_bit_limbs --features random --no-default-features && echo "Step 26. Checking malachite-nz lib with random and no std" && cargo check --lib --features random --no-default-features && echo "Step 27. Checking malachite-nz lib with 32_bit_limbs and serde and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 28. Checking malachite-nz lib with serde and no std" && cargo check --lib --features enable_serde --no-default-features && echo "Step 29. Checking malachite-nz lib with 32_bit_limbs, serde, and random and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 30. Checking malachite-nz lib with serde and random and no std" && cargo check --lib --features enable_serde --features random --no-default-features && echo "Step 31. Checking all malachite-nz targets with bin_build, 32_bit_limbs, and serde and no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 32. Checking all malachite-nz targets with bin_build and serde and no std" && cargo check --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 33. Checking all malachite-nz targets with bin_build, 32_bit_limbs, serde, and random and no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 34. Checking all malachite-nz targets with bin_build, serde, and random and no std" && cargo check --all-targets --features bin_build --features enable_serde --features random --no-default-features && cd ../malachite-q && echo "Step 35. Formatting malachite-q" && bash ../superfmt.sh && echo "Step 36. Checking malachite-q lib with 32_bit_limbs" && cargo check --lib --features 32_bit_limbs && echo "Step 37. Checking malachite-q lib" && cargo check --lib && echo "Step 38. Checking malachite-q lib with 32_bit_limbs and random" && cargo check --lib --features 32_bit_limbs --features random && echo "Step 39. Checking malachite-q lib with random" && cargo check --lib --features random && echo "Step 40. Checking malachite-q lib with 32_bit_limbs and serde" && cargo check --lib --features 32_bit_limbs --features enable_serde && echo "Step 41. Checking malachite-q lib with serde" && cargo check --lib --features enable_serde && echo "Step 42. Checking malachite-q lib with 32_bit_limbs, serde, and random" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random && echo "Step 43. Checking malachite-q lib with serde and random" && cargo check --lib --features enable_serde --features random && echo "Step 44. Checking all malachite-q targets with bin_build, 32_bit_limbs, and serde" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde && echo "Step 45. Checking all malachite-q targets with bin_build and serde" && cargo check --all-targets --features bin_build --features enable_serde && echo "Step 46. Checking all malachite-q targets with bin_build, 32_bit_limbs, serde, and random" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random && echo "Step 47. Checking all malachite-q targets with bin_build, serde, and random" && cargo check --all-targets --features bin_build --features enable_serde --features random && echo "Step 48. Checking malachite-q lib with 32_bit_limbs and no std" && cargo check --lib --features 32_bit_limbs --no-default-features && echo "Step 49. Checking malachite-q lib with no std" && cargo check --lib --no-default-features && echo "Step 50. Checking malachite-q lib with 32_bit_limbs and random and no std" && cargo check --lib --features 32_bit_limbs --features random --no-default-features && echo "Step 51. Checking malachite-q lib with random and no std" && cargo check --lib --features random --no-default-features && echo "Step 52. Checking malachite-q lib with 32_bit_limbs and serde and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 53. Checking malachite-q lib with serde and no std" && cargo check --lib --features enable_serde --no-default-features && echo "Step 54. Checking malachite-q lib with 32_bit_limbs, serde, and random and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 55. Checking malachite-q lib with serde and random and no std" && cargo check --lib --features enable_serde --features random --no-default-features && echo "Step 56. Checking all malachite-q targets with bin_build, 32_bit_limbs, and serde and no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 57. Checking all malachite-q targets with bin_build and serde and no std" && cargo check --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 58. Checking all malachite-q targets with bin_build, 32_bit_limbs, serde, and random and no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 59. Checking all malachite-q targets with bin_build, serde, and random and no std" && cargo check --all-targets --features bin_build --features enable_serde --features random --no-default-features && cd ../malachite-float && echo "Step 60. Formatting malachite-float" && bash ../superfmt.sh && echo "Step 61. Checking malachite-float lib with 32_bit_limbs" && cargo check --lib --features 32_bit_limbs && echo "Step 62. Checking malachite-float lib" && cargo check --lib && echo "Step 63. Checking malachite-float lib with 32_bit_limbs and random" && cargo check --lib --features 32_bit_limbs --features random && echo "Step 64. Checking malachite-float lib with random" && cargo check --lib --features random && echo "Step 65. Checking malachite-float lib with 32_bit_limbs and serde" && cargo check --lib --features 32_bit_limbs --features enable_serde && echo "Step 66. Checking malachite-float lib with serde" && cargo check --lib --features enable_serde && echo "Step 67. Checking malachite-float lib with 32_bit_limbs, serde, and random" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random && echo "Step 68. Checking malachite-float lib with serde and random" && cargo check --lib --features enable_serde --features random && echo "Step 69. Checking all malachite-float targets with bin_build, 32_bit_limbs, and serde" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde && echo "Step 70. Checking all malachite-float targets with bin_build and serde" && cargo check --all-targets --features bin_build --features enable_serde && echo "Step 71. Checking all malachite-float targets with bin_build, 32_bit_limbs, serde, and random" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random && echo "Step 72. Checking all malachite-float targets with bin_build, serde, and random" && cargo check --all-targets --features bin_build --features enable_serde --features random && echo "Step 73. Checking malachite-float lib with 32_bit_limbs and no std" && cargo check --lib --features 32_bit_limbs --no-default-features && echo "Step 74. Checking malachite-float lib with no std" && cargo check --lib --no-default-features && echo "Step 75. Checking malachite-float lib with 32_bit_limbs and random and no std" && cargo check --lib --features 32_bit_limbs --features random --no-default-features && echo "Step 76. Checking malachite-float lib with random and no std" && cargo check --lib --features random --no-default-features && echo "Step 77. Checking malachite-float lib with 32_bit_limbs and serde and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 78. Checking malachite-float lib with serde and no std" && cargo check --lib --features enable_serde --no-default-features && echo "Step 79. Checking malachite-float lib with 32_bit_limbs, serde, and random and no std" && cargo check --lib --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 80. Checking malachite-float lib with serde and random and no std" && cargo check --lib --features enable_serde --features random --no-default-features && echo "Step 81. Checking all malachite-float targets with bin_build, 32_bit_limbs, and serde no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 82. Checking all malachite-float targets with bin_build and serde and no std" && cargo check --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 83. Checking all malachite-float targets with bin_build, 32_bit_limbs, serde, and random and no std" && cargo check --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --features random --no-default-features && echo "Step 84. Checking all malachite-float targets with bin_build, serde, and random and no std" && cargo check --all-targets --features bin_build --features enable_serde --features random --no-default-features && cd ../malachite-criterion-bench && echo "Step 85. Formatting malachite-criterion-bench" && bash ../superfmt.sh && echo "Step 86. Checking malachite-criterion-bench" && cargo check && cd ../malachite-bigint && echo "Step 87. Formatting malachite-bigint" && bash ../superfmt.sh && echo "Step 88. Checking all malachite-bigint targets" && cargo check --all-targets && echo "Step 89. Checking all malachite-bigint targets with no std" && cargo check --all-targets --no-default-features && echo "Step 90. Checking the malachite meta-crate" && cd ../malachite && cargo check --all-targets && echo "Step 91. Checking the malachite meta-crate with serde" && cargo check --all-targets --features enable_serde && cd .. && echo "Step 92. Running additional-lints" && python3 additional-lints.py && cd malachite-base && echo "Step 93. Updating malachite-base" && cargo update && echo "Step 94. Formatting malachite-base" && bash ../superfmt.sh && echo "Step 95. Running clippy on malachite-base" && cargo clippy --all-targets --features bin_build && echo "Step 96. Running clippy on malachite-base with no std" && cargo clippy --all-targets --features bin_build --no-default-features && echo "Step 97. Testing malachite-base" && cargo test --release --tests --features bin_build && echo "Step 98. Testing malachite-base with no std" && cargo test --release --tests --features bin_build --no-default-features && echo "Step 99. Testing malachite-base doctests" && bash ../rundoc.sh --features test_build && echo "Step 100. Testing malachite-base doctests with random" && bash ../rundoc.sh --features test_build --features random && echo "Step 101. Documenting malachite-base" && RUSTDOCFLAGS="--html-in-header katex-header.html" cargo doc --lib --no-deps --features random && echo "Step 102. Building malachite-base lib for wasm" && cargo build --lib --release --target wasm32-unknown-unknown && cd ../malachite-nz && echo "Step 103. Updating malachite-nz" && cargo update && echo "Step 104. Formatting malachite-nz" && bash ../superfmt.sh && echo "Step 105. Running clippy on malachite-nz" && cargo clippy --all-targets --features bin_build --features enable_serde && echo "Step 106. Running clippy on malachite-nz with 32_bit_limbs" && cargo clippy --all-targets --features bin_build --features 32_bit_limbs --features enable_serde && echo "Step 107. Running clippy on malachite-nz with no std" && cargo clippy --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 108. Running clippy on malachite-nz with 32_bit_limbs and no std" && cargo clippy --all-targets --features bin_build --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 109. Testing malachite-nz" && cargo test --release --tests --features test_build --features enable_serde && echo "Step 110. Testing malachite-nz with no std" && cargo test --release --tests --features test_build --features enable_serde --no-default-features && echo "Step 111. Testing malachite-nz doctests" && bash ../rundoc.sh --features test_build && echo "Step 112. Testing malachite-nz with 32_bit_limbs" && cargo test --release --tests --features test_build --features 32_bit_limbs --features enable_serde && echo "Step 113. Testing malachite-nz with 32_bit_limbs and no std" && cargo test --release --tests --features test_build --features 32_bit_limbs --features enable_serde --no-default-features && echo "Step 114. Testing malachite-nz doctests with 32_bit_limbs" && bash ../rundoc.sh --features test_build --features 32_bit_limbs&& echo "Step 115. Testing malachite-nz doctests with 32_bit_limbs and random" && bash ../rundoc.sh --features test_build --features 32_bit_limbs --features random && echo "Step 116. Running extra tests for malachite-nz" && python3 extra-tests.py && echo "Step 117. Documenting malachite-nz" && RUSTDOCFLAGS="--html-in-header katex-header.html" cargo doc --lib --no-deps --features doc-images --features random && echo "Step 118. Building malachite-nz lib for wasm with 32_bit_limbs" && cargo build --lib --release --features 32_bit_limbs --target wasm32-unknown-unknown && echo "Step 119. Building malachite-nz lib for wasm" && cargo build --lib --release --target wasm32-unknown-unknown && cd ../malachite-q && echo "Step 120. Updating malachite-q" && cargo update && echo "Step 121. Formatting malachite-q" && bash ../superfmt.sh && echo "Step 122. Running clippy on malachite-q" && cargo clippy --all-targets --features bin_build --features enable_serde && echo "Step 123. Running clippy on malachite-q with 32_bit_limbs" && cargo clippy --all-targets --features bin_build --features enable_serde --features 32_bit_limbs && echo "Step 124. Running clippy on malachite-q with no std" && cargo clippy --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 125. Running clippy on malachite-q with 32_bit_limbs and no std" && cargo clippy --all-targets --features bin_build --features enable_serde --features 32_bit_limbs --no-default-features && echo "Step 126. Testing malachite-q" && cargo test --release --tests --features bin_build --features enable_serde && echo "Step 127. Testing malachite-q with no std" && cargo test --release --tests --features bin_build --features enable_serde --no-default-features && echo "Step 128. Testing malachite-q doctests" && bash ../rundoc.sh --features test_build && echo "Step 129. Testing malachite-q with 32_bit_limbs" && cargo test --release --tests --features bin_build --features enable_serde --features 32_bit_limbs && echo "Step 130. Testing malachite-q with 32_bit_limbs and no std" && cargo test --release --tests --features bin_build --features enable_serde --features 32_bit_limbs --no-default-features && echo "Step 131. Testing malachite-q doctests with 32_bit_limbs" && bash ../rundoc.sh --features test_build --features 32_bit_limbs && echo "Step 132. Testing malachite-q doctests with random" && bash ../rundoc.sh --features test_build --features random && echo "Step 133. Testing malachite-q doctests with random and 32_bit_limbs" && bash ../rundoc.sh --features test_build --features random --features 32_bit_limbs && echo "Step 134. Documenting malachite-q" && RUSTDOCFLAGS="--html-in-header katex-header.html" cargo doc --lib --no-deps --features random && echo "Step 135. Building malachite-q lib for wasm" && cargo build --lib --release --target wasm32-unknown-unknown && echo "Step 136. Building malachite-q lib for wasm with 32_bit_limbs" && cargo build --lib --release --features 32_bit_limbs --target wasm32-unknown-unknown && cd ../malachite-float && echo "Step 137. Updating malachite-float" && cargo update && echo "Step 138. Formatting malachite-float" && bash ../superfmt.sh && echo "Step 139. Running clippy on malachite-float" && cargo clippy --all-targets --features bin_build --features enable_serde && echo "Step 140. Running clippy on malachite-float with 32_bit_limbs" && cargo clippy --all-targets --features bin_build --features enable_serde --features 32_bit_limbs && echo "Step 141. Running clippy on malachite-float with no std" && cargo clippy --all-targets --features bin_build --features enable_serde --no-default-features && echo "Step 142. Running clippy on malachite-float with 32_bit_limbs and no std" && cargo clippy --all-targets --features bin_build --features enable_serde --features 32_bit_limbs --no-default-features && echo "Step 143. Testing malachite-float" && cargo test --release --tests --features bin_build --features enable_serde && echo "Step 144. Testing malachite-float with no std" && cargo test --release --tests --features bin_build --features enable_serde --no-default-features && echo "Step 145. Testing malachite-float doctests" && bash ../rundoc.sh --features test_build && echo "Step 146. Testing malachite-float with 32_bit_limbs" && cargo test --release --tests --features bin_build --features 32_bit_limbs && echo "Step 147. Testing malachite-float with 32_bit_limbs and no std" && cargo test --release --tests --features bin_build --features 32_bit_limbs --no-default-features && echo "Step 148. Testing malachite-float doctests with 32_bit_limbs" && bash ../rundoc.sh --features test_build --features 32_bit_limbs && echo "Step 149. Testing malachite-float doctests with random" && bash ../rundoc.sh --features test_build --features random && echo "Step 150. Testing malachite-float doctests with random and 32_bit_limbs" && bash ../rundoc.sh --features test_build --features random --features 32_bit_limbs && echo "Step 151. Documenting malachite-float" && RUSTDOCFLAGS="--html-in-header katex-header.html" cargo doc --lib --no-deps --features random && echo "Step 152. Building malachite-float lib for wasm" && cargo build --lib --release --target wasm32-unknown-unknown && echo "Step 153. Building malachite-float lib for wasm with 32_bit_limbs" && cargo build --lib --release --features 32_bit_limbs --target wasm32-unknown-unknown && cd ../malachite-bigint && echo "Step 154. Updating malachite-bigint" && cargo update && echo "Step 155. Formatting malachite-bigint" && bash ../superfmt.sh && echo "Step 156. Running clippy on malachite-bigint" && cargo clippy --all-targets && echo "Step 157. Running clippy on malachite-bigint with no std" && cargo clippy --all-targets --no-default-features && echo "Step 158. Testing malachite-bigint" && cargo test --release && echo "Step 159. Testing malachite-bigint with no std" && cargo test --release --no-default-features && echo "Step 160. Documenting malachite-bigint" && cargo doc --lib --no-deps && echo "Step 161. Building malachite-bigint lib for wasm" && cargo build --lib --release --target wasm32-unknown-unknown && cd ../malachite && echo "Step 162. Documenting malachite" && RUSTDOCFLAGS="--html-in-header katex-header.html" cargo doc --lib --no-deps --features random && cd ../malachite-criterion-bench && echo "Step 163. Updating malachite-criterion-bench" && cargo update && echo "Step 164. Formatting malachite-criterion-bench" && bash ../superfmt.sh && cd .. && echo "Step 165. Running additional-lints" && python3 additional-lints.py && echo "Step 166. Testing against FLINT" && cd ../malachite-cpp-test/malachite-test-cpp && cargo run --release && echo "Step 167. Checking links" && cd ../../check-malachite-links && cargo run --release ================================================ FILE: docs/CNAME ================================================ www.malachite.rs ================================================ FILE: docs/_config.yml ================================================ theme: jekyll-theme-slate ================================================ FILE: docs/_includes/head-custom.html ================================================ ================================================ FILE: docs/_layouts/post.html ================================================ --- layout: default theme: jekyll-theme-slate ---

{{ page.title }}

{{ page.date | date_to_string }} — {{ page.author }}

{{ content }}
Copyright © 2026 Mikhail Hogrefe ================================================ FILE: docs/_posts/2022-06-05-1-intro.md ================================================ --- layout: post title: Intro author: Mikhail Hogrefe --- Welcome to the Malachite blog! After 5 years and over 600,000 lines of code, I'm finally releasing Malachite, a high-performance arbitrary-precison arithmetic library for Rust. There's a lot of stuff in this library, and while it's well-documented on docs.rs, I think it's a good idea to publish some long-form explanations of what it can do and what the ideas behind it are. ================================================ FILE: docs/_posts/2022-06-05-2-exhaustive.md ================================================ --- layout: post title: Iterators that generate everything, part 1 author: Mikhail Hogrefe --- ## Iterators If you've ever used a modern programming language, you're probably familiar with iterators. For example, if you've got a `Vec` called `xs` in Rust, you can write this: ```rust for x in &xs { println!("{}", x); } ``` This code takes `xs` and produces an iterator, a thing that knows how to spit out elements. Iterators are very flexible: you can filter them, map them, zip them, and collect them into concrete collections like `Vec`s or sets. In Haskell, the basic aggregate type, `List`, _is_ an iterator. Iterators are also very general. An iterator doesn't have to be backed by anything in memory. You can easily write this: ```rust for x: u16 in 0..10 { println!("{}", x); } ``` or even ```rust for x: u16 in 0.. { println!("{}", x); } ``` There's something compelling about an iterator that generates EVERY `u16`. If you were testing a function that takes a `u16`, you could test it on every possible input! If we were dealing with with `u64`s instead, you'd want to cut it off after some number of values using `take`. # Some simple examples The `malachite_base` crate provides lots of exhaustive iterators. Let me show you: ```rust for b in exhaustive_bools() { println!("{}", b); } ``` ``` false true ``` I mentioned `0..` earlier. Malachite provides an iterator that does the same thing but more explicitly: ```rust for u in exhaustive_unsigneds::().take(10) { println!("{}", u); } ``` ``` 0 1 2 3 4 5 6 7 8 9 ``` Ok, this isn't very interesting so far. How about signed integers? ```rust for u in exhaustive_signeds::().take(10) { println!("{}", u); } ``` ``` 0 1 -1 2 -2 3 -3 4 -4 5 ``` The philosophy behind exhaustive iterators in Malachite is that simpler values should come first. That's why the `i16`s are sorted by absolute value rather than by their usual order. If you _do_ want to start at -65536 and go up from there, you can use `primitive_int_increasing_inclusive_range(i16::MIN, i16::MAX)` instead. By the way, there are lots of other iterators I'm skipping over, like `exhaustive_nonzero_integers`. You can find them by going [here](https://docs.rs/malachite-base/latest/malachite_base/all.html) and Ctrl-F'ing "exhaustive". How about `char`s? ```rust for c in exhaustive_chars().take(10) { println!("{}", c); } ``` ``` a b c d e f g h i j ``` Again, these are not in their usual order. Thanks to various historical circumstances, the `char`s that are usually ordered first are mostly unprintable useless characters like "vertical tab" and "unit separator". `exhaustive_chars` pushes these to the back of the line; see its [documentation](https://docs.rs/malachite-base/latest/malachite_base/chars/exhaustive/fn.exhaustive_chars.html) for details. ## Combining iterators We've touched on most of Rust's primitive types, except for floats; those are more complicated and I'll discuss them later. But now, let's see how to create iterators for composite types, like `Option`: ```rust for ox in exhaustive_options(exhaustive_signeds::()).take(10) { println!("{:?}", ox); } ``` ``` None Some(0) Some(1) Some(-1) Some(2) Some(-2) Some(3) Some(-3) Some(4) Some(-4) ``` Reasonable. Next, I want to talk about `Union`s. These don't exist in the standard library, so I've defined them in Malachite. (Since variadic generics aren't a thing in Rust yet, what I've _actually_ defined are `Union2`s and a macro to define unions of higher arity.) A union (specifically a tagged union, also called a variant or a sum type) is essentially a generic enum. For example, a value of type `Union2` might be `Union2::A(12)` or `Union2::B('d')`. It's usually better to use a purpose-built enum than a union, but it's very handy to have exhaustive iterators for unions. If you want to create an exhaustive iterator for a 2-variant enum, you can just do `exhaustive_union2s(...).map(|u| match u { ... })`. Actually, before `exhaustive_union2s`, let me show you `lex_union2s`: ```rust for b_or_u in lex_union2s(exhaustive_bools(), 1..=3) { println!("{}", b_or_u); } ``` ``` A(false) A(true) B(1) B(2) B(3) ``` It's very simple; it just produces all the values of the first variant, then all the values of the second variant. I've called it `lex` because it returns its elements in lexicographic, or "dictionary", order (with respect to the order of the input iterators' elements). It's only suitable when the first iterator is short. You don't want to use `lex_union2s(exhaustive_unsigneds::(), ...)` because you'll be waiting forever before you see the second variant. In general, `exhaustive_union2s` is the better choice: ```rust for u_or_b in exhaustive_union2s( exhaustive_unsigneds::(), exhaustive_bools() ).take(10) { println!("{}", u_or_b); } ``` ``` A(0), B(false), A(1), B(true), A(2), A(3), A(4), A(5), A(6), A(7), ``` and now the `B` variant gets to see the light of day. `exhaustive_union3s`, etc., work in the same way, selecting between their variants in a round-robin fashion. # Intermission We haven't gotten to the really interesting bits, which have to do with generating tuples (and after that, lists, sets, and floats). I'll talk about those in future posts. [Part 2: Generating tuples](/2022/07/03/exhaustive) ================================================ FILE: docs/_posts/2022-07-03-exhaustive.md ================================================ --- layout: post title: Iterators that generate everything, part 2 author: Mikhail Hogrefe --- ## Introduction In [Part 1](/2022/06/05/2-exhaustive) of this series, I described how Malachite provides iterators that generate all values of a type, or all values satisfying some condition. Now I'm going to show you how to generate tuples. It's not immediately obvious how to do this. One thing you might try is generating the tuples in lexicographic order. Malachite lets you do this: ```rust for p in lex_pairs_from_single(exhaustive_unsigneds::()).take(10) { println!("{}", p); } ``` ``` (0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) ``` (The "from_single" in [`lex_pairs_from_single`](https://docs.rs/malachite-base/latest/malachite_base/tuples/exhaustive/fn.lex_pairs_from_single.html) indicates that both elements of the output pairs come from the same iterator. There's also a [`lex_pairs`](https://docs.rs/malachite-base/latest/malachite_base/tuples/exhaustive/fn.lex_pairs.html) function that accepts two iterators.) As you can see, lexicographic generation only makes sense if the input iterator has a small number of elements, like `exhaustive_bools`. It doesn't work so well for `exhaustive_unsigneds::`, since you'd have to wait forever to get to any pair that doesn't start with 0. But Malachite does provide [`exhaustive_pairs`](https://docs.rs/malachite-base/latest/malachite_base/tuples/exhaustive/fn.exhaustive_pairs.html) and [`exhaustive_pairs_from_single`](https://docs.rs/malachite-base/latest/malachite_base/tuples/exhaustive/fn.exhaustive_pairs_from_single.html), that work well for any input iterators. How do these functions work? ## First attempt: the Cantor pairing function For simplicity, let's first consider `exhaustive_pairs_from_single(exhaustive_naturals())`. To think about generating every pair of `Natural`s, it helps to visualize a path through an infinite grid. One such path is this:

The path defined by the Cantor pairing function

You can think of it as first generating (0, 0), whose sum is 0; then (1, 0) and (0, 1), whose sum is 1; then (2, 0), (1, 1), and (0, 2), whose sum is 2; and so on. This path describes a bijection between the indices 0, 1, 2, ..., and all pairs of natural numbers. The opposite direction of this bijection, that takes pairs to indices, is known as the Cantor pairing function. This bijection has some nice properties; for example, the function from pairs to indices is a polynomial in the elements of the pair: the pair $$(x, y)$$ corresponds to index $$\tfrac{1}{2}(x + y)(x + y + 1)$$. We can also look at the two functions from sequence index to the first and second elements of the pairs. These functions look like this:

The inverses of the Cantor pairing function

Although the functions jump around a lot (they have to, since they must evaluate to every natural number infinitely many times), there's a sense in which they are nicely balanced. Both are $$O(\sqrt n)$$, and if you take evaluate them at a random large input, they're generally about the same size:

The Cantor unpairing of powers of 3

However, it isn't obvious how generalize the Cantor pairing function to triples in a balanced way. The standard way to create a tripling function from a pairing function is $$g(x, y, z) = f(x, f(y, z))$$, but this is no longer balanced. If $$f$$ is the Cantor pairing function, then the three outputs of $$g^{-1}$$ are $$O(\sqrt n)$$, $$O(\sqrt[4] n)$$, and $$O(\sqrt[4]n)$$. Here's what the corresponding table looks like:

An unbalanced Cantor untripling of powers of 3

## More balance and flexibility with bit interleaving Instead of the Cantor pairing function, Malachite uses bit interleaving. This idea is not new; it has been described by [Steven Pigeon](https://hbfs.wordpress.com/2011/09/27/pairing-functions/) and others. To generate the pairs corresponding to index 0, 1, 2, and so on, first write the indices in binary, with infinitely many leading zeros:

First step in un-interleaving bits

And then distribute the bits of each index into the two slots of the corresponding pair. The even-indexed bits (counting from the right) end up in the second slot, and the odd-indexed bits in the first:

Final steps in un-interleaving bits

I've color-coded the bits according to which slot they end up in. Malachite keeps track of this using an explicit bit map that looks like $$[1, 0, 1, 0, 1, 0, \ldots]$$, indicating that bit 0 goes to slot 1, bit 1 goes to slot 0, bit 2 goes to slot 1, and so on. This is how this method walks through the grid of pairs of natural numbers:

The path defined by the bit-interleaving pairing function

This path is called a [Z-order curve](https://en.wikipedia.org/wiki/Z-order_curve), although with this choice of coordinates it looks like it's made up of N's rather than Z's. And here's what the functions from the index to the first and second elements of the pairs look like:

The inverses of the bit interleaving pairing function

Like the inverses of the Cantor pairing function, these functions are balanced in the sense that both are $$O(\sqrt n)$$, although here the first element lags noticeably behind the second. And here's a table showing them evaluated at large indices:

Bit un-interleaving of powers of 3

The advantage that this approach has over the Cantor pairing approach is flexibility. We can generate triples in a balanced way simply by changing the bit map to $$[2, 1, 0, 2, 1, 0, 2, 1, 0, \ldots]$$:

un-interleaving bits to form triples

Here are the three functions from index to output. They each are $$O(\sqrt[3]n)$$.

The inverses of the bit interleaving tripling function

Here they are evaluated at large indices:

Bit un-interleaving of powers of 3 to form triples

This generalizes straightforwardly to $$k$$-tuples for any $$k$$. Notice that the first $$2^{ka}$$ tuples are all the tuples with elements less than $$2^a$$. ## Customized balancing By changing the bit map further, we can deliberately unbalance the tuples. For example, if we want to produce pairs where the second element of the pair is $$O(\sqrt[3]n)$$ and the first element is $$O(n^{2/3})$$, we can use the bit map $$[1, 0, 0, 1, 0, 0, 1, 0, 0, \ldots]$$. If we want the the first element to be exponentially larger than the second, we can use $$[0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, \ldots]$$, where there is a 1 at the $$2^i$$th position and 0 elsewhere. To actually generate the pair sequences in the two preceding examples, you can use ```rust exhaustive_pairs_custom_output( exhaustive_naturals(), exhaustive_naturals(), BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(1), ) ``` and ```rust exhaustive_pairs_custom_output( exhaustive_naturals(), exhaustive_naturals(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) ``` respectively. See the documentation of [exhaustive_pairs_custom_output](https://docs.rs/malachite-base/0.2.4/malachite_base/tuples/exhaustive/fn.exhaustive_pairs_custom_output.html) and [BitDistributorOutputType](https://docs.rs/malachite-base/latest/malachite_base/iterators/bit_distributor/struct.BitDistributorOutputType.html) for more details. ## Generating tuples of other iterators So far I've only talked about generating tuples of `Natural`s. What about tuples of elements from some other iterator `xs`? If `xs` is infinitely long, then the process is straightforward. Instead of generating, say, (8, 3), generate the pair consisting of the 8th and 3rd elements of `xs` (indexing from 0, of course). Internally, Malachite uses a structure called [`IteratorCache`](https://docs.rs/malachite-base/latest/malachite_base/iterators/iterator_cache/struct.IteratorCache.html), which stores the values produced by `xs` into a `Vec` for easy access. For example, here's how to generate all pairs of the characters `'a'` to `'z'` (in this case, there are additional complications due to `xs` being finite, but we'll address those in a moment): ```rust for p in exhaustive_pairs_from_single('a'..='z').take(10) { println!("{:?}", p); } ``` ``` (a, a) (a, b) (b, a) (b, b) (a, c) (a, d) (b, c) (b, d) (c, a) (c, b) ``` ## Dealing with finite iterators Finite iterators are a bit of a problem. You can't generate the (8th, 3rd) pair if the input iterator has no 8th element. To take an extreme case, consider `exhaustive_pairs(exhaustive_naturals(), exhaustive_bools())`. There are only two bools, so any index pair $$(i, j)$$ where $$j \geq 2$$ can't be used for indexing. Here's our grid of indices again, with valid indices green and invalid indices red:

Valid indices when one iterator has length 2

My original solution was just to skip over the invalid indices, with a bit of extra logic to determine when both input iterators are finished. This was very slow: out of the first $$n$$ pairs, only about $$2 \sqrt n$$ are valid, and the situation gets worse for higher-arity tuples. So what does `exhaustive_pairs` do instead? Again, we can leverage the bit map! This scenario is actually what led me to make the bit map an explicit object in memory. What `exhaustive_pairs` does is notice when one of its iterators has completed, and then adjusts the bit map on the fly. In this particular case, it realizes that since `exhaustive_bools` produces two elements, it only needs a single bit for indexing; and then bit map is modified from $$[1, 0, 1, 0, 1, 0, 1, 0, \ldots]$$, to $$[1, 0, 0, 0, 0, 0, 0, \ldots]$$. In general, modifying the bit map on the fly is dangerous because you might end up repeating some output that you've already produced, but `exhaustive_pairs` only modifies the part of the map that hasn't been used yet. If the finite iterator's length is a power of 2, as it was in this example, then updating the bit map results in all indices being valid. If it isn't a power of 2, then some indices will remain invalid; for example, in `exhaustive_pairs(exhaustive_naturals(), 0..6)` the bit map will be updated from $$[1, 0, 1, 0, 1, 0, 1, 0, \ldots]$$, to $$[1, 0, 1, 0, 1, 0, 0, 0, \ldots]$$, so that the index of the second pair slot will vary from 0 to 7, and only $$3/4$$ of all the indices will be valid. But this is a constant proportion; it's much better than the earlier example where only $$(2 \sqrt n)/n$$ were valid. (In this particular case, the best thing to do would be to use `lex_pairs(exhaustive_naturals(), exhaustive_bools())`, which would produce (0, false), (0, true), (1, false), (1, true), and so on. But in general, when you call `exhaustive_pairs(xs, ys)` you might not know ahead of time whether `ys` is short, long, or infinite.) In the next part, I will discuss how Malachite generates all `Vec`s containing elements from some iterator. ================================================ FILE: docs/_posts/2022-07-30-denominators.md ================================================ --- layout: post title: Which denominators does an interval contain? author: Mikhail Hogrefe --- ## Introduction In this post I'm going to talk a bit about a problem that came up when I was figuring out how to generate rational numbers exhaustively. Malachite generates all positive rationals using the [Calkin-Wilf sequence](https://en.wikipedia.org/wiki/Calkin%E2%80%93Wilf_tree#Breadth_first_traversal): 1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, 5/3, 3/4, 4, 1/5, 5/4, 4/7, 7/3, 3/8, ..., and by manipulating this sequence a bit it can also generate all rationals, all negative rationals, and so on. How about generating all rationals in a specified interval? This has many uses: for example, when testing conversion from rationals to floats, we might want to generate rationals that fall into the 64-bit subnormal float range. For the remainder of this post I'm going to consider closed intervals only. ## First try The most straightforward approach is this: 1. Generate all rationals in $$[0, 1]$$. 2. Scale those rationals to bring them into the target interval. Step 1 is easy: we can generate 0 and 1, and then select every other rational from the above sequence: 0, 1, 1/2, 1/3, 2/3, 1/4, 3/5, 2/5, 3/4, 1/5, 4/7, 3/8, 5/7, 2/7, 5/8, 3/7, 4/5, 1/6, 5/9, 4/11, ... . Step 2 is also easy. If our target interval is $$[a, b]$$, we transform each rational using $$x \to (b - a)x + a$$. For example, here are the rationals in $$[1/3, 1/2]$$: 1/3, 1/2, 5/12, 7/18, 4/9, 3/8, 13/30, 2/5, 11/24, 11/30, 3/7, 19/48, 19/42, 8/21, 7/16, 17/42, 7/15, 13/36, 23/54, 13/33, ... . For a simple interval this approach works fine. But what if we generate intervals in $$[268876667/98914198, 245850922/78256779]$$? The endpoints of this interval are the simplest rationals that round to the best 64-bit float representations of $$e$$ and $$\pi$$, respectively. Our algorithm gives us 268876667/98914198, 245850922/78256779, 45359568684866149/15481413065696484, 33200495296270871/11611059799272363, 69677715462056705/23222119598544726, 87442412500217335/30962826131392968, 19172880691153809/6450588777373535, 111760559277407891/38703532664241210, 31331954079749087/10320942043797656, 54241917203946464/19351766332120605, ... . This is not so nice. Our interval contains nice rationals like 3, 11/4, 14/5, and 17/6, but they are nowhere to be seen (they will appear eventually, but much later in the sequence). We want an algorithm that gives preferential treatment to rationals with small denominators. Here's what Malachite does: An improved algorithm --------------------- Malachite's algorithm needs to be able to do three things: 1. Determine which denominators occur in an interval; 2. Generate all rationals with a given denominator in an interval; 3. Given infinitely many iterators, each generating rationals with different denominators, interleave the iterators into a single iterator. Number 2 is easy to do and not very interesting. You can see the details [here](https://docs.rs/malachite-q/latest/malachite_q/exhaustive/fn.exhaustive_rationals_with_denominator_inclusive_range.html). Number 3 is more interesting, but already solved. I'll post about it in the future, but for now I'll just leave a link to the relevant function [here](https://docs.rs/malachite-base/latest/malachite_base/tuples/exhaustive/fn.exhaustive_dependent_pairs.html). That leaves number 1. ## Finding all denominators in an interval Let's define the problem more explicitly. **Problem:** Given a closed interval $$[a, b]$$ with $$a, b \in \mathbb{Q}$$ and $$a < b$$, for which $$d \in \N^+$$ does there exist an $$n \in \Z$$ with $$\gcd(n, d) = 1$$ and $$n/d \in [a, b]$$? The simplest algorithm is to consider each denominator 1, 2, 3, ... in turn and determine whether some rational with the denominator exists in the interval. This works fine unless the diameter $$b - a$$ is very small. If the interval is $$[0, 2^{-100}]$$, it would take a very long time to find an admissible denominator greater than 1. Luckily, Malachite knows how to find the simplest rational in an interval ("simplest" meaning "having the lowest denominator"). It uses the continued fractions of the endpoints and follows the algorithm sketched out [here](https://en.wikipedia.org/wiki/Continued_fraction#Best_rational_approximations). This gives us the lowest denominator in the interval in $$O(n^2 \log n \log\log n)$$ time, $$n$$ being the maximum bit-length of the numerators and denominators of both endpoints. Once we've found the lowest denominator, we can find the $$m$$ rationals with that denominator in $$[a, b]$$ and then partition $$[a, b]$$ into $$m + 1$$ smaller intervals. Then we can repeat the process to get the second-lowest denominator, and so on. This algorithm is efficient enough to be useful, but it's still a bit cumbersome. Our intuition suggests that $$[a, b]$$ contains every denominator in $$\N^+$$ except for finitely many exceptions: in other words, that for every interval $$[a, b]$$ there exists a threshold $$D$$ such that for all $$d \geq D$$, $$[a, b]$$ contains a rational with denominator $$d$$. If we knew what $$D$$ was, then we could find start finding denominators using our cumbersome continued-fraction method, but once we reached $$D$$ we could simply generate $$D, D + 1, D + 2, \ldots$$ forever. For the remainder of this post, I'll prove that a $$D$$ exists for any interval and give an efficient algorithm for finding it (though it generally won't be the lowest possible $$D$$). ## The relationship between an interval's diameter and the denominators it contains Let $$s = b - a$$ be the diameter of $$[a, b]$$. If $$s \geq 1$$, then we can take $$D = 1$$: $$[a, b]$$ contains all denominators in $$\N^+$$. (For any denominator $$d$$, $$k + 1/d$$ is in $$[a, b]$$ for some integer $$k$$.) What if $$s < 1$$? We might think that if $$s \geq 1/d$$ then $$[a, b]$$ must contain some rational with denominator $$d$$, but this is not the case. For example, an interval with $$s > 1/6$$ might not contain any sixths:

The largest gap between sixths

The largest gap between sixths is $$2/3$$. Let's define $$f(d)$$ to be the largest gap between fractions with denominator $$d$$:

The largest gap between rationals with denominators 1 through 10

A graph of the largest-gap function

Any interval with $$s \geq f(d)$$ is, by definition, guaranteed to contain some rational with denominator $$d$$. If $$f$$ were monotonically decreasing, then we could use that to prove that $$D$$ exists. We'd simply need to find a $$D$$ such that $$f(D) \leq s$$, and then any $$f(d)$$ for $$d \geq D$$ would also be less than or equal to $$s$$. But $$f$$ does not monotonically decrease. ## The Jacobsthal function and primorials I couldn't find any reference to $$f(n)$$ in the literature, but fortunately $$g(n) = n f(n)$$ has been studied: it's called the [Jacobsthal function](http://oeis.org/A048669) (not to be confused with the Jacobsthal numbers, which are something unrelated). $$g(n)$$ is the size of the maximal gap in the list of all integers relatively prime to $$n$$.

A graph of the Jacobsthal function

We can make use of the bound ([^1]) $$g(n) \leq 2^w$$, where $$w$$ is the number of distinct prime factors of $$n$$. | constraint on $$n$$ | bound on $$w$$ | bound on $$g$$ | bound on $$f$$ | |-----------------------|----------------|------------------|----------------------| | $$1 \leq n < 2$$ | $$w \leq 0$$ | $$g(n) \leq 1$$ | $$f(n) \leq 1$$ | | $$2 \leq n < 6$$ | $$w \leq 1$$ | $$g(n) \leq 2$$ | $$f(n) \leq 1$$ | | $$6 \leq n < 30$$ | $$w \leq 2$$ | $$g(n) \leq 4$$ | $$f(n) \leq 2/3$$ | | $$30 \leq n < 210$$ | $$w \leq 3$$ | $$g(n) \leq 8$$ | $$f(n) \leq 4/15$$ | | $$210 \leq n < 2310$$ | $$w \leq 4$$ | $$g(n) \leq 16$$ | $$f(n) \leq 8/105$$ | | $$\ldots$$ | $$\ldots$$ | $$\ldots$$ | $$\ldots$$ | The sequence in the leftmost column, 1, 2, 6, 30, 210, ..., is the sequence of [primorials](https://en.wikipedia.org/wiki/Primorial): they are the products of the first 0, 1, 2, ... primes and therefore the smallest integers with 0, 1, 2, ... distinct prime factors. The $$n$$th primorial is denoted $$p_n\#$$. The sequence of bounds in the rightmost column, 1, 1, 2/3, 4/15, 8/105, ... is $$2^n/p_n\#$$ and is weakly monotonically decreasing. This allows us to construct a weakly monotonically decreasing function $$h$$ that bounds $$f$$ from above: $$h(n) = 2^k/p_k\# \ \text{where} \ p_k\# \leq n < p_{k+1}\#$$. Here are $$f$$ and $$h$$ plotted together:

A graph of the largest-gap function and an upper bound

$$h$$ is not a very tight bound. With more careful analysis, we could come up with a better one, perhaps by interpolating between the primorials or by making use of the bound ([^1]) $$g(h) \leq 2k^{2+2e\log k}$$. We now have an algorithm or determining a threshold $$D$$ for an interval $$[a, b]$$: 1. Find the diameter $$s = b - a$$. 2. Compute the sequence $$2^n/p_n\#$$ until it is less than or equal to $$s$$: the sequence decreases as $$O((2/n)^n)$$, so this step doesn't take long. 3. Let $$n$$ be the value at which $$2^n/p_n\# \leq s$$. Then take $$D$$ to be $$p_n\#$$. ## Results Let's go back to our example interval, $$[268876667/98914198, 245850922/78256779]$$. Its diameter is about 0.42, so its $$D$$ is 30, meaning that it's guaranteed to contain all denominators greater than or equal to 30. This threshold is low enough that we can just test all the denominators 1 through 29, and after doing this we find that the denominators 1, 4, and all denominators greater than 4 are present. Malachite generates the rationals contained in the interval in this order: 3, 11/4, 14/5, 20/7, 17/6, 23/8, 25/8, 30/11, 25/9, 29/10, 26/9, 31/11, 28/9, 31/10, 32/11, 41/15, 34/11, 35/12, 37/12, 39/14, ... . [^1]: Hans-Joachim Kanold, *Über eine zahlentheoretische Funktion von Jacobsthal*, Mathematische Annalen 170.4 (1967): 314-326 ================================================ FILE: docs/assets/denominators/gap-and-bound-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); int gcd(int a, int b) { while (b != 0) { int t = b; b = a % b; a = t; } return a; } int jacobsthal(int n) { int previous = 0; int largest_gap = 0; for (int i = 0; i <= 2 * n; ++i) { if (gcd(i, n) == 1) { int gap = i - previous; if (gap > largest_gap) { largest_gap = gap; } previous = i; } } return largest_gap; } scale(Linear,Log); real[] x={}; real[] y1={}; real[] y2={}; for (int i = 1; i < 500; ++i) { x.push(i); y1.push(jacobsthal(i)/i); if (i < 6) { y2.push(1); } else if (i < 30) { y2.push(2/3); } else if (i < 210) { y2.push(4/15); } else if (i < 2310) { y2.push(8/105); } } draw(graph(x,y1),black,"$f(n)$"); draw(graph(x,y2),red,"$h(n)$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(50,-25),UnFill); ================================================ FILE: docs/assets/denominators/gap-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); int gcd(int a, int b) { while (b != 0) { int t = b; b = a % b; a = t; } return a; } int jacobsthal(int n) { int previous = 0; int largest_gap = 0; for (int i = 0; i <= 2 * n; ++i) { if (gcd(i, n) == 1) { int gap = i - previous; if (gap > largest_gap) { largest_gap = gap; } previous = i; } } return largest_gap; } scale(Linear,Log); real[] x={}; real[] y={}; for (int i = 1; i < 500; ++i) { x.push(i); y.push(jacobsthal(i)/i); } draw(graph(x,y),black,"$f(n)$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(25,-25),UnFill); ================================================ FILE: docs/assets/denominators/gaps.asy ================================================ import graph; size(15cm); pen small=fontcommand("\scriptsize"); int gcd(int a, int b) { while (b != 0) { int t = b; b = a % b; a = t; } return a; } int jacobsthal(int n) { int previous = 0; int largest_gap = 0; for (int i = 0; i <= 2 * n; ++i) { if (gcd(i, n) == 1) { int gap = i - previous; if (gap > largest_gap) { largest_gap = gap; } previous = i; } } return largest_gap; } string gap_function(int d) { int n = jacobsthal(d); int g = gcd(n, d); n = n#g; d = d#g; if (d == 1) { return string(n); } else { return string(n) + "/" + string(d); } } void draw_rationals(int d, real offset) { guide gaxis=(0,offset)--(20,offset); draw(gaxis); for(int i = 0; i < 3; ++i){ tick(relpoint(gaxis,i/2),-plain.I*reldir(gaxis,i/2),ticksize*2); } for(int i = 0; i < 20; ++i){ tick(relpoint(gaxis,i/20),-plain.I*reldir(gaxis,i/20),ticksize); } label("$0$",relpoint(gaxis,0),-3*plain.I*reldir(gaxis,0)); label("$1$",relpoint(gaxis,0.5),-3*plain.I*reldir(gaxis,0.5)); label("$2$",relpoint(gaxis,1),-3*plain.I*reldir(gaxis,1)); for (int i= 0; i <= 2 * d; ++i) { if (gcd(i, d) == 1) { dot((i*10/d, offset), red); if (d != 1) { label("$" + string(i) + "/" + string(d) + "$",relpoint(gaxis,i/(2*d)),-2*plain.I*reldir(gaxis,0.5), red+small); } } } label("$f(" + string(d) + ") = " + gap_function(d) + "$",(24.5, offset), align=LeftSide); } real offset = 0; for (int d = 1; d <= 10; ++d) { draw_rationals(d, offset); offset -= 2; } // Force bottom margin to expand draw(box((-1,1),(-0.5, -20)),white); ================================================ FILE: docs/assets/denominators/j-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); int gcd(int a, int b) { while (b != 0) { int t = b; b = a % b; a = t; } return a; } int jacobsthal(int n) { int previous = 0; int largest_gap = 0; for (int i = 0; i <= 2 * n; ++i) { if (gcd(i, n) == 1) { int gap = i - previous; if (gap > largest_gap) { largest_gap = gap; } previous = i; } } return largest_gap; } //scale(Linear,Log); real[] x={}; real[] y={}; for (int i = 1; i < 500; ++i) { x.push(i); y.push(jacobsthal(i)); } draw(graph(x,y),black,"$g(n)$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(25,-25),UnFill); ================================================ FILE: docs/assets/denominators/sixths.asy ================================================ import graph; size(10cm); guide gaxis=(0,0)--(20,0); pen small=fontcommand("\footnotesize"); draw(gaxis); for(int i = 0; i < 3; ++i){ tick(relpoint(gaxis,i/2),-plain.I*reldir(gaxis,i/2),ticksize*2); } for(int i = 0; i < 20; ++i){ tick(relpoint(gaxis,i/20),-plain.I*reldir(gaxis,i/20),ticksize); } label("$0$",relpoint(gaxis,0),-3*plain.I*reldir(gaxis,0)); label("$1$",relpoint(gaxis,0.5),-3*plain.I*reldir(gaxis,0.5)); label("$2$",relpoint(gaxis,1),-3*plain.I*reldir(gaxis,1)); int gcd(int a, int b) { while (b != 0) { int t = b; b = a % b; a = t; } return a; } for (int i= 0; i <= 12; ++i) { if (gcd(i, 6) == 1) { dot((i*10/6, 0), red); label("$" + string(i) + "/6$",relpoint(gaxis,i/(2*6)),-2*plain.I*reldir(gaxis,0.5), red+small); } } draw((1.8, 0.2)--(1.8, -0.2),blue+linewidth(0.5mm)); draw((1.8, 0)--(8.2, 0),blue+linewidth(0.5mm)); draw((8.2, 0.2)--(8.2, -0.2),blue+linewidth(0.5mm)); ================================================ FILE: docs/assets/exhaustive-part-2/cantor-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); pair unpair(int i) { int j = 0; int r = i; while (r >= j) { r -= j; j += 1; } j -= 1; return (j - r, r); } real[] x={}; real[] y1={}; real[] y2={}; for (int i = 0; i < 500; ++i) { x.push(i); y1.push(unpair(i).x); y2.push(unpair(i).y); } real[] z=sqrt(2x); draw(graph(x,y1),red,"first element"); draw(graph(x,y2),blue,"second element"); draw(graph(x,z),black,"$\sqrt{2x}$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(25,-25),UnFill); ================================================ FILE: docs/assets/exhaustive-part-2/cantor-grid.asy ================================================ unitsize(1cm); int size = 5; for (int x = 0; x < size; ++x) { for (int y = 0; y < size; ++y) { dot((x, y)); } } pair unpair(int i) { int j = 0; int r = i; while (r >= j) { r -= j; j += 1; } j -= 1; return (j - r, r); } path boundary = box((-0.5, -0.5), (size + 0.5, size + 0.5)); pair previous = (0, 0); for (int i = 1; i < 15; ++i) { pair next = unpair(i); bool previous_in_range = previous.x < size && previous.y < size; bool next_in_range = next.x < size && next.y < size; if (previous_in_range && next_in_range) { draw(previous -- next, arrow=Arrow, gray); } else { draw(previous -- next, gray+Dotted()); } previous = next; } clip(boundary); ================================================ FILE: docs/assets/exhaustive-part-2/cantor-large.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \begin{document} \begin{equation*} \begin{split} 3^{20} &\rightarrow (33123, 50384) \\ 3^{40} &\rightarrow (2293673435, 2637384353) \\ 3^{60} &\rightarrow (158808187801698, 132365843578904) \\ 3^{80} &\rightarrow (12105097562203174223, 5088437816790055004) \\ 3^{100} &\rightarrow (416864661676079910029691, 598396408918091282666529) \\ \end{split} \end{equation*} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/cantor-triples-large.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \begin{document} \begin{equation*} \begin{split} 3^{20} &\rightarrow (33123, 298, 18) \\ 3^{40} &\rightarrow (2293673435, 7475, 65152) \\ 3^{60} &\rightarrow (158808187801698, 13757728, 2512848) \\ 3^{80} &\rightarrow (12105097562203174223, 2695483339, 494638230) \\ 3^{100} &\rightarrow (416864661676079910029691, 871747234874, 222233029040) \\ \end{split} \end{equation*} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/interleave-bits-1.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \begin{document} \begin{tabular}{rcr} 0 & $\rightarrow$ & \ldots 000000 \\ 1 & $\rightarrow$ & \ldots 000001 \\ 2 & $\rightarrow$ & \ldots 000010 \\ 3 & $\rightarrow$ & \ldots 000011 \\ 4 & $\rightarrow$ & \ldots 000100 \\ 5 & $\rightarrow$ & \ldots 000101 \\ 6 & $\rightarrow$ & \ldots 000110 \\ 7 & $\rightarrow$ & \ldots 000111 \\ \end{tabular} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/interleave-bits-2.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \usepackage{xcolor} \begin{document} \begin{tabular}{rcrcrcr} 0 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}0\color{red}0\color{blue}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00000 \color{black})$ & $\rightarrow$ & $(0, 0)$ \\ 1 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}0\color{red}0\color{blue}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00001 \color{black})$ & $\rightarrow$ & $(0, 1)$ \\ 2 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}0\color{red}1\color{blue}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00000 \color{black})$ & $\rightarrow$ & $(1, 0)$ \\ 3 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}0\color{red}1\color{blue}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00001 \color{black})$ & $\rightarrow$ & $(1, 1)$ \\ 4 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}1\color{red}0\color{blue}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00010 \color{black})$ & $\rightarrow$ & $(0, 2)$ \\ 5 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}1\color{red}0\color{blue}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00011 \color{black})$ & $\rightarrow$ & $(0, 3)$ \\ 6 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}1\color{red}1\color{blue}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00010 \color{black})$ & $\rightarrow$ & $(1, 2)$ \\ 7 & $\rightarrow$ & \ldots \color{red}0\color{blue}0\color{red}0\color{blue}1\color{red}1\color{blue}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00011 \color{black})$ & $\rightarrow$ & $(1, 3)$ \\ \end{tabular} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/interleave-grid-filtered.asy ================================================ unitsize(1cm); int size = 8; for (int x = 0; x < size; ++x) { for (int y = 0; y < size; ++y) { if (y < 2) { dot((x, y), green); } else { dot((x, y), red); } } } pair unpair(int i) { int x = 0; int y = 0; bool on_x = false; int out_mask = 1; while (i != 0) { if (i % 2 != 0) { if (on_x) { x += out_mask; } else { y += out_mask; } } if (on_x) { on_x = false; out_mask *= 2; } else { on_x = true; } i #= 2; } return (x, y); } path boundary = box((-0.5, -0.5), (size + 0.5, size + 0.5)); pair previous = (0, 0); for (int i = 1; i < size * size; ++i) { pair next = unpair(i); bool previous_in_range = previous.x <= size && previous.y <= size; bool next_in_range = next.x <= size && next.y <= size; if (previous_in_range && next_in_range) { draw(previous -- next, arrow=Arrow, gray); } else { draw(previous -- next, gray+Dotted()); } previous = next; } clip(boundary); ================================================ FILE: docs/assets/exhaustive-part-2/interleave-grid.asy ================================================ unitsize(1cm); int size = 8; for (int x = 0; x < size; ++x) { for (int y = 0; y < size; ++y) { dot((x, y)); } } pair unpair(int i) { int x = 0; int y = 0; bool on_x = false; int out_mask = 1; while (i != 0) { if (i % 2 != 0) { if (on_x) { x += out_mask; } else { y += out_mask; } } if (on_x) { on_x = false; out_mask *= 2; } else { on_x = true; } i #= 2; } return (x, y); } path boundary = box((-0.5, -0.5), (size + 0.5, size + 0.5)); pair previous = (0, 0); for (int i = 1; i < size * size; ++i) { pair next = unpair(i); bool previous_in_range = previous.x <= size && previous.y <= size; bool next_in_range = next.x <= size && next.y <= size; if (previous_in_range && next_in_range) { draw(previous -- next, arrow=Arrow, gray); } else { draw(previous -- next, gray+Dotted()); } previous = next; } clip(boundary); ================================================ FILE: docs/assets/exhaustive-part-2/interleave-large.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \begin{document} \begin{equation*} \begin{split} 3^{20} &\rightarrow (47160, 48725) \\ 3^{40} &\rightarrow (4005651428, 74192769) \\ 3^{60} &\rightarrow (191657527975116, 14476912773621) \\ 3^{80} &\rightarrow (8489200491033962112, 13032031964488297961) \\ 3^{100} &\rightarrow (231900172002858385847832, 957915753008438345446493) \\ \end{split} \end{equation*} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/interleave-pairs-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); pair unpair(int i) { int x = 0; int y = 0; bool on_x = false; int out_mask = 1; while (i != 0) { if (i % 2 != 0) { if (on_x) { x += out_mask; } else { y += out_mask; } } if (on_x) { on_x = false; out_mask *= 2; } else { on_x = true; } i #= 2; } return (x, y); } real[] x={}; real[] y1={}; real[] y2={}; for (int i = 0; i < 10000; ++i) { x.push(i); y1.push(unpair(i).x); y2.push(unpair(i).y); } real[] z=sqrt(3*x); draw(graph(x,y1),red,"first element"); draw(graph(x,y2),blue,"second element"); draw(graph(x,z),black,"$\sqrt{3x}$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(25,-25),UnFill); ================================================ FILE: docs/assets/exhaustive-part-2/interleave-triples-bits.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \usepackage{xcolor} \begin{document} \begin{tabular}{rcrcrcr} 0 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}0\color{blue}0\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00000 \color{black})$ & $\rightarrow$ & $(0, 0, 0)$ \\ 1 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}0\color{blue}0\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00001 \color{black})$ & $\rightarrow$ & $(0, 0, 1)$ \\ 2 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}0\color{blue}1\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00000 \color{black})$ & $\rightarrow$ & $(0, 1, 0)$ \\ 3 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}0\color{blue}1\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00001 \color{black})$ & $\rightarrow$ & $(0, 1, 1)$ \\ 4 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}1\color{blue}0\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00000 \color{black})$ & $\rightarrow$ & $(1, 0, 0)$ \\ 5 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}1\color{blue}0\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00001 \color{black})$ & $\rightarrow$ & $(1, 0, 1)$ \\ 6 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}1\color{blue}1\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00000 \color{black})$ & $\rightarrow$ & $(1, 1, 0)$ \\ 7 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}0\color{red}1\color{blue}1\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00001 \color{black})$ & $\rightarrow$ & $(1, 1, 1)$ \\ 8 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}0\color{blue}0\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00010 \color{black})$ & $\rightarrow$ & $(0, 0, 2)$ \\ 9 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}0\color{blue}0\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00011 \color{black})$ & $\rightarrow$ & $(0, 0, 3)$ \\ 10 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}0\color{blue}1\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00010 \color{black})$ & $\rightarrow$ & $(0, 1, 2)$ \\ 11 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}0\color{blue}1\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00000, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00011 \color{black})$ & $\rightarrow$ & $(0, 1, 3)$ \\ 12 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}1\color{blue}0\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00010 \color{black})$ & $\rightarrow$ & $(1, 0, 2)$ \\ 13 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}1\color{blue}0\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00000, \ \color{green} \ldots 00011 \color{black})$ & $\rightarrow$ & $(1, 0, 3)$ \\ 14 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}1\color{blue}1\color{green}0 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00010 \color{black})$ & $\rightarrow$ & $(1, 1, 2)$ \\ 15 & $\rightarrow$ & \ldots \color{green}0\color{red}0\color{blue}0\color{green}1\color{red}1\color{blue}1\color{green}1 & $\rightarrow$ & $(\color{red} \ldots 00001, \ \color{blue} \ldots 00001, \ \color{green} \ldots 00011 \color{black})$ & $\rightarrow$ & $(1, 1, 3)$ \\ \end{tabular} \end{document} ================================================ FILE: docs/assets/exhaustive-part-2/interleave-triples-graph.asy ================================================ import graph; size(600,400,IgnoreAspect); triple untriple(int i) { int x = 0; int y = 0; int z = 0; int j = 2; int out_mask = 1; while (i != 0) { if (i % 2 != 0) { if (j == 0) { x += out_mask; } else if (j == 1) { y += out_mask; } else { z += out_mask; } } if (j == 0) { j = 2; out_mask *= 2; } else if (j == 1) { j = 0; } else { j = 1; } i #= 2; } return (x, y, z); } real[] x={}; real[] y1={}; real[] y2={}; real[] y3={}; for (int i = 0; i < 10000; ++i) { x.push(i); y1.push(untriple(i).x); y2.push(untriple(i).y); y3.push(untriple(i).z); } real[] z=(7*x)^(1/3); draw(graph(x,y1),red,"first element"); draw(graph(x,y2),blue,"second element"); draw(graph(x,y3),green,"third element"); draw(graph(x,z),black,"$\sqrt[3]{7x}$"); xaxis(BottomTop,LeftTicks); yaxis(LeftRight, RightTicks); add(legend(),point(NW),(25,-25),UnFill); ================================================ FILE: docs/assets/exhaustive-part-2/interleave-triples-large.tex ================================================ \documentclass[11pt]{article} \usepackage{amsmath} \begin{document} \begin{equation*} \begin{split} 3^{20} &\rightarrow (460, 1414, 1881) \\ 3^{40} &\rightarrow (709242, 1441904, 2284385) \\ 3^{60} &\rightarrow (2679879830, 1355562942, 821033137) \\ 3^{80} &\rightarrow (3812501379408, 1191406597864, 8482842874549) \\ 3^{100} &\rightarrow (7172636040844612, 458719279115590, 7931619284932509) \\ \end{split} \end{equation*} \end{document} ================================================ FILE: docs/assets/logo.asy ================================================ unitsize(1mm); pair p1 = (25.0, -279.5970461708813); pair p2 = (73.21397343575165, -453.91200545461675); pair p3 = (87.46591514137958, -478.59709259527415); pair p4 = (135.6798885771313, -87.89385577922775); pair p5 = (139.89273037187124, -171.40290740472582); pair p6 = (202.35864551325085, -370.4029538291187); pair p7 = (214.32011142286873, -607.5090980498909); pair p8 = (284.53465067912623, -562.1061442207722); pair p9 = (310.7480582943721, -42.490901950109105); pair p10 = (339.2519417056279, -42.490901950109105); pair p11 = (347.00056582050587, -196.08799454538328); pair p12 = (425.6407886662433, -408.50905162549805); pair p13 = (435.67988857713124, -607.5090980498909); pair p14 = (514.3201114228686, -87.89385577922775); pair p15 = (550.5726189490025, -241.49094837450195); pair p16 = (562.5340848586204, -478.59709259527415); pair p17 = (576.7860265642483, -453.91200545461675); pair p18 = (625.0, -279.5970461708813); pair a = (0.5, sqrt(3)/2); pair b = (0, 0); pair c = (1, 0); pair center = (0.5, sqrt(3)/6); pen[] colors = new pen [] { RGB(115, 209, 160), RGB(86,158,118), RGB(56,106,76), RGB(27, 44, 34) }; fill(p1 -- p3 -- p6 -- p5 -- cycle, colors[2]); fill(p12 -- p17 -- p13 -- p8 -- cycle, colors[2]); fill(p9 -- p14 -- p15 -- p11 -- cycle, colors[2]); fill(p6 -- p12 -- p11 -- cycle, colors[2]); fill(p3 -- p8 -- p7 -- cycle, colors[2]); fill(p9 -- p5 -- p4 -- cycle, colors[2]); fill(p17 -- p15 -- p18 -- cycle, colors[2]); fill(p1 -- p2 -- p3 -- cycle, colors[1]); fill(p3 -- p6 -- p8 -- cycle, colors[1]); fill(p6 -- p8 -- p12 -- cycle, colors[0]); fill(p6 -- p5 -- p11 -- cycle, colors[0]); fill(p13 -- p8 -- p7 -- cycle, colors[1]); fill(p13 -- p16 -- p17 -- cycle, colors[1]); fill(p12 -- p17 -- p15 -- cycle, colors[1]); fill(p12 -- p11 -- p15 -- cycle, colors[0]); fill(p1 -- p5 -- p4 -- cycle, colors[1]); fill(p9 -- p5 -- p11 -- cycle, colors[1]); fill(p9 -- p10 -- p14 -- cycle, colors[1]); fill(p14 -- p15 -- p18 -- cycle, colors[1]); ================================================ FILE: docs/index.md ================================================

Logo

Malachite is an arbitrary-precision arithmetic library for [Rust](https://www.rust-lang.org/). It achieves high performance in part by using algorithms derived from [GMP](https://gmplib.org/), [FLINT](https://www.flintlib.org/), and [MPFR](https://www.mpfr.org/). The documentation for Malachite is [here](https://docs.rs/malachite/latest/malachite/), and its crate is [here](https://crates.io/crates/malachite). ```rust use malachite::num::arithmetic::traits::Factorial; use malachite::Natural; fn main() { println!("{}", Natural::factorial(100)); } ``` The code above outputs the following: ``` 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 ``` You have to scroll to see the entire output. Here's a more complex example, calculating the negative-one-millionth power of 3 and displaying the result with 30 digits of precision. ```rust use malachite::num::arithmetic::traits::Pow; use malachite::num::conversion::string::options::ToSciOptions; use malachite::num::conversion::traits::ToSci; use malachite::Rational; fn main() { let mut options = ToSciOptions::default(); options.set_precision(30); println!("{}", Rational::from(3).pow(-1_000_000i64).to_sci_with_options(options)); } ``` The output is this: ``` 5.56263209915712886588211486263e-477122 ``` Every digit is correct, except that the least-significant digit was rounded up from 2. The default rounding mode, [`Nearest`](https://docs.rs/malachite-base/latest/malachite_base/rounding_modes/enum.RoundingMode.html#variant.Nearest), uses [bankers' rounding](https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_even), but you may specify different rounding behavior via the options parameter. Malachite is designed to work with very large numbers efficiently. See [here](/performance) for a performance comparison against other libraries. Malachite uses `no_std`, unless the `random`, `test_build`, or `bin_build` features are enabled. To use Malachite, add the following to your project's `Cargo.toml` file: ```yaml [dependencies.malachite] version = "0.9.1" ``` By default, all of Malachite's features are included, but you can opt out of some of them. For example, if you want to use `Natural` and `Integer` but not `Rational`, you can instead use ```yaml [dependencies.malachite] version = "0.9.1" default-features = false features = [ "naturals_and_integers" ] ``` The `malachite` crate re-exports three sub-crates. - **malachite-base** ([crates.io](https://crates.io/crates/malachite-base)) is a collection of utilities supporting the other crates. It includes - Traits that wrap functions from the standard library, like [`CheckedAdd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.CheckedAdd.html); - Traits that give extra functionality to primitive types, like [`Gcd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.Gcd.html), [`FloorSqrt`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.FloorSqrt.html), and [`BitAccess`](https://docs.rs/malachite-base/latest/malachite_base/num/logic/traits/trait.BitAccess.html); - Iterator-producing functions that let you generate values for testing. - **malachite-nz** ([crates.io](https://crates.io/crates/malachite-nz)) defines two bignum types, [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s and [`Integer`](https://docs.rs/malachite-nz/latest/malachite_nz/integer/struct.Integer.html)s. The functions defined on these types include - All the ones you'd expect, like addition, subtraction, multiplication, and integer division; - Implementations of [`DivRound`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.DivRound.html), which provides division that rounds according to a specified [`RoundingMode`](https://docs.rs/malachite-base/latest/malachite_base/rounding_modes/enum.RoundingMode.html); - Various mathematical functions, like implementations of [`FloorSqrt`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.FloorSqrt.html) and [`Gcd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.Gcd.html); - Modular arithmetic functions, like implementations of [`ModAdd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModAdd.html) and [`ModPow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPow.html), and of traits for arithmetic modulo a power of 2, like [`ModPowerOf2Add`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPowerOf2Add.html) and [`ModPowerOf2Pow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPowerOf2Pow.html); - Various functions for logic and bit manipulation, like [`BitAnd`](https://doc.rust-lang.org/nightly/core/ops/trait.BitAnd.html) and [`BitAccess`](https://docs.rs/malachite-base/latest/malachite_base/num/logic/traits/trait.BitAccess.html). If you need to explicitly include this crate as a dependency of the `malachite` crate, use the `naturals_and_integers` or `malachite-nz` feature. - **malachite-q** ([crates.io](https://crates.io/crates/malachite-q)) defines [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s. The functions defined on this type include - All the ones you'd expect, like addition, subtraction, multiplication, and division; - Functions related to conversion between [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s and other kinds of numbers, including primitive floats; - Functions for Diophantine approximation; - Functions for expressing [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s in scientific notation. If you need to explicitly include this crate as a dependency of the `malachite` crate, use the `rationals` or `malachite-q` feature. - **malachite-float** Arbitrary-precision floating-point numbers. These are in development, and most features are missing. Malachite is under active development, with many more types and features planned for the future. Nonetheless, it is extensively tested and documented, and ready for use today. Just be aware that its API is not stable yet, and that Malachite is licensed under LGPL 3.0. Malachite is developed by Mikhail Hogrefe. `malachite-bigint`, a drop-in num-bigint replacement based on Malachite, was created by Steve Shi and is now maintained by Mikhail Hogrefe. Thanks to b4D8, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, shekohex, and skycloudd for additional contributions. # FAQ **How is "Malachite" pronounced, and what does it mean?** "Malachite" is pronounced MA-luh-kite, or /ˈmæl.əˌkaɪt/. It is the name of [a green gemstone](https://en.wikipedia.org/wiki/Malachite). Unfortunately, malachite does not contain iron, which would have made it a particularly good namesake for a Rust library. Malachite's logo is an image of a [snub cube](https://en.wikipedia.org/wiki/Snub_cube). **When does Malachite allocate memory?** Any `Natural` less than $$2^{64}$$ is represented inline, without allocating memory. Any `Integer` whose absolute value is less than $$2^{64}$$ doesn't allocate either, and neither does any `Rational` whose absolute numerator and denominator are both less than $$2^{64}$$. If you're using a build with `--features 32_bit_limbs`, then the threshold is $$2^{32}$$ instead. **Can I build Malachite for WebAssembly?** Yes. If, in the future, Malachite includes code incompatible with Wasm (for example, code that uses [rayon](https://docs.rs/rayon/latest/rayon/)), it will be possible to disable that code with cargo flags. # Blog Posts Copyright © 2026 Mikhail Hogrefe ================================================ FILE: docs/performance.md ================================================ --- layout: default title: "Malachite Performance" permalink: /performance/ theme: jekyll-theme-slate --- # Performance Here are some benchmarks comparing the Malachite to two other libraries: - [`num`](https://crates.io/crates/num), the de facto standard bignum library for Rust. - [`rug`](https://crates.io/crates/rug), a library that calls GMP, a widely used, highly-optimized bignum library written in C. The `num` version that is compared against is 0.4.0, and the `rug` version is 1.16.0. The general trend is that Malachite is faster than `num` due to better algorithms, and slower than `rug`. My guess is that the better performance of `rug` is due partly to GMP's use of inline assembly (Malachite has none, being written entirely in safe Rust), and possibly due to operations on Rust's slices being a little slower than C's raw pointers. The following is just a small sample of the benchmarks that are available in Malachite. For each benchmark, I've included the command that you can use to run it yourself. You can specify the output file using `-o benchfile.gp`, and then use [gnuplot](http://www.gnuplot.info/) to convert the `.gp` to your format of choice. I like SVG: `gnuplot -e "set terminal svg; l \"benchfile.gp\"" > benchfile.svg` ## Rational addition `cargo run --features bin_build --release -- -l 100000 -m random -b benchmark_rational_add_library_comparison -c "mean_bits_n 256"`

Rational addition

The most significant operations involved in adding two rational numbers (fractions) are GCD computation and division. For GCD computation, `num` uses the [binary GCD algorithm](https://en.wikipedia.org/wiki/Binary_GCD_algorithm), a quadratic algorithm. Malachite follows GMP in using [Lehmer's GCD algorithm](https://en.wikipedia.org/wiki/Lehmer%27s_GCD_algorithm), which takes advantage of fast multiplication algorithms to achieve $$O(n (\log n)^2 \log \log n)$$ time. For division, `num` uses Knuth's [Algorithm D](https://ridiculousfish.com/blog/posts/labor-of-division-episode-iv.html), which is also quadratic. Malachite, again following GMP, uses several division algorithms depending on the input size. For the largest inputs, it uses a kind of [Barrett reduction](https://en.wikipedia.org/wiki/Barrett_reduction), which takes $$O(n \log n \log \log n)$$ time. ## Converting a Natural to a string `cargo run --features bin_build --release -- -l 100000 -m random -b benchmark_natural_to_string_library_comparison -c "mean_bits_n 1024"`

Natural to string

When converting a natural number to a string, `num` seems to use an $$O(n^{3/2})$$ algorithm. Malachite uses a divide-and-conquer algorithm that takes $$O(n (\log n)^2 \log \log n)$$ time. ## Natural multiplication `cargo run --features bin_build --release -- -l 20000 -m random -b benchmark_natural_mul_library_comparison -c "mean_bits_n 16384"`

Natural multiplication

For multiplying two natural numbers, `num` uses a basecase quadratic algorithm for small inputs, then [Toom-22](https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication) (Karatsuba) multiplication for larger inputs, and finally Toom-33 for the largest ones. This means that multiplication takes $$O(n^{\log_3 5}) \approx O(n^{1.465})$$ time. Malachite also uses a basecase quadratic algorithm, then 13 variants of Toom-Cook multiplication, and finally [Schönhage-Strassen (FFT) multiplication](https://en.wikipedia.org/wiki/Schonhage-Strassen_algorithm) for the largest inputs, achieving $$O(n \log n \log \log n)$$ time. Given all of this machinery, it's a little disappointing that Malachite isn't much faster at multiplying than `num` is, in practice. I have a few improvements in mind that should boost Malachite's multiplication performance further. For numbers of up to 1000 bits, all three libraries are about equally fast: `cargo run --features bin_build --release -- -l 100000 -m random -b benchmark_natural_mul_library_comparison -c "mean_bits_n 64"`

Natural multiplication

## Natural addition `cargo run --features bin_build --release -- -l 100000 -m random -b benchmark_natural_add_library_comparison -c "mean_bits_n 1024"`

Natural addition

Addition of natural numbers is fast for all three libraries, being a straightforward and linear-time affair. Interestingly, `rug` is the slowest of the bunch. I find it hard to believe that GMP is slower than `num` or Malachite, so maybe there's some overhead associated with FFI. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: find_replace.py ================================================ import os import sys def search_replace(filename, old, new): with open(filename) as f: new_lines = [] replaced = False for line in f.readlines(): line = line.rstrip() if old in line: replaced = True new_lines.append(line.replace(old, new)) else: new_lines.append(line) if replaced: with open(filename, 'w') as out_f: for line in new_lines: out_f.write(line + '\n') return replaced old = sys.argv[1] new = sys.argv[2] filename_list = [] for root, directories, filenames in os.walk('.'): for filename in filenames: filename = os.path.join(root, filename) if '/target/' not in filename and filename.endswith('.rs'): filename_list.append(filename) for root, directories, filenames in os.walk('../rust-wheels'): for filename in filenames: filename = os.path.join(root, filename) if '/target/' not in filename and filename.endswith('.rs'): filename_list.append(filename) filename_list.sort() line_count = 0 for filename in filename_list: if search_replace(filename, old, new): print(filename) ================================================ FILE: flake.nix ================================================ { description = "malachite development environment"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; # Rust rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; }; }; }; outputs = { self, nixpkgs, rust-overlay, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; }; lib = pkgs.lib; toolchain = pkgs.rust-bin.stable.latest.default.override { extensions = [ "rust-src" ]; targets = [ "wasm32-unknown-unknown" ]; }; in { devShells.default = pkgs.mkShell { name = "malachite"; nativeBuildInputs = [ pkgs.pkg-config pkgs.clang # Mold Linker for faster builds (only on Linux) (lib.optionals pkgs.stdenv.isLinux pkgs.mold) (lib.optionals pkgs.stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.Security) (lib.optionals pkgs.stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.SystemConfiguration) ]; buildInputs = [ # We want the unwrapped version, wrapped comes with nixpkgs' toolchain pkgs.rust-analyzer-unwrapped # Finally the toolchain toolchain ]; packages = [ pkgs.cargo-nextest ]; # Environment variables RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; # Needed for testing rug LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.gmp ]; }; }); } ================================================ FILE: katex-header.html ================================================ ================================================ FILE: malachite/Cargo.toml ================================================ [package] name = "malachite" version = "0.9.1" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true description = "Arbitrary-precision arithmetic, with efficient algorithms partially derived from GMP, FLINT, and MPFR." readme = "../README.md" homepage = "https://malachite.rs/" repository = "https://github.com/mhogrefe/malachite" license = "LGPL-3.0-only" keywords = ["mathematics", "math", "numerics", "bignum"] categories = ["mathematics"] [dependencies] malachite-base = { version = "0.9.1", default-features = false, path = "../malachite-base" } malachite-nz = { version = "0.9.1", default-features = false, optional = true, path = "../malachite-nz" } malachite-q = { version = "0.9.1", default-features = false, optional = true, path = "../malachite-q" } malachite-float = { version = "0.9.1", default-features = false, optional = true, path = "../malachite-float" } serde = { version = "1.0.188", optional = true, features = ["derive"] } embed-doc-image = { version = "0.1.4", optional = true } [features] default = [ "std", "naturals_and_integers", "rationals" ] std = [ "malachite-base/std", "malachite-nz/std", "malachite-q/std", "malachite-float/std" ] enable_pyo3 = [ "malachite-nz/enable_pyo3" ] enable_serde = [ "malachite-nz/enable_serde", "malachite-q/enable_serde", "malachite-float/enable_serde" ] random = ["malachite-base/random", "malachite-nz/random", "malachite-q/random", "malachite-float/random"] 32_bit_limbs = ["malachite-nz/32_bit_limbs", "malachite-q/32_bit_limbs", "malachite-float/32_bit_limbs"] naturals_and_integers = [ "malachite-nz" ] rationals = [ "malachite-q" ] floats = [ "malachite-float" ] [package.metadata.docs.rs] # docs.rs uses a nightly compiler, so by instructing it to use our `doc-images` feature we # ensure that it will render any images that we may have in inner attribute documentation. features = ["embed-doc-image", "random"] rustdoc-args = [ "--html-in-header", "katex-header.html" ] ================================================ FILE: malachite/katex-header.html ================================================ ================================================ FILE: malachite/src/lib.rs ================================================ // Copyright © 2026 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 . #![cfg_attr(not(any(feature = "random", feature = "std")), no_std)] /// This module contains various functions that support the other crates. This includes many /// numeric traits and their implementation for primitive numeric types, as well as many functions /// for exhaustively and randomly generating values of many types. pub mod base { pub use malachite_base::*; } #[cfg(feature = "naturals_and_integers")] #[cfg(feature = "rationals")] #[cfg(feature = "floats")] pub use malachite_float::Float; #[cfg(feature = "naturals_and_integers")] pub use malachite_nz::integer::Integer; #[cfg(feature = "naturals_and_integers")] pub use malachite_nz::natural::Natural; #[cfg(feature = "naturals_and_integers")] pub use malachite_nz::*; #[cfg(feature = "naturals_and_integers")] #[cfg(feature = "rationals")] /// [`Rational`], a type representing rational numbers with arbitrarily large numerators and /// denominators. pub mod rational { pub use malachite_q::*; } #[cfg(feature = "naturals_and_integers")] #[cfg(feature = "rationals")] pub use malachite_q::Rational; /// Various types and constants dependent on whether Malachite is built using 32-bit limbs or /// 64-bit limbs. `Limb` is the type such that `Vec`s of limbs are used to represent the bits of a /// [`Natural`]. pub mod platform { #[cfg(feature = "32_bit_limbs")] pub use malachite_nz::platform_32::*; #[cfg(not(feature = "32_bit_limbs"))] pub use malachite_nz::platform_64::*; } ================================================ FILE: malachite-base/.gitignore ================================================ target *.bk .idea* *.iml ================================================ FILE: malachite-base/Cargo.toml ================================================ [package] name = "malachite-base" version = "0.9.1" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true description = "A collection of utilities, including new arithmetic traits and iterators that generate all values of a type." readme = "README.md" homepage = "https://malachite.rs/" repository = "https://github.com/mhogrefe/malachite" license = "LGPL-3.0-only" keywords = ["mathematics", "math", "numerics", "testing"] categories = ["mathematics", "development-tools::testing"] [lib] name = "malachite_base" path = "src/lib.rs" [[bin]] name = "malachite_base_main" path = "src/bin.rs" test = false [dependencies] itertools = { version = "0.14.0", default-features = false, features = ["use_alloc"] } ryu = { version = "1.0.22", default-features = false } hashbrown = { version = "0.16.1", default-features = false, features = ["default-hasher", "inline-more"] } libm = { version = "0.2.16", default-features = false } sha3 = { version = "0.10.8", optional = true, default-features = false } rand = { version = "0.9.2", optional = true, default-features = false } rand_chacha = { version = "0.9.0", optional = true, default-features = false } getrandom = { version = "0.2", default-features = false, features = ["js"], optional = true } clap = { version = "2.33.1", optional = true } gnuplot = { version = "0.0.46", optional = true } time = { version = "0.3.47", optional = true } walkdir = { version = "2.5.0", optional = true } [features] default = ["std"] std = ["itertools/use_std"] random = ["sha3", "rand", "rand_chacha", "getrandom"] test_build = ["gnuplot", "time", "clap", "random", "itertools/use_std"] bin_build = ["walkdir", "test_build"] [dev-dependencies] malachite-base = { workspace = true, features = ["test_build"] } maplit = "1.0.2" [package.metadata.docs.rs] rustdoc-args = [ "--html-in-header", "katex-header.html" ] ================================================ FILE: malachite-base/README.md ================================================ - [crates.io](https://crates.io/crates/malachite-base) - [docs.rs](https://docs.rs/malachite-base/latest/malachite_base/) Rather than using this crate directly, use the [`malachite`](https://crates.io/crates/malachite) meta-crate. It re-exports all of this crate's public members. In `malachite-base`'s doctests you will frequently see import paths beginning with `malachite_base::`. When using the `malachite` crate, replace this part of the paths with `malachite::`. # malachite-base This crate contains many utilities that are used by the [`malachite-nz`](https://crates.io/crates/malachite-nz) and [`malachite-q`](https://crates.io/crates/malachite-q) crates. These utilities include - Traits that wrap functions from the standard library, like [`CheckedAdd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.CheckedAdd.html). - Traits that give extra functionality to primitive types, like [`Gcd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.Gcd.html), [`FloorSqrt`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.FloorSqrt.html), and [`BitAccess`](https://docs.rs/malachite-base/latest/malachite_base/num/logic/traits/trait.BitAccess.html). - Iterator-producing functions that let you generate values for testing. Here's an example of an iterator that produces all pairs of [`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html)s: ``` use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single; let mut pairs = exhaustive_pairs_from_single(exhaustive_unsigneds::()); assert_eq!( pairs.take(20).collect::>(), &[ (0, 0), (0, 1), (1, 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1), (3, 0), (3, 1), (2, 2), (2, 3), (3, 2), (3, 3), (0, 4), (0, 5), (1, 4), (1, 5) ] ); ``` - The [`RoundingMode`](https://docs.rs/malachite-base/latest/malachite_base/rounding_modes/enum.RoundingMode.html) enum, which allows you to specify the rounding behavior of various functions. - The [`NiceFloat`](https://docs.rs/malachite-base/latest/malachite_base/num/float/struct.NiceFloat.html) wrapper, which provides alternative implementations of [`Eq`](https://doc.rust-lang.org/nightly/core/cmp/trait.Eq.html), [`Ord`](https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html), and [`Display`](https://doc.rust-lang.org/nightly/core/fmt/trait.Display.html) for floating-point values which are in some ways nicer than the defaults. # Demos and benchmarks This crate comes with a `bin` target that can be used for running demos and benchmarks. - Almost all of the public functions in this crate have an associated demo. Running a demo shows you a function's behavior on a large number of inputs. For example, to demo the [`mod_pow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPow.html#tymethod.mod_pow) function on [`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html)s, you can use the following command: ``` cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_mod_pow_u32 ``` This command uses the `exhaustive` mode, which generates every possible input, generally starting with the simplest input and progressing to more complex ones. Another mode is `random`. The `-l` flag specifies how many inputs should be generated. - You can use a similar command to run benchmarks. The following command benchmarks various GCD algorithms for [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html)s: ```text cargo run --features bin_build --release -- -l 1000000 -m random -b \ benchmark_gcd_algorithms_u64 -o gcd-bench.gp ``` This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like so: ```text gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg ``` The list of available demos and benchmarks is not documented anywhere; you must find them by browsing through [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-base/src/bin_util/demo_and_bench). # Features - `random`: This feature provides some functions for randomly generating values. It is off by default to avoid pulling in some extra dependencies. - `test_build`: A large proportion of the code in this crate is only used for testing. For a typical user, building this code would result in an unnecessarily long compilation time and an unnecessarily large binary. Much of it is also used for testing [`malachite-nz`](https://crates.io/crates/malachite-nz) and [`malachite-q`](https://crates.io/crates/malachite-q), so it can't just be confined to the `tests` directory. My solution is to only build this code when the `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`. However, doctests don't require it, since they only test the public interface. Enabling this feature also enables `random`. - `bin_build`: This feature is used to build the code for demos and benchmarks, which also takes a long time to build. Enabling this feature also enables `test_build` and `random`. Malachite is developed by Mikhail Hogrefe. Thanks to b4D8, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, shekohex, and skycloudd for additional contributions. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: malachite-base/katex-header.html ================================================ ================================================ FILE: malachite-base/rustfmt.toml ================================================ max_width = 100 array_width = 100 ================================================ FILE: malachite-base/src/bin.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #[cfg(feature = "bin_build")] extern crate itertools; #[cfg(feature = "bin_build")] #[macro_use] extern crate malachite_base; #[cfg(feature = "bin_build")] extern crate walkdir; #[cfg(feature = "bin_build")] use bin_util::demo_and_bench::register; #[cfg(feature = "bin_build")] use bin_util::generate::max_base::generate_max_base; #[cfg(feature = "bin_build")] use bin_util::generate::rle::generate_rle_encoding; #[cfg(feature = "bin_build")] use bin_util::generate::tuning_manager::{build_reference_data, test}; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::Runner; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::cmd::read_command_line_arguments; // Examples: // // ``` // cargo run --features bin_build -- -g max_base // cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_mod_pow_u32 // ``` #[cfg(feature = "bin_build")] fn main() { let args = read_command_line_arguments("malachite-base"); let mut runner = Runner::new(); register(&mut runner); if let Some(demo_key) = args.demo_key { runner.run_demo(&demo_key, args.generation_mode, &args.config, args.limit); } else if let Some(bench_key) = args.bench_key { runner.run_bench( &bench_key, args.generation_mode, &args.config, args.limit, &args.out, ); } else { let codegen_key = args.codegen_key.unwrap(); match codegen_key.as_str() { "max_base" => generate_max_base(), "rle_encode" => generate_rle_encoding(), "tm_build_reference_data" => build_reference_data(), "tm_test" => test(), _ => panic!("Invalid codegen key: {codegen_key}"), } } } #[cfg(not(feature = "bin_build"))] const fn main() {} #[cfg(feature = "bin_build")] pub mod bin_util { pub mod demo_and_bench; pub mod generate; } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/bools/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { not_assign::register(runner); } mod not_assign; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/bools/not_assign.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::NotAssign; use malachite_base::test_util::generators::bool_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_bool_not_assign); } fn demo_bool_not_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut b in bool_gen().get(gm, config).take(limit) { let b_old = b; b.not_assign(); println!("b := {b_old}; b.not_assign(); b = {b}"); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/chars/crement/char_to_contiguous_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::crement::char_to_contiguous_range; use malachite_base::test_util::bench::bucketers::char_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::char_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_char_to_contiguous_range); register_bench!(runner, benchmark_char_to_contiguous_range); } fn demo_char_to_contiguous_range(gm: GenMode, config: &GenConfig, limit: usize) { for c in char_gen().get(gm, config).take(limit) { println!( "char_to_contiguous_range({:?}) = {}", c, char_to_contiguous_range(c) ); } } fn benchmark_char_to_contiguous_range( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "char_to_contiguous_range(char)", BenchmarkType::Single, char_gen().get(gm, config), gm.name(), limit, file_name, &char_bucketer(), &mut [("Malachite", &mut |c| no_out!(char_to_contiguous_range(c)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/chars/crement/contiguous_range_to_char.rs ================================================ // Copyright © 2026 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 malachite_base::chars::crement::contiguous_range_to_char; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_contiguous_range_to_char); register_bench!(runner, benchmark_contiguous_range_to_char); } fn demo_contiguous_range_to_char(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen().get(gm, config).take(limit) { println!( "contiguous_range_to_char({}) = {:?}", u, contiguous_range_to_char(u) ); } } fn benchmark_contiguous_range_to_char( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "contiguous_range_to_char(u32)", BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(contiguous_range_to_char(u)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/chars/crement/crement.rs ================================================ // Copyright © 2026 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 malachite_base::chars::crement::{decrement_char, increment_char}; use malachite_base::test_util::bench::bucketers::char_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{char_gen_var_1, char_gen_var_2}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_increment_char); register_demo!(runner, demo_decrement_char); register_bench!(runner, benchmark_increment_char); register_bench!(runner, benchmark_decrement_char); } fn demo_increment_char(gm: GenMode, config: &GenConfig, limit: usize) { for mut c in char_gen_var_1().get(gm, config).take(limit) { let c_old = c; increment_char(&mut c); println!("c := {c_old:?}; increment_char(&mut c); c = {c:?}"); } } fn demo_decrement_char(gm: GenMode, config: &GenConfig, limit: usize) { for mut c in char_gen_var_2().get(gm, config).take(limit) { let c_old = c; increment_char(&mut c); println!("c := {c_old:?}; decrement_char(&mut c); c = {c:?}"); } } fn benchmark_increment_char(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "increment_char(&mut char)", BenchmarkType::Single, char_gen_var_1().get(gm, config), gm.name(), limit, file_name, &char_bucketer(), &mut [("Malachite", &mut |mut c| increment_char(&mut c))], ); } fn benchmark_decrement_char(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "decrement_char(&mut char)", BenchmarkType::Single, char_gen_var_2().get(gm, config), gm.name(), limit, file_name, &char_bucketer(), &mut [("Malachite", &mut |mut c| decrement_char(&mut c))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/chars/crement/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { char_to_contiguous_range::register(runner); contiguous_range_to_char::register(runner); crement::register(runner); } pub mod char_to_contiguous_range; pub mod contiguous_range_to_char; #[allow(clippy::module_inception)] pub mod crement; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/chars/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { crement::register(runner); } mod crement; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/comparison/macros.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_max_bit_bucketer, triple_max_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_max_1); register_demo!(runner, demo_max_2); register_demo!(runner, demo_max_3); register_demo!(runner, demo_min_1); register_demo!(runner, demo_min_2); register_demo!(runner, demo_min_3); register_bench!(runner, benchmark_max_1); register_bench!(runner, benchmark_max_2); register_bench!(runner, benchmark_max_3); register_bench!(runner, benchmark_min_1); register_bench!(runner, benchmark_min_2); register_bench!(runner, benchmark_min_3); } fn demo_max_1(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("max!({}) = {}", x, max!(x)); } } fn demo_max_2(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("max!({}, {}) = {}", x, y, max!(x, y)); } } fn demo_max_3(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!("max!({}, {}, {}) = {}", x, y, z, max!(x, y, z)); } } fn demo_min_1(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("min!({}) = {}", x, min!(x)); } } fn demo_min_2(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("min!({}, {}) = {}", x, y, min!(x, y)); } } fn demo_min_3(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!("min!({}, {}, {}) = {}", x, y, z, min!(x, y, z)); } } fn benchmark_max_1(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "max!(T)", BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(max!(x)))], ); } fn benchmark_max_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "max!(T, T)", BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(max!(x, y)))], ); } fn benchmark_max_3(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "max!(T, T, T)", BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(max!(x, y, z)))], ); } fn benchmark_min_1(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "min!(T)", BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(min!(x)))], ); } fn benchmark_min_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "min!(T, T)", BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(min!(x, y)))], ); } fn benchmark_min_3(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "min!(T, T, T)", BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(min!(x, y, z)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { macros::register(runner); } mod macros; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; macro_rules! unsigned_single_arg_demo { ($name: ident, $f: ident) => { fn $name(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!(concat!("{}.", stringify!($f), "() = {}"), u, u.$f()); } } }; } macro_rules! signed_single_arg_demo { ($name: ident, $f: ident) => { fn $name(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!(concat!("({}).", stringify!($f), "() = {}"), i, i.$f()); } } }; } macro_rules! unsigned_single_arg_bench { ($name: ident, $f: ident) => { fn $name( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!(concat!("{}.", stringify!($f), "()"), T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.$f()))], ); } }; } macro_rules! signed_single_arg_bench { ($name: ident, $f: ident) => { fn $name( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!(concat!("{}.", stringify!($f), "()"), T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.$f()))], ); } }; } pub(crate) fn register(runner: &mut Runner) { bools::register(runner); chars::register(runner); comparison::register(runner); num::register(runner); rational_sequences::register(runner); rounding_modes::register(runner); slices::register(runner); strings::register(runner); vecs::register(runner); } mod bools; mod chars; mod comparison; mod num; mod rational_sequences; mod rounding_modes; mod slices; mod strings; mod vecs; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{primitive_float_bucketer, signed_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_abs_assign_signed); register_primitive_float_demos!(runner, demo_abs_assign_primitive_float); register_signed_benches!(runner, benchmark_abs_assign_signed); register_primitive_float_benches!(runner, benchmark_abs_assign_primitive_float); } fn demo_abs_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen_var_1::().get(gm, config).take(limit) { let old_i = i; i.abs_assign(); println!("i := {old_i}; i.abs_assign(); i = {i}"); } } fn demo_abs_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.abs_assign(); println!( "i := {}; i.abs_assign(); i = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_abs_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.abs_assign()", T::NAME), BenchmarkType::Single, signed_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.abs_assign())], ); } fn benchmark_abs_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.abs_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.abs_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_abs_diff_assign); register_unsigned_benches!(runner, benchmark_abs_diff_assign); } fn demo_abs_diff_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.abs_diff_assign(y); println!("x := {old_x}; x.abs_diff_assign({y}); x = {x}"); } } fn benchmark_abs_diff_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.abs_diff_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.abs_diff_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ triple_max_bit_bucketer, triple_max_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_triple_gen, signed_triple_gen_var_1, unsigned_triple_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_add_mul_unsigned); register_signed_demos!(runner, demo_add_mul_signed); register_primitive_float_demos!(runner, demo_add_mul_primitive_float); register_unsigned_demos!(runner, demo_add_mul_assign_unsigned); register_signed_demos!(runner, demo_add_mul_assign_signed); register_primitive_float_demos!(runner, demo_add_mul_assign_primitive_float); register_unsigned_benches!(runner, benchmark_add_mul_unsigned); register_signed_benches!(runner, benchmark_add_mul_signed); register_primitive_float_benches!(runner, benchmark_add_mul_primitive_float); register_unsigned_benches!(runner, benchmark_add_mul_assign_unsigned); register_signed_benches!(runner, benchmark_add_mul_assign_signed); register_primitive_float_benches!(runner, benchmark_add_mul_assign_primitive_float); } fn demo_add_mul_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in unsigned_triple_gen_var_1::().get(gm, config).take(limit) { println!("{}.add_mul({}, {}) = {}", x, y, z, x.add_mul(y, z)); } } fn demo_add_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen_var_1::().get(gm, config).take(limit) { println!("({}).add_mul({}, {}) = {}", x, y, z, x.add_mul(y, z)); } } fn demo_add_mul_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in primitive_float_triple_gen::() .get(gm, config) .take(limit) { println!( "({}).add_mul({}, {}) = {}", NiceFloat(x), NiceFloat(y), NiceFloat(z), NiceFloat(x.add_mul(y, z)) ); } } fn demo_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_1::().get(gm, config).take(limit) { let old_x = x; x.add_mul_assign(y, z); println!("x := {old_x}; x.add_mul_assign({y}, {z}); x = {x}"); } } fn demo_add_mul_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in signed_triple_gen_var_1::().get(gm, config).take(limit) { let old_x = x; x.add_mul_assign(y, z); println!("x := {old_x}; x.add_mul_assign({y}, {z}); x = {x}"); } } fn demo_add_mul_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in primitive_float_triple_gen::() .get(gm, config) .take(limit) { let old_x = x; x.add_mul_assign(y, z); println!( "x := {}; x.add_mul_assign({}, {}); x = {}", NiceFloat(old_x), NiceFloat(y), NiceFloat(z), NiceFloat(x) ); } } fn benchmark_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.add_mul(y, z)))], ); } fn benchmark_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.add_mul(y, z)))], ); } fn benchmark_add_mul_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, primitive_float_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_primitive_float_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.add_mul(y, z)))], ); } fn benchmark_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.add_mul_assign(y, z))], ); } fn benchmark_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.add_mul_assign(y, z))], ); } fn benchmark_add_mul_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, primitive_float_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_primitive_float_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.add_mul_assign(y, z))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/arithmetic_checked_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{pair_2_bucketer, pair_2_unsigned_abs_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen_var_2, signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, unsigned_signed_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_arithmetic_checked_shl_unsigned_unsigned); register_unsigned_signed_demos!(runner, demo_arithmetic_checked_shl_unsigned_signed); register_signed_unsigned_demos!(runner, demo_arithmetic_checked_shl_signed_unsigned); register_signed_signed_demos!(runner, demo_arithmetic_checked_shl_signed_signed); register_unsigned_unsigned_benches!(runner, benchmark_arithmetic_checked_shl_unsigned_unsigned); register_unsigned_signed_benches!(runner, benchmark_arithmetic_checked_shl_unsigned_signed); register_signed_unsigned_benches!(runner, benchmark_arithmetic_checked_shl_signed_unsigned); register_signed_signed_benches!(runner, benchmark_arithmetic_checked_shl_signed_signed); } fn demo_arithmetic_checked_shl_unsigned_unsigned< T: ArithmeticCheckedShl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}.arithmetic_checked_shl({}) = {:?}", n, u, n.arithmetic_checked_shl(u) ); } } fn demo_arithmetic_checked_shl_unsigned_signed< T: ArithmeticCheckedShl + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in unsigned_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.arithmetic_checked_shl({}) = {:?}", n, i, n.arithmetic_checked_shl(i) ); } } fn demo_arithmetic_checked_shl_signed_unsigned< T: ArithmeticCheckedShl + PrimitiveSigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "({}).arithmetic_checked_shl({}) = {:?}", n, u, n.arithmetic_checked_shl(u) ); } } fn demo_arithmetic_checked_shl_signed_signed< T: ArithmeticCheckedShl + PrimitiveSigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in signed_pair_gen_var_2::().get(gm, config).take(limit) { println!( "({}).arithmetic_checked_shl({}) = {:?}", n, i, n.arithmetic_checked_shl(i) ); } } fn benchmark_arithmetic_checked_shl_unsigned_unsigned< T: ArithmeticCheckedShl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.arithmetic_checked_shl({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shl(y)); })], ); } fn benchmark_arithmetic_checked_shl_unsigned_signed< T: ArithmeticCheckedShl + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.arithmetic_checked_shl({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_unsigned_abs_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shl(y)); })], ); } fn benchmark_arithmetic_checked_shl_signed_unsigned< T: ArithmeticCheckedShl + PrimitiveSigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.arithmetic_checked_shl({})", T::NAME, U::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shl(y)); })], ); } fn benchmark_arithmetic_checked_shl_signed_signed< T: ArithmeticCheckedShl + PrimitiveSigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.arithmetic_checked_shl({})", T::NAME, U::NAME), BenchmarkType::Single, signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_unsigned_abs_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shl(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/arithmetic_checked_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShr, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_unsigned_abs_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen_var_2, unsigned_signed_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_signed_demos!(runner, demo_arithmetic_checked_shr_unsigned_signed); register_signed_signed_demos!(runner, demo_arithmetic_checked_shr_signed_signed); register_unsigned_signed_benches!(runner, benchmark_arithmetic_checked_shr_unsigned_signed); register_signed_signed_benches!(runner, benchmark_arithmetic_checked_shr_signed_signed); } fn demo_arithmetic_checked_shr_unsigned_signed< T: ArithmeticCheckedShr + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in unsigned_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.arithmetic_checked_shr({}) = {:?}", n, i, n.arithmetic_checked_shr(i) ); } } fn demo_arithmetic_checked_shr_signed_signed< T: ArithmeticCheckedShr + PrimitiveSigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in signed_pair_gen_var_2::().get(gm, config).take(limit) { println!( "({}).arithmetic_checked_shr({}) = {:?}", n, i, n.arithmetic_checked_shr(i) ); } } fn benchmark_arithmetic_checked_shr_unsigned_signed< T: ArithmeticCheckedShr + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.arithmetic_checked_shr({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_unsigned_abs_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shr(y)); })], ); } fn benchmark_arithmetic_checked_shr_signed_signed< T: ArithmeticCheckedShr + PrimitiveSigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.arithmetic_checked_shr({})", T::NAME, U::NAME), BenchmarkType::Single, signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_unsigned_abs_bucketer("other"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.arithmetic_checked_shr(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ abs_usize_convertible_pair_max_bucketer, usize_convertible_pair_max_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen_var_11, signed_pair_gen_var_12, unsigned_pair_gen_var_28, unsigned_pair_gen_var_44, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_binomial_coefficient_unsigned); register_signed_demos!(runner, demo_binomial_coefficient_signed); register_unsigned_demos!(runner, demo_checked_binomial_coefficient_unsigned); register_signed_demos!(runner, demo_checked_binomial_coefficient_signed); register_unsigned_benches!(runner, benchmark_binomial_coefficient_unsigned); register_signed_benches!(runner, benchmark_binomial_coefficient_signed); register_unsigned_benches!(runner, benchmark_checked_binomial_coefficient_unsigned); register_signed_benches!(runner, benchmark_checked_binomial_coefficient_signed); } fn demo_binomial_coefficient_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_44().get(gm, config).take(limit) { println!("C({}, {}) = {}", n, k, T::binomial_coefficient(n, k)); } } fn demo_binomial_coefficient_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in signed_pair_gen_var_12().get(gm, config).take(limit) { println!("C({}, {}) = {}", n, k, T::binomial_coefficient(n, k)); } } fn demo_checked_binomial_coefficient_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_28().get(gm, config).take(limit) { println!( "C({}, {}) = {:?}", n, k, T::checked_binomial_coefficient(n, k) ); } } fn demo_checked_binomial_coefficient_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in signed_pair_gen_var_11().get(gm, config).take(limit) { println!( "C({}, {}) = {:?}", n, k, T::checked_binomial_coefficient(n, k) ); } } fn benchmark_binomial_coefficient_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!( "{}::binomial_coefficient({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_44().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_max_bucketer("n", "k"), &mut [("Malachite", &mut |(n, k)| { no_out!(T::binomial_coefficient(n, k)); })], ); } fn benchmark_binomial_coefficient_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, ::Output: Ord, { run_benchmark( &format!( "{}::binomial_coefficient({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_pair_gen_var_12().get(gm, config), gm.name(), limit, file_name, &abs_usize_convertible_pair_max_bucketer("n", "k"), &mut [("Malachite", &mut |(n, k)| { no_out!(T::binomial_coefficient(n, k)); })], ); } fn benchmark_checked_binomial_coefficient_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!( "{}::checked_binomial_coefficient({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_28().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_max_bucketer("n", "k"), &mut [("Malachite", &mut |(n, k)| { no_out!(T::checked_binomial_coefficient(n, k)); })], ); } fn benchmark_checked_binomial_coefficient_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, ::Output: Ord, { run_benchmark( &format!( "{}::checked_binomial_coefficient({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &abs_usize_convertible_pair_max_bucketer("n", "k"), &mut [("Malachite", &mut |(n, k)| { no_out!(T::checked_binomial_coefficient(n, k)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_ceiling_assign); register_primitive_float_benches!(runner, benchmark_ceiling_assign); } fn demo_ceiling_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.ceiling_assign(); println!( "i := {}; i.ceiling_assign(); i = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_ceiling_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.ceiling_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/checked_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_checked_add_mul_unsigned); register_signed_demos!(runner, demo_checked_add_mul_signed); register_unsigned_benches!(runner, benchmark_checked_add_mul_unsigned); register_signed_benches!(runner, benchmark_checked_add_mul_signed); } fn demo_checked_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.checked_add_mul({}, {}) = {:?}", x, y, z, x.checked_add_mul(y, z) ); } } fn demo_checked_add_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "({}).checked_add_mul({}, {}) = {:?}", x, y, z, x.checked_add_mul(y, z) ); } } fn benchmark_checked_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.checked_add_mul(y, z)); })], ); } fn benchmark_checked_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.checked_add_mul(y, z)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/checked_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_checked_square_unsigned); register_signed_demos!(runner, demo_checked_square_signed); register_unsigned_benches!(runner, benchmark_checked_square_unsigned); register_signed_benches!(runner, benchmark_checked_square_signed); } fn demo_checked_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("{}.checked_square() = {:?}", x, x.checked_square()); } } fn demo_checked_square_signed(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen::().get(gm, config).take(limit) { println!("({}).checked_square() = {:?}", x, x.checked_square()); } } fn benchmark_checked_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_square()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.checked_square()))], ); } fn benchmark_checked_square_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_square()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.checked_square()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_checked_sub_mul_unsigned); register_signed_demos!(runner, demo_checked_sub_mul_signed); register_unsigned_benches!(runner, benchmark_checked_sub_mul_unsigned); register_signed_benches!(runner, benchmark_checked_sub_mul_signed); } fn demo_checked_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.checked_sub_mul({}, {}) = {:?}", x, y, z, x.checked_sub_mul(y, z) ); } } fn demo_checked_sub_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "({}).checked_sub_mul({}, {}) = {:?}", x, y, z, x.checked_sub_mul(y, z) ); } } fn benchmark_checked_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.checked_sub_mul(y, z)); })], ); } fn benchmark_checked_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.checked_sub_mul(y, z)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::coprime_with::{ coprime_with_check_2, coprime_with_check_2_3, coprime_with_check_2_3_5, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_coprime_with); register_unsigned_benches!(runner, benchmark_coprime_with_algorithms); } fn demo_coprime_with(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { if x.coprime_with(y) { println!("{x} is coprime with {y}"); } else { println!("{x} is not coprime with {y}"); } } } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_coprime_with_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.coprime_with({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.coprime_with(y))), ("no divisibility check", &mut |(x, y)| { no_out!(x.gcd(y) == T::ONE); }), ("check divisibility by 2", &mut |(x, y)| { no_out!(coprime_with_check_2(x, y)); }), ("check divisibility by 2 and 3", &mut |(x, y)| { no_out!(coprime_with_check_2_3(x, y)); }), ("check divisibility by 2, 3, and 5", &mut |(x, y)| { no_out!(coprime_with_check_2_3_5(x, y)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen_var_3, unsigned_pair_gen_var_11}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_div_exact_unsigned); register_signed_demos!(runner, demo_div_exact_signed); register_unsigned_demos!(runner, demo_div_exact_assign_unsigned); register_signed_demos!(runner, demo_div_exact_assign_signed); register_unsigned_benches!(runner, benchmark_div_exact_unsigned); register_signed_benches!(runner, benchmark_div_exact_signed); register_unsigned_benches!(runner, benchmark_div_exact_assign_unsigned); register_signed_benches!(runner, benchmark_div_exact_assign_signed); } fn demo_div_exact_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_11::().get(gm, config).take(limit) { println!("{}.div_exact({}) = {}", x, y, x.div_exact(y)); } } fn demo_div_exact_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_3::().get(gm, config).take(limit) { println!("({}).div_exact({}) = {}", x, y, x.div_exact(y)); } } fn demo_div_exact_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_11::().get(gm, config).take(limit) { let old_x = x; x.div_exact_assign(y); println!("x := {old_x}; x.div_exact_assign({y}); x = {x}"); } } fn demo_div_exact_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_3::().get(gm, config).take(limit) { let old_x = x; x.div_exact_assign(y); println!("x := {old_x}; x.div_exact_assign({y}); x = {x}"); } } fn benchmark_div_exact_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_exact({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.div_exact(y)))], ); } fn benchmark_div_exact_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_exact({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.div_exact(y)))], ); } fn benchmark_div_exact_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_exact_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.div_exact_assign(y))], ); } fn benchmark_div_exact_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_exact_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.div_exact_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen_var_4, unsigned_pair_gen_var_12}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_div_mod_unsigned); register_signed_demos!(runner, demo_div_mod_signed); register_unsigned_demos!(runner, demo_div_assign_mod_unsigned); register_signed_demos!(runner, demo_div_assign_mod_signed); register_unsigned_demos!(runner, demo_div_rem_unsigned); register_signed_demos!(runner, demo_div_rem_signed); register_unsigned_demos!(runner, demo_div_assign_rem_unsigned); register_signed_demos!(runner, demo_div_assign_rem_signed); register_unsigned_demos!(runner, demo_ceiling_div_neg_mod); register_unsigned_demos!(runner, demo_ceiling_div_assign_neg_mod); register_signed_demos!(runner, demo_ceiling_div_mod); register_signed_demos!(runner, demo_ceiling_div_assign_mod); register_unsigned_benches!(runner, benchmark_div_mod_unsigned_algorithms); register_signed_benches!(runner, benchmark_div_mod_signed_algorithms); register_unsigned_benches!(runner, benchmark_div_assign_mod_unsigned); register_signed_benches!(runner, benchmark_div_assign_mod_signed); register_unsigned_benches!(runner, benchmark_div_rem_unsigned_algorithms); register_signed_benches!(runner, benchmark_div_rem_signed_algorithms); register_unsigned_benches!(runner, benchmark_div_assign_rem_unsigned); register_signed_benches!(runner, benchmark_div_assign_rem_signed); register_unsigned_benches!(runner, benchmark_ceiling_div_neg_mod_algorithms); register_unsigned_benches!(runner, benchmark_ceiling_div_assign_neg_mod); register_signed_benches!(runner, benchmark_ceiling_div_mod_algorithms); register_signed_benches!(runner, benchmark_ceiling_div_assign_mod); } fn demo_div_mod_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.div_mod({}) = {:?}", x, y, x.div_mod(y)); } } fn demo_div_mod_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { println!("({}).div_mod({}) = {:?}", x, y, x.div_mod(y)); } } fn demo_div_assign_mod_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; let r = x.div_assign_mod(y); println!("x := {old_x}; x.div_assign_mod({y}) = {r}; x = {x}"); } } fn demo_div_assign_mod_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { let old_x = x; let r = x.div_assign_mod(y); println!("x := {old_x}; x.div_assign_mod({y}) = {r}; x = {x}"); } } fn demo_div_rem_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.div_rem({}) = {:?}", x, y, x.div_rem(y)); } } fn demo_div_rem_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { println!("({}).div_rem({}) = {:?}", x, y, x.div_rem(y)); } } fn demo_div_assign_rem_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; let r = x.div_assign_rem(y); println!("x := {old_x}; x.div_assign_rem({y}) = {r}; x = {x}"); } } fn demo_div_assign_rem_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { let old_x = x; let r = x.div_assign_rem(y); println!("x := {old_x}; x.div_assign_rem({y}) = {r}; x = {x}"); } } fn demo_ceiling_div_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "{}.ceiling_div_neg_mod({}) = {:?}", x, y, x.ceiling_div_neg_mod(y) ); } } fn demo_ceiling_div_assign_neg_mod( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; let r = x.ceiling_div_assign_neg_mod(y); println!("x := {old_x}; x.ceiling_div_assign_neg_mod({y}) = {r}; x = {x}"); } } fn demo_ceiling_div_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { println!( "({}).ceiling_div_mod({}) = {:?}", x, y, x.ceiling_div_mod(y) ); } } fn demo_ceiling_div_assign_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_4::().get(gm, config).take(limit) { let old_x = x; let r = x.ceiling_div_assign_mod(y); println!("x := {old_x}; x.ceiling_div_assign_mod({y}) = {r}; x = {x}"); } } #[allow(clippy::no_effect)] fn benchmark_div_mod_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y))), ("using / and %", &mut |(x, y)| no_out!((x / y, x % y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_div_mod_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y))), ("using div_round and mod_op", &mut |(x, y)| { no_out!((x.div_round(y, Floor), x.mod_op(y))); }), ], ); } fn benchmark_div_assign_mod_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_assign_mod({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x.div_assign_mod(y)))], ); } fn benchmark_div_assign_mod_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_assign_mod({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x.div_assign_mod(y)))], ); } #[allow(clippy::no_effect)] fn benchmark_div_rem_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_rem({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using div_rem", &mut |(x, y)| no_out!(x.div_rem(y))), ("using / and %", &mut |(x, y)| no_out!((x / y, x % y))), ], ); } #[allow(clippy::no_effect)] fn benchmark_div_rem_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_rem({})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using div_rem", &mut |(x, y)| no_out!(x.div_rem(y))), ("using / and %", &mut |(x, y)| no_out!((x / y, x % y))), ], ); } fn benchmark_div_assign_rem_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_assign_rem({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x.div_assign_rem(y)))], ); } fn benchmark_div_assign_rem_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_assign_rem({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x.div_assign_rem(y)))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_ceiling_div_neg_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_div_neg_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using ceiling_div_neg_mod", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(y)); }), ("using div_round and neg_mod", &mut |(x, y)| { no_out!((x.div_round(y, Ceiling), x.neg_mod(y))); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_ceiling_div_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_div_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using ceiling_div_mod", &mut |(x, y)| { no_out!(x.ceiling_div_mod(y)); }), ("using div_round and ceiling_mod", &mut |(x, y)| { no_out!((x.div_round(y, Ceiling), x.ceiling_mod(y))); }), ], ); } fn benchmark_ceiling_div_assign_neg_mod( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_div_assign_neg_mod({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.ceiling_div_assign_neg_mod(y)); })], ); } fn benchmark_ceiling_div_assign_mod( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_div_assign_mod({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.ceiling_div_assign_mod(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_1_2_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_signed_rounding_mode_triple_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_div_round_unsigned); register_signed_demos!(runner, demo_div_round_signed); register_unsigned_demos!(runner, demo_div_round_assign_unsigned); register_signed_demos!(runner, demo_div_round_assign_signed); register_unsigned_benches!(runner, benchmark_div_round_unsigned); register_signed_benches!(runner, benchmark_div_round_signed); register_unsigned_benches!(runner, benchmark_div_round_assign_unsigned); register_signed_benches!(runner, benchmark_div_round_assign_signed); } fn demo_div_round_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!("{}.div_round({}, {}) = {:?}", x, y, rm, x.div_round(y, rm)); } } fn demo_div_round_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in signed_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "({}).div_round({}, {}) = {:?}", x, y, rm, x.div_round(y, rm) ); } } fn demo_div_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_x = x; let o = x.div_round_assign(y, rm); println!("x := {old_x}; x.div_round_assign({y}, {rm}) = {o:?}; x = {x}"); } } fn demo_div_round_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in signed_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_x = x; let o = x.div_round_assign(y, rm); println!("x := {old_x}; x.div_round_assign({y}, {rm}) = {o:?}; x = {x}"); } } fn benchmark_div_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_round({}, RoundingMode)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, rm)| no_out!(x.div_round(y, rm)))], ); } fn benchmark_div_round_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_round({}, RoundingMode)", T::NAME, T::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, rm)| no_out!(x.div_round(y, rm)))], ); } fn benchmark_div_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_round_assign({}, RoundingMode)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.div_round_assign(y, rm)); })], ); } fn benchmark_div_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.div_round_assign({}, RoundingMode)", T::NAME, T::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.div_round_assign(y, rm)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_divisible_by_unsigned); register_signed_demos!(runner, demo_divisible_by_signed); register_unsigned_benches!(runner, benchmark_divisible_by_unsigned); register_signed_benches!(runner, benchmark_divisible_by_signed); } fn demo_divisible_by_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { if x.divisible_by(y) { println!("{x} is divisible by {y}"); } else { println!("{x} is not divisible by {y}"); } } } fn demo_divisible_by_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { if x.divisible_by(y) { println!("{x} is divisible by {y}"); } else { println!("{x} is not divisible by {y}"); } } } fn benchmark_divisible_by_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.divisible_by({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.divisible_by(y)))], ); } fn benchmark_divisible_by_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.divisible_by({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.divisible_by(y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_divisible_by_power_of_2_unsigned); register_signed_demos!(runner, demo_divisible_by_power_of_2_signed); register_unsigned_benches!(runner, benchmark_divisible_by_power_of_2_unsigned); register_signed_benches!(runner, benchmark_divisible_by_power_of_2_signed); } fn demo_divisible_by_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (u, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { if u.divisible_by_power_of_2(pow) { println!("{u} is divisible by 2^{pow}"); } else { println!("{u} is not divisible by 2^{pow}"); } } } fn demo_divisible_by_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (i, pow) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { if i.divisible_by_power_of_2(pow) { println!("{i} is divisible by 2^{pow}"); } else { println!("{i} is not divisible by 2^{pow}"); } } } fn benchmark_divisible_by_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.divisible_by_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.divisible_by_power_of_2(y)); })], ); } fn benchmark_divisible_by_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.divisible_by_power_of_2(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("i"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.divisible_by_power_of_2(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_eq_mod_unsigned); register_signed_demos!(runner, demo_eq_mod_signed); register_unsigned_benches!(runner, benchmark_eq_mod_unsigned); register_signed_benches!(runner, benchmark_eq_mod_signed); } fn demo_eq_mod_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { if x.eq_mod(y, z) { println!("{x} is equal to {y} mod {z}"); } else { println!("{x} is not equal to {y} mod {z}"); } } } fn demo_eq_mod_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { if x.eq_mod(y, z) { println!("{x} is equal to {y} mod {z}"); } else { println!("{x} is not equal to {y} mod {z}"); } } } fn benchmark_eq_mod_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_mod({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.eq_mod(y, z)))], ); } fn benchmark_eq_mod_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_mod({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.eq_mod(y, z)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_1_2_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_signed_unsigned_triple_gen_var_2, unsigned_triple_gen_var_4, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_eq_mod_power_of_2_unsigned); register_signed_demos!(runner, demo_eq_mod_power_of_2_signed); register_unsigned_benches!(runner, benchmark_eq_mod_power_of_2_unsigned); register_signed_benches!(runner, benchmark_eq_mod_power_of_2_signed); } fn demo_eq_mod_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, pow) in unsigned_triple_gen_var_4::() .get(gm, config) .take(limit) { if x.eq_mod_power_of_2(y, pow) { println!("{x} is equal to {y} mod 2^{pow}"); } else { println!("{x} is not equal to {y} mod 2^{pow}"); } } } fn demo_eq_mod_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, pow) in signed_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { if x.eq_mod_power_of_2(y, pow) { println!("{x} is equal to {y} mod 2^{pow}"); } else { println!("{x} is not equal to {y} mod 2^{pow}"); } } } fn benchmark_eq_mod_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_mod_power_of_2({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.eq_mod_power_of_2(y, pow)); })], ); } fn benchmark_eq_mod_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_mod_power_of_2({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, signed_signed_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.eq_mod_power_of_2(y, pow)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::extended_gcd::extended_gcd_unsigned_binary; use malachite_base::num::arithmetic::traits::ExtendedGcd; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::num::arithmetic::extended_gcd::extended_gcd_unsigned_euclidean; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_signed_match_demos!(runner, demo_extended_gcd_unsigned); register_unsigned_signed_match_demos!(runner, demo_extended_gcd_signed); register_unsigned_signed_match_benches!(runner, benchmark_extended_gcd_algorithms_unsigned); register_signed_benches!(runner, benchmark_extended_gcd_signed); } fn demo_extended_gcd_unsigned< U: ExtendedGcd + PrimitiveUnsigned, S: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.extended_gcd({}) = {:?}", x, y, x.extended_gcd(y)); } } fn demo_extended_gcd_signed + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("{}.extended_gcd({}) = {:?}", x, y, x.extended_gcd(y)); } } fn benchmark_extended_gcd_algorithms_unsigned< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.extended_gcd({})", U::NAME, U::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.extended_gcd(y))), ("Euclidean", &mut |(x, y)| { no_out!(extended_gcd_unsigned_euclidean::(x, y)); }), ("binary", &mut |(x, y)| { no_out!(extended_gcd_unsigned_binary::(x, y)); }), ], ); } fn benchmark_extended_gcd_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.extended_gcd({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("default", &mut |(x, y)| no_out!(x.extended_gcd(y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::factorial::checked_multifactorial_naive; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ unsigned_direct_bucketer, usize_convertible_pair_max_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_23, unsigned_gen_var_24, unsigned_gen_var_25, unsigned_pair_gen_var_12, unsigned_pair_gen_var_43, }; use malachite_base::test_util::num::arithmetic::factorial::{ checked_double_factorial_naive, checked_factorial_naive, checked_subfactorial_naive, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_factorial); register_unsigned_demos!(runner, demo_checked_factorial); register_unsigned_demos!(runner, demo_double_factorial); register_unsigned_demos!(runner, demo_checked_double_factorial); register_unsigned_demos!(runner, demo_multifactorial); register_unsigned_demos!(runner, demo_checked_multifactorial); register_unsigned_demos!(runner, demo_subfactorial); register_unsigned_demos!(runner, demo_checked_subfactorial); register_unsigned_benches!(runner, benchmark_factorial_algorithms); register_unsigned_benches!(runner, benchmark_checked_factorial); register_unsigned_benches!(runner, benchmark_double_factorial_algorithms); register_unsigned_benches!(runner, benchmark_checked_double_factorial); register_unsigned_benches!(runner, benchmark_multifactorial_algorithms); register_unsigned_benches!(runner, benchmark_checked_multifactorial); register_unsigned_benches!(runner, benchmark_subfactorial_algorithms); register_unsigned_benches!(runner, benchmark_checked_subfactorial); } fn demo_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_23::().get(gm, config).take(limit) { println!("{}! = {}", n, T::factorial(n)); } } fn demo_checked_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen().get(gm, config).take(limit) { println!("{}! = {:?}", n, T::checked_factorial(n)); } } fn demo_double_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_24::().get(gm, config).take(limit) { println!("{}!! = {}", n, T::double_factorial(n)); } } fn demo_checked_double_factorial( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen().get(gm, config).take(limit) { println!("{}!! = {:?}", n, T::checked_double_factorial(n)); } } fn demo_multifactorial(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in unsigned_pair_gen_var_43::().get(gm, config).take(limit) { if m <= 5 { print!("{n}"); for _ in 0..m { print!("!"); } println!(" = {}", T::multifactorial(n, m)); } else { println!("{}[!^{}] = {}", n, m, T::multifactorial(n, m)); } } } fn demo_checked_multifactorial( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, m) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { if m <= 5 { print!("{n}"); for _ in 0..m { print!("!"); } println!(" = {:?}", T::checked_multifactorial(n, m)); } else { println!("{}[!^{}] = {:?}", n, m, T::checked_multifactorial(n, m)); } } } fn demo_subfactorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_25::().get(gm, config).take(limit) { println!("!{} = {}", n, T::subfactorial(n)); } } fn demo_checked_subfactorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen().get(gm, config).take(limit) { println!("!{} = {:?}", n, T::checked_subfactorial(n)); } } fn benchmark_factorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::factorial(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_23::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::factorial(n))), ("naive", &mut |n| { no_out!(checked_factorial_naive::(n).unwrap()); }), ], ); } fn benchmark_checked_factorial( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_factorial(u64)", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::checked_factorial(n)))], ); } fn benchmark_double_factorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::double_factorial(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_24::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::double_factorial(n))), ("naive", &mut |n| { no_out!(checked_double_factorial_naive::(n).unwrap()); }), ], ); } fn benchmark_checked_double_factorial( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_double_factorial(u64)", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| { no_out!(T::checked_double_factorial(n)); })], ); } fn benchmark_multifactorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::multifactorial(u64, u64)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_43::().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_max_bucketer("n", "m"), &mut [ ("default", &mut |(n, m)| no_out!(T::multifactorial(n, m))), ("naive", &mut |(n, m)| { no_out!(checked_multifactorial_naive::(n, m).unwrap()); }), ], ); } fn benchmark_checked_multifactorial( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_multifactorial(u64, u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_max_bucketer("n", "m"), &mut [("Malachite", &mut |(n, m)| { no_out!(T::checked_multifactorial(n, m)); })], ); } fn benchmark_subfactorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::subfactorial(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_25::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::subfactorial(n))), ("naive", &mut |n| { no_out!(checked_subfactorial_naive::(n).unwrap()); }), ], ); } fn benchmark_checked_subfactorial( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_subfactorial(u64)", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::checked_subfactorial(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/floor.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_floor_assign); register_primitive_float_benches!(runner, benchmark_floor_assign); } fn demo_floor_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.floor_assign(); println!( "i := {}; i.floor_assign(); i = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_floor_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.floor_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::gcd::{gcd_binary, gcd_euclidean, gcd_fast_a, gcd_fast_b}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_gcd); register_unsigned_demos!(runner, demo_gcd_assign); register_unsigned_benches!(runner, benchmark_gcd_algorithms); register_unsigned_benches!(runner, benchmark_gcd_assign); } fn demo_gcd(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.gcd({}) = {}", x, y, x.gcd(y)); } } fn demo_gcd_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.gcd_assign(y); println!("x := {old_x}; x.gcd_assign({y}); x = {x}"); } } fn benchmark_gcd_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gcd({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.gcd(y))), ("Euclidean", &mut |(x, y)| no_out!(gcd_euclidean(x, y))), ("binary", &mut |(x, y)| no_out!(gcd_binary(x, y))), ("fast A", &mut |(x, y)| no_out!(gcd_fast_a(x, y))), ("fast B", &mut |(x, y)| no_out!(gcd_fast_b(x, y))), ], ); } fn benchmark_gcd_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gcd_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.gcd_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_is_power_of_2); register_primitive_float_benches!(runner, benchmark_is_power_of_2); } fn demo_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for f in primitive_float_gen::().get(gm, config).take(limit) { if f.is_power_of_2() { println!("{} is a power of 2", NiceFloat(f)); } else { println!("{} is not a power of 2", NiceFloat(f)); } } } fn benchmark_is_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_power_of_2()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(f.is_power_of_2()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::kronecker_symbol::{ jacobi_symbol_unsigned_double_fast_2, jacobi_symbol_unsigned_simple, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, WrappingFrom}; use malachite_base::test_util::bench::bucketers::{ pair_max_bit_bucketer, quadruple_max_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen, signed_pair_gen_var_8, unsigned_pair_gen_var_27, unsigned_pair_gen_var_40, unsigned_quadruple_gen_var_12, }; use malachite_base::test_util::num::arithmetic::kronecker_symbol::{ jacobi_symbol_unsigned_double_fast_1, jacobi_symbol_unsigned_double_simple, jacobi_symbol_unsigned_fast_1, jacobi_symbol_unsigned_fast_2_1, jacobi_symbol_unsigned_fast_2_2, jacobi_symbol_unsigned_fast_2_3, jacobi_symbol_unsigned_fast_2_4, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_jacobi_symbol_unsigned_double_fast_1); register_unsigned_demos!(runner, demo_jacobi_symbol_unsigned_double_fast_2); register_unsigned_demos!(runner, demo_jacobi_symbol_unsigned); register_unsigned_signed_match_demos!(runner, demo_jacobi_symbol_signed); register_unsigned_demos!(runner, demo_kronecker_symbol_unsigned); register_signed_demos!(runner, demo_kronecker_symbol_signed); register_generic_benches_2!( runner, benchmark_jacobi_symbol_unsigned_double_algorithms, [u8, u16], [u16, u32], [u32, u64], [u64, u128] ); register_unsigned_benches!(runner, benchmark_jacobi_symbol_unsigned_algorithms); register_unsigned_signed_match_benches!(runner, benchmark_jacobi_symbol_signed); register_unsigned_benches!(runner, benchmark_kronecker_symbol_unsigned); register_signed_benches!(runner, benchmark_kronecker_symbol_signed); } fn demo_jacobi_symbol_unsigned_double_fast_1( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x1, x0, y1, y0) in unsigned_quadruple_gen_var_12::() .get(gm, config) .take(limit) { println!( "jacobi_symbol_unsigned_double_fast_1({}, {}, {}, {}) = {}", x1, x0, y1, y0, jacobi_symbol_unsigned_double_fast_1(x1, x0, y1, y0) ); } } fn demo_jacobi_symbol_unsigned_double_fast_2( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x1, x0, y1, y0) in unsigned_quadruple_gen_var_12::() .get(gm, config) .take(limit) { println!( "jacobi_symbol_unsigned_double_fast_1({}, {}, {}, {}) = {}", x1, x0, y1, y0, jacobi_symbol_unsigned_double_fast_2(x1, x0, y1, y0) ); } } fn demo_jacobi_symbol_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_40::().get(gm, config).take(limit) { println!("{}.jacobi_symbol({}) = {}", x, y, x.jacobi_symbol(y)); } } fn demo_jacobi_symbol_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in signed_pair_gen_var_8::().get(gm, config).take(limit) { println!("({}).jacobi_symbol({}) = {}", x, y, x.jacobi_symbol(y)); } } fn demo_kronecker_symbol_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.kronecker_symbol({}) = {}", x, y, x.kronecker_symbol(y)); } } fn demo_kronecker_symbol_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).kronecker_symbol({}) = {}", x, y, x.kronecker_symbol(y) ); } } fn benchmark_jacobi_symbol_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.jacobi_symbol({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_40::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.jacobi_symbol(y))), ("simple", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_simple(x, y)); }), ("fast 1", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_fast_1(x, y)); }), ("fast 2.1", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_fast_2_1(x, y)); }), ("fast 2.2", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_fast_2_2(x, y)); }), ("fast 2.3", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_fast_2_3(x, y)); }), ("fast 2.4", &mut |(x, y)| { no_out!(jacobi_symbol_unsigned_fast_2_4(x, y)); }), ], ); } fn benchmark_jacobi_symbol_unsigned_double_algorithms< T: PrimitiveUnsigned, D: HasHalf + JoinHalves + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "jacobi_symbol_unsigned_double({}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_quadruple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &quadruple_max_bit_bucketer("x1", "x0", "y1", "y0"), &mut [ ("simple", &mut |(x1, x0, y1, y0)| { no_out!(jacobi_symbol_unsigned_double_simple::(x1, x0, y1, y0)); }), ("fast 1", &mut |(x1, x0, y1, y0)| { no_out!(jacobi_symbol_unsigned_double_fast_1(x1, x0, y1, y0)); }), ("fast 2", &mut |(x1, x0, y1, y0)| { no_out!(jacobi_symbol_unsigned_double_fast_2(x1, x0, y1, y0)); }), ], ); } fn benchmark_jacobi_symbol_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.jacobi_symbol({})", S::NAME, S::NAME), BenchmarkType::Single, signed_pair_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("default", &mut |(x, y)| no_out!(x.jacobi_symbol(y)))], ); } fn benchmark_kronecker_symbol_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.kronecker_symbol({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.kronecker_symbol(y)))], ); } fn benchmark_kronecker_symbol_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.kronecker_symbol({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("default", &mut |(x, y)| no_out!(x.kronecker_symbol(y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_pair_gen_var_33, unsigned_pair_gen_var_34}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_lcm); register_unsigned_demos!(runner, demo_lcm_assign); register_unsigned_demos!(runner, demo_checked_lcm); register_unsigned_benches!(runner, benchmark_lcm); register_unsigned_benches!(runner, benchmark_lcm_assign); register_unsigned_benches!(runner, benchmark_checked_lcm); } fn demo_lcm(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_34::().get(gm, config).take(limit) { println!("{}.lcm({}) = {}", x, y, x.lcm(y)); } } fn demo_lcm_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_34::().get(gm, config).take(limit) { let old_x = x; x.lcm_assign(y); println!("x := {old_x}; x.lcm_assign({y}); x = {x}"); } } fn demo_checked_lcm(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_33::().get(gm, config).take(limit) { println!("{}.checked_lcm({}) = {:?}", x, y, x.checked_lcm(y)); } } fn benchmark_lcm( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lcm({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_34::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lcm(y)))], ); } fn benchmark_lcm_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lcm_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_34::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.lcm_assign(y))], ); } fn benchmark_checked_lcm( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_lcm({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_33::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.checked_lcm(y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::log_base::{ceiling_log_base_naive, checked_log_base_naive}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_24; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_floor_log_base); register_unsigned_demos!(runner, demo_ceiling_log_base); register_unsigned_demos!(runner, demo_checked_log_base); register_unsigned_benches!(runner, benchmark_floor_log_base); register_unsigned_benches!(runner, benchmark_ceiling_log_base_algorithms); register_unsigned_benches!(runner, benchmark_checked_log_base_algorithms); } fn demo_floor_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, b) in unsigned_pair_gen_var_24::() .get(gm, config) .take(limit) { println!("{}.floor_log_base({}) = {}", n, b, n.floor_log_base(b)); } } fn demo_ceiling_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, b) in unsigned_pair_gen_var_24::() .get(gm, config) .take(limit) { println!("{}.ceiling_log_base({}) = {}", n, b, n.ceiling_log_base(b)); } } fn demo_checked_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, b) in unsigned_pair_gen_var_24::() .get(gm, config) .take(limit) { println!( "{}.checked_log_base({}) = {:?}", n, b, n.checked_log_base(b) ); } } fn benchmark_floor_log_base( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_log_base({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_24::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, base)| { no_out!(n.floor_log_base(base)); })], ); } fn benchmark_ceiling_log_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_log_base({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_24::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [ ("default", &mut |(n, base)| { no_out!(n.ceiling_log_base(base)); }), ("naive", &mut |(n, base)| { no_out!(ceiling_log_base_naive(n, base)); }), ], ); } fn benchmark_checked_log_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_log_base({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_24::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [ ("default", &mut |(n, base)| { no_out!(n.checked_log_base(base)); }), ("naive", &mut |(n, base)| { no_out!(checked_log_base_naive(n, base)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, primitive_int_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen_var_18, unsigned_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_floor_log_base_2_unsigned); register_unsigned_demos!(runner, demo_ceiling_log_base_2_unsigned); register_unsigned_demos!(runner, demo_checked_log_base_2_unsigned); register_primitive_float_demos!(runner, demo_floor_log_base_2_primitive_float); register_primitive_float_demos!(runner, demo_ceiling_log_base_2_primitive_float); register_primitive_float_demos!(runner, demo_checked_log_base_2_primitive_float); register_unsigned_benches!(runner, benchmark_floor_log_base_2_unsigned); register_unsigned_benches!(runner, benchmark_ceiling_log_base_2_unsigned); register_unsigned_benches!(runner, benchmark_checked_log_base_2_unsigned); register_primitive_float_benches!(runner, benchmark_floor_log_base_2_primitive_float); register_primitive_float_benches!(runner, benchmark_ceiling_log_base_2_primitive_float); register_primitive_float_benches!(runner, benchmark_checked_log_base_2_primitive_float); } fn demo_floor_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_1::().get(gm, config).take(limit) { println!("{}.floor_log_base_2() = {}", n, n.floor_log_base_2()); } } fn demo_ceiling_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_1::().get(gm, config).take(limit) { println!("{}.ceiling_log_base_2() = {}", n, n.ceiling_log_base_2()); } } fn demo_checked_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_1::().get(gm, config).take(limit) { println!("{}.checked_log_base_2() = {:?}", n, n.checked_log_base_2()); } } fn demo_floor_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in primitive_float_gen_var_18::() .get(gm, config) .take(limit) { println!( "{}.floor_log_base_2() = {}", NiceFloat(n), n.floor_log_base_2() ); } } fn demo_ceiling_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in primitive_float_gen_var_18::() .get(gm, config) .take(limit) { println!( "{}.ceiling_log_base_2() = {}", NiceFloat(n), n.ceiling_log_base_2() ); } } fn demo_checked_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in primitive_float_gen_var_18::() .get(gm, config) .take(limit) { println!( "{}.checked_log_base_2() = {:?}", NiceFloat(n), n.checked_log_base_2() ); } } fn benchmark_floor_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_log_base_2()", T::NAME), BenchmarkType::Single, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.floor_log_base_2()))], ); } fn benchmark_ceiling_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_log_base_2()", T::NAME), BenchmarkType::Single, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.ceiling_log_base_2()))], ); } fn benchmark_checked_log_base_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_log_base_2()", T::NAME), BenchmarkType::Single, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.checked_log_base_2()))], ); } fn benchmark_floor_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_log_base_2()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.floor_log_base_2()))], ); } fn benchmark_ceiling_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_log_base_2()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.ceiling_log_base_2()))], ); } fn benchmark_checked_log_base_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_log_base_2()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.checked_log_base_2()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::log_base_power_of_2::ceiling_log_base_power_of_2_naive; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, pair_1_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_unsigned_pair_gen_var_3, unsigned_pair_gen_var_21, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_floor_log_base_power_of_2_unsigned); register_primitive_float_demos!(runner, demo_floor_log_base_power_of_2_primitive_float); register_unsigned_demos!(runner, demo_ceiling_log_base_power_of_2_unsigned); register_primitive_float_demos!(runner, demo_ceiling_log_base_power_of_2_primitive_float); register_unsigned_demos!(runner, demo_checked_log_base_power_of_2_unsigned); register_primitive_float_demos!(runner, demo_checked_log_base_power_of_2_primitive_float); register_unsigned_benches!(runner, benchmark_floor_log_base_power_of_2_unsigned); register_primitive_float_benches!(runner, benchmark_floor_log_base_power_of_2_primitive_float); register_unsigned_benches!( runner, benchmark_ceiling_log_base_power_of_2_algorithms_unsigned ); register_primitive_float_benches!( runner, benchmark_ceiling_log_base_power_of_2_primitive_float ); register_unsigned_benches!(runner, benchmark_checked_log_base_power_of_2_unsigned); register_primitive_float_benches!( runner, benchmark_checked_log_base_power_of_2_primitive_float ); } fn demo_floor_log_base_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_21::() .get(gm, config) .take(limit) { println!( "{}.floor_log_base_power_of_2({}) = {}", n, pow, n.floor_log_base_power_of_2(pow) ); } } fn demo_floor_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in primitive_float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.floor_log_base_power_of_2({}) = {}", NiceFloat(n), pow, n.floor_log_base_power_of_2(pow) ); } } fn demo_ceiling_log_base_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_21::() .get(gm, config) .take(limit) { println!( "{}.ceiling_log_base_power_of_2({}) = {}", n, pow, n.ceiling_log_base_power_of_2(pow) ); } } fn demo_ceiling_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in primitive_float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.ceiling_log_base_power_of_2({}) = {}", NiceFloat(n), pow, n.ceiling_log_base_power_of_2(pow) ); } } fn demo_checked_log_base_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_21::() .get(gm, config) .take(limit) { println!( "{}.checked_log_base_power_of_2({}) = {:?}", n, pow, n.checked_log_base_power_of_2(pow) ); } } fn demo_checked_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in primitive_float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.checked_log_base_power_of_2({}) = {:?}", NiceFloat(n), pow, n.checked_log_base_power_of_2(pow) ); } } fn benchmark_floor_log_base_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_21::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.floor_log_base_power_of_2(pow)); })], ); } fn benchmark_floor_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.floor_log_base_power_of_2(pow)); })], ); } fn benchmark_ceiling_log_base_power_of_2_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_21::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [ ("default", &mut |(n, pow)| { no_out!(n.ceiling_log_base_power_of_2(pow)); }), ("naive", &mut |(n, pow)| { no_out!(ceiling_log_base_power_of_2_naive(n, pow)); }), ], ); } fn benchmark_ceiling_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.ceiling_log_base_power_of_2(pow)); })], ); } fn benchmark_checked_log_base_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_21::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.checked_log_base_power_of_2(pow)); })], ); } fn benchmark_checked_log_base_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_log_base_power_of_2(u64)", T::NAME), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.checked_log_base_power_of_2(pow)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs::register(runner); abs_diff::register(runner); add_mul::register(runner); arithmetic_checked_shl::register(runner); arithmetic_checked_shr::register(runner); binomial_coefficient::register(runner); ceiling::register(runner); checked_add_mul::register(runner); checked_square::register(runner); checked_sub_mul::register(runner); coprime_with::register(runner); div_exact::register(runner); div_mod::register(runner); div_round::register(runner); divisible_by::register(runner); divisible_by_power_of_2::register(runner); eq_mod::register(runner); eq_mod_power_of_2::register(runner); extended_gcd::register(runner); factorial::register(runner); floor::register(runner); gcd::register(runner); is_power_of_2::register(runner); kronecker_symbol::register(runner); lcm::register(runner); log_base::register(runner); log_base_2::register(runner); log_base_power_of_2::register(runner); mod_inverse::register(runner); mod_is_reduced::register(runner); mod_add::register(runner); mod_mul::register(runner); mod_neg::register(runner); mod_op::register(runner); mod_pow::register(runner); mod_power_of_2::register(runner); mod_power_of_2_add::register(runner); mod_power_of_2_inverse::register(runner); mod_power_of_2_is_reduced::register(runner); mod_power_of_2_mul::register(runner); mod_power_of_2_pow::register(runner); mod_power_of_2_shl::register(runner); mod_power_of_2_shr::register(runner); mod_power_of_2_square::register(runner); mod_power_of_2_neg::register(runner); mod_power_of_2_sub::register(runner); mod_shl::register(runner); mod_shr::register(runner); mod_square::register(runner); mod_sub::register(runner); neg::register(runner); next_power_of_2::register(runner); overflowing_abs::register(runner); overflowing_add::register(runner); overflowing_add_mul::register(runner); overflowing_div::register(runner); overflowing_mul::register(runner); overflowing_neg::register(runner); overflowing_pow::register(runner); overflowing_square::register(runner); overflowing_sub::register(runner); overflowing_sub_mul::register(runner); parity::register(runner); pow::register(runner); power_of_2::register(runner); primorial::register(runner); reciprocal::register(runner); root::register(runner); rotate::register(runner); round_to_multiple::register(runner); round_to_multiple_of_power_of_2::register(runner); saturating_abs::register(runner); saturating_add::register(runner); saturating_add_mul::register(runner); saturating_mul::register(runner); saturating_neg::register(runner); saturating_pow::register(runner); saturating_square::register(runner); saturating_sub::register(runner); saturating_sub_mul::register(runner); shl_round::register(runner); shr_round::register(runner); sign::register(runner); sqrt::register(runner); square::register(runner); sub_mul::register(runner); wrapping_abs::register(runner); wrapping_add::register(runner); wrapping_add_mul::register(runner); wrapping_div::register(runner); wrapping_mul::register(runner); wrapping_neg::register(runner); wrapping_pow::register(runner); wrapping_square::register(runner); wrapping_sub::register(runner); wrapping_sub_mul::register(runner); x_mul_y_to_zz::register(runner); xx_add_yy_to_zz::register(runner); xx_div_mod_y_to_qr::register(runner); xx_sub_yy_to_zz::register(runner); xxx_add_yyy_to_zzz::register(runner); xxx_sub_yyy_to_zzz::register(runner); xxxx_add_yyyy_to_zzzz::register(runner); } mod abs; mod abs_diff; mod add_mul; mod arithmetic_checked_shl; mod arithmetic_checked_shr; mod binomial_coefficient; mod ceiling; mod checked_add_mul; mod checked_square; mod checked_sub_mul; mod coprime_with; mod div_exact; mod div_mod; mod div_round; mod divisible_by; mod divisible_by_power_of_2; mod eq_mod; mod eq_mod_power_of_2; mod extended_gcd; mod factorial; mod floor; mod gcd; mod is_power_of_2; mod kronecker_symbol; mod lcm; mod log_base; mod log_base_2; mod log_base_power_of_2; mod mod_add; mod mod_inverse; mod mod_is_reduced; mod mod_mul; mod mod_neg; mod mod_op; mod mod_pow; mod mod_power_of_2; mod mod_power_of_2_add; mod mod_power_of_2_inverse; mod mod_power_of_2_is_reduced; mod mod_power_of_2_mul; mod mod_power_of_2_neg; mod mod_power_of_2_pow; mod mod_power_of_2_shl; mod mod_power_of_2_shr; mod mod_power_of_2_square; mod mod_power_of_2_sub; mod mod_shl; mod mod_shr; mod mod_square; mod mod_sub; mod neg; mod next_power_of_2; mod overflowing_abs; mod overflowing_add; mod overflowing_add_mul; mod overflowing_div; mod overflowing_mul; mod overflowing_neg; mod overflowing_pow; mod overflowing_square; mod overflowing_sub; mod overflowing_sub_mul; mod parity; mod pow; mod power_of_2; mod primorial; mod reciprocal; mod root; mod rotate; mod round_to_multiple; mod round_to_multiple_of_power_of_2; mod saturating_abs; mod saturating_add; mod saturating_add_mul; mod saturating_mul; mod saturating_neg; mod saturating_pow; mod saturating_square; mod saturating_sub; mod saturating_sub_mul; mod shl_round; mod shr_round; mod sign; mod sqrt; mod square; mod sub_mul; mod wrapping_abs; mod wrapping_add; mod wrapping_add_mul; mod wrapping_div; mod wrapping_mul; mod wrapping_neg; mod wrapping_pow; mod wrapping_square; mod wrapping_sub; mod wrapping_sub_mul; mod x_mul_y_to_zz; mod xx_add_yy_to_zz; mod xx_div_mod_y_to_qr; mod xx_sub_yy_to_zz; mod xxx_add_yyy_to_zzz; mod xxx_sub_yyy_to_zzz; mod xxxx_add_yyyy_to_zzzz; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_12; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_add); register_unsigned_demos!(runner, demo_mod_add_assign); register_unsigned_benches!(runner, benchmark_mod_add); register_unsigned_benches!(runner, benchmark_mod_add_assign); } fn demo_mod_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { println!("{} + {} ≡ {} mod {}", x, y, x.mod_add(y, m), m); } } fn demo_mod_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.mod_add_assign(y, m); println!("x := {old_x}; x.mod_add_assign({y}, {m}); x = {x}"); } } fn benchmark_mod_add( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_add({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [("Malachite", &mut |(x, y, m)| no_out!(x.mod_add(y, m)))], ); } fn benchmark_mod_add_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_add({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [("Malachite", &mut |(mut x, y, m)| x.mod_add_assign(y, m))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_inverse::mod_inverse_binary; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::pair_2_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_38; use malachite_base::test_util::num::arithmetic::mod_inverse::mod_inverse_euclidean; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_inverse); register_unsigned_signed_match_benches!(runner, benchmark_mod_inverse_algorithms); } fn demo_mod_inverse(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in unsigned_pair_gen_var_38::().get(gm, config).take(limit) { if let Some(inverse) = n.mod_inverse(m) { println!("{n}⁻¹ ≡ {inverse} mod {m}"); } else { println!("{n} is not invertible mod {m}"); } } } fn benchmark_mod_inverse_algorithms< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_inverse({})", U::NAME, U::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_38::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [ ("default", &mut |(n, m)| no_out!(n.mod_inverse(m))), ("Euclidean", &mut |(n, m)| { no_out!(mod_inverse_euclidean::(n, m)); }), ("binary", &mut |(n, m)| { no_out!(mod_inverse_binary::(n, m)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_12; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_is_reduced); register_unsigned_benches!(runner, benchmark_mod_is_reduced); } fn demo_mod_is_reduced(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { if n.mod_is_reduced(&m) { println!("{n} is reduced mod {m}"); } else { println!("{n} is not reduced mod {m}"); } } } fn benchmark_mod_is_reduced( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_is_reduced(&{})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [("Malachite", &mut |(n, m)| no_out!(n.mod_is_reduced(&m)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_mul::{ fast_mod_mul, limbs_invert_limb_u32, limbs_invert_limb_u64, mod_preinverted_double, naive_mod_mul, }; use malachite_base::num::arithmetic::traits::ModMulPrecomputed; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::test_util::bench::bucketers::{ ignore_highest_bit_unsigned_bit_bucketer, quadruple_1_2_bit_bucketer, triple_3_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_12, unsigned_quadruple_gen_var_5, unsigned_triple_gen_var_12, }; use malachite_base::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_invert_limb_u32); register_demo!(runner, demo_limbs_invert_limb_u64); register_generic_demos_2!( runner, demo_mod_preinverted_double, [u8, u16], [u16, u32], [u32, u64], [u64, u128] ); register_unsigned_demos!(runner, demo_mod_mul); register_unsigned_demos!(runner, demo_mod_mul_assign); register_bench!(runner, benchmark_limbs_invert_limb_u32_algorithms); register_bench!(runner, benchmark_limbs_invert_limb_u64_algorithms); register_generic_benches_2!( runner, benchmark_mod_preinverted_double_algorithms, [u8, u16], [u16, u32], [u32, u64], [u64, u128] ); register_generic_benches!(runner, benchmark_mod_mul_algorithms, u8, u16, u128, usize); register_generic_benches_2!( runner, benchmark_mod_mul_algorithms_with_fast, [u32, u64], [u64, u128] ); register_unsigned_benches!(runner, benchmark_mod_mul_assign); register_unsigned_benches!(runner, benchmark_mod_mul_precomputed_algorithms); } fn demo_limbs_invert_limb_u32(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_12().get(gm, config).take(limit) { println!( "limbs_invert_limb_u32({}) = {}", x, limbs_invert_limb_u32(x) ); } } fn demo_limbs_invert_limb_u64(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_12().get(gm, config).take(limit) { println!( "limbs_invert_limb_u64({}) = {}", x, limbs_invert_limb_u64(x) ); } } fn demo_mod_preinverted_double< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x_1, x_0, m, inv) in unsigned_quadruple_gen_var_5::() .get(gm, config) .take(limit) { println!( "mod_preinverted_double({}, {}, {}, {}) = {}", x_1, x_0, m, inv, mod_preinverted_double::(x_1, x_0, m, inv) ); } } fn demo_mod_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { println!("{} * {} ≡ {} mod {}", x, y, x.mod_mul(y, m), m); } } fn demo_mod_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.mod_mul_assign(y, m); println!("x := {old_x}; x.mod_mul_assign({y}, {m}); x = {x}"); } } fn benchmark_limbs_invert_limb_u32_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_invert_limb_u32(u32)", BenchmarkType::Algorithms, unsigned_gen_var_12().get(gm, config), gm.name(), limit, file_name, &ignore_highest_bit_unsigned_bit_bucketer("m"), &mut [ ("default", &mut |x| no_out!(limbs_invert_limb_u32(x))), ("naive", &mut |x| { no_out!(limbs_invert_limb_naive::(x)); }), ], ); } fn benchmark_limbs_invert_limb_u64_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_invert_limb_u64(u64)", BenchmarkType::Algorithms, unsigned_gen_var_12().get(gm, config), gm.name(), limit, file_name, &ignore_highest_bit_unsigned_bit_bucketer("m"), &mut [ ("default", &mut |x| no_out!(limbs_invert_limb_u64(x))), ("naive", &mut |x| { no_out!(limbs_invert_limb_naive::(x)); }), ], ); } fn benchmark_mod_preinverted_double_algorithms< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "mod_preinverted_double({}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_quadruple_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_bit_bucketer("x"), &mut [ ("default", &mut |(x_1, x_0, d, d_inv)| { no_out!(mod_preinverted_double::(x_1, x_0, d, d_inv)); }), ("naive", &mut |(x_1, x_0, d, _)| { no_out!(T::exact_from(DT::join_halves(x_1, x_0) % DT::from(d))); }), ], ); } fn benchmark_mod_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| no_out!(x.mod_mul(y, m))), ("naive", &mut |(x, y, m)| no_out!(naive_mod_mul(x, y, m))), ], ); } fn benchmark_mod_mul_algorithms_with_fast< T: ModMulPrecomputed + PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| no_out!(x.mod_mul(y, m))), ("naive", &mut |(x, y, m)| no_out!(naive_mod_mul(x, y, m))), ("fast", &mut |(x, y, m)| { no_out!(fast_mod_mul::( x, y, m, T::precompute_mod_mul_data(&m) )); }), ], ); } fn benchmark_mod_mul_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [("Malachite", &mut |(mut x, y, m)| x.mod_mul_assign(y, m))], ); } fn benchmark_mod_mul_precomputed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| { for _ in 0..10 { x.mod_mul(y, m); } }), ("precomputed", &mut |(x, y, m)| { let data = T::precompute_mod_mul_data(&m); for _ in 0..10 { x.mod_mul_precomputed(y, m, &data); } }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_neg); register_unsigned_demos!(runner, demo_mod_neg_assign); register_unsigned_benches!(runner, benchmark_mod_neg); register_unsigned_benches!(runner, benchmark_mod_neg_assign); } fn demo_mod_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in unsigned_pair_gen_var_16::().get(gm, config).take(limit) { println!("-{} ≡ {} mod {}", n, n.mod_neg(m), m); } } fn demo_mod_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, m) in unsigned_pair_gen_var_16::().get(gm, config).take(limit) { let old_n = n; n.mod_neg_assign(m); println!("n := {old_n}; n.mod_neg_assign({m}); n = {n}"); } } fn benchmark_mod_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_neg({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [("Malachite", &mut |(n, m)| no_out!(n.mod_neg(m)))], ); } fn benchmark_mod_neg_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_neg({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [("Malachite", &mut |(mut n, m)| n.mod_neg_assign(m))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen_var_4, signed_pair_gen_var_6, unsigned_pair_gen_var_12, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_unsigned); register_signed_demos!(runner, demo_mod_signed); register_unsigned_demos!(runner, demo_mod_assign_unsigned); register_signed_demos!(runner, demo_mod_assign_signed); register_unsigned_demos!(runner, demo_neg_mod); register_unsigned_demos!(runner, demo_neg_mod_assign); register_signed_demos!(runner, demo_ceiling_mod); register_signed_demos!(runner, demo_ceiling_mod_assign); register_unsigned_benches!(runner, benchmark_mod_unsigned_algorithms); register_signed_benches!(runner, benchmark_mod_signed_algorithms); register_unsigned_benches!(runner, benchmark_mod_assign_unsigned); register_signed_benches!(runner, benchmark_mod_assign_signed); register_unsigned_benches!(runner, benchmark_neg_mod_algorithms); register_unsigned_benches!(runner, benchmark_neg_mod_assign); register_signed_benches!(runner, benchmark_ceiling_mod_algorithms); register_signed_benches!(runner, benchmark_ceiling_mod_assign); } fn demo_mod_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.mod_op({}) = {}", x, y, x.mod_op(y)); } } fn demo_mod_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { println!("({}).mod_op({}) = {}", x, y, x.mod_op(y)); } } fn demo_mod_assign_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.mod_assign(y); println!("x := {old_x}; x.mod_assign({y}); x = {x}"); } } fn demo_mod_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { let old_x = x; x.mod_assign(y); println!("x := {old_x}; x.mod_assign({y}); x = {x}"); } } fn demo_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.neg_mod({}) = {}", x, y, x.neg_mod(y)); } } fn demo_neg_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.neg_mod_assign(y); println!("x := {old_x}; x.neg_mod_assign({y}); x = {x}"); } } fn demo_ceiling_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { println!("({}).ceiling_mod({}) = {}", x, y, x.ceiling_mod(y)); } } fn demo_ceiling_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { let old_x = x; x.ceiling_mod_assign(y); println!("x := {old_x}; x.ceiling_mod_assign({y}); x = {x}"); } } #[allow(clippy::unnecessary_operation)] fn benchmark_mod_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using mod", &mut |(x, y)| no_out!(x.mod_op(y))), ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y).1)), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_mod_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using mod", &mut |(x, y)| no_out!(x.mod_op(y))), ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y).1)), ], ); } fn benchmark_mod_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.mod_assign(y))], ); } fn benchmark_mod_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.mod_assign(y))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_neg_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using neg_mod", &mut |(x, y)| no_out!(x.neg_mod(y))), ("using ceiling_div_mod", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(y).1); }), ], ); } fn benchmark_neg_mod_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_mod_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.neg_mod_assign(y))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_ceiling_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_mod({})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("using ceiling_mod", &mut |(x, y)| no_out!(x.ceiling_mod(y))), ("using ceiling_div_mod", &mut |(x, y)| { no_out!(x.ceiling_div_mod(y).1); }), ], ); } fn benchmark_ceiling_mod_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_mod_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.ceiling_mod_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_pow::simple_binary_mod_pow; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_2_3_product_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_14, unsigned_triple_gen_var_15, }; use malachite_base::test_util::num::arithmetic::mod_pow::naive_mod_pow; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_pow); register_unsigned_demos!(runner, demo_mod_pow_assign); register_unsigned_benches!(runner, benchmark_mod_pow_algorithms); register_unsigned_benches!(runner, benchmark_mod_pow_naive_algorithms); register_unsigned_benches!(runner, benchmark_mod_pow_assign); register_unsigned_benches!(runner, benchmark_mod_pow_precomputed_algorithms); } fn demo_mod_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in unsigned_triple_gen_var_15::() .get(gm, config) .take(limit) { println!("{}.pow({}) ≡ {} mod {}", x, exp, x.mod_pow(exp, m), m); } } fn demo_mod_pow_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, m) in unsigned_triple_gen_var_15::() .get(gm, config) .take(limit) { let old_x = x; x.mod_pow_assign(exp, m); println!("x := {old_x}; x.mod_pow_assign({exp}, {m}); x = {x}"); } } fn benchmark_mod_pow_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_pow(u64, {})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("exp", "m"), &mut [ ("default", &mut |(x, exp, m)| no_out!(x.mod_pow(exp, m))), ("simple binary", &mut |(x, exp, m)| { no_out!(simple_binary_mod_pow(x, exp, m)); }), ], ); } fn benchmark_mod_pow_naive_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_pow(u64, {})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_14::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("exp", "m"), &mut [ ("default", &mut |(x, exp, m)| no_out!(x.mod_pow(exp, m))), ("naive", &mut |(x, exp, m)| { no_out!(naive_mod_pow(x, exp, m)); }), ("simple binary", &mut |(x, exp, m)| { no_out!(simple_binary_mod_pow(x, exp, m)); }), ], ); } fn benchmark_mod_pow_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_pow_assign(u64, {})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("exp", "m"), &mut [("Malachite", &mut |(mut x, exp, m)| x.mod_pow_assign(exp, m))], ); } fn benchmark_mod_pow_precomputed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_pow(u64, {})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("exp", "m"), &mut [ ("default", &mut |(x, exp, m)| { for _ in 0..10 { x.mod_pow(exp, m); } }), ("precomputed", &mut |(x, exp, m)| { let data = T::precompute_mod_pow_data(&m); for _ in 0..10 { x.mod_pow_precomputed(exp, m, &data); } }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ModPowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_4, signed_unsigned_pair_gen_var_10, signed_unsigned_pair_gen_var_11, unsigned_pair_gen_var_2, unsigned_pair_gen_var_20, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_unsigned); register_signed_demos!(runner, demo_mod_power_of_2_signed); register_unsigned_demos!(runner, demo_mod_power_of_2_assign_unsigned); register_signed_demos!(runner, demo_mod_power_of_2_assign_signed); register_unsigned_demos!(runner, demo_rem_power_of_2_unsigned); register_signed_demos!(runner, demo_rem_power_of_2_signed); register_unsigned_demos!(runner, demo_rem_power_of_2_assign_unsigned); register_signed_demos!(runner, demo_rem_power_of_2_assign_signed); register_unsigned_demos!(runner, demo_neg_mod_power_of_2); register_unsigned_demos!(runner, demo_neg_mod_power_of_2_assign); register_unsigned_signed_match_demos!(runner, demo_ceiling_mod_power_of_2); register_unsigned_signed_match_demos!(runner, demo_ceiling_mod_power_of_2_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_unsigned); register_signed_benches!(runner, benchmark_mod_power_of_2_signed); register_unsigned_benches!(runner, benchmark_mod_power_of_2_assign_unsigned); register_signed_benches!(runner, benchmark_mod_power_of_2_assign_signed); register_unsigned_benches!(runner, benchmark_rem_power_of_2_unsigned); register_signed_benches!(runner, benchmark_rem_power_of_2_signed); register_unsigned_benches!(runner, benchmark_rem_power_of_2_assign_unsigned); register_signed_benches!(runner, benchmark_rem_power_of_2_assign_signed); register_unsigned_benches!(runner, benchmark_neg_mod_power_of_2); register_unsigned_benches!(runner, benchmark_neg_mod_power_of_2_assign); register_unsigned_signed_match_benches!(runner, benchmark_ceiling_mod_power_of_2); register_unsigned_signed_match_benches!(runner, benchmark_ceiling_mod_power_of_2_assign); } fn demo_mod_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("{} ≡ {} mod 2^{}", n, n.mod_power_of_2(pow), pow); } } fn demo_mod_power_of_2_signed(gm: GenMode, config: &GenConfig, limit: usize) where ::Output: PrimitiveUnsigned, { for (n, pow) in signed_unsigned_pair_gen_var_10::() .get(gm, config) .take(limit) { println!("{} ≡ {} mod 2^{}", n, n.mod_power_of_2(pow), pow); } } fn demo_mod_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let old_n = n; n.mod_power_of_2_assign(pow); println!("n := {old_n}; n.mod_power_of_2_assign({pow}); n = {n}"); } } fn demo_mod_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where ::Output: PrimitiveUnsigned, { for (mut n, pow) in signed_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let old_n = n; n.mod_power_of_2_assign(pow); println!("n := {old_n}; n.mod_power_of_2_assign({pow}); n = {n}"); } } fn demo_rem_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("{}.rem_power_of_2({}) = {}", n, pow, n.rem_power_of_2(pow)); } } fn demo_rem_power_of_2_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("{}.rem_power_of_2({}) = {}", n, pow, n.rem_power_of_2(pow)); } } fn demo_rem_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let old_n = n; n.rem_power_of_2_assign(pow); println!("n := {old_n}; n.rem_power_of_2_assign({pow}); n = {n}"); } } fn demo_rem_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; n.rem_power_of_2_assign(pow); println!("n := {old_n}; n.rem_power_of_2_assign({pow}); n = {n}"); } } fn demo_neg_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in unsigned_pair_gen_var_20::().get(gm, config).take(limit) { println!( "{}.neg_mod_power_of_2({}) = {}", n, pow, n.neg_mod_power_of_2(pow) ); } } fn demo_neg_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in unsigned_pair_gen_var_20::().get(gm, config).take(limit) { let old_n = n; n.neg_mod_power_of_2_assign(pow); println!("n := {old_n}; n.neg_mod_power_of_2_assign({pow}); n = {n}"); } } fn demo_ceiling_mod_power_of_2< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in signed_unsigned_pair_gen_var_11::() .get(gm, config) .take(limit) { println!( "({}).ceiling_mod_power_of_2({}) = {}", n, pow, n.ceiling_mod_power_of_2(pow) ); } } fn demo_ceiling_mod_power_of_2_assign< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in signed_unsigned_pair_gen_var_11::() .get(gm, config) .take(limit) { let old_n = n; n.ceiling_mod_power_of_2_assign(pow); println!("n := {old_n}; n.ceiling_mod_power_of_2_assign({pow}); n = {n}"); } } fn benchmark_mod_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| no_out!(n.mod_power_of_2(pow)))], ); } fn benchmark_mod_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PrimitiveUnsigned, { run_benchmark( &format!("{}.mod_power_of_2(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| no_out!(n.mod_power_of_2(pow)))], ); } fn benchmark_mod_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.mod_power_of_2_assign(pow); })], ); } fn benchmark_mod_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.mod_power_of_2_assign(pow); })], ); } fn benchmark_rem_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rem_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| no_out!(n.rem_power_of_2(pow)))], ); } fn benchmark_rem_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PrimitiveUnsigned, { run_benchmark( &format!("{}.rem_power_of_2(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| no_out!(n.rem_power_of_2(pow)))], ); } fn benchmark_rem_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rem_power_of_2_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.rem_power_of_2_assign(pow); })], ); } fn benchmark_rem_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rem_power_of_2_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.rem_power_of_2_assign(pow); })], ); } fn benchmark_neg_mod_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_mod_power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_20::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.neg_mod_power_of_2(pow)); })], ); } fn benchmark_neg_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_mod_power_of_2_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_20::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.neg_mod_power_of_2_assign(pow); })], ); } fn benchmark_ceiling_mod_power_of_2< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_mod_power_of_2(u64)", S::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.ceiling_mod_power_of_2(pow)); })], ); } fn benchmark_ceiling_mod_power_of_2_assign< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_mod_power_of_2_assign(u64)", S::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, pow)| { n.ceiling_mod_power_of_2_assign(pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_add); register_unsigned_demos!(runner, demo_mod_power_of_2_add_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_add); register_unsigned_benches!(runner, benchmark_mod_power_of_2_add_assign); } fn demo_mod_power_of_2_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { println!( "{} + {} ≡ {} mod 2^{}", x, y, x.mod_power_of_2_add(y, pow), pow ); } } fn demo_mod_power_of_2_add_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { let old_x = x; x.mod_power_of_2_add_assign(y, pow); println!("x := {old_x}; x.mod_power_of_2_add_assign({y}, {pow}); x = {x}"); } } fn benchmark_mod_power_of_2_add( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_add({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_add(y, pow)); })], ); } fn benchmark_mod_power_of_2_add_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_add_assign({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_add_assign(y, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_power_of_2_inverse::mod_power_of_2_inverse_fast; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_39; use malachite_base::test_util::num::arithmetic::mod_power_of_2_inverse::*; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_inverse); register_unsigned_signed_match_benches!(runner, benchmark_mod_power_of_2_inverse_algorithms); } fn demo_mod_power_of_2_inverse( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_39::().get(gm, config).take(limit) { if let Some(inverse) = n.mod_power_of_2_inverse(pow) { println!("{n}⁻¹ ≡ {inverse} mod 2^{pow}"); } else { println!("{n} is not invertible mod 2^{pow}"); } } } fn benchmark_mod_power_of_2_inverse_algorithms< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_inverse(u64)", U::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_39::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("default", &mut |(n, pow)| { no_out!(n.mod_power_of_2_inverse(pow)); }), ("Euclidean", &mut |(n, pow)| { no_out!(mod_power_of_2_inverse_euclidean::(n, pow)); }), ("fast", &mut |(n, pow)| { no_out!(mod_power_of_2_inverse_fast(n, pow)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_2; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_is_reduced); register_unsigned_benches!(runner, benchmark_mod_power_of_2_is_reduced); } fn demo_mod_power_of_2_is_reduced( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { if n.mod_power_of_2_is_reduced(pow) { println!("{n} is reduced mod 2^{pow}"); } else { println!("{n} is not reduced mod 2^{pow}"); } } } fn benchmark_mod_power_of_2_is_reduced( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_is_reduced(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.mod_power_of_2_is_reduced(pow)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_mul); register_unsigned_demos!(runner, demo_mod_power_of_2_mul_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_mul); register_unsigned_benches!(runner, benchmark_mod_power_of_2_mul_assign); } fn demo_mod_power_of_2_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { println!( "{} * {} ≡ {} mod 2^{}", x, y, x.mod_power_of_2_mul(y, pow), pow ); } } fn demo_mod_power_of_2_mul_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { let old_x = x; x.mod_power_of_2_mul_assign(y, pow); println!("x := {old_x}; x.mod_power_of_2_mul_assign({y}, {pow}); x = {x}"); } } fn benchmark_mod_power_of_2_mul( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_mul({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_mul(y, pow)); })], ); } fn benchmark_mod_power_of_2_mul_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_mul_assign({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_mul_assign(y, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_17; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_neg); register_unsigned_demos!(runner, demo_mod_power_of_2_neg_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_neg); register_unsigned_benches!(runner, benchmark_mod_power_of_2_neg_assign); } fn demo_mod_power_of_2_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in unsigned_pair_gen_var_17::().get(gm, config).take(limit) { println!("-{} ≡ {} mod 2^{}", n, n.mod_power_of_2_neg(pow), pow); } } fn demo_mod_power_of_2_neg_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in unsigned_pair_gen_var_17::().get(gm, config).take(limit) { let old_n = n; n.mod_power_of_2_neg_assign(pow); println!("n := {old_n}; n.mod_power_of_2_neg_assign({pow}); n = {n}"); } } fn benchmark_mod_power_of_2_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_neg(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.mod_power_of_2_neg(pow)); })], ); } fn benchmark_mod_power_of_2_neg_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_neg_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut n, pow)| { n.mod_power_of_2_neg_assign(pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_16; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_pow); register_unsigned_demos!(runner, demo_mod_power_of_2_pow_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_pow); register_unsigned_benches!(runner, benchmark_mod_power_of_2_pow_assign); } fn demo_mod_power_of_2_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, pow) in unsigned_triple_gen_var_16::() .get(gm, config) .take(limit) { println!( "{}.pow({}) ≡ {} mod 2^{}", x, exp, x.mod_power_of_2_pow(exp, pow), pow ); } } fn demo_mod_power_of_2_pow_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, exp, pow) in unsigned_triple_gen_var_16::() .get(gm, config) .take(limit) { let old_x = x; x.mod_power_of_2_pow_assign(exp, pow); println!("x := {old_x}; x.mod_power_of_2_pow_assign({exp}, {pow}); x = {x}"); } } fn benchmark_mod_power_of_2_pow( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_pow(u64, u64)", T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, exp, pow)| { no_out!(x.mod_power_of_2_pow(exp, pow)); })], ); } fn benchmark_mod_power_of_2_pow_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_pow_assign({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, exp, pow)| { x.mod_power_of_2_pow_assign(exp, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2Shl, ModPowerOf2ShlAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_signed_unsigned_triple_gen_var_1, unsigned_triple_gen_var_17, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_mod_power_of_2_shl_unsigned_unsigned); register_unsigned_signed_demos!(runner, demo_mod_power_of_2_shl_unsigned_signed); register_unsigned_unsigned_demos!(runner, demo_mod_power_of_2_shl_assign_unsigned_unsigned); register_unsigned_signed_demos!(runner, demo_mod_power_of_2_shl_assign_unsigned_signed); register_unsigned_unsigned_benches!(runner, benchmark_mod_power_of_2_shl_unsigned_unsigned); register_unsigned_signed_benches!(runner, benchmark_mod_power_of_2_shl_unsigned_signed); register_unsigned_unsigned_benches!( runner, benchmark_mod_power_of_2_shl_assign_unsigned_unsigned ); register_unsigned_signed_benches!(runner, benchmark_mod_power_of_2_shl_assign_unsigned_signed); } fn demo_mod_power_of_2_shl_unsigned_unsigned< T: ModPowerOf2Shl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, pow) in unsigned_triple_gen_var_17::() .get(gm, config) .take(limit) { println!( "{}.mod_power_of_2_shl({}, {}) = {}", n, u, pow, n.mod_power_of_2_shl(u, pow) ); } } fn demo_mod_power_of_2_shl_unsigned_signed< T: ModPowerOf2Shl + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, pow) in unsigned_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.mod_power_of_2_shl({}, {}) = {}", n, u, pow, n.mod_power_of_2_shl(u, pow) ); } } fn demo_mod_power_of_2_shl_assign_unsigned_unsigned< T: ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, pow) in unsigned_triple_gen_var_17::() .get(gm, config) .take(limit) { let old_n = n; n.mod_power_of_2_shl_assign(u, pow); println!("x := {old_n}; x.mod_power_of_2_shl_assign({u}, {pow}); x = {n}"); } } fn demo_mod_power_of_2_shl_assign_unsigned_signed< T: ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, pow) in unsigned_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; n.mod_power_of_2_shl_assign(u, pow); println!("x := {old_n}; x.mod_power_of_2_shl_assign({u}, {pow}); x = {n}"); } } fn benchmark_mod_power_of_2_shl_unsigned_unsigned< T: ModPowerOf2Shl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shl({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_triple_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shl(y, pow)); })], ); } fn benchmark_mod_power_of_2_shl_unsigned_signed< T: ModPowerOf2Shl + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shl({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shl(y, pow)); })], ); } fn benchmark_mod_power_of_2_shl_assign_unsigned_unsigned< T: ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shl_assign({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_triple_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shl_assign(y, pow); })], ); } fn benchmark_mod_power_of_2_shl_assign_unsigned_signed< T: ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shl_assign({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shl_assign(y, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2Shr, ModPowerOf2ShrAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_signed_unsigned_triple_gen_var_1; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_signed_demos!(runner, demo_mod_power_of_2_shr); register_unsigned_signed_demos!(runner, demo_mod_power_of_2_shr_assign); register_unsigned_signed_benches!(runner, benchmark_mod_power_of_2_shr); register_unsigned_signed_benches!(runner, benchmark_mod_power_of_2_shr_assign); } fn demo_mod_power_of_2_shr< T: ModPowerOf2Shr + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, pow) in unsigned_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.mod_power_of_2_shr({}, {}) = {}", n, u, pow, n.mod_power_of_2_shr(u, pow) ); } } fn demo_mod_power_of_2_shr_assign< T: ModPowerOf2ShrAssign + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, pow) in unsigned_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; n.mod_power_of_2_shr_assign(u, pow); println!("x := {old_n}; x.mod_power_of_2_shr_assign({u}, {pow}); x = {n}"); } } fn benchmark_mod_power_of_2_shr< T: ModPowerOf2Shr + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shr({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shr(y, pow)); })], ); } fn benchmark_mod_power_of_2_shr_assign< T: ModPowerOf2ShrAssign + PrimitiveUnsigned, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_shr_assign({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shr_assign(y, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_17; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_square); register_unsigned_demos!(runner, demo_mod_power_of_2_square_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_square); register_unsigned_benches!(runner, benchmark_mod_power_of_2_square_assign); } fn demo_mod_power_of_2_square(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in unsigned_pair_gen_var_17::().get(gm, config).take(limit) { println!( "{}.square() ≡ {} mod 2^{}", n, n.mod_power_of_2_square(pow), pow ); } } fn demo_mod_power_of_2_square_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow) in unsigned_pair_gen_var_17::().get(gm, config).take(limit) { let old_n = n; n.mod_power_of_2_square_assign(pow); println!("n := {old_n}; n.mod_power_of_2_square_assign({pow}); n = {n}"); } } fn benchmark_mod_power_of_2_square( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_square(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.mod_power_of_2_square(pow)); })], ); } fn benchmark_mod_power_of_2_square_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_square_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut n, pow)| { n.mod_power_of_2_square_assign(pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_power_of_2_sub); register_unsigned_demos!(runner, demo_mod_power_of_2_sub_assign); register_unsigned_benches!(runner, benchmark_mod_power_of_2_sub); register_unsigned_benches!(runner, benchmark_mod_power_of_2_sub_assign); } fn demo_mod_power_of_2_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { println!( "{} - {} ≡ {} mod 2^{}", x, y, x.mod_power_of_2_sub(y, pow), pow ); } } fn demo_mod_power_of_2_sub_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, pow) in unsigned_triple_gen_var_11::() .get(gm, config) .take(limit) { let old_x = x; x.mod_power_of_2_sub_assign(y, pow); println!("x := {old_x}; x.mod_power_of_2_sub_assign({y}, {pow}); x = {x}"); } } fn benchmark_mod_power_of_2_sub( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_sub({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_sub(y, pow)); })], ); } fn benchmark_mod_power_of_2_sub_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_power_of_2_sub_assign({}, u64)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_sub_assign(y, pow); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModShl, ModShlAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::triple_2_3_product_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_signed_unsigned_triple_gen_var_2, unsigned_triple_gen_var_18, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_mod_shl_unsigned_unsigned); register_unsigned_unsigned_signed_match_demos!(runner, demo_mod_shl_unsigned_signed); register_unsigned_unsigned_demos!(runner, demo_mod_shl_assign_unsigned_unsigned); register_unsigned_unsigned_signed_match_demos!(runner, demo_mod_shl_assign_unsigned_signed); register_unsigned_unsigned_benches!(runner, benchmark_mod_shl_unsigned_unsigned); register_unsigned_unsigned_signed_match_benches!(runner, benchmark_mod_shl_unsigned_signed); register_unsigned_unsigned_benches!(runner, benchmark_mod_shl_assign_unsigned_unsigned); register_unsigned_unsigned_signed_match_benches!( runner, benchmark_mod_shl_assign_unsigned_signed ); } fn demo_mod_shl_unsigned_unsigned< T: ModShl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, u, m) in unsigned_triple_gen_var_18::() .get(gm, config) .take(limit) { println!("{} << {} ≡ {} mod {}", x, u, x.mod_shl(u, m), m); } } fn demo_mod_shl_unsigned_signed< T: ModShl + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, u, m) in unsigned_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { println!("{} << {} ≡ {} mod {}", x, u, x.mod_shl(u, m), m); } } fn demo_mod_shl_assign_unsigned_unsigned< T: ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, u, m) in unsigned_triple_gen_var_18::() .get(gm, config) .take(limit) { let old_x = x; x.mod_shl_assign(u, m); println!("x := {old_x}; x.mod_shl_assign({u}, {m}); x = {x}"); } } fn demo_mod_shl_assign_unsigned_signed< T: ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, u, m) in unsigned_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_x = x; x.mod_shl_assign(u, m); println!("x := {old_x}; x.mod_shl_assign({u}, {m}); x = {x}"); } } fn benchmark_mod_shl_unsigned_unsigned< T: ModShl + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shl({}, {})", T::NAME, U::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(x, pow, m)| no_out!(x.mod_shl(pow, m)))], ); } fn benchmark_mod_shl_unsigned_signed< T: ModShl + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shl({}, {})", T::NAME, S::NAME, T::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(x, u, m)| no_out!(x.mod_shl(u, m)))], ); } fn benchmark_mod_shl_assign_unsigned_unsigned< T: ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shl_assign({}, u64)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_triple_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(mut x, u, m)| x.mod_shl_assign(u, m))], ); } fn benchmark_mod_shl_assign_unsigned_signed< T: ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shl_assign({}, u64)", T::NAME, S::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(mut x, u, m)| x.mod_shl_assign(u, m))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModShr, ModShrAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::triple_2_3_product_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_signed_unsigned_triple_gen_var_2; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_signed_match_demos!(runner, demo_mod_shr); register_unsigned_unsigned_signed_match_demos!(runner, demo_mod_shr_assign); register_unsigned_unsigned_signed_match_benches!(runner, benchmark_mod_shr); register_unsigned_unsigned_signed_match_benches!(runner, benchmark_mod_shr_assign); } fn demo_mod_shr< T: ModShr + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, u, m) in unsigned_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { println!("{} >> {} ≡ {} mod {}", x, u, x.mod_shr(u, m), m); } } fn demo_mod_shr_assign< T: ModShrAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, u, m) in unsigned_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_x = x; x.mod_shr_assign(u, m); println!("x := {old_x}; x.mod_shr_assign({u}, {m}); x = {x}"); } } fn benchmark_mod_shr< T: ModShr + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shr({}, {})", T::NAME, S::NAME, T::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(x, u, m)| no_out!(x.mod_shr(u, m)))], ); } fn benchmark_mod_shr_assign< T: ModShrAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_shr_assign({}, u64)", T::NAME, S::NAME), BenchmarkType::Single, unsigned_signed_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_product_bit_bucketer("u", "m"), &mut [("Malachite", &mut |(mut x, u, m)| x.mod_shr_assign(u, m))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_square); register_unsigned_demos!(runner, demo_mod_square_assign); register_unsigned_benches!(runner, benchmark_mod_square); register_unsigned_benches!(runner, benchmark_mod_square_assign); register_unsigned_benches!(runner, benchmark_mod_square_precomputed_algorithms); } fn demo_mod_square(gm: GenMode, config: &GenConfig, limit: usize) { for (x, m) in unsigned_pair_gen_var_16::().get(gm, config).take(limit) { println!("{}.square() ≡ {} mod {}", x, x.mod_square(m), m); } } fn demo_mod_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, m) in unsigned_pair_gen_var_16::().get(gm, config).take(limit) { let old_x = x; x.mod_square_assign(m); println!("x := {old_x}; x.mod_square_assign({m}); x = {x}"); } } fn benchmark_mod_square( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_square({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [("Malachite", &mut |(x, m)| no_out!(x.mod_square(m)))], ); } fn benchmark_mod_square_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_square({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [("Malachite", &mut |(mut x, m)| x.mod_square_assign(m))], ); } fn benchmark_mod_square_precomputed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_square({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_2_bit_bucketer("m"), &mut [ ("default", &mut |(x, m)| { for _ in 0..10 { x.mod_square(m); } }), ("precomputed", &mut |(x, m)| { let data = T::precompute_mod_pow_data(&m); for _ in 0..10 { x.mod_square_precomputed(m, &data); } }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_12; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_mod_sub); register_unsigned_demos!(runner, demo_mod_sub_assign); register_unsigned_benches!(runner, benchmark_mod_sub); register_unsigned_benches!(runner, benchmark_mod_sub_assign); } fn demo_mod_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { println!("{} - {} ≡ {} mod {}", x, y, x.mod_sub(y, m), m); } } fn demo_mod_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in unsigned_triple_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.mod_sub_assign(y, m); println!("x := {old_x}; x.mod_sub_assign({y}, {m}); x = {x}"); } } fn benchmark_mod_sub( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_sub({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [("Malachite", &mut |(x, y, m)| no_out!(x.mod_sub(y, m)))], ); } fn benchmark_mod_sub_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.mod_sub({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [("Malachite", &mut |(mut x, y, m)| x.mod_sub_assign(y, m))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{primitive_float_bucketer, signed_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_neg_assign_signed); register_primitive_float_demos!(runner, demo_neg_assign_primitive_float); register_signed_benches!(runner, benchmark_neg_assign_signed); register_primitive_float_benches!(runner, benchmark_neg_assign_primitive_float); } fn demo_neg_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen_var_1::().get(gm, config).take(limit) { let old_i = i; i.neg_assign(); println!("i := {old_i}; i.neg_assign(); i = {i}"); } } fn demo_neg_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in primitive_float_gen::().get(gm, config).take(limit) { let old_x = x; x.neg_assign(); println!( "x := {}; x.neg_assign(); x = {}", NiceFloat(old_x), NiceFloat(x) ); } } fn benchmark_neg_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_assign()", T::NAME), BenchmarkType::Single, signed_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.neg_assign())], ); } fn benchmark_neg_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.neg_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |mut x| x.neg_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen_var_19, unsigned_gen_var_14}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_next_power_of_2_primitive_float); register_unsigned_demos!(runner, demo_next_power_of_2_assign_unsigned); register_primitive_float_demos!(runner, demo_next_power_of_2_assign_primitive_float); register_primitive_float_benches!(runner, benchmark_next_power_of_2_primitive_float); register_unsigned_benches!(runner, benchmark_next_power_of_2_assign_unsigned); register_primitive_float_benches!(runner, benchmark_next_power_of_2_assign_primitive_float); } fn demo_next_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in primitive_float_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.next_power_of_2() = {}", NiceFloat(n), NiceFloat(n.next_power_of_2()) ); } } fn demo_next_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in unsigned_gen_var_14::().get(gm, config).take(limit) { let old_n = n; n.next_power_of_2_assign(); println!("n := {old_n}; n.next_power_of_2_assign(); n = {n}"); } } fn demo_next_power_of_2_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in primitive_float_gen_var_19::() .get(gm, config) .take(limit) { let old_n = n; n.next_power_of_2_assign(); println!( "n := {}; n.next_power_of_2_assign(); n = {}", NiceFloat(old_n), NiceFloat(n) ); } } fn benchmark_next_power_of_2_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.next_power_of_2()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.next_power_of_2()))], ); } fn benchmark_next_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.next_power_of_2_assign()", T::NAME), BenchmarkType::Single, unsigned_gen_var_14::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.next_power_of_2_assign())], ); } fn benchmark_next_power_of_2_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.next_power_of_2_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |mut n| n.next_power_of_2_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::signed_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_overflowing_abs_assign); register_signed_benches!(runner, benchmark_overflowing_abs_assign); } fn demo_overflowing_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; let overflow = i.overflowing_abs_assign(); println!("i := {old_i}; i.overflowing_abs_assign() = {overflow}; i = {i}"); } } fn benchmark_overflowing_abs_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_abs_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| { no_out!(i.overflowing_abs_assign()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_add_unsigned); register_signed_demos!(runner, demo_overflowing_add_signed); register_unsigned_demos!(runner, demo_overflowing_add_assign_unsigned); register_signed_demos!(runner, demo_overflowing_add_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_add_unsigned); register_signed_benches!(runner, benchmark_overflowing_add_signed); register_unsigned_benches!(runner, benchmark_overflowing_add_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_add_assign_signed); } fn demo_overflowing_add_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.overflowing_add({}) = {:?}", x, y, x.overflowing_add(y)); } } fn demo_overflowing_add_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).overflowing_add({}) = {:?}", x, y, x.overflowing_add(y) ); } } fn demo_overflowing_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_add_assign(y); println!("x := {old_x}; x.overflowing_add_assign({y}) = {overflow}; x = {x}"); } } fn demo_overflowing_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_add_assign(y); println!("x := {old_x}; x.overflowing_add_assign({y}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_add_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_add(y)))], ); } fn benchmark_overflowing_add_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_add(y)))], ); } fn benchmark_overflowing_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_add_assign(y)); })], ); } fn benchmark_overflowing_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_add_assign(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_add_mul_unsigned); register_signed_demos!(runner, demo_overflowing_add_mul_signed); register_unsigned_demos!(runner, demo_overflowing_add_mul_assign_unsigned); register_signed_demos!(runner, demo_overflowing_add_mul_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_add_mul_unsigned); register_signed_benches!(runner, benchmark_overflowing_add_mul_signed); register_unsigned_benches!(runner, benchmark_overflowing_add_mul_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_add_mul_assign_signed); } fn demo_overflowing_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.overflowing_add_mul({}, {}) = {:?}", x, y, z, x.overflowing_add_mul(y, z) ); } } fn demo_overflowing_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.overflowing_add_mul({}, {}) = {:?}", x, y, z, x.overflowing_add_mul(y, z) ); } } fn demo_overflowing_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; let overflow = x.overflowing_add_mul_assign(y, z); println!("x := {old_x}; x.overflowing_add_mul_assign({y}, {z}) = {overflow}; x = {x}"); } } fn demo_overflowing_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_add_mul_assign(y, z); println!("x := {old_x}; x.overflowing_add_mul_assign({y}, {z}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.overflowing_add_mul(y, z)); })], ); } fn benchmark_overflowing_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.overflowing_add_mul(y, z)); })], ); } fn benchmark_overflowing_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.overflowing_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { no_out!(x.overflowing_add_mul_assign(y, z)); })], ); } fn benchmark_overflowing_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.overflowing_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { no_out!(x.overflowing_add_mul_assign(y, z)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_div.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen_var_6, unsigned_pair_gen_var_12}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_div_unsigned); register_signed_demos!(runner, demo_overflowing_div_signed); register_unsigned_demos!(runner, demo_overflowing_div_assign_unsigned); register_signed_demos!(runner, demo_overflowing_div_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_div_unsigned); register_signed_benches!(runner, benchmark_overflowing_div_signed); register_unsigned_benches!(runner, benchmark_overflowing_div_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_div_assign_signed); } fn demo_overflowing_div_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.overflowing_div({}) = {:?}", x, y, x.overflowing_div(y)); } } fn demo_overflowing_div_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { println!( "({}).overflowing_div({}) = {:?}", x, y, x.overflowing_div(y) ); } } fn demo_overflowing_div_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; let overflow = x.overflowing_div_assign(y); println!("x := {old_x}; x.overflowing_div_assign({y}) = {overflow}; x = {x}"); } } fn demo_overflowing_div_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_div_assign(y); println!("x := {old_x}; x.overflowing_div_assign({y}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_div_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_div({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_div(y)))], ); } fn benchmark_overflowing_div_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_div({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_div(y)))], ); } fn benchmark_overflowing_div_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_div_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_div_assign(y)); })], ); } fn benchmark_overflowing_div_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_div_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_div_assign(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_mul_unsigned); register_signed_demos!(runner, demo_overflowing_mul_signed); register_unsigned_demos!(runner, demo_overflowing_mul_assign_unsigned); register_signed_demos!(runner, demo_overflowing_mul_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_mul_unsigned); register_signed_benches!(runner, benchmark_overflowing_mul_signed); register_unsigned_benches!(runner, benchmark_overflowing_mul_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_mul_assign_signed); } fn demo_overflowing_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.overflowing_mul({}) = {:?}", x, y, x.overflowing_mul(y)); } } fn demo_overflowing_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).overflowing_mul({}) = {:?}", x, y, x.overflowing_mul(y) ); } } fn demo_overflowing_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_mul_assign(y); println!("x := {old_x}; x.overflowing_mul_assign({y}) = {overflow}; x = {x}"); } } fn demo_overflowing_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_mul_assign(y); println!("x := {old_x}; x.overflowing_mul_assign({y}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_mul({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_mul(y)))], ); } fn benchmark_overflowing_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_mul({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_mul(y)))], ); } fn benchmark_overflowing_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_mul_assign(y)); })], ); } fn benchmark_overflowing_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_mul_assign(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_neg_assign_unsigned); register_signed_demos!(runner, demo_overflowing_neg_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_neg_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_neg_assign_signed); } fn demo_overflowing_neg_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut u in unsigned_gen::().get(gm, config).take(limit) { let old_u = u; let overflow = u.overflowing_neg_assign(); println!("u := {old_u}; u.overflowing_neg_assign() = {overflow}; u = {u}"); } } fn demo_overflowing_neg_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; let overflow = i.overflowing_neg_assign(); println!("i := {old_i}; i.overflowing_neg_assign() = {overflow}; i = {i}"); } } fn benchmark_overflowing_neg_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_neg_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut i| { no_out!(i.overflowing_neg_assign()); })], ); } fn benchmark_overflowing_neg_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_neg_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| { no_out!(i.overflowing_neg_assign()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_pow_assign_unsigned); register_signed_demos!(runner, demo_overflowing_pow_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_pow_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_pow_assign_signed); } fn demo_overflowing_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_pow_assign(y); println!("x := {old_x}; x.overflowing_pow_assign({y}) = {overflow}; x = {x}"); } } fn demo_overflowing_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_unsigned_pair_gen::() .get(gm, config) .take(limit) { let old_x = x; let overflow = x.overflowing_pow_assign(y); println!("x := {old_x}; x.overflowing_pow_assign({y}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_pow_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_pow_assign(y)); })], ); } fn benchmark_overflowing_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_pow_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_pow_assign(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_square_unsigned); register_signed_demos!(runner, demo_overflowing_square_signed); register_unsigned_demos!(runner, demo_overflowing_square_assign_unsigned); register_signed_demos!(runner, demo_overflowing_square_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_square_unsigned); register_signed_benches!(runner, benchmark_overflowing_square_signed); register_unsigned_benches!(runner, benchmark_overflowing_square_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_square_assign_signed); } fn demo_overflowing_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("{}.overflowing_square() = {:?}", x, x.overflowing_square()); } } fn demo_overflowing_square_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in signed_gen::().get(gm, config).take(limit) { println!("{}.overflowing_square() = {:?}", x, x.overflowing_square()); } } fn demo_overflowing_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in unsigned_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_square_assign(); println!("x := {old_x}; x.overflowing_square_assign() = {overflow}; x = {x}"); } } fn demo_overflowing_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in signed_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_square_assign(); println!("x := {old_x}; x.overflowing_square_assign() = {overflow}; x = {x}"); } } fn benchmark_overflowing_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_square()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.overflowing_square()))], ); } fn benchmark_overflowing_square_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_square()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.overflowing_square()))], ); } fn benchmark_overflowing_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_square_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut x| { no_out!(x.overflowing_square_assign()); })], ); } fn benchmark_overflowing_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_square_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut x| { no_out!(x.overflowing_square_assign()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_sub_unsigned); register_signed_demos!(runner, demo_overflowing_sub_signed); register_unsigned_demos!(runner, demo_overflowing_sub_assign_unsigned); register_signed_demos!(runner, demo_overflowing_sub_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_sub_unsigned); register_signed_benches!(runner, benchmark_overflowing_sub_signed); register_unsigned_benches!(runner, benchmark_overflowing_sub_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_sub_assign_signed); } fn demo_overflowing_sub_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.overflowing_sub({}) = {:?}", x, y, x.overflowing_sub(y)); } } fn demo_overflowing_sub_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).overflowing_sub({}) = {:?}", x, y, x.overflowing_sub(y) ); } } fn demo_overflowing_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_sub_assign(y); println!("x := {old_x}; x.overflowing_sub_assign({y}) = {overflow}; x = {x}"); } } fn demo_overflowing_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_sub_assign(y); println!("x := {old_x}; x.overflowing_sub_assign({y}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_sub_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_sub(y)))], ); } fn benchmark_overflowing_sub_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.overflowing_sub(y)))], ); } fn benchmark_overflowing_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_sub_assign(y)); })], ); } fn benchmark_overflowing_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| { no_out!(x.overflowing_sub_assign(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/overflowing_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_overflowing_sub_mul_unsigned); register_signed_demos!(runner, demo_overflowing_sub_mul_signed); register_unsigned_demos!(runner, demo_overflowing_sub_mul_assign_unsigned); register_signed_demos!(runner, demo_overflowing_sub_mul_assign_signed); register_unsigned_benches!(runner, benchmark_overflowing_sub_mul_unsigned); register_signed_benches!(runner, benchmark_overflowing_sub_mul_signed); register_unsigned_benches!(runner, benchmark_overflowing_sub_mul_assign_unsigned); register_signed_benches!(runner, benchmark_overflowing_sub_mul_assign_signed); } fn demo_overflowing_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.overflowing_sub_mul({}, {}) = {:?}", x, y, z, x.overflowing_sub_mul(y, z) ); } } fn demo_overflowing_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.overflowing_sub_mul({}, {}) = {:?}", x, y, z, x.overflowing_sub_mul(y, z) ); } } fn demo_overflowing_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; let overflow = x.overflowing_sub_mul_assign(y, z); println!("x := {old_x}; x.overflowing_sub_mul_assign({y}, {z}) = {overflow}; x = {x}"); } } fn demo_overflowing_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; let overflow = x.overflowing_sub_mul_assign(y, z); println!("x := {old_x}; x.overflowing_sub_mul_assign({y}, {z}) = {overflow}; x = {x}"); } } fn benchmark_overflowing_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.overflowing_sub_mul(y, z)); })], ); } fn benchmark_overflowing_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.overflowing_sub_mul(y, z)); })], ); } fn benchmark_overflowing_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.overflowing_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { no_out!(x.overflowing_sub_mul_assign(y, z)); })], ); } fn benchmark_overflowing_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.overflowing_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { no_out!(x.overflowing_sub_mul_assign(y, z)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_even_unsigned); register_signed_demos!(runner, demo_even_signed); register_unsigned_demos!(runner, demo_odd_unsigned); register_signed_demos!(runner, demo_odd_signed); register_unsigned_benches!(runner, benchmark_even_unsigned); register_signed_benches!(runner, benchmark_even_signed); register_unsigned_benches!(runner, benchmark_odd_unsigned); register_signed_benches!(runner, benchmark_odd_signed); } fn demo_even_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.even() { println!("{u} is even"); } else { println!("{u} is not even"); } } } fn demo_even_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { if i.even() { println!("{i} is even"); } else { println!("{i} is not even"); } } } fn demo_odd_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.odd() { println!("{u} is odd"); } else { println!("{u} is not odd"); } } } fn demo_odd_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { if i.odd() { println!("{i} is odd"); } else { println!("{i} is not odd"); } } } fn benchmark_even_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.even()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.even()))], ); } fn benchmark_even_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.even()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.even()))], ); } fn benchmark_odd_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.odd()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.odd()))], ); } fn benchmark_odd_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.odd()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.odd()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, pair_1_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_pair_gen, primitive_float_signed_pair_gen, signed_unsigned_pair_gen_var_15, unsigned_pair_gen_var_29, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_pow_assign_unsigned); register_signed_demos!(runner, demo_pow_assign_signed); register_primitive_float_demos!(runner, demo_pow_assign_i64_primitive_float); register_primitive_float_demos!(runner, demo_pow_assign_primitive_float_primitive_float); register_unsigned_benches!(runner, benchmark_pow_assign_unsigned); register_signed_benches!(runner, benchmark_pow_assign_signed); register_primitive_float_benches!(runner, benchmark_pow_assign_i64_primitive_float); register_primitive_float_benches!(runner, benchmark_pow_assign_primitive_float_primitive_float); } fn demo_pow_assign_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in unsigned_pair_gen_var_29::().get(gm, config).take(limit) { let old_x = x; x.pow_assign(y); println!("x := {old_x}; x.pow_assign({y}); x = {x}"); } } fn demo_pow_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in signed_unsigned_pair_gen_var_15::() .get(gm, config) .take(limit) { let old_x = x; x.pow_assign(y); println!("x := {old_x}; x.pow_assign({y}); x = {x}"); } } fn demo_pow_assign_i64_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in primitive_float_signed_pair_gen::() .get(gm, config) .take(limit) { let old_x = x; x.pow_assign(y); println!( "x := {}; x.pow_assign({}); x = {}", NiceFloat(old_x), y, NiceFloat(x) ); } } fn demo_pow_assign_primitive_float_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.pow_assign(y); println!( "x := {}; x.pow_assign({}); x = {}", NiceFloat(old_x), NiceFloat(y), NiceFloat(x) ); } } fn benchmark_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.pow_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, y)| x.pow_assign(y))], ); } fn benchmark_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.pow_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, y)| x.pow_assign(y))], ); } fn benchmark_pow_assign_i64_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.pow_assign(i64)", T::NAME), BenchmarkType::Single, primitive_float_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(mut x, y)| x.pow_assign(y))], ); } fn benchmark_pow_assign_primitive_float_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.pow_assign({})", T::NAME, T::NAME), BenchmarkType::Single, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(mut x, y)| x.pow_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{signed_abs_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen_var_11, unsigned_gen_var_15, unsigned_gen_var_16, unsigned_gen_var_30, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_power_of_2_unsigned); register_signed_demos!(runner, demo_power_of_2_signed); register_primitive_float_demos!(runner, demo_power_of_2_primitive_float_unsigned); register_primitive_float_demos!(runner, demo_power_of_2_primitive_float_signed); register_unsigned_benches!(runner, benchmark_power_of_2_unsigned); register_signed_benches!(runner, benchmark_power_of_2_signed); register_primitive_float_benches!(runner, benchmark_power_of_2_primitive_float_unsigned); register_primitive_float_benches!(runner, benchmark_power_of_2_primitive_float_signed); } fn demo_power_of_2_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for pow in unsigned_gen_var_15::().get(gm, config).take(limit) { println!("2^{} = {}", pow, T::power_of_2(pow)); } } fn demo_power_of_2_signed(gm: GenMode, config: &GenConfig, limit: usize) { for pow in unsigned_gen_var_16::().get(gm, config).take(limit) { println!("2^{} = {}", pow, T::power_of_2(pow)); } } fn demo_power_of_2_primitive_float_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for pow in unsigned_gen_var_30::().get(gm, config).take(limit) { println!("2^({}) = {}", pow, NiceFloat(T::power_of_2(pow))); } } fn demo_power_of_2_primitive_float_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for pow in signed_gen_var_11::().get(gm, config).take(limit) { println!("2^({}) = {}", pow, NiceFloat(T::power_of_2(pow))); } } fn benchmark_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |pow| no_out!(T::power_of_2(pow)))], ); } fn benchmark_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.power_of_2(u64)", T::NAME), BenchmarkType::Single, unsigned_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |pow| no_out!(T::power_of_2(pow)))], ); } fn benchmark_power_of_2_primitive_float_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.power_of_2(i64)", T::NAME), BenchmarkType::Single, unsigned_gen_var_30::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |pow| no_out!(T::power_of_2(pow)))], ); } fn benchmark_power_of_2_primitive_float_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.power_of_2(i64)", T::NAME), BenchmarkType::Single, signed_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &signed_abs_bucketer("pow"), &mut [("Malachite", &mut |pow| no_out!(T::power_of_2(pow)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_27, unsigned_gen_var_28, }; use malachite_base::test_util::num::arithmetic::primorial::{ checked_primorial_naive, checked_product_of_first_n_primes_naive, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_primorial); register_unsigned_demos!(runner, demo_checked_primorial); register_unsigned_demos!(runner, demo_product_of_first_n_primes); register_unsigned_demos!(runner, demo_checked_product_of_first_n_primes); register_unsigned_benches!(runner, benchmark_primorial_algorithms); register_unsigned_benches!(runner, benchmark_checked_primorial); register_unsigned_benches!(runner, benchmark_product_of_first_n_primes_algorithms); register_unsigned_benches!(runner, benchmark_checked_product_of_first_n_primes); } fn demo_primorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_27::().get(gm, config).take(limit) { println!("{}# = {}", n, T::primorial(n)); } } fn demo_checked_primorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen().get(gm, config).take(limit) { println!("{}# = {:?}", n, T::checked_primorial(n)); } } fn demo_product_of_first_n_primes( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_28::().get(gm, config).take(limit) { println!("p_{}# = {}", n, T::product_of_first_n_primes(n)); } } fn demo_checked_product_of_first_n_primes( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen().get(gm, config).take(limit) { println!("p_{}# = {:?}", n, T::checked_product_of_first_n_primes(n)); } } fn benchmark_primorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::primorial(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::primorial(n))), ("naive", &mut |n| { no_out!(checked_primorial_naive::(n).unwrap()); }), ], ); } fn benchmark_checked_primorial( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_primorial(u64)", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::checked_primorial(n)))], ); } fn benchmark_product_of_first_n_primes_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::product_of_first_n_primes(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_28::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::product_of_first_n_primes(n))), ("naive", &mut |n| { no_out!(checked_product_of_first_n_primes_naive::(n).unwrap()); }), ], ); } fn benchmark_checked_product_of_first_n_primes( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::checked_product_of_first_n_primes(u64)", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| { no_out!(T::checked_product_of_first_n_primes(n)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_reciprocal_primitive_float); register_primitive_float_demos!(runner, demo_reciprocal_assign_primitive_float); register_primitive_float_benches!(runner, benchmark_reciprocal_primitive_float); register_primitive_float_benches!(runner, benchmark_reciprocal_assign_primitive_float); } fn demo_reciprocal_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for f in primitive_float_gen::().get(gm, config).take(limit) { println!( "({}).reciprocal() = {}", NiceFloat(f), NiceFloat(f.reciprocal()) ); } } fn demo_reciprocal_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.reciprocal_assign(); println!( "f := {}; f.reciprocal_assign(); x = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_reciprocal_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.reciprocal()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(f.reciprocal()))], ); } fn benchmark_reciprocal_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.reciprocal_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.reciprocal_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::arithmetic::root::{ cbrt_chebyshev_approx_u32, cbrt_chebyshev_approx_u64, fast_ceiling_root_u32, fast_ceiling_root_u64, fast_checked_root_u32, fast_checked_root_u64, fast_floor_cbrt_u32, fast_floor_cbrt_u64, fast_floor_root_u32, fast_floor_root_u64, fast_root_rem_u32, fast_root_rem_u64, floor_root_approx_and_refine, }; use malachite_base::num::arithmetic::root::{ ceiling_root_binary, checked_root_binary, floor_root_binary, root_rem_binary, }; use malachite_base::num::arithmetic::traits::{CeilingRoot, CheckedRoot, FloorRoot, RootRem}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_18, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_32, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_floor_cbrt_unsigned); register_signed_demos!(runner, demo_floor_cbrt_signed); register_unsigned_demos!(runner, demo_floor_cbrt_assign_unsigned); register_signed_demos!(runner, demo_floor_cbrt_assign_signed); register_unsigned_demos!(runner, demo_ceiling_cbrt_unsigned); register_signed_demos!(runner, demo_ceiling_cbrt_signed); register_unsigned_demos!(runner, demo_ceiling_cbrt_assign_unsigned); register_signed_demos!(runner, demo_ceiling_cbrt_assign_signed); register_unsigned_demos!(runner, demo_checked_cbrt_unsigned); register_signed_demos!(runner, demo_checked_cbrt_signed); register_unsigned_demos!(runner, demo_cbrt_rem); register_unsigned_demos!(runner, demo_cbrt_assign_rem); register_unsigned_demos!(runner, demo_floor_root_unsigned); register_signed_demos!(runner, demo_floor_root_signed); register_unsigned_demos!(runner, demo_floor_root_assign_unsigned); register_signed_demos!(runner, demo_floor_root_assign_signed); register_unsigned_demos!(runner, demo_ceiling_root_unsigned); register_signed_demos!(runner, demo_ceiling_root_signed); register_unsigned_demos!(runner, demo_ceiling_root_assign_unsigned); register_signed_demos!(runner, demo_ceiling_root_assign_signed); register_unsigned_demos!(runner, demo_checked_root_unsigned); register_signed_demos!(runner, demo_checked_root_signed); register_unsigned_demos!(runner, demo_root_rem); register_unsigned_demos!(runner, demo_root_assign_rem); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_u8); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_u16); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_u32); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_u64); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_u128); register_bench!(runner, benchmark_floor_cbrt_algorithms_unsigned_usize); register_signed_benches!(runner, benchmark_floor_cbrt_signed); register_unsigned_benches!(runner, benchmark_floor_cbrt_assign_unsigned); register_signed_benches!(runner, benchmark_floor_cbrt_assign_signed); register_unsigned_benches!(runner, benchmark_ceiling_cbrt_algorithms_unsigned); register_signed_benches!(runner, benchmark_ceiling_cbrt_signed); register_unsigned_benches!(runner, benchmark_ceiling_cbrt_assign_unsigned); register_signed_benches!(runner, benchmark_ceiling_cbrt_assign_signed); register_unsigned_benches!(runner, benchmark_checked_cbrt_algorithms_unsigned); register_signed_benches!(runner, benchmark_checked_cbrt_signed); register_unsigned_benches!(runner, benchmark_cbrt_rem_algorithms); register_unsigned_benches!(runner, benchmark_cbrt_assign_rem); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_u8); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_u16); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_u32); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_u64); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_u128); register_bench!(runner, benchmark_floor_root_algorithms_unsigned_usize); register_signed_benches!(runner, benchmark_floor_root_signed); register_unsigned_benches!(runner, benchmark_floor_root_assign_unsigned); register_signed_benches!(runner, benchmark_floor_root_assign_signed); register_unsigned_benches!(runner, benchmark_ceiling_root_algorithms_unsigned); register_signed_benches!(runner, benchmark_ceiling_root_signed); register_unsigned_benches!(runner, benchmark_ceiling_root_assign_unsigned); register_signed_benches!(runner, benchmark_ceiling_root_assign_signed); register_unsigned_benches!(runner, benchmark_checked_root_algorithms_unsigned); register_signed_benches!(runner, benchmark_checked_root_signed); register_unsigned_benches!(runner, benchmark_root_rem_algorithms); register_unsigned_benches!(runner, benchmark_root_assign_rem); register_bench!(runner, benchmark_floor_cbrt_algorithms_2_u32); register_bench!(runner, benchmark_floor_cbrt_algorithms_2_u64); register_bench!(runner, benchmark_floor_root_algorithms_2_u32); register_bench!(runner, benchmark_floor_root_algorithms_2_u64); register_bench!(runner, benchmark_ceiling_root_algorithms_2_u32); register_bench!(runner, benchmark_ceiling_root_algorithms_2_u64); register_bench!(runner, benchmark_checked_root_algorithms_2_u32); register_bench!(runner, benchmark_checked_root_algorithms_2_u64); register_bench!(runner, benchmark_root_rem_algorithms_2_u32); register_bench!(runner, benchmark_root_rem_algorithms_2_u64); } fn demo_floor_cbrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("floor_root({}, 3) = {}", n, n.floor_root(3)); } } fn demo_floor_cbrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen::().get(gm, config).take(limit) { println!("floor_root({}, 3) = {}", n, n.floor_root(3)); } } fn demo_floor_cbrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; n.floor_root_assign(3); println!("n := {old_n}; n.floor_root_assign(3); n = {n}"); } } fn demo_floor_cbrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in signed_gen::().get(gm, config).take(limit) { let old_n = n; n.floor_root_assign(3); println!("n := {old_n}; n.floor_root_assign(3); n = {n}"); } } fn demo_ceiling_cbrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("ceiling_root({}, 3) = {}", n, n.ceiling_root(3)); } } fn demo_ceiling_cbrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen::().get(gm, config).take(limit) { println!("ceiling_root({}, 3) = {}", n, n.ceiling_root(3)); } } fn demo_ceiling_cbrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; n.ceiling_root_assign(3); println!("n := {old_n}; n.ceiling_root_assign(3); n = {n}"); } } fn demo_ceiling_cbrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in signed_gen::().get(gm, config).take(limit) { let old_n = n; n.ceiling_root_assign(3); println!("n := {old_n}; n.ceiling_root_assign(3); n = {n}"); } } fn demo_checked_cbrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("checked_root({}, 3) = {:?}", n, n.checked_root(3)); } } fn demo_checked_cbrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen::().get(gm, config).take(limit) { println!("checked_root({}, 3) = {:?}", n, n.checked_root(3)); } } fn demo_cbrt_rem(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("root_rem({}, 3) = {:?}", n, n.root_rem(3)); } } fn demo_cbrt_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; let rem = n.root_assign_rem(3); println!("n := {old_n}; n.root_assign_rem(3) = {rem}; n = {n}"); } } fn demo_floor_root_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { println!("floor_root({}, {}) = {}", n, exp, n.floor_root(exp)); } } fn demo_floor_root_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in signed_unsigned_pair_gen_var_18::() .get(gm, config) .take(limit) { println!("floor_root({}, {}) = {}", n, exp, n.floor_root(exp)); } } fn demo_floor_root_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { let old_n = n; n.floor_root_assign(exp); println!("n := {old_n}; n.floor_root_assign({exp}); n = {n}"); } } fn demo_floor_root_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, exp) in signed_unsigned_pair_gen_var_18::() .get(gm, config) .take(limit) { let old_n = n; n.floor_root_assign(exp); println!("n := {old_n}; n.floor_root_assign({exp}); n = {n}"); } } fn demo_ceiling_root_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { println!("ceiling_root({}, {}) = {}", n, exp, n.ceiling_root(exp)); } } fn demo_ceiling_root_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in signed_unsigned_pair_gen_var_18::() .get(gm, config) .take(limit) { println!("ceiling_root({}, {}) = {}", n, exp, n.ceiling_root(exp)); } } fn demo_ceiling_root_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { let old_n = n; n.floor_root_assign(exp); println!("n := {old_n}; n.ceiling_root_assign({exp}); n = {n}"); } } fn demo_ceiling_root_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, exp) in signed_unsigned_pair_gen_var_18::() .get(gm, config) .take(limit) { let old_n = n; n.floor_root_assign(exp); println!("n := {old_n}; n.ceiling_root_assign({exp}); n = {n}"); } } fn demo_checked_root_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { println!("checked_root({}, {}) = {:?}", n, exp, n.checked_root(exp)); } } fn demo_checked_root_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in signed_unsigned_pair_gen_var_18::() .get(gm, config) .take(limit) { println!("checked_root({}, {}) = {:?}", n, exp, n.checked_root(exp)); } } fn demo_root_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { println!("root_rem({}, {}) = {:?}", n, exp, n.root_rem(exp)); } } fn demo_root_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, exp) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { let old_n = n; let rem = n.root_assign_rem(exp); println!("n := {old_n}; n.root_assign_rem({exp}) = {rem}; n = {n}"); } } macro_rules! benchmark_floor_cbrt_algorithms_unsigned { ($t:ident, $f:ident) => { fn $f(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { #[allow(clippy::cast_lossless)] run_benchmark( &format!("{}.floor_root(3)", $t::NAME), BenchmarkType::Algorithms, unsigned_gen::<$t>().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.floor_root(3))), ("binary", &mut |n| no_out!(floor_root_binary(n, 3))), ("approx and refine", &mut |n| { no_out!(floor_root_approx_and_refine( |x| x as f64, |f| f as $t, n, 3 )) }), ], ); } }; } benchmark_floor_cbrt_algorithms_unsigned!(u8, benchmark_floor_cbrt_algorithms_unsigned_u8); benchmark_floor_cbrt_algorithms_unsigned!(u16, benchmark_floor_cbrt_algorithms_unsigned_u16); benchmark_floor_cbrt_algorithms_unsigned!(u32, benchmark_floor_cbrt_algorithms_unsigned_u32); benchmark_floor_cbrt_algorithms_unsigned!(u64, benchmark_floor_cbrt_algorithms_unsigned_u64); benchmark_floor_cbrt_algorithms_unsigned!(u128, benchmark_floor_cbrt_algorithms_unsigned_u128); benchmark_floor_cbrt_algorithms_unsigned!(usize, benchmark_floor_cbrt_algorithms_unsigned_usize); fn benchmark_floor_cbrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_root(3)", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.floor_root(3)))], ); } fn benchmark_floor_cbrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_root_assign(3)", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.floor_root_assign(3))], ); } fn benchmark_floor_cbrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_cbrt_assign(3)", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.floor_root_assign(3))], ); } fn benchmark_ceiling_cbrt_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root(3)", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.ceiling_root(3))), ("binary", &mut |n| no_out!(ceiling_root_binary(n, 3))), ], ); } fn benchmark_ceiling_cbrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root(3)", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.ceiling_root(3)))], ); } fn benchmark_ceiling_cbrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root_assign(3)", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.ceiling_root_assign(3))], ); } fn benchmark_ceiling_cbrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_cbrt_assign(3)", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.ceiling_root_assign(3))], ); } fn benchmark_checked_cbrt_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_root(3)", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.checked_root(3))), ("binary", &mut |n| no_out!(checked_root_binary(n, 3))), ], ); } fn benchmark_checked_cbrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_roor(3)", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.checked_root(3)))], ); } fn benchmark_cbrt_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.root_rem(3)", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.root_rem(3))), ("binary", &mut |n| no_out!(root_rem_binary(n, 3))), ], ); } fn benchmark_cbrt_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.root_assign_rem(3)", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| no_out!(n.root_assign_rem(3)))], ); } macro_rules! benchmark_floor_root_algorithms_unsigned { ($t:ident, $f:ident) => { fn $f(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { #[allow(clippy::cast_lossless)] run_benchmark( &format!("{}.floor_root(u64)", $t::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_32::<$t, u64>().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.floor_root(exp))), ("binary", &mut |(n, exp)| no_out!(floor_root_binary(n, exp))), ("approx and refine", &mut |(n, exp)| { no_out!(floor_root_approx_and_refine( |x| x as f64, |f| f as $t, n, exp )) }), ], ); } }; } benchmark_floor_root_algorithms_unsigned!(u8, benchmark_floor_root_algorithms_unsigned_u8); benchmark_floor_root_algorithms_unsigned!(u16, benchmark_floor_root_algorithms_unsigned_u16); benchmark_floor_root_algorithms_unsigned!(u32, benchmark_floor_root_algorithms_unsigned_u32); benchmark_floor_root_algorithms_unsigned!(u64, benchmark_floor_root_algorithms_unsigned_u64); benchmark_floor_root_algorithms_unsigned!(u128, benchmark_floor_root_algorithms_unsigned_u128); benchmark_floor_root_algorithms_unsigned!(usize, benchmark_floor_root_algorithms_unsigned_usize); fn benchmark_floor_root_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_root(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(n, exp)| no_out!(n.floor_root(exp)))], ); } fn benchmark_floor_root_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_root_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.floor_root_assign(exp))], ); } fn benchmark_floor_root_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_root_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.floor_root_assign(exp))], ); } fn benchmark_ceiling_root_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.ceiling_root(exp))), ("binary", &mut |(n, exp)| { no_out!(ceiling_root_binary(n, exp)); }), ], ); } fn benchmark_ceiling_root_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(n, exp)| no_out!(n.ceiling_root(exp)))], ); } fn benchmark_ceiling_root_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.ceiling_root_assign(exp))], ); } fn benchmark_ceiling_root_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_root_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.ceiling_root_assign(exp))], ); } fn benchmark_checked_root_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_root(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.checked_root(exp))), ("binary", &mut |(n, exp)| { no_out!(checked_root_binary(n, exp)); }), ], ); } fn benchmark_checked_root_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_root(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(n, exp)| no_out!(n.checked_root(exp)))], ); } fn benchmark_root_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.root_rem(u64)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.root_rem(exp))), ("binary", &mut |(n, exp)| no_out!(root_rem_binary(n, exp))), ], ); } fn benchmark_root_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.root_assign_rem(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| { no_out!(n.root_assign_rem(exp)); })], ); } fn benchmark_floor_cbrt_algorithms_2_u32( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.floor_root(3)", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.floor_root(3))), ("binary", &mut |n| no_out!(floor_root_binary(n, 3))), ("fast", &mut |n| no_out!(fast_floor_cbrt_u32(n))), ("Chebyshev", &mut |n| no_out!(cbrt_chebyshev_approx_u32(n))), ("approx and refine", &mut |n| { no_out!(floor_root_approx_and_refine(f64::from, |f| f as u32, n, 3)); }), ], ); } fn benchmark_floor_cbrt_algorithms_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.floor_root(3)", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.floor_root(3))), ("binary", &mut |n| no_out!(floor_root_binary(n, 3))), ("fast", &mut |n| no_out!(fast_floor_cbrt_u64(n))), ("Chebyshev", &mut |n| no_out!(cbrt_chebyshev_approx_u64(n))), ("approx and refine", &mut |n| { no_out!(floor_root_approx_and_refine( |x| x as f64, |f| f as u64, n, 3 )); }), ], ); } fn benchmark_floor_root_algorithms_2_u32( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.floor_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.floor_root(exp))), ("binary", &mut |(n, exp)| no_out!(floor_root_binary(n, exp))), ("fast", &mut |(n, exp)| no_out!(fast_floor_root_u32(n, exp))), ("approx and refine", &mut |(n, exp)| { no_out!(floor_root_approx_and_refine( f64::from, |f| f as u32, n, exp )); }), ], ); } fn benchmark_floor_root_algorithms_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.floor_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.floor_root(exp))), ("binary", &mut |(n, exp)| no_out!(floor_root_binary(n, exp))), ("fast", &mut |(n, exp)| no_out!(fast_floor_root_u64(n, exp))), ("approx and refine", &mut |(n, exp)| { no_out!(floor_root_approx_and_refine( |x| x as f64, |f| f as u64, n, exp )); }), ], ); } fn benchmark_ceiling_root_algorithms_2_u32( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.ceiling_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.ceiling_root(exp))), ("binary", &mut |(n, exp)| { no_out!(ceiling_root_binary(n, exp)); }), ("fast", &mut |(n, exp)| { no_out!(fast_ceiling_root_u32(n, exp)); }), ], ); } fn benchmark_ceiling_root_algorithms_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.ceiling_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.ceiling_root(exp))), ("binary", &mut |(n, exp)| { no_out!(ceiling_root_binary(n, exp)); }), ("fast", &mut |(n, exp)| { no_out!(fast_ceiling_root_u64(n, exp)); }), ], ); } fn benchmark_checked_root_algorithms_2_u32( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.checked_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.checked_root(exp))), ("binary", &mut |(n, exp)| { no_out!(checked_root_binary(n, exp)); }), ("fast", &mut |(n, exp)| { no_out!(fast_checked_root_u32(n, exp)); }), ], ); } fn benchmark_checked_root_algorithms_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.checked_root(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.checked_root(exp))), ("binary", &mut |(n, exp)| { no_out!(checked_root_binary(n, exp)); }), ("fast", &mut |(n, exp)| { no_out!(fast_checked_root_u64(n, exp)); }), ], ); } fn benchmark_root_rem_algorithms_2_u32( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.root_rem(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.root_rem(exp))), ("binary", &mut |(n, exp)| no_out!(root_rem_binary(n, exp))), ("fast", &mut |(n, exp)| no_out!(fast_root_rem_u32(n, exp))), ], ); } fn benchmark_root_rem_algorithms_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.root_rem(u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("default", &mut |(n, exp)| no_out!(n.root_rem(exp))), ("binary", &mut |(n, exp)| no_out!(root_rem_binary(n, exp))), ("fast", &mut |(n, exp)| no_out!(fast_root_rem_u64(n, exp))), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/rotate.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rotate_left_assign_unsigned); register_signed_demos!(runner, demo_rotate_left_assign_signed); register_unsigned_demos!(runner, demo_rotate_right_assign_unsigned); register_signed_demos!(runner, demo_rotate_right_assign_signed); register_unsigned_benches!(runner, benchmark_rotate_left_assign_unsigned); register_signed_benches!(runner, benchmark_rotate_left_assign_signed); register_unsigned_benches!(runner, benchmark_rotate_right_assign_unsigned); register_signed_benches!(runner, benchmark_rotate_right_assign_signed); } fn demo_rotate_left_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut u, n) in unsigned_pair_gen::().get(gm, config).take(limit) { let old_u = u; u.rotate_left_assign(n); println!("u := {old_u}; u.rotate_left_assign({n}); u = {u}"); } } fn demo_rotate_left_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut i, n) in signed_unsigned_pair_gen::() .get(gm, config) .take(limit) { let old_i = i; i.rotate_left_assign(n); println!("i := {old_i}; i.rotate_left_assign({n}); i = {i}"); } } fn demo_rotate_right_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut u, n) in unsigned_pair_gen::().get(gm, config).take(limit) { let old_u = u; u.rotate_right_assign(n); println!("u := {old_u}; u.rotate_right_assign({n}); u = {u}"); } } fn demo_rotate_right_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut i, n) in signed_unsigned_pair_gen::() .get(gm, config) .take(limit) { let old_i = i; i.rotate_right_assign(n); println!("i := {old_i}; i.rotate_right_assign({n}); i = {i}"); } } fn benchmark_rotate_left_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rotate_left_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(mut u, n)| u.rotate_left_assign(n))], ); } fn benchmark_rotate_left_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rotate_left_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("i"), &mut [("Malachite", &mut |(mut i, n)| i.rotate_left_assign(n))], ); } fn benchmark_rotate_right_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rotate_right_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(mut u, n)| u.rotate_right_assign(n))], ); } fn benchmark_rotate_right_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rotate_right_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("i"), &mut [("Malachite", &mut |(mut i, n)| i.rotate_right_assign(n))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::test_util::bench::bucketers::triple_1_2_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_signed_rounding_mode_triple_gen_var_2, unsigned_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_round_to_multiple_unsigned); register_unsigned_demos!(runner, demo_round_to_multiple_assign_unsigned); register_signed_unsigned_match_demos!(runner, demo_round_to_multiple_signed); register_signed_unsigned_match_demos!(runner, demo_round_to_multiple_assign_signed); register_unsigned_benches!(runner, benchmark_round_to_multiple_unsigned); register_unsigned_benches!(runner, benchmark_round_to_multiple_assign_unsigned); register_signed_unsigned_match_benches!(runner, benchmark_round_to_multiple_signed); register_signed_unsigned_match_benches!(runner, benchmark_round_to_multiple_assign_signed); } fn demo_round_to_multiple_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}.round_to_multiple({}, {}) = {:?}", x, y, rm, x.round_to_multiple(y, rm) ); } } fn demo_round_to_multiple_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_x = x; let o = x.round_to_multiple_assign(y, rm); println!("x := {old_x}; x.round_to_multiple_assign({y}, {rm}) = {o:?}; x = {x}"); } } fn demo_round_to_multiple_signed< S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, rm) in signed_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "({}).round_to_multiple({}, {}) = {:?}", x, y, rm, x.round_to_multiple(y, rm) ); } } fn demo_round_to_multiple_assign_signed< S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, rm) in signed_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_x = x; let o = x.round_to_multiple_assign(y, rm); println!("x := {old_x}; x.round_to_multiple_assign({y}, {rm}) = {o:?}; x = {x}"); } } fn benchmark_round_to_multiple_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.round_to_multiple({}, RoundingMode)", T::NAME, T::NAME), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, rm)| { no_out!(x.round_to_multiple(y, rm)); })], ); } fn benchmark_round_to_multiple_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_assign({}, RoundingMode)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_assign(y, rm)); })], ); } fn benchmark_round_to_multiple_signed< S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.round_to_multiple({}, RoundingMode)", S::NAME, S::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y, rm)| { no_out!(x.round_to_multiple(y, rm)); })], ); } fn benchmark_round_to_multiple_assign_signed< S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_assign({}, RoundingMode)", S::NAME, S::NAME ), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_assign(y, rm)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_rounding_mode_triple_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_3, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_round_to_multiple_of_power_of_2_unsigned); register_unsigned_demos!(runner, demo_round_to_multiple_of_power_of_2_assign_unsigned); register_signed_demos!(runner, demo_round_to_multiple_of_power_of_2_signed); register_signed_demos!(runner, demo_round_to_multiple_of_power_of_2_assign_signed); register_unsigned_benches!(runner, benchmark_round_to_multiple_of_power_of_2_unsigned); register_unsigned_benches!( runner, benchmark_round_to_multiple_of_power_of_2_assign_unsigned ); register_signed_benches!(runner, benchmark_round_to_multiple_of_power_of_2_signed); register_signed_benches!( runner, benchmark_round_to_multiple_of_power_of_2_assign_signed ); } fn demo_round_to_multiple_of_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, pow, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.round_to_multiple_of_power_of_2({}, {}) = {:?}", x, pow, rm, x.round_to_multiple_of_power_of_2(pow, rm) ); } } fn demo_round_to_multiple_of_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, pow, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { let old_x = x; let o = x.round_to_multiple_of_power_of_2_assign(pow, rm); println!( "x := {old_x}; x.round_to_multiple_of_power_of_2_assign({pow}, {rm}) = {o:?}; x = {x}" ); } } fn demo_round_to_multiple_of_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, pow, rm) in signed_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "({}).round_to_multiple_of_power_of_2({}, {}) = {:?}", x, pow, rm, x.round_to_multiple_of_power_of_2(pow, rm) ); } } fn demo_round_to_multiple_of_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, pow, rm) in signed_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_x = x; let o = x.round_to_multiple_of_power_of_2_assign(pow, rm); println!( "x := {old_x}; x.round_to_multiple_of_power_of_2_assign({pow}, {rm}) = {o:?}; x = {x}" ); } } fn benchmark_round_to_multiple_of_power_of_2_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_of_power_of_2({}, RoundingMode)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2(y, rm)); })], ); } fn benchmark_round_to_multiple_of_power_of_2_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_of_power_of_2_assign({}, RoundingMode)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2_assign(y, rm)); })], ); } fn benchmark_round_to_multiple_of_power_of_2_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_of_power_of_2({}, RoundingMode)", T::NAME, T::NAME ), BenchmarkType::Single, signed_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2(y, rm)); })], ); } fn benchmark_round_to_multiple_of_power_of_2_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.round_to_multiple_of_power_of_2_assign({}, RoundingMode)", T::NAME, T::NAME ), BenchmarkType::Single, signed_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2_assign(y, rm)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::signed_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_saturating_abs_assign); register_signed_benches!(runner, benchmark_saturating_abs_assign); } fn demo_saturating_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; i.saturating_abs_assign(); println!("i := {old_i}; i.saturating_abs_assign(); i = {i}"); } } fn benchmark_saturating_abs_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_abs_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.saturating_abs_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_add_unsigned); register_signed_demos!(runner, demo_saturating_add_signed); register_unsigned_demos!(runner, demo_saturating_add_assign_unsigned); register_signed_demos!(runner, demo_saturating_add_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_add_unsigned); register_signed_benches!(runner, benchmark_saturating_add_signed); register_unsigned_benches!(runner, benchmark_saturating_add_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_add_assign_signed); } fn demo_saturating_add_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.saturating_add({}) = {}", x, y, x.saturating_add(y)); } } fn demo_saturating_add_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).saturating_add({}) = {}", x, y, x.saturating_add(y)); } } fn demo_saturating_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.saturating_add_assign(y); println!("x := {old_x}; x.saturating_add_assign({y}); x = {x}"); } } fn demo_saturating_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_add_assign(y); println!("x := {old_x}; x.saturating_add_assign({y}); x = {x}"); } } fn benchmark_saturating_add_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_add(y)))], ); } fn benchmark_saturating_add_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_add(y)))], ); } fn benchmark_saturating_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_add_assign(y))], ); } fn benchmark_saturating_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_add_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_add_mul_unsigned); register_signed_demos!(runner, demo_saturating_add_mul_signed); register_unsigned_demos!(runner, demo_saturating_add_mul_assign_unsigned); register_signed_demos!(runner, demo_saturating_add_mul_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_add_mul_unsigned); register_signed_benches!(runner, benchmark_saturating_add_mul_signed); register_unsigned_benches!(runner, benchmark_saturating_add_mul_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_add_mul_assign_signed); } fn demo_saturating_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.saturating_add_mul({}, {}) = {}", x, y, z, x.saturating_add_mul(y, z) ); } } fn demo_saturating_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.saturating_add_mul({}, {}) = {}", x, y, z, x.saturating_add_mul(y, z) ); } } fn demo_saturating_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; x.saturating_add_mul_assign(y, z); println!("x := {old_x}; x.saturating_add_mul_assign({y}, {z}); x = {x}"); } } fn demo_saturating_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_add_mul_assign(y, z); println!("x := {old_x}; x.saturating_add_mul_assign({y}, {z}); x = {x}"); } } fn benchmark_saturating_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.saturating_add_mul(y, z)); })], ); } fn benchmark_saturating_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.saturating_add_mul(y, z)); })], ); } fn benchmark_saturating_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.saturating_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.saturating_add_mul_assign(y, z); })], ); } fn benchmark_saturating_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.saturating_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.saturating_add_mul_assign(y, z); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_mul_unsigned); register_signed_demos!(runner, demo_saturating_mul_signed); register_unsigned_demos!(runner, demo_saturating_mul_assign_unsigned); register_signed_demos!(runner, demo_saturating_mul_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_mul_unsigned); register_signed_benches!(runner, benchmark_saturating_mul_signed); register_unsigned_benches!(runner, benchmark_saturating_mul_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_mul_assign_signed); } fn demo_saturating_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.saturating_mul({}) = {}", x, y, x.saturating_mul(y)); } } fn demo_saturating_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).saturating_mul({}) = {}", x, y, x.saturating_mul(y)); } } fn demo_saturating_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.saturating_mul_assign(y); println!("x := {old_x}; x.saturating_mul_assign({y}); x = {x}"); } } fn demo_saturating_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_mul_assign(y); println!("x := {old_x}; x.saturating_mul_assign({y}); x = {x}"); } } fn benchmark_saturating_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_mul({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_mul(y)))], ); } fn benchmark_saturating_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_mul({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_mul(y)))], ); } fn benchmark_saturating_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_mul_assign(y))], ); } fn benchmark_saturating_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_mul_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::signed_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_saturating_neg_assign); register_signed_benches!(runner, benchmark_saturating_neg_assign); } fn demo_saturating_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; i.saturating_neg_assign(); println!("i := {old_i}; i.saturating_neg_assign(); i = {i}"); } } fn benchmark_saturating_neg_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_neg_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.saturating_neg_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_pow_assign_unsigned); register_signed_demos!(runner, demo_saturating_pow_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_pow_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_pow_assign_signed); } fn demo_saturating_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_pow_assign(y); println!("x := {old_x}; x.saturating_pow_assign({y}); x = {x}"); } } fn demo_saturating_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_unsigned_pair_gen::() .get(gm, config) .take(limit) { let old_x = x; x.saturating_pow_assign(y); println!("x := {old_x}; x.saturating_pow_assign({y}); x = {x}"); } } fn benchmark_saturating_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_pow_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_pow_assign(y))], ); } fn benchmark_saturating_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_pow_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_pow_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_square_unsigned); register_signed_demos!(runner, demo_saturating_square_signed); register_unsigned_demos!(runner, demo_saturating_square_assign_unsigned); register_signed_demos!(runner, demo_saturating_square_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_square_unsigned); register_signed_benches!(runner, benchmark_saturating_square_signed); register_unsigned_benches!(runner, benchmark_saturating_square_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_square_assign_signed); } fn demo_saturating_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("{}.saturating_square() = {}", x, x.saturating_square()); } } fn demo_saturating_square_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in signed_gen::().get(gm, config).take(limit) { println!("{}.saturating_square() = {}", x, x.saturating_square()); } } fn demo_saturating_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in unsigned_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_square_assign(); println!("x := {old_x}; x.saturating_square_assign(); x = {x}"); } } fn demo_saturating_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in signed_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_square_assign(); println!("x := {old_x}; x.saturating_square_assign(); x = {x}"); } } fn benchmark_saturating_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_square()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.saturating_square()))], ); } fn benchmark_saturating_square_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_square()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.saturating_square()))], ); } fn benchmark_saturating_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_square_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut x| x.saturating_square_assign())], ); } fn benchmark_saturating_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_square_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut x| x.saturating_square_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_sub_unsigned); register_signed_demos!(runner, demo_saturating_sub_signed); register_unsigned_demos!(runner, demo_saturating_sub_assign_unsigned); register_signed_demos!(runner, demo_saturating_sub_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_sub_unsigned); register_signed_benches!(runner, benchmark_saturating_sub_signed); register_unsigned_benches!(runner, benchmark_saturating_sub_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_sub_assign_signed); } fn demo_saturating_sub_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.saturating_sub({}) = {}", x, y, x.saturating_sub(y)); } } fn demo_saturating_sub_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).saturating_sub({}) = {}", x, y, x.saturating_sub(y)); } } fn demo_saturating_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.saturating_sub_assign(y); println!("x := {old_x}; x.saturating_sub_assign({y}); x = {x}"); } } fn demo_saturating_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_sub_assign(y); println!("x := {old_x}; x.saturating_sub_assign({y}); x = {x}"); } } fn benchmark_saturating_sub_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_sub(y)))], ); } fn benchmark_saturating_sub_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.saturating_sub(y)))], ); } fn benchmark_saturating_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_sub_assign(y))], ); } fn benchmark_saturating_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.saturating_sub_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_saturating_sub_mul_unsigned); register_signed_demos!(runner, demo_saturating_sub_mul_signed); register_unsigned_demos!(runner, demo_saturating_sub_mul_assign_unsigned); register_signed_demos!(runner, demo_saturating_sub_mul_assign_signed); register_unsigned_benches!(runner, benchmark_saturating_sub_mul_unsigned); register_signed_benches!(runner, benchmark_saturating_sub_mul_signed); register_unsigned_benches!(runner, benchmark_saturating_sub_mul_assign_unsigned); register_signed_benches!(runner, benchmark_saturating_sub_mul_assign_signed); } fn demo_saturating_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.saturating_sub_mul({}, {}) = {}", x, y, z, x.saturating_sub_mul(y, z) ); } } fn demo_saturating_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.saturating_sub_mul({}, {}) = {}", x, y, z, x.saturating_sub_mul(y, z) ); } } fn demo_saturating_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; x.saturating_sub_mul_assign(y, z); println!("x := {old_x}; x.saturating_sub_mul_assign({y}, {z}); x = {x}"); } } fn demo_saturating_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; x.saturating_sub_mul_assign(y, z); println!("x := {old_x}; x.saturating_sub_mul_assign({y}, {z}); x = {x}"); } } fn benchmark_saturating_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.saturating_sub_mul(y, z)); })], ); } fn benchmark_saturating_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.saturating_sub_mul(y, z)); })], ); } fn benchmark_saturating_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.saturating_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.saturating_sub_mul_assign(y, z); })], ); } fn benchmark_saturating_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.saturating_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.saturating_sub_mul_assign(y, z); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShlRound, ShlRoundAssign, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_2_unsigned_abs_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_signed_rounding_mode_triple_gen_var_4, unsigned_signed_rounding_mode_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_signed_demos!(runner, demo_shl_round_unsigned_signed); register_signed_signed_demos!(runner, demo_shl_round_signed_signed); register_unsigned_signed_demos!(runner, demo_shl_round_assign_unsigned_signed); register_signed_signed_demos!(runner, demo_shl_round_assign_signed_signed); register_unsigned_signed_benches!(runner, benchmark_shl_round_unsigned_signed); register_signed_signed_benches!(runner, benchmark_shl_round_signed_signed); register_unsigned_signed_benches!(runner, benchmark_shl_round_assign_unsigned_signed); register_signed_signed_benches!(runner, benchmark_shl_round_assign_signed_signed); } fn demo_shl_round_unsigned_signed< T: PrimitiveUnsigned + ShlRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i, rm) in unsigned_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!("{}.shl_round({}, {}) = {:?}", n, i, rm, n.shl_round(i, rm)); } } fn demo_shl_round_signed_signed< T: PrimitiveSigned + ShlRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i, rm) in signed_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { println!( "({}).shl_round({}, {}) = {:?}", n, i, rm, n.shl_round(i, rm) ); } } fn demo_shl_round_assign_unsigned_signed< T: PrimitiveUnsigned + ShlRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, i, rm) in unsigned_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shl_round_assign(i, rm); println!("x := {old_n}; x.shl_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_shl_round_assign_signed_signed< T: PrimitiveSigned + ShlRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, i, rm) in signed_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shl_round_assign(i, rm); println!("x := {old_n}; x.shl_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn benchmark_shl_round_unsigned_signed< T: PrimitiveUnsigned + ShlRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shl_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(n, i, rm)| no_out!(n.shl_round(i, rm)))], ); } fn benchmark_shl_round_signed_signed< T: PrimitiveSigned + ShlRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shl_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(n, i, rm)| no_out!(n.shl_round(i, rm)))], ); } fn benchmark_shl_round_assign_unsigned_signed< T: PrimitiveUnsigned + ShlRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shl_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(mut n, i, rm)| { no_out!(n.shl_round_assign(i, rm)); })], ); } fn benchmark_shl_round_assign_signed_signed< T: PrimitiveSigned + ShlRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shl_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(mut n, i, rm)| { no_out!(n.shl_round_assign(i, rm)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ triple_2_bucketer, triple_2_unsigned_abs_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_signed_rounding_mode_triple_gen_var_3, signed_unsigned_rounding_mode_triple_gen_var_2, unsigned_signed_rounding_mode_triple_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_shr_round_unsigned_unsigned); register_unsigned_signed_demos!(runner, demo_shr_round_unsigned_signed); register_signed_unsigned_demos!(runner, demo_shr_round_signed_unsigned); register_signed_signed_demos!(runner, demo_shr_round_signed_signed); register_unsigned_unsigned_demos!(runner, demo_shr_round_assign_unsigned_unsigned); register_unsigned_signed_demos!(runner, demo_shr_round_assign_unsigned_signed); register_signed_unsigned_demos!(runner, demo_shr_round_assign_signed_unsigned); register_signed_signed_demos!(runner, demo_shr_round_assign_signed_signed); register_unsigned_unsigned_benches!(runner, benchmark_shr_round_unsigned_unsigned); register_unsigned_signed_benches!(runner, benchmark_shr_round_unsigned_signed); register_signed_unsigned_benches!(runner, benchmark_shr_round_signed_unsigned); register_signed_signed_benches!(runner, benchmark_shr_round_signed_signed); register_unsigned_unsigned_benches!(runner, benchmark_shr_round_assign_unsigned_unsigned); register_unsigned_signed_benches!(runner, benchmark_shr_round_assign_unsigned_signed); register_signed_unsigned_benches!(runner, benchmark_shr_round_assign_signed_unsigned); register_signed_signed_benches!(runner, benchmark_shr_round_assign_signed_signed); } fn demo_shr_round_unsigned_unsigned< T: PrimitiveUnsigned + ShrRound, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { println!("{}.shr_round({}, {}) = {:?}", n, u, rm, n.shr_round(u, rm)); } } fn demo_shr_round_unsigned_signed< T: PrimitiveUnsigned + ShrRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i, rm) in unsigned_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!("{}.shr_round({}, {}) = {:?}", n, i, rm, n.shr_round(i, rm)); } } fn demo_shr_round_signed_unsigned< T: PrimitiveSigned + ShrRound, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, rm) in signed_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "({}).shr_round({}, {}) = {:?}", n, u, rm, n.shr_round(u, rm) ); } } fn demo_shr_round_signed_signed< T: PrimitiveSigned + ShrRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i, rm) in signed_signed_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "({}).shr_round({}, {}) = {:?}", n, i, rm, n.shr_round(i, rm) ); } } fn demo_shr_round_assign_unsigned_unsigned< T: PrimitiveUnsigned + ShrRoundAssign, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shr_round_assign(u, rm); println!("x := {old_n}; x.shr_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_shr_round_assign_unsigned_signed< T: PrimitiveUnsigned + ShrRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, i, rm) in unsigned_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shr_round_assign(i, rm); println!("x := {old_n}; x.shr_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_shr_round_assign_signed_unsigned< T: PrimitiveSigned + ShrRoundAssign, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, rm) in signed_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shr_round_assign(u, rm); println!("x := {old_n}; x.shr_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_shr_round_assign_signed_signed< T: PrimitiveSigned + ShrRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, i, rm) in signed_signed_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { let old_n = n; let o = n.shr_round_assign(i, rm); println!("x := {old_n}; x.shr_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn benchmark_shr_round_unsigned_unsigned< T: PrimitiveUnsigned + ShrRound, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.shr_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("u"), &mut [("Malachite", &mut |(n, u, rm)| no_out!(n.shr_round(u, rm)))], ); } fn benchmark_shr_round_unsigned_signed< T: PrimitiveUnsigned + ShrRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shr_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(n, i, rm)| no_out!(n.shr_round(i, rm)))], ); } fn benchmark_shr_round_signed_unsigned< T: PrimitiveSigned + ShrRound, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.shr_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("u"), &mut [("Malachite", &mut |(n, u, rm)| no_out!(n.shr_round(u, rm)))], ); } fn benchmark_shr_round_signed_signed< T: PrimitiveSigned + ShrRound, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shr_round({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(n, i, rm)| no_out!(n.shr_round(i, rm)))], ); } fn benchmark_shr_round_assign_unsigned_unsigned< T: PrimitiveUnsigned + ShrRoundAssign, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.shr_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_unsigned_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("u"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shr_round_assign(u, rm)); })], ); } fn benchmark_shr_round_assign_unsigned_signed< T: PrimitiveUnsigned + ShrRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shr_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, unsigned_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(mut n, i, rm)| { no_out!(n.shr_round_assign(i, rm)); })], ); } fn benchmark_shr_round_assign_signed_unsigned< T: PrimitiveSigned + ShrRoundAssign, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}.shr_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("u"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shr_round_assign(u, rm)); })], ); } fn benchmark_shr_round_assign_signed_signed< T: PrimitiveSigned + ShrRoundAssign, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom<::Output>, { run_benchmark( &format!("{}.shr_round_assign({}, RoundingMode)", T::NAME, U::NAME), BenchmarkType::Single, signed_signed_rounding_mode_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_2_unsigned_abs_bucketer("i"), &mut [("Malachite", &mut |(mut n, i, rm)| { no_out!(n.shr_round_assign(i, rm)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_sign_unsigned); register_signed_demos!(runner, demo_sign_signed); register_primitive_float_demos!(runner, demo_sign_primitive_float); register_unsigned_benches!(runner, benchmark_sign_unsigned); register_signed_benches!(runner, benchmark_sign_signed); register_primitive_float_benches!(runner, benchmark_sign_primitive_float); } fn demo_sign_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.sign() = {:?}", u, u.sign()); } } fn demo_sign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("{}.sign() = {:?}", i, i.sign()); } } fn demo_sign_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in primitive_float_gen::().get(gm, config).take(limit) { println!("({}).sign() = {:?}", NiceFloat(f), f.sign()); } } fn benchmark_sign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.sign()))], ); } fn benchmark_sign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.sign()))], ); } fn benchmark_sign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(f.sign()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::sqrt::{ ceiling_sqrt_binary, checked_sqrt_binary, floor_sqrt_binary, sqrt_rem_binary, sqrt_rem_newton, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, signed_gen_var_2, unsigned_gen, unsigned_gen_var_17, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_floor_sqrt_unsigned); register_signed_demos!(runner, demo_floor_sqrt_signed); register_unsigned_demos!(runner, demo_floor_sqrt_assign_unsigned); register_signed_demos!(runner, demo_floor_sqrt_assign_signed); register_unsigned_demos!(runner, demo_ceiling_sqrt_unsigned); register_signed_demos!(runner, demo_ceiling_sqrt_signed); register_unsigned_demos!(runner, demo_ceiling_sqrt_assign_unsigned); register_signed_demos!(runner, demo_ceiling_sqrt_assign_signed); register_unsigned_demos!(runner, demo_checked_sqrt_unsigned); register_signed_demos!(runner, demo_checked_sqrt_signed); register_unsigned_demos!(runner, demo_sqrt_rem); register_unsigned_demos!(runner, demo_sqrt_assign_rem); register_primitive_float_demos!(runner, demo_sqrt_assign); register_unsigned_benches!(runner, benchmark_floor_sqrt_algorithms_unsigned); register_signed_benches!(runner, benchmark_floor_sqrt_signed); register_unsigned_benches!(runner, benchmark_floor_sqrt_assign_unsigned); register_signed_benches!(runner, benchmark_floor_sqrt_assign_signed); register_unsigned_benches!(runner, benchmark_ceiling_sqrt_algorithms_unsigned); register_signed_benches!(runner, benchmark_ceiling_sqrt_signed); register_unsigned_benches!(runner, benchmark_ceiling_sqrt_assign_unsigned); register_signed_benches!(runner, benchmark_ceiling_sqrt_assign_signed); register_unsigned_benches!(runner, benchmark_checked_sqrt_algorithms_unsigned); register_signed_benches!(runner, benchmark_checked_sqrt_signed); register_unsigned_benches!(runner, benchmark_sqrt_rem_algorithms); register_generic_benches_2_only_first_in_key!( runner, benchmark_sqrt_rem_algorithms_2, [u32, i32], [u64, i64] ); register_unsigned_benches!(runner, benchmark_sqrt_assign_rem); register_primitive_float_benches!(runner, benchmark_sqrt_assign); } fn demo_floor_sqrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("floor_sqrt({}) = {}", n, n.floor_sqrt()); } } fn demo_floor_sqrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen_var_2::().get(gm, config).take(limit) { println!("floor_sqrt({}) = {}", n, n.floor_sqrt()); } } fn demo_floor_sqrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; n.floor_sqrt_assign(); println!("n := {old_n}; n.floor_sqrt_assign(); n = {n}"); } } fn demo_floor_sqrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in signed_gen_var_2::().get(gm, config).take(limit) { let old_n = n; n.floor_sqrt_assign(); println!("n := {old_n}; n.floor_sqrt_assign(); n = {n}"); } } fn demo_ceiling_sqrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("ceiling_sqrt({}) = {}", n, n.ceiling_sqrt()); } } fn demo_ceiling_sqrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen_var_2::().get(gm, config).take(limit) { println!("ceiling_sqrt({}) = {}", n, n.ceiling_sqrt()); } } fn demo_ceiling_sqrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; n.ceiling_sqrt_assign(); println!("n := {old_n}; n.ceiling_sqrt_assign(); n = {n}"); } } fn demo_ceiling_sqrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut n in signed_gen_var_2::().get(gm, config).take(limit) { let old_n = n; n.ceiling_sqrt_assign(); println!("n := {old_n}; n.ceiling_sqrt_assign(); n = {n}"); } } fn demo_checked_sqrt_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { println!("checked_sqrt({}) = {:?}", n, n.checked_sqrt()); } } fn demo_checked_sqrt_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen_var_2::().get(gm, config).take(limit) { println!("checked_sqrt({}) = {:?}", n, n.checked_sqrt()); } } fn demo_sqrt_rem(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen::().get(gm, config).take(limit) { let (sqrt, rem) = n.sqrt_rem(); println!("{n} = {sqrt} ^ 2 + {rem}"); } } fn demo_sqrt_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in unsigned_gen::().get(gm, config).take(limit) { let old_n = n; let rem = n.sqrt_assign_rem(); println!("n := {old_n}; n.sqrt_assign() = {rem}; n = {n}"); } } fn demo_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.sqrt_assign(); println!( "i := {}; i.sqrt_assign(); i = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_floor_sqrt_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_sqrt()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.floor_sqrt())), ("binary", &mut |n| no_out!(floor_sqrt_binary(n))), ], ); } fn benchmark_floor_sqrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_sqrt()", T::NAME), BenchmarkType::Algorithms, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.floor_sqrt()))], ); } fn benchmark_floor_sqrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_sqrt_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.floor_sqrt_assign())], ); } fn benchmark_floor_sqrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.floor_sqrt_assign()", T::NAME), BenchmarkType::Single, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.floor_sqrt_assign())], ); } fn benchmark_ceiling_sqrt_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_sqrt()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.ceiling_sqrt())), ("binary", &mut |n| no_out!(ceiling_sqrt_binary(n))), ], ); } fn benchmark_ceiling_sqrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_sqrt()", T::NAME), BenchmarkType::Single, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.ceiling_sqrt()))], ); } fn benchmark_ceiling_sqrt_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_sqrt_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.ceiling_sqrt_assign())], ); } fn benchmark_ceiling_sqrt_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ceiling_sqrt_assign()", T::NAME), BenchmarkType::Single, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut n| n.ceiling_sqrt_assign())], ); } fn benchmark_checked_sqrt_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_sqrt()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.checked_sqrt())), ("binary", &mut |n| no_out!(checked_sqrt_binary(n))), ], ); } fn benchmark_checked_sqrt_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_sqrt()", T::NAME), BenchmarkType::Single, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(n.checked_sqrt()))], ); } fn benchmark_sqrt_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sqrt_rem()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| no_out!(n.sqrt_rem())), ("binary", &mut |n| no_out!(sqrt_rem_binary(n))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sqrt_rem_algorithms_2< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sqrt_assign_rem()", U::NAME), BenchmarkType::Algorithms, unsigned_gen_var_17::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |n| { for _ in 0..10 { n.sqrt_rem().0; } }), ("Newton's method", &mut |n| { for _ in 0..10 { sqrt_rem_newton::(n).0; } }), ], ); } fn benchmark_sqrt_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sqrt_assign_rem()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut n| no_out!(n.sqrt_assign_rem()))], ); } fn benchmark_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sqrt_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.sqrt_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, signed_gen_var_10, unsigned_gen_var_21, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_square_unsigned); register_unsigned_demos!(runner, demo_square_assign_unsigned); register_signed_unsigned_match_demos!(runner, demo_square_signed); register_signed_unsigned_match_demos!(runner, demo_square_assign_signed); register_primitive_float_demos!(runner, demo_square_primitive_float); register_primitive_float_demos!(runner, demo_square_assign_primitive_float); register_unsigned_benches!(runner, benchmark_square_unsigned); register_unsigned_benches!(runner, benchmark_square_assign_unsigned); register_signed_unsigned_match_benches!(runner, benchmark_square_signed); register_signed_unsigned_match_benches!(runner, benchmark_square_assign_signed); register_primitive_float_benches!(runner, benchmark_square_primitive_float); register_primitive_float_benches!(runner, benchmark_square_assign_primitive_float); } fn demo_square_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_21::().get(gm, config).take(limit) { println!("{}.square() = {}", u, u.square()); } } fn demo_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut u in unsigned_gen_var_21::().get(gm, config).take(limit) { let old_u = u; u.square_assign(); println!("u := {old_u}; u.square_assign(); u = {u}"); } } fn demo_square_signed< S: PrimitiveSigned + WrappingFrom, U: PrimitiveUnsigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen_var_10::().get(gm, config).take(limit) { println!("{}.square() = {}", i, i.square()); } } fn demo_square_assign_signed< S: PrimitiveSigned + WrappingFrom, U: PrimitiveUnsigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut i in signed_gen_var_10::().get(gm, config).take(limit) { let old_i = i; i.square_assign(); println!("i := {old_i}; i.square_assign(); i = {i}"); } } fn demo_square_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in primitive_float_gen::().get(gm, config).take(limit) { println!("({}).square() = {}", NiceFloat(f), NiceFloat(f.square())); } } fn demo_square_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut f in primitive_float_gen::().get(gm, config).take(limit) { let old_f = f; f.square_assign(); println!( "f := {}; f.square_assign(); x = {}", NiceFloat(old_f), NiceFloat(f) ); } } fn benchmark_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square()", T::NAME), BenchmarkType::Single, unsigned_gen_var_21::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.square()))], ); } fn benchmark_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square_assign()", T::NAME), BenchmarkType::Single, unsigned_gen_var_21::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut u| u.square_assign())], ); } fn benchmark_square_signed< S: PrimitiveSigned + WrappingFrom, U: PrimitiveUnsigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square()", S::NAME), BenchmarkType::Single, signed_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.square()))], ); } fn benchmark_square_assign_signed< S: PrimitiveSigned + WrappingFrom, U: PrimitiveUnsigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square_assign()", S::NAME), BenchmarkType::Single, signed_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.square_assign())], ); } fn benchmark_square_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(f.square()))], ); } fn benchmark_square_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.square_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut f| f.square_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ triple_max_bit_bucketer, triple_max_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_triple_gen, signed_triple_gen_var_2, unsigned_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_sub_mul_unsigned); register_signed_demos!(runner, demo_sub_mul_signed); register_primitive_float_demos!(runner, demo_sub_mul_primitive_float); register_unsigned_demos!(runner, demo_sub_mul_assign_unsigned); register_signed_demos!(runner, demo_sub_mul_assign_signed); register_primitive_float_demos!(runner, demo_sub_mul_assign_primitive_float); register_unsigned_benches!(runner, benchmark_sub_mul_unsigned); register_signed_benches!(runner, benchmark_sub_mul_signed); register_primitive_float_benches!(runner, benchmark_sub_mul_primitive_float); register_unsigned_benches!(runner, benchmark_sub_mul_assign_unsigned); register_signed_benches!(runner, benchmark_sub_mul_assign_signed); register_primitive_float_benches!(runner, benchmark_sub_mul_assign_primitive_float); } fn demo_sub_mul_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in unsigned_triple_gen_var_2::().get(gm, config).take(limit) { println!("{}.sub_mul({}, {}) = {}", x, y, z, x.sub_mul(y, z)); } } fn demo_sub_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen_var_2::().get(gm, config).take(limit) { println!("({}).sub_mul({}, {}) = {}", x, y, z, x.sub_mul(y, z)); } } fn demo_sub_mul_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in primitive_float_triple_gen::() .get(gm, config) .take(limit) { println!( "({}).sub_mul({}, {}) = {}", NiceFloat(x), NiceFloat(y), NiceFloat(z), NiceFloat(x.sub_mul(y, z)) ); } } fn demo_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_2::().get(gm, config).take(limit) { let old_x = x; x.sub_mul_assign(y, z); println!("x := {old_x}; x.sub_mul_assign({y}, {z}); x = {x}"); } } fn demo_sub_mul_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in signed_triple_gen_var_2::().get(gm, config).take(limit) { let old_x = x; x.sub_mul_assign(y, z); println!("x := {old_x}; x.sub_mul_assign({y}, {z}); x = {x}"); } } fn demo_sub_mul_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in primitive_float_triple_gen::() .get(gm, config) .take(limit) { let old_x = x; x.sub_mul_assign(y, z); println!( "x := {}; x.sub_mul_assign({}, {}); x = {}", NiceFloat(old_x), NiceFloat(y), NiceFloat(z), NiceFloat(x) ); } } fn benchmark_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.sub_mul(y, z)))], ); } fn benchmark_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.sub_mul(y, z)))], ); } fn benchmark_sub_mul_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, primitive_float_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_primitive_float_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| no_out!(x.sub_mul(y, z)))], ); } fn benchmark_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.sub_mul_assign(y, z))], ); } fn benchmark_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.sub_mul_assign(y, z))], ); } fn benchmark_sub_mul_assign_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, primitive_float_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_primitive_float_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| x.sub_mul_assign(y, z))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::signed_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_wrapping_abs_assign); register_signed_benches!(runner, benchmark_wrapping_abs_assign); } fn demo_wrapping_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; i.wrapping_abs_assign(); println!("i := {old_i}; i.wrapping_abs_assign(); i = {i}"); } } fn benchmark_wrapping_abs_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_abs_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.wrapping_abs_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_add_unsigned); register_signed_demos!(runner, demo_wrapping_add_signed); register_unsigned_demos!(runner, demo_wrapping_add_assign_unsigned); register_signed_demos!(runner, demo_wrapping_add_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_add_unsigned); register_signed_benches!(runner, benchmark_wrapping_add_signed); register_unsigned_benches!(runner, benchmark_wrapping_add_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_add_assign_signed); } fn demo_wrapping_add_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.wrapping_add({}) = {}", x, y, x.wrapping_add(y)); } } fn demo_wrapping_add_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).wrapping_add({}) = {}", x, y, x.wrapping_add(y)); } } fn demo_wrapping_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.wrapping_add_assign(y); println!("x := {old_x}; x.wrapping_add_assign({y}); x = {x}"); } } fn demo_wrapping_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_add_assign(y); println!("x := {old_x}; x.wrapping_add_assign({y}); x = {x}"); } } fn benchmark_wrapping_add_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_add(y)))], ); } fn benchmark_wrapping_add_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_add(y)))], ); } fn benchmark_wrapping_add_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_add_assign(y))], ); } fn benchmark_wrapping_add_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_add_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_add_mul_unsigned); register_signed_demos!(runner, demo_wrapping_add_mul_signed); register_unsigned_demos!(runner, demo_wrapping_add_mul_assign_unsigned); register_signed_demos!(runner, demo_wrapping_add_mul_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_add_mul_unsigned); register_signed_benches!(runner, benchmark_wrapping_add_mul_signed); register_unsigned_benches!(runner, benchmark_wrapping_add_mul_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_add_mul_assign_signed); } fn demo_wrapping_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.wrapping_add_mul({}, {}) = {}", x, y, z, x.wrapping_add_mul(y, z) ); } } fn demo_wrapping_add_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.wrapping_add_mul({}, {}) = {}", x, y, z, x.wrapping_add_mul(y, z) ); } } fn demo_wrapping_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; x.wrapping_add_mul_assign(y, z); println!("x := {old_x}; x.wrapping_add_mul_assign({y}, {z}); x = {x}"); } } fn demo_wrapping_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_add_mul_assign(y, z); println!("x := {old_x}; x.wrapping_add_mul_assign({y}, {z}); x = {x}"); } } fn benchmark_wrapping_add_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.wrapping_add_mul(y, z)); })], ); } fn benchmark_wrapping_add_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_add_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.wrapping_add_mul(y, z)); })], ); } fn benchmark_wrapping_add_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.wrapping_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.wrapping_add_mul_assign(y, z); })], ); } fn benchmark_wrapping_add_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.wrapping_add_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.wrapping_add_mul_assign(y, z); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_div.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen_var_6, unsigned_pair_gen_var_12}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_div_unsigned); register_signed_demos!(runner, demo_wrapping_div_signed); register_unsigned_demos!(runner, demo_wrapping_div_assign_unsigned); register_signed_demos!(runner, demo_wrapping_div_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_div_unsigned); register_signed_benches!(runner, benchmark_wrapping_div_signed); register_unsigned_benches!(runner, benchmark_wrapping_div_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_div_assign_signed); } fn demo_wrapping_div_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!("{}.wrapping_div({}) = {}", x, y, x.wrapping_div(y)); } } fn demo_wrapping_div_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { println!("({}).wrapping_div({}) = {}", x, y, x.wrapping_div(y)); } } fn demo_wrapping_div_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { let old_x = x; x.wrapping_div_assign(y); println!("x := {old_x}; x.wrapping_div_assign({y}); x = {x}"); } } fn demo_wrapping_div_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen_var_6::().get(gm, config).take(limit) { let old_x = x; x.wrapping_div_assign(y); println!("x := {old_x}; x.wrapping_div_assign({y}); x = {x}"); } } fn benchmark_wrapping_div_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_div({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_div(y)))], ); } fn benchmark_wrapping_div_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_div({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_div(y)))], ); } fn benchmark_wrapping_div_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_div_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_div_assign(y))], ); } fn benchmark_wrapping_div_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_div_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_div_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_mul_unsigned); register_signed_demos!(runner, demo_wrapping_mul_signed); register_unsigned_demos!(runner, demo_wrapping_mul_assign_unsigned); register_signed_demos!(runner, demo_wrapping_mul_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_mul_unsigned); register_signed_benches!(runner, benchmark_wrapping_mul_signed); register_unsigned_benches!(runner, benchmark_wrapping_mul_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_mul_assign_signed); } fn demo_wrapping_mul_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.wrapping_mul({}) = {}", x, y, x.wrapping_mul(y)); } } fn demo_wrapping_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).wrapping_mul({}) = {}", x, y, x.wrapping_mul(y)); } } fn demo_wrapping_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.wrapping_mul_assign(y); println!("x := {old_x}; x.wrapping_mul_assign({y}); x = {x}"); } } fn demo_wrapping_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_mul_assign(y); println!("x := {old_x}; x.wrapping_mul_assign({y}); x = {x}"); } } fn benchmark_wrapping_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_mul({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_mul(y)))], ); } fn benchmark_wrapping_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_mul({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_mul(y)))], ); } fn benchmark_wrapping_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_mul_assign(y))], ); } fn benchmark_wrapping_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_mul_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_mul_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_neg_assign_unsigned); register_signed_demos!(runner, demo_wrapping_neg_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_neg_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_neg_assign_signed); } fn demo_wrapping_neg_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut u in unsigned_gen::().get(gm, config).take(limit) { let old_u = u; u.wrapping_neg_assign(); println!("u := {old_u}; u.wrapping_neg_assign(); u = {u}"); } } fn demo_wrapping_neg_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; i.wrapping_neg_assign(); println!("i := {old_i}; i.wrapping_neg_assign(); i = {i}"); } } fn benchmark_wrapping_neg_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_neg_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.wrapping_neg_assign())], ); } fn benchmark_wrapping_neg_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_neg_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.wrapping_neg_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_pow_assign_unsigned); register_signed_demos!(runner, demo_wrapping_pow_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_pow_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_pow_assign_signed); } fn demo_wrapping_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_pow_assign(y); println!("x := {old_x}; x.wrapping_pow_assign({y}); x = {x}"); } } fn demo_wrapping_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_unsigned_pair_gen::() .get(gm, config) .take(limit) { let old_x = x; x.wrapping_pow_assign(y); println!("x := {old_x}; x.wrapping_pow_assign({y}); x = {x}"); } } fn benchmark_wrapping_pow_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_pow_assign(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_pow_assign(y))], ); } fn benchmark_wrapping_pow_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_pow_assign(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_pow_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_square_unsigned); register_signed_demos!(runner, demo_wrapping_square_signed); register_unsigned_demos!(runner, demo_wrapping_square_assign_unsigned); register_signed_demos!(runner, demo_wrapping_square_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_square_unsigned); register_signed_benches!(runner, benchmark_wrapping_square_signed); register_unsigned_benches!(runner, benchmark_wrapping_square_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_square_assign_signed); } fn demo_wrapping_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("{}.wrapping_square() = {}", x, x.wrapping_square()); } } fn demo_wrapping_square_signed(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen::().get(gm, config).take(limit) { println!("{}.wrapping_square() = {}", x, x.wrapping_square()); } } fn demo_wrapping_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in unsigned_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_square_assign(); println!("x := {old_x}; x.wrapping_square_assign(); x = {x}"); } } fn demo_wrapping_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for mut x in signed_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_square_assign(); println!("x := {old_x}; x.wrapping_square_assign(); x = {x}"); } } fn benchmark_wrapping_square_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_square()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.wrapping_square()))], ); } fn benchmark_wrapping_square_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_square()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.wrapping_square()))], ); } fn benchmark_wrapping_square_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_square_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut x| x.wrapping_square_assign())], ); } fn benchmark_wrapping_square_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_square_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut x| x.wrapping_square_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_sub_unsigned); register_signed_demos!(runner, demo_wrapping_sub_signed); register_unsigned_demos!(runner, demo_wrapping_sub_assign_unsigned); register_signed_demos!(runner, demo_wrapping_sub_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_sub_unsigned); register_signed_benches!(runner, benchmark_wrapping_sub_signed); register_unsigned_benches!(runner, benchmark_wrapping_sub_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_sub_assign_signed); } fn demo_wrapping_sub_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.wrapping_sub({}) = {}", x, y, x.wrapping_sub(y)); } } fn demo_wrapping_sub_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).wrapping_sub({}) = {}", x, y, x.wrapping_sub(y)); } } fn demo_wrapping_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { let old_x = x; x.wrapping_sub_assign(y); println!("x := {old_x}; x.wrapping_sub_assign({y}); x = {x}"); } } fn demo_wrapping_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y) in signed_pair_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_sub_assign(y); println!("x := {old_x}; x.wrapping_sub_assign({y}); x = {x}"); } } fn benchmark_wrapping_sub_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_sub(y)))], ); } fn benchmark_wrapping_sub_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.wrapping_sub(y)))], ); } fn benchmark_wrapping_sub_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_sub_assign(y))], ); } fn benchmark_wrapping_sub_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub_assign({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(mut x, y)| x.wrapping_sub_assign(y))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/wrapping_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_triple_gen, unsigned_triple_gen_var_19}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_wrapping_sub_mul_unsigned); register_signed_demos!(runner, demo_wrapping_sub_mul_signed); register_unsigned_demos!(runner, demo_wrapping_sub_mul_assign_unsigned); register_signed_demos!(runner, demo_wrapping_sub_mul_assign_signed); register_unsigned_benches!(runner, benchmark_wrapping_sub_mul_unsigned); register_signed_benches!(runner, benchmark_wrapping_sub_mul_signed); register_unsigned_benches!(runner, benchmark_wrapping_sub_mul_assign_unsigned); register_signed_benches!(runner, benchmark_wrapping_sub_mul_assign_signed); } fn demo_wrapping_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}.wrapping_sub_mul({}, {}) = {}", x, y, z, x.wrapping_sub_mul(y, z) ); } } fn demo_wrapping_sub_mul_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { println!( "{}.wrapping_sub_mul({}, {}) = {}", x, y, z, x.wrapping_sub_mul(y, z) ); } } fn demo_wrapping_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in unsigned_triple_gen_var_19::() .get(gm, config) .take(limit) { let old_x = x; x.wrapping_sub_mul_assign(y, z); println!("x := {old_x}; x.wrapping_sub_mul_assign({y}, {z}); x = {x}"); } } fn demo_wrapping_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, z) in signed_triple_gen::().get(gm, config).take(limit) { let old_x = x; x.wrapping_sub_mul_assign(y, z); println!("x := {old_x}; x.wrapping_sub_mul_assign({y}, {z}); x = {x}"); } } fn benchmark_wrapping_sub_mul_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.wrapping_sub_mul(y, z)); })], ); } fn benchmark_wrapping_sub_mul_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_sub_mul({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(x, y, z)| { no_out!(x.wrapping_sub_mul(y, z)); })], ); } fn benchmark_wrapping_sub_mul_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.wrapping_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.wrapping_sub_mul_assign(y, z); })], ); } fn benchmark_wrapping_sub_mul_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.wrapping_sub_mul_assign({}, {})", T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, signed_triple_gen::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x", "y", "z"), &mut [("Malachite", &mut |(mut x, y, z)| { x.wrapping_sub_mul_assign(y, z); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/x_mul_y_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::x_mul_y_to_zz::explicit_x_mul_y_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_x_mul_y_to_zz); register_unsigned_benches!(runner, benchmark_x_mul_y_to_zz_algorithms); } fn demo_x_mul_y_to_zz(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{} * {} = {:?}", x, y, T::x_mul_y_to_zz(x, y)); } } fn benchmark_x_mul_y_to_zz_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::x_mul_y_to_zz({}, {})", T::NAME, T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(T::x_mul_y_to_zz(x, y))), ("explicit", &mut |(x, y)| { no_out!(explicit_x_mul_y_to_zz(x, y)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xx_add_yy_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_add_yy_to_zz::explicit_xx_add_yy_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::quadruple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_quadruple_gen_var_10; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xx_add_yy_to_zz); register_unsigned_benches!(runner, benchmark_xx_add_yy_to_zz_algorithms); } fn demo_xx_add_yy_to_zz(gm: GenMode, config: &GenConfig, limit: usize) { for (x_1, x_0, y_1, y_0) in unsigned_quadruple_gen_var_10::() .get(gm, config) .take(limit) { println!( "[{}, {}] + [{}, {}] = {:?}", x_1, x_0, y_1, y_0, T::xx_add_yy_to_zz(x_1, x_0, y_1, y_0) ); } } fn benchmark_xx_add_yy_to_zz_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xx_add_yy_to_zz({}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_quadruple_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &quadruple_max_bit_bucketer("x_1", "x_0", "y_1", "y_0"), &mut [ ("default", &mut |(x_1, x_0, y_1, y_0)| { no_out!(T::xx_add_yy_to_zz(x_1, x_0, y_1, y_0)); }), ("explicit", &mut |(x_1, x_0, y_1, y_0)| { no_out!(explicit_xx_add_yy_to_zz(x_1, x_0, y_1, y_0)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xx_div_mod_y_to_qr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_div_mod_y_to_qr::explicit_xx_div_mod_y_to_qr; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_triple_gen_var_15; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xx_div_mod_y_to_qr); register_unsigned_benches!(runner, benchmark_xx_div_mod_y_to_qr_algorithms); } fn demo_xx_div_mod_y_to_qr(gm: GenMode, config: &GenConfig, limit: usize) { for (x_1, x_0, y) in unsigned_triple_gen_var_15::() .get(gm, config) .take(limit) { println!( "[{}, {}].div_mod({}) = {:?}", x_1, x_0, y, T::xx_div_mod_y_to_qr(x_1, x_0, y) ); } } fn benchmark_xx_div_mod_y_to_qr_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xx_div_mod_y_to_qr({}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_triple_gen_var_15::().get(gm, config), gm.name(), limit, file_name, &triple_max_bit_bucketer("x_1", "x_0", "y"), &mut [ ("default", &mut |(x_1, x_0, y)| { no_out!(T::xx_div_mod_y_to_qr(x_1, x_0, y)); }), ("explicit", &mut |(x_1, x_0, y)| { no_out!(explicit_xx_div_mod_y_to_qr(x_1, x_0, y)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xx_sub_yy_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_sub_yy_to_zz::explicit_xx_sub_yy_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::quadruple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_quadruple_gen_var_10; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xx_sub_yy_to_zz); register_unsigned_benches!(runner, benchmark_xx_sub_yy_to_zz_algorithms); } fn demo_xx_sub_yy_to_zz(gm: GenMode, config: &GenConfig, limit: usize) { for (x_1, x_0, y_1, y_0) in unsigned_quadruple_gen_var_10::() .get(gm, config) .take(limit) { println!( "[{}, {}] - [{}, {}] = {:?}", x_1, x_0, y_1, y_0, T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0) ); } } fn benchmark_xx_sub_yy_to_zz_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xx_sub_yy_to_zz({}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_quadruple_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &quadruple_max_bit_bucketer("x_1", "x_0", "y_1", "y_0"), &mut [ ("default", &mut |(x_1, x_0, y_1, y_0)| { no_out!(T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0)); }), ("explicit", &mut |(x_1, x_0, y_1, y_0)| { no_out!(explicit_xx_sub_yy_to_zz(x_1, x_0, y_1, y_0)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xxx_add_yyy_to_zzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::sextuple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_sextuple_gen_var_1; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xxx_add_yyy_to_zzz); register_unsigned_benches!(runner, benchmark_xxx_add_yyy_to_zzz); } fn demo_xxx_add_yyy_to_zzz(gm: GenMode, config: &GenConfig, limit: usize) { for (x_2, x_1, x_0, y_2, y_1, y_0) in unsigned_sextuple_gen_var_1::() .get(gm, config) .take(limit) { println!( "[{}, {}, {}] + [{}, {}, {}] = {:?}", x_2, x_1, x_0, y_2, y_1, y_0, T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0) ); } } fn benchmark_xxx_add_yyy_to_zzz( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xxx_add_yyy_to_zzz({}, {}, {}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_sextuple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &sextuple_max_bit_bucketer("x_2", "x_1", "x_0", "y_2", "y_1", "y_0"), &mut [("default", &mut |(x_2, x_1, x_0, y_2, y_1, y_0)| { no_out!(T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xxx_sub_yyy_to_zzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::sextuple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_sextuple_gen_var_1; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xxx_sub_yyy_to_zzz); register_unsigned_benches!(runner, benchmark_xxx_sub_yyy_to_zzz); } fn demo_xxx_sub_yyy_to_zzz(gm: GenMode, config: &GenConfig, limit: usize) { for (x_2, x_1, x_0, y_2, y_1, y_0) in unsigned_sextuple_gen_var_1::() .get(gm, config) .take(limit) { println!( "[{}, {}, {}] - [{}, {}, {}] = {:?}", x_2, x_1, x_0, y_2, y_1, y_0, T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0) ); } } fn benchmark_xxx_sub_yyy_to_zzz( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xxx_sub_yyy_to_zzz({}, {}, {}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_sextuple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &sextuple_max_bit_bucketer("x_2", "x_1", "x_0", "y_2", "y_1", "y_0"), &mut [("default", &mut |(x_2, x_1, x_0, y_2, y_1, y_0)| { no_out!(T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/arithmetic/xxxx_add_yyyy_to_zzzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::octuple_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_octuple_gen_var_1; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_xxxx_add_yyyy_to_zzzz); register_unsigned_benches!(runner, benchmark_xxxx_add_yyyy_to_zzzz); } fn demo_xxxx_add_yyyy_to_zzzz(gm: GenMode, config: &GenConfig, limit: usize) { for (x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0) in unsigned_octuple_gen_var_1::() .get(gm, config) .take(limit) { println!( "[{}, {}, {}, {}] + [{}, {}, {}, {}] = {:?}", x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0, T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0) ); } } fn benchmark_xxxx_add_yyyy_to_zzzz( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::xxxx_add_yyyy_to_zzzz({}, {}, {}, {}, {}, {}, {}, {})", T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_octuple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &octuple_max_bit_bucketer("x_3", "x_2", "x_1", "x_0", "y_3", "y_2", "y_1", "y_0"), &mut [("default", &mut |( x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0, )| { no_out!(T::xxxx_add_yyyy_to_zzzz( x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0 )); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_max_bit_bucketer, pair_max_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_pair_gen, signed_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_cmp_abs_signed); register_signed_demos!(runner, demo_partial_cmp_abs_signed); register_primitive_float_demos!(runner, demo_partial_cmp_abs_primitive_float); register_signed_benches!(runner, benchmark_cmp_abs_signed_algorithms); register_signed_benches!(runner, benchmark_partial_cmp_abs_signed); register_primitive_float_benches!(runner, benchmark_partial_cmp_abs_primitive_float_algorithms); } fn demo_cmp_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).cmp_abs(&{}) = {:?}", x, y, x.cmp_abs(&y)); } } fn demo_partial_cmp_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).partial_cmp_abs(&{}) = {:?}", x, y, x.partial_cmp_abs(&y) ); } } fn demo_partial_cmp_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { println!( "({}).partial_cmp_abs(&{}) = {:?}", NiceFloat(x), NiceFloat(y), x.partial_cmp_abs(&y) ); } } #[allow(unused_must_use)] fn benchmark_cmp_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: Ord, { run_benchmark( &format!("{}.cmp_abs(&{})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.cmp_abs(&y))), ("default", &mut |(x, y)| { no_out!(x.unsigned_abs().cmp(&y.unsigned_abs())); }), ], ); } fn benchmark_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y)))], ); } #[allow(unused_must_use)] fn benchmark_partial_cmp_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&{})", T::NAME, T::NAME), BenchmarkType::Algorithms, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("default", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_max_bit_bucketer, pair_max_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_pair_gen, signed_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_eq_abs_signed); register_primitive_float_demos!(runner, demo_eq_abs_primitive_float); register_signed_benches!(runner, benchmark_eq_abs_signed_algorithms); register_primitive_float_benches!(runner, benchmark_eq_abs_primitive_float_algorithms); } fn demo_eq_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_eq_abs_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } #[allow(unused_must_use)] fn benchmark_eq_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PrimitiveUnsigned, { run_benchmark( &format!("{}.eq_abs(&{})", T::NAME, T::NAME), BenchmarkType::Algorithms, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.unsigned_abs() == y.unsigned_abs()); }), ], ); } #[allow(unused_must_use)] fn benchmark_eq_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { eq_abs::register(runner); cmp_abs::register(runner); ord_abs_comparators::register(runner); } mod cmp_abs; mod eq_abs; mod ord_abs_comparators; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/comparison/ord_abs_comparators.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_lt_abs_signed); register_signed_demos!(runner, demo_gt_abs_signed); register_signed_demos!(runner, demo_le_abs_signed); register_signed_demos!(runner, demo_ge_abs_signed); register_signed_benches!(runner, benchmark_lt_abs_signed); register_signed_benches!(runner, benchmark_gt_abs_signed); register_signed_benches!(runner, benchmark_le_abs_signed); register_signed_benches!(runner, benchmark_ge_abs_signed); } fn demo_lt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).lt_abs(&{}) = {}", x, y, x.lt_abs(&y)); } } fn demo_gt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).gt_abs(&{}) = {}", x, y, x.gt_abs(&y)); } } fn demo_le_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).le_abs(&{}) = {}", x, y, x.le_abs(&y)); } } fn demo_ge_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!("({}).ge_abs(&{}) = {}", x, y, x.ge_abs(&y)); } } fn benchmark_lt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_gt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_le_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_ge_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&{})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/general_digits/from_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{Digits, SaturatingFrom}; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_7, unsigned_vec_unsigned_pair_gen_var_8, unsigned_vec_unsigned_pair_gen_var_9, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_from_digits_asc); register_unsigned_unsigned_demos!(runner, demo_from_digits_desc); register_unsigned_unsigned_demos!(runner, demo_from_digits_asc_targeted); register_unsigned_unsigned_demos!(runner, demo_from_digits_desc_targeted); register_unsigned_unsigned_benches!(runner, benchmark_from_digits_asc); register_unsigned_unsigned_benches!(runner, benchmark_from_digits_desc); } fn demo_from_digits_asc< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_9::() .get(gm, config) .take(limit) { println!( "{}.from_digits_asc({}, {:?}) = {:?}", U::NAME, base, xs, U::from_digits_asc(&base, xs.iter().copied()) ); } } fn demo_from_digits_desc< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_9::() .get(gm, config) .take(limit) { println!( "{}.from_digits_desc({}, {:?}) = {:?}", U::NAME, base, xs, U::from_digits_desc(&base, xs.iter().copied()) ); } } fn demo_from_digits_asc_targeted< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_8::() .get(gm, config) .take(limit) { println!( "{}.from_digits_asc({}, {:?}) = {}", U::NAME, base, xs, U::from_digits_asc(&base, xs.iter().copied()).unwrap() ); } } fn demo_from_digits_desc_targeted< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_7::() .get(gm, config) .take(limit) { println!( "{}.from_digits_desc({}, {:?}) = {}", U::NAME, base, xs, U::from_digits_desc(&base, xs.iter().copied()).unwrap() ); } } fn benchmark_from_digits_asc< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.from_digits_asc({}, Iterator)", U::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("digits"), &mut [("Malachite", &mut |(xs, base)| { no_out!(U::from_digits_asc(&base, xs.iter().copied())); })], ); } fn benchmark_from_digits_desc< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}.from_digits_desc({}, Iterator)", U::NAME, T::NAME, T::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_7::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("digits"), &mut [("Malachite", &mut |(xs, base)| { no_out!(U::from_digits_desc(&base, xs.iter().copied())); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/general_digits/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_digits::register(runner); to_digits::register(runner); } mod from_digits; mod to_digits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/general_digits/to_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{Digits, SaturatingFrom}; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_6; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_to_digits_asc); register_unsigned_unsigned_demos!(runner, demo_to_digits_desc); register_unsigned_unsigned_benches!(runner, benchmark_to_digits_asc); register_unsigned_unsigned_benches!(runner, benchmark_to_digits_desc); } fn demo_to_digits_asc< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base) in unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}.to_digits_asc({}) = {:?}", x, base, x.to_digits_asc(&base) ); } } fn demo_to_digits_desc< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base) in unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}.to_digits_desc({}) = {:?}", x, base, x.to_digits_desc(&base) ); } } fn benchmark_to_digits_asc< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_digits_asc({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base)| { no_out!(x.to_digits_asc(&base)); })], ); } fn benchmark_to_digits_desc< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_digits_desc({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base)| { no_out!(x.to_digits_desc(&base)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { general_digits::register(runner); power_of_2_digits::register(runner); } mod general_digits; mod power_of_2_digits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/power_of_2_digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_3, unsigned_vec_unsigned_pair_gen_var_6, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_from_power_of_2_digits_asc); register_unsigned_unsigned_demos!(runner, demo_from_power_of_2_digits_desc); register_unsigned_unsigned_demos!(runner, demo_from_power_of_2_digits_asc_targeted); register_unsigned_unsigned_demos!(runner, demo_from_power_of_2_digits_desc_targeted); register_unsigned_unsigned_benches!(runner, benchmark_from_power_of_2_digits_asc); register_unsigned_unsigned_benches!(runner, benchmark_from_power_of_2_digits_desc); } fn demo_from_power_of_2_digits_asc< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, log_base) in unsigned_vec_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}::from_power_of_2_digits_asc({}, {:?}) = {:?}", T::NAME, log_base, xs, T::from_power_of_2_digits_asc(log_base, xs.iter().copied()) ); } } fn demo_from_power_of_2_digits_desc< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, log_base) in unsigned_vec_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}::from_power_of_2_digits_desc({}, {:?}) = {:?}", T::NAME, log_base, xs, T::from_power_of_2_digits_desc(log_base, xs.iter().copied()) ); } } fn demo_from_power_of_2_digits_asc_targeted< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, log_base) in unsigned_vec_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}::from_power_of_2_digits_asc({}, {:?}) = {}", T::NAME, log_base, xs, T::from_power_of_2_digits_asc(log_base, xs.iter().copied()).unwrap() ); } } fn demo_from_power_of_2_digits_desc_targeted< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, log_base) in unsigned_vec_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}::from_power_of_2_digits_desc({}, {:?}) = {}", T::NAME, log_base, xs, T::from_power_of_2_digits_desc(log_base, xs.iter().copied()).unwrap() ); } } fn benchmark_from_power_of_2_digits_asc< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_power_of_2_digits_asc>(u64, I)", T::NAME, U::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, log_base)| { no_out!(T::from_power_of_2_digits_asc(log_base, xs.into_iter())); })], ); } fn benchmark_from_power_of_2_digits_desc< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_power_of_2_digits_asc>(u64, I)", T::NAME, U::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, log_base)| { no_out!(T::from_power_of_2_digits_desc(log_base, xs.into_iter())); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/power_of_2_digits/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_power_of_2_digits::register(runner); power_of_2_digit_iterable::register(runner); to_power_of_2_digits::register(runner); } mod from_power_of_2_digits; mod power_of_2_digit_iterable; mod to_power_of_2_digits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/power_of_2_digits/power_of_2_digit_iterable.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, PowerOf2Digits, }; use malachite_base::test_util::bench::bucketers::{pair_1_bit_bucketer, triple_1_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_pair_gen_var_4, unsigned_triple_gen_var_3}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_power_of_2_digits); register_unsigned_unsigned_demos!(runner, demo_power_of_2_digits_rev); register_unsigned_unsigned_demos!(runner, demo_power_of_2_digits_size_hint); register_unsigned_unsigned_demos!(runner, demo_power_of_2_digits_get_digit); register_unsigned_unsigned_benches!(runner, benchmark_power_of_2_digits_size_hint); register_unsigned_unsigned_benches!(runner, benchmark_power_of_2_digits_get_digit_algorithms); } fn demo_power_of_2_digits + PrimitiveUnsigned, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base) in unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}) = {:?}", x, log_base, PowerOf2DigitIterable::::power_of_2_digits(x, log_base).collect_vec() ); } } fn demo_power_of_2_digits_rev< T: PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base) in unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).rev() = {:?}", x, log_base, PowerOf2DigitIterable::::power_of_2_digits(x, log_base) .rev() .collect_vec() ); } } fn demo_power_of_2_digits_size_hint< T: PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base) in unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).size_hint() = {:?}", x, log_base, PowerOf2DigitIterable::::power_of_2_digits(x, log_base).size_hint() ); } } fn demo_power_of_2_digits_get_digit< T: PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base, i) in unsigned_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).get_digit({}) = {:?}", x, log_base, i, PowerOf2DigitIterable::::power_of_2_digits(x, log_base).get_digit(i) ); } } fn benchmark_power_of_2_digits_size_hint< T: PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "PowerOf2DigitIterable::<{}>::power_of_2_digits(&{}, u64).size_hint()", U::NAME, T::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, log_base)| { no_out!(PowerOf2DigitIterable::::power_of_2_digits(x, log_base).size_hint()); })], ); } fn benchmark_power_of_2_digits_get_digit_algorithms< T: PowerOf2DigitIterable + PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "PowerOf2DigitIterable::<{}>::power_of_2_digits(&{}, u64).size_hint()", U::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [ ( &format!("power_of_2_digits({}, u64).get_digit(u64)", T::NAME), &mut |(u, log_base, i)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(u, log_base).get_digit(i) ); }, ), ( &format!("{}.to_power_of_2_digits_asc(u64)[usize]", T::NAME), &mut |(x, log_base, i)| { let digits = PowerOf2Digits::::to_power_of_2_digits_asc(&x, log_base); let i = usize::exact_from(i); if i >= digits.len() { U::ZERO } else { digits[i] }; }, ), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/digits/power_of_2_digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{PowerOf2DigitIterable, PowerOf2Digits}; use malachite_base::test_util::bench::bucketers::pair_1_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_4; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_to_power_of_2_digits_asc); register_unsigned_unsigned_demos!(runner, demo_to_power_of_2_digits_desc); register_unsigned_unsigned_benches!( runner, benchmark_to_power_of_2_digits_asc_evaluation_strategy ); register_unsigned_unsigned_benches!( runner, benchmark_to_power_of_2_digits_desc_evaluation_strategy ); } fn demo_to_power_of_2_digits_asc + PrimitiveUnsigned, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base) in unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_asc({}) = {:?}", x, log_base, PowerOf2Digits::::to_power_of_2_digits_asc(&x, log_base) ); } } fn demo_to_power_of_2_digits_desc< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, log_base) in unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_desc({}) = {:?}", x, log_base, PowerOf2Digits::::to_power_of_2_digits_desc(&x, log_base) ); } } fn benchmark_to_power_of_2_digits_asc_evaluation_strategy< T: PowerOf2Digits + PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "PowerOf2Digits::<{}>::to_power_of_2_digits_asc({}, u64)", U::NAME, T::NAME ), BenchmarkType::EvaluationStrategy, unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("Malachite", &mut |(x, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_asc(&x, log_base)); }), ( &format!("{}.power_of_2_digits(u64).collect_vec()", T::NAME), &mut |(x, log_base)| { PowerOf2DigitIterable::::power_of_2_digits(x, log_base).collect_vec(); }, ), ], ); } fn benchmark_to_power_of_2_digits_desc_evaluation_strategy< T: PowerOf2Digits + PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "PowerOf2Digits::<{}>::to_power_of_2_digits_desc({}, u64)", U::NAME, T::NAME ), BenchmarkType::EvaluationStrategy, unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("Malachite", &mut |(x, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_desc(&x, log_base)); }), ( &format!("{}.power_of_2_digits(u64).rev().collect_vec()", T::NAME), &mut |(x, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(x, log_base) .rev() .collect_vec() ); }, ), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/convertible_from.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_unsigned_demos!(runner, demo_primitive_int_convertible_from_unsigned); register_primitive_int_signed_demos!(runner, demo_primitive_int_convertible_from_signed); register_primitive_int_primitive_float_demos!( runner, demo_primitive_int_convertible_from_primitive_float ); register_primitive_float_unsigned_demos!( runner, demo_primitive_float_convertible_from_unsigned ); register_primitive_float_signed_demos!(runner, demo_primitive_float_convertible_from_signed); register_primitive_int_unsigned_benches!( runner, benchmark_primitive_int_convertible_from_unsigned ); register_primitive_int_signed_benches!(runner, benchmark_primitive_int_convertible_from_signed); register_primitive_int_primitive_float_benches!( runner, benchmark_primitive_int_convertible_from_primitive_float ); register_primitive_float_unsigned_benches!( runner, benchmark_primitive_float_convertible_from_unsigned ); register_primitive_float_signed_benches!( runner, benchmark_primitive_float_convertible_from_signed ); } fn demo_primitive_int_convertible_from_unsigned< T: ConvertibleFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", u, if T::convertible_from(u) { "" } else { "not " }, T::NAME, ); } } fn demo_primitive_int_convertible_from_signed + Named, U: PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", i, if T::convertible_from(i) { "" } else { "not " }, T::NAME, ); } } fn demo_primitive_int_convertible_from_primitive_float< T: ConvertibleFrom + PrimitiveInt, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", NiceFloat(x), if T::convertible_from(x) { "" } else { "not " }, T::NAME, ); } } fn demo_primitive_float_convertible_from_unsigned< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", u, if T::convertible_from(u) { "" } else { "not " }, T::NAME, ); } } fn demo_primitive_float_convertible_from_signed< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", i, if T::convertible_from(i) { "" } else { "not " }, T::NAME, ); } } fn benchmark_primitive_int_convertible_from_unsigned< T: ConvertibleFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.convertible_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(n)))], ); } fn benchmark_primitive_int_convertible_from_signed< T: ConvertibleFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.convertible_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(n)))], ); } fn benchmark_primitive_int_convertible_from_primitive_float< T: ConvertibleFrom + PrimitiveInt, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.convertible_from({})", T::NAME, U::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(n)))], ); } fn benchmark_primitive_float_convertible_from_unsigned< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.convertible_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(n)))], ); } fn benchmark_primitive_float_convertible_from_signed< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.convertible_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { convertible_from::register(runner); overflowing_from::register(runner); rounding_from::register(runner); saturating_from::register(runner); try_from_and_exact_from::register(runner); wrapping_from::register(runner); } mod convertible_from; mod overflowing_from; mod rounding_from; mod saturating_from; mod try_from_and_exact_from; mod wrapping_from; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/overflowing_from.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::OverflowingFrom; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_unsigned_demos!(runner, demo_primitive_int_overflowing_from_unsigned); register_primitive_int_signed_demos!(runner, demo_primitive_int_overflowing_from_signed); register_primitive_int_unsigned_benches!( runner, benchmark_primitive_int_overflowing_from_unsigned ); register_primitive_int_signed_benches!(runner, benchmark_primitive_int_overflowing_from_signed); } fn demo_primitive_int_overflowing_from_unsigned< T: Debug + OverflowingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{}::overflowing_from({}) = {:?}", T::NAME, u, T::overflowing_from(u) ); } } fn demo_primitive_int_overflowing_from_signed< T: Debug + OverflowingFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen::().get(gm, config).take(limit) { println!( "{}::overflowing_from({}) = {:?}", T::NAME, i, T::overflowing_from(i) ); } } fn benchmark_primitive_int_overflowing_from_unsigned< T: OverflowingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::overflowing_from(n)))], ); } fn benchmark_primitive_int_overflowing_from_signed< T: OverflowingFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.overflowing_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::overflowing_from(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/rounding_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, pair_1_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_rounding_mode_pair_gen_var_3, signed_rounding_mode_pair_gen_var_4, unsigned_rounding_mode_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_primitive_float_demos!( runner, demo_primitive_int_rounding_from_primitive_float ); register_primitive_float_unsigned_demos!(runner, demo_primitive_float_rounding_from_unsigned); register_primitive_float_signed_demos!(runner, demo_primitive_float_rounding_from_signed); register_primitive_int_primitive_float_benches!( runner, benchmark_primitive_int_rounding_from_primitive_float ); register_primitive_float_unsigned_benches!( runner, benchmark_primitive_float_rounding_from_unsigned ); register_primitive_float_signed_benches!( runner, benchmark_primitive_float_rounding_from_signed ); } fn demo_primitive_int_rounding_from_primitive_float< T: ConvertibleFrom + PrimitiveInt + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (f, rm) in primitive_float_rounding_mode_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, NiceFloat(f), rm, T::rounding_from(f, rm) ); } } fn demo_primitive_float_rounding_from_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (u, rm) in unsigned_rounding_mode_pair_gen_var_2::() .get(gm, config) .take(limit) { let (x, o) = T::rounding_from(u, rm); println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, u, rm, (NiceFloat(x), o) ); } } fn demo_primitive_float_rounding_from_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (i, rm) in signed_rounding_mode_pair_gen_var_4::() .get(gm, config) .take(limit) { let (x, o) = T::rounding_from(i, rm); println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, i, rm, (NiceFloat(x), o) ); } } fn benchmark_primitive_int_rounding_from_primitive_float< T: ConvertibleFrom + PrimitiveInt + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rounding_from({})", T::NAME, U::NAME), BenchmarkType::Single, primitive_float_rounding_mode_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("x"), &mut [("Malachite", &mut |(f, rm)| no_out!(T::rounding_from(f, rm)))], ); } fn benchmark_primitive_float_rounding_from_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rounding_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(u, rm)| no_out!(T::rounding_from(u, rm)))], ); } fn benchmark_primitive_float_rounding_from_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.rounding_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_rounding_mode_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("i"), &mut [("Malachite", &mut |(i, rm)| no_out!(T::rounding_from(i, rm)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/saturating_from.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::SaturatingFrom; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; use std::fmt::Display; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_unsigned_demos!(runner, demo_primitive_int_saturating_from_unsigned); register_primitive_int_signed_demos!(runner, demo_primitive_int_saturating_from_signed); register_primitive_int_unsigned_benches!( runner, benchmark_primitive_int_saturating_from_unsigned ); register_primitive_int_signed_benches!(runner, benchmark_primitive_int_saturating_from_signed); } fn demo_primitive_int_saturating_from_unsigned< T: Display + SaturatingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{}::saturating_from({}) = {}", T::NAME, u, T::saturating_from(u) ); } } fn demo_primitive_int_saturating_from_signed< T: Display + SaturatingFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen::().get(gm, config).take(limit) { println!( "{}::saturating_from({}) = {}", T::NAME, i, T::saturating_from(i) ); } } fn benchmark_primitive_int_saturating_from_unsigned< T: SaturatingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::saturating_from(n)))], ); } fn benchmark_primitive_int_saturating_from_signed< T: SaturatingFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.saturating_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::saturating_from(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/try_from_and_exact_from.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_13, primitive_float_gen_var_14, signed_gen, signed_gen_var_2, signed_gen_var_7, unsigned_gen, unsigned_gen_var_18, }; use malachite_base::test_util::runner::Runner; use std::fmt::{Debug, Display}; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_primitive_float_demos!( runner, demo_primitive_int_try_from_primitive_float ); register_unsigned_primitive_float_demos!(runner, demo_primitive_float_try_from_unsigned); register_signed_primitive_float_demos!(runner, demo_primitive_float_try_from_signed); register_primitive_int_unsigned_demos!(runner, demo_primitive_int_exact_from_unsigned); register_primitive_int_signed_demos!(runner, demo_primitive_int_exact_from_signed); register_unsigned_primitive_float_demos!(runner, demo_unsigned_exact_from_primitive_float); register_signed_primitive_float_demos!(runner, demo_signed_exact_from_primitive_float); register_primitive_float_unsigned_demos!(runner, demo_primitive_float_exact_from_unsigned); register_primitive_float_signed_demos!(runner, demo_primitive_float_exact_from_signed); register_primitive_int_primitive_float_benches!( runner, benchmark_primitive_int_try_from_primitive_float ); register_primitive_float_unsigned_benches!(runner, benchmark_primitive_float_try_from_unsigned); register_primitive_float_signed_benches!(runner, benchmark_primitive_float_try_from_signed); register_primitive_int_unsigned_benches!(runner, benchmark_primitive_int_exact_from_unsigned); register_primitive_int_signed_benches!(runner, benchmark_primitive_int_exact_from_signed); register_unsigned_primitive_float_benches!( runner, benchmark_unsigned_exact_from_primitive_float ); register_signed_primitive_float_benches!(runner, benchmark_signed_exact_from_primitive_float); register_primitive_float_unsigned_benches!( runner, benchmark_primitive_float_exact_from_unsigned ); register_primitive_float_signed_benches!(runner, benchmark_primitive_float_exact_from_signed); } fn demo_primitive_int_try_from_primitive_float< T: TryFrom> + Debug + Named, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) where >>::Error: Debug, { for f in primitive_float_gen::().get(gm, config).take(limit) { let f = NiceFloat(f); println!("{}::try_from({}) = {:?}", T::NAME, f, T::try_from(f)); } } fn demo_primitive_float_try_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, as TryFrom>::Error: Debug, { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", U::NAME, u, NiceFloat::::try_from(u) ); } } fn demo_primitive_float_try_from_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, as TryFrom>::Error: Debug, { for u in signed_gen::().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", U::NAME, u, NiceFloat::::try_from(u) ); } } fn demo_primitive_int_exact_from_unsigned + Display + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}::exact_from({}) = {}", T::NAME, u, T::exact_from(u)); } } fn demo_primitive_int_exact_from_signed + Display + Named, U: PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen_var_2::().get(gm, config).take(limit) { println!("{}::exact_from({}) = {}", T::NAME, i, T::exact_from(i)); } } fn demo_unsigned_exact_from_primitive_float< T: TryFrom> + PrimitiveUnsigned, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, { for f in primitive_float_gen_var_13::() .get(gm, config) .take(limit) { let f = NiceFloat(f); println!("{}::exact_from({}) = {}", T::NAME, f, T::exact_from(f)); } } fn demo_signed_exact_from_primitive_float< T: TryFrom> + PrimitiveSigned + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, { for f in primitive_float_gen_var_14::() .get(gm, config) .take(limit) { let f = NiceFloat(f); println!("{}::exact_from({}) = {}", T::NAME, f, T::exact_from(f)); } } fn demo_primitive_float_exact_from_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, { for u in unsigned_gen_var_18::().get(gm, config).take(limit) { println!( "{}::exact_from({}) = {}", T::NAME, u, NiceFloat::::exact_from(u) ); } } fn demo_primitive_float_exact_from_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveSigned + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where NiceFloat: TryFrom, { for i in signed_gen_var_7::().get(gm, config).take(limit) { println!( "{}::exact_from({}) = {}", T::NAME, i, NiceFloat::::exact_from(i) ); } } fn benchmark_primitive_int_try_from_primitive_float< T: TryFrom> + Named, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.try_from({})", T::NAME, U::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| { no_out!(T::try_from(NiceFloat(n)).ok()); })], ); } fn benchmark_primitive_float_try_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.try_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| { no_out!(NiceFloat::::try_from(n).ok()); })], ); } fn benchmark_primitive_float_try_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.try_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| { no_out!(NiceFloat::::try_from(n).ok()); })], ); } fn benchmark_primitive_int_exact_from_unsigned + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::exact_from(n)))], ); } fn benchmark_primitive_int_exact_from_signed + Named, U: PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::exact_from(n)))], ); } fn benchmark_unsigned_exact_from_primitive_float< T: TryFrom> + PrimitiveUnsigned, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, primitive_float_gen_var_13::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(NiceFloat(n))))], ); } fn benchmark_signed_exact_from_primitive_float< T: TryFrom> + PrimitiveSigned, U: PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, primitive_float_gen_var_14::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(NiceFloat(n))))], ); } fn benchmark_primitive_float_exact_from_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen_var_18::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(NiceFloat::::exact_from(n)))], ); } fn benchmark_primitive_float_exact_from_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveSigned + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where NiceFloat: TryFrom, { run_benchmark( &format!("{}.exact_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen_var_7::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(NiceFloat::::exact_from(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/from/wrapping_from.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; use std::fmt::Display; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_unsigned_demos!(runner, demo_primitive_int_wrapping_from_unsigned); register_primitive_int_signed_demos!(runner, demo_primitive_int_wrapping_from_signed); register_primitive_int_unsigned_benches!( runner, benchmark_primitive_int_wrapping_from_unsigned ); register_primitive_int_signed_benches!(runner, benchmark_primitive_int_wrapping_from_signed); } fn demo_primitive_int_wrapping_from_unsigned< T: Display + WrappingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{}::wrapping_from({}) = {}", T::NAME, u, T::wrapping_from(u) ); } } fn demo_primitive_int_wrapping_from_signed< T: Display + WrappingFrom + Named, U: PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for i in signed_gen::().get(gm, config).take(limit) { println!( "{}::wrapping_from({}) = {}", T::NAME, i, T::wrapping_from(i) ); } } fn benchmark_primitive_int_wrapping_from_unsigned< T: WrappingFrom + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_from({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::wrapping_from(n)))], ); } fn benchmark_primitive_int_wrapping_from_signed + Named, U: PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.wrapping_from({})", T::NAME, U::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::wrapping_from(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/half/join_halves.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::JoinHalves; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_generic_demos!(runner, demo_join_halves, u16, u32, u64, u128); register_generic_benches!(runner, benchmark_join_halves, u16, u32, u64, u128); } fn demo_join_halves( gm: GenMode, config: &GenConfig, limit: usize, ) where T::Half: PrimitiveUnsigned, { for (x, y) in unsigned_pair_gen_var_27::() .get(gm, config) .take(limit) { println!( "{}::join_halves({}, {}) = {}", T::NAME, x, y, T::join_halves(x, y) ); } } fn benchmark_join_halves( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where T::Half: PrimitiveUnsigned, { run_benchmark( &format!( "{}::join_halves({}, {})", T::NAME, T::Half::NAME, T::Half::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(T::join_halves(x, y)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/half/lower_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::test_util::bench::bucketers::unsigned_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_generic_demos!(runner, demo_lower_half, u16, u32, u64, u128); register_generic_benches!(runner, benchmark_lower_half, u16, u32, u64, u128); } fn demo_lower_half( gm: GenMode, config: &GenConfig, limit: usize, ) where T::Half: PrimitiveUnsigned, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.lower_half() = {}", u, u.lower_half()); } } fn benchmark_lower_half( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lower_half()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.lower_half()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/half/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { join_halves::register(runner); lower_half::register(runner); split_in_half::register(runner); upper_half::register(runner); } mod join_halves; mod lower_half; mod split_in_half; mod upper_half; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/half/split_in_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::test_util::bench::bucketers::unsigned_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_generic_demos!(runner, demo_split_in_half, u16, u32, u64, u128); register_generic_benches!(runner, benchmark_split_in_half, u16, u32, u64, u128); } fn demo_split_in_half( gm: GenMode, config: &GenConfig, limit: usize, ) where T::Half: PrimitiveUnsigned, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.split_in_half() = {:?}", u, u.split_in_half()); } } fn benchmark_split_in_half( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.split_in_half()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.split_in_half()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/half/upper_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::test_util::bench::bucketers::unsigned_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_generic_demos!(runner, demo_upper_half, u16, u32, u64, u128); register_generic_benches!(runner, benchmark_upper_half, u16, u32, u64, u128); } fn demo_upper_half( gm: GenMode, config: &GenConfig, limit: usize, ) where T::Half: PrimitiveUnsigned, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.upper_half() = {}", u, u.upper_half()); } } fn benchmark_upper_half( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.upper_half()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.upper_half()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ primitive_float_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_is_integer_unsigned); register_signed_demos!(runner, demo_is_integer_signed); register_primitive_float_demos!(runner, demo_is_integer_primitive_float); register_unsigned_benches!(runner, benchmark_is_integer_unsigned); register_signed_benches!(runner, benchmark_is_integer_signed); register_primitive_float_benches!(runner, benchmark_is_integer_primitive_float); } fn demo_is_integer_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen::().get(gm, config).take(limit) { if x.is_integer() { println!("{} is an integer", NiceFloat(x)); } else { println!("{} is not an integer", NiceFloat(x)); } } } fn demo_is_integer_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen::().get(gm, config).take(limit) { if x.is_integer() { println!("{x} is an integer"); } else { println!("{x} is not an integer"); } } } fn demo_is_integer_signed(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen::().get(gm, config).take(limit) { if x.is_integer() { println!("{x} is an integer"); } else { println!("{x} is not an integer"); } } } fn benchmark_is_integer_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_integer()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } fn benchmark_is_integer_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_integer()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } fn benchmark_is_integer_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_integer()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/mantissa_and_exponent/integer_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, primitive_float_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, unsigned_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_30, unsigned_signed_pair_gen_var_1, unsigned_signed_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_mantissa_and_exponent_unsigned); register_unsigned_demos!(runner, demo_integer_mantissa_unsigned); register_unsigned_demos!(runner, demo_integer_exponent_unsigned); register_unsigned_demos!(runner, demo_from_integer_mantissa_and_exponent_unsigned); register_unsigned_demos!( runner, demo_from_integer_mantissa_and_exponent_targeted_unsigned ); register_primitive_float_demos!(runner, demo_integer_mantissa_and_exponent_primitive_float); register_primitive_float_demos!(runner, demo_integer_mantissa_primitive_float); register_primitive_float_demos!(runner, demo_integer_exponent_primitive_float); register_primitive_float_demos!( runner, demo_from_integer_mantissa_and_exponent_primitive_float ); register_primitive_float_demos!( runner, demo_from_integer_mantissa_and_exponent_targeted_primitive_float ); register_unsigned_benches!( runner, benchmark_integer_mantissa_and_exponent_algorithms_unsigned ); register_unsigned_benches!(runner, benchmark_integer_mantissa_algorithms_unsigned); register_unsigned_benches!(runner, benchmark_integer_exponent_algorithms_unsigned); register_unsigned_benches!( runner, benchmark_from_integer_mantissa_and_exponent_unsigned ); register_unsigned_benches!( runner, benchmark_from_integer_mantissa_and_exponent_targeted_unsigned ); register_primitive_float_benches!( runner, benchmark_integer_mantissa_and_exponent_algorithms_primitive_float ); register_primitive_float_benches!( runner, benchmark_integer_mantissa_algorithms_primitive_float ); register_primitive_float_benches!( runner, benchmark_integer_exponent_algorithms_primitive_float ); register_primitive_float_benches!( runner, benchmark_from_integer_mantissa_and_exponent_primitive_float ); register_primitive_float_benches!( runner, benchmark_from_integer_mantissa_and_exponent_targeted_primitive_float ); } fn demo_integer_mantissa_and_exponent_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { println!( "integer_mantissa_and_exponent({}) = {:?}", x, x.integer_mantissa_and_exponent() ); } } fn demo_integer_mantissa_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { println!("integer_mantissa({}) = {}", x, x.integer_mantissa()); } } fn demo_integer_exponent_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { println!("integer_exponent({}) = {}", x, x.integer_exponent()); } } fn demo_from_integer_mantissa_and_exponent_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}::from_integer_mantissa_and_exponent({}, {}) = {:?}", T::NAME, mantissa, exponent, T::from_integer_mantissa_and_exponent(mantissa, exponent) ); } } fn demo_from_integer_mantissa_and_exponent_targeted_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in unsigned_pair_gen_var_30::().get(gm, config).take(limit) { println!( "{}::from_integer_mantissa_and_exponent({}, {}) = {}", T::NAME, mantissa, exponent, T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap() ); } } fn demo_integer_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!( "integer_mantissa_and_exponent({}) = {:?}", NiceFloat(x), x.integer_mantissa_and_exponent() ); } } fn demo_integer_mantissa_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!( "integer_mantissa({}) = {}", NiceFloat(x), x.integer_mantissa() ); } } fn demo_integer_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!( "integer_exponent({}) = {}", NiceFloat(x), x.integer_exponent() ); } } fn demo_from_integer_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in unsigned_signed_pair_gen_var_1().get(gm, config).take(limit) { println!( "{}::from_integer_mantissa_and_exponent({}, {}) = {:?}", T::NAME, mantissa, exponent, T::from_integer_mantissa_and_exponent(mantissa, exponent).map(NiceFloat) ); } } fn demo_from_integer_mantissa_and_exponent_targeted_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in unsigned_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}::from_integer_mantissa_and_exponent({}, {}) = {}", T::NAME, mantissa, exponent, NiceFloat(T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap()) ); } } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_mantissa_and_exponent_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_mantissa_and_exponent()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| { no_out!(x.integer_mantissa_and_exponent()); }), ("alt", &mut |x| { no_out!((x.integer_mantissa(), x.integer_exponent())); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_mantissa_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_mantissa()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| no_out!(x.integer_mantissa())), ("alt", &mut |x| no_out!(x.integer_mantissa_and_exponent().0)), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_exponent_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_exponent()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| no_out!(x.integer_exponent())), ("alt", &mut |x| no_out!(x.integer_mantissa_and_exponent().1)), ], ); } fn benchmark_from_integer_mantissa_and_exponent_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_integer_mantissa_and_exponent({}, u64)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_integer_mantissa_and_exponent(mantissa, exponent)); })], ); } fn benchmark_from_integer_mantissa_and_exponent_targeted_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_integer_mantissa_and_exponent({}, u64)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_30::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_integer_mantissa_and_exponent(mantissa, exponent)); })], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_mantissa_and_exponent_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_mantissa_and_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| { no_out!(x.integer_mantissa_and_exponent()); }), ("alt", &mut |x| { no_out!((x.integer_mantissa(), x.integer_exponent())); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_mantissa_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_mantissa()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.integer_mantissa())), ("alt", &mut |x| no_out!(x.integer_mantissa_and_exponent().0)), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_exponent_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.integer_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.integer_exponent())), ("alt", &mut |x| no_out!(x.integer_mantissa_and_exponent().1)), ], ); } fn benchmark_from_integer_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_integer_mantissa_and_exponent(u64, u64)", T::NAME), BenchmarkType::Single, unsigned_signed_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_integer_mantissa_and_exponent(mantissa, exponent)); })], ); } fn benchmark_from_integer_mantissa_and_exponent_targeted_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_integer_mantissa_and_exponent(u64, u64)", T::NAME), BenchmarkType::Single, unsigned_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_integer_mantissa_and_exponent(mantissa, exponent)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/mantissa_and_exponent/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { integer_mantissa_and_exponent::register(runner); raw_mantissa_and_exponent::register(runner); sci_mantissa_and_exponent::register(runner); } mod integer_mantissa_and_exponent; mod raw_mantissa_and_exponent; mod sci_mantissa_and_exponent; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/mantissa_and_exponent/raw_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{pair_1_bit_bucketer, primitive_float_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{primitive_float_gen, unsigned_pair_gen_var_26}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_raw_mantissa_and_exponent); register_primitive_float_demos!(runner, demo_raw_mantissa); register_primitive_float_demos!(runner, demo_raw_exponent); register_primitive_float_demos!(runner, demo_from_raw_mantissa_and_exponent); register_primitive_float_benches!(runner, benchmark_raw_mantissa_and_exponent_algorithms); register_primitive_float_benches!(runner, benchmark_raw_mantissa_algorithms); register_primitive_float_benches!(runner, benchmark_raw_exponent_algorithms); register_primitive_float_benches!(runner, benchmark_from_raw_mantissa_and_exponent); } fn demo_raw_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "raw_mantissa_and_exponent({}) = {:?}", NiceFloat(x), x.raw_mantissa_and_exponent() ); } } fn demo_raw_mantissa(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen::().get(gm, config).take(limit) { println!("raw_mantissa({}) = {}", NiceFloat(x), x.raw_mantissa()); } } fn demo_raw_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen::().get(gm, config).take(limit) { println!("raw_exponent({}) = {}", NiceFloat(x), x.raw_exponent()); } } fn demo_from_raw_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in unsigned_pair_gen_var_26::().get(gm, config).take(limit) { println!( "{}::from_raw_mantissa_and_exponent({}, {}) = {}", T::NAME, mantissa, exponent, NiceFloat(T::from_raw_mantissa_and_exponent(mantissa, exponent)) ); } } #[allow(clippy::unnecessary_operation)] fn benchmark_raw_mantissa_and_exponent_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.raw_mantissa_and_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.raw_mantissa_and_exponent())), ("alt", &mut |x| { no_out!((x.raw_mantissa(), x.raw_exponent())); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_raw_mantissa_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.raw_mantissa()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.raw_mantissa())), ("alt", &mut |x| no_out!(x.raw_mantissa_and_exponent().0)), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_raw_exponent_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.raw_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.raw_exponent())), ("alt", &mut |x| no_out!(x.raw_mantissa_and_exponent().1)), ], ); } fn benchmark_from_raw_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_raw_mantissa_and_exponent(u64, u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_26::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_raw_mantissa_and_exponent(mantissa, exponent)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/mantissa_and_exponent/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::mantissa_and_exponent::{ from_sci_mantissa_and_exponent_round, sci_mantissa_and_exponent_round, }; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_primitive_float_bucketer, primitive_float_bucketer, triple_1_primitive_float_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, primitive_float_signed_pair_gen_var_1, primitive_float_signed_pair_gen_var_2, primitive_float_unsigned_pair_gen_var_1, primitive_float_unsigned_pair_gen_var_2, primitive_float_unsigned_rounding_mode_triple_gen_var_1, primitive_float_unsigned_rounding_mode_triple_gen_var_2, unsigned_gen_var_1, unsigned_rounding_mode_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_unsigned); register_unsigned_primitive_float_demos!(runner, demo_sci_mantissa_unsigned); register_unsigned_primitive_float_demos!(runner, demo_sci_exponent_unsigned); register_unsigned_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_round); register_unsigned_primitive_float_demos!(runner, demo_from_sci_mantissa_and_exponent_unsigned); register_unsigned_primitive_float_demos!( runner, demo_from_sci_mantissa_and_exponent_targeted_unsigned ); register_unsigned_primitive_float_demos!(runner, demo_from_sci_mantissa_and_exponent_round); register_unsigned_primitive_float_demos!( runner, demo_from_sci_mantissa_and_exponent_round_targeted ); register_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_primitive_float); register_primitive_float_demos!(runner, demo_sci_mantissa_primitive_float); register_primitive_float_demos!(runner, demo_sci_exponent_primitive_float); register_primitive_float_demos!(runner, demo_from_sci_mantissa_and_exponent_primitive_float); register_primitive_float_demos!( runner, demo_from_sci_mantissa_and_exponent_targeted_primitive_float ); register_unsigned_primitive_float_benches!( runner, benchmark_sci_mantissa_and_exponent_algorithms_unsigned ); register_unsigned_primitive_float_benches!(runner, benchmark_sci_mantissa_algorithms_unsigned); register_unsigned_primitive_float_benches!(runner, benchmark_sci_exponent_algorithms_unsigned); register_unsigned_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_unsigned ); register_unsigned_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_targeted_unsigned ); register_unsigned_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_round ); register_unsigned_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_round_targeted ); register_primitive_float_benches!( runner, benchmark_sci_mantissa_and_exponent_algorithms_primitive_float ); register_primitive_float_benches!(runner, benchmark_sci_mantissa_algorithms_primitive_float); register_primitive_float_benches!(runner, benchmark_sci_exponent_algorithms_primitive_float); register_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_primitive_float ); register_primitive_float_benches!( runner, benchmark_from_sci_mantissa_and_exponent_targeted_primitive_float ); } fn demo_sci_mantissa_and_exponent_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { let (m, e): (U, u64) = x.sci_mantissa_and_exponent(); println!("sci_mantissa_and_exponent({}) = {:?}", x, (NiceFloat(m), e)); } } fn demo_sci_mantissa_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { let m: U = x.sci_mantissa(); println!("sci_mantissa({}) = {}", x, NiceFloat(m)); } } fn demo_sci_exponent_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_1::().get(gm, config).take(limit) { println!( "sci_exponent({}) = {}", x, SciMantissaAndExponent::::sci_exponent(x) ); } } fn demo_sci_mantissa_and_exponent_round< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, rm) in unsigned_rounding_mode_pair_gen_var_1::() .get(gm, config) .take(limit) { let o = sci_mantissa_and_exponent_round::(x, rm).map(|(m, e, o)| (NiceFloat(m), e, o)); println!("sci_mantissa_and_exponent_round({x}, {rm}) = {o:?}"); } } fn demo_from_sci_mantissa_and_exponent_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in primitive_float_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}::from_sci_mantissa_and_exponent({}, {}) = {:?}", T::NAME, NiceFloat(mantissa), exponent, T::from_sci_mantissa_and_exponent(mantissa, exponent) ); } } fn demo_from_sci_mantissa_and_exponent_targeted_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in primitive_float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}::from_sci_mantissa_and_exponent({}, {}) = {:?}", T::NAME, NiceFloat(mantissa), exponent, T::from_sci_mantissa_and_exponent(mantissa, exponent) ); } } fn demo_from_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "from_sci_mantissa_and_exponent_round({}, {}, {}) = {:?}", NiceFloat(mantissa), exponent, rm, from_sci_mantissa_and_exponent_round::(mantissa, exponent, rm) ); } } fn demo_from_sci_mantissa_and_exponent_round_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "from_sci_mantissa_and_exponent_round({}, {}, {}) = {:?}", NiceFloat(mantissa), exponent, rm, from_sci_mantissa_and_exponent_round::(mantissa, exponent, rm) ); } } fn demo_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { let (m, e) = x.sci_mantissa_and_exponent(); println!( "sci_mantissa_and_exponent({}) = {:?}", NiceFloat(x), (NiceFloat(m), e) ); } } fn demo_sci_mantissa_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!( "sci_mantissa({}) = {}", NiceFloat(x), NiceFloat(x.sci_mantissa()) ); } } fn demo_sci_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!("sci_exponent({}) = {}", NiceFloat(x), x.sci_exponent()); } } fn demo_from_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in primitive_float_signed_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "{}::from_sci_mantissa_and_exponent({}, {}) = {:?}", T::NAME, NiceFloat(mantissa), exponent, T::from_sci_mantissa_and_exponent(mantissa, exponent).map(NiceFloat) ); } } fn demo_from_sci_mantissa_and_exponent_targeted_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in primitive_float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}::from_sci_mantissa_and_exponent({}, {}) = {}", T::NAME, NiceFloat(mantissa), exponent, NiceFloat(T::from_sci_mantissa_and_exponent(mantissa, exponent).unwrap()) ); } } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_mantissa_and_exponent_algorithms_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_mantissa_and_exponent()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa_and_exponent( x )); }), ("alt", &mut |x| { no_out!(( SciMantissaAndExponent::::sci_mantissa(x), SciMantissaAndExponent::::sci_exponent(x) )); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_mantissa_algorithms_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_mantissa()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa(x)); }), ("alt", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa_and_exponent(x).0); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_exponent_algorithms_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_exponent()", T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |x| { no_out!(SciMantissaAndExponent::::sci_exponent(x)); }), ("alt", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa_and_exponent(x).1); }), ], ); } fn benchmark_from_sci_mantissa_and_exponent_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_sci_mantissa_and_exponent({}, u64)", U::NAME, T::NAME ), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_sci_mantissa_and_exponent(mantissa, exponent)); })], ); } fn benchmark_from_sci_mantissa_and_exponent_targeted_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_sci_mantissa_and_exponent({}, u64)", U::NAME, T::NAME ), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_sci_mantissa_and_exponent(mantissa, exponent)); })], ); } fn benchmark_from_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "from_sci_mantissa_and_exponent_round({}, u64, RoundingMode)", U::NAME ), BenchmarkType::Single, primitive_float_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent, rm)| { no_out!(from_sci_mantissa_and_exponent_round::( mantissa, exponent, rm )); })], ); } fn benchmark_from_sci_mantissa_and_exponent_round_targeted< T: PrimitiveUnsigned, U: PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "from_sci_mantissa_and_exponent_round({}, u64, RoundingMode)", U::NAME ), BenchmarkType::Single, primitive_float_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent, rm)| { no_out!(from_sci_mantissa_and_exponent_round::( mantissa, exponent, rm )); })], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_mantissa_and_exponent_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_mantissa_and_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.sci_mantissa_and_exponent())), ("alt", &mut |x| { no_out!((x.sci_mantissa(), x.sci_exponent())); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_mantissa_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_mantissa()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.sci_mantissa())), ("alt", &mut |x| no_out!(x.sci_mantissa_and_exponent().0)), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_sci_exponent_algorithms_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.sci_exponent()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("default", &mut |x| no_out!(x.sci_exponent())), ("alt", &mut |x| no_out!(x.sci_mantissa_and_exponent().1)), ], ); } fn benchmark_from_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_sci_mantissa_and_exponent({}, u64)", T::NAME, T::NAME ), BenchmarkType::Single, primitive_float_signed_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_sci_mantissa_and_exponent(mantissa, exponent)); })], ); } fn benchmark_from_sci_mantissa_and_exponent_targeted_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_sci_mantissa_and_exponent({}, u64)", T::NAME, T::NAME ), BenchmarkType::Single, primitive_float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(T::from_sci_mantissa_and_exponent(mantissa, exponent)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { digits::register(runner); from::register(runner); half::register(runner); is_integer::register(runner); mantissa_and_exponent::register(runner); slice::register(runner); string::register(runner); } mod digits; mod from; mod half; mod is_integer; mod mantissa_and_exponent; mod slice; mod string; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/slice/from_other_type_slice.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::FromOtherTypeSlice; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; use std::fmt::Display; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_from_other_type_slice); register_unsigned_unsigned_benches!(runner, benchmark_from_other_type_slice); } fn demo_from_other_type_slice + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "{}::from_other_type_slice({:?}) = {}", T::NAME, xs, T::from_other_type_slice(&xs) ); } } fn benchmark_from_other_type_slice + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.from_other_type_slice(&[{}])", T::NAME, U::NAME), BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| { no_out!(T::from_other_type_slice(&xs)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/slice/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_other_type_slice::register(runner); vec_from_other_type::register(runner); vec_from_other_type_slice::register(runner); } mod from_other_type_slice; mod vec_from_other_type; mod vec_from_other_type_slice; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/slice/vec_from_other_type.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::VecFromOtherType; use malachite_base::test_util::bench::bucketers::unsigned_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::runner::Runner; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_vec_from_other_type); register_unsigned_unsigned_benches!(runner, benchmark_vec_from_other_type); } fn demo_vec_from_other_type + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!( "{}::vec_from_other_type({}) = {:?}", T::NAME, u, T::vec_from_other_type(u) ); } } fn benchmark_vec_from_other_type + Named, U: PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.vec_from_other_type({})", T::NAME, U::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(T::vec_from_other_type(n)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/slice/vec_from_other_type_slice.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::VecFromOtherTypeSlice; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_unsigned_unsigned_demos!(runner, demo_vec_from_other_type_slice); register_unsigned_unsigned_benches!(runner, benchmark_vec_from_other_type_slice); } fn demo_vec_from_other_type_slice< T: Debug + VecFromOtherTypeSlice + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "{}::vec_from_other_type_slice({:?}) = {:?}", T::NAME, xs, T::vec_from_other_type_slice(&xs) ); } } fn benchmark_vec_from_other_type_slice< T: VecFromOtherTypeSlice + Named, U: PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.vec_from_other_type_slice(&[{}])", T::NAME, U::NAME), BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| { no_out!(T::vec_from_other_type_slice(&xs)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::bench::bucketers::{ pair_1_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen, string_from_sci_string_options_pair_gen_var_1, string_gen, string_gen_var_13, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_demos!(runner, demo_primitive_int_from_sci_string); register_primitive_int_demos!(runner, demo_primitive_int_from_sci_string_targeted); register_primitive_int_demos!(runner, demo_primitive_int_from_sci_string_with_options); register_primitive_int_demos!( runner, demo_primitive_int_from_sci_string_with_options_targeted ); register_primitive_int_benches!(runner, benchmark_primitive_int_from_sci_string); register_primitive_int_benches!(runner, benchmark_primitive_int_from_sci_string_with_options); } fn demo_primitive_int_from_sci_string( gm: GenMode, config: &GenConfig, limit: usize, ) { for s in string_gen().get(gm, config).take(limit) { println!( "{}::from_sci_string({}) = {:?}", T::NAME, s, T::from_sci_string(&s) ); } } fn demo_primitive_int_from_sci_string_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for s in string_gen_var_13().get(gm, config).take(limit) { println!( "{}::from_sci_string({}) = {:?}", T::NAME, s, T::from_sci_string(&s) ); } } fn demo_primitive_int_from_sci_string_with_options( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, options) in string_from_sci_string_options_pair_gen() .get(gm, config) .take(limit) { println!( "{}::from_sci_string_with_options({}, {:?}) = {:?}", T::NAME, s, options, T::from_sci_string_with_options(&s, options) ); } } fn demo_primitive_int_from_sci_string_with_options_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, options) in string_from_sci_string_options_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "{}::from_sci_string_with_options({}, {:?}) = {:?}", T::NAME, s, options, T::from_sci_string_with_options(&s, options) ); } } fn benchmark_primitive_int_from_sci_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_sci_string(&str)", T::NAME), BenchmarkType::Single, string_gen_var_13().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(T::from_sci_string(&s)))], ); } fn benchmark_primitive_int_from_sci_string_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "{}::from_sci_string_with_options(&str, FromSciStringOptions)", T::NAME ), BenchmarkType::Single, string_from_sci_string_options_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_string_len_bucketer("s"), &mut [("Malachite", &mut |(s, options)| { no_out!(T::from_sci_string_with_options(&s, options)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::string::from_string::digit_from_display_byte; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_gen, unsigned_gen_var_10}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_digit_from_display_byte); register_demo!(runner, demo_digit_from_display_byte_targeted); } fn demo_digit_from_display_byte(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen().get(gm, config).take(limit) { println!( "digit_from_display_byte({}) = {:?}", b, digit_from_display_byte(b) ); } } fn demo_digit_from_display_byte_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen_var_10().get(gm, config).take(limit) { println!( "digit_from_display_byte({}) = {}", b, digit_from_display_byte(b).unwrap() ); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sci_string::register(runner); from_string::register(runner); options::register(runner); to_sci::register(runner); to_string::register(runner); } mod from_sci_string; mod from_string; mod options; mod to_sci; mod to_string; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/options/from_sci_string_options.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ from_sci_string_options_gen, from_sci_string_options_rounding_mode_pair_gen, from_sci_string_options_unsigned_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_from_sci_string_options_to_debug_string); register_demo!(runner, demo_from_sci_string_options_get_base); register_demo!(runner, demo_from_sci_string_options_get_rounding_mode); register_demo!(runner, demo_from_sci_string_options_set_base); register_demo!(runner, demo_from_sci_string_options_set_rounding_mode); } fn demo_from_sci_string_options_to_debug_string(gm: GenMode, config: &GenConfig, limit: usize) { for options in from_sci_string_options_gen().get(gm, config).take(limit) { println!("{options:?}"); } } fn demo_from_sci_string_options_get_base(gm: GenMode, config: &GenConfig, limit: usize) { for options in from_sci_string_options_gen().get(gm, config).take(limit) { println!("get_base({:?}) = {}", options, options.get_base()); } } fn demo_from_sci_string_options_get_rounding_mode(gm: GenMode, config: &GenConfig, limit: usize) { for options in from_sci_string_options_gen().get(gm, config).take(limit) { println!( "get_rounding_mode({:?}) = {}", options, options.get_rounding_mode() ); } } fn demo_from_sci_string_options_set_base(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, base) in from_sci_string_options_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { let old_options = options; options.set_base(base); println!("options := {old_options:?}; options.set_base({base}); options = {options:?}"); } } fn demo_from_sci_string_options_set_rounding_mode(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, rm) in from_sci_string_options_rounding_mode_pair_gen() .get(gm, config) .take(limit) { let old_options = options; options.set_rounding_mode(rm); println!( "options := {old_options:?}; options.set_rounding_mode({rm}); options = {options:?}", ); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/options/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sci_string_options::register(runner); sci_size_options::register(runner); to_sci_options::register(runner); } mod from_sci_string_options; mod sci_size_options; mod to_sci_options; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/options/sci_size_options.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::sci_size_options_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_sci_size_options_to_debug_string); } fn demo_sci_size_options_to_debug_string(gm: GenMode, config: &GenConfig, limit: usize) { for options in sci_size_options_gen().get(gm, config).take(limit) { println!("{options:?}"); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/options/to_sci_options.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ to_sci_options_bool_pair_gen, to_sci_options_gen, to_sci_options_rounding_mode_pair_gen, to_sci_options_signed_pair_gen_var_1, to_sci_options_unsigned_pair_gen_var_1, to_sci_options_unsigned_pair_gen_var_2, to_sci_options_unsigned_pair_gen_var_3, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_to_sci_options_to_debug_string); register_demo!(runner, demo_to_sci_options_get_base); register_demo!(runner, demo_to_sci_options_get_rounding_mode); register_demo!(runner, demo_to_sci_options_get_size_options); register_demo!(runner, demo_to_sci_options_get_neg_exp_threshold); register_demo!(runner, demo_to_sci_options_get_lowercase); register_demo!(runner, demo_to_sci_options_get_e_lowercase); register_demo!(runner, demo_to_sci_options_get_force_exponent_plus_sign); register_demo!(runner, demo_to_sci_options_get_include_trailing_zeros); register_demo!(runner, demo_to_sci_options_set_base); register_demo!(runner, demo_to_sci_options_set_rounding_mode); register_demo!(runner, demo_to_sci_options_set_size_complete); register_demo!(runner, demo_to_sci_options_set_precision); register_demo!(runner, demo_to_sci_options_set_scale); register_demo!(runner, demo_to_sci_options_set_neg_exp_threshold); register_demo!(runner, demo_to_sci_options_set_lowercase); register_demo!(runner, demo_to_sci_options_set_uppercase); register_demo!(runner, demo_to_sci_options_set_e_lowercase); register_demo!(runner, demo_to_sci_options_set_e_uppercase); register_demo!(runner, demo_to_sci_options_set_force_exponent_plus_sign); register_demo!(runner, demo_to_sci_options_set_include_trailing_zeros); } fn demo_to_sci_options_to_debug_string(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!("{options:?}"); } } fn demo_to_sci_options_get_base(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!("get_base({:?}) = {}", options, options.get_base()); } } fn demo_to_sci_options_get_rounding_mode(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_rounding_mode({:?}) = {}", options, options.get_rounding_mode() ); } } fn demo_to_sci_options_get_size_options(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_size_options({:?}) = {:?}", options, options.get_size_options() ); } } fn demo_to_sci_options_get_neg_exp_threshold(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_neg_exp_threshold({:?}) = {}", options, options.get_neg_exp_threshold() ); } } fn demo_to_sci_options_get_lowercase(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!("get_lowercase({:?}) = {}", options, options.get_lowercase()); } } fn demo_to_sci_options_get_e_lowercase(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_e_lowercase({:?}) = {}", options, options.get_e_lowercase() ); } } fn demo_to_sci_options_get_force_exponent_plus_sign(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_force_exponent_plus_sign({:?}) = {}", options, options.get_force_exponent_plus_sign() ); } } fn demo_to_sci_options_get_include_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for options in to_sci_options_gen().get(gm, config).take(limit) { println!( "get_include_trailing_zeros({:?}) = {}", options, options.get_include_trailing_zeros() ); } } fn demo_to_sci_options_set_base(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, base) in to_sci_options_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { let old_options = options; options.set_base(base); println!("options := {old_options:?}; options.set_base({base}); options = {options:?}"); } } fn demo_to_sci_options_set_rounding_mode(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, rm) in to_sci_options_rounding_mode_pair_gen() .get(gm, config) .take(limit) { let old_options = options; options.set_rounding_mode(rm); println!( "options := {old_options:?}; options.set_rounding_mode({rm}); options = {options:?}", ); } } fn demo_to_sci_options_set_size_complete(gm: GenMode, config: &GenConfig, limit: usize) { for mut options in to_sci_options_gen().get(gm, config).take(limit) { let old_options = options; options.set_size_complete(); println!("options := {old_options:?}; options.set_size_complete(); options = {options:?}"); } } fn demo_to_sci_options_set_precision(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, precision) in to_sci_options_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let old_options = options; options.set_precision(precision); println!( "options := {old_options:?}; options.set_precision({precision}); options = {options:?}", ); } } fn demo_to_sci_options_set_scale(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, scale) in to_sci_options_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let old_options = options; options.set_scale(scale); println!("options := {old_options:?}; options.set_scale({scale}); options = {options:?}"); } } fn demo_to_sci_options_set_neg_exp_threshold(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, neg_exp_threshold) in to_sci_options_signed_pair_gen_var_1() .get(gm, config) .take(limit) { let old_options = options; options.set_neg_exp_threshold(neg_exp_threshold); println!( "options := {old_options:?}; options.set_neg_exp_threshold({neg_exp_threshold}); \ options = {options:?}", ); } } fn demo_to_sci_options_set_lowercase(gm: GenMode, config: &GenConfig, limit: usize) { for mut options in to_sci_options_gen().get(gm, config).take(limit) { let old_options = options; options.set_lowercase(); println!("options := {old_options:?}; options.set_lowercase(); options = {options:?}"); } } fn demo_to_sci_options_set_uppercase(gm: GenMode, config: &GenConfig, limit: usize) { for mut options in to_sci_options_gen().get(gm, config).take(limit) { let old_options = options; options.set_uppercase(); println!("options := {old_options:?}; options.set_uppercase(); options = {options:?}"); } } fn demo_to_sci_options_set_e_lowercase(gm: GenMode, config: &GenConfig, limit: usize) { for mut options in to_sci_options_gen().get(gm, config).take(limit) { let old_options = options; options.set_e_lowercase(); println!("options := {old_options:?}; options.set_e_lowercase(); options = {options:?}"); } } fn demo_to_sci_options_set_e_uppercase(gm: GenMode, config: &GenConfig, limit: usize) { for mut options in to_sci_options_gen().get(gm, config).take(limit) { let old_options = options; options.set_e_uppercase(); println!("options := {old_options:?}; options.set_e_uppercase(); options = {options:?}"); } } fn demo_to_sci_options_set_force_exponent_plus_sign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, force_exponent_plus_sign) in to_sci_options_bool_pair_gen().get(gm, config).take(limit) { let old_options = options; options.set_force_exponent_plus_sign(force_exponent_plus_sign); println!( "options := {old_options:?}; \ options.set_force_exponent_plus_sign({force_exponent_plus_sign}); \ options = {options:?}", ); } } fn demo_to_sci_options_set_include_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for (mut options, include_trailing_zeros) in to_sci_options_bool_pair_gen().get(gm, config).take(limit) { let old_options = options; options.set_include_trailing_zeros(include_trailing_zeros); println!( "options := {old_options:?}; \ options.set_include_trailing_zeros({include_trailing_zeros}); options = {options:?}", ); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, signed_bit_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen, signed_to_sci_options_pair_gen, signed_to_sci_options_pair_gen_var_1, unsigned_gen, unsigned_to_sci_options_pair_gen, unsigned_to_sci_options_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_to_sci_unsigned); register_signed_demos!(runner, demo_to_sci_signed); register_unsigned_demos!(runner, demo_fmt_sci_valid_unsigned); register_signed_demos!(runner, demo_fmt_sci_valid_signed); register_unsigned_demos!(runner, demo_to_sci_with_options_unsigned); register_signed_demos!(runner, demo_to_sci_with_options_signed); register_unsigned_benches!(runner, benchmark_to_sci_unsigned); register_signed_benches!(runner, benchmark_to_sci_signed); register_unsigned_benches!(runner, benchmark_fmt_sci_valid_unsigned); register_signed_benches!(runner, benchmark_fmt_sci_valid_signed); register_unsigned_benches!(runner, benchmark_to_sci_with_options_unsigned); register_signed_benches!(runner, benchmark_to_sci_with_options_signed); } fn demo_to_sci_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen::().get(gm, config).take(limit) { println!("{}.to_sci() = {}", x, x.to_sci()); } } fn demo_to_sci_signed(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen::().get(gm, config).take(limit) { println!("{}.to_sci() = {}", x, x.to_sci()); } } fn demo_fmt_sci_valid_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, options) in unsigned_to_sci_options_pair_gen::() .get(gm, config) .take(limit) { if x.fmt_sci_valid(options) { println!("{x} can be converted to sci using {options:?}"); } else { println!("{x} cannot be converted to sci using {options:?}"); } } } fn demo_fmt_sci_valid_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in signed_to_sci_options_pair_gen::() .get(gm, config) .take(limit) { if x.fmt_sci_valid(options) { println!("{x} can be converted to sci using {options:?}"); } else { println!("{x} cannot be converted to sci using {options:?}"); } } } fn demo_to_sci_with_options_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, options) in unsigned_to_sci_options_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "to_sci_with_options({}, {:?}) = {}", x, options, x.to_sci_with_options(options) ); } } fn demo_to_sci_with_options_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, options) in signed_to_sci_options_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "to_sci_with_options({}, {:?}) = {}", x, options, x.to_sci_with_options(options) ); } } fn benchmark_to_sci_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_sci()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.to_sci().to_string()))], ); } fn benchmark_to_sci_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_sci()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(x.to_sci().to_string()))], ); } fn benchmark_fmt_sci_valid_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.fmt_sci_valid(ToSciOptions)", T::NAME), BenchmarkType::Single, unsigned_to_sci_options_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.fmt_sci_valid(options)); })], ); } fn benchmark_fmt_sci_valid_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.fmt_sci_valid(ToSciOptions)", T::NAME), BenchmarkType::Single, signed_to_sci_options_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("i"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.fmt_sci_valid(options)); })], ); } fn benchmark_to_sci_with_options_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_sci_with_options(ToSciOptions)", T::NAME), BenchmarkType::Single, unsigned_to_sci_options_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.to_sci_with_options(options).to_string()); })], ); } fn benchmark_to_sci_with_options_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_sci_with_options(ToSciOptions)", T::NAME), BenchmarkType::Single, signed_to_sci_options_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("u"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.to_sci_with_options(options).to_string()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::to_string::{ BaseFmtWrapper, digit_to_display_byte_lower, digit_to_display_byte_upper, }; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::bench::bucketers::{pair_1_bit_bucketer, triple_1_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_5, signed_unsigned_unsigned_triple_gen_var_3, unsigned_gen, unsigned_gen_var_7, unsigned_pair_gen_var_8, unsigned_triple_gen_var_6, }; use malachite_base::test_util::num::conversion::string::to_string::{ to_string_base_signed_naive, to_string_base_unsigned_naive, }; use malachite_base::test_util::runner::Runner; use std::fmt::Display; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_digit_to_display_byte_lower); register_demo!(runner, demo_digit_to_display_byte_upper); register_demo!(runner, demo_digit_to_display_byte_lower_targeted); register_demo!(runner, demo_digit_to_display_byte_upper_targeted); register_unsigned_demos!(runner, demo_to_string_base_unsigned); register_signed_demos!(runner, demo_to_string_base_signed); register_unsigned_demos!(runner, demo_to_string_base_upper_unsigned); register_signed_demos!(runner, demo_to_string_base_upper_signed); register_unsigned_demos!(runner, demo_base_fmt_wrapper_fmt_unsigned); register_unsigned_demos!(runner, demo_base_fmt_wrapper_fmt_with_width_unsigned); register_signed_demos!(runner, demo_base_fmt_wrapper_fmt_signed); register_signed_demos!(runner, demo_base_fmt_wrapper_fmt_with_width_signed); register_unsigned_demos!(runner, demo_base_fmt_wrapper_fmt_upper_unsigned); register_unsigned_demos!(runner, demo_base_fmt_wrapper_fmt_upper_with_width_unsigned); register_signed_demos!(runner, demo_base_fmt_wrapper_fmt_upper_signed); register_signed_demos!(runner, demo_base_fmt_wrapper_fmt_upper_with_width_signed); register_unsigned_benches!(runner, benchmark_to_string_base_algorithms_unsigned); register_signed_benches!(runner, benchmark_to_string_base_algorithms_signed); register_unsigned_benches!(runner, benchmark_to_string_base_upper_algorithms_unsigned); register_signed_benches!(runner, benchmark_to_string_base_upper_algorithms_signed); register_unsigned_benches!(runner, benchmark_base_fmt_wrapper_fmt_with_width_unsigned); register_signed_benches!(runner, benchmark_base_fmt_wrapper_fmt_with_width_signed); register_unsigned_benches!( runner, benchmark_base_fmt_wrapper_fmt_upper_with_width_unsigned ); register_signed_benches!( runner, benchmark_base_fmt_wrapper_fmt_upper_with_width_signed ); } fn demo_digit_to_display_byte_lower(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen().get(gm, config).take(limit) { println!( "digit_to_display_byte_lower({}) = {:?}", b, digit_to_display_byte_lower(b) ); } } fn demo_digit_to_display_byte_upper(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen().get(gm, config).take(limit) { println!( "digit_to_display_byte_upper({}) = {:?}", b, digit_to_display_byte_upper(b) ); } } fn demo_digit_to_display_byte_lower_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen_var_7().get(gm, config).take(limit) { println!( "digit_to_display_byte_lower({}) = {}", b, digit_to_display_byte_lower(b).unwrap() ); } } fn demo_digit_to_display_byte_upper_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for b in unsigned_gen_var_7().get(gm, config).take(limit) { println!( "digit_to_display_byte_upper({}) = {}", b, digit_to_display_byte_upper(b).unwrap() ); } } fn demo_to_string_base_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base) in unsigned_pair_gen_var_8::() .get(gm, config) .take(limit) { println!( "{}.to_string_base({}) = {}", x, base, x.to_string_base(base) ); } } fn demo_to_string_base_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in signed_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "({}).to_string_base({}) = {}", x, base, x.to_string_base(base) ); } } fn demo_to_string_base_upper_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base) in unsigned_pair_gen_var_8::() .get(gm, config) .take(limit) { println!( "{}.to_string_base_upper({}) = {}", x, base, x.to_string_base_upper(base) ); } } fn demo_to_string_base_upper_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base) in signed_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "({}).to_string_base_upper({}) = {}", x, base, x.to_string_base_upper(base) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base) in unsigned_pair_gen_var_8::() .get(gm, config) .take(limit) { println!( "format!(\"{{}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{}", BaseFmtWrapper::new(x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_with_width_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base, width) in unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:0width$}", BaseFmtWrapper::new(x, base), width = width) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base) in signed_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "format!(\"{{}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{}", BaseFmtWrapper::new(x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_with_width_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base, width) in signed_unsigned_unsigned_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:0width$}", BaseFmtWrapper::new(x, base), width = width) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_upper_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base) in unsigned_pair_gen_var_8::() .get(gm, config) .take(limit) { println!( "format!(\"{{:#}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{:#}", BaseFmtWrapper::new(x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_upper_with_width_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base, width) in unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:#0width$}", BaseFmtWrapper::new(x, base), width = width) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_upper_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base) in signed_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "format!(\"{{:#}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{:#}", BaseFmtWrapper::new(x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_base_fmt_wrapper_fmt_upper_with_width_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where BaseFmtWrapper: Display, { for (x, base, width) in signed_unsigned_unsigned_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:#0width$}", BaseFmtWrapper::new(x, base), width = width) ); } } #[allow(unused_must_use)] fn benchmark_to_string_base_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, u8: WrappingFrom, { run_benchmark( &format!("{}.to_string_base(u8)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{}", BaseFmtWrapper::new(x, base))); }), ("naive", &mut |(x, base)| { no_out!(to_string_base_unsigned_naive(x, base)); }), ], ); } #[allow(unused_must_use)] fn benchmark_to_string_base_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, u8: WrappingFrom<::Output>, ::Output: PrimitiveUnsigned, { run_benchmark( &format!("{}.to_string_base(u8)", T::NAME), BenchmarkType::Algorithms, signed_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{}", BaseFmtWrapper::new(x, base))); }), ("naive", &mut |(x, base)| { no_out!(to_string_base_signed_naive(x, base)); }), ], ); } #[allow(unused_must_use)] fn benchmark_to_string_base_upper_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!("{}.to_string_base_upper(u8)", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base_upper(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{:#}", BaseFmtWrapper::new(x, base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_to_string_base_upper_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!("{}.to_string_base_upper(u8)", T::NAME), BenchmarkType::Algorithms, signed_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{}", BaseFmtWrapper::new(x, base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_base_fmt_wrapper_fmt_with_width_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!( "format!(\"{{:0usize}}\", BaseFmtWrapper::new({}, u8))", T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:0width$}", BaseFmtWrapper::new(x, base), width = width )); })], ); } #[allow(unused_must_use)] fn benchmark_base_fmt_wrapper_fmt_with_width_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!( "format!(\"{{:0usize}}\", BaseFmtWrapper::new({}, u8))", T::NAME ), BenchmarkType::Single, signed_unsigned_unsigned_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:0width$}", BaseFmtWrapper::new(x, base), width = width )); })], ); } #[allow(unused_must_use)] fn benchmark_base_fmt_wrapper_fmt_upper_with_width_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!( "format!(\"{{:#0usize}}\", BaseFmtWrapper::new({}, u8))", T::NAME ), BenchmarkType::Single, unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:#0width$}", BaseFmtWrapper::new(x, base), width = width )); })], ); } #[allow(unused_must_use)] fn benchmark_base_fmt_wrapper_fmt_upper_with_width_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BaseFmtWrapper: Display, { run_benchmark( &format!( "format!(\"{{:#0usize}}\", BaseFmtWrapper::new({}, u8))", T::NAME ), BenchmarkType::Single, signed_unsigned_unsigned_triple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:#0width$}", BaseFmtWrapper::new(x, base), width = width )); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/factor.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::factorization::traits::Factor; use malachite_base::test_util::bench::bucketers::primitive_int_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_1; use malachite_base::test_util::num::factorization::factor::factor_naive; use malachite_base::test_util::runner::Runner; use std::fmt::Write; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_u8_factor); register_demo!(runner, demo_u16_factor); register_demo!(runner, demo_u32_factor); register_demo!(runner, demo_u64_factor); register_demo!(runner, demo_usize_factor); register_bench!(runner, benchmark_u8_factor_algorithms); register_bench!(runner, benchmark_u16_factor_algorithms); register_bench!(runner, benchmark_u32_factor); register_bench!(runner, benchmark_u32_factor_algorithms); register_bench!(runner, benchmark_u64_factor); register_bench!(runner, benchmark_u64_factor_algorithms); register_bench!(runner, benchmark_usize_factor_algorithms); } fn demo_factor_helper(u: T) where ::FACTORS: IntoIterator, { let mut s = String::new(); for (p, e) in u.factor() { if !s.is_empty() { write!(s, "×").ok(); } if e == 1 { write!(s, "{p}").ok(); } else { write!(s, "{p}^{e}").ok(); } } if s.is_empty() { s = "1".to_string(); } println!("factor({u}) = {s}"); } fn demo_u8_factor(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_1::().get(gm, config).take(limit) { demo_factor_helper(u); } } fn demo_u16_factor(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_1::().get(gm, config).take(limit) { demo_factor_helper(u); } } fn demo_u32_factor(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_1::().get(gm, config).take(limit) { demo_factor_helper(u); } } fn demo_u64_factor(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_1::().get(gm, config).take(limit) { demo_factor_helper(u); } } fn demo_usize_factor(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_1::().get(gm, config).take(limit) { demo_factor_helper(u); } } fn benchmark_u8_factor_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u8.factor()", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } }), ("naive", &mut |u| { let fs = factor_naive(u); unsafe { std::ptr::read_volatile(&fs); } }), ], ); } fn benchmark_u16_factor_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u16.factor()", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } }), ("naive", &mut |u| { let fs = factor_naive(u); unsafe { std::ptr::read_volatile(&fs); } }), ], ); } fn benchmark_u32_factor(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u32.factor()", BenchmarkType::Single, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } })], ); } fn benchmark_u32_factor_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u32.factor()", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } }), ("naive", &mut |u| { let fs = factor_naive(u); unsafe { std::ptr::read_volatile(&fs); } }), ], ); } fn benchmark_u64_factor(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u64.factor()", BenchmarkType::Single, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } })], ); } fn benchmark_u64_factor_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u64.factor()", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } }), ("naive", &mut |u| { let fs = factor_naive(u); unsafe { std::ptr::read_volatile(&fs); } }), ], ); } fn benchmark_usize_factor_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "usize.factor()", BenchmarkType::Algorithms, unsigned_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let fs = u.factor(); unsafe { std::ptr::read_volatile(&fs); } }), ("naive", &mut |u| { let fs = factor_naive(u); unsafe { std::ptr::read_volatile(&fs); } }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/is_power.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_express_as_power_unsigned); register_signed_demos!(runner, demo_express_as_power_signed); register_unsigned_demos!(runner, demo_is_power_unsigned); register_signed_demos!(runner, demo_is_power_signed); register_unsigned_benches!(runner, benchmark_express_as_power_unsigned); register_signed_benches!(runner, benchmark_express_as_power_signed); register_unsigned_benches!(runner, benchmark_is_power_unsigned_algorithms); register_signed_benches!(runner, benchmark_is_power_signed_algorithms); } fn demo_express_as_power_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.express_as_power() = {:?}", u, u.express_as_power()); } } fn demo_express_as_power_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("({}).express_as_power() = {:?}", i, i.express_as_power()); } } fn demo_is_power_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_power() { println!("{u} is a perfect power"); } else { println!("{u} is not a perfect power"); } } } fn demo_is_power_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { if i.is_power() { println!("{i} is a perfect power"); } else { println!("{i} is not a perfect power"); } } } fn benchmark_express_as_power_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.express_as_power()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.express_as_power()))], ); } fn benchmark_express_as_power_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.express_as_power()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(i.express_as_power()))], ); } #[allow(unused_must_use)] fn benchmark_is_power_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_power()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |u| no_out!(u.is_power())), ("using express_as_power", &mut |u| { no_out!(u.express_as_power().is_some()); }), ], ); } #[allow(unused_must_use)] fn benchmark_is_power_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_power()", T::NAME), BenchmarkType::Algorithms, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("default", &mut |i| no_out!(i.is_power())), ("using express_as_power", &mut |i| { no_out!(i.express_as_power().is_some()); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/is_prime.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::traits::IsPrime; use malachite_base::test_util::bench::bucketers::primitive_int_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::num::factorization::is_prime::is_prime_naive; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_u8_is_prime); register_demo!(runner, demo_u16_is_prime); register_demo!(runner, demo_u32_is_prime); register_demo!(runner, demo_u64_is_prime); register_demo!(runner, demo_usize_is_prime); register_bench!(runner, benchmark_u8_is_prime_algorithms); register_bench!(runner, benchmark_u16_is_prime_algorithms); register_bench!(runner, benchmark_u32_is_prime); register_bench!(runner, benchmark_u32_is_prime_algorithms); register_bench!(runner, benchmark_u64_is_prime); register_bench!(runner, benchmark_u64_is_prime_algorithms); register_bench!(runner, benchmark_usize_is_prime_algorithms); } fn demo_u8_is_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_prime() { println!("{u} is prime"); } else { println!("{u} is not prime"); } } } fn demo_u16_is_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_prime() { println!("{u} is prime"); } else { println!("{u} is not prime"); } } } fn demo_u32_is_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_prime() { println!("{u} is prime"); } else { println!("{u} is not prime"); } } } fn demo_u64_is_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_prime() { println!("{u} is prime"); } else { println!("{u} is not prime"); } } } fn demo_usize_is_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_prime() { println!("{u} is prime"); } else { println!("{u} is not prime"); } } } fn benchmark_u8_is_prime_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u8.is_prime()", BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| no_out!(u.is_prime())), ("naive", &mut |u| no_out!(is_prime_naive(u))), ], ); } fn benchmark_u16_is_prime_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u16.is_prime()", BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| no_out!(u.is_prime())), ("naive", &mut |u| no_out!(is_prime_naive(u))), ], ); } fn benchmark_u32_is_prime(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u32.is_prime()", BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| { let b = u.is_prime(); unsafe { std::ptr::read_volatile(&b); } })], ); } fn benchmark_u32_is_prime_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.is_prime()", BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let b = u.is_prime(); unsafe { std::ptr::read_volatile(&b); } }), ("naive", &mut |u| { let b = is_prime_naive(u); unsafe { std::ptr::read_volatile(&b); } }), ], ); } fn benchmark_u64_is_prime(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "u64.is_prime()", BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| { let b = u.is_prime(); unsafe { std::ptr::read_volatile(&b); } })], ); } fn benchmark_u64_is_prime_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.is_prime()", BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| { let b = u.is_prime(); unsafe { std::ptr::read_volatile(&b); } }), ("naive", &mut |u| { let b = is_prime_naive(u); unsafe { std::ptr::read_volatile(&b); } }), ], ); } fn benchmark_usize_is_prime_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "usize.is_prime()", BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [ ("default", &mut |u| no_out!(u.is_prime())), ("naive", &mut |u| no_out!(is_prime_naive(u))), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/is_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_is_square_unsigned); register_signed_demos!(runner, demo_is_square_signed); register_unsigned_benches!(runner, benchmark_is_square_unsigned_algorithms); register_signed_benches!(runner, benchmark_is_square_signed_algorithms); } fn demo_is_square_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { if u.is_square() { println!("{u} is a perfect square"); } else { println!("{u} is not a perfect square"); } } } fn demo_is_square_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { if i.is_square() { println!("{i} is a perfect square"); } else { println!("{i} is not a perfect square"); } } } #[allow(unused_must_use)] fn benchmark_is_square_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_square()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("default", &mut |u| no_out!(u.is_square())), ("naive", &mut |u| no_out!(u.checked_sqrt().is_some())), ], ); } #[allow(unused_must_use)] fn benchmark_is_square_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_square()", T::NAME), BenchmarkType::Algorithms, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("default", &mut |i| no_out!(i.is_square())), ("naive", &mut |i| no_out!(i.checked_sqrt().is_some())), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { factor::register(runner); is_power::register(runner); is_prime::register(runner); is_square::register(runner); primes::register(runner); prime_sieve::register(runner); primitive_root_prime::register(runner); } mod factor; mod is_power; mod is_prime; mod is_square; mod prime_sieve; mod primes; mod primitive_root_prime; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/prime_sieve.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::prime_sieve::{ limbs_prime_sieve_size, limbs_prime_sieve_u32, limbs_prime_sieve_u64, }; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_26; use malachite_base::test_util::num::factorization::prime_sieve::{ limbs_prime_sieve_naive_1, limbs_prime_sieve_naive_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_prime_sieve_u32); register_demo!(runner, demo_limbs_prime_sieve_u64); register_bench!(runner, benchmark_limbs_prime_sieve_u32_algorithms); register_bench!(runner, benchmark_limbs_prime_sieve_u64_algorithms); } fn demo_limbs_prime_sieve_u32(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_26().get(gm, config).take(limit) { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_u32(&mut sieve, n); print!("limbs_prime_sieve_u32({n}): "); let mut first = true; for s in sieve { if first { first = false; } else { print!(", "); } print!("{s:b}"); } println!(); } } fn demo_limbs_prime_sieve_u64(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_26().get(gm, config).take(limit) { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_u64(&mut sieve, n); print!("limbs_prime_sieve_u64({n}): "); let mut first = true; for s in sieve { if first { first = false; } else { print!(", "); } print!("{s:b}"); } println!(); } } fn benchmark_limbs_prime_sieve_u32_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_prime_sieve_u32(&mut [Limb], u64)", BenchmarkType::Algorithms, unsigned_gen_var_26().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_u32(&mut sieve, n); }), ("test each prime separately", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_naive_1::(&mut sieve, n); }), ("naive sieve", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_naive_2::(&mut sieve, n); }), ], ); } fn benchmark_limbs_prime_sieve_u64_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_prime_sieve_u64(&mut [Limb], u64)", BenchmarkType::Algorithms, unsigned_gen_var_26().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_u64(&mut sieve, n); }), ("test each prime separately", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_naive_1::(&mut sieve, n); }), ("naive sieve", &mut |n| { let len = limbs_prime_sieve_size::(n); let mut sieve = vec![0; len]; limbs_prime_sieve_naive_2::(&mut sieve, n); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/primes.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::factorization::primes::{ prime_indicator_sequence, prime_indicator_sequence_less_than, prime_indicator_sequence_less_than_or_equal_to, }; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_pair_gen_var_28, unsigned_triple_gen_var_24, }; use malachite_base::test_util::num::factorization::primes::primes_naive; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_primes_less_than); register_unsigned_demos!(runner, demo_primes_less_than_or_equal_to); register_unsigned_demos!(runner, demo_primes); register_demo!(runner, demo_prime_indicator_sequence_less_than); register_demo!(runner, demo_prime_indicator_sequence_less_than_or_equal_to); register_demo!(runner, demo_prime_indicator_sequence); runner.register_demo( "demo_primes_less_than_jump_after_u8", &demo_primes_less_than_jump_after::, ); runner.register_demo( "demo_primes_less_than_jump_after_u16", &demo_primes_less_than_jump_after::, ); runner.register_demo( "demo_primes_less_than_jump_after_u32", &demo_primes_less_than_jump_after::, ); runner.register_demo( "demo_primes_less_than_jump_after_u64", &demo_primes_less_than_jump_after::, ); runner.register_demo( "demo_primes_less_than_jump_after_u128", &demo_primes_less_than_jump_after::, ); runner.register_demo( "demo_primes_less_than_jump_after_usize", &demo_primes_less_than_jump_after::, ); runner.register_demo("demo_primes_jump_after_u8", &demo_primes_jump_after::); runner.register_demo("demo_primes_jump_after_u16", &demo_primes_jump_after::); runner.register_demo("demo_primes_jump_after_u32", &demo_primes_jump_after::); runner.register_demo("demo_primes_jump_after_u64", &demo_primes_jump_after::); runner.register_demo( "demo_primes_jump_after_u128", &demo_primes_jump_after::, ); runner.register_demo( "demo_primes_jump_after_usize", &demo_primes_jump_after::, ); register_unsigned_benches!(runner, benchmark_primes_less_than_algorithms); register_unsigned_benches!(runner, benchmark_primes_less_than_algorithms_2); register_unsigned_benches!(runner, benchmark_primes_less_than_or_equal_to_algorithms); register_unsigned_benches!(runner, benchmark_primes_less_than_or_equal_to_algorithms_2); register_bench!(runner, benchmark_prime_indicator_sequence_less_than); register_bench!( runner, benchmark_prime_indicator_sequence_less_than_or_equal_to ); } fn demo_primes_less_than(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5::().get(gm, config).take(limit) { println!( "primes_less_than({}) = {:?}", n, T::primes_less_than(&n).collect_vec() ); } } fn demo_primes_less_than_or_equal_to( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_5::().get(gm, config).take(limit) { println!( "primes_less_than_or_equal_to({}) = {:?}", n, T::primes_less_than_or_equal_to(&n).collect_vec() ); } } fn demo_primes(_gm: GenMode, _config: &GenConfig, limit: usize) { for p in T::primes().take(limit) { println!("{p}"); } } fn demo_prime_indicator_sequence_less_than(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!( "prime_indicator_sequence_less_than({}) = {:?}", n, prime_indicator_sequence_less_than(n).collect_vec() ); } } fn demo_prime_indicator_sequence_less_than_or_equal_to( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!( "prime_indicator_sequence_less_than_or_equal_to({}) = {:?}", n, prime_indicator_sequence_less_than_or_equal_to(n).collect_vec() ); } } fn demo_prime_indicator_sequence(_gm: GenMode, _config: &GenConfig, limit: usize) { for b in prime_indicator_sequence().take(limit) { println!("{b}"); } } fn demo_primes_less_than_jump_after( gm: GenMode, config: &GenConfig, limit: usize, ) { let mut config = config.clone(); config.insert("mean_small_n", 10000); for (size, jump, skip) in unsigned_triple_gen_var_24::() .get(gm, &config) .take(limit) { let mut ps = T::primes_less_than(&size); for _ in 0..skip { ps.next(); } if ps.jump_after(jump) { let next = ps.next().unwrap(); println!( "Created iterator less than {size}, skipped {skip}, jumped after {jump}, \ then returned {next}" ); } else { println!( "Created iterator less than {size}, skipped {skip}, and jumped after {jump}, \ which was too far" ); } } } fn demo_primes_jump_after(gm: GenMode, config: &GenConfig, limit: usize) { let mut config = config.clone(); config.insert("mean_small_n", 10000); for (jump, skip) in unsigned_pair_gen_var_28::() .get(gm, &config) .take(limit) { let mut ps = T::primes(); for _ in 0..skip { ps.next(); } if ps.jump_after(jump) { let next = ps.next().unwrap(); println!("Created iterator, skipped {skip}, jumped after {jump}, then returned {next}"); } else { println!( "Created iterator, skipped {skip}, and jumped after {jump}, which was too far" ); } } } fn benchmark_primes_less_than_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}::primes_less_than({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::primes_less_than(&n).count())), ("using primes", &mut |n| { no_out!(T::primes().take_while(|&p| p < n).count()); }), ("naive", &mut |n| { no_out!(primes_naive::().take_while(|&p| p < n).count()); }), ], ); } fn benchmark_primes_less_than_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}::primes_less_than(&{})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(T::primes_less_than(&n).count())), ("using primes", &mut |n| { no_out!(T::primes().take_while(|&p| p < n).count()); }), ], ); } fn benchmark_primes_less_than_or_equal_to_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}::primes_less_than_or_equal_to(&{})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| { no_out!(T::primes_less_than_or_equal_to(&n).count()); }), ("using primes", &mut |n| { no_out!(T::primes().take_while(|&p| p <= n).count()); }), ("naive", &mut |n| { no_out!(primes_naive::().take_while(|&p| p <= n).count()); }), ], ); } fn benchmark_primes_less_than_or_equal_to_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where usize: TryFrom, { run_benchmark( &format!("{}::primes_less_than_or_equal_to({})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| { no_out!(T::primes_less_than_or_equal_to(&n).count()); }), ("using primes", &mut |n| { no_out!(T::primes().take_while(|&p| p <= n).count()); }), ], ); } fn benchmark_prime_indicator_sequence_less_than( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "prime_indicator_sequence_less_than(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| { no_out!(prime_indicator_sequence_less_than(n).count()); })], ); } fn benchmark_prime_indicator_sequence_less_than_or_equal_to( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "prime_indicator_sequence_less_than_or_equal_to(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| { no_out!(prime_indicator_sequence_less_than_or_equal_to(n).count()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/factorization/primitive_root_prime.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::traits::PrimitiveRootPrime; use malachite_base::test_util::bench::bucketers::primitive_int_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_29; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_u8_primitive_root_prime); register_demo!(runner, demo_u16_primitive_root_prime); register_demo!(runner, demo_u32_primitive_root_prime); register_demo!(runner, demo_u64_primitive_root_prime); register_demo!(runner, demo_usize_primitive_root_prime); register_bench!(runner, benchmark_u8_primitive_root_prime); register_bench!(runner, benchmark_u16_primitive_root_prime); register_bench!(runner, benchmark_u32_primitive_root_prime); register_bench!(runner, benchmark_u64_primitive_root_prime); register_bench!(runner, benchmark_usize_primitive_root_prime); } fn demo_u8_primitive_root_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_29::().get(gm, config).take(limit) { println!("primitive_root_prime({}) = {}", u, u.primitive_root_prime()); } } fn demo_u16_primitive_root_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_29::().get(gm, config).take(limit) { println!("primitive_root_prime({}) = {}", u, u.primitive_root_prime()); } } fn demo_u32_primitive_root_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_29::().get(gm, config).take(limit) { println!("primitive_root_prime({}) = {}", u, u.primitive_root_prime()); } } fn demo_u64_primitive_root_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_29::().get(gm, config).take(limit) { println!("primitive_root_prime({}) = {}", u, u.primitive_root_prime()); } } fn demo_usize_primitive_root_prime(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen_var_29::().get(gm, config).take(limit) { println!("primitive_root_prime({}) = {}", u, u.primitive_root_prime()); } } fn benchmark_u8_primitive_root_prime( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u8.primitive_root_prime()", BenchmarkType::Single, unsigned_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.primitive_root_prime()))], ); } fn benchmark_u16_primitive_root_prime( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u16.primitive_root_prime()", BenchmarkType::Single, unsigned_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.primitive_root_prime()))], ); } fn benchmark_u32_primitive_root_prime( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32.primitive_root_prime()", BenchmarkType::Single, unsigned_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.primitive_root_prime()))], ); } fn benchmark_u64_primitive_root_prime( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64.primitive_root_prime()", BenchmarkType::Single, unsigned_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.primitive_root_prime()))], ); } fn benchmark_usize_primitive_root_prime( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "usize.primitive_root_prime()", BenchmarkType::Single, unsigned_gen_var_29::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |u| no_out!(u.primitive_root_prime()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/abs_negative_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_abs_negative_zero); register_primitive_float_demos!(runner, demo_abs_negative_zero_assign); register_primitive_float_benches!(runner, benchmark_abs_negative_zero); register_primitive_float_benches!(runner, benchmark_abs_negative_zero_assign); } fn demo_abs_negative_zero(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "abs_negative_zero({}) = {}", NiceFloat(x), NiceFloat(x.abs_negative_zero()) ); } } fn demo_abs_negative_zero_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in primitive_float_gen::().get(gm, config).take(limit) { let old_x = x; x.abs_negative_zero_assign(); println!( "x := {}; x.abs_negative_zero_assign(); x = {}", NiceFloat(old_x), NiceFloat(x) ); } } fn benchmark_abs_negative_zero( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.abs_negative_zero()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.abs_negative_zero()))], ); } fn benchmark_abs_negative_zero_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.abs_negative_zero_assign()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |mut x| { no_out!(x.abs_negative_zero_assign()); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/from_ordered_representation.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::unsigned_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_13; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_from_ordered_representation); register_primitive_float_benches!(runner, benchmark_from_ordered_representation); } fn demo_from_ordered_representation( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in unsigned_gen_var_13::().get(gm, config).take(limit) { println!( "from_ordered_representation({}) = {}", x, NiceFloat(T::from_ordered_representation(x)) ); } } fn benchmark_from_ordered_representation( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_ordered_representation(u64)", T::NAME), BenchmarkType::Single, unsigned_gen_var_13::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| { no_out!(T::from_ordered_representation(x)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/is_negative_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_is_negative_zero); register_primitive_float_benches!(runner, benchmark_is_negative_zero); } fn demo_is_negative_zero(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen::().get(gm, config).take(limit) { if x.is_negative_zero() { println!("{} is negative zero", NiceFloat(x)); } else { println!("{} is not negative zero", NiceFloat(x)); } } } fn benchmark_is_negative_zero( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.is_negative_zero()", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.is_negative_zero()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/max_precision_for_sci_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::test_util::bench::bucketers::signed_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::signed_gen_var_11; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_max_precision_for_sci_exponent); register_primitive_float_benches!(runner, benchmark_max_precision_for_sci_exponent); } fn demo_max_precision_for_sci_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) { for exp in signed_gen_var_11::().get(gm, config).take(limit) { println!( "{}.max_precision_for_sci_exponent() = {}", exp, T::max_precision_for_sci_exponent(exp) ); } } fn benchmark_max_precision_for_sci_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::max_precision_for_sci_exponent(i64)", T::NAME), BenchmarkType::Single, signed_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |exp| { no_out!(T::max_precision_for_sci_exponent(exp)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs_negative_zero::register(runner); from_ordered_representation::register(runner); is_negative_zero::register(runner); max_precision_for_sci_exponent::register(runner); next_higher::register(runner); next_lower::register(runner); precision::register(runner); to_ordered_representation::register(runner); } mod abs_negative_zero; mod from_ordered_representation; mod is_negative_zero; mod max_precision_for_sci_exponent; mod next_higher; mod next_lower; mod precision; mod to_ordered_representation; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/next_higher.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen_var_9; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_next_higher); register_primitive_float_benches!(runner, benchmark_next_higher); } fn demo_next_higher(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen_var_9::().get(gm, config).take(limit) { println!( "next_higher({}) = {}", NiceFloat(x), NiceFloat(x.next_higher()) ); } } fn benchmark_next_higher( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.next_higher()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_9::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.next_higher()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/next_lower.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen_var_10; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_next_lower); register_primitive_float_benches!(runner, benchmark_next_lower); } fn demo_next_lower(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen_var_10::() .get(gm, config) .take(limit) { println!( "next_lower({}) = {}", NiceFloat(x), NiceFloat(x.next_lower()) ); } } fn benchmark_next_lower( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.next_lower()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.next_lower()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/precision.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen_var_12; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_precision); register_primitive_float_benches!(runner, benchmark_precision); } fn demo_precision(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen_var_12::() .get(gm, config) .take(limit) { println!("({}).precision() = {}", NiceFloat(x), x.precision()); } } fn benchmark_precision( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.precision()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.precision()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/basic/to_ordered_representation.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen_var_11; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_to_ordered_representation); register_primitive_float_benches!(runner, benchmark_to_ordered_representation); } fn demo_to_ordered_representation( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in primitive_float_gen_var_11::() .get(gm, config) .take(limit) { println!( "to_ordered_representation({}) = {}", NiceFloat(x), x.to_ordered_representation() ); } } fn benchmark_to_ordered_representation( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_ordered_representation()", T::NAME), BenchmarkType::Single, primitive_float_gen_var_11::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(x.to_ordered_representation()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { basic::register(runner); nice_float::register(runner); } mod basic; mod nice_float; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_max_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_base::test_util::runner::Runner; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_cmp); register_primitive_float_benches!(runner, benchmark_nice_float_cmp_algorithms); } fn demo_nice_float_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { let x = NiceFloat(x); let y = NiceFloat(y); match x.cmp(&y) { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } #[allow(unused_must_use)] fn benchmark_nice_float_cmp_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat<{}>.cmp(&NiceFloat<{}>)", T::NAME, T::NAME), BenchmarkType::Algorithms, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("f", "g"), &mut [ ("Malachite", &mut |(x, y)| { no_out!(NiceFloat(x).cmp(&NiceFloat(y))); }), ("Rust default", &mut |(x, y)| no_out!(x.partial_cmp(&y))), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::OrdAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_max_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_base::test_util::runner::Runner; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_cmp_abs); register_primitive_float_benches!(runner, benchmark_nice_float_cmp_abs_algorithms); } fn demo_nice_float_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { let x = NiceFloat(x); let y = NiceFloat(y); match x.cmp_abs(&y) { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } #[allow(unused_must_use)] fn benchmark_nice_float_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat<{}>.cmp_abs(&NiceFloat<{}>)", T::NAME, T::NAME), BenchmarkType::Algorithms, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("f", "g"), &mut [ ("Malachite", &mut |(x, y)| { no_out!(NiceFloat(x).cmp_abs(&NiceFloat(y))); }), ("without NiceFloat", &mut |(x, y)| { no_out!(x.partial_cmp_abs(&y)); }), ("using abs", &mut |(x, y)| { no_out!(NiceFloat(x.abs()).cmp(&NiceFloat(y.abs()))); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/eq.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_max_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_eq); register_primitive_float_benches!(runner, benchmark_nice_float_eq_algorithms); } fn demo_nice_float_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { let x = NiceFloat(x); let y = NiceFloat(y); if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_nice_float_eq_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat<{}> == NiceFloat<{}>", T::NAME, T::NAME), BenchmarkType::Algorithms, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("f", "g"), &mut [ ("Malachite", &mut |(x, y)| { no_out!(NiceFloat(x) == NiceFloat(y)); }), ("Rust default", &mut |(x, y)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_max_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_eq_abs); register_primitive_float_benches!(runner, benchmark_nice_float_eq_abs_algorithms); } fn demo_nice_float_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { let x = NiceFloat(x); let y = NiceFloat(y); if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_nice_float_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat<{}>.eq_abs(&NiceFloat<{}>)", T::NAME, T::NAME), BenchmarkType::Algorithms, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("f", "g"), &mut [ ("Malachite", &mut |(x, y)| { no_out!(NiceFloat(x).eq_abs(&NiceFloat(y))); }), ("without NiceFloat", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(NiceFloat(x.abs()) == NiceFloat(y.abs())); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/from_str.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_10}; use malachite_base::test_util::runner::Runner; use std::fmt::Debug; use std::str::FromStr; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_from_str); register_primitive_float_demos!(runner, demo_nice_float_from_str_targeted); register_primitive_float_benches!(runner, benchmark_nice_float_from_str); } fn demo_nice_float_from_str(gm: GenMode, config: &GenConfig, limit: usize) where ::Err: Debug, { for s in string_gen().get(gm, config).take(limit) { println!( "NiceFloat::from_str({:?}) = {:?}", s, NiceFloat::::from_str(&s) ); } } fn demo_nice_float_from_str_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where ::Err: Debug, { for s in string_gen_var_10().get(gm, config).take(limit) { println!( "NiceFloat::from_str({:?}) = {:?}", s, NiceFloat::::from_str(&s) ); } } #[allow(unused_must_use)] fn benchmark_nice_float_from_str( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat::<{}>::from_str(&str)", T::NAME), BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(NiceFloat::::from_str(&s)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/hash.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_hash); register_primitive_float_benches!(runner, benchmark_nice_float_hash); } fn demo_nice_float_hash(gm: GenMode, config: &GenConfig, limit: usize) { for x in primitive_float_gen::().get(gm, config).take(limit) { let x = NiceFloat(x); println!("hash({}) = {}", x, hash(&x)); } } fn benchmark_nice_float_hash( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("hash(&NiceFloat<{}>())", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |x| no_out!(hash(&NiceFloat(x))))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); cmp_abs::register(runner); eq::register(runner); eq_abs::register(runner); from_str::register(runner); hash::register(runner); to_string::register(runner); } mod cmp; mod cmp_abs; mod eq; mod eq_abs; mod from_str; mod hash; mod to_string; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/float/nice_float/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_nice_float_to_string); register_primitive_float_benches!(runner, benchmark_nice_float_to_string_algorithms); } fn demo_nice_float_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for f in primitive_float_gen::().get(gm, config).take(limit) { println!("{}", NiceFloat(f)); } } fn benchmark_nice_float_to_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("NiceFloat::<{}>.to_string()", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("Malachite", &mut |f| no_out!(NiceFloat(f).to_string())), ("Rust default", &mut |f| no_out!(f.to_string())), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_bool_triple_gen_var_1, unsigned_unsigned_bool_triple_gen_var_1, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_assign_bit_unsigned); register_signed_demos!(runner, demo_assign_bit_signed); register_unsigned_benches!(runner, benchmark_assign_bit_unsigned); register_signed_benches!(runner, benchmark_assign_bit_signed); } fn demo_assign_bit_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index, bit) in unsigned_unsigned_bool_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n; n.assign_bit(index, bit); println!("x := {n_old}; x.assign_bit({index}, {bit}); x = {n}"); } } fn demo_assign_bit_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index, bit) in signed_unsigned_bool_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n; n.assign_bit(index, bit); println!("x := {n_old}; x.assign_bit({index}, {bit}); x = {n}"); } } fn benchmark_assign_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.assign_bit(u64, bool)", T::NAME), BenchmarkType::Single, unsigned_unsigned_bool_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index, bit)| { n.assign_bit(index, bit); })], ); } fn benchmark_assign_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.assign_bit(u64, bool)", T::NAME), BenchmarkType::Single, signed_unsigned_bool_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index, bit)| { n.assign_bit(index, bit); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_4, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_clear_bit_unsigned); register_signed_demos!(runner, demo_clear_bit_signed); register_unsigned_benches!(runner, benchmark_clear_bit_unsigned); register_signed_benches!(runner, benchmark_clear_bit_signed); } fn demo_clear_bit_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n; n.clear_bit(index); println!("x := {n_old}; x.clear_bit({index}); x = {n}"); } } fn demo_clear_bit_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in signed_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n; n.clear_bit(index); println!("x := {n_old}; x.clear_bit({index}); x = {n}"); } } fn benchmark_clear_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.clear_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.clear_bit(index))], ); } fn benchmark_clear_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.clear_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.clear_bit(index))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_2, unsigned_pair_gen_var_3, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_flip_bit_unsigned); register_signed_demos!(runner, demo_flip_bit_signed); register_unsigned_benches!(runner, benchmark_flip_bit_unsigned); register_signed_benches!(runner, benchmark_flip_bit_signed); } fn demo_flip_bit_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in unsigned_pair_gen_var_3::().get(gm, config).take(limit) { let n_old = n; n.flip_bit(index); println!("x := {n_old}; x.flip_bit({index}); x = {n}"); } } fn demo_flip_bit_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in signed_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n; n.flip_bit(index); println!("x := {n_old}; x.flip_bit({index}); x = {n}"); } } fn benchmark_flip_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.flip_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.flip_bit(index))], ); } fn benchmark_flip_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.flip_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.flip_bit(index))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_get_bit_unsigned); register_signed_demos!(runner, demo_get_bit_signed); register_unsigned_benches!(runner, benchmark_get_bit_unsigned); register_signed_benches!(runner, benchmark_get_bit_signed); } fn demo_get_bit_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (n, index) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("get_bit({}, {}) = {}", n, index, n.get_bit(index)); } } fn demo_get_bit_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, index) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("get_bit({}, {}) = {}", n, index, n.get_bit(index)); } } fn benchmark_get_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.get_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(n, index)| no_out!(n.get_bit(index)))], ); } fn benchmark_get_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.get_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(n, index)| no_out!(n.get_bit(index)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { assign_bit::register(runner); clear_bit::register(runner); flip_bit::register(runner); get_bit::register(runner); set_bit::register(runner); } mod assign_bit; mod clear_bit; mod flip_bit; mod get_bit; mod set_bit; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_access/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_3, unsigned_pair_gen_var_3, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_set_bit_unsigned); register_signed_demos!(runner, demo_set_bit_signed); register_unsigned_benches!(runner, benchmark_set_bit_unsigned); register_signed_benches!(runner, benchmark_set_bit_signed); } fn demo_set_bit_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in unsigned_pair_gen_var_3::().get(gm, config).take(limit) { let n_old = n; n.set_bit(index); println!("x := {n_old}; x.set_bit({index}); x = {n}"); } } fn demo_set_bit_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in signed_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n; n.set_bit(index); println!("x := {n_old}; x.set_bit({index}); x = {n}"); } } fn benchmark_set_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.set_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.set_bit(index))], ); } fn benchmark_set_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.set_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.set_bit(index))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_block_access/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::assign_bits_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, unsigned_quadruple_gen_var_1, }; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_assign_bits_unsigned); register_signed_unsigned_match_demos!(runner, demo_assign_bits_signed); register_unsigned_benches!(runner, benchmark_assign_bits_algorithms_unsigned); register_signed_unsigned_match_benches!(runner, benchmark_assign_bits_algorithms_signed); } fn demo_assign_bits_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where T::Bits: PrimitiveUnsigned, { for (mut n, start, end, bits) in unsigned_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; n.assign_bits(start, end, &bits); println!("n := {old_n}; n.assign_bits({start}, {end}, &{bits}); n = {n}"); } } fn demo_assign_bits_signed< T: BitBlockAccess + PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, start, end, bits) in signed_unsigned_unsigned_unsigned_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let old_n = n; n.assign_bits(start, end, &bits); println!("n := {old_n}; n.assign_bits({start}, {end}, &{bits}); n = {n}"); } } fn benchmark_assign_bits_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where T::Bits: PrimitiveUnsigned, { run_benchmark( &format!("{}.assign_bits(u64, u64, {})", T::NAME, T::NAME), BenchmarkType::Algorithms, unsigned_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &assign_bits_bucketer(), &mut [ ("default", &mut |(mut n, start, end, bits)| { no_out!(n.assign_bits(start, end, &bits)); }), ("naive", &mut |(mut n, start, end, bits)| { no_out!(assign_bits_naive::(&mut n, start, end, &bits)); }), ], ); } fn benchmark_assign_bits_algorithms_signed< T: BitBlockAccess + PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.assign_bits(u64, u64, {})", T::NAME, U::NAME), BenchmarkType::Algorithms, signed_unsigned_unsigned_unsigned_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &assign_bits_bucketer(), &mut [ ("default", &mut |(mut n, start, end, bits)| { no_out!(n.assign_bits(start, end, &bits)); }), ("naive", &mut |(mut n, start, end, bits)| { no_out!(assign_bits_naive::(&mut n, start, end, &bits)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_block_access/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::get_bits_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_unsigned_triple_gen_var_2, unsigned_triple_gen_var_5, }; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_get_bits_unsigned); register_unsigned_signed_match_demos!(runner, demo_get_bits_signed); register_unsigned_benches!(runner, benchmark_get_bits_algorithms_unsigned); register_unsigned_signed_match_benches!(runner, benchmark_get_bits_algorithms_signed); } fn demo_get_bits_unsigned + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, start, end) in unsigned_triple_gen_var_5::() .get(gm, config) .take(limit) { println!( "{}.get_bits({}, {}) = {}", n, start, end, n.get_bits(start, end) ); } } fn demo_get_bits_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where S::Bits: PrimitiveUnsigned, { for (n, start, end) in signed_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "({}).get_bits({}, {}) = {}", n, start, end, n.get_bits(start, end) ); } } fn benchmark_get_bits_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.get_bits(u64, u64)", T::NAME), BenchmarkType::Algorithms, unsigned_triple_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &get_bits_bucketer(), &mut [ ("default", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("naive", &mut |(n, start, end)| { no_out!(get_bits_naive::(&n, start, end)); }), ], ); } fn benchmark_get_bits_algorithms_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.get_bits(u64, u64)", S::NAME), BenchmarkType::Algorithms, signed_unsigned_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &get_bits_bucketer(), &mut [ ("default", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("naive", &mut |(n, start, end)| { no_out!(get_bits_naive::(&n, start, end)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_block_access/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { assign_bits::register(runner); get_bits::register(runner); } mod assign_bits; mod get_bits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_convertible/from_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ bool_vec_gen_var_1, bool_vec_gen_var_2, bool_vec_gen_var_3, bool_vec_gen_var_4, }; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_asc_signed_naive, from_bits_asc_unsigned_naive, from_bits_desc_alt, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_from_bits_asc_unsigned); register_signed_demos!(runner, demo_from_bits_asc_signed); register_unsigned_demos!(runner, demo_from_bits_desc_unsigned); register_signed_demos!(runner, demo_from_bits_desc_signed); register_unsigned_benches!(runner, benchmark_from_bits_asc_algorithms_unsigned); register_signed_benches!(runner, benchmark_from_bits_asc_algorithms_signed); register_unsigned_benches!(runner, benchmark_from_bits_desc_algorithms_unsigned); register_signed_benches!(runner, benchmark_from_bits_desc_algorithms_signed); } fn demo_from_bits_asc_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for bs in bool_vec_gen_var_1::().get(gm, config).take(limit) { println!( "{}::from_bits_asc({:?}) = {}", T::NAME, bs, T::from_bits_asc(bs.iter().copied()) ); } } fn demo_from_bits_asc_signed(gm: GenMode, config: &GenConfig, limit: usize) { for bs in bool_vec_gen_var_2::().get(gm, config).take(limit) { println!( "{}::from_bits_asc({:?}) = {}", T::NAME, bs, T::from_bits_asc(bs.iter().copied()) ); } } fn demo_from_bits_desc_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for bs in bool_vec_gen_var_3::().get(gm, config).take(limit) { println!( "{}::from_bits_desc({:?}) = {}", T::NAME, bs, T::from_bits_desc(bs.iter().copied()) ); } } fn demo_from_bits_desc_signed(gm: GenMode, config: &GenConfig, limit: usize) { for bs in bool_vec_gen_var_4::().get(gm, config).take(limit) { println!( "{}::from_bits_desc({:?}) = {}", T::NAME, bs, T::from_bits_desc(bs.iter().copied()) ); } } fn benchmark_from_bits_asc_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_bits_asc>(I)", T::NAME), BenchmarkType::Algorithms, bool_vec_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref bs| { no_out!(T::from_bits_asc(bs.iter().copied())); }), ("alt", &mut |ref bs| { no_out!(from_bits_asc_alt::(bs.iter().copied())); }), ("naive", &mut |ref bs| { no_out!(from_bits_asc_unsigned_naive::(bs.iter().copied())); }), ], ); } fn benchmark_from_bits_asc_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_bits_asc>(I)", T::NAME), BenchmarkType::Algorithms, bool_vec_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref bs| { no_out!(T::from_bits_asc(bs.iter().copied())); }), ("alt", &mut |ref bs| { no_out!(from_bits_asc_alt::(bs.iter().copied())); }), ("naive", &mut |ref bs| { no_out!(from_bits_asc_signed_naive::(bs.iter().copied())); }), ], ); } fn benchmark_from_bits_desc_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_bits_desc>(I)", T::NAME), BenchmarkType::Algorithms, bool_vec_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref bs| { no_out!(T::from_bits_desc(bs.iter().copied())); }), ("alt", &mut |ref bs| { no_out!(from_bits_desc_alt::(bs.iter().copied())); }), ], ); } fn benchmark_from_bits_desc_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::from_bits_desc>(I)", T::NAME), BenchmarkType::Algorithms, bool_vec_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref bs| { no_out!(T::from_bits_desc(bs.iter().copied())); }), ("alt", &mut |ref bs| { no_out!(from_bits_desc_alt::(bs.iter().copied())); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_convertible/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_bits::register(runner); to_bits::register(runner); } mod from_bits; mod to_bits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_convertible/to_bits.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::num::logic::bit_convertible::{ to_bits_asc_alt, to_bits_asc_signed_naive, to_bits_asc_unsigned_naive, to_bits_desc_alt, to_bits_desc_signed_naive, to_bits_desc_unsigned_naive, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_to_bits_asc_unsigned); register_signed_demos!(runner, demo_to_bits_asc_signed); register_unsigned_demos!(runner, demo_to_bits_desc_unsigned); register_signed_demos!(runner, demo_to_bits_desc_signed); register_unsigned_benches!(runner, benchmark_to_bits_asc_algorithms_unsigned); register_signed_benches!(runner, benchmark_to_bits_asc_algorithms_signed); register_unsigned_benches!(runner, benchmark_to_bits_asc_evaluation_strategy_unsigned); register_signed_benches!(runner, benchmark_to_bits_asc_evaluation_strategy_signed); register_unsigned_benches!(runner, benchmark_to_bits_desc_algorithms_unsigned); register_signed_benches!(runner, benchmark_to_bits_desc_algorithms_signed); register_unsigned_benches!(runner, benchmark_to_bits_desc_evaluation_strategy_unsigned); register_signed_benches!(runner, benchmark_to_bits_desc_evaluation_strategy_signed); } fn demo_to_bits_asc_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.to_bits_asc() = {:?}", u, u.to_bits_asc()); } } fn demo_to_bits_asc_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("{}.to_bits_asc() = {:?}", i, i.to_bits_asc()); } } fn demo_to_bits_desc_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("{}.to_bits_desc() = {:?}", u, u.to_bits_desc()); } } fn demo_to_bits_desc_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("{}.to_bits_desc() = {:?}", i, i.to_bits_desc()); } } fn benchmark_to_bits_asc_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_asc()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(u.to_bits_asc())), ("alt", &mut |u| no_out!(to_bits_asc_alt(&u))), ("naive", &mut |u| no_out!(to_bits_asc_unsigned_naive(u))), ], ); } fn benchmark_to_bits_asc_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_asc()", T::NAME), BenchmarkType::Algorithms, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(i.to_bits_asc())), ("alt", &mut |i| no_out!(to_bits_asc_alt(&i))), ("naive", &mut |i| no_out!(to_bits_asc_signed_naive(i))), ], ); } #[allow(unused_must_use)] fn benchmark_to_bits_asc_evaluation_strategy_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_asc()", T::NAME), BenchmarkType::EvaluationStrategy, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ (&format!("{}.to_bits_asc()", T::NAME), &mut |n| { no_out!(n.to_bits_asc()); }), (&format!("{}.bits().collect_vec()", T::NAME), &mut |n| { no_out!(n.bits().collect_vec()); }), ], ); } #[allow(unused_must_use)] fn benchmark_to_bits_asc_evaluation_strategy_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_asc()", T::NAME), BenchmarkType::EvaluationStrategy, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ (&format!("{}.to_bits_asc()", T::NAME), &mut |n| { no_out!(n.to_bits_asc()); }), (&format!("{}.bits().collect_vec()", T::NAME), &mut |n| { no_out!(n.bits().collect_vec()); }), ], ); } fn benchmark_to_bits_desc_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_desc()", T::NAME), BenchmarkType::Algorithms, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(u.to_bits_desc())), ("alt", &mut |u| no_out!(to_bits_desc_alt(&u))), ("naive", &mut |u| no_out!(to_bits_desc_unsigned_naive(u))), ], ); } fn benchmark_to_bits_desc_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_desc()", T::NAME), BenchmarkType::Algorithms, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(i.to_bits_desc())), ("alt", &mut |i| no_out!(to_bits_desc_alt(&i))), ("naive", &mut |i| no_out!(to_bits_desc_signed_naive(i))), ], ); } #[allow(unused_must_use)] fn benchmark_to_bits_desc_evaluation_strategy_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_desc()", T::NAME), BenchmarkType::EvaluationStrategy, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ (&format!("{}.to_bits_desc()", T::NAME), &mut |n| { no_out!(n.to_bits_desc()); }), ( &format!("{}.bits().rev().collect_vec()", T::NAME), &mut |n| no_out!(n.bits().rev().collect_vec()), ), ], ); } #[allow(unused_must_use)] fn benchmark_to_bits_desc_evaluation_strategy_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.to_bits_desc()", T::NAME), BenchmarkType::EvaluationStrategy, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ (&format!("{}.to_bits_desc()", T::NAME), &mut |n| { no_out!(n.to_bits_desc()); }), ( &format!("{}.bits().rev().collect_vec()", T::NAME), &mut |n| no_out!(n.bits().rev().collect_vec()), ), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_iterable.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{pair_1_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; use std::ops::Index; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_bits_unsigned); register_signed_demos!(runner, demo_bits_signed); register_unsigned_demos!(runner, demo_bits_rev_unsigned); register_signed_demos!(runner, demo_bits_rev_signed); register_unsigned_demos!(runner, demo_bits_size_hint_unsigned); register_signed_demos!(runner, demo_bits_index_signed); register_unsigned_benches!(runner, benchmark_bits_size_hint_unsigned); register_unsigned_benches!(runner, benchmark_bits_get_algorithms_unsigned); register_signed_benches!(runner, benchmark_bits_get_algorithms_signed); } fn demo_bits_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("bits({}) = {:?}", u, u.bits().collect_vec()); } } fn demo_bits_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("bits({}) = {:?}", i, i.bits().collect_vec()); } } fn demo_bits_rev_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("bits({}).rev() = {:?}", u, u.bits().rev().collect_vec()); } } fn demo_bits_rev_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen::().get(gm, config).take(limit) { println!("bits({}).rev() = {:?}", i, i.bits().rev().collect_vec()); } } fn demo_bits_size_hint_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for u in unsigned_gen::().get(gm, config).take(limit) { println!("bits({}).size_hint() = {:?}", u, u.bits().size_hint()); } } fn demo_bits_index_signed(gm: GenMode, config: &GenConfig, limit: usize) where T::BitIterator: Index, { for (n, i) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("bits({})[{}] = {:?}", n, i, n.bits()[i]); } } fn benchmark_bits_size_hint_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.bits().size_hint()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [(&format!("{}.bits().size_hint()", T::NAME), &mut |n| { no_out!(n.bits().size_hint()); })], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_bits_get_algorithms_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where T::BitIterator: Index, { run_benchmark( &format!("{}.bits()[u64]", T::NAME), BenchmarkType::Algorithms, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [ (&format!("{}.bits()[u]", T::NAME), &mut |(n, u)| { no_out!(n.bits()[u]); }), (&format!("{}.to_bits_asc()[u]", T::NAME), &mut |(n, u)| { let bits = n.to_bits_asc(); let u = usize::exact_from(u); if u >= bits.len() { n < T::ZERO } else { bits[u] }; }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_bits_get_algorithms_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where T::BitIterator: Index, { run_benchmark( &format!("{}.bits()[u64]", T::NAME), BenchmarkType::Algorithms, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [ (&format!("{}.bits()[u]", T::NAME), &mut |(n, u)| { no_out!(n.bits()[u]); }), (&format!("{}.to_bits_asc()[u]", T::NAME), &mut |(n, u)| { let bits = n.to_bits_asc(); let u = usize::exact_from(u); if u >= bits.len() { n < T::ZERO } else { bits[u] }; }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_scan/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_index_of_next_false_bit_unsigned); register_signed_demos!(runner, demo_index_of_next_false_bit_signed); register_unsigned_benches!(runner, benchmark_index_of_next_false_bit_unsigned); register_signed_benches!(runner, benchmark_index_of_next_false_bit_signed); } fn demo_index_of_next_false_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, start) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}.index_of_next_false_bit({}) = {:?}", n, start, n.index_of_next_false_bit(start) ); } } fn demo_index_of_next_false_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, start) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.index_of_next_false_bit({}) = {:?}", n, start, n.index_of_next_false_bit(start) ); } } fn benchmark_index_of_next_false_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.index_of_next_false_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("start"), &mut [("Malachite", &mut |(n, start)| { no_out!(n.index_of_next_false_bit(start)); })], ); } fn benchmark_index_of_next_false_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.index_of_next_false_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(n, start)| { no_out!(n.index_of_next_false_bit(start)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_scan/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_index_of_next_true_bit_unsigned); register_signed_demos!(runner, demo_index_of_next_true_bit_signed); register_unsigned_benches!(runner, benchmark_index_of_next_true_bit_unsigned); register_signed_benches!(runner, benchmark_index_of_next_true_bit_signed); } fn demo_index_of_next_true_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, start) in unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "{}.index_of_next_true_bit({}) = {:?}", n, start, n.index_of_next_true_bit(start) ); } } fn demo_index_of_next_true_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, start) in signed_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.index_of_next_true_bit({}) = {:?}", n, start, n.index_of_next_true_bit(start) ); } } fn benchmark_index_of_next_true_bit_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.index_of_next_true_bit(u64)", T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("start"), &mut [("Malachite", &mut |(n, start)| { no_out!(n.index_of_next_true_bit(start)); })], ); } fn benchmark_index_of_next_true_bit_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.index_of_next_true_bit(u64)", T::NAME), BenchmarkType::Single, signed_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(n, start)| { no_out!(n.index_of_next_true_bit(start)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/bit_scan/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { index_of_next_false_bit::register(runner); index_of_next_true_bit::register(runner); } mod index_of_next_false_bit; mod index_of_next_true_bit; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/get_highest_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_get_highest_bit_unsigned); register_signed_demos!(runner, demo_get_highest_bit_signed); register_unsigned_benches!(runner, benchmark_get_highest_bit_unsigned); register_signed_benches!(runner, benchmark_get_highest_bit_signed); } unsigned_single_arg_demo!(demo_get_highest_bit_unsigned, get_highest_bit); signed_single_arg_demo!(demo_get_highest_bit_signed, get_highest_bit); unsigned_single_arg_bench!(benchmark_get_highest_bit_unsigned, get_highest_bit); signed_single_arg_bench!(benchmark_get_highest_bit_signed, get_highest_bit); ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::pair_max_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_hamming_distance_unsigned); register_signed_demos!(runner, demo_checked_hamming_distance_signed); register_unsigned_benches!(runner, benchmark_hamming_distance_unsigned); register_signed_benches!(runner, benchmark_checked_hamming_distance_signed); } fn demo_hamming_distance_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27::().get(gm, config).take(limit) { println!("{}.hamming_distance({}) = {}", x, y, x.hamming_distance(y)); } } fn demo_checked_hamming_distance_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in signed_pair_gen::().get(gm, config).take(limit) { println!( "({}).checked_hamming_distance({}) = {:?}", x, y, x.checked_hamming_distance(y) ); } } fn benchmark_hamming_distance_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.hamming_distance({})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_27::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.hamming_distance(y)))], ); } fn benchmark_checked_hamming_distance_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.checked_hamming_distance({})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(x.checked_hamming_distance(y)); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::bench::bucketers::primitive_int_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_9; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_demos!(runner, demo_low_mask); register_primitive_int_benches!(runner, benchmark_low_mask); } fn demo_low_mask(gm: GenMode, config: &GenConfig, limit: usize) { for bits in unsigned_gen_var_9::().get(gm, config).take(limit) { println!("{}::low_mask({}) = {}", T::NAME, bits, T::low_mask(bits)); } } fn benchmark_low_mask( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.low_mask(u64)", T::NAME), BenchmarkType::Single, unsigned_gen_var_9::().get(gm, config), gm.name(), limit, file_name, &primitive_int_direct_bucketer(), &mut [("Malachite", &mut |bits| no_out!(T::low_mask(bits)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { bit_access::register(runner); bit_block_access::register(runner); bit_convertible::register(runner); bit_iterable::register(runner); bit_scan::register(runner); get_highest_bit::register(runner); hamming_distance::register(runner); low_mask::register(runner); not_assign::register(runner); significant_bits::register(runner); } mod bit_access; mod bit_block_access; mod bit_convertible; mod bit_iterable; mod bit_scan; mod get_highest_bit; mod hamming_distance; mod low_mask; mod not_assign; mod significant_bits; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/not_assign.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_not_assign_unsigned); register_signed_demos!(runner, demo_not_assign_signed); register_unsigned_benches!(runner, benchmark_not_assign_unsigned); register_signed_benches!(runner, benchmark_not_assign_signed); } fn demo_not_assign_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for mut u in unsigned_gen::().get(gm, config).take(limit) { let old_u = u; u.not_assign(); println!("u := {old_u}; u.not_assign(); u = {u}"); } } fn demo_not_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) { for mut i in signed_gen::().get(gm, config).take(limit) { let old_i = i; i.not_assign(); println!("i := {old_i}; i.not_assign(); i = {i}"); } } fn benchmark_not_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.not_assign()", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |mut u| u.not_assign())], ); } fn benchmark_not_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.not_assign()", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |mut i| i.not_assign())], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_significant_bits_unsigned); register_signed_demos!(runner, demo_significant_bits_signed); register_unsigned_benches!(runner, benchmark_significant_bits_unsigned); register_signed_benches!(runner, benchmark_significant_bits_signed); } unsigned_single_arg_demo!(demo_significant_bits_unsigned, significant_bits); signed_single_arg_demo!(demo_significant_bits_signed, significant_bits); unsigned_single_arg_bench!(benchmark_significant_bits_unsigned, significant_bits); signed_single_arg_bench!(benchmark_significant_bits_signed, significant_bits); ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/num/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); comparison::register(runner); conversion::register(runner); factorization::register(runner); float::register(runner); logic::register(runner); } mod arithmetic; mod comparison; mod conversion; mod factorization; mod float; mod logic; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/access/get.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::pair_1_rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_rational_sequence_unsigned_pair_gen_var_1, unsigned_rational_sequence_unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_get); register_demo!(runner, demo_rational_sequence_index); register_bench!(runner, benchmark_rational_sequence_get); register_bench!(runner, benchmark_rational_sequence_index); } fn demo_rational_sequence_get(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, index) in unsigned_rational_sequence_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("{}.get({}) = {:?}", xs, index, xs.get(index)); } } fn demo_rational_sequence_index(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, index) in unsigned_rational_sequence_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("{}[{}] = {}", xs, index, xs[index]); } } fn benchmark_rational_sequence_get(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "RationalSequence.get(usize)", BenchmarkType::Single, unsigned_rational_sequence_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, index)| no_out!(xs.get(index)))], ); } #[allow(clippy::no_effect)] fn benchmark_rational_sequence_index( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence[usize]", BenchmarkType::Single, unsigned_rational_sequence_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, index)| no_out!(xs[index]))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/access/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { get::register(runner); mutate::register(runner); } mod get; mod mutate; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/access/mutate.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::quadruple_1_rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::large_type_gen_var_22; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_mutate); register_bench!(runner, benchmark_rational_sequence_mutate); } fn demo_rational_sequence_mutate(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index, y, z) in large_type_gen_var_22::().get(gm, config).take(limit) { let xs_old = xs.clone(); let out = xs.mutate(index, |x| { *x = y; z }); println!("xs := {xs_old}; xs.mutate({index}, |x| {{ *x = {y}; {z} }}) = {out}; xs = {xs}"); } } fn benchmark_rational_sequence_mutate( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.mutate(usize, FnOnce(&mut T) -> U)", BenchmarkType::Single, large_type_gen_var_22::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, index, y, z)| { no_out!(xs.mutate(index, |x| { *x = y; z })); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/component_len.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_component_len); register_bench!(runner, benchmark_rational_sequence_component_len); } fn demo_rational_sequence_component_len(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("component_len({}) = {}", xs, xs.component_len()); } } fn benchmark_rational_sequence_component_len( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.component_len()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.component_len()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/is_empty.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_is_empty); register_bench!(runner, benchmark_rational_sequence_is_empty); } fn demo_rational_sequence_is_empty(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { if xs.is_empty() { println!("{xs} is empty"); } else { println!("{xs} is not empty"); } } } fn benchmark_rational_sequence_is_empty( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.is_empty()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.is_empty()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/is_finite.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_is_finite); register_bench!(runner, benchmark_rational_sequence_is_finite); } fn demo_rational_sequence_is_finite(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { if xs.is_finite() { println!("{xs} is finite"); } else { println!("{xs} is not finite"); } } } fn benchmark_rational_sequence_is_finite( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.is_finite()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.is_finite()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/iter.rs ================================================ // Copyright © 2026 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::prefix_to_string; use malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_iter); register_bench!(runner, benchmark_rational_sequence_iter); } fn demo_rational_sequence_iter(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("{} = {}", xs, prefix_to_string(xs.iter(), 20)); } } fn benchmark_rational_sequence_iter( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.iter()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [( "RationalSequence.iter().take(20).collect_vec()", &mut |xs| no_out!(xs.iter().take(20).collect_vec()), )], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/len.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_len); register_bench!(runner, benchmark_rational_sequence_len); } fn demo_rational_sequence_len(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("len({}) = {:?}", xs, xs.len()); } } fn benchmark_rational_sequence_len(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "RationalSequence.len()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.len()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/basic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { component_len::register(runner); is_empty::register(runner); is_finite::register(runner); iter::register(runner); len::register(runner); } mod component_len; mod is_empty; mod is_finite; mod iter; mod len; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::pair_rational_sequence_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_pair_gen; use malachite_base::test_util::runner::Runner; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_cmp); register_bench!(runner, benchmark_rational_sequence_cmp); } fn demo_rational_sequence_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_rational_sequence_pair_gen::() .get(gm, config) .take(limit) { match xs.cmp(&ys) { Less => println!("{xs} < {ys}"), Equal => println!("{xs} = {ys}"), Greater => println!("{xs} > {ys}"), } } } #[allow(unused_must_use)] fn benchmark_rational_sequence_cmp(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "RationalSequence.cmp(&RationalSequence)", BenchmarkType::Single, unsigned_rational_sequence_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_rational_sequence_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(xs.cmp(&ys)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::pair_rational_sequence_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_eq); register_bench!(runner, benchmark_rational_sequence_eq); } fn demo_rational_sequence_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_rational_sequence_pair_gen::() .get(gm, config) .take(limit) { if xs == ys { println!("{xs} = {ys}"); } else { println!("{xs} ≠ {ys}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_sequence_eq(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "RationalSequence == RationalSequence", BenchmarkType::Single, unsigned_rational_sequence_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_rational_sequence_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(xs == ys))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_hash); register_bench!(runner, benchmark_rational_sequence_hash); } fn demo_rational_sequence_hash(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("hash({}) = {}", xs, hash(&xs)); } } fn benchmark_rational_sequence_hash( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational hash", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(hash(&xs)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); eq::register(runner); hash::register(runner); } mod cmp; mod eq; mod hash; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_rational_sequence_max_len_bucketer, rational_sequence_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_rational_sequence_gen, unsigned_rational_sequence_pair_gen, }; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_clone); register_demo!(runner, demo_rational_sequence_clone_from); register_bench!(runner, benchmark_rational_sequence_clone); register_bench!(runner, benchmark_rational_sequence_clone_from); } fn demo_rational_sequence_clone(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("clone({}) = {}", xs, xs.clone()); } } fn demo_rational_sequence_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_rational_sequence_pair_gen::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); xs.clone_from(&ys); println!("xs := {xs_old}; xs.clone_from({ys}); xs = {xs}"); } } #[allow(clippy::redundant_clone, unused_must_use)] fn benchmark_rational_sequence_clone( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.clone()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.clone()))], ); } fn benchmark_rational_sequence_clone_from( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.clone_from(&RationalSequence)", BenchmarkType::Single, unsigned_rational_sequence_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_rational_sequence_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, ys)| xs.clone_from(&ys))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/conversion/from_vec.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_from_vec); register_demo!(runner, demo_rational_sequence_from_slice); register_bench!( runner, benchmark_rational_sequence_from_vec_evaluation_strategy ); } fn demo_rational_sequence_from_vec(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "from_vec({:?}) = {}", xs.clone(), RationalSequence::from_vec(xs) ); } } fn demo_rational_sequence_from_slice(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "from_slice(&{:?}) = {}", xs, RationalSequence::from_slice(&xs) ); } } fn benchmark_rational_sequence_from_vec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence::from_vec(Vec)", BenchmarkType::EvaluationStrategy, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("from_vec", &mut |xs| { no_out!(RationalSequence::from_vec(xs)); }), ("from_slice", &mut |xs| { no_out!(RationalSequence::from_slice(&xs)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/conversion/from_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::bench::bucketers::pair_sum_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_from_vecs); register_demo!(runner, demo_rational_sequence_from_slices); register_bench!( runner, benchmark_rational_sequence_from_vecs_evaluation_strategy ); } fn demo_rational_sequence_from_vecs(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen::().get(gm, config).take(limit) { println!( "from_vecs({:?}, {:?}) = {}", xs.clone(), ys.clone(), RationalSequence::from_vecs(xs, ys) ); } } fn demo_rational_sequence_from_slices(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen::().get(gm, config).take(limit) { println!( "from_slices(&{:?}, &{:?}) = {}", xs, ys, RationalSequence::from_slices(&xs, &ys) ); } } fn benchmark_rational_sequence_from_vecs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence::from_vecs(Vec, Vec)", BenchmarkType::EvaluationStrategy, unsigned_vec_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_sum_vec_len_bucketer("xs", "ys"), &mut [ ("from_vecs", &mut |(xs, ys)| { no_out!(RationalSequence::from_vecs(xs, ys)); }), ("from_slices", &mut |(xs, ys)| { no_out!(RationalSequence::from_slices(&xs, &ys)); }), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); from_vec::register(runner); from_vecs::register(runner); to_vecs::register(runner); } mod clone; mod from_vec; mod from_vecs; mod to_vecs; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/conversion/to_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_to_vecs); register_demo!(runner, demo_rational_sequence_into_vecs); register_demo!(runner, demo_rational_sequence_slices_ref); register_bench!( runner, benchmark_rational_sequence_to_vecs_evaluation_strategy ); } fn demo_rational_sequence_to_vecs(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("to_vecs(&{}) = {:?}", xs, xs.to_vecs()); } } fn demo_rational_sequence_into_vecs(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("into_vecs({}) = {:?}", xs.clone(), xs.into_vecs()); } } fn demo_rational_sequence_slices_ref(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("slices_ref(&{}) = {:?}", xs, xs.slices_ref()); } } fn benchmark_rational_sequence_to_vecs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.to_vecs()", BenchmarkType::EvaluationStrategy, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [ ("to_vecs", &mut |xs| no_out!(xs.to_vecs())), ("into_vecs", &mut |xs| no_out!(xs.into_vecs())), ("slices_ref", &mut |xs| no_out!(xs.slices_ref())), ], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { access::register(runner); basic::register(runner); comparison::register(runner); conversion::register(runner); to_string::register(runner); } mod access; mod basic; mod comparison; mod conversion; mod to_string; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rational_sequences/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToDebugString; use malachite_base::test_util::bench::bucketers::rational_sequence_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sequence_to_string); register_demo!(runner, demo_rational_sequence_to_debug_string); register_bench!(runner, benchmark_rational_sequence_to_string); register_bench!(runner, benchmark_rational_sequence_to_debug_string); } fn demo_rational_sequence_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("{xs}"); } } fn demo_rational_sequence_to_debug_string(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_rational_sequence_gen::() .get(gm, config) .take(limit) { println!("{xs:?}"); } } fn benchmark_rational_sequence_to_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.to_string()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.to_string()))], ); } fn benchmark_rational_sequence_to_debug_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "RationalSequence.to_debug_string()", BenchmarkType::Single, unsigned_rational_sequence_gen::().get(gm, config), gm.name(), limit, file_name, &rational_sequence_len_bucketer("xs"), &mut [("Malachite", &mut |xs| no_out!(xs.to_debug_string()))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{rounding_mode_gen, rounding_mode_pair_gen}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_clone); register_demo!(runner, demo_rounding_mode_clone_from); } fn demo_rounding_mode_clone(gm: GenMode, config: &GenConfig, limit: usize) { for rm in rounding_mode_gen().get(gm, config).take(limit) { println!("clone({}) = {}", rm, rm.clone()); } } fn demo_rounding_mode_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rounding_mode_pair_gen().get(gm, config).take(limit) { let x_old = x; x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::rounding_mode_pair_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_eq); } fn demo_rounding_mode_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rounding_mode_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/from_str.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_2}; use malachite_base::test_util::runner::Runner; use std::str::FromStr; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_from_str); register_demo!(runner, demo_rounding_mode_from_str_targeted); register_bench!(runner, benchmark_rounding_mode_from_str); } fn demo_rounding_mode_from_str(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!( "RoundingMode::from_str({:?}) = {:?}", s, RoundingMode::from_str(&s) ); } } fn demo_rounding_mode_from_str_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_2().get(gm, config).take(limit) { println!( "RoundingMode::from_str({:?}) = {:?}", s, RoundingMode::from_str(&s) ); } } #[allow(unused_must_use)] fn benchmark_rounding_mode_from_str( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "from_str(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(RoundingMode::from_str(&s)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::rounding_mode_gen; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_hash); } fn demo_rounding_mode_hash(gm: GenMode, config: &GenConfig, limit: usize) { for rm in rounding_mode_gen().get(gm, config).take(limit) { println!("hash({}) = {}", rm, hash(&rm)); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); eq::register(runner); from_str::register(runner); hash::register(runner); neg::register(runner); to_string::register(runner); } mod clone; mod eq; mod from_str; mod hash; mod neg; mod to_string; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::rounding_mode_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_neg_assign); register_demo!(runner, demo_rounding_mode_neg); } fn demo_rounding_mode_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut rm in rounding_mode_gen().get(gm, config).take(limit) { let rm_old = rm; rm.neg_assign(); println!("rm := {rm_old}; r.neg_assign(); rm = {rm}"); } } fn demo_rounding_mode_neg(gm: GenMode, config: &GenConfig, limit: usize) { for rm in rounding_mode_gen().get(gm, config).take(limit) { println!("-{} = {}", rm, -rm); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/rounding_modes/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::rounding_mode_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rounding_mode_to_string); } fn demo_rounding_mode_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for rm in rounding_mode_gen().get(gm, config).take(limit) { println!("{rm}"); } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/min_repeating_len.rs ================================================ // Copyright © 2026 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 malachite_base::slices::min_repeating_len; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_4; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_min_repeating_len); register_bench!(runner, benchmark_min_repeating_len); } fn demo_min_repeating_len(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_4::().get(gm, config).take(limit) { println!("min_repeating_len({:?}) = {}", xs, min_repeating_len(&xs)); } } fn benchmark_min_repeating_len(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "min_repeating_len(&[T])", BenchmarkType::Single, unsigned_vec_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(min_repeating_len(&xs)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { min_repeating_len::register(runner); slice_leading_zeros::register(runner); slice_move_left::register(runner); slice_set_zero::register(runner); slice_test_zero::register(runner); slice_trailing_zeros::register(runner); split_into_chunks::register(runner); } mod min_repeating_len; mod slice_leading_zeros; mod slice_move_left; mod slice_set_zero; mod slice_test_zero; mod slice_trailing_zeros; mod split_into_chunks; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/slice_leading_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::slices::slice_leading_zeros; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_slice_leading_zeros); register_bench!(runner, benchmark_slice_leading_zeros); } fn demo_slice_leading_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "slice_leading_zeros({:?}) = {}", xs, slice_leading_zeros(&xs) ); } } fn benchmark_slice_leading_zeros(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "slice_leading_zeros(&[T])", BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(slice_leading_zeros(&xs)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/slice_move_left.rs ================================================ // Copyright © 2026 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 malachite_base::slices::slice_move_left; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_1; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_slice_move_left); register_bench!(runner, benchmark_slice_move_left); } fn demo_slice_move_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, amount) in unsigned_vec_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let old_xs = xs.clone(); slice_move_left(&mut xs, amount); println!("xs := {old_xs:?}; slice_move_left(&mut xs, {amount}); xs = {xs:?}"); } } fn benchmark_slice_move_left(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "slice_move_left(&mut [T], usize)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, amount)| { slice_move_left(&mut xs, amount); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/slice_set_zero.rs ================================================ // Copyright © 2026 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 malachite_base::slices::slice_set_zero; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_slice_set_zero); register_bench!(runner, benchmark_slice_set_zero); } fn demo_slice_set_zero(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen::().get(gm, config).take(limit) { let old_xs = xs.clone(); slice_set_zero(&mut xs); println!("xs := {old_xs:?}; slice_set_zero(&mut xs); xs = {xs:?}"); } } fn benchmark_slice_set_zero(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "slice_set_zero(&mut [T])", BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut xs| slice_set_zero(&mut xs))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/slice_test_zero.rs ================================================ // Copyright © 2026 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 malachite_base::slices::slice_test_zero; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_slice_test_zero); register_bench!(runner, benchmark_slice_test_zero); } fn demo_slice_test_zero(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!("slice_test_zero({:?}) = {:?}", xs, slice_test_zero(&xs)); } } fn benchmark_slice_test_zero(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "slice_test_zero(&[T])", BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(slice_test_zero(&xs)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/slice_trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::slices::slice_trailing_zeros; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_slice_trailing_zeros); register_bench!(runner, benchmark_slice_trailing_zeros); } fn demo_slice_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen::().get(gm, config).take(limit) { println!( "slice_trailing_zeros({:?}) = {}", xs, slice_trailing_zeros(&xs) ); } } fn benchmark_slice_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "slice_trailing_zeros(&[T])", BenchmarkType::Single, unsigned_vec_gen::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(slice_trailing_zeros(&xs)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/slices/split_into_chunks.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_unsigned_triple_gen_var_2; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_split_into_chunks); register_demo!(runner, demo_split_into_chunks_mut); } macro_rules! split_into_chunks_helper { ($xs: expr, $len: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {{ split_into_chunks!($xs, $len, [$($xs_i),*], $xs_last); let xss = &[$($xs_i,)* $xs_last]; let mut message = "xs := ".to_string(); message.push_str(&$xs.to_debug_string()); message.push_str("; split_into_chunks!(xs, "); message.push_str(&$len.to_string()); message.push_str(", ["); message.push_str(&(1..$n).map(|i| format!("xs_{}", i)).join(", ")); message.push_str("], xs_"); message.push_str(&$n.to_string()); message.push_str("); "); message.push_str(&(1..=$n).zip(xss) .map(|(i, xs)| format!("xs_{} = {:?}", i, xs)).join("; ")); println!("{}", message); }} } fn demo_split_into_chunks(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, len, n) in unsigned_vec_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { match n { 0 => split_into_chunks_helper!(xs, len, 1, [], xs_1), 1 => split_into_chunks_helper!(xs, len, 2, [xs_1], xs_2), 2 => split_into_chunks_helper!(xs, len, 3, [xs_1, xs_2], xs_3), 3 => split_into_chunks_helper!(xs, len, 4, [xs_1, xs_2, xs_3], xs_4), 4 => split_into_chunks_helper!(xs, len, 5, [xs_1, xs_2, xs_3, xs_4], xs_5), 5 => split_into_chunks_helper!(xs, len, 6, [xs_1, xs_2, xs_3, xs_4, xs_5], xs_6), 6 => split_into_chunks_helper!(xs, len, 7, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6], xs_7), 7 => split_into_chunks_helper!( xs, len, 8, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6, xs_7], xs_8 ), _ => println!("Large number of chunks"), } } } macro_rules! split_into_chunks_mut_helper { ($xs: expr, $len: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {{ split_into_chunks_mut!($xs, $len, [$($xs_i),*], $xs_last); let xss = &[$($xs_i.to_vec(),)* $xs_last.to_vec()]; let mut message = "xs := ".to_string(); message.push_str(&$xs.to_debug_string()); message.push_str("; split_into_chunks_mut!(xs, "); message.push_str(&$len.to_string()); message.push_str(", ["); message.push_str(&(1..$n).map(|i| format!("xs_{}", i)).join(", ")); message.push_str("], xs_"); message.push_str(&$n.to_string()); message.push_str("); "); message.push_str(&(1..=$n).zip(xss) .map(|(i, xs)| format!("xs_{} = {:?}", i, xs)).join("; ")); println!("{}", message); }} } fn demo_split_into_chunks_mut(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, len, n) in unsigned_vec_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { match n { 0 => split_into_chunks_mut_helper!(xs, len, 1, [], xs_1), 1 => split_into_chunks_mut_helper!(xs, len, 2, [xs_1], xs_2), 2 => split_into_chunks_mut_helper!(xs, len, 3, [xs_1, xs_2], xs_3), 3 => split_into_chunks_mut_helper!(xs, len, 4, [xs_1, xs_2, xs_3], xs_4), 4 => split_into_chunks_mut_helper!(xs, len, 5, [xs_1, xs_2, xs_3, xs_4], xs_5), 5 => split_into_chunks_mut_helper!(xs, len, 6, [xs_1, xs_2, xs_3, xs_4, xs_5], xs_6), 6 => split_into_chunks_mut_helper!( xs, len, 7, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6], xs_7 ), 7 => split_into_chunks_mut_helper!( xs, len, 8, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6, xs_7], xs_8 ), _ => println!("Large number of chunks"), } } } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/strings/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { string_is_subset::register(runner); string_sort::register(runner); string_unique::register(runner); } mod string_is_subset; mod string_sort; mod string_unique; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/strings/string_is_subset.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_is_subset; use malachite_base::test_util::bench::bucketers::pair_string_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_pair_gen, string_pair_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_string_is_subset); register_demo!(runner, demo_string_is_subset_ascii); register_bench!(runner, benchmark_string_is_subset); } fn demo_string_is_subset(gm: GenMode, config: &GenConfig, limit: usize) { for (s, t) in string_pair_gen().get(gm, config).take(limit) { println!( "{:?} is {}a subset of {:?}", s, if string_is_subset(&s, &t) { "" } else { "not " }, t ); } } fn demo_string_is_subset_ascii(gm: GenMode, config: &GenConfig, limit: usize) { for (s, t) in string_pair_gen_var_1().get(gm, config).take(limit) { println!( "{:?} is {}a subset of {:?}", s, if string_is_subset(&s, &t) { "" } else { "not " }, t ); } } fn benchmark_string_is_subset(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "string_is_subset(&str, &str)", BenchmarkType::Single, string_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_string_max_len_bucketer("s", "t"), &mut [("Malachite", &mut |(s, t)| no_out!(string_is_subset(&s, &t)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/strings/string_sort.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_sort; use malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_string_sort); register_demo!(runner, demo_string_sort_ascii); register_bench!(runner, benchmark_string_sort); } fn demo_string_sort(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!("string_sort({:?}) = {:?}", s, string_sort(&s)); } } fn demo_string_sort_ascii(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_1().get(gm, config).take(limit) { println!("string_sort({:?}) = {:?}", s, string_sort(&s)); } } fn benchmark_string_sort(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "string_sort(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(string_sort(&s)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/strings/string_unique.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_unique; use malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_1}; use malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_string_unique); register_demo!(runner, demo_string_unique_ascii); register_bench!(runner, benchmark_string_unique); } fn demo_string_unique(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!("string_unique({:?}) = {:?}", s, string_unique(&s)); } } fn demo_string_unique_ascii(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_1().get(gm, config).take(limit) { println!("string_unique({:?}) = {:?}", s, string_unique(&s)); } } fn benchmark_string_unique(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "string_unique(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(string_unique(&s)))], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/vecs/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { vec_delete_left::register(runner); vec_pad_left::register(runner); } mod vec_delete_left; mod vec_pad_left; ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/vecs/vec_delete_left.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_base::vecs::vec_delete_left; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_vec_delete_left); register_bench!(runner, benchmark_vec_delete_left); } fn demo_vec_delete_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, amount) in unsigned_vec_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let old_xs = xs.clone(); vec_delete_left(&mut xs, amount); println!("xs := {old_xs:?}; vec_delete_left(&mut xs, {amount}); xs = {xs:?}"); } } fn benchmark_vec_delete_left(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "vec_delete_left(&mut [T], usize)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, amount)| { vec_delete_left(&mut xs, amount); })], ); } ================================================ FILE: malachite-base/src/bin_util/demo_and_bench/vecs/vec_pad_left.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::triple_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_unsigned_triple_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_base::vecs::vec_pad_left; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_vec_pad_left); register_bench!(runner, benchmark_vec_pad_left); } fn demo_vec_pad_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, pad_size, pad_value) in unsigned_vec_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_xs = xs.clone(); vec_pad_left(&mut xs, pad_size, pad_value); println!("xs := {old_xs:?}; vec_pad_left(&mut xs, {pad_size}, {pad_value}); xs = {xs:?}"); } } fn benchmark_vec_pad_left(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "vec_pad_left(&mut [T], usize, T)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, pad_size, pad_value)| { vec_pad_left(&mut xs, pad_size, pad_value); })], ); } ================================================ FILE: malachite-base/src/bin_util/generate/max_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; fn max_base_helper() { if T::NAME == "usize" { return; } print!( "const MAX_BASE_{}: [{}; {}] = [0", T::WIDTH, T::NAME, T::WIDTH ); for exp in 1..T::WIDTH { print!(", {}", T::MAX.floor_root(exp)); } println!("];"); println!(); print!( "const MAX_POWER_{}: [{}; {}] = [0", T::WIDTH, T::NAME, T::WIDTH ); for exp in 1..T::WIDTH { print!(", {}", T::MAX.floor_root(exp).pow(exp)); } println!("];"); println!(); } pub(crate) fn generate_max_base() { println!("// This section is created by max_base.rs."); apply_fn_to_unsigneds!(max_base_helper); } ================================================ FILE: malachite-base/src/bin_util/generate/mod.rs ================================================ // Copyright © 2026 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 . pub mod max_base; pub mod rle; pub mod tuning_manager; ================================================ FILE: malachite-base/src/bin_util/generate/rle.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::rle_encode; pub(crate) fn generate_rle_encoding() { // Example xs let xs = &[1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2]; println!("{:?}", rle_encode(xs.iter())); } ================================================ FILE: malachite-base/src/bin_util/generate/tuning_manager.rs ================================================ // Copyright © 2026 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 std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fs::File; use std::io::{BufRead, BufReader}; use walkdir::WalkDir; const PARENT_PATHS: [&str; 2] = ["../malachite-base/src", "../malachite-nz/src"]; fn find_all_file_paths() -> BTreeSet { let mut paths = BTreeSet::new(); for &parent_path in &PARENT_PATHS { for entry in WalkDir::new(parent_path) { let name = entry.unwrap().path().display().to_string(); // Exclude platform_64 as we'll get all the same info from _32 if name.ends_with(".rs") && !name.ends_with("/platform_64.rs") { paths.insert(name); } } } paths } fn primitive_tokenize(s: &str) -> Vec { let chars = s.chars().collect_vec(); let mut tokens = Vec::new(); let mut token = String::new(); for &c in &chars { if c.is_alphanumeric() || c == '_' { token.push(c); } else if !token.is_empty() { tokens.push(token); token = String::new(); } } if !token.is_empty() { tokens.push(token); } tokens } const FN_PREFIXES: [&str; 6] = ["pub fn ", "pub(crate) fn ", "fn ", "pub const fn ", "pub(crate) const fn ", "const fn "]; const ALLOWED_DOUBLE_NAMES: [&str; 3] = ["limbs_mod_limb", "oz_fmt", "fail_on_untested_path"]; #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] struct FunctionRecord { name: String, file_path: String, line_number: usize, } fn get_all_top_level_functions() -> BTreeMap { let allowed_double_names: HashSet<&str> = ALLOWED_DOUBLE_NAMES.iter().copied().collect(); let mut fns = BTreeMap::new(); let file_paths = find_all_file_paths(); for path in &file_paths { let input = File::open(path).unwrap(); let buffered = BufReader::new(input); for (i, line) in buffered.lines().enumerate() { let line = line.unwrap(); for &prefix in &FN_PREFIXES { if let Some(fn_string) = line.strip_prefix(prefix) { let fn_name = primitive_tokenize(fn_string).swap_remove(0); if !allowed_double_names.contains(&fn_name.as_str()) && fns.contains_key(&fn_name) { panic!("Duplicate top-level function name: {fn_name}"); } fns.insert( fn_name.clone(), FunctionRecord { name: fn_name, file_path: path.to_string(), line_number: i, }, ); } } } } fns } const CONST_PREFIXES: [&str; 3] = ["pub const ", "pub(crate) const ", "const "]; fn get_all_tuneable_constants() -> BTreeMap { let file_paths = find_all_file_paths(); let mut constants = BTreeMap::new(); let mut expecting_constant = false; for path in &file_paths { let input = File::open(path).unwrap(); let buffered = BufReader::new(input); for (i, line) in buffered.lines().enumerate() { let line = line.unwrap(); if expecting_constant { if line.starts_with("//") || line.starts_with("#[") { // do nothing } else { let mut p = None; for &prefix in &CONST_PREFIXES { if line.starts_with(prefix) { p = Some(prefix); break; } } assert!(p.is_some(), "Bad const. line {i} in {path}"); let p = p.unwrap(); let name = &line[p.len()..]; let colon_index = name.chars().position(|c| c == ':').unwrap(); let name = &name[..colon_index]; assert!( !constants.contains_key(name), "Duplicate constant name: {name}" ); constants.insert( name.to_string(), FunctionRecord { name: name.to_string(), file_path: path.to_string(), line_number: i, }, ); expecting_constant = false; } } else if line == "//TODO tune" { expecting_constant = true; } } } assert!(!expecting_constant); constants } fn extract_functions_and_constants( name: &str, lines: &[String], fns: &BTreeMap, cs: &BTreeMap, ) -> (BTreeSet, BTreeSet) { let mut matched_fns = BTreeSet::new(); let mut matched_cs = BTreeSet::new(); let mut first = true; for line in lines { for token in primitive_tokenize(line) { if fns.contains_key(&token) { if first { assert_eq!(token, name); first = false; } else { matched_fns.insert(token.clone()); } } else if cs.contains_key(&token) { if first { assert_eq!(token, name); first = false; } else { matched_cs.insert(token.clone()); } } } } (matched_fns, matched_cs) } fn get_referenced_items_for_constant( constant: &FunctionRecord, fns: &BTreeMap, cs: &BTreeMap, ) -> (BTreeSet, BTreeSet) { let input = File::open(&constant.file_path).unwrap(); let buffered = BufReader::new(input); let mut lines = Vec::new(); let mut brace_index = 0; for (i, line) in buffered.lines().enumerate() { if i < constant.line_number { continue; } let line = line.unwrap(); let mut done = false; for c in line.chars() { match c { '{' => brace_index += 1, '}' => { assert_ne!(brace_index, 0); brace_index -= 1; } ';' => { if brace_index == 0 { done = true; break; } } _ => {} } } lines.push(line); if done { break; } } extract_functions_and_constants(&constant.name, &lines, fns, cs) } fn get_referenced_items_for_function( function: &FunctionRecord, fns: &BTreeMap, cs: &BTreeMap, ) -> (BTreeSet, BTreeSet) { let input = File::open(&function.file_path).unwrap(); let buffered = BufReader::new(input); let mut lines = Vec::new(); let mut brace_index = 0; for (i, line) in buffered.lines().enumerate() { if i < function.line_number { continue; } let line = line.unwrap(); let mut done = false; for c in line.chars() { match c { '{' => brace_index += 1, '}' => { assert_ne!(brace_index, 0); brace_index -= 1; if brace_index == 0 { done = true; break; } } _ => {} } } lines.push(line); if done { break; } } extract_functions_and_constants(&function.name, &lines, fns, cs) } pub struct ReferenceData { functions: BTreeMap, constants: BTreeMap, pub constants_referencing_constants: BTreeMap>, pub constants_referencing_functions: BTreeMap>, functions_referencing_constants: BTreeMap>, pub functions_referencing_functions: BTreeMap>, } fn parse_and_get_references() -> ReferenceData { let fns = get_all_top_level_functions(); let cs = get_all_tuneable_constants(); let mut crc = BTreeMap::new(); let mut crf = BTreeMap::new(); for c in cs.values() { let (rf, rc) = get_referenced_items_for_constant(c, &fns, &cs); crc.insert(c.name.clone(), rc); crf.insert(c.name.clone(), rf); } let mut frc = BTreeMap::new(); let mut frf = BTreeMap::new(); for f in fns.values() { let (rf, rc) = get_referenced_items_for_function(f, &fns, &cs); frc.insert(f.name.clone(), rc); frf.insert(f.name.clone(), rf); } ReferenceData { functions: fns, constants: cs, constants_referencing_constants: crc, constants_referencing_functions: crf, functions_referencing_constants: frc, functions_referencing_functions: frf, } } fn invert_map(m: &BTreeMap>) -> BTreeMap> { let mut inverse = BTreeMap::new(); for (k, vs) in m { for v in vs { inverse .entry(v.clone()) .or_insert_with(BTreeSet::new) .insert(k.clone()); } } inverse } pub fn build_reference_data() { parse_and_get_references(); } fn hfdm_helper(map: &mut BTreeMap, k: &str, v: &str) { map.insert(k.to_string(), v.to_string()); } fn hardcoded_defining_function_map() -> BTreeMap { let mut m = BTreeMap::new(); hfdm_helper(&mut m, "BMOD_1_TO_MOD_1_THRESHOLD", "limbs_mod_limb_helper"); hfdm_helper( &mut m, "DC_BDIV_QR_THRESHOLD", "limbs_modular_div_mod_helper", ); hfdm_helper(&mut m, "DC_BDIV_Q_THRESHOLD", "limbs_modular_invert_small"); hfdm_helper(&mut m, "DC_DIVAPPR_Q_THRESHOLD", "limbs_div_approx_helper"); hfdm_helper(&mut m, "DC_DIV_QR_THRESHOLD", "limbs_div_dc_helper"); hfdm_helper(&mut m, "DC_DIV_Q_THRESHOLD", "limbs_div_q_dc_helper"); m } fn generate_defining_function_map(data: &ReferenceData) -> BTreeMap { let mut defining_functions = hardcoded_defining_function_map(); for (k, v) in &defining_functions { assert!(data.constants.contains_key(k)); assert!(data.functions.contains_key(v)); assert!(data.functions_referencing_constants[v].contains(k)); } for (c, fs) in invert_map(&data.functions_referencing_constants) { if defining_functions.contains_key(&c) { continue; } if fs.len() == 1 { defining_functions.insert(c.clone(), fs.iter().next().unwrap().clone()); } else { panic!("Must specify defining function for {c}. Possibilities are {fs:?}"); } } defining_functions } pub fn test() { let data = parse_and_get_references(); generate_defining_function_map(&data); } ================================================ FILE: malachite-base/src/bools/constants.rs ================================================ // Copyright © 2026 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 crate::comparison::traits::{Max, Min}; use crate::named::Named; impl Min for bool { /// The minimum value of a [`bool`]: `false`. const MIN: Self = false; } impl Max for bool { /// The maximum value of a [`bool`]: `true`. const MAX: Self = true; } impl_named!(bool); ================================================ FILE: malachite-base/src/bools/exhaustive.rs ================================================ // Copyright © 2026 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 core::iter::Copied; use core::slice::Iter; /// An iterator that generates both [`bool`]s. /// /// This `struct` is created by [`exhaustive_bools`]; see its documentation for more. pub type ExhaustiveBools = Copied>; /// Generates both [`bool`]s. /// /// The output length is 2. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// /// assert_eq!(exhaustive_bools().collect_vec(), &[false, true]); /// ``` #[inline] pub fn exhaustive_bools() -> ExhaustiveBools { [false, true].iter().copied() } ================================================ FILE: malachite-base/src/bools/mod.rs ================================================ // Copyright © 2026 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 . /// Constants associated with [`bool`]s. /// /// The constants [`MIN`](crate::comparison::traits::Min::MIN) and /// [`MAX`](crate::comparison::traits::Max::MAX) are defined as for [`bool`]s as `false` and `true`, /// respectively. The constant [`NAME`](crate::named::Named::NAME) is defined as "bool". pub mod constants; /// An iterator that generates [`bool`]s without repetition. pub mod exhaustive; /// The implementation of [`NotAssign`](crate::num::logic::traits::NotAssign) for [`bool`]. pub mod not_assign; #[cfg(feature = "random")] /// Iterators that generate [`bool`]s randomly. pub mod random; ================================================ FILE: malachite-base/src/bools/not_assign.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::NotAssign; impl NotAssign for bool { /// Replaces a [`bool`] by its opposite. /// /// $b \gets \lnot b$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::NotAssign; /// /// let mut b = false; /// b.not_assign(); /// assert_eq!(b, true); /// /// let mut b = true; /// b.not_assign(); /// assert_eq!(b, false); /// ``` #[inline] fn not_assign(&mut self) { *self = !*self; } } ================================================ FILE: malachite-base/src/bools/random.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Parity; use crate::num::random::geometric::SimpleRational; use crate::num::random::{ RandomUnsignedsLessThan, VariableRangeGenerator, random_unsigneds_less_than, }; use crate::random::Seed; use rand::Rng; use rand_chacha::ChaCha20Rng; /// Uniformly generates random [`bool`]s. /// /// This `struct` is created by [`random_bools`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomBools { rng: ChaCha20Rng, x: u32, bits_left: u8, } impl Iterator for RandomBools { type Item = bool; #[inline] fn next(&mut self) -> Option { if self.bits_left == 0 { self.x = self.rng.random(); self.bits_left = 31; } else { self.x >>= 1; self.bits_left -= 1; } Some(self.x.odd()) } } /// Uniformly generates random [`bool`]s. /// /// $P(\text{false}) = P(\text{true}) = \frac{1}{2}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::bools::random::random_bools; /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_bools(EXAMPLE_SEED), 10), /// "[true, false, false, false, true, true, true, false, true, true, ...]" /// ) /// ``` /// /// # Notes /// The resulting iterator uses every random bit generated by the PRNG, unlike some implementations /// which only use one bit out of 32 or 64. #[inline] pub fn random_bools(seed: Seed) -> RandomBools { RandomBools { rng: seed.get_rng(), x: 0, bits_left: 0, } } /// Generates random [`bool`]s, with a fixed probability of generating `true`. /// /// This `struct` is created by [`weighted_random_bools`]; see its documentation for more. #[derive(Clone, Debug)] pub struct WeightedRandomBools { numerator: u64, xs: RandomUnsignedsLessThan, } impl Iterator for WeightedRandomBools { type Item = bool; #[inline] fn next(&mut self) -> Option { Some(self.xs.next().unwrap() < self.numerator) } } /// Generates random [`bool`]s, with a fixed probability of generating `true`. /// /// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$. Then /// /// $P(\text{true}) = p$, /// /// $P(\text{false}) = 1-p$. /// /// The output length is infinite. /// /// # Panics /// Panics if `p_denominator` is 0 or `p_numerator > p_denominator`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `p_denominator.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::bools::random::weighted_random_bools; /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(weighted_random_bools(EXAMPLE_SEED, 3, 4), 10), /// "[true, true, false, true, false, false, true, false, true, true, ...]" /// ) /// ``` pub fn weighted_random_bools( seed: Seed, p_numerator: u64, p_denominator: u64, ) -> WeightedRandomBools { assert!(p_numerator <= p_denominator); let p = SimpleRational::new(p_numerator, p_denominator); WeightedRandomBools { numerator: p.n, xs: random_unsigneds_less_than(seed, p.d), } } /// Generates a random [`bool`] with a particular probability of being `true`. /// /// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$. Then /// /// $P(\text{true}) = p$, /// /// $P(\text{false}) = 1-p$. /// /// # Panics /// Panics if `p_denominator` is 0 or `p_numerator > p_denominator`. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `p_denominator.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::bools::random::get_weighted_random_bool; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 10), /// false /// ); /// ``` pub fn get_weighted_random_bool( range_generator: &mut VariableRangeGenerator, p_numerator: u64, p_denominator: u64, ) -> bool { assert_ne!(p_denominator, 0); assert!(p_numerator <= p_denominator); if p_numerator == 0 { return false; } else if p_numerator == p_denominator { return true; } let p = SimpleRational::new(p_numerator, p_denominator); range_generator.next_less_than(p.d) < p.n } ================================================ FILE: malachite-base/src/chars/constants.rs ================================================ // Copyright © 2026 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 crate::comparison::traits::{Max, Min}; use crate::named::Named; /// The number of [Unicode scalar values](https://www.unicode.org/glossary/#unicode_scalar_value). /// $2^{20}+2^{16}-2^{11} = \mathrm{0x10\\,f800} = 1,\\!112,\\!064$. pub const NUMBER_OF_CHARS: u32 = (1 << 20) + (1 << 16) - NUMBER_OF_SURROGATE_CODE_POINTS; /// The number of [surrogate code points](https://www.unicode.org/glossary/#surrogate_code_point); /// these are code points that do not correspond to any valid [`char`]. /// /// $2^{11} = 2,\\!048$. pub const NUMBER_OF_SURROGATE_CODE_POINTS: u32 = 1 << 11; /// The first [surrogate code point](https://www.unicode.org/glossary/#surrogate_code_point). pub const FIRST_SURROGATE_CODE_POINT: u32 = 0xd800; /// The [`char`] that comes just before the surrogate range. /// /// This happens to be an unassigned (as of Unicode 14.0) character in the [Hangul Jamo Extended-B /// block](https://www.unicode.org/charts/PDF/UD7B0.pdf). pub const CHAR_JUST_BELOW_SURROGATES: char = '\u{d7ff}'; /// The [`char`] that comes just after the surrogate range. /// /// This is a character in the [Private Use Area](https://www.unicode.org/charts/PDF/UE000.pdf). pub const CHAR_JUST_ABOVE_SURROGATES: char = '\u{e000}'; impl Min for char { /// The minimum value of a [`char`]: `'\u{0}'`. /// /// This is the famous NUL character, a [C0 /// control](https://www.unicode.org/charts/PDF/U0000.pdf). const MIN: Self = '\u{0}'; } impl Max for char { /// The maximum value of a [`char`]: `'\u{10ffff}'`. /// /// This is a character in [Supplementary Private Use /// Area-B](https://www.unicode.org/charts/PDF/U10FF80.pdf). const MAX: Self = core::char::MAX; } impl_named!(char); ================================================ FILE: malachite-base/src/chars/crement.rs ================================================ // Copyright © 2026 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 crate::chars::constants::{ CHAR_JUST_BELOW_SURROGATES, FIRST_SURROGATE_CODE_POINT, NUMBER_OF_CHARS, NUMBER_OF_SURROGATE_CODE_POINTS, }; /// Converts a [`char`] to a [`u32`]. /// /// The conversion is done in such a way that if the next largest [`char`] after $x$ is $y$, then /// $\mathrm{char\\_to\\_contiguous\\_range(x)}+1 = \mathrm{char\\_to\\_contiguous\\_range(y)}$. /// This can't be accomplished just through casting, because there is a range of [`u32`]s (the /// [surrogate code points](https://www.unicode.org/glossary/#surrogate_code_point)) that do not /// correspond to any [`char`]. /// /// The inverse of this function is [`contiguous_range_to_char`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::crement::char_to_contiguous_range; /// use std::char; /// /// assert_eq!(char_to_contiguous_range('\u{0}'), 0); /// assert_eq!(char_to_contiguous_range('a'), 97); /// assert_eq!(char_to_contiguous_range(char::MAX), 1112063); /// ``` pub const fn char_to_contiguous_range(c: char) -> u32 { match c { '\u{0}'..=CHAR_JUST_BELOW_SURROGATES => c as u32, _ => c as u32 - NUMBER_OF_SURROGATE_CODE_POINTS, } } /// Converts a [`u32`] to a [`char`]; if all [`char`]s were arranged in ascending order, passing $u$ /// to this function would return the $u$th [`char`]. /// /// This function is the inverse of [`char_to_contiguous_range`]. Every [`u32`] between 0 and /// $\mathrm{NUMBER\\_OF\\_CHARS} - 1$, inclusive, is mapped to a distinct [`char`]. Passing a /// larger [`u32`] yields `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::crement::contiguous_range_to_char; /// use std::char; /// /// assert_eq!(contiguous_range_to_char(0), Some('\u{0}')); /// assert_eq!(contiguous_range_to_char(97), Some('a')); /// assert_eq!(contiguous_range_to_char(1112063), Some(char::MAX)); /// ``` pub const fn contiguous_range_to_char(u: u32) -> Option { const ONE_BELOW_FIRST_SURROGATE_CODE_POINT: u32 = FIRST_SURROGATE_CODE_POINT - 1; const ONE_BELOW_NUMBER_OF_CHARS: u32 = NUMBER_OF_CHARS - 1; match u { 0..=ONE_BELOW_FIRST_SURROGATE_CODE_POINT => core::char::from_u32(u), FIRST_SURROGATE_CODE_POINT..=ONE_BELOW_NUMBER_OF_CHARS => { core::char::from_u32(u + NUMBER_OF_SURROGATE_CODE_POINTS) } _ => None, } } /// Increments this [`char`], skipping over the [surrogate code /// points](https://www.unicode.org/glossary/#surrogate_code_point). /// /// # Panics /// Panics if `self` is `char::MAX`. /// /// # Examples /// ``` /// use malachite_base::chars::crement::increment_char; /// /// let mut c = '\u{0}'; /// increment_char(&mut c); /// assert_eq!(c, '\u{1}'); /// /// let mut c = 'a'; /// increment_char(&mut c); /// assert_eq!(c, 'b'); /// ``` #[inline] pub const fn increment_char(c: &mut char) { *c = contiguous_range_to_char(char_to_contiguous_range(*c) + 1) .expect("Cannot increment char::MAX"); } /// Decrements this [`char`], skipping over the [surrogate code /// points](https://www.unicode.org/glossary/#surrogate_code_point). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is `'\u{0}'`. /// /// # Examples /// ``` /// use malachite_base::chars::crement::decrement_char; /// /// let mut c = '\u{1}'; /// decrement_char(&mut c); /// assert_eq!(c, '\u{0}'); /// /// let mut c = 'b'; /// decrement_char(&mut c); /// assert_eq!(c, 'a'); /// ``` #[inline] pub fn decrement_char(c: &mut char) { if *c == char::MIN { panic!("Cannot decrement char '{}'", *c); } else { *c = contiguous_range_to_char(char_to_contiguous_range(*c) - 1).unwrap(); } } ================================================ FILE: malachite-base/src/chars/exhaustive.rs ================================================ // Copyright © 2026 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 crate::chars::CharType; use crate::chars::crement::increment_char; use core::ops::RangeInclusive; /// Generates all ASCII [`char`]s, in ascending order. /// /// For a friendlier order (_e.g_. nonprintable [`char`]s coming last), try /// [`exhaustive_ascii_chars`]. /// /// The output length is 128. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::exhaustive::ascii_chars_increasing; /// /// assert_eq!( /// ascii_chars_increasing().collect::(), /// "\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\u{12}\ /// \u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f} !\"#$%&\'()*\ /// +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u{7f}" /// ); /// ``` pub const fn ascii_chars_increasing() -> RangeInclusive { char::MIN..='\u{7f}' } /// Generates all [`char`]s, in ascending order. /// /// For a friendlier order (_e.g_. nonprintable [`char`]s coming last), try [`exhaustive_chars`]. /// /// The output length is 1,112,064. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::exhaustive::chars_increasing; /// /// assert_eq!( /// chars_increasing().take(200).collect::(), /// "\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\u{12}\ /// \u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f} !\"#$%&\'()*\ /// +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u{7f}\ /// \u{80}\u{81}\u{82}\u{83}\u{84}\u{85}\u{86}\u{87}\u{88}\u{89}\u{8a}\u{8b}\u{8c}\u{8d}\u{8e}\ /// \u{8f}\u{90}\u{91}\u{92}\u{93}\u{94}\u{95}\u{96}\u{97}\u{98}\u{99}\u{9a}\u{9b}\u{9c}\u{9d}\ /// \u{9e}\u{9f}\u{a0}¡¢£¤¥¦§¨©ª«¬\u{ad}®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇ" /// ); /// ``` pub const fn chars_increasing() -> RangeInclusive { char::MIN..=char::MAX } /// Generates all [`char`]s, in a friendly order, so that more familiar [`char`]s come first. /// /// The order is /// - Lowercase ASCII letters, /// - Uppercase ASCII letters, /// - ASCII digits, /// - Graphic ASCII [`char`]s (not alphanumeric and not control), including `' '` but no other /// whitespace, /// - (only if `ascii_only` is false) Graphic Non-ASCII [`char`]s; all non-ASCII [`char`]s whose /// [`Debug`](std::fmt::Debug) representations don't start with `'\'`, /// - All remaining [`char`]s. /// /// This `struct` is created by [`exhaustive_chars`] and [`exhaustive_ascii_chars`]; see their /// documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct ExhaustiveChars { ascii_only: bool, first: bool, c: char, current_type: CharType, } impl Iterator for ExhaustiveChars { type Item = char; fn next(&mut self) -> Option { if self.first { self.first = false; } else { match self.current_type { CharType::AsciiLower => { if self.c == 'z' { self.current_type = CharType::AsciiUpper; self.c = 'A'; } else { increment_char(&mut self.c); } } CharType::AsciiUpper => { if self.c == 'Z' { self.current_type = CharType::AsciiNumeric; self.c = '0'; } else { increment_char(&mut self.c); } } CharType::AsciiNumeric => { if self.c == '9' { self.current_type = CharType::AsciiNonAlphanumericGraphic; self.c = ' '; } else { increment_char(&mut self.c); } } CharType::AsciiNonAlphanumericGraphic => { if self.c == '~' { if self.ascii_only { self.current_type = CharType::NonGraphic; self.c = '\0'; } else { self.current_type = CharType::NonAsciiGraphic; self.c = '\u{a1}'; }; } else { increment_char(&mut self.c); // No control chars between ' ' and '~' while self.c.is_ascii_alphanumeric() { increment_char(&mut self.c); } } } CharType::NonAsciiGraphic => { if self.c == '\u{33479}' { self.current_type = CharType::NonGraphic; self.c = '\0'; } else { increment_char(&mut self.c); while !CharType::NonAsciiGraphic.contains(self.c) { increment_char(&mut self.c); } } } CharType::NonGraphic => { let limit = if self.ascii_only { '\u{7f}' } else { char::MAX }; if self.c == limit { return None; } increment_char(&mut self.c); while !self.c.is_ascii_control() && (self.c.is_ascii() || CharType::NonAsciiGraphic.contains(self.c)) { increment_char(&mut self.c); } } } } Some(self.c) } } /// Generates all ASCII [`char`]s, in a friendly order, so that more familiar [`char`]s come first. /// /// The order is /// - Lowercase ASCII letters, /// - Uppercase ASCII letters, /// - ASCII digits, /// - Graphic ASCII [`char`]s (not alphanumeric and not control), including `' '` but no other /// whitespace, /// - All remaining ASCII [`char`]s. /// /// Within each group, the [`char`]s are ordered according to their usual order. /// /// If you want to generate ASCII [`char`]s in their usual order, try [`ascii_chars_increasing`]. /// /// The output length is 128. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// /// assert_eq!( /// exhaustive_ascii_chars().collect::(), /// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !\"#$%&\'()*+,-./:;<=>?@[\\\ /// ]^_`{|}~\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\ /// \u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}\u{7f}" /// ); /// ``` pub const fn exhaustive_ascii_chars() -> ExhaustiveChars { ExhaustiveChars { ascii_only: true, first: true, c: 'a', current_type: CharType::AsciiLower, } } /// Generates all [`char`]s, in a friendly order, so that more familiar [`char`]s come first. /// /// The order is /// - Lowercase ASCII letters, /// - Uppercase ASCII letters, /// - ASCII digits, /// - Graphic ASCII [`char`] (not alphanumeric and not control), including `' '` but no other /// whitespace, /// - Graphic Non-ASCII [`char`]s; all non-ASCII [`char`]s whose [`Debug`](std::fmt::Debug) /// representations don't start with `'\'`, /// - All remaining [`char`]s. /// /// Within each group, the [`char`]s are ordered according to their usual order. /// /// If you want to generate [`char`]s in their usual order, try [`chars_increasing`]. /// /// The output length is 1,112,064. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::exhaustive::exhaustive_chars; /// /// assert_eq!( /// exhaustive_chars().take(200).collect::(), /// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !\"#$%&\'()*+,-./:;<=>?@[\\\ /// ]^_`{|}~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóô\ /// õö÷øùúûüýþÿĀāĂ㥹ĆćĈĉĊ" /// ); /// ``` pub const fn exhaustive_chars() -> ExhaustiveChars { ExhaustiveChars { ascii_only: false, first: true, c: 'a', current_type: CharType::AsciiLower, } } ================================================ FILE: malachite-base/src/chars/mod.rs ================================================ // Copyright © 2026 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 crate::strings::ToDebugString; #[cfg(feature = "test_build")] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum CharType { AsciiLower, AsciiUpper, AsciiNumeric, AsciiNonAlphanumericGraphic, NonAsciiGraphic, NonGraphic, } #[cfg(not(feature = "test_build"))] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] enum CharType { AsciiLower, AsciiUpper, AsciiNumeric, AsciiNonAlphanumericGraphic, NonAsciiGraphic, NonGraphic, } fn debug_starts_with_slash(c: char) -> bool { // Skip the first `char`, which is always a single quote c.to_debug_string().chars().nth(1) == Some('\\') } /// Determines whether a [`char`] is graphic. /// /// There is an [official Unicode /// definition](https://www.unicode.org/versions/Unicode14.0.0/ch03.pdf#G30602) of _graphic /// character_, but that definition is not followed here. In Malachite, a [`char`] is considered /// graphic if it is ASCII and not a [C0 control](https://www.unicode.org/charts/PDF/U0000.pdf), or /// non-ASCII and its debug string does not begin with a backslash. This function can be used as a /// guide to whether a [`char`] can be displayed on a screen without resorting to some sort of /// escape sequence. Of course, many typefaces will not be able to render many graphic [`char`]s. /// /// The ASCII space `' '` is the only graphic whitespace [`char`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::char_is_graphic; /// /// assert_eq!(char_is_graphic('a'), true); /// assert_eq!(char_is_graphic(' '), true); /// assert_eq!(char_is_graphic('\n'), false); /// assert_eq!(char_is_graphic('ñ'), true); /// assert_eq!(char_is_graphic('\u{5f771}'), false); /// ``` pub fn char_is_graphic(c: char) -> bool { if c.is_ascii() { !c.is_ascii_control() } else { !debug_starts_with_slash(c) } } impl CharType { pub_crate_test! {contains(self, c: char) -> bool { match self { Self::AsciiLower => c.is_ascii_lowercase(), Self::AsciiUpper => c.is_ascii_uppercase(), Self::AsciiNumeric => c.is_ascii_digit(), Self::AsciiNonAlphanumericGraphic => { c.is_ascii() && !c.is_ascii_alphanumeric() && !c.is_ascii_control() } Self::NonAsciiGraphic => !c.is_ascii() && !debug_starts_with_slash(c), Self::NonGraphic => { c.is_ascii_control() || !c.is_ascii() && debug_starts_with_slash(c) } } }} } /// Constants associated with [`char`]s. /// /// Apart from the constants visibile on this page, the trait-based constants /// [`MIN`](crate::comparison::traits::Min::MIN), [`MAX`](crate::comparison::traits::Max::MAX), and /// [`NAME`](crate::named::Named::NAME) are also defined. pub mod constants; /// Functions for incrementing and decrementing [`char`]s. pub mod crement; /// Iterators that generate [`char`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`char`]s randomly. pub mod random; ================================================ FILE: malachite-base/src/chars/random.rs ================================================ // Copyright © 2026 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 crate::bools::random::{WeightedRandomBools, weighted_random_bools}; use crate::chars::char_is_graphic; use crate::chars::crement::{char_to_contiguous_range, contiguous_range_to_char, decrement_char}; use crate::num::random::{RandomUnsignedInclusiveRange, random_unsigned_inclusive_range}; use crate::random::Seed; use crate::vecs::{RandomValuesFromVec, random_values_from_vec}; /// Uniformly generates random [`char`]s in a closed interval. /// /// This `struct` is created by [`random_char_range`] and [`random_char_inclusive_range`]; see their /// documentation for more. #[derive(Clone, Debug)] pub struct RandomCharRange { chunks: RandomUnsignedInclusiveRange, } impl Iterator for RandomCharRange { type Item = char; #[inline] fn next(&mut self) -> Option { contiguous_range_to_char(self.chunks.next().unwrap()) } } /// Uniformly generates random [`char`]s in a closed interval, weighting graphic and non-graphic /// [`char`]s separately. /// /// This `struct` is created by [`graphic_weighted_random_char_range`] and /// [`graphic_weighted_random_char_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug)] pub struct WeightedGraphicRandomCharRange { xs: WeightedRandomBools, graphic: RandomValuesFromVec, non_graphic: RandomValuesFromVec, } impl Iterator for WeightedGraphicRandomCharRange { type Item = char; fn next(&mut self) -> Option { if self.xs.next().unwrap() { self.graphic.next() } else { self.non_graphic.next() } } } /// Uniformly generates random [`char`]s. /// /// $P(c) = \frac{1}{2^{20}+2^{16}-2^{11}}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::random::random_chars; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// random_chars(EXAMPLE_SEED) /// .take(10) /// .collect::() /// .as_str(), /// "\u{5f771}\u{87234}\u{bcd36}\u{9e195}\u{5da07}\u{36553}\u{45028}\u{1cdfd}\u{d8530}\u{c7f2e}" /// ) /// ``` #[inline] pub fn random_chars(seed: Seed) -> RandomCharRange { random_char_inclusive_range(seed, char::MIN, char::MAX) } /// Uniformly generates random ASCII [`char`]s. /// /// $$ /// P(c) = \\begin{cases} /// 2^{-7} & \text{if} \\quad c < \\backslash\\text{u\\{0x80\\}} \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::chars::random::random_ascii_chars; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// random_ascii_chars(EXAMPLE_SEED) /// .take(20) /// .collect::() /// .as_str(), /// "q^\u{17}bF\\4T!/\u{1}q6\n/\u{11}Y\\wB" /// ) /// ``` #[inline] pub fn random_ascii_chars(seed: Seed) -> RandomCharRange { random_char_inclusive_range(seed, char::MIN, '\u{7f}') } /// Uniformly generates random [`char`]s in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. This function cannot create a range that includes `char::MAX`; for /// that, use [`random_char_inclusive_range`]. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1} /// {\mathrm{char\\_to\\_contiguous\\_range(b)}-\mathrm{char\\_to\\_contiguous\\_range(a)}} & /// \text{if} \\quad a \leq x < b \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::chars::random::random_char_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// random_char_range(EXAMPLE_SEED, 'a', 'z') /// .take(50) /// .collect::() /// .as_str(), /// "rlewrsgkdlbeouylrelopxqkoonftexoshqulgvonioatekqes" /// ) /// ``` #[inline] pub fn random_char_range(seed: Seed, a: char, mut b: char) -> RandomCharRange { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); decrement_char(&mut b); random_char_inclusive_range(seed, a, b) } /// Uniformly generates random [`char`]s in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1} /// {\mathrm{char\\_to\\_contiguous\\_range(b)}-\mathrm{char\\_to\\_contiguous\\_range(a)} /// +1} & /// \text{if} \\quad a \leq x < b \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// random_char_inclusive_range(EXAMPLE_SEED, 'a', 'z') /// .take(50) /// .collect::() /// .as_str(), /// "rlewrsgkdlbeouylrelopxqkoonftexoshqulgvonioatekqes" /// ) /// ``` #[inline] pub fn random_char_inclusive_range(seed: Seed, a: char, b: char) -> RandomCharRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); RandomCharRange { chunks: random_unsigned_inclusive_range( seed, char_to_contiguous_range(a), char_to_contiguous_range(b), ), } } /// Generates random [`char`]s, weighting graphic and non-graphic [`char`]s separately. /// /// See [`char_is_graphic`] for the definition of a graphic [`char`]. /// /// Let $n_p$ be `p_numerator` and $d_p$ be `p_denominator`, and let $p = p_n/p_d$. /// /// The set of graphic [`char`]s is selected with probability $p$, and the set of non-graphic /// [`char`]s with probability $1-p$. Then, a [`char`] is selected uniformly from the appropriate /// set. There are 142,523 graphic [`char`]s out of 1,112,064, so we have /// /// $$ /// P(x) = \\begin{cases} /// \frac{p}{142523} & \text{if} \\quad x \\ \\text{is} \\ \\text{graphic} \\\\ /// \frac{1-p}{969541} & \\text{otherwise} /// \\end{cases} /// $$ /// /// To recover the uniform distribution, use $p = 142523/1112064$, which is roughly $1/8$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `p_denominator` is zero or `p_denominator > p_denominator`. /// /// # Examples /// ``` /// use malachite_base::chars::random::graphic_weighted_random_chars; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// graphic_weighted_random_chars(EXAMPLE_SEED, 10, 11) /// .take(20) /// .collect::() /// .as_str(), /// "𗄡𭼭礜깬ꅉ杼쭗𫆬╳𲐕𡺽⢏𲣍\u{90141}𮛊瀊𰥶\u{3a6f5}\u{d9ae0}𲛂" /// ) /// ``` #[inline] pub fn graphic_weighted_random_chars( seed: Seed, p_numerator: u64, p_denominator: u64, ) -> WeightedGraphicRandomCharRange { graphic_weighted_random_char_inclusive_range( seed, char::MIN, char::MAX, p_numerator, p_denominator, ) } /// Generates random ASCII [`char`]s, weighting graphic and non-graphic [`char`]s separately. /// /// See [`char_is_graphic`] for the definition of a graphic [`char`]. /// /// Let $n_p$ be `p_numerator` and $d_p$ be `p_denominator`, and let $p = p_n/p_d$. /// /// The set of graphic ASCII [`char`]s is selected with probability $p$, and the set of non-graphic /// ASCII [`char`]s with probability $1-p$. Then, a [`char`] is selected uniformly from the /// appropriate set. There are 95 graphic ASCII [`char`]s out of 128, so we have /// /// $$ /// P(x) = \\begin{cases} /// \frac{p}{95} & \text{if} \\quad /// x < \\backslash\\text{u\\{0x80\\}} \\ \\text{and} \\ x \\ \\text{is graphic} \\\\ /// \frac{1-p}{33} & \text{if} \\quad /// x < \\backslash\\text{u\\{0x80\\}} \\ \\text{and} \\ x \\ \\text{is not graphic} \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// To recover the uniform distribution, use $p = 95/128$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `p_denominator` is zero or `p_denominator > p_denominator`. /// /// # Examples /// ``` /// use malachite_base::chars::random::graphic_weighted_random_ascii_chars; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// graphic_weighted_random_ascii_chars(EXAMPLE_SEED, 10, 11) /// .take(40) /// .collect::() /// .as_str(), /// "x14N(bcXr$g)7\u{1b}/E+\u{8}\rf\u{2}\u{11}Y\u{11}Poo.$V2R.$V=6\u{13}\t\u{11}" /// ) /// ``` #[inline] pub fn graphic_weighted_random_ascii_chars( seed: Seed, p_numerator: u64, p_denominator: u64, ) -> WeightedGraphicRandomCharRange { graphic_weighted_random_char_inclusive_range( seed, char::MIN, '\u{7f}', p_numerator, p_denominator, ) } /// Generates random [`char`]s in the half-open interval $[a, b)$, weighting graphic and non-graphic /// [`char`]s separately. /// /// See [`char_is_graphic`] for the definition of a graphic [`char`]. /// /// Let $n_p$ be `p_numerator` and $d_p$ be `p_denominator`, and let $p = p_n/p_d$. /// /// The set of graphic [`char`]s in the specified range is selected with probability $p$, and the /// set of non-graphic [`char`]s in the range with probability $1-p$. Then, a [`char`] is selected /// uniformly from the appropriate set. /// /// $a$ must be less than $b$. Furthermore, $[a, b)$ must contain both graphic and non-graphic /// [`char`]s. This function cannot create a range that includes `char::MAX`; for that, use /// [`graphic_weighted_random_char_inclusive_range`]. /// /// Let $g$ be the number of graphic [`char`]s in $[a, b)$. Then we have /// /// $$ /// P(x) = \\begin{cases} /// \frac{p}{g} & a \leq x < b \\ \\text{and} \\ x \\ \\text{is graphic} \\\\ /// \frac{1-p}{b-a-g} & a \leq x < b \\ \\text{and} \\ x \\ \\text{is not graphic} \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// To recover the uniform distribution, use $p = g/(b-a)$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `p_denominator` is zero or `p_denominator > p_denominator`, if $a \geq b$, if $[a, b)$ /// contains no graphic [`char`]s, or if $[a, b)$ contains only graphic [`char`]s. /// /// # Examples /// ``` /// use malachite_base::chars::random::graphic_weighted_random_char_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// graphic_weighted_random_char_range(EXAMPLE_SEED, '\u{100}', '\u{400}', 10, 11) /// .take(30) /// .collect::() /// .as_str(), /// "ǘɂŜȢΙƘƣʅΰǟ˳ˊȇ\u{31b}ʰɥΈ\u{324}\u{35a}Ϟ\u{367}\u{337}ƃ\u{342}ʌμƢϳϪǰ" /// ) /// ``` #[inline] pub fn graphic_weighted_random_char_range( seed: Seed, a: char, mut b: char, p_numerator: u64, p_denominator: u64, ) -> WeightedGraphicRandomCharRange { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); decrement_char(&mut b); graphic_weighted_random_char_inclusive_range(seed, a, b, p_numerator, p_denominator) } /// Generates random [`char`]s in the closed interval $[a, b]$, weighting graphic and non-graphic /// [`char`]s separately. /// /// See [`char_is_graphic`] for the definition of a graphic [`char`]. /// /// Let $n_p$ be `p_numerator` and $d_p$ be `p_denominator`, and let $p = p_n/p_d$. /// /// The set of graphic [`char`]s in the specified range is selected with probability $p$, and the /// set of non-graphic [`char`]s in the range with probability $1-p$. Then, a [`char`] is selected /// uniformly from the appropriate set. /// /// $a$ must be less than $b$. Furthermore, $[a, b]$ must contain both graphic and non-graphic /// [`char`]s. This function cannot create a range that includes `char::MAX`; for that, use /// [`graphic_weighted_random_char_inclusive_range`]. /// /// Let $g$ be the number of graphic [`char`]s in $[a, b]$. Then we have /// /// $$ /// P(x) = \\begin{cases} /// \frac{p}{g} & a \leq x < b \\ \\text{and} \\ x \\ \\text{is graphic} \\\\ /// \frac{1-p}{b-a-g+1} & a \leq x < b \\ \\text{and} \\ x \\ \\text{is not graphic} \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// /// To recover the uniform distribution, use $p = g/(b-a+1)$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `p_denominator` is zero or `p_denominator > p_denominator`, if $a > b$, if $[a, b]$ /// contains no graphic [`char`]s, or if $[a, b]$ contains only graphic [`char`]s. /// /// # Examples /// ``` /// use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// graphic_weighted_random_char_inclusive_range(EXAMPLE_SEED, '\u{100}', '\u{3ff}', 10, 11) /// .take(30) /// .collect::() /// .as_str(), /// "ǘɂŜȢΙƘƣʅΰǟ˳ˊȇ\u{31b}ʰɥΈ\u{324}\u{35a}Ϟ\u{367}\u{337}ƃ\u{342}ʌμƢϳϪǰ" /// ) /// ``` pub fn graphic_weighted_random_char_inclusive_range( seed: Seed, a: char, b: char, p_numerator: u64, p_denominator: u64, ) -> WeightedGraphicRandomCharRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); let (graphic_chars, non_graphic_chars): (Vec<_>, Vec<_>) = (a..=b).partition(|&c| char_is_graphic(c)); assert!( !graphic_chars.is_empty(), "The range {a:?}..={b:?} contains no graphic chars" ); assert!( !non_graphic_chars.is_empty(), "The range {a:?}..={b:?} only contains graphic chars" ); WeightedGraphicRandomCharRange { xs: weighted_random_bools(seed.fork("xs"), p_numerator, p_denominator), graphic: random_values_from_vec(seed.fork("graphic"), graphic_chars), non_graphic: random_values_from_vec(seed.fork("non_graphic"), non_graphic_chars), } } ================================================ FILE: malachite-base/src/comparison/macros.rs ================================================ // Copyright © 2026 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 . /// Computes the minimum of a list of expressions. /// /// The list must be nonempty, the expressions must all have the same type, and that type must /// implement [`Ord`]. Each expression is only evaluated once. /// /// # Examples /// ``` /// use malachite_base::min; /// /// assert_eq!(min!(3), 3); /// assert_eq!(min!(3, 1), 1); /// assert_eq!(min!(3, 1, 4), 1); /// ``` #[macro_export] macro_rules! min { ($first: expr $(,$next: expr)*) => { { let mut min = $first; $( let next = $next; if next < min { min = next; } )* min } }; } /// Computes the maximum of a list of expressions. /// /// The list must be nonempty, the expressions must all have the same type, and that type must /// implement [`Ord`]. Each expression is only evaluated once. /// /// # Examples /// ``` /// use malachite_base::max; /// /// assert_eq!(max!(3), 3); /// assert_eq!(max!(3, 1), 3); /// assert_eq!(max!(3, 1, 4), 4); /// ``` #[macro_export] macro_rules! max { ($first: expr $(,$next: expr)*) => { { let mut max = $first; $( let next = $next; if next > max { max = next; } )* max } }; } ================================================ FILE: malachite-base/src/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// Macros related to comparing values. /// /// This module defines the `min` and `max` macros. #[macro_use] pub mod macros; /// Traits related to comparing values. pub mod traits; ================================================ FILE: malachite-base/src/comparison/traits.rs ================================================ // Copyright © 2026 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 . /// Defines the minimum value of a type. #[allow(clippy::declare_interior_mutable_const)] pub trait Min { /// The minimum value of `Self`. const MIN: Self; } /// Defines the maximum value of a type. #[allow(clippy::declare_interior_mutable_const)] pub trait Max { /// The maximum value of `Self`. const MAX: Self; } ================================================ FILE: malachite-base/src/iterators/bit_distributor.rs ================================================ // Copyright © 2026 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 crate::num::basic::integers::PrimitiveInt; use crate::num::logic::traits::{BitConvertible, NotAssign}; use alloc::vec::Vec; use core::fmt::Debug; const COUNTER_WIDTH: usize = u64::WIDTH as usize; /// This struct is used to configure [`BitDistributor`]s. /// /// See the [`BitDistributor`] documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct BitDistributorOutputType { weight: usize, // 0 means a tiny output_type max_bits: Option, } impl BitDistributorOutputType { /// Creates a normal output with a specified weight. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `weight` is zero. /// /// The corresponding element grows as a power of $i$. See the [`BitDistributor`] documentation /// for more. pub const fn normal(weight: usize) -> Self { assert!(weight != 0); Self { weight, max_bits: None, } } /// Creates a tiny output. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// The corresponding element grows logarithmically. See the [`BitDistributor`] documentation /// for more. pub const fn tiny() -> Self { Self { weight: 0, max_bits: None, } } } /// Helps generate tuples exhaustively. /// /// Think of `counter` as the bits of an integer. It's initialized to zero (all `false`s), and as /// it's repeatedly incremented, it eventually takes on every 64-bit value. /// /// `output_types` is a list of $n$ configuration structs that, together, specify how to generate an /// n-element tuple of unsigned integers. Calling `get_output` repeatedly, passing in 0 through $n - /// 1$ as `index`, distributes the bits of `counter` into a tuple. /// /// This is best shown with an example. If `output_types` is set to /// `[BitDistributorOutputType::normal(1); 2]`, the distributor will generate all pairs of unsigned /// integers. A pair may be extracted by calling `get_output(0)` and `get_output(1)`; then `counter` /// may be incremented to create the next pair. In this case, the pairs will be $(0, 0), (0, 1), (1, /// 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1), \ldots$. /// /// If you think of these pairs as coordinates in the $xy$-plane, they are traversed along a /// [Z-order curve](https://en.wikipedia.org/wiki/Z-order_curve). Every pair of unsigned integers /// will be generated exactly once. /// /// In general, setting `output_types` to `[BitDistributorOutputType::normal(1); n]` will generate /// $n$-tuples. The elements of the tuples will be very roughly the same size, in the sense that /// each element will grow as $O(\sqrt\[n\]{i})$, where $i$ is the counter. Sometimes we want the /// elements to grow at different rates. To accomplish this, we can change the weights of the output /// types. For example, if we set `output_types` to `[BitDistributorOutputType::normal(1), /// BitDistributorOutputType::normal(2)]`, the first element of the generated pairs will grow as /// $O(\sqrt\[3\]{i})$ and the second as $O(i^{2/3})$. In general, if the weights are $w_0, w_1, /// \\ldots, w_{n-1}$, then the $k$th element of the output tuples will grow as /// $O(i^{w_i/\sum_{j=0}^{n-1}w_j})$. /// /// Apart from creating _normal_ output types with different weights, we can create _tiny_ output /// types, which indicate that the corresponding tuple element should grow especially slowly. If /// `output_types` contains $m$ tiny output types, each tiny tuple element grows as /// $O(\sqrt\[m\]{\log i})$. The growth of the other elements is unaffected. Having only tiny types /// in `output_types` is disallowed. /// /// The above discussion of growth rates assumes that `max_bits` is not specified for any output /// type. But if `max_bits` is set to $b$, then the corresponding element will start growing just as /// if `max_bits` wasn't specified, but will stop growing once it reaches $2^b-1$. #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct BitDistributor { #[cfg(feature = "test_build")] pub output_types: Vec, #[cfg(not(feature = "test_build"))] output_types: Vec, bit_map: [usize; COUNTER_WIDTH], counter: [bool; COUNTER_WIDTH], } impl BitDistributor { fn new_without_init(output_types: &[BitDistributorOutputType]) -> Self { if output_types .iter() .all(|output_type| output_type.weight == 0) { panic!("All output_types cannot be tiny"); } Self { output_types: output_types.to_vec(), bit_map: [0; COUNTER_WIDTH], counter: [false; COUNTER_WIDTH], } } /// Creates a new [`BitDistributor`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `output_types.len()`. /// /// # Examples /// ``` /// use malachite_base::iterators::bit_distributor::{ /// BitDistributor, BitDistributorOutputType, /// }; /// /// BitDistributor::new(&[ /// BitDistributorOutputType::normal(2), /// BitDistributorOutputType::tiny(), /// ]); /// ``` pub fn new(output_types: &[BitDistributorOutputType]) -> Self { let mut distributor = Self::new_without_init(output_types); distributor.update_bit_map(); distributor } /// Returns a reference to the internal bit map as a slice. /// /// The bit map determines which output gets each bit of the counter. For example, if the bit /// map is $[0, 1, 0, 1, 0, 1, \ldots]$, then the first element of the output pair gets the bits /// with indices $0, 2, 4, \ldots$ and the second element gets the bits with indices $1, 3, 5, /// \ldots$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::bit_distributor::{ /// BitDistributor, BitDistributorOutputType, /// }; /// /// let bd = BitDistributor::new(&[ /// BitDistributorOutputType::normal(2), /// BitDistributorOutputType::tiny(), /// ]); /// assert_eq!( /// bd.bit_map_as_slice(), /// &[ /// 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /// 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /// 0, 0, 0, 0, 0, 0, 0, 1 /// ][..] /// ); /// ``` pub fn bit_map_as_slice(&self) -> &[usize] { self.bit_map.as_ref() } fn update_bit_map(&mut self) { let (mut normal_output_type_indices, mut tiny_output_type_indices): ( Vec, Vec, ) = (0..self.output_types.len()).partition(|&i| self.output_types[i].weight != 0); let mut normal_output_types_bits_used = vec![0; normal_output_type_indices.len()]; let mut tiny_output_types_bits_used = vec![0; tiny_output_type_indices.len()]; let mut ni = normal_output_type_indices.len() - 1; let mut ti = tiny_output_type_indices.len().saturating_sub(1); let mut weight_counter = self.output_types[normal_output_type_indices[ni]].weight; for i in 0..COUNTER_WIDTH { let use_normal_output_type = !normal_output_type_indices.is_empty() && (tiny_output_type_indices.is_empty() || !usize::is_power_of_two(i + 1)); if use_normal_output_type { self.bit_map[i] = normal_output_type_indices[ni]; let output_type = self.output_types[normal_output_type_indices[ni]]; normal_output_types_bits_used[ni] += 1; weight_counter -= 1; if output_type.max_bits == Some(normal_output_types_bits_used[ni]) { normal_output_type_indices.remove(ni); normal_output_types_bits_used.remove(ni); if normal_output_type_indices.is_empty() { continue; } weight_counter = 0; } if weight_counter == 0 { if ni == 0 { ni = normal_output_type_indices.len() - 1; } else { ni -= 1; } weight_counter = self.output_types[normal_output_type_indices[ni]].weight; } } else { if tiny_output_type_indices.is_empty() { self.bit_map[i] = usize::MAX; continue; } self.bit_map[i] = tiny_output_type_indices[ti]; let output_type = self.output_types[tiny_output_type_indices[ti]]; tiny_output_types_bits_used[ti] += 1; if output_type.max_bits == Some(tiny_output_types_bits_used[ti]) { tiny_output_type_indices.remove(ti); tiny_output_types_bits_used.remove(ti); if tiny_output_type_indices.is_empty() { continue; } } if ti == 0 { ti = tiny_output_type_indices.len() - 1; } else { ti -= 1; } } } } /// Sets the maximum bits for several outputs. /// /// Given slice of output indices, sets the maximum bits for each of the outputs and rebuilds /// the bit map. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `output_type_indices.len()`. /// /// # Panics /// Panics if `max_bits` is 0 or if any index is greater than or equal to /// `self.output_types.len()`. /// /// # Examples /// ``` /// use malachite_base::iterators::bit_distributor::{ /// BitDistributor, BitDistributorOutputType, /// }; /// /// let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(2); 3]); /// assert_eq!( /// bd.bit_map_as_slice(), /// &[ /// 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, /// 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, /// 1, 1, 0, 0, 2, 2, 1, 1 /// ][..] /// ); /// /// bd.set_max_bits(&[0, 2], 5); /// assert_eq!( /// bd.bit_map_as_slice(), /// &[ /// 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /// 1, 1, 1, 1, 1, 1, 1, 1 /// ][..] /// ); /// ``` pub fn set_max_bits(&mut self, output_type_indices: &[usize], max_bits: usize) { assert_ne!(max_bits, 0); for &index in output_type_indices { self.output_types[index].max_bits = Some(max_bits); } self.update_bit_map(); } /// Increments the counter in preparation for a new set of outputs. /// /// If the counter is incremented $2^{64}$ times, it rolls back to 0. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::bit_distributor::{ /// BitDistributor, BitDistributorOutputType, /// }; /// /// let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(1)]); /// let mut outputs = Vec::new(); /// for _ in 0..20 { /// outputs.push(bd.get_output(0)); /// bd.increment_counter(); /// } /// assert_eq!( /// outputs, /// &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] /// ); /// ``` pub fn increment_counter(&mut self) { for b in &mut self.counter { b.not_assign(); if *b { break; } } } /// Gets the output at a specified index. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `index` is greater than or equal to `self.output_types.len()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::bit_distributor::{ /// BitDistributor, BitDistributorOutputType, /// }; /// /// let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]); /// let mut outputs = Vec::new(); /// for _ in 0..10 { /// outputs.push((0..2).map(|i| bd.get_output(i)).collect_vec()); /// bd.increment_counter(); /// } /// let expected_outputs: &[&[usize]] = &[ /// &[0, 0], /// &[0, 1], /// &[1, 0], /// &[1, 1], /// &[0, 2], /// &[0, 3], /// &[1, 2], /// &[1, 3], /// &[2, 0], /// &[2, 1], /// ]; /// assert_eq!(outputs, expected_outputs); /// ``` pub fn get_output(&self, index: usize) -> usize { assert!(index < self.output_types.len()); usize::from_bits_asc( self.bit_map .iter() .zip(self.counter.iter()) .filter_map(|(&m, &c)| if m == index { Some(c) } else { None }), ) } } ================================================ FILE: malachite-base/src/iterators/comparison.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; /// An iterator that generates the [`Ordering`]s of adjacent elements of a given iterator. /// /// This `struct` is created by [`delta_directions`]; see its documentation for more. #[derive(Clone, Debug)] pub struct DeltaDirections where I::Item: Ord, { previous: Option, xs: I, } impl Iterator for DeltaDirections where I::Item: Ord, { type Item = Ordering; fn next(&mut self) -> Option { if self.previous.is_none() { if let Some(x) = self.xs.next() { self.previous = Some(x); } else { return None; } } self.xs.next().and_then(|x| { let result = Some(x.cmp(self.previous.as_ref().unwrap())); self.previous = Some(x); result }) } } /// Returns an iterator that generates the [`Ordering`]s of adjacent pairs of elements of a given /// iterator. /// /// To put it another way (at least for types where subtraction is defined), the returned iterator /// produces the signs of the finite differences of the input iterator. /// /// $f((x_k)_{k=0}^N) = (\\operatorname{cmp}(x_k, x\_{k-1}))\_{k=1}^N$, where $N$ may be $\infty$. /// /// The output length is infinite if `xs` is infinite, or $\max(n - 1, 0)$ otherwise, where $n$ is /// `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::comparison::delta_directions; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// delta_directions([3, 1, 4, 1, 5, 9].into_iter()).collect_vec(), /// &[Less, Greater, Less, Greater, Greater] /// ) /// ``` #[inline] pub const fn delta_directions(xs: I) -> DeltaDirections where I::Item: Ord, { DeltaDirections { previous: None, xs } } /// Determines whether each element of an iterator is greater than the preceding one. /// /// This function will hang if given an infinite strictly ascending iterator. /// /// $$ /// f((x_k)\_{k=0}^N) = \\bigwedge\_{k=1}^N{x\_k > x\_{k-1}}, /// $$ /// where $N$ may be $\infty$. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_strictly_ascending; /// /// assert_eq!(is_strictly_ascending([1, 2, 3, 4].into_iter()), true); /// assert_eq!(is_strictly_ascending([1, 2, 2, 4].into_iter()), false); /// ``` #[inline] pub fn is_strictly_ascending(xs: I) -> bool where I::Item: Ord, { delta_directions(xs).all(|x| x == Greater) } /// Determines whether each element of an iterator is less than the preceding one. /// /// This function will hang if given an infinite strictly descending iterator. /// /// $$ /// f((x_k)\_{k=0}^N) = \\bigwedge\_{k=1}^N{x\_k < x\_{k-1}}, /// $$ /// where $N$ may be $\infty$. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_strictly_descending; /// /// assert_eq!(is_strictly_descending([4, 3, 2, 1].into_iter()), true); /// assert_eq!(is_strictly_descending([4, 2, 2, 1].into_iter()), false); /// ``` #[inline] pub fn is_strictly_descending(xs: I) -> bool where I::Item: Ord, { delta_directions(xs).all(|x| x == Less) } /// Determines whether each element of an iterator is greater than or equal to the preceding one. /// /// This function will hang if given an infinite weakly ascending iterator. /// /// $$ /// f((x_k)\_{k=0}^N) = \\bigwedge\_{k=1}^N{x\_k \geq x\_{k-1}}, /// $$ /// where $N$ may be $\infty$. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_weakly_ascending; /// /// assert_eq!(is_weakly_ascending([1, 2, 3, 4].into_iter()), true); /// assert_eq!(is_weakly_ascending([1, 2, 2, 4].into_iter()), true); /// assert_eq!(is_weakly_ascending([1, 3, 2, 4].into_iter()), false); /// ``` #[inline] pub fn is_weakly_ascending(xs: I) -> bool where I::Item: Ord, { delta_directions(xs).all(|x| x != Less) } /// Determines whether each element of an iterator is less than or equal to the preceding one. /// /// This function will hang if given an infinite weakly descending iterator. /// /// $$ /// f((x_k)\_{k=0}^N) = \\bigwedge\_{k=1}^N{x\_k \leq x\_{k-1}}, /// $$ /// where $N$ may be $\infty$. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_weakly_descending; /// /// assert_eq!(is_weakly_descending([4, 3, 2, 1].into_iter()), true); /// assert_eq!(is_weakly_descending([4, 2, 2, 1].into_iter()), true); /// assert_eq!(is_weakly_descending([4, 2, 3, 1].into_iter()), false); /// ``` #[inline] pub fn is_weakly_descending(xs: I) -> bool where I::Item: Ord, { delta_directions(xs).all(|x| x != Greater) } /// Determines whether the sequence strictly zigzags. /// /// A strictly zigzagging sequence is one where every odd-indexed element is greater than its /// even-indexed neighbors, or one where every odd-indexed element is less than its even-indexed /// neighbors. /// /// This function will hang if given an infinite strictly zigzagging iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_strictly_zigzagging; /// /// assert_eq!(is_strictly_zigzagging([1, 2, 3, 4].into_iter()), false); /// assert_eq!(is_strictly_zigzagging([4, 3, 2, 1].into_iter()), false); /// assert_eq!(is_strictly_zigzagging([1, 3, 2, 4].into_iter()), true); /// assert_eq!(is_strictly_zigzagging([1, 2, 2, 4].into_iter()), false); /// ``` pub fn is_strictly_zigzagging(xs: I) -> bool where I::Item: Ord, { let mut previous = None; for direction in delta_directions(xs) { if direction == Equal { return false; } if let Some(previous) = previous && direction == previous { return false; } previous = Some(direction); } true } /// Determines whether the sequence weakly zigzags. /// /// A weakly zigzagging sequence is one where every odd-indexed element is greater than or equal to /// its even-indexed neighbors, or one where every odd-indexed element is less than or equal to its /// even-indexed neighbors. /// /// This function will hang if given an infinite strictly zigzagging iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::comparison::is_weakly_zigzagging; /// /// assert_eq!(is_weakly_zigzagging([1, 2, 3, 4].into_iter()), false); /// assert_eq!(is_weakly_zigzagging([4, 3, 2, 1].into_iter()), false); /// assert_eq!(is_weakly_zigzagging([1, 3, 2, 4].into_iter()), true); /// assert_eq!(is_weakly_zigzagging([1, 2, 2, 4].into_iter()), true); /// ``` pub fn is_weakly_zigzagging(xs: I) -> bool where I::Item: Ord, { let mut previous = None; for direction in delta_directions(xs) { if let Some(previous) = &mut previous { if direction == *previous { return false; } *previous = previous.reverse(); } else if direction != Equal { previous = Some(direction); } } true } ================================================ FILE: malachite-base/src/iterators/iterator_cache.rs ================================================ // Copyright © 2026 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 alloc::vec::Vec; /// Remembers values produced by an iterator. /// /// After wrapping an iterator with an `IteratorCache`, you can retrieve a reference to the $n$th /// element of an iterator, and then retrieve a reference to the $m$th element in constant time for /// any $m \leq n$ (not counting the time it took to first get the $n$th element). #[derive(Clone, Debug)] pub struct IteratorCache { xs: I, cache: Vec, done: bool, } impl IteratorCache { /// Creates a new `IteratorCache`. /// /// This function does not allocate any memory or advance the iterator. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// /// IteratorCache::new([1, 2, 3].iter()); /// ``` pub const fn new(xs: I) -> Self { Self { xs, cache: Vec::new(), done: false, } } /// Retrieves the $n$th element of an iterator. Indexing starts at 0. /// /// If the index is higher than any other previously-requested index, the iterator is advanced /// to that index, or until it runs out. If the iterator has previously been advanced past the /// index, the requested element is returned from the cache in constant time. If the iterator is /// too short to have an element at the index, `None` is returned. /// /// If you know that the element is present, and want to only take an immutable reference to /// `self`, consider using [`assert_get`](Self::assert_get) instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is 1 if `get` has previously been /// called with an index at least this large, or `index` otherwise. /// /// # Examples /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// /// let mut xs = IteratorCache::new([1, 2, 3].iter().cloned()); /// assert_eq!(xs.get(1), Some(&2)); /// assert_eq!(xs.get(0), Some(&1)); /// assert_eq!(xs.get(3), None); /// assert_eq!(xs.get(2), Some(&3)); /// ``` pub fn get(&mut self, index: usize) -> Option<&I::Item> { if !self.done && index >= self.cache.len() { self.cache .extend((&mut self.xs).take(index - self.cache.len() + 1)); if index >= self.cache.len() { self.done = true; return None; } } self.cache.get(index) } /// Retrieves the $n$th element of an iterator, while asserting that the iterator has already /// reached that element. Indexing starts at 0. /// /// If the iterator has not advanced that far, or if it has fewer than $n + 1$ elements, this /// function panics. /// /// The purpose of this function is to allow the caller to get an element immutably, assuming /// that the caller knows that the element is present. The [`get`](Self::get) function has to /// take a mutable reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// /// let mut xs = IteratorCache::new([1, 2, 3].iter().cloned()); /// // Force the iterator to iterate to completion /// xs.get(3); /// assert_eq!(xs.assert_get(1), &2); /// assert_eq!(xs.assert_get(0), &1); /// assert_eq!(xs.assert_get(2), &3); /// ``` pub fn assert_get(&self, index: usize) -> &I::Item { self.cache.get(index).unwrap() } /// Returns the total number of elements in the iterator, if the iterator has been completely /// consumed. /// /// If the iterator has not been completely consumed yet, returns `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// /// let mut xs = IteratorCache::new([1, 2, 3].iter().cloned()); /// assert_eq!(xs.known_len(), None); /// assert_eq!(xs.get(1), Some(&2)); /// assert_eq!(xs.known_len(), None); /// assert_eq!(xs.get(0), Some(&1)); /// assert_eq!(xs.get(3), None); /// assert_eq!(xs.known_len(), Some(3)); /// assert_eq!(xs.get(2), Some(&3)); /// ``` pub const fn known_len(&self) -> Option { if self.done { Some(self.cache.len()) } else { None } } } ================================================ FILE: malachite-base/src/iterators/mod.rs ================================================ // Copyright © 2026 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 . #[cfg(feature = "random")] use crate::bools::random::{WeightedRandomBools, weighted_random_bools}; use crate::num::arithmetic::traits::Parity; use crate::num::basic::traits::Zero; #[cfg(feature = "random")] use crate::random::Seed; #[cfg(feature = "random")] use crate::vecs::{RandomValuesFromVec, random_values_from_vec}; use alloc::collections::VecDeque; use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::fmt::Display; use core::hash::Hash; use hashbrown::HashSet; use itertools::Itertools; /// Generates all the nonzero values of a provided iterator. /// /// This `struct` is created by [`nonzero_values`]; see its documentation for more. #[derive(Clone, Debug)] pub struct NonzeroValues(I) where I::Item: PartialEq + Zero; impl Iterator for NonzeroValues where I::Item: PartialEq + Zero, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { loop { let x = self.0.next(); if x != Some(I::Item::ZERO) { return x; } } } } impl DoubleEndedIterator for NonzeroValues where I::Item: PartialEq + Zero, { #[inline] fn next_back(&mut self) -> Option { loop { let x = self.0.next_back(); if x != Some(I::Item::ZERO) { return x; } } } } /// Returns an iterator that generates all the nonzero values of a provided iterator. /// /// `nonzero_values(xs)` generates the same values as `xs.filter(|x| x != I::Item::ZERO)`, but its /// type is easier to work with. /// /// This iterator will hang if given an iterator that produces an infinite suffix of zeros. /// /// The output length is the number of nonzero values produced by `xs`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::nonzero_values; /// /// assert_eq!( /// nonzero_values([-3i8, -2, -1, 0, 1, 2, 3].iter().cloned()).collect_vec(), /// &[-3, -2, -1, 1, 2, 3] /// ) /// ``` #[inline] pub const fn nonzero_values(xs: I) -> NonzeroValues where I::Item: PartialEq + Zero, { NonzeroValues(xs) } /// Returns whether all of the values generated by an iterator are equal. /// /// `is_constant(xs)` is equivalent to `xs.unique().count() == 1` for finite nonempty iterators, but /// is more efficient, doesn't require [`Clone`] or [`Hash`] implementations, and doesn't hang if /// provided an infinite non-constant iterator. /// /// This function will hang if given an infinite constant iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::is_constant; /// /// assert_eq!(is_constant([1; 4].iter()), true); /// assert_eq!(is_constant([1, 2, 3, 4].iter()), false); /// assert_eq!(is_constant(0..), false); /// ``` pub fn is_constant(xs: I) -> bool where I::Item: Eq, { let mut first = None; for x in xs { if let Some(ref first) = first { if x != *first { return false; } } else { first = Some(x); } } true } /// Returns whether an iterator returns at least some number of values. /// /// `count_is_at_least(xs, n)` is equivalent to `xs.count() >= n` for finite iterators, but doesn't /// hang if provided an infinite iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::count_is_at_least; /// /// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 3), true); /// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 4), true); /// assert_eq!(count_is_at_least([1, 2, 3, 4].iter(), 5), false); /// assert_eq!(count_is_at_least(0.., 5), true); /// ``` #[inline] pub fn count_is_at_least(xs: I, n: usize) -> bool { xs.take(n).count() == n } /// Returns whether an iterator returns at most some number of values. /// /// `count_is_at_most(xs, n)` is equivalent to `xs.count() <= n` for finite iterators, but doesn't /// hang if provided an infinite iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::count_is_at_most; /// /// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 3), false); /// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 4), true); /// assert_eq!(count_is_at_most([1, 2, 3, 4].iter(), 5), true); /// assert_eq!(count_is_at_most(0.., 5), false); /// ``` #[inline] pub fn count_is_at_most(xs: I, n: usize) -> bool { xs.take(n + 1).count() <= n } /// Returns whether an iterator never returns the same value twice. /// /// `is_unique(xs)` is equivalent to `xs.unique().count() <= 1` for finite iterators, but is more /// efficient and doesn't hang if provided a non-unique infinite iterator. /// /// This iterator will hang if given an infinite unique iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::is_unique; /// /// let empty: [u32; 0] = []; /// assert_eq!(is_unique(empty.iter()), true); /// assert_eq!(is_unique([1, 2, 3, 4].iter()), true); /// assert_eq!(is_unique([1, 2, 3, 1].iter()), false); /// assert_eq!(is_unique((0..).map(|i| i / 2)), false); /// ``` #[inline] pub fn is_unique(xs: I) -> bool where I::Item: Eq + Hash, { let mut set = HashSet::new(); for x in xs { if !set.insert(x) { return false; } } true } /// Returns the first and last elements of an iterator, or `None` if it is empty. /// /// The iterator's elements must be cloneable, since if the iterator consists of a single element /// `x`, the result will be `(x, x)`. /// /// This iterator will hang if given an infinite iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::first_and_last; /// /// let empty: [u32; 0] = []; /// assert_eq!(first_and_last(&mut empty.iter()), None); /// assert_eq!(first_and_last(&mut [1].iter().cloned()), Some((1, 1))); /// assert_eq!(first_and_last(&mut [1, 2, 3].iter().cloned()), Some((1, 3))); /// ``` pub fn first_and_last(xs: &mut I) -> Option<(I::Item, I::Item)> where I::Item: Clone, { xs.next().map(|first| { if let Some(last) = xs.last() { (first, last) } else { (first.clone(), first) } }) } /// Groups elements of an iterator into intervals of adjacent elements that match a predicate. The /// endpoints of each interval are returned. /// /// The intervals are inclusive. /// /// This iterator will hang if given an infinite iterator. /// /// # Examples /// ``` /// use malachite_base::iterators::matching_intervals_in_iterator; /// /// let xs = &[1, 2, 10, 11, 12, 7, 8, 16, 5]; /// assert_eq!( /// matching_intervals_in_iterator(xs.iter().cloned(), |&x| x >= 10).as_slice(), /// &[(10, 12), (16, 16)] /// ); /// assert_eq!( /// matching_intervals_in_iterator(xs.iter().cloned(), |&x| x < 10).as_slice(), /// &[(1, 2), (7, 8), (5, 5)] /// ); /// ``` pub fn matching_intervals_in_iterator bool>( xs: I, predicate: F, ) -> Vec<(I::Item, I::Item)> where I::Item: Clone, { xs.chunk_by(predicate) .into_iter() .filter_map(|(b, mut group)| if b { first_and_last(&mut group) } else { None }) .collect() } #[cfg(feature = "random")] /// An iterator that randomly produces another iterator's values, or produces a special value. /// /// This `struct` is created by [`with_special_value`]; see its documentation for more. #[derive(Clone, Debug)] pub struct WithSpecialValue where I::Item: Clone, { bs: WeightedRandomBools, special_value: I::Item, xs: I, } #[cfg(feature = "random")] impl Iterator for WithSpecialValue where I::Item: Clone, { type Item = I::Item; fn next(&mut self) -> Option { if self.bs.next().unwrap() { Some(self.special_value.clone()) } else { self.xs.next() } } } #[cfg(feature = "random")] /// An iterator that randomly produces another iterator's values, or produces a special value. /// /// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$. /// /// Every time a value is to be generated, the iterator returns the special value with probability /// $p$, or else returns a value from the inner iterator. /// /// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`. /// /// # Panics /// Panics if `p_denominator` is 0 or `p_numerator` is greater than `p_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::{prefix_to_string, with_special_value}; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// with_special_value(EXAMPLE_SEED, -1i16, 1, 2, &random_primitive_ints::), /// 20 /// ), /// "[-1, -1, -1, 2901, -1, -14200, -1, -1, -1, -30997, -8245, -5338, -1, -1, -20007, -1, -1, \ /// -1, -1, -1, ...]" /// ); /// ``` pub fn with_special_value( seed: Seed, special_value: I::Item, p_numerator: u64, p_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> WithSpecialValue where I::Item: Clone, { WithSpecialValue { bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator), special_value, xs: xs_gen(seed.fork("xs")), } } #[cfg(feature = "random")] /// An iterator that randomly produces another iterator's values, or samples from a [`Vec`] of /// special values. /// /// This `struct` is created by [`with_special_values`]; see its documentation for more. #[derive(Clone, Debug)] pub struct WithSpecialValues where I::Item: Clone, { bs: WeightedRandomBools, special_values: RandomValuesFromVec, xs: I, } #[cfg(feature = "random")] impl Iterator for WithSpecialValues where I::Item: Clone, { type Item = I::Item; fn next(&mut self) -> Option { if self.bs.next().unwrap() { self.special_values.next() } else { self.xs.next() } } } #[cfg(feature = "random")] /// An iterator that randomly produces another iterator's values, or produces a random special value /// from a [`Vec`]. /// /// Let $n_p$ be `p_numerator`, $d_p$ be `p_denominator`, and let $p=n_p/d_p$. /// /// Every time a value is to be generated, the iterator uniformly samples the special values [`Vec`] /// with probability $p$, or else returns a value from the inner iterator. /// /// If $p > 0$, the output length is infinite. Otherwise, it is the same as the length of `xs`. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `special_values` is empty, `p_denominator` is 0, or if `p_numerator` is greater than /// `p_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::{prefix_to_string, with_special_values}; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// with_special_values( /// EXAMPLE_SEED, /// vec![1, 2, 3], /// 1, /// 2, /// &random_primitive_ints:: /// ), /// 20, /// ), /// "[3, 1, 3, 2901, 1, -14200, 2, 3, 1, -30997, -8245, -5338, 1, 1, -20007, 3, 1, 1, 1, 1, \ /// ...]" /// ); /// ``` pub fn with_special_values( seed: Seed, special_values: Vec, p_numerator: u64, p_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> WithSpecialValues where I::Item: Clone, { WithSpecialValues { bs: weighted_random_bools(seed.fork("bs"), p_numerator, p_denominator), special_values: random_values_from_vec(seed.fork("special_values"), special_values), xs: xs_gen(seed.fork("xs")), } } /// Generates sliding windows of elements from an iterator. /// /// This `struct` is created by [`iter_windows`]; see its documentation for more. #[derive(Clone, Debug)] pub struct IterWindows where I::Item: Clone, { xs: I, window: VecDeque, window_size: usize, } impl Iterator for IterWindows where I::Item: Clone, { type Item = VecDeque; fn next(&mut self) -> Option> { if self.window.len() < self.window_size { self.window = (&mut self.xs).take(self.window_size).collect(); if self.window.len() < self.window_size { None } else { Some(self.window.clone()) } } else { let x = self.xs.next()?; self.window.pop_front(); self.window.push_back(x); Some(self.window.clone()) } } } /// Returns windows of $n$ adjacent elements of an iterator, advancing the window by 1 in each /// iteration. The values are cloned each time a new window is generated. /// /// The output length is $n - k + 1$, where $n$ is `xs.count()` and $k$ is `window_size`. /// /// # Panics /// Panics if `window_size` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::iter_windows; /// /// let xs = 0..=5; /// let windows = iter_windows(3, xs) /// .map(|ws| ws.iter().cloned().collect_vec()) /// .collect_vec(); /// assert_eq!( /// windows.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[&[0, 1, 2], &[1, 2, 3], &[2, 3, 4], &[3, 4, 5]] /// ); /// ``` pub fn iter_windows(window_size: usize, xs: I) -> IterWindows where I::Item: Clone, { assert_ne!(window_size, 0); IterWindows { xs, window: VecDeque::with_capacity(window_size), window_size, } } /// Converts a prefix of an iterator to a string. /// /// Suppose the iterator generates $(a, b, c, d)$. If `max_len` is 3, this function will return the /// string `"[a, b, c, ...]"`. If `max_len` is 4 or more, this function will return `[a, b, c, d]`. /// /// This function will attempt to advance the iterator `max_len + 1` times. The extra time is used /// determine whether the output string should contain an ellipsis. /// /// # Panics /// Panics if `max_len` is 0. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// /// assert_eq!(prefix_to_string(0..10, 3), "[0, 1, 2, ...]"); /// assert_eq!(prefix_to_string(0..4, 5), "[0, 1, 2, 3]"); /// ``` pub fn prefix_to_string(mut xs: I, max_len: usize) -> String where I::Item: Display, { assert_ne!(max_len, 0); let mut s = String::new(); s.push('['); let mut first = true; let mut done = false; for _ in 0..max_len { if let Some(x) = xs.next() { if first { first = false; } else { s.push_str(", "); } s.push_str(&x.to_string()); } else { done = true; break; } } if !done && xs.next().is_some() { s.push_str(", ..."); } s.push(']'); s } /// An iterator that generates the Thue-Morse sequence. See [`thue_morse_sequence`] for more /// information. #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct ThueMorseSequence(u64); impl Iterator for ThueMorseSequence { type Item = bool; fn next(&mut self) -> Option { let b = self.0.count_ones().odd(); self.0 += 1; Some(b) } } /// Returns an iterator that generates the Thue-Morse sequence. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::thue_morse_sequence; /// /// let s: String = thue_morse_sequence() /// .take(100) /// .map(|b| if b { '1' } else { '0' }) /// .collect(); /// assert_eq!( /// s, /// "01101001100101101001011001101001100101100110100101101001100101101001011001101001011010011\ /// 00101100110" /// ) /// ``` #[inline] pub const fn thue_morse_sequence() -> ThueMorseSequence { ThueMorseSequence(0) } /// Contains [`BitDistributor`](bit_distributor::BitDistributor), which helps generate tuples /// exhaustively. pub mod bit_distributor; /// Functions that compare adjacent iterator elements. pub mod comparison; /// Contains [`IteratorCache`](iterator_cache::IteratorCache), which remembers values produced by an /// iterator. pub mod iterator_cache; ================================================ FILE: malachite-base/src/lib.rs ================================================ // Copyright © 2026 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 . //! This crate contains many utilities that are used by the //! [`malachite-nz`](https://docs.rs/malachite-nz/latest/malachite_nz/) and //! [`malachite-q`]((https://docs.rs/malachite-q/latest/malachite_q/)) crates. These utilities //! include //! - Traits that wrap functions from the standard library, like //! [`CheckedAdd`](num::arithmetic::traits::CheckedAdd). //! - Traits that give extra functionality to primitive types, like //! [`Gcd`](num::arithmetic::traits::Gcd), [`FloorSqrt`](num::arithmetic::traits::FloorSqrt), and //! [`BitAccess`](num::logic::traits::BitAccess). //! - Iterator-producing functions that let you generate values for testing. Here's an example of //! an iterator that produces all pairs of [`u32`]s: //! ``` //! use malachite_base::num::exhaustive::exhaustive_unsigneds; //! use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single; //! //! let mut pairs = exhaustive_pairs_from_single(exhaustive_unsigneds::()); //! assert_eq!( //! pairs.take(20).collect::>(), //! &[ //! (0, 0), (0, 1), (1, 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1), //! (3, 0), (3, 1), (2, 2), (2, 3), (3, 2), (3, 3), (0, 4), (0, 5), (1, 4), (1, 5) //! ] //! ); //! ``` //! - The [`RoundingMode`](rounding_modes::RoundingMode) enum, which allows you to specify the //! rounding behavior of various functions. //! - The [`NiceFloat`](num::float::NiceFloat) wrapper, which provides alternative implementations //! of [`Eq`], [`Ord`], and [`Display`](std::fmt::Display) for floating-point values which are in //! some ways nicer than the defaults. //! //! # Demos and benchmarks //! This crate comes with a `bin` target that can be used for running demos and benchmarks. //! - Almost all of the public functions in this crate have an associated demo. Running a demo //! shows you a function's behavior on a large number of inputs. For example, to demo the //! [`mod_pow`](num::arithmetic::traits::ModPow::mod_pow) function on [`u32`]s, you can use the //! following command: //! ```text //! cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_mod_pow_u32 //! ``` //! This command uses the `exhaustive` mode, which generates every possible input, generally //! starting with the simplest input and progressing to more complex ones. Another mode is //! `random`. The `-l` flag specifies how many inputs should be generated. //! - You can use a similar command to run benchmarks. The following command benchmarks various //! GCD algorithms for [`u64`]s: //! ```text //! cargo run --features bin_build --release -- -l 1000000 -m random -b \ //! benchmark_gcd_algorithms_u64 -o gcd-bench.gp //! ``` //! This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like //! so: //! ```text //! gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg //! ``` //! //! The list of available demos and benchmarks is not documented anywhere; you must find them by //! browsing through //! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-base/src/bin_util/demo_and_bench). //! //! # Features //! - `test_build`: A large proportion of the code in this crate is only used for testing. For a //! typical user, building this code would result in an unnecessarily long compilation time and //! an unnecessarily large binary. Much of it is also used for testing //! [`malachite-nz`](https://docs.rs/malachite-nz/latest/malachite_nz/) and //! [`malachite-q`](https://docs.rs/malachite-q/latest/malachite_q/), so it can't just be //! confined to the `tests` directory. My solution is to only build this code when the //! `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`. //! However, doctests don't require it, since they only test the public interface. //! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also //! takes a long time to build. Enabling this feature also enables `test_build`. #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #![cfg_attr( not(any(feature = "test_build", feature = "random", feature = "std")), no_std )] #[macro_use] extern crate alloc; #[cfg(feature = "test_build")] #[doc(hidden)] #[inline] pub fn fail_on_untested_path(message: &str) { panic!("Untested path. {message}"); } #[cfg(not(feature = "test_build"))] #[doc(hidden)] #[inline] pub const fn fail_on_untested_path(_message: &str) {} // TODO links for malachite-nz and malachite-q /// The [`Named`](named::Named) trait, for getting a type's name. #[macro_use] pub mod named; #[doc(hidden)] #[macro_use] pub mod macros; /// Functions for working with [`bool`]s. #[macro_use] pub mod bools; /// Functions for working with [`char`]s. #[macro_use] pub mod chars; /// Macros and traits related to comparing values. pub mod comparison; /// Functions and adaptors for iterators. pub mod iterators; /// [`Never`](nevers::Never), a type that cannot be instantiated. pub mod nevers; /// Functions for working with primitive integers and floats. #[macro_use] pub mod num; /// Functions for working with [`Ordering`](std::cmp::Ordering)s. pub mod options; /// Functions for working with [`Option`]s. pub mod orderings; #[cfg(feature = "random")] /// Functions for generating random values. pub mod random; /// [`RationalSequence`](rational_sequences::RationalSequence), a type representing a sequence that /// is finite or eventually repeating, just like the digits of a rational number. pub mod rational_sequences; /// [`RoundingMode`](rounding_modes::RoundingMode), an enum used to specify rounding behavior. pub mod rounding_modes; /// Functions for working with [`HashSet`](std::collections::HashSet)s and /// [`BTreeSet`](std::collections::BTreeSet)s. pub mod sets; /// Functions for working with slices. #[macro_use] pub mod slices; /// Functions for working with [`String`]s. pub mod strings; /// Functions for working with tuples. pub mod tuples; /// Unions (sum types). These are essentially generic enums. /// /// # unwrap /// ``` /// use malachite_base::union_struct; /// use malachite_base::unions::UnionFromStrError; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// /// let mut u: Union3; /// /// u = Union3::A('a'); /// assert_eq!(u.unwrap(), 'a'); /// /// u = Union3::B('b'); /// assert_eq!(u.unwrap(), 'b'); /// /// u = Union3::C('c'); /// assert_eq!(u.unwrap(), 'c'); /// ``` /// /// # fmt /// ``` /// use malachite_base::union_struct; /// use malachite_base::unions::UnionFromStrError; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// /// let mut u: Union3; /// /// u = Union3::A('a'); /// assert_eq!(u.to_string(), "A(a)"); /// /// u = Union3::B(5); /// assert_eq!(u.to_string(), "B(5)"); /// /// u = Union3::C(false); /// assert_eq!(u.to_string(), "C(false)"); /// ``` /// /// # from_str /// ``` /// use malachite_base::union_struct; /// use malachite_base::unions::UnionFromStrError; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// /// let u3: Union3 = Union3::from_str("B(5)").unwrap(); /// assert_eq!(u3, Union3::B(5)); /// /// let result: Result, _> = Union3::from_str("xyz"); /// assert_eq!(result, Err(UnionFromStrError::Generic("xyz".to_string()))); /// /// let result: Result, _> = Union3::from_str("A(ab)"); /// if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result { /// } else { /// panic!("wrong error variant") /// } /// ``` pub mod unions; /// Functions for working with [`Vec`]s. pub mod vecs; #[cfg(feature = "test_build")] pub mod test_util; pub mod platform; ================================================ FILE: malachite-base/src/macros/mod.rs ================================================ // Copyright © 2026 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 . #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub fn $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* fn $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_crate_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub fn $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_crate_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub(crate) fn $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_test_struct { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub struct $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_test_struct { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub struct $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_crate_test_struct { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub struct $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_crate_test_struct { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub(crate) struct $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_const_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub const fn $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_const_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* const fn $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_const_crate_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub const fn $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_const_crate_test { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub(crate) const fn $name $( $body )* }; } #[doc(hidden)] #[cfg(feature = "test_build")] #[macro_export] macro_rules! pub_const_crate_test_const { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub const $name $( $body )* }; } #[doc(hidden)] #[cfg(not(feature = "test_build"))] #[macro_export] macro_rules! pub_const_crate_test_const { ($( #[$meta:meta] )* $name:ident $( $body:tt )*) => { $( #[$meta] )* pub(crate) const $name $( $body )* }; } ================================================ FILE: malachite-base/src/named/mod.rs ================================================ // Copyright © 2026 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 . /// Defines the name of a type. This is useful for constructing error messages in a generic /// function. pub trait Named { /// The name of `Self`. const NAME: &'static str; } /// Automatically implements [`Named`] for a type. /// /// It doesn't work very well for types whose names contain several tokens, like `(u8, u8)`, `&str`, /// or `Vec`. /// /// # Examples /// ``` /// use malachite_base::named::Named; /// /// assert_eq!(u8::NAME, "u8"); /// assert_eq!(String::NAME, "String"); /// ``` #[macro_export] macro_rules! impl_named { ($t:ident) => { impl Named for $t { /// The name of this type, as given by the [`stringify`] macro. /// /// See the documentation for [`impl_named`] for more details. const NAME: &'static str = stringify!($t); } }; } ================================================ FILE: malachite-base/src/nevers/mod.rs ================================================ // Copyright © 2026 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 core::fmt::{Display, Formatter}; use core::iter::{Empty, empty}; use core::str::FromStr; /// `Never` is a type that cannot be instantiated. /// /// This is a [bottom type](https://en.wikipedia.org/wiki/Bottom_type). /// /// # Examples /// ``` /// use malachite_base::nevers::Never; /// /// let _x: Option = None; /// ``` #[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] pub enum Never {} impl Display for Never { /// Would convert a [`Never`] to a [`String`]. fn fmt(&self, _f: &mut Formatter) -> core::fmt::Result { unreachable!() } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct NeverError; impl FromStr for Never { type Err = NeverError; /// Would convert a [`String`] to a [`Never`]. /// /// Since a [`Never`] can never be instantiated, `from_str` never succeeds. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::nevers::{Never, NeverError}; /// use std::str::FromStr; /// /// assert_eq!(Never::from_str("abc"), Err(NeverError)); /// ``` #[inline] fn from_str(_: &str) -> Result { Err(NeverError) } } /// Generates all (none) of the [`Never`]s. /// /// The output length is 0. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::nevers::nevers; /// /// assert_eq!(nevers().collect_vec(), &[]); /// ``` pub const fn nevers() -> Empty { empty() } ================================================ FILE: malachite-base/src/num/arithmetic/abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Abs, AbsAssign, UnsignedAbs}; macro_rules! impl_abs_primitive_int { ($u:ident, $s:ident) => { impl Abs for $s { type Output = $s; /// This is a wrapper over the `abs` functions in the standard library, for example /// [this one](i32::abs). #[inline] fn abs(self) -> $s { $s::abs(self) } } impl AbsAssign for $s { /// Replaces a number with its absolute value. /// /// $x \gets |x|$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::abs#abs_assign). #[inline] fn abs_assign(&mut self) { *self = self.abs(); } } impl UnsignedAbs for $s { type Output = $u; /// This is a wrapper over the `unsigned_abs` functions in the standard library, for /// example [this one](i32::unsigned_abs). #[inline] fn unsigned_abs(self) -> $u { self.unsigned_abs() } } }; } apply_to_unsigned_signed_pairs!(impl_abs_primitive_int); macro_rules! impl_abs_primitive_float { ($f:ident) => { impl Abs for $f { type Output = $f; /// This is a wrapper over the `fabs` functions from [`libm`]. #[inline] fn abs(self) -> $f { libm::Libm::<$f>::fabs(self) } } impl AbsAssign for $f { /// Replaces a number with its absolute value. /// /// $x \gets |x|$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::abs#abs_assign). #[inline] fn abs_assign(&mut self) { *self = self.abs(); } } }; } apply_to_primitive_floats!(impl_abs_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{AbsDiff, AbsDiffAssign}; macro_rules! impl_abs_diff_unsigned { ($t:ident) => { impl AbsDiff for $t { type Output = $t; /// This is a wrapper over the `abs_diff` functions in the standard library, for example /// [this one](u32::abs_diff). #[inline] fn abs_diff(self, other: $t) -> $t { self.abs_diff(other) } } impl AbsDiffAssign for $t { /// Subtracts a number by another and takes the absolute value, in place. The output /// type is the unsigned type with the same width. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::abs_diff#abs_diff_assign). #[inline] fn abs_diff_assign(&mut self, other: $t) { *self = self.abs_diff(other); } } }; } apply_to_unsigneds!(impl_abs_diff_unsigned); macro_rules! impl_abs_diff_signed { ($u:ident, $s:ident) => { impl AbsDiff for $s { type Output = $u; /// This is a wrapper over the `abs_diff` functions in the standard library, for example /// [this one](i32::abs_diff). #[inline] fn abs_diff(self, other: $s) -> $u { self.abs_diff(other) } } }; } apply_to_unsigned_signed_pairs!(impl_abs_diff_signed); ================================================ FILE: malachite-base/src/num/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{AddMul, AddMulAssign, WrappingAddMul, WrappingAddMulAssign}; macro_rules! impl_add_mul_primitive_int { ($t:ident) => { impl AddMul for $t { type Output = $t; /// Adds a number and the product of two other numbers. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::add_mul#add_mul). #[inline] fn add_mul(self, y: $t, z: $t) -> $t { self.wrapping_add_mul(y, z) } } impl AddMulAssign<$t> for $t { /// Adds the product of two other numbers to a number in place. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::add_mul#add_mul_assign). #[inline] fn add_mul_assign(&mut self, y: $t, z: $t) { self.wrapping_add_mul_assign(y, z) } } }; } apply_to_primitive_ints!(impl_add_mul_primitive_int); macro_rules! impl_add_mul_primitive_float { ($t:ident) => { impl AddMul for $t { type Output = $t; /// Adds a number and the product of two other numbers. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::add_mul#add_mul). #[inline] fn add_mul(self, y: $t, z: $t) -> $t { self + y * z } } impl AddMulAssign<$t> for $t { /// Adds the product of two other numbers to a number in place. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::add_mul#add_mul_assign). #[inline] fn add_mul_assign(&mut self, y: $t, z: $t) { *self += y * z; } } }; } apply_to_primitive_floats!(impl_add_mul_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/arithmetic_checked_shl.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ArithmeticCheckedShl, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use core::ops::{Shl, Shr}; fn arithmetic_checked_shl_unsigned_unsigned< T: PrimitiveUnsigned + Shl + Shr, U: Copy + Ord + WrappingFrom, >( x: T, bits: U, ) -> Option { if x == T::ZERO { Some(x) } else if bits >= U::wrapping_from(T::WIDTH) { None } else { let result = x << bits; if result >> bits == x { Some(result) } else { None } } } macro_rules! impl_arithmetic_checked_shl_unsigned_unsigned { ($t:ident) => { macro_rules! impl_arithmetic_checked_shl_unsigned_unsigned_inner { ($u:ident) => { impl ArithmeticCheckedShl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(2^b x) & \text{if} \\quad 2^b x < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad 2^b x \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shl#arithmetic_checked_shl). #[inline] fn arithmetic_checked_shl(self, bits: $u) -> Option<$t> { arithmetic_checked_shl_unsigned_unsigned(self, bits) } } }; } apply_to_unsigneds!(impl_arithmetic_checked_shl_unsigned_unsigned_inner); }; } apply_to_unsigneds!(impl_arithmetic_checked_shl_unsigned_unsigned); fn arithmetic_checked_shl_unsigned_signed< T: ArithmeticCheckedShl + PrimitiveUnsigned + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, ) -> Option { if bits >= S::ZERO { x.arithmetic_checked_shl(bits.unsigned_abs()) } else { let abs_bits = bits.unsigned_abs(); Some(if abs_bits >= U::wrapping_from(T::WIDTH) { T::ZERO } else { x >> abs_bits }) } } macro_rules! impl_arithmetic_checked_shl_unsigned_signed { ($t:ident) => { macro_rules! impl_arithmetic_checked_shl_unsigned_signed_inner { ($u:ident) => { impl ArithmeticCheckedShl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount, and any number may be shifted by any /// negative amount; shifting by a negative amount with a high absolute value /// returns `Some(0)`. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(2^b x) & /// \text{if} \\quad b \geq 0 \\ \mathrm{and}\\ 2^b x < 2^W, \\\\ /// \operatorname{None} & /// \text{if} \\quad b \geq 0 \\ \mathrm{and} \\ 2^b x \geq 2^W, \\\\ /// \operatorname{Some}(\lfloor x/2^{-b} \rfloor) & /// \text{if} \\quad b < 0, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shl#arithmetic_checked_shl). #[inline] fn arithmetic_checked_shl(self, bits: $u) -> Option<$t> { arithmetic_checked_shl_unsigned_signed(self, bits) } } }; } apply_to_signeds!(impl_arithmetic_checked_shl_unsigned_signed_inner); }; } apply_to_unsigneds!(impl_arithmetic_checked_shl_unsigned_signed); fn arithmetic_checked_shl_signed_unsigned< U: ArithmeticCheckedShl + PrimitiveUnsigned, S: TryFrom + PrimitiveSigned + UnsignedAbs, B, >( x: S, bits: B, ) -> Option { let abs = x.unsigned_abs(); if x >= S::ZERO { abs.arithmetic_checked_shl(bits) .and_then(|x| S::try_from(x).ok()) } else { abs.arithmetic_checked_shl(bits).and_then(|x| { if x == S::MIN.unsigned_abs() { Some(S::MIN) } else { S::try_from(x).ok().map(|y| -y) } }) } } macro_rules! impl_arithmetic_checked_shl_signed_unsigned { ($t:ident) => { macro_rules! impl_arithmetic_checked_shl_signed_unsigned_inner { ($u:ident) => { impl ArithmeticCheckedShl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(2^b x) & /// \text{if} \\quad -2^{W-1} \leq 2^b x < 2^{W-1}, \\\\ /// \operatorname{None} & /// \text{if} \\quad 2^b x < -2^{W-1} \\ \mathrm{or} /// \\ 2^b x \geq 2^{W-1}, \\\\ /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shl#arithmetic_checked_shl). #[inline] fn arithmetic_checked_shl(self, bits: $u) -> Option<$t> { arithmetic_checked_shl_signed_unsigned(self, bits) } } }; } apply_to_unsigneds!(impl_arithmetic_checked_shl_signed_unsigned_inner); }; } apply_to_signeds!(impl_arithmetic_checked_shl_signed_unsigned); fn arithmetic_checked_shl_signed_signed< T: ArithmeticCheckedShl + PrimitiveSigned + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, ) -> Option { if bits >= S::ZERO { x.arithmetic_checked_shl(bits.unsigned_abs()) } else { let width = U::wrapping_from(T::WIDTH); let abs_bits = bits.unsigned_abs(); Some(if width != U::ZERO && abs_bits >= width { -T::from(x < T::ZERO) } else { x >> abs_bits }) } } macro_rules! impl_arithmetic_checked_shl_signed_signed { ($t:ident) => { macro_rules! impl_arithmetic_checked_shl_signed_signed_inner { ($u:ident) => { impl ArithmeticCheckedShl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount, and any number may be shifted by any /// negative amount; shifting by a negative amount with a high absolute value /// returns `Some(0)` if `self` is positive, and `Some(-1)` if `self` is /// negative. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(2^b x) & /// \text{if} \\quad b \geq 0 \\ \mathrm{and} /// \\ -2^{W-1} \leq 2^b x < 2^{W-1}, \\\\ /// \operatorname{None} & /// \text{if} \\quad b \geq 0 \\ \mathrm{and} /// \\ (2^b x < -2^{W-1} \\ \mathrm{or} \\ 2^b x \geq 2^{W-1}), \\\\ /// \operatorname{Some}(\lfloor x/2^{-b} \rfloor) & \text{if} \\quad b < 0, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shl#arithmetic_checked_shl). fn arithmetic_checked_shl(self, bits: $u) -> Option<$t> { arithmetic_checked_shl_signed_signed(self, bits) } } }; } apply_to_signeds!(impl_arithmetic_checked_shl_signed_signed_inner); }; } apply_to_signeds!(impl_arithmetic_checked_shl_signed_signed); ================================================ FILE: malachite-base/src/num/arithmetic/arithmetic_checked_shr.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ArithmeticCheckedShl, ArithmeticCheckedShr, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use core::ops::Shr; fn arithmetic_checked_shr_unsigned_signed< T: ArithmeticCheckedShl + PrimitiveUnsigned + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, ) -> Option { if bits < S::ZERO { x.arithmetic_checked_shl(bits.unsigned_abs()) } else { let abs_bits = bits.unsigned_abs(); Some(if abs_bits >= U::wrapping_from(T::WIDTH) { T::ZERO } else { x >> abs_bits }) } } macro_rules! impl_arithmetic_checked_shr_unsigned_signed { ($t:ident) => { macro_rules! impl_arithmetic_checked_shr_unsigned_signed_inner { ($u:ident) => { impl ArithmeticCheckedShr<$u> for $t { type Output = $t; /// Shifts a number right (divides it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount, and any number may be shifted by any /// non-negative amount; shifting by a large amount returns `Some(0)`. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(\lfloor x/2^b \rfloor) & /// \text{if} \\quad b \geq 0, \\\\ /// \operatorname{Some}(2^{-b} x) & /// \text{if} \\quad b < 0 \\ \mathrm{and} \\ 2^{-b} x < 2^W, \\\\ /// \operatorname{None} & /// \text{if} \\quad b < 0 \\ \mathrm{and} \\ 2^{-b} x \geq 2^W, \\\\ /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shr#arithmetic_checked_shr). #[inline] fn arithmetic_checked_shr(self, bits: $u) -> Option<$t> { arithmetic_checked_shr_unsigned_signed(self, bits) } } }; } apply_to_signeds!(impl_arithmetic_checked_shr_unsigned_signed_inner); }; } apply_to_unsigneds!(impl_arithmetic_checked_shr_unsigned_signed); fn arithmetic_checked_shr_signed_signed< T: ArithmeticCheckedShl + PrimitiveSigned + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, ) -> Option { if bits < S::ZERO { x.arithmetic_checked_shl(bits.unsigned_abs()) } else { let width = U::wrapping_from(T::WIDTH); let abs_bits = bits.unsigned_abs(); Some(if width != U::ZERO && abs_bits >= width { -T::from(x < T::ZERO) } else { x >> abs_bits }) } } macro_rules! impl_arithmetic_checked_shr_signed_signed { ($t:ident) => { macro_rules! impl_arithmetic_checked_shr_signed_signed_inner { ($u:ident) => { impl ArithmeticCheckedShr<$u> for $t { type Output = $t; /// Shifts a number right (divides it by a power of 2). If the result is too /// large to be represented, `None` is returned. /// /// Zero may be shifted by any amount, and any number may be shifted by any /// non-negative amount; shifting by a large amount returns `Some(0)` if `self` /// is positive, and `Some(-1)` if `self` is negative. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(\lfloor x/2^b \rfloor) & /// \text{if} \\quad b \geq 0, \\\\ /// \operatorname{Some}(2^{-b} x) & /// \text{if} \\quad b < 0 \\ \mathrm{and} /// \\ -2^{W-1} \leq 2^{-b} x < 2^{W-1}, \\\\ /// \operatorname{None} & /// \text{if} \\quad b < 0 \\ \mathrm{and} /// \\ (2^{-b} x < -2^{W-1} \\ \mathrm{or} /// \\ 2^{-b} x \geq 2^{W-1}), \\\\ /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::arithmetic_checked_shr#arithmetic_checked_shr). #[inline] fn arithmetic_checked_shr(self, bits: $u) -> Option<$t> { arithmetic_checked_shr_signed_signed(self, bits) } } }; } apply_to_signeds!(impl_arithmetic_checked_shr_signed_signed_inner); }; } apply_to_signeds!(impl_arithmetic_checked_shr_signed_signed); ================================================ FILE: malachite-base/src/num/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ BinomialCoefficient, CheckedBinomialCoefficient, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::OverflowingFrom; use crate::num::exhaustive::primitive_int_increasing_inclusive_range; use core::cmp::min; fn checked_binomial_coefficient_unsigned(n: T, mut k: T) -> Option { if k > n { return Some(T::ZERO); } k = min(k, n - k); if k == T::ZERO { Some(T::ONE) } else if k == T::ONE { Some(n) } else if k == T::TWO { (if n.even() { n - T::ONE } else { n }).checked_mul(n >> 1) } else { // Some binomial coefficient algorithms have intermediate results greater than the final // result, risking overflow. This one does not. let mut product = n - k + T::ONE; let mut numerator = product; for i in primitive_int_increasing_inclusive_range(T::TWO, k) { numerator += T::ONE; let gcd = numerator.gcd(i); product /= i / gcd; product = product.checked_mul(numerator / gcd)?; } Some(product) } } fn checked_binomial_coefficient_signed< U: PrimitiveUnsigned, S: OverflowingFrom + PrimitiveSigned + TryFrom + UnsignedAbs, >( n: S, k: S, ) -> Option { if k < S::ZERO { return None; } if n >= S::ZERO { S::try_from(U::checked_binomial_coefficient( n.unsigned_abs(), k.unsigned_abs(), )?) .ok() } else { let k = k.unsigned_abs(); let b = U::checked_binomial_coefficient(n.unsigned_abs() + k - U::ONE, k)?; if k.even() { S::try_from(b).ok() } else { let (b, overflow) = S::overflowing_from(b); if overflow { if b == S::MIN { Some(S::MIN) } else { None } } else { Some(-b) } } } } macro_rules! impl_binomial_coefficient_unsigned { ($t:ident) => { impl CheckedBinomialCoefficient for $t { /// Computes the binomial coefficient of two numbers. If the inputs are too large, the /// function returns `None`. /// /// $$ /// f(n, k) = \\begin{cases} /// \operatorname{Some}(\binom{n}{k}) & \text{if} \\quad \binom{n}{k} < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad \binom{n}{k} \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// $T(k) = O(k)$ /// /// $M(k) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is `k`. /// /// # Examples /// See [here](super::binomial_coefficient#checked_binomial_coefficient). #[inline] fn checked_binomial_coefficient(n: $t, k: $t) -> Option<$t> { checked_binomial_coefficient_unsigned(n, k) } } }; } apply_to_unsigneds!(impl_binomial_coefficient_unsigned); macro_rules! impl_binomial_coefficient_signed { ($t:ident) => { impl CheckedBinomialCoefficient for $t { /// Computes the binomial coefficient of two numbers. If the inputs are too large, the /// function returns `None`. /// /// The second argument must be non-negative, but the first may be negative. If it is, /// the identity $\binom{-n}{k} = (-1)^k \binom{n+k-1}{k}$ is used. /// /// $$ /// f(n, k) = \\begin{cases} /// \operatorname{Some}(\binom{n}{k}) & \text{if} \\quad n \geq 0 \\ \text{and} /// \\ -2^{W-1} \leq \binom{n}{k} < 2^{W-1}, \\\\ /// \operatorname{Some}((-1)^k \binom{-n+k-1}{k}) & \text{if} \\quad n < 0 /// \\ \text{and} \\ -2^{W-1} \leq \binom{n}{k} < 2^{W-1}, \\\\ /// \operatorname{None} & \\quad \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// $T(k) = O(k)$ /// /// $M(k) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is `k.abs()`. /// /// # Examples /// See [here](super::binomial_coefficient#checked_binomial_coefficient). #[inline] fn checked_binomial_coefficient(n: $t, k: $t) -> Option<$t> { checked_binomial_coefficient_signed(n, k) } } }; } apply_to_signeds!(impl_binomial_coefficient_signed); macro_rules! impl_binomial_coefficient_primitive_int { ($t:ident) => { impl BinomialCoefficient for $t { /// Computes the binomial coefficient of two numbers. If the inputs are too large, the /// function panics. /// /// The second argument must be non-negative, but the first may be negative. If it is, /// the identity $\binom{-n}{k} = (-1)^k \binom{n+k-1}{k}$ is used. /// /// $$ /// f(n, k) = \\begin{cases} /// \binom{n}{k} & \text{if} \\quad n \geq 0, \\\\ /// (-1)^k \binom{-n+k-1}{k} & \text{if} \\quad n < 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(k) = O(k)$ /// /// $M(k) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is `k.abs()`. /// /// # Panics /// Panics if the result is not representable by this type, or if $k$ is negative. /// /// # Examples /// See [here](super::binomial_coefficient#binomial_coefficient). #[inline] fn binomial_coefficient(n: $t, k: $t) -> $t { $t::checked_binomial_coefficient(n, k).unwrap() } } }; } apply_to_primitive_ints!(impl_binomial_coefficient_primitive_int); ================================================ FILE: malachite-base/src/num/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Ceiling, CeilingAssign}; macro_rules! impl_ceiling { ($f:ident) => { impl Ceiling for $f { type Output = $f; /// This is a wrapper over the `ceil` functions in [`libm`] #[inline] fn ceiling(self) -> $f { libm::Libm::<$f>::ceil(self) } } impl CeilingAssign for $f { /// Replaces a number with its ceiling. /// /// A number's ceiling is the smallest integer greater than or equal to the number. /// /// $x \gets \lceil x \rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::ceiling#ceiling_assign). #[inline] fn ceiling_assign(&mut self) { *self = self.ceiling(); } } }; } apply_to_primitive_floats!(impl_ceiling); ================================================ FILE: malachite-base/src/num/arithmetic/checked_abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedAbs; macro_rules! impl_checked_abs { ($t:ident) => { impl CheckedAbs for $t { type Output = $t; /// This is a wrapper over the `checked_abs` functions in the standard library, for /// example [this one](i32::checked_abs). #[inline] fn checked_abs(self) -> Option<$t> { $t::checked_abs(self) } } }; } apply_to_signeds!(impl_checked_abs); ================================================ FILE: malachite-base/src/num/arithmetic/checked_add.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedAdd; macro_rules! impl_checked_add { ($t:ident) => { impl CheckedAdd<$t> for $t { type Output = $t; /// This is a wrapper over the `checked_add` functions in the standard library, for /// example [this one](u32::checked_add). #[inline] fn checked_add(self, other: $t) -> Option<$t> { $t::checked_add(self, other) } } }; } apply_to_primitive_ints!(impl_checked_add); ================================================ FILE: malachite-base/src/num/arithmetic/checked_add_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedAddMul, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; fn checked_add_mul_unsigned(x: T, y: T, z: T) -> Option { y.checked_mul(z).and_then(|yz| x.checked_add(yz)) } macro_rules! impl_checked_add_mul_unsigned { ($t:ident) => { impl CheckedAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers, returning `None` if the result /// cannot be represented. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x + yz) & \text{if} \\quad x + yz < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad x + yz \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::checked_add_mul#checked_add_mul). #[inline] fn checked_add_mul(self, y: $t, z: $t) -> Option<$t> { checked_add_mul_unsigned(self, y, z) } } }; } apply_to_unsigneds!(impl_checked_add_mul_unsigned); fn checked_add_mul_signed< U: PrimitiveUnsigned, T: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: T, y: T, z: T, ) -> Option { if y == T::ZERO || z == T::ZERO { return Some(x); } let x_sign = x >= T::ZERO; if x_sign == ((y >= T::ZERO) == (z >= T::ZERO)) { x.checked_add(y.checked_mul(z)?) } else { let x = x.unsigned_abs(); let product = y.unsigned_abs().checked_mul(z.unsigned_abs())?; let result = T::wrapping_from(if x_sign { x.wrapping_sub(product) } else { product.wrapping_sub(x) }); if x >= product || (x_sign == (result < T::ZERO)) { Some(result) } else { None } } } macro_rules! impl_checked_add_mul_signed { ($t:ident) => { impl CheckedAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers, returning `None` if the result /// cannot be represented. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x + yz) & /// \text{if} \\quad -2^{W-1} \leq x + yz < 2^{W-1}, \\\\ /// \operatorname{None} & /// \text{if} \\quad x + yz < -2^{W-1} \\ \mathrm{or} /// \\ x + yz \geq 2^{W-1}, \\\\ /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::checked_add_mul#checked_add_mul). #[inline] fn checked_add_mul(self, y: $t, z: $t) -> Option<$t> { checked_add_mul_signed(self, y, z) } } }; } apply_to_signeds!(impl_checked_add_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/checked_div.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedDiv; macro_rules! impl_checked_div { ($t:ident) => { impl CheckedDiv<$t> for $t { type Output = $t; /// This is a wrapper over the `checked_div` functions in the standard library, for /// example [this one](u32::checked_div). #[inline] fn checked_div(self, other: $t) -> Option<$t> { $t::checked_div(self, other) } } }; } apply_to_primitive_ints!(impl_checked_div); ================================================ FILE: malachite-base/src/num/arithmetic/checked_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedMul; macro_rules! impl_checked_mul { ($t:ident) => { impl CheckedMul<$t> for $t { type Output = $t; /// This is a wrapper over the `checked_mul` functions in the standard library, for /// example [this one](u32::checked_mul). #[inline] fn checked_mul(self, other: $t) -> Option<$t> { $t::checked_mul(self, other) } } }; } apply_to_primitive_ints!(impl_checked_mul); ================================================ FILE: malachite-base/src/num/arithmetic/checked_neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedNeg; macro_rules! impl_checked_neg { ($t:ident) => { impl CheckedNeg for $t { type Output = $t; /// This is a wrapper over the `checked_neg` functions in the standard library, for /// example [this one](u32::checked_neg). #[inline] fn checked_neg(self) -> Option<$t> { $t::checked_neg(self) } } }; } apply_to_primitive_ints!(impl_checked_neg); ================================================ FILE: malachite-base/src/num/arithmetic/checked_next_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedNextPowerOf2; macro_rules! impl_checked_next_power_of_2 { ($t:ident) => { impl CheckedNextPowerOf2 for $t { type Output = $t; /// This is a wrapper over the `checked_next_power_of_two` functions in the standard /// library, for example [this one](u32::checked_next_power_of_two). #[inline] fn checked_next_power_of_2(self) -> Option<$t> { $t::checked_next_power_of_two(self) } } }; } apply_to_unsigneds!(impl_checked_next_power_of_2); ================================================ FILE: malachite-base/src/num/arithmetic/checked_pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedPow, Parity}; macro_rules! impl_checked_pow_unsigned { ($t:ident) => { impl CheckedPow for $t { type Output = $t; /// This is a wrapper over the `checked_pow` functions in the standard library, for /// example [this one](u32::checked_pow). #[inline] fn checked_pow(self, exp: u64) -> Option<$t> { if exp == 0 { Some(1) } else if self < 2 { Some(self) } else { self.checked_pow(u32::try_from(exp).ok()?) } } } }; } apply_to_unsigneds!(impl_checked_pow_unsigned); macro_rules! impl_checked_pow_signed { ($t:ident) => { impl CheckedPow for $t { type Output = $t; /// This is a wrapper over the `checked_pow` functions in the standard library, for /// example [this one](i32::checked_pow). #[inline] fn checked_pow(self, exp: u64) -> Option<$t> { if exp == 0 { Some(1) } else if self == 0 || self == 1 { Some(self) } else if self == -1 { Some(if exp.even() { 1 } else { -1 }) } else { self.checked_pow(u32::try_from(exp).ok()?) } } } }; } apply_to_signeds!(impl_checked_pow_signed); ================================================ FILE: malachite-base/src/num/arithmetic/checked_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedSquare; macro_rules! impl_checked_square { ($t:ident) => { impl CheckedSquare for $t { type Output = $t; /// Squares a number, returning `None` if the result cannot be represented. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(x^2) & \text{if} \\quad x^2 < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad x^2 \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::checked_square#checked_square). #[inline] fn checked_square(self) -> Option<$t> { self.checked_mul(self) } } }; } apply_to_primitive_ints!(impl_checked_square); ================================================ FILE: malachite-base/src/num/arithmetic/checked_sub.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CheckedSub; macro_rules! impl_checked_sub { ($t:ident) => { impl CheckedSub<$t> for $t { type Output = $t; /// This is a wrapper over the `checked_sub` functions in the standard library, for /// example [this one](u32::checked_sub). #[inline] fn checked_sub(self, other: $t) -> Option<$t> { $t::checked_sub(self, other) } } }; } apply_to_primitive_ints!(impl_checked_sub); ================================================ FILE: malachite-base/src/num/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedSubMul, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; fn checked_sub_mul_unsigned(x: T, y: T, z: T) -> Option { y.checked_mul(z).and_then(|yz| x.checked_sub(yz)) } macro_rules! impl_checked_sub_mul_unsigned { ($t:ident) => { impl CheckedSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers, returning `None` if the /// result cannot be represented. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{if} \\quad x < yz, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::checked_sub_mul#checked_sub_mul). #[inline] fn checked_sub_mul(self, y: $t, z: $t) -> Option<$t> { checked_sub_mul_unsigned(self, y, z) } } }; } apply_to_unsigneds!(impl_checked_sub_mul_unsigned); fn checked_sub_mul_signed< U: Ord + PrimitiveUnsigned, T: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: T, y: T, z: T, ) -> Option { if y == T::ZERO || z == T::ZERO { return Some(x); } let x_sign = x >= T::ZERO; if x_sign == ((y >= T::ZERO) != (z >= T::ZERO)) { x.checked_sub(y.checked_mul(z)?) } else { let x = x.unsigned_abs(); let product = y.unsigned_abs().checked_mul(z.unsigned_abs())?; let result = T::wrapping_from(if x_sign { x.wrapping_sub(product) } else { product.wrapping_sub(x) }); if x >= product || (x_sign == (result < T::ZERO)) { Some(result) } else { None } } } macro_rules! impl_checked_sub_mul_signed { ($t:ident) => { impl CheckedSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers, returning `None` if the /// result cannot be represented. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & /// \text{if} \\quad -2^{W-1} \leq x - yz < 2^{W-1}, \\\\ /// \operatorname{None} & /// \text{if} \\quad x - yz < -2^{W-1} \\ \mathrm{or} /// \\ xy - z \geq 2^{W-1}, \\\\ /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::checked_sub_mul#checked_sub_mul). #[inline] fn checked_sub_mul(self, y: $t, z: $t) -> Option<$t> { checked_sub_mul_signed(self, y, z) } } }; } apply_to_signeds!(impl_checked_sub_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::CoprimeWith; use crate::num::basic::unsigneds::PrimitiveUnsigned; pub_test! {coprime_with_check_2(x: T, y: T) -> bool { (x.odd() || y.odd()) && x.gcd(y) == T::ONE }} #[cfg(feature = "test_build")] pub fn coprime_with_check_2_3(x: T, y: T) -> bool { (x.odd() || y.odd()) && (!x.divisible_by(T::from(3u8)) || !y.divisible_by(T::from(3u8))) && x.gcd(y) == T::ONE } #[cfg(feature = "test_build")] pub fn coprime_with_check_2_3_5(x: T, y: T) -> bool { if x.even() && y.even() { false } else { let c15 = T::from(15u8); let c3 = T::from(3u8); let c6 = T::from(6u8); let c9 = T::from(9u8); let c12 = T::from(12u8); let c5 = T::from(5u8); let c10 = T::from(10u8); let x15 = x % c15; let y15 = y % c15; if (x15 == T::ZERO || x15 == c3 || x15 == c6 || x15 == c9 || x15 == c12) && (y15 == T::ZERO || y15 == c3 || y15 == c6 || y15 == c9 || y15 == c12) { return false; } if (x15 == T::ZERO || x15 == c5 || x15 == c10) && (y15 == T::ZERO || y15 == c5 || y15 == c10) { return false; } x.gcd(y) == T::ONE } } macro_rules! impl_coprime_with { ($t:ident) => { impl CoprimeWith<$t> for $t { /// Returns whether two numbers are coprime; that is, whether they have no common factor /// other than 1. /// /// Every number is coprime with 1. No number is coprime with 0, except 1. /// /// $f(x, y) = (\gcd(x, y) = 1)$. /// /// $f(x, y) = ((k,m,n \in \N \land x=km \land y=kn) \implies k=1)$. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::coprime_with#coprime_with). #[inline] fn coprime_with(self, other: $t) -> bool { coprime_with_check_2(self, other) } } }; } apply_to_unsigneds!(impl_coprime_with); ================================================ FILE: malachite-base/src/num/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivExact, DivExactAssign}; macro_rules! impl_div_exact { ($t:ident) => { impl DivExact<$t> for $t { type Output = $t; /// Divides a value by another value. The first value must be exactly divisible by the /// second. /// /// If `self` is not exactly divisible by `other`, this function may panic or return a /// meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self / other` instead. If /// you're unsure and you want to know, use `self.div_mod(other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, /// use `self.div_round(other, Exact)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero or if `self` is `Self::MIN` and other is -1. /// /// # Examples /// See [here](super::div_exact#div_exact). #[inline] fn div_exact(self, other: $t) -> $t { self / other } } impl DivExactAssign<$t> for $t { /// Divides a value by another value in place. The value being assigned to must be /// exactly divisible by the value on the right-hand side. /// /// If `self` is not exactly divisible by `other`, this function may panic or return a /// meaningless result. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self /= other` instead. /// If you're unsure and you want to know, use `self.div_assign_mod(other)` and check /// whether the remainder is zero. If you want a function that panics if the division is /// not exact, use `self.div_round_assign(other, Exact)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero or if `self` is `Self::MIN` and other is -1. /// /// # Examples /// See [here](super::div_exact#div_exact_assign). #[inline] fn div_exact_assign(&mut self, other: $t) { *self /= other; } } }; } apply_to_primitive_ints!(impl_div_exact); ================================================ FILE: malachite-base/src/num/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ CeilingDivAssignMod, CeilingDivAssignNegMod, CeilingDivMod, CeilingDivNegMod, DivAssignMod, DivAssignRem, DivMod, DivRem, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; fn div_mod_unsigned(x: T, other: T) -> (T, T) { let q = x / other; (q, x - q * other) } fn div_assign_mod_unsigned(x: &mut T, other: T) -> T { let original = *x; *x /= other; original - *x * other } fn ceiling_div_neg_mod_unsigned(x: T, other: T) -> (T, T) { let (quotient, remainder) = x.div_mod(other); if remainder == T::ZERO { (quotient, T::ZERO) } else { // Here remainder != 0, so other > 1, so quotient < T::MAX. (quotient + T::ONE, other - remainder) } } fn ceiling_div_assign_neg_mod_unsigned(x: &mut T, other: T) -> T { let remainder = x.div_assign_mod(other); if remainder == T::ZERO { T::ZERO } else { // Here remainder != 0, so other > 1, so self < T::MAX. *x += T::ONE; other - remainder } } macro_rules! impl_div_mod_unsigned { ($t:ident) => { impl DivMod<$t> for $t { type DivOutput = $t; type ModOutput = $t; /// Divides a number by another number, returning the quotient and remainder. The /// quotient is rounded towards negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#div_mod). #[inline] fn div_mod(self, other: $t) -> ($t, $t) { div_mod_unsigned(self, other) } } impl DivAssignMod<$t> for $t { type ModOutput = $t; /// Divides a number by another number in place, returning the remainder. The quotient /// is rounded towards negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#div_assign_mod). #[inline] fn div_assign_mod(&mut self, other: $t) -> $t { div_assign_mod_unsigned(self, other) } } impl DivRem<$t> for $t { type DivOutput = $t; type RemOutput = $t; /// Divides a number by another number, returning the quotient and remainder. The /// quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// For unsigned integers, `div_rem` is equivalent to `div_mod`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#div_rem). #[inline] fn div_rem(self, other: $t) -> ($t, $t) { self.div_mod(other) } } impl DivAssignRem<$t> for $t { type RemOutput = $t; /// Divides a number by another number in place, returning the remainder. The quotient /// is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For unsigned integers, `div_assign_rem` is equivalent to `div_assign_mod`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#div_assign_rem). #[inline] fn div_assign_rem(&mut self, other: $t) -> $t { self.div_assign_mod(other) } } impl CeilingDivNegMod<$t> for $t { type DivOutput = $t; type ModOutput = $t; /// Divides a number by another number, returning the ceiling of the quotient and the /// remainder of the negative of the first number divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// y\left \lceil \frac{x}{y} \right \rceil - x \right ). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#ceiling_div_neg_mod). #[inline] fn ceiling_div_neg_mod(self, other: $t) -> ($t, $t) { ceiling_div_neg_mod_unsigned(self, other) } } impl CeilingDivAssignNegMod<$t> for $t { type ModOutput = $t; /// Divides a number by another number in place, returning the remainder of the negative /// of the first number divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::div_mod#ceiling_div_assign_neg_mod). #[inline] fn ceiling_div_assign_neg_mod(&mut self, other: $t) -> $t { ceiling_div_assign_neg_mod_unsigned(self, other) } } }; } apply_to_unsigneds!(impl_div_mod_unsigned); fn div_mod_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + ExactFrom + UnsignedAbs + WrappingFrom, >( x: S, other: S, ) -> (S, S) { let (quotient, remainder) = if (x >= S::ZERO) == (other >= S::ZERO) { let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs()); (S::exact_from(quotient), remainder) } else { let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs()); (S::wrapping_from(quotient).wrapping_neg(), remainder) }; ( quotient, if other >= S::ZERO { S::exact_from(remainder) } else { -S::exact_from(remainder) }, ) } fn div_rem_signed(x: T, other: T) -> (T, T) { let q = x.checked_div(other).unwrap(); (q, x - q * other) } fn div_assign_rem_signed(x: &mut T, other: T) -> T { let original = *x; *x = x.checked_div(other).unwrap(); original - *x * other } fn ceiling_div_mod_signed< U: PrimitiveUnsigned, T: PrimitiveSigned + ExactFrom + UnsignedAbs + WrappingFrom, >( x: T, other: T, ) -> (T, T) { let (quotient, remainder) = if (x >= T::ZERO) == (other >= T::ZERO) { let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs()); (T::exact_from(quotient), remainder) } else { let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs()); (T::wrapping_from(quotient).wrapping_neg(), remainder) }; ( quotient, if other >= T::ZERO { -T::exact_from(remainder) } else { T::exact_from(remainder) }, ) } macro_rules! impl_div_mod_signed { ($t:ident) => { impl DivMod<$t> for $t { type DivOutput = $t; type ModOutput = $t; /// Divides a number by another number, returning the quotient and remainder. The /// quotient is rounded towards negative infinity, and the remainder has the same sign /// as the second number. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#div_mod). #[inline] fn div_mod(self, other: $t) -> ($t, $t) { div_mod_signed(self, other) } } impl DivAssignMod<$t> for $t { type ModOutput = $t; /// Divides a number by another number in place, returning the remainder. The quotient /// is rounded towards negative infinity, and the remainder has the same sign as the /// second number. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#div_assign_mod). #[inline] fn div_assign_mod(&mut self, other: $t) -> $t { let (q, r) = self.div_mod(other); *self = q; r } } impl DivRem<$t> for $t { type DivOutput = $t; type RemOutput = $t; /// Divides a number by another number, returning the quotient and remainder. The /// quotient is rounded towards zero and the remainder has the same sign as the /// dividend. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor, \space /// x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#div_rem). #[inline] fn div_rem(self, other: $t) -> ($t, $t) { div_rem_signed(self, other) } } impl DivAssignRem<$t> for $t { type RemOutput = $t; /// Divides a number by another number in place, returning the remainder. The quotient /// is rounded towards zero and the remainder has the same sign as the dividend. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor, /// $$ /// $$ /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#div_assign_rem). #[inline] fn div_assign_rem(&mut self, other: $t) -> $t { div_assign_rem_signed(self, other) } } impl CeilingDivMod<$t> for $t { type DivOutput = $t; type ModOutput = $t; /// Divides a number by another number, returning the quotient and remainder. The /// quotient is rounded towards positive infinity and the remainder has the opposite /// sign as the second number. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// x - y\left \lceil \frac{x}{y} \right \rceil \right ). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#ceiling_div_mod). #[inline] fn ceiling_div_mod(self, other: $t) -> ($t, $t) { ceiling_div_mod_signed(self, other) } } impl CeilingDivAssignMod<$t> for $t { type ModOutput = $t; /// Divides a number by another number in place, returning the remainder. The quotient /// is rounded towards positive infinity and the remainder has the opposite sign as the /// second number. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil\frac{x}{y} \right \rceil, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1. /// /// # Examples /// See [here](super::div_mod#ceiling_div_assign_mod). #[inline] fn ceiling_div_assign_mod(&mut self, other: $t) -> $t { let (q, r) = self.ceiling_div_mod(other); *self = q; r } } }; } apply_to_signeds!(impl_div_mod_signed); ================================================ FILE: malachite-base/src/num/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivRound, DivRoundAssign, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::rounding_modes::RoundingMode::{self, *}; use core::cmp::Ordering::{self, *}; fn div_round_unsigned(x: T, other: T, rm: RoundingMode) -> (T, Ordering) { let quotient = x / other; let remainder = x - quotient * other; match rm { _ if remainder == T::ZERO => (quotient, Equal), Down | Floor => (quotient, Less), Up | Ceiling => (quotient + T::ONE, Greater), Nearest => { let shifted_other = other >> 1; if remainder > shifted_other || remainder == shifted_other && other.even() && quotient.odd() { (quotient + T::ONE, Greater) } else { (quotient, Less) } } Exact => { panic!("Division is not exact: {x} / {other}"); } } } macro_rules! impl_div_round_unsigned { ($t:ident) => { impl DivRound<$t> for $t { type Output = $t; /// Divides a value by another value and rounds according to a specified rounding mode. /// An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by /// `other`. /// /// # Examples /// See [here](super::div_round#div_round). #[inline] fn div_round(self, other: $t, rm: RoundingMode) -> ($t, Ordering) { div_round_unsigned(self, other, rm) } } impl DivRoundAssign<$t> for $t { /// Divides a value by another value in place and rounds according to a specified /// rounding mode. An [`Ordering`] is returned, indicating whether the assigned value is /// less than, equal to, or greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by /// `other`. /// /// # Examples /// See [here](super::div_round#div_round_assign). #[inline] fn div_round_assign(&mut self, other: $t, rm: RoundingMode) -> Ordering { let o; (*self, o) = self.div_round(other, rm); o } } }; } apply_to_unsigneds!(impl_div_round_unsigned); fn div_round_signed< U: PrimitiveUnsigned, S: ExactFrom + PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: S, other: S, rm: RoundingMode, ) -> (S, Ordering) { if (x >= S::ZERO) == (other >= S::ZERO) { let (q, o) = x.unsigned_abs().div_round(other.unsigned_abs(), rm); (S::exact_from(q), o) } else { // Has to be wrapping so that (self, other) == (T::MIN, 1) works let (q, o) = x.unsigned_abs().div_round(other.unsigned_abs(), -rm); (S::wrapping_from(q).wrapping_neg(), o.reverse()) } } macro_rules! impl_div_round_signed { ($t:ident) => { impl DivRound<$t> for $t { type Output = $t; /// Divides a value by another value and rounds according to a specified rounding mode. /// An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero, if `self` is `Self::MIN` and `other` is `-1`, or if `rm` /// is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// See [here](super::div_round#div_round). fn div_round(self, other: $t, rm: RoundingMode) -> ($t, Ordering) { div_round_signed(self, other, rm) } } impl DivRoundAssign<$t> for $t { /// Divides a value by another value in place and rounds according to a specified /// rounding mode. An [`Ordering`] is returned, indicating whether the assigned value is /// less than, equal to, or greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is zero, if `self` is `Self::MIN` and `other` is `-1`, or if `rm` /// is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// See [here](super::div_round#div_round_assign). #[inline] fn div_round_assign(&mut self, other: $t, rm: RoundingMode) -> Ordering { let o; (*self, o) = self.div_round(other, rm); o } } }; } apply_to_signeds!(impl_div_round_signed); ================================================ FILE: malachite-base/src/num/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::DivisibleBy; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn divisible_by_unsigned(x: T, other: T) -> bool { x == T::ZERO || other != T::ZERO && x % other == T::ZERO } macro_rules! impl_divisible_by_unsigned { ($t:ident) => { impl DivisibleBy<$t> for $t { /// Returns whether a number is divisible by another number; in other words, whether the /// first number is a multiple of the second. /// /// This means that zero is divisible by any number, including zero; but a nonzero /// number is never divisible by zero. /// /// $f(x, m) = (m|x)$. /// /// $f(x, m) = (\exists k \in \N : x = km)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::divisible_by#divisible_by). #[inline] fn divisible_by(self, other: $t) -> bool { divisible_by_unsigned(self, other) } } }; } apply_to_unsigneds!(impl_divisible_by_unsigned); fn divisible_by_signed(x: T, other: T) -> bool { x == T::ZERO || x == T::MIN && other == T::NEGATIVE_ONE || other != T::ZERO && x % other == T::ZERO } macro_rules! impl_divisible_by_signed { ($t:ident) => { impl DivisibleBy<$t> for $t { /// Returns whether a number is divisible by another number; in other words, whether the /// first number is a multiple of the second. /// /// This means that zero is divisible by any number, including zero; but a nonzero /// number is never divisible by zero. /// /// $f(x, m) = (m|x)$. /// /// $f(x, m) = (\exists k \in \Z : \ x = km)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::divisible_by#divisible_by). #[inline] fn divisible_by(self, other: $t) -> bool { divisible_by_signed(self, other) } } }; } apply_to_signeds!(impl_divisible_by_signed); ================================================ FILE: malachite-base/src/num/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivisibleByPowerOf2, ModPowerOf2}; use crate::num::conversion::traits::WrappingFrom; macro_rules! impl_divisible_by_power_of_2_unsigned { ($t:ident) => { impl DivisibleByPowerOf2 for $t { /// Returns whether a number is divisible by $2^k$. /// /// $f(x, k) = (2^k|x)$. /// /// $f(x, k) = (\exists n \in \N : \ x = n2^k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::divisible_by_power_of_2#divisible_by_power_of_2). #[inline] fn divisible_by_power_of_2(self, pow: u64) -> bool { self.mod_power_of_2(pow) == 0 } } }; } apply_to_unsigneds!(impl_divisible_by_power_of_2_unsigned); macro_rules! impl_divisible_by_power_of_2_signed { ($u:ident, $s:ident) => { impl DivisibleByPowerOf2 for $s { /// Returns whether a number is divisible by $2^k$. /// /// $f(x, k) = (2^k|x)$. /// /// $f(x, k) = (\exists n \in \N : x = n2^k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::divisible_by_power_of_2#divisible_by_power_of_2). #[inline] fn divisible_by_power_of_2(self, pow: u64) -> bool { $u::wrapping_from(self).divisible_by_power_of_2(pow) } } }; } apply_to_unsigned_signed_pairs!(impl_divisible_by_power_of_2_signed); ================================================ FILE: malachite-base/src/num/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{EqMod, Mod}; use crate::num::basic::traits::Zero; fn eq_mod + Zero>(x: S, other: S, m: S) -> bool { x == other || m != S::ZERO && x.mod_op(m) == other.mod_op(m) } macro_rules! impl_eq_mod { ($t:ident) => { impl EqMod<$t> for $t { /// Returns whether a number is equivalent to another number modulo a third; that is, /// whether the difference between the first two is a multiple of the third. /// /// Two numbers are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::eq_mod#eq_mod). #[inline] fn eq_mod(self, other: $t, m: $t) -> bool { eq_mod(self, other, m) } } }; } apply_to_primitive_ints!(impl_eq_mod); ================================================ FILE: malachite-base/src/num/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivisibleByPowerOf2, EqModPowerOf2}; macro_rules! impl_eq_mod_power_of_2 { ($t:ident) => { impl EqModPowerOf2<$t> for $t { /// Returns whether one number is equal to another modulo $2^k$. /// /// $f(x, y, k) = (x \equiv y \mod 2^k)$. /// /// $f(x, y, k) = (\exists n \in \Z : x - y = n2^k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::eq_mod_power_of_2#eq_mod_power_of_2). #[inline] fn eq_mod_power_of_2(self, other: $t, pow: u64) -> bool { (self ^ other).divisible_by_power_of_2(pow) } } }; } apply_to_primitive_ints!(impl_eq_mod_power_of_2); ================================================ FILE: malachite-base/src/num/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2009, 2016 William Hart // // 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 crate::num::arithmetic::traits::ExtendedGcd; use crate::num::arithmetic::traits::UnsignedAbs; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::rounding_modes::RoundingMode::*; use core::mem::swap; fn extended_gcd_signed< U: ExtendedGcd + PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( a: S, b: S, ) -> (U, S, S) { let (gcd, mut x, mut y) = a.unsigned_abs().extended_gcd(b.unsigned_abs()); if a < S::ZERO { x = x.checked_neg().unwrap(); } if b < S::ZERO { y = y.checked_neg().unwrap(); } (gcd, x, y) } // This is equivalent to `n_xgcd` from `ulong_extras/xgcd.c`, FLINT 2.7.1, with an adjustment to // find the minimal cofactors. pub_test! {extended_gcd_unsigned_binary< U: WrappingFrom + PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, >( mut a: U, mut b: U, ) -> (U, S, S) { if a == U::ZERO && b == U::ZERO { return (U::ZERO, S::ZERO, S::ZERO); } else if a == b || a == U::ZERO { return (b, S::ZERO, S::ONE); } else if b == U::ZERO { return (a, S::ONE, S::ZERO); } let mut swapped = false; if a < b { swap(&mut a, &mut b); swapped = true; } let mut u1 = S::ONE; let mut v2 = S::ONE; let mut u2 = S::ZERO; let mut v1 = S::ZERO; let mut u3 = a; let mut v3 = b; let mut d; let mut t2; let mut t1; if (a & b).get_highest_bit() { d = u3 - v3; t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } while v3.get_bit(U::WIDTH - 2) { d = u3 - v3; if d < v3 { // quot = 1 t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if d < (v3 << 1) { // quot = 2 t1 = u2; u2 = u1 - (u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; v3 = d - u3; } else { // quot = 3 t1 = u2; u2 = u1 - S::wrapping_from(3) * u2; u1 = t1; u3 = v3; t2 = v2; v2 = v1 - S::wrapping_from(3) * v2; v1 = t2; v3 = d - (u3 << 1); } } while v3 != U::ZERO { d = u3 - v3; // overflow not possible, top 2 bits of v3 not set if u3 < (v3 << 2) { if d < v3 { // quot = 1 t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if d < (v3 << 1) { // quot = 2 t1 = u2; u2 = u1.wrapping_sub(u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(v2 << 1); v1 = t2; v3 = d - u3; } else { // quot = 3 t1 = u2; u2 = u1.wrapping_sub(S::wrapping_from(3).wrapping_mul(u2)); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(S::wrapping_from(3).wrapping_mul(v2)); v1 = t2; v3 = d.wrapping_sub(u3 << 1); } } else { let (quot, rem) = u3.div_rem(v3); t1 = u2; u2 = u1.wrapping_sub(S::wrapping_from(quot).wrapping_mul(u2)); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(S::wrapping_from(quot).wrapping_mul(v2)); v1 = t2; v3 = rem; } } // Remarkably, |u1| < x/2, thus comparison with 0 is valid if u1 <= S::ZERO { u1.wrapping_add_assign(S::wrapping_from(b)); v1.wrapping_sub_assign(S::wrapping_from(a)); } // The cofactors at this point are not necessarily minimal, so we may need to adjust. let gcd = u3; let mut x = U::wrapping_from(u1); let mut y = U::wrapping_from(v1); let two_limit_a = a / gcd; let two_limit_b = b / gcd; let limit_b = two_limit_b >> 1; if x > limit_b { let k = (x - limit_b).div_round(two_limit_b, Ceiling).0; x.wrapping_sub_assign(two_limit_b.wrapping_mul(k)); y.wrapping_add_assign(two_limit_a.wrapping_mul(k)); } if swapped { swap(&mut x, &mut y); } (gcd, S::wrapping_from(x), S::wrapping_from(y)) }} macro_rules! impl_extended_gcd { ($u:ident, $s:ident) => { impl ExtendedGcd<$u> for $u { type Gcd = $u; type Cofactor = $s; /// Computes the GCD (greatest common divisor) of two numbers $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the /// full specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(a, /// b)$, where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, /// and $y \leq \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::extended_gcd#extended_gcd). #[inline] fn extended_gcd(self, other: $u) -> ($u, $s, $s) { extended_gcd_unsigned_binary(self, other) } } impl ExtendedGcd<$s> for $s { type Gcd = $u; type Cofactor = $s; /// Computes the GCD (greatest common divisor) of two numbers $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the /// full specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, /// |b|)$, where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, /// and $y \leq \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::extended_gcd#extended_gcd). #[inline] fn extended_gcd(self, other: $s) -> ($u, $s, $s) { extended_gcd_signed(self, other) } } }; } apply_to_unsigned_signed_pairs!(impl_extended_gcd); ================================================ FILE: malachite-base/src/num/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ CheckedDoubleFactorial, CheckedFactorial, CheckedMultifactorial, CheckedSubfactorial, DoubleFactorial, Factorial, Multifactorial, Parity, Subfactorial, }; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; pub_test! {checked_multifactorial_naive(n: u64, m: u64) -> Option { assert_ne!(m, 0); let mut f = T::ONE; let mut n = T::try_from(n).ok()?; let m = T::saturating_from(m); while n != T::ZERO { f = f.checked_mul(n)?; n.saturating_sub_assign(m); } Some(f) }} const FACTORIALS_U8: [u8; 6] = [1, 1, 2, 6, 24, 120]; const FACTORIALS_U16: [u16; 9] = [1, 1, 2, 6, 24, 120, 720, 5040, 40320]; const FACTORIALS_U32: [u32; 13] = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600]; const FACTORIALS_U64: [u64; 21] = [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, ]; const FACTORIALS_U128: [u128; 35] = [ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000, 1124000727777607680000, 25852016738884976640000, 620448401733239439360000, 15511210043330985984000000, 403291461126605635584000000, 10888869450418352160768000000, 304888344611713860501504000000, 8841761993739701954543616000000, 265252859812191058636308480000000, 8222838654177922817725562880000000, 263130836933693530167218012160000000, 8683317618811886495518194401280000000, 295232799039604140847618609643520000000, ]; const ODD_DOUBLE_FACTORIALS_U8: [u8; 4] = [1, 3, 15, 105]; const ODD_DOUBLE_FACTORIALS_U16: [u16; 6] = [1, 3, 15, 105, 945, 10395]; const ODD_DOUBLE_FACTORIALS_U32: [u32; 10] = [1, 3, 15, 105, 945, 10395, 135135, 2027025, 34459425, 654729075]; const ODD_DOUBLE_FACTORIALS_U64: [u64; 17] = [ 1, 3, 15, 105, 945, 10395, 135135, 2027025, 34459425, 654729075, 13749310575, 316234143225, 7905853580625, 213458046676875, 6190283353629375, 191898783962510625, 6332659870762850625, ]; const ODD_DOUBLE_FACTORIALS_U128: [u128; 28] = [ 1, 3, 15, 105, 945, 10395, 135135, 2027025, 34459425, 654729075, 13749310575, 316234143225, 7905853580625, 213458046676875, 6190283353629375, 191898783962510625, 6332659870762850625, 221643095476699771875, 8200794532637891559375, 319830986772877770815625, 13113070457687988603440625, 563862029680583509947946875, 25373791335626257947657609375, 1192568192774434123539907640625, 58435841445947272053455474390625, 2980227913743310874726229193921875, 157952079428395476360490147277859375, 8687364368561751199826958100282265625, ]; const SUBFACTORIALS_U8: [u8; 6] = [1, 0, 1, 2, 9, 44]; const SUBFACTORIALS_U16: [u16; 9] = [1, 0, 1, 2, 9, 44, 265, 1854, 14833]; const SUBFACTORIALS_U32: [u32; 14] = [1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961, 14684570, 176214841, 2290792932]; const SUBFACTORIALS_U64: [u64; 21] = [ 1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961, 14684570, 176214841, 2290792932, 32071101049, 481066515734, 7697064251745, 130850092279664, 2355301661033953, 44750731559645106, 895014631192902121, ]; const SUBFACTORIALS_U128: [u128; 35] = [ 1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961, 14684570, 176214841, 2290792932, 32071101049, 481066515734, 7697064251745, 130850092279664, 2355301661033953, 44750731559645106, 895014631192902121, 18795307255050944540, 413496759611120779881, 9510425471055777937262, 228250211305338670494289, 5706255282633466762357224, 148362637348470135821287825, 4005791208408693667174771274, 112162153835443422680893595673, 3252702461227859257745914274516, 97581073836835777732377428235481, 3025013288941909109703700275299910, 96800425246141091510518408809597121, 3194414033122656019847107490716704992, 108610077126170304674801654684367969729, ]; macro_rules! impl_factorials_a { ($t:ident, $fs:ident, $odfs:ident, $sfs:ident, $df_limit:expr) => { impl CheckedFactorial for $t { /// Computes the factorial of a number. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n!) & \text{if} \\quad n! < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n! \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// $n! = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_factorial). #[inline] fn checked_factorial(n: u64) -> Option<$t> { $fs.get(usize::try_from(n).ok()?).copied() } } impl CheckedDoubleFactorial for $t { /// Computes the double factorial of a number. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n!!) & \text{if} \\quad n!! < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n!! \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// $n!! = O(\sqrt{n}(n/e)^{n/2})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_double_factorial). #[inline] fn checked_double_factorial(n: u64) -> Option<$t> { if n > $df_limit { None } else if n.odd() { $odfs.get(usize::try_from(n >> 1).ok()?).copied() } else { let half = n >> 1; $fs.get(usize::try_from(half).ok()?).map(|&f| f << half) } } } impl CheckedSubfactorial for $t { /// Computes the subfactorial of a number. /// /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a /// derangement is a permutation with no fixed points. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(!n) & \text{if} \\quad !n < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad !n \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_subfactorial). #[inline] fn checked_subfactorial(n: u64) -> Option<$t> { $sfs.get(usize::try_from(n).ok()?).copied() } } }; } impl_factorials_a!( u8, FACTORIALS_U8, ODD_DOUBLE_FACTORIALS_U8, SUBFACTORIALS_U8, 7 ); impl_factorials_a!( u16, FACTORIALS_U16, ODD_DOUBLE_FACTORIALS_U16, SUBFACTORIALS_U16, 12 ); impl_factorials_a!( u32, FACTORIALS_U32, ODD_DOUBLE_FACTORIALS_U32, SUBFACTORIALS_U32, 20 ); impl_factorials_a!( u64, FACTORIALS_U64, ODD_DOUBLE_FACTORIALS_U64, SUBFACTORIALS_U64, 33 ); impl_factorials_a!( u128, FACTORIALS_U128, ODD_DOUBLE_FACTORIALS_U128, SUBFACTORIALS_U128, 56 ); impl CheckedFactorial for usize { /// Computes the factorial of a [`usize`]. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n!) & \text{if} \\quad n! < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n! \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `usize::WIDTH`. /// /// $n! = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_factorial). #[inline] fn checked_factorial(n: u64) -> Option { FACTORIALS_U64 .get(Self::try_from(n).ok()?) .and_then(|&f| Self::try_from(f).ok()) } } impl CheckedSubfactorial for usize { /// Computes the subfactorial of a [`usize`]. /// /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a /// derangement is a permutation with no fixed points. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(!n) & \text{if} \\quad !n < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad !n \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `usize::WIDTH`. /// /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_subfactorial). #[inline] fn checked_subfactorial(n: u64) -> Option { SUBFACTORIALS_U64 .get(Self::try_from(n).ok()?) .and_then(|&f| Self::try_from(f).ok()) } } impl CheckedDoubleFactorial for usize { /// Computes the double factorial of a [`usize`]. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n!!) & \text{if} \\quad n!! < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n!! \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `usize::WIDTH`. /// /// $n!! = O(\sqrt{n}(n/e)^{n/2})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_double_factorial). #[inline] fn checked_double_factorial(n: u64) -> Option { if USIZE_IS_U32 { u32::checked_double_factorial(n).map(Self::wrapping_from) } else { u64::checked_double_factorial(n).map(Self::wrapping_from) } } } macro_rules! impl_factorials_b { ($t:ident) => { impl Factorial for $t { /// Computes the factorial of a number. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try [`checked_factorial`](CheckedFactorial::checked_factorial). /// /// $$ /// f(n) = n! = 1 \times 2 \times 3 \times \cdots \times n. /// $$ /// /// $n! = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::factorial#factorial). #[inline] fn factorial(n: u64) -> $t { $t::checked_factorial(n).unwrap() } } impl DoubleFactorial for $t { /// Computes the double factorial of a number. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try /// [`checked_double_factorial`](CheckedDoubleFactorial::checked_double_factorial). /// /// $$ /// f(n) = n!! = n \times (n - 2) \times (n - 4) \times \cdots \times i, /// $$ /// where $i$ is 1 if $n$ is odd and $2$ if $n$ is even. /// /// $n!! = O(\sqrt{n}(n/e)^{n/2})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::factorial#double_factorial). #[inline] fn double_factorial(n: u64) -> $t { $t::checked_double_factorial(n).unwrap() } } impl Multifactorial for $t { /// Computes a multifactorial of a number. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try /// [`checked_multifactorial`](CheckedMultifactorial::checked_multifactorial). /// /// $$ /// f(n, m) = n!^{(m)} = n \times (n - m) \times (n - 2m) \times \cdots \times i. /// $$ /// If $n$ is divisible by $m$, then $i$ is $m$; otherwise, $i$ is the remainder when /// $n$ is divided by $m$. /// /// $n!^{(m)} = O(\sqrt{n}(n/e)^{n/m})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::factorial#multifactorial). #[inline] fn multifactorial(n: u64, m: u64) -> $t { $t::checked_multifactorial(n, m).unwrap() } } impl CheckedMultifactorial for $t { /// Computes a multifactorial of a number. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n, m) = \\begin{cases} /// \operatorname{Some}(n!^{(m)}) & \text{if} \\quad n!^{(m)} < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n!^{(m)} \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// $n!^{(m)} = O(\sqrt{n}(n/e)^{n/m})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::factorial#checked_multifactorial). #[inline] fn checked_multifactorial(n: u64, m: u64) -> Option<$t> { assert_ne!(m, 0); if m == 1 { $t::checked_factorial(n) } else if m == 2 { $t::checked_double_factorial(n) } else { checked_multifactorial_naive(n, m) } } } impl Subfactorial for $t { /// Computes the subfactorial of a number. /// /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a /// derangement is a permutation with no fixed points. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try [`checked_subfactorial`](CheckedSubfactorial::checked_subfactorial). /// /// $$ /// f(n) = \\ !n = \lfloor n!/e \rfloor. /// $$ /// /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::factorial#subfactorial). #[inline] fn subfactorial(n: u64) -> $t { $t::checked_subfactorial(n).unwrap() } } }; } apply_to_unsigneds!(impl_factorials_b); ================================================ FILE: malachite-base/src/num/arithmetic/floor.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Floor, FloorAssign}; macro_rules! impl_floor { ($f:ident) => { impl Floor for $f { type Output = $f; /// This is a wrapper over the `floor` functions in [`libm`]. #[inline] fn floor(self) -> $f { libm::Libm::<$f>::floor(self) } } impl FloorAssign for $f { /// Replaces a number with its floor. /// /// A number's floor is the largest integer less than or equal to the number. /// /// $x \gets \lfloor x \rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::floor#floor_assign). #[inline] fn floor_assign(&mut self) { *self = self.floor(); } } }; } apply_to_primitive_floats!(impl_floor); ================================================ FILE: malachite-base/src/num/arithmetic/gcd.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2009, 2016 William Hart // // 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 crate::num::arithmetic::traits::{Gcd, GcdAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use core::cmp::min; #[cfg(feature = "test_build")] pub fn gcd_euclidean(x: T, y: T) -> T { if y == T::ZERO { x } else { gcd_euclidean(y, x % y) } } #[cfg(feature = "test_build")] pub fn gcd_binary(x: T, y: T) -> T { if x == y { x } else if x == T::ZERO { y } else if y == T::ZERO { x } else if x.even() { if y.odd() { gcd_binary(x >> 1, y) } else { gcd_binary(x >> 1, y >> 1) << 1 } } else if y.even() { gcd_binary(x, y >> 1) } else if x > y { gcd_binary((x - y) >> 1, y) } else { gcd_binary((y - x) >> 1, x) } } pub_test! {gcd_fast_a(mut x: T, mut y: T) -> T { if x == T::ZERO { return y; } if y == T::ZERO { return x; } let x_zeros = x.trailing_zeros(); let y_zeros = y.trailing_zeros(); let f = min(x_zeros, y_zeros); x >>= x_zeros; y >>= y_zeros; while x != y { if x < y { y -= x; y >>= y.trailing_zeros(); } else { x -= y; x >>= x.trailing_zeros(); } } x << f }} #[cfg(feature = "test_build")] // This is a modified version of `n_xgcd` from `ulong_extras/xgcd.c`, FLINT 2.7.1. pub fn gcd_fast_b(mut x: T, y: T) -> T { let mut v; if x >= y { v = y; } else { v = x; x = y; } let mut d; // x and y both have their top bit set. if (x & v).get_highest_bit() { d = x - v; x = v; v = d; } // The second value has its second-highest set. while (v << 1u32).get_highest_bit() { d = x - v; x = v; if d < v { v = d; } else if d < (v << 1) { v = d - x; } else { v = d - (x << 1); } } while v != T::ZERO { // Overflow is not possible due to top 2 bits of v not being set. Avoid divisions when // quotient < 4. if x < (v << 2) { d = x - v; x = v; if d < v { v = d; } else if d < (v << 1) { v = d - x; } else { v = d - (x << 1); } } else { let rem = x % v; x = v; v = rem; } } x } macro_rules! impl_gcd { ($t:ident) => { impl Gcd<$t> for $t { type Output = $t; /// Computes the GCD (greatest common divisor) of two numbers. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which /// makes sense if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// f(x, y) = \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::gcd#gcd). #[inline] fn gcd(self, other: $t) -> $t { gcd_fast_a(self, other) } } impl GcdAssign<$t> for $t { /// Replaces another with the GCD (greatest common divisor) of it and another number. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which /// makes sense if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// x \gets \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::gcd#gcd_assign). #[inline] fn gcd_assign(&mut self, other: $t) { *self = gcd_fast_a(*self, other); } } }; } apply_to_unsigneds!(impl_gcd); ================================================ FILE: malachite-base/src/num/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::IsPowerOf2; use crate::num::conversion::traits::IntegerMantissaAndExponent; macro_rules! impl_is_power_of_2_unsigned { ($t:ident) => { impl IsPowerOf2 for $t { /// This is a wrapper over the `is_power_of_two` functions in the standard library, for /// example [this one](u32::is_power_of_two). #[inline] fn is_power_of_2(&self) -> bool { $t::is_power_of_two(*self) } } }; } apply_to_unsigneds!(impl_is_power_of_2_unsigned); macro_rules! impl_is_power_of_2_primitive_float { ($t:ident) => { impl IsPowerOf2 for $t { /// Determines whether a number is an integer power of 2. /// /// $f(x) = (\exists n \in \Z : 2^n = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power_of_2#is_power_of_2). #[inline] fn is_power_of_2(&self) -> bool { self.is_finite() && *self > 0.0 && self.integer_mantissa() == 1 } } }; } apply_to_primitive_floats!(impl_is_power_of_2_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1996, 1998, 2000-2004, 2008, 2010 Free Software Foundation, Inc. // // Uses code adopted from the FLINT Library. // // Copyright © 2008 Peter Shrimpton // // Copyright © 2009 William Hart // // 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 crate::fail_on_untested_path; use crate::num::arithmetic::traits::{ JacobiSymbol, KroneckerSymbol, LegendreSymbol, ModPowerOf2, NegAssign, Parity, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::SplitInHalf; use crate::num::logic::traits::NotAssign; use core::mem::swap; pub_test! {jacobi_symbol_unsigned_simple(mut a: T, mut n: T) -> i8 { assert_ne!(n, T::ZERO); assert!(n.odd()); a %= n; let mut t = 1i8; while a != T::ZERO { while a.even() { a >>= 1; let r: u8 = n.mod_power_of_2(3).wrapping_into(); if r == 3 || r == 5 { t.neg_assign(); } } swap(&mut a, &mut n); if (a & n).get_bit(1) { t.neg_assign(); } a %= n; } if n == T::ONE { t } else { 0 } }} // Computes (a / b) where b is odd, and a and b are otherwise arbitrary two-limb numbers. // // This is equivalent to `mpn_jacobi_2` from `mpn/jacobi_2.c`, GMP 6.2.1, where `JACOBI_2_METHOD == // 2` and `bit` is 0. pub_test! {jacobi_symbol_unsigned_double_fast_2( mut x_1: T, mut x_0: T, mut y_1: T, mut y_0: T, ) -> i8 { assert!(y_0.odd()); if y_1 == T::ZERO && y_0 == T::ONE { // (x|1) = 1 return 1; } let mut bit = false; if x_0 == T::ZERO { if x_1 == T::ZERO { // (0|y) = 0, y > 1 return 0; } let c = x_1.trailing_zeros(); if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } x_0 = y_0; y_0 = x_1 >> c; if y_0 == T::ONE { // (1|y) = 1 return if bit { -1 } else { 1 }; } x_1 = y_1; if (x_0 & y_0).get_bit(1) { bit.not_assign(); } } else { if x_0.even() { let c = x_0.trailing_zeros(); x_0 = (x_1 << (T::WIDTH - c)) | (x_0 >> c); x_1 >>= c; if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } } let mut skip_loop = false; if x_1 == T::ZERO { if y_1 == T::ZERO { assert!(y_0.odd()); assert!(y_0 > T::ONE); let j = x_0.jacobi_symbol(y_0); return if bit { -j } else { j }; } if (x_0 & y_0).get_bit(1) { bit.not_assign(); } swap(&mut x_0, &mut y_0); x_1 = y_1; skip_loop = true; } if !skip_loop { 'outer: while y_1 != T::ZERO { // Compute (x|y) while x_1 > y_1 { (x_1, x_0) = T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); if x_0 == T::ZERO { let c = x_1.trailing_zeros(); if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } x_0 = y_0; y_0 = x_1 >> c; x_1 = y_1; if (x_0 & y_0).get_bit(1) { bit.not_assign(); } break 'outer; } let c = x_0.trailing_zeros(); if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } x_0 = (x_1 << (T::WIDTH - c)) | (x_0 >> c); x_1 >>= c; } if x_1 != y_1 { if x_1 == T::ZERO { if (x_0 & y_0).get_bit(1) { bit.not_assign(); } swap(&mut x_0, &mut y_0); x_1 = y_1; break; } if (x_0 & y_0).get_bit(1) { bit.not_assign(); } // Compute (y|x) while y_1 > x_1 { (y_1, y_0) = T::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0); if y_0 == T::ZERO { let c = y_1.trailing_zeros(); if c.odd() & (x_0 ^ (x_0 >> 1)).get_bit(1) { bit.not_assign(); } y_0 = y_1 >> c; if (x_0 & y_0).get_bit(1) { bit.not_assign(); } break 'outer; } let c = y_0.trailing_zeros(); if c.odd() & (x_0 ^ (x_0 >> 1)).get_bit(1) { bit.not_assign(); } y_0 = (y_1 << (T::WIDTH - c)) | (y_0 >> c); y_1 >>= c; } if (x_0 & y_0).get_bit(1) { bit.not_assign(); } } // Compute (x|y) if x_1 == y_1 { if x_0 < y_0 { swap(&mut x_0, &mut y_0); if (x_0 & y_0).get_bit(1) { bit.not_assign(); } } x_0 -= y_0; if x_0 == T::ZERO { return 0; } let c = x_0.trailing_zeros(); if c.odd() & (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } x_0 >>= c; if x_0 == T::ONE { return if bit { -1 } else { 1 }; } swap(&mut x_0, &mut y_0); if (x_0 & y_0).get_bit(1) { bit.not_assign(); } break; } } } } // Compute (x|y), with y a single limb. assert!(y_0.odd()); if y_0 == T::ONE { // (x|1) = 1 return if bit { -1 } else { 1 }; } while x_1 != T::ZERO { x_1 -= if x_0 < y_0 { T::ONE } else { T::ZERO }; x_0.wrapping_sub_assign(y_0); if x_0 == T::ZERO { if x_1 == T::ZERO { fail_on_untested_path( "jacobi_symbol_unsigned_double_fast_2, x_1 == T::ZERO fourth time", ); return 0; } let c = x_1.trailing_zeros(); if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } x_0 = x_1 >> c; break; } let c = x_0.trailing_zeros(); x_0 = (x_1 << (T::WIDTH - c)) | (x_0 >> c); x_1 >>= c; if c.odd() && (y_0 ^ (y_0 >> 1)).get_bit(1) { bit.not_assign(); } } assert!(y_0.odd()); assert!(y_0 > T::ONE); let j = x_0.jacobi_symbol(y_0); if bit { -j } else { j } }} fn jacobi_symbol_signed< U: PrimitiveUnsigned, S: ModPowerOf2 + PrimitiveSigned + UnsignedAbs, >( a: S, n: S, ) -> i8 { assert!(n > S::ZERO); assert!(n.odd()); let s = a.unsigned_abs().jacobi_symbol(n.unsigned_abs()); if a < S::ZERO && n.get_bit(1) { -s } else { s } } fn kronecker_symbol_unsigned(a: T, b: T) -> i8 { if b == T::ZERO { i8::from(a == T::ONE) } else if a.even() && b.even() { 0 } else { let b_twos = b.trailing_zeros(); let mut s = a.jacobi_symbol(b >> b_twos); if b_twos.odd() { let m: u32 = a.mod_power_of_2(3).wrapping_into(); if m == 3 || m == 5 { s.neg_assign(); } } s } } fn kronecker_symbol_signed + PrimitiveSigned>( a: S, b: S, ) -> i8 { if b == S::ZERO { i8::from(a == S::ONE || a == S::NEGATIVE_ONE) } else if a.even() && b.even() { 0 } else { let b_twos = b.trailing_zeros(); let mut s = a.jacobi_symbol((b >> b_twos).abs()); if a < S::ZERO && b < S::ZERO { s.neg_assign(); } if b_twos.odd() { let m: u32 = a.mod_power_of_2(3).wrapping_into(); if m == 3 || m == 5 { s.neg_assign(); } } s } } macro_rules! impl_symbols { ($u:ident, $s:ident) => { impl LegendreSymbol<$u> for $u { /// Computes the Legendre symbol of two numbers. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Panics /// Panics if `n` is even. /// /// # Examples /// See [here](super::kronecker_symbol#legendre_symbol). #[inline] fn legendre_symbol(self, n: $u) -> i8 { self.jacobi_symbol(n) } } impl LegendreSymbol<$s> for $s { /// Computes the Legendre symbol of two numbers. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Panics /// Panics if `n` is even or negative. /// /// # Examples /// See [here](super::kronecker_symbol#legendre_symbol). #[inline] fn legendre_symbol(self, n: $s) -> i8 { self.jacobi_symbol(n) } } impl JacobiSymbol<$s> for $s { /// Computes the Jacobi symbol of two numbers. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Panics /// Panics if `n` is even. /// /// # Examples /// See [here](super::kronecker_symbol#jacobi_symbol). #[inline] fn jacobi_symbol(self, n: $s) -> i8 { jacobi_symbol_signed::<$u, $s>(self, n) } } impl KroneckerSymbol<$u> for $u { /// Computes the Kronecker symbol of two numbers. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::kronecker_symbol#kronecker_symbol). #[inline] fn kronecker_symbol(self, n: $u) -> i8 { kronecker_symbol_unsigned(self, n) } } impl KroneckerSymbol<$s> for $s { /// Computes the Kronecker symbol of two numbers. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::kronecker_symbol#kronecker_symbol). #[inline] fn kronecker_symbol(self, n: $s) -> i8 { kronecker_symbol_signed::<$u, $s>(self, n) } } }; } apply_to_unsigned_signed_pairs!(impl_symbols); macro_rules! impl_jacobi_symbol_unsigned { ($u:ident) => { /// Computes the Jacobi symbol of two numbers. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `n` is even or negative. /// /// # Examples /// See [here](super::kronecker_symbol#jacobi_symbol). impl JacobiSymbol<$u> for $u { #[inline] fn jacobi_symbol(self, n: $u) -> i8 { jacobi_symbol_unsigned_simple(self, n) } } }; } impl_jacobi_symbol_unsigned!(u8); impl_jacobi_symbol_unsigned!(u16); impl_jacobi_symbol_unsigned!(u32); impl_jacobi_symbol_unsigned!(u64); impl_jacobi_symbol_unsigned!(usize); impl JacobiSymbol for u128 { /// Computes the Jacobi symbol of two `u128`s. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// See [here](super::kronecker_symbol#jacobi_symbol). #[inline] fn jacobi_symbol(self, n: Self) -> i8 { let (x_1, x_0) = self.split_in_half(); let (y_1, y_0) = n.split_in_half(); jacobi_symbol_unsigned_double_fast_2(x_1, x_0, y_1, y_0) } } ================================================ FILE: malachite-base/src/num/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedLcm, Lcm, LcmAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; #[inline] fn lcm(x: T, y: T) -> T { checked_lcm(x, y).unwrap() } fn checked_lcm(x: T, y: T) -> Option { if x == T::ZERO && y == T::ZERO { Some(T::ZERO) } else { (x / x.gcd(y)).checked_mul(y) } } macro_rules! impl_lcm { ($t:ident) => { impl Lcm<$t> for $t { type Output = $t; /// Computes the LCM (least common multiple) of two numbers. /// /// $$ /// f(x, y) = \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Panics /// Panics if the result is too large to be represented. /// /// # Examples /// See [here](super::lcm#lcm). #[inline] fn lcm(self, other: $t) -> $t { lcm(self, other) } } impl LcmAssign<$t> for $t { /// Replaces a number with the LCM (least common multiple) of it and another number. /// /// $$ /// x \gets \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Panics /// Panics if the result is too large to be represented. /// /// # Examples /// See [here](super::lcm#lcm_assign). #[inline] fn lcm_assign(&mut self, other: $t) { *self = lcm(*self, other); } } impl CheckedLcm<$t> for $t { type Output = $t; /// Computes the LCM (least common multiple) of two numbers, returning `None` if the /// result is too large to represent. /// /// $$ /// f(x, y) = \\begin{cases} /// \operatorname{Some}(\operatorname{lcm}(x, y)) & /// \text{if} \\quad \operatorname{lcm}(x, y) < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad \operatorname{lcm}(x, y) \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// See [here](super::lcm#checked_lcm). #[inline] fn checked_lcm(self, other: $t) -> Option<$t> { checked_lcm(self, other) } } }; } apply_to_unsigneds!(impl_lcm); ================================================ FILE: malachite-base/src/num/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CeilingLogBase, CheckedLogBase, FloorLogBase}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn floor_log_base_naive(x: T, base: T) -> u64 { assert_ne!(x, T::ZERO); assert!(base > T::ONE); let mut result = 0; let mut p = T::ONE; // loop always executes at least once while p <= x { result += 1; if let Some(next_p) = p.checked_mul(base) { p = next_p; } else { break; } } result - 1 } pub_test! {ceiling_log_base_naive(x: T, base: T) -> u64 { assert_ne!(x, T::ZERO); assert!(base > T::ONE); let mut result = 0; let mut p = T::ONE; while p < x { result += 1; if let Some(next_p) = p.checked_mul(base) { p = next_p; } else { break; } } result }} pub_test! {checked_log_base_naive(x: T, base: T) -> Option { assert_ne!(x, T::ZERO); assert!(base > T::ONE); let mut result = 0; let mut p = T::ONE; while p < x { result += 1; if let Some(next_p) = p.checked_mul(base) { p = next_p; } else { return None; } } if p == x { Some(result) } else { None } }} fn floor_log_base(x: T, base: T) -> u64 { if let Some(log_base) = base.checked_log_base_2() { x.floor_log_base_power_of_2(log_base) } else { floor_log_base_naive(x, base) } } fn ceiling_log_base(x: T, base: T) -> u64 { if let Some(log_base) = base.checked_log_base_2() { x.ceiling_log_base_power_of_2(log_base) } else { ceiling_log_base_naive(x, base) } } fn checked_log_base(x: T, base: T) -> Option { if let Some(log_base) = base.checked_log_base_2() { x.checked_log_base_power_of_2(log_base) } else { checked_log_base_naive(x, base) } } macro_rules! impl_log_base_unsigned { ($t:ident) => { impl FloorLogBase for $t { type Output = u64; /// Returns the floor of the base-$b$ logarithm of a positive integer. /// /// $f(x, b) = \lfloor\log_b x\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits() / /// base.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// See [here](super::log_base#floor_log_base). #[inline] fn floor_log_base(self, base: $t) -> u64 { // TODO use ilog once stabilized floor_log_base(self, base) } } impl CeilingLogBase for $t { type Output = u64; /// Returns the ceiling of the base-$b$ logarithm of a positive integer. /// /// $f(x, b) = \lceil\log_b x\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits() / /// base.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// See [here](super::log_base#ceiling_log_base). #[inline] fn ceiling_log_base(self, base: $t) -> u64 { ceiling_log_base(self, base) } } impl CheckedLogBase for $t { type Output = u64; /// Returns the base-$b$ logarithm of a positive integer. If the integer is not a power /// of $b$, `None` is returned. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(\log_b x) & \text{if} \\quad \log_b x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits() / /// base.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// See [here](super::log_base#checked_log_base). #[inline] fn checked_log_base(self, base: $t) -> Option { checked_log_base(self, base) } } }; } apply_to_unsigneds!(impl_log_base_unsigned); ================================================ FILE: malachite-base/src/num/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CeilingLogBase2, CheckedLogBase2, FloorLogBase2}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::SciMantissaAndExponent; use crate::num::logic::traits::{LeadingZeros, TrailingZeros}; fn floor_log_base_2(x: T) -> u64 { assert!(x != T::ZERO, "Cannot take the base-2 logarithm of 0."); x.significant_bits() - 1 } fn ceiling_log_base_2(x: T) -> u64 { let floor_log_base_2 = x.floor_log_base_2(); if x.is_power_of_2() { floor_log_base_2 } else { floor_log_base_2 + 1 } } fn checked_log_base_2(x: T) -> Option { assert!(x != T::ZERO, "Cannot take the base-2 logarithm of 0."); let leading_zeros = LeadingZeros::leading_zeros(x); let trailing_zeros = TrailingZeros::trailing_zeros(x); if leading_zeros + trailing_zeros == T::WIDTH - 1 { Some(trailing_zeros) } else { None } } macro_rules! impl_log_base_2_unsigned { ($t:ident) => { impl FloorLogBase2 for $t { type Output = u64; /// Returns the floor of the base-2 logarithm of a positive integer. /// /// $f(x) = \lfloor\log_2 x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// See [here](super::log_base_2#floor_log_base_2). #[inline] fn floor_log_base_2(self) -> u64 { // TODO use ilog2 once stabilized floor_log_base_2(self) } } impl CeilingLogBase2 for $t { type Output = u64; /// Returns the ceiling of the base-2 logarithm of a positive integer. /// /// $f(x) = \lceil\log_2 x\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// See [here](super::log_base_2#ceiling_log_base_2). #[inline] fn ceiling_log_base_2(self) -> u64 { ceiling_log_base_2(self) } } impl CheckedLogBase2 for $t { type Output = u64; /// Returns the base-2 logarithm of a positive integer. If the integer is not a power of /// 2, `None` is returned. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\log_2 x) & \text{if} \\quad \log_2 x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// See [here](super::log_base_2#checked_log_base_2). #[inline] fn checked_log_base_2(self) -> Option { checked_log_base_2(self) } } }; } apply_to_unsigneds!(impl_log_base_2_unsigned); macro_rules! impl_log_base_2_primitive_float { ($t:ident) => { impl FloorLogBase2 for $t { type Output = i64; /// Returns the floor of the base-2 logarithm of a positive float. /// /// $f(x) = \lfloor\log_2 x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero. /// /// # Examples /// See [here](super::log_base_2#floor_log_base_2). #[inline] fn floor_log_base_2(self) -> i64 { assert!(self > 0.0); self.sci_exponent() } } impl CeilingLogBase2 for $t { type Output = i64; /// Returns the ceiling of the base-2 logarithm of a positive float. /// /// $f(x) = \lceil\log_2 x\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero. /// /// # Examples /// See [here](super::log_base_2#ceiling_log_base_2). #[inline] fn ceiling_log_base_2(self) -> i64 { assert!(self > 0.0); let (mantissa, exponent) = self.sci_mantissa_and_exponent(); if mantissa == 1.0 { exponent } else { exponent + 1 } } } impl CheckedLogBase2 for $t { type Output = i64; /// Returns the base-2 logarithm of a positive float If the float is not a power of 2, /// `None` is returned. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\log_2 x) & \text{if} \\quad \log_2 x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero. /// /// # Examples /// See [here](super::log_base_2#checked_log_base_2). #[inline] fn checked_log_base_2(self) -> Option { assert!(self > 0.0); let (mantissa, exponent) = self.sci_mantissa_and_exponent(); if mantissa == 1.0 { Some(exponent) } else { None } } } }; } apply_to_primitive_floats!(impl_log_base_2_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ CeilingLogBasePowerOf2, CheckedLogBasePowerOf2, DivMod, DivRound, FloorLogBasePowerOf2, }; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; use crate::rounding_modes::RoundingMode::*; #[cfg(feature = "test_build")] pub fn ceiling_log_base_power_of_2_naive(x: T, pow: u64) -> u64 { assert_ne!(x, T::ZERO); assert_ne!(pow, 0); if pow >= T::WIDTH { return u64::from(x != T::ONE); } let mut result = 0; let mut p = T::ONE; while p < x { let highest_possible = p.leading_zeros() < pow; result += 1; if highest_possible { break; } p <<= pow; } result } fn floor_log_base_power_of_2(x: T, pow: u64) -> u64 { assert!(x != T::ZERO, "Cannot take the base-2 logarithm of 0."); assert_ne!(pow, 0); (x.significant_bits() - 1) / pow } fn ceiling_log_base_power_of_2(x: T, pow: u64) -> u64 { assert!(x != T::ZERO, "Cannot take the base-2 logarithm of 0."); assert_ne!(pow, 0); let (floor_log, rem) = (x.significant_bits() - 1).div_mod(pow); if rem == 0 && T::is_power_of_2(&x) { floor_log } else { floor_log + 1 } } fn checked_log_base_power_of_2(x: T, pow: u64) -> Option { assert!(x != T::ZERO, "Cannot take the base-2 logarithm of 0."); assert_ne!(pow, 0); let (floor_log, rem) = (x.significant_bits() - 1).div_mod(pow); if rem == 0 && T::is_power_of_2(&x) { Some(floor_log) } else { None } } macro_rules! impl_log_base_power_of_2_unsigned { ($t:ident) => { impl FloorLogBasePowerOf2 for $t { type Output = u64; /// Returns the floor of the base-$2^k$ logarithm of a positive integer. /// /// $f(x, k) = \lfloor\log_{2^k} x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero, or if `pow` is /// zero. /// /// # Examples /// See [here](super::log_base_power_of_2#floor_log_base_power_of_2). #[inline] fn floor_log_base_power_of_2(self, pow: u64) -> u64 { floor_log_base_power_of_2(self, pow) } } impl CeilingLogBasePowerOf2 for $t { type Output = u64; /// Returns the ceiling of the base-$2^k$ logarithm of a positive integer. /// /// $f(x, k) = \lceil\log_{2^k} x\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero, or if `pow` is /// zero. /// /// # Examples /// See [here](super::log_base_power_of_2#ceiling_log_base_power_of_2). #[inline] fn ceiling_log_base_power_of_2(self, pow: u64) -> u64 { ceiling_log_base_power_of_2(self, pow) } } impl CheckedLogBasePowerOf2 for $t { type Output = u64; /// Returns the base-$2^k$ logarithm of a positive integer. If the integer is not a /// power of $2^k$, `None` is returned. /// /// $$ /// f(x, k) = \\begin{cases} /// \operatorname{Some}(\log_{2^k} x) & \text{if} \\quad \log_{2^k} x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is infinite, `NaN`, or less than or equal to zero, or if `pow` is /// zero. /// /// # Examples /// See [here](super::log_base_power_of_2#ceiling_log_base_power_of_2). #[inline] fn checked_log_base_power_of_2(self, pow: u64) -> Option { checked_log_base_power_of_2(self, pow) } } }; } apply_to_unsigneds!(impl_log_base_power_of_2_unsigned); macro_rules! impl_log_base_power_of_2_primitive_float { ($t:ident) => { impl FloorLogBasePowerOf2 for $t { type Output = i64; /// Returns the floor of the base-$2^k$ logarithm of a positive float. /// /// $f(x, k) = \lfloor\log_{2^k} x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `pow` are 0. /// /// # Examples /// See [here](super::log_base_power_of_2#floor_log_base_power_of_2). #[inline] fn floor_log_base_power_of_2(self, pow: u64) -> i64 { assert!(self > 0.0); self.sci_exponent().div_round(i64::exact_from(pow), Floor).0 } } impl CeilingLogBasePowerOf2 for $t { type Output = i64; /// Returns the ceiling of the base-$2^k$ logarithm of a positive float. /// /// $f(x, k) = \lceil\log_{2^k} x\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `pow` are 0. /// /// # Examples /// See [here](super::log_base_power_of_2#ceiling_log_base_power_of_2). #[inline] fn ceiling_log_base_power_of_2(self, pow: u64) -> i64 { assert!(self > 0.0); let (mantissa, exponent) = self.sci_mantissa_and_exponent(); let exact = mantissa == 1.0; let (q, r) = exponent.div_mod(i64::exact_from(pow)); if exact && r == 0 { q } else { q + 1 } } } impl CheckedLogBasePowerOf2 for $t { type Output = i64; /// Returns the base-$2^k$ logarithm of a positive float. If the float is not a power of /// $2^k$, `None` is returned. /// /// $$ /// f(x, k) = \\begin{cases} /// \operatorname{Some}(\log_{2^k} x) & \text{if} \\quad \log_{2^k} x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `pow` are 0. /// /// # Examples /// See [here](super::log_base_power_of_2#checked_log_base_power_of_2). #[inline] fn checked_log_base_power_of_2(self, pow: u64) -> Option { assert!(self > 0.0); let (mantissa, exponent) = self.sci_mantissa_and_exponent(); if mantissa != 1.0 { return None; } let (q, r) = exponent.div_mod(i64::exact_from(pow)); if r == 0 { Some(q) } else { None } } } }; } apply_to_primitive_floats!(impl_log_base_power_of_2_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . /// [`Abs`](traits::Abs), [`AbsAssign`](traits::AbsAssign), and /// [`UnsignedAbs`](traits::UnsignedAbs), traits for getting the absolute value of a number. /// /// # abs_assign /// ``` /// use malachite_base::num::arithmetic::traits::AbsAssign; /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::float::NiceFloat; /// /// let mut x = 0i8; /// x.abs_assign(); /// assert_eq!(x, 0i8); /// /// let mut x = 100i64; /// x.abs_assign(); /// assert_eq!(x, 100i64); /// /// let mut x = -100i64; /// x.abs_assign(); /// assert_eq!(x, 100i64); /// /// let mut x = -0.0; /// x.abs_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(0.0)); /// /// let mut x = f64::NEGATIVE_INFINITY; /// x.abs_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(f64::INFINITY)); /// /// let mut x = 100.0; /// x.abs_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(100.0)); /// /// let mut x = -100.0; /// x.abs_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(100.0)); /// ``` pub mod abs; /// [`AbsDiff`](traits::AbsDiff) and [`AbsDiffAssign`](traits::AbsDiffAssign), traits for getting /// the absolute value of the difference between two numbers. /// /// # abs_diff /// ``` /// assert_eq!(10u8.abs_diff(20u8), 10u8); /// assert_eq!(10i8.abs_diff(-10i8), 20u8); /// ``` /// /// # abs_diff_assign /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiffAssign; /// /// let mut x = 10u8; /// x.abs_diff_assign(20u8); /// assert_eq!(x, 10); /// ``` pub mod abs_diff; /// [`AddMul`](traits::AddMul) and [`AddMulAssign`](traits::AddMulAssign), traits for adding a /// number and the product of two other numbers. /// /// # add_mul /// ``` /// use malachite_base::num::arithmetic::traits::AddMul; /// /// assert_eq!(2u8.add_mul(3, 7), 23); /// assert_eq!(127i8.add_mul(-2, 100), -73); /// assert_eq!(1.0f32.add_mul(2.0, 3.0), 7.0); /// ``` /// /// # add_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::AddMulAssign; /// /// let mut x = 2u8; /// x.add_mul_assign(3, 7); /// assert_eq!(x, 23); /// /// let mut x = 127i8; /// x.add_mul_assign(-2, 100); /// assert_eq!(x, -73); /// /// let mut x = 1.0f32; /// x.add_mul_assign(2.0, 3.0); /// assert_eq!(x, 7.0); /// ``` pub mod add_mul; /// [`ArithmeticCheckedShl`](traits::ArithmeticCheckedShl), a trait for left-shifting a number and /// checking whether the result is representable. /// /// # arithmetic_checked_shl /// ``` /// use malachite_base::num::arithmetic::traits::ArithmeticCheckedShl; /// /// assert_eq!(3u8.arithmetic_checked_shl(6), Some(192u8)); /// assert_eq!(3u8.arithmetic_checked_shl(7), None); /// assert_eq!(3u8.arithmetic_checked_shl(100), None); /// assert_eq!(0u8.arithmetic_checked_shl(100), Some(0u8)); /// /// assert_eq!(3u8.arithmetic_checked_shl(6), Some(192u8)); /// assert_eq!(3u8.arithmetic_checked_shl(7), None); /// assert_eq!(3u8.arithmetic_checked_shl(100), None); /// assert_eq!(0u8.arithmetic_checked_shl(100), Some(0u8)); /// assert_eq!(100u8.arithmetic_checked_shl(-3), Some(12u8)); /// assert_eq!(100u8.arithmetic_checked_shl(-100), Some(0u8)); /// /// assert_eq!(3i8.arithmetic_checked_shl(5), Some(96i8)); /// assert_eq!(3i8.arithmetic_checked_shl(6), None); /// assert_eq!((-3i8).arithmetic_checked_shl(5), Some(-96i8)); /// assert_eq!((-3i8).arithmetic_checked_shl(6), None); /// assert_eq!(3i8.arithmetic_checked_shl(100), None); /// assert_eq!((-3i8).arithmetic_checked_shl(100), None); /// assert_eq!(0i8.arithmetic_checked_shl(100), Some(0i8)); /// /// assert_eq!(3i8.arithmetic_checked_shl(5), Some(96i8)); /// assert_eq!(3i8.arithmetic_checked_shl(6), None); /// assert_eq!((-3i8).arithmetic_checked_shl(5), Some(-96i8)); /// assert_eq!((-3i8).arithmetic_checked_shl(6), None); /// assert_eq!(3i8.arithmetic_checked_shl(100), None); /// assert_eq!((-3i8).arithmetic_checked_shl(100), None); /// assert_eq!(0i8.arithmetic_checked_shl(100), Some(0i8)); /// assert_eq!(100i8.arithmetic_checked_shl(-3), Some(12i8)); /// assert_eq!((-100i8).arithmetic_checked_shl(-3), Some(-13i8)); /// assert_eq!(100i8.arithmetic_checked_shl(-100), Some(0i8)); /// assert_eq!((-100i8).arithmetic_checked_shl(-100), Some(-1i8)); /// ``` pub mod arithmetic_checked_shl; /// [`ArithmeticCheckedShr`](traits::ArithmeticCheckedShr), a trait for right-shifting a number and /// checking whether the result is representable. /// /// # arithmetic_checked_shr /// ``` /// use malachite_base::num::arithmetic::traits::ArithmeticCheckedShr; /// /// assert_eq!(100u8.arithmetic_checked_shr(3), Some(12u8)); /// assert_eq!(100u8.arithmetic_checked_shr(100), Some(0u8)); /// assert_eq!(3u8.arithmetic_checked_shr(-6), Some(192u8)); /// assert_eq!(3u8.arithmetic_checked_shr(-7), None); /// assert_eq!(3u8.arithmetic_checked_shr(-100), None); /// assert_eq!(0u8.arithmetic_checked_shr(-100), Some(0u8)); /// /// assert_eq!(100i8.arithmetic_checked_shr(3), Some(12i8)); /// assert_eq!((-100i8).arithmetic_checked_shr(3), Some(-13i8)); /// assert_eq!(100i8.arithmetic_checked_shr(100), Some(0i8)); /// assert_eq!((-100i8).arithmetic_checked_shr(100), Some(-1i8)); /// assert_eq!(3i8.arithmetic_checked_shr(-5), Some(96i8)); /// assert_eq!(3i8.arithmetic_checked_shr(-6), None); /// assert_eq!((-3i8).arithmetic_checked_shr(-5), Some(-96i8)); /// assert_eq!((-3i8).arithmetic_checked_shr(-6), None); /// assert_eq!(3i8.arithmetic_checked_shr(-100), None); /// assert_eq!((-3i8).arithmetic_checked_shr(-100), None); /// assert_eq!(0i8.arithmetic_checked_shr(-100), Some(0i8)); /// ``` pub mod arithmetic_checked_shr; /// Traits for computing the binomial coefficient of two numbers. There is a trait whose /// implementations panic if the result cannot be represented, and a checked trait whose /// implementations return `None` in that case: [`BinomialCoefficient`](traits::BinomialCoefficient) /// and [`CheckedBinomialCoefficient`](traits::CheckedBinomialCoefficient). /// /// # binomial_coefficient /// ``` /// use malachite_base::num::arithmetic::traits::BinomialCoefficient; /// /// assert_eq!(u8::binomial_coefficient(3, 0), 1); /// assert_eq!(u8::binomial_coefficient(3, 1), 3); /// assert_eq!(u8::binomial_coefficient(3, 2), 3); /// assert_eq!(u8::binomial_coefficient(3, 3), 1); /// assert_eq!(u8::binomial_coefficient(10, 5), 252); /// /// assert_eq!(i8::binomial_coefficient(-3, 0), 1); /// assert_eq!(i8::binomial_coefficient(-3, 1), -3); /// assert_eq!(i8::binomial_coefficient(-3, 2), 6); /// assert_eq!(i8::binomial_coefficient(-3, 3), -10); /// ``` /// /// # checked_binomial_coefficient /// ``` /// use malachite_base::num::arithmetic::traits::CheckedBinomialCoefficient; /// /// assert_eq!(u8::checked_binomial_coefficient(3, 0), Some(1)); /// assert_eq!(u8::checked_binomial_coefficient(3, 1), Some(3)); /// assert_eq!(u8::checked_binomial_coefficient(3, 2), Some(3)); /// assert_eq!(u8::checked_binomial_coefficient(3, 3), Some(1)); /// assert_eq!(u8::checked_binomial_coefficient(10, 5), Some(252)); /// assert_eq!(u8::checked_binomial_coefficient(11, 5), None); /// /// assert_eq!(i8::checked_binomial_coefficient(-3, 0), Some(1)); /// assert_eq!(i8::checked_binomial_coefficient(-3, 1), Some(-3)); /// assert_eq!(i8::checked_binomial_coefficient(-3, 2), Some(6)); /// assert_eq!(i8::checked_binomial_coefficient(-3, 3), Some(-10)); /// assert_eq!(i8::checked_binomial_coefficient(-3, -3), None); /// assert_eq!(i8::checked_binomial_coefficient(11, 5), None); /// ``` pub mod binomial_coefficient; /// [`Ceiling`](traits::Ceiling) and [`CeilingAssign`](traits::CeilingAssign), traits for computing /// the ceiling of a number. /// /// # ceiling /// ``` /// use malachite_base::num::arithmetic::traits::CeilingAssign; /// /// let mut x = 1.5f32; /// x.ceiling_assign(); /// assert_eq!(x, 2.0); /// /// let mut x = -1.5f32; /// x.ceiling_assign(); /// assert_eq!(x, -1.0); /// ``` pub mod ceiling; /// [`CheckedAbs`](traits::CheckedAbs), a trait for computing the absolute value of number and /// checking whether the result is representable. pub mod checked_abs; /// [`CheckedAdd`](traits::CheckedAdd), a trait for adding two numbers and checking whether the /// result is representable. pub mod checked_add; /// [`CheckedAddMul`](traits::CheckedAddMul), a trait for adding a number and the product of two /// other numbers, and checking whether the result is representable. /// /// # checked_add_mul /// ``` /// use malachite_base::num::arithmetic::traits::CheckedAddMul; /// /// assert_eq!(2u8.checked_add_mul(3, 7), Some(23)); /// assert_eq!(2u8.checked_add_mul(20, 20), None); /// /// assert_eq!(127i8.checked_add_mul(-2, 100), Some(-73)); /// assert_eq!((-127i8).checked_add_mul(-2, 100), None); /// ``` pub mod checked_add_mul; /// [`CheckedDiv`](traits::CheckedDiv), a trait for dividing two numbers and checking whether the /// result is representable. pub mod checked_div; /// [`CheckedMul`](traits::CheckedMul), a trait for multiplying two numbers and checking whether the /// result is representable. pub mod checked_mul; /// [`CheckedNeg`](traits::CheckedNeg), a trait for negating a number and checking whether the /// result is representable. pub mod checked_neg; /// [`CheckedNextPowerOf2`](traits::CheckedNextPowerOf2), a trait for getting the next-highest power /// of 2, if it's representable. pub mod checked_next_power_of_2; /// [`CheckedPow`](traits::CheckedPow), a trait for raising a number to the power of a [`u64`] and /// checking whether the result is representable. pub mod checked_pow; /// [`CheckedSquare`](traits::CheckedSquare), a trait for squaring a number and checking whether the /// result is representable. /// /// # checked_square /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSquare; /// /// assert_eq!(3u8.checked_square(), Some(9)); /// assert_eq!((-1000i32).checked_square(), Some(1000000)); /// assert_eq!((1000u16).checked_square(), None); /// ``` pub mod checked_square; /// [`CheckedSub`](traits::CheckedSub), a trait for subtracting two numbers and checking whether the /// result is representable. pub mod checked_sub; /// [`CheckedSubMul`](traits::CheckedSubMul), a trait for subtracting the product of two numbers /// from another number, and checking whether the result is representable. /// /// # checked_sub_mul /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSubMul; /// /// assert_eq!(60u8.checked_sub_mul(5, 10), Some(10)); /// assert_eq!(2u8.checked_sub_mul(10, 5), None); /// /// assert_eq!(127i8.checked_sub_mul(2, 100), Some(-73)); /// assert_eq!((-127i8).checked_sub_mul(2, 100), None); /// ``` pub mod checked_sub_mul; /// [`CoprimeWith`](traits::CoprimeWith), a trait for determining whether two numbers are coprime. /// /// # coprime_with /// ``` /// use malachite_base::num::arithmetic::traits::CoprimeWith; /// /// assert_eq!(0u8.coprime_with(0), false); /// assert_eq!(0u8.coprime_with(1), true); /// assert_eq!(6u8.coprime_with(1), true); /// assert_eq!(3u8.coprime_with(5), true); /// assert_eq!(6u8.coprime_with(4), false); /// assert_eq!(6u8.coprime_with(35), true); /// ``` pub mod coprime_with; /// [`DivExact`](traits::DivExact) and [`DivExactAssign`](traits::DivExactAssign), traits for /// dividing two numbers when it's known that the division is exact. /// /// # div_exact /// ``` /// use malachite_base::num::arithmetic::traits::DivExact; /// /// // 123 * 456 = 56088 /// #[allow(unstable_name_collisions)] /// { /// assert_eq!(56088u32.div_exact(456), 123); /// } /// /// // -123 * -456 = 56088 /// #[allow(unstable_name_collisions)] /// { /// assert_eq!(56088i64.div_exact(-456), -123); /// } /// ``` /// /// # div_exact_assign /// ``` /// use malachite_base::num::arithmetic::traits::DivExactAssign; /// /// // 123 * 456 = 56088 /// let mut x = 56088u32; /// x.div_exact_assign(456); /// assert_eq!(x, 123); /// /// // -123 * -456 = 56088 /// let mut x = 56088i64; /// x.div_exact_assign(-456); /// assert_eq!(x, -123); /// ``` pub mod div_exact; /// Traits for simultaneously finding the quotient and remainder of two numbers, subject to various /// rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |--------------|---------------------------------|----------------------------------------| /// | towards $-\infty$ | [`DivMod`](traits::DivMod) | [`DivAssignMod`](traits::DivAssignMod) | /// | towards 0 | [`DivRem`](traits::DivRem) | [`DivAssignRem`](traits::DivAssignRem) | /// | towards $\infty$ | [`CeilingDivMod`](traits::CeilingDivMod) | [`CeilingDivAssignMod`](traits::CeilingDivAssignMod) | /// | towards $\infty$ | [`CeilingDivNegMod`](traits::CeilingDivNegMod) | [`CeilingDivAssignNegMod`](traits::CeilingDivAssignNegMod) | /// /// [`CeilingDivMod`](traits::CeilingDivMod) and [`CeilingDivNegMod`](traits::CeilingDivNegMod) are /// similar. The difference is that [`CeilingDivMod`](traits::CeilingDivMod) returns a remainder /// less than or equal to 0, so that the usual relation $x = qy + r$ is satisfied, while /// [`CeilingDivNegMod`](traits::CeilingDivNegMod) returns a remainder greater than or equal to /// zero. This allows the remainder to have an unsigned type, but modifies the relation to $x = qy /// - r$. /// /// # div_mod /// ``` /// use malachite_base::num::arithmetic::traits::DivMod; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23u8.div_mod(10), (2, 3)); /// /// // 9 * 5 + 0 = 45 /// assert_eq!(45u32.div_mod(5), (9, 0)); /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23i8.div_mod(10), (2, 3)); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(23i16.div_mod(-10), (-3, -7)); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((-23i32).div_mod(10), (-3, 7)); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((-23i64).div_mod(-10), (2, -3)); /// ``` /// /// # div_assign_mod /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// /// // 2 * 10 + 3 = 23 /// let mut x = 23u8; /// assert_eq!(x.div_assign_mod(10), 3); /// assert_eq!(x, 2); /// /// // 9 * 5 + 0 = 45 /// let mut x = 45u32; /// assert_eq!(x.div_assign_mod(5), 0); /// assert_eq!(x, 9); /// /// // 2 * 10 + 3 = 23 /// let mut x = 23i8; /// assert_eq!(x.div_assign_mod(10), 3); /// assert_eq!(x, 2); /// /// // -3 * -10 + -7 = 23 /// let mut x = 23i16; /// assert_eq!(x.div_assign_mod(-10), -7); /// assert_eq!(x, -3); /// /// // -3 * 10 + 7 = -23 /// let mut x = -23i32; /// assert_eq!(x.div_assign_mod(10), 7); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = -23i64; /// assert_eq!(x.div_assign_mod(-10), -3); /// assert_eq!(x, 2); /// ``` /// /// # div_rem /// ``` /// use malachite_base::num::arithmetic::traits::DivRem; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23u8.div_rem(10), (2, 3)); /// /// // 9 * 5 + 0 = 45 /// assert_eq!(45u32.div_rem(5), (9, 0)); /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23i8.div_rem(10), (2, 3)); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(23i16.div_rem(-10), (-2, 3)); /// /// // -2 * 10 + -3 = -23 /// assert_eq!((-23i32).div_rem(10), (-2, -3)); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((-23i64).div_rem(-10), (2, -3)); /// ``` /// /// # div_assign_rem /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignRem; /// /// // 2 * 10 + 3 = 23 /// let mut x = 23u8; /// assert_eq!(x.div_assign_rem(10), 3); /// assert_eq!(x, 2); /// /// // 9 * 5 + 0 = 45 /// let mut x = 45u32; /// assert_eq!(x.div_assign_rem(5), 0); /// assert_eq!(x, 9); /// /// // 2 * 10 + 3 = 23 /// let mut x = 23i8; /// assert_eq!(x.div_assign_rem(10), 3); /// assert_eq!(x, 2); /// /// // -2 * -10 + 3 = 23 /// let mut x = 23i16; /// assert_eq!(x.div_assign_rem(-10), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = -23i32; /// assert_eq!(x.div_assign_rem(10), -3); /// assert_eq!(x, -2); /// /// // 2 * -10 + -3 = -23 /// let mut x = -23i64; /// assert_eq!(x.div_assign_rem(-10), -3); /// assert_eq!(x, 2); /// ``` /// /// # ceiling_div_neg_mod /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivNegMod; /// /// // 3 * 10 - 7 = 23 /// assert_eq!(23u8.ceiling_div_neg_mod(10), (3, 7)); /// /// // 9 * 5 + 0 = 45 /// assert_eq!(45u32.ceiling_div_neg_mod(5), (9, 0)); /// ``` /// /// # ceiling_div_assign_neg_mod /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivAssignNegMod; /// /// // 3 * 10 - 7 = 23 /// let mut x = 23u8; /// assert_eq!(x.ceiling_div_assign_neg_mod(10), 7); /// assert_eq!(x, 3); /// /// // 9 * 5 + 0 = 45 /// let mut x = 45u32; /// assert_eq!(x.ceiling_div_assign_neg_mod(5), 0); /// assert_eq!(x, 9); /// ``` /// /// # ceiling_div_mod /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivMod; /// /// // 3 * 10 + -7 = 23 /// assert_eq!(23i8.ceiling_div_mod(10), (3, -7)); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(23i16.ceiling_div_mod(-10), (-2, 3)); /// /// // -2 * 10 + -3 = -23 /// assert_eq!((-23i32).ceiling_div_mod(10), (-2, -3)); /// /// // 3 * -10 + 7 = -23 /// assert_eq!((-23i64).ceiling_div_mod(-10), (3, 7)); /// ``` /// /// # ceiling_div_assign_mod /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivAssignMod; /// /// // 3 * 10 + -7 = 23 /// let mut x = 23i8; /// assert_eq!(x.ceiling_div_assign_mod(10), -7); /// assert_eq!(x, 3); /// /// // -2 * -10 + 3 = 23 /// let mut x = 23i16; /// assert_eq!(x.ceiling_div_assign_mod(-10), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = -23i32; /// assert_eq!(x.ceiling_div_assign_mod(10), -3); /// assert_eq!(x, -2); /// /// // 3 * -10 + 7 = -23 /// let mut x = -23i64; /// assert_eq!(x.ceiling_div_assign_mod(-10), 7); /// assert_eq!(x, 3); /// ``` pub mod div_mod; /// [`DivRound`](traits::DivRound) and [`DivExactAssign`](traits::DivRoundAssign), traits for /// dividing two numbers according to a specified /// [`RoundingMode`](crate::rounding_modes::RoundingMode). /// /// # div_round /// ``` /// use malachite_base::num::arithmetic::traits::DivRound; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(10u8.div_round(4, Down), (2, Less)); /// assert_eq!(10u16.div_round(4, Up), (3, Greater)); /// assert_eq!(10u32.div_round(5, Exact), (2, Equal)); /// assert_eq!(10u64.div_round(3, Nearest), (3, Less)); /// assert_eq!(20u128.div_round(3, Nearest), (7, Greater)); /// assert_eq!(10usize.div_round(4, Nearest), (2, Less)); /// assert_eq!(14u8.div_round(4, Nearest), (4, Greater)); /// /// assert_eq!((-10i8).div_round(4, Down), (-2, Greater)); /// assert_eq!((-10i16).div_round(4, Up), (-3, Less)); /// assert_eq!((-10i32).div_round(5, Exact), (-2, Equal)); /// assert_eq!((-10i64).div_round(3, Nearest), (-3, Greater)); /// assert_eq!((-20i128).div_round(3, Nearest), (-7, Less)); /// assert_eq!((-10isize).div_round(4, Nearest), (-2, Greater)); /// assert_eq!((-14i8).div_round(4, Nearest), (-4, Less)); /// /// assert_eq!((-10i16).div_round(-4, Down), (2, Less)); /// assert_eq!((-10i32).div_round(-4, Up), (3, Greater)); /// assert_eq!((-10i64).div_round(-5, Exact), (2, Equal)); /// assert_eq!((-10i128).div_round(-3, Nearest), (3, Less)); /// assert_eq!((-20isize).div_round(-3, Nearest), (7, Greater)); /// assert_eq!((-10i8).div_round(-4, Nearest), (2, Less)); /// assert_eq!((-14i16).div_round(-4, Nearest), (4, Greater)); /// ``` /// /// # div_round_assign /// ``` /// use malachite_base::num::arithmetic::traits::DivRoundAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// let mut x = 10u8; /// assert_eq!(x.div_round_assign(4, Down), Less); /// assert_eq!(x, 2); /// /// let mut x = 10u16; /// assert_eq!(x.div_round_assign(4, Up), Greater); /// assert_eq!(x, 3); /// /// let mut x = 10u32; /// assert_eq!(x.div_round_assign(5, Exact), Equal); /// assert_eq!(x, 2); /// /// let mut x = 10u64; /// assert_eq!(x.div_round_assign(3, Nearest), Less); /// assert_eq!(x, 3); /// /// let mut x = 20u128; /// assert_eq!(x.div_round_assign(3, Nearest), Greater); /// assert_eq!(x, 7); /// /// let mut x = 10usize; /// assert_eq!(x.div_round_assign(4, Nearest), Less); /// assert_eq!(x, 2); /// /// let mut x = 14u8; /// assert_eq!(x.div_round_assign(4, Nearest), Greater); /// assert_eq!(x, 4); /// /// let mut x = -10i8; /// assert_eq!(x.div_round_assign(4, Down), Greater); /// assert_eq!(x, -2); /// /// let mut x = -10i16; /// assert_eq!(x.div_round_assign(4, Up), Less); /// assert_eq!(x, -3); /// /// let mut x = -10i32; /// assert_eq!(x.div_round_assign(5, Exact), Equal); /// assert_eq!(x, -2); /// /// let mut x = -10i64; /// assert_eq!(x.div_round_assign(3, Nearest), Greater); /// assert_eq!(x, -3); /// /// let mut x = -20i128; /// assert_eq!(x.div_round_assign(3, Nearest), Less); /// assert_eq!(x, -7); /// /// let mut x = -10isize; /// assert_eq!(x.div_round_assign(4, Nearest), Greater); /// assert_eq!(x, -2); /// /// let mut x = -14i8; /// assert_eq!(x.div_round_assign(4, Nearest), Less); /// assert_eq!(x, -4); /// /// let mut x = -10i16; /// assert_eq!(x.div_round_assign(-4, Down), Less); /// assert_eq!(x, 2); /// /// let mut x = -10i32; /// assert_eq!(x.div_round_assign(-4, Up), Greater); /// assert_eq!(x, 3); /// /// let mut x = -10i64; /// assert_eq!(x.div_round_assign(-5, Exact), Equal); /// assert_eq!(x, 2); /// /// let mut x = -10i128; /// assert_eq!(x.div_round_assign(-3, Nearest), Less); /// assert_eq!(x, 3); /// /// let mut x = -20isize; /// assert_eq!(x.div_round_assign(-3, Nearest), Greater); /// assert_eq!(x, 7); /// /// let mut x = -10i8; /// assert_eq!(x.div_round_assign(-4, Nearest), Less); /// assert_eq!(x, 2); /// /// let mut x = -14i16; /// assert_eq!(x.div_round_assign(-4, Nearest), Greater); /// assert_eq!(x, 4); /// ``` pub mod div_round; /// [`DivisibleBy`](traits::DivisibleBy), a trait for determining whether one number is divisible by /// another. /// /// # divisible_by /// ``` /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// /// assert_eq!(0u8.divisible_by(0), true); /// assert_eq!(100u16.divisible_by(3), false); /// assert_eq!(102u32.divisible_by(3), true); /// /// assert_eq!(0i8.divisible_by(0), true); /// assert_eq!((-100i16).divisible_by(-3), false); /// assert_eq!(102i32.divisible_by(-3), true); /// ``` pub mod divisible_by; /// [`DivisibleByPowerOf2`](traits::DivisibleByPowerOf2), a trait for determining whether a number /// is divisible by $2^k$. /// /// # divisible_by_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; /// /// assert_eq!(0u8.divisible_by_power_of_2(100), true); /// assert_eq!(96u16.divisible_by_power_of_2(5), true); /// assert_eq!(96u32.divisible_by_power_of_2(6), false); /// /// assert_eq!(0i8.divisible_by_power_of_2(100), true); /// assert_eq!((-96i16).divisible_by_power_of_2(5), true); /// assert_eq!(96i32.divisible_by_power_of_2(6), false); /// ``` pub mod divisible_by_power_of_2; /// [`EqMod`](traits::EqMod), a trait for determining whether one number is equal by another modulo /// a third. /// /// # eq_mod /// ``` /// use malachite_base::num::arithmetic::traits::EqMod; /// /// assert_eq!(123u16.eq_mod(223, 100), true); /// assert_eq!((-123i32).eq_mod(277, 100), true); /// assert_eq!((-123i64).eq_mod(278, 100), false); /// ``` pub mod eq_mod; /// [`EqModPowerOf2`](traits::EqModPowerOf2), a trait for determining whether one number is equal to /// another modulo $2^k$. /// /// # eq_mod_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::EqModPowerOf2; /// /// assert_eq!(0u16.eq_mod_power_of_2(256, 8), true); /// assert_eq!((-0b1101i32).eq_mod_power_of_2(0b11011, 3), true); /// assert_eq!((-0b1101i64).eq_mod_power_of_2(0b11011, 4), false); /// ``` pub mod eq_mod_power_of_2; /// [`ExtendedGcd`](traits::ExtendedGcd), a trait for computing the GCD (greatest common divisor) of /// two numbers as well as the coefficients of Bézout's identity $ax+by=\gcd(a,b)$. /// /// # extended_gcd /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// /// assert_eq!(3u8.extended_gcd(5), (1, 2, -1)); /// assert_eq!(240u16.extended_gcd(46), (2, -9, 47)); /// assert_eq!((-111i16).extended_gcd(300), (3, 27, 10)); /// ``` pub mod extended_gcd; /// Traits for computing the factorial, double factorial, multifactorial, and subfactorial. Each /// function has a trait whose implementations panic if the result cannot be represented, and a /// checked trait whose implementations return `None` in that case. The traits are /// [`Factorial`](traits::Factorial), [`DoubleFactorial`](traits::DoubleFactorial), /// [`Multifactorial`](traits::Multifactorial), [`Subfactorial`](traits::Subfactorial), /// [`CheckedFactorial`](traits::CheckedFactorial), /// [`CheckedDoubleFactorial`](traits::CheckedDoubleFactorial), /// [`CheckedMultifactorial`](traits::CheckedMultifactorial), and /// [`CheckedSubfactorial`](traits::CheckedSubfactorial). /// /// # factorial /// ``` /// use malachite_base::num::arithmetic::traits::Factorial; /// /// assert_eq!(u8::factorial(0), 1); /// assert_eq!(u8::factorial(1), 1); /// assert_eq!(u8::factorial(2), 2); /// assert_eq!(u8::factorial(3), 6); /// assert_eq!(u8::factorial(4), 24); /// assert_eq!(u8::factorial(5), 120); /// assert_eq!(u32::factorial(10), 3628800); /// ``` /// /// # checked_factorial /// ``` /// use malachite_base::num::arithmetic::traits::CheckedFactorial; /// /// assert_eq!(u8::checked_factorial(0), Some(1)); /// assert_eq!(u8::checked_factorial(1), Some(1)); /// assert_eq!(u8::checked_factorial(2), Some(2)); /// assert_eq!(u8::checked_factorial(3), Some(6)); /// assert_eq!(u8::checked_factorial(4), Some(24)); /// assert_eq!(u8::checked_factorial(5), Some(120)); /// assert_eq!(u8::checked_factorial(6), None); /// assert_eq!(u32::checked_factorial(10), Some(3628800)); /// assert_eq!(u32::checked_factorial(100), None); /// ``` /// /// # double_factorial /// ``` /// use malachite_base::num::arithmetic::traits::DoubleFactorial; /// /// assert_eq!(u8::double_factorial(0), 1); /// assert_eq!(u8::double_factorial(1), 1); /// assert_eq!(u8::double_factorial(2), 2); /// assert_eq!(u8::double_factorial(3), 3); /// assert_eq!(u8::double_factorial(4), 8); /// assert_eq!(u8::double_factorial(5), 15); /// assert_eq!(u8::double_factorial(6), 48); /// assert_eq!(u8::double_factorial(7), 105); /// assert_eq!(u32::double_factorial(19), 654729075); /// assert_eq!(u32::double_factorial(20), 3715891200); /// ``` /// /// # checked_double_factorial /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDoubleFactorial; /// /// assert_eq!(u8::checked_double_factorial(0), Some(1)); /// assert_eq!(u8::checked_double_factorial(1), Some(1)); /// assert_eq!(u8::checked_double_factorial(2), Some(2)); /// assert_eq!(u8::checked_double_factorial(3), Some(3)); /// assert_eq!(u8::checked_double_factorial(4), Some(8)); /// assert_eq!(u8::checked_double_factorial(5), Some(15)); /// assert_eq!(u8::checked_double_factorial(6), Some(48)); /// assert_eq!(u8::checked_double_factorial(7), Some(105)); /// assert_eq!(u8::checked_double_factorial(8), None); /// assert_eq!(u32::checked_double_factorial(19), Some(654729075)); /// assert_eq!(u32::checked_double_factorial(20), Some(3715891200)); /// assert_eq!(u32::checked_double_factorial(100), None); /// ``` /// /// # multifactorial /// ``` /// use malachite_base::num::arithmetic::traits::Multifactorial; /// /// assert_eq!(u8::multifactorial(0, 1), 1); /// assert_eq!(u8::multifactorial(1, 1), 1); /// assert_eq!(u8::multifactorial(2, 1), 2); /// assert_eq!(u8::multifactorial(3, 1), 6); /// assert_eq!(u8::multifactorial(4, 1), 24); /// assert_eq!(u8::multifactorial(5, 1), 120); /// /// assert_eq!(u8::multifactorial(0, 2), 1); /// assert_eq!(u8::multifactorial(1, 2), 1); /// assert_eq!(u8::multifactorial(2, 2), 2); /// assert_eq!(u8::multifactorial(3, 2), 3); /// assert_eq!(u8::multifactorial(4, 2), 8); /// assert_eq!(u8::multifactorial(5, 2), 15); /// assert_eq!(u8::multifactorial(6, 2), 48); /// assert_eq!(u8::multifactorial(7, 2), 105); /// /// assert_eq!(u8::multifactorial(0, 3), 1); /// assert_eq!(u8::multifactorial(1, 3), 1); /// assert_eq!(u8::multifactorial(2, 3), 2); /// assert_eq!(u8::multifactorial(3, 3), 3); /// assert_eq!(u8::multifactorial(4, 3), 4); /// assert_eq!(u8::multifactorial(5, 3), 10); /// assert_eq!(u8::multifactorial(6, 3), 18); /// assert_eq!(u8::multifactorial(7, 3), 28); /// assert_eq!(u8::multifactorial(8, 3), 80); /// assert_eq!(u8::multifactorial(9, 3), 162); /// /// assert_eq!(u32::multifactorial(10, 1), 3628800); /// assert_eq!(u32::multifactorial(20, 2), 3715891200); /// assert_eq!(u32::multifactorial(25, 3), 608608000); /// ``` /// /// # checked_multifactorial /// ``` /// use malachite_base::num::arithmetic::traits::CheckedMultifactorial; /// /// assert_eq!(u8::checked_multifactorial(0, 1), Some(1)); /// assert_eq!(u8::checked_multifactorial(1, 1), Some(1)); /// assert_eq!(u8::checked_multifactorial(2, 1), Some(2)); /// assert_eq!(u8::checked_multifactorial(3, 1), Some(6)); /// assert_eq!(u8::checked_multifactorial(4, 1), Some(24)); /// assert_eq!(u8::checked_multifactorial(5, 1), Some(120)); /// assert_eq!(u8::checked_multifactorial(6, 1), None); /// /// assert_eq!(u8::checked_multifactorial(0, 2), Some(1)); /// assert_eq!(u8::checked_multifactorial(1, 2), Some(1)); /// assert_eq!(u8::checked_multifactorial(2, 2), Some(2)); /// assert_eq!(u8::checked_multifactorial(3, 2), Some(3)); /// assert_eq!(u8::checked_multifactorial(4, 2), Some(8)); /// assert_eq!(u8::checked_multifactorial(5, 2), Some(15)); /// assert_eq!(u8::checked_multifactorial(6, 2), Some(48)); /// assert_eq!(u8::checked_multifactorial(7, 2), Some(105)); /// assert_eq!(u8::checked_multifactorial(8, 2), None); /// /// assert_eq!(u8::checked_multifactorial(0, 3), Some(1)); /// assert_eq!(u8::checked_multifactorial(1, 3), Some(1)); /// assert_eq!(u8::checked_multifactorial(2, 3), Some(2)); /// assert_eq!(u8::checked_multifactorial(3, 3), Some(3)); /// assert_eq!(u8::checked_multifactorial(4, 3), Some(4)); /// assert_eq!(u8::checked_multifactorial(5, 3), Some(10)); /// assert_eq!(u8::checked_multifactorial(6, 3), Some(18)); /// assert_eq!(u8::checked_multifactorial(7, 3), Some(28)); /// assert_eq!(u8::checked_multifactorial(8, 3), Some(80)); /// assert_eq!(u8::checked_multifactorial(9, 3), Some(162)); /// assert_eq!(u8::checked_multifactorial(10, 3), None); /// /// assert_eq!(u32::checked_multifactorial(10, 1), Some(3628800)); /// assert_eq!(u32::checked_multifactorial(20, 2), Some(3715891200)); /// assert_eq!(u32::checked_multifactorial(25, 3), Some(608608000)); /// assert_eq!(u32::checked_multifactorial(100, 1), None); /// assert_eq!(u32::checked_multifactorial(100, 2), None); /// assert_eq!(u32::checked_multifactorial(100, 3), None); /// ``` /// /// # subfactorial /// ``` /// use malachite_base::num::arithmetic::traits::Subfactorial; /// /// assert_eq!(u8::subfactorial(0), 1); /// assert_eq!(u8::subfactorial(1), 0); /// assert_eq!(u8::subfactorial(2), 1); /// assert_eq!(u8::subfactorial(3), 2); /// assert_eq!(u8::subfactorial(4), 9); /// assert_eq!(u8::subfactorial(5), 44); /// assert_eq!(u32::subfactorial(10), 1334961); /// ``` /// /// # checked_subfactorial /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSubfactorial; /// /// assert_eq!(u8::checked_subfactorial(0), Some(1)); /// assert_eq!(u8::checked_subfactorial(1), Some(0)); /// assert_eq!(u8::checked_subfactorial(2), Some(1)); /// assert_eq!(u8::checked_subfactorial(3), Some(2)); /// assert_eq!(u8::checked_subfactorial(4), Some(9)); /// assert_eq!(u8::checked_subfactorial(5), Some(44)); /// assert_eq!(u8::checked_subfactorial(6), None); /// assert_eq!(u32::checked_subfactorial(10), Some(1334961)); /// assert_eq!(u32::checked_subfactorial(100), None); /// ``` pub mod factorial; /// [`Floor`](traits::Floor) and [`FloorAssign`](traits::FloorAssign), traits for computing the /// floor of a number. /// /// # floor_assign /// ``` /// use malachite_base::num::arithmetic::traits::FloorAssign; /// /// let mut x = 1.5f32; /// x.floor_assign(); /// assert_eq!(x, 1.0); /// /// let mut x = -1.5f32; /// x.floor_assign(); /// assert_eq!(x, -2.0); /// ``` pub mod floor; /// [`Gcd`](traits::Gcd) and [`GcdAssign`](traits::GcdAssign), traits for computing the GCD /// (greatest common divisor) of two numbers. /// /// # gcd /// ``` /// use malachite_base::num::arithmetic::traits::Gcd; /// /// assert_eq!(3u8.gcd(5), 1); /// assert_eq!(12u16.gcd(90), 6); /// ``` /// /// # gcd_assign /// ``` /// use malachite_base::num::arithmetic::traits::GcdAssign; /// /// let mut x = 3u8; /// x.gcd_assign(5); /// assert_eq!(x, 1); /// /// let mut x = 12u16; /// x.gcd_assign(90); /// assert_eq!(x, 6); /// ``` pub mod gcd; /// [`IsPowerOf2`](traits::IsPowerOf2), a trait for determining whether a number is an integer power /// of 2. /// /// # is_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::IsPowerOf2; /// /// assert_eq!(4.0.is_power_of_2(), true); /// assert_eq!(0.25.is_power_of_2(), true); /// assert_eq!(0.2.is_power_of_2(), false); /// assert_eq!((-4.0).is_power_of_2(), false); /// ``` pub mod is_power_of_2; /// [`LegendreSymbol`](traits::LegendreSymbol), [`JacobiSymbol`](traits::JacobiSymbol), and /// [`KroneckerSymbol`](traits::KroneckerSymbol), traits for computing the Legendre, Jacobi, and /// Kronecker symbols of two numbers. /// /// # legendre_symbol /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// /// assert_eq!(10u8.legendre_symbol(5), 0); /// assert_eq!(7u8.legendre_symbol(5), -1); /// assert_eq!(11u8.legendre_symbol(5), 1); /// /// assert_eq!((-7i8).legendre_symbol(5), -1); /// assert_eq!((-11i8).legendre_symbol(5), 1); /// ``` /// /// # jacobi_symbol /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// /// assert_eq!(10u8.jacobi_symbol(5), 0); /// assert_eq!(7u8.jacobi_symbol(5), -1); /// assert_eq!(11u8.jacobi_symbol(5), 1); /// assert_eq!(11u8.jacobi_symbol(9), 1); /// /// assert_eq!((-7i8).jacobi_symbol(5), -1); /// assert_eq!((-11i8).jacobi_symbol(5), 1); /// assert_eq!((-11i8).jacobi_symbol(9), 1); /// ``` /// /// # kronecker_symbol /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// /// assert_eq!(10u8.kronecker_symbol(5), 0); /// assert_eq!(7u8.kronecker_symbol(5), -1); /// assert_eq!(11u8.kronecker_symbol(5), 1); /// assert_eq!(11u8.kronecker_symbol(9), 1); /// assert_eq!(11u8.kronecker_symbol(8), -1); /// /// assert_eq!((-7i8).kronecker_symbol(5), -1); /// assert_eq!((-11i8).kronecker_symbol(5), 1); /// assert_eq!((-11i8).kronecker_symbol(9), 1); /// assert_eq!((-11i8).kronecker_symbol(8), -1); /// assert_eq!((-11i8).kronecker_symbol(-8), 1); /// ``` pub mod kronecker_symbol; /// [`Lcm`](traits::Lcm), [`LcmAssign`](traits::LcmAssign), and [`CheckedLcm`](traits::CheckedLcm), /// traits for computing the LCM (least common multiple) of two numbers. /// /// # lcm /// ``` /// use malachite_base::num::arithmetic::traits::Lcm; /// /// assert_eq!(3u8.lcm(5), 15); /// assert_eq!(12u16.lcm(90), 180); /// ``` /// /// # lcm_assign /// ``` /// use malachite_base::num::arithmetic::traits::LcmAssign; /// /// let mut x = 3u8; /// x.lcm_assign(5); /// assert_eq!(x, 15); /// /// let mut x = 12u16; /// x.lcm_assign(90); /// assert_eq!(x, 180); /// ``` /// /// # checked_lcm /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLcm; /// /// assert_eq!(3u8.checked_lcm(5), Some(15)); /// assert_eq!(12u16.checked_lcm(90), Some(180)); /// assert_eq!(120u8.checked_lcm(90), None); /// ``` pub mod lcm; /// Traits for taking the base-$b$ logarithm of a number. /// /// The traits are [`FloorLogBase`](traits::FloorLogBase), /// [`CeilingLogBase`](traits::CeilingLogBase), and [`CheckedLogBase`](traits::CheckedLogBase). /// /// # floor_log_base /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase; /// /// assert_eq!(1u8.floor_log_base(5), 0); /// assert_eq!(125u8.floor_log_base(5), 3); /// assert_eq!(99u64.floor_log_base(10), 1); /// assert_eq!(100u64.floor_log_base(10), 2); /// assert_eq!(101u64.floor_log_base(10), 2); /// ``` /// /// # ceiling_log_base /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase; /// /// assert_eq!(1u8.ceiling_log_base(5), 0); /// assert_eq!(125u8.ceiling_log_base(5), 3); /// assert_eq!(99u64.ceiling_log_base(10), 2); /// assert_eq!(100u64.ceiling_log_base(10), 2); /// assert_eq!(101u64.ceiling_log_base(10), 3); /// ``` /// /// # checked_log_base /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBase; /// /// assert_eq!(1u8.checked_log_base(5), Some(0)); /// assert_eq!(125u8.checked_log_base(5), Some(3)); /// assert_eq!(99u64.checked_log_base(10), None); /// assert_eq!(100u64.checked_log_base(10), Some(2)); /// assert_eq!(101u64.checked_log_base(10), None); /// ``` pub mod log_base; /// Traits for taking the base-2 logarithm of a number. /// /// The traits are [`FloorLogBase2`](traits::FloorLogBase2), /// [`CeilingLogBase2`](traits::CeilingLogBase2), and [`CheckedLogBase2`](traits::CheckedLogBase2). /// /// # floor_log_base_2 /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase2; /// /// assert_eq!(1u8.floor_log_base_2(), 0); /// assert_eq!(100u64.floor_log_base_2(), 6); /// /// assert_eq!(1.0f32.floor_log_base_2(), 0); /// assert_eq!(100.0f32.floor_log_base_2(), 6); /// assert_eq!(0.1f32.floor_log_base_2(), -4); /// ``` /// /// # ceiling_log_base_2 /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase2; /// /// assert_eq!(1u8.ceiling_log_base_2(), 0); /// assert_eq!(100u64.ceiling_log_base_2(), 7); /// /// assert_eq!(1.0f32.ceiling_log_base_2(), 0); /// assert_eq!(100.0f32.ceiling_log_base_2(), 7); /// assert_eq!(0.1f32.ceiling_log_base_2(), -3); /// ``` /// /// # checked_log_base_2 /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBase2; /// /// assert_eq!(1u8.checked_log_base_2(), Some(0)); /// assert_eq!(100u64.checked_log_base_2(), None); /// assert_eq!(128u64.checked_log_base_2(), Some(7)); /// /// assert_eq!(1.0f32.checked_log_base_2(), Some(0)); /// assert_eq!(100.0f32.checked_log_base_2(), None); /// assert_eq!(128.0f32.checked_log_base_2(), Some(7)); /// assert_eq!(0.1f32.checked_log_base_2(), None); /// assert_eq!(0.0625f32.checked_log_base_2(), Some(-4)); /// ``` pub mod log_base_2; /// Traits for taking the base-$2^k$ logarithm of a number. /// /// The traits are [`FloorLogBasePowerOf2`](traits::FloorLogBasePowerOf2), /// [`CeilingLogBasePowerOf2`](traits::CeilingLogBasePowerOf2), and /// [`CheckedLogBasePowerOf2`](traits::CheckedLogBasePowerOf2). /// /// # floor_log_base_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBasePowerOf2; /// /// assert_eq!(1u8.floor_log_base_power_of_2(4), 0); /// assert_eq!(100u64.floor_log_base_power_of_2(2), 3); /// /// assert_eq!(0.1f32.floor_log_base_power_of_2(2), -2); /// ``` /// /// # ceiling_log_base_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBasePowerOf2; /// /// assert_eq!(1u8.ceiling_log_base_power_of_2(4), 0); /// assert_eq!(100u64.ceiling_log_base_power_of_2(2), 4); /// /// assert_eq!(0.1f32.ceiling_log_base_power_of_2(2), -1); /// ``` /// /// # checked_log_base_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBasePowerOf2; /// /// assert_eq!(1u8.checked_log_base_power_of_2(4), Some(0)); /// assert_eq!(100u64.checked_log_base_power_of_2(4), None); /// assert_eq!(256u64.checked_log_base_power_of_2(4), Some(2)); /// /// assert_eq!(0.1f32.checked_log_base_power_of_2(2), None); /// assert_eq!(0.0625f32.checked_log_base_power_of_2(2), Some(-2)); /// ``` pub mod log_base_power_of_2; /// [`ModAdd`](traits::ModAdd) and [`ModAddAssign`](traits::ModAddAssign), traits for adding two /// numbers modulo another number. /// /// # mod_add /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// /// assert_eq!(0u8.mod_add(3, 5), 3); /// assert_eq!(7u32.mod_add(5, 10), 2); /// ``` /// /// # mod_add_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModAddAssign; /// /// let mut n = 0u8; /// n.mod_add_assign(3, 5); /// assert_eq!(n, 3); /// /// let mut n = 7u32; /// n.mod_add_assign(5, 10); /// assert_eq!(n, 2); /// ``` pub mod mod_add; /// [`ModInverse`](traits::ModInverse), a trait for finding the multiplicative inverse of a number /// modulo another number. /// /// # mod_inverse /// ``` /// use malachite_base::num::arithmetic::traits::ModInverse; /// /// assert_eq!(7u8.mod_inverse(10), Some(3)); /// assert_eq!(8u8.mod_inverse(10), None); /// assert_eq!(123u32.mod_inverse(4567), Some(854)); /// ``` pub mod mod_inverse; /// [`ModIsReduced`](traits::ModIsReduced), a trait for checking whether a number is reduced modulo /// another number. /// /// # mod_is_reduced /// ``` /// use malachite_base::num::arithmetic::traits::ModIsReduced; /// /// assert_eq!(0u8.mod_is_reduced(&5), true); /// assert_eq!(100u64.mod_is_reduced(&100), false); /// assert_eq!(100u16.mod_is_reduced(&101), true); /// ``` pub mod mod_is_reduced; /// Traits for multiplying two numbers modulo another number. /// /// The traits are [`ModMul`](traits::ModMul), [`ModMulAssign`](traits::ModMulAssign), /// [`ModMulPrecomputed`](traits::ModMulPrecomputed), and /// [`ModMulPrecomputedAssign`](traits::ModMulPrecomputedAssign). /// [`ModMulPrecomputed`](traits::ModMulPrecomputed) and /// [`ModMulPrecomputedAssign`](traits::ModMulPrecomputedAssign) are useful when having to make /// several multiplications modulo the same modulus. /// /// # mod_mul /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// /// assert_eq!(2u8.mod_mul(3, 7), 6); /// assert_eq!(7u32.mod_mul(3, 10), 1); /// ``` /// /// # mod_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModMulAssign; /// /// let mut n = 2u8; /// n.mod_mul_assign(3, 7); /// assert_eq!(n, 6); /// /// let mut n = 7u32; /// n.mod_mul_assign(3, 10); /// assert_eq!(n, 1); /// ``` /// /// # mod_mul_precomputed /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// /// let data = u32::precompute_mod_mul_data(&7); /// assert_eq!(2u32.mod_mul_precomputed(3, 7, &data), 6); /// assert_eq!(5u32.mod_mul_precomputed(3, 7, &data), 1); /// assert_eq!(4u32.mod_mul_precomputed(4, 7, &data), 2); /// /// let data = u64::precompute_mod_mul_data(&10); /// assert_eq!(7u64.mod_mul_precomputed(3, 10, &data), 1); /// assert_eq!(4u64.mod_mul_precomputed(9, 10, &data), 6); /// assert_eq!(5u64.mod_mul_precomputed(8, 10, &data), 0); /// /// let data = u8::precompute_mod_mul_data(&7); /// assert_eq!(2u8.mod_mul_precomputed(3, 7, &data), 6); /// assert_eq!(5u8.mod_mul_precomputed(3, 7, &data), 1); /// assert_eq!(4u8.mod_mul_precomputed(4, 7, &data), 2); /// /// let data = u16::precompute_mod_mul_data(&10); /// assert_eq!(7u16.mod_mul_precomputed(3, 10, &data), 1); /// assert_eq!(4u16.mod_mul_precomputed(9, 10, &data), 6); /// assert_eq!(5u16.mod_mul_precomputed(8, 10, &data), 0); /// /// let data = u128::precompute_mod_mul_data(&7); /// assert_eq!(2u128.mod_mul_precomputed(3, 7, &data), 6); /// assert_eq!(5u128.mod_mul_precomputed(3, 7, &data), 1); /// assert_eq!(4u128.mod_mul_precomputed(4, 7, &data), 2); /// /// let data = u128::precompute_mod_mul_data(&10); /// assert_eq!(7u128.mod_mul_precomputed(3, 10, &data), 1); /// assert_eq!(4u128.mod_mul_precomputed(9, 10, &data), 6); /// assert_eq!(5u128.mod_mul_precomputed(8, 10, &data), 0); /// ``` /// /// # mod_mul_precomputed_assign /// ``` /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign}; /// /// let data = u8::precompute_mod_mul_data(&7); /// /// let mut x = 2u8; /// x.mod_mul_precomputed_assign(3, 7, &data); /// assert_eq!(x, 6); /// /// let mut x = 5u8; /// x.mod_mul_precomputed_assign(3, 7, &data); /// assert_eq!(x, 1); /// /// let mut x = 4u8; /// x.mod_mul_precomputed_assign(4, 7, &data); /// assert_eq!(x, 2); /// /// let data = u32::precompute_mod_mul_data(&10); /// /// let mut x = 7u32; /// x.mod_mul_precomputed_assign(3, 10, &data); /// assert_eq!(x, 1); /// /// let mut x = 4u32; /// x.mod_mul_precomputed_assign(9, 10, &data); /// assert_eq!(x, 6); /// /// let mut x = 5u32; /// x.mod_mul_precomputed_assign(8, 10, &data); /// assert_eq!(x, 0); /// ``` pub mod mod_mul; /// [`ModNeg`](traits::ModNeg) and [`ModNegAssign`](traits::ModNegAssign), traits for negating a /// number modulo another number. /// /// # mod_neg /// ``` /// use malachite_base::num::arithmetic::traits::ModNeg; /// /// assert_eq!(0u8.mod_neg(5), 0); /// assert_eq!(7u32.mod_neg(10), 3); /// assert_eq!(100u16.mod_neg(101), 1); /// ``` /// /// # mod_neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModNegAssign; /// /// let mut n = 0u8; /// n.mod_neg_assign(5); /// assert_eq!(n, 0); /// /// let mut n = 7u32; /// n.mod_neg_assign(10); /// assert_eq!(n, 3); /// /// let mut n = 100u16; /// n.mod_neg_assign(101); /// assert_eq!(n, 1); /// ``` pub mod mod_neg; /// Traits for finding the remainder of two numbers, subject to various rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |-------------------|----------------------------|----------------------------------------| /// | towards $-\infty$ | [`Mod`](traits::Mod) | [`ModAssign`](traits::ModAssign) | /// | towards $\infty$ | [`CeilingMod`](traits::CeilingMod) | [`CeilingModAssign`](traits::CeilingModAssign) | /// | towards $\infty$ | [`NegMod`](traits::NegMod) | [`NegModAssign`](traits::NegModAssign) | /// /// [`CeilingMod`](traits::CeilingMod) and [`NegMod`](traits::NegMod) are similar. The difference is /// that [`CeilingMod`](traits::CeilingMod) returns a remainder less than or equal to 0, so that the /// usual relation $x = qy + r$ is satisfied, while [`NegMod`](traits::NegMod) returns a remainder /// greater than or equal to zero. This allows the remainder to have an unsigned type, but modifies /// the relation to $x = qy - r$. /// /// The [`Rem`](std::ops::Rem) trait in the standard library rounds towards 0. /// /// # mod_op /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23u8.mod_op(10), 3); /// /// // 9 * 5 + 0 = 45 /// assert_eq!(45u32.mod_op(5), 0); /// /// // 2 * 10 + 3 = 23 /// assert_eq!(23i8.mod_op(10), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(23i16.mod_op(-10), -7); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((-23i32).mod_op(10), 7); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((-23i64).mod_op(-10), -3); /// ``` /// /// # mod_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModAssign; /// /// // 2 * 10 + 3 = 23 /// let mut x = 23u8; /// x.mod_assign(10); /// assert_eq!(x, 3); /// /// // 9 * 5 + 0 = 45 /// let mut x = 45u32; /// x.mod_assign(5); /// assert_eq!(x, 0); /// /// // 2 * 10 + 3 = 23 /// let mut x = 23i8; /// x.mod_assign(10); /// assert_eq!(x, 3); /// /// // -3 * -10 + -7 = 23 /// let mut x = 23i16; /// x.mod_assign(-10); /// assert_eq!(x, -7); /// /// // -3 * 10 + 7 = -23 /// let mut x = -23i32; /// x.mod_assign(10); /// assert_eq!(x, 7); /// /// // 2 * -10 + -3 = -23 /// let mut x = -23i64; /// x.mod_assign(-10); /// assert_eq!(x, -3); /// ``` /// /// # neg_mod /// ``` /// use malachite_base::num::arithmetic::traits::NegMod; /// /// // 3 * 10 - 7 = 23 /// assert_eq!(23u8.neg_mod(10), 7); /// /// // 9 * 5 + 0 = 45 /// assert_eq!(45u32.neg_mod(5), 0); /// ``` /// /// # neg_mod_assign /// ``` /// use malachite_base::num::arithmetic::traits::NegModAssign; /// /// // 3 * 10 - 7 = 23 /// let mut x = 23u8; /// x.neg_mod_assign(10); /// assert_eq!(x, 7); /// /// // 9 * 5 + 0 = 45 /// let mut x = 45u32; /// x.neg_mod_assign(5); /// assert_eq!(x, 0); /// ``` /// /// # ceiling_mod /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// /// // 3 * 10 + -7 = 23 /// assert_eq!(23i8.ceiling_mod(10), -7); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(23i16.ceiling_mod(-10), 3); /// /// // -2 * 10 + -3 = -23 /// assert_eq!((-23i32).ceiling_mod(10), -3); /// /// // 3 * -10 + 7 = -23 /// assert_eq!((-23i64).ceiling_mod(-10), 7); /// ``` /// /// # ceiling_mod_assign /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModAssign; /// /// // 3 * 10 + -7 = 23 /// let mut x = 23i8; /// x.ceiling_mod_assign(10); /// assert_eq!(x, -7); /// /// // -2 * -10 + 3 = 23 /// let mut x = 23i16; /// x.ceiling_mod_assign(-10); /// assert_eq!(x, 3); /// /// // -2 * 10 + -3 = -23 /// let mut x = -23i32; /// x.ceiling_mod_assign(10); /// assert_eq!(x, -3); /// /// // 3 * -10 + 7 = -23 /// let mut x = -23i64; /// x.ceiling_mod_assign(-10); /// assert_eq!(x, 7); /// ``` pub mod mod_op; /// Traits for raising a number to a power modulo another number. /// /// The traits are [`ModPow`](traits::ModPow), [`ModPowAssign`](traits::ModPowAssign), and /// [`ModPowPrecomputed`](traits::ModPowPrecomputed). /// [`ModPowPrecomputed`](traits::ModPowPrecomputed) is useful when having to make several /// exponentiations modulo the same modulus. /// /// # mod_pow /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// /// assert_eq!(4u16.mod_pow(13, 497), 445); /// assert_eq!(10u32.mod_pow(1000, 30), 10); /// ``` /// /// # mod_pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowAssign; /// /// let mut n = 4u16; /// n.mod_pow_assign(13, 497); /// assert_eq!(n, 445); /// /// let mut n = 10u32; /// n.mod_pow_assign(1000, 30); /// assert_eq!(n, 10); /// ``` /// /// # mod_pow_precomputed /// ``` /// use malachite_base::num::arithmetic::traits::ModPowPrecomputed; /// /// let data = u32::precompute_mod_pow_data(&497); /// assert_eq!(4u32.mod_pow_precomputed(13, 497, &data), 445); /// assert_eq!(5u32.mod_pow_precomputed(3, 497, &data), 125); /// assert_eq!(4u32.mod_pow_precomputed(100, 497, &data), 116); /// /// let data = u64::precompute_mod_pow_data(&30); /// assert_eq!(10u64.mod_pow_precomputed(1000, 30, &data), 10); /// assert_eq!(4u64.mod_pow_precomputed(9, 30, &data), 4); /// assert_eq!(5u64.mod_pow_precomputed(8, 30, &data), 25); /// /// let data = u16::precompute_mod_pow_data(&497); /// assert_eq!(4u16.mod_pow_precomputed(13, 497, &data), 445); /// assert_eq!(5u16.mod_pow_precomputed(3, 497, &data), 125); /// assert_eq!(4u16.mod_pow_precomputed(100, 497, &data), 116); /// /// let data = u8::precompute_mod_pow_data(&30); /// assert_eq!(10u8.mod_pow_precomputed(1000, 30, &data), 10); /// assert_eq!(4u8.mod_pow_precomputed(9, 30, &data), 4); /// assert_eq!(5u8.mod_pow_precomputed(8, 30, &data), 25); /// /// let data = u128::precompute_mod_pow_data(&497); /// assert_eq!(4u128.mod_pow_precomputed(13, 497, &data), 445); /// assert_eq!(5u128.mod_pow_precomputed(3, 497, &data), 125); /// assert_eq!(4u128.mod_pow_precomputed(100, 497, &data), 116); /// /// let data = u128::precompute_mod_pow_data(&30); /// assert_eq!(10u128.mod_pow_precomputed(1000, 30, &data), 10); /// assert_eq!(4u128.mod_pow_precomputed(9, 30, &data), 4); /// assert_eq!(5u128.mod_pow_precomputed(8, 30, &data), 25); /// ``` /// /// # mod_pow_precomputed_assign /// ``` /// use malachite_base::num::arithmetic::traits::{ModPowPrecomputed, ModPowPrecomputedAssign}; /// /// let data = u32::precompute_mod_pow_data(&497); /// /// let mut x = 4u32; /// x.mod_pow_precomputed_assign(13, 497, &data); /// assert_eq!(x, 445); /// /// let mut x = 5u32; /// x.mod_pow_precomputed_assign(3, 497, &data); /// assert_eq!(x, 125); /// /// let mut x = 4u32; /// x.mod_pow_precomputed_assign(100, 497, &data); /// assert_eq!(x, 116); /// /// let data = u64::precompute_mod_pow_data(&30); /// /// let mut x = 10u64; /// x.mod_pow_precomputed_assign(1000, 30, &data); /// assert_eq!(x, 10); /// /// let mut x = 4u64; /// x.mod_pow_precomputed_assign(9, 30, &data); /// assert_eq!(x, 4); /// /// let mut x = 5u64; /// x.mod_pow_precomputed_assign(8, 30, &data); /// assert_eq!(x, 25); /// ``` pub mod mod_pow; /// Traits for finding the remainder of a number divided by $2^k$, subject to various rounding /// rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |----------|-----------------------|-----------------------------------| /// | towards $-\infty$ | [`ModPowerOf2`](traits::ModPowerOf2) | [`ModPowerOf2Assign`](traits::ModPowerOf2Assign) | /// | towards 0 | [`RemPowerOf2`](traits::RemPowerOf2) | [`RemPowerOf2Assign`](traits::RemPowerOf2Assign) | /// | towards $\infty$ | [`CeilingModPowerOf2`](traits::CeilingModPowerOf2) | [`CeilingModPowerOf2Assign`](traits::CeilingModPowerOf2Assign) | /// | towards $\infty$ | [`NegModPowerOf2`](traits::NegModPowerOf2) | [`NegModPowerOf2Assign`](traits::NegModPowerOf2Assign) | /// /// [`CeilingModPowerOf2`](traits::CeilingModPowerOf2) and /// [`NegModPowerOf2`](traits::NegModPowerOf2) are similar. The difference is that /// [`CeilingModPowerOf2`](traits::CeilingModPowerOf2) returns a remainder less than or equal to 0, /// so that the usual relation $x = q2^k + r$ is satisfied, while /// [`NegModPowerOf2`](traits::NegModPowerOf2) returns a remainder greater than or equal to zero. /// This allows the remainder to have an unsigned type, but modifies the relation to $x = q2^k - r$. /// /// # mod_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(260u16.mod_power_of_2(8), 4); /// /// // 100 * 2^4 + 11 = 1611 /// assert_eq!(1611u32.mod_power_of_2(4), 11); /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(260i16.mod_power_of_2(8), 4); /// /// // -101 * 2^4 + 5 = -1611 /// assert_eq!((-1611i32).mod_power_of_2(4), 5); /// ``` /// /// # mod_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Assign; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = 260u16; /// x.mod_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // 100 * 2^4 + 11 = 1611 /// let mut x = 1611u32; /// x.mod_power_of_2_assign(4); /// assert_eq!(x, 11); /// /// // 1 * 2^8 + 4 = 260 /// let mut x = 260i16; /// x.mod_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // -101 * 2^4 + 5 = -1611 /// let mut x = -1611i32; /// x.mod_power_of_2_assign(4); /// assert_eq!(x, 5); /// ``` /// /// # rem_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(260u16.rem_power_of_2(8), 4); /// /// // 100 * 2^4 + 11 = 1611 /// assert_eq!(1611u32.rem_power_of_2(4), 11); /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(260i16.rem_power_of_2(8), 4); /// /// // -100 * 2^4 + -11 = -1611 /// assert_eq!((-1611i32).rem_power_of_2(4), -11); /// ``` /// /// # rem_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2Assign; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = 260u16; /// x.rem_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // 100 * 2^4 + 11 = 1611 /// let mut x = 1611u32; /// x.rem_power_of_2_assign(4); /// assert_eq!(x, 11); /// /// // 1 * 2^8 + 4 = 260 /// let mut x = 260i16; /// x.rem_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // -100 * 2^4 + -11 = -1611 /// let mut x = -1611i32; /// x.rem_power_of_2_assign(4); /// assert_eq!(x, -11); /// ``` /// /// # neg_mod_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::NegModPowerOf2; /// /// // 2 * 2^8 - 252 = 260 /// assert_eq!(260u16.neg_mod_power_of_2(8), 252); /// /// // 101 * 2^4 - 5 = 1611 /// assert_eq!(1611u32.neg_mod_power_of_2(4), 5); /// ``` /// /// # neg_mod_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::NegModPowerOf2Assign; /// /// // 2 * 2^8 - 252 = 260 /// let mut x = 260u16; /// x.neg_mod_power_of_2_assign(8); /// assert_eq!(x, 252); /// /// // 101 * 2^4 - 5 = 1611 /// let mut x = 1611u32; /// x.neg_mod_power_of_2_assign(4); /// assert_eq!(x, 5); /// ``` /// /// # ceiling_mod_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModPowerOf2; /// /// // 2 * 2^8 + -252 = 260 /// assert_eq!(260i16.ceiling_mod_power_of_2(8), -252); /// /// // -100 * 2^4 + -11 = -1611 /// assert_eq!((-1611i32).ceiling_mod_power_of_2(4), -11); /// ``` /// /// # ceiling_mod_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModPowerOf2Assign; /// /// // 2 * 2^8 + -252 = 260 /// let mut x = 260i16; /// x.ceiling_mod_power_of_2_assign(8); /// assert_eq!(x, -252); /// /// // -100 * 2^4 + -11 = -1611 /// let mut x = -1611i32; /// x.ceiling_mod_power_of_2_assign(4); /// assert_eq!(x, -11); /// ``` pub mod mod_power_of_2; /// [`ModPowerOf2Add`](traits::ModPowerOf2Add) and /// [`ModPowerOf2AddAssign`](traits::ModPowerOf2AddAssign), traits for adding two numbers modulo /// $2^k$. /// /// # mod_power_of_2_add /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add; /// /// assert_eq!(0u8.mod_power_of_2_add(2, 5), 2); /// assert_eq!(10u32.mod_power_of_2_add(14, 4), 8); /// ``` /// /// # mod_power_of_2_add_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign; /// /// let mut n = 0u8; /// n.mod_power_of_2_add_assign(2, 5); /// assert_eq!(n, 2); /// /// let mut n = 10u32; /// n.mod_power_of_2_add_assign(14, 4); /// assert_eq!(n, 8); /// ``` pub mod mod_power_of_2_add; /// [`ModPowerOf2Inverse`](traits::ModPowerOf2Inverse), a trait for finding the multiplicative /// inverse of a number modulo $2^k$. /// /// # mod_inverse /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Inverse; /// /// assert_eq!(7u8.mod_power_of_2_inverse(4), Some(7)); /// assert_eq!(8u8.mod_power_of_2_inverse(4), None); /// assert_eq!(123u32.mod_power_of_2_inverse(7), Some(51)); /// ``` pub mod mod_power_of_2_inverse; /// [`ModPowerOf2IsReduced`](traits::ModPowerOf2IsReduced), a trait for checking whether a number is /// reduced modulo $2^k$. /// /// # mod_power_of_2_is_reduced /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2IsReduced; /// /// assert_eq!(0u8.mod_power_of_2_is_reduced(5), true); /// assert_eq!(100u64.mod_power_of_2_is_reduced(5), false); /// assert_eq!(100u16.mod_power_of_2_is_reduced(8), true); /// ``` pub mod mod_power_of_2_is_reduced; /// [`ModPowerOf2Mul`](traits::ModPowerOf2Mul) and /// [`ModPowerOf2MulAssign`](traits::ModPowerOf2MulAssign), traits for multiplying two numbers /// modulo $2^k$. /// /// # mod_power_of_2_mul /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Mul; /// /// assert_eq!(3u8.mod_power_of_2_mul(2, 5), 6); /// assert_eq!(10u32.mod_power_of_2_mul(14, 4), 12); /// ``` /// /// # mod_power_of_2_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2MulAssign; /// /// let mut n = 3u8; /// n.mod_power_of_2_mul_assign(2, 5); /// assert_eq!(n, 6); /// /// let mut n = 10u32; /// n.mod_power_of_2_mul_assign(14, 4); /// assert_eq!(n, 12); /// ``` pub mod mod_power_of_2_mul; /// [`ModPowerOf2Neg`](traits::ModPowerOf2Neg) and /// [`ModPowerOf2NegAssign`](traits::ModPowerOf2NegAssign), traits for negating a number modulo /// $2^k$. /// /// # mod_power_of_2_neg /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Neg; /// /// assert_eq!(0u8.mod_power_of_2_neg(5), 0); /// assert_eq!(10u32.mod_power_of_2_neg(4), 6); /// assert_eq!(100u16.mod_power_of_2_neg(8), 156); /// ``` /// /// # mod_power_of_2_neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2NegAssign; /// /// let mut n = 0u8; /// n.mod_power_of_2_neg_assign(5); /// assert_eq!(n, 0); /// /// let mut n = 10u32; /// n.mod_power_of_2_neg_assign(4); /// assert_eq!(n, 6); /// /// let mut n = 100u16; /// n.mod_power_of_2_neg_assign(8); /// assert_eq!(n, 156); /// ``` pub mod mod_power_of_2_neg; /// [`ModPowerOf2Pow`](traits::ModPowerOf2Pow) and /// [`ModPowerOf2PowAssign`](traits::ModPowerOf2PowAssign), traits for raising a number to a power /// modulo $2^k$. /// /// # mod_power_of_2_pow /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow; /// /// assert_eq!(5u8.mod_power_of_2_pow(13, 3), 5); /// assert_eq!(7u32.mod_power_of_2_pow(1000, 6), 1); /// ``` /// /// # mod_power_of_2_pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign; /// /// let mut n = 5u8; /// n.mod_power_of_2_pow_assign(13, 3); /// assert_eq!(n, 5); /// /// let mut n = 7u32; /// n.mod_power_of_2_pow_assign(1000, 6); /// assert_eq!(n, 1); /// ``` pub mod mod_power_of_2_pow; /// [`ModPowerOf2Shl`](traits::ModPowerOf2Shl) and /// [`ModPowerOf2ShlAssign`](traits::ModPowerOf2ShlAssign), traits for left-shifting a number modulo /// $2^k$. /// /// # mod_power_of_2_shl /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Shl; /// /// assert_eq!(12u32.mod_power_of_2_shl(2u8, 5), 16); /// assert_eq!(10u8.mod_power_of_2_shl(100u64, 4), 0); /// /// assert_eq!(12u32.mod_power_of_2_shl(2i8, 5), 16); /// assert_eq!(10u8.mod_power_of_2_shl(-2i64, 4), 2); /// ``` /// /// # mod_power_of_2_shl_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2ShlAssign; /// /// let mut n = 12u32; /// n.mod_power_of_2_shl_assign(2u8, 5); /// assert_eq!(n, 16); /// /// let mut n = 10u8; /// n.mod_power_of_2_shl_assign(100u64, 4); /// assert_eq!(n, 0); /// /// let mut n = 12u32; /// n.mod_power_of_2_shl_assign(2i8, 5); /// assert_eq!(n, 16); /// /// let mut n = 10u8; /// n.mod_power_of_2_shl_assign(-2i64, 4); /// assert_eq!(n, 2); /// ``` pub mod mod_power_of_2_shl; /// [`ModPowerOf2Shr`](traits::ModPowerOf2Shr) and /// [`ModPowerOf2ShrAssign`](traits::ModPowerOf2ShrAssign), traits for right-shifting a number /// modulo $2^k$. /// /// # mod_power_of_2_shr /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Shr; /// /// assert_eq!(10u8.mod_power_of_2_shr(2i64, 4), 2); /// assert_eq!(12u32.mod_power_of_2_shr(-2i8, 5), 16); /// ``` /// /// # mod_power_of_2_shr_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2ShrAssign; /// /// let mut n = 10u8; /// n.mod_power_of_2_shr_assign(2i64, 4); /// assert_eq!(n, 2); /// /// let mut n = 12u32; /// n.mod_power_of_2_shr_assign(-2i8, 5); /// assert_eq!(n, 16); /// ``` pub mod mod_power_of_2_shr; /// [`ModPowerOf2Square`](traits::ModPowerOf2Square) and /// [`ModPowerOf2SquareAssign`](traits::ModPowerOf2SquareAssign), traits for squaring a number /// modulo $2^k$. /// /// # mod_power_of_2_square /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Square; /// /// assert_eq!(5u8.mod_power_of_2_square(3), 1); /// assert_eq!(100u32.mod_power_of_2_square(8), 16); /// ``` /// /// # mod_power_of_2_square_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2SquareAssign; /// /// let mut n = 5u8; /// n.mod_power_of_2_square_assign(3); /// assert_eq!(n, 1); /// /// let mut n = 100u32; /// n.mod_power_of_2_square_assign(8); /// assert_eq!(n, 16); /// ``` pub mod mod_power_of_2_square; /// [`ModPowerOf2Sub`](traits::ModPowerOf2Sub) and /// [`ModPowerOf2SubAssign`](traits::ModPowerOf2SubAssign), traits for subtracting one number by /// another modulo $2^k$. /// /// # mod_power_of_2_sub /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Sub; /// /// assert_eq!(5u8.mod_power_of_2_sub(2, 5), 3); /// assert_eq!(10u32.mod_power_of_2_sub(14, 4), 12); /// ``` /// /// # mod_power_of_2_sub_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2SubAssign; /// /// let mut n = 5u8; /// n.mod_power_of_2_sub_assign(2, 5); /// assert_eq!(n, 3); /// /// let mut n = 10u32; /// n.mod_power_of_2_sub_assign(14, 4); /// assert_eq!(n, 12); /// ``` pub mod mod_power_of_2_sub; /// [`ModShl`](traits::ModShl) and [`ModShlAssign`](traits::ModShlAssign), traits for left-shifting /// a number modulo another number. /// /// # mod_shl /// ``` /// use malachite_base::num::arithmetic::traits::ModShl; /// /// assert_eq!(8u32.mod_shl(2u8, 10), 2); /// assert_eq!(10u8.mod_shl(100u64, 17), 7); /// /// assert_eq!(8u32.mod_shl(2i8, 10), 2); /// assert_eq!(10u8.mod_shl(-2i64, 15), 2); /// ``` /// /// # mod_shl_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModShlAssign; /// /// let mut n = 8u32; /// n.mod_shl_assign(2u8, 10); /// assert_eq!(n, 2); /// /// let mut n = 10u8; /// n.mod_shl_assign(100u64, 17); /// assert_eq!(n, 7); /// /// let mut n = 8u32; /// n.mod_shl_assign(2i8, 10); /// assert_eq!(n, 2); /// /// let mut n = 10u8; /// n.mod_shl_assign(-2i64, 15); /// assert_eq!(n, 2); /// ``` pub mod mod_shl; /// [`ModShr`](traits::ModShr) and [`ModShrAssign`](traits::ModShrAssign), traits for right-shifting /// a number modulo another number. /// /// # mod_shr /// ``` /// use malachite_base::num::arithmetic::traits::ModShr; /// /// assert_eq!(10u8.mod_shr(2i64, 15), 2); /// assert_eq!(8u32.mod_shr(-2i8, 10), 2); /// ``` /// /// # mod_shr_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModShrAssign; /// /// let mut n = 10u8; /// n.mod_shr_assign(2i64, 15); /// assert_eq!(n, 2); /// /// let mut n = 8u32; /// n.mod_shr_assign(-2i8, 10); /// assert_eq!(n, 2); /// ``` pub mod mod_shr; /// Traits for squaring a number modulo another number. /// /// The traits are [`ModSquare`](traits::ModSquare), [`ModSquareAssign`](traits::ModSquareAssign), /// and [`ModSquarePrecomputed`](traits::ModSquarePrecomputed). /// [`ModSquarePrecomputed`](traits::ModSquarePrecomputed) is useful when having to make several /// squarings modulo the same modulus. /// /// # mod_square /// ``` /// use malachite_base::num::arithmetic::traits::ModSquare; /// /// assert_eq!(2u8.mod_square(10), 4); /// assert_eq!(100u32.mod_square(497), 60); /// ``` /// /// # mod_square_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModSquareAssign; /// /// let mut n = 2u8; /// n.mod_square_assign(10); /// assert_eq!(n, 4); /// /// let mut n = 100u32; /// n.mod_square_assign(497); /// assert_eq!(n, 60); /// ``` /// /// # mod_square_precomputed /// ``` /// use malachite_base::num::arithmetic::traits::{ModPowPrecomputed, ModSquarePrecomputed}; /// /// let data = u16::precompute_mod_pow_data(&497); /// assert_eq!(100u16.mod_square_precomputed(497, &data), 60); /// assert_eq!(200u16.mod_square_precomputed(497, &data), 240); /// assert_eq!(300u16.mod_square_precomputed(497, &data), 43); /// ``` /// /// # mod_square_precomputed_assign /// ``` /// use malachite_base::num::arithmetic::traits::{ModPowPrecomputed, ModSquarePrecomputedAssign}; /// /// let data = u32::precompute_mod_pow_data(&497); /// /// let mut x = 100u32; /// x.mod_square_precomputed_assign(497, &data); /// assert_eq!(x, 60); /// /// let mut x = 200u32; /// x.mod_square_precomputed_assign(497, &data); /// assert_eq!(x, 240); /// /// let mut x = 300u32; /// x.mod_square_precomputed_assign(497, &data); /// assert_eq!(x, 43); /// ``` pub mod mod_square; /// [`ModSub`](traits::ModSub) and [`ModSubAssign`](traits::ModSubAssign), traits for subtracting /// two numbers modulo another number. /// /// # mod_sub /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// /// assert_eq!(4u8.mod_sub(3, 5), 1); /// assert_eq!(7u32.mod_sub(9, 10), 8); /// ``` /// /// # mod_sub_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModSubAssign; /// /// let mut n = 4u8; /// n.mod_sub_assign(3, 5); /// assert_eq!(n, 1); /// /// let mut n = 7u32; /// n.mod_sub_assign(9, 10); /// assert_eq!(n, 8); /// ``` pub mod mod_sub; /// [`NegAssign`](traits::NegAssign), a trait for negating a number in place. /// /// # neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::NegAssign; /// /// let mut x = 0i8; /// x.neg_assign(); /// assert_eq!(x, 0i8); /// /// let mut x = 100i64; /// x.neg_assign(); /// assert_eq!(x, -100i64); /// /// let mut x = -100i64; /// x.neg_assign(); /// assert_eq!(x, 100i64); /// /// let mut x = 1.2f32; /// x.neg_assign(); /// assert_eq!(x, -1.2f32); /// ``` pub mod neg; /// [`NextPowerOf2`](traits::NextPowerOf2) and [`NextPowerOf2Assign`](traits::NextPowerOf2Assign), /// traits for getting the next-highest power of 2. /// /// # next_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::NextPowerOf2; /// /// assert_eq!(100.0f32.next_power_of_2(), 128.0); /// assert_eq!(0.01f32.next_power_of_2(), 0.015625); /// ``` /// /// # next_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::NextPowerOf2Assign; /// /// let mut x = 0u8; /// x.next_power_of_2_assign(); /// assert_eq!(x, 1); /// /// let mut x = 4u16; /// x.next_power_of_2_assign(); /// assert_eq!(x, 4); /// /// let mut x = 10u32; /// x.next_power_of_2_assign(); /// assert_eq!(x, 16); /// /// let mut x = (1u64 << 40) - 5; /// x.next_power_of_2_assign(); /// assert_eq!(x, 1 << 40); /// /// let mut x = 100.0f32; /// x.next_power_of_2_assign(); /// assert_eq!(x, 128.0); /// /// let mut x = 0.01f32; /// x.next_power_of_2_assign(); /// assert_eq!(x, 0.015625); /// ``` pub mod next_power_of_2; /// [`OverflowingAbs`](traits::OverflowingAbs) and /// [`OverflowingAbsAssign`](traits::OverflowingAbsAssign), traits for taking the absolute value of /// a number and returning a boolean indicating whether an overflow occurred. /// /// # overflowing_abs_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingAbsAssign; /// /// let mut x = 0i8; /// assert_eq!(x.overflowing_abs_assign(), false); /// assert_eq!(x, 0); /// /// let mut x = 100i64; /// assert_eq!(x.overflowing_abs_assign(), false); /// assert_eq!(x, 100); /// /// let mut x = -100i64; /// assert_eq!(x.overflowing_abs_assign(), false); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// assert_eq!(x.overflowing_abs_assign(), true); /// assert_eq!(x, -128); /// ``` pub mod overflowing_abs; /// [`OverflowingAdd`](traits::OverflowingAdd) and /// [`OverflowingAddAssign`](traits::OverflowingAddAssign), traits for adding two numbers and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_add_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingAddAssign; /// /// let mut x = 123u16; /// assert_eq!(x.overflowing_add_assign(456), false); /// assert_eq!(x, 579); /// /// let mut x = 123u8; /// assert_eq!(x.overflowing_add_assign(200), true); /// assert_eq!(x, 67); /// ``` pub mod overflowing_add; /// [`OverflowingAddMul`](traits::OverflowingAddMul) and /// [`OverflowingAddMulAssign`](traits::OverflowingAddMulAssign), traits for adding the product of /// two other numbers to a number and returning a boolean indicating whether an overflow occurred. /// /// # overflowing_add_mul /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingAddMul; /// /// assert_eq!(2u8.overflowing_add_mul(3, 7), (23, false)); /// assert_eq!(2u8.overflowing_add_mul(20, 20), (146, true)); /// /// assert_eq!(127i8.overflowing_add_mul(-2, 100), (-73, false)); /// assert_eq!((-127i8).overflowing_add_mul(-2, 100), (-71, true)); /// ``` /// /// # overflowing_add_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingAddMulAssign; /// /// let mut x = 2u8; /// assert_eq!(x.overflowing_add_mul_assign(3, 7), false); /// assert_eq!(x, 23); /// /// let mut x = 2u8; /// assert_eq!(x.overflowing_add_mul_assign(20, 20), true); /// assert_eq!(x, 146); /// /// let mut x = 127i8; /// assert_eq!(x.overflowing_add_mul_assign(-2, 100), false); /// assert_eq!(x, -73); /// /// let mut x = -127i8; /// assert_eq!(x.overflowing_add_mul_assign(-2, 100), true); /// assert_eq!(x, -71); /// ``` pub mod overflowing_add_mul; /// [`OverflowingDiv`](traits::OverflowingDiv) and /// [`OverflowingDivAssign`](traits::OverflowingDivAssign), traits for dividing two numbers and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_div_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingDivAssign; /// /// let mut x = 100u16; /// assert_eq!(x.overflowing_div_assign(3), false); /// assert_eq!(x, 33); /// /// let mut x = -128i8; /// assert_eq!(x.overflowing_div_assign(-1), true); /// assert_eq!(x, -128); /// ``` pub mod overflowing_div; /// [`OverflowingMul`](traits::OverflowingMul) and /// [`OverflowingMulAssign`](traits::OverflowingMulAssign), traits for multiplying two numbers and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingMulAssign; /// /// let mut x = 123u16; /// assert_eq!(x.overflowing_mul_assign(456), false); /// assert_eq!(x, 56088); /// /// let mut x = 123u8; /// assert_eq!(x.overflowing_mul_assign(200), true); /// assert_eq!(x, 24); /// ``` pub mod overflowing_mul; /// [`OverflowingNeg`](traits::OverflowingNeg) and /// [`OverflowingNegAssign`](traits::OverflowingNegAssign), traits for negating a number and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingNegAssign; /// /// let mut x = 0i8; /// assert_eq!(x.overflowing_neg_assign(), false); /// assert_eq!(x, 0); /// /// let mut x = 100u64; /// assert_eq!(x.overflowing_neg_assign(), true); /// assert_eq!(x, 18446744073709551516); /// /// let mut x = -100i64; /// assert_eq!(x.overflowing_neg_assign(), false); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// assert_eq!(x.overflowing_neg_assign(), true); /// assert_eq!(x, -128); /// ``` pub mod overflowing_neg; /// [`OverflowingPow`](traits::OverflowingPow) and /// [`OverflowingPowAssign`](traits::OverflowingPowAssign), traits for raising a number to a power /// and returning a boolean indicating whether an overflow occurred. /// /// # overflowing_pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingPowAssign; /// /// let mut x = 3u8; /// assert_eq!(x.overflowing_pow_assign(3), false); /// assert_eq!(x, 27); /// /// let mut x = -10i32; /// assert_eq!(x.overflowing_pow_assign(9), false); /// assert_eq!(x, -1000000000); /// /// let mut x = -10i16; /// assert_eq!(x.overflowing_pow_assign(9), true); /// assert_eq!(x, 13824); /// ``` pub mod overflowing_pow; /// [`OverflowingSquare`](traits::OverflowingSquare) and /// [`OverflowingSquareAssign`](traits::OverflowingSquareAssign), traits for squaring a number and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_square_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingSquareAssign; /// /// let mut x = 3u8; /// assert_eq!(x.overflowing_square_assign(), false); /// assert_eq!(x, 9); /// /// let mut x = -1000i32; /// assert_eq!(x.overflowing_square_assign(), false); /// assert_eq!(x, 1000000); /// /// let mut x = 1000u16; /// assert_eq!(x.overflowing_square_assign(), true); /// assert_eq!(x, 16960); /// ``` pub mod overflowing_square; /// [`OverflowingSub`](traits::OverflowingSub) and /// [`OverflowingSubAssign`](traits::OverflowingSubAssign), traits for subtracting two numbers and /// returning a boolean indicating whether an overflow occurred. /// /// # overflowing_sub /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingSquare; /// /// assert_eq!(3u8.overflowing_square(), (9, false)); /// assert_eq!((-1000i32).overflowing_square(), (1000000, false)); /// assert_eq!(1000u16.overflowing_square(), (16960, true)); /// ``` /// /// # overflowing_sub_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingSubAssign; /// /// let mut x = 456u16; /// assert_eq!(x.overflowing_sub_assign(123), false); /// assert_eq!(x, 333); /// /// let mut x = 123u16; /// assert_eq!(x.overflowing_sub_assign(456), true); /// assert_eq!(x, 65203); /// ``` pub mod overflowing_sub; /// [`OverflowingSubMul`](traits::OverflowingSubMul) and /// [`OverflowingSubMulAssign`](traits::OverflowingSubMulAssign), traits for subtracting the product /// of two other numbers from a number and returning a boolean indicating whether an overflow /// occurred. /// /// # overflowing_sub_mul /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingSubMul; /// /// assert_eq!(60u8.overflowing_sub_mul(5, 10), (10, false)); /// assert_eq!(2u8.overflowing_sub_mul(10, 5), (208, true)); /// /// assert_eq!(127i8.overflowing_sub_mul(2, 100), (-73, false)); /// assert_eq!((-127i8).overflowing_sub_mul(2, 100), (-71, true)); /// ``` /// /// # overflowing_sub_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::OverflowingSubMulAssign; /// /// let mut x = 60u8; /// assert_eq!(x.overflowing_sub_mul_assign(5, 10), false); /// assert_eq!(x, 10); /// /// let mut x = 2u8; /// assert_eq!(x.overflowing_sub_mul_assign(10, 5), true); /// assert_eq!(x, 208); /// /// let mut x = 127i8; /// assert_eq!(x.overflowing_sub_mul_assign(2, 100), false); /// assert_eq!(x, -73); /// /// let mut x = -127i8; /// assert_eq!(x.overflowing_sub_mul_assign(2, 100), true); /// assert_eq!(x, -71); /// ``` pub mod overflowing_sub_mul; /// [`Parity`](traits::Parity), a trait for determining whether a number is even or odd. /// /// # even /// ``` /// use malachite_base::num::arithmetic::traits::Parity; /// /// assert_eq!(0u8.even(), true); /// assert_eq!((-5i16).even(), false); /// assert_eq!(4u32.even(), true); /// ``` /// /// # odd /// ``` /// use malachite_base::num::arithmetic::traits::Parity; /// /// assert_eq!(0u8.odd(), false); /// assert_eq!((-5i16).odd(), true); /// assert_eq!(4u32.odd(), false); /// ``` pub mod parity; /// [`Pow`](traits::Pow) and [`PowAssign`](traits::PowAssign), traits for raising a number to a /// power. /// /// # pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::PowAssign; /// /// let mut x = 3u8; /// x.pow_assign(3); /// assert_eq!(x, 27); /// /// let mut x = -10i32; /// x.pow_assign(9); /// assert_eq!(x, -1000000000); /// /// let mut x = 2.0f32; /// x.pow_assign(5); /// assert_eq!(x, 32.0); /// /// let mut x = 2.0f32; /// x.pow_assign(5.0); /// assert_eq!(x, 32.0); /// ``` pub mod pow; /// [`PowerOf2`](traits::PowerOf2), a trait for computing a power of 2. /// /// # power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// /// assert_eq!(u16::power_of_2(0), 1); /// assert_eq!(u8::power_of_2(3), 8); /// assert_eq!(u64::power_of_2(40), 1 << 40); /// /// assert_eq!(i16::power_of_2(0), 1); /// assert_eq!(i8::power_of_2(3), 8); /// assert_eq!(i64::power_of_2(40), 1 << 40); /// /// assert_eq!(f32::power_of_2(0u64), 1.0); /// assert_eq!(f32::power_of_2(3u64), 8.0); /// assert_eq!(f32::power_of_2(-3i64), 0.125); /// ``` pub mod power_of_2; /// Traits for computing the primorial and the product of the first $n$ primes. There is a trait /// whose implementations panic if the result cannot be represented, and a checked trait whose /// implementations return `None` in that case: [`Primorial`](traits::Primorial) and /// [`CheckedPrimorial`](traits::CheckedPrimorial). /// /// # primorial /// ``` /// use malachite_base::num::arithmetic::traits::Primorial; /// /// assert_eq!(u8::primorial(0), 1); /// assert_eq!(u8::primorial(1), 1); /// assert_eq!(u8::primorial(2), 2); /// assert_eq!(u8::primorial(3), 6); /// assert_eq!(u8::primorial(4), 6); /// assert_eq!(u8::primorial(5), 30); /// assert_eq!(u32::primorial(20), 9699690); /// ``` /// /// # product_of_first_n_primes /// ``` /// use malachite_base::num::arithmetic::traits::Primorial; /// /// assert_eq!(u8::product_of_first_n_primes(0), 1); /// assert_eq!(u8::product_of_first_n_primes(1), 2); /// assert_eq!(u8::product_of_first_n_primes(2), 6); /// assert_eq!(u8::product_of_first_n_primes(3), 30); /// assert_eq!(u8::product_of_first_n_primes(4), 210); /// assert_eq!(u32::product_of_first_n_primes(9), 223092870); /// ``` /// /// # checked_primorial /// ``` /// use malachite_base::num::arithmetic::traits::CheckedPrimorial; /// /// assert_eq!(u8::checked_primorial(0), Some(1)); /// assert_eq!(u8::checked_primorial(1), Some(1)); /// assert_eq!(u8::checked_primorial(2), Some(2)); /// assert_eq!(u8::checked_primorial(3), Some(6)); /// assert_eq!(u8::checked_primorial(4), Some(6)); /// assert_eq!(u8::checked_primorial(5), Some(30)); /// /// assert_eq!(u8::checked_primorial(11), None); /// assert_eq!(u32::checked_primorial(20), Some(9699690)); /// assert_eq!(u32::checked_primorial(100), None); /// ``` /// /// # checked_product_of_first_n_primes /// ``` /// use malachite_base::num::arithmetic::traits::CheckedPrimorial; /// /// assert_eq!(u8::checked_product_of_first_n_primes(0), Some(1)); /// assert_eq!(u8::checked_product_of_first_n_primes(1), Some(2)); /// assert_eq!(u8::checked_product_of_first_n_primes(2), Some(6)); /// assert_eq!(u8::checked_product_of_first_n_primes(3), Some(30)); /// assert_eq!(u8::checked_product_of_first_n_primes(4), Some(210)); /// assert_eq!(u32::checked_product_of_first_n_primes(9), Some(223092870)); /// /// assert_eq!(u8::checked_product_of_first_n_primes(5), None); /// assert_eq!(u32::checked_product_of_first_n_primes(100), None); /// ``` pub mod primorial; /// [`Reciprocal`](traits::Reciprocal) and [`ReciprocalAssign`](traits::ReciprocalAssign), traits /// for computing the reciprocal (multiplicative inverse) of a number. /// /// # reciprocal /// ``` /// use malachite_base::num::arithmetic::traits::Reciprocal; /// /// assert_eq!(0.0f32.reciprocal(), f32::INFINITY); /// assert_eq!(1.5f32.reciprocal(), 0.6666667); /// ``` /// /// # reciprocal_assign /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalAssign; /// /// let mut x = 0.0f32; /// x.reciprocal_assign(); /// assert_eq!(x, f32::INFINITY); /// /// let mut x = 1.5f32; /// x.reciprocal_assign(); /// assert_eq!(x, 0.6666667); /// ``` pub mod reciprocal; /// Traits for taking the $n$th root of a number. /// /// The traits are [`FloorRoot`](traits::FloorRoot), [`FloorRootAssign`](traits::FloorRootAssign), /// [`CeilingRoot`](traits::CeilingRoot), [`CeilingRootAssign`](traits::CeilingRootAssign), /// [`CheckedRoot`](traits::CheckedRoot), [`RootRem`](traits::RootRem), and /// [`RootAssignRem`](traits::RootAssignRem). /// /// # floor_root /// ``` /// use malachite_base::num::arithmetic::traits::FloorRoot; /// /// assert_eq!(999u16.floor_root(3), 9); /// assert_eq!(1000u16.floor_root(3), 10); /// assert_eq!(1001u16.floor_root(3), 10); /// assert_eq!(100000000000i64.floor_root(5), 158); /// assert_eq!((-100000000000i64).floor_root(5), -159); /// ``` /// /// # floor_root_assign /// ``` /// use malachite_base::num::arithmetic::traits::FloorRootAssign; /// /// let mut x = 999u16; /// x.floor_root_assign(3); /// assert_eq!(x, 9); /// /// let mut x = 1000u16; /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = 1001u16; /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = 100000000000i64; /// x.floor_root_assign(5); /// assert_eq!(x, 158); /// /// let mut x = -100000000000i64; /// x.floor_root_assign(5); /// assert_eq!(x, -159); /// ``` /// /// # ceiling_root /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRoot; /// /// assert_eq!(999u16.ceiling_root(3), 10); /// assert_eq!(1000u16.ceiling_root(3), 10); /// assert_eq!(1001u16.ceiling_root(3), 11); /// assert_eq!(100000000000i64.ceiling_root(5), 159); /// assert_eq!((-100000000000i64).ceiling_root(5), -158); /// ``` /// /// # ceiling_root_assign /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRootAssign; /// /// let mut x = 999u16; /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = 1000u16; /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = 1001u16; /// x.ceiling_root_assign(3); /// assert_eq!(x, 11); /// /// let mut x = 100000000000i64; /// x.ceiling_root_assign(5); /// assert_eq!(x, 159); /// /// let mut x = -100000000000i64; /// x.ceiling_root_assign(5); /// assert_eq!(x, -158); /// ``` /// /// # checked_root /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// /// assert_eq!(999u16.checked_root(3), None); /// assert_eq!(1000u16.checked_root(3), Some(10)); /// assert_eq!(1001u16.checked_root(3), None); /// assert_eq!(100000000000i64.checked_root(5), None); /// assert_eq!((-100000000000i64).checked_root(5), None); /// assert_eq!(10000000000i64.checked_root(5), Some(100)); /// assert_eq!((-10000000000i64).checked_root(5), Some(-100)); /// ``` /// /// # root_rem /// ``` /// use malachite_base::num::arithmetic::traits::RootRem; /// /// assert_eq!(999u16.root_rem(3), (9, 270)); /// assert_eq!(1000u16.root_rem(3), (10, 0)); /// assert_eq!(1001u16.root_rem(3), (10, 1)); /// assert_eq!(100000000000u64.root_rem(5), (158, 1534195232)); /// ``` /// /// # root_assign_rem /// ``` /// use malachite_base::num::arithmetic::traits::RootAssignRem; /// /// let mut x = 999u16; /// assert_eq!(x.root_assign_rem(3), 270); /// assert_eq!(x, 9); /// /// let mut x = 1000u16; /// assert_eq!(x.root_assign_rem(3), 0); /// assert_eq!(x, 10); /// /// let mut x = 1001u16; /// assert_eq!(x.root_assign_rem(3), 1); /// assert_eq!(x, 10); /// /// let mut x = 100000000000u64; /// assert_eq!(x.root_assign_rem(5), 1534195232); /// assert_eq!(x, 158); /// ``` pub mod root; /// [`RotateLeft`](traits::RotateLeft), [`RotateLeftAssign`](traits::RotateLeftAssign), /// [`RotateRight`](traits::RotateRight), and [`RotateRightAssign`](traits::RotateRightAssign), /// traits for rotating a number's bits. /// /// # rotate_left_assign /// ``` /// use malachite_base::num::arithmetic::traits::RotateLeftAssign; /// /// let mut x: u32 = 0xabcd6789; /// x.rotate_left_assign(4); /// assert_eq!(x, 0xbcd6789a); /// /// x = 0xabcd6789; /// x.rotate_left_assign(32); /// assert_eq!(x, 0xabcd6789); /// /// x = 0xabcd6789; /// x.rotate_left_assign(36); /// assert_eq!(x, 0xbcd6789a); /// ``` /// /// # rotate_right_assign /// ``` /// use malachite_base::num::arithmetic::traits::RotateRightAssign; /// /// let mut x: u32 = 0xabcd6789; /// x.rotate_right_assign(4); /// assert_eq!(x, 0x9abcd678); /// /// x = 0xabcd6789; /// x.rotate_right_assign(32); /// assert_eq!(x, 0xabcd6789); /// /// x = 0xabcd6789; /// x.rotate_right_assign(36); /// assert_eq!(x, 0x9abcd678); /// ``` pub mod rotate; /// [`RoundToMultiple`](traits::RoundToMultiple) and /// [`RoundToMultipleAssign`](traits::RoundToMultipleAssign), traits for rounding a number to a /// multiple of another number. /// /// # round_to_multiple /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(5u32.round_to_multiple(0, Down), (0, Less)); /// /// assert_eq!(10u8.round_to_multiple(4, Down), (8, Less)); /// assert_eq!(10u16.round_to_multiple(4, Up), (12, Greater)); /// assert_eq!(10u32.round_to_multiple(5, Exact), (10, Equal)); /// assert_eq!(10u64.round_to_multiple(3, Nearest), (9, Less)); /// assert_eq!(20u128.round_to_multiple(3, Nearest), (21, Greater)); /// assert_eq!(10usize.round_to_multiple(4, Nearest), (8, Less)); /// assert_eq!(14u8.round_to_multiple(4, Nearest), (16, Greater)); /// /// assert_eq!((-5i32).round_to_multiple(0, Down), (0, Greater)); /// /// assert_eq!((-10i8).round_to_multiple(4, Down), (-8, Greater)); /// assert_eq!((-10i16).round_to_multiple(4, Up), (-12, Less)); /// assert_eq!((-10i32).round_to_multiple(5, Exact), (-10, Equal)); /// assert_eq!((-10i64).round_to_multiple(3, Nearest), (-9, Greater)); /// assert_eq!((-20i128).round_to_multiple(3, Nearest), (-21, Less)); /// assert_eq!((-10isize).round_to_multiple(4, Nearest), (-8, Greater)); /// assert_eq!((-14i8).round_to_multiple(4, Nearest), (-16, Less)); /// /// assert_eq!((-10i16).round_to_multiple(-4, Down), (-8, Greater)); /// assert_eq!((-10i32).round_to_multiple(-4, Up), (-12, Less)); /// assert_eq!((-10i64).round_to_multiple(-5, Exact), (-10, Equal)); /// assert_eq!((-10i128).round_to_multiple(-3, Nearest), (-9, Greater)); /// assert_eq!((-20isize).round_to_multiple(-3, Nearest), (-21, Less)); /// assert_eq!((-10i8).round_to_multiple(-4, Nearest), (-8, Greater)); /// assert_eq!((-14i16).round_to_multiple(-4, Nearest), (-16, Less)); /// ``` /// /// # round_to_multiple_assign /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// let mut x = 5u32; /// assert_eq!(x.round_to_multiple_assign(0, Down), Less); /// assert_eq!(x, 0); /// /// let mut x = 10u8; /// assert_eq!(x.round_to_multiple_assign(4, Down), Less); /// assert_eq!(x, 8); /// /// let mut x = 10u16; /// assert_eq!(x.round_to_multiple_assign(4, Up), Greater); /// assert_eq!(x, 12); /// /// let mut x = 10u32; /// assert_eq!(x.round_to_multiple_assign(5, Exact), Equal); /// assert_eq!(x, 10); /// /// let mut x = 10u64; /// assert_eq!(x.round_to_multiple_assign(3, Nearest), Less); /// assert_eq!(x, 9); /// /// let mut x = 20u128; /// assert_eq!(x.round_to_multiple_assign(3, Nearest), Greater); /// assert_eq!(x, 21); /// /// let mut x = 10usize; /// assert_eq!(x.round_to_multiple_assign(4, Nearest), Less); /// assert_eq!(x, 8); /// /// let mut x = 14u8; /// assert_eq!(x.round_to_multiple_assign(4, Nearest), Greater); /// assert_eq!(x, 16); /// /// let mut x = -5i32; /// assert_eq!(x.round_to_multiple_assign(0, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = -10i8; /// assert_eq!(x.round_to_multiple_assign(4, Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = -10i16; /// assert_eq!(x.round_to_multiple_assign(4, Up), Less); /// assert_eq!(x, -12); /// /// let mut x = -10i32; /// assert_eq!(x.round_to_multiple_assign(5, Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = -10i64; /// assert_eq!(x.round_to_multiple_assign(3, Nearest), Greater); /// assert_eq!(x, -9); /// /// let mut x = -20i128; /// assert_eq!(x.round_to_multiple_assign(3, Nearest), Less); /// assert_eq!(x, -21); /// /// let mut x = -10isize; /// assert_eq!(x.round_to_multiple_assign(4, Nearest), Greater); /// assert_eq!(x, -8); /// /// let mut x = -14i8; /// assert_eq!(x.round_to_multiple_assign(4, Nearest), Less); /// assert_eq!(x, -16); /// /// let mut x = -10i16; /// assert_eq!(x.round_to_multiple_assign(-4, Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = -10i32; /// assert_eq!(x.round_to_multiple_assign(-4, Up), Less); /// assert_eq!(x, -12); /// /// let mut x = -10i64; /// assert_eq!(x.round_to_multiple_assign(-5, Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = -10i128; /// assert_eq!(x.round_to_multiple_assign(-3, Nearest), Greater); /// assert_eq!(x, -9); /// /// let mut x = -20isize; /// assert_eq!(x.round_to_multiple_assign(-3, Nearest), Less); /// assert_eq!(x, -21); /// /// let mut x = -10i8; /// assert_eq!(x.round_to_multiple_assign(-4, Nearest), Greater); /// assert_eq!(x, -8); /// /// let mut x = -14i16; /// assert_eq!(x.round_to_multiple_assign(-4, Nearest), Less); /// assert_eq!(x, -16); /// ``` pub mod round_to_multiple; /// [`RoundToMultipleOfPowerOf2`](traits::RoundToMultipleOfPowerOf2) and /// [`RoundToMultipleOfPowerOf2Assign`](traits::RoundToMultipleOfPowerOf2Assign), traits for /// rounding a number to a multiple of a power of 2. /// /// # round_to_multiple_of_power_of_2 /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(10u8.round_to_multiple_of_power_of_2(2, Floor), (8, Less)); /// assert_eq!( /// 10u8.round_to_multiple_of_power_of_2(2, Ceiling), /// (12, Greater) /// ); /// assert_eq!(10u8.round_to_multiple_of_power_of_2(2, Down), (8, Less)); /// assert_eq!(10u8.round_to_multiple_of_power_of_2(2, Up), (12, Greater)); /// assert_eq!(10u8.round_to_multiple_of_power_of_2(2, Nearest), (8, Less)); /// assert_eq!(12u8.round_to_multiple_of_power_of_2(2, Exact), (12, Equal)); /// /// assert_eq!( /// (-10i8).round_to_multiple_of_power_of_2(2, Floor), /// (-12, Less) /// ); /// assert_eq!( /// (-10i8).round_to_multiple_of_power_of_2(2, Ceiling), /// (-8, Greater) /// ); /// assert_eq!( /// (-10i8).round_to_multiple_of_power_of_2(2, Down), /// (-8, Greater) /// ); /// assert_eq!((-10i8).round_to_multiple_of_power_of_2(2, Up), (-12, Less)); /// assert_eq!( /// (-10i8).round_to_multiple_of_power_of_2(2, Nearest), /// (-8, Greater) /// ); /// assert_eq!( /// (-12i8).round_to_multiple_of_power_of_2(2, Exact), /// (-12, Equal) /// ); /// ``` /// /// # round_to_multiple_of_power_of_2_assign /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// let mut x = 10u8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Floor), Less); /// assert_eq!(x, 8); /// /// let mut x = 10u8; /// assert_eq!( /// x.round_to_multiple_of_power_of_2_assign(2, Ceiling), /// Greater /// ); /// assert_eq!(x, 12); /// /// let mut x = 10u8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Down), Less); /// assert_eq!(x, 8); /// /// let mut x = 10u8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Up), Greater); /// assert_eq!(x, 12); /// /// let mut x = 10u8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Nearest), Less); /// assert_eq!(x, 8); /// /// let mut x = 12u8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Exact), Equal); /// assert_eq!(x, 12); /// /// let mut x = -10i8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Floor), Less); /// assert_eq!(x, -12); /// /// let mut x = -10i8; /// assert_eq!( /// x.round_to_multiple_of_power_of_2_assign(2, Ceiling), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = -10i8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = -10i8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Up), Less); /// assert_eq!(x, -12); /// /// let mut x = -10i8; /// assert_eq!( /// x.round_to_multiple_of_power_of_2_assign(2, Nearest), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = -12i8; /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(2, Exact), Equal); /// assert_eq!(x, -12); /// ``` pub mod round_to_multiple_of_power_of_2; /// [`SaturatingAbs`](traits::SaturatingAbs) and /// [`SaturatingAbsAssign`](traits::SaturatingAbsAssign), traits for taking the absolute value of a /// number and saturating at numeric bounds instead of overflowing. /// /// # saturating_abs_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingAbsAssign; /// /// let mut x = 0i8; /// x.saturating_abs_assign(); /// assert_eq!(x, 0); /// /// let mut x = 100i64; /// x.saturating_abs_assign(); /// assert_eq!(x, 100); /// /// let mut x = -100i64; /// x.saturating_abs_assign(); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// x.saturating_abs_assign(); /// assert_eq!(x, 127); /// ``` pub mod saturating_abs; /// [`SaturatingAdd`](traits::SaturatingAdd) and /// [`SaturatingAddAssign`](traits::SaturatingAddAssign), traits for adding two numbers and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_add_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingAddAssign; /// /// let mut x = 123u16; /// x.saturating_add_assign(456); /// assert_eq!(x, 579); /// /// let mut x = 123u8; /// x.saturating_add_assign(200); /// assert_eq!(x, 255); /// ``` pub mod saturating_add; /// [`SaturatingAddMul`](traits::SaturatingAddMul) and /// [`SaturatingAddMulAssign`](traits::SaturatingAddMulAssign), traits for adding the product of two /// numbers to a number and saturating at numeric bounds instead of overflowing. /// /// # saturating_add_mul /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingAddMul; /// /// assert_eq!(2u8.saturating_add_mul(3, 7), 23); /// assert_eq!(2u8.saturating_add_mul(20, 20), 255); /// /// assert_eq!(127i8.saturating_add_mul(-2, 100), -73); /// assert_eq!((-127i8).saturating_add_mul(-2, 100), -128); /// ``` /// /// # saturating_add_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingAddMulAssign; /// /// let mut x = 2u8; /// x.saturating_add_mul_assign(3, 7); /// assert_eq!(x, 23); /// /// let mut x = 2u8; /// x.saturating_add_mul_assign(20, 20); /// assert_eq!(x, 255); /// /// let mut x = 127i8; /// x.saturating_add_mul_assign(-2, 100); /// assert_eq!(x, -73); /// /// let mut x = -127i8; /// x.saturating_add_mul_assign(-2, 100); /// assert_eq!(x, -128); /// ``` pub mod saturating_add_mul; /// [`SaturatingMul`](traits::SaturatingMul) and /// [`SaturatingMulAssign`](traits::SaturatingMulAssign), traits for multiplying two numbers and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingMulAssign; /// /// let mut x = 123u16; /// x.saturating_mul_assign(456); /// assert_eq!(x, 56088); /// /// let mut x = 123u8; /// x.saturating_mul_assign(200); /// assert_eq!(x, 255); /// ``` pub mod saturating_mul; /// [`SaturatingNeg`](traits::SaturatingNeg) and /// [`SaturatingNegAssign`](traits::SaturatingNegAssign), traits for negating a number and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingNegAssign; /// /// let mut x = 0i8; /// x.saturating_neg_assign(); /// assert_eq!(x, 0); /// /// let mut x = 100i64; /// x.saturating_neg_assign(); /// assert_eq!(x, -100); /// /// let mut x = -100i64; /// x.saturating_neg_assign(); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// x.saturating_neg_assign(); /// assert_eq!(x, 127); /// ``` pub mod saturating_neg; /// [`SaturatingPow`](traits::SaturatingPow) and /// [`SaturatingPowAssign`](traits::SaturatingPowAssign), traits for raising a number to a power and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingPowAssign; /// /// let mut x = 3u8; /// x.saturating_pow_assign(3); /// assert_eq!(x, 27); /// /// let mut x = -10i32; /// x.saturating_pow_assign(9); /// assert_eq!(x, -1000000000); /// /// let mut x = -10i16; /// x.saturating_pow_assign(9); /// assert_eq!(x, -32768); /// ``` pub mod saturating_pow; /// [`SaturatingSquare`](traits::SaturatingSquare) and /// [`SaturatingSquareAssign`](traits::SaturatingSquareAssign), traits for squaring a number and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_square /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSquare; /// /// assert_eq!(3u8.saturating_square(), 9); /// assert_eq!((-1000i32).saturating_square(), 1000000); /// assert_eq!(1000u16.saturating_square(), u16::MAX); /// ``` /// /// # saturating_square_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSquareAssign; /// /// let mut x = 3u8; /// x.saturating_square_assign(); /// assert_eq!(x, 9); /// /// let mut x = -1000i32; /// x.saturating_square_assign(); /// assert_eq!(x, 1000000); /// /// let mut x = 1000u16; /// x.saturating_square_assign(); /// assert_eq!(x, u16::MAX); /// ``` pub mod saturating_square; /// [`SaturatingSub`](traits::SaturatingSub) and /// [`SaturatingSubAssign`](traits::SaturatingSubAssign), traits for subtracting two numbers and /// saturating at numeric bounds instead of overflowing. /// /// # saturating_sub_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSubAssign; /// /// let mut x = 456u16; /// x.saturating_sub_assign(123); /// assert_eq!(x, 333); /// /// let mut x = 123u16; /// x.saturating_sub_assign(456); /// assert_eq!(x, 0); /// ``` pub mod saturating_sub; /// [`SaturatingSubMul`](traits::SaturatingSubMul) and /// [`SaturatingSubMulAssign`](traits::SaturatingSubMulAssign), traits for subtracting a number by /// the product of two numbers and saturating at numeric bounds instead of overflowing. /// /// # saturating_sub_mul /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSubMul; /// /// assert_eq!(60u8.saturating_sub_mul(5, 10), 10); /// assert_eq!(2u8.saturating_sub_mul(10, 5), 0); /// /// assert_eq!(127i8.saturating_sub_mul(2, 100), -73); /// assert_eq!((-127i8).saturating_sub_mul(2, 100), -128); /// ``` /// /// # saturating_sub_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSubMulAssign; /// /// let mut x = 60u8; /// x.saturating_sub_mul_assign(5, 10); /// assert_eq!(x, 10); /// /// let mut x = 2u8; /// x.saturating_sub_mul_assign(10, 5); /// assert_eq!(x, 0); /// /// let mut x = 127i8; /// x.saturating_sub_mul_assign(2, 100); /// assert_eq!(x, -73); /// /// let mut x = -127i8; /// x.saturating_sub_mul_assign(2, 100); /// assert_eq!(x, -128); /// ``` pub mod saturating_sub_mul; /// [`ShlRound`](traits::ShlRound) and [`ShlRoundAssign`](traits::ShlRoundAssign), traits for /// multiplying a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](crate::rounding_modes::RoundingMode). /// /// # shl_round /// ``` /// use malachite_base::num::arithmetic::traits::ShlRound; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(0x101u16.shl_round(-8i8, Down), (1, Less)); /// assert_eq!(0x101u32.shl_round(-8i16, Up), (2, Greater)); /// /// assert_eq!((-0x101i16).shl_round(-9i32, Down), (0, Greater)); /// assert_eq!((-0x101i32).shl_round(-9i64, Up), (-1, Less)); /// assert_eq!((-0x101i64).shl_round(-9i8, Nearest), (-1, Less)); /// assert_eq!((-0xffi32).shl_round(-9i16, Nearest), (0, Greater)); /// assert_eq!((-0x100i16).shl_round(-9i32, Nearest), (0, Greater)); /// /// assert_eq!(0x100u64.shl_round(-8i64, Exact), (1, Equal)); /// ``` /// /// # shl_round_assign /// ``` /// use malachite_base::num::arithmetic::traits::ShlRoundAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// let mut x = 0x101u16; /// assert_eq!(x.shl_round_assign(-8i8, Down), Less); /// assert_eq!(x, 1); /// /// let mut x = 0x101u32; /// assert_eq!(x.shl_round_assign(-8i16, Up), Greater); /// assert_eq!(x, 2); /// /// let mut x = -0x101i16; /// assert_eq!(x.shl_round_assign(-9i32, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x101i32; /// assert_eq!(x.shl_round_assign(-9i64, Up), Less); /// assert_eq!(x, -1); /// /// let mut x = -0x101i64; /// assert_eq!(x.shl_round_assign(-9i8, Nearest), Less); /// assert_eq!(x, -1); /// /// let mut x = -0xffi32; /// assert_eq!(x.shl_round_assign(-9i16, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x100i16; /// assert_eq!(x.shl_round_assign(-9i32, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = 0x100u64; /// assert_eq!(x.shl_round_assign(-8i64, Exact), Equal); /// assert_eq!(x, 1); /// ``` pub mod shl_round; /// [`ShrRound`](traits::ShrRound) and [`ShrRoundAssign`](traits::ShrRoundAssign), traits for /// dividing a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](crate::rounding_modes::RoundingMode). /// /// # shr_round /// ``` /// use malachite_base::num::arithmetic::traits::ShrRound; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(0x101u32.shr_round(8u8, Down), (1, Less)); /// assert_eq!(0x101u16.shr_round(8u16, Up), (2, Greater)); /// /// assert_eq!(0x101u64.shr_round(9u32, Down), (0, Less)); /// assert_eq!(0x101u32.shr_round(9u64, Up), (1, Greater)); /// assert_eq!(0x101u16.shr_round(9u8, Nearest), (1, Greater)); /// assert_eq!(0xffu8.shr_round(9u16, Nearest), (0, Less)); /// assert_eq!(0x100u32.shr_round(9u32, Nearest), (0, Less)); /// /// assert_eq!(0x100u32.shr_round(8u64, Exact), (1, Equal)); /// /// assert_eq!(0x101i32.shr_round(8u8, Down), (1, Less)); /// assert_eq!(0x101i16.shr_round(8u16, Up), (2, Greater)); /// /// assert_eq!((-0x101i32).shr_round(9u32, Down), (0, Greater)); /// assert_eq!((-0x101i64).shr_round(9u64, Up), (-1, Less)); /// assert_eq!((-0x101i16).shr_round(9u8, Nearest), (-1, Less)); /// assert_eq!((-0xffi32).shr_round(9u16, Nearest), (0, Greater)); /// assert_eq!((-0x100i64).shr_round(9u32, Nearest), (0, Greater)); /// /// assert_eq!(0x100i32.shr_round(8u64, Exact), (1, Equal)); /// /// assert_eq!(0x101u32.shr_round(8i8, Down), (1, Less)); /// assert_eq!(0x101u16.shr_round(8i16, Up), (2, Greater)); /// /// assert_eq!((-0x101i32).shr_round(9i32, Down), (0, Greater)); /// assert_eq!((-0x101i64).shr_round(9i64, Up), (-1, Less)); /// assert_eq!((-0x101i16).shr_round(9i8, Nearest), (-1, Less)); /// assert_eq!((-0xffi32).shr_round(9i16, Nearest), (0, Greater)); /// assert_eq!((-0x100i64).shr_round(9i32, Nearest), (0, Greater)); /// /// assert_eq!(0x100u32.shr_round(8i64, Exact), (1, Equal)); /// ``` /// /// # shr_round_assign /// ``` /// use malachite_base::num::arithmetic::traits::ShrRoundAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// let mut x = 0x101u32; /// assert_eq!(x.shr_round_assign(8u8, Down), Less); /// assert_eq!(x, 1); /// /// let mut x = 0x101u16; /// assert_eq!(x.shr_round_assign(8u16, Up), Greater); /// assert_eq!(x, 2); /// /// let mut x = 0x101u64; /// assert_eq!(x.shr_round_assign(9u32, Down), Less); /// assert_eq!(x, 0); /// /// let mut x = 0x101u32; /// assert_eq!(x.shr_round_assign(9u64, Up), Greater); /// assert_eq!(x, 1); /// /// let mut x = 0x101u16; /// assert_eq!(x.shr_round_assign(9u8, Nearest), Greater); /// assert_eq!(x, 1); /// /// let mut x = 0xffu8; /// assert_eq!(x.shr_round_assign(9u16, Nearest), Less); /// assert_eq!(x, 0); /// /// let mut x = 0x100u32; /// assert_eq!(x.shr_round_assign(9u32, Nearest), Less); /// assert_eq!(x, 0); /// /// let mut x = 0x100u32; /// assert_eq!(x.shr_round_assign(8u64, Exact), Equal); /// assert_eq!(x, 1); /// /// let mut x = 0x101i32; /// assert_eq!(x.shr_round_assign(8u8, Down), Less); /// assert_eq!(x, 1); /// /// let mut x = 0x101i16; /// assert_eq!(x.shr_round_assign(8u16, Up), Greater); /// assert_eq!(x, 2); /// /// let mut x = -0x101i32; /// assert_eq!(x.shr_round_assign(9u32, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x101i64; /// assert_eq!(x.shr_round_assign(9u64, Up), Less); /// assert_eq!(x, -1); /// /// let mut x = -0x101i16; /// assert_eq!(x.shr_round_assign(9u8, Nearest), Less); /// assert_eq!(x, -1); /// /// let mut x = -0xffi32; /// assert_eq!(x.shr_round_assign(9u16, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x100i64; /// assert_eq!(x.shr_round_assign(9u32, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = 0x100u32; /// assert_eq!(x.shr_round_assign(8i64, Exact), Equal); /// assert_eq!(x, 1); /// /// let mut x = 0x101u32; /// assert_eq!(x.shr_round_assign(8i8, Down), Less); /// assert_eq!(x, 1); /// /// let mut x = 0x101u16; /// assert_eq!(x.shr_round_assign(8i16, Up), Greater); /// assert_eq!(x, 2); /// /// let mut x = -0x101i32; /// assert_eq!(x.shr_round_assign(9i32, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x101i64; /// assert_eq!(x.shr_round_assign(9i64, Up), Less); /// assert_eq!(x, -1); /// /// let mut x = -0x101i16; /// assert_eq!(x.shr_round_assign(9i8, Nearest), Less); /// assert_eq!(x, -1); /// /// let mut x = -0xffi32; /// assert_eq!(x.shr_round_assign(9i16, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = -0x100i64; /// assert_eq!(x.shr_round_assign(9i32, Nearest), Greater); /// assert_eq!(x, 0); /// /// let mut x = 0x100u32; /// assert_eq!(x.shr_round_assign(8i64, Exact), Equal); /// assert_eq!(x, 1); /// ``` pub mod shr_round; /// [`Sign`](traits::Sign), a trait for determining the sign of a number. /// /// # sign /// ``` /// use malachite_base::num::arithmetic::traits::Sign; /// use malachite_base::num::basic::traits::NegativeInfinity; /// use std::cmp::Ordering::*; /// /// assert_eq!(0u8.sign(), Equal); /// assert_eq!(100u64.sign(), Greater); /// assert_eq!((-100i16).sign(), Less); /// /// assert_eq!(0.0.sign(), Greater); /// assert_eq!(1.0.sign(), Greater); /// assert_eq!(f64::INFINITY.sign(), Greater); /// /// assert_eq!((-0.0).sign(), Less); /// assert_eq!((-1.0).sign(), Less); /// assert_eq!(f64::NEGATIVE_INFINITY.sign(), Less); /// /// assert_eq!(f64::NAN.sign(), Equal); /// ``` pub mod sign; /// Traits for taking the square root of a number. /// /// The traits are [`FloorSqrt`](traits::FloorSqrt), [`FloorSqrtAssign`](traits::FloorSqrtAssign), /// [`CeilingSqrt`](traits::CeilingSqrt), [`CeilingSqrtAssign`](traits::CeilingSqrtAssign), /// [`CheckedSqrt`](traits::CheckedSqrt), [`SqrtRem`](traits::SqrtRem), /// [`SqrtAssignRem`](traits::SqrtAssignRem), and [`SqrtAssign`](traits::SqrtAssign). /// /// # floor_sqrt /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrt; /// /// assert_eq!(99u8.floor_sqrt(), 9); /// assert_eq!(100u8.floor_sqrt(), 10); /// assert_eq!(101u8.floor_sqrt(), 10); /// assert_eq!(1000000000i32.floor_sqrt(), 31622); /// assert_eq!(10000000000i64.floor_sqrt(), 100000); /// ``` /// /// # floor_sqrt_assign /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrtAssign; /// /// let mut x = 99u8; /// x.floor_sqrt_assign(); /// assert_eq!(x, 9); /// /// let mut x = 100u8; /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = 101u8; /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = 1000000000i32; /// x.floor_sqrt_assign(); /// assert_eq!(x, 31622); /// /// let mut x = 10000000000i64; /// x.floor_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` /// /// # ceiling_sqrt /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrt; /// /// assert_eq!(99u8.ceiling_sqrt(), 10); /// assert_eq!(100u8.ceiling_sqrt(), 10); /// assert_eq!(101u8.ceiling_sqrt(), 11); /// assert_eq!(1000000000u32.ceiling_sqrt(), 31623); /// assert_eq!(10000000000u64.ceiling_sqrt(), 100000); /// ``` /// /// # ceiling_sqrt_assign /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrtAssign; /// /// let mut x = 99u8; /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = 100u8; /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = 101u8; /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 11); /// /// let mut x = 1000000000i32; /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 31623); /// /// let mut x = 10000000000i64; /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` /// /// # checked_sqrt /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// /// assert_eq!(99u8.checked_sqrt(), None); /// assert_eq!(100u8.checked_sqrt(), Some(10)); /// assert_eq!(101u8.checked_sqrt(), None); /// assert_eq!(1000000000i32.checked_sqrt(), None); /// assert_eq!(10000000000i64.checked_sqrt(), Some(100000)); /// ``` /// /// # sqrt_rem /// ``` /// use malachite_base::num::arithmetic::traits::SqrtRem; /// /// assert_eq!(99u8.sqrt_rem(), (9, 18)); /// assert_eq!(100u8.sqrt_rem(), (10, 0)); /// assert_eq!(101u8.sqrt_rem(), (10, 1)); /// assert_eq!(1000000000u32.sqrt_rem(), (31622, 49116)); /// assert_eq!(10000000000u64.sqrt_rem(), (100000, 0)); /// ``` /// /// # sqrt_assign_rem /// ``` /// use malachite_base::num::arithmetic::traits::SqrtAssignRem; /// /// let mut x = 99u8; /// assert_eq!(x.sqrt_assign_rem(), 18); /// assert_eq!(x, 9); /// /// let mut x = 100u8; /// assert_eq!(x.sqrt_assign_rem(), 0); /// assert_eq!(x, 10); /// /// let mut x = 101u8; /// assert_eq!(x.sqrt_assign_rem(), 1); /// assert_eq!(x, 10); /// /// let mut x = 1000000000u32; /// assert_eq!(x.sqrt_assign_rem(), 49116); /// assert_eq!(x, 31622); /// /// let mut x = 10000000000u64; /// assert_eq!(x.sqrt_assign_rem(), 0); /// assert_eq!(x, 100000); /// ``` /// /// # sqrt_assign /// ``` /// use malachite_base::num::arithmetic::traits::SqrtAssign; /// use malachite_base::num::float::NiceFloat; /// /// let mut x = 4.0f64; /// x.sqrt_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(2.0)); /// /// let mut x = 2.0f64; /// x.sqrt_assign(); /// assert_eq!(NiceFloat(x), NiceFloat(std::f64::consts::SQRT_2)); /// ``` pub mod sqrt; /// [`Square`](traits::Square) and [`SquareAssign`](traits::SquareAssign), traits for squaring a /// number. /// /// # square /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// /// assert_eq!(3u8.square(), 9); /// assert_eq!((-1000i32).square(), 1000000); /// assert_eq!(1.5f32.square(), 2.25); /// ``` /// /// # square_assign /// ``` /// use malachite_base::num::arithmetic::traits::SquareAssign; /// /// let mut x = 3u8; /// x.square_assign(); /// assert_eq!(x, 9); /// /// let mut x = -1000i32; /// x.square_assign(); /// assert_eq!(x, 1000000); /// /// let mut x = 1.5f32; /// x.square_assign(); /// assert_eq!(x, 2.25); /// ``` pub mod square; /// [`SubMul`](traits::SubMul) and [`SubMulAssign`](traits::SubMulAssign), traits for subtracting /// the product of two numbers from a number. /// /// # sub_mul /// ``` /// use malachite_base::num::arithmetic::traits::SubMul; /// /// assert_eq!(60u32.sub_mul(5, 10), 10); /// assert_eq!(127i8.sub_mul(2, 100), -73); /// assert_eq!(1.0f32.sub_mul(2.0, 3.0), -5.0); /// ``` /// /// # sub_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::SubMulAssign; /// /// let mut x = 60u32; /// x.sub_mul_assign(5, 10); /// assert_eq!(x, 10); /// /// let mut x = 127i8; /// x.sub_mul_assign(2, 100); /// assert_eq!(x, -73); /// /// let mut x = 1.0f32; /// x.sub_mul_assign(2.0, 3.0); /// assert_eq!(x, -5.0); /// ``` pub mod sub_mul; /// Various traits for performing arithmetic operations on numbers. pub mod traits; /// [`WrappingAbs`](traits::WrappingAbs) and [`WrappingAbsAssign`](traits::WrappingAbsAssign), /// traits for computing the absolute value of a number and wrapping at the boundary of the type. /// /// # wrapping_abs_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingAbsAssign; /// /// let mut x = 0i8; /// x.wrapping_abs_assign(); /// assert_eq!(x, 0); /// /// let mut x = 100i64; /// x.wrapping_abs_assign(); /// assert_eq!(x, 100); /// /// let mut x = -100i64; /// x.wrapping_abs_assign(); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// x.wrapping_abs_assign(); /// assert_eq!(x, -128); /// ``` pub mod wrapping_abs; /// [`WrappingAdd`](traits::WrappingAdd) and [`WrappingAddAssign`](traits::WrappingAddAssign), /// traits for adding two numbers and wrapping at the boundary of the type. /// /// # wrapping_add_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingAddAssign; /// /// let mut x = 123u16; /// x.wrapping_add_assign(456); /// assert_eq!(x, 579); /// /// let mut x = 123u8; /// x.wrapping_add_assign(200); /// assert_eq!(x, 67); /// ``` pub mod wrapping_add; /// [`WrappingAddMul`](traits::WrappingAddMul) and /// [`WrappingAddMulAssign`](traits::WrappingAddMulAssign), traits for adding the product of two /// numbers to a third and wrapping at the boundary of the type. /// /// # wrapping_add_mul /// ``` /// use malachite_base::num::arithmetic::traits::WrappingAddMul; /// /// assert_eq!(2u8.wrapping_add_mul(3, 7), 23); /// assert_eq!((-127i8).wrapping_add_mul(-2, 100), -71); /// ``` /// /// # wrapping_add_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingAddMulAssign; /// /// let mut x = 2u8; /// x.wrapping_add_mul_assign(3, 7); /// assert_eq!(x, 23); /// /// let mut x = -127i8; /// x.wrapping_add_mul_assign(-2, 100); /// assert_eq!(x, -71); /// ``` pub mod wrapping_add_mul; /// [`WrappingDiv`](traits::WrappingDiv) and [`WrappingDivAssign`](traits::WrappingDivAssign), /// traits for dividing two numbers and wrapping at the boundary of the type. /// /// # wrapping_div_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingDivAssign; /// /// let mut x = 100u16; /// x.wrapping_div_assign(3); /// assert_eq!(x, 33); /// /// let mut x = -128i8; /// x.wrapping_div_assign(-1); /// assert_eq!(x, -128); /// ``` pub mod wrapping_div; /// [`WrappingMul`](traits::WrappingMul) and [`WrappingMulAssign`](traits::WrappingMulAssign), /// traits for multiplying two numbers and wrapping at the boundary of the type. /// /// # wrapping_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingMulAssign; /// /// let mut x = 123u16; /// x.wrapping_mul_assign(456); /// assert_eq!(x, 56088); /// /// let mut x = 123u8; /// x.wrapping_mul_assign(200); /// assert_eq!(x, 24); /// ``` pub mod wrapping_mul; /// [`WrappingNeg`](traits::WrappingNeg) and [`WrappingNegAssign`](traits::WrappingNegAssign) for /// negating a number and wrapping at the boundary of the type. /// /// # wrapping_neg_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingNegAssign; /// /// let mut x = 0i8; /// x.wrapping_neg_assign(); /// assert_eq!(x, 0); /// /// let mut x = 100u64; /// x.wrapping_neg_assign(); /// assert_eq!(x, 18446744073709551516); /// /// let mut x = -100i64; /// x.wrapping_neg_assign(); /// assert_eq!(x, 100); /// /// let mut x = -128i8; /// x.wrapping_neg_assign(); /// assert_eq!(x, -128); /// ``` pub mod wrapping_neg; /// [`WrappingPow`](traits::WrappingPow) and [`WrappingPowAssign`](traits::WrappingPowAssign), /// traits for raising a number to a power and wrapping at the boundary of the type. /// /// # wrapping_pow_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingPowAssign; /// /// let mut x = 3u8; /// x.wrapping_pow_assign(3); /// assert_eq!(x, 27); /// /// let mut x = -10i32; /// x.wrapping_pow_assign(9); /// assert_eq!(x, -1000000000); /// /// let mut x = -10i16; /// x.wrapping_pow_assign(9); /// assert_eq!(x, 13824); /// ``` pub mod wrapping_pow; /// [`WrappingSquare`](traits::WrappingSquare) and /// [`WrappingSquareAssign`](traits::WrappingAbsAssign), traits for squaring a number and wrapping /// at the boundary of the type. /// /// # wrapping_square /// ``` /// use malachite_base::num::arithmetic::traits::WrappingSquare; /// /// assert_eq!(3u8.wrapping_square(), 9); /// assert_eq!((-1000i32).wrapping_square(), 1000000); /// assert_eq!(1000u16.wrapping_square(), 16960); /// ``` /// /// # wrapping_square_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingSquareAssign; /// /// let mut x = 3u8; /// x.wrapping_square_assign(); /// assert_eq!(x, 9); /// /// let mut x = -1000i32; /// x.wrapping_square_assign(); /// assert_eq!(x, 1000000); /// /// let mut x = 1000u16; /// x.wrapping_square_assign(); /// assert_eq!(x, 16960); /// ``` pub mod wrapping_square; /// [`WrappingSub`](traits::WrappingSub) and [`WrappingSubAssign`](traits::WrappingSubAssign), /// traits for subtracting two numbers and wrapping at the boundary of the type. /// /// # wrapping_sub_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingSubAssign; /// /// let mut x = 456u16; /// x.wrapping_sub_assign(123); /// assert_eq!(x, 333); /// /// let mut x = 123u16; /// x.wrapping_sub_assign(456); /// assert_eq!(x, 65203); /// ``` pub mod wrapping_sub; /// [`WrappingSubMul`](traits::WrappingSubMul) and /// [`WrappingSubMulAssign`](traits::WrappingSubMulAssign), traits for subtracting a number by the /// product of two other numbers and wrapping at the boundary of the type. /// /// # wrapping_sub_mul /// ``` /// use malachite_base::num::arithmetic::traits::WrappingSubMul; /// /// assert_eq!(127i8.wrapping_sub_mul(2, 100), -73); /// assert_eq!((-127i8).wrapping_sub_mul(2, 100), -71); /// ``` /// /// # wrapping_sub_mul_assign /// ``` /// use malachite_base::num::arithmetic::traits::WrappingAddMulAssign; /// /// let mut x = 2u8; /// x.wrapping_add_mul_assign(3, 7); /// assert_eq!(x, 23); /// /// let mut x = -127i8; /// x.wrapping_add_mul_assign(-2, 100); /// assert_eq!(x, -71); /// ``` pub mod wrapping_sub_mul; /// [`XMulYToZZ`](traits::XMulYToZZ), a trait for multiplying two numbers and returning the result /// as a double-width number. /// /// # x_mul_y_to_zz /// ``` /// use malachite_base::num::arithmetic::traits::XMulYToZZ; /// /// assert_eq!(u64::x_mul_y_to_zz(15, 3), (0, 45)); /// assert_eq!(u8::x_mul_y_to_zz(0x78, 0x9a), (0x48, 0x30)); /// ``` pub mod x_mul_y_to_zz; /// [`XXAddYYToZZ`](traits::XXAddYYToZZ), a trait for adding two double-width numbers and returning /// the result as a double-width number. /// /// # xx_add_yy_to_zz /// ``` /// use malachite_base::num::arithmetic::traits::XXAddYYToZZ; /// /// assert_eq!(u64::xx_add_yy_to_zz(0x12, 0x34, 0x33, 0x33), (0x45, 0x67)); /// assert_eq!(u8::xx_add_yy_to_zz(0x78, 0x9a, 0xbc, 0xde), (0x35, 0x78)); /// ``` pub mod xx_add_yy_to_zz; /// [`XXDivModYToQR`](traits::XXDivModYToQR), a trait for dividing a double-width number by a /// single-width number and returning the quotient and remainder. /// /// # xx_div_mod_y_to_qr /// ``` /// use malachite_base::num::arithmetic::traits::XXDivModYToQR; /// /// assert_eq!( /// u64::xx_div_mod_y_to_qr(0x12, 0x34, 0x33), /// (0x5a5a5a5a5a5a5a5b, 0x13) /// ); /// assert_eq!(u8::xx_div_mod_y_to_qr(0x78, 0x9a, 0xbc), (0xa4, 0x2a)); /// ``` pub mod xx_div_mod_y_to_qr; /// [`XXSubYYToZZ`](traits::XXSubYYToZZ), a trait for subtracting two double-width numbers and /// returning the result as a double-width number. /// /// # xx_sub_yy_to_zz /// ``` /// use malachite_base::num::arithmetic::traits::XXSubYYToZZ; /// /// assert_eq!(u64::xx_sub_yy_to_zz(0x67, 0x89, 0x33, 0x33), (0x34, 0x56)); /// assert_eq!(u8::xx_sub_yy_to_zz(0x78, 0x9a, 0xbc, 0xde), (0xbb, 0xbc)); /// ``` pub mod xx_sub_yy_to_zz; /// [`XXXAddYYYToZZZ`](traits::XXXAddYYYToZZZ), a trait for adding two triple-width numbers and /// returning the result as a triple-width number. /// /// # xxx_add_yyy_to_zzz /// ``` /// use malachite_base::num::arithmetic::traits::XXXAddYYYToZZZ; /// /// assert_eq!( /// u64::xxx_add_yyy_to_zzz(0x12, 0x34, 0x56, 0x33, 0x33, 0x33), /// (0x45, 0x67, 0x89) /// ); /// assert_eq!( /// u8::xxx_add_yyy_to_zzz(0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc), /// (0x57, 0x99, 0x98) /// ); /// ``` pub mod xxx_add_yyy_to_zzz; /// [`XXXSubYYYToZZZ`](traits::XXXSubYYYToZZZ), a trait for subtracting two triple-width numbers and /// returning the result as a triple-width number. /// /// # xxx_sub_yyy_to_zzz /// ``` /// use malachite_base::num::arithmetic::traits::XXXSubYYYToZZZ; /// /// assert_eq!( /// u64::xxx_sub_yyy_to_zzz(0x67, 0x89, 0xab, 0x33, 0x33, 0x33), /// (0x34, 0x56, 0x78) /// ); /// assert_eq!( /// u8::xxx_sub_yyy_to_zzz(0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc), /// (0x99, 0x9b, 0xe0) /// ); /// ``` pub mod xxx_sub_yyy_to_zzz; /// [`XXXXAddYYYYToZZZZ`](traits::XXXXAddYYYYToZZZZ), a trait for adding two quadruple-width numbers /// and returning the result as a quadruple-width number. /// /// # xxxx_add_yyyy_to_zzzz /// ``` /// use malachite_base::num::arithmetic::traits::XXXXAddYYYYToZZZZ; /// /// assert_eq!( /// u64::xxxx_add_yyyy_to_zzzz(0x12, 0x34, 0x56, 0x78, 0x33, 0x33, 0x33, 0x33), /// (0x45, 0x67, 0x89, 0xab) /// ); /// assert_eq!( /// u8::xxxx_add_yyyy_to_zzzz(0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc, 0xba, 0x98), /// (0x77, 0x77, 0x77, 0x76) /// ); /// ``` pub mod xxxx_add_yyyy_to_zzzz; ================================================ FILE: malachite-base/src/num/arithmetic/mod_add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2010 William Hart // // Copyright © 2021 Fredrik Johansson // // 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 crate::num::arithmetic::traits::{ModAdd, ModAddAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_add(x: T, y: T, m: T) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); assert!(y < m, "y must be reduced mod m, but {y} >= {m}"); let neg = m - x; if neg > y { x + y } else { y - neg } } fn mod_add_assign(x: &mut T, y: T, m: T) { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); assert!(y < m, "y must be reduced mod m, but {y} >= {m}"); let neg = m - *x; if neg > y { *x += y; } else { *x = y - neg; } } macro_rules! impl_mod_add { ($t:ident) => { impl ModAdd<$t> for $t { type Output = $t; /// Adds two numbers modulo a third number $m$. The inputs must be already reduced /// modulo $m$. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_add#mod_add). /// /// This is equivalent to `nmod_add` from `nmod.h`, FLINT 2.7.1. #[inline] fn mod_add(self, other: $t, m: $t) -> $t { mod_add(self, other, m) } } impl ModAddAssign<$t> for $t { /// Adds two numbers modulo a third number $m$, in place. The inputs must be already /// reduced modulo $m$. /// /// $x \gets z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_add#mod_add_assign). /// /// This is equivalent to `nmod_add` from `nmod.h`, FLINT 2.7.1, where the result is /// assigned to `a`. #[inline] fn mod_add_assign(&mut self, other: $t, m: $t) { mod_add_assign(self, other, m); } } }; } apply_to_unsigneds!(impl_mod_add); ================================================ FILE: malachite-base/src/num/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2009, 2016 William Hart // // 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 crate::num::arithmetic::traits::ModInverse; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::rounding_modes::RoundingMode::*; // This is a variation of `n_xgcd` from `ulong_extras/xgcd.c`, FLINT 2.7.1. pub_test! {mod_inverse_binary< U: WrappingFrom + PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, >( x: U, m: U, ) -> Option { assert_ne!(x, U::ZERO); assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); let mut u1 = S::ONE; let mut v2 = S::ONE; let mut u2 = S::ZERO; let mut v1 = S::ZERO; let mut u3 = m; let mut v3 = x; let mut d; let mut t2; let mut t1; if (m & x).get_highest_bit() { d = u3 - v3; t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } while v3.get_bit(U::WIDTH - 2) { d = u3 - v3; if d < v3 { // quot = 1 t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if d < (v3 << 1) { // quot = 2 t1 = u2; u2 = u1 - (u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1 - (v2 << 1); v1 = t2; v3 = d - u3; } else { // quot = 3 t1 = u2; u2 = u1 - S::wrapping_from(3) * u2; u1 = t1; u3 = v3; t2 = v2; v2 = v1 - S::wrapping_from(3) * v2; v1 = t2; v3 = d - (u3 << 1); } } while v3 != U::ZERO { d = u3 - v3; // overflow not possible, top 2 bits of v3 not set if u3 < (v3 << 2) { if d < v3 { // quot = 1 t2 = v2; t1 = u2; u2 = u1 - u2; u1 = t1; u3 = v3; v2 = v1 - v2; v1 = t2; v3 = d; } else if d < (v3 << 1) { // quot = 2 t1 = u2; u2 = u1.wrapping_sub(u2 << 1); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(v2 << 1); v1 = t2; v3 = d - u3; } else { // quot = 3 t1 = u2; u2 = u1.wrapping_sub(S::wrapping_from(3).wrapping_mul(u2)); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(S::wrapping_from(3).wrapping_mul(v2)); v1 = t2; v3 = d.wrapping_sub(u3 << 1); } } else { let (quot, rem) = u3.div_rem(v3); t1 = u2; u2 = u1.wrapping_sub(S::wrapping_from(quot).wrapping_mul(u2)); u1 = t1; u3 = v3; t2 = v2; v2 = v1.wrapping_sub(S::wrapping_from(quot).wrapping_mul(v2)); v1 = t2; v3 = rem; } } if u3 != U::ONE { return None; } let mut inverse = U::wrapping_from(v1); if u1 <= S::ZERO { inverse.wrapping_sub_assign(m); } let limit = (m >> 1u32).wrapping_neg(); if inverse < limit { let k = (limit - inverse).div_round(m, Ceiling).0; inverse.wrapping_add_assign(m.wrapping_mul(k)); } Some(if inverse.get_highest_bit() { inverse.wrapping_add(m) } else { inverse }) }} macro_rules! impl_mod_inverse { ($u:ident, $s:ident) => { impl ModInverse<$u> for $u { type Output = $u; /// Computes the multiplicative inverse of a number modulo another number $m$. The input /// must be already reduced modulo $m$. /// /// Returns `None` if $x$ and $m$ are not coprime. /// /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), m.significant_bits())`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_inverse#mod_inverse). #[inline] fn mod_inverse(self, m: $u) -> Option<$u> { mod_inverse_binary::<$u, $s>(self, m) } } }; } apply_to_unsigned_signed_pairs!(impl_mod_inverse); ================================================ FILE: malachite-base/src/num/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::ModIsReduced; macro_rules! impl_mod_is_reduced { ($t:ident) => { impl ModIsReduced for $t { /// Returns whether a number is reduced modulo another number $m$; in other words, /// whether it is less than $m$. $m$ cannot be zero. /// /// $f(x, m) = (x < m)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $m$ is 0. /// /// # Examples /// See [here](super::mod_is_reduced#mod_is_reduced). #[inline] fn mod_is_reduced(&self, m: &$t) -> bool { assert_ne!(*m, 0); self < m } } }; } apply_to_unsigneds!(impl_mod_is_reduced); ================================================ FILE: malachite-base/src/num/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // Copyright © 2006, 2007, 2008, 2009, 2010, 2015, 2016 William Hart // // Copyright © 2010, 2011, 2021 Fredrik Johansson // // Copyright © 2008, Peter Shrimpton // // Copyright © 2009, Tom Boothby // // 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 crate::num::arithmetic::traits::{ ModMul, ModMulAssign, ModMulPrecomputed, ModMulPrecomputedAssign, Parity, PowerOf2, WrappingSubAssign, }; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, HasHalf, JoinHalves, SplitInHalf, WrappingFrom}; use crate::num::logic::traits::LeadingZeros; pub_test! {naive_mod_mul(x: T, y: T, m: T) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); assert!(y < m, "y must be reduced mod m, but {y} >= {m}"); let (product_1, product_0) = T::x_mul_y_to_zz(x, y); T::xx_div_mod_y_to_qr(product_1, product_0, m).1 }} const INVERT_U32_TABLE_LOG_SIZE: u64 = 9; const INVERT_U32_TABLE_SIZE: usize = 1 << INVERT_U32_TABLE_LOG_SIZE; // INVERT_U32_TABLE[i] = floor((2^24 - 2^14 + 2^9) / (2^9 + i)) const INVERT_U32_TABLE: [u32; INVERT_U32_TABLE_SIZE] = [ 32737, 32673, 32609, 32546, 32483, 32420, 32357, 32295, 32233, 32171, 32109, 32048, 31987, 31926, 31865, 31805, 31744, 31684, 31625, 31565, 31506, 31447, 31388, 31329, 31271, 31212, 31154, 31097, 31039, 30982, 30924, 30868, 30811, 30754, 30698, 30642, 30586, 30530, 30475, 30419, 30364, 30309, 30255, 30200, 30146, 30092, 30038, 29984, 29930, 29877, 29824, 29771, 29718, 29666, 29613, 29561, 29509, 29457, 29405, 29354, 29303, 29251, 29200, 29150, 29099, 29049, 28998, 28948, 28898, 28849, 28799, 28750, 28700, 28651, 28602, 28554, 28505, 28457, 28409, 28360, 28313, 28265, 28217, 28170, 28123, 28075, 28029, 27982, 27935, 27889, 27842, 27796, 27750, 27704, 27658, 27613, 27568, 27522, 27477, 27432, 27387, 27343, 27298, 27254, 27209, 27165, 27121, 27078, 27034, 26990, 26947, 26904, 26861, 26818, 26775, 26732, 26690, 26647, 26605, 26563, 26521, 26479, 26437, 26395, 26354, 26312, 26271, 26230, 26189, 26148, 26108, 26067, 26026, 25986, 25946, 25906, 25866, 25826, 25786, 25747, 25707, 25668, 25628, 25589, 25550, 25511, 25473, 25434, 25395, 25357, 25319, 25281, 25242, 25205, 25167, 25129, 25091, 25054, 25016, 24979, 24942, 24905, 24868, 24831, 24794, 24758, 24721, 24685, 24649, 24612, 24576, 24540, 24504, 24469, 24433, 24397, 24362, 24327, 24291, 24256, 24221, 24186, 24151, 24117, 24082, 24047, 24013, 23979, 23944, 23910, 23876, 23842, 23808, 23774, 23741, 23707, 23674, 23640, 23607, 23574, 23541, 23508, 23475, 23442, 23409, 23377, 23344, 23312, 23279, 23247, 23215, 23183, 23151, 23119, 23087, 23055, 23023, 22992, 22960, 22929, 22898, 22866, 22835, 22804, 22773, 22742, 22711, 22681, 22650, 22619, 22589, 22559, 22528, 22498, 22468, 22438, 22408, 22378, 22348, 22318, 22289, 22259, 22229, 22200, 22171, 22141, 22112, 22083, 22054, 22025, 21996, 21967, 21938, 21910, 21881, 21853, 21824, 21796, 21767, 21739, 21711, 21683, 21655, 21627, 21599, 21571, 21544, 21516, 21488, 21461, 21433, 21406, 21379, 21352, 21324, 21297, 21270, 21243, 21216, 21190, 21163, 21136, 21110, 21083, 21056, 21030, 21004, 20977, 20951, 20925, 20899, 20873, 20847, 20821, 20795, 20769, 20744, 20718, 20693, 20667, 20642, 20616, 20591, 20566, 20540, 20515, 20490, 20465, 20440, 20415, 20390, 20366, 20341, 20316, 20292, 20267, 20243, 20218, 20194, 20170, 20145, 20121, 20097, 20073, 20049, 20025, 20001, 19977, 19953, 19930, 19906, 19882, 19859, 19835, 19812, 19789, 19765, 19742, 19719, 19696, 19672, 19649, 19626, 19603, 19581, 19558, 19535, 19512, 19489, 19467, 19444, 19422, 19399, 19377, 19354, 19332, 19310, 19288, 19265, 19243, 19221, 19199, 19177, 19155, 19133, 19112, 19090, 19068, 19046, 19025, 19003, 18982, 18960, 18939, 18917, 18896, 18875, 18854, 18832, 18811, 18790, 18769, 18748, 18727, 18706, 18686, 18665, 18644, 18623, 18603, 18582, 18561, 18541, 18520, 18500, 18479, 18459, 18439, 18419, 18398, 18378, 18358, 18338, 18318, 18298, 18278, 18258, 18238, 18218, 18199, 18179, 18159, 18139, 18120, 18100, 18081, 18061, 18042, 18022, 18003, 17984, 17964, 17945, 17926, 17907, 17888, 17869, 17850, 17831, 17812, 17793, 17774, 17755, 17736, 17718, 17699, 17680, 17662, 17643, 17624, 17606, 17587, 17569, 17551, 17532, 17514, 17496, 17477, 17459, 17441, 17423, 17405, 17387, 17369, 17351, 17333, 17315, 17297, 17279, 17261, 17244, 17226, 17208, 17191, 17173, 17155, 17138, 17120, 17103, 17085, 17068, 17051, 17033, 17016, 16999, 16982, 16964, 16947, 16930, 16913, 16896, 16879, 16862, 16845, 16828, 16811, 16794, 16778, 16761, 16744, 16727, 16711, 16694, 16677, 16661, 16644, 16628, 16611, 16595, 16578, 16562, 16546, 16529, 16513, 16497, 16481, 16464, 16448, 16432, 16416, 16400, 16384, ]; #[cfg(feature = "test_build")] pub fn test_invert_u32_table() { for (i, &x) in INVERT_U32_TABLE.iter().enumerate() { let value = (u32::power_of_2(24) - u32::power_of_2(14) + u32::power_of_2(9)) / (u32::power_of_2(9) + u32::exact_from(i)); assert_eq!( x, value, "INVERT_U32_TABLE gives incorrect value, {x}, for index {i}" ); } } // Computes // $$ // f(x) = \left \lfloor \frac{2^{64} - 2^{32}x - 1}{x} \right \rfloor = // \left \lfloor \frac{2^{64}-1}{x}-2^{32} \right \rfloor. // $$ // // The highest bit of `x` must be set. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `invert_limb` from `longlong.h`, FLINT 2.7.1, when `GMP_LIMB_BITS == 32`. pub_crate_test! {limbs_invert_limb_u32(x: u32) -> u32 { assert!(x.get_highest_bit()); let a = INVERT_U32_TABLE[usize::exact_from(x << 1 >> 23)]; let b = (a << 4) .wrapping_sub((u64::from(a * a) * u64::from((x >> 11) + 1)).upper_half()) .wrapping_sub(1); let mut c = b.wrapping_mul(x >> 1).wrapping_neg(); if x.odd() { c.wrapping_sub_assign(b.wrapping_sub(b >> 1)); } let d = (b << 15).wrapping_add((u64::from(b) * u64::from(c)).upper_half() >> 1); d.wrapping_sub( (u64::from(d) * u64::from(x)) .wrapping_add(u64::from(x)) .upper_half() .wrapping_add(x), ) }} const INVERT_U64_TABLE_LOG_SIZE: u64 = 8; const INVERT_U64_TABLE_SIZE: usize = 1 << INVERT_U64_TABLE_LOG_SIZE; // INVERT_U32_TABLE[i] = floor((2^19 - 3*2^8) / (2^8 + i)) const INVERT_U64_TABLE: [u64; INVERT_U64_TABLE_SIZE] = [ 2045, 2037, 2029, 2021, 2013, 2005, 1998, 1990, 1983, 1975, 1968, 1960, 1953, 1946, 1938, 1931, 1924, 1917, 1910, 1903, 1896, 1889, 1883, 1876, 1869, 1863, 1856, 1849, 1843, 1836, 1830, 1824, 1817, 1811, 1805, 1799, 1792, 1786, 1780, 1774, 1768, 1762, 1756, 1750, 1745, 1739, 1733, 1727, 1722, 1716, 1710, 1705, 1699, 1694, 1688, 1683, 1677, 1672, 1667, 1661, 1656, 1651, 1646, 1641, 1636, 1630, 1625, 1620, 1615, 1610, 1605, 1600, 1596, 1591, 1586, 1581, 1576, 1572, 1567, 1562, 1558, 1553, 1548, 1544, 1539, 1535, 1530, 1526, 1521, 1517, 1513, 1508, 1504, 1500, 1495, 1491, 1487, 1483, 1478, 1474, 1470, 1466, 1462, 1458, 1454, 1450, 1446, 1442, 1438, 1434, 1430, 1426, 1422, 1418, 1414, 1411, 1407, 1403, 1399, 1396, 1392, 1388, 1384, 1381, 1377, 1374, 1370, 1366, 1363, 1359, 1356, 1352, 1349, 1345, 1342, 1338, 1335, 1332, 1328, 1325, 1322, 1318, 1315, 1312, 1308, 1305, 1302, 1299, 1295, 1292, 1289, 1286, 1283, 1280, 1276, 1273, 1270, 1267, 1264, 1261, 1258, 1255, 1252, 1249, 1246, 1243, 1240, 1237, 1234, 1231, 1228, 1226, 1223, 1220, 1217, 1214, 1211, 1209, 1206, 1203, 1200, 1197, 1195, 1192, 1189, 1187, 1184, 1181, 1179, 1176, 1173, 1171, 1168, 1165, 1163, 1160, 1158, 1155, 1153, 1150, 1148, 1145, 1143, 1140, 1138, 1135, 1133, 1130, 1128, 1125, 1123, 1121, 1118, 1116, 1113, 1111, 1109, 1106, 1104, 1102, 1099, 1097, 1095, 1092, 1090, 1088, 1086, 1083, 1081, 1079, 1077, 1074, 1072, 1070, 1068, 1066, 1064, 1061, 1059, 1057, 1055, 1053, 1051, 1049, 1047, 1044, 1042, 1040, 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024, ]; /// Tests that `INVERT_U64_TABLE` is correct. #[cfg(feature = "test_build")] pub fn test_invert_u64_table() { for (i, &x) in INVERT_U64_TABLE.iter().enumerate() { let value = (u64::power_of_2(19) - 3 * u64::power_of_2(8)) / (u64::power_of_2(8) + u64::exact_from(i)); assert_eq!( x, value, "INVERT_U64_TABLE gives incorrect value, {x}, for index {i}" ); } } // Computes // $$ // f(x) = \left \lfloor \frac{2^{128} - 2^{64}x - 1}{x} \right \rfloor = // \left \lfloor \frac{2^{128}-1}{x}-2^{64} \right \rfloor. // $$ // // The highest bit of `x` must be set. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `invert_limb` from `longlong.h`, FLINT 2.7.1, when `GMP_LIMB_BITS == 64`. pub_crate_test! {limbs_invert_limb_u64(x: u64) -> u64 { assert!(x.get_highest_bit()); let a = (x >> 24) + 1; let b = INVERT_U64_TABLE[usize::exact_from(x << 1 >> 56)]; let c = (b << 11).wrapping_sub(((b * b).wrapping_mul(a) >> 40) + 1); let d = (c.wrapping_mul(u64::power_of_2(60).wrapping_sub(c.wrapping_mul(a))) >> 47) .wrapping_add(c << 13); let mut e = d.wrapping_mul(x >> 1).wrapping_neg(); if x.odd() { e.wrapping_sub_assign(d.wrapping_sub(d >> 1)); } let f = (d << 31).wrapping_add((u128::from(d) * u128::from(e)).upper_half() >> 1); f.wrapping_sub( (u128::from(f) * u128::from(x)) .wrapping_add(u128::from(x)) .upper_half() .wrapping_add(x), ) }} // This is equivalent to `n_ll_mod_preinv` from `ulong_extras/ll_mod_preinv.c`, FLINT 2.7.1. pub_test! {mod_preinverted_double< T: PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( mut x_1: T, x_0: T, d: T, d_inv: T, ) -> T { assert_ne!(d, T::ZERO); let d_inv = DT::from(d_inv); let shift = LeadingZeros::leading_zeros(d); if shift == 0 { if x_1 >= d { x_1 -= d; } let (q_1, q_0) = (d_inv * DT::from(x_1)) .wrapping_add(DT::join_halves(x_1, x_0)) .split_in_half(); let mut r = x_0.wrapping_sub(q_1.wrapping_add(T::ONE).wrapping_mul(d)); if r > q_0 { r.wrapping_add_assign(d); } if r < d { r } else { r - d } } else { let mut d = d; if x_1 >= d { let y_1 = x_1 >> (T::WIDTH - shift); let y_0 = x_1 << shift; d <<= shift; let (q1, q0) = (d_inv * DT::from(y_1)) .wrapping_add(DT::join_halves(y_1, y_0)) .split_in_half(); x_1 = y_0.wrapping_sub(q1.wrapping_add(T::ONE).wrapping_mul(d)); if x_1 > q0 { x_1.wrapping_add_assign(d); } if x_1 >= d { x_1 -= d; } } else { d <<= shift; x_1 <<= shift; } let y_1 = x_1.wrapping_add(x_0 >> (T::WIDTH - shift)); let y_0 = x_0 << shift; let (q_1, q_0) = (d_inv * DT::from(y_1)) .wrapping_add(DT::join_halves(y_1, y_0)) .split_in_half(); let mut r = y_0.wrapping_sub(q_1.wrapping_add(T::ONE).wrapping_mul(d)); if r > q_0 { r.wrapping_add_assign(d); } if r < d { r >> shift } else { (r - d) >> shift } } }} // This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1. pub_test! {fast_mod_mul< T: PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( x: T, y: T, m: T, inv: T, ) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); assert!(y < m, "y must be reduced mod m, but {y} >= {m}"); let (product_1, product_0) = (DT::from(x) * DT::from(y)).split_in_half(); mod_preinverted_double::(product_1, product_0, m, inv) }} macro_rules! impl_mod_mul_precomputed_fast { ($t:ident, $dt:ident, $invert_limb:ident) => { impl ModMulPrecomputed<$t, $t> for $t { type Output = $t; type Data = $t; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](super::traits::ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1. fn precompute_mod_mul_data(&m: &$t) -> $t { $invert_limb(m << LeadingZeros::leading_zeros(m)) } /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced /// modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular multiplications with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul_precomputed). /// /// This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1. fn mod_mul_precomputed(self, other: $t, m: $t, data: &$t) -> $t { fast_mod_mul::<$t, $dt>(self, other, m, *data) } } }; } impl_mod_mul_precomputed_fast!(u32, u64, limbs_invert_limb_u32); impl_mod_mul_precomputed_fast!(u64, u128, limbs_invert_limb_u64); macro_rules! impl_mod_mul_precomputed_promoted { ($t:ident) => { impl ModMulPrecomputed<$t, $t> for $t { type Output = $t; type Data = u32; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](super::traits::ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1. fn precompute_mod_mul_data(&m: &$t) -> u32 { u32::precompute_mod_mul_data(&u32::from(m)) } /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced /// modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular multiplications with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul_precomputed). /// /// This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1. fn mod_mul_precomputed(self, other: $t, m: $t, data: &u32) -> $t { $t::wrapping_from(u32::from(self).mod_mul_precomputed( u32::from(other), u32::from(m), data, )) } } }; } impl_mod_mul_precomputed_promoted!(u8); impl_mod_mul_precomputed_promoted!(u16); impl ModMulPrecomputed for u128 { type Output = Self; type Data = (); /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](super::traits::ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. fn precompute_mod_mul_data(_m: &Self) {} /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced modulo /// $m$. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul_precomputed). /// /// This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1. #[inline] fn mod_mul_precomputed(self, other: Self, m: Self, _data: &()) -> Self { naive_mod_mul(self, other, m) } } impl ModMulPrecomputed for usize { type Output = Self; type Data = Self; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](super::traits::ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1. fn precompute_mod_mul_data(&m: &Self) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::precompute_mod_mul_data(&u32::wrapping_from(m))) } else { Self::wrapping_from(u64::precompute_mod_mul_data(&u64::wrapping_from(m))) } } /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced modulo /// $m$. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// `precompute_mod_mul_data`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul_precomputed). /// /// This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1. fn mod_mul_precomputed(self, other: Self, m: Self, data: &Self) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).mod_mul_precomputed( u32::wrapping_from(other), u32::wrapping_from(m), &u32::wrapping_from(*data), )) } else { Self::wrapping_from(u64::wrapping_from(self).mod_mul_precomputed( u64::wrapping_from(other), u64::wrapping_from(m), &u64::wrapping_from(*data), )) } } } macro_rules! impl_mod_mul { ($t:ident) => { impl ModMulPrecomputedAssign<$t, $t> for $t { /// Multiplies two numbers modulo a third number $m$, in place. The inputs must be /// already reduced modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular multiplications with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul_precomputed_assign). /// /// This is equivalent to `n_mulmod2_preinv` from `ulong_extras.h`, FLINT 2.7.1, where /// the return value is assigned to `a`. #[inline] fn mod_mul_precomputed_assign(&mut self, other: $t, m: $t, data: &Self::Data) { *self = self.mod_mul_precomputed(other, m, data); } } impl ModMul<$t> for $t { type Output = $t; /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced /// modulo $m$. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_mul#mod_mul). /// /// This is equivalent to `nmod_mul` from `nmod.h`, FLINT 2.7.1. #[inline] fn mod_mul(self, other: $t, m: $t) -> $t { naive_mod_mul(self, other, m) } } impl ModMulAssign<$t> for $t { /// Multiplies two numbers modulo a third number $m$, in place. The inputs must be /// already reduced modulo $m$. /// /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_mul#mod_mul_assign). /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// This is equivalent to `nmod_mul` from `nmod.h`, FLINT 2.7.1, where the result is /// assigned to `a`. #[inline] fn mod_mul_assign(&mut self, other: $t, m: $t) { *self = naive_mod_mul(*self, other, m); } } }; } apply_to_unsigneds!(impl_mod_mul); ================================================ FILE: malachite-base/src/num/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2010 William Hart // // Copyright © 2021 Fredrik Johansson // // 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 crate::num::arithmetic::traits::{ModNeg, ModNegAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_neg(x: T, m: T) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); if x == T::ZERO { T::ZERO } else { m - x } } fn mod_neg_assign(x: &mut T, m: T) { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); if *x != T::ZERO { *x = m - *x; } } macro_rules! impl_mod_neg { ($t:ident) => { impl ModNeg for $t { type Output = $t; /// Negates a number modulo another number $m$, in place. The input must be already /// reduced modulo $m$. /// /// $f(x, m) = y$, where $x, y < m$ and $-x \equiv y \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_neg#mod_neg). /// /// This is equivalent to `nmod_neg` from `nmod.h`, FLINT 2.7.1. #[inline] fn mod_neg(self, m: $t) -> $t { mod_neg(self, m) } } impl ModNegAssign for $t { /// Negates a number modulo another number $m$. The input must be already reduced modulo /// $m$. /// /// $x \gets y$, where $x, y < m$ and $-x \equiv y \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_neg#mod_neg_assign). /// /// This is equivalent to `nmod_neg` from `nmod.h`, FLINT 2.7.1, where the output is /// assigned to `a`. #[inline] fn mod_neg_assign(&mut self, m: $t) { mod_neg_assign(self, m) } } }; } apply_to_unsigneds!(impl_mod_neg); ================================================ FILE: malachite-base/src/num/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ CeilingMod, CeilingModAssign, Mod, ModAssign, NegMod, NegModAssign, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactFrom; fn neg_mod_unsigned(x: T, other: T) -> T { let remainder = x % other; if remainder == T::ZERO { T::ZERO } else { other - remainder } } fn neg_mod_assign_unsigned(x: &mut T, other: T) { *x %= other; if *x != T::ZERO { *x = other - *x; } } macro_rules! impl_mod_unsigned { ($t:ident) => { impl Mod<$t> for $t { type Output = $t; /// Divides a number by another number, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#mod_op). #[inline] fn mod_op(self, other: $t) -> $t { self % other } } impl ModAssign<$t> for $t { /// Divides a number by another number, replacing the first number by the remainder. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq r < y$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#mod_assign). #[inline] fn mod_assign(&mut self, other: $t) { *self %= other; } } impl NegMod<$t> for $t { type Output = $t; /// Divides the negative of a number by another number, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ /// and $0 \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#neg_mod). #[inline] fn neg_mod(self, other: $t) -> $t { neg_mod_unsigned(self, other) } } impl NegModAssign<$t> for $t { /// Divides the negative of a number by another number, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ /// and $0 \leq r < y$. /// /// $$ /// x \gets y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#neg_mod_assign). #[inline] fn neg_mod_assign(&mut self, other: $t) { neg_mod_assign_unsigned(self, other); } } }; } apply_to_unsigneds!(impl_mod_unsigned); fn mod_op_signed< U: PrimitiveUnsigned, S: ExactFrom + PrimitiveSigned + UnsignedAbs, >( x: S, other: S, ) -> S { let remainder = if (x >= S::ZERO) == (other >= S::ZERO) { x.unsigned_abs() % other.unsigned_abs() } else { x.unsigned_abs().neg_mod(other.unsigned_abs()) }; if other >= S::ZERO { S::exact_from(remainder) } else { -S::exact_from(remainder) } } fn ceiling_mod_signed< U: PrimitiveUnsigned, S: ExactFrom + PrimitiveSigned + UnsignedAbs, >( x: S, other: S, ) -> S { let remainder = if (x >= S::ZERO) == (other >= S::ZERO) { x.unsigned_abs().neg_mod(other.unsigned_abs()) } else { x.unsigned_abs() % other.unsigned_abs() }; if other >= S::ZERO { -S::exact_from(remainder) } else { S::exact_from(remainder) } } macro_rules! impl_mod_signed { ($t:ident) => { impl Mod<$t> for $t { type Output = $t; /// Divides a number by another number, returning just the remainder. The remainder has /// the same sign as the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#mod_op). #[inline] fn mod_op(self, other: $t) -> $t { mod_op_signed(self, other) } } impl ModAssign<$t> for $t { /// Divides a number by another number, replacing the first number by the remainder. The /// remainder has the same sign as the second number. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#mod_assign). #[inline] fn mod_assign(&mut self, other: $t) { *self = self.mod_op(other); } } impl CeilingMod<$t> for $t { type Output = $t; /// Divides a number by another number, returning just the remainder. The remainder has /// the opposite sign as the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#ceiling_mod). #[inline] fn ceiling_mod(self, other: $t) -> $t { ceiling_mod_signed(self, other) } } impl CeilingModAssign<$t> for $t { /// Divides a number by another number, replacing the first number by the remainder. The /// remainder has the opposite sign as the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ /// and $0 \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `other` is 0. /// /// # Examples /// See [here](super::mod_op#ceiling_mod_assign). #[inline] fn ceiling_mod_assign(&mut self, other: $t) { *self = self.ceiling_mod(other); } } }; } apply_to_signeds!(impl_mod_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2009, 2010, 2012, 2016 William Hart // // 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 crate::num::arithmetic::mod_mul::{limbs_invert_limb_u32, limbs_invert_limb_u64}; use crate::num::arithmetic::traits::{ ModPow, ModPowAssign, ModPowPrecomputed, ModPowPrecomputedAssign, }; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use crate::num::logic::traits::{BitIterable, LeadingZeros}; pub_test! {simple_binary_mod_pow(x: T, exp: u64, m: T) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); if m == T::ONE { return T::ZERO; } let data = T::precompute_mod_mul_data(&m); let mut out = T::ONE; for bit in exp.bits().rev() { out.mod_mul_precomputed_assign(out, m, &data); if bit { out.mod_mul_precomputed_assign(x, m, &data); } } out }} // m.get_highest_bit(), x < m, y < m // // This is equivalent to `n_mulmod_preinv` from `ulong_extras/mulmod_preinv.c`, FLINT 2.7.1. pub(crate) fn mul_mod_helper< T: PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( mut x: T, y: T, m: T, inverse: T, shift: u64, ) -> T { x >>= shift; let p = DT::from(x) * DT::from(y); let (p_hi, p_lo) = p.split_in_half(); let (q_1, q_0) = (DT::from(p_hi) * DT::from(inverse)) .wrapping_add(p) .split_in_half(); let mut r = p_lo.wrapping_sub(q_1.wrapping_add(T::ONE).wrapping_mul(m)); if r > q_0 { r.wrapping_add_assign(m); } if r < m { r } else { r.wrapping_sub(m) } } // m.get_highest_bit(), x < m // // This is equivalent to `n_powmod_ui_preinv` from ulong_extras/powmod_ui_preinv.c, FLINT 2.7.1. pub(crate) fn fast_mod_pow< T: PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( mut x: T, exp: u64, m: T, inverse: T, shift: u64, ) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); if exp == 0 { let x = T::power_of_2(shift); if x == m { T::ZERO } else { x } } else if x == T::ZERO { T::ZERO } else { let mut bits = exp.bits(); let mut out = if bits.next().unwrap() { x } else { T::power_of_2(shift) }; for bit in bits { x = mul_mod_helper::(x, x, m, inverse, shift); if bit { out = mul_mod_helper::(out, x, m, inverse, shift); } } out } } macro_rules! impl_mod_pow_precomputed_fast { ($t:ident, $dt:ident, $invert_limb:ident) => { impl ModPowPrecomputed for $t { type Output = $t; type Data = ($t, u64); /// Precomputes data for modular exponentiation. /// /// See `mod_pow_precomputed` and /// [`mod_pow_precomputed_assign`](super::traits::ModPowPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. fn precompute_mod_pow_data(&m: &$t) -> ($t, u64) { let leading_zeros = LeadingZeros::leading_zeros(m); ($invert_limb(m << leading_zeros), leading_zeros) } /// Raises a number to a power modulo another number $m$. The base must be already /// reduced modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular exponentiations with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_precomputed). fn mod_pow_precomputed(self, exp: u64, m: $t, data: &($t, u64)) -> $t { let (inverse, shift) = *data; fast_mod_pow::<$t, $dt>(self << shift, exp, m << shift, inverse, shift) >> shift } } }; } impl_mod_pow_precomputed_fast!(u32, u64, limbs_invert_limb_u32); impl_mod_pow_precomputed_fast!(u64, u128, limbs_invert_limb_u64); macro_rules! impl_mod_pow_precomputed_promoted { ($t:ident) => { impl ModPowPrecomputed for $t { type Output = $t; type Data = (u32, u64); /// Precomputes data for modular exponentiation. /// /// See `mod_pow_precomputed` and /// [`mod_pow_precomputed_assign`](super::traits::ModPowPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. fn precompute_mod_pow_data(&m: &$t) -> (u32, u64) { u32::precompute_mod_pow_data(&u32::from(m)) } /// Raises a number to a power modulo another number $m$. The base must be already /// reduced modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular exponentiations with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_precomputed). fn mod_pow_precomputed(self, exp: u64, m: $t, data: &(u32, u64)) -> $t { $t::wrapping_from(u32::from(self).mod_pow_precomputed(exp, u32::from(m), data)) } } }; } impl_mod_pow_precomputed_promoted!(u8); impl_mod_pow_precomputed_promoted!(u16); impl ModPowPrecomputed for u128 { type Output = Self; type Data = (); /// Precomputes data for modular exponentiation. /// /// See `mod_pow_precomputed` and /// [`mod_pow_precomputed_assign`](super::traits::ModPowPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. fn precompute_mod_pow_data(_m: &Self) {} /// Raises a number to a power modulo another number $m$. The base must be already reduced /// modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// exponentiations with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_precomputed). #[inline] fn mod_pow_precomputed(self, exp: u64, m: Self, _data: &()) -> Self { simple_binary_mod_pow(self, exp, m) } } impl ModPowPrecomputed for usize { type Output = Self; type Data = (Self, u64); /// Precomputes data for modular exponentiation. /// /// See `mod_pow_precomputed` and /// [`mod_pow_precomputed_assign`](super::traits::ModPowPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. fn precompute_mod_pow_data(&m: &Self) -> (Self, u64) { if USIZE_IS_U32 { let (inverse, shift) = u32::precompute_mod_pow_data(&u32::wrapping_from(m)); (Self::wrapping_from(inverse), shift) } else { let (inverse, shift) = u64::precompute_mod_pow_data(&u64::wrapping_from(m)); (Self::wrapping_from(inverse), shift) } } /// Raises a number to a power modulo another number $m$. The base must be already reduced /// modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// exponentiations with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_precomputed). fn mod_pow_precomputed(self, exp: u64, m: Self, data: &(Self, u64)) -> Self { let (inverse, shift) = *data; if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).mod_pow_precomputed( exp, u32::wrapping_from(m), &(u32::wrapping_from(inverse), shift), )) } else { Self::wrapping_from(u64::wrapping_from(self).mod_pow_precomputed( exp, u64::wrapping_from(m), &(u64::wrapping_from(inverse), shift), )) } } } macro_rules! impl_mod_pow { ($t:ident) => { impl ModPowPrecomputedAssign for $t { /// Raises a number to a power modulo another number $m$, in place. The base must be /// already reduced modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular exponentiations with the same modulus. The precomputed data should be /// obtained using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_precomputed_assign). #[inline] fn mod_pow_precomputed_assign(&mut self, exp: u64, m: $t, data: &Self::Data) { *self = self.mod_pow_precomputed(exp, m, data); } } impl ModPow for $t { type Output = $t; /// Raises a number to a power modulo another number $m$. The base must be already /// reduced modulo $m$. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow). #[inline] fn mod_pow(self, exp: u64, m: $t) -> $t { simple_binary_mod_pow(self, exp, m) } } impl ModPowAssign for $t { /// Raises a number to a power modulo another number $m$, in place. The base must be /// already reduced modulo $m$. /// /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_pow#mod_pow_assign). #[inline] fn mod_pow_assign(&mut self, exp: u64, m: $t) { *self = simple_binary_mod_pow(*self, exp, m); } } }; } apply_to_unsigneds!(impl_mod_pow); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ CeilingModPowerOf2, CeilingModPowerOf2Assign, ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, NegModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use core::fmt::Debug; const ERROR_MESSAGE: &str = "Result exceeds width of output type"; fn mod_power_of_2_unsigned(x: T, pow: u64) -> T { if x == T::ZERO || pow >= T::WIDTH { x } else { x & T::low_mask(pow) } } fn mod_power_of_2_assign_unsigned(x: &mut T, pow: u64) { if *x != T::ZERO && pow < T::WIDTH { *x &= T::low_mask(pow); } } #[inline] fn neg_mod_power_of_2_unsigned(x: T, pow: u64) -> T { assert!(x == T::ZERO || pow <= T::WIDTH, "{ERROR_MESSAGE}"); x.wrapping_neg().mod_power_of_2(pow) } macro_rules! impl_mod_power_of_2_unsigned { ($s:ident) => { impl ModPowerOf2 for $s { type Output = $s; /// Divides a number by $2^k$, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#mod_power_of_2). #[inline] fn mod_power_of_2(self, pow: u64) -> $s { mod_power_of_2_unsigned(self, pow) } } impl ModPowerOf2Assign for $s { /// Divides a number by $2^k$, replacing the first number by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#mod_power_of_2_assign). #[inline] fn mod_power_of_2_assign(&mut self, pow: u64) { mod_power_of_2_assign_unsigned(self, pow); } } impl RemPowerOf2 for $s { type Output = $s; /// Divides a number by $2^k$, returning just the remainder. For unsigned integers, /// `rem_power_of_2` is equivalent to [`mod_power_of_2`](super::traits::ModPowerOf2). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#rem_power_of_2). #[inline] fn rem_power_of_2(self, pow: u64) -> $s { self.mod_power_of_2(pow) } } impl RemPowerOf2Assign for $s { /// Divides a number by $2^k$, replacing the first number by the remainder. For unsigned /// integers, `rem_power_of_2_assign` is equivalent to /// [`mod_power_of_2_assign`](super::traits::ModPowerOf2Assign). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#rem_power_of_2_assign). #[inline] fn rem_power_of_2_assign(&mut self, pow: u64) { self.mod_power_of_2_assign(pow) } } impl NegModPowerOf2 for $s { type Output = $s; /// Divides the negative of a number by a $2^k$, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - /// r$ and $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is nonzero and `pow` is greater than `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#neg_mod_power_of_2). #[inline] fn neg_mod_power_of_2(self, pow: u64) -> $s { neg_mod_power_of_2_unsigned(self, pow) } } impl NegModPowerOf2Assign for $s { /// Divides the negative of a number by $2^k$, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - /// r$ and $0 \leq r < 2^k$. /// /// $$ /// x \gets 2^k\left \lceil \frac{x}{2^k} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is nonzero and `pow` is greater than `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#neg_mod_power_of_2_assign). #[inline] fn neg_mod_power_of_2_assign(&mut self, pow: u64) { *self = self.neg_mod_power_of_2(pow) } } }; } apply_to_unsigneds!(impl_mod_power_of_2_unsigned); fn mod_power_of_2_signed, S: PrimitiveSigned>( x: S, pow: u64, ) -> U { assert!(x >= S::ZERO || pow <= S::WIDTH, "{ERROR_MESSAGE}"); U::wrapping_from(x).mod_power_of_2(pow) } fn mod_power_of_2_assign_signed + ModPowerOf2 + PrimitiveSigned>( x: &mut S, pow: u64, ) where >::Error: Debug, { *x = S::try_from(x.mod_power_of_2(pow)).expect(ERROR_MESSAGE); } fn rem_power_of_2_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: S, pow: u64, ) -> S { if x >= S::ZERO { S::wrapping_from(U::wrapping_from(x).mod_power_of_2(pow)) } else { S::wrapping_from(U::wrapping_from(x.wrapping_neg()).mod_power_of_2(pow)).wrapping_neg() } } fn ceiling_mod_power_of_2_signed< U: PrimitiveUnsigned + WrappingFrom, S: TryFrom + PrimitiveSigned, >( x: S, pow: u64, ) -> S where >::Error: Debug, { let abs_result = if x >= S::ZERO { U::wrapping_from(x).neg_mod_power_of_2(pow) } else { U::wrapping_from(x.wrapping_neg()).mod_power_of_2(pow) }; S::try_from(abs_result) .expect(ERROR_MESSAGE) .checked_neg() .expect(ERROR_MESSAGE) } macro_rules! impl_mod_power_of_2_signed { ($u:ident, $s:ident) => { impl ModPowerOf2 for $s { type Output = $u; /// Divides a number by $2^k$, returning just the remainder. The remainder is /// non-negative. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative and `pow` is greater than `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#mod_power_of_2). #[inline] fn mod_power_of_2(self, pow: u64) -> $u { mod_power_of_2_signed(self, pow) } } impl ModPowerOf2Assign for $s { /// Divides a number by $2^k$, replacing the first number by the remainder. The /// remainder is non-negative. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative and `pow` is greater than or equal to `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#mod_power_of_2_assign). #[inline] fn mod_power_of_2_assign(&mut self, pow: u64) { mod_power_of_2_assign_signed(self, pow); } } impl RemPowerOf2 for $s { type Output = $s; /// Divides a number by $2^k$, returning just the remainder. The remainder has the same /// sign as the first number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq |r| < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#rem_power_of_2). #[inline] fn rem_power_of_2(self, pow: u64) -> $s { rem_power_of_2_signed::<$u, $s>(self, pow) } } impl RemPowerOf2Assign for $s { /// Divides a number by $2^k$, replacing the first number by the remainder. The /// remainder has the same sign as the first number. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2#rem_power_of_2_assign). #[inline] fn rem_power_of_2_assign(&mut self, pow: u64) { *self = self.rem_power_of_2(pow) } } impl CeilingModPowerOf2 for $s { type Output = $s; /// Divides a number by $2^k$, returning just the remainder. The remainder is /// non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq -r < 2^k$. /// /// $$ /// f(x, y) = x - 2^k\left \lceil \frac{x}{2^k} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is positive or `Self::MIN`, and `pow` is greater than or equal to /// `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#ceiling_mod_power_of_2). #[inline] fn ceiling_mod_power_of_2(self, pow: u64) -> $s { ceiling_mod_power_of_2_signed::<$u, $s>(self, pow) } } impl CeilingModPowerOf2Assign for $s { /// Divides a number by $2^k$, replacing the first number by the remainder. The /// remainder is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + /// r$ and $0 \leq -r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lceil\frac{x}{2^k} \right \rceil. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is positive or `Self::MIN`, and `pow` is greater than or equal to /// `Self::WIDTH`. /// /// # Examples /// See [here](super::mod_power_of_2#ceiling_mod_power_of_2_assign). #[inline] fn ceiling_mod_power_of_2_assign(&mut self, pow: u64) { *self = self.ceiling_mod_power_of_2(pow) } } }; } apply_to_unsigned_signed_pairs!(impl_mod_power_of_2_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Add, ModPowerOf2AddAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_power_of_2_add(x: T, y: T, pow: u64) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_add(y).mod_power_of_2(pow) } fn mod_power_of_2_add_assign(x: &mut T, y: T, pow: u64) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_add_assign(y); x.mod_power_of_2_assign(pow); } macro_rules! impl_mod_power_of_2_add { ($t:ident) => { impl ModPowerOf2Add<$t> for $t { type Output = $t; /// Adds two numbers modulo a third number $2^k$. The inputs must be already reduced /// modulo $2^k$. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_add#mod_power_of_2_add). #[inline] fn mod_power_of_2_add(self, other: $t, pow: u64) -> $t { mod_power_of_2_add(self, other, pow) } } impl ModPowerOf2AddAssign<$t> for $t { /// Adds two numbers modulo a third number $2^k$, in place. The inputs must be already /// reduced modulo $2^k$. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_add#mod_power_of_2_add_assign). #[inline] fn mod_power_of_2_add_assign(&mut self, other: $t, pow: u64) { mod_power_of_2_add_assign(self, other, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_add); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::ModPowerOf2Inverse; use crate::num::basic::unsigneds::PrimitiveUnsigned; // Uses Newton's method, as described by Colin Plumb in // https://groups.google.com/g/sci.crypt/c/UI-UMbUnYGk/m/hX2-wQVyE3oJ. pub_test! {mod_power_of_2_inverse_fast(x: T, pow: u64) -> Option { assert_ne!(x, T::ZERO); assert!(pow <= T::WIDTH); assert!(x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}"); if x.even() { return None; } else if x == T::ONE { return Some(T::ONE); } let mut small_pow = 2; let mut inverse = x.mod_power_of_2(2); while small_pow < pow { small_pow <<= 1; if small_pow > pow { small_pow = pow; } // inverse <- inverse * (2 - inverse * x) mod 2^small_pow inverse.mod_power_of_2_mul_assign( T::TWO.mod_power_of_2_sub( inverse.mod_power_of_2_mul(x.mod_power_of_2(small_pow), small_pow), small_pow, ), small_pow, ); } Some(inverse) }} macro_rules! impl_mod_power_of_2_inverse { ($u:ident) => { impl ModPowerOf2Inverse for $u { type Output = $u; /// Computes the multiplicative inverse of a number modulo $2^k$. The input must be /// already reduced modulo $2^k$. /// /// Returns `None` if $x$ is even. /// /// $f(x, k) = y$, where $x, y < 2^k$, $x$ is odd, and $xy \equiv 1 \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH`, if `self` is zero, or if `self` is /// greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_inverse#mod_power_of_2_inverse). #[inline] fn mod_power_of_2_inverse(self, pow: u64) -> Option<$u> { mod_power_of_2_inverse_fast(self, pow) } } }; } apply_to_unsigneds!(impl_mod_power_of_2_inverse); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::ModPowerOf2IsReduced; use crate::num::logic::traits::SignificantBits; macro_rules! impl_mod_power_of_2_is_reduced { ($t:ident) => { impl ModPowerOf2IsReduced for $t { /// Returns whether a number is reduced modulo another number $2^k$; in other words, /// whether it has no more than $k$ significant bits. /// /// $f(x, k) = (x < 2^k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2_is_reduced#mod_power_of_2_is_reduced). #[inline] fn mod_power_of_2_is_reduced(&self, pow: u64) -> bool { self.significant_bits() <= pow } } }; } apply_to_unsigneds!(impl_mod_power_of_2_is_reduced); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Mul, ModPowerOf2MulAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_power_of_2_mul(x: T, y: T, pow: u64) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_mul(y).mod_power_of_2(pow) } #[inline] fn mod_power_of_2_mul_assign(x: &mut T, y: T, pow: u64) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_mul_assign(y); x.mod_power_of_2_assign(pow); } macro_rules! impl_mod_power_of_2_mul { ($t:ident) => { impl ModPowerOf2Mul<$t> for $t { type Output = $t; /// Multiplies two numbers modulo a third number $2^k$. The inputs must be already /// reduced modulo $2^k$. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_mul#mod_power_of_2_mul). #[inline] fn mod_power_of_2_mul(self, other: $t, pow: u64) -> $t { mod_power_of_2_mul(self, other, pow) } } impl ModPowerOf2MulAssign<$t> for $t { /// Multiplies two numbers modulo a third number $2^k$, in place. The inputs must be /// already reduced modulo $2^k$. /// /// $x \gets z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_mul#mod_power_of_2_mul_assign). #[inline] fn mod_power_of_2_mul_assign(&mut self, other: $t, pow: u64) { mod_power_of_2_mul_assign(self, other, pow) } } }; } apply_to_unsigneds!(impl_mod_power_of_2_mul); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Neg, ModPowerOf2NegAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_power_of_2_neg(x: T, pow: u64) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); x.wrapping_neg().mod_power_of_2(pow) } fn mod_power_of_2_neg_assign(x: &mut T, pow: u64) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); x.wrapping_neg_assign(); x.mod_power_of_2_assign(pow); } macro_rules! impl_mod_power_of_2_neg { ($t:ident) => { impl ModPowerOf2Neg for $t { type Output = $t; /// Negates a number modulo another number $2^k$. The input must be already reduced /// modulo $2^k$. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_neg#mod_power_of_2_neg). #[inline] fn mod_power_of_2_neg(self, pow: u64) -> $t { mod_power_of_2_neg(self, pow) } } impl ModPowerOf2NegAssign for $t { /// Negates a number modulo another number $2^k$, in place. The input must be already /// reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_neg#mod_power_of_2_neg_assign). #[inline] fn mod_power_of_2_neg_assign(&mut self, pow: u64) { mod_power_of_2_neg_assign(self, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_neg); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Pow, ModPowerOf2PowAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::BitIterable; fn mod_power_of_2_pow(x: T, exp: u64, pow: u64) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if pow == 0 { return T::ZERO; } let mut out = T::ONE; for bit in exp.bits().rev() { out.mod_power_of_2_mul_assign(out, pow); if bit { out.mod_power_of_2_mul_assign(x, pow); } } out } macro_rules! impl_mod_power_of_2_pow { ($t:ident) => { impl ModPowerOf2Pow for $t { type Output = $t; /// Raises a number to a power modulo another number $2^k$. The base must be already /// reduced modulo $2^k$. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_pow#mod_power_of_2_pow). #[inline] fn mod_power_of_2_pow(self, exp: u64, pow: u64) -> $t { mod_power_of_2_pow(self, exp, pow) } } impl ModPowerOf2PowAssign for $t { /// Raises a number to a power modulo another number $2^k$, in place. The base must be /// already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_pow#mod_power_of_2_pow_assign). #[inline] fn mod_power_of_2_pow_assign(&mut self, exp: u64, pow: u64) { *self = self.mod_power_of_2_pow(exp, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_pow); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Shl, ModPowerOf2ShlAssign, UnsignedAbs}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; fn mod_power_of_2_shl_unsigned, U: PrimitiveUnsigned>( x: T, other: U, pow: u64, ) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if other >= U::exact_from(T::WIDTH) { T::ZERO } else { (x << other).mod_power_of_2(pow) } } fn mod_power_of_2_shl_assign_unsigned, U: PrimitiveUnsigned>( x: &mut T, other: U, pow: u64, ) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if other >= U::exact_from(T::WIDTH) { *x = T::ZERO; } else { *x <<= other; x.mod_power_of_2_assign(pow); } } macro_rules! impl_mod_power_of_2_shl_unsigned { ($t:ident) => { macro_rules! impl_mod_power_of_2_shl_unsigned_inner { ($u:ident) => { impl ModPowerOf2Shl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$. The /// number must be already reduced modulo $2^k$. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $2^nx \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(self, other: $u, pow: u64) -> $t { mod_power_of_2_shl_unsigned(self, other, pow) } } impl ModPowerOf2ShlAssign<$u> for $t { /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$, in place. /// The number must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $2^nx \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl_assign). #[inline] fn mod_power_of_2_shl_assign(&mut self, other: $u, pow: u64) { mod_power_of_2_shl_assign_unsigned(self, other, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_shl_unsigned_inner); }; } apply_to_unsigneds!(impl_mod_power_of_2_shl_unsigned); fn mod_power_of_2_shl_signed< T: ModPowerOf2Shl + PrimitiveInt + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, other: S, pow: u64, ) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let other_abs = other.unsigned_abs(); if other >= S::ZERO { x.mod_power_of_2_shl(other_abs, pow) } else { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { T::ZERO } else { x >> other_abs } } } fn mod_power_of_2_shl_assign_signed< T: ModPowerOf2ShlAssign + PrimitiveInt + ShrAssign, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, other: S, pow: u64, ) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let other_abs = other.unsigned_abs(); if other >= S::ZERO { x.mod_power_of_2_shl_assign(other_abs, pow); } else { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { *x = T::ZERO; } else { *x >>= other_abs; } } } macro_rules! impl_mod_power_of_2_shl_signed { ($t:ident) => { macro_rules! impl_mod_power_of_2_shl_signed_inner { ($u:ident) => { impl ModPowerOf2Shl<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$. The /// number must be already reduced modulo $2^k$. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^nx \rfloor \equiv y \mod /// 2^k$. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(self, other: $u, pow: u64) -> $t { mod_power_of_2_shl_signed(self, other, pow) } } impl ModPowerOf2ShlAssign<$u> for $t { /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$, in place. /// The number must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $\lfloor 2^nx \rfloor \equiv y \mod /// 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl_assign). #[inline] fn mod_power_of_2_shl_assign(&mut self, other: $u, pow: u64) { mod_power_of_2_shl_assign_signed(self, other, pow); } } }; } apply_to_signeds!(impl_mod_power_of_2_shl_signed_inner); }; } apply_to_unsigneds!(impl_mod_power_of_2_shl_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, ModPowerOf2ShrAssign, UnsignedAbs, }; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use core::ops::{Shr, ShrAssign}; fn mod_power_of_2_shr_signed< T: ModPowerOf2Shl + PrimitiveInt + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, other: S, pow: u64, ) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let other_abs = other.unsigned_abs(); if other >= S::ZERO { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { T::ZERO } else { x >> other_abs } } else { x.mod_power_of_2_shl(other_abs, pow) } } fn mod_power_of_2_shr_assign_signed< T: ModPowerOf2ShlAssign + PrimitiveInt + ShrAssign, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, other: S, pow: u64, ) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let other_abs = other.unsigned_abs(); if other >= S::ZERO { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { *x = T::ZERO; } else { *x >>= other_abs; } } else { x.mod_power_of_2_shl_assign(other_abs, pow); } } macro_rules! impl_mod_power_of_2_shr_signed { ($t:ident) => { macro_rules! impl_mod_power_of_2_shr_signed_inner { ($u:ident) => { impl ModPowerOf2Shr<$u> for $t { type Output = $t; /// Right-shifts a number (divides it by a power of 2) modulo $2^k$. The number /// must be already reduced modulo $2^k$. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y /// \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr). #[inline] fn mod_power_of_2_shr(self, other: $u, pow: u64) -> $t { mod_power_of_2_shr_signed(self, other, pow) } } impl ModPowerOf2ShrAssign<$u> for $t { /// Right-shifts a number (divides it by a power of 2) modulo $2^k$, in place. /// The number must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod /// 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than /// or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr_assign). #[inline] fn mod_power_of_2_shr_assign(&mut self, other: $u, pow: u64) { mod_power_of_2_shr_assign_signed(self, other, pow) } } }; } apply_to_signeds!(impl_mod_power_of_2_shr_signed_inner); }; } apply_to_unsigneds!(impl_mod_power_of_2_shr_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ ModPowerOf2Mul, ModPowerOf2MulAssign, ModPowerOf2Square, ModPowerOf2SquareAssign, }; macro_rules! impl_mod_power_of_2_square { ($t:ident) => { impl ModPowerOf2Square for $t { type Output = $t; /// Squares a number modulo another number $2^k$. The input must be already reduced /// modulo $2^k$. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $x^2 \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_square#mod_power_of_2_square). #[inline] fn mod_power_of_2_square(self, pow: u64) -> $t { self.mod_power_of_2_mul(self, pow) } } impl ModPowerOf2SquareAssign for $t { /// Squares a number modulo another number $2^k$, in place. The input must be already /// reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $x^2 \equiv y \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` is greater than or equal /// to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_square#mod_power_of_2_square_assign). #[inline] fn mod_power_of_2_square_assign(&mut self, pow: u64) { self.mod_power_of_2_mul_assign(*self, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_square); ================================================ FILE: malachite-base/src/num/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2Sub, ModPowerOf2SubAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_power_of_2_sub(x: T, y: T, pow: u64) -> T { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_sub(y).mod_power_of_2(pow) } fn mod_power_of_2_sub_assign(x: &mut T, y: T, pow: u64) { assert!(pow <= T::WIDTH); assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); assert!( y.significant_bits() <= pow, "y must be reduced mod 2^pow, but {y} >= 2^{pow}" ); x.wrapping_sub_assign(y); x.mod_power_of_2_assign(pow); } macro_rules! impl_mod_power_of_2_sub { ($t:ident) => { impl ModPowerOf2Sub<$t> for $t { type Output = $t; /// Subtracts two numbers modulo a third number $2^k$. The inputs must be already /// reduced modulo $2^k$. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_sub#mod_power_of_2_sub). #[inline] fn mod_power_of_2_sub(self, other: $t, pow: u64) -> $t { mod_power_of_2_sub(self, other, pow) } } impl ModPowerOf2SubAssign<$t> for $t { /// Subtracts two numbers modulo a third number $2^k$, in place. The inputs must be /// already reduced modulo $2^k$. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `pow` is greater than `Self::WIDTH` or if `self` or `other` are greater /// than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_sub#mod_power_of_2_sub_assign). #[inline] fn mod_power_of_2_sub_assign(&mut self, other: $t, pow: u64) { mod_power_of_2_sub_assign(self, other, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_sub); ================================================ FILE: malachite-base/src/num/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModShl, ModShlAssign, UnsignedAbs}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactFrom; use core::ops::{Shr, ShrAssign}; fn mod_shl_unsigned(x: T, other: U, m: T) -> T where u64: ExactFrom, { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); if other == U::ZERO { x } else if m == T::ONE || m == T::TWO { T::ZERO } else { x.mod_mul(T::TWO.mod_pow(u64::exact_from(other), m), m) } } fn mod_shl_assign_unsigned(x: &mut T, other: U, m: T) where u64: ExactFrom, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); if other == U::ZERO { } else if m == T::ONE || m == T::TWO { *x = T::ZERO; } else { x.mod_mul_assign(T::TWO.mod_pow(u64::exact_from(other), m), m); } } macro_rules! impl_mod_shl_unsigned { ($t:ident) => { macro_rules! impl_mod_shl_unsigned_inner { ($u:ident) => { impl ModShl<$u, $t> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2) modulo a number $m$. /// The number must be already reduced modulo $m$. /// /// $f(x, n, m) = y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, other: $u, m: $t) -> $t { mod_shl_unsigned(self, other, m) } } impl ModShlAssign<$u, $t> for $t { /// Left-shifts a number (multiplies it by a power of 2) modulo a number $m$, in /// place. The number must be already reduced modulo $m$. /// /// $x \gets y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, other: $u, m: $t) { mod_shl_assign_unsigned(self, other, m); } } }; } apply_to_unsigneds!(impl_mod_shl_unsigned_inner); }; } apply_to_unsigneds!(impl_mod_shl_unsigned); fn mod_shl_signed< T: ModShl + PrimitiveInt + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, other: S, m: T, ) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); let other_abs = other.unsigned_abs(); if other >= S::ZERO { x.mod_shl(other_abs, m) } else { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { T::ZERO } else { x >> other_abs } } } fn mod_shl_assign_signed< T: ModShlAssign + PrimitiveUnsigned + ShrAssign, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, other: S, m: T, ) { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let other_abs = other.unsigned_abs(); if other >= S::ZERO { x.mod_shl_assign(other_abs, m); } else { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { *x = T::ZERO; } else { *x >>= other_abs; } } } macro_rules! impl_mod_shl_signed { ($t:ident) => { macro_rules! impl_mod_shl_signed_inner { ($u:ident) => { impl ModShl<$u, $t> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2) modulo a number $m$. /// The number must be already reduced modulo $m$. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod /// m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, other: $u, m: $t) -> $t { mod_shl_signed(self, other, m) } } impl ModShlAssign<$u, $t> for $t { /// Left-shifts a number (multiplies it by a power of 2) modulo a number $m$, in /// place. The number must be already reduced modulo $m$. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, other: $u, m: $t) { mod_shl_assign_signed(self, other, m); } } }; } apply_to_signeds!(impl_mod_shl_signed_inner); }; } apply_to_unsigneds!(impl_mod_shl_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModShl, ModShlAssign, ModShr, ModShrAssign, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use core::ops::{Shr, ShrAssign}; fn mod_shr_signed< T: ModShl + PrimitiveUnsigned + Shr, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, other: S, m: T, ) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); let other_abs = other.unsigned_abs(); if other >= S::ZERO { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { T::ZERO } else { x >> other_abs } } else { x.mod_shl(other_abs, m) } } fn mod_shr_assign_signed< T: ModShlAssign + PrimitiveUnsigned + ShrAssign, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, other: S, m: T, ) { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let other_abs = other.unsigned_abs(); if other >= S::ZERO { let width = U::wrapping_from(T::WIDTH); if width != U::ZERO && other_abs >= width { *x = T::ZERO; } else { *x >>= other_abs; } } else { x.mod_shl_assign(other_abs, m); } } macro_rules! impl_mod_shr_signed { ($t:ident) => { macro_rules! impl_mod_shr_signed_inner { ($u:ident) => { impl ModShr<$u, $t> for $t { type Output = $t; /// Right-shifts a number (divides it by a power of 2) modulo a number $m$. The /// number must be already reduced modulo $m$. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y /// \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr(self, other: $u, m: $t) -> $t { mod_shr_signed(self, other, m) } } impl ModShrAssign<$u, $t> for $t { /// Right-shifts a number (divides it by a power of 2) modulo a number $m$, in /// place. The number must be already reduced modulo $m$. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `other.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr_assign(&mut self, other: $u, m: $t) { mod_shr_assign_signed(self, other, m) } } }; } apply_to_signeds!(impl_mod_shr_signed_inner); }; } apply_to_unsigneds!(impl_mod_shr_signed); ================================================ FILE: malachite-base/src/num/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ ModPow, ModPowAssign, ModPowPrecomputed, ModPowPrecomputedAssign, ModSquare, ModSquareAssign, ModSquarePrecomputed, ModSquarePrecomputedAssign, }; macro_rules! impl_mod_square { ($t:ident) => { impl ModSquare for $t { type Output = $t; /// Squares a number modulo another number $m$. The input must be already reduced modulo /// $m$. /// /// $f(x, m) = y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_square#mod_square). #[inline] fn mod_square(self, m: $t) -> $t { self.mod_pow(2, m) } } impl ModSquareAssign for $t { /// Squares a number modulo another number $m$, in place. The input must be already /// reduced modulo $m$. /// /// $x \gets y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_square#mod_square_assign). #[inline] fn mod_square_assign(&mut self, m: $t) { self.mod_pow_assign(2, m); } } impl ModSquarePrecomputed for $t { /// Squares a number modulo another number $m$. The input must be already reduced modulo /// $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular squarings with the same modulus. The precomputed data should be obtained /// using [`precompute_mod_pow_data`](super::traits::ModPowPrecomputed). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_square#mod_square_precomputed). #[inline] fn mod_square_precomputed(self, m: $t, data: &Self::Data) -> Self::Output { self.mod_pow_precomputed(2, m, data) } } impl ModSquarePrecomputedAssign for $t { /// Squares a number modulo another number $m$, in place. The input must be already /// reduced modulo $m$. /// /// Some precomputed data is provided; this speeds up computations involving several /// modular squarings with the same modulus. The precomputed data should be obtained /// using [`precompute_mod_pow_data`](super::traits::ModPowPrecomputed). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_square#mod_square_precomputed_assign). #[inline] fn mod_square_precomputed_assign(&mut self, m: $t, data: &Self::Data) { self.mod_pow_precomputed_assign(2, m, data); } } }; } apply_to_unsigneds!(impl_mod_square); ================================================ FILE: malachite-base/src/num/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2010 William Hart // // Copyright © 2021 Fredrik Johansson // // 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 crate::num::arithmetic::traits::{ModSub, ModSubAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn mod_sub(x: T, y: T, m: T) -> T { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); assert!(y < m, "y must be reduced mod m, but {y} >= {m}"); let diff = x.wrapping_sub(y); if x < y { m.wrapping_add(diff) } else { diff } } macro_rules! impl_mod_sub { ($t:ident) => { impl ModSub<$t> for $t { type Output = $t; /// Subtracts two numbers modulo a third number $m$. The inputs must be already reduced /// modulo $m$. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_sub#mod_sub). /// /// This is equivalent to `nmod_sub` from `nmod.h`, FLINT 2.7.1. #[inline] fn mod_sub(self, other: $t, m: $t) -> $t { mod_sub(self, other, m) } } impl ModSubAssign<$t> for $t { /// Subtracts two numbers modulo a third number $m$, in place. The inputs must be /// already reduced modulo $m$. /// /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_sub#mod_sub_assign). /// /// This is equivalent to `nmod_sub` from `nmod.h`, FLINT 2.7.1, where the result is /// assigned to `a`. #[inline] fn mod_sub_assign(&mut self, other: $t, m: $t) { *self = self.mod_sub(other, m); } } }; } apply_to_unsigneds!(impl_mod_sub); ================================================ FILE: malachite-base/src/num/arithmetic/neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::NegAssign; macro_rules! impl_neg_signed { ($t:ident) => { impl NegAssign for $t { /// Negates a number in place. /// /// Assumes that the negative can be represented. /// /// $x \gets -x$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::neg#neg_assign). #[inline] fn neg_assign(&mut self) { *self = -*self; } } }; } apply_to_signeds!(impl_neg_signed); macro_rules! impl_neg_float { ($t:ident) => { impl NegAssign for $t { /// Negates a number in place. /// /// Assumes that the negative can be represented. /// /// $x \gets -x$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::neg#neg_assign). #[inline] fn neg_assign(&mut self) { *self = -*self; } } }; } apply_to_primitive_floats!(impl_neg_float); ================================================ FILE: malachite-base/src/num/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign, PowerOf2, Sign}; use crate::num::basic::floats::PrimitiveFloat; use crate::num::conversion::traits::SciMantissaAndExponent; use core::cmp::Ordering::*; macro_rules! impl_next_power_of_2_unsigned { ($t:ident) => { impl NextPowerOf2 for $t { type Output = $t; /// This is a wrapper over the `next_power_of_two` functions in the standard library, /// for example [this one](u32::next_power_of_two). #[inline] fn next_power_of_2(self) -> $t { $t::next_power_of_two(self) } } impl NextPowerOf2Assign for $t { /// Replaces a number with the smallest power of 2 greater than or equal to it. /// /// $x \gets 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the next power of 2 is greater than the type's maximum value. /// /// # Examples /// See [here](super::next_power_of_2#next_power_of_2_assign). #[inline] fn next_power_of_2_assign(&mut self) { *self = $t::next_power_of_2(*self); } } }; } apply_to_unsigneds!(impl_next_power_of_2_unsigned); macro_rules! impl_next_power_of_2_primitive_float { ($t:ident) => { impl NextPowerOf2 for $t { type Output = $t; /// Finds the smallest power of 2 greater than or equal to a number. /// /// $x \gets 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` has a negative sign (positive zero is allowed, but negative zero is /// not), or if the next power of 2 is greater than the type's maximum value. /// /// # Examples /// See [here](super::next_power_of_2#next_power_of_2). #[inline] fn next_power_of_2(self) -> $t { assert_eq!(self.sign(), Greater); assert!(self.is_finite()); if self == 0.0 { return $t::MIN_POSITIVE_SUBNORMAL; } let (mantissa, exponent) = self.sci_mantissa_and_exponent(); if mantissa == 1.0 { self } else if exponent == $t::MAX_EXPONENT { panic!("Next power of 2 is too large to represent"); } else { $t::power_of_2(exponent + 1) } } } impl NextPowerOf2Assign for $t { /// Replaces a number with the smallest power of 2 greater than or equal to it. /// /// $x \gets 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the next power of 2 is greater than the type's maximum value. /// /// # Examples /// See [here](super::next_power_of_2#next_power_of_2_assign). #[inline] fn next_power_of_2_assign(&mut self) { *self = $t::next_power_of_2(*self); } } }; } apply_to_primitive_floats!(impl_next_power_of_2_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingAbs, OverflowingAbsAssign}; macro_rules! impl_overflowing_abs { ($t:ident) => { impl OverflowingAbs for $t { type Output = $t; /// This is a wrapper over the `overflowing_abs` functions in the standard library, for /// example [this one](i32::overflowing_abs). #[inline] fn overflowing_abs(self) -> ($t, bool) { $t::overflowing_abs(self) } } impl OverflowingAbsAssign for $t { /// Replaces a number with its absolute value. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_abs#overflowing_abs_assign). #[inline] fn overflowing_abs_assign(&mut self) -> bool { let overflow; (*self, overflow) = self.overflowing_abs(); overflow } } }; } apply_to_signeds!(impl_overflowing_abs); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_add.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingAdd, OverflowingAddAssign}; macro_rules! impl_overflowing_add { ($t:ident) => { impl OverflowingAdd<$t> for $t { type Output = $t; /// This is a wrapper over the `overflowing_add` functions in the standard library, for /// example [this one](u32::overflowing_add). #[inline] fn overflowing_add(self, other: $t) -> ($t, bool) { $t::overflowing_add(self, other) } } impl OverflowingAddAssign<$t> for $t { /// Adds a number to another number, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_add#overflowing_add_assign). #[inline] fn overflowing_add_assign(&mut self, other: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_add(other); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_add); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_add_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ OverflowingAddAssign, OverflowingAddMul, OverflowingAddMulAssign, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn overflowing_add_mul_unsigned(x: T, y: T, z: T) -> (T, bool) { let (product, overflow_1) = y.overflowing_mul(z); let (result, overflow_2) = x.overflowing_add(product); (result, overflow_1 | overflow_2) } macro_rules! impl_overflowing_add_mul_unsigned { ($t:ident) => { impl OverflowingAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers. /// /// Returns a tuple containing the result and a boolean indicating whether an arithmetic /// overflow occurred. If an overflow occurred, then the wrapped value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_add_mul#overflowing_add_mul). #[inline] fn overflowing_add_mul(self, y: $t, z: $t) -> ($t, bool) { overflowing_add_mul_unsigned(self, y, z) } } impl OverflowingAddMulAssign<$t> for $t { /// Adds a number and the product of two other numbers, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_add_mul#overflowing_add_mul_assign). #[inline] fn overflowing_add_mul_assign(&mut self, y: $t, z: $t) -> bool { let (product, overflow) = y.overflowing_mul(z); self.overflowing_add_assign(product) | overflow } } }; } apply_to_unsigneds!(impl_overflowing_add_mul_unsigned); fn overflowing_add_mul_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: S, y: S, z: S, ) -> (S, bool) { if y == S::ZERO || z == S::ZERO { return (x, false); } let x_sign = x >= S::ZERO; if x_sign == ((y >= S::ZERO) == (z >= S::ZERO)) { let (product, overflow_1) = y.overflowing_mul(z); let (result, overflow_2) = x.overflowing_add(product); (result, overflow_1 | overflow_2) } else { let result = x.wrapping_add(y.wrapping_mul(z)); let overflow = { let x = x.unsigned_abs(); match y.unsigned_abs().checked_mul(z.unsigned_abs()) { Some(product) => { x < product && if x_sign { !x.wrapping_sub(product).get_highest_bit() } else { product.wrapping_sub(x).get_highest_bit() } } None => true, } }; (result, overflow) } } macro_rules! impl_overflowing_add_mul_signed { ($t:ident) => { impl OverflowingAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers. /// /// Returns a tuple containing the result and a boolean indicating whether an arithmetic /// overflow occurred. If an overflow occurred, then the wrapped value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_add_mul#overflowing_add_mul). #[inline] fn overflowing_add_mul(self, y: $t, z: $t) -> ($t, bool) { overflowing_add_mul_signed(self, y, z) } } impl OverflowingAddMulAssign<$t> for $t { /// Adds a number and the product of two other numbers, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_add_mul#overflowing_add_mul_assign). #[inline] fn overflowing_add_mul_assign(&mut self, y: $t, z: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_add_mul(y, z); overflow } } }; } apply_to_signeds!(impl_overflowing_add_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_div.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingDiv, OverflowingDivAssign}; macro_rules! impl_overflowing_div { ($t:ident) => { impl OverflowingDiv<$t> for $t { type Output = $t; /// This is a wrapper over the `overflowing_div` functions in the standard library, for /// example [this one](u32::overflowing_div). #[inline] fn overflowing_div(self, other: $t) -> ($t, bool) { $t::overflowing_div(self, other) } } impl OverflowingDivAssign<$t> for $t { /// Divides a number by another number, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. Overflow only occurs when `Self` is /// signed, `self` is `Self::MIN`, and `other` is -1. The "actual" result, `-Self::MIN`, /// can't be represented and is wrapped back to `Self::MIN`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_div#overflowing_div_assign). #[inline] fn overflowing_div_assign(&mut self, other: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_div(other); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_div); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingMul, OverflowingMulAssign}; macro_rules! impl_overflowing_mul { ($t:ident) => { impl OverflowingMul<$t> for $t { type Output = $t; /// This is a wrapper over the `overflowing_mul` functions in the standard library, for /// example [this one](u32::overflowing_mul). #[inline] fn overflowing_mul(self, other: $t) -> ($t, bool) { $t::overflowing_mul(self, other) } } impl OverflowingMulAssign<$t> for $t { /// Multiplies a number by another number, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_mul#overflowing_mul_assign). #[inline] fn overflowing_mul_assign(&mut self, other: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_mul(other); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_mul); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingNeg, OverflowingNegAssign}; macro_rules! impl_overflowing_neg { ($t:ident) => { impl OverflowingNeg for $t { type Output = $t; /// This is a wrapper over the `overflowing_neg` functions in the standard library, for /// example [this one](u32::overflowing_neg). #[inline] fn overflowing_neg(self) -> ($t, bool) { $t::overflowing_neg(self) } } impl OverflowingNegAssign for $t { /// Negates a number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_neg#overflowing_neg_assign). #[inline] fn overflowing_neg_assign(&mut self) -> bool { let overflow; (*self, overflow) = self.overflowing_neg(); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_neg); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingPow, OverflowingPowAssign, Parity, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::OverflowingFrom; use crate::num::logic::traits::BitIterable; fn overflowing_pow_unsigned(x: T, exp: u64) -> (T, bool) { if exp == 0 { (T::ONE, false) } else if x < T::TWO { (x, false) } else { let (mut power, mut overflow) = (x, false); for bit in exp.bits().rev().skip(1) { overflow |= power.overflowing_square_assign(); if bit { overflow |= power.overflowing_mul_assign(x); } } (power, overflow) } } fn overflowing_unsigned_to_signed_neg< U: PrimitiveUnsigned, S: OverflowingFrom + PrimitiveSigned, >( x: U, ) -> (S, bool) { let (signed_x, overflow) = S::overflowing_from(x); if signed_x == S::MIN { (signed_x, false) } else { (signed_x.wrapping_neg(), overflow) } } fn overflowing_pow_signed< U: PrimitiveUnsigned, S: OverflowingFrom + PrimitiveSigned + UnsignedAbs, >( x: S, exp: u64, ) -> (S, bool) { let (p_abs, overflow) = OverflowingPow::overflowing_pow(x.unsigned_abs(), exp); let (p, overflow_2) = if x >= S::ZERO || exp.even() { S::overflowing_from(p_abs) } else { overflowing_unsigned_to_signed_neg(p_abs) }; (p, overflow || overflow_2) } macro_rules! impl_overflowing_pow_unsigned { ($t:ident) => { impl OverflowingPow for $t { type Output = $t; /// This is a wrapper over the `overflowing_pow` functions in the standard library, for /// example [this one](u32::overflowing_pow). #[inline] fn overflowing_pow(self, exp: u64) -> ($t, bool) { overflowing_pow_unsigned(self, exp) } } }; } apply_to_unsigneds!(impl_overflowing_pow_unsigned); macro_rules! impl_overflowing_pow_signed { ($t:ident) => { impl OverflowingPow for $t { type Output = $t; /// This is a wrapper over the `overflowing_pow` functions in the standard library, for /// example [this one](i32::overflowing_pow). #[inline] fn overflowing_pow(self, exp: u64) -> ($t, bool) { overflowing_pow_signed(self, exp) } } }; } apply_to_signeds!(impl_overflowing_pow_signed); macro_rules! impl_overflowing_pow_primitive_int { ($t:ident) => { impl OverflowingPowAssign for $t { /// Raises a number to a power, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Examples /// See [here](super::overflowing_pow#overflowing_pow_assign). #[inline] fn overflowing_pow_assign(&mut self, exp: u64) -> bool { let overflow; (*self, overflow) = OverflowingPow::overflowing_pow(*self, exp); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_pow_primitive_int); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ OverflowingMulAssign, OverflowingSquare, OverflowingSquareAssign, }; macro_rules! impl_overflowing_square { ($t:ident) => { impl OverflowingSquare for $t { type Output = $t; /// Squares a number. /// /// Returns a tuple containing the result and a boolean indicating whether an arithmetic /// occurred. If an overflow occurred, then the wrapped value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_square#overflowing_square). #[inline] fn overflowing_square(self) -> ($t, bool) { self.overflowing_mul(self) } } impl OverflowingSquareAssign for $t { /// Squares a number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_square#overflowing_square_assign). #[inline] fn overflowing_square_assign(&mut self) -> bool { self.overflowing_mul_assign(*self) } } }; } apply_to_primitive_ints!(impl_overflowing_square); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_sub.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{OverflowingSub, OverflowingSubAssign}; macro_rules! impl_overflowing_sub { ($t:ident) => { impl OverflowingSub<$t> for $t { type Output = $t; /// This is a wrapper over the `overflowing_sub` functions in the standard library, for /// example [this one](u32::overflowing_sub). #[inline] fn overflowing_sub(self, other: $t) -> ($t, bool) { $t::overflowing_sub(self, other) } } impl OverflowingSubAssign<$t> for $t { /// Subtracts a number by another number, in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow /// occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_sub#overflowing_sub_assign). #[inline] fn overflowing_sub_assign(&mut self, other: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_sub(other); overflow } } }; } apply_to_primitive_ints!(impl_overflowing_sub); ================================================ FILE: malachite-base/src/num/arithmetic/overflowing_sub_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ OverflowingSubAssign, OverflowingSubMul, OverflowingSubMulAssign, UnsignedAbs, }; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn overflowing_sub_mul_unsigned(x: T, y: T, z: T) -> (T, bool) { let (product, overflow_1) = y.overflowing_mul(z); let (result, overflow_2) = x.overflowing_sub(product); (result, overflow_1 | overflow_2) } macro_rules! impl_overflowing_sub_mul_unsigned { ($t:ident) => { impl OverflowingSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers. /// /// Returns a tuple containing the result and a boolean indicating whether an arithmetic /// overflow would occur. If an overflow would have occurred, then the wrapped value is /// returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_sub_mul#overflowing_sub_mul). #[inline] fn overflowing_sub_mul(self, y: $t, z: $t) -> ($t, bool) { overflowing_sub_mul_unsigned(self, y, z) } } impl OverflowingSubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers, in place. /// /// Returns a boolean indicating whether an arithmetic overflow would occur. If an /// overflow would have occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_sub_mul#overflowing_sub_mul_assign). #[inline] fn overflowing_sub_mul_assign(&mut self, y: $t, z: $t) -> bool { let (product, overflow) = y.overflowing_mul(z); self.overflowing_sub_assign(product) | overflow } } }; } apply_to_unsigneds!(impl_overflowing_sub_mul_unsigned); fn overflowing_sub_mul>( x: S, y: S, z: S, ) -> (S, bool) { if y == S::ZERO || z == S::ZERO { return (x, false); } let x_sign = x >= S::ZERO; if x_sign == ((y >= S::ZERO) != (z >= S::ZERO)) { let (product, overflow_1) = y.overflowing_mul(z); let (result, overflow_2) = x.overflowing_sub(product); (result, overflow_1 | overflow_2) } else { let result = x.wrapping_sub(y.wrapping_mul(z)); let overflow = { let x = x.unsigned_abs(); match y.unsigned_abs().checked_mul(z.unsigned_abs()) { Some(product) => { x < product && if x_sign { !x.wrapping_sub(product).get_highest_bit() } else { product.wrapping_sub(x).get_highest_bit() } } None => true, } }; (result, overflow) } } macro_rules! impl_overflowing_sub_mul_signed { ($t:ident) => { impl OverflowingSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers. /// /// Returns a tuple containing the result and a boolean indicating whether an arithmetic /// overflow occurred. If an overflow occurred, then the wrapped value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_sub_mul#overflowing_sub_mul). #[inline] fn overflowing_sub_mul(self, y: $t, z: $t) -> ($t, bool) { overflowing_sub_mul(self, y, z) } } impl OverflowingSubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers, in place. /// /// Returns a boolean indicating whether an arithmetic overflow would occur. If an /// overflow would have occurred, then the wrapped value is assigned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::overflowing_sub_mul#overflowing_sub_mul_assign). #[inline] fn overflowing_sub_mul_assign(&mut self, y: $t, z: $t) -> bool { let overflow; (*self, overflow) = self.overflowing_sub_mul(y, z); overflow } } }; } apply_to_signeds!(impl_overflowing_sub_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/parity.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Parity; macro_rules! impl_parity { ($t:ident) => { impl Parity for $t { /// Tests whether a number is even. /// /// $f(x) = (2|x)$. /// /// $f(x) = (\exists k \in \N \ x = 2k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::parity#even). #[inline] fn even(self) -> bool { (self & 1) == 0 } /// Tests whether a number is odd. /// /// $f(x) = (2\nmid x)$. /// /// $f(x) = (\exists k \in \N \ x = 2k+1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::parity#odd). #[inline] fn odd(self) -> bool { (self & 1) != 0 } } }; } apply_to_primitive_ints!(impl_parity); ================================================ FILE: malachite-base/src/num/arithmetic/pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Parity, Pow, PowAssign}; use crate::num::conversion::traits::ExactFrom; macro_rules! impl_pow_unsigned { ($t:ident) => { impl Pow for $t { type Output = $t; /// This is a wrapper over the `pow` functions in the standard library, for example /// [this one](u32::pow). #[inline] fn pow(self, exp: u64) -> $t { if exp == 0 { 1 } else if self < 2 { self } else { self.pow(u32::exact_from(exp)) } } } }; } apply_to_unsigneds!(impl_pow_unsigned); macro_rules! impl_pow_signed { ($t:ident) => { impl Pow for $t { type Output = $t; /// This is a wrapper over the `pow` functions in the standard library, for example /// [this one](i32::pow). #[inline] fn pow(self, exp: u64) -> $t { if exp == 0 { 1 } else if self == 0 || self == 1 { self } else if self == -1 { if exp.even() { 1 } else { -1 } } else { self.pow(u32::exact_from(exp)) } } } }; } apply_to_signeds!(impl_pow_signed); macro_rules! impl_pow_primitive_int { ($t:ident) => { impl PowAssign for $t { /// Raises a number to a power, in place. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `exp.significant_bits()`. /// /// # Examples /// See [here](super::pow#pow_assign). #[inline] fn pow_assign(&mut self, exp: u64) { *self = Pow::pow(*self, exp); } } }; } apply_to_primitive_ints!(impl_pow_primitive_int); macro_rules! impl_pow_primitive_float { ($t:ident) => { impl Pow for $t { type Output = $t; /// This is a wrapper over the `powi` functions in the standard library, for example /// [this one](f32::powi). #[inline] fn pow(self, exp: i64) -> $t { libm::Libm::<$t>::pow(self, exp as $t) } } impl PowAssign for $t { /// Raises a number to a power, in place. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::pow#pow_assign). #[inline] fn pow_assign(&mut self, exp: i64) { *self = libm::Libm::<$t>::pow(*self, exp as $t); } } impl Pow<$t> for $t { type Output = $t; /// This is a wrapper over the `powf` functions in the standard library, for example /// [this one](f32::powf). #[inline] fn pow(self, exp: $t) -> $t { libm::Libm::<$t>::pow(self, exp) } } impl PowAssign<$t> for $t { /// Raises a number to a power, in place. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::pow#pow_assign). #[inline] fn pow_assign(&mut self, exp: $t) { *self = libm::Libm::<$t>::pow(*self, exp); } } }; } apply_to_primitive_floats!(impl_pow_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::PowerOf2; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{IntegerMantissaAndExponent, SaturatingFrom}; fn power_of_2_unsigned(pow: u64) -> T { assert!(pow < T::WIDTH); T::ONE << pow } macro_rules! impl_power_of_2_unsigned { ($t:ident) => { impl PowerOf2 for $t { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the result is not representable. /// /// # Examples /// See [here](super::power_of_2#power_of_2). #[inline] fn power_of_2(pow: u64) -> $t { power_of_2_unsigned(pow) } } }; } apply_to_unsigneds!(impl_power_of_2_unsigned); fn power_of_2_signed(pow: u64) -> T { assert!(pow < T::WIDTH - 1); T::ONE << pow } macro_rules! impl_power_of_2_signed { ($t:ident) => { impl PowerOf2 for $t { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the result is not representable. /// /// # Examples /// See [here](super::power_of_2#power_of_2). #[inline] fn power_of_2(pow: u64) -> $t { power_of_2_signed(pow) } } }; } apply_to_signeds!(impl_power_of_2_signed); macro_rules! impl_power_of_2_primitive_float { ($t:ident) => { impl PowerOf2 for $t { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the power is greater than `Self::MAX_EXPONENT`. /// /// # Examples /// See [here](super::power_of_2#power_of_2). #[inline] fn power_of_2(pow: u64) -> $t { $t::from_integer_mantissa_and_exponent(1, i64::saturating_from(pow)).unwrap() } } impl PowerOf2 for $t { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the power is smaller than `Self::MIN_EXPONENT` or greater than /// `Self::MAX_EXPONENT`. /// /// # Examples /// See [here](super::power_of_2#power_of_2). #[inline] fn power_of_2(pow: i64) -> $t { $t::from_integer_mantissa_and_exponent(1, pow).unwrap() } } }; } apply_to_primitive_floats!(impl_power_of_2_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedPrimorial, Primorial}; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::conversion::traits::WrappingFrom; const PRIMORIALS_U8: [u8; 5] = [1, 2, 6, 30, 210]; const PRIMORIALS_U16: [u16; 7] = [1, 2, 6, 30, 210, 2310, 30030]; const PRIMORIALS_U32: [u32; 10] = [1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870]; const PRIMORIALS_U64: [u64; 16] = [ 1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870, 6469693230, 200560490130, 7420738134810, 304250263527210, 13082761331670030, 614889782588491410, ]; const PRIMORIALS_U128: [u128; 27] = [ 1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870, 6469693230, 200560490130, 7420738134810, 304250263527210, 13082761331670030, 614889782588491410, 32589158477190044730, 1922760350154212639070, 117288381359406970983270, 7858321551080267055879090, 557940830126698960967415390, 40729680599249024150621323470, 3217644767340672907899084554130, 267064515689275851355624017992790, 23768741896345550770650537601358310, 2305567963945518424753102147331756070, 232862364358497360900063316880507363070, ]; const PRIMORIAL_PRIMES_U8: [u64; 5] = [2, 3, 5, 7, 11]; const PRIMORIAL_PRIMES_U16: [u64; 7] = [2, 3, 5, 7, 11, 13, 17]; const PRIMORIAL_PRIMES_U32: [u64; 10] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]; const PRIMORIAL_PRIMES_U64: [u64; 16] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]; const PRIMORIAL_PRIMES_U128: [u64; 27] = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, ]; macro_rules! impl_primorials_a { ($t:ident, $ps:ident, $pps:ident) => { impl CheckedPrimorial for $t { /// Computes the primorial of a number: the product of all primes less than or equal to /// it. /// /// The /// [`checked_product_of_first_n_primes`](CheckedPrimorial::checked_product_of_first_n_primes) /// function is similar; it computes the primorial of the $n$th prime. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n\\#) & \text{if} \\quad n\\# < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n\\# \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primorial#checked_primorial). #[inline] fn checked_primorial(n: u64) -> Option<$t> { let i = match $pps.binary_search(&n) { Ok(i) => i + 1, Err(i) => i, }; $ps.get(i).copied() } /// Computes the product of the first $n$ primes. /// /// The [`checked_primorial`](CheckedPrimorial::checked_primorial) function is similar; /// it computes the product of all primes less than or equal to $n$. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(p_n\\#) & \text{if} \\quad p_n\\# < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad p_n\\# \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primorial#checked_product_of_first_n_primes). #[inline] fn checked_product_of_first_n_primes(n: u64) -> Option<$t> { $ps.get(usize::try_from(n).ok()?).copied() } } }; } impl_primorials_a!(u8, PRIMORIALS_U8, PRIMORIAL_PRIMES_U8); impl_primorials_a!(u16, PRIMORIALS_U16, PRIMORIAL_PRIMES_U16); impl_primorials_a!(u32, PRIMORIALS_U32, PRIMORIAL_PRIMES_U32); impl_primorials_a!(u64, PRIMORIALS_U64, PRIMORIAL_PRIMES_U64); impl_primorials_a!(u128, PRIMORIALS_U128, PRIMORIAL_PRIMES_U128); impl CheckedPrimorial for usize { /// Computes the primorial of a [`usize`]: the product of all primes less than or equal to it. /// /// The /// [`checked_product_of_first_n_primes`](CheckedPrimorial::checked_product_of_first_n_primes) /// function is similar; it computes the primorial of the $n$th prime. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(n\\#) & \text{if} \\quad n\\# < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad n\\# \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `usize::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primorial#checked_primorial). #[inline] fn checked_primorial(n: u64) -> Option { if USIZE_IS_U32 { u32::checked_primorial(n).map(Self::wrapping_from) } else { u64::checked_primorial(n).map(Self::wrapping_from) } } /// Computes the product of the first $n$ primes. /// /// The [`checked_primorial`](CheckedPrimorial::checked_primorial) function is similar; it /// computes the product of all primes less than or equal to $n$. /// /// If the input is too large, the function returns `None`. /// /// $$ /// f(n) = \\begin{cases} /// \operatorname{Some}(p_n\\#) & \text{if} \\quad p_n\\# < 2^W, \\\\ /// \operatorname{None} & \text{if} \\quad p_n\\# \geq 2^W, /// \\end{cases} /// $$ /// where $W$ is `usize::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primorial#checked_product_of_first_n_primes). #[inline] fn checked_product_of_first_n_primes(n: u64) -> Option { if USIZE_IS_U32 { u32::checked_product_of_first_n_primes(n).map(Self::wrapping_from) } else { u64::checked_product_of_first_n_primes(n).map(Self::wrapping_from) } } } macro_rules! impl_primorials_b { ($t:ident) => { impl Primorial for $t { /// Computes the primorial of a number: the product of all primes less than or equal to /// it. /// /// The [`product_of_first_n_primes`](Primorial::product_of_first_n_primes) function is /// similar; it computes the primorial of the $n$th prime. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try [`checked_primorial`](CheckedPrimorial::checked_primorial). /// /// $$ /// f(n) = n\\# = \prod_{p \leq n \atop p \\ \\text {prime}} p. /// $$ /// /// $n\\# = O(e^{(1+o(1))n})$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::primorial#primorial). #[inline] fn primorial(n: u64) -> $t { $t::checked_primorial(n).unwrap() } /// Computes the product of the first $n$ primes. /// /// The [`primorial`](Primorial::primorial) function is similar; it computes the product /// of all primes less than or equal to $n$. /// /// If the input is too large, the function panics. For a function that returns `None` /// instead, try /// [`checked_product_of_first_n_primes`](CheckedPrimorial::checked_product_of_first_n_primes). /// /// $$ /// f(n) = p_n\\# = \prod_{k=1}^n p_n, /// $$ /// where $p_n$ is the $n$th prime number. /// /// $p_n\\# = O\left ( \left ( \frac{1}{e}k\log k\left ( \frac{\log k}{e^2}k \right /// )^{1/\log k} \right )^k \omega(1)\right )$. /// /// This asymptotic approximation is due to [Bart /// Michels](https://math.stackexchange.com/a/1594930). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the output is too large to be represented. /// /// # Examples /// See [here](super::primorial#product_of_first_n_primes). #[inline] fn product_of_first_n_primes(n: u64) -> $t { $t::checked_product_of_first_n_primes(n).unwrap() } } }; } apply_to_unsigneds!(impl_primorials_b); ================================================ FILE: malachite-base/src/num/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Reciprocal, ReciprocalAssign}; macro_rules! impl_reciprocal { ($t:ident) => { impl Reciprocal for $t { type Output = $t; /// Takes the reciprocal of a floating-point number. /// /// $$ /// f(x) = 1/x+\varepsilon. /// $$ /// Let $p$ be the precision of the input float (typically 24 for `f32`s and 53 for /// `f64`s, unless the float is subnormal). /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to /// be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=-0.0$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=-\infty$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::reciprocal#reciprocal). #[inline] fn reciprocal(self) -> $t { 1.0 / self } } impl ReciprocalAssign for $t { /// Takes the reciprocal of a floating-point number, in place. /// /// $x \gets 1/x+\varepsilon$. Let $p$ be the precision of the input float (typically 24 /// for `f32`s and 53 for `f64`s, unless the float is subnormal). /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to /// be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// See the `reciprocal` documentation for information on special cases. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::reciprocal#reciprocal_assign). #[inline] fn reciprocal_assign(&mut self) { *self = 1.0 / *self; } } }; } apply_to_primitive_floats!(impl_reciprocal); ================================================ FILE: malachite-base/src/num/arithmetic/root.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2015 William Hart // // Copyright © 2015 Fredrik Johansson // // Copyright © 2015 Kushagra Singh // // 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 . #[cfg(feature = "test_build")] use crate::num::arithmetic::sqrt::floor_inverse_checked_binary; #[cfg(feature = "test_build")] use crate::num::arithmetic::traits::DivRound; use crate::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CeilingSqrt, CheckedRoot, CheckedSqrt, DivMod, FloorRoot, FloorRootAssign, FloorSqrt, Parity, Pow, PowerOf2, RootAssignRem, RootRem, SqrtRem, XMulYToZZ, }; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ RawMantissaAndExponent, RoundingFrom, SaturatingFrom, WrappingFrom, }; use crate::num::logic::traits::{LowMask, SignificantBits}; use crate::rounding_modes::RoundingMode::*; use core::cmp::Ordering::*; const U8_CUBES: [u8; 7] = [0, 1, 8, 27, 64, 125, 216]; // This section is created by max_base.rs. const MAX_BASE_8: [u8; 8] = [0, 255, 15, 6, 3, 3, 2, 2]; const MAX_POWER_8: [u8; 8] = [0, 255, 225, 216, 81, 243, 64, 128]; const MAX_BASE_16: [u16; 16] = [0, 65535, 255, 40, 15, 9, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2]; const MAX_POWER_16: [u16; 16] = [ 0, 65535, 65025, 64000, 50625, 59049, 46656, 16384, 6561, 19683, 59049, 2048, 4096, 8192, 16384, 32768, ]; const MAX_BASE_32: [u32; 32] = [ 0, 4294967295, 65535, 1625, 255, 84, 40, 23, 15, 11, 9, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ]; const MAX_POWER_32: [u32; 32] = [ 0, 4294967295, 4294836225, 4291015625, 4228250625, 4182119424, 4096000000, 3404825447, 2562890625, 2357947691, 3486784401, 1977326743, 2176782336, 1220703125, 268435456, 1073741824, 43046721, 129140163, 387420489, 1162261467, 3486784401, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, ]; const MAX_BASE_64: [u64; 64] = [ 0, 18446744073709551615, 4294967295, 2642245, 65535, 7131, 1625, 565, 255, 138, 84, 56, 40, 30, 23, 19, 15, 13, 11, 10, 9, 8, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ]; const MAX_POWER_64: [u64; 64] = [ 0, 18446744073709551615, 18446744065119617025, 18446724184312856125, 18445618199572250625, 18439629140666724651, 18412815093994140625, 18379730316001328125, 17878103347812890625, 18151468971815029248, 17490122876598091776, 16985107389382393856, 16777216000000000000, 15943230000000000000, 11592836324538749809, 15181127029874798299, 6568408355712890625, 8650415919381337933, 5559917313492231481, 10000000000000000000, 12157665459056928801, 9223372036854775808, 3909821048582988049, 789730223053602816, 4738381338321616896, 298023223876953125, 1490116119384765625, 7450580596923828125, 72057594037927936, 288230376151711744, 1152921504606846976, 4611686018427387904, 1853020188851841, 5559060566555523, 16677181699666569, 50031545098999707, 150094635296999121, 450283905890997363, 1350851717672992089, 4052555153018976267, 12157665459056928801, 2199023255552, 4398046511104, 8796093022208, 17592186044416, 35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312, 1125899906842624, 2251799813685248, 4503599627370496, 9007199254740992, 18014398509481984, 36028797018963968, 72057594037927936, 144115188075855872, 288230376151711744, 576460752303423488, 1152921504606846976, 2305843009213693952, 4611686018427387904, 9223372036854775808, ]; const MAX_BASE_128: [u128; 128] = [ 0, 340282366920938463463374607431768211455, 18446744073709551615, 6981463658331, 4294967295, 50859008, 2642245, 319557, 65535, 19112, 7131, 3183, 1625, 920, 565, 370, 255, 184, 138, 106, 84, 68, 56, 47, 40, 34, 30, 26, 23, 21, 19, 17, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ]; const MAX_POWER_128: [u128; 128] = [ 0, 340282366920938463463374607431768211455, 340282366920938463426481119284349108225, 340282366920856711588743492508790678691, 340282366604025813516997721482669850625, 340282351457171161640582485552312352768, 340281633132112807150397932954950015625, 340281506971235808117106851925354131693, 340240830764391036687105719527812890625, 340216388952569572744243119867142602752, 340019922845325450206316382040251071801, 339784078391451014674643196649809097167, 339031759685618453659117221832275390625, 338253076642491662461829120000000000000, 337814486488938281014651876763916015625, 333446267951815307088493000000000000000, 319626579315078487616775634918212890625, 317616452802997733092688724349413228544, 329475825834763755052723200291095445504, 302559950208758936970093677790372560896, 305904398238499908683087849324518834176, 303869538891536196286006028740295917568, 288493873028852398739253829029106548736, 287243845682065590744605010781602099023, 281474976710656000000000000000000000000, 193630125104980427932766033374162714624, 254186582832900000000000000000000000000, 160059109085386090080713531498405298176, 134393854047545109686936775588697536481, 220983347100817338120002444455525554981, 230466617897195215045509519405933293401, 139288917338851014461418017489467720433, 43143988327398919500410556793212890625, 66408730383449729837806206197059026944, 74829695578286078013428929473144712489, 59066822915424320448445358917464096768, 30912680532870672635673352936887453361, 340039485861577398992406882305761986971, 100000000000000000000000000000000000000, 16423203268260658146231467800709255289, 147808829414345923316083210206383297601, 10633823966279326983230456482242756608, 85070591730234615865843651857942052864, 2183814375991796599109312252753832343, 15286700631942576193765185769276826401, 107006904423598033356356300384937784807, 623673825204293256669089197883129856, 3742042951225759540014535187298779136, 22452257707354557240087211123792674816, 134713546244127343440523266742756048896, 88817841970012523233890533447265625, 444089209850062616169452667236328125, 2220446049250313080847263336181640625, 11102230246251565404236316680908203125, 55511151231257827021181583404541015625, 277555756156289135105907917022705078125, 5192296858534827628530496329220096, 20769187434139310514121985316880384, 83076749736557242056487941267521536, 332306998946228968225951765070086144, 1329227995784915872903807060280344576, 5316911983139663491615228241121378304, 21267647932558653966460912964485513216, 85070591730234615865843651857942052864, 3433683820292512484657849089281, 10301051460877537453973547267843, 30903154382632612361920641803529, 92709463147897837085761925410587, 278128389443693511257285776231761, 834385168331080533771857328695283, 2503155504993241601315571986085849, 7509466514979724803946715958257547, 22528399544939174411840147874772641, 67585198634817523235520443624317923, 202755595904452569706561330872953769, 608266787713357709119683992618861307, 1824800363140073127359051977856583921, 5474401089420219382077155933569751763, 16423203268260658146231467800709255289, 49269609804781974438694403402127765867, 147808829414345923316083210206383297601, 2417851639229258349412352, 4835703278458516698824704, 9671406556917033397649408, 19342813113834066795298816, 38685626227668133590597632, 77371252455336267181195264, 154742504910672534362390528, 309485009821345068724781056, 618970019642690137449562112, 1237940039285380274899124224, 2475880078570760549798248448, 4951760157141521099596496896, 9903520314283042199192993792, 19807040628566084398385987584, 39614081257132168796771975168, 79228162514264337593543950336, 158456325028528675187087900672, 316912650057057350374175801344, 633825300114114700748351602688, 1267650600228229401496703205376, 2535301200456458802993406410752, 5070602400912917605986812821504, 10141204801825835211973625643008, 20282409603651670423947251286016, 40564819207303340847894502572032, 81129638414606681695789005144064, 162259276829213363391578010288128, 324518553658426726783156020576256, 649037107316853453566312041152512, 1298074214633706907132624082305024, 2596148429267413814265248164610048, 5192296858534827628530496329220096, 10384593717069655257060992658440192, 20769187434139310514121985316880384, 41538374868278621028243970633760768, 83076749736557242056487941267521536, 166153499473114484112975882535043072, 332306998946228968225951765070086144, 664613997892457936451903530140172288, 1329227995784915872903807060280344576, 2658455991569831745807614120560689152, 5316911983139663491615228241121378304, 10633823966279326983230456482242756608, 21267647932558653966460912964485513216, 42535295865117307932921825928971026432, 85070591730234615865843651857942052864, 170141183460469231731687303715884105728, ]; pub_test! {floor_root_approx_and_refine f64, G: Fn(f64) -> T>( f: F, g: G, x: T, exp: u64, ) -> T { assert_ne!(exp, 0); if x == T::ZERO || exp == 1 { return x; } if exp >= T::WIDTH { return T::ONE; } let exp_usize = usize::wrapping_from(exp); let max_root = match T::WIDTH { u8::WIDTH => T::wrapping_from(MAX_BASE_8[exp_usize]), u16::WIDTH => T::wrapping_from(MAX_BASE_16[exp_usize]), u32::WIDTH => T::wrapping_from(MAX_BASE_32[exp_usize]), u64::WIDTH => T::wrapping_from(MAX_BASE_64[exp_usize]), u128::WIDTH => T::wrapping_from(MAX_BASE_128[exp_usize]), _ => unreachable!(), }; let max_pow = match T::WIDTH { u8::WIDTH => T::wrapping_from(MAX_POWER_8[exp_usize]), u16::WIDTH => T::wrapping_from(MAX_POWER_16[exp_usize]), u32::WIDTH => T::wrapping_from(MAX_POWER_32[exp_usize]), u64::WIDTH => T::wrapping_from(MAX_POWER_64[exp_usize]), u128::WIDTH => T::wrapping_from(MAX_POWER_128[exp_usize]), _ => unreachable!(), }; if x >= max_pow { return max_root; } let mut root = g(f(x).pow(1.0 / (exp as f64))); let mut pow = if let Some(pow) = root.checked_pow(exp) { pow } else { // set to max possible pow root = max_root; max_pow }; match pow.cmp(&x) { Equal => root, Less => loop { root += T::ONE; pow = root.pow(exp); match pow.cmp(&x) { Equal => return root, Less => {} Greater => return root - T::ONE, } }, Greater => loop { root -= T::ONE; pow = root.pow(exp); if pow <= x { return root; } }, } }} // Coefficients of Chebyshev's approximation polynomial (deg 2) {c0, c1, c2} splitting 0.5 to 1 into // 8 equal intervals // // Values of these coefficients of Chebyshev's approximation polynomial have been calculated from // the python module, "mpmath" - http://mpmath.org/ function call: mpmath.chebyfit(lambda x: // mpmath.root(x,3), [i, j], 3, error=True) where (i, j) is the range. // // ``` // c0 c1 c2 range // 0.445434042 0.864136635 -0.335205926 [0.50000, 0.53125] // 0.454263239 0.830878907 -0.303884962 [0.53125, 0.56250] // 0.462761624 0.800647514 -0.276997626 [0.56250, 0.59375] // 0.470958569 0.773024522 -0.253724515 [0.59375, 0.62500] // 0.478879482 0.747667468 -0.233429710 [0.62500, 0.65625] // 0.486546506 0.724292830 -0.215613166 [0.65625, 0.68750] // 0.493979069 0.702663686 -0.199877008 [0.68750, 0.71875] // 0.501194325 0.682580388 -0.185901247 [0.71875, 0.75000] // 0.508207500 0.663873398 -0.173426009 [0.75000, 0.78125] // 0.515032183 0.646397742 -0.162238357 [0.78125, 0.81250] // 0.521680556 0.630028647 -0.152162376 [0.81250, 0.84375] // 0.528163588 0.614658092 -0.143051642 [0.84375, 0.87500] // 0.534491194 0.600192044 -0.134783425 [0.87500, 0.90625] // 0.540672371 0.586548233 -0.127254189 [0.90625, 0.93750] // 0.546715310 0.573654340 -0.120376066 [0.93750, 0.96875] // 0.552627494 0.561446514 -0.114074068 [0.96875, 1.00000] // ``` // // 1^(1/3), 2^(1/3), 4^(1/3) const FACTOR_TABLE: [f32; 3] = [1.000000, 1.259921, 1.587401]; #[allow(clippy::excessive_precision)] const COEFF: [[f32; 3]; 16] = [ [0.445434042, 0.864136635, -0.335205926], [0.454263239, 0.830878907, -0.303884962], [0.462761624, 0.800647514, -0.276997626], [0.470958569, 0.773024522, -0.253724515], [0.478879482, 0.747667468, -0.233429710], [0.486546506, 0.724292830, -0.215613166], [0.493979069, 0.702663686, -0.199877008], [0.501194325, 0.682580388, -0.185901247], [0.508207500, 0.663873398, -0.173426009], [0.515032183, 0.646397742, -0.162238357], [0.521680556, 0.630028647, -0.152162376], [0.528163588, 0.614658092, -0.143051642], [0.534491194, 0.600192044, -0.134783425], [0.540672371, 0.586548233, -0.127254189], [0.546715310, 0.573654340, -0.120376066], [0.552627494, 0.561446514, -0.114074068], ]; // n cannot be 0 // // This is equivalent to `n_cbrt_chebyshev_approx` from // `ulong_extras/cbrt_chebyshev_approximation.c`, FLINT 2.7.1, where `FLINT64` is `false`. pub_test! {cbrt_chebyshev_approx_u32(n: u32) -> u32 { // UPPER_LIMIT is the max cube root possible for one word const UPPER_LIMIT: u32 = 1625; // 1625 < (2^32)^(1/3) const BIAS_HEX: u32 = 0x3f000000; const BIAS: u32 = 126; let (mantissa, exponent) = (n as f32).raw_mantissa_and_exponent(); let mut mantissa = u32::wrapping_from(mantissa); let table_index = usize::wrapping_from(mantissa >> (f32::MANTISSA_WIDTH - 4)); mantissa |= BIAS_HEX; let (exponent_over_3, exponent_rem) = (u32::wrapping_from(exponent) - BIAS).div_mod(3); // Calculating cube root of dec using Chebyshev approximation polynomial // // Evaluating approx polynomial at (dec) by Estrin's scheme let x = f32::from_bits(mantissa); let row = COEFF[table_index]; let mut cbrt = ((row[0] + row[1] * x + row[2] * (x * x)) * f32::power_of_2(i64::wrapping_from(exponent_over_3)) * FACTOR_TABLE[usize::wrapping_from(exponent_rem)]) as u32; const MAX_CUBE: u32 = UPPER_LIMIT * UPPER_LIMIT * UPPER_LIMIT; if cbrt >= UPPER_LIMIT { if n >= MAX_CUBE { return UPPER_LIMIT; } cbrt = UPPER_LIMIT - 1; } while cbrt * cbrt * cbrt <= n { cbrt += 1; if cbrt == UPPER_LIMIT { break; } } while cbrt * cbrt * cbrt > n { cbrt -= 1; } cbrt }} // n cannot be 0 // // This is equivalent to `n_cbrt_chebyshev_approx` from // `ulong_extras/cbrt_chebyshev_approximation.c`, FLINT 2.7.1, where `FLINT64` is `true`. pub_test! {cbrt_chebyshev_approx_u64(n: u64) -> u64 { // UPPER_LIMIT is the max cube root possible for one word const UPPER_LIMIT: u64 = 2642245; // 2642245 < (2^64)^(1/3) const BIAS_HEX: u64 = 0x3fe0000000000000; const BIAS: u64 = 1022; let (mut mantissa, exponent) = (n as f64).raw_mantissa_and_exponent(); let table_index = usize::wrapping_from(mantissa >> (f64::MANTISSA_WIDTH - 4)); mantissa |= BIAS_HEX; let (exponent_over_3, exponent_rem) = (exponent - BIAS).div_mod(3); // Calculating cube root of dec using Chebyshev approximation polynomial // // Evaluating approx polynomial at x by Estrin's scheme let x = f64::from_bits(mantissa); let row = COEFF[table_index]; let mut cbrt = ((f64::from(row[0]) + f64::from(row[1]) * x + f64::from(row[2]) * (x * x)) * f64::power_of_2(i64::wrapping_from(exponent_over_3)) * f64::from(FACTOR_TABLE[usize::wrapping_from(exponent_rem)])) as u64; const MAX_CUBE: u64 = UPPER_LIMIT * UPPER_LIMIT * UPPER_LIMIT; if cbrt >= UPPER_LIMIT { if n >= MAX_CUBE { return UPPER_LIMIT; } cbrt = UPPER_LIMIT - 1; } while cbrt * cbrt * cbrt <= n { cbrt += 1; if cbrt == UPPER_LIMIT { break; } } while cbrt * cbrt * cbrt > n { cbrt -= 1; } cbrt }} // This is equivalent to `n_cbrt_estimate` from `ulong_extras/n_cbrt_estimate.c`, FLINT 2.7.1, where // `FLINT64` is `true`. #[cfg(feature = "test_build")] fn cbrt_estimate_f64(a: f64) -> f64 { const S: u64 = 4607182418800017408; // ((1 << 10) - 1) << 52 f64::from_bits( u64::wrapping_from((u128::from(a.to_bits() - S) * 6148914691236517205) >> 64) + S, ) } // This is equivalent to `n_cbrt` from `ulong_extras/cbrt.c`, FLINT 2.7.1, where `FLINT64` is // `false`. #[cfg(feature = "test_build")] pub fn fast_floor_cbrt_u32(n: u32) -> u32 { // Taking care of smaller roots if n < 125 { return if n >= 64 { 4 } else if n >= 27 { 3 } else if n >= 8 { 2 } else { u32::from(n >= 1) }; } if n < 1331 { return if n >= 1000 { 10 } else if n >= 729 { 9 } else if n >= 512 { 8 } else if n >= 343 { 7 } else if n >= 216 { 6 } else { 5 }; } if n < 4913 { return if n >= 4096 { 16 } else if n >= 3375 { 15 } else if n >= 2744 { 14 } else if n >= 2197 { 13 } else if n >= 1728 { 12 } else { 11 }; } let val = f64::from(n); const UPPER_LIMIT: u32 = 1625; // 1625 < (2^32)^(1/3) let mut x = cbrt_estimate_f64(val); // Kahan's iterations to get cube root let xcub = x * x * x; let num = (xcub - val) * x; let den = xcub + xcub + val; x -= num / den; let mut ret = x as u32; const UPPER_LIMIT_CUBE: u32 = UPPER_LIMIT * UPPER_LIMIT * UPPER_LIMIT; // In case ret ^ 3 or (ret + 1) ^ 3 will cause overflow if ret >= UPPER_LIMIT { if n >= UPPER_LIMIT_CUBE { return UPPER_LIMIT; } ret = UPPER_LIMIT - 1; } while ret * ret * ret <= n { ret += 1; if ret == UPPER_LIMIT { break; } } while ret * ret * ret > n { ret -= 1; } ret } // TODO tune #[cfg(feature = "test_build")] const CBRT_CHEBYSHEV_THRESHOLD: u64 = 10; // This is equivalent to `n_cbrt` from `ulong_extras/cbrt.c`, FLINT 2.7.1, where `FLINT64` is // `true`. #[cfg(feature = "test_build")] pub fn fast_floor_cbrt_u64(n: u64) -> u64 { // Taking care of smaller roots if n < 125 { return if n >= 64 { 4 } else if n >= 27 { 3 } else if n >= 8 { 2 } else { u64::from(n >= 1) }; } if n < 1331 { return if n >= 1000 { 10 } else if n >= 729 { 9 } else if n >= 512 { 8 } else if n >= 343 { 7 } else if n >= 216 { 6 } else { 5 }; } if n < 4913 { return if n >= 4096 { 16 } else if n >= 3375 { 15 } else if n >= 2744 { 14 } else if n >= 2197 { 13 } else if n >= 1728 { 12 } else { 11 }; } if n.significant_bits() > CBRT_CHEBYSHEV_THRESHOLD { return cbrt_chebyshev_approx_u64(n); } let val = n as f64; const UPPER_LIMIT: u64 = 2642245; // 2642245 < (2^64)^(1/3) let mut x = cbrt_estimate_f64(val); // Kahan's iterations to get cube root let xcub = x * x * x; let num = (xcub - val) * x; let den = xcub + xcub + val; x -= num / den; let mut ret = x as u64; const UPPER_LIMIT_CUBE: u64 = UPPER_LIMIT * UPPER_LIMIT * UPPER_LIMIT; // In case ret ^ 3 or (ret + 1) ^ 3 will cause overflow if ret >= UPPER_LIMIT { if n >= UPPER_LIMIT_CUBE { return UPPER_LIMIT; } ret = UPPER_LIMIT - 1; } while ret * ret * ret <= n { ret += 1; if ret == UPPER_LIMIT { break; } } while ret * ret * ret > n { ret -= 1; } ret } // this table contains the value of UWORD_MAX / n, for n in range [1, 32] const MUL_FACTOR_32: [u32; 33] = [ 0, u32::MAX, 2147483647, 1431655765, 1073741823, 858993459, 715827882, 613566756, 536870911, 477218588, 429496729, 390451572, 357913941, 330382099, 306783378, 286331153, 268435455, 252645135, 238609294, 226050910, 214748364, 204522252, 195225786, 186737708, 178956970, 171798691, 165191049, 159072862, 153391689, 148102320, 143165576, 138547332, 134217727, ]; // this table contains the value of UWORD_MAX / n, for n in range [1, 64] const MUL_FACTOR_64: [u64; 65] = [ 0, u64::MAX, 9223372036854775807, 6148914691236517205, 4611686018427387903, 3689348814741910323, 3074457345618258602, 2635249153387078802, 2305843009213693951, 2049638230412172401, 1844674407370955161, 1676976733973595601, 1537228672809129301, 1418980313362273201, 1317624576693539401, 1229782938247303441, 1152921504606846975, 1085102592571150095, 1024819115206086200, 970881267037344821, 922337203685477580, 878416384462359600, 838488366986797800, 802032351030850070, 768614336404564650, 737869762948382064, 709490156681136600, 683212743470724133, 658812288346769700, 636094623231363848, 614891469123651720, 595056260442243600, 576460752303423487, 558992244657865200, 542551296285575047, 527049830677415760, 512409557603043100, 498560650640798692, 485440633518672410, 472993437787424400, 461168601842738790, 449920587163647600, 439208192231179800, 428994048225803525, 419244183493398900, 409927646082434480, 401016175515425035, 392483916461905353, 384307168202282325, 376464164769582686, 368934881474191032, 361700864190383365, 354745078340568300, 348051774975651917, 341606371735362066, 335395346794719120, 329406144173384850, 323627089012448273, 318047311615681924, 312656679215416129, 307445734561825860, 302405640552615600, 297528130221121800, 292805461487453200, 288230376151711743, ]; // This is equivalent to `n_root_estimate` from `ulong_extras/root_estimate.c`, FLINT 2.7.1, where // `FLINT64` is `false`. fn root_estimate_32(a: f64, n: usize) -> u32 { let s = u32::low_mask(f32::EXPONENT_WIDTH - 1) << f32::MANTISSA_WIDTH; f32::from_bits(u32::x_mul_y_to_zz((a as f32).to_bits() - s, MUL_FACTOR_32[n]).0 + s) as u32 } // This is equivalent to `n_root_estimate` from `ulong_extras/root_estimate.c`, FLINT 2.7.1, where // `FLINT64` is `true`. fn root_estimate_64(a: f64, n: usize) -> u64 { let s = u64::low_mask(f64::EXPONENT_WIDTH - 1) << f64::MANTISSA_WIDTH; f64::from_bits(u64::x_mul_y_to_zz(a.to_bits() - s, MUL_FACTOR_64[n]).0 + s) as u64 } const INV_TABLE: [f64; 65] = [ 0.000000000000000, 1.000000000000000, 0.500000000000000, 0.333333333333333, 0.250000000000000, 0.200000000000000, 0.166666666666667, 0.142857142857143, 0.125000000000000, 0.111111111111111, 0.100000000000000, 0.090909090909091, 0.083333333333333, 0.076923076923077, 0.071428571428571, 0.066666666666667, 0.062500000000000, 0.058823529411765, 0.055555555555556, 0.052631578947368, 0.050000000000000, 0.047619047619048, 0.045454545454545, 0.043478260869565, 0.041666666666667, 0.040000000000000, 0.038461538461538, 0.037037037037037, 0.035714285714286, 0.034482758620690, 0.033333333333333, 0.032258064516129, 0.031250000000000, 0.030303030303030, 0.029411764705882, 0.028571428571429, 0.027777777777778, 0.027027027027027, 0.026315789473684, 0.025641025641026, 0.025000000000000, 0.024390243902439, 0.023809523809524, 0.023255813953488, 0.022727272727273, 0.022222222222222, 0.021739130434783, 0.021276595744681, 0.020833333333333, 0.020408163265306, 0.020000000000000, 0.019607843137255, 0.019230769230769, 0.018867924528302, 0.018518518518519, 0.018181818181818, 0.017857142857143, 0.017543859649123, 0.017241379310345, 0.016949152542373, 0.016666666666667, 0.016393442622951, 0.016129032258065, 0.015873015873016, 0.015625000000000, ]; // This is equivalent to `n_root` from `ulong_extras/root.c`, FLINT 2.7.1, where `FLINT64` is // `false` and `root` is nonzero. pub_test! {fast_floor_root_u32(n: u32, exp: u64) -> u32 { assert_ne!(exp, 0); if n < 2 || exp == 1 { return n; } else if exp >= u32::WIDTH || n.significant_bits() <= exp { return 1; } else if exp == 2 { return n.floor_sqrt(); } else if exp == 3 { return cbrt_chebyshev_approx_u32(n); } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_32[exp_usize]; // n <= upper_limit ^ exp let x = root_estimate_32(f64::from(n), exp_usize); // one round of Newton iteration let mut root = u32::rounding_from( (f64::from(n / x.pow(exp - 1)) - f64::from(x)) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return root; } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } root }} // This is equivalent to `n_root` from `ulong_extras/root.c`, FLINT 2.7.1, where `FLINT64` is `true` // and `root` is nonzero. pub_test! {fast_floor_root_u64(n: u64, exp: u64) -> u64 { assert_ne!(exp, 0); if n < 2 || exp == 1 { return n; } else if exp == 2 { return n.floor_sqrt(); } else if exp == 3 { return cbrt_chebyshev_approx_u64(n); } else if exp >= u64::WIDTH || (1 << exp) > n { return 1; } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_64[exp_usize]; // n <= upper_limit ^ exp let x = root_estimate_64(n as f64, exp_usize); // one round of Newton iteration let mut root = u64::rounding_from( (((n / x.saturating_pow(exp - 1)) as f64) - x as f64) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return root; } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } root }} pub_test! {fast_ceiling_root_u32(n: u32, exp: u64) -> u32 { assert_ne!(exp, 0); if n < 2 || exp == 1 { return n; } if exp >= u32::WIDTH || n.significant_bits() <= exp { return 2; } if exp == 2 { return n.ceiling_sqrt(); } if exp == 3 { let root = cbrt_chebyshev_approx_u32(n); return if root.pow(3) == n { root } else { root + 1 }; } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_32[exp_usize]; // n <= upper_limit ^ exp let x = root_estimate_32(f64::from(n), exp_usize); // one round of Newton iteration let mut root = u32::rounding_from( (f64::from(n / x.pow(exp - 1)) - f64::from(x)) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return root; } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } if pow == n { root } else { root + 1 } }} pub_test! {fast_ceiling_root_u64(n: u64, exp: u64) -> u64 { assert_ne!(exp, 0); if n < 2 || exp == 1 { return n; } if exp >= u64::WIDTH || n.significant_bits() <= exp { return 2; } if exp == 2 { return n.ceiling_sqrt(); } if exp == 3 { let root = cbrt_chebyshev_approx_u64(n); return if root.pow(3) == n { root } else { root + 1 }; } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_64[exp_usize]; // n <= upper_limit ^ root let x = root_estimate_64(n as f64, exp_usize); // one round of Newton iteration let mut root = u64::rounding_from( (((n / x.wrapping_pow(exp - 1)) as f64) - x as f64) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return root; } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } if pow == n { root } else { root + 1 } }} pub_test! {fast_checked_root_u32(n: u32, exp: u64) -> Option { assert_ne!(exp, 0); if n < 2 || exp == 1 { return Some(n); } if exp >= u32::WIDTH || n.significant_bits() <= exp { return None; } if exp == 2 { return n.checked_sqrt(); } if exp == 3 { let root = cbrt_chebyshev_approx_u32(n); return if root.pow(3) == n { Some(root) } else { None }; } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_32[exp_usize]; // n <= upper_limit ^ exp let x = root_estimate_32(f64::from(n), exp_usize); // one round of Newton iteration let mut root = u32::rounding_from( (f64::from(n / x.pow(exp - 1)) - f64::from(x)) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return Some(root); } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } if pow == n { Some(root) } else { None } }} pub_test! {fast_checked_root_u64(n: u64, exp: u64) -> Option { assert_ne!(exp, 0); if n < 2 || exp == 1 { return Some(n); } if exp >= u64::WIDTH || n.significant_bits() <= exp { return None; } if exp == 2 { return n.checked_sqrt(); } if exp == 3 { let root = cbrt_chebyshev_approx_u64(n); return if root.pow(3) == n { Some(root) } else { None }; } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_64[exp_usize]; // n <= upper_limit ^ root let x = root_estimate_64(n as f64, exp_usize); // one round of Newton iteration let mut root = u64::rounding_from( (((n / x.wrapping_pow(exp - 1)) as f64) - x as f64) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return Some(root); } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } if pow == n { Some(root) } else { None } }} pub_test! {fast_root_rem_u32(n: u32, exp: u64) -> (u32, u32) { assert_ne!(exp, 0); if n < 2 || exp == 1 { return (n, 0); } if exp >= u32::WIDTH || n.significant_bits() <= exp { return (1, n - 1); } if exp == 2 { return n.sqrt_rem(); } if exp == 3 { let root = cbrt_chebyshev_approx_u32(n); let pow = root.pow(3); return (root, n - pow); } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_32[exp_usize]; // n <= upper_limit ^ exp let x = root_estimate_32(f64::from(n), exp_usize); // one round of Newton iteration let mut root = u32::rounding_from( (f64::from(n / x.pow(exp - 1)) - f64::from(x)) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return (root, 0); } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } (root, n - pow) }} pub_test! {fast_root_rem_u64(n: u64, exp: u64) -> (u64, u64) { assert_ne!(exp, 0); if n < 2 || exp == 1 { return (n, 0); } if exp >= u64::WIDTH || n.significant_bits() <= exp { return (1, n - 1); } if exp == 2 { return n.sqrt_rem(); } if exp == 3 { let root = cbrt_chebyshev_approx_u64(n); let pow = root.pow(3); return (root, n - pow); } let exp = u32::wrapping_from(exp); let exp_usize = usize::wrapping_from(exp); let upper_limit = MAX_BASE_64[exp_usize]; // n <= upper_limit ^ root let x = root_estimate_64(n as f64, exp_usize); // one round of Newton iteration let mut root = u64::rounding_from( (((n / x.wrapping_pow(exp - 1)) as f64) - x as f64) * INV_TABLE[exp_usize], Down, ).0; if root >= upper_limit { root = upper_limit - 1; } let mut pow = root.pow(exp); if pow == n { return (root, 0); } while pow <= n { root += 1; pow = root.pow(exp); if root == upper_limit { break; } } while pow > n { root -= 1; pow = root.pow(exp); } (root, n - pow) }} #[cfg(feature = "test_build")] pub fn floor_root_binary(x: T, exp: u64) -> T { if exp == 0 { panic!("Cannot take 0th root"); } else if exp == 1 || x < T::TWO { x } else { let bits = x.significant_bits(); if bits <= exp { T::ONE } else { let p = T::power_of_2(bits.div_round(exp, Ceiling).0); floor_inverse_checked_binary(|i| i.checked_pow(exp), x, p >> 1, p) } } } #[cfg(feature = "test_build")] pub fn ceiling_root_binary(x: T, exp: u64) -> T { let floor_root = floor_root_binary(x, exp); if floor_root.pow(exp) == x { floor_root } else { floor_root + T::ONE } } #[cfg(feature = "test_build")] pub fn checked_root_binary(x: T, exp: u64) -> Option { let floor_root = floor_root_binary(x, exp); if floor_root.pow(exp) == x { Some(floor_root) } else { None } } #[cfg(feature = "test_build")] pub fn root_rem_binary(x: T, exp: u64) -> (T, T) { let floor_root = floor_root_binary(x, exp); (floor_root, x - floor_root.pow(exp)) } impl FloorRoot for u8 { type Output = Self; /// Returns the floor of the $n$th root of a [`u8`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#floor_root). /// /// # Notes /// The [`u8`] implementation uses lookup tables. #[inline] fn floor_root(self, exp: u64) -> Self { match (self, exp) { (_, 0) => panic!(), (0 | 1, _) | (_, 1) => self, (_, 8..=u64::MAX) => 1, (x, 2) => x.floor_sqrt(), (x, 3) => Self::wrapping_from(match U8_CUBES.binary_search(&x) { Ok(i) => i, Err(i) => i - 1, }), (x, 4) if x < 16 => 1, (x, 4) if x < 81 => 2, (x, 5) if x < 32 => 1, (x, 5) if x < 243 => 2, (_, 4 | 5) => 3, (x, 6) if x < 64 => 1, (x, 7) if x < 128 => 1, (_, 6 | 7) => 2, } } } impl CeilingRoot for u8 { type Output = Self; /// Returns the ceiling of the $n$th root of a [`u8`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// The [`u8`] implementation uses lookup tables. fn ceiling_root(self, exp: u64) -> Self { match (self, exp) { (_, 0) => panic!(), (0 | 1, _) | (_, 1) => self, (_, 8..=u64::MAX) => 2, (x, 2) => x.ceiling_sqrt(), (x, 3) => Self::wrapping_from(match U8_CUBES.binary_search(&x) { Ok(i) | Err(i) => i, }), (x, 4) if x <= 16 => 2, (x, 4) if x <= 81 => 3, (x, 5) if x <= 32 => 2, (x, 5) if x <= 243 => 3, (_, 4 | 5) => 4, (x, 6) if x <= 64 => 2, (x, 7) if x <= 128 => 2, (_, 6 | 7) => 3, } } } impl CheckedRoot for u8 { type Output = Self; /// Returns the the $n$th root of a [`u8`], or `None` if the [`u8`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// The [`u8`] implementation uses lookup tables. fn checked_root(self, exp: u64) -> Option { match (self, exp) { (_, 0) => panic!(), (0 | 1, _) | (_, 1) => Some(self), (x, 2) => x.checked_sqrt(), (x, 3) => U8_CUBES.binary_search(&x).ok().map(Self::wrapping_from), (16, 4) | (32, 5) | (64, 6) | (128, 7) => Some(2), (81, 4) | (243, 5) => Some(3), _ => None, } } } impl RootRem for u8 { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`u8`], and the remainder (the difference between /// the [`u8`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// The [`u8`] implementation uses lookup tables. fn root_rem(self, exp: u64) -> (Self, Self) { match (self, exp) { (_, 0) => panic!(), (0 | 1, _) | (_, 1) => (self, 0), (x, 8..=u64::MAX) => (1, x - 1), (x, 2) => x.sqrt_rem(), (x, 3) => match U8_CUBES.binary_search(&x) { Ok(i) => (Self::wrapping_from(i), 0), Err(i) => (Self::wrapping_from(i - 1), x - U8_CUBES[i - 1]), }, (x, 4) if x < 16 => (1, x - 1), (x, 4) if x < 81 => (2, x - 16), (x, 4) => (3, x - 81), (x, 5) if x < 32 => (1, x - 1), (x, 5) if x < 243 => (2, x - 32), (x, 5) => (3, x - 243), (x, 6) if x < 64 => (1, x - 1), (x, 6) => (2, x - 64), (x, 7) if x < 128 => (1, x - 1), (x, 7) => (2, x - 128), } } } impl FloorRoot for u16 { type Output = Self; /// Returns the floor of the $n$th root of a [`u16`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn floor_root(self, exp: u64) -> Self { Self::wrapping_from(u32::from(self).floor_root(exp)) } } impl CeilingRoot for u16 { type Output = Self; /// Returns the ceiling of the $n$th root of a [`u16`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn ceiling_root(self, exp: u64) -> Self { Self::wrapping_from(u32::from(self).ceiling_root(exp)) } } impl CheckedRoot for u16 { type Output = Self; /// Returns the the $n$th root of a [`u16`], or `None` if the [`u16`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn checked_root(self, exp: u64) -> Option { u32::from(self).checked_root(exp).map(Self::wrapping_from) } } impl RootRem for u16 { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`u16`], and the remainder (the difference between /// the [`u16`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn root_rem(self, exp: u64) -> (Self, Self) { let (sqrt, rem) = u32::from(self).root_rem(exp); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } } impl FloorRoot for u32 { type Output = Self; /// Returns the floor of the $n$th root of a [`u32`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#floor_root). /// /// # Notes /// For cube roots, the [`u32`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn floor_root(self, exp: u64) -> Self { fast_floor_root_u32(self, exp) } } impl CeilingRoot for u32 { type Output = Self; /// Returns the ceiling of the $n$th root of a [`u32`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// For cube roots, the [`u32`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn ceiling_root(self, exp: u64) -> Self { fast_ceiling_root_u32(self, exp) } } impl CheckedRoot for u32 { type Output = Self; /// Returns the the $n$th root of a [`u32`], or `None` if the [`u32`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// For cube roots, the [`u32`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn checked_root(self, exp: u64) -> Option { fast_checked_root_u32(self, exp) } } impl RootRem for u32 { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`u32`], and the remainder (the difference between /// the [`u32`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// For cube roots, the [`u32`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn root_rem(self, exp: u64) -> (Self, Self) { fast_root_rem_u32(self, exp) } } impl FloorRoot for u64 { type Output = Self; /// Returns the floor of the $n$th root of a [`u64`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#floor_root). /// /// # Notes /// For cube roots, the [`u64`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn floor_root(self, exp: Self) -> Self { fast_floor_root_u64(self, exp) } } impl CeilingRoot for u64 { type Output = Self; /// Returns the ceiling of the $n$th root of a [`u64`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// For cube roots, the [`u64`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn ceiling_root(self, exp: Self) -> Self { fast_ceiling_root_u64(self, exp) } } impl CheckedRoot for u64 { type Output = Self; /// Returns the the $n$th root of a [`u64`], or `None` if the [`u64`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// For cube roots, the [`u64`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn checked_root(self, exp: Self) -> Option { fast_checked_root_u64(self, exp) } } impl RootRem for u64 { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`u64`], and the remainder (the difference between /// the [`u64`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// For cube roots, the [`u64`] implementation uses a piecewise Chebyshev approximation. For /// other roots, it uses Newton's method. In both implementations, the result of these /// approximations is adjusted afterwards to account for error. #[inline] fn root_rem(self, exp: Self) -> (Self, Self) { fast_root_rem_u64(self, exp) } } impl FloorRoot for usize { type Output = Self; /// Returns the floor of the $n$th root of a [`usize`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#floor_root). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn floor_root(self, exp: u64) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).floor_root(exp)) } else { Self::wrapping_from(u64::wrapping_from(self).floor_root(exp)) } } } impl CeilingRoot for usize { type Output = Self; /// Returns the ceiling of the $n$th root of a [`usize`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn ceiling_root(self, exp: u64) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).ceiling_root(exp)) } else { Self::wrapping_from(u64::wrapping_from(self).ceiling_root(exp)) } } } impl CheckedRoot for usize { type Output = Self; /// Returns the the $n$th root of a [`usize`], or `None` if the [`usize`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn checked_root(self, exp: u64) -> Option { if USIZE_IS_U32 { u32::wrapping_from(self) .checked_root(exp) .map(Self::wrapping_from) } else { u64::wrapping_from(self) .checked_root(exp) .map(Self::wrapping_from) } } } impl RootRem for usize { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`usize`], and the remainder (the difference /// between the [`usize`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn root_rem(self, exp: u64) -> (Self, Self) { if USIZE_IS_U32 { let (sqrt, rem) = u32::wrapping_from(self).root_rem(exp); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } else { let (sqrt, rem) = u64::wrapping_from(self).root_rem(exp); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } } } impl FloorRoot for u128 { type Output = Self; /// Returns the floor of the $n$th root of a [`u128`]. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#floor_root). /// /// # Notes /// The [`u128`] implementation computes the root using floating-point arithmetic. The /// approximate result is adjusted afterwards to account for error. fn floor_root(self, exp: u64) -> Self { if exp == 2 { return self.floor_sqrt(); } floor_root_approx_and_refine(|x| x as f64, |x| x as Self, self, exp) } } impl CeilingRoot for u128 { type Output = Self; /// Returns the ceiling of the $n$th root of a [`u128`]. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#ceiling_root). /// /// # Notes /// The [`u128`] implementation computes the root using floating-point arithmetic. The /// approximate result is adjusted afterwards to account for error. fn ceiling_root(self, exp: u64) -> Self { if exp == 2 { return self.ceiling_sqrt(); } let root = floor_root_approx_and_refine(|x| x as f64, |x| x as Self, self, exp); if root.pow(u32::saturating_from(exp)) == self { root } else { root + 1 } } } impl CheckedRoot for u128 { type Output = Self; /// Returns the the $n$th root of a [`u128`], or `None` if the [`u128`] is not a perfect $n$th /// power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#checked_root). /// /// # Notes /// The [`u128`] implementation computes the root using floating-point arithmetic. The /// approximate result is adjusted afterwards to account for error. fn checked_root(self, exp: u64) -> Option { if exp == 2 { return self.checked_sqrt(); } let root = floor_root_approx_and_refine(|x| x as f64, |x| x as Self, self, exp); if root.pow(u32::saturating_from(exp)) == self { Some(root) } else { None } } } impl RootRem for u128 { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`u128`], and the remainder (the difference between /// the [`u128`] and the $n$th power of the floor). /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^n)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_rem). /// /// # Notes /// The [`u128`] implementation computes the root using floating-point arithmetic. The /// approximate result is adjusted afterwards to account for error. fn root_rem(self, exp: u64) -> (Self, Self) { if exp == 2 { return self.sqrt_rem(); } let root = floor_root_approx_and_refine(|x| x as f64, |x| x as Self, self, exp); (root, self - root.pow(u32::saturating_from(exp))) } } macro_rules! impl_root_assign_rem { ($t: ident) => { impl RootAssignRem for $t { type RemOutput = $t; /// Replaces an integer with the floor of its $n$th root, and returns the remainder (the /// difference between the original integer and the $n$th power of the floor). /// /// $f(x, n) = x - \lfloor\sqrt\[n\]{x}\rfloor^n$, /// /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// See [here](super::root#root_assign_rem). #[inline] fn root_assign_rem(&mut self, exp: u64) -> $t { let rem; (*self, rem) = self.root_rem(exp); rem } } }; } apply_to_unsigneds!(impl_root_assign_rem); macro_rules! impl_root_signed { ($t: ident) => { impl FloorRoot for $t { type Output = $t; /// Returns the floor of the $n$th root of an integer. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero, or if `self` is negative and `exp` is even. /// /// # Examples /// See [here](super::root#floor_root). #[inline] fn floor_root(self, exp: u64) -> $t { if self >= 0 { $t::wrapping_from(self.unsigned_abs().floor_root(exp)) } else if exp.odd() { $t::wrapping_from(self.unsigned_abs().ceiling_root(exp)).wrapping_neg() } else { panic!("Cannot take even root of a negative number"); } } } impl CeilingRoot for $t { type Output = $t; /// Returns the ceiling of the $n$th root of an integer. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero, or if `self` is negative and `exp` is even. /// /// # Examples /// See [here](super::root#ceiling_root). #[inline] fn ceiling_root(self, exp: u64) -> $t { if self >= 0 { $t::wrapping_from(self.unsigned_abs().ceiling_root(exp)) } else if exp.odd() { $t::wrapping_from(self.unsigned_abs().floor_root(exp)).wrapping_neg() } else { panic!("Cannot take even root of a negative number"); } } } impl CheckedRoot for $t { type Output = $t; /// Returns the the $n$th root of an integer, or `None` if the integer is not a perfect /// $n$th power. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero, or if `self` is negative and `exp` is even. /// /// # Examples /// See [here](super::root#checked_root). #[inline] fn checked_root(self, exp: u64) -> Option<$t> { if self >= 0 { self.unsigned_abs().checked_root(exp).map($t::wrapping_from) } else if exp.odd() { self.unsigned_abs() .checked_root(exp) .map(|x| $t::wrapping_from(x).wrapping_neg()) } else { panic!("Cannot take even root of a negative number"); } } } }; } apply_to_signeds!(impl_root_signed); macro_rules! impl_root_primitive_int { ($t: ident) => { impl FloorRootAssign for $t { /// Replaces an integer with the floor of its $n$th root. /// /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero, or if `self` is negative and `exp` is even. /// /// # Examples /// See [here](super::root#floor_root_assign). #[inline] fn floor_root_assign(&mut self, exp: u64) { *self = self.floor_root(exp); } } impl CeilingRootAssign for $t { /// Replaces an integer with the ceiling of its $n$th root. /// /// $x \gets \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exp` is zero, or if `self` is negative and `exp` is even. /// /// # Examples /// See [here](super::root#ceiling_root_assign). #[inline] fn ceiling_root_assign(&mut self, exp: u64) { *self = self.ceiling_root(exp); } } }; } apply_to_primitive_ints!(impl_root_primitive_int); ================================================ FILE: malachite-base/src/num/arithmetic/rotate.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ RotateLeft, RotateLeftAssign, RotateRight, RotateRightAssign, }; use crate::num::conversion::traits::WrappingFrom; macro_rules! impl_rotate { ($t:ident) => { impl RotateLeft for $t { type Output = $t; /// This is a wrapper over the `rotate_left` functions in the standard library, for /// example [this one](u32::rotate_left). #[inline] fn rotate_left(self, n: u64) -> $t { $t::rotate_left(self, u32::wrapping_from(n)) } } impl RotateLeftAssign for $t { /// Rotates a number left, in place. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::rotate#rotate_left_assign). #[inline] fn rotate_left_assign(&mut self, n: u64) { *self = self.rotate_left(u32::wrapping_from(n)); } } impl RotateRight for $t { type Output = $t; /// This is a wrapper over the `rotate_right` functions in the standard library, for /// example [this one](u32::rotate_right). #[inline] fn rotate_right(self, n: u64) -> $t { $t::rotate_right(self, u32::wrapping_from(n)) } } impl RotateRightAssign for $t { /// Rotates a number right, in place. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::rotate#rotate_right_assign). #[inline] fn rotate_right_assign(&mut self, n: u64) { *self = self.rotate_right(u32::wrapping_from(n)); } } }; } apply_to_primitive_ints!(impl_rotate); ================================================ FILE: malachite-base/src/num/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactFrom; use crate::rounding_modes::RoundingMode::{self, *}; use core::cmp::Ordering::{self, *}; fn round_to_multiple_unsigned( x: T, other: T, rm: RoundingMode, ) -> (T, Ordering) { match (x, other) { (x, y) if x == y => (x, Equal), (x, y) if y == T::ZERO => match rm { Down | Floor | Nearest => (T::ZERO, Less), _ => panic!("Cannot round {x} to zero using RoundingMode {rm}"), }, (x, y) => { let r = x % y; if r == T::ZERO { (x, Equal) } else { let floor = x - r; match rm { Down | Floor => (floor, Less), Up | Ceiling => (floor.checked_add(y).unwrap(), Greater), Nearest => { match r.cmp(&(y >> 1)) { Less => (floor, Less), Greater => (floor.checked_add(y).unwrap(), Greater), Equal => { if y.odd() { (floor, Less) } else { // The even multiple of y will have more trailing zeros. let (ceiling, overflow) = floor.overflowing_add(y); if floor.trailing_zeros() > ceiling.trailing_zeros() { (floor, Less) } else if overflow { panic!("Cannot round {x} to {y} using RoundingMode {rm}"); } else { (ceiling, Greater) } } } } } Exact => { panic!("Cannot round {x} to {y} using RoundingMode {rm}") } } } } } } macro_rules! impl_round_to_multiple_unsigned { ($t:ident) => { impl RoundToMultiple<$t> for $t { type Output = $t; /// Rounds a number to a multiple of another number, according to a specified rounding /// mode. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// The only rounding modes that are guaranteed to return without a panic are `Down` and /// `Floor`. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \N$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If the multiple is outside the representable range. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// See [here](super::round_to_multiple#round_to_multiple). #[inline] fn round_to_multiple(self, other: $t, rm: RoundingMode) -> ($t, Ordering) { round_to_multiple_unsigned(self, other, rm) } } impl RoundToMultipleAssign<$t> for $t { /// Rounds a number to a multiple of another number in place, according to a specified /// rounding mode. An [`Ordering`] is returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// The only rounding modes that are guaranteed to return without a panic are `Down` and /// `Floor`. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If the multiple is outside the representable range. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// See [here](super::round_to_multiple#round_to_multiple_assign). #[inline] fn round_to_multiple_assign(&mut self, other: $t, rm: RoundingMode) -> Ordering { let o; (*self, o) = self.round_to_multiple(other, rm); o } } }; } apply_to_unsigneds!(impl_round_to_multiple_unsigned); fn round_to_multiple_signed< U: PrimitiveUnsigned, S: ExactFrom + PrimitiveSigned + UnsignedAbs, >( x: S, other: S, rm: RoundingMode, ) -> (S, Ordering) { if x >= S::ZERO { let (m, o) = x.unsigned_abs().round_to_multiple(other.unsigned_abs(), rm); (S::exact_from(m), o) } else { let (abs_result, o) = x .unsigned_abs() .round_to_multiple(other.unsigned_abs(), -rm); ( if abs_result == S::MIN.unsigned_abs() { S::MIN } else { S::exact_from(abs_result).checked_neg().unwrap() }, o.reverse(), ) } } macro_rules! impl_round_to_multiple_signed { ($t:ident) => { impl RoundToMultiple<$t> for $t { type Output = $t; /// Rounds a number to a multiple of another number, according to a specified rounding /// mode. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// The only rounding mode that is guaranteed to return without a panic is `Down`. /// /// Let $q = \frac{x}{|y|}$: /// /// $f(x, y, \mathrm{Down}) = \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$ /// /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If the multiple is outside the representable range. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// See [here](super::round_to_multiple#round_to_multiple). #[inline] fn round_to_multiple(self, other: $t, rm: RoundingMode) -> ($t, Ordering) { round_to_multiple_signed(self, other, rm) } } impl RoundToMultipleAssign<$t> for $t { /// Rounds a number to a multiple of another number in place, according to a specified /// rounding mode. An [`Ordering`] is returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// The only rounding mode that is guaranteed to return without a panic is `Down`. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If the multiple is outside the representable range. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// See [here](super::round_to_multiple#round_to_multiple_assign). #[inline] fn round_to_multiple_assign(&mut self, other: $t, rm: RoundingMode) -> Ordering { let o; (*self, o) = self.round_to_multiple(other, rm); o } } }; } apply_to_signeds!(impl_round_to_multiple_signed); ================================================ FILE: malachite-base/src/num/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign}; use crate::num::basic::integers::PrimitiveInt; use crate::rounding_modes::RoundingMode; use core::cmp::Ordering; fn round_to_multiple_of_power_of_2( x: T, pow: u64, rm: RoundingMode, ) -> (T, Ordering) { let (s, o) = x.shr_round(pow, rm); (s.arithmetic_checked_shl(pow).unwrap(), o) } macro_rules! impl_round_to_multiple_of_power_of_2 { ($t:ident) => { impl RoundToMultipleOfPowerOf2 for $t { type Output = $t; /// Rounds a number to a multiple of $2^k$ according to a specified rounding mode. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, /// equal to, or greater than the original value. /// /// The only rounding mode that is guaranteed to return without a panic is `Down`. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = 2^k \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = 2^k \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2(pow, Exact)` /// - `{ assert!(x.divisible_by_power_of_2(pow)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// - If `rm` is `Floor`, but `self` is negative with a too-large absolute value to /// round to the next lowest multiple. /// - If `rm` is `Ceiling`, but `self` is too large to round to the next highest /// multiple. /// - If `rm` is `Up`, but `self` has too large an absolute value to round to the next /// multiple with a greater absolute value. /// - If `rm` is `Nearest`, but the nearest multiple is outside the representable range. /// /// # Examples /// See [here](super::round_to_multiple_of_power_of_2#round_to_multiple_of_power_of_2). #[inline] fn round_to_multiple_of_power_of_2(self, pow: u64, rm: RoundingMode) -> ($t, Ordering) { round_to_multiple_of_power_of_2(self, pow, rm) } } impl RoundToMultipleOfPowerOf2Assign for $t { /// Rounds a number to a multiple of $2^k$ in place, according to a specified rounding /// mode. An [`Ordering`] is returned, indicating whether the returned value is less /// than, equal to, or greater than the original value. /// /// The only rounding mode that is guaranteed to return without a panic is `Down`. /// /// See the [`RoundToMultipleOfPowerOf2`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2_assign(pow, Exact);` /// - `assert!(x.divisible_by_power_of_2(pow));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// - If `rm` is `Floor`, but `self` is negative with a too-large absolute value to /// round to the next lowest multiple. /// - If `rm` is `Ceiling`, but `self` is too large to round to the next highest /// multiple. /// - If `rm` is `Up`, but `self` has too large an absolute value to round to the next /// multiple with a greater absolute value. /// - If `rm` is `Nearest`, but the nearest multiple is outside the representable range. /// /// # Examples /// See /// [here](super::round_to_multiple_of_power_of_2#round_to_multiple_of_power_of_2_assign). #[inline] fn round_to_multiple_of_power_of_2_assign( &mut self, pow: u64, rm: RoundingMode, ) -> Ordering { let o; (*self, o) = self.round_to_multiple_of_power_of_2(pow, rm); o } } }; } apply_to_primitive_ints!(impl_round_to_multiple_of_power_of_2); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingAbs, SaturatingAbsAssign}; macro_rules! impl_saturating_abs { ($t:ident) => { impl SaturatingAbs for $t { type Output = $t; /// This is a wrapper over the `saturating_abs` functions in the standard library, for /// example [this one](i32::saturating_abs). #[inline] fn saturating_abs(self) -> $t { $t::saturating_abs(self) } } impl SaturatingAbsAssign for $t { /// Replaces a number with its absolute value, saturating at the numeric bounds instead /// of overflowing. /// /// $$ /// x \gets \\begin{cases} /// |x| & \text{if} \\quad x > -2^{W-1}, \\\\ /// 2^{W-1} - 1 & \text{if} \\quad x = -2^{W-1}, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_abs#saturating_abs_assign). #[inline] fn saturating_abs_assign(&mut self) { *self = self.saturating_abs(); } } }; } apply_to_signeds!(impl_saturating_abs); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_add.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingAdd, SaturatingAddAssign}; macro_rules! impl_saturating_add { ($t:ident) => { impl SaturatingAdd<$t> for $t { type Output = $t; /// This is a wrapper over the `saturating_add` functions in the standard library, for /// example [this one](i32::saturating_add). #[inline] fn saturating_add(self, other: $t) -> $t { $t::saturating_add(self, other) } } impl SaturatingAddAssign<$t> for $t { /// Adds a number to another number, in place, saturating at the numeric bounds instead /// of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x + y & \text{if} \\quad m \leq x + y \leq M, \\\\ /// M & \text{if} \\quad x + y > M, \\\\ /// m & \text{if} \\quad x + y < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_add#saturating_add_assign). #[inline] fn saturating_add_assign(&mut self, other: $t) { *self = self.saturating_add(other); } } }; } apply_to_primitive_ints!(impl_saturating_add); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_add_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingAddMul, SaturatingAddMulAssign, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; fn saturating_add_mul_unsigned(x: T, y: T, z: T) -> T { x.saturating_add(y.saturating_mul(z)) } fn saturating_add_mul_assign_unsigned(x: &mut T, y: T, z: T) { x.saturating_add_assign(y.saturating_mul(z)); } macro_rules! impl_saturating_add_mul_unsigned { ($t:ident) => { impl SaturatingAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers, saturating at the numeric bounds /// instead of overflowing. /// /// $$ /// f(x, y, z) = \\begin{cases} /// x + yz & \text{if} \\quad m \leq x + yz \leq M, \\\\ /// M & \text{if} \\quad x + yz > M, \\\\ /// m & \text{if} \\quad x + yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_add_mul#saturating_add_mul). #[inline] fn saturating_add_mul(self, y: $t, z: $t) -> $t { saturating_add_mul_unsigned(self, y, z) } } impl SaturatingAddMulAssign<$t> for $t { /// Adds a number and the product of two other numbers in place, saturating at the /// numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x + yz & \text{if} \\quad m \leq x + yz \leq M, \\\\ /// M & \text{if} \\quad x + yz > M, \\\\ /// m & \text{if} \\quad x + yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_add#saturating_add_mul_assign). #[inline] fn saturating_add_mul_assign(&mut self, y: $t, z: $t) { saturating_add_mul_assign_unsigned(self, y, z); } } }; } apply_to_unsigneds!(impl_saturating_add_mul_unsigned); fn saturating_add_mul_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: S, y: S, z: S, ) -> S { if y == S::ZERO || z == S::ZERO { return x; } let x_sign = x >= S::ZERO; if x_sign == ((y >= S::ZERO) == (z >= S::ZERO)) { x.saturating_add(y.saturating_mul(z)) } else { let x = x.unsigned_abs(); let product = if let Some(product) = y.unsigned_abs().checked_mul(z.unsigned_abs()) { product } else { return if x_sign { S::MIN } else { S::MAX }; }; let result = S::wrapping_from(if x_sign { x.wrapping_sub(product) } else { product.wrapping_sub(x) }); if x >= product || (x_sign == (result < S::ZERO)) { result } else if x_sign { S::MIN } else { S::MAX } } } macro_rules! impl_saturating_add_mul_signed { ($t:ident) => { impl SaturatingAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers, saturating at the numeric bounds /// instead of overflowing. /// /// $$ /// f(x, y, z) = \\begin{cases} /// x + yz & \text{if} \\quad m \leq x + yz \leq M, \\\\ /// M & \text{if} \\quad x + yz > M, \\\\ /// m & \text{if} \\quad x + yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_add_mul#saturating_add_mul_assign). #[inline] fn saturating_add_mul(self, y: $t, z: $t) -> $t { saturating_add_mul_signed(self, y, z) } } impl SaturatingAddMulAssign<$t> for $t { /// Adds a number and the product of two other numbers in place, saturating at the /// numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x + yz & \text{if} \\quad m \leq x + yz \leq M, \\\\ /// M & \text{if} \\quad x + yz > M, \\\\ /// m & \text{if} \\quad x + yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_add_mul#saturating_add_mul_assign). #[inline] fn saturating_add_mul_assign(&mut self, y: $t, z: $t) { *self = self.saturating_add_mul(y, z); } } }; } apply_to_signeds!(impl_saturating_add_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingMul, SaturatingMulAssign}; macro_rules! impl_saturating_mul { ($t:ident) => { impl SaturatingMul<$t> for $t { type Output = $t; /// This is a wrapper over the `saturating_mul` functions in the standard library, for /// example [this one](i32::saturating_mul). #[inline] fn saturating_mul(self, other: $t) -> $t { $t::saturating_mul(self, other) } } impl SaturatingMulAssign<$t> for $t { /// Multiplies a number by another number, in place, saturating at the numeric bounds /// instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// xy & \text{if} \\quad m \leq xy \leq M, \\\\ /// M & \text{if} \\quad xy > M, \\\\ /// m & \text{if} \\quad xy < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_mul#saturating_mul_assign). #[inline] fn saturating_mul_assign(&mut self, other: $t) { *self = self.saturating_mul(other); } } }; } apply_to_primitive_ints!(impl_saturating_mul); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingNeg, SaturatingNegAssign}; macro_rules! impl_saturating_neg { ($t:ident) => { impl SaturatingNeg for $t { type Output = $t; /// This is a wrapper over the `saturating_neg` functions in the standard library, for /// example [this one](i32::saturating_neg). #[inline] fn saturating_neg(self) -> $t { $t::saturating_neg(self) } } impl SaturatingNegAssign for $t { /// Negates a number in place, saturating at the numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// -x & \text{if} \\quad x^2 > -2^{W-1}, \\\\ /// 2^{W-1} - 1 & \text{if} \\quad x = -2^{W-1}, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_neg#saturating_neg_assign). #[inline] fn saturating_neg_assign(&mut self) { *self = self.saturating_neg(); } } }; } apply_to_signeds!(impl_saturating_neg); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Parity, SaturatingPow, SaturatingPowAssign}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; fn saturating_pow_unsigned(x: T, exp: u64) -> T { if exp == 0 { T::ONE } else if x < T::TWO { x } else if let Some(p) = x.checked_pow(exp) { p } else { T::MAX } } fn saturating_pow_signed(x: T, exp: u64) -> T { if exp == 0 { T::ONE } else if x == T::ZERO || x == T::ONE { x } else if x == T::NEGATIVE_ONE { if exp.even() { T::ONE } else { T::NEGATIVE_ONE } } else if let Some(p) = x.checked_pow(exp) { p } else if x > T::ZERO || exp.even() { T::MAX } else { T::MIN } } macro_rules! impl_saturating_pow_unsigned { ($t:ident) => { impl SaturatingPow for $t { type Output = $t; /// This is a wrapper over the `saturating_pow` functions in the standard library, for /// example [this one](u32::saturating_pow). #[inline] fn saturating_pow(self, exp: u64) -> $t { saturating_pow_unsigned(self, exp) } } }; } apply_to_unsigneds!(impl_saturating_pow_unsigned); macro_rules! impl_saturating_pow_signed { ($t:ident) => { impl SaturatingPow for $t { type Output = $t; /// This is a wrapper over the `saturating_pow` functions in the standard library, for /// example [this one](i32::saturating_pow). #[inline] fn saturating_pow(self, exp: u64) -> $t { saturating_pow_signed(self, exp) } } }; } apply_to_signeds!(impl_saturating_pow_signed); macro_rules! impl_saturating_pow_primitive_int { ($t:ident) => { impl SaturatingPowAssign for $t { /// Raises a number to a power, in place, saturating at the numeric bounds instead of /// overflowing. /// /// $$ /// x \gets \\begin{cases} /// x^y & \text{if} \\quad m \leq x^y \leq M, \\\\ /// M & \text{if} \\quad x^y > M, \\\\ /// m & \text{if} \\quad x^y < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_pow#saturating_pow_assign). #[inline] fn saturating_pow_assign(&mut self, exp: u64) { *self = SaturatingPow::saturating_pow(*self, exp); } } }; } apply_to_primitive_ints!(impl_saturating_pow_primitive_int); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ SaturatingMulAssign, SaturatingSquare, SaturatingSquareAssign, }; macro_rules! impl_saturating_square { ($t:ident) => { impl SaturatingSquare for $t { type Output = $t; /// Squares a number, saturating at the numeric bounds instead of overflowing. /// /// $$ /// f(x) = \\begin{cases} /// x^2 & \text{if} \\quad x^2 \leq M, \\\\ /// M & \text{if} \\quad x^2 > M, /// \\end{cases} /// $$ /// where $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_square#saturating_square). #[inline] fn saturating_square(self) -> $t { self.saturating_mul(self) } } impl SaturatingSquareAssign for $t { /// Squares a number in place, saturating at the numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x^2 & \text{if} \\quad x^2 \leq M, \\\\ /// M & \text{if} \\quad x^2 > M, /// \\end{cases} /// $$ /// where $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_square#saturating_square_assign). #[inline] fn saturating_square_assign(&mut self) { self.saturating_mul_assign(*self); } } }; } apply_to_primitive_ints!(impl_saturating_square); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingSub, SaturatingSubAssign}; macro_rules! impl_saturating_sub { ($t:ident) => { impl SaturatingSub<$t> for $t { type Output = $t; /// This is a wrapper over the `saturating_sub` functions in the standard library, for /// example [this one](i32::saturating_sub). #[inline] fn saturating_sub(self, other: $t) -> $t { $t::saturating_sub(self, other) } } impl SaturatingSubAssign<$t> for $t { /// Subtracts a number by another number in place, saturating at the numeric bounds /// instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x - y & \text{if} \\quad m \leq x - y \leq M, \\\\ /// M & \text{if} \\quad x - y > M, \\\\ /// m & \text{if} \\quad x - y < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_sub#saturating_sub_assign). #[inline] fn saturating_sub_assign(&mut self, other: $t) { *self = self.saturating_sub(other); } } }; } apply_to_primitive_ints!(impl_saturating_sub); ================================================ FILE: malachite-base/src/num/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingSubMul, SaturatingSubMulAssign, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; fn saturating_sub_mul_unsigned(x: T, y: T, z: T) -> T { x.saturating_sub(y.saturating_mul(z)) } fn saturating_sub_mul_assign_unsigned(x: &mut T, y: T, z: T) { x.saturating_sub_assign(y.saturating_mul(z)); } macro_rules! impl_saturating_sub_mul_unsigned { ($t:ident) => { impl SaturatingSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers, saturating at the numeric /// bounds instead of overflowing. /// /// $$ /// f(x, y, z) = \\begin{cases} /// x - yz & \text{if} \\quad m \leq x - yz \leq M, \\\\ /// M & \text{if} \\quad x - yz > M, \\\\ /// m & \text{if} \\quad x - yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_sub_mul#saturating_sub_mul_assign). #[inline] fn saturating_sub_mul(self, y: $t, z: $t) -> $t { saturating_sub_mul_unsigned(self, y, z) } } impl SaturatingSubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers in place, saturating at the /// numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x - yz & \text{if} \\quad m \leq x - yz \leq M, \\\\ /// M & \text{if} \\quad x - yz > M, \\\\ /// m & \text{if} \\quad x - yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_sub_mul#saturating_sub_mul_assign). #[inline] fn saturating_sub_mul_assign(&mut self, y: $t, z: $t) { saturating_sub_mul_assign_unsigned(self, y, z); } } }; } apply_to_unsigneds!(impl_saturating_sub_mul_unsigned); fn saturating_sub_mul_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: S, y: S, z: S, ) -> S { if y == S::ZERO || z == S::ZERO { return x; } let x_sign = x >= S::ZERO; if x_sign == ((y >= S::ZERO) != (z >= S::ZERO)) { x.saturating_sub(y.saturating_mul(z)) } else { let x = x.unsigned_abs(); let product = if let Some(product) = y.unsigned_abs().checked_mul(z.unsigned_abs()) { product } else { return if x_sign { S::MIN } else { S::MAX }; }; let result = S::wrapping_from(if x_sign { x.wrapping_sub(product) } else { product.wrapping_sub(x) }); if x >= product || (x_sign == (result < S::ZERO)) { result } else if x_sign { S::MIN } else { S::MAX } } } macro_rules! impl_saturating_sub_mul_signed { ($t:ident) => { impl SaturatingSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers, saturating at the numeric /// bounds instead of overflowing. /// /// $$ /// f(x, y, z) = \\begin{cases} /// x - yz & \text{if} \\quad m \leq x - yz \leq M, \\\\ /// M & \text{if} \\quad x - yz > M, \\\\ /// m & \text{if} \\quad x - yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_sub_mul#saturating_sub_mul). #[inline] fn saturating_sub_mul(self, y: $t, z: $t) -> $t { saturating_sub_mul_signed(self, y, z) } } impl SaturatingSubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers in place, saturating at the /// numeric bounds instead of overflowing. /// /// $$ /// x \gets \\begin{cases} /// x - yz & \text{if} \\quad m \leq x - yz \leq M, \\\\ /// M & \text{if} \\quad x - yz > M, \\\\ /// m & \text{if} \\quad x - yz < m, /// \\end{cases} /// $$ /// where $m$ is `Self::MIN` and $M$ is `Self::MAX`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::saturating_sub_mul#saturating_sub_mul_assign). #[inline] fn saturating_sub_mul_assign(&mut self, y: $t, z: $t) { *self = self.saturating_sub_mul(y, z); } } }; } apply_to_signeds!(impl_saturating_sub_mul_signed); ================================================ FILE: malachite-base/src/num/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ ShlRound, ShlRoundAssign, ShrRound, ShrRoundAssign, UnsignedAbs, }; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::rounding_modes::RoundingMode; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign}; fn shl_round< T: PrimitiveInt + Shl + ShrRound, U, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, rm: RoundingMode, ) -> (T, Ordering) { if bits >= S::ZERO { let width = S::wrapping_from(T::WIDTH); ( if width >= S::ZERO && bits >= width { T::ZERO } else { x << bits.unsigned_abs() }, Equal, ) } else { x.shr_round(bits.unsigned_abs(), rm) } } fn shl_round_assign< T: PrimitiveInt + ShlAssign + ShrRoundAssign, U, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, bits: S, rm: RoundingMode, ) -> Ordering { if bits >= S::ZERO { let width = S::wrapping_from(T::WIDTH); if width >= S::ZERO && bits >= width { *x = T::ZERO; } else { *x <<= bits.unsigned_abs(); } Equal } else { x.shr_round_assign(bits.unsigned_abs(), rm) } } macro_rules! impl_shl_round { ($t:ident) => { macro_rules! impl_shl_round_inner { ($u:ident) => { impl ShlRound<$u> for $t { type Output = $t; /// Left-shifts a number (multiplies it by a power of 2 or divides it by a power /// of 2 and takes the floor) and rounds according to the specified rounding /// mode. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the exact value. If `bits` is /// non-negative, then the returned [`Ordering`] is always `Equal`, even if the /// higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `bits > 0 || self.divisible_by_power_of_2(bits)`. /// Rounding might only be necessary if `bits` is negative. /// /// Let $q = x2^k$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is positive and `rm` is `Exact` but `self` is not divisible /// by $2^b$. /// /// # Examples /// See [here](super::shl_round#shl_round). #[inline] fn shl_round(self, bits: $u, rm: RoundingMode) -> ($t, Ordering) { shl_round(self, bits, rm) } } impl ShlRoundAssign<$u> for $t { /// Left-shifts a number (multiplies it by a power of 2 or divides it by a power /// of 2 and takes the floor) and rounds according to the specified rounding /// mode, in place. An [`Ordering`] is returned, indicating whether the assigned /// value is less than, equal to, or greater than the exact value. If `bits` is /// non-negative, then the returned [`Ordering`] is always `Equal`, even if the /// higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `bits > 0 || self.divisible_by_power_of_2(bits)`. /// Rounding might only be necessary if `bits` is negative. /// /// See the [`ShlRound`] documentation for details. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is positive and `rm` is `Exact` but `self` is not divisible /// by $2^b$. /// /// # Examples /// See [here](super::shl_round#shl_round_assign). #[inline] fn shl_round_assign(&mut self, bits: $u, rm: RoundingMode) -> Ordering { shl_round_assign(self, bits, rm) } } }; } apply_to_signeds!(impl_shl_round_inner); }; } apply_to_primitive_ints!(impl_shl_round); ================================================ FILE: malachite-base/src/num/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::rounding_modes::RoundingMode::{self, *}; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; fn shr_round_unsigned_unsigned< T: PrimitiveUnsigned + Shl + Shr, U: PrimitiveUnsigned, >( x: T, bits: U, rm: RoundingMode, ) -> (T, Ordering) { if bits == U::ZERO || x == T::ZERO { return (x, Equal); } let width = U::wrapping_from(T::WIDTH); match rm { Down | Floor if bits >= width => (T::ZERO, Less), Down | Floor => { let shifted = x >> bits; (shifted, if shifted << bits == x { Equal } else { Less }) } Up | Ceiling if bits >= width => (T::ONE, Greater), Up | Ceiling => { let shifted = x >> bits; if shifted << bits == x { (shifted, Equal) } else { (shifted + T::ONE, Greater) } } Nearest if bits == width && x > T::power_of_2(T::WIDTH - 1) => (T::ONE, Greater), Nearest if bits >= width => (T::ZERO, Less), Nearest => { let bm1 = bits - U::ONE; let mostly_shifted = x >> bm1; let bm1_zeros = mostly_shifted << bm1 == x; if mostly_shifted.even() { // round down (mostly_shifted >> 1, if bm1_zeros { Equal } else { Less }) } else if !bm1_zeros { // round up ((mostly_shifted >> 1) + T::ONE, Greater) } else { // result is half-integer; round to even let shifted: T = mostly_shifted >> 1; if shifted.even() { (shifted, Less) } else { (shifted + T::ONE, Greater) } } } Exact if bits >= width => { panic!("Right shift is not exact: {x} >> {bits}"); } Exact => { let shifted = x >> bits; assert!( shifted << bits == x, "Right shift is not exact: {x} >> {bits}" ); (shifted, Equal) } } } fn shr_round_assign_unsigned_unsigned< T: PrimitiveUnsigned + Shl + ShrAssign, U: PrimitiveUnsigned, >( x: &mut T, bits: U, rm: RoundingMode, ) -> Ordering { if bits == U::ZERO || *x == T::ZERO { return Equal; } let width = U::wrapping_from(T::WIDTH); match rm { Down | Floor if bits >= width => { *x = T::ZERO; Less } Down | Floor => { let original = *x; *x >>= bits; if *x << bits == original { Equal } else { Less } } Up | Ceiling if bits >= width => { *x = T::ONE; Greater } Up | Ceiling => { let original = *x; *x >>= bits; if *x << bits == original { Equal } else { *x += T::ONE; Greater } } Nearest if bits == width && *x > T::power_of_2(T::WIDTH - 1) => { *x = T::ONE; Greater } Nearest if bits >= width => { *x = T::ZERO; Less } Nearest => { let original = *x; let bm1 = bits - U::ONE; *x >>= bm1; let bm1_zeros = *x << bm1 == original; let old_x = *x; *x >>= 1; if old_x.even() { // round down if bm1_zeros { Equal } else { Less } } else if !bm1_zeros { // round up *x += T::ONE; Greater } else { // result is half-integer; round to even if x.even() { Less } else { *x += T::ONE; Greater } } } Exact if bits >= width => { panic!("Right shift is not exact: {} >>= {}", *x, bits); } Exact => { let original = *x; *x >>= bits; assert!( *x << bits == original, "Right shift is not exact: {original} >>= {bits}" ); Equal } } } macro_rules! impl_shr_round_unsigned_unsigned { ($t:ident) => { macro_rules! impl_shr_round_unsigned_unsigned_inner { ($u:ident) => { impl ShrRound<$u> for $t { type Output = $t; /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the exact /// value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the /// first element of the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `self` is not divisible by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $u, rm: RoundingMode) -> ($t, Ordering) { shr_round_unsigned_unsigned(self, bits, rm) } } impl ShrRoundAssign<$u> for $t { /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater /// than the exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `self` is not divisible by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $u, rm: RoundingMode) -> Ordering { shr_round_assign_unsigned_unsigned(self, bits, rm) } } }; } apply_to_unsigneds!(impl_shr_round_unsigned_unsigned_inner); }; } apply_to_unsigneds!(impl_shr_round_unsigned_unsigned); fn shr_round_signed_unsigned< U: PrimitiveUnsigned + ShrRound, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, B, >( x: S, bits: B, rm: RoundingMode, ) -> (S, Ordering) { let abs = x.unsigned_abs(); if x >= S::ZERO { let (abs_shifted, o) = abs.shr_round(bits, rm); (S::wrapping_from(abs_shifted), o) } else { let (abs_shifted, o) = abs.shr_round(bits, -rm); ( if abs_shifted == U::ZERO { S::ZERO } else if abs_shifted == S::MIN.unsigned_abs() { S::MIN } else { -S::wrapping_from(abs_shifted) }, o.reverse(), ) } } macro_rules! impl_shr_round_signed_unsigned { ($t:ident) => { macro_rules! impl_shr_round_signed_unsigned_inner { ($u:ident) => { impl ShrRound<$u> for $t { type Output = $t; /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the exact /// value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the /// first element of the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `self` is not divisible by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $u, rm: RoundingMode) -> ($t, Ordering) { shr_round_signed_unsigned(self, bits, rm) } } impl ShrRoundAssign<$u> for $t { /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode, in place. An [`Ordering`] isreturned, /// indicating whether the assigned value is less than, equal to, or greater /// than the exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `self` is not divisible by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $u, rm: RoundingMode) -> Ordering { let o; (*self, o) = self.shr_round(bits, rm); o } } }; } apply_to_unsigneds!(impl_shr_round_signed_unsigned_inner); }; } apply_to_signeds!(impl_shr_round_signed_unsigned); fn shr_round_primitive_signed< T: PrimitiveInt + Shl + ShrRound, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: T, bits: S, rm: RoundingMode, ) -> (T, Ordering) { if bits >= S::ZERO { x.shr_round(bits.unsigned_abs(), rm) } else { let abs = bits.unsigned_abs(); ( if abs >= U::wrapping_from(T::WIDTH) { T::ZERO } else { x << bits.unsigned_abs() }, Equal, ) } } fn shr_round_assign_primitive_signed< T: PrimitiveInt + ShlAssign + ShrRoundAssign, U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( x: &mut T, bits: S, rm: RoundingMode, ) -> Ordering { if bits >= S::ZERO { x.shr_round_assign(bits.unsigned_abs(), rm) } else { let abs = bits.unsigned_abs(); if abs >= U::wrapping_from(T::WIDTH) { *x = T::ZERO; } else { *x <<= bits.unsigned_abs(); } Equal } } macro_rules! impl_shr_round_primitive_signed { ($t:ident) => { macro_rules! impl_shr_round_primitive_signed_inner { ($u:ident) => { impl ShrRound<$u> for $t { type Output = $t; /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the exact /// value. If `bits` is negative, then the returned [`Ordering`] is always /// `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. Rounding /// might only be necessary if `bits` is non-negative. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the /// first element of the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $g(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is positive and `rm` is `Exact` but `self` is not divisible /// by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $u, rm: RoundingMode) -> ($t, Ordering) { shr_round_primitive_signed(self, bits, rm) } } impl ShrRoundAssign<$u> for $t { /// Shifts a number right (divides it by a power of 2) and rounds according to /// the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater /// than the exact value. If `bits` is negative, then the returned [`Ordering`] /// is always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether /// `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. Rounding /// might only be necessary if `bits` is non-negative. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is positive and `rm` is `Exact` but `self` is not divisible /// by $2^b$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $u, rm: RoundingMode) -> Ordering { shr_round_assign_primitive_signed(self, bits, rm) } } }; } apply_to_signeds!(impl_shr_round_primitive_signed_inner); }; } apply_to_primitive_ints!(impl_shr_round_primitive_signed); ================================================ FILE: malachite-base/src/num/arithmetic/sign.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Sign; use core::cmp::Ordering::{self, *}; macro_rules! impl_sign_primitive_int { ($t:ident) => { impl Sign for $t { /// Compares a number to zero. /// /// Returns `Greater`, `Equal`, or `Less`, depending on whether the number is positive, /// zero, or negative, respectively. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sign#sign). #[inline] fn sign(&self) -> Ordering { self.cmp(&0) } } }; } apply_to_primitive_ints!(impl_sign_primitive_int); macro_rules! impl_sign_primitive_float { ($t:ident) => { impl Sign for $t { /// Compares a number to zero. /// /// - Positive finite numbers, positive zero, and positive infinity have sign `Greater`. /// - Negative finite numbers, negative zero, and negative infinity have sign `Less`. /// - `NaN` has sign `Equal`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sign#sign). #[inline] fn sign(&self) -> Ordering { if self.is_nan() { Equal } else if self.is_sign_positive() { Greater } else { Less } } } }; } apply_to_primitive_floats!(impl_sign_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/sqrt.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_sqrtrem1` contributed to the GNU project by Torbjörn Granlund. // // Copyright © 1999-2002, 2004, 2005, 2008, 2010, 2012, 2015, 2017 Free Software Foundation, // Inc. // // Uses code adopted from the FLINT Library. // // Copyright © 2009 William Hart // // 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 crate::num::arithmetic::traits::{ CeilingSqrt, CeilingSqrtAssign, CheckedSqrt, FloorSqrt, FloorSqrtAssign, RoundToMultipleOfPowerOf2, ShrRound, Sqrt, SqrtAssign, SqrtAssignRem, SqrtRem, }; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::logic::traits::SignificantBits; use crate::rounding_modes::RoundingMode::*; use core::cmp::Ordering::*; const U8_SQUARES: [u8; 16] = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225]; impl FloorSqrt for u8 { type Output = Self; /// Returns the floor of the square root of a [`u8`]. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). /// /// # Notes /// The [`u8`] implementation uses a lookup table. fn floor_sqrt(self) -> Self { Self::wrapping_from(match U8_SQUARES.binary_search(&self) { Ok(i) => i, Err(i) => i - 1, }) } } impl CeilingSqrt for u8 { type Output = Self; /// Returns the ceiling of the square root of a [`u8`]. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). /// /// # Notes /// The [`u8`] implementation uses a lookup table. fn ceiling_sqrt(self) -> Self { Self::wrapping_from(match U8_SQUARES.binary_search(&self) { Ok(i) | Err(i) => i, }) } } impl CheckedSqrt for u8 { type Output = Self; /// Returns the the square root of a [`u8`], or `None` if the [`u8`] is not a perfect square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). /// /// # Notes /// The [`u8`] implementation uses a lookup table. fn checked_sqrt(self) -> Option { U8_SQUARES .binary_search(&self) .ok() .map(Self::wrapping_from) } } impl SqrtRem for u8 { type SqrtOutput = Self; type RemOutput = Self; /// Returns the floor of the square root of a [`u8`], and the remainder (the difference between /// the [`u8`] and the square of the floor). /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_rem). /// /// # Notes /// The [`u8`] implementation uses a lookup table. fn sqrt_rem(self) -> (Self, Self) { match U8_SQUARES.binary_search(&self) { Ok(i) => (Self::wrapping_from(i), 0), Err(i) => (Self::wrapping_from(i - 1), self - U8_SQUARES[i - 1]), } } } pub(crate) fn floor_inverse_checked_binary Option>( f: F, x: T, mut low: T, mut high: T, ) -> T { loop { if high <= low { return low; } let mid: T = low.checked_add(high).unwrap().shr_round(1, Ceiling).0; match f(mid).map(|mid| mid.cmp(&x)) { Some(Equal) => return mid, Some(Less) => low = mid, Some(Greater) | None => high = mid - T::ONE, } } } pub_test! {floor_sqrt_binary(x: T) -> T { if x < T::TWO { x } else { let p = T::power_of_2(x.significant_bits().shr_round(1, Ceiling).0); floor_inverse_checked_binary(T::checked_square, x, p >> 1, p) } }} pub_test! {ceiling_sqrt_binary(x: T) -> T { let floor_sqrt = floor_sqrt_binary(x); if floor_sqrt.square() == x { floor_sqrt } else { floor_sqrt + T::ONE } }} pub_test! {checked_sqrt_binary(x: T) -> Option { let floor_sqrt = floor_sqrt_binary(x); if floor_sqrt.square() == x { Some(floor_sqrt) } else { None } }} pub_test! {sqrt_rem_binary(x: T) -> (T, T) { let floor_sqrt = floor_sqrt_binary(x); (floor_sqrt, x - floor_sqrt.square()) }} const INV_SQRT_TAB: [u16; 384] = [ 0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf2, 0xf0, 0xee, 0xec, 0xea, 0xe9, 0xe7, 0xe5, 0xe4, 0xe2, 0xe0, 0xdf, 0xdd, 0xdb, 0xda, 0xd8, 0xd7, 0xd5, 0xd4, 0xd2, 0xd1, 0xcf, 0xce, 0xcc, 0xcb, 0xc9, 0xc8, 0xc6, 0xc5, 0xc4, 0xc2, 0xc1, 0xc0, 0xbe, 0xbd, 0xbc, 0xba, 0xb9, 0xb8, 0xb7, 0xb5, 0xb4, 0xb3, 0xb2, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x79, 0x78, 0x77, 0x76, 0x76, 0x75, 0x74, 0x73, 0x72, 0x72, 0x71, 0x70, 0x6f, 0x6f, 0x6e, 0x6d, 0x6d, 0x6c, 0x6b, 0x6a, 0x6a, 0x69, 0x68, 0x68, 0x67, 0x66, 0x66, 0x65, 0x64, 0x64, 0x63, 0x62, 0x62, 0x61, 0x60, 0x60, 0x5f, 0x5e, 0x5e, 0x5d, 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x59, 0x58, 0x57, 0x57, 0x56, 0x56, 0x55, 0x54, 0x54, 0x53, 0x53, 0x52, 0x52, 0x51, 0x50, 0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4b, 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 0x46, 0x46, 0x45, 0x45, 0x44, 0x44, 0x43, 0x43, 0x42, 0x42, 0x41, 0x41, 0x40, 0x40, 0x3f, 0x3f, 0x3e, 0x3e, 0x3d, 0x3d, 0x3c, 0x3c, 0x3b, 0x3b, 0x3a, 0x3a, 0x39, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35, 0x35, 0x34, 0x34, 0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2e, 0x2e, 0x2d, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x2b, 0x2b, 0x2a, 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26, 0x26, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23, 0x22, 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20, 0x1f, 0x1f, 0x1f, 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, 0x1b, 0x1b, 0x1b, 0x1a, 0x1a, 0x1a, 0x19, 0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, ]; // This is equivalent to `mpn_sqrtrem1` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where both the // square root and the remainder are returned. #[doc(hidden)] pub fn sqrt_rem_newton< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( n: U, ) -> (U, U) { let magic = match U::WIDTH { u32::WIDTH => { U::wrapping_from(0x100000u32) // 0xfee6f < MAGIC < 0x29cbc8 } u64::WIDTH => { U::wrapping_from(0x10000000000u64) // 0xffe7debbfc < magic < 0x232b1850f410 } _ => panic!(), }; assert!(n.leading_zeros() < 2); // Use Newton iterations for approximating 1/sqrt(a) instead of sqrt(a), since we can do the // former without division. As part of the last iteration convert from 1/sqrt(a) to sqrt(a). let i: usize = (n >> (U::WIDTH - 9)).wrapping_into(); // extract bits for table lookup let mut inv_sqrt = U::wrapping_from(INV_SQRT_TAB[i - 0x80]); inv_sqrt.set_bit(8); // initial 1/sqrt(a) let mut sqrt: U = match U::WIDTH { u32::WIDTH => { let p = inv_sqrt * (n >> 8); let t: U = p >> 13; let a: U = n << 6; let t = S::wrapping_from(a.wrapping_sub(t.wrapping_square()).wrapping_sub(magic)) >> 8; p.wrapping_add(U::wrapping_from((S::wrapping_from(inv_sqrt) * t) >> 7)) >> 16 } u64::WIDTH => { let a1 = n >> (U::WIDTH - 33); let t = (S::wrapping_from(0x2000000000000u64 - 0x30000) - S::wrapping_from(a1 * inv_sqrt.square())) >> 16; let a: U = inv_sqrt << 16; inv_sqrt = a.wrapping_add(U::wrapping_from((S::wrapping_from(inv_sqrt) * t) >> 18)); let p = inv_sqrt * (n >> 24); let t: U = p >> 25; let a: U = n << 14; let t = S::wrapping_from(a.wrapping_sub(t.wrapping_square()).wrapping_sub(magic)) >> 24; p.wrapping_add(U::wrapping_from((S::wrapping_from(inv_sqrt) * t) >> 15)) >> 32 } _ => unreachable!(), }; // x0 is now a full limb approximation of sqrt(a0) let mut square = sqrt.square(); if square + (sqrt << 1) < n { square += (sqrt << 1) + U::ONE; sqrt += U::ONE; } (sqrt, n - square) } // Returns (sqrt, r_hi, r_lo) such that [n_lo, n_hi] = sqrt ^ 2 + [r_lo, r_hi]. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_sqrtrem2` from `mpn/generic/sqrtrem.c`, GMP 6.2.1. pub fn sqrt_rem_2_newton< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( n_hi: U, n_lo: U, ) -> (U, bool, U) { assert!(n_hi.leading_zeros() < 2); let (mut sqrt, mut r_lo) = sqrt_rem_newton::(n_hi); let prec = U::WIDTH >> 1; let prec_p_1: u64 = prec + 1; let prec_m_1: u64 = prec - 1; // r_lo <= 2 * sqrt < 2 ^ (prec + 1) r_lo = (r_lo << prec_m_1) | (n_lo >> prec_p_1); let mut q = r_lo / sqrt; // q <= 2 ^ prec, if q = 2 ^ prec, reduce the overestimate. q -= q >> prec; // now we have q < 2 ^ prec let u = r_lo - q * sqrt; // now we have (rp_lo << prec + n_lo >> prec) / 2 = q * sqrt + u sqrt = (sqrt << prec) | q; let mut r_hi = (u >> prec_m_1) + U::ONE; r_lo = (u << prec_p_1) | (n_lo.mod_power_of_2(prec_p_1)); let q_squared = q.square(); if r_lo < q_squared { assert_ne!(r_hi, U::ZERO); r_hi -= U::ONE; } r_lo.wrapping_sub_assign(q_squared); if r_hi == U::ZERO { r_lo.wrapping_add_assign(sqrt); if r_lo < sqrt { r_hi += U::ONE; } sqrt -= U::ONE; r_lo.wrapping_add_assign(sqrt); if r_lo < sqrt { r_hi += U::ONE; } } r_hi -= U::ONE; assert!(r_hi < U::TWO); (sqrt, r_hi == U::ONE, r_lo) } // This is equivalent to `n_sqrt` from `ulong_extras/sqrt.c`, FLINT 2.7.1. fn floor_sqrt_approx_and_refine f64, G: Fn(f64) -> T>( f: F, g: G, max_square: T, x: T, ) -> T { if x >= max_square { return T::low_mask(T::WIDTH >> 1); } let mut sqrt = g(f(x).sqrt()); let mut square = if let Some(square) = sqrt.checked_square() { square } else { // set to max possible sqrt sqrt = T::low_mask(T::WIDTH >> 1); sqrt.square() }; match square.cmp(&x) { Equal => sqrt, Less => loop { square = square.checked_add((sqrt << 1) + T::ONE).unwrap(); sqrt += T::ONE; match square.cmp(&x) { Equal => return sqrt, Less => {} Greater => return sqrt - T::ONE, } }, Greater => loop { square -= (sqrt << 1) - T::ONE; sqrt -= T::ONE; if square <= x { return sqrt; } }, } } fn ceiling_sqrt_approx_and_refine f64, G: Fn(f64) -> T>( f: F, g: G, max_square: T, x: T, ) -> T { if x > max_square { return T::power_of_2(T::WIDTH >> 1); } let mut sqrt = g(f(x).sqrt()); let mut square = if let Some(square) = sqrt.checked_square() { square } else { // set to max possible sqrt sqrt = T::low_mask(T::WIDTH >> 1); sqrt.square() }; match square.cmp(&x) { Equal => sqrt, Less => loop { square = square.checked_add((sqrt << 1) + T::ONE).unwrap(); sqrt += T::ONE; if square >= x { return sqrt; } }, Greater => loop { square -= (sqrt << 1) - T::ONE; sqrt -= T::ONE; match square.cmp(&x) { Equal => return sqrt, Greater => {} Less => return sqrt + T::ONE, } }, } } fn checked_sqrt_approx_and_refine f64, G: Fn(f64) -> T>( f: F, g: G, max_square: T, x: T, ) -> Option { if x > max_square { return None; } let mut sqrt = g(f(x).sqrt()); let mut square = if let Some(square) = sqrt.checked_square() { square } else { // set to max possible sqrt sqrt = T::low_mask(T::WIDTH >> 1); sqrt.square() }; match square.cmp(&x) { Equal => Some(sqrt), Less => loop { square = square.checked_add((sqrt << 1) + T::ONE).unwrap(); sqrt += T::ONE; match square.cmp(&x) { Equal => return Some(sqrt), Less => {} Greater => return None, } }, Greater => loop { square -= (sqrt << 1) - T::ONE; sqrt -= T::ONE; match square.cmp(&x) { Equal => return Some(sqrt), Less => return None, Greater => {} } }, } } // This is equivalent to `n_sqrtrem` from `ulong_extras/sqrtrem.c`, FLINT 2.7.1. fn sqrt_rem_approx_and_refine f64, G: Fn(f64) -> T>( f: F, g: G, max_square: T, x: T, ) -> (T, T) { if x >= max_square { return (T::low_mask(T::WIDTH >> 1), x - max_square); } let mut sqrt = g(f(x).sqrt()); let mut square = if let Some(square) = sqrt.checked_square() { square } else { // set to max possible sqrt sqrt = T::low_mask(T::WIDTH >> 1); sqrt.square() }; match square.cmp(&x) { Equal => (sqrt, T::ZERO), Less => loop { square = square.checked_add((sqrt << 1) + T::ONE).unwrap(); sqrt += T::ONE; match square.cmp(&x) { Equal => return (sqrt, T::ZERO), Less => {} Greater => { square -= (sqrt << 1) - T::ONE; sqrt -= T::ONE; return (sqrt, x - square); } } }, Greater => loop { square -= (sqrt << 1) - T::ONE; sqrt -= T::ONE; if square <= x { return (sqrt, x - square); } }, } } fn floor_sqrt_newton_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: U, ) -> U { if x == U::ZERO { return U::ZERO; } let shift = x .leading_zeros() .round_to_multiple_of_power_of_2(1, Floor) .0; sqrt_rem_newton::(x << shift).0 >> (shift >> 1) } fn ceiling_sqrt_newton_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: U, ) -> U { if x == U::ZERO { return U::ZERO; } let shift = x .leading_zeros() .round_to_multiple_of_power_of_2(1, Floor) .0; let (mut sqrt, rem) = sqrt_rem_newton::(x << shift); sqrt >>= shift >> 1; if rem != U::ZERO { sqrt += U::ONE; } sqrt } fn checked_sqrt_newton_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: U, ) -> Option { if x == U::ZERO { return Some(U::ZERO); } let shift = x .leading_zeros() .round_to_multiple_of_power_of_2(1, Floor) .0; let (sqrt, rem) = sqrt_rem_newton::(x << shift); if rem == U::ZERO { Some(sqrt >> (shift >> 1)) } else { None } } fn sqrt_rem_newton_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: U, ) -> (U, U) { if x == U::ZERO { return (U::ZERO, U::ZERO); } let shift = x .leading_zeros() .round_to_multiple_of_power_of_2(1, Floor) .0; let (mut sqrt, rem) = sqrt_rem_newton::(x << shift); if shift == 0 { (sqrt, rem) } else { sqrt >>= shift >> 1; (sqrt, x - sqrt.square()) } } macro_rules! impl_sqrt_newton { ($u: ident, $s: ident) => { impl FloorSqrt for $u { type Output = $u; /// Returns the floor of the square root of an integer. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). /// /// # Notes /// For [`u32`] and [`u64`], the square root is computed using Newton's method. #[inline] fn floor_sqrt(self) -> $u { floor_sqrt_newton_helper::<$u, $s>(self) } } impl CeilingSqrt for $u { type Output = $u; /// Returns the ceiling of the square root of an integer. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). /// /// # Notes /// For [`u32`] and [`u64`], the square root is computed using Newton's method. #[inline] fn ceiling_sqrt(self) -> $u { ceiling_sqrt_newton_helper::<$u, $s>(self) } } impl CheckedSqrt for $u { type Output = $u; /// Returns the the square root of an integer, or `None` if the integer is not a perfect /// square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). /// /// # Notes /// For [`u32`] and [`u64`], the square root is computed using Newton's method. #[inline] fn checked_sqrt(self) -> Option<$u> { checked_sqrt_newton_helper::<$u, $s>(self) } } impl SqrtRem for $u { type SqrtOutput = $u; type RemOutput = $u; /// Returns the floor of the square root of an integer, and the remainder (the /// difference between the integer and the square of the floor). /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_rem). /// /// # Notes /// For [`u32`] and [`u64`], the square root is computed using Newton's method. #[inline] fn sqrt_rem(self) -> ($u, $u) { sqrt_rem_newton_helper::<$u, $s>(self) } } }; } impl_sqrt_newton!(u32, i32); impl_sqrt_newton!(u64, i64); impl FloorSqrt for u16 { type Output = Self; /// Returns the floor of the square root of a [`u16`]. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn floor_sqrt(self) -> Self { Self::wrapping_from(u32::from(self).floor_sqrt()) } } impl CeilingSqrt for u16 { type Output = Self; /// Returns the ceiling of the square root of a [`u16`]. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn ceiling_sqrt(self) -> Self { Self::wrapping_from(u32::from(self).ceiling_sqrt()) } } impl CheckedSqrt for u16 { type Output = Self; /// Returns the the square root of a [`u16`], or `None` if the integer is not a perfect square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn checked_sqrt(self) -> Option { u32::from(self).checked_sqrt().map(Self::wrapping_from) } } impl SqrtRem for u16 { type SqrtOutput = Self; type RemOutput = Self; /// Returns the floor of the square root of a [`u16`], and the remainder (the difference between /// the [`u16`] and the square of the floor). /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_rem). /// /// # Notes /// The [`u16`] implementation calls the implementation for [`u32`]s. #[inline] fn sqrt_rem(self) -> (Self, Self) { let (sqrt, rem) = u32::from(self).sqrt_rem(); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } } impl FloorSqrt for usize { type Output = Self; /// Returns the floor of the square root of a [`usize`]. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn floor_sqrt(self) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).floor_sqrt()) } else { Self::wrapping_from(u64::wrapping_from(self).floor_sqrt()) } } } impl CeilingSqrt for usize { type Output = Self; /// Returns the ceiling of the square root of a [`usize`]. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn ceiling_sqrt(self) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::wrapping_from(self).ceiling_sqrt()) } else { Self::wrapping_from(u64::wrapping_from(self).ceiling_sqrt()) } } } impl CheckedSqrt for usize { type Output = Self; /// Returns the the square root of a [`usize`], or `None` if the [`usize`] is not a perfect /// square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn checked_sqrt(self) -> Option { if USIZE_IS_U32 { u32::wrapping_from(self) .checked_sqrt() .map(Self::wrapping_from) } else { u64::wrapping_from(self) .checked_sqrt() .map(Self::wrapping_from) } } } impl SqrtRem for usize { type SqrtOutput = Self; type RemOutput = Self; /// Returns the floor of the square root of a [`usize`], and the remainder (the difference /// between the [`usize`] and the square of the floor). /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_rem). /// /// # Notes /// The [`usize`] implementation calls the [`u32`] or [`u64`] implementations. #[inline] fn sqrt_rem(self) -> (Self, Self) { if USIZE_IS_U32 { let (sqrt, rem) = u32::wrapping_from(self).sqrt_rem(); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } else { let (sqrt, rem) = u64::wrapping_from(self).sqrt_rem(); (Self::wrapping_from(sqrt), Self::wrapping_from(rem)) } } } // TODO tune const U128_SQRT_THRESHOLD: u64 = 125; const U128_MAX_SQUARE: u128 = 0xfffffffffffffffe0000000000000001; impl FloorSqrt for u128 { type Output = Self; /// Returns the floor of the square root of a [`u128`]. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). /// /// # Notes /// For [`u128`], using a floating-point approximation and refining the result works, but the /// number of necessary adjustments becomes large for large [`u128`]s. To overcome this, large /// [`u128`]s switch to a binary search algorithm. To get decent starting bounds, the following /// fact is used: /// /// If $x$ is nonzero and has $b$ significant bits, then /// /// $2^{b-1} \leq x \leq 2^b-1$, /// /// $2^{b-1} \leq x \leq 2^b$, /// /// $2^{2\lfloor (b-1)/2 \rfloor} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $2^{2(\lceil b/2 \rceil-1)} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $\lfloor\sqrt{2^{2(\lceil b/2 \rceil-1)}}\rfloor \leq \lfloor\sqrt{x}\rfloor \leq /// \lfloor\sqrt{2^{2\lceil b/2 \rceil}}\rfloor$, since $x \mapsto \lfloor\sqrt{x}\rfloor$ is /// weakly increasing, /// /// $2^{\lceil b/2 \rceil-1} \leq \lfloor\sqrt{x}\rfloor \leq 2^{\lceil b/2 \rceil}$. /// /// For example, since $10^9$ has 30 significant bits, we know that $2^{14} \leq /// \lfloor\sqrt{10^9}\rfloor \leq 2^{15}$. fn floor_sqrt(self) -> Self { if self.significant_bits() < U128_SQRT_THRESHOLD { floor_sqrt_approx_and_refine(|x| x as f64, |x| x as Self, U128_MAX_SQUARE, self) } else { floor_sqrt_binary(self) } } } impl CeilingSqrt for u128 { type Output = Self; /// Returns the ceiling of the square root of a [`u128`]. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). /// /// # Notes /// For [`u128`], using a floating-point approximation and refining the result works, but the /// number of necessary adjustments becomes large for large [`u128`]s. To overcome this, large /// [`u128`]s switch to a binary search algorithm. To get decent starting bounds, the following /// fact is used: /// /// If $x$ is nonzero and has $b$ significant bits, then /// /// $2^{b-1} \leq x \leq 2^b-1$, /// /// $2^{b-1} \leq x \leq 2^b$, /// /// $2^{2\lfloor (b-1)/2 \rfloor} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $2^{2(\lceil b/2 \rceil-1)} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $\lfloor\sqrt{2^{2(\lceil b/2 \rceil-1)}}\rfloor \leq \lfloor\sqrt{x}\rfloor \leq /// \lfloor\sqrt{2^{2\lceil b/2 \rceil}}\rfloor$, since $x \mapsto \lfloor\sqrt{x}\rfloor$ is /// weakly increasing, /// /// $2^{\lceil b/2 \rceil-1} \leq \lfloor\sqrt{x}\rfloor \leq 2^{\lceil b/2 \rceil}$. /// /// For example, since $10^9$ has 30 significant bits, we know that $2^{14} \leq /// \lfloor\sqrt{10^9}\rfloor \leq 2^{15}$. fn ceiling_sqrt(self) -> Self { if self.significant_bits() < U128_SQRT_THRESHOLD { ceiling_sqrt_approx_and_refine(|x| x as f64, |x| x as Self, U128_MAX_SQUARE, self) } else { ceiling_sqrt_binary(self) } } } impl CheckedSqrt for u128 { type Output = Self; /// Returns the the square root of a [`u128`], or `None` if the [`u128`] is not a perfect /// square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). /// /// # Notes /// For [`u128`], using a floating-point approximation and refining the result works, but the /// number of necessary adjustments becomes large for large [`u128`]s. To overcome this, large /// [`u128`]s switch to a binary search algorithm. To get decent starting bounds, the following /// fact is used: /// /// If $x$ is nonzero and has $b$ significant bits, then /// /// $2^{b-1} \leq x \leq 2^b-1$, /// /// $2^{b-1} \leq x \leq 2^b$, /// /// $2^{2\lfloor (b-1)/2 \rfloor} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $2^{2(\lceil b/2 \rceil-1)} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $\lfloor\sqrt{2^{2(\lceil b/2 \rceil-1)}}\rfloor \leq \lfloor\sqrt{x}\rfloor \leq /// \lfloor\sqrt{2^{2\lceil b/2 \rceil}}\rfloor$, since $x \mapsto \lfloor\sqrt{x}\rfloor$ is /// weakly increasing, /// /// $2^{\lceil b/2 \rceil-1} \leq \lfloor\sqrt{x}\rfloor \leq 2^{\lceil b/2 \rceil}$. /// /// For example, since $10^9$ has 30 significant bits, we know that $2^{14} \leq /// \lfloor\sqrt{10^9}\rfloor \leq 2^{15}$. fn checked_sqrt(self) -> Option { if self.significant_bits() < U128_SQRT_THRESHOLD { checked_sqrt_approx_and_refine(|x| x as f64, |x| x as Self, U128_MAX_SQUARE, self) } else { checked_sqrt_binary(self) } } } impl SqrtRem for u128 { type SqrtOutput = Self; type RemOutput = Self; /// Returns the floor of the square root of a [`u128`], and the remainder (the difference /// between the [`u128`] and the square of the floor). /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::sqrt#sqrt_rem). /// /// # Notes /// For [`u128`], using a floating-point approximation and refining the result works, but the /// number of necessary adjustments becomes large for large [`u128`]s. To overcome this, large /// [`u128`]s switch to a binary search algorithm. To get decent starting bounds, the following /// fact is used: /// /// If $x$ is nonzero and has $b$ significant bits, then /// /// $2^{b-1} \leq x \leq 2^b-1$, /// /// $2^{b-1} \leq x \leq 2^b$, /// /// $2^{2\lfloor (b-1)/2 \rfloor} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $2^{2(\lceil b/2 \rceil-1)} \leq x \leq 2^{2\lceil b/2 \rceil}$, /// /// $\lfloor\sqrt{2^{2(\lceil b/2 \rceil-1)}}\rfloor \leq \lfloor\sqrt{x}\rfloor \leq /// \lfloor\sqrt{2^{2\lceil b/2 \rceil}}\rfloor$, since $x \mapsto \lfloor\sqrt{x}\rfloor$ is /// weakly increasing, /// /// $2^{\lceil b/2 \rceil-1} \leq \lfloor\sqrt{x}\rfloor \leq 2^{\lceil b/2 \rceil}$. /// /// For example, since $10^9$ has 30 significant bits, we know that $2^{14} \leq /// \lfloor\sqrt{10^9}\rfloor \leq 2^{15}$. fn sqrt_rem(self) -> (Self, Self) { if self.significant_bits() < U128_SQRT_THRESHOLD { sqrt_rem_approx_and_refine(|x| x as f64, |x| x as Self, U128_MAX_SQUARE, self) } else { sqrt_rem_binary(self) } } } macro_rules! impl_sqrt_signed { ($u: ident, $s: ident) => { impl FloorSqrt for $s { type Output = $s; /// Returns the floor of the square root of an integer. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// See [here](super::sqrt#floor_sqrt). #[inline] fn floor_sqrt(self) -> Self { if self >= 0 { $s::wrapping_from(self.unsigned_abs().floor_sqrt()) } else { panic!("Cannot take square root of {}", self) } } } impl CeilingSqrt for $s { type Output = $s; /// Returns the ceiling of the square root of an integer. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt). #[inline] fn ceiling_sqrt(self) -> $s { if self >= 0 { $s::wrapping_from(self.unsigned_abs().ceiling_sqrt()) } else { panic!("Cannot take square root of {}", self) } } } impl CheckedSqrt for $s { type Output = $s; /// Returns the the square root of an integer, or `None` if the integer is not a perfect /// square. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// See [here](super::sqrt#checked_sqrt). #[inline] fn checked_sqrt(self) -> Option<$s> { if self >= 0 { self.unsigned_abs().checked_sqrt().map($s::wrapping_from) } else { panic!("Cannot take square root of {}", self) } } } }; } apply_to_unsigned_signed_pairs!(impl_sqrt_signed); macro_rules! impl_sqrt_assign_rem_unsigned { ($t: ident) => { impl SqrtAssignRem for $t { type RemOutput = $t; /// Replaces an integer with the floor of its square root, and returns the remainder /// (the difference between the original integer and the square of the floor). /// /// $f(x) = x - \lfloor\sqrt{x}\rfloor^2$, /// /// $x \gets \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_assign_rem). #[inline] fn sqrt_assign_rem(&mut self) -> $t { let rem; (*self, rem) = self.sqrt_rem(); rem } } }; } apply_to_unsigneds!(impl_sqrt_assign_rem_unsigned); macro_rules! impl_sqrt_assign { ($t: ident) => { impl FloorSqrtAssign for $t { /// Replaces an integer with the floor of its square root. /// /// $x \gets \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// See [here](super::sqrt#floor_sqrt_assign). #[inline] fn floor_sqrt_assign(&mut self) { *self = self.floor_sqrt(); } } impl CeilingSqrtAssign for $t { /// Replaces an integer with the ceiling of its square root. /// /// $x \gets \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// See [here](super::sqrt#ceiling_sqrt_assign). #[inline] fn ceiling_sqrt_assign(&mut self) { *self = self.ceiling_sqrt(); } } }; } apply_to_primitive_ints!(impl_sqrt_assign); macro_rules! impl_sqrt_primitive_float { ($f:ident) => { impl Sqrt for $f { type Output = Self; /// This is a wrapper over the `sqrt` function in `libm`. #[inline] fn sqrt(self) -> $f { libm::Libm::<$f>::sqrt(self) } } impl SqrtAssign for $f { /// Replaces a number with its square root. /// /// $x \gets \sqrt x$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sqrt#sqrt_assign). #[inline] fn sqrt_assign(&mut self) { *self = self.sqrt(); } } }; } apply_to_primitive_floats!(impl_sqrt_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Square, SquareAssign}; macro_rules! impl_square { ($t:ident) => { impl Square for $t { type Output = $t; /// Squares a number. /// /// $f(x) = x^2$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::square#square). #[inline] fn square(self) -> $t { self * self } } impl SquareAssign for $t { /// Squares a number in place. /// /// $x \gets x^2$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::square#square_assign). #[inline] fn square_assign(&mut self) { *self *= *self; } } }; } apply_to_primitive_ints!(impl_square); apply_to_primitive_floats!(impl_square); ================================================ FILE: malachite-base/src/num/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SubMul, SubMulAssign, WrappingSubMul, WrappingSubMulAssign}; macro_rules! impl_sub_mul_primitive_int { ($t:ident) => { impl SubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sub_mul#sub_mul). #[inline] fn sub_mul(self, y: $t, z: $t) -> $t { self.wrapping_sub_mul(y, z) } } impl SubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers in place. /// /// $x \gets x - yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sub_mul#sub_mul_assign). #[inline] fn sub_mul_assign(&mut self, y: $t, z: $t) { self.wrapping_sub_mul_assign(y, z); } } }; } apply_to_primitive_ints!(impl_sub_mul_primitive_int); macro_rules! impl_sub_mul_primitive_float { ($t:ident) => { impl SubMul for $t { type Output = $t; /// Subtracts a number by the product of two other numbers. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sub_mul#sub_mul). #[inline] fn sub_mul(self, y: $t, z: $t) -> $t { self - y * z } } impl SubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers in place. /// /// $x \gets x - yz$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::sub_mul#sub_mul_assign). #[inline] fn sub_mul_assign(&mut self, y: $t, z: $t) { *self -= y * z; } } }; } apply_to_primitive_floats!(impl_sub_mul_primitive_float); ================================================ FILE: malachite-base/src/num/arithmetic/traits.rs ================================================ // Copyright © 2026 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 crate::num::basic::traits::Two; use crate::rounding_modes::RoundingMode; use core::cmp::Ordering; /// Takes the absolute value of a number. Assumes that the number has a representable absolute /// value. pub trait Abs { type Output; fn abs(self) -> Self::Output; } /// Replaces a number with its absolute value. Assumes that the number has a representable absolute /// value. pub trait AbsAssign { fn abs_assign(&mut self); } /// Takes the absolute value of a number and converts to the unsigned equivalent. pub trait UnsignedAbs { type Output; fn unsigned_abs(self) -> Self::Output; } /// Subtracts two numbers and takes the absolute value of the difference. pub trait AbsDiff { type Output; fn abs_diff(self, other: RHS) -> Self::Output; } /// Replaces a number with the absolute value of its difference with another number. pub trait AbsDiffAssign { fn abs_diff_assign(&mut self, other: RHS); } /// Adds a number and the product of two other numbers. pub trait AddMul { type Output; fn add_mul(self, y: Y, z: Z) -> Self::Output; } /// Adds a number and the product of two other numbers, in place. pub trait AddMulAssign { fn add_mul_assign(&mut self, y: Y, z: Z); } /// Calculates the AGM (arithmetic-geometric mean) of two numbers. pub trait Agm { type Output; fn agm(self, other: RHS) -> Self::Output; } /// Replaces a number with the AGM (arithmetic-geometric mean) of it and another number. pub trait AgmAssign { fn agm_assign(&mut self, other: RHS); } /// Left-shifts a number (multiplies it by a power of 2), returning `None` if the result is not /// representable. pub trait ArithmeticCheckedShl { type Output; fn arithmetic_checked_shl(self, other: RHS) -> Option; } /// Right-shifts a number (divides it by a power of 2), returning `None` if the result is not /// representable. pub trait ArithmeticCheckedShr { type Output; fn arithmetic_checked_shr(self, other: RHS) -> Option; } pub trait BinomialCoefficient { fn binomial_coefficient(n: T, k: T) -> Self; } pub trait CheckedBinomialCoefficient: Sized { fn checked_binomial_coefficient(n: T, k: T) -> Option; } /// Takes the ceiling of a number. pub trait Ceiling { type Output; fn ceiling(self) -> Self::Output; } /// Replaces a number with its ceiling. pub trait CeilingAssign { fn ceiling_assign(&mut self); } /// Takes the absolute valie of a number, returning `None` if the result is not representable. pub trait CheckedAbs { type Output; fn checked_abs(self) -> Option; } /// Adds two numbers, returning `None` if the result is not representable. pub trait CheckedAdd { type Output; fn checked_add(self, other: RHS) -> Option; } /// Adds a number and the product of two other numbers, returning `None` if the result is not /// representable. pub trait CheckedAddMul { type Output; fn checked_add_mul(self, y: Y, z: Z) -> Option; } /// Divides two numbers, returning `None` if the result is not representable. pub trait CheckedDiv { type Output; fn checked_div(self, other: RHS) -> Option; } /// Multiplies two numbers, returning `None` if the result is not representable. pub trait CheckedMul { type Output; fn checked_mul(self, other: RHS) -> Option; } /// Negates a number, returning `None` if the result is not representable. pub trait CheckedNeg { type Output; fn checked_neg(self) -> Option; } /// Finds the smallest integer power of 2 greater than or equal to a number, returning `None` if the /// result is not representable. pub trait CheckedNextPowerOf2 { type Output; fn checked_next_power_of_2(self) -> Option; } /// Raises a number to a power, returning `None` if the result is not representable. pub trait CheckedPow { type Output; fn checked_pow(self, exp: RHS) -> Option; } /// Squares a number, returning `None` if the result is not representable. pub trait CheckedSquare { type Output; fn checked_square(self) -> Option; } /// Subtracts two numbers, returning `None` if the result is not representable. pub trait CheckedSub { type Output; fn checked_sub(self, other: RHS) -> Option; } /// Subtracts a number by the product of two other numbers, returning `None` if the result is not /// representable. pub trait CheckedSubMul { type Output; fn checked_sub_mul(self, y: Y, z: Z) -> Option; } /// Determines whether two numbers are coprime. pub trait CoprimeWith { fn coprime_with(self, other: RHS) -> bool; } /// Divides two numbers, assuming the first exactly divides the second. /// /// If it doesn't, the `div_exact` function may panic or return a meaningless result. pub trait DivExact { type Output; fn div_exact(self, other: RHS) -> Self::Output; } /// Divides a number by another number in place, assuming the first exactly divides the second. /// /// If it doesn't, this function may panic or assign a meaningless number to the first number. pub trait DivExactAssign { fn div_exact_assign(&mut self, other: RHS); } /// Divides two numbers, returning the quotient and remainder. The quotient is rounded towards /// negative infinity, and the remainder has the same sign as the divisor (second input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait DivMod { type DivOutput; type ModOutput; fn div_mod(self, other: RHS) -> (Self::DivOutput, Self::ModOutput); } /// Divides a number by another number in place, returning the remainder. The quotient is rounded /// towards negative infinity, and the remainder has the same sign as the divisor (second input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait DivAssignMod { type ModOutput; fn div_assign_mod(&mut self, other: RHS) -> Self::ModOutput; } /// Divides two numbers, returning the quotient and remainder. The quotient is rounded towards zero, /// and the remainder has the same sign as the dividend (first input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait DivRem { type DivOutput; type RemOutput; fn div_rem(self, other: RHS) -> (Self::DivOutput, Self::RemOutput); } /// Divides a number by another number in place, returning the remainder. The quotient is rounded /// towards zero, and the remainder has the same sign as the dividend (first input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait DivAssignRem { type RemOutput; fn div_assign_rem(&mut self, other: RHS) -> Self::RemOutput; } /// Divides a number by another number, returning the ceiling of the quotient and the remainder of /// the negative of the first number divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. pub trait CeilingDivNegMod { type DivOutput; type ModOutput; fn ceiling_div_neg_mod(self, other: RHS) -> (Self::DivOutput, Self::ModOutput); } /// Divides a number by another number in place, taking the ceiling of the quotient and returning /// the remainder of the negative of the first number divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. pub trait CeilingDivAssignNegMod { type ModOutput; fn ceiling_div_assign_neg_mod(&mut self, other: RHS) -> Self::ModOutput; } /// Divides a number by another number, returning the quotient and remainder. The quotient is /// rounded towards positive infinity and the remainder has the opposite sign as the divisor (second /// input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait CeilingDivMod { type DivOutput; type ModOutput; fn ceiling_div_mod(self, other: RHS) -> (Self::DivOutput, Self::ModOutput); } /// Divides a number by another number in place, taking the quotient and returning the remainder. /// The quotient is rounded towards positive infinity and the remainder has the opposite sign of the /// divisor (second input). /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. pub trait CeilingDivAssignMod { type ModOutput; fn ceiling_div_assign_mod(&mut self, other: RHS) -> Self::ModOutput; } /// Divides a number by another number and rounds according to a specified rounding mode. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, or /// greater than the exact value. pub trait DivRound { type Output; fn div_round(self, other: RHS, rm: RoundingMode) -> (Self::Output, Ordering); } /// Divides a number by another number in place and rounds according to a specified rounding mode. /// An [`Ordering`] is returned, indicating whether the assigned value is less than, equal to, or /// greater than the exact value. pub trait DivRoundAssign { fn div_round_assign(&mut self, other: RHS, rm: RoundingMode) -> Ordering; } /// Determines whether a number is divisible by $2^k$. pub trait DivisibleByPowerOf2 { fn divisible_by_power_of_2(self, pow: u64) -> bool; } /// Determines whether a number is divisible by another number. pub trait DivisibleBy { fn divisible_by(self, other: RHS) -> bool; } /// Determines whether a number is equivalent to another number modulo $2^k$. pub trait EqModPowerOf2 { fn eq_mod_power_of_2(self, other: RHS, pow: u64) -> bool; } /// Determines whether a number is equivalent to another number modulo $m$. pub trait EqMod { fn eq_mod(self, other: RHS, m: M) -> bool; } /// Computes the GCD (greatest common divisor) of two numbers $a$ and $b$, and also the coefficients /// $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. /// /// The are infinitely many $x$, $y$ that satisfy the identity, so the full specification is more /// detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$, where /// $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq \lfloor a/g /// \rfloor$. pub trait ExtendedGcd { type Gcd; type Cofactor; fn extended_gcd(self, other: RHS) -> (Self::Gcd, Self::Cofactor, Self::Cofactor); } /// Computes the factorial of a `u64`. pub trait Factorial { fn factorial(n: u64) -> Self; } /// Computes the factorial of a `u64`, returning `None` if the result is too large to be /// represented. pub trait CheckedFactorial: Sized { fn checked_factorial(n: u64) -> Option; } /// Computes the double factorial of a `u64`. The double factorial of a non-negative integer is the /// product of all the positive integers that are less than or equal to it and have the same parity /// as it. pub trait DoubleFactorial { fn double_factorial(n: u64) -> Self; } /// Computes the double factorial of a `u64`, returning `None` if the result is too large to be /// represented. The double factorial of a non-negative integer is the product of all the positive /// integers that are less than or equal to it and have the same parity as it. pub trait CheckedDoubleFactorial: Sized { fn checked_double_factorial(n: u64) -> Option; } /// Computes the $m$-multifactorial of a `u64`. The $m$-multifactorial of a non-negative integer $n$ /// is the product of all integers $k$ such that $0 Self; } /// Computes the $m$-multifactorial of a `u64`, returning `None` if the result is too large to be /// represented. The $m$-multifactorial of a non-negative integer $n$ is the product of all integers /// $k$ such that $0 Option; } /// Computes the subfactorial of a `u64`. The subfactorial of a non-negative integer $n$ counts the /// number of derangements of $n$ elements, which are the permutations in which no element is fixed. pub trait Subfactorial { fn subfactorial(n: u64) -> Self; } /// Computes the subfactorial of a `u64`, returning `None` if the result is too large to be /// represented. The subfactorial of a non-negative integer $n$ counts the number of derangements of /// $n$ elements, which are the permutations in which no element is fixed. pub trait CheckedSubfactorial: Sized { fn checked_subfactorial(n: u64) -> Option; } /// Takes the floor of a number. pub trait Floor { type Output; fn floor(self) -> Self::Output; } /// Replaces a number with its floor. pub trait FloorAssign { fn floor_assign(&mut self); } /// Calculates the GCD (greatest common divisor) of two numbers. pub trait Gcd { type Output; fn gcd(self, other: RHS) -> Self::Output; } /// Replaces a number with the GCD (greatest common divisor) of it and another number. pub trait GcdAssign { fn gcd_assign(&mut self, other: RHS); } /// Determines whether a number is an integer power of 2. pub trait IsPowerOf2 { fn is_power_of_2(&self) -> bool; } /// Calculates the LCM (least common multiple) of two numbers. pub trait Lcm { type Output; fn lcm(self, other: RHS) -> Self::Output; } /// Replaces a number with the LCM (least common multiple) of it and another number. pub trait LcmAssign { fn lcm_assign(&mut self, other: RHS); } /// Takes the natural logarithm of a number. pub trait Ln { type Output; fn ln(self) -> Self::Output; } /// Replaces a number with its natural logarithm. pub trait LnAssign { fn ln_assign(&mut self); } /// Calculates the LCM (least common multiple) of two numbers, returning `None` if the result is not /// representable. pub trait CheckedLcm { type Output; fn checked_lcm(self, other: RHS) -> Option; } /// Calculates the Legendre symbol of two numbers. Typically the implementations will be identical /// to those of [`JacobiSymbol`]. pub trait LegendreSymbol { fn legendre_symbol(self, other: RHS) -> i8; } /// Calculates the Jacobi symbol of two numbers. pub trait JacobiSymbol { fn jacobi_symbol(self, other: RHS) -> i8; } /// Calculates the Kronecker symbol of two numbers. pub trait KroneckerSymbol { fn kronecker_symbol(self, other: RHS) -> i8; } /// Calculates the base-$b$ logarithm of a number, or returns `None` if the number is not a perfect /// power of $b$. pub trait CheckedLogBase { type Output; fn checked_log_base(self, base: B) -> Option; } /// Calculates the floor of the base-$b$ logarithm of a number. pub trait FloorLogBase { type Output; fn floor_log_base(self, base: B) -> Self::Output; } /// Calculates the ceiling of the base-$b$ logarithm of a number. pub trait CeilingLogBase { type Output; fn ceiling_log_base(self, base: B) -> Self::Output; } /// Calculates the base-2 logarithm of a number, or returns `None` if the number is not a perfect /// power of 2. pub trait CheckedLogBase2 { type Output; fn checked_log_base_2(self) -> Option; } /// Calculates the floor of the base-2 logarithm of a number. pub trait FloorLogBase2 { type Output; fn floor_log_base_2(self) -> Self::Output; } /// Calculates the ceiling of the base-2 logarithm of a number. pub trait CeilingLogBase2 { type Output; fn ceiling_log_base_2(self) -> Self::Output; } /// Calculates the base-$2^k$ logarithm of a number, or returns `None` if the number is not a /// perfect power of $2^k$. pub trait CheckedLogBasePowerOf2 { type Output; fn checked_log_base_power_of_2(self, pow: POW) -> Option; } /// Calculates the floor of the base-$2^k$ logarithm of a number. pub trait FloorLogBasePowerOf2 { type Output; fn floor_log_base_power_of_2(self, pow: POW) -> Self::Output; } /// Calculates the ceiling of the base-$2^k$ logarithm of a number. pub trait CeilingLogBasePowerOf2 { type Output; fn ceiling_log_base_power_of_2(self, pow: POW) -> Self::Output; } /// Adds two numbers modulo a third number $m$. The inputs must be already reduced modulo $m$. pub trait ModAdd { type Output; fn mod_add(self, other: RHS, m: M) -> Self::Output; } /// Adds two numbers modulo a third number $m$, in place. The inputs must be already reduced modulo /// $m$. pub trait ModAddAssign { fn mod_add_assign(&mut self, other: RHS, m: M); } /// Finds the multiplicative inverse of a number modulo another number $m$. The input must be /// already reduced modulo $m$. pub trait ModInverse { type Output; fn mod_inverse(self, m: M) -> Option; } /// Checks whether a number is reduced modulo another number $m$. pub trait ModIsReduced { fn mod_is_reduced(&self, m: &M) -> bool; } /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced modulo $m$. pub trait ModMul { type Output; fn mod_mul(self, other: RHS, m: M) -> Self::Output; } /// Multiplies two numbers modulo a third number $m$, in place. The inputs must be already reduced /// modulo $m$. pub trait ModMulAssign { fn mod_mul_assign(&mut self, other: RHS, m: M); } /// Multiplies two numbers modulo a third number $m$. The inputs must be already reduced modulo $m$. /// /// If multiple modular multiplications with the same modulus are necessary, it can be quicker to /// precompute some piece of data and reuse it in the multiplication calls. This trait provides a /// function for precomputing the data and a function for using it during multiplication. pub trait ModMulPrecomputed { type Output; type Data; /// Precomputes some data to use for modular multiplication. fn precompute_mod_mul_data(m: &M) -> Self::Data; fn mod_mul_precomputed(self, other: RHS, m: M, data: &Self::Data) -> Self::Output; } /// Multiplies two numbers modulo a third number $m$, in place.The inputs must be already reduced /// modulo $m$. /// /// If multiple modular multiplications with the same modulus are necessary, it can be quicker to /// precompute some piece of data and reuse it in the multiplication calls. This trait provides a /// function for using precomputed data during multiplication. For precomputing the data, use the /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data) function in /// [`ModMulPrecomputed`]. pub trait ModMulPrecomputedAssign: ModMulPrecomputed { fn mod_mul_precomputed_assign(&mut self, other: RHS, m: M, data: &Self::Data); } /// Negates a number modulo another number $m$. The input must be already reduced modulo $m$. pub trait ModNeg { type Output; fn mod_neg(self, m: M) -> Self::Output; } /// Negates a number modulo another number $m$, in place. The input must be already reduced modulo /// $m$. pub trait ModNegAssign { fn mod_neg_assign(&mut self, m: M); } /// Divides a number by another number, returning just the remainder. The remainder has the same /// sign as the divisor (second number). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 \leq /// |r| < |y|$. pub trait Mod { type Output; fn mod_op(self, other: RHS) -> Self::Output; } /// Divides a number by another number, replacing the first number by the remainder. The remainder /// has the same sign as the divisor (second number). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 \leq /// |r| < |y|$. pub trait ModAssign { fn mod_assign(&mut self, other: RHS); } /// Divides the negative of a number by another number, returning the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 \leq /// r < y$. pub trait NegMod { type Output; fn neg_mod(self, other: RHS) -> Self::Output; } /// Divides the negative of a number by another number, replacing the first number by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 \leq /// r < y$. pub trait NegModAssign { fn neg_mod_assign(&mut self, other: RHS); } /// Divides a number by another number, returning just the remainder. The remainder has the opposite /// sign as the divisor (second number). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 \leq /// |r| < |y|$. pub trait CeilingMod { type Output; fn ceiling_mod(self, other: RHS) -> Self::Output; } /// Divides a number by another number, replacing the first number by the remainder. The remainder /// has the same sign as the divisor (second number). /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 \leq /// |r| < |y|$. pub trait CeilingModAssign { fn ceiling_mod_assign(&mut self, other: RHS); } /// Raises a number to a power modulo another number $m$. The base must be already reduced modulo /// $m$. pub trait ModPow { type Output; fn mod_pow(self, exp: RHS, m: M) -> Self::Output; } /// Raises a number to a power modulo another number $m$, in place. The base must be already reduced /// modulo $m$. pub trait ModPowAssign { fn mod_pow_assign(&mut self, exp: RHS, m: M); } /// Raises a number to a power modulo another number $m$. The base must be already reduced modulo /// $m$. /// /// If multiple modular exponentiations with the same modulus are necessary, it can be quicker to /// precompute some piece of data and reuse it in the exponentiation calls. This trait provides a /// function for precomputing the data and a function for using it during exponentiation. pub trait ModPowPrecomputed where Self: Sized, { type Output; type Data; /// Precomputes some data to use for modular exponentiation. fn precompute_mod_pow_data(m: &M) -> Self::Data; fn mod_pow_precomputed(self, exp: RHS, m: M, data: &Self::Data) -> Self::Output; } /// Raises a number to a power modulo another number $m$, in place. The base must be already reduced /// modulo $m$. /// /// If multiple modular exponentiations with the same modulus are necessary, it can be quicker to /// precompute some piece of data and reuse it in the exponentiation calls. This trait provides a /// function for using precomputed data during exponentiation. For precomputing the data, use the /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data) function in /// [`ModPowPrecomputed`]. pub trait ModPowPrecomputedAssign: ModPowPrecomputed { fn mod_pow_precomputed_assign(&mut self, exp: RHS, m: M, data: &Self::Data); } /// Adds two numbers modulo $2^k$. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2Add { type Output; fn mod_power_of_2_add(self, other: RHS, pow: u64) -> Self::Output; } /// Adds two numbers modulo $2^k$, in place. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2AddAssign { fn mod_power_of_2_add_assign(&mut self, other: RHS, pow: u64); } /// Finds the multiplicative inverse of a number modulo $2^k$. The input must be already reduced /// modulo $2^k$. pub trait ModPowerOf2Inverse { type Output; fn mod_power_of_2_inverse(self, pow: u64) -> Option; } /// Checks whether a number is reduced modulo $2^k$. pub trait ModPowerOf2IsReduced { fn mod_power_of_2_is_reduced(&self, pow: u64) -> bool; } /// Multiplies two numbers modulo $2^k$. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2Mul { type Output; fn mod_power_of_2_mul(self, other: RHS, pow: u64) -> Self::Output; } /// Multiplies two numbers modulo $2^k$, in place. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2MulAssign { fn mod_power_of_2_mul_assign(&mut self, other: RHS, pow: u64); } /// Negates a number modulo $2^k$. The input must be already reduced modulo $2^k$. pub trait ModPowerOf2Neg { type Output; fn mod_power_of_2_neg(self, pow: u64) -> Self::Output; } /// Negates a number modulo $2^k$ in place. The input must be already reduced modulo $2^k$. pub trait ModPowerOf2NegAssign { fn mod_power_of_2_neg_assign(&mut self, pow: u64); } /// Raises a number to a power modulo $2^k$. The base must be already reduced modulo $2^k$. pub trait ModPowerOf2Pow { type Output; fn mod_power_of_2_pow(self, exp: RHS, pow: u64) -> Self::Output; } /// Raises a number to a power modulo $2^k$, in place. The base must be already reduced modulo /// $2^k$. pub trait ModPowerOf2PowAssign { fn mod_power_of_2_pow_assign(&mut self, exp: RHS, pow: u64); } /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$. The number must be already /// reduced modulo $2^k$. pub trait ModPowerOf2Shl { type Output; fn mod_power_of_2_shl(self, other: RHS, pow: u64) -> Self::Output; } /// Left-shifts a number (multiplies it by a power of 2) modulo $2^k$, in place. The number must be /// already reduced modulo $2^k$. pub trait ModPowerOf2ShlAssign { fn mod_power_of_2_shl_assign(&mut self, other: RHS, pow: u64); } /// Right-shifts a number (divides it by a power of 2) modulo $2^k$. The number must be already /// reduced modulo $2^k$. pub trait ModPowerOf2Shr { type Output; fn mod_power_of_2_shr(self, other: RHS, pow: u64) -> Self::Output; } /// Right-shifts a number (divides it by a power of 2) modulo $2^k$, in place. The number must be /// already reduced modulo $2^k$. pub trait ModPowerOf2ShrAssign { fn mod_power_of_2_shr_assign(&mut self, other: RHS, pow: u64); } /// Squares a number modulo $2^k$. The input must be already reduced modulo $2^k$. pub trait ModPowerOf2Square { type Output; fn mod_power_of_2_square(self, pow: u64) -> Self::Output; } /// Squares a number modulo $2^k$ in place. The input must be already reduced modulo $2^k$. pub trait ModPowerOf2SquareAssign { fn mod_power_of_2_square_assign(&mut self, pow: u64); } /// Subtracts two numbers modulo $2^k$. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2Sub { type Output; fn mod_power_of_2_sub(self, other: RHS, pow: u64) -> Self::Output; } /// Subtracts two numbers modulo $2^k$, in place. The inputs must be already reduced modulo $2^k$. pub trait ModPowerOf2SubAssign { fn mod_power_of_2_sub_assign(&mut self, other: RHS, pow: u64); } /// Divides a number by $2^k$, returning just the remainder. The remainder is non-negative. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq r < 2^k$. pub trait ModPowerOf2 { type Output; fn mod_power_of_2(self, other: u64) -> Self::Output; } /// Divides a number by $2^k$, replacing the number by the remainder. The remainder is non-negative. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq r < 2^k$. pub trait ModPowerOf2Assign { fn mod_power_of_2_assign(&mut self, other: u64); } /// Divides a number by $2^k$, returning just the remainder. The remainder has the same sign as the /// number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq |r| < 2^k$. pub trait RemPowerOf2 { type Output; fn rem_power_of_2(self, other: u64) -> Self::Output; } /// Divides a number by $2^k$, replacing the number by the remainder. The remainder has the same /// sign as the number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq |r| < 2^k$. pub trait RemPowerOf2Assign { fn rem_power_of_2_assign(&mut self, other: u64); } /// Divides the negative of a number by $2^k$, returning the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and $0 /// \leq r < 2^k$. pub trait NegModPowerOf2 { type Output; fn neg_mod_power_of_2(self, other: u64) -> Self::Output; } /// Divides the negative of a number by $2^k$, replacing the number by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and $0 /// \leq r < 2^k$. pub trait NegModPowerOf2Assign { fn neg_mod_power_of_2_assign(&mut self, other: u64); } /// Divides a number by $2^k$, returning just the remainder. The remainder is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq -r < 2^k$. pub trait CeilingModPowerOf2 { type Output; fn ceiling_mod_power_of_2(self, other: u64) -> Self::Output; } /// Divides a number by $2^k$, replacing the number by the remainder. The remainder is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq -r < 2^k$. pub trait CeilingModPowerOf2Assign { fn ceiling_mod_power_of_2_assign(&mut self, other: u64); } /// Left-shifts a number (multiplies it by a power of 2) modulo another number $m$. The number must /// be already reduced modulo $m$. pub trait ModShl { type Output; fn mod_shl(self, other: RHS, m: M) -> Self::Output; } /// Left-shifts a number (multiplies it by a power of 2) modulo another number $m$, in place. The /// number must be already reduced modulo $m$. pub trait ModShlAssign { fn mod_shl_assign(&mut self, other: RHS, m: M); } /// Left-shifts a number (divides it by a power of 2) modulo another number $m$. The number must be /// already reduced modulo $m$. pub trait ModShr { type Output; fn mod_shr(self, other: RHS, m: M) -> Self::Output; } /// Left-shifts a number (divides it by a power of 2) modulo another number $m$, in place. The /// number must be already reduced modulo $m$. pub trait ModShrAssign { fn mod_shr_assign(&mut self, other: RHS, m: M); } /// Squares a number modulo another number $m$. The input must be already reduced modulo $m$. pub trait ModSquare { type Output; fn mod_square(self, m: M) -> Self::Output; } /// Squares a number modulo another number $m$, in place. The input must be already reduced modulo /// $m$. pub trait ModSquareAssign { fn mod_square_assign(&mut self, m: M); } /// Squares a number modulo another number $m$. The input must be already reduced modulo $m$. /// /// If multiple modular squarings with the same modulus are necessary, it can be quicker to /// precompute some piece of data using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data) function in /// [`ModMulPrecomputed`] and reuse it in the squaring calls. pub trait ModSquarePrecomputed: ModPowPrecomputed where Self: Sized, { fn mod_square_precomputed(self, m: M, data: &Self::Data) -> Self::Output; } /// Squares a number modulo another number $m$, in place. The input must be already reduced modulo /// $m$. /// /// If multiple modular squarings with the same modulus are necessary, it can be quicker to /// precompute some piece of data using /// [`precompute_mod_pow_data`](ModPowPrecomputed::precompute_mod_pow_data) function in /// [`ModMulPrecomputed`] and reuse it in the squaring calls. pub trait ModSquarePrecomputedAssign: ModPowPrecomputed { fn mod_square_precomputed_assign(&mut self, m: M, data: &Self::Data); } /// Adds two numbers modulo a third number $m$. The inputs must be already reduced modulo $m$. pub trait ModSub { type Output; fn mod_sub(self, other: RHS, m: M) -> Self::Output; } /// Adds two numbers modulo a third number $m$, in place. The inputs must be already reduced modulo /// $m$. pub trait ModSubAssign { fn mod_sub_assign(&mut self, other: RHS, m: M); } /// Replaces a number with its negative. Assumes the result is representable. pub trait NegAssign { fn neg_assign(&mut self); } /// Returns the smallest power of 2 greater than or equal to a number. Assumes the result is /// representable. pub trait NextPowerOf2 { type Output; fn next_power_of_2(self) -> Self::Output; } /// Replaces a number with the smallest power of 2 greater than or equal it. Assumes the result is /// representable. pub trait NextPowerOf2Assign { fn next_power_of_2_assign(&mut self); } /// Takes the absolute value of a number. /// /// Returns a tuple of the result along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingAbs { type Output; fn overflowing_abs(self) -> (Self::Output, bool); } /// Replaces a number with its absolute value. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingAbsAssign { fn overflowing_abs_assign(&mut self) -> bool; } /// Adds two numbers. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingAdd { type Output; fn overflowing_add(self, other: RHS) -> (Self::Output, bool); } /// Adds a number to another number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingAddAssign { fn overflowing_add_assign(&mut self, other: RHS) -> bool; } /// Adds a number and the product of two other numbers. /// /// Returns a tuple of the result along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingAddMul { type Output; fn overflowing_add_mul(self, y: Y, z: Z) -> (Self::Output, bool); } /// Adds a number and the product of two other numbers, in place. /// /// Returns a tuple of the result along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingAddMulAssign { fn overflowing_add_mul_assign(&mut self, y: Y, z: Z) -> bool; } /// Divides two numbers. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingDiv { type Output; fn overflowing_div(self, other: RHS) -> (Self::Output, bool); } /// Divides a number by another number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingDivAssign { fn overflowing_div_assign(&mut self, other: RHS) -> bool; } /// Multiplies two numbers. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingMul { type Output; fn overflowing_mul(self, other: RHS) -> (Self::Output, bool); } /// Multiplies a number by another number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingMulAssign { fn overflowing_mul_assign(&mut self, other: RHS) -> bool; } /// Negates a number. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingNeg { type Output; fn overflowing_neg(self) -> (Self::Output, bool); } /// Negates a number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingNegAssign { fn overflowing_neg_assign(&mut self) -> bool; } /// Raises a number to a power. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingPow { type Output; fn overflowing_pow(self, exp: RHS) -> (Self::Output, bool); } /// Raises a number to a power in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingPowAssign { fn overflowing_pow_assign(&mut self, exp: RHS) -> bool; } /// Squares a number. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingSquare { type Output; fn overflowing_square(self) -> (Self::Output, bool); } /// Squares a number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingSquareAssign { fn overflowing_square_assign(&mut self) -> bool; } /// Subtracts two numbers. /// /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingSub { type Output; fn overflowing_sub(self, other: RHS) -> (Self::Output, bool); } /// Subtracts a number by another number in place. /// /// Returns a boolean indicating whether an arithmetic overflow occurred. If an overflow occurred, /// then the wrapped number is assigned. pub trait OverflowingSubAssign { fn overflowing_sub_assign(&mut self, other: RHS) -> bool; } /// Subtracts a number by the product of two other numbers. /// /// Returns a tuple of the result along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingSubMul { type Output; fn overflowing_sub_mul(self, y: Y, z: Z) -> (Self::Output, bool); } /// Subtracts a number by the product of two other numbers, in place. /// /// Returns a tuple of the result along with a boolean indicating whether an arithmetic overflow /// occurred. If an overflow occurred, then the wrapped number is returned. pub trait OverflowingSubMulAssign { fn overflowing_sub_mul_assign(&mut self, y: Y, z: Z) -> bool; } /// Determines whether a number is even or odd. pub trait Parity { /// Determines whether a number is even. fn even(self) -> bool; /// Determines whether a number is odd. fn odd(self) -> bool; } /// Raises a number to a power. Assumes the result is representable. pub trait Pow { type Output; fn pow(self, exp: RHS) -> Self::Output; } /// Raises a number to a power in place. Assumes the result is representable. pub trait PowAssign { fn pow_assign(&mut self, exp: RHS); } /// Raises 2 to a power. pub trait PowerOf2 { fn power_of_2(pow: POW) -> Self; } pub trait Primorial { fn primorial(n: u64) -> Self; fn product_of_first_n_primes(n: u64) -> Self; } pub trait CheckedPrimorial: Sized { fn checked_primorial(n: u64) -> Option; fn checked_product_of_first_n_primes(n: u64) -> Option; } /// Finds the reciprocal (multiplicative inverse) of a number. pub trait Reciprocal { type Output; fn reciprocal(self) -> Self::Output; } /// Replaces a number with its reciprocal (multiplicative inverse). pub trait ReciprocalAssign { fn reciprocal_assign(&mut self); } /// Takes the reciprocal of the square root of a number. pub trait ReciprocalSqrt { type Output; fn reciprocal_sqrt(self) -> Self::Output; } /// Replaces a number with the reciprocal of its square root. pub trait ReciprocalSqrtAssign { fn reciprocal_sqrt_assign(&mut self); } /// Finds the floor of the $n$th root of a number. pub trait FloorRoot { type Output; fn floor_root(self, pow: POW) -> Self::Output; } /// Replaces a number with the floor of its $n$th root. pub trait FloorRootAssign { fn floor_root_assign(&mut self, pow: POW); } /// Finds the ceiling of the $n$th root of a number. pub trait CeilingRoot { type Output; fn ceiling_root(self, pow: POW) -> Self::Output; } /// Replaces a number with the ceiling of its $n$th root. pub trait CeilingRootAssign { fn ceiling_root_assign(&mut self, pow: POW); } /// Finds the $n$th root of a number, returning `None` if it is not a perfect $n$th power. pub trait CheckedRoot { type Output; fn checked_root(self, pow: POW) -> Option; } /// Finds the floor of the $n$th root of a number, returning both the root and the remainder. pub trait RootRem { type RootOutput; type RemOutput; fn root_rem(self, exp: POW) -> (Self::RootOutput, Self::RemOutput); } /// Replaces a number with the floor of its $n$th root, returning the remainder. pub trait RootAssignRem { type RemOutput; fn root_assign_rem(&mut self, exp: POW) -> Self::RemOutput; } /// Rotates a number left, inserting the leftmost bits into the right end. pub trait RotateLeft { type Output; fn rotate_left(self, n: u64) -> Self::Output; } /// Rotates a number left, inserting the leftmost bits into the right end, in place. pub trait RotateLeftAssign { fn rotate_left_assign(&mut self, n: u64); } /// Rotates a number right, inserting the leftmost bits into the left end. pub trait RotateRight { type Output; fn rotate_right(self, n: u64) -> Self::Output; } /// Rotates a number right, inserting the leftmost bits into the left end, in place. pub trait RotateRightAssign { fn rotate_right_assign(&mut self, n: u64); } /// Rounds a number to a multiple of another number, according to a specified rounding mode. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. pub trait RoundToMultiple { type Output; fn round_to_multiple(self, other: RHS, rm: RoundingMode) -> (Self::Output, Ordering); } /// Rounds a number to a multiple of another number in place, according to a specified rounding /// mode. [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. pub trait RoundToMultipleAssign { fn round_to_multiple_assign(&mut self, other: RHS, rm: RoundingMode) -> Ordering; } /// Rounds a number to a multiple of $2^k$, according to a specified rounding mode. An [`Ordering`] /// is also returned, indicating whether the returned value is less than, equal to, or greater than /// the original value. pub trait RoundToMultipleOfPowerOf2 { type Output; fn round_to_multiple_of_power_of_2( self, pow: RHS, rm: RoundingMode, ) -> (Self::Output, Ordering); } /// Rounds a number to a multiple of $2^k$ in place, according to a specified rounding mode. An /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. pub trait RoundToMultipleOfPowerOf2Assign { fn round_to_multiple_of_power_of_2_assign(&mut self, pow: RHS, rm: RoundingMode) -> Ordering; } /// Takes the absolute value of a number, saturating at the numeric bounds instead of overflowing. pub trait SaturatingAbs { type Output; fn saturating_abs(self) -> Self::Output; } /// Replaces a number with its absolute value, saturating at the numeric bounds instead of /// overflowing. pub trait SaturatingAbsAssign { fn saturating_abs_assign(&mut self); } /// Adds two numbers, saturating at the numeric bounds instead of overflowing. pub trait SaturatingAdd { type Output; fn saturating_add(self, other: RHS) -> Self::Output; } /// Add a number to another number in place, saturating at the numeric bounds instead of /// overflowing. pub trait SaturatingAddAssign { fn saturating_add_assign(&mut self, other: RHS); } /// Adds a number and the product of two other numbers, saturating at the numeric bounds instead of /// overflowing. pub trait SaturatingAddMul { type Output; fn saturating_add_mul(self, y: Y, z: Z) -> Self::Output; } /// Adds a number and the product of two other numbers in place, saturating at the numeric bounds /// instead of overflowing. pub trait SaturatingAddMulAssign { fn saturating_add_mul_assign(&mut self, y: Y, z: Z); } /// Multiplies two numbers, saturating at the numeric bounds instead of overflowing. pub trait SaturatingMul { type Output; fn saturating_mul(self, other: RHS) -> Self::Output; } /// Multiplies a number by another number in place, saturating at the numeric bounds instead of /// overflowing. pub trait SaturatingMulAssign { fn saturating_mul_assign(&mut self, other: RHS); } /// Negates a number, saturating at the numeric bounds instead of overflowing. pub trait SaturatingNeg { type Output; fn saturating_neg(self) -> Self::Output; } /// Negates a number in place, saturating at the numeric bounds instead of overflowing. pub trait SaturatingNegAssign { fn saturating_neg_assign(&mut self); } /// Raises a number to a power, saturating at the numeric bounds instead of overflowing. pub trait SaturatingPow { type Output; fn saturating_pow(self, exp: RHS) -> Self::Output; } /// Raises a number to a power in place, saturating at the numeric bounds instead of overflowing. pub trait SaturatingPowAssign { fn saturating_pow_assign(&mut self, exp: RHS); } /// Squares a number, saturating at the numeric bounds instead of overflowing. pub trait SaturatingSquare { type Output; fn saturating_square(self) -> Self::Output; } /// Squares a number in place, saturating at the numeric bounds instead of overflowing. pub trait SaturatingSquareAssign { fn saturating_square_assign(&mut self); } /// Subtracts two numbers, saturating at the numeric bounds instead of overflowing. pub trait SaturatingSub { type Output; fn saturating_sub(self, other: RHS) -> Self::Output; } /// Subtracts a number by another number in place, saturating at the numeric bounds instead of /// overflowing. pub trait SaturatingSubAssign { fn saturating_sub_assign(&mut self, other: RHS); } /// Subtracts a number by the product of two other numbers, saturating at the numeric bounds instead /// of overflowing. pub trait SaturatingSubMul { type Output; fn saturating_sub_mul(self, y: Y, z: Z) -> Self::Output; } /// Subtracts a number by the product of two other numbers in place, saturating at the numeric /// bounds instead of overflowing. pub trait SaturatingSubMulAssign { fn saturating_sub_mul_assign(&mut self, y: Y, z: Z); } /// Left-shifts a number (multiplies it by a power of 2), rounding the result according to a /// specified rounding mode. An [`Ordering`] is also returned, indicating whether the returned value /// is less than, equal to, or greater than the exact value. /// /// Rounding might only be necessary if `other` is negative. pub trait ShlRound { type Output; fn shl_round(self, other: RHS, rm: RoundingMode) -> (Self::Output, Ordering); } /// Left-shifts a number (multiplies it by a power of 2) in place, rounding the result according to /// a specified rounding mode. An [`Ordering`] is also returned, indicating whether the assigned /// value is less than, equal to, or greater than the exact value. /// /// Rounding might only be necessary if `other` is negative. pub trait ShlRoundAssign { fn shl_round_assign(&mut self, other: RHS, rm: RoundingMode) -> Ordering; } /// Right-shifts a number (divides it by a power of 2), rounding the result according to a specified /// rounding mode. An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the exact value. /// /// Rounding might only be necessary if `other` is positive. pub trait ShrRound { type Output; fn shr_round(self, other: RHS, rm: RoundingMode) -> (Self::Output, Ordering); } /// Right-shifts a number (divides it by a power of 2) in place, rounding the result according to a /// specified rounding mode. An [`Ordering`] is also returned, indicating whether the assigned value /// is less than, equal to, or greater than the exact value. /// /// Rounding might only be necessary if `other` is positive. pub trait ShrRoundAssign { fn shr_round_assign(&mut self, other: RHS, rm: RoundingMode) -> Ordering; } /// Returns `Greater`, `Equal`, or `Less`, depending on whether a number is positive, zero, or /// negative, respectively. pub trait Sign { fn sign(&self) -> Ordering; } /// Takes the square root of a number. pub trait Sqrt { type Output; fn sqrt(self) -> Self::Output; } /// Replaces a number with its square root. pub trait SqrtAssign { fn sqrt_assign(&mut self); } /// Finds the floor of the square root of a number. pub trait FloorSqrt { type Output; fn floor_sqrt(self) -> Self::Output; } /// Replaces a number with the floor of its square root. pub trait FloorSqrtAssign { fn floor_sqrt_assign(&mut self); } /// Finds the ceiling of the square root of a number. pub trait CeilingSqrt { type Output; fn ceiling_sqrt(self) -> Self::Output; } /// Replaces a number with the ceiling of its square root. pub trait CeilingSqrtAssign { fn ceiling_sqrt_assign(&mut self); } /// Finds the square root of a number, returning `None` if it is not a perfect square. pub trait CheckedSqrt { type Output; fn checked_sqrt(self) -> Option; } /// Finds the floor of the square root of a number, returning both the root and the remainder. pub trait SqrtRem { type SqrtOutput; type RemOutput; fn sqrt_rem(self) -> (Self::SqrtOutput, Self::RemOutput); } /// Replaces a number with the floor of its square root, returning the remainder. pub trait SqrtAssignRem { type RemOutput; fn sqrt_assign_rem(&mut self) -> Self::RemOutput; } /// Squares a number. pub trait Square { type Output; fn square(self) -> Self::Output; } /// Replaces a number with its square. pub trait SquareAssign { fn square_assign(&mut self); } /// Subtracts a number by the product of two other numbers. pub trait SubMul { type Output; fn sub_mul(self, y: Y, z: Z) -> Self::Output; } /// Subtracts a number by the product of two other numbers, in place. pub trait SubMulAssign { fn sub_mul_assign(&mut self, y: Y, z: Z); } /// Takes the absolute value of a number, wrapping around at the boundary of the type. pub trait WrappingAbs { type Output; fn wrapping_abs(self) -> Self::Output; } /// Replaces a number with its absolute value, wrapping around at the boundary of the type. pub trait WrappingAbsAssign { fn wrapping_abs_assign(&mut self); } /// Adds two numbers, wrapping around at the boundary of the type. pub trait WrappingAdd { type Output; fn wrapping_add(self, other: RHS) -> Self::Output; } /// Adds a number to another number in place, wrapping around at the boundary of the type. pub trait WrappingAddAssign { fn wrapping_add_assign(&mut self, other: RHS); } /// Adds a number and the product of two other numbers, wrapping around at the boundary of the type. pub trait WrappingAddMul { type Output; fn wrapping_add_mul(self, y: Y, z: Z) -> Self::Output; } /// Adds a number and the product of two other numbers, in place, wrapping around at the boundary of /// the type. pub trait WrappingAddMulAssign { fn wrapping_add_mul_assign(&mut self, y: Y, z: Z); } /// Divides a number by another number, wrapping around at the boundary of the type. pub trait WrappingDiv { type Output; fn wrapping_div(self, other: RHS) -> Self::Output; } /// Divides a number by another number in place, wrapping around at the boundary of the type. pub trait WrappingDivAssign { fn wrapping_div_assign(&mut self, other: RHS); } /// Multiplies two numbers, wrapping around at the boundary of the type. pub trait WrappingMul { type Output; fn wrapping_mul(self, other: RHS) -> Self::Output; } /// Multiplies a number by another number in place, wrapping around at the boundary of the type. pub trait WrappingMulAssign { fn wrapping_mul_assign(&mut self, other: RHS); } /// Negates a number, wrapping around at the boundary of the type. pub trait WrappingNeg { type Output; fn wrapping_neg(self) -> Self::Output; } /// Negates a number in place, wrapping around at the boundary of the type. pub trait WrappingNegAssign { fn wrapping_neg_assign(&mut self); } /// Raises a number to a power, wrapping around at the boundary of the type. pub trait WrappingPow { type Output; fn wrapping_pow(self, exp: RHS) -> Self::Output; } /// Raises a number to a power in place, wrapping around at the boundary of the type. pub trait WrappingPowAssign { fn wrapping_pow_assign(&mut self, exp: RHS); } /// Squares a number, wrapping around at the boundary of the type. pub trait WrappingSquare { type Output; fn wrapping_square(self) -> Self::Output; } /// Squares a number in place, wrapping around at the boundary of the type. pub trait WrappingSquareAssign { fn wrapping_square_assign(&mut self); } /// Subtracts two numbers, wrapping around at the boundary of the type. pub trait WrappingSub { type Output; fn wrapping_sub(self, other: RHS) -> Self::Output; } /// Subtracts a number by another number in place, wrapping around at the boundary of the type. pub trait WrappingSubAssign { fn wrapping_sub_assign(&mut self, other: RHS); } /// Subtracts a number by the product of two other numbers, wrapping around at the boundary of the /// type. pub trait WrappingSubMul { type Output; fn wrapping_sub_mul(self, y: Y, z: Z) -> Self::Output; } /// Subtracts a number by the product of two other numbers, in place, wrapping around at the /// boundary of the type. pub trait WrappingSubMulAssign { fn wrapping_sub_mul_assign(&mut self, y: Y, z: Z); } /// Multiplies two numbers, returning the product as a pair of `Self` values. /// /// The more significant number always comes first. pub trait XMulYToZZ: Sized { fn x_mul_y_to_zz(x: Self, y: Self) -> (Self, Self); } /// Adds two numbers, each composed of two `Self` values, returning the sum as a pair of `Self` /// values. /// /// The more significant number always comes first. Addition is wrapping, and overflow is not /// indicated. pub trait XXAddYYToZZ: Sized { fn xx_add_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self); } /// Computes the quotient and remainder of two numbers. The first is composed of two `Self` values, /// and the second of a single one. /// /// `x_1` must be less than `y`. pub trait XXDivModYToQR: Sized { fn xx_div_mod_y_to_qr(x_1: Self, x_0: Self, y: Self) -> (Self, Self); } /// Subtracts two numbers, each composed of two `Self` values, returing the difference as a pair of /// `Self` values. /// /// The more significant number always comes first. Subtraction is wrapping, and overflow is not /// indicated. pub trait XXSubYYToZZ: Sized { fn xx_sub_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self); } /// Adds two numbers, each composed of three `Self` values, returning the sum as a triple of `Self` /// values. /// /// The more significant number always comes first. Addition is wrapping, and overflow is not /// indicated. pub trait XXXAddYYYToZZZ: Sized { fn xxx_add_yyy_to_zzz( x_2: Self, x_1: Self, x_0: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self); } /// Subtracts two numbers, each composed of three `Self` values, returing the difference as a triple /// of `Self` values. /// /// The more significant number always comes first. Subtraction is wrapping, and overflow is not /// indicated. pub trait XXXSubYYYToZZZ: Sized { fn xxx_sub_yyy_to_zzz( x_2: Self, x_1: Self, x_0: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self); } /// Adds two numbers, each composed of four `Self` values, returning the sum as a quadruple of /// `Self` values. /// /// The more significant number always comes first. Addition is wrapping, and overflow is not /// indicated. pub trait XXXXAddYYYYToZZZZ: Sized { #[allow(clippy::too_many_arguments)] fn xxxx_add_yyyy_to_zzzz( x_3: Self, x_2: Self, x_1: Self, x_0: Self, y_3: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self, Self); } ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingAbs, WrappingAbsAssign}; macro_rules! impl_wrapping_abs { ($t:ident) => { impl WrappingAbs for $t { type Output = $t; /// This is a wrapper over the `wrapping_abs` functions in the standard library, for /// example [this one](i32::wrapping_abs). #[inline] fn wrapping_abs(self) -> $t { $t::wrapping_abs(self) } } impl WrappingAbsAssign for $t { /// Replaces a number with its absolute value, wrapping around at the boundary of the /// type. /// /// $$ /// x \gets \\begin{cases} /// |x| & \text{if} \\quad x > -2^{W-1}, \\\\ /// -2^{W-1} & \text{if} \\quad x = -2^{W-1}, /// \\end{cases} /// $$ /// where $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_abs#wrapping_abs_assign). #[inline] fn wrapping_abs_assign(&mut self) { *self = self.wrapping_abs(); } } }; } apply_to_signeds!(impl_wrapping_abs); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_add.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingAdd, WrappingAddAssign}; macro_rules! impl_wrapping_add { ($t:ident) => { impl WrappingAdd<$t> for $t { type Output = $t; /// This is a wrapper over the `wrapping_add` functions in the standard library, for /// example [this one](u32::wrapping_add). #[inline] fn wrapping_add(self, other: $t) -> $t { $t::wrapping_add(self, other) } } impl WrappingAddAssign<$t> for $t { /// Adds a number to another number in place, wrapping around at the boundary of the /// type. /// /// $x \gets z$, where $z \equiv x + y \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_add#wrapping_add_assign). #[inline] fn wrapping_add_assign(&mut self, other: $t) { *self = self.wrapping_add(other); } } }; } apply_to_primitive_ints!(impl_wrapping_add); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_add_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingAddMul, WrappingAddMulAssign}; use crate::num::basic::integers::PrimitiveInt; fn wrapping_add_mul(x: T, y: T, z: T) -> T { x.wrapping_add(y.wrapping_mul(z)) } fn wrapping_add_mul_assign(x: &mut T, y: T, z: T) { x.wrapping_add_assign(y.wrapping_mul(z)); } macro_rules! impl_wrapping_add_mul { ($t:ident) => { impl WrappingAddMul<$t> for $t { type Output = $t; /// Adds a number and the product of two other numbers, wrapping around at the boundary /// of the type. /// /// $f(x, y, z) = w$, where $w \equiv x + yz \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_add_mul#wrapping_add_mul). #[inline] fn wrapping_add_mul(self, y: $t, z: $t) -> $t { wrapping_add_mul(self, y, z) } } impl WrappingAddMulAssign<$t> for $t { /// Adds a number and the product of two other numbers in place, wrapping around at the /// boundary of the type. /// /// $x \gets w$, where $w \equiv x + yz \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_add_mul#wrapping_add_mul_assign). #[inline] fn wrapping_add_mul_assign(&mut self, y: $t, z: $t) { wrapping_add_mul_assign(self, y, z); } } }; } apply_to_primitive_ints!(impl_wrapping_add_mul); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_div.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingDiv, WrappingDivAssign}; macro_rules! impl_wrapping_div { ($t:ident) => { impl WrappingDiv<$t> for $t { type Output = $t; /// This is a wrapper over the `wrapping_div` functions in the standard library, for /// example [this one](u32::wrapping_div). #[inline] fn wrapping_div(self, other: $t) -> $t { $t::wrapping_div(self, other) } } impl WrappingDivAssign<$t> for $t { /// Divides a number by another number in place, wrapping around at the boundary of the /// type. /// /// Wrapping only occurs when `Self` is signed, `self` is `Self::MIN`, and `other` is /// -1. The "actual" result, `-Self::MIN`, can't be represented and is wrapped back to /// `Self::MIN`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_div#wrapping_div_assign). #[inline] fn wrapping_div_assign(&mut self, other: $t) { *self = self.wrapping_div(other); } } }; } apply_to_primitive_ints!(impl_wrapping_div); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingMul, WrappingMulAssign}; macro_rules! impl_wrapping_mul { ($t:ident) => { impl WrappingMul<$t> for $t { type Output = $t; /// This is a wrapper over the `wrapping_mul` functions in the standard library, for /// example [this one](u32::wrapping_mul). #[inline] fn wrapping_mul(self, other: $t) -> $t { $t::wrapping_mul(self, other) } } impl WrappingMulAssign<$t> for $t { /// Adds a number to another number in place, wrapping around at the boundary of the /// type. /// /// $x \gets z$, where $z \equiv xy \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_mul#wrapping_mul_assign). #[inline] fn wrapping_mul_assign(&mut self, other: $t) { *self = self.wrapping_mul(other); } } }; } apply_to_primitive_ints!(impl_wrapping_mul); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingNeg, WrappingNegAssign}; macro_rules! impl_wrapping_neg { ($t:ident) => { impl WrappingNeg for $t { type Output = $t; /// This is a wrapper over the `wrapping_neg` functions in the standard library, for /// example [this one](u32::wrapping_neg). #[inline] fn wrapping_neg(self) -> $t { $t::wrapping_neg(self) } } impl WrappingNegAssign for $t { /// Negates a number in place, wrapping around at the boundary of the type. /// /// $x \gets y$, where $y \equiv -x \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_neg#wrapping_neg_assign). #[inline] fn wrapping_neg_assign(&mut self) { *self = self.wrapping_neg(); } } }; } apply_to_primitive_ints!(impl_wrapping_neg); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_pow.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{Parity, UnsignedAbs, WrappingPow, WrappingPowAssign}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::logic::traits::BitIterable; fn wrapping_pow_unsigned(x: T, exp: u64) -> T { if exp == 0 { T::ONE } else if x < T::TWO { x } else { let mut power = x; for bit in exp.bits().rev().skip(1) { power.wrapping_square_assign(); if bit { power.wrapping_mul_assign(x); } } power } } fn wrapping_pow_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( x: S, exp: u64, ) -> S { let p_abs = x.unsigned_abs().wrapping_pow(exp); if x >= S::ZERO || exp.even() { S::wrapping_from(p_abs) } else { S::wrapping_from(p_abs).wrapping_neg() } } macro_rules! impl_wrapping_pow_unsigned { ($t:ident) => { impl WrappingPow for $t { type Output = $t; /// This is a wrapper over the `wrapping_pow` functions in the standard library, for /// example [this one](u32::wrapping_pow). #[inline] fn wrapping_pow(self, exp: u64) -> $t { wrapping_pow_unsigned(self, exp) } } }; } apply_to_unsigneds!(impl_wrapping_pow_unsigned); macro_rules! impl_wrapping_pow_signed { ($t:ident) => { impl WrappingPow for $t { type Output = $t; /// This is a wrapper over the `wrapping_pow` functions in the standard library, for /// example [this one](i32::wrapping_pow). #[inline] fn wrapping_pow(self, exp: u64) -> $t { wrapping_pow_signed(self, exp) } } }; } apply_to_signeds!(impl_wrapping_pow_signed); macro_rules! impl_wrapping_pow_primitive_int { ($t:ident) => { impl WrappingPowAssign for $t { /// Raises a number to a power, in place, wrapping around at the boundary of the type. /// /// $x \gets y$, where $y \equiv x^n \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_pow#wrapping_pow_assign). #[inline] fn wrapping_pow_assign(&mut self, exp: u64) { *self = WrappingPow::wrapping_pow(*self, exp); } } }; } apply_to_primitive_ints!(impl_wrapping_pow_primitive_int); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_square.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingMulAssign, WrappingSquare, WrappingSquareAssign}; macro_rules! impl_wrapping_square { ($t:ident) => { impl WrappingSquare for $t { type Output = $t; /// Squares a number, wrapping around at the boundary of the type. /// /// $f(x) = y$, where $y \equiv x^2 \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_square#wrapping_square). #[inline] fn wrapping_square(self) -> $t { self.wrapping_mul(self) } } impl WrappingSquareAssign for $t { /// Squares a number in place, wrapping around at the boundary of the type. /// /// $x \gets y$, where $y \equiv x^2 \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_square#wrapping_square_assign). #[inline] fn wrapping_square_assign(&mut self) { self.wrapping_mul_assign(*self); } } }; } apply_to_primitive_ints!(impl_wrapping_square); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_sub.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingSub, WrappingSubAssign}; macro_rules! impl_wrapping_sub { ($t:ident) => { impl WrappingSub<$t> for $t { type Output = $t; /// This is a wrapper over the `wrapping_sub` functions in the standard library, for /// example [this one](u32::wrapping_sub). #[inline] fn wrapping_sub(self, other: $t) -> $t { $t::wrapping_sub(self, other) } } impl WrappingSubAssign<$t> for $t { /// Subtracts a number by another number in place, wrapping around at the boundary of /// the type. /// /// $x \gets z$, where $z \equiv x - y \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_sub#wrapping_sub_assign). #[inline] fn wrapping_sub_assign(&mut self, other: $t) { *self = self.wrapping_sub(other); } } }; } apply_to_primitive_ints!(impl_wrapping_sub); ================================================ FILE: malachite-base/src/num/arithmetic/wrapping_sub_mul.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{WrappingSubMul, WrappingSubMulAssign}; use crate::num::basic::integers::PrimitiveInt; fn wrapping_sub_mul(x: T, y: T, z: T) -> T { x.wrapping_sub(y.wrapping_mul(z)) } fn wrapping_sub_mul_assign(x: &mut T, y: T, z: T) { x.wrapping_sub_assign(y.wrapping_mul(z)); } macro_rules! impl_wrapping_sub_mul { ($t:ident) => { impl WrappingSubMul<$t> for $t { type Output = $t; /// Subtracts a number by the product of two other numbers, wrapping around at the /// boundary of the type. /// /// $f(x, y, z) = w$, where $w \equiv x - yz \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_sub_mul#wrapping_sub_mul). #[inline] fn wrapping_sub_mul(self, y: $t, z: $t) -> $t { wrapping_sub_mul(self, y, z) } } impl WrappingSubMulAssign<$t> for $t { /// Subtracts a number by the product of two other numbers in place, wrapping around at /// the boundary of the type. /// /// $x \gets w$, where $w \equiv x - yz \mod 2^W$ and $W$ is `Self::WIDTH`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::wrapping_sub_mul#wrapping_sub_mul_assign). #[inline] fn wrapping_sub_mul_assign(&mut self, y: $t, z: $t) { wrapping_sub_mul_assign(self, y, z) } } }; } apply_to_primitive_ints!(impl_wrapping_sub_mul); ================================================ FILE: malachite-base/src/num/arithmetic/x_mul_y_to_zz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2020 Free Software // Foundation, Inc. // // 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 crate::num::arithmetic::traits::XMulYToZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::half::{wide_join_halves, wide_split_in_half, wide_upper_half}; use crate::num::conversion::traits::{HasHalf, SplitInHalf, WrappingFrom}; fn implicit_x_mul_y_to_zz + HasHalf + PrimitiveUnsigned + SplitInHalf>( x: T, y: T, ) -> (T, T) { (DT::from(x) * DT::from(y)).split_in_half() } pub_test! {explicit_x_mul_y_to_zz(x: T, y: T) -> (T, T) { let (x_1, x_0) = wide_split_in_half(x); let (y_1, y_0) = wide_split_in_half(y); let x_0_y_0 = x_0 * y_0; let mut x_0_y_1 = x_0 * y_1; let x_1_y_0 = x_1 * y_0; let mut x_1_y_1 = x_1 * y_1; let (x_0_y_0_1, x_0_y_0_0) = wide_split_in_half(x_0_y_0); x_0_y_1.wrapping_add_assign(x_0_y_0_1); if x_0_y_1.overflowing_add_assign(x_1_y_0) { x_1_y_1.wrapping_add_assign(T::power_of_2(T::WIDTH >> 1)); } let z_1 = x_1_y_1.wrapping_add(wide_upper_half(x_0_y_1)); let z_0 = wide_join_halves(x_0_y_1, x_0_y_0_0); (z_1, z_0) }} macro_rules! implicit_x_mul_y_to_zz { ($t:ident, $dt:ident) => { impl XMulYToZZ for $t { /// Multiplies two numbers, returning the product as a pair of `Self` values. /// /// The more significant value always comes first. /// /// $$ /// f(x, y) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x, y, z_1, z_0 < 2^W$, and /// $$ /// xy = 2^Wz_1 + z_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::x_mul_y_to_zz#x_mul_y_to_zz). /// /// This is equivalent to `umul_ppmm` from `longlong.h`, GMP 6.2.1, where `(w1, w0)` is /// returned. #[inline] fn x_mul_y_to_zz(x: $t, y: $t) -> ($t, $t) { implicit_x_mul_y_to_zz::<$t, $dt>(x, y) } } }; } implicit_x_mul_y_to_zz!(u8, u16); implicit_x_mul_y_to_zz!(u16, u32); implicit_x_mul_y_to_zz!(u32, u64); implicit_x_mul_y_to_zz!(u64, u128); impl XMulYToZZ for usize { /// Multiplies two numbers, returning the product as a pair of [`usize`] values. /// /// The more significant value always comes first. /// /// $$ /// f(x, y) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x, y, z_1, z_0 < 2^W$, and /// $$ /// xy = 2^Wz_1 + z_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::x_mul_y_to_zz#x_mul_y_to_zz). /// /// This is equivalent to `umul_ppmm` from `longlong.h`, GMP 6.2.1, where `(w1, w0)` is /// returned. fn x_mul_y_to_zz(x: Self, y: Self) -> (Self, Self) { if USIZE_IS_U32 { let (z_1, z_0) = u32::x_mul_y_to_zz(u32::wrapping_from(x), u32::wrapping_from(y)); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } else { let (z_1, z_0) = u64::x_mul_y_to_zz(u64::wrapping_from(x), u64::wrapping_from(y)); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } } } impl XMulYToZZ for u128 { /// Multiplies two numbers, returning the product as a pair of [`u128`] values. /// /// The more significant value always comes first. /// /// $$ /// f(x, y) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x, y, z_1, z_0 < 2^W$, and /// $$ /// xy = 2^Wz_1 + z_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::x_mul_y_to_zz#x_mul_y_to_zz). /// /// This is equivalent to `umul_ppmm` from `longlong.h`, GMP 6.2.1, where `(w1, w0)` is /// returned. #[inline] fn x_mul_y_to_zz(x: Self, y: Self) -> (Self, Self) { explicit_x_mul_y_to_zz(x, y) } } ================================================ FILE: malachite-base/src/num/arithmetic/xx_add_yy_to_zz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2020 Free Software // Foundation, Inc. // // 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 crate::num::arithmetic::traits::XXAddYYToZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{JoinHalves, SplitInHalf, WrappingFrom}; fn implicit_xx_add_yy_to_zz( x_1: DT::Half, x_0: DT::Half, y_1: DT::Half, y_0: DT::Half, ) -> (DT::Half, DT::Half) { DT::join_halves(x_1, x_0) .wrapping_add(DT::join_halves(y_1, y_0)) .split_in_half() } pub_test! { explicit_xx_add_yy_to_zz(x_1: T, x_0: T, y_1: T, y_0: T) -> (T, T) { let (z_0, carry) = x_0.overflowing_add(y_0); let mut z_1 = x_1.wrapping_add(y_1); if carry { z_1.wrapping_add_assign(T::ONE); } (z_1, z_0) }} macro_rules! implicit_xx_add_yy_to_zz { ($t:ident, $dt:ident) => { impl XXAddYYToZZ for $t { /// Adds two numbers, each composed of two `Self` values, returning the sum as a pair of /// `Self` values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is /// not indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) + (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_add_yy_to_zz#xx_add_yy_to_zz). /// /// This is equivalent to `add_ssaaaa` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. #[inline] fn xx_add_yy_to_zz(x_1: $t, x_0: $t, y_1: $t, y_0: $t) -> ($t, $t) { implicit_xx_add_yy_to_zz::<$dt>(x_1, x_0, y_1, y_0) } } }; } implicit_xx_add_yy_to_zz!(u8, u16); implicit_xx_add_yy_to_zz!(u16, u32); implicit_xx_add_yy_to_zz!(u32, u64); implicit_xx_add_yy_to_zz!(u64, u128); impl XXAddYYToZZ for usize { /// Adds two numbers, each composed of two [`usize`] values, returning the sum as a pair of /// `usize` values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) + (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_add_yy_to_zz#xx_add_yy_to_zz). /// /// This is equivalent to `add_ssaaaa` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. fn xx_add_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self) { if USIZE_IS_U32 { let (z_1, z_0) = u32::xx_add_yy_to_zz( u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y_1), u32::wrapping_from(y_0), ); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } else { let (z_1, z_0) = u64::xx_add_yy_to_zz( u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y_1), u64::wrapping_from(y_0), ); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } } } impl XXAddYYToZZ for u128 { /// Adds two numbers, each composed of two [`u128`] values, returning the sum as a pair of /// [`u128`] values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) + (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_add_yy_to_zz#xx_add_yy_to_zz). /// /// This is equivalent to `add_ssaaaa` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. #[inline] fn xx_add_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self) { explicit_xx_add_yy_to_zz(x_1, x_0, y_1, y_0) } } ================================================ FILE: malachite-base/src/num/arithmetic/xx_div_mod_y_to_qr.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // Copyright © 2009, 2015, 2016 William Hart // // Copyright © 2011 Fredrik Johansson // // 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 crate::num::arithmetic::traits::XXDivModYToQR; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::half::{wide_join_halves, wide_split_in_half}; use crate::num::conversion::traits::WrappingFrom; use crate::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use crate::num::logic::traits::LeadingZeros; fn implicit_xx_div_mod_y_to_qr< T: PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( x_1: T, x_0: T, y: T, ) -> (T, T) { assert!(x_1 < y); let (q, r) = DT::join_halves(x_1, x_0).div_mod(DT::from(y)); (q.lower_half(), r.lower_half()) } // This is equivalent to `udiv_qrnnd_int` from `longlong.h`, FLINT 2.7.1, where `(q, r)` is // returned. fn explicit_xx_div_mod_y_to_qr_normalized(x_1: T, x_0: T, y: T) -> (T, T) { let (d_1, d_0) = wide_split_in_half(y); let (x_0_1, x_0_0) = wide_split_in_half(x_0); let mut q_1 = x_1 / d_1; let mut r_1 = x_1.wrapping_sub(q_1.wrapping_mul(d_1)); let product = q_1.wrapping_mul(d_0); r_1 = wide_join_halves(r_1, x_0_1); if r_1 < product { q_1.wrapping_sub_assign(T::ONE); if !r_1.overflowing_add_assign(y) && r_1 < product { q_1.wrapping_sub_assign(T::ONE); r_1.wrapping_add_assign(y); } } r_1.wrapping_sub_assign(product); let mut q_0 = r_1 / d_1; let mut r_0 = r_1.wrapping_sub(q_0.wrapping_mul(d_1)); let product = q_0.wrapping_mul(d_0); r_0 = wide_join_halves(r_0, x_0_0); if r_0 < product { q_0.wrapping_sub_assign(T::ONE); if !r_0.overflowing_add_assign(y) && r_0 < product { q_0.wrapping_sub_assign(T::ONE); r_0.wrapping_add_assign(y); } } r_0.wrapping_sub_assign(product); (wide_join_halves(q_1, q_0), r_0) } // This is udiv_qrnnd from longlong.h, FLINT 2.7.1, where (q, r) is returned. pub_test! {explicit_xx_div_mod_y_to_qr(x_1: T, x_0: T, y: T) -> (T, T) { assert!(x_1 < y); let shift = LeadingZeros::leading_zeros(y); if shift == 0 { explicit_xx_div_mod_y_to_qr_normalized(x_1, x_0, y) } else { let (q, r) = explicit_xx_div_mod_y_to_qr_normalized( (x_1 << shift) | (x_0 >> (T::WIDTH - shift)), x_0 << shift, y << shift, ); (q, r >> shift) } }} macro_rules! implicit_xx_div_mod_to_qr { ($t:ident, $dt:ident) => { impl XXDivModYToQR for $t { /// Computes the quotient and remainder of two numbers. The first is composed of two /// `Self` values, and the second of a single one. /// /// `x_1` must be less than `y`. /// /// $$ /// f(x_1, x_0, y) = (q, r), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y, q, r < 2^W$, /// /// $x_1, r < y$, and /// $$ /// qy + r = 2^Wx_1 + x_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_div_mod_y_to_qr#xx_div_mod_y_to_qr). /// /// This is equivalent to `udiv_qrnnd` from `longlong.h`, FLINT 2.7.1, where `(q, r)` is /// returned. #[inline] fn xx_div_mod_y_to_qr(x_1: $t, x_0: $t, y: $t) -> ($t, $t) { implicit_xx_div_mod_y_to_qr::<$t, $dt>(x_1, x_0, y) } } }; } implicit_xx_div_mod_to_qr!(u8, u16); implicit_xx_div_mod_to_qr!(u16, u32); implicit_xx_div_mod_to_qr!(u32, u64); implicit_xx_div_mod_to_qr!(u64, u128); impl XXDivModYToQR for usize { /// Computes the quotient and remainder of two numbers. The first is composed of two [`usize`] /// values, and the second of a single one. /// /// `x_1` must be less than `y`. /// /// $$ /// f(x_1, x_0, y) = (q, r), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y, q, r < 2^W$, /// /// $x_1, r < y$, and /// $$ /// qy + r = 2^Wx_1 + x_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_div_mod_y_to_qr#xx_div_mod_y_to_qr). /// /// This is `udiv_qrnnd` from `longlong.h`, FLINT 2.7.1, where `(q, r)` is returned. fn xx_div_mod_y_to_qr(x_1: Self, x_0: Self, y: Self) -> (Self, Self) { if USIZE_IS_U32 { let (q, r) = u32::xx_div_mod_y_to_qr( u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y), ); (Self::wrapping_from(q), Self::wrapping_from(r)) } else { let (q, r) = u64::xx_div_mod_y_to_qr( u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y), ); (Self::wrapping_from(q), Self::wrapping_from(r)) } } } impl XXDivModYToQR for u128 { /// Computes the quotient and remainder of two numbers. The first is composed of two [`u128`] /// values, and the second of a single one. /// /// `x_1` must be less than `y`. /// /// $$ /// f(x_1, x_0, y) = (q, r), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y, q, r < 2^W$, /// /// $x_1, r < y$, and /// $$ /// qy + r = 2^Wx_1 + x_0. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_div_mod_y_to_qr#xx_div_mod_y_to_qr). /// /// This is equivalent to `udiv_qrnnd` from `longlong.h`, FLINT 2.7.1, where `(q, r)` is /// returned. #[inline] fn xx_div_mod_y_to_qr(x_1: Self, x_0: Self, y: Self) -> (Self, Self) { explicit_xx_div_mod_y_to_qr(x_1, x_0, y) } } ================================================ FILE: malachite-base/src/num/arithmetic/xx_sub_yy_to_zz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2020 Free Software // Foundation, Inc. // // 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 crate::num::arithmetic::traits::XXSubYYToZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{JoinHalves, SplitInHalf, WrappingFrom}; fn implicit_xx_sub_yy_to_zz( x_1: DT::Half, x_0: DT::Half, y_1: DT::Half, y_0: DT::Half, ) -> (DT::Half, DT::Half) { DT::join_halves(x_1, x_0) .wrapping_sub(DT::join_halves(y_1, y_0)) .split_in_half() } pub_test! { explicit_xx_sub_yy_to_zz(x_1: T, x_0: T, y_1: T, y_0: T) -> (T, T) { let (z_0, borrow) = x_0.overflowing_sub(y_0); let mut z_1 = x_1.wrapping_sub(y_1); if borrow { z_1.wrapping_sub_assign(T::ONE); } (z_1, z_0) }} macro_rules! implicit_xx_sub_yy_to_zz { ($t:ident, $dt:ident) => { impl XXSubYYToZZ for $t { /// Subtracts two numbers, each composed of two `Self` values, returning the difference /// as a pair of `Self` values. /// /// The more significant value always comes first. Subtraction is wrapping, and overflow /// is not indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) - (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_sub_yy_to_zz#xx_sub_yy_to_zz). /// /// This is equivalent to `sub_ddmmss` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. #[inline] fn xx_sub_yy_to_zz(x_1: $t, x_0: $t, y_1: $t, y_0: $t) -> ($t, $t) { implicit_xx_sub_yy_to_zz::<$dt>(x_1, x_0, y_1, y_0) } } }; } implicit_xx_sub_yy_to_zz!(u8, u16); implicit_xx_sub_yy_to_zz!(u16, u32); implicit_xx_sub_yy_to_zz!(u32, u64); implicit_xx_sub_yy_to_zz!(u64, u128); impl XXSubYYToZZ for usize { /// Subtracts two numbers, each composed of two [`usize`] values, returning the difference as a /// pair of [`usize`] values. /// /// The more significant value always comes first. Subtraction is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) - (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xx_sub_yy_to_zz#xx_sub_yy_to_zz). /// /// This is equivalent to `sub_ddmmss` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. fn xx_sub_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self) { if USIZE_IS_U32 { let (z_1, z_0) = u32::xx_sub_yy_to_zz( u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y_1), u32::wrapping_from(y_0), ); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } else { let (z_1, z_0) = u64::xx_sub_yy_to_zz( u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y_1), u64::wrapping_from(y_0), ); (Self::wrapping_from(z_1), Self::wrapping_from(z_0)) } } } impl XXSubYYToZZ for u128 { /// Subtracts two numbers, each composed of two [`u128`] values, returning the difference as a /// pair of [`u128`] values. /// /// The more significant value always comes first. Subtraction is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_1, x_0, y_1, y_0) = (z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_1, x_0, y_1, y_0, z_1, z_0 < 2^W$, and /// $$ /// (2^Wx_1 + x_0) - (2^Wy_1 + y_0) \equiv 2^Wz_1 + z_0 \mod 2^{2W}. /// $$ /// /// # Examples /// See [here](super::xx_sub_yy_to_zz#xx_sub_yy_to_zz). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to `sub_ddmmss` from `longlong.h`, GMP 6.2.1, where `(sh, sl)` is /// returned. #[inline] fn xx_sub_yy_to_zz(x_1: Self, x_0: Self, y_1: Self, y_0: Self) -> (Self, Self) { explicit_xx_sub_yy_to_zz(x_1, x_0, y_1, y_0) } } ================================================ FILE: malachite-base/src/num/arithmetic/xxx_add_yyy_to_zzz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // Copyright © 2009, 2015, 2016 William Hart // // Copyright © 2011 Fredrik Johansson // // 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 crate::num::arithmetic::traits::XXXAddYYYToZZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; pub_test! {xxx_add_yyy_to_zzz( x_2: T, x_1: T, x_0: T, y_2: T, y_1: T, y_0: T, ) -> (T, T, T) { let (z_0, carry_1) = x_0.overflowing_add(y_0); let (mut z_1, mut carry_2) = x_1.overflowing_add(y_1); if carry_1 { carry_2 |= z_1.overflowing_add_assign(T::ONE); } let mut z_2 = x_2.wrapping_add(y_2); if carry_2 { z_2.wrapping_add_assign(T::ONE); } (z_2, z_1, z_0) }} macro_rules! impl_xxx_add_yyy_to_zzz { ($t:ident) => { impl XXXAddYYYToZZZ for $t { /// Adds two numbers, each composed of three `Self` values, returning the sum as a /// triple of `Self` values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is /// not indicated. /// /// $$ /// f(x_2, x_1, x_0, y_2, y_1, y_0) = (z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_2, x_1, x_0, y_2, y_1, y_0, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{2W}x_2 + 2^Wx_1 + x_0) + (2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{3W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxx_add_yyy_to_zzz#xxx_add_yyy_to_zzz). /// /// This is equivalent to `add_sssaaaaaa` from `longlong.h`, FLINT 2.7.1, where `(sh, /// sm, sl)` is returned. #[inline] fn xxx_add_yyy_to_zzz( x_2: $t, x_1: $t, x_0: $t, y_2: $t, y_1: $t, y_0: $t, ) -> ($t, $t, $t) { xxx_add_yyy_to_zzz::<$t>(x_2, x_1, x_0, y_2, y_1, y_0) } } }; } impl_xxx_add_yyy_to_zzz!(u8); impl_xxx_add_yyy_to_zzz!(u16); impl_xxx_add_yyy_to_zzz!(u32); impl_xxx_add_yyy_to_zzz!(u64); impl_xxx_add_yyy_to_zzz!(u128); impl XXXAddYYYToZZZ for usize { /// Adds two numbers, each composed of three [`usize`] values, returning the sum as a triple of /// [`usize`] values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_2, x_1, x_0, y_2, y_1, y_0) = (z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_2, x_1, x_0, y_2, y_1, y_0, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{2W}x_2 + 2^Wx_1 + x_0) + (2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{3W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxx_add_yyy_to_zzz#xxx_add_yyy_to_zzz). /// /// This is equivalent to `add_sssaaaaaa` from `longlong.h`, FLINT 2.7.1, where `(sh, sm, sl)` /// is returned. fn xxx_add_yyy_to_zzz( x_2: Self, x_1: Self, x_0: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self) { if USIZE_IS_U32 { let (z_2, z_1, z_0) = u32::xxx_add_yyy_to_zzz( u32::wrapping_from(x_2), u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y_2), u32::wrapping_from(y_1), u32::wrapping_from(y_0), ); ( Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } else { let (z_2, z_1, z_0) = u64::xxx_add_yyy_to_zzz( u64::wrapping_from(x_2), u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y_2), u64::wrapping_from(y_1), u64::wrapping_from(y_0), ); ( Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } } } ================================================ FILE: malachite-base/src/num/arithmetic/xxx_sub_yyy_to_zzz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // Copyright © 2009, 2015, 2016 William Hart // // Copyright © 2011 Fredrik Johansson // // 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 crate::num::arithmetic::traits::XXXSubYYYToZZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; pub_test! {xxx_sub_yyy_to_zzz( x_2: T, x_1: T, x_0: T, y_2: T, y_1: T, y_0: T, ) -> (T, T, T) { let (z_0, borrow_1) = x_0.overflowing_sub(y_0); let (mut z_1, mut borrow_2) = x_1.overflowing_sub(y_1); if borrow_1 { borrow_2 |= z_1.overflowing_sub_assign(T::ONE); } let mut z_2 = x_2.wrapping_sub(y_2); if borrow_2 { z_2.wrapping_sub_assign(T::ONE); } (z_2, z_1, z_0) }} macro_rules! impl_xxx_sub_yyy_to_zzz { ($t:ident) => { impl XXXSubYYYToZZZ for $t { /// Subtracts two numbers, each composed of three `Self` values, returning the /// difference as a triple of `Self` values. /// /// The more significant value always comes first. Subtraction is wrapping, and overflow /// is not indicated. /// /// $$ /// f(x_2, x_1, x_0, y_2, y_1, y_0) = (z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_2, x_1, x_0, y_2, y_1, y_0, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{2W}x_2 + 2^Wx_1 + x_0) - (2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{3W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxx_sub_yyy_to_zzz#xxx_sub_yyy_to_zzz). /// /// This is equivalent to `sub_dddmmmsss` from `longlong.h`, FLINT 2.7.1, where `(dh, /// dm, dl)` is returned. #[inline] fn xxx_sub_yyy_to_zzz( x_2: $t, x_1: $t, x_0: $t, y_2: $t, y_1: $t, y_0: $t, ) -> ($t, $t, $t) { xxx_sub_yyy_to_zzz::<$t>(x_2, x_1, x_0, y_2, y_1, y_0) } } }; } impl_xxx_sub_yyy_to_zzz!(u8); impl_xxx_sub_yyy_to_zzz!(u16); impl_xxx_sub_yyy_to_zzz!(u32); impl_xxx_sub_yyy_to_zzz!(u64); impl_xxx_sub_yyy_to_zzz!(u128); impl XXXSubYYYToZZZ for usize { /// Subtracts two numbers, each composed of three [`usize`] values, returning the difference as /// a triple of [`usize`] values. /// /// The more significant value always comes first. Subtraction is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_2, x_1, x_0, y_2, y_1, y_0) = (z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_2, x_1, x_0, y_2, y_1, y_0, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{2W}x_2 + 2^Wx_1 + x_0) - (2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{3W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxx_sub_yyy_to_zzz#xxx_sub_yyy_to_zzz). /// /// This is equivalent to `sub_dddmmmsss` from `longlong.h`, FLINT 2.7.1, where `(dh, dm, dl)` /// is returned. fn xxx_sub_yyy_to_zzz( x_2: Self, x_1: Self, x_0: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self) { if USIZE_IS_U32 { let (z_2, z_1, z_0) = u32::xxx_sub_yyy_to_zzz( u32::wrapping_from(x_2), u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y_2), u32::wrapping_from(y_1), u32::wrapping_from(y_0), ); ( Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } else { let (z_2, z_1, z_0) = u64::xxx_sub_yyy_to_zzz( u64::wrapping_from(x_2), u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y_2), u64::wrapping_from(y_1), u64::wrapping_from(y_0), ); ( Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } } } ================================================ FILE: malachite-base/src/num/arithmetic/xxxx_add_yyyy_to_zzzz.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 1991, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // Copyright © 2009, 2015, 2016 William Hart // // Copyright © 2011 Fredrik Johansson // // 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 crate::num::arithmetic::traits::XXXXAddYYYYToZZZZ; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; #[allow(clippy::too_many_arguments)] fn xxxx_add_yyyy_to_zzzz( x_3: T, x_2: T, x_1: T, x_0: T, y_3: T, y_2: T, y_1: T, y_0: T, ) -> (T, T, T, T) { let (z_0, carry_1) = x_0.overflowing_add(y_0); let (mut z_1, mut carry_2) = x_1.overflowing_add(y_1); if carry_1 { carry_2 |= z_1.overflowing_add_assign(T::ONE); } let (mut z_2, mut carry_3) = x_2.overflowing_add(y_2); if carry_2 { carry_3 |= z_2.overflowing_add_assign(T::ONE); } let mut z_3 = x_3.wrapping_add(y_3); if carry_3 { z_3.wrapping_add_assign(T::ONE); } (z_3, z_2, z_1, z_0) } macro_rules! impl_xxxx_add_yyyy_to_zzzz { ($t:ident) => { impl XXXXAddYYYYToZZZZ for $t { /// Adds two numbers, each composed of four `Self` values, returning the sum as a /// quadruple of `Self` values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is /// not indicated. /// /// $$ /// f(x_3, x_2, x_1, x_0, y_2, y_2, y_1, y_0) = (z_3, z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0, z_3, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{3W}x_3 + 2^{2W}x_2 + 2^Wx_1 + x_0) + (2^{3W}y_3 + 2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{3W}z_3 + 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{4W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxxx_add_yyyy_to_zzzz#xxxx_add_yyyy_to_zzzz). /// /// This is equivalent to `add_ssssaaaaaaaa` from `longlong.h`, FLINT 2.7.1, where `(s3, /// s2, s1, s0)` is returned. #[inline] fn xxxx_add_yyyy_to_zzzz( x_3: $t, x_2: $t, x_1: $t, x_0: $t, y_3: $t, y_2: $t, y_1: $t, y_0: $t, ) -> ($t, $t, $t, $t) { xxxx_add_yyyy_to_zzzz::<$t>(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0) } } }; } impl_xxxx_add_yyyy_to_zzzz!(u8); impl_xxxx_add_yyyy_to_zzzz!(u16); impl_xxxx_add_yyyy_to_zzzz!(u32); impl_xxxx_add_yyyy_to_zzzz!(u64); impl_xxxx_add_yyyy_to_zzzz!(u128); impl XXXXAddYYYYToZZZZ for usize { /// Adds two numbers, each composed of four [`usize`] values, returning the sum as a quadruple /// of [`usize`] values. /// /// The more significant value always comes first. Addition is wrapping, and overflow is not /// indicated. /// /// $$ /// f(x_3, x_2, x_1, x_0, y_2, y_2, y_1, y_0) = (z_3, z_2, z_1, z_0), /// $$ /// where $W$ is `Self::WIDTH`, /// /// $x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0, z_3, z_2, z_1, z_0 < 2^W$, and /// $$ /// (2^{3W}x_3 + 2^{2W}x_2 + 2^Wx_1 + x_0) + (2^{3W}y_3 + 2^{2W}y_2 + 2^Wy_1 + y_0) /// \equiv 2^{3W}z_3 + 2^{2W}z_2 + 2^Wz_1 + z_0 \mod 2^{4W}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::xxxx_add_yyyy_to_zzzz#xxxx_add_yyyy_to_zzzz). /// /// This is equivalent to `add_ssssaaaaaaaa` from `longlong.h`, FLINT 2.7.1, where `(s3, s2, s1, /// s0)` is returned. fn xxxx_add_yyyy_to_zzzz( x_3: Self, x_2: Self, x_1: Self, x_0: Self, y_3: Self, y_2: Self, y_1: Self, y_0: Self, ) -> (Self, Self, Self, Self) { if USIZE_IS_U32 { let (z_3, z_2, z_1, z_0) = u32::xxxx_add_yyyy_to_zzzz( u32::wrapping_from(x_3), u32::wrapping_from(x_2), u32::wrapping_from(x_1), u32::wrapping_from(x_0), u32::wrapping_from(y_3), u32::wrapping_from(y_2), u32::wrapping_from(y_1), u32::wrapping_from(y_0), ); ( Self::wrapping_from(z_3), Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } else { let (z_3, z_2, z_1, z_0) = u64::xxxx_add_yyyy_to_zzzz( u64::wrapping_from(x_3), u64::wrapping_from(x_2), u64::wrapping_from(x_1), u64::wrapping_from(x_0), u64::wrapping_from(y_3), u64::wrapping_from(y_2), u64::wrapping_from(y_1), u64::wrapping_from(y_0), ); ( Self::wrapping_from(z_3), Self::wrapping_from(z_2), Self::wrapping_from(z_1), Self::wrapping_from(z_0), ) } } } ================================================ FILE: malachite-base/src/num/basic/floats.rs ================================================ // Copyright © 2026 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 crate::comparison::traits::{Max, Min}; use crate::named::Named; use crate::num::arithmetic::traits::{ Abs, AbsAssign, AddMul, AddMulAssign, Ceiling, CeilingAssign, CeilingLogBase2, CeilingLogBasePowerOf2, CheckedLogBase2, CheckedLogBasePowerOf2, Floor, FloorAssign, FloorLogBase2, FloorLogBasePowerOf2, IsPowerOf2, NegAssign, NextPowerOf2, NextPowerOf2Assign, Pow, PowAssign, PowerOf2, Reciprocal, ReciprocalAssign, Sign, Sqrt, SqrtAssign, Square, SquareAssign, SubMul, SubMulAssign, }; use crate::num::basic::traits::{ GaussConstant, Infinity, LemniscateConstant, Ln2, Log2E, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, OneOverPi, OneOverSqrtPi, OneOverSqrtTau, Phi, Pi, PiOver2, PiOver3, PiOver4, PiOver6, PiOver8, PrimeConstant, ProuhetThueMorseConstant, Sqrt2, Sqrt2Over2, Sqrt3, Sqrt3Over3, SqrtPi, Tau, Two, TwoOverPi, TwoOverSqrtPi, Zero, }; use crate::num::comparison::traits::{EqAbs, PartialOrdAbs}; use crate::num::conversion::traits::{ ConvertibleFrom, ExactInto, IntegerMantissaAndExponent, IsInteger, RawMantissaAndExponent, RoundingFrom, RoundingInto, SciMantissaAndExponent, WrappingFrom, }; use crate::num::float::FmtRyuString; use crate::num::logic::traits::{BitAccess, LowMask, SignificantBits, TrailingZeros}; use core::cmp::Ordering::*; use core::fmt::{Debug, Display, LowerExp, UpperExp}; use core::iter::{Product, Sum}; use core::num::FpCategory; use core::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign, }; use core::panic::RefUnwindSafe; use core::str::FromStr; /// This trait defines functions on primitive float types: [`f32`] and [`f64`]. /// /// Many of the functions here concern exponents and mantissas. We define three ways to express a /// float, each with its own exponent and mantissa. In the following, let $x$ be an arbitrary /// positive, finite, non-zero, non-NaN float. Let $M$ and $E$ be the mantissa width and exponent /// width of the floating point type; for [`f32`]s, this is 23 and 8, and for [`f64`]s it's 52 and /// 11. /// /// In the following we assume that $x$ is positive, but you can easily extend these definitions to /// negative floats by first taking their absolute value. /// /// # raw form /// The raw exponent and raw mantissa are the actual bit patterns used to represent the components /// of $x$. The raw exponent $e_r$ is an integer in $[0, 2^E-2]$ and the raw mantissa $m_r$ is an /// integer in $[0, 2^M-1]$. Since we are dealing with a nonzero $x$, we forbid $e_r$ and $m_r$ from /// both being zero. We have /// $$ /// x = \\begin{cases} /// 2^{2-2^{E-1}-M}m_r & \text{if} \quad e_r = 0, \\\\ /// 2^{e_r-2^{E-1}+1}(2^{-M}m_r+1) & \textrm{otherwise}, /// \\end{cases} /// $$ /// $$ /// e_r = \\begin{cases} /// 0 & \text{if} \quad x < 2^{2-2^{E-1}}, \\\\ /// \lfloor \log_2 x \rfloor + 2^{E-1} - 1 & \textrm{otherwise}, /// \\end{cases} /// $$ /// $$ /// m_r = \\begin{cases} /// 2^{M+2^{E-1}-2}x & \text{if} \quad x < 2^{2-2^{E-1}}, \\\\ /// 2^M \left ( \frac{x}{2^{\lfloor \log_2 x \rfloor}}-1\right ) & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # scientific form /// We can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is a rational number with $1 /// \leq m_s < 2$. If $x$ is a valid float, the scientific mantissa $m_s$ is always exactly /// representable as a float of the same type. We have /// $$ /// x = 2^{e_s}m_s, /// $$ /// $$ /// e_s = \lfloor \log_2 x \rfloor, /// $$ /// $$ /// m_s = \frac{x}{2^{\lfloor \log_2 x \rfloor}}. /// $$ /// /// # integer form /// We can also write $x = 2^{e_i}m_i$, where $e_i$ is an integer and $m_i$ is an odd integer. We /// have /// $$ /// x = 2^{e_i}m_i, /// $$ /// $e_i$ is the unique integer such that $x/2^{e_i}$is an odd integer, and /// $$ /// m_i = \frac{x}{2^{e_i}}. /// $$ pub trait PrimitiveFloat: 'static + Abs + AbsAssign + Add + AddAssign + AddMul + AddMulAssign + Ceiling + CeilingAssign + CeilingLogBase2 + CeilingLogBasePowerOf2 + CheckedLogBase2 + CheckedLogBasePowerOf2 + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + Copy + Debug + Default + Display + Div + DivAssign + EqAbs + Floor + FloorAssign + FloorLogBase2 + FloorLogBasePowerOf2 + FmtRyuString + From + FromStr + Infinity + IntegerMantissaAndExponent + Into + IsInteger + IsPowerOf2 + Log2E + Ln2 + LowerExp + Min + Max + Mul + MulAssign + Named + NaN + NegativeInfinity + NegativeZero + Neg + NegAssign + NegativeOne + NextPowerOf2 + NextPowerOf2Assign + One + PartialEq + PartialOrd + PartialOrdAbs + Phi + Pi + Pow + Pow + PowAssign + PowAssign + PowerOf2 + PowerOf2 + PrimeConstant + Product + RawMantissaAndExponent + Reciprocal + ReciprocalAssign + RefUnwindSafe + Rem + RemAssign + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingFrom + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + RoundingInto + SciMantissaAndExponent + Sign + Sized + Sqrt + SqrtAssign + Sqrt2 + Sqrt2Over2 + Sqrt3 + Sqrt3Over3 + Square + SquareAssign + Sub + SubAssign + SubMul + SubMulAssign + Sum + ProuhetThueMorseConstant + Two + UpperExp + Zero { /// The number of bits taken up by the type. /// /// This is $M+E+1$. The three terms in the sum correspond to the width of the mantissa, the /// width of the exponent, and the sign bit. /// - For [`f32`]s, this is 32. /// - For [`f64`]s, this is 64. const WIDTH: u64; /// The number of bits taken up by the exponent. /// - For [`f32`]s, this is 8. /// - For [`f64`]s, this is 11. const EXPONENT_WIDTH: u64 = Self::WIDTH - Self::MANTISSA_WIDTH - 1; /// The number of bits taken up by the mantissa. /// - For [`f32`]s, this is 23. /// - For [`f64`]s, this is 52. const MANTISSA_WIDTH: u64; /// The smallest possible exponent of a float in the normal range. Any floats with smaller /// exponents are subnormal and thus have reduced precision. This is $2-2^{E-1}$. /// - For [`f32`]s, this is -126. /// - For [`f64`]s, this is -1022. const MIN_NORMAL_EXPONENT: i64 = -(1 << (Self::EXPONENT_WIDTH - 1)) + 2; /// The smallest possible exponent of a float. This is $2-2^{E-1}-M$. /// - For [`f32`]s, this is -149. /// - For [`f64`]s, this is -1074. const MIN_EXPONENT: i64 = Self::MIN_NORMAL_EXPONENT - (Self::MANTISSA_WIDTH as i64); /// The largest possible exponent of a float. This is $2^{E-1}-1$. /// - For [`f32`]s, this is 127. /// - For [`f64`]s, this is 1023. const MAX_EXPONENT: i64 = (1 << (Self::EXPONENT_WIDTH - 1)) - 1; /// The smallest positive float. This is $2^{2-2^{E-1}-M}$. /// - For [`f32`]s, this is $2^{-149}$, or `1.0e-45`. /// - For [`f64`]s, this is $2^{-1074}$, or `5.0e-324`. const MIN_POSITIVE_SUBNORMAL: Self; /// The largest float in the subnormal range. This is $2^{2-2^{E-1}-M}(2^M-1)$. /// - For [`f32`]s, this is $2^{-149}(2^{23}-1)$, or `1.1754942e-38`. /// - For [`f64`]s, this is $2^{-1074}(2^{52}-1)$, or `2.225073858507201e-308`. const MAX_SUBNORMAL: Self; /// The smallest positive normal float. This is $2^{2-2^{E-1}}$. /// - For [`f32`]s, this is $2^{-126}$, or `1.1754944e-38`. /// - For [`f64`]s, this is $2^{-1022}$, or `2.2250738585072014e-308`. const MIN_POSITIVE_NORMAL: Self; /// The largest finite float. This is $2^{2^{E-1}-1}(2-2^{-M})$. /// - For [`f32`]s, this is $2^{127}(2-2^{-23})$, or `3.4028235e38`. /// - For [`f64`]s, this is $2^{1023}(2-2^{-52})$, or `1.7976931348623157e308`. const MAX_FINITE: Self; /// The smallest positive integer that cannot be represented as a float. This is $2^{M+1}+1$. /// - For [`f32`]s, this is $2^{24}+1$, or 16777217. /// - For [`f64`]s, this is $2^{53}+1$, or 9007199254740993. const SMALLEST_UNREPRESENTABLE_UINT: u64; /// If you list all floats in increasing order, excluding NaN and giving negative and positive /// zero separate adjacent spots, this will be index of the last element, positive infinity. It /// is $2^{M+1}(2^E-1)+1$. /// - For [`f32`]s, this is $2^{32}-2^{24}+1$, or 4278190081. /// - For [`f64`]s, this is $2^{64}-2^{53}+1$, or 18437736874454810625. const LARGEST_ORDERED_REPRESENTATION: u64; fn is_nan(self) -> bool; fn is_infinite(self) -> bool; fn is_finite(self) -> bool; fn is_normal(self) -> bool; fn is_sign_positive(self) -> bool; fn is_sign_negative(self) -> bool; fn classify(self) -> FpCategory; fn to_bits(self) -> u64; fn from_bits(v: u64) -> Self; /// Tests whether `self` is negative zero. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// /// assert!((-0.0).is_negative_zero()); /// assert!(!0.0.is_negative_zero()); /// assert!(!1.0.is_negative_zero()); /// assert!(!f32::NAN.is_negative_zero()); /// assert!(!f32::INFINITY.is_negative_zero()); /// ``` #[inline] fn is_negative_zero(self) -> bool { self.sign() == Less && self == Self::ZERO } /// If `self` is negative zero, returns positive zero; otherwise, returns `self`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat((-0.0).abs_negative_zero()), NiceFloat(0.0)); /// assert_eq!(NiceFloat(0.0.abs_negative_zero()), NiceFloat(0.0)); /// assert_eq!(NiceFloat(1.0.abs_negative_zero()), NiceFloat(1.0)); /// assert_eq!(NiceFloat((-1.0).abs_negative_zero()), NiceFloat(-1.0)); /// assert_eq!(NiceFloat(f32::NAN.abs_negative_zero()), NiceFloat(f32::NAN)); /// ``` #[inline] fn abs_negative_zero(self) -> Self { if self == Self::ZERO { Self::ZERO } else { self } } /// If `self` is negative zero, replaces it with positive zero; otherwise, leaves `self` /// unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::float::NiceFloat; /// /// let mut f = -0.0; /// f.abs_negative_zero_assign(); /// assert_eq!(NiceFloat(f), NiceFloat(0.0)); /// /// let mut f = 0.0; /// f.abs_negative_zero_assign(); /// assert_eq!(NiceFloat(f), NiceFloat(0.0)); /// /// let mut f = 1.0; /// f.abs_negative_zero_assign(); /// assert_eq!(NiceFloat(f), NiceFloat(1.0)); /// /// let mut f = -1.0; /// f.abs_negative_zero_assign(); /// assert_eq!(NiceFloat(f), NiceFloat(-1.0)); /// /// let mut f = f32::NAN; /// f.abs_negative_zero_assign(); /// assert_eq!(NiceFloat(f), NiceFloat(f32::NAN)); /// ``` #[inline] fn abs_negative_zero_assign(&mut self) { if *self == Self::ZERO { *self = Self::ZERO; } } /// Returns the smallest float larger than `self`. /// /// Passing `-0.0` returns `0.0`; passing `NaN` or positive infinity panics. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is `NaN` or positive infinity. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat((-0.0f32).next_higher()), NiceFloat(0.0)); /// assert_eq!(NiceFloat(0.0f32.next_higher()), NiceFloat(1.0e-45)); /// assert_eq!(NiceFloat(1.0f32.next_higher()), NiceFloat(1.0000001)); /// assert_eq!(NiceFloat((-1.0f32).next_higher()), NiceFloat(-0.99999994)); /// ``` fn next_higher(self) -> Self { assert!(!self.is_nan()); if self.sign() == Greater { assert_ne!(self, Self::INFINITY); Self::from_bits(self.to_bits() + 1) } else if self == Self::ZERO { // negative zero -> positive zero Self::ZERO } else { Self::from_bits(self.to_bits() - 1) } } /// Returns the largest float smaller than `self`. /// /// Passing `0.0` returns `-0.0`; passing `NaN` or negative infinity panics. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is `NaN` or negative infinity. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat(0.0f32.next_lower()), NiceFloat(-0.0)); /// assert_eq!(NiceFloat((-0.0f32).next_lower()), NiceFloat(-1.0e-45)); /// assert_eq!(NiceFloat(1.0f32.next_lower()), NiceFloat(0.99999994)); /// assert_eq!(NiceFloat((-1.0f32).next_lower()), NiceFloat(-1.0000001)); /// ``` fn next_lower(self) -> Self { assert!(!self.is_nan()); if self.sign() == Less { assert_ne!(self, Self::NEGATIVE_INFINITY); Self::from_bits(self.to_bits() + 1) } else if self == Self::ZERO { // positive zero -> negative zero Self::NEGATIVE_ZERO } else { Self::from_bits(self.to_bits() - 1) } } /// Maps `self` to an integer. The map preserves ordering, and adjacent floats are mapped to /// adjacent integers. /// /// Negative infinity is mapped to 0, and positive infinity is mapped to the largest value, /// [`LARGEST_ORDERED_REPRESENTATION`](PrimitiveFloat::LARGEST_ORDERED_REPRESENTATION). Negative /// and positive zero are mapped to distinct adjacent values. Passing in `NaN` panics. /// /// The inverse operation is /// [`from_ordered_representation`](PrimitiveFloat::from_ordered_representation). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is `NaN`. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::traits::NegativeInfinity; /// /// assert_eq!(f32::NEGATIVE_INFINITY.to_ordered_representation(), 0); /// assert_eq!((-0.0f32).to_ordered_representation(), 2139095040); /// assert_eq!(0.0f32.to_ordered_representation(), 2139095041); /// assert_eq!(1.0f32.to_ordered_representation(), 3204448257); /// assert_eq!(f32::INFINITY.to_ordered_representation(), 4278190081); /// ``` fn to_ordered_representation(self) -> u64 { assert!(!self.is_nan()); let bits = self.to_bits(); if self.sign() == Greater { (u64::low_mask(Self::EXPONENT_WIDTH) << Self::MANTISSA_WIDTH) + bits + 1 } else { (u64::low_mask(Self::EXPONENT_WIDTH + 1) << Self::MANTISSA_WIDTH) - bits } } /// Maps a non-negative integer, less than or equal to /// [`LARGEST_ORDERED_REPRESENTATION`](PrimitiveFloat::LARGEST_ORDERED_REPRESENTATION), to a /// float. The map preserves ordering, and adjacent integers are mapped to adjacent floats. /// /// Zero is mapped to negative infinity, and /// [`LARGEST_ORDERED_REPRESENTATION`](PrimitiveFloat::LARGEST_ORDERED_REPRESENTATION) is mapped /// to positive infinity. Negative and positive zero are produced by two distinct adjacent /// integers. `NaN` is never produced. /// /// The inverse operation is /// [`to_ordered_representation`](PrimitiveFloat::to_ordered_representation). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is greater than /// [`LARGEST_ORDERED_REPRESENTATION`](PrimitiveFloat::LARGEST_ORDERED_REPRESENTATION). /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::traits::NegativeInfinity; /// /// assert_eq!(f32::from_ordered_representation(0), f32::NEGATIVE_INFINITY); /// assert_eq!(f32::from_ordered_representation(2139095040), -0.0f32); /// assert_eq!(f32::from_ordered_representation(2139095041), 0.0f32); /// assert_eq!(f32::from_ordered_representation(3204448257), 1.0f32); /// assert_eq!(f32::from_ordered_representation(4278190081), f32::INFINITY); /// ``` fn from_ordered_representation(n: u64) -> Self { let zero_exp = u64::low_mask(Self::EXPONENT_WIDTH) << Self::MANTISSA_WIDTH; let f = if n <= zero_exp { Self::from_bits((u64::low_mask(Self::EXPONENT_WIDTH + 1) << Self::MANTISSA_WIDTH) - n) } else { let f = Self::from_bits(n - zero_exp - 1); assert_eq!(f.sign(), Greater); f }; assert!(!f.is_nan()); f } /// Returns the precision of a nonzero finite floating-point number. /// /// The precision is the number of significant bits of the integer mantissa. For example, the /// positive floats with precision 1 are the powers of 2, those with precision 2 are 3 times a /// power of 2, those with precision 3 are 5 or 7 times a power of 2, and so on. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// /// assert_eq!(1.0.precision(), 1); /// assert_eq!(2.0.precision(), 1); /// assert_eq!(3.0.precision(), 2); /// assert_eq!(1.5.precision(), 2); /// assert_eq!(1.234f32.precision(), 23); /// ``` fn precision(self) -> u64 { assert!(self.is_finite()); assert!(self != Self::ZERO); let (mut mantissa, exponent) = self.raw_mantissa_and_exponent(); if exponent == 0 { mantissa.significant_bits() - TrailingZeros::trailing_zeros(mantissa) } else { mantissa.set_bit(Self::MANTISSA_WIDTH); Self::MANTISSA_WIDTH + 1 - TrailingZeros::trailing_zeros(mantissa) } } /// Given a scientific exponent, returns the largest possible precision for a float with that /// exponent. /// /// See the documentation of the [`precision`](PrimitiveFloat::precision) function for a /// definition of precision. /// /// For exponents greater than or equal to /// [`MIN_NORMAL_EXPONENT`](PrimitiveFloat::MIN_NORMAL_EXPONENT), the maximum precision is one /// more than the mantissa width. For smaller exponents (corresponding to the subnormal range), /// the precision is lower. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `exponent` is less than [`MIN_EXPONENT`](PrimitiveFloat::MIN_EXPONENT) or greater /// than [`MAX_EXPONENT`](PrimitiveFloat::MAX_EXPONENT). /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// /// assert_eq!(f32::max_precision_for_sci_exponent(0), 24); /// assert_eq!(f32::max_precision_for_sci_exponent(127), 24); /// assert_eq!(f32::max_precision_for_sci_exponent(-149), 1); /// assert_eq!(f32::max_precision_for_sci_exponent(-148), 2); /// assert_eq!(f32::max_precision_for_sci_exponent(-147), 3); /// ``` fn max_precision_for_sci_exponent(exponent: i64) -> u64 { assert!(exponent >= Self::MIN_EXPONENT); assert!(exponent <= Self::MAX_EXPONENT); if exponent >= Self::MIN_NORMAL_EXPONENT { Self::MANTISSA_WIDTH + 1 } else { u64::wrapping_from(exponent - Self::MIN_EXPONENT) + 1 } } } /// Defines basic trait implementations for floating-point types. macro_rules! impl_basic_traits_primitive_float { ( $t: ident, $width: expr, $min_positive_subnormal: expr, $max_subnormal: expr, $min_positive_normal: expr, $prouhet_thue_morse_constant: expr, $prime_constant: expr, $sqrt_3: expr, $sqrt_3_over_3: expr, $phi: expr, $sqrt_pi: expr, $one_over_sqrt_pi: expr, $one_over_sqrt_tau: expr, $gauss_constant: expr, $lemniscate_constant: expr ) => { impl PrimitiveFloat for $t { const WIDTH: u64 = $width; const MANTISSA_WIDTH: u64 = ($t::MANTISSA_DIGITS as u64) - 1; const MAX_FINITE: Self = $t::MAX; const MIN_POSITIVE_SUBNORMAL: Self = $min_positive_subnormal; const MAX_SUBNORMAL: Self = $max_subnormal; const MIN_POSITIVE_NORMAL: Self = $min_positive_normal; const SMALLEST_UNREPRESENTABLE_UINT: u64 = (1 << (Self::MANTISSA_WIDTH + 1)) + 1; // We can't shift by $width when $width is 64, so we shift by $width - 1 and then by 1 const LARGEST_ORDERED_REPRESENTATION: u64 = (1u64 << ($width - 1) << 1) .wrapping_sub(((1 << Self::MANTISSA_WIDTH) - 1) << 1) - 1; #[inline] fn is_nan(self) -> bool { $t::is_nan(self) } #[inline] fn is_infinite(self) -> bool { $t::is_infinite(self) } #[inline] fn is_finite(self) -> bool { $t::is_finite(self) } #[inline] fn is_normal(self) -> bool { $t::is_normal(self) } #[inline] fn is_sign_positive(self) -> bool { $t::is_sign_positive(self) } #[inline] fn is_sign_negative(self) -> bool { $t::is_sign_negative(self) } #[inline] fn classify(self) -> FpCategory { $t::classify(self) } #[inline] fn to_bits(self) -> u64 { u64::wrapping_from($t::to_bits(self)) } #[inline] fn from_bits(v: u64) -> $t { $t::from_bits(v.exact_into()) } } impl_named!($t); /// The constant 0. impl Zero for $t { const ZERO: $t = 0.0; } /// The constant 1. impl One for $t { const ONE: $t = 1.0; } /// The constant 2. impl Two for $t { const TWO: $t = 2.0; } /// The constant 1/2. impl OneHalf for $t { const ONE_HALF: $t = 0.5; } /// The constant -1.0 for primitive floating-point types. impl NegativeOne for $t { const NEGATIVE_ONE: $t = -1.0; } /// The constant -0.0 for primitive floating-point types. impl NegativeZero for $t { const NEGATIVE_ZERO: $t = -0.0; } /// The constant Infinity for primitive floating-point types. impl Infinity for $t { const INFINITY: $t = $t::INFINITY; } /// The constant -Infinity for primitive floating-point types. impl NegativeInfinity for $t { const NEGATIVE_INFINITY: $t = $t::NEG_INFINITY; } /// The constant NaN for primitive floating-point types. impl NaN for $t { const NAN: $t = $t::NAN; } /// The lowest value representable by this type, negative infinity. impl Min for $t { const MIN: $t = $t::NEGATIVE_INFINITY; } /// The highest value representable by this type, positive infinity. impl Max for $t { const MAX: $t = $t::INFINITY; } /// The Prouhet-Thue-Morse constant. impl ProuhetThueMorseConstant for $t { const PROUHET_THUE_MORSE_CONSTANT: $t = $prouhet_thue_morse_constant; } /// The prime constant. impl PrimeConstant for $t { const PRIME_CONSTANT: $t = $prime_constant; } /// $\ln 2$. impl Ln2 for $t { const LN_2: $t = core::$t::consts::LN_2; } /// $\log_2 e$. impl Log2E for $t { const LOG_2_E: $t = core::$t::consts::LOG2_E; } /// $\sqrt{2}$. impl Sqrt2 for $t { const SQRT_2: $t = core::$t::consts::SQRT_2; } /// $\sqrt{3}$. impl Sqrt3 for $t { const SQRT_3: $t = $sqrt_3; } /// $\sqrt{2}/2=\sqrt{1/2}=1/\sqrt{2}$. impl Sqrt2Over2 for $t { const SQRT_2_OVER_2: $t = core::$t::consts::FRAC_1_SQRT_2; } /// $\sqrt{3}/3=\sqrt{1/3}=1/\sqrt{3}$. impl Sqrt3Over3 for $t { const SQRT_3_OVER_3: $t = $sqrt_3_over_3; } /// $\varphi$, the golden ratio. impl Phi for $t { const PHI: $t = $phi; } /// $\pi$. impl Pi for $t { const PI: $t = core::$t::consts::PI; } /// $\tau=2\pi$. impl Tau for $t { const TAU: $t = core::$t::consts::TAU; } /// $\pi/2$. impl PiOver2 for $t { const PI_OVER_2: $t = core::$t::consts::FRAC_PI_2; } /// $\pi/3$. impl PiOver3 for $t { const PI_OVER_3: $t = core::$t::consts::FRAC_PI_3; } /// $\pi/4$. impl PiOver4 for $t { const PI_OVER_4: $t = core::$t::consts::FRAC_PI_4; } /// $\pi/6$. impl PiOver6 for $t { const PI_OVER_6: $t = core::$t::consts::FRAC_PI_6; } /// $\pi/8$. impl PiOver8 for $t { const PI_OVER_8: $t = core::$t::consts::FRAC_PI_8; } /// $1/\pi$. impl OneOverPi for $t { const ONE_OVER_PI: $t = core::$t::consts::FRAC_1_PI; } /// $\sqrt{\pi}$. impl SqrtPi for $t { const SQRT_PI: $t = $sqrt_pi; } /// $1/\sqrt{\pi}$. impl OneOverSqrtPi for $t { const ONE_OVER_SQRT_PI: $t = $one_over_sqrt_pi; } /// $1/\sqrt{\tau}$. impl OneOverSqrtTau for $t { const ONE_OVER_SQRT_TAU: $t = $one_over_sqrt_tau; } /// $2/\pi$. impl TwoOverPi for $t { const TWO_OVER_PI: $t = core::$t::consts::FRAC_2_PI; } /// $2/\sqrt{\pi}$. impl TwoOverSqrtPi for $t { const TWO_OVER_SQRT_PI: $t = core::$t::consts::FRAC_2_SQRT_PI; } /// $G=1/\mathrm{AGM}(1,\sqrt{2})$. impl GaussConstant for $t { const GAUSS_CONSTANT: $t = $gauss_constant; } /// $\varpi=\pi G$. impl LemniscateConstant for $t { const LEMNISCATE_CONSTANT: $t = $lemniscate_constant; } }; } impl_basic_traits_primitive_float!( f32, 32, 1.0e-45, 1.1754942e-38, 1.1754944e-38, 0.41245404, 0.4146825, 1.7320508, 0.57735026, 1.618034, 1.7724539, 0.5641896, 0.3989423, 0.83462685, 2.6220574 ); impl_basic_traits_primitive_float!( f64, 64, 5.0e-324, 2.225073858507201e-308, 2.2250738585072014e-308, 0.4124540336401076, 0.41468250985111166, 1.7320508075688772, 0.5773502691896257, 1.618033988749895, 1.772453850905516, 0.5641895835477563, 0.3989422804014327, 0.8346268416740732, 2.6220575542921196 ); ================================================ FILE: malachite-base/src/num/basic/integers.rs ================================================ // Copyright © 2026 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 crate::comparison::traits::{Max, Min}; use crate::named::Named; use crate::num::arithmetic::traits::{ AbsDiff, AddMul, AddMulAssign, ArithmeticCheckedShl, ArithmeticCheckedShr, BinomialCoefficient, CeilingRoot, CeilingRootAssign, CeilingSqrt, CeilingSqrtAssign, CheckedAdd, CheckedAddMul, CheckedBinomialCoefficient, CheckedDiv, CheckedMul, CheckedNeg, CheckedPow, CheckedRoot, CheckedSqrt, CheckedSquare, CheckedSub, CheckedSubMul, DivAssignMod, DivAssignRem, DivExact, DivExactAssign, DivMod, DivRem, DivRound, DivRoundAssign, DivisibleBy, DivisibleByPowerOf2, EqMod, EqModPowerOf2, ExtendedGcd, FloorRoot, FloorRootAssign, FloorSqrt, FloorSqrtAssign, JacobiSymbol, KroneckerSymbol, LegendreSymbol, Mod, ModAssign, ModPowerOf2, ModPowerOf2Assign, OverflowingAdd, OverflowingAddAssign, OverflowingAddMul, OverflowingAddMulAssign, OverflowingDiv, OverflowingDivAssign, OverflowingMul, OverflowingMulAssign, OverflowingNeg, OverflowingNegAssign, OverflowingPow, OverflowingPowAssign, OverflowingSquare, OverflowingSquareAssign, OverflowingSub, OverflowingSubAssign, OverflowingSubMul, OverflowingSubMulAssign, Parity, Pow, PowAssign, PowerOf2, RemPowerOf2, RemPowerOf2Assign, RotateLeft, RotateLeftAssign, RotateRight, RotateRightAssign, RoundToMultiple, RoundToMultipleAssign, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, SaturatingAdd, SaturatingAddAssign, SaturatingAddMul, SaturatingAddMulAssign, SaturatingMul, SaturatingMulAssign, SaturatingPow, SaturatingPowAssign, SaturatingSquare, SaturatingSquareAssign, SaturatingSub, SaturatingSubAssign, SaturatingSubMul, SaturatingSubMulAssign, ShlRound, ShlRoundAssign, ShrRound, ShrRoundAssign, Sign, Square, SquareAssign, SubMul, SubMulAssign, WrappingAdd, WrappingAddAssign, WrappingAddMul, WrappingAddMulAssign, WrappingDiv, WrappingDivAssign, WrappingMul, WrappingMulAssign, WrappingNeg, WrappingNegAssign, WrappingPow, WrappingPowAssign, WrappingSquare, WrappingSquareAssign, WrappingSub, WrappingSubAssign, WrappingSubMul, WrappingSubMulAssign, }; use crate::num::basic::traits::{One, Two, Zero}; use crate::num::conversion::traits::{ ConvertibleFrom, ExactFrom, ExactInto, FromSciString, FromStringBase, IsInteger, OverflowingFrom, OverflowingInto, RoundingFrom, RoundingInto, SaturatingFrom, SaturatingInto, ToSci, ToStringBase, WrappingFrom, WrappingInto, }; use crate::num::factorization::traits::{ExpressAsPower, IsPower, IsSquare}; use crate::num::float::NiceFloat; use crate::num::logic::traits::{ BitAccess, BitBlockAccess, BitConvertible, BitIterable, BitScan, CountOnes, CountZeros, LeadingZeros, LowMask, NotAssign, SignificantBits, TrailingZeros, }; #[cfg(feature = "random")] use crate::num::random::HasRandomPrimitiveInts; use core::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex}; use core::hash::Hash; use core::iter::{Product, Sum}; use core::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::str::FromStr; pub const USIZE_IS_U32: bool = usize::WIDTH == u32::WIDTH; pub const USIZE_IS_U64: bool = usize::WIDTH == u64::WIDTH; // Checks that usize is equivalent to u32 or u64, at compile time. The rest of Malachite can assume // that this condition is true. const _USIZE_ASSERTION: () = assert!(USIZE_IS_U32 || USIZE_IS_U64); // When the `random` feature is enabled, the HasRandomPrimitiveInts bound is included. #[cfg(feature = "random")] /// Defines functions on primitive integer types: uxx, ixx, usize, and isize. /// /// The different types are distinguished by whether they are signed or unsigned, and by their /// widths. The width $W$ is the number of bits in the type. For example, the width of [`u32`] or /// [`i32`] is 32. Each type has $2^W$ distinct values. /// /// Let $n$ be a value of type `Self`. If `Self` is unsigned, $0 \leq n < 2^W$. If `Self` is signed, /// $2^{W-1} \leq n < 2^{W-1}$. pub trait PrimitiveInt: 'static + AbsDiff + Add + AddAssign + AddMul + AddMulAssign + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + Binary + BinomialCoefficient + BitAccess + BitAnd + BitAndAssign + BitBlockAccess + BitConvertible + BitIterable + BitOr + BitOrAssign + BitScan + BitXor + BitXorAssign + CeilingRoot + CeilingRootAssign + CeilingSqrt + CeilingSqrtAssign + CheckedAdd + CheckedAddMul + CheckedBinomialCoefficient + CheckedDiv + CheckedMul + CheckedNeg + CheckedPow + CheckedRoot + CheckedSqrt + CheckedSquare + CheckedSub + CheckedSubMul + Clone + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + Copy + CountOnes + CountZeros + Debug + Default + Display + Div + DivAssign + DivAssignMod + DivAssignRem + DivExact + DivExactAssign + DivMod + DivRem + DivRound + DivRoundAssign + DivisibleBy + DivisibleByPowerOf2 + Eq + EqMod + EqModPowerOf2 + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExpressAsPower + ExtendedGcd + FloorRoot + FloorRootAssign + FloorSqrt + FloorSqrtAssign + From + FromSciString + FromStr + FromStringBase + HasRandomPrimitiveInts + Hash + IsInteger + IsPower + IsSquare + JacobiSymbol + KroneckerSymbol + LeadingZeros + LegendreSymbol + LowMask + LowerHex + Max + Min + Mod + ModAssign + ModPowerOf2 + ModPowerOf2Assign + Mul + MulAssign + Named + Not + NotAssign + Octal + One + Ord + OverflowingAdd + OverflowingAddAssign + OverflowingAddMul + OverflowingAddMulAssign + OverflowingDiv + OverflowingDivAssign + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingMul + OverflowingMulAssign + OverflowingNeg + OverflowingNegAssign + OverflowingPow + OverflowingPowAssign + OverflowingSquare + OverflowingSquareAssign + OverflowingSub + OverflowingSubAssign + OverflowingSubMul + OverflowingSubMulAssign + Parity + PartialEq + PartialOrd + Pow + PowAssign + PowerOf2 + Product + RefUnwindSafe + Rem + RemAssign + RemPowerOf2 + RemPowerOf2Assign + RotateLeft + RotateLeftAssign + RotateRight + RotateRightAssign + RoundToMultiple + RoundToMultipleAssign + RoundToMultipleOfPowerOf2 + RoundToMultipleOfPowerOf2Assign + RoundingFrom + RoundingFrom + RoundingInto + RoundingInto + SaturatingAdd + SaturatingAddAssign + SaturatingAddMul + SaturatingAddMulAssign + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingMul + SaturatingMulAssign + SaturatingPow + SaturatingPowAssign + SaturatingSquare + SaturatingSquareAssign + SaturatingSub + SaturatingSubAssign + SaturatingSubMul + SaturatingSubMulAssign + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlRound + ShlRound + ShlRound + ShlRound + ShlRound + ShlRound + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + Sign + SignificantBits + Sized + Square + SquareAssign + Sub + SubAssign + SubMul + SubMulAssign + Sum + ToSci + ToStringBase + TrailingZeros + TryFrom> + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryInto> + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + Two + UnwindSafe + UpperHex + WrappingAdd + WrappingAddAssign + WrappingAddMul + WrappingAddMulAssign + WrappingDiv + WrappingDivAssign + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingMul + WrappingMulAssign + WrappingNeg + WrappingNegAssign + WrappingPow + WrappingPowAssign + WrappingSquare + WrappingSquareAssign + WrappingSub + WrappingSubAssign + WrappingSubMul + WrappingSubMulAssign + Zero { /// The number of bits of `Self`. const WIDTH: u64; /// The base-2 logarithm of the number of bits of `Self`. /// /// Whenever you need to use `n / WIDTH`, you can use `n >> LOG_WIDTH` instead. /// /// This is $\log_2 W$. /// /// Note that this value is correct for all of the built-in primitive integer types, but it will /// not be correct for custom types whose $W$ is not a power of 2. For such implementations, /// `LOG_WIDTH` should not be used. const LOG_WIDTH: u64 = Self::WIDTH.trailing_zeros() as u64; /// A mask that consists of `LOG_WIDTH` bits. /// /// Whenever you need to use `n % WIDTH`, you can use `n & WIDTH_MASK` instead. /// /// This is $W - 1$. /// /// Note that this value is correct for all of the built-in primitive integer types, but it will /// not be correct for custom types whose $W$ is not a power of 2. For such implementations, /// `WIDTH_MASK` should not be used. const WIDTH_MASK: u64 = Self::WIDTH - 1; /// Gets the most-significant bit of `Self`. For signed integers, this is the sign bit. /// /// If `Self` is unsigned, $f(n) = (n \geq 2^{W-1})$. If `Self` is unsigned, $f(n) = (n < 0)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// /// assert_eq!(123u32.get_highest_bit(), false); /// assert_eq!(4000000000u32.get_highest_bit(), true); /// assert_eq!(2000000000i32.get_highest_bit(), false); /// assert_eq!((-2000000000i32).get_highest_bit(), true); /// ``` #[inline] fn get_highest_bit(&self) -> bool { self.get_bit(Self::WIDTH - 1) } } #[cfg(not(feature = "random"))] /// Defines functions on primitive integer types: uxx, ixx, usize, and isize. /// /// The different types are distinguished by whether they are signed or unsigned, and by their /// widths. The width $W$ is the number of bits in the type. For example, the width of [`u32`] or /// [`i32`] is 32. Each type has $2^W$ distinct values. /// /// Let $n$ be a value of type `Self`. If `Self` is unsigned, $0 \leq n < 2^W$. If `Self` is signed, /// $2^{W-1} \leq n < 2^{W-1}$. pub trait PrimitiveInt: 'static + AbsDiff + Add + AddAssign + AddMul + AddMulAssign + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShl + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + ArithmeticCheckedShr + Binary + BinomialCoefficient + BitAccess + BitAnd + BitAndAssign + BitBlockAccess + BitConvertible + BitIterable + BitOr + BitOrAssign + BitScan + BitXor + BitXorAssign + CeilingRoot + CeilingRootAssign + CeilingSqrt + CeilingSqrtAssign + CheckedAdd + CheckedAddMul + CheckedBinomialCoefficient + CheckedDiv + CheckedMul + CheckedNeg + CheckedPow + CheckedRoot + CheckedSqrt + CheckedSquare + CheckedSub + CheckedSubMul + Clone + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + ConvertibleFrom + Copy + CountOnes + CountZeros + Debug + Default + Display + Div + DivAssign + DivAssignMod + DivAssignRem + DivExact + DivExactAssign + DivMod + DivRem + DivRound + DivRoundAssign + DivisibleBy + DivisibleByPowerOf2 + Eq + EqMod + EqModPowerOf2 + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactFrom + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExactInto + ExpressAsPower + ExtendedGcd + FloorRoot + FloorRootAssign + FloorSqrt + FloorSqrtAssign + From + FromSciString + FromStr + FromStringBase + Hash + IsInteger + IsPower + IsSquare + JacobiSymbol + KroneckerSymbol + LeadingZeros + LegendreSymbol + LowMask + LowerHex + Max + Min + Mod + ModAssign + ModPowerOf2 + ModPowerOf2Assign + Mul + MulAssign + Named + Not + NotAssign + Octal + One + Ord + OverflowingAdd + OverflowingAddAssign + OverflowingAddMul + OverflowingAddMulAssign + OverflowingDiv + OverflowingDivAssign + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingFrom + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingInto + OverflowingMul + OverflowingMulAssign + OverflowingNeg + OverflowingNegAssign + OverflowingPow + OverflowingPowAssign + OverflowingSquare + OverflowingSquareAssign + OverflowingSub + OverflowingSubAssign + OverflowingSubMul + OverflowingSubMulAssign + Parity + PartialEq + PartialOrd + Pow + PowAssign + PowerOf2 + Product + RefUnwindSafe + Rem + RemAssign + RemPowerOf2 + RemPowerOf2Assign + RotateLeft + RotateLeftAssign + RotateRight + RotateRightAssign + RoundToMultiple + RoundToMultipleAssign + RoundToMultipleOfPowerOf2 + RoundToMultipleOfPowerOf2Assign + RoundingFrom + RoundingFrom + RoundingInto + RoundingInto + SaturatingAdd + SaturatingAddAssign + SaturatingAddMul + SaturatingAddMulAssign + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingFrom + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingInto + SaturatingMul + SaturatingMulAssign + SaturatingPow + SaturatingPowAssign + SaturatingSquare + SaturatingSquareAssign + SaturatingSub + SaturatingSubAssign + SaturatingSubMul + SaturatingSubMulAssign + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + Shl + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlAssign + ShlRound + ShlRound + ShlRound + ShlRound + ShlRound + ShlRound + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + ShlRoundAssign + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + Shr + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrAssign + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRound + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + ShrRoundAssign + Sign + SignificantBits + Sized + Square + SquareAssign + Sub + SubAssign + SubMul + SubMulAssign + Sum + ToSci + ToStringBase + TrailingZeros + TryFrom> + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryFrom + TryInto> + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + TryInto + Two + UnwindSafe + UpperHex + WrappingAdd + WrappingAddAssign + WrappingAddMul + WrappingAddMulAssign + WrappingDiv + WrappingDivAssign + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingFrom + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingInto + WrappingMul + WrappingMulAssign + WrappingNeg + WrappingNegAssign + WrappingPow + WrappingPowAssign + WrappingSquare + WrappingSquareAssign + WrappingSub + WrappingSubAssign + WrappingSubMul + WrappingSubMulAssign + Zero { /// The number of bits of `Self`. const WIDTH: u64; /// The base-2 logarithm of the number of bits of `Self`. /// /// Whenever you need to use `n / WIDTH`, you can use `n >> LOG_WIDTH` instead. /// /// This is $\log_2 W$. /// /// Note that this value is correct for all of the built-in primitive integer types, but it will /// not be correct for custom types whose $W$ is not a power of 2. For such implementations, /// `LOG_WIDTH` should not be used. const LOG_WIDTH: u64 = Self::WIDTH.trailing_zeros() as u64; /// A mask that consists of `LOG_WIDTH` bits. /// /// Whenever you need to use `n % WIDTH`, you can use `n & WIDTH_MASK` instead. /// /// This is $W - 1$. /// /// Note that this value is correct for all of the built-in primitive integer types, but it will /// not be correct for custom types whose $W$ is not a power of 2. For such implementations, /// `WIDTH_MASK` should not be used. const WIDTH_MASK: u64 = Self::WIDTH - 1; /// Gets the most-significant bit of `Self`. For signed integers, this is the sign bit. /// /// If `Self` is unsigned, $f(n) = (n \geq 2^{W-1})$. If `Self` is unsigned, $f(n) = (n < 0)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// /// assert_eq!(123u32.get_highest_bit(), false); /// assert_eq!(4000000000u32.get_highest_bit(), true); /// assert_eq!(2000000000i32.get_highest_bit(), false); /// assert_eq!((-2000000000i32).get_highest_bit(), true); /// ``` #[inline] fn get_highest_bit(&self) -> bool { self.get_bit(Self::WIDTH - 1) } } /// Defines basic trait implementations that are the same for unsigned and signed types. macro_rules! impl_basic_traits_primitive_int { ($t:ident, $width:expr) => { /// # Examples /// /// See [here](self). impl PrimitiveInt for $t { const WIDTH: u64 = $width; } impl_named!($t); /// The constant 0. /// /// # Examples /// See [here](self). impl Zero for $t { const ZERO: $t = 0; } /// The constant 1. /// /// # Examples /// See [here](self). impl One for $t { const ONE: $t = 1; } /// The constant 2. /// /// # Examples /// See [here](self). impl Two for $t { const TWO: $t = 2; } /// The lowest value representable by this type. /// /// If `Self` is unsigned, `MIN` is 0. If `Self` is signed, `MIN` is $-2^{W-1}$. /// /// # Examples /// See [here](self). impl Min for $t { const MIN: $t = $t::MIN; } /// The highest value representable by this type. /// /// If `Self` is unsigned, `MAX` is $2^W-1$. If `Self` is signed, `MAX` is $2^{W-1}-1$. /// /// # Examples /// See [here](self). impl Max for $t { const MAX: $t = $t::MAX; } }; } impl_basic_traits_primitive_int!(u8, 8); impl_basic_traits_primitive_int!(u16, 16); impl_basic_traits_primitive_int!(u32, 32); impl_basic_traits_primitive_int!(u64, 64); impl_basic_traits_primitive_int!(u128, 128); impl_basic_traits_primitive_int!(usize, 0usize.trailing_zeros() as u64); impl_basic_traits_primitive_int!(i8, 8); impl_basic_traits_primitive_int!(i16, 16); impl_basic_traits_primitive_int!(i32, 32); impl_basic_traits_primitive_int!(i64, 64); impl_basic_traits_primitive_int!(i128, 128); impl_basic_traits_primitive_int!(isize, 0usize.trailing_zeros() as u64); ================================================ FILE: malachite-base/src/num/basic/mod.rs ================================================ // Copyright © 2026 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 . /// The [`PrimitiveFloat`](floats::PrimitiveFloat) trait. pub mod floats; /// The [`PrimitiveInt`](integers::PrimitiveInt) trait. /// /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::{One, Two, Zero}; /// /// assert_eq!(u32::WIDTH, 32); /// assert_eq!(u32::LOG_WIDTH, 5); /// assert_eq!(u32::WIDTH_MASK, 0x1f); /// /// assert_eq!(u32::ZERO, 0); /// assert_eq!(u32::ONE, 1); /// assert_eq!(i16::TWO, 2); /// /// assert_eq!(u32::MAX, 0xffffffff); /// assert_eq!(u32::MIN, 0); /// assert_eq!(i32::MAX, 0x7fffffff); /// assert_eq!(i32::MIN, -0x80000000); /// ``` pub mod integers; /// The [`PrimitiveSigned`](signeds::PrimitiveSigned) trait. /// /// ``` /// use malachite_base::num::basic::traits::NegativeOne; /// /// assert_eq!(i16::NEGATIVE_ONE, -1); /// ``` pub mod signeds; /// Traits for constants. pub mod traits; /// The [`PrimitiveUnsigned`](unsigneds::PrimitiveUnsigned) trait. pub mod unsigneds; ================================================ FILE: malachite-base/src/num/basic/signeds.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ Abs, AbsAssign, CeilingDivAssignMod, CeilingDivMod, CeilingMod, CeilingModAssign, CeilingModPowerOf2, CeilingModPowerOf2Assign, CheckedAbs, ExtendedGcd, NegAssign, OverflowingAbs, OverflowingAbsAssign, SaturatingAbs, SaturatingAbsAssign, SaturatingNeg, SaturatingNegAssign, UnsignedAbs, WrappingAbs, WrappingAbsAssign, }; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::traits::NegativeOne; use crate::num::comparison::traits::{EqAbs, OrdAbs, PartialOrdAbs}; use crate::num::logic::traits::CheckedHammingDistance; #[cfg(feature = "random")] use crate::num::random::{HasRandomSignedRange, RandomSignedChunkable}; use core::ops::Neg; // When the `random` feature is enabled, the HasRandomSignedRange and RandomSignedChunkable bounds // are included. #[cfg(feature = "random")] /// Defines functions on primitive signed integer types: ixx and isize. pub trait PrimitiveSigned: Abs + AbsAssign + CeilingDivAssignMod + CeilingDivMod + CeilingMod + CeilingModAssign + CeilingModPowerOf2 + CeilingModPowerOf2Assign + CheckedAbs + CheckedHammingDistance + EqAbs + ExtendedGcd + From + HasRandomSignedRange + Neg + NegAssign + NegativeOne + OrdAbs + OverflowingAbs + OverflowingAbsAssign + PartialOrdAbs + PrimitiveInt + RandomSignedChunkable + SaturatingAbs + SaturatingAbsAssign + SaturatingNeg + SaturatingNegAssign + UnsignedAbs + WrappingAbs + WrappingAbsAssign { } #[cfg(not(feature = "random"))] /// Defines functions on primitive signed integer types: ixx and isize. pub trait PrimitiveSigned: Abs + AbsAssign + CeilingDivAssignMod + CeilingDivMod + CeilingMod + CeilingModAssign + CeilingModPowerOf2 + CeilingModPowerOf2Assign + CheckedAbs + CheckedHammingDistance + EqAbs + ExtendedGcd + From + Neg + NegAssign + NegativeOne + OrdAbs + OverflowingAbs + OverflowingAbsAssign + PartialOrdAbs + PrimitiveInt + SaturatingAbs + SaturatingAbsAssign + SaturatingNeg + SaturatingNegAssign + UnsignedAbs + WrappingAbs + WrappingAbsAssign { } /// Defines basic trait implementations for signed types. macro_rules! impl_basic_traits { ($s: ident) => { impl PrimitiveSigned for $s {} /// The constant -1. /// /// # Examples /// See [here](self). impl NegativeOne for $s { const NEGATIVE_ONE: $s = -1; } }; } apply_to_signeds!(impl_basic_traits); ================================================ FILE: malachite-base/src/num/basic/traits.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Implementations of traits for NonZero* types by b4D8. // // 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 core::num::*; /// Provides the constant 0. #[allow(clippy::declare_interior_mutable_const)] pub trait Zero { const ZERO: Self; } /// Provides the constant 1. #[allow(clippy::declare_interior_mutable_const)] pub trait One { const ONE: Self; } /// Provides the constant 2. #[allow(clippy::declare_interior_mutable_const)] pub trait Two { const TWO: Self; } /// Provides the constant -1. #[allow(clippy::declare_interior_mutable_const)] pub trait NegativeOne { const NEGATIVE_ONE: Self; } /// Provides the constant 1/2. #[allow(clippy::declare_interior_mutable_const)] pub trait OneHalf { const ONE_HALF: Self; } /// Provides the constant -0. #[allow(clippy::declare_interior_mutable_const)] pub trait NegativeZero { const NEGATIVE_ZERO: Self; } /// Provides the constant (positive) Infinity. #[allow(clippy::declare_interior_mutable_const)] pub trait Infinity { const INFINITY: Self; } /// Provides the constant -Infinity. #[allow(clippy::declare_interior_mutable_const)] pub trait NegativeInfinity { const NEGATIVE_INFINITY: Self; } /// Provides the constant NaN. #[allow(clippy::declare_interior_mutable_const)] pub trait NaN { const NAN: Self; } /// Provides the Prouhet-Thue-Morse constant, whose bits are the Thue-Morse sequence. pub trait ProuhetThueMorseConstant { const PROUHET_THUE_MORSE_CONSTANT: Self; } /// Provides the prime constant, whose $n$th bit (starting from $n=1$) is true if and only if $n$ is /// prime. pub trait PrimeConstant { const PRIME_CONSTANT: Self; } /// Provides $\ln 2$. pub trait Ln2 { const LN_2: Self; } /// Provides $\log_2 e$. pub trait Log2E { const LOG_2_E: Self; } /// Provides $\sqrt{2}$. pub trait Sqrt2 { const SQRT_2: Self; } /// Provides $\sqrt{3}$. pub trait Sqrt3 { const SQRT_3: Self; } /// Provides $\sqrt{2}/2=\sqrt{1/2}=1/\sqrt{2}$. pub trait Sqrt2Over2 { const SQRT_2_OVER_2: Self; } /// Provides $\sqrt{3}/3=\sqrt{1/3}=1/\sqrt{3}$. pub trait Sqrt3Over3 { const SQRT_3_OVER_3: Self; } /// Provides $\varphi$, the golden ratio. pub trait Phi { const PHI: Self; } /// Provides $\pi$. pub trait Pi { const PI: Self; } /// Provides $\tau=2\pi$. pub trait Tau { const TAU: Self; } /// Provides $\pi/2$. pub trait PiOver2 { const PI_OVER_2: Self; } /// Provides $\pi/3$. pub trait PiOver3 { const PI_OVER_3: Self; } /// Provides $\pi/4$. pub trait PiOver4 { const PI_OVER_4: Self; } /// Provides $\pi/6$. pub trait PiOver6 { const PI_OVER_6: Self; } /// Provides $\pi/8$. pub trait PiOver8 { const PI_OVER_8: Self; } /// Provides $1/\pi$. pub trait OneOverPi { const ONE_OVER_PI: Self; } /// Provides $\sqrt{\pi}$. pub trait SqrtPi { const SQRT_PI: Self; } /// Provides $1/\sqrt{\pi}$. pub trait OneOverSqrtPi { const ONE_OVER_SQRT_PI: Self; } /// Provides $1/\sqrt{\tau}=1/\sqrt{2\pi}$. pub trait OneOverSqrtTau { const ONE_OVER_SQRT_TAU: Self; } /// Provides $2/\pi$. pub trait TwoOverPi { const TWO_OVER_PI: Self; } /// Provides $2/\sqrt{\pi}$. pub trait TwoOverSqrtPi { const TWO_OVER_SQRT_PI: Self; } /// Provides Gauss's constant, $G=1/\mathrm{AGM}(1,\sqrt{2})$. /// /// Having three consecutive esses in an identifier is awkward, so let's pretend that we sometimes /// use AP Style and write "Gauss' constant". pub trait GaussConstant { const GAUSS_CONSTANT: Self; } /// Provides the lemniscate constant $\varpi=\pi G$, where $G$ is Gauss's constant. pub trait LemniscateConstant { const LEMNISCATE_CONSTANT: Self; } // Implementation for `NonZero*` types: // - `One` and `Two` for both signed and unsigned variants // - `NegativeOne` for the signed variant macro_rules! impl_non_zero { ($($t:ident),+) => { $( impl One for $t { const ONE: Self = match Self::new(1) { Some(v) => v, None => unreachable!() // 1 is a valid nonzero value }; } impl Two for $t { const TWO: Self = match Self::new(2) { Some(v) => v, None => unreachable!() // 2 is a valid nonzero value }; } )+ }; ($($u:ident && $i:ident),+) => { $( impl_non_zero!($u, $i); impl NegativeOne for $i { const NEGATIVE_ONE: Self = match Self::new(-1) { Some(v) => v, None => unreachable!() // -1 is a valid non zero value }; } )+ } } impl_non_zero!( NonZeroUsize && NonZeroIsize, NonZeroU128 && NonZeroI128, NonZeroU64 && NonZeroI64, NonZeroU32 && NonZeroI32, NonZeroU16 && NonZeroI16, NonZeroU8 && NonZeroI8 ); ================================================ FILE: malachite-base/src/num/basic/unsigneds.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ AbsDiff, AbsDiffAssign, CeilingDivAssignNegMod, CeilingDivNegMod, CeilingLogBase, CeilingLogBase2, CeilingLogBasePowerOf2, CheckedDoubleFactorial, CheckedFactorial, CheckedLcm, CheckedLogBase, CheckedLogBase2, CheckedLogBasePowerOf2, CheckedMultifactorial, CheckedNextPowerOf2, CheckedPrimorial, CheckedSubfactorial, CoprimeWith, DoubleFactorial, ExtendedGcd, Factorial, FloorLogBase, FloorLogBase2, FloorLogBasePowerOf2, Gcd, GcdAssign, IsPowerOf2, Lcm, LcmAssign, ModAdd, ModAddAssign, ModInverse, ModIsReduced, ModMul, ModMulAssign, ModMulPrecomputed, ModMulPrecomputedAssign, ModNeg, ModNegAssign, ModPow, ModPowAssign, ModPowPrecomputed, ModPowPrecomputedAssign, ModPowerOf2, ModPowerOf2Add, ModPowerOf2AddAssign, ModPowerOf2Inverse, ModPowerOf2IsReduced, ModPowerOf2Mul, ModPowerOf2MulAssign, ModPowerOf2Neg, ModPowerOf2NegAssign, ModPowerOf2Pow, ModPowerOf2PowAssign, ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, ModPowerOf2ShrAssign, ModPowerOf2Square, ModPowerOf2SquareAssign, ModPowerOf2Sub, ModPowerOf2SubAssign, ModSquare, ModSquareAssign, ModSquarePrecomputed, ModSquarePrecomputedAssign, ModSub, ModSubAssign, Multifactorial, NegMod, NegModAssign, NegModPowerOf2, NegModPowerOf2Assign, NextPowerOf2, NextPowerOf2Assign, Primorial, RootAssignRem, RootRem, SqrtAssignRem, SqrtRem, Subfactorial, XMulYToZZ, XXAddYYToZZ, XXDivModYToQR, XXSubYYToZZ, XXXAddYYYToZZZ, XXXSubYYYToZZZ, XXXXAddYYYYToZZZZ, }; use crate::num::basic::integers::PrimitiveInt; use crate::num::conversion::traits::{ Digits, FromOtherTypeSlice, IntegerMantissaAndExponent, PowerOf2DigitIterable, PowerOf2Digits, SciMantissaAndExponent, VecFromOtherType, VecFromOtherTypeSlice, }; use crate::num::factorization::primes::{PrimesIterator, PrimesLessThanIterator}; use crate::num::factorization::traits::Primes; use crate::num::logic::traits::{BitBlockAccess, HammingDistance}; /// Defines functions on primitive unsigned integer types: uxx and usize. pub trait PrimitiveUnsigned: AbsDiff + AbsDiffAssign + BitBlockAccess + CeilingLogBase + CeilingLogBase2 + CeilingLogBasePowerOf2 + CeilingDivAssignNegMod + CeilingDivNegMod + CheckedDoubleFactorial + CheckedFactorial + CheckedMultifactorial + CheckedPrimorial + CheckedSubfactorial + CheckedLcm + CheckedLogBase + CheckedLogBase2 + CheckedLogBasePowerOf2 + CheckedNextPowerOf2 + CoprimeWith + DoubleFactorial + Digits + Digits + Digits + Digits + Digits + Digits + ExtendedGcd + Factorial + FloorLogBase + FloorLogBase2 + FloorLogBasePowerOf2 + From + FromOtherTypeSlice + FromOtherTypeSlice + FromOtherTypeSlice + FromOtherTypeSlice + FromOtherTypeSlice + FromOtherTypeSlice + Gcd + GcdAssign + HammingDistance + IntegerMantissaAndExponent + IsPowerOf2 + Lcm + LcmAssign + ModIsReduced + ModAdd + ModAddAssign + ModInverse + ModMul + ModMulAssign + ModMulPrecomputed + ModMulPrecomputedAssign + ModNeg + ModNegAssign + ModPow + ModPowAssign + ModPowerOf2 + ModPowerOf2Add + ModPowerOf2AddAssign + ModPowerOf2Inverse + ModPowerOf2IsReduced + ModPowerOf2Mul + ModPowerOf2MulAssign + ModPowerOf2Neg + ModPowerOf2NegAssign + ModPowerOf2Pow + ModPowerOf2PowAssign + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2Shl + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2ShlAssign + ModPowerOf2Shr + ModPowerOf2Shr + ModPowerOf2Shr + ModPowerOf2Shr + ModPowerOf2Shr + ModPowerOf2ShrAssign + ModPowerOf2ShrAssign + ModPowerOf2ShrAssign + ModPowerOf2ShrAssign + ModPowerOf2ShrAssign + ModPowerOf2ShrAssign + ModPowerOf2Square + ModPowerOf2SquareAssign + ModPowerOf2Sub + ModPowerOf2SubAssign + ModPowPrecomputed + ModPowPrecomputedAssign + ModSquare + ModSquareAssign + ModSquarePrecomputed + ModSquarePrecomputedAssign + ModSub + ModSubAssign + Multifactorial + NegMod + NegModAssign + NegModPowerOf2 + NegModPowerOf2Assign + NextPowerOf2 + NextPowerOf2Assign + PowerOf2Digits + PowerOf2Digits + PowerOf2Digits + PowerOf2Digits + PowerOf2Digits + PowerOf2Digits + PowerOf2DigitIterable + PowerOf2DigitIterable + PowerOf2DigitIterable + PowerOf2DigitIterable + PowerOf2DigitIterable + PowerOf2DigitIterable + Primes, LI = PrimesLessThanIterator> + PrimitiveInt + Primorial + RootRem + RootAssignRem + SciMantissaAndExponent + SciMantissaAndExponent + SqrtRem + SqrtAssignRem + Subfactorial + VecFromOtherType + VecFromOtherType + VecFromOtherType + VecFromOtherType + VecFromOtherType + VecFromOtherType + VecFromOtherTypeSlice + VecFromOtherTypeSlice + VecFromOtherTypeSlice + VecFromOtherTypeSlice + VecFromOtherTypeSlice + VecFromOtherTypeSlice + XXAddYYToZZ + XXDivModYToQR + XXSubYYToZZ + XMulYToZZ + XXXAddYYYToZZZ + XXXSubYYYToZZZ + XXXXAddYYYYToZZZZ { } macro_rules! impl_basic_traits { ($u:ident) => { impl PrimitiveUnsigned for $u {} }; } apply_to_unsigneds!(impl_basic_traits); ================================================ FILE: malachite-base/src/num/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::UnsignedAbs; use crate::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use core::cmp::Ordering; macro_rules! impl_partial_ord_abs { ($t:ident) => { impl PartialOrdAbs<$t> for $t { /// Compares the absolute values of two numbers, taking both by reference. /// /// The [`PartialOrdAbs`] interface allows for pairs of incomparable elements, but for /// primitive integers these never occur. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::cmp_abs#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { Some(self.cmp_abs(other)) } } }; } apply_to_signeds!(impl_partial_ord_abs); fn cmp_abs_signed>(x: &S, y: &S) -> Ordering { x.unsigned_abs().cmp(&y.unsigned_abs()) } macro_rules! impl_ord_abs_signed { ($t:ident) => { impl OrdAbs for $t { /// Compares the absolute values of two numbers, taking both by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::cmp_abs#cmp_abs). #[inline] fn cmp_abs(&self, other: &Self) -> Ordering { cmp_abs_signed(self, other) } } }; } apply_to_signeds!(impl_ord_abs_signed); macro_rules! impl_ord_abs_primitive_float { ($t:ident) => { impl PartialOrdAbs for $t { /// Compares the absolute values of two numbers, taking both by reference. /// /// For unsigned values, this is the same as ordinary comparison. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::cmp_abs#cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Self) -> Option { self.abs().partial_cmp(&other.abs()) } } }; } apply_to_primitive_floats!(impl_ord_abs_primitive_float); ================================================ FILE: malachite-base/src/num/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 crate::num::comparison::traits::EqAbs; macro_rules! impl_eq_abs_signed { ($t:ident) => { impl EqAbs<$t> for $t { /// Compares the absolute values of two numbers for equality, taking both by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::eq_abs#eq_abs). #[inline] fn eq_abs(&self, other: &Self) -> bool { self.unsigned_abs() == other.unsigned_abs() } } }; } apply_to_signeds!(impl_eq_abs_signed); macro_rules! impl_eq_abs_float { ($t:ident) => { impl EqAbs<$t> for $t { /// Compares the absolute values of two numbers for equality, taking both by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::eq_abs#eq_abs). #[inline] fn eq_abs(&self, other: &Self) -> bool { self.abs() == other.abs() } } }; } apply_to_primitive_floats!(impl_eq_abs_float); ================================================ FILE: malachite-base/src/num/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// [`PartialOrdAbs`](`traits::PartialOrdAbs`) and [`OrdAbs`](`traits::OrdAbs`), traits for /// comparing the absolute values of numbers by order. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use std::cmp::Ordering::*; /// /// assert_eq!(123i32.partial_cmp_abs(&-456), Some(Less)); /// assert_eq!(123i32.partial_cmp_abs(&-123), Some(Equal)); /// ``` /// /// # cmp_abs /// ``` /// use malachite_base::num::comparison::traits::OrdAbs; /// use std::cmp::Ordering::*; /// /// assert_eq!(123i32.cmp_abs(&-456), Less); /// assert_eq!(123i32.cmp_abs(&-123), Equal); /// ``` pub mod cmp_abs; /// [`EqAbs`](`traits::EqAbs`), a trait for comparing the absolute values of numbers by equality. /// /// # eq_abs /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// /// assert_eq!(123i32.eq_abs(&-456), false); /// assert_eq!(123i32.eq_abs(&-123), true); /// assert_eq!(1.0.eq_abs(&-1.0), true); /// assert_eq!(1.0.eq_abs(&f64::NAN), false); /// ``` pub mod eq_abs; /// Various traits for comparing numbers. pub mod traits; ================================================ FILE: malachite-base/src/num/comparison/traits.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; /// Determines equality between the absolute values of two numbers. pub trait EqAbs { /// Compares the absolute values of two numbers for equality, taking both by reference. fn eq_abs(&self, other: &Rhs) -> bool; /// Compares the absolute values of two numbers for inequality, taking both by reference. /// /// # Worst-case complexity /// Same as the time and additional memory complexity of [`eq_abs`](Self::eq_abs). #[inline] fn ne_abs(&self, other: &Rhs) -> bool { !self.eq_abs(other) } } /// Determines equality between the absolute values of two numbers, where some pairs of numbers may /// not be comparable. pub trait PartialOrdAbs { /// Compares the absolute values of two numbers, taking both by reference. /// /// If the two values are not comparable, `None` is returned. fn partial_cmp_abs(&self, other: &Rhs) -> Option; /// Determines whether the absolute value of one number is less than the absolute value of /// another. /// /// # Worst-case complexity /// Same as the time and additional memory complexity of /// [`partial_cmp_abs`](Self::partial_cmp_abs). #[inline] fn lt_abs(&self, other: &Rhs) -> bool { matches!(self.partial_cmp_abs(other), Some(Less)) } /// Determines whether the absolute value of one number is less than or equal to the absolute /// value of another. /// /// # Worst-case complexity /// Same as the time and additional memory complexity of /// [`partial_cmp_abs`](Self::partial_cmp_abs). #[inline] fn le_abs(&self, other: &Rhs) -> bool { matches!(self.partial_cmp_abs(other), Some(Less | Equal)) } /// Determines whether the absolute value of one number is greater than the absolute value of /// another. /// /// # Worst-case complexity /// Same as the time and additional memory complexity of /// [`partial_cmp_abs`](Self::partial_cmp_abs). #[inline] fn gt_abs(&self, other: &Rhs) -> bool { matches!(self.partial_cmp_abs(other), Some(Greater)) } /// Determines whether the absolute value of one number is greater than or equal to the absolute /// value of another. /// /// # Worst-case complexity /// Same as the time and additional memory complexity of /// [`partial_cmp_abs`](Self::partial_cmp_abs). #[inline] fn ge_abs(&self, other: &Rhs) -> bool { matches!(self.partial_cmp_abs(other), Some(Greater | Equal)) } } /// Compares the absolute values of two numbers. pub trait OrdAbs: Eq + PartialOrdAbs { fn cmp_abs(&self, other: &Self) -> Ordering; } ================================================ FILE: malachite-base/src/num/conversion/digits/general_digits.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, PowerOf2Digits, WrappingFrom, }; use alloc::vec::Vec; use itertools::Itertools; pub_test! {unsigned_to_digits_asc_naive< T: ExactFrom + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, >( x: &T, base: U, ) -> Vec { assert!(base > U::ONE); let mut digits = Vec::new(); let mut remainder = *x; let base = T::exact_from(base); while remainder != T::ZERO { digits.push(U::wrapping_from(remainder.div_assign_mod(base))); } digits }} fn to_digits_asc< T: ConvertibleFrom + ExactFrom + PrimitiveUnsigned + PowerOf2Digits, U: PrimitiveUnsigned + WrappingFrom, >( x: &T, base: &U, ) -> Vec { assert!(T::convertible_from(*base)); if *x == T::ZERO { Vec::new() } else if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_asc(log_base) } else { unsigned_to_digits_asc_naive(x, *base) } } fn to_digits_desc< T: ConvertibleFrom + ExactFrom + PrimitiveUnsigned + PowerOf2Digits, U: PrimitiveUnsigned + WrappingFrom, >( x: &T, base: &U, ) -> Vec { assert!(T::convertible_from(*base)); if *x == T::ZERO { Vec::new() } else if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_desc(log_base) } else { let mut digits = unsigned_to_digits_asc_naive(x, *base); digits.reverse(); digits } } fn from_digits_asc< T: Digits + PowerOf2Digits, U: PrimitiveUnsigned, I: Iterator, >( base: &U, digits: I, ) -> Option { if let Some(log_base) = base.checked_log_base_2() { T::from_power_of_2_digits_asc(log_base, digits) } else { let mut digits = digits.collect_vec(); digits.reverse(); T::from_digits_desc(base, digits.into_iter()) } } fn from_digits_desc< T: Digits + TryFrom + PrimitiveUnsigned + PowerOf2Digits, U: PrimitiveUnsigned, I: Iterator, >( base: &U, digits: I, ) -> Option { assert!(*base > U::ONE); if let Some(log_base) = base.checked_log_base_2() { T::from_power_of_2_digits_desc(log_base, digits) } else { let base = T::try_from(*base).ok()?; let mut x = T::ZERO; for digit in digits { let digit = T::try_from(digit).ok()?; if digit >= base { return None; } x = x.checked_mul(base)?.checked_add(digit)?; } Some(x) } } macro_rules! impl_digits { ($t:ident) => { macro_rules! impl_digits_inner { ($u:ident) => { impl Digits<$u> for $t { /// Returns a [`Vec`] containing the digits of a number in ascending order /// (least- to most-significant). /// /// The base must be convertible to `Self`. If `self` is 0, the [`Vec`] is /// empty; otherwise, it ends with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or /// $d_{k-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than `Self::MAX`. /// /// # Examples /// See [here](super::general_digits#to_digits_asc). #[inline] fn to_digits_asc(&self, base: &$u) -> Vec<$u> { to_digits_asc(self, base) } /// Returns a [`Vec`] containing the digits of a number in descending order /// (most- to least-significant). /// /// The base must be convertible to `Self`. If `self` is 0, the [`Vec`] is /// empty; otherwise, it begins with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or /// $d_{k-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_{k-i-1} = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than `$t::MAX`. /// /// # Examples /// See [here](super::general_digits#to_digits_desc). #[inline] fn to_digits_desc(&self, base: &$u) -> Vec<$u> { to_digits_desc(self, base) } /// Converts an iterator of digits into a value. /// /// The input digits are in ascending order (least- to most-significant). The /// base must be no larger than `Self::MAX`. The function returns `None` if the /// input represents a number that can't fit in `Self`, if `base` is greater /// than `Self::MAX`, or if any of the digits are greater than or equal to the /// base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^id_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#from_digits_asc). #[inline] fn from_digits_asc>(base: &$u, digits: I) -> Option<$t> { from_digits_asc(base, digits) } /// Converts an iterator of digits into a value. /// /// The input digits are in descending order (most- to least-significant). The /// base must be no larger than `Self::MAX`. The function returns `None` if the /// input represents a number that can't fit in `Self`, if `base` is greater /// than `Self::MAX`, or if any of the digits are greater than or equal to the /// base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^{k-i-1}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#from_digits_desc). #[inline] fn from_digits_desc>( base: &$u, digits: I, ) -> Option<$t> { from_digits_desc(base, digits) } } }; } apply_to_unsigneds!(impl_digits_inner); }; } apply_to_unsigneds!(impl_digits); ================================================ FILE: malachite-base/src/num/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 . /// [`Digits`](super::traits::Digits), a trait for extracting digits from numbers and constructing /// numbers from digits. /// /// # to_digits_asc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// /// assert_eq!(0u8.to_digits_asc(&6u64), &[]); /// assert_eq!(2u16.to_digits_asc(&6u32), &[2]); /// assert_eq!( /// 123456u32.to_digits_asc(&3u16), /// &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2] /// ); /// ``` /// /// # to_digits_desc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// /// assert_eq!(0u8.to_digits_asc(&6u64), &[]); /// assert_eq!(2u16.to_digits_asc(&6u32), &[2]); /// assert_eq!( /// 123456u32.to_digits_desc(&3u16), /// &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0] /// ); /// ``` /// /// # from_digits_asc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// /// assert_eq!( /// u8::from_digits_asc(&64, [0u64, 0, 0].iter().cloned()), /// Some(0) /// ); /// assert_eq!( /// u32::from_digits_asc(&3, [0u64, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2].iter().cloned()), /// Some(123456) /// ); /// assert_eq!( /// u32::from_digits_asc(&8, [3u16, 7, 1].iter().cloned()), /// Some(123) /// ); /// /// assert!(u64::from_digits_asc(&64, [1u8; 1000].iter().cloned()).is_none()); /// assert!(u64::from_digits_asc(&2, [2u8].iter().cloned()).is_none()); /// assert!(u8::from_digits_asc(&1000, [1u16, 2, 3].iter().cloned()).is_none()); /// ``` /// /// # from_digits_desc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// /// assert_eq!( /// u8::from_digits_desc(&64, [0u64, 0, 0].iter().cloned()), /// Some(0) /// ); /// assert_eq!( /// u32::from_digits_desc(&3, [2u64, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0].iter().cloned()), /// Some(123456) /// ); /// assert_eq!( /// u32::from_digits_desc(&8, [1u16, 7, 3].iter().cloned()), /// Some(123) /// ); /// /// assert!(u64::from_digits_desc(&64, [1u8; 1000].iter().cloned()).is_none()); /// assert!(u64::from_digits_desc(&2, [2u8].iter().cloned()).is_none()); /// assert!(u8::from_digits_desc(&1000, [1u16, 2, 3].iter().cloned()).is_none()); /// ``` pub mod general_digits; /// [`PowerOf2DigitIterable`](super::traits::PowerOf2DigitIterable), a trait for producing /// [`PrimitivePowerOf2DigitIterator`](power_of_2_digit_iterable::PrimitivePowerOf2DigitIterator), a /// double-ended iterator for iterating over a number's base-$2^k$ digits. /// /// # power_of_2_digits /// ``` /// use itertools::Itertools; /// use malachite_base::num::conversion::traits::PowerOf2DigitIterable; /// /// let mut digits = PowerOf2DigitIterable::::power_of_2_digits(0u8, 2); /// assert!(digits.next().is_none()); /// /// // 107 = 1101011b /// let digits = PowerOf2DigitIterable::::power_of_2_digits(107u32, 2); /// assert_eq!(digits.collect_vec(), &[3, 2, 2, 1]); /// /// let mut digits = PowerOf2DigitIterable::::power_of_2_digits(0u8, 2); /// assert!(digits.next_back().is_none()); /// /// // 107 = 1101011b /// let digits = PowerOf2DigitIterable::::power_of_2_digits(107u32, 2); /// assert_eq!(digits.rev().collect_vec(), &[1, 2, 2, 3]); /// ``` pub mod power_of_2_digit_iterable; /// [`PowerOf2Digits`](super::traits::PowerOf2Digits), a trait for extracting base-$2^k$ $digits /// from numbers and constructing numbers from digits. /// /// # to_power_of_2_digits_asc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&0u8, 6), /// &[] /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&2u16, 6), /// &[2] /// ); /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&123u32, 3), /// &[3, 7, 1] /// ); /// ``` /// /// # to_power_of_2_digits_desc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&0u8, 6), /// &[] /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&2u16, 6), /// &[2] /// ); /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&123u32, 3), /// &[1, 7, 3] /// ); /// ``` /// /// # from_power_of_2_digits_asc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// /// assert_eq!( /// u8::from_power_of_2_digits_asc(6, [0u64, 0, 0].iter().cloned()), /// Some(0) /// ); /// assert_eq!( /// u16::from_power_of_2_digits_asc(6, [2u64, 0].iter().cloned()), /// Some(2) /// ); /// assert_eq!( /// u32::from_power_of_2_digits_asc(3, [3u16, 7, 1].iter().cloned()), /// Some(123) /// ); /// /// assert!(u8::from_power_of_2_digits_asc(4, [1u64; 100].iter().cloned()).is_none()); /// assert!(u8::from_power_of_2_digits_asc(1, [2u64].iter().cloned()).is_none()); /// ``` /// /// # from_power_of_2_digits_desc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// /// assert_eq!( /// u8::from_power_of_2_digits_desc(6, [0u64, 0, 0].iter().cloned()), /// Some(0) /// ); /// assert_eq!( /// u16::from_power_of_2_digits_desc(6, [0u64, 2].iter().cloned()), /// Some(2) /// ); /// assert_eq!( /// u32::from_power_of_2_digits_desc(3, [1u16, 7, 3].iter().cloned()), /// Some(123) /// ); /// /// assert!(u8::from_power_of_2_digits_desc(4, [1u64; 100].iter().cloned()).is_none()); /// assert!(u8::from_power_of_2_digits_desc(1, [2u64].iter().cloned()).is_none()); /// ``` pub mod power_of_2_digits; ================================================ FILE: malachite-base/src/num/conversion/digits/power_of_2_digit_iterable.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivRound, SaturatingSubAssign}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, WrappingFrom, }; use crate::num::logic::traits::BitBlockAccess; use crate::rounding_modes::RoundingMode::*; use core::marker::PhantomData; /// A double-ended iterator over the base-$2^k$ digits of an unsigned primitive integer. /// /// This `struct` is created by the [`PowerOf2DigitIterable::power_of_2_digits`] function. See its /// documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct PrimitivePowerOf2DigitIterator { pub(crate) value: T, pub(crate) log_base: u64, pub(crate) remaining: usize, // If `n` is nonzero, this index initially points to the least-significant bit of the least- // significant digit, and is left-shifted by `next`. pub(crate) i: u64, // If `n` is nonzero, this mask initially points to the least-significant bit of the most- // significant nonzero digit, and is right-shifted by `next_back`. pub(crate) j: u64, phantom: PhantomData<*const U>, } impl::Bits>> Iterator for PrimitivePowerOf2DigitIterator { type Item = U; fn next(&mut self) -> Option { if self.remaining != 0 { let digit = U::wrapping_from(self.value.get_bits(self.i, self.i + self.log_base)); self.i += self.log_base; self.remaining -= 1; Some(digit) } else { None } } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl::Bits>> DoubleEndedIterator for PrimitivePowerOf2DigitIterator { fn next_back(&mut self) -> Option { if self.remaining != 0 { let digit = U::wrapping_from(self.value.get_bits(self.j, self.j + self.log_base)); self.j.saturating_sub_assign(self.log_base); self.remaining -= 1; Some(digit) } else { None } } } impl::Bits>> ExactSizeIterator for PrimitivePowerOf2DigitIterator { } impl::Bits>> PowerOf2DigitIterator for PrimitivePowerOf2DigitIterator { /// Retrieves base-$2^k$ digits by index. /// /// Indexing at or above the significant digit count returns zero. /// /// This function doesn't affect, and isn't affected by, the iterator's position. /// /// $f(x, k, i) = d_i$, where $0 \leq d_i < 2^k$ for all $i$ and /// $$ /// \sum_{i=0}^\infty2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::{ /// PowerOf2DigitIterable, PowerOf2DigitIterator, /// }; /// /// let digits = PowerOf2DigitIterable::::power_of_2_digits(0u8, 2); /// assert_eq!(digits.get_digit(0), 0); /// /// // 107 = 1101011b /// let digits = PowerOf2DigitIterable::::power_of_2_digits(107u32, 2); /// assert_eq!(digits.get_digit(0), 3); /// assert_eq!(digits.get_digit(1), 2); /// assert_eq!(digits.get_digit(2), 2); /// assert_eq!(digits.get_digit(100), 0); /// ``` fn get_digit(&self, index: u64) -> U { let i = index * self.log_base; U::wrapping_from(self.value.get_bits(i, i + self.log_base)) } } fn power_of_2_digits( x: T, log_base: u64, ) -> PrimitivePowerOf2DigitIterator { assert_ne!(log_base, 0); assert!( log_base <= U::WIDTH, "type {:?} is too small for a digit of width {}", U::NAME, log_base ); let significant_digits = x.significant_bits().div_round(log_base, Ceiling).0; PrimitivePowerOf2DigitIterator { value: x, log_base, remaining: usize::exact_from(significant_digits), i: 0, j: significant_digits.saturating_sub(1) * log_base, phantom: PhantomData, } } macro_rules! impl_power_of_2_digit_iterable { ($t:ident) => { macro_rules! impl_power_of_2_digit_iterable_inner { ($u:ident) => { impl PowerOf2DigitIterable<$u> for $t { type PowerOf2DigitIterator = PrimitivePowerOf2DigitIterator<$t, $u>; /// Returns a double-ended iterator over the base-$2^k$ digits of a primitive /// unsigned integer. /// /// The forward order is ascending, so that less-significant digits appear /// first. There are no trailing zeros going forward, or leading zeros going /// backward. /// /// If it's necessary to get a [`Vec`] of all the digits, consider using /// [`to_power_of_2_digits_asc`](super::super::traits::PowerOf2Digits::to_power_of_2_digits_asc) /// or /// [`to_power_of_2_digits_desc`](super::super::traits::PowerOf2Digits::to_power_of_2_digits_desc) /// instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `log_base` is larger than the width of output type width. /// /// # Examples /// See [here](super::power_of_2_digit_iterable#power_of_2_digits). #[inline] fn power_of_2_digits( self, log_base: u64, ) -> PrimitivePowerOf2DigitIterator<$t, $u> { power_of_2_digits(self, log_base) } } }; } apply_to_unsigneds!(impl_power_of_2_digit_iterable_inner); }; } apply_to_unsigneds!(impl_power_of_2_digit_iterable); ================================================ FILE: malachite-base/src/num/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{PowerOf2Digits, WrappingFrom}; use alloc::vec::Vec; fn to_power_of_2_digits_asc>( x: &T, log_base: u64, ) -> Vec { assert_ne!(log_base, 0); assert!( log_base <= U::WIDTH, "type {:?} is too small for a digit of width {}", U::NAME, log_base ); let mut digits = Vec::new(); if *x == T::ZERO { } else if x.significant_bits() <= log_base { digits.push(U::wrapping_from(*x)); } else { let mut x = *x; let mask = U::low_mask(log_base); while x != T::ZERO { digits.push(U::wrapping_from(x) & mask); x >>= log_base; } } digits } fn to_power_of_2_digits_desc>( x: &T, log_base: u64, ) -> Vec { let mut digits = to_power_of_2_digits_asc(x, log_base); digits.reverse(); digits } fn from_power_of_2_digits_asc< T: TryFrom + PrimitiveUnsigned + WrappingFrom, U: PrimitiveUnsigned, I: Iterator, >( log_base: u64, digits: I, ) -> Option { assert_ne!(log_base, 0); assert!( log_base <= U::WIDTH, "type {:?} is too small for a digit of width {}", U::NAME, log_base ); let mut n = T::ZERO; let mut shift = 0; for digit in digits { if digit.significant_bits() > log_base { return None; } n |= T::try_from(digit) .ok() .and_then(|d| d.arithmetic_checked_shl(shift))?; shift += log_base; } Some(n) } fn from_power_of_2_digits_desc< T: PrimitiveUnsigned + WrappingFrom, U: PrimitiveUnsigned, I: Iterator, >( log_base: u64, digits: I, ) -> Option { assert_ne!(log_base, 0); assert!( log_base <= U::WIDTH, "type {:?} is too small for a digit of width {}", U::NAME, log_base ); let mut n = T::ZERO; for digit in digits { if digit.significant_bits() > log_base { return None; } let shifted = n.arithmetic_checked_shl(log_base)?; n = shifted | T::wrapping_from(digit); } Some(n) } macro_rules! impl_power_of_2_digits { ($t:ident) => { macro_rules! impl_power_of_2_digits_inner { ($u:ident) => { impl PowerOf2Digits<$u> for $t { /// Returns a [`Vec`] containing the base-$2^k$ digits of a number in ascending /// order (least- to most-significant). /// /// The base-2 logarithm of the base is specified. `log_base` must be no larger /// than the width of the digit type. If `self` is 0, the [`Vec`] is empty; /// otherwise, it ends with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ /// or $d_{n-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{n-1}2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the output type, or if /// `log_base` is zero. /// /// # Examples /// See [here](super::power_of_2_digits#to_power_of_2_digits_asc). #[inline] fn to_power_of_2_digits_asc(&self, log_base: u64) -> Vec<$u> { to_power_of_2_digits_asc(self, log_base) } /// Returns a [`Vec`] containing the base-$2^k$ digits of a number in descending /// order (most- to least-significant). /// /// The base-2 logarithm of the base is specified. `log_base` must be no larger /// than the width of the digit type. If `self` is 0, the [`Vec`] is empty; /// otherwise, it begins with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ /// or $d_0 \neq 0$, and /// /// $$ /// \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the output type, or if /// `log_base` is zero. /// /// # Examples /// See [here](super::power_of_2_digits#to_power_of_2_digits_desc). #[inline] fn to_power_of_2_digits_desc(&self, log_base: u64) -> Vec<$u> { to_power_of_2_digits_desc(self, log_base) } /// Converts an iterator of base-$2^k$ digits into a value. /// /// The base-2 logarithm of the base is specified. The input digits are in /// ascending order (least- to most-significant). `log_base` must be no larger /// than the width of the digit type. The function returns `None` if the input /// represents a number that can't fit in the output type. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{ki}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the digit type, or if /// `log_base` is zero. /// /// # Examples /// See [here](super::power_of_2_digits#from_power_of_2_digits_asc). #[inline] fn from_power_of_2_digits_asc>( log_base: u64, digits: I, ) -> Option<$t> { from_power_of_2_digits_asc(log_base, digits) } /// Converts an iterator of base-$2^k$ digits into a value. /// /// The base-2 logarithm of the base is specified. The input digits are in /// descending order (most- to least-significant). `log_base` must be no larger /// than the width of the digit type. The function returns `None` if the input /// represents a number that can't fit in the output type. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the digit type, or if /// `log_base` is zero. /// /// # Examples /// See [here](super::power_of_2_digits#from_power_of_2_digits_desc). fn from_power_of_2_digits_desc>( log_base: u64, digits: I, ) -> Option<$t> { from_power_of_2_digits_desc(log_base, digits) } } }; } apply_to_unsigneds!(impl_power_of_2_digits_inner); }; } apply_to_unsigneds!(impl_power_of_2_digits); ================================================ FILE: malachite-base/src/num/conversion/from.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ShrRoundAssign, UnsignedAbs}; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::mantissa_and_exponent::sci_mantissa_and_exponent_round; use crate::num::conversion::traits::{ ConvertibleFrom, OverflowingFrom, RoundingFrom, SaturatingFrom, SciMantissaAndExponent, WrappingFrom, }; use crate::num::float::NiceFloat; use crate::rounding_modes::RoundingMode::{self, *}; use core::cmp::Ordering::{self, *}; use core::ops::Neg; // This macro defines conversions from a type to itself. macro_rules! identity_conversion { ($t:ty) => { impl WrappingFrom<$t> for $t { /// Converts a value to its own type. This conversion is always valid and always leaves /// the value unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#wrapping_from). #[inline] fn wrapping_from(value: $t) -> $t { value } } impl SaturatingFrom<$t> for $t { /// Converts a value to its own type. This conversion is always valid and always leaves /// the value unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#saturating_from). #[inline] fn saturating_from(value: $t) -> $t { value } } impl OverflowingFrom<$t> for $t { /// Converts a value to its own type. Since this conversion is always valid and always /// leaves the value unchanged, the second component of the result is always false (no /// overflow). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#overflowing_from). #[inline] fn overflowing_from(value: $t) -> ($t, bool) { (value, false) } } impl ConvertibleFrom<$t> for $t { /// Checks whether a value is convertible to its own type. The result is always `true`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(_: $t) -> bool { true } } }; } // This macro defines conversions from type $a to type $b, where every value of type $a is // representable by a value of type $b. macro_rules! lossless_conversion { ($a:ty, $b:ident) => { impl WrappingFrom<$a> for $b { /// Converts a value to another type. This conversion is always valid and always leaves /// the value unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#wrapping_from). #[inline] fn wrapping_from(value: $a) -> $b { $b::from(value) } } impl SaturatingFrom<$a> for $b { /// Converts a value to another type. This conversion is always valid and always leaves /// the value unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#saturating_from). #[inline] fn saturating_from(value: $a) -> $b { $b::from(value) } } impl OverflowingFrom<$a> for $b { /// Converts a value to the value's type. Since this conversion is always valid and /// always leaves the value unchanged, the second component of the result is always /// false (no overflow). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#overflowing_from). #[inline] fn overflowing_from(value: $a) -> ($b, bool) { ($b::from(value), false) } } impl ConvertibleFrom<$a> for $b { /// Checks whether a value is convertible to a different type. The result is always /// `true`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(_: $a) -> bool { true } } }; } fn saturating_from_lossy + PrimitiveInt, B: PrimitiveInt + WrappingFrom>( value: A, ) -> B { if let Ok(b_max) = A::try_from(B::MAX) && value >= b_max { return B::MAX; } if let Ok(b_min) = A::try_from(B::MIN) && value <= b_min { return B::MIN; } B::wrapping_from(value) } fn overflowing_from_lossy, B: PrimitiveInt + WrappingFrom>( value: A, ) -> (B, bool) { let result = B::wrapping_from(value); ( result, (result >= B::ZERO) != (value >= A::ZERO) || A::wrapping_from(result) != value, ) } fn convertible_from_lossy, B: PrimitiveInt + WrappingFrom>( value: A, ) -> bool { let result = B::wrapping_from(value); (result >= B::ZERO) == (value >= A::ZERO) && A::wrapping_from(result) == value } // This macro defines conversions from type $a to type $b, where not every value of type $a is // representable by a value of type $b. macro_rules! lossy_conversion { ($a:ident, $b:ident) => { #[allow(clippy::cast_lossless)] impl WrappingFrom<$a> for $b { /// Converts a value to another type. If the value cannot be represented in the new /// type, it is wrapped. /// /// Let $W$ be the width of the target type. /// /// If the target type is unsigned, then $f_W(n) = m$, where $m < 2^W$ and $n + 2^W k = /// m$ for some $k \in \Z$. /// /// If the target type is signed, then $f_W(n) = m$, where $-2^{W-1} \leq m < 2^{W-1}$ /// and $n + 2^W k = m$ for some $k \in \Z$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#wrapping_from). #[inline] fn wrapping_from(value: $a) -> $b { value as $b } } impl SaturatingFrom<$a> for $b { /// Converts a value to another type. If the value cannot be represented in the new /// type, the maximum or minimum value of the new type, whichever is closer, is /// returned. /// /// Let $W$ be the width of the target type. /// /// If the target type is unsigned, then /// $$ /// f_W(n) = \\begin{cases} /// 0 & n < 0 \\\\ /// 2^W-1 & \text{if} \\quad n \geq 2^W, \\\\ /// n & \\text{otherwise}. /// \\end{cases} /// $$ /// /// If the target type is signed, then /// $$ /// f_W(n) = \\begin{cases} /// -2^{W-1} & \text{if} \\quad n < -2^{W-1}, \\\\ /// 2^{W-1}-1 & \text{if} \\quad n \geq 2^{W-1}, \\\\ /// n & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#saturating_from). #[inline] fn saturating_from(value: $a) -> $b { saturating_from_lossy(value) } } impl OverflowingFrom<$a> for $b { /// Converts a value to another type. If the value cannot be represented in the new /// type, it is wrapped. The second component of the result indicates whether overflow /// occurred. /// /// Let $W$ be the width of the target type. /// /// If the target type is unsigned, then $f_W(n) = (m, k \neq 0)$, where $m < 2^W$ and /// $n + 2^W k = m$ for some $k \in \Z$. /// /// If the target type is signed, then $f_W(n) = (m, k \neq 0)$, where $-2^{W-1} \leq m /// < 2^{W-1}$ and $n + 2^W k = m$ for some $k \in \Z$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#overflowing_from). #[inline] fn overflowing_from(value: $a) -> ($b, bool) { overflowing_from_lossy(value) } } impl ConvertibleFrom<$a> for $b { /// Determines whether a value is convertible to a different type. /// /// Let $W$ be the width of the target type. /// /// If the target type is unsigned then, /// $$ /// f_W(n) = (0 \leq n < 2^W). /// $$ /// /// If the target type is signed then, /// $$ /// f_W(n) = (-2^{W-1} \leq n < 2^{W-1}-1). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(value: $a) -> bool { convertible_from_lossy::<$a, $b>(value) } } }; } // This macro defines conversions from type $a to type $b, where the set of values representable by // type $a is a proper subset of the set of values representable by type $b. macro_rules! proper_subset_conversion { ($a:ident, $b:ident) => { lossless_conversion!($a, $b); lossy_conversion!($b, $a); }; } // This macro defines conversions from type $a to type $b, where the set of values representable by // type $a is neither a subset nor a superset of the set of values representable by type $b. macro_rules! no_containment_conversion { ($a:ident, $b:ident) => { lossy_conversion!($a, $b); lossy_conversion!($b, $a); }; } apply_to_primitive_ints!(identity_conversion); proper_subset_conversion!(u8, u16); proper_subset_conversion!(u8, u32); proper_subset_conversion!(u8, u64); proper_subset_conversion!(u8, u128); proper_subset_conversion!(u8, usize); proper_subset_conversion!(u8, i16); proper_subset_conversion!(u8, i32); proper_subset_conversion!(u8, i64); proper_subset_conversion!(u8, i128); proper_subset_conversion!(u8, isize); proper_subset_conversion!(u16, u32); proper_subset_conversion!(u16, u64); proper_subset_conversion!(u16, u128); proper_subset_conversion!(u16, usize); proper_subset_conversion!(u16, i32); proper_subset_conversion!(u16, i64); proper_subset_conversion!(u16, i128); proper_subset_conversion!(u32, u64); proper_subset_conversion!(u32, u128); proper_subset_conversion!(u32, i64); proper_subset_conversion!(u32, i128); proper_subset_conversion!(u64, u128); proper_subset_conversion!(u64, i128); proper_subset_conversion!(i8, i16); proper_subset_conversion!(i8, i32); proper_subset_conversion!(i8, i64); proper_subset_conversion!(i8, i128); proper_subset_conversion!(i8, isize); proper_subset_conversion!(i16, i32); proper_subset_conversion!(i16, i64); proper_subset_conversion!(i16, i128); proper_subset_conversion!(i16, isize); proper_subset_conversion!(i32, i64); proper_subset_conversion!(i32, i128); proper_subset_conversion!(i64, i128); no_containment_conversion!(u8, i8); no_containment_conversion!(u16, i8); no_containment_conversion!(u16, i16); no_containment_conversion!(u16, isize); no_containment_conversion!(u32, usize); no_containment_conversion!(u32, i8); no_containment_conversion!(u32, i16); no_containment_conversion!(u32, i32); no_containment_conversion!(u32, isize); no_containment_conversion!(u64, usize); no_containment_conversion!(u64, i8); no_containment_conversion!(u64, i16); no_containment_conversion!(u64, i32); no_containment_conversion!(u64, i64); no_containment_conversion!(u64, isize); no_containment_conversion!(u128, usize); no_containment_conversion!(u128, i8); no_containment_conversion!(u128, i16); no_containment_conversion!(u128, i32); no_containment_conversion!(u128, i64); no_containment_conversion!(u128, i128); no_containment_conversion!(u128, isize); no_containment_conversion!(usize, i8); no_containment_conversion!(usize, i16); no_containment_conversion!(usize, i32); no_containment_conversion!(usize, i64); no_containment_conversion!(usize, i128); no_containment_conversion!(usize, isize); no_containment_conversion!(i32, isize); no_containment_conversion!(i64, isize); no_containment_conversion!(i128, isize); fn primitive_float_rounding_from_unsigned( value: U, rm: RoundingMode, ) -> (T, Ordering) { if value == U::ZERO { return (T::ZERO, Equal); } let (mantissa, exponent, o) = sci_mantissa_and_exponent_round(value, rm).unwrap(); if let Some(f) = T::from_sci_mantissa_and_exponent(mantissa, i64::wrapping_from(exponent)) { (f, o) } else { match rm { Exact => { panic!("Value cannot be represented exactly as an {}", T::NAME) } Floor | Down | Nearest => (T::MAX_FINITE, Less), _ => (T::INFINITY, Greater), } } } fn unsigned_rounding_from_primitive_float( value: U, rm: RoundingMode, ) -> (T, Ordering) { assert!(!value.is_nan()); if value.is_infinite() { return if value.is_sign_positive() { match rm { Exact => { panic!("Value cannot be represented exactly as a {}", T::NAME) } Down | Floor | Nearest => (T::MAX, Less), _ => panic!("Cannot round away from positive infinity"), } } else { match rm { Exact => { panic!("Value cannot be represented exactly as a {}", T::NAME) } Down | Ceiling | Nearest => (T::ZERO, Greater), _ => panic!("Cannot round away from negative infinity"), } }; } if value == U::ZERO { return (T::ZERO, Equal); } if value.is_sign_negative() { return match rm { Exact => { panic!("Value cannot be represented exactly as a {}", T::NAME) } Ceiling | Down | Nearest => (T::ZERO, Greater), _ => panic!("Value is less than 0 and rounding mode is {rm}"), }; } let (mut mantissa, exponent) = value.integer_mantissa_and_exponent(); let (result, o) = if exponent <= 0 { let o = mantissa.shr_round_assign(-exponent, rm); (T::try_from(mantissa).ok(), o) } else { ( T::try_from(mantissa) .ok() .and_then(|n| n.arithmetic_checked_shl(exponent)), Equal, ) }; if let Some(n) = result { (n, o) } else { match rm { Exact => { panic!("Value cannot be represented exactly as a {}", T::NAME) } Floor | Down | Nearest => (T::MAX, Less), _ => panic!( "Value is greater than {}::MAX and rounding mode is {}", T::NAME, rm ), } } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PrimitiveFloatFromUnsignedError; fn primitive_float_try_from_unsigned( value: U, ) -> Result { if value == U::ZERO { return Ok(T::ZERO); } let (mantissa, exponent, _) = sci_mantissa_and_exponent_round(value, Exact).ok_or(PrimitiveFloatFromUnsignedError)?; T::from_sci_mantissa_and_exponent(mantissa, i64::wrapping_from(exponent)) .ok_or(PrimitiveFloatFromUnsignedError) } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum UnsignedFromFloatError { FloatInfiniteOrNan, FloatNegative, FloatNonIntegerOrOutOfRange, } fn unsigned_try_from_primitive_float( value: U, ) -> Result { if !value.is_finite() { Err(UnsignedFromFloatError::FloatInfiniteOrNan) } else if value == U::ZERO { Ok(T::ZERO) } else if value < U::ZERO { Err(UnsignedFromFloatError::FloatNegative) } else { let (mantissa, exponent) = value.integer_mantissa_and_exponent(); if exponent < 0 { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { T::try_from(mantissa) .or(Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)) .and_then(|n| { n.arithmetic_checked_shl(exponent) .ok_or(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) }) } } } fn primitive_float_convertible_from_unsigned< T: PrimitiveFloat, U: PrimitiveUnsigned + SciMantissaAndExponent, >( value: U, ) -> bool { if value == U::ZERO { return true; } let precision = (value >> value.trailing_zeros()).significant_bits(); precision <= T::MANTISSA_WIDTH + 1 && i64::wrapping_from(SciMantissaAndExponent::::sci_exponent(value)) <= T::MAX_EXPONENT } #[inline] fn unsigned_convertible_from_primitive_float( value: U, ) -> bool { value >= U::ZERO && value.is_integer() && (value == U::ZERO || value.sci_exponent() < i64::wrapping_from(T::WIDTH)) } macro_rules! impl_from_float_unsigned { ($u:ident) => { macro_rules! impl_from_float_unsigned_inner { ($f:ident) => { impl RoundingFrom<$u> for $f { /// Converts a value of an unsigned type to a value of a floating point type /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// - If the rounding mode is `Floor` or `Down`, the largest float less than or /// equal to the value is returned. /// - If the rounding mode is `Ceiling` or `Up`, the smallest float greater than /// or equal to the value is returned. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If /// the value is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. If the value is /// larger than the maximum finite float (which can only happen when /// converting a `u128` to an `f32`), the maximum finite float is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `value` is not exactly equal to any value of /// the primitive float type. /// /// # Examples /// See [here](super::from#rounding_from). #[inline] fn rounding_from(value: $u, rm: RoundingMode) -> ($f, Ordering) { primitive_float_rounding_from_unsigned(value, rm) } } impl RoundingFrom<$f> for $u { /// Converts a value of a floating point type to a value of an unsigned type /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// - If the rounding mode is `Floor`, the largest number less than or equal to /// the value is returned. If the float is greater than the maximum /// representable unsigned value, the maximum unsigned value is returned. If /// the float is negative, the function panics. /// - If the rounding mode is `Ceiling`, the smallest number greater than or /// equal to the value is returned. If the float is negative, zero is /// returned. If the float is greater than the maximum representable unsigned /// value, the function panics. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` /// if the float is non-negative and as with `Ceiling` if the value is /// negative. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` /// if the value is non-negative and as with `Floor` if the value is negative. /// - If the rounding mode is `Nearest`, then the nearest value is returned. If /// the value is exactly between two numbers, the even one is selected. If the /// float is greater than the maximum representable unsigned value, the /// maximum unsigned value is returned. If the float is negative, zero is /// returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `value` is `NaN`. /// - If `rm` is `Exact` but `value` is not exactly equal to any value of the /// unsigned type. /// - If `value` is greater than the maximum value of the unsigned type and `rm` /// is `Ceiling` or `Up`. /// - If `value` is negative and `rm` is `Floor` or `Up`. /// /// # Examples /// See [here](super::from#rounding_from). #[inline] fn rounding_from(value: $f, rm: RoundingMode) -> ($u, Ordering) { unsigned_rounding_from_primitive_float(value, rm) } } impl TryFrom<$u> for NiceFloat<$f> { type Error = PrimitiveFloatFromUnsignedError; /// Converts a value of an unsigned type to a value of a floating point type, /// returning an error if an exact conversion is not possible. /// /// The conversion succeeds if the unsigned value is not too large to represent /// (which can only happen when converting a [`u128`] to an [`f32`]) and the /// precision of the unsigned value is not too high. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#try_from). #[inline] fn try_from(value: $u) -> Result, Self::Error> { primitive_float_try_from_unsigned(value).map(NiceFloat) } } impl TryFrom> for $u { type Error = UnsignedFromFloatError; /// Converts a value of a floating point type to a value of an unsigned type, /// returning an error if an exact conversion is not possible. /// /// The conversion succeeds if the floating point value is an integer, not /// negative (negative zero is ok), and not too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#try_from). #[inline] fn try_from(value: NiceFloat<$f>) -> Result<$u, Self::Error> { unsigned_try_from_primitive_float(value.0) } } impl ConvertibleFrom<$u> for $f { /// Checks whether a value of an unsigned type is convertible to a floating /// point type. /// /// An exact conversion is possible if the unsigned value is not too large to /// represent (which can only happen when converting a [`u128`] to an [`f32`]) /// and the precision of the unsigned value is not too high. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(value: $u) -> bool { primitive_float_convertible_from_unsigned::<$f, $u>(value) } } impl ConvertibleFrom<$f> for $u { /// Checks whether a value of a floating point type is convertible to an /// unsigned type. /// /// An exact conversion is possible if the floating point value is an integer, /// not negative (negative zero is ok), and not too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(value: $f) -> bool { unsigned_convertible_from_primitive_float::<$u, $f>(value) } } }; } apply_to_primitive_floats!(impl_from_float_unsigned_inner); }; } apply_to_unsigneds!(impl_from_float_unsigned); #[inline] fn primitive_float_rounding_from_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, F: PrimitiveFloat + RoundingFrom, >( value: S, rm: RoundingMode, ) -> (F, Ordering) { let abs = value.unsigned_abs(); if value >= S::ZERO { F::rounding_from(abs, rm) } else { let (x, o) = F::rounding_from(abs, -rm); (-x, o.reverse()) } } fn signed_rounding_from_primitive_float< U: PrimitiveUnsigned + RoundingFrom, S: TryFrom + PrimitiveSigned + UnsignedAbs, F: PrimitiveFloat, >( value: F, rm: RoundingMode, ) -> (S, Ordering) { if value.is_infinite() { return if value.is_sign_positive() { match rm { Exact => { panic!("Value cannot be represented exactly as a {}", S::NAME) } Down | Floor | Nearest => (S::MAX, Less), _ => panic!("Cannot round away from extreme value"), } } else { match rm { Exact => { panic!("Value cannot be represented exactly as a {}", S::NAME) } Down | Nearest | Ceiling => (S::MIN, Greater), _ => panic!("Cannot round away from extreme value"), } }; } if value == F::ZERO { return (S::ZERO, Equal); } if value.is_sign_positive() { let (abs, o) = U::rounding_from(value, rm); if let Ok(n) = S::try_from(abs) { (n, o) } else { match rm { Exact => { panic!("Value cannot be represented exactly as an {}", S::NAME) } Floor | Down | Nearest => (S::MAX, Less), _ => panic!( "Value is greater than {}::MAX and rounding mode is {}", S::NAME, rm ), } } } else { let (abs, o) = U::rounding_from(-value, -rm); let n = if abs == S::MIN.unsigned_abs() { Some(S::MIN) } else { S::try_from(abs).ok().map(Neg::neg) }; if let Some(n) = n { (n, o.reverse()) } else { match rm { Exact => { panic!("Value cannot be represented exactly as an {}", S::NAME) } Ceiling | Down | Nearest => (S::MIN, Greater), _ => panic!( "Value is smaller than {}::MIN and rounding mode is {}", S::NAME, rm ), } } } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PrimitiveFloatFromSignedError; #[inline] fn primitive_float_try_from_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, F: PrimitiveFloat, >( value: S, ) -> Result where NiceFloat: TryFrom, { let abs = value.unsigned_abs(); if value >= S::ZERO { NiceFloat::::try_from(abs) .map(|f| f.0) .map_err(|_| PrimitiveFloatFromSignedError) } else { NiceFloat::::try_from(abs) .map(|f| -f.0) .map_err(|_| PrimitiveFloatFromSignedError) } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SignedFromFloatError { FloatInfiniteOrNan, FloatNonIntegerOrOutOfRange, } fn signed_try_from_primitive_float< U: TryFrom> + PrimitiveUnsigned, S: TryFrom + PrimitiveSigned + UnsignedAbs, F: PrimitiveFloat, >( value: F, ) -> Result { if !value.is_finite() { return Err(SignedFromFloatError::FloatInfiniteOrNan); } if value >= F::ZERO { S::try_from( U::try_from(NiceFloat(value)) .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))?, ) .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)) } else { let abs = U::try_from(NiceFloat(-value)) .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))?; if abs == S::MIN.unsigned_abs() { Ok(S::MIN) } else { S::try_from(abs) .map(Neg::neg) .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)) } } } #[inline] fn primitive_float_convertible_from_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, F: ConvertibleFrom + PrimitiveFloat, >( value: S, ) -> bool { F::convertible_from(value.unsigned_abs()) } fn signed_convertible_from_primitive_float( value: F, ) -> bool { if !value.is_integer() { return false; } if value >= F::ZERO { value == F::ZERO || value.sci_exponent() < i64::wrapping_from(U::WIDTH) - 1 } else { let exponent = value.sci_exponent(); let limit = i64::wrapping_from(U::WIDTH) - 1; value == F::ZERO || exponent < limit || exponent == limit && value == -F::from_sci_mantissa_and_exponent(F::ONE, exponent).unwrap() } } macro_rules! impl_from_float_signed { ($u:ident, $i:ident) => { macro_rules! impl_from_float_signed_inner { ($f:ident) => { impl RoundingFrom<$i> for $f { /// Converts a value of a signed type to a value of a floating point type /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// - If the rounding mode is `Floor`, the largest float less than or equal to /// the value is returned. /// - If the rounding mode is `Ceiling`, the smallest float greater than or /// equal to the value is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` /// if the value is non-negative and as with `Ceiling` if the value is /// negative. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` /// if the value is non-negative and as with `Floor` if the value is negative. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If /// the value is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `rm` is `Exact` but `value` is not exactly equal to any value of /// the primitive float type. /// /// # Examples /// See [here](super::from#rounding_from). #[inline] fn rounding_from(value: $i, rm: RoundingMode) -> ($f, Ordering) { primitive_float_rounding_from_signed::<$u, $i, $f>(value, rm) } } impl RoundingFrom<$f> for $i { /// Converts a value of a floating point type to a value of a signed type /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// - If the rounding mode is `Floor`, the largest number less than or equal to /// the value is returned. If the float is greater than the maximum /// representable signed value, the maximum signed value is returned. If the /// float is smaller than the minimum representable signed value, the function /// panics. /// - If the rounding mode is `Ceiling`, the smallest number greater than or /// equal to the value is returned. If the float is smaller than the minimum /// representable signed value, the minimum signed value is returned. If the /// float is greater than the maximum representable signed value, the function /// panics. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` /// if the float is non-negative and as with `Ceiling` if the value is /// negative. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` /// if the value is non-negative and as with `Floor` if the value is negative. /// - If the rounding mode is `Nearest`, then the nearest value is returned. If /// the value is exactly between two numbers, the even one is selected. If the /// float is greater than the maximum representable signed value, the maximum /// signed value is returned. If the float is smaller than the minimum /// representable signed value, the minimum signed value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// - If `value` is `NaN`. /// - If `rm` is `Exact` but `value` is not exactly equal to any value of the /// unsigned type. /// - If `value` is greater than the maximum value of the signed type and `rm` /// is `Ceiling` or `Up`. /// - If `value` is smaller than the minimum value of the signed type and `rm` /// is `Floor` or `Up`. /// /// # Examples /// See [here](super::from#rounding_from). #[inline] fn rounding_from(value: $f, rm: RoundingMode) -> ($i, Ordering) { signed_rounding_from_primitive_float::<$u, $i, $f>(value, rm) } } impl TryFrom<$i> for NiceFloat<$f> { type Error = PrimitiveFloatFromSignedError; /// Converts a value of a signed type to a value of a floating point type, /// returning an error if an exact conversion is not possible. /// /// The conversion succeeds if the precision of the signed value is not too /// high. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#try_from). #[inline] fn try_from(value: $i) -> Result, Self::Error> { primitive_float_try_from_signed(value).map(NiceFloat) } } impl TryFrom> for $i { type Error = SignedFromFloatError; /// Converts a value of a floating point type to a value of a signed type, /// returning an error if an exact conversion is not possible. /// /// The conversion succeeds if the floating point value is an integer and not /// too large or too small. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#try_from). #[inline] fn try_from(value: NiceFloat<$f>) -> Result<$i, Self::Error> { signed_try_from_primitive_float::<$u, $i, $f>(value.0) } } impl ConvertibleFrom<$i> for $f { /// Checks whether a value of a signed type is convertible to a floating point /// type. /// /// An exact conversion is possible if the precision of the signed value is not /// too high. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(value: $i) -> bool { primitive_float_convertible_from_signed::<$u, $i, $f>(value) } } impl ConvertibleFrom<$f> for $i { /// Checks whether a value of a floating point type is convertible to a signed /// type. /// /// An exact conversion is possible if the floating point value is an integer /// and not too large or too small. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from#convertible_from). #[inline] fn convertible_from(value: $f) -> bool { signed_convertible_from_primitive_float::<$u, $f>(value) } } }; } apply_to_primitive_floats!(impl_from_float_signed_inner); }; } apply_to_unsigned_signed_pairs!(impl_from_float_signed); ================================================ FILE: malachite-base/src/num/conversion/half.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf, WrappingFrom}; #[inline] fn join_halves + PrimitiveUnsigned, H: PrimitiveUnsigned>(upper: H, lower: H) -> T { (T::from(upper) << H::WIDTH) | T::from(lower) } #[inline] fn upper_half>(x: &T) -> H { H::wrapping_from(*x >> H::WIDTH) } macro_rules! impl_half_traits { ($t:ident, $ht: ident) => { impl HasHalf for $t { /// The primitive integer type whose width is half of `Self`'s. type Half = $ht; } impl JoinHalves for $t { /// Joins two unsigned integers to form an unsigned integer with twice the width. /// /// Let $W$ be the width of `Self` (the output type). /// /// $f(x, y) = 2^{W/2} x + y$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::half#join_halves). #[inline] fn join_halves(upper: Self::Half, lower: Self::Half) -> Self { join_halves(upper, lower) } } impl SplitInHalf for $t { /// Extracts the lower, or least significant, half of an unsigned integer. /// /// Let $W$ be the width of `Self` (the input type). /// /// $f(n) = m$, where $m < 2^{W/2}$ and $n + 2^{W/2} k = m$ for some $k \in \Z$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::half#lower_half). #[inline] fn lower_half(&self) -> Self::Half { $ht::wrapping_from(*self) } /// Extracts the upper, or most-significant, half of an unsigned integer. /// /// Let $W$ be the width of `Self` (the input type). /// /// $f(n) = \lfloor \frac{n}{2^{W/2}} \rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::half#upper_half). #[inline] fn upper_half(&self) -> Self::Half { upper_half(self) } } }; } impl_half_traits!(u16, u8); impl_half_traits!(u32, u16); impl_half_traits!(u64, u32); impl_half_traits!(u128, u64); #[inline] fn wide_lower_half(x: T) -> T { x.mod_power_of_2(T::WIDTH >> 1) } #[inline] pub(crate) fn wide_upper_half(x: T) -> T { x >> (T::WIDTH >> 1) } #[inline] pub(crate) fn wide_split_in_half(x: T) -> (T, T) { (wide_upper_half(x), wide_lower_half(x)) } #[inline] pub(crate) fn wide_join_halves(hi: T, lo: T) -> T { (hi << (T::WIDTH >> 1)) | lo } ================================================ FILE: malachite-base/src/num/conversion/is_integer.rs ================================================ // Copyright © 2026 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 crate::num::basic::floats::PrimitiveFloat; use crate::num::conversion::traits::{IsInteger, WrappingFrom}; use crate::num::logic::traits::TrailingZeros; fn is_integer_float(x: T) -> bool { if x.is_nan() || x.is_infinite() { false } else if x == T::ZERO { true } else { let (raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); raw_exponent != 0 && i64::wrapping_from( raw_exponent + if raw_mantissa == 0 { T::MANTISSA_WIDTH } else { TrailingZeros::trailing_zeros(raw_mantissa) }, ) > -T::MIN_EXPONENT } } macro_rules! impl_is_integer_primitive_int { ($t:ident) => { impl IsInteger for $t { /// Determines whether a value is an integer. /// /// For primitive integer types this always returns `true`. /// /// $f(x) = \textrm{true}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_integer#is_integer). #[inline] fn is_integer(self) -> bool { true } } }; } apply_to_primitive_ints!(impl_is_integer_primitive_int); macro_rules! impl_is_integer_primitive_float { ($t:ident) => { impl IsInteger for $t { /// Determines whether a value is an integer. /// /// $f(x) = (x \in \Z)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_integer#is_integer). #[inline] fn is_integer(self) -> bool { is_integer_float(self) } } }; } apply_to_primitive_floats!(impl_is_integer_primitive_float); ================================================ FILE: malachite-base/src/num/conversion/mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ ArithmeticCheckedShl, DivisibleByPowerOf2, ModPowerOf2, ShrRound, }; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ ExactFrom, IntegerMantissaAndExponent, RawMantissaAndExponent, SciMantissaAndExponent, WrappingFrom, }; use crate::num::logic::traits::{BitAccess, LeadingZeros, LowMask, SignificantBits, TrailingZeros}; use crate::rounding_modes::RoundingMode::{self, *}; use core::cmp::Ordering::{self, *}; fn raw_mantissa_and_exponent(x: T) -> (u64, u64) { let bits = x.to_bits(); ( bits.mod_power_of_2(T::MANTISSA_WIDTH), (bits >> T::MANTISSA_WIDTH).mod_power_of_2(T::EXPONENT_WIDTH), ) } #[inline] fn raw_mantissa(x: T) -> u64 { x.to_bits().mod_power_of_2(T::MANTISSA_WIDTH) } #[inline] fn raw_exponent(x: T) -> u64 { (x.to_bits() >> T::MANTISSA_WIDTH).mod_power_of_2(T::EXPONENT_WIDTH) } fn from_raw_mantissa_and_exponent(raw_mantissa: u64, raw_exponent: u64) -> T { assert!(raw_mantissa.significant_bits() <= T::MANTISSA_WIDTH); assert!(raw_exponent.significant_bits() <= T::EXPONENT_WIDTH); let x = T::from_bits((raw_exponent << T::MANTISSA_WIDTH) | raw_mantissa); // Only output the canonical NaN if x.is_nan() { T::NAN } else { x } } fn integer_mantissa_and_exponent_primitive_float(x: T) -> (u64, i64) { assert!(x.is_finite()); assert!(x != T::ZERO); let (mut raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); if raw_exponent == 0 { let trailing_zeros = raw_mantissa.trailing_zeros(); ( raw_mantissa >> trailing_zeros, i64::wrapping_from(trailing_zeros) + T::MIN_EXPONENT, ) } else { raw_mantissa.set_bit(T::MANTISSA_WIDTH); let trailing_zeros = TrailingZeros::trailing_zeros(raw_mantissa); ( raw_mantissa >> trailing_zeros, i64::wrapping_from(raw_exponent + trailing_zeros) + T::MIN_EXPONENT - 1, ) } } fn integer_mantissa_primitive_float(x: T) -> u64 { assert!(x.is_finite()); assert!(x != T::ZERO); let (mut raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); if raw_exponent != 0 { raw_mantissa.set_bit(T::MANTISSA_WIDTH); } raw_mantissa >> raw_mantissa.trailing_zeros() } fn integer_exponent_primitive_float(x: T) -> i64 { assert!(x.is_finite()); assert!(x != T::ZERO); let (raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); if raw_exponent == 0 { i64::wrapping_from(raw_mantissa.trailing_zeros()) + T::MIN_EXPONENT } else { i64::wrapping_from( raw_exponent + if raw_mantissa == 0 { T::MANTISSA_WIDTH } else { TrailingZeros::trailing_zeros(raw_mantissa) }, ) + T::MIN_EXPONENT - 1 } } fn from_integer_mantissa_and_exponent_primitive_float( integer_mantissa: u64, integer_exponent: i64, ) -> Option { if integer_mantissa == 0 { return Some(T::ZERO); } let trailing_zeros = integer_mantissa.trailing_zeros(); let (integer_mantissa, adjusted_exponent) = ( integer_mantissa >> trailing_zeros, integer_exponent + i64::wrapping_from(trailing_zeros), ); let mantissa_bits = integer_mantissa.significant_bits(); let sci_exponent = adjusted_exponent.checked_add(i64::exact_from(mantissa_bits))? - 1; let mut raw_mantissa; let raw_exponent; if sci_exponent < T::MIN_EXPONENT || sci_exponent > T::MAX_EXPONENT { return None; } else if sci_exponent < T::MIN_NORMAL_EXPONENT { if adjusted_exponent < T::MIN_EXPONENT { return None; } raw_exponent = 0; raw_mantissa = integer_mantissa << (adjusted_exponent - T::MIN_EXPONENT); } else if mantissa_bits > T::MANTISSA_WIDTH + 1 { return None; } else { raw_exponent = u64::exact_from(sci_exponent + i64::low_mask(T::EXPONENT_WIDTH - 1)); raw_mantissa = integer_mantissa << (T::MANTISSA_WIDTH + 1 - mantissa_bits); raw_mantissa.clear_bit(T::MANTISSA_WIDTH); } Some(T::from_raw_mantissa_and_exponent( raw_mantissa, raw_exponent, )) } fn sci_mantissa_and_exponent_primitive_float(x: T) -> (T, i64) { assert!(x.is_finite()); assert!(x != T::ZERO); let (raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); // Note that Self::MAX_EXPONENT is also the raw exponent of 1.0. if raw_exponent == 0 { let leading_zeros = LeadingZeros::leading_zeros(raw_mantissa) - (u64::WIDTH - T::MANTISSA_WIDTH); let mut mantissa = raw_mantissa << (leading_zeros + 1); mantissa.clear_bit(T::MANTISSA_WIDTH); ( T::from_raw_mantissa_and_exponent(mantissa, u64::wrapping_from(T::MAX_EXPONENT)), i64::wrapping_from(T::MANTISSA_WIDTH - leading_zeros - 1) + T::MIN_EXPONENT, ) } else { ( T::from_raw_mantissa_and_exponent(raw_mantissa, u64::wrapping_from(T::MAX_EXPONENT)), i64::wrapping_from(raw_exponent) - T::MAX_EXPONENT, ) } } fn sci_mantissa_primitive_float(x: T) -> T { assert!(x.is_finite()); assert!(x != T::ZERO); let (mut mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); // Note that Self::MAX_EXPONENT is also the raw exponent of 1.0. if raw_exponent == 0 { mantissa <<= LeadingZeros::leading_zeros(mantissa) - (u64::WIDTH - T::MANTISSA_WIDTH) + 1; mantissa.clear_bit(T::MANTISSA_WIDTH); } T::from_raw_mantissa_and_exponent(mantissa, u64::wrapping_from(T::MAX_EXPONENT)) } fn sci_exponent_primitive_float(x: T) -> i64 { assert!(x.is_finite()); assert!(x != T::ZERO); let (raw_mantissa, raw_exponent) = x.raw_mantissa_and_exponent(); // Note that Self::MAX_EXPONENT is also the raw exponent of 1.0. if raw_exponent == 0 { i64::wrapping_from(u64::WIDTH - LeadingZeros::leading_zeros(raw_mantissa) - 1) + T::MIN_EXPONENT } else { i64::wrapping_from(raw_exponent) - T::MAX_EXPONENT } } #[allow(clippy::wrong_self_convention)] fn from_sci_mantissa_and_exponent_primitive_float( sci_mantissa: T, sci_exponent: i64, ) -> Option { assert!(sci_mantissa.is_finite()); assert!(sci_mantissa > T::ZERO); if sci_exponent < T::MIN_EXPONENT || sci_exponent > T::MAX_EXPONENT { return None; } let (mut orig_mantissa, orig_exponent) = sci_mantissa.raw_mantissa_and_exponent(); // Note that Self::MAX_EXPONENT is also the raw exponent of 1.0. if orig_exponent != u64::wrapping_from(T::MAX_EXPONENT) { return None; } if sci_exponent < T::MIN_NORMAL_EXPONENT { let shift = T::MIN_NORMAL_EXPONENT - sci_exponent; if orig_mantissa.divisible_by_power_of_2(u64::wrapping_from(shift)) { orig_mantissa.set_bit(T::MANTISSA_WIDTH); Some(T::from_raw_mantissa_and_exponent(orig_mantissa >> shift, 0)) } else { None } } else { Some(T::from_raw_mantissa_and_exponent( orig_mantissa, u64::wrapping_from(sci_exponent + T::MAX_EXPONENT), )) } } /// Returns the scientific mantissa and exponent of an unsinged value. An [`Ordering`] is also /// returned, indicating whether the mantissa and exponent correspond to a value less than, equal /// to, or greater than the original value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is a /// rational number with $1 \leq m_s < 2$. We represent the rational mantissa as a float. The /// conversion might not be exact, so we round to the nearest float using the provided rounding /// mode. If the rounding mode is `Exact` but the conversion is not exact, `None` is returned. /// $$ /// f(x, r) \approx (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, \lfloor \log_2 x \rfloor). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; /// use malachite_base::num::conversion::mantissa_and_exponent::*; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use std::cmp::Ordering::{self, *}; /// /// fn test( /// n: T, /// rm: RoundingMode, /// out: Option<(U, u64, Ordering)>, /// ) { /// assert_eq!( /// sci_mantissa_and_exponent_round(n, rm).map(|(m, e, o)| (NiceFloat(m), e, o)), /// out.map(|(m, e, o)| (NiceFloat(m), e, o)) /// ); /// } /// test::(3, Down, Some((1.5, 1, Equal))); /// test::(3, Ceiling, Some((1.5, 1, Equal))); /// test::(3, Up, Some((1.5, 1, Equal))); /// test::(3, Nearest, Some((1.5, 1, Equal))); /// test::(3, Exact, Some((1.5, 1, Equal))); /// /// test::(123, Floor, Some((1.921875, 6, Equal))); /// test::(123, Down, Some((1.921875, 6, Equal))); /// test::(123, Ceiling, Some((1.921875, 6, Equal))); /// test::(123, Up, Some((1.921875, 6, Equal))); /// test::(123, Nearest, Some((1.921875, 6, Equal))); /// test::(123, Exact, Some((1.921875, 6, Equal))); /// /// test::(1000000000, Nearest, Some((1.8626451, 29, Equal))); /// test::(999999999, Nearest, Some((1.8626451, 29, Greater))); /// ``` pub fn sci_mantissa_and_exponent_round( x: T, rm: RoundingMode, ) -> Option<(U, u64, Ordering)> { assert_ne!(x, T::ZERO); let significant_bits = x.significant_bits(); let mut exponent = significant_bits - 1; let (mut raw_mantissa, o) = if significant_bits > U::MANTISSA_WIDTH { let shift = significant_bits - U::MANTISSA_WIDTH - 1; if rm == Exact && TrailingZeros::trailing_zeros(x) < shift { return None; } let (s, o) = x.shr_round(shift, rm); (s.wrapping_into(), o) } else { let x: u64 = x.wrapping_into(); (x << (U::MANTISSA_WIDTH - significant_bits + 1), Equal) }; if raw_mantissa.significant_bits() == U::MANTISSA_WIDTH + 2 { // Rounding up to a power of 2 raw_mantissa >>= 1; exponent += 1; } raw_mantissa.clear_bit(U::MANTISSA_WIDTH); // Note that Self::MAX_EXPONENT is also the raw exponent of 1.0. Some(( U::from_raw_mantissa_and_exponent(raw_mantissa, u64::wrapping_from(U::MAX_EXPONENT)), exponent, o, )) } /// Constructs a primitive integer from its scientific mantissa and exponent. An [`Ordering`] is /// also returned, indicating whether the returned value is less than, equal to, or greater than the /// exact value implied by the input. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is a /// rational number with $1 \leq m_s < 2$. Here, the rational mantissa is provided as a float. If /// the mantissa is outside the range $[1, 2)$, `None` is returned. /// /// Some combinations of mantissas and exponents do not specify an integer, in which case the /// resulting value is rounded to an integer using the specified rounding mode. If the rounding mode /// is `Exact` but the input does not exactly specify an integer, `None` is returned. /// /// $$ /// f(x, r) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `sci_mantissa` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; /// use malachite_base::num::conversion::mantissa_and_exponent::*; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use std::cmp::Ordering::{self, *}; /// /// fn test( /// mantissa: U, /// exponent: u64, /// rm: RoundingMode, /// out: Option<(T, Ordering)>, /// ) { /// assert_eq!( /// from_sci_mantissa_and_exponent_round::(mantissa, exponent, rm), /// out /// ); /// } /// test::(1.5, 1, Floor, Some((3, Equal))); /// test::(1.5, 1, Down, Some((3, Equal))); /// test::(1.5, 1, Ceiling, Some((3, Equal))); /// test::(1.5, 1, Up, Some((3, Equal))); /// test::(1.5, 1, Nearest, Some((3, Equal))); /// test::(1.5, 1, Exact, Some((3, Equal))); /// /// test::(1.51, 1, Floor, Some((3, Less))); /// test::(1.51, 1, Down, Some((3, Less))); /// test::(1.51, 1, Ceiling, Some((4, Greater))); /// test::(1.51, 1, Up, Some((4, Greater))); /// test::(1.51, 1, Nearest, Some((3, Less))); /// test::(1.51, 1, Exact, None); /// /// test::(2.0, 1, Floor, None); /// test::(10.0, 1, Floor, None); /// test::(0.5, 1, Floor, None); /// ``` pub fn from_sci_mantissa_and_exponent_round( sci_mantissa: U, sci_exponent: u64, rm: RoundingMode, ) -> Option<(T, Ordering)> { assert_ne!(sci_mantissa, U::ZERO); if sci_mantissa < U::ONE || sci_mantissa >= U::TWO { return None; } let mut raw_mantissa = sci_mantissa.raw_mantissa(); raw_mantissa.set_bit(U::MANTISSA_WIDTH); if sci_exponent >= U::MANTISSA_WIDTH { T::try_from(raw_mantissa) .ok()? .arithmetic_checked_shl(sci_exponent - U::MANTISSA_WIDTH) .map(|n| (n, Equal)) } else { let shift = U::MANTISSA_WIDTH - sci_exponent; if rm == Exact && TrailingZeros::trailing_zeros(raw_mantissa) < shift { return None; } let (s, o) = raw_mantissa.shr_round(shift, rm); T::try_from(s).ok().map(|s| (s, o)) } } macro_rules! impl_mantissa_and_exponent_unsigned { ($t:ident) => { impl IntegerMantissaAndExponent<$t, u64> for $t { /// Returns the integer mantissa and exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = (\frac{|x|}{2^{e_i}}, e_i), /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The inverse operation is /// [`from_integer_mantissa_and_exponent`](Self::from_integer_mantissa_and_exponent). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_mantissa_and_exponent). #[inline] fn integer_mantissa_and_exponent(self) -> ($t, u64) { assert_ne!(self, 0); let exponent = TrailingZeros::trailing_zeros(self); (self >> exponent, exponent) } /// Returns the integer mantissa. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = \frac{|x|}{2^{e_i}}, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_mantissa). #[inline] fn integer_mantissa(self) -> $t { assert_ne!(self, 0); self >> self.trailing_zeros() } /// Returns the integer exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = e_i, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_exponent). #[inline] fn integer_exponent(self) -> u64 { assert_ne!(self, 0); TrailingZeros::trailing_zeros(self) } /// Constructs an unsigned primitive integer from its integer mantissa and exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// /// $$ /// f(x) = 2^{e_i}m_i, /// $$ /// or `None` if the result cannot be exactly represented as an integer of the desired /// type (this happens if the exponent is too large). /// /// The input does not have to be reduced; that is to say, the mantissa does not have to /// be odd. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_integer_mantissa_and_exponent). #[inline] fn from_integer_mantissa_and_exponent( integer_mantissa: $t, integer_exponent: u64, ) -> Option<$t> { integer_mantissa.arithmetic_checked_shl(integer_exponent) } } }; } apply_to_unsigneds!(impl_mantissa_and_exponent_unsigned); macro_rules! impl_sci_mantissa_and_exponent_unsigned { ($u:ident) => { macro_rules! impl_sci_mantissa_and_exponent_unsigned_inner { ($f:ident) => { impl SciMantissaAndExponent<$f, u64> for $u { /// Returns the scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an /// integer and $m_s$ is a rational number with $1 \leq m_s < 2$. We represent /// the rational mantissa as a float. The conversion might not be exact, so we /// round to the nearest float using the `Nearest` rounding mode. To use other /// rounding modes, use [`sci_mantissa_and_exponent_round`]. /// /// If the result cannot be expressed as an integer of the specified type, /// `None` is returned. /// $$ /// f(x) \approx (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, /// \lfloor \log_2 x \rfloor). /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($f, u64) { let (m, e, _) = sci_mantissa_and_exponent_round(self, Nearest).unwrap(); (m, e) } /// Constructs a primitive integer from its scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an /// integer and $m_s$ is a rational number with $1 \leq m_s < 2$. Here, the /// rational mantissa is provided as a float. If the mantissa is outside the /// range $[1, 2)$, `None` is returned. /// /// Some combinations of mantissas and exponents do not specify an integer, in /// which case the resulting value is rounded to an integer using the `Nearest` /// rounding mode. To specify other rounding modes, use /// [`from_sci_mantissa_and_exponent_round`]. /// /// $$ /// f(x) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `sci_mantissa` is zero. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_sci_mantissa_and_exponent). #[inline] fn from_sci_mantissa_and_exponent( sci_mantissa: $f, sci_exponent: u64, ) -> Option<$u> { from_sci_mantissa_and_exponent_round(sci_mantissa, sci_exponent, Nearest) .map(|p| p.0) } } }; } apply_to_primitive_floats!(impl_sci_mantissa_and_exponent_unsigned_inner); }; } apply_to_unsigneds!(impl_sci_mantissa_and_exponent_unsigned); macro_rules! impl_mantissa_and_exponent_primitive_float { ($t:ident) => { impl RawMantissaAndExponent for $t { /// Returns the raw mantissa and exponent. /// /// The raw exponent and raw mantissa are the actual bit patterns used to represent the /// components of `self`. When `self` is nonzero and finite, the raw exponent $e_r$ is /// an integer in $[0, 2^E-2]$ and the raw mantissa $m_r$ is an integer in $[0, 2^M-1]$. /// /// When `self` is nonzero and finite, $f(x) = (m_r, e_r)$, where /// $$ /// m_r = \\begin{cases} /// 2^{M+2^{E-1}-2}|x| & \text{if} \\quad |x| < 2^{2-2^{E-1},} \\\\ /// 2^M \left ( \frac{|x|}{2^{\lfloor \log_2 |x| \rfloor}}-1\right ) & /// \textrm{otherwise}, /// \\end{cases} /// $$ /// and /// $$ /// e_r = \\begin{cases} /// 0 & \text{if} \\quad |x| < 2^{2-2^{E-1}} \\\\ /// \lfloor \log_2 |x| \rfloor + 2^{E-1} - 1 & \textrm{otherwise}. /// \\end{cases} /// $$ /// and $M$ and $E$ are the mantissa width and exponent width, respectively. /// /// For zeros, infinities, or `NaN`, refer to [IEEE /// 754](https://standards.ieee.org/ieee/754/6210/) or look at the examples below. /// /// The inverse operation is [`Self::from_raw_mantissa_and_exponent`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#raw_mantissa_and_exponent). #[inline] fn raw_mantissa_and_exponent(self) -> (u64, u64) { raw_mantissa_and_exponent(self) } /// Returns the raw mantissa. /// /// The raw mantissa is the actual bit pattern used to represent the mantissa of `self`. /// When `self` is nonzero and finite, it is an integer in $[0, 2^M-1]$. /// /// When `self` is nonzero and finite, /// $$ /// f(x) = \\begin{cases} /// 2^{M+2^{E-1}-2}|x| & \text{if} \\quad |x| < 2^{2-2^{E-1}}, \\\\ /// 2^M \left ( \frac{|x|}{2^{\lfloor \log_2 |x| \rfloor}}-1\right ) /// & \textrm{otherwise}, /// \\end{cases} /// $$ /// where $M$ and $E$ are the mantissa width and exponent width, respectively. /// /// For zeros, infinities, or `NaN`, refer to [IEEE /// 754](https://standards.ieee.org/ieee/754/6210/) or look at the examples below. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#raw_mantissa). #[inline] fn raw_mantissa(self) -> u64 { raw_mantissa(self) } /// Returns the raw exponent. /// /// The raw exponent is the actual bit pattern used to represent the exponent of `self`. /// When `self` is nonzero and finite, it is an integer in $[0, 2^E-2]$. /// /// When `self` is nonzero and finite, /// $$ /// f(x) = \\begin{cases} /// 0 & \text{if} \\quad |x| < 2^{2-2^{E-1}}, \\\\ /// \lfloor \log_2 |x| \rfloor + 2^{E-1} - 1 & \textrm{otherwise}, /// \\end{cases} /// $$ /// where $M$ and $E$ are the mantissa width and exponent width, respectively. /// /// For zeros, infinities, or `NaN`, refer to [IEEE /// 754](https://standards.ieee.org/ieee/754/6210/) or look at the examples below. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#raw_exponent). #[inline] fn raw_exponent(self) -> u64 { raw_exponent(self) } /// Constructs a float from its raw mantissa and exponent. /// /// The raw exponent and raw mantissa are the actual bit patterns used to represent the /// components of a float. When the float is nonzero and finite, the raw exponent $e_r$ /// is an integer in $[0, 2^E-2]$ and the raw mantissa $m_r$ is an integer in $[0, /// 2^M-1]$. /// /// When the exponent is not `2^E-1`, /// $$ /// f(m_r, e_r) = \\begin{cases} /// 2^{2-2^{E-1}-M}m_r & \text{if} \\quad e_r = 0, \\\\ /// 2^{e_r-2^{E-1}+1}(2^{-M}m_r+1) & \textrm{otherwise}, /// \\end{cases} /// $$ /// where $M$ and $E$ are the mantissa width and exponent width, respectively. /// /// For zeros, infinities, or `NaN`, refer to [IEEE /// 754](https://standards.ieee.org/ieee/754/6210/) or look at the examples below. /// /// This function only outputs a single, canonical, `NaN`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_raw_mantissa_and_exponent). #[inline] fn from_raw_mantissa_and_exponent(raw_mantissa: u64, raw_exponent: u64) -> $t { from_raw_mantissa_and_exponent(raw_mantissa, raw_exponent) } } impl IntegerMantissaAndExponent for $t { /// Returns the integer mantissa and exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_i}m_i$, where /// $e_i$ is an integer and $m_i$ is an odd integer. /// $$ /// f(x) = (\frac{|x|}{2^{e_i}}, e_i), /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The inverse operation is [`Self::from_integer_mantissa_and_exponent`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_mantissa_and_exponent). #[inline] fn integer_mantissa_and_exponent(self) -> (u64, i64) { integer_mantissa_and_exponent_primitive_float(self) } /// Returns the integer mantissa. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_i}m_i$, where /// $e_i$ is an integer and $m_i$ is an odd integer. /// $$ /// f(x) = \frac{|x|}{2^{e_i}}, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_mantissa). #[inline] fn integer_mantissa(self) -> u64 { integer_mantissa_primitive_float(self) } /// Returns the integer exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_i}m_i$, where /// $e_i$ is an integer and $m_i$ is an odd integer. /// $$ /// f(x) = e_i, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#integer_exponent). #[inline] fn integer_exponent(self) -> i64 { integer_exponent_primitive_float(self) } /// Constructs a float from its integer mantissa and exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_i}m_i$, where /// $e_i$ is an integer and $m_i$ is an odd integer. /// /// $$ /// f(x) = 2^{e_i}m_i, /// $$ /// or `None` if the result cannot be exactly represented as a float of the desired type /// (this happens if the exponent is too large or too small, or if the mantissa's /// precision is too high for the exponent). /// /// The input does not have to be reduced; that is to say, the mantissa does not have to /// be odd. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_integer_mantissa_and_exponent). #[inline] fn from_integer_mantissa_and_exponent( integer_mantissa: u64, integer_exponent: i64, ) -> Option<$t> { from_integer_mantissa_and_exponent_primitive_float( integer_mantissa, integer_exponent, ) } } impl SciMantissaAndExponent<$t, i64> for $t { /// Returns the scientific mantissa and exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_s}m_s$, where /// $e_s$ is an integer and $m_s$ is a rational number with $1 \leq m_s < 2$. If $x$ is /// a valid float, the scientific mantissa $m_s$ is always exactly representable as a /// float of the same type. We have /// $$ /// f(x) = (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, \lfloor \log_2 x \rfloor). /// $$ /// /// The inverse operation is `from_sci_mantissa_and_exponent`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($t, i64) { sci_mantissa_and_exponent_primitive_float(self) } /// Returns the scientific mantissa. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_s}m_s$, where /// $e_s$ is an integer and $m_s$ is a rational number with $1 \leq m_s < 2$. If $x$ is /// a valid float, the scientific mantissa $m_s$ is always exactly representable as a /// float of the same type. We have /// $$ /// f(x) = \frac{x}{2^{\lfloor \log_2 x \rfloor}}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa). #[inline] fn sci_mantissa(self) -> $t { sci_mantissa_primitive_float(self) } /// Returns the scientific exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_s}m_s$, where /// $e_s$ is an integer and $m_s$ is a rational number with $1 \leq m_s < 2$. We have /// $$ /// f(x) = \lfloor \log_2 x \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_exponent). #[inline] fn sci_exponent(self) -> i64 { sci_exponent_primitive_float(self) } /// Constructs a float from its scientific mantissa and exponent. /// /// When $x$ is positive, nonzero, and finite, we can write $x = 2^{e_s}m_s$, where /// $e_s$ is an integer and $m_s$ is a rational number with $1 \leq m_s < 2$. /// /// $$ /// f(x) = 2^{e_s}m_s, /// $$ /// or `None` if the result cannot be exactly represented as a float of the desired type /// (this happens if the exponent is too large or too small, if the mantissa is not in /// the range $[1, 2)$, or if the mantissa's precision is too high for the exponent). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `mantissa` is zero, infinite, or `NaN`. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_sci_mantissa_and_exponent). #[inline] fn from_sci_mantissa_and_exponent(sci_mantissa: $t, sci_exponent: i64) -> Option<$t> { from_sci_mantissa_and_exponent_primitive_float(sci_mantissa, sci_exponent) } } }; } apply_to_primitive_floats!(impl_mantissa_and_exponent_primitive_float); ================================================ FILE: malachite-base/src/num/conversion/mod.rs ================================================ // Copyright © 2026 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 . /// Traits for working with the digits of numbers. pub mod digits; /// Traits for converting between different number types. The traits are /// [`WrappingFrom`](traits::WrappingFrom), [`SaturatingFrom`](traits::SaturatingFrom), /// [`OverflowingFrom`](traits::OverflowingFrom), [`ConvertibleFrom`](traits::ConvertibleFrom), and /// [`RoundingFrom`](traits::RoundingFrom). /// /// # try_from /// ``` /// use malachite_base::num::conversion::from::{ /// PrimitiveFloatFromSignedError, PrimitiveFloatFromUnsignedError, SignedFromFloatError, /// UnsignedFromFloatError, /// }; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat::::try_from(100u8), Ok(NiceFloat(100.0))); /// assert_eq!( /// NiceFloat::::try_from(u32::MAX), /// Err(PrimitiveFloatFromUnsignedError) /// ); /// assert_eq!(NiceFloat::::try_from(100i8), Ok(NiceFloat(100.0))); /// assert_eq!( /// NiceFloat::::try_from(i32::MAX), /// Err(PrimitiveFloatFromSignedError) /// ); /// /// assert_eq!(u8::try_from(NiceFloat(100.0f32)), Ok(100)); /// assert_eq!( /// u8::try_from(NiceFloat(100.1f32)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(NiceFloat(300.0f32)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(NiceFloat(-100.0f32)), /// Err(UnsignedFromFloatError::FloatNegative) /// ); /// assert_eq!(i8::try_from(NiceFloat(-100.0f32)), Ok(-100)); /// assert_eq!( /// i8::try_from(NiceFloat(-200.0f32)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// ``` /// /// # wrapping_from /// ``` /// use malachite_base::num::conversion::traits::WrappingFrom; /// /// assert_eq!(u8::wrapping_from(123u8), 123); /// assert_eq!(i32::wrapping_from(-5i32), -5); /// /// assert_eq!(u16::wrapping_from(123u8), 123); /// assert_eq!(i64::wrapping_from(-5i32), -5); /// assert_eq!(u32::wrapping_from(5u64), 5); /// /// assert_eq!(u8::wrapping_from(1000u16), 232); /// assert_eq!(u32::wrapping_from(-5i32), 4294967291); /// assert_eq!(i32::wrapping_from(3000000000u32), -1294967296); /// assert_eq!(i8::wrapping_from(-1000i16), 24); /// ``` /// /// # saturating_from /// ``` /// use malachite_base::num::conversion::traits::SaturatingFrom; /// /// assert_eq!(u8::saturating_from(123u8), 123); /// assert_eq!(i32::saturating_from(-5i32), -5); /// /// assert_eq!(u16::saturating_from(123u8), 123); /// assert_eq!(i64::saturating_from(-5i32), -5); /// assert_eq!(u32::saturating_from(5u64), 5); /// /// assert_eq!(u8::saturating_from(1000u16), 255); /// assert_eq!(u32::saturating_from(-5i32), 0); /// assert_eq!(i32::saturating_from(3000000000u32), 2147483647); /// assert_eq!(i8::saturating_from(-1000i16), -128); /// ``` /// /// # overflowing_from /// ``` /// use malachite_base::num::conversion::traits::OverflowingFrom; /// /// assert_eq!(u8::overflowing_from(123u8), (123, false)); /// assert_eq!(i32::overflowing_from(-5i32), (-5, false)); /// /// assert_eq!(u16::overflowing_from(123u8), (123, false)); /// assert_eq!(i64::overflowing_from(-5i32), (-5, false)); /// assert_eq!(u32::overflowing_from(5u64), (5, false)); /// /// assert_eq!(u8::overflowing_from(1000u16), (232, true)); /// assert_eq!(u32::overflowing_from(-5i32), (4294967291, true)); /// assert_eq!(i32::overflowing_from(3000000000u32), (-1294967296, true)); /// assert_eq!(i8::overflowing_from(-1000i16), (24, true)); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// /// assert_eq!(u8::convertible_from(123u8), true); /// assert_eq!(i32::convertible_from(-5i32), true); /// /// assert_eq!(u16::convertible_from(123u8), true); /// assert_eq!(i64::convertible_from(-5i32), true); /// assert_eq!(u32::convertible_from(5u64), true); /// /// assert_eq!(u8::convertible_from(1000u16), false); /// assert_eq!(u32::convertible_from(-5i32), false); /// assert_eq!(i32::convertible_from(3000000000u32), false); /// assert_eq!(i8::convertible_from(-1000i16), false); /// /// assert_eq!(f32::convertible_from(100u8), true); /// assert_eq!(f32::convertible_from(u32::MAX), false); /// /// assert_eq!(u8::convertible_from(100.0f32), true); /// assert_eq!(u8::convertible_from(100.1f32), false); /// assert_eq!(u8::convertible_from(300.0f32), false); /// assert_eq!(u8::convertible_from(-100.0f32), false); /// ``` /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use std::cmp::Ordering::*; /// /// assert_eq!(f32::rounding_from(100, Floor), (100.0, Equal)); /// assert_eq!(f32::rounding_from(100, Down), (100.0, Equal)); /// assert_eq!(f32::rounding_from(100, Ceiling), (100.0, Equal)); /// assert_eq!(f32::rounding_from(100, Up), (100.0, Equal)); /// assert_eq!(f32::rounding_from(100, Nearest), (100.0, Equal)); /// assert_eq!(f32::rounding_from(100, Exact), (100.0, Equal)); /// /// assert_eq!(f32::rounding_from(i32::MAX, Floor), (2147483500.0, Less)); /// assert_eq!(f32::rounding_from(i32::MAX, Down), (2147483500.0, Less)); /// assert_eq!( /// f32::rounding_from(i32::MAX, Ceiling), /// (2147483600.0, Greater) /// ); /// assert_eq!(f32::rounding_from(i32::MAX, Up), (2147483600.0, Greater)); /// assert_eq!( /// f32::rounding_from(i32::MAX, Nearest), /// (2147483600.0, Greater) /// ); /// /// assert_eq!(u32::rounding_from(100.0f32, Floor), (100, Equal)); /// assert_eq!(u32::rounding_from(100.0f32, Down), (100, Equal)); /// assert_eq!(u32::rounding_from(100.0f32, Ceiling), (100, Equal)); /// assert_eq!(u32::rounding_from(100.0f32, Up), (100, Equal)); /// assert_eq!(u32::rounding_from(100.0f32, Nearest), (100, Equal)); /// assert_eq!(u32::rounding_from(100.0f32, Exact), (100, Equal)); /// /// assert_eq!(u32::rounding_from(100.5f32, Floor), (100, Less)); /// assert_eq!(u32::rounding_from(100.5f32, Down), (100, Less)); /// assert_eq!(u32::rounding_from(100.5f32, Ceiling), (101, Greater)); /// assert_eq!(u32::rounding_from(100.5f32, Up), (101, Greater)); /// assert_eq!(u32::rounding_from(100.5f32, Nearest), (100, Less)); /// ``` pub mod from; /// [`JoinHalves`](traits::JoinHalves) and [`SplitInHalf`](traits::SplitInHalf), traits for joining /// the bits of two numbers or for splitting a number in half. /// /// # join_halves /// ``` /// use malachite_base::num::conversion::traits::JoinHalves; /// /// assert_eq!(u16::join_halves(1, 2), 258); /// assert_eq!(u32::join_halves(0xabcd, 0x1234), 0xabcd1234); /// ``` /// /// # split_in_half /// ``` /// use malachite_base::num::conversion::traits::SplitInHalf; /// /// assert_eq!(258u16.split_in_half(), (1, 2)); /// assert_eq!(0xabcd1234u32.split_in_half(), (0xabcd, 0x1234)); /// ``` /// /// # lower_half /// ``` /// use malachite_base::num::conversion::traits::SplitInHalf; /// /// assert_eq!(258u16.lower_half(), 2); /// assert_eq!(0xabcd1234u32.lower_half(), 0x1234); /// ``` /// /// # upper_half /// ``` /// use malachite_base::num::conversion::traits::SplitInHalf; /// /// assert_eq!(258u16.upper_half(), 1); /// assert_eq!(0xabcd1234u32.upper_half(), 0xabcd); /// ``` pub mod half; /// [`IsInteger`](traits::IsInteger), a trait for determining whether a value is an integer. /// /// # is_integer /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::IsInteger; /// /// assert_eq!(0.is_integer(), true); /// assert_eq!(1.is_integer(), true); /// assert_eq!(100.is_integer(), true); /// assert_eq!((-1).is_integer(), true); /// assert_eq!((-100).is_integer(), true); /// /// assert_eq!(0.0.is_integer(), true); /// assert_eq!(1.0.is_integer(), true); /// assert_eq!(100.0.is_integer(), true); /// assert_eq!((-1.0).is_integer(), true); /// assert_eq!((-100.0).is_integer(), true); /// /// assert_eq!(0.1.is_integer(), false); /// assert_eq!(100.1.is_integer(), false); /// assert_eq!(f32::NAN.is_integer(), false); /// assert_eq!(f32::INFINITY.is_integer(), false); /// assert_eq!(f32::NEGATIVE_INFINITY.is_integer(), false); /// ``` pub mod is_integer; /// Traits for converting numbers to and from mantissa and exponent representations. /// /// See [`PrimitiveFloat`](super::basic::floats::PrimitiveFloat) for a description of the different /// types of mantissas and exponents. The traits are /// [`RawMantissaAndExponent`](traits::RawMantissaAndExponent), /// [`IntegerMantissaAndExponent`](traits::IntegerMantissaAndExponent), and /// [`SciMantissaAndExponent`](traits::SciMantissaAndExponent). /// /// # raw_mantissa_and_exponent /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// /// assert_eq!(0.0f32.raw_mantissa_and_exponent(), (0, 0)); /// assert_eq!((-0.0f32).raw_mantissa_and_exponent(), (0, 0)); /// assert_eq!(f32::NAN.raw_mantissa_and_exponent(), (0x400000, 255)); /// assert_eq!(f32::INFINITY.raw_mantissa_and_exponent(), (0, 255)); /// assert_eq!(f32::NEGATIVE_INFINITY.raw_mantissa_and_exponent(), (0, 255)); /// assert_eq!(1.0f32.raw_mantissa_and_exponent(), (0, 127)); /// assert_eq!( /// core::f32::consts::PI.raw_mantissa_and_exponent(), /// (4788187, 128) /// ); /// assert_eq!(0.1f32.raw_mantissa_and_exponent(), (5033165, 123)); /// ``` /// /// # raw_mantissa /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// /// assert_eq!(0.0f32.raw_mantissa(), 0); /// assert_eq!((-0.0f32).raw_mantissa(), 0); /// assert_eq!(f32::NAN.raw_mantissa(), 0x400000); /// assert_eq!(f32::INFINITY.raw_mantissa(), 0); /// assert_eq!(f32::NEGATIVE_INFINITY.raw_mantissa(), 0); /// assert_eq!(1.0f32.raw_mantissa(), 0); /// assert_eq!(core::f32::consts::PI.raw_mantissa(), 4788187); /// assert_eq!(0.1f32.raw_mantissa(), 5033165); /// ``` /// /// # raw_exponent /// /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// /// assert_eq!(0.0f32.raw_exponent(), 0); /// assert_eq!((-0.0f32).raw_exponent(), 0); /// assert_eq!(f32::NAN.raw_exponent(), 255); /// assert_eq!(f32::INFINITY.raw_exponent(), 255); /// assert_eq!(f32::NEGATIVE_INFINITY.raw_exponent(), 255); /// assert_eq!(1.0f32.raw_exponent(), 127); /// assert_eq!(core::f32::consts::PI.raw_exponent(), 128); /// assert_eq!(0.1f32.raw_exponent(), 123); /// ``` /// /// # from_raw_mantissa_and_exponent /// ``` /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(0, 0)), /// NiceFloat(0.0) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(0x400000, 255)), /// NiceFloat(f32::NAN) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(0, 255)), /// NiceFloat(f32::INFINITY) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(0, 127)), /// NiceFloat(1.0) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(4788187, 128)), /// NiceFloat(core::f32::consts::PI) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(5033165, 123)), /// NiceFloat(0.1) /// ); /// assert_eq!( /// NiceFloat(f32::from_raw_mantissa_and_exponent(2097152, 130)), /// NiceFloat(10.0) /// ); /// ``` /// /// # integer_mantissa_and_exponent /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// /// assert_eq!(1u8.integer_mantissa_and_exponent(), (1, 0)); /// assert_eq!(2u8.integer_mantissa_and_exponent(), (1, 1)); /// assert_eq!(3u8.integer_mantissa_and_exponent(), (3, 0)); /// assert_eq!(100u8.integer_mantissa_and_exponent(), (25, 2)); /// /// assert_eq!( /// core::f32::consts::PI.integer_mantissa_and_exponent(), /// (13176795, -22) /// ); /// assert_eq!(0.1f32.integer_mantissa_and_exponent(), (13421773, -27)); /// assert_eq!(10.0f32.integer_mantissa_and_exponent(), (5, 1)); /// assert_eq!( /// f32::MIN_POSITIVE_SUBNORMAL.integer_mantissa_and_exponent(), /// (1, -149) /// ); /// assert_eq!( /// f32::MAX_SUBNORMAL.integer_mantissa_and_exponent(), /// (0x7fffff, -149) /// ); /// assert_eq!( /// f32::MIN_POSITIVE_NORMAL.integer_mantissa_and_exponent(), /// (1, -126) /// ); /// assert_eq!( /// f32::MAX_FINITE.integer_mantissa_and_exponent(), /// (0xffffff, 104) /// ); /// ``` /// /// # integer_mantissa /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// /// assert_eq!(1u8.integer_mantissa(), 1); /// assert_eq!(2u8.integer_mantissa(), 1); /// assert_eq!(3u8.integer_mantissa(), 3); /// assert_eq!(100u8.integer_mantissa(), 25); /// /// assert_eq!(1.0f32.integer_mantissa(), 1); /// assert_eq!(core::f32::consts::PI.integer_mantissa(), 13176795); /// assert_eq!(0.1f32.integer_mantissa(), 13421773); /// assert_eq!(10.0f32.integer_mantissa(), 5); /// assert_eq!(f32::MIN_POSITIVE_SUBNORMAL.integer_mantissa(), 1); /// assert_eq!(f32::MAX_SUBNORMAL.integer_mantissa(), 0x7fffff); /// assert_eq!(f32::MIN_POSITIVE_NORMAL.integer_mantissa(), 1); /// assert_eq!(f32::MAX_FINITE.integer_mantissa(), 0xffffff); /// ``` /// /// # integer_exponent /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// /// assert_eq!(1u8.integer_exponent(), 0); /// assert_eq!(2u8.integer_exponent(), 1); /// assert_eq!(3u8.integer_exponent(), 0); /// assert_eq!(100u8.integer_exponent(), 2); /// /// assert_eq!(1.0f32.integer_exponent(), 0); /// assert_eq!(core::f32::consts::PI.integer_exponent(), -22); /// assert_eq!(0.1f32.integer_exponent(), -27); /// assert_eq!(10.0f32.integer_exponent(), 1); /// assert_eq!(f32::MIN_POSITIVE_SUBNORMAL.integer_exponent(), -149); /// assert_eq!(f32::MAX_SUBNORMAL.integer_exponent(), -149); /// assert_eq!(f32::MIN_POSITIVE_NORMAL.integer_exponent(), -126); /// assert_eq!(f32::MAX_FINITE.integer_exponent(), 104); /// ``` /// /// # from_integer_mantissa_and_exponent; /// ``` /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(u8::from_integer_mantissa_and_exponent(0, 1), Some(0)); /// assert_eq!(u8::from_integer_mantissa_and_exponent(1, 0), Some(1)); /// assert_eq!(u8::from_integer_mantissa_and_exponent(1, 1), Some(2)); /// assert_eq!(u8::from_integer_mantissa_and_exponent(3, 0), Some(3)); /// assert_eq!(u8::from_integer_mantissa_and_exponent(25, 2), Some(100)); /// /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(0, 5).map(NiceFloat), /// Some(NiceFloat(0.0)) /// ); /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(1, 0).map(NiceFloat), /// Some(NiceFloat(1.0)) /// ); /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(4, -2).map(NiceFloat), /// Some(NiceFloat(1.0)) /// ); /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(13176795, -22).map(NiceFloat), /// Some(NiceFloat(core::f32::consts::PI)) /// ); /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(13421773, -27).map(NiceFloat), /// Some(NiceFloat(0.1)) /// ); /// assert_eq!( /// f32::from_integer_mantissa_and_exponent(5, 1).map(NiceFloat), /// Some(NiceFloat(10.0)) /// ); /// /// assert_eq!(f32::from_integer_mantissa_and_exponent(5, 10000), None); /// assert_eq!(f32::from_integer_mantissa_and_exponent(5, -10000), None); /// // In the next 3 examples, the precision is too high. /// assert_eq!(f32::from_integer_mantissa_and_exponent(u64::MAX, -32), None); /// assert_eq!(f32::from_integer_mantissa_and_exponent(3, -150), None); /// assert_eq!(f32::from_integer_mantissa_and_exponent(1, 128), None); /// ``` /// /// # sci_mantissa_and_exponent /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// /// let test = |n: u32, mantissa: f32, exponent: u64| { /// let (m, e) = n.sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(mantissa)); /// assert_eq!(e, exponent); /// }; /// test(3, 1.5, 1); /// test(123, 1.921875, 6); /// test(1000000000, 1.8626451, 29); /// /// let test = |x: f32, mantissa: f32, exponent: i64| { /// let (actual_mantissa, actual_exponent) = x.sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); /// assert_eq!(actual_exponent, exponent); /// }; /// test(1.0, 1.0, 0); /// test(core::f32::consts::PI, 1.5707964, 1); /// test(0.1, 1.6, -4); /// test(10.0, 1.25, 3); /// test(f32::MIN_POSITIVE_SUBNORMAL, 1.0, -149); /// test(f32::MAX_SUBNORMAL, 1.9999998, -127); /// test(f32::MIN_POSITIVE_NORMAL, 1.0, -126); /// test(f32::MAX_FINITE, 1.9999999, 127); /// ``` /// /// # sci_mantissa /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat(1.0f32.sci_mantissa()), NiceFloat(1.0)); /// assert_eq!( /// NiceFloat(core::f32::consts::PI.sci_mantissa()), /// NiceFloat(1.5707964) /// ); /// assert_eq!(NiceFloat(0.1f32.sci_mantissa()), NiceFloat(1.6)); /// assert_eq!(NiceFloat(10.0f32.sci_mantissa()), NiceFloat(1.25)); /// assert_eq!( /// NiceFloat(f32::MIN_POSITIVE_SUBNORMAL.sci_mantissa()), /// NiceFloat(1.0) /// ); /// assert_eq!( /// NiceFloat(f32::MAX_SUBNORMAL.sci_mantissa()), /// NiceFloat(1.9999998) /// ); /// assert_eq!( /// NiceFloat(f32::MIN_POSITIVE_NORMAL.sci_mantissa()), /// NiceFloat(1.0) /// ); /// assert_eq!( /// NiceFloat(f32::MAX_FINITE.sci_mantissa()), /// NiceFloat(1.9999999) /// ); /// ``` /// /// # sci_exponent /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// /// assert_eq!(1.0f32.sci_exponent(), 0); /// assert_eq!(core::f32::consts::PI.sci_exponent(), 1); /// assert_eq!(0.1f32.sci_exponent(), -4); /// assert_eq!(10.0f32.sci_exponent(), 3); /// assert_eq!(f32::MIN_POSITIVE_SUBNORMAL.sci_exponent(), -149); /// assert_eq!(f32::MAX_SUBNORMAL.sci_exponent(), -127); /// assert_eq!(f32::MIN_POSITIVE_NORMAL.sci_exponent(), -126); /// assert_eq!(f32::MAX_FINITE.sci_exponent(), 127); /// ``` /// /// # from_sci_mantissa_and_exponent; /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(u32::from_sci_mantissa_and_exponent(1.5, 1u64), Some(3u32)); /// assert_eq!(u32::from_sci_mantissa_and_exponent(1.51, 1u64), Some(3u32)); /// assert_eq!( /// u32::from_sci_mantissa_and_exponent(1.921875, 6u64), /// Some(123u32) /// ); /// assert_eq!(u32::from_sci_mantissa_and_exponent(1.5, 1u64), Some(3u32)); /// /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.0, 0).map(NiceFloat), /// Some(NiceFloat(1.0)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.5707964, 1).map(NiceFloat), /// Some(NiceFloat(core::f32::consts::PI)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.6, -4).map(NiceFloat), /// Some(NiceFloat(0.1)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.25, 3).map(NiceFloat), /// Some(NiceFloat(10.0)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.0, -149).map(NiceFloat), /// Some(NiceFloat(f32::MIN_POSITIVE_SUBNORMAL)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.9999998, -127).map(NiceFloat), /// Some(NiceFloat(f32::MAX_SUBNORMAL)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.0, -126).map(NiceFloat), /// Some(NiceFloat(f32::MIN_POSITIVE_NORMAL)) /// ); /// assert_eq!( /// f32::from_sci_mantissa_and_exponent(1.9999999, 127).map(NiceFloat), /// Some(NiceFloat(f32::MAX_FINITE)) /// ); /// /// assert_eq!(f32::from_sci_mantissa_and_exponent(2.0, 1), None); /// assert_eq!(f32::from_sci_mantissa_and_exponent(1.1, -2000), None); /// assert_eq!(f32::from_sci_mantissa_and_exponent(1.1, 2000), None); /// assert_eq!(f32::from_sci_mantissa_and_exponent(1.999, -149), None); /// ``` pub mod mantissa_and_exponent; /// Traits for converting slices to numbers, slices to [`Vec`]s, or numbers to [`Vec`]s. The traits /// are [`FromOtherTypeSlice`](traits::FromOtherTypeSlice), /// [`VecFromOtherTypeSlice`](traits::VecFromOtherTypeSlice), and /// [`VecFromOtherType`](traits::VecFromOtherType). /// /// # from_other_type_slice /// ``` /// use malachite_base::num::conversion::traits::FromOtherTypeSlice; /// /// let xs: &[u32] = &[]; /// assert_eq!(u32::from_other_type_slice(xs), 0); /// assert_eq!(u32::from_other_type_slice(&[123u32, 456]), 123); /// /// assert_eq!(u8::from_other_type_slice(&[0xabcdu16, 0xef01]), 0xcd); /// /// assert_eq!(u16::from_other_type_slice(&[0xabu8, 0xcd, 0xef]), 0xcdab); /// assert_eq!(u64::from_other_type_slice(&[0xabu8, 0xcd, 0xef]), 0xefcdab); /// ``` /// /// # vec_from_other_type_slice /// ``` /// use malachite_base::num::conversion::traits::VecFromOtherTypeSlice; /// /// assert_eq!(u32::vec_from_other_type_slice(&[123u32, 456]), &[123, 456]); /// assert_eq!( /// u8::vec_from_other_type_slice(&[0xcdabu16, 0x01ef, 0x4523, 0x8967]), /// &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89] /// ); /// assert_eq!( /// u16::vec_from_other_type_slice(&[0xabu8, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67]), /// &[0xcdab, 0x01ef, 0x4523, 0x67] /// ); /// ``` /// /// # vec_from_other_type /// ``` /// use malachite_base::num::conversion::traits::VecFromOtherType; /// /// assert_eq!(u32::vec_from_other_type(123u32), &[123]); /// assert_eq!(u8::vec_from_other_type(0xcdabu16), &[0xab, 0xcd]); /// assert_eq!(u16::vec_from_other_type(0xabu8), &[0xab]); /// ``` pub mod slice; /// Traits for converting numbers to and from [`String`]s. pub mod string; /// Various traits for converting numbers. pub mod traits; ================================================ FILE: malachite-base/src/num/conversion/slice.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::ShrRound; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ FromOtherTypeSlice, SplitInHalf, VecFromOtherType, VecFromOtherTypeSlice, WrappingFrom, }; use crate::rounding_modes::RoundingMode::*; use alloc::vec; use alloc::vec::Vec; const fn from_other_type_slice_ident(xs: &[T]) -> T { if xs.is_empty() { T::ZERO } else { xs[0] } } macro_rules! impl_slice_traits_ident { ($a:ty) => { impl FromOtherTypeSlice<$a> for $a { /// Converts a slice of one type of value to a single value of the same type. /// /// $$ /// f((x_k)_{k=0}^{n-1}) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// x_0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The slice is interpreted as the base-$2^W$ digits of the value, in ascending order, /// where $W$ is the width of the type. If there's more than one element in the input /// slice, the value wraps and all elements past the first are ignored. This means that /// if the slice is empty, the output value is 0; otherwise, it's the first element of /// the slice. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#from_other_type_slice). #[inline] fn from_other_type_slice(xs: &[$a]) -> Self { from_other_type_slice_ident(xs) } } impl VecFromOtherTypeSlice<$a> for $a { /// Converts a slice of one type of value to a [`Vec`] of the same type. /// /// In this case, it just converts the slice to a [`Vec`] the usual way. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// See [here](super::slice#vec_from_other_type_slice). #[inline] fn vec_from_other_type_slice(xs: &[$a]) -> Vec { xs.to_vec() } } impl VecFromOtherType<$a> for $a { /// Converts a value of one type to a [`Vec`] of the same type. /// /// In this case, it just creates a one-element [`Vec`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#vec_from_other_type). #[inline] fn vec_from_other_type(x: $a) -> Vec { ::alloc::vec![x] } } }; } fn from_other_type_slice_large_to_small< A: PrimitiveUnsigned, B: PrimitiveUnsigned + WrappingFrom, >( xs: &[A], ) -> B { if xs.is_empty() { B::ZERO } else { B::wrapping_from(xs[0]) } } fn vec_from_other_type_slice_large_to_small< A: PrimitiveUnsigned, B: PrimitiveUnsigned + WrappingFrom, >( xs: &[A], ) -> Vec { let log_size_ratio = A::LOG_WIDTH - B::LOG_WIDTH; let mut out = ::alloc::vec![B::ZERO; xs.len() << log_size_ratio]; for (chunk, &u) in out.chunks_exact_mut(1 << log_size_ratio).zip(xs.iter()) { let mut u = u; for x in chunk { *x = B::wrapping_from(u); u >>= B::WIDTH; } } out } fn vec_from_other_type_large_to_small< A: PrimitiveUnsigned, B: PrimitiveUnsigned + WrappingFrom, >( mut x: A, ) -> Vec { let mut xs = ::alloc::vec![B::ZERO; 1 << (A::LOG_WIDTH - B::LOG_WIDTH)]; for out in &mut xs { *out = B::wrapping_from(x); x >>= B::WIDTH; } xs } macro_rules! impl_slice_traits_large_to_small { ($a:ident, $b:ident) => { impl FromOtherTypeSlice<$a> for $b { /// Converts a slice of one type of unsigned integer to a single value of a smaller /// unsigned type. /// /// $$ /// f((x_k)_{k=0}^{n-1}) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// y & \\text{otherwise}, /// \\end{cases} /// $$ /// where $0 \leq y < 2^W$, $x = y + k2^W$ for some integer $k$, and $W$ is the width of /// the output type. /// /// The slice is interpreted as the base-$2^W$ digits of the value, in ascending order, /// where $W$ is the width of the type. If the slice is empty, the output value is 0; /// otherwise, it consists of the least-significant bits of the first element of the /// slice. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#from_other_type_slice). #[inline] fn from_other_type_slice(xs: &[$a]) -> Self { from_other_type_slice_large_to_small(xs) } } impl VecFromOtherTypeSlice<$a> for $b { /// Converts a slice of one type of unsigned integer to a [`Vec`] of a smaller unsigned /// type. /// /// Each value of the input slice will be broken up into several values in the output /// [`Vec`]. /// /// Let $V$ be the the width of the input type and $W$ the width of the output type. /// /// $f((x_k)_ {k=0}^{n-1}) = (y_k)_ {k=0}^{m-1}$, where /// /// $$ /// \sum_{j=0}^{n-1}2^{jV}x_j = \sum_{j=0}^{m-1}2^{jW}y_j, /// $$ /// /// $y_j < 2^W$ for all $j$, and $m = 2^{V-W}n$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// See [here](super::slice#vec_from_other_type_slice). #[inline] fn vec_from_other_type_slice(xs: &[$a]) -> Vec { vec_from_other_type_slice_large_to_small(xs) } } impl VecFromOtherType<$a> for $b { /// Converts a value of one type of unsigned integer to a [`Vec`] of a smaller unsigned /// type. /// /// The input value will be broken up into several values in the output [`Vec`]. /// /// $f(x) = (y_k)_{k=0}^{m-1}$, where $x = \sum_{j=0}^{m-1}2^{jW}y_j$ and $m = /// 2^{V-W}n$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#vec_from_other_type). #[inline] fn vec_from_other_type(x: $a) -> Vec { vec_from_other_type_large_to_small(x) } } }; } fn from_other_type_slice_small_to_large< A: PrimitiveUnsigned, B: PrimitiveUnsigned + WrappingFrom, >( xs: &[A], ) -> B { let mut result = B::ZERO; let mut offset = 0; for &u in xs.iter().take(1 << (B::LOG_WIDTH - A::LOG_WIDTH)) { result |= B::wrapping_from(u) << offset; offset += A::WIDTH; } result } fn vec_from_other_type_slice_small_to_large< A: PrimitiveUnsigned, B: PrimitiveUnsigned + WrappingFrom, >( xs: &[A], ) -> Vec { let log_size_ratio = B::LOG_WIDTH - A::LOG_WIDTH; let mut out = ::alloc::vec![B::ZERO; xs.len().shr_round(log_size_ratio, Ceiling).0]; for (x, chunk) in out.iter_mut().zip(xs.chunks(1 << log_size_ratio)) { *x = from_other_type_slice_small_to_large(chunk); } out } fn vec_from_other_type_small_to_large>(x: A) -> Vec { ::alloc::vec![B::wrapping_from(x)] } macro_rules! impl_slice_traits_small_to_large { ($a:ident, $b:ident) => { impl FromOtherTypeSlice<$a> for $b { /// Converts a slice of one type of unsigned integer to a single value of a larger /// unsigned type. /// /// Let $V$ be the the width of the input type and $W$ the width of the output type. /// /// $f((x_k)_{k=0}^{n-1}) = y$, where $y < 2^W$ and /// /// $$ /// y = k2^W + \sum_{j=0}^{n-1}2^{jV}x_j /// $$ /// /// for some integer $k$. /// /// If the input slice contains more values than necessary to build an output value, the /// trailing values are ignored. If the input slice contains too few values to build an /// output value, the most-significant bits of the output value are set to 0. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#from_other_type_slice). #[inline] fn from_other_type_slice(xs: &[$a]) -> Self { from_other_type_slice_small_to_large(xs) } } impl VecFromOtherTypeSlice<$a> for $b { /// Converts a slice of one type of unsigned integer to a [`Vec`] of a larger unsigned /// type. /// /// Adjacent chunks of values in the input slice will be joined into values of the /// output [`Vec`]. If the last few elements of the input slice don't make up a full /// chunk, the most-significant bits of the last output value are set to 0. /// /// Let $V$ be the the width of the input type and $W$ the width of the output type. /// /// $f((x_k)_ {k=0}^{n-1}) = (y_k)_ {k=0}^{m-1}$, where /// /// $$ /// \sum_{j=0}^{n-1}2^{jV}x_j = \sum_{j=0}^{m-1}2^{jW}y_j, /// $$ /// /// $y_j < 2^W$ for all $j$, and $m = \lceil n / 2^{W-V} \rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// See [here](super::slice#vec_from_other_type_slice). #[inline] fn vec_from_other_type_slice(xs: &[$a]) -> Vec { vec_from_other_type_slice_small_to_large(xs) } } impl VecFromOtherType<$a> for $b { /// Converts a value of one type of unsigned integer to a [`Vec`] of a larger unsigned /// type. /// /// The output [`Vec`] only contains one value. The least-significant bits of the output /// value contain the input value, and the most-significant bits are set to 0. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::slice#vec_from_other_type). #[inline] fn vec_from_other_type(x: $a) -> Vec { vec_from_other_type_small_to_large(x) } } }; } apply_to_unsigneds!(impl_slice_traits_ident); impl_slice_traits_large_to_small!(u16, u8); impl_slice_traits_large_to_small!(u32, u8); impl_slice_traits_large_to_small!(u32, u16); impl_slice_traits_large_to_small!(u64, u8); impl_slice_traits_large_to_small!(u64, u16); impl_slice_traits_large_to_small!(u64, u32); impl_slice_traits_large_to_small!(u128, u8); impl_slice_traits_large_to_small!(u128, u16); impl_slice_traits_large_to_small!(u128, u32); impl_slice_traits_large_to_small!(u128, u64); impl_slice_traits_large_to_small!(u128, usize); impl_slice_traits_large_to_small!(usize, u8); impl_slice_traits_large_to_small!(usize, u16); impl_slice_traits_small_to_large!(u8, u16); impl_slice_traits_small_to_large!(u8, u32); impl_slice_traits_small_to_large!(u8, u64); impl_slice_traits_small_to_large!(u8, u128); impl_slice_traits_small_to_large!(u8, usize); impl_slice_traits_small_to_large!(u16, u32); impl_slice_traits_small_to_large!(u16, u64); impl_slice_traits_small_to_large!(u16, u128); impl_slice_traits_small_to_large!(u16, usize); impl_slice_traits_small_to_large!(u32, u64); impl_slice_traits_small_to_large!(u32, u128); impl_slice_traits_small_to_large!(u64, u128); impl_slice_traits_small_to_large!(usize, u128); impl FromOtherTypeSlice for usize { /// Converts a slice of `u32`s to a single `usize`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#from_other_type_slice). fn from_other_type_slice(xs: &[u32]) -> Self { if USIZE_IS_U32 { if xs.is_empty() { 0 } else { Self::wrapping_from(xs[0]) } } else { assert_eq!(Self::WIDTH, u64::WIDTH); let mut result = 0; let mut offset = 0; for &u in xs.iter().take(2) { result |= Self::wrapping_from(u) << offset; offset += u32::WIDTH; } result } } } impl VecFromOtherTypeSlice for usize { /// Converts a slice of [`u32`]s to a [`Vec`] of [`usize`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// See [here](super::slice#vec_from_other_type_slice). fn vec_from_other_type_slice(xs: &[u32]) -> Vec { let mut out; if USIZE_IS_U32 { out = vec![0; xs.len()]; for (x, &u) in out.iter_mut().zip(xs.iter()) { *x = Self::wrapping_from(u); } } else { assert_eq!(Self::WIDTH, u64::WIDTH); out = vec![0; xs.len().shr_round(1, Ceiling).0]; for (x, chunk) in out.iter_mut().zip(xs.chunks(2)) { *x = Self::from_other_type_slice(chunk); } } out } } impl VecFromOtherType for usize { /// Converts a [`u32`] to a [`Vec`] of [`usize`]s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#vec_from_other_type). #[inline] fn vec_from_other_type(x: u32) -> Vec { vec![Self::wrapping_from(x)] } } impl FromOtherTypeSlice for usize { /// Converts a slice of [`u64`]s to a single [`usize`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#from_other_type_slice). #[inline] fn from_other_type_slice(xs: &[u64]) -> Self { if xs.is_empty() { 0 } else { Self::wrapping_from(xs[0]) } } } impl VecFromOtherTypeSlice for usize { /// Converts a slice of [`u64`]s to a [`Vec`] of [`usize`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// See [here](super::slice#vec_from_other_type_slice). #[allow(arithmetic_overflow)] fn vec_from_other_type_slice(xs: &[u64]) -> Vec { let mut out; if USIZE_IS_U32 { out = ::alloc::vec![0; xs.len() << 1]; for (chunk, &u) in out.chunks_exact_mut(2).zip(xs.iter()) { let mut u = u; for x in chunk { *x = Self::wrapping_from(u); u >>= Self::WIDTH; } } } else { assert_eq!(Self::WIDTH, u64::WIDTH); out = ::alloc::vec![0; xs.len()]; for (x, &u) in out.iter_mut().zip(xs.iter()) { *x = Self::wrapping_from(u); } } out } } impl VecFromOtherType for usize { /// Converts a [`u64`] to a [`Vec`] of [`usize`]s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#vec_from_other_type). fn vec_from_other_type(x: u64) -> Vec { if USIZE_IS_U32 { let (upper, lower) = x.split_in_half(); ::alloc::vec![Self::wrapping_from(lower), Self::wrapping_from(upper)] } else { assert_eq!(Self::WIDTH, u64::WIDTH); ::alloc::vec![Self::wrapping_from(x)] } } } impl FromOtherTypeSlice for u32 { /// Converts a slice of [`usize`]s to a single [`u32`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#from_other_type_slice). #[inline] fn from_other_type_slice(xs: &[usize]) -> Self { if xs.is_empty() { 0 } else { Self::wrapping_from(xs[0]) } } } impl VecFromOtherTypeSlice for u32 { /// Converts a slice of [`usize`]s to a [`Vec`] of [`u32`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// See [here](super::slice#vec_from_other_type_slice). #[allow(arithmetic_overflow)] fn vec_from_other_type_slice(xs: &[usize]) -> Vec { let mut out; if USIZE_IS_U32 { out = ::alloc::vec![0; xs.len()]; for (x, &u) in out.iter_mut().zip(xs.iter()) { *x = Self::wrapping_from(u); } } else { assert_eq!(usize::WIDTH, u64::WIDTH); out = ::alloc::vec![0; xs.len() << 1]; for (chunk, &u) in out.chunks_exact_mut(2).zip(xs.iter()) { let mut u = u; for x in chunk { *x = Self::wrapping_from(u); u >>= Self::WIDTH; } } } out } } impl VecFromOtherType for u32 { /// Converts a [`usize`] to a [`Vec`] of [`u32`]s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#vec_from_other_type). #[allow(arithmetic_overflow)] fn vec_from_other_type(x: usize) -> Vec { if USIZE_IS_U32 { ::alloc::vec![Self::wrapping_from(x)] } else { assert_eq!(usize::WIDTH, u64::WIDTH); let (upper, lower) = u64::wrapping_from(x).split_in_half(); ::alloc::vec![lower, upper] } } } impl FromOtherTypeSlice for u64 { /// Converts a slice of [`usize`]s to a single [`u64`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#from_other_type_slice). fn from_other_type_slice(xs: &[usize]) -> Self { if USIZE_IS_U32 { let mut result = 0; let mut offset = 0; for &u in xs.iter().take(2) { result |= Self::wrapping_from(u) << offset; offset += usize::WIDTH; } result } else { assert_eq!(usize::WIDTH, Self::WIDTH); if xs.is_empty() { 0 } else { Self::wrapping_from(xs[0]) } } } } impl VecFromOtherTypeSlice for u64 { /// Converts a slice of [`usize`]s to a [`Vec`] of [`u64`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// See [here](super::slice#vec_from_other_type_slice). fn vec_from_other_type_slice(xs: &[usize]) -> Vec { let mut out; if USIZE_IS_U32 { out = ::alloc::vec![0; xs.len().shr_round(1, Ceiling).0]; for (x, chunk) in out.iter_mut().zip(xs.chunks(2)) { *x = Self::from_other_type_slice(chunk); } } else { assert_eq!(usize::WIDTH, Self::WIDTH); out = ::alloc::vec![0; xs.len()]; for (x, &u) in out.iter_mut().zip(xs.iter()) { *x = Self::wrapping_from(u); } } out } } impl VecFromOtherType for u64 { /// Converts a [`usize`] to a [`Vec`] of [`u64`]s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::slice#vec_from_other_type). #[inline] fn vec_from_other_type(x: usize) -> Vec { ::alloc::vec![Self::wrapping_from(x)] } } ================================================ FILE: malachite-base/src/num/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Parity; use crate::num::basic::integers::PrimitiveInt; use crate::num::conversion::string::from_string::digit_from_display_byte; use crate::num::conversion::string::options::FromSciStringOptions; use crate::num::conversion::traits::FromSciString; use crate::rounding_modes::RoundingMode::*; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use core::str::FromStr; #[doc(hidden)] pub fn parse_exponent(s: &[u8]) -> Option { i64::from_str(core::str::from_utf8(s).ok()?).ok() } #[doc(hidden)] pub fn validate_helper(s: &[u8], base: u8) -> Option<()> { for &c in s { if digit_from_display_byte(c)? >= base { return None; } } Some(()) } #[doc(hidden)] pub fn is_zero_helper(s: &[u8], base: u8) -> Option { let mut all_zeros = true; for &c in s { let d = digit_from_display_byte(c)?; if d >= base { return None; } if d != 0 { all_zeros = false; } } Some(all_zeros) } #[doc(hidden)] pub fn cmp_half_helper(s: &[u8], base: u8) -> Option { if s.is_empty() { return Some(Less); } let h = base >> 1; let mut done = false; let mut result; if base.even() { // 1/2 is 0.h result = Equal; let mut first = true; for &c in s { let d = digit_from_display_byte(c)?; if d >= base { return None; } if done { continue; } if first { let half_c = d.cmp(&h); if half_c != Equal { result = half_c; done = true; } first = false; } else if d != 0 { result = Greater; done = true; } } } else { // 1/2 is 0.hhh... result = Less; for &c in s { let d = digit_from_display_byte(c)?; if done { continue; } let half_c = d.cmp(&h); if half_c != Equal { result = half_c; done = true; } } } Some(result) } fn parse_int(cs: &[u8], base: u8) -> Option { // if T is unsigned, from_string_base won't handle -0 let mut test_neg_zero = false; if T::MIN == T::ZERO && let Some(&b'-') = cs.first() { test_neg_zero = true; } if test_neg_zero { if cs.len() == 1 { return None; } for &c in &cs[1..] { if c != b'0' { return None; } } Some(T::ZERO) } else { T::from_string_base(base, core::str::from_utf8(cs).ok()?) } } fn up_1(x: T, neg: bool) -> Option { if neg { x.checked_sub(T::ONE) } else { x.checked_add(T::ONE) } } #[doc(hidden)] pub fn preprocess_sci_string(s: &str, options: FromSciStringOptions) -> Option<(Vec, i64)> { let mut s = s.as_bytes().to_vec(); let mut exponent = 0; if options.base < 15 { for (i, &c) in s.iter().enumerate().rev() { if c == b'e' || c == b'E' { if i == 0 || i == s.len() - 1 { return None; } exponent = parse_exponent(&s[i + 1..])?; s.truncate(i); break; } } } else { for (i, &c) in s.iter().enumerate().rev() { if c == b'+' || c == b'-' { if i == 0 { break; } if i == 1 || i == s.len() - 1 { return None; } let exp_indicator = s[i - 1]; if exp_indicator != b'e' && exp_indicator != b'E' { return None; } exponent = parse_exponent(&s[i..])?; s.truncate(i - 1); break; } } } let mut point_index = None; for (i, &c) in s.iter().enumerate() { if c == b'.' { point_index = Some(i); break; } } if let Some(point_index) = point_index { let len = s.len(); if point_index != len - 1 { let next_char = s[point_index + 1]; if next_char == b'+' || next_char == b'-' { return None; } exponent = exponent.checked_sub(i64::try_from(len - point_index - 1).ok()?)?; s.copy_within(point_index + 1..len, point_index); } s.pop(); } Some((s, exponent)) } fn from_sci_string_with_options_primitive_int( s: &str, options: FromSciStringOptions, ) -> Option { let (s, exponent) = preprocess_sci_string(s, options)?; if exponent >= 0 { let x = parse_int::(&s, options.base)?; x.checked_mul(T::wrapping_from(options.base).checked_pow(exponent.unsigned_abs())?) } else { let neg_exponent = usize::try_from(exponent.unsigned_abs()).ok()?; let len = s.len(); if len == 0 { return None; } let first = s[0]; let neg = first == b'-'; let sign = neg || first == b'+'; let rm = if neg { -options.rounding_mode } else { options.rounding_mode }; let sig_len = if sign { len - 1 } else { len }; if sig_len == 0 { return None; } if neg_exponent > sig_len { let s = if sign { &s[1..] } else { &s[..] }; return match rm { Down | Floor | Nearest => { validate_helper(s, options.base)?; Some(T::ZERO) } Up | Ceiling => { if is_zero_helper(s, options.base)? { Some(T::ZERO) } else { up_1(T::ZERO, neg) } } Exact => None, }; } let (before_e, after_e) = s.split_at(len - neg_exponent); let x = match before_e { &[] | &[b'-'] | &[b'+'] => T::ZERO, before_e => parse_int(before_e, options.base)?, }; if after_e.is_empty() { return Some(x); } match rm { Down | Floor => { validate_helper(after_e, options.base)?; Some(x) } Up | Ceiling => { if is_zero_helper(after_e, options.base)? { Some(x) } else { up_1(x, neg) } } Exact => { if is_zero_helper(after_e, options.base)? { Some(x) } else { None } } Nearest => match cmp_half_helper(after_e, options.base)? { Less => Some(x), Greater => up_1(x, neg), Equal => { if x.even() { Some(x) } else { up_1(x, neg) } } }, } } } macro_rules! impl_from_sci_string { ($t:ident) => { impl FromSciString for $t { /// Converts a [`String`], possibly in scientfic notation, to a primitive integer. /// /// Use [`FromSciStringOptions`] to specify the base (from 2 to 36, inclusive) and the /// rounding mode, in case rounding is necessary because the string represents a /// non-integer. /// /// If the base is greater than 10, the higher digits are represented by the letters /// `'a'` through `'z'` or `'A'` through `'Z'`; the case doesn't matter and doesn't need /// to be consistent. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. If the /// base is 15 or greater, an ambiguity arises where it may not be clear whether `'e'` /// is a digit or an exponent indicator. To resolve this ambiguity, always use a `'+'` /// or `'-'` sign after the exponent indicator when the base is 15 or greater. /// /// The exponent itself is always parsed using base 10. /// /// Decimal (or other-base) points are allowed. These are most useful in conjunction /// with exponents, but they may be used on their own. If the string represents a /// non-integer, the rounding mode specified in `options` is used to round to an /// integer. /// /// If the string is unparseable or parses to an out-of-range integer, `None` is /// returned. `None` is also returned if the rounding mode in options is `Exact`, but /// rounding is necessary. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// See [here](super::from_sci_string). #[inline] fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option<$t> { from_sci_string_with_options_primitive_int(s, options) } } }; } apply_to_primitive_ints!(impl_from_sci_string); ================================================ FILE: malachite-base/src/num/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::num::conversion::traits::FromStringBase; /// Produces a digit from a byte corresponding to a numeric or alphabetic (lower- or uppercase) /// [`char`] that represents the digit. /// /// Bytes corresponding to `char`s from '0' to '9' become digits 0 to 9. Bytes corresponding to /// `char`s from 'a' to 'z' become digits 10 to 35. Bytes corresponding to `char`s from 'A' to 'Z' /// also become digits 10 to 35. Passing a byte that does not correspond to any of these `char`s /// yields `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::from_string::digit_from_display_byte; /// /// assert_eq!(digit_from_display_byte(b'0'), Some(0)); /// assert_eq!(digit_from_display_byte(b'9'), Some(9)); /// assert_eq!(digit_from_display_byte(b'a'), Some(10)); /// assert_eq!(digit_from_display_byte(b'z'), Some(35)); /// assert_eq!(digit_from_display_byte(b'A'), Some(10)); /// assert_eq!(digit_from_display_byte(b'Z'), Some(35)); /// assert_eq!(digit_from_display_byte(b' '), None); /// assert_eq!(digit_from_display_byte(b'!'), None); /// ``` pub const fn digit_from_display_byte(b: u8) -> Option { match b { b'0'..=b'9' => Some(b - b'0'), b'a'..=b'z' => Some(b - b'a' + 10), b'A'..=b'Z' => Some(b - b'A' + 10), _ => None, } } macro_rules! impl_from_string_base { ($t:ident) => { impl FromStringBase for $t { /// This is a wrapper over the `from_str_radix` functions in the standard library, for /// example [this one](u32::from_str_radix). #[inline] fn from_string_base(base: u8, s: &str) -> Option { $t::from_str_radix(s, u32::from(base)).ok() } } }; } apply_to_primitive_ints!(impl_from_string_base); ================================================ FILE: malachite-base/src/num/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . /// [`FromSciString`](super::traits::FromSciString), a trait for converting strings, possibly using /// scientific notation, to numbers. /// /// # from_sci_string /// ``` /// use malachite_base::num::conversion::traits::FromSciString; /// /// assert_eq!(u8::from_sci_string("123"), Some(123)); /// assert_eq!(u8::from_sci_string("123.5"), Some(124)); /// assert_eq!(u8::from_sci_string("256"), None); /// assert_eq!(u64::from_sci_string("1.23e10"), Some(12300000000)); /// ``` /// /// # from_sci_string_with_options /// ``` /// use malachite_base::num::conversion::string::options::FromSciStringOptions; /// use malachite_base::num::conversion::traits::FromSciString; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// let mut options = FromSciStringOptions::default(); /// assert_eq!( /// u8::from_sci_string_with_options("123.5", options), /// Some(124) /// ); /// /// options.set_rounding_mode(Floor); /// assert_eq!( /// u8::from_sci_string_with_options("123.5", options), /// Some(123) /// ); /// /// options = FromSciStringOptions::default(); /// options.set_base(16); /// assert_eq!(u8::from_sci_string_with_options("ff", options), Some(255)); /// ``` pub mod from_sci_string; /// [`FromStringBase`](super::traits::FromStringBase), a trait for converting strings in a specified /// base to numbers. pub mod from_string; /// [`ToSciOptions`](options::ToSciOptions) and /// [`FromSciSringOptions`](options::FromSciStringOptions), `struct`s for specifying parameters when /// using the [`FromSciString`](super::traits::FromSciString) and [`ToSci`](super::traits::ToSci) /// traits. pub mod options; /// [`ToSci`](super::traits::ToSci), a trait for converting a number to string, possibly using /// scientific notation. /// /// # to_sci /// ``` /// use malachite_base::num::conversion::traits::ToSci; /// /// // If the value can fit in a `u32`, the result is the same as with `to_string` /// assert_eq!(123u8.to_sci().to_string(), "123"); /// /// assert_eq!(u128::MAX.to_sci().to_string(), "3.402823669209385e38"); /// assert_eq!(i128::MIN.to_sci().to_string(), "-1.701411834604692e38"); /// ``` /// /// # to_sci_with_options /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// let mut options = ToSciOptions::default(); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "123456"); /// /// options.set_precision(3); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "1.23e5"); /// /// options.set_rounding_mode(Ceiling); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "1.24e5"); /// /// options.set_e_uppercase(); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "1.24E5"); /// /// options.set_force_exponent_plus_sign(true); /// assert_eq!( /// 123456u32.to_sci_with_options(options).to_string(), /// "1.24E+5" /// ); /// /// options = ToSciOptions::default(); /// options.set_base(36); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "2n9c"); /// /// options.set_uppercase(); /// assert_eq!(123456u32.to_sci_with_options(options).to_string(), "2N9C"); /// /// options.set_base(2); /// options.set_precision(10); /// assert_eq!( /// 123456u32.to_sci_with_options(options).to_string(), /// "1.1110001e16" /// ); /// /// options.set_include_trailing_zeros(true); /// assert_eq!( /// 123456u32.to_sci_with_options(options).to_string(), /// "1.111000100e16" /// ); /// ``` /// /// # fmt_sci_valid /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// let mut options = ToSciOptions::default(); /// assert!(123u8.fmt_sci_valid(options)); /// assert!(u128::MAX.fmt_sci_valid(options)); /// options.set_rounding_mode(Exact); /// assert!(!u128::MAX.fmt_sci_valid(options)); // u128::MAX has more than 16 significant digits /// options.set_precision(50); /// assert!(u128::MAX.fmt_sci_valid(options)); /// ``` pub mod to_sci; /// The [`BaseFmtWrapper`](to_string::BaseFmtWrapper) struct and /// [`ToStringBase`](super::traits::ToStringBase) trait, used for converting numbers to strings. /// /// # Display::fmt for BaseFmtWrapper /// ``` /// use malachite_base::num::conversion::string::to_string::BaseFmtWrapper; /// /// let x = BaseFmtWrapper::new(1000000000u32, 36); /// assert_eq!(format!("{}", x), "gjdgxs"); /// assert_eq!(format!("{:#}", x), "GJDGXS"); /// assert_eq!(format!("{:010}", x), "0000gjdgxs"); /// assert_eq!(format!("{:#010}", x), "0000GJDGXS"); /// /// let x = BaseFmtWrapper::new(-1000000000i32, 36); /// assert_eq!(format!("{}", x), "-gjdgxs"); /// assert_eq!(format!("{:#}", x), "-GJDGXS"); /// assert_eq!(format!("{:010}", x), "-000gjdgxs"); /// assert_eq!(format!("{:#010}", x), "-000GJDGXS"); /// ``` /// /// # Debug::fmt for BaseFmtWrapper /// ``` /// use malachite_base::num::conversion::string::to_string::BaseFmtWrapper; /// /// let x = BaseFmtWrapper::new(1000000000u32, 36); /// assert_eq!(format!("{:?}", x), "gjdgxs"); /// assert_eq!(format!("{:#?}", x), "GJDGXS"); /// assert_eq!(format!("{:010?}", x), "0000gjdgxs"); /// assert_eq!(format!("{:#010?}", x), "0000GJDGXS"); /// /// let x = BaseFmtWrapper::new(-1000000000i32, 36); /// assert_eq!(format!("{:?}", x), "-gjdgxs"); /// assert_eq!(format!("{:#?}", x), "-GJDGXS"); /// assert_eq!(format!("{:010?}", x), "-000gjdgxs"); /// assert_eq!(format!("{:#010?}", x), "-000GJDGXS"); /// ``` /// /// # to_string_base /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// /// assert_eq!(1000u16.to_string_base(2), "1111101000"); /// assert_eq!(1000u16.to_string_base(10), "1000"); /// assert_eq!(1000u16.to_string_base(36), "rs"); /// /// assert_eq!(1000i16.to_string_base(2), "1111101000"); /// assert_eq!(1000i16.to_string_base(10), "1000"); /// assert_eq!(1000i16.to_string_base(36), "rs"); /// /// assert_eq!((-1000i16).to_string_base(2), "-1111101000"); /// assert_eq!((-1000i16).to_string_base(10), "-1000"); /// assert_eq!((-1000i16).to_string_base(36), "-rs"); /// ``` /// /// # to_string_base_upper /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// /// assert_eq!(1000u16.to_string_base_upper(2), "1111101000"); /// assert_eq!(1000u16.to_string_base_upper(10), "1000"); /// assert_eq!(1000u16.to_string_base_upper(36), "RS"); /// /// assert_eq!(1000i16.to_string_base_upper(2), "1111101000"); /// assert_eq!(1000i16.to_string_base_upper(10), "1000"); /// assert_eq!(1000i16.to_string_base_upper(36), "RS"); /// /// assert_eq!((-1000i16).to_string_base_upper(2), "-1111101000"); /// assert_eq!((-1000i16).to_string_base_upper(10), "-1000"); /// assert_eq!((-1000i16).to_string_base_upper(36), "-RS"); /// ``` pub mod to_string; ================================================ FILE: malachite-base/src/num/conversion/string/options/exhaustive.rs ================================================ // Copyright © 2026 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 crate::bools::exhaustive::exhaustive_bools; use crate::num::conversion::string::options::{FromSciStringOptions, SciSizeOptions, ToSciOptions}; use crate::num::exhaustive::{ exhaustive_negative_signeds, primitive_int_increasing_inclusive_range, }; use crate::num::logic::traits::NotAssign; use crate::rounding_modes::RoundingMode; use crate::rounding_modes::exhaustive::exhaustive_rounding_modes; use crate::tuples::exhaustive::{exhaustive_triples, lex_pairs, lex_quadruples_from_single}; use alloc::boxed::Box; /// Generates all [`SciSizeOptions`]s. /// /// This struct is created by [`exhaustive_sci_size_options`]; see its documentation for more. pub struct ExhaustiveSciSizeOptions { i: u64, even: bool, } impl Iterator for ExhaustiveSciSizeOptions { type Item = SciSizeOptions; fn next(&mut self) -> Option { let out = if self.even { if self.i == 0 { SciSizeOptions::Complete } else { SciSizeOptions::Precision(self.i) } } else { let i = self.i; self.i += 1; SciSizeOptions::Scale(i) }; self.even.not_assign(); Some(out) } } /// Generates all [`SciSizeOptions`]s. /// /// The output length is $2^{65}$. /// /// # Complexity per iteration /// Constant time and additional memory. pub const fn exhaustive_sci_size_options() -> ExhaustiveSciSizeOptions { ExhaustiveSciSizeOptions { i: 0, even: true } } /// Generates all [`ToSciOptions`]s. /// /// This struct is created by [`exhaustive_to_sci_options`]; see its documentation for more. pub struct ExhaustiveToSciOptions( Box< dyn Iterator< Item = ( (u8, SciSizeOptions, i64), (RoundingMode, (bool, bool, bool, bool)), ), >, >, ); impl Iterator for ExhaustiveToSciOptions { type Item = ToSciOptions; fn next(&mut self) -> Option { let ( (base, size_options, neg_exp_threshold), ( rounding_mode, (lowercase, e_lowercase, force_exponent_plus_sign, include_trailing_zeros), ), ) = self.0.next()?; Some(ToSciOptions { base, size_options, neg_exp_threshold, rounding_mode, lowercase, e_lowercase, force_exponent_plus_sign, include_trailing_zeros, }) } } /// Generates all [`ToSciOptions`]s. /// /// The output length is $2^{133}\times 3 \times 5 \times 7 \approx 1.4335 \times 10^{42}$. /// /// # Complexity per iteration /// Constant time and additional memory. pub fn exhaustive_to_sci_options() -> ExhaustiveToSciOptions { ExhaustiveToSciOptions(Box::new(lex_pairs( exhaustive_triples( primitive_int_increasing_inclusive_range(2, 36), exhaustive_sci_size_options(), exhaustive_negative_signeds(), ), lex_pairs( exhaustive_rounding_modes(), lex_quadruples_from_single(exhaustive_bools()), ), ))) } /// Generates all [`FromSciStringOptions`]s. /// /// This struct is created by [`exhaustive_from_sci_string_options`]; see its documentation for /// more. pub struct ExhaustiveFromSciStringOptions(Box>); impl Iterator for ExhaustiveFromSciStringOptions { type Item = FromSciStringOptions; fn next(&mut self) -> Option { let (base, rounding_mode) = self.0.next()?; Some(FromSciStringOptions { base, rounding_mode, }) } } /// Generates all [`FromSciStringOptions`]s. /// /// The output length is 210. /// /// # Complexity per iteration /// Constant time and additional memory. pub fn exhaustive_from_sci_string_options() -> ExhaustiveFromSciStringOptions { ExhaustiveFromSciStringOptions(Box::new(lex_pairs( primitive_int_increasing_inclusive_range(2, 36), exhaustive_rounding_modes(), ))) } ================================================ FILE: malachite-base/src/num/conversion/string/options/mod.rs ================================================ // Copyright © 2026 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 crate::rounding_modes::RoundingMode::{self, *}; /// A `struct` determining how much "detail" should be used when creating a scientific-notation /// string. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SciSizeOptions { /// Indicates that the number should be rendered in its full precision. Complete, /// Indicates how many significant figures should be shown. The precision cannot be zero. Precision(u64), /// Indicates how many digits after the decimal (or other-base) point should be shown. For /// example, if the base is 10 and the scale is 2, then up to two digits after the decimal point /// should be shown. Scale(u64), } impl Default for SciSizeOptions { fn default() -> Self { Self::Precision(16) // Similar to f64 string output } } #[cfg(feature = "test_build")] impl SciSizeOptions { pub const fn is_valid(&self) -> bool { if let Self::Precision(p) = *self { p != 0 } else { true } } } /// A `struct` determining how a number should be formatted as a "scientific" string. /// /// - The base must be between 2 and 36, inclusive. The characters representing the digits are `'0'` /// through `'9'` and either `'a'` through `'z'` or `'A'` through `'Z'`, depending on whether the /// `lowercase` field is set. The default base is 10. /// /// - The rounding mode determines how the output should be rounded, in case the `size_options` /// field is such that the number can't be fully represented. The default rounding mode is /// `Nearest`. /// /// - The size options determine the precision or scale that the number should be displayed with. /// The default is `Precision(16)`, which is about as much precision as an `f64` is usually /// displayed with. /// /// - The negative exponent threshold determines when small numbers switch to scientific notation. /// The default is $-6$, meaning that the numbers $1/10, 1/100, 1/1000, \ldots$. would be /// displayed as `0.1, 0.01, 0.001, 0.0001, 0.00001, 1e-6, 1e-7...`. The threshold must be /// negative. /// /// - The lowercase setting determines whether digits in bases greater than 10 are lowercase or /// uppercase. The default is `true`. /// /// - The exponent lowercase setting determines whether the exponent indicator is lowercase (`'e'`) /// or uppercase (`'E'`). The default is `true`. /// /// - The "force exponent plus sign" setting determines whether positive exponents should be /// rendered with an explicit plus sign. If the base is 15 or greater, then the explicit plus sign /// is used regardless, in order to distinguish the exponent indicator from the digit `'e'`. The /// default is `false`. /// /// - The "include trailing zeros" setting determines whether trailing zeros after the decimal (or /// other-base) point should be included. The default is `false`. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct ToSciOptions { pub(crate) base: u8, pub(crate) rounding_mode: RoundingMode, pub(crate) size_options: SciSizeOptions, neg_exp_threshold: i64, pub(crate) lowercase: bool, pub(crate) e_lowercase: bool, pub(crate) force_exponent_plus_sign: bool, pub(crate) include_trailing_zeros: bool, } impl Default for ToSciOptions { fn default() -> Self { Self { base: 10, rounding_mode: Nearest, size_options: SciSizeOptions::default(), neg_exp_threshold: -6, lowercase: true, e_lowercase: true, force_exponent_plus_sign: false, include_trailing_zeros: false, } } } impl ToSciOptions { /// Returns the base to be used in the conversion. It is always between 2 and 36, inclusive. #[inline] pub const fn get_base(&self) -> u8 { self.base } /// Returns the rounding mode to be used in the conversion. #[inline] pub const fn get_rounding_mode(&self) -> RoundingMode { self.rounding_mode } /// Returns the size options to be used in the conversion. #[inline] pub const fn get_size_options(&self) -> SciSizeOptions { self.size_options } /// Returns the exponent low threshold to be used in the conversion. It is always negative. #[inline] pub const fn get_neg_exp_threshold(&self) -> i64 { self.neg_exp_threshold } /// Returns whether the digits should be lowercase. #[inline] pub const fn get_lowercase(&self) -> bool { self.lowercase } /// Returns whether the exponent indicator should be lowercase (`'e'` rather than `'E'`). #[inline] pub const fn get_e_lowercase(&self) -> bool { self.e_lowercase } /// Returns whether positive exponents should always be preceded by an explicit plus sign. #[inline] pub const fn get_force_exponent_plus_sign(&self) -> bool { self.force_exponent_plus_sign } /// Returns whether trailing zeros should be included after the decimal (or other-base) point. #[inline] pub const fn get_include_trailing_zeros(&self) -> bool { self.include_trailing_zeros } /// Sets the base to be used in the conversion. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. #[inline] pub fn set_base(&mut self, base: u8) { assert!(base >= 2); assert!(base <= 36); self.base = base; } /// Sets the rounding mode to be used in the conversion. #[inline] pub const fn set_rounding_mode(&mut self, rm: RoundingMode) { self.rounding_mode = rm; } /// Sets the size options to the "Complete" mode, indicating that the number should be converted /// using its full precision. #[inline] pub const fn set_size_complete(&mut self) { self.size_options = SciSizeOptions::Complete; } /// Sets the size options to some precision, or number of significant digits. /// /// # Panics /// Panics if `precision` is zero. #[inline] pub fn set_precision(&mut self, precision: u64) { assert_ne!(precision, 0); self.size_options = SciSizeOptions::Precision(precision); } /// Sets the size options to some scale, or number of digits after the decimal (or other-base) /// point. #[inline] pub const fn set_scale(&mut self, scale: u64) { self.size_options = SciSizeOptions::Scale(scale); } /// Sets the threshold at which nonzero numbers with a small absolute value start being /// represented using negative exponents. #[inline] pub fn set_neg_exp_threshold(&mut self, neg_exp_threshold: i64) { assert!(neg_exp_threshold < 0); self.neg_exp_threshold = neg_exp_threshold; } /// Specifies that digits in bases greater than ten should be output with lowercase letters. #[inline] pub const fn set_lowercase(&mut self) { self.lowercase = true; } /// Specifies that digits in bases greater than ten should be output with uppercase letters. #[inline] pub const fn set_uppercase(&mut self) { self.lowercase = false; } /// Specifies that the exponent-indicating character should be `'e'`. #[inline] pub const fn set_e_lowercase(&mut self) { self.e_lowercase = true; } /// Specifies that the exponent-indicating character should be `'E'`. #[inline] pub const fn set_e_uppercase(&mut self) { self.e_lowercase = false; } /// Sets whether a positive exponent should be preceded by an explicit plus sign. /// /// If the base is 15 or greater, an explicit plus sign will be used regardless, in order to /// differentiate the exponent-indicating character from the digit `'e'`. #[inline] pub const fn set_force_exponent_plus_sign(&mut self, force_exponent_plus_sign: bool) { self.force_exponent_plus_sign = force_exponent_plus_sign; } /// Sets whether trailing zeros after the decimal (or other-base) point should be included. #[inline] pub const fn set_include_trailing_zeros(&mut self, include_trailing_zeros: bool) { self.include_trailing_zeros = include_trailing_zeros; } #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { (2..=36).contains(&self.base) && self.neg_exp_threshold < 0 && self.size_options.is_valid() } } /// A `struct` determining how a number should be parsed from a "scientific" string. /// /// - The base must be between 2 and 36, inclusive. The characters representing the digits may be /// `'0'` through `'9'` and either `'a'` through `'z'` or `'A'` through `'Z'`. The default base is /// 10. /// /// - The rounding mode determines how the output should be rounded, in case the output type can't /// represent all possible input strings. The default rounding mode is `Nearest`. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct FromSciStringOptions { pub(crate) base: u8, pub(crate) rounding_mode: RoundingMode, } impl Default for FromSciStringOptions { fn default() -> Self { Self { base: 10, rounding_mode: Nearest, } } } impl FromSciStringOptions { /// Returns the base to be used in the conversion. It is always between 2 and 36, inclusive. #[inline] pub const fn get_base(&self) -> u8 { self.base } /// Returns the rounding mode to be used in the conversion. #[inline] pub const fn get_rounding_mode(&self) -> RoundingMode { self.rounding_mode } /// Sets the base to be used in the conversion. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. #[inline] pub fn set_base(&mut self, base: u8) { assert!(base >= 2); assert!(base <= 36); self.base = base; } /// Sets the rounding mode to be used in the conversion. #[inline] pub const fn set_rounding_mode(&mut self, rm: RoundingMode) { self.rounding_mode = rm; } #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { (2..=36).contains(&self.base) } } /// Iterators that generate [`SciSizeOptions`], [`ToSciOptions`], and [`FromSciStringOptions`] /// without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`SciSizeOptions`], [`ToSciOptions`], and [`FromSciStringOptions`] /// randomly. pub mod random; ================================================ FILE: malachite-base/src/num/conversion/string/options/random.rs ================================================ // Copyright © 2026 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 crate::bools::random::{RandomBools, random_bools}; use crate::num::conversion::string::options::{FromSciStringOptions, SciSizeOptions, ToSciOptions}; use crate::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomNegativeSigneds, geometric_random_negative_signeds, geometric_random_unsigneds, }; use crate::num::random::{RandomUnsignedInclusiveRange, random_unsigned_inclusive_range}; use crate::random::Seed; use crate::rounding_modes::random::{RandomRoundingModes, random_rounding_modes}; /// Generates random [`SciSizeOptions`]s. /// /// This struct is created by [`random_sci_size_options`]; see its documentation for more. pub struct RandomSciSizeOptions { bs: RandomBools, xs: GeometricRandomNaturalValues, } impl Iterator for RandomSciSizeOptions { type Item = SciSizeOptions; fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { if x == 0 { SciSizeOptions::Complete } else { SciSizeOptions::Precision(x) } } else { SciSizeOptions::Scale(x) }) } } /// Generates random [`SciSizeOptions`]s. /// /// The scales and precisions are chosen from a geometric distribution whose mean is the ratio /// `m_size_numerator / m_size_denominator`. /// /// # Panics /// Panics if `m_size_numerator` or `m_size_denominator` are zero, or, if after being reduced to /// lowest terms, their sum is greater than or equal to $2^{64}$. /// /// The output length is infinite. pub fn random_sci_size_options( seed: Seed, m_size_numerator: u64, m_size_denominator: u64, ) -> RandomSciSizeOptions { RandomSciSizeOptions { bs: random_bools(seed.fork("bs")), xs: geometric_random_unsigneds(seed.fork("xs"), m_size_numerator, m_size_denominator), } } /// Generates random [`ToSciOptions`]s. /// /// This struct is created by [`random_to_sci_options`]; see its documentation for more. pub struct RandomToSciOptions { us: RandomUnsignedInclusiveRange, rms: RandomRoundingModes, sos: RandomSciSizeOptions, is: GeometricRandomNegativeSigneds, bs: RandomBools, } impl Iterator for RandomToSciOptions { type Item = ToSciOptions; fn next(&mut self) -> Option { Some(ToSciOptions { base: self.us.next().unwrap(), rounding_mode: self.rms.next().unwrap(), size_options: self.sos.next().unwrap(), neg_exp_threshold: self.is.next().unwrap(), lowercase: self.bs.next().unwrap(), e_lowercase: self.bs.next().unwrap(), force_exponent_plus_sign: self.bs.next().unwrap(), include_trailing_zeros: self.bs.next().unwrap(), }) } } /// Generates random [`ToSciOptions`]s. /// /// The scales, precisions, and the negative of the negative exponenet threshold are chosen from a /// geometric distribution whose mean is the ratio `m_size_numerator / m_size_denominator`. /// /// # Panics /// Panics if `m_size_numerator` or `m_size_denominator` are zero, or, if after being reduced to /// lowest terms, their sum is greater than or equal to $2^{64}$. /// /// The output length is infinite. pub fn random_to_sci_options( seed: Seed, m_size_numerator: u64, m_size_denominator: u64, ) -> RandomToSciOptions { RandomToSciOptions { us: random_unsigned_inclusive_range(seed.fork("us"), 2, 36), rms: random_rounding_modes(seed.fork("rms")), sos: random_sci_size_options(seed.fork("sos"), m_size_numerator, m_size_denominator), is: geometric_random_negative_signeds( seed.fork("is"), m_size_numerator, m_size_denominator, ), bs: random_bools(seed.fork("bs")), } } /// Generates random [`FromSciStringOptions`]s. /// /// This struct is created by [`random_from_sci_string_options`]; see its documentation for more. pub struct RandomFromSciStringOptions { us: RandomUnsignedInclusiveRange, rms: RandomRoundingModes, } impl Iterator for RandomFromSciStringOptions { type Item = FromSciStringOptions; fn next(&mut self) -> Option { Some(FromSciStringOptions { base: self.us.next().unwrap(), rounding_mode: self.rms.next().unwrap(), }) } } /// Generates random [`FromSciStringOptions`]s. /// /// The output length is infinite. pub fn random_from_sci_string_options(seed: Seed) -> RandomFromSciStringOptions { RandomFromSciStringOptions { us: random_unsigned_inclusive_range(seed.fork("us"), 2, 36), rms: random_rounding_modes(seed.fork("rms")), } } ================================================ FILE: malachite-base/src/num/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedLogBase2, NegAssign, Pow, UnsignedAbs}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::options::{SciSizeOptions, ToSciOptions}; use crate::num::conversion::string::to_string::BaseFmtWrapper; use crate::num::conversion::string::to_string::{ digit_to_display_byte_lower, digit_to_display_byte_upper, }; use crate::num::conversion::traits::{ExactFrom, ToSci}; use crate::rounding_modes::RoundingMode::*; use crate::slices::slice_trailing_zeros; use alloc::string::String; use core::fmt::{Display, Formatter, Write}; /// A `struct` that can be used to format a number in scientific notation. pub struct SciWrapper<'a, T: ToSci> { pub(crate) x: &'a T, pub(crate) options: ToSciOptions, } impl Display for SciWrapper<'_, T> { #[inline] fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { self.x.fmt_sci(f, self.options) } } #[doc(hidden)] pub fn write_exponent( f: &mut Formatter, options: ToSciOptions, exp: T, ) -> core::fmt::Result { f.write_char(if options.get_e_lowercase() { 'e' } else { 'E' })?; if exp > T::ZERO && (options.get_force_exponent_plus_sign() || options.get_base() >= 15) { f.write_char('+')?; } write!(f, "{exp}") } fn write_helper(x: T, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result where BaseFmtWrapper: Display, { let w = BaseFmtWrapper { x, base: options.base, }; if options.lowercase { Display::fmt(&w, f) } else { write!(f, "{w:#}") } } fn fmt_sci_valid_unsigned(x: T, options: ToSciOptions) -> bool { if x == T::ZERO || options.rounding_mode != Exact { return true; } match options.size_options { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => true, SciSizeOptions::Precision(precision) => { let t_base = T::from(options.base); let log = x.floor_log_base(t_base); if log < precision { return true; } let neg_scale = log - precision + 1; if let Some(base_log) = options.base.checked_log_base_2() { x.divisible_by_power_of_2(base_log * neg_scale) } else { x.divisible_by(Pow::pow(t_base, neg_scale)) } } } } fn fmt_sci_unsigned( mut x: T, f: &mut Formatter, options: ToSciOptions, ) -> core::fmt::Result where BaseFmtWrapper: Display, { match options.size_options { SciSizeOptions::Complete | SciSizeOptions::Scale(0) => write_helper(x, f, options), SciSizeOptions::Scale(scale) => { write_helper(x, f, options)?; if options.include_trailing_zeros { f.write_char('.')?; for _ in 0..scale { f.write_char('0')?; } } Ok(()) } SciSizeOptions::Precision(precision) => { let t_base = T::from(options.base); let log = if x == T::ZERO { 0 } else { x.floor_log_base(t_base) }; if log < precision { // no exponent write_helper(x, f, options)?; if options.include_trailing_zeros { let extra_zeros = precision - log - 1; if extra_zeros != 0 { f.write_char('.')?; for _ in 0..extra_zeros { f.write_char('0')?; } } } Ok(()) } else { // exponent let mut e = log; let neg_scale = log - precision + 1; if let Some(base_log) = options.base.checked_log_base_2() { x.shr_round_assign(base_log * neg_scale, options.rounding_mode); } else { x.div_round_assign(Pow::pow(t_base, neg_scale), options.rounding_mode); } let mut chars = x.to_digits_desc(&options.base); let mut len = chars.len(); let p = usize::exact_from(precision); if len > p { // rounded up to a power of the base, need to reduce precision chars.pop(); len -= 1; e += 1; } assert_eq!(len, p); if !options.include_trailing_zeros { chars.truncate(len - slice_trailing_zeros(&chars)); } if options.lowercase { for digit in &mut chars { *digit = digit_to_display_byte_lower(*digit).unwrap(); } } else { for digit in &mut chars { *digit = digit_to_display_byte_upper(*digit).unwrap(); } } len = chars.len(); if len != 1 { chars.push(b'0'); chars.copy_within(1..len, 2); chars[1] = b'.'; } f.write_str(&String::from_utf8(chars).unwrap())?; write_exponent(f, options, e) } } } } #[inline] fn fmt_sci_valid_signed(x: T, options: ToSciOptions) -> bool where ::Output: PrimitiveUnsigned, { fmt_sci_valid_unsigned(x.unsigned_abs(), options) } fn fmt_sci_signed( x: T, f: &mut Formatter, mut options: ToSciOptions, ) -> core::fmt::Result where ::Output: PrimitiveUnsigned, { let abs = x.unsigned_abs(); if x >= T::ZERO { abs.fmt_sci(f, options) } else { options.rounding_mode.neg_assign(); f.write_char('-')?; abs.fmt_sci(f, options) } } macro_rules! impl_to_sci_unsigned { ($t:ident) => { impl ToSci for $t { /// Determines whether an unsigned number can be converted to a string using /// [`to_sci_with_options`](super::super::traits::ToSci::to_sci_with_options) and a /// particular set of options. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::to_sci#fmt_sci_valid). #[inline] fn fmt_sci_valid(&self, options: ToSciOptions) -> bool { fmt_sci_valid_unsigned(*self, options) } /// Converts an unsigned number to a string using a specified base, possibly formatting /// the number using scientific notation. /// /// See [`ToSciOptions`] for details on the available options. Note that setting /// `neg_exp_threshold` has no effect, since there is never a need to use negative /// exponents when representing an integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the /// input must be rounded. /// /// # Examples /// See [here](super::to_sci). #[inline] fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result { fmt_sci_unsigned(*self, f, options) } } }; } apply_to_unsigneds!(impl_to_sci_unsigned); macro_rules! impl_to_sci_signed { ($t:ident) => { impl ToSci for $t { /// Determines whether a signed number can be converted to a string using /// [`to_sci_with_options`](super::super::traits::ToSci::to_sci_with_options) and a /// particular set of options. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::to_sci#fmt_sci_valid). #[inline] fn fmt_sci_valid(&self, options: ToSciOptions) -> bool { fmt_sci_valid_signed(*self, options) } /// Converts a signed number to a string using a specified base, possibly formatting the /// number using scientific notation. /// /// See [`ToSciOptions`] for details on the available options. Note that setting /// `neg_exp_threshold` has no effect, since there is never a need to use negative /// exponents when representing an integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the /// input must be rounded. /// /// # Examples /// See [here](super::to_sci). #[inline] fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result { fmt_sci_signed(*self, f, options) } } }; } apply_to_signeds!(impl_to_sci_signed); ================================================ FILE: malachite-base/src/num/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::UnsignedAbs; use crate::num::basic::traits::Zero; use crate::num::conversion::traits::{Digits, ToStringBase, WrappingFrom}; use crate::vecs::vec_pad_left; use alloc::string::String; use alloc::string::ToString; use core::fmt::{Debug, Display, Formatter, Result, Write}; /// A `struct` that allows for formatting a numeric type and rendering its digits in a specified /// base. #[derive(Clone, Eq, Hash, PartialEq)] pub struct BaseFmtWrapper { pub(crate) x: T, pub(crate) base: u8, } impl BaseFmtWrapper { /// Creates a new `BaseFmtWrapper`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::to_string::BaseFmtWrapper; /// /// let x = BaseFmtWrapper::new(1000000000u32, 36); /// assert_eq!(format!("{}", x), "gjdgxs"); /// assert_eq!(format!("{:#}", x), "GJDGXS"); /// ``` pub fn new(x: T, base: u8) -> Self { assert!((2..=36).contains(&base), "base out of range"); Self { x, base } } /// Recovers the value from a `BaseFmtWrapper`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::to_string::BaseFmtWrapper; /// /// assert_eq!(BaseFmtWrapper::new(1000000000u32, 36).unwrap(), 1000000000); /// ``` #[allow(clippy::missing_const_for_fn)] pub fn unwrap(self) -> T { self.x } } /// Converts a digit to a byte corresponding to a numeric or lowercase alphabetic [`char`] that /// represents the digit. /// /// Digits from 0 to 9 become bytes corresponding to [`char`]s from '0' to '9'. Digits from 10 to 35 /// become bytes representing the lowercase [`char`]s 'a' to 'z'. Passing a digit greater than 35 /// gives a `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::to_string::digit_to_display_byte_lower; /// /// assert_eq!(digit_to_display_byte_lower(0), Some(b'0')); /// assert_eq!(digit_to_display_byte_lower(9), Some(b'9')); /// assert_eq!(digit_to_display_byte_lower(10), Some(b'a')); /// assert_eq!(digit_to_display_byte_lower(35), Some(b'z')); /// assert_eq!(digit_to_display_byte_lower(100), None); /// ``` pub const fn digit_to_display_byte_lower(b: u8) -> Option { match b { 0..=9 => Some(b + b'0'), 10..=35 => Some(b + b'a' - 10), _ => None, } } /// Converts a digit to a byte corresponding to a numeric or uppercase alphabetic [`char`] that /// represents the digit. /// /// Digits from 0 to 9 become bytes corresponding to [`char`]s from '0' to '9'. Digits from 10 to 35 /// become bytes representing the lowercase [`char`]s 'A' to 'Z'. Passing a digit greater than 35 /// gives a `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::to_string::digit_to_display_byte_upper; /// /// assert_eq!(digit_to_display_byte_upper(0), Some(b'0')); /// assert_eq!(digit_to_display_byte_upper(9), Some(b'9')); /// assert_eq!(digit_to_display_byte_upper(10), Some(b'A')); /// assert_eq!(digit_to_display_byte_upper(35), Some(b'Z')); /// assert_eq!(digit_to_display_byte_upper(100), None); /// ``` pub const fn digit_to_display_byte_upper(b: u8) -> Option { match b { 0..=9 => Some(b + b'0'), 10..=35 => Some(b + b'A' - 10), _ => None, } } fn fmt_unsigned + Eq + Zero>( w: &BaseFmtWrapper, f: &mut Formatter, ) -> Result { let mut digits = w.x.to_digits_desc(&u8::wrapping_from(w.base)); if f.alternate() { for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } } else { for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } } if w.x == T::ZERO { digits.push(b'0'); } f.pad_integral(true, "", core::str::from_utf8(&digits).unwrap()) } fn to_string_base_unsigned + Eq + Zero>(x: &T, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if *x == T::ZERO { "0".to_string() } else { let mut digits = x.to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } String::from_utf8(digits).unwrap() } } fn to_string_base_upper_unsigned + Eq + Zero>(x: &T, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if *x == T::ZERO { "0".to_string() } else { let mut digits = x.to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } String::from_utf8(digits).unwrap() } } macro_rules! impl_to_string_base_unsigned { ($t:ident) => { impl Display for BaseFmtWrapper<$t> { /// Writes a wrapped unsigned number to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. /// Using the `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string). #[inline] fn fmt(&self, f: &mut Formatter) -> Result { fmt_unsigned(self, f) } } impl Debug for BaseFmtWrapper<$t> { /// Writes a wrapped unsigned number to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. /// Using the `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string). #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl ToStringBase for $t { /// Converts an unsigned number to a string using a specified base. /// /// Digits from 0 to 9 become `char`s from '0' to '9'. Digits from 10 to 35 become the /// lowercase [`char`]s 'a' to 'z'. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string#to_string_base). #[inline] fn to_string_base(&self, base: u8) -> String { to_string_base_unsigned(self, base) } /// Converts an unsigned number to a string using a specified base. /// /// Digits from 0 to 9 become `char`s from '0' to '9'. Digits from 10 to 35 become the /// uppercase [`char`]s 'A' to 'Z'. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string#to_string_base_upper). #[inline] fn to_string_base_upper(&self, base: u8) -> String { to_string_base_upper_unsigned(self, base) } } }; } apply_to_unsigneds!(impl_to_string_base_unsigned); fn fmt_signed( w: &BaseFmtWrapper, f: &mut Formatter, ) -> Result where BaseFmtWrapper<::Output>: Display, { if w.x < T::ZERO { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$}", &BaseFmtWrapper::new(w.x.unsigned_abs(), w.base), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$}", &BaseFmtWrapper::new(w.x.unsigned_abs(), w.base), width = width.saturating_sub(1) ) }; } } Display::fmt(&BaseFmtWrapper::new(w.x.unsigned_abs(), w.base), f) } fn to_string_base_signed, S: Copy + Eq + Ord + UnsignedAbs + Zero>( x: &S, base: u8, ) -> String { assert!((2..=36).contains(&base), "base out of range"); if *x == S::ZERO { "0".to_string() } else { let mut digits = x.unsigned_abs().to_digits_desc(&u8::wrapping_from(base)); for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } if *x < S::ZERO { vec_pad_left(&mut digits, 1, b'-'); } String::from_utf8(digits).unwrap() } } fn to_string_base_upper_signed< U: Digits, S: Copy + Eq + Ord + UnsignedAbs + Zero, >( x: &S, base: u8, ) -> String { assert!((2..=36).contains(&base), "base out of range"); if *x == S::ZERO { "0".to_string() } else { let mut digits = x.unsigned_abs().to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } if *x < S::ZERO { vec_pad_left(&mut digits, 1, b'-'); } String::from_utf8(digits).unwrap() } } macro_rules! impl_to_string_base_signed { ($u:ident, $s:ident) => { impl Display for BaseFmtWrapper<$s> { /// Writes a wrapped signed number to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. /// Using the `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// Unlike with the default implementations of [`Binary`](std::fmt::Binary), /// [`Octal`](std::fmt::Octal), [`LowerHex`](std::fmt::LowerHex), and /// [`UpperHex`](std::fmt::UpperHex), negative numbers are represented using a negative /// sign, not two's complement. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string). #[inline] fn fmt(&self, f: &mut Formatter) -> Result { fmt_signed(self, f) } } impl Debug for BaseFmtWrapper<$s> { /// Writes a wrapped signed number to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. /// Using the `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// Unlike with the default implementations of [`Binary`](std::fmt::Binary), /// [`Octal`](std::fmt::Octal), [`LowerHex`](std::fmt::LowerHex), and /// [`UpperHex`](std::fmt::UpperHex), negative numbers are represented using a negative /// sign, not two's complement. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string). #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl ToStringBase for $s { /// Converts a signed number to a string using a specified base. /// /// Digits from 0 to 9 become `char`s from '0' to '9'. Digits from 10 to 35 become the /// lowercase [`char`]s 'a' to 'z'. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string#to_string_base). #[inline] fn to_string_base(&self, base: u8) -> String { to_string_base_signed::<$u, $s>(self, base) } /// Converts a signed number to a string using a specified base. /// /// Digits from 0 to 9 become `char`s from '0' to '9'. Digits from 10 to 35 become the /// uppercase [`char`]s 'A' to 'Z'. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// See [here](super::to_string#to_string_base_upper). #[inline] fn to_string_base_upper(&self, base: u8) -> String { to_string_base_upper_signed::<$u, $s>(self, base) } } }; } apply_to_unsigned_signed_pairs!(impl_to_string_base_signed); ================================================ FILE: malachite-base/src/num/conversion/traits.rs ================================================ // Copyright © 2026 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 crate::num::conversion::string::options::{FromSciStringOptions, ToSciOptions}; use crate::num::conversion::string::to_sci::SciWrapper; use crate::rounding_modes::RoundingMode; use alloc::string::String; use alloc::vec::Vec; use core::cmp::Ordering; use core::fmt::{Formatter, Result}; /// Expresses a value as a [`Vec`] of digits, or reads a value from an iterator of digits. /// /// The trait is parameterized by `T`, which is both the digit type and the base type. pub trait Digits: Sized { /// Returns a [`Vec`] containing the digits of a value in ascending order: least- to /// most-significant. fn to_digits_asc(&self, base: &T) -> Vec; /// Returns a [`Vec`] containing the digits of a value in descending order: most- to /// least-significant. fn to_digits_desc(&self, base: &T) -> Vec; /// Converts an iterator of digits into a value. /// /// The input digits are in ascending order: least- to most-significant. fn from_digits_asc>(base: &T, digits: I) -> Option; /// Converts an iterator of digits into a value. /// /// The input digits are in descending order: most- to least-significant. fn from_digits_desc>(base: &T, digits: I) -> Option; } /// An iterator over a value's base-$2^k$ digits. pub trait PowerOf2DigitIterator: Iterator + DoubleEndedIterator { fn get_digit(&self, index: u64) -> T; } /// Creates an iterator over a value's base-$2^k$ digits. pub trait PowerOf2DigitIterable { type PowerOf2DigitIterator: PowerOf2DigitIterator; /// Returns a double-ended iterator over a value's digits in base $2^l$, where $k$ is /// `log_base`. /// /// The iterator ends after the value's most-significant digit. fn power_of_2_digits(self, log_base: u64) -> Self::PowerOf2DigitIterator; } /// Expresses a value as a [`Vec`] of base-$2^k$ digits, or reads a value from an iterator of /// base-$2^k$ digits. /// /// The trait is parameterized by the digit type. pub trait PowerOf2Digits: Sized { /// Returns a [`Vec`] containing the digits of a value in ascending order: least- to /// most-significant. /// /// The base is $2^k$, where $k$ is `log_base`. fn to_power_of_2_digits_asc(&self, log_base: u64) -> Vec; /// Returns a [`Vec`] containing the digits of a value in descending order: most- to /// least-significant. /// /// The base is $2^k$, where $k$ is `log_base`. fn to_power_of_2_digits_desc(&self, log_base: u64) -> Vec; /// Converts an iterator of digits into a value. /// /// The input digits are in ascending order: least- to most-significant. The base is $2^k$, /// where $k$ is `log_base`. fn from_power_of_2_digits_asc>(log_base: u64, digits: I) -> Option; /// Converts an iterator of digits into a value. /// /// The input digits are in descending order: most- to least-significant. The base is $2^k$, /// where $k$ is `log_base`. fn from_power_of_2_digits_desc>(log_base: u64, digits: I) -> Option; } /// Converts a string slice in a given base to a value. pub trait FromStringBase: Sized { fn from_string_base(base: u8, s: &str) -> Option; } /// Converts a number to a string using a specified base. pub trait ToStringBase { /// Converts a signed number to a lowercase string using a specified base. fn to_string_base(&self, base: u8) -> String; /// Converts a signed number to an uppercase string using a specified base. fn to_string_base_upper(&self, base: u8) -> String; } /// Converts a number to a string, possibly in scientific notation. pub trait ToSci: Sized { /// Formats a number, possibly in scientific notation. fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> Result; /// Determines whether some formatting options can be applied to a number. fn fmt_sci_valid(&self, options: ToSciOptions) -> bool; /// Converts a number to a string, possibly in scientific notation. fn to_sci_with_options(&self, options: ToSciOptions) -> SciWrapper<'_, Self> { SciWrapper { x: self, options } } /// Converts a number to a string, possibly in scientific notation, using the default /// [`ToSciOptions`]. #[inline] fn to_sci(&self) -> SciWrapper<'_, Self> { SciWrapper { x: self, options: ToSciOptions::default(), } } } /// Converts a `&str`, possibly in scientific notation, to a number. pub trait FromSciString: Sized { /// Converts a `&str`, possibly in scientific notation, to a number. fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option; /// Converts a `&str`, possibly in scientific notation, to a number, using the default /// [`FromSciStringOptions`]. #[inline] fn from_sci_string(s: &str) -> Option { Self::from_sci_string_with_options(s, FromSciStringOptions::default()) } } /// Converts a value from one type to another. If the conversion fails, the function panics. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`TryFrom`] is implemented. pub trait ExactFrom: Sized { fn exact_from(value: T) -> Self; } /// Converts a value from one type to another. If the conversion fails, the function panics. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`ExactFrom`] is implemented. pub trait ExactInto { fn exact_into(self) -> T; } impl> ExactFrom for U { #[inline] fn exact_from(value: T) -> U { U::try_from(value).ok().unwrap() } } impl> ExactInto for T { #[inline] fn exact_into(self) -> U { U::exact_from(self) } } /// Converts a value from one type to another. where if the conversion is not exact the result will /// wrap around. /// /// If `WrappingFrom` is implemented, it usually makes sense to implement [`OverflowingFrom`] as /// well. pub trait WrappingFrom: Sized { fn wrapping_from(value: T) -> Self; } /// Converts a value from one type to another, where if the conversion is not exact the result will /// wrap around. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`WrappingFrom`] is implemented. pub trait WrappingInto: Sized { fn wrapping_into(self) -> T; } impl> WrappingInto for T { #[inline] fn wrapping_into(self) -> U { U::wrapping_from(self) } } /// Converts a value from one type to another, where if the conversion is not exact the result is /// set to the maximum or minimum value of the result type, whichever is closer. pub trait SaturatingFrom: Sized { fn saturating_from(value: T) -> Self; } /// Converts a value from one type to another, where if the conversion is not exact the result is /// set to the maximum or minimum value of the result type, whichever is closer. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`SaturatingFrom`] is implemented. pub trait SaturatingInto: Sized { fn saturating_into(self) -> T; } impl> SaturatingInto for T { #[inline] fn saturating_into(self) -> U { U::saturating_from(self) } } /// Converts a value from one type to another, where if the conversion is not exact the result will /// wrap around. The result is returned along with a [`bool`] that indicates whether wrapping has /// occurred. /// /// If `OverflowingFrom` is implemented, it usually makes sense to implement [`WrappingFrom`] as /// well. pub trait OverflowingFrom: Sized { fn overflowing_from(value: T) -> (Self, bool); } /// Converts a value from one type to another, where if the conversion is not exact the result will /// wrap around. The result is returned along with a [`bool`] that indicates whether wrapping has /// occurred. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`OverflowingFrom`] is implemented. pub trait OverflowingInto: Sized { fn overflowing_into(self) -> (T, bool); } impl> OverflowingInto for T { #[inline] fn overflowing_into(self) -> (U, bool) { U::overflowing_from(self) } } /// Converts a value from one type to another, where the conversion is made according to a specified /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. pub trait RoundingFrom: Sized { fn rounding_from(value: T, rm: RoundingMode) -> (Self, Ordering); } /// Converts a value from one type to another, where the conversion is made according to a specified /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// It is recommended that this trait is not implemented directly; it is automatically implemented /// when [`RoundingFrom`] is implemented. pub trait RoundingInto: Sized { fn rounding_into(self, rm: RoundingMode) -> (T, Ordering); } impl> RoundingInto for T { #[inline] fn rounding_into(self, rm: RoundingMode) -> (U, Ordering) { U::rounding_from(self, rm) } } /// Tests whether a value of one type is convertible into a value of another. /// /// If `ConvertibleFrom` for `Self` is implemented, it usually makes sense to implement /// [`TryFrom`] for `T` as well. pub trait ConvertibleFrom { fn convertible_from(value: T) -> bool; } /// Associates with `Self` a type that's half `Self`'s size. pub trait HasHalf { /// The type that's half the size of `Self`. type Half; } /// Provides a function to join two pieces into a number. For example, two [`u32`]s may be joined to /// form a [`u64`]. pub trait JoinHalves: HasHalf { /// Joins two values into a single value; the upper, or most-significant, half comes first. fn join_halves(upper: Self::Half, lower: Self::Half) -> Self; } /// Provides functions to split a number into two pieces. For example, a [`u64`] may be split into /// two [`u32`]s. pub trait SplitInHalf: HasHalf { /// Extracts the lower, or least-significant, half of a number. fn lower_half(&self) -> Self::Half; /// Extracts the upper, or most-significant half of a number. fn upper_half(&self) -> Self::Half; /// Extracts both halves of a number; the upper, or most-significant, half comes first. /// /// # Worst-case complexity /// $T(n) = O(\max(T_U(n), T_L(n)))$ /// /// $M(n) = O(\max(M_U(n), M_L(n)))$ /// /// where $T$ is time, $M$ is additional memory, $T_U$ and $T_L$ are the time complexities of /// the [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions, /// respectively, and $M_U$ and $M_L$ are the memory complexities of the /// [`upper_half`](Self::upper_half) and [`lower_half`](Self::lower_half) functions, /// respectively. #[inline] fn split_in_half(&self) -> (Self::Half, Self::Half) { (self.upper_half(), self.lower_half()) } } /// Determines whether a number is an integer. pub trait IsInteger { #[allow(clippy::wrong_self_convention)] fn is_integer(self) -> bool; } /// Converts a number to or from a raw mantissa and exponent. /// /// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of raw mantissa and /// exponent. pub trait RawMantissaAndExponent: Sized { /// Extracts the raw mantissa and exponent from a number. fn raw_mantissa_and_exponent(self) -> (M, E); /// Extracts the raw mantissa from a number. fn raw_mantissa(self) -> M { self.raw_mantissa_and_exponent().0 } /// Extracts the raw exponent from a number. fn raw_exponent(self) -> E { self.raw_mantissa_and_exponent().1 } /// Constructs a number from its raw mantissa and exponent. fn from_raw_mantissa_and_exponent(raw_mantissa: M, raw_exponent: E) -> T; } /// Converts a number to or from an integer mantissa and exponent. /// /// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of integer mantissa and /// exponent. /// /// The mantissa is an odd integer, and the exponent is an integer, such that $x = 2^em$. pub trait IntegerMantissaAndExponent: Sized { /// Extracts the integer mantissa and exponent from a number. fn integer_mantissa_and_exponent(self) -> (M, E); /// Extracts the integer mantissa from a number. fn integer_mantissa(self) -> M { self.integer_mantissa_and_exponent().0 } /// Extracts the integer exponent from a number. fn integer_exponent(self) -> E { self.integer_mantissa_and_exponent().1 } /// Constructs a number from its integer mantissa and exponent. fn from_integer_mantissa_and_exponent(integer_mantissa: M, integer_exponent: E) -> Option; } /// Converts a number to or from a scientific mantissa and exponent. /// /// See [here](crate::num::basic::floats::PrimitiveFloat) for a definition of scientific mantissa /// and exponent. pub trait SciMantissaAndExponent: Sized { /// Extracts the scientific mantissa and exponent from a number. fn sci_mantissa_and_exponent(self) -> (M, E); /// Extracts the scientific mantissa from a number. fn sci_mantissa(self) -> M { self.sci_mantissa_and_exponent().0 } /// Extracts the scientific exponent from a number. fn sci_exponent(self) -> E { self.sci_mantissa_and_exponent().1 } /// Constructs a number from its scientific mantissa and exponent. fn from_sci_mantissa_and_exponent(sci_mantissa: M, sci_exponent: E) -> Option; } /// Converts a slice of one type of value to a single value of another type. pub trait FromOtherTypeSlice { fn from_other_type_slice(slice: &[T]) -> Self; } /// Converts a slice of one type of value to a [`Vec`] of another type. pub trait VecFromOtherTypeSlice: Sized { fn vec_from_other_type_slice(slice: &[T]) -> Vec; } /// Converts a slice of one type of value to a [`Vec`] of another type. pub trait VecFromOtherType: Sized { fn vec_from_other_type(value: T) -> Vec; } ================================================ FILE: malachite-base/src/num/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::iterators::{NonzeroValues, nonzero_values}; use crate::num::arithmetic::traits::{PowerOf2, RoundToMultipleOfPowerOf2}; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::float::NiceFloat; use crate::num::iterators::{RulerSequence, ruler_sequence}; use crate::num::logic::traits::{BitAccess, NotAssign, SignificantBits}; use crate::rounding_modes::RoundingMode::*; use crate::tuples::exhaustive::{ ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, LexDependentPairs, exhaustive_dependent_pairs, lex_dependent_pairs, }; use alloc::vec::IntoIter; use alloc::vec::Vec; use core::iter::{Chain, Once, Rev, once}; use core::marker::PhantomData; use itertools::{Interleave, Itertools}; /// Generates all primitive integers in an interval. /// /// This `struct` is created by [`primitive_int_increasing_range`] and /// [`primitive_int_increasing_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PrimitiveIntIncreasingRange { a: Option, b: Option, } impl Iterator for PrimitiveIntIncreasingRange { type Item = T; fn next(&mut self) -> Option { if self.a == self.b { None } else { let result = self.a; self.a = result.and_then(|x| x.checked_add(T::ONE)); result } } } impl DoubleEndedIterator for PrimitiveIntIncreasingRange { fn next_back(&mut self) -> Option { if self.a == self.b { None } else { self.b = Some(self.b.map_or(T::MAX, |b| b - T::ONE)); self.b } } } /// Generates all values of a signed integer type in an interval, in order of increasing absolute /// value. /// /// This `enum` is created by [`exhaustive_signed_range`] and [`exhaustive_signed_inclusive_range`]; /// see their documentation for more. #[derive(Clone, Debug)] pub enum ExhaustiveSignedRange { NonNegative(PrimitiveIntIncreasingRange), NonPositive(Rev>), BothSigns(ExhaustiveSigneds), } impl Iterator for ExhaustiveSignedRange { type Item = T; fn next(&mut self) -> Option { match self { Self::NonNegative(xs) => xs.next(), Self::NonPositive(xs) => xs.next(), Self::BothSigns(xs) => xs.next(), } } } #[doc(hidden)] pub type PrimitiveIntUpDown = Interleave, Rev>>; /// Generates all unsigned integers in ascending order. /// /// The output is $(k)_{k=0}^{2^W-1}$, where $W$ is the width of the type. /// /// The output length is $2^W$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// /// assert_eq!( /// prefix_to_string(exhaustive_unsigneds::(), 10), /// "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]" /// ) /// ``` #[inline] pub fn exhaustive_unsigneds() -> PrimitiveIntIncreasingRange { primitive_int_increasing_inclusive_range(T::ZERO, T::MAX) } /// Generates all positive primitive integers in ascending order. /// /// Let $L=2^W-1$ if `T` is unsigned and $L=2^{W-1}-1$ if `T` is signed, where $W$ is the width of /// the type. /// /// The output is $(k)_{k=1}^{L}$. /// /// The output length is $L$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_positive_primitive_ints; /// /// assert_eq!( /// prefix_to_string(exhaustive_positive_primitive_ints::(), 10), /// "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]" /// ) /// ``` #[inline] pub fn exhaustive_positive_primitive_ints() -> PrimitiveIntIncreasingRange { primitive_int_increasing_inclusive_range(T::ONE, T::MAX) } pub type ExhaustiveSigneds = Chain, PrimitiveIntUpDown>; /// Generates all signed integers in order of increasing absolute value. /// /// When two numbers have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [-2^{W-1}, 2^{W-1})$, where $W$ is the width of /// the type, and $i < j$. /// /// The output length is $2^W$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_signeds; /// /// assert_eq!( /// prefix_to_string(exhaustive_signeds::(), 10), /// "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, ...]" /// ) /// ``` #[inline] pub fn exhaustive_signeds() -> ExhaustiveSigneds { once(T::ZERO).chain(exhaustive_nonzero_signeds()) } /// Generates all natural (non-negative) signed integers in ascending order. /// /// The output is $(k)_{k=0}^{2^{W-1}-1}$, where $W$ is the width of the type. /// /// The output length is $2^{W-1}$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_natural_signeds; /// /// assert_eq!( /// prefix_to_string(exhaustive_natural_signeds::(), 10), /// "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]" /// ) /// ``` #[inline] pub fn exhaustive_natural_signeds() -> PrimitiveIntIncreasingRange { primitive_int_increasing_inclusive_range(T::ZERO, T::MAX) } /// Generates all negative signed integers in descending order. /// /// The output is $(-k)_{k=1}^{2^{W-1}}$, where $W$ is the width of the type. /// /// The output length is $2^{W-1}$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_negative_signeds; /// /// assert_eq!( /// prefix_to_string(exhaustive_negative_signeds::(), 10), /// "[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, ...]" /// ) /// ``` #[inline] pub fn exhaustive_negative_signeds() -> Rev> { primitive_int_increasing_range(T::MIN, T::ZERO).rev() } /// Generates all nonzero signed integers in order of increasing absolute value. /// /// When two numbers have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [-2^{W-1}, 2^{W-1}) \\setminus \\{0\\}$, where /// $W$ is the width of the type, and $i < j$. /// /// The output length is $2^W-1$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_nonzero_signeds; /// /// assert_eq!( /// prefix_to_string(exhaustive_nonzero_signeds::(), 10), /// "[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, ...]" /// ) /// ``` #[inline] pub fn exhaustive_nonzero_signeds() -> PrimitiveIntUpDown { exhaustive_positive_primitive_ints().interleave(exhaustive_negative_signeds()) } /// Generates all primitive integers in the half-open interval $[a, b)$, in ascending order. /// /// $a$ must be less than or equal to $b$. If $a$ and $b$ are equal, the range is empty. This /// function cannot create a range that includes `T::MAX`; for that, use /// [`primitive_int_increasing_inclusive_range`]. /// /// The output is $(k)_{k=a}^{b-1}$. /// /// The output length is $b - a$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::primitive_int_increasing_range; /// /// assert_eq!( /// primitive_int_increasing_range::(-5, 5).collect_vec(), /// &[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] /// ) /// ``` #[inline] pub fn primitive_int_increasing_range( a: T, b: T, ) -> PrimitiveIntIncreasingRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); PrimitiveIntIncreasingRange { a: Some(a), b: Some(b), } } /// Generates all primitive integers in the closed interval $[a, b]$, in ascending order. /// /// $a$ must be less than or equal to $b$. If $a$ and $b$ are equal, the range contains a single /// element. /// /// The output is $(k)_{k=a}^{b}$. /// /// The output length is $b - a + 1$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::primitive_int_increasing_inclusive_range; /// /// assert_eq!( /// primitive_int_increasing_inclusive_range::(-5, 5).collect_vec(), /// &[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5] /// ) /// ``` #[inline] pub fn primitive_int_increasing_inclusive_range( a: T, b: T, ) -> PrimitiveIntIncreasingRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); PrimitiveIntIncreasingRange { a: Some(a), b: b.checked_add(T::ONE), } } /// Generates all signed integers in the half-open interval $[a, b)$, in order of increasing /// absolute value. /// /// When two numbers have the same absolute value, the positive one comes first. $a$ must be less /// than or equal to $b$. If $a$ and $b$ are equal, the range is empty. This function cannot create /// a range that includes `T::MAX`; for that, use [`exhaustive_signed_inclusive_range`]. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [0, b - a)$ and $i < j$. /// /// The output length is $b - a$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_signed_range; /// /// assert_eq!( /// exhaustive_signed_range::(-5, 5).collect_vec(), /// &[0, 1, -1, 2, -2, 3, -3, 4, -4, -5] /// ) /// ``` pub fn exhaustive_signed_range(a: T, b: T) -> ExhaustiveSignedRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= T::ZERO { ExhaustiveSignedRange::NonNegative(primitive_int_increasing_range(a, b)) } else if b <= T::ZERO { ExhaustiveSignedRange::NonPositive(primitive_int_increasing_range(a, b).rev()) } else { ExhaustiveSignedRange::BothSigns( once(T::ZERO).chain( primitive_int_increasing_range(T::ONE, b) .interleave(primitive_int_increasing_range(a, T::ZERO).rev()), ), ) } } /// Generates all signed integers in the closed interval $[a, b]$, in order of increasing absolute /// value. /// /// When two numbers have the same absolute value, the positive one comes first. $a$ must be less /// than or equal to $b$. If $a$ and $b$ are equal, the range contains a single element. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [0, b - a]$ and $i < j$. /// /// The output length is $b - a + 1$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_signed_inclusive_range; /// /// assert_eq!( /// exhaustive_signed_inclusive_range::(-5, 5).collect_vec(), /// &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5] /// ) /// ``` pub fn exhaustive_signed_inclusive_range( a: T, b: T, ) -> ExhaustiveSignedRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= T::ZERO { ExhaustiveSignedRange::NonNegative(primitive_int_increasing_inclusive_range(a, b)) } else if b <= T::ZERO { ExhaustiveSignedRange::NonPositive(primitive_int_increasing_inclusive_range(a, b).rev()) } else { ExhaustiveSignedRange::BothSigns( once(T::ZERO).chain( primitive_int_increasing_inclusive_range(T::ONE, b) .interleave(primitive_int_increasing_inclusive_range(a, T::NEGATIVE_ONE).rev()), ), ) } } /// Generates all primitive floats in an interval, in increasing order. /// /// This `struct` implements [`DoubleEndedIterator`], so you can reverse it to generate floats in /// decreasing order. /// /// Positive zero and negative zero are both generated. Negative zero is considered to be less than /// positive zero. /// /// This `struct` is created by [`primitive_float_increasing_range`] and /// [`primitive_float_increasing_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PrimitiveFloatIncreasingRange { phantom: PhantomData<*const T>, xs: PrimitiveIntIncreasingRange, } impl Iterator for PrimitiveFloatIncreasingRange { type Item = T; #[inline] fn next(&mut self) -> Option { self.xs.next().map(T::from_ordered_representation) } } impl DoubleEndedIterator for PrimitiveFloatIncreasingRange { #[inline] fn next_back(&mut self) -> Option { self.xs.next_back().map(T::from_ordered_representation) } } /// Generates all primitive floats in the half-open interval $[a, b)$, in ascending order. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// `NiceFloat(a)` must be less than or equal to `NiceFloat(b)`. If `NiceFloat(a)` and /// `NiceFloat(b)` are equal, the range is empty. This function cannot create a range that includes /// `INFINITY`; for that, use [`primitive_float_increasing_inclusive_range`]. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=\varphi(a)}^{\varphi(b)-1}$. /// /// The output length is $\varphi(b) - \varphi(a)$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `NiceFloat(a) > NiceFloat(b)`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::primitive_float_increasing_range; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// primitive_float_increasing_range::(1.0, 2.0).map(NiceFloat), /// 20 /// ), /// "[1.0, 1.0000001, 1.0000002, 1.0000004, 1.0000005, 1.0000006, 1.0000007, 1.0000008, \ /// 1.000001, 1.0000011, 1.0000012, 1.0000013, 1.0000014, 1.0000015, 1.0000017, 1.0000018, \ /// 1.0000019, 1.000002, 1.0000021, 1.0000023, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// primitive_float_increasing_range::(1.0, 2.0) /// .rev() /// .map(NiceFloat), /// 20, /// ), /// "[1.9999999, 1.9999998, 1.9999996, 1.9999995, 1.9999994, 1.9999993, 1.9999992, 1.999999, \ /// 1.9999989, 1.9999988, 1.9999987, 1.9999986, 1.9999985, 1.9999983, 1.9999982, 1.9999981, \ /// 1.999998, 1.9999979, 1.9999977, 1.9999976, ...]", /// ); /// ``` pub fn primitive_float_increasing_range( a: T, b: T, ) -> PrimitiveFloatIncreasingRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!( NiceFloat(a) <= NiceFloat(b), "a must be less than or equal to b. a: {}, b: {}", NiceFloat(a), NiceFloat(b) ); PrimitiveFloatIncreasingRange { phantom: PhantomData, xs: primitive_int_increasing_range( a.to_ordered_representation(), b.to_ordered_representation(), ), } } /// Generates all primitive floats in the closed interval $[a, b]$, in ascending order. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// `NiceFloat(a)` must be less than or equal to `NiceFloat(b)`. If `NiceFloat(a)` and /// `NiceFloat(b)` are equal, the range contains a single element. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=\varphi(a)}^\varphi(b)$. /// /// The output length is $\varphi(b) - \varphi(a) + 1$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `NiceFloat(a) > NiceFloat(b)`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::primitive_float_increasing_inclusive_range; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// primitive_float_increasing_inclusive_range::(1.0, 2.0).map(NiceFloat), /// 20 /// ), /// "[1.0, 1.0000001, 1.0000002, 1.0000004, 1.0000005, 1.0000006, 1.0000007, 1.0000008, \ /// 1.000001, 1.0000011, 1.0000012, 1.0000013, 1.0000014, 1.0000015, 1.0000017, 1.0000018, \ /// 1.0000019, 1.000002, 1.0000021, 1.0000023, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// primitive_float_increasing_inclusive_range::(1.0, 2.0) /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[2.0, 1.9999999, 1.9999998, 1.9999996, 1.9999995, 1.9999994, 1.9999993, 1.9999992, \ /// 1.999999, 1.9999989, 1.9999988, 1.9999987, 1.9999986, 1.9999985, 1.9999983, 1.9999982, \ /// 1.9999981, 1.999998, 1.9999979, 1.9999977, ...]" /// ); /// ``` pub fn primitive_float_increasing_inclusive_range( a: T, b: T, ) -> PrimitiveFloatIncreasingRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!( NiceFloat(a) <= NiceFloat(b), "a must be less than or equal to b. a: {}, b: {}", NiceFloat(a), NiceFloat(b) ); PrimitiveFloatIncreasingRange { phantom: PhantomData, xs: primitive_int_increasing_inclusive_range( a.to_ordered_representation(), b.to_ordered_representation(), ), } } /// Generates all finite positive primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// [`MIN_POSITIVE_SUBNORMAL`](super::basic::floats::PrimitiveFloat::MIN_POSITIVE_SUBNORMAL) is /// generated first and [`MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is /// generated last. The returned iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=2^M(2^E-1)+2}^{2^{M+1}(2^E-1)}$. /// /// The output length is $2^M(2^E-1)-1$. /// - For [`f32`], this is $2^{31}-2^{23}-1$, or 2139095039. /// - For [`f64`], this is $2^{63}-2^{52}-1$, or 9218868437227405311. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::positive_finite_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// positive_finite_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[1.0e-45, 3.0e-45, 4.0e-45, 6.0e-45, 7.0e-45, 8.0e-45, 1.0e-44, 1.1e-44, 1.3e-44, \ /// 1.4e-44, 1.5e-44, 1.7e-44, 1.8e-44, 2.0e-44, 2.1e-44, 2.2e-44, 2.4e-44, 2.5e-44, 2.7e-44, \ /// 2.8e-44, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// positive_finite_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, 3.4028225e38, \ /// 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, 3.4028212e38, \ /// 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, 3.40282e38, \ /// 3.4028198e38, 3.4028196e38, ...]" /// ); /// ``` #[inline] pub fn positive_finite_primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(T::MIN_POSITIVE_SUBNORMAL, T::MAX_FINITE) } /// Generates all finite negative primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// [`-MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is generated first and /// [`-MIN_POSITIVE_SUBNORMAL`](super::basic::floats::PrimitiveFloat::MIN_POSITIVE_SUBNORMAL) is /// generated last. The returned iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=1}^{2^M(2^E-1)-1}$. /// /// The output length is $2^M(2^E-1)-1$. /// - For [`f32`], this is $2^{31}-2^{23}-1$, or 2139095039. /// - For [`f64`], this is $2^{63}-2^{52}-1$, or 9218868437227405311. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::negative_finite_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// negative_finite_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[-3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, -3.4028196e38, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// negative_finite_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[-1.0e-45, -3.0e-45, -4.0e-45, -6.0e-45, -7.0e-45, -8.0e-45, -1.0e-44, -1.1e-44, \ /// -1.3e-44, -1.4e-44, -1.5e-44, -1.7e-44, -1.8e-44, -2.0e-44, -2.1e-44, -2.2e-44, -2.4e-44, \ /// -2.5e-44, -2.7e-44, -2.8e-44, ...]" /// ); /// ``` #[inline] pub fn negative_finite_primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(-T::MAX_FINITE, -T::MIN_POSITIVE_SUBNORMAL) } /// Generates all finite nonzero primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// [-`MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is generated first and /// [`MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is generated last. The returned /// iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is /// $$ /// (\varphi^{-1}(k))_ {k=1}^{2^M(2^E-1)-1} ⧺ (\varphi^{-1}(k))_ {k=2^M(2^E-1)+2}^{2^{M+1}(2^E-1)} /// $$. /// /// The output length is $2^{M+1}(2^E-1)-2$. /// - For [`f32`], this is $2^{32}-2^{24}-2$, or 4278190078. /// - For [`f64`], this is $2^{64}-2^{53}-2$, or 18437736874454810622. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::nonzero_finite_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// nonzero_finite_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[-3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, -3.4028196e38, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// nonzero_finite_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, 3.4028225e38, \ /// 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, 3.4028212e38, \ /// 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, 3.40282e38, \ /// 3.4028198e38, 3.4028196e38, ...]" /// ); /// ``` #[inline] pub fn nonzero_finite_primitive_floats_increasing() -> NonzeroValues> { nonzero_values(finite_primitive_floats_increasing()) } /// Generates all finite primitive floats, in ascending order. /// /// Positive and negative zero are both included. Negative zero comes first. /// /// [`-MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is generated first and /// [`MAX_FINITE`](super::basic::floats::PrimitiveFloat::MAX_FINITE) is generated last. The /// returned iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=1}^{2^{M+1}(2^E-1)}$. /// /// The output length is $2^{M+1}(2^E-1)$. /// - For [`f32`], this is $2^{32}-2^{24}$, or 4278190080. /// - For [`f64`], this is $2^{64}-2^{53}$, or 18437736874454810624. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::finite_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// finite_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[-3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, -3.4028196e38, ...]", /// ); /// assert_eq!( /// prefix_to_string( /// finite_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, 3.4028225e38, \ /// 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, 3.4028212e38, \ /// 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, 3.40282e38, \ /// 3.4028198e38, 3.4028196e38, ...]" /// ); /// ``` #[inline] pub fn finite_primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(-T::MAX_FINITE, T::MAX_FINITE) } /// Generates all positive primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// [`MIN_POSITIVE_SUBNORMAL`](super::basic::floats::PrimitiveFloat::MIN_POSITIVE_SUBNORMAL) is /// generated first and `INFINITY` is generated last. The returned iterator is /// double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=2^M(2^E-1)+2}^{2^{M+1}(2^E-1)+1}$. /// /// The output length is $2^M(2^E-1)$. /// - For [`f32`], this is $2^{31}-2^{23}$, or 2139095040. /// - For [`f64`], this is $2^{63}-2^{52}$, or 9218868437227405312. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::positive_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// positive_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[1.0e-45, 3.0e-45, 4.0e-45, 6.0e-45, 7.0e-45, 8.0e-45, 1.0e-44, 1.1e-44, 1.3e-44, \ /// 1.4e-44, 1.5e-44, 1.7e-44, 1.8e-44, 2.0e-44, 2.1e-44, 2.2e-44, 2.4e-44, 2.5e-44, 2.7e-44, \ /// 2.8e-44, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// positive_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[Infinity, 3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, \ /// 3.4028225e38, 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, \ /// 3.4028212e38, 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, \ /// 3.40282e38, 3.4028198e38, ...]" /// ); /// ``` #[inline] pub fn positive_primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(T::MIN_POSITIVE_SUBNORMAL, T::INFINITY) } /// Generates all negative primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// `NEGATIVE_INFINITY` is generated first and /// [`-MIN_POSITIVE_SUBNORMAL`](super::basic::floats::PrimitiveFloat::MIN_POSITIVE_SUBNORMAL) is /// generated last. The returned iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=0}^{2^M(2^E-1)-1}$. /// /// The output length is $2^M(2^E-1)$. /// - For [`f32`], this is $2^{31}-2^{23}$, or 2139095040. /// - For [`f64`], this is $2^{63}-2^{52}$, or 9218868437227405312. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::negative_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// negative_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[-Infinity, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// negative_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[-1.0e-45, -3.0e-45, -4.0e-45, -6.0e-45, -7.0e-45, -8.0e-45, -1.0e-44, -1.1e-44, \ /// -1.3e-44, -1.4e-44, -1.5e-44, -1.7e-44, -1.8e-44, -2.0e-44, -2.1e-44, -2.2e-44, -2.4e-44, \ /// -2.5e-44, -2.7e-44, -2.8e-44, ...]" /// ); /// ``` #[inline] pub fn negative_primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(T::NEGATIVE_INFINITY, -T::MIN_POSITIVE_SUBNORMAL) } /// Generates all nonzero primitive floats, in ascending order. /// /// Positive and negative zero are both excluded. /// /// `NEGATIVE_INFINITY` is generated first and `INFINITY` is generated last. The returned /// iterator is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is /// $$ /// (\varphi^{-1}(k))_ {k=0}^{2^M(2^E-1)-1} ⧺ (\varphi^{-1}(k))_ /// {k=2^M(2^E-1)+2}^{2^{M+1}(2^E-1)+1} $$. /// /// The output length is $2^{M+1}(2^E-1)$. /// - For [`f32`], this is $2^{32}-2^{24}$, or 4278190080. /// - For [`f64`], this is $2^{64}-2^{53}$, or 18437736874454810624. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::nonzero_primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// nonzero_primitive_floats_increasing::().map(NiceFloat), /// 20 /// ), /// "[-Infinity, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// nonzero_primitive_floats_increasing::() /// .rev() /// .map(NiceFloat), /// 20 /// ), /// "[Infinity, 3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, \ /// 3.4028225e38, 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, \ /// 3.4028212e38, 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, \ /// 3.40282e38, 3.4028198e38, ...]" /// ); /// ``` #[inline] pub fn nonzero_primitive_floats_increasing() -> NonzeroValues> { nonzero_values(primitive_floats_increasing()) } /// Generates all primitive floats, except `NaN`, in ascending order. /// /// Positive and negative zero are both included. Negative zero comes first. /// /// `NEGATIVE_INFINITY` is generated first and `INFINITY` is generated last. The returned iterator /// is double-ended, so it may be reversed. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output is $(\varphi^{-1}(k))_{k=0}^{2^{M+1}(2^E-1)+1}$. /// /// The output length is $2^{M+1}(2^E-1)+2$. /// - For [`f32`], this is $2^{32}-2^{24}+2$, or 4278190082. /// - For [`f64`], this is $2^{64}-2^{53}+2$, or 18437736874454810626. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::primitive_floats_increasing; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string(primitive_floats_increasing::().map(NiceFloat), 20), /// "[-Infinity, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, \ /// -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, \ /// -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, \ /// -3.40282e38, -3.4028198e38, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// primitive_floats_increasing::().rev().map(NiceFloat), /// 20 /// ), /// "[Infinity, 3.4028235e38, 3.4028233e38, 3.402823e38, 3.4028229e38, 3.4028227e38, \ /// 3.4028225e38, 3.4028222e38, 3.402822e38, 3.4028218e38, 3.4028216e38, 3.4028214e38, \ /// 3.4028212e38, 3.402821e38, 3.4028208e38, 3.4028206e38, 3.4028204e38, 3.4028202e38, \ /// 3.40282e38, 3.4028198e38, ...]" /// ); /// ``` pub fn primitive_floats_increasing() -> PrimitiveFloatIncreasingRange { primitive_float_increasing_inclusive_range(T::NEGATIVE_INFINITY, T::INFINITY) } /// Generates all finite positive primitive floats with a specified `sci_exponent` and precision. /// /// This `struct` is created by [`exhaustive_primitive_floats_with_sci_exponent_and_precision`]; see /// its documentation for more. #[derive(Clone, Debug, Default)] pub struct ConstantPrecisionPrimitiveFloats { phantom: PhantomData<*const T>, n: u64, increment: u64, i: u64, count: u64, } impl Iterator for ConstantPrecisionPrimitiveFloats { type Item = T; fn next(&mut self) -> Option { if self.i == self.count { None } else { let out = T::from_bits(self.n); self.i += 1; if self.i < self.count { self.n += self.increment; } Some(out) } } } /// Generates all finite positive primitive floats with a specified `sci_exponent` and precision. /// /// Positive and negative zero are both excluded. /// /// A finite positive primitive float may be uniquely expressed as $x = m_s2^e_s$, where $1 \leq m_s /// < 2$ and $e_s$ is an integer; then $e_s$ is the sci-exponent. An integer $e_s$ occurs as the /// sci-exponent of a float iff $2-2^{E-1}-M \leq e_s < 2^{E-1}$. /// /// In the above equation, $m$ is a dyadic rational. Let $p$ be the smallest integer such that /// $m2^{p-1}$ is an integer. Then $p$ is the float's precision. It is also the number of /// significant bits. /// /// For example, consider the float $100.0$. It may be written as $\frac{25}{16}2^6$, so /// $m=\frac{25}{16}$ and $e=6$. We can write $m$ in binary as $1.1001_2$. Thus, the sci-exponent is /// 6 and the precision is 5. /// /// If $p$ is 1, the output length is 1; otherwise, it is $2^{p-2}$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if the sci-exponent is less than /// [`MIN_EXPONENT`](super::basic::floats::PrimitiveFloat::MIN_EXPONENT) or greater than /// [`MAX_EXPONENT`](super::basic::floats::PrimitiveFloat::MAX_EXPONENT), or if the precision is /// zero or too large for the given sci-exponent (this can be checked using /// [`max_precision_for_sci_exponent`](super::basic::floats::PrimitiveFloat::max_precision_for_sci_exponent)). /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::*; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// exhaustive_primitive_floats_with_sci_exponent_and_precision::(0, 3) /// .map(NiceFloat) /// .collect_vec(), /// [1.25, 1.75].iter().copied().map(NiceFloat).collect_vec() /// ); /// assert_eq!( /// exhaustive_primitive_floats_with_sci_exponent_and_precision::(0, 5) /// .map(NiceFloat) /// .collect_vec(), /// [1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375] /// .iter() /// .copied() /// .map(NiceFloat) /// .collect_vec() /// ); /// assert_eq!( /// exhaustive_primitive_floats_with_sci_exponent_and_precision::(6, 5) /// .map(NiceFloat) /// .collect_vec(), /// [68.0, 76.0, 84.0, 92.0, 100.0, 108.0, 116.0, 124.0] /// .iter() /// .copied() /// .map(NiceFloat) /// .collect_vec() /// ); /// ``` pub fn exhaustive_primitive_floats_with_sci_exponent_and_precision( sci_exponent: i64, precision: u64, ) -> ConstantPrecisionPrimitiveFloats { assert!(sci_exponent >= T::MIN_EXPONENT); assert!(sci_exponent <= T::MAX_EXPONENT); assert_ne!(precision, 0); let max_precision = T::max_precision_for_sci_exponent(sci_exponent); assert!(precision <= max_precision); let increment = u64::power_of_2(max_precision - precision + 1); let first_mantissa = if precision == 1 { 1 } else { u64::power_of_2(precision - 1) | 1 }; let first = T::from_integer_mantissa_and_exponent( first_mantissa, sci_exponent - i64::exact_from(precision) + 1, ) .unwrap() .to_bits(); let count = if precision == 1 { 1 } else { u64::power_of_2(precision - 2) }; ConstantPrecisionPrimitiveFloats { phantom: PhantomData, n: first, increment, i: 0, count, } } #[derive(Clone, Debug)] struct PrimitiveFloatsWithExponentGenerator { phantom: PhantomData<*const T>, sci_exponent: i64, } impl ExhaustiveDependentPairsYsGenerator> for PrimitiveFloatsWithExponentGenerator { #[inline] fn get_ys(&self, &precision: &u64) -> ConstantPrecisionPrimitiveFloats { exhaustive_primitive_floats_with_sci_exponent_and_precision(self.sci_exponent, precision) } } #[inline] fn exhaustive_primitive_floats_with_sci_exponent_helper( sci_exponent: i64, ) -> LexDependentPairs< u64, T, PrimitiveFloatsWithExponentGenerator, PrimitiveIntIncreasingRange, ConstantPrecisionPrimitiveFloats, > { lex_dependent_pairs( primitive_int_increasing_inclusive_range( 1, T::max_precision_for_sci_exponent(sci_exponent), ), PrimitiveFloatsWithExponentGenerator { phantom: PhantomData, sci_exponent, }, ) } /// Generates all positive finite primitive floats with a specified `sci_exponent`. /// /// This `struct` is created by [`exhaustive_primitive_floats_with_sci_exponent`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustivePrimitiveFloatsWithExponent( LexDependentPairs< u64, T, PrimitiveFloatsWithExponentGenerator, PrimitiveIntIncreasingRange, ConstantPrecisionPrimitiveFloats, >, ); impl Iterator for ExhaustivePrimitiveFloatsWithExponent { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all positive finite primitive floats with a specified sci-exponent. /// /// Positive and negative zero are both excluded. /// /// A finite positive primitive float may be uniquely expressed as $x = m_s2^e_s$, where $1 \leq m_s /// < 2$ and $e_s$ is an integer; then $e$ is the sci-exponent. An integer $e_s$ occurs as the /// sci-exponent of a float iff $2-2^{E-1}-M \leq e_s < 2^{E-1}$. /// /// If $e_s \geq 2-2^{E-1}$ (the float is normal), the output length is $2^M$. /// - For [`f32`], this is $2^{23}$, or 8388608. /// - For [`f64`], this is $2^{52}$, or 4503599627370496. /// /// If $e_s < 2-2^{E-1}$ (the float is subnormal), the output length is $2^{e_s+2^{E-1}+M-2}$. /// - For [`f32`], this is $2^{e_s+149}$. /// - For [`f64`], this is $2^{e_s+1074}$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if the sci-exponent is less than /// [`MIN_EXPONENT`](super::basic::floats::PrimitiveFloat::MIN_EXPONENT) or greater than /// [`MAX_EXPONENT`](super::basic::floats::PrimitiveFloat::MAX_EXPONENT). /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_primitive_floats_with_sci_exponent; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_primitive_floats_with_sci_exponent::(0).map(NiceFloat), /// 20 /// ), /// "[1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, \ /// 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, ...]", /// ); /// assert_eq!( /// prefix_to_string( /// exhaustive_primitive_floats_with_sci_exponent::(4).map(NiceFloat), /// 20 /// ), /// "[16.0, 24.0, 20.0, 28.0, 18.0, 22.0, 26.0, 30.0, 17.0, 19.0, 21.0, 23.0, 25.0, 27.0, \ /// 29.0, 31.0, 16.5, 17.5, 18.5, 19.5, ...]" /// ); /// assert_eq!( /// exhaustive_primitive_floats_with_sci_exponent::(-147) /// .map(NiceFloat) /// .collect_vec(), /// [6.0e-45, 8.0e-45, 7.0e-45, 1.0e-44] /// .iter() /// .copied() /// .map(NiceFloat) /// .collect_vec() /// ); /// ``` #[inline] pub fn exhaustive_primitive_floats_with_sci_exponent( sci_exponent: i64, ) -> ExhaustivePrimitiveFloatsWithExponent { ExhaustivePrimitiveFloatsWithExponent(exhaustive_primitive_floats_with_sci_exponent_helper( sci_exponent, )) } #[derive(Clone, Debug)] struct ExhaustivePositiveFinitePrimitiveFloatsGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for ExhaustivePositiveFinitePrimitiveFloatsGenerator { #[inline] fn get_ys(&self, &sci_exponent: &i64) -> ExhaustivePrimitiveFloatsWithExponent { exhaustive_primitive_floats_with_sci_exponent(sci_exponent) } } #[inline] fn exhaustive_positive_finite_primitive_floats_helper() -> ExhaustiveDependentPairs< i64, T, RulerSequence, ExhaustivePositiveFinitePrimitiveFloatsGenerator, ExhaustiveSignedRange, ExhaustivePrimitiveFloatsWithExponent, > { exhaustive_dependent_pairs( ruler_sequence(), exhaustive_signed_inclusive_range(T::MIN_EXPONENT, T::MAX_EXPONENT), ExhaustivePositiveFinitePrimitiveFloatsGenerator { phantom: PhantomData, }, ) } /// Generates all positive finite primitive floats. /// /// This `struct` is created by [`exhaustive_positive_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveFinitePrimitiveFloats( ExhaustiveDependentPairs< i64, T, RulerSequence, ExhaustivePositiveFinitePrimitiveFloatsGenerator, ExhaustiveSignedRange, ExhaustivePrimitiveFloatsWithExponent, >, ); impl Iterator for ExhaustivePositiveFinitePrimitiveFloats { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all positive finite primitive floats. /// /// Positive and negative zero are both excluded. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`positive_finite_primitive_floats_increasing`]. /// /// The output length is $2^M(2^E-1)-1$. /// - For [`f32`], this is $2^{31}-2^{23}-1$, or 2139095039. /// - For [`f64`], this is $2^{63}-2^{52}-1$, or 9218868437227405311. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_positive_finite_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_positive_finite_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, \ /// 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, \ /// 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, \ /// 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, 3.125, ...]" /// ); /// ``` #[inline] pub fn exhaustive_positive_finite_primitive_floats() -> ExhaustivePositiveFinitePrimitiveFloats { ExhaustivePositiveFinitePrimitiveFloats(exhaustive_positive_finite_primitive_floats_helper()) } /// Generates all negative finite primitive floats. /// /// This `struct` is created by [`exhaustive_negative_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveNegativeFinitePrimitiveFloats( ExhaustivePositiveFinitePrimitiveFloats, ); impl Iterator for ExhaustiveNegativeFinitePrimitiveFloats { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|f| -f) } } /// Generates all negative finite primitive floats. /// /// Positive and negative zero are both excluded. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`negative_finite_primitive_floats_increasing`]. /// /// The output length is $2^M(2^E-1)-1$. /// - For [`f32`], this is $2^{31}-2^{23}-1$, or 2139095039. /// - For [`f64`], this is $2^{63}-2^{52}-1$, or 9218868437227405311. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_negative_finite_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_negative_finite_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[-1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, -0.75, -1.625, \ /// -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, -1.4375, -6.0, \ /// -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, -2.125, \ /// -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, -0.6875, \ /// -1.40625, -2.875, -1.46875, -0.375, -1.53125, -3.125, ...]" /// ); /// ``` #[inline] pub fn exhaustive_negative_finite_primitive_floats() -> ExhaustiveNegativeFinitePrimitiveFloats { ExhaustiveNegativeFinitePrimitiveFloats(exhaustive_positive_finite_primitive_floats()) } /// Generates all nonzero finite primitive floats. /// /// This `struct` is created by [`exhaustive_nonzero_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveNonzeroFinitePrimitiveFloats { toggle: bool, xs: ExhaustivePositiveFinitePrimitiveFloats, x: T, } impl Iterator for ExhaustiveNonzeroFinitePrimitiveFloats { type Item = T; #[inline] fn next(&mut self) -> Option { self.toggle.not_assign(); Some(if self.toggle { self.x = self.xs.next().unwrap(); self.x } else { -self.x }) } } /// Generates all nonzero finite primitive floats. /// /// Positive and negative zero are both excluded. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`nonzero_finite_primitive_floats_increasing`]. /// /// The output length is $2^{M+1}(2^E-1)-2$. /// - For [`f32`], this is $2^{32}-2^{24}-2$, or 4278190078. /// - For [`f64`], this is $2^{64}-2^{53}-2$, or 18437736874454810622. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_nonzero_finite_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_nonzero_finite_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, \ /// -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, \ /// 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, \ /// 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, 1.5625, -1.5625, ...]" /// ); /// ``` #[inline] pub fn exhaustive_nonzero_finite_primitive_floats() -> ExhaustiveNonzeroFinitePrimitiveFloats { ExhaustiveNonzeroFinitePrimitiveFloats { toggle: false, xs: exhaustive_positive_finite_primitive_floats(), x: T::ZERO, } } pub type ExhaustiveFinitePrimitiveFloats = Chain, ExhaustiveNonzeroFinitePrimitiveFloats>; /// Generates all finite primitive floats. /// /// Positive and negative zero are both included. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`finite_primitive_floats_increasing`]. /// /// The output length is $2^{M+1}(2^E-1)$. /// - For [`f32`], this is $2^{32}-2^{24}$, or 4278190080. /// - For [`f64`], this is $2^{64}-2^{53}$, or 18437736874454810624. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_finite_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_finite_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, \ /// -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, \ /// 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, \ /// 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, ...]" /// ); /// ``` #[inline] pub fn exhaustive_finite_primitive_floats() -> Chain, ExhaustiveNonzeroFinitePrimitiveFloats> { ::alloc::vec![T::ZERO, T::NEGATIVE_ZERO] .into_iter() .chain(exhaustive_nonzero_finite_primitive_floats()) } /// Generates all positive primitive floats. /// /// Positive and negative zero are both excluded. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`positive_primitive_floats_increasing`]. /// /// The output length is $2^M(2^E-1)$. /// - For [`f32`], this is $2^{31}-2^{23}$, or 2139095040. /// - For [`f64`], this is $2^{63}-2^{52}$, or 9218868437227405312. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_positive_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_positive_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[Infinity, 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, \ /// 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, \ /// 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, \ /// 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, \ /// 1.53125, ...]" /// ); /// ``` #[inline] pub fn exhaustive_positive_primitive_floats() -> Chain, ExhaustivePositiveFinitePrimitiveFloats> { once(T::INFINITY).chain(exhaustive_positive_finite_primitive_floats()) } /// Generates all negative primitive floats. /// /// Positive and negative zero are both excluded. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`negative_primitive_floats_increasing`]. /// /// The output length is $2^M(2^E-1)$. /// - For [`f32`], this is $2^{31}-2^{23}$, or 2139095040. /// - For [`f64`], this is $2^{63}-2^{52}$, or 9218868437227405312. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_negative_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_negative_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[-Infinity, -1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, \ /// -0.75, -1.625, -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, \ /// -1.4375, -6.0, -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, \ /// -2.125, -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, \ /// -0.6875, -1.40625, -2.875, -1.46875, -0.375, -1.53125, ...]" /// ); /// ``` #[inline] pub fn exhaustive_negative_primitive_floats() -> Chain, ExhaustiveNegativeFinitePrimitiveFloats> { once(T::NEGATIVE_INFINITY).chain(exhaustive_negative_finite_primitive_floats()) } /// Generates all nonzero primitive floats. /// /// Positive and negative zero are both excluded. NaN is excluded as well. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats in /// ascending order instead, use [`nonzero_primitive_floats_increasing`]. /// /// The output length is $2^{M+1}(2^E-1)$. /// - For [`f32`], this is $2^{32}-2^{24}$, or 4278190080. /// - For [`f64`], this is $2^{64}-2^{53}$, or 18437736874454810624. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_nonzero_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_nonzero_primitive_floats::().map(NiceFloat), /// 50 /// ), /// "[Infinity, -Infinity, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, \ /// -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, \ /// 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, \ /// 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, \ /// ...]" /// ); /// ``` #[inline] pub fn exhaustive_nonzero_primitive_floats() -> Chain, ExhaustiveNonzeroFinitePrimitiveFloats> { ::alloc::vec![T::INFINITY, T::NEGATIVE_INFINITY] .into_iter() .chain(exhaustive_nonzero_finite_primitive_floats()) } /// Generates all primitive floats. /// /// Positive and negative zero are both included. /// /// Roughly speaking, the simplest floats are generated first. If you want to generate the floats /// (except `NaN`) in ascending order instead, use [`primitive_floats_increasing`]. /// /// The output length is $2^{M+1}(2^E-1)+2$. /// - For [`f32`], this is $2^{32}-2^{24}+2$, or 4278190082. /// - For [`f64`], this is $2^{64}-2^{53}+2$, or 18437736874454810626. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_primitive_floats; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string(exhaustive_primitive_floats::().map(NiceFloat), 50), /// "[NaN, Infinity, -Infinity, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, \ /// -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, \ /// -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, \ /// -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, ...]" /// ); /// ``` #[inline] pub fn exhaustive_primitive_floats() -> Chain, ExhaustiveNonzeroFinitePrimitiveFloats> { ::alloc::vec![T::NAN, T::INFINITY, T::NEGATIVE_INFINITY, T::ZERO, T::NEGATIVE_ZERO] .into_iter() .chain(exhaustive_nonzero_finite_primitive_floats()) } pub_test! {exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range( a: T, b: T, sci_exponent: i64, precision: u64 ) -> ConstantPrecisionPrimitiveFloats { assert!(a.is_finite()); assert!(b.is_finite()); assert!(a > T::ZERO); assert!(b > T::ZERO); assert!(sci_exponent >= T::MIN_EXPONENT); assert!(sci_exponent <= T::MAX_EXPONENT); let (am, ae) = a.raw_mantissa_and_exponent(); let (bm, be) = b.raw_mantissa_and_exponent(); let ae_actual_sci_exponent = if ae == 0 { i64::wrapping_from(am.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(ae) - T::MAX_EXPONENT }; let be_actual_sci_exponent = if be == 0 { i64::wrapping_from(bm.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(be) - T::MAX_EXPONENT }; assert_eq!(ae_actual_sci_exponent, sci_exponent); assert_eq!(be_actual_sci_exponent, sci_exponent); assert!(am <= bm); assert_ne!(precision, 0); let max_precision = T::max_precision_for_sci_exponent(sci_exponent); assert!(precision <= max_precision); if precision == 1 && am == 0 { return ConstantPrecisionPrimitiveFloats { phantom: PhantomData, n: a.to_bits(), increment: 0, i: 0, count: 1, }; } let trailing_zeros = max_precision - precision; let increment = u64::power_of_2(trailing_zeros + 1); let mut start_mantissa = am.round_to_multiple_of_power_of_2(trailing_zeros, Up).0; if !start_mantissa.get_bit(trailing_zeros) { start_mantissa.set_bit(trailing_zeros); } if start_mantissa > bm { return ConstantPrecisionPrimitiveFloats::default(); } let mut end_mantissa = bm.round_to_multiple_of_power_of_2(trailing_zeros, Down).0; if !end_mantissa.get_bit(trailing_zeros) { let adjust = u64::power_of_2(trailing_zeros); if adjust > end_mantissa { return ConstantPrecisionPrimitiveFloats::default(); } end_mantissa -= adjust; } assert!(start_mantissa <= end_mantissa); let count = ((end_mantissa - start_mantissa) >> (trailing_zeros + 1)) + 1; let first = T::from_raw_mantissa_and_exponent(start_mantissa, ae).to_bits(); ConstantPrecisionPrimitiveFloats { phantom: PhantomData, n: first, increment, i: 0, count, } }} #[derive(Clone, Debug)] struct PrimitiveFloatsWithExponentInRangeGenerator { a: T, b: T, sci_exponent: i64, phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for PrimitiveFloatsWithExponentInRangeGenerator { #[inline] fn get_ys(&self, &precision: &u64) -> ConstantPrecisionPrimitiveFloats { exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range( self.a, self.b, self.sci_exponent, precision, ) } } #[inline] fn exhaustive_primitive_floats_with_sci_exponent_in_range_helper( a: T, b: T, sci_exponent: i64, ) -> LexDependentPairs< u64, T, PrimitiveFloatsWithExponentInRangeGenerator, PrimitiveIntIncreasingRange, ConstantPrecisionPrimitiveFloats, > { lex_dependent_pairs( primitive_int_increasing_inclusive_range( 1, T::max_precision_for_sci_exponent(sci_exponent), ), PrimitiveFloatsWithExponentInRangeGenerator { a, b, sci_exponent, phantom: PhantomData, }, ) } #[doc(hidden)] #[derive(Clone, Debug)] pub struct ExhaustivePrimitiveFloatsWithExponentInRange( LexDependentPairs< u64, T, PrimitiveFloatsWithExponentInRangeGenerator, PrimitiveIntIncreasingRange, ConstantPrecisionPrimitiveFloats, >, ); impl Iterator for ExhaustivePrimitiveFloatsWithExponentInRange { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } #[doc(hidden)] #[inline] pub fn exhaustive_primitive_floats_with_sci_exponent_in_range( a: T, b: T, sci_exponent: i64, ) -> ExhaustivePrimitiveFloatsWithExponentInRange { ExhaustivePrimitiveFloatsWithExponentInRange( exhaustive_primitive_floats_with_sci_exponent_in_range_helper(a, b, sci_exponent), ) } #[derive(Clone, Debug)] struct ExhaustivePositiveFinitePrimitiveFloatsInRangeGenerator { a: T, b: T, a_sci_exponent: i64, b_sci_exponent: i64, phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for ExhaustivePositiveFinitePrimitiveFloatsInRangeGenerator { #[inline] fn get_ys(&self, &sci_exponent: &i64) -> ExhaustivePrimitiveFloatsWithExponentInRange { let a = if sci_exponent == self.a_sci_exponent { self.a } else { T::from_integer_mantissa_and_exponent(1, sci_exponent).unwrap() }; let b = if sci_exponent == self.b_sci_exponent { self.b } else { T::from_integer_mantissa_and_exponent(1, sci_exponent + 1) .unwrap() .next_lower() }; exhaustive_primitive_floats_with_sci_exponent_in_range(a, b, sci_exponent) } } #[inline] fn exhaustive_positive_finite_primitive_floats_in_range_helper( a: T, b: T, ) -> ExhaustiveDependentPairs< i64, T, RulerSequence, ExhaustivePositiveFinitePrimitiveFloatsInRangeGenerator, ExhaustiveSignedRange, ExhaustivePrimitiveFloatsWithExponentInRange, > { assert!(a.is_finite()); assert!(b.is_finite()); assert!(a > T::ZERO); assert!(a <= b); let (am, ae) = a.raw_mantissa_and_exponent(); let (bm, be) = b.raw_mantissa_and_exponent(); let a_sci_exponent = if ae == 0 { i64::wrapping_from(am.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(ae) - T::MAX_EXPONENT }; let b_sci_exponent = if be == 0 { i64::wrapping_from(bm.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(be) - T::MAX_EXPONENT }; exhaustive_dependent_pairs( ruler_sequence(), exhaustive_signed_inclusive_range(a_sci_exponent, b_sci_exponent), ExhaustivePositiveFinitePrimitiveFloatsInRangeGenerator { a, b, a_sci_exponent, b_sci_exponent, phantom: PhantomData, }, ) } #[doc(hidden)] #[derive(Clone, Debug)] pub struct ExhaustivePositiveFinitePrimitiveFloatsInRange( ExhaustiveDependentPairs< i64, T, RulerSequence, ExhaustivePositiveFinitePrimitiveFloatsInRangeGenerator, ExhaustiveSignedRange, ExhaustivePrimitiveFloatsWithExponentInRange, >, ); impl Iterator for ExhaustivePositiveFinitePrimitiveFloatsInRange { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } #[doc(hidden)] #[inline] pub fn exhaustive_positive_finite_primitive_floats_in_range( a: T, b: T, ) -> ExhaustivePositiveFinitePrimitiveFloatsInRange { ExhaustivePositiveFinitePrimitiveFloatsInRange( exhaustive_positive_finite_primitive_floats_in_range_helper(a, b), ) } #[doc(hidden)] #[derive(Clone, Debug)] pub enum ExhaustiveNonzeroFinitePrimitiveFloatsInRange { AllPositive(ExhaustivePositiveFinitePrimitiveFloatsInRange), AllNegative(ExhaustivePositiveFinitePrimitiveFloatsInRange), PositiveAndNegative( bool, ExhaustivePositiveFinitePrimitiveFloatsInRange, ExhaustivePositiveFinitePrimitiveFloatsInRange, ), } impl Iterator for ExhaustiveNonzeroFinitePrimitiveFloatsInRange { type Item = T; fn next(&mut self) -> Option { match self { Self::AllPositive(xs) => xs.next(), Self::AllNegative(xs) => xs.next().map(T::neg), Self::PositiveAndNegative(toggle, pos_xs, neg_xs) => { toggle.not_assign(); if *toggle { pos_xs.next().or_else(|| neg_xs.next().map(T::neg)) } else { neg_xs.next().map(T::neg).or_else(|| pos_xs.next()) } } } } } #[doc(hidden)] #[inline] pub fn exhaustive_nonzero_finite_primitive_floats_in_range( a: T, b: T, ) -> ExhaustiveNonzeroFinitePrimitiveFloatsInRange { assert!(a.is_finite()); assert!(b.is_finite()); assert!(a != T::ZERO); assert!(b != T::ZERO); assert!(a <= b); if a > T::ZERO { ExhaustiveNonzeroFinitePrimitiveFloatsInRange::AllPositive( exhaustive_positive_finite_primitive_floats_in_range(a, b), ) } else if b < T::ZERO { ExhaustiveNonzeroFinitePrimitiveFloatsInRange::AllNegative( exhaustive_positive_finite_primitive_floats_in_range(-b, -a), ) } else { ExhaustiveNonzeroFinitePrimitiveFloatsInRange::PositiveAndNegative( false, exhaustive_positive_finite_primitive_floats_in_range(T::MIN_POSITIVE_SUBNORMAL, b), exhaustive_positive_finite_primitive_floats_in_range(T::MIN_POSITIVE_SUBNORMAL, -a), ) } } /// Generates all primitive floats in an interval. /// /// This `enum` is created by [`exhaustive_primitive_float_range`] and /// [`exhaustive_primitive_float_inclusive_range`]; see their documentation for more. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum ExhaustivePrimitiveFloatInclusiveRange { JustSpecials(IntoIter), NotJustSpecials(Chain, ExhaustiveNonzeroFinitePrimitiveFloatsInRange>), } impl Iterator for ExhaustivePrimitiveFloatInclusiveRange { type Item = T; fn next(&mut self) -> Option { match self { Self::JustSpecials(xs) => xs.next(), Self::NotJustSpecials(xs) => xs.next(), } } } /// Generates all primitive floats in the half-open interval $[a, b)$. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// The floats are generated in a way such that simpler floats (with lower precision) are generated /// first. To generate floats in ascending order instead, use [`primitive_float_increasing_range`] /// instead. /// /// `NiceFloat(a)` must be less than or equal to `NiceFloat(b)`. If `NiceFloat(a)` and /// `NiceFloat(b)` are equal, the range is empty. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output length is $\varphi(b) - \varphi(a)$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `NiceFloat(a) > NiceFloat(b)`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_primitive_float_range; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_primitive_float_range::(core::f32::consts::E, core::f32::consts::PI) /// .map(NiceFloat), /// 50 /// ), /// "[3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, \ /// 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, \ /// 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, \ /// 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, \ /// 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, \ /// 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ...]" /// ); /// ``` #[inline] pub fn exhaustive_primitive_float_range( a: T, b: T, ) -> ExhaustivePrimitiveFloatInclusiveRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!(NiceFloat(a) <= NiceFloat(b)); if NiceFloat(a) == NiceFloat(b) { ExhaustivePrimitiveFloatInclusiveRange::JustSpecials(Vec::new().into_iter()) } else { exhaustive_primitive_float_inclusive_range(a, b.next_lower()) } } /// Generates all primitive floats in the closed interval $[a, b]$. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// The floats are generated in a way such that simpler floats (with lower precision) are generated /// first. To generate floats in ascending order instead, use /// `primitive_float_increasing_inclusive_range` instead. /// /// `NiceFloat(a)` must be less than or equal to `NiceFloat(b)`. If `NiceFloat(a)` and /// `NiceFloat(b)` are equal, the range contains a single element. /// /// Let $\varphi$ be /// [`to_ordered_representation`](super::basic::floats::PrimitiveFloat::to_ordered_representation): /// /// The output length is $\varphi(b) - \varphi(a) + 1$. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `NiceFloat(a) > NiceFloat(b)`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::exhaustive::exhaustive_primitive_float_inclusive_range; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_primitive_float_inclusive_range::( /// core::f32::consts::E, /// core::f32::consts::PI /// ) /// .map(NiceFloat), /// 50 /// ), /// "[3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, \ /// 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, \ /// 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, \ /// 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, \ /// 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, \ /// 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ...]" /// ); /// ``` #[inline] pub fn exhaustive_primitive_float_inclusive_range( mut a: T, mut b: T, ) -> ExhaustivePrimitiveFloatInclusiveRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!(NiceFloat(a) <= NiceFloat(b)); let mut specials = Vec::new(); if b == T::INFINITY { specials.push(T::INFINITY); if a == T::INFINITY { return ExhaustivePrimitiveFloatInclusiveRange::JustSpecials(specials.into_iter()); } b = T::MAX_FINITE; } if a == T::NEGATIVE_INFINITY { specials.push(T::NEGATIVE_INFINITY); if b == T::NEGATIVE_INFINITY { return ExhaustivePrimitiveFloatInclusiveRange::JustSpecials(specials.into_iter()); } a = -T::MAX_FINITE; } if NiceFloat(a) <= NiceFloat(T::ZERO) && NiceFloat(b) >= NiceFloat(T::ZERO) { specials.push(T::ZERO); } if NiceFloat(a) <= NiceFloat(T::NEGATIVE_ZERO) && NiceFloat(b) >= NiceFloat(T::NEGATIVE_ZERO) { specials.push(T::NEGATIVE_ZERO); } if a == T::ZERO { if b == T::ZERO { return ExhaustivePrimitiveFloatInclusiveRange::JustSpecials(specials.into_iter()); } a = T::MIN_POSITIVE_SUBNORMAL; } if b == T::ZERO { b = -T::MIN_POSITIVE_SUBNORMAL; } ExhaustivePrimitiveFloatInclusiveRange::NotJustSpecials( specials .into_iter() .chain(exhaustive_nonzero_finite_primitive_floats_in_range(a, b)), ) } ================================================ FILE: malachite-base/src/num/factorization/factor.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2009 Tom Boothby // // Copyright © 2008, 2009, 2012 William Hart // // 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 crate::num::arithmetic::mod_pow::mul_mod_helper; use crate::num::arithmetic::sqrt::{sqrt_rem_2_newton, sqrt_rem_newton}; use crate::num::arithmetic::traits::{ DivMod, FloorRoot, FloorSqrt, Gcd, ModMulPrecomputed, ModSub, ModSubAssign, Parity, PowerOf2, SqrtRem, Square, WrappingAddAssign, WrappingMulAssign, WrappingSquare, WrappingSubAssign, XMulYToZZ, XXDivModYToQR, XXSubYYToZZ, }; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::factorization::primes::SMALL_PRIMES; use crate::num::factorization::traits::{Factor, IsPrime, IsSquare, Primes}; use crate::num::logic::traits::{LeadingZeros, LowMask, SignificantBits}; use core::mem::swap; pub(crate) const MAX_FACTORS_IN_U8: usize = 4; pub(crate) const MAX_FACTORS_IN_U16: usize = 6; pub(crate) const MAX_FACTORS_IN_U32: usize = 9; pub(crate) const MAX_FACTORS_IN_U64: usize = 15; pub(crate) const MAX_FACTORS_IN_USIZE: usize = 15; /// A struct that contains the prime factorization of an integer. See implementations of the /// [`Factor`] trait for more information. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Factors { factors: [T; N], exponents: [u8; N], } /// An iterator over [`Factors`]. #[derive(Clone, Debug, Eq, PartialEq)] pub struct FactorsIterator { i: usize, factors: Factors, } impl Iterator for FactorsIterator { type Item = (T, u8); fn next(&mut self) -> Option<(T, u8)> { let e = *self.factors.exponents.get(self.i)?; if e == 0 { return None; } let f = self.factors.factors[self.i]; self.i += 1; Some((f, e)) } } impl IntoIterator for Factors { type IntoIter = FactorsIterator; type Item = (T, u8); fn into_iter(self) -> FactorsIterator { FactorsIterator { i: 0, factors: self, } } } impl Factors { const fn new() -> Self { Self { factors: [T::ZERO; N], exponents: [0; N], } } // This takes linear time in the number of factors, but that's ok because the number of factors // is small. // // This is n_factor_insert from ulong_extras/factor_insert.c, FLINT 3.1.2, but it also ensures // that the factors are ordered least to greatest. fn insert(&mut self, factor: T, exp: u8) { let mut inserting = false; let mut previous_f = T::ZERO; let mut previous_e = 0; for (f, e) in self.factors.iter_mut().zip(self.exponents.iter_mut()) { if inserting { swap(&mut previous_f, f); swap(&mut previous_e, e); if previous_e == 0 { break; } } else if *e == 0 { *f = factor; *e = exp; break; } else if *f == factor { *e += exp; break; } else if *f > factor { previous_f = *f; previous_e = *e; *f = factor; *e = exp; inserting = true; } } } } type FactorsU8 = Factors; type FactorsU16 = Factors; type FactorsU32 = Factors; type FactorsU64 = Factors; type FactorsUsize = Factors; // This is n_divrem2_precomp when FLINT64 is false, from ulong_extras/divrem2_precomp.c, FLINT // 3.1.2, simplified to only include the branches used when factoring a `u32`. fn div_rem_precomputed_float_for_u32_factorization(a: u32, n: u32, inverse: f64) -> (u32, u32) { let mut q = (f64::from(a) * inverse) as u32; let r = a.wrapping_sub(q * n); let ri = i32::wrapping_from(r); if ri >= i32::wrapping_from(n) { q += (f64::from(ri) * inverse) as u32; (q + 1, a.wrapping_sub(q * n).wrapping_sub(n)) } else { (q, r) } } // This is n_divrem2_precomp when FLINT64 is true, from ulong_extras/divrem2_precomp.c, FLINT 3.1.2, // returning both q and r. fn div_rem_precomputed_float_u64(a: u64, n: u64, npre: f64) -> (u64, u64) { if a < n { return (0, a); } if n.get_highest_bit() { return (1, a.wrapping_sub(n)); } let (mut q, r) = if n == 1 { (a, 0) } else { let q = ((a as f64) * npre) as u64; (q, a.wrapping_sub(q.wrapping_mul(n))) }; let ri = i64::wrapping_from(r); let ni = i64::wrapping_from(n); if ri < ni.wrapping_neg() { q -= ((-(ri as f64)) * npre) as u64; } else if ri >= ni { q += ((ri as f64) * npre) as u64; } else if ri < 0 { return (q - 1, r.wrapping_add(n)); } else { return (q, r); } let r = a.wrapping_sub(q.wrapping_mul(n)); let ri = i64::wrapping_from(r); if ri >= ni { (q + 1, r.wrapping_sub(n)) } else if ri < 0 { (q - 1, r.wrapping_add(n)) } else { (q, r) } } // This is n_remove2_precomp when FLINT64 is false, from ulong_extras/remove2_precomp.c, FLINT // 3.1.2, returning n and exp. fn remove_factor_precomputed_float_u32(mut n: u32, p: u32, inverse: f64) -> (u32, u8) { if p == 2 { let exp = n.trailing_zeros(); if exp != 0 { n >>= exp; } (n, u8::wrapping_from(exp)) } else { let mut exp = 0; while n >= p { let (q, r) = div_rem_precomputed_float_for_u32_factorization(n, p, inverse); if r != 0 { break; } exp += 1; n = q; } (n, exp) } } // This is n_remove2_precomp when FLINT64 is true, from ulong_extras/remove2_precomp.c, FLINT 3.1.2, // returning n and exp. fn remove_factor_precomputed_float_u64(mut n: u64, p: u64, inverse: f64) -> (u64, u8) { if p == 2 { let exp = u64::from(n.trailing_zeros()); if exp != 0 { n >>= exp; } (n, u8::wrapping_from(exp)) } else { let mut exp = 0; while n >= p { let (q, r) = div_rem_precomputed_float_u64(n, p, inverse); if r != 0 { break; } exp += 1; n = q; } (n, exp) } } // This is n_factor_trial_range when FLINT64 is false, from ulong_extras/factor_trial.c, FLINT // 3.1.2, where start == 0. fn factor_trial_range_u32(factors: &mut FactorsU32, mut n: u32, num_primes: usize) -> u32 { for p in u32::primes().take(num_primes) { if p.square() > n { break; } let exp; (n, exp) = remove_factor_precomputed_float_u32(n, p, 1.0 / f64::from(p)); if exp != 0 { factors.insert(p, exp); } } n } // This is n_factor_trial_range when FLINT64 is true, from ulong_extras/factor_trial.c, FLINT 3.1.2. fn factor_trial_range_u64(factors: &mut FactorsU64, mut n: u64, num_primes: usize) -> u64 { for p in u64::primes().take(num_primes) { if p.square() > n { break; } let exp; (n, exp) = remove_factor_precomputed_float_u64(n, p, 1.0 / (p as f64)); if exp != 0 { factors.insert(p, exp); } } n } const POWER235_MOD63: [u8; 63] = [ 7, 7, 4, 0, 5, 4, 0, 5, 6, 5, 4, 4, 0, 4, 4, 0, 5, 4, 5, 4, 4, 0, 5, 4, 0, 5, 4, 6, 7, 4, 0, 4, 4, 0, 4, 6, 7, 5, 4, 0, 4, 4, 0, 5, 4, 4, 5, 4, 0, 5, 4, 0, 4, 4, 4, 6, 4, 0, 5, 4, 0, 4, 6, ]; const POWER235_MOD61: [u8; 61] = [ 7, 7, 0, 3, 1, 1, 0, 0, 2, 3, 0, 6, 1, 5, 5, 1, 1, 0, 0, 1, 3, 4, 1, 2, 2, 1, 0, 3, 2, 4, 0, 0, 4, 2, 3, 0, 1, 2, 2, 1, 4, 3, 1, 0, 0, 1, 1, 5, 5, 1, 6, 0, 3, 2, 0, 0, 1, 1, 3, 0, 7, ]; const POWER235_MOD44: [u8; 44] = [ 7, 7, 0, 2, 3, 3, 0, 2, 2, 3, 0, 6, 7, 2, 0, 2, 3, 2, 0, 2, 3, 6, 0, 6, 2, 3, 0, 2, 2, 2, 0, 2, 6, 7, 0, 2, 3, 3, 0, 2, 2, 2, 0, 6, ]; const POWER235_MOD31: [u8; 31] = [7, 7, 3, 0, 3, 5, 4, 1, 3, 1, 1, 0, 0, 0, 1, 2, 3, 0, 1, 1, 1, 0, 0, 2, 0, 5, 4, 2, 1, 2, 6]; // This is n_factor_power235 when FLINT64 is false, from ulong_extras/factor_power235.c, FLINT // 3.1.2, returning y and exp, and simplified to only include the branches used when factoring a // `u32`. In particular, only perfect squares are checked for. fn factor_square_u32(n: u32) -> (u32, u8) { let mut t = POWER235_MOD31[(n % 31) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD44[(n % 44) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD61[(n % 61) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD63[(n % 63) as usize]; if t.odd() { let (y, r) = n.sqrt_rem(); if r == 0 { return (y, 2); } } (0, 0) } // This is n_factor_power235 when FLINT64 is true, from ulong_extras/factor_power235.c, FLINT 3.1.2, // returning y and exp. Fifth powers are not checked for, because this function is only called on // values with no prime factor less than 27449, and 27449^5 is greater than 2^64. fn factor_power23_u64(n: u64) -> (u64, u8) { let mut t = POWER235_MOD31[(n % 31) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD44[(n % 44) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD61[(n % 61) as usize]; if t == 0 { return (0, 0); }; t &= POWER235_MOD63[(n % 63) as usize]; if t.odd() { let (y, r) = n.sqrt_rem(); if r == 0 { return (y, 2); } } if t & 2 != 0 { let y = n.floor_root(3); if n == y.pow(3) { return (y, 3); } } (0, 0) } const FLINT_ONE_LINE_MULTIPLIER: u32 = 480; // This is n_factor_one_line when FLINT64 is true, from ulong_extras/factor_one_line.c, FLINT 3.1.2. fn factor_one_line_u64(mut n: u64, iters: usize) -> u64 { let orig_n = n; n.wrapping_mul_assign(u64::from(FLINT_ONE_LINE_MULTIPLIER)); let mut iin = 0; let mut inn = n; for _ in 0..iters { if iin >= inn { break; } let mut sqrti = inn.floor_sqrt() + 1; let square = sqrti.square(); let mmod = square - inn; if mmod.is_square() { sqrti -= mmod.floor_sqrt(); let factor = orig_n.gcd(sqrti); if factor != 1 { return factor; } } iin = inn; inn.wrapping_add_assign(n); } 0 } fn wyhash64(seed: &mut u64) -> u64 { seed.wrapping_add_assign(0x60bee2bee120fc15); let tmp = u128::from(*seed) * 0xa3b195354a39b70d; let tmp = ((tmp >> 64) ^ tmp).wrapping_mul(0x1b03738712fad5c9); u64::wrapping_from((tmp >> 64) ^ tmp) } struct WyhashRandomU64s { seed: u64, } impl WyhashRandomU64s { const fn new() -> Self { Self { seed: 0x452aee49c457bbc3, } } } impl Iterator for WyhashRandomU64s { type Item = u64; fn next(&mut self) -> Option { Some(wyhash64(&mut self.seed)) } } // This is n_factor_pp1_table from ulong_extras/factor_pp1.c, FLINT 3.1.2. const N_FACTOR_PP1_TABLE: [(u16, u8); 34] = [ (2784, 5), (1208, 2), (2924, 3), (286, 5), (58, 5), (61, 4), (815, 2), (944, 2), (61, 3), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (606, 1), (2403, 1), (2524, 1), (2924, 1), (3735, 2), (669, 2), (6092, 3), (2179, 3), (3922, 3), (6717, 4), (4119, 4), (2288, 4), (9004, 3), (9004, 3), (9004, 3), ]; // This is n_pp1_pow_ui when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2, returning // the new values of x and y. y is not passed in as its initial value is never used. fn pp1_pow_ui_u64(mut x: u64, exp: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64) { let x_orig = x; let two = u64::power_of_2(norm + 1); let mut y = mul_mod_helper::(x, x, n, ninv, norm).mod_sub(two, n); let mut bit = u64::power_of_2(exp.significant_bits() - 2); while bit != 0 { (x, y) = if exp & bit != 0 { ( mul_mod_helper::(x, y, n, ninv, norm).mod_sub(x_orig, n), mul_mod_helper::(y, y, n, ninv, norm).mod_sub(two, n), ) } else { ( mul_mod_helper::(x, x, n, ninv, norm).mod_sub(two, n), mul_mod_helper::(y, x, n, ninv, norm).mod_sub(x_orig, n), ) }; bit >>= 1; } (x, y) } // This is n_pp1_factor when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2. fn pp1_factor_u64(mut n: u64, mut x: u64, norm: u64) -> u64 { if norm != 0 { n >>= norm; x >>= norm; } x.mod_sub_assign(2, n); if x == 0 { 0 } else { n.gcd(x) } } // This is n_pp1_find_power when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2, // returning factor and the new values of x and y. y is not passed in as its initial value is never // used. fn pp1_find_power_u64(mut x: u64, p: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64, u64) { let mut factor = 1; let mut y = 0; while factor == 1 { (x, y) = pp1_pow_ui_u64(x, p, n, ninv, norm); factor = pp1_factor_u64(n, x, norm); } (factor, x, y) } // This is n_factor_pp1 when FLINT64 is false, from ulong_extras/factor_pp1.c, FLINT 3.1.2. It is // assumed that n is odd. fn factor_pp1_u64(mut n: u64, b1: u64, c: u64) -> u64 { let mut primes = u64::primes(); let sqrt = b1.floor_sqrt(); let bits0 = b1.significant_bits(); let norm = LeadingZeros::leading_zeros(n); n <<= norm; let n_inverse = u64::precompute_mod_mul_data(&n); let mut x = c << norm; // mul by various prime powers let mut p = 0; let mut old_p = 0; let mut i = 0; let mut old_x = 0; while p < b1 { let j = i + 1024; old_p = p; old_x = x; while i < j { p = primes.next().unwrap(); x = if p < sqrt { pp1_pow_ui_u64( x, p.pow(u32::wrapping_from(bits0 / p.significant_bits())), n, n_inverse, norm, ) .0 } else { pp1_pow_ui_u64(x, p, n, n_inverse, norm).0 }; i += 1; } let factor = pp1_factor_u64(n, x, norm); if factor == 0 { break; } if factor != 1 { return factor; } } if p < b1 { // factor = 0 primes.jump_after(old_p); x = old_x; loop { p = primes.next().unwrap(); old_x = x; x = if p < sqrt { pp1_pow_ui_u64( x, p.pow(u32::wrapping_from(bits0 / p.significant_bits())), n, n_inverse, norm, ) .0 } else { pp1_pow_ui_u64(x, p, n, n_inverse, norm).0 }; let factor = pp1_factor_u64(n, x, norm); if factor == 0 { break; } if factor != 1 { return factor; } } } else { return 0; } // factor still 0 pp1_find_power_u64(old_x, p, n, n_inverse, norm).0 } // This is n_factor_pp1_wrapper when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2. fn factor_pp1_wrapper_u64(n: u64) -> u64 { let bits = n.significant_bits(); // silently fail if trial factoring would always succeed if bits < 31 { return 0; } let (b1, count) = N_FACTOR_PP1_TABLE[usize::wrapping_from(bits) - 31]; let b1 = u64::from(b1); let mut state = WyhashRandomU64s::new(); let mask = u64::low_mask((n - 4).significant_bits()); let limit = n - 3; for _ in 0..count { let mut randint = u64::MAX; while randint >= limit { randint = state.next().unwrap() & mask; } let factor = factor_pp1_u64(n, b1, randint + 3); if factor != 0 { return factor; } } 0 } // This is equivalent to `mpn_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where `rp` is not // `NULL` and `Limb == u64`, and the input has two limbs. One limb of the square root and two limbs // of the remainder are returned. #[doc(hidden)] fn limbs_sqrt_rem_to_out_u64(xs_hi: u64, xs_lo: u64) -> (u64, u64, u64, usize) { let high = if xs_hi == 0 { xs_lo } else { xs_hi }; assert_ne!(high, 0); let shift = LeadingZeros::leading_zeros(high) >> 1; let two_shift = shift << 1; if xs_hi == 0 { let (sqrt_lo, rem_lo) = if shift == 0 { sqrt_rem_newton::(high) } else { let sqrt = sqrt_rem_newton::(high << two_shift).0 >> shift; (sqrt, high - sqrt.square()) }; (sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0)) } else if shift == 0 { let (sqrt_lo, rem_hi, rem_lo) = sqrt_rem_2_newton::(xs_hi, xs_lo); if rem_hi { (sqrt_lo, 1, rem_lo, 2) } else { (sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0)) } } else { let mut lo = xs_lo; let hi = (high << two_shift) | (lo >> (u64::WIDTH - two_shift)); let sqrt_lo = sqrt_rem_2_newton::(hi, lo << two_shift).0 >> shift; lo.wrapping_sub_assign(sqrt_lo.wrapping_square()); (sqrt_lo, 0, lo, usize::from(lo != 0)) } } const FACTOR_SQUFOF_ITERS: usize = 50_000; const FACTOR_ONE_LINE_ITERS: usize = 40_000; // This is _ll_factor_SQUFOF when FLINT64 is true, from ulong_extras/factor_SQUFOF.c, FLINT 3.1.2. fn ll_factor_squfof_u64(n_hi: u64, n_lo: u64, max_iters: usize) -> u64 { let (mut sqrt_lo, mut rem_lo, num) = if n_hi != 0 { let (sqrt_lo, _, rem_lo, size) = limbs_sqrt_rem_to_out_u64(n_hi, n_lo); (sqrt_lo, rem_lo, size) } else { let (sqrt_lo, rem_lo) = n_lo.sqrt_rem(); (sqrt_lo, rem_lo, usize::from(sqrt_lo != 0)) }; let sqroot = sqrt_lo; let mut p = sqroot; let mut q = rem_lo; if q == 0 || num == 0 { return sqroot; } let l = 1 + ((p << 1).floor_sqrt() << 1); let l2 = l >> 1; let mut qupto = 0; let mut qlast = 1u64; let mut qarr = [0; 50]; let mut r = 0; let mut finished_loop = true; for i in 0..max_iters { let iq = (sqroot + p) / q; let pnext = iq * q - p; if q <= l { if q.even() { qarr[qupto] = q >> 1; qupto += 1; if qupto >= 50 { return 0; } } else if q <= l2 { qarr[qupto] = q; qupto += 1; if qupto >= 50 { return 0; } } } let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext))); qlast = q; q = t; p = pnext; if i.odd() || !q.is_square() { continue; } r = q.floor_sqrt(); if qupto == 0 { finished_loop = false; break; } let mut done = true; for &q in &qarr[..qupto] { if r == q { done = false; break; } } if done { finished_loop = false; break; } if r == 1 { return 0; } } if finished_loop { return 0; } qlast = r; p = p + r * ((sqroot - p) / r); let rem_hi; (rem_hi, rem_lo) = u64::x_mul_y_to_zz(p, p); let sqrt_hi; (sqrt_hi, sqrt_lo) = u64::xx_sub_yy_to_zz(n_hi, n_lo, rem_hi, rem_lo); q = if sqrt_hi != 0 { let norm = LeadingZeros::leading_zeros(qlast); u64::xx_div_mod_y_to_qr( (sqrt_hi << norm) + (sqrt_lo >> (u64::WIDTH - norm)), sqrt_lo << norm, qlast << norm, ) .0 } else { sqrt_lo / qlast }; let mut finished_loop = true; for _ in 0..max_iters { let iq = (sqroot + p) / q; let pnext = iq * q - p; if p == pnext { finished_loop = false; break; } let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext))); qlast = q; q = t; p = pnext; } if finished_loop { 0 } else if q.even() { q >> 1 } else { q } } // This is n_factor_SQUFOF when FLINT64 is true, from ulong_extras/factor_SQUFOF.c, FLINT 3.1.2. fn factor_squfof_u64(n: u64, iters: usize) -> u64 { let mut factor = ll_factor_squfof_u64(0, n, iters); let mut finished_loop = true; for &p in &SMALL_PRIMES[1..] { if factor != 0 { finished_loop = false; break; } let multiplier = u64::from(p); let (multn_1, multn_0) = u64::x_mul_y_to_zz(multiplier, n); factor = ll_factor_squfof_u64(multn_1, multn_0, iters); if factor != 0 { let (quot, rem) = factor.div_mod(multiplier); if rem == 0 { factor = quot; } if factor == 1 || factor == n { factor = 0; } } } if finished_loop { 0 } else { factor } } const FACTOR_TRIAL_PRIMES: usize = 3000; const FACTOR_TRIAL_CUTOFF: u32 = 27449 * 27449; impl Factor for u8 { type FACTORS = FactorsU8; /// Returns the prime factorization of a `u8`. The return value is iterable, and produces pairs /// $(p,e)$ of type `(u8, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The /// primes are in ascending order. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Factor; /// /// assert_eq!(251u8.factor().into_iter().collect_vec(), &[(251, 1)]); /// assert_eq!( /// 120u8.factor().into_iter().collect_vec(), /// &[(2, 3), (3, 1), (5, 1)] /// ); /// ``` fn factor(&self) -> FactorsU8 { assert_ne!(*self, 0); let mut n = *self; let mut factors = FactorsU8::new(); if n == 1 { return factors; } let zeros = n.trailing_zeros(); if zeros != 0 { factors.insert(2, zeros as Self); n >>= zeros; if n == 1 { return factors; } } let mut e; let (q, r) = n.div_mod(3); if r == 0 { e = 1; n = q; let (q, r) = n.div_mod(3); if r == 0 { e = 2; n = q; let (q, r) = n.div_mod(3); if r == 0 { e = 3; n = q; let (q, r) = n.div_mod(3); if r == 0 { e = 4; n = q; if n == 3 { e = 5; n = 1; } } } } factors.insert(3, e); if n == 1 { return factors; } } let (q, r) = n.div_mod(5); if r == 0 { e = 1; n = q; let (q, r) = n.div_mod(5); if r == 0 { e = 2; n = q; if n == 5 { e = 3; n = 1; } } factors.insert(5, e); if n == 1 { return factors; } } let (q, r) = n.div_mod(7); if r == 0 { e = 1; n = q; if n == 7 { e = 2; n = 1; } factors.insert(7, e); if n == 1 { return factors; } } match n { 121 => { factors.insert(11, 2); } 143 => { factors.insert(11, 1); factors.insert(13, 1); } 169 => { factors.insert(13, 2); } 187 => { factors.insert(11, 1); factors.insert(17, 1); } 209 => { factors.insert(11, 1); factors.insert(19, 1); } 221 => { factors.insert(13, 1); factors.insert(17, 1); } 247 => { factors.insert(13, 1); factors.insert(19, 1); } 253 => { factors.insert(11, 1); factors.insert(23, 1); } _ => { factors.insert(n, 1); } } factors } } impl Factor for u16 { type FACTORS = FactorsU16; /// Returns the prime factorization of a `u16`. The return value is iterable, and produces pairs /// $(p,e)$ of type `(u16, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The /// primes are in ascending order. /// /// # Worst-case complexity /// $T(n) = O(2^{n/4})$ /// /// $M(n) = O(2^n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Factor; /// /// assert_eq!(65521u16.factor().into_iter().collect_vec(), &[(65521, 1)]); /// assert_eq!( /// 40320u16.factor().into_iter().collect_vec(), /// &[(2, 7), (3, 2), (5, 1), (7, 1)] /// ); /// ``` fn factor(&self) -> FactorsU16 { let mut factors = FactorsU16::new(); for (f, e) in u32::from(*self).factor() { factors.insert(f as Self, e); } factors } } impl Factor for u32 { type FACTORS = FactorsU32; /// Returns the prime factorization of a `u32`. The return value is iterable, and produces pairs /// $(p,e)$ of type `(u32, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The /// primes are in ascending order. /// /// # Worst-case complexity /// $T(n) = O(2^{n/4})$ /// /// $M(n) = O(2^n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Factor; /// /// assert_eq!( /// 4294967291u32.factor().into_iter().collect_vec(), /// &[(4294967291, 1)] /// ); /// assert_eq!( /// 479001600u32.factor().into_iter().collect_vec(), /// &[(2, 10), (3, 5), (5, 2), (7, 1), (11, 1)] /// ); /// ``` /// /// This is n_factor when FLINT64 is false, from ulong_extras/factor.c, FLINT 3.1.2. fn factor(&self) -> FactorsU32 { let n = *self; assert_ne!(n, 0); let mut factors = FactorsU32::new(); let cofactor = factor_trial_range_u32(&mut factors, n, FACTOR_TRIAL_PRIMES); if cofactor == 1 { return factors; } if cofactor.is_prime() { factors.insert(cofactor, 1); return factors; } let mut factor_arr = [0; MAX_FACTORS_IN_U32]; let mut exp_arr = [0; MAX_FACTORS_IN_U32]; factor_arr[0] = cofactor; let mut factors_left = 1; exp_arr[0] = 1; let cutoff = FACTOR_TRIAL_CUTOFF; while factors_left != 0 { let mut factor = factor_arr[factors_left - 1]; if factor >= cutoff { let (mut cofactor, exp) = factor_square_u32(factor); if cofactor != 0 { exp_arr[factors_left - 1] *= exp; factor = cofactor; factor_arr[factors_left - 1] = factor; } if factor >= cutoff && !factor.is_prime() { cofactor = Self::exact_from(factor_one_line_u64( u64::from(factor), FACTOR_ONE_LINE_ITERS, )); exp_arr[factors_left] = exp_arr[factors_left - 1]; factor_arr[factors_left] = cofactor; factor_arr[factors_left - 1] /= cofactor; factors_left += 1; } else { factors.insert(factor, exp_arr[factors_left - 1]); factors_left -= 1; } } else { factors.insert(factor, exp_arr[factors_left - 1]); factors_left -= 1; } } factors } } const FACTOR_ONE_LINE_MAX: u64 = 1 << 39; impl Factor for u64 { type FACTORS = FactorsU64; /// Returns the prime factorization of a `u64`. The return value is iterable, and produces pairs /// $(p,e)$ of type `(u64, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The /// primes are in ascending order. /// /// # Worst-case complexity /// $T(n) = O(2^{n/4})$ /// /// $M(n) = O(2^n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Factor; /// /// assert_eq!( /// 18446744073709551557u64.factor().into_iter().collect_vec(), /// &[(18446744073709551557, 1)] /// ); /// assert_eq!( /// 2432902008176640000u64.factor().into_iter().collect_vec(), /// &[(2, 18), (3, 8), (5, 4), (7, 2), (11, 1), (13, 1), (17, 1), (19, 1)] /// ); /// ``` /// /// This is n_factor when FLINT64 is true, from ulong_extras/factor.c, FLINT 3.1.2. fn factor(&self) -> FactorsU64 { let n = *self; assert_ne!(n, 0); let mut factors = FactorsU64::new(); let cofactor = factor_trial_range_u64(&mut factors, n, FACTOR_TRIAL_PRIMES); if cofactor == 1 { return factors; } if cofactor.is_prime() { factors.insert(cofactor, 1); return factors; } let mut factor_arr = [0; MAX_FACTORS_IN_U64]; let mut exp_arr = [0; MAX_FACTORS_IN_U64]; factor_arr[0] = cofactor; let mut factors_left = 1; exp_arr[0] = 1; const CUTOFF: u64 = FACTOR_TRIAL_CUTOFF as u64; while factors_left != 0 { let mut factor = factor_arr[factors_left - 1]; if factor >= CUTOFF { let (mut cofactor, exp) = factor_power23_u64(factor); if cofactor != 0 { exp_arr[factors_left - 1] *= exp; factor = cofactor; factor_arr[factors_left - 1] = factor; } if factor >= CUTOFF && !factor.is_prime() { cofactor = 0; if factor < FACTOR_ONE_LINE_MAX { cofactor = factor_one_line_u64(factor, FACTOR_ONE_LINE_ITERS); } if cofactor == 0 { cofactor = factor_pp1_wrapper_u64(factor); if cofactor == 0 { cofactor = factor_squfof_u64(factor, FACTOR_SQUFOF_ITERS); assert_ne!(cofactor, 0); } } exp_arr[factors_left] = exp_arr[factors_left - 1]; factor_arr[factors_left] = cofactor; factor_arr[factors_left - 1] /= cofactor; factors_left += 1; } else { factors.insert(factor, exp_arr[factors_left - 1]); factors_left -= 1; } } else { factors.insert(factor, exp_arr[factors_left - 1]); factors_left -= 1; } } factors } } impl Factor for usize { type FACTORS = FactorsUsize; /// Returns the prime factorization of a `usize`. The return value is iterable, and produces /// pairs $(p,e)$ of type `(usize, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. /// The primes are in ascending order. /// /// # Worst-case complexity /// $T(n) = O(2^{n/4})$ /// /// $M(n) = O(2^n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Factor; /// /// assert_eq!( /// 4294967291usize.factor().into_iter().collect_vec(), /// &[(4294967291, 1)] /// ); /// assert_eq!( /// 479001600usize.factor().into_iter().collect_vec(), /// &[(2, 10), (3, 5), (5, 2), (7, 1), (11, 1)] /// ); /// ``` fn factor(&self) -> FactorsUsize { let mut factors = FactorsUsize::new(); if USIZE_IS_U32 { for (f, e) in (*self as u32).factor() { factors.insert(f as Self, e); } } else { for (f, e) in (*self as u64).factor() { factors.insert(f as Self, e); } } factors } } ================================================ FILE: malachite-base/src/num/factorization/is_power.rs ================================================ // Copyright © 2026 William Youmans // // Uses code adopted from the FLINT Library. // // Copyright © 2009 William Hart // // 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 crate::num::arithmetic::traits::{ CheckedRoot, DivAssignMod, DivMod, GcdAssign, Parity, RootRem, SqrtRem, }; use crate::num::basic::integers::USIZE_IS_U32; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::factorization::primes::SMALL_PRIMES; use crate::num::factorization::traits::{ ExpressAsPower, Factor, IsPower, IsPrime, IsSquare, Primes, }; use crate::num::logic::traits::{SignificantBits, TrailingZeros}; // The following arrays are bitmasks indicating whether an integer is a 2, 3, or 5th power residue. // For example, modulo 31 we have: // - squares: {0, 1, 2, 4, 5, 7, 8, 9, 10, 14, 16, 18, 19, 20, 25, 28} // - cubes: {0, 1, 2, 4, 8, 15, 16, 23, 27, 29, 30} // - 5th powers: {0, 1, 5, 6, 25, 26, 30} // Since 2 is a square, cube, but not a 5th power mod 31, we encode it as 011 = 3. Then MOD31[2] = // 3. const MOD63: [u8; 63] = [ 7, 7, 4, 0, 5, 4, 0, 5, 6, 5, 4, 4, 0, 4, 4, 0, 5, 4, 5, 4, 4, 0, 5, 4, 0, 5, 4, 6, 7, 4, 0, 4, 4, 0, 4, 6, 7, 5, 4, 0, 4, 4, 0, 5, 4, 4, 5, 4, 0, 5, 4, 0, 4, 4, 4, 6, 4, 0, 5, 4, 0, 4, 6, ]; const MOD61: [u8; 61] = [ 7, 7, 0, 3, 1, 1, 0, 0, 2, 3, 0, 6, 1, 5, 5, 1, 1, 0, 0, 1, 3, 4, 1, 2, 2, 1, 0, 3, 2, 4, 0, 0, 4, 2, 3, 0, 1, 2, 2, 1, 4, 3, 1, 0, 0, 1, 1, 5, 5, 1, 6, 0, 3, 2, 0, 0, 1, 1, 3, 0, 7, ]; const MOD44: [u8; 44] = [ 7, 7, 0, 2, 3, 3, 0, 2, 2, 3, 0, 6, 7, 2, 0, 2, 3, 2, 0, 2, 3, 6, 0, 6, 2, 3, 0, 2, 2, 2, 0, 2, 6, 7, 0, 2, 3, 3, 0, 2, 2, 2, 0, 6, ]; const MOD31: [u8; 31] = [7, 7, 3, 0, 3, 5, 4, 1, 3, 1, 1, 0, 0, 0, 1, 2, 3, 0, 1, 1, 1, 0, 0, 2, 0, 5, 4, 2, 1, 2, 6]; const MOD72: [u8; 72] = [ 7, 7, 0, 0, 0, 7, 0, 7, 7, 7, 0, 7, 0, 7, 0, 0, 7, 7, 0, 7, 0, 0, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 7, 0, 0, 7, 0, 7, 0, 0, 7, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 0, 0, 7, 0, 7, 7, 0, 0, 7, 0, 7, 0, 7, 7, 7, 0, 7, 0, 0, 0, 7, ]; const MOD49: [u8; 49] = [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ]; const MOD67: [u8; 67] = [ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ]; const MOD79: [u8; 79] = [ 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ]; // This is n_is_power when FLINT64 is false, from ulong_extras/is_power.c, FLINT 3.1.2. fn get_perfect_power_u32(n: u32) -> Option<(u32, u64)> { // Check for powers 2, 3, 5 let mut t = MOD31[(n % 31) as usize]; t &= MOD44[(n % 44) as usize]; t &= MOD61[(n % 61) as usize]; t &= MOD63[(n % 63) as usize]; // Check for perfect square if t & 1 != 0 { let (rt, rem) = n.sqrt_rem(); if rem == 0 { return Some((rt, 2)); } } // Check for perfect cube if t & 2 != 0 { let (rt, rem) = n.root_rem(3); if rem == 0 { return Some((rt, 3)); } } // Check for perfect fifth power if t & 4 != 0 { let (rt, rem) = n.root_rem(5); if rem == 0 { return Some((rt, 5)); } } // Check for powers 7, 11, 13 t = MOD49[(n % 49) as usize]; t |= MOD67[(n % 67) as usize]; t |= MOD79[(n % 79) as usize]; t &= MOD72[(n % 72) as usize]; // Check for perfect 7th power if t & 1 != 0 { let (rt, rem) = n.root_rem(7); if rem == 0 { return Some((rt, 7)); } } // Check for perfect 11th power if t & 2 != 0 { let (rt, rem) = n.root_rem(11); if rem == 0 { return Some((rt, 11)); } } // Check for perfect 13th power if t & 13 != 0 { let (rt, rem) = n.root_rem(13); if rem == 0 { return Some((rt, 13)); } } // Handle powers of 2 let count = u64::from(n.trailing_zeros()); let mut n = n >> count; if n == 1 { return if count == 1 { None // Just 2^1 = 2, not a perfect power } else { Some((2, count)) }; } // Check other powers (exp >= 17, root <= 13 and odd) let mut exp = 0; while n.is_multiple_of(3) { n /= 3; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { if count == 0 { return Some((3, exp)); } else if count == exp { return Some((6, exp)); } else if count == 2 * exp { return Some((12, exp)); } } return None; } None } // This is n_is_power when FLINT64 is false, from ulong_extras/is_power.c, FLINT 3.1.2, returning // only whether n can be expressed as a nontrivial perfect power. fn get_perfect_power_u32_bool(n: u32) -> bool { // Check for powers 2, 3, 5 let mut t = MOD31[(n % 31) as usize]; t &= MOD44[(n % 44) as usize]; t &= MOD61[(n % 61) as usize]; t &= MOD63[(n % 63) as usize]; // Check for perfect square if t & 1 != 0 && n.is_square() { return true; } // Check for perfect cube if t & 2 != 0 && n.root_rem(3).1 == 0 { return true; } // Check for perfect fifth power if t & 4 != 0 && n.root_rem(5).1 == 0 { return true; } // Check for powers 7, 11, 13 t = MOD49[(n % 49) as usize]; t |= MOD67[(n % 67) as usize]; t |= MOD79[(n % 79) as usize]; t &= MOD72[(n % 72) as usize]; // Check for perfect 7th power if t & 1 != 0 && n.root_rem(7).1 == 0 { return true; } // Check for perfect 11th power if t & 2 != 0 && n.root_rem(11).1 == 0 { return true; } // Check for perfect 13th power if t & 13 != 0 && n.root_rem(13).1 == 0 { return true; } // Handle powers of 2 let count = n.trailing_zeros(); let mut n = n >> n.trailing_zeros(); if n == 1 { return count != 1; } // Check other powers (exp >= 17, root <= 13 and odd) let mut exp = 0; while n.is_multiple_of(3) { n /= 3; exp += 1; } exp > 0 && n == 1 && exp > 1 && (count == 0 || count == exp || count == exp << 1) } // This is n_is_power when FLINT64 is true, from ulong_extras/is_power.c, FLINT 3.1.2. fn get_perfect_power_u64(n: u64) -> Option<(u64, u64)> { // Check for powers 2, 3, 5 let mut t = MOD31[(n % 31) as usize]; t &= MOD44[(n % 44) as usize]; t &= MOD61[(n % 61) as usize]; t &= MOD63[(n % 63) as usize]; // Check for perfect square if t & 1 != 0 { let (rt, rem) = n.sqrt_rem(); if rem == 0 { return Some((rt, 2)); } } // Check for perfect cube if t & 2 != 0 { let (rt, rem) = n.root_rem(3); if rem == 0 { return Some((rt, 3)); } } // Check for perfect fifth power if t & 4 != 0 { let (rt, rem) = n.root_rem(5); if rem == 0 { return Some((rt, 5)); } } // Check for powers 7, 11, 13 t = MOD49[(n % 49) as usize]; t |= MOD67[(n % 67) as usize]; t |= MOD79[(n % 79) as usize]; t &= MOD72[(n % 72) as usize]; // Check for perfect 7th power if t & 1 != 0 { let (rt, rem) = n.root_rem(7); if rem == 0 { return Some((rt, 7)); } } // Check for perfect 11th power if t & 2 != 0 { let (rt, rem) = n.root_rem(11); if rem == 0 { return Some((rt, 11)); } } // Check for perfect 13th power if t & 13 != 0 { let (rt, rem) = n.root_rem(13); if rem == 0 { return Some((rt, 13)); } } // Handle powers of 2 let count = u64::from(n.trailing_zeros()); let mut n = n >> count; if n == 1 { return if count == 1 { None // Just 2^1 = 2, not a perfect power } else { Some((2, count)) }; } // Check other powers (exp >= 17, root <= 13 and odd) let mut exp = 0; while n.is_multiple_of(3) { n /= 3; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { if count == 0 { return Some((3, exp)); } else if count == exp { return Some((6, exp)); } else if count == 2 * exp { return Some((12, exp)); } } return None; } // Check powers of 5 exp = 0; while n.is_multiple_of(5) { n /= 5; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { if count == 0 { return Some((5, exp)); } else if count == exp { return Some((10, exp)); } } return None; } if count > 0 { return None; } // Check powers of 7 exp = 0; while n.is_multiple_of(7) { n /= 7; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { return Some((7, exp)); } return None; } // Check powers of 11 exp = 0; while n.is_multiple_of(11) { n /= 11; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { return Some((11, exp)); } return None; } // Check powers of 13 exp = 0; while n.is_multiple_of(13) { n /= 13; exp += 1; } if exp > 0 { if n == 1 && exp > 1 { return Some((13, exp)); } return None; } None } // This is n_is_power when FLINT64 is true, from ulong_extras/is_power.c, FLINT 3.1.2, returning // only whether n can be expressed as a nontrivial perfect power. fn get_perfect_power_u64_bool(n: u64) -> bool { // Check for powers 2, 3, 5 let mut t = MOD31[(n % 31) as usize]; t &= MOD44[(n % 44) as usize]; t &= MOD61[(n % 61) as usize]; t &= MOD63[(n % 63) as usize]; // Check for perfect square if t & 1 != 0 && n.is_square() { return true; } // Check for perfect cube if t & 2 != 0 && n.root_rem(3).1 == 0 { return true; } // Check for perfect fifth power if t & 4 != 0 && n.root_rem(5).1 == 0 { return true; } // Check for powers 7, 11, 13 t = MOD49[(n % 49) as usize]; t |= MOD67[(n % 67) as usize]; t |= MOD79[(n % 79) as usize]; t &= MOD72[(n % 72) as usize]; // Check for perfect 7th power if t & 1 != 0 && n.root_rem(7).1 == 0 { return true; } // Check for perfect 11th power if t & 2 != 0 && n.root_rem(11).1 == 0 { return true; } // Check for perfect 13th power if t & 13 != 0 && n.root_rem(13).1 == 0 { return true; } // Handle powers of 2 let count = u64::from(n.trailing_zeros()); let mut n = n >> count; if n == 1 { return count != 1; } // Check other powers (exp >= 17, root <= 13 and odd) let mut exp = 0; while n.is_multiple_of(3) { n /= 3; exp += 1; } if exp > 0 { return n == 1 && exp > 1 && (count == 0 || count == exp || count == exp << 1); } // Check powers of 5 exp = 0; while n.is_multiple_of(5) { n /= 5; exp += 1; } if exp > 0 { return n == 1 && exp > 1 && (count == 0 || count == exp); } if count > 0 { return false; } // Check powers of 7 exp = 0; while n.is_multiple_of(7) { n /= 7; exp += 1; } if exp > 0 { return n == 1 && exp > 1; } // Check powers of 11 exp = 0; while n.is_multiple_of(11) { n /= 11; exp += 1; } if exp > 0 { return n == 1 && exp > 1; } // Check powers of 13 exp = 0; while n.is_multiple_of(13) { n /= 13; exp += 1; } n == 1 && exp > 1 } fn get_perfect_power_u128(n: u128) -> Option<(u128, u64)> { if let Ok(n) = u64::try_from(n) { return get_perfect_power_u64(n).map(|(p, e)| (u128::from(p), e)); } // Find largest power of 2 dividing n let mut pow_2 = TrailingZeros::trailing_zeros(n); // Two divides exactly once - not a perfect power if pow_2 == 1 { return None; } // If pow_2 is prime, just check if n is a perfect pow_2-th power if pow_2.is_prime() { return n.checked_root(pow_2).map(|root| (root, pow_2)); } // Divide out 2^pow_2 to get the odd part let mut q = n >> pow_2; // Factor out powers of small primes for &prime in SMALL_PRIMES[..168].iter().skip(1) { let prime = u128::from(prime); let (new_q, r) = q.div_mod(prime); if r == 0 { q = new_q; if q.div_assign_mod(prime) != 0 { return None; // prime divides exactly once, reject } let mut pow_p = 2u64; loop { let (new_q, r) = q.div_mod(prime); if r == 0 { q = new_q; pow_p += 1; } else { break; } } pow_2.gcd_assign(pow_p); if pow_2 == 1 { return None; // we have multiplicity 1 of some factor } // As soon as pow_2 becomes prime, stop factoring if q == 1 || pow_2.is_prime() { return n.checked_root(pow_2).map(|root| (root, pow_2)); } } } // After factoring, check remaining cases if pow_2 == 0 { // No factors found above; exhaustively check all prime exponents let bits = n.significant_bits(); for nth in u64::primes() { // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits) if nth > bits { return None; } if let Some(root) = n.checked_root(nth) { return Some((root, nth)); } } } else { // Found some factors; only check prime divisors of pow_2 for (nth, _) in pow_2.factor() { if let Some(root) = n.checked_root(nth) { return Some((root, nth)); } } } None } fn get_perfect_power_u128_bool(n: u128) -> bool { if let Ok(n) = u64::try_from(n) { return get_perfect_power_u64_bool(n); } // Find largest power of 2 dividing n let mut pow_2 = TrailingZeros::trailing_zeros(n); // Two divides exactly once - not a perfect power if pow_2 == 1 { return false; } // If pow_2 is prime, check if n is a perfect pow_2-th power if pow_2.is_prime() { return n.checked_root(pow_2).is_some(); } // Divide out 2^pow_2 to get the odd part let mut q = n >> pow_2; // Factor out powers of small primes for &prime in SMALL_PRIMES[..168].iter().skip(1) { let prime = u128::from(prime); let (new_q, r) = q.div_mod(prime); if r == 0 { q = new_q; if q.div_assign_mod(prime) != 0 { return false; // prime divides exactly once, reject } let mut pow_p = 2u64; loop { let (new_q, r) = q.div_mod(prime); if r == 0 { q = new_q; pow_p += 1; } else { break; } } pow_2.gcd_assign(pow_p); if pow_2 == 1 { return false; // we have multiplicity 1 of some factor } // As soon as pow_2 becomes prime, stop factoring if q == 1 || pow_2.is_prime() { return n.checked_root(pow_2).is_some(); } } } // After factoring, check remaining cases if pow_2 == 0 { // No factors found above; exhaustively check all prime exponents let bits = n.significant_bits(); for nth in u64::primes() { // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits) if nth > bits { return false; } if n.checked_root(nth).is_some() { return true; } } } else { // Found some factors; only check prime divisors of pow_2 for (nth, _) in pow_2.factor() { if n.checked_root(nth).is_some() { return true; } } } false } fn express_as_power_u32(n: u32) -> Option<(u32, u64)> { if n <= 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u32(n)?; while base > 3 { match get_perfect_power_u32(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => { return Some((base, exp)); } } } Some((base, exp)) } fn express_as_power_u64(n: u64) -> Option<(u64, u64)> { if n <= 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u64(n)?; while base > 3 { match get_perfect_power_u64(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => { return Some((base, exp)); } } } Some((base, exp)) } fn express_as_power_u128(n: u128) -> Option<(u128, u64)> { if n <= 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u128(n)?; while base > 3 { match get_perfect_power_u128(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => { return Some((base, exp)); } } } Some((base, exp)) } fn express_as_power_i32(n: i32) -> Option<(i32, u64)> { if n == 0 || n == 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u32(n.unsigned_abs())?; while base > 3 { match get_perfect_power_u32(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // handle negative input if n < 0 && exp.even() { while exp.even() { base *= base; exp >>= 1; } if exp == 1 { return None; } } let ibase = i32::exact_from(base); Some((if n >= 0 { ibase } else { -ibase }, exp)) } fn express_as_power_i64(n: i64) -> Option<(i64, u64)> { if n == 0 || n == 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u64(n.unsigned_abs())?; while base > 3 { match get_perfect_power_u64(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // handle negative input if n < 0 && exp.even() { while exp.even() { base *= base; exp >>= 1; } if exp == 1 { return None; } } let ibase = i64::exact_from(base); Some((if n >= 0 { ibase } else { -ibase }, exp)) } fn express_as_power_i128(n: i128) -> Option<(i128, u64)> { if n == 0 || n == 1 { return Some((n, 2)); } // continue until we have largest possible exponent let (mut base, mut exp) = get_perfect_power_u128(n.unsigned_abs())?; while base > 3 { match get_perfect_power_u128(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // handle negative input if n < 0 && exp.even() { while exp.even() { base *= base; exp >>= 1; } if exp == 1 { return None; } } let ibase = i128::exact_from(base); Some((if n >= 0 { ibase } else { -ibase }, exp)) } #[inline] fn is_power_u32(n: u32) -> bool { n <= 1 || get_perfect_power_u32_bool(n) } #[inline] fn is_power_u64(n: u64) -> bool { n <= 1 || get_perfect_power_u64_bool(n) } fn is_power_i32(n: i32) -> bool { if n == 0 || n == 1 { return true; } if n > 0 { // For positive numbers, just check if it's a perfect power return get_perfect_power_u32_bool(n.unsigned_abs()); } // For negative numbers, we need to check if there's an odd exponent representation // // continue until we have largest possible exponent let (mut base, mut exp) = if let Some((base, exp)) = get_perfect_power_u32(n.unsigned_abs()) { (base, exp) } else { return false; }; while base > 3 { match get_perfect_power_u32(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // Check if we can make the exponent odd !exp.is_power_of_two() } fn is_power_i64(n: i64) -> bool { if n == 0 || n == 1 { return true; } if n > 0 { // For positive numbers, just check if it's a perfect power return get_perfect_power_u64_bool(n.unsigned_abs()); } // For negative numbers, we need to check if there's an odd exponent representation // // continue until we have largest possible exponent let (mut base, mut exp) = if let Some((base, exp)) = get_perfect_power_u64(n.unsigned_abs()) { (base, exp) } else { return false; }; while base > 3 { match get_perfect_power_u64(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // Check if we can make the exponent odd !exp.is_power_of_two() } fn is_power_i128(n: i128) -> bool { if n == 0 || n == 1 { return true; } if n > 0 { // For positive numbers, just check if it's a perfect power return get_perfect_power_u128_bool(n.unsigned_abs()); } // For negative numbers, we need to check if there's an odd exponent representation // // continue until we have largest possible exponent let (mut base, mut exp) = if let Some((base, exp)) = get_perfect_power_u128(n.unsigned_abs()) { (base, exp) } else { return false; }; while base > 3 { match get_perfect_power_u128(base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } // Check if we can make the exponent odd !exp.is_power_of_two() } impl ExpressAsPower for u64 { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. #[inline] fn express_as_power(&self) -> Option<(u64, u64)> { express_as_power_u64(*self) } } impl ExpressAsPower for u128 { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. #[inline] fn express_as_power(&self) -> Option<(Self, u64)> { express_as_power_u128(*self) } } impl ExpressAsPower for usize { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. fn express_as_power(&self) -> Option<(Self, u64)> { if USIZE_IS_U32 { match express_as_power_u32(u32::wrapping_from(*self)) { Some((base, exp)) => Some((Self::wrapping_from(base), exp)), _ => None, } } else { match express_as_power_u64(u64::wrapping_from(*self)) { Some((base, exp)) => Some((Self::wrapping_from(base), exp)), _ => None, } } } } impl IsPower for u64 { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { is_power_u64(*self) } } impl IsPower for u128 { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { get_perfect_power_u128_bool(*self) } } impl IsPower for usize { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). fn is_power(&self) -> bool { if USIZE_IS_U32 { is_power_u32(u32::wrapping_from(*self)) } else { is_power_u64(u64::wrapping_from(*self)) } } } macro_rules! impl_unsigned_32 { ($t: ident) => { impl ExpressAsPower for $t { /// Expresses a number as a perfect power, if such a representation exists. We define a /// perfect power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both /// integers. In particular, 0 and 1 are considered perfect powers. If a number has more /// than one representation as a power, the representation with the smallest base is /// returned. For example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather /// than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a /// perfect power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. fn express_as_power(&self) -> Option<($t, u64)> { match express_as_power_u32(u32::from(*self)) { Some((base, exp)) => Some(($t::exact_from(base), exp)), _ => None, } } } impl IsPower for $t { /// Determines whether an integer is a perfect power. We define a perfect power as any /// number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular 0 and 1 are considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { is_power_u32(u32::from(*self)) } } }; } impl_unsigned_32!(u8); impl_unsigned_32!(u16); impl_unsigned_32!(u32); impl ExpressAsPower for i64 { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. #[inline] fn express_as_power(&self) -> Option<(Self, u64)> { express_as_power_i64(*self) } } impl ExpressAsPower for i128 { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. #[inline] fn express_as_power(&self) -> Option<(Self, u64)> { express_as_power_i128(*self) } } impl ExpressAsPower for isize { /// Expresses a number as a perfect power, if such a representation exists. We define a perfect /// power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular, 0 and 1 are considered perfect powers. If a number has more than one /// representation as a power, the representation with the smallest base is returned. For /// example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a perfect /// power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. fn express_as_power(&self) -> Option<(Self, u64)> { if USIZE_IS_U32 { match express_as_power_i32(i32::wrapping_from(*self)) { Some((base, exp)) => Some((Self::wrapping_from(base), exp)), _ => None, } } else { match express_as_power_i64(i64::wrapping_from(*self)) { Some((base, exp)) => Some((Self::wrapping_from(base), exp)), _ => None, } } } } impl IsPower for i64 { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { is_power_i64(*self) } } impl IsPower for i128 { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { is_power_i128(*self) } } impl IsPower for isize { /// Determines whether an integer is a perfect power. We define a perfect power as any number of /// the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In particular 0 and 1 are /// considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). fn is_power(&self) -> bool { if USIZE_IS_U32 { is_power_i32(i32::wrapping_from(*self)) } else { is_power_i64(i64::wrapping_from(*self)) } } } macro_rules! impl_signed_32 { ($t: ident) => { impl ExpressAsPower for $t { /// Expresses a number as a perfect power, if such a representation exists. We define a /// perfect power as any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both /// integers. In particular, 0 and 1 are considered perfect powers. If a number has more /// than one representation as a power, the representation with the smallest base is /// returned. For example, $64=2^6=4^3=8^2$, but this function returns `(2,6)` rather /// than `(4,3)` or `(8,2)`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#express_as_power). /// /// # Notes /// - This returns an [`Option`] which is either `Some((base, exp))` if the input is a /// perfect power equal to $\text{base}^\text{exp}$, otherwise `None`. /// - For 0 this returns `Some((0, 2))` and for 1 this returns `Some((1, 2))`. fn express_as_power(&self) -> Option<($t, u64)> { match express_as_power_i32(i32::from(*self)) { Some((base, exp)) => Some(($t::exact_from(base), exp)), _ => None, } } } impl IsPower for $t { /// Determines whether an integer is a perfect power. We define a perfect power as any /// number of the form $a^x$ where $x > 1$, with $a$ and $x$ both integers. In /// particular 0 and 1 are considered perfect powers. /// /// $f(x) = (\exists b \in \Z, e \in \N : e > 1 \ \text{and} \ b^e = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_power#is_power). #[inline] fn is_power(&self) -> bool { is_power_i32(i32::from(*self)) } } }; } impl_signed_32!(i8); impl_signed_32!(i16); impl_signed_32!(i32); ================================================ FILE: malachite-base/src/num/factorization/is_prime.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2008 Peter Shrimpton // // Copyright © 2009 Tom Boothby // // Copyright © 2009, 2010, 2013, 2015, 2016 William Hart // // Copyright © 2010 Fredrik Johansson // // Copyright © 2014 Dana Jacobsen // // Copyright © 2023 Mathieu Gouttenoire // // 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 crate::num::arithmetic::mod_pow::mul_mod_helper; use crate::num::arithmetic::traits::{ Gcd, JacobiSymbol, ModAdd, ModInverse, ModMulPrecomputed, ModMulPrecomputedAssign, ModSub, Parity, PowerOf2, WrappingAddAssign, WrappingNegAssign, XMulYToZZ, XXAddYYToZZ, }; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::comparison::traits::PartialOrdAbs; use crate::num::conversion::traits::WrappingFrom; use crate::num::factorization::traits::IsPrime; use crate::num::logic::traits::{BitAccess, LeadingZeros, SignificantBits, TrailingZeros}; // This is FLINT_ODD_PRIME_LOOKUP when FLINT64 is true, from ulong_extras/is_oddprime.c, FLINT // 3.1.2. const ODD_PRIME_LOOKUP_U64: [u64; 32] = [ 0x816d129a64b4cb6e, 0x2196820d864a4c32, 0xa48961205a0434c9, 0x4a2882d129861144, 0x834992132424030, 0x148a48844225064b, 0xb40b4086c304205, 0x65048928125108a0, 0x80124496804c3098, 0xc02104c941124221, 0x804490000982d32, 0x220825b082689681, 0x9004265940a28948, 0x6900924430434006, 0x12410da408088210, 0x86122d22400c060, 0x110d301821b0484, 0x14916022c044a002, 0x92094d204a6400c, 0x4ca2100800522094, 0xa48b081051018200, 0x34c108144309a25, 0x2084490880522502, 0x241140a218003250, 0xa41a00101840128, 0x2926000836004512, 0x10100480c0618283, 0xc20c26584822006d, 0x4520582024894810, 0x10c0250219002488, 0x802832ca01140868, 0x60901300264b0400, ]; // This is FLINT_ODD_PRIME_LOOKUP when FLINT64 is false, from ulong_extras/is_oddprime.c, FLINT // 3.1.2. const ODD_PRIME_LOOKUP_U32: [u32; 64] = [ 0x64b4cb6e, 0x816d129a, 0x864a4c32, 0x2196820d, 0x5a0434c9, 0xa4896120, 0x29861144, 0x4a2882d1, 0x32424030, 0x8349921, 0x4225064b, 0x148a4884, 0x6c304205, 0xb40b408, 0x125108a0, 0x65048928, 0x804c3098, 0x80124496, 0x41124221, 0xc02104c9, 0x982d32, 0x8044900, 0x82689681, 0x220825b0, 0x40a28948, 0x90042659, 0x30434006, 0x69009244, 0x8088210, 0x12410da4, 0x2400c060, 0x86122d2, 0x821b0484, 0x110d301, 0xc044a002, 0x14916022, 0x4a6400c, 0x92094d2, 0x522094, 0x4ca21008, 0x51018200, 0xa48b0810, 0x44309a25, 0x34c1081, 0x80522502, 0x20844908, 0x18003250, 0x241140a2, 0x1840128, 0xa41a001, 0x36004512, 0x29260008, 0xc0618283, 0x10100480, 0x4822006d, 0xc20c2658, 0x24894810, 0x45205820, 0x19002488, 0x10c02502, 0x1140868, 0x802832ca, 0x264b0400, 0x60901300, ]; // This is FLINT_D_BITS when FLINT64 is true, from flint.h, FLINT 3.1.2. const FLINT_D_BITS: u64 = 53; // This is n_is_oddprime_small_u64 when FLINT64 is true, from ulong_extras/is_oddprime.c, FLINT // 3.1.2. #[inline] fn is_odd_prime_small_u64(n: u64) -> bool { ODD_PRIME_LOOKUP_U64[(n >> 7) as usize].get_bit((n >> 1) & u64::WIDTH_MASK) } // This is n_is_oddprime_small_u64 when FLINT64 is false, from ulong_extras/is_oddprime.c, FLINT // 3.1.2. #[inline] fn is_odd_prime_small_u32(n: u32) -> bool { ODD_PRIME_LOOKUP_U32[(n >> 6) as usize].get_bit(u64::from(n >> 1) & u32::WIDTH_MASK) } // This is n_mod2_preinv when FLINT64 is false, from ulong_extras/mod2_preinv.c, FLINT 3.1.2. fn mod_preinverted_u32(a: u32, mut n: u32, inverse: u32) -> u32 { assert_ne!(n, 0); let norm = LeadingZeros::leading_zeros(n); n <<= norm; let u1 = a >> (u32::WIDTH - norm); let u0 = a << norm; let (mut q1, mut q0) = u32::x_mul_y_to_zz(inverse, u1); (q1, q0) = u32::xx_add_yy_to_zz(q1, q0, u1, u0); let mut r = u0 - (q1 + 1) * n; if r > q0 { r += n; } if r < n { r >> norm } else { (r - n) >> norm } } // This is n_mod2_preinv when FLINT64 is true, from ulong_extras/mod2_preinv.c, FLINT 3.1.2. fn mod_preinverted_u64(a: u64, mut n: u64, inverse: u64) -> u64 { assert_ne!(n, 0); let norm = LeadingZeros::leading_zeros(n); n <<= norm; let u1 = a >> (u64::WIDTH - norm); let u0 = a << norm; let (mut q1, mut q0) = u64::x_mul_y_to_zz(inverse, u1); (q1, q0) = u64::xx_add_yy_to_zz(q1, q0, u1, u0); let mut r = u0 - (q1 + 1) * n; if r > q0 { r += n; } if r < n { r >> norm } else { (r - n) >> norm } } // This is n_powmod2_ui_preinv when FLINT64 is false, from ulong_extras/powmod2_ui_preinv.c, FLINT // 3.1.2. fn mod_pow_preinverted_u32(mut a: u32, mut exp: u32, mut n: u32, inverse: u32) -> u32 { assert_ne!(n, 0); if exp == 0 { // anything modulo 1 is 0 return u32::from(n != 1); } if a == 0 { return 0; } if a >= n { a = mod_preinverted_u32(a, n, inverse); } let norm = LeadingZeros::leading_zeros(n); a <<= norm; n <<= norm; while exp.even() { a = mul_mod_helper::(a, a, n, inverse, norm); exp >>= 1; } let mut x = a; loop { exp >>= 1; if exp == 0 { break; } a = mul_mod_helper::(a, a, n, inverse, norm); if exp.odd() { x = mul_mod_helper::(x, a, n, inverse, norm); } } x >> norm } // This is n_powmod2_ui_preinv when FLINT64 is true, from ulong_extras/powmod2_ui_preinv.c, FLINT // 3.1.2. fn mod_pow_preinverted_u64(mut a: u64, mut exp: u64, mut n: u64, inverse: u64) -> u64 { assert_ne!(n, 0); if exp == 0 { // anything modulo 1 is 0 return u64::from(n != 1); } if a == 0 { return 0; } if a >= n { a = mod_preinverted_u64(a, n, inverse); } let norm = LeadingZeros::leading_zeros(n); a <<= norm; n <<= norm; while exp.even() { a = mul_mod_helper::(a, a, n, inverse, norm); exp >>= 1; } let mut x = a; loop { exp >>= 1; if exp == 0 { break; } a = mul_mod_helper::(a, a, n, inverse, norm); if exp.odd() { x = mul_mod_helper::(x, a, n, inverse, norm); } } x >> norm } // This is n_mulmod_precomp when FLINT64 is true, from ulong_extras/mulmod_precomp.c, FLINT 3.1.2. fn mod_mul_preinverted_float(a: u64, b: u64, n: u64, inverse: f64) -> u64 { let q = ((a as f64) * (b as f64) * inverse) as u64; let mut r = (a.wrapping_mul(b)).wrapping_sub(q.wrapping_mul(n)); if r.get_highest_bit() { r.wrapping_add_assign(n); if r.get_highest_bit() { return r.wrapping_add(n); } } else if r >= n { return r - n; } r } // This is n_powmod_ui_precomp when FLINT64 is true, from ulong_extras/powmod_precomp.c, FLINT // 3.1.2. pub(crate) fn mod_pow_preinverted_float(a: u64, mut exp: u64, n: u64, inverse: f64) -> u64 { if n == 1 { return 0; } let mut x = 1; let mut y = a; while exp != 0 { if exp.odd() { x = mod_mul_preinverted_float(x, y, n, inverse); } exp >>= 1; if exp != 0 { y = mod_mul_preinverted_float(y, y, n, inverse); } } x } // This is n_is_probabprime_fermat when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT // 3.1.2. fn is_probable_prime_fermat(n: u64, i: u64) -> bool { (if n.significant_bits() <= FLINT_D_BITS { mod_pow_preinverted_float(i, n - 1, n, 1.0 / (n as f64)) } else { mod_pow_preinverted_u64(i, n - 1, n, u64::precompute_mod_mul_data(&n)) }) == 1 } // This is fchain_precomp when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2. fn fibonacci_chain_precomputed(m: u64, n: u64, inverse: f64) -> (u64, u64) { let mut x = 2; let mut y = n - 3; let mut power = u64::power_of_2(m.significant_bits() - 1); while power != 0 { let xy = mod_mul_preinverted_float(x, y, n, inverse).mod_add(3, n); (x, y) = if m & power != 0 { ( xy, mod_mul_preinverted_float(y, y, n, inverse).mod_sub(2, n), ) } else { ( mod_mul_preinverted_float(x, x, n, inverse).mod_sub(2, n), xy, ) }; power >>= 1; } (x, y) } // This is fchain2_preinv when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2. fn fibonacci_chain_preinvert(m: u64, n: u64, ninv: u64) -> (u64, u64) { let mut x = 2; let mut y = n - 3; let mut power = u64::power_of_2(m.significant_bits() - 1); while power != 0 { let xy = x.mod_mul_precomputed(y, n, &ninv).mod_add(3, n); (x, y) = if m & power != 0 { (xy, y.mod_mul_precomputed(y, n, &ninv).mod_sub(2, n)) } else { (x.mod_mul_precomputed(x, n, &ninv).mod_sub(2, n), xy) }; power >>= 1; } (x, y) } // This is n_is_probabprime_fibonacci when FLINT64 is true, from ulong_extras/is_probabprime.c, // FLINT 3.1.2. fn is_probable_prime_fibonacci(n: u64) -> bool { if i64::wrapping_from(n).le_abs(&3) { return n >= 2; } // cannot overflow as (5 / n) = 0 for n = 2 ^ 64 - 1 let m = n.wrapping_sub(u64::wrapping_from(5.jacobi_symbol(n))) >> 1; if n.significant_bits() <= FLINT_D_BITS { let inverse = 1.0 / (n as f64); let (x, y) = fibonacci_chain_precomputed(m, n, inverse); mod_mul_preinverted_float(n - 3, x, n, inverse) == mod_mul_preinverted_float(2, y, n, inverse) } else { let inverse = u64::precompute_mod_mul_data(&n); let (x, y) = fibonacci_chain_preinvert(m, n, inverse); (n - 3).mod_mul_precomputed(x, n, &inverse) == 2.mod_mul_precomputed(y, n, &inverse) } } // This is lchain_precomp when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2. fn lucas_chain_precomputed(m: u64, a: u64, n: u64, npre: f64) -> (u64, u64) { let mut x = 2; let mut y = n - 3; let mut power = u64::power_of_2(m.significant_bits() - 1); while power != 0 { let xy = mod_mul_preinverted_float(x, y, n, npre).mod_sub(a, n); (x, y) = if m & power != 0 { (xy, mod_mul_preinverted_float(y, y, n, npre).mod_sub(2, n)) } else { (mod_mul_preinverted_float(x, x, n, npre).mod_sub(2, n), xy) }; power >>= 1; } (x, y) } // This is lchain2_preinv when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2. fn lucas_chain_preinvert(m: u64, a: u64, n: u64, ninv: u64) -> (u64, u64) { let mut x = 2; let mut y = a; let mut power = u64::power_of_2(m.significant_bits() - 1); while power != 0 { let xy = x.mod_mul_precomputed(y, n, &ninv).mod_sub(a, n); (x, y) = if m & power != 0 { (xy, y.mod_mul_precomputed(y, n, &ninv).mod_sub(2, n)) } else { (x.mod_mul_precomputed(x, n, &ninv).mod_sub(2, n), xy) }; power >>= 1; } (x, y) } // This is n_is_probabprime_lucas when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT // 3.1.2, where n is odd and greater than 52, and only true or false is returned, rather than 0, 1, // or -1. fn is_probable_prime_lucas(n: u64) -> bool { let mut d = 0u64; if i64::wrapping_from(n).le_abs(&2) { return n == 2; } let mut neg_d = false; let mut j = 0; for i in 0..100 { d = 5 + (i << 1); neg_d = false; if d.gcd(n % d) == 1 { if i.odd() { neg_d = true; } let jacobi = if neg_d { (-i128::from(d)).jacobi_symbol(i128::from(n)) } else { d.jacobi_symbol(n) }; if jacobi == -1 { break; } } else if n != d { return false; } j += 1; } if j == 100 { return true; } if neg_d { d.wrapping_neg_assign(); } let mut q = u64::wrapping_from(1i64.wrapping_sub(i64::wrapping_from(d)) / 4); if q.get_highest_bit() { q.wrapping_add_assign(n); } let a = q.mod_inverse(n).unwrap().mod_sub(2, n); let (left, right) = if n <= FLINT_D_BITS { let inverse = 1.0 / (n as f64); let (x, y) = lucas_chain_precomputed(n + 1, a, n, inverse); ( mod_mul_preinverted_float(a, x, n, inverse), mod_mul_preinverted_float(2, y, n, inverse), ) } else { let inverse = u64::precompute_mod_mul_data(&n); let (x, y) = lucas_chain_preinvert(n + 1, a, n, inverse); ( a.mod_mul_precomputed(x, n, &inverse), 2.mod_mul_precomputed(y, n, &inverse), ) }; left == right } // This is n_is_strong_probabprime2_preinv when FLINT64 is false, from // ulong_extras/is_strong_probabprime2_preinv.c, FLINT 3.1.2. fn is_strong_probable_prime_preinverted_u32(n: u32, inverse: u32, a: u32, d: u32) -> bool { assert!(a < n); let nm1 = n - 1; if a <= 1 || a == nm1 { return true; } let mut t = d; let mut y = mod_pow_preinverted_u32(a, t, n, inverse); if y == 1 { return true; } t <<= 1; while t != nm1 && y != nm1 { y.mod_mul_precomputed_assign(y, n, &inverse); t <<= 1; } y == nm1 } // This is n_is_strong_probabprime2_preinv when FLINT64 is true, from // ulong_extras/is_strong_probabprime2_preinv.c, FLINT 3.1.2. fn is_strong_probable_prime_preinverted_u64(n: u64, inverse: u64, a: u64, d: u64) -> bool { assert!(a < n); let nm1 = n - 1; if a <= 1 || a == nm1 { return true; } let mut t = d; let mut y = mod_pow_preinverted_u64(a, t, n, inverse); if y == 1 { return true; } t <<= 1; while t != nm1 && y != nm1 { y.mod_mul_precomputed_assign(y, n, &inverse); t <<= 1; } y == nm1 } // This is n_mod2_precomp when FLINT64 is true, from ulong_extras/mod2_precomp.c, FLINT 3.1.2. fn mod_preinverted_float(a: u64, n: u64, inverse: f64) -> u64 { if a < n { return a; } let ni = i64::wrapping_from(n); if ni < 0 { return a.wrapping_sub(n); } let (mut q, mut r) = if n == 1 { (a, 0) } else { let q = ((a as f64) * inverse) as u64; ( q, i64::wrapping_from(a).wrapping_sub(i64::wrapping_from(q.wrapping_mul(n))), ) }; if r < ni.wrapping_neg() { q -= ((r.wrapping_neg() as f64) * inverse) as u64; } else if r >= ni { q += ((r as f64) * inverse) as u64; } else if r < 0 { return u64::wrapping_from(r + ni); } else { return u64::wrapping_from(r); } r = i64::wrapping_from(a) - i64::wrapping_from(q.wrapping_mul(n)); u64::wrapping_from(if r >= ni { r.wrapping_sub(ni) } else if r < 0 { r.wrapping_add(ni) } else { r }) } // This is n_is_strong_probabprime_precomp when FLINT64 is true, from // ulong_extras/is_strong_probabprime_precomp.c, FLINT 3.1.2. fn is_strong_probable_prime_preinverted_float(n: u64, inverse: f64, mut a: u64, d: u64) -> bool { // Map large base to range 2 ... n - 1 if a >= n { a = mod_preinverted_float(a, n, inverse); } let nm1 = n - 1; if a <= 1 || a == nm1 { return true; } let mut t = d; let mut y = mod_pow_preinverted_float(a, t, n, inverse); if y == 1 { return true; } t <<= 1; while t != nm1 && y != nm1 { y = mod_mul_preinverted_float(y, y, n, inverse); t <<= 1; } y == nm1 } // This is n_is_probabprime_BPSW when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT // 3.1.2, where n is odd and greater than 1. fn is_probable_prime_bpsw(n: u64) -> bool { let nm10 = n % 10; if nm10 == 3 || nm10 == 7 { return is_probable_prime_fermat(n, 2) && is_probable_prime_fibonacci(n); } let mut d = n - 1; while d.even() { d >>= 1; } let result = if n.significant_bits() <= FLINT_D_BITS { is_strong_probable_prime_preinverted_float(n, 1.0 / (n as f64), 2, d) } else { is_strong_probable_prime_preinverted_u64(n, u64::precompute_mod_mul_data(&n), 2, d) }; if !result { return false; } is_probable_prime_lucas(n) } const FLINT_ODDPRIME_SMALL_CUTOFF: u32 = 4096; // This is n_is_probabprime when FLINT64 is false, from ulong_extras/is_probabprime.c, FLINT 3.1.2, // assuming n is odd and greater than 2. fn is_probable_prime_u32(n: u32) -> bool { if n < FLINT_ODDPRIME_SMALL_CUTOFF { return is_odd_prime_small_u32(n); } let mut d = n - 1; d >>= TrailingZeros::trailing_zeros(d); // For 32-bit, just the 2-base or 3-base Miller-Rabin is enough. let inverse = u32::precompute_mod_mul_data(&n); if n < 9080191 { is_strong_probable_prime_preinverted_u32(n, inverse, 31, d) && is_strong_probable_prime_preinverted_u32(n, inverse, 73, d) } else { is_strong_probable_prime_preinverted_u32(n, inverse, 2, d) && is_strong_probable_prime_preinverted_u32(n, inverse, 7, d) && is_strong_probable_prime_preinverted_u32(n, inverse, 61, d) } } // This is n_is_probabprime when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2, // assuming n is odd and greater than 2. fn is_probable_prime_u64(n: u64) -> bool { if n < u64::from(FLINT_ODDPRIME_SMALL_CUTOFF) { return is_odd_prime_small_u64(n); } else if n >= 1050535501 { // Avoid the unnecessary inverse return is_probable_prime_bpsw(n); } let mut d = n - 1; d >>= TrailingZeros::trailing_zeros(d); let inverse = 1.0 / (n as f64); // For 64-bit, BPSW seems to be a little bit faster than 3 bases. if n < 341531 { is_strong_probable_prime_preinverted_float(n, inverse, 9345883071009581737, d) } else { is_strong_probable_prime_preinverted_float(n, inverse, 336781006125, d) && is_strong_probable_prime_preinverted_float(n, inverse, 9639812373923155, d) } } impl IsPrime for u8 { /// Tests whether a `u8` is prime. /// /// This implementation just does a few divisibility checks. /// /// If you want to generate many small primes, try using /// [`u8::primes`][crate::num::factorization::traits::Primes::primes] instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPrime; /// /// assert_eq!(5u8.is_prime(), true); /// assert_eq!(6u8.is_prime(), false); /// ``` fn is_prime(&self) -> bool { let n = *self; if n < 11 { n == 2 || n == 3 || n == 5 || n == 7 } else if n.even() || n.is_multiple_of(3) || n.is_multiple_of(5) || n.is_multiple_of(7) { false } else { n < 121 || !n.is_multiple_of(11) && !n.is_multiple_of(13) } } } impl IsPrime for u16 { /// Tests whether a `u16` is prime. /// /// This implementation does a few divisibility checks, then performs strong probable prime /// tests with bases 31 and 73, which is enough to prove primality for any integer less than /// $2^{16}$. /// /// If you want to generate many small primes, try using /// [`u16::primes`][crate::num::factorization::traits::Primes::primes] instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPrime; /// /// assert_eq!(5u16.is_prime(), true); /// assert_eq!(6u16.is_prime(), false); /// assert_eq!(65521u16.is_prime(), true); /// ``` fn is_prime(&self) -> bool { // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's // database [1, 2] up to 2^64 by Dana Jacobsen. // - [1] http://www.janfeitsma.nl/math/psp2/database // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html let n = *self; if n < 11 { n == 2 || n == 3 || n == 5 || n == 7 } else if n.even() || n.is_multiple_of(3) || n.is_multiple_of(5) || n.is_multiple_of(7) { false } else if n < 121 { // 11*11 true } else if n.is_multiple_of(11) || n.is_multiple_of(13) || n.is_multiple_of(17) || n.is_multiple_of(19) || n.is_multiple_of(23) || n.is_multiple_of(29) || n.is_multiple_of(31) || n.is_multiple_of(37) || n.is_multiple_of(41) || n.is_multiple_of(43) || n.is_multiple_of(47) || n.is_multiple_of(53) { false } else { n < 3481 || is_probable_prime_u32(u32::from(n)) } } } impl IsPrime for u32 { /// Tests whether a `u32` is prime. /// /// This implementation does a few divisibility checks, then performs a few strong probable /// prime tests, which is enough to prove primality for any integer less than $2^{32}$. /// /// If you want to generate many small primes, try using /// [`u32::primes`][crate::num::factorization::traits::Primes::primes] instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPrime; /// /// assert_eq!(5u32.is_prime(), true); /// assert_eq!(6u32.is_prime(), false); /// assert_eq!(4294967291u32.is_prime(), true); /// ``` fn is_prime(&self) -> bool { // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's // database [1, 2] up to 2^64 by Dana Jacobsen. // - [1] http://www.janfeitsma.nl/math/psp2/database // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html let n = *self; if n < 11 { n == 2 || n == 3 || n == 5 || n == 7 } else if n.even() || n.is_multiple_of(3) || n.is_multiple_of(5) || n.is_multiple_of(7) { false } else if n < 121 { // 11*11 true } else if n.is_multiple_of(11) || n.is_multiple_of(13) || n.is_multiple_of(17) || n.is_multiple_of(19) || n.is_multiple_of(23) || n.is_multiple_of(29) || n.is_multiple_of(31) || n.is_multiple_of(37) || n.is_multiple_of(41) || n.is_multiple_of(43) || n.is_multiple_of(47) || n.is_multiple_of(53) { false } else if n < 3481 { // 59*59 true } else if n > 1000000 && (n.is_multiple_of(59) || n.is_multiple_of(61) || n.is_multiple_of(67) || n.is_multiple_of(71) || n.is_multiple_of(73) || n.is_multiple_of(79) || n.is_multiple_of(83) || n.is_multiple_of(89) || n.is_multiple_of(97) || n.is_multiple_of(101) || n.is_multiple_of(103) || n.is_multiple_of(107) || n.is_multiple_of(109) || n.is_multiple_of(113) || n.is_multiple_of(127) || n.is_multiple_of(131) || n.is_multiple_of(137) || n.is_multiple_of(139) || n.is_multiple_of(149)) { false } else { is_probable_prime_u32(n) } } } impl IsPrime for u64 { /// Tests whether a `u64` is prime. /// /// This implementation first does a few divisibility checks. Then, depending on the input, it /// either runs a few strong probable prime tests or the Baillie–PSW test. This is enough to /// prove primality for any integer less than $2^{64}$. /// /// If you want to generate many small primes, try using /// [`u64::primes`][crate::num::factorization::traits::Primes::primes] instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPrime; /// /// assert_eq!(5u64.is_prime(), true); /// assert_eq!(6u64.is_prime(), false); /// assert_eq!(5509785649208481923u64.is_prime(), true); /// ``` fn is_prime(&self) -> bool { // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's // database [1, 2] up to 2^64 by Dana Jacobsen. // - [1] http://www.janfeitsma.nl/math/psp2/database // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html let n = *self; if n < 11 { n == 2 || n == 3 || n == 5 || n == 7 } else if n.even() || n.is_multiple_of(3) || n.is_multiple_of(5) || n.is_multiple_of(7) { false } else if n < 121 { // 11*11 true } else if n.is_multiple_of(11) || n.is_multiple_of(13) || n.is_multiple_of(17) || n.is_multiple_of(19) || n.is_multiple_of(23) || n.is_multiple_of(29) || n.is_multiple_of(31) || n.is_multiple_of(37) || n.is_multiple_of(41) || n.is_multiple_of(43) || n.is_multiple_of(47) || n.is_multiple_of(53) { false } else if n < 3481 { // 59*59 true } else if n > 1000000 && (n.is_multiple_of(59) || n.is_multiple_of(61) || n.is_multiple_of(67) || n.is_multiple_of(71) || n.is_multiple_of(73) || n.is_multiple_of(79) || n.is_multiple_of(83) || n.is_multiple_of(89) || n.is_multiple_of(97) || n.is_multiple_of(101) || n.is_multiple_of(103) || n.is_multiple_of(107) || n.is_multiple_of(109) || n.is_multiple_of(113) || n.is_multiple_of(127) || n.is_multiple_of(131) || n.is_multiple_of(137) || n.is_multiple_of(139) || n.is_multiple_of(149)) { false } else { is_probable_prime_u64(n) } } } impl IsPrime for usize { /// Tests whether a `usize` is prime. /// /// This implementation first does a few divisibility checks. Then, depending on the input, it /// either runs a few strong probable prime tests or the Baillie–PSW test. This is enough to /// prove primality for any integer that fits in a `usize`. /// /// If you want to generate many small primes, try using /// [`usize::primes`][crate::num::factorization::traits::Primes::primes] instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPrime; /// /// assert_eq!(5usize.is_prime(), true); /// assert_eq!(6usize.is_prime(), false); /// assert_eq!(4294967291usize.is_prime(), true); /// ``` #[inline] fn is_prime(&self) -> bool { if USIZE_IS_U32 { u32::wrapping_from(*self).is_prime() } else { u64::wrapping_from(*self).is_prime() } } } ================================================ FILE: malachite-base/src/num/factorization/is_square.rs ================================================ // Copyright © 2026 William Youmans // // Uses code adopted from the FLINT Library. // // Copyright © 2009 William Hart // // 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 crate::num::arithmetic::traits::{CheckedSqrt, FloorSqrt, Square}; use crate::num::basic::integers::PrimitiveInt; use crate::num::conversion::traits::{SplitInHalf, WrappingFrom}; use crate::num::factorization::traits::IsSquare; const IS_SQUARE_MOD64: [bool; 64] = [ true, true, false, false, true, false, false, false, false, true, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, true, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, ]; const IS_SQUARE_MOD65: [bool; 65] = [ true, true, false, false, true, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false, false, false, true, true, false, false, true, true, false, false, false, false, false, false, false, false, true, false, true, false, false, false, true, true, false, false, false, false, true, false, false, true, ]; const IS_SQUARE_MOD63: [bool; 63] = [ true, true, false, false, true, false, false, true, false, true, false, false, false, false, true, false, true, false, true, false, false, false, true, false, false, true, false, false, true, false, false, false, false, false, false, true, true, true, false, false, false, false, false, true, false, false, true, false, false, true, false, false, false, false, false, false, true, false, true, false, false, false, false, ]; // This is n_is_square when FLINT64 is false, from ulong_extras/is_square.c, FLINT 3.1.2. fn is_square_u64(x: u64) -> bool { IS_SQUARE_MOD64[(x % 64) as usize] && IS_SQUARE_MOD63[(x % 63) as usize] && IS_SQUARE_MOD65[(x % 65) as usize] && x.floor_sqrt().square() == x } macro_rules! impl_unsigned { ($t: ident) => { impl IsSquare for $t { /// Determines whether an integer is a perfect square. /// /// $f(x) = (\exists b \in \Z : b^2 = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_square#is_square). #[inline] fn is_square(&self) -> bool { is_square_u64(u64::wrapping_from(*self)) } } }; } impl_unsigned!(u8); impl_unsigned!(u16); impl_unsigned!(u32); impl_unsigned!(u64); impl_unsigned!(usize); // From mpn/generic/mod_34lsub1.c const B1: u64 = u64::WIDTH >> 2; const B2: u64 = B1 * 2; const B3: u64 = B1 * 3; const M2: u64 = (1 << B2) - 1; const M3: u64 = (1 << B3) - 1; const fn low0(n: u64) -> u64 { n & M3 } const fn high0(n: u64) -> u64 { n >> B3 } const fn low1(n: u64) -> u64 { (n & M2) << B1 } const fn high1(n: u64) -> u64 { n >> B2 } // This is mpn_mod_34lsub1 from mpn/generic/mod_34lsub1.c, GMP 6.3.0. // // Calculate a remainder from `limbs` divided by 2^(u64::WIDTH*3/4)-1. The remainder is not fully // reduced, it's any limb value congruent to `limbs` modulo that divisor. // // Check gen-psqr.c. mpn_mod_34lsub1 preferred over mpn_mod_1 (plus a PERFSQR_PP modulus) with 32 // and 64 bit limb. const fn mod_34lsub1(x_hi: u64, x_lo: u64) -> u64 { low0(x_lo) + high0(x_lo) + low1(x_hi) + high1(x_hi) } const MOD34_BITS: u64 = (u64::WIDTH >> 2) * 3; const MOD34_MASK: u64 = (1 << MOD34_BITS) - 1; const fn perfsqr_mod_34(x_hi: u64, x_lo: u64) -> u64 { let r = mod_34lsub1(x_hi, x_lo); (r & MOD34_MASK) + (r >> MOD34_BITS) } // This is PERFSQR_MOD_BITS from mpn/perfsqr.h, GMP 6.3.0. Either 49 on 64 bit limb or 25 on 32 bit // limb. 2^48-1 = 3^2 * 5 * 7 * 13 * 17 * 97 ... 2^24-1 = 3^2 * 5 * 7 * 13 * 17 ... const SQR_MOD_BITS: u64 = MOD34_BITS + 1; const SQR_MOD_MASK: u64 = (1 << SQR_MOD_BITS) - 1; const fn perfsqr_mod_idx(r: u64, d: u64, inv: u64) -> u64 { assert!(r <= SQR_MOD_MASK); assert!(inv.wrapping_mul(d) & SQR_MOD_MASK == 1); assert!(u64::MAX / d >= SQR_MOD_MASK); let q = r.wrapping_mul(inv) & SQR_MOD_MASK; assert!(r == (q.wrapping_mul(d) & SQR_MOD_MASK)); q.wrapping_mul(d) >> SQR_MOD_BITS } // Single limb. Check precomputed bitmasks to see if remainder is a quadratic residue fn perfsqr_mod_1(r: u64, d: u64, inv: u64, mask: u64) -> bool { assert!(d <= u64::WIDTH); let idx = perfsqr_mod_idx(r, d, inv); if (mask >> idx) & 1 == 0 { // non-square return false; } true } // Double limb. Check precomputed bitmasks to see if remainder is a quadratic residue fn perfsqr_mod_2(r: u64, d: u64, inv: u64, mhi: u64, mlo: u64) -> bool { assert!(d <= const { 2 * u64::WIDTH }); let mut idx = perfsqr_mod_idx(r, d, inv); let m = if idx < u64::WIDTH { mlo } else { mhi }; idx %= u64::WIDTH; if (m >> idx) & 1 == 0 { // non-square return false; } true } // This test identifies 97.81% as non-squares. Grand total sq_res_0x100 and PERFSQR_MOD_TEST, 99.62% // non-squares. fn perfsqr_mod_test(x: u128) -> bool { let (x_hi, x_lo) = x.split_in_half(); let r = perfsqr_mod_34(x_hi, x_lo); perfsqr_mod_2(r, 91, 0xfd2fd2fd2fd3, 0x2191240, 0x8850a206953820e1) // 69.23% && perfsqr_mod_2(r, 85, 0xfcfcfcfcfcfd, 0x82158, 0x10b48c4b4206a105) // 68.24% && perfsqr_mod_1(r, 9, 0xe38e38e38e39, 0x93) // 55.56% && perfsqr_mod_2(r, 97, 0xfd5c5f02a3a1, 0x1eb628b47, 0x6067981b8b451b5f) // 49.48% } // This is sq_res0x100 from mpn/perfsqr.h when generated for 64 bit limb, GMP 6.3.0. Non-zero bit // indicates a quadratic residue mod 0x100. This test identifies 82.81% as non-squares (212/256). const SQR_MOD256: [u64; 4] = [0x202021202030213, 0x202021202020213, 0x202021202030212, 0x202021202020212]; impl IsSquare for u128 { /// Determines whether an integer is a perfect square. /// /// $f(x) = (\exists b \in \Z : b^2 = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_square#is_square). #[inline] fn is_square(&self) -> bool { let idx = self % 0x100; // mod 256 // The first test excludes 212/256 (82.8%) of the perfect square candidates in O(1) time. // // This just checks the particular bit in the bitmask SQR_MOD256_U64 encoding where the // input can be a perfect square mod 256. if (SQR_MOD256[(idx >> u64::LOG_WIDTH) as usize] >> (idx & const { u64::WIDTH_MASK as Self })) & 1 == 0 { return false; } // The second test uses mpn_mod_34lsub1 to detect non-squares according to their residues // modulo small primes (or powers of primes). See mpn/perfsqr.h, GMP 6.3.0. if !perfsqr_mod_test(*self) { return false; } // For the third and last test, we finally compute the square root, to make sure we've // really got a perfect square. self.checked_sqrt().is_some() } } macro_rules! impl_signed { ($t: ident) => { impl IsSquare for $t { /// Determines whether an integer is a perfect square. /// /// $f(x) = (\exists b \in \Z : b^2 = x)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::is_square#is_square). #[inline] fn is_square(&self) -> bool { if *self < 0 { false } else { self.unsigned_abs().is_square() } } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-base/src/num/factorization/mod.rs ================================================ // Copyright © 2026 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 . /// [`Factor`](traits::Factor), a trait for computing the prime factorization of a number. pub mod factor; /// [`IsPower`](traits::IsPower) and [`ExpressAsPower`](traits::ExpressAsPower), traits for testing /// if a number is a perfect power and, if it is, expressing it as such. /// /// # is_power /// ``` /// use malachite_base::num::factorization::traits::IsPower; /// /// assert!(0u8.is_power()); /// assert!(1u16.is_power()); /// assert!(36u32.is_power()); /// assert!(64u32.is_power()); /// assert!(100u64.is_power()); /// assert!(1728u64.is_power()); /// /// assert!(0u8.is_power()); /// assert!(1u16.is_power()); /// assert!(!2u64.is_power()); /// assert!(!3u64.is_power()); /// ``` /// /// # express_as_power /// ``` /// use malachite_base::num::factorization::traits::ExpressAsPower; /// /// assert_eq!(0u8.express_as_power().unwrap(), (0, 2)); /// assert_eq!(1u16.express_as_power().unwrap(), (1, 2)); /// assert_eq!(36u32.express_as_power().unwrap(), (6, 2)); /// assert_eq!(64u32.express_as_power().unwrap(), (2, 6)); /// assert_eq!(100u64.express_as_power().unwrap(), (10, 2)); /// assert_eq!(1728u64.express_as_power().unwrap(), (12, 3)); /// /// assert!(0u8.express_as_power().is_some()); /// assert!(1u16.express_as_power().is_some()); /// assert!(2u64.express_as_power().is_none()); /// assert!(3u64.express_as_power().is_none()); /// ``` pub mod is_power; /// [`IsPrime`](traits::IsPrime), a trait for testing a number for primality. pub mod is_prime; /// [`IsSquare`](traits::IsSquare), a trait for testing if a number if a perfect square. /// /// # is_square /// ``` /// use malachite_base::num::factorization::traits::IsSquare; /// /// assert!(0u8.is_square()); /// assert!(1u16.is_square()); /// assert!(4u32.is_square()); /// assert!(256u64.is_square()); /// /// assert!(!2u8.is_square()); /// assert!(!5u16.is_square()); /// assert!(!8u32.is_square()); /// assert!(!128u64.is_square()); /// ``` pub mod is_square; /// An efficient prime sieve. pub mod prime_sieve; /// [`Primes`](traits::Primes), a trait for generating prime numbers. /// /// # primes_less_than /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Primes; /// /// assert_eq!(u8::primes_less_than(&10).collect_vec(), &[2, 3, 5, 7]); /// assert_eq!(u16::primes_less_than(&11).collect_vec(), &[2, 3, 5, 7]); /// assert_eq!( /// u32::primes_less_than(&100).collect_vec(), /// &[ /// 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, /// 89, 97 /// ] /// ); /// ``` /// /// # primes_less_than_or_equal_to /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Primes; /// /// assert_eq!( /// u8::primes_less_than_or_equal_to(&10).collect_vec(), /// &[2, 3, 5, 7] /// ); /// assert_eq!( /// u16::primes_less_than_or_equal_to(&11).collect_vec(), /// &[2, 3, 5, 7, 11] /// ); /// assert_eq!( /// u32::primes_less_than_or_equal_to(&100).collect_vec(), /// &[ /// 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, /// 89, 97 /// ] /// ); /// ``` /// /// # primes /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Primes; /// /// assert_eq!( /// u8::primes().collect_vec(), /// &[ /// 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, /// 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, /// 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 /// ] /// ); /// ``` pub mod primes; /// [`PrimitiveRootPrime`](traits::PrimitiveRootPrime), a trait for finding a primitive root modulo /// a prime number. /// /// # primitive_root_prime /// ``` /// use malachite_base::num::factorization::traits::PrimitiveRootPrime; /// /// assert_eq!(5u32.primitive_root_prime(), 2); /// assert_eq!(191u32.primitive_root_prime(), 19); /// assert_eq!(4294967291u32.primitive_root_prime(), 2); /// ``` pub mod primitive_root_prime; /// Various traits for generating primes, primality testing, and factorization. pub mod traits; ================================================ FILE: malachite-base/src/num/factorization/prime_sieve.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `primesieve.c` contributed to the GNU project by Marco Bodrato. // // Copyright © 2010-2012, 2015, 2016 Free Software Foundation, Inc. // // 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 crate::num::basic::integers::PrimitiveInt; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactFrom; use crate::num::logic::traits::CountOnes; pub const SIEVE_SEED_U32: u32 = 0x69128480; // 70bits pre-sieved mask for primes 5, 7 pub const SIEVE_MASK1_U32: u32 = 0x12148960; pub const SIEVE_MASK2_U32: u32 = 0x44a120cc; pub const SIEVE_MASKT_U32: u32 = 0x1a; pub const SEED_LIMIT_U32: u64 = 120; pub const SIEVE_SEED_U64: u64 = 0x3294C9E069128480; // 110bits pre-sieved mask for primes 5, 11 pub const SIEVE_MASK1_U64: u64 = 0x81214a1204892058; pub const SIEVE_MASKT_U64: u64 = 0xc8130681244; // 182bits pre-sieved mask for primes 7, 13 pub const SIEVE_2MSK1_U64: u64 = 0x9402180c40230184; pub const SIEVE_2MSK2_U64: u64 = 0x0285021088402120; pub const SIEVE_2MSKT_U64: u64 = 0xa41210084421; pub const SEED_LIMIT_U64: u64 = 210; const C70M2U32W: u64 = 70 - (u32::WIDTH << 1); const C70MU32W: u64 = 70 - u32::WIDTH; const C2U32W: u64 = u32::WIDTH << 1; const C3U32WM70: u64 = 3 * u32::WIDTH - 70; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bit_array.len()`. // // This is equivalent to `fill_bitpattern` from `primesieve.c`, GMP 6.2.1. fn fill_bitpattern_u32(bit_array: &mut [u32], mut offset: u64) -> u64 { let mut len = bit_array.len(); let (mut mask, mut mask2, mut tail) = if offset == 0 { (SIEVE_MASK1_U32, SIEVE_MASK2_U32, SIEVE_MASKT_U32) } else { offset %= 70; if offset != 0 { if offset <= u32::WIDTH { let offset_comp = u32::WIDTH - offset; let mut mask = SIEVE_MASK2_U32 << offset_comp; let mut mask2 = SIEVE_MASKT_U32 << offset_comp; if offset != u32::WIDTH { mask |= SIEVE_MASK1_U32 >> offset; mask2 |= SIEVE_MASK2_U32 >> offset; } let tail = if offset <= C70M2U32W { (SIEVE_MASK1_U32 << (C70M2U32W - offset)) | (SIEVE_MASKT_U32 >> offset) } else { mask2 |= SIEVE_MASK1_U32 << (C70MU32W - offset); SIEVE_MASK1_U32 >> (offset - C70M2U32W) }; (mask, mask2, tail) } else if offset < C2U32W { let mut mask = (SIEVE_MASK2_U32 >> (offset - u32::WIDTH)) | (SIEVE_MASKT_U32 << (C2U32W - offset)); if offset <= C70MU32W { let mut tail = SIEVE_MASK2_U32 << (C70MU32W - offset); if offset != C70MU32W { tail |= SIEVE_MASK1_U32 >> (offset - C70M2U32W); } ( mask, (SIEVE_MASKT_U32 >> (offset - u32::WIDTH)) | (SIEVE_MASK1_U32 << (C70MU32W - offset)), tail, ) } else { let d70_offset = 70 - offset; let width_m_d70_offset = u32::WIDTH - d70_offset; mask |= SIEVE_MASK1_U32 << d70_offset; ( mask, (SIEVE_MASK2_U32 << d70_offset) | (SIEVE_MASK1_U32 >> width_m_d70_offset), SIEVE_MASK2_U32 >> width_m_d70_offset, ) } } else { let d70_offset = 70 - offset; let width_m_d70_offset = u32::WIDTH - d70_offset; ( (SIEVE_MASK1_U32 << d70_offset) | (SIEVE_MASKT_U32 >> (offset - C2U32W)), (SIEVE_MASK2_U32 << d70_offset) | (SIEVE_MASK1_U32 >> width_m_d70_offset), (SIEVE_MASKT_U32 << d70_offset) | (SIEVE_MASK2_U32 >> width_m_d70_offset), ) } } else { (SIEVE_MASK1_U32, SIEVE_MASK2_U32, SIEVE_MASKT_U32) } }; for xs in bit_array.chunks_mut(2) { xs[0] = mask; len -= 1; if len == 0 { break; } xs[1] = mask2; let temp = mask2 >> C3U32WM70; mask2 = (mask2 << C70M2U32W) | (mask >> C3U32WM70); mask = (mask << C70M2U32W) | tail; tail = temp; len -= 1; if len == 0 { break; } } 2 } const C110MU64W: u64 = 110 - u64::WIDTH; const C2U64WM110: u64 = (u64::WIDTH << 1) - 110; const C182MU64W: u64 = 182 - u64::WIDTH; const C182M2U64W: u64 = 182 - (u64::WIDTH << 1); const C3U64WM182: u64 = 3 * u64::WIDTH - 182; const C2U64W: u64 = u64::WIDTH << 1; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bit_array.len()`. // // This is equivalent to `fill_bitpattern` from `primesieve.c`, GMP 6.2.1. fn fill_bitpattern_u64(bit_array: &mut [u64], mut offset: u64) -> u64 { let mut len = bit_array.len(); let ((mut m11, mut m12), (mut m21, mut m22, mut m23)) = if offset == 0 { ( (SIEVE_MASK1_U64, SIEVE_MASKT_U64), (SIEVE_2MSK1_U64, SIEVE_2MSK2_U64, SIEVE_2MSKT_U64), ) } else { // correctly handle offset == 0... let mut m21 = offset % 110; let (m11, m12) = if m21 != 0 { if m21 < u64::WIDTH { let mut m11 = (SIEVE_MASK1_U64 >> m21) | (SIEVE_MASKT_U64 << (u64::WIDTH - m21)); if m21 <= C110MU64W { ( m11, (SIEVE_MASK1_U64 << (C110MU64W - m21)) | (SIEVE_MASKT_U64 >> m21), ) } else { m11 |= SIEVE_MASK1_U64 << (110 - m21); (m11, SIEVE_MASK1_U64 >> (m21 - C110MU64W)) } } else { ( (SIEVE_MASK1_U64 << (110 - m21)) | (SIEVE_MASKT_U64 >> (m21 - u64::WIDTH)), (SIEVE_MASKT_U64 << (110 - m21)) | (SIEVE_MASK1_U64 >> (m21 - C110MU64W)), ) } } else { (SIEVE_MASK1_U64, SIEVE_MASKT_U64) }; ((m11, m12), { offset %= 182; if offset != 0 { if offset <= u64::WIDTH { let mut m21 = SIEVE_2MSK2_U64 << (u64::WIDTH - offset); let mut m22 = SIEVE_2MSKT_U64 << (u64::WIDTH - offset); if offset != u64::WIDTH { m21 |= SIEVE_2MSK1_U64 >> offset; m22 |= SIEVE_2MSK2_U64 >> offset; } if offset <= C182M2U64W { ( m21, m22, (SIEVE_2MSK1_U64 << (C182M2U64W - offset)) | (SIEVE_2MSKT_U64 >> offset), ) } else { m22 |= SIEVE_2MSK1_U64 << (C182MU64W - offset); (m21, m22, SIEVE_2MSK1_U64 >> (offset - C182M2U64W)) } } else if offset < C2U64W { m21 = (SIEVE_2MSK2_U64 >> (offset - u64::WIDTH)) | (SIEVE_2MSKT_U64 << (C2U64W - offset)); if offset <= C182MU64W { let mut m23 = SIEVE_2MSK2_U64 << (C182MU64W - offset); if offset != C182MU64W { m23 |= SIEVE_2MSK1_U64 >> (offset - C182M2U64W); } ( m21, (SIEVE_2MSKT_U64 >> (offset - u64::WIDTH)) | (SIEVE_2MSK1_U64 << (C182MU64W - offset)), m23, ) } else { m21 |= SIEVE_2MSK1_U64 << (182 - offset); ( m21, (SIEVE_2MSK2_U64 << (182 - offset)) | (SIEVE_2MSK1_U64 >> (offset - C182MU64W)), SIEVE_2MSK2_U64 >> (offset - C182MU64W), ) } } else { ( (SIEVE_2MSK1_U64 << (182 - offset)) | (SIEVE_2MSKT_U64 >> (offset - C2U64W)), (SIEVE_2MSK2_U64 << (182 - offset)) | (SIEVE_2MSK1_U64 >> (offset - C182MU64W)), (SIEVE_2MSKT_U64 << (182 - offset)) | (SIEVE_2MSK2_U64 >> (offset - C182MU64W)), ) } } else { (SIEVE_2MSK1_U64, SIEVE_2MSK2_U64, SIEVE_2MSKT_U64) } }) }; for xs in bit_array.chunks_mut(2) { xs[0] = m11 | m21; len -= 1; if len == 0 { break; } let temp = m11 >> C2U64WM110; m11 = (m11 << C110MU64W) | m12; m12 = temp; xs[1] = m11 | m22; let temp = m11 >> C2U64WM110; m11 = (m11 << C110MU64W) | m12; m12 = temp; let temp = m22 >> C3U64WM182; m22 = (m22 << C182M2U64W) | (m21 >> C3U64WM182); m21 = (m21 << C182M2U64W) | m23; m23 = temp; len -= 1; if len == 0 { break; } } 4 } #[doc(hidden)] // This is equivalent to `n_to_bit` from `primesieve.c`, GMP 6.2.1. pub const fn n_to_bit(n: u64) -> u64 { ((n - 5) | 1) / 3 } #[doc(hidden)] // This is equivalent to `id_to_n` from `primesieve.c`, GMP 6.2.1. pub const fn id_to_n(id: u64) -> u64 { id * 3 + 1 + (id & 1) } // # Worst-case complexity // $T(n) = O(n\log\log n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bit_array.len()`. // // This is equivalent to `first_block_primesieve` from `primesieve.c`, GMP 6.2.1. fn first_block_primesieve u64>( bit_array: &mut [T], n: u64, fill_bitpattern: F, sieve_seed: T, seed_limit: u64, ) { assert!(n > 4); let bits = n_to_bit(n); let limbs = usize::exact_from(bits >> T::LOG_WIDTH); let mut i = if limbs == 0 { 0 } else { fill_bitpattern(&mut bit_array[1..=limbs], 0) }; bit_array[0] = sieve_seed; if (bits + 1) & T::WIDTH_MASK != 0 { bit_array[limbs] |= T::MAX << ((bits + 1) & T::WIDTH_MASK); } if n > seed_limit { assert!(i < T::WIDTH); if n_to_bit(seed_limit + 1) < T::WIDTH { i = 0; } let mut mask = T::power_of_2(i); let mut index = 0; for i in i + 1.. { if bit_array[index] & mask == T::ZERO { let mut step = id_to_n(i); // lindex = n_to_bit(id_to_n(i) * id_to_n(i)); let mut lindex = i * (step + 1) - 1 + ((i & 1).wrapping_neg() & (i + 1)); // lindex = i * (step + 1 + (i & 1)) - 1 + (i & 1); if lindex > bits { break; } step <<= 1; let maskrot = step & T::WIDTH_MASK; let mut lmask = T::power_of_2(lindex & T::WIDTH_MASK); while lindex <= bits { bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask; lmask.rotate_left_assign(maskrot); lindex += step; } // lindex = n_to_bit(id_to_n(i) * bit_to_n(i)); lindex = i * (i * 3 + 6) + (i & 1); lmask = T::power_of_2(lindex & T::WIDTH_MASK); while lindex <= bits { bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask; lmask.rotate_left_assign(maskrot); lindex += step; } } mask <<= 1; if mask == T::ZERO { mask = T::ONE; index += 1; } } } } // # Worst-case complexity // $T(n) = O(n\log\log n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bit_array.len()`. // // This is equivalent to `block_resieve` from `primesieve.c`, GMP 6.2.1. fn block_resieve u64>( bit_array: &mut [T], offset: u64, sieve: &[T], fill_bitpattern: &F, ) { let limbs = bit_array.len(); let off = offset; assert_ne!(limbs, 0); assert!(offset >= T::WIDTH); let bits = u64::exact_from(limbs << T::LOG_WIDTH) - 1; let i = fill_bitpattern(&mut bit_array[..limbs], offset - T::WIDTH); assert!(i < T::WIDTH); let mut mask = T::power_of_2(i); let mut index = 0; for i in i + 1.. { if sieve[index] & mask == T::ZERO { let mut step = id_to_n(i); // lindex = n_to_bit(id_to_n(i)*id_to_n(i)); let mut lindex = i * (step + 1) - 1 + ((i & 1).wrapping_neg() & (i + 1)); // lindex = i*(step+1+(i&1))-1+(i&1); if lindex > bits + off { break; } step <<= 1; let maskrot = step & T::WIDTH_MASK; if lindex < off { lindex += step * ((off - lindex - 1) / step + 1); } lindex -= off; let mut lmask = T::power_of_2(lindex & T::WIDTH_MASK); while lindex <= bits { bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask; lmask.rotate_left_assign(maskrot); lindex += step; } // lindex = n_to_bit(id_to_n(i)*bit_to_n(i)); lindex = i * (i * 3 + 6) + (i & 1); if lindex < off { lindex += step * ((off - lindex - 1) / step + 1); } lindex -= off; lmask = T::power_of_2(lindex & T::WIDTH_MASK); while lindex <= bits { bit_array[usize::exact_from(lindex >> T::LOG_WIDTH)] |= lmask; lmask.rotate_left_assign(maskrot); lindex += step; } } mask <<= 1; if mask == T::ZERO { mask = T::ONE; index += 1; } } } #[doc(hidden)] #[inline] // This is equivalent to `primesieve_size` from `primesieve.c`, GMP 6.2.1. pub fn limbs_prime_sieve_size(n: u64) -> usize { assert!(n >= 5); usize::exact_from((n_to_bit(n) >> T::LOG_WIDTH) + 1) } const BLOCK_SIZE: usize = 2048; pub_test! {limbs_count_ones(xs: &[T]) -> u64 { xs.iter().map(|&x| CountOnes::count_ones(x)).sum() }} // Fills bit_array with the characteristic function of composite numbers up to the parameter n. I.e. // a bit set to "1" represent a composite, a "0" represent a prime. // // The primesieve_size(n) limbs pointed to by bit_array are overwritten. The returned value counts // prime integers in the interval [4, n]. Note that n > 4. // // Even numbers and multiples of 3 are excluded "a priori", only numbers equivalent to +/- 1 mod 6 // have their bit in the array. // // Once sieved, if the bit b is ZERO it represent a prime, the represented prime is bit_to_n(b), if // the LSbit is bit 0, or id_to_n(b), if you call "1" the first bit. // // # Worst-case complexity // $T(n) = O(n\log\log n)$ // // $M(n) = O(1)$ fn limbs_prime_sieve_generic u64>( bit_array: &mut [T], n: u64, fill_bitpattern: F, sieve_seed: T, seed_limit: u64, ) -> u64 { assert!(n > 4); let bits = n_to_bit(n); let size = usize::exact_from((bits >> T::LOG_WIDTH) + 1); if size > BLOCK_SIZE << 1 { let mut off = BLOCK_SIZE + (size % BLOCK_SIZE); first_block_primesieve( bit_array, id_to_n(u64::exact_from(off) << T::LOG_WIDTH), &fill_bitpattern, sieve_seed, seed_limit, ); let (sieve, bit_array) = bit_array.split_at_mut(off); for xs in bit_array.chunks_mut(BLOCK_SIZE) { block_resieve( xs, u64::exact_from(off) << T::LOG_WIDTH, sieve, &fill_bitpattern, ); off += BLOCK_SIZE; if off >= size { break; } } } else { first_block_primesieve(bit_array, n, &fill_bitpattern, sieve_seed, seed_limit); } if (bits + 1) & T::WIDTH_MASK != 0 { bit_array[size - 1] |= T::MAX << ((bits + 1) & T::WIDTH_MASK); } (u64::exact_from(size) << T::LOG_WIDTH) - limbs_count_ones(&bit_array[..size]) } #[doc(hidden)] // This is equivalent to `gmp_primesieve` from `primesieve.c`, GMP 6.2.1. #[inline] pub fn limbs_prime_sieve_u32(bit_array: &mut [u32], n: u64) -> u64 { limbs_prime_sieve_generic( bit_array, n, fill_bitpattern_u32, SIEVE_SEED_U32, SEED_LIMIT_U32, ) } #[doc(hidden)] // This is equivalent to `gmp_primesieve` from `primesieve.c`, GMP 6.2.1. #[inline] pub fn limbs_prime_sieve_u64(bit_array: &mut [u64], n: u64) -> u64 { limbs_prime_sieve_generic( bit_array, n, fill_bitpattern_u64, SIEVE_SEED_U64, SEED_LIMIT_U64, ) } ================================================ FILE: malachite-base/src/num/factorization/primes.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library and the FLINT Library. // // Prime sieve code contributed to the GNU project by Marco Bodrato. // // Copyright © 2009 Tom Boothby // // Copyright © 2009 William Hart // // Copyright © 2010 Fredrik Johansson // // Copyright © 2010–2012, 2015, 2016 Free Software Foundation, Inc. // // 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::factorization::prime_sieve::n_to_bit; use crate::num::factorization::prime_sieve::{ id_to_n, limbs_prime_sieve_size, limbs_prime_sieve_u64, }; use crate::num::factorization::traits::Primes; use crate::num::logic::traits::TrailingZeros; use alloc::vec::Vec; use core::marker::PhantomData; const NUM_SMALL_PRIMES: usize = 172; // This is flint_primes_small from ulong_extras/compute_primes.c, FLINT 3.1.2. pub(crate) const SMALL_PRIMES: [u16; NUM_SMALL_PRIMES] = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, ]; // This differs from the identically-named function in malachite-nz; this one returns None if there // are no more false bits. fn limbs_index_of_next_false_bit(xs: &[T], start: u64) -> Option { let starting_index = usize::exact_from(start >> T::LOG_WIDTH); if starting_index >= xs.len() { return None; } if let Some(result) = xs[starting_index].index_of_next_false_bit(start & T::WIDTH_MASK) && result != T::WIDTH { return Some((u64::wrapping_from(starting_index) << T::LOG_WIDTH) + result); } if starting_index == xs.len() - 1 { return None; } let false_index = starting_index + 1 + xs[starting_index + 1..] .iter() .take_while(|&&y| y == T::MAX) .count(); if false_index == xs.len() { None } else { Some( (u64::exact_from(false_index) << T::LOG_WIDTH) + TrailingZeros::trailing_zeros(!xs[false_index]), ) } } /// An iterator over that generates all primes less than a given value. /// /// This `struct` is created by [`Primes::primes_less_than`] and /// [`Primes::primes_less_than_or_equal_to`]; see their documentation for more. #[derive(Clone, Debug)] pub struct PrimesLessThanIterator { small: bool, i: u64, limit: T, sieve: Vec, phantom: PhantomData<*const T>, } impl PrimesLessThanIterator { fn new(n: T) -> Self { let limit = n; let n: u64 = n.saturating_into(); let mut sieve; // 1031 is the smallest prime greater than 2^10. if n < 1031 { sieve = Vec::with_capacity(0); } else { sieve = alloc::vec![0; limbs_prime_sieve_size::(n)]; limbs_prime_sieve_u64(&mut sieve, n); } Self { small: true, i: 0, limit, sieve, phantom: PhantomData, } } /// Moves the iterator to just after a given value, returning whether the iterator will return /// any more values after that point. If `false` is returned, calling `next` will return `None`; /// if `true` is returned, calling `next` will return smallest prime greater than $n$. /// /// # Worst-case complexity (amortized) /// $T(n) = O(n\log \log n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::Primes; /// /// let mut primes = u32::primes_less_than(&10_000); /// assert_eq!(primes.jump_after(1000), true); /// assert_eq!(primes.next(), Some(1009)); /// /// assert_eq!(primes.jump_after(10_000), false); /// assert_eq!(primes.next(), None); /// ``` pub fn jump_after(&mut self, n: T) -> bool { // 1021 is the greatest prime smaller than 2^10. if n < T::saturating_from(1021) { self.small = true; self.i = u64::wrapping_from(match SMALL_PRIMES.binary_search(&n.wrapping_into()) { Ok(i) => i + 1, Err(i) => i, }); if self.i == NUM_SMALL_PRIMES as u64 { if self.sieve.is_empty() { false } else { self.small = false; const NEXT_INDEX: u64 = n_to_bit(1031) - 1; self.i = NEXT_INDEX; let next_i = if let Some(next_i) = limbs_index_of_next_false_bit(&self.sieve, self.i) { next_i } else { return false; }; let next_p = T::exact_from(id_to_n(next_i + 1)); next_p <= self.limit } } else if let Ok(next_p) = T::try_from(SMALL_PRIMES[self.i as usize]) { next_p <= self.limit } else { false } } else { self.small = false; self.i = if let Ok(n) = n.try_into() { n_to_bit(n) + 1 } else { return false; }; let next_i = if let Some(next_i) = limbs_index_of_next_false_bit(&self.sieve, self.i) { next_i } else { return false; }; let next_p = T::exact_from(id_to_n(next_i + 1)); next_p <= self.limit } } } impl Iterator for PrimesLessThanIterator { type Item = T; fn next(&mut self) -> Option { if self.small { let p = if let Ok(p) = T::try_from(SMALL_PRIMES[self.i as usize]) { p } else { return None; }; if p > self.limit { return None; } self.i += 1; if self.i == NUM_SMALL_PRIMES as u64 { self.small = false; const NEXT_INDEX: u64 = n_to_bit(1031) - 1; self.i = NEXT_INDEX; } Some(p) } else { self.i = limbs_index_of_next_false_bit(&self.sieve, self.i)? + 1; let p = T::exact_from(id_to_n(self.i)); if p > self.limit { None } else { Some(p) } } } } /// An iterator over that generates all primes. /// /// This `struct` is created by [`Primes::primes`]; see its documentation for more. #[derive(Clone, Debug)] pub struct PrimesIterator { limit: T, xs: PrimesLessThanIterator, } impl PrimesIterator { fn new() -> Self { let limit = T::saturating_from(1024u16); Self { limit, xs: PrimesLessThanIterator::new(limit), } } /// Moves the iterator to just after a given value, returning whether the iterator will return /// any more values after that point. If `false` is returned, calling `next` will return `None` /// (which only happens if $n$ is very close to the maximum value of `T`); if `true` is /// returned, calling `next` will return smallest prime greater than $n$. /// /// # Worst-case complexity (amortized) /// $T(n) = O(n\log \log n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n`. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::Primes; /// /// let mut primes = u16::primes(); /// assert_eq!(primes.jump_after(1000), true); /// assert_eq!(primes.next(), Some(1009)); /// /// assert_eq!(primes.jump_after(u16::MAX), false); /// assert_eq!(primes.next(), None); /// ``` pub fn jump_after(&mut self, n: T) -> bool { loop { if self.xs.jump_after(n) { return true; } else if self.limit == T::MAX { return false; } self.limit.saturating_mul_assign(T::TWO); while self.limit != T::MAX && self.limit <= n { self.limit.saturating_mul_assign(T::TWO); } let i = self.xs.i; self.xs = T::primes_less_than_or_equal_to(&self.limit); self.xs.i = i; } } } impl Iterator for PrimesIterator { type Item = T; fn next(&mut self) -> Option { loop { let p = self.xs.next(); if p.is_some() { return p; } else if self.limit == T::MAX { return None; } self.limit.saturating_mul_assign(T::TWO); let i = if self.xs.small { n_to_bit(1031) } else { self.xs.i }; self.xs = T::primes_less_than_or_equal_to(&self.limit); self.xs.small = false; self.xs.i = i; } } } macro_rules! impl_primes { ($t:ident) => { impl Primes for $t { type I = PrimesIterator<$t>; type LI = PrimesLessThanIterator<$t>; /// Returns an iterator that generates all primes less than a given value. /// /// The iterator produced by `primes_less_than(n)` generates the same primes as the /// iterator produced by `primes().take_while(|&p| p < n)`, but the latter would be /// slower because it doesn't know in advance how large its prime sieve should be, and /// might have to create larger and larger prime sieves. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// See [here](super::primes#primes_less_than). #[inline] fn primes_less_than(n: &$t) -> PrimesLessThanIterator<$t> { PrimesLessThanIterator::new(n.saturating_sub(1)) } /// Returns an iterator that generates all primes less than or equal to a given value. /// /// The iterator produced by `primes_less_than_or_equal_to(n)` generates the same primes /// as the iterator produced by `primes().take_while(|&p| p <= n)`, but the latter would /// be slower because it doesn't know in advance how large its prime sieve should be, /// and might have to create larger and larger prime sieves. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// See [here](super::primes#primes_less_than_or_equal_to). #[inline] fn primes_less_than_or_equal_to(&n: &$t) -> PrimesLessThanIterator<$t> { PrimesLessThanIterator::new(n) } /// Returns all primes that fit into the specified type. /// /// The iterator produced by `primes(n)` generates the same primes as the iterator /// produced by `primes_less_than_or_equal_to(T::MAX)`. If you really need to generate /// _every_ prime, and `T` is `u32` or smaller, then you should use the latter, as it /// will allocate all the needed memory at once. If `T` is `u64` or larger, or if you /// probably don't need every prime, then `primes()` will be faster as it won't allocate /// too much memory right away. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// See [here](super::primes#primes). #[inline] fn primes() -> PrimesIterator<$t> { PrimesIterator::new() } } }; } apply_to_unsigneds!(impl_primes); /// An iterator that generates `bool`s up to a certain limit, where the $n$th `bool` is `true` if /// and only if $n$ is prime. See [`prime_indicator_sequence_less_than`] for more information. #[derive(Clone, Debug)] pub struct PrimeIndicatorSequenceLessThan { primes: PrimesLessThanIterator, limit: u64, i: u64, next_prime: u64, } impl Iterator for PrimeIndicatorSequenceLessThan { type Item = bool; fn next(&mut self) -> Option { if self.i >= self.limit { None } else if self.i == self.next_prime { self.i += 1; self.next_prime = self.primes.next().unwrap_or(0); Some(true) } else { self.i += 1; Some(false) } } } /// Returns an iterator that generates an sequence of `bool`s, where the $n$th `bool` is `true` if /// and only if $n$ is prime. The first `bool` generated has index 1, and the last one has index /// $\max(0,\ell-1)$, where $\ell$ is `limit`. /// /// The output length is $max(0,\ell-1)$, where $\ell$ is `limit`. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use malachite_base::num::factorization::primes::prime_indicator_sequence_less_than; /// /// let s: String = prime_indicator_sequence_less_than(101) /// .map(|b| if b { '1' } else { '0' }) /// .collect(); /// assert_eq!( /// s, /// "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ /// 00000001000" /// ) /// ``` pub fn prime_indicator_sequence_less_than(limit: u64) -> PrimeIndicatorSequenceLessThan { let mut primes = u64::primes_less_than(&limit); primes.next(); // skip 2 PrimeIndicatorSequenceLessThan { primes, limit, i: 1, next_prime: 2, } } /// Returns an iterator that generates an sequence of `bool`s, where the $n$th `bool` is `true` if /// and only if $n$ is prime. The first `bool` generated has index 1, and the last one has index /// `limit`. /// /// The output length is `limit`. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use malachite_base::num::factorization::primes::prime_indicator_sequence_less_than_or_equal_to; /// /// let s: String = prime_indicator_sequence_less_than_or_equal_to(100) /// .map(|b| if b { '1' } else { '0' }) /// .collect(); /// assert_eq!( /// s, /// "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ /// 00000001000" /// ) /// ``` pub fn prime_indicator_sequence_less_than_or_equal_to( limit: u64, ) -> PrimeIndicatorSequenceLessThan { prime_indicator_sequence_less_than(limit.checked_add(1).unwrap()) } /// An iterator that generates `bool`s, where the $n$th `bool` is `true` if and only if $n$ is /// prime. See [`prime_indicator_sequence`] for more information. #[derive(Clone, Debug)] pub struct PrimeIndicatorSequence { primes: PrimesIterator, i: u64, next_prime: u64, } impl Iterator for PrimeIndicatorSequence { type Item = bool; fn next(&mut self) -> Option { Some(if self.i == self.next_prime { self.i += 1; self.next_prime = self.primes.next().unwrap(); true } else { self.i += 1; false }) } } /// Returns an iterator that generates an infinite sequence of `bool`s, where the $n$th `bool` is /// `true` if and only if $n$ is prime. The first `bool` generated has index 1. /// /// The output length is infinite. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use malachite_base::num::factorization::primes::prime_indicator_sequence; /// /// let s: String = prime_indicator_sequence() /// .take(100) /// .map(|b| if b { '1' } else { '0' }) /// .collect(); /// assert_eq!( /// s, /// "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ /// 00000001000" /// ) /// ``` pub fn prime_indicator_sequence() -> PrimeIndicatorSequence { let mut primes = u64::primes(); primes.next(); // skip 2 PrimeIndicatorSequence { primes, i: 1, next_prime: 2, } } ================================================ FILE: malachite-base/src/num/factorization/primitive_root_prime.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2013 Mike Hansen // // Copyright © 2024 Vincent Neiger // // 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::exhaustive::primitive_int_increasing_range; use crate::num::factorization::factor::{ MAX_FACTORS_IN_U8, MAX_FACTORS_IN_U16, MAX_FACTORS_IN_U32, MAX_FACTORS_IN_U64, MAX_FACTORS_IN_USIZE, }; use crate::num::factorization::traits::{Factor, IsPrime, PrimitiveRootPrime}; // This is n_primitive_root_prime from ulong_extras/primitive_root_prime.c, FLINT 3.3.0-dev. fn primitive_root_prime(p: T) -> T where ::FACTORS: Clone + IntoIterator, { assert!(p > T::ONE); if p == T::TWO { return T::ONE; } // compute (p - 1) / factors once and for all let mut exponents = [T::ZERO; N]; let pm1 = p - T::ONE; for (e, (pf, _)) in exponents.iter_mut().zip((p - T::ONE).factor().into_iter()) { *e = pm1 / pf; } // try 2, 3, ..., p - 1 let data = T::precompute_mod_pow_data(&p); 'outer: for a in primitive_int_increasing_range(T::TWO, p) { for &exponent in &exponents { if exponent == T::ZERO { break; } if a.mod_pow_precomputed(exponent.wrapping_into(), p, &data) == T::ONE { continue 'outer; } } return a; } // If we haven't found a primitive root, it must be because p is not prime. Confirm this by // failing an assertion, which will produce an appropriate error message. assert!(p.is_prime()); unreachable!() } macro_rules! impl_primitive_root_prime { ($t:ident, $n:ident) => { impl PrimitiveRootPrime for $t { type Output = $t; /// Given a prime number, computes a primitive root modulo that number. In other words, /// given a prime $p$, finds a generator of the cyclic group /// $(\mathbb{Z}/p\mathbb{Z})^\times$. /// /// If the input is not prime, this function's behavior is unspecified. Since primality /// checking can be expensive, the input is not tested for primality. /// /// Currently the smallest primitive root is returned, but there is no guarantee that /// this will be the case in the future. /// /// # Worst-case complexity /// $T(n) = O(2^{n/4})$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0, and possibly panics if `self` is not prime. /// /// # Examples /// See [here](super::primitive_root_prime#primitive_root_prime). #[inline] fn primitive_root_prime(&self) -> $t { primitive_root_prime::<$t, $n>(*self) } } }; } impl_primitive_root_prime!(u8, MAX_FACTORS_IN_U8); impl_primitive_root_prime!(u16, MAX_FACTORS_IN_U16); impl_primitive_root_prime!(u32, MAX_FACTORS_IN_U32); impl_primitive_root_prime!(u64, MAX_FACTORS_IN_U64); impl_primitive_root_prime!(usize, MAX_FACTORS_IN_USIZE); ================================================ FILE: malachite-base/src/num/factorization/traits.rs ================================================ // Copyright © 2026 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 . /// A trait for testing whether a number is prime. pub trait IsPrime { fn is_prime(&self) -> bool; } /// A trait for testing whether a number is a square. pub trait IsSquare { fn is_square(&self) -> bool; } /// A trait for testing whether a number is a perfect power. pub trait IsPower { fn is_power(&self) -> bool; } /// A trait for expessing as number as the power of some number raised to an exponent greater than /// 1, if such a representation exists. pub trait ExpressAsPower: Sized { fn express_as_power(&self) -> Option<(Self, u64)>; } /// A trait for finding the prime factorization of a number. pub trait Factor { type FACTORS; fn factor(&self) -> Self::FACTORS; } /// A trait for producing iterators of primes. pub trait Primes { type I: Iterator; type LI: Iterator; fn primes_less_than(n: &Self) -> Self::LI; fn primes_less_than_or_equal_to(n: &Self) -> Self::LI; fn primes() -> Self::I; } /// A trait for finding a primitive root modulo a prime. pub trait PrimitiveRootPrime { type Output; fn primitive_root_prime(&self) -> Self::Output; } ================================================ FILE: malachite-base/src/num/float/mod.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Abs; use crate::num::basic::floats::PrimitiveFloat; use crate::num::comparison::traits::{EqAbs, OrdAbs, PartialOrdAbs}; use core::cmp::Ordering::{self, *}; use core::fmt::{self, Debug, Display, Formatter}; use core::hash::{Hash, Hasher}; use core::str::FromStr; /// `NiceFloat` is a wrapper around primitive float types that provides nicer [`Eq`], [`Ord`], /// [`Hash`], [`Display`], and [`FromStr`] instances. /// /// In most languages, floats behave weirdly due to the IEEE 754 standard. The `NiceFloat` type /// ignores the standard in favor of more intuitive behavior. /// * Using `NiceFloat`, `NaN`s are equal to themselves. There is a single, unique `NaN`; there's no /// concept of signalling `NaN`s. Positive and negative zero are two distinct values, not equal to /// each other. /// * The `NiceFloat` hash respects this equality. /// * `NiceFloat` has a total order. These are the classes of floats, in ascending order: /// - Negative infinity /// - Negative nonzero finite floats /// - Negative zero /// - NaN /// - Positive zero /// - Positive nonzero finite floats /// - Positive infinity /// * `NiceFloat` uses a different [`Display`] implementation than floats do by default in Rust. For /// example, Rust will format `f32::MIN_POSITIVE_SUBNORMAL` as something with many zeros, but /// `NiceFloat(f32::MIN_POSITIVE_SUBNORMAL)` just formats it as `"1.0e-45"`. The conversion /// function uses David Tolnay's [`ryu`](https://docs.rs/ryu/latest/ryu/) crate, with a few /// modifications: /// - All finite floats have a decimal point. For example, Ryu by itself would convert /// `f32::MIN_POSITIVE_SUBNORMAL` to `"1e-45"`. /// - Positive infinity, negative infinity, and NaN are converted to the strings `"Infinity"`, /// `"-Infinity"`, and "`NaN`", respectively. /// * [`FromStr`] accepts these strings. #[derive(Clone, Copy, Default)] pub struct NiceFloat(pub T); #[derive(Eq, Ord, PartialEq, PartialOrd)] enum FloatType { NegativeInfinity, NegativeFinite, NegativeZero, NaN, PositiveZero, PositiveFinite, PositiveInfinity, } impl NiceFloat { fn float_type(self) -> FloatType { let f = self.0; if f.is_nan() { FloatType::NaN } else if f.sign() == Greater { if f == T::ZERO { FloatType::PositiveZero } else if f.is_finite() { FloatType::PositiveFinite } else { FloatType::PositiveInfinity } } else if f == T::ZERO { FloatType::NegativeZero } else if f.is_finite() { FloatType::NegativeFinite } else { FloatType::NegativeInfinity } } } impl Abs for FloatType { type Output = Self; fn abs(self) -> Self::Output { match self { Self::NegativeInfinity => Self::PositiveInfinity, Self::NegativeFinite => Self::PositiveFinite, Self::NegativeZero => Self::PositiveZero, t => t, } } } impl PartialEq for NiceFloat { /// Compares two `NiceFloat`s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// `NiceFloat`, `NaN`s are equal to themselves. There is a single, unique `NaN`; there's no /// concept of signalling `NaN`s. Positive and negative zero are two distinct values, not equal /// to each other. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat(0.0), NiceFloat(0.0)); /// assert_eq!(NiceFloat(f32::NAN), NiceFloat(f32::NAN)); /// assert_ne!(NiceFloat(f32::NAN), NiceFloat(0.0)); /// assert_ne!(NiceFloat(0.0), NiceFloat(-0.0)); /// assert_eq!(NiceFloat(1.0), NiceFloat(1.0)); /// ``` #[inline] fn eq(&self, other: &Self) -> bool { let f = self.0; let g = other.0; f.to_bits() == g.to_bits() || f.is_nan() && g.is_nan() } } impl Eq for NiceFloat {} impl EqAbs for NiceFloat { /// Compares the absolute values of two `NiceFloat`s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// `NiceFloat`, `NaN`s are equal to themselves. There is a single, unique `NaN`; there's no /// concept of signalling `NaN`s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_base::num::float::NiceFloat; /// /// assert!(NiceFloat(0.0).eq_abs(&NiceFloat(0.0))); /// assert!(NiceFloat(f32::NAN).eq_abs(&NiceFloat(f32::NAN))); /// assert!(NiceFloat(f32::NAN).ne_abs(&NiceFloat(0.0))); /// assert!(NiceFloat(0.0).eq_abs(&NiceFloat(-0.0))); /// assert!(NiceFloat(1.0).eq_abs(&NiceFloat(1.0))); /// assert!(NiceFloat(1.0).eq_abs(&NiceFloat(-1.0))); /// ``` fn eq_abs(&self, other: &Self) -> bool { let f = self.0; let g = other.0; f.abs().to_bits() == g.abs().to_bits() || f.is_nan() && g.is_nan() } } impl Hash for NiceFloat { /// Computes a hash of a `NiceFloat`. /// /// The hash is compatible with `NiceFloat` equality: all `NaN`s hash to the same value. /// /// # Worst-case complexity /// Constant time and additional memory. fn hash(&self, state: &mut H) { let f = self.0; if f.is_nan() { "NaN".hash(state); } else { f.to_bits().hash(state); } } } impl Ord for NiceFloat { /// Compares two `NiceFloat`s. /// /// This implementation ignores the IEEE 754 standard in favor of a comparison operation that /// respects the expected properties of antisymmetry, reflexivity, and transitivity. `NiceFloat` /// has a total order. These are the classes of floats, in ascending order: /// - Negative infinity /// - Negative nonzero finite floats /// - Negative zero /// - NaN /// - Positive zero /// - Positive nonzero finite floats /// - Positive infinity /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// /// assert!(NiceFloat(0.0) > NiceFloat(-0.0)); /// assert!(NiceFloat(f32::NAN) < NiceFloat(0.0)); /// assert!(NiceFloat(f32::NAN) > NiceFloat(-0.0)); /// assert!(NiceFloat(f32::INFINITY) > NiceFloat(f32::NAN)); /// assert!(NiceFloat(f32::NAN) < NiceFloat(1.0)); /// ``` fn cmp(&self, other: &Self) -> Ordering { let self_type = self.float_type(); let other_type = other.float_type(); self_type.cmp(&other_type).then_with(|| { if self_type == FloatType::PositiveFinite || self_type == FloatType::NegativeFinite { self.0.partial_cmp(&other.0).unwrap() } else { Equal } }) } } impl PartialOrd for NiceFloat { /// Compares a `NiceFloat` to another `NiceFloat`. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl OrdAbs for NiceFloat { /// Compares the absolute values of two `NiceFloat`s. /// /// This implementation ignores the IEEE 754 standard in favor of a comparison operation that /// respects the expected properties of antisymmetry, reflexivity, and transitivity. `NiceFloat` /// has a total order. These are the classes of floats, in order of ascending absolute value: /// - NaN /// - Positive zero /// - Positive nonzero finite floats /// - Positive infinity /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; /// use malachite_base::num::float::NiceFloat; /// /// assert!(NiceFloat(0.0).eq_abs(&NiceFloat(-0.0))); /// assert!(NiceFloat(f32::NAN).lt_abs(&NiceFloat(0.0))); /// assert!(NiceFloat(f32::NAN).lt_abs(&NiceFloat(-0.0))); /// assert!(NiceFloat(f32::INFINITY).gt_abs(&NiceFloat(f32::NAN))); /// assert!(NiceFloat(f32::NEGATIVE_INFINITY).gt_abs(&NiceFloat(f32::NAN))); /// assert!(NiceFloat(f32::NAN).lt_abs(&NiceFloat(1.0))); /// assert!(NiceFloat(f32::NAN).lt_abs(&NiceFloat(-1.0))); /// ``` fn cmp_abs(&self, other: &Self) -> Ordering { let self_type = self.float_type().abs(); let other_type = other.float_type().abs(); self_type.cmp(&other_type).then_with(|| { if self_type == FloatType::PositiveFinite { self.0.abs().partial_cmp(&other.0.abs()).unwrap() } else { Equal } }) } } impl PartialOrdAbs for NiceFloat { /// Compares the absolute values of two `NiceFloat`s. /// /// See the documentation for the [`OrdAbs`] implementation. #[inline] fn partial_cmp_abs(&self, other: &Self) -> Option { Some(self.cmp_abs(other)) } } #[doc(hidden)] pub trait FmtRyuString: Copy { fn fmt_ryu_string(self, f: &mut Formatter<'_>) -> fmt::Result; } macro_rules! impl_fmt_ryu_string { ($f: ident) => { impl FmtRyuString for $f { #[inline] fn fmt_ryu_string(self, f: &mut Formatter<'_>) -> fmt::Result { let mut buffer = ryu::Buffer::new(); let printed = buffer.format_finite(self); // Convert e.g. "1e100" to "1.0e100". `printed` is ASCII, so we can manipulate bytes // rather than chars. let mut e_index = None; let mut found_dot = false; for (i, &b) in printed.as_bytes().iter().enumerate() { match b { b'.' => { found_dot = true; break; // If there's a '.', we don't need to do anything } b'e' => { e_index = Some(i); break; // OK to break since there won't be a '.' after an 'e' } _ => {} } } if found_dot { f.write_str(printed) } else { if let Some(e_index) = e_index { let mut out_bytes = ::alloc::vec![0; printed.len() + 2]; let (in_bytes_lo, in_bytes_hi) = printed.as_bytes().split_at(e_index); let (out_bytes_lo, out_bytes_hi) = out_bytes.split_at_mut(e_index); out_bytes_lo.copy_from_slice(in_bytes_lo); out_bytes_hi[0] = b'.'; out_bytes_hi[1] = b'0'; out_bytes_hi[2..].copy_from_slice(in_bytes_hi); f.write_str(core::str::from_utf8(&out_bytes).unwrap()) } else { panic!("Unexpected Ryu string: {}", printed); } } } } }; } impl_fmt_ryu_string!(f32); impl_fmt_ryu_string!(f64); impl Display for NiceFloat { /// Formats a `NiceFloat` as a string. /// /// `NiceFloat` uses a different [`Display`] implementation than floats do by default in Rust. /// For example, Rust will convert `f32::MIN_POSITIVE_SUBNORMAL` to something with many zeros, /// but `NiceFloat(f32::MIN_POSITIVE_SUBNORMAL)` just converts to `"1.0e-45"`. The conversion /// function uses David Tolnay's [`ryu`](https://docs.rs/ryu/latest/ryu/) crate, with a few /// modifications: /// - All finite floats have a decimal point. For example, Ryu by itself would convert /// `f32::MIN_POSITIVE_SUBNORMAL` to `"1e-45"`. /// - Positive infinity, negative infinity, and NaN are converted to the strings `"Infinity"`, /// `"-Infinity"`, and "`NaN`", respectively. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::float::NiceFloat; /// /// assert_eq!(NiceFloat(0.0).to_string(), "0.0"); /// assert_eq!(NiceFloat(-0.0).to_string(), "-0.0"); /// assert_eq!(NiceFloat(f32::INFINITY).to_string(), "Infinity"); /// assert_eq!(NiceFloat(f32::NEGATIVE_INFINITY).to_string(), "-Infinity"); /// assert_eq!(NiceFloat(f32::NAN).to_string(), "NaN"); /// /// assert_eq!(NiceFloat(1.0).to_string(), "1.0"); /// assert_eq!(NiceFloat(-1.0).to_string(), "-1.0"); /// assert_eq!( /// NiceFloat(f32::MIN_POSITIVE_SUBNORMAL).to_string(), /// "1.0e-45" /// ); /// assert_eq!( /// NiceFloat(std::f64::consts::E).to_string(), /// "2.718281828459045" /// ); /// assert_eq!( /// NiceFloat(std::f64::consts::PI).to_string(), /// "3.141592653589793" /// ); /// ``` fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.0.is_nan() { f.write_str("NaN") } else if self.0.is_infinite() { if self.0.sign() == Greater { f.write_str("Infinity") } else { f.write_str("-Infinity") } } else { self.0.fmt_ryu_string(f) } } } impl Debug for NiceFloat { /// Formats a `NiceFloat` as a string. /// /// This is identical to the [`Display::fmt`] implementation. #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { Display::fmt(self, f) } } impl FromStr for NiceFloat { type Err = ::Err; /// Converts a `&str` to a `NiceFloat`. /// /// If the `&str` does not represent a valid `NiceFloat`, an `Err` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `src.len()`. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// use std::str::FromStr; /// /// assert_eq!(NiceFloat::from_str("NaN").unwrap(), NiceFloat(f32::NAN)); /// assert_eq!(NiceFloat::from_str("-0.00").unwrap(), NiceFloat(-0.0f64)); /// assert_eq!(NiceFloat::from_str(".123").unwrap(), NiceFloat(0.123f32)); /// ``` #[inline] fn from_str(src: &str) -> Result::Err> { match src { "NaN" => Ok(T::NAN), "Infinity" => Ok(T::INFINITY), "-Infinity" => Ok(T::NEGATIVE_INFINITY), "inf" | "-inf" => T::from_str("invalid"), src => T::from_str(src), } .map(NiceFloat) } } ================================================ FILE: malachite-base/src/num/iterators/mod.rs ================================================ // Copyright © 2026 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 crate::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; use crate::num::arithmetic::traits::{DivMod, DivisibleBy}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use core::cmp::Ordering::*; use core::marker::PhantomData; #[doc(hidden)] #[derive(Clone, Debug)] pub struct SameWidthIteratorToBitChunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, > { xs: I, width: u64, phantom: PhantomData<*const U>, } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned> SameWidthIteratorToBitChunks { fn next_with_wrapping U>(&mut self, wrap: F) -> Option> { self.xs.next().map(|x| { if x.significant_bits() <= self.width { Some(wrap(x)) } else { None } }) } } const fn same_width_iterator_to_bit_chunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( xs: I, width: u64, ) -> SameWidthIteratorToBitChunks { SameWidthIteratorToBitChunks { xs, width, phantom: PhantomData, } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct EvenFractionIteratorToBitChunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, > { xs: I, x: T, multiple: u64, x_width: u64, y_width: u64, counter: u64, phantom: PhantomData<*const U>, } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned> EvenFractionIteratorToBitChunks { fn next_with_wrapping U>(&mut self, wrap: F) -> Option> { if self.counter == 0 { if let Some(x) = self.xs.next() { if x.significant_bits() > self.x_width { return Some(None); } self.x = x; self.counter = self.multiple; } else { return None; } } else { self.x >>= self.y_width; } let y = wrap(self.x.mod_power_of_2(self.y_width)); self.counter -= 1; Some(Some(y)) } } const fn even_fraction_iterator_to_bit_chunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( xs: I, multiple: u64, out_chunk_size: u64, ) -> EvenFractionIteratorToBitChunks { EvenFractionIteratorToBitChunks { xs, x: T::ZERO, multiple, x_width: multiple * out_chunk_size, y_width: out_chunk_size, counter: 0, phantom: PhantomData, } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct EvenMultipleIteratorToBitChunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, > { xs: I, x_width: u64, y_width: u64, done: bool, phantom: PhantomData<*const U>, } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned> EvenMultipleIteratorToBitChunks { fn next_with_wrapping U>(&mut self, wrap: F) -> Option> { if self.done { return None; } let mut y = U::ZERO; let mut shift = 0; while shift < self.y_width { if let Some(x) = self.xs.next() { if x.significant_bits() > self.x_width { return Some(None); } y |= wrap(x) << shift; shift += self.x_width; } else { self.done = true; break; } } if shift == 0 { None } else { Some(Some(y)) } } } const fn even_multiple_iterator_to_bit_chunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( xs: I, in_chunk_size: u64, out_chunk_size: u64, ) -> EvenMultipleIteratorToBitChunks { EvenMultipleIteratorToBitChunks { xs, x_width: in_chunk_size, y_width: out_chunk_size, done: false, phantom: PhantomData, } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct IrregularIteratorToBitChunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, > { xs: I, x: T, x_width: u64, y_width: u64, remaining_x_bits: u64, in_inner_loop: bool, phantom: PhantomData<*const U>, } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned> IrregularIteratorToBitChunks { fn next_with_wrapping U>(&mut self, wrap: F) -> Option> { let mut y = U::ZERO; let mut remaining_y_bits = self.y_width; loop { if !self.in_inner_loop { if let Some(x) = self.xs.next() { if x.significant_bits() > self.x_width { return Some(None); } self.x = x; } else { break; } self.remaining_x_bits = self.x_width; self.in_inner_loop = true; } while self.remaining_x_bits != 0 { let y_index = self.y_width - remaining_y_bits; if self.remaining_x_bits <= remaining_y_bits { y |= wrap(self.x) << y_index; remaining_y_bits -= self.remaining_x_bits; self.remaining_x_bits = 0; } else { y |= wrap(self.x).mod_power_of_2(remaining_y_bits) << y_index; self.x >>= remaining_y_bits; self.remaining_x_bits -= remaining_y_bits; remaining_y_bits = 0; } if remaining_y_bits == 0 { return Some(Some(y)); } } self.in_inner_loop = false; } if y == U::ZERO { None } else { Some(Some(y)) } } } const fn irregular_iterator_to_bit_chunks< I: Iterator, T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( xs: I, in_chunk_size: u64, out_chunk_size: u64, ) -> IrregularIteratorToBitChunks { IrregularIteratorToBitChunks { xs, x: T::ZERO, x_width: in_chunk_size, y_width: out_chunk_size, remaining_x_bits: 0, in_inner_loop: false, phantom: PhantomData, } } /// Regroups an iterator of bit chunks into another iterator of bit chunks, possibly with a /// different chunk size. /// /// This `enum` is created by [`iterator_to_bit_chunks`]; see its documentation for more. #[derive(Clone, Debug)] pub enum IteratorToBitChunks, T: PrimitiveUnsigned, U: PrimitiveUnsigned> { SameWidth(SameWidthIteratorToBitChunks), EvenFraction(EvenFractionIteratorToBitChunks), EvenMultiple(EvenMultipleIteratorToBitChunks), Irregular(IrregularIteratorToBitChunks), } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned> IteratorToBitChunks { pub(crate) fn next_with_wrapping U>(&mut self, wrap: F) -> Option> { match self { Self::SameWidth(xs) => xs.next_with_wrapping(wrap), Self::EvenFraction(xs) => xs.next_with_wrapping(wrap), Self::EvenMultiple(xs) => xs.next_with_wrapping(wrap), Self::Irregular(xs) => xs.next_with_wrapping(wrap), } } } impl, T: PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom> Iterator for IteratorToBitChunks { type Item = Option; #[inline] fn next(&mut self) -> Option> { self.next_with_wrapping(U::wrapping_from) } } /// Regroups an iterator of bit chunks into another iterator of bit chunks, possibly with a /// different chunk size. /// /// In other words, let $A$ be the input chunk size and $B$ the output chunk size. Let's consider /// the lowest $A$ bits of each unsigned value produced by the input iterator, and concatenate them /// (least-significant bits first) into a single bit sequence. Then we chop the sequence up into /// chunks of $B$ bits, and have the output iterator return each chunk. /// /// Let $(x\_i)\_{i=0}^{n-1}$ be the input iterator, where $n$ may be $\infty$. If $n$ is finite, we /// assume that $x\_{n-1} \neq 0$. Then we define the bit sequence $b\_{k=0}^\infty$ such that $b /// \in \\{0, 1\\}$, $b\_k=0$ for $k \geq An$, and /// $$ /// x_i = \sum_{k=0}^{A-1} b_{Ai+k}2^k. /// $$ /// Then, let $(y\_j)\_{j=0}^{m-1}$ be a sequence such that /// $$ /// y_j = \sum_{k=0}^{B-1} b_{Bi+k}2^k. /// $$ /// Then we have $f((x\_i)\_{i=0}^{n-1}) = (y\_j)\_{j=0}^{m-1}$. Note that the sequence $y$ is not /// uniquely specified, since it may contain arbitrarily many trailing zeros. However, if $x$ is /// finite, $y$ is guaranteed to also be finite. /// /// The output length is $An/B + O(1)$, where $n$ is `xs.count()`, $A$ is `in_chunk_size`, and $B$ /// is `out_chunk_size`. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::iterators::iterator_to_bit_chunks; /// /// assert_eq!( /// iterator_to_bit_chunks::<_, u16, u32>([123, 456].iter().cloned(), 10, 10) /// .map(Option::unwrap) /// .collect_vec(), /// &[123, 456] /// ); /// assert_eq!( /// iterator_to_bit_chunks::<_, u16, u16>([0b000111111, 0b110010010].iter().cloned(), 9, 3) /// .map(Option::unwrap) /// .collect_vec(), /// &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110] /// ); /// assert_eq!( /// iterator_to_bit_chunks::<_, u16, u32>( /// [0b111, 0b111, 0b000, 0b010, 0b010, 0b110].iter().cloned(), /// 3, /// 9 /// ) /// .map(Option::unwrap) /// .collect_vec(), /// &[0b000111111, 0b110010010] /// ); /// assert_eq!( /// iterator_to_bit_chunks::<_, u32, u16>( /// [0b1010101, 0b1111101, 0b0100001, 0b110010].iter().cloned(), /// 7, /// 6 /// ) /// .map(Option::unwrap) /// .collect_vec(), /// &[0b010101, 0b111011, 0b000111, 0b010010, 0b110] /// ); /// ``` pub fn iterator_to_bit_chunks, T: PrimitiveUnsigned, U: PrimitiveUnsigned>( xs: I, in_chunk_size: u64, out_chunk_size: u64, ) -> IteratorToBitChunks { assert_ne!(in_chunk_size, 0); assert_ne!(out_chunk_size, 0); assert!(in_chunk_size <= T::WIDTH); assert!(out_chunk_size <= U::WIDTH); match in_chunk_size.cmp(&out_chunk_size) { Equal => { return IteratorToBitChunks::SameWidth(same_width_iterator_to_bit_chunks( xs, in_chunk_size, )); } Less => { if out_chunk_size.divisible_by(in_chunk_size) { return IteratorToBitChunks::EvenMultiple(even_multiple_iterator_to_bit_chunks( xs, in_chunk_size, out_chunk_size, )); } } Greater => { let (multiple, remainder) = in_chunk_size.div_mod(out_chunk_size); if remainder == 0 { return IteratorToBitChunks::EvenFraction(even_fraction_iterator_to_bit_chunks( xs, multiple, out_chunk_size, )); } } } IteratorToBitChunks::Irregular(irregular_iterator_to_bit_chunks( xs, in_chunk_size, out_chunk_size, )) } /// A `struct` that holds the state of the ruler sequence. /// /// This `struct` is created by [`ruler_sequence`]; see its documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct RulerSequence> { i: u64, phantom: PhantomData<*const T>, } impl> Iterator for RulerSequence { type Item = T; fn next(&mut self) -> Option { self.i += 1; Some(T::exact_from(self.i.trailing_zeros())) } } /// Returns the ruler sequence. /// /// The ruler sequence () is the number of times that 2 divides the /// numbers $1, 2, 3, \ldots$. /// /// $(x_i)_{i=1}^\infty = t_i$, where for each $i$, $i = (2k_i+1)2^{t_i}$ for some $k_i\in /// \mathbb{Z}$. /// /// The $n$th term of this sequence is no greater than $\log_2(n + 1)$. Every number occurs /// infinitely many times, and any number's first occurrence is after all smaller numbers have /// occurred. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::iterators::ruler_sequence; /// /// assert_eq!( /// prefix_to_string(ruler_sequence::(), 20), /// "[0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, ...]" /// ); /// ``` pub const fn ruler_sequence>() -> RulerSequence { RulerSequence { i: 0, phantom: PhantomData, } } /// A `struct` that holds the state of a bit distributor sequence. /// /// This `struct` is created by [`bit_distributor_sequence`]; see its documentation for more. #[derive(Clone, Debug)] pub struct BitDistributorSequence { bit_distributor: BitDistributor, } impl Iterator for BitDistributorSequence { type Item = usize; fn next(&mut self) -> Option { let i = self.bit_distributor.get_output(1); self.bit_distributor.increment_counter(); Some(i) } } /// Returns a sequence based on a [`BitDistributor`]. /// /// The sequence is obtained by taking the second output of a two-output [`BitDistributor`]. If both /// output types are normal with weight 1, the sequence is . /// /// The smaller the first output type is relative to the second (where tiny outputs are smaller than /// normal outputs), the slower the sequence will grow. /// /// - If the first output type is normal and the second is tiny, the sequence grows as $O(n)$. /// - If the first output type is tiny and the second is normal, the sequence grows as $O(\log n)$. /// - If both output types are normal with weights $p$ and $q$, the sequence grows as /// $O(n^\frac{p}{p+q})$. /// - The output types cannot both be tiny. /// /// Every number occurs infinitely many times, and any number's first occurrence is after all /// smaller numbers have occurred. The sequence increases by no more than 1 at each step, but may /// decrease by an arbitrarily large amount. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if both output types are tiny. /// /// # Examples /// ``` /// use malachite_base::iterators::bit_distributor::BitDistributorOutputType; /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::iterators::bit_distributor_sequence; /// /// assert_eq!( /// prefix_to_string( /// bit_distributor_sequence( /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::normal(2) /// ), /// 50 /// ), /// "[0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, \ /// 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// bit_distributor_sequence( /// BitDistributorOutputType::normal(2), /// BitDistributorOutputType::normal(1) /// ), /// 50 /// ), /// "[0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 8, 9, 10, 11, 12, 13, 14, \ /// 15, 12, 13, 14, 15, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, ...]" /// ); /// ``` pub fn bit_distributor_sequence( x_output_type: BitDistributorOutputType, y_output_type: BitDistributorOutputType, ) -> BitDistributorSequence { BitDistributorSequence { bit_distributor: BitDistributor::new(&[y_output_type, x_output_type]), } } ================================================ FILE: malachite-base/src/num/logic/bit_access.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::BitAccess; fn get_bit_unsigned(x: &T, index: u64) -> bool { index < T::WIDTH && (*x >> index).odd() } fn set_bit_unsigned(x: &mut T, index: u64) { if index < T::WIDTH { *x |= T::power_of_2(index); } else { panic!( "Cannot set bit {} in non-negative value of width {}", index, T::WIDTH ); } } fn clear_bit_unsigned(x: &mut T, index: u64) { if index < T::WIDTH { *x &= !T::power_of_2(index); } } macro_rules! impl_bit_access_unsigned { ($t:ident) => { impl BitAccess for $t { /// Determines whether the $i$th bit of an unsigned primitive integer, or the /// coefficient of $2^i$ in its binary expansion, is 0 or 1. /// /// `false` means 0 and `true` means 1. Getting bits beyond the type's width is allowed; /// those bits are false. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the /// rest are 0. Then $f(n, j) = (b_j = 1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_access#get_bit). #[inline] fn get_bit(&self, index: u64) -> bool { get_bit_unsigned(self, index) } /// Sets the $i$th bit of an unsigned primitive integer, or the coefficient of $2^i$ in /// its binary expansion, to 1. /// /// Setting bits beyond the type's width is disallowed. /// /// Let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then /// $$ /// n \gets \\begin{cases} /// n + 2^j & \text{if} \\quad b_j = 0, \\\\ /// n & \text{otherwise}, /// \\end{cases} /// $$ /// where $j < W$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $i \geq W$, where $i$ is `index` and $W$ is `$t::WIDTH`. /// /// # Examples /// See [here](super::bit_access#set_bit). #[inline] fn set_bit(&mut self, index: u64) { set_bit_unsigned(self, index) } /// Sets the $i$th bit of an unsigned primitive integer, or the coefficient of $2^i$ in /// its binary expansion, to 0. /// /// Clearing bits beyond the type's width is allowed; since those bits are already /// `false`, clearing them does nothing. /// /// Let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then /// $$ /// n \gets \\begin{cases} /// n - 2^j & \text{if} \\quad b_j = 1, \\\\ /// n & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_access#clear_bit). #[inline] fn clear_bit(&mut self, index: u64) { clear_bit_unsigned(self, index) } } }; } apply_to_unsigneds!(impl_bit_access_unsigned); fn get_bit_signed(x: &T, index: u64) -> bool { if index < T::WIDTH { (*x >> index).odd() } else { *x < T::ZERO } } fn set_bit_signed(x: &mut T, index: u64) { if index < T::WIDTH { *x |= T::ONE << index; } else if *x >= T::ZERO { panic!( "Cannot set bit {} in non-negative value of width {}", index, T::WIDTH ); } } fn clear_bit_signed(x: &mut T, index: u64) { if index < T::WIDTH { *x &= !(T::ONE << index); } else if *x < T::ZERO { panic!( "Cannot clear bit {} in negative value of width {}", index, T::WIDTH ); } } macro_rules! impl_bit_access_signed { ($t:ident) => { impl BitAccess for $t { /// Determines whether the $i$th bit of a signed primitive integer is 0 or 1. /// /// `false` means 0 and `true` means 1. Getting bits beyond the type's width is allowed; /// those bits are `true` if the value is negative, and `false` otherwise. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the /// rest are 0. Then $f(n, i) = (b_i = 1)$. /// /// If $n < 0$, let /// $$ /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where /// - $W$ is the type's width /// - for all $i$, $b_i\in \\{0, 1\\}$, and $b_i = 1$ for $i \geq W$. /// /// Then $f(n, j) = (b_j = 1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_access#get_bit). #[inline] fn get_bit(&self, index: u64) -> bool { get_bit_signed(self, index) } /// Sets the $i$th bit of a signed primitive integer to 1. /// /// Setting bits beyond the type's width is disallowed if the number is non-negative. /// /// If $n \geq 0$ and $j \neq W - 1$, let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}; /// $$ /// but if $n < 0$ or $j = W - 1$, let /// $$ /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then /// $$ /// n \gets \\begin{cases} /// n + 2^j & \text{if} \\quad b_j = 0, \\\\ /// n & \text{otherwise}, /// \\end{cases} /// $$ /// where $n < 0$ or $j < W$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $n \geq 0$ and $i \geq W$, where $n$ is `self`, $i$ is `index` and $W$ is /// the width of the type. /// /// # Examples /// See [here](super::bit_access#set_bit). #[inline] fn set_bit(&mut self, index: u64) { set_bit_signed(self, index) } /// Sets the $i$th bit of a signed primitive integer to 0. /// /// Clearing bits beyond the type's width is disallowed if the number is negative. /// /// If $n \geq 0$ or $j = W - 1$, let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}; /// $$ /// but if $n < 0$ or $j = W - 1$, let /// $$ /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$ and $W$ is the width of the type. Then /// $$ /// n \gets \\begin{cases} /// n - 2^j & \text{if} \\quad b_j = 1, \\\\ /// n & \text{otherwise}, /// \\end{cases} /// $$ /// where $n \geq 0$ or $j < W$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $n < 0$ and $i \geq W$, where $n$ is `self`, $i$ is `index` and $W$ is the /// width of the type. /// /// # Examples /// See [here](super::bit_access#clear_bit). #[inline] fn clear_bit(&mut self, index: u64) { clear_bit_signed(self, index) } } }; } apply_to_signeds!(impl_bit_access_signed); ================================================ FILE: malachite-base/src/num/logic/bit_block_access.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{ModPowerOf2, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::logic::traits::{BitBlockAccess, LeadingZeros}; use core::cmp::min; const ERROR_MESSAGE: &str = "Result exceeds width of output type"; fn get_bits_unsigned(x: &T, start: u64, end: u64) -> T { assert!(start <= end); if start >= T::WIDTH { T::ZERO } else { (*x >> start).mod_power_of_2(end - start) } } fn assign_bits_unsigned(x: &mut T, start: u64, end: u64, bits: &T) { assert!(start <= end); let width = T::WIDTH; let bits_width = end - start; let bits = bits.mod_power_of_2(bits_width); if bits != T::ZERO && LeadingZeros::leading_zeros(bits) < start { panic!("{}", ERROR_MESSAGE); } else if start < width { *x &= !(T::MAX.mod_power_of_2(min(bits_width, width - start)) << start); *x |= bits << start; } } macro_rules! impl_bit_block_access_unsigned { ($t:ident) => { impl BitBlockAccess for $t { type Bits = $t; /// Extracts a block of adjacent bits from a number. /// /// The first index is `start` and last index is `end - 1`. /// /// The block of bits has the same type as the input. If `end` is greater than the /// type's width, the high bits of the result are all 0. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the /// rest are 0. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `start < end`. /// /// # Examples /// See [here](super::bit_block_access#get_bits). #[inline] fn get_bits(&self, start: u64, end: u64) -> Self { get_bits_unsigned(self, start, end) } /// Replaces a block of adjacent bits in a number with other bits. /// /// The least-significant `end - start` bits of `bits` are assigned to bits `start` /// through `end - 1`, inclusive, of `self`. /// /// The block of bits has the same type as the input. If `bits` has fewer bits than `end /// - start`, the high bits are interpreted as 0. If `end` is greater than the type's /// width, the high bits of `bits` must be 0. /// /// Let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$ and $W$ is `$t::WIDTH`. Let /// $$ /// m = \sum_{i=0}^k 2^{d_i}, /// $$ /// where for all $i$, $d_i\in \\{0, 1\\}$. Also, let $p, q \in \mathbb{N}$, where $d_i /// = 0$ for all $i \geq W + p$. /// /// Then /// $$ /// n \gets \sum_{i=0}^{W-1} 2^{c_i}, /// $$ /// where /// $$ /// \\{c_0, c_1, c_2, \ldots, c_ {W-1}\\} = /// \\{b_0, b_1, b_2, \ldots, b_{p-1}, d_0, d_1, \ldots, d_{p-q-1}, b_q, \ldots, /// b_ {W-1}\\}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Let `W` be the type's width. Panics if `start < end`, or if `end > W` and bits `W - /// start` through `end - start` of `bits` are nonzero. /// /// # Examples /// See [here](super::bit_block_access#assign_bits). #[inline] fn assign_bits(&mut self, start: u64, end: u64, bits: &Self::Bits) { assign_bits_unsigned(self, start, end, bits) } } }; } apply_to_unsigneds!(impl_bit_block_access_unsigned); fn get_bits_signed + PrimitiveSigned, U>( x: &T, start: u64, end: u64, ) -> U { assert!(start <= end); (if start >= T::WIDTH { -T::from(*x < T::ZERO) } else { *x >> start }) .mod_power_of_2(end - start) } fn assign_bits_signed< T: PrimitiveSigned + UnsignedAbs + WrappingFrom, U: PrimitiveUnsigned, >( x: &mut T, start: u64, end: u64, bits: &U, ) { assert!(start <= end); if *x >= T::ZERO { let mut abs_x = x.unsigned_abs(); abs_x.assign_bits(start, end, bits); assert!(!abs_x.get_highest_bit(), "{ERROR_MESSAGE}"); *x = T::wrapping_from(abs_x); } else { let width = T::WIDTH - 1; let bits_width = end - start; let bits = bits.mod_power_of_2(bits_width); let max = U::MAX; if bits_width > width + 1 { panic!("{}", ERROR_MESSAGE); } else if start >= width { assert!(bits == max.mod_power_of_2(bits_width), "{ERROR_MESSAGE}"); } else { let lower_width = width - start; if end > width && bits >> lower_width != max.mod_power_of_2(end - width) { panic!("{}", ERROR_MESSAGE); } else { *x &= T::wrapping_from(!(max.mod_power_of_2(min(bits_width, lower_width)) << start)); *x |= T::wrapping_from(bits << start); } } } } macro_rules! impl_bit_block_access_signed { ($u:ident, $s:ident) => { impl BitBlockAccess for $s { type Bits = $u; /// Extracts a block of adjacent bits from a number. /// /// The first index is `start` and last index is `end - 1`. /// /// The type of the block of bits is the unsigned version of the input type. If `end` is /// greater than the type's width, the high bits of the result are all 0, or all 1, /// depending on the input value's sign; and if the input is negative and `end - start` /// is greater than the type's width, the function panics. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the /// rest are 0. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// If $n < 0$, let /// $$ /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where /// - $W$ is the type's width /// - for all $i$, $b_i\in \\{0, 1\\}$, and $b_i = 1$ for $i \geq W$. /// /// Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Let `W` be the type's width. Panics if `start < end` or (`self < 0` and `end - start /// > W`). /// /// # Examples /// See [here](super::bit_block_access#get_bits). #[inline] fn get_bits(&self, start: u64, end: u64) -> Self::Bits { get_bits_signed(self, start, end) } /// Replaces a block of adjacent bits in a number with other bits. /// /// The least-significant `end - start` bits of `bits` are assigned to bits `start` /// through `end - 1`, inclusive, of `self`. /// /// The type of the block of bits is the unsigned version of the input type. If `bits` /// has fewer bits than `end - start`, the high bits are interpreted as 0 or 1, /// depending on the sign of `self`. If `end` is greater than the type's width, the high /// bits of `bits` must be 0 or 1, depending on the sign of `self`. /// /// The sign of `self` remains unchanged, since only a finite number of bits are changed /// and the sign is determined by the implied infinite prefix of bits. /// /// If $n \geq 0$ and $j \neq W - 1$, let /// $$ /// n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$ and $W$ is `$t::WIDTH`. Let /// $$ /// m = \sum_{i=0}^k 2^{d_i}, /// $$ /// where for all $i$, $d_i\in \\{0, 1\\}$. Also, let $p, q \in \mathbb{N}$, where $d_i /// = 0$ for all $i \geq W + p - 1$. Then /// $$ /// n \gets \sum_{i=0}^{W-1} 2^{c_i}, /// $$ /// where /// $$ /// \\{c_0, c_1, c_2, \ldots, c_ {W-1}\\} = /// \\{b_0, b_1, b_2, \ldots, b_{p-1}, d_0, d_1, \ldots, d_{p-q-1}, b_q, \ldots, /// b_ {W-1}\\}. /// $$ /// /// If $n < 0$ or $j = W - 1$, let /// $$ /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$ and $W$ is `$t::WIDTH`. Let /// $$ /// m = \sum_{i=0}^k 2^{d_i}, /// $$ /// where for all $i$, $d_i\in \\{0, 1\\}$. Also, let $p, q \in \mathbb{N}$, where $d_i /// = 1$ for all $i \geq W + p - 1$. Then /// $$ /// f(n, p, q, m) = \left ( \sum_{i=0}^{W-1} 2^{c_i} \right ) - 2^W, /// $$ /// where /// $$ /// \\{c_0, c_1, c_2, \ldots, c_ {W-1}\\} = /// \\{b_0, b_1, b_2, \ldots, b_{p-1}, d_0, d_1, \ldots, d_{p-q-1}, b_q, \ldots, /// b_ {W-1}\\}. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Let `W` be the type's width Panics if `start < end`, or if `end >= W` and bits `W - /// start` through `end - start` of `bits` are not equal to the original sign bit of /// `self`. /// /// # Examples /// See [here](super::bit_block_access#assign_bits). #[inline] fn assign_bits(&mut self, start: u64, end: u64, bits: &Self::Bits) { assign_bits_signed(self, start, end, bits) } } }; } apply_to_unsigned_signed_pairs!(impl_bit_block_access_signed); ================================================ FILE: malachite-base/src/num/logic/bit_convertible.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::logic::traits::{BitConvertible, LeadingZeros}; use alloc::vec::Vec; fn to_bits_asc_unsigned(x: &T) -> Vec { let mut bits = Vec::new(); let mut x = *x; while x != T::ZERO { bits.push(x.odd()); x >>= 1; } bits } fn to_bits_desc_unsigned(x: &T) -> Vec { let mut bits = Vec::new(); if *x == T::ZERO { return bits; } bits.push(true); if *x == T::ONE { return bits; } let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(*x) - 2); while mask != T::ZERO { bits.push(*x & mask != T::ZERO); mask >>= 1; } bits } fn from_bits_asc_unsigned>(bits: I) -> T { let mut n = T::ZERO; let mut mask = T::ONE; for bit in bits { if mask == T::ZERO { assert!(!bit, "Bits cannot fit in integer of type {}", T::NAME); } else { if bit { n |= mask; } mask <<= 1; } } n } #[inline] fn from_bits_desc_unsigned>(bits: I) -> T { let mut n = T::ZERO; let high_mask = T::power_of_2(T::WIDTH - 1); for bit in bits { assert!( n & high_mask == T::ZERO, "Bits cannot fit in integer of type {}", T::NAME ); n <<= 1; if bit { n |= T::ONE; } } n } macro_rules! impl_bit_convertible_unsigned { ($t:ident) => { impl BitConvertible for $t { /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to /// most-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, it ends with `true`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::bit_convertible#to_bits_asc). #[inline] fn to_bits_asc(&self) -> Vec { to_bits_asc_unsigned(self) } /// Returns a [`Vec`] containing the bits of a number in descending order: most- to /// least-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, it begins with `true`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::bit_convertible#to_bits_desc). #[inline] fn to_bits_desc(&self) -> Vec { to_bits_desc_unsigned(self) } /// Converts an iterator of bits into a number. The bits should be in ascending order /// (least- to most-significant). /// /// The function panics if the input represents a number that can't fit in the output /// type. /// /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`. /// /// # Panics /// Panics if the bits represent a value that isn't representable by the output type. /// /// # Examples /// See [here](super::bit_convertible#from_bits_asc). #[inline] fn from_bits_asc>(bits: I) -> $t { from_bits_asc_unsigned(bits) } /// Converts an iterator of bits into a number. The bits should be in descending order /// (most- to least-significant). /// /// The function panics if the input represents a number that can't fit in the output /// type. /// /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`. /// /// # Panics /// Panics if the bits represent a value that isn't representable by the output type. /// /// # Examples /// See [here](super::bit_convertible#from_bits_desc). #[inline] fn from_bits_desc>(bits: I) -> $t { from_bits_desc_unsigned(bits) } } }; } apply_to_unsigneds!(impl_bit_convertible_unsigned); fn to_bits_asc_signed(x: &T) -> Vec { let mut bits = Vec::new(); let mut x = *x; if x >= T::ZERO { while x != T::ZERO { bits.push(x.odd()); x >>= 1; } if !bits.is_empty() { bits.push(false); } } else { while x != T::NEGATIVE_ONE { bits.push(x.odd()); x >>= 1; } bits.push(true); } bits } fn to_bits_desc_signed(x: &T) -> Vec { let mut bits = Vec::new(); if *x >= T::ZERO { if *x == T::ZERO { return bits; } bits.push(false); bits.push(true); if *x == T::ONE { return bits; } let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(*x) - 2); while mask != T::ZERO { bits.push(*x & mask != T::ZERO); mask >>= 1; } } else { bits.push(true); if *x == T::NEGATIVE_ONE { return bits; } bits.push(false); if *x == T::NEGATIVE_ONE << 1 { return bits; } let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(!*x) - 2); while mask != T::ZERO { bits.push(*x & mask != T::ZERO); mask >>= 1; } } bits } fn from_bits_asc_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, I: Iterator, >( bits: I, ) -> S { let mut n = U::ZERO; let mut mask = U::ONE; let mut last_bit = false; for bit in bits { if mask == U::ZERO { assert_eq!( bit, last_bit, "Bits cannot fit in integer of type {}", S::NAME ); } else { if bit { n |= mask; } mask <<= 1; last_bit = bit; } } if last_bit { S::wrapping_from(n | mask.wrapping_neg()) } else { S::wrapping_from(n) } } #[inline] fn from_bits_desc_signed< U: PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, I: Iterator, >( bits: I, ) -> S { let mut n = U::ZERO; let high_mask = U::power_of_2(U::WIDTH - 2); let mut first = true; let mut sign_bit = false; for bit in bits { if first { sign_bit = bit; first = false; } else { assert!( n & high_mask == U::ZERO, "Bits cannot fit in integer of type {}", S::NAME ); n <<= 1; if bit != sign_bit { n |= U::ONE; } } } if sign_bit { S::wrapping_from(!n) } else { S::wrapping_from(n) } } macro_rules! impl_bit_convertible_signed { ($u:ident, $s:ident) => { impl BitConvertible for $s { /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to /// most-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, the last bit is the sign bit: /// `false` if the number is non-negative and `true` if it is negative. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::bit_convertible#to_bits_asc). #[inline] fn to_bits_asc(&self) -> Vec { to_bits_asc_signed(self) } /// Returns a [`Vec`] containing the bits of a number in ascending order: most- to /// least-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, the first bit is the sign bit: /// `false` if the number is non-negative and `true` if it is negative. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::bit_convertible#to_bits_desc). #[inline] fn to_bits_desc(&self) -> Vec { to_bits_desc_signed(self) } /// Converts an iterator of bits into a value. The bits should be in ascending order /// (least- to most-significant). /// /// The bits are interpreted as in twos-complement, and the last bit is the sign bit; if /// it is `false`, the number is non-negative, and if it is `true`, the number is /// negative. /// /// The function panics if the input represents a number that can't fit in the output /// type. /// /// Let $k$ be `bits.count()`. If $k = 0$ or $b_{k-1}$ is `false`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// If $b_{k-1}$ is `true`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^i \[b_i\] \right ) - 2^k. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`. /// /// # Panics /// Panics if the bits represent a value that doesn't fit in the output type. /// /// # Examples /// See [here](super::bit_convertible#from_bits_asc). #[inline] fn from_bits_asc>(bits: I) -> $s { from_bits_asc_signed::<$u, $s, _>(bits) } /// Converts an iterator of bits into a value. The bits should be in descending order /// (most- to least-significant). /// /// The bits are interpreted as in twos-complement, and the first bit is the sign bit; /// if it is `false`, the number is non-negative, and if it is `true`, the number is /// negative. /// /// The function panics if the input represents a number that can't fit in the output /// type. /// /// If `bits` is empty or $b_0$ is `false`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// If $b_0$ is `true`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\] \right ) - 2^k. /// $$ /// /// # Examples /// See [here](super::bit_convertible#from_bits_desc). #[inline] fn from_bits_desc>(bits: I) -> $s { from_bits_desc_signed::<$u, $s, _>(bits) } } }; } apply_to_unsigned_signed_pairs!(impl_bit_convertible_signed); ================================================ FILE: malachite-base/src/num/logic/bit_iterable.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::logic::traits::BitIterable; use core::cmp::Ordering::*; use core::cmp::min; use core::marker::PhantomData; use core::ops::Index; /// A double-ended iterator over the bits of an unsigned primitive integer. /// /// This `struct` is created by [`BitIterable::bits`]; see its documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct PrimitiveUnsignedBitIterator { pub(crate) value: T, pub(crate) remaining: usize, // If `n` is nonzero, this mask initially points to the least-significant bit, and is left- // shifted by next(). pub(crate) i_mask: T, // If `n` is nonzero, this mask initially points to the most-significant nonzero bit, and is // right-shifted by next_back(). pub(crate) j_mask: T, } impl Iterator for PrimitiveUnsignedBitIterator { type Item = bool; fn next(&mut self) -> Option { if self.remaining != 0 { let bit = self.value & self.i_mask != T::ZERO; self.i_mask <<= 1; self.remaining -= 1; Some(bit) } else { None } } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for PrimitiveUnsignedBitIterator { fn next_back(&mut self) -> Option { if self.remaining != 0 { let bit = self.value & self.j_mask != T::ZERO; self.j_mask >>= 1; self.remaining -= 1; Some(bit) } else { None } } } impl ExactSizeIterator for PrimitiveUnsignedBitIterator {} impl Index for PrimitiveUnsignedBitIterator { type Output = bool; /// A function to retrieve bits by index. /// /// The index is the power of 2 of which the bit is a coefficient. Indexing at or above the /// significant bit count returns false bits. /// /// This is equivalent to [`get_bit`](super::traits::BitAccess::get_bit). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitIterable; /// /// assert_eq!(0u8.bits()[0], false); /// /// // 105 = 1101001b /// let bits = 105u32.bits(); /// assert_eq!(bits[0], true); /// assert_eq!(bits[1], false); /// assert_eq!(bits[2], false); /// assert_eq!(bits[3], true); /// assert_eq!(bits[4], false); /// assert_eq!(bits[5], true); /// assert_eq!(bits[6], true); /// assert_eq!(bits[7], false); /// assert_eq!(bits[100], false); /// ``` fn index(&self, index: u64) -> &bool { if self.value.get_bit(index) { &true } else { &false } } } fn bits_unsigned(x: T) -> PrimitiveUnsignedBitIterator { let significant_bits = x.significant_bits(); PrimitiveUnsignedBitIterator { value: x, remaining: usize::exact_from(significant_bits), i_mask: T::ONE, j_mask: T::power_of_2(significant_bits.saturating_sub(1)), } } macro_rules! impl_bit_iterable_unsigned { ($t:ident) => { impl BitIterable for $t { type BitIterator = PrimitiveUnsignedBitIterator<$t>; /// Returns a double-ended iterator over the bits of an unsigned primitive integer. /// /// The forward order is ascending, so that less significant bits appear first. There /// are no trailing false bits going forward, or leading falses going backward. /// /// If it's necessary to get a [`Vec`] of all the bits, consider using /// [`to_bits_asc`](super::traits::BitConvertible::to_bits_asc) or /// [`to_bits_desc`](super::traits::BitConvertible::to_bits_desc) instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_iterable#bits). #[inline] fn bits(self) -> PrimitiveUnsignedBitIterator<$t> { bits_unsigned(self) } } }; } apply_to_unsigneds!(impl_bit_iterable_unsigned); /// A double-ended iterator over the bits of a signed primitive integer. /// /// This `struct` is created by [`BitIterable::bits`]; see its documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct PrimitiveSignedBitIterator { phantom: PhantomData<*const S>, xs: PrimitiveUnsignedBitIterator, } impl Iterator for PrimitiveSignedBitIterator { type Item = bool; #[inline] fn next(&mut self) -> Option { self.xs.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.xs.size_hint() } } impl DoubleEndedIterator for PrimitiveSignedBitIterator { #[inline] fn next_back(&mut self) -> Option { self.xs.next_back() } } impl ExactSizeIterator for PrimitiveSignedBitIterator { } impl Index for PrimitiveSignedBitIterator { type Output = bool; /// A function to retrieve bits by index. The index is the power of 2 of which the bit is a /// coefficient. /// /// Indexing at or above the significant bit count returns false or true bits, depending on the /// value's sign. /// /// This is equivalent to [`get_bit`](super::traits::BitAccess::get_bit). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitIterable; /// /// assert_eq!(0i8.bits()[0], false); /// /// // -105 = 10010111 in two's complement /// let bits = (-105i32).bits(); /// assert_eq!(bits[0], true); /// assert_eq!(bits[1], true); /// assert_eq!(bits[2], true); /// assert_eq!(bits[3], false); /// assert_eq!(bits[4], true); /// assert_eq!(bits[5], false); /// assert_eq!(bits[6], false); /// assert_eq!(bits[7], true); /// assert_eq!(bits[100], true); /// ``` fn index(&self, index: u64) -> &bool { if self.xs[min(index, U::WIDTH - 1)] { &true } else { &false } } } fn bits_signed, S: PrimitiveSigned>( x: S, ) -> PrimitiveSignedBitIterator { let unsigned = U::wrapping_from(x); let significant_bits = match x.sign() { Equal => 0, Greater => unsigned.significant_bits() + 1, Less => (!unsigned).significant_bits() + 1, }; PrimitiveSignedBitIterator { phantom: PhantomData, xs: PrimitiveUnsignedBitIterator { value: unsigned, remaining: usize::exact_from(significant_bits), i_mask: U::ONE, j_mask: U::power_of_2(significant_bits.saturating_sub(1)), }, } } macro_rules! impl_bit_iterable_signed { ($u:ident, $s:ident) => { impl BitIterable for $s { type BitIterator = PrimitiveSignedBitIterator<$u, $s>; /// Returns a double-ended iterator over the bits of a signed primitive integer. /// /// The forward order is ascending, so that less significant bits appear first. There /// are no trailing sign bits going forward, or leading sign bits going backward. /// /// If it's necessary to get a [`Vec`] of all the bits, consider using /// [`to_bits_asc`](super::traits::BitConvertible::to_bits_asc) or /// [`to_bits_desc`](super::traits::BitConvertible::to_bits_desc) instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_iterable#bits). #[inline] fn bits(self) -> PrimitiveSignedBitIterator<$u, $s> { bits_signed::<$u, $s>(self) } } }; } apply_to_unsigned_signed_pairs!(impl_bit_iterable_signed); ================================================ FILE: malachite-base/src/num/logic/bit_scan.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::{BitScan, TrailingZeros}; fn index_of_next_false_bit_unsigned(x: T, start: u64) -> u64 { if start >= T::WIDTH { start } else { TrailingZeros::trailing_zeros(!(x | T::low_mask(start))) } } fn index_of_next_true_bit_unsigned(x: T, start: u64) -> Option { if start >= T::WIDTH { None } else { let index = TrailingZeros::trailing_zeros(x & !T::low_mask(start)); if index == T::WIDTH { None } else { Some(index) } } } macro_rules! impl_bit_scan_unsigned { ($t:ident) => { impl BitScan for $t { /// Given a number and a starting index, searches the number for the smallest index of a /// `false` bit that is greater than or equal to the starting index. /// /// Since the number is unsigned and therefore has an implicit prefix of infinitely-many /// zeros, this function always returns a value. /// /// Starting beyond the type's width is allowed; the result is the starting index. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_scan#index_of_next_false_bit). #[inline] fn index_of_next_false_bit(self, start: u64) -> Option { Some(index_of_next_false_bit_unsigned(self, start)) } /// Given a number and a starting index, searches the number for the smallest index of a /// `true` bit that is greater than or equal to the starting index. /// /// If the starting index is greater than or equal to the type's width, the result is /// `None` since there are no `true` bits past that point. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_scan#index_of_next_true_bit). #[inline] fn index_of_next_true_bit(self, start: u64) -> Option { index_of_next_true_bit_unsigned(self, start) } } }; } apply_to_unsigneds!(impl_bit_scan_unsigned); fn index_of_next_false_bit_signed(x: T, start: u64) -> Option { if start >= T::WIDTH - 1 { if x >= T::ZERO { Some(start) } else { None } } else { let index = TrailingZeros::trailing_zeros(!(x | T::low_mask(start))); if index == T::WIDTH { None } else { Some(index) } } } fn index_of_next_true_bit_signed(x: T, start: u64) -> Option { if start >= T::WIDTH - 1 { if x >= T::ZERO { None } else { Some(start) } } else { let index = TrailingZeros::trailing_zeros(x & !T::low_mask(start)); if index == T::WIDTH { None } else { Some(index) } } } macro_rules! impl_bit_scan_signed { ($t:ident) => { impl BitScan for $t { /// Given a number and a starting index, searches the number for the smallest index of a /// `false` bit that is greater than or equal to the starting index. /// /// If the starting index is greater than or equal to the type's width, then the result /// depends on whether the number is negative. If it is, then the result is `None` since /// there are no `false` bits past that point. If the number is non-negative, then the /// result is the starting index. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_scan#index_of_next_false_bit). #[inline] fn index_of_next_false_bit(self, start: u64) -> Option { index_of_next_false_bit_signed(self, start) } /// Given a number and a starting index, searches the number for the smallest index of a /// `true` bit that is greater than or equal to the starting index. /// /// If the starting index is greater than or equal to the type's width, then the result /// depends on whether the number is non-negative. If it is, then the result is `None` /// since there are no `true` bits past that point. If the number is negative, then the /// result is the starting index. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::bit_scan#index_of_next_true_bit). #[inline] fn index_of_next_true_bit(self, start: u64) -> Option { index_of_next_true_bit_signed(self, start) } } }; } apply_to_signeds!(impl_bit_scan_signed); ================================================ FILE: malachite-base/src/num/logic/count_ones.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::CountOnes; macro_rules! impl_count_ones { ($t:ident) => { impl CountOnes for $t { /// This is a wrapper over the `count_ones` functions in the standard library, for /// example [this one](u32::count_ones). #[inline] fn count_ones(self) -> u64 { u64::from($t::count_ones(self)) } } }; } apply_to_primitive_ints!(impl_count_ones); ================================================ FILE: malachite-base/src/num/logic/count_zeros.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::CountZeros; macro_rules! impl_count_zeros { ($t:ident) => { impl CountZeros for $t { /// This is a wrapper over the `count_zeros` functions in the standard library, for /// example [this one](u32::count_zeros). #[inline] fn count_zeros(self) -> u64 { u64::from($t::count_zeros(self)) } } }; } apply_to_primitive_ints!(impl_count_zeros); ================================================ FILE: malachite-base/src/num/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::{CheckedHammingDistance, CountOnes, HammingDistance}; fn hamming_distance_unsigned(x: T, y: T) -> u64 { CountOnes::count_ones(x ^ y) } macro_rules! impl_hamming_distance_unsigned { ($t:ident) => { impl HammingDistance<$t> for $t { /// Returns the Hamming distance between two numbers, or the number of bit flips needed /// to turn one into the other. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::hamming_distance#hamming_distance). #[inline] fn hamming_distance(self, other: $t) -> u64 { hamming_distance_unsigned(self, other) } } }; } apply_to_unsigneds!(impl_hamming_distance_unsigned); fn checked_hamming_distance_signed(x: T, y: T) -> Option { if (x >= T::ZERO) == (y >= T::ZERO) { Some(CountOnes::count_ones(x ^ y)) } else { None } } macro_rules! impl_checked_hamming_distance_signed { ($t:ident) => { impl CheckedHammingDistance<$t> for $t { /// Returns the Hamming distance between two numbers, or the number of bit flips needed /// to turn one into the other. /// /// If the two numbers have opposite signs, then the number of flips would be infinite, /// so the result is `None`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::hamming_distance#checked_hamming_distance). #[inline] fn checked_hamming_distance(self, other: $t) -> Option { checked_hamming_distance_signed(self, other) } } }; } apply_to_signeds!(impl_checked_hamming_distance_signed); ================================================ FILE: malachite-base/src/num/logic/leading_zeros.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::LeadingZeros; macro_rules! impl_leading_zeros { ($t:ident) => { impl LeadingZeros for $t { /// This is a wrapper over the `leading_zeros` functions in the standard library, for /// example [this one](u32::leading_zeros). #[inline] fn leading_zeros(self) -> u64 { u64::from($t::leading_zeros(self)) } } }; } apply_to_primitive_ints!(impl_leading_zeros); ================================================ FILE: malachite-base/src/num/logic/low_mask.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::LowMask; fn low_mask_unsigned(bits: u64) -> T { assert!(bits <= T::WIDTH); if bits == T::WIDTH { T::MAX } else { T::power_of_2(bits) - T::ONE } } macro_rules! impl_low_mask_unsigned { ($t:ident) => { impl LowMask for $t { /// Returns a number whose least significant $b$ bits are `true` and whose other bits /// are `false`. /// /// $f(b) = 2^b - 1$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is greater than the width of of the type. /// /// # Examples /// See [here](super::low_mask#low_mask). #[inline] fn low_mask(bits: u64) -> $t { low_mask_unsigned(bits) } } }; } apply_to_unsigneds!(impl_low_mask_unsigned); fn low_mask_signed(bits: u64) -> T { assert!(bits <= T::WIDTH); if bits == T::WIDTH { T::NEGATIVE_ONE } else if bits == T::WIDTH - 1 { T::MAX } else { T::power_of_2(bits) - T::ONE } } macro_rules! impl_low_mask_signed { ($t:ident) => { impl LowMask for $t { /// Returns a number whose least significant $b$ bits are `true` and whose other bits /// are `false`. /// /// $$ /// f(b) = \\begin{cases} /// 2^b - 1 & \text{if} \\quad 0 \leq n < W, \\\\ /// -1 & \text{if} \\quad n = W, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `bits` is greater than the width of the type. /// /// # Examples /// See [here](super::low_mask#low_mask). #[inline] fn low_mask(bits: u64) -> $t { low_mask_signed(bits) } } }; } apply_to_signeds!(impl_low_mask_signed); ================================================ FILE: malachite-base/src/num/logic/mod.rs ================================================ // Copyright © 2026 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 . /// [`BitAccess`](traits::BitAccess), a trait for getting and setting individual bits of a number. /// /// # get_bit /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// /// assert_eq!(123u8.get_bit(2), false); /// assert_eq!(123u16.get_bit(3), true); /// assert_eq!(123u32.get_bit(100), false); /// assert_eq!(1000000000000u64.get_bit(12), true); /// assert_eq!(1000000000000u64.get_bit(100), false); /// /// assert_eq!(123i8.get_bit(2), false); /// assert_eq!(123i16.get_bit(3), true); /// assert_eq!(123i32.get_bit(100), false); /// assert_eq!((-123i8).get_bit(0), true); /// assert_eq!((-123i16).get_bit(1), false); /// assert_eq!((-123i32).get_bit(100), true); /// assert_eq!(1000000000000i64.get_bit(12), true); /// assert_eq!(1000000000000i64.get_bit(100), false); /// assert_eq!((-1000000000000i64).get_bit(12), true); /// assert_eq!((-1000000000000i64).get_bit(100), true); /// ``` /// /// # set_bit /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// /// let mut x = 0u8; /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, 100); /// /// let mut x = 0i8; /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, 100); /// /// let mut x = -0x100i16; /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, -156); /// ``` /// /// # clear_bit /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// /// let mut x = 0x7fu8; /// x.clear_bit(0); /// x.clear_bit(1); /// x.clear_bit(3); /// x.clear_bit(4); /// assert_eq!(x, 100); /// /// let mut x = 0x7fi8; /// x.clear_bit(0); /// x.clear_bit(1); /// x.clear_bit(3); /// x.clear_bit(4); /// assert_eq!(x, 100); /// /// let mut x = -156i16; /// x.clear_bit(2); /// x.clear_bit(5); /// x.clear_bit(6); /// assert_eq!(x, -256); /// ``` /// /// # assign_bit /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// /// let mut x = 0; /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, 100); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, 0); /// /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, 100); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, 0); /// /// let mut x = -0x100i16; /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, -156); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, -256); /// ``` /// /// # flip_bit /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// /// let mut x = 0u64; /// x.flip_bit(10); /// assert_eq!(x, 1024); /// x.flip_bit(10); /// assert_eq!(x, 0); /// /// let mut x = 0i32; /// x.flip_bit(10); /// assert_eq!(x, 1024); /// x.flip_bit(10); /// assert_eq!(x, 0); /// /// let mut x = -1i64; /// x.flip_bit(10); /// assert_eq!(x, -1025); /// x.flip_bit(10); /// assert_eq!(x, -1); /// ``` pub mod bit_access; /// [`BitBlockAccess`](traits::BitBlockAccess), a trait for getting and setting adjacent blocks of /// bits in a number. /// /// # get_bits /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// /// assert_eq!(0xabcdu16.get_bits(4, 8), 0xc); /// assert_eq!(0xabcdu16.get_bits(12, 100), 0xa); /// assert_eq!(0xabcdu16.get_bits(5, 9), 14); /// assert_eq!(0xabcdu16.get_bits(5, 5), 0); /// assert_eq!(0xabcdu16.get_bits(100, 200), 0); /// /// assert_eq!((-0x5433i16).get_bits(4, 8), 0xc); /// assert_eq!((-0x5433i16).get_bits(5, 9), 14); /// assert_eq!((-0x5433i16).get_bits(5, 5), 0); /// assert_eq!((-0x5433i16).get_bits(100, 104), 0xf); /// ``` /// /// # assign_bits /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// /// let mut x = 0xab5du16; /// x.assign_bits(4, 8, &0xc); /// assert_eq!(x, 0xabcd); /// /// let mut x = 0xabcdu16; /// x.assign_bits(100, 200, &0); /// assert_eq!(x, 0xabcd); /// /// let mut x = 0xabcdu16; /// x.assign_bits(0, 100, &0x1234); /// assert_eq!(x, 0x1234); /// /// let mut x = 0x2b5di16; /// x.assign_bits(4, 8, &0xc); /// assert_eq!(x, 0x2bcd); /// /// let mut x = -0x5413i16; /// x.assign_bits(4, 8, &0xc); /// assert_eq!(x, -0x5433); /// /// let mut x = -0x5433i16; /// x.assign_bits(100, 104, &0xf); /// assert_eq!(x, -0x5433); /// ``` pub mod bit_block_access; /// [`BitConvertible`](traits::BitConvertible), a trait for extracting all bits from a number or /// constructing a number from bits. /// /// # to_bits_asc /// ``` /// use malachite_base::num::logic::traits::BitConvertible; /// /// assert_eq!(0u8.to_bits_asc(), &[]); /// assert_eq!(2u16.to_bits_asc(), &[false, true]); /// assert_eq!( /// 123u32.to_bits_asc(), /// &[true, true, false, true, true, true, true] /// ); /// /// assert_eq!(0i8.to_bits_asc(), &[]); /// assert_eq!(2i16.to_bits_asc(), &[false, true, false]); /// assert_eq!( /// (-123i32).to_bits_asc(), /// &[true, false, true, false, false, false, false, true] /// ); /// ``` /// /// # to_bits_desc /// ``` /// use malachite_base::num::logic::traits::BitConvertible; /// /// assert_eq!(0u8.to_bits_desc(), &[]); /// assert_eq!(2u16.to_bits_desc(), &[true, false]); /// assert_eq!( /// 123u32.to_bits_desc(), /// &[true, true, true, true, false, true, true] /// ); /// /// assert_eq!(0i8.to_bits_desc(), &[]); /// assert_eq!(2i16.to_bits_desc(), &[false, true, false]); /// assert_eq!( /// (-123i32).to_bits_desc(), /// &[true, false, false, false, false, true, false, true] /// ); /// ``` /// /// # from_bits_asc /// ``` /// use malachite_base::num::logic::traits::BitConvertible; /// use std::iter::empty; /// /// assert_eq!(u8::from_bits_asc(empty()), 0); /// assert_eq!(u16::from_bits_asc([false, true, false].iter().cloned()), 2); /// assert_eq!( /// u32::from_bits_asc([true, true, false, true, true, true, true].iter().cloned()), /// 123 /// ); /// /// assert_eq!(i8::from_bits_asc(empty()), 0); /// assert_eq!(i16::from_bits_asc([false, true, false].iter().cloned()), 2); /// assert_eq!( /// i32::from_bits_asc( /// [true, false, true, false, false, false, false, true] /// .iter() /// .cloned() /// ), /// -123 /// ); /// ``` /// /// # from_bits_desc /// ``` /// use malachite_base::num::logic::traits::BitConvertible; /// use std::iter::empty; /// /// assert_eq!(u8::from_bits_desc(empty()), 0); /// assert_eq!(u16::from_bits_desc([false, true, false].iter().cloned()), 2); /// assert_eq!( /// u32::from_bits_desc([true, true, true, true, false, true, true].iter().cloned()), /// 123 /// ); /// /// assert_eq!(i8::from_bits_desc(empty()), 0); /// assert_eq!(i16::from_bits_desc([false, true, false].iter().cloned()), 2); /// assert_eq!( /// i32::from_bits_desc( /// [true, false, false, false, false, true, false, true] /// .iter() /// .cloned() /// ), /// -123 /// ); /// ``` pub mod bit_convertible; /// [`BitIterable`](traits::BitIterable), a trait for producing a double-ended iterator over a /// number's bits. /// /// # bits /// ``` /// use itertools::Itertools; /// use malachite_base::num::logic::traits::BitIterable; /// /// assert!(0u8.bits().next().is_none()); /// // 105 = 1101001b /// assert_eq!( /// 105u32.bits().collect_vec(), /// &[true, false, false, true, false, true, true] /// ); /// /// assert!(0u8.bits().next_back().is_none()); /// // 105 = 1101001b /// assert_eq!( /// 105u32.bits().rev().collect_vec(), /// &[true, true, false, true, false, false, true] /// ); /// /// assert_eq!(0i8.bits().next(), None); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// 105i32.bits().collect_vec(), /// &[true, false, false, true, false, true, true, false] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// (-105i32).bits().collect_vec(), /// &[true, true, true, false, true, false, false, true] /// ); /// /// assert_eq!(0i8.bits().next_back(), None); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// 105i32.bits().rev().collect_vec(), /// &[false, true, true, false, true, false, false, true] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// (-105i32).bits().rev().collect_vec(), /// &[true, false, false, true, false, true, true, true] /// ); /// ``` pub mod bit_iterable; /// [`BitScan`](traits::BitScan), a trait for finding the next `true` or `false` bit in a number /// after a provided index. /// /// # index_of_next_false_bit /// ``` /// use malachite_base::num::logic::traits::BitScan; /// /// assert_eq!(0xb00000000u64.index_of_next_false_bit(0), Some(0)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(20), Some(20)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(31), Some(31)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(32), Some(34)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(33), Some(34)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(34), Some(34)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(35), Some(36)); /// assert_eq!(0xb00000000u64.index_of_next_false_bit(100), Some(100)); /// /// assert_eq!((-0x500000000i64).index_of_next_false_bit(0), Some(0)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(20), Some(20)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(31), Some(31)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(32), Some(34)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(33), Some(34)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(34), Some(34)); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(35), None); /// assert_eq!((-0x500000000i64).index_of_next_false_bit(100), None); /// ``` /// /// # index_of_next_true_bit /// ``` /// use malachite_base::num::logic::traits::BitScan; /// /// assert_eq!(0xb00000000u64.index_of_next_true_bit(0), Some(32)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(20), Some(32)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(31), Some(32)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(32), Some(32)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(33), Some(33)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(34), Some(35)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(35), Some(35)); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(36), None); /// assert_eq!(0xb00000000u64.index_of_next_true_bit(100), None); /// /// assert_eq!((-0x500000000i64).index_of_next_true_bit(0), Some(32)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(20), Some(32)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(31), Some(32)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(32), Some(32)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(33), Some(33)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(34), Some(35)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(35), Some(35)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(36), Some(36)); /// assert_eq!((-0x500000000i64).index_of_next_true_bit(100), Some(100)); /// ``` pub mod bit_scan; /// [`CountOnes`](traits::CountOnes), a trait for counting the number of ones in the binary /// representation of a number. pub mod count_ones; /// [`CountZeros`](traits::CountZeros), a trait for counting the number of ones in the binary /// representation of a number. pub mod count_zeros; /// [`HammingDistance`](traits::HammingDistance) and /// [`CheckedHammingDistance`](traits::CheckedHammingDistance), traits for computing the Hamming /// distance between two numbers. /// /// # hamming_distance /// ``` /// use malachite_base::num::logic::traits::HammingDistance; /// /// assert_eq!(123u32.hamming_distance(456), 6); /// assert_eq!(0u8.hamming_distance(255), 8); /// ``` /// /// # checked_hamming_distance /// ``` /// use malachite_base::num::logic::traits::CheckedHammingDistance; /// /// assert_eq!(123i32.checked_hamming_distance(456), Some(6)); /// assert_eq!(0i8.checked_hamming_distance(127), Some(7)); /// assert_eq!(0i8.checked_hamming_distance(-1), None); /// ``` pub mod hamming_distance; /// [`LeadingZeros`](traits::LeadingZeros), a trait for determining the number of zeros that a /// number starts with, when written in binary using $W$ bits, $W$ being the type width. pub mod leading_zeros; /// [`LowMask`](traits::LowMask), a trait for generating a low bit mask (a number in which only the /// $k$ least-significant bits are 1). /// /// # low_mask /// ``` /// use malachite_base::num::logic::traits::LowMask; /// /// assert_eq!(u16::low_mask(0), 0); /// assert_eq!(u8::low_mask(3), 0x7); /// assert_eq!(u8::low_mask(8), 0xff); /// assert_eq!(u64::low_mask(40), 0xffffffffff); /// /// assert_eq!(i16::low_mask(0), 0); /// assert_eq!(i8::low_mask(3), 0x7); /// assert_eq!(i8::low_mask(8), -1); /// assert_eq!(i64::low_mask(40), 0xffffffffff); /// ``` pub mod low_mask; /// [`NotAssign`](traits::NotAssign), a trait for replacing a number with its bitwise negation. /// /// # not_assign /// ``` /// use malachite_base::num::logic::traits::NotAssign; /// /// let mut x = 123u16; /// x.not_assign(); /// assert_eq!(x, 65412); /// ``` pub mod not; /// [`SignificantBits`](traits::SignificantBits), a trait for determining how many significant bits /// a number has. /// /// # significant_bits /// ``` /// use malachite_base::num::logic::traits::SignificantBits; /// /// assert_eq!(0u8.significant_bits(), 0); /// assert_eq!(100u64.significant_bits(), 7); /// /// assert_eq!(0i8.significant_bits(), 0); /// assert_eq!((-100i64).significant_bits(), 7); /// ``` pub mod significant_bits; /// [`TrailingZeros`](traits::TrailingZeros), a trait for determining the number of zeros that a /// number ends with when written in binary. pub mod trailing_zeros; /// Various traits for performing logic or bitwise operations on numbers. pub mod traits; ================================================ FILE: malachite-base/src/num/logic/not.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::NotAssign; macro_rules! impl_not { ($t:ident) => { impl NotAssign for $t { /// Replaces a number with its bitwise negation. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::not#not_assign). #[inline] fn not_assign(&mut self) { *self = !*self; } } }; } apply_to_primitive_ints!(impl_not); ================================================ FILE: malachite-base/src/num/logic/significant_bits.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::UnsignedAbs; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::{LeadingZeros, SignificantBits}; fn significant_bits_unsigned(x: T) -> u64 { T::WIDTH - LeadingZeros::leading_zeros(x) } macro_rules! impl_significant_bits_unsigned { ($t:ident) => { impl SignificantBits for $t { /// Returns the number of significant bits of an unsigned primitive integer. /// /// This is the integer's width minus the number of leading zeros. /// /// $$ /// f(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \lfloor \log_2 n \rfloor + 1 & \text{if} \\quad n > 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::significant_bits#significant_bits). #[inline] fn significant_bits(self) -> u64 { significant_bits_unsigned(self) } } }; } apply_to_unsigneds!(impl_significant_bits_unsigned); fn significant_bits_signed>( x: S, ) -> u64 { x.unsigned_abs().significant_bits() } macro_rules! impl_significant_bits_signed { ($u:ident, $s:ident) => { /// Returns the number of significant bits of a signed primitive integer. /// /// This is the integer's width minus the number of leading zeros of its absolute value. /// /// $$ /// f(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \lfloor \log_2 |n| \rfloor + 1 & \text{if} \\quad n \neq 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::significant_bits#significant_bits). impl SignificantBits for $s { #[inline] fn significant_bits(self) -> u64 { significant_bits_signed(self) } } }; } apply_to_unsigned_signed_pairs!(impl_significant_bits_signed); ================================================ FILE: malachite-base/src/num/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 crate::num::logic::traits::TrailingZeros; macro_rules! impl_trailing_zeros { ($t:ident) => { impl TrailingZeros for $t { /// This is a wrapper over the `trailing_zeros` functions in the standard library, for /// example [this one](u32::trailing_zeros). #[inline] fn trailing_zeros(self) -> u64 { u64::from($t::trailing_zeros(self)) } } }; } apply_to_primitive_ints!(impl_trailing_zeros); ================================================ FILE: malachite-base/src/num/logic/traits.rs ================================================ // Copyright © 2026 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 alloc::vec::Vec; use core::ops::Index; /// Defines functions that access or modify individual bits in a number. pub trait BitAccess { /// Determines whether a number has a `true` or `false` bit at `index`. fn get_bit(&self, index: u64) -> bool; /// Sets the bit at `index` to `true`. fn set_bit(&mut self, index: u64); /// Sets the bit at `index` to `false`. fn clear_bit(&mut self, index: u64); /// Sets the bit at `index` to whichever value `bit` is. /// /// # Worst-case complexity /// $T(n) = O(\max(T_S(n), T_C(n)))$, /// /// $M(n) = O(\max(M_S(n), M_C(n)))$ /// /// where $T$ is time, $M$ is additional memory, $T_S$ and $M_S$ are the complexities of /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of /// [`clear_bit`](Self::clear_bit). /// /// # Panics /// See panics for [`set_bit`](Self::set_bit) and [`clear_bit`](Self::clear_bit). #[inline] fn assign_bit(&mut self, index: u64, bit: bool) { if bit { self.set_bit(index); } else { self.clear_bit(index); } } /// Sets the bit at `index` to the opposite of its original value. /// /// # Worst-case complexity /// $T(n) = O(T_G(n) + \max(T_S(n), T_C(n)))$, /// /// $M(n) = O(M_G(n) + \max(M_S(n), M_C(n)))$ /// /// where $T$ is time, $M$ is additional memory, $T_G$ and $M_G$ are the complexities of /// [`get_bit`](Self::get_bit), $T_S$ and $M_S$ are the complexities of /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of /// [`clear_bit`](Self::clear_bit). /// /// # Panics /// See panics for [`get_bit`](Self::get_bit), [`set_bit`](Self::set_bit) and /// [`clear_bit`](Self::clear_bit). #[inline] fn flip_bit(&mut self, index: u64) { if self.get_bit(index) { self.clear_bit(index); } else { self.set_bit(index); } } } /// Defines functions that access or modify blocks of adjacent bits in a number. pub trait BitBlockAccess: Sized { type Bits; /// Extracts a block of bits whose first index is `start` and last index is `end - 1`. fn get_bits(&self, start: u64, end: u64) -> Self::Bits; /// Extracts a block of bits whose first index is `start` and last index is `end - 1`, taking /// ownership of `self`. /// /// # Worst-case complexity /// For the default implementation, same as [`get_bits`](Self::get_bits). /// /// # Panics /// For the default implementation, ee panics for [`get_bits`](Self::get_bits). /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// /// assert_eq!((-0x5433i16).get_bits_owned(4, 8), 0xc); /// assert_eq!((-0x5433i16).get_bits_owned(5, 9), 14); /// assert_eq!((-0x5433i16).get_bits_owned(5, 5), 0); /// assert_eq!((-0x5433i16).get_bits_owned(100, 104), 0xf); /// ``` #[inline] fn get_bits_owned(self, start: u64, end: u64) -> Self::Bits { self.get_bits(start, end) } /// Assigns the least-significant `end - start` bits of `bits` to bits `start` through `end - 1` /// (inclusive) of `self`. fn assign_bits(&mut self, start: u64, end: u64, bits: &Self::Bits); } /// Defines functions that express a number as a [`Vec`] of bits or construct a number from an /// iterator of bits. pub trait BitConvertible { /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to /// most-significant. fn to_bits_asc(&self) -> Vec; /// Returns a [`Vec`] containing the bits of a number in descending order: most- to /// least-significant. fn to_bits_desc(&self) -> Vec; /// Converts an iterator of bits into a number. The input bits are in ascending order: least- to /// most-significant. fn from_bits_asc>(bits: I) -> Self; /// Converts an iterator of bits into a value. The input bits are in descending order: most- to /// least-significant. fn from_bits_desc>(bits: I) -> Self; } /// Defines an iterator over a value's bits. pub trait BitIterable { type BitIterator: DoubleEndedIterator + Index; /// Returns a double-ended iterator over a number's bits. When iterating in the forward /// direction, the iterator ends after the producing the number's most-significant bit. fn bits(self) -> Self::BitIterator; } /// Defines functions that search for the next `true` or `false` bit in a number, starting at a /// specified index and searching in the more-significant direction. pub trait BitScan { /// Given a number and a starting index, searches the number for the smallest index of a `false` /// bit that is greater than or equal to the starting index. fn index_of_next_false_bit(self, start: u64) -> Option; /// Given a number and a starting index, searches the number for the smallest index of a `true` /// bit that is greater than or equal to the starting index. fn index_of_next_true_bit(self, start: u64) -> Option; } /// Returns the number of ones in the binary representation of a number. pub trait CountOnes { fn count_ones(self) -> u64; } /// Returns the number of zeros in the binary representation of a number. pub trait CountZeros { fn count_zeros(self) -> u64; } /// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one /// into the other. pub trait HammingDistance { fn hamming_distance(self, other: RHS) -> u64; } /// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one /// into the other. /// /// This trait allows for the possibility of the distance being undefined for some pairs of numbers, /// in which case [`checked_hamming_distance`](Self::checked_hamming_distance) should return `None`. pub trait CheckedHammingDistance { fn checked_hamming_distance(self, other: RHS) -> Option; } /// Returns the number of leading zeros in the binary representation of a number. pub trait LeadingZeros { fn leading_zeros(self) -> u64; } /// Returns a number whose least significant $b$ bits are `true` and whose other bits are `false`. pub trait LowMask { fn low_mask(bits: u64) -> Self; } /// Replaces a number with its bitwise negation. pub trait NotAssign { fn not_assign(&mut self); } // Returns the number of significant bits of a number. pub trait SignificantBits { /// The number of bits it takes to represent `self`. fn significant_bits(self) -> u64; } /// Returns the number of trailing zeros in the binary representation of a number. pub trait TrailingZeros { fn trailing_zeros(self) -> u64; } ================================================ FILE: malachite-base/src/num/macros.rs ================================================ // Copyright © 2026 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 . #[doc(hidden)] #[macro_export] macro_rules! apply_to_unsigneds { ($m: tt) => { $m!(u8); $m!(u16); $m!(u32); $m!(u64); $m!(u128); $m!(usize); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_to_signeds { ($m: tt) => { $m!(i8); $m!(i16); $m!(i32); $m!(i64); $m!(i128); $m!(isize); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_to_primitive_ints { ($m: tt) => { apply_to_unsigneds!($m); apply_to_signeds!($m); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_to_unsigned_signed_pairs { ($m: tt) => { $m!(u8, i8); $m!(u16, i16); $m!(u32, i32); $m!(u64, i64); $m!(u128, i128); $m!(usize, isize); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_signeds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_ints { ($f: ident) => { apply_fn_to_unsigneds!($f); apply_fn_to_signeds!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigned_signed_pairs { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds_and_unsigneds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds_and_signeds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds_and_primitive_ints { ($f: ident) => { apply_fn_to_unsigneds_and_unsigneds!($f); apply_fn_to_unsigneds_and_signeds!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds_and_unsigned_signed_pairs { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_unsigneds_and_primitive_floats { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_signeds_and_primitive_floats { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_ints_and_primitive_floats { ($f: ident) => { apply_fn_to_unsigneds_and_primitive_floats!($f); apply_fn_to_signeds_and_primitive_floats!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_floats_and_unsigneds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_floats_and_signeds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_floats_and_unsigned_signed_pairs { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_signeds_and_unsigneds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_signeds_and_signeds { ($f: ident) => { $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); $f::(); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_ints_and_unsigneds { ($f: ident) => { apply_fn_to_unsigneds_and_unsigneds!($f); apply_fn_to_signeds_and_unsigneds!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_ints_and_signeds { ($f: ident) => { apply_fn_to_unsigneds_and_signeds!($f); apply_fn_to_signeds_and_signeds!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_ints_and_primitive_ints { ($f: ident) => { apply_fn_to_primitive_ints_and_unsigneds!($f); apply_fn_to_primitive_ints_and_signeds!($f); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_to_primitive_floats { ($m: tt) => { $m!(f32); $m!(f64); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_to_primitive_float_unsigned_pairs { ($m: tt) => { $m!(f32, u32); $m!(f64, u64); }; } #[doc(hidden)] #[macro_export] macro_rules! apply_fn_to_primitive_floats { ($f: ident) => { $f::(); $f::(); }; } ================================================ FILE: malachite-base/src/num/mod.rs ================================================ // Copyright © 2026 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 . #[doc(hidden)] #[macro_use] pub mod macros; /// Traits for arithmetic. pub mod arithmetic; /// Traits for primitive integers or floats and some of their basic functionality. pub mod basic; /// Traits for comparing the absolute values of numbers for equality or order. pub mod comparison; /// Traits for converting to and from numbers, converting to and from strings, and extracting /// digits. pub mod conversion; /// Iterators that generate numbers without repetition. pub mod exhaustive; /// Traits for generating primes, primality testing, and factorization. pub mod factorization; /// [`NiceFloat`](float::NiceFloat), a wrapper around primitive floats. pub mod float; /// Iterators related to numbers. pub mod iterators; /// Traits for logic and bit manipulation. pub mod logic; #[cfg(feature = "random")] /// Iterators that generate numbers randomly. pub mod random; ================================================ FILE: malachite-base/src/num/random/geometric.rs ================================================ // Copyright © 2026 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 crate::bools::random::{ RandomBools, WeightedRandomBools, get_weighted_random_bool, random_bools, weighted_random_bools, }; use crate::num::arithmetic::traits::Gcd; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactInto; use crate::random::Seed; use std::fmt::Debug; use super::VariableRangeGenerator; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) struct SimpleRational { pub(crate) n: u64, pub(crate) d: u64, } impl SimpleRational { pub(crate) fn new(n: u64, d: u64) -> Self { assert_ne!(d, 0); let gcd = n.gcd(d); Self { n: n / gcd, d: d / gcd, } } fn inverse(self) -> Self { assert_ne!(self.n, 0); Self { n: self.d, d: self.n, } } // unwrap not const yet #[allow(clippy::missing_const_for_fn)] fn sub_u64(self, x: u64) -> Self { Self { n: self.n.checked_sub(x.checked_mul(self.d).unwrap()).unwrap(), d: self.d, } } } pub(crate) fn mean_to_p_with_min( min: T, um_numerator: u64, um_denominator: u64, ) -> (u64, u64) { let um = SimpleRational::new(um_numerator, um_denominator); let p = um.sub_u64(ExactInto::::exact_into(min)).inverse(); (p.n, p.d) } /// Generates random unsigned integers from a truncated geometric distribution. #[derive(Clone, Debug)] pub struct GeometricRandomNaturalValues { xs: WeightedRandomBools, min: T, max: T, } impl Iterator for GeometricRandomNaturalValues { type Item = T; fn next(&mut self) -> Option { let mut failures = self.min; loop { if self.xs.next().unwrap() { return Some(failures); } // Wrapping to min is equivalent to restarting this function. if failures == self.max { failures = self.min; } else { failures += T::ONE; } } } } fn geometric_random_natural_values_inclusive_range( seed: Seed, min: T, max: T, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert!(min <= max); assert_ne!(um_denominator, 0); let (numerator, denominator) = mean_to_p_with_min(min, um_numerator, um_denominator); GeometricRandomNaturalValues { xs: weighted_random_bools(seed, numerator, numerator.checked_add(denominator).unwrap()), min, max, } } fn get_geometric_random_natural_value_from_inclusive_range( range_generator: &mut VariableRangeGenerator, min: T, max: T, um_numerator: u64, um_denominator: u64, ) -> T { assert!(min <= max); assert_ne!(um_denominator, 0); let (n, denominator) = mean_to_p_with_min(min, um_numerator, um_denominator); let d = n.checked_add(denominator).unwrap(); let mut failures = min; loop { if get_weighted_random_bool(range_generator, n, d) { return failures; } // Wrapping to min is equivalent to restarting this function. if failures == max { failures = min; } else { failures += T::ONE; } } } /// Generates random negative signed integers from a modified geometric distribution. #[derive(Clone, Debug)] pub struct GeometricRandomNegativeSigneds { xs: WeightedRandomBools, abs_min: T, abs_max: T, } impl Iterator for GeometricRandomNegativeSigneds { type Item = T; fn next(&mut self) -> Option { let mut result = self.abs_min; loop { if self.xs.next().unwrap() { return Some(result); } // Wrapping to min is equivalent to restarting this function. if result == self.abs_max { result = self.abs_min; } else { result -= T::ONE; } } } } fn geometric_random_negative_signeds_inclusive_range( seed: Seed, abs_min: T, abs_max: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomNegativeSigneds { assert!(abs_min >= abs_max); assert_ne!(abs_um_denominator, 0); let (numerator, denominator) = mean_to_p_with_min( abs_min.checked_neg().unwrap(), abs_um_numerator, abs_um_denominator, ); GeometricRandomNegativeSigneds { xs: weighted_random_bools(seed, numerator, numerator.checked_add(denominator).unwrap()), abs_min, abs_max, } } fn get_geometric_random_negative_signed_from_inclusive_range( range_generator: &mut VariableRangeGenerator, abs_min: T, abs_max: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> T { assert!(abs_min >= abs_max); assert_ne!(abs_um_denominator, 0); let (n, denominator) = mean_to_p_with_min( abs_min.checked_neg().unwrap(), abs_um_numerator, abs_um_denominator, ); let d = n.checked_add(denominator).unwrap(); let mut result = abs_min; loop { if get_weighted_random_bool(range_generator, n, d) { return result; } // Wrapping to min is equivalent to restarting this function. if result == abs_max { result = abs_min; } else { result -= T::ONE; } } } /// Generates random nonzero signed integers from a modified geometric distribution. #[derive(Clone, Debug)] pub struct GeometricRandomNonzeroSigneds { bs: RandomBools, xs: WeightedRandomBools, min: T, max: T, } impl Iterator for GeometricRandomNonzeroSigneds { type Item = T; fn next(&mut self) -> Option { loop { if self.bs.next().unwrap() { let mut result = T::ONE; loop { if self.xs.next().unwrap() { return Some(result); } else if result == self.max { break; } result += T::ONE; } } else { let mut result = T::NEGATIVE_ONE; loop { if self.xs.next().unwrap() { return Some(result); } else if result == self.min { break; } result -= T::ONE; } } } } } fn geometric_random_nonzero_signeds_inclusive_range( seed: Seed, min: T, max: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomNonzeroSigneds { assert!(min <= max); assert_ne!(abs_um_denominator, 0); let (numerator, denominator) = mean_to_p_with_min(T::ONE, abs_um_numerator, abs_um_denominator); GeometricRandomNonzeroSigneds { bs: random_bools(seed.fork("bs")), xs: weighted_random_bools( seed.fork("xs"), numerator, numerator.checked_add(denominator).unwrap(), ), min, max, } } /// Generates random signed integers from a modified geometric distribution. #[derive(Clone, Debug)] pub struct GeometricRandomSigneds { bs: RandomBools, xs: WeightedRandomBools, min: T, max: T, } impl Iterator for GeometricRandomSigneds { type Item = T; fn next(&mut self) -> Option { loop { let mut result = T::ZERO; if self.bs.next().unwrap() { loop { if self.xs.next().unwrap() { if result == T::ZERO && self.bs.next().unwrap() { break; } return Some(result); } else if result == self.max { break; } result += T::ONE; } } else { loop { if self.xs.next().unwrap() { if result == T::ZERO && self.bs.next().unwrap() { break; } return Some(result); } else if result == self.min { break; } result -= T::ONE; } } } } } fn geometric_random_signed_inclusive_range_helper( seed: Seed, min: T, max: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomSigneds { assert!(min <= max); assert_ne!(abs_um_denominator, 0); let (numerator, denominator) = mean_to_p_with_min(T::ZERO, abs_um_numerator, abs_um_denominator); GeometricRandomSigneds { bs: random_bools(seed.fork("bs")), xs: weighted_random_bools( seed.fork("xs"), numerator, numerator.checked_add(denominator).unwrap(), ), min, max, } } fn get_geometric_random_signed_from_inclusive_range_helper( range_generator: &mut VariableRangeGenerator, min: T, max: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> T { assert!(min <= max); assert_ne!(abs_um_denominator, 0); let (n, denominator) = mean_to_p_with_min(T::ZERO, abs_um_numerator, abs_um_denominator); let d = n.checked_add(denominator).unwrap(); loop { let mut result = T::ZERO; if range_generator.next_bool() { loop { if get_weighted_random_bool(range_generator, n, d) { if result == T::ZERO && range_generator.next_bool() { break; } return result; } else if result == max { break; } result += T::ONE; } } else { loop { if get_weighted_random_bool(range_generator, n, d) { if result == T::ZERO && range_generator.next_bool() { break; } return result; } else if result == min { break; } result -= T::ONE; } } } } /// Generates random negative signed integers in a range from a modified geometric distribution. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum GeometricRandomSignedRange { NonNegative(GeometricRandomNaturalValues), NonPositive(GeometricRandomNegativeSigneds), BothSigns(GeometricRandomSigneds), } impl Iterator for GeometricRandomSignedRange { type Item = T; fn next(&mut self) -> Option { match self { Self::NonNegative(xs) => xs.next(), Self::NonPositive(xs) => xs.next(), Self::BothSigns(xs) => xs.next(), } } } /// Generates random unsigned integers from a truncated geometric distribution. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(0), P(1), P(2), \ldots$ decrease in a geometric sequence; that's /// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is /// truncated, meaning that values above `T::MAX` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than `T::MAX`, which is usually the case, then it is very close to the /// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the /// more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but note /// that the iteration time increases linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[0, 2^W)$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S, /// $$ /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if `um_numerator` or `um_denominator` are zero, or, if after being reduced to lowest /// terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(geometric_random_unsigneds::(EXAMPLE_SEED, 1, 1), 10), /// "[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{1-(1-p)^{2^W}} & \text{if} \\quad 0 \\leq n < 2^W, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = (1-p)^np. /// $$ pub fn geometric_random_unsigneds( seed: Seed, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert_ne!(um_numerator, 0); geometric_random_natural_values_inclusive_range( seed, T::ZERO, T::MAX, um_numerator, um_denominator, ) } /// Generates random positive unsigned integers from a truncated geometric distribution. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(1), P(2), P(3), \ldots$ decrease in a geometric sequence; that's /// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is /// truncated, meaning that values above `T::MAX` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than `T::MAX`, which is usually the case, then it is very close to the /// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the /// more quickly they drop. $m_u$ must be greater than one. It may be arbitrarily high, but note /// that the iteration time increases linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[1, 2^W)$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if `um_denominator` is zero or if `um_numerator <= um_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_positive_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_positive_unsigneds::(EXAMPLE_SEED, 2, 1), /// 10 /// ), /// "[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^{n-1}p}{1-(1-p)^{2^W-1}} & \text{if} \\quad 0 < n < 2^W, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = (1-p)^{n-1}p. /// $$ pub fn geometric_random_positive_unsigneds( seed: Seed, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert!(um_numerator > um_denominator); geometric_random_natural_values_inclusive_range( seed, T::ONE, T::MAX, um_numerator, um_denominator, ) } /// Generates random signed integers from a modified geometric distribution. /// /// This distribution can be derived from a truncated geometric distribution by mirroring it, /// producing a truncated double geometric distribution. Zero is included. /// /// With this distribution, the probability of a value being generated decreases as its absolute /// value increases. The probabilities $P(0), P(\pm 1), P(\pm 2), \ldots$ decrease in a geometric /// sequence; that's where the "geometric" comes from. Values below `T::MIN` or above `T::MAX` are /// never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean /// is what the mean generated value would be if the distribution were not truncated, and were /// restricted to non-negative values. If $m_u$ is significantly lower than `T::MAX`, which is /// usually the case, then it is very close to the actual mean of the distribution restricted to /// positive values. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, /// the more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but /// note that the iteration time increases linearly with `abs_um_numerator + abs_um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[-2^{W-1}, 2^{W-1})$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// Whenever $n \geq 0$ and $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}, /// $$ /// and whenever $n \leq 0$ and $n, n - 1 \in S$, /// $$ /// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}. /// $$ /// /// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `abs_um_numerator + abs_um_denominator`. /// /// # Panics /// Panics if `abs_um_numerator` or `abs_um_denominator` are zero, or, if after being reduced to /// lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(geometric_random_signeds::(EXAMPLE_SEED, 1, 1), 10), /// "[-1, -1, -1, 1, -2, 1, 0, 0, 0, 0, ...]" /// ) /// ``` /// /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^{|n|}p}{((1-p)^{2^{W-1}}-1)(p-2)} & /// \text{if} \\quad -2^{W-1} \leq n < 2^{W-1}, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = \frac{(1-p)^{|n|}p}{2-p}. /// $$ pub fn geometric_random_signeds( seed: Seed, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomSigneds { assert_ne!(abs_um_numerator, 0); geometric_random_signed_inclusive_range_helper( seed, T::MIN, T::MAX, abs_um_numerator, abs_um_denominator, ) } /// Generates random natural (non-negative) signed integers from a truncated geometric distribution. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(0), P(1), P(2), \ldots$ decrease in a geometric sequence; that's /// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is /// truncated, meaning that values above `T::MAX` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than `T::MAX`, which is usually the case, then it is very close to the /// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the /// more quickly they drop. $m_u$ must be greater than zero. It may be arbitrarily high, but note /// that the iteration time increases linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[0, 2^{W-1})$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if `um_numerator` or `um_denominator` are zero, or, if after being reduced to lowest /// terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_natural_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_natural_signeds::(EXAMPLE_SEED, 1, 1), /// 10 /// ), /// "[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p} - 1$, or $p = \frac{1}{m_u + 1}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{1-(1-p)^{2^{W-1}}} & \text{if} \\quad 0 \\leq n < 2^{W-1}, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = \\begin{cases} /// (1-p)^np & \text{if} \\quad n \geq 0, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ pub fn geometric_random_natural_signeds( seed: Seed, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert_ne!(um_numerator, 0); geometric_random_natural_values_inclusive_range( seed, T::ZERO, T::MAX, um_numerator, um_denominator, ) } /// Generates random positive signed integers from a truncated geometric distribution. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(1), P(2), P(3), \ldots$ decrease in a geometric sequence; that's /// where the "geometric" comes from. Unlike a true geometric distribution, this distribution is /// truncated, meaning that values above `T::MAX` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than `T::MAX`, which is usually the case, then it is very close to the /// actual mean. The higher $m_u$ is, the more gently the probabilities drop; the lower it is, the /// more quickly they drop. $m_u$ must be greater than one. It may be arbitrarily high, but note /// that the iteration time increases linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[1, 2^{W-1})$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if `um_denominator` is zero or if `um_numerator <= um_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_positive_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_positive_signeds::(EXAMPLE_SEED, 2, 1), /// 10 /// ), /// "[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^{n-1}p}{1-(1-p)^{2^{W-1}-1}} & \text{if} \\quad 0 < n < 2^{W-1}, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = \\begin{cases} /// (1-p)^{n-1}p & \text{if} \\quad n > 0, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ pub fn geometric_random_positive_signeds( seed: Seed, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { geometric_random_natural_values_inclusive_range( seed, T::ONE, T::MAX, um_numerator, um_denominator, ) } /// Generates random negative signed integers from a modified geometric distribution. /// /// This distribution can be derived from a truncated geometric distribution by negating its domain. /// The distribution is truncated at `T::MIN`. /// /// With this distribution, the probability of a value being generated decreases as its absolute /// value increases. The probabilities $P(-1), P(-2), P(-3), \ldots$ decrease in a geometric /// sequence; that's where the "geometric" comes from. Values below `T::MIN` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean /// is what the mean of the absolute values of the generated values would be if the distribution /// were not truncated. If $m_u$ is significantly lower than `-T::MIN`, which is usually the case, /// then it is very close to the actual mean of the absolute values. The higher $m_u$ is, the more /// gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be /// greater than one. It may be arbitrarily high, but note that the iteration time increases /// linearly with `abs_um_numerator + abs_um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[-2^{W-1}, 0)$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// /// and whenever $n, n - 1 \in S$, /// $$ /// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `abs_um_numerator + abs_um_denominator`. /// /// # Panics /// Panics if `abs_um_denominator` is zero or if `abs_um_numerator <= abs_um_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_negative_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_negative_signeds::(EXAMPLE_SEED, 2, 1), /// 10 /// ), /// "[-2, -1, -1, -4, -5, -5, -2, -1, -1, -2, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^{-n-1}p}{1-(1-p)^{2^{W-1}}} & \text{if} \\quad -2^{W-1} \leq n < 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = \\begin{cases} /// (1-p)^{-n-1}p & \text{if} \\quad n < 0, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ pub fn geometric_random_negative_signeds( seed: Seed, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomNegativeSigneds { assert!(abs_um_numerator > abs_um_denominator); geometric_random_negative_signeds_inclusive_range( seed, T::NEGATIVE_ONE, T::MIN, abs_um_numerator, abs_um_denominator, ) } /// Generates random nonzero signed integers from a modified geometric distribution. /// /// This distribution can be derived from a truncated geometric distribution by mirroring it, /// producing a truncated double geometric distribution. Zero is excluded. /// /// With this distribution, the probability of a value being generated decreases as its absolute /// value increases. The probabilities $P(\pm 1), P(\pm 2), P(\pm 3), \ldots$ decrease in a /// geometric sequence; that's where the "geometric" comes from. Values below `T::MIN` or above /// `T::MAX` are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean /// is what the mean of the absolute values of the generated values would be if the distribution /// were not truncated. If $m_u$ is significantly lower than `T::MAX`, which is usually the case, /// then it is very close to the actual mean of the absolute values. The higher $m_u$ is, the more /// gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be /// greater than one. It may be arbitrarily high, but note that the iteration time increases /// linearly with `abs_um_numerator + abs_um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[-2^{W-1}, 2^{W-1}) \setminus \\{0\\}$, where $W$ is the width of the type. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// $$ /// P(1) = P(-1) /// $$ /// Whenever $n > 0$ and $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u}{m_u - 1}, /// $$ /// and whenever $n < 0$ and $n, n - 1 \in S$, /// $$ /// \frac{P(n)}{P(n-1)} = \frac{m_u}{m_u - 1}. /// $$ /// /// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `abs_um_numerator + abs_um_denominator`. /// /// # Panics /// Panics if `abs_um_denominator` is zero or if `abs_um_numerator <= abs_um_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_nonzero_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_nonzero_signeds::(EXAMPLE_SEED, 2, 1), /// 10 /// ), /// "[-2, -2, -2, 2, -3, 2, -1, -1, -1, 1, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p}$, or $p = \frac{1}{m_u}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^{|n|}p}{(1-p)^{2^{W-1}}(p-2)-2p+2} & /// \text{if} \\quad -2^{W-1} \leq n < 0 \\ \mathrm{or} \\ 0 < n < -2^{W-1}, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// It's also useful to note that /// $$ /// \lim_{W \to \infty} P(n) = \\begin{cases} /// \frac{(1-p)^{|n|}p}{2-2p} & \text{if} \\quad n \neq 0, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ pub fn geometric_random_nonzero_signeds( seed: Seed, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomNonzeroSigneds { assert!(abs_um_numerator > abs_um_denominator); geometric_random_nonzero_signeds_inclusive_range( seed, T::MIN, T::MAX, abs_um_numerator, abs_um_denominator, ) } /// Generates random unsigned integers from a truncated geometric distribution over the half-open /// interval $[a, b)$. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(a), P(a + 1), P(a + 2), \ldots$ decrease in a geometric /// sequence; that's where the "geometric" comes from. Unlike a true geometric distribution, this /// distribution is truncated, meaning that values above $b$ are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than $b$, then it is very close to the actual mean. The higher $m_u$ is, the /// more gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be /// greater than $a$. It may be arbitrarily high, but note that the iteration time increases /// linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[a, b)$. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if $a \geq b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less /// than or equal to $a$, or if they are too large and manipulating them leads to arithmetic /// overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_unsigned_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_unsigned_range::(EXAMPLE_SEED, 1, 7, 3, 1), /// 10 /// ), /// "[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p} + a - 1$, or $p = \frac{1}{m_u - a + 1}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{(1-p)^a-(1-p)^b} & \text{if} \\quad a \\leq n < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ #[inline] pub fn geometric_random_unsigned_range( seed: Seed, a: T, b: T, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); geometric_random_natural_values_inclusive_range( seed, a, b - T::ONE, um_numerator, um_denominator, ) } /// Generates random unsigned integers from a truncated geometric distribution over the closed /// interval $[a, b]$. /// /// With this distribution, the probability of a value being generated decreases as the value /// increases. The probabilities $P(a), P(a + 1), P(a + 2), \ldots$ decrease in a geometric /// sequence; that's where the "geometric" comes from. Unlike a true geometric distribution, this /// distribution is truncated, meaning that values above $b$ are never generated. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `um_numerator / um_denominator`. The unadjusted mean is what /// the mean generated value would be if the distribution were not truncated. If $m_u$ is /// significantly lower than $b$, then it is very close to the actual mean. The higher $m_u$ is, the /// more gently the probabilities drop; the lower it is, the more quickly they drop. $m_u$ must be /// greater than $a$. It may be arbitrarily high, but note that the iteration time increases /// linearly with `um_numerator + um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[a, b]$. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// /// and whenever $n, n + 1 \in S$, /// $$ /// \frac{P(n)}{P(n+1)} = \frac{m_u + 1}{m_u}. /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than /// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 6, 3, 1), /// 10 /// ), /// "[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, ...]" /// ) /// ``` /// /// # Further details /// Geometric distributions are more typically parametrized by a parameter $p$. The relationship /// between $p$ and $m_u$ is $m_u = \frac{1}{p} + a - 1$, or $p = \frac{1}{m_u - a + 1}$. /// /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{(1-p)^a-(1-p)^{b+1}} & \text{if} \\quad a \\leq n \\leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ #[inline] pub fn geometric_random_unsigned_inclusive_range( seed: Seed, a: T, b: T, um_numerator: u64, um_denominator: u64, ) -> GeometricRandomNaturalValues { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); geometric_random_natural_values_inclusive_range(seed, a, b, um_numerator, um_denominator) } /// Generates random signed integers from a modified geometric distribution over the half-open /// interval $[a, b)$. /// /// With this distribution, the probability of a value being generated decreases as its absolute /// value increases. The probabilities $P(n), P(n + \operatorname{sgn}(n)), P(n + /// 2\operatorname{sgn}(n)), \ldots$, where $n, n + \operatorname{sgn}(n), n + /// 2\operatorname{sgn}(n), \ldots \in [a, b) \\setminus \\{0\\}$, decrease in a geometric sequence; /// that's where the "geometric" comes from. /// /// The form of the distribution depends on the range. If $a \geq 0$, the distribution is highest at /// $a$ and is truncated at $b$. If $b \leq 1$, the distribution is reflected: it is highest at $b - /// 1$ and is truncated at $a$. Otherwise, the interval includes both positive and negative values. /// In that case the distribution is doubled: it is highest at zero and is truncated at $a$ and $b$. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean /// is what the mean of the absolute values of the generated values would be if the distribution /// were not truncated. If $m_u$ is significantly lower than $b$, then it is very close to the /// actual mean of the absolute values. The higher $m_u$ is, the more gently the probabilities drop; /// the lower it is, the more quickly they drop. $m_u$ must be greater than $a$. It may be /// arbitrarily high, but note that the iteration time increases linearly with `abs_um_numerator + /// abs_um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[a, b)$. Let $c = \min_{n\in S}|n|$. Geometric distributions are typically parametrized /// by a parameter $p$. The relationship between $p$ and $m_u$ is $m_u = \frac{1}{p} + c - 1$, or $p /// = \frac{1}{m_u - c + 1}$. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// If $0, 1 \in S$, then /// $$ /// \frac{P(0)}{P(1)} = \frac{m_u + 1}{m_u}. /// $$ /// If $-1, 0 \in S$, then /// $$ /// \frac{P(0)}{P(-1)} = \frac{m_u + 1}{m_u}. /// $$ /// and whenever $n, n + \operatorname{sgn}(n) \in S \setminus \\{0\\}$, /// $$ /// \frac{P(n)}{P(n+\operatorname{sgn}(n))} = \frac{m_u + 1}{m_u}. /// $$ /// /// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if $a \geq b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less /// than or equal to $a$, or if they are too large and manipulating them leads to arithmetic /// overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_signed_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_signed_range::(EXAMPLE_SEED, -100, 100, 30, 1), /// 10 /// ), /// "[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, ...]" /// ) /// ``` /// /// # Further details /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{(1-p)^a-(1-p)^b} & \text{if} \\quad 0 \\leq a \\leq n < b, \\\\ /// \frac{(1-p)^{-n}p}{(1-p)^{1-b}-(1-p)^{1-a}} & \text{if} \\quad a \\leq n < b \\leq 1, \\\\ /// \frac{(1-p)^{|n|}p}{2-p-(1-p)^{1-a}-(1-p)^b} & /// \text{if} \\quad a < 0 < 1 < b \\ \mathrm{and} \\ a \\leq n < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ #[inline] pub fn geometric_random_signed_range( seed: Seed, a: T, b: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomSignedRange { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); if a >= T::ZERO { GeometricRandomSignedRange::NonNegative(geometric_random_natural_values_inclusive_range( seed, a, b - T::ONE, abs_um_numerator, abs_um_denominator, )) } else if b <= T::ONE { GeometricRandomSignedRange::NonPositive(geometric_random_negative_signeds_inclusive_range( seed, b - T::ONE, a, abs_um_numerator, abs_um_denominator, )) } else { GeometricRandomSignedRange::BothSigns(geometric_random_signed_inclusive_range_helper( seed, a, b - T::ONE, abs_um_numerator, abs_um_denominator, )) } } /// Generates random signed integers from a modified geometric distribution over the closed interval /// $[a, b]$. /// /// With this distribution, the probability of a value being generated decreases as its absolute /// value increases. The probabilities $P(n), P(n + \operatorname{sgn}(n)), P(n + /// 2\operatorname{sgn}(n)), \ldots$, where $n, n + \operatorname{sgn}(n), n + /// 2\operatorname{sgn}(n), \ldots \in [a, b] \\setminus \\{0\\}$, decrease in a geometric sequence; /// that's where the "geometric" comes from. /// /// The form of the distribution depends on the range. If $a \geq 0$, the distribution is highest at /// $a$ and is truncated at $b$. If $b \leq 0$, the distribution is reflected: it is highest at $b$ /// and is truncated at $a$. Otherwise, the interval includes both positive and negative values. In /// that case the distribution is doubled: it is highest at zero and is truncated at $a$ and $b$. /// /// The probabilities can drop more quickly or more slowly depending on a parameter $m_u$, called /// the unadjusted mean. It is equal to `abs_um_numerator / abs_um_denominator`. The unadjusted mean /// is what the mean of the absolute values of the generated values would be if the distribution /// were not truncated. If $m_u$ is significantly lower than $b$, then it is very close to the /// actual mean of the absolute values. The higher $m_u$ is, the more gently the probabilities drop; /// the lower it is, the more quickly they drop. $m_u$ must be greater than $a$. It may be /// arbitrarily high, but note that the iteration time increases linearly with `abs_um_numerator + /// abs_um_denominator`. /// /// Here is a more precise characterization of this distribution. Let its support $S \subset \Z$ /// equal $[a, b]$. Let $c = \min_{n\in S}|n|$. Geometric distributions are typically parametrized /// by a parameter $p$. The relationship between $p$ and $m_u$ is $m_u = \frac{1}{p} + c - 1$, or $p /// = \frac{1}{m_u - c + 1}$. Then we have /// $$ /// P(n) \neq 0 \leftrightarrow n \in S /// $$ /// If $0, 1 \in S$, then /// $$ /// \frac{P(0)}{P(1)} = \frac{m_u + 1}{m_u}. /// $$ /// If $-1, 0 \in S$, then /// $$ /// \frac{P(0)}{P(-1)} = \frac{m_u + 1}{m_u}. /// $$ /// and whenever $n, n + \operatorname{sgn}(n) \in S \setminus \\{0\\}$, /// $$ /// \frac{P(n)}{P(n+\operatorname{sgn}(n))} = \frac{m_u + 1}{m_u}. /// $$ /// /// As a corollary, $P(n) = P(-n)$ whenever $n, -n \in S$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than /// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::geometric::geometric_random_signed_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// geometric_random_signed_inclusive_range::(EXAMPLE_SEED, -100, 99, 30, 1), /// 10 /// ), /// "[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, ...]" /// ) /// ``` /// /// # Further details /// The probability mass function of this distribution is /// $$ /// P(n) = \\begin{cases} /// \frac{(1-p)^np}{(1-p)^a-(1-p)^{b+1}} & \text{if} \\quad 0 \\leq a \\leq n \\leq b, \\\\ /// \frac{(1-p)^{-n}p}{(1-p)^{-b}-(1-p)^{1-a}} /// & \text{if} \\quad a \\leq n \\leq b \\leq 0, \\\\ /// \frac{(1-p)^{|n|}p}{2-p-(1-p)^{1-a}-(1-p)^{b+1}} /// & \text{if} \\quad a < 0 < b \\ \mathrm{and} \\ a \\leq n \\leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ #[inline] pub fn geometric_random_signed_inclusive_range( seed: Seed, a: T, b: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> GeometricRandomSignedRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= T::ZERO { GeometricRandomSignedRange::NonNegative(geometric_random_natural_values_inclusive_range( seed, a, b, abs_um_numerator, abs_um_denominator, )) } else if b <= T::ZERO { GeometricRandomSignedRange::NonPositive(geometric_random_negative_signeds_inclusive_range( seed, b, a, abs_um_numerator, abs_um_denominator, )) } else { GeometricRandomSignedRange::BothSigns(geometric_random_signed_inclusive_range_helper( seed, a, b, abs_um_numerator, abs_um_denominator, )) } } /// Generates a random signed integers from a modified geometric distribution over the closed /// interval $[a, b]$. /// /// See [`geometric_random_signed_inclusive_range`] for a detailed description of the distribution. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `um_numerator + um_denominator`. /// /// # Panics /// Panics if $a > b$, if `um_numerator` or `um_denominator` are zero, if their ratio is less than /// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::num::random::geometric::get_geometric_random_signed_from_inclusive_range; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// get_geometric_random_signed_from_inclusive_range::( /// &mut VariableRangeGenerator::new(EXAMPLE_SEED), /// -100, /// 99, /// 30, /// 1 /// ), /// 8 /// ) /// ``` pub fn get_geometric_random_signed_from_inclusive_range( range_generator: &mut VariableRangeGenerator, a: T, b: T, abs_um_numerator: u64, abs_um_denominator: u64, ) -> T { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= T::ZERO { get_geometric_random_natural_value_from_inclusive_range( range_generator, a, b, abs_um_numerator, abs_um_denominator, ) } else if b <= T::ZERO { get_geometric_random_negative_signed_from_inclusive_range( range_generator, b, a, abs_um_numerator, abs_um_denominator, ) } else { get_geometric_random_signed_from_inclusive_range_helper( range_generator, a, b, abs_um_numerator, abs_um_denominator, ) } } ================================================ FILE: malachite-base/src/num/random/mod.rs ================================================ // Copyright © 2026 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 crate::bools::random::{RandomBools, random_bools}; use crate::iterators::{ NonzeroValues, WithSpecialValue, WithSpecialValues, nonzero_values, with_special_value, with_special_values, }; use crate::num::arithmetic::traits::{Parity, PowerOf2, ShrRound}; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::float::NiceFloat; use crate::num::iterators::{IteratorToBitChunks, iterator_to_bit_chunks}; use crate::num::logic::traits::{BitAccess, SignificantBits}; use crate::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, geometric_random_signed_inclusive_range, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use crate::random::{EXAMPLE_SEED, Seed}; use crate::rounding_modes::RoundingMode::*; use crate::vecs::{RandomValuesFromVec, random_values_from_vec}; use itertools::Itertools; use rand::Rng; use rand_chacha::ChaCha20Rng; use std::collections::HashMap; use std::convert::identity; use std::fmt::Debug; use std::marker::PhantomData; // Uniformly generates random primitive integers. #[doc(hidden)] #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ThriftyRandomState { x: u32, bits_left: u64, } #[doc(hidden)] pub trait HasRandomPrimitiveInts { type State: Clone + Debug; fn new_state() -> Self::State; fn get_random(rng: &mut ChaCha20Rng, state: &mut Self::State) -> Self; } macro_rules! impl_trivial_random_primitive_ints { ($t: ident) => { impl HasRandomPrimitiveInts for $t { type State = (); #[inline] fn new_state() -> () {} #[inline] fn get_random(rng: &mut ChaCha20Rng, _state: &mut ()) -> $t { rng.random() } } }; } impl_trivial_random_primitive_ints!(u32); impl_trivial_random_primitive_ints!(u64); impl_trivial_random_primitive_ints!(u128); impl_trivial_random_primitive_ints!(i32); impl_trivial_random_primitive_ints!(i64); impl_trivial_random_primitive_ints!(i128); impl HasRandomPrimitiveInts for usize { type State = (); #[inline] fn new_state() {} #[inline] fn get_random(rng: &mut ChaCha20Rng, _state: &mut ()) -> Self { if USIZE_IS_U32 { let x: u32 = rng.random(); x as Self } else { let x: u64 = rng.random(); x as Self } } } impl HasRandomPrimitiveInts for isize { type State = (); #[inline] fn new_state() {} #[inline] fn get_random(rng: &mut ChaCha20Rng, _state: &mut ()) -> Self { if USIZE_IS_U32 { let x: i32 = rng.random(); x as Self } else { let x: i64 = rng.random(); x as Self } } } fn get_random(rng: &mut ChaCha20Rng, state: &mut ThriftyRandomState) -> T { if state.bits_left == 0 { state.x = rng.random(); state.bits_left = u32::WIDTH - T::WIDTH; } else { state.x >>= T::WIDTH; state.bits_left -= T::WIDTH; } T::wrapping_from(state.x) } macro_rules! impl_thrifty_random_primitive_ints { ($t: ident) => { impl HasRandomPrimitiveInts for $t { type State = ThriftyRandomState; #[inline] fn new_state() -> ThriftyRandomState { ThriftyRandomState { x: 0, bits_left: 0 } } #[inline] fn get_random(rng: &mut ChaCha20Rng, state: &mut ThriftyRandomState) -> $t { get_random(rng, state) } } }; } impl_thrifty_random_primitive_ints!(u8); impl_thrifty_random_primitive_ints!(u16); impl_thrifty_random_primitive_ints!(i8); impl_thrifty_random_primitive_ints!(i16); /// Uniformly generates random primitive integers. /// /// This `struct` is created by [`random_primitive_ints`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomPrimitiveInts { pub(crate) rng: ChaCha20Rng, pub(crate) state: T::State, } impl Iterator for RandomPrimitiveInts { type Item = T; #[inline] fn next(&mut self) -> Option { Some(T::get_random(&mut self.rng, &mut self.state)) } } /// Uniformly generates random unsigned integers less than a positive limit. /// /// This `enum` is created by [`random_unsigneds_less_than`]; see its documentation for more. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum RandomUnsignedsLessThan { One, AtLeastTwo(RandomUnsignedBitChunks, T), } impl Iterator for RandomUnsignedsLessThan { type Item = T; #[inline] fn next(&mut self) -> Option { match self { Self::One => Some(T::ZERO), Self::AtLeastTwo(xs, limit) => loop { let x = xs.next(); if x.unwrap() < *limit { return x; } }, } } } /// Uniformly generates random unsigned integers in the half-open interval $[a, b)$. /// /// This `struct` is created by [`random_unsigned_range`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomUnsignedRange { pub(crate) xs: RandomUnsignedsLessThan, pub(crate) a: T, } impl Iterator for RandomUnsignedRange { type Item = T; #[inline] fn next(&mut self) -> Option { self.xs.next().map(|x| x + self.a) } } /// Uniformly generates random unsigned integers in the closed interval $[a, b]$. /// /// This `struct` is created by [`random_unsigned_inclusive_range`]; see its documentation for more. #[derive(Clone, Debug)] pub enum RandomUnsignedInclusiveRange { NotAll(RandomUnsignedsLessThan, T), All(RandomPrimitiveInts), } impl Iterator for RandomUnsignedInclusiveRange { type Item = T; #[inline] fn next(&mut self) -> Option { match self { Self::NotAll(xs, a) => xs.next().map(|x| x + *a), Self::All(xs) => xs.next(), } } } #[doc(hidden)] pub trait HasRandomSignedRange: Sized { type UnsignedValue: PrimitiveUnsigned; fn new_unsigned_range(seed: Seed, a: Self, b: Self) -> RandomUnsignedRange; fn new_unsigned_inclusive_range( seed: Seed, a: Self, b: Self, ) -> RandomUnsignedInclusiveRange; fn from_unsigned_value(x: Self::UnsignedValue) -> Self; } macro_rules! impl_has_random_signed_range { ($u: ident, $s: ident) => { impl HasRandomSignedRange for $s { type UnsignedValue = $u; fn new_unsigned_range(seed: Seed, mut a: $s, mut b: $s) -> RandomUnsignedRange<$u> { a.flip_bit($u::WIDTH - 1); b.flip_bit($u::WIDTH - 1); random_unsigned_range(seed, $u::wrapping_from(a), $u::wrapping_from(b)) } fn new_unsigned_inclusive_range( seed: Seed, mut a: $s, mut b: $s, ) -> RandomUnsignedInclusiveRange<$u> { a.flip_bit($u::WIDTH - 1); b.flip_bit($u::WIDTH - 1); random_unsigned_inclusive_range(seed, $u::wrapping_from(a), $u::wrapping_from(b)) } fn from_unsigned_value(mut u: $u) -> $s { u.flip_bit($u::WIDTH - 1); $s::wrapping_from(u) } } }; } apply_to_unsigned_signed_pairs!(impl_has_random_signed_range); /// Uniformly generates random signed integers in the half-open interval $[a, b)$. /// /// This `struct` is created by [`random_signed_range`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomSignedRange { pub(crate) xs: RandomUnsignedRange, } impl Iterator for RandomSignedRange { type Item = T; fn next(&mut self) -> Option { self.xs.next().map(T::from_unsigned_value) } } /// Uniformly generates random signed integers in the closed interval $[a, b]$. /// /// This `struct` is created by [`random_signed_inclusive_range`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomSignedInclusiveRange { pub(crate) xs: RandomUnsignedInclusiveRange, } impl Iterator for RandomSignedInclusiveRange { type Item = T; fn next(&mut self) -> Option { self.xs.next().map(T::from_unsigned_value) } } /// Uniformly generates unsigned integers with up to some number of bits. /// /// This `struct` is created by [`random_unsigned_bit_chunks`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomUnsignedBitChunks { xs: IteratorToBitChunks, T, T>, } impl Iterator for RandomUnsignedBitChunks { type Item = T; fn next(&mut self) -> Option { self.xs.next_with_wrapping(identity).map(Option::unwrap) } } #[doc(hidden)] pub trait RandomSignedChunkable: Sized { type AbsoluteChunks: Clone + Debug; fn new_absolute_chunks(seed: Seed, chunk_size: u64) -> Self::AbsoluteChunks; fn next_chunk(xs: &mut Self::AbsoluteChunks) -> Option; } macro_rules! impl_random_signed_chunkable { ($u: ident, $s: ident) => { impl RandomSignedChunkable for $s { type AbsoluteChunks = RandomUnsignedBitChunks<$u>; fn new_absolute_chunks(seed: Seed, chunk_size: u64) -> RandomUnsignedBitChunks<$u> { random_unsigned_bit_chunks(seed, chunk_size) } fn next_chunk(xs: &mut Self::AbsoluteChunks) -> Option<$s> { xs.next().map(WrappingFrom::wrapping_from) } } }; } apply_to_unsigned_signed_pairs!(impl_random_signed_chunkable); /// Uniformly generates signed integers with up to some number of bits. /// /// This `struct` is created by [`random_signed_bit_chunks`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomSignedBitChunks { pub(crate) xs: T::AbsoluteChunks, } impl Iterator for RandomSignedBitChunks { type Item = T; fn next(&mut self) -> Option { T::next_chunk(&mut self.xs) } } /// Modifies the output values of an iterator by setting their highest bit. #[derive(Clone, Debug)] pub struct RandomHighestBitSetValues where I::Item: PrimitiveInt, { pub(crate) xs: I, pub(crate) mask: I::Item, } impl Iterator for RandomHighestBitSetValues where I::Item: PrimitiveInt, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { self.xs.next().map(|x| x | self.mask) } } /// Uniformly generates random primitive integers. /// /// $P(x) = 2^{-W}$, where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_primitive_ints::(EXAMPLE_SEED), 10), /// "[113, 239, 69, 108, 228, 210, 168, 161, 87, 32, ...]" /// ) /// ``` #[inline] pub fn random_primitive_ints(seed: Seed) -> RandomPrimitiveInts { RandomPrimitiveInts { rng: seed.get_rng(), state: T::new_state(), } } /// Uniformly generates random positive unsigned integers. /// /// $$ /// P(x) = \\begin{cases} /// \\frac{1}{2^W-1} & \text{if} \\quad x > 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_positive_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_positive_unsigneds::(EXAMPLE_SEED), 10), /// "[113, 239, 69, 108, 228, 210, 168, 161, 87, 32, ...]" /// ) /// ``` #[inline] pub fn random_positive_unsigneds( seed: Seed, ) -> NonzeroValues> { nonzero_values(random_primitive_ints(seed)) } /// Uniformly generates random positive signed integers. /// /// $$ /// P(x) = \\begin{cases} /// \\frac{1}{2^{W-1}-1} & \text{if} \\quad x > 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_positive_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_positive_signeds::(EXAMPLE_SEED), 10), /// "[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, ...]" /// ) /// ``` #[inline] pub fn random_positive_signeds( seed: Seed, ) -> NonzeroValues> { nonzero_values(random_natural_signeds(seed)) } /// Uniformly generates random negative signed integers. /// /// $$ /// P(x) = \\begin{cases} /// 2^{1-W} & \text{if} \\quad x < 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_negative_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_negative_signeds::(EXAMPLE_SEED), 10), /// "[-15, -34, -105, -30, -58, -36, -76, -44, -95, -81, ...]" /// ) /// ``` #[inline] pub fn random_negative_signeds( seed: Seed, ) -> RandomHighestBitSetValues> { RandomHighestBitSetValues { xs: random_signed_bit_chunks(seed, T::WIDTH - 1), mask: T::MIN, } } /// Uniformly generates random natural (non-negative) signed integers. /// /// $$ /// P(x) = \\begin{cases} /// 2^{1-W} & \text{if} \\quad x \geq 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_natural_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_natural_signeds::(EXAMPLE_SEED), 10), /// "[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, ...]" /// ) /// ``` #[inline] pub fn random_natural_signeds(seed: Seed) -> RandomSignedBitChunks { random_signed_bit_chunks(seed, T::WIDTH - 1) } /// Uniformly generates random nonzero signed integers. /// /// $$ /// P(x) = \\begin{cases} /// \\frac{1}{2^W-1} & \text{if} \\quad x \\neq 0, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_nonzero_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_nonzero_signeds::(EXAMPLE_SEED), 10), /// "[113, -17, 69, 108, -28, -46, -88, -95, 87, 32, ...]" /// ) /// ``` #[inline] pub fn random_nonzero_signeds( seed: Seed, ) -> NonzeroValues> { nonzero_values(random_primitive_ints(seed)) } /// Uniformly generates random unsigned integers less than a positive limit. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{\\ell} & \text{if} \\quad x < \\ell, \\\\ /// 0 & \\text{otherwise,} /// \\end{cases} /// $$ /// where $\ell$ is `limit`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `limit` is 0. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_unsigneds_less_than; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_unsigneds_less_than::(EXAMPLE_SEED, 10), 10), /// "[1, 7, 5, 4, 6, 4, 2, 8, 1, 7, ...]" /// ) /// ``` pub fn random_unsigneds_less_than( seed: Seed, limit: T, ) -> RandomUnsignedsLessThan { if limit == T::ZERO { panic!("limit cannot be 0."); } else if limit == T::ONE { RandomUnsignedsLessThan::One } else { RandomUnsignedsLessThan::AtLeastTwo( random_unsigned_bit_chunks(seed, limit.ceiling_log_base_2()), limit, ) } } /// Uniformly generates random unsigned integers in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. This function cannot create a range that includes `T::MAX`; for that, /// use [`random_unsigned_inclusive_range`]. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a} & \text{if} \\quad a \leq x < b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_unsigned_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_unsigned_range::(EXAMPLE_SEED, 10, 20), 10), /// "[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, ...]" /// ) /// ``` pub fn random_unsigned_range( seed: Seed, a: T, b: T, ) -> RandomUnsignedRange { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); RandomUnsignedRange { xs: random_unsigneds_less_than(seed, b - a), a, } } /// Uniformly generates random unsigned integers in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a+1} & \text{if} \\quad a \leq x \leq b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 10, 19), /// 10 /// ), /// "[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, ...]" /// ) /// ``` pub fn random_unsigned_inclusive_range( seed: Seed, a: T, b: T, ) -> RandomUnsignedInclusiveRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a == T::ZERO && b == T::MAX { RandomUnsignedInclusiveRange::All(random_primitive_ints(seed)) } else { RandomUnsignedInclusiveRange::NotAll(random_unsigneds_less_than(seed, b - a + T::ONE), a) } } /// Uniformly generates random signed integers in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. This function cannot create a range that includes `T::MAX`; for that, /// use [`random_signed_inclusive_range`]. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a} & \text{if} \\quad a \leq x < b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_signed_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_signed_range::(EXAMPLE_SEED, -100, 100), 10), /// "[13, -31, 8, 68, 61, -13, -68, 10, -17, 88, ...]" /// ) /// ``` #[inline] pub fn random_signed_range(seed: Seed, a: T, b: T) -> RandomSignedRange { assert!(a < b, "a must be less than b. a: {a}, b: {b}"); RandomSignedRange { xs: T::new_unsigned_range(seed, a, b), } } /// Uniformly generates random signed integers in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a+1} & \text{if} \\quad a \leq x \leq b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_signed_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_signed_inclusive_range::(EXAMPLE_SEED, -100, 99), /// 10 /// ), /// "[13, -31, 8, 68, 61, -13, -68, 10, -17, 88, ...]" /// ) /// ``` #[inline] pub fn random_signed_inclusive_range( seed: Seed, a: T, b: T, ) -> RandomSignedInclusiveRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); RandomSignedInclusiveRange { xs: T::new_unsigned_inclusive_range(seed, a, b), } } /// Uniformly generates unsigned integers containing some maximum number of bits. /// /// $$ /// P(x) = \\begin{cases} /// 2^{-c} & \text{if} \\quad 0 \\leq x < 2^c, \\\\ /// 0 & \\text{otherwise,} /// \\end{cases} /// $$ /// where $c$ is `chunk_size`. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `chunk_size` is zero or greater than the width of the type. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_unsigned_bit_chunks; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_unsigned_bit_chunks::(EXAMPLE_SEED, 3), 10), /// "[1, 6, 5, 7, 6, 3, 1, 2, 4, 5, ...]" /// ) /// ``` pub fn random_unsigned_bit_chunks( seed: Seed, chunk_size: u64, ) -> RandomUnsignedBitChunks { RandomUnsignedBitChunks { xs: iterator_to_bit_chunks(random_primitive_ints(seed), T::WIDTH, chunk_size), } } /// Uniformly generates signed integers containing some maximum number of bits. /// /// The generated values will all be non-negative unless `chunk_size` is equal to the width of the /// type. /// /// $$ /// P(x) = \\begin{cases} /// 2^{-c} & \text{if} \\quad c = W \\ \\text{or} /// \\ (c < W \\ \\text{and} \\ 0 \\leq x < 2^c), \\\\ /// 0 & \\text{otherwise,} /// \\end{cases} /// $$ /// where $c$ is `chunk_size` and $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `chunk_size` is zero or greater than the width of the type. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_signed_bit_chunks; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_signed_bit_chunks::(EXAMPLE_SEED, 3), 10), /// "[1, 6, 5, 7, 6, 3, 1, 2, 4, 5, ...]" /// ) /// ``` pub fn random_signed_bit_chunks( seed: Seed, chunk_size: u64, ) -> RandomSignedBitChunks { assert!(chunk_size <= T::WIDTH); RandomSignedBitChunks { xs: T::new_absolute_chunks(seed, chunk_size), } } /// Uniformly generates unsigned integers whose highest bit is set. /// /// $$ /// P(x) = \\begin{cases} /// 2^{1-W} & \text{if} \\quad 2^{W-1} \\leq x < 2^W ,\\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $W$ is the width of the type. /// /// The output length is infinite. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_highest_bit_set_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string(random_highest_bit_set_unsigneds::(EXAMPLE_SEED), 10), /// "[241, 222, 151, 226, 198, 220, 180, 212, 161, 175, ...]" /// ) /// ``` #[inline] pub fn random_highest_bit_set_unsigneds( seed: Seed, ) -> RandomHighestBitSetValues> { RandomHighestBitSetValues { xs: random_unsigned_bit_chunks(seed, T::WIDTH - 1), mask: T::power_of_2(T::WIDTH - 1), } } /// Generates random primitive floats in the half-open interval $[a, b)$. /// /// This `struct` is created by [`random_primitive_float_range`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomPrimitiveFloatRange { phantom: PhantomData<*const T>, xs: RandomUnsignedRange, } impl Iterator for RandomPrimitiveFloatRange { type Item = T; fn next(&mut self) -> Option { self.xs.next().map(T::from_ordered_representation) } } /// Generates random primitive floats in the closed interval $[a, b]$. /// /// This `struct` is created by [`random_primitive_float_inclusive_range`]; see its documentation /// for more. #[derive(Clone, Debug)] pub struct RandomPrimitiveFloatInclusiveRange { phantom: PhantomData<*const T>, xs: RandomUnsignedInclusiveRange, } impl Iterator for RandomPrimitiveFloatInclusiveRange { type Item = T; fn next(&mut self) -> Option { self.xs.next().map(T::from_ordered_representation) } } /// Generates random primitive floats in the half-open interval $[a, b)$. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, if the range /// is $[0, 2)$, a float in $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since /// these subranges contain an equal number of floats. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// `NaN` is never generated. /// /// $a$ must be less than $b$. This function cannot create a range that includes `T::INFINITY`; for /// that, use [`random_primitive_float_inclusive_range`]. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_primitive_float_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_primitive_float_range::(EXAMPLE_SEED, -0.1, 0.1).map(NiceFloat), /// 10 /// ), /// "[5.664681e-11, 1.2492925e-35, 2.3242339e-29, 4.699183e-7, -2.8244436e-36, -2.264039e-37, \ /// -0.0000017299129, 1.40616e-23, 2.7418007e-27, 1.5418819e-16, ...]" /// ); /// ``` #[inline] pub fn random_primitive_float_range( seed: Seed, a: T, b: T, ) -> RandomPrimitiveFloatRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!( NiceFloat(a) < NiceFloat(b), "a must be less than b. a: {}, b: {}", NiceFloat(a), NiceFloat(b) ); RandomPrimitiveFloatRange { phantom: PhantomData, xs: random_unsigned_range( seed, a.to_ordered_representation(), b.to_ordered_representation(), ), } } /// Generates random primitive floats in the closed interval $[a, b]$. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, if the range /// is $[0, 2]$, a float in $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since /// these subranges contain an equal number of floats. /// /// Positive and negative zero are treated as two distinct values, with negative zero being smaller /// than zero. /// /// $a$ must be less than or equal to $b$. /// /// `NaN` is never generated. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_primitive_float_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_primitive_float_inclusive_range::(EXAMPLE_SEED, -0.1, 0.1).map(NiceFloat), /// 10 /// ), /// "[5.664681e-11, 1.2492925e-35, 2.3242339e-29, 4.699183e-7, -2.8244436e-36, -2.264039e-37, \ /// -0.0000017299129, 1.40616e-23, 2.7418007e-27, 1.5418819e-16, ...]" /// ); /// ``` #[inline] pub fn random_primitive_float_inclusive_range( seed: Seed, a: T, b: T, ) -> RandomPrimitiveFloatInclusiveRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!( NiceFloat(a) <= NiceFloat(b), "a must be less than or equal to b. a: {}, b: {}", NiceFloat(a), NiceFloat(b) ); RandomPrimitiveFloatInclusiveRange { phantom: PhantomData, xs: random_unsigned_inclusive_range( seed, a.to_ordered_representation(), b.to_ordered_representation(), ), } } /// Generates random finite positive primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since these subranges contain an /// equal number of floats. /// /// Positive zero is generated; negative zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_positive_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_positive_finite_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[9.5715654e26, 209.6476, 386935780.0, 7.965817e30, 0.00021030706, 0.0027270128, \ /// 3.4398167e-34, 2.3397111e14, 44567765000.0, 2.3479653e21, ...]" /// ); /// ``` #[inline] pub fn random_positive_finite_primitive_floats( seed: Seed, ) -> RandomPrimitiveFloatInclusiveRange { random_primitive_float_inclusive_range(seed, T::MIN_POSITIVE_SUBNORMAL, T::MAX_FINITE) } /// Generates random finite negative primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $(-1/2, 1/4]$ is as likely to be chosen as a float in $(-2, -1]$, since these subranges contain /// an equal number of floats. /// /// Negative zero is generated; positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_negative_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_negative_finite_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484663e-27, -0.010641626, -5.8060583e-9, -2.8182442e-31, -10462.532, -821.12994, \ /// -6.303163e33, -9.50376e-15, -4.9561126e-11, -8.565163e-22, ...]" /// ); /// ``` #[inline] pub fn random_negative_finite_primitive_floats( seed: Seed, ) -> RandomPrimitiveFloatInclusiveRange { random_primitive_float_inclusive_range(seed, -T::MAX_FINITE, -T::MIN_POSITIVE_SUBNORMAL) } /// Generates random finite nonzero primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since these subranges contain an /// equal number of floats. /// /// Neither positive nor negative zero are generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_nonzero_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_nonzero_finite_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484663e-27, 2.287989e-18, -2.0729893e-12, 3.360012e28, -9.021723e-32, 3564911.2, \ /// -0.0000133769445, -1.8855448e18, 8.2494555e-29, 2.2178014e-38, ...]" /// ); /// ``` #[inline] pub fn random_nonzero_finite_primitive_floats( seed: Seed, ) -> NonzeroValues> { nonzero_values(random_finite_primitive_floats(seed)) } /// Generates random finite primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since these subranges contain an /// equal number of floats. /// /// Positive zero and negative zero are both generated. `NaN` is not. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_finite_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484663e-27, 2.287989e-18, -2.0729893e-12, 3.360012e28, -9.021723e-32, 3564911.2, \ /// -0.0000133769445, -1.8855448e18, 8.2494555e-29, 2.2178014e-38, ...]" /// ); /// ``` #[inline] pub fn random_finite_primitive_floats( seed: Seed, ) -> RandomPrimitiveFloatInclusiveRange { random_primitive_float_inclusive_range(seed, -T::MAX_FINITE, T::MAX_FINITE) } /// Generates random positive primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since these subranges contain an /// equal number of floats. /// /// Positive zero is generated; negative zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_positive_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_positive_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[9.5715654e26, 209.6476, 386935780.0, 7.965817e30, 0.00021030706, 0.0027270128, \ /// 3.4398167e-34, 2.3397111e14, 44567765000.0, 2.3479653e21, ...]" /// ); /// ``` #[inline] pub fn random_positive_primitive_floats( seed: Seed, ) -> RandomPrimitiveFloatInclusiveRange { random_primitive_float_inclusive_range(seed, T::MIN_POSITIVE_SUBNORMAL, T::INFINITY) } /// Generates random negative primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $(-1/2, -1/4]$ is as likely to be chosen as a float in $(-2, -1]$, since these subranges contain /// an equal number of floats. /// /// Negative zero is generated; positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_negative_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_negative_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484665e-27, -0.010641627, -5.8060587e-9, -2.8182444e-31, -10462.533, -821.13, \ /// -6.3031636e33, -9.5037605e-15, -4.956113e-11, -8.565164e-22, ...]" /// ); /// ``` #[inline] pub fn random_negative_primitive_floats( seed: Seed, ) -> RandomPrimitiveFloatInclusiveRange { random_primitive_float_inclusive_range(seed, T::NEGATIVE_INFINITY, -T::MIN_POSITIVE_SUBNORMAL) } /// Generates random nonzero primitive floats. /// /// Every float within the range has an equal probability of being chosen. This does not mean that /// the distribution approximates a uniform distribution over the reals. For example, a float in /// $[1/4, 1/2)$ is as likely to be chosen as a float in $[1, 2)$, since these subranges contain an /// equal number of floats. /// /// Neither positive nor negative zero are generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_nonzero_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_nonzero_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, \ /// -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, ...]", /// ); /// ``` #[inline] pub fn random_nonzero_primitive_floats( seed: Seed, ) -> NonzeroValues> { nonzero_values(random_primitive_floats(seed)) } /// Generates random primitive floats. /// /// This `struct` is created by [`random_primitive_floats`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomPrimitiveFloats { phantom: PhantomData<*const T>, pub(crate) xs: RandomUnsignedInclusiveRange, nan: u64, } impl Iterator for RandomPrimitiveFloats { type Item = T; fn next(&mut self) -> Option { self.xs.next().map(|x| { if x == self.nan { T::NAN } else { T::from_ordered_representation(x) } }) } } /// Generates random finite primitive floats. /// /// Every float has an equal probability of being chosen. This does not mean that the distribution /// approximates a uniform distribution over the reals. For example, a float in $[1/4, 1/2)$ is as /// likely to be chosen as a float in $[1, 2)$, since these subranges contain an equal number of /// floats. /// /// Positive zero, negative zero, and `NaN` are all generated. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::random_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// random_primitive_floats::(EXAMPLE_SEED).map(NiceFloat), /// 10 /// ), /// "[-2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, \ /// -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, ...]" /// ); /// ``` #[inline] pub fn random_primitive_floats(seed: Seed) -> RandomPrimitiveFloats { let nan = T::INFINITY.to_ordered_representation() + 1; RandomPrimitiveFloats { phantom: PhantomData, xs: random_unsigned_inclusive_range(seed, 0, nan), nan, } } /// Generates positive finite primitive floats. /// /// This `struct` is created by [`special_random_positive_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct SpecialRandomPositiveFiniteFloats { seed: Seed, sci_exponents: GeometricRandomSignedRange, range_map: HashMap>, ranges: VariableRangeGenerator, mean_precision_n: u64, mean_precision_d: u64, phantom: PhantomData<*const T>, } impl Iterator for SpecialRandomPositiveFiniteFloats { type Item = T; fn next(&mut self) -> Option { let sci_exponent = self.sci_exponents.next().unwrap(); let mean_precision_n = self.mean_precision_n; let mean_precision_d = self.mean_precision_d; let seed = self.seed; let precisions = self.range_map.entry(sci_exponent).or_insert_with(move || { geometric_random_unsigned_inclusive_range( seed.fork(&sci_exponent.to_string()), 1, T::max_precision_for_sci_exponent(sci_exponent), mean_precision_n, mean_precision_d, ) }); let precision = precisions.next().unwrap(); let mantissa = if precision == 1 { 1 } else { // e.g. if precision is 4, generate odd values from 1001 through 1111, inclusive let x = self.ranges.next_in_range( u64::power_of_2(precision - 2), u64::power_of_2(precision - 1), ); (x << 1) | 1 }; T::from_integer_mantissa_and_exponent( mantissa, sci_exponent - i64::wrapping_from(precision) + 1, ) } } /// Generates positive finite primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Positive zero is generated; negative zero is not. `NaN` is not generated either. TODO: don't /// generate any zeros! /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_positive_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_positive_finite_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1) /// .map(NiceFloat), /// 20 /// ), /// "[0.80126953, 0.0000013709068, 0.015609741, 0.98552704, 65536.0, 0.008257866, \ /// 0.017333984, 2.25, 7.7089844, 0.00004425831, 0.40625, 24576.0, 37249.0, 1.1991882, \ /// 32.085938, 0.4375, 0.0012359619, 1536.0, 0.22912993, 0.0015716553, ...]" /// ); /// ``` pub fn special_random_positive_finite_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> SpecialRandomPositiveFiniteFloats { assert_ne!(mean_precision_denominator, 0); assert!(mean_precision_numerator > mean_precision_denominator); SpecialRandomPositiveFiniteFloats { seed: seed.fork("precisions"), sci_exponents: geometric_random_signed_inclusive_range( EXAMPLE_SEED.fork("exponents"), T::MIN_EXPONENT, T::MAX_EXPONENT, mean_sci_exponent_numerator, mean_sci_exponent_denominator, ), range_map: HashMap::new(), ranges: VariableRangeGenerator::new(seed.fork("ranges")), mean_precision_n: mean_precision_numerator, mean_precision_d: mean_precision_denominator, phantom: PhantomData, } } /// Generates negative finite primitive floats. /// /// This `struct` is created by [`special_random_negative_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct SpecialRandomNegativeFiniteFloats( SpecialRandomPositiveFiniteFloats, ); impl Iterator for SpecialRandomNegativeFiniteFloats { type Item = T; #[inline] fn next(&mut self) -> Option { self.0.next().map(|f| -f) } } /// Generates negative finite primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Negative zero is generated; positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_negative_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_negative_finite_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1) /// .map(NiceFloat), /// 20 /// ), /// "[-0.80126953, -0.0000013709068, -0.015609741, -0.98552704, -65536.0, -0.008257866, \ /// -0.017333984, -2.25, -7.7089844, -0.00004425831, -0.40625, -24576.0, -37249.0, \ /// -1.1991882, -32.085938, -0.4375, -0.0012359619, -1536.0, -0.22912993, -0.0015716553, ...]" /// ); /// ``` #[inline] pub fn special_random_negative_finite_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> SpecialRandomNegativeFiniteFloats { SpecialRandomNegativeFiniteFloats(special_random_positive_finite_primitive_floats( seed, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, )) } /// Generates nonzero finite primitive floats. /// /// This `struct` is created by [`special_random_nonzero_finite_primitive_floats`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct SpecialRandomNonzeroFiniteFloats { bs: RandomBools, xs: SpecialRandomPositiveFiniteFloats, } impl Iterator for SpecialRandomNonzeroFiniteFloats { type Item = T; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } /// Generates finite nonzero primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Neither positive not negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_nonzero_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_nonzero_finite_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1) /// .map(NiceFloat), /// 20 /// ), /// "[-0.6328125, -9.536743e-7, -0.013671875, 0.6875, -70208.0, 0.01550293, -0.028625488, \ /// -3.3095703, -5.775879, 0.000034958124, 0.4375, 31678.0, -49152.0, -1.0, 49.885254, \ /// -0.40625, -0.0015869141, -1889.5625, -0.14140439, -0.001449585, ...]" /// ); /// ``` #[inline] pub fn special_random_nonzero_finite_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> SpecialRandomNonzeroFiniteFloats { SpecialRandomNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: special_random_positive_finite_primitive_floats( seed.fork("xs"), mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates finite primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that a zero will be /// generated. You can also specify the mean absolute sci-exponent and precision by passing the /// numerators and denominators of their means of the nonzero floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Positive and negative zero are both generated. `NaN` is not. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_finite_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_finite_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .map(NiceFloat), /// 20 /// ), /// "[0.65625, 0.0000014255784, 0.013183594, 0.0, -0.8125, -74240.0, -0.0078125, -0.03060913, \ /// 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, -0.0, -59392.0, -1.75, -41.1875, 0.0, \ /// 0.30940247, -0.0009765625, ...]" /// ); /// ``` #[inline] pub fn special_random_finite_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, ) -> WithSpecialValues> { with_special_values( seed, vec![T::ZERO, T::NEGATIVE_ZERO], mean_zero_p_numerator, mean_zero_p_denominator, &|seed_2| { special_random_nonzero_finite_primitive_floats( seed_2, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ) } /// Generates positive primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that positive infinity /// will be generated. You can also specify the mean absolute sci-exponent and precision by passing /// the numerators and denominators of their means of the finite floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Positive zero is generated; negative zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_positive_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_positive_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .map(NiceFloat), /// 20 /// ), /// "[0.6328125, 9.536743e-7, 0.013671875, Infinity, 0.6875, 70208.0, 0.01550293, \ /// 0.028625488, 3.3095703, 5.775879, 0.000034958124, 0.4375, 31678.0, Infinity, 49152.0, \ /// 1.0, 49.885254, Infinity, 0.40625, 0.0015869141, ...]" /// ); /// ``` #[inline] pub fn special_random_positive_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValue> { with_special_value( seed, T::INFINITY, mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { special_random_positive_finite_primitive_floats( seed_2, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ) } /// Generates negative primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that negative infinity /// will be generated. You can also specify the mean absolute sci-exponent and precision by passing /// the numerators and denominators of their means of the finite floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Negative zero is generated; positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_negative_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_negative_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .map(NiceFloat), /// 20 /// ), /// "[-0.6328125, -9.536743e-7, -0.013671875, -Infinity, -0.6875, -70208.0, -0.01550293, \ /// -0.028625488, -3.3095703, -5.775879, -0.000034958124, -0.4375, -31678.0, -Infinity, \ /// -49152.0, -1.0, -49.885254, -Infinity, -0.40625, -0.0015869141, ...]" /// ); /// ``` #[inline] pub fn special_random_negative_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValue> { with_special_value( seed, T::NEGATIVE_INFINITY, mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { special_random_negative_finite_primitive_floats( seed_2, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ) } /// Generates nonzero primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that an infinity will /// be generated. You can also specify the mean absolute sci-exponent and precision by passing the /// numerators and denominators of their means of the finite floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Neither negative not positive zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_nonzero_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_nonzero_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .map(NiceFloat), /// 20 /// ), /// "[0.65625, 0.0000014255784, 0.013183594, Infinity, -0.8125, -74240.0, -0.0078125, \ /// -0.03060913, 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, -Infinity, -59392.0, \ /// -1.75, -41.1875, Infinity, 0.30940247, -0.0009765625, ...]" /// ); /// ``` #[inline] pub fn special_random_nonzero_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues> { with_special_values( seed, vec![T::INFINITY, T::NEGATIVE_INFINITY], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { special_random_nonzero_finite_primitive_floats( seed_2, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ) } /// Generates primitive floats. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that zero, infinity, or /// NaN will be generated. You can also specify the mean absolute sci-exponent and precision by /// passing the numerators and denominators of their means of the finite floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_primitive_floats; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_primitive_floats::(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .map(NiceFloat), /// 20 /// ), /// "[0.65625, 0.0000014255784, 0.013183594, Infinity, -0.8125, -74240.0, -0.0078125, \ /// -0.03060913, 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, Infinity, -59392.0, \ /// -1.75, -41.1875, Infinity, 0.30940247, -0.0009765625, ...]" /// ); /// ``` #[inline] pub fn special_random_primitive_floats( seed: Seed, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues> { with_special_values( seed, vec![T::ZERO, T::NEGATIVE_ZERO, T::INFINITY, T::NEGATIVE_INFINITY, T::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { special_random_nonzero_finite_primitive_floats( seed_2, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ) } // normalized sci_exponent and raw mantissas in input, adjusted sci_exponent and mantissas in output fn mantissas_inclusive( mut sci_exponent: i64, mut am: u64, mut bm: u64, precision: u64, ) -> Option<(i64, u64, u64)> { assert_ne!(precision, 0); let p: u64 = if sci_exponent < T::MIN_NORMAL_EXPONENT { let ab = am.significant_bits(); let bb = bm.significant_bits(); assert_eq!(ab, bb); ab - precision } else { am.set_bit(T::MANTISSA_WIDTH); bm.set_bit(T::MANTISSA_WIDTH); T::MANTISSA_WIDTH + 1 - precision }; let mut lo = am.shr_round(p, Up).0; if lo.even() { lo += 1; } let mut hi = bm.shr_round(p, Down).0; if hi == 0 { return None; } else if hi.even() { hi -= 1; } if sci_exponent >= T::MIN_NORMAL_EXPONENT { sci_exponent -= i64::wrapping_from(T::MANTISSA_WIDTH); } sci_exponent += i64::wrapping_from(p); if lo > hi { None } else { Some((sci_exponent, lo >> 1, hi >> 1)) } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct SpecialRandomPositiveFiniteFloatInclusiveRange { phantom: PhantomData<*const T>, am: u64, // raw mantissa bm: u64, ae: i64, // sci_exponent be: i64, sci_exponents: GeometricRandomSignedRange, precision_range_map: HashMap>, precision_indices: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, } impl Iterator for SpecialRandomPositiveFiniteFloatInclusiveRange { type Item = T; fn next(&mut self) -> Option { let sci_exponent = self.sci_exponents.next().unwrap(); let ae = self.ae; let be = self.be; let am = self.am; let bm = self.bm; let precision_ranges = self .precision_range_map .entry(sci_exponent) .or_insert_with(|| { let am = if sci_exponent == ae { am } else { T::from_integer_mantissa_and_exponent(1, sci_exponent) .unwrap() .raw_mantissa() }; let bm = if sci_exponent == be { bm } else { T::from_integer_mantissa_and_exponent(1, sci_exponent + 1) .unwrap() .next_lower() .raw_mantissa() }; (1..=T::max_precision_for_sci_exponent(sci_exponent)) .filter_map(|p| mantissas_inclusive::(sci_exponent, am, bm, p)) .collect_vec() }); assert!(!precision_ranges.is_empty()); let i = self.precision_indices.next().unwrap() % precision_ranges.len(); let t = precision_ranges[i]; let mantissa = (self.ranges.next_in_inclusive_range(t.1, t.2) << 1) | 1; Some(T::from_integer_mantissa_and_exponent(mantissa, t.0).unwrap()) } } fn special_random_positive_finite_float_inclusive_range( seed: Seed, a: T, b: T, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> SpecialRandomPositiveFiniteFloatInclusiveRange { assert!(a.is_finite()); assert!(b.is_finite()); assert!(a > T::ZERO); assert!(a <= b); let (am, ae) = a.raw_mantissa_and_exponent(); let (bm, be) = b.raw_mantissa_and_exponent(); let ae = if ae == 0 { i64::wrapping_from(am.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(ae) - T::MAX_EXPONENT }; let be = if be == 0 { i64::wrapping_from(bm.significant_bits()) + T::MIN_EXPONENT - 1 } else { i64::wrapping_from(be) - T::MAX_EXPONENT }; SpecialRandomPositiveFiniteFloatInclusiveRange { phantom: PhantomData, am, bm, ae, be, sci_exponents: geometric_random_signed_inclusive_range( seed.fork("exponents"), ae, be, mean_sci_exponent_numerator, mean_sci_exponent_denominator, ), precision_range_map: HashMap::new(), precision_indices: geometric_random_unsigneds( seed.fork("precisions"), mean_precision_numerator, mean_precision_denominator, ), ranges: VariableRangeGenerator::new(seed.fork("ranges")), } } #[allow(clippy::large_enum_variant)] #[doc(hidden)] #[derive(Clone, Debug)] pub enum SpecialRandomFiniteFloatInclusiveRange { AllPositive(SpecialRandomPositiveFiniteFloatInclusiveRange), AllNegative(SpecialRandomPositiveFiniteFloatInclusiveRange), PositiveAndNegative( RandomBools, SpecialRandomPositiveFiniteFloatInclusiveRange, SpecialRandomPositiveFiniteFloatInclusiveRange, ), } impl Iterator for SpecialRandomFiniteFloatInclusiveRange { type Item = T; fn next(&mut self) -> Option { match self { Self::AllPositive(xs) => xs.next(), Self::AllNegative(xs) => xs.next().map(|x| -x), Self::PositiveAndNegative(bs, xs, ys) => { if bs.next().unwrap() { xs.next() } else { ys.next().map(|x| -x) } } } } } fn special_random_finite_float_inclusive_range( seed: Seed, a: T, b: T, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> SpecialRandomFiniteFloatInclusiveRange { assert!(a.is_finite()); assert!(b.is_finite()); assert_ne!(a, T::ZERO); assert_ne!(b, T::ZERO); assert!(a <= b); if a > T::ZERO { SpecialRandomFiniteFloatInclusiveRange::AllPositive( special_random_positive_finite_float_inclusive_range( seed, a, b, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), ) } else if b < T::ZERO { SpecialRandomFiniteFloatInclusiveRange::AllNegative( special_random_positive_finite_float_inclusive_range( seed, -b, -a, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), ) } else { SpecialRandomFiniteFloatInclusiveRange::PositiveAndNegative( random_bools(seed.fork("bs")), special_random_positive_finite_float_inclusive_range( seed, T::MIN_POSITIVE_SUBNORMAL, b, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), special_random_positive_finite_float_inclusive_range( seed, T::MIN_POSITIVE_SUBNORMAL, -a, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), ) } } /// Generates random primitive floats in a range. /// /// This `enum` is created by [`special_random_primitive_float_range`]; see its documentation for /// more. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum SpecialRandomFloatInclusiveRange { OnlySpecial(RandomValuesFromVec), NoSpecial(Box>), Special(Box>>), } impl Iterator for SpecialRandomFloatInclusiveRange { type Item = T; fn next(&mut self) -> Option { match self { Self::OnlySpecial(xs) => xs.next(), Self::NoSpecial(xs) => xs.next(), Self::Special(xs) => xs.next(), } } } /// Generates random primitive floats in the half-open interval $[a, b)$. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that any special values /// (positive or negative zero or infinity) are generated, provided that they are in the range. You /// can also specify the mean absolute sci-exponent and precision by passing the numerators and /// denominators of their means of the finite floats. /// /// But note that the means are only approximate, since the distributions we are sampling are /// truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual mean is lower than the specified means. /// - However, increasing the approximate mean increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater the smallest absolute of any sci-exponent of a /// float in the range, and the precision mean greater than 2, but they may be as high as you /// like. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater the smallest absolute value of any /// sci-exponent of a float in the range, and the precision mean greater than 2, but they may be /// as high as you like. /// /// `NaN` is never generated. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a$ or $b$ are `NaN`, if $a$ is greater than or equal to $b$ in the `NiceFloat` /// ordering, if any of the denominators are zero, if the special probability is greater than 1, if /// the mean precision is less than 2, or if the mean sci-exponent is less than or equal to the /// minimum absolute value of any sci-exponent in the range. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_primitive_float_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_primitive_float_range::( /// EXAMPLE_SEED, /// core::f32::consts::E, /// core::f32::consts::PI, /// 10, /// 1, /// 10, /// 1, /// 1, /// 100 /// ) /// .map(NiceFloat), /// 20 /// ), /// "[2.9238281, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462658, 3.140625, \ /// 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.0214844, 2.970642, 3.0179443, 2.968872, 2.75, ...]" /// ); /// ``` pub fn special_random_primitive_float_range( seed: Seed, a: T, b: T, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> SpecialRandomFloatInclusiveRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!(NiceFloat(a) < NiceFloat(b)); special_random_primitive_float_inclusive_range( seed, a, b.next_lower(), mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) } /// Generates random primitive floats in the closed interval $[a, b]$. /// /// Simpler floats (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that any special values /// (positive or negative zero or infinity) are generated, provided that they are in the range. You /// can also specify the mean absolute sci-exponent and precision by passing the numerators and /// denominators of their means of the finite floats. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater the smallest absolute value of any /// sci-exponent of a float in the range, and the precision mean greater than 2, but they may be /// as high as you like. /// /// `NaN` is never generated. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if $a$ or $b$ are `NaN`, if $a$ is greater than $b$ in the `NiceFloat` ordering, if any /// of the denominators are zero, if the special probability is greater than 1, if the mean /// precision is less than 2, or if the mean sci-exponent is less than or equal to the minimum /// absolute value of any sci-exponent in the range. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::num::random::special_random_primitive_float_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// special_random_primitive_float_inclusive_range::( /// EXAMPLE_SEED, /// core::f32::consts::E, /// core::f32::consts::PI, /// 10, /// 1, /// 10, /// 1, /// 1, /// 100 /// ) /// .map(NiceFloat), /// 20 /// ), /// "[2.9238281, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462658, 3.140625, \ /// 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.0214844, 2.970642, 3.0179443, 2.968872, 2.75, ...]" /// ); /// ``` pub fn special_random_primitive_float_inclusive_range( seed: Seed, mut a: T, mut b: T, mean_sci_exponent_numerator: u64, mean_sci_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> SpecialRandomFloatInclusiveRange { assert!(!a.is_nan()); assert!(!b.is_nan()); assert!(NiceFloat(a) <= NiceFloat(b)); assert_ne!(mean_special_p_denominator, 0); assert!(mean_special_p_numerator <= mean_special_p_denominator); assert_ne!(mean_precision_denominator, 0); assert!(mean_precision_numerator > mean_precision_denominator); let only_special = a == T::INFINITY || b == T::NEGATIVE_INFINITY || a == T::ZERO && b == T::ZERO; let mut special_values = Vec::new(); if a == T::NEGATIVE_INFINITY { special_values.push(a); a = -T::MAX_FINITE; } if b == T::INFINITY { special_values.push(b); b = T::MAX_FINITE; } if NiceFloat(a) <= NiceFloat(T::NEGATIVE_ZERO) && NiceFloat(b) >= NiceFloat(T::NEGATIVE_ZERO) { special_values.push(T::NEGATIVE_ZERO); } if NiceFloat(a) <= NiceFloat(T::ZERO) && NiceFloat(b) >= NiceFloat(T::ZERO) { special_values.push(T::ZERO); } if a == T::ZERO { a = T::MIN_POSITIVE_SUBNORMAL; } if b == T::ZERO { b = -T::MIN_POSITIVE_SUBNORMAL; } if only_special { SpecialRandomFloatInclusiveRange::OnlySpecial(random_values_from_vec(seed, special_values)) } else if special_values.is_empty() { SpecialRandomFloatInclusiveRange::NoSpecial(Box::new( special_random_finite_float_inclusive_range( seed, a, b, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), )) } else { SpecialRandomFloatInclusiveRange::Special(Box::new(with_special_values( seed, special_values, mean_special_p_numerator, mean_special_p_denominator, &|seed| { special_random_finite_float_inclusive_range( seed, a, b, mean_sci_exponent_numerator, mean_sci_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ) }, ))) } } /// Generates unsigneds sampled from ranges. A single generator can sample from different ranges of /// different types. /// /// This `struct` is created by [`VariableRangeGenerator::new`]; see its documentation for more. #[derive(Clone, Debug)] pub struct VariableRangeGenerator { xs: RandomPrimitiveInts, x: u32, in_inner_loop: bool, remaining_x_bits: u64, } impl VariableRangeGenerator { /// Generates unsigneds sampled from ranges. A single generator can sample from different ranges /// of different types. /// /// If you only need to generate values from a single range, it is slightly more efficient to /// use [`random_unsigned_bit_chunks`], [`random_unsigneds_less_than`], /// [`random_unsigned_range`], or [`random_unsigned_inclusive_range`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// assert_eq!(generator.next_bit_chunk::(10), 881); /// assert_eq!(generator.next_less_than::(100), 34); /// assert_eq!(generator.next_in_range::(10, 20), 16); /// assert_eq!(generator.next_in_inclusive_range::(10, 20), 14); /// ``` pub fn new(seed: Seed) -> Self { Self { xs: random_primitive_ints(seed), x: 0, in_inner_loop: false, remaining_x_bits: 0, } } /// Uniformly generates a `bool`. /// /// $$ /// $P(\text{false}) = P(\text{true}) = \frac{1}{2}$. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_bool()); /// } /// assert_eq!( /// xs, /// &[true, false, true, false, true, true, true, true, true, false] /// ); /// ``` pub fn next_bool(&mut self) -> bool { self.xs.next().unwrap().odd() } /// Uniformly generates an unsigned integer with up to some number of bits. /// /// $$ /// P(x) = \\begin{cases} /// 2^{-c} & \text{if} \\quad 0 \\leq x < 2^c, \\\\ /// 0 & \text{if} \\quad \\text{otherwise,} /// \\end{cases} /// $$ /// where $c$ is `chunk_size`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `chunk_size` is zero or greater than the width of the type. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_bit_chunk::(3)); /// } /// assert_eq!(xs, &[1, 6, 5, 7, 6, 3, 1, 2, 4, 5]); /// ``` pub fn next_bit_chunk(&mut self, chunk_size: u64) -> T { assert_ne!(chunk_size, 0); assert!(chunk_size <= T::WIDTH); let mut y = T::ZERO; let mut remaining_y_bits = chunk_size; loop { if !self.in_inner_loop { self.x = self.xs.next().unwrap(); self.remaining_x_bits = u32::WIDTH; self.in_inner_loop = true; } while self.remaining_x_bits != 0 { let y_index = chunk_size - remaining_y_bits; if self.remaining_x_bits <= remaining_y_bits { y |= T::wrapping_from(self.x) << y_index; remaining_y_bits -= self.remaining_x_bits; self.remaining_x_bits = 0; } else { y |= T::wrapping_from(self.x).mod_power_of_2(remaining_y_bits) << y_index; self.x >>= remaining_y_bits; self.remaining_x_bits -= remaining_y_bits; remaining_y_bits = 0; } if remaining_y_bits == 0 { return y; } } self.in_inner_loop = false; } } /// Uniformly generates a random unsigned integer less than a positive limit. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{\\ell} & \text{if} \\quad x < \\ell \\\\ /// 0 & \\text{otherwise} /// \\end{cases} /// $$ /// where $\ell$ is `limit`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `limit` is 0. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_less_than(10u8)); /// } /// assert_eq!(xs, &[1, 7, 5, 4, 6, 4, 2, 8, 1, 7]); /// ``` pub fn next_less_than(&mut self, limit: T) -> T { assert_ne!(limit, T::ZERO); if limit == T::ONE { T::ZERO } else { let chunk_size = limit.ceiling_log_base_2(); loop { let x = self.next_bit_chunk(chunk_size); if x < limit { return x; } } } } /// Uniformly generates a random unsigned integer in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. This function cannot create a range that includes `T::MAX`; for /// that, use [`next_in_inclusive_range`](Self::next_in_inclusive_range). /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a} & \text{if} \\quad a \leq x < b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_in_range(10u8, 20)); /// } /// assert_eq!(xs, &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17]); /// ``` pub fn next_in_range(&mut self, a: T, b: T) -> T { self.next_less_than(b - a) + a } /// Uniformly generates a random unsigned integer in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a+1} & \text{if} \\quad a \leq x \leq b, \\\\ /// 0 & \\text{otherwise.} /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut xs = Vec::with_capacity(10); /// let mut generator = VariableRangeGenerator::new(EXAMPLE_SEED); /// for _ in 0..10 { /// xs.push(generator.next_in_inclusive_range(10u8, 19)); /// } /// assert_eq!(xs, &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17]); /// ``` pub fn next_in_inclusive_range(&mut self, a: T, b: T) -> T { if a == T::ZERO && b == T::MAX { self.next_bit_chunk(T::WIDTH) } else { self.next_less_than(b - a + T::ONE) + a } } } /// Iterators that generate primitive integers from geometric-like distributions. pub mod geometric; /// Iterators that generate primitive integers that tend to have long runs of binary 0s and 1s. /// /// Integers with long runs of 0s and 1s are good for testing; they're more likely to result in /// carries and borrows than uniformly random integers. This idea was inspired by GMP's /// `mpz_rrandomb` function, although striped integer generators are more general: they can also /// produce integers with runs that are shorter than average, so that they tend to contain /// alternating bits like $1010101$. /// /// Let the average length of a run of 0s and 1s be $m$. The functions in this module allow the user /// to specify a rational $m$ through the parameters `m_numerator` and `m_denominator`. Since any /// binary sequence has an average run length of at least 1, $m$ must be at least 1; but if it is /// exactly 1 then the sequence is strictly alternating and no longer random, so 1 is not allowed /// either. if $m$ is between 1 and 2, the sequence is less likely to have two equal adjacent bits /// than a uniformly random sequence. If $m$ is 2, the sequence is uniformly random. If $m$ is /// greater than 2 (the most useful case), the sequence tends to have long runs of 0s and 1s. /// /// # Details /// /// A random striped sequence with parameter $m \geq 1$ is an infinite sequence of bits, defined as /// follows. The first bit is 0 or 1 with equal probability. Every subsequent bit has a $1/m$ /// probability of being different than the preceding bit. Notice that every sequence has an equal /// probability as its negation. Also, if $m > 1$, any sequence has a nonzero probability of /// occurring. /// /// * $m=1$ is disallowed. If it were allowed, the sequence would be either /// $01010101010101010101\ldots$ or $10101010101010101010\ldots$. /// * If $12$, the sequence tends to have longer runs of 0s and 1s than a uniformly random /// sequence. A sample sequence with $m=32$ is $1111111111111111110000000011111111111111\ldots$. /// /// An alternative way to generate a striped sequence is to start with 0 or 1 with equal probability /// and then determine the length of each block of equal bits using a geometric distribution with /// mean $m$. In practice, this isn't any more efficient than the naive algorithm. /// /// We can generate a random striped unsigned integer of type `T` by taking the first $W$ bits of a /// striped sequence. Fixing the parameter $m$ defines a distribution over `T`s. A few things can be /// said about the probability $P_m(n)$ of an unsigned integer $n$ of width $W$ being generated: /// * $P_m(n) = P_m(\lnot n)$ /// * $P_m(0) = P_m(2^W-1) = \frac{1}{2} \left ( 1-\frac{1}{m} \right )^{W-1}$. If $m>2$, this is /// the maximum probability achieved; if $m<2$, the minimum. /// * $P_m(\lfloor 2^W/3 \rfloor) = P_m(\lfloor 2^{W+1}/3 \rfloor) = 1/(2m^{W-1})$. If $m>2$, this /// is the minimum probability achieved; if $m<2$, the maximum. /// * Because of these distributions' symmetry, their mean is $(2^W-1)/2$ and their skewness is 0. /// It's hard to say anything about their standard deviations or excess kurtoses, although these /// can be computed quickly for specific values of $m$ when $W$ is 8 or 16. /// /// We can similarly generate random striped signed integers of width $W$. The sign bit is chosen /// uniformly, and the remaining $W-1$ are taken from a striped sequence. /// /// To generate striped integers from a range, the integers are constructed one bit at a time. Some /// bits are forced; they must be 0 or 1 in order for the final integer to be within the specified /// range. If a bit is _not_ forced, it is different from the preceding bit with probability $1/m$. pub mod striped; ================================================ FILE: malachite-base/src/num/random/striped.rs ================================================ // Copyright © 2026 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 crate::bools::random::{RandomBools, WeightedRandomBools, random_bools, weighted_random_bools}; use crate::iterators::{NonzeroValues, nonzero_values}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, mean_to_p_with_min, }; use crate::num::random::{ RandomUnsignedInclusiveRange, RandomUnsignedRange, random_unsigned_inclusive_range, random_unsigned_range, }; use crate::random::Seed; use itertools::Itertools; use std::iter::{Repeat, repeat}; use std::marker::PhantomData; /// Generates bits from a striped random sequence. /// /// See [here](self) for more information. #[derive(Clone, Debug)] pub struct StripedBitSource { first_bit_of_block: bool, previous_bit: bool, bs: RandomBools, xs: WeightedRandomBools, } impl Iterator for StripedBitSource { type Item = bool; /// Gets a bit from this `StripedBitSource`. If this function is being called for the first /// time, the probabilities of a `true` or a `false` are equal. On subsequent calls, the /// probability of getting a bit different from the previous one is $1 / m$. /// /// To reset the bit source, so that the next call to `next` has equal probabilities of `true` /// or `false`, call [`end_block`](Self::end_block). /// /// # Expected complexity /// Constant time and additional memory. #[inline] fn next(&mut self) -> Option { self.previous_bit = if self.first_bit_of_block { self.first_bit_of_block = false; self.bs.next().unwrap() } else { self.previous_bit ^ self.xs.next().unwrap() }; Some(self.previous_bit) } } impl StripedBitSource { /// Creates a new `StripedBitSource`. /// /// The mean run length is $m$, where $m$ is `m_numerator / m_denominator`. /// /// # Expected complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `m_denominator` is zero or if `m_numerator <= m_denominator`. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// /// let bit_source = StripedBitSource::new(EXAMPLE_SEED, 4, 1); /// let mut string = String::with_capacity(40); /// for bit in bit_source.take(40) { /// if bit { /// string.push('1'); /// } else { /// string.push('0'); /// } /// } /// assert_eq!(string, "0000000101100110000000011110000000001111"); /// ``` pub fn new(seed: Seed, m_numerator: u64, m_denominator: u64) -> Self { assert_ne!(m_denominator, 0); assert!(m_numerator > m_denominator); let (numerator, denominator) = mean_to_p_with_min(1u64, m_numerator, m_denominator); Self { first_bit_of_block: true, previous_bit: false, bs: random_bools(seed.fork("bs")), xs: weighted_random_bools(seed.fork("xs"), numerator, numerator + denominator), } } /// Resets this `StripedBitSource`, so that the next time [`next`](Self::next) is called, the /// probabilities of `true` or `false` will be equal. /// /// # Expected complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// /// fn generate_string(bit_source: &mut StripedBitSource) -> String { /// let mut string = String::with_capacity(40); /// for bit in bit_source.take(40) { /// if bit { /// string.push('1'); /// } else { /// string.push('0'); /// } /// } /// string /// } /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 1000000, 1); /// let mut strings = Vec::with_capacity(5); /// for _ in 0..5 { /// strings.push(generate_string(&mut bit_source)); /// bit_source.end_block(); /// } /// assert_eq!( /// strings, /// &[ /// "0000000000000000000000000000000000000000", /// "0000000000000000000000000000000000000000", /// "0000000000000000000000000000000000000000", /// "1111111111111111111111111111111111111111", /// "0000000000000000000000000000000000000000" /// ] /// ); /// ``` pub const fn end_block(&mut self) { self.first_bit_of_block = true; } /// Sets the previous bit of a `StripedBitSource`. This will affect the probability of the next /// bit. /// /// # Expected complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// /// fn generate_string(bit_source: &mut StripedBitSource) -> String { /// let mut string = String::with_capacity(40); /// for bit in bit_source.take(40) { /// if bit { /// string.push('1'); /// } else { /// string.push('0'); /// } /// } /// string /// } /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 1000000, 1); /// bit_source.next(); /// let mut strings = Vec::with_capacity(3); /// bit_source.set_previous_bit(true); /// strings.push(generate_string(&mut bit_source)); /// bit_source.set_previous_bit(false); /// strings.push(generate_string(&mut bit_source)); /// bit_source.set_previous_bit(true); /// strings.push(generate_string(&mut bit_source)); /// assert_eq!( /// strings, /// &[ /// "1111111111111111111111111111111111111111", /// "0000000000000000000000000000000000000000", /// "1111111111111111111111111111111111111111", /// ] /// ); /// ``` pub const fn set_previous_bit(&mut self, bit: bool) { self.previous_bit = bit; } } /// Generates random unsigned integers from a random striped distribution. /// /// This `struct` is created by [`striped_random_unsigned_bit_chunks`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct StripedRandomUnsignedBitChunks { phantom: PhantomData<*const T>, bits: StripedBitSource, chunk_size: usize, } impl Iterator for StripedRandomUnsignedBitChunks { type Item = T; fn next(&mut self) -> Option { self.bits.end_block(); let mut x = T::ZERO; for bit in (&mut self.bits).take(self.chunk_size) { x <<= 1; if bit { x |= T::ONE; } } Some(x) } } /// Generates random signed integers from a random striped distribution. /// /// This `struct` is created by [`striped_random_signeds`]; see its documentation for more. #[derive(Clone, Debug)] pub struct StripedRandomSigneds { phantom: PhantomData<*const T>, bits: StripedBitSource, bs: RandomBools, } impl Iterator for StripedRandomSigneds { type Item = T; fn next(&mut self) -> Option { self.bits.end_block(); let mut x = T::ZERO; for bit in (&mut self.bits).take(usize::wrapping_from(T::WIDTH) - 1) { x <<= 1; if bit { x |= T::ONE; } } if self.bs.next().unwrap() { x.set_bit(T::WIDTH - 1); } Some(x) } } /// Generates random natural (non-negative) signed integers from a random striped distribution. /// /// This `struct` is created by [`striped_random_natural_signeds`]; see its documentation for more. #[derive(Clone, Debug)] pub struct StripedRandomNaturalSigneds { phantom: PhantomData<*const T>, bits: StripedBitSource, } impl Iterator for StripedRandomNaturalSigneds { type Item = T; fn next(&mut self) -> Option { self.bits.end_block(); let mut x = T::ZERO; for bit in (&mut self.bits).take(usize::wrapping_from(T::WIDTH) - 1) { x <<= 1; if bit { x |= T::ONE; } } Some(x) } } /// Generates random negative signed integers from a random striped distribution. /// /// This `struct` is created by [`striped_random_negative_signeds`]; see its documentation for more. #[derive(Clone, Debug)] pub struct StripedRandomNegativeSigneds { phantom: PhantomData<*const T>, bits: StripedBitSource, } impl Iterator for StripedRandomNegativeSigneds { type Item = T; fn next(&mut self) -> Option { self.bits.end_block(); let mut x = T::ZERO; for bit in (&mut self.bits).take(usize::wrapping_from(T::WIDTH) - 1) { x <<= 1; if bit { x |= T::ONE; } } x.set_bit(T::WIDTH - 1); Some(x) } } /// Generates random unsigned integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigneds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1001100, 1111111, 11000011, 0, 10000000, 1111, 1110110, 0, 11111000, ...]" /// ) /// ``` #[inline] pub fn striped_random_unsigneds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> StripedRandomUnsignedBitChunks { striped_random_unsigned_bit_chunks(seed, T::WIDTH, m_numerator, m_denominator) } /// Generates random positive unsigned integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_positive_unsigneds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_positive_unsigneds::(EXAMPLE_SEED, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1001100, 1111111, 11000011, 10000000, 1111, 1110110, 11111000, 11111111, 11111101, \ /// ...]" /// ) /// ``` pub fn striped_random_positive_unsigneds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> NonzeroValues> { nonzero_values(striped_random_unsigneds(seed, m_numerator, m_denominator)) } /// Generates random signed integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_signeds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[1100001, 1000000, 1100000, 10000111, 1111, 10000001, 1111000, 100011, 111101, 11111100, \ /// ...]" /// ) /// ``` pub fn striped_random_signeds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> StripedRandomSigneds { StripedRandomSigneds { phantom: PhantomData, bits: StripedBitSource::new(seed.fork("bits"), m_numerator, m_denominator), bs: random_bools(seed.fork("bs")), } } /// Generates random natural (non-negative) signed integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_natural_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_natural_signeds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[0, 101100, 110000, 1111100, 1111, 1111110, 0, 111, 11101, 1100000, ...]" /// ) /// ``` pub fn striped_random_natural_signeds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> StripedRandomNaturalSigneds { StripedRandomNaturalSigneds { phantom: PhantomData, bits: StripedBitSource::new(seed, m_numerator, m_denominator), } } /// Generates random positive signed integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_positive_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_positive_signeds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[101100, 110000, 1111100, 1111, 1111110, 111, 11101, 1100000, 1111111, 1100000, ...]" /// ) /// ``` pub fn striped_random_positive_signeds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> NonzeroValues> { nonzero_values(striped_random_natural_signeds( seed, m_numerator, m_denominator, )) } /// Generates random negative signed integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_negative_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_negative_signeds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[10000000, 10101100, 10110000, 11111100, 10001111, 11111110, 10000000, 10000111, \ /// 10011101, 11100000, ...]" /// ) /// ``` pub fn striped_random_negative_signeds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> StripedRandomNegativeSigneds { StripedRandomNegativeSigneds { phantom: PhantomData, bits: StripedBitSource::new(seed, m_numerator, m_denominator), } } /// Generates random nonzero signed integers from a random striped distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is the width of the type. /// /// # Panics /// Panics if `m_denominator` is zero or if m_numerator <= m_denominator. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_nonzero_signeds; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_nonzero_signeds::(EXAMPLE_SEED, 4, 1).map(|x| x.to_binary_string()), /// 10 /// ), /// "[1100001, 1000000, 1100000, 10000111, 1111, 10000001, 1111000, 100011, 111101, 11111100, \ /// ...]" /// ) /// ``` pub fn striped_random_nonzero_signeds( seed: Seed, m_numerator: u64, m_denominator: u64, ) -> NonzeroValues> { nonzero_values(striped_random_signeds(seed, m_numerator, m_denominator)) } /// Generates random unsigned integers of up to `chunk_size` bits from a random striped /// distribution. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `m_numerator / /// m_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `chunk_size`. /// /// # Panics /// Panics if `m_denominator` is zero, if m_numerator <= m_denominator, or if `chunk_size` is /// greater than the width of the type. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_bit_chunks; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_bit_chunks::(EXAMPLE_SEED, 3, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[0, 0, 0, 101, 11, 100, 11, 11, 0, 111, ...]" /// ) /// ``` pub fn striped_random_unsigned_bit_chunks( seed: Seed, chunk_size: u64, m_numerator: u64, m_denominator: u64, ) -> StripedRandomUnsignedBitChunks { assert!(chunk_size <= T::WIDTH); StripedRandomUnsignedBitChunks { phantom: PhantomData, bits: StripedBitSource::new(seed, m_numerator, m_denominator), chunk_size: usize::exact_from(chunk_size), } } /// Generates a striped `Vec`, with a given length, from a [`StripedBitSource`]. /// /// See [here](self) for more information. /// /// The output length is `len`. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `len`. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::{get_striped_bool_vec, StripedBitSource}; /// use malachite_base::random::EXAMPLE_SEED; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// let bits: String = get_striped_bool_vec(&mut bit_source, 50) /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect(); /// assert_eq!(bits, "00011111111111000000011111111111111000000000001111"); /// ``` pub fn get_striped_bool_vec(bit_source: &mut StripedBitSource, len: u64) -> Vec { bit_source.end_block(); bit_source.take(usize::exact_from(len)).collect() } /// Generates random striped `Vec`s. #[derive(Clone, Debug)] pub struct StripedRandomBoolVecs> { lengths: I, bit_source: StripedBitSource, } impl> Iterator for StripedRandomBoolVecs { type Item = Vec; fn next(&mut self) -> Option> { Some(get_striped_bool_vec( &mut self.bit_source, self.lengths.next().unwrap(), )) } } /// Generates random striped `Vec`s, with lengths from an iterator. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero or if `mean_stripe_numerator <= /// mean_stripe_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_bool_vecs_from_length_iterator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random_values_from_vec; /// /// assert_eq!( /// prefix_to_string( /// striped_random_bool_vecs_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// 10, /// 1, /// ) /// .map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[00, 0000, 00, 0000, 0000, 11, , 00, , 1111, 0001, 11, 1100, 00, 0000, 0000, 1110, , \ /// 0000, , ...]" /// ); /// ``` #[inline] pub fn striped_random_bool_vecs_from_length_iterator>( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomBoolVecs { StripedRandomBoolVecs { lengths: lengths_gen(seed.fork("lengths")), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates random striped `Vec`s of a given length. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// If `len` is 0, the output consists of the empty list, repeated. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `len`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_fixed_length_bool_vecs; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// striped_random_fixed_length_bool_vecs(EXAMPLE_SEED, 5, 10, 1).map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[00000, 00000, 00000, 00000, 00011, 11000, 00000, 11111, 01111, 11111, 10000, 00011, \ /// 00000, 00000, 11000, 00000, 11111, 00000, 00000, 11111, ...]" /// ); /// ``` pub fn striped_random_fixed_length_bool_vecs( seed: Seed, len: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomBoolVecs> { striped_random_bool_vecs_from_length_iterator( seed, &|_| repeat(len), mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped `Vec`s. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_length_numerator / /// mean_length_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, if `mean_length_numerator` or `mean_length_denominator` are zero, or, /// if after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_bool_vecs; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// striped_random_bool_vecs(EXAMPLE_SEED, 10, 1, 2, 1).map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[000000, 0, 00000000, 0, 00000001110000, , 11111, 0000, 1, , 011111, 11, , , 1, 000, , \ /// 0, , 0, ...]" /// ); /// ``` #[inline] pub fn striped_random_bool_vecs( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StripedRandomBoolVecs> { striped_random_bool_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped `Vec`s, with a minimum length. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than /// `min_length`. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_length_numerator / /// mean_length_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, if `mean_length_numerator` or `mean_length_denominator` are zero, if /// their ratio is less than or equal to `min_length`, or if they are too large and manipulating /// them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_bool_vecs_min_length; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// striped_random_bool_vecs_min_length(EXAMPLE_SEED, 3, 10, 1, 5, 1).map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[000000000, 0000, 00000000111, 0111, 00000000011111111, 100, 00000111, 1111111, 0001, \ /// 111, 111111111, 00000, 000, 000, 1111, 000000, 111, 0011, 000, 1111, ...]" /// ); /// ``` #[inline] pub fn striped_random_bool_vecs_min_length( seed: Seed, min_length: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StripedRandomBoolVecs> { striped_random_bool_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped `Vec`s, with lengths in $[a, b)$. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \\begin{cases} /// \frac{1}{b-a}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(b)$ /// /// $M(n) = O(b)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_bool_vecs_length_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// striped_random_bool_vecs_length_range(EXAMPLE_SEED, 4, 10, 10, 1).map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[000000000, 000000000, 000111000, 000000000, 0111, 11111, 00111111, 1000000, 00000011, \ /// 111111111, 111111, 00000000, 00000000, 001111, 111111111, 000000000, 110000, 0001111, \ /// 0000000, 111101111, ...]" /// ); /// ``` #[inline] pub fn striped_random_bool_vecs_length_range( seed: Seed, a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomBoolVecs> { striped_random_bool_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped `Vec`s, with lengths in $[a, b]$. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b]$. $a$ must be /// less than $b$. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \\begin{cases} /// \frac{1}{b-a+1}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n \leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(b)$ /// /// $M(n) = O(b)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_bool_vecs_length_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// prefix_to_string( /// striped_random_bool_vecs_length_inclusive_range(EXAMPLE_SEED, 4, 9, 10, 1).map(|bs| bs /// .into_iter() /// .map(|b| if b { '1' } else { '0' }) /// .collect::()), /// 20 /// ), /// "[000000000, 000000000, 000111000, 000000000, 0111, 11111, 00111111, 1000000, 00000011, \ /// 111111111, 111111, 00000000, 00000000, 001111, 111111111, 000000000, 110000, 0001111, \ /// 0000000, 111101111, ...]" /// ); /// ``` #[inline] pub fn striped_random_bool_vecs_length_inclusive_range( seed: Seed, a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomBoolVecs> { striped_random_bool_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates a striped unsigned [`Vec`], with a given number of bits (not length!), from a /// [`StripedBitSource`]. /// /// See [here](self) for more information. /// /// The output length is `bit_len.div_round(T::WIDTH, Ceiling)`. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bit_len`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::striped::{get_striped_unsigned_vec, StripedBitSource}; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// let xs = get_striped_unsigned_vec::(&mut bit_source, 100) /// .iter() /// .map(u8::to_binary_string) /// .collect_vec(); /// assert_eq!( /// xs, /// &[ /// "11111000", "111111", "11100000", "11111111", "111", "11000000", "11111111", "0", "0", /// "11111000", "11111111", "11111111", "11", /// ] /// ); /// ``` pub fn get_striped_unsigned_vec( bit_source: &mut StripedBitSource, bit_len: u64, ) -> Vec { bit_source.end_block(); bit_source .take(usize::exact_from(bit_len)) .chunks(usize::wrapping_from(T::WIDTH)) .into_iter() .map(T::from_bits_asc) .collect() } /// Generates random striped [`Vec`]s of unsigneds. #[derive(Clone, Debug)] pub struct StripedRandomUnsignedVecs> { phantom: PhantomData<*const T>, lengths: I, bit_source: StripedBitSource, } impl> Iterator for StripedRandomUnsignedVecs { type Item = Vec; fn next(&mut self) -> Option> { Some(get_striped_unsigned_vec( &mut self.bit_source, self.lengths.next().unwrap() << T::LOG_WIDTH, )) } } /// Generates random striped [`Vec`]s of unsigneds, with lengths from an iterator. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero or if `mean_stripe_numerator <= /// mean_stripe_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_vecs_from_length_iterator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_base::vecs::random_values_from_vec; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_vecs_from_length_iterator::( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// 10, /// 1, /// ) /// .map(|xs| prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100)), /// 10, /// ), /// "[[0, 0], [1110000, 0, 11111100, 11], [11111110, 1111], [0, 0, 0, 11111000], \ /// [0, 0, 1111110, 0], [11011111, 11111111], [], [11110000, 11111111], [], \ /// [11111111, 11000011, 11111, 0], ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_vecs_from_length_iterator< T: PrimitiveUnsigned, I: Iterator, >( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedVecs { StripedRandomUnsignedVecs { phantom: PhantomData, lengths: lengths_gen(seed.fork("lengths")), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates random striped unsigned [`Vec`]s of a given length. /// /// See [here](self) for more information. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// If `len` is 0, the output consists of the empty list, repeated. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `len`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_fixed_length_unsigned_vecs; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_fixed_length_unsigned_vecs::(EXAMPLE_SEED, 3, 10, 1).map(|xs| { /// prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100) /// }), /// 10, /// ), /// "[[0, 0, 111000], [0, 11111100, 11], [11111110, 1111, 0], [0, 0, 11111000], \ /// [0, 0, 1111110], [11111111, 11011111, 11111111], [11110000, 11111111, 11111111], \ /// [11000011, 11111, 0], [0, 10000000, 11111001], [11111111, 0, 0], ...]" /// ); /// ``` #[inline] pub fn striped_random_fixed_length_unsigned_vecs( seed: Seed, len: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedVecs> { striped_random_unsigned_vecs_from_length_iterator( seed, &|_| repeat(len), mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Vec`]s of unsigneds. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \frac{m^n}{(m+1)^{n+1}}\prod_{i=0}^{n-1}P(x_i). /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_length_numerator / /// mean_length_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, if `mean_length_numerator` or `mean_length_denominator` are zero, or, /// if after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_vecs; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_vecs::(EXAMPLE_SEED, 10, 1, 2, 1) /// .map(|xs| prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100)), /// 10, /// ), /// "[[0, 0, 111000, 0, 11111110, 10000001], [0], \ /// [11110000, 11111111, 11111111, 11111111, 11, 0, 10000000, 11111], [0], \ /// [10000, 0, 11111100, 11111111, 1111111, 11111000, 11, 0, 0, 10011000, 11111111, 111, 0, \ /// 0], [], [11111111, 11111111, 11111111, 11111111, 10111111], [0, 0, 0, 11110000], \ /// [11111111], [], ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_vecs( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StripedRandomUnsignedVecs> { striped_random_unsigned_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Vec`]s of unsigneds, with a minimum length. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than /// `min_length`. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \\begin{cases} /// \frac{(m-a)^{n-a}}{(m+1-a)^{n+1-a}}\prod_{i=0}^{n-1}P(x_i) & n \geq a \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $a$ is `min_length`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_length_numerator / /// mean_length_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, if `mean_length_numerator` or `mean_length_denominator` are zero, if /// their ratio is less than or equal to `min_length`, or if they are too large and manipulating /// them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_vecs_min_length; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 2, 10, 1, 3, 1) /// .map(|xs| prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100)), /// 10, /// ), /// "[[0, 0, 111000], [0, 11111100, 11, 11111111], \ /// [11110000, 11111111, 11111111, 11111111], [11111000, 11111111, 11111111, 11000000], \ /// [0, 10000, 0], [111, 0, 0, 1111], [11110000, 11111111], [11111111, 111111], \ /// [110, 10000000, 11111111], [11111111, 11111111], ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_vecs_min_length( seed: Seed, min_length: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StripedRandomUnsignedVecs> { striped_random_unsigned_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Vec`]s of unsigneds, with lengths in $[a, b)$. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \\begin{cases} /// \frac{1}{b-a}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(b)$ /// /// $M(n) = O(b)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_vecs_length_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_vecs_length_range::(EXAMPLE_SEED, 2, 4, 10, 1) /// .map(|xs| prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100)), /// 10, /// ), /// "[[0, 0, 111000], [0, 11111100], [11111000, 1, 11110000], [0, 0, 0], \ /// [11110000, 11111111], [11111111, 11, 11111111], [1000000, 0, 11110000], \ /// [11111111, 11111111], [1111000, 11000000, 11111111], [11111111, 11111111, 1100], ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_vecs_length_range( seed: Seed, a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedVecs> { striped_random_unsigned_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Vec`]s of unsigneds, with lengths in $[a, b]$. /// /// See [here](self) for more information. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b]$. $a$ must be /// less than $b$. /// /// The mean run length (before the bit sequences are truncated) is $m$ = `mean_stripe_numerator / /// mean_stripe_denominator`. /// /// $$ /// P((x_0, x_1, \ldots, x_{n-1})) = \\begin{cases} /// \frac{1}{b-a+1}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n \leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(b)$ /// /// $M(n) = O(b)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_vecs_length_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_vecs_length_inclusive_range::(EXAMPLE_SEED, 2, 3, 10, 1) /// .map(|xs| prefix_to_string(xs.into_iter().map(|x: u8| x.to_binary_string()), 100)), /// 10, /// ), /// "[[0, 0, 111000], [0, 11111100], [11111000, 1, 11110000], [0, 0, 0], \ /// [11110000, 11111111], [11111111, 11, 11111111], [1000000, 0, 11110000], \ /// [11111111, 11111111], [1111000, 11000000, 11111111], [11111111, 11111111, 1100], ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_vecs_length_inclusive_range( seed: Seed, a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedVecs> { striped_random_unsigned_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), mean_stripe_numerator, mean_stripe_denominator, ) } #[inline] fn ranges_intersect(lo_0: T, hi_0: T, lo: T, hi: T) -> bool { lo <= hi_0 && lo_0 <= hi } /// Generates random striped unsigneds from a range. #[derive(Clone, Debug)] pub struct StripedRandomUnsignedInclusiveRange { a: T, b: T, lo_template: T, hi_template: T, next_bit: u64, bit_source: StripedBitSource, } impl Iterator for StripedRandomUnsignedInclusiveRange { type Item = T; fn next(&mut self) -> Option { if self.next_bit == 0 { return Some(self.lo_template); } let mut lo_template = self.lo_template; let mut hi_template = self.hi_template; let mut first = true; let mut previous_forced = true; let mut previous_bit = lo_template.get_bit(self.next_bit); for next_bit in (0..self.next_bit).rev() { let false_possible; let true_possible; if first { false_possible = true; true_possible = true; lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); first = false; } else { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); false_possible = ranges_intersect(lo_template, hi_template, self.a, self.b); lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); true_possible = ranges_intersect(lo_template, hi_template, self.a, self.b); } assert!(false_possible || true_possible); let bit = if !false_possible { previous_forced = true; true } else if !true_possible { previous_forced = true; false } else { if previous_forced { self.bit_source.end_block(); self.bit_source.set_previous_bit(previous_bit); previous_forced = false; } self.bit_source.next().unwrap() }; if !bit { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); } previous_bit = bit; } Some(lo_template) } } /// Generates random striped unsigneds in the range $[a, b)$. /// /// See [here](self) for more information. /// /// The unsigneds are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the unsigneds are constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_range::(EXAMPLE_SEED, 1, 7, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1, 1, 110, 1, 110, 10, 11, 11, 100, ...]" /// ); /// ``` #[inline] pub fn striped_random_unsigned_range( seed: Seed, a: T, b: T, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedInclusiveRange { assert!(a < b); striped_random_unsigned_inclusive_range( seed, a, b - T::ONE, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped unsigneds in the range $[a, b]$. /// /// See [here](self) for more information. /// /// The unsigneds are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the unsigneds are constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 6, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1, 1, 110, 1, 110, 10, 11, 11, 100, ...]" /// ); /// ``` pub fn striped_random_unsigned_inclusive_range( seed: Seed, a: T, b: T, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomUnsignedInclusiveRange { assert!(a <= b); let diff_bits = T::WIDTH - (a ^ b).leading_zeros(); let mask = T::low_mask(diff_bits); let lo_template = a & !mask; let hi_template = lo_template | mask; StripedRandomUnsignedInclusiveRange { a, b, lo_template, hi_template, next_bit: diff_bits, bit_source: StripedBitSource::new(seed, mean_stripe_numerator, mean_stripe_denominator), } } /// Generates random striped signeds from a range. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum StripedRandomSignedInclusiveRange< U: PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, > { NonNegative(PhantomData, StripedRandomUnsignedInclusiveRange), Negative(PhantomData, StripedRandomUnsignedInclusiveRange), Both( PhantomData, Box, StripedRandomUnsignedInclusiveRange, StripedRandomUnsignedInclusiveRange, ), } impl> Iterator for StripedRandomSignedInclusiveRange { type Item = S; fn next(&mut self) -> Option { match self { Self::NonNegative(_, xs) => xs.next().map(S::wrapping_from), Self::Negative(_, xs) => xs.next().map(|x| S::wrapping_from(x).wrapping_neg()), Self::Both(_, bs, xs_nn, xs_n) => { if bs.next().unwrap() { xs_nn.next().map(S::wrapping_from) } else { xs_n.next().map(|x| S::wrapping_from(x).wrapping_neg()) } } } } } /// Generates random striped signeds in the range $[a, b]$. /// /// See [here](self) for more information. /// /// The unsigneds are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the signeds are constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_signed_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_signed_inclusive_range::(EXAMPLE_SEED, -5, 10, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[11111011, 11111100, 1000, 111, 11111111, 1000, 11, 1000, 0, 1000, ...]" /// ); /// ``` #[inline] pub fn striped_random_signed_range< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( seed: Seed, a: S, b: S, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomSignedInclusiveRange { assert!(a < b); striped_random_signed_inclusive_range( seed, a, b - S::ONE, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped signeds in the range $[a, b)$. /// /// See [here](self) for more information. /// /// The unsigneds are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the signeds are constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::striped::striped_random_signed_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!( /// prefix_to_string( /// striped_random_signed_range::(EXAMPLE_SEED, -5, 11, 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[11111011, 11111100, 1000, 111, 11111111, 1000, 11, 1000, 0, 1000, ...]" /// ); /// ``` pub fn striped_random_signed_inclusive_range< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( seed: Seed, a: S, b: S, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomSignedInclusiveRange { assert!(a <= b); if a >= S::ZERO { StripedRandomSignedInclusiveRange::NonNegative( PhantomData, striped_random_unsigned_inclusive_range( seed, U::wrapping_from(a), U::wrapping_from(b), mean_stripe_numerator, mean_stripe_denominator, ), ) } else if b < S::ZERO { StripedRandomSignedInclusiveRange::Negative( PhantomData, striped_random_unsigned_inclusive_range( seed, U::wrapping_from(b.wrapping_neg()), U::wrapping_from(a.wrapping_neg()), mean_stripe_numerator, mean_stripe_denominator, ), ) } else { StripedRandomSignedInclusiveRange::Both( PhantomData, Box::new(random_bools(seed.fork("sign"))), striped_random_unsigned_inclusive_range( seed.fork("non-negative"), U::ZERO, U::wrapping_from(b), mean_stripe_numerator, mean_stripe_denominator, ), striped_random_unsigned_inclusive_range( seed.fork("negative"), U::ONE, U::wrapping_from(a.wrapping_neg()), mean_stripe_numerator, mean_stripe_denominator, ), ) } } ================================================ FILE: malachite-base/src/options/exhaustive.rs ================================================ // Copyright © 2026 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 core::iter::{Chain, Once, once}; /// Generates all [`Option`]s except `None`, with values from a given iterator. /// /// This `struct` is created by [`exhaustive_somes`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveSomes { xs: I, } impl Iterator for ExhaustiveSomes { type Item = Option; fn next(&mut self) -> Option> { self.xs.next().map(Some) } } /// Generates all [`Option`]s except `None`, with values from a given iterator. /// /// The elements of the given iterator are wrapped in `Some` and generated in the original order. /// /// The output length is `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::options::exhaustive::exhaustive_somes; /// /// assert_eq!( /// exhaustive_somes([1, 2, 3].iter().cloned()).collect_vec(), /// &[Some(1), Some(2), Some(3)] /// ); /// ``` #[inline] pub const fn exhaustive_somes(xs: I) -> ExhaustiveSomes { ExhaustiveSomes { xs } } /// Generates all [`Option`]s with values from a given iterator. /// /// `None` comes first, followed by the elements of the given iterator wrapped in `Some`. /// /// The output length is `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::options::exhaustive::exhaustive_options; /// /// assert_eq!( /// exhaustive_options([1, 2, 3].iter().cloned()).collect_vec(), /// &[None, Some(1), Some(2), Some(3)] /// ); /// ``` #[inline] pub fn exhaustive_options(xs: I) -> Chain>, ExhaustiveSomes> { once(None).chain(exhaustive_somes(xs)) } ================================================ FILE: malachite-base/src/options/mod.rs ================================================ // Copyright © 2026 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 core::str::FromStr; /// Converts a string to an `Option`, where `T` implements [`FromStr`]. /// /// If the string does not represent a valid `Option`, `None` is returned. /// /// If `T` does not implement [`FromStr`], try using [`option_from_str_custom`] instead. /// /// # Examples /// ``` /// use malachite_base::options::option_from_str; /// /// assert_eq!(option_from_str::("Some(false)"), Some(Some(false))); /// assert_eq!(option_from_str::("Some(5)"), Some(Some(5))); /// assert_eq!(option_from_str::("None"), Some(None)); /// assert_eq!(option_from_str::("Some(hi)"), None); /// assert_eq!(option_from_str::("abc"), None); /// ``` #[inline] pub fn option_from_str(src: &str) -> Option> { option_from_str_custom(&(|t| t.parse().ok()), src) } /// Converts a string to an `Option`, given a function to parse a string into a `T`. /// /// If the string does not represent a valid `Option`, `None` is returned. /// /// If `f` just uses the [`FromStr`] implementation on `T`, you can use [`option_from_str`] instead. /// /// # Examples /// ``` /// use malachite_base::options::{option_from_str, option_from_str_custom}; /// use malachite_base::orderings::ordering_from_str; /// use std::cmp::Ordering::{self, *}; /// /// assert_eq!( /// option_from_str_custom::(&ordering_from_str, "Some(Less)"), /// Some(Some(Less)) /// ); /// assert_eq!( /// option_from_str_custom::>(&option_from_str, "Some(Some(false))"), /// Some(Some(Some(false))) /// ); /// assert_eq!( /// option_from_str_custom::(&ordering_from_str, "Some(hi)"), /// None /// ); /// assert_eq!( /// option_from_str_custom::(&ordering_from_str, "abc"), /// None /// ); /// ``` pub fn option_from_str_custom(f: &dyn Fn(&str) -> Option, src: &str) -> Option> { if src == "None" { Some(None) } else if src.starts_with("Some(") && src.ends_with(')') { f(&src[5..src.len() - 1]).map(Some) } else { None } } /// Iterators that generate [`Option`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`Option`]s randomly. pub mod random; ================================================ FILE: malachite-base/src/options/random.rs ================================================ // Copyright © 2026 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 crate::bools::random::{WeightedRandomBools, weighted_random_bools}; use crate::random::Seed; /// Generates random [`Option`]s except `None`, with values from a given random iterator. /// /// This `struct` is created by [`random_somes`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomSomes { xs: I, } impl Iterator for RandomSomes { type Item = Option; #[inline] fn next(&mut self) -> Option> { Some(self.xs.next()) } } /// Generates random [`Option`]s except `None`, with values from a given random iterator. /// /// The values have the same distribution as the values generated by the given iterator: If $Q(x)$ /// is the probability of $x$ being generated by `xs`, then /// /// $P(\operatorname{Some}(x)) = Q(x)$. /// /// `xs` must be infinite. /// /// The output length is infinite. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::options::random::random_somes; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToDebugString; /// /// assert_eq!( /// prefix_to_string( /// random_somes(random_primitive_ints::(EXAMPLE_SEED)).map(|x| x.to_debug_string()), /// 5 /// ), /// "[Some(113), Some(239), Some(69), Some(108), Some(228), ...]", /// ) /// ``` pub const fn random_somes(xs: I) -> RandomSomes { RandomSomes { xs } } /// Generates random [`Option`]s with values from a given random iterator. /// /// We don't use [`WithSpecialValue`](crate::iterators::WithSpecialValue) here because that requires /// `I::Item` to be cloneable. The "special value" in this case, `None`, can be produced on demand /// without any cloning. /// /// This `struct` is created by [`random_options`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomOptions { bs: WeightedRandomBools, xs: I, } impl Iterator for RandomOptions { type Item = Option; #[inline] fn next(&mut self) -> Option> { Some(if self.bs.next().unwrap() { self.xs.next() } else { None }) } } /// Generates random [`Option`]s with values from a given random iterator. /// /// The probability of generating `None` is specified by $p$ = `none_p_numerator / /// none_p_denominator`. If a `Some` is generated, its values have the same distribution as the /// values generated by the given iterator. /// /// If $Q(x)$ is the probability of $x$ being generated by `xs`, then /// /// $P(\text{None}) = p$ /// /// $P(\operatorname{Some}(x)) = (1-p)Q(x)$ /// /// `xs` must be infinite. /// /// The output length is infinite. /// /// # Panics /// Panics if `none_p_denominator` is 0 or `none_p_numerator > none_p_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::options::random::random_options; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToDebugString; /// /// assert_eq!( /// prefix_to_string( /// random_options(EXAMPLE_SEED, 1, 2, &random_primitive_ints::) /// .map(|x| x.to_debug_string()), /// 10 /// ), /// "[Some(85), Some(11), Some(136), None, Some(200), None, Some(235), Some(134), Some(203), \ /// None, ...]" /// ) /// ``` pub fn random_options( seed: Seed, none_p_numerator: u64, none_p_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomOptions { RandomOptions { bs: weighted_random_bools( seed.fork("bs"), none_p_denominator - none_p_numerator, none_p_denominator, ), xs: xs_gen(seed.fork("xs")), } } ================================================ FILE: malachite-base/src/orderings/exhaustive.rs ================================================ // Copyright © 2026 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 crate::orderings::ORDERINGS; use core::cmp::Ordering::{self, *}; use core::iter::Copied; use core::slice::Iter; pub type ExhaustiveOrderings = Copied>; /// Generates all [`Ordering`]s, in increasing order. /// /// The output length is 3. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::orderings::exhaustive::orderings_increasing; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// orderings_increasing().collect_vec(), /// &[Less, Equal, Greater] /// ); /// ``` #[inline] pub fn orderings_increasing() -> ExhaustiveOrderings { [Less, Equal, Greater].iter().copied() } /// Generates all [`Ordering`]s, with `Equal` coming first. /// /// The output length is 3. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::orderings::exhaustive::exhaustive_orderings; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// exhaustive_orderings().collect_vec(), /// &[Equal, Less, Greater] /// ); /// ``` #[inline] pub fn exhaustive_orderings() -> Copied> { ORDERINGS.iter().copied() } ================================================ FILE: malachite-base/src/orderings/mod.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; pub(crate) const ORDERINGS: [Ordering; 3] = [Equal, Less, Greater]; /// Converts a string to an [`Ordering`]. /// /// If the string does not represent a valid [`Ordering`], `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::orderings::ordering_from_str; /// use std::cmp::Ordering::*; /// /// assert_eq!(ordering_from_str("Equal"), Some(Equal)); /// assert_eq!(ordering_from_str("Less"), Some(Less)); /// assert_eq!(ordering_from_str("Greater"), Some(Greater)); /// assert_eq!(ordering_from_str("abc"), None); /// ``` #[inline] pub fn ordering_from_str(src: &str) -> Option { match src { "Equal" => Some(Equal), "Less" => Some(Less), "Greater" => Some(Greater), _ => None, } } /// Iterators that generate [`Ordering`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`Ordering`]s randomly. pub mod random; ================================================ FILE: malachite-base/src/orderings/random.rs ================================================ // Copyright © 2026 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 crate::orderings::ORDERINGS; use crate::random::Seed; use crate::slices::{RandomValuesFromSlice, random_values_from_slice}; use std::cmp::Ordering; use std::iter::Copied; pub type RandomOrderings = Copied>; /// Generates a random [`Ordering`] that has an equal probability of being `Less`, `Greater`, or /// `Equal`. /// /// $P(<) = P(=) = P(>) = \frac{1}{3}$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::orderings::random::random_orderings; /// use malachite_base::random::EXAMPLE_SEED; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// random_orderings(EXAMPLE_SEED).take(10).collect_vec(), /// &[Less, Equal, Less, Greater, Less, Less, Equal, Less, Equal, Greater] /// ) /// ``` #[inline] pub fn random_orderings(seed: Seed) -> RandomOrderings { random_values_from_slice(seed, &ORDERINGS).copied() } ================================================ FILE: malachite-base/src/platform.rs ================================================ // Copyright © 2026 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 . #[cfg(not(feature = "std"))] #[macro_export] macro_rules! fma { ($a: expr, $b: expr, $c: expr) => {{ libm::fma($a, $b, $c) }}; } #[cfg(feature = "std")] #[macro_export] macro_rules! fma { ($a: expr, $b: expr, $c: expr) => {{ $a.mul_add($b, $c) }}; } pub use fma; #[cfg(not(feature = "std"))] #[macro_export] macro_rules! round_even { ($a: expr) => {{ libm::roundeven($a) }}; } #[cfg(feature = "std")] #[macro_export] macro_rules! round_even { ($a: expr) => {{ $a.round_ties_even() }}; } pub use round_even; ================================================ FILE: malachite-base/src/random/mod.rs ================================================ // Copyright © 2026 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 rand::{RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; use sha3::{Digest, Sha3_256}; /// A random seed used for reproducible testing. pub const EXAMPLE_SEED: Seed = Seed::from_bytes([ 0xbf, 0x18, 0x11, 0xce, 0x15, 0xee, 0xfd, 0x20, 0x2f, 0xdf, 0x67, 0x6a, 0x6b, 0xba, 0xaf, 0x04, 0xff, 0x71, 0xe0, 0xf8, 0x0b, 0x2a, 0xcf, 0x27, 0x85, 0xb3, 0x32, 0xc6, 0x20, 0x80, 0x5e, 0x36, ]); /// A type representing a random seed. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub struct Seed { pub bytes: [u8; 32], } impl Seed { /// Creates a `Seed` from a slice of 32 bytes. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::random::Seed; /// /// Seed::from_bytes([10; 32]); /// ``` #[inline] pub const fn from_bytes(bytes: [u8; 32]) -> Self { Self { bytes } } /// Creates a PRNG from a slice of 32 bytes. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::random::EXAMPLE_SEED; /// /// EXAMPLE_SEED.get_rng(); /// ``` #[inline] pub fn get_rng(self) -> ChaCha20Rng { ChaCha20Rng::from_seed(self.bytes) } /// Uniformly generates a random `Seed`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::random::Seed; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// EXAMPLE_SEED.next(), /// Seed::from_bytes([ /// 0x71, 0xef, 0x45, 0x6c, 0xe4, 0xd2, 0xa8, 0xa1, 0x57, 0x20, 0x6e, 0x53, 0xbc, 0x22, /// 0x59, 0xee, 0x5d, 0xc8, 0x95, 0x73, 0xbd, 0x95, 0xd9, 0xc9, 0x75, 0x92, 0x1f, 0x48, /// 0x97, 0xa9, 0xae, 0x21 /// ]) /// ); /// ``` #[inline] pub fn next(self) -> Self { let mut bytes = [0; 32]; self.get_rng().fill_bytes(&mut bytes); Self::from_bytes(bytes) } /// Generates a new `Seed` from this seed. Passing different `key`s will, with very high /// probability, generate different seeds. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::random::Seed; /// use malachite_base::random::EXAMPLE_SEED; /// /// assert_eq!( /// EXAMPLE_SEED.fork("first"), /// Seed::from_bytes([ /// 0x20, 0x18, 0x1, 0x3d, 0x96, 0x4d, 0x3e, 0x98, 0x10, 0x9d, 0x35, 0x75, 0x22, 0x89, /// 0xf7, 0xe9, 0xbe, 0x2f, 0x9c, 0x15, 0x95, 0x42, 0x1a, 0x79, 0x52, 0xf, 0x56, 0x9a, /// 0x7b, 0x8c, 0xd9, 0x34 /// ]) /// ); /// assert_eq!( /// EXAMPLE_SEED.fork("second"), /// Seed::from_bytes([ /// 0xe0, 0x36, 0x88, 0x58, 0x6d, 0x67, 0x33, 0xea, 0xf2, 0x1c, 0x88, 0xf9, 0xe3, 0xbd, /// 0x52, 0xc0, 0xe5, 0xad, 0x61, 0x81, 0x21, 0xd8, 0x2f, 0x8e, 0xcd, 0xf, 0x89, 0x9d, /// 0x32, 0xc5, 0x35, 0x83 /// ]) /// ); /// ``` pub fn fork(&self, key: &str) -> Self { let mut seed = self.next(); let forked_seed = &mut seed.bytes; let hash = Sha3_256::digest(key.as_bytes()); for i in 0..32 { forked_seed[i] ^= hash[i]; } seed.next() } } ================================================ FILE: malachite-base/src/rational_sequences/access.rs ================================================ // Copyright © 2026 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 crate::rational_sequences::{RationalSequence, rational_sequence_reduce}; use core::ops::Index; impl Index for RationalSequence { type Output = T; /// Gets a reference to an element of a [`RationalSequence`] at an index. /// /// If the index is greater than or equal to the length of the sequence, this function panics. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `index` is greater than or equal to the length of this sequence. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::from_slices(&[1, 2], &[3, 4])[1], 2); /// assert_eq!(RationalSequence::from_slices(&[1, 2], &[3, 4])[10], 3); /// ``` #[inline] fn index(&self, i: usize) -> &T { self.get(i).unwrap() } } impl RationalSequence { /// Gets a reference to an element of a [`RationalSequence`] at an index. /// /// If the index is greater than or equal to the length of the sequence, `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::from_slices(&[1, 2], &[3, 4]).get(1), /// Some(&2) /// ); /// assert_eq!( /// RationalSequence::from_slices(&[1, 2], &[3, 4]).get(10), /// Some(&3) /// ); /// ``` pub fn get(&self, i: usize) -> Option<&T> { let non_repeating_len = self.non_repeating.len(); if i < non_repeating_len { Some(&self.non_repeating[i]) } else if self.repeating.is_empty() { None } else { Some(&self.repeating[(i - non_repeating_len) % self.repeating.len()]) } } } impl RationalSequence { /// Mutates an element of a [`RationalSequence`] at an index using a provided closure, and then /// returns whatever the closure returns. /// /// If the index is greater than or equal to the length of the sequence, this function panics. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `index`. /// /// # Panics /// Panics if `index` is greater than or equal to the length of this sequence. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// let mut xs = RationalSequence::from_slices(&[1, 2], &[3, 4]); /// assert_eq!( /// xs.mutate(1, |x| { /// *x = 100; /// 25 /// }), /// 25 /// ); /// assert_eq!(xs, RationalSequence::from_slices(&[1, 100], &[3, 4])); /// /// let mut xs = RationalSequence::from_slices(&[1, 2], &[3, 4]); /// assert_eq!( /// xs.mutate(6, |x| { /// *x = 100; /// 25 /// }), /// 25 /// ); /// assert_eq!( /// xs, /// RationalSequence::from_slices(&[1, 2, 3, 4, 3, 4, 100], &[4, 3]) /// ); /// ``` pub fn mutate U, U>(&mut self, i: usize, f: F) -> U { let non_repeating_len = self.non_repeating.len(); let result = if i < non_repeating_len { f(&mut self.non_repeating[i]) } else if self.repeating.is_empty() { panic!("index out of bounds"); } else { let repeating_len = self.repeating.len(); let extra = i - non_repeating_len + 1; self.non_repeating .extend(self.repeating.iter().cycle().take(extra).cloned()); self.repeating.rotate_left(extra % repeating_len); f(&mut self.non_repeating[i]) }; rational_sequence_reduce(&mut self.non_repeating, &mut self.repeating); result } } ================================================ FILE: malachite-base/src/rational_sequences/cmp.rs ================================================ // Copyright © 2026 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 crate::rational_sequences::RationalSequence; use core::cmp::Ordering::{self, *}; impl PartialOrd for RationalSequence { /// Compares a [`RationalSequence`] to another [`RationalSequence`]. /// /// See [here](RationalSequence::cmp) for more information. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for RationalSequence { /// Compares a [`RationalSequence`] to another [`RationalSequence`]. /// /// The comparison is made lexicographically with respect to the element type's ordering. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.component_len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert!( /// RationalSequence::from_slice(&[1, 2]) < RationalSequence::from_slices(&[1, 2], &[1]) /// ); /// assert!( /// RationalSequence::from_slice(&[1, 2, 3]) /// < RationalSequence::from_slices(&[1, 2], &[3, 4]) /// ); /// ``` fn cmp(&self, other: &Self) -> Ordering { if self == other { Equal } else { Iterator::cmp(self.iter(), other.iter()) } } } ================================================ FILE: malachite-base/src/rational_sequences/conversion.rs ================================================ // Copyright © 2026 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 crate::rational_sequences::{RationalSequence, rational_sequence_reduce}; use alloc::vec; use alloc::vec::Vec; impl RationalSequence { /// Converts a [`Vec`] to a finite [`RationalSequence`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_vec(vec![]).to_string(), "[]"); /// assert_eq!( /// RationalSequence::::from_vec(vec![1, 2]).to_string(), /// "[1, 2]" /// ); /// ``` pub const fn from_vec(non_repeating: Vec) -> Self { Self { non_repeating, repeating: vec![], } } /// Converts two [`Vec`]s to a finite [`RationalSequence`]. The first [`Vec`] is the /// nonrepeating part and the second is the repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(n + m^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n, m) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `non_repeating.len()`, and $m$ is /// `repeating.len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![]).to_string(), /// "[]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![1, 2]).to_string(), /// "[[1, 2]]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![]).to_string(), /// "[1, 2]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![3, 4]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2, 3], vec![4, 3]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// ``` pub fn from_vecs(mut non_repeating: Vec, mut repeating: Vec) -> Self { rational_sequence_reduce(&mut non_repeating, &mut repeating); Self { non_repeating, repeating, } } /// Converts a [`RationalSequence`] to a pair of [`Vec`]s containing the non-repeating and /// repeating parts, taking the [`RationalSequence`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::from_slices(&[1, 2], &[3, 4]).into_vecs(), /// (vec![1, 2], vec![3, 4]) /// ); /// ``` #[allow(clippy::missing_const_for_fn)] // can't be const because of destructors pub fn into_vecs(self) -> (Vec, Vec) { (self.non_repeating, self.repeating) } /// Returns references to the non-repeating and repeating parts of a [`RationalSequence`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::from_slices(&[1u8, 2], &[3, 4]).slices_ref(), /// (&[1u8, 2][..], &[3u8, 4][..]) /// ); /// ``` #[allow(clippy::missing_const_for_fn)] pub fn slices_ref(&self) -> (&[T], &[T]) { (&self.non_repeating, &self.repeating) } } impl RationalSequence { /// Converts a slice to a finite [`RationalSequence`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_slice(&[]).to_string(), "[]"); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2]).to_string(), /// "[1, 2]" /// ); /// ``` pub fn from_slice(non_repeating: &[T]) -> Self { Self { non_repeating: non_repeating.to_vec(), repeating: vec![], } } /// Converts two slices to a finite [`RationalSequence`]. The first slice is the nonrepeating /// part and the second is the repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(n + m^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `non_repeating.len()`, and $m$ is /// `repeating.len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::::from_slices(&[], &[]).to_string(), /// "[]" /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[1, 2]).to_string(), /// "[[1, 2]]" /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[]).to_string(), /// "[1, 2]" /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2, 3], &[4, 3]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// ``` pub fn from_slices(non_repeating: &[T], repeating: &[T]) -> Self { let mut non_repeating = non_repeating.to_vec(); let mut repeating = repeating.to_vec(); rational_sequence_reduce(&mut non_repeating, &mut repeating); Self { non_repeating, repeating, } } /// Converts a [`RationalSequence`] to a pair of [`Vec`]s containing the non-repeating and /// repeating parts, taking the [`RationalSequence`] by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.component_len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::from_slices(&[1, 2], &[3, 4]).to_vecs(), /// (vec![1, 2], vec![3, 4]) /// ); /// ``` pub fn to_vecs(&self) -> (Vec, Vec) { (self.non_repeating.clone(), self.repeating.clone()) } } ================================================ FILE: malachite-base/src/rational_sequences/exhaustive.rs ================================================ // Copyright © 2026 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 crate::num::exhaustive::PrimitiveIntIncreasingRange; use crate::rational_sequences::{RationalSequence, rational_sequence_is_reduced}; use crate::tuples::exhaustive::{ExhaustivePairs1Input, exhaustive_pairs_from_single}; use crate::vecs::exhaustive::{ExhaustiveVecs, exhaustive_vecs}; /// Generates all [`RationalSequence`]s containing elements from an iterator. /// /// This `struct` is created by [`exhaustive_rational_sequences`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveRationalSequences( ExhaustivePairs1Input, I>>, ) where I::Item: Clone; impl Iterator for ExhaustiveRationalSequences where I::Item: Clone + Eq, { type Item = RationalSequence; fn next(&mut self) -> Option> { loop { let (non_repeating, repeating) = self.0.next()?; if rational_sequence_is_reduced(&non_repeating, &repeating) { return Some(RationalSequence { non_repeating, repeating, }); } } } } /// Generates all [`RationalSequence`]s containing elements from a given iterator. /// /// The input iterator should contain no repetitions, but this is not enforced. /// /// The output length is 1 if the input iterator is empty, and infinite otherwise. /// /// # Worst-case complexity per iteration /// $T(i) = O(T^\prime(i) + (\log i)^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(i) = O((\log i) M^\prime(i))$ /// /// where $T$ is time, $M$ is additional memory, and $T^\prime$ and $M^\prime$ are the time and /// memory functions of the input iterator. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// use malachite_base::rational_sequences::exhaustive::exhaustive_rational_sequences; /// use malachite_base::strings::ToDebugString; /// /// assert_eq!( /// exhaustive_rational_sequences(exhaustive_unsigneds::()) /// .take(10) /// .collect_vec() /// .to_debug_string(), /// "[[], [[0]], [0], [[1]], [0, [1]], [1], [1, [0]], [0, 0, 0], [0, 0, 0, [1]], [[2]]]" /// ) /// ``` pub fn exhaustive_rational_sequences(xs: I) -> ExhaustiveRationalSequences where I::Item: Clone + Eq, { ExhaustiveRationalSequences(exhaustive_pairs_from_single(exhaustive_vecs(xs))) } ================================================ FILE: malachite-base/src/rational_sequences/mod.rs ================================================ // Copyright © 2026 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 crate::slices::min_repeating_len; use alloc::vec::Vec; use core::iter::{Chain, Cycle}; fn rational_sequence_reduce(non_repeating: &mut Vec, repeating: &mut Vec) { if repeating.is_empty() { return; } repeating.truncate(min_repeating_len(repeating)); if non_repeating.is_empty() { return; } let extra_non_repeating = non_repeating .iter() .rev() .zip(repeating.iter().rev().cycle()) .take_while(|(x, y)| x == y) .count(); if extra_non_repeating != 0 { non_repeating.truncate(non_repeating.len() - extra_non_repeating); let len = repeating.len(); repeating.rotate_right(extra_non_repeating % len); } } pub_test! {rational_sequence_is_reduced(non_repeating: &[T], repeating: &[T]) -> bool { if repeating.is_empty() { return true; } if min_repeating_len(repeating) != repeating.len() { return false; } if non_repeating.is_empty() { return true; } non_repeating .iter() .rev() .zip(repeating.iter().rev().cycle()) .take_while(|(x, y)| x == y) .count() == 0 }} /// A `RationalSequence` is a sequence that is either finite or eventually repeating, just like the /// digits of a rational number. /// /// In testing, the set of rational sequences may be used as a proxy for the set of all sequences, /// which is too large to work with. #[derive(Clone, Default, Eq, Hash, PartialEq)] pub struct RationalSequence { non_repeating: Vec, repeating: Vec, } impl RationalSequence { /// Returns whether this `RationalSequence` is empty. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_slice(&[]).is_empty(), true); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2, 3]).is_empty(), /// false /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[3, 4]).is_empty(), /// false /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]).is_empty(), /// false /// ); /// ``` pub const fn is_empty(&self) -> bool { self.non_repeating.is_empty() && self.repeating.is_empty() } /// Returns whether this `RationalSequence` is finite (has no repeating part). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_slice(&[]).is_finite(), true); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2, 3]).is_finite(), /// true /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[3, 4]).is_finite(), /// false /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]).is_finite(), /// false /// ); /// ``` pub const fn is_finite(&self) -> bool { self.repeating.is_empty() } /// Returns the length of this `RationalSequence`. If the sequence is infinite, `None` is /// returned. /// /// For a measure of length that always exists, try [`component_len`](Self::component_len). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_slice(&[]).len(), Some(0)); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2, 3]).len(), /// Some(3) /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[3, 4]).len(), /// None /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]).len(), /// None /// ); /// ``` pub const fn len(&self) -> Option { if self.repeating.is_empty() { Some(self.non_repeating.len()) } else { None } } /// Returns the sum of the lengths of the non-repeating and repeating parts of this /// `RationalSequence`. /// /// This is often a more useful way of measuring the complexity of a sequence than /// [`len`](Self::len). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!(RationalSequence::::from_slice(&[]).component_len(), 0); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2, 3]).component_len(), /// 3 /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[3, 4]).component_len(), /// 2 /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]).component_len(), /// 4 /// ); /// ``` pub const fn component_len(&self) -> usize { self.non_repeating.len() + self.repeating.len() } /// Returns an iterator of references to the elements of this sequence. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::rational_sequences::RationalSequence; /// /// let empty: &[u8] = &[]; /// assert_eq!( /// RationalSequence::::from_slice(empty) /// .iter() /// .cloned() /// .collect_vec(), /// empty /// ); /// assert_eq!( /// RationalSequence::::from_slice(&[1, 2, 3]) /// .iter() /// .cloned() /// .collect_vec(), /// &[1, 2, 3] /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[], &[3, 4]) /// .iter() /// .cloned() /// .take(10) /// .collect_vec(), /// &[3, 4, 3, 4, 3, 4, 3, 4, 3, 4] /// ); /// assert_eq!( /// RationalSequence::::from_slices(&[1, 2], &[3, 4]) /// .iter() /// .cloned() /// .take(10) /// .collect_vec(), /// &[1, 2, 3, 4, 3, 4, 3, 4, 3, 4] /// ); /// ``` pub fn iter(&self) -> Chain, Cycle>> { self.non_repeating .iter() .chain(self.repeating.iter().cycle()) } } impl RationalSequence { // Returns true iff `self` is valid. // // To be valid, the non-repeating and repeating parts must be reduced. For example, `[1, 2]` and // `[3, 4]` is a reduced pair. On the other hand, `[1, 2]` and `[3, 4, 3, 4]` is a non-reduced // pair representing the same sequence, as is `[1, 2, 3]` and `[4, 3]`. All `RationalSequence`s // must be valid. #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { rational_sequence_is_reduced(&self.non_repeating, &self.repeating) } } /// Functions for getting and setting elements in a [`RationalSequence`]. pub mod access; /// Functions for comparing [`RationalSequence`]s. pub mod cmp; /// Functions for converting a [`RationalSequence`]s to and from a [`Vec`] or a slice. pub mod conversion; /// Functions for generating all [`RationalSequence`]s over a set of elements. pub mod exhaustive; #[cfg(feature = "random")] /// Functions for generating random [`RationalSequence`]s from a set of elements. pub mod random; /// Functions for displaying a [`RationalSequence`]. pub mod to_string; ================================================ FILE: malachite-base/src/rational_sequences/random.rs ================================================ // Copyright © 2026 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 crate::num::random::geometric::GeometricRandomNaturalValues; use crate::random::Seed; use crate::rational_sequences::RationalSequence; use crate::vecs::random::{RandomVecs, random_vecs}; /// Generates random [`RationalSequence`]s, given an iterator of random elements. /// /// This `struct` is created by [`random_rational_sequences`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomRationalSequences( RandomVecs, I>, ) where I::Item: Eq; impl Iterator for RandomRationalSequences where I::Item: Eq, { type Item = RationalSequence; fn next(&mut self) -> Option> { Some(RationalSequence::from_vecs( self.0.next().unwrap(), self.0.next().unwrap(), )) } } /// Generates random [`RationalSequence`]s whose non-repeating and repeating components have a /// specified mean length, with elements from a given iterator. /// /// The input iterator must be infinite, but this is not enforced. /// /// The output length is infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::rational_sequences::random::random_rational_sequences; /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// random_rational_sequences(EXAMPLE_SEED, &random_primitive_ints::, 4, 1) /// .take(10) /// .map(|x| RationalSequence::to_string(&x)) /// .collect_vec(), /// &[ /// "[[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32]]", /// "[166, 234, 30, 218, [90, 106, 9, 216]]", /// "[204]", /// "[151, 213, 97, 253, 78, [91, 39]]", /// "[191, 175, 170, 232]", /// "[233, 2, 35, 22, 217, 198]", /// "[[114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144]]", /// "[148, 79, 115, 52, 73, 69, 137, 91]", /// "[153, 178, 112]", /// "[34, 95, 106, 167, 197, [130, 168, 122, 207, 172, 177, 86, 150, 221]]" /// ] /// ) /// ``` pub fn random_rational_sequences( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomRationalSequences where I::Item: Eq, { RandomRationalSequences(random_vecs( seed, xs_gen, mean_length_numerator, mean_length_denominator, )) } ================================================ FILE: malachite-base/src/rational_sequences/to_string.rs ================================================ // Copyright © 2026 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 crate::rational_sequences::RationalSequence; use core::fmt::{Debug, Display, Formatter, Result, Write}; impl Display for RationalSequence { /// Converts a [`RationalSequence`] to a [`String`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.component_len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![]).to_string(), /// "[]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![1, 2]).to_string(), /// "[[1, 2]]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![]).to_string(), /// "[1, 2]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![3, 4]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { f.write_char('[')?; let mut first = true; for x in &self.non_repeating { if first { first = false; } else { f.write_str(", ")?; } Display::fmt(x, f)?; } if !self.repeating.is_empty() { if !self.non_repeating.is_empty() { f.write_str(", ")?; } f.write_char('[')?; let mut first = true; for x in &self.repeating { if first { first = false; } else { f.write_str(", ")?; } Display::fmt(x, f)?; } f.write_char(']')?; } f.write_char(']') } } impl Debug for RationalSequence { /// Converts a [`RationalSequence`] to a [`String`]. /// /// This is the same implementation as for [`Display`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.component_len()`. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// use malachite_base::strings::ToDebugString; /// /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![]).to_debug_string(), /// "[]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![], vec![1, 2]).to_debug_string(), /// "[[1, 2]]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![]).to_debug_string(), /// "[1, 2]" /// ); /// assert_eq!( /// RationalSequence::::from_vecs(vec![1, 2], vec![3, 4]).to_string(), /// "[1, 2, [3, 4]]" /// ); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } ================================================ FILE: malachite-base/src/rounding_modes/exhaustive.rs ================================================ // Copyright © 2026 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 crate::rounding_modes::{ROUNDING_MODES, RoundingMode}; use core::iter::Copied; use core::slice::Iter; pub type ExhaustiveRoundingModes = Copied>; /// Generates all [`RoundingMode`]s. /// /// The output length is 6. /// /// # Complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// assert_eq!( /// exhaustive_rounding_modes().collect_vec(), /// &[Down, Up, Floor, Ceiling, Nearest, Exact,] /// ); /// ``` #[inline] pub fn exhaustive_rounding_modes() -> ExhaustiveRoundingModes { ROUNDING_MODES.iter().copied() } ================================================ FILE: malachite-base/src/rounding_modes/from_str.rs ================================================ // Copyright © 2026 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 crate::rounding_modes::RoundingMode::{self, *}; use alloc::string::String; use alloc::string::ToString; use core::str::FromStr; impl FromStr for RoundingMode { type Err = String; /// Converts a string to a [`RoundingMode`]. /// /// If the string does not represent a valid [`RoundingMode`], an `Err` is returned with the /// unparseable string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ = `src.len()`. /// /// The worst case occurs when the input string is invalid and must be copied into an `Err`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use std::str::FromStr; /// /// assert_eq!(RoundingMode::from_str("Down"), Ok(Down)); /// assert_eq!(RoundingMode::from_str("Up"), Ok(Up)); /// assert_eq!(RoundingMode::from_str("Floor"), Ok(Floor)); /// assert_eq!(RoundingMode::from_str("Ceiling"), Ok(Ceiling)); /// assert_eq!(RoundingMode::from_str("Nearest"), Ok(Nearest)); /// assert_eq!(RoundingMode::from_str("Exact"), Ok(Exact)); /// assert_eq!(RoundingMode::from_str("abc"), Err("abc".to_string())); /// ``` #[inline] fn from_str(src: &str) -> Result { match src { "Down" => Ok(Down), "Up" => Ok(Up), "Floor" => Ok(Floor), "Ceiling" => Ok(Ceiling), "Nearest" => Ok(Nearest), "Exact" => Ok(Exact), _ => Err(src.to_string()), } } } ================================================ FILE: malachite-base/src/rounding_modes/mod.rs ================================================ // Copyright © 2026 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 crate::named::Named; use crate::rounding_modes::RoundingMode::*; /// An enum that specifies how a value should be rounded. /// /// A `RoundingMode` can often be specified when a function conceptually returns a value of one /// type, but must be rounded to another type. The most common case is a conceptually real-valued /// function whose result must be rounded to an integer, like /// [`div_round`](crate::num::arithmetic::traits::DivRound::div_round). /// /// # Examples /// Here are some examples of how floating-point values would be rounded to integer values using the /// different `RoundingMode`s. /// /// | x | `Floor` | `Ceiling` | `Down` | `Up` | `Nearest` | `Exact` | /// |------|---------|-----------|--------|------|-----------|------------| /// | 3.0 | 3 | 3 | 3 | 3 | 3 | 3 | /// | 3.2 | 3 | 4 | 3 | 4 | 3 | `panic!()` | /// | 3.8 | 3 | 4 | 3 | 4 | 4 | `panic!()` | /// | 3.5 | 3 | 4 | 3 | 4 | 4 | `panic!()` | /// | 4.5 | 4 | 5 | 4 | 5 | 4 | `panic!()` | /// | -3.2 | -4 | -3 | -3 | -4 | -3 | `panic!()` | /// | -3.8 | -4 | -3 | -3 | -4 | -4 | `panic!()` | /// | -3.5 | -4 | -3 | -3 | -4 | -4 | `panic!()` | /// | -4.5 | -5 | -4 | -4 | -5 | -4 | `panic!()` | /// /// Sometimes a `RoundingMode` is used in an unusual context, such as rounding an integer to a /// floating-point number, in which case further explanation of its behavior is provided at the /// usage site. /// /// A `RoundingMode` takes up 1 byte of space. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum RoundingMode { /// Applies the function $x \mapsto \operatorname{sgn}(x) \lfloor |x| \rfloor$. In other words, /// the value is rounded towards 0. Down, /// Applies the function $x \mapsto \operatorname{sgn}(x) \lceil |x| \rceil$. In other words, /// the value is rounded away from 0. Up, /// Applies the floor function: $x \mapsto \lfloor x \rfloor$. In other words, the value is /// rounded towards $-\infty$. Floor, /// Applies the ceiling function: $x \mapsto \lceil x \rceil$. In other words, the value is /// rounded towards $\infty$. Ceiling, /// Applies the function /// $$ /// x \mapsto \\begin{cases} /// \lfloor x \rfloor & x - \lfloor x \rfloor < \frac{1}{2} \\\\ /// \lceil x \rceil & x - \lfloor x \rfloor > \frac{1}{2} \\\\ /// \lfloor x \rfloor & /// x - \lfloor x \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor x \rfloor \\ \text{is even} \\\\ /// \lceil x \rceil & /// x - \lfloor x \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor x \rfloor \\ \text{is odd.} /// \\end{cases} /// $$ /// In other words, it rounds to the nearest integer, and when there's a tie, it rounds to the /// nearest even integer. This is also called _bankers' rounding_ and is often used as a /// default. Nearest, /// Panics if the value is not already rounded. Exact, } impl_named!(RoundingMode); /// A list of all six rounding modes. pub const ROUNDING_MODES: [RoundingMode; 6] = [Down, Up, Floor, Ceiling, Nearest, Exact]; /// Iterators that generate [`RoundingMode`]s without repetition. pub mod exhaustive; /// Functions for converting a string to a [`RoundingMode`]. pub mod from_str; /// Functions for negating a [`RoundingMode`]. pub mod neg; #[cfg(feature = "random")] /// Iterators that generate [`RoundingMode`]s randomly. pub mod random; /// Functions for displaying a [`RoundingMode`]. pub mod to_string; ================================================ FILE: malachite-base/src/rounding_modes/neg.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::NegAssign; use crate::rounding_modes::RoundingMode::{self, *}; use core::ops::Neg; /// Returns the negative of a [`RoundingMode`]. /// /// The negative is defined so that if a [`RoundingMode`] $m$ is used to round the result of an odd /// function $f$, then $f(x, -m) = -f(-x, m)$. `Floor` and `Ceiling` are swapped, and the other /// modes are unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// /// assert_eq!(-Down, Down); /// assert_eq!(-Up, Up); /// assert_eq!(-Floor, Ceiling); /// assert_eq!(-Ceiling, Floor); /// assert_eq!(-Nearest, Nearest); /// assert_eq!(-Exact, Exact); /// ``` impl Neg for RoundingMode { type Output = Self; #[inline] fn neg(self) -> Self { match self { Floor => Ceiling, Ceiling => Floor, rm => rm, } } } impl NegAssign for RoundingMode { /// Replaces a [`RoundingMode`] with its negative. /// /// The negative is defined so that if a [`RoundingMode`] $m$ is used to round the result of an /// odd function $f$, then $f(x, -m) = -f(-x, m)$. `Floor` and `Ceiling` are swapped, and the /// other modes are unchanged. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// let mut rm = Down; /// rm.neg_assign(); /// assert_eq!(rm, Down); /// /// let mut rm = Floor; /// rm.neg_assign(); /// assert_eq!(rm, Ceiling); /// ``` #[inline] fn neg_assign(&mut self) { if *self == Floor { *self = Ceiling; } else if *self == Ceiling { *self = Floor; } } } ================================================ FILE: malachite-base/src/rounding_modes/random.rs ================================================ // Copyright © 2026 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 crate::random::Seed; use crate::rounding_modes::{ROUNDING_MODES, RoundingMode}; use crate::slices::{RandomValuesFromSlice, random_values_from_slice}; use std::iter::Copied; /// Uniformly generates random [`RoundingMode`]s. pub type RandomRoundingModes = Copied>; /// Uniformly generates random [`RoundingMode`]s. /// /// The output length is infinite. /// /// # Expected complexity /// /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::rounding_modes::random::random_rounding_modes; /// use malachite_base::rounding_modes::RoundingMode::*; /// /// assert_eq!( /// random_rounding_modes(EXAMPLE_SEED).take(10).collect_vec(), /// &[Up, Exact, Ceiling, Up, Floor, Nearest, Exact, Up, Floor, Exact] /// ) /// ``` #[inline] pub fn random_rounding_modes(seed: Seed) -> RandomRoundingModes { random_values_from_slice(seed, &ROUNDING_MODES).copied() } ================================================ FILE: malachite-base/src/rounding_modes/to_string.rs ================================================ // Copyright © 2026 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 crate::rounding_modes::RoundingMode; use core::fmt::{Debug, Display, Formatter, Result}; impl Display for RoundingMode { /// Converts a [`RoundingMode`] to a [`String`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// /// assert_eq!(Down.to_string(), "Down"); /// assert_eq!(Up.to_string(), "Up"); /// assert_eq!(Floor.to_string(), "Floor"); /// assert_eq!(Ceiling.to_string(), "Ceiling"); /// assert_eq!(Nearest.to_string(), "Nearest"); /// assert_eq!(Exact.to_string(), "Exact"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Debug::fmt(self, f) } } ================================================ FILE: malachite-base/src/sets/exhaustive.rs ================================================ // Copyright © 2026 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 crate::vecs::exhaustive::{ ExhaustiveOrderedUniqueCollections, LexFixedLengthOrderedUniqueCollections, LexOrderedUniqueCollections, ShortlexOrderedUniqueCollections, }; #[cfg(not(feature = "std"))] use alloc::collections::BTreeSet; use core::hash::Hash; #[cfg(not(feature = "std"))] use hashbrown::HashSet; #[cfg(feature = "std")] use std::collections::{BTreeSet, HashSet}; /// Generates [`HashSet`]s of a given size with elements from a single iterator. /// /// The [`HashSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`HashSet`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_hash_sets_fixed_length; /// use maplit::hashset; /// /// let xss = lex_hash_sets_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2, 3, 4}, /// hashset! {1, 2, 3, 5}, /// hashset! {1, 2, 3, 6}, /// hashset! {1, 2, 4, 5}, /// hashset! {1, 2, 4, 6}, /// hashset! {1, 2, 5, 6}, /// hashset! {1, 3, 4, 5}, /// hashset! {1, 3, 4, 6}, /// hashset! {1, 3, 5, 6}, /// hashset! {1, 4, 5, 6}, /// hashset! {2, 3, 4, 5}, /// hashset! {2, 3, 4, 6}, /// hashset! {2, 3, 5, 6}, /// hashset! {2, 4, 5, 6}, /// hashset! {3, 4, 5, 6} /// ] /// ); /// ``` #[inline] pub fn lex_hash_sets_fixed_length( k: u64, xs: I, ) -> LexFixedLengthOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { LexFixedLengthOrderedUniqueCollections::new(k, xs) } /// Generates [`HashSet`]s with elements from a single iterator. /// /// The [`HashSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`HashSet`]s of length 2 and above will never /// be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`HashSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_hash_sets; /// use maplit::hashset; /// /// let xss = shortlex_hash_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {}, /// hashset! {1}, /// hashset! {2}, /// hashset! {3}, /// hashset! {4}, /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// hashset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn shortlex_hash_sets( xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { shortlex_hash_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`HashSet`]s with a mininum length, with elements from a single iterator. /// /// The [`HashSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`HashSet`]s of length `\max(2, \ell + 1)` and /// above will never be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_hash_sets_min_length; /// use maplit::hashset; /// /// let xss = shortlex_hash_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// hashset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn shortlex_hash_sets_min_length( min_length: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { shortlex_hash_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`HashSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The [`HashSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`HashSet`]s of length `\max(2, a + 1)` and /// above will never be generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_hash_sets_length_range; /// use maplit::hashset; /// /// let xss = shortlex_hash_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// ] /// ); /// ``` #[inline] pub fn shortlex_hash_sets_length_range( mut a: u64, mut b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } shortlex_hash_sets_length_inclusive_range(a, b - 1, xs) } /// Generates [`HashSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The [`HashSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`HashSet`]s of length `\max(2, a + 1)` and /// above will never be generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_hash_sets_length_inclusive_range; /// use maplit::hashset; /// /// let xss = shortlex_hash_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// ] /// ); /// ``` #[inline] pub fn shortlex_hash_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { ShortlexOrderedUniqueCollections::new(a, b, xs) } /// Generates [`HashSet`]s with elements from a single iterator. /// /// The [`HashSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`HashSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_hash_sets; /// use maplit::hashset; /// /// let xss = lex_hash_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {}, /// hashset! {1}, /// hashset! {1, 2}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 3, 4}, /// hashset! {1, 2, 4}, /// hashset! {1, 3}, /// hashset! {1, 3, 4}, /// hashset! {1, 4}, /// hashset! {2}, /// hashset! {2, 3}, /// hashset! {2, 3, 4}, /// hashset! {2, 4}, /// hashset! {3}, /// hashset! {3, 4}, /// hashset! {4} /// ] /// ); /// ``` #[inline] pub fn lex_hash_sets(xs: I) -> LexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { lex_hash_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`HashSet`]s with a mininum length, with elements from a single iterator. /// /// The [`HashSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_hash_sets_min_length; /// use maplit::hashset; /// /// let xss = lex_hash_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 3, 4}, /// hashset! {1, 2, 4}, /// hashset! {1, 3}, /// hashset! {1, 3, 4}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 3, 4}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_hash_sets_min_length( min_length: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { lex_hash_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`HashSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The [`HashSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_hash_sets_length_range; /// use maplit::hashset; /// /// let xss = lex_hash_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3}, /// hashset! {1, 3, 4}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 3, 4}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_hash_sets_length_range( mut a: u64, mut b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } lex_hash_sets_length_inclusive_range(a, b - 1, xs) } /// Generates [`HashSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The [`HashSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_hash_sets_length_inclusive_range; /// use maplit::hashset; /// /// let xss = lex_hash_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 2, 3}, /// hashset! {1, 2, 4}, /// hashset! {1, 3}, /// hashset! {1, 3, 4}, /// hashset! {1, 4}, /// hashset! {2, 3}, /// hashset! {2, 3, 4}, /// hashset! {2, 4}, /// hashset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_hash_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { LexOrderedUniqueCollections::new(a, b, xs) } /// Generates [`HashSet`]s of a given size with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`HashSet`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_hash_sets_fixed_length; /// use maplit::hashset; /// /// let xss = exhaustive_hash_sets_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2, 3, 4}, /// hashset! {1, 2, 3, 5}, /// hashset! {1, 2, 4, 5}, /// hashset! {1, 3, 4, 5}, /// hashset! {2, 3, 4, 5}, /// hashset! {1, 2, 3, 6}, /// hashset! {1, 2, 4, 6}, /// hashset! {1, 3, 4, 6}, /// hashset! {2, 3, 4, 6}, /// hashset! {1, 2, 5, 6}, /// hashset! {1, 3, 5, 6}, /// hashset! {2, 3, 5, 6}, /// hashset! {1, 4, 5, 6}, /// hashset! {2, 4, 5, 6}, /// hashset! {3, 4, 5, 6} /// ] /// ); /// ``` #[inline] pub fn exhaustive_hash_sets_fixed_length( k: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { exhaustive_hash_sets_length_inclusive_range(k, k, xs) } /// Generates [`HashSet`]s with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`HashSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_hash_sets; /// use maplit::hashset; /// /// let xss = exhaustive_hash_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {}, /// hashset! {1}, /// hashset! {2}, /// hashset! {1, 2}, /// hashset! {3}, /// hashset! {1, 3}, /// hashset! {2, 3}, /// hashset! {1, 2, 3}, /// hashset! {4}, /// hashset! {1, 4}, /// hashset! {2, 4}, /// hashset! {1, 2, 4}, /// hashset! {3, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// hashset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_hash_sets( xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { exhaustive_hash_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`HashSet`]s with a mininum length, with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_hash_sets_min_length; /// use maplit::hashset; /// /// let xss = exhaustive_hash_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {2, 3}, /// hashset! {1, 2, 3}, /// hashset! {1, 4}, /// hashset! {2, 4}, /// hashset! {1, 2, 4}, /// hashset! {3, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4}, /// hashset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_hash_sets_min_length( min_length: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { exhaustive_hash_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`HashSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_hash_sets_length_range; /// use maplit::hashset; /// /// let xss = exhaustive_hash_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {2, 3}, /// hashset! {1, 2, 3}, /// hashset! {1, 4}, /// hashset! {2, 4}, /// hashset! {1, 2, 4}, /// hashset! {3, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_hash_sets_length_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { if a >= b { ExhaustiveOrderedUniqueCollections::None } else { exhaustive_hash_sets_length_inclusive_range(a, b - 1, xs) } } /// Generates [`HashSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`HashSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_hash_sets_length_inclusive_range; /// use maplit::hashset; /// /// let xss = exhaustive_hash_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {1, 2}, /// hashset! {1, 3}, /// hashset! {2, 3}, /// hashset! {1, 2, 3}, /// hashset! {1, 4}, /// hashset! {2, 4}, /// hashset! {1, 2, 4}, /// hashset! {3, 4}, /// hashset! {1, 3, 4}, /// hashset! {2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_hash_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Eq + Hash, { ExhaustiveOrderedUniqueCollections::new(a, b, xs) } /// Generates [`BTreeSet`]s of a given size with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`BTreeSet`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_b_tree_sets_fixed_length; /// use maplit::btreeset; /// /// let xss = lex_b_tree_sets_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2, 3, 4}, /// btreeset! {1, 2, 3, 5}, /// btreeset! {1, 2, 3, 6}, /// btreeset! {1, 2, 4, 5}, /// btreeset! {1, 2, 4, 6}, /// btreeset! {1, 2, 5, 6}, /// btreeset! {1, 3, 4, 5}, /// btreeset! {1, 3, 4, 6}, /// btreeset! {1, 3, 5, 6}, /// btreeset! {1, 4, 5, 6}, /// btreeset! {2, 3, 4, 5}, /// btreeset! {2, 3, 4, 6}, /// btreeset! {2, 3, 5, 6}, /// btreeset! {2, 4, 5, 6}, /// btreeset! {3, 4, 5, 6} /// ] /// ); /// ``` #[inline] pub fn lex_b_tree_sets_fixed_length( k: u64, xs: I, ) -> LexFixedLengthOrderedUniqueCollections> where I::Item: Clone + Ord, { LexFixedLengthOrderedUniqueCollections::new(k, xs) } /// Generates [`BTreeSet`]s with elements from a single iterator. /// /// The [`BTreeSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`BTreeSet`]s of length 2 and above will never /// be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`HashSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_b_tree_sets; /// use maplit::btreeset; /// /// let xss = shortlex_b_tree_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {}, /// btreeset! {1}, /// btreeset! {2}, /// btreeset! {3}, /// btreeset! {4}, /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// btreeset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn shortlex_b_tree_sets( xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Ord, { shortlex_b_tree_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`BTreeSet`]s with a mininum length, with elements from a single iterator. /// /// The [`BTreeSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`BTreeSet`]s of length `\max(2, \ell + 1)` /// and above will never be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_b_tree_sets_min_length; /// use maplit::btreeset; /// /// let xss = shortlex_b_tree_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// btreeset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn shortlex_b_tree_sets_min_length( min_length: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Ord, { shortlex_b_tree_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The [`BTreeSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`BTreeSet`]s of length `\max(2, a + 1)` and /// above will never be generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_b_tree_sets_length_range; /// use maplit::btreeset; /// /// let xss = shortlex_b_tree_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// ] /// ); /// ``` #[inline] pub fn shortlex_b_tree_sets_length_range( mut a: u64, mut b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Ord, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } shortlex_b_tree_sets_length_inclusive_range(a, b - 1, xs) } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The [`BTreeSet`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`BTreeSet`]s of length `\max(2, a + 1)` and /// above will never be generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::shortlex_b_tree_sets_length_inclusive_range; /// use maplit::btreeset; /// /// let xss = shortlex_b_tree_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// ] /// ); /// ``` #[inline] pub fn shortlex_b_tree_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone + Ord, { ShortlexOrderedUniqueCollections::new(a, b, xs) } /// Generates [`BTreeSet`]s with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`BTreeSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_b_tree_sets; /// use maplit::btreeset; /// /// let xss = lex_b_tree_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {}, /// btreeset! {1}, /// btreeset! {1, 2}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 3, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3}, /// btreeset! {1, 3, 4}, /// btreeset! {1, 4}, /// btreeset! {2}, /// btreeset! {2, 3}, /// btreeset! {2, 3, 4}, /// btreeset! {2, 4}, /// btreeset! {3}, /// btreeset! {3, 4}, /// btreeset! {4} /// ] /// ); /// ``` #[inline] pub fn lex_b_tree_sets( xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Ord, { lex_b_tree_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`BTreeSet`]s with a mininum length, with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_b_tree_sets_min_length; /// use maplit::btreeset; /// /// let xss = lex_b_tree_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 3, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3}, /// btreeset! {1, 3, 4}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 3, 4}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_b_tree_sets_min_length( min_length: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Ord, { lex_b_tree_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_b_tree_sets_length_range; /// use maplit::btreeset; /// /// let xss = lex_b_tree_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3}, /// btreeset! {1, 3, 4}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 3, 4}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_b_tree_sets_length_range( mut a: u64, mut b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Ord, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } lex_b_tree_sets_length_inclusive_range(a, b - 1, xs) } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::lex_b_tree_sets_length_inclusive_range; /// use maplit::btreeset; /// /// let xss = lex_b_tree_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 2, 4}, /// btreeset! {1, 3}, /// btreeset! {1, 3, 4}, /// btreeset! {1, 4}, /// btreeset! {2, 3}, /// btreeset! {2, 3, 4}, /// btreeset! {2, 4}, /// btreeset! {3, 4}, /// ] /// ); /// ``` #[inline] pub fn lex_b_tree_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone + Ord, { LexOrderedUniqueCollections::new(a, b, xs) } /// Generates [`BTreeSet`]s of a given size with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`BTreeSet`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_fixed_length; /// use maplit::btreeset; /// /// let xss = exhaustive_b_tree_sets_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2, 3, 4}, /// btreeset! {1, 2, 3, 5}, /// btreeset! {1, 2, 4, 5}, /// btreeset! {1, 3, 4, 5}, /// btreeset! {2, 3, 4, 5}, /// btreeset! {1, 2, 3, 6}, /// btreeset! {1, 2, 4, 6}, /// btreeset! {1, 3, 4, 6}, /// btreeset! {2, 3, 4, 6}, /// btreeset! {1, 2, 5, 6}, /// btreeset! {1, 3, 5, 6}, /// btreeset! {2, 3, 5, 6}, /// btreeset! {1, 4, 5, 6}, /// btreeset! {2, 4, 5, 6}, /// btreeset! {3, 4, 5, 6} /// ] /// ); /// ``` #[inline] pub fn exhaustive_b_tree_sets_fixed_length( k: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Ord, { exhaustive_b_tree_sets_length_inclusive_range(k, k, xs) } /// Generates [`BTreeSet`]s with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`BTreeSet`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_b_tree_sets; /// use maplit::btreeset; /// /// let xss = exhaustive_b_tree_sets(1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {}, /// btreeset! {1}, /// btreeset! {2}, /// btreeset! {1, 2}, /// btreeset! {3}, /// btreeset! {1, 3}, /// btreeset! {2, 3}, /// btreeset! {1, 2, 3}, /// btreeset! {4}, /// btreeset! {1, 4}, /// btreeset! {2, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// btreeset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_b_tree_sets( xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Ord, { exhaustive_b_tree_sets_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`BTreeSet`]s with a mininum length, with elements from a single iterator. /// /// The [`BTreeSet`]s are ordered lexicographically with respect to the order of the element /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_min_length; /// use maplit::btreeset; /// /// let xss = exhaustive_b_tree_sets_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {2, 3}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4}, /// btreeset! {1, 2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_b_tree_sets_min_length( min_length: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Ord, { exhaustive_b_tree_sets_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b)$, with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b - 1 \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_length_range; /// use maplit::btreeset; /// /// let xss = exhaustive_b_tree_sets_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {2, 3}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_b_tree_sets_length_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Ord, { if a >= b { ExhaustiveOrderedUniqueCollections::None } else { exhaustive_b_tree_sets_length_inclusive_range(a, b - 1, xs) } } /// Generates [`BTreeSet`]s, with lengths in a range $[a, b]$, with elements from a single iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`BTreeSet`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_length_inclusive_range; /// use maplit::btreeset; /// /// let xss = exhaustive_b_tree_sets_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {1, 2}, /// btreeset! {1, 3}, /// btreeset! {2, 3}, /// btreeset! {1, 2, 3}, /// btreeset! {1, 4}, /// btreeset! {2, 4}, /// btreeset! {1, 2, 4}, /// btreeset! {3, 4}, /// btreeset! {1, 3, 4}, /// btreeset! {2, 3, 4} /// ] /// ); /// ``` #[inline] pub fn exhaustive_b_tree_sets_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone + Ord, { ExhaustiveOrderedUniqueCollections::new(a, b, xs) } ================================================ FILE: malachite-base/src/sets/mod.rs ================================================ // Copyright © 2026 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 . /// Iterators that generate sets without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate sets randomly. pub mod random; ================================================ FILE: malachite-base/src/sets/random.rs ================================================ // Copyright © 2026 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 crate::num::conversion::traits::ExactFrom; use crate::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use crate::num::random::{ RandomUnsignedInclusiveRange, RandomUnsignedRange, random_unsigned_inclusive_range, random_unsigned_range, }; use crate::random::Seed; #[cfg(not(feature = "test_build"))] use alloc::collections::BTreeSet; use core::hash::Hash; #[cfg(not(feature = "test_build"))] use hashbrown::HashSet; #[cfg(feature = "test_build")] use std::collections::{BTreeSet, HashSet}; /// Generates random [`HashSet`]s of a fixed length, where the [`Vec`]s have no repeated elements, /// and the elements are in ascending order. /// /// This `struct` is created by [`random_hash_sets_fixed_length`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomHashSetsFixedLength where I::Item: Eq + Hash, { len: usize, xs: I, } impl Iterator for RandomHashSetsFixedLength where I::Item: Eq + Hash, { type Item = HashSet; #[inline] fn next(&mut self) -> Option> { let mut set = HashSet::new(); while set.len() < self.len { set.insert(self.xs.next().unwrap()); } Some(set) } } /// Randomly generates [`HashSet`]s of a given length. /// /// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will /// hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// If `len` is 0, the output consists of the empty set, repeated. /// /// `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets_fixed_length; /// use maplit::hashset; /// /// let xss = random_hash_sets_fixed_length( /// 2, /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 100), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// xss, /// &[ /// hashset! {24, 95}, /// hashset! {71, 99}, /// hashset! {53, 93}, /// hashset! {34, 85}, /// hashset! {2, 48}, /// hashset! {11, 55}, /// hashset! {18, 48}, /// hashset! {90, 93}, /// hashset! {67, 93}, /// hashset! {93, 95} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets_fixed_length(len: u64, xs: I) -> RandomHashSetsFixedLength where I::Item: Eq + Hash, { RandomHashSetsFixedLength { len: usize::exact_from(len), xs, } } /// Generates random [`HashSet`]s with lengths from an iterator. #[derive(Clone, Debug)] pub struct RandomHashSets, J: Iterator> { lengths: I, xs: J, } impl, J: Iterator> Iterator for RandomHashSets { type Item = HashSet; fn next(&mut self) -> Option> { let len = usize::exact_from(self.lengths.next().unwrap()); let mut set = HashSet::new(); while set.len() < len { set.insert(self.xs.next().unwrap()); } Some(set) } } /// Generates random [`HashSet`]s using elements from an iterator and with lengths from another /// iterator. /// /// The input iterator must generate at least many distinct elements as any number generated by the /// lengths iterator; otherwise, this iterator will hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P(n)\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `lengths` and `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets_from_length_iterator; /// use malachite_base::vecs::random_values_from_vec; /// use maplit::hashset; /// /// let xs = random_hash_sets_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// hashset! {11, 85}, /// hashset! {134, 136, 200, 235}, /// hashset! {203, 223}, /// hashset! {38, 177, 217, 235}, /// hashset! {32, 162, 166, 234}, /// hashset! {30, 218}, /// hashset! {}, /// hashset! {90, 106}, /// hashset! {}, /// hashset! {9, 151, 204, 216}, /// hashset! {78, 97, 213, 253}, /// hashset! {39, 91}, /// hashset! {170, 175, 191, 232}, /// hashset! {2, 233}, /// hashset! {22, 35, 198, 217}, /// hashset! {17, 32, 114, 173}, /// hashset! {65, 114, 121, 222}, /// hashset! {}, /// hashset! {25, 144, 148, 173}, /// hashset! {} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets_from_length_iterator< T: Eq + Hash, I: Iterator, J: Iterator, >( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, ) -> RandomHashSets { RandomHashSets { lengths: lengths_gen(seed.fork("lengths")), xs: xs_gen(seed.fork("xs")), } } /// Generates random [`HashSet`]s using elements from an iterator. /// /// The lengths of the [`HashSet`]s are sampled from a geometric distribution with a specified mean /// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in [`geometric_random_unsigneds`]. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets; /// use maplit::hashset; /// /// let xs = random_hash_sets(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// hashset! {}, /// hashset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, /// hashset! {30, 90, 218, 234}, /// hashset! {9, 106, 204, 216}, /// hashset! {151}, /// hashset! {}, /// hashset! {78, 91, 97, 213, 253}, /// hashset! {39, 191}, /// hashset! {170, 175, 232, 233}, /// hashset! {}, /// hashset! {2, 22, 35, 114, 198, 217}, /// hashset! {}, /// hashset! {}, /// hashset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, /// hashset! {52, 69, 73, 91, 115, 137, 153, 178}, /// hashset! {}, /// hashset! {34, 95, 112}, /// hashset! {}, /// hashset! {106, 130, 167, 168, 197}, /// hashset! {86, 101, 122, 150, 172, 177, 207, 218, 221} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomHashSets, I> where I::Item: Eq + Hash, { random_hash_sets_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, xs_gen, ) } /// Generates random [`HashSet`]s with a minimum length, using elements from an iterator. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in /// [`geometric_random_unsigned_inclusive_range`] with $a$ equal to `min_length` and `b` to /// `u64::MAX`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less /// than or equal to `min_length`, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets_min_length; /// use maplit::hashset; /// /// let xs = random_hash_sets_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::, 6, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// hashset! {11, 85}, /// hashset! { /// 30, 32, 38, 90, 134, 136, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235 /// }, /// hashset! {9, 106, 151, 204, 213, 216}, /// hashset! {39, 78, 91, 97, 191, 253}, /// hashset! {170, 175, 232}, /// hashset! {2, 233}, /// hashset! {17, 22, 32, 35, 114, 198, 217}, /// hashset! {65, 114, 121, 173}, /// hashset! {25, 79, 144, 148, 173, 222}, /// hashset! {52, 115}, /// hashset! {34, 69, 73, 91, 112, 137, 153, 178}, /// hashset! {95, 106}, /// hashset! {167, 197}, /// hashset! {74, 86, 101, 115, 122, 130, 150, 168, 172, 177, 207, 218, 221}, /// hashset! {9, 48, 52, 109, 123, 133, 159, 201, 247, 250}, /// hashset! {196, 235}, /// hashset! {40, 68, 97, 104, 190}, /// hashset! {7, 216}, /// hashset! {11, 24, 43, 112, 157, 216, 217}, /// hashset! {29, 51, 55, 65, 84, 89, 103, 135, 191, 206, 211} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets_min_length( seed: Seed, min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomHashSets, I> where I::Item: Eq + Hash, { random_hash_sets_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, xs_gen, ) } /// Generates random [`HashSet`]s with lengths in $[a, b)$, using elements from an iterator. /// /// The lengths of the [`HashSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets_length_range; /// use maplit::hashset; /// /// let xs = random_hash_sets_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// hashset! {11, 85, 136}, /// hashset! {134, 200, 203, 235}, /// hashset! {38, 223, 235}, /// hashset! {32, 162, 177, 217}, /// hashset! {30, 166, 218, 234}, /// hashset! {9, 90, 106}, /// hashset! {204, 216}, /// hashset! {97, 151, 213}, /// hashset! {78, 253}, /// hashset! {39, 91, 175, 191}, /// hashset! {2, 170, 232, 233}, /// hashset! {22, 35, 217}, /// hashset! {17, 32, 114, 198}, /// hashset! {65, 114, 173}, /// hashset! {25, 121, 173, 222}, /// hashset! {79, 115, 144, 148}, /// hashset! {52, 69, 73, 137}, /// hashset! {91, 153}, /// hashset! {34, 95, 112, 178}, /// hashset! {106, 167} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets_length_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomHashSets, I> where I::Item: Eq + Hash, { random_hash_sets_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), xs_gen, ) } /// Generates random [`HashSet`]s with lengths in $[a, b]$, using elements from an iterator. /// /// The lengths of the [`HashSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than or equal to $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_hash_sets_length_inclusive_range; /// use maplit::hashset; /// /// let xs = /// random_hash_sets_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// hashset! {11, 85, 136}, /// hashset! {134, 200, 203, 235}, /// hashset! {38, 223, 235}, /// hashset! {32, 162, 177, 217}, /// hashset! {30, 166, 218, 234}, /// hashset! {9, 90, 106}, /// hashset! {204, 216}, /// hashset! {97, 151, 213}, /// hashset! {78, 253}, /// hashset! {39, 91, 175, 191}, /// hashset! {2, 170, 232, 233}, /// hashset! {22, 35, 217}, /// hashset! {17, 32, 114, 198}, /// hashset! {65, 114, 173}, /// hashset! {25, 121, 173, 222}, /// hashset! {79, 115, 144, 148}, /// hashset! {52, 69, 73, 137}, /// hashset! {91, 153}, /// hashset! {34, 95, 112, 178}, /// hashset! {106, 167} /// ] /// ); /// ``` #[inline] pub fn random_hash_sets_length_inclusive_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomHashSets, I> where I::Item: Eq + Hash, { random_hash_sets_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), xs_gen, ) } /// Generates random [`BTreeSet`]s of a fixed length, where the [`Vec`]s have no repeated elements, /// and the elements are in ascending order. /// /// This `struct` is created by [`random_b_tree_sets_fixed_length`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomBTreeSetsFixedLength where I::Item: Ord, { len: usize, xs: I, } impl Iterator for RandomBTreeSetsFixedLength where I::Item: Ord, { type Item = BTreeSet; #[inline] fn next(&mut self) -> Option> { let mut set = BTreeSet::new(); while set.len() < self.len { set.insert(self.xs.next().unwrap()); } Some(set) } } /// Randomly generates [`BTreeSet`]s of a given length. /// /// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will /// hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// If `len` is 0, the output consists of the empty set, repeated. /// /// `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets_fixed_length; /// use maplit::btreeset; /// /// let xss = random_b_tree_sets_fixed_length( /// 2, /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 100), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// xss, /// &[ /// btreeset! {24, 95}, /// btreeset! {71, 99}, /// btreeset! {53, 93}, /// btreeset! {34, 85}, /// btreeset! {2, 48}, /// btreeset! {11, 55}, /// btreeset! {18, 48}, /// btreeset! {90, 93}, /// btreeset! {67, 93}, /// btreeset! {93, 95} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets_fixed_length( len: u64, xs: I, ) -> RandomBTreeSetsFixedLength where I::Item: Ord, { RandomBTreeSetsFixedLength { len: usize::exact_from(len), xs, } } /// Generates random [`BTreeSet`]s with lengths from an iterator. #[derive(Clone, Debug)] pub struct RandomBTreeSets, J: Iterator> { lengths: I, xs: J, } impl, J: Iterator> Iterator for RandomBTreeSets { type Item = BTreeSet; fn next(&mut self) -> Option> { let len = usize::exact_from(self.lengths.next().unwrap()); let mut set = BTreeSet::new(); while set.len() < len { set.insert(self.xs.next().unwrap()); } Some(set) } } /// Generates random [`BTreeSet`]s using elements from an iterator and with lengths from another /// iterator. /// /// The input iterator must generate at least many distinct elements as any number generated by the /// lengths iterator; otherwise, this iterator will hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P(n)\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `lengths` and `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets_from_length_iterator; /// use malachite_base::vecs::random_values_from_vec; /// use maplit::btreeset; /// /// let xs = random_b_tree_sets_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// btreeset! {11, 85}, /// btreeset! {134, 136, 200, 235}, /// btreeset! {203, 223}, /// btreeset! {38, 177, 217, 235}, /// btreeset! {32, 162, 166, 234}, /// btreeset! {30, 218}, /// btreeset! {}, /// btreeset! {90, 106}, /// btreeset! {}, /// btreeset! {9, 151, 204, 216}, /// btreeset! {78, 97, 213, 253}, /// btreeset! {39, 91}, /// btreeset! {170, 175, 191, 232}, /// btreeset! {2, 233}, /// btreeset! {22, 35, 198, 217}, /// btreeset! {17, 32, 114, 173}, /// btreeset! {65, 114, 121, 222}, /// btreeset! {}, /// btreeset! {25, 144, 148, 173}, /// btreeset! {} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets_from_length_iterator< T: Ord, I: Iterator, J: Iterator, >( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, ) -> RandomBTreeSets { RandomBTreeSets { lengths: lengths_gen(seed.fork("lengths")), xs: xs_gen(seed.fork("xs")), } } /// Generates random [`BTreeSet`]s using elements from an iterator. /// /// The lengths of the [`BTreeSet`]s are sampled from a geometric distribution with a specified mean /// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in [`geometric_random_unsigneds`]. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets; /// use maplit::btreeset; /// /// let xs = random_b_tree_sets(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// btreeset! {}, /// btreeset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, /// btreeset! {30, 90, 218, 234}, /// btreeset! {9, 106, 204, 216}, /// btreeset! {151}, /// btreeset! {}, /// btreeset! {78, 91, 97, 213, 253}, /// btreeset! {39, 191}, /// btreeset! {170, 175, 232, 233}, /// btreeset! {}, /// btreeset! {2, 22, 35, 114, 198, 217}, /// btreeset! {}, /// btreeset! {}, /// btreeset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, /// btreeset! {52, 69, 73, 91, 115, 137, 153, 178}, /// btreeset! {}, /// btreeset! {34, 95, 112}, /// btreeset! {}, /// btreeset! {106, 130, 167, 168, 197}, /// btreeset! {86, 101, 122, 150, 172, 177, 207, 218, 221} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomBTreeSets, I> where I::Item: Ord, { random_b_tree_sets_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, xs_gen, ) } /// Generates random [`BTreeSet`]s with a minimum length, using elements from an iterator. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in /// [`geometric_random_unsigned_inclusive_range`], with $a$ equal to `min_length` and `b` to /// `u64::MAX`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less /// than or equal to `min_length`, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets_min_length; /// use maplit::btreeset; /// /// let xs = random_b_tree_sets_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::, 6, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// btreeset! {11, 85}, /// btreeset! { /// 30, 32, 38, 90, 134, 136, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235 /// }, /// btreeset! {9, 106, 151, 204, 213, 216}, /// btreeset! {39, 78, 91, 97, 191, 253}, /// btreeset! {170, 175, 232}, /// btreeset! {2, 233}, /// btreeset! {17, 22, 32, 35, 114, 198, 217}, /// btreeset! {65, 114, 121, 173}, /// btreeset! {25, 79, 144, 148, 173, 222}, /// btreeset! {52, 115}, /// btreeset! {34, 69, 73, 91, 112, 137, 153, 178}, /// btreeset! {95, 106}, /// btreeset! {167, 197}, /// btreeset! {74, 86, 101, 115, 122, 130, 150, 168, 172, 177, 207, 218, 221}, /// btreeset! {9, 48, 52, 109, 123, 133, 159, 201, 247, 250}, /// btreeset! {196, 235}, /// btreeset! {40, 68, 97, 104, 190}, /// btreeset! {7, 216}, /// btreeset! {11, 24, 43, 112, 157, 216, 217}, /// btreeset! {29, 51, 55, 65, 84, 89, 103, 135, 191, 206, 211} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets_min_length( seed: Seed, min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomBTreeSets, I> where I::Item: Ord, { random_b_tree_sets_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, xs_gen, ) } /// Generates random [`BTreeSet`]s with lengths in $[a, b]$, using elements from an iterator. /// /// The lengths of the [`BTreeSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must /// be less than or equal to $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets_length_range; /// use maplit::btreeset; /// /// let xs = random_b_tree_sets_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// btreeset! {11, 85, 136}, /// btreeset! {134, 200, 203, 235}, /// btreeset! {38, 223, 235}, /// btreeset! {32, 162, 177, 217}, /// btreeset! {30, 166, 218, 234}, /// btreeset! {9, 90, 106}, /// btreeset! {204, 216}, /// btreeset! {97, 151, 213}, /// btreeset! {78, 253}, /// btreeset! {39, 91, 175, 191}, /// btreeset! {2, 170, 232, 233}, /// btreeset! {22, 35, 217}, /// btreeset! {17, 32, 114, 198}, /// btreeset! {65, 114, 173}, /// btreeset! {25, 121, 173, 222}, /// btreeset! {79, 115, 144, 148}, /// btreeset! {52, 69, 73, 137}, /// btreeset! {91, 153}, /// btreeset! {34, 95, 112, 178}, /// btreeset! {106, 167} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets_length_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomBTreeSets, I> where I::Item: Ord, { random_b_tree_sets_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), xs_gen, ) } /// Generates random [`BTreeSet`]s with lengths in $[a, b]$, using elements from an iterator. /// /// The lengths of the [`BTreeSet`]s are sampled from a uniform distribution on $[a, b)$. $a$ must /// be less than or equal to $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::sets::random::random_b_tree_sets_length_inclusive_range; /// use maplit::btreeset; /// /// let xs = /// random_b_tree_sets_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values, /// &[ /// btreeset! {11, 85, 136}, /// btreeset! {134, 200, 203, 235}, /// btreeset! {38, 223, 235}, /// btreeset! {32, 162, 177, 217}, /// btreeset! {30, 166, 218, 234}, /// btreeset! {9, 90, 106}, /// btreeset! {204, 216}, /// btreeset! {97, 151, 213}, /// btreeset! {78, 253}, /// btreeset! {39, 91, 175, 191}, /// btreeset! {2, 170, 232, 233}, /// btreeset! {22, 35, 217}, /// btreeset! {17, 32, 114, 198}, /// btreeset! {65, 114, 173}, /// btreeset! {25, 121, 173, 222}, /// btreeset! {79, 115, 144, 148}, /// btreeset! {52, 69, 73, 137}, /// btreeset! {91, 153}, /// btreeset! {34, 95, 112, 178}, /// btreeset! {106, 167} /// ] /// ); /// ``` #[inline] pub fn random_b_tree_sets_length_inclusive_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomBTreeSets, I> where I::Item: Ord, { random_b_tree_sets_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), xs_gen, ) } ================================================ FILE: malachite-base/src/slices/mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1997, 1999-2016, 2009, 2020 Free Software Foundation, Inc. // // 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 crate::num::arithmetic::traits::DivisibleBy; use crate::num::basic::traits::Zero; #[cfg(feature = "random")] use crate::num::conversion::traits::ExactFrom; #[cfg(feature = "random")] use crate::num::random::{RandomUnsignedsLessThan, random_unsigneds_less_than}; #[cfg(feature = "random")] use crate::random::Seed; use alloc::vec::Vec; #[cfg(feature = "random")] use rand::prelude::SliceRandom; #[cfg(feature = "random")] use rand_chacha::ChaCha20Rng; /// Sets all values in a slice to 0. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_set_zero; /// /// let mut xs = [1, 2, 3, 4, 5]; /// slice_set_zero::(&mut xs[1..4]); /// assert_eq!(xs, [1, 0, 0, 0, 5]); /// ``` /// /// This is equivalent to `mpn_zero` from `mpn/generic/zero.c`, GMP 6.2.1. Note that this is needed /// less often in Malachite than in GMP, since Malachite generally initializes new memory with /// zeros. pub fn slice_set_zero(xs: &mut [T]) { for x in &mut *xs { *x = T::ZERO; } } /// Tests whether all values in a slice are equal to 0. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_test_zero; /// /// assert!(slice_test_zero::(&[0, 0, 0])); /// assert!(!slice_test_zero::(&[0, 1, 0])); /// ``` /// /// This is equivalent to `mpn_zero_p` from `gmp-h.in`, GMP 6.2.1. pub fn slice_test_zero(xs: &[T]) -> bool { let zero = T::ZERO; xs.iter().all(|x| x == &zero) } /// Counts the number of zeros that a slice starts with. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_leading_zeros; /// /// assert_eq!(slice_leading_zeros::(&[1, 2, 3]), 0); /// assert_eq!(slice_leading_zeros::(&[0, 0, 0, 1, 2, 3]), 3); /// ``` pub fn slice_leading_zeros(xs: &[T]) -> usize { let zero = T::ZERO; xs.iter().take_while(|&x| x == &zero).count() } /// Counts the number of zeros that a slice ends with. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_trailing_zeros; /// /// assert_eq!(slice_trailing_zeros::(&[1, 2, 3]), 0); /// assert_eq!(slice_trailing_zeros::(&[1, 2, 3, 0, 0, 0]), 3); /// ``` pub fn slice_trailing_zeros(xs: &[T]) -> usize { let zero = T::ZERO; xs.iter().rev().take_while(|&x| x == &zero).count() } /// Given a slice and an starting index, copies the subslice starting from that index to the /// beginning of the slice. /// /// In other words, this function copies the contents of `&xs[starting_index..]` to `&xs[..xs.len() /// - starting_index]`. /// /// In other other words, if $k$ is `starting_index`, the sequence $[x_0, x_1, \ldots, x_{n-1}]$ /// becomes $[x_k, x_{k+1}, \ldots, x_{n-1}, x_{n-k}, x_{n-k+1}, \ldots, x_{n-1}]$. /// /// If `starting_index` is zero or `xs.len()`, nothing happens. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Panics /// Panics if `starting_index` is greater than the length of `xs`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_move_left; /// /// let xs = &mut [1, 2, 3, 4, 5, 6]; /// slice_move_left::(xs, 2); /// assert_eq!(xs, &[3, 4, 5, 6, 5, 6]); /// ``` #[inline] pub fn slice_move_left(xs: &mut [T], starting_index: usize) { xs.copy_within(starting_index..xs.len(), 0); } /// Splits an immutable slice into adjacent immutable chunks. /// /// An input slice $\mathbf{x}$, a chunk length $n$, and $k + 1$ output slice names $\\mathbf{x}_0, /// \\mathbf{x}_1, \\ldots, \\mathbf{x}_k$ are given. The last output slice name, $\mathbf{x}_k$, is /// specified via a separate argument called `xs_last`. /// /// The first $k$ output slice names are assigned adjacent length-$n$ chunks from $\mathbf{x}$. If /// $|\mathbf{x}| < kn$, the generated code panics. /// /// The last slice, $\mathbf{x}_k$, which is assigned to `xs_last`, has length $|\mathbf{x}| - kn$. /// This length may be greater than $n$. /// /// # Worst-case complexity /// $T(k) = O(k)$ /// /// $M(k) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is the number of output slice names `xs_i`. /// /// # Examples /// ``` /// use malachite_base::split_into_chunks; /// /// let xs = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; /// split_into_chunks!(xs, 3, [xs_1, xs_2, xs_3], xs_4); /// assert_eq!(xs_1, &[0, 1, 2]); /// assert_eq!(xs_2, &[3, 4, 5]); /// assert_eq!(xs_3, &[6, 7, 8]); /// assert_eq!(xs_4, &[9, 10, 11, 12]); /// ``` #[macro_export] macro_rules! split_into_chunks { ($xs: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => { let remainder = &$xs[..]; let n = $n; $( let ($xs_i, remainder) = remainder.split_at(n); )* let $xs_last = remainder; } } /// Splits a mutable slice into adjacent mutable chunks. /// /// An input slice $\mathbf{x}$, a chunk length $n$, and $k + 1$ output slice names $\\mathbf{x}_0, /// \\mathbf{x}_1, \\ldots, \\mathbf{x}_k$ are given. The last output slice name, $\mathbf{x}_k$, is /// specified via a separate argument called `xs_last`. /// /// The first $k$ output slice names are assigned adjacent length-$n$ chunks from $\mathbf{x}$. If /// $|\mathbf{x}| < kn$, the generated code panics. /// /// The last slice, $\mathbf{x}_k$, which is assigned to `xs_last`, has length $|\mathbf{x}| - kn$. /// This length may be greater than $n$. /// /// # Worst-case complexity /// $T(k) = O(k)$ /// /// $M(k) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is the number of output slice names `xs_i`. /// /// # Examples /// ``` /// use malachite_base::slices::slice_set_zero; /// use malachite_base::split_into_chunks_mut; /// /// let xs = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; /// split_into_chunks_mut!(xs, 3, [xs_1, xs_2, xs_3], xs_4); /// assert_eq!(xs_1, &[0, 1, 2]); /// assert_eq!(xs_2, &[3, 4, 5]); /// assert_eq!(xs_3, &[6, 7, 8]); /// assert_eq!(xs_4, &[9, 10, 11, 12]); /// /// slice_set_zero(xs_2); /// assert_eq!(xs, &[0, 1, 2, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12]); /// ``` #[macro_export] macro_rules! split_into_chunks_mut { ($xs: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => { let remainder = &mut $xs[..]; let n = $n; $( let ($xs_i, remainder) = remainder.split_at_mut(n); )* let $xs_last = remainder; } } #[cfg(feature = "random")] /// Uniformly generates a random reference to a value from a nonempty slice. /// /// This `struct` is created by [`random_values_from_slice`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomValuesFromSlice<'a, T> { xs: &'a [T], indices: RandomUnsignedsLessThan, } #[cfg(feature = "random")] impl<'a, T> Iterator for RandomValuesFromSlice<'a, T> { type Item = &'a T; #[inline] fn next(&mut self) -> Option<&'a T> { Some(&self.xs[usize::exact_from(self.indices.next().unwrap())]) } } #[cfg(feature = "random")] /// Uniformly generates a random reference to a value from a nonempty slice. /// /// The iterator cannot outlive the slice. It may be more convenient for the iterator to own the /// data, in which case you may use [`random_values_from_vec`](crate::vecs::random_values_from_vec) /// instead. /// /// The output length is infinite. /// /// $P(x) = 1/n$, where $n$ is `xs.len()`. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Panics /// Panics if `xs` is empty. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::slices::random_values_from_slice; /// /// let xs = &[2, 3, 5, 7, 11]; /// assert_eq!( /// random_values_from_slice(EXAMPLE_SEED, xs) /// .cloned() /// .take(10) /// .collect_vec(), /// &[3, 7, 3, 5, 11, 3, 5, 11, 2, 2] /// ); /// ``` #[inline] pub fn random_values_from_slice(seed: Seed, xs: &[T]) -> RandomValuesFromSlice<'_, T> { assert!(!xs.is_empty(), "empty slice"); RandomValuesFromSlice { xs, indices: random_unsigneds_less_than(seed, u64::exact_from(xs.len())), } } pub(crate) fn advance_indices(indices: &mut [usize]) -> bool { let n = indices.len(); if n == 0 { return true; } // Find the index of the value right before the longest descending suffix. let mut pivot_index = n; let mut i = 0; let mut reached_end = true; while pivot_index > 0 { pivot_index -= 1; let next_i = indices[pivot_index]; if next_i < i { reached_end = false; break; } i = next_i; } if reached_end { return true; } let pivot = indices[pivot_index]; let mut swap_index = n - 1; while indices[swap_index] < pivot { swap_index -= 1; } indices.swap(pivot_index, swap_index); indices[pivot_index + 1..].reverse(); false } /// Generates every permutation of a slice. /// /// This `struct` is created by [`exhaustive_slice_permutations`]; see its documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExhaustiveSlicePermutations<'a, T> { xs: &'a [T], indices: Vec, done: bool, } impl<'a, T> Iterator for ExhaustiveSlicePermutations<'a, T> { type Item = Vec<&'a T>; fn next(&mut self) -> Option> { if self.done { None } else { let out = Some(self.indices.iter().map(|&i| &self.xs[i]).collect()); self.done = advance_indices(&mut self.indices); out } } } /// Generates every permutation of a slice. /// /// The permutations are [`Vec`]s of references into the slice. It may be more convenient for the /// iterator to own the data, in which case you may use /// [`exhaustive_vec_permutations`](crate::vecs::exhaustive_vec_permutations) instead. /// /// The permutations are generated in lexicographic order with respect to the ordering in the slice. /// /// The output length is $n!$, where $n$ is `xs.len()`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::slices::exhaustive_slice_permutations; /// /// let css: Vec = exhaustive_slice_permutations(&['a', 'b', 'c', 'd']) /// .map(|ds| ds.into_iter().copied().collect()) /// .collect(); /// assert_eq!( /// css.iter().map(String::as_str).collect_vec().as_slice(), /// [ /// "abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac", /// "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca", /// "dcab", "dcba" /// ] /// ); /// ``` pub fn exhaustive_slice_permutations(xs: &[T]) -> ExhaustiveSlicePermutations<'_, T> { ExhaustiveSlicePermutations { xs, indices: (0..xs.len()).collect(), done: false, } } #[cfg(feature = "random")] /// Uniformly generates a random permutation of references to a slice. /// /// This `struct` is created by [`random_slice_permutations`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomSlicePermutations<'a, T> { xs: &'a [T], indices: Vec, rng: ChaCha20Rng, } #[cfg(feature = "random")] impl<'a, T> Iterator for RandomSlicePermutations<'a, T> { type Item = Vec<&'a T>; fn next(&mut self) -> Option> { self.indices.shuffle(&mut self.rng); Some(self.indices.iter().map(|&i| &self.xs[i]).collect()) } } #[cfg(feature = "random")] /// Uniformly generates a random permutation of references to a slice. /// /// The iterator cannot outlive the slice. It may be more convenient for the iterator to own the /// data, in which case you may use /// [`random_vec_permutations`](crate::vecs::random_vec_permutations) instead. /// /// The output length is infinite. /// /// $P(p) = 1/n!$, where $n$ is `xs.len()`. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::slices::random_slice_permutations; /// /// let css: Vec = random_slice_permutations(EXAMPLE_SEED, &['a', 'b', 'c', 'd']) /// .take(20) /// .map(|ds| ds.into_iter().copied().collect()) /// .collect(); /// assert_eq!( /// css.iter().map(String::as_str).collect_vec().as_slice(), /// [ /// "dacb", "cbad", "cdab", "cbad", "cdab", "bcda", "bcda", "acbd", "bcda", "dbca", "bdac", /// "dbac", "dbca", "bcad", "cadb", "dacb", "acbd", "dbac", "bdca", "abdc" /// ] /// ); /// ``` pub fn random_slice_permutations(seed: Seed, xs: &[T]) -> RandomSlicePermutations<'_, T> { RandomSlicePermutations { xs, indices: (0..xs.len()).collect(), rng: seed.get_rng(), } } /// Given a slice with nonzero length $\ell$, returns the smallest $n$ such that the slice consists /// of $n/\ell$ copies of a length-$\ell$ subslice. /// /// Typically $\ell = n$. /// /// # Worst-case complexity /// $T(n) = O(n^{1+\varepsilon})$ for all $\varepsilon > 0$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Panics /// Panics if `xs` is empty. /// /// # Examples /// ``` /// use malachite_base::slices::min_repeating_len; /// /// assert_eq!(min_repeating_len(&[1, 2, 1, 2, 1, 2]), 2); /// assert_eq!(min_repeating_len(&[1, 2, 1, 2, 1, 3]), 6); /// assert_eq!(min_repeating_len(&[5, 5, 5]), 1); /// ``` pub fn min_repeating_len(xs: &[T]) -> usize { let len = xs.len(); assert_ne!(len, 0); for start_i in 1..=len >> 1 { if !len.divisible_by(start_i) { continue; } let (xs_lo, xs_hi) = xs.split_at(start_i); if Iterator::eq(xs_lo.iter().cycle().take(len - start_i), xs_hi.iter()) { return start_i; } } len } ================================================ FILE: malachite-base/src/strings/exhaustive.rs ================================================ // Copyright © 2026 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 crate::chars::exhaustive::{ExhaustiveChars, exhaustive_chars}; use crate::num::exhaustive::PrimitiveIntIncreasingRange; use crate::strings::{StringsFromCharVecs, strings_from_char_vecs}; use crate::vecs::exhaustive::{ ExhaustiveFixedLengthVecs1Input, ExhaustiveVecs, LexFixedLengthVecsFromSingle, ShortlexVecs, exhaustive_vecs, exhaustive_vecs_fixed_length_from_single, lex_vecs_fixed_length_from_single, shortlex_vecs, }; /// Generates all [`String`]s of a given length with [`char`]s from a single iterator, in /// lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// `cs` must be finite. /// /// The output length is $\ell^n$, where $\ell$ is `cs.count()` and $n$ is `len`. /// /// If `len` is 0, the output consists of one empty [`String`]. /// /// If `cs` is empty, the output is also empty, unless `len` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::lex_fixed_length_strings_using_chars; /// /// let ss = lex_fixed_length_strings_using_chars(2, ['c', 'a', 't'].iter().cloned()).collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &["cc", "ca", "ct", "ac", "aa", "at", "tc", "ta", "tt"] /// ); /// ``` #[inline] pub fn lex_fixed_length_strings_using_chars>( len: u64, cs: I, ) -> StringsFromCharVecs> { strings_from_char_vecs(lex_vecs_fixed_length_from_single(len, cs)) } /// Generates all [`String`]s of a given length in lexicographic order. /// /// The order is lexicographic with respect to the order of [`exhaustive_chars`], which is not the /// default lexicographic order for [`char`]s. (For example, the first characters are not control /// characters, but lowercase Latin letters.) If you want the default [`char`] order, use /// `lex_fixed_length_strings_using_chars(len, chars_increasing())`. /// /// The output length is $1112064^n$, where $n$ is `len`. /// /// If `len` is 0, the output consists of one empty [`String`]. /// /// # Complexity per iteration /// $T(i, n) = O(n)$ /// /// $M(i, n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `len`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::lex_fixed_length_strings; /// /// let ss = lex_fixed_length_strings(2).take(20).collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &[ /// "aa", "ab", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an", /// "ao", "ap", "aq", "ar", "as", "at" /// ] /// ); /// ``` #[inline] pub fn lex_fixed_length_strings( len: u64, ) -> StringsFromCharVecs> { lex_fixed_length_strings_using_chars(len, exhaustive_chars()) } /// Generates all `String`s of a given length with [`char`]s from a single iterator. /// /// If `cs` is finite, the output length is $\ell^n$, where $\ell$ is `cs.count()` and $n$ is `len`. /// If `cs` is infinite, the output is also infinite. /// /// If `len` is 0, the output consists of one empty [`String`]. /// /// If `cs` is empty, the output is also empty, unless `len` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::exhaustive_fixed_length_strings_using_chars; /// /// let ss = exhaustive_fixed_length_strings_using_chars(2, ['c', 'a', 't'].iter().cloned()) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &["cc", "ca", "ac", "aa", "ct", "at", "tc", "ta", "tt"] /// ); /// ``` #[inline] pub fn exhaustive_fixed_length_strings_using_chars>( len: u64, cs: I, ) -> StringsFromCharVecs> { strings_from_char_vecs(exhaustive_vecs_fixed_length_from_single(len, cs)) } /// Generates all [`String`]s of a given length. /// /// The output length is $1112064^n$, where $n$ is `len`. /// /// If `len` is 0, the output consists of one empty [`String`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::exhaustive_fixed_length_strings; /// /// let ss = exhaustive_fixed_length_strings(2).take(20).collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &[ /// "aa", "ab", "ba", "bb", "ac", "ad", "bc", "bd", "ca", "cb", "da", "db", "cc", "cd", /// "dc", "dd", "ae", "af", "be", "bf" /// ] /// ); /// ``` #[inline] pub fn exhaustive_fixed_length_strings( len: u64, ) -> StringsFromCharVecs> { exhaustive_fixed_length_strings_using_chars(len, exhaustive_chars()) } /// Generates [`String`]s with [`char`]s from a specified iterator, in shortlex order. /// /// Shortlex order means that the [`String`]s are output from shortest to longest, and [`String`]s /// of the same length are output in lexicographic order with respect to the ordering of the /// [`char`]s specified by the input iterator. /// /// `cs` must be finite; if it's infinite, only [`String`]s of length 0 and 1 are ever produced. /// /// If `cs` is empty, the output length is 1; otherwise, the output is infinite. /// /// The lengths of the output [`String`]s grow logarithmically. /// /// # Complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::shortlex_strings_using_chars; /// /// let ss = shortlex_strings_using_chars('x'..='z') /// .take(20) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(String::as_str).collect_vec().as_slice(), /// &[ /// "", "x", "y", "z", "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz", "xxx", "xxy", /// "xxz", "xyx", "xyy", "xyz", "xzx" /// ] /// ); /// ``` #[inline] pub fn shortlex_strings_using_chars>( cs: I, ) -> StringsFromCharVecs, I>> { strings_from_char_vecs(shortlex_vecs(cs)) } /// Generates [`String`]s in shortlex order. /// /// Shortlex order means that the [`String`]s are output from shortest to longest, and [`String`]s /// of the same length are output in lexicographic order with respect to the order of /// [`exhaustive_chars`], which is not the default lexicographic order for [`char`]s. (For example, /// the first characters are not control characters, but lowercase Latin letters.) If you want the /// default [`char`] order, use `shortlex_strings_using_chars(chars_increasing())`. /// /// The output is infinite. /// /// The lengths of the output [`String`]s grow logarithmically. /// /// # Complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::shortlex_strings; /// /// let ss = shortlex_strings().take(20).collect_vec(); /// assert_eq!( /// ss.iter().map(String::as_str).collect_vec().as_slice(), /// &[ /// "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", /// "q", "r", "s" /// ] /// ); /// ``` #[inline] pub fn shortlex_strings() -> StringsFromCharVecs, ExhaustiveChars>> { shortlex_strings_using_chars(exhaustive_chars()) } /// Generates all [`String`]s with [`char`]s from a specified iterator. /// /// If `cs` is empty, the output length is 1; otherwise, the output is infinite. /// /// The lengths of the output [`String`]s grow logarithmically. /// /// # Complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::exhaustive_strings_using_chars; /// /// let ss = exhaustive_strings_using_chars('x'..='z') /// .take(20) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(String::as_str).collect_vec().as_slice(), /// &[ /// "", "x", "y", "xxx", "z", "xx", "xy", "xxxxx", "yx", "xxy", "yy", "xxxx", "xz", "xyx", /// "yz", "xxxxxx", "zx", "xyy", "zy", "xxxy" /// ] /// ); /// ``` #[inline] pub fn exhaustive_strings_using_chars>( cs: I, ) -> StringsFromCharVecs, I>> { strings_from_char_vecs(exhaustive_vecs(cs)) } /// Generates all [`String`]s. /// /// The lengths of the output [`String`]s grow logarithmically. /// /// # Complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time and $M$ is additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::exhaustive::exhaustive_strings; /// /// let ss = exhaustive_strings().take(20).collect_vec(); /// assert_eq!( /// ss.iter().map(String::as_str).collect_vec().as_slice(), /// &[ /// "", "a", "b", "aaa", "c", "aa", "d", "aaaa", "e", "ab", "f", "aab", "g", "ba", "h", /// "aaaaa", "i", "bb", "j", "aba" /// ] /// ); /// ``` #[inline] pub fn exhaustive_strings() -> StringsFromCharVecs, ExhaustiveChars>> { exhaustive_strings_using_chars(exhaustive_chars()) } ================================================ FILE: malachite-base/src/strings/mod.rs ================================================ // Copyright © 2026 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 crate::named::Named; use alloc::string::String; use alloc::vec::Vec; use core::fmt::{Binary, Debug, LowerHex, Octal, UpperHex}; use hashbrown::HashSet; use itertools::Itertools; /// Sorts the characters of a string slice and returns them in a new [`String`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use malachite_base::strings::string_sort; /// /// assert_eq!(string_sort("Hello, world!"), " !,Hdellloorw"); /// assert_eq!(string_sort("Mississippi"), "Miiiippssss"); /// ``` pub fn string_sort(s: &str) -> String { let mut chars = s.chars().collect_vec(); chars.sort_unstable(); chars.iter().collect() } /// Takes a string slice's unique characters and returns them in a new [`String`]. /// /// The unique characters are output in order of appearance. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use malachite_base::strings::string_unique; /// /// assert_eq!(string_unique("Hello, world!"), "Helo, wrd!"); /// assert_eq!(string_unique("Mississippi"), "Misp"); /// ``` pub fn string_unique(s: &str) -> String { let mut chars = HashSet::new(); let mut nub = String::new(); for c in s.chars() { if chars.insert(c) { nub.push(c); } } nub } /// Returns whether all of the first string slice's characters are present in the second string /// slice. /// /// Does not take multiplicities into account. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `t.len()`. /// /// # Examples /// ``` /// use malachite_base::strings::string_is_subset; /// /// assert_eq!(string_is_subset("oH, well", "Hello, world!"), true); /// assert_eq!(string_is_subset("MMM", "Mississippi"), true); /// assert_eq!(string_is_subset("Hello, World!", "Hello, world!"), false); /// assert_eq!(string_is_subset("j", "Mississippi"), false); /// ``` pub fn string_is_subset(s: &str, t: &str) -> bool { let t_chars: HashSet = t.chars().collect(); s.chars().all(|c| t_chars.contains(&c)) } impl_named!(String); /// A trait that provides an ergonomic way to create the string specified by a [`Debug`] /// implementation. pub trait ToDebugString: Debug { fn to_debug_string(&self) -> String; } impl ToDebugString for T { /// Returns the [`String`] produced by `T`s [`Debug`] implementation. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// /// assert_eq!([1, 2, 3].to_debug_string(), "[1, 2, 3]"); /// assert_eq!( /// [vec![2, 3], vec![], vec![4]].to_debug_string(), /// "[[2, 3], [], [4]]" /// ); /// assert_eq!(Some(5).to_debug_string(), "Some(5)"); /// ``` #[inline] fn to_debug_string(&self) -> String { ::alloc::format!("{self:?}") } } /// A trait that provides an ergonomic way to create the string specified by a [`Binary`] /// implementation. pub trait ToBinaryString: Binary { fn to_binary_string(&self) -> String; } impl ToBinaryString for T { /// Returns the [`String`] produced by `T`s [`Binary`] implementation. /// /// # Examples /// ``` /// use malachite_base::strings::ToBinaryString; /// /// assert_eq!(5u64.to_binary_string(), "101"); /// assert_eq!((-100i16).to_binary_string(), "1111111110011100"); /// ``` #[inline] fn to_binary_string(&self) -> String { ::alloc::format!("{self:b}") } } /// A trait that provides an ergonomic way to create the string specified by an [`Octal`] /// implementation. pub trait ToOctalString: Octal { fn to_octal_string(&self) -> String; } impl ToOctalString for T { /// Returns the [`String`] produced by `T`s [`Octal`] implementation. /// /// # Examples /// ``` /// use malachite_base::strings::ToOctalString; /// /// assert_eq!(50u64.to_octal_string(), "62"); /// assert_eq!((-100i16).to_octal_string(), "177634"); /// ``` #[inline] fn to_octal_string(&self) -> String { ::alloc::format!("{self:o}") } } /// A trait that provides an ergonomic way to create the string specified by a [`LowerHex`] /// implementation. pub trait ToLowerHexString: LowerHex { fn to_lower_hex_string(&self) -> String; } impl ToLowerHexString for T { /// Returns the [`String`] produced by `T`s [`LowerHex`] implementation. /// /// # Examples /// ``` /// use malachite_base::strings::ToLowerHexString; /// /// assert_eq!(50u64.to_lower_hex_string(), "32"); /// assert_eq!((-100i16).to_lower_hex_string(), "ff9c"); /// ``` #[inline] fn to_lower_hex_string(&self) -> String { ::alloc::format!("{self:x}") } } /// A trait that provides an ergonomic way to create the string specified by an [`UpperHex`] /// implementation. pub trait ToUpperHexString: UpperHex { fn to_upper_hex_string(&self) -> String; } impl ToUpperHexString for T { /// Returns the [`String`] produced by `T`s [`UpperHex`] implementation. /// /// # Examples /// ``` /// use malachite_base::strings::ToUpperHexString; /// /// assert_eq!(50u64.to_upper_hex_string(), "32"); /// assert_eq!((-100i16).to_upper_hex_string(), "FF9C"); /// ``` #[inline] fn to_upper_hex_string(&self) -> String { ::alloc::format!("{self:X}") } } /// Generates [`String`]s, given an iterator that generates `Vec`s. /// /// This `struct` is created by [`strings_from_char_vecs`]; see its documentation for more. #[derive(Clone, Debug)] pub struct StringsFromCharVecs>> { css: I, } impl>> Iterator for StringsFromCharVecs { type Item = String; #[inline] fn next(&mut self) -> Option { self.css.next().map(|cs| cs.into_iter().collect()) } } /// Generates [`String`]s, given an iterator that generates `Vec`s. /// /// The elements appear in the same order as they do in the given iterator, but as [`String`]s. /// /// The output length is `css.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::strings_from_char_vecs; /// /// let ss = /// &strings_from_char_vecs([vec!['a', 'b'], vec!['c', 'd']].iter().cloned()).collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &["ab", "cd"] /// ); /// ``` #[inline] pub const fn strings_from_char_vecs>>( css: I, ) -> StringsFromCharVecs { StringsFromCharVecs { css } } /// Iterators that generate [`String`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`String`]s randomly. pub mod random; ================================================ FILE: malachite-base/src/strings/random.rs ================================================ // Copyright © 2026 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 crate::chars::random::{RandomCharRange, random_chars}; use crate::num::random::geometric::GeometricRandomNaturalValues; use crate::random::Seed; use crate::strings::StringsFromCharVecs; use crate::vecs::random::{ RandomFixedLengthVecsFromSingle, RandomVecs, random_vecs, random_vecs_fixed_length_from_single, }; /// Randomly generates [`String`]s of a given length using [`char`]s from a single iterator. /// /// The probability of a particular length-$n$ [`String`] being generated is the product of the /// probabilities of each of its `char`s. /// /// If `len` is 0, the output consists of the empty [`String`], repeated. /// /// `cs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::random::random_fixed_length_strings_using_chars; /// /// let ss = random_fixed_length_strings_using_chars( /// 2, /// random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &["ba", "bc", "bb", "ab", "ac", "ba", "bc", "ca", "ba", "cc"] /// ); /// ``` #[inline] pub const fn random_fixed_length_strings_using_chars>( len: u64, cs: I, ) -> StringsFromCharVecs> { StringsFromCharVecs { css: random_vecs_fixed_length_from_single(len, cs), } } /// Randomly generates [`String`]s of a given length. /// /// The probability of a particular length-$n$ [`String`] being generated is $1112064^{-\ell}$, /// where $\ell$ is `len`. /// /// If `len` is 0, the output consists of the empty [`String`], repeated. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `len`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::random::random_fixed_length_strings; /// /// let ss = random_fixed_length_strings(EXAMPLE_SEED, 2) /// .take(10) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &[ /// "\u{5f771}\u{87234}", /// "\u{bcd36}\u{9e195}", /// "\u{5da07}\u{36553}", /// "\u{45028}\u{1cdfd}", /// "\u{d8530}\u{c7f2e}", /// "\u{ba4bc}\u{ff677}", /// "\u{a12e2}\u{d775c}", /// "\u{f827b}\u{bdf7a}", /// "簅\u{15aca}", /// "\u{4e5e2}\u{bb286}" /// ] /// ); /// ``` #[inline] pub fn random_fixed_length_strings( seed: Seed, len: u64, ) -> StringsFromCharVecs> { random_fixed_length_strings_using_chars(len, random_chars(seed)) } /// Generates random [`String`]s using [`char`]s from an iterator. /// /// The lengths of the [`String`]s are sampled from a geometric distribution with a specified mean /// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// $$ /// P((c_0, c_1, \ldots, c_{n-1})) = \frac{m^n}{(m+1)^{n+1}}\prod_{i=0}^{n-1}P(c_i). /// $$ /// /// The iterators produced by `cs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::random::random_strings_using_chars; /// /// let ss = random_strings_using_chars( /// EXAMPLE_SEED, /// &|seed| random_char_inclusive_range(seed, 'x', 'z'), /// 4, /// 1, /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &["", "yyyyzxxxzxzxzx", "zzzy", "xzzx", "y", "", "zyzxz", "zy", "zyyx", ""] /// ); /// ``` #[inline] pub fn random_strings_using_chars>( seed: Seed, cs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StringsFromCharVecs, I>> { StringsFromCharVecs { css: random_vecs(seed, cs_gen, mean_length_numerator, mean_length_denominator), } } /// Generates random [`String`]s. /// /// The lengths of the [`String`]s are sampled from a geometric distribution with a specified mean /// $m$, equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// $$ /// P((c_0, c_1, \ldots, c_{n-1})) = \frac{m^n}{1112064^n(m+1)^{n+1}} /// $$ /// /// # Expected complexity per iteration /// $T(n) = O(m)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, and $m$ is `mean_length_numerator / /// mean_length_denominator`. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::random::random_strings; /// /// let ss = random_strings(EXAMPLE_SEED, 4, 1).take(10).collect_vec(); /// assert_eq!( /// ss.iter().map(|cs| cs.as_str()).collect_vec().as_slice(), /// &[ /// "", /// "\u{81355}\u{a331d}\u{b707b}\u{1354b}\u{b16ac}𣙘\u{67377}\u{4aaa4}\u{a6d6e}\u{45616}\ /// \u{7725f}\u{41e2d}\u{d6b59}\u{de165}", /// "\u{c2d29}\u{695af}\u{98fd7}\u{10ca51}", /// "\u{bec46}\u{c0bec}\u{cb677}\u{71318}", /// "\u{755e1}", /// "", /// "𫮜\u{a2f84}柂\u{f5560}\u{6737b}", /// "\u{8442e}\u{a6883}", /// "\u{49cf2}\u{32d2b}\u{1e6e5}\u{1084bd}", /// "" /// ] /// ); /// ``` #[inline] pub fn random_strings( seed: Seed, mean_length_numerator: u64, mean_length_denominator: u64, ) -> StringsFromCharVecs, RandomCharRange>> { random_strings_using_chars( seed, &random_chars, mean_length_numerator, mean_length_denominator, ) } ================================================ FILE: malachite-base/src/test_util/bench/bucketers.rs ================================================ // Copyright © 2026 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 crate::chars::crement::char_to_contiguous_range; use crate::max; use crate::num::arithmetic::traits::UnsignedAbs; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::logic::traits::SignificantBits; use crate::rational_sequences::RationalSequence; use std::cmp::{max, min}; pub struct Bucketer<'a, T> { pub bucketing_function: &'a dyn Fn(&T) -> usize, pub bucketing_label: String, } pub fn char_bucketer<'a>() -> Bucketer<'a, char> { Bucketer { bucketing_function: &|&c| usize::exact_from(char_to_contiguous_range(c)), bucketing_label: "char_to_contiguous_range(c)".to_string(), } } pub fn float_size(f: T) -> usize { if f == T::ZERO || !f.is_finite() || f.is_nan() { 0 } else { let (m, e) = f.integer_mantissa_and_exponent(); usize::exact_from(m.significant_bits()) + usize::wrapping_from(e.abs()) } } pub fn primitive_float_bucketer<'a, T: PrimitiveFloat>(var_name: &str) -> Bucketer<'a, T> { Bucketer { bucketing_function: &|&f| float_size(f), bucketing_label: format!("precision({var_name}) + |exponent({var_name})|"), } } pub fn pair_1_primitive_float_bucketer<'a, T: PrimitiveFloat, U>( var_name: &str, ) -> Bucketer<'a, (T, U)> { Bucketer { bucketing_function: &|&(f, _)| float_size(f), bucketing_label: format!("precision({var_name}) + |exponent({var_name})|"), } } pub fn pair_max_primitive_float_bucketer<'a, T: PrimitiveFloat>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, T)> { Bucketer { bucketing_function: &|&(f, g)| max(float_size(f), float_size(g)), bucketing_label: format!( "max(precision({x_name}) + |exponent({x_name})|, \ precision({y_name}) + |exponent({y_name})|)" ), } } pub fn triple_1_primitive_float_bucketer<'a, T: PrimitiveFloat, U, V>( var_name: &str, ) -> Bucketer<'a, (T, U, V)> { Bucketer { bucketing_function: &|&(f, _, _)| float_size(f), bucketing_label: format!("precision({var_name}) + |exponent({var_name})|"), } } pub fn triple_max_primitive_float_bucketer<'a, T: PrimitiveFloat>( x_name: &str, y_name: &str, z_name: &str, ) -> Bucketer<'a, (T, T, T)> { Bucketer { bucketing_function: &|&(f, g, h)| max!(float_size(f), float_size(g), float_size(h)), bucketing_label: format!( "max(precision({x_name}) + |exponent({x_name})|, \ precision({y_name}) + |exponent({y_name})|, \ precision({z_name}) + |exponent({z_name})|)", ), } } pub fn pair_primitive_float_bit_u64_max_bucketer<'a, T: PrimitiveFloat>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, u64)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(u64::wrapping_from(float_size(*x)), *y)) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn triple_1_2_primitive_float_bit_u64_max_bucketer<'a, T: PrimitiveFloat, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, u64, U)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max(u64::wrapping_from(float_size(*x)), *y)) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn usize_convertible_direct_bucketer(var_name: &str) -> Bucketer<'_, T> where usize: ExactFrom, { Bucketer { bucketing_function: &|&x| usize::exact_from(x), bucketing_label: var_name.to_string(), } } pub fn primitive_int_direct_bucketer<'a, T: PrimitiveInt>() -> Bucketer<'a, T> where usize: ExactFrom, { usize_convertible_direct_bucketer("n") } pub fn unsigned_direct_bucketer<'a, T: PrimitiveUnsigned>() -> Bucketer<'a, T> where usize: ExactFrom, { usize_convertible_direct_bucketer("u") } pub fn signed_direct_bucketer<'a, T: PrimitiveSigned>() -> Bucketer<'a, T> where usize: ExactFrom, { usize_convertible_direct_bucketer("i") } pub fn usize_convertible_pair_max_bucketer<'a, T: Copy + Ord>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, T)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(x, y)| usize::exact_from(max(x, y)), bucketing_label: format!("max({x_name}, {y_name})"), } } pub fn abs_usize_convertible_pair_max_bucketer<'a, T: Copy + UnsignedAbs>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, T)> where usize: ExactFrom<::Output>, ::Output: Ord, { Bucketer { bucketing_function: &|&(x, y)| usize::exact_from(max(x.unsigned_abs(), y.unsigned_abs())), bucketing_label: format!("max({x_name}, {y_name})"), } } pub fn abs_pair_usize_convertible_max_bucketer<'a, T: Copy + UnsignedAbs, U: Copy>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U)> where usize: ExactFrom<::Output> + ExactFrom, ::Output: Ord, { Bucketer { bucketing_function: &|&(x, y)| { max(usize::exact_from(x.unsigned_abs()), usize::exact_from(y)) }, bucketing_label: format!("max({x_name}, {y_name})"), } } pub fn abs_triple_1_2_usize_convertible_max_bucketer<'a, T: Copy + UnsignedAbs, U: Copy, V>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, V)> where usize: ExactFrom<::Output> + ExactFrom, ::Output: Ord, { Bucketer { bucketing_function: &|&(x, y, _)| { max(usize::exact_from(x.unsigned_abs()), usize::exact_from(y)) }, bucketing_label: format!("max({x_name}, {y_name})"), } } pub fn usize_convertible_pair_ratio_bucketer<'a, T: Copy>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, T)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(x, y)| usize::exact_from(x) / usize::exact_from(y), bucketing_label: format!("{x_name} / {y_name}"), } } pub fn signed_abs_bucketer(var_name: &str) -> Bucketer<'_, T> where usize: ExactFrom<::Output>, { Bucketer { bucketing_function: &|&x| usize::exact_from(x.unsigned_abs()), bucketing_label: var_name.to_string(), } } pub fn bit_bucketer(var_name: &str) -> Bucketer<'_, T> { Bucketer { bucketing_function: &|&x| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn primitive_int_bit_bucketer<'a, T: PrimitiveInt>() -> Bucketer<'a, T> { bit_bucketer("n") } pub fn unsigned_bit_bucketer<'a, T: PrimitiveUnsigned>() -> Bucketer<'a, T> { bit_bucketer("u") } pub fn signed_bit_bucketer<'a, T: PrimitiveSigned>() -> Bucketer<'a, T> { bit_bucketer("i") } pub fn ignore_highest_bit_unsigned_bit_bucketer<'a, T: PrimitiveUnsigned>( var_name: &str, ) -> Bucketer<'a, T> { Bucketer { bucketing_function: &|&x| { let mut x = x; x.clear_bit(T::WIDTH - 1); usize::exact_from(x.significant_bits()) }, bucketing_label: format!( "({} - (1 << {})).significant_bits()", var_name, T::WIDTH - 1 ), } } pub fn string_len_bucketer<'a>() -> Bucketer<'a, String> { Bucketer { bucketing_function: &String::len, bucketing_label: "s.len()".to_string(), } } pub fn pair_string_max_len_bucketer<'a>( s_name: &str, t_name: &str, ) -> Bucketer<'a, (String, String)> { Bucketer { bucketing_function: &|(s, t)| max(s.len(), t.len()), bucketing_label: format!("max(s.len({s_name}), t.len({t_name}))"), } } pub fn pair_1_string_len_bucketer(s_name: &str) -> Bucketer<'_, (String, T)> { Bucketer { bucketing_function: &|(s, _)| s.len(), bucketing_label: format!("{s_name}.len()"), } } pub fn pair_2_string_len_bucketer(s_name: &str) -> Bucketer<'_, (T, String)> { Bucketer { bucketing_function: &|(_, s)| s.len(), bucketing_label: format!("{s_name}.len()"), } } pub fn vec_len_bucketer<'a, T>() -> Bucketer<'a, Vec> { Bucketer { bucketing_function: &Vec::len, bucketing_label: "xs.len()".to_string(), } } pub fn pair_vec_max_len_bucketer<'a, T, U>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec)> { Bucketer { bucketing_function: &|(xs, ys)| max(xs.len(), ys.len()), bucketing_label: format!("max({xs_name}.len(), {ys_name}.len())"), } } pub fn pair_vec_min_len_bucketer<'a, T, U>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec)> { Bucketer { bucketing_function: &|(xs, ys)| min(xs.len(), ys.len()), bucketing_label: format!("min({xs_name}.len(), {ys_name}.len())"), } } pub fn pair_max_bit_bucketer<'a, T: Copy + SignificantBits, U: Copy + SignificantBits>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, U)> { Bucketer { bucketing_function: &|&(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_max_bit_bucketer< 'a, T: Copy + SignificantBits, U: Copy + SignificantBits, V: Copy + SignificantBits, >( x_name: &str, y_name: &str, z_name: &str, ) -> Bucketer<'a, (T, U, V)> { Bucketer { bucketing_function: &|&(x, y, z)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits())", ), } } pub fn quadruple_max_bit_bucketer< 'a, T: Copy + SignificantBits, U: Copy + SignificantBits, V: Copy + SignificantBits, W: Copy + SignificantBits, >( x_name: &str, y_name: &str, z_name: &str, w_name: &str, ) -> Bucketer<'a, (T, U, V, W)> { Bucketer { bucketing_function: &|&(x, y, z, w)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits(), w.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits(), {w_name}.significant_bits())", ), } } pub fn sextuple_max_bit_bucketer< 'a, T: Copy + SignificantBits, U: Copy + SignificantBits, V: Copy + SignificantBits, W: Copy + SignificantBits, X: Copy + SignificantBits, Y: Copy + SignificantBits, >( x_name: &str, y_name: &str, z_name: &str, w_name: &str, v_name: &str, u_name: &str, ) -> Bucketer<'a, (T, U, V, W, X, Y)> { Bucketer { bucketing_function: &|&(x, y, z, w, v, u)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits(), w.significant_bits(), v.significant_bits(), u.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits(), {w_name}.significant_bits(), \ {v_name}.significant_bits(), {u_name}.significant_bits())", ), } } #[allow(clippy::type_complexity)] pub fn octuple_max_bit_bucketer< 'a, T: Copy + SignificantBits, U: Copy + SignificantBits, V: Copy + SignificantBits, W: Copy + SignificantBits, X: Copy + SignificantBits, Y: Copy + SignificantBits, Z: Copy + SignificantBits, A: Copy + SignificantBits, >( x_name: &str, y_name: &str, z_name: &str, w_name: &str, v_name: &str, u_name: &str, t_name: &str, s_name: &str, ) -> Bucketer<'a, (T, U, V, W, X, Y, Z, A)> { Bucketer { bucketing_function: &|&(x, y, z, w, v, u, t, s)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits(), w.significant_bits(), v.significant_bits(), u.significant_bits(), t.significant_bits(), s.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits(), {w_name}.significant_bits(), \ {v_name}.significant_bits(), {u_name}.significant_bits(), \ {t_name}.significant_bits(), {s_name}.significant_bits())", ), } } pub fn triple_1_2_max_bit_bucketer<'a, T: Copy + SignificantBits, U: Copy + SignificantBits, V>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, U, V)> { Bucketer { bucketing_function: &|&(x, y, ref _z)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_2_3_product_bit_bucketer< 'a, T, U: Copy + SignificantBits, V: Copy + SignificantBits, >( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, U, V)> { Bucketer { bucketing_function: &|&(_, y, z)| { usize::exact_from( y.significant_bits() .checked_mul(z.significant_bits()) .unwrap(), ) }, bucketing_label: format!("{x_name}.significant_bits() * {y_name}.significant_bits()"), } } pub fn pair_1_bucketer(x_name: &str) -> Bucketer<'_, (T, U)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(x, _)| usize::exact_from(x), bucketing_label: x_name.to_string(), } } pub fn pair_2_bucketer(y_name: &str) -> Bucketer<'_, (T, U)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, y)| usize::exact_from(y), bucketing_label: y_name.to_string(), } } pub fn pair_2_pair_2_bucketer(y_name: &str) -> Bucketer<'_, (T, (U, V))> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, (_, y))| usize::exact_from(y), bucketing_label: y_name.to_string(), } } pub fn pair_2_unsigned_abs_bucketer(y_name: &str) -> Bucketer<'_, (T, U)> where usize: ExactFrom<::Output>, { Bucketer { bucketing_function: &|&(_, y)| usize::exact_from(y.unsigned_abs()), bucketing_label: y_name.to_string(), } } pub fn triple_2_bucketer(y_name: &str) -> Bucketer<'_, (T, U, V)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, y, _)| usize::exact_from(y), bucketing_label: y_name.to_string(), } } pub fn triple_3_bucketer(z_name: &str) -> Bucketer<'_, (T, U, V)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, _, z)| usize::exact_from(z), bucketing_label: z_name.to_string(), } } pub fn triple_2_unsigned_abs_bucketer( y_name: &str, ) -> Bucketer<'_, (T, U, V)> where usize: ExactFrom<::Output>, { Bucketer { bucketing_function: &|&(_, y, _)| usize::exact_from(y.unsigned_abs()), bucketing_label: y_name.to_string(), } } pub fn pair_2_triple_2_bucketer(y_name: &str) -> Bucketer<'_, (T, (U, V, W))> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, (_, y, _))| usize::exact_from(y), bucketing_label: y_name.to_string(), } } pub fn triple_3_pair_2_bucketer(y_name: &str) -> Bucketer<'_, (T, U, (V, W))> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, _, (_, y))| usize::exact_from(y), bucketing_label: y_name.to_string(), } } pub fn pair_1_bit_bucketer(x_name: &str) -> Bucketer<'_, (T, U)> { Bucketer { bucketing_function: &|&(x, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{x_name}.significant_bits()"), } } pub fn pair_2_bit_bucketer(x_name: &str) -> Bucketer<'_, (T, U)> { Bucketer { bucketing_function: &|&(_, x)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{x_name}.significant_bits()"), } } pub fn triple_1_bit_bucketer( x_name: &str, ) -> Bucketer<'_, (T, U, V)> { Bucketer { bucketing_function: &|&(x, _, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{x_name}.significant_bits()"), } } pub fn triple_3_bit_bucketer( z_name: &str, ) -> Bucketer<'_, (T, U, V)> { Bucketer { bucketing_function: &|&(_, _, z)| usize::exact_from(z.significant_bits()), bucketing_label: format!("{z_name}.significant_bits()"), } } pub fn quadruple_1_2_bit_bucketer( combined_name: &str, ) -> Bucketer<'_, (T, T, U, V)> { Bucketer { bucketing_function: &|&(x_1, x_0, _, _)| { usize::exact_from(if x_1 == T::ZERO { x_0.significant_bits() } else { x_1.significant_bits() + T::WIDTH }) }, bucketing_label: format!("{combined_name}.significant_bits()"), } } pub fn quadruple_3_bucketer(z_name: &str) -> Bucketer<'_, (T, U, V, W)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(_, _, z, _)| usize::exact_from(z), bucketing_label: z_name.to_string(), } } pub fn pair_primitive_int_bit_u64_max_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, u64)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn triple_1_2_primitive_int_bit_u64_max_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, u64, U)> { Bucketer { bucketing_function: &|(x, y, _)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn pair_primitive_int_bit_i64_max_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, i64)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.unsigned_abs())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.unsigned_abs())"), } } pub fn triple_primitive_int_bit_i64_u64_max_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (T, i64, u64)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn quadruple_1_2_3_primitive_int_bit_i64_u64_max_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (T, i64, u64, U)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn pair_1_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (Vec, U)> { Bucketer { bucketing_function: &|(xs, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn pair_1_vec_len_sub_1_bucketer(xs_name: &str) -> Bucketer<'_, (Vec, U)> { Bucketer { bucketing_function: &|(xs, _)| xs.len() - 1, bucketing_label: format!("{xs_name}.len() - 1"), } } pub fn pair_2_vec_len_bucketer(ys_name: &str) -> Bucketer<'_, (T, Vec)> { Bucketer { bucketing_function: &|(_, ys)| ys.len(), bucketing_label: format!("{ys_name}.len()"), } } pub fn triple_1_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (Vec, U, V)> { Bucketer { bucketing_function: &|(xs, _, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn triple_3_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (T, U, Vec)> { Bucketer { bucketing_function: &|(_, _, xs)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn triple_2_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (T, Vec, V)> { Bucketer { bucketing_function: &|(_, xs, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn triple_vec_max_len_bucketer<'a, T, U, V>( xs_name: &str, ys_name: &str, zs_name: &str, ) -> Bucketer<'a, (Vec, Vec, Vec)> { Bucketer { bucketing_function: &|(xs, ys, zs)| max!(xs.len(), ys.len(), zs.len()), bucketing_label: format!("max({xs_name}.len(), {ys_name}.len(), {zs_name}.len())"), } } pub fn triple_1_2_vec_max_len_bucketer<'a, T, U, V>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec, V)> { Bucketer { bucketing_function: &|(xs, ys, _)| max(xs.len(), ys.len()), bucketing_label: format!("max({xs_name}.len(), {ys_name}.len())"), } } pub fn triple_2_3_vec_max_len_bucketer<'a, T, U, V>( ys_name: &str, zs_name: &str, ) -> Bucketer<'a, (T, Vec, Vec)> { Bucketer { bucketing_function: &|(_, xs, ys)| max(xs.len(), ys.len()), bucketing_label: format!("max({ys_name}.len(), {zs_name}.len())"), } } pub fn triple_1_2_vec_min_len_bucketer<'a, T, U, V>( ys_name: &str, zs_name: &str, ) -> Bucketer<'a, (Vec, Vec, V)> { Bucketer { bucketing_function: &|(xs, ys, _)| min(xs.len(), ys.len()), bucketing_label: format!("min({ys_name}.len(), {zs_name}.len())"), } } pub fn triple_2_3_vec_min_len_bucketer<'a, T, U, V>( ys_name: &str, zs_name: &str, ) -> Bucketer<'a, (T, Vec, Vec)> { Bucketer { bucketing_function: &|(_, xs, ys)| min(xs.len(), ys.len()), bucketing_label: format!("min({ys_name}.len(), {zs_name}.len())"), } } pub fn quadruple_2_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (T, Vec, V, W)> { Bucketer { bucketing_function: &|(_, xs, _, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn quadruple_3_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (T, U, Vec, W)> { Bucketer { bucketing_function: &|(_, _, xs, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn quadruple_4_vec_len_bucketer(xs_name: &str) -> Bucketer<'_, (T, U, V, Vec)> { Bucketer { bucketing_function: &|(_, _, _, xs)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn quadruple_1_3_vec_max_len_bucketer<'a, T, U, V, W>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (T, Vec, V, Vec)> { Bucketer { bucketing_function: &|(_, xs, _, ys)| max(xs.len(), ys.len()), bucketing_label: format!("max({xs_name}.len(), {ys_name}.len())"), } } pub fn quintuple_1_vec_len_bucketer( xs_name: &str, ) -> Bucketer<'_, (Vec, U, V, W, X)> { Bucketer { bucketing_function: &|(xs, _, _, _, _)| xs.len(), bucketing_label: format!("{xs_name}.len()"), } } pub fn pair_sum_vec_len_bucketer<'a, T, U>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec)> { Bucketer { bucketing_function: &|(xs, ys)| xs.len() + ys.len(), bucketing_label: format!("{xs_name}.len() + {ys_name}.len()"), } } pub fn triple_2_3_sum_vec_len_bucketer<'a, T, U, V>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (T, Vec, Vec)> { Bucketer { bucketing_function: &|(_, xs, ys)| xs.len() + ys.len(), bucketing_label: format!("{xs_name}.len() + {ys_name}.len()"), } } pub fn triple_2_3_diff_vec_len_bucketer<'a, T, U, V>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (T, Vec, Vec)> { Bucketer { bucketing_function: &|(_, xs, ys)| xs.len() - ys.len(), bucketing_label: format!("{xs_name}.len() - {ys_name}.len()"), } } pub fn quadruple_2_3_diff_vec_len_bucketer<'a, T, U, V, W>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (T, Vec, Vec, W)> { Bucketer { bucketing_function: &|(_, xs, ys, _)| xs.len() - ys.len(), bucketing_label: format!("{xs_name}.len() - {ys_name}.len()"), } } pub fn get_bits_bucketer() -> Bucketer<'static, (T, u64, u64)> { Bucketer { bucketing_function: &|&(_, start, end)| usize::exact_from(end - start), bucketing_label: "end - start".to_string(), } } pub fn assign_bits_bucketer() -> Bucketer<'static, (T, u64, u64, U)> { Bucketer { bucketing_function: &|&(_, start, end, _)| usize::exact_from(end - start), bucketing_label: "end - start".to_string(), } } pub fn pair_1_vec_len_times_pair_2_bits_bucketer<'a, T, U: PrimitiveUnsigned>( xs_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Vec, U)> { Bucketer { bucketing_function: &|(xs, y)| { xs.len() .checked_mul(usize::exact_from(y.significant_bits())) .unwrap() }, bucketing_label: format!("{xs_name}.len() * {y_name}.significant_bits()"), } } pub fn pair_product_vec_len_bucketer<'a, T, U>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec)> { Bucketer { bucketing_function: &|(xs, ys)| xs.len().checked_mul(ys.len()).unwrap(), bucketing_label: format!("{xs_name}.len() * {ys_name}.len()"), } } pub fn triple_1_2_product_vec_len_bucketer<'a, T, U, V>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (Vec, Vec, V)> { Bucketer { bucketing_function: &|(xs, ys, _)| xs.len().checked_mul(ys.len()).unwrap(), bucketing_label: format!("{xs_name}.len() * {ys_name}.len()"), } } pub fn triple_2_bits_times_triple_3_bucketer<'a, T, U, V: Copy>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, V)> where usize: ExactFrom, for<'b> &'b U: SignificantBits, { Bucketer { bucketing_function: &|(_, x, y)| { let x_bits: usize = ExactFrom::::exact_from(x.significant_bits()); x_bits.checked_mul(ExactFrom::::exact_from(*y)).unwrap() }, bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn pair_1_vec_len_times_pair_2_bucketer<'a, T, U: Copy>( xs_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Vec, U)> where usize: ExactFrom, { Bucketer { bucketing_function: &|(xs, y)| xs.len().checked_mul(usize::exact_from(*y)).unwrap(), bucketing_label: format!("{xs_name}.len() * {y_name}"), } } pub fn pair_1_bits_times_pair_2_bucketer<'a, T, U: Copy>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U)> where usize: ExactFrom, for<'b> &'b T: SignificantBits, { Bucketer { bucketing_function: &|(x, y)| { let x_bits: usize = ExactFrom::::exact_from(x.significant_bits()); x_bits.checked_mul(ExactFrom::::exact_from(*y)).unwrap() }, bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn triple_3_pair_1_bits_times_pair_2_bucketer<'a, T, U, V, W: Copy>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (V, W))> where usize: ExactFrom, for<'b> &'b V: SignificantBits, { Bucketer { bucketing_function: &|(_, _, (x, y))| { let x_bits: usize = ExactFrom::::exact_from(x.significant_bits()); x_bits.checked_mul(ExactFrom::::exact_from(*y)).unwrap() }, bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn rational_sequence_len_bucketer<'a, T: Eq>( xs_name: &str, ) -> Bucketer<'a, RationalSequence> { Bucketer { bucketing_function: &RationalSequence::component_len, bucketing_label: format!("{xs_name}.component_len()"), } } pub fn pair_rational_sequence_max_len_bucketer<'a, T: Eq, U: Eq>( xs_name: &str, ys_name: &str, ) -> Bucketer<'a, (RationalSequence, RationalSequence)> { Bucketer { bucketing_function: &|(xs, ys)| max(xs.component_len(), ys.component_len()), bucketing_label: format!("max({xs_name}.component_len(), {ys_name}.component_len())"), } } pub fn pair_1_rational_sequence_len_bucketer<'a, T: Eq, U>( xs_name: &str, ) -> Bucketer<'a, (RationalSequence, U)> { Bucketer { bucketing_function: &|(xs, _)| xs.component_len(), bucketing_label: format!("{xs_name}.component_len()"), } } pub fn quadruple_1_rational_sequence_len_bucketer<'a, T: Eq, U, V, W>( xs_name: &str, ) -> Bucketer<'a, (RationalSequence, U, V, W)> { Bucketer { bucketing_function: &|(xs, _, _, _)| xs.component_len(), bucketing_label: format!("{xs_name}.component_len()"), } } ================================================ FILE: malachite-base/src/test_util/bench/mod.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Parity; use crate::num::conversion::traits::ExactFrom; use crate::test_util::bench::bucketers::Bucketer; use gnuplot::{AxesCommon, Caption, Color, Figure}; use itertools::Itertools; use std::collections::{BTreeMap, HashMap}; use std::iter::Iterator; use std::time::Instant; fn escape_label_string(s: &str) -> String { let mut escaped = String::new(); for c in s.chars() { if c == '_' { escaped.push_str("\\_"); } else if c == '&' { escaped.push_str("\\&"); } else { escaped.push(c); } } escaped } struct BenchmarkSeriesOptions<'a, T: 'a> { pub name: &'a str, pub function: &'a mut dyn FnMut(T), pub color: &'a str, } struct BenchmarkOptions<'a, I: Iterator> where I::Item: 'a, { pub generator: I, pub title: &'a str, pub limit: usize, pub bucketing_function: &'a dyn Fn(&I::Item) -> usize, pub x_axis_label: &'a str, pub y_axis_label: &'a str, pub file_name: String, pub series_options: Vec>, } fn quick_median(xs: &mut [u64]) -> u64 { assert!(!xs.is_empty()); xs.sort_unstable(); let half_index = xs.len() >> 1; if xs.len().odd() { xs[half_index] } else { (xs[half_index - 1] + xs[half_index]) >> 1 } } fn quick_mean(xs: &[u64]) -> u64 { assert!(!xs.is_empty()); let sum: u64 = xs.iter().sum(); sum / u64::exact_from(xs.len()) } fn run_benchmark_internal(mut options: BenchmarkOptions) where I::Item: Clone, { let reps = 5; let min_bucket_size = 2; let mut durations_maps = Vec::new(); for _ in 0..options.series_options.len() { durations_maps.push(HashMap::new()); } for x in options.generator.take(options.limit) { let size = (options.bucketing_function)(&x); for (i, series) in options.series_options.iter_mut().enumerate() { let mut durations_vec = Vec::new(); for _ in 0..reps { let x = x.clone(); let now = Instant::now(); (series.function)(x); durations_vec.push(u64::exact_from(now.elapsed().as_nanos())); } let median_duration = quick_median(&mut durations_vec); durations_maps[i] .entry(size) .or_insert_with(Vec::new) .push(median_duration); } } let mut median_durations_maps = Vec::new(); for durations_map in durations_maps { let mut median_durations_map: BTreeMap = BTreeMap::new(); for (&size, durations) in &durations_map { if durations.len() >= min_bucket_size { median_durations_map.insert(size, quick_mean(durations)); } } median_durations_maps.push(median_durations_map); } let mut fg = Figure::new(); { let axes = fg.axes2d(); axes.set_title(&escape_label_string(options.title), &[]); axes.set_x_label(&escape_label_string(options.x_axis_label), &[]); axes.set_y_label(&escape_label_string(options.y_axis_label), &[]); for (median_durations_map, options) in median_durations_maps .iter() .zip(options.series_options.iter()) { let sizes = median_durations_map .iter() .map(|entry| *entry.0) .collect_vec(); let durations = median_durations_map .iter() .map(|entry| *entry.1) .collect_vec(); axes.lines( &sizes, &durations, &[ Caption(&escape_label_string(options.name)), Color(gnuplot::RGBString(options.color)), ], ); } } fg.echo_to_file(&options.file_name); } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum BenchmarkType { Single, LibraryComparison, EvaluationStrategy, Algorithms, } #[allow(clippy::print_stdout, clippy::type_complexity)] pub fn run_benchmark<'a, I: Iterator>( title: &'a str, benchmark_type: BenchmarkType, generator: I, generation_mode_name: &'a str, limit: usize, file_name: &'a str, bucketer: &Bucketer<'a, I::Item>, series: &mut [(&'a str, &'a mut dyn FnMut(I::Item))], ) where I::Item: Clone, { assert_eq!( benchmark_type == BenchmarkType::Single, series.len() == 1, "Bad benchmark: {title}. \ Benchmarks should have type Single iff they have only one series.", ); if limit == 0 { return; } let title = match benchmark_type { BenchmarkType::Single => title.to_string(), BenchmarkType::LibraryComparison => format!("{title} library comparison"), BenchmarkType::EvaluationStrategy => format!("{title} evaluation strategy"), BenchmarkType::Algorithms => format!("{title} algorithms"), }; println!("benchmarking {generation_mode_name} {title}"); let colors = ["green", "blue", "red", "black", "orange", "yellow", "gray", "purple"]; assert!(series.len() <= colors.len(), "not enough available colors"); let mut series_options = Vec::new(); for (&mut (label, ref mut function), color) in series.iter_mut().zip(colors.iter()) { series_options.push(BenchmarkSeriesOptions { name: label, function, color, }); } let options = BenchmarkOptions { generator, title: &title, limit, bucketing_function: bucketer.bucketing_function, x_axis_label: &bucketer.bucketing_label, y_axis_label: "time (ns)", file_name: file_name.to_string(), series_options, }; run_benchmark_internal(options); } #[allow(clippy::print_stdout, clippy::type_complexity)] pub fn run_benchmark_old<'a, I: Iterator>( title: &'a str, benchmark_type: BenchmarkType, generator: I, generation_mode_name: &'a str, limit: usize, file_name: &'a str, bucketing_function: &'a dyn Fn(&I::Item) -> usize, bucketing_label: &'a str, series: &mut [(&'a str, &'a mut dyn FnMut(I::Item))], ) where I::Item: Clone, { assert_eq!( benchmark_type == BenchmarkType::Single, series.len() == 1, "Bad benchmark: {title}. \ Benchmarks should have type Single iff they have only one series.", ); if limit == 0 { return; } let title = match benchmark_type { BenchmarkType::Single => title.to_string(), BenchmarkType::LibraryComparison => format!("{title} library comparison"), BenchmarkType::EvaluationStrategy => format!("{title} evaluation strategy"), BenchmarkType::Algorithms => format!("{title} algorithms"), }; println!("benchmarking {generation_mode_name} {title}"); let colors = ["green", "blue", "red", "black", "orange", "yellow", "gray", "purple"]; assert!(series.len() <= colors.len(), "not enough available colors"); let mut series_options = Vec::new(); for (&mut (label, ref mut function), color) in series.iter_mut().zip(colors.iter()) { series_options.push(BenchmarkSeriesOptions { name: label, function, color, }); } let options = BenchmarkOptions { generator, title: &title, limit, bucketing_function, x_axis_label: bucketing_label, y_axis_label: "time (ns)", file_name: format!("benchmarks/{file_name}"), series_options, }; run_benchmark_internal(options); } #[macro_export] macro_rules! no_out { ($e:expr) => {{ $e; }}; } pub mod bucketers; ================================================ FILE: malachite-base/src/test_util/common/mod.rs ================================================ // Copyright © 2026 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 std::cmp::Ordering; use std::fmt::Debug; use std::str::FromStr; #[macro_export] macro_rules! assert_panic { ($e: expr) => { let result = catch_unwind(|| $e); assert!(result.is_err()); }; } fn read_strings(strings: &[&str]) -> Vec where T::Err: Debug, { strings.iter().map(|s| s.parse().unwrap()).collect() } fn test_helper_helper< T: Debug + FromStr, U: Debug + Eq, F: FnMut(usize, usize) -> U, G: FnMut(&T, &T) -> U, >( strings: &[&str], mut compare_indices: F, mut compare_elements: G, ) where T::Err: Debug, { let xs = read_strings::(strings); let ys = read_strings::(strings); for (i, x) in xs.iter().enumerate() { for (j, y) in ys.iter().enumerate() { assert_eq!(compare_indices(i, j), compare_elements(x, y)); } } } pub fn test_eq_helper(strings: &[&str]) where T::Err: Debug, { test_helper_helper(strings, |i, j| i == j, |x: &T, y: &T| x == y); } pub fn test_cmp_helper(strings: &[&str]) where T::Err: Debug, { test_helper_helper::(strings, |i, j| i.cmp(&j), Ord::cmp); } pub fn test_custom_cmp_helper Ordering>( strings: &[&str], compare: F, ) where T::Err: Debug, { test_helper_helper(strings, |i, j| i.cmp(&j), compare); } #[macro_export] macro_rules! triple_significant_bits_fn { ($t:ident, $bucketing_function:ident) => { fn $bucketing_function(t: &($t, $t, $t)) -> usize { usize::exact_from(max!( t.0.significant_bits(), t.1.significant_bits(), t.2.significant_bits() )) } }; } pub const TRIPLE_SIGNIFICANT_BITS_LABEL: &str = "max(a.significant_bits(), b.significant_bits(), c.significant_bits())"; pub fn rle_encode(xs: I) -> Vec<(I::Item, usize)> where I::Item: Clone + Eq, { let mut out = Vec::new(); let mut previous: Option = None; let mut count = 0; for x in xs { if let Some(p) = previous.as_ref() { if x == *p { count += 1; } else { out.push((p.clone(), count)); previous = Some(x.clone()); count = 1; } } else { count = 1; previous = Some(x.clone()); } } if let Some(p) = previous { out.push((p, count)); } out } pub fn rle_decode(ps: &[(T, usize)]) -> Vec { let mut out = Vec::new(); for (x, count) in ps { for _ in 0..*count { out.push(x.clone()); } } out } pub fn test_double_ended_iterator_size_hint( mut xs: I, original_expected_size: usize, ) { let original_xs = xs.clone(); let mut expected_size = original_expected_size; for _ in 0..10 { assert_eq!(xs.size_hint(), (expected_size, Some(expected_size))); if xs.next().is_none() { break; }; expected_size -= 1; } let mut xs = original_xs; let mut expected_size = original_expected_size; for _ in 0..10 { assert_eq!(xs.size_hint(), (expected_size, Some(expected_size))); if xs.next_back().is_none() { break; }; expected_size -= 1; } } ================================================ FILE: malachite-base/src/test_util/extra_variadic/mod.rs ================================================ // Copyright © 2026 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 crate::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; use crate::iterators::iterator_cache::IteratorCache; use crate::num::arithmetic::traits::CheckedPow; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::logic::traits::SignificantBits; use crate::num::random::{RandomUnsignedRange, random_unsigned_range}; use crate::random::Seed; use crate::tuples::exhaustive::clone_helper; use crate::tuples::random::next_helper; use crate::unions::UnionFromStrError; use crate::{ custom_tuples, exhaustive_tuples_1_input, exhaustive_unions, lex_custom_tuples, lex_tuples, random_custom_tuples, random_tuples, random_unions, union_struct, }; use std::cmp::max; use std::fmt::{self, Display, Formatter}; 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()) } #[allow(clippy::missing_const_for_fn)] fn unwrap_quadruple( (a, b, c, d): (Option, Option, Option, Option), ) -> (X, Y, Z, W) { (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap()) } 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_custom_tuples!( (pub(crate)), LexTriplesXYY, (X, Y, Y), (None, None, None), unwrap_triple, lex_triples_xyy, [X, I, xs, [0, x_0]], [Y, J, ys, [1, y_1], [2, y_2]] ); 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)), ExhaustiveSextuples1Input, exhaustive_sextuples_1_input, exhaustive_sextuples_from_single, (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] ); 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] ); exhaustive_tuples_1_input!( (pub(crate)), ExhaustiveDuodecuples1Input, exhaustive_duodecuples_1_input, exhaustive_duodecuples_from_single, ( I::Item, I::Item, I::Item, I::Item, 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], [8, output_type_r], [9, output_type_q], [10, output_type_p], [11, output_type_o] ); 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]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXXXY, (X, X, X, Y), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xxxy, exhaustive_quadruples_xxxy_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1], [2, output_type_xs_2]], [Y, J, ys, ys_done, [3, output_type_ys_3]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXXYX, (X, X, Y, X), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xxyx, exhaustive_quadruples_xxyx_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1], [3, output_type_xs_3]], [Y, J, ys, ys_done, [2, output_type_ys_2]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYYX, (X, Y, Y, X), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyyx, exhaustive_quadruples_xyyx_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [3, output_type_xs_3]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYYZ, (X, Y, Y, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyyz, exhaustive_quadruples_xyyz_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]], [Z, K, zs, zs_done, [3, output_type_zs_3]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYZZ, (X, Y, Z, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyzz, exhaustive_quadruples_xyzz_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0]], [Y, J, ys, ys_done, [1, output_type_ys_1]], [Z, K, zs, zs_done, [2, output_type_zs_2], [3, output_type_zs_3]] ); 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_tuples!( (pub(crate)), RandomQuadruples, RandomQuadruplesFromSingle, random_quadruples, random_quadruples_from_single, (I::Item, I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen] ); random_tuples!( (pub(crate)), RandomSextuples, RandomSextuplesFromSingle, random_sextuples, random_sextuples_from_single, (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen], [4, V, M, vs, vs_gen], [5, U, N, us, us_gen] ); random_tuples!( (pub(crate)), RandomOctuples, RandomOctuplesFromSingle, random_octuples, random_octuples_from_single, ( I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item ), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen], [4, V, M, vs, vs_gen], [5, U, N, us, us_gen], [6, T, O, ts, ts_gen], [7, S, P, ss, ss_gen] ); random_tuples!( (pub(crate)), RandomDuodecuples, RandomDuodecuplesFromSingle, random_duodecuples, random_duodecuples_from_single, ( I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item ), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen], [4, V, M, vs, vs_gen], [5, U, N, us, us_gen], [6, T, OI, ts, ts_gen], [7, S, PI, ss, ss_gen], [8, R, QI, rs, rs_gen], [9, Q, RI, qs, qs_gen], [10, P, SI, ps, ps_gen], [11, O, TI, os, os_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_custom_tuples!( (pub(crate)), RandomTriplesXYY, (X, Y, Y), random_triples_xyy, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXXXY, (X, X, X, Y), random_quadruples_xxxy, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_2, x_2]], [Y, J, ys, ys_gen, [y_3, y_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXXYX, (X, X, Y, X), random_quadruples_xxyx, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_3, y_2]], [Y, J, ys, ys_gen, [y_2, x_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYYX, (X, Y, Y, X), random_quadruples_xyyx, [X, I, xs, xs_gen, [x_0, x_0], [x_3, y_1]], [Y, J, ys, ys_gen, [y_1, y_2], [y_2, x_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYXY, (X, Y, X, Y), random_quadruples_xyxy, [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]], [Y, J, ys, ys_gen, [y_1, x_2], [y_3, y_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYYZ, (X, Y, Y, Z), random_quadruples_xyyz, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]], [Z, K, zs, zs_gen, [z_3, z_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYZZ, (X, Y, Z, Z), random_quadruples_xyzz, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1]], [Z, K, zs, zs_gen, [z_2, z_2], [z_3, z_3]] ); 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] ); ================================================ FILE: malachite-base/src/test_util/generators/common.rs ================================================ // Copyright © 2026 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 std::collections::HashMap; use std::marker::PhantomData; pub const TINY_LIMIT: usize = 1000; pub const SMALL_LIMIT: usize = 1000; pub const LARGE_LIMIT: usize = 10000; #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub enum GenMode { Exhaustive, Random, SpecialRandom, } impl GenMode { pub const fn name(self) -> &'static str { match self { Self::Exhaustive => "exhaustive", Self::Random => "random", Self::SpecialRandom => "special_random", } } } pub type It = Box>; #[derive(Clone, Debug)] pub struct GenConfig(HashMap); impl GenConfig { pub fn new() -> Self { Self(HashMap::new()) } pub fn insert(&mut self, key: &str, value: u64) { self.0.insert(key.to_string(), value); } pub fn get_or(&self, key: &'static str, default: u64) -> u64 { *self.0.get(key).unwrap_or(&default) } } impl Default for GenConfig { fn default() -> Self { Self::new() } } pub struct Generator { phantom: PhantomData<*const T>, exhaustive: &'static dyn Fn() -> It, random: &'static dyn Fn(&GenConfig) -> It, special_random: Option<&'static dyn Fn(&GenConfig) -> It>, } impl Generator { pub fn new( exhaustive: &'static dyn Fn() -> It, random: &'static dyn Fn(&GenConfig) -> It, special_random: &'static dyn Fn(&GenConfig) -> It, ) -> Self { Self { phantom: PhantomData, exhaustive, random, special_random: Some(special_random), } } pub fn new_no_special( exhaustive: &'static dyn Fn() -> It, random: &'static dyn Fn(&GenConfig) -> It, ) -> Self { Self { phantom: PhantomData, exhaustive, random, special_random: None, } } fn test_properties_with_config_with_limit_and_optional_exhaustive_limit( &self, config: &GenConfig, mut test: F, limit: usize, exhaustive_limit: bool, ) { if exhaustive_limit { for x in (self.exhaustive)().take(limit) { test(x); } } else { for x in (self.exhaustive)() { test(x); } } for x in (self.random)(config).take(limit) { test(x); } if let Some(special_random) = self.special_random { for x in special_random(config).take(limit) { test(x); } } } pub fn test_properties_with_limit(&self, limit: usize, test: F) { self.test_properties_with_config_with_limit_and_optional_exhaustive_limit( &GenConfig::new(), test, limit, true, ); } fn test_properties_with_config_optional_exhaustive_limit( &self, config: &GenConfig, test: F, exhaustive_limit: bool, ) { self.test_properties_with_config_with_limit_and_optional_exhaustive_limit( config, test, LARGE_LIMIT, exhaustive_limit, ); } pub fn test_properties_with_config(&self, config: &GenConfig, test: F) { self.test_properties_with_config_optional_exhaustive_limit(config, test, true); } #[inline] pub fn test_properties(&self, test: F) { self.test_properties_with_config(&GenConfig::new(), test); } #[inline] pub fn test_properties_with_limit_and_no_exhaustive_limit(&self, test: F) { self.test_properties_with_config_optional_exhaustive_limit(&GenConfig::new(), test, false); } #[inline] pub fn test_properties_no_exhaustive_limit(&self, test: F) { self.test_properties_with_config_optional_exhaustive_limit(&GenConfig::new(), test, false); } pub fn get(&self, gm: GenMode, config: &GenConfig) -> It { match gm { GenMode::Exhaustive => (self.exhaustive)(), GenMode::Random => (self.random)(config), GenMode::SpecialRandom => { (self .special_random .expect("special_random mode unsupported"))(config) } } } } pub fn permute_1_3_2( it: Box>, ) -> Box> { Box::new(it.map(|(a, b, c)| (a, c, b))) } pub fn permute_2_1( it: Box>, ) -> Box> { Box::new(it.map(|(a, b)| (b, a))) } pub fn permute_3_1_4_2( it: Box>, ) -> Box> { Box::new(it.map(|(a, b, c, d)| (c, a, d, b))) } pub fn reshape_1_2_to_3( it: Box>, ) -> Box> { Box::new(it.map(|(a, (b, c))| (a, b, c))) } pub fn reshape_1_3_to_4( it: Box>, ) -> Box> { Box::new(it.map(|(a, (b, c, d))| (a, b, c, d))) } pub fn reshape_2_1_to_3( it: Box>, ) -> Box> { Box::new(it.map(|((a, b), c)| (a, b, c))) } pub fn reshape_2_1_1_to_4( it: Box>, ) -> Box> { Box::new(it.map(|((a, b), c, d)| (a, b, c, d))) } #[allow(clippy::type_complexity)] pub fn reshape_2_2_to_4( it: Box>, ) -> Box> { Box::new(it.map(|((a, b), (c, d))| (a, b, c, d))) } pub fn reshape_3_1_to_4( it: Box>, ) -> Box> { Box::new(it.map(|((a, b, c), d)| (a, b, c, d))) } ================================================ FILE: malachite-base/src/test_util/generators/exhaustive.rs ================================================ // Copyright © 2026 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 crate::bools::exhaustive::{ExhaustiveBools, exhaustive_bools}; use crate::chars::constants::NUMBER_OF_CHARS; use crate::chars::exhaustive::{exhaustive_ascii_chars, exhaustive_chars}; use crate::iterators::bit_distributor::BitDistributorOutputType; use crate::iterators::iter_windows; use crate::max; use crate::num::arithmetic::traits::CoprimeWith; use crate::num::arithmetic::traits::{ ArithmeticCheckedShl, CheckedNeg, DivRound, Parity, PowerOf2, ShrRound, UnsignedAbs, }; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::options::exhaustive::{ exhaustive_from_sci_string_options, exhaustive_sci_size_options, exhaustive_to_sci_options, }; use crate::num::conversion::string::options::{FromSciStringOptions, SciSizeOptions, ToSciOptions}; use crate::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, HasHalf, JoinHalves, RoundingFrom, SaturatingFrom, SplitInHalf, WrappingFrom, }; use crate::num::exhaustive::{ ExhaustiveSigneds, PrimitiveIntIncreasingRange, exhaustive_finite_primitive_floats, exhaustive_natural_signeds, exhaustive_negative_signeds, exhaustive_nonzero_finite_primitive_floats, exhaustive_nonzero_signeds, exhaustive_positive_finite_primitive_floats, exhaustive_positive_primitive_ints, exhaustive_primitive_float_range, exhaustive_primitive_floats, exhaustive_signed_inclusive_range, exhaustive_signed_range, exhaustive_signeds, exhaustive_unsigneds, primitive_int_increasing_inclusive_range, primitive_int_increasing_range, }; use crate::num::float::NiceFloat; use crate::num::iterators::{bit_distributor_sequence, ruler_sequence}; use crate::num::logic::traits::{BitBlockAccess, LeadingZeros}; use crate::rational_sequences::RationalSequence; use crate::rational_sequences::exhaustive::exhaustive_rational_sequences; use crate::rounding_modes::RoundingMode::{self, *}; use crate::rounding_modes::exhaustive::exhaustive_rounding_modes; use crate::slices::slice_test_zero; use crate::strings::exhaustive::{exhaustive_strings, exhaustive_strings_using_chars}; use crate::strings::{StringsFromCharVecs, strings_from_char_vecs}; use crate::test_util::extra_variadic::{ ExhaustiveTriples1Input, ExhaustiveTriplesXXY, Union3, exhaustive_duodecuples_from_single, exhaustive_octuples_from_single, exhaustive_quadruples_from_single, exhaustive_quadruples_xxxy, exhaustive_quadruples_xxxy_custom_output, exhaustive_quadruples_xxyx, exhaustive_quadruples_xyyx, exhaustive_quadruples_xyyz, exhaustive_quadruples_xyyz_custom_output, exhaustive_quadruples_xyzz, exhaustive_sextuples_from_single, exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, exhaustive_triples_xyx, exhaustive_triples_xyx_custom_output, lex_triples_from_single, lex_triples_xyy, lex_union3s, }; use crate::test_util::generators::common::{ It, permute_1_3_2, permute_2_1, permute_3_1_4_2, reshape_1_2_to_3, reshape_2_1_1_to_4, reshape_2_1_to_3, reshape_2_2_to_4, reshape_3_1_to_4, }; use crate::test_util::generators::{ digits_valid, exhaustive_pairs_big_small, exhaustive_pairs_big_tiny, large_exponent, signed_assign_bits_valid, smallest_invalid_value, unsigned_assign_bits_valid, }; use crate::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use crate::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use crate::test_util::num::float::PRIMITIVE_FLOAT_CHARS; use crate::test_util::rounding_modes::ROUNDING_MODE_CHARS; use crate::tuples::exhaustive::{ ExhaustiveDependentPairsYsGenerator, ExhaustivePairs, ExhaustivePairs1Input, ExhaustiveQuadruples, ExhaustiveTriples, ExhaustiveTriplesXYY, exhaustive_dependent_pairs, exhaustive_ordered_unique_pairs, exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_quadruples, exhaustive_triples, exhaustive_triples_custom_output, exhaustive_triples_xyy, exhaustive_triples_xyy_custom_output, lex_pairs, lex_pairs_from_single, }; use crate::vecs::exhaustive::{ ExhaustiveFixedLengthVecs1Input, ExhaustiveVecs, LexFixedLengthVecsFromSingle, ShortlexVecs, exhaustive_vecs, exhaustive_vecs_fixed_length_from_single, exhaustive_vecs_length_inclusive_range, exhaustive_vecs_min_length, lex_vecs_fixed_length_from_single, shortlex_vecs, shortlex_vecs_length_inclusive_range, shortlex_vecs_min_length, }; use itertools::{Itertools, repeat_n}; use std::cmp::{max, min}; use std::iter::once; use std::marker::PhantomData; use std::vec::IntoIter; // general fn add_mul_inputs_valid(x: T, y: T, z: T) -> bool { x.checked_add_mul(y, z).is_some() } fn sub_mul_inputs_valid(x: T, y: T, z: T) -> bool { x.checked_sub_mul(y, z).is_some() } // -- bool -- pub fn exhaustive_bool_gen() -> It { Box::new(exhaustive_bools()) } // -- char -- pub fn exhaustive_char_gen() -> It { Box::new(exhaustive_chars()) } #[allow(unstable_name_collisions)] pub fn exhaustive_char_gen_var_1() -> It { Box::new(char::MIN..char::MAX) } #[allow(unstable_name_collisions)] pub fn exhaustive_char_gen_var_2() -> It { Box::new('\u{1}'..=char::MAX) } // -- (char, char) -- pub fn exhaustive_char_pair_gen() -> It<(char, char)> { Box::new(exhaustive_pairs_from_single(exhaustive_chars())) } // -- FromSciStringOptions -- pub fn exhaustive_from_sci_string_options_gen() -> It { Box::new(exhaustive_from_sci_string_options()) } // -- (FromSciStringOptions, PrimitiveUnsigned) -- pub fn exhaustive_from_sci_string_options_unsigned_pair_gen_var_1() -> It<(FromSciStringOptions, T)> { Box::new(exhaustive_pairs( exhaustive_from_sci_string_options(), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )) } // -- (FromSciStringOptions, RoundingMode) -- pub fn exhaustive_from_sci_string_options_rounding_mode_pair_gen() -> It<(FromSciStringOptions, RoundingMode)> { Box::new(exhaustive_pairs( exhaustive_from_sci_string_options(), exhaustive_rounding_modes(), )) } // -- PrimitiveFloat -- pub fn exhaustive_primitive_float_gen() -> It { Box::new(exhaustive_primitive_floats()) } pub fn exhaustive_primitive_float_gen_var_1() -> It { Box::new(exhaustive_primitive_float_range( T::NEGATIVE_ONE / T::TWO, T::INFINITY, )) } struct ExhaustivePositiveNaturalFloats { phantom: PhantomData<*const T>, done: bool, exponent: i64, limit: u64, mantissa: u64, } impl Iterator for ExhaustivePositiveNaturalFloats { type Item = T; fn next(&mut self) -> Option { if self.done { None } else { let f = T::from_integer_mantissa_and_exponent(self.mantissa, self.exponent).unwrap(); if f == T::MAX_FINITE { self.done = true; } else { self.mantissa += 1; if self.mantissa == self.limit { self.mantissa >>= 1; self.exponent += 1; self.limit = u64::power_of_2(T::MANTISSA_WIDTH + 1); } } Some(f) } } } fn exhaustive_positive_natural_floats() -> ExhaustivePositiveNaturalFloats { ExhaustivePositiveNaturalFloats { phantom: PhantomData, done: false, exponent: 0, limit: u64::power_of_2(T::MANTISSA_WIDTH + 1), mantissa: 1, } } pub fn exhaustive_primitive_float_gen_var_2() -> It { Box::new(once(T::ZERO).chain(exhaustive_positive_natural_floats())) } pub fn exhaustive_primitive_float_gen_var_3() -> It { Box::new(exhaustive_positive_finite_primitive_floats::().filter(|f| !f.is_integer())) } pub fn exhaustive_primitive_float_gen_var_4() -> It { let limit = T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)).unwrap(); Box::new( exhaustive_positive_natural_floats::() .take_while(move |&f| f <= limit) .map(|f| f - T::ONE / T::TWO), ) } pub fn exhaustive_primitive_float_gen_var_5() -> It { Box::new( lex_pairs( exhaustive_primitive_float_gen_var_2::(), exhaustive_bools(), ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn exhaustive_primitive_float_gen_var_6() -> It { Box::new( lex_pairs( exhaustive_primitive_float_gen_var_3::(), exhaustive_bools(), ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn exhaustive_primitive_float_gen_var_7() -> It { Box::new( lex_pairs( exhaustive_primitive_float_gen_var_4::(), exhaustive_bools(), ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn exhaustive_primitive_float_gen_var_8() -> It { Box::new(exhaustive_finite_primitive_floats()) } pub fn exhaustive_primitive_float_gen_var_9() -> It { Box::new(exhaustive_primitive_floats::().filter(|&f| !f.is_nan() && f != T::INFINITY)) } pub fn exhaustive_primitive_float_gen_var_10() -> It { Box::new( exhaustive_primitive_floats::().filter(|&f| !f.is_nan() && f != T::NEGATIVE_INFINITY), ) } pub fn exhaustive_primitive_float_gen_var_11() -> It { Box::new(exhaustive_primitive_floats::().filter(|&f| !f.is_nan())) } pub fn exhaustive_primitive_float_gen_var_12() -> It { Box::new(exhaustive_nonzero_finite_primitive_floats()) } pub fn exhaustive_primitive_float_gen_var_13() -> It where NiceFloat: TryFrom, { Box::new( exhaustive_unsigneds::().filter_map(|x| NiceFloat::::try_from(x).ok().map(|x| x.0)), ) } pub fn exhaustive_primitive_float_gen_var_14() -> It where NiceFloat: TryFrom, { Box::new( exhaustive_signeds::().filter_map(|x| NiceFloat::::try_from(x).ok().map(|x| x.0)), ) } pub fn exhaustive_primitive_float_gen_var_15< T: PrimitiveFloat, U: ConvertibleFrom + PrimitiveInt, >() -> It { Box::new(exhaustive_primitive_floats::().filter(|&f| !U::convertible_from(f))) } pub fn exhaustive_primitive_float_gen_var_16< T: PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >() -> It { let limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( exhaustive_positive_natural_floats::() .take_while(move |&f| f <= limit) .map(|f| f - T::ONE / T::TWO), ) } pub fn exhaustive_primitive_float_gen_var_17< T: PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >() -> It { let min_limit = min( NiceFloat(-T::rounding_from(U::MIN, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; let max_limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( exhaustive_positive_natural_floats::() .take_while(move |&f| f <= max_limit) .map(|f| f - T::ONE / T::TWO) .interleave( exhaustive_positive_natural_floats::() .take_while(move |&f| f <= min_limit) .map(|f| T::ONE / T::TWO - f), ), ) } pub fn exhaustive_primitive_float_gen_var_18() -> It { Box::new(exhaustive_positive_finite_primitive_floats::()) } pub fn exhaustive_primitive_float_gen_var_19() -> It { Box::new(exhaustive_primitive_float_range( T::ZERO, T::power_of_2(T::MAX_EXPONENT), )) } // -- (PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_primitive_float_pair_gen() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single(exhaustive_primitive_floats())) } pub fn exhaustive_primitive_float_pair_gen_var_1() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single( exhaustive_primitive_floats::().filter(|&f| !f.is_nan()), )) } // -- (PrimitiveFloat, PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_primitive_float_triple_gen() -> It<(T, T, T)> { Box::new(exhaustive_triples_from_single(exhaustive_primitive_floats())) } // -- (PrimitiveFloat, PrimitiveInt) -- pub fn exhaustive_primitive_float_primitive_int_pair_gen_var_1< T: PrimitiveFloat, U: PrimitiveInt, >() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_finite_primitive_floats(), exhaustive_positive_primitive_ints(), )) } // -- (PrimitiveFloat, PrimitiveSigned) -- pub fn exhaustive_primitive_float_signed_pair_gen() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_primitive_floats(), exhaustive_signeds(), )) } pub fn exhaustive_primitive_float_signed_pair_gen_var_1() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_finite_primitive_floats(), exhaustive_signeds(), )) } pub fn exhaustive_primitive_float_signed_pair_gen_var_2() -> It<(T, i64)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_primitive_float_range(T::ONE, T::TWO), exhaustive_signed_inclusive_range(T::MIN_EXPONENT, T::MAX_EXPONENT), ) .filter(|&(m, e)| m.precision() <= T::max_precision_for_sci_exponent(e)), ) } pub fn exhaustive_primitive_float_signed_pair_gen_var_3() -> It<(T, i64)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_primitive_float_range(T::ONE, T::TWO), exhaustive_signeds(), )) } pub fn exhaustive_primitive_float_signed_pair_gen_var_4() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_primitive_floats(), exhaustive_signeds(), )) } // -- (PrimitiveFloat, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_primitive_float_signed_unsigned_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { reshape_1_2_to_3(Box::new(exhaustive_pairs_big_small( exhaustive_primitive_floats(), exhaustive_pairs(exhaustive_signeds(), exhaustive_positive_primitive_ints()), ))) } // -- (PrimitiveFloat, PrimitiveUnsigned) -- pub fn exhaustive_primitive_float_unsigned_pair_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_finite_primitive_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_primitive_float_unsigned_pair_gen_var_2() -> It<(T, u64)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_primitive_float_range(T::ONE, T::TWO), exhaustive_unsigneds(), )) } pub fn exhaustive_primitive_float_unsigned_pair_gen_var_3< T: PrimitiveFloat, U: PrimitiveUnsigned, >() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_primitive_floats(), exhaustive_positive_primitive_ints(), )) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_positive_finite_primitive_floats(), exhaustive_unsigneds(), ), exhaustive_rounding_modes(), ))) } pub fn exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_2() -> It<(T, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_primitive_float_range(T::ONE, T::TWO), exhaustive_unsigneds(), ), exhaustive_rounding_modes(), ))) } // var 3 is in malachite-float. // -- (PrimitiveFloat, RoundingMode) -- pub(crate) fn float_rounding_mode_filter_var_1(p: &(T, RoundingMode)) -> bool { let &(f, rm) = p; match rm { Floor | Up => f >= T::ZERO, Ceiling | Down => f > T::NEGATIVE_ONE, Nearest => f >= T::NEGATIVE_ONE / T::TWO, Exact => f >= T::ZERO && f.is_integer(), } } pub fn exhaustive_primitive_float_rounding_mode_pair_gen_var_1() -> It<(T, RoundingMode)> { Box::new( lex_pairs( exhaustive_finite_primitive_floats(), exhaustive_rounding_modes(), ) .filter(float_rounding_mode_filter_var_1), ) } pub fn exhaustive_primitive_float_rounding_mode_pair_gen_var_2() -> It<(T, RoundingMode)> { Box::new( lex_pairs( exhaustive_finite_primitive_floats::(), exhaustive_rounding_modes(), ) .filter(|&(f, rm)| rm != Exact || f.is_integer()), ) } pub fn exhaustive_primitive_float_rounding_mode_pair_gen_var_3< T: PrimitiveFloat + RoundingFrom, U: ConvertibleFrom + PrimitiveInt, >() -> It<(T, RoundingMode)> { let f_min = T::rounding_from(U::MIN, Down).0; let f_max = T::rounding_from(U::MAX, Down).0; Box::new( lex_pairs( exhaustive_primitive_floats::().filter(|f| !f.is_nan()), exhaustive_rounding_modes(), ) .filter(move |&(f, rm)| match rm { Up => f >= f_min && f <= f_max, Ceiling => f <= f_max, Floor => f >= f_min, Down | Nearest => true, Exact => U::convertible_from(f), }), ) } // -- PrimitiveInt -- pub fn exhaustive_primitive_int_gen_var_1() -> It { Box::new(exhaustive_positive_primitive_ints()) } pub fn exhaustive_primitive_int_gen_var_2() -> It { Box::new(primitive_int_increasing_inclusive_range(T::TWO, T::MAX)) } pub fn exhaustive_primitive_int_gen_var_3() -> It { Box::new(primitive_int_increasing_range(T::ZERO, T::exact_from(36))) } pub fn exhaustive_primitive_int_gen_var_4() -> It { Box::new(primitive_int_increasing_inclusive_range( T::TWO, T::exact_from(36), )) } pub fn exhaustive_primitive_int_gen_var_5() -> It { Box::new(primitive_int_increasing_inclusive_range( T::power_of_2(T::WIDTH - 2), T::MAX, )) } pub fn exhaustive_primitive_int_gen_var_6() -> It { Box::new(primitive_int_increasing_inclusive_range( T::wrapping_from(5u8), T::MAX, )) } // -- (PrimitiveInt, PrimitiveInt) -- pub fn exhaustive_primitive_int_pair_gen_var_1 + PrimitiveInt>() -> It<(T, U)> { Box::new(lex_pairs( exhaustive_positive_primitive_ints(), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )) } pub fn exhaustive_primitive_int_pair_gen_var_2() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_primitive_ints(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_primitive_int_pair_gen_var_3() -> T1 { Box::new(exhaustive_pairs_big_small( exhaustive_positive_primitive_ints(), primitive_int_increasing_inclusive_range(U::TWO, U::MAX), )) } pub fn exhaustive_primitive_int_pair_gen_var_4() -> It<(T, T)> { Box::new(exhaustive_ordered_unique_pairs( exhaustive_positive_primitive_ints(), )) } // -- (PrimitiveInt, PrimitiveUnsigned) -- pub fn exhaustive_primitive_int_unsigned_pair_gen_var_1() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_primitive_ints(), exhaustive_unsigneds(), )) } pub fn exhaustive_primitive_int_unsigned_pair_gen_var_2() -> It<(T, U)> { Box::new(exhaustive_pairs( primitive_int_increasing_inclusive_range(T::power_of_2(T::WIDTH - 2), T::MAX), exhaustive_unsigneds(), )) } pub fn exhaustive_primitive_int_unsigned_pair_gen_var_3() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single( primitive_int_increasing_inclusive_range(T::TWO, T::MAX), )) } // -- (PrimitiveInt, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_primitive_int_unsigned_unsigned_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >() -> It<(T, U, U)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_positive_primitive_ints(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(x, y, z): (T, U, U)| y.checked_add(z).map(|new_z| (x, y, new_z))), ) } // -- (PrimitiveInt, RoundingMode) -- pub fn exhaustive_primitive_int_rounding_mode_pair_gen_var_1() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_positive_primitive_ints(), exhaustive_rounding_modes(), )) } pub fn exhaustive_primitive_int_rounding_mode_pair_gen_var_2() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_positive_primitive_ints(), exhaustive_rounding_modes().filter(|&rm| rm != Exact), )) } // -- PrimitiveSigned -- pub fn exhaustive_signed_gen() -> It { Box::new(exhaustive_signeds()) } pub fn exhaustive_signed_gen_var_1() -> It { Box::new(exhaustive_signed_inclusive_range(T::MIN + T::ONE, T::MAX)) } pub fn exhaustive_signed_gen_var_2() -> It { Box::new(exhaustive_natural_signeds()) } pub fn exhaustive_signed_gen_var_3() -> It { Box::new(exhaustive_signeds().filter(|&x| x != T::ZERO && x != T::NEGATIVE_ONE)) } pub fn exhaustive_signed_gen_var_4() -> It { Box::new(exhaustive_negative_signeds()) } pub fn exhaustive_signed_gen_var_5() -> It { Box::new(exhaustive_nonzero_signeds()) } pub fn exhaustive_signed_gen_var_6 + PrimitiveFloat>() -> It { Box::new(exhaustive_signeds().filter(|&x| U::convertible_from(x))) } pub fn exhaustive_signed_gen_var_7 + PrimitiveFloat>() -> It { Box::new( primitive_int_increasing_inclusive_range( T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .interleave( primitive_int_increasing_inclusive_range( T::MIN, T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT).saturating_neg(), ) .rev(), ) .filter(|&x| !U::convertible_from(x)), ) } pub fn exhaustive_signed_gen_var_8 + PrimitiveFloat>() -> It { Box::new( iter_windows( 2, primitive_int_increasing_inclusive_range( T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter(|&x| U::convertible_from(x)), ) .filter_map(|xs| { let mut xs = xs.into_iter(); let a = xs.next().unwrap(); let diff = xs.next().unwrap() - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }) .interleave( iter_windows( 2, primitive_int_increasing_inclusive_range( T::MIN, T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT) .checked_neg() .unwrap(), ) .rev() .filter(|&x| U::convertible_from(x)), ) .filter_map(|xs| { let mut xs = xs.into_iter(); let a = xs.next().unwrap(); let diff = a - xs.next().unwrap(); if diff.even() { // This happens almost always Some(a - (diff >> 1)) } else { None } }), ), ) } pub fn exhaustive_signed_gen_var_9< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> It { let limit = S::wrapping_from(U::wrapping_from(S::MAX).floor_sqrt()); Box::new(exhaustive_signed_inclusive_range(-limit, limit)) } pub fn exhaustive_signed_gen_var_10() -> It { Box::new(exhaustive_signed_inclusive_range( T::MIN_EXPONENT, T::MAX_EXPONENT, )) } pub fn exhaustive_signed_gen_var_11() -> It { Box::new(exhaustive_signeds().filter(|&x| x != T::ZERO && x != T::MIN)) } pub fn exhaustive_signed_gen_var_12() -> It { Box::new( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), ) } // -- (PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_signed_pair_gen() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single(exhaustive_signeds())) } pub fn exhaustive_signed_pair_gen_var_1() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single(exhaustive_natural_signeds()) .interleave(exhaustive_pairs_from_single(exhaustive_negative_signeds())), ) } pub fn exhaustive_signed_pair_gen_var_3() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_signeds(), exhaustive_signeds(), )) } struct TakeWhileExtra bool> { xs: I, p: P, false_seen: bool, } impl bool> Iterator for TakeWhileExtra { type Item = I::Item; fn next(&mut self) -> Option { loop { if let Some(x) = self.xs.next() { if (self.p)(&x) { return Some(x); } else if self.false_seen { return None; } self.false_seen = true; } else { return None; } } } } #[inline] const fn take_while_extra bool>( xs: I, p: P, ) -> TakeWhileExtra { TakeWhileExtra { xs, p, false_seen: false, } } struct SignedDivisiblePairsGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for SignedDivisiblePairsGenerator { #[inline] fn get_ys(&self, y: &T) -> It { // A simple take_while doesn't work. For example, if T is i8 and y is 64, trying to // checked-multiply y by the exhaustive signeds gives [Some(0), Some(64), Some(-64), None, // Some(-128), None, None, ...], where the first None corresponds to 128, which is not // representable as an i8. Doing a take_while would lose the Some(-128). Instead, we use // take_while_extra, which is like a take_while, but it waits until it sees a second None to // stop iterating. let y = *y; Box::new( take_while_extra( exhaustive_signeds().map(move |k| y.checked_mul(k)), Option::is_some, ) .map(Option::unwrap), ) } } pub fn exhaustive_signed_pair_gen_var_4() -> It<(T, T)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_nonzero_signeds(), SignedDivisiblePairsGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_signed_pair_gen_var_5() -> It<(T, T)> { Box::new( exhaustive_pairs(exhaustive_signeds(), exhaustive_nonzero_signeds()) .filter(|&(x, y)| x != T::MIN || y != T::NEGATIVE_ONE), ) } pub fn exhaustive_signed_pair_gen_var_6() -> It<(T, T)> { Box::new( exhaustive_pairs(exhaustive_signeds::(), exhaustive_nonzero_signeds::()) .filter(|&(x, y)| !x.divisible_by(y)), ) } pub fn exhaustive_signed_pair_gen_var_7() -> It<(T, T)> { Box::new(exhaustive_pairs( exhaustive_signeds(), exhaustive_nonzero_signeds(), )) } pub fn exhaustive_signed_pair_gen_var_8() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single(exhaustive_natural_signeds())) } pub fn exhaustive_signed_pair_gen_var_9() -> It<(T, T)> { Box::new(exhaustive_pairs( exhaustive_signeds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_signed_pair_gen_var_10() -> It<(T, T)> where ::Output: PrimitiveUnsigned, { Box::new( exhaustive_pairs_from_single( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), ) .filter(|&(a, b): &(T, T)| a.unsigned_abs().coprime_with(b.unsigned_abs())), ) } pub fn exhaustive_signed_pair_gen_var_11< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >() -> It<(S, S)> { Box::new( exhaustive_pairs_from_single(exhaustive_signeds()) .filter(|&(x, y): &(S, S)| x.unsigned_abs().coprime_with(y.unsigned_abs())), ) } pub fn exhaustive_signed_pair_gen_var_12() -> It<(T, U)> { Box::new(exhaustive_pairs(exhaustive_signeds(), exhaustive_signeds())) } pub fn exhaustive_signed_pair_gen_var_13() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single(exhaustive_signeds()) .filter(|&(n, k)| T::checked_binomial_coefficient(n, k).is_some()), ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_signed_triple_gen() -> It<(T, T, T)> { Box::new(exhaustive_triples_from_single(exhaustive_signeds())) } pub fn exhaustive_signed_triple_gen_var_1() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_signeds()) .filter(|&(x, y, z)| add_mul_inputs_valid(x, y, z)), ) } pub fn exhaustive_signed_triple_gen_var_2() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_signeds()) .filter(|&(x, y, z)| sub_mul_inputs_valid(x, y, z)), ) } pub fn exhaustive_signed_triple_gen_var_3() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_natural_signeds()) .interleave(exhaustive_triples_from_single(exhaustive_negative_signeds())), ) } struct SignedModEqTriplesInnerGenerator { phantom: PhantomData<(U, S)>, } impl> ExhaustiveDependentPairsYsGenerator<(U, U), (S, S), It<(S, S)>> for SignedModEqTriplesInnerGenerator { #[inline] fn get_ys(&self, p: &(U, U)) -> It<(S, S)> { let &(m, k) = p; if k == U::ZERO { Box::new(exhaustive_signeds().map(|x| (x, x))) } else { let d = m.checked_mul(k).unwrap(); let d_s = S::wrapping_from(d); Box::new( exhaustive_signed_inclusive_range(S::MIN, S::MAX.wrapping_sub(d_s)) .map(move |n| (n, n.wrapping_add(d_s))) .interleave( exhaustive_signed_inclusive_range(S::MIN, S::MAX.wrapping_sub(d_s)) .map(move |n| (n.wrapping_add(d_s), n)), ), ) } } } struct SignedModEqTriplesGenerator { phantom: PhantomData<(U, S)>, } impl + WrappingFrom> ExhaustiveDependentPairsYsGenerator> for SignedModEqTriplesGenerator { #[inline] fn get_ys(&self, m: &S) -> It<(S, S)> { let m = *m; let m_abs = m.unsigned_abs(); if m == S::ZERO { Box::new(exhaustive_signeds().map(|x| (x, x))) } else { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(U::ZERO, U::MAX / m_abs) .map(move |k| (m_abs, k)), SignedModEqTriplesInnerGenerator { phantom: PhantomData, }, ) .map(|p| p.1), ) } } } pub fn exhaustive_signed_triple_gen_var_4< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >() -> It<(S, S, S)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_signeds(), SignedModEqTriplesGenerator { phantom: PhantomData, }, )))) } pub fn exhaustive_signed_triple_gen_var_5() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_signeds::()) .filter(|&(x, y, m)| !x.eq_mod(y, m)), ) } pub fn exhaustive_signed_triple_gen_var_6() -> It<(T, T, T)> { Box::new(exhaustive_triples_xxy( exhaustive_signeds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_signed_triple_gen_var_7() -> It<(T, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_signeds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), )) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_signed_quadruple_gen() -> It<(T, T, T, T)> { Box::new(exhaustive_quadruples_from_single(exhaustive_signeds())) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_signed_signed_signed_unsigned_quadruple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(T, T, T, U)> { Box::new(exhaustive_quadruples_xxxy_custom_output( exhaustive_signeds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- struct SignedModPow2EqTriplesInnerGenerator { phantom: PhantomData<(U, S)>, } impl> ExhaustiveDependentPairsYsGenerator<(u64, U), (S, S), It<(S, S)>> for SignedModPow2EqTriplesInnerGenerator { #[inline] fn get_ys(&self, p: &(u64, U)) -> It<(S, S)> { let &(pow, k) = p; if k == U::ZERO { Box::new(exhaustive_signeds().map(|x| (x, x))) } else { let d = k << pow; let d_s = S::wrapping_from(d); Box::new( exhaustive_signed_inclusive_range(S::MIN, S::MAX.wrapping_sub(d_s)) .map(move |n| (n, n.wrapping_add(d_s))) .interleave( exhaustive_signed_inclusive_range(S::MIN, S::MAX.wrapping_sub(d_s)) .map(move |n| (n.wrapping_add(d_s), n)), ), ) } } } struct SignedModPow2EqTriplesGenerator { phantom: PhantomData<(U, S)>, } impl> ExhaustiveDependentPairsYsGenerator> for SignedModPow2EqTriplesGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It<(S, S)> { let pow = *pow; if pow >= S::WIDTH { Box::new(exhaustive_signeds().map(|x| (x, x))) } else { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(U::ZERO, U::MAX >> pow) .map(move |k| (pow, k)), SignedModPow2EqTriplesInnerGenerator { phantom: PhantomData, }, ) .map(|p| p.1), ) } } } pub fn exhaustive_signed_signed_unsigned_triple_gen_var_1< U: PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, >() -> It<(S, S, u64)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), SignedModPow2EqTriplesGenerator:: { phantom: PhantomData, }, )))) } pub fn exhaustive_signed_signed_unsigned_triple_gen_var_2() -> It<(T, T, u64)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_signeds::(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter(|&(x, y, pow)| !x.eq_mod_power_of_2(y, pow)), ) } pub fn exhaustive_signed_signed_unsigned_triple_gen_var_3< T: PrimitiveSigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { reshape_1_2_to_3(Box::new(exhaustive_pairs_big_small( exhaustive_signeds(), exhaustive_pairs(exhaustive_signeds(), exhaustive_positive_primitive_ints()), ))) } // -- (PrimitiveSigned, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_signed_signed_rounding_mode_triple_gen_var_1() -> It<(T, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs(exhaustive_signeds::(), exhaustive_nonzero_signeds::()), exhaustive_rounding_modes(), ) .filter(|&((x, y), rm)| { (x != T::MIN || y != T::NEGATIVE_ONE) && (rm != Exact || x.divisible_by(y)) }), )) } fn round_to_multiple_unsigned_helper(x: T, y: T, rm: RoundingMode) -> bool { if x == y { true } else if y == T::ZERO { rm == Down || rm == Floor || rm == Nearest } else { x.div_round(y, rm).0.checked_mul(y).is_some() } } fn round_to_multiple_signed_helper< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >( x: S, y: S, rm: RoundingMode, ) -> bool { let x_abs = x.unsigned_abs(); let y_abs = y.unsigned_abs(); if x >= S::ZERO { round_to_multiple_unsigned_helper(x_abs, y_abs, rm) && S::convertible_from(x_abs.round_to_multiple(y_abs, rm).0) } else if !round_to_multiple_unsigned_helper(x_abs, y_abs, -rm) { false } else { let abs_result = x_abs.round_to_multiple(y_abs, -rm).0; abs_result == S::MIN.unsigned_abs() || S::try_from(abs_result) .ok() .and_then(CheckedNeg::checked_neg) .is_some() } } pub(crate) fn round_to_multiple_signed_filter_map< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >( x: S, y: S, rm: RoundingMode, ) -> Option<(S, S, RoundingMode)> { if rm == Exact { x.checked_mul(y).map(|product| (product, y, rm)) } else if round_to_multiple_signed_helper(x, y, rm) { Some((x, y, rm)) } else { None } } pub fn exhaustive_signed_signed_rounding_mode_triple_gen_var_2< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >() -> It<(S, S, RoundingMode)> { Box::new( lex_pairs( exhaustive_pairs(exhaustive_signeds(), exhaustive_nonzero_signeds()), exhaustive_rounding_modes(), ) .filter_map(|((x, y), rm)| round_to_multiple_signed_filter_map::(x, y, rm)), ) } pub fn exhaustive_signed_signed_rounding_mode_triple_gen_var_3< T: PrimitiveSigned, U: PrimitiveSigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_signeds::(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .filter(|&((x, pow), rm)| { rm != Exact || pow <= U::ZERO || x.divisible_by_power_of_2(pow.exact_into()) }), )) } pub fn exhaustive_signed_signed_rounding_mode_triple_gen_var_4< T: PrimitiveSigned, U: PrimitiveSigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_signeds::(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .filter(|&((x, pow), rm)| { let pow: i64 = pow.exact_into(); rm != Exact || pow >= 0 || x.divisible_by_power_of_2(pow.unsigned_abs()) }), )) } // -- (PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_signed_unsigned_pair_gen() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_signeds(), exhaustive_unsigneds(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_2() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_signeds(), exhaustive_unsigneds(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_3() -> It<(T, u64)> { Box::new( lex_pairs( exhaustive_natural_signeds(), primitive_int_increasing_range(0, T::WIDTH), ) .interleave(exhaustive_pairs( exhaustive_negative_signeds(), exhaustive_unsigneds(), )), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_4() -> It<(T, u64)> { Box::new(lex_pairs( exhaustive_signeds(), primitive_int_increasing_range(0, T::WIDTH), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_5() -> It<(T, u64)> { Box::new( lex_pairs( exhaustive_negative_signeds(), primitive_int_increasing_range(0, T::WIDTH), ) .interleave(exhaustive_pairs( exhaustive_natural_signeds(), exhaustive_unsigneds(), )), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_6< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, >() -> It<(T, U)> { Box::new(lex_pairs( exhaustive_signeds(), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_7() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_natural_signeds(), exhaustive_unsigneds(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_8< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, >() -> It<(T, U)> { Box::new(lex_pairs( exhaustive_natural_signeds(), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_9() -> It<(T, U)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_signeds::(), exhaustive_unsigneds::()) .filter(|&(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } struct SignedDivisibleByP2PairsGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for SignedDivisibleByP2PairsGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It { let pow = *pow; if pow >= T::WIDTH { Box::new(once(T::ZERO)) } else if pow == 0 { Box::new(exhaustive_signeds()) } else { Box::new( exhaustive_signed_inclusive_range( -T::low_mask(T::WIDTH - pow), T::low_mask(T::WIDTH - pow), ) .map(move |k| k << pow), ) } } } pub fn exhaustive_signed_unsigned_pair_gen_var_10() -> It<(T, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), SignedDivisibleByP2PairsGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_signed_unsigned_pair_gen_var_11() -> It<(T, u64)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_natural_signeds(), exhaustive_unsigneds()).interleave( exhaustive_pairs_big_tiny( exhaustive_signeds(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ), ), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_12() -> It<(T, u64)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_signed_range(T::MIN + T::ONE, T::ONE), exhaustive_unsigneds(), ) .interleave(exhaustive_pairs_big_tiny( exhaustive_signeds(), primitive_int_increasing_range(0, T::WIDTH), )), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_13() -> It<(T, u64)> { Box::new(lex_pairs( exhaustive_signeds(), primitive_int_increasing_inclusive_range(0, U::WIDTH), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_14() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_signed_inclusive_range( if T::WIDTH <= u64::WIDTH { T::MIN } else { -T::exact_from(u64::MAX) }, T::saturating_from(u64::MAX), ), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_15() -> It<(T, u64)> { Box::new( exhaustive_pairs(exhaustive_signeds::(), exhaustive_unsigneds()) .filter(|&(x, y)| x.checked_pow(y).is_some()), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_16() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_signed_range(T::MIN + T::ONE, T::ZERO), exhaustive_unsigneds(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_17() -> It<(T, U)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_natural_signeds(), exhaustive_positive_primitive_ints(), ) .interleave(exhaustive_pairs_big_tiny( exhaustive_negative_signeds(), exhaustive_unsigneds::() .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | U::ONE)), )), ) } pub fn exhaustive_signed_unsigned_pair_gen_var_18() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_signeds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_signed_unsigned_pair_gen_var_19() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_signeds(), exhaustive_positive_primitive_ints(), )) } // -- (PrimitiveSigned, PrimitiveUnsigned, bool) -- pub fn exhaustive_signed_unsigned_bool_triple_gen_var_1() -> It<(T, u64, bool)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_signeds(), exhaustive_unsigneds()) .map(|(x, y)| (x, y, x < T::ZERO)) .interleave( lex_pairs( exhaustive_signeds(), primitive_int_increasing_range(0, T::WIDTH), ) .map(|(x, y)| (x, y, x >= T::ZERO)), ), ) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_signed_unsigned_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { Box::new(exhaustive_triples_custom_output( exhaustive_signeds(), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_signed_unsigned_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(T, U, U)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_positive_primitive_ints(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .interleave(exhaustive_triples_custom_output( exhaustive_signed_inclusive_range(T::MIN, T::ZERO), exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(U::ZERO, U::exact_from(T::WIDTH)), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) .filter_map(|(x, y, z)| y.checked_add(z).map(|new_z| (x, y, new_z))), ) } pub fn exhaustive_signed_unsigned_unsigned_triple_gen_var_3< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { permute_1_3_2(reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_signeds(), exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )))) } pub fn exhaustive_signed_unsigned_unsigned_triple_gen_var_4< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(T, T, U)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_signeds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1< T: PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >() -> It<(T, u64, u64, U)> { Box::new( exhaustive_quadruples_xyyz_custom_output( exhaustive_signeds(), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ) .filter_map(|(x, y, z, w): (T, u64, u64, U)| { y.checked_add(z).and_then(|new_z| { if signed_assign_bits_valid(x, y, new_z, w) { Some((x, y, new_z, w)) } else { None } }) }), ) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_1() -> It<(T, u64, RoundingMode)> { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_signeds::(), exhaustive_unsigneds::()), exhaustive_rounding_modes(), ) .filter_map(|((x, pow), rm)| round_to_multiple_of_power_of_2_filter_map(x, pow, rm)), ) } pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_signeds::(), exhaustive_unsigneds::()), exhaustive_rounding_modes(), ) .filter(|&((x, y), rm)| rm != Exact || x.divisible_by_power_of_2(y.exact_into())), )) } // var 3 through 5 are in malachite-float. pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_6< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs( exhaustive_signeds::(), exhaustive_positive_primitive_ints::(), ), exhaustive_rounding_modes(), ))) } // -- (PrimitiveSigned, RoundingMode) -- pub fn exhaustive_signed_rounding_mode_pair_gen() -> It<(T, RoundingMode)> { Box::new(lex_pairs(exhaustive_signeds(), exhaustive_rounding_modes())) } pub fn exhaustive_signed_rounding_mode_pair_gen_var_1() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_nonzero_signeds(), exhaustive_rounding_modes(), )) } pub fn exhaustive_signed_rounding_mode_pair_gen_var_2() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_signed_inclusive_range(T::MIN + T::ONE, T::MAX), exhaustive_rounding_modes(), )) } pub fn exhaustive_signed_rounding_mode_pair_gen_var_3() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_nonzero_signeds().filter(|&x| x != T::MIN), exhaustive_rounding_modes(), )) } pub fn exhaustive_signed_rounding_mode_pair_gen_var_4< T: PrimitiveSigned, U: ConvertibleFrom + PrimitiveFloat, >() -> It<(T, RoundingMode)> { Box::new( lex_pairs(exhaustive_signeds(), exhaustive_rounding_modes()) .filter(|&(i, rm)| rm != Exact || U::convertible_from(i)), ) } // -- (PrimitiveSigned, ToSciOptions) -- pub fn exhaustive_signed_to_sci_options_pair_gen() -> It<(T, ToSciOptions)> { Box::new(exhaustive_pairs( exhaustive_signeds(), exhaustive_to_sci_options(), )) } type TSO = ToSciOptions; pub fn exhaustive_signed_to_sci_options_pair_gen_var_1() -> It<(T, TSO)> { Box::new( exhaustive_pairs(exhaustive_signeds::(), exhaustive_to_sci_options()) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (PrimitiveSigned, Vec) -- struct SignedBoolVecPairGeneratorVar1; impl ExhaustiveDependentPairsYsGenerator, LexFixedLengthVecsFromSingle> for SignedBoolVecPairGeneratorVar1 { #[inline] fn get_ys(&self, &x: &T) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single( u64::exact_from(x.to_bits_asc().len()), exhaustive_bools(), ) } } pub fn exhaustive_signed_bool_vec_pair_gen_var_1() -> It<(T, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_signeds(), SignedBoolVecPairGeneratorVar1, )) } // -- PrimitiveUnsigned -- pub fn exhaustive_unsigned_gen() -> It { Box::new(exhaustive_unsigneds()) } pub fn exhaustive_unsigned_gen_var_1() -> It { Box::new(primitive_int_increasing_range(0, NUMBER_OF_CHARS)) } pub fn exhaustive_unsigned_gen_var_2() -> It { Box::new(primitive_int_increasing_inclusive_range(1, T::WIDTH)) } pub fn exhaustive_unsigned_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() -> It { Box::new(primitive_int_increasing_inclusive_range( U::TWO, U::saturating_from(T::MAX), )) } pub fn exhaustive_unsigned_gen_var_5() -> It { Box::new(primitive_int_increasing_inclusive_range(0, T::WIDTH)) } pub fn exhaustive_unsigned_gen_var_6() -> It { Box::new( lex_union3s( primitive_int_increasing_inclusive_range(b'0', b'9'), primitive_int_increasing_inclusive_range(b'a', b'z'), primitive_int_increasing_inclusive_range(b'A', b'Z'), ) .map(Union3::unwrap), ) } pub fn exhaustive_unsigned_gen_var_7() -> It { Box::new(primitive_int_increasing_inclusive_range( T::power_of_2(T::WIDTH - 1), T::MAX, )) } pub fn exhaustive_unsigned_gen_var_8() -> It { Box::new(primitive_int_increasing_inclusive_range( 0, T::LARGEST_ORDERED_REPRESENTATION, )) } pub fn exhaustive_unsigned_gen_var_9() -> It { Box::new(primitive_int_increasing_inclusive_range( T::ZERO, T::power_of_2(T::WIDTH - 1), )) } pub fn exhaustive_unsigned_gen_var_10() -> It { Box::new(primitive_int_increasing_range(0, T::WIDTH)) } pub fn exhaustive_unsigned_gen_var_11() -> It { Box::new(primitive_int_increasing_inclusive_range(0, T::WIDTH - 2)) } pub fn exhaustive_unsigned_gen_var_12< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >() -> It { Box::new(exhaustive_unsigneds().filter(|&x| U::convertible_from(x))) } pub fn exhaustive_unsigned_gen_var_13< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >() -> It { Box::new( primitive_int_increasing_inclusive_range( T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter(|&x| !U::convertible_from(x)), ) } pub fn exhaustive_unsigned_gen_var_14< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >() -> It { Box::new( iter_windows( 2, primitive_int_increasing_inclusive_range( T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter(|&x| U::convertible_from(x)), ) .filter_map(|xs| { let mut xs = xs.into_iter(); let a = xs.next().unwrap(); let diff = xs.next().unwrap() - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn exhaustive_unsigned_gen_var_15() -> It { Box::new(primitive_int_increasing_inclusive_range( T::ZERO, T::MAX.floor_sqrt(), )) } pub fn exhaustive_unsigned_gen_var_22() -> It { Box::new( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), ) } pub fn exhaustive_unsigned_gen_var_23() -> It { let limit = smallest_invalid_value(T::checked_factorial); Box::new(primitive_int_increasing_range(0, limit)) } pub fn exhaustive_unsigned_gen_var_24() -> It { let limit = smallest_invalid_value(T::checked_double_factorial); Box::new(primitive_int_increasing_range(0, limit)) } pub fn exhaustive_unsigned_gen_var_25() -> It { let limit = smallest_invalid_value(T::checked_subfactorial); Box::new(primitive_int_increasing_range(0, limit)) } pub fn exhaustive_unsigned_gen_var_26() -> It { let limit = smallest_invalid_value(T::checked_primorial); Box::new(primitive_int_increasing_range(0, limit)) } pub fn exhaustive_unsigned_gen_var_27() -> It { let limit = smallest_invalid_value(T::checked_product_of_first_n_primes); Box::new(primitive_int_increasing_range(0, limit)) } pub fn exhaustive_unsigned_gen_var_28() -> It { Box::new(T::primes()) } pub fn exhaustive_unsigned_gen_var_29() -> It { Box::new(primitive_int_increasing_inclusive_range( 0, u64::exact_from(T::MAX_EXPONENT), )) } // -- (PrimitiveUnsigned, PrimitiveInt) -- pub fn exhaustive_unsigned_primitive_int_gen_var_1() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_primitive_int_pair_gen_var_2< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveInt, >() -> It<(T, U)> { Box::new(lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )) } pub fn exhaustive_unsigned_primitive_int_gen_var_3() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } // -- (PrimitiveUnsigned, PrimitiveInt, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_primitive_int_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveInt, V: PrimitiveUnsigned, >() -> It<(T, u64, V)> { Box::new(exhaustive_triples( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(1, U::WIDTH), exhaustive_unsigneds(), )) } // -- (PrimitiveUnsigned, PrimitiveSigned) -- pub fn exhaustive_unsigned_signed_pair_gen() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_unsigneds(), exhaustive_signeds(), )) } pub fn exhaustive_unsigned_signed_pair_gen_var_1() -> It<(T, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_unsigneds(), exhaustive_signeds(), )) } struct IntegerMantissaAndExponentGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator<(u64, i64), (u64, i64), It<(u64, i64)>> for IntegerMantissaAndExponentGenerator { #[inline] fn get_ys(&self, p: &(u64, i64)) -> It<(u64, i64)> { let &(mantissa, exponent) = p; Box::new(exhaustive_natural_signeds().filter_map(move |i| { Some(( mantissa.arithmetic_checked_shl(i)?, exponent.checked_sub(i)?, )) })) } } pub fn exhaustive_unsigned_signed_pair_gen_var_2() -> It<(u64, i64)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_positive_finite_primitive_floats().map(T::integer_mantissa_and_exponent), IntegerMantissaAndExponentGenerator:: { phantom: PhantomData, }, ) .map(|p| p.1), ) } // -- (PrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned) -- struct ModPowerOf2PairWithExtraSignedGenerator { phantom: PhantomData<(T, U)>, } type LongType = ExhaustivePairs, U, ExhaustiveSigneds>; impl ExhaustiveDependentPairsYsGenerator< u64, (T, U), ExhaustivePairs, U, ExhaustiveSigneds>, > for ModPowerOf2PairWithExtraSignedGenerator { #[inline] fn get_ys(&self, &pow: &u64) -> LongType { exhaustive_pairs( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(pow)), exhaustive_signeds(), ) } } pub fn exhaustive_unsigned_signed_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveSigned, >() -> It<(T, U, u64)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2PairWithExtraSignedGenerator:: { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_signed_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveSigned, >() -> It<(T, U, T)> { Box::new( exhaustive_triples_xyx( exhaustive_unsigneds(), exhaustive_signed_inclusive_range( if U::WIDTH <= u64::WIDTH { U::MIN } else { -U::exact_from(u64::MAX) }, U::saturating_from(u64::MAX), ), ) .filter_map(|(x, y, z): (T, U, T)| Some((x, y, x.checked_add(z)?.checked_add(T::ONE)?))), ) } pub fn exhaustive_unsigned_signed_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveSigned, >() -> It<(T, U, T)> { Box::new( exhaustive_triples_xyx(exhaustive_unsigneds(), exhaustive_signeds()).filter_map( |(x, y, z): (T, U, T)| Some((x, y, x.checked_add(z)?.checked_add(T::ONE)?)), ), ) } pub fn exhaustive_unsigned_signed_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { reshape_1_2_to_3(Box::new(exhaustive_pairs_big_small( exhaustive_unsigneds(), exhaustive_pairs(exhaustive_signeds(), exhaustive_positive_primitive_ints()), ))) } // -- (PrimitiveUnsigned, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_unsigned_signed_rounding_mode_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveSigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_unsigneds::(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .filter(|&((x, pow), rm)| { rm != Exact || pow <= U::ZERO || x.divisible_by_power_of_2(pow.exact_into()) }), )) } pub fn exhaustive_unsigned_signed_rounding_mode_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveSigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_unsigneds::(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .filter(|&((x, pow), rm)| { let pow: i64 = pow.exact_into(); rm != Exact || pow >= 0 || x.divisible_by_power_of_2(pow.unsigned_abs()) }), )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_pair_gen() -> It<(T, U)> { Box::new(exhaustive_pairs( exhaustive_unsigneds(), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_pair_gen_var_1() -> It<(u32, u32)> { Box::new(exhaustive_pairs_from_single( primitive_int_increasing_range(0, NUMBER_OF_CHARS), )) } type T1 = It<(T, U)>; pub fn exhaustive_unsigned_pair_gen_var_2() -> T1 { Box::new(exhaustive_pairs_big_tiny( exhaustive_unsigneds(), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_pair_gen_var_3() -> It<(T, u64)> { Box::new(lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_range(0, T::WIDTH), )) } pub fn exhaustive_unsigned_pair_gen_var_4() -> It<(T, u64)> { Box::new(lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(1, U::WIDTH), )) } pub fn exhaustive_unsigned_pair_gen_var_5< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() -> It<(T, U)> { Box::new(exhaustive_pairs_big_small( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(U::TWO, U::saturating_from(T::MAX)), )) } // TODO make better pub fn exhaustive_unsigned_pair_gen_var_6() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x <= y)) } pub fn exhaustive_unsigned_pair_gen_var_7< T: PrimitiveInt + SaturatingFrom, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> It<(T, V)> { Box::new(exhaustive_pairs_big_tiny( primitive_int_increasing_inclusive_range(T::TWO, T::saturating_from(U::MAX)), exhaustive_unsigneds(), )) } struct UnsignedDivisiblePairsGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for UnsignedDivisiblePairsGenerator { #[inline] fn get_ys(&self, y: &T) -> It { let y = *y; Box::new( exhaustive_unsigneds() .map(move |k| y.checked_mul(k)) .take_while(Option::is_some) .map(Option::unwrap), ) } } pub fn exhaustive_unsigned_pair_gen_var_8() -> It<(T, T)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_positive_primitive_ints(), UnsignedDivisiblePairsGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_pair_gen_var_9() -> T1 { Box::new(exhaustive_pairs( exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_pair_gen_var_10() -> It<(T, T)> { Box::new( exhaustive_pairs( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints::(), ) .filter(|&(x, y)| !x.divisible_by(y)), ) } pub fn exhaustive_unsigned_pair_gen_var_11() -> T1 { Box::new( exhaustive_pairs_big_tiny(exhaustive_unsigneds::(), exhaustive_unsigneds::()) .filter(|&(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } struct UnsignedDivisibleByP2PairsGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for UnsignedDivisibleByP2PairsGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It { let pow = *pow; if pow >= T::WIDTH { Box::new(once(T::ZERO)) } else { Box::new( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - pow)) .map(move |k| k << pow), ) } } } pub fn exhaustive_unsigned_pair_gen_var_12() -> It<(T, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), UnsignedDivisibleByP2PairsGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_pair_gen_var_13() -> It<(T, T)> { Box::new(exhaustive_ordered_unique_pairs(exhaustive_unsigneds())) } struct ModPowerOf2SingleGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for ModPowerOf2SingleGenerator { #[inline] fn get_ys(&self, &pow: &u64) -> PrimitiveIntIncreasingRange { primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(pow)) } } struct ModPowerOf2SingleGenerator2 { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for ModPowerOf2SingleGenerator2 { #[inline] fn get_ys(&self, &pow: &u64) -> PrimitiveIntIncreasingRange { primitive_int_increasing_inclusive_range(T::ONE, T::low_mask(pow)) } } pub fn exhaustive_unsigned_pair_gen_var_14() -> It<(T, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2SingleGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_pair_gen_var_15() -> It<(T, u64)> { Box::new( exhaustive_unsigneds() .map(|x| (T::ZERO, x)) .interleave(exhaustive_pairs_big_tiny( exhaustive_positive_primitive_ints(), primitive_int_increasing_range(0, T::WIDTH), )), ) } pub fn exhaustive_unsigned_pair_gen_var_16() -> It<(u64, u64)> { Box::new(exhaustive_pairs_from_single( primitive_int_increasing_inclusive_range(0, T::LARGEST_ORDERED_REPRESENTATION), )) } pub fn exhaustive_unsigned_pair_gen_var_17() -> It<(T, u64)> { Box::new(lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(0, U::WIDTH), )) } pub fn exhaustive_unsigned_pair_gen_var_18() -> It<(T, U)> { Box::new(exhaustive_pairs( primitive_int_increasing_inclusive_range(T::ZERO, T::saturating_from(u64::MAX)), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_pair_gen_var_19() -> It<(u64, u64)> { Box::new(exhaustive_pairs( primitive_int_increasing_range(0, u64::power_of_2(T::MANTISSA_WIDTH)), primitive_int_increasing_range(0, u64::power_of_2(T::EXPONENT_WIDTH)), )) } pub fn exhaustive_unsigned_pair_gen_var_20() -> It<(T, T)> { Box::new(exhaustive_pairs_from_single(exhaustive_unsigneds())) } pub fn exhaustive_unsigned_pair_gen_var_21() -> It<(T, u64)> { Box::new( exhaustive_pairs(exhaustive_unsigneds::(), exhaustive_unsigneds()) .filter(|&(x, y)| x.checked_pow(y).is_some()), ) } pub fn exhaustive_unsigned_pair_gen_var_22() -> It<(T, u64)> { Box::new(exhaustive_unsigned_pair_gen_var_14().map(|(x, p)| (x, T::WIDTH - p))) } pub fn exhaustive_unsigned_pair_gen_var_23() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single(exhaustive_unsigneds::()) .filter(|&(x, y)| x.checked_lcm(y).is_some()), ) } pub fn exhaustive_unsigned_pair_gen_var_24() -> It<(T, T)> { Box::new(exhaustive_pairs( primitive_int_increasing_inclusive_range(T::power_of_2(T::WIDTH - 1), T::MAX), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_pair_gen_var_25() -> It<(T, T)> { Box::new( exhaustive_pairs(exhaustive_positive_primitive_ints(), exhaustive_unsigneds()) .filter(|&(x, y)| x != T::ONE || y != T::ZERO), ) } pub fn exhaustive_unsigned_pair_gen_var_26() -> It<(T, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(1, T::WIDTH), ModPowerOf2SingleGenerator2 { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_pair_gen_var_27() -> It<(T, T)> { Box::new(exhaustive_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_unsigned_pair_gen_var_28() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), ) .filter(|&(a, b): &(T, T)| a.coprime_with(b)), ) } pub fn exhaustive_unsigned_pair_gen_var_29() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single(exhaustive_unsigneds()) .filter(|&(x, y): &(T, T)| x.coprime_with(y)), ) } struct MultifactorialNGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for MultifactorialNGenerator { #[inline] fn get_ys(&self, &m: &u64) -> PrimitiveIntIncreasingRange { let limit = smallest_invalid_value(|n| T::checked_multifactorial(n, m)); primitive_int_increasing_range(0, limit) } } pub fn exhaustive_unsigned_pair_gen_var_30() -> It<(u64, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_positive_primitive_ints(), MultifactorialNGenerator { phantom: PhantomData::<*const T>, }, ))) } pub fn exhaustive_unsigned_pair_gen_var_31() -> It<(T, T)> { Box::new( exhaustive_pairs_from_single(exhaustive_unsigneds()) .filter(|&(n, k)| T::checked_binomial_coefficient(n, k).is_some()), ) } // vars 32 through 36 are in malachite-nz. // -- (PrimitiveUnsigned, PrimitiveUnsigned, bool) -- pub fn exhaustive_unsigned_unsigned_bool_triple_gen_var_1() -> It<(T, u64, bool)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_unsigneds(), exhaustive_unsigneds()) .map(|(x, y)| (x, y, false)) .interleave( lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_range(0, T::WIDTH), ) .map(|(x, y)| (x, y, true)), ), ) } pub fn exhaustive_unsigned_unsigned_bool_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(T, U, bool)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_unsigneds(), exhaustive_positive_primitive_ints()), exhaustive_bools(), ))) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_triple_gen_var_1() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_unsigneds()) .filter(|&(x, y, z)| add_mul_inputs_valid(x, y, z)), ) } pub fn exhaustive_unsigned_triple_gen_var_2() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_unsigneds()) .filter(|&(x, y, z)| sub_mul_inputs_valid(x, y, z)), ) } pub fn exhaustive_unsigned_triple_gen_var_3() -> It<(T, T, U)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_unsigned_triple_gen_var_4() -> It<(T, U, U)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(x, y, z): (T, U, U)| y.checked_add(z).map(|new_z| (x, y, new_z))), ) } pub fn exhaustive_unsigned_triple_gen_var_5< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> It<(T, U, V)> { permute_1_3_2(reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_unsigneds(), exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(U::TWO, U::exact_from(36u8)), )))) } struct UnsignedModEqTriplesInnerGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator<(T, T), (T, T), It<(T, T)>> for UnsignedModEqTriplesInnerGenerator { #[inline] fn get_ys(&self, p: &(T, T)) -> It<(T, T)> { let &(m, k) = p; if k == T::ZERO { Box::new(exhaustive_unsigneds().map(|x| (x, x))) } else { let d = m.checked_mul(k).unwrap(); Box::new( primitive_int_increasing_inclusive_range(T::ZERO, T::MAX - d) .map(move |n| (n, n + d)) .interleave( primitive_int_increasing_inclusive_range(T::ZERO, T::MAX - d) .map(move |n| (n + d, n)), ), ) } } } struct UnsignedModEqTriplesGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for UnsignedModEqTriplesGenerator { #[inline] fn get_ys(&self, m: &T) -> It<(T, T)> { let m = *m; if m == T::ZERO { Box::new(exhaustive_unsigneds().map(|x| (x, x))) } else { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(T::ZERO, T::MAX / m) .map(move |k| (m, k)), UnsignedModEqTriplesInnerGenerator { phantom: PhantomData, }, ) .map(|p| p.1), ) } } } pub fn exhaustive_unsigned_triple_gen_var_6() -> It<(T, T, T)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_unsigneds(), UnsignedModEqTriplesGenerator { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_triple_gen_var_7() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_unsigneds::()) .filter(|&(x, y, m)| !x.eq_mod(y, m)), ) } struct UnsignedModPow2EqTriplesInnerGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator<(u64, T), (T, T), It<(T, T)>> for UnsignedModPow2EqTriplesInnerGenerator { #[inline] fn get_ys(&self, p: &(u64, T)) -> It<(T, T)> { let &(pow, k) = p; if k == T::ZERO { Box::new(exhaustive_unsigneds().map(|x| (x, x))) } else { let d = k << pow; Box::new( primitive_int_increasing_inclusive_range(T::ZERO, T::MAX - d) .map(move |n| (n, n + d)) .interleave( primitive_int_increasing_inclusive_range(T::ZERO, T::MAX - d) .map(move |n| (n + d, n)), ), ) } } } struct UnsignedModPow2EqTriplesGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator> for UnsignedModPow2EqTriplesGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It<(T, T)> { let pow = *pow; if pow >= T::WIDTH { Box::new(exhaustive_unsigneds().map(|x| (x, x))) } else { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(T::ZERO, T::MAX >> pow) .map(move |k| (pow, k)), UnsignedModPow2EqTriplesInnerGenerator { phantom: PhantomData, }, ) .map(|p| p.1), ) } } } pub fn exhaustive_unsigned_triple_gen_var_8() -> It<(T, T, u64)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), UnsignedModPow2EqTriplesGenerator { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_triple_gen_var_9() -> It<(T, T, u64)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_unsigneds::(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter(|&(x, y, pow)| !x.eq_mod_power_of_2(y, pow)), ) } struct ModPowerOf2PairGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator< u64, (T, T), ExhaustivePairs1Input>, > for ModPowerOf2PairGenerator { #[inline] fn get_ys(&self, &pow: &u64) -> ExhaustivePairs1Input> { exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range( T::ZERO, T::low_mask(pow), )) } } pub fn exhaustive_unsigned_triple_gen_var_10() -> It<(T, T, u64)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2PairGenerator { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_triple_gen_var_11() -> It<(T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_unsigneds::()) .filter_map(|(x, y, z)| Some((x, y, max(x, y).checked_add(z)?.checked_add(T::ONE)?))), ) } pub fn exhaustive_unsigned_triple_gen_var_12() -> It<(T, U, U)> { Box::new(exhaustive_triples_xyy_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_unsigned_triple_gen_var_13() -> It<(T, U, T)> { Box::new( exhaustive_triples_xyx_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ) .filter_map(|(x, y, z): (T, U, T)| Some((x, y, x.checked_add(z)?.checked_add(T::ONE)?))), ) } pub fn exhaustive_unsigned_triple_gen_var_14() -> It<(T, U, T)> { Box::new( exhaustive_triples_xyx(exhaustive_unsigneds(), exhaustive_unsigneds()).filter_map( |(x, y, z): (T, U, T)| Some((x, y, x.checked_add(z)?.checked_add(T::ONE)?)), ), ) } struct ModPowerOf2PairWithExtraUnsignedGenerator { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator< u64, (T, U), ExhaustivePairs, U, PrimitiveIntIncreasingRange>, > for ModPowerOf2PairWithExtraUnsignedGenerator { #[inline] fn get_ys( &self, &pow: &u64, ) -> ExhaustivePairs, U, PrimitiveIntIncreasingRange> { exhaustive_pairs( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(pow)), exhaustive_unsigneds(), ) } } pub fn exhaustive_unsigned_triple_gen_var_15() -> It<(T, U, u64)> { reshape_2_1_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2PairWithExtraUnsignedGenerator:: { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_triple_gen_var_16() -> It<(T, U, T)> { Box::new( exhaustive_triples_xyx( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(U::ZERO, U::saturating_from(u64::MAX)), ) .filter_map(|(x, y, z): (T, U, T)| Some((x, y, x.checked_add(z)?.checked_add(T::ONE)?))), ) } pub fn exhaustive_unsigned_triple_gen_var_17() -> It<(T, T, T)> { Box::new(exhaustive_triples_from_single(exhaustive_unsigneds())) } pub fn exhaustive_unsigned_triple_gen_var_18() -> It<(T, T, T)> { Box::new(exhaustive_triples_xyx( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_unsigned_triple_gen_var_19() -> It<(T, T, T)> { Box::new(exhaustive_triples_xxy( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_unsigned_triple_gen_var_20() -> It<(T, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), )) } pub fn exhaustive_unsigned_triple_gen_var_21() -> It<(T, T, U)> { Box::new(exhaustive_triples_xxy( exhaustive_unsigneds(), exhaustive_unsigneds(), )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_quadruple_gen_var_1() -> It<(T, u64, u64, U)> { Box::new( exhaustive_quadruples_xyyz_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ) .filter_map(|(x, y, z, w): (T, u64, u64, U)| { y.checked_add(z).and_then(|new_z| { if unsigned_assign_bits_valid(y, new_z, w) { Some((x, y, new_z, w)) } else { None } }) }), ) } pub fn exhaustive_unsigned_quadruple_gen_var_2() -> It<(T, T, T, U)> { Box::new(exhaustive_quadruples_xxxy_custom_output( exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } struct ModPowerOf2TripleGenerator { phantom: PhantomData<*const T>, } impl ExhaustiveDependentPairsYsGenerator< u64, (T, T, T), ExhaustiveTriples1Input>, > for ModPowerOf2TripleGenerator { #[inline] fn get_ys(&self, &pow: &u64) -> ExhaustiveTriples1Input> { exhaustive_triples_from_single(primitive_int_increasing_inclusive_range( T::ZERO, T::low_mask(pow), )) } } pub fn exhaustive_unsigned_quadruple_gen_var_3() -> It<(T, T, T, u64)> { reshape_3_1_to_4(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2TripleGenerator { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_quadruple_gen_var_4() -> It<(T, T, T, T)> { Box::new( exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z, w)| Some((x, y, z, max!(x, y, z).checked_add(w)?.checked_add(T::ONE)?)), ), ) } pub fn exhaustive_unsigned_quadruple_gen_var_5< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >() -> It<(T, T, T, T)> { Box::new( exhaustive_triples_xxy(exhaustive_unsigneds(), exhaustive_positive_primitive_ints()).map( |(x_1, x_0, d)| { let inv = limbs_invert_limb_naive::(d << LeadingZeros::leading_zeros(d)); (x_1, x_0, d, inv) }, ), ) } pub fn exhaustive_unsigned_quadruple_gen_var_6() -> It<(T, T, U, T)> { Box::new( exhaustive_quadruples_xxyx(exhaustive_unsigneds::(), exhaustive_unsigneds::()) .filter_map(|(x, y, z, w)| { Some((x, y, z, max(x, y).checked_add(w)?.checked_add(T::ONE)?)) }), ) } pub fn exhaustive_unsigned_quadruple_gen_var_7() -> It<(T, U, U, T)> { Box::new( exhaustive_quadruples_xyyx(exhaustive_unsigneds::(), exhaustive_unsigneds::()) .filter_map(|(x, y, z, w)| Some((x, y, z, x.checked_add(w)?.checked_add(T::ONE)?))), ) } struct ModPowerOf2TripleWithExtraUnsignedGenerator { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator< u64, (T, T, U), ExhaustiveTriplesXXY, U, PrimitiveIntIncreasingRange>, > for ModPowerOf2TripleWithExtraUnsignedGenerator { #[inline] fn get_ys( &self, &pow: &u64, ) -> ExhaustiveTriplesXXY, U, PrimitiveIntIncreasingRange> { exhaustive_triples_xxy( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(pow)), exhaustive_unsigneds(), ) } } pub fn exhaustive_unsigned_quadruple_gen_var_8() -> It<(T, T, U, u64)> { reshape_3_1_to_4(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2TripleWithExtraUnsignedGenerator:: { phantom: PhantomData, }, )))) } struct ModPowerOf2QuadrupleWithTwoExtraUnsignedsGenerator< T: PrimitiveUnsigned, U: PrimitiveUnsigned, > { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator< u64, (T, U, U), ExhaustiveTriplesXYY, U, PrimitiveIntIncreasingRange>, > for ModPowerOf2QuadrupleWithTwoExtraUnsignedsGenerator { #[inline] fn get_ys( &self, &pow: &u64, ) -> ExhaustiveTriplesXYY, U, PrimitiveIntIncreasingRange> { exhaustive_triples_xyy( primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(pow)), exhaustive_unsigneds(), ) } } pub fn exhaustive_unsigned_quadruple_gen_var_9() -> It<(T, U, U, u64)> { reshape_3_1_to_4(permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(0, T::WIDTH), ModPowerOf2QuadrupleWithTwoExtraUnsignedsGenerator:: { phantom: PhantomData, }, )))) } pub fn exhaustive_unsigned_quadruple_gen_var_10() -> It<(T, T, T, T)> { Box::new(exhaustive_quadruples_from_single(exhaustive_unsigneds())) } pub fn exhaustive_unsigned_quadruple_gen_var_11() -> It<(T, T, T, T)> { Box::new( exhaustive_quadruples_from_single(exhaustive_unsigneds()).filter(|&(n1, n0, d1, d0)| { // conditions: D >= 2^W, N >= D, and N / D < 2^W d1 != T::ZERO && (n1 > d1 || n1 == d1 && n0 >= d0) }), ) } pub fn exhaustive_unsigned_quadruple_gen_var_12() -> It<(T, T, T, T)> { Box::new(exhaustive_quadruples_xxxy( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), )) } // -- (PrimitiveUnsigned * 6) -- pub fn exhaustive_unsigned_sextuple_gen_var_1() -> It<(T, T, T, T, T, T)> { Box::new(exhaustive_sextuples_from_single(exhaustive_unsigneds())) } // var 2 is in malachite-nz. // -- (PrimitiveUnsigned * 8) -- #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_octuple_gen_var_1() -> It<(T, T, T, T, T, T, T, T)> { Box::new(exhaustive_octuples_from_single(exhaustive_unsigneds())) } // -- (PrimitiveUnsigned * 9) -- #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_nonuple_gen_var_1() -> It<(T, T, T, T, T, T, T, T, T)> { Box::new( exhaustive_triples_from_single(exhaustive_triples_from_single(exhaustive_unsigneds())) .map(|((a, b, c), (d, e, f), (g, h, i))| (a, b, c, d, e, f, g, h, i)), ) } // -- (PrimitiveUnsigned * 12) -- #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_duodecuple_gen_var_1() -> It<(T, T, T, T, T, T, T, T, T, T, T, T)> { Box::new(exhaustive_duodecuples_from_single(exhaustive_unsigneds())) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_1() -> It<(T, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints::(), ), exhaustive_rounding_modes(), ) .filter(|&((x, y), rm)| rm != Exact || x.divisible_by(y)), )) } pub(crate) fn round_to_multiple_unsigned_filter_map( x: T, y: T, rm: RoundingMode, ) -> Option<(T, T, RoundingMode)> { if x == y { Some((x, y, rm)) } else if y == T::ZERO { if rm == Floor || rm == Down || rm == Nearest { Some((x, y, rm)) } else { None } } else if rm != Exact { x.div_round(y, rm).0.checked_mul(y).map(|_| (x, y, rm)) } else { x.checked_mul(y).map(|product| (product, y, rm)) } } pub(crate) fn round_to_multiple_of_power_of_2_filter_map( n: T, u: u64, rm: RoundingMode, ) -> Option<(T, u64, RoundingMode)> { if n == T::ZERO || rm != Exact { n.shr_round(u, rm) .0 .arithmetic_checked_shl(u) .map(|_| (n, u, rm)) } else { n.arithmetic_checked_shl(u).map(|shifted| (shifted, u, rm)) } } pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_3() -> It<(T, T, RoundingMode)> { Box::new( lex_pairs( exhaustive_pairs( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints::(), ), exhaustive_rounding_modes(), ) .filter_map(|((x, y), rm)| round_to_multiple_unsigned_filter_map(x, y, rm)), ) } pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_4() -> It<(T, u64, RoundingMode)> { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_unsigneds::(), exhaustive_unsigneds::()), exhaustive_rounding_modes(), ) .filter_map(|((x, pow), rm)| round_to_multiple_of_power_of_2_filter_map(x, pow, rm)), ) } pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_5< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_unsigneds::(), exhaustive_unsigneds::()), exhaustive_rounding_modes(), ) .filter(|&((x, y), rm)| rm != Exact || x.divisible_by_power_of_2(y.exact_into())), )) } // vars 6 through 7 are in malachite-float. pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_8< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(T, U, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints::(), ), exhaustive_rounding_modes(), ))) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, Vec) -- struct UnsignedUnsignedBoolVecTripleGeneratorVar1; impl ExhaustiveDependentPairsYsGenerator< (T, u64), Vec, LexFixedLengthVecsFromSingle, > for UnsignedUnsignedBoolVecTripleGeneratorVar1 { #[inline] fn get_ys(&self, &(x, log_base): &(T, u64)) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single( x.significant_bits().div_round(log_base, Ceiling).0, exhaustive_bools(), ) } } pub fn exhaustive_unsigned_unsigned_bool_vec_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(T, u64, Vec)> { reshape_2_1_to_3(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), lex_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(1, U::WIDTH), ), UnsignedUnsignedBoolVecTripleGeneratorVar1, ))) } // -- (PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_unsigned_rounding_mode_pair_gen() -> It<(T, RoundingMode)> { Box::new(lex_pairs( exhaustive_unsigneds(), exhaustive_rounding_modes(), )) } pub fn exhaustive_unsigned_rounding_mode_pair_gen_var_1< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >() -> It<(T, RoundingMode)> { Box::new( lex_pairs(exhaustive_unsigneds(), exhaustive_rounding_modes()) .filter(move |&(u, rm)| rm != Exact || U::convertible_from(u)), ) } // -- (PrimitiveUnsigned, String) -- pub fn valid_digit_chars(base: u8) -> Vec { let mut chars = Vec::new(); if base <= 10 { chars.extend('0'..char::from(base + b'0')); } else { chars.extend('0'..='9'); chars.extend('a'..char::from(base - 10 + b'a')); chars.extend('A'..char::from(base - 10 + b'A')); } chars } struct DigitStringGenerator; impl ExhaustiveDependentPairsYsGenerator< u8, String, StringsFromCharVecs, IntoIter>>, > for DigitStringGenerator { #[inline] fn get_ys( &self, &base: &u8, ) -> StringsFromCharVecs, IntoIter>> { assert!((2..=36).contains(&base)); strings_from_char_vecs(exhaustive_vecs_min_length( 1, valid_digit_chars(base).into_iter(), )) } } pub fn exhaustive_unsigned_string_pair_gen_var_1() -> It<(u8, String)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(2, 36), DigitStringGenerator, )) } pub fn exhaustive_unsigned_string_pair_gen_var_2() -> It<(u8, String)> { Box::new(exhaustive_pairs( primitive_int_increasing_inclusive_range(2, 36), exhaustive_strings(), )) } struct TargetedIntegerFromStringBaseInputs { neg: bool, u: u8, s: String, uss: It<(u8, String)>, } impl Iterator for TargetedIntegerFromStringBaseInputs { type Item = (u8, String); fn next(&mut self) -> Option<(u8, String)> { Some(if self.neg { self.neg = false; let next = self.uss.next().unwrap(); self.u = next.0; self.s = next.1; (self.u, self.s.clone()) } else { self.neg = true; let mut s = '-'.to_string(); s.push_str(&self.s); (self.u, s) }) } } pub fn exhaustive_unsigned_string_pair_gen_var_3() -> It<(u8, String)> { Box::new(TargetedIntegerFromStringBaseInputs { neg: true, u: 0, s: String::new(), uss: exhaustive_unsigned_string_pair_gen_var_1(), }) } // -- (PrimitiveUnsigned, ToSciOptions) -- pub fn exhaustive_unsigned_to_sci_options_pair_gen() -> It<(T, ToSciOptions)> { Box::new(exhaustive_pairs( exhaustive_unsigneds(), exhaustive_to_sci_options(), )) } pub fn exhaustive_unsigned_to_sci_options_pair_gen_var_1() -> It<(T, ToSciOptions)> { Box::new( exhaustive_pairs(exhaustive_unsigneds::(), exhaustive_to_sci_options()) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (PrimitiveUnsigned, Vec) -- struct UnsignedBoolVecPairGeneratorVar1; impl ExhaustiveDependentPairsYsGenerator, LexFixedLengthVecsFromSingle> for UnsignedBoolVecPairGeneratorVar1 { #[inline] fn get_ys(&self, &x: &T) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single(x.significant_bits(), exhaustive_bools()) } } pub fn exhaustive_unsigned_bool_vec_pair_gen_var_1() -> It<(T, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_unsigneds(), UnsignedBoolVecPairGeneratorVar1, )) } // -- RationalSequence -- pub fn exhaustive_unsigned_rational_sequence_gen() -> It> { Box::new(exhaustive_rational_sequences(exhaustive_unsigneds())) } // -- (RationalSequence, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_rational_sequence_unsigned_pair_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(RationalSequence, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_rational_sequences(exhaustive_unsigneds()), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_rational_sequence_unsigned_pair_gen_var_2() -> It<(RationalSequence, usize)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_rational_sequences(exhaustive_unsigneds()), exhaustive_unsigneds(), ) .filter(|&(ref xs, i)| { if let Some(len) = xs.len() { i < len } else { true } }), ) } // -- (RationalSequence, RationalSequence) -- pub fn exhaustive_unsigned_rational_sequence_pair_gen() -> It<(RationalSequence, RationalSequence)> { Box::new(exhaustive_pairs_from_single(exhaustive_rational_sequences( exhaustive_unsigneds(), ))) } // -- RationalSequence * 3 -- pub fn exhaustive_unsigned_rational_sequence_triple_gen() -> It<( RationalSequence, RationalSequence, RationalSequence, )> { Box::new(exhaustive_triples_from_single( exhaustive_rational_sequences(exhaustive_unsigneds()), )) } // -- RoundingMode -- pub fn exhaustive_rounding_mode_gen() -> It { Box::new(exhaustive_rounding_modes()) } // -- (RoundingMode, RoundingMode) -- pub fn exhaustive_rounding_mode_pair_gen() -> It<(RoundingMode, RoundingMode)> { Box::new(lex_pairs_from_single(exhaustive_rounding_modes())) } // -- (RoundingMode, RoundingMode, RoundingMode) -- pub fn exhaustive_rounding_mode_triple_gen() -> It<(RoundingMode, RoundingMode, RoundingMode)> { Box::new(lex_triples_from_single(exhaustive_rounding_modes())) } // -- SciSizeOptions -- pub fn exhaustive_sci_size_options_gen() -> It { Box::new(exhaustive_sci_size_options()) } // -- String -- pub fn exhaustive_string_gen() -> It { Box::new(exhaustive_strings()) } pub fn exhaustive_string_gen_var_1() -> It { Box::new(exhaustive_strings_using_chars(exhaustive_ascii_chars())) } pub fn exhaustive_string_gen_var_2() -> It { Box::new(exhaustive_strings_using_chars(ROUNDING_MODE_CHARS.chars())) } pub fn exhaustive_string_gen_var_3() -> It { Box::new(strings_from_char_vecs(exhaustive_vecs_min_length( 1, '0'..='9', ))) } struct TargetedIntegerFromStrStringsVar1 { neg: bool, s: String, ss: It, } impl Iterator for TargetedIntegerFromStrStringsVar1 { type Item = String; fn next(&mut self) -> Option { Some(if self.neg { self.neg = false; self.s = self.ss.next().unwrap(); self.s.clone() } else { self.neg = true; format!("-{}", self.s) }) } } pub fn exhaustive_string_gen_var_4() -> It { Box::new(TargetedIntegerFromStrStringsVar1 { neg: true, s: String::new(), ss: exhaustive_string_gen_var_3(), }) } pub fn exhaustive_string_gen_var_5() -> It { Box::new(strings_from_char_vecs(exhaustive_vecs_min_length( 1, '0'..='1', ))) } pub fn exhaustive_string_gen_var_6() -> It { Box::new(strings_from_char_vecs(exhaustive_vecs_min_length( 1, '0'..='7', ))) } pub fn exhaustive_string_gen_var_7() -> It { Box::new(strings_from_char_vecs(exhaustive_vecs_min_length( 1, lex_union3s('0'..='9', 'a'..='f', 'A'..='F').map(Union3::unwrap), ))) } pub fn exhaustive_string_gen_var_8() -> It { Box::new( strings_from_char_vecs(exhaustive_vecs_min_length( 1, lex_union3s('0'..='9', 'a'..='f', 'A'..='F').map(Union3::unwrap), )) .map(|s| format!("\"0x{s}\"")), ) } struct TargetedIntegerFromStrStringsVar2 { neg: bool, s: String, ss: It, } impl Iterator for TargetedIntegerFromStrStringsVar2 { type Item = String; fn next(&mut self) -> Option { Some(if self.neg { self.neg = false; self.s = self.ss.next().unwrap(); format!("\"0x{}\"", self.s) } else { self.neg = true; format!("\"-0x{}\"", self.s) }) } } pub fn exhaustive_string_gen_var_9() -> It { Box::new(TargetedIntegerFromStrStringsVar2 { neg: true, s: String::new(), ss: exhaustive_string_gen_var_7(), }) } pub fn exhaustive_string_gen_var_10() -> It { Box::new(exhaustive_strings_using_chars( PRIMITIVE_FLOAT_CHARS.chars(), )) } // vars 11 through 12 are in malachite-q. pub fn exhaustive_string_gen_var_13() -> It { Box::new(exhaustive_strings_using_chars( DECIMAL_SCI_STRING_CHARS.chars(), )) } pub fn exhaustive_string_gen_var_14() -> It { Box::new(exhaustive_strings().filter(|s| !large_exponent(s))) } pub fn exhaustive_string_gen_var_15() -> It { Box::new( exhaustive_strings_using_chars(DECIMAL_SCI_STRING_CHARS.chars()) .filter(|s| !large_exponent(s)), ) } // -- (String, FromSciStringOptions) -- pub fn exhaustive_string_from_sci_string_options_pair_gen() -> It<(String, FromSciStringOptions)> { Box::new(exhaustive_pairs( exhaustive_strings(), exhaustive_from_sci_string_options(), )) } struct SciDigitStringGenerator; impl ExhaustiveDependentPairsYsGenerator< FromSciStringOptions, String, StringsFromCharVecs, IntoIter>>, > for SciDigitStringGenerator { #[inline] fn get_ys( &self, &options: &FromSciStringOptions, ) -> StringsFromCharVecs, IntoIter>> { let base = options.get_base(); let mut cs = vec!['+', '-', '.']; if base < 15 { cs.push('e'); cs.push('E'); } cs.extend(valid_digit_chars(base)); assert!((2..=36).contains(&base)); strings_from_char_vecs(exhaustive_vecs_min_length(1, cs.into_iter())) } } struct SciDigitStringGenerator2; impl ExhaustiveDependentPairsYsGenerator< u8, String, StringsFromCharVecs, IntoIter>>, > for SciDigitStringGenerator2 { #[inline] fn get_ys( &self, &base: &u8, ) -> StringsFromCharVecs, IntoIter>> { let mut cs = vec!['+', '-', '.']; if base < 15 { cs.push('e'); cs.push('E'); } cs.extend(valid_digit_chars(base)); assert!((2..=36).contains(&base)); strings_from_char_vecs(exhaustive_vecs_min_length(1, cs.into_iter())) } } pub fn exhaustive_string_from_sci_string_options_pair_gen_var_1() -> It<(String, FromSciStringOptions)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_from_sci_string_options(), SciDigitStringGenerator, ))) } pub fn exhaustive_string_from_sci_string_options_pair_gen_var_2() -> It<(String, FromSciStringOptions)> { Box::new(exhaustive_pairs( exhaustive_strings().filter(|s| !large_exponent(s)), exhaustive_from_sci_string_options(), )) } pub fn exhaustive_string_from_sci_string_options_pair_gen_var_3() -> It<(String, FromSciStringOptions)> { permute_2_1(Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_from_sci_string_options(), SciDigitStringGenerator, ) .filter(|(_, s)| !large_exponent(s)), )) } // -- (String, PrimitiveUnsigned) -- pub fn exhaustive_string_unsigned_pair_gen_var_1() -> It<(String, u8)> { Box::new(exhaustive_pairs( exhaustive_strings().filter(|s| !large_exponent(s)), primitive_int_increasing_inclusive_range(2, 36), )) } pub fn exhaustive_string_unsigned_pair_gen_var_2() -> It<(String, u8)> { permute_2_1(Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(2, 36), SciDigitStringGenerator2, ) .filter(|(_, s)| !large_exponent(s)), )) } // -- (String, String) -- pub fn exhaustive_string_pair_gen() -> It<(String, String)> { Box::new(exhaustive_pairs_from_single(exhaustive_strings())) } pub fn exhaustive_string_pair_gen_var_1() -> It<(String, String)> { Box::new(exhaustive_pairs_from_single( exhaustive_strings_using_chars(exhaustive_ascii_chars()), )) } // -- ToSciOptions -- pub fn exhaustive_to_sci_options_gen() -> It { Box::new(exhaustive_to_sci_options()) } // -- (ToSciOptions, bool) -- pub fn exhaustive_to_sci_options_bool_pair_gen() -> It<(ToSciOptions, bool)> { Box::new(lex_pairs(exhaustive_to_sci_options(), exhaustive_bools())) } // -- (ToSciOptions, PrimitiveInt) -- pub fn exhaustive_to_sci_options_primitive_int_pair_gen_var_1() -> It<(ToSciOptions, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_to_sci_options(), exhaustive_positive_primitive_ints(), )) } // -- (ToSciOptions, PrimitiveSigned) -- pub fn exhaustive_to_sci_options_signed_pair_gen_var_1() -> It<(TSO, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_to_sci_options(), exhaustive_negative_signeds(), )) } // -- (ToSciOptions, PrimitiveUnsigned) -- pub fn exhaustive_to_sci_options_unsigned_pair_gen_var_1() -> It<(ToSciOptions, T)> { Box::new(exhaustive_pairs( exhaustive_to_sci_options(), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )) } pub fn exhaustive_to_sci_options_unsigned_pair_gen_var_2() -> It<(ToSciOptions, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_to_sci_options(), exhaustive_unsigneds(), )) } // -- (ToSciOptions, RoundingMode) -- pub fn exhaustive_to_sci_options_rounding_mode_pair_gen() -> It<(ToSciOptions, RoundingMode)> { Box::new(exhaustive_pairs( exhaustive_to_sci_options(), exhaustive_rounding_modes(), )) } // -- Vec -- pub fn exhaustive_bool_vec_gen() -> It> { Box::new(shortlex_vecs(exhaustive_bools())) } pub fn exhaustive_bool_vec_gen_var_1() -> It> { Box::new( shortlex_vecs_length_inclusive_range(0, T::WIDTH, exhaustive_bools()).interleave( exhaustive_pairs_big_tiny( lex_vecs_fixed_length_from_single(T::WIDTH, exhaustive_bools()), exhaustive_positive_primitive_ints(), ) .map(|(bs, n)| bs.into_iter().chain(repeat_n(false, n)).collect()), ), ) } pub fn exhaustive_bool_vec_gen_var_2() -> It> { Box::new( shortlex_vecs_length_inclusive_range(0, T::WIDTH - 1, exhaustive_bools()).interleave( exhaustive_pairs_big_tiny( lex_vecs_fixed_length_from_single(T::WIDTH - 1, exhaustive_bools()), exhaustive_nonzero_signeds::(), ) .map(|(bs, n)| { bs.into_iter() .chain(repeat_n(n < 0, n.unsigned_abs())) .collect() }), ), ) } pub fn exhaustive_bool_vec_gen_var_3() -> It> { Box::new( shortlex_vecs_length_inclusive_range(0, T::WIDTH, exhaustive_bools()).interleave( exhaustive_pairs_big_tiny( lex_vecs_fixed_length_from_single(T::WIDTH, exhaustive_bools()), exhaustive_positive_primitive_ints(), ) .map(|(bs, n)| repeat_n(false, n).chain(bs).collect()), ), ) } pub fn exhaustive_bool_vec_gen_var_4() -> It> { Box::new( shortlex_vecs_length_inclusive_range(0, T::WIDTH - 1, exhaustive_bools()).interleave( exhaustive_pairs_big_tiny( lex_vecs_fixed_length_from_single(T::WIDTH - 1, exhaustive_bools()), exhaustive_nonzero_signeds::(), ) .map(|(bs, n)| repeat_n(n < 0, n.unsigned_abs()).chain(bs).collect()), ), ) } pub fn exhaustive_bool_vec_gen_var_5() -> It> { Box::new(shortlex_vecs_min_length(1, exhaustive_bools()).filter(|bs| bs.iter().any(|&b| b))) } // -- Vec -- pub fn exhaustive_unsigned_vec_gen() -> It> { Box::new(exhaustive_vecs(exhaustive_unsigneds())) } pub fn exhaustive_unsigned_vec_gen_var_1() -> It> { Box::new( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), ) } pub fn exhaustive_unsigned_vec_gen_var_2() -> It> { Box::new( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), ) } pub fn exhaustive_unsigned_vec_gen_var_3() -> It> { Box::new(exhaustive_vecs(exhaustive_unsigneds()).filter(|xs| xs.last() != Some(&T::ZERO))) } pub fn exhaustive_unsigned_vec_gen_var_4() -> It> { Box::new(exhaustive_vecs_min_length(1, exhaustive_unsigneds())) } // var 5 is in malachite-nz. pub fn exhaustive_unsigned_vec_gen_var_6() -> It> { Box::new(exhaustive_vecs_min_length(2, exhaustive_unsigneds())) } // --(Vec, PrimitiveInt) -- pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs_big_small( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs_big_small( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), primitive_int_increasing_inclusive_range(U::exact_from(3), U::MAX), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_5< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(2, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_6< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(U::power_of_2(U::WIDTH - 1), U::MAX), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_7< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), primitive_int_increasing_range(U::ONE, U::power_of_2(U::WIDTH - 1)), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_8< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(U::power_of_2(U::WIDTH - 1), U::MAX), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_9< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), primitive_int_increasing_range(U::ONE, U::power_of_2(U::WIDTH - 1)), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_10< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), primitive_int_increasing_range(U::ONE, U::power_of_2(U::WIDTH - 2)), )) } pub fn exhaustive_unsigned_vec_primitive_int_pair_gen_var_11< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs_big_small( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), primitive_int_increasing_inclusive_range(U::TWO, U::MAX), )) } // --(Vec, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_vec_unsigned_pair_gen() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), )) } struct UnsignedVecUnsignedPairGeneratorVar1; impl ExhaustiveDependentPairsYsGenerator< (usize, usize), Vec, ExhaustiveFixedLengthVecs1Input>, > for UnsignedVecUnsignedPairGeneratorVar1 { #[inline] fn get_ys( &self, &p: &(usize, usize), ) -> ExhaustiveFixedLengthVecs1Input> { exhaustive_vecs_fixed_length_from_single(u64::exact_from(p.1), exhaustive_unsigneds()) } } // TODO generate (usize, usize) pairs better pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_1() -> T1, usize> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x <= y), UnsignedVecUnsignedPairGeneratorVar1, ) .map(|((x, _), zs)| (zs, x)), ) } struct UnsignedVecUnsignedPairGeneratorVar2 { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator, It>> for UnsignedVecUnsignedPairGeneratorVar2 { #[inline] fn get_ys(&self, &log_base: &u64) -> It> { Box::new( exhaustive_vecs_length_inclusive_range( 0, T::WIDTH.div_round(log_base, Ceiling).0, primitive_int_increasing_inclusive_range( U::ZERO, U::low_mask(min(T::WIDTH, log_base)), ), ) .filter(move |xs| digits_valid::(log_base, xs)), ) } } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(1, U::WIDTH), UnsignedVecUnsignedPairGeneratorVar2:: { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, u64)> { Box::new( exhaustive_unsigned_vec_unsigned_pair_gen_var_2::() .map(|(xs, y)| (xs.into_iter().rev().collect(), y)), ) } // var 4 is in malachite-nz struct ValidDigitsGenerator { phantom: PhantomData<(T, U)>, } impl, U: PrimitiveUnsigned> ExhaustiveDependentPairsYsGenerator, It>> for ValidDigitsGenerator { #[inline] fn get_ys(&self, base: &U) -> It> { Box::new(exhaustive_vecs(primitive_int_increasing_range( T::ZERO, T::wrapping_from(*base), ))) } } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_5< T: PrimitiveUnsigned + WrappingFrom, U: PrimitiveUnsigned + SaturatingFrom, >() -> It<(Vec, U)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(U::TWO, U::saturating_from(T::MAX)), ValidDigitsGenerator { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_6() -> It<(Vec, u64)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(1, T::WIDTH), )) } struct DigitsDesc { max_digits: Vec, ds: ShortlexVecs, PrimitiveIntIncreasingRange>, } impl Iterator for DigitsDesc { type Item = Vec; fn next(&mut self) -> Option> { loop { let digits = self.ds.next()?; if digits.len() < self.max_digits.len() || digits <= self.max_digits { return Some(digits); } } } } struct DigitsDescGenerator + PrimitiveUnsigned> { phantom: PhantomData<(T, U)>, } impl + PrimitiveUnsigned> ExhaustiveDependentPairsYsGenerator, DigitsDesc> for DigitsDescGenerator { #[inline] fn get_ys(&self, base: &T) -> DigitsDesc { let max_digits = U::MAX.to_digits_desc(base); DigitsDesc { ds: shortlex_vecs_length_inclusive_range( 0, u64::exact_from(max_digits.len()), primitive_int_increasing_range(T::ZERO, *base), ), max_digits, } } } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_7< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >() -> It<(Vec, T)> { permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(T::TWO, T::saturating_from(U::MAX)), DigitsDescGenerator:: { phantom: PhantomData, }, ))) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_8< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >() -> It<(Vec, T)> { Box::new( exhaustive_unsigned_vec_unsigned_pair_gen_var_7::().map(|(mut xs, base)| { xs.reverse(); (xs, base) }), ) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_9() -> It<(Vec, T)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::TWO, T::MAX), )) } struct PowerOf2DigitsGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, Vec, ExhaustiveVecs, PrimitiveIntIncreasingRange>, > for PowerOf2DigitsGenerator { #[inline] fn get_ys( &self, &log_base: &u64, ) -> ExhaustiveVecs, PrimitiveIntIncreasingRange> { exhaustive_vecs(primitive_int_increasing_inclusive_range( T::ZERO, T::low_mask(log_base), )) } } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_10() -> It<(Vec, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(1, T::WIDTH), PowerOf2DigitsGenerator, ))) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_11() -> It<(Vec, u64)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(1, T::WIDTH), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_12< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(U::TWO, U::saturating_from(T::MAX)), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_13< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_14< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_15< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), ) .filter(|(xs, y)| *y < U::exact_from(xs.len() << T::LOG_WIDTH)), ) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_16< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_17< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_unsigneds(), )) } // vars 18 through 20 are in malachite-nz. pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_21() -> It<(Vec, u64)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_range(1, U::WIDTH), )) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_22() -> It<(Vec, u64)> { Box::new(exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), primitive_int_increasing_range(1, U::WIDTH), )) } // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen() -> It<(Vec, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), )) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> It<(Vec, U, V)> { Box::new(exhaustive_triples_custom_output( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), )) } struct UnsignedVecUnsignedUnsignedTripleGeneratorVar2; impl ExhaustiveDependentPairsYsGenerator< (usize, usize), Vec, ExhaustiveVecs, PrimitiveIntIncreasingRange>, > for UnsignedVecUnsignedUnsignedTripleGeneratorVar2 { #[inline] fn get_ys( &self, &(i, j): &(usize, usize), ) -> ExhaustiveVecs, PrimitiveIntIncreasingRange> { exhaustive_vecs_min_length(u64::exact_from(i * j), exhaustive_unsigneds()) } } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_2() -> It<(Vec, usize, usize)> { reshape_1_2_to_3(permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds()), UnsignedVecUnsignedUnsignedTripleGeneratorVar2, )))) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U, U)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(xs, y, z): (Vec, U, U)| y.checked_add(z).map(|new_z| (xs, y, new_z))), ) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U, U)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(xs, y, z): (Vec, U, U)| y.checked_add(z).map(|new_z| (xs, y, new_z))), ) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_5() -> It<(Vec, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_positive_primitive_ints(), )) } // var 6 is in malachite-nz. pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_7() -> It<(Vec, T, T)> { Box::new(exhaustive_triples( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_8< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // var 9 is in malachite-nz. pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_10() -> It<(Vec, T, T)> { Box::new(exhaustive_triples( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), exhaustive_unsigneds(), )) } // vars 11 through 12 are in malachite-nz. pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_13< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_unsigneds(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // var 14 is in malachite-nz. // -- (Vec, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_unsigned_vec_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U, RoundingMode)> { Box::new(exhaustive_triples( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_unsigneds(), exhaustive_rounding_modes(), )) } pub fn exhaustive_unsigned_vec_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, U, RoundingMode)> { Box::new(exhaustive_triples_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), exhaustive_unsigneds(), exhaustive_rounding_modes(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), )) } // -- (Vec, Vec) -- pub fn exhaustive_unsigned_vec_pair_gen() -> It<(Vec, Vec)> { Box::new(exhaustive_pairs_from_single(exhaustive_vecs( exhaustive_unsigneds(), ))) } pub struct UnsignedVecPairLenGenerator1; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Vec, Vec), ExhaustivePairs< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, >, > for UnsignedVecPairLenGenerator1 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j): &(u64, u64), ) -> ExhaustivePairs< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, > { exhaustive_pairs( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()), ) } } pub fn exhaustive_unsigned_vec_pair_gen_var_1() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_2() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_3() -> It<(Vec, Vec)> { Box::new(exhaustive_pairs_from_single(exhaustive_vecs_min_length( 1, exhaustive_unsigneds(), ))) } pub fn exhaustive_unsigned_vec_pair_gen_var_4() -> It<(Vec, Vec)> { Box::new( exhaustive_pairs_from_single(exhaustive_vecs_min_length(1, exhaustive_unsigneds())).filter( |(xs, es)| { !xs.is_empty() && (es.len() > 1 || es.len() == 1 && es[0] > T::ONE) && *es.last().unwrap() != T::ZERO }, ), ) } struct UnsignedVecSqrtRemGenerator; impl ExhaustiveDependentPairsYsGenerator<(u64, u64), (Vec, Vec), It<(Vec, Vec)>> for UnsignedVecSqrtRemGenerator { #[allow(clippy::type_complexity)] #[inline] fn get_ys(&self, &(out_len, len): &(u64, u64)) -> It<(Vec, Vec)> { Box::new( exhaustive_triples( exhaustive_vecs_fixed_length_from_single(out_len, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(len - 1, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::power_of_2(T::WIDTH - 2), T::MAX), ) .map(move |(out, mut ns, n_hi)| { ns.insert((usize::exact_from(out_len) << 1) - 1, n_hi); (out, ns) }), ) } } pub fn exhaustive_unsigned_vec_pair_gen_var_5() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let n = x.checked_add(2)?; let len: u64 = n.arithmetic_checked_shl(1)?; let len = len.checked_add(y)?; Some((n, len)) }), UnsignedVecSqrtRemGenerator, ) .map(|p| p.1), ) } struct UnsignedVecSqrtGenerator; impl ExhaustiveDependentPairsYsGenerator<(u64, u64), (Vec, Vec), It<(Vec, Vec)>> for UnsignedVecSqrtGenerator { #[allow(clippy::type_complexity)] #[inline] fn get_ys(&self, &(out_len, len): &(u64, u64)) -> It<(Vec, Vec)> { Box::new( exhaustive_triples( exhaustive_vecs_fixed_length_from_single(out_len, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(len - 1, exhaustive_unsigneds()), exhaustive_positive_primitive_ints(), ) .map(move |(out, mut ns, n_hi)| { ns.push(n_hi); (out, ns) }), ) } } pub fn exhaustive_unsigned_vec_pair_gen_var_6() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let in_len = x.checked_add(1)?; let mut out_len: u64 = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; Some((out_len, in_len)) }), UnsignedVecSqrtGenerator, ) .map(|p| p.1), ) } struct UnsignedVecPairSameLenGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, (Vec, Vec), ExhaustivePairs1Input>>, > for UnsignedVecPairSameLenGenerator { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &len: &u64, ) -> ExhaustivePairs1Input>> { exhaustive_pairs_from_single(exhaustive_vecs_fixed_length_from_single( len, exhaustive_unsigneds(), )) } } pub fn exhaustive_unsigned_vec_pair_gen_var_7() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_unsigneds(), UnsignedVecPairSameLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_8() -> It<(Vec, Vec)> { Box::new(exhaustive_pairs_from_single( exhaustive_vecs(exhaustive_unsigneds()).filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn exhaustive_unsigned_vec_pair_gen_var_9() -> It<(Vec, Vec)> { Box::new(exhaustive_pairs_from_single( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).filter(|xs| !slice_test_zero(xs)), )) } pub struct UnsignedVecPairLenGenerator2; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Vec, Vec), ExhaustivePairs, It>, Vec, It>>, > for UnsignedVecPairLenGenerator2 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j): &(u64, u64), ) -> ExhaustivePairs, It>, Vec, It>> { exhaustive_pairs( Box::new( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()) .filter(|xs| !slice_test_zero(xs)), ), Box::new( exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()) .filter(|xs| !slice_test_zero(xs)), ), ) } } pub fn exhaustive_unsigned_vec_pair_gen_var_10() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator2, ) .map(|p| p.1), ) } // var 11 is in malachite-nz. pub fn exhaustive_unsigned_vec_pair_gen_var_12() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( ruler_sequence(), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .filter_map(|(_, (ns, ds))| { if *ds.last().unwrap() == T::ZERO { None } else { Some((ns, ds)) } }), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_13() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .filter_map( |(_, (xs, ys)): (_, (Vec, Vec))| if ys[0].odd() { Some((xs, ys)) } else { None }, ), ) } // vars 14 through 15 are in malachite-nz pub fn exhaustive_unsigned_vec_pair_gen_var_16() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .filter_map(|(_, (mut xs, mut ys))| { let last_x = xs.last_mut().unwrap(); let last_y = ys.last_mut().unwrap(); if *last_x == T::MAX || *last_y == T::MAX { None } else { *last_x += T::ONE; *last_y += T::ONE; Some((xs, ys)) } }), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_17() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .filter_map(|(_, (mut xs, mut ys))| { let last_x = xs.last_mut().unwrap(); let last_y = ys.last_mut().unwrap(); if *last_x == T::MAX || *last_y == T::MAX { None } else { *last_x += T::ONE; *last_y += T::ONE; Some((xs, ys)) } }), ) } // var 18 is in malachite-nz. pub fn exhaustive_unsigned_vec_pair_gen_var_19() -> It<(Vec, Vec)> { Box::new( exhaustive_triples( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::power_of_2(T::WIDTH - 1), T::MAX), exhaustive_unsigneds(), ) .map(|(n, d_1, d_0)| (n, vec![d_0, d_1])), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_20() -> It<(Vec, Vec)> { Box::new(exhaustive_pairs_from_single( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()).filter_map(|mut xs| { let last = xs.last_mut().unwrap(); *last = last.checked_add(T::ONE)?; Some(xs) }), )) } pub fn exhaustive_unsigned_vec_pair_gen_var_21() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } // vars 22 through 31 are in malachite-nz. pub fn exhaustive_unsigned_vec_pair_gen_var_32() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_33() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_positive_primitive_ints(), UnsignedVecPairSameLenGenerator, ) .filter_map(|(_, (xs, ys)): (_, (Vec, Vec))| { if (*xs.last().unwrap() != T::ZERO || *ys.last().unwrap() != T::ZERO) && ys[0].odd() { Some((xs, ys)) } else { None } }), ) } // var 34 is in malachite-nz. // --(Vec, Vec, bool) -- pub fn exhaustive_unsigned_vec_unsigned_vec_bool_triple_gen_var_1() -> It<(Vec, Vec, bool)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_unsigned_vec_pair_gen_var_7(), exhaustive_bools(), ))) } // --(Vec, Vec, PrimitiveUnsigned) -- pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), exhaustive_unsigneds(), ))) } // var 2 and 3 are in malachite-nz pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), exhaustive_unsigneds(), ))) } struct UnsignedVecPairLenGenerator3; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Vec, Vec), ExhaustivePairs< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, It>, >, > for UnsignedVecPairLenGenerator3 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j): &(u64, u64), ) -> ExhaustivePairs< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, It>, > { exhaustive_pairs( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), Box::new( exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()) .filter(|xs| !slice_test_zero(xs)), ), ) } } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator3, ) .map(|p| p.1), exhaustive_unsigneds(), ))) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, Vec, U)> { Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_positive_primitive_ints(), )) } // vars 7 through 8 are in malachite-nz. pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, Vec, U)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, Vec, U)> { Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_positive_primitive_ints(), )) } struct UnsignedVecPairLenAndIndexGenerator; impl ExhaustiveDependentPairsYsGenerator< (u64, u64, u64), (Vec, Vec, usize), It<(Vec, Vec, usize)>, > for UnsignedVecPairLenAndIndexGenerator { #[inline] fn get_ys(&self, &(x, y, i): &(u64, u64, u64)) -> It<(Vec, Vec, usize)> { Box::new( exhaustive_pairs( exhaustive_vecs_fixed_length_from_single(x, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(y, exhaustive_unsigneds()), ) .map(move |(x, y)| (x, y, usize::exact_from(i))), ) } } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11() -> It<(Vec, Vec, usize)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, i)| { let y = y.checked_add(i)?; let x = x.checked_add(y)?; Some((x, y, i)) }, ), UnsignedVecPairLenAndIndexGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_unsigned_vec_pair_gen_var_7(), exhaustive_unsigneds(), ))) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13() -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), exhaustive_positive_primitive_ints(), ))) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_range(1, U::WIDTH), ))) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_range(1, U::WIDTH), ))) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24() -> It<(Vec, Vec, usize)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, i)| { let x = x.checked_add(i)?; Some((x, x, i)) }), UnsignedVecPairLenAndIndexGenerator, ) .map(|p| p.1), ) } // --(Vec, Vec, Vec) -- pub struct UnsignedVecTripleXYYLenGenerator; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Vec, Vec, Vec), ExhaustiveTriplesXYY< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, >, > for UnsignedVecTripleXYYLenGenerator { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j): &(u64, u64), ) -> ExhaustiveTriplesXYY< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, > { exhaustive_triples_xyy( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()), ) } } pub fn exhaustive_unsigned_vec_triple_gen_var_1() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } pub struct UnsignedVecTripleLenGenerator1; impl ExhaustiveDependentPairsYsGenerator< (u64, u64, u64), (Vec, Vec, Vec), ExhaustiveTriples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, >, > for UnsignedVecTripleLenGenerator1 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j, k): &(u64, u64, u64), ) -> ExhaustiveTriples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, > { exhaustive_triples( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(k, exhaustive_unsigneds()), ) } } pub struct UnsignedVecQuadrupleLenGenerator1; impl ExhaustiveDependentPairsYsGenerator< (u64, u64, u64, u64), (Vec, Vec, Vec, Vec), ExhaustiveQuadruples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, >, > for UnsignedVecQuadrupleLenGenerator1 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j, k, l): &(u64, u64, u64, u64), ) -> ExhaustiveQuadruples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, Vec, ExhaustiveFixedLengthVecs1Input>, > { exhaustive_quadruples( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(k, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(l, exhaustive_unsigneds()), ) } } pub fn exhaustive_unsigned_vec_triple_gen_var_2() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_3() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(1)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ) } // vars 4 through 23 are in malachite-nz pub fn exhaustive_unsigned_vec_triple_gen_var_24() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_25() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_26() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } struct UnsignedVecTripleXXXLenGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, (Vec, Vec, Vec), ExhaustiveTriples1Input>>, > for UnsignedVecTripleXXXLenGenerator { #[inline] fn get_ys( &self, &i: &u64, ) -> ExhaustiveTriples1Input>> { exhaustive_triples_from_single(exhaustive_vecs_fixed_length_from_single( i, exhaustive_unsigneds(), )) } } pub fn exhaustive_unsigned_vec_triple_gen_var_27() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range::(2, u64::MAX), UnsignedVecTripleXXXLenGenerator, ) .map(|p| p.1), ) } struct UnsignedVecSqrtRemGenerator3; impl ExhaustiveDependentPairsYsGenerator< (u64, u64, u64), (Vec, Vec, Vec), It<(Vec, Vec, Vec)>, > for UnsignedVecSqrtRemGenerator3 { #[allow(clippy::type_complexity)] #[inline] fn get_ys(&self, &(out_len, rem_len, len): &(u64, u64, u64)) -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_quadruples( exhaustive_vecs_fixed_length_from_single(out_len, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(rem_len, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(len - 1, exhaustive_unsigneds()), exhaustive_positive_primitive_ints(), ) .map(move |(out, rs, mut ns, n_hi)| { ns.push(n_hi); (out, rs, ns) }), ) } } pub fn exhaustive_unsigned_vec_triple_gen_var_28() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let in_len = x.checked_add(1)?; let mut out_len: u64 = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; let rem_len = in_len.checked_add(z)?; Some((out_len, rem_len, in_len)) }, ), UnsignedVecSqrtRemGenerator3, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_29() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_unsigneds(), UnsignedVecTripleXXXLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_30() -> It<(Vec, Vec, Vec)> { Box::new(exhaustive_triples_from_single( exhaustive_vecs(exhaustive_unsigneds()).filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn exhaustive_unsigned_vec_triple_gen_var_31() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_32() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let o = max(x, y).checked_add(o)?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ) } struct UnsignedVecTripleLenGenerator2; impl ExhaustiveDependentPairsYsGenerator< (u64, u64, u64), (Vec, Vec, Vec), ExhaustiveTriples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, It>, Vec, It>, >, > for UnsignedVecTripleLenGenerator2 { #[allow(clippy::type_complexity)] #[inline] fn get_ys( &self, &(i, j, k): &(u64, u64, u64), ) -> ExhaustiveTriples< Vec, ExhaustiveFixedLengthVecs1Input>, Vec, It>, Vec, It>, > { exhaustive_triples( exhaustive_vecs_fixed_length_from_single(i, exhaustive_unsigneds()), Box::new( exhaustive_vecs_fixed_length_from_single(j, exhaustive_unsigneds()) .filter(|xs| !slice_test_zero(xs)), ), Box::new( exhaustive_vecs_fixed_length_from_single(k, exhaustive_unsigneds()) .filter(|xs| !slice_test_zero(xs)), ), ) } } pub fn exhaustive_unsigned_vec_triple_gen_var_33() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(x)?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator2, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_34() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(max(x, y))?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator2, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_35() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(min(x, y))?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator2, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_36() -> It<(Vec, Vec, Vec)> { Box::new(exhaustive_triples_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } // vars 37 through 38 are in malachite-nz. pub fn exhaustive_unsigned_vec_triple_gen_var_39() -> It<(Vec, Vec, Vec)> { Box::new(exhaustive_triples_from_single( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } pub fn exhaustive_unsigned_vec_triple_gen_var_40() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(o, x, y)| { let x = x.checked_add(y)?; let o = o.checked_add(x)?; Some((o, x, y)) }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_41() -> It<(Vec, Vec, Vec)> { Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(1, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } // vars 42 through 49 are in malachite-nz. pub fn exhaustive_unsigned_vec_triple_gen_var_50() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (x, mut y, z)): (_, (Vec, Vec, Vec))| { let last_y = y.last_mut().unwrap(); if last_y.get_highest_bit() { return None; } last_y.set_bit(T::WIDTH - 1); Some((x, y, z)) }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_51() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let y = y.checked_add(5)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (x, mut y, z)): (_, (Vec, Vec, Vec))| { let last_y = y.last_mut().unwrap(); if last_y.get_highest_bit() { return None; } last_y.set_bit(T::WIDTH - 1); Some((x, y, z)) }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_52() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let q = x.checked_add(3)?; let n = y.checked_add(9)?; let d = z.checked_add(6)?; if n < d { return None; } let q_alt = n - d + 1; if (q_alt << 1) > n || q_alt > d { return None; } let n_alt = q_alt << 1; let d_alt = q_alt; if q >= q_alt && d_alt >= 6 && n_alt >= d_alt + 3 && d_alt >= q_alt { Some((q, n, d)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (x, y, mut z)): (_, (Vec, Vec, Vec))| { let last_z = z.last_mut().unwrap(); if last_z.get_highest_bit() { return None; } last_z.set_bit(T::WIDTH - 1); Some((x, y, z)) }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_53() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range(2, u64::MAX), ) .filter(|&(x, y)| x >= y - 2), UnsignedVecPairLenGenerator1, ), exhaustive_unsigned_pair_gen_var_24(), ) .map(|((_, (q, n)), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // vars 54 through 56 are in malachite-nz. pub fn exhaustive_unsigned_vec_triple_gen_var_57() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(r_len, n_len, d_len)| { let d_len = d_len.checked_add(2)?; let r_len = r_len.checked_add(d_len)?; let n_len = n_len.checked_add(d_len)?; Some((r_len, n_len, d_len)) }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (r, n, mut d)): (_, (Vec, Vec, Vec))| { let last_d = d.last_mut().unwrap(); *last_d = last_d.checked_add(T::ONE)?; Some((r, n, d)) }), ) } // var 58 is in malachite-nz. pub fn exhaustive_unsigned_vec_triple_gen_var_59() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(xs_len, ys_len, zs_len)| { let ys_len = ys_len.checked_add(2)?; let zs_len = zs_len.checked_add(2)?; let xs_len = xs_len.checked_add(ys_len + zs_len - 1)?; Some((xs_len, ys_len, zs_len)) }, ), UnsignedVecTripleLenGenerator1, ) .filter_map( |(_, (mut xs, mut ys, mut zs)): (_, (Vec, Vec, Vec))| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(T::ONE)?; let last_y = ys.last_mut().unwrap(); *last_y = last_y.checked_add(T::ONE)?; let last_z = zs.last_mut().unwrap(); *last_z = last_z.checked_add(T::ONE)?; Some((xs, ys, zs)) }, ), ) } // var 60 is in malachite-nz. // -- large types -- pub fn exhaustive_large_type_gen_var_1() -> It<(Vec, Vec, T, T)> { reshape_2_2_to_4(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), exhaustive_pairs_from_single(exhaustive_unsigneds()), ))) } struct UnsignedVecSqrtRemGenerator2; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Vec, Vec, u64, bool), It<(Vec, Vec, u64, bool)>, > for UnsignedVecSqrtRemGenerator2 { #[allow(clippy::type_complexity)] #[inline] fn get_ys(&self, &(n, len): &(u64, u64)) -> It<(Vec, Vec, u64, bool)> { Box::new( exhaustive_pairs( exhaustive_vecs_fixed_length_from_single(n, exhaustive_unsigneds()), exhaustive_vecs_fixed_length_from_single(len, exhaustive_unsigneds::()) .filter(|xs| *xs.last().unwrap() != T::ZERO), ) .map(move |(out, ns)| { let shift = ns.last().unwrap().leading_zeros() >> 1; (out, ns, shift, len.odd()) }), ) } } pub fn exhaustive_large_type_gen_var_2() -> It<(Vec, Vec, u64, bool)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), Box::new(exhaustive_unsigneds::().filter_map(|x| { let len = x.checked_add(9)?; let n = len.shr_round(1, Ceiling).0; Some((n, len)) })), UnsignedVecSqrtRemGenerator2, ) .map(|p| p.1), ) } pub fn exhaustive_large_type_gen_var_3() -> It<(Vec, U, U, Vec)> { Box::new( exhaustive_quadruples_xyyx::, _, U, _>( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), ) .filter_map(|(x, y, z, w)| Some((x, y, y.checked_add(U::ONE)?.checked_add(z)?, w))), ) } pub fn exhaustive_large_type_gen_var_4() -> It<(Vec, U, U, Vec)> { Box::new( exhaustive_quadruples_xyyz( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()) .filter(|xs| !slice_test_zero(xs)), exhaustive_unsigneds::(), exhaustive_vecs(exhaustive_unsigneds::()), ) .filter_map(|(x, y, z, w)| Some((x, y, y.checked_add(U::ONE)?.checked_add(z)?, w))), ) } // vars 5 through 8 are in malachite-nz #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_9() -> It<(Vec, Vec, Vec, bool)> { reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), exhaustive_bools(), ))) } // vars 10 through 21 are in malachite-nz. pub fn exhaustive_large_type_gen_var_22() -> It<(RationalSequence, usize, T, T)> { Box::new( exhaustive_quadruples_xyzz( exhaustive_rational_sequences(exhaustive_unsigneds()), exhaustive_unsigneds(), exhaustive_unsigneds(), ) .filter(|&(ref xs, index, _, _)| { if let Some(len) = xs.len() { index < len } else { true } }), ) } // vars 23 through 26 are in malachite-nz. pub fn exhaustive_large_type_gen_var_27() -> It<(bool, Vec, bool, Vec)> { permute_3_1_4_2(reshape_2_1_1_to_4(Box::new(lex_triples_xyy( exhaustive_pairs_from_single( exhaustive_vecs(exhaustive_unsigneds()).filter(|xs| xs.last() != Some(&T::ZERO)), ), exhaustive_bools(), )))) } ================================================ FILE: malachite-base/src/test_util/generators/mod.rs ================================================ // Copyright © 2026 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 crate::iterators::bit_distributor::BitDistributorOutputType; use crate::num::arithmetic::traits::UnsignedAbs; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::options::{FromSciStringOptions, SciSizeOptions, ToSciOptions}; use crate::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, HasHalf, JoinHalves, RoundingFrom, SaturatingFrom, SplitInHalf, WrappingFrom, WrappingInto, }; use crate::num::factorization::traits::IsPrime; use crate::num::float::NiceFloat; use crate::num::logic::traits::{BitBlockAccess, LeadingZeros}; use crate::rational_sequences::RationalSequence; use crate::rounding_modes::RoundingMode; use crate::slices::slice_trailing_zeros; use crate::test_util::generators::common::Generator; use crate::test_util::generators::exhaustive::*; use crate::test_util::generators::random::*; use crate::test_util::generators::special_random::*; use crate::tuples::exhaustive::{ExhaustivePairs, exhaustive_pairs_custom_output}; // general #[inline] pub fn exhaustive_pairs_big_tiny< X: Clone, I: Iterator, Y: Clone, J: Iterator, >( xs: I, ys: J, ) -> ExhaustivePairs { exhaustive_pairs_custom_output( xs, ys, BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) } #[inline] pub fn exhaustive_pairs_big_small< X: Clone, I: Iterator, Y: Clone, J: Iterator, >( xs: I, ys: J, ) -> ExhaustivePairs { exhaustive_pairs_custom_output( xs, ys, BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(1), ) } fn digits_valid(log_base: u64, digits: &[U]) -> bool { let digits = &digits[..digits.len() - slice_trailing_zeros(digits)]; if digits.is_empty() { return true; } let significant_bits = ((u64::wrapping_from(digits.len()) - 1) * log_base) + digits.last().unwrap().significant_bits(); significant_bits <= T::WIDTH } fn unsigned_assign_bits_valid(start: u64, end: u64, bits: T) -> bool { let bits_width = end - start; let bits = bits.mod_power_of_2(bits_width); bits == T::ZERO || LeadingZeros::leading_zeros(bits) >= start } fn signed_assign_bits_valid< T: PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >( x: T, start: u64, end: u64, bits: U, ) -> bool { if x >= T::ZERO { unsigned_assign_bits_valid(start, end, bits) && { let mut abs_self = x.unsigned_abs(); abs_self.assign_bits(start, end, &bits); !abs_self.get_highest_bit() } } else { start <= end && { let width = T::WIDTH; let bits_width = end - start; let bits = bits.mod_power_of_2(bits_width); bits_width <= width && if start >= width - 1 { bits == U::low_mask(bits_width) } else { end < width || bits >> (width - 1 - start) == U::low_mask(end - width + 1) } } } } // -- bool -- pub fn bool_gen() -> Generator { Generator::new_no_special(&exhaustive_bool_gen, &random_bool_gen) } // -- char -- pub fn char_gen() -> Generator { Generator::new( &exhaustive_char_gen, &random_char_gen, &special_random_char_gen, ) } // All `char`s except for `char::MAX`. pub fn char_gen_var_1() -> Generator { Generator::new( &exhaustive_char_gen_var_1, &random_char_gen_var_1, &special_random_char_gen_var_1, ) } // All `char`s except for `char::MIN`. pub fn char_gen_var_2() -> Generator { Generator::new( &exhaustive_char_gen_var_2, &random_char_gen_var_2, &special_random_char_gen_var_2, ) } // -- (char, char) -- pub fn char_pair_gen() -> Generator<(char, char)> { Generator::new( &exhaustive_char_pair_gen, &random_char_pair_gen, &special_random_char_pair_gen, ) } // -- FromSciStringOptions -- pub fn from_sci_string_options_gen() -> Generator { Generator::new_no_special( &exhaustive_from_sci_string_options_gen, &random_from_sci_string_options_gen, ) } // -- (FromSciStringOptions, PrimitiveUnsigned) -- // All `(FromSciStringOptions, T)` where `T` is unsigned and the `T` is between 2 and 36, inclusive. pub fn from_sci_string_options_unsigned_pair_gen_var_1() -> Generator<(FromSciStringOptions, T)> { Generator::new( &exhaustive_from_sci_string_options_unsigned_pair_gen_var_1, &random_from_sci_string_options_unsigned_pair_gen_var_1, &special_random_from_sci_string_options_unsigned_pair_gen_var_1, ) } // -- (FromSciStringOptions, RoundingMode) -- pub fn from_sci_string_options_rounding_mode_pair_gen() -> Generator<(FromSciStringOptions, RoundingMode)> { Generator::new_no_special( &exhaustive_from_sci_string_options_rounding_mode_pair_gen, &random_from_sci_string_options_rounding_mode_pair_gen, ) } // -- PrimitiveFloat -- pub fn primitive_float_gen() -> Generator { Generator::new( &exhaustive_primitive_float_gen, &random_primitive_float_gen, &special_random_primitive_float_gen, ) } // All primitive floats that are finite, not NaN, and greater than or equal to -0.5. pub fn primitive_float_gen_var_1() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_1, &random_primitive_float_gen_var_1, &special_random_primitive_float_gen_var_1, ) } // All primitive floats that are non-negative and equal to an integer. pub fn primitive_float_gen_var_2() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_2, &random_primitive_float_gen_var_2, &special_random_primitive_float_gen_var_2, ) } // All primitive floats that are non-negative and not equal to any integer. pub fn primitive_float_gen_var_3() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_3, &random_primitive_float_gen_var_3, &special_random_primitive_float_gen_var_3, ) } // All primitive floats that are non-negative and halfway between two adjacent integers. pub fn primitive_float_gen_var_4() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_4, &random_primitive_float_gen_var_4, &special_random_primitive_float_gen_var_4, ) } // All primitive floats that are equal to an integer. pub fn primitive_float_gen_var_5() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_5, &random_primitive_float_gen_var_5, &special_random_primitive_float_gen_var_5, ) } // All primitive floats that are not equal to any integer. pub fn primitive_float_gen_var_6() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_6, &random_primitive_float_gen_var_6, &special_random_primitive_float_gen_var_6, ) } // All primitive floats that are halfway between two adjacent integers. pub fn primitive_float_gen_var_7() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_7, &random_primitive_float_gen_var_7, &special_random_primitive_float_gen_var_7, ) } // All finite primitive floats. pub fn primitive_float_gen_var_8() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_8, &random_primitive_float_gen_var_8, &special_random_primitive_float_gen_var_8, ) } // All primitive floats that are not NaN or positive infinity. pub fn primitive_float_gen_var_9() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_9, &random_primitive_float_gen_var_9, &special_random_primitive_float_gen_var_9, ) } // All primitive floats that are not NaN or negative infinity. pub fn primitive_float_gen_var_10() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_10, &random_primitive_float_gen_var_10, &special_random_primitive_float_gen_var_10, ) } // All primitive floats that are not NaN. pub fn primitive_float_gen_var_11() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_11, &random_primitive_float_gen_var_11, &special_random_primitive_float_gen_var_11, ) } // All nonzero finite primitive floats. pub fn primitive_float_gen_var_12() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_12, &random_primitive_float_gen_var_12, &special_random_primitive_float_gen_var_12, ) } // All primitive floats `T` that are equal to an unsigned value of type `U`. pub fn primitive_float_gen_var_13, U: PrimitiveUnsigned>() -> Generator where NiceFloat: TryFrom, { Generator::new( &exhaustive_primitive_float_gen_var_13::, &random_primitive_float_gen_var_13::, &special_random_primitive_float_gen_var_13::, ) } // All primitive floats `T` that are equal to a signed value of type `U`. pub fn primitive_float_gen_var_14, U: PrimitiveSigned>() -> Generator where NiceFloat: TryFrom, { Generator::new( &exhaustive_primitive_float_gen_var_14::, &random_primitive_float_gen_var_13::, &special_random_primitive_float_gen_var_14::, ) } // All primitive floats of type `T` that are not equal to any primitive integer of type `U`. pub fn primitive_float_gen_var_15 + PrimitiveInt>() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_15::, &random_primitive_float_gen_var_14::, &special_random_primitive_float_gen_var_15::, ) } // All primitive floats of type `T` that are halfway between two adjacent values of the primitive // unsigned type `U`. pub fn primitive_float_gen_var_16, U: PrimitiveUnsigned>() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_16::, &random_primitive_float_gen_var_15::, &special_random_primitive_float_gen_var_16::, ) } // All primitive floats of type `T` that are halfway between two adjacent values of the primitive // signed type `U`. pub fn primitive_float_gen_var_17, U: PrimitiveSigned>() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_17::, &random_primitive_float_gen_var_16::, &special_random_primitive_float_gen_var_17::, ) } // All positive finite primitive floats of type `T`. pub fn primitive_float_gen_var_18() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_18, &random_primitive_float_gen_var_17, &special_random_primitive_float_gen_var_18, ) } // All non-negative finite primitive floats of type `T` that are less than or equal to the largest // representable power of 2. Negative zero is excluded. pub fn primitive_float_gen_var_19() -> Generator { Generator::new( &exhaustive_primitive_float_gen_var_19, &random_primitive_float_gen_var_18, &special_random_primitive_float_gen_var_19, ) } // -- (PrimitiveFloat, PrimitiveFloat) -- pub fn primitive_float_pair_gen() -> Generator<(T, T)> { Generator::new( &exhaustive_primitive_float_pair_gen, &random_primitive_float_pair_gen, &special_random_primitive_float_pair_gen, ) } // All pairs of primitive floats that are not NaN. pub fn primitive_float_pair_gen_var_1() -> Generator<(T, T)> { Generator::new( &exhaustive_primitive_float_pair_gen_var_1, &random_primitive_float_pair_gen_var_1, &special_random_primitive_float_pair_gen_var_1, ) } // -- (PrimitiveFloat, PrimitiveFloat, PrimitiveFloat) -- pub fn primitive_float_triple_gen() -> Generator<(T, T, T)> { Generator::new( &exhaustive_primitive_float_triple_gen, &random_primitive_float_triple_gen, &special_random_primitive_float_triple_gen, ) } // -- (PrimitiveFloat, PrimitiveSigned) -- pub fn primitive_float_signed_pair_gen() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_signed_pair_gen, &random_primitive_float_signed_pair_gen, &special_random_primitive_float_signed_pair_gen, ) } // All `(T, U)` where `T` is a primitive float type, `U` is signed, the `T` is finite and positive, // and the `U` is small. pub fn primitive_float_signed_pair_gen_var_1() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_signed_pair_gen_var_1, &random_primitive_float_signed_pair_gen_var_1, &special_random_primitive_float_signed_pair_gen_var_1, ) } // All `(T, i64)` that are valid inputs to `T::from_sci_mantissa_and_exponent`. pub fn primitive_float_signed_pair_gen_var_2() -> Generator<(T, i64)> { Generator::new( &exhaustive_primitive_float_signed_pair_gen_var_2, &random_primitive_float_signed_pair_gen_var_2, &special_random_primitive_float_signed_pair_gen_var_2, ) } // All `(T, i64)` where `T` is a primitive float type, the `T` is greater than or equal to 1.0 and // less than 2.0, and the `i64` is small. pub fn primitive_float_signed_pair_gen_var_3() -> Generator<(T, i64)> { Generator::new( &exhaustive_primitive_float_signed_pair_gen_var_3, &random_primitive_float_signed_pair_gen_var_3, &special_random_primitive_float_signed_pair_gen_var_3, ) } // All `(T, U)` where `T` is a primitive float type, `U` is signed, and the `U` is small. pub fn primitive_float_signed_pair_gen_var_4() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_signed_pair_gen_var_4, &random_primitive_float_signed_pair_gen_var_4, &special_random_primitive_float_signed_pair_gen_var_4, ) } // -- (PrimitiveFloat, PrimitiveSigned, PrimitiveUnsigned) -- // All `(T, U, V)` where `T` is a primitive float type, `U` is signed, `V` is unsigned, the `U` is // small, and the `V` is small and positive. pub fn primitive_float_signed_unsigned_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_primitive_float_signed_unsigned_triple_gen_var_1, &random_primitive_float_signed_unsigned_triple_gen_var_1, &special_random_primitive_float_signed_unsigned_triple_gen_var_1, ) } // -- (PrimitiveFloat, PrimitiveUnsigned) -- // All `(T, U)` where `T` is a primitive float type, `U` is unsigned, the `T` is finite and // positive, and the `U` is small. pub fn primitive_float_unsigned_pair_gen_var_1() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_unsigned_pair_gen_var_1, &random_primitive_float_unsigned_pair_gen_var_1, &special_random_primitive_float_unsigned_pair_gen_var_1, ) } // All `(T, u64)` where `T` is a primitive float type, the `T` is greater than or equal to 1.0 and // less than 2.0, and the `u64` is small. pub fn primitive_float_unsigned_pair_gen_var_2() -> Generator<(T, u64)> { Generator::new( &exhaustive_primitive_float_unsigned_pair_gen_var_2, &random_primitive_float_unsigned_pair_gen_var_2, &special_random_primitive_float_unsigned_pair_gen_var_2, ) } // All `(T, U)` where `T` is a primitive float type, `U` is unsigned, the `T` is finite and // positive, and the `U` is small and positive. pub fn primitive_float_unsigned_pair_gen_var_3() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_primitive_int_pair_gen_var_1, &random_primitive_float_unsigned_pair_gen_var_3, &special_random_primitive_float_unsigned_pair_gen_var_3, ) } // All `(T, U)` where `T` is a primitive float type, `U` is unsigned, and the `U` is small and // positive. pub fn primitive_float_unsigned_pair_gen_var_4() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_float_unsigned_pair_gen_var_3, &random_primitive_float_unsigned_pair_gen_var_4, &special_random_primitive_float_unsigned_pair_gen_var_4, ) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- // All `(T, U, RoundingMode)` where `T` is a primitive float type, `U` is unsigned, the `T` is // finite and positive, and the `U` is small. pub fn primitive_float_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_1, &random_primitive_float_unsigned_rounding_mode_triple_gen_var_1, &special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_1, ) } // All `(T, u64, RoundingMode)` where `T` is a primitive float type, the `T` is greater than or // equal to 1.0 and less than 2.0, and the `u64` is small. pub fn primitive_float_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_2, &random_primitive_float_unsigned_rounding_mode_triple_gen_var_2, &special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_2, ) } // var 3 is in malachite-float. // -- (PrimitiveFloat, RoundingMode) -- // All `(T, RoundingMode)` where `T` is a primitive float and the values are valid inputs to // `Natural::rounding_from`. pub fn primitive_float_rounding_mode_pair_gen_var_1() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_primitive_float_rounding_mode_pair_gen_var_1, &random_primitive_float_rounding_mode_pair_gen_var_1, &special_random_primitive_float_rounding_mode_pair_gen_var_1, ) } // All `(T, RoundingMode)` where `T` is a primitive float and the values are valid inputs to // `Integer::rounding_from`. pub fn primitive_float_rounding_mode_pair_gen_var_2() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_primitive_float_rounding_mode_pair_gen_var_2, &random_primitive_float_rounding_mode_pair_gen_var_2, &special_random_primitive_float_rounding_mode_pair_gen_var_2, ) } // All `(T, RoundingMode)` where `T` is a primitive float, `U` is unsigned, and the pair is a valid // input to `U::rounding_from`. pub fn primitive_float_rounding_mode_pair_gen_var_3< T: PrimitiveFloat + RoundingFrom, U: ConvertibleFrom + PrimitiveInt, >() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_primitive_float_rounding_mode_pair_gen_var_3::, &random_primitive_float_rounding_mode_pair_gen_var_3::, &special_random_primitive_float_rounding_mode_pair_gen_var_3::, ) } // -- PrimitiveSigned -- pub fn signed_gen() -> Generator { Generator::new( &exhaustive_signed_gen, &random_primitive_int_gen, &special_random_signed_gen, ) } // All signed `T`s which are not `T::MIN`. pub fn signed_gen_var_1() -> Generator { Generator::new( &exhaustive_signed_gen_var_1, &random_signed_gen_var_1, &special_random_signed_gen_var_1, ) } // All signed natural (non-negative) `T`s. pub fn signed_gen_var_2() -> Generator { Generator::new( &exhaustive_signed_gen_var_2, &random_signed_gen_var_2, &special_random_signed_gen_var_2, ) } // All signed `T`s that are neither 0 nor -1. pub fn signed_gen_var_3() -> Generator { Generator::new( &exhaustive_signed_gen_var_3, &random_signed_gen_var_3, &special_random_signed_gen_var_3, ) } // All negative signed `T`s. pub fn signed_gen_var_4() -> Generator { Generator::new( &exhaustive_signed_gen_var_4, &random_signed_gen_var_4, &special_random_signed_gen_var_4, ) } // All small signed `T`s. pub fn signed_gen_var_5() -> Generator { Generator::new_no_special(&exhaustive_signed_gen::, &random_signed_gen_var_5::) } // All nonzero signed `T`s. pub fn signed_gen_var_6() -> Generator { Generator::new( &exhaustive_signed_gen_var_5, &random_signed_gen_var_6, &special_random_signed_gen_var_5, ) } // All signeds `T` that are equal to a primitive float value of type `U`. pub fn signed_gen_var_7< T: PrimitiveSigned + RoundingFrom, U: ConvertibleFrom + PrimitiveFloat + RoundingFrom, >() -> Generator { Generator::new( &exhaustive_signed_gen_var_6::, &random_primitive_int_gen_var_1::, &special_random_primitive_int_gen_var_1::, ) } type G = Generator; // All signeds `S` that are not exactly equal to any value of a floating-point type `V`. // // Acceptable `(S, V)` pairs are those where `S::WIDTH` > `V::MANTISSA_WIDTH`. pub fn signed_gen_var_8< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: ConvertibleFrom + PrimitiveFloat, >() -> G { Generator::new( &exhaustive_signed_gen_var_7::, &random_signed_gen_var_7::, &special_random_signed_gen_var_6::, ) } // All signeds `S` that are exactly between two values of a floating-point type `V`. // // Acceptable `(S, V)` pairs are those where `S::WIDTH` > `V::MANTISSA_WIDTH`. pub fn signed_gen_var_9< U: PrimitiveUnsigned + WrappingFrom, S: TryFrom> + PrimitiveSigned + WrappingFrom, V: ConvertibleFrom + PrimitiveFloat + RoundingFrom, >() -> Generator { Generator::new( &exhaustive_signed_gen_var_8::, &random_signed_gen_var_8::, &special_random_signed_gen_var_7::, ) } // All signed `T`s whose square is also representable as a `T`. pub fn signed_gen_var_10< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator { Generator::new( &exhaustive_signed_gen_var_9::, &random_signed_gen_var_9::, &special_random_signed_gen_var_8::, ) } // All valid scientific exponents for the float type `T`. pub fn signed_gen_var_11() -> Generator { Generator::new( &exhaustive_signed_gen_var_10::, &random_signed_gen_var_10::, &special_random_signed_gen_var_9::, ) } // All signed `T`s that are neither 0 nor -1. pub fn signed_gen_var_12() -> Generator { Generator::new( &exhaustive_signed_gen_var_11, &random_signed_gen_var_11, &special_random_signed_gen_var_10, ) } // All odd positive signeds. pub fn signed_gen_var_13< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator { Generator::new( &exhaustive_signed_gen_var_12, &random_signed_gen_var_12, &special_random_signed_gen_var_11::, ) } // -- (PrimitiveSigned, PrimitiveSigned) -- pub fn signed_pair_gen() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen, &random_primitive_int_pair_gen_var_1, &special_random_signed_pair_gen, ) } // All pairs of signeds where either both values are non-negative or both are negative. pub fn signed_pair_gen_var_1() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_1, &random_signed_pair_gen_var_1, &special_random_signed_pair_gen_var_1, ) } // All pairs of signeds where the second value is small. pub fn signed_pair_gen_var_2() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_pair_gen_var_3, &random_primitive_int_signed_pair_gen_var_1, &special_random_signed_pair_gen_var_2, ) } // All pairs of signed `T` where the first is divisible by the second. pub fn signed_pair_gen_var_3() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_4, &random_signed_pair_gen_var_2, &special_random_signed_pair_gen_var_3, ) } // All pairs of signed `T` where the second `T` is nonzero and the pair is not `(T::MIN, -1)`. pub fn signed_pair_gen_var_4() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_5, &random_signed_pair_gen_var_3, &special_random_signed_pair_gen_var_4, ) } // All pairs of signed `T` where the second `T` is nonzero and the first is not divisible by the // second. pub fn signed_pair_gen_var_5() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_6, &random_signed_pair_gen_var_4, &special_random_signed_pair_gen_var_5, ) } // All pairs of signed `T` where the second `T` is nonzero. pub fn signed_pair_gen_var_6() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_7, &random_signed_pair_gen_var_5, &special_random_signed_pair_gen_var_6, ) } // All pairs of natural (non-negative) signeds. pub fn signed_pair_gen_var_7() -> Generator<(T, T)> { Generator::new( &exhaustive_signed_pair_gen_var_8, &random_signed_pair_gen_var_6, &special_random_signed_pair_gen_var_7, ) } // All pairs of signeds where the second element is positive and odd. pub fn signed_pair_gen_var_8< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(S, S)> { Generator::new( &exhaustive_signed_pair_gen_var_9, &random_signed_pair_gen_var_7, &special_random_signed_pair_gen_var_8::, ) } // All coprime pairs of signeds where both elements are odd and positive. pub fn signed_pair_gen_var_9< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >() -> Generator<(S, S)> { Generator::new( &exhaustive_signed_pair_gen_var_10, &random_signed_pair_gen_var_8, &special_random_signed_pair_gen_var_9::, ) } // All coprime pairs of signeds. pub fn signed_pair_gen_var_10< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >() -> Generator<(S, S)> { Generator::new( &exhaustive_signed_pair_gen_var_11, &random_signed_pair_gen_var_9, &special_random_signed_pair_gen_var_10, ) } // All `(T, U)` where `T` and `U` are signed and both the `T` and the `U` are small. pub fn signed_pair_gen_var_11() -> Generator<(T, U)> { Generator::new_no_special( &exhaustive_signed_pair_gen_var_12, &random_signed_pair_gen_var_10, ) } // All `(T, T)` where the `T`s are small, signed, and valid inputs to `T::binomial_coefficient`. pub fn signed_pair_gen_var_12() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_signed_pair_gen_var_13, &random_signed_pair_gen_var_11, ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn signed_triple_gen() -> Generator<(T, T, T)> { Generator::new( &exhaustive_signed_triple_gen, &random_primitive_int_triple_gen_var_4, &special_random_signed_triple_gen, ) } // All `(x, y, z): (T, T, T)` where `T` is signed and x + y * z does not overflow. pub fn signed_triple_gen_var_1() -> Generator<(T, T, T)> { Generator::new( &exhaustive_signed_triple_gen_var_1, &random_signed_triple_gen_var_1, &special_random_signed_triple_gen_var_1, ) } // All `(x, y, z): (T, T, T)` where `T` is signed and x - y * z does not overflow. pub fn signed_triple_gen_var_2() -> Generator<(T, T, T)> { Generator::new( &exhaustive_signed_triple_gen_var_2, &random_signed_triple_gen_var_2, &special_random_signed_triple_gen_var_2, ) } // All triple of signeds where either all values are non-negative or all are negative. pub fn signed_triple_gen_var_3() -> Generator<(T, T, T)> { Generator::new( &exhaustive_signed_triple_gen_var_3, &random_signed_triple_gen_var_3, &special_random_signed_triple_gen_var_3, ) } // All triples of signeds (x, y, m) where x is equal to y mod m. pub fn signed_triple_gen_var_4< U: PrimitiveUnsigned + WrappingInto + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >() -> Generator<(S, S, S)> { Generator::new( &exhaustive_signed_triple_gen_var_4, &random_signed_triple_gen_var_4::, &special_random_signed_triple_gen_var_4::, ) } // All triples of signeds (x, y, m) where x is not equal to y mod m. pub fn signed_triple_gen_var_5() -> Generator<(T, T, T)> { Generator::new( &exhaustive_signed_triple_gen_var_5, &random_primitive_int_triple_gen_var_1, &special_random_signed_triple_gen_var_5, ) } // All triples of signeds where the third element is positive and odd. pub fn signed_triple_gen_var_6< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(S, S, S)> { Generator::new( &exhaustive_signed_triple_gen_var_6, &random_signed_triple_gen_var_5, &special_random_signed_triple_gen_var_6::, ) } // All triples of signeds where the second and third elements are positive and odd. pub fn signed_triple_gen_var_7< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(S, S, S)> { Generator::new( &exhaustive_signed_triple_gen_var_7, &random_signed_triple_gen_var_6, &special_random_signed_triple_gen_var_7::, ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn signed_quadruple_gen() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_signed_quadruple_gen, &random_primitive_int_quadruple_gen_var_4, &special_random_signed_quadruple_gen, ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- // All `(T, T, T, U)` where `T` is signed, `U` is unsigned, and the `U` is small. pub fn signed_signed_signed_unsigned_quadruple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> Generator<(T, T, T, U)> { Generator::new( &exhaustive_signed_signed_signed_unsigned_quadruple_gen_var_1, &random_primitive_int_primitive_int_primitive_int_unsigned_quadruple_gen_var_1, &special_random_signed_signed_signed_unsigned_quadruple_gen_var_2, ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- // All triples `(T, T, u64)` (x, y, k) where `T` is signed and x is equal to y mod $2^k$. pub fn signed_signed_unsigned_triple_gen_var_1< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(S, S, u64)> { Generator::new( &exhaustive_signed_signed_unsigned_triple_gen_var_1::, &random_signed_signed_unsigned_triple_gen_var_1::, &special_random_signed_signed_unsigned_triple_gen_var_1::, ) } // All `(T, T, U)` where `T` is signed, `U` is unsigned, and the `U` is small. pub fn signed_signed_unsigned_triple_gen_var_2() -> Generator<(T, T, U)> { Generator::new( &exhaustive_signed_unsigned_unsigned_triple_gen_var_4, &random_primitive_int_primitive_int_unsigned_triple_gen_var_2, &special_random_signed_signed_unsigned_triple_gen_var_2, ) } // All triples `(T, T, u64)` (x, y, k) where `T` is unsigned and x is not equal to y mod $2^k$. pub fn signed_signed_unsigned_triple_gen_var_3() -> Generator<(T, T, u64)> { Generator::new( &exhaustive_signed_signed_unsigned_triple_gen_var_2, &random_primitive_int_primitive_int_unsigned_triple_gen_var_3, &special_random_signed_signed_unsigned_triple_gen_var_3, ) } // All `(T, U, V)` where `T` is signed, `U` is signed and small, and `V` is unsigned, small, and // positive. pub fn signed_signed_unsigned_triple_gen_var_4< T: PrimitiveSigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_signed_signed_unsigned_triple_gen_var_3, &random_signed_signed_unsigned_triple_gen_var_2, &special_random_signed_signed_unsigned_triple_gen_var_4, ) } // -- (PrimitiveSigned, PrimitiveSigned, RoundingMode) -- // All `(T, T, RoundingMode)` where `T` is signed and the triple is a valid input to `T::div_round`. pub fn signed_signed_rounding_mode_triple_gen_var_1() -> Generator<(T, T, RoundingMode)> { Generator::new( &exhaustive_signed_signed_rounding_mode_triple_gen_var_1, &random_signed_signed_rounding_mode_triple_gen_var_1, &special_random_signed_signed_rounding_mode_triple_gen_var_1, ) } // All `(T, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `T::round_to_multiple`. pub fn signed_signed_rounding_mode_triple_gen_var_2< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >() -> Generator<(S, S, RoundingMode)> { Generator::new( &exhaustive_signed_signed_rounding_mode_triple_gen_var_2, &random_signed_signed_rounding_mode_triple_gen_var_2, &special_random_signed_signed_rounding_mode_triple_gen_var_2, ) } // All `(T, U, RoundingMode)` where `T` and `U` are signed and the triple is a valid input to // `T::shr_round`. pub fn signed_signed_rounding_mode_triple_gen_var_3() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_signed_signed_rounding_mode_triple_gen_var_3, &random_primitive_int_signed_rounding_mode_triple_gen_var_1, &special_random_signed_signed_rounding_mode_triple_gen_var_3, ) } // All `(T, U, RoundingMode)` where `T` and `U` are signed and the triple is a valid input to // `T::shl_round`. pub fn signed_signed_rounding_mode_triple_gen_var_4() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_signed_signed_rounding_mode_triple_gen_var_4, &random_primitive_int_signed_rounding_mode_triple_gen_var_2, &special_random_signed_signed_rounding_mode_triple_gen_var_4, ) } // -- (PrimitiveSigned, PrimitiveUnsigned) -- pub fn signed_unsigned_pair_gen() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen, &random_primitive_int_pair_gen, &special_random_signed_unsigned_pair_gen, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, and the `U` is small. pub fn signed_unsigned_pair_gen_var_1() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_2, &random_primitive_int_unsigned_pair_gen_var_1, &special_random_signed_unsigned_pair_gen_var_1, ) } // All `(T, u64)`s where `T` is signed and the `u64` is smaller than `T::WIDTH`. pub fn signed_unsigned_pair_gen_var_2() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_4, &random_primitive_int_unsigned_pair_gen_var_2, &special_random_signed_unsigned_pair_gen_var_2, ) } // All `(T, u64)`s where `T` is signed and the either the `T` is negative or the `u64` is less than // `T::WIDTH`. pub fn signed_unsigned_pair_gen_var_3() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_3, &random_signed_unsigned_pair_gen_var_1, &special_random_signed_unsigned_pair_gen_var_3, ) } // All `(T, u64)`s where `T` is signed and the either the `T` is non-negative or the `u64` is less // than `T::WIDTH`. pub fn signed_unsigned_pair_gen_var_4() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_5, &random_signed_unsigned_pair_gen_var_2, &special_random_signed_unsigned_pair_gen_var_4, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, and the `U` is greater than 1 and no greater // than 36. pub fn signed_unsigned_pair_gen_var_5 + PrimitiveUnsigned>() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_6, &random_primitive_int_unsigned_pair_gen_var_5, &special_random_signed_unsigned_pair_gen_var_5, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, the `T` is non-negative, and the `U` is // small. pub fn signed_unsigned_pair_gen_var_6() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_7, &random_signed_unsigned_pair_gen_var_3, &special_random_signed_unsigned_pair_gen_var_6, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, the `T` is non-negative, and the `U` is // greater than 1 and no greater than 36. pub fn signed_unsigned_pair_gen_var_7 + PrimitiveUnsigned>() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_8, &random_signed_unsigned_pair_gen_var_4, &special_random_signed_unsigned_pair_gen_var_7, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, the `U` is small, and the `T` is not // divisible by 2 to the power of the `U`. pub fn signed_unsigned_pair_gen_var_8() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_9, &random_primitive_int_unsigned_pair_gen_var_6, &special_random_signed_unsigned_pair_gen_var_8, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, the `U` is small, and the `T` is divisible by // 2 to the power of the `U`. pub fn signed_unsigned_pair_gen_var_9() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_10, &random_primitive_int_unsigned_pair_gen_var_7, &special_random_signed_unsigned_pair_gen_var_9, ) } // All `(T, u64)`s where `T` is signed and the either the `T` is non-negative or the `u64` is less // than or equal to `T::WIDTH`. pub fn signed_unsigned_pair_gen_var_10() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_11, &random_signed_unsigned_pair_gen_var_5, &special_random_signed_unsigned_pair_gen_var_10, ) } // All `(S, u64)`s where `S` is signed and the either the `S` is non-positive and not `S::MIN`, or // the `u64` is less than `S::WIDTH`. pub fn signed_unsigned_pair_gen_var_11< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(S, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_12, &random_signed_unsigned_pair_gen_var_6, &special_random_signed_unsigned_pair_gen_var_11::, ) } // All `(T, u64)`s where `T` is signed and the `u64` is between 0 and `U::WIDTH`, inclusive. pub fn signed_unsigned_pair_gen_var_12() -> Generator<(T, u64)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_13::, &random_primitive_int_unsigned_pair_gen_var_8::, &special_random_unsigned_pair_gen_var_17::, ) } // All `(S, V)`s where `S` is signed, `V` is unsigned, `S` is between `-u64::MAX` and `u64::MAX`, // inclusive, and the `V` is positive. pub fn signed_unsigned_pair_gen_var_13< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >() -> Generator<(S, V)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_14, &random_signed_unsigned_pair_gen_var_7, &special_random_signed_unsigned_pair_gen_var_12::, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, and both `T` and `U` are small. pub fn signed_unsigned_pair_gen_var_14() -> Generator<(T, U)> { Generator::new_no_special( &exhaustive_signed_unsigned_pair_gen, &random_signed_unsigned_pair_gen_var_8, ) } // All `(T, u64)`s where `T` is signed, both the `T` and the `u64` are small, and the `T` raised to // the power of the `u64` does not overflow. pub fn signed_unsigned_pair_gen_var_15() -> Generator<(T, u64)> { Generator::new_no_special( &exhaustive_signed_unsigned_pair_gen_var_15, &random_signed_unsigned_pair_gen_var_9, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, the `T` is positive, and the `U` is small. pub fn signed_unsigned_pair_gen_var_16() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_int_unsigned_pair_gen_var_1, &random_signed_unsigned_pair_gen_var_10, &special_random_signed_unsigned_pair_gen_var_13, ) } // All `(S, V)`s where `S` is signed, `V` is unsigned, the `S` is negative and not `S::MIN`, and the // `V` is small. pub fn signed_unsigned_pair_gen_var_17< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >() -> Generator<(S, V)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_16, &random_signed_unsigned_pair_gen_var_11, &special_random_signed_unsigned_pair_gen_var_15::, ) } // All `(T, U)`s where `T` is signed, the `U` is unsigned, positive, and small, and either the `T` // is non-negative or the `U` is odd. pub fn signed_unsigned_pair_gen_var_18() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_17, &random_signed_unsigned_pair_gen_var_12, &special_random_signed_unsigned_pair_gen_var_14, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, both `T` and `U` are small, and the `U` is // positive. pub fn signed_unsigned_pair_gen_var_19() -> Generator<(T, U)> { Generator::new_no_special( &exhaustive_signed_unsigned_pair_gen_var_18, &random_signed_unsigned_pair_gen_var_13, ) } // All `(T, U)`s where `T` is signed, `U` is unsigned, and the `U` is small and positive. pub fn signed_unsigned_pair_gen_var_20() -> Generator<(T, U)> { Generator::new( &exhaustive_signed_unsigned_pair_gen_var_19, &random_primitive_int_unsigned_pair_gen_var_10, &special_random_signed_unsigned_pair_gen_var_16, ) } // -- (PrimitiveSigned, PrimitiveUnsigned, bool) -- // All (`T`, `u64`, and `bool`) where `T` is signed and either the `u64` is smaller than `T::WIDTH` // or the `bool` is equal to whether the `T` is negative. pub fn signed_unsigned_bool_triple_gen_var_1() -> Generator<(T, u64, bool)> { Generator::new( &exhaustive_signed_unsigned_bool_triple_gen_var_1, &random_primitive_int_unsigned_bool_triple_gen_var_2, &random_signed_unsigned_bool_triple_gen_var_1, ) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned) -- // All `(T, U, V)` where `T` is signed, `U` and `V` are unsigned, and the `V` is small. pub fn signed_unsigned_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_signed_unsigned_unsigned_triple_gen_var_1, &random_primitive_int_primitive_int_unsigned_triple_gen_var_2, &special_random_signed_unsigned_unsigned_triple_gen_var_1, ) } // All `(S, V, V)` where `S` is signed, `V` is unsigned, both `V`s are small, the first `V` is less // than or equal to the second, and if the `S` is negative, the difference between the two `V`s is // no greater than the width of `S`. pub fn signed_unsigned_unsigned_triple_gen_var_2< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >() -> Generator<(S, V, V)> { Generator::new( &exhaustive_signed_unsigned_unsigned_triple_gen_var_2, &random_signed_unsigned_unsigned_triple_gen_var_1, &special_random_signed_unsigned_unsigned_triple_gen_var_2::, ) } // All `(T, U, V)`s where `T` is signed, `U` and `V` are unsigned, the `U` is greater than 1 and no // greater than 36, and the `V` is small. pub fn signed_unsigned_unsigned_triple_gen_var_3< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_signed_unsigned_unsigned_triple_gen_var_3, &random_primitive_int_unsigned_unsigned_triple_gen_var_3, &special_random_signed_unsigned_unsigned_triple_gen_var_3, ) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- // All `(T, u64, u64, U)` where `T` is signed, `U` is unsigned, both `u64`s are small, and the four // values are valid arguments to `assign_bits`. pub fn signed_unsigned_unsigned_unsigned_quadruple_gen_var_1< T: PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >() -> Generator<(T, u64, u64, U)> { Generator::new( &exhaustive_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, &random_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, &special_random_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, ) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- // All `(T, u64, RoundingMode)` where `T` is signed and the triple is a valid input to // `T::round_to_multiple_of_power_of_2`. pub fn signed_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_1, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_1, &special_random_signed_unsigned_rounding_mode_triple_gen_var_1, ) } // All `(T, U, RoundingMode)` where `T` is signed, `U` is unsigned, and the triple is a valid input // to `T::shr_round`. pub fn signed_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_2, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_2, &special_random_signed_unsigned_rounding_mode_triple_gen_var_2, ) } // vars 3 through 6 are in malachite-float. // All `(T, U, RoundingMode)` where `T` is signed, `U` is unsigned, and the `U` is positive. pub fn signed_unsigned_rounding_mode_triple_gen_var_7() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_6, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_4, &special_random_signed_unsigned_rounding_mode_triple_gen_var_6, ) } // All `(T, U, RoundingMode)` where `T` is small and signed, `U` is small and unsigned, and the `U` // is positive. pub fn signed_unsigned_rounding_mode_triple_gen_var_8() -> Generator<(T, U, RoundingMode)> { Generator::new_no_special( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_6, &random_signed_unsigned_rounding_mode_triple_gen_var_1, ) } // -- (PrimitiveSigned, RoundingMode) -- pub fn signed_rounding_mode_pair_gen() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_signed_rounding_mode_pair_gen, &random_primitive_int_rounding_mode_pair_gen, &special_random_signed_rounding_mode_pair_gen, ) } // All `(T, RoundingMode)`s where `T` is signed and the `T` is nonzero. pub fn signed_rounding_mode_pair_gen_var_1() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_signed_rounding_mode_pair_gen_var_1, &random_signed_rounding_mode_pair_gen_var_1, &special_random_signed_rounding_mode_pair_gen_var_1, ) } // All `(T, RoundingMode)`s where `T` is signed and the `T` is not `T::MIN`. pub fn signed_rounding_mode_pair_gen_var_2() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_signed_rounding_mode_pair_gen_var_2, &random_signed_rounding_mode_pair_gen_var_2, &special_random_signed_rounding_mode_pair_gen_var_2, ) } // All `(T, RoundingMode)`s where `T` is signed and the `T` is nonzero and not `T::MIN`. pub fn signed_rounding_mode_pair_gen_var_3() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_signed_rounding_mode_pair_gen_var_3, &random_signed_rounding_mode_pair_gen_var_3, &special_random_signed_rounding_mode_pair_gen_var_3, ) } // All `(T, RoundingMode)` where `T` is signed, `U` is a primitive float type, and the pair is a // valid input to `U::rounding_from`. pub fn signed_rounding_mode_pair_gen_var_4< T: PrimitiveSigned, U: ConvertibleFrom + PrimitiveFloat, >() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_signed_rounding_mode_pair_gen_var_4::, &random_primitive_int_rounding_mode_pair_gen_var_1::, &special_random_signed_rounding_mode_pair_gen_var_4::, ) } // All `(T, RoundingMode)`s where `T` is small and signed. pub fn signed_rounding_mode_pair_gen_var_5() -> Generator<(T, RoundingMode)> { Generator::new_no_special( &exhaustive_signed_rounding_mode_pair_gen, &random_signed_rounding_mode_pair_gen_var_4, ) } // -- (PrimitiveSigned, ToSciOptions) -- pub fn signed_to_sci_options_pair_gen() -> Generator<(T, ToSciOptions)> { Generator::new( &exhaustive_signed_to_sci_options_pair_gen, &random_primitive_int_to_sci_options_pair_gen, &special_random_signed_to_sci_options_pair_gen, ) } // All `(T, ToSciOptions)` pairs where `T` is signed and the `T` can be formatted using the options. pub fn signed_to_sci_options_pair_gen_var_1() -> Generator<(T, ToSciOptions)> { Generator::new( &exhaustive_signed_to_sci_options_pair_gen_var_1, &random_primitive_int_to_sci_options_pair_gen_var_1, &special_random_signed_to_sci_options_pair_gen_var_1, ) } // -- (PrimitiveSigned, Vec) -- // All `(T, Vec)` where `T` is signed and the `Vec` has as many elements as // `u64::exact_from(n.to_bits_asc().len())` (which is not necessarily the same as the number of // significant bits). pub fn signed_bool_vec_pair_gen_var_1() -> Generator<(T, Vec)> { Generator::new( &exhaustive_signed_bool_vec_pair_gen_var_1, &random_signed_bool_vec_pair_gen_var_1, &special_random_signed_bool_vec_pair_gen_var_1, ) } // -- PrimitiveUnsigned -- pub fn unsigned_gen() -> Generator { Generator::new( &exhaustive_unsigned_gen, &random_primitive_int_gen, &special_random_unsigned_gen, ) } // All unsigned positive `T`s. pub fn unsigned_gen_var_1() -> Generator { Generator::new( &exhaustive_primitive_int_gen_var_1, &random_unsigned_gen_var_1, &special_random_unsigned_gen_var_1, ) } // All `u32`s smaller than `NUMBER_OF_CHARS`. pub fn unsigned_gen_var_2() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_1, &random_unsigned_gen_var_2, &special_random_unsigned_gen_var_2, ) } // All `u64`s between 1 and `T::WIDTH`, inclusive, where `T` is a primitive integer. pub fn unsigned_gen_var_3() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_2::, &random_unsigned_gen_var_3::, &special_random_unsigned_gen_var_3::, ) } // All `U`s greater than 1 and no greater than `T::MAX`. pub fn unsigned_gen_var_4>() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_4::, &random_unsigned_gen_var_4::, &special_random_unsigned_gen_var_4::, ) } // All small unsigned `T`s. pub fn unsigned_gen_var_5() -> Generator { Generator::new_no_special( &exhaustive_unsigned_gen::, &random_unsigned_gen_var_5::, ) } // All unsigned `T`s greater than or equal to 2. pub fn unsigned_gen_var_6() -> Generator { Generator::new( &exhaustive_primitive_int_gen_var_2::, &random_unsigned_gen_var_6::, &special_random_unsigned_gen_var_5::, ) } // All unsigned `T`s less than 36. pub fn unsigned_gen_var_7() -> Generator { Generator::new( &exhaustive_primitive_int_gen_var_3, &random_unsigned_gen_var_7, &special_random_unsigned_gen_var_6, ) } // All unsigned `T`s greater than or equal to 2 and less than or equal to 36. pub fn unsigned_gen_var_8() -> Generator { Generator::new( &exhaustive_primitive_int_gen_var_4, &random_unsigned_gen_var_8, &special_random_unsigned_gen_var_7, ) } // All `u64`s between 0 and `T::WIDTH`, inclusive, where `T` is a primitive integer. pub fn unsigned_gen_var_9() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_5::, &random_unsigned_gen_var_9::, &special_random_unsigned_gen_var_8::, ) } // All `u8`s that correspond to an ASCII alphanumeric character: '0' through '9', 'a' through 'z', // and 'A' through 'Z'. pub fn unsigned_gen_var_10() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_6, &random_unsigned_gen_var_10, &special_random_unsigned_gen_var_9, ) } // All small positive unsigned `T`s. pub fn unsigned_gen_var_11() -> Generator { Generator::new_no_special( &exhaustive_primitive_int_gen_var_1::, &random_unsigned_gen_var_11::, ) } // All unsigned `T`s whose highest bit is set. pub fn unsigned_gen_var_12() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_7, &random_unsigned_gen_var_12, &special_random_unsigned_gen_var_10, ) } // All unsigneds that are valid inputs into `T::from_ordered_representation` for a float type `T`. pub fn unsigned_gen_var_13() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_8::, &random_unsigned_gen_var_13::, &special_random_unsigned_gen_var_11::, ) } // All unsigned `T`s that are less than or equal to the largest representable power of 2. pub fn unsigned_gen_var_14() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_9, &random_unsigned_gen_var_14, &special_random_unsigned_gen_var_12, ) } // All `u64`s between 0 and `T::WIDTH - 1`, inclusive, where `T` is a primitive integer. pub fn unsigned_gen_var_15() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_10::, &random_unsigned_gen_var_15::, &special_random_unsigned_gen_var_13::, ) } // All `u64`s between 0 and `T::WIDTH - 2`, inclusive, where `T` is a primitive integer. pub fn unsigned_gen_var_16() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_11::, &random_unsigned_gen_var_16::, &special_random_unsigned_gen_var_14::, ) } // All unsigned `T`s whose two highest bits are not both zero. pub fn unsigned_gen_var_17() -> Generator { Generator::new( &exhaustive_primitive_int_gen_var_5, &random_unsigned_gen_var_17, &special_random_unsigned_gen_var_15, ) } // All unsigneds `T` that are equal to a primitive float value of type `U`. pub fn unsigned_gen_var_18< T: PrimitiveUnsigned + RoundingFrom, U: ConvertibleFrom + PrimitiveFloat + RoundingFrom, >() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_12::, &random_primitive_int_gen_var_1::, &special_random_primitive_int_gen_var_1::, ) } // All unsigneds `T` that are not exactly equal to any value of a floating-point type `U`. // // Acceptable `(T, U)` pairs are those where `T::WIDTH` > `U::MANTISSA_WIDTH`. pub fn unsigned_gen_var_19 + PrimitiveFloat>() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_13::, &random_unsigned_gen_var_18::, &special_random_unsigned_gen_var_16::, ) } // All unsigneds `T` that are exactly between two values of a floating-point type `U`. // // Acceptable `(T, U)` pairs are those where `T::WIDTH` > `U::MANTISSA_WIDTH`. pub fn unsigned_gen_var_20< T: TryFrom> + PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat + RoundingFrom, >() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_14::, &random_unsigned_gen_var_19::, &special_random_unsigned_gen_var_17::, ) } // All unsigned `T`s whose square is also representable as a `T`. pub fn unsigned_gen_var_21() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_15, &random_unsigned_gen_var_20, &special_random_unsigned_gen_var_18, ) } // All odd unsigned `T`s. pub fn unsigned_gen_var_22() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_22, &random_unsigned_gen_var_21, &special_random_unsigned_gen_var_19, ) } pub(crate) fn smallest_invalid_value Option>(f: F) -> u64 { for n in 0.. { if f(n).is_none() { return n; } } 0 } // All `u64`s whose factorial is representable as a `T`. pub fn unsigned_gen_var_23() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_23::, &random_unsigned_gen_var_22::, &special_random_unsigned_gen_var_20::, ) } // All `u64`s whose double factorial is representable as a `T`. pub fn unsigned_gen_var_24() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_24::, &random_unsigned_gen_var_23::, &special_random_unsigned_gen_var_21::, ) } // All `u64`s whose subfactorial is representable as a `T`. pub fn unsigned_gen_var_25() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_25::, &random_unsigned_gen_var_24::, &special_random_unsigned_gen_var_22::, ) } // All small unsigned `T`s greater than 4. pub fn unsigned_gen_var_26() -> Generator { Generator::new_no_special( &exhaustive_primitive_int_gen_var_6, &random_unsigned_gen_var_25, ) } // All `u64`s whose primorial is representable as a `T`. pub fn unsigned_gen_var_27() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_26::, &random_unsigned_gen_var_26::, &special_random_unsigned_gen_var_23::, ) } // All `u64`s `n` such that the product of the first `n` primes is representable as a `T`. pub fn unsigned_gen_var_28() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_27::, &random_unsigned_gen_var_27::, &special_random_unsigned_gen_var_24::, ) } // All unsigned prime `T`s. pub fn unsigned_gen_var_29() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_28, &random_unsigned_gen_var_28, &special_random_unsigned_gen_var_25, ) } // All `u64`s that are equal to valid scientific exponents for the float type `T`. pub fn unsigned_gen_var_30() -> Generator { Generator::new( &exhaustive_unsigned_gen_var_29::, &random_signed_gen_var_29::, &special_random_unsigned_gen_var_26::, ) } // -- (PrimitiveUnsigned, PrimitiveSigned) -- pub fn unsigned_signed_pair_gen() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_signed_pair_gen, &random_primitive_int_pair_gen, &special_random_unsigned_signed_pair_gen, ) } // All `(T, U)`s where `T` is unsigned, `U` is signed, and the `U` is small. pub fn unsigned_signed_pair_gen_var_1() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_signed_pair_gen_var_1, &random_primitive_int_signed_pair_gen_var_1, &special_random_unsigned_signed_pair_gen_var_1, ) } // Given a float type `T`, returns all `(T::UnsignedOfEqualWidth, i64)` that are valid inputs to // `T::from_integer_mantissa_and_exponent`. pub fn unsigned_signed_pair_gen_var_2() -> Generator<(u64, i64)> { Generator::new( &exhaustive_unsigned_signed_pair_gen_var_2::, &random_unsigned_signed_pair_gen_var_1::, &special_random_unsigned_signed_pair_gen_var_2::, ) } // -- (PrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned) -- // All `(T, U, u64)` where `T` is unsigned, `U` is signed, the `U` is small, the u64 is no greater // than `T::WIDTH`, and the `T`s is less than 2 to the power of the `u64`. pub fn unsigned_signed_unsigned_triple_gen_var_1() -> Generator<(T, U, u64)> { Generator::new( &exhaustive_unsigned_signed_unsigned_triple_gen_var_1, &random_unsigned_signed_unsigned_triple_gen_var_1, &special_random_unsigned_signed_unsigned_triple_gen_var_1, ) } // All `(T, S, T)` where `T` is unsigned, `S` is signed, the `S` is between `-u64::MAX` and // `u64::MAX`, inclusive, and the first element is less than the third. pub fn unsigned_signed_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() -> Generator<(T, S, T)> { Generator::new( &exhaustive_unsigned_signed_unsigned_triple_gen_var_2, &random_primitive_int_signed_primitive_int_triple_gen_var_1, &special_random_unsigned_signed_unsigned_triple_gen_var_2::, ) } // All `(T, U, T)` where `T` is unsigned, `U` is signed, and the first element is less than the // third. pub fn unsigned_signed_unsigned_triple_gen_var_3() -> Generator<(T, U, T)> { Generator::new( &exhaustive_unsigned_signed_unsigned_triple_gen_var_3, &random_primitive_int_triple_gen_var_3, &special_random_unsigned_signed_unsigned_triple_gen_var_3, ) } // All `(T, U, V)` where `T` is unsigned, `U` is signed and small, and `V` is unsigned, small, and // positive. pub fn unsigned_signed_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_unsigned_signed_unsigned_triple_gen_var_4, &random_unsigned_signed_unsigned_triple_gen_var_2, &special_random_unsigned_signed_unsigned_triple_gen_var_4, ) } // -- (PrimitiveUnsigned, PrimitiveSigned, RoundingMode) -- // All `(T, U, RoundingMode)` where `T` is unsigned, `U` is signed, and the triple is a valid input // to `T::shr_round`. pub fn unsigned_signed_rounding_mode_triple_gen_var_1() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_unsigned_signed_rounding_mode_triple_gen_var_1, &random_primitive_int_signed_rounding_mode_triple_gen_var_1, &special_random_unsigned_signed_rounding_mode_triple_gen_var_1, ) } // All `(T, U, RoundingMode)` where `T` is unsigned, `U` is signed, and the triple is a valid input // to `T::shl_round`. pub fn unsigned_signed_rounding_mode_triple_gen_var_2() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_unsigned_signed_rounding_mode_triple_gen_var_2, &random_primitive_int_signed_rounding_mode_triple_gen_var_2, &special_random_unsigned_signed_rounding_mode_triple_gen_var_2, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn unsigned_pair_gen() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen, &random_primitive_int_pair_gen, &special_random_unsigned_pair_gen, ) } // All `(u32, u32)`s where each `u32` is smaller than `NUMBER_OF_CHARS`. pub fn unsigned_pair_gen_var_1() -> Generator<(u32, u32)> { Generator::new( &exhaustive_unsigned_pair_gen_var_1, &random_unsigned_pair_gen_var_1, &special_random_unsigned_pair_gen_var_26, ) } // All `(T, U)`s where `T` and `U` are unsigned and the `U` is small. pub fn unsigned_pair_gen_var_2() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen_var_2, &random_primitive_int_unsigned_pair_gen_var_1, &special_random_unsigned_pair_gen_var_1, ) } // All `(T, u64)`s where `T` is unsigned and the `u64` is smaller than `T::WIDTH`. pub fn unsigned_pair_gen_var_3() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_3, &random_primitive_int_unsigned_pair_gen_var_2, &special_random_unsigned_pair_gen_var_2, ) } // All `(T, u64)`s where `T` is unsigned and the `u64` is between 1 and `U::WIDTH`, inclusive. pub fn unsigned_pair_gen_var_4() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_4::, &random_primitive_int_unsigned_pair_gen_var_3::, &special_random_unsigned_pair_gen_var_3::, ) } // All `(T, u64)`s where `T` is unsigned, the `T` is small, and the `u64` is between 1 and // `U::WIDTH`, inclusive. pub fn unsigned_pair_gen_var_5() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_4::, &random_unsigned_pair_gen_var_2::, &special_random_unsigned_pair_gen_var_27::, ) } // All `(T, U)`s where `T` and `U` are unsigned and the `U` is greater than 1 and no greater than // `T::MAX`. pub fn unsigned_pair_gen_var_6>() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen_var_5::, &random_primitive_int_unsigned_pair_gen_var_4::, &special_random_unsigned_pair_gen_var_4::, ) } // All `(T, T)` where `T` is unsigned and the first element is less than or equal to the second. pub fn unsigned_pair_gen_var_7() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_6, &random_primitive_int_pair_gen_var_2, &special_random_unsigned_pair_gen_var_5, ) } // All `(T, U)`s where `T` and `U` are unsigned and the `U` is greater than 1 and no greater than // 36. pub fn unsigned_pair_gen_var_8 + PrimitiveUnsigned>() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_primitive_int_pair_gen_var_2, &random_primitive_int_unsigned_pair_gen_var_5, &special_random_unsigned_pair_gen_var_6, ) } // All `(T, U)`s where `T` and `U` are unsigned, the `T` is small, and the `U` is greater than 1 and // no greater than 36. pub fn unsigned_pair_gen_var_9 + PrimitiveUnsigned>() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_primitive_int_pair_gen_var_2, &random_unsigned_pair_gen_var_3, &special_random_unsigned_pair_gen_var_28, ) } // All `(T, V)`s where `T` is unsigned, the `T` is between 2 and `max(T::MAX, U::MAX)`, inclusive, // and the `V` is small. pub fn unsigned_pair_gen_var_10< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> Generator<(T, V)> { Generator::new( &exhaustive_unsigned_pair_gen_var_7::, &random_unsigned_pair_gen_var_4::, &special_random_unsigned_pair_gen_var_29::, ) } // All pairs of unsigned `T` where the first is divisible by the second, and the second is positive. pub fn unsigned_pair_gen_var_11() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_8, &random_unsigned_pair_gen_var_5, &special_random_unsigned_pair_gen_var_7, ) } // All pairs of unsigned `T` and `U` where the `U` is positive. pub fn unsigned_pair_gen_var_12() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen_var_9, &random_unsigned_pair_gen_var_6, &special_random_unsigned_pair_gen_var_8, ) } // All pairs of unsigned `T` where the second `T` is positive and the first is not divisible by the // second. pub fn unsigned_pair_gen_var_13() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_10, &random_unsigned_pair_gen_var_7, &special_random_unsigned_pair_gen_var_9, ) } // All `(T, U)`s where `T` and `U` are unsigned, the `U` is small, and the `T` is not divisible by 2 // to the power of the `U`. pub fn unsigned_pair_gen_var_14() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen_var_11, &random_primitive_int_unsigned_pair_gen_var_6, &special_random_unsigned_pair_gen_var_10, ) } // All `(T, U)`s where `T` and `U` are unsigned, the `U` is small, and the `T` is divisible by 2 to // the power of the `U`. pub fn unsigned_pair_gen_var_15() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_12, &random_primitive_int_unsigned_pair_gen_var_7, &special_random_unsigned_pair_gen_var_11, ) } // All `(T, T)` where `T` is unsigned and the first element is smaller than the second. pub fn unsigned_pair_gen_var_16() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_13, &random_primitive_int_pair_gen_var_3, &special_random_unsigned_pair_gen_var_12, ) } // All `(T, u64)` where `T` is unsigned, the u64 is no greater than `T::WIDTH`, and the `T` is less // than 2 to the power of the `u64`. pub fn unsigned_pair_gen_var_17() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_14, &random_unsigned_pair_gen_var_8, &special_random_unsigned_pair_gen_var_13, ) } // All `(T, U)` where `T` and `U` are unsigned, the `T` and the `U` are small, and the `U` is // positive. pub fn unsigned_pair_gen_var_18() -> Generator<(T, U)> { Generator::new_no_special( &exhaustive_unsigned_primitive_int_gen_var_1, &random_unsigned_pair_gen_var_9, ) } // All `(T, U)`s where `T` and `U` are unsigned, the `T` is positive and small, and the `U` is // greater than 1 and no greater than 36. pub fn unsigned_pair_gen_var_19 + PrimitiveUnsigned>() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_int_pair_gen_var_1, &random_unsigned_pair_gen_var_10, &special_random_unsigned_pair_gen_var_30, ) } // All `(T, u64)`s where `T` is unsigned, and either the `T` is 0 or the `u64` is less than // `T::WIDTH`. pub fn unsigned_pair_gen_var_20() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_15, &random_unsigned_pair_gen_var_11, &special_random_unsigned_pair_gen_var_31, ) } // All `(T, U)`s where `T` and `U` are unsigned and positive and the `U` is small. pub fn unsigned_pair_gen_var_21() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_int_pair_gen_var_2, &random_unsigned_pair_gen_var_12, &special_random_unsigned_pair_gen_var_14, ) } // All pairs of unsigneds that each are valid inputs into `T::from_ordered_representation` for a // float type `T`. pub fn unsigned_pair_gen_var_22() -> Generator<(u64, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_16::, &random_unsigned_pair_gen_var_13::, &special_random_unsigned_pair_gen_var_32::, ) } // All `(T, u64)`s where `T` is unsigned and the `u64` is between 0 and `U::WIDTH`, inclusive. pub fn unsigned_pair_gen_var_23() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_17::, &random_primitive_int_unsigned_pair_gen_var_8::, &special_random_unsigned_pair_gen_var_15::, ) } // All pairs of unsigneds where the first element is positive and the second is greater than 1. pub fn unsigned_pair_gen_var_24() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_int_pair_gen_var_3, &random_unsigned_pair_gen_var_14, &special_random_unsigned_pair_gen_var_16, ) } // All pairs of unsigned `T` and `U` where the `U` is no greater than `u64::MAX` and `T` is // positive. pub fn unsigned_pair_gen_var_25() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_pair_gen_var_18, &random_unsigned_pair_gen_var_15, &special_random_unsigned_pair_gen_var_18, ) } // Given a float type `T`, all `(u64, u64)` that are valid raw mantissas and exponents of a value of // type `T`. pub fn unsigned_pair_gen_var_26() -> Generator<(u64, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_19::, &random_unsigned_pair_gen_var_16::, &special_random_unsigned_pair_gen_var_19::, ) } // All pairs of unsigneds of the same type. pub fn unsigned_pair_gen_var_27() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_20, &random_primitive_int_pair_gen_var_1, &special_random_unsigned_pair_gen_var_35, ) } // All `(T, U)` where `T` and `U` are unsigned and both the `T` and the `U` are small. pub fn unsigned_pair_gen_var_28() -> Generator<(T, U)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen, &random_unsigned_pair_gen_var_17, ) } // All `(T, u64)` where `T` is unsigned, both the `T` and the `u64` are small, and the `T` raised // the power of the `u64` does not overflow. pub fn unsigned_pair_gen_var_29() -> Generator<(T, u64)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_21, &random_unsigned_pair_gen_var_18, ) } // All `(T, u64)` where `T` is unsigned and the `u64` is no greater than the number of leading zeros // of the `T`. pub fn unsigned_pair_gen_var_30() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_22, &random_unsigned_pair_gen_var_19, &special_random_unsigned_pair_gen_var_20, ) } // All pairs of unsigned `T` where the two highest bits of the first `T` are not both zero. pub fn unsigned_pair_gen_var_31() -> Generator<(T, T)> { Generator::new( &exhaustive_primitive_int_unsigned_pair_gen_var_2::, &random_unsigned_primitive_int_pair_gen_var_1::, &special_random_unsigned_pair_gen_var_33::, ) } // All `(T, U)`s where `T` and `U` are unsigned and the `U` is small and positive. pub fn unsigned_pair_gen_var_32() -> Generator<(T, U)> { Generator::new( &exhaustive_unsigned_primitive_int_gen_var_3, &random_primitive_int_unsigned_pair_gen_var_9, &special_random_unsigned_pair_gen_var_21, ) } // All `(T, T)`s where `T` is unsigned. When the generation mode is random or special random, the // pairs are selected from a distribution such that their product is likely to be representable. pub fn unsigned_pair_gen_var_33() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_20, &random_unsigned_pair_gen_var_21, &special_random_unsigned_pair_gen_var_22, ) } // All `(T, T)`s where the LCM of the two numbers is representable. pub fn unsigned_pair_gen_var_34() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_23, &random_unsigned_pair_gen_var_22, &special_random_unsigned_pair_gen_var_23, ) } // All pairs of unsigneds where the highest bit of the first element is set. pub fn unsigned_pair_gen_var_35() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_24, &random_unsigned_pair_gen_var_23, &special_random_unsigned_pair_gen_var_24, ) } // All pairs of unsigneds that are valid inputs to `limbs_precompute_mod_mul_two_limbs`. pub fn unsigned_pair_gen_var_36() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_25, &random_unsigned_pair_gen_var_24, &special_random_unsigned_pair_gen_var_25, ) } // All `(T, U)`s where `T` and `U` are unsigned, the `T` is positive, and the `U` is small. pub fn unsigned_pair_gen_var_37() -> Generator<(T, U)> { Generator::new( &exhaustive_primitive_int_unsigned_pair_gen_var_1, &random_unsigned_pair_gen_var_25, &special_random_unsigned_pair_gen_var_34, ) } // All `(T, T)` where `T` is unsigned, both elements are nonzero, and the first element is smaller // than the second. pub fn unsigned_pair_gen_var_38() -> Generator<(T, T)> { Generator::new( &exhaustive_primitive_int_pair_gen_var_4, &random_unsigned_pair_gen_var_26, &special_random_unsigned_pair_gen_var_36, ) } // All `(T, u64)` where `T` is unsigned, the u64 is no greater than `T::WIDTH`, the `T` is positive, // and the `T` is less than 2 to the power of the `u64`. pub fn unsigned_pair_gen_var_39() -> Generator<(T, u64)> { Generator::new( &exhaustive_unsigned_pair_gen_var_26, &random_unsigned_pair_gen_var_27, &special_random_unsigned_pair_gen_var_37, ) } // All pairs of unsigneds where the second element is odd. pub fn unsigned_pair_gen_var_40() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_27, &random_unsigned_pair_gen_var_28, &special_random_unsigned_pair_gen_var_38, ) } // All coprime pairs of unsigneds where both elements are odd. pub fn unsigned_pair_gen_var_41() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_28, &random_unsigned_pair_gen_var_29, &special_random_unsigned_pair_gen_var_39, ) } // All coprime pairs of unsigneds of the same type. pub fn unsigned_pair_gen_var_42() -> Generator<(T, T)> { Generator::new( &exhaustive_unsigned_pair_gen_var_29, &random_unsigned_pair_gen_var_30, &special_random_unsigned_pair_gen_var_40, ) } // All pairs `u64`s that are valid inputs to `T::multifactorial`. pub fn unsigned_pair_gen_var_43() -> Generator<(u64, u64)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_30::, &random_unsigned_pair_gen_var_31::, ) } // All `(T, T)` where the `T`s are small, unsigned, and valid inputs to `T::binomial_coefficient`. pub fn unsigned_pair_gen_var_44() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_31, &random_unsigned_pair_gen_var_32, ) } // vars 45 through 49 are in malachite-nz // All pairs of unsigneds of the same type, where each value is greater than 1. pub fn unsigned_pair_gen_var_50() -> Generator<(T, T)> { Generator::new( &exhaustive_primitive_int_unsigned_pair_gen_var_3, &random_unsigned_pair_gen_var_38, &special_random_unsigned_pair_gen_var_41, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, bool) -- // All `(T, u64, `bool) where `T` is unsigned and either the `bool` is false or the `u64` is smaller // than `T::WIDTH`. pub fn unsigned_unsigned_bool_triple_gen_var_1() -> Generator<(T, u64, bool)> { Generator::new( &exhaustive_unsigned_unsigned_bool_triple_gen_var_1, &random_primitive_int_unsigned_bool_triple_gen_var_1, &special_random_unsigned_unsigned_bool_triple_gen_var_1, ) } // All `(T, U, bool)` where `T` and `U` are unsigned and the `U` is positive. pub fn unsigned_unsigned_bool_triple_gen_var_2() -> Generator<(T, U, bool)> { Generator::new( &exhaustive_unsigned_unsigned_bool_triple_gen_var_2, &random_primitive_int_unsigned_bool_triple_gen_var_3, &special_random_unsigned_unsigned_bool_triple_gen_var_2, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- // All `(x, y, z): (T, T, T)` where `T` is unsigned and x + y * z does not overflow. pub fn unsigned_triple_gen_var_1() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_1, &random_unsigned_triple_gen_var_1, &special_random_unsigned_triple_gen_var_1, ) } // All `(x, y, z): (T, T, T)` where `T` is unsigned and x - y * z does not overflow. pub fn unsigned_triple_gen_var_2() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_2, &random_unsigned_triple_gen_var_2, &special_random_unsigned_triple_gen_var_2, ) } // All `(T, u64, V)` where `T` is unsigned, the `u64` is between 1 and `U::WIDTH`, inclusive, and // `V` is unsigned and the `V` is small. pub fn unsigned_triple_gen_var_3() -> Generator<(T, u64, V)> { Generator::new( &exhaustive_unsigned_primitive_int_unsigned_triple_gen_var_3::, &random_primitive_int_unsigned_unsigned_triple_gen_var_1::, &special_random_unsigned_triple_gen_var_3::, ) } // All `(T, T, U)` where `T` and `U` are unsigned and the `U` is small. pub fn unsigned_triple_gen_var_4() -> Generator<(T, T, U)> { Generator::new( &exhaustive_unsigned_triple_gen_var_3, &random_primitive_int_primitive_int_unsigned_triple_gen_var_1, &special_random_unsigned_triple_gen_var_4, ) } // All `(T, U, U)` where `T` and `U` are unsigned, both `U`s are small, and the second `U` is less // than or equal to the third. pub fn unsigned_triple_gen_var_5() -> Generator<(T, U, U)> { Generator::new( &exhaustive_unsigned_triple_gen_var_4, &random_primitive_int_unsigned_unsigned_triple_gen_var_2, &special_random_unsigned_triple_gen_var_5, ) } // All `(T, U, V)`s where `T`, `U`, and `V` are unsigned, the `U` is greater than 1 and no greater // than 36, and the `V` is small. pub fn unsigned_triple_gen_var_6< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> Generator<(T, U, V)> { Generator::new( &exhaustive_unsigned_triple_gen_var_5, &random_primitive_int_unsigned_unsigned_triple_gen_var_3, &special_random_unsigned_triple_gen_var_6, ) } // All triples of unsigneds (x, y, m) where x is equal to y mod m. pub fn unsigned_triple_gen_var_7() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_6, &random_unsigned_triple_gen_var_3, &special_random_unsigned_triple_gen_var_7, ) } // All triples of unsigneds (x, y, m) where x is not equal to y mod m. pub fn unsigned_triple_gen_var_8() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_7, &random_primitive_int_triple_gen_var_1, &special_random_unsigned_triple_gen_var_8, ) } // All triples `(T, T, u64)` (x, y, k) where `T` is unsigned and x is equal to y mod $2^k$. pub fn unsigned_triple_gen_var_9() -> Generator<(T, T, u64)> { Generator::new( &exhaustive_unsigned_triple_gen_var_8, &random_unsigned_triple_gen_var_4, &special_random_unsigned_triple_gen_var_9, ) } // All triples `(T, T, u64)` (x, y, k) where `T` is unsigned and x is not equal to y mod $2^k$. pub fn unsigned_triple_gen_var_10() -> Generator<(T, T, u64)> { Generator::new( &exhaustive_unsigned_triple_gen_var_9, &random_primitive_int_primitive_int_unsigned_triple_gen_var_3, &special_random_unsigned_triple_gen_var_10, ) } // All `(T, T, u64)` where `T` is unsigned, the u64 is no greater than `T::WIDTH`, and both `T`s are // less than 2 to the power of the `u64`. pub fn unsigned_triple_gen_var_11() -> Generator<(T, T, u64)> { Generator::new( &exhaustive_unsigned_triple_gen_var_10, &random_unsigned_triple_gen_var_5, &special_random_unsigned_triple_gen_var_11, ) } // All `(T, T, T)` where `T` is unsigned and the first and second elements are less than the third. pub fn unsigned_triple_gen_var_12() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_11, &random_primitive_int_triple_gen_var_2, &special_random_unsigned_triple_gen_var_12, ) } // All `(T, U, U)` where `T` and `U` are unsigned and the `U`s are small. pub fn unsigned_triple_gen_var_13() -> Generator<(T, U, U)> { Generator::new( &exhaustive_unsigned_triple_gen_var_12, &random_primitive_int_unsigned_unsigned_triple_gen_var_4, &special_random_unsigned_triple_gen_var_13, ) } // All `(T, U, T)` where `T` and `U` are unsigned, the `U` is small, and the first element is less // than the third. pub fn unsigned_triple_gen_var_14() -> Generator<(T, U, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_13, &random_primitive_int_unsigned_primitive_int_triple_gen_var_1, &special_random_unsigned_triple_gen_var_14, ) } // All `(T, U, T)` where `T` and `U` are unsigned and the first element is less than the third. pub fn unsigned_triple_gen_var_15() -> Generator<(T, U, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_14, &random_primitive_int_triple_gen_var_3, &special_random_unsigned_triple_gen_var_15, ) } // All `(T, U, u64)` where `T` and `U` are unsigned, the u64 is no greater than `T::WIDTH`, and the // `T`s is less than 2 to the power of the `u64`. pub fn unsigned_triple_gen_var_16() -> Generator<(T, U, u64)> { Generator::new( &exhaustive_unsigned_triple_gen_var_15, &random_unsigned_primitive_int_unsigned_triple_gen_var_1, &special_random_unsigned_triple_gen_var_16, ) } // All `(T, U, u64)` where `T` and `U` are unsigned, the `U` is small, the u64 is no greater than // `T::WIDTH`, and the `T`s is less than 2 to the power of the `u64`. pub fn unsigned_triple_gen_var_17() -> Generator<(T, U, u64)> { Generator::new( &exhaustive_unsigned_triple_gen_var_15, &random_unsigned_triple_gen_var_6, &special_random_unsigned_triple_gen_var_17, ) } // All `(T, U, T)` where `T` and `U` are unsigned, the `U` is no larger than `u64::MAX`, and the // first element is less than the third. pub fn unsigned_triple_gen_var_18() -> Generator<(T, U, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_16, &random_primitive_int_unsigned_primitive_int_triple_gen_var_2, &special_random_unsigned_triple_gen_var_18, ) } // All triples of unsigneds of the same type. pub fn unsigned_triple_gen_var_19() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_17, &random_primitive_int_triple_gen_var_4, &special_random_unsigned_triple_gen_var_19, ) } // All `(T, U, U)` where `T` and `U` are unsigned, both `U`s are small, the `T` is positive, and the // first `U` is less than or equal to the second. pub fn unsigned_triple_gen_var_20() -> Generator<(T, U, U)> { Generator::new( &exhaustive_primitive_int_unsigned_unsigned_triple_gen_var_1, &random_unsigned_triple_gen_var_7, &special_random_unsigned_triple_gen_var_20, ) } // All triples of unsigneds where the second element is odd. pub fn unsigned_triple_gen_var_21() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_18, &random_unsigned_triple_gen_var_8, &special_random_unsigned_triple_gen_var_21, ) } // All triples of unsigneds where the third element is odd. pub fn unsigned_triple_gen_var_22() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_19, &random_unsigned_triple_gen_var_9, &special_random_unsigned_triple_gen_var_22, ) } // All triples of unsigneds where the second and third elements are odd. pub fn unsigned_triple_gen_var_23() -> Generator<(T, T, T)> { Generator::new( &exhaustive_unsigned_triple_gen_var_20, &random_unsigned_triple_gen_var_10, &special_random_unsigned_triple_gen_var_23, ) } // All `(T, T, U)`, where `T` and `U` are unsigned, and everything is small. pub fn unsigned_triple_gen_var_24() -> Generator<(T, T, U)> { Generator::new_no_special( &exhaustive_unsigned_triple_gen_var_21, &random_unsigned_triple_gen_var_11, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- // All `(T, u64, u64, U)` where `T` and `U` are unsigned, both `u64`s are small, and the four values // are valid arguments to `assign_bits`. pub fn unsigned_quadruple_gen_var_1() -> Generator<(T, u64, u64, U)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_1, &random_primitive_int_unsigned_unsigned_unsigned_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_1, ) } // All `(T, T, T, U)` where `T` and `U` are unsigned and the `U` is small. pub fn unsigned_quadruple_gen_var_2() -> Generator<(T, T, T, U)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_2, &random_primitive_int_primitive_int_primitive_int_unsigned_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_2, ) } // All `(T, T, T, u64)` where `T` is unsigned, the u64 is no greater than `T::WIDTH`, and all three // `T`s are less than 2 to the power of the `u64`. pub fn unsigned_quadruple_gen_var_3() -> Generator<(T, T, T, u64)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_3, &random_unsigned_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_3, ) } // All `(T, T, T, T)` where `T` is unsigned and the first three elements are each less than the // fourth. pub fn unsigned_quadruple_gen_var_4() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_4, &random_primitive_int_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_4, ) } // All `(T, T, T, T)` that are valid inputs to `limbs_mod_preinverted`. pub fn unsigned_quadruple_gen_var_5< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_5::, &random_unsigned_quadruple_gen_var_2::, &special_random_unsigned_quadruple_gen_var_5::, ) } // All `(T, T, U, T)` where `T` and `U` are unsigned and the first two elements are each less than // the fourth. pub fn unsigned_quadruple_gen_var_6() -> Generator<(T, T, U, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_6, &random_primitive_int_quadruple_gen_var_2, &special_random_unsigned_quadruple_gen_var_6, ) } // All `(T, U, U, T)` where `T` and `U` are unsigned and the first element is less than the fourth. pub fn unsigned_quadruple_gen_var_7() -> Generator<(T, U, U, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_7, &random_primitive_int_quadruple_gen_var_3, &special_random_unsigned_quadruple_gen_var_7, ) } // All `(T, T, U, u64)` where `T` and `U` are unsigned, the u64 is no greater than `T::WIDTH`, and // both `T`s are less than 2 to the power of the `u64`. pub fn unsigned_quadruple_gen_var_8() -> Generator<(T, T, U, u64)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_8, &random_unsigned_unsigned_primitive_int_unsigned_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_8, ) } // All `(T, U, U, u64)` where `T` and `U` are unsigned, the u64 is no greater than `T::WIDTH`, and // the `T`s is less than 2 to the power of the `u64`. pub fn unsigned_quadruple_gen_var_9() -> Generator<(T, U, U, u64)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_9, &random_unsigned_primitive_int_primitive_int_unsigned_quadruple_gen_var_1, &special_random_unsigned_quadruple_gen_var_9, ) } // All quadruples of unsigneds of the same type. pub fn unsigned_quadruple_gen_var_10() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_10, &random_primitive_int_quadruple_gen_var_4, &special_random_unsigned_quadruple_gen_var_10, ) } // All quadruples of unsigneds which, if grouped into two double-width unsigneds N and D (high // halves first) satisfy D >= 2^W, N >= D, and N / D < 2^W. pub fn unsigned_quadruple_gen_var_11() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_11, &random_primitive_int_quadruple_gen_var_5, &special_random_unsigned_quadruple_gen_var_11, ) } // All quadruples of unsigneds where the fourth element is odd. pub fn unsigned_quadruple_gen_var_12() -> Generator<(T, T, T, T)> { Generator::new( &exhaustive_unsigned_quadruple_gen_var_12, &random_unsigned_quadruple_gen_var_3, &special_random_unsigned_quadruple_gen_var_12, ) } // -- (PrimitiveUnsigned * 6) -- // All sextuples of unsigneds of the same type. pub fn unsigned_sextuple_gen_var_1() -> Generator<(T, T, T, T, T, T)> { Generator::new( &exhaustive_unsigned_sextuple_gen_var_1, &random_primitive_int_sextuple_gen_var_1, &special_random_unsigned_sextuple_gen_var_1, ) } // var 2 is in malachite-nz. // -- (PrimitiveUnsigned * 8) -- // All octuples of unsigneds of the same type. #[allow(clippy::type_complexity)] pub fn unsigned_octuple_gen_var_1() -> Generator<(T, T, T, T, T, T, T, T)> { Generator::new( &exhaustive_unsigned_octuple_gen_var_1, &random_primitive_int_octuple_gen_var_1, &special_random_unsigned_octuple_gen_var_1, ) } // -- (PrimitiveUnsigned * 9) -- // All nonuples of unsigneds of the same type. #[allow(clippy::type_complexity)] pub fn unsigned_nonuple_gen_var_1() -> Generator<(T, T, T, T, T, T, T, T, T)> { Generator::new( &exhaustive_unsigned_nonuple_gen_var_1, &random_primitive_int_nonuple_gen_var_1, &special_random_unsigned_nonuple_gen_var_1, ) } // -- (PrimitiveUnsigned * 12) -- // All duodecuples of unsigneds of the same type. #[allow(clippy::type_complexity)] pub fn unsigned_duodecuple_gen_var_1() -> Generator<(T, T, T, T, T, T, T, T, T, T, T, T)> { Generator::new( &exhaustive_unsigned_duodecuple_gen_var_1, &random_primitive_int_duodecuple_gen_var_1, &special_random_unsigned_duodecuple_gen_var_1, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // All `(T, T, RoundingMode)` that are valid inputs to `T::div_round`. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(T, T, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_1, &random_unsigned_unsigned_rounding_mode_triple_gen_var_1, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_1, ) } // All `(T, T, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `T::round_to_multiple`. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(T, T, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_3, &random_unsigned_unsigned_rounding_mode_triple_gen_var_2, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_2, ) } // All `(T, u64, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `T::round_to_multiple_of_power_of_2`. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_4, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_1, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(T, U, RoundingMode)` where `T` is unsigned, `U` is unsigned, and the triple is a valid // input to `T::shr_round`. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_5, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_2, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_4, ) } // vars 5 through 6 are in malachite-float. // All `(T, U, RoundingMode)` where `T` and `U` are unsigned and the `U` is positive. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_7< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(T, U, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_8, &random_primitive_int_unsigned_rounding_mode_triple_gen_var_4, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_7, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, Vec) -- // All `(T, u64, Vec)` where `T` is unsigned, the `u64` is between 1 and `U::WIDTH`, // inclusive, and the `Vec` has as many elements as the `T` has digits in base $2^\ell$, where // $\ell$ is the `u64`. pub fn unsigned_unsigned_bool_vec_triple_gen_var_1() -> Generator<(T, u64, Vec)> { Generator::new( &exhaustive_unsigned_unsigned_bool_vec_triple_gen_var_1::, &random_primitive_int_unsigned_bool_vec_triple_gen_var_1::, &special_random_unsigned_unsigned_bool_vec_triple_gen_var_1::, ) } // -- (PrimitiveUnsigned, RoundingMode) -- pub fn unsigned_rounding_mode_pair_gen() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_unsigned_rounding_mode_pair_gen, &random_primitive_int_rounding_mode_pair_gen, &special_random_unsigned_rounding_mode_pair_gen, ) } // All `(T, RoundingMode)`s where `T` is unsigned and the `T` is positive. pub fn unsigned_rounding_mode_pair_gen_var_1() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_primitive_int_rounding_mode_pair_gen_var_1, &random_unsigned_rounding_mode_pair_gen_var_1, &special_random_unsigned_rounding_mode_pair_gen_var_1, ) } // All `(T, RoundingMode)` where `T` is unsigned, `U` is a primitive float type, and the pair is a // valid input to `U::rounding_from`. pub fn unsigned_rounding_mode_pair_gen_var_2< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >() -> Generator<(T, RoundingMode)> { Generator::new( &exhaustive_unsigned_rounding_mode_pair_gen_var_1::, &random_primitive_int_rounding_mode_pair_gen_var_1::, &special_random_unsigned_rounding_mode_pair_gen_var_2::, ) } // All `(T, RoundingMode)`s where `T` is small, unsigned, and positive. pub fn unsigned_rounding_mode_pair_gen_var_3() -> Generator<(T, RoundingMode)> { Generator::new_no_special( &exhaustive_primitive_int_rounding_mode_pair_gen_var_1, &random_unsigned_rounding_mode_pair_gen_var_2, ) } // All `(T, RoundingMode)`s where `T` is small, unsigned, and positive, and the rounding mode is not // `Exact`. pub fn unsigned_rounding_mode_pair_gen_var_4() -> Generator<(T, RoundingMode)> { Generator::new_no_special( &exhaustive_primitive_int_rounding_mode_pair_gen_var_2, &random_unsigned_rounding_mode_pair_gen_var_3, ) } // All `(T, RoundingMode)`s where `T` is small and unsigned. pub fn unsigned_rounding_mode_pair_gen_var_5() -> Generator<(T, RoundingMode)> { Generator::new_no_special( &exhaustive_unsigned_rounding_mode_pair_gen, &random_unsigned_rounding_mode_pair_gen_var_4, ) } // -- (PrimitiveUnsigned, String) -- // All `(u8, String)` that, when passed to `Natural::from_string_base`, return a `Some`. pub fn unsigned_string_pair_gen_var_1() -> Generator<(u8, String)> { Generator::new_no_special( &exhaustive_unsigned_string_pair_gen_var_1, &random_unsigned_string_pair_gen_var_1, ) } // All `(u8, String)` that are valid inputs to `Natural::from_string_base` or // `Integer::from_string_base`, regardless of whether it returns `Some` or `None`. pub fn unsigned_string_pair_gen_var_2() -> Generator<(u8, String)> { Generator::new( &exhaustive_unsigned_string_pair_gen_var_2, &random_unsigned_string_pair_gen_var_2, &special_random_unsigned_string_pair_gen_var_1, ) } // All `(u8, String)` that, when passed to `Integer::from_string_base`, return a `Some`. pub fn unsigned_string_pair_gen_var_3() -> Generator<(u8, String)> { Generator::new_no_special( &exhaustive_unsigned_string_pair_gen_var_3, &random_unsigned_string_pair_gen_var_3, ) } // -- (PrimitiveUnsigned, ToSciOptions) -- pub fn unsigned_to_sci_options_pair_gen() -> Generator<(T, ToSciOptions)> { Generator::new( &exhaustive_unsigned_to_sci_options_pair_gen, &random_primitive_int_to_sci_options_pair_gen, &special_random_unsigned_to_sci_options_pair_gen, ) } type TSO = ToSciOptions; // All `(T, ToSciOptions)` pairs where `T` is unsigned and the `T` can be formatted using the // options. pub fn unsigned_to_sci_options_pair_gen_var_1() -> Generator<(T, TSO)> { Generator::new( &exhaustive_unsigned_to_sci_options_pair_gen_var_1, &random_primitive_int_to_sci_options_pair_gen_var_1, &special_random_unsigned_to_sci_options_pair_gen_var_1, ) } // -- (PrimitiveUnsigned, Vec) -- // All `(T, Vec)` where `T` is unsigned and the `Vec` has as many elements as the `T` has // significant bits. pub fn unsigned_bool_vec_pair_gen_var_1() -> Generator<(T, Vec)> { Generator::new( &exhaustive_unsigned_bool_vec_pair_gen_var_1, &random_unsigned_bool_vec_pair_gen_var_1, &special_random_unsigned_bool_vec_pair_gen_var_1, ) } // -- RationalSequence -- pub fn unsigned_rational_sequence_gen() -> Generator> { Generator::new( &exhaustive_unsigned_rational_sequence_gen, &random_primitive_int_rational_sequence_gen, &special_random_unsigned_rational_sequence_gen, ) } // -- (RationalSequence, PrimitiveUnsigned) -- // All `(RationalSequence, U)` pairs where `T` and `U` are unsigned and the `U` is small. pub fn unsigned_rational_sequence_unsigned_pair_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(RationalSequence, U)> { Generator::new( &exhaustive_unsigned_rational_sequence_unsigned_pair_gen_var_1, &random_primitive_int_rational_sequence_unsigned_pair_gen_var_1, &special_random_unsigned_rational_sequence_unsigned_pair_gen_var_1, ) } // All `(RationalSequence, usize)` pairs where `T` is unsigned and the `usize` is less than the // length of the `RationalSequence`. pub fn unsigned_rational_sequence_unsigned_pair_gen_var_2() -> Generator<(RationalSequence, usize)> { Generator::new( &exhaustive_unsigned_rational_sequence_unsigned_pair_gen_var_2, &random_primitive_int_rational_sequence_unsigned_pair_gen_var_2, &special_random_unsigned_rational_sequence_unsigned_pair_gen_var_2, ) } // -- (RationalSequence, RationalSequence) -- pub fn unsigned_rational_sequence_pair_gen() -> Generator<(RationalSequence, RationalSequence)> { Generator::new( &exhaustive_unsigned_rational_sequence_pair_gen, &random_primitive_int_rational_sequence_pair_gen, &special_random_unsigned_rational_sequence_pair_gen, ) } // -- RationalSequence * 3 -- pub fn unsigned_rational_sequence_triple_gen() -> Generator<( RationalSequence, RationalSequence, RationalSequence, )> { Generator::new( &exhaustive_unsigned_rational_sequence_triple_gen, &random_primitive_int_rational_sequence_triple_gen, &special_random_unsigned_rational_sequence_triple_gen, ) } // -- RoundingMode -- pub fn rounding_mode_gen() -> Generator { Generator::new_no_special(&exhaustive_rounding_mode_gen, &random_rounding_mode_gen) } // -- (RoundingMode, RoundingMode) -- pub fn rounding_mode_pair_gen() -> Generator<(RoundingMode, RoundingMode)> { Generator::new_no_special( &exhaustive_rounding_mode_pair_gen, &random_rounding_mode_pair_gen, ) } // -- (RoundingMode, RoundingMode, RoundingMode) -- pub fn rounding_mode_triple_gen() -> Generator<(RoundingMode, RoundingMode, RoundingMode)> { Generator::new_no_special( &exhaustive_rounding_mode_triple_gen, &random_rounding_mode_triple_gen, ) } // -- SciSizeOptions -- pub fn sci_size_options_gen() -> Generator { Generator::new_no_special( &exhaustive_sci_size_options_gen, &random_sci_size_options_gen, ) } // -- String -- pub fn string_gen() -> Generator { Generator::new( &exhaustive_string_gen, &random_string_gen, &special_random_string_gen, ) } // All ASCII `String`s. pub fn string_gen_var_1() -> Generator { Generator::new( &exhaustive_string_gen_var_1, &random_string_gen_var_1, &special_random_string_gen_var_1, ) } // All `String`s containing only characters that appear in the `String` representations of // `RoundingMode`s. pub fn string_gen_var_2() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_2, &random_string_gen_var_2) } // All nonempty `String`s containing only the characters '0' through '9'. pub fn string_gen_var_3() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_3, &random_string_gen_var_3) } // All nonempty `String`s containing only the characters '0' through '9', except for a possible '-' // in the first position. pub fn string_gen_var_4() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_4, &random_string_gen_var_4) } // All nonempty `String`s containing only the characters '0' and '1'. pub fn string_gen_var_5() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_5, &random_string_gen_var_5) } // All nonempty `String`s containing only the characters '0' through '7'. pub fn string_gen_var_6() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_6, &random_string_gen_var_6) } // All nonempty `String`s containing only the characters '0' through '9', 'a' through 'f', or 'A' // through 'F'. pub fn string_gen_var_7() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_7, &random_string_gen_var_7) } // All `String`s of the form `"\"0xD\""`, where D is a nonempty substring containing only the // characters '0' through '9', 'a' through 'f', or 'A' through 'F'. pub fn string_gen_var_8() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_8, &random_string_gen_var_8) } // All `String`s of the form `"\"0xD\""` or `"\"-0xD\""`, where D is a nonempty substring containing // only the characters '0' through '9', 'a' through 'f', or 'A' through 'F'. pub fn string_gen_var_9() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_9, &random_string_gen_var_9) } // All `String`s containing only characters that appear in the `String` representations of // `NiceFloat`s. pub fn string_gen_var_10() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_10, &random_string_gen_var_10) } // vars 11 through 12 are in malachite-q. // All `String`s containing only the characters `+-.0123456789Ee`. pub fn string_gen_var_13() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_13, &random_string_gen_var_13) } fn large_exponent(s: &str) -> bool { let mut i = 0; let mut expect_e = false; for c in s.chars().rev() { if expect_e { return c == 'e' || c == 'E'; } else if c.is_ascii_digit() { i += 1; } else if i <= 3 { return false; } else if c == 'e' || c == 'E' { return true; } else if c == '+' || c == '-' { expect_e = true; } } false } // All `Strings` that do not end in an 'e' or 'E' followed by an optional plus or minus sign and // more than three digits. pub fn string_gen_var_14() -> Generator { Generator::new( &exhaustive_string_gen_var_14, &random_string_gen_var_14, &special_random_string_gen_var_4, ) } // All `String`s containing only the characters `+-.0123456789Ee`, and that do not end in an 'e' or // 'E' followed by an optional plus or minus sign and more than three digits. pub fn string_gen_var_15() -> Generator { Generator::new_no_special(&exhaustive_string_gen_var_15, &random_string_gen_var_15) } // -- (String, FromSciStringOptions) -- pub fn string_from_sci_string_options_pair_gen() -> Generator<(String, FromSciStringOptions)> { Generator::new( &exhaustive_string_from_sci_string_options_pair_gen, &random_string_from_sci_string_options_pair_gen, &special_random_string_from_sci_string_options_pair_gen, ) } // All `(String, FromSciStringOptions)`, where the `String` only contains characters that occur in // valid inputs to `T::from_sci_string_options`, using the specified options. pub fn string_from_sci_string_options_pair_gen_var_1() -> Generator<(String, FromSciStringOptions)> { Generator::new_no_special( &exhaustive_string_from_sci_string_options_pair_gen_var_1, &random_string_from_sci_string_options_pair_gen_var_1, ) } // All `(String, FromSciStringOptions)`, where the string does not end in an 'e' or 'E' followed by // an optional plus or minus sign and more than three digits. pub fn string_from_sci_string_options_pair_gen_var_2() -> Generator<(String, FromSciStringOptions)> { Generator::new( &exhaustive_string_from_sci_string_options_pair_gen_var_2, &random_string_from_sci_string_options_pair_gen_var_2, &special_random_string_from_sci_string_options_pair_gen_var_1, ) } // All `(String, FromSciStringOptions)`, where the `String` only contains characters that occur in // valid inputs to `T::from_sci_string_options`, using the specified options, and the string does // not end in an 'e' or 'E' followed by an optional plus or minus sign and more than three digits. pub fn string_from_sci_string_options_pair_gen_var_3() -> Generator<(String, FromSciStringOptions)> { Generator::new_no_special( &exhaustive_string_from_sci_string_options_pair_gen_var_3, &random_string_from_sci_string_options_pair_gen_var_3, ) } // -- (String, PrimitiveUnsigned) -- // All `(String, u8)`s where the `u8` is between 2 and 36, inclusive, and the string does not end in // an 'e' or 'E' followed by an optional plus or minus sign and more than three digits. pub fn string_unsigned_pair_gen_var_1() -> Generator<(String, u8)> { Generator::new( &exhaustive_string_unsigned_pair_gen_var_1, &random_string_unsigned_pair_gen_var_1, &special_random_string_unsigned_pair_gen_var_1, ) } // All `(String, u8)`s where the `u8` is between 2 and 36, inclusive, the `String` only contains // characters that occur in valid inputs to `T::from_sci_string_options` with the specified base, // and the string does not end in an 'e' or 'E' followed by an optional plus or minus sign and more // than three digits. pub fn string_unsigned_pair_gen_var_2() -> Generator<(String, u8)> { Generator::new_no_special( &exhaustive_string_unsigned_pair_gen_var_2, &random_string_unsigned_pair_gen_var_2, ) } // -- (String, String) -- pub fn string_pair_gen() -> Generator<(String, String)> { Generator::new( &exhaustive_string_pair_gen, &random_string_pair_gen, &special_random_string_pair_gen, ) } // All pairs of ASCII `String`s. pub fn string_pair_gen_var_1() -> Generator<(String, String)> { Generator::new( &exhaustive_string_pair_gen_var_1, &random_string_pair_gen_var_1, &special_random_string_pair_gen_var_1, ) } // -- ToSciOptions -- pub fn to_sci_options_gen() -> Generator { Generator::new_no_special(&exhaustive_to_sci_options_gen, &random_to_sci_options_gen) } // -- (ToSciOptions, bool) -- pub fn to_sci_options_bool_pair_gen() -> Generator<(ToSciOptions, bool)> { Generator::new_no_special( &exhaustive_to_sci_options_bool_pair_gen, &random_to_sci_options_bool_pair_gen, ) } // -- (ToSciOptions, PrimitiveSigned) -- // All `(ToSciOptions, T)` where `T` is signed and the `T` is small and negative. pub fn to_sci_options_signed_pair_gen_var_1() -> Generator<(ToSciOptions, T)> { Generator::new_no_special( &exhaustive_to_sci_options_signed_pair_gen_var_1, &random_to_sci_options_signed_pair_gen_var_1, ) } // -- (ToSciOptions, PrimitiveUnsigned) -- // All `(ToSciOptions, T)` where `T` is unsigned and the `T` is between 2 and 36, inclusive. pub fn to_sci_options_unsigned_pair_gen_var_1() -> Generator<(TSO, T)> { Generator::new( &exhaustive_to_sci_options_unsigned_pair_gen_var_1, &random_to_sci_options_unsigned_pair_gen_var_1, &special_random_to_sci_options_unsigned_pair_gen_var_1, ) } // All `(ToSciOptions, T)` where `T` is unsigned and the `T` is small. pub fn to_sci_options_unsigned_pair_gen_var_2() -> Generator<(TSO, T)> { Generator::new_no_special( &exhaustive_to_sci_options_unsigned_pair_gen_var_2, &random_to_sci_options_unsigned_pair_gen_var_2, ) } // All `(ToSciOptions, T)` where `T` is unsigned and the `T` is small and positive. pub fn to_sci_options_unsigned_pair_gen_var_3() -> Generator<(TSO, T)> { Generator::new_no_special( &exhaustive_to_sci_options_primitive_int_pair_gen_var_1, &random_to_sci_options_unsigned_pair_gen_var_3, ) } // -- (ToSciOptions, RoundingMode) -- pub fn to_sci_options_rounding_mode_pair_gen() -> Generator<(ToSciOptions, RoundingMode)> { Generator::new_no_special( &exhaustive_to_sci_options_rounding_mode_pair_gen, &random_to_sci_options_rounding_mode_pair_gen, ) } // -- Vec -- pub fn bool_vec_gen() -> Generator> { Generator::new( &exhaustive_bool_vec_gen, &random_bool_vec_gen, &special_random_bool_vec_gen, ) } // All `Vec`s that could be the bits, in ascending order, of an unsigned value of type `T`. // The `Vec`s may be arbitrarily long. pub fn bool_vec_gen_var_1() -> Generator> { Generator::new( &exhaustive_bool_vec_gen_var_1::, &random_bool_vec_gen_var_1::, &special_random_bool_vec_gen_var_1::, ) } // All `Vec`s that could be the bits, in ascending order, of a signed value of type `T`. The // `Vec`s may be arbitrarily long. pub fn bool_vec_gen_var_2() -> Generator> { Generator::new( &exhaustive_bool_vec_gen_var_2::, &random_bool_vec_gen_var_2::, &special_random_bool_vec_gen_var_2::, ) } // All `Vec`s that could be the bits, in descending order, of an unsigned value of type `T`. // The `Vec`s may be arbitrarily long. pub fn bool_vec_gen_var_3() -> Generator> { Generator::new( &exhaustive_bool_vec_gen_var_3::, &random_bool_vec_gen_var_3::, &special_random_bool_vec_gen_var_3::, ) } // All `Vec`s that could be the bits, in descending order, of a signed value of type `T`. The // `Vec`s may be arbitrarily long. pub fn bool_vec_gen_var_4() -> Generator> { Generator::new( &exhaustive_bool_vec_gen_var_4::, &random_bool_vec_gen_var_4::, &special_random_bool_vec_gen_var_4::, ) } // All `Vec`s that contain at least one `true`. pub fn bool_vec_gen_var_5() -> Generator> { Generator::new( &exhaustive_bool_vec_gen_var_5, &random_bool_vec_gen_var_5, &special_random_bool_vec_gen_var_5, ) } // -- Vec -- pub fn unsigned_vec_gen() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen, &random_primitive_int_vec_gen, &special_random_unsigned_vec_gen, ) } // All nonempty `Vec`s of unsigneds whose last element is not zero. pub fn unsigned_vec_gen_var_1() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_1, &random_primitive_int_vec_gen_var_1, &special_random_unsigned_vec_gen_var_1, ) } // All `Vec`s of unsigneds that contain at least one nonzero value. pub fn unsigned_vec_gen_var_2() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_2, &random_primitive_int_vec_gen_var_2, &special_random_unsigned_vec_gen_var_2, ) } // All nonempty `Vec`s of unsigneds that do not end in a nonzero value. pub fn unsigned_vec_gen_var_3() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_3, &random_primitive_int_vec_gen_var_3, &special_random_unsigned_vec_gen_var_3, ) } // All nonempty `Vec`s of unsigneds. pub fn unsigned_vec_gen_var_4() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_4, &random_primitive_int_vec_gen_var_4, &special_random_unsigned_vec_gen_var_4, ) } // var 5 is in malachite-nz. // All `Vec`s of unsigneds with lengths at least 2. pub fn unsigned_vec_gen_var_6() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_6, &random_primitive_int_vec_gen_var_5, &special_random_unsigned_vec_gen_var_6, ) } // -- (Vec, PrimitiveUnsigned) -- pub fn unsigned_vec_unsigned_pair_gen() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen, &random_primitive_int_vec_primitive_int_pair_gen, &special_random_unsigned_vec_unsigned_pair_gen, ) } // All `(Vec, usize)` where `T` is unsigned and the `usize` is less than or equal to the length // of the `Vec`. pub fn unsigned_vec_unsigned_pair_gen_var_1() -> Generator<(Vec, usize)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_1, &random_primitive_int_vec_unsigned_pair_gen_var_1, &special_random_unsigned_vec_unsigned_pair_gen_var_3, ) } // All `(Vec, u64)` such that the flipped `(u64, Vec)` is a `Some`-returning input to // `from_power_of_2_digits_asc`, where the `Vec` is no longer than the number of digits of // `T::MAX` in the base 2 to the power of the `u64`. pub fn unsigned_vec_unsigned_pair_gen_var_2() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_2::, &random_unsigned_vec_unsigned_pair_gen_var_1::, &special_random_unsigned_vec_unsigned_pair_gen_var_1::, ) } // All `(Vec, u64)` such that the flipped `(u64, Vec)` is a `Some`-returning input to // `from_power_of_2_digits_desc`, where the `Vec` is no longer than the number of digits of // `T::MAX` in the base 2 to the power of the `u64`. pub fn unsigned_vec_unsigned_pair_gen_var_3() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_3::, &random_unsigned_vec_unsigned_pair_gen_var_2::, &special_random_unsigned_vec_unsigned_pair_gen_var_2::, ) } // var 4 is in malachite-nz // All `(Vec, U)` that are valid, `Some`-returning inputs to _from_digits_desc_basecase in // malachite-nz. pub fn unsigned_vec_unsigned_pair_gen_var_5< T: ExactFrom + PrimitiveUnsigned + WrappingFrom, U: PrimitiveUnsigned + SaturatingFrom + WrappingFrom, >() -> Generator<(Vec, U)> { Generator::new_no_special( &exhaustive_unsigned_vec_unsigned_pair_gen_var_5::, &random_unsigned_vec_unsigned_pair_gen_var_3::, ) } // All `(Vec, u64)` such that the flipped `(u64, Vec)` is a `Some`-returning input to // `from_power_of_2_digits_asc` or `from_power_of_2_digits_desc`, regardless of whether // the returned value is `Some` or `None`. pub fn unsigned_vec_unsigned_pair_gen_var_6() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_6::, &random_primitive_int_vec_unsigned_pair_gen_var_2::, &special_random_unsigned_vec_unsigned_pair_gen_var_5::, ) } // All `(T, Vec)` that are a valid input to `U::from_digits_desc`, where the `Vec` is no longer // than the number of digits of `U::MAX` in the base of the `T`. pub fn unsigned_vec_unsigned_pair_gen_var_7< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >() -> Generator<(Vec, T)> { Generator::new_no_special( &exhaustive_unsigned_vec_unsigned_pair_gen_var_7::, &random_unsigned_vec_unsigned_pair_gen_var_4::, ) } // All `(Vec, T)` that are is a valid input to `U::from_digits_asc`, where the `Vec` is no longer // than the number of digits of `U::MAX` in the base of the `T`. pub fn unsigned_vec_unsigned_pair_gen_var_8< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >() -> Generator<(Vec, T)> { Generator::new_no_special( &exhaustive_unsigned_vec_unsigned_pair_gen_var_8::, &random_unsigned_vec_unsigned_pair_gen_var_5::, ) } // All `(Vec, T)` such that the flipped `(u64, Vec)` is a `Some`-returning input to // `from_digits_asc` or `from_digits_desc`, regardless of whether the returned value is // `Some` or `None`. pub fn unsigned_vec_unsigned_pair_gen_var_9() -> Generator<(Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_9::, &random_unsigned_vec_unsigned_pair_gen_var_6::, &special_random_unsigned_vec_unsigned_pair_gen_var_6::, ) } // All `(Vec, u64)`, where the `u64` is between 1 and `T::WIDTH`, inclusive, and each `T` in the // `Vec` is less than 2 to the power of the `u64`. pub fn unsigned_vec_unsigned_pair_gen_var_10() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_10, &random_unsigned_vec_unsigned_pair_gen_var_7, &special_random_unsigned_vec_unsigned_pair_gen_var_7, ) } // All `(Vec, u64)`, where the `u64` is between 1 and `T::WIDTH`, inclusive. pub fn unsigned_vec_unsigned_pair_gen_var_11() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_11, &random_primitive_int_vec_unsigned_pair_gen_var_3, &special_random_unsigned_vec_unsigned_pair_gen_var_8, ) } // All `(Vec, U)` that are valid, inputs to from_digits_desc_basecase in malachite-nz, regardless // of whether they return `Some` or `None`. pub fn unsigned_vec_unsigned_pair_gen_var_12< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_12::, &random_primitive_int_vec_unsigned_pair_gen_var_4::, &special_random_unsigned_vec_unsigned_pair_gen_var_9::, ) } // All `(Vec, U)` where the last element of the `Vec` is nonzero. pub fn unsigned_vec_unsigned_pair_gen_var_13() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_1::, &random_primitive_int_vec_unsigned_pair_gen_var_5::, &special_random_unsigned_vec_unsigned_pair_gen_var_10::, ) } // All `(Vec, U)` where the last element of the `Vec` is nonzero and `U` is small and greater // than 2. pub fn unsigned_vec_unsigned_pair_gen_var_14() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_2::, &random_primitive_int_vec_unsigned_pair_gen_var_6::, &special_random_unsigned_vec_unsigned_pair_gen_var_11::, ) } // All `(Vec, U)` where `T` and `U` are unsigned and the `Vec` is nonempty. pub fn unsigned_vec_unsigned_pair_gen_var_15() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_13, &random_primitive_int_vec_primitive_int_pair_gen_var_1, &special_random_unsigned_vec_unsigned_pair_gen_var_11, ) } // All `(Vec, U)` where `T` and `U` are unsigned and the `U` is small. pub fn unsigned_vec_unsigned_pair_gen_var_16() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_14, &random_primitive_int_vec_unsigned_pair_gen_var_7, &special_random_unsigned_vec_unsigned_pair_gen_var_13, ) } // All `(Vec, U)` where `T` and `U` are unsigned and the U is less than `T::WIDTH` times the // length of the `Vec`. pub fn unsigned_vec_unsigned_pair_gen_var_17() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_15, &random_primitive_int_vec_unsigned_pair_gen_var_8, &special_random_unsigned_vec_unsigned_pair_gen_var_14, ) } // All `(Vec, U)` where `T` and `U` are unsigned and the `Vec` contains at least one nonzero // value. pub fn unsigned_vec_unsigned_pair_gen_var_18() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_16, &random_primitive_int_vec_primitive_int_pair_gen_var_2, &special_random_unsigned_vec_unsigned_pair_gen_var_15, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` contains at least one nonzero value, // and the `U` is positive. pub fn unsigned_vec_unsigned_pair_gen_var_19() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_3, &random_primitive_int_vec_unsigned_pair_gen_var_9, &special_random_unsigned_vec_unsigned_pair_gen_var_16, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` contains at least one nonzero value, // and the `U` is small. pub fn unsigned_vec_unsigned_pair_gen_var_20() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_17, &random_primitive_int_vec_unsigned_pair_gen_var_10, &special_random_unsigned_vec_unsigned_pair_gen_var_17, ) } // var 21 is in malachite-nz. // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` has at least 2 elements, and the `U` // is positive. pub fn unsigned_vec_unsigned_pair_gen_var_22() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_4, &random_primitive_int_vec_unsigned_pair_gen_var_11, &special_random_unsigned_vec_unsigned_pair_gen_var_19, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` has at least 2 elements and at least // one nonzero element, and the `U` is positive. pub fn unsigned_vec_unsigned_pair_gen_var_23() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_5, &random_primitive_int_vec_unsigned_pair_gen_var_12, &special_random_unsigned_vec_unsigned_pair_gen_var_20, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` has at least 2 elements, and the // highest bit of the `U` is set. pub fn unsigned_vec_unsigned_pair_gen_var_24() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_6, &random_primitive_int_vec_unsigned_pair_gen_var_13, &special_random_unsigned_vec_unsigned_pair_gen_var_21, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` has at least 2 elements, the `U` is // positive, and the highest bit of the `U` is not set. pub fn unsigned_vec_unsigned_pair_gen_var_25() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_7, &random_primitive_int_vec_unsigned_pair_gen_var_14, &special_random_unsigned_vec_unsigned_pair_gen_var_22, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` is nonempty, and the highest bit of // the `U` is set. pub fn unsigned_vec_unsigned_pair_gen_var_26() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_8, &random_primitive_int_vec_unsigned_pair_gen_var_15, &special_random_unsigned_vec_unsigned_pair_gen_var_23, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` is nonempty, the `U` is positive, and // the highest bit of the `U` is not set. pub fn unsigned_vec_unsigned_pair_gen_var_27() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_9, &random_primitive_int_vec_unsigned_pair_gen_var_16, &special_random_unsigned_vec_unsigned_pair_gen_var_24, ) } // All `(Vec, U)` where `T` and `U` are unsigned, the `Vec` is nonempty, the `U` is positive, and // the two highest bits of the `U` are not set. pub fn unsigned_vec_unsigned_pair_gen_var_28() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_10, &random_primitive_int_vec_unsigned_pair_gen_var_17, &special_random_unsigned_vec_unsigned_pair_gen_var_25, ) } // vars 29 through 30 are in malachite-nz. // All `(Vec, U)` where the last element of the `Vec` is nonzero and `U` is small and greater // than 1. pub fn unsigned_vec_unsigned_pair_gen_var_31() -> Generator<(Vec, U)> { Generator::new( &exhaustive_unsigned_vec_primitive_int_pair_gen_var_11::, &random_primitive_int_vec_unsigned_pair_gen_var_18::, &special_random_unsigned_vec_unsigned_pair_gen_var_28::, ) } // All `(Vec, u64)`, where `T` is unsigned, `U` is a primitive integer type, and the `u64` is // between 1 and `U::WIDTH` - 1, inclusive. pub fn unsigned_vec_unsigned_pair_gen_var_32() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_21::, &random_primitive_int_vec_unsigned_pair_gen_var_19::, &special_random_unsigned_vec_unsigned_pair_gen_var_29::, ) } // All `(Vec, u64)`, where `T` is unsigned, `U` is a primitive integer type, the `Vec` is // nonempty, and the `u64` is between 1 and `U::WIDTH` - 1, inclusive. pub fn unsigned_vec_unsigned_pair_gen_var_33() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_22::, &random_primitive_int_vec_unsigned_pair_gen_var_20::, &special_random_unsigned_vec_unsigned_pair_gen_var_30::, ) } // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- type T1 = Generator<(Vec, T, T)>; pub fn unsigned_vec_unsigned_unsigned_triple_gen() -> T1 { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen, &random_primitive_int_vec_primitive_int_primitive_int_triple_gen, &special_random_unsigned_vec_unsigned_unsigned_triple_gen, ) } // All `(Vec, U, V)` where `T`, `U`, and `V` are unsigned and the `U` is small. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >() -> Generator<(Vec, U, V)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_1, &random_primitive_int_vec_unsigned_primitive_int_triple_gen_var_1, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_1, ) } // All `(Vec, usize, usize)` where `T` is unsigned and the length of the `Vec` is at least the // product of the `usize`s. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_2() -> Generator<(Vec, usize, usize)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_2, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_1, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_2, ) } // All `(Vec, U, U)` where `T` and `U` are unsigned, both `U`s are small, and the first `U` is // less than or equal to the second. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, U, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_3, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_2, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_3, ) } // All `(Vec, U, U)` where `T` and `U` are unsigned, both `U`s are small, the `Vec` contains at // least one nonzero value, and the first `U` is less than or equal to the second. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, U, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_4, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_3, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_4, ) } // All `(Vec, T, T)` where `T` is unsigned, both `T`s are positive, the `Vec` contains at least // two elements, and its last element is nonzero. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_5() -> T1 { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_5, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_4, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_5, ) } // var 6 is in malachite-nz. // All `(Vec, T, T)` where `T` is unsigned, the second `T` is positive, the `Vec` contains at // least two elements, and its last element is nonzero. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_7() -> T1 { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_7, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_5, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_7, ) } // All `(Vec, T, U)` where `T` and `U` are unsigned, the `U` is small, the `Vec` contains at // least two elements, and its last element is nonzero. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_8< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, T, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_8, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_6, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_8, ) } // var 9 is in malachite-nz. // All `(Vec, T, T)`s where `T` is unsigned, the `Vec` is nonempty, and the first `T` is odd. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_10() -> Generator<(Vec, T, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_10, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_3, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_10, ) } // vars 11 through 12 are in malachite-nz. // All `(Vec, T, U)` where `T` and `U` are unsigned, the `U` is small, and the `Vec` ends with a // nonzero element. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_13< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, T, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_13, &random_primitive_int_vec_unsigned_unsigned_triple_gen_var_7, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_13, ) } // var 14 is in malachite-nz. // -- (Vec, PrimitiveUnsigned, RoundingMode) -- // All `(Vec, T, RoundingMode)` where `T` is unsigned, the `Vec` has at least two elements, and // the `Vec`s last element is nonzero. pub fn unsigned_vec_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(Vec, T, RoundingMode)> { Generator::new( &exhaustive_unsigned_vec_unsigned_rounding_mode_triple_gen_var_1, &random_primitive_int_vec_primitive_int_rounding_mode_triple_gen_var_1, &special_random_unsigned_vec_unsigned_rounding_mode_triple_gen_var_1, ) } // All `(Vec, U, RoundingMode)` where `T` and `U` are unsigned, the `U` is small, and the `Vec` // does not only contain zeros. pub fn unsigned_vec_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, U, RoundingMode)> { Generator::new( &exhaustive_unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, &random_primitive_int_vec_primitive_int_rounding_mode_triple_gen_var_2, &special_random_unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, ) } // -- (Vec, Vec) -- pub fn unsigned_vec_pair_gen() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen, &random_primitive_int_vec_pair_gen, &special_random_unsigned_vec_pair_gen, ) } // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s are nonempty, and the first `Vec` is at // least as long as the second. pub fn unsigned_vec_pair_gen_var_1() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_2, &random_primitive_int_vec_pair_gen_var_2, &special_random_unsigned_vec_pair_gen_var_2, ) } // All `(Vec, Vec)` where `T` is unsigned and both `Vec`s are nonempty. pub fn unsigned_vec_pair_gen_var_2() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_3, &random_primitive_int_vec_pair_gen_var_3, &special_random_unsigned_vec_pair_gen_var_3, ) } // All `(Vec, Vec)` that are valid inputs to `limbs_pow_low` in malachite-nz. pub fn unsigned_vec_pair_gen_var_3() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_4, &random_primitive_int_vec_pair_gen_var_4, &special_random_unsigned_vec_pair_gen_var_4, ) } // All `(Vec, Vec)` that are valid `(out, xs)` inputs to `limbs_sqrt_rem_helper`. pub fn unsigned_vec_pair_gen_var_4() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_5::, &random_unsigned_vec_pair_gen_var_1::, &special_random_unsigned_vec_pair_gen_var_5::, ) } // All `(Vec, Vec)` that are valid `(out, xs)` inputs to `limbs_sqrt_to_out`. pub fn unsigned_vec_pair_gen_var_5() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_6::, &random_unsigned_vec_pair_gen_var_2::, &special_random_unsigned_vec_pair_gen_var_6::, ) } // All `(Vec, Vec)` where `T` is unsigned and both `Vec`s have the same length. pub fn unsigned_vec_pair_gen_var_6() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_7, &random_primitive_int_vec_pair_gen_var_5, &special_random_unsigned_vec_pair_gen_var_7, ) } // All `(Vec, Vec)` where `T` is unsigned and neither `Vec` ends with zero. pub fn unsigned_vec_pair_gen_var_7() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_8, &random_primitive_int_vec_pair_gen_var_6, &special_random_unsigned_vec_pair_gen_var_8, ) } // All `(Vec, Vec)` where `T` is unsigned and each `Vec` contains at least one nonzero value. pub fn unsigned_vec_pair_gen_var_8() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_9, &random_primitive_int_vec_pair_gen_var_7, &special_random_unsigned_vec_pair_gen_var_9, ) } // All `(Vec, Vec)` where `T` is unsigned, each `Vec` contains at least one nonzero value, and // the first `Vec` is at least as long as the second. pub fn unsigned_vec_pair_gen_var_9() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_10, &random_primitive_int_vec_pair_gen_var_8, &special_random_unsigned_vec_pair_gen_var_10, ) } // var 10 is in malachite-nz. // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s have at least 2 elements, the first // `Vec` is at least as long as the second, and the last element of the second `Vec` is nonzero. pub fn unsigned_vec_pair_gen_var_11() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_12, &random_primitive_int_vec_pair_gen_var_10, &special_random_unsigned_vec_pair_gen_var_12, ) } // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s are nonempty, the first `Vec` is at // least as long as the second, and the first element of the second `Vec` is odd. pub fn unsigned_vec_pair_gen_var_12() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_13, &random_primitive_int_vec_pair_gen_var_11, &special_random_unsigned_vec_pair_gen_var_13, ) } // vars 13 through 14 are in malachite-nz. // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s are nonempty, the last elements of both // `Vec`s are nonzero, and the first `Vec` is at least as long as the second. pub fn unsigned_vec_pair_gen_var_15() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_16, &random_primitive_int_vec_pair_gen_var_12, &special_random_unsigned_vec_pair_gen_var_16, ) } // All `(Vec, Vec)` that are valid inputs to `limbs_div_mod` and `limbs_divisible_by`. pub fn unsigned_vec_pair_gen_var_16() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_17, &random_primitive_int_vec_pair_gen_var_13, &special_random_unsigned_vec_pair_gen_var_17, ) } // var 17 is in malachite-nz. // All `(Vec, Vec)` that are valid inputs to `limbs_mod_by_two_limb_normalized`. pub fn unsigned_vec_pair_gen_var_18() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_19, &random_unsigned_vec_pair_gen_var_5, &special_random_unsigned_vec_pair_gen_var_19, ) } // All `(Vec, Vec)` where `T` is unsigned and both `Vec`s end with a nonzero number. pub fn unsigned_vec_pair_gen_var_19() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_20, &random_primitive_int_vec_pair_gen_var_14, &special_random_unsigned_vec_pair_gen_var_20, ) } // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s have at least 2 elements, and the first // `Vec` is at least as long as the second. pub fn unsigned_vec_pair_gen_var_20() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_21, &random_primitive_int_vec_pair_gen_var_15, &special_random_unsigned_vec_pair_gen_var_21, ) } // vars 21 through 30 are malachite-nz. // All `(Vec, Vec)` where `T` is unsigned and the first `Vec` is at least as long as the // second. pub fn unsigned_vec_pair_gen_var_31() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_32, &random_primitive_int_vec_pair_gen_var_26, &special_random_unsigned_vec_pair_gen_var_32, ) } // All `(Vec, Vec)` where `T` is unsigned, both `Vec`s have the same length, at least one ends // with a nonzero value, and the first element of the second `Vec` is odd. pub fn unsigned_vec_pair_gen_var_32() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_33, &random_primitive_int_vec_pair_gen_var_27, &special_random_unsigned_vec_pair_gen_var_33, ) } // var 33 is in malachite-nz. // -- (Vec, Vec, bool) -- // All `(Vec, Vec, bool)` where `T` is unsigned and both `Vec`s have the same length. pub fn unsigned_vec_unsigned_vec_bool_triple_gen_var_1() -> Generator<(Vec, Vec, bool)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_bool_triple_gen_var_1, &random_primitive_int_vec_primitive_int_vec_bool_triple_gen_var_1, &special_random_unsigned_vec_unsigned_vec_bool_triple_gen_var_1, ) } // -- (Vec, Vec, PrimitiveUnsigned) -- // All `(Vec, Vec, T)` where `T` is unsigned and the first `Vec` is at least as long as the // second. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() -> Generator<(Vec, Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_1, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, ) } // vars 2 and 3 are in malachite-nz // All `(Vec, Vec, T)` where `T` is unsigned, the first `Vec` is at least as long as the // second, and the second is nonempty. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() -> Generator<(Vec, Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_2, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, ) } // All `(Vec, Vec, T)` where `T` is unsigned, the first `Vec` is at least as long as the // second, and the second contains at least one nonzero value. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() -> Generator<(Vec, Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_3, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, ) } // All `(Vec, Vec, U)` where `T` and `U` are unsigned, the `U` is positive, both `Vec`s // contain at least two elements, and their last elements are nonzero. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_4, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, ) } // vars 7 through 8 are in malachite-nz. // All `(Vec, Vec, U)` where `T` and `U` are unsigned, the `U` is small, and the last elements // of both `Vec`s are nonzero. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_5, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, ) } // All `(Vec, Vec, U)` where `T` and `U` are unsigned, the `U` is positive, and the last // elements of both `Vec`s are nonzero. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, Vec, U)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_6, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, ) } // All `(Vec, Vec, usize)` where `T` is unsigned, the first `Vec` is at least as long as the // second, and the `usize` is no greater than the length of the second `Vec`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11() -> Generator<(Vec, Vec, usize)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11, &random_primitive_int_vec_primitive_int_vec_unsigned_triple_gen_var_1, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11, ) } // All `(Vec, Vec, T)` where `T` is unsigned and the two `Vec`s have the same length. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() -> Generator<(Vec, Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_7, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, ) } // All `(Vec, Vec, T)` where `T` is unsigned and positive, the first `Vec` is at least as long // as the second, and the second has at least two elements. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13() -> Generator<(Vec, Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, ) } // vars 14 through 21 are in malachite-nz. // All `(Vec, Vec, u64)` where `T` is unsigned, `U` is a primitive integer type, the first // `Vec` is at least as long as the second, and the `u64` is between 1 and `U::WIDTH - 1`, // inclusive. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22::, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_8::, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22::, ) } // All `(Vec, Vec, u64)` where `T` is unsigned, `U` is a primitive integer type, the first // `Vec` is at least as long as the second, neither `Vec` is empty, and the `u64` is between 1 and // `U::WIDTH - 1`, inclusive. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::, &random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_9::, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::, ) } // All `(Vec, Vec, usize)` where `T` is unsigned, the `Vec`s have the same length, and the // `usize` is no greater than the length of either `Vec`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24() -> Generator<(Vec, Vec, usize)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24, &random_primitive_int_vec_primitive_int_vec_unsigned_triple_gen_var_2, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24, ) } // -- (Vec, Vec, Vec) -- // All `(Vec, Vec, Vec)` where `T` is unsigned, no `Vec` is empty, the second and third // `Vec`s have equal length, and the first is at least twice as long as the second. pub fn unsigned_vec_triple_gen_var_1() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_1, &random_primitive_int_vec_triple_gen_var_1, &special_random_unsigned_vec_triple_gen_var_1, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, no `Vec` is empty, the second is at least // as long as the third, and the length of the first is at least the sum of the lengths of the // second and the third. pub fn unsigned_vec_triple_gen_var_2() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_2, &random_primitive_int_vec_triple_gen_var_2, &special_random_unsigned_vec_triple_gen_var_2, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, no `Vec` is empty, and the length of the // first is at least the sum of the lengths of the second and the third. pub fn unsigned_vec_triple_gen_var_3() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_3, &random_primitive_int_vec_triple_gen_var_3, &special_random_unsigned_vec_triple_gen_var_3, ) } // vars 4 through 23 are in malachite-nz // All `(Vec, Vec, Vec)` where `T` is unsigned, no `Vec` is empty, the second and third // `Vec`s have equal length, and the first is at least as long as the second. pub fn unsigned_vec_triple_gen_var_24() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_24, &random_primitive_int_vec_triple_gen_var_24, &special_random_unsigned_vec_triple_gen_var_24, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, all `Vec`s have length at least 2, the // second and third `Vec`s have equal length, and the first is at least twice as long as the second. pub fn unsigned_vec_triple_gen_var_25() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_25, &random_primitive_int_vec_triple_gen_var_25, &special_random_unsigned_vec_triple_gen_var_25, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, all `Vec`s have length at least 2, the // second and third `Vec`s have equal length, and the first is at least as long as the second. pub fn unsigned_vec_triple_gen_var_26() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_26, &random_primitive_int_vec_triple_gen_var_26, &special_random_unsigned_vec_triple_gen_var_26, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned and all three `Vec`s have the same length, // which is at least 2. pub fn unsigned_vec_triple_gen_var_27() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_27, &random_primitive_int_vec_triple_gen_var_27, &special_random_unsigned_vec_triple_gen_var_27, ) } // All `(Vec, Vec, Vec)` that are valid `(out, rs, xs)` inputs to `limbs_sqrt_rem_to_out`. pub fn unsigned_vec_triple_gen_var_28() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_28::, &random_unsigned_vec_triple_gen_var_9::, &special_random_unsigned_vec_triple_gen_var_28::, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned and all three `Vec`s have the same length. pub fn unsigned_vec_triple_gen_var_29() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_29, &random_primitive_int_vec_triple_gen_var_28, &special_random_unsigned_vec_triple_gen_var_29, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned and no `Vec` ends with zero. pub fn unsigned_vec_triple_gen_var_30() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_30, &random_primitive_int_vec_triple_gen_var_29, &special_random_unsigned_vec_triple_gen_var_30, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, the second and third `Vec`s have equal // length, and the first is at least as long as the second. pub fn unsigned_vec_triple_gen_var_31() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_31, &random_primitive_int_vec_triple_gen_var_30, &special_random_unsigned_vec_triple_gen_var_31, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned and the first `Vec` is at least as long as // the second and at least as long as the third. pub fn unsigned_vec_triple_gen_var_32() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_32, &random_primitive_int_vec_triple_gen_var_31, &special_random_unsigned_vec_triple_gen_var_32, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, the second and third `Vec`s each contain at // least one nonzero element, and the first `Vec` is at least as long as the second. pub fn unsigned_vec_triple_gen_var_33() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_33, &random_primitive_int_vec_triple_gen_var_32, &special_random_unsigned_vec_triple_gen_var_33, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, the second and third `Vec`s each contain at // least one nonzero element, and the first `Vec` is at least as long as the second AND at least as // long as the third. pub fn unsigned_vec_triple_gen_var_34() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_34, &random_primitive_int_vec_triple_gen_var_33, &special_random_unsigned_vec_triple_gen_var_34, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, the second and third `Vec`s each contain at // least one nonzero element, and the first `Vec` is at least as long as the second OR at least as // long as the third. pub fn unsigned_vec_triple_gen_var_35() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_35, &random_primitive_int_vec_triple_gen_var_34, &special_random_unsigned_vec_triple_gen_var_35, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, each `Vec` contains at least two elements, // and the last element of each `Vec` is nonzero. pub fn unsigned_vec_triple_gen_var_36() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_36, &random_primitive_int_vec_triple_gen_var_35, &special_random_unsigned_vec_triple_gen_var_36, ) } // vars 37 through 38 are in malachite-nz // All `(Vec, Vec, Vec)` where `T` is unsigned and each `Vec` ends with a nonzero element. pub fn unsigned_vec_triple_gen_var_39() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_39, &random_primitive_int_vec_triple_gen_var_38, &special_random_unsigned_vec_triple_gen_var_39, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned and the first `Vec` is at least as long as // the second and the second is at least as long as the third. pub fn unsigned_vec_triple_gen_var_40() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_40, &random_primitive_int_vec_triple_gen_var_39, &special_random_unsigned_vec_triple_gen_var_40, ) } // All `(Vec, Vec, Vec)` where `T` is unsigned, every `Vec` ends with a nonzero element, // and the last `Vec` has length at least 2. pub fn unsigned_vec_triple_gen_var_41() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_41, &random_primitive_int_vec_triple_gen_var_40, &special_random_unsigned_vec_triple_gen_var_41, ) } // vars 42 through 49 are in malachite-nz. // All `(Vec, Vec, Vec)` where the first `Vec` is at least as long as the second, the third // is at least as long as twice the length of the second, and the second is nonempty and its most // significant bit is set. pub fn unsigned_vec_triple_gen_var_50() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_50, &random_primitive_int_vec_triple_gen_var_41, &special_random_unsigned_vec_triple_gen_var_50, ) } // All `(Vec, Vec, Vec)` where the first `Vec` is at least as long as the second, the third // is at least as long as twice the length of the second, and the second has length at least 5 and // its most significant bit is set. pub fn unsigned_vec_triple_gen_var_51() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_51, &random_primitive_int_vec_triple_gen_var_42, &special_random_unsigned_vec_triple_gen_var_51, ) } // All `(Vec, Vec, Vec)` that meet certain preconditions that enable comparing the // performance of divide-and-conquer division and Barrett division. pub fn unsigned_vec_triple_gen_var_52() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_52, &random_primitive_int_vec_triple_gen_var_43, &special_random_unsigned_vec_triple_gen_var_52, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_div_mod_by_two_limb_normalized`. pub fn unsigned_vec_triple_gen_var_53() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_53, &random_unsigned_vec_triple_gen_var_10, &special_random_unsigned_vec_triple_gen_var_53, ) } // vars 54 through 56 are in malachite-base. // All `(Vec, Vec, Vec)` where `T` is unsigned, the first `Vec` is at least as long as the // second and at least as long as the third, all `Vec`s have at least 2 elements, and the last // element of the third is nonzero. pub fn unsigned_vec_triple_gen_var_57() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_57, &random_primitive_int_vec_triple_gen_var_44, &special_random_unsigned_vec_triple_gen_var_57, ) } // var 58 is in malachite-nz. // All `(Vec, Vec, Vec)` `(xs, ys, zs)` where `T` is unsigned, `ys` and `zs` have at least // two elements, `xs` has at least `ys.len() + zs.len() - 1` elements, and each slice ends with a // nonzero value. pub fn unsigned_vec_triple_gen_var_59() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_59, &random_primitive_int_vec_triple_gen_var_46, &special_random_unsigned_vec_triple_gen_var_59, ) } // var 60 is in malachite-nz. // -- large types -- // TODO description pub fn large_type_gen_var_1() -> Generator<(Vec, Vec, T, T)> { Generator::new( &exhaustive_large_type_gen_var_1, &random_large_type_gen_var_1, &special_random_large_type_gen_var_1, ) } // All `(Vec, Vec, u64, bool)` that are valid inputs to `limbs_sqrt_helper`. pub fn large_type_gen_var_2() -> Generator<(Vec, Vec, u64, bool)> { Generator::new( &exhaustive_large_type_gen_var_2, &random_large_type_gen_var_2, &special_random_large_type_gen_var_2, ) } // All `(Vec, U, U, Vec)` where `T` and `U` are unsigned and the first `U` is less than the // second. pub fn large_type_gen_var_3() -> Generator<(Vec, U, U, Vec)> { Generator::new( &exhaustive_large_type_gen_var_3, &random_large_type_gen_var_3, &special_random_large_type_gen_var_3, ) } // All `(Vec, U, U, Vec)` where `T` and `U` are unsigned, the first `U` is less than the // second, and the first `Vec` contains at least one nonzero value. pub fn large_type_gen_var_4() -> Generator<(Vec, U, U, Vec)> { Generator::new( &exhaustive_large_type_gen_var_4, &random_large_type_gen_var_4, &special_random_large_type_gen_var_4, ) } // vars 5 through 8 are in malachite-nz // All `(Vec, Vec, Vec, bool)` where `T` is unsigned, the second and third `Vec`s have // equal length, and the first is at least as long as the second. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_9() -> Generator<(Vec, Vec, Vec, bool)> { Generator::new( &exhaustive_large_type_gen_var_9, &random_large_type_gen_var_9, &special_random_large_type_gen_var_9, ) } // vars 10 through 21 are in malachite-nz. type T2 = Generator<(RationalSequence, usize, T, T)>; // All `(RationalSequence, usize, T, T)` quadruples where `T` is unsigned and the `usize` is less // than the length of the `RationalSequence`. pub fn large_type_gen_var_22() -> T2 { Generator::new( &exhaustive_large_type_gen_var_22, &random_large_type_gen_var_22, &special_random_large_type_gen_var_22, ) } // vars 23 through 26 are in malachite-nz. // All (bool, Vec, bool, Vec) where `T` is unsigned and neither `Vec` ends with a zero. pub fn large_type_gen_var_27() -> Generator<(bool, Vec, bool, Vec)> { Generator::new( &exhaustive_large_type_gen_var_27, &random_large_type_gen_var_27, &special_random_large_type_gen_var_25, ) } // var 23 is in malachite-nz. pub mod common; pub mod exhaustive; pub mod random; pub mod special_random; ================================================ FILE: malachite-base/src/test_util/generators/random.rs ================================================ // Copyright © 2026 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 crate::bools::random::{RandomBools, random_bools}; use crate::chars::constants::NUMBER_OF_CHARS; use crate::chars::random::{ random_ascii_chars, random_char_inclusive_range, random_char_range, random_chars, }; use crate::iterators::with_special_value; use crate::num::arithmetic::traits::CoprimeWith; use crate::num::arithmetic::traits::{ ArithmeticCheckedShl, DivRound, Parity, PowerOf2, ShrRound, UnsignedAbs, }; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::options::random::{ RandomFromSciStringOptions, random_from_sci_string_options, random_sci_size_options, random_to_sci_options, }; use crate::num::conversion::string::options::{FromSciStringOptions, SciSizeOptions, ToSciOptions}; use crate::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, HasHalf, JoinHalves, RoundingFrom, SaturatingFrom, SplitInHalf, WrappingFrom, WrappingInto, }; use crate::num::factorization::traits::IsPrime; use crate::num::float::NiceFloat; use crate::num::logic::traits::{BitBlockAccess, LeadingZeros}; use crate::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, GeometricRandomSigneds, geometric_random_natural_signeds, geometric_random_negative_signeds, geometric_random_nonzero_signeds, geometric_random_positive_unsigneds, geometric_random_signed_inclusive_range, geometric_random_signed_range, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigned_range, geometric_random_unsigneds, }; use crate::num::random::{ RandomPrimitiveInts, RandomUnsignedBitChunks, RandomUnsignedInclusiveRange, RandomUnsignedRange, SpecialRandomNonzeroFiniteFloats, VariableRangeGenerator, random_highest_bit_set_unsigneds, random_natural_signeds, random_negative_signeds, random_nonzero_signeds, random_positive_signeds, random_positive_unsigneds, random_primitive_ints, random_signed_inclusive_range, random_signed_range, random_unsigned_bit_chunks, random_unsigned_inclusive_range, random_unsigned_range, random_unsigneds_less_than, special_random_finite_primitive_floats, special_random_nonzero_finite_primitive_floats, special_random_positive_finite_primitive_floats, special_random_primitive_float_inclusive_range, special_random_primitive_float_range, special_random_primitive_floats, }; use crate::random::{EXAMPLE_SEED, Seed}; use crate::rational_sequences::RationalSequence; use crate::rational_sequences::random::random_rational_sequences; use crate::rounding_modes::RoundingMode::{self, *}; use crate::rounding_modes::random::{RandomRoundingModes, random_rounding_modes}; use crate::slices::slice_test_zero; use crate::strings::random::{random_strings, random_strings_using_chars}; use crate::strings::strings_from_char_vecs; use crate::test_util::extra_variadic::{ Union3, random_duodecuples_from_single, random_octuples_from_single, random_quadruples_from_single, random_quadruples_xxxy, random_quadruples_xxyx, random_quadruples_xyxy, random_quadruples_xyyx, random_quadruples_xyyz, random_quadruples_xyzz, random_sextuples_from_single, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyx, random_triples_xyy, random_union3s, }; use crate::test_util::generators::common::{ GenConfig, It, reshape_1_2_to_3, reshape_2_1_to_3, reshape_2_2_to_4, reshape_3_1_to_4, }; use crate::test_util::generators::exhaustive::{ float_rounding_mode_filter_var_1, valid_digit_chars, }; use crate::test_util::generators::{ digits_valid, large_exponent, round_to_multiple_of_power_of_2_filter_map, round_to_multiple_signed_filter_map, round_to_multiple_unsigned_filter_map, signed_assign_bits_valid, smallest_invalid_value, unsigned_assign_bits_valid, }; use crate::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use crate::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use crate::test_util::num::float::PRIMITIVE_FLOAT_CHARS; use crate::test_util::rounding_modes::ROUNDING_MODE_CHARS; use crate::tuples::random::{random_ordered_unique_pairs, random_pairs, random_pairs_from_single}; use crate::unions::Union2; use crate::unions::random::random_union2s; use crate::vecs::random::{ random_vecs, random_vecs_fixed_length_from_single, random_vecs_length_inclusive_range, random_vecs_min_length, }; use crate::vecs::random_values_from_vec; use itertools::Itertools; use itertools::repeat_n; use std::cmp::{Ordering::*, max, min}; use std::collections::HashMap; use std::marker::PhantomData; use std::mem::swap; // -- bool -- pub fn random_bool_gen(_config: &GenConfig) -> It { Box::new(random_bools(EXAMPLE_SEED)) } // -- char -- pub fn random_char_gen(_config: &GenConfig) -> It { Box::new(random_chars(EXAMPLE_SEED)) } #[allow(unstable_name_collisions)] pub fn random_char_gen_var_1(_config: &GenConfig) -> It { Box::new(random_char_range(EXAMPLE_SEED, char::MIN, char::MAX)) } #[allow(unstable_name_collisions)] pub fn random_char_gen_var_2(_config: &GenConfig) -> It { Box::new(random_char_inclusive_range( EXAMPLE_SEED, '\u{1}', char::MAX, )) } // -- (char, char) -- pub fn random_char_pair_gen(_config: &GenConfig) -> It<(char, char)> { Box::new(random_pairs_from_single(random_chars(EXAMPLE_SEED))) } // -- FromSciStringOptions -- pub fn random_from_sci_string_options_gen(_config: &GenConfig) -> It { Box::new(random_from_sci_string_options(EXAMPLE_SEED)) } // -- (FromSciStringOptions, PrimitiveUnsigned) -- pub fn random_from_sci_string_options_unsigned_pair_gen_var_1( _config: &GenConfig, ) -> It<(FromSciStringOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &random_from_sci_string_options, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), )) } // -- (FromSciStringOptions, RoundingMode) -- pub fn random_from_sci_string_options_rounding_mode_pair_gen( _config: &GenConfig, ) -> It<(FromSciStringOptions, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &random_from_sci_string_options, &random_rounding_modes, )) } // -- PrimitiveFloat -- pub fn random_primitive_float_gen(config: &GenConfig) -> It { Box::new(special_random_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), )) } pub fn random_primitive_float_gen_var_1(config: &GenConfig) -> It { Box::new(special_random_primitive_float_range( EXAMPLE_SEED, T::NEGATIVE_ONE / T::TWO, T::INFINITY, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), )) } struct RandomPositiveNaturalFloats { exponents: GeometricRandomSignedRange, ranges: VariableRangeGenerator, phantom: PhantomData, } impl Iterator for RandomPositiveNaturalFloats { type Item = T; fn next(&mut self) -> Option { let exponent = self.exponents.next().unwrap(); let a = if exponent == 0 { 1 } else { u64::power_of_2(T::MANTISSA_WIDTH) }; let mantissa = self .ranges .next_in_range(a, u64::power_of_2(T::MANTISSA_WIDTH + 1)); Some(T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap()) } } fn random_positive_natural_floats( seed: Seed, mean_exponent_numerator: u64, mean_exponent_denominator: u64, ) -> RandomPositiveNaturalFloats { RandomPositiveNaturalFloats { exponents: geometric_random_signed_range( seed.fork("exponents"), 0, i64::power_of_2(T::EXPONENT_WIDTH - 1) - i64::wrapping_from(T::MANTISSA_WIDTH) - 1, mean_exponent_numerator, mean_exponent_denominator, ), ranges: VariableRangeGenerator::new(seed.fork("mantissas")), phantom: PhantomData, } } pub fn random_primitive_float_gen_var_2(config: &GenConfig) -> It { Box::new(with_special_value(EXAMPLE_SEED, T::ZERO, 1, 100, &|seed| { random_positive_natural_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) })) } pub fn random_primitive_float_gen_var_3(config: &GenConfig) -> It { Box::new( special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) .filter(|f| !f.is_integer()), ) } pub fn random_primitive_float_gen_var_4(config: &GenConfig) -> It { Box::new( special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, ) .map(|f| f.floor() - T::ONE / T::TWO), ) } pub fn random_primitive_float_gen_var_5(config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { with_special_value(seed, T::ZERO, 1, 100, &|seed_2| { random_positive_natural_floats( seed_2, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) }) }, &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn random_primitive_float_gen_var_6(config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_positive_finite_primitive_floats::( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) .filter(|f| !f.is_integer()) }, &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn random_primitive_float_gen_var_7(config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_float_inclusive_range::( seed, T::ONE, T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, ) .map(|f| f.floor() - T::ONE / T::TWO) }, &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn random_primitive_float_gen_var_8(config: &GenConfig) -> It { Box::new(special_random_finite_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), )) } pub fn random_primitive_float_gen_var_9(config: &GenConfig) -> It { Box::new( special_random_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|&f| !f.is_nan() && f != T::INFINITY), ) } pub fn random_primitive_float_gen_var_10(config: &GenConfig) -> It { Box::new( special_random_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|&f| !f.is_nan() && f != T::NEGATIVE_INFINITY), ) } pub fn random_primitive_float_gen_var_11(config: &GenConfig) -> It { Box::new( special_random_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|&f| !f.is_nan()), ) } pub fn random_primitive_float_gen_var_12(config: &GenConfig) -> It { Box::new(special_random_nonzero_finite_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), )) } pub fn random_primitive_float_gen_var_13, U: PrimitiveInt>( _config: &GenConfig, ) -> It { Box::new(random_primitive_ints::(EXAMPLE_SEED).map(|n| T::rounding_from(n, Down).0)) } pub fn random_primitive_float_gen_var_14< T: PrimitiveFloat, U: ConvertibleFrom + PrimitiveInt, >( config: &GenConfig, ) -> It { Box::new( special_random_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|&f| !U::convertible_from(f)), ) } pub fn random_primitive_float_gen_var_15< T: PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It { let limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, limit, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, ) .map(|f| f.floor() - T::ONE / T::TWO), ) } pub fn random_primitive_float_gen_var_16< T: PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >( config: &GenConfig, ) -> It { let min_limit = min( NiceFloat(-T::rounding_from(U::MIN, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; let max_limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( random_union2s( EXAMPLE_SEED, &|seed| { special_random_primitive_float_inclusive_range::( seed, T::ONE, max_limit, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, ) .map(|f| f.floor() - T::ONE / T::TWO) }, &|seed| { special_random_primitive_float_inclusive_range::( seed, T::ONE, min_limit, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, ) .map(|f| T::ONE / T::TWO - f.floor()) }, ) .map(Union2::unwrap), ) } pub fn random_primitive_float_gen_var_17(config: &GenConfig) -> It { Box::new(special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), )) } pub fn random_primitive_float_gen_var_18(config: &GenConfig) -> It { Box::new(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ZERO, T::power_of_2(T::MAX_EXPONENT), config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), 1, 100, )) } // -- (PrimitiveFloat, PrimitiveFloat) -- pub fn random_primitive_float_pair_gen(config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(special_random_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ))) } pub fn random_primitive_float_pair_gen_var_1(config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single( special_random_primitive_floats::( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|&f| !f.is_nan()), )) } // -- (PrimitiveFloat, PrimitiveFloat, PrimitiveFloat) -- pub fn random_primitive_float_triple_gen(config: &GenConfig) -> It<(T, T, T)> { Box::new(random_triples_from_single(special_random_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ))) } // -- (PrimitiveFloat, PrimitiveSigned) -- pub fn random_primitive_float_signed_pair_gen( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } pub fn random_primitive_float_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_positive_finite_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } pub fn random_primitive_float_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(T, i64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_float_range( seed, T::ONE, T::TWO, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_signed_inclusive_range( seed, T::MIN_EXPONENT, T::MAX_EXPONENT, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, ) .filter(|&(m, e)| m.precision() <= T::max_precision_for_sci_exponent(e)), ) } pub fn random_primitive_float_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(T, i64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_float_range( seed, T::ONE, T::TWO, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } pub fn random_primitive_float_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_primitive_float_signed_unsigned_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveUnsigned) -- pub fn random_primitive_float_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_positive_finite_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_float_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_float_range( seed, T::ONE, T::TWO, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_float_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_positive_finite_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_float_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- pub fn random_primitive_float_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { special_random_positive_finite_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, &random_rounding_modes, )) } pub fn random_primitive_float_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { special_random_primitive_float_range( seed, T::ONE, T::TWO, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, &random_rounding_modes, )) } // var 3 is in malachite-float. // -- (PrimitiveFloat, RoundingMode) -- pub fn random_primitive_float_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_finite_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &random_rounding_modes, ) .filter(float_rounding_mode_filter_var_1), ) } pub fn random_primitive_float_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_finite_primitive_floats::( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, &random_rounding_modes, ) .filter(|&(f, rm)| rm != Exact || f.is_integer()), ) } pub fn random_primitive_float_rounding_mode_pair_gen_var_3< T: PrimitiveFloat + RoundingFrom, U: ConvertibleFrom + PrimitiveInt, >( config: &GenConfig, ) -> It<(T, RoundingMode)> { let f_min = T::rounding_from(U::MIN, Down).0; let f_max = T::rounding_from(U::MAX, Down).0; Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_primitive_floats::( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .filter(|f| !f.is_nan()) }, &random_rounding_modes, ) .filter(move |&(f, rm)| match rm { Up => f >= f_min && f <= f_max, Ceiling => f <= f_max, Floor => f >= f_min, Down | Nearest => true, Exact => U::convertible_from(f), }), ) } // -- PrimitiveInt -- pub fn random_primitive_int_gen(_config: &GenConfig) -> It { Box::new(random_primitive_ints(EXAMPLE_SEED)) } pub fn random_primitive_int_gen_var_1< T: PrimitiveInt + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >( config: &GenConfig, ) -> It { Box::new( special_random_primitive_float_range( EXAMPLE_SEED, U::rounding_from(T::MIN, Down).0, U::rounding_from(T::MAX, Down).0, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .map(|f| T::rounding_from(f, Down).0), ) } // -- (PrimitiveInt, PrimitiveInt) -- pub fn random_primitive_int_pair_gen( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &random_primitive_ints, )) } pub fn random_primitive_int_pair_gen_var_1(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } // TODO make better pub fn random_primitive_int_pair_gen_var_2(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs_from_single(random_primitive_ints(EXAMPLE_SEED)) .map(|(x, y)| if x <= y { (x, y) } else { (y, x) }), ) } pub fn random_primitive_int_pair_gen_var_3(_config: &GenConfig) -> It<(T, T)> { Box::new(random_ordered_unique_pairs(random_primitive_ints::( EXAMPLE_SEED, ))) } // -- (PrimitiveInt, PrimitiveInt, PrimitiveInt) -- pub fn random_primitive_int_triple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints::(EXAMPLE_SEED)) .filter(|&(x, y, m)| !x.eq_mod(y, m)), ) } // Returns (highest, second-highest) pub fn get_two_highest(xs: &[T]) -> (&T, &T) { assert!(xs.len() > 1); let (mut hi, mut next_hi) = (&xs[0], &xs[1]); if hi < next_hi { swap(&mut hi, &mut next_hi); } for x in &xs[2..] { if x > next_hi { if x > hi { hi = x; next_hi = hi; } else { next_hi = x; } } } (hi, next_hi) } pub fn random_primitive_int_triple_gen_var_2( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints::(EXAMPLE_SEED)).filter_map( |(x, y, z)| { let ranking = [(x, 0), (y, 1), (z, 2)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, x), 1 => (x, z, y), _ => (x, y, z), }) } }, ), ) } pub fn random_primitive_int_triple_gen_var_3( _config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx(EXAMPLE_SEED, &random_primitive_ints, &random_primitive_ints) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn random_primitive_int_triple_gen_var_4( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } // -- (PrimitiveInt, PrimitiveInt, PrimitiveInt, PrimitiveInt) -- pub fn random_primitive_int_quadruple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_quadruples_from_single(random_primitive_ints::(EXAMPLE_SEED)).filter_map( |(x, y, z, w)| { let ranking = [(x, 0), (y, 1), (z, 2), (w, 3)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, w, x), 1 => (x, z, w, y), 2 => (x, y, w, z), _ => (x, y, z, w), }) } }, ), ) } pub fn random_primitive_int_quadruple_gen_var_2( _config: &GenConfig, ) -> It<(T, T, U, T)> { Box::new( random_quadruples_xxyx( EXAMPLE_SEED, &random_primitive_ints::, &random_primitive_ints::, ) .filter_map(|(x, y, z, w)| { let ranking = [(x, 0), (y, 1), (w, 2)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, w, z, x), 1 => (x, w, z, y), _ => (x, y, z, w), }) } }), ) } pub fn random_primitive_int_quadruple_gen_var_3( _config: &GenConfig, ) -> It<(T, U, U, T)> { Box::new( random_quadruples_xyyx( EXAMPLE_SEED, &random_primitive_ints::, &random_primitive_ints::, ) .filter_map(|(x, y, z, w)| match x.cmp(&w) { Equal => None, Less => Some((x, y, z, w)), Greater => Some((w, y, z, x)), }), ) } pub fn random_primitive_int_quadruple_gen_var_4( _config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new(random_quadruples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } pub fn random_primitive_int_quadruple_gen_var_5( _config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_quadruples_from_single(random_primitive_ints(EXAMPLE_SEED)).filter( |&(n1, n0, d1, d0)| { // conditions: D >= 2^W, N >= D, and N / D < 2^W d1 != T::ZERO && (n1 > d1 || n1 == d1 && n0 >= d0) }, ), ) } // -- (PrimitiveInt * 6) -- pub fn random_primitive_int_sextuple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T, T, T, T)> { Box::new(random_sextuples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } // -- (PrimitiveInt * 8) -- #[allow(clippy::type_complexity)] pub fn random_primitive_int_octuple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T)> { Box::new(random_octuples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } // -- (PrimitiveInt * 9) -- #[allow(clippy::type_complexity)] pub fn random_primitive_int_nonuple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T, T)> { Box::new( random_triples_from_single(random_triples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) .map(|((a, b, c), (d, e, f), (g, h, i))| (a, b, c, d, e, f, g, h, i)), ) } // -- (PrimitiveInt * 12) -- #[allow(clippy::type_complexity)] pub fn random_primitive_int_duodecuple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T, T, T, T, T)> { Box::new(random_duodecuples_from_single(random_primitive_ints( EXAMPLE_SEED, ))) } // -- (PrimitiveInt, PrimitiveInt, PrimitiveUnsigned) -- pub fn random_primitive_int_primitive_int_unsigned_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, T, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_primitive_int_unsigned_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveInt, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_primitive_int_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new( random_triples_xxy(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .filter(|&(x, y, pow)| !x.eq_mod_power_of_2(y, pow)), ) } // -- (PrimitiveInt, PrimitiveInt, PrimitiveInt, PrimitiveUnsigned) -- pub fn random_primitive_int_primitive_int_primitive_int_unsigned_quadruple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, T, T, U)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveInt, PrimitiveSigned) -- pub fn random_primitive_int_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } // -- (PrimitiveInt, PrimitiveSigned, PrimitiveInt) -- pub fn random_primitive_int_signed_primitive_int_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveSigned, >( _config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx(EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_signed_inclusive_range( seed, if U::WIDTH <= u64::WIDTH { U::MIN } else { -U::exact_from(u64::MAX) }, U::saturating_from(u64::MAX), ) }) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } // -- (PrimitiveInt, PrimitiveSigned, RoundingMode) -- pub fn random_primitive_int_signed_rounding_mode_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { rm != Exact || pow <= U::ZERO || x.divisible_by_power_of_2(pow.exact_into()) }), ) } pub fn random_primitive_int_signed_rounding_mode_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { let pow: i64 = pow.exact_into(); rm != Exact || pow >= 0 || x.divisible_by_power_of_2(pow.unsigned_abs()) }), ) } // -- (PrimitiveInt, PrimitiveUnsigned) -- pub fn random_primitive_int_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_unsigned_pair_gen_var_2( _config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigneds_less_than(seed, T::WIDTH), )) } pub fn random_primitive_int_unsigned_pair_gen_var_3( _config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, 1, U::WIDTH), )) } pub fn random_primitive_int_unsigned_pair_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned + SaturatingFrom, >( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::saturating_from(T::MAX)), )) } pub fn random_primitive_int_unsigned_pair_gen_var_5< T: PrimitiveInt, U: ExactFrom + PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::exact_from(36u8)), )) } pub fn random_primitive_int_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .filter(|&(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn random_primitive_int_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn random_primitive_int_unsigned_pair_gen_var_8( _config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigneds_less_than(seed, U::WIDTH + 1), )) } pub fn random_primitive_int_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveInt, PrimitiveUnsigned, bool) -- pub fn random_primitive_int_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, bool)> { reshape_1_2_to_3(Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_union2s( seed, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) .map(|x| (x, false)) }, &|seed_2| random_unsigneds_less_than(seed_2, T::WIDTH).map(|x| (x, true)), ) .map(Union2::unwrap) }, ))) } pub fn random_primitive_int_unsigned_bool_triple_gen_var_2( config: &GenConfig, ) -> It<(T, u64, bool)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs(seed, &random_primitive_ints, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .map(|(x, y)| (x, y, x < T::ZERO)) }, &|seed| { random_pairs(seed, &random_primitive_ints, &|seed_2| { random_unsigneds_less_than(seed_2, T::WIDTH) }) .map(|(x, y)| (x, y, x >= T::ZERO)) }, ) .map(Union2::unwrap), ) } pub fn random_primitive_int_unsigned_bool_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(T, U, bool)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints::, &random_positive_unsigneds::, &random_bools, )) } // -- (PrimitiveInt, PrimitiveUnsigned, PrimitiveInt) -- pub fn random_primitive_int_unsigned_primitive_int_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx(EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn random_primitive_int_unsigned_primitive_int_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx(EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, U::ZERO, U::saturating_from(u64::MAX)) }) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn random_primitive_int_unsigned_primitive_int_triple_gen_var_3< T: PrimitiveInt, U: PrimitiveInt, >( _config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx(EXAMPLE_SEED, &random_primitive_ints, &random_primitive_ints) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } // -- (PrimitiveInt, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_primitive_int_unsigned_unsigned_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveInt, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, u64, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, 1, U::WIDTH), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_unsigned_unsigned_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, U)> { Box::new( random_triples_xyy(EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn random_primitive_int_unsigned_unsigned_triple_gen_var_3< T: PrimitiveInt, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::exact_from(36u8)), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_unsigned_unsigned_triple_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, U)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // --(PrimitiveInt, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_primitive_int_unsigned_unsigned_unsigned_quadruple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, u64, u64, U)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_primitive_ints, ) .filter_map(|(x, y, z, w)| { let (y, z) = if y <= z { (y, z) } else { (z, y) }; if unsigned_assign_bits_valid(y, z, w) { Some((x, y, z, w)) } else { None } }), ) } // --(PrimitiveInt, PrimitiveUnsigned, RoundingMode) -- pub fn random_primitive_int_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, pow, rm)| round_to_multiple_of_power_of_2_filter_map(x, pow, rm)), ) } pub fn random_primitive_int_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, y, rm)| rm != Exact || x.divisible_by_power_of_2(y.exact_into())), ) } pub fn random_primitive_int_unsigned_rounding_mode_triple_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &random_positive_unsigneds, &random_rounding_modes, )) } // --(PrimitiveInt, PrimitiveUnsigned, Vec) -- struct PrimitiveIntUnsignedBoolVecTripleGeneratorVar1 { xs: RandomPrimitiveInts, log_bases: RandomUnsignedInclusiveRange, bs: RandomBools, } impl Iterator for PrimitiveIntUnsignedBoolVecTripleGeneratorVar1 { type Item = (T, u64, Vec); fn next(&mut self) -> Option<(T, u64, Vec)> { let x = self.xs.next().unwrap(); let log_base = self.log_bases.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from( x.significant_bits().div_round(log_base, Ceiling).0, )) .collect(); Some((x, log_base, bs)) } } pub fn random_primitive_int_unsigned_bool_vec_triple_gen_var_1( _config: &GenConfig, ) -> It<(T, u64, Vec)> { Box::new(PrimitiveIntUnsignedBoolVecTripleGeneratorVar1 { xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), log_bases: random_unsigned_inclusive_range(EXAMPLE_SEED.fork("log_bases"), 1, U::WIDTH), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- (PrimitiveInt, RoundingMode) -- pub fn random_primitive_int_rounding_mode_pair_gen( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &random_rounding_modes, )) } pub fn random_primitive_int_rounding_mode_pair_gen_var_1< T: PrimitiveInt, U: ConvertibleFrom + PrimitiveFloat, >( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs(EXAMPLE_SEED, &random_primitive_ints, &random_rounding_modes) .filter(move |&(n, rm)| rm != Exact || U::convertible_from(n)), ) } // -- (PrimitiveInt, ToSciOptions) -- pub fn random_primitive_int_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, )) } pub fn random_primitive_int_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new( random_pairs(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- PrimitiveSigned -- pub fn random_signed_gen_var_1(_config: &GenConfig) -> It { Box::new(random_primitive_ints(EXAMPLE_SEED).filter(|&x| x != T::MIN)) } pub fn random_signed_gen_var_2(_config: &GenConfig) -> It { Box::new(random_natural_signeds(EXAMPLE_SEED)) } pub fn random_signed_gen_var_3(_config: &GenConfig) -> It { Box::new(random_primitive_ints(EXAMPLE_SEED).filter(|&x| x != T::ZERO && x != T::NEGATIVE_ONE)) } pub fn random_signed_gen_var_4(_config: &GenConfig) -> It { Box::new(random_negative_signeds(EXAMPLE_SEED)) } pub fn random_signed_gen_var_5(config: &GenConfig) -> It { Box::new(geometric_random_signeds( EXAMPLE_SEED, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), )) } pub fn random_signed_gen_var_6(_config: &GenConfig) -> It { Box::new(random_nonzero_signeds(EXAMPLE_SEED)) } pub fn random_signed_gen_var_7 + PrimitiveFloat>( _config: &GenConfig, ) -> It { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_signed_inclusive_range( seed, T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) }, &|seed| { random_signed_inclusive_range( seed, T::MIN, T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT).saturating_neg(), ) }, ) .map(Union2::unwrap) .filter(|&x| !U::convertible_from(x)), ) } pub fn random_signed_gen_var_8< T: TryFrom> + PrimitiveSigned, U: PrimitiveFloat + RoundingFrom, >( _config: &GenConfig, ) -> It { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_signed_inclusive_range( seed, T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter_map(|a| { let f = U::rounding_from(a, Down).0; let a = T::try_from(NiceFloat(f)).ok()?; let b = T::try_from(NiceFloat(f.next_higher())).ok()?; let diff = b - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }) }, &|seed| { random_signed_inclusive_range( seed, T::MIN, T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT) .checked_neg() .unwrap(), ) .filter_map(|a| { let f = U::rounding_from(a, Down).0; let a = T::try_from(NiceFloat(f)).ok()?; let b = T::try_from(NiceFloat(f.next_lower())).ok()?; let diff = a - b; if diff.even() { // This happens almost always Some(a - (diff >> 1)) } else { None } }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_gen_var_9< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( _config: &GenConfig, ) -> It { let limit = S::wrapping_from(U::wrapping_from(S::MAX).floor_sqrt()); Box::new(random_signed_inclusive_range(EXAMPLE_SEED, -limit, limit)) } pub fn random_signed_gen_var_10(_config: &GenConfig) -> It { Box::new(random_signed_inclusive_range( EXAMPLE_SEED, T::MIN_EXPONENT, T::MAX_EXPONENT, )) } pub fn random_signed_gen_var_11(_config: &GenConfig) -> It { Box::new(random_primitive_ints(EXAMPLE_SEED).filter(|&x| x != T::ZERO && x != T::MIN)) } pub fn random_signed_gen_var_12(_config: &GenConfig) -> It { Box::new( random_signed_inclusive_range(EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), ) } // -- (PrimitiveSigned, PrimitiveSigned) -- pub fn random_signed_pair_gen_var_1(_config: &GenConfig) -> It<(T, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_pairs_from_single(random_natural_signeds(seed)), &|seed| random_pairs_from_single(random_negative_signeds(seed)), ) .map(Union2::unwrap), ) } pub fn random_signed_pair_gen_var_2(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_nonzero_signeds::, ) .filter_map(|(mut x, y)| { x.round_to_multiple_assign(y, Down); if x == T::MIN && y == T::NEGATIVE_ONE { None } else { Some((x, y)) } }), ) } pub fn random_signed_pair_gen_var_3(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_nonzero_signeds::, ) .filter(|&(x, y)| x != T::MIN || y != T::NEGATIVE_ONE), ) } pub fn random_signed_pair_gen_var_4(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_nonzero_signeds::, ) .filter(|&(x, y)| !x.divisible_by(y)), ) } pub fn random_signed_pair_gen_var_5(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_nonzero_signeds::, )) } pub fn random_signed_pair_gen_var_6(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(random_natural_signeds::( EXAMPLE_SEED, ))) } pub fn random_signed_pair_gen_var_7(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_signed_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_signed_pair_gen_var_8(_config: &GenConfig) -> It<(T, T)> where ::Output: PrimitiveUnsigned, { Box::new( random_pairs_from_single( random_signed_inclusive_range(EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE), ) .filter(|&(a, b): &(T, T)| a.unsigned_abs().coprime_with(b.unsigned_abs())), ) } pub fn random_signed_pair_gen_var_9< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( _config: &GenConfig, ) -> It<(S, S)> { Box::new( random_pairs_from_single(random_primitive_ints(EXAMPLE_SEED)) .filter(|&(x, y): &(S, S)| x.unsigned_abs().coprime_with(y.unsigned_abs())), ) } pub fn random_signed_pair_gen_var_10( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_signed_pair_gen_var_11(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs_from_single(geometric_random_signeds( EXAMPLE_SEED, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), )) .filter(|&(n, k)| T::checked_binomial_coefficient(n, k).is_some()), ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- fn halve_bits(x: T) -> T { let half_width = (T::WIDTH >> 1) - 1; let half_mask = T::low_mask(half_width); if x >= T::ZERO { x & half_mask } else { x | (T::NEGATIVE_ONE << half_width) } } pub(crate) fn reduce_to_fit_add_mul_signed(x: T, y: T, z: T) -> (T, T, T) { if x.checked_add_mul(y, z).is_some() { (x, y, z) } else { (halve_bits(x), halve_bits(y), halve_bits(z)) } } pub fn random_signed_triple_gen_var_1(_config: &GenConfig) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints(EXAMPLE_SEED)) .map(|(x, y, z)| reduce_to_fit_add_mul_signed(x, y, z)), ) } pub(crate) fn reduce_to_fit_sub_mul_signed(x: T, y: T, z: T) -> (T, T, T) { if x.checked_sub_mul(y, z).is_some() { (x, y, z) } else { (halve_bits(x), halve_bits(y), halve_bits(z)) } } pub fn random_signed_triple_gen_var_2(_config: &GenConfig) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints(EXAMPLE_SEED)) .map(|(x, y, z)| reduce_to_fit_sub_mul_signed(x, y, z)), ) } pub fn random_signed_triple_gen_var_3(_config: &GenConfig) -> It<(T, T, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_triples_from_single(random_natural_signeds(seed)), &|seed| random_triples_from_single(random_negative_signeds(seed)), ) .map(Union2::unwrap), ) } pub fn random_signed_triple_gen_var_4< U: PrimitiveUnsigned + WrappingFrom + WrappingInto, S: PrimitiveSigned + UnsignedAbs, >( _config: &GenConfig, ) -> It<(S, S, S)> { Box::new( random_triples_from_single(random_primitive_ints::(EXAMPLE_SEED)).map(|(x, y, m)| { if m == S::ZERO { let min = min(x, y); (min, min, m) } else if x <= y { let adjusted_diff = U::wrapping_from(y.wrapping_sub(x)) .round_to_multiple(m.unsigned_abs(), Down) .0; ( x, (U::wrapping_from(x).wrapping_add(adjusted_diff)).wrapping_into(), m, ) } else { let adjusted_diff = U::wrapping_from(x.wrapping_sub(y)) .round_to_multiple(m.unsigned_abs(), Down) .0; ( (U::wrapping_from(y).wrapping_add(adjusted_diff)).wrapping_into(), y, m, ) } }), ) } pub fn random_signed_triple_gen_var_5(_config: &GenConfig) -> It<(T, T, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_signed_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_signed_triple_gen_var_6(_config: &GenConfig) -> It<(T, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_signed_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 2)) .map(|u| (u << 1) | T::ONE) }, )) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_signed_signed_unsigned_triple_gen_var_1< U: PrimitiveUnsigned + WrappingFrom + WrappingInto, S: PrimitiveSigned, >( config: &GenConfig, ) -> It<(S, S, u64)> { Box::new( random_triples_xxy(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_pow_n", 32), config.get_or("mean_pow_d", 1), ) }) .map(|(x, y, pow)| { if pow >= S::WIDTH { (x, x, pow) } else if x <= y { let adjusted_diff = U::wrapping_from(y.wrapping_sub(x)) .round_to_multiple_of_power_of_2(pow, Down) .0; ( x, (U::wrapping_from(x).wrapping_add(adjusted_diff)).wrapping_into(), pow, ) } else { let adjusted_diff = U::wrapping_from(x.wrapping_sub(y)) .round_to_multiple_of_power_of_2(pow, Down) .0; ( (U::wrapping_from(y).wrapping_add(adjusted_diff)).wrapping_into(), y, pow, ) } }), ) } pub fn random_signed_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveSigned, RoundingMode) -- struct SignedSignedRoundingModeTripleGenerator { xs: RandomPrimitiveInts, rms: RandomRoundingModes, } impl Iterator for SignedSignedRoundingModeTripleGenerator { type Item = (T, T, RoundingMode); fn next(&mut self) -> Option<(T, T, RoundingMode)> { let mut x; let mut y; loop { x = self.xs.next().unwrap(); loop { y = self.xs.next().unwrap(); if y != T::ZERO { break; } } if x != T::MIN || y != T::NEGATIVE_ONE { break; } } let rm = self.rms.next().unwrap(); if rm == Exact { x.round_to_multiple_assign(y, Down); } Some((x, y, rm)) } } pub fn random_signed_signed_rounding_mode_triple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new(SignedSignedRoundingModeTripleGenerator { xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), rms: random_rounding_modes(EXAMPLE_SEED.fork("rms")), }) } pub fn random_signed_signed_rounding_mode_triple_gen_var_2< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >( _config: &GenConfig, ) -> It<(S, S, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints, &random_nonzero_signeds, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_signed_filter_map(x, y, rm)), ) } // -- (PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_signed_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs(seed, &random_natural_signeds, &|seed_2| { random_unsigned_range(seed_2, 0, T::WIDTH) }) }, &|seed| { random_pairs(seed, &random_negative_signeds, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs(seed, &random_negative_signeds, &|seed_2| { random_unsigned_range(seed_2, 0, T::WIDTH) }) }, &|seed| { random_pairs(seed, &random_natural_signeds, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_natural_signeds, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_signed_unsigned_pair_gen_var_4< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_natural_signeds, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::exact_from(36u8)), )) } pub fn random_signed_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs(seed, &random_natural_signeds, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) }, &|seed| { random_pairs(seed, &random_primitive_ints, &|seed_2| { random_unsigned_inclusive_range(seed_2, 0, T::WIDTH) }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| random_signed_range(seed_2, T::MIN + T::ONE, T::ONE), &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) }, &|seed| { random_pairs(seed, &random_primitive_ints, &|seed_2| { random_unsigned_range(seed_2, 0, T::WIDTH) }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_unsigned_pair_gen_var_7( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_signed_inclusive_range( seed, if T::WIDTH <= u64::WIDTH { T::MIN } else { -T::exact_from(u64::MAX) }, T::saturating_from(u64::MAX), ) }, &random_positive_unsigneds, )) } pub fn random_signed_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_signed_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(x, y)| x.checked_pow(y).is_some()), ) } pub fn random_signed_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_signeds, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_signed_unsigned_pair_gen_var_11( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_signed_range(seed, T::MIN + T::ONE, T::ZERO), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_signed_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs(seed, &random_natural_signeds, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) }, &|seed| { random_pairs(seed, &random_negative_signeds, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | U::ONE)) }) }, ) .map(Union2::unwrap), ) } pub fn random_signed_unsigned_pair_gen_var_13( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_signed_unsigned_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, U)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_triples_xyy(seed, &random_positive_signeds, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }) }, &|seed| { random_triples( seed, &|seed_2| random_signed_range(seed_2, T::MIN, T::ZERO), &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed_2| random_unsigned_range(seed_2, U::ZERO, U::exact_from(T::WIDTH)), ) .filter_map(|(x, y, z): (T, U, U)| y.checked_add(z).map(|new_z| (x, y, new_z))) }, ) .map(Union2::unwrap), ) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1< T: PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, u64, u64, U)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_primitive_ints, ) .filter_map(|(x, y, z, w)| { let (y, z) = if y <= z { (y, z) } else { (z, y) }; if signed_assign_bits_valid(x, y, z, w) { Some((x, y, z, w)) } else { None } }), ) } pub fn random_signed_rounding_mode_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &random_nonzero_signeds, &random_rounding_modes, )) } pub fn random_signed_rounding_mode_pair_gen_var_2( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_signed_inclusive_range(seed, T::MIN + T::ONE, T::MAX), &random_rounding_modes, )) } pub fn random_signed_rounding_mode_pair_gen_var_3( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_nonzero_signeds(seed).filter(|&x| x != T::MIN), &random_rounding_modes, )) } pub fn random_signed_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) pub fn random_signed_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // --(PrimitiveSigned, Vec) -- struct SignedBoolVecPairGeneratorVar1 { xs: RandomPrimitiveInts, bs: RandomBools, } impl Iterator for SignedBoolVecPairGeneratorVar1 { type Item = (T, Vec); fn next(&mut self) -> Option<(T, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from(u64::exact_from(x.to_bits_asc().len()))) .collect(); Some((x, bs)) } } pub fn random_signed_bool_vec_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, Vec)> { Box::new(SignedBoolVecPairGeneratorVar1 { xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- PrimitiveUnsigned -- pub fn random_unsigned_gen_var_1(_config: &GenConfig) -> It { Box::new(random_positive_unsigneds(EXAMPLE_SEED)) } pub fn random_unsigned_gen_var_2(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than(EXAMPLE_SEED, NUMBER_OF_CHARS)) } pub fn random_unsigned_gen_var_3(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range(EXAMPLE_SEED, 1, T::WIDTH)) } pub fn random_unsigned_gen_var_4>( _config: &GenConfig, ) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, U::TWO, U::saturating_from(T::MAX), )) } pub fn random_unsigned_gen_var_5(config: &GenConfig) -> It { Box::new(geometric_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), )) } pub fn random_unsigned_gen_var_6(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::MAX, )) } pub fn random_unsigned_gen_var_7(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than(EXAMPLE_SEED, T::exact_from(36))) } pub fn random_unsigned_gen_var_8(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::exact_from(36), )) } pub fn random_unsigned_gen_var_9(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than(EXAMPLE_SEED, T::WIDTH + 1)) } pub fn random_unsigned_gen_var_10(_config: &GenConfig) -> It { Box::new( random_union3s( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, b'0', b'9'), &|seed| random_unsigned_inclusive_range(seed, b'a', b'z'), &|seed| random_unsigned_inclusive_range(seed, b'A', b'Z'), ) .map(Union3::unwrap), ) } pub fn random_unsigned_gen_var_11(config: &GenConfig) -> It { Box::new(geometric_random_positive_unsigneds( EXAMPLE_SEED, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), )) } pub fn random_unsigned_gen_var_12(_config: &GenConfig) -> It { Box::new(random_highest_bit_set_unsigneds(EXAMPLE_SEED)) } pub fn random_unsigned_gen_var_13(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than( EXAMPLE_SEED, T::LARGEST_ORDERED_REPRESENTATION, )) } pub fn random_unsigned_gen_var_14(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than( EXAMPLE_SEED, T::power_of_2(T::WIDTH - 1) + T::ONE, )) } pub fn random_unsigned_gen_var_15(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than(EXAMPLE_SEED, T::WIDTH)) } pub fn random_unsigned_gen_var_16(_config: &GenConfig) -> It { Box::new(random_unsigneds_less_than(EXAMPLE_SEED, T::WIDTH - 1)) } pub fn random_unsigned_gen_var_17(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, T::power_of_2(T::WIDTH - 2), T::MAX, )) } pub fn random_unsigned_gen_var_18 + PrimitiveFloat>( _config: &GenConfig, ) -> It { Box::new( random_unsigned_inclusive_range( EXAMPLE_SEED, T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter(|&x| !U::convertible_from(x)), ) } pub fn random_unsigned_gen_var_19< T: TryFrom> + PrimitiveUnsigned, U: PrimitiveFloat + RoundingFrom, >( _config: &GenConfig, ) -> It { Box::new( random_unsigned_inclusive_range( EXAMPLE_SEED, T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, ) .filter_map(|a| { let f = U::rounding_from(a, Down).0; let a = T::try_from(NiceFloat(f)).ok()?; let b = T::try_from(NiceFloat(f.next_higher())).ok()?; let diff = b - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn random_unsigned_gen_var_20(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, T::ZERO, T::MAX.floor_sqrt(), )) } pub fn random_unsigned_gen_var_21(_config: &GenConfig) -> It { Box::new( random_unsigned_inclusive_range(EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), ) } pub fn random_unsigned_gen_var_22(_config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_factorial); Box::new(random_unsigned_range(EXAMPLE_SEED, 0, limit)) } pub fn random_unsigned_gen_var_23(_config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_double_factorial); Box::new(random_unsigned_range(EXAMPLE_SEED, 0, limit)) } pub fn random_unsigned_gen_var_24(_config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_subfactorial); Box::new(random_unsigned_range(EXAMPLE_SEED, 0, limit)) } pub fn random_unsigned_gen_var_25(config: &GenConfig) -> It { Box::new(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED, T::wrapping_from(5u8), T::MAX, config.get_or("mean_n", 128), config.get_or("mean_d", 1), )) } pub fn random_unsigned_gen_var_26(_config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_primorial); Box::new(random_unsigned_range(EXAMPLE_SEED, 0, limit)) } pub fn random_unsigned_gen_var_27(_config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_product_of_first_n_primes); Box::new(random_unsigned_range(EXAMPLE_SEED, 0, limit)) } pub fn random_unsigned_gen_var_28(_config: &GenConfig) -> It { Box::new(random_primitive_ints(EXAMPLE_SEED).filter(T::is_prime)) } pub fn random_signed_gen_var_29(_config: &GenConfig) -> It { Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED, 0, u64::exact_from(T::MAX_EXPONENT), )) } // -- (PrimitiveUnsigned, PrimitiveInt) -- pub fn random_unsigned_primitive_int_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, T::power_of_2(T::WIDTH - 2), T::MAX), &random_primitive_ints, )) } // -- (PrimitiveUnsigned, PrimitiveInt, PrimitiveInt, PrimitiveUnsigned) -- struct ModPowerOf2QuadrupleWithTwoExtraPrimitiveIntsGenerator { ms: GeometricRandomNaturalValues, us: RandomPrimitiveInts, xss: Vec>>, } impl Iterator for ModPowerOf2QuadrupleWithTwoExtraPrimitiveIntsGenerator { type Item = (T, U, U, u64); fn next(&mut self) -> Option<(T, U, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), self.us.next().unwrap(), pow)) } } pub fn random_unsigned_primitive_int_primitive_int_unsigned_quadruple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(T, U, U, u64)> { Box::new(ModPowerOf2QuadrupleWithTwoExtraPrimitiveIntsGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: random_primitive_ints(EXAMPLE_SEED.fork("us")), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } // -- (PrimitiveUnsigned, PrimitiveInt, PrimitiveUnsigned) -- struct ModPowerOf2TripleWithExtraPrimitiveIntGenerator { ms: GeometricRandomNaturalValues, us: RandomPrimitiveInts, xss: Vec>>, } impl Iterator for ModPowerOf2TripleWithExtraPrimitiveIntGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn random_unsigned_primitive_int_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleWithExtraPrimitiveIntGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: random_primitive_ints(EXAMPLE_SEED.fork("us")), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } // -- (PrimitiveUnsigned, PrimitiveSigned) -- struct IntegerMantissaAndExponentGenerator { xs: SpecialRandomNonzeroFiniteFloats, shifts: GeometricRandomNaturalValues, } #[inline] pub(crate) fn shift_integer_mantissa_and_exponent( mantissa: u64, exponent: i64, shift: i64, ) -> Option<(u64, i64)> { Some(( mantissa.arithmetic_checked_shl(shift)?, exponent.checked_sub(shift)?, )) } impl Iterator for IntegerMantissaAndExponentGenerator { type Item = (u64, i64); fn next(&mut self) -> Option<(u64, i64)> { loop { let (mantissa, exponent) = self.xs.next().unwrap().integer_mantissa_and_exponent(); let shift = self.shifts.next().unwrap(); let out = shift_integer_mantissa_and_exponent(mantissa, exponent, shift); if out.is_some() { return out; } } } } pub fn random_unsigned_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(u64, i64)> { Box::new(IntegerMantissaAndExponentGenerator:: { xs: special_random_nonzero_finite_primitive_floats( EXAMPLE_SEED.fork("xs"), config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ), shifts: geometric_random_natural_signeds( EXAMPLE_SEED.fork("shifts"), config.get_or("shift_mean_n", 4), config.get_or("shift_mean_d", 1), ), }) } // -- (PrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned) -- struct ModPowerOf2TripleWithExtraSmallSignedGenerator { ms: GeometricRandomNaturalValues, us: GeometricRandomSigneds, xss: Vec>>, } impl Iterator for ModPowerOf2TripleWithExtraSmallSignedGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn random_unsigned_signed_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleWithExtraSmallSignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: geometric_random_signeds( EXAMPLE_SEED.fork("us"), config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } pub fn random_unsigned_signed_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_unsigned_pair_gen_var_1(_config: &GenConfig) -> It<(u32, u32)> { Box::new(random_pairs_from_single(random_unsigneds_less_than( EXAMPLE_SEED, NUMBER_OF_CHARS, ))) } pub fn random_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, 1, U::WIDTH), )) } pub fn random_unsigned_pair_gen_var_3< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::exact_from(36u8)), )) } pub fn random_unsigned_pair_gen_var_4< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, V)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::saturating_from(U::MAX)), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_5(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_positive_unsigneds::, ) .map(|(x, y)| (x.round_to_multiple(y, Down).0, y)), ) } pub fn random_unsigned_pair_gen_var_6( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_positive_unsigneds::, )) } pub fn random_unsigned_pair_gen_var_7(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_ints::, &random_positive_unsigneds::, ) .filter(|&(x, y)| !x.divisible_by(y)), ) } struct ModPowerOf2SingleGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, } impl Iterator for ModPowerOf2SingleGenerator { type Item = (T, u64); fn next(&mut self) -> Option<(T, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, pow)) } } struct ModPowerOf2SingleGenerator2 { ms: GeometricRandomNaturalValues, xss: Vec>>>, } impl Iterator for ModPowerOf2SingleGenerator2 { type Item = (T, u64); fn next(&mut self) -> Option<(T, u64)> { let pow = self.ms.next().unwrap(); assert_ne!(pow, 0); let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(Box::new( random_unsigned_bit_chunks(EXAMPLE_SEED.fork(&pow.to_string()), pow) .filter(|&x| x != T::ZERO), )); } let x = xs.as_mut().unwrap().next().unwrap(); Some((x, pow)) } } pub fn random_unsigned_pair_gen_var_8(config: &GenConfig) -> It<(T, u64)> { Box::new(ModPowerOf2SingleGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } pub fn random_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_10< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, U::TWO, U::exact_from(36u8)), )) } pub fn random_unsigned_pair_gen_var_11(config: &GenConfig) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) .map(|x| (T::ZERO, x)) }, &|seed| { random_pairs(seed, &random_positive_unsigneds, &|seed_2| { random_unsigneds_less_than(seed_2, T::WIDTH) }) }, ) .map(Union2::unwrap), ) } pub fn random_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_unsigneds, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_13(_config: &GenConfig) -> It<(u64, u64)> { Box::new(random_pairs_from_single(random_unsigneds_less_than( EXAMPLE_SEED, T::LARGEST_ORDERED_REPRESENTATION, ))) } pub fn random_unsigned_pair_gen_var_14( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_unsigneds, &|seed| { geometric_random_unsigned_range( seed, U::TWO, U::MAX, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_15( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, T::ZERO, T::saturating_from(u64::MAX)), &random_positive_unsigneds::, )) } pub fn random_unsigned_pair_gen_var_16(_config: &GenConfig) -> It<(u64, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_bit_chunks(seed, T::MANTISSA_WIDTH), &|seed| random_unsigned_bit_chunks(seed, T::EXPONENT_WIDTH), )) } pub fn random_unsigned_pair_gen_var_17( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_18(config: &GenConfig) -> It<(T, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(x, y)| x.checked_pow(y).is_some()), ) } pub fn random_unsigned_pair_gen_var_19(config: &GenConfig) -> It<(T, u64)> { Box::new(random_unsigned_pair_gen_var_8(config).map(|(x, p)| (x, T::WIDTH - p))) } pub fn random_unsigned_pair_gen_var_20( _config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| random_unsigned_inclusive_range(seed, U::power_of_2(U::WIDTH - 2), U::MAX), )) } struct LikelyMultiplyablePairs { bits: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, phantom: PhantomData<*const T>, } impl Iterator for LikelyMultiplyablePairs { type Item = (T, T); fn next(&mut self) -> Option<(T, T)> { let x_bits = self.bits.next().unwrap(); let x = if x_bits == 0 { T::ZERO } else { self.ranges.next_bit_chunk(x_bits) }; let y_bits = self.bits.next().unwrap(); let y = if y_bits == 0 { T::ZERO } else { self.ranges.next_bit_chunk(y_bits) }; Some((x, y)) } } pub fn random_unsigned_pair_gen_var_21(_config: &GenConfig) -> It<(T, T)> { Box::new(LikelyMultiplyablePairs { bits: geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("bits"), 0, T::WIDTH, T::WIDTH >> 1, 1, ), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } pub fn random_unsigned_pair_gen_var_22(config: &GenConfig) -> It<(T, T)> { Box::new( random_unsigned_pair_gen_var_21::(config).filter(|&(x, y)| x.checked_lcm(y).is_some()), ) } pub fn random_unsigned_pair_gen_var_23(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, T::power_of_2(T::WIDTH - 1), T::MAX), &random_primitive_ints, )) } pub fn random_unsigned_pair_gen_var_24(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &random_positive_unsigneds, &random_primitive_ints, ) .filter(|&(x, y)| x != T::ONE || y != T::ZERO), ) } pub fn random_unsigned_pair_gen_var_25( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_unsigneds, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_unsigned_pair_gen_var_26(_config: &GenConfig) -> It<(T, T)> { Box::new(random_ordered_unique_pairs(random_positive_unsigneds::( EXAMPLE_SEED, ))) } pub fn random_unsigned_pair_gen_var_27(config: &GenConfig) -> It<(T, u64)> { Box::new(ModPowerOf2SingleGenerator2 { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 1, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: { let len = usize::wrapping_from(T::WIDTH) + 1; let mut xss = Vec::with_capacity(len); xss.resize_with(len, || None); xss }, }) } pub fn random_unsigned_pair_gen_var_28(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_unsigned_pair_gen_var_29(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs_from_single( random_unsigned_inclusive_range(EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE), ) .filter(|&(a, b): &(T, T)| a.coprime_with(b)), ) } pub fn random_unsigned_pair_gen_var_30(_config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs_from_single(random_primitive_ints(EXAMPLE_SEED)) .filter(|&(x, y): &(T, T)| x.coprime_with(y)), ) } struct MultifactorialNGenerator { ms: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, ms_to_n_limit: HashMap, phantom: PhantomData<*const T>, } impl Iterator for MultifactorialNGenerator { type Item = (u64, u64); fn next(&mut self) -> Option<(u64, u64)> { let m = self.ms.next().unwrap(); let smallest_invalid_n = self .ms_to_n_limit .entry(m) .or_insert_with(|| smallest_invalid_value(|n| T::checked_multifactorial(n, m))); let n = self.ranges.next_less_than(*smallest_invalid_n); Some((n, m)) } } pub fn random_unsigned_pair_gen_var_31(config: &GenConfig) -> It<(u64, u64)> { Box::new(MultifactorialNGenerator { ms: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_m_n", 4), config.get_or("mean_m_d", 1), ), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), ms_to_n_limit: HashMap::new(), phantom: PhantomData::<*const T>, }) } pub fn random_unsigned_pair_gen_var_32(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs_from_single(geometric_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), )) .filter(|&(n, k)| T::checked_binomial_coefficient(n, k).is_some()), ) } // vars 33 through 37 are in malachite-nz pub fn random_unsigned_pair_gen_var_38(_config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::MAX, ))) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveInt, PrimitiveUnsigned) -- struct ModPowerOf2QuadrupleWithExtraPrimitiveIntGenerator { ms: GeometricRandomNaturalValues, us: RandomPrimitiveInts, xss: Vec>>, } impl Iterator for ModPowerOf2QuadrupleWithExtraPrimitiveIntGenerator { type Item = (T, T, U, u64); fn next(&mut self) -> Option<(T, T, U, u64)> { let pow = self.ms.next().unwrap(); let (x, y) = if pow == 0 { (T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, self.us.next().unwrap(), pow)) } } pub fn random_unsigned_unsigned_primitive_int_unsigned_quadruple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(T, T, U, u64)> { Box::new(ModPowerOf2QuadrupleWithExtraPrimitiveIntGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: random_primitive_ints(EXAMPLE_SEED.fork("us")), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- fn wrapping_shr(x: T, bits: u64) -> T { if bits >= x.significant_bits() { T::ZERO } else { x >> bits } } pub(crate) fn reduce_to_fit_add_mul_unsigned(x: T, y: T, z: T) -> (T, T, T) { let (p_hi, p_lo) = T::x_mul_y_to_zz(y, z); let r_hi = T::xx_add_yy_to_zz(T::ZERO, x, p_hi, p_lo).0; if r_hi == T::ZERO { (x, y, z) } else { let excess_x: u64 = r_hi.significant_bits(); let excess_yz = excess_x.shr_round(1, Ceiling).0; ( wrapping_shr(x, excess_x), wrapping_shr(y, excess_yz), wrapping_shr(z, excess_yz), ) } } pub fn random_unsigned_triple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints(EXAMPLE_SEED)) .map(|(x, y, z)| reduce_to_fit_add_mul_unsigned(x, y, z)), ) } pub(crate) fn reduce_to_fit_sub_mul_unsigned(x: T, y: T, z: T) -> (T, T, T) { let x_bits = x.significant_bits(); let (p_hi, p_lo) = T::x_mul_y_to_zz(y, z); let product_bits = if p_hi == T::ZERO { p_lo.significant_bits() } else { p_hi.significant_bits() + T::WIDTH }; if x_bits > product_bits { (x, y, z) } else { let excess = (product_bits - x_bits + 1).shr_round(1, Ceiling).0; (x, wrapping_shr(y, excess), wrapping_shr(z, excess)) } } pub fn random_unsigned_triple_gen_var_2( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints(EXAMPLE_SEED)) .map(|(x, y, z)| reduce_to_fit_sub_mul_unsigned(x, y, z)), ) } pub fn random_unsigned_triple_gen_var_3( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(random_primitive_ints::(EXAMPLE_SEED)).map(|(x, y, m)| { if m == T::ZERO { let min = min(x, y); (min, min, m) } else if x <= y { let adjusted_diff = (y - x).round_to_multiple(m, Down).0; (x, x + adjusted_diff, m) } else { let adjusted_diff = (x - y).round_to_multiple(m, Down).0; (y + adjusted_diff, y, m) } }), ) } pub fn random_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new( random_triples_xxy(EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_pow_n", 32), config.get_or("mean_pow_d", 1), ) }) .map(|(x, y, pow)| { if pow >= T::WIDTH { (x, x, pow) } else if x <= y { let adjusted_diff = (y - x).round_to_multiple_of_power_of_2(pow, Down).0; (x, x + adjusted_diff, pow) } else { let adjusted_diff = (x - y).round_to_multiple_of_power_of_2(pow, Down).0; (y + adjusted_diff, y, pow) } }), ) } struct ModPowerOf2PairGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, } impl Iterator for ModPowerOf2PairGenerator { type Item = (T, T, u64); fn next(&mut self) -> Option<(T, T, u64)> { let pow = self.ms.next().unwrap(); let (x, y) = if pow == 0 { (T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, pow)) } } pub fn random_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new(ModPowerOf2PairGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } struct ModPowerOf2TripleWithExtraSmallUnsignedGenerator { ms: GeometricRandomNaturalValues, us: GeometricRandomNaturalValues, xss: Vec>>, } impl Iterator for ModPowerOf2TripleWithExtraSmallUnsignedGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn random_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleWithExtraSmallUnsignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: geometric_random_unsigneds( EXAMPLE_SEED.fork("us"), config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } pub fn random_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(T, U, U)> { Box::new( random_triples_xyy(EXAMPLE_SEED, &random_positive_unsigneds, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn random_unsigned_triple_gen_var_8( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xyx( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_unsigned_triple_gen_var_9( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_unsigned_triple_gen_var_10( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, )) } pub fn random_unsigned_triple_gen_var_11( config: &GenConfig, ) -> It<(T, T, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- struct ModPowerOf2TripleGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, } impl Iterator for ModPowerOf2TripleGenerator { type Item = (T, T, T, u64); fn next(&mut self) -> Option<(T, T, T, u64)> { let pow = self.ms.next().unwrap(); let (x, y, z) = if pow == 0 { (T::ZERO, T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, z, pow)) } } pub fn random_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T, u64)> { Box::new(ModPowerOf2TripleGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], }) } pub fn random_unsigned_quadruple_gen_var_2< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( _config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &random_primitive_ints, &random_positive_unsigneds, ) .map(|(x_1, x_0, d)| { let inv = limbs_invert_limb_naive::(d << LeadingZeros::leading_zeros(d)); (x_1, x_0, d, inv) }), ) } pub fn random_unsigned_quadruple_gen_var_3( _config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &random_primitive_ints, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- struct UnsignedUnsignedRoundingModeTripleGenerator { xs: RandomPrimitiveInts, rms: RandomRoundingModes, } impl Iterator for UnsignedUnsignedRoundingModeTripleGenerator { type Item = (T, T, RoundingMode); fn next(&mut self) -> Option<(T, T, RoundingMode)> { let mut x = self.xs.next().unwrap(); let mut y; loop { y = self.xs.next().unwrap(); if y != T::ZERO { break; } } let rm = self.rms.next().unwrap(); if rm == Exact { x.round_to_multiple_assign(y, Down); } Some((x, y, rm)) } } pub fn random_unsigned_unsigned_rounding_mode_triple_gen_var_1( _config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new(UnsignedUnsignedRoundingModeTripleGenerator { xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), rms: random_rounding_modes(EXAMPLE_SEED.fork("rms")), }) } pub fn random_unsigned_unsigned_rounding_mode_triple_gen_var_2( _config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints, &random_positive_unsigneds, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_unsigned_filter_map(x, y, rm)), ) } // vars 3 through 5 are in malachite-float. // -- (PrimitiveUnsigned, RoundingMode) -- pub fn random_unsigned_rounding_mode_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_unsigneds, &random_rounding_modes, )) } pub fn random_unsigned_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } pub fn random_unsigned_rounding_mode_pair_gen_var_3( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } pub fn random_unsigned_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // -- (PrimitiveUnsigned, String) -- struct DigitStringGenerator { ranges: VariableRangeGenerator, digit_map: HashMap>, digit_counts: GeometricRandomNaturalValues, } impl Iterator for DigitStringGenerator { type Item = (u8, String); fn next(&mut self) -> Option<(u8, String)> { let base = self.ranges.next_in_inclusive_range(2, 36); let digits = self .digit_map .entry(base) .or_insert_with(|| valid_digit_chars(base)); let digit_count = self.digit_counts.next().unwrap(); let mut s = String::with_capacity(digit_count); for _ in 0..digit_count { let index = self.ranges.next_less_than(digits.len()); s.push(digits[index]); } Some((base, s)) } } pub fn random_unsigned_string_pair_gen_var_1(config: &GenConfig) -> It<(u8, String)> { Box::new(DigitStringGenerator { ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), }) } pub fn random_unsigned_string_pair_gen_var_2(config: &GenConfig) -> It<(u8, String)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_unsigned_inclusive_range(seed, 2, 36), &|seed| { random_strings( seed, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) }, )) } struct TargetedIntegerFromStringBaseInputs { uss: It<(u8, String)>, negs: RandomBools, } impl Iterator for TargetedIntegerFromStringBaseInputs { type Item = (u8, String); fn next(&mut self) -> Option<(u8, String)> { if self.negs.next().unwrap() { let (u, s) = self.uss.next().unwrap(); let mut out = '-'.to_string(); out.push_str(&s); Some((u, out)) } else { self.uss.next() } } } pub fn random_unsigned_string_pair_gen_var_3(config: &GenConfig) -> It<(u8, String)> { Box::new(TargetedIntegerFromStringBaseInputs { uss: Box::new(DigitStringGenerator { ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), }), negs: random_bools(EXAMPLE_SEED.fork("negs")), }) } // --(PrimitiveUnsigned, Vec) -- struct UnsignedBoolVecPairGeneratorVar1 { xs: RandomPrimitiveInts, bs: RandomBools, } impl Iterator for UnsignedBoolVecPairGeneratorVar1 { type Item = (T, Vec); fn next(&mut self) -> Option<(T, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from(x.significant_bits())) .collect(); Some((x, bs)) } } pub fn random_unsigned_bool_vec_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, Vec)> { Box::new(UnsignedBoolVecPairGeneratorVar1 { xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- RationalSequence -- pub fn random_primitive_int_rational_sequence_gen( config: &GenConfig, ) -> It> { Box::new(random_rational_sequences( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } // -- (RationalSequence, PrimitiveUnsigned) -- pub fn random_primitive_int_rational_sequence_unsigned_pair_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(RationalSequence, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_int_rational_sequence_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(RationalSequence, usize)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, ) .filter(|&(ref xs, i)| { if let Some(len) = xs.len() { i < len } else { true } }), ) } // -- (RationalSequence, RationalSequence) -- pub fn random_primitive_int_rational_sequence_pair_gen( config: &GenConfig, ) -> It<(RationalSequence, RationalSequence)> { Box::new(random_pairs_from_single(random_rational_sequences( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } // -- RationalSequence * 3 -- pub fn random_primitive_int_rational_sequence_triple_gen( config: &GenConfig, ) -> It<( RationalSequence, RationalSequence, RationalSequence, )> { Box::new(random_triples_from_single(random_rational_sequences( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } // -- RoundingMode -- pub fn random_rounding_mode_gen(_config: &GenConfig) -> It { Box::new(random_rounding_modes(EXAMPLE_SEED)) } // -- (RoundingMode, RoundingMode) -- pub fn random_rounding_mode_pair_gen(_config: &GenConfig) -> It<(RoundingMode, RoundingMode)> { Box::new(random_pairs_from_single(random_rounding_modes( EXAMPLE_SEED, ))) } // -- (RoundingMode, RoundingMode, RoundingMode) -- pub fn random_rounding_mode_triple_gen( _config: &GenConfig, ) -> It<(RoundingMode, RoundingMode, RoundingMode)> { Box::new(random_triples_from_single(random_rounding_modes( EXAMPLE_SEED, ))) } // -- SciSizeOptions -- pub fn random_sci_size_options_gen(config: &GenConfig) -> It { Box::new(random_sci_size_options( EXAMPLE_SEED, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), )) } // -- String -- pub fn random_string_gen(config: &GenConfig) -> It { Box::new(random_strings( EXAMPLE_SEED, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } pub fn random_string_gen_var_1(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &random_ascii_chars, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } pub fn random_string_gen_var_2(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &|seed| random_values_from_vec(seed, ROUNDING_MODE_CHARS.chars().collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } pub fn random_string_gen_var_3(config: &GenConfig) -> It { Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED, 1, &|seed| random_values_from_vec(seed, ('0'..='9').collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } struct TargetedIntegerFromStrStringsVar1 { ss: It, negs: RandomBools, } impl Iterator for TargetedIntegerFromStrStringsVar1 { type Item = String; fn next(&mut self) -> Option { if self.negs.next().unwrap() { Some(format!("-{}", self.ss.next().unwrap())) } else { self.ss.next() } } } pub fn random_string_gen_var_4(config: &GenConfig) -> It { Box::new(TargetedIntegerFromStrStringsVar1 { ss: Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED.fork("ss"), 1, &|seed| random_values_from_vec(seed, ('0'..='9').collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))), negs: random_bools(EXAMPLE_SEED.fork("negs")), }) } pub fn random_string_gen_var_5(config: &GenConfig) -> It { Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED, 1, &|seed| random_values_from_vec(seed, ('0'..='1').collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } pub fn random_string_gen_var_6(config: &GenConfig) -> It { Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED, 1, &|seed| random_values_from_vec(seed, ('0'..='7').collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } pub fn random_string_gen_var_7(config: &GenConfig) -> It { Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED, 1, &|seed| { random_union3s( seed, &|seed_2| random_values_from_vec(seed_2, ('0'..='9').collect()), &|seed_2| random_values_from_vec(seed_2, ('a'..='f').collect()), &|seed_2| random_values_from_vec(seed_2, ('A'..='F').collect()), ) .map(Union3::unwrap) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } pub fn random_string_gen_var_8(config: &GenConfig) -> It { Box::new( strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED, 1, &|seed| { random_union3s( seed, &|seed_2| random_values_from_vec(seed_2, ('0'..='9').collect()), &|seed_2| random_values_from_vec(seed_2, ('a'..='f').collect()), &|seed_2| random_values_from_vec(seed_2, ('A'..='F').collect()), ) .map(Union3::unwrap) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) .map(|s| format!("\"0x{s}\"")), ) } struct TargetedIntegerFromStrStringsVar2 { ss: It, negs: RandomBools, } impl Iterator for TargetedIntegerFromStrStringsVar2 { type Item = String; fn next(&mut self) -> Option { Some(if self.negs.next().unwrap() { format!("\"-0x{}\"", self.ss.next().unwrap()) } else { format!("\"0x{}\"", self.ss.next().unwrap()) }) } } pub fn random_string_gen_var_9(config: &GenConfig) -> It { Box::new(TargetedIntegerFromStrStringsVar2 { ss: Box::new(strings_from_char_vecs(random_vecs_min_length( EXAMPLE_SEED.fork("ss"), 1, &|seed| { random_union3s( seed, &|seed_2| random_values_from_vec(seed_2, ('0'..='9').collect()), &|seed_2| random_values_from_vec(seed_2, ('a'..='f').collect()), &|seed_2| random_values_from_vec(seed_2, ('A'..='F').collect()), ) .map(Union3::unwrap) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))), negs: random_bools(EXAMPLE_SEED.fork("negs")), }) } pub fn random_string_gen_var_10(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &|seed| random_values_from_vec(seed, PRIMITIVE_FLOAT_CHARS.chars().collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } // vars 11 through 12 are in malachite-q. pub fn random_string_gen_var_13(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &|seed| random_values_from_vec(seed, DECIMAL_SCI_STRING_CHARS.chars().collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } pub fn random_string_gen_var_14(config: &GenConfig) -> It { Box::new( random_strings( EXAMPLE_SEED, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)), ) } pub fn random_string_gen_var_15(config: &GenConfig) -> It { Box::new( random_strings_using_chars( EXAMPLE_SEED, &|seed| random_values_from_vec(seed, DECIMAL_SCI_STRING_CHARS.chars().collect()), config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)), ) } // -- (String, FromSciStringOptions) -- pub fn random_string_from_sci_string_options_pair_gen( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings( seed, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) }, &random_from_sci_string_options, )) } struct SciDigitStringGenerator { options: RandomFromSciStringOptions, ranges: VariableRangeGenerator, digit_map: HashMap>, digit_counts: GeometricRandomNaturalValues, } impl Iterator for SciDigitStringGenerator { type Item = (String, FromSciStringOptions); fn next(&mut self) -> Option<(String, FromSciStringOptions)> { let options = self.options.next().unwrap(); let base = options.get_base(); let digits = self.digit_map.entry(base).or_insert_with(|| { let mut cs = vec!['+', '-', '.']; if base < 15 { cs.push('e'); cs.push('E'); } cs.extend(valid_digit_chars(base)); cs }); let digit_count = self.digit_counts.next().unwrap(); let mut s = String::with_capacity(digit_count); for _ in 0..digit_count { let index = self.ranges.next_less_than(digits.len()); s.push(digits[index]); } Some((s, options)) } } struct SciDigitStringGenerator2 { ranges: VariableRangeGenerator, digit_map: HashMap>, digit_counts: GeometricRandomNaturalValues, } impl Iterator for SciDigitStringGenerator2 { type Item = (String, u8); fn next(&mut self) -> Option<(String, u8)> { let base = self.ranges.next_in_inclusive_range(2, 36); let digits = self.digit_map.entry(base).or_insert_with(|| { let mut cs = vec!['+', '-', '.']; if base < 15 { cs.push('e'); cs.push('E'); } cs.extend(valid_digit_chars(base)); cs }); let digit_count = self.digit_counts.next().unwrap(); let mut s = String::with_capacity(digit_count); for _ in 0..digit_count { let index = self.ranges.next_less_than(digits.len()); s.push(digits[index]); } Some((s, base)) } } pub fn random_string_from_sci_string_options_pair_gen_var_1( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new(SciDigitStringGenerator { options: random_from_sci_string_options(EXAMPLE_SEED.fork("options")), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), }) } pub fn random_string_from_sci_string_options_pair_gen_var_2( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings( seed, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)) }, &random_from_sci_string_options, )) } pub fn random_string_from_sci_string_options_pair_gen_var_3( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new( SciDigitStringGenerator { options: random_from_sci_string_options(EXAMPLE_SEED.fork("options")), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), } .filter(|(s, _)| !large_exponent(s)), ) } // -- (String, PrimitiveUnsigned) -- pub fn random_string_unsigned_pair_gen_var_1(config: &GenConfig) -> It<(String, u8)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings( seed, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)) }, &|seed| random_unsigned_inclusive_range(seed, 2, 36), )) } pub fn random_string_unsigned_pair_gen_var_2(config: &GenConfig) -> It<(String, u8)> { Box::new( SciDigitStringGenerator2 { ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), digit_map: HashMap::new(), digit_counts: geometric_random_unsigned_range( EXAMPLE_SEED.fork("digit_counts"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), } .filter(|(s, _)| !large_exponent(s)), ) } // -- (String, String) -- pub fn random_string_pair_gen(config: &GenConfig) -> It<(String, String)> { Box::new(random_pairs_from_single(random_strings( EXAMPLE_SEED, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } pub fn random_string_pair_gen_var_1(config: &GenConfig) -> It<(String, String)> { Box::new(random_pairs_from_single(random_strings_using_chars( EXAMPLE_SEED, &random_ascii_chars, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } // -- ToSciOptions -- pub fn random_to_sci_options_gen(config: &GenConfig) -> It { Box::new(random_to_sci_options( EXAMPLE_SEED, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), )) } // -- (ToSciOptions, bool) -- pub fn random_to_sci_options_bool_pair_gen(config: &GenConfig) -> It<(ToSciOptions, bool)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &random_bools, )) } // -- (ToSciOptions, PrimitiveSigned) -- pub fn random_to_sci_options_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(ToSciOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &|seed| { geometric_random_negative_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (ToSciOptions, PrimitiveUnsigned) -- pub fn random_to_sci_options_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(ToSciOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), )) } pub fn random_to_sci_options_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(ToSciOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_to_sci_options_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(ToSciOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (ToSciOptions, RoundingMode) -- pub fn random_to_sci_options_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(ToSciOptions, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &random_rounding_modes, )) } // -- Vec -- pub fn random_bool_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &random_bools, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } pub fn random_bool_vec_gen_var_1(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_vecs_length_inclusive_range(seed, 0, T::WIDTH, &random_bools), &|seed| { random_pairs( seed, &|seed_2| random_vecs_fixed_length_from_single(T::WIDTH, random_bools(seed_2)), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| bs.into_iter().chain(repeat_n(false, n)).collect()) }, ) .map(Union2::unwrap), ) } pub fn random_bool_vec_gen_var_2(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_vecs_length_inclusive_range(seed, 0, T::WIDTH - 1, &random_bools), &|seed| { random_pairs( seed, &|seed_2| { random_vecs_fixed_length_from_single(T::WIDTH - 1, random_bools(seed_2)) }, &|seed_2| { geometric_random_nonzero_signeds::( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| { bs.into_iter() .chain(repeat_n(n < 0, n.unsigned_abs())) .collect() }) }, ) .map(Union2::unwrap), ) } pub fn random_bool_vec_gen_var_3(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_vecs_length_inclusive_range(seed, 0, T::WIDTH, &random_bools), &|seed| { random_pairs( seed, &|seed_2| random_vecs_fixed_length_from_single(T::WIDTH, random_bools(seed_2)), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| repeat_n(false, n).chain(bs).collect()) }, ) .map(Union2::unwrap), ) } pub fn random_bool_vec_gen_var_4(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| random_vecs_length_inclusive_range(seed, 0, T::WIDTH - 1, &random_bools), &|seed| { random_pairs( seed, &|seed_2| { random_vecs_fixed_length_from_single(T::WIDTH - 1, random_bools(seed_2)) }, &|seed_2| { geometric_random_nonzero_signeds::( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| repeat_n(n < 0, n.unsigned_abs()).chain(bs).collect()) }, ) .map(Union2::unwrap), ) } pub fn random_bool_vec_gen_var_5(config: &GenConfig) -> It> { Box::new( random_vecs_min_length( EXAMPLE_SEED, 1, &random_bools, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|bs| bs.iter().any(|&b| b)), ) } // -- Vec -- pub fn random_primitive_int_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } pub fn random_primitive_int_vec_gen_var_1(config: &GenConfig) -> It> { Box::new( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), ) } pub fn random_primitive_int_vec_gen_var_2(config: &GenConfig) -> It> { Box::new( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)), ) } pub fn random_primitive_int_vec_gen_var_3(config: &GenConfig) -> It> { Box::new( random_vecs( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), ) } pub fn random_primitive_int_vec_gen_var_4(config: &GenConfig) -> It> { Box::new(random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } pub fn random_primitive_int_vec_gen_var_5(config: &GenConfig) -> It> { Box::new(random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } // --(Vec, PrimitiveInt) -- pub fn random_primitive_int_vec_primitive_int_pair_gen( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints, )) } pub fn random_primitive_int_vec_primitive_int_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints, )) } pub fn random_primitive_int_vec_primitive_int_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &random_primitive_ints, )) } // --(Vec, PrimitiveUnsigned) -- struct PrimitiveIntVecUnsignedPairGeneratorVar1 { xs: GeometricRandomNaturalValues, ys: RandomPrimitiveInts, } impl Iterator for PrimitiveIntVecUnsignedPairGeneratorVar1 { type Item = (Vec, usize); fn next(&mut self) -> Option<(Vec, usize)> { let x_1 = self.xs.next().unwrap(); let x_2 = self.xs.next().unwrap(); let (len, i) = if x_1 <= x_2 { (x_2, x_1) } else { (x_1, x_2) }; Some(((&mut self.ys).take(len).collect(), i)) } } pub fn random_primitive_int_vec_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, usize)> { Box::new(PrimitiveIntVecUnsignedPairGeneratorVar1 { xs: geometric_random_unsigneds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), ys: random_primitive_ints(EXAMPLE_SEED.fork("ys")), }) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed, 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned + SaturatingFrom, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { random_unsigned_inclusive_range(seed.fork("base"), U::TWO, U::saturating_from(T::MAX)) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, U::exact_from(3), U::MAX, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(Vec, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|(xs, y)| *y < U::exact_from(xs.len() << T::LOG_WIDTH)), ) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_11( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_13( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, U::power_of_2(U::WIDTH - 1), U::MAX), )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_14( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_range(seed, U::ONE, U::power_of_2(U::WIDTH - 1)), )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_15( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, U::power_of_2(U::WIDTH - 1), U::MAX), )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_16( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_range(seed, U::ONE, U::power_of_2(U::WIDTH - 1)), )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_17( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_range(seed, U::ONE, U::power_of_2(U::WIDTH - 2)), )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_18( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, U::TWO, U::MAX, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_19( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed, 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_pair_gen_var_20( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed, 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } // --(Vec, PrimitiveUnsigned, PrimitiveInt) -- pub fn random_primitive_int_vec_unsigned_primitive_int_triple_gen_var_1< T: PrimitiveInt, U: PrimitiveUnsigned, V: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, &random_primitive_ints, )) } // --(Vec, PrimitiveInt, PrimitiveInt) -- pub fn random_primitive_int_vec_primitive_int_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints, )) } // --(Vec, PrimitiveInt, RoundingMode) -- pub fn random_primitive_int_vec_primitive_int_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, T, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_primitive_ints, &random_rounding_modes, )) } pub fn random_primitive_int_vec_primitive_int_rounding_mode_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // --(Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- struct PrimitiveIntVecUnsignedUnsignedTripleGeneratorVar1 { is: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, } impl Iterator for PrimitiveIntVecUnsignedUnsignedTripleGeneratorVar1 { type Item = (Vec, usize, usize); fn next(&mut self) -> Option<(Vec, usize, usize)> { let i = self.is.next().unwrap(); let j = self.is.next().unwrap(); let excess = self.is.next().unwrap(); let xs = (&mut self.xs).take(i * j + excess).collect(); Some((xs, i, j)) } } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, usize, usize)> { Box::new(PrimitiveIntVecUnsignedUnsignedTripleGeneratorVar1 { is: geometric_random_unsigneds( EXAMPLE_SEED.fork("is"), config.get_or("mean_small_n", 2), config.get_or("mean_small_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_2< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_3< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_5< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_primitive_ints, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_6< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_vec_unsigned_unsigned_triple_gen_var_7< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_primitive_ints, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (Vec, Vec) -- pub fn random_primitive_int_vec_pair_gen( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single(random_vecs( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } pub struct PrimitiveIntVecPairLenGenerator1> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecPairLenGenerator1 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(j).collect(), )) } } fn random_primitive_int_vec_pair_gen_var_1_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }) } pub fn random_primitive_int_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec)> { random_primitive_int_vec_pair_gen_var_1_helper(config, EXAMPLE_SEED) } pub fn random_primitive_int_vec_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single(random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } pub fn random_primitive_int_vec_pair_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single(random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|(xs, es)| { !xs.is_empty() && (es.len() > 1 || es.len() == 1 && es[0] > T::ONE) && *es.last().unwrap() != T::ZERO }), ) } struct PrimitiveIntVecPairSameLenGenerator> { phantom: PhantomData<*const T>, lengths: I, xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecPairSameLenGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let len = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(len).collect(), (&mut self.xs).take(len).collect(), )) } } pub fn random_primitive_int_vec_pair_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_pair_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( random_vecs( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn random_primitive_int_vec_pair_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)), )) } pub struct PrimitiveIntVecPairLenGenerator2> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecPairLenGenerator2 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); let mut xs; loop { xs = (&mut self.xs).take(i).collect_vec(); if !slice_test_zero(&xs) { break; } } let mut ys; loop { ys = (&mut self.xs).take(j).collect_vec(); if !slice_test_zero(&ys) { break; } } Some((xs, ys)) } } pub fn random_primitive_int_vec_pair_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator2 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // var 9 is in malachite-nz. pub fn random_primitive_int_vec_pair_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(_, ds)| *ds.last().unwrap() != T::ZERO), ) } pub fn random_primitive_int_vec_pair_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints::(EXAMPLE_SEED.fork("xs")), } .map(|(xs, mut ys)| { ys[0] |= T::ONE; (xs, ys) }), ) } pub fn random_primitive_int_vec_pair_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(xs, ys)| *xs.last().unwrap() != T::ZERO && *ys.last().unwrap() != T::ZERO), ) } pub fn random_primitive_int_vec_pair_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(xs, ys)| *xs.last().unwrap() != T::ZERO && *ys.last().unwrap() != T::ZERO), ) } pub fn random_primitive_int_vec_pair_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let last = xs.last_mut().unwrap(); *last = last.checked_add(T::ONE)?; Some(xs) }), )) } pub fn random_primitive_int_vec_pair_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // vars 16 through 25 are in malachite-nz. pub fn random_primitive_int_vec_pair_gen_var_26( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_pair_gen_var_27( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(xs, ys): &(Vec, Vec)| { (*xs.last().unwrap() != T::ZERO || *ys.last().unwrap() != T::ZERO) && ys[0].odd() }), ) } // var 28 is in malachite-nz. // -- (Vec, Vec, bool) -- pub fn random_primitive_int_vec_primitive_int_vec_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, bool)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(seed.fork("xs")), }, &random_bools, ))) } // -- (Vec, Vec, PrimitiveInt) -- pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_1< T: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_int_vec_pair_gen_var_1_helper(config, seed), &random_primitive_ints, ))) } fn random_primitive_int_vec_pair_gen_var_2_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_2< T: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_int_vec_pair_gen_var_2_helper(config, seed), &random_primitive_ints, ))) } struct PrimitiveIntVecPairLenGenerator3> { phantom: PhantomData<*const T>, lengths: I, xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecPairLenGenerator3 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); let xs = (&mut self.xs).take(i).collect(); let mut ys; loop { ys = (&mut self.xs).take(j).collect_vec(); if !slice_test_zero(&ys) { break; } } Some((xs, ys)) } } fn random_primitive_int_vec_pair_gen_var_3_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator3 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_3< T: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_int_vec_pair_gen_var_3_helper(config, seed), &random_primitive_ints, ))) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_5< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_6< T: PrimitiveInt, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &random_positive_unsigneds, )) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_7< T: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(seed.fork("xs")), }, &random_primitive_ints, ))) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_8< T: PrimitiveInt, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_int_vec_pair_gen_var_1_helper(config, seed), &|seed| random_unsigned_range(seed, 1, U::WIDTH), ))) } pub fn random_primitive_int_vec_primitive_int_vec_primitive_int_triple_gen_var_9< T: PrimitiveInt, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| random_unsigned_range(seed, 1, U::WIDTH), ))) } // -- (Vec, Vec, PrimitiveUnsigned) -- pub struct PrimitiveIntVecPairLenAndIndexGenerator< T: PrimitiveInt, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecPairLenAndIndexGenerator { type Item = (Vec, Vec, usize); fn next(&mut self) -> Option<(Vec, Vec, usize)> { let (i, j, k) = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(j).collect(), k, )) } } pub fn random_primitive_int_vec_primitive_int_vec_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, usize)> { Box::new(PrimitiveIntVecPairLenAndIndexGenerator { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(y)?; let o = o.checked_add(x)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_primitive_int_vec_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, usize)> { Box::new(PrimitiveIntVecPairLenAndIndexGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, i)| { let x = x.checked_add(i)?; Some((x, x, i)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // -- (Vec, Vec, Vec) -- pub struct PrimitiveIntVecTripleXYYLenGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecTripleXYYLenGenerator { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(j).collect(), (&mut self.xs).take(j).collect(), )) } } pub fn random_primitive_int_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub struct PrimitiveIntVecTripleLenGenerator1< T: PrimitiveInt, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecTripleLenGenerator1 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j, k) = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(j).collect(), (&mut self.xs).take(k).collect(), )) } } pub struct PrimitiveIntVecQuadrupleLenGenerator1< T: PrimitiveInt, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecQuadrupleLenGenerator1 { type Item = (Vec, Vec, Vec, Vec); fn next(&mut self) -> Option { let (i, j, k, l) = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(j).collect(), (&mut self.xs).take(k).collect(), (&mut self.xs).take(l).collect(), )) } } pub fn random_primitive_int_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(1)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // vars 4 through 23 are in malachite-nz pub fn random_primitive_int_vec_triple_gen_var_24( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; Some((x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_25( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_26( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y)?; Some((x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } struct PrimitiveIntVecTripleXXXLenGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecTripleXXXLenGenerator { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let i = self.lengths.next().unwrap(); Some(( (&mut self.xs).take(i).collect(), (&mut self.xs).take(i).collect(), (&mut self.xs).take(i).collect(), )) } } pub fn random_primitive_int_vec_triple_gen_var_27( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXXXLenGenerator { phantom: PhantomData, lengths: geometric_random_unsigned_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_28( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXXXLenGenerator { phantom: PhantomData, lengths: geometric_random_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_29( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( random_vecs( EXAMPLE_SEED, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn random_primitive_int_vec_triple_gen_var_30( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_31( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let o = max(x, y).checked_add(o)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } struct PrimitiveIntVecTripleLenGenerator2< T: PrimitiveInt, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for PrimitiveIntVecTripleLenGenerator2 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j, k) = self.lengths.next().unwrap(); let out = (&mut self.xs).take(i).collect(); let mut xs; loop { xs = (&mut self.xs).take(j).collect_vec(); if !slice_test_zero(&xs) { break; } } let mut ys; loop { ys = (&mut self.xs).take(k).collect_vec(); if !slice_test_zero(&ys) { break; } } Some((out, xs, ys)) } } pub fn random_primitive_int_vec_triple_gen_var_32( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(x)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_33( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(max(x, y))?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_34( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(min(x, y))?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_35( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } // vars 36 through 37 are in malachite-nz. pub fn random_primitive_int_vec_triple_gen_var_38( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } pub fn random_primitive_int_vec_triple_gen_var_39( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(y)?; let o = o.checked_add(x)?; Some((o, x, y)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_40( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, )) } pub fn random_primitive_int_vec_triple_gen_var_41( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }), xs: random_primitive_ints::(EXAMPLE_SEED.fork("xs")), } .map(|(x, mut y, z)| { y.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn random_primitive_int_vec_triple_gen_var_42( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let y = y.checked_add(5)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }), xs: random_primitive_ints::(EXAMPLE_SEED.fork("xs")), } .map(|(x, mut y, z)| { y.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn random_primitive_int_vec_triple_gen_var_43( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let q = x.checked_add(3)?; let n = y.checked_add(9)?; let d = z.checked_add(6)?; if n < d { return None; } let q_alt = n - d + 1; if (q_alt << 1) > n || q_alt > d { return None; } let n_alt = q_alt << 1; let d_alt = q_alt; if q >= q_alt && d_alt >= 6 && n_alt >= d_alt + 3 && d_alt >= q_alt { Some((q, n, d)) } else { None } }), xs: random_primitive_ints::(EXAMPLE_SEED.fork("xs")), } .map(|(x, y, mut z)| { z.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn random_primitive_int_vec_triple_gen_var_44( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(r_len, n_len, d_len)| { let d_len = d_len.checked_add(2)?; let r_len = r_len.checked_add(d_len)?; let n_len = n_len.checked_add(d_len)?; Some((r_len, n_len, d_len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter_map(|(r, n, mut d): (Vec, Vec, Vec)| { let last_d = d.last_mut().unwrap(); *last_d = last_d.checked_add(T::ONE)?; Some((r, n, d)) }), ) } // var 45 is in malachite-nz. pub fn random_primitive_int_vec_triple_gen_var_46( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(xs_len, ys_len, zs_len)| { let ys_len = ys_len.checked_add(2)?; let zs_len = zs_len.checked_add(2)?; let xs_len = xs_len.checked_add(ys_len + zs_len - 1)?; Some((xs_len, ys_len, zs_len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter_map(|(mut xs, mut ys, mut zs): (Vec, Vec, Vec)| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(T::ONE)?; let last_y = ys.last_mut().unwrap(); *last_y = last_y.checked_add(T::ONE)?; let last_z = zs.last_mut().unwrap(); *last_z = last_z.checked_add(T::ONE)?; Some((xs, ys, zs)) }), ) } // var 47 is in malachite-nz. // -- (Vec, PrimitiveUnsigned) -- struct UnsignedVecUnsignedPairGeneratorVar1 { log_bases: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, phantom: PhantomData<(T, U)>, } impl Iterator for UnsignedVecUnsignedPairGeneratorVar1 { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let max_count = usize::exact_from(T::WIDTH.div_round(log_base, Ceiling).0); loop { let digit_count = self.ranges.next_in_inclusive_range(0, max_count); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { digits.push(self.ranges.next_bit_chunk(log_base)); } if digits_valid::(log_base, &digits) { return Some((digits, log_base)); } } } } pub fn random_unsigned_vec_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(UnsignedVecUnsignedPairGeneratorVar1:: { log_bases: geometric_random_unsigned_range( EXAMPLE_SEED.fork("log_bases"), 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } pub fn random_unsigned_vec_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new( random_unsigned_vec_unsigned_pair_gen_var_1::(config) .map(|(xs, y)| (xs.into_iter().rev().collect(), y)), ) } struct BasecaseDigitsRandomGenerator< T: ExactFrom + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, > { bases: RandomUnsignedInclusiveRange, digit_counts: GeometricRandomNaturalValues, digits: VariableRangeGenerator, phantom: PhantomData<*const T>, } impl + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom> Iterator for BasecaseDigitsRandomGenerator { type Item = (Vec, U); fn next(&mut self) -> Option<(Vec, U)> { let base = self.bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); let t_base = T::exact_from(base); for _ in 0..digit_count { digits.push(self.digits.next_less_than(t_base)); } Some((digits, base)) } } pub fn random_unsigned_vec_unsigned_pair_gen_var_3< T: ExactFrom + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(BasecaseDigitsRandomGenerator { bases: random_unsigned_inclusive_range( EXAMPLE_SEED.fork("bases"), U::TWO, U::saturating_from(T::MAX), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), digits: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } struct DigitsDesc + PrimitiveUnsigned> { ranges: VariableRangeGenerator, phantom: PhantomData<(T, U)>, } impl, U: Digits + PrimitiveUnsigned> Iterator for DigitsDesc { type Item = (Vec, T); fn next(&mut self) -> Option<(Vec, T)> { let base = self .ranges .next_in_inclusive_range(T::TWO, T::saturating_from(U::MAX)); let max_digits = U::MAX.to_digits_desc(&base); let max_digits_len = max_digits.len(); loop { let digit_count = self.ranges.next_in_inclusive_range(0, max_digits_len); let mut ds = Vec::with_capacity(digit_count); for _ in 0..digit_count { ds.push(self.ranges.next_less_than(base)); } if digit_count < max_digits_len || ds <= max_digits { return Some((ds, base)); } } } } pub fn random_unsigned_vec_unsigned_pair_gen_var_4< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( _config: &GenConfig, ) -> It<(Vec, T)> { Box::new(DigitsDesc:: { ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } pub fn random_unsigned_vec_unsigned_pair_gen_var_5< T: PrimitiveUnsigned + SaturatingFrom, U: Digits + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T)> { Box::new( random_unsigned_vec_unsigned_pair_gen_var_4::(config).map(|(mut xs, base)| { xs.reverse(); (xs, base) }), ) } pub fn random_unsigned_vec_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::MAX), )) } struct PowerOf2DigitsGenerator { log_bases: GeometricRandomNaturalValues, digit_counts: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, phantom: PhantomData<*const T>, } impl Iterator for PowerOf2DigitsGenerator { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { digits.push(self.ranges.next_bit_chunk(log_base)); } Some((digits, log_base)) } } pub fn random_unsigned_vec_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(PowerOf2DigitsGenerator:: { log_bases: geometric_random_unsigned_range( EXAMPLE_SEED.fork("log_bases"), 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_count"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } // vars 8 through 11 are in malachite-nz. // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 2 are in malachite-nz. pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { random_unsigned_inclusive_range(seed, T::ZERO, T::low_mask(T::WIDTH - 1)) .map(|u| (u << 1) | T::ONE) }, &random_primitive_ints, )) } // vars 4 through 6 are in malachite-nz. // -- (Vec, Vec) -- struct UnsignedVecSqrtRemGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, hi_n_bits: RandomUnsignedRange, } impl> Iterator for UnsignedVecSqrtRemGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (out_len, len) = self.lengths.next().unwrap(); let out = (&mut self.xs).take(out_len).collect(); let mut ns: Vec = (&mut self.xs).take(len).collect(); let n_hi = &mut ns[(usize::exact_from(out_len) << 1) - 1]; n_hi.mod_power_of_2_assign(T::WIDTH - 2); *n_hi |= self.hi_n_bits.next().unwrap() << (T::WIDTH - 2); Some((out, ns)) } } pub fn random_unsigned_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecSqrtRemGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let out_len = x.checked_add(2)?; let len: usize = out_len.arithmetic_checked_shl(1)?; let len = len.checked_add(y)?; Some((out_len, len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), hi_n_bits: random_unsigned_range(EXAMPLE_SEED.fork("hi_n_bits"), T::ONE, T::exact_from(4)), }) } struct UnsignedVecSqrtGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for UnsignedVecSqrtGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (out_len, len) = self.lengths.next().unwrap(); let out = (&mut self.xs).take(out_len).collect(); let mut ns: Vec = (&mut self.xs).take(len).collect(); let hi_n = ns.last_mut().unwrap(); if *hi_n == T::ZERO { *hi_n = T::ONE; } Some((out, ns)) } } pub fn random_unsigned_vec_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecSqrtGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let in_len = x.checked_add(1)?; let mut out_len: usize = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; Some((out_len, in_len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // vars 3 through 4 are in malachite-nz. pub fn random_unsigned_vec_pair_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::power_of_2(T::WIDTH - 1), T::MAX), &random_primitive_ints, ) .map(|(n, d_1, d_0)| (n, vec![d_0, d_1])), ) } // -- (Vec, Vec, PrimitiveUnsigned) -- pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( seed.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }, &random_positive_unsigneds, ))) } // var 2 is in malachite-nz. // -- (Vec, Vec, Vec) -- // vars 1 through 8 are in malachite-nz. struct UnsignedVecSqrtRemGenerator3> { pub phantom: PhantomData<*const T>, pub lengths: I, pub xs: RandomPrimitiveInts, } impl> Iterator for UnsignedVecSqrtRemGenerator3 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (out_len, rs_len, len) = self.lengths.next().unwrap(); let out = (&mut self.xs).take(out_len).collect(); let rs = (&mut self.xs).take(rs_len).collect(); let mut ns: Vec = (&mut self.xs).take(len).collect(); let hi_n = ns.last_mut().unwrap(); if *hi_n == T::ZERO { *hi_n = T::ONE; } Some((out, rs, ns)) } } pub fn random_unsigned_vec_triple_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecSqrtRemGenerator3 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let in_len = x.checked_add(1)?; let mut out_len: usize = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; let rem_len = in_len.checked_add(z)?; Some((out_len, rem_len, in_len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_unsigned_vec_triple_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(x, y)| y >= 2 && x >= y - 2), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_pairs( seed, &|seed_2| { random_unsigned_inclusive_range(seed_2, T::power_of_2(T::WIDTH - 1), T::MAX) }, &random_primitive_ints, ) }, ) .map(|((q, n), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // var 11 is in malachite-nz. // -- large types -- pub fn random_large_type_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, T, T)> { reshape_2_2_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_int_vec_pair_gen_var_1_helper(config, seed), &|seed| random_pairs_from_single(random_primitive_ints(seed)), ))) } struct UnsignedVecSqrtRemGenerator2 { pub phantom: PhantomData<*const T>, pub lengths: GeometricRandomNaturalValues, pub xs: RandomPrimitiveInts, } impl Iterator for UnsignedVecSqrtRemGenerator2 { type Item = (Vec, Vec, u64, bool); fn next(&mut self) -> Option<(Vec, Vec, u64, bool)> { let len = self.lengths.next().unwrap(); let n = len.shr_round(1, Ceiling).0; let out = (&mut self.xs).take(n).collect(); let mut ns: Vec = (&mut self.xs).take(len).collect(); let last = ns.last_mut().unwrap(); if *last == T::ZERO { *last = T::ONE; } let shift = last.leading_zeros() >> 1; Some((out, ns, shift, len.odd())) } } pub fn random_large_type_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, u64, bool)> { Box::new(UnsignedVecSqrtRemGenerator2 { phantom: PhantomData, lengths: geometric_random_unsigned_range::( EXAMPLE_SEED.fork("lengths"), 9, usize::MAX, config.get_or("mean_length_n", 12), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_large_type_gen_var_3( config: &GenConfig, ) -> It<(Vec, U, U, Vec)> { Box::new( random_quadruples_xyyx::<_, _, U, _>( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } pub fn random_large_type_gen_var_4( config: &GenConfig, ) -> It<(Vec, U, U, Vec)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { random_vecs( seed, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // vars 5 through 8 are in malachite-nz #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, Vec, bool)> { reshape_3_1_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), xs: random_primitive_ints(seed.fork("xs")), }, &random_bools, ))) } // vars 10 through 21 are in malachite-nz. pub fn random_large_type_gen_var_22( config: &GenConfig, ) -> It<(RationalSequence, usize, T, T)> { Box::new( random_quadruples_xyzz( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, &random_primitive_ints, ) .filter(|&(ref xs, index, _, _)| { if let Some(len) = xs.len() { index < len } else { true } }), ) } // vars 23 through 26 are in malachite-nz. pub fn random_large_type_gen_var_27( config: &GenConfig, ) -> It<(bool, Vec, bool, Vec)> { Box::new(random_quadruples_xyxy( EXAMPLE_SEED, &random_bools, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)) }, )) } ================================================ FILE: malachite-base/src/test_util/generators/special_random.rs ================================================ // Copyright © 2026 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 crate::bools::random::random_bools; use crate::chars::constants::NUMBER_OF_CHARS; use crate::chars::random::{ graphic_weighted_random_ascii_chars, graphic_weighted_random_char_inclusive_range, graphic_weighted_random_char_range, graphic_weighted_random_chars, }; use crate::iterators::{NonzeroValues, with_special_value}; use crate::num::arithmetic::traits::{ ArithmeticCheckedShl, DivRound, Parity, PowerOf2, ShrRound, UnsignedAbs, }; use crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::options::random::{ random_from_sci_string_options, random_to_sci_options, }; use crate::num::conversion::string::options::{FromSciStringOptions, ToSciOptions}; use crate::num::conversion::traits::{ ConvertibleFrom, ExactFrom, HasHalf, JoinHalves, RoundingFrom, SaturatingFrom, SplitInHalf, WrappingFrom, WrappingInto, }; use crate::num::factorization::traits::IsPrime; use crate::num::float::NiceFloat; use crate::num::logic::traits::{BitAccess, BitBlockAccess, LeadingZeros}; use crate::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, GeometricRandomSigneds, geometric_random_natural_signeds, geometric_random_nonzero_signeds, geometric_random_positive_unsigneds, geometric_random_signed_inclusive_range, geometric_random_signed_range, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigned_range, geometric_random_unsigneds, }; use crate::num::random::striped::{ StripedBitSource, StripedRandomSigneds, StripedRandomUnsignedBitChunks, StripedRandomUnsignedInclusiveRange, get_striped_bool_vec, get_striped_unsigned_vec, striped_random_bool_vecs, striped_random_bool_vecs_length_inclusive_range, striped_random_bool_vecs_min_length, striped_random_fixed_length_bool_vecs, striped_random_natural_signeds, striped_random_negative_signeds, striped_random_nonzero_signeds, striped_random_positive_signeds, striped_random_positive_unsigneds, striped_random_signed_inclusive_range, striped_random_signed_range, striped_random_signeds, striped_random_unsigned_bit_chunks, striped_random_unsigned_inclusive_range, striped_random_unsigned_range, striped_random_unsigned_vecs, striped_random_unsigned_vecs_min_length, striped_random_unsigneds, }; use crate::num::random::{ RandomPrimitiveFloatInclusiveRange, VariableRangeGenerator, random_finite_primitive_floats, random_nonzero_finite_primitive_floats, random_positive_finite_primitive_floats, random_primitive_float_inclusive_range, random_primitive_float_range, random_primitive_floats, random_unsigneds_less_than, }; use crate::random::{EXAMPLE_SEED, Seed}; use crate::rational_sequences::RationalSequence; use crate::rational_sequences::random::random_rational_sequences; use crate::rounding_modes::RoundingMode::{self, *}; use crate::rounding_modes::random::{RandomRoundingModes, random_rounding_modes}; use crate::slices::slice_test_zero; use crate::strings::random::random_strings_using_chars; use crate::test_util::extra_variadic::{ Union3, random_duodecuples_from_single, random_octuples_from_single, random_quadruples_from_single, random_quadruples_xxxy, random_quadruples_xxyx, random_quadruples_xyxy, random_quadruples_xyyx, random_quadruples_xyyz, random_quadruples_xyzz, random_sextuples_from_single, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyx, random_triples_xyy, random_union3s, }; use crate::test_util::generators::common::{ GenConfig, It, reshape_1_2_to_3, reshape_2_1_to_3, reshape_2_2_to_4, reshape_3_1_to_4, }; use crate::test_util::generators::{ digits_valid, float_rounding_mode_filter_var_1, get_two_highest, large_exponent, reduce_to_fit_add_mul_signed, reduce_to_fit_add_mul_unsigned, reduce_to_fit_sub_mul_signed, reduce_to_fit_sub_mul_unsigned, round_to_multiple_of_power_of_2_filter_map, round_to_multiple_signed_filter_map, round_to_multiple_unsigned_filter_map, shift_integer_mantissa_and_exponent, signed_assign_bits_valid, smallest_invalid_value, unsigned_assign_bits_valid, }; use crate::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use crate::tuples::random::{random_ordered_unique_pairs, random_pairs, random_pairs_from_single}; use crate::unions::Union2; use crate::unions::random::random_union2s; use itertools::Itertools; use itertools::repeat_n; use std::cmp::{Ordering::*, max, min}; use std::collections::HashMap; use std::marker::PhantomData; // -- char -- pub fn special_random_char_gen(config: &GenConfig) -> It { Box::new(graphic_weighted_random_chars( EXAMPLE_SEED, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), )) } #[allow(unstable_name_collisions)] pub fn special_random_char_gen_var_1(config: &GenConfig) -> It { Box::new(graphic_weighted_random_char_range( EXAMPLE_SEED, char::MIN, char::MAX, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), )) } #[allow(unstable_name_collisions)] pub fn special_random_char_gen_var_2(config: &GenConfig) -> It { Box::new(graphic_weighted_random_char_inclusive_range( EXAMPLE_SEED, '\u{1}', char::MAX, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), )) } // -- (char, char) -- pub fn special_random_char_pair_gen(config: &GenConfig) -> It<(char, char)> { Box::new(random_pairs_from_single(graphic_weighted_random_chars( EXAMPLE_SEED, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ))) } // -- (FromSciStringOptions, PrimitiveUnsigned> -- pub fn special_random_from_sci_string_options_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(FromSciStringOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &random_from_sci_string_options, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_stripe_n", T::WIDTH), config.get_or("mean_stripe_d", 1), ) }, )) } // -- PrimitiveFloat -- pub fn special_random_primitive_float_gen(_config: &GenConfig) -> It { Box::new(random_primitive_floats(EXAMPLE_SEED)) } pub fn special_random_primitive_float_gen_var_1(_config: &GenConfig) -> It { Box::new(random_primitive_float_range( EXAMPLE_SEED, T::NEGATIVE_ONE / T::TWO, T::INFINITY, )) } struct SpecialRandomPositiveNaturalFloats { exponents: GeometricRandomSignedRange, mantissas: StripedRandomUnsignedBitChunks, phantom: PhantomData, } impl Iterator for SpecialRandomPositiveNaturalFloats { type Item = T; fn next(&mut self) -> Option { let exponent = self.exponents.next().unwrap(); let mut mantissa = self.mantissas.next().unwrap(); if exponent != 0 { mantissa.set_bit(T::MANTISSA_WIDTH); } else if mantissa == 0 { mantissa = 1; } Some(T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap()) } } fn special_random_positive_natural_floats( seed: Seed, mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> SpecialRandomPositiveNaturalFloats { SpecialRandomPositiveNaturalFloats { exponents: geometric_random_signed_range( seed.fork("exponents"), 0, i64::power_of_2(T::EXPONENT_WIDTH - 1) - i64::wrapping_from(T::MANTISSA_WIDTH) - 1, mean_exponent_numerator, mean_exponent_denominator, ), mantissas: striped_random_unsigned_bit_chunks( seed.fork("mantissas"), T::MANTISSA_WIDTH + 1, mean_stripe_numerator, mean_stripe_denominator, ), phantom: PhantomData, } } pub fn special_random_primitive_float_gen_var_2(config: &GenConfig) -> It { Box::new(with_special_value(EXAMPLE_SEED, T::ZERO, 1, 100, &|seed| { special_random_positive_natural_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) })) } pub fn special_random_primitive_float_gen_var_3(_config: &GenConfig) -> It { Box::new(random_positive_finite_primitive_floats::(EXAMPLE_SEED).filter(|f| !f.is_integer())) } pub fn special_random_primitive_float_gen_var_4(_config: &GenConfig) -> It { Box::new( random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ) .map(|f| f.floor() - T::ONE / T::TWO), ) } pub fn special_random_primitive_float_gen_var_5(config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { with_special_value(seed, T::ZERO, 1, 100, &|seed_2| { special_random_positive_natural_floats( seed_2, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) }) }, &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn special_random_primitive_float_gen_var_6(_config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_positive_finite_primitive_floats::(seed).filter(|f| !f.is_integer()), &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn special_random_primitive_float_gen_var_7(_config: &GenConfig) -> It { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_primitive_float_inclusive_range::( seed, T::ONE, T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ) .map(|f| f.floor() - T::ONE / T::TWO) }, &random_bools, ) .map(|(f, b)| if b { f } else { -f }), ) } pub fn special_random_primitive_float_gen_var_8(_config: &GenConfig) -> It { Box::new(random_finite_primitive_floats(EXAMPLE_SEED)) } pub fn special_random_primitive_float_gen_var_9(_config: &GenConfig) -> It { Box::new( random_primitive_floats::(EXAMPLE_SEED).filter(|&f| !f.is_nan() && f != T::INFINITY), ) } pub fn special_random_primitive_float_gen_var_10(_config: &GenConfig) -> It { Box::new( random_primitive_floats::(EXAMPLE_SEED) .filter(|&f| !f.is_nan() && f != T::NEGATIVE_INFINITY), ) } pub fn special_random_primitive_float_gen_var_11(_config: &GenConfig) -> It { Box::new(random_primitive_floats::(EXAMPLE_SEED).filter(|&f| !f.is_nan())) } pub fn special_random_primitive_float_gen_var_12(_config: &GenConfig) -> It { Box::new(random_nonzero_finite_primitive_floats(EXAMPLE_SEED)) } pub fn special_random_primitive_float_gen_var_13< T: PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It { Box::new( striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|n| T::rounding_from(n, Down).0), ) } pub fn special_random_primitive_float_gen_var_14< T: PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >( config: &GenConfig, ) -> It { Box::new( striped_random_signeds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|n| T::rounding_from(n, Down).0), ) } pub fn special_random_primitive_float_gen_var_15< T: PrimitiveFloat, U: ConvertibleFrom + PrimitiveInt, >( _config: &GenConfig, ) -> It { Box::new(random_primitive_floats::(EXAMPLE_SEED).filter(|&f| !U::convertible_from(f))) } pub fn special_random_primitive_float_gen_var_16< T: PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned, >( _config: &GenConfig, ) -> It { let limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( random_primitive_float_inclusive_range::(EXAMPLE_SEED, T::ONE, limit) .map(|f| f.floor() - T::ONE / T::TWO), ) } pub fn special_random_primitive_float_gen_var_17< T: PrimitiveFloat + RoundingFrom, U: PrimitiveSigned, >( _config: &GenConfig, ) -> It { let min_limit = min( NiceFloat(-T::rounding_from(U::MIN, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; let max_limit = min( NiceFloat(T::rounding_from(U::MAX, Down).0), NiceFloat( T::from_integer_mantissa_and_exponent(1, i64::wrapping_from(T::MANTISSA_WIDTH)) .unwrap(), ), ) .0; Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_primitive_float_inclusive_range::(seed, T::ONE, max_limit) .map(|f| f.floor() - T::ONE / T::TWO) }, &|seed| { random_primitive_float_inclusive_range::(seed, T::ONE, min_limit) .map(|f| T::ONE / T::TWO - f.floor()) }, ) .map(Union2::unwrap), ) } pub fn special_random_primitive_float_gen_var_18(_config: &GenConfig) -> It { Box::new(random_positive_finite_primitive_floats::(EXAMPLE_SEED)) } pub fn special_random_primitive_float_gen_var_19(_config: &GenConfig) -> It { Box::new(random_primitive_float_inclusive_range( EXAMPLE_SEED, T::ZERO, T::power_of_2(T::MAX_EXPONENT), )) } // -- (PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_primitive_float_pair_gen( _config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs_from_single(random_primitive_floats( EXAMPLE_SEED, ))) } pub fn special_random_primitive_float_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs_from_single( random_primitive_floats::(EXAMPLE_SEED).filter(|&f| !f.is_nan()), )) } // -- (PrimitiveFloat, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_primitive_float_triple_gen( _config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_from_single(random_primitive_floats( EXAMPLE_SEED, ))) } // -- (PrimitiveFloat, PrimitiveSigned) -- pub fn special_random_primitive_float_signed_pair_gen( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_signeds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_signed_pair_gen_var_1< T: PrimitiveFloat, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_finite_primitive_floats, &|seed| { geometric_random_signeds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(T, i64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_primitive_float_range(seed, T::ONE, T::TWO), &|seed| { geometric_random_signed_inclusive_range( seed, T::MIN_EXPONENT, T::MAX_EXPONENT, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, ) .filter(|&(m, e)| m.precision() <= T::max_precision_for_sci_exponent(e)), ) } pub fn special_random_primitive_float_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(T, i64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_float_range(seed, T::ONE, T::TWO), &|seed| { geometric_random_signeds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_signed_pair_gen_var_4< T: PrimitiveFloat, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_signeds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_primitive_float_signed_unsigned_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_signeds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveUnsigned) -- pub fn special_random_primitive_float_unsigned_pair_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_finite_primitive_floats, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| random_primitive_float_range(seed, T::ONE, T::TWO), &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_unsigned_pair_gen_var_3< T: PrimitiveFloat, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_positive_finite_primitive_floats, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_primitive_float_unsigned_pair_gen_var_4< T: PrimitiveFloat, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_1< T: PrimitiveFloat, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &random_positive_finite_primitive_floats, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| random_primitive_float_range(seed, T::ONE, T::TWO), &|seed| { geometric_random_unsigneds( seed, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, &random_rounding_modes, )) } // var 3 is in malachite-float. // -- (PrimitiveFloat, RoundingMode) -- pub fn special_random_primitive_float_rounding_mode_pair_gen_var_1( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &random_finite_primitive_floats, &random_rounding_modes, ) .filter(float_rounding_mode_filter_var_1), ) } pub fn special_random_primitive_float_rounding_mode_pair_gen_var_2( _config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &random_primitive_floats::, &random_rounding_modes, ) .filter(|&(f, rm)| rm != Exact || f.is_integer()), ) } pub fn special_random_primitive_float_rounding_mode_pair_gen_var_3< T: PrimitiveFloat + RoundingFrom, U: ConvertibleFrom + PrimitiveInt, >( _config: &GenConfig, ) -> It<(T, RoundingMode)> { let f_min = T::rounding_from(U::MIN, Down).0; let f_max = T::rounding_from(U::MAX, Down).0; Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_primitive_floats::(seed).filter(|f| !f.is_nan()), &random_rounding_modes, ) .filter(move |&(f, rm)| match rm { Up => f >= f_min && f <= f_max, Ceiling => f <= f_max, Floor => f >= f_min, Down | Nearest => true, Exact => U::convertible_from(f), }), ) } // -- PrimitiveInt -- pub fn special_random_primitive_int_gen_var_1< T: PrimitiveInt + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >( _config: &GenConfig, ) -> It { Box::new( random_primitive_float_range( EXAMPLE_SEED, U::rounding_from(T::MIN, Down).0, U::rounding_from(T::MAX, Down).0, ) .map(|f| T::rounding_from(f, Down).0), ) } // -- PrimitiveSigned -- pub fn special_random_signed_gen(config: &GenConfig) -> It { Box::new(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_1(config: &GenConfig) -> It { Box::new(special_random_signed_gen(config).filter(|&x| x != T::MIN)) } pub fn special_random_signed_gen_var_2(config: &GenConfig) -> It { Box::new(striped_random_natural_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_3(config: &GenConfig) -> It { Box::new( striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter(|&x| x != T::ZERO && x != T::NEGATIVE_ONE), ) } pub fn special_random_signed_gen_var_4(config: &GenConfig) -> It { Box::new(striped_random_negative_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_5(config: &GenConfig) -> It { Box::new(striped_random_nonzero_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_6< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: ConvertibleFrom + PrimitiveFloat, >( config: &GenConfig, ) -> It { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_signed_inclusive_range::( seed, S::saturating_from(V::SMALLEST_UNREPRESENTABLE_UINT), S::MAX, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_signed_inclusive_range::( seed, S::MIN, S::saturating_from(V::SMALLEST_UNREPRESENTABLE_UINT).saturating_neg(), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(Union2::unwrap) .filter(|&x| !V::convertible_from(x)), ) } pub fn special_random_signed_gen_var_7< U: PrimitiveUnsigned + WrappingFrom, S: TryFrom> + PrimitiveSigned + WrappingFrom, V: PrimitiveFloat + RoundingFrom, >( config: &GenConfig, ) -> It { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_signed_inclusive_range::( seed, S::exact_from(V::SMALLEST_UNREPRESENTABLE_UINT), S::MAX, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter_map(|a| { let f = V::rounding_from(a, Down).0; let a = S::try_from(NiceFloat(f)).ok()?; let b = S::try_from(NiceFloat(f.next_higher())).ok()?; let diff = b - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }) }, &|seed| { striped_random_signed_inclusive_range::( seed, S::MIN, S::exact_from(V::SMALLEST_UNREPRESENTABLE_UINT) .checked_neg() .unwrap(), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter_map(|a| { let f = V::rounding_from(a, Down).0; let a = S::try_from(NiceFloat(f)).ok()?; let b = S::try_from(NiceFloat(f.next_lower())).ok()?; let diff = a - b; if diff.even() { // This happens almost always Some(a - (diff >> 1)) } else { None } }) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_gen_var_8< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It { let limit = S::wrapping_from(U::wrapping_from(S::MAX).floor_sqrt()); Box::new(striped_random_signed_inclusive_range::( EXAMPLE_SEED, -limit, limit, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_9(config: &GenConfig) -> It { Box::new(striped_random_signed_inclusive_range::( EXAMPLE_SEED, T::MIN_EXPONENT, T::MAX_EXPONENT, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_signed_gen_var_10(config: &GenConfig) -> It { Box::new( striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter(|&x| x != T::ZERO && x != T::MIN), ) } pub fn special_random_signed_gen_var_11< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It { Box::new( striped_random_signed_inclusive_range::( EXAMPLE_SEED, S::ZERO, S::low_mask(S::WIDTH - 2), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | S::ONE), ) } // -- (PrimitiveSigned, PrimitiveSigned) -- pub fn special_random_signed_pair_gen(config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_signed_pair_gen_var_1(config: &GenConfig) -> It<(T, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, &|seed| { random_pairs_from_single(striped_random_negative_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_signed_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_signed_stripe_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } pub fn special_random_signed_pair_gen_var_3(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(mut x, y)| { x.round_to_multiple_assign(y, Down); if x == T::MIN && y == T::NEGATIVE_ONE { None } else { Some((x, y)) } }), ) } pub fn special_random_signed_pair_gen_var_4(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|&(x, y)| x != T::MIN || y != T::NEGATIVE_ONE), ) } pub fn special_random_signed_pair_gen_var_5(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|&(x, y)| !x.divisible_by(y)), ) } pub fn special_random_signed_pair_gen_var_6(config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_signed_pair_gen_var_7(config: &GenConfig) -> It<(T, T)> { Box::new(random_pairs_from_single(striped_random_natural_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_signed_pair_gen_var_8< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It<(S, S)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_signed_inclusive_range::( seed, S::ZERO, S::low_mask(S::WIDTH - 2), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | S::ONE) }, )) } pub fn special_random_signed_pair_gen_var_9< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( config: &GenConfig, ) -> It<(S, S)> { Box::new( random_pairs_from_single( striped_random_signed_inclusive_range::( EXAMPLE_SEED, S::ZERO, S::low_mask(S::WIDTH - 2), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | S::ONE), ) .filter(|&(a, b): &(S, S)| a.unsigned_abs().coprime_with(b.unsigned_abs())), ) } pub fn special_random_signed_pair_gen_var_10< U: PrimitiveUnsigned, S: PrimitiveSigned + UnsignedAbs, >( config: &GenConfig, ) -> It<(S, S)> { Box::new( random_pairs_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter(|&(x, y): &(S, S)| x.unsigned_abs().coprime_with(y.unsigned_abs())), ) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn special_random_signed_triple_gen(config: &GenConfig) -> It<(T, T, T)> { Box::new(random_triples_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, z)| reduce_to_fit_add_mul_signed(x, y, z)), ) } pub fn special_random_signed_triple_gen_var_2( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, z)| reduce_to_fit_sub_mul_signed(x, y, z)), ) } pub fn special_random_signed_triple_gen_var_3( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_triples_from_single(striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, &|seed| { random_triples_from_single(striped_random_negative_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_triple_gen_var_4< U: PrimitiveUnsigned + WrappingFrom + WrappingInto, S: PrimitiveSigned + UnsignedAbs, >( config: &GenConfig, ) -> It<(S, S, S)> { Box::new( random_triples_from_single(striped_random_signeds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, m)| { if m == S::ZERO { let min = min(x, y); (min, min, m) } else if x <= y { let adjusted_diff = U::wrapping_from(y.wrapping_sub(x)) .round_to_multiple(m.unsigned_abs(), Down) .0; ( x, (U::wrapping_from(x).wrapping_add(adjusted_diff)).wrapping_into(), m, ) } else { let adjusted_diff = U::wrapping_from(x.wrapping_sub(y)) .round_to_multiple(m.unsigned_abs(), Down) .0; ( (U::wrapping_from(y).wrapping_add(adjusted_diff)).wrapping_into(), y, m, ) } }), ) } pub fn special_random_signed_triple_gen_var_5( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_signeds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter(|&(x, y, m)| !x.eq_mod(y, m)), ) } pub fn special_random_signed_triple_gen_var_6< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It<(S, S, S)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_signed_inclusive_range::( seed, S::ZERO, S::low_mask(S::WIDTH - 2), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | S::ONE) }, )) } pub fn special_random_signed_triple_gen_var_7< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It<(S, S, S)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_signed_inclusive_range::( seed, S::ZERO, S::low_mask(S::WIDTH - 2), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | S::ONE) }, )) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveSigned) -- pub fn special_random_signed_quadruple_gen( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new(random_quadruples_from_single(striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_signed_signed_signed_unsigned_quadruple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, T, T, U)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_signed_signed_unsigned_triple_gen_var_1< U: PrimitiveUnsigned + WrappingFrom + WrappingInto, S: PrimitiveSigned, >( config: &GenConfig, ) -> It<(S, S, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_pow_n", 32), config.get_or("mean_pow_d", 1), ) }, ) .map(|(x, y, pow)| { if pow >= S::WIDTH { (x, x, pow) } else if x <= y { let adjusted_diff = U::wrapping_from(y.wrapping_sub(x)) .round_to_multiple_of_power_of_2(pow, Down) .0; ( x, (U::wrapping_from(x).wrapping_add(adjusted_diff)).wrapping_into(), pow, ) } else { let adjusted_diff = U::wrapping_from(x.wrapping_sub(y)) .round_to_multiple_of_power_of_2(pow, Down) .0; ( (U::wrapping_from(y).wrapping_add(adjusted_diff)).wrapping_into(), y, pow, ) } }), ) } pub fn special_random_signed_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_signed_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter(|&(x, y, pow)| !x.eq_mod_power_of_2(y, pow)), ) } pub fn special_random_signed_signed_unsigned_triple_gen_var_4< T: PrimitiveSigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveSigned, RoundingMode) -- struct SignedSignedRoundingModeTripleGenerator { xs: StripedRandomSigneds, rms: RandomRoundingModes, } impl Iterator for SignedSignedRoundingModeTripleGenerator { type Item = (T, T, RoundingMode); fn next(&mut self) -> Option<(T, T, RoundingMode)> { let mut x; let mut y; loop { x = self.xs.next().unwrap(); loop { y = self.xs.next().unwrap(); if y != T::ZERO { break; } } if x != T::MIN || y != T::NEGATIVE_ONE { break; } } let rm = self.rms.next().unwrap(); if rm == Exact { x.round_to_multiple_assign(y, Down); } Some((x, y, rm)) } } pub fn special_random_signed_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new(SignedSignedRoundingModeTripleGenerator { xs: striped_random_signeds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), rms: random_rounding_modes(EXAMPLE_SEED.fork("rms")), }) } pub fn special_random_signed_signed_rounding_mode_triple_gen_var_2< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >( config: &GenConfig, ) -> It<(S, S, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_nonzero_signeds( seed, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_signed_filter_map(x, y, rm)), ) } pub fn special_random_signed_signed_rounding_mode_triple_gen_var_3< T: PrimitiveSigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { rm != Exact || pow <= U::ZERO || x.divisible_by_power_of_2(pow.exact_into()) }), ) } pub fn special_random_signed_signed_rounding_mode_triple_gen_var_4< T: PrimitiveSigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { let pow: i64 = pow.exact_into(); rm != Exact || pow >= 0 || x.divisible_by_power_of_2(pow.unsigned_abs()) }), ) } // -- (PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_signed_unsigned_pair_gen( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", U::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| random_unsigneds_less_than(seed, T::WIDTH), )) } pub fn special_random_signed_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed| { striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { striped_random_unsigned_range( seed_2, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed| { striped_random_negative_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_negative_signeds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { striped_random_unsigned_range( seed_2, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_natural_signeds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_pair_gen_var_5< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_natural_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_7< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_large_signed_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_signed_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter(|&(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn special_random_signed_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn special_random_signed_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_natural_signeds::( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_signeds::( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { striped_random_unsigned_inclusive_range( seed_2, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_pair_gen_var_11< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It<(S, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_signed_range::( seed_2, S::MIN + S::ONE, S::ONE, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_signeds::( seed_2, config.get_or("mean_large_unsigned_stripe_n", S::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed_2| { striped_random_unsigned_range( seed_2, 0, S::WIDTH, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_pair_gen_var_12< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(S, V)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signed_inclusive_range::( seed, if S::WIDTH <= u64::WIDTH { S::MIN } else { -S::exact_from(u64::MAX) }, S::saturating_from(u64::MAX), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_13( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_14( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed| { striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed| { striped_random_negative_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | U::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_pair_gen_var_15< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(S, V)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signed_range::( seed, S::MIN + S::ONE, S::ZERO, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_signed_unsigned_pair_gen_var_16( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveUnsigned, bool) -- pub fn random_signed_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, bool)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_signeds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(x, y)| (x, y, x < T::ZERO)) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_signeds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| random_unsigneds_less_than(seed_2, T::WIDTH), ) .map(|(x, y)| (x, y, x >= T::ZERO)) }, ) .map(Union2::unwrap), ) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_signed_unsigned_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_signed_unsigned_unsigned_triple_gen_var_2< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(S, V, V)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_triples_xyy( seed, &|seed_2| { striped_random_positive_signeds( seed_2, config.get_or("mean_large_stripe_n", S::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }) }, &|seed| { random_triples( seed, &|seed_2| { striped_random_signed_range::( seed_2, S::MIN, S::ZERO, config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed_2| { striped_random_unsigned_range( seed_2, V::ZERO, V::exact_from(S::WIDTH), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(x, y, z): (S, V, V)| y.checked_add(z).map(|new_z| (x, y, new_z))) }, ) .map(Union2::unwrap), ) } pub fn special_random_signed_unsigned_unsigned_triple_gen_var_3< T: PrimitiveSigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // -- (PrimitiveSigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_signed_unsigned_unsigned_unsigned_quadruple_gen_var_1< T: PrimitiveSigned + UnsignedAbs, U: BitBlockAccess + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, u64, u64, U)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed_2| { striped_random_signeds( seed_2, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed_2| { striped_random_unsigneds( seed_2, config.get_or("mean_large_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_stripe_d", 1), ) }, ) .filter_map(|(x, y, z, w)| { let (y, z) = if y <= z { (y, z) } else { (z, y) }; if signed_assign_bits_valid(x, y, z, w) { Some((x, y, z, w)) } else { None } }), ) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, pow, rm)| round_to_multiple_of_power_of_2_filter_map(x, pow, rm)), ) } pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, y, rm)| rm != Exact || x.divisible_by_power_of_2(y.exact_into())), ) } // vars 3 through 5 are in malachite-float. pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_6< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } // -- (PrimitiveSigned, RoundingMode) -- pub fn special_random_signed_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_signed_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_signed_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter(|&x| x != T::MIN) }, &random_rounding_modes, )) } pub fn special_random_signed_rounding_mode_pair_gen_var_3( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter(|&x| x != T::MIN) }, &random_rounding_modes, )) } pub fn special_random_signed_rounding_mode_pair_gen_var_4< T: PrimitiveSigned, U: ConvertibleFrom + PrimitiveFloat, >( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, ) .filter(move |&(n, rm)| rm != Exact || U::convertible_from(n)), ) } // -- (PrimitiveUnsigned, ToSciOptions) -- pub fn special_random_signed_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, )) } pub fn special_random_signed_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_signeds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (PrimitiveSigned, Vec) -- struct SignedBoolVecPairGeneratorVar1 { xs: StripedRandomSigneds, striped_bit_source: StripedBitSource, } impl Iterator for SignedBoolVecPairGeneratorVar1 { type Item = (T, Vec); fn next(&mut self) -> Option<(T, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec( &mut self.striped_bit_source, u64::exact_from(x.to_bits_asc().len()), ); Some((x, bs)) } } pub fn special_random_signed_bool_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(T, Vec)> { Box::new(SignedBoolVecPairGeneratorVar1 { xs: striped_random_signeds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // -- PrimitiveUnsigned -- pub fn special_random_unsigned_gen(config: &GenConfig) -> It { Box::new(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_1(config: &GenConfig) -> It { Box::new(striped_random_positive_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_2(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, NUMBER_OF_CHARS, config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_3(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, 1, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_4< T: PrimitiveInt, U: PrimitiveUnsigned + SaturatingFrom, >( config: &GenConfig, ) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, U::TWO, U::saturating_from(T::MAX), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_5(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_6(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, T::ZERO, T::exact_from(36), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_7(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::exact_from(36), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_8(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, T::WIDTH + 1, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_9(config: &GenConfig) -> It { Box::new( random_union3s( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, b'0', b'9', config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, b'a', b'z', config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, b'A', b'Z', config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, ) .map(Union3::unwrap), ) } pub fn special_random_unsigned_gen_var_10(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::power_of_2(T::WIDTH - 1), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_11(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, T::LARGEST_ORDERED_REPRESENTATION, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_12(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, T::ZERO, T::power_of_2(T::WIDTH - 1) + T::ONE, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_13(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, T::WIDTH, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_14(config: &GenConfig) -> It { Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, T::WIDTH - 1, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_15(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::power_of_2(T::WIDTH - 2), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_16< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >( config: &GenConfig, ) -> It { Box::new( striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::saturating_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter(|&x| !U::convertible_from(x)), ) } pub fn special_random_unsigned_gen_var_17< T: TryFrom> + PrimitiveUnsigned, U: PrimitiveFloat + RoundingFrom, >( config: &GenConfig, ) -> It { Box::new( striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::exact_from(U::SMALLEST_UNREPRESENTABLE_UINT), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .filter_map(|a| { let f = U::rounding_from(a, Down).0; let a = T::try_from(NiceFloat(f)).ok()?; let b = T::try_from(NiceFloat(f.next_higher())).ok()?; let diff = b - a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn special_random_unsigned_gen_var_18(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::ZERO, T::MAX.floor_sqrt(), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_19(config: &GenConfig) -> It { Box::new( striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE), ) } pub fn special_random_unsigned_gen_var_20(config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_factorial); Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, limit, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_21(config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_double_factorial); Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, limit, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_22(config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_subfactorial); Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, limit, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_23(config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_primorial); Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, limit, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_24(config: &GenConfig) -> It { let limit = smallest_invalid_value(T::checked_product_of_first_n_primes); Box::new(striped_random_unsigned_range( EXAMPLE_SEED, 0, limit, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), )) } pub fn special_random_unsigned_gen_var_25( config: &GenConfig, ) -> It { Box::new( striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) .filter(T::is_prime), ) } pub fn special_random_unsigned_gen_var_26(config: &GenConfig) -> It { Box::new(striped_random_unsigned_inclusive_range::( EXAMPLE_SEED, 0, u64::exact_from(T::MAX_EXPONENT), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) } // -- (PrimitiveUnsigned, PrimitiveSigned) -- pub fn special_random_unsigned_signed_pair_gen( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_signed_n", 32), config.get_or("mean_small_signed_d", 1), ) }, )) } struct IntegerMantissaAndExponentGenerator { xs: NonzeroValues>, shifts: GeometricRandomNaturalValues, } impl Iterator for IntegerMantissaAndExponentGenerator { type Item = (u64, i64); fn next(&mut self) -> Option<(u64, i64)> { loop { let (mantissa, exponent) = self.xs.next().unwrap().integer_mantissa_and_exponent(); let shift = self.shifts.next().unwrap(); let out = shift_integer_mantissa_and_exponent(mantissa, exponent, shift); if out.is_some() { return out; } } } } pub fn special_random_unsigned_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(u64, i64)> { Box::new(IntegerMantissaAndExponentGenerator:: { xs: random_nonzero_finite_primitive_floats(EXAMPLE_SEED.fork("xs")), shifts: geometric_random_natural_signeds( EXAMPLE_SEED.fork("shifts"), config.get_or("shift_mean_n", 4), config.get_or("shift_mean_d", 1), ), }) } // -- (PrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned) -- struct ModPowerOf2TripleExtraSmallSignedGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, us: GeometricRandomSigneds, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2TripleExtraSmallSignedGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn special_random_unsigned_signed_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleExtraSmallSignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: geometric_random_signeds( EXAMPLE_SEED.fork("ms"), config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_signed_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( config: &GenConfig, ) -> It<(T, S, T)> { Box::new( random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { striped_random_signed_inclusive_range::( seed, if S::WIDTH <= u64::WIDTH { S::MIN } else { -S::exact_from(u64::MAX) }, S::saturating_from(u64::MAX), config.get_or("mean_stripe_n", S::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(x, y, z): (T, S, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn special_random_unsigned_signed_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_large_unsigned_stripe_n", U::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, ) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn special_random_unsigned_signed_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveSigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } // -- (PrimitiveUnsigned, PrimitiveSigned, RoundingMode) -- pub fn special_random_unsigned_signed_rounding_mode_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { rm != Exact || pow <= U::ZERO || x.divisible_by_power_of_2(pow.exact_into()) }), ) } pub fn special_random_unsigned_signed_rounding_mode_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveSigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_shift_n", 4), config.get_or("mean_shift_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, pow, rm)| { let pow: i64 = pow.exact_into(); rm != Exact || pow >= 0 || x.divisible_by_power_of_2(pow.unsigned_abs()) }), ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_unsigned_pair_gen( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| random_unsigneds_less_than(seed, T::WIDTH), )) } pub fn special_random_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::saturating_from(T::MAX), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // TODO make better pub fn special_random_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y)| if x <= y { (x, y) } else { (y, x) }), ) } pub fn special_random_unsigned_pair_gen_var_6< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(|(x, y)| (x.round_to_multiple(y, Down).0, y)), ) } pub fn special_random_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|&(x, y)| !x.divisible_by(y)), ) } pub fn special_random_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter(|&(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn special_random_unsigned_pair_gen_var_11( config: &GenConfig, ) -> It<(T, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn special_random_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_ordered_unique_pairs(striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } struct ModPowerOf2SingleGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2SingleGenerator { type Item = (T, u64); fn next(&mut self) -> Option<(T, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, pow)) } } struct ModPowerOf2SingleGenerator2 { ms: GeometricRandomNaturalValues, xss: Vec>>>, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2SingleGenerator2 { type Item = (T, u64); fn next(&mut self) -> Option<(T, u64)> { let pow = self.ms.next().unwrap(); assert_ne!(pow, 0); let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(Box::new( striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, ) .filter(|&x| x != T::ZERO), )); } let x = xs.as_mut().unwrap().next().unwrap(); Some((x, pow)) } } pub fn special_random_unsigned_pair_gen_var_13( config: &GenConfig, ) -> It<(T, u64)> { Box::new(ModPowerOf2SingleGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_pair_gen_var_14( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_15( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| random_unsigneds_less_than(seed, U::WIDTH + 1), )) } pub fn special_random_unsigned_pair_gen_var_16( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed, U::TWO, U::MAX, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_17( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| random_unsigneds_less_than(seed, U::WIDTH + 1), )) } pub fn special_random_unsigned_pair_gen_var_18( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::saturating_from(u64::MAX), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_19( config: &GenConfig, ) -> It<(u64, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_bit_chunks( seed, T::MANTISSA_WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_bit_chunks( seed, T::EXPONENT_WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_20( config: &GenConfig, ) -> It<(T, u64)> { Box::new(special_random_unsigned_pair_gen_var_13(config).map(|(x, p)| (x, T::WIDTH - p))) } pub fn special_random_unsigned_pair_gen_var_21( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } struct LikelyMultiplyablePairs { bits: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, phantom: PhantomData<*const T>, } impl Iterator for LikelyMultiplyablePairs { type Item = (T, T); fn next(&mut self) -> Option<(T, T)> { let x = T::from_bits_asc( get_striped_bool_vec(&mut self.striped_bit_source, self.bits.next().unwrap()) .into_iter(), ); let y = T::from_bits_asc( get_striped_bool_vec(&mut self.striped_bit_source, self.bits.next().unwrap()) .into_iter(), ); Some((x, y)) } } pub fn special_random_unsigned_pair_gen_var_22( config: &GenConfig, ) -> It<(T, T)> { Box::new(LikelyMultiplyablePairs { bits: geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("bits"), 0, T::WIDTH, T::WIDTH >> 1, 1, ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), phantom: PhantomData, }) } pub fn special_random_unsigned_pair_gen_var_23( config: &GenConfig, ) -> It<(T, T)> { Box::new( special_random_unsigned_pair_gen_var_22::(config) .filter(|&(x, y)| x.checked_lcm(y).is_some()), ) } pub fn special_random_unsigned_pair_gen_var_24( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, T::power_of_2(T::WIDTH - 1), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_unsigned_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_25( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|&(x, y)| x != T::ONE || y != T::ZERO), ) } pub fn special_random_unsigned_pair_gen_var_26(config: &GenConfig) -> It<(u32, u32)> { Box::new(random_pairs_from_single(striped_random_unsigned_range( EXAMPLE_SEED, 0, NUMBER_OF_CHARS, config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_unsigned_pair_gen_var_27( config: &GenConfig, ) -> It<(T, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_28< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_29< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, V)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::saturating_from(U::MAX), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_30< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_31( config: &GenConfig, ) -> It<(T, u64)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) .map(|x| (T::ZERO, x)) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_positive_unsigneds::( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { striped_random_unsigned_range( seed_2, 0, T::WIDTH, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_unsigned_pair_gen_var_32( config: &GenConfig, ) -> It<(u64, u64)> { Box::new(random_pairs_from_single(striped_random_unsigned_range( EXAMPLE_SEED, 0, T::LARGEST_ORDERED_REPRESENTATION, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_unsigned_pair_gen_var_33( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, T::power_of_2(T::WIDTH - 2), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_34( config: &GenConfig, ) -> It<(T, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_pair_gen_var_35( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_unsigned_pair_gen_var_36( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_ordered_unique_pairs( striped_random_positive_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), )) } pub fn special_random_unsigned_pair_gen_var_37( config: &GenConfig, ) -> It<(T, u64)> { Box::new(ModPowerOf2SingleGenerator2 { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 1, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: { let len = usize::wrapping_from(T::WIDTH) + 1; let mut xss = Vec::with_capacity(len); xss.resize_with(len, || None); xss }, mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_pair_gen_var_38( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, )) } pub fn special_random_unsigned_pair_gen_var_39( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs_from_single( striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE), ) .filter(|&(a, b): &(T, T)| a.coprime_with(b)), ) } pub fn special_random_unsigned_pair_gen_var_40( config: &GenConfig, ) -> It<(T, T)> { Box::new( random_pairs_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter(|&(x, y): &(T, T)| x.coprime_with(y)), ) } pub fn special_random_unsigned_pair_gen_var_41( config: &GenConfig, ) -> It<(T, T)> { Box::new(random_pairs_from_single( striped_random_unsigned_inclusive_range( EXAMPLE_SEED, T::TWO, T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, bool) -- pub fn special_random_unsigned_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, bool)> { reshape_1_2_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_union2s( seed, &|seed_2| { geometric_random_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .map(|x| (x, false)) }, &|seed_2| random_unsigneds_less_than(seed_2, T::WIDTH).map(|x| (x, true)), ) .map(Union2::unwrap) }, ))) } pub fn special_random_unsigned_unsigned_bool_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_bools, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, z)| reduce_to_fit_add_mul_unsigned(x, y, z)), ) } pub fn special_random_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, z)| reduce_to_fit_sub_mul_unsigned(x, y, z)), ) } pub fn special_random_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveInt, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, u64, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(T, T, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(T, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn special_random_unsigned_triple_gen_var_6< T: PrimitiveUnsigned, U: ExactFrom + PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::TWO, U::exact_from(36u8), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(x, y, m)| { if m == T::ZERO { let min = min(x, y); (min, min, m) } else if x <= y { let adjusted_diff = (y - x).round_to_multiple(m, Down).0; (x, x + adjusted_diff, m) } else { let adjusted_diff = (x - y).round_to_multiple(m, Down).0; (y + adjusted_diff, y, m) } }), ) } pub fn special_random_unsigned_triple_gen_var_8( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter(|&(x, y, m)| !x.eq_mod(y, m)), ) } pub fn special_random_unsigned_triple_gen_var_9( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_pow_n", 32), config.get_or("mean_pow_d", 1), ) }, ) .map(|(x, y, pow)| { if pow >= T::WIDTH { (x, x, pow) } else if x <= y { let adjusted_diff = (y - x).round_to_multiple_of_power_of_2(pow, Down).0; (x, x + adjusted_diff, pow) } else { let adjusted_diff = (x - y).round_to_multiple_of_power_of_2(pow, Down).0; (y + adjusted_diff, y, pow) } }), ) } pub fn special_random_unsigned_triple_gen_var_10( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter(|&(x, y, pow)| !x.eq_mod_power_of_2(y, pow)), ) } struct ModPowerOf2PairGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2PairGenerator { type Item = (T, T, u64); fn next(&mut self) -> Option<(T, T, u64)> { let pow = self.ms.next().unwrap(); let (x, y) = if pow == 0 { (T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, pow)) } } pub fn special_random_unsigned_triple_gen_var_11( config: &GenConfig, ) -> It<(T, T, u64)> { Box::new(ModPowerOf2PairGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_triple_gen_var_12( config: &GenConfig, ) -> It<(T, T, T)> { Box::new( random_triples_from_single(striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter_map(|(x, y, z)| { let ranking = [(x, 0), (y, 1), (z, 2)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, x), 1 => (x, z, y), _ => (x, y, z), }) } }), ) } pub fn special_random_unsigned_triple_gen_var_13( config: &GenConfig, ) -> It<(T, U, U)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_unsigned_triple_gen_var_14( config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn special_random_unsigned_triple_gen_var_15( config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", U::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, ) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } struct ModPowerOf2TripleExtraUnsignedGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, us: StripedRandomUnsignedBitChunks, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2TripleExtraUnsignedGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn special_random_unsigned_triple_gen_var_16( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleExtraUnsignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: striped_random_unsigneds::( EXAMPLE_SEED.fork("us"), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } struct ModPowerOf2TripleExtraSmallUnsignedGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, us: GeometricRandomNaturalValues, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2TripleExtraSmallUnsignedGenerator { type Item = (T, U, u64); fn next(&mut self) -> Option<(T, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), pow)) } } pub fn special_random_unsigned_triple_gen_var_17( config: &GenConfig, ) -> It<(T, U, u64)> { Box::new(ModPowerOf2TripleExtraSmallUnsignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: geometric_random_unsigneds( EXAMPLE_SEED.fork("ms"), config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_triple_gen_var_18( config: &GenConfig, ) -> It<(T, U, T)> { Box::new( random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::ZERO, U::saturating_from(u64::MAX), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(x, y, z): (T, U, T)| match x.cmp(&z) { Equal => None, Less => Some((x, y, z)), Greater => Some((z, y, x)), }), ) } pub fn special_random_unsigned_triple_gen_var_19( config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_unsigned_triple_gen_var_20( config: &GenConfig, ) -> It<(T, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn special_random_unsigned_triple_gen_var_21( config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, )) } pub fn special_random_unsigned_triple_gen_var_22( config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, )) } pub fn special_random_unsigned_triple_gen_var_23( config: &GenConfig, ) -> It<(T, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, u64, U)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, ) .filter_map(|(x, y, z, w)| { let (y, z) = if y <= z { (y, z) } else { (z, y) }; if unsigned_assign_bits_valid(y, z, w) { Some((x, y, z, w)) } else { None } }), ) } pub fn special_random_unsigned_quadruple_gen_var_2( config: &GenConfig, ) -> It<(T, T, T, U)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_large_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_large_unsigned_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } struct ModPowerOf2TripleGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2TripleGenerator { type Item = (T, T, T, u64); fn next(&mut self) -> Option<(T, T, T, u64)> { let pow = self.ms.next().unwrap(); let (x, y, z) = if pow == 0 { (T::ZERO, T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, z, pow)) } } pub fn special_random_unsigned_quadruple_gen_var_3( config: &GenConfig, ) -> It<(T, T, T, u64)> { Box::new(ModPowerOf2TripleGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_quadruple_gen_var_4( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_quadruples_from_single(striped_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter_map(|(x, y, z, w)| { let ranking = [(x, 0), (y, 1), (z, 2), (w, 3)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, w, x), 1 => (x, z, w, y), 2 => (x, y, w, z), _ => (x, y, z, w), }) } }), ) } pub fn special_random_unsigned_quadruple_gen_var_5< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(|(x_1, x_0, d)| { let inv = limbs_invert_limb_naive::(d << LeadingZeros::leading_zeros(d)); (x_1, x_0, d, inv) }), ) } pub fn special_random_unsigned_quadruple_gen_var_6( config: &GenConfig, ) -> It<(T, T, U, T)> { Box::new( random_quadruples_xxyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(x, y, z, w)| { let ranking = [(x, 0), (y, 1), (w, 2)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, w, z, x), 1 => (x, w, z, y), _ => (x, y, z, w), }) } }), ) } pub fn special_random_unsigned_quadruple_gen_var_7( config: &GenConfig, ) -> It<(T, U, U, T)> { Box::new( random_quadruples_xyyx( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match x.cmp(&w) { Equal => None, Less => Some((x, y, z, w)), Greater => Some((w, y, z, x)), }), ) } struct ModPowerOf2QuadrupleWithExtraUnsignedGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, us: StripedRandomUnsignedBitChunks, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2QuadrupleWithExtraUnsignedGenerator { type Item = (T, T, U, u64); fn next(&mut self) -> Option<(T, T, U, u64)> { let pow = self.ms.next().unwrap(); let (x, y) = if pow == 0 { (T::ZERO, T::ZERO) } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } let xs = xs.as_mut().unwrap(); (xs.next().unwrap(), xs.next().unwrap()) }; Some((x, y, self.us.next().unwrap(), pow)) } } pub fn special_random_unsigned_quadruple_gen_var_8( config: &GenConfig, ) -> It<(T, T, U, u64)> { Box::new(ModPowerOf2QuadrupleWithExtraUnsignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: striped_random_unsigneds::( EXAMPLE_SEED.fork("us"), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } struct ModPowerOf2QuadrupleWithTwoExtraUnsignedGenerator { ms: GeometricRandomNaturalValues, xss: Vec>>, us: StripedRandomUnsignedBitChunks, mean_stripe_n: u64, mean_stripe_d: u64, } impl Iterator for ModPowerOf2QuadrupleWithTwoExtraUnsignedGenerator { type Item = (T, U, U, u64); fn next(&mut self) -> Option<(T, U, U, u64)> { let pow = self.ms.next().unwrap(); let x = if pow == 0 { T::ZERO } else { let xs = &mut self.xss[usize::wrapping_from(pow)]; if xs.is_none() { *xs = Some(striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&pow.to_string()), pow, self.mean_stripe_n, self.mean_stripe_d, )); } xs.as_mut().unwrap().next().unwrap() }; Some((x, self.us.next().unwrap(), self.us.next().unwrap(), pow)) } } pub fn special_random_unsigned_quadruple_gen_var_9( config: &GenConfig, ) -> It<(T, U, U, u64)> { Box::new(ModPowerOf2QuadrupleWithTwoExtraUnsignedGenerator { ms: geometric_random_unsigned_range( EXAMPLE_SEED.fork("ms"), 0, T::WIDTH, config.get_or("mean_pow_n", T::WIDTH >> 1), config.get_or("mean_pow_d", 1), ), us: striped_random_unsigneds::( EXAMPLE_SEED.fork("us"), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), xss: vec![None; usize::wrapping_from(T::WIDTH) + 1], mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH >> 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), }) } pub fn special_random_unsigned_quadruple_gen_var_10( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new(random_quadruples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } pub fn special_random_unsigned_quadruple_gen_var_11( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new( random_quadruples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter(|&(n1, n0, d1, d0)| { // conditions: D >= 2^W, N >= D, and N / D < 2^W d1 != T::ZERO && (n1 > d1 || n1 == d1 && n0 >= d0) }), ) } pub fn special_random_unsigned_quadruple_gen_var_12( config: &GenConfig, ) -> It<(T, T, T, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, )) } // -- (PrimitiveUnsigned * 6) -- pub fn special_random_unsigned_sextuple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T, T, T, T)> { Box::new(random_sextuples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } // var 2 is in malachite-nz. // -- (PrimitiveUnsigned * 8) -- #[allow(clippy::type_complexity)] pub fn special_random_unsigned_octuple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T)> { Box::new(random_octuples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } // -- (PrimitiveUnsigned * 9) -- #[allow(clippy::type_complexity)] pub fn special_random_unsigned_nonuple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T, T)> { Box::new( random_triples_from_single(random_triples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) .map(|((a, b, c), (d, e, f), (g, h, i))| (a, b, c, d, e, f, g, h, i)), ) } // -- (PrimitiveUnsigned * 12) -- #[allow(clippy::type_complexity)] pub fn special_random_unsigned_duodecuple_gen_var_1( config: &GenConfig, ) -> It<(T, T, T, T, T, T, T, T, T, T, T, T)> { Box::new(random_duodecuples_from_single(striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ))) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- struct UnsignedUnsignedRoundingModeTripleGenerator { xs: StripedRandomUnsignedBitChunks, rms: RandomRoundingModes, } impl Iterator for UnsignedUnsignedRoundingModeTripleGenerator { type Item = (T, T, RoundingMode); fn next(&mut self) -> Option<(T, T, RoundingMode)> { let mut x = self.xs.next().unwrap(); let mut y; loop { y = self.xs.next().unwrap(); if y != T::ZERO { break; } } let rm = self.rms.next().unwrap(); if rm == Exact { x.round_to_multiple_assign(y, Down); } Some((x, y, rm)) } } pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new(UnsignedUnsignedRoundingModeTripleGenerator { xs: striped_random_unsigneds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), rms: random_rounding_modes(EXAMPLE_SEED.fork("rms")), }) } pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(T, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_unsigned_filter_map(x, y, rm)), ) } pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, pow, rm)| round_to_multiple_of_power_of_2_filter_map(x, pow, rm)), ) } pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, y, rm)| rm != Exact || x.divisible_by_power_of_2(y.exact_into())), ) } // vars 5 through 6 are in malachite-float. pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_7< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(T, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, Vec) -- struct UnsignedUnsignedBoolVecTripleGeneratorVar1 { xs: StripedRandomUnsignedBitChunks, log_bases: StripedRandomUnsignedInclusiveRange, striped_bit_source: StripedBitSource, } impl Iterator for UnsignedUnsignedBoolVecTripleGeneratorVar1 { type Item = (T, u64, Vec); fn next(&mut self) -> Option<(T, u64, Vec)> { let x = self.xs.next().unwrap(); let log_base = self.log_bases.next().unwrap(); let bs = get_striped_bool_vec( &mut self.striped_bit_source, x.significant_bits().div_round(log_base, Ceiling).0, ); Some((x, log_base, bs)) } } pub fn special_random_unsigned_unsigned_bool_vec_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(T, u64, Vec)> { Box::new(UnsignedUnsignedBoolVecTripleGeneratorVar1 { xs: striped_random_unsigneds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), log_bases: striped_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("log_bases"), 1, U::WIDTH, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // -- (PrimitiveUnsigned, RoundingMode) -- pub fn special_random_unsigned_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_unsigned_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_unsigned_rounding_mode_pair_gen_var_2< T: PrimitiveUnsigned, U: ConvertibleFrom + PrimitiveFloat, >( config: &GenConfig, ) -> It<(T, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, ) .filter(move |&(n, rm)| rm != Exact || U::convertible_from(n)), ) } // -- (PrimitiveUnsigned, String) -- pub fn special_random_unsigned_string_pair_gen_var_1(config: &GenConfig) -> It<(u8, String)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_inclusive_range( seed, 2, 36, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_strings_using_chars( seed, &|seed_2| { graphic_weighted_random_chars( seed_2, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) }, )) } // -- (PrimitiveUnsigned, ToSciOptions) -- pub fn special_random_unsigned_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, )) } pub fn special_random_unsigned_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(T, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (PrimitiveUnsigned, Vec) -- struct UnsignedBoolVecPairGeneratorVar1 { xs: StripedRandomUnsignedBitChunks, striped_bit_source: StripedBitSource, } impl Iterator for UnsignedBoolVecPairGeneratorVar1 { type Item = (T, Vec); fn next(&mut self) -> Option<(T, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec(&mut self.striped_bit_source, x.significant_bits()); Some((x, bs)) } } pub fn special_random_unsigned_bool_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(T, Vec)> { Box::new(UnsignedBoolVecPairGeneratorVar1 { xs: striped_random_unsigneds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // -- RationalSequence -- pub fn special_random_unsigned_rational_sequence_gen( config: &GenConfig, ) -> It> { Box::new(random_rational_sequences( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } // -- (RationalSequence, PrimitiveUnsigned) -- pub fn special_random_unsigned_rational_sequence_unsigned_pair_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(RationalSequence, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &|seed_2| { striped_random_unsigneds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn special_random_unsigned_rational_sequence_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(RationalSequence, usize)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &|seed_2| { striped_random_unsigneds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, ) .filter(|&(ref xs, i)| { if let Some(len) = xs.len() { i < len } else { true } }), ) } // -- (RationalSequence, RationalSequence) -- pub fn special_random_unsigned_rational_sequence_pair_gen( config: &GenConfig, ) -> It<(RationalSequence, RationalSequence)> { Box::new(random_pairs_from_single(random_rational_sequences( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } // -- RationalSequence * 3 -- pub fn special_random_unsigned_rational_sequence_triple_gen( config: &GenConfig, ) -> It<( RationalSequence, RationalSequence, RationalSequence, )> { Box::new(random_triples_from_single(random_rational_sequences( EXAMPLE_SEED, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } // -- String -- pub fn special_random_string_gen(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &|seed| { graphic_weighted_random_chars( seed, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } pub fn special_random_string_gen_var_1(config: &GenConfig) -> It { Box::new(random_strings_using_chars( EXAMPLE_SEED, &|seed| { graphic_weighted_random_ascii_chars( seed, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), )) } // vars 2 and 3 are in malachite-q. pub fn special_random_string_gen_var_4(config: &GenConfig) -> It { Box::new( random_strings_using_chars( EXAMPLE_SEED, &|seed| { graphic_weighted_random_chars( seed, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)), ) } // -- (String, FromSciStringOptions) -- pub fn special_random_string_from_sci_string_options_pair_gen( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings_using_chars( seed, &|seed_2| { graphic_weighted_random_chars( seed_2, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) }, &random_from_sci_string_options, )) } pub fn special_random_string_from_sci_string_options_pair_gen_var_1( config: &GenConfig, ) -> It<(String, FromSciStringOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings_using_chars( seed, &|seed_2| { graphic_weighted_random_chars( seed_2, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)) }, &random_from_sci_string_options, )) } // -- (String, PrimitiveUnsigned) -- pub fn special_random_string_unsigned_pair_gen_var_1(config: &GenConfig) -> It<(String, u8)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_strings_using_chars( seed, &|seed_2| { graphic_weighted_random_chars( seed_2, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ) .filter(|s| !large_exponent(s)) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 2, 36, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (String, String) -- pub fn special_random_string_pair_gen(config: &GenConfig) -> It<(String, String)> { Box::new(random_pairs_from_single(random_strings_using_chars( EXAMPLE_SEED, &|seed| { graphic_weighted_random_chars( seed, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } pub fn special_random_string_pair_gen_var_1(config: &GenConfig) -> It<(String, String)> { Box::new(random_pairs_from_single(random_strings_using_chars( EXAMPLE_SEED, &|seed| { graphic_weighted_random_ascii_chars( seed, config.get_or("graphic_char_prob_n", 50), config.get_or("graphic_char_prob_d", 51), ) }, config.get_or("mean_length_n", 32), config.get_or("mean_length_d", 1), ))) } // -- (ToSciOptions, PrimitiveUnsigned> -- pub fn special_random_to_sci_options_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(ToSciOptions, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_to_sci_options( seed, config.get_or("mean_size_n", 32), config.get_or("mean_size_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_stripe_n", T::WIDTH), config.get_or("mean_stripe_d", 1), ) }, )) } // -- Vec -- pub fn special_random_bool_vec_gen(config: &GenConfig) -> It> { Box::new(striped_random_bool_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", 8), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } pub fn special_random_bool_vec_gen_var_1( config: &GenConfig, ) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_bool_vecs_length_inclusive_range( seed, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_fixed_length_bool_vecs( seed_2, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| bs.into_iter().chain(repeat_n(false, n)).collect()) }, ) .map(Union2::unwrap), ) } pub fn special_random_bool_vec_gen_var_2(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_bool_vecs_length_inclusive_range( seed, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_fixed_length_bool_vecs( seed_2, T::WIDTH - 1, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_nonzero_signeds::( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| { bs.into_iter() .chain(repeat_n(n < 0, n.unsigned_abs())) .collect() }) }, ) .map(Union2::unwrap), ) } pub fn special_random_bool_vec_gen_var_3( config: &GenConfig, ) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_bool_vecs_length_inclusive_range( seed, 0, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_fixed_length_bool_vecs( seed_2, T::WIDTH, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| repeat_n(false, n).chain(bs).collect()) }, ) .map(Union2::unwrap), ) } pub fn special_random_bool_vec_gen_var_4(config: &GenConfig) -> It> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { striped_random_bool_vecs_length_inclusive_range( seed, 0, T::WIDTH - 1, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_fixed_length_bool_vecs( seed_2, T::WIDTH - 1, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { geometric_random_nonzero_signeds::( seed_2, config.get_or("mean_excess_length_n", 32), config.get_or("mean_excess_length_d", 1), ) }, ) .map(|(bs, n)| repeat_n(n < 0, n.unsigned_abs()).chain(bs).collect()) }, ) .map(Union2::unwrap), ) } pub fn special_random_bool_vec_gen_var_5(config: &GenConfig) -> It> { Box::new( striped_random_bool_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", 8), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|bs| bs.iter().any(|&b| b)), ) } // -- Vec -- pub fn special_random_unsigned_vec_gen(config: &GenConfig) -> It> { Box::new(striped_random_unsigned_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } pub fn special_random_unsigned_vec_gen_var_1( config: &GenConfig, ) -> It> { Box::new( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), ) } pub fn special_random_unsigned_vec_gen_var_2( config: &GenConfig, ) -> It> { Box::new( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)), ) } pub fn special_random_unsigned_vec_gen_var_3( config: &GenConfig, ) -> It> { Box::new( striped_random_unsigned_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), ) } pub fn special_random_unsigned_vec_gen_var_4( config: &GenConfig, ) -> It> { Box::new(striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } // var 5 is in malachite-nz. pub fn special_random_unsigned_vec_gen_var_6( config: &GenConfig, ) -> It> { Box::new(striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) } // --(Vec, PrimitiveUnsigned) -- pub fn special_random_unsigned_vec_unsigned_pair_gen( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } struct UnsignedVecUnsignedPairGeneratorVar1 { log_bases: GeometricRandomNaturalValues, ranges: VariableRangeGenerator, striped_bit_source: StripedBitSource, phantom: PhantomData<(T, U)>, } impl Iterator for UnsignedVecUnsignedPairGeneratorVar1 { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let max_count = usize::exact_from(T::WIDTH.div_round(log_base, Ceiling).0); loop { let digit_count = self.ranges.next_in_inclusive_range(0, max_count); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { digits.push(U::from_bits_asc( get_striped_bool_vec(&mut self.striped_bit_source, log_base).into_iter(), )); } if digits_valid::(log_base, &digits) { return Some((digits, log_base)); } } } } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(UnsignedVecUnsignedPairGeneratorVar1:: { log_bases: geometric_random_unsigned_range( EXAMPLE_SEED.fork("log_bases"), 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), ranges: VariableRangeGenerator::new(EXAMPLE_SEED.fork("ranges")), phantom: PhantomData, }) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new( special_random_unsigned_vec_unsigned_pair_gen_var_1::(config) .map(|(xs, y)| (xs.into_iter().rev().collect(), y)), ) } struct UnsignedVecUnsignedPairGeneratorVar3 { phantom: PhantomData<*const T>, xs: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, } impl Iterator for UnsignedVecUnsignedPairGeneratorVar3 { type Item = (Vec, usize); fn next(&mut self) -> Option<(Vec, usize)> { let x_1 = self.xs.next().unwrap(); let x_2 = self.xs.next().unwrap(); let (len, i) = if x_1 <= x_2 { (x_2, x_1) } else { (x_1, x_2) }; Some(( get_striped_unsigned_vec( &mut self.striped_bit_source, u64::exact_from(len) << T::LOG_WIDTH, ), i, )) } } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, usize)> { Box::new(UnsignedVecUnsignedPairGeneratorVar3 { phantom: PhantomData, xs: geometric_random_unsigneds( EXAMPLE_SEED.fork("xs"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), ), }) } // var 4 is in malachite-nz pub fn special_random_unsigned_vec_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed.fork("log_bases"), 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } struct PowerOf2DigitsGenerator { log_bases: GeometricRandomNaturalValues, digit_counts: GeometricRandomNaturalValues, digit_map: HashMap>, mean_stripe_n: u64, mean_stripe_d: u64, phantom: PhantomData<*const T>, } impl Iterator for PowerOf2DigitsGenerator { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mean_stripe_n = self.mean_stripe_n; let mean_stripe_d = self.mean_stripe_d; let digits = self.digit_map.entry(log_base).or_insert_with(|| { striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork(&log_base.to_string()), log_base, mean_stripe_n, mean_stripe_d, ) }); let digits = digits.take(digit_count).collect_vec(); Some((digits, log_base)) } } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(PowerOf2DigitsGenerator:: { log_bases: geometric_random_unsigned_range( EXAMPLE_SEED.fork("log_bases"), 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_count"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), digit_map: HashMap::new(), mean_stripe_n: config.get_or("mean_stripe_n", T::WIDTH << 1), mean_stripe_d: config.get_or("mean_stripe_d", 1), phantom: PhantomData, }) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed.fork("log_bases"), 1, T::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_9< T: PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed.fork("base"), U::TWO, U::saturating_from(T::MAX), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_10< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_11< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, U::exact_from(3), U::MAX, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_12< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_13< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_14< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, ) .filter(|(xs, y)| *y < U::exact_from(xs.len() << T::LOG_WIDTH)), ) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_15< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_16< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_17< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } // var 18 is in malachite-nz pub fn special_random_unsigned_vec_unsigned_pair_gen_var_19< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_20< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_21< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::power_of_2(U::WIDTH - 1), U::MAX, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_22< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_range( seed, U::ONE, U::power_of_2(U::WIDTH - 1), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_23< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, U::power_of_2(U::WIDTH - 1), U::MAX, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_24< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_range( seed, U::ONE, U::power_of_2(U::WIDTH - 1), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_25< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_range( seed, U::ONE, U::power_of_2(U::WIDTH - 2), config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // vars 26 through 27 are in malachite-nz. pub fn special_random_unsigned_vec_unsigned_pair_gen_var_28< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, U::TWO, U::MAX, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_29< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed.fork("log_bases"), 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_30< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_range( seed.fork("log_bases"), 1, U::WIDTH, config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ) }, )) } // --(Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, V: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, V)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } struct UnsignedVecUnsignedUnsignedTripleGeneratorVar1 { phantom: PhantomData<*const T>, is: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, } impl Iterator for UnsignedVecUnsignedUnsignedTripleGeneratorVar1 { type Item = (Vec, usize, usize); fn next(&mut self) -> Option<(Vec, usize, usize)> { let i = self.is.next().unwrap(); let j = self.is.next().unwrap(); let excess = self.is.next().unwrap(); let xs = get_striped_unsigned_vec( &mut self.striped_bit_source, u64::exact_from(i * j + excess) << T::LOG_WIDTH, ); Some((xs, i, j)) } } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, usize, usize)> { Box::new(UnsignedVecUnsignedUnsignedTripleGeneratorVar1 { phantom: PhantomData, is: geometric_random_unsigneds( EXAMPLE_SEED.fork("is"), config.get_or("small_unsigned_mean_n", 2), config.get_or("small_unsigned_mean_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_4< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, U)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // var 6 is in malachite-nz. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_8< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // var 9 is in malachite-nz. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_10( config: &GenConfig, ) -> It<(Vec, T, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::ZERO, T::low_mask(T::WIDTH - 1), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(|u| (u << 1) | T::ONE) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // vars 11 through 12 are in malachite-nz. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_13< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } // var 14 is in malachite-nz. // -- (Vec, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_unsigned_vec_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, T, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_unsigned_vec_unsigned_rounding_mode_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, U, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // -- (Vec, Vec) -- pub fn special_random_unsigned_vec_pair_gen( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single(striped_random_unsigned_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ))) } pub struct UnsignedVecPairLenGenerator1> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecPairLenGenerator1 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH), )) } } fn special_random_unsigned_vec_pair_gen_var_1_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_unsigned_vec_pair_gen_var_1_helper(config, EXAMPLE_SEED) } pub fn special_random_unsigned_vec_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), )) } pub fn special_random_unsigned_vec_pair_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single(striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|(xs, es)| { !xs.is_empty() && (es.len() > 1 || es.len() == 1 && es[0] > T::ONE) && *es.last().unwrap() != T::ZERO }), ) } struct UnsignedVecSqrtRemGenerator> { phantom: PhantomData<*const T>, lengths: I, striped_bit_source: StripedBitSource, hi_n_bits: StripedRandomUnsignedInclusiveRange, } impl> Iterator for UnsignedVecSqrtRemGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (out_len, len) = self.lengths.next().unwrap(); let out = get_striped_unsigned_vec(&mut self.striped_bit_source, out_len << T::LOG_WIDTH); let mut ns: Vec = get_striped_unsigned_vec(&mut self.striped_bit_source, len << T::LOG_WIDTH); let n_hi = &mut ns[(usize::exact_from(out_len) << 1) - 1]; n_hi.mod_power_of_2_assign(T::WIDTH - 2); *n_hi |= self.hi_n_bits.next().unwrap() << (T::WIDTH - 2); Some((out, ns)) } } pub fn special_random_unsigned_vec_pair_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecSqrtRemGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let out_len = x.checked_add(2)?; let len: u64 = out_len.arithmetic_checked_shl(1)?; let len = len.checked_add(y)?; Some((out_len, len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), hi_n_bits: striped_random_unsigned_range( EXAMPLE_SEED.fork("hi_n_bits"), T::ONE, T::exact_from(4), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct UnsignedVecSqrtGenerator> { phantom: PhantomData<*const T>, lengths: I, striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecSqrtGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (out_len, len) = self.lengths.next().unwrap(); let out = get_striped_unsigned_vec(&mut self.striped_bit_source, out_len << T::LOG_WIDTH); let mut ns: Vec = get_striped_unsigned_vec(&mut self.striped_bit_source, len << T::LOG_WIDTH); let hi_n = ns.last_mut().unwrap(); if *hi_n == T::ZERO { *hi_n = T::ONE; } Some((out, ns)) } } pub fn special_random_unsigned_vec_pair_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecSqrtGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let in_len = x.checked_add(1)?; let mut out_len: u64 = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; Some((out_len, in_len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct UnsignedVecPairSameLenGenerator> { phantom: PhantomData<*const T>, lengths: I, striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecPairSameLenGenerator { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let len = self.lengths.next().unwrap() << T::LOG_WIDTH; Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, len), get_striped_unsigned_vec(&mut self.striped_bit_source, len), )) } } pub fn special_random_unsigned_vec_pair_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_pair_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( striped_random_unsigned_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn special_random_unsigned_vec_pair_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)), )) } pub struct UnsignedVecPairLenGenerator2> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecPairLenGenerator2 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); let mut xs; loop { xs = get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH); if !slice_test_zero(&xs) { break; } } let mut ys; loop { ys = get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH); if !slice_test_zero(&ys) { break; } } Some((xs, ys)) } } pub fn special_random_unsigned_vec_pair_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator2 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // var 11 is in malachite-nz. pub fn special_random_unsigned_vec_pair_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(_, ds)| *ds.last().unwrap() != T::ZERO), ) } pub fn special_random_unsigned_vec_pair_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(xs, mut ys)| { ys[0] |= T::ONE; (xs, ys) }), ) } // vars 14 through 15 are in malachite-nz. pub fn special_random_unsigned_vec_pair_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(xs, ys)| *xs.last().unwrap() != T::ZERO && *ys.last().unwrap() != T::ZERO), ) } pub fn special_random_unsigned_vec_pair_gen_var_17( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(xs, ys)| *xs.last().unwrap() != T::ZERO && *ys.last().unwrap() != T::ZERO), ) } // var 18 is in malachite-nz. pub fn special_random_unsigned_vec_pair_gen_var_19( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::power_of_2(T::WIDTH - 1), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_unsigned_stripe_n", T::WIDTH >> 1), config.get_or("mean_unsigned_stripe_d", 1), ) }, ) .map(|(n, d_1, d_0)| (n, vec![d_0, d_1])), ) } pub fn special_random_unsigned_vec_pair_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(random_pairs_from_single( striped_random_unsigned_vecs_min_length::( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let last = xs.last_mut().unwrap(); *last = last.checked_add(T::ONE)?; Some(xs) }), )) } pub fn special_random_unsigned_vec_pair_gen_var_21( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // vars 22 through 31 are in malachite-nz. pub fn special_random_unsigned_vec_pair_gen_var_32( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_pair_gen_var_33( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(xs, ys): &(Vec, Vec)| { (*xs.last().unwrap() != T::ZERO || *ys.last().unwrap() != T::ZERO) && ys[0].odd() }), ) } // var 34 is in malachite-nz. // -- (Vec, Vec, bool) -- pub fn special_random_unsigned_vec_unsigned_vec_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, bool)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &random_bools, ))) } // -- (Vec, Vec, PrimitiveUnsigned) -- pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| special_random_unsigned_vec_pair_gen_var_1_helper(config, seed), &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } // var 2 and 3 are in malachite-nz fn special_random_unsigned_vec_pair_gen_var_2_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| special_random_unsigned_vec_pair_gen_var_2_helper(config, seed), &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } struct UnsignedVecPairLenGenerator3> { phantom: PhantomData<*const T>, lengths: I, striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecPairLenGenerator3 { type Item = (Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); let xs = get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH); let mut ys; loop { ys = get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH); if !slice_test_zero(&ys) { break; } } Some((xs, ys)) } } fn special_random_unsigned_vec_pair_gen_var_3_helper( config: &GenConfig, seed: Seed, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator3 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| special_random_unsigned_vec_pair_gen_var_3_helper(config, seed), &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // vars 7 through 8 are in malachite-nz. pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, U)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub struct PrimitiveIntVecPairLenAndIndexGenerator< T: PrimitiveUnsigned, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for PrimitiveIntVecPairLenAndIndexGenerator { type Item = (Vec, Vec, usize); fn next(&mut self) -> Option<(Vec, Vec, usize)> { let (i, j, k) = self.lengths.next().unwrap(); Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH), usize::exact_from(k), )) } } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, usize)> { Box::new(PrimitiveIntVecPairLenAndIndexGenerator { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(y)?; let o = o.checked_add(x)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairSameLenGenerator { phantom: PhantomData, lengths: geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( seed.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } // vars 14 through 21 are in malachite-nz. pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| special_random_unsigned_vec_pair_gen_var_1_helper(config, seed), &|seed| { striped_random_unsigned_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", U::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24( config: &GenConfig, ) -> It<(Vec, Vec, usize)> { Box::new(PrimitiveIntVecPairLenAndIndexGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, i)| { let x = x.checked_add(i)?; Some((x, x, i)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // -- (Vec, Vec, Vec) -- pub struct UnsignedVecTripleXYYLenGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecTripleXYYLenGenerator { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j) = self.lengths.next().unwrap(); let shifted_j = j << T::LOG_WIDTH; Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, shifted_j), get_striped_unsigned_vec(&mut self.striped_bit_source, shifted_j), )) } } pub fn special_random_unsigned_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub struct UnsignedVecTripleLenGenerator1> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecTripleLenGenerator1 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j, k) = self.lengths.next().unwrap(); Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, k << T::LOG_WIDTH), )) } } pub struct UnsignedVecQuadrupleLenGenerator1< T: PrimitiveUnsigned, I: Iterator, > { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecQuadrupleLenGenerator1 { type Item = (Vec, Vec, Vec, Vec); fn next(&mut self) -> Option { let (i, j, k, l) = self.lengths.next().unwrap(); Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, k << T::LOG_WIDTH), get_striped_unsigned_vec(&mut self.striped_bit_source, l << T::LOG_WIDTH), )) } } pub fn special_random_unsigned_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(1)?; let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // vars 4 through 23 are in malachite-nz pub fn special_random_unsigned_vec_triple_gen_var_24( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_25( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_26( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let y = y.checked_add(2)?; let x = x.checked_add(y)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct UnsignedVecTripleXXXLenGenerator> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecTripleXXXLenGenerator { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let i = self.lengths.next().unwrap() << T::LOG_WIDTH; Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, i), get_striped_unsigned_vec(&mut self.striped_bit_source, i), get_striped_unsigned_vec(&mut self.striped_bit_source, i), )) } } pub fn special_random_unsigned_vec_triple_gen_var_27( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXXXLenGenerator { phantom: PhantomData, lengths: geometric_random_unsigned_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct UnsignedVecSqrtRemGenerator3> { phantom: PhantomData<*const T>, lengths: I, striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecSqrtRemGenerator3 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (out_len, rs_len, len) = self.lengths.next().unwrap(); let out = get_striped_unsigned_vec(&mut self.striped_bit_source, out_len << T::LOG_WIDTH); let rs = get_striped_unsigned_vec(&mut self.striped_bit_source, rs_len << T::LOG_WIDTH); let mut ns: Vec = get_striped_unsigned_vec(&mut self.striped_bit_source, len << T::LOG_WIDTH); let hi_n = ns.last_mut().unwrap(); if *hi_n == T::ZERO { *hi_n = T::ONE; } Some((out, rs, ns)) } } pub fn special_random_unsigned_vec_triple_gen_var_28( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecSqrtRemGenerator3 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let in_len = x.checked_add(1)?; let mut out_len: u64 = in_len.shr_round(1, Ceiling).0; out_len = out_len.checked_add(y)?; let rem_len = in_len.checked_add(z)?; Some((out_len, rem_len, in_len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_29( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXXXLenGenerator { phantom: PhantomData, lengths: geometric_random_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_30( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( striped_random_unsigned_vecs( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)), )) } pub fn special_random_unsigned_vec_triple_gen_var_31( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_32( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let o = max(x, y).checked_add(o)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct UnsignedVecTripleLenGenerator2> { pub phantom: PhantomData<*const T>, pub lengths: I, pub striped_bit_source: StripedBitSource, } impl> Iterator for UnsignedVecTripleLenGenerator2 { type Item = (Vec, Vec, Vec); fn next(&mut self) -> Option<(Vec, Vec, Vec)> { let (i, j, k) = self.lengths.next().unwrap(); let out = get_striped_unsigned_vec(&mut self.striped_bit_source, i << T::LOG_WIDTH); let mut xs; loop { xs = get_striped_unsigned_vec(&mut self.striped_bit_source, j << T::LOG_WIDTH); if !slice_test_zero(&xs) { break; } } let mut ys; loop { ys = get_striped_unsigned_vec(&mut self.striped_bit_source, k << T::LOG_WIDTH); if !slice_test_zero(&ys) { break; } } Some((out, xs, ys)) } } pub fn special_random_unsigned_vec_triple_gen_var_33( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(x)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_34( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(max(x, y))?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_35( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator2 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(1)?; let y = y.checked_add(1)?; let o = o.checked_add(min(x, y))?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_36( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } // vars 37 through 38 are in malachite-nz. pub fn special_random_unsigned_vec_triple_gen_var_39( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO), )) } pub fn special_random_unsigned_vec_triple_gen_var_40( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(o, x, y)| { let x = x.checked_add(y)?; let o = o.checked_add(x)?; Some((o, x, y)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_41( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != T::ZERO) }, )) } // vars 42 through 49 are in malachite-nz. pub fn special_random_unsigned_vec_triple_gen_var_50( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let y = y.checked_add(1)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(x, mut y, z): (Vec, Vec, Vec)| { y.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_51( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let y = y.checked_add(5)?; let x = x.checked_add(y)?; let z = z.checked_add(y.arithmetic_checked_shl(1)?)?; Some((x, y, z)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(x, mut y, z): (Vec, Vec, Vec)| { y.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_52( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let q = x.checked_add(3)?; let n = y.checked_add(9)?; let d = z.checked_add(6)?; if n < d { return None; } let q_alt = n - d + 1; if (q_alt << 1) > n || q_alt > d { return None; } let n_alt = q_alt << 1; let d_alt = q_alt; if q >= q_alt && d_alt >= 6 && n_alt >= d_alt + 3 && d_alt >= q_alt { Some((q, n, d)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(x, y, mut z): (Vec, Vec, Vec)| { z.last_mut().unwrap().set_bit(T::WIDTH - 1); (x, y, z) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_53( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(x, y)| y >= 2 && x >= y - 2), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_unsigned_inclusive_range( seed_2, T::power_of_2(T::WIDTH - 1), T::MAX, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, ) .map(|((q, n), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // vars 54 through 56 are in malachite-nz. pub fn special_random_unsigned_vec_triple_gen_var_57( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(r_len, n_len, d_len)| { let d_len = d_len.checked_add(2)?; let r_len = r_len.checked_add(d_len)?; let n_len = n_len.checked_add(d_len)?; Some((r_len, n_len, d_len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter_map(|(r, n, mut d): (Vec, Vec, Vec)| { let last_d = d.last_mut().unwrap(); *last_d = last_d.checked_add(T::ONE)?; Some((r, n, d)) }), ) } // var 58 is in malachite-nz. pub fn special_random_unsigned_vec_triple_gen_var_59( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(xs_len, ys_len, zs_len)| { let ys_len = ys_len.checked_add(2)?; let zs_len = zs_len.checked_add(2)?; let xs_len = xs_len.checked_add(ys_len + zs_len - 1)?; Some((xs_len, ys_len, zs_len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter_map(|(mut xs, mut ys, mut zs): (Vec, Vec, Vec)| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(T::ONE)?; let last_y = ys.last_mut().unwrap(); *last_y = last_y.checked_add(T::ONE)?; let last_z = zs.last_mut().unwrap(); *last_z = last_z.checked_add(T::ONE)?; Some((xs, ys, zs)) }), ) } // var 60 is in malachite-nz. // -- large types -- pub fn special_random_large_type_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, T, T)> { reshape_2_2_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| special_random_unsigned_vec_pair_gen_var_1_helper(config, seed), &|seed| { random_pairs_from_single(striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, ))) } struct UnsignedVecSqrtRemGenerator2 { pub phantom: PhantomData<*const T>, pub lengths: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, } impl Iterator for UnsignedVecSqrtRemGenerator2 { type Item = (Vec, Vec, u64, bool); fn next(&mut self) -> Option<(Vec, Vec, u64, bool)> { let len = self.lengths.next().unwrap(); let n = len.shr_round(1, Ceiling).0; let out = get_striped_unsigned_vec(&mut self.striped_bit_source, n << T::LOG_WIDTH); let mut ns: Vec = get_striped_unsigned_vec(&mut self.striped_bit_source, len << T::LOG_WIDTH); let last = ns.last_mut().unwrap(); if *last == T::ZERO { *last = T::ONE; } let shift = last.leading_zeros() >> 1; Some((out, ns, shift, len.odd())) } } pub fn special_random_large_type_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, u64, bool)> { Box::new(UnsignedVecSqrtRemGenerator2 { phantom: PhantomData, lengths: geometric_random_unsigned_range::( EXAMPLE_SEED.fork("lengths"), 9, u64::MAX, config.get_or("mean_length_n", 12), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_large_type_gen_var_3( config: &GenConfig, ) -> It<(Vec, U, U, Vec)> { Box::new( random_quadruples_xyyx::<_, _, U, _>( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } pub fn special_random_large_type_gen_var_4( config: &GenConfig, ) -> It<(Vec, U, U, Vec)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs::( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| !slice_test_zero(xs)) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_unsigned_vecs::( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // vars 5 through 8 are in malachite-nz #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, Vec, bool)> { reshape_3_1_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y)| { let x = x.checked_add(y)?; Some((x, y)) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &random_bools, ))) } // vars 10 through 21 are in malachite-nz. pub fn special_random_large_type_gen_var_22( config: &GenConfig, ) -> It<(RationalSequence, usize, T, T)> { Box::new( random_quadruples_xyzz( EXAMPLE_SEED, &|seed| { random_rational_sequences( seed, &|seed_2| { striped_random_unsigneds( seed_2, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 32), config.get_or("mean_small_unsigned_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|&(ref xs, index, _, _)| { if let Some(len) = xs.len() { index < len } else { true } }), ) } // vars 23 through 24 are in malachite-nz. pub fn special_random_large_type_gen_var_25( config: &GenConfig, ) -> It<(bool, Vec, bool, Vec)> { Box::new(random_quadruples_xyxy( EXAMPLE_SEED, &random_bools, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| xs.last() != Some(&T::ZERO)) }, )) } ================================================ FILE: malachite-base/src/test_util/hash/mod.rs ================================================ // Copyright © 2026 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 std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; pub fn hash(n: &T) -> u64 { let mut s = DefaultHasher::new(); n.hash(&mut s); s.finish() } ================================================ FILE: malachite-base/src/test_util/mod.rs ================================================ // Copyright © 2026 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 . pub mod bench; pub mod common; pub mod extra_variadic; pub mod generators; pub mod hash; pub mod num; pub mod rounding_modes; pub mod runner; pub mod sets; pub mod slices; pub mod stats; pub mod vecs; ================================================ FILE: malachite-base/src/test_util/num/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; pub fn extended_gcd_unsigned_euclidean< U: PrimitiveUnsigned, S: PrimitiveSigned + WrappingFrom, >( a: U, b: U, ) -> (U, S, S) { if a == U::ZERO && b == U::ZERO { (U::ZERO, S::ZERO, S::ZERO) } else if a == b || a == U::ZERO { (b, S::ZERO, S::ONE) } else { let (gcd, x, y) = extended_gcd_unsigned_euclidean(b % a, a); (gcd, y - S::wrapping_from(b / a) * x, x) } } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::logic::traits::NotAssign; pub fn checked_factorial_naive(n: u64) -> Option { let mut f = T::ONE; let mut n = T::try_from(n).ok()?; while n != T::ZERO { f = f.checked_mul(n)?; n -= T::ONE; } Some(f) } pub fn checked_double_factorial_naive(n: u64) -> Option { let mut f = T::ONE; let mut n = T::try_from(n).ok()?; while n != T::ZERO { f = f.checked_mul(n)?; n.saturating_sub_assign(T::TWO); } Some(f) } pub fn checked_subfactorial_naive(n: u64) -> Option { let mut f = T::ONE; let mut b = true; for i in 1..=n { f = f.checked_mul(T::try_from(i).ok()?)?; if b { f -= T::ONE; } else { f = f.checked_add(T::ONE)?; } b.not_assign(); } Some(f) } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1996, 1998, 1999-2002, 2000-2004, 2008, 2010 Free Software Foundation, Inc. // // 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 crate::num::arithmetic::traits::{NegAssign, Parity}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{HasHalf, JoinHalves}; use crate::num::logic::traits::NotAssign; use std::mem::swap; // This is equivalent to `n_jacobi_unsigned` from `ulong_extras/jacobi.c`, FLINT 2.7.1. pub fn jacobi_symbol_unsigned_fast_1(x: T, y: T) -> i8 { let mut a = x; let mut b = y; let mut s = 1; if a < b && b != T::ONE { if a == T::ZERO { return 0; } swap(&mut a, &mut b); let exp = b.trailing_zeros(); b >>= exp; if T::wrapping_from(exp) .wrapping_mul(a.wrapping_square() - T::ONE) .get_bit(3) != (a - T::ONE).wrapping_mul(b - T::ONE).get_bit(2) { s.neg_assign(); } } while b != T::ONE { if a >> 2 < b { let temp = a - b; a = b; b = if temp < b { temp } else if temp < b << 1 { temp - a } else { temp - (a << 1) } } else { a %= b; swap(&mut a, &mut b); } if b == T::ZERO { return 0; } let exp = b.trailing_zeros(); b >>= exp; if T::wrapping_from(exp) .wrapping_mul(a.wrapping_square() - T::ONE) .get_bit(3) != (a - T::ONE).wrapping_mul(b - T::ONE).get_bit(2) { s.neg_assign(); } } s } // This is equivalent to `mpn_jacobi_base` from `mpn/jacbase.c`, GMP 6.2.1, where // `JACOBI_BASE_METHOD == 1` and `result_bit_1` is false. pub fn jacobi_symbol_unsigned_fast_2_1(mut a: T, mut b: T) -> i8 { assert!(b.odd()); if b == T::ONE { return 1; } else if a == T::ZERO { return 0; } let mut s = 1; let a_twos = a.trailing_zeros(); if a_twos.odd() && ((b >> 1u32) ^ b).get_bit(1) { s.neg_assign(); } a >>= a_twos; if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } loop { assert!(a.odd()); assert!(b.odd()); assert!(a >= b); a -= b; if a == T::ZERO { return 0; } let a_twos = a.trailing_zeros(); if a_twos.odd() && ((b >> 1u32) ^ b).get_bit(1) { s.neg_assign(); } a >>= a_twos; if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } } } // This is equivalent to `mpn_jacobi_base` from `mpn/jacbase.c`, GMP 6.2.1, where // `JACOBI_BASE_METHOD == 2` and `result_bit_1` is false. pub fn jacobi_symbol_unsigned_fast_2_2(mut a: T, mut b: T) -> i8 { assert!(b.odd()); if b == T::ONE { return 1; } else if a == T::ZERO { return 0; } let mut s = 1; if a.even() { let two = (b >> 1u32) ^ b; loop { a >>= 1; if two.get_bit(1) { s.neg_assign(); } if a.odd() { break; } } } if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } loop { assert!(a.odd()); assert!(b.odd()); assert!(a >= b); a -= b; if a == T::ZERO { return 0; } let two = (b >> 1u32) ^ b; loop { a >>= 1; if two.get_bit(1) { s.neg_assign(); } if a.odd() { break; } } if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } } } // This is equivalent to `mpn_jacobi_base` from `mpn/jacbase.c`, GMP 6.2.1, where // `JACOBI_BASE_METHOD == 3` and `result_bit_1` is false. pub fn jacobi_symbol_unsigned_fast_2_3(mut a: T, mut b: T) -> i8 { assert!(b.odd()); if b == T::ONE { return 1; } else if a == T::ZERO { return 0; } let mut s = 1; let two = (b >> 1u32) ^ b; let shift = !a & T::ONE; let shift_8: u8 = shift.wrapping_into(); a >>= shift_8; let mask = shift << 1u32; if (two & mask).get_bit(1) { s.neg_assign(); } let two_bit = two.get_bit(1); while a.even() { a >>= 1; if two_bit { s.neg_assign(); } } if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } loop { assert!(a.odd()); assert!(b.odd()); assert!(a >= b); a -= b; if a == T::ZERO { return 0; } let two = (b >> 1u32) ^ b; let mask = !a & T::TWO; a >>= 1; if a.even() { a >>= 1; } if (two ^ (two & mask)).get_bit(1) { s.neg_assign(); } while a.even() { a >>= 1; if two.get_bit(1) { s.neg_assign(); } } if a == T::ONE { return s; } if a < b { if (a & b).get_bit(1) { s.neg_assign(); } swap(&mut a, &mut b); } } } // This is equivalent to `mpn_jacobi_base` from `mpn/jacbase.c`, GMP 6.2.1, where // `JACOBI_BASE_METHOD == 4` and `result_bit_1` is false. pub fn jacobi_symbol_unsigned_fast_2_4(mut a: T, mut b: T) -> i8 { assert!(b.odd()); if b == T::ONE { return 1; } else if a == T::ZERO { return 0; } let mut s = 1; b >>= 1u32; let c = a.trailing_zeros(); if (T::wrapping_from(c) & (b ^ (b >> 1))).odd() { s.neg_assign(); } // We may have c == T::WIDTH - 1, so we can't use a >> (c + 1). a >>= c; a >>= 1; while b != T::ZERO { let t = a.wrapping_sub(b); if t == T::ZERO { return 0; } let bgta = if t.get_highest_bit() { T::MAX } else { T::ZERO }; // If b > a, invoke reciprocity if (bgta & a & b).odd() { s.neg_assign(); } // b <-- min (a, b) b.wrapping_add_assign(bgta & t); // a <-- |a - b| a = (t ^ bgta).wrapping_sub(bgta); // Number of trailing zeros is the same no matter if we look at t or a, but using t gives // more parallelism. let c = t.trailing_zeros() + 1; // (2/b) = -1 if b = 3 or 5 mod 8 if (T::wrapping_from(c) & (b ^ (b >> 1))).odd() { s.neg_assign(); } a >>= c; } s } pub fn jacobi_symbol_unsigned_double_simple< T: PrimitiveUnsigned, D: HasHalf + JoinHalves + PrimitiveUnsigned, >( x_1: T, x_0: T, y_1: T, y_0: T, ) -> i8 { D::join_halves(x_1, x_0).jacobi_symbol(D::join_halves(y_1, y_0)) } // Computes (a / b) where b is odd, and a and b are otherwise arbitrary two-limb numbers. // // This is equivalent to `mpn_jacobi_2` from `mpn/jacobi_2.c`, GMP 6.2.1, where `JACOBI_2_METHOD == // 1` and `bit` is 0. pub fn jacobi_symbol_unsigned_double_fast_1( mut x_1: T, mut x_0: T, mut y_1: T, mut y_0: T, ) -> i8 { assert!(y_0.odd()); y_0 = (y_1 << (T::WIDTH - 1)) | (y_0 >> 1); y_1 >>= 1; if y_1 == T::ZERO && y_0 == T::ZERO { return 1; } if x_1 == T::ZERO && x_0 == T::ZERO { return 0; } if x_0 == T::ZERO { x_0 = x_1; x_1 = T::ZERO; } let mut bit = false; let c = x_0.trailing_zeros() + 1; if c.even() && (y_0 ^ (y_0 >> 1)).odd() { bit.not_assign(); } if c == T::WIDTH { x_0 = x_1; x_1 = T::ZERO; } else { x_0 = (x_1 << (T::WIDTH - c)) | (x_0 >> c); x_1 >>= c; } while x_1 != T::ZERO || y_1 != T::ZERO { let (diff_1, diff_0) = T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); if diff_0 == T::ZERO && diff_1 == T::ZERO { return 0; } let mask = if diff_1.get_highest_bit() { T::MAX } else { T::ZERO }; // If y > x, invoke reciprocity if (mask & x_0 & y_0).odd() { bit.not_assign(); } // y <- min(x, y) (y_1, y_0) = T::xx_add_yy_to_zz(y_1, y_0, diff_1 & mask, diff_0 & mask); if y_1 == T::ZERO && y_0 == T::ZERO { return if bit { -1 } else { 1 }; } // x <- |x - y| x_0 = (mask ^ diff_0).wrapping_sub(mask); x_1 = mask ^ diff_1; if x_0 == T::ZERO { // If y > x, x_0 == 0 implies that we have a carry to propagate. x_0 = x_1.wrapping_sub(mask); x_1 = T::ZERO; } let c = x_0.trailing_zeros() + 1; if c.odd() && (y_0 ^ (y_0 >> 1)).odd() { bit.not_assign(); } if c == T::WIDTH { x_0 = x_1; x_1 = T::ZERO; } else { x_0 = (x_1 << (T::WIDTH - c)) | (x_0 >> c); x_1 >>= c; } } assert_ne!(y_0, T::ZERO); while (x_0 | y_0).get_highest_bit() { // Need an extra comparison to get the mask. let t = x_0.wrapping_sub(y_0); let mask = if y_0 > x_0 { T::MAX } else { T::ZERO }; if t == T::ZERO { return 0; } // If y > x, invoke reciprocity if (mask & x_0 & y_0).odd() { bit.not_assign(); } // y <- min(x, y) y_0.wrapping_add_assign(mask & t); // x <- |x - y| x_0 = (t ^ mask).wrapping_sub(mask); // Number of trailing zeros is the same no matter if we look at t or x, but using t gives // more parallelism. let c = t.trailing_zeros() + 1; // (2 / y) = -1 if y = 3 or 5 mod 8 if c.odd() && (y_0 ^ (y_0 >> 1)).odd() { bit.not_assign(); } if c == T::WIDTH { return if bit { -1 } else { 1 }; } x_0 >>= c; } let j = ((x_0 << 1u32) | T::ONE).jacobi_symbol((y_0 << 1u32) | T::ONE); if bit { -j } else { j } } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . pub mod extended_gcd; pub mod factorial; pub mod kronecker_symbol; pub mod mod_inverse; pub mod mod_mul; pub mod mod_pow; pub mod mod_power_of_2_inverse; pub mod primorial; ================================================ FILE: malachite-base/src/test_util/num/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::test_util::num::arithmetic::extended_gcd::extended_gcd_unsigned_euclidean; pub fn mod_inverse_euclidean< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( x: U, m: U, ) -> Option { assert_ne!(x, U::ZERO); assert!(x < m); let (gcd, inverse, _) = extended_gcd_unsigned_euclidean::(x, m); if gcd == U::ONE { Some(if inverse >= S::ZERO { U::wrapping_from(inverse) } else { U::wrapping_from(inverse).wrapping_add(m) }) } else { None } } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::HasHalf; pub fn limbs_invert_limb_naive< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + PrimitiveUnsigned, >( x: T, ) -> T { T::exact_from(DT::MAX / DT::from(x) - DT::power_of_2(T::WIDTH)) } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; pub fn naive_mod_pow(x: T, exp: u64, m: T) -> T { if m == T::ONE { return T::ZERO; } let data = T::precompute_mod_mul_data(&m); let mut out = T::ONE; for _ in 0..exp { out.mod_mul_precomputed_assign(x, m, &data); } out } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::test_util::num::arithmetic::extended_gcd::extended_gcd_unsigned_euclidean; pub fn mod_power_of_2_inverse_euclidean< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >( a: U, pow: u64, ) -> Option { assert_ne!(a, U::ZERO); assert!(pow <= U::WIDTH); assert!(a.significant_bits() <= pow); if a.even() { return None; } else if a == U::ONE { return Some(U::ONE); } Some(if pow == U::WIDTH { let (q, r) = U::xx_div_mod_y_to_qr(U::ONE, U::ZERO, a); let (_, x, y) = extended_gcd_unsigned_euclidean(r, a); U::wrapping_from(y - S::wrapping_from(q) * x) } else { let m = U::power_of_2(pow); let (_, x, _) = extended_gcd_unsigned_euclidean::(a, m); if x >= S::ZERO { U::wrapping_from(x) } else { U::wrapping_from(x).wrapping_add(m) } }) } ================================================ FILE: malachite-base/src/test_util/num/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; pub fn checked_primorial_naive(n: u64) -> Option { let n = T::try_from(n).ok()?; let mut f = T::ONE; for p in T::primes().take_while(|&p| p <= n) { f = f.checked_mul(p)?; } Some(f) } pub fn checked_product_of_first_n_primes_naive(n: u64) -> Option { let mut f = T::ONE; for p in T::primes().take(usize::try_from(n).ok()?) { f = f.checked_mul(p)?; } Some(f) } ================================================ FILE: malachite-base/src/test_util/num/conversion/mod.rs ================================================ // Copyright © 2026 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 . pub mod string; ================================================ FILE: malachite-base/src/test_util/num/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 . pub const DECIMAL_SCI_STRING_CHARS: &str = "+-.0123456789Ee"; ================================================ FILE: malachite-base/src/test_util/num/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . pub mod from_sci_string; pub mod to_string; ================================================ FILE: malachite-base/src/test_util/num/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{DivAssignMod, UnsignedAbs}; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::traits::Zero; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::string::to_string::digit_to_display_byte_lower; use crate::num::conversion::traits::WrappingFrom; pub fn to_string_base_unsigned_naive(mut x: T, base: u8) -> String where u8: WrappingFrom, { assert!((2..=36).contains(&base), "base out of range"); if x == T::ZERO { "0".to_string() } else { let base = T::from(base); let mut cs = Vec::new(); while x != T::ZERO { cs.push(char::from( digit_to_display_byte_lower(u8::wrapping_from(x.div_assign_mod(base))).unwrap(), )); } cs.into_iter().rev().collect() } } pub fn to_string_base_signed_naive(x: T, base: u8) -> String where u8: WrappingFrom<::Output>, ::Output: PrimitiveUnsigned, { assert!((2..=36).contains(&base), "base out of range"); if x == T::ZERO { "0".to_string() } else { let base = ::Output::from(base); let mut cs = Vec::new(); let mut abs_x = x.unsigned_abs(); while abs_x != ::Output::ZERO { cs.push(char::from( digit_to_display_byte_lower(u8::wrapping_from(abs_x.div_assign_mod(base))).unwrap(), )); } if x < T::ZERO { cs.push('-'); } cs.into_iter().rev().collect() } } ================================================ FILE: malachite-base/src/test_util/num/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::num::basic::floats::PrimitiveFloat; use crate::num::float::NiceFloat; use itertools::Itertools; pub fn exhaustive_primitive_floats_helper_helper_with_limit< T: PrimitiveFloat, I: Iterator, >( limit: usize, xs: I, out: &[T], ) { assert_eq!( xs.take(limit).map(NiceFloat).collect_vec(), out.iter().copied().map(NiceFloat).collect_vec() ); } pub fn exhaustive_primitive_floats_helper_helper>( xs: I, out: &[T], ) { exhaustive_primitive_floats_helper_helper_with_limit(50, xs, out); } pub fn exhaustive_primitive_floats_helper_helper_with_reverse< T: PrimitiveFloat, I: Clone + DoubleEndedIterator, >( xs: I, first_20: &[T], last_20: &[T], ) { assert_eq!( xs.clone().take(20).map(NiceFloat).collect_vec(), first_20.iter().copied().map(NiceFloat).collect_vec() ); let mut reversed = xs.rev().take(20).map(NiceFloat).collect_vec(); reversed.reverse(); assert_eq!( reversed, last_20.iter().copied().map(NiceFloat).collect_vec() ); } ================================================ FILE: malachite-base/src/test_util/num/factorization/factor.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingInto; use crate::test_util::common::rle_encode; pub fn factor_naive(mut n: T) -> Vec<(T, u8)> { assert_ne!(n, T::ZERO); if n == T::ONE { return Vec::new(); } let mut factors = Vec::new(); 'outer: loop { let limit = n.floor_sqrt(); for p in T::primes().take_while(|&p| p <= limit) { let (q, r) = n.div_mod(p); if r == T::ZERO { factors.push(p); n = q; continue 'outer; } } factors.push(n); break; } rle_encode(factors.into_iter()) .into_iter() .map(|(p, e)| { let e: u8 = e.wrapping_into(); (p, e) }) .collect() } ================================================ FILE: malachite-base/src/test_util/num/factorization/is_prime.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use std::cmp::Ordering::*; pub fn is_prime_naive(n: T) -> bool { match n.cmp(&T::TWO) { Less => false, Equal => true, Greater => { if n.even() { return false; } let limit = n.floor_sqrt(); let mut i = T::from(3u8); while i <= limit { if n.divisible_by(i) { return false; } i += T::TWO; } true } } } ================================================ FILE: malachite-base/src/test_util/num/factorization/mod.rs ================================================ // Copyright © 2026 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 . pub mod factor; pub mod is_prime; pub mod prime_sieve; pub mod primes; ================================================ FILE: malachite-base/src/test_util/num/factorization/prime_sieve.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{CheckedSquare, DivisibleBy, Parity}; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::factorization::prime_sieve::{id_to_n, limbs_count_ones, n_to_bit}; use crate::num::factorization::traits::IsPrime; use crate::num::logic::traits::{NotAssign, TrailingZeros}; use crate::slices::slice_leading_zeros; pub fn limbs_prime_sieve_naive_1(bit_array: &mut [T], n: u64) -> u64 { assert!(n > 4); let mut f = 5; let mut b = false; 'outer: for x in &mut *bit_array { *x = T::MAX; for i in 0..T::WIDTH { if f.is_prime() { x.clear_bit(i); } f += if b { 4 } else { 2 }; if f > n { break 'outer; } b.not_assign(); } } (u64::exact_from(bit_array.len()) << T::LOG_WIDTH) - limbs_count_ones(bit_array) } fn limbs_index_of_next_true_bit(xs: &[T], start: u64) -> Option { let starting_index = usize::exact_from(start >> T::LOG_WIDTH); if starting_index >= xs.len() { None } else if let Some(result) = xs[starting_index].index_of_next_true_bit(start & T::WIDTH_MASK) { Some((u64::wrapping_from(starting_index) << T::LOG_WIDTH) + result) } else if starting_index == xs.len() - 1 { None } else { let true_index = starting_index + 1 + slice_leading_zeros(&xs[starting_index + 1..]); if true_index == xs.len() { None } else { let result_offset = u64::wrapping_from(true_index) << T::LOG_WIDTH; Some( result_offset .checked_add(TrailingZeros::trailing_zeros(xs[true_index])) .unwrap(), ) } } } fn limbs_set_bit_helper(xs: &mut [T], index: u64, limb_index: usize) { xs[limb_index].set_bit(index & T::WIDTH_MASK); } fn limbs_slice_set_bit(xs: &mut [T], index: u64) { limbs_set_bit_helper(xs, index, usize::exact_from(index >> T::LOG_WIDTH)); } fn limbs_clear_bit(xs: &mut [T], index: u64) { let small_index = usize::exact_from(index >> T::LOG_WIDTH); if small_index < xs.len() { xs[small_index].clear_bit(index & T::WIDTH_MASK); } } pub fn limbs_prime_sieve_naive_2(bit_array: &mut [T], n: u64) -> u64 { assert!(n > 4); for x in &mut *bit_array { *x = T::MAX; } let mut p = 0; loop { let id = limbs_index_of_next_true_bit(bit_array, if p == 0 { 0 } else { n_to_bit(p) + 1 }); if let Some(id) = id { p = id_to_n(id + 1); } else { break; } let m = p.checked_square(); if m.is_none() { break; } let mut m = m.unwrap(); if m > n { break; } let two_p = p << 1; while m <= n { if m.odd() && !m.divisible_by(3) { limbs_clear_bit(bit_array, n_to_bit(m)); } m += two_p; } } for x in &mut *bit_array { x.not_assign(); } let bit_len = u64::exact_from(bit_array.len()) << T::LOG_WIDTH; for i in (0..bit_len).rev() { if id_to_n(i + 1) <= n { break; } limbs_slice_set_bit(bit_array, i); } bit_len - limbs_count_ones(bit_array) } ================================================ FILE: malachite-base/src/test_util/num/factorization/primes.rs ================================================ // Copyright © 2026 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 crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::exhaustive::primitive_int_increasing_inclusive_range; pub struct PrimesNaive(T); impl Iterator for PrimesNaive { type Item = T; fn next(&mut self) -> Option { if self.0 == T::ONE { self.0 = T::TWO; return Some(self.0); } else if self.0 == T::TWO { self.0 = T::from(3u8); return Some(self.0); } 'outer: loop { self.0 = self.0.checked_add(T::TWO)?; let a = T::from(3u8); let b = self.0.floor_sqrt(); if a <= b { for f in primitive_int_increasing_inclusive_range(a, b) { if self.0.divisible_by(f) { continue 'outer; } } } return Some(self.0); } } } pub const fn primes_naive() -> PrimesNaive { // 1 will never actually be generated PrimesNaive(T::ONE) } ================================================ FILE: malachite-base/src/test_util/num/float/mod.rs ================================================ // Copyright © 2026 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 . pub const PRIMITIVE_FLOAT_CHARS: &str = "-.0123456789INaefinty"; ================================================ FILE: malachite-base/src/test_util/num/logic/bit_block_access.rs ================================================ // Copyright © 2026 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 crate::num::basic::traits::Zero; use crate::num::logic::traits::BitAccess; pub fn get_bits_naive(n: &T, start: u64, end: u64) -> U { let mut result = U::ZERO; for i in start..end { if n.get_bit(i) { result.set_bit(i - start); } } result } pub fn assign_bits_naive(n: &mut T, start: u64, end: u64, bits: &U) { for i in start..end { n.assign_bit(i, bits.get_bit(i - start)); } } ================================================ FILE: malachite-base/src/test_util/num/logic/bit_convertible.rs ================================================ // Copyright © 2026 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 crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::ExactFrom; use crate::num::logic::traits::BitConvertible; use itertools::Itertools; pub fn to_bits_asc_alt(n: &T) -> Vec { let mut bits = n.to_bits_desc(); bits.reverse(); bits } pub fn to_bits_desc_alt(n: &T) -> Vec { let mut bits = n.to_bits_asc(); bits.reverse(); bits } pub fn from_bits_asc_alt>(bits: I) -> T { let mut bits = bits.collect_vec(); bits.reverse(); T::from_bits_desc(bits.into_iter()) } pub fn from_bits_desc_alt>(bits: I) -> T { let mut bits = bits.collect_vec(); bits.reverse(); T::from_bits_asc(bits.into_iter()) } pub fn to_bits_asc_unsigned_naive(n: T) -> Vec { let mut bits = Vec::new(); for i in 0..n.significant_bits() { bits.push(n.get_bit(i)); } bits } pub fn to_bits_desc_unsigned_naive(n: T) -> Vec { let mut bits = Vec::new(); for i in (0..n.significant_bits()).rev() { bits.push(n.get_bit(i)); } bits } pub fn from_bits_asc_unsigned_naive>(bits: I) -> T { let mut n = T::ZERO; for i in bits .enumerate() .filter_map(|(i, bit)| if bit { Some(u64::exact_from(i)) } else { None }) { n.set_bit(i); } n } pub fn to_bits_asc_signed_naive(n: T) -> Vec { let mut bits = Vec::new(); if n == T::ZERO { return bits; } for i in 0..n.significant_bits() { bits.push(n.get_bit(i)); } let last_bit = *bits.last().unwrap(); if last_bit != (n < T::ZERO) { bits.push(!last_bit); } bits } pub fn to_bits_desc_signed_naive(n: T) -> Vec { let mut bits = Vec::new(); if n == T::ZERO { return bits; } let significant_bits = n.significant_bits(); let last_bit = n.get_bit(significant_bits - 1); if last_bit != (n < T::ZERO) { bits.push(!last_bit); } for i in (0..significant_bits).rev() { bits.push(n.get_bit(i)); } bits } pub fn from_bits_asc_signed_naive>(bits: I) -> T { let bits = bits.collect_vec(); if bits.is_empty() { return T::ZERO; } let mut n; if *bits.last().unwrap() { n = T::NEGATIVE_ONE; for i in bits .iter() .enumerate() .filter_map(|(i, &bit)| if bit { None } else { Some(u64::exact_from(i)) }) { n.clear_bit(i); } } else { n = T::ZERO; for i in bits .iter() .enumerate() .filter_map(|(i, &bit)| if bit { Some(u64::exact_from(i)) } else { None }) { n.set_bit(i); } }; n } ================================================ FILE: malachite-base/src/test_util/num/logic/mod.rs ================================================ // Copyright © 2026 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 . pub mod bit_block_access; pub mod bit_convertible; ================================================ FILE: malachite-base/src/test_util/num/mod.rs ================================================ // Copyright © 2026 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 . pub mod arithmetic; pub mod conversion; pub mod exhaustive; pub mod factorization; pub mod float; pub mod logic; pub mod random; ================================================ FILE: malachite-base/src/test_util/num/random/geometric.rs ================================================ // Copyright © 2026 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 crate::num::basic::floats::PrimitiveFloat; use crate::num::basic::integers::PrimitiveInt; use crate::num::logic::traits::BitAccess; use std::cmp::Ordering::*; pub fn unadjusted_mean_to_adjusted_mean(unadjusted_mean: f64, limit: f64) -> f64 { let m = limit; assert!(unadjusted_mean > 0.0); assert!(m > 0.0); let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let pow = q.powf(m + 1.0); let adjusted = ((m * p + 1.0) * pow - q) / (p * (pow - 1.0)); adjusted.abs() } pub fn adjusted_mean_to_unadjusted_mean(adjusted_mean: f64, limit: f64) -> f64 { assert!(adjusted_mean > 0.0); assert!(adjusted_mean < limit / 2.0); let mut min = f64::MIN_POSITIVE_SUBNORMAL.to_ordered_representation(); let mut max = f64::MAX_FINITE.to_ordered_representation(); loop { if min == max { let f_max = unadjusted_mean_to_adjusted_mean(f64::from_ordered_representation(max), limit); assert!(!f_max.is_nan() && f_max <= limit && f_max >= adjusted_mean); return f64::from_ordered_representation(max); } let (sum, overflow) = min.overflowing_add(max); let mut mid = sum >> 1; if overflow { mid.set_bit(u64::WIDTH - 1); } let f_mid = unadjusted_mean_to_adjusted_mean(f64::from_ordered_representation(mid), limit); let compare = if f_mid.is_nan() { Greater } else { f_mid.partial_cmp(&adjusted_mean).unwrap() }; match compare { Greater => max = mid, Less => min = mid + 1, Equal => return f64::from_ordered_representation(mid), } } } ================================================ FILE: malachite-base/src/test_util/num/random/mod.rs ================================================ // Copyright © 2026 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 crate::num::basic::floats::PrimitiveFloat; use crate::num::float::NiceFloat; use crate::test_util::stats::common_values_map::common_values_map; use crate::test_util::stats::median; use crate::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use itertools::Itertools; pub fn random_primitive_floats_helper_helper< T: CheckedToF64 + PrimitiveFloat, I: Clone + Iterator, >( xs: I, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { let actual_values = xs.clone().take(20).map(NiceFloat).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone().map(NiceFloat)); let actual_median = median(xs.clone().map(NiceFloat).take(1000000)); let actual_moment_stats = moment_stats(xs.take(1000000)); let (lo, hi) = expected_median; assert_eq!( ( actual_values, actual_common_values.as_slice(), actual_median, actual_moment_stats ), ( expected_values.iter().copied().map(NiceFloat).collect_vec(), expected_common_values .iter() .map(|&(x, freq)| (NiceFloat(x), freq)) .collect_vec() .as_slice(), (NiceFloat(lo), hi.map(NiceFloat)), expected_moment_stats ) ); } pub fn special_random_primitive_floats_helper_helper< T: CheckedToF64 + PrimitiveFloat, I: Clone + Iterator, >( xs: I, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { let actual_values = xs.clone().take(50).map(NiceFloat).collect_vec(); let actual_common_values = common_values_map(1000000, 20, xs.clone().map(NiceFloat)); let actual_median = median(xs.clone().map(NiceFloat).take(1000000)); let actual_moment_stats = moment_stats(xs.take(1000000)); let (lo, hi) = expected_median; assert_eq!( ( actual_values, actual_common_values.as_slice(), actual_median, actual_moment_stats ), ( expected_values.iter().copied().map(NiceFloat).collect_vec(), expected_common_values .iter() .map(|&(x, freq)| (NiceFloat(x), freq)) .collect_vec() .as_slice(), (NiceFloat(lo), hi.map(NiceFloat)), expected_moment_stats ) ); } pub mod geometric; ================================================ FILE: malachite-base/src/test_util/rounding_modes/mod.rs ================================================ // Copyright © 2026 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 . pub const ROUNDING_MODE_CHARS: &str = "CDEFNUacegilnoprstwx"; ================================================ FILE: malachite-base/src/test_util/runner/cmd.rs ================================================ // Copyright © 2026 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 crate::test_util::generators::common::{GenConfig, GenMode}; use clap::{App, Arg}; use itertools::Itertools; use std::str::FromStr; #[derive(Clone, Debug)] pub struct CommandLineArguments { pub codegen_key: Option, pub demo_key: Option, pub bench_key: Option, pub generation_mode: GenMode, pub config: GenConfig, pub limit: usize, pub out: String, } pub fn read_command_line_arguments(name: &str) -> CommandLineArguments { let matches = App::new(name) .version("0.1.0") .author("Mikhail Hogrefe ") .about("Runs demos and benchmarks for malachite-base functions.") .arg( Arg::with_name("generation_mode") .short("m") .long("generation_mode") .help("May be 'exhaustive', 'random', or 'special_random'.") .takes_value(true), ) .arg( Arg::with_name("config") .short("c") .long("config") .help("e.g. 'mean_run_length_n 4 mean_run_length_d 1'") .takes_value(true), ) .arg( Arg::with_name("limit") .short("l") .long("limit") .help("Specifies the maximum number of elements to generate") .takes_value(true), ) .arg( Arg::with_name("out") .short("o") .long("out") .help("Specifies the file name to write a benchmark to") .takes_value(true), ) .arg( Arg::with_name("demo") .short("d") .long("demo") .help("Specifies the demo name") .takes_value(true), ) .arg( Arg::with_name("bench") .short("b") .long("bench") .help("Specifies the benchmark name") .takes_value(true), ) .arg( Arg::with_name("codegen") .short("g") .long("codegen") .help("Specifies the code to generate") .takes_value(true), ) .get_matches(); let generation_mode = match matches.value_of("generation_mode").unwrap_or("exhaustive") { "exhaustive" => GenMode::Exhaustive, "random" => GenMode::Random, "special_random" => GenMode::SpecialRandom, _ => panic!("Invalid generation mode"), }; let config_string = matches.value_of("config").unwrap_or(""); let mut config = GenConfig::new(); if !config_string.is_empty() { for mut chunk in &config_string.split(' ').chunks(2) { let key = chunk.next().unwrap(); let value = u64::from_str(chunk.next().expect("Bad config")).expect("Invalid config value"); config.insert(key, value); } } let limit = usize::from_str(matches.value_of("limit").unwrap_or("10000")).expect("Invalid limit"); let out = matches.value_of("out").unwrap_or("temp.gp").to_string(); let demo_key = matches.value_of("demo").map(ToString::to_string); let bench_key = matches.value_of("bench").map(ToString::to_string); let codegen_key = matches.value_of("codegen").map(ToString::to_string); assert!( demo_key.is_some() || bench_key.is_some() || codegen_key.is_some(), "Must specify demo, bench, or codegen" ); CommandLineArguments { codegen_key, demo_key, bench_key, generation_mode, config, limit, out, } } ================================================ FILE: malachite-base/src/test_util/runner/mod.rs ================================================ // Copyright © 2026 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 crate::test_util::generators::common::{GenConfig, GenMode}; use std::collections::HashMap; pub type DemoFn = &'static dyn Fn(GenMode, &GenConfig, usize); pub type BenchFn = &'static dyn Fn(GenMode, &GenConfig, usize, &str); pub struct Runner { demo_map: HashMap<&'static str, DemoFn>, bench_map: HashMap<&'static str, BenchFn>, } impl Runner { pub fn new() -> Self { Self { demo_map: HashMap::new(), bench_map: HashMap::new(), } } pub fn run_demo(&self, key: &str, gm: GenMode, config: &GenConfig, limit: usize) { self.demo_map.get(key).expect("Invalid demo key")(gm, config, limit); } pub fn run_bench( &self, key: &str, gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { self.bench_map.get(key).expect("Invalid bench key")(gm, config, limit, file_name); } pub fn register_demo(&mut self, key: &'static str, f: DemoFn) { assert!( self.demo_map.insert(key, f).is_none(), "Duplicate demo with key {key}", ); } pub fn register_bench(&mut self, key: &'static str, f: BenchFn) { assert!( self.bench_map.insert(key, f).is_none(), "Duplicate bench with key {key}", ); } } impl Default for Runner { fn default() -> Self { Self::new() } } #[macro_export] macro_rules! register_demo { ($runner: ident, $f: ident) => { $runner.register_demo(stringify!($f), &$f); }; } #[macro_export] macro_rules! register_generic_demos { ($runner: ident, $f: ident $(,$t:ty)*) => { $( $runner.register_demo(concat!(stringify!($f), "_", stringify!($t)), &$f::<$t>); )* }; } #[macro_export] macro_rules! register_generic_demos_2 { ($runner: ident, $f: ident $(,[$t:ty, $u:ty])*) => { $( $runner.register_demo( concat!(stringify!($f), "_", stringify!($t), "_", stringify!($u)), &$f::<$t, $u> ); )* }; } #[macro_export] macro_rules! register_generic_demos_3_only_1_3_in_key { ($runner: ident, $f: ident $(,[$t:ty, $u:ty, $v:ty])*) => { $( $runner.register_demo( concat!(stringify!($f), "_", stringify!($t), "_", stringify!($v)), &$f::<$t, $u, $v> ); )* }; } #[macro_export] macro_rules! register_generic_benches_3_only_1_3_in_key { ($runner: ident, $f: ident $(,[$t:ty, $u:ty, $v:ty])*) => { $( $runner.register_bench( concat!(stringify!($f), "_", stringify!($t), "_", stringify!($v)), &$f::<$t, $u, $v> ); )* }; } #[macro_export] macro_rules! register_generic_demos_2_only_first_in_key { ($runner: ident, $f: ident $(,[$t:ty, $u:ty])*) => { $( $runner.register_demo( concat!(stringify!($f), "_", stringify!($t)), &$f::<$t, $u> ); )* }; } #[macro_export] macro_rules! register_unsigned_demos { ($runner: ident, $f: ident) => { register_generic_demos!($runner, $f, u8, u16, u32, u64, u128, usize); }; } #[macro_export] macro_rules! register_signed_demos { ($runner: ident, $f: ident) => { register_generic_demos!($runner, $f, i8, i16, i32, i64, i128, isize); }; } #[macro_export] macro_rules! register_primitive_float_demos { ($runner: ident, $f: ident) => { register_generic_demos!($runner, $f, f32, f64); }; } #[macro_export] macro_rules! register_primitive_float_unsigned_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [f32, u8], [f32, u16], [f32, u32], [f32, u64], [f32, u128], [f32, usize], [f64, u8], [f64, u16], [f64, u32], [f64, u64], [f64, u128], [f64, usize] ); }; } #[macro_export] macro_rules! register_primitive_float_signed_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [f32, i8], [f32, i16], [f32, i32], [f32, i64], [f32, i128], [f32, isize], [f64, i8], [f64, i16], [f64, i32], [f64, i64], [f64, i128], [f64, isize] ); }; } #[macro_export] macro_rules! register_signed_unsigned_match_demos { ($runner: ident, $f: ident) => { register_generic_demos_2_only_first_in_key!( $runner, $f, [i8, u8], [i16, u16], [i32, u32], [i64, u64], [i128, u128], [isize, usize] ); }; } #[macro_export] macro_rules! register_unsigned_signed_match_demos { ($runner: ident, $f: ident) => { register_generic_demos_2_only_first_in_key!( $runner, $f, [u8, i8], [u16, i16], [u32, i32], [u64, i64], [u128, i128], [usize, isize] ); }; } #[macro_export] macro_rules! register_primitive_int_demos { ($runner: ident, $f: ident) => { register_unsigned_demos!($runner, $f); register_signed_demos!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_unsigned_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [u8, u8], [u8, u16], [u8, u32], [u8, u64], [u8, u128], [u8, usize], [u16, u8], [u16, u16], [u16, u32], [u16, u64], [u16, u128], [u16, usize], [u32, u8], [u32, u16], [u32, u32], [u32, u64], [u32, u128], [u32, usize], [u64, u8], [u64, u16], [u64, u32], [u64, u64], [u64, u128], [u64, usize], [u128, u8], [u128, u16], [u128, u32], [u128, u64], [u128, u128], [u128, usize], [usize, u8], [usize, u16], [usize, u32], [usize, u64], [usize, u128], [usize, usize] ); }; } #[macro_export] macro_rules! register_signed_unsigned_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [i8, u8], [i8, u16], [i8, u32], [i8, u64], [i8, u128], [i8, usize], [i16, u8], [i16, u16], [i16, u32], [i16, u64], [i16, u128], [i16, usize], [i32, u8], [i32, u16], [i32, u32], [i32, u64], [i32, u128], [i32, usize], [i64, u8], [i64, u16], [i64, u32], [i64, u64], [i64, u128], [i64, usize], [i128, u8], [i128, u16], [i128, u32], [i128, u64], [i128, u128], [i128, usize], [isize, u8], [isize, u16], [isize, u32], [isize, u64], [isize, u128], [isize, usize] ); }; } #[macro_export] macro_rules! register_primitive_int_unsigned_demos { ($runner: ident, $f: ident) => { register_unsigned_unsigned_demos!($runner, $f); register_signed_unsigned_demos!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_signed_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [u8, i8], [u8, i16], [u8, i32], [u8, i64], [u8, i128], [u8, isize], [u16, i8], [u16, i16], [u16, i32], [u16, i64], [u16, i128], [u16, isize], [u32, i8], [u32, i16], [u32, i32], [u32, i64], [u32, i128], [u32, isize], [u64, i8], [u64, i16], [u64, i32], [u64, i64], [u64, i128], [u64, isize], [u128, i8], [u128, i16], [u128, i32], [u128, i64], [u128, i128], [u128, isize], [usize, i8], [usize, i16], [usize, i32], [usize, i64], [usize, i128], [usize, isize] ); }; } #[macro_export] macro_rules! register_unsigned_unsigned_signed_match_demos { ($runner: ident, $f: ident) => { register_generic_demos_3_only_1_3_in_key!( $runner, $f, [u8, u8, i8], [u8, u16, i16], [u8, u32, i32], [u8, u64, i64], [u8, u128, i128], [u8, usize, isize], [u16, u8, i8], [u16, u16, i16], [u16, u32, i32], [u16, u64, i64], [u16, u128, i128], [u16, usize, isize], [u32, u8, i8], [u32, u16, i16], [u32, u32, i32], [u32, u64, i64], [u32, u128, i128], [u32, usize, isize], [u64, u8, i8], [u64, u16, i16], [u64, u32, i32], [u64, u64, i64], [u64, u128, i128], [u64, usize, isize], [u128, u8, i8], [u128, u16, i16], [u128, u32, i32], [u128, u64, i64], [u128, u128, i128], [u128, usize, isize], [usize, u8, i8], [usize, u16, i16], [usize, u32, i32], [usize, u64, i64], [usize, u128, i128], [usize, usize, isize] ); }; } #[macro_export] macro_rules! register_signed_signed_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [i8, i8], [i8, i16], [i8, i32], [i8, i64], [i8, i128], [i8, isize], [i16, i8], [i16, i16], [i16, i32], [i16, i64], [i16, i128], [i16, isize], [i32, i8], [i32, i16], [i32, i32], [i32, i64], [i32, i128], [i32, isize], [i64, i8], [i64, i16], [i64, i32], [i64, i64], [i64, i128], [i64, isize], [i128, i8], [i128, i16], [i128, i32], [i128, i64], [i128, i128], [i128, isize], [isize, i8], [isize, i16], [isize, i32], [isize, i64], [isize, i128], [isize, isize] ); }; } #[macro_export] macro_rules! register_primitive_int_signed_demos { ($runner: ident, $f: ident) => { register_unsigned_signed_demos!($runner, $f); register_signed_signed_demos!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_primitive_float_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [u8, f32], [u8, f64], [u16, f32], [u16, f64], [u32, f32], [u32, f64], [u64, f32], [u64, f64], [u128, f32], [u128, f64], [usize, f32], [usize, f64] ); }; } #[macro_export] macro_rules! register_signed_primitive_float_demos { ($runner: ident, $f: ident) => { register_generic_demos_2!( $runner, $f, [i8, f32], [i8, f64], [i16, f32], [i16, f64], [i32, f32], [i32, f64], [i64, f32], [i64, f64], [i128, f32], [i128, f64], [isize, f32], [isize, f64] ); }; } #[macro_export] macro_rules! register_primitive_int_primitive_float_demos { ($runner: ident, $f: ident) => { register_unsigned_primitive_float_demos!($runner, $f); register_signed_primitive_float_demos!($runner, $f); }; } #[macro_export] macro_rules! register_bench { ($runner: ident, $f: ident) => { $runner.register_bench(stringify!($f), &$f); }; } #[macro_export] macro_rules! register_generic_benches { ($runner: ident, $f: ident $(,$t:ty)*) => { $( $runner.register_bench(concat!(stringify!($f), "_", stringify!($t)), &$f::<$t>); )* }; } #[macro_export] macro_rules! register_generic_benches_2 { ($runner: ident, $f: ident $(,[$t:ty, $u:ty])*) => { $( $runner.register_bench( concat!(stringify!($f), "_", stringify!($t), "_", stringify!($u)), &$f::<$t, $u> ); )* }; } #[macro_export] macro_rules! register_generic_benches_2_only_first_in_key { ($runner: ident, $f: ident $(,[$t:ty, $u:ty])*) => { $( $runner.register_bench( concat!(stringify!($f), "_", stringify!($t)), &$f::<$t, $u> ); )* }; } #[macro_export] macro_rules! register_unsigned_benches { ($runner: ident, $f: ident) => { register_generic_benches!($runner, $f, u8, u16, u32, u64, u128, usize); }; } #[macro_export] macro_rules! register_signed_benches { ($runner: ident, $f: ident) => { register_generic_benches!($runner, $f, i8, i16, i32, i64, i128, isize); }; } #[macro_export] macro_rules! register_primitive_float_benches { ($runner: ident, $f: ident) => { register_generic_benches!($runner, $f, f32, f64); }; } #[macro_export] macro_rules! register_primitive_float_unsigned_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [f32, u8], [f32, u16], [f32, u32], [f32, u64], [f32, u128], [f32, usize], [f64, u8], [f64, u16], [f64, u32], [f64, u64], [f64, u128], [f64, usize] ); }; } #[macro_export] macro_rules! register_primitive_float_signed_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [f32, i8], [f32, i16], [f32, i32], [f32, i64], [f32, i128], [f32, isize], [f64, i8], [f64, i16], [f64, i32], [f64, i64], [f64, i128], [f64, isize] ); }; } #[macro_export] macro_rules! register_signed_unsigned_match_benches { ($runner: ident, $f: ident) => { register_generic_benches_2_only_first_in_key!( $runner, $f, [i8, u8], [i16, u16], [i32, u32], [i64, u64], [i128, u128], [isize, usize] ); }; } #[macro_export] macro_rules! register_unsigned_signed_match_benches { ($runner: ident, $f: ident) => { register_generic_benches_2_only_first_in_key!( $runner, $f, [u8, i8], [u16, i16], [u32, i32], [u64, i64], [u128, i128], [usize, isize] ); }; } #[macro_export] macro_rules! register_primitive_int_benches { ($runner: ident, $f: ident) => { register_unsigned_benches!($runner, $f); register_signed_benches!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_unsigned_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [u8, u8], [u8, u16], [u8, u32], [u8, u64], [u8, u128], [u8, usize], [u16, u8], [u16, u16], [u16, u32], [u16, u64], [u16, u128], [u16, usize], [u32, u8], [u32, u16], [u32, u32], [u32, u64], [u32, u128], [u32, usize], [u64, u8], [u64, u16], [u64, u32], [u64, u64], [u64, u128], [u64, usize], [u128, u8], [u128, u16], [u128, u32], [u128, u64], [u128, u128], [u128, usize], [usize, u8], [usize, u16], [usize, u32], [usize, u64], [usize, u128], [usize, usize] ); }; } #[macro_export] macro_rules! register_signed_unsigned_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [i8, u8], [i8, u16], [i8, u32], [i8, u64], [i8, u128], [i8, usize], [i16, u8], [i16, u16], [i16, u32], [i16, u64], [i16, u128], [i16, usize], [i32, u8], [i32, u16], [i32, u32], [i32, u64], [i32, u128], [i32, usize], [i64, u8], [i64, u16], [i64, u32], [i64, u64], [i64, u128], [i64, usize], [i128, u8], [i128, u16], [i128, u32], [i128, u64], [i128, u128], [i128, usize], [isize, u8], [isize, u16], [isize, u32], [isize, u64], [isize, u128], [isize, usize] ); }; } #[macro_export] macro_rules! register_primitive_int_unsigned_benches { ($runner: ident, $f: ident) => { register_unsigned_unsigned_benches!($runner, $f); register_signed_unsigned_benches!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_signed_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [u8, i8], [u8, i16], [u8, i32], [u8, i64], [u8, i128], [u8, isize], [u16, i8], [u16, i16], [u16, i32], [u16, i64], [u16, i128], [u16, isize], [u32, i8], [u32, i16], [u32, i32], [u32, i64], [u32, i128], [u32, isize], [u64, i8], [u64, i16], [u64, i32], [u64, i64], [u64, i128], [u64, isize], [u128, i8], [u128, i16], [u128, i32], [u128, i64], [u128, i128], [u128, isize], [usize, i8], [usize, i16], [usize, i32], [usize, i64], [usize, i128], [usize, isize] ); }; } #[macro_export] macro_rules! register_unsigned_unsigned_signed_match_benches { ($runner: ident, $f: ident) => { register_generic_benches_3_only_1_3_in_key!( $runner, $f, [u8, u8, i8], [u8, u16, i16], [u8, u32, i32], [u8, u64, i64], [u8, u128, i128], [u8, usize, isize], [u16, u8, i8], [u16, u16, i16], [u16, u32, i32], [u16, u64, i64], [u16, u128, i128], [u16, usize, isize], [u32, u8, i8], [u32, u16, i16], [u32, u32, i32], [u32, u64, i64], [u32, u128, i128], [u32, usize, isize], [u64, u8, i8], [u64, u16, i16], [u64, u32, i32], [u64, u64, i64], [u64, u128, i128], [u64, usize, isize], [u128, u8, i8], [u128, u16, i16], [u128, u32, i32], [u128, u64, i64], [u128, u128, i128], [u128, usize, isize], [usize, u8, i8], [usize, u16, i16], [usize, u32, i32], [usize, u64, i64], [usize, u128, i128], [usize, usize, isize] ); }; } #[macro_export] macro_rules! register_signed_signed_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [i8, i8], [i8, i16], [i8, i32], [i8, i64], [i8, i128], [i8, isize], [i16, i8], [i16, i16], [i16, i32], [i16, i64], [i16, i128], [i16, isize], [i32, i8], [i32, i16], [i32, i32], [i32, i64], [i32, i128], [i32, isize], [i64, i8], [i64, i16], [i64, i32], [i64, i64], [i64, i128], [i64, isize], [i128, i8], [i128, i16], [i128, i32], [i128, i64], [i128, i128], [i128, isize], [isize, i8], [isize, i16], [isize, i32], [isize, i64], [isize, i128], [isize, isize] ); }; } #[macro_export] macro_rules! register_primitive_int_signed_benches { ($runner: ident, $f: ident) => { register_unsigned_signed_benches!($runner, $f); register_signed_signed_benches!($runner, $f); }; } #[macro_export] macro_rules! register_unsigned_primitive_float_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [u8, f32], [u8, f64], [u16, f32], [u16, f64], [u32, f32], [u32, f64], [u64, f32], [u64, f64], [u128, f32], [u128, f64], [usize, f32], [usize, f64] ); }; } #[macro_export] macro_rules! register_signed_primitive_float_benches { ($runner: ident, $f: ident) => { register_generic_benches_2!( $runner, $f, [i8, f32], [i8, f64], [i16, f32], [i16, f64], [i32, f32], [i32, f64], [i64, f32], [i64, f64], [i128, f32], [i128, f64], [isize, f32], [isize, f64] ); }; } #[macro_export] macro_rules! register_primitive_int_primitive_float_benches { ($runner: ident, $f: ident) => { register_unsigned_primitive_float_benches!($runner, $f); register_signed_primitive_float_benches!($runner, $f); }; } pub mod cmd; ================================================ FILE: malachite-base/src/test_util/sets/exhaustive/mod.rs ================================================ // Copyright © 2026 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 . #[cfg(not(feature = "std"))] use alloc::collections::BTreeSet; #[cfg(not(feature = "std"))] use hashbrown::HashSet; use itertools::Itertools; #[cfg(feature = "std")] use std::collections::{BTreeSet, HashSet}; use std::fmt::Debug; use std::hash::Hash; pub fn exhaustive_b_tree_sets_helper_helper< T: Clone + Debug + Ord, I: Iterator>, >( xss: I, out: &[BTreeSet], ) { let xss = xss.take(20).collect_vec(); assert_eq!(xss.into_iter().collect_vec().as_slice(), out); } pub fn exhaustive_b_tree_sets_small_helper_helper< T: Clone + Debug + Ord, I: Clone + Iterator>, >( xss: I, out_len: usize, out: &[BTreeSet], ) { let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!(xss_prefix.into_iter().collect_vec().as_slice(), out); assert_eq!(xss.count(), out_len); } pub fn exhaustive_hash_sets_helper_helper< T: Clone + Debug + Eq + Hash, I: Iterator>, >( xss: I, out: &[HashSet], ) { let xss = xss.take(20).collect_vec(); assert_eq!(xss.into_iter().collect_vec().as_slice(), out); } pub fn exhaustive_hash_sets_small_helper_helper< T: Clone + Debug + Eq + Hash, I: Clone + Iterator>, >( xss: I, out_len: usize, out: &[HashSet], ) { let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!(xss_prefix.into_iter().collect_vec().as_slice(), out); assert_eq!(xss.count(), out_len); } ================================================ FILE: malachite-base/src/test_util/sets/mod.rs ================================================ // Copyright © 2026 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 . pub mod exhaustive; ================================================ FILE: malachite-base/src/test_util/slices/mod.rs ================================================ // Copyright © 2026 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 . pub fn slice_move_left_naive(xs: &mut [T], amount: usize) { let slice = xs[amount..].to_vec(); let limit = xs.len() - amount; xs[..limit].copy_from_slice(&slice); } ================================================ FILE: malachite-base/src/test_util/stats/common_values_map.rs ================================================ // Copyright © 2026 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 crate::strings::ToDebugString; use std::cmp::Ordering; use std::collections::{BinaryHeap, HashMap}; use std::fmt::{Debug, Display}; use std::hash::Hash; macro_rules! impl_common_values_map { ($CommonOrdered: ident, $StringTrait: ident, $to_string: ident, $common_values_map: ident) => { #[derive(Eq, PartialEq)] struct $CommonOrdered { x: T, frequency: usize, } impl PartialOrd for $CommonOrdered { fn partial_cmp(&self, other: &$CommonOrdered) -> Option { Some(self.cmp(other)) } } impl Ord for $CommonOrdered { fn cmp(&self, other: &$CommonOrdered) -> Ordering { other.frequency.cmp(&self.frequency).then_with(|| { let x = self.x.$to_string(); let y = other.x.$to_string(); x.len().cmp(&y.len()).then_with(|| x.cmp(&y)) }) } } /// Takes the first `limit` values of an iterator `xs`. Groups them into (unique value, /// frequency) pairs. Takes the top `n` pairs, preferring ones with high frequency. To break /// ties, prefers values with low `$to_string` representations, where the strings are /// shortlex-ordered (ordered by length, then lexicographically). pub fn $common_values_map( limit: usize, n: usize, xs: I, ) -> Vec<(I::Item, usize)> where I::Item: $StringTrait + Eq + Hash, { assert_ne!(n, 0); let mut frequencies: HashMap = HashMap::new(); for x in xs.take(limit) { *frequencies.entry(x).or_insert(0) += 1; } let mut top_n = BinaryHeap::new(); let mut full = false; for (x, frequency) in frequencies { top_n.push($CommonOrdered { x, frequency }); if full { top_n.pop(); } else if top_n.len() == n { full = true; } } let mut common_values = Vec::new(); while let Some(pair) = top_n.pop() { common_values.push((pair.x, pair.frequency)); } common_values.reverse(); common_values } }; } impl_common_values_map!(CommonOrdered, Display, to_string, common_values_map); impl_common_values_map!( CommonOrderedDebug, Debug, to_debug_string, common_values_map_debug ); ================================================ FILE: malachite-base/src/test_util/stats/median.rs ================================================ // Copyright © 2026 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 crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::test_util::stats::moments::CheckedToF64; pub const fn uniform_bool_median(min: bool, max: bool) -> (bool, Option) { if min == max { (min, None) } else { (false, Some(true)) } } pub fn uniform_primitive_int_median(min: T, max: T) -> (T, Option) { let mut mean = min.wrapping_add(max); mean >>= 1; if mean < min || mean > max { mean.flip_bit(T::WIDTH - 1); } if min.even() == max.even() { (mean, None) } else { (mean, Some(mean + T::ONE)) } } pub fn deleted_uniform_primitive_int_median( min: T, max: T, deleted: T, ) -> (T, Option) { let (mut lo, mut hi) = uniform_primitive_int_median(min, max - T::ONE); if lo >= deleted { lo += T::ONE; } if let Some(hi) = hi.as_mut() && *hi >= deleted { *hi += T::ONE; } (lo, hi) } fn binary_search_median f64, C: Fn(T) -> f64>( mut min: T, mut max: T, pmf: P, cdf: C, ) -> (T, Option) { let initial_median; loop { if min == max { initial_median = Some(min); break; } let mut mean = min.wrapping_add(max); mean >>= 1; if mean < min || mean > max { mean.flip_bit(T::WIDTH - 1); } if 1.0 - cdf(mean) > 0.5 { min = mean + T::ONE; } else if cdf(max) - pmf(max) > 0.5 { max = mean; } else { initial_median = Some(mean); break; } } let mut first_median = initial_median.unwrap(); let mut first_good = false; while 1.0 - cdf(first_median) <= 0.5 && cdf(first_median) - pmf(first_median) <= 0.5 { first_good = true; first_median.wrapping_sub_assign(T::ONE); } assert!(first_good, "could not find median"); first_median.wrapping_add_assign(T::ONE); let mut last_median = first_median.wrapping_add(T::ONE); while 1.0 - cdf(last_median) <= 0.5 && cdf(last_median) - pmf(last_median) <= 0.5 { last_median.wrapping_add_assign(T::ONE); } last_median.wrapping_sub_assign(T::ONE); if first_median == last_median { (first_median, None) } else { (first_median, Some(last_median)) } } fn truncated_geometric_pmf(m: f64, unadjusted_mean: f64, n: f64) -> f64 { if n >= 0.0 && m >= n { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; (q.powf(n) * p) / (1.0 - q.powf(1.0 + m)) } else { 0.0 } } fn truncated_geometric_cdf(m: f64, unadjusted_mean: f64, n: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); if n < 0.0 { 0.0 } else if n <= m { let q = 1.0 - p; (1.0 - q.powf(1.0 + n)) / (1.0 - q.powf(1.0 + m)) } else { 1.0 } } pub fn truncated_geometric_median( min: T, max: T, unadjusted_mean: f64, ) -> (T, Option) { assert!(min >= T::ZERO); assert!(min <= max); let min_64 = min.checked_to_f64(); let max_64 = max.checked_to_f64() - min_64; let unadjusted_mean = unadjusted_mean - min_64; binary_search_median( min, max, |n| truncated_geometric_pmf(max_64, unadjusted_mean, n.checked_to_f64() - min_64), |n| truncated_geometric_cdf(max_64, unadjusted_mean, n.checked_to_f64() - min_64), ) } fn double_nonzero_geometric_pmf(a: f64, b: f64, unadjusted_mean: f64, n: f64) -> f64 { if n == 0.0 || n > a || n < -b { 0.0 } else { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; q.powf(-1.0 + n.abs()) * p / (2.0 - q.powf(a) - q.powf(b)) } } fn double_nonzero_geometric_cdf(a: f64, b: f64, unadjusted_mean: f64, n: f64) -> f64 { if n < -b { return 0.0; } else if n >= a { return 1.0; } let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let d = 2.0 - q.powf(a) - q.powf(b); if n == -b { q.powf(-1.0 + b) * p / d } else if n < 0.0 { (1.0 - q.powf(1.0 + b + n)) * q.powf(-1.0 - n) / d } else { (2.0 - q.powf(b) - q.powf(n)) / d } } pub fn double_nonzero_geometric_median( min: T, max: T, unadjusted_mean: f64, ) -> (T, Option) { assert!(min < T::ZERO); assert!(max > T::ZERO); let min_64 = -min.checked_to_f64(); let max_64 = max.checked_to_f64(); binary_search_median( min, max, |n| double_nonzero_geometric_pmf(max_64, min_64, unadjusted_mean, n.checked_to_f64()), |n| double_nonzero_geometric_cdf(max_64, min_64, unadjusted_mean, n.checked_to_f64()), ) } fn double_geometric_pmf(a: f64, b: f64, unadjusted_mean: f64, n: f64) -> f64 { if n > a || n < -b { 0.0 } else { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); q.powf(n.abs()) * p / (2.0 - qpa - q.powf(1.0 + b) - p + qpa * p) } } fn double_geometric_cdf(a: f64, b: f64, unadjusted_mean: f64, n: f64) -> f64 { if n < -b { return 0.0; } else if n >= a { return 1.0; } let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); let d = 2.0 - qpa - q.powf(1.0 + b) - p + qpa * p; if n == -b { qpb * p / d } else if n <= 0.0 { (1.0 - q.powf(1.0 + b + n)) * q.powf(-n) / d } else { (2.0 - qpb - q.powf(1.0 + n) - p + qpb * p) / d } } pub fn double_geometric_median( min: T, max: T, unadjusted_mean: f64, ) -> (T, Option) { assert!(min < T::ZERO); assert!(max > T::ZERO); let min_64 = -min.checked_to_f64(); let max_64 = max.checked_to_f64(); binary_search_median( min, max, |n| double_geometric_pmf(max_64, min_64, unadjusted_mean, n.checked_to_f64()), |n| double_geometric_cdf(max_64, min_64, unadjusted_mean, n.checked_to_f64()), ) } ================================================ FILE: malachite-base/src/test_util/stats/mod.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::Parity; use itertools::Itertools; pub fn median(xs: I) -> (I::Item, Option) where I::Item: Eq + Ord, { let mut xs = xs.collect_vec(); assert!(!xs.is_empty()); xs.sort_unstable(); let n = xs.len(); let half_n = n >> 1; if n.even() { // swap-remove m_2 first because if n == 2 it's the last element of the list. let m_2 = xs.swap_remove(half_n); let m_1 = xs.swap_remove(half_n - 1); if m_1 == m_2 { (m_1, None) } else { (m_1, Some(m_2)) } } else { (xs.swap_remove(half_n), None) } } pub mod common_values_map; pub mod median; pub mod moments; ================================================ FILE: malachite-base/src/test_util/stats/moments.rs ================================================ // Copyright © 2026 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 crate::num::arithmetic::traits::{SaturatingAbs, UnsignedAbs}; use crate::num::basic::integers::PrimitiveInt; use crate::num::basic::signeds::PrimitiveSigned; use crate::num::basic::traits::Zero; use crate::num::basic::unsigneds::PrimitiveUnsigned; use crate::num::conversion::traits::WrappingFrom; use crate::num::float::NiceFloat; use crate::test_util::stats::common_values_map::common_values_map; use crate::test_util::stats::median; use crate::test_util::stats::median::{ deleted_uniform_primitive_int_median, double_geometric_median, double_nonzero_geometric_median, truncated_geometric_median, uniform_bool_median, uniform_primitive_int_median, }; use itertools::Itertools; use std::fmt::{self, Debug, Formatter}; // Panics if the input exceeds the finite range of f64. pub trait CheckedToF64 { fn checked_to_f64(&self) -> f64; } macro_rules! impl_checked_to_f64_for_primitive_ints { ($t: ident) => { impl CheckedToF64 for $t { #[allow(clippy::cast_lossless)] #[inline] fn checked_to_f64(&self) -> f64 { // No primitive integer type, not even u128 and i128, exceeds the finite range of // f64. *self as f64 } } }; } apply_to_primitive_ints!(impl_checked_to_f64_for_primitive_ints); impl CheckedToF64 for bool { #[inline] fn checked_to_f64(&self) -> f64 { if *self { 1.0 } else { 0.0 } } } impl CheckedToF64 for f32 { #[inline] fn checked_to_f64(&self) -> f64 { f64::from(*self) } } impl CheckedToF64 for f64 { #[inline] fn checked_to_f64(&self) -> f64 { *self } } #[derive(Copy, Clone, Eq, PartialEq)] pub struct MomentStats { pub mean: NiceFloat, pub standard_deviation: NiceFloat, pub skewness: NiceFloat, pub excess_kurtosis: NiceFloat, } impl Debug for MomentStats { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!( "MomentStats {{ mean: NiceFloat({}), standard_deviation: NiceFloat({}), \ skewness: NiceFloat({}), excess_kurtosis: NiceFloat({}) }}", self.mean, self.standard_deviation, self.skewness, self.excess_kurtosis )) } } // From https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance #[allow(clippy::suspicious_operation_groupings)] pub fn moment_stats(xs: I) -> MomentStats where I::Item: CheckedToF64, { let mut n: usize = 1; let mut m = 0.0; let mut m_2 = 0.0; let mut m_3 = 0.0; let mut m_4 = 0.0; for x in xs { let d = x.checked_to_f64() - m; let nf = n.checked_to_f64(); let d_n = d / nf; let d_n_2 = d_n * d_n; let d_n_3 = d_n_2 * d_n; let m_4_1 = (nf - 1.0) * (nf * nf - 3.0 * nf + 3.0) * d_n_3 * d; let m_4_2 = m_2 * d_n_2 * 6.0; let m_4_3 = m_3 * d_n * 4.0; m_4 += m_4_1 + m_4_2 - m_4_3; let m_3_1 = (nf - 1.0) * (nf - 2.0) * d_n_2 * d; let m_3_2 = m_2 * d_n * 3.0; m_3 += m_3_1 - m_3_2; m_2 += (nf - 1.0) * d_n * d; m += d_n; n += 1; } n -= 1; let nf = n.checked_to_f64(); let mean = m; let standard_deviation = (m_2 / (nf - 1.0)).sqrt(); let sqrt_m_2 = m_2.sqrt(); let skewness = m_3 * nf.sqrt() / (sqrt_m_2 * sqrt_m_2 * sqrt_m_2); let excess_kurtosis = m_4 * nf / (m_2 * m_2) - 3.0; MomentStats { mean: NiceFloat(mean), standard_deviation: NiceFloat(standard_deviation), skewness: NiceFloat(skewness), excess_kurtosis: NiceFloat(excess_kurtosis), } } pub const NAN_MOMENT_STATS: MomentStats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; pub fn mean(xs: I) -> NiceFloat where I::Item: CheckedToF64, { let mut n: usize = 1; let mut m = 0.0; for x in xs { let d_n = (x.checked_to_f64() - m) / n.checked_to_f64(); m += d_n; n += 1; } NiceFloat(m) } fn moment_stats_from_raw_moments( mean: f64, p_2_mean: f64, p_3_mean: f64, p_4_mean: f64, ) -> MomentStats { let mean_2 = mean * mean; let mean_3 = mean_2 * mean; let mean_4 = mean_2 * mean_2; let variance = p_2_mean - mean_2; let standard_deviation = variance.sqrt(); let mu_3 = p_3_mean - 3.0 * mean * p_2_mean + 2.0 * mean_3; let mu_4 = p_4_mean - 4.0 * mean * p_3_mean + 6.0 * mean_2 * p_2_mean - 3.0 * mean_4; MomentStats { mean: NiceFloat(mean), standard_deviation: NiceFloat(standard_deviation), skewness: NiceFloat(mu_3 / (variance * standard_deviation)), excess_kurtosis: NiceFloat(mu_4 / (variance * variance) - 3.0), } } #[inline] fn pop_uniform_mean(a: &T, b: &T) -> f64 { (a.checked_to_f64() + b.checked_to_f64()) / 2.0 } fn pop_uniform_standard_deviation(a: &T, b: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); let n = b - a + 1.0; ((n * n - 1.0) / 12.0).sqrt() } fn pop_uniform_skewness(a: &T, b: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); if a == b { f64::NAN } else { 0.0 } } fn pop_uniform_excess_kurtosis(a: &T, b: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); if a == b { f64::NAN } else { let n = b - a + 1.0; let n_squared = n * n; 6.0 / 5.0 * (-1.0 - 2.0 / (-1.0 + n_squared)) } } pub fn pop_disc_uniform_dist_moment_stats(a: &T, b: &T) -> MomentStats { MomentStats { mean: NiceFloat(pop_uniform_mean(a, b)), standard_deviation: NiceFloat(pop_uniform_standard_deviation(a, b)), skewness: NiceFloat(pop_uniform_skewness(a, b)), excess_kurtosis: NiceFloat(pop_uniform_excess_kurtosis(a, b)), } } pub fn uniform_bool_assertions>( xs: I, a: bool, b: bool, expected_values: &[bool], expected_common_values: &[(bool, usize)], expected_pop_median: (bool, Option), expected_sample_median: (bool, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), uniform_bool_median(a, b), actual_sample_median, pop_disc_uniform_dist_moment_stats(&a, &b), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } pub fn uniform_primitive_int_assertions( xs: I, a: I::Item, b: I::Item, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_pop_median: (I::Item, Option), expected_sample_median: (I::Item, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) where I::Item: CheckedToF64 + PrimitiveInt, { let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), uniform_primitive_int_median(a, b), actual_sample_median, pop_disc_uniform_dist_moment_stats(&a, &b), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } fn pop_deleted_disc_uniform_dist_mean(a: &T, b: &T, c: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); let c = c.checked_to_f64(); (a - a * a + b + b * b - 2.0 * c) / (2.0 * (b - a)) } fn pop_deleted_disc_uniform_dist_2_mean(a: &T, b: &T, c: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); let c = c.checked_to_f64(); let a_2 = a * a; let a_3 = a_2 * a; (a - 3.0 * a_2 + 2.0 * a_3 - b * (1.0 + b) * (1.0 + 2.0 * b) + 6.0 * c * c) / (6.0 * (a - b)) } fn pop_deleted_disc_uniform_dist_3_mean(a: &T, b: &T, c: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); let c = c.checked_to_f64(); let a_2 = a * a; let b_2 = b * b; let a_m_1 = a - 1.0; let b_p_1 = b + 1.0; (a_m_1 * a_m_1 * a_2 - b_2 * b_p_1 * b_p_1 + 4.0 * c * c * c) / (4.0 * (a - b)) } fn pop_deleted_disc_uniform_dist_4_mean(a: &T, b: &T, c: &T) -> f64 { let a = a.checked_to_f64(); let b = b.checked_to_f64(); let c = c.checked_to_f64(); let a_2 = a * a; let a_3 = a_2 * a; let a_4 = a_2 * a_2; let a_5 = a_3 * a_2; let b_2 = b * b; let b_3 = b_2 * b; let b_4 = b_2 * b_2; let b_5 = b_3 * b_2; let c_2 = c * c; (-a + 10.0 * a_3 - 15.0 * a_4 + 6.0 * a_5 + b - 10.0 * b_3 - 15.0 * b_4 - 6.0 * b_5 + 30.0 * c_2 * c_2) / (30.0 * (a - b)) } fn deleted_uniform_primitive_int_moment_stats( a: &T, b: &T, c: &T, ) -> MomentStats { assert!(a <= c); assert!(c <= b); moment_stats_from_raw_moments( pop_deleted_disc_uniform_dist_mean(a, b, c), pop_deleted_disc_uniform_dist_2_mean(a, b, c), pop_deleted_disc_uniform_dist_3_mean(a, b, c), pop_deleted_disc_uniform_dist_4_mean(a, b, c), ) } pub fn deleted_uniform_primitive_int_assertions( xs: I, a: I::Item, b: I::Item, c: I::Item, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_pop_median: (I::Item, Option), expected_sample_median: (I::Item, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) where I::Item: CheckedToF64 + PrimitiveInt, { let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), deleted_uniform_primitive_int_median(a, b, c), actual_sample_median, deleted_uniform_primitive_int_moment_stats(&a, &b, &c), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } // unadjusted_mean is what the mean would be if the distribution were not truncated. fn pop_truncated_geometric_dist_mean(max: f64, unadjusted_mean: f64) -> f64 { let m = max; let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; (q - q.powf(m) * q * (1.0 + m * p)) / (p - q.powf(1.0 + m) * p) } fn pop_truncated_geometric_dist_2_mean(max: f64, unadjusted_mean: f64) -> f64 { let m = max; let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let p_2 = p * p; (2.0 - 3.0 * p + p_2 - q.powf(m) * q * (2.0 + p * (-1.0 + m * (2.0 + m * p)))) / ((1.0 - q.powf(1.0 + m)) * p_2) } fn pop_truncated_geometric_dist_3_mean(max: f64, unadjusted_mean: f64) -> f64 { let m = max; let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let p_2 = p * p; let p_3 = p_2 * p; (6.0 - 12.0 * p + 7.0 * p_2 - p_3 - q.powf(m) * q * (6.0 + p * (-6.0 + p + m * (6.0 + p * (-3.0 + m * (3.0 + m * p)))))) / ((1.0 - q.powf(1.0 + m)) * p_3) } fn pop_truncated_geometric_dist_4_mean(max: f64, unadjusted_mean: f64) -> f64 { let m = max; let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let m_2 = m * m; let m_4 = m_2 * m_2; let p_2 = p * p; let p_3 = p_2 * p; let p_4 = p_2 * p_2; (1.0 / ((1.0 - q.powf(1.0 + m)) * p_4)) * (24.0 - 60.0 * p + 50.0 * p_2 - 15.0 * p_3 + p_4 - q.powf(m) * q * (24.0 + p * (-36.0 + 24.0 * m + 2.0 * (7.0 + 6.0 * (-2.0 + m) * m) * p + (-1.0 + 2.0 * m * (2.0 + m * (-3.0 + 2.0 * m))) * p_2 + m_4 * p_3))) } fn pop_truncated_geometric_dist_moment_stats( min: f64, max: f64, unadjusted_mean: f64, ) -> MomentStats { assert!(min <= max); assert!(min <= unadjusted_mean); // unadjusted_mean may be arbitrarily large let unadjusted_mean = unadjusted_mean - min; let max = max - min; let mut stats = moment_stats_from_raw_moments( pop_truncated_geometric_dist_mean(max, unadjusted_mean), pop_truncated_geometric_dist_2_mean(max, unadjusted_mean), pop_truncated_geometric_dist_3_mean(max, unadjusted_mean), pop_truncated_geometric_dist_4_mean(max, unadjusted_mean), ); stats.mean = NiceFloat(stats.mean.0 + min); stats } pub fn truncated_geometric_dist_assertions( xs: I, min: I::Item, max: I::Item, um_numerator: u64, um_denominator: u64, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_pop_median: (I::Item, Option), expected_sample_median: (I::Item, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) where I::Item: CheckedToF64 + PrimitiveInt, { let min_64 = min.checked_to_f64(); let max_64 = max.checked_to_f64(); let unadjusted_mean = um_numerator as f64 / um_denominator as f64; let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), truncated_geometric_median(min, max, unadjusted_mean), actual_sample_median, pop_truncated_geometric_dist_moment_stats(min_64, max_64, unadjusted_mean), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } pub fn negative_truncated_geometric_dist_assertions< I: Clone + Iterator, S: CheckedToF64 + PrimitiveSigned + UnsignedAbs + WrappingFrom, U: CheckedToF64 + PrimitiveUnsigned, >( xs: I, abs_min: S, abs_max: S, abs_um_numerator: u64, abs_um_denominator: u64, expected_values: &[S], expected_common_values: &[(S, usize)], expected_pop_median: (S, Option), expected_sample_median: (S, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let abs_min_64 = -abs_min.checked_to_f64(); let abs_max_64 = -abs_max.checked_to_f64(); let abs_unadjusted_mean = abs_um_numerator as f64 / abs_um_denominator as f64; let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); let mut pop_sample_moment_stats = pop_truncated_geometric_dist_moment_stats(abs_min_64, abs_max_64, abs_unadjusted_mean); pop_sample_moment_stats.mean = NiceFloat(-pop_sample_moment_stats.mean.0); pop_sample_moment_stats.skewness = NiceFloat(-pop_sample_moment_stats.skewness.0); let (x, y) = truncated_geometric_median( abs_min.unsigned_abs(), abs_max.unsigned_abs(), abs_unadjusted_mean, ); let (x, y) = y.map_or((S::wrapping_from(x.wrapping_neg()), None), |y| { ( S::wrapping_from(y.wrapping_neg()), Some(S::wrapping_from(x.wrapping_neg())), ) }); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), (x, y), actual_sample_median, pop_sample_moment_stats, actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } fn pop_double_nonzero_truncated_geometric_dist_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); (qpa * (1.0 + a * p) - qpb * (1.0 + b * p)) / ((-2.0 + qpa + qpb) * p) } fn pop_double_nonzero_truncated_geometric_dist_2_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); (2.0 + (p * (2.0 - qpa + a * qpa * (2.0 + a * p) + qpb * (-1.0 + b * (2.0 + b * p)))) / (-2.0 + qpa + qpb)) / (p * p) } fn pop_double_nonzero_truncated_geometric_dist_3_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); (qpa * (6.0 + p * (-6.0 + p + a * (6.0 + p * (-3.0 + a * (3.0 + a * p))))) - qpb * (6.0 + p * (-6.0 + p + b * (6.0 + p * (-3.0 + b * (3.0 + b * p)))))) / ((-2.0 + qpa + qpb) * p * p * p) } fn pop_double_nonzero_truncated_geometric_dist_4_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let a_2 = a * a; let a_3 = a_2 * a; let a_4 = a_2 * a_2; let b_2 = b * b; let b_4 = b_2 * b_2; let p_2 = p * p; let p_3 = p_2 * p; let p_4 = p_2 * p_2; let qpa = q.powf(a); let qpb = q.powf(b); 1.0 / p_4 * (24.0 + 1.0 / (-2.0 + qpa + qpb) * p * (-6.0 * a_2 * qpa * (-2.0 + p) * p + 4.0 * a_3 * qpa * p_2 + a_4 * qpa * p_3 - (-2.0 + qpa) * (36.0 + (-14.0 + p) * p) + 4.0 * a * qpa * (6.0 + (-6.0 + p) * p) + qpb * (-36.0 + 24.0 * b + 2.0 * (7.0 + 6.0 * (-2.0 + b) * b) * p + (-1.0 + 2.0 * b * (2.0 + b * (-3.0 + 2.0 * b))) * p_2 + b_4 * p_3))) } fn pop_double_nonzero_truncated_geometric_dist_moment_stats( min: f64, max: f64, unadjusted_mean: f64, ) -> MomentStats { assert!(min < 0.0); assert!(max > 0.0); assert!(unadjusted_mean > 1.0); // unadjusted_mean may be arbitrarily large moment_stats_from_raw_moments( pop_double_nonzero_truncated_geometric_dist_mean(-min, max, unadjusted_mean - 1.0), pop_double_nonzero_truncated_geometric_dist_2_mean(-min, max, unadjusted_mean - 1.0), pop_double_nonzero_truncated_geometric_dist_3_mean(-min, max, unadjusted_mean - 1.0), pop_double_nonzero_truncated_geometric_dist_4_mean(-min, max, unadjusted_mean - 1.0), ) } pub fn double_nonzero_truncated_geometric_dist_assertions( xs: I, min: I::Item, max: I::Item, um_numerator: u64, um_denominator: u64, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_abs_mean: NiceFloat, expected_pop_median: (I::Item, Option), expected_sample_median: (I::Item, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) where I::Item: CheckedToF64 + PrimitiveSigned, { let min_64 = min.checked_to_f64(); let max_64 = max.checked_to_f64(); let unadjusted_mean = um_numerator as f64 / um_denominator as f64; let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_abs_mean = mean(xs.clone().map(SaturatingAbs::saturating_abs).take(1000000)); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), actual_abs_mean, double_nonzero_geometric_median(min, max, unadjusted_mean), actual_sample_median, pop_double_nonzero_truncated_geometric_dist_moment_stats( min_64, max_64, unadjusted_mean, ), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_abs_mean, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } fn pop_double_truncated_geometric_dist_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); q * (qpa * (1.0 + a * p) - q.powf(b) * (1.0 + b * p)) / (p * (-2.0 + qpa + q.powf(1.0 + b) + p - qpa * p)) } #[allow(clippy::suspicious_operation_groupings)] fn pop_double_truncated_geometric_dist_2_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); q * (2.0 * (-2.0 + qpa + qpb) + p * (2.0 - qpa + a * qpa * (2.0 + a * p) + qpb * (-1.0 + b * (2.0 + b * p)))) / (p * p * (-2.0 + qpa + q.powf(1.0 + b) + p - qpa * p)) } fn pop_double_truncated_geometric_dist_3_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); q * (qpa * (6.0 + p * (-6.0 + p + a * (6.0 + p * (-3.0 + a * (3.0 + a * p))))) - qpb * (6.0 + p * (-6.0 + p + b * (6.0 + p * (-3.0 + b * (3.0 + b * p)))))) / (p * p * p * (-2.0 + qpa + q.powf(1.0 + b) + p - qpa * p)) } fn pop_double_truncated_geometric_dist_4_mean(b: f64, a: f64, unadjusted_mean: f64) -> f64 { let p = 1.0 / (unadjusted_mean + 1.0); let q = 1.0 - p; let qpa = q.powf(a); let qpb = q.powf(b); let a_2 = a * a; let a_3 = a_2 * a; let a_4 = a_2 * a_2; let b_2 = b * b; let b_4 = b_2 * b_2; let p_2 = p * p; let p_3 = p_2 * p; let p_4 = p_2 * p_2; q * (24.0 * (-2.0 + qpa + qpb) + p * (-6.0 * a_2 * qpa * (-2.0 + p) * p + 4.0 * a_3 * qpa * p_2 + a_4 * qpa * p_3 - (-2.0 + qpa) * (36.0 + (-14.0 + p) * p) + 4.0 * a * qpa * (6.0 + (-6.0 + p) * p) + qpb * (-36.0 + 24.0 * b + 2.0 * (7.0 + 6.0 * (-2.0 + b) * b) * p + (-1.0 + 2.0 * b * (2.0 + b * (-3.0 + 2.0 * b))) * p_2 + b_4 * p_3))) / (p_4 * (-2.0 + qpa + q.powf(1.0 + b) + p - qpa * p)) } fn pop_double_truncated_geometric_dist_moment_stats( min: f64, max: f64, unadjusted_mean: f64, ) -> MomentStats { assert!(min < 0.0); assert!(max > 0.0); assert!(unadjusted_mean > 0.0); // unadjusted_mean may be arbitrarily large moment_stats_from_raw_moments( pop_double_truncated_geometric_dist_mean(-min, max, unadjusted_mean), pop_double_truncated_geometric_dist_2_mean(-min, max, unadjusted_mean), pop_double_truncated_geometric_dist_3_mean(-min, max, unadjusted_mean), pop_double_truncated_geometric_dist_4_mean(-min, max, unadjusted_mean), ) } pub fn double_truncated_geometric_dist_assertions( xs: I, min: I::Item, max: I::Item, um_numerator: u64, um_denominator: u64, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_natural_mean: NiceFloat, expected_pop_median: (I::Item, Option), expected_sample_median: (I::Item, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) where I::Item: CheckedToF64 + PrimitiveSigned, { let min_64 = min.checked_to_f64(); let max_64 = max.checked_to_f64(); let unadjusted_mean = um_numerator as f64 / um_denominator as f64; let actual_values = xs.clone().take(20).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()); let actual_natural_mean = mean(xs.clone().filter(|&x| x >= I::Item::ZERO).take(1000000)); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), actual_natural_mean, double_geometric_median(min, max, unadjusted_mean), actual_sample_median, pop_double_truncated_geometric_dist_moment_stats(min_64, max_64, unadjusted_mean), actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_natural_mean, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats ) ); } ================================================ FILE: malachite-base/src/test_util/vecs/exhaustive/mod.rs ================================================ // Copyright © 2026 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 std::fmt::Debug; pub fn exhaustive_vecs_helper_helper>>(xss: I, out: &[&[T]]) where T: Clone + Debug + Eq, { let xss = xss.take(20).collect_vec(); assert_eq!(xss.iter().map(Vec::as_slice).collect_vec().as_slice(), out); } pub fn exhaustive_vecs_small_helper_helper>>( xss: I, out_len: usize, out: &[&[T]], ) where T: Clone + Debug + Eq, { let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); assert_eq!(xss.count(), out_len); } ================================================ FILE: malachite-base/src/test_util/vecs/mod.rs ================================================ // Copyright © 2026 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 . pub mod exhaustive; pub mod random; ================================================ FILE: malachite-base/src/test_util/vecs/random/mod.rs ================================================ // Copyright © 2026 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 crate::test_util::stats::common_values_map::common_values_map_debug; use crate::test_util::stats::median; use itertools::Itertools; use std::fmt::Debug; use std::hash::Hash; pub fn random_vecs_helper_helper>>( xss: I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) where T: Clone + Debug + Eq + Hash + Ord, { let values = xss.clone().take(20).collect_vec(); let values = values.iter().map(Vec::as_slice).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()); let common_values = common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec(); let (a, ob) = median(xss.take(1000000)); let median = (a.as_slice(), ob.as_deref()); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } ================================================ FILE: malachite-base/src/tuples/exhaustive.rs ================================================ // Copyright © 2026 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 crate::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; use crate::iterators::iterator_cache::IteratorCache; use crate::num::arithmetic::traits::CheckedPow; use crate::num::conversion::traits::{ExactFrom, WrappingFrom}; use crate::num::logic::traits::SignificantBits; use crate::vecs::exhaustive::{ UniqueIndices, fixed_length_ordered_unique_indices_helper, next_bit_pattern, unique_indices, }; use alloc::vec; use alloc::vec::Vec; use core::cmp::max; use core::fmt::Debug; use core::iter::{Once, once}; use core::marker::PhantomData; use core::mem::take; /// Generates the only unit: `()`. /// /// The output length is 1. /// /// # Worst-case complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::exhaustive_units; /// /// assert_eq!(exhaustive_units().collect_vec(), &[()]); /// ``` pub fn exhaustive_units() -> Once<()> { once(()) } // hack for macro pub_test! { #[inline] clone_helper(x: &T, _i: usize) -> T { x.clone() }} /// Defines lexicographic tuple generators. /// /// Malachite provides [`lex_pairs`] and [`lex_pairs_from_single`], but you can also define /// `lex_triples`, `lex_quadruples`, and so on, and `lex_triples_from_single`, /// `lex_quadruples_from_single`, and so on, in your program using the code below. The documentation /// for [`lex_pairs`] and [`lex_pairs_from_single`] describes these other functions as well. /// /// See usage examples [here](self#lex_pairs) and [here](self#lex_pairs_from_single). /// /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_tuples; /// /// fn clone_helper(x: &T, _i: usize) -> T { /// x.clone() /// } /// /// 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)), /// 6, /// LexSextuples, /// LexSextuplesFromSingle, /// lex_sextuples, /// lex_sextuples_from_single, /// (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] /// ); /// lex_tuples!( /// (pub(crate)), /// 7, /// LexSeptuples, /// LexSeptuplesFromSingle, /// lex_septuples, /// lex_septuples_from_single, /// (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] /// ); /// 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] /// ); /// ``` #[macro_export] macro_rules! lex_tuples { ( ($($vis:tt)*), $k: expr, $exhaustive_struct: ident, $exhaustive_struct_from_single: ident, $exhaustive_fn: ident, $exhaustive_fn_from_single: ident, $single_out: tt, $([$i: expr, $t: ident, $it: ident, $xs: ident, $x:ident]),* ) => { /// This documentation applies not only to `LexPairs`, but also to `LexTriples`, /// `LexQuadruples`, and so on. See `lex_tuples` for more information. /// /// Generates all $n$-tuples with elements from $n$ iterators, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct<$($t: Clone, $it: Iterator,)*> { first: bool, done: bool, $($xs: IteratorCache<$it>,)* counters: [usize; $k], } impl<$($t: Clone, $it: Iterator,)*> $exhaustive_struct<$($t, $it,)*> { fn increment_counters(&mut self) -> bool { for (i, counter) in self.counters.iter_mut().enumerate().rev() { *counter += 1; let no_carry = match i { $( $i => self.$xs.get(*counter).is_some(), )* _ => unreachable!(), }; if no_carry { return false; } else if i == 0 { return true; } *counter = 0; } false } } impl<$($t: Clone, $it: Iterator,)*> Iterator for $exhaustive_struct<$($t, $it,)*> { type Item = ($($t,)*); fn next(&mut self) -> Option { if self.done { None } else if self.first { self.first = false; $( let $x; )* $( if let Some(x) = self.$xs.get(0) { $x = x.clone(); } else { self.done = true; return None; } )* Some(($($x,)*)) } else if self.increment_counters() { self.done = true; None } else { Some(($(self.$xs.get(self.counters[$i]).unwrap().clone(),)*)) } } } /// This documentation applies not only to `lex_pairs`, but also to `lex_triples`, /// `lex_quadruples`, and so on. See [`lex_tuples`] for more information. /// /// Generates all $n$-tuples with elements from $n$ iterators, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. /// /// All of `ys`, `zs`, ... (but not necessarily `xs`) must be finite. If `xs` is finite, the /// output length is the product of the lengths of all the input iterators. If `xs` is /// infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_pairs). #[allow(dead_code)] $($vis)* const fn $exhaustive_fn<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_struct { first: true, done: false, $($xs: IteratorCache::new($xs),)* counters: [$($i * 0,)*], } } /// This documentation applies not only to `LexPairsFromSingle`, but also to /// `LexTriplesFromSingle`, `LexQuadruplesFromSingle`, and so on. See [`lex_tuples`] for /// more information. /// /// Generates all $n$-tuples with elements a single iterator, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterator. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct_from_single> { first: bool, done: bool, xs: IteratorCache, counters: [usize; $k], } impl> $exhaustive_struct_from_single { fn increment_counters(&mut self) -> bool { for (i, counter) in self.counters.iter_mut().enumerate().rev() { *counter += 1; if self.xs.get(*counter).is_some() { return false; } else if i == 0 { return true; } *counter = 0; } false } } impl> Iterator for $exhaustive_struct_from_single { type Item = $single_out; fn next(&mut self) -> Option<$single_out> { if self.done { None } else if self.first { self.first = false; if let Some(x) = self.xs.get(0) { Some(($(clone_helper(x, $i),)*)) } else { self.done = true; None } } else if self.increment_counters() { self.done = true; None } else { Some(($(self.xs.get(self.counters[$i]).unwrap().clone(),)*)) } } } /// This documentation applies not only to `lex_pairs_from_single`, but also to /// `lex_triples_from_single`, `lex_quadruples_from_single`, and so on. See [`lex_tuples`] /// for more information. /// /// Generates all $n$-tuples with elements from a single iterator, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// `xs` must be finite. /// /// The output length is $k^n$, where $k$ is `xs.count()` and $n$ is `len`. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_pairs_from_single). #[allow(dead_code)] $($vis)* const fn $exhaustive_fn_from_single>( xs: I ) -> $exhaustive_struct_from_single { $exhaustive_struct_from_single { first: true, done: false, xs: IteratorCache::new(xs), counters: [$($i * 0,)*], } } } } lex_tuples!( (pub), 2, LexPairs, LexPairsFromSingle, lex_pairs, lex_pairs_from_single, (T, T), [0, X, I, xs, x], [1, Y, J, ys, y] ); 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] ); /// Defines custom lexicographic tuple generators. /// /// You can define custom tuple generators like `lex_triples_xxy` in your program using the code /// below. /// /// See usage examples [here](self#lex_triples_xxy). /// /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_custom_tuples; /// /// fn _unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { /// (a.unwrap(), b.unwrap(), c.unwrap()) /// } /// /// lex_custom_tuples! { /// (pub), /// 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), /// 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_custom_tuples!( /// (pub), /// LexTriplesXYY, /// (X, Y, Y), /// (None, None, None), /// _unwrap_triple, /// lex_triples_xyy, /// [X, I, xs, [0, x_0]], /// [Y, J, ys, [1, y_1], [2, y_2]] /// ); /// ``` #[macro_export] macro_rules! lex_custom_tuples { ( ($($vis:tt)*), $exhaustive_struct: ident, $out_t: ty, $nones: expr, $unwrap_tuple: ident, $exhaustive_fn: ident, $([$t: ident, $it: ident, $xs: ident, $([$i: tt, $x: ident]),*]),* ) => { // Generates all $n$-tuples with elements from $m$ iterators, where $m \leq n$, in // lexicographic order. // // The order is lexicographic with respect to the order of the element iterators. // // The mapping from iterators to tuple slots is indicated by the struct name; for example, // in `LexTriplesXYX` there are two iterators, `X`, and `Y`; `X` generates the elements in // the first and third slots of the output triples, and `Y` generates the elements in the // second slots. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct<$($t: Clone, $it: Iterator,)*> { first: bool, done: bool, $($xs: IteratorCache<$it>,)* counters: Vec, } impl<$($t: Clone, $it: Iterator,)*> $exhaustive_struct<$($t, $it,)*> { fn increment_counters(&mut self) -> bool { for (i, counter) in self.counters.iter_mut().enumerate().rev() { *counter += 1; let no_carry = match i { $( $($i)|* => self.$xs.get(*counter).is_some(), )* _ => unreachable!(), }; if no_carry { return false; } else if i == 0 { return true; } *counter = 0; } false } } impl<$($t: Clone, $it: Iterator,)*> Iterator for $exhaustive_struct<$($t, $it,)*> { type Item = $out_t; fn next(&mut self) -> Option { if self.done { None } else if self.first { self.first = false; $($(let $x;)*)* $( if let Some(x) = self.$xs.get(0) { $($x = x.clone();)* } else { self.done = true; return None; } )* let mut out = $nones; $($(out.$i = Some($x);)*)* Some($unwrap_tuple(out)) } else if self.increment_counters() { self.done = true; None } else { let mut out = $nones; $($(out.$i = self.$xs.get(self.counters[$i]).cloned();)*)* Some($unwrap_tuple(out)) } } } // Generates all $n$-tuples with elements from $m$ iterators, where $m \leq n$, in // lexicographic order. // // The order is lexicographic with respect to the order of the element iterators. // // The mapping from iterators to tuple slots is indicated by the function name; for example, // `lex_triples_xyx` takes two iterators, `xs`, and `ys`; `xs` generates the elements in the // first and third slots of the output triples, and `ys` generates the elements in the // second slots. // // Let `xs` be the input iterator mapped to the first slot of the output tuples. All the // input iterators, except possibly `xs`, must be finite. If `xs` is finite, the output // length is the product of the lengths of all the input iterators. If `xs` is infinite, the // output is also infinite. // // If any of the input iterators is empty, the output is also empty. // // # Examples // See [here](self#lex_triples_xyx). $($vis)* fn $exhaustive_fn<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_struct { first: true, done: false, $($xs: IteratorCache::new($xs),)* counters: vec![$($(($i * 0),)*)*], } } } } /// Defines exhaustive tuple generators that generate tuples from a single iterator. /// /// Malachite provides [`exhaustive_pairs_from_single`] and [`exhaustive_pairs_1_input`], but you /// can also define `exhaustive_triples_from_single`, `exhaustive_quadruples_from_single`, and so /// on, and `exhaustive_triples_1_input`, `exhaustive_quadruples_1_input`, and so on, in your /// program using the code below. The documentation for [`exhaustive_pairs_from_single`] and /// [`exhaustive_pairs_1_input`] describes these other functions as well. /// /// See usage examples [here](self#exhaustive_pairs_from_single) and /// [here](self#exhaustive_pairs_1_input). /// /// ``` /// use malachite_base::exhaustive_tuples_1_input; /// 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::logic::traits::SignificantBits; /// use std::cmp::max; /// use std::marker::PhantomData; /// /// 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)), /// ExhaustiveSextuples1Input, /// exhaustive_sextuples_1_input, /// exhaustive_sextuples_from_single, /// (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] /// ); /// exhaustive_tuples_1_input!( /// (pub(crate)), /// ExhaustiveSeptuples1Input, /// exhaustive_septuples_1_input, /// exhaustive_septuples_from_single, /// ( /// 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] /// ); /// 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] /// ); /// ``` #[macro_export] macro_rules! exhaustive_tuples_1_input { ( ($($vis:tt)*), $exhaustive_struct: ident, $exhaustive_fn: ident, $exhaustive_fn_from_single: ident, $out_type: ty, $([$i: tt, $out_x: ident]),* ) => { /// This documentation applies not only to `ExhaustivePairs1Input`, but also to /// `ExhaustiveTriples1Input`, `ExhaustiveQuadruples1Input`, and so on. See /// [`exhaustive_tuples_1_input`] for more information. /// /// Generates all $n$-tuples of a given length with elements from a single iterator. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct where I::Item: Clone, { i: u64, limit: Option, distributor: BitDistributor, xs: IteratorCache, xs_done: bool, phantom: PhantomData<*const I::Item>, } impl Iterator for $exhaustive_struct where I::Item: Clone, { type Item = $out_type; fn next(&mut self) -> Option { if Some(self.i) == self.limit { None } else { if self.i == u64::MAX { panic!("Too many iterations"); } loop { let mut all_are_valid = true; $( if all_are_valid && self.xs.get(self.distributor.get_output($i)).is_none() { all_are_valid = false; } )* if all_are_valid { break; } else if !self.xs_done { let xs_len = self.xs.known_len().unwrap(); $( let _max_index = $i; )* let size = _max_index + 1; self.limit = CheckedPow::checked_pow( u64::exact_from(xs_len), u64::exact_from(size) ); if Some(self.i) == self.limit { return None; } self.xs_done = true; // xs_len > 0 at this point self.distributor.set_max_bits( &[0], max(1, usize::wrapping_from((xs_len - 1).significant_bits())), ); } else { self.distributor.increment_counter(); } } let result = Some( ($(self.xs.get(self.distributor.get_output($i)).unwrap().clone(),)*) ); self.i += 1; self.distributor.increment_counter(); result } } } /// This documentation applies not only to `exhaustive_pairs_1_input`, but also to /// `exhaustive_triples_1_input`, `exhaustive_quadruples_1_input`, and so on. See /// [`exhaustive_tuples_1_input`] for more information. /// /// Generates all length-$n$ tuples with elements from a single iterator. /// /// These functions differ from `exhaustive_[n-tuples]_from_single` in that different /// [`BitDistributorOutputType`]s may be specified for each output element. /// /// The $i$th parameter `output_types_[x_i]` is a [`BitDistributorOutputType`] that /// determines how quickly the $i$th output slot advances through the iterator; see the /// [`BitDistributor`] documentation for a description of the different types. /// /// If `xs` is finite, the output length is $k^n$, where $k$ is `xs.count()` and $n$ is the /// width of the tuples. If `xs` is infinite, the output is also infinite. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_pairs_1_input). #[allow(dead_code)] $($vis)* fn $exhaustive_fn( xs: I, $($out_x: BitDistributorOutputType,)* ) -> $exhaustive_struct where I::Item: Clone, { $exhaustive_struct { i: 0, limit: None, distributor: BitDistributor::new(&[$($out_x,)*]), xs: IteratorCache::new(xs), xs_done: false, phantom: PhantomData, } } /// This documentation applies not only to `exhaustive_pairs_from_single`, but also to /// `exhaustive_triples_from_single`, `exhaustive_quadruples_from_single`, and so on. See /// [`exhaustive_tuples_1_input`] for more information. /// /// Generates all $n$-tuples with elements from a single iterator. /// /// If `xs` is finite, the output length is $k^n$, where $k$ is `xs.count()` and $n$ is the /// width of the tuples. If `xs` is infinite, the output is also infinite. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_pairs_from_single). #[allow(dead_code)] #[inline] $($vis)* fn $exhaustive_fn_from_single(xs: I) -> $exhaustive_struct where I::Item: Clone, { $exhaustive_fn(xs, $(BitDistributorOutputType::normal(1 + $i * 0)),*) } } } exhaustive_tuples_1_input!( (pub), ExhaustivePairs1Input, exhaustive_pairs_1_input, exhaustive_pairs_from_single, (I::Item, I::Item), [0, output_type_x], [1, output_type_y] ); /// Defines exhaustive tuple generators. /// /// Malachite provides [`exhaustive_pairs`] and [`exhaustive_pairs_custom_output`], but you can also /// define `exhaustive_triples`, `exhaustive_quadruples`, and so on, and /// `exhaustive_triples_custom_output`, `exhaustive_quadruples_custom_output`, and so on, in your /// program using the code below. The documentation for [`exhaustive_pairs`] and /// [`exhaustive_pairs_custom_output`] describes these other functions as well. /// /// See usage examples [here](self#exhaustive_pairs) and /// [here](self#exhaustive_pairs_custom_output). /// /// ``` /// use malachite_base::exhaustive_tuples; /// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; /// use malachite_base::num::logic::traits::SignificantBits; /// use std::cmp::max; /// /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveTriples, /// exhaustive_triples, /// exhaustive_triples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z] /// ); /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveQuadruples, /// exhaustive_quadruples, /// exhaustive_quadruples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z], /// [3, W, L, ws, ws_done, output_type_w] /// ); /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveQuintuples, /// exhaustive_quintuples, /// exhaustive_quintuples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z], /// [3, W, L, ws, ws_done, output_type_w], /// [4, V, M, vs, vs_done, output_type_v] /// ); /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveSextuples, /// exhaustive_sextuples, /// exhaustive_sextuples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z], /// [3, W, L, ws, ws_done, output_type_w], /// [4, V, M, vs, vs_done, output_type_v], /// [5, U, N, us, us_done, output_type_u] /// ); /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveSeptuples, /// exhaustive_septuples, /// exhaustive_septuples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z], /// [3, W, L, ws, ws_done, output_type_w], /// [4, V, M, vs, vs_done, output_type_v], /// [5, U, N, us, us_done, output_type_u], /// [6, T, O, ts, ts_done, output_type_t] /// ); /// exhaustive_tuples!( /// (pub(crate)), /// ExhaustiveOctuples, /// exhaustive_octuples, /// exhaustive_octuples_custom_output, /// [0, X, I, xs, xs_done, output_type_x], /// [1, Y, J, ys, ys_done, output_type_y], /// [2, Z, K, zs, zs_done, output_type_z], /// [3, W, L, ws, ws_done, output_type_w], /// [4, V, M, vs, vs_done, output_type_v], /// [5, U, N, us, us_done, output_type_u], /// [6, T, O, ts, ts_done, output_type_t], /// [7, S, P, ss, ss_done, output_type_s] /// ); /// ``` #[macro_export] macro_rules! exhaustive_tuples { ( ($($vis:tt)*), $exhaustive_struct: ident, $exhaustive_fn: ident, $exhaustive_fn_custom_output: ident, $([$i: tt, $t: ident, $it: ident, $xs: ident, $xs_done: ident, $out_x: ident]),* ) => { /// This documentation applies not only to `ExhaustivePairs`, but also to /// `ExhaustiveTriples`, `ExhaustiveQuadruples`, and so on. See [`exhaustive_tuples`] for /// more information. /// /// Generates all $n$-tuples with elements from $n$ iterators. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct<$($t: Clone, $it: Iterator,)*> { i: u64, limit: Option, distributor: BitDistributor, $( $xs: IteratorCache<$it>, $xs_done: bool, )* } impl<$($t: Clone, $it: Iterator,)*> $exhaustive_struct<$($t, $it,)*> { fn try_getting_limit(&mut self) { let mut all_limits_known = true; $( if let Some(xs_len) = self.$xs.known_len() { if xs_len == 0 { self.limit = Some(0); return; } } else { all_limits_known = false; } )* if !all_limits_known { return; } let mut product = 1u64; $( let xs_len = u64::exact_from(self.$xs.known_len().unwrap()); if let Some(new_product) = product.checked_mul(u64::exact_from(xs_len)) { product = new_product; } else { return; } )* self.limit = Some(product); } } impl<$($t: Clone, $it: Iterator,)*> Iterator for $exhaustive_struct<$($t, $it,)*> { type Item = ($($t,)*); fn next(&mut self) -> Option { if Some(self.i) == self.limit { None } else { if self.i == u64::MAX { panic!("Too many iterations"); } loop { $( if self.$xs.get(self.distributor.get_output($i)).is_none() { if !self.$xs_done { let xs_len = self.$xs.known_len().unwrap(); self.try_getting_limit(); if Some(self.i) == self.limit { return None; } self.$xs_done = true; self.distributor.set_max_bits( &[$i], max( 1, usize::wrapping_from((xs_len - 1).significant_bits()) ), ); } else { self.distributor.increment_counter(); } continue; } )* break; } let result = Some( ($(self.$xs.get(self.distributor.get_output($i)).unwrap().clone(),)*) ); self.i += 1; self.distributor.increment_counter(); result } } } /// This documentation applies not only to `exhaustive_pairs_custom_output`, but also to /// `exhaustive_triples_custom_output`, `exhaustive_quadruples_custom_output`, and so on. /// See [`exhaustive_tuples`] for more information. /// /// Generates all $n$-tuples with elements from $n$ iterators, possibly with different /// output growth rates. /// /// The $i$th `output_type_[x_i]` parameter is a [`BitDistributorOutputType`] that /// determines how quickly the $i$th output slot advances through its iterator; see the /// [`BitDistributor`] documentation for a description of the different types. /// /// If all of `xs`, `ys`, `zs`, ... are finite, the output length is the product of their /// lengths. If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_pairs_custom_output). #[allow(dead_code)] $($vis)* fn $exhaustive_fn_custom_output<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* $($out_x: BitDistributorOutputType,)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_struct { i: 0, limit: None, distributor: BitDistributor::new(&[$($out_x,)*]), $( $xs: IteratorCache::new($xs), $xs_done: false, )* } } /// This documentation applies not only to `exhaustive_pairs`, but also to /// `exhaustive_triples`, `exhaustive_quadruples`, and so on. See [`exhaustive_tuples`] for /// more information. /// /// Generates all $n$-tuples with elements from $n$ iterators. /// /// If all of `xs`, `ys`, `zs`, ... are finite, the output length is the product of their /// lengths. If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_pairs). #[allow(dead_code)] #[inline] $($vis)* fn $exhaustive_fn<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_fn_custom_output( $($xs,)* $(BitDistributorOutputType::normal(1 + 0 * $i),)* ) } } } exhaustive_tuples!( (pub), ExhaustivePairs, exhaustive_pairs, exhaustive_pairs_custom_output, [0, X, I, xs, xs_done, output_type_x], [1, Y, J, ys, ys_done, output_type_y] ); #[cfg(feature = "test_build")] exhaustive_tuples!( (pub), ExhaustiveTriples, exhaustive_triples, exhaustive_triples_custom_output, [0, X, I, xs, xs_done, output_type_x], [1, Y, J, ys, ys_done, output_type_y], [2, Z, K, zs, zs_done, output_type_z] ); #[cfg(not(feature = "test_build"))] exhaustive_tuples!( (pub(crate)), ExhaustiveTriples, exhaustive_triples, exhaustive_triples_custom_output, [0, X, I, xs, xs_done, output_type_x], [1, Y, J, ys, ys_done, output_type_y], [2, Z, K, zs, zs_done, output_type_z] ); #[cfg(feature = "test_build")] exhaustive_tuples!( (pub), ExhaustiveQuadruples, exhaustive_quadruples, exhaustive_quadruples_custom_output, [0, X, I, xs, xs_done, output_type_x], [1, Y, J, ys, ys_done, output_type_y], [2, Z, K, zs, zs_done, output_type_z], [3, W, L, ws, ws_done, output_type_w] ); /// Defines custom exhaustive tuple generators. /// /// You can define custom tuple generators like `exhaustive_triples_xyx` or /// `exhaustive_triples_xyx_custom_output` in your program using the code below. /// /// See usage examples [here](self#exhaustive_triples_xyx) and /// [here](self#exhaustive_triples_xyx_custom_output). /// /// ``` /// use malachite_base::custom_tuples; /// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; /// use malachite_base::num::logic::traits::SignificantBits; /// use std::cmp::max; /// /// #[allow(clippy::missing_const_for_fn)] /// fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { /// (a.unwrap(), b.unwrap(), c.unwrap()) /// } /// /// #[allow(clippy::missing_const_for_fn)] /// fn unwrap_quadruple( /// (a, b, c, d): (Option, Option, Option, Option), /// ) -> (X, Y, Z, W) { /// (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap()) /// } /// /// #[allow(clippy::missing_const_for_fn)] /// fn unwrap_quintuple( /// (a, b, c, d, e): (Option, Option, Option, Option, Option), /// ) -> (X, Y, Z, W, V) { /// (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap(), e.unwrap()) /// } /// /// custom_tuples!( /// (pub), /// 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), /// 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]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveTriplesXYY, /// (X, Y, Y), /// (None, None, None), /// unwrap_triple, /// exhaustive_triples_xyy, /// exhaustive_triples_xyy_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0]], /// [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXXXY, /// (X, X, X, Y), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xxxy, /// exhaustive_quadruples_xxxy_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1], [2, output_type_xs_2]], /// [Y, J, ys, ys_done, [3, output_type_ys_3]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXXYX, /// (X, X, Y, X), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xxyx, /// exhaustive_quadruples_xxyx_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1], [3, output_type_xs_3]], /// [Y, J, ys, ys_done, [2, output_type_ys_2]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXXYZ, /// (X, X, Y, Z), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xxyz, /// exhaustive_quadruples_xxyz_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]], /// [Z, K, zs, zs_done, [3, output_type_zs_3]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXYXZ, /// (X, Y, X, Z), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xyxz, /// exhaustive_quadruples_xyxz_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_xs_2]], /// [Y, J, ys, ys_done, [1, output_type_ys_1]], /// [Z, K, zs, zs_done, [3, output_type_zs_3]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXYYX, /// (X, Y, Y, X), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xyyx, /// exhaustive_quadruples_xyyx_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0], [3, output_type_xs_3]], /// [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXYYZ, /// (X, Y, Y, Z), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xyyz, /// exhaustive_quadruples_xyyz_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0]], /// [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]], /// [Z, K, zs, zs_done, [3, output_type_zs_3]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuadruplesXYZZ, /// (X, Y, Z, Z), /// (None, None, None, None), /// unwrap_quadruple, /// exhaustive_quadruples_xyzz, /// exhaustive_quadruples_xyzz_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0]], /// [Y, J, ys, ys_done, [1, output_type_ys_1]], /// [Z, K, zs, zs_done, [2, output_type_zs_2], [3, output_type_zs_3]] /// ); /// custom_tuples!( /// (pub), /// ExhaustiveQuintuplesXYYYZ, /// (X, Y, Y, Y, Z), /// (None, None, None, None, None), /// unwrap_quintuple, /// exhaustive_quintuples_xyyyz, /// exhaustive_quintuples_xyyyz_custom_output, /// [X, I, xs, xs_done, [0, output_type_xs_0]], /// [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2], [3, output_type_ys_3]], /// [Z, K, zs, zs_done, [4, output_type_zs_4]] /// ); /// ``` #[macro_export] macro_rules! custom_tuples { ( ($($vis:tt)*), $exhaustive_struct: ident, $out_t: ty, $nones: expr, $unwrap_tuple: ident, $exhaustive_fn: ident, $exhaustive_custom_fn: ident, $([$t: ident, $it: ident, $xs: ident, $xs_done: ident, $([$i: tt, $out_x: ident]),*]),* ) => { // Generates all $n$-tuples with elements from $m$ iterators, where $m \leq n$. // // The mapping from iterators to tuple slots is indicated by the struct name; for example, // in `TriplesXYX` there are two iterators, `X`, and `Y`; `X` generates the elements in the // first and third slots of the output triples, and `Y` generates the elements in the second // slots. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct<$($t: Clone, $it: Iterator,)*> { i: u64, limit: Option, distributor: BitDistributor, $( $xs: IteratorCache<$it>, $xs_done: bool, )* } impl<$($t: Clone, $it: Iterator,)*> $exhaustive_struct<$($t, $it,)*> { fn try_getting_limit(&mut self) { let mut all_limits_known = true; $( if let Some(xs_len) = self.$xs.known_len() { if xs_len == 0 { self.limit = Some(0); return; } } else { all_limits_known = false; } )* if !all_limits_known { return; } let mut product = 1u64; $( let xs_len = u64::exact_from(self.$xs.known_len().unwrap()); $( let _x = $i; if let Some(new_product) = product.checked_mul(xs_len) { product = new_product; } else { return; } )* )* self.limit = Some(product); } } impl<$($t: Clone, $it: Iterator,)*> Iterator for $exhaustive_struct<$($t, $it,)*> { type Item = $out_t; fn next(&mut self) -> Option { if Some(self.i) == self.limit { None } else { if self.i == u64::MAX { panic!("Too many iterations"); } loop { $( $( if self.$xs.get(self.distributor.get_output($i)).is_none() { if !self.$xs_done { let xs_len = self.$xs.known_len().unwrap(); self.try_getting_limit(); if Some(self.i) == self.limit { return None; } self.$xs_done = true; self.distributor.set_max_bits( &[$i], max( 1, usize::wrapping_from( (xs_len - 1).significant_bits() ) ), ); } else { self.distributor.increment_counter(); } continue; } )* )* break; } let mut out = $nones; $( $( let x = self.$xs.get(self.distributor.get_output($i)).unwrap(); out.$i = Some(x.clone()); )* )* self.i += 1; self.distributor.increment_counter(); Some($unwrap_tuple(out)) } } } // Generates all $n$-tuples with elements from $m$ iterators, where $m \leq n$, possibly // with different output growth rates. // // The mapping from iterators to tuple slots is indicated by the function name; for example, // `exhaustive_triples_xyx_custom_output` takes two iterators, `xs`, and `ys`; `xs` // generates the elements in the first and third slots of the output triples, and `ys` // generates the elements in the second slots. // // Let $i$ be the index of the input iterators and $j$ be the index of the output slots. So // for `exhaustive_triples_xyx_custom_output`, $i=0$ corresponds to $j=0$ and $j=2$, and // $i=1$ corresponds to $j=1$. // // The $j$th `output_type_[i_j]` parameter is a // [`BitDistributorOutputType`](crate::iterators::bit_distributor::BitDistributorOutputType) // that determines how quickly the $j$th output slot advances through its iterator; see the // [`BitDistributor`](crate::iterators::bit_distributor::BitDistributor) documentation for a // description of the different types. // // If all of `xs`, `ys`, `zs`, ... are finite, then the output length may be obtained by // raising the length of each input iterator to power of the number of outputs it maps to, // and taking the product of the resulting values. // // If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. // // If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. // // # Examples // See [here](self#exhaustive_triples_xyx_custom_output). #[allow(dead_code)] $($vis)* fn $exhaustive_custom_fn<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* $($($out_x: BitDistributorOutputType,)*)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_struct { i: 0, limit: None, distributor: BitDistributor::new(&[$($($out_x,)*)*]), $( $xs: IteratorCache::new($xs), $xs_done: false, )* } } // Generates all $n$-tuples with elements from $m$ iterators, where $m \leq n$. // // The mapping from iterators to tuple slots is indicated by the function name; for example, // `exhaustive_triples_xyx` takes two iterators, `xs`, and `ys`; `xs` generates the elements // in the first and third slots of the output triples, and `ys` generates the elements in // the second slots. // // If all of `xs`, `ys`, `zs`, ... are finite, then the output length may be obtained by // raising the length of each input iterator to power of the number of outputs it maps to, // and taking the product of the resulting values. // // If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. // // If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. // // # Examples // See [here](self#exhaustive_triples_xyx). #[allow(dead_code)] #[inline] $($vis)* fn $exhaustive_fn<$($t: Clone, $it: Iterator,)*>( $($xs: $it,)* ) -> $exhaustive_struct<$($t, $it,)*> { $exhaustive_custom_fn( $($xs,)* $($(BitDistributorOutputType::normal(1 + 0 * $i),)*)* ) } } } #[cfg(feature = "test_build")] #[allow(clippy::missing_const_for_fn)] fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { (a.unwrap(), b.unwrap(), c.unwrap()) } #[cfg(feature = "test_build")] custom_tuples!( (pub), ExhaustiveTriplesXYY, (X, Y, Y), (None, None, None), unwrap_triple, exhaustive_triples_xyy, exhaustive_triples_xyy_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]] ); /// A trait used by dependent-pairs structs. /// /// Given a reference to an `x`, produces an iterator of `ys`. /// /// See [`LexDependentPairs`] and [`ExhaustiveDependentPairs`]. pub trait ExhaustiveDependentPairsYsGenerator> { fn get_ys(&self, x: &X) -> J; } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. All $y$ /// values are output before proceeding to the next $x$. /// /// This `struct` is created by; [`lex_dependent_pairs`]; see its documentation for more. #[derive(Clone, Debug)] pub struct LexDependentPairs< X: Clone, Y, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, > { done: bool, stop_after_empty_ys: bool, xs: I, ys: Option, x: Option, ys_generator: S, } impl< X: Clone, Y, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, > LexDependentPairs { fn advance_xs(&mut self) -> bool { if let Some(next_x) = self.xs.next() { self.x = Some(next_x); self.ys = Some(self.ys_generator.get_ys(self.x.as_ref().unwrap())); false } else { true } } } impl< X: Clone, Y, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, > Iterator for LexDependentPairs { type Item = (X, Y); fn next(&mut self) -> Option<(X, Y)> { if self.done { None } else { let mut new_ys = false; if self.x.is_none() { if self.advance_xs() { self.done = true; return None; } new_ys = true; } loop { if let Some(y) = self.ys.as_mut().unwrap().next() { return Some((self.x.as_ref().unwrap().clone(), y)); } else if self.stop_after_empty_ys && new_ys || self.advance_xs() { self.done = true; return None; } new_ys = true; } } } } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. All $y$ /// values are output before proceeding to the next $x$. /// /// This function takes an iterator `xs` that produces $x$ values, along with a `ys_generator` that /// creates an iterator of $y$ values when given a reference to an $x$ value. The resulting iterator /// first generates all pairs generated by the first $x$ value, then all pairs generated by the /// second $x$ value, and so on. /// /// It's called `lex_dependent_pairs` because if the `xs` iterator produces elements in some order, /// and each `ys` iterator produces elements in some order (uniform across all `ys`), then the /// resulting pairs are output in lexicographic order with respect to the $x$ and $y$ orders. /// /// Each `ys` iterator produced by `ys_generator` must be finite; if some `ys` is infinite, then no /// further `xs` value will be used. For a similar function that works with infinite `ys`, see /// [`exhaustive_dependent_pairs`]. /// /// If, after a certain point, all the generated `ys` are empty, the output iterator will hang /// trying to find another $(x, y)$ to output. To get around this, try /// [`lex_dependent_pairs_stop_after_empty_ys`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::{ /// lex_dependent_pairs, ExhaustiveDependentPairsYsGenerator, /// }; /// use maplit::hashmap; /// use std::collections::HashMap; /// use std::hash::Hash; /// use std::iter::Cloned; /// use std::slice::Iter; /// /// #[derive(Clone, Debug)] /// struct DPGeneratorFromMap { /// map: HashMap, /// } /// /// impl /// ExhaustiveDependentPairsYsGenerator>> /// for DPGeneratorFromMap /// { /// #[inline] /// fn get_ys(&self, x: &X) -> Cloned> { /// self.map[x].iter().cloned() /// } /// } /// /// let xs = ["a", "b", "c", "b", "a"].iter().cloned(); /// let xss = lex_dependent_pairs( /// xs, /// DPGeneratorFromMap { /// map: hashmap! { /// "a" => &[2, 3, 4][..], /// "b" => &[20][..], /// "c" => &[30, 40][..] /// }, /// }, /// ) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.as_slice(), /// &[ /// ("a", 2), /// ("a", 3), /// ("a", 4), /// ("b", 20), /// ("c", 30), /// ("c", 40), /// ("b", 20), /// ("a", 2), /// ("a", 3), /// ("a", 4) /// ] /// ); /// /// let xs = [1, 2, 3, 2, 3, 2, 2].iter().cloned(); /// let xss = lex_dependent_pairs( /// xs, /// DPGeneratorFromMap { /// map: hashmap! { /// 1 => &[100, 101, 102][..], /// 2 => &[][..], /// 3 => &[300, 301, 302][..] /// }, /// }, /// ) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.as_slice(), /// &[(1, 100), (1, 101), (1, 102), (3, 300), (3, 301), (3, 302), (3, 300), (3, 301), (3, 302),] /// ); /// ``` #[inline] pub const fn lex_dependent_pairs< X: Clone, Y, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, >( xs: I, ys_generator: S, ) -> LexDependentPairs { LexDependentPairs { done: false, stop_after_empty_ys: false, xs, ys: None, x: None, ys_generator, } } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. $x$ /// values with no corresponding $y$ values are treated specially. /// /// See [`lex_dependent_pairs`] for context. /// /// If the output iterator encounters an $x$ value whose corresponding `ys` iterator is empty, the /// output iterator stops iterating altogether. This prevents the iterator from getting stuck if all /// `ys` iterators after a certain point are empty. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::{ /// lex_dependent_pairs_stop_after_empty_ys, ExhaustiveDependentPairsYsGenerator, /// }; /// use maplit::hashmap; /// use std::collections::HashMap; /// use std::hash::Hash; /// use std::iter::Cloned; /// use std::slice::Iter; /// /// #[derive(Clone, Debug)] /// struct DPGeneratorFromMap { /// map: HashMap, /// } /// /// impl /// ExhaustiveDependentPairsYsGenerator>> /// for DPGeneratorFromMap /// { /// #[inline] /// fn get_ys(&self, x: &X) -> Cloned> { /// self.map[x].iter().cloned() /// } /// } /// /// let xs = [1, 2, 3, 2, 3, 2, 2].iter().cloned(); /// let xss = lex_dependent_pairs_stop_after_empty_ys( /// xs, /// DPGeneratorFromMap { /// map: hashmap! { /// 1 => &[100, 101, 102][..], /// 2 => &[][..], /// 3 => &[300, 301, 302][..] /// }, /// }, /// ) /// .take(20) /// .collect_vec(); /// // Stops after seeing 2, which maps to an empty iterator /// assert_eq!(xss.as_slice(), &[(1, 100), (1, 101), (1, 102)]); /// ``` #[inline] pub const fn lex_dependent_pairs_stop_after_empty_ys< X: Clone, Y, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, >( xs: I, ys_generator: S, ) -> LexDependentPairs { LexDependentPairs { done: false, stop_after_empty_ys: true, xs, ys: None, x: None, ys_generator, } } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. /// /// This `struct` is created by [`exhaustive_dependent_pairs`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveDependentPairs< X: Clone, Y, G: Iterator, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, > { done: bool, xs_done: bool, stop_after_empty_ys: bool, index_generator: G, xs: I, xs_yss: Vec<(X, J, bool)>, ys_generator: S, } impl< X: Clone, Y, G: Iterator, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, > Iterator for ExhaustiveDependentPairs { type Item = (X, Y); fn next(&mut self) -> Option<(X, Y)> { if self.done { None } else { let original_i = self.index_generator.next().unwrap(); loop { let mut i = original_i; let mut xs_yss_len = self.xs_yss.len(); if self.xs_done { i %= xs_yss_len; } else if i >= xs_yss_len { for x in (&mut self.xs).take(i - xs_yss_len + 1) { let ys = self.ys_generator.get_ys(&x); self.xs_yss.push((x, ys, true)); } xs_yss_len = self.xs_yss.len(); if xs_yss_len == 0 { self.done = true; return None; } else if i >= xs_yss_len { self.xs_done = true; i %= xs_yss_len; } } let t = &mut self.xs_yss[i]; if let Some(y) = t.1.next() { // t has been used t.2 = false; return Some((t.0.clone(), y)); } else if self.stop_after_empty_ys && t.2 { self.done = true; return None; } self.xs_yss.remove(i); if self.xs_done && self.xs_yss.is_empty() { self.done = true; return None; } } } } } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. /// /// This function takes an iterator `xs` that produces $x$ values, along with a `ys_generator` that /// creates an iterator of $y$ values when given a reference to an $x$ value. The resulting iterator /// does not use all of an $x$'s $y$s immediately. Instead, it uses an `index_generator` (an /// iterator of `usize`s) to determine which $x$ value's iterator should be advanced. This /// arrangement allows for an $x$ to map to infinitely many `ys`. /// /// `index_generator` must generate every natural number infinitely many times. Good generators can /// be created using [`ruler_sequence`](crate::num::iterators::ruler_sequence) or /// [`bit_distributor_sequence`](crate::num::iterators::bit_distributor_sequence). The slower the /// sequence's growth rate, the more this iterator will prefer to use initial $x$ values before /// exploring later ones. /// /// If you want all of an $x$ value's $y$s to be used before moving on to the next $x$, use /// [`lex_dependent_pairs`] instead. /// /// If, after a certain point, all the generated `ys` are empty, the output iterator will hang /// trying to find another $(x, y)$ to output. To get around this, try /// [`exhaustive_dependent_pairs_stop_after_empty_ys`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_positive_primitive_ints; /// use malachite_base::num::iterators::ruler_sequence; /// use malachite_base::tuples::exhaustive::{ /// exhaustive_dependent_pairs, ExhaustiveDependentPairsYsGenerator, /// }; /// use maplit::hashmap; /// use std::collections::HashMap; /// use std::hash::Hash; /// use std::iter::Cloned; /// use std::slice::Iter; /// /// #[derive(Clone, Debug)] /// struct MultiplesGeneratorHelper { /// u: u64, /// step: u64, /// } /// /// impl Iterator for MultiplesGeneratorHelper { /// type Item = u64; /// /// fn next(&mut self) -> Option { /// let next = self.u; /// self.u += self.step; /// Some(next) /// } /// } /// /// #[derive(Clone, Debug)] /// struct MultiplesGenerator {} /// /// impl ExhaustiveDependentPairsYsGenerator /// for MultiplesGenerator /// { /// #[inline] /// fn get_ys(&self, x: &u64) -> MultiplesGeneratorHelper { /// MultiplesGeneratorHelper { u: *x, step: *x } /// } /// } /// /// #[derive(Clone, Debug)] /// struct DPGeneratorFromMap { /// map: HashMap, /// } /// /// impl /// ExhaustiveDependentPairsYsGenerator>> /// for DPGeneratorFromMap /// { /// #[inline] /// fn get_ys(&self, x: &X) -> Cloned> { /// self.map[x].iter().cloned() /// } /// } /// /// // All (x, y) where x is a positive natural and y is a positive multiple of x. It would be /// // easier to do /// // /// // exhaustive_pairs_from_single(exhaustive_positive_primitive_ints::()) /// // .map(|(x, y)| (x, x * y)) /// // /// // in this case. /// let xs = exhaustive_positive_primitive_ints::(); /// let xss = exhaustive_dependent_pairs(ruler_sequence(), xs.clone(), MultiplesGenerator {}) /// .take(50) /// .collect_vec(); /// assert_eq!( /// xss.as_slice(), /// &[ /// (1, 1), /// (2, 2), /// (1, 2), /// (3, 3), /// (1, 3), /// (2, 4), /// (1, 4), /// (4, 4), /// (1, 5), /// (2, 6), /// (1, 6), /// (3, 6), /// (1, 7), /// (2, 8), /// (1, 8), /// (5, 5), /// (1, 9), /// (2, 10), /// (1, 10), /// (3, 9), /// (1, 11), /// (2, 12), /// (1, 12), /// (4, 8), /// (1, 13), /// (2, 14), /// (1, 14), /// (3, 12), /// (1, 15), /// (2, 16), /// (1, 16), /// (6, 6), /// (1, 17), /// (2, 18), /// (1, 18), /// (3, 15), /// (1, 19), /// (2, 20), /// (1, 20), /// (4, 12), /// (1, 21), /// (2, 22), /// (1, 22), /// (3, 18), /// (1, 23), /// (2, 24), /// (1, 24), /// (5, 10), /// (1, 25), /// (2, 26) /// ] /// ); /// /// let xs = [1, 2, 3, 2, 3, 2, 2].iter().cloned(); /// let xss = exhaustive_dependent_pairs( /// ruler_sequence(), /// xs, /// DPGeneratorFromMap { /// map: hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, /// }, /// ) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.as_slice(), /// &[(1, 100), (3, 300), (1, 101), (3, 300), (1, 102), (3, 301), (3, 302), (3, 301), (3, 302)] /// ); /// ``` #[inline] pub const fn exhaustive_dependent_pairs< X: Clone, Y, G: Iterator, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, >( index_generator: G, xs: I, ys_generator: S, ) -> ExhaustiveDependentPairs { ExhaustiveDependentPairs { done: false, xs_done: false, stop_after_empty_ys: false, index_generator, xs, xs_yss: Vec::new(), ys_generator, } } /// Generates pairs $(x, y)$, where the possible values of $y$ depend on the value of $x$. $x$ /// values with no corresponding $y$ values are treated specially. /// /// See [`exhaustive_dependent_pairs`] for context. /// /// If the output iterator encounters an $x$ value whose corresponding `ys` iterator is empty, the /// output iterator stops iterating altogether. This prevents the iterator from getting stuck if all /// `ys` iterators after a certain point are empty. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::iterators::ruler_sequence; /// use malachite_base::tuples::exhaustive::{ /// exhaustive_dependent_pairs_stop_after_empty_ys, ExhaustiveDependentPairsYsGenerator, /// }; /// use maplit::hashmap; /// use std::collections::HashMap; /// use std::hash::Hash; /// use std::iter::Cloned; /// use std::slice::Iter; /// /// #[derive(Clone, Debug)] /// struct DPGeneratorFromMap { /// map: HashMap, /// } /// /// impl /// ExhaustiveDependentPairsYsGenerator>> /// for DPGeneratorFromMap /// { /// #[inline] /// fn get_ys(&self, x: &X) -> Cloned> { /// self.map[x].iter().cloned() /// } /// } /// /// let xs = [1, 2, 3, 2, 3, 2, 2].iter().cloned(); /// let xss = exhaustive_dependent_pairs_stop_after_empty_ys( /// ruler_sequence(), /// xs, /// DPGeneratorFromMap { /// map: hashmap! { /// 1 => &[100, 101, 102][..], /// 2 => &[][..], /// 3 => &[300, 301, 302][..] /// }, /// }, /// ) /// .take(20) /// .collect_vec(); /// assert_eq!(xss.as_slice(), &[(1, 100)]); /// ``` #[inline] pub const fn exhaustive_dependent_pairs_stop_after_empty_ys< X: Clone, Y, G: Iterator, S: ExhaustiveDependentPairsYsGenerator, I: Iterator, J: Iterator, >( index_generator: G, xs: I, ys_generator: S, ) -> ExhaustiveDependentPairs { ExhaustiveDependentPairs { done: false, xs_done: false, stop_after_empty_ys: true, index_generator, xs, xs_yss: Vec::new(), ys_generator, } } /// Defines lexicographic ordered unique tuple generators. /// /// Malachite provides [`lex_ordered_unique_pairs`], but you can also define /// `lex_ordered_unique_triples`, `lex_ordered_unique_quadruples`, and so on, in your program using /// the code below. The documentation for [`lex_ordered_unique_pairs`] describes these other /// functions as well. /// /// See usage examples [here](self#lex_ordered_unique_quadruples). /// /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_ordered_unique_tuples; /// use malachite_base::vecs::exhaustive::fixed_length_ordered_unique_indices_helper; /// use std::marker::PhantomData; /// /// 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] /// ); /// lex_ordered_unique_tuples!( /// (pub(crate)), /// LexOrderedUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// lex_ordered_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// lex_ordered_unique_tuples!( /// (pub(crate)), /// LexOrderedUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// lex_ordered_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// lex_ordered_unique_tuples!( /// (pub(crate)), /// LexOrderedUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// lex_ordered_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! lex_ordered_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: expr),*] ) => { /// This documentation applies not only to `LexOrderedUniquePairs`, but also to /// `LexOrderedUniqueTriples`, `LexOrderedUniqueQuadruples`, and so on. See /// [`lex_ordered_unique_tuples`] for more information. /// /// Generates all $k$-tuples of elements from an iterator, where the tuples have no /// repetitions and are ordered the same way as in the iterator. /// /// The tuples are generated in lexicographic order with respect to the order of the element /// iterator. #[derive(Clone, Debug)] $($vis)* struct $struct where I::Item: Clone { first: bool, done: bool, xs: IteratorCache, indices: [usize; $k], phantom: PhantomData<*const I::Item>, } impl Iterator for $struct where I::Item: Clone { type Item = $out_t; fn next(&mut self) -> Option { if self.done { return None; } if self.first { self.first = false; self.xs.get($k); if let Some(n) = self.xs.known_len() { if n < $k { self.done = true; return None; } } } else { if let Some(n) = self.xs.known_len() { if fixed_length_ordered_unique_indices_helper(n, $k, &mut self.indices) { self.done = true; return None; } } else { *self.indices.last_mut().unwrap() += 1; } } if let Some(&last_index) = self.indices.last() { // Give known len a chance to be set self.xs.get(last_index + 1); } Some(($(self.xs.assert_get(self.indices[$i]).clone(),)*)) } } /// This documentation applies not only to `lex_ordered_unique_pairs`, but also to /// `lex_ordered_unique_triples`, `lex_ordered_unique_quadruples`, and so on. See /// [`lex_ordered_unique_tuples`] for more information. /// /// Generates $k$-tuples of elements from a single iterator, such that each tuple has no /// repeated elements, and the elements in each [`Vec`] are ordered the same way as they are /// in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_ordered_unique_quadruples). $($vis)* const fn $fn(xs: I) -> $struct where I::Item: Clone { $struct { first: true, done: false, xs: IteratorCache::new(xs), indices: [$($i),*], phantom: PhantomData, } } } } lex_ordered_unique_tuples!( (pub), LexOrderedUniquePairs, 2, (I::Item, I::Item), lex_ordered_unique_pairs, [0, 1] ); /// Defines exhaustive ordered unique tuple generators. /// /// Malachite provides [`exhaustive_ordered_unique_pairs`], but you can also define /// `exhaustive_ordered_unique_triples`, `exhaustive_ordered_unique_quadruples`, and so on, in your /// program using the code below. The documentation for [`exhaustive_ordered_unique_pairs`] /// describes these other functions as well. /// /// See usage examples [here](self#exhaustive_ordered_unique_quadruples). /// /// ``` /// use malachite_base::exhaustive_ordered_unique_tuples; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::vecs::exhaustive::next_bit_pattern; /// /// 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] /// ); /// exhaustive_ordered_unique_tuples!( /// (pub(crate)), /// ExhaustiveOrderedUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// exhaustive_ordered_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// exhaustive_ordered_unique_tuples!( /// (pub(crate)), /// ExhaustiveOrderedUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// exhaustive_ordered_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// exhaustive_ordered_unique_tuples!( /// (pub(crate)), /// ExhaustiveOrderedUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// exhaustive_ordered_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! exhaustive_ordered_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: expr),*] ) => { /// This documentation applies not only to `ExhaustiveOrderedUniquePairs`, but also to /// `ExhaustiveOrderedUniqueTriples`, `ExhaustiveOrderedUniqueQuadruples`, and so on. See /// [`exhaustive_ordered_unique_tuples`] for more information. /// /// Generates all $k$-tuples of elements from an iterator, where the tuples have no /// repetitions and are ordered the same way as in the iterator. #[derive(Clone)] pub struct $struct where I::Item: Clone, { done: bool, first: bool, xs: IteratorCache, pattern: Vec, } impl Iterator for $struct where I::Item: Clone, { type Item = $out_t; fn next(&mut self) -> Option { if self.done { return None; } else if self.first { self.first = false; } else { let mut c = $k; next_bit_pattern(&mut self.pattern, &mut c, $k, $k); } if !self.pattern.is_empty() && self.xs.get(self.pattern.len() - 1).is_none() { self.done = true; return None; } let mut results = self.pattern.iter().enumerate().filter_map(|(i, &b)| { if b { Some(self.xs.assert_get(i).clone()) } else { None } }); Some(($(((results.next().unwrap(), $i).0)),*)) } } /// This documentation applies not only to `exhaustive_ordered_unique_pairs`, but also to /// `exhaustive_ordered_unique_triples`, `exhaustive_ordered_unique_quadruples`, and so on. /// See [`exhaustive_ordered_unique_tuples`] for more information. /// /// Generates $k$-tuples of elements from a single iterator, such that each tuple has no /// repeated elements, and the elements in each [`Vec`] are ordered the same way as they are /// in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_ordered_unique_quadruples). pub fn $fn(xs: I) -> $struct where I::Item: Clone, { $struct { done: false, first: true, xs: IteratorCache::new(xs), pattern: vec![true; $k], } } } } exhaustive_ordered_unique_tuples!( (pub), ExhaustiveOrderedUniquePairs, 2, (I::Item, I::Item), exhaustive_ordered_unique_pairs, [0, 1] ); /// Defines lexicographic unique tuple generators. /// /// Malachite provides [`lex_unique_pairs`], but you can also define `lex_unique_triples`, /// `lex_unique_quadruples`, and so on, in your program using the code below. The documentation for /// [`lex_unique_pairs`] describes these other functions as well. /// /// See usage examples [here](self#lex_unique_pairs). /// /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_unique_tuples; /// use malachite_base::vecs::exhaustive::{unique_indices, UniqueIndices}; /// /// 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] /// ); /// lex_unique_tuples!( /// (pub(crate)), /// LexUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// lex_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// lex_unique_tuples!( /// (pub(crate)), /// LexUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// lex_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// lex_unique_tuples!( /// (pub(crate)), /// LexUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// lex_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! lex_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: expr),*] ) => { /// This documentation applies not only to `LexUniquePairs`, but also to `LexUniqueTriples`, /// `LexUniqueQuadruples`, and so on. See [`lex_unique_tuples`] for more information. /// /// Generates all $k$-tuples of elements from an iterator, where the tuples have no /// repetitions. /// /// The tuples are generated in lexicographic order with respect to the order of the element /// iterator. #[derive(Clone)] $($vis)* struct $struct where I::Item: Clone { first: bool, xs: IteratorCache, indices: UniqueIndices, } impl Iterator for $struct where I::Item: Clone { type Item = $out_t; fn next(&mut self) -> Option { if self.first { let nonempty = !self.indices.used.is_empty(); if nonempty && self.xs.get(self.indices.get_n() - 1).is_none() { self.indices.done = true; } self.first = false; } if self.xs.get(self.indices.get_n()).is_some() { self.indices.increment_n(); } self.indices.next().map(|indices| { let mut results = indices.into_iter().map(|i| self.xs.assert_get(i).clone()); ($(((results.next().unwrap(), $i).0)),*) }) } } /// This documentation applies not only to `lex_unique_pairs`, but also to /// `lex_unique_triples`, `lex_unique_quadruples`, and so on. See [`lex_unique_tuples`] for /// more information. /// /// Generates $k$-tuples of elements from a single iterator, such that each tuple has no /// repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $\frac{n!}{k!}$. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_unique_quadruples). #[inline] $($vis)* fn $fn(xs: I) -> $struct where I::Item: Clone { $struct { first: true, xs: IteratorCache::new(xs), // Initial n is k, but will grow to reach actual n (or forever, if n is infinite) indices: unique_indices($k, $k), } } } } lex_unique_tuples!( (pub), LexUniquePairs, 2, (I::Item, I::Item), lex_unique_pairs, [0, 1] ); /// Generates all pairs of elements from an iterator, where the pairs have no repetitions. /// /// This `struct` is created by [`exhaustive_unique_pairs`]; see its documentation for more. #[derive(Clone)] pub struct ExhaustiveUniquePairs where I::Item: Clone, { next: Option<(I::Item, I::Item)>, ps: ExhaustiveOrderedUniquePairs, } impl Iterator for ExhaustiveUniquePairs where I::Item: Clone, { type Item = (I::Item, I::Item); fn next(&mut self) -> Option<(I::Item, I::Item)> { if self.next.is_some() { take(&mut self.next) } else if let Some(p) = self.ps.next() { self.next = Some((p.1.clone(), p.0.clone())); Some(p) } else { None } } } /// Generates pairs of elements from a single iterator, such that each pair has no repeated /// elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $\tfrac{1}{2}{n!}$. /// /// If `xs` is empty, the output is also empty. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::exhaustive_unique_pairs; /// /// let xss = exhaustive_unique_pairs(1..=6).take(20).collect_vec(); /// assert_eq!( /// xss.into_iter().collect_vec().as_slice(), /// &[ /// (1, 2), /// (2, 1), /// (1, 3), /// (3, 1), /// (2, 3), /// (3, 2), /// (1, 4), /// (4, 1), /// (2, 4), /// (4, 2), /// (3, 4), /// (4, 3), /// (1, 5), /// (5, 1), /// (2, 5), /// (5, 2), /// (3, 5), /// (5, 3), /// (4, 5), /// (5, 4) /// ] /// ); /// ``` pub fn exhaustive_unique_pairs(xs: I) -> ExhaustiveUniquePairs where I::Item: Clone, { ExhaustiveUniquePairs { next: None, ps: exhaustive_ordered_unique_pairs(xs), } } /// Defines lexicographic unique tuple generators. /// /// Malachite provides [`exhaustive_unique_pairs`], but you can also define /// `exhaustive_unique_triples`, `lex_unique_quadruples`, and so on, in your program using the code /// below. /// /// See usage examples [here](self#lex_unique_quadruples). /// /// ``` /// use malachite_base::exhaustive_unique_tuples; /// use malachite_base::num::iterators::{ruler_sequence, RulerSequence}; /// use malachite_base::tuples::exhaustive::{ /// exhaustive_dependent_pairs, ExhaustiveDependentPairs, /// }; /// use malachite_base::vecs::exhaustive::{ /// exhaustive_ordered_unique_vecs_fixed_length, ExhaustiveOrderedUniqueCollections, /// ExhaustiveUniqueVecsGenerator, /// }; /// use malachite_base::vecs::ExhaustiveVecPermutations; /// /// 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] /// ); /// exhaustive_unique_tuples!( /// (pub(crate)), /// ExhaustiveUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// exhaustive_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// exhaustive_unique_tuples!( /// (pub(crate)), /// ExhaustiveUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// exhaustive_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// exhaustive_unique_tuples!( /// (pub(crate)), /// ExhaustiveUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// exhaustive_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! exhaustive_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: expr),*] ) => { // Generates all $k$-tuples of elements from an iterator, where the tuples have no // repetitions. #[derive(Clone)] $($vis)* struct $struct where I::Item: Clone { xss: ExhaustiveDependentPairs< Vec, Vec, RulerSequence, ExhaustiveUniqueVecsGenerator, ExhaustiveOrderedUniqueCollections>, ExhaustiveVecPermutations, > } impl Iterator for $struct where I::Item: Clone { type Item = $out_t; fn next(&mut self) -> Option { self.xss.next().map(|mut p| { let mut drain = p.1.drain(..); ($(((drain.next().unwrap(), $i).0)),*) }) } } // Generates $k$-tuples of elements from a single iterator, such that each tuple has no // repeated elements. // // The source iterator should not repeat any elements, but this is not enforced. // // If the input iterator is infinite, the output length is also infinite. // // If the input iterator length is $n$, the output length is $\frac{n!}{k!}$. // // If `xs` is empty, the output is also empty. // // # Examples // See [here](self#exhaustive_unique_quadruples). $($vis)* fn $fn(xs: I) -> $struct where I::Item: Clone { $struct { xss: exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs_fixed_length($k, xs), ExhaustiveUniqueVecsGenerator::new(), ) } } } } ================================================ FILE: malachite-base/src/tuples/mod.rs ================================================ // Copyright © 2026 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 . /// Generates all singletons (1-element tuples) with values from a given iterator. /// /// This `struct` is created by [`singletons`]; see its documentation for more. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Singletons { xs: I, } impl Iterator for Singletons { type Item = (I::Item,); #[inline] fn next(&mut self) -> Option<(I::Item,)> { self.xs.next().map(|x| (x,)) } } /// Generates all singletons (1-element tuples) with values from a given iterator. /// /// The elements appear in the same order as they do in the given iterator, but wrapped in `(_,)`. /// /// The output length is `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::singletons; /// /// assert_eq!( /// singletons([1, 2, 3].iter().cloned()).collect_vec(), /// &[(1,), (2,), (3,)] /// ); /// ``` #[inline] pub const fn singletons(xs: I) -> Singletons { Singletons { xs } } /// Iterators that generate tuples without repetition. /// /// To reduce binary size and lower compilation time, many of the functions described here are not /// actually defined in Malachite, but may be created in your program using macros exported from /// Malachite. To do this, see the documentation for `lex_tuples` and `lex_custom_tuples`. /// /// # lex_pairs /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::lex_pairs; /// /// assert_eq!( /// lex_pairs('a'..'f', 0..3).collect_vec(), /// &[ /// ('a', 0), /// ('a', 1), /// ('a', 2), /// ('b', 0), /// ('b', 1), /// ('b', 2), /// ('c', 0), /// ('c', 1), /// ('c', 2), /// ('d', 0), /// ('d', 1), /// ('d', 2), /// ('e', 0), /// ('e', 1), /// ('e', 2) /// ] /// ); /// ``` /// /// # lex_pairs_from_single /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::lex_pairs_from_single; /// /// assert_eq!( /// lex_pairs_from_single(0..3).collect_vec(), /// &[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] /// ); /// ``` /// /// # lex_triples_xyx /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_custom_tuples; /// /// fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { /// (a.unwrap(), b.unwrap(), c.unwrap()) /// } /// /// 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]] /// ); /// /// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first /// // iterator, `xs`, the chars 'a' through 'c', and the second, `ys`, produces the three numbers /// // 0, 1, and 2. The function we're using is `lex_triples_xyx`, meaning that the first element of /// // the output triples will be taken from `xs`, the second element from `ys`, and the third also /// // from `xs`. /// let ts = lex_triples_xyx('a'..='c', 0..3); /// assert_eq!( /// ts.collect_vec(), /// &[ /// ('a', 0, 'a'), /// ('a', 0, 'b'), /// ('a', 0, 'c'), /// ('a', 1, 'a'), /// ('a', 1, 'b'), /// ('a', 1, 'c'), /// ('a', 2, 'a'), /// ('a', 2, 'b'), /// ('a', 2, 'c'), /// ('b', 0, 'a'), /// ('b', 0, 'b'), /// ('b', 0, 'c'), /// ('b', 1, 'a'), /// ('b', 1, 'b'), /// ('b', 1, 'c'), /// ('b', 2, 'a'), /// ('b', 2, 'b'), /// ('b', 2, 'c'), /// ('c', 0, 'a'), /// ('c', 0, 'b'), /// ('c', 0, 'c'), /// ('c', 1, 'a'), /// ('c', 1, 'b'), /// ('c', 1, 'c'), /// ('c', 2, 'a'), /// ('c', 2, 'b'), /// ('c', 2, 'c') /// ] /// ); /// ``` /// /// # exhaustive_pairs_from_single /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::exhaustive_pairs_from_single; /// /// assert_eq!( /// exhaustive_pairs_from_single(0..4).collect_vec(), /// &[ /// (0, 0), /// (0, 1), /// (1, 0), /// (1, 1), /// (0, 2), /// (0, 3), /// (1, 2), /// (1, 3), /// (2, 0), /// (2, 1), /// (3, 0), /// (3, 1), /// (2, 2), /// (2, 3), /// (3, 2), /// (3, 3) /// ] /// ); /// ``` /// /// # exhaustive_pairs_1_input /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::exhaustive_tuples_1_input; /// 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::logic::traits::SignificantBits; /// use std::cmp::max; /// use std::marker::PhantomData; /// /// 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] /// ); /// /// // We are generating triples of `char`s using one input iterator, which produces all ASCII /// // `char`s. The third element has a tiny output type, so it will grow more slowly than the other /// // two elements (though it doesn't look that way from the first few tuples). /// let ts = exhaustive_triples_1_input( /// exhaustive_ascii_chars(), /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::tiny(), /// ); /// assert_eq!( /// ts.take(20).collect_vec(), /// &[ /// ('a', 'a', 'a'), /// ('a', 'a', 'b'), /// ('a', 'a', 'c'), /// ('a', 'a', 'd'), /// ('a', 'b', 'a'), /// ('a', 'b', 'b'), /// ('a', 'b', 'c'), /// ('a', 'b', 'd'), /// ('a', 'a', 'e'), /// ('a', 'a', 'f'), /// ('a', 'a', 'g'), /// ('a', 'a', 'h'), /// ('a', 'b', 'e'), /// ('a', 'b', 'f'), /// ('a', 'b', 'g'), /// ('a', 'b', 'h'), /// ('b', 'a', 'a'), /// ('b', 'a', 'b'), /// ('b', 'a', 'c'), /// ('b', 'a', 'd') /// ] /// ); /// ``` /// /// # exhaustive_pairs /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::exhaustive::exhaustive_pairs; /// /// let xss = exhaustive_pairs(['a', 'b', 'c'].iter().cloned(), 0..3).collect_vec(); /// assert_eq!( /// xss, /// &[('a', 0), ('a', 1), ('b', 0), ('b', 1), ('a', 2), ('b', 2), ('c', 0), ('c', 1), ('c', 2)] /// ); /// ``` /// /// # exhaustive_pairs_custom_output /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::bit_distributor::BitDistributorOutputType; /// use malachite_base::tuples::exhaustive::exhaustive_pairs_custom_output; /// /// let xss = exhaustive_pairs_custom_output( /// ['a', 'b', 'c'].iter().cloned(), /// 0..3, /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::tiny(), /// ) /// .collect_vec(); /// assert_eq!( /// xss, /// &[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2), ('c', 0), ('c', 1), ('c', 2)] /// ); /// ``` /// /// # exhaustive_triples_xyx /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::custom_tuples; /// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; /// use malachite_base::num::logic::traits::SignificantBits; /// use std::cmp::max; /// /// #[allow(clippy::missing_const_for_fn)] /// fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { /// (a.unwrap(), b.unwrap(), c.unwrap()) /// } /// /// 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]] /// ); /// /// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first /// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers /// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx`, meaning that the first /// // element of the output triples will be taken from `xs`, the second element from `ys`, and the /// // third also from `xs`. /// let ts = exhaustive_triples_xyx(exhaustive_ascii_chars(), 0..3); /// assert_eq!( /// ts.take(20).collect_vec(), /// &[ /// ('a', 0, 'a'), /// ('a', 0, 'b'), /// ('a', 1, 'a'), /// ('a', 1, 'b'), /// ('b', 0, 'a'), /// ('b', 0, 'b'), /// ('b', 1, 'a'), /// ('b', 1, 'b'), /// ('a', 0, 'c'), /// ('a', 0, 'd'), /// ('a', 1, 'c'), /// ('a', 1, 'd'), /// ('b', 0, 'c'), /// ('b', 0, 'd'), /// ('b', 1, 'c'), /// ('b', 1, 'd'), /// ('a', 2, 'a'), /// ('a', 2, 'b'), /// ('b', 2, 'a'), /// ('b', 2, 'b') /// ] /// ); /// ``` /// /// # exhaustive_triples_xyx_custom_output /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::custom_tuples; /// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; /// use malachite_base::num::logic::traits::SignificantBits; /// use std::cmp::max; /// /// #[allow(clippy::missing_const_for_fn)] /// fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { /// (a.unwrap(), b.unwrap(), c.unwrap()) /// } /// /// 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]] /// ); /// /// // We are generating triples of `char`, `i8`, and `char` using two input iterators. The first /// // iterator, `xs`, produces all ASCII `char`s, and the second, `ys`, produces the three numbers /// // 0, 1, and 2. The function we're using is `exhaustive_triples_xyx_custom_output`, meaning that /// // the first element of the output triples will be taken from `xs`, the second element from /// // `ys`, and the third also from `xs`. /// // /// // The third element has a tiny output type, so it will grow more slowly than the other two /// // elements (though it doesn't look that way from the first few tuples). /// let ts = exhaustive_triples_xyx_custom_output( /// exhaustive_ascii_chars(), /// 0..3, /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::tiny(), /// ); /// assert_eq!( /// ts.take(20).collect_vec(), /// &[ /// ('a', 0, 'a'), /// ('a', 0, 'b'), /// ('a', 0, 'c'), /// ('a', 0, 'd'), /// ('a', 1, 'a'), /// ('a', 1, 'b'), /// ('a', 1, 'c'), /// ('a', 1, 'd'), /// ('a', 0, 'e'), /// ('a', 0, 'f'), /// ('a', 0, 'g'), /// ('a', 0, 'h'), /// ('a', 1, 'e'), /// ('a', 1, 'f'), /// ('a', 1, 'g'), /// ('a', 1, 'h'), /// ('b', 0, 'a'), /// ('b', 0, 'b'), /// ('b', 0, 'c'), /// ('b', 0, 'd') /// ] /// ); /// ``` /// /// # lex_ordered_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_ordered_unique_tuples; /// use malachite_base::vecs::exhaustive::fixed_length_ordered_unique_indices_helper; /// use std::marker::PhantomData; /// /// lex_ordered_unique_tuples!( /// (pub(crate)), /// LexOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// lex_ordered_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let xss = lex_ordered_unique_quadruples(1..=6).collect_vec(); /// assert_eq!( /// xss.into_iter().collect_vec().as_slice(), /// &[ /// (1, 2, 3, 4), /// (1, 2, 3, 5), /// (1, 2, 3, 6), /// (1, 2, 4, 5), /// (1, 2, 4, 6), /// (1, 2, 5, 6), /// (1, 3, 4, 5), /// (1, 3, 4, 6), /// (1, 3, 5, 6), /// (1, 4, 5, 6), /// (2, 3, 4, 5), /// (2, 3, 4, 6), /// (2, 3, 5, 6), /// (2, 4, 5, 6), /// (3, 4, 5, 6) /// ] /// ); /// ``` /// /// # exhaustive_ordered_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::exhaustive_ordered_unique_tuples; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::vecs::exhaustive::next_bit_pattern; /// /// exhaustive_ordered_unique_tuples!( /// (pub(crate)), /// ExhaustiveOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// exhaustive_ordered_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let xss = exhaustive_ordered_unique_quadruples(1..=6).collect_vec(); /// assert_eq!( /// xss.into_iter().collect_vec().as_slice(), /// &[ /// (1, 2, 3, 4), /// (1, 2, 3, 5), /// (1, 2, 4, 5), /// (1, 3, 4, 5), /// (2, 3, 4, 5), /// (1, 2, 3, 6), /// (1, 2, 4, 6), /// (1, 3, 4, 6), /// (2, 3, 4, 6), /// (1, 2, 5, 6), /// (1, 3, 5, 6), /// (2, 3, 5, 6), /// (1, 4, 5, 6), /// (2, 4, 5, 6), /// (3, 4, 5, 6) /// ] /// ); /// ``` /// /// # lex_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_unique_tuples; /// use malachite_base::vecs::exhaustive::{unique_indices, UniqueIndices}; /// /// lex_unique_tuples!( /// (pub(crate)), /// LexUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// lex_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let xss = lex_unique_quadruples(1..=6).take(20).collect_vec(); /// assert_eq!( /// xss.into_iter().collect_vec().as_slice(), /// &[ /// (1, 2, 3, 4), /// (1, 2, 3, 5), /// (1, 2, 3, 6), /// (1, 2, 4, 3), /// (1, 2, 4, 5), /// (1, 2, 4, 6), /// (1, 2, 5, 3), /// (1, 2, 5, 4), /// (1, 2, 5, 6), /// (1, 2, 6, 3), /// (1, 2, 6, 4), /// (1, 2, 6, 5), /// (1, 3, 2, 4), /// (1, 3, 2, 5), /// (1, 3, 2, 6), /// (1, 3, 4, 2), /// (1, 3, 4, 5), /// (1, 3, 4, 6), /// (1, 3, 5, 2), /// (1, 3, 5, 4) /// ] /// ); /// ``` /// /// # exhaustive_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::exhaustive_unique_tuples; /// use malachite_base::num::iterators::{ruler_sequence, RulerSequence}; /// use malachite_base::tuples::exhaustive::{ /// exhaustive_dependent_pairs, ExhaustiveDependentPairs, /// }; /// use malachite_base::vecs::exhaustive::{ /// exhaustive_ordered_unique_vecs_fixed_length, ExhaustiveOrderedUniqueCollections, /// ExhaustiveUniqueVecsGenerator, /// }; /// use malachite_base::vecs::ExhaustiveVecPermutations; /// /// exhaustive_unique_tuples!( /// (pub(crate)), /// ExhaustiveUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// exhaustive_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let xss = exhaustive_unique_quadruples(1..=6).take(20).collect_vec(); /// assert_eq!( /// xss.into_iter().collect_vec().as_slice(), /// &[ /// (1, 2, 3, 4), /// (1, 2, 3, 5), /// (1, 2, 4, 3), /// (1, 2, 4, 5), /// (1, 3, 2, 4), /// (1, 2, 5, 3), /// (1, 3, 4, 2), /// (1, 3, 4, 5), /// (1, 4, 2, 3), /// (1, 3, 2, 5), /// (1, 4, 3, 2), /// (1, 2, 5, 4), /// (2, 1, 3, 4), /// (1, 3, 5, 2), /// (2, 1, 4, 3), /// (2, 3, 4, 5), /// (2, 3, 1, 4), /// (1, 5, 2, 3), /// (2, 3, 4, 1), /// (1, 4, 2, 5) /// ] /// ); /// ``` pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate tuples randomly. /// /// # random_pairs /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::tuples::random::random_pairs; /// /// let ps = random_pairs( /// EXAMPLE_SEED, /// &|seed| random_unsigned_inclusive_range::(seed, 0, 2), /// &|seed| random_char_inclusive_range(seed, 'x', 'z'), /// ); /// assert_eq!( /// ps.take(20).collect_vec().as_slice(), /// &[ /// (1, 'z'), /// (1, 'x'), /// (1, 'z'), /// (1, 'y'), /// (2, 'x'), /// (0, 'z'), /// (0, 'z'), /// (0, 'z'), /// (2, 'z'), /// (0, 'y'), /// (2, 'x'), /// (0, 'x'), /// (2, 'z'), /// (0, 'z'), /// (2, 'x'), /// (2, 'x'), /// (2, 'y'), /// (1, 'y'), /// (0, 'x'), /// (2, 'x') /// ] /// ); /// ``` /// /// # random_pairs_from_single /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::tuples::random::random_pairs_from_single; /// /// let ps = random_pairs_from_single(random_unsigned_inclusive_range::(EXAMPLE_SEED, 0, 2)); /// assert_eq!( /// ps.take(20).collect_vec().as_slice(), /// &[ /// (1, 0), /// (1, 2), /// (1, 1), /// (0, 1), /// (0, 2), /// (1, 0), /// (1, 2), /// (2, 0), /// (1, 0), /// (2, 2), /// (2, 1), /// (0, 2), /// (2, 1), /// (1, 1), /// (0, 0), /// (2, 0), /// (2, 2), /// (1, 0), /// (1, 1), /// (0, 2) /// ] /// ); /// ``` /// /// # random_triples_xyx /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::{Seed, EXAMPLE_SEED}; /// use malachite_base::random_custom_tuples; /// /// 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]] /// ); /// /// // We are generating triples of `char`s using two input iterators. The first iterator, `xs`, /// // produces all ASCII `char`s, and the second, `ys`, produces the three numbers 0, 1, and 2. The /// // function we're using is `random_triples_xyx`, meaning that the first element of the /// // output triples will be taken from `xs`, the second element from `ys`, and the third also from /// // `xs`. /// let ts = random_triples_xyx( /// EXAMPLE_SEED, /// &|seed| random_char_inclusive_range(seed, 'x', 'z'), /// &|seed| random_unsigned_inclusive_range::(seed, 0, 2), /// ); /// assert_eq!( /// ts.take(20).collect_vec().as_slice(), /// &[ /// ('y', 2, 'y'), /// ('y', 0, 'y'), /// ('z', 2, 'x'), /// ('x', 1, 'x'), /// ('z', 0, 'x'), /// ('z', 2, 'x'), /// ('z', 2, 'x'), /// ('z', 2, 'z'), /// ('z', 2, 'y'), /// ('x', 1, 'z'), /// ('z', 0, 'x'), /// ('y', 0, 'z'), /// ('y', 2, 'z'), /// ('x', 2, 'z'), /// ('z', 0, 'y'), /// ('z', 0, 'y'), /// ('y', 1, 'x'), /// ('z', 1, 'z'), /// ('x', 0, 'z'), /// ('z', 0, 'x') /// ] /// ); /// ``` /// /// # random_ordered_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::random_ordered_unique_tuples; /// use malachite_base::sets::random::{ /// random_b_tree_sets_fixed_length, RandomBTreeSetsFixedLength, /// }; /// /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// random_ordered_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let qs = random_ordered_unique_quadruples(random_unsigned_inclusive_range::( /// EXAMPLE_SEED, /// 1, /// 10, /// )); /// assert_eq!( /// qs.take(20).collect_vec().as_slice(), /// &[ /// (2, 5, 6, 8), /// (3, 5, 7, 9), /// (1, 2, 6, 8), /// (3, 4, 6, 7), /// (3, 6, 9, 10), /// (4, 6, 8, 10), /// (3, 6, 8, 10), /// (2, 5, 9, 10), /// (2, 3, 8, 10), /// (1, 3, 7, 8), /// (1, 2, 6, 10), /// (2, 5, 8, 9), /// (1, 8, 9, 10), /// (1, 3, 7, 8), /// (2, 3, 4, 5), /// (1, 3, 4, 8), /// (3, 6, 7, 9), /// (5, 6, 7, 8), /// (3, 4, 5, 9), /// (4, 6, 9, 10) /// ] /// ); /// ``` /// /// # random_unique_quadruples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::random_unique_tuples; /// use std::collections::HashMap; /// use std::hash::Hash; /// /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// random_unique_quadruples, /// [0, 1, 2, 3] /// ); /// /// let qs = random_unique_quadruples(random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 10)); /// assert_eq!( /// qs.take(20).collect_vec().as_slice(), /// &[ /// (2, 8, 6, 5), /// (7, 5, 3, 9), /// (2, 8, 6, 1), /// (3, 7, 4, 6), /// (3, 10, 6, 9), /// (6, 10, 4, 8), /// (6, 10, 8, 3), /// (10, 2, 9, 5), /// (8, 10, 2, 3), /// (8, 1, 7, 3), /// (2, 6, 1, 10), /// (9, 5, 8, 2), /// (8, 1, 9, 10), /// (7, 3, 8, 1), /// (3, 2, 5, 4), /// (3, 8, 4, 1), /// (9, 7, 6, 3), /// (5, 7, 8, 6), /// (5, 3, 9, 4), /// (9, 10, 4, 6) /// ] /// ); /// ``` pub mod random; ================================================ FILE: malachite-base/src/tuples/random.rs ================================================ // Copyright © 2026 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 crate::random::Seed; use std::cmp::Ordering::*; use std::iter::{Repeat, repeat}; /// Generates random units; repeats `()`. /// /// $P(()) = 1$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::tuples::random::random_units; /// /// assert_eq!(random_units().take(10).collect_vec(), &[(); 10]); /// ``` pub fn random_units() -> Repeat<()> { repeat(()) } // hack for macro #[doc(hidden)] #[inline] pub fn next_helper(x: &mut I, _i: usize) -> Option { x.next() } /// Defines random tuple generators. /// /// Malachite provides [`random_pairs`] and [`random_pairs_from_single`], but you can also define /// `random_triples`, `random_quadruples`, and so on, and `random_triples_from_single`, /// `random_quadruples_from_single`, and so on, in your program using the code below. The /// documentation for [`random_pairs`] and [`random_pairs_from_single`] describes these other /// functions as well. /// /// See usage examples [here](self#random_pairs) and [here](self#random_pairs_from_single). /// /// ``` /// use malachite_base::random::Seed; /// use malachite_base::random_tuples; /// use malachite_base::tuples::random::next_helper; /// /// 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_tuples!( /// (pub(crate)), /// RandomQuadruples, /// RandomQuadruplesFromSingle, /// random_quadruples, /// random_quadruples_from_single, /// (I::Item, I::Item, I::Item, I::Item), /// [0, X, I, xs, xs_gen], /// [1, Y, J, ys, ys_gen], /// [2, Z, K, zs, zs_gen], /// [3, W, L, ws, ws_gen] /// ); /// random_tuples!( /// (pub(crate)), /// RandomQuintuples, /// RandomQuintuplesFromSingle, /// random_quintuples, /// random_quintuples_from_single, /// (I::Item, I::Item, I::Item, I::Item, I::Item), /// [0, X, I, xs, xs_gen], /// [1, Y, J, ys, ys_gen], /// [2, Z, K, zs, zs_gen], /// [3, W, L, ws, ws_gen], /// [4, V, M, vs, vs_gen] /// ); /// random_tuples!( /// (pub(crate)), /// RandomSextuples, /// RandomSextuplesFromSingle, /// random_sextuples, /// random_sextuples_from_single, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// [0, X, I, xs, xs_gen], /// [1, Y, J, ys, ys_gen], /// [2, Z, K, zs, zs_gen], /// [3, W, L, ws, ws_gen], /// [4, V, M, vs, vs_gen], /// [5, U, N, us, us_gen] /// ); /// random_tuples!( /// (pub(crate)), /// RandomSeptuples, /// RandomSeptuplesFromSingle, /// random_septuples, /// random_septuples_from_single, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// [0, X, I, xs, xs_gen], /// [1, Y, J, ys, ys_gen], /// [2, Z, K, zs, zs_gen], /// [3, W, L, ws, ws_gen], /// [4, V, M, vs, vs_gen], /// [5, U, N, us, us_gen], /// [6, T, O, ts, ts_gen] /// ); /// random_tuples!( /// (pub(crate)), /// RandomOctuples, /// RandomOctuplesFromSingle, /// random_octuples, /// random_octuples_from_single, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// [0, X, I, xs, xs_gen], /// [1, Y, J, ys, ys_gen], /// [2, Z, K, zs, zs_gen], /// [3, W, L, ws, ws_gen], /// [4, V, M, vs, vs_gen], /// [5, U, N, us, us_gen], /// [6, T, O, ts, ts_gen], /// [7, S, P, ss, ss_gen] /// ); /// ``` #[macro_export] macro_rules! random_tuples { ( ($($vis:tt)*), $random_struct: ident, $random_struct_from_single: ident, $random_fn: ident, $random_fn_from_single: ident, $single_out: tt, $([$i: expr, $t: ident, $it: ident, $xs: ident, $xs_gen:ident]),* ) => { /// This documentation applies not only to `RandomPairs`, but also to `RandomTriples`, /// `RandomQuadruples`, and so on. See [`random_tuples`] for more information. /// /// Generates random $n$-tuples using elements from $n$ iterators. #[derive(Clone, Debug)] #[allow(dead_code)] $($vis)* struct $random_struct<$($t: Clone, $it: Iterator,)*> { $($xs: $it,)* } impl<$($t: Clone, $it: Iterator,)*> Iterator for $random_struct<$($t, $it,)*> { type Item = ($($t,)*); #[inline] fn next(&mut self) -> Option { Some(($(self.$xs.next().unwrap()),*)) } } /// This documentation applies not only to `random_pairs`, but also to `random_triples`, /// `random_quadruples`, and so on. See [`random_tuples`] for more information. /// /// Generates random $n$-tuples with elements from $n$ iterators. /// /// The probability of a particular $n$-tuple being generated is the product of the /// probabilities of each of its elements. /// /// `xs`, `ys`, `zs`, ... must be infinite. /// /// # Examples /// See [here](self#random_pairs). #[allow(dead_code)] $($vis)* fn $random_fn<$($t: Clone, $it: Iterator,)*>( seed: Seed, $($xs_gen: &dyn Fn(Seed) -> $it,)* ) -> $random_struct<$($t, $it,)*> { $random_struct { $($xs: $xs_gen(seed.fork(stringify!($xs))),)* } } /// This documentation applies not only to `RandomPairsFromSingle`, but also to /// `RandomTriplesFromSingle`, `RandomQuadruplesFromSingle`, and so on. See /// [`random_tuples`] for more information. /// /// Generates random $n$-tuples using elements from a single iterator. #[derive(Clone, Debug)] #[allow(dead_code)] $($vis)* struct $random_struct_from_single { xs: I } impl Iterator for $random_struct_from_single { type Item = $single_out; #[inline] fn next(&mut self) -> Option<$single_out> { Some(($(next_helper(&mut self.xs, $i).unwrap(),)*)) } } /// This documentation applies not only to `random_pairs_from_single`, but also to /// `random_triples_from_single`, `random_quadruples_from_single`, and so on. See /// [`random_tuples`] for more information. /// /// Generates random $n$-tuples using elements from a single iterator. /// /// The probability of a particular $n$-tuple being generated is the product of the /// probabilities of each of its elements. /// /// `xs` must be infinite. /// /// # Examples /// See [here](self#random_pairs_from_single). #[allow(dead_code)] #[inline] $($vis)* const fn $random_fn_from_single(xs: I) -> $random_struct_from_single { $random_struct_from_single { xs } } } } random_tuples!( (pub), RandomPairs, RandomPairsFromSingle, random_pairs, random_pairs_from_single, (I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen] ); /// Defines custom random tuple generators. /// /// You can define custom tuple generators like `random_triples_xyx` in your program using the code /// below. /// /// See usage examples [here](self#random_triples_xyx). /// /// ``` /// use malachite_base::random::Seed; /// use malachite_base::random_custom_tuples; /// /// 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_custom_tuples!( /// (pub(crate)), /// RandomTriplesXYY, /// (X, Y, Y), /// random_triples_xyy, /// [X, I, xs, xs_gen, [x_0, x_0]], /// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXXXY, /// (X, X, X, Y), /// random_quadruples_xxxy, /// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_2, x_2]], /// [Y, J, ys, ys_gen, [y_3, y_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXXYX, /// (X, X, Y, X), /// random_quadruples_xxyx, /// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_3, y_2]], /// [Y, J, ys, ys_gen, [y_2, x_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXXYZ, /// (X, X, Y, Z), /// random_quadruples_xxyz, /// [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]], /// [Y, J, ys, ys_gen, [y_2, y_2]], /// [Z, K, zs, zs_gen, [z_3, z_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXYXZ, /// (X, Y, X, Z), /// random_quadruples_xyxz, /// [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]], /// [Y, J, ys, ys_gen, [y_1, x_2]], /// [Z, K, zs, zs_gen, [z_3, z_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXYYX, /// (X, Y, Y, X), /// random_quadruples_xyyx, /// [X, I, xs, xs_gen, [x_0, x_0], [x_3, y_1]], /// [Y, J, ys, ys_gen, [y_1, y_2], [y_2, x_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXYYZ, /// (X, Y, Y, Z), /// random_quadruples_xyyz, /// [X, I, xs, xs_gen, [x_0, x_0]], /// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]], /// [Z, K, zs, zs_gen, [z_3, z_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuadruplesXYZZ, /// (X, Y, Z, Z), /// random_quadruples_xyzz, /// [X, I, xs, xs_gen, [x_0, x_0]], /// [Y, J, ys, ys_gen, [y_1, y_1]], /// [Z, K, zs, zs_gen, [z_2, z_2], [z_3, z_3]] /// ); /// random_custom_tuples!( /// (pub(crate)), /// RandomQuintuplesXYYYZ, /// (X, Y, Y, Y, Z), /// random_quintuples_xyyyz, /// [X, I, xs, xs_gen, [x_0, x_0]], /// [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2], [y_3, y_3]], /// [Z, K, zs, zs_gen, [z_4, z_4]] /// ); /// ``` #[macro_export] macro_rules! random_custom_tuples { ( ($($vis:tt)*), $random_struct: ident, $out_t: ty, $random_fn: ident, $([$t: ident, $it: ident, $xs: ident, $xs_gen: ident, $([$x: ident, $x_ord: ident]),*]),* ) => { // Generates random $n$-tuples with elements from $m$ iterators, where $m \leq n$. // // The mapping from iterators to tuple slots is indicated by the struct name; for example, // in `RandomTriplesXYX` there are two iterators, `X`, and `Y`; `X` generates the elements // in the first and third slots of the output triples, and `Y` generates the elements in the // second slots. #[derive(Clone, Debug)] $($vis)* struct $random_struct<$($t: Clone, $it: Iterator,)*> { $($xs: $it,)* } impl<$($t: Clone, $it: Iterator,)*> Iterator for $random_struct<$($t, $it,)*> { type Item = $out_t; fn next(&mut self) -> Option { $( $( let $x = self.$xs.next().unwrap(); )* )* Some(($($($x_ord,)*)*)) } } // Generates random $n$-tuples with elements from $m$ iterators, where $m \leq n$. // // The mapping from iterators to tuple slots is indicated by the function name; for example, // `random_triples_xyx` takes two iterators, `xs`, and `ys`; `xs` generates the elements in // the first and third slots of the output triples, and `ys` generates the elements in the // second slots. // // The probability of a particular $n$-tuple being generated is the product of the // probabilities of each of its elements. // // `xs`, `ys`, `zs`, ... must be infinite. // // # Examples // See [here](self#random_triples_xyx). $($vis)* fn $random_fn<$($t: Clone, $it: Iterator,)*>( seed: Seed, $($xs_gen: &dyn Fn(Seed) -> $it,)* ) -> $random_struct<$($t, $it,)*> { $random_struct { $($xs: $xs_gen(seed.fork(stringify!($xs))),)* } } } } /// Generates random pairs using elements from a single iterator, where the first element is less /// than the second. #[derive(Clone, Debug)] pub struct RandomOrderedUniquePairs where I::Item: Ord, { xs: I, } impl Iterator for RandomOrderedUniquePairs where I::Item: Ord, { type Item = (I::Item, I::Item); #[inline] fn next(&mut self) -> Option { let mut out_0 = None; let out_1; loop { let x = self.xs.next().unwrap(); if out_0.is_none() { out_0 = Some(x); } else { match x.cmp(out_0.as_ref().unwrap()) { Equal => {} Greater => { out_1 = x; break; } Less => { out_1 = out_0.unwrap(); out_0 = Some(x); break; } } } } Some((out_0.unwrap(), out_1)) } } /// Generates random pairs using elements from a single iterator, where the first element of each /// pair is less than the second. /// /// The input iterator must generate at least two distinct elements; otherwise, this iterator will /// hang. /// /// $$ /// P((x\_0, x\_1)) = 2P(x\_0)P(x\_1). /// $$ /// /// The above formula assumes that the pair is valid, \emph{i.e.} its first element is less than its /// second. The probability of an invalid pair is zero. /// /// `xs` must be infinite. #[inline] pub const fn random_ordered_unique_pairs(xs: I) -> RandomOrderedUniquePairs where I::Item: Ord, { RandomOrderedUniquePairs { xs } } /// Defines random ordered unique tuple generators. /// /// Malachite provides [`random_ordered_unique_pairs`], but you can also define /// `random_ordered_unique_triples`, `random_ordered_unique_quadruples`, and so on, in your program /// using the code below. /// /// See usage examples [here](self#random_ordered_unique_quadruples). /// /// ``` /// use malachite_base::random_ordered_unique_tuples; /// use malachite_base::sets::random::{ /// random_b_tree_sets_fixed_length, RandomBTreeSetsFixedLength, /// }; /// /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueTriples, /// 3, /// (I::Item, I::Item, I::Item), /// random_ordered_unique_triples, /// [0, 1, 2] /// ); /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// random_ordered_unique_quadruples, /// [0, 1, 2, 3] /// ); /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuintuples, /// 5, /// (I::Item, I::Item, I::Item, I::Item, I::Item), /// random_ordered_unique_quintuples, /// [0, 1, 2, 3, 4] /// ); /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// random_ordered_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// random_ordered_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// random_ordered_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// random_ordered_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! random_ordered_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: expr),*] ) => { // Generates random $n$-tuples using elements from a single iterator, where the tuples have // no repeated elements, and the elements are in ascending order. #[derive(Clone, Debug)] $($vis)* struct $struct where I::Item: Ord { xs: RandomBTreeSetsFixedLength, } impl Iterator for $struct where I::Item: Ord { type Item = $out_t; #[inline] fn next(&mut self) -> Option { let mut elements = self.xs.next().unwrap().into_iter(); Some(($(((elements.next().unwrap(), $i).0)),*)) } } // Generates random $n$-tuples using elements from a single iterator, where the tuples have // no repeated elements, and the elements are in ascending order. // // The input iterator must generate at least `len` distinct elements; otherwise, this // iterator will hang. // // $$ // P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i). // $$ // // The above formula assumes that the tuple is valid, \emph{i.e.} its elements are strictly // increasing. The probability of an invalid tuple is zero. // // `xs` must be infinite. // // # Examples // See [here](self#random_ordered_unique_quadruples). #[inline] $($vis)* fn $fn(xs: I) -> $struct where I::Item: Ord, { $struct { xs: random_b_tree_sets_fixed_length($k, xs), } } } } /// Generates random pairs using elements from a single iterator, where the first element is not /// equal to the second. #[derive(Clone, Debug)] pub struct RandomUniquePairs where I::Item: Eq, { xs: I, } impl Iterator for RandomUniquePairs where I::Item: Eq, { type Item = (I::Item, I::Item); #[inline] fn next(&mut self) -> Option { let mut out_0 = None; let out_1; loop { let x = self.xs.next().unwrap(); if let Some(out_0) = out_0.as_ref() { if x != *out_0 { out_1 = x; break; } } else { out_0 = Some(x); } } Some((out_0.unwrap(), out_1)) } } /// Generates random pairs using elements from a single iterator, where the two elements of each /// pair are unequal. /// /// The input iterator must generate at least two distinct elements; otherwise, this iterator will /// hang. /// /// `xs` must be infinite. #[inline] pub const fn random_unique_pairs(xs: I) -> RandomUniquePairs where I::Item: Eq, { RandomUniquePairs { xs } } /// Defines random unique tuple generators. /// /// Malachite provides [`random_unique_pairs`], but you can also define `random_unique_triples`, /// `random_unique_quadruples`, and so on, in your program using the code below. /// /// See usage examples [here](self#random_unique_quadruples). /// /// ``` /// use malachite_base::random_unique_tuples; /// use std::collections::HashMap; /// use std::hash::Hash; /// /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueTriples, /// 3, /// (I::Item, I::Item, I::Item), /// random_unique_triples, /// [0, 1, 2] /// ); /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuadruples, /// 4, /// (I::Item, I::Item, I::Item, I::Item), /// random_unique_quadruples, /// [0, 1, 2, 3] /// ); /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueQuintuples, /// 5, /// (I::Item, I::Item, I::Item, I::Item, I::Item), /// random_unique_quintuples, /// [0, 1, 2, 3, 4] /// ); /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueSextuples, /// 6, /// (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), /// random_unique_sextuples, /// [0, 1, 2, 3, 4, 5] /// ); /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueSeptuples, /// 7, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// random_unique_septuples, /// [0, 1, 2, 3, 4, 5, 6] /// ); /// random_unique_tuples!( /// (pub(crate)), /// RandomOrderedUniqueOctuples, /// 8, /// ( /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item, /// I::Item /// ), /// random_unique_octuples, /// [0, 1, 2, 3, 4, 5, 6, 7] /// ); /// ``` #[macro_export] macro_rules! random_unique_tuples { ( ($($vis:tt)*), $struct: ident, $k: expr, $out_t: ty, $fn: ident, [$($i: tt),*] ) => { #[derive(Clone, Debug)] $($vis)* struct $struct where I::Item: Eq + Hash { xs: I, } impl Iterator for $struct where I::Item: Eq + Hash { type Item = $out_t; #[inline] fn next(&mut self) -> Option { let mut xs_to_indices = HashMap::with_capacity($k); let mut i = 0; while i < $k { xs_to_indices .entry(self.xs.next().unwrap()) .or_insert_with(|| { i += 1; i - 1 }); } let mut out = ($((None, $i).0),*); for (x, i) in xs_to_indices { match i { $($i => {out.$i = Some(x)},)* _ => {} } } Some(($(out.$i.unwrap()),*)) } } #[inline] $($vis)* fn $fn(xs: I) -> $struct where I::Item: Eq + Hash, { $struct { xs } } } } ================================================ FILE: malachite-base/src/unions/exhaustive.rs ================================================ // Copyright © 2026 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 crate::unions::Union2; /// Defines exhaustive union generators. /// /// Malachite provides [`lex_union2s`] and [`exhaustive_union2s`], but you can also define /// `lex_union3s`, `lex_union4s`, and so on, and `exhaustive_union3s`, `exhaustive_union4s`, and so /// on, in your program using the code below. The documentation for [`lex_union2s`] and /// [`exhaustive_union2s`] describes these other functions as well. /// /// See usage examples [here](self#lex_union2s) and [here](self#exhaustive_union2s). /// /// ``` /// use malachite_base::unions::UnionFromStrError; /// use malachite_base::{exhaustive_unions, union_struct}; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// union_struct!( /// (pub(crate)), /// Union4, /// Union4, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d] /// ); /// union_struct!( /// (pub(crate)), /// Union5, /// Union5, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e] /// ); /// union_struct!( /// (pub(crate)), /// Union6, /// Union6, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f] /// ); /// union_struct!( /// (pub(crate)), /// Union7, /// Union7, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g] /// ); /// union_struct!( /// (pub(crate)), /// Union8, /// Union8, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g], /// [H, H, 'H', h] /// ); /// /// 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] /// ); /// exhaustive_unions!( /// (pub(crate)), /// Union4, /// LexUnion4s, /// ExhaustiveUnion4s, /// lex_union4s, /// exhaustive_union4s, /// 4, /// [0, X, I, A, xs, xs_done], /// [1, Y, J, B, ys, ys_done], /// [2, Z, K, C, zs, zs_done], /// [3, W, L, D, ws, ws_done] /// ); /// exhaustive_unions!( /// (pub(crate)), /// Union5, /// LexUnion5s, /// ExhaustiveUnion5s, /// lex_union5s, /// exhaustive_union5s, /// 5, /// [0, X, I, A, xs, xs_done], /// [1, Y, J, B, ys, ys_done], /// [2, Z, K, C, zs, zs_done], /// [3, W, L, D, ws, ws_done], /// [4, V, M, E, vs, vs_done] /// ); /// exhaustive_unions!( /// (pub(crate)), /// Union6, /// LexUnion6s, /// ExhaustiveUnion6s, /// lex_union6s, /// exhaustive_union6s, /// 6, /// [0, X, I, A, xs, xs_done], /// [1, Y, J, B, ys, ys_done], /// [2, Z, K, C, zs, zs_done], /// [3, W, L, D, ws, ws_done], /// [4, V, M, E, vs, vs_done], /// [5, U, N, F, us, us_done] /// ); /// exhaustive_unions!( /// (pub(crate)), /// Union7, /// LexUnion7s, /// ExhaustiveUnion7s, /// lex_union7s, /// exhaustive_union7s, /// 7, /// [0, X, I, A, xs, xs_done], /// [1, Y, J, B, ys, ys_done], /// [2, Z, K, C, zs, zs_done], /// [3, W, L, D, ws, ws_done], /// [4, V, M, E, vs, vs_done], /// [5, U, N, F, us, us_done], /// [6, T, O, G, ts, ts_done] /// ); /// exhaustive_unions!( /// (pub(crate)), /// Union8, /// LexUnion8s, /// ExhaustiveUnion8s, /// lex_union8s, /// exhaustive_union8s, /// 8, /// [0, X, I, A, xs, xs_done], /// [1, Y, J, B, ys, ys_done], /// [2, Z, K, C, zs, zs_done], /// [3, W, L, D, ws, ws_done], /// [4, V, M, E, vs, vs_done], /// [5, U, N, F, us, us_done], /// [6, T, O, G, ts, ts_done], /// [7, S, P, H, ss, ss_done] /// ); /// ``` #[macro_export] macro_rules! exhaustive_unions { ( ($($vis:tt)*), $union: ident, $lex_struct: ident, $exhaustive_struct: ident, $lex_fn: ident, $exhaustive_fn: ident, $n: expr, $([$i: expr, $t: ident, $it: ident, $variant: ident, $xs: ident, $xs_done:ident]),* ) => { /// This documentation applies not only to `LexUnion2s`, but also to `LexUnion3s`, /// `LexUnion4s`, and so on. See [`exhaustive_unions`] for more information. /// /// Generates all $n$-unions with elements from $n$ iterators, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. All of /// the first variant's elements are generated first, followed by the second variant's /// elements, and so on. #[allow(dead_code)] #[derive(Clone, Debug)] $($vis)* struct $lex_struct<$($t, $it: Iterator),*> { i: u64, $($xs: $it,)* } impl<$($t, $it: Iterator),*> Iterator for $lex_struct<$($t, $it),*> { type Item = $union<$($t),*>; fn next(&mut self) -> Option { loop { match self.i { $( $i => { let next = self.$xs.next().map($union::$variant); if next.is_some() { return next; } }, )* _ => return None, } self.i += 1; } } } /// This documentation applies not only to `lex_union2s`, but also to `lex_union3s`, /// `lex_union4s`, and so on. See [`exhaustive_unions`] for more information. /// /// Generates all $n$-unions with elements from $n$ iterators, in lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. All of /// the first variant's elements are generated first, followed by the second variant's /// elements, and so on. This means that all of the iterators, except possibly the last one, /// must be finite. For functions that support multiple infinite element iterators, try /// `exhaustive_union[n]s`. /// /// If the last iterator is finite, the output length is the sum of the lengths of all the /// input iterators. If the last iterator is infinite, the output is also infinite. /// /// If all of the input iterators are empty, the output is also empty. /// /// # Examples /// See [here](self#lex_union2s). #[allow(dead_code)] #[inline] $($vis)* const fn $lex_fn<$($t, $it: Iterator),*>($($xs: $it),*) -> $lex_struct<$($t, $it),*> { $lex_struct { i: 0, $($xs,)* } } /// This documentation applies not only to `ExhaustiveUnion2s`, but also to /// `ExhaustiveUnion3s`, `ExhaustiveUnion4s`, and so on. See [`exhaustive_unions`] for more /// information. /// /// Generates all $n$-unions with elements from $n$ iterators. #[allow(dead_code)] #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct<$($t, $it: Iterator),*> { done: bool, i: u64, $( $xs: $it, $xs_done: bool, )* } impl<$($t, $it: Iterator),*> Iterator for $exhaustive_struct<$($t, $it),*> { type Item = $union<$($t),*>; fn next(&mut self) -> Option { if self.done { None } else { let original_i = self.i; loop { let mut next = None; match self.i { $( $i => if !self.$xs_done { next = self.$xs.next().map($union::$variant); self.$xs_done = next.is_none(); }, )* _ => unreachable!(), } self.i += 1; if self.i == $n { self.i = 0; } if next.is_some() { return next; } if self.i == original_i { self.done = true; return None; } } } } } /// This documentation applies not only to `exhaustive_union2s`, but also to /// `exhaustive_union3s`, `exhaustive_union4s`, and so on. See [`exhaustive_unions`] for /// more information. /// /// Generates all $n$-unions with elements from $n$ iterators. /// /// The input iterators are advanced in a round-robin fashion. First an element from the /// first variant's iterator is selected, followed by an element from the second variant's /// iterator, and so on until an element has been selected from each iterator. Then another /// element from the first iterator is selected, etc. Iterators that have been exhausted are /// skipped. [`exhaustive_union2s`] behaves just like /// [`Itertools::interleave`]([`itertools::Itertools::interleave`]). /// /// If all input iterators are finite, the output length is the sum of the lengths of the /// iterators. If any iterator is infinite, the output is also infinite. /// /// If all of the input iterators are empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_union2s). #[allow(dead_code)] #[inline] $($vis)* const fn $exhaustive_fn<$($t, $it: Iterator),*>($($xs: $it),*) -> $exhaustive_struct<$($t, $it),*> { $exhaustive_struct { done: false, i: 0, $( $xs, $xs_done: false, )* } } } } exhaustive_unions!( (pub), Union2, LexUnion2s, ExhaustiveUnion2s, lex_union2s, exhaustive_union2s, 2, [0, X, I, A, xs, xs_done], [1, Y, J, B, ys, ys_done] ); ================================================ FILE: malachite-base/src/unions/mod.rs ================================================ // Copyright © 2026 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 alloc::string::String; use alloc::string::ToString; use core::fmt::{self, Display, Formatter}; use core::str::FromStr; /// This is the error type for the unions' [`FromStr`] implementations. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum UnionFromStrError { /// For when the union's variant can't be determined. Generic(String), /// For when the union's variant can be determined but the wrapped value can't be parsed. Specific(E), } /// Defines unions. /// /// Malachite provides [`Union2`], but you can also define `Union3`, `Union4`, and so on, in your /// program using the code below. The documentation for [`Union2`] and describes these other `enum`s /// as well. /// /// ``` /// use malachite_base::union_struct; /// use malachite_base::unions::UnionFromStrError; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// union_struct!( /// (pub(crate)), /// Union4, /// Union4, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d] /// ); /// union_struct!( /// (pub(crate)), /// Union5, /// Union5, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e] /// ); /// union_struct!( /// (pub(crate)), /// Union6, /// Union6, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f] /// ); /// union_struct!( /// (pub(crate)), /// Union7, /// Union7, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g] /// ); /// union_struct!( /// (pub(crate)), /// Union8, /// Union8, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g], /// [H, H, 'H', h] /// ); /// ``` #[macro_export] macro_rules! union_struct { ( ($($vis:tt)*), $name: ident, $single: ty, $([$t: ident, $cons: ident, $c: expr, $x: ident]),* ) => { #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] /// This is a union, or sum type, of $n$ values. It is essentially a generic enum. $($vis)* enum $name<$($t),*> { $($cons($t)),* } impl $single { /// Given a union whose variants all have the same type, unwraps it into a value of that /// type. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](self#unwrap). #[allow(clippy::missing_const_for_fn)] // Can't be const because of destructor $($vis)* fn unwrap(self) -> T { match self { $( $name::$cons($x) => $x ),* } } } impl<$($t: Display),*> Display for $name<$($t),*> { /// Converts a union to a [`String`]. /// /// # Examples /// See [here](self#fmt). #[inline] fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { $( $name::$cons($x) => f.write_fmt(format_args!("{}({})", $c, $x)) ),* } } } impl<$($t: FromStr),*> FromStr for $name<$($t),*> { type Err = UnionFromStrError<$name<$($t::Err),*>>; /// Converts a string to a union. /// /// If the string does not represent a valid union, an error value is returned. /// /// # Examples /// See [here](self#from_str). #[inline] fn from_str(src: &str) -> Result<$name<$($t),*>, Self::Err> { if src.is_empty() { return Err(UnionFromStrError::Generic(String::new())); } let (head, tail) = src.split_at(1); let tail = if let Some(tail) = tail.strip_prefix('(') { tail } else { return Err(UnionFromStrError::Generic(src.to_string())); }; let tail = if let Some(tail) = tail.strip_suffix(')') { tail } else { return Err(UnionFromStrError::Generic(src.to_string())); }; match head.chars().next().unwrap() { $( $c => $t::from_str(tail) .map($name::$cons) .map_err(|e| UnionFromStrError::Specific($name::$cons(e))), )* _ => Err(UnionFromStrError::Generic(src.to_string())) } } } } } union_struct!((pub), Union2, Union2, [A, A, 'A', a], [B, B, 'B', b]); /// Iterators that generate unions without repetition. /// /// # lex_union2s /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::unions::exhaustive::lex_union2s; /// use malachite_base::unions::Union2; /// /// let u2s = lex_union2s(exhaustive_bools(), 0..4).collect_vec(); /// assert_eq!( /// u2s.as_slice(), /// &[ /// Union2::A(false), /// Union2::A(true), /// Union2::B(0), /// Union2::B(1), /// Union2::B(2), /// Union2::B(3) /// ] /// ); /// ``` /// /// # exhaustive_union2s /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::unions::exhaustive::exhaustive_union2s; /// use malachite_base::unions::Union2; /// /// let u2s = exhaustive_union2s(exhaustive_bools(), 0..4).collect_vec(); /// assert_eq!( /// u2s.as_slice(), /// &[ /// Union2::A(false), /// Union2::B(0), /// Union2::A(true), /// Union2::B(1), /// Union2::B(2), /// Union2::B(3) /// ] /// ); /// ``` pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate unions randomly. /// /// # random_union2s /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::unions::random::random_union2s; /// use malachite_base::unions::Union2; /// /// let us = random_union2s( /// EXAMPLE_SEED, /// &|seed| random_char_inclusive_range(seed, 'a', 'z'), /// &|seed| random_unsigned_inclusive_range::(seed, 1, 10), /// ); /// assert_eq!( /// us.take(20).collect_vec().as_slice(), /// &[ /// Union2::A('v'), /// Union2::B(3), /// Union2::A('c'), /// Union2::A('q'), /// Union2::A('i'), /// Union2::A('e'), /// Union2::A('p'), /// Union2::A('g'), /// Union2::A('s'), /// Union2::B(7), /// Union2::A('n'), /// Union2::A('t'), /// Union2::B(9), /// Union2::A('m'), /// Union2::A('z'), /// Union2::B(7), /// Union2::B(9), /// Union2::A('o'), /// Union2::A('m'), /// Union2::B(3), /// ], /// ); /// ``` pub mod random; ================================================ FILE: malachite-base/src/unions/random.rs ================================================ // Copyright © 2026 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 crate::num::random::{RandomUnsignedRange, random_unsigned_range}; use crate::random::Seed; use crate::unions::Union2; /// Defines random union generators. /// /// Malachite provides [`random_union2s`], but you can also define `random_union3s`, /// `random_union4s`, and so on, in your program using the code below. The documentation for /// [`random_union2s`] describes these other functions as well. /// /// See usage examples [here](self#random_union2s). /// /// ``` /// use malachite_base::num::random::{random_unsigned_range, RandomUnsignedRange}; /// use malachite_base::random::Seed; /// use malachite_base::unions::UnionFromStrError; /// use malachite_base::{random_unions, union_struct}; /// use std::fmt::{self, Display, Formatter}; /// use std::str::FromStr; /// /// union_struct!( /// (pub(crate)), /// Union3, /// Union3, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c] /// ); /// union_struct!( /// (pub(crate)), /// Union4, /// Union4, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d] /// ); /// union_struct!( /// (pub(crate)), /// Union5, /// Union5, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e] /// ); /// union_struct!( /// (pub(crate)), /// Union6, /// Union6, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f] /// ); /// union_struct!( /// (pub(crate)), /// Union7, /// Union7, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g] /// ); /// union_struct!( /// (pub(crate)), /// Union8, /// Union8, /// [A, A, 'A', a], /// [B, B, 'B', b], /// [C, C, 'C', c], /// [D, D, 'D', d], /// [E, E, 'E', e], /// [F, F, 'F', f], /// [G, G, 'G', g], /// [H, H, 'H', h] /// ); /// /// 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] /// ); /// random_unions!( /// (pub(crate)), /// Union4, /// RandomUnion4s, /// random_union4s, /// 4, /// [0, X, I, A, xs, xs_gen], /// [1, Y, J, B, ys, ys_gen], /// [2, Z, K, C, zs, zs_gen], /// [3, W, L, D, ws, ws_gen] /// ); /// random_unions!( /// (pub(crate)), /// Union5, /// RandomUnion5s, /// random_union5s, /// 5, /// [0, X, I, A, xs, xs_gen], /// [1, Y, J, B, ys, ys_gen], /// [2, Z, K, C, zs, zs_gen], /// [3, W, L, D, ws, ws_gen], /// [4, V, M, E, vs, vs_gen] /// ); /// random_unions!( /// (pub(crate)), /// Union6, /// RandomUnion6s, /// random_union6s, /// 6, /// [0, X, I, A, xs, xs_gen], /// [1, Y, J, B, ys, ys_gen], /// [2, Z, K, C, zs, zs_gen], /// [3, W, L, D, ws, ws_gen], /// [4, V, M, E, vs, vs_gen], /// [5, U, N, F, us, us_gen] /// ); /// random_unions!( /// (pub(crate)), /// Union7, /// RandomUnion7s, /// random_union7s, /// 7, /// [0, X, I, A, xs, xs_gen], /// [1, Y, J, B, ys, ys_gen], /// [2, Z, K, C, zs, zs_gen], /// [3, W, L, D, ws, ws_gen], /// [4, V, M, E, vs, vs_gen], /// [5, U, N, F, us, us_gen], /// [6, T, O, G, ts, ts_gen] /// ); /// random_unions!( /// (pub(crate)), /// Union8, /// RandomUnion8s, /// random_union8s, /// 8, /// [0, X, I, A, xs, xs_gen], /// [1, Y, J, B, ys, ys_gen], /// [2, Z, K, C, zs, zs_gen], /// [3, W, L, D, ws, ws_gen], /// [4, V, M, E, vs, vs_gen], /// [5, U, N, F, us, us_gen], /// [6, T, O, G, ts, ts_gen], /// [7, S, P, H, ss, ss_gen] /// ); /// ``` #[macro_export] macro_rules! random_unions { ( ($($vis:tt)*), $union: ident, $random_struct: ident, $random_fn: ident, $n: expr, $([$i: expr, $t: ident, $it: ident, $variant: ident, $xs: ident, $xs_gen: ident]),* ) => { /// This documentation applies not only to `RandomUnion2s`, but also to `RandomUnion3s`, /// `RandomUnion4s`, and so on. See [`random_unions`] for more information. /// /// Generates random $n$-unions with elements from $n$ iterators. #[derive(Clone, Debug)] $($vis)* struct $random_struct<$($t, $it: Iterator),*> { indices: RandomUnsignedRange, $($xs: $it,)* } impl<$($t, $it: Iterator),*> Iterator for $random_struct<$($t, $it),*> { type Item = $union<$($t),*>; fn next(&mut self) -> Option { match self.indices.next().unwrap() { $($i => self.$xs.next().map($union::$variant),)* _ => unreachable!(), } } } /// This documentation applies not only to `random_union2s`, but also to `random_union3s`, /// `random_union4s`, and so on. See [`random_unions`] for more information. /// /// Generates random $n$-unions with elements from $n$ iterators. /// /// The probability of a particular $n$-union being generated is the probability of its /// element divided by $n$. /// /// `xs`, `ys`, `zs`, ... must be infinite. /// /// # Examples /// See [here](self#random_union2s). $($vis)* fn $random_fn<$($t, $it: Iterator),*>( seed: Seed, $($xs_gen: &dyn Fn(Seed) -> $it),* ) -> $random_struct<$($t, $it),*> { $random_struct { indices: random_unsigned_range(seed.fork("indices"), 0, $n), $($xs: $xs_gen(seed.fork(stringify!($xs))),)* } } } } random_unions!( (pub), Union2, RandomUnion2s, random_union2s, 2, [0, X, I, A, xs, xs_gen], [1, Y, J, B, ys, ys_gen] ); ================================================ FILE: malachite-base/src/vecs/exhaustive.rs ================================================ // Copyright © 2026 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 crate::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; use crate::iterators::iterator_cache::IteratorCache; use crate::num::arithmetic::traits::CheckedPow; use crate::num::conversion::traits::{ExactFrom, SaturatingFrom, WrappingFrom}; use crate::num::exhaustive::{ PrimitiveIntIncreasingRange, exhaustive_unsigneds, primitive_int_increasing_inclusive_range, primitive_int_increasing_range, }; use crate::num::iterators::{RulerSequence, ruler_sequence}; use crate::num::logic::traits::SignificantBits; use crate::tuples::exhaustive::{ ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, LexDependentPairs, exhaustive_dependent_pairs, exhaustive_dependent_pairs_stop_after_empty_ys, lex_dependent_pairs_stop_after_empty_ys, }; use crate::vecs::{ExhaustiveVecPermutations, exhaustive_vec_permutations}; use alloc::vec; use alloc::vec::Vec; use core::cmp::{ Ordering::{self, *}, max, min, }; use core::iter::{FromIterator, Once, Zip, empty, once}; use core::marker::PhantomData; use core::mem::take; use core::ops::RangeFrom; use itertools::{Itertools, repeat_n}; #[doc(hidden)] pub fn validate_oi_map>(max_input_index: usize, xs: I) { let mut oi_unique = hashbrown::HashSet::new(); oi_unique.extend(xs); let oi_sorted_unique = oi_unique.into_iter().sorted().collect_vec(); assert_eq!(oi_sorted_unique.len(), max_input_index + 1); assert_eq!(*oi_sorted_unique.first().unwrap(), 0); assert_eq!(*oi_sorted_unique.last().unwrap(), max_input_index); } #[doc(hidden)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct LexFixedLengthVecsOutput { pub input_index: usize, pub counter: usize, } /// Defines lexicographic fixed-length [`Vec`] generators. /// /// Malachite provides [`lex_vecs_length_2`] and [`lex_vecs_fixed_length_2_inputs`], but you can /// also define `lex_vecs_length_3`, `lex_vecs_length_4`, and so on, and /// `lex_vecs_fixed_length_3_inputs`, `lex_vecs_fixed_length_4_inputs`, and so on, in your program /// using the code below. The documentation for [`lex_vecs_length_2`] and /// [`lex_vecs_fixed_length_2_inputs`] describes these other functions as well. /// /// See usage examples [here](self#lex_vecs_length_2) and /// [here](self#lex_vecs_fixed_length_2_inputs). /// /// ``` /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::lex_vecs_fixed_length; /// use malachite_base::vecs::exhaustive::{validate_oi_map, LexFixedLengthVecsOutput}; /// /// 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] /// ); /// lex_vecs_fixed_length!( /// (pub(crate)), /// LexFixedLengthVecs4Inputs, /// lex_vecs_fixed_length_4_inputs, /// lex_vecs_length_4, /// [0, I, xs, xs_outputs], /// [1, J, ys, ys_outputs], /// [2, K, zs, zs_outputs], /// [3, L, ws, ws_outputs] /// ); /// lex_vecs_fixed_length!( /// (pub(crate)), /// LexFixedLengthVecs5Inputs, /// lex_vecs_fixed_length_5_inputs, /// lex_vecs_length_5, /// [0, I, xs, xs_outputs], /// [1, J, ys, ys_outputs], /// [2, K, zs, zs_outputs], /// [3, L, ws, ws_outputs], /// [4, M, vs, vs_outputs] /// ); /// lex_vecs_fixed_length!( /// (pub(crate)), /// LexFixedLengthVecs6Inputs, /// lex_vecs_fixed_length_6_inputs, /// lex_vecs_length_6, /// [0, I, xs, xs_outputs], /// [1, J, ys, ys_outputs], /// [2, K, zs, zs_outputs], /// [3, L, ws, ws_outputs], /// [4, M, vs, vs_outputs], /// [5, N, us, us_outputs] /// ); /// lex_vecs_fixed_length!( /// (pub(crate)), /// LexFixedLengthVecs7Inputs, /// lex_vecs_fixed_length_7_inputs, /// lex_vecs_length_7, /// [0, I, xs, xs_outputs], /// [1, J, ys, ys_outputs], /// [2, K, zs, zs_outputs], /// [3, L, ws, ws_outputs], /// [4, M, vs, vs_outputs], /// [5, N, us, us_outputs], /// [6, O, ts, ts_outputs] /// ); /// lex_vecs_fixed_length!( /// (pub(crate)), /// LexFixedLengthVecs8Inputs, /// lex_vecs_fixed_length_8_inputs, /// lex_vecs_length_8, /// [0, I, xs, xs_outputs], /// [1, J, ys, ys_outputs], /// [2, K, zs, zs_outputs], /// [3, L, ws, ws_outputs], /// [4, M, vs, vs_outputs], /// [5, N, us, us_outputs], /// [6, O, ts, ts_outputs], /// [7, P, ss, ss_outputs] /// ); /// ``` #[macro_export] macro_rules! lex_vecs_fixed_length { ( ($($vis:tt)*), $exhaustive_struct: ident, $exhaustive_custom_fn: ident, $exhaustive_1_to_1_fn: ident, $([$i: expr, $it: ident, $xs: ident, $xs_outputs: ident]),* ) => { /// This documentation applies not only to `LexFixedLengthVecs2Inputs`, but also to /// `LexFixedLengthVecs3Inputs`, `LexFixedLengthVecs4Inputs`, and so on. See /// [`lex_vecs_fixed_length`] for more information. /// /// Generates all [`Vec`]s of a given length with elements from $m$ iterators, in /// lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. /// /// The fixed length $n$ of the [`Vec`]s is greater than or equal to $m$. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct,)*> { first: bool, done: bool, $( $xs: IteratorCache<$it>, $xs_outputs: Vec, )* outputs: Vec, } impl,)*> $exhaustive_struct { fn increment_counters(&mut self) -> bool { for (i, output) in self.outputs.iter_mut().enumerate().rev() { output.counter += 1; let no_carry = match output.input_index { $( $i => self.$xs.get(output.counter).is_some(), )* _ => unreachable!(), }; if no_carry { return false; } else if i == 0 { return true; } output.counter = 0; } false } } impl,)*> Iterator for $exhaustive_struct { type Item = Vec; fn next(&mut self) -> Option> { if self.done { None } else if self.first { self.first = false; let mut next = vec![None; self.outputs.len()]; $( if let Some(x) = self.$xs.get(0) { for &output_index in &self.$xs_outputs { next[output_index] = Some(x.clone()); } } else { self.done = true; return None; } )* Some(next.into_iter().map(Option::unwrap).collect()) } else { if self.increment_counters() { self.done = true; return None; } let mut next = Vec::with_capacity(self.outputs.len()); for &output in &self.outputs { let x = match output.input_index { $( $i => self.$xs.get(output.counter), )* _ => unreachable!(), }; next.push(x.unwrap().clone()); } Some(next) } } } /// This documentation applies not only to `lex_vecs_fixed_length_2_inputs`, but also to /// `lex_vecs_fixed_length_3_inputs`, `lex_vecs_fixed_length_4_inputs`, and so on. See /// [`lex_vecs_fixed_length`] for more information. /// /// Generates all length-$n$ [`Vec`]s with elements from $m$ iterators, where $m \leq n$, in /// lexicographic order. /// /// The order is lexicographic with respect to the order of the element iterators. /// /// The `output_to_input_map` parameter defines which iterators are mapped to which slot in /// the output [`Vec`]s. The length of the output [`Vec`]s, $n$, is specified by the length /// of `output_to_input_map`. /// /// The $i$th element of `output_to_input_map` is an index from 0 to $m-1$ which specifies /// which iterator the $i$th output slot is populated with. Together, the elements must /// include all indices from 0 to $m-1$, inclusive, possibly with repetitions. /// /// Let `xs` be the input iterator mapped to the first slot of the output [`Vec`]s. All the /// input iterators, except possibly `xs`, must be finite. If `xs` is finite, the output /// length is the product of the lengths of all the input iterators. If `xs` is infinite, /// the output is also infinite. /// /// If any of the input iterators is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_vecs_fixed_length_2_inputs). #[allow(dead_code)] $($vis)* fn $exhaustive_custom_fn,)*>( $($xs: $it,)* output_to_input_map: &[usize], ) -> $exhaustive_struct { $( let _max_input_index = $i; )* validate_oi_map(_max_input_index, output_to_input_map.iter().cloned()); $( let $xs_outputs = output_to_input_map .iter() .enumerate() .filter_map(|(o, i)| if *i == $i { Some(o) } else { None }) .collect(); )* $exhaustive_struct { first: true, done: false, $( $xs: IteratorCache::new($xs), $xs_outputs, )* outputs: output_to_input_map .iter() .map(|&i| LexFixedLengthVecsOutput { input_index: i, counter: 0, }) .collect(), } } /// This documentation applies not only to `lex_vecs_length_2`, but also to /// `lex_vecs_length_3`, `lex_vecs_length_4`, and so on. See [`lex_vecs_fixed_length`] for /// more information. /// /// Generates all length-$n$ [`Vec`]s with elements from $n$ iterators, in lexicographic /// order. /// /// The order is lexicographic with respect to the order of the element iterators. /// /// All of `ys`, `zs`, ... (but not necessarily `xs`) must be finite. If `xs` is finite, the /// output length is the product of the lengths of all the input iterators. If `xs` is /// infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Examples /// See [here](self#lex_vecs_length_2). #[allow(dead_code)] #[inline] $($vis)* fn $exhaustive_1_to_1_fn,)*>( $($xs: $it,)* ) -> $exhaustive_struct { $exhaustive_custom_fn($($xs,)* &[$($i,)*]) } } } lex_vecs_fixed_length!( (pub), LexFixedLengthVecs2Inputs, lex_vecs_fixed_length_2_inputs, lex_vecs_length_2, [0, I, xs, xs_outputs], [1, J, ys, ys_outputs] ); #[doc(hidden)] #[derive(Clone, Debug)] pub struct LexFixedLengthVecsFromSingleG where I::Item: Clone, { first: bool, done: bool, xs: IteratorCache, counters: Vec, phantom: PhantomData<*const I::Item>, } impl LexFixedLengthVecsFromSingleG where I::Item: Clone, { fn increment_counters(&mut self) -> bool { for (i, counter) in self.counters.iter_mut().enumerate().rev() { *counter += 1; if self.xs.get(*counter).is_some() { return false; } else if i == 0 { return true; } *counter = 0; } false } } impl Iterator for LexFixedLengthVecsFromSingleG where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { if self.done { None } else if self.first { self.first = false; if let Some(x) = self.xs.get(0) { Some(repeat_n(x, self.counters.len()).cloned().collect()) } else { self.done = true; None } } else if self.increment_counters() { self.done = true; None } else { let xs = &mut self.xs; Some( self.counters .iter() .map(|&c| xs.get(c).unwrap().clone()) .collect(), ) } } } fn lex_vecs_fixed_length_from_single_g( len: u64, xs: I, ) -> LexFixedLengthVecsFromSingleG where I::Item: Clone, { LexFixedLengthVecsFromSingleG { first: true, done: false, xs: IteratorCache::new(xs), counters: vec![0; usize::exact_from(len)], phantom: PhantomData, } } /// Generates all [`Vec`]s of a given length with elements from a single iterator, in lexicographic /// order. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// This `struct` is created by the [`lex_vecs_fixed_length_from_single`]; see its documentation for /// more. #[derive(Clone, Debug)] pub enum LexFixedLengthVecsFromSingle where I::Item: Clone, { Zero(Once>), One(I), GreaterThanOne(LexFixedLengthVecsFromSingleG), } impl Iterator for LexFixedLengthVecsFromSingle where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { match self { Self::Zero(xs) => xs.next(), Self::One(xs) => xs.next().map(|x| vec![x]), Self::GreaterThanOne(xs) => xs.next(), } } } /// Generates all [`Vec`]s of a given length with elements from a single iterator, in lexicographic /// order. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// `xs` must be finite. /// /// The output length is $k^n$, where $k$ is `xs.count()` and $n$ is `len`. /// /// If `len` is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless `len` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_vecs_fixed_length_from_single; /// /// let xss = lex_vecs_fixed_length_from_single(2, 0..4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[0, 0], /// &[0, 1], /// &[0, 2], /// &[0, 3], /// &[1, 0], /// &[1, 1], /// &[1, 2], /// &[1, 3], /// &[2, 0], /// &[2, 1], /// &[2, 2], /// &[2, 3], /// &[3, 0], /// &[3, 1], /// &[3, 2], /// &[3, 3] /// ] /// ); /// ``` pub fn lex_vecs_fixed_length_from_single( len: u64, xs: I, ) -> LexFixedLengthVecsFromSingle where I::Item: Clone, { match len { 0 => LexFixedLengthVecsFromSingle::Zero(once(Vec::new())), 1 => LexFixedLengthVecsFromSingle::One(xs), len => LexFixedLengthVecsFromSingle::GreaterThanOne(lex_vecs_fixed_length_from_single_g( len, xs, )), } } /// Defines exhaustive fixed-length [`Vec`] generators. /// /// Malachite provides [`exhaustive_vecs_length_2`] and [`exhaustive_vecs_fixed_length_2_inputs`], /// but you can also define `exhaustive_vecs_length_3`, `exhaustive_vecs_length_4`, and so on, and /// `exhaustive_vecs_fixed_length_3_inputs`, `exhaustive_vecs_fixed_length_4_inputs`, and so on, in /// your program using the code below. The documentation for [`exhaustive_vecs_length_2`] and /// [`exhaustive_vecs_fixed_length_2_inputs`] describes these other functions as well. /// /// See usage examples [here](self#exhaustive_vecs_length_2) and /// [here](self#exhaustive_vecs_fixed_length_2_inputs). /// /// ``` /// use itertools::Itertools; /// use malachite_base::exhaustive_vecs_fixed_length; /// use malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; /// use malachite_base::iterators::iterator_cache::IteratorCache; /// use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; /// use malachite_base::num::logic::traits::SignificantBits; /// use malachite_base::vecs::exhaustive::validate_oi_map; /// use std::cmp::max; /// /// 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] /// ); /// exhaustive_vecs_fixed_length!( /// (pub(crate)), /// ExhaustiveFixedLengthVecs4Inputs, /// exhaustive_vecs_fixed_length_4_inputs, /// exhaustive_vecs_length_4, /// [0, I, xs, xs_done, xs_outputs], /// [1, J, ys, ys_done, ys_outputs], /// [2, K, zs, zs_done, zs_outputs], /// [3, L, ws, ws_done, ws_outputs] /// ); /// exhaustive_vecs_fixed_length!( /// (pub(crate)), /// ExhaustiveFixedLengthVecs5Inputs, /// exhaustive_vecs_fixed_length_5_inputs, /// exhaustive_vecs_length_5, /// [0, I, xs, xs_done, xs_outputs], /// [1, J, ys, ys_done, ys_outputs], /// [2, K, zs, zs_done, zs_outputs], /// [3, L, ws, ws_done, ws_outputs], /// [4, M, vs, vs_done, vs_outputs] /// ); /// exhaustive_vecs_fixed_length!( /// (pub(crate)), /// ExhaustiveFixedLengthVecs6Inputs, /// exhaustive_vecs_fixed_length_6_inputs, /// exhaustive_vecs_length_6, /// [0, I, xs, xs_done, xs_outputs], /// [1, J, ys, ys_done, ys_outputs], /// [2, K, zs, zs_done, zs_outputs], /// [3, L, ws, ws_done, ws_outputs], /// [4, M, vs, vs_done, vs_outputs], /// [5, N, us, us_done, us_outputs] /// ); /// exhaustive_vecs_fixed_length!( /// (pub(crate)), /// ExhaustiveFixedLengthVecs7, /// exhaustive_vecs_fixed_length_7_inputs, /// exhaustive_vecs_length_7, /// [0, I, xs, xs_done, xs_outputs], /// [1, J, ys, ys_done, ys_outputs], /// [2, K, zs, zs_done, zs_outputs], /// [3, L, ws, ws_done, ws_outputs], /// [4, M, vs, vs_done, vs_outputs], /// [5, N, us, us_done, us_outputs], /// [6, O, ts, ts_done, ts_outputs] /// ); /// exhaustive_vecs_fixed_length!( /// (pub(crate)), /// ExhaustiveFixedLengthVecs8Inputs, /// exhaustive_vecs_fixed_length_8_inputs, /// exhaustive_vecs_length_8, /// [0, I, xs, xs_done, xs_outputs], /// [1, J, ys, ys_done, ys_outputs], /// [2, K, zs, zs_done, zs_outputs], /// [3, L, ws, ws_done, ws_outputs], /// [4, M, vs, vs_done, vs_outputs], /// [5, N, us, us_done, us_outputs], /// [6, O, ts, ts_done, ts_outputs], /// [7, P, ss, ss_done, ss_outputs] /// ); /// ``` #[macro_export] macro_rules! exhaustive_vecs_fixed_length { ( ($($vis:tt)*), $exhaustive_struct: ident, $exhaustive_custom_fn: ident, $exhaustive_1_to_1_fn: ident, $([$i: expr, $it: ident, $xs: ident, $xs_done: ident, $outputs: ident]),* ) => { /// This documentation applies not only to `ExhaustiveFixedLengthVecs2Inputs`, but also to /// `ExhaustiveFixedLengthVecs3Inputs`, `ExhaustiveFixedLengthVecs4Inputs`, and so on. See /// [`exhaustive_vecs_fixed_length`] for more information. /// /// Generates all [`Vec`]s of a given length with elements from $m$ iterators. /// /// The fixed length $n$ of the [`Vec`]s is greater than or equal to $m$. #[derive(Clone, Debug)] $($vis)* struct $exhaustive_struct,)*> { i: u64, len: u64, limit: Option, distributor: BitDistributor, $( $xs: IteratorCache<$it>, $xs_done: bool, $outputs: Vec, )* } impl,)*> $exhaustive_struct { fn try_getting_limit(&mut self) { let mut all_limits_known = true; $( if let Some(xs_len) = self.$xs.known_len() { if xs_len == 0 { self.limit = Some(0); return; } } else { all_limits_known = false; } )* if !all_limits_known { return; } let mut product = 1u64; $( let xs_len = u64::exact_from(self.$xs.known_len().unwrap()); for _ in 0..self.$outputs.len() { if let Some(new_product) = product.checked_mul(xs_len) { product = new_product; } else { return; } } )* self.limit = Some(product); } } impl,)*> Iterator for $exhaustive_struct { type Item = Vec; fn next(&mut self) -> Option> { if Some(self.i) == self.limit { None } else { if self.i == u64::MAX { panic!("Too many iterations"); } loop { let mut all_are_valid = true; $( for &output_index in &self.$outputs { if self.$xs.get( self.distributor.get_output(output_index) ).is_none() { all_are_valid = false; break; } } if !all_are_valid { if self.i == 0 { self.limit = Some(0); return None; } else if !self.$xs_done { self.try_getting_limit(); if Some(self.i) == self.limit { return None; } self.$xs_done = true; let xs_len = self.$xs.known_len().unwrap(); // xs_len > 0 at this point self.distributor.set_max_bits( &self.$outputs, max( 1, usize::wrapping_from((xs_len - 1).significant_bits()) ) ); } else { self.distributor.increment_counter(); } continue; } )* break; } let mut out = vec![None; usize::exact_from(self.len)]; $( for &output_index in &self.$outputs { let x = self.$xs.get(self.distributor.get_output(output_index)); out[output_index] = Some(x.unwrap().clone()); } )* self.i += 1; self.distributor.increment_counter(); Some(out.into_iter().map(Option::unwrap).collect()) } } } /// This documentation applies not only to `exhaustive_vecs_fixed_length_2_inputs`, but also /// to `exhaustive_vecs_fixed_length_3_inputs`, `exhaustive_vecs_fixed_length_4_inputs`, and /// so on. See [`exhaustive_vecs_fixed_length`] for more information. /// /// Generates all [`Vec`]s of a given length with elements from $m$ iterators, where $m \leq /// n$. /// /// The `output_types` parameter defines which iterators are mapped to which slot in the /// output [`Vec`]s, and how quickly each output slot advances through its iterator. The /// length of the output [`Vec`]s, $n$, is specified by the length of `output_types`. /// /// The $i$th element of `output_types` is a pair of [`BitDistributorOutputType`] and /// `usize`. The [`BitDistributorOutputType`] determines how quickly the $i$th output slot /// advances through its iterator; see the [`BitDistributor`] documentation for a /// description of the different types. The `usize` is an index from 0 to $m-1$ which /// specifies which iterator the $i$th output slot is populated with. Together, the `usize`s /// must include all indices from 0 to $m-1$, inclusive, possibly with repetitions. /// /// If all of `xs`, `ys`, `zs`, ... are finite, the output length is the product of their /// lengths. If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Panics /// Panics if the `usize`s in `output_types` do not include all indices from 0 to $m-1$, /// inclusive, possibly with repetitions. In particular, the length of `output_types` must /// be at least $m$. /// /// # Examples /// See [here](self#exhaustive_vecs_fixed_length_2_inputs). #[allow(dead_code)] $($vis)* fn $exhaustive_custom_fn,)*> ( $($xs: $it,)* output_types: &[(BitDistributorOutputType, usize)], ) -> $exhaustive_struct { $( let _max_input_index = $i; )* let output_to_input_map = output_types.iter().map(|(_, i)| *i).collect_vec(); validate_oi_map(_max_input_index, output_to_input_map.iter().cloned()); $exhaustive_struct { i: 0, len: u64::exact_from(output_types.len()), limit: None, distributor: BitDistributor::new(output_types.iter().map(|(ot, _)| *ot) .collect_vec().as_slice()), $( $xs: IteratorCache::new($xs), $xs_done: false, $outputs: output_types.iter().enumerate() .filter_map(|(o, (_, i))| if *i == $i { Some(o) } else { None }).collect(), )* } } /// This documentation applies not only to `exhaustive_vecs_length_2`, but also to /// `exhaustive_vecs_length_3`, `exhaustive_vecs_length_4`, and so on. See /// [`exhaustive_vecs_fixed_length`] for more information. /// /// Generates all length-$n$ [`Vec`]s with elements from $n$ iterators. /// /// If all of `xs`, `ys`, `zs`, ... are finite, the output length is the product of their /// lengths. If any of `xs`, `ys`, `zs`, ... are infinite, the output is also infinite. /// /// If any of `xs`, `ys`, `zs`, ... is empty, the output is also empty. /// /// # Examples /// See [here](self#exhaustive_vecs_length_2). #[allow(dead_code)] #[inline] $($vis)* fn $exhaustive_1_to_1_fn,)*> ( $($xs: $it,)* ) -> $exhaustive_struct { $exhaustive_custom_fn( $($xs,)* &[$((BitDistributorOutputType::normal(1), $i),)*] ) } } } exhaustive_vecs_fixed_length!( (pub), ExhaustiveFixedLengthVecs2Inputs, exhaustive_vecs_fixed_length_2_inputs, exhaustive_vecs_length_2, [0, I, xs, xs_done, xs_outputs], [1, J, ys, ys_done, ys_outputs] ); #[doc(hidden)] #[derive(Clone, Debug)] pub struct ExhaustiveFixedLengthVecs1InputG where I::Item: Clone, { i: u64, len: u64, limit: Option, distributor: BitDistributor, xs: IteratorCache, xs_done: bool, phantom: PhantomData<*const I::Item>, } impl Iterator for ExhaustiveFixedLengthVecs1InputG where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { if Some(self.i) == self.limit { None } else { assert!(self.i != u64::MAX, "Too many iterations"); loop { let mut all_are_valid = true; for i in 0..usize::exact_from(self.len) { if self.xs.get(self.distributor.get_output(i)).is_none() { all_are_valid = false; break; } } if all_are_valid { break; } else if !self.xs_done { let xs_len = self.xs.known_len().unwrap(); self.limit = CheckedPow::checked_pow(u64::exact_from(xs_len), self.len); if Some(self.i) == self.limit { return None; } self.xs_done = true; // xs_len > 0 at this point self.distributor.set_max_bits( &[0], max(1, usize::wrapping_from((xs_len - 1).significant_bits())), ); } else { self.distributor.increment_counter(); } } let out = (0..usize::exact_from(self.len)) .map(|i| self.xs.get(self.distributor.get_output(i)).unwrap().clone()) .collect(); self.i += 1; self.distributor.increment_counter(); Some(out) } } } fn exhaustive_vecs_fixed_length_1_input_g( xs: I, output_types: &[BitDistributorOutputType], ) -> ExhaustiveFixedLengthVecs1InputG where I::Item: Clone, { ExhaustiveFixedLengthVecs1InputG { i: 0, len: u64::exact_from(output_types.len()), limit: None, distributor: BitDistributor::new(output_types), xs: IteratorCache::new(xs), xs_done: false, phantom: PhantomData, } } /// Generates all [`Vec`]s of a given length with elements from a single iterator. /// /// This `struct` is created by [`exhaustive_vecs_fixed_length_from_single`]; see its documentation /// for more. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum ExhaustiveFixedLengthVecs1Input where I::Item: Clone, { Zero(Once>), One(I), GreaterThanOne(ExhaustiveFixedLengthVecs1InputG), } impl Iterator for ExhaustiveFixedLengthVecs1Input where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { match self { Self::Zero(xs) => xs.next(), Self::One(xs) => xs.next().map(|x| vec![x]), Self::GreaterThanOne(xs) => xs.next(), } } } /// Generates all length-$n$ [`Vec`]s with elements from a single iterator. /// /// This function differs from [`exhaustive_vecs_fixed_length_from_single`] in that different /// [`BitDistributorOutputType`]s may be specified for each output element. /// /// The $i$th element of `output_types` is a [`BitDistributorOutputType`] that determines how /// quickly the $i$th output slot advances through the iterator; see the [`BitDistributor`] /// documentation for a description of the different types. The length of the output [`Vec`]s, $n$, /// is specified by the length of `output_types`. /// /// If `xs` is finite, the output length is $k^n$, where $k$ is `xs.count()` and $n$ is `len`. If /// `xs` is infinite, the output is also infinite. /// /// If `len` is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless `len` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::iterators::bit_distributor::BitDistributorOutputType; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_fixed_length_1_input; /// /// // We are generating length-3 [`Vec`]s of chars using one input iterator, which produces all /// // ASCII chars. The third element has a tiny output type, so it will grow more slowly than the /// // other two elements (though it doesn't look that way from the first few [`Vec`]s). /// let xss = exhaustive_vecs_fixed_length_1_input( /// exhaustive_ascii_chars(), /// &[ /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::normal(1), /// BitDistributorOutputType::tiny(), /// ], /// ); /// let xss_prefix = xss.take(20).collect_vec(); /// assert_eq!( /// xss_prefix /// .iter() /// .map(Vec::as_slice) /// .collect_vec() /// .as_slice(), /// &[ /// &['a', 'a', 'a'], /// &['a', 'a', 'b'], /// &['a', 'a', 'c'], /// &['a', 'a', 'd'], /// &['a', 'b', 'a'], /// &['a', 'b', 'b'], /// &['a', 'b', 'c'], /// &['a', 'b', 'd'], /// &['a', 'a', 'e'], /// &['a', 'a', 'f'], /// &['a', 'a', 'g'], /// &['a', 'a', 'h'], /// &['a', 'b', 'e'], /// &['a', 'b', 'f'], /// &['a', 'b', 'g'], /// &['a', 'b', 'h'], /// &['b', 'a', 'a'], /// &['b', 'a', 'b'], /// &['b', 'a', 'c'], /// &['b', 'a', 'd'] /// ] /// ); /// ``` pub fn exhaustive_vecs_fixed_length_1_input( xs: I, output_types: &[BitDistributorOutputType], ) -> ExhaustiveFixedLengthVecs1Input where I::Item: Clone, { match output_types.len() { 0 => ExhaustiveFixedLengthVecs1Input::Zero(once(Vec::new())), 1 => ExhaustiveFixedLengthVecs1Input::One(xs), _ => ExhaustiveFixedLengthVecs1Input::GreaterThanOne( exhaustive_vecs_fixed_length_1_input_g(xs, output_types), ), } } /// Generates all [`Vec`]s of a given length with elements from a single iterator. /// /// If `xs` is finite, the output length is $\ell^n$, where $\ell$ is `xs.count()` and $n$ is `len`. /// If `xs` is infinite, the output is also infinite. /// /// If `len` is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless `len` is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_fixed_length_from_single; /// /// let xss = exhaustive_vecs_fixed_length_from_single(2, 0..4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[0, 0], /// &[0, 1], /// &[1, 0], /// &[1, 1], /// &[0, 2], /// &[0, 3], /// &[1, 2], /// &[1, 3], /// &[2, 0], /// &[2, 1], /// &[3, 0], /// &[3, 1], /// &[2, 2], /// &[2, 3], /// &[3, 2], /// &[3, 3] /// ] /// ); /// ``` #[inline] pub fn exhaustive_vecs_fixed_length_from_single( len: u64, xs: I, ) -> ExhaustiveFixedLengthVecs1Input where I::Item: Clone, { exhaustive_vecs_fixed_length_1_input( xs, &vec![BitDistributorOutputType::normal(1); usize::exact_from(len)], ) } #[derive(Clone, Debug)] struct LexVecsGenerator> { ys: J, } impl> ExhaustiveDependentPairsYsGenerator, LexFixedLengthVecsFromSingle> for LexVecsGenerator { #[inline] fn get_ys(&self, &x: &u64) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single(x, self.ys.clone()) } } #[inline] const fn shortlex_vecs_from_element_iterator_helper< T: Clone, I: Iterator, J: Clone + Iterator, >( xs: I, ys: J, ) -> LexDependentPairs, LexVecsGenerator, I, LexFixedLengthVecsFromSingle> { lex_dependent_pairs_stop_after_empty_ys(xs, LexVecsGenerator { ys }) } /// Generates all [`Vec`]s with elements from a specified iterator and with lengths from another /// iterator. #[derive(Clone, Debug)] pub struct ShortlexVecs, J: Clone + Iterator>( LexDependentPairs, LexVecsGenerator, I, LexFixedLengthVecsFromSingle>, ); impl, J: Clone + Iterator> Iterator for ShortlexVecs { type Item = Vec; #[inline] fn next(&mut self) -> Option> { self.0.next().map(|p| p.1) } } /// Generates all [`Vec`]s with elements from a specified iterator and with lengths from another /// iterator. /// /// The length-generating iterator is `xs`, and the element-generating iterator is `ys`. /// /// If the provided lengths are $\ell_0, \ell_1, \ell_2, \ldots$, then first all [`Vec`]s with /// length $\ell_0$ will be generated, in lexicographic order; then all [`Vec`]s with length /// $\ell_2$, and so on. If the lengths iterator has repetitions, then the generated [`Vec`]s will /// be repeated too. /// /// `ys` must be finite; if it's infinite, the output will never get past the first nonzero $\ell$. /// /// There's one quirk if `ys` is empty: then the iterator will stop as soon as it encounters a /// nonzero $\ell$, even if there are zeros later on. This prevents the iterator hanging when given /// an empty `ys` and lengths $0, 1, 2, \ldots$. /// /// If `ys` is empty, the output length is the amount of zeros generated by `xs` before the first /// nonzero length. If `ys` is nonempty and `xs` is infinite, the output is infinite. Finally, if /// `ys` is nonempty and `xs` is finite, the output length is /// $$ /// \sum_{k=0}^{m-1} n^{\ell_k}, /// $$ /// where $n$ is `ys.count()` and $m$ is `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::nevers::nevers; /// use malachite_base::vecs::exhaustive::shortlex_vecs_from_length_iterator; /// /// let xss = shortlex_vecs_from_length_iterator([2, 1, 2].iter().cloned(), exhaustive_bools()) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[false, false][..], /// &[false, true], /// &[true, false], /// &[true, true], /// &[false], /// &[true], /// &[false, false], /// &[false, true], /// &[true, false], /// &[true, true] /// ] /// ); /// /// let xss = /// shortlex_vecs_from_length_iterator([0, 0, 1, 0].iter().cloned(), nevers()).collect_vec(); /// // Stops after first empty ys /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[&[], &[]] /// ); /// ``` #[inline] pub const fn shortlex_vecs_from_length_iterator< T: Clone, I: Iterator, J: Clone + Iterator, >( xs: I, ys: J, ) -> ShortlexVecs { ShortlexVecs(shortlex_vecs_from_element_iterator_helper(xs, ys)) } /// Generates [`Vec`]s with elements from a specified iterator, in shortlex order. /// /// Shortlex order means that the [`Vec`]s are output from shortest to longest, and [`Vec`]s of the /// same length are output in lexicographic order with respect to the ordering of the [`Vec`] /// elements specified by the input iterator. /// /// `xs` must be finite; if it's infinite, only [`Vec`]s of length 0 and 1 are ever produced. /// /// If `xs` is empty, the output length is 1; otherwise, the output is infinite. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::vecs::exhaustive::shortlex_vecs; /// /// let bss = shortlex_vecs(exhaustive_bools()).take(20).collect_vec(); /// assert_eq!( /// bss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[false], /// &[true], /// &[false, false], /// &[false, true], /// &[true, false], /// &[true, true], /// &[false, false, false], /// &[false, false, true], /// &[false, true, false], /// &[false, true, true], /// &[true, false, false], /// &[true, false, true], /// &[true, true, false], /// &[true, true, true], /// &[false, false, false, false], /// &[false, false, false, true], /// &[false, false, true, false], /// &[false, false, true, true], /// &[false, true, false, false] /// ] /// ); /// ``` #[inline] pub fn shortlex_vecs( xs: I, ) -> ShortlexVecs, I> where I::Item: Clone, { shortlex_vecs_from_length_iterator(exhaustive_unsigneds(), xs) } /// Generates all [`Vec`]s with a minimum length and with elements from a specified iterator, in /// shortlex order. /// /// Shortlex order means that the [`Vec`]s are output from shortest to longest, and [`Vec`]s of the /// same length are output in lexicographic order with respect to the ordering of the [`Vec`] /// elements specified by the input iterator. /// /// `xs` must be finite; if it's infinite, only [`Vec`]s of length `min_length` (or 0 and 1, if /// `min_length` is 0) are ever produced. /// /// If `xs` is empty and `min_length` is 0, the output length is 1; if `xs` is empty and /// `min_length` is greater than 0, the output is empty; otherwise, the output is infinite. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::vecs::exhaustive::shortlex_vecs_min_length; /// /// let bss = shortlex_vecs_min_length(2, exhaustive_bools()) /// .take(20) /// .collect_vec(); /// assert_eq!( /// bss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[false, false][..], /// &[false, true], /// &[true, false], /// &[true, true], /// &[false, false, false], /// &[false, false, true], /// &[false, true, false], /// &[false, true, true], /// &[true, false, false], /// &[true, false, true], /// &[true, true, false], /// &[true, true, true], /// &[false, false, false, false], /// &[false, false, false, true], /// &[false, false, true, false], /// &[false, false, true, true], /// &[false, true, false, false], /// &[false, true, false, true], /// &[false, true, true, false], /// &[false, true, true, true] /// ] /// ); /// ``` #[inline] pub fn shortlex_vecs_min_length( min_length: u64, xs: I, ) -> ShortlexVecs, I> where I::Item: Clone, { shortlex_vecs_from_length_iterator( primitive_int_increasing_inclusive_range(min_length, u64::MAX), xs, ) } /// Generates all [`Vec`]s with lengths in $[a, b)$ and with elements from a specified iterator, in /// shortlex order. /// /// Shortlex order means that the [`Vec`]s are output from shortest to longest, and [`Vec`]s of the /// same length are output in lexicographic order with respect to the ordering of the [`Vec`] /// elements specified by the input iterator. /// /// `xs` must be finite; if it's infinite and $a < b$, only [`Vec`]s of length `a` (or 0 and 1, if /// `a` is 0) are ever produced. /// /// The output length is /// $$ /// \sum_{k=a}^{b-1} n^k, /// $$ /// where $k$ is `xs.count()`. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::vecs::exhaustive::shortlex_vecs_length_range; /// /// let bss = shortlex_vecs_length_range(2, 4, exhaustive_bools()).collect_vec(); /// assert_eq!( /// bss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[false, false][..], /// &[false, true], /// &[true, false], /// &[true, true], /// &[false, false, false], /// &[false, false, true], /// &[false, true, false], /// &[false, true, true], /// &[true, false, false], /// &[true, false, true], /// &[true, true, false], /// &[true, true, true] /// ] /// ); /// ``` #[inline] pub fn shortlex_vecs_length_range( a: u64, mut b: u64, xs: I, ) -> ShortlexVecs, I> where I::Item: Clone, { if a > b { b = a; } shortlex_vecs_from_length_iterator(primitive_int_increasing_range(a, b), xs) } /// Generates all [`Vec`]s with lengths in $[a, b]$ and with elements from a specified iterator, in /// shortlex order. /// /// Shortlex order means that the [`Vec`]s are output from shortest to longest, and [`Vec`]s of the /// same length are output in lexicographic order with respect to the ordering of the [`Vec`] /// elements specified by the input iterator. /// /// `xs` must be finite; if it's infinite, only [`Vec`]s of length `a` (or 0 and 1, if `a` is 0) are /// ever produced. /// /// The output length is /// $$ /// \sum_{k=a}^b n^k, /// $$ /// where $k$ is `xs.count()`. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::vecs::exhaustive::shortlex_vecs_length_inclusive_range; /// /// let bss = shortlex_vecs_length_inclusive_range(2, 3, exhaustive_bools()).collect_vec(); /// assert_eq!( /// bss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[false, false][..], /// &[false, true], /// &[true, false], /// &[true, true], /// &[false, false, false], /// &[false, false, true], /// &[false, true, false], /// &[false, true, true], /// &[true, false, false], /// &[true, false, true], /// &[true, true, false], /// &[true, true, true] /// ] /// ); /// ``` #[inline] pub fn shortlex_vecs_length_inclusive_range( mut a: u64, mut b: u64, xs: I, ) -> ShortlexVecs, I> where I::Item: Clone, { if a > b { a = 1; b = 0; } shortlex_vecs_from_length_iterator(primitive_int_increasing_range(a, b.saturating_add(1)), xs) } #[doc(hidden)] #[derive(Clone, Debug)] struct ExhaustiveVecsGenerator> { ys: J, } impl> ExhaustiveDependentPairsYsGenerator, ExhaustiveFixedLengthVecs1Input> for ExhaustiveVecsGenerator { #[inline] fn get_ys(&self, &x: &u64) -> ExhaustiveFixedLengthVecs1Input { exhaustive_vecs_fixed_length_1_input( self.ys.clone(), &vec![BitDistributorOutputType::normal(1); usize::exact_from(x)], ) } } #[inline] const fn exhaustive_vecs_from_element_iterator_helper< T: Clone, I: Iterator, J: Clone + Iterator, >( xs: I, ys: J, ) -> ExhaustiveDependentPairs< u64, Vec, RulerSequence, ExhaustiveVecsGenerator, I, ExhaustiveFixedLengthVecs1Input, > { exhaustive_dependent_pairs_stop_after_empty_ys( ruler_sequence(), xs, ExhaustiveVecsGenerator { ys }, ) } /// Generates all [`Vec`]s with elements from a specified iterator and with lengths from another /// iterator. #[derive(Clone, Debug)] pub struct ExhaustiveVecs, J: Clone + Iterator>( ExhaustiveDependentPairs< u64, Vec, RulerSequence, ExhaustiveVecsGenerator, I, ExhaustiveFixedLengthVecs1Input, >, ); impl, J: Clone + Iterator> Iterator for ExhaustiveVecs { type Item = Vec; #[inline] fn next(&mut self) -> Option> { self.0.next().map(|p| p.1) } } /// Generates all [`Vec`]s with elements from a specified iterator and with lengths from another /// iterator. /// /// The length-generating iterator is `xs`, and the element-generating iterator is `ys`. /// /// If the lengths iterator has repetitions, then the generated [`Vec`]s will be repeated too. /// /// There's one quirk if `ys` is empty: then the iterator will stop at some point after it /// encounters a nonzero $\ell$, even if there are zeros later on. This prevents the iterator /// hanging when given an empty `ys` and lengths $0, 1, 2, \ldots$. /// /// - If `ys` is empty, the output length is finite. /// - If `ys` is infinite, the output length is infinite. /// - If `ys` is nonempty and finite, and `xs` is infinite, the output is infinite. /// - If `ys` is nonempty and finite, and `xs` is finite, the output length is /// $$ /// \sum_{k=0}^{m-1} n^{\ell_k}, /// $$ /// where $n$ is `ys.count()` and $m$ is `xs.count()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::bools::exhaustive::exhaustive_bools; /// use malachite_base::nevers::nevers; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_from_length_iterator; /// /// let xss = exhaustive_vecs_from_length_iterator([2, 1, 2].iter().cloned(), exhaustive_bools()) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[false, false][..], /// &[false], /// &[false, true], /// &[false, false], /// &[true, false], /// &[true], /// &[true, true], /// &[false, true], /// &[true, false], /// &[true, true] /// ] /// ); /// /// let xss = /// exhaustive_vecs_from_length_iterator([0, 0, 1, 0].iter().cloned(), nevers()).collect_vec(); /// // Stops at some point after first empty ys /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[&[], &[]] /// ); /// ``` #[inline] pub const fn exhaustive_vecs_from_length_iterator< T: Clone, I: Iterator, J: Clone + Iterator, >( lengths: I, xs: J, ) -> ExhaustiveVecs { ExhaustiveVecs(exhaustive_vecs_from_element_iterator_helper(lengths, xs)) } /// Generates all [`Vec`]s with elements from a specified iterator. /// /// If `xs` is empty, the output length is 1; otherwise, the output is infinite. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// use malachite_base::vecs::exhaustive::exhaustive_vecs; /// /// let xss = exhaustive_vecs(exhaustive_unsigneds::()) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[0], /// &[1], /// &[0, 0, 0], /// &[2], /// &[0, 0], /// &[3], /// &[0, 0, 0, 0], /// &[4], /// &[0, 1], /// &[5], /// &[0, 0, 1], /// &[6], /// &[1, 0], /// &[7], /// &[0, 0, 0, 0, 0], /// &[8], /// &[1, 1], /// &[9], /// &[0, 1, 0] /// ] /// ); /// ``` #[inline] pub fn exhaustive_vecs( xs: I, ) -> ExhaustiveVecs, I> where I::Item: Clone, { exhaustive_vecs_from_length_iterator(exhaustive_unsigneds(), xs) } /// Generates all [`Vec`]s with a minimum length and with elements from a specified iterator. /// /// If `xs` is empty and `min_length` is 0, the output length is 1; if `xs` is empty and /// `min_length` is greater than 0, the output is empty; otherwise, the output is infinite. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_min_length; /// /// let xss = exhaustive_vecs_min_length(2, exhaustive_unsigneds::()) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[0, 0][..], /// &[0, 0, 0], /// &[0, 1], /// &[0, 0, 0, 0], /// &[1, 0], /// &[0, 0, 1], /// &[1, 1], /// &[0, 0, 0, 0, 0], /// &[0, 2], /// &[0, 1, 0], /// &[0, 3], /// &[0, 0, 0, 1], /// &[1, 2], /// &[0, 1, 1], /// &[1, 3], /// &[0, 0, 0, 0, 0, 0], /// &[2, 0], /// &[1, 0, 0], /// &[2, 1], /// &[0, 0, 1, 0] /// ] /// ); /// ``` #[inline] pub fn exhaustive_vecs_min_length( min_length: u64, xs: I, ) -> ExhaustiveVecs, I> where I::Item: Clone, { exhaustive_vecs_from_length_iterator( primitive_int_increasing_inclusive_range(min_length, u64::MAX), xs, ) } /// Generates all [`Vec`]s with lengths in $[a, b)$ and with elements from a specified iterator. /// /// - If $a \geq b$, the output length is 0. /// - If $a = 0$ and $b = 1$, the output length is 1. /// - If $a < b$, $b > 1$, and `xs` is infinite, the output length is infinite. /// - If `xs` is finite, the output length is /// $$ /// \sum_{k=a}^{b-1} n^k, /// $$ /// where $k$ is `xs.count()`. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_length_range; /// /// let xss = exhaustive_vecs_length_range(2, 4, exhaustive_unsigneds::()) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[0, 0][..], /// &[0, 0, 0], /// &[0, 1], /// &[1, 0], /// &[1, 1], /// &[0, 0, 1], /// &[0, 2], /// &[0, 1, 0], /// &[0, 3], /// &[0, 1, 1], /// &[1, 2], /// &[1, 3], /// &[2, 0], /// &[1, 0, 0], /// &[2, 1], /// &[3, 0], /// &[3, 1], /// &[1, 0, 1], /// &[2, 2], /// &[2, 3] /// ] /// ); /// ``` #[inline] pub fn exhaustive_vecs_length_range( a: u64, mut b: u64, xs: I, ) -> ExhaustiveVecs, I> where I::Item: Clone, { if a > b { b = a; } exhaustive_vecs_from_length_iterator(primitive_int_increasing_range(a, b), xs) } /// Generates all [`Vec`]s with lengths in $[a, b]$ and with elements from a specified iterator. /// /// - If $a > b$, the output length is 0. /// - If $a = b = 0$, the output length is 1. /// - If $a < b$, $b > 0$, and `xs` is infinite, the output length is infinite. /// - If `xs` is finite, the output length is /// $$ /// \sum_{k=a}^b n^k, /// $$ /// where $k$ is `xs.count()`. /// /// The lengths of the output [`Vec`]s grow logarithmically. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::exhaustive::exhaustive_unsigneds; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_length_inclusive_range; /// /// let xss = exhaustive_vecs_length_inclusive_range(2, 4, exhaustive_unsigneds::()) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[0, 0][..], /// &[0, 0, 0], /// &[0, 1], /// &[0, 0, 0, 0], /// &[1, 0], /// &[0, 0, 1], /// &[1, 1], /// &[0, 2], /// &[0, 3], /// &[0, 1, 0], /// &[1, 2], /// &[0, 0, 0, 1], /// &[1, 3], /// &[0, 1, 1], /// &[2, 0], /// &[1, 0, 0], /// &[2, 1], /// &[1, 0, 1], /// &[3, 0], /// &[0, 0, 1, 0] /// ] /// ); /// ``` #[inline] pub fn exhaustive_vecs_length_inclusive_range( mut a: u64, mut b: u64, xs: I, ) -> ExhaustiveVecs, I> where I::Item: Clone, { if a > b { a = 1; b = 0; } exhaustive_vecs_from_length_iterator(primitive_int_increasing_range(a, b.saturating_add(1)), xs) } /// Generates all collections of elements from an iterator, where the collections are of a fixed /// length, have no repetitions, and are ordered the same way as in the iterator. #[derive(Clone, Debug)] pub struct LexFixedLengthOrderedUniqueCollections> where I::Item: Clone, { first: bool, done: bool, xs: IteratorCache, indices: Vec, phantom: PhantomData<(I::Item, C)>, } impl> LexFixedLengthOrderedUniqueCollections where I::Item: Clone, { pub fn new(k: u64, xs: I) -> Self { Self { first: true, done: false, xs: IteratorCache::new(xs), indices: (0..usize::exact_from(k)).collect(), phantom: PhantomData, } } } #[doc(hidden)] pub fn fixed_length_ordered_unique_indices_helper( n: usize, k: usize, indices: &mut [usize], ) -> bool { let mut expected_j = n - 1; let mut i = k - 1; // Find longest suffix of the form [..., n - 3, n - 2, n - 1]. After this loop, i is the index // right before this longest suffix. loop { if expected_j != indices[i] { break; } if i == 0 { return true; } i -= 1; expected_j -= 1; } let mut j = indices[i] + 1; for index in &mut indices[i..] { *index = j; j += 1; } false } impl> Iterator for LexFixedLengthOrderedUniqueCollections where I::Item: Clone, { type Item = C; fn next(&mut self) -> Option { if self.done { return None; } let k = self.indices.len(); if self.first { self.first = false; self.xs.get(k); if let Some(n) = self.xs.known_len() && n < k { self.done = true; return None; } } else { if k == 0 { self.done = true; return None; } if let Some(n) = self.xs.known_len() { if fixed_length_ordered_unique_indices_helper(n, k, &mut self.indices) { self.done = true; return None; } } else { *self.indices.last_mut().unwrap() += 1; } } if let Some(&last_index) = self.indices.last() { // Give known len a chance to be set self.xs.get(last_index + 1); } Some( self.indices .iter() .map(|&i| self.xs.assert_get(i).clone()) .collect(), ) } } /// Generates [`Vec`]s of a given length with elements from a single iterator, such that each /// [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the same way as /// they are in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_fixed_length; /// /// let xss = lex_ordered_unique_vecs_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2, 3, 4], /// &[1, 2, 3, 5], /// &[1, 2, 3, 6], /// &[1, 2, 4, 5], /// &[1, 2, 4, 6], /// &[1, 2, 5, 6], /// &[1, 3, 4, 5], /// &[1, 3, 4, 6], /// &[1, 3, 5, 6], /// &[1, 4, 5, 6], /// &[2, 3, 4, 5], /// &[2, 3, 4, 6], /// &[2, 3, 5, 6], /// &[2, 4, 5, 6], /// &[3, 4, 5, 6] /// ] /// ); /// ``` #[inline] pub fn lex_ordered_unique_vecs_fixed_length( k: u64, xs: I, ) -> LexFixedLengthOrderedUniqueCollections> where I::Item: Clone, { LexFixedLengthOrderedUniqueCollections::new(k, xs) } /// Generates all collections of elements from an iterator in shortlex order, where the collections /// have no repetitions and are ordered the same way as in the iterator. #[derive(Clone)] pub struct ShortlexOrderedUniqueCollections> where I::Item: Clone, { current_len: u64, max_len: u64, xs: I, current_xss: LexFixedLengthOrderedUniqueCollections, } impl> ShortlexOrderedUniqueCollections where I::Item: Clone, { pub(crate) fn new(a: u64, b: u64, xs: I) -> Self { Self { current_len: a, max_len: b, xs: xs.clone(), current_xss: LexFixedLengthOrderedUniqueCollections::new(a, xs), } } } impl> Iterator for ShortlexOrderedUniqueCollections where I::Item: Clone, { type Item = C; fn next(&mut self) -> Option { if self.current_len > self.max_len { return None; } if let Some(next) = self.current_xss.next() { Some(next) } else { self.current_len += 1; if self.current_len > self.max_len { return None; } self.current_xss = LexFixedLengthOrderedUniqueCollections { first: true, done: false, xs: IteratorCache::new(self.xs.clone()), indices: (0..usize::exact_from(self.current_len)).collect(), phantom: PhantomData, }; if let Some(next) = self.current_xss.next() { Some(next) } else { // Prevent any further iteration self.max_len = 0; self.current_len = 1; None } } } } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements, and the elements in each [`Vec`] are ordered the same way as they are in the source /// iterator. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length 2 and above will never be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs; /// /// let xss = shortlex_ordered_unique_vecs(1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[2], /// &[3], /// &[4], /// &[1, 2], /// &[1, 3], /// &[1, 4], /// &[2, 3], /// &[2, 4], /// &[3, 4], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// &[1, 2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn shortlex_ordered_unique_vecs( xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone, { shortlex_ordered_unique_vecs_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the same way as /// they are in the source iterator. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, \ell + 1)` and /// above will never be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_min_length; /// /// let xss = shortlex_ordered_unique_vecs_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 3], /// &[2, 4], /// &[3, 4], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// &[1, 2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn shortlex_ordered_unique_vecs_min_length( min_length: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone, { shortlex_ordered_unique_vecs_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, a + 1)` and above /// will never be generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_length_range; /// /// let xss = shortlex_ordered_unique_vecs_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 3], /// &[2, 4], /// &[3, 4], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// ] /// ); /// ``` #[inline] pub fn shortlex_ordered_unique_vecs_length_range( mut a: u64, mut b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } shortlex_ordered_unique_vecs_length_inclusive_range(a, b - 1, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b]$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, a + 1)` and above /// will never be generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_length_inclusive_range; /// /// let xss = shortlex_ordered_unique_vecs_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 3], /// &[2, 4], /// &[3, 4], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// ] /// ); /// ``` #[inline] pub fn shortlex_ordered_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ShortlexOrderedUniqueCollections> where I::Item: Clone, { ShortlexOrderedUniqueCollections::new(a, b, xs) } /// Generates all collections of elements from an iterator in lexicographic order, where the /// collections have no repetitions and are ordered the same way as in the iterator. #[derive(Clone, Debug)] pub struct LexOrderedUniqueCollections> where I::Item: Clone, { done: bool, first: bool, min_len: usize, max_len: usize, xs: IteratorCache, indices: Vec, phantom: PhantomData<(I::Item, C)>, } impl> LexOrderedUniqueCollections where I::Item: Clone, { pub(crate) fn new(a: u64, b: u64, xs: I) -> Self { Self { done: a > b, first: true, min_len: usize::exact_from(a), max_len: usize::exact_from(b), xs: IteratorCache::new(xs), indices: (0..usize::exact_from(a)).collect(), phantom: PhantomData, } } } impl> Iterator for LexOrderedUniqueCollections where I::Item: Clone, { type Item = C; fn next(&mut self) -> Option { if self.done { return None; } let k = self.indices.len(); if self.first { self.first = false; self.xs.get(k); if let Some(n) = self.xs.known_len() && n < k { self.done = true; return None; } } else if k == 0 { if self.xs.get(0).is_none() { self.done = true; return None; } self.indices.push(0); } else { let last_i = *self.indices.last().unwrap(); let next_i = last_i + 1; if k < self.max_len && self.xs.get(next_i).is_some() { // For example, if xs is [0, 1, 2, 3] and max_len is 4, then the next set of indices // after [0, 1] is [0, 1, 2]. self.indices.push(next_i); } else if k == self.min_len { // For example, if xs is [0, 1, 2, 3] and min_len is 2, then the next set of indices // after [1, 3] is [2, 3]. if let Some(n) = self.xs.known_len() { if fixed_length_ordered_unique_indices_helper(n, k, &mut self.indices) { self.done = true; return None; } } else { *self.indices.last_mut().unwrap() += 1; } } else if self.xs.get(next_i).is_some() { // For example, if xs is [0, 1, 2, 3] and max_len is 3, then the next set of indices // after [1, 2, 3] is [1, 2, 4]. *self.indices.last_mut().unwrap() = next_i; } else { let x = self.indices.pop(); if let Some(last) = self.indices.last_mut() { // For example, if xs is [0, 1, 2, 3] and max_len is 3, then the next set of // indices after [0, 1, 2] is [0, 1, 3]. *last += 1; } else { let next_x = x.unwrap() + 1; if self.xs.get(next_x).is_none() { // For example, if xs is [0, 1, 2, 3], then nothing comes after the indices // [3]. self.done = true; return None; } // For example, if xs is [0, 1, 2, 3] and max_len is 1, then the next set of // indices after [0] is [1]. self.indices.push(next_x); } } } if let Some(&last_index) = self.indices.last() { // Give known len a chance to be set self.xs.get(last_index + 1); } Some( self.indices .iter() .map(|&i| self.xs.assert_get(i).clone()) .collect(), ) } } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements, and the elements in each [`Vec`] are ordered the same way as they are in the source /// iterator. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs; /// /// let xss = lex_ordered_unique_vecs(1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[1, 2], /// &[1, 2, 3], /// &[1, 2, 3, 4], /// &[1, 2, 4], /// &[1, 3], /// &[1, 3, 4], /// &[1, 4], /// &[2], /// &[2, 3], /// &[2, 3, 4], /// &[2, 4], /// &[3], /// &[3, 4], /// &[4] /// ] /// ); /// ``` #[inline] pub fn lex_ordered_unique_vecs( xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone, { lex_ordered_unique_vecs_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the same way as /// they are in the source iterator. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_min_length; /// /// let xss = lex_ordered_unique_vecs_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 3, 4], /// &[1, 2, 4], /// &[1, 3], /// &[1, 3, 4], /// &[1, 4], /// &[2, 3], /// &[2, 3, 4], /// &[2, 4], /// &[3, 4], /// ] /// ); /// ``` #[inline] pub fn lex_ordered_unique_vecs_min_length( min_length: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone, { lex_ordered_unique_vecs_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_length_range; /// /// let xss = lex_ordered_unique_vecs_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3], /// &[1, 3, 4], /// &[1, 4], /// &[2, 3], /// &[2, 3, 4], /// &[2, 4], /// &[3, 4], /// ] /// ); /// ``` #[inline] pub fn lex_ordered_unique_vecs_length_range( mut a: u64, mut b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } lex_ordered_unique_vecs_length_inclusive_range(a, b - 1, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b]$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_length_inclusive_range; /// /// let xss = lex_ordered_unique_vecs_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3], /// &[1, 3, 4], /// &[1, 4], /// &[2, 3], /// &[2, 3, 4], /// &[2, 4], /// &[3, 4], /// ] /// ); /// ``` #[inline] pub fn lex_ordered_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> LexOrderedUniqueCollections> where I::Item: Clone, { LexOrderedUniqueCollections::new(a, b, xs) } /// This function is used for iterating through all bit patterns with a specified number of minimum /// and maximum `true` bits. /// /// Given an existing bit pattern, and a reference `bit_count`, which must equal the number of /// `true`s in the pattern, mutates the pattern into the next pattern with a valid number of `true` /// bits. See the unit tests for many examples. /// /// # Worst-case complexity /// $$ /// T(k) = O(k) /// $$ /// /// $$ /// M(k) = O(k) /// $$ /// /// where $T$ is time, $M$ is additional memory, and $k$ is the length of `pattern`. The memory /// usage is only linear when the pattern vector needs to be reallocated, which happens rarely. /// /// # Panics /// Panics if `max_bits` is zero. (However, `min_bits` may be zero.) /// /// # Examples /// ``` /// use malachite_base::vecs::exhaustive::next_bit_pattern; /// /// // Suppose we are generating all bit patterns with 2 to 4 true bits, inclusive. Suppose our /// // current pattern is `1111000`. Then, the lexicographically next largest valid pattern is /// // `10000001`. (All patterns of the form `1111xxx`, where the `x`s are not all zero, have too /// // many ones. That brings us to `10000000`, which has too few ones, and then `10000001`.) /// // /// // The patterns are represented "in reverse", with least-significant bits appearing first. /// let mut pattern = vec![false, false, false, true, true, true, true]; /// let mut bit_count = 4; /// next_bit_pattern(&mut pattern, &mut bit_count, 2, 4); /// assert_eq!( /// pattern, /// &[true, false, false, false, false, false, false, true] /// ); /// assert_eq!(bit_count, 2); /// ``` pub fn next_bit_pattern( pattern: &mut Vec, bit_count: &mut usize, min_bits: usize, max_bits: usize, ) { assert_ne!(max_bits, 0); match pattern.first() { None => { pattern.push(true); *bit_count = 1; } Some(&false) => { if *bit_count < max_bits { pattern[0] = true; *bit_count += 1; } else { let leading_false_count = pattern.iter().take_while(|&&b| !b).count(); let true_after_false_count = pattern[leading_false_count..] .iter() .take_while(|&&b| b) .count(); let tf_count = leading_false_count + true_after_false_count; if tf_count == pattern.len() { for b in &mut *pattern { *b = false; } pattern.push(true); *bit_count = 1; } else { for b in &mut pattern[leading_false_count..tf_count] { *b = false; } pattern[tf_count] = true; *bit_count -= true_after_false_count - 1; } if *bit_count < min_bits { let diff = min_bits - *bit_count; for b in &mut pattern[..diff] { *b = true; } *bit_count += diff; } } } Some(&true) => { let leading_true_count = pattern.iter().take_while(|&&b| b).count(); for b in &mut pattern[..leading_true_count] { *b = false; } if leading_true_count == pattern.len() { pattern.push(true); } else { pattern[leading_true_count] = true; } *bit_count -= leading_true_count - 1; if *bit_count < min_bits { let diff = min_bits - *bit_count; for b in &mut pattern[..diff] { *b = true; } *bit_count += diff; } } } } #[derive(Clone)] #[doc(hidden)] pub struct ExhaustiveOrderedUniqueCollectionsGreaterThanOne> where I::Item: Clone, { done: bool, first: bool, min_bits: usize, max_bits: usize, xs: IteratorCache, pattern: Vec, bit_count: usize, phantom: PhantomData<*const C>, } impl> Iterator for ExhaustiveOrderedUniqueCollectionsGreaterThanOne where I::Item: Clone, { type Item = C; fn next(&mut self) -> Option { if self.done { return None; } else if self.first { self.first = false; } else { next_bit_pattern( &mut self.pattern, &mut self.bit_count, self.min_bits, self.max_bits, ); } if !self.pattern.is_empty() && self.xs.get(self.pattern.len() - 1).is_none() { self.done = true; return None; } Some( self.pattern .iter() .enumerate() .filter_map(|(i, &b)| { if b { Some(self.xs.assert_get(i).clone()) } else { None } }) .collect(), ) } } /// Generates all collections of elements from an iterator, where the collections have no /// repetitions and are ordered the same way as in the iterator. #[derive(Clone)] pub enum ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { None, Zero(bool), ZeroOne(bool, I), One(I), GreaterThanOne(ExhaustiveOrderedUniqueCollectionsGreaterThanOne), } impl> ExhaustiveOrderedUniqueCollections where I::Item: Clone, { pub(crate) fn new(a: u64, b: u64, xs: I) -> Self { match (a, b) { (a, b) if a > b => Self::None, (0, 0) => Self::Zero(false), (0, 1) => Self::ZeroOne(true, xs), (1, 1) => Self::One(xs), (a, b) => Self::GreaterThanOne(ExhaustiveOrderedUniqueCollectionsGreaterThanOne { done: false, first: true, min_bits: usize::saturating_from(a), max_bits: usize::saturating_from(b), xs: IteratorCache::new(xs), pattern: vec![true; usize::saturating_from(a)], bit_count: usize::saturating_from(a), phantom: PhantomData, }), } } } impl> Iterator for ExhaustiveOrderedUniqueCollections where I::Item: Clone, { type Item = C; fn next(&mut self) -> Option { match self { Self::None => None, Self::Zero(done) => { if *done { None } else { *done = true; Some(empty().collect()) } } Self::ZeroOne(first, xs) => { if *first { *first = false; Some(empty().collect()) } else { xs.next().map(|x| once(x).collect()) } } Self::One(xs) => xs.next().map(|x| once(x).collect()), Self::GreaterThanOne(xs) => xs.next(), } } } /// Generates [`Vec`]s of a given length with elements from a single iterator, such that each /// [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the same way as /// they are in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is $\binom{n}{k}$. /// /// If $k$ is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_fixed_length; /// /// let xss = exhaustive_ordered_unique_vecs_fixed_length(4, 1..=6).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2, 3, 4], /// &[1, 2, 3, 5], /// &[1, 2, 4, 5], /// &[1, 3, 4, 5], /// &[2, 3, 4, 5], /// &[1, 2, 3, 6], /// &[1, 2, 4, 6], /// &[1, 3, 4, 6], /// &[2, 3, 4, 6], /// &[1, 2, 5, 6], /// &[1, 3, 5, 6], /// &[2, 3, 5, 6], /// &[1, 4, 5, 6], /// &[2, 4, 5, 6], /// &[3, 4, 5, 6] /// ] /// ); /// ``` #[inline] pub fn exhaustive_ordered_unique_vecs_fixed_length( k: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { exhaustive_ordered_unique_vecs_length_inclusive_range(k, k, xs) } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements, and the elements in each [`Vec`] are ordered the same way as they are in the source /// iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is $2^n$. /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs; /// /// let xss = exhaustive_ordered_unique_vecs(1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[2], /// &[1, 2], /// &[3], /// &[1, 3], /// &[2, 3], /// &[1, 2, 3], /// &[4], /// &[1, 4], /// &[2, 4], /// &[1, 2, 4], /// &[3, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// &[1, 2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_ordered_unique_vecs( xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { exhaustive_ordered_unique_vecs_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the same way as /// they are in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_min_length; /// /// let xss = exhaustive_ordered_unique_vecs_min_length(2, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 3], /// &[1, 2, 3], /// &[1, 4], /// &[2, 4], /// &[1, 2, 4], /// &[3, 4], /// &[1, 3, 4], /// &[2, 3, 4], /// &[1, 2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_ordered_unique_vecs_min_length( min_length: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { exhaustive_ordered_unique_vecs_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_length_range; /// /// let xss = exhaustive_ordered_unique_vecs_length_range(2, 4, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 3], /// &[1, 2, 3], /// &[1, 4], /// &[2, 4], /// &[1, 2, 4], /// &[3, 4], /// &[1, 3, 4], /// &[2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_ordered_unique_vecs_length_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { if a >= b { ExhaustiveOrderedUniqueCollections::None } else { exhaustive_ordered_unique_vecs_length_inclusive_range(a, b - 1, xs) } } /// Generates [`Vec`]s, with lengths in a range $[a, b]$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements, and the elements in each [`Vec`] are ordered the /// same way as they are in the source iterator. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \binom{n}{i}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_length_inclusive_range; /// /// let xss = exhaustive_ordered_unique_vecs_length_inclusive_range(2, 3, 1..=4).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 3], /// &[1, 2, 3], /// &[1, 4], /// &[2, 4], /// &[1, 2, 4], /// &[3, 4], /// &[1, 3, 4], /// &[2, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_ordered_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ExhaustiveOrderedUniqueCollections> where I::Item: Clone, { ExhaustiveOrderedUniqueCollections::new(a, b, xs) } fn fixed_length_unique_indices_helper(indices: &mut [usize], used: &mut [bool]) -> bool { let n = used.len(); let k = indices.len(); assert!(k <= n); for i in (0..k).rev() { let x = indices[i]; used[x] = false; for y in x + 1..n { if !used[y] { indices[i] = y; used[y] = true; let mut p = 0; for j in &mut indices[i + 1..k] { while used[p] { p += 1; } *j = p; used[p] = true; } return false; } } } true } #[doc(hidden)] #[derive(Clone, Debug)] pub struct UniqueIndices { pub done: bool, first: bool, indices: Vec, pub used: Vec, } impl UniqueIndices { #[doc(hidden)] pub const fn get_n(&self) -> usize { self.used.len() } #[doc(hidden)] pub fn increment_n(&mut self) { self.used.push(false); } } impl Iterator for UniqueIndices { type Item = Vec; fn next(&mut self) -> Option> { if self.done { None } else if self.first { self.first = false; Some(self.indices.clone()) } else if fixed_length_unique_indices_helper(&mut self.indices, &mut self.used) { self.done = true; None } else { Some(self.indices.clone()) } } } #[doc(hidden)] pub fn unique_indices(n: usize, k: usize) -> UniqueIndices { UniqueIndices { done: n == 0 && k != 0, first: true, indices: (0..k).collect_vec(), used: repeat_n(true, k) .chain(repeat_n(false, n - k)) .collect_vec(), } } /// Generates all [`Vec`]s of elements from an iterator, where the [`Vec`]s are of a fixed length /// and have no repetitions. #[derive(Clone)] pub struct LexUniqueVecsFixedLength where I::Item: Clone, { first: bool, xs: IteratorCache, indices: UniqueIndices, } impl Iterator for LexUniqueVecsFixedLength where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { if self.first { if !self.indices.used.is_empty() && self.xs.get(self.indices.get_n() - 1).is_none() { self.indices.done = true; } self.first = false; } if self.xs.get(self.indices.get_n()).is_some() { self.indices.increment_n(); } self.indices.next().map(|indices| { indices .into_iter() .map(|i| self.xs.assert_get(i).clone()) .collect_vec() }) } } /// Generates [`Vec`]s of a given length with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The order is lexicographic with respect to the order of the element iterator. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is /// $$ /// (n)_ k = \prod_ {i=0}^{k-1}(n - i) = frac{n!}{(n-k)!}. /// $$ /// /// If $k$ is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_unique_vecs_fixed_length; /// /// let xss = lex_unique_vecs_fixed_length(4, 1..=6) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2, 3, 4], /// &[1, 2, 3, 5], /// &[1, 2, 3, 6], /// &[1, 2, 4, 3], /// &[1, 2, 4, 5], /// &[1, 2, 4, 6], /// &[1, 2, 5, 3], /// &[1, 2, 5, 4], /// &[1, 2, 5, 6], /// &[1, 2, 6, 3], /// &[1, 2, 6, 4], /// &[1, 2, 6, 5], /// &[1, 3, 2, 4], /// &[1, 3, 2, 5], /// &[1, 3, 2, 6], /// &[1, 3, 4, 2], /// &[1, 3, 4, 5], /// &[1, 3, 4, 6], /// &[1, 3, 5, 2], /// &[1, 3, 5, 4], /// ] /// ); /// ``` #[inline] pub fn lex_unique_vecs_fixed_length(k: u64, xs: I) -> LexUniqueVecsFixedLength where I::Item: Clone, { let k = usize::exact_from(k); LexUniqueVecsFixedLength { first: true, xs: IteratorCache::new(xs), // Initial n is k, but will grow to reach actual n (or forever, if n is infinite) indices: unique_indices(k, k), } } /// Generates all [`Vec`]s of elements from an iterator in shortlex order, where the [`Vec`]s have /// no repetitions. #[derive(Clone)] pub struct ShortlexUniqueVecs where I::Item: Clone, { current_len: u64, max_len: u64, xs: I, current_xss: LexUniqueVecsFixedLength, } impl ShortlexUniqueVecs where I::Item: Clone, { fn new(a: u64, b: u64, xs: I) -> Self { Self { current_len: a, max_len: b, xs: xs.clone(), current_xss: lex_unique_vecs_fixed_length(a, xs), } } } impl Iterator for ShortlexUniqueVecs where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { if self.current_len > self.max_len { return None; } if let Some(next) = self.current_xss.next() { Some(next) } else { self.current_len += 1; if self.current_len > self.max_len { return None; } self.current_xss = lex_unique_vecs_fixed_length(self.current_len, self.xs.clone()); if let Some(next) = self.current_xss.next() { Some(next) } else { // Prevent any further iteration self.max_len = 0; self.current_len = 1; None } } } } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length 2 and above will never be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_ {k=0}^n \frac{n!}{k!} /// $$ /// $$ /// = \\begin{cases} /// 1 & \text{if} \\quad n = 0, \\\\ /// 2 & \text{if} \\quad n = 1, \\\\ /// \operatorname{round}(en!) & \\text{otherwise}. /// \\end{cases} /// $$ /// /// See . /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_unique_vecs; /// /// let xss = shortlex_unique_vecs(1..=4).take(20).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[2], /// &[3], /// &[4], /// &[1, 2], /// &[1, 3], /// &[1, 4], /// &[2, 1], /// &[2, 3], /// &[2, 4], /// &[3, 1], /// &[3, 2], /// &[3, 4], /// &[4, 1], /// &[4, 2], /// &[4, 3], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2] /// ] /// ); /// ``` #[inline] pub fn shortlex_unique_vecs(xs: I) -> ShortlexUniqueVecs where I::Item: Clone, { shortlex_unique_vecs_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, \ell + 1)` and /// above will never be generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_ {k=\ell}^n \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_unique_vecs_min_length; /// /// let xss = shortlex_unique_vecs_min_length(2, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 1], /// &[2, 3], /// &[2, 4], /// &[3, 1], /// &[3, 2], /// &[3, 4], /// &[4, 1], /// &[4, 2], /// &[4, 3], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 3, 4], /// &[1, 4, 2], /// &[1, 4, 3], /// &[2, 1, 3], /// &[2, 1, 4] /// ] /// ); /// ``` #[inline] pub fn shortlex_unique_vecs_min_length( min_length: u64, xs: I, ) -> ShortlexUniqueVecs where I::Item: Clone, { shortlex_unique_vecs_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, a + 1)` and above /// will never be generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_unique_vecs_length_range; /// /// let xss = shortlex_unique_vecs_length_range(2, 4, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 1], /// &[2, 3], /// &[2, 4], /// &[3, 1], /// &[3, 2], /// &[3, 4], /// &[4, 1], /// &[4, 2], /// &[4, 3], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 3, 4], /// &[1, 4, 2], /// &[1, 4, 3], /// &[2, 1, 3], /// &[2, 1, 4] /// ] /// ); /// ``` #[inline] pub fn shortlex_unique_vecs_length_range( mut a: u64, mut b: u64, xs: I, ) -> ShortlexUniqueVecs where I::Item: Clone, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } shortlex_unique_vecs_length_inclusive_range(a, b - 1, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b]$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements. /// /// The [`Vec`]s are generated in order of increasing length, and within each length they are /// ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, [`Vec`]s of length `\max(2, a + 1)` and above /// will never be generated. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::shortlex_unique_vecs_length_inclusive_range; /// /// let xss = shortlex_unique_vecs_length_inclusive_range(2, 3, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[1, 4], /// &[2, 1], /// &[2, 3], /// &[2, 4], /// &[3, 1], /// &[3, 2], /// &[3, 4], /// &[4, 1], /// &[4, 2], /// &[4, 3], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 3, 4], /// &[1, 4, 2], /// &[1, 4, 3], /// &[2, 1, 3], /// &[2, 1, 4] /// ] /// ); /// ``` #[inline] pub fn shortlex_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ShortlexUniqueVecs where I::Item: Clone, { ShortlexUniqueVecs::new(a, b, xs) } fn compare_indexed_vecs_lex(xs: &[(usize, T)], ys: &[(usize, T)]) -> Ordering { let xs_len = xs.len(); let ys_len = ys.len(); for i in 0..min(xs_len, ys_len) { let o = xs[i].0.cmp(&ys[i].0); if o != Equal { return o; } } xs_len.cmp(&ys_len) } /// Generates all collections of elements from an iterator in lexicographic order, where the /// collections have no repetitions. #[derive(Clone)] pub struct LexUniqueVecs where I::Item: Clone, { done: bool, first: bool, min: usize, max: usize, xs_for_prefix: I, xs: I, phase_1_vec: Option>, xsss: Vec, I>>>, next_xss: Vec>>, } impl Iterator for LexUniqueVecs where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { if self.done { return None; } if self.first { self.first = false; return self.phase_1_vec.clone(); } if let Some(prefix) = self.phase_1_vec.as_mut() && prefix.len() < self.max { if let Some(x) = self.xs_for_prefix.next() { prefix.push(x); return Some(prefix.clone()); } self.max = prefix.len(); } if self.phase_1_vec.is_some() { for k in self.min..=self.max { let mut xss = lex_unique_vecs_fixed_length(u64::exact_from(k), (0..).zip(self.xs.clone())); // Skip over first Vec of length k, which was already generated in phase 1 xss.next(); self.next_xss.push(xss.next()); self.xsss.push(xss); } self.phase_1_vec = None; } let mut min_i = None; let mut i_done = None; for i in 0..self.next_xss.len() { let choose = if let Some(xs) = &self.next_xss[i] { if let Some(min_i) = min_i { let ys: &Option> = &self.next_xss[min_i]; compare_indexed_vecs_lex(xs, ys.as_ref().unwrap()) == Less } else { true } } else { i_done = Some(i); false }; if choose { min_i = Some(i); } } if let Some(i) = min_i { self.next_xss.push(self.xsss[i].next()); let xs = self .next_xss .swap_remove(i) .map(|xs| xs.into_iter().map(|p| p.1).collect()); if let Some(i_done) = i_done { self.xsss.remove(i_done); self.next_xss.remove(i_done); } xs } else { self.done = true; None } } } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_ {k=0}^n \frac{n!}{k!} /// $$ /// $$ /// = \\begin{cases} /// 1 & \text{if} \\quad n = 0, \\\\ /// 2 & \text{if} \\quad n = 1, \\\\ /// \operatorname{round}(en!) & \\text{otherwise}. /// \\end{cases} /// $$ /// /// See . /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_unique_vecs; /// /// let xss = lex_unique_vecs(1..=4).take(20).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[1, 2], /// &[1, 2, 3], /// &[1, 2, 3, 4], /// &[1, 2, 4], /// &[1, 2, 4, 3], /// &[1, 3], /// &[1, 3, 2], /// &[1, 3, 2, 4], /// &[1, 3, 4], /// &[1, 3, 4, 2], /// &[1, 4], /// &[1, 4, 2], /// &[1, 4, 2, 3], /// &[1, 4, 3], /// &[1, 4, 3, 2], /// &[2], /// &[2, 1], /// &[2, 1, 3] /// ] /// ); /// ``` #[inline] pub fn lex_unique_vecs(xs: I) -> LexUniqueVecs where I::Item: Clone, { lex_unique_vecs_length_inclusive_range(0, u64::MAX, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_unique_vecs_min_length; /// /// let xss = lex_unique_vecs_min_length(2, 1..=4).take(20).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 3, 4], /// &[1, 2, 4], /// &[1, 2, 4, 3], /// &[1, 3], /// &[1, 3, 2], /// &[1, 3, 2, 4], /// &[1, 3, 4], /// &[1, 3, 4, 2], /// &[1, 4], /// &[1, 4, 2], /// &[1, 4, 2, 3], /// &[1, 4, 3], /// &[1, 4, 3, 2], /// &[2, 1], /// &[2, 1, 3], /// &[2, 1, 3, 4], /// &[2, 1, 4], /// &[2, 1, 4, 3] /// ] /// ); /// ``` #[inline] pub fn lex_unique_vecs_min_length(min_length: u64, xs: I) -> LexUniqueVecs where I::Item: Clone, { lex_unique_vecs_length_inclusive_range(min_length, u64::MAX, xs) } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_unique_vecs_length_range; /// /// let xss = lex_unique_vecs_length_range(2, 4, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3], /// &[1, 3, 2], /// &[1, 3, 4], /// &[1, 4], /// &[1, 4, 2], /// &[1, 4, 3], /// &[2, 1], /// &[2, 1, 3], /// &[2, 1, 4], /// &[2, 3], /// &[2, 3, 1], /// &[2, 3, 4], /// &[2, 4], /// &[2, 4, 1], /// &[2, 4, 3], /// &[3, 1], /// &[3, 1, 2] /// ] /// ); /// ``` #[inline] pub fn lex_unique_vecs_length_range( mut a: u64, mut b: u64, xs: I, ) -> LexUniqueVecs where I::Item: Clone, { if b == 0 { // Transform an empty (x, 0) range into (2, 1), which is also empty but doesn't cause // overflow a = 2; b = 1; } lex_unique_vecs_length_inclusive_range(a, b - 1, xs) } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The [`Vec`]s are ordered lexicographically with respect to the order of the element iterator. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// The iterator should be finite; if it is infinite, only prefixes of the iterator will be /// generated. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_{i=\ell}^n \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_unique_vecs_min_length; /// /// let xss = lex_unique_vecs_min_length(2, 1..=4).take(20).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 2, 3], /// &[1, 2, 3, 4], /// &[1, 2, 4], /// &[1, 2, 4, 3], /// &[1, 3], /// &[1, 3, 2], /// &[1, 3, 2, 4], /// &[1, 3, 4], /// &[1, 3, 4, 2], /// &[1, 4], /// &[1, 4, 2], /// &[1, 4, 2, 3], /// &[1, 4, 3], /// &[1, 4, 3, 2], /// &[2, 1], /// &[2, 1, 3], /// &[2, 1, 3, 4], /// &[2, 1, 4], /// &[2, 1, 4, 3] /// ] /// ); /// ``` #[inline] pub fn lex_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> LexUniqueVecs where I::Item: Clone, { let a = usize::exact_from(a); let b = usize::exact_from(b); let mut xs_for_prefix = xs.clone(); let phase_1_vec = (&mut xs_for_prefix).take(a).collect_vec(); LexUniqueVecs { done: a > b || phase_1_vec.len() < a, first: true, min: a, max: b, xs_for_prefix, xs, phase_1_vec: Some(phase_1_vec), xsss: Vec::new(), next_xss: Vec::new(), } } #[doc(hidden)] #[derive(Clone)] pub struct ExhaustiveUniqueVecs2 where I::Item: Clone, { next: Option<(I::Item, I::Item)>, ps: ExhaustiveOrderedUniqueCollections>, } impl Iterator for ExhaustiveUniqueVecs2 where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { if self.next.is_some() { let (a, b) = take(&mut self.next).unwrap(); Some(vec![a, b]) } else if let Some(p) = self.ps.next() { self.next = Some((p[1].clone(), p[0].clone())); Some(p) } else { None } } } fn exhaustive_unique_vecs_2(xs: I) -> ExhaustiveUniqueVecs2 where I::Item: Clone, { ExhaustiveUniqueVecs2 { next: None, ps: exhaustive_ordered_unique_vecs_fixed_length(2, xs), } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct ExhaustiveUniqueVecsGenerator> { phantom: PhantomData<(T, I)>, } impl> ExhaustiveUniqueVecsGenerator { #[doc(hidden)] #[inline] pub const fn new() -> Self { Self { phantom: PhantomData, } } } impl> ExhaustiveDependentPairsYsGenerator, Vec, ExhaustiveVecPermutations> for ExhaustiveUniqueVecsGenerator { #[inline] fn get_ys(&self, xs: &Vec) -> ExhaustiveVecPermutations { exhaustive_vec_permutations(xs.clone()) } } /// Generates all fixed-length [`Vec`]s of elements from an iterator, where the [`Vec`]s have no /// repetitions and are ordered the same way as in the iterator. #[derive(Clone)] pub enum ExhaustiveUniqueVecsFixedLength where I::Item: Clone, { Zero(bool), One(I), Two(ExhaustiveUniqueVecs2), GreaterThanTwo( ExhaustiveDependentPairs< Vec, Vec, RulerSequence, ExhaustiveUniqueVecsGenerator, ExhaustiveOrderedUniqueCollections>, ExhaustiveVecPermutations, >, ), } impl Iterator for ExhaustiveUniqueVecsFixedLength where I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option> { match self { Self::Zero(done) => { if *done { None } else { *done = true; Some(Vec::new()) } } Self::One(xs) => xs.next().map(|x| vec![x]), Self::Two(ps) => ps.next(), Self::GreaterThanTwo(xss) => xss.next().map(|p| p.1), } } } /// Generates [`Vec`]s of a given length with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $k$ is 0, the output length is 1. /// /// If $k$ is nonzero and the input iterator is infinite, the output length is also infinite. /// /// If $k$ is nonzero and the input iterator length is $n$, the output length is /// $$ /// (n)_ k = \prod_ {i=0}^{k-1}(n - i) = frac{n!}{(n-k)!}. /// $$ /// /// If $k$ is 0, the output consists of one empty [`Vec`]. /// /// If `xs` is empty, the output is also empty, unless $k$ is 0. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_fixed_length; /// /// let xss = exhaustive_unique_vecs_fixed_length(4, 1..=6) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2, 3, 4], /// &[1, 2, 3, 5], /// &[1, 2, 4, 3], /// &[1, 2, 4, 5], /// &[1, 3, 2, 4], /// &[1, 2, 5, 3], /// &[1, 3, 4, 2], /// &[1, 3, 4, 5], /// &[1, 4, 2, 3], /// &[1, 3, 2, 5], /// &[1, 4, 3, 2], /// &[1, 2, 5, 4], /// &[2, 1, 3, 4], /// &[1, 3, 5, 2], /// &[2, 1, 4, 3], /// &[2, 3, 4, 5], /// &[2, 3, 1, 4], /// &[1, 5, 2, 3], /// &[2, 3, 4, 1], /// &[1, 4, 2, 5] /// ] /// ); /// ``` pub fn exhaustive_unique_vecs_fixed_length( k: u64, xs: I, ) -> ExhaustiveUniqueVecsFixedLength where I::Item: Clone, { match k { 0 => ExhaustiveUniqueVecsFixedLength::Zero(false), 1 => ExhaustiveUniqueVecsFixedLength::One(xs), 2 => ExhaustiveUniqueVecsFixedLength::Two(exhaustive_unique_vecs_2(xs)), k => ExhaustiveUniqueVecsFixedLength::GreaterThanTwo(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs_fixed_length(k, xs), ExhaustiveUniqueVecsGenerator::new(), )), } } /// Generates all [`Vec`]s of elements from an iterator, where the [`Vec`]s have no repetitions and /// are ordered the same way as in the iterator. #[derive(Clone)] pub struct ExhaustiveUniqueVecs where I::Item: Clone, { xs: ExhaustiveDependentPairs< Vec, Vec, RulerSequence, ExhaustiveUniqueVecsGenerator, ExhaustiveOrderedUniqueCollections>, ExhaustiveVecPermutations, >, } impl Iterator for ExhaustiveUniqueVecs where I::Item: Clone, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { self.xs.next().map(|p| p.1) } } /// Generates [`Vec`]s with elements from a single iterator, such that each [`Vec`] has no repeated /// elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_ {k=0}^n \frac{n!}{k!} /// $$ /// $$ /// = \\begin{cases} /// 1 & \text{if} \\quad n = 0, \\\\ /// 2 & \text{if} \\quad n = 1, \\\\ /// \operatorname{round}(en!) & \\text{otherwise}. /// \\end{cases} /// $$ /// /// See . /// /// If `xs` is empty, the output consists of a single empty [`Vec`]. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_unique_vecs; /// /// let xss = exhaustive_unique_vecs(1..=4).take(20).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[1], /// &[2], /// &[3], /// &[1, 2], /// &[1, 3], /// &[2, 1], /// &[1, 2, 3], /// &[3, 1], /// &[2, 3], /// &[3, 2], /// &[4], /// &[1, 3, 2], /// &[1, 4], /// &[2, 1, 3], /// &[3, 4], /// &[2, 3, 1], /// &[4, 1], /// &[3, 1, 2], /// &[2, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_unique_vecs(xs: I) -> ExhaustiveUniqueVecs where I::Item: Clone, { ExhaustiveUniqueVecs { xs: exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs(xs), ExhaustiveUniqueVecsGenerator::new(), ), } } /// Generates [`Vec`]s with a mininum length, with elements from a single iterator, such that each /// [`Vec`] has no repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If the input iterator is infinite, the output length is also infinite. /// /// If the input iterator length is $n$ and the `min_length` is $\ell$, the output length is /// $$ /// \sum_ {k=\ell}^n \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_min_length; /// /// let xss = exhaustive_unique_vecs_min_length(2, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 1], /// &[2, 3], /// &[3, 1], /// &[3, 2], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 4], /// &[2, 1, 3], /// &[2, 4], /// &[2, 3, 1], /// &[4, 1], /// &[3, 1, 2], /// &[3, 4], /// &[3, 2, 1], /// &[4, 2], /// &[1, 4, 2], /// &[1, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_unique_vecs_min_length( min_length: u64, xs: I, ) -> ExhaustiveUniqueVecs where I::Item: Clone, { ExhaustiveUniqueVecs { xs: exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs_min_length(min_length, xs), ExhaustiveUniqueVecsGenerator::new(), ), } } /// Generates [`Vec`]s, with lengths in a range $[a, b)$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $a \leq b$, the output is empty. /// /// If $a = 0$ and $b = 1$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a < b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^{b - 1} \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_length_range; /// /// let xss = exhaustive_unique_vecs_length_range(2, 4, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 1], /// &[2, 3], /// &[3, 1], /// &[3, 2], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 4], /// &[2, 1, 3], /// &[2, 4], /// &[2, 3, 1], /// &[4, 1], /// &[3, 1, 2], /// &[3, 4], /// &[3, 2, 1], /// &[4, 2], /// &[1, 4, 2], /// &[1, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_unique_vecs_length_range( a: u64, b: u64, xs: I, ) -> ExhaustiveUniqueVecs where I::Item: Clone, { ExhaustiveUniqueVecs { xs: exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs_length_range(a, b, xs), ExhaustiveUniqueVecsGenerator::new(), ), } } /// Generates [`Vec`]s, with lengths in a range $[a, b]$, with elements from a single iterator, such /// that each [`Vec`] has no repeated elements. /// /// The source iterator should not repeat any elements, but this is not enforced. /// /// If $a < b$, the output is empty. /// /// If $a = b = 0$, the output consists of a single empty [`Vec`]. /// /// If the input iterator is infinite and $0 < a \leq b$, the output length is also infinite. /// /// If the input iterator length is $n$, the output length is /// $$ /// \sum_{i=a}^b \frac{n!}{k!}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_length_inclusive_range; /// /// let xss = exhaustive_unique_vecs_length_inclusive_range(2, 3, 1..=4) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 2][..], /// &[1, 3], /// &[2, 1], /// &[2, 3], /// &[3, 1], /// &[3, 2], /// &[1, 2, 3], /// &[1, 2, 4], /// &[1, 3, 2], /// &[1, 4], /// &[2, 1, 3], /// &[2, 4], /// &[2, 3, 1], /// &[4, 1], /// &[3, 1, 2], /// &[3, 4], /// &[3, 2, 1], /// &[4, 2], /// &[1, 4, 2], /// &[1, 3, 4] /// ] /// ); /// ``` #[inline] pub fn exhaustive_unique_vecs_length_inclusive_range( a: u64, b: u64, xs: I, ) -> ExhaustiveUniqueVecs where I::Item: Clone, { ExhaustiveUniqueVecs { xs: exhaustive_dependent_pairs( ruler_sequence(), exhaustive_ordered_unique_vecs_length_inclusive_range(a, b, xs), ExhaustiveUniqueVecsGenerator::new(), ), } } /// Generates all $k$-compositions of a number: all length-$k$ [`Vec`]s of positive [`usize`]s whose /// sum is a given number. #[derive(Clone, Debug)] pub struct LexKCompositions { done: bool, first: bool, xs: Vec, } impl Iterator for LexKCompositions { type Item = Vec; fn next(&mut self) -> Option> { if self.done { return None; } else if self.first { self.first = false; return Some(self.xs.clone()); } let last_not_one_index = self.xs.iter().rposition(|&x| x != 1); if last_not_one_index.is_none() || last_not_one_index == Some(0) { self.done = true; return None; } let last_not_one_index = last_not_one_index.unwrap(); self.xs[last_not_one_index - 1] += 1; let last_not_one = self.xs[last_not_one_index]; let (last, init) = self.xs.split_last_mut().unwrap(); *last = last_not_one - 1; for x in &mut init[last_not_one_index..] { *x = 1; } Some(self.xs.clone()) } } /// Generates all $k$-compositions of a number: given $n$ and $k$, generates all length-$k$ [`Vec`]s /// of positive [`usize`]s whose sum is $n$. /// /// The [`Vec`]s are output in lexicographic order. /// /// If $k = 0$ and $n \neq 0$, or if $n < k$, then the output is empty. /// /// The output length is /// $$ /// \binom{n-1}{k-1}. /// $$ /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_k_compositions; /// /// let xss = lex_k_compositions(5, 3).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[&[1, 1, 3], &[1, 2, 2], &[1, 3, 1], &[2, 1, 2], &[2, 2, 1], &[3, 1, 1]] /// ); /// ``` pub fn lex_k_compositions(n: usize, k: usize) -> LexKCompositions { if k == 0 && n != 0 || n < k { return LexKCompositions { done: true, first: true, xs: Vec::new(), }; } let mut xs = vec![1; k]; if k != 0 { xs[k - 1] = n + 1 - k; } LexKCompositions { done: false, first: true, xs, } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct LexKCompositionsGenerator { k: usize, } impl ExhaustiveDependentPairsYsGenerator, LexKCompositions> for LexKCompositionsGenerator { #[inline] fn get_ys(&self, &n: &usize) -> LexKCompositions { lex_k_compositions(n, self.k) } } /// Generates $k$-compositions of $n$ for all $n$ in a given range: all length-$k$ [`Vec`]s of /// positive [`usize`]s whose sum is in a given range. #[derive(Clone, Debug)] pub struct ExhaustiveCombinedKCompositions { xs: ExhaustiveDependentPairs< usize, Vec, RulerSequence, LexKCompositionsGenerator, PrimitiveIntIncreasingRange, LexKCompositions, >, } impl Iterator for ExhaustiveCombinedKCompositions { type Item = Vec; #[inline] fn next(&mut self) -> Option> { self.xs.next().map(|p| p.1) } } /// Given $n_\text{min}$, $n_\text{max}$, and $k$, generates all length-$k$ [`Vec`]s of positive /// [`usize`]s whose sum is in the closed interval $[n_\text{min}, n_\text{max}]$. /// /// The output length is /// $$ /// \sum_{n=n_\text{min}}^{n_\text{max}} \binom{n-1}{k-1}. /// $$ /// /// # Panics /// Panics if $n_\text{min} > n_\text{max}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_combined_k_compositions; /// /// let xss = exhaustive_combined_k_compositions(4, 6, 3).collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[1, 1, 2], /// &[1, 1, 3], /// &[1, 2, 1], /// &[1, 1, 4], /// &[2, 1, 1], /// &[1, 2, 2], /// &[1, 3, 1], /// &[1, 2, 3], /// &[2, 1, 2], /// &[1, 3, 2], /// &[2, 2, 1], /// &[3, 1, 1], /// &[1, 4, 1], /// &[2, 1, 3], /// &[2, 2, 2], /// &[2, 3, 1], /// &[3, 1, 2], /// &[3, 2, 1], /// &[4, 1, 1] /// ] /// ); /// ``` #[inline] pub fn exhaustive_combined_k_compositions( n_min: usize, n_max: usize, k: usize, ) -> ExhaustiveCombinedKCompositions { ExhaustiveCombinedKCompositions { xs: exhaustive_dependent_pairs( ruler_sequence(), primitive_int_increasing_inclusive_range(n_min, n_max), LexKCompositionsGenerator { k }, ), } } ================================================ FILE: malachite-base/src/vecs/mod.rs ================================================ // Copyright © 2026 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 . #[cfg(feature = "random")] use crate::num::conversion::traits::ExactFrom; #[cfg(feature = "random")] use crate::num::random::{RandomUnsignedsLessThan, random_unsigneds_less_than}; #[cfg(feature = "random")] use crate::random::Seed; use crate::slices::advance_indices; use alloc::string::String; use alloc::vec::Vec; use core::str::FromStr; #[cfg(feature = "random")] use rand::prelude::SliceRandom; #[cfg(feature = "random")] use rand_chacha::ChaCha20Rng; /// Inserts several copies of a value at the left (beginning) of a [`Vec`]. /// /// Using this function is more efficient than inserting the values one by one. /// /// # Worst-case complexity /// $T(n) = O(n + m)$ /// /// $M(n) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ = `xs.len()` before the function is called, and /// $m$ = `pad_size`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_pad_left; /// /// let mut xs = vec![1, 2, 3]; /// vec_pad_left::(&mut xs, 5, 10); /// assert_eq!(xs, [10, 10, 10, 10, 10, 1, 2, 3]); /// ``` pub fn vec_pad_left(xs: &mut Vec, pad_size: usize, pad_value: T) { let old_len = xs.len(); xs.resize(old_len + pad_size, pad_value); for i in (0..old_len).rev() { xs.swap(i, i + pad_size); } } /// Deletes several values from the left (beginning) of a [`Vec`]. /// /// Using this function is more efficient than deleting the values one by one. /// /// # Worst-case complexity /// $T(n) = O(\operatorname{max}(1, n - m))$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, $n$ = `xs.len()` before the function is called, and /// $m$ = `delete_size`. /// /// # Panics /// Panics if `delete_size` is greater than `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_delete_left; /// /// let mut xs = vec![1, 2, 3, 4, 5]; /// vec_delete_left::(&mut xs, 3); /// assert_eq!(xs, [4, 5]); /// ``` pub fn vec_delete_left(xs: &mut Vec, delete_size: usize) { let old_len = xs.len(); xs.copy_within(delete_size..old_len, 0); xs.truncate(old_len - delete_size); } /// Converts a string to an `Vec`, where `T` implements [`FromStr`]. /// /// If the string does not represent a valid `Vec`, `None` is returned. /// /// If `T` does not implement [`FromStr`], try using [`vec_from_str_custom`] instead. /// /// Substrings representing `T`s may contain commas. Sometimes this may lead to ambiguities: for /// example, the two `Vec<&str>`s `vec!["a, b"]` and `vec!["a", "b"]` both have the string /// representation `"[a, b]"`. The parser is greedy, so it will interpet this string as `vec!["a", /// "b"]`. /// /// # Examples /// ``` /// use malachite_base::nevers::Never; /// use malachite_base::vecs::vec_from_str; /// /// assert_eq!(vec_from_str::("[]"), Some(vec![])); /// assert_eq!(vec_from_str("[5, 6, 7]"), Some(vec![5, 6, 7])); /// assert_eq!( /// vec_from_str("[false, false, true]"), /// Some(vec![false, false, true]) /// ); /// assert_eq!(vec_from_str::("[false, false, true"), None); /// ``` #[inline] pub fn vec_from_str(src: &str) -> Option> { vec_from_str_custom(&(|t| t.parse().ok()), src) } /// Converts a string to an `Vec`, given a function to parse a string into a `T`. /// /// If the string does not represent a valid `Option`, `None` is returned. /// /// If `f` just uses [`FromStr::from_str`], you can use [`vec_from_str`] instead. /// /// Substrings representing `T`s may contain commas. Sometimes this may lead to ambiguities: for /// example, the two `Vec<&str>`s `vec!["a, b"]` and `vec!["a", "b"]` both have the string /// representation `"[a, b]"`. The parser is greedy, so it will interpet this string as `vec!["a", /// "b"]`. /// /// # Examples /// ``` /// use malachite_base::options::option_from_str; /// use malachite_base::orderings::ordering_from_str; /// use malachite_base::vecs::{vec_from_str, vec_from_str_custom}; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// vec_from_str_custom(&ordering_from_str, "[Less, Greater]"), /// Some(vec![Less, Greater]), /// ); /// assert_eq!( /// vec_from_str_custom(&option_from_str, "[Some(false), None]"), /// Some(vec![Some(false), None]), /// ); /// assert_eq!( /// vec_from_str_custom(&vec_from_str, "[[], [3], [2, 5]]"), /// Some(vec![vec![], vec![3], vec![2, 5]]), /// ); /// assert_eq!( /// vec_from_str_custom(&option_from_str::, "[Some(fals), None]"), /// None /// ); /// ``` pub fn vec_from_str_custom(f: &dyn Fn(&str) -> Option, src: &str) -> Option> { if !src.starts_with('[') || !src.ends_with(']') { return None; } let mut xs = Vec::new(); let mut buffer = String::new(); for token in src[1..src.len() - 1].split(", ") { if !buffer.is_empty() { buffer.push_str(", "); } buffer.push_str(token); if let Some(x) = f(&buffer) { xs.push(x); buffer.clear(); } } if buffer.is_empty() { Some(xs) } else { None } } #[cfg(feature = "random")] /// Uniformly generates a random value from a nonempty [`Vec`]. /// /// This `struct` is created by [`random_values_from_vec`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomValuesFromVec { xs: Vec, indices: RandomUnsignedsLessThan, } #[cfg(feature = "random")] impl Iterator for RandomValuesFromVec { type Item = T; #[inline] fn next(&mut self) -> Option { Some(self.xs[usize::exact_from(self.indices.next().unwrap())].clone()) } } #[cfg(feature = "random")] /// Uniformly generates a random value from a nonempty [`Vec`]. /// /// The iterator owns the data. It may be more convenient for the iterator to return references to a /// pre-existing slice, in which case you may use /// [`random_values_from_slice`](crate::slices::random_values_from_slice) instead. /// /// The output length is infinite. /// /// $P(x) = 1/n$, where $n$ is `xs.len()`. /// /// # Panics /// Panics if `xs` is empty. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random_values_from_vec; /// /// let xs = vec![2, 3, 5, 7, 11]; /// assert_eq!( /// random_values_from_vec(EXAMPLE_SEED, xs) /// .take(10) /// .collect_vec(), /// &[3, 7, 3, 5, 11, 3, 5, 11, 2, 2] /// ); /// ``` #[inline] pub fn random_values_from_vec(seed: Seed, xs: Vec) -> RandomValuesFromVec { assert!(!xs.is_empty(), "empty Vec"); let indices = random_unsigneds_less_than(seed, u64::exact_from(xs.len())); RandomValuesFromVec { xs, indices } } /// Generates every permutation of a [`Vec`]. /// /// This `struct` is created by [`exhaustive_vec_permutations`]; see its documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExhaustiveVecPermutations { xs: Vec, indices: Vec, done: bool, } impl Iterator for ExhaustiveVecPermutations { type Item = Vec; fn next(&mut self) -> Option> { if self.done { None } else { let out = Some(self.indices.iter().map(|&i| self.xs[i].clone()).collect()); self.done = advance_indices(&mut self.indices); out } } } /// Generates every permutation of a [`Vec`]. /// /// The permutations are [`Vec`]s of cloned items. It may be more convenient for the iterator to /// return references to a slice, in which case you may use /// [`exhaustive_slice_permutations`](crate::slices::exhaustive_slice_permutations) instead. /// /// The permutations are generated in lexicographic order with respect to the ordering in the /// [`Vec`]. /// /// The output length is $n!$, where $n$ is `xs.len()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive_vec_permutations; /// /// let css: Vec = exhaustive_vec_permutations(vec!['a', 'b', 'c', 'd']) /// .map(|ds| ds.into_iter().collect()) /// .collect(); /// assert_eq!( /// css.iter().map(String::as_str).collect_vec().as_slice(), /// [ /// "abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac", /// "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca", /// "dcab", "dcba" /// ] /// ); /// ``` pub fn exhaustive_vec_permutations(xs: Vec) -> ExhaustiveVecPermutations { let len = xs.len(); ExhaustiveVecPermutations { xs, indices: (0..len).collect(), done: false, } } #[cfg(feature = "random")] /// Uniformly generates a random [`Vec`] of values cloned from an original [`Vec`]. /// /// This `struct` is created by [`random_vec_permutations`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomVecPermutations { xs: Vec, indices: Vec, rng: ChaCha20Rng, } #[cfg(feature = "random")] impl Iterator for RandomVecPermutations { type Item = Vec; fn next(&mut self) -> Option> { self.indices.shuffle(&mut self.rng); Some(self.indices.iter().map(|&i| self.xs[i].clone()).collect()) } } #[cfg(feature = "random")] /// Uniformly generates a random [`Vec`] of values cloned from an original [`Vec`]. /// /// The permutations are [`Vec`]s of cloned items. It may be more convenient for the iterator to /// return references to a slice, in which case you may use /// [`random_slice_permutations`](crate::slices::random_slice_permutations) instead. /// /// The output length is infinite. /// /// $P(p) = 1/n!$, where $n$ is `xs.len()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random_vec_permutations; /// /// let css: Vec = random_vec_permutations(EXAMPLE_SEED, vec!['a', 'b', 'c', 'd']) /// .take(20) /// .map(|ds| ds.into_iter().collect()) /// .collect(); /// assert_eq!( /// css.iter().map(String::as_str).collect_vec().as_slice(), /// [ /// "dacb", "cbad", "cdab", "cbad", "cdab", "bcda", "bcda", "acbd", "bcda", "dbca", "bdac", /// "dbac", "dbca", "bcad", "cadb", "dacb", "acbd", "dbac", "bdca", "abdc" /// ] /// ); /// ``` pub fn random_vec_permutations(seed: Seed, xs: Vec) -> RandomVecPermutations { let len = xs.len(); RandomVecPermutations { xs, indices: (0..len).collect(), rng: seed.get_rng(), } } /// Iterators that generate [`Vec`]s without repetition. /// /// # lex_vecs_length_2 /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::lex_vecs_length_2; /// /// let xss = lex_vecs_length_2( /// ['a', 'b', 'c'].iter().cloned(), /// ['x', 'y', 'z'].iter().cloned(), /// ) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &['a', 'x'], /// &['a', 'y'], /// &['a', 'z'], /// &['b', 'x'], /// &['b', 'y'], /// &['b', 'z'], /// &['c', 'x'], /// &['c', 'y'], /// &['c', 'z'] /// ] /// ); /// ``` /// /// # lex_vecs_fixed_length_2_inputs /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::vecs::exhaustive::lex_vecs_fixed_length_2_inputs; /// /// // We are generating length-3 `Vec`s of `char`s using two input iterators. The first iterator /// // (with index 0) produces all ASCII `char`s, and the second (index 1) produces the three /// // `char`s `'x'`, `'y'`, and `'z'`. The elements of `output_types` are 0, 1, and 0, meaning that /// // the first element of the output `Vec`s will be taken from iterator 0, the second element from /// // iterator 1, and the third also from iterator 0. /// let xss = lex_vecs_fixed_length_2_inputs( /// exhaustive_ascii_chars(), /// ['x', 'y', 'z'].iter().cloned(), /// &[0, 1, 0], /// ); /// let xss_prefix = xss.take(20).collect_vec(); /// assert_eq!( /// xss_prefix /// .iter() /// .map(Vec::as_slice) /// .collect_vec() /// .as_slice(), /// &[ /// &['a', 'x', 'a'], /// &['a', 'x', 'b'], /// &['a', 'x', 'c'], /// &['a', 'x', 'd'], /// &['a', 'x', 'e'], /// &['a', 'x', 'f'], /// &['a', 'x', 'g'], /// &['a', 'x', 'h'], /// &['a', 'x', 'i'], /// &['a', 'x', 'j'], /// &['a', 'x', 'k'], /// &['a', 'x', 'l'], /// &['a', 'x', 'm'], /// &['a', 'x', 'n'], /// &['a', 'x', 'o'], /// &['a', 'x', 'p'], /// &['a', 'x', 'q'], /// &['a', 'x', 'r'], /// &['a', 'x', 's'], /// &['a', 'x', 't'] /// ] /// ); /// ``` /// /// # exhaustive_vecs_length_2 /// ``` /// use itertools::Itertools; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_length_2; /// /// let xss = exhaustive_vecs_length_2( /// ['a', 'b', 'c'].iter().cloned(), /// ['x', 'y', 'z'].iter().cloned(), /// ) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &['a', 'x'], /// &['a', 'y'], /// &['b', 'x'], /// &['b', 'y'], /// &['a', 'z'], /// &['b', 'z'], /// &['c', 'x'], /// &['c', 'y'], /// &['c', 'z'] /// ] /// ); /// ``` /// /// # exhaustive_vecs_fixed_length_2_inputs /// ``` /// use itertools::Itertools; /// use malachite_base::chars::exhaustive::exhaustive_ascii_chars; /// use malachite_base::iterators::bit_distributor::BitDistributorOutputType; /// use malachite_base::vecs::exhaustive::exhaustive_vecs_fixed_length_2_inputs; /// /// // We are generating length-3 `Vec`s of `char`s using two input iterators. The first iterator /// // (with index 0) produces all ASCII `char`s, and the second (index 1) produces the three /// // `char`s `'x'`, `'y'`, and `'z'`. The elements of `output_types` have the indices 0, 1, and 0, /// // meaning that the first element of the output `Vec`s will be taken from iterator 0, the second /// // element from iterator 1, and the third also from iterator 0. The third element has a tiny /// // output type, so it will grow more slowly than the other two elements (though it doesn't look /// // that way from the first few `Vec`s). /// let xss = exhaustive_vecs_fixed_length_2_inputs( /// exhaustive_ascii_chars(), /// ['x', 'y', 'z'].iter().cloned(), /// &[ /// (BitDistributorOutputType::normal(1), 0), /// (BitDistributorOutputType::normal(1), 1), /// (BitDistributorOutputType::tiny(), 0), /// ], /// ); /// let xss_prefix = xss.take(20).collect_vec(); /// assert_eq!( /// xss_prefix /// .iter() /// .map(Vec::as_slice) /// .collect_vec() /// .as_slice(), /// &[ /// &['a', 'x', 'a'], /// &['a', 'x', 'b'], /// &['a', 'x', 'c'], /// &['a', 'x', 'd'], /// &['a', 'y', 'a'], /// &['a', 'y', 'b'], /// &['a', 'y', 'c'], /// &['a', 'y', 'd'], /// &['a', 'x', 'e'], /// &['a', 'x', 'f'], /// &['a', 'x', 'g'], /// &['a', 'x', 'h'], /// &['a', 'y', 'e'], /// &['a', 'y', 'f'], /// &['a', 'y', 'g'], /// &['a', 'y', 'h'], /// &['b', 'x', 'a'], /// &['b', 'x', 'b'], /// &['b', 'x', 'c'], /// &['b', 'x', 'd'] /// ] /// ); /// ``` pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`Vec`]s randomly. /// /// # random_vecs_length_2 /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::random_char_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_length_2; /// /// let xss = random_vecs_length_2( /// EXAMPLE_SEED, /// &|seed| random_char_inclusive_range(seed, 'a', 'c'), /// &|seed| random_char_inclusive_range(seed, 'x', 'z'), /// ) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &['b', 'z'], /// &['b', 'x'], /// &['b', 'z'], /// &['b', 'y'], /// &['c', 'x'], /// &['a', 'z'], /// &['a', 'z'], /// &['a', 'z'], /// &['c', 'z'], /// &['a', 'y'], /// &['c', 'x'], /// &['a', 'x'], /// &['c', 'z'], /// &['a', 'z'], /// &['c', 'x'], /// &['c', 'x'], /// &['c', 'y'], /// &['b', 'y'], /// &['a', 'x'], /// &['c', 'x'] /// ] /// ); /// ``` /// /// # random_vecs_fixed_length_2_inputs /// ``` /// use itertools::Itertools; /// use malachite_base::chars::random::{random_ascii_chars, random_char_inclusive_range}; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_fixed_length_2_inputs; /// /// // We are generating length-3 `Vec`s of `char`s using two input iterators. The first iterator /// // (with index 0) produces random ASCII `char`s, and the second (index 1) produces the three /// // `char`s `'x'`, `'y'`, and `'z'`, uniformly at random. The elements of `output_types` are 0, /// // 1, and 0, meaning that the first element of the output `Vec`s will be taken from iterator 0, /// // the second element from iterator 1, and the third also from iterator 0. /// let xss = random_vecs_fixed_length_2_inputs( /// EXAMPLE_SEED, /// &random_ascii_chars, /// &|seed| random_char_inclusive_range(seed, 'x', 'z'), /// &[0, 1, 0], /// ) /// .take(20) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &['U', 'z', '\u{16}'], /// &[' ', 'x', 'D'], /// &['<', 'z', ']'], /// &['a', 'y', 'e'], /// &['_', 'x', 'M'], /// &[',', 'z', 'O'], /// &['\u{1d}', 'z', 'V'], /// &['(', 'z', '\u{10}'], /// &['&', 'z', 'U'], /// &['{', 'y', 'P'], /// &['-', 'x', 'K'], /// &['Z', 'x', '\u{4}'], /// &['X', 'z', '\u{19}'], /// &['_', 'z', ','], /// &['\u{1d}', 'x', ','], /// &['?', 'x', '\''], /// &['[', 'y', 'N'], /// &['|', 'y', '}'], /// &['*', 'x', '\u{15}'], /// &['z', 'x', 't'] /// ] /// ); /// ``` pub mod random; ================================================ FILE: malachite-base/src/vecs/random.rs ================================================ // Copyright © 2026 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 crate::num::conversion::traits::ExactFrom; use crate::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use crate::num::random::{ RandomUnsignedInclusiveRange, RandomUnsignedRange, random_unsigned_inclusive_range, random_unsigned_range, }; use crate::random::Seed; use crate::sets::random::{ RandomBTreeSets, RandomBTreeSetsFixedLength, random_b_tree_sets_fixed_length, random_b_tree_sets_from_length_iterator, }; use crate::vecs::exhaustive::validate_oi_map; use std::cmp::Ordering::*; use std::collections::HashMap; use std::hash::Hash; use std::iter::{Repeat, repeat}; /// Generates random [`Vec`]s of a given length using elements from a single iterator. /// /// This `struct` is created by [`random_vecs_fixed_length_from_single`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct RandomFixedLengthVecsFromSingle { len: u64, xs: I, } impl Iterator for RandomFixedLengthVecsFromSingle { type Item = Vec; #[inline] fn next(&mut self) -> Option> { Some((&mut self.xs).take(usize::exact_from(self.len)).collect()) } } /// Randomly generates [`Vec`]s of a given length using elements from a single iterator. /// /// The probability of a particular length-$n$ [`Vec`] being generated is the product of the /// probabilities of each of its elements. /// /// If `len` is 0, the output consists of the empty list, repeated. /// /// `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_fixed_length_from_single; /// /// let xss = random_vecs_fixed_length_from_single( /// 2, /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 100), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[95, 24], /// &[99, 71], /// &[93, 53], /// &[85, 34], /// &[48, 2], /// &[55, 11], /// &[48, 18], /// &[90, 93], /// &[67, 93], /// &[93, 95] /// ] /// ); /// ``` #[inline] pub const fn random_vecs_fixed_length_from_single( len: u64, xs: I, ) -> RandomFixedLengthVecsFromSingle { RandomFixedLengthVecsFromSingle { len, xs } } /// Defines random fixed-length [`Vec`] generators. /// /// Malachite provides [`random_vecs_length_2`] and [`random_vecs_fixed_length_2_inputs`], but you /// can also define `random_vecs_length_3`, `random_vecs_length_4`, and so on, and /// `random_vecs_fixed_length_3_inputs`, `random_vecs_fixed_length_4_inputs`, and so on, in your /// program using the code below. The documentation for [`random_vecs_length_2`] and /// [`random_vecs_fixed_length_2_inputs`] describes these other functions as well. /// /// See usage examples [here](self#lex_vecs_length_2) and /// [here](self#random_vecs_fixed_length_2_inputs). /// /// ``` /// use malachite_base::random::Seed; /// use malachite_base::random_vecs_fixed_length; /// use malachite_base::vecs::exhaustive::validate_oi_map; /// /// 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] /// ); /// random_vecs_fixed_length!( /// (pub(crate)), /// RandomFixedLengthVecs4Inputs, /// random_vecs_fixed_length_4_inputs, /// random_vecs_length_4, /// [0, I, xs, xs_gen], /// [1, J, ys, ys_gen], /// [2, K, zs, zs_gen], /// [3, L, ws, ws_gen] /// ); /// random_vecs_fixed_length!( /// (pub(crate)), /// RandomFixedLengthVecs5Inputs, /// random_vecs_fixed_length_5_inputs, /// random_vecs_length_5, /// [0, I, xs, xs_gen], /// [1, J, ys, ys_gen], /// [2, K, zs, zs_gen], /// [3, L, ws, ws_gen], /// [4, M, vs, vs_gen] /// ); /// random_vecs_fixed_length!( /// (pub(crate)), /// RandomFixedLengthVecs6Inputs, /// random_vecs_fixed_length_6_inputs, /// random_vecs_length_6, /// [0, I, xs, xs_gen], /// [1, J, ys, ys_gen], /// [2, K, zs, zs_gen], /// [3, L, ws, ws_gen], /// [4, M, vs, vs_gen], /// [5, N, us, us_gen] /// ); /// random_vecs_fixed_length!( /// (pub(crate)), /// RandomFixedLengthVecs7Inputs, /// random_vecs_fixed_length_7_inputs, /// random_vecs_length_7, /// [0, I, xs, xs_gen], /// [1, J, ys, ys_gen], /// [2, K, zs, zs_gen], /// [3, L, ws, ws_gen], /// [4, M, vs, vs_gen], /// [5, N, us, us_gen], /// [6, O, ts, ts_gen] /// ); /// random_vecs_fixed_length!( /// (pub(crate)), /// RandomFixedLengthVecs8Inputs, /// random_vecs_fixed_length_8_inputs, /// random_vecs_length_8, /// [0, I, xs, xs_gen], /// [1, J, ys, ys_gen], /// [2, K, zs, zs_gen], /// [3, L, ws, ws_gen], /// [4, M, vs, vs_gen], /// [5, N, us, us_gen], /// [6, O, ts, ts_gen], /// [7, P, ss, ss_gen] /// ); /// ``` #[macro_export] macro_rules! random_vecs_fixed_length { ( ($($vis:tt)*), $random_struct: ident, $random_fn: ident, $random_1_to_1_fn: ident, $([$i: expr, $it: ident, $xs: ident, $xs_gen: ident]),* ) => { /// This documentation applies not only to `RandomFixedLengthVecs2Inputs`, but also to /// `RandomFixedLengthVecs3Inputs`, `RandomFixedLengthVecs4Inputs`, and so on. See /// [`random_vecs_fixed_length`] for more information. /// /// Generates random [`Vec`]s of a given length using elements from $m$ iterators. /// /// The fixed length $n$ of the [`Vec`]s is greater than or equal to $m$. #[derive(Clone, Debug)] $($vis)* struct $random_struct),*> { $($xs: $it,)* output_to_input_map: Vec, } impl),*> Iterator for $random_struct { type Item = Vec; #[inline] fn next(&mut self) -> Option> { let mut out = Vec::with_capacity(self.output_to_input_map.len()); for &i in &self.output_to_input_map { out.push( match i { $( $i => self.$xs.next(), )* _ => unreachable!(), } .unwrap(), ); } Some(out) } } /// This documentation applies not only to `random_vecs_fixed_length_2_inputs`, but also to /// `random_vecs_fixed_length_3_inputs`, `random_vecs_fixed_length_4_inputs`, and so on. See /// [`random_vecs_fixed_length`] for more information. /// /// Generates random length-$n$ [`Vec`]s using elements from $m$ iterators, where $m \leq /// n$. /// /// The `output_to_input_map` parameter defines which iterators are mapped to which slot in /// the output [`Vec`]s. The length of the output [`Vec`]s, $n$, is specified by the length /// of `output_to_input_map`. /// /// The $i$th element of `output_to_input_map` is an index from 0 to $m-1$ which specifies /// which iterator the $i$th output slot is populated with. Together, the elements must /// include all indices from 0 to $m-1$, inclusive, possibly with repetitions. /// /// `xs` must be infinite. /// /// # Examples /// See [here](self#random_vecs_fixed_length_2_inputs). #[allow(dead_code)] $($vis)* fn $random_fn),*>( seed: Seed, $($xs_gen: &dyn Fn(Seed) -> $it,)* output_to_input_map: &[usize], ) -> $random_struct { $( let _max_input_index = $i; )* validate_oi_map(_max_input_index, output_to_input_map.iter().cloned()); $random_struct { $($xs: $xs_gen(seed.fork(stringify!($xs))),)* output_to_input_map: output_to_input_map.to_vec(), } } /// This documentation applies not only to `random_vecs_length_2`, but also to /// `random_vecs_length_3`, `random_vecs_length_4`, and so on. See /// [`random_vecs_fixed_length`] for more information. /// /// Generates random length-$n$ [`Vec`]s with elements from $n$ iterators. /// /// The probability of a particular length-$n$ [`Vec`] being generated is the product of the /// probabilities of each of its elements. /// /// `xs`, `ys`, `zs`, ... must be infinite. /// /// # Examples /// See [here](self#random_vecs_length_2). #[allow(dead_code)] #[inline] $($vis)* fn $random_1_to_1_fn),*>( seed: Seed, $($xs_gen: &dyn Fn(Seed) -> $it,)* ) -> $random_struct { $random_fn(seed, $($xs_gen,)* &[$($i),*]) } } } random_vecs_fixed_length!( (pub), RandomFixedLengthVecs2Inputs, random_vecs_fixed_length_2_inputs, random_vecs_length_2, [0, I, xs, xs_gen], [1, J, ys, ys_gen] ); /// Generates random [`Vec`]s using elements from an iterator and with lengths from another /// iterator. #[derive(Clone, Debug)] pub struct RandomVecs, J: Iterator> { lengths: I, xs: J, } impl, J: Iterator> Iterator for RandomVecs { type Item = Vec; fn next(&mut self) -> Option> { Some( (&mut self.xs) .take(usize::exact_from(self.lengths.next().unwrap())) .collect(), ) } } /// Generates random [`Vec`]s using elements from an iterator and with lengths from another /// iterator. /// /// The probability of a particular [`Vec`] being generated is the product of the probabilities of /// each of its elements, multiplied by the probability of its length being generated. /// /// `lengths` and `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_from_length_iterator; /// use malachite_base::vecs::random_values_from_vec; /// /// let xs = random_vecs_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11][..], /// &[136, 200, 235, 134], /// &[203, 223], /// &[38, 235, 217, 177], /// &[162, 32, 166, 234], /// &[30, 218], /// &[], /// &[90, 106], /// &[], /// &[9, 216, 204, 151], /// &[213, 97, 253, 78], /// &[91, 39], /// &[191, 175, 170, 232], /// &[233, 2], /// &[35, 22, 217, 198], /// &[114, 17, 32, 173], /// &[114, 65, 121, 222], /// &[], /// &[173, 25, 144, 148], /// &[] /// ] /// ); /// ``` #[inline] pub fn random_vecs_from_length_iterator, J: Iterator>( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, ) -> RandomVecs { RandomVecs { lengths: lengths_gen(seed.fork("lengths")), xs: xs_gen(seed.fork("xs")), } } /// Generates random [`Vec`]s using elements from an iterator. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = \frac{m^n}{(m+1)^{n+1}}\prod_{i=0}^{n-1}P(x_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs; /// /// let xs = random_vecs(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32], /// &[166, 234, 30, 218], /// &[90, 106, 9, 216], /// &[204], /// &[], /// &[151, 213, 97, 253, 78], /// &[91, 39], /// &[191, 175, 170, 232], /// &[], /// &[233, 2, 35, 22, 217, 198], /// &[], /// &[], /// &[114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144], /// &[148, 79, 115, 52, 73, 69, 137, 91], /// &[], /// &[153, 178, 112], /// &[], /// &[34, 95, 106, 167, 197], /// &[130, 168, 122, 207, 172, 177, 86, 150, 221] /// ] /// ); /// ``` #[inline] pub fn random_vecs( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomVecs, I> { random_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, xs_gen, ) } /// Generates random [`Vec`]s with a minimum length, using elements from an iterator. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than /// `min_length`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = \\begin{cases} /// \frac{(m-a)^{n-a}}{(m+1-a)^{n+1-a}}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad n\geq a, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $a$ is `min_length`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less /// than or equal to `min_length`, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_min_length; /// /// let xs = random_vecs_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::, 6, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11][..], /// &[136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32, 166, 234, 30, 218], /// &[90, 106, 9, 216, 204, 151], /// &[213, 97, 253, 78, 91, 39], /// &[191, 175, 170], /// &[232, 233], /// &[2, 35, 22, 217, 198, 114, 17], /// &[32, 173, 114, 65], /// &[121, 222, 173, 25, 144, 148], /// &[79, 115], /// &[52, 73, 69, 137, 91, 153, 178, 112], /// &[34, 95], /// &[106, 167], /// &[197, 130, 168, 122, 207, 172, 177, 86, 150, 221, 218, 101, 115], /// &[74, 9, 123, 109, 52, 201, 159, 247, 250, 48], /// &[133, 235], /// &[196, 40, 97, 104, 68], /// &[190, 216], /// &[7, 216, 157, 43, 43, 112, 217], /// &[24, 11, 103, 211, 84, 135, 55, 29, 206, 89, 65] /// ] /// ); /// ``` #[inline] pub fn random_vecs_min_length( seed: Seed, min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomVecs, I> { random_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, xs_gen, ) } /// Generates random [`Vec`]s with lengths in $[a, b)$, using elements from an iterator. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = \\begin{cases} /// \frac{1}{b-a}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_length_range; /// /// let xs = random_vecs_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11, 136][..], /// &[200, 235, 134, 203], /// &[223, 38, 235], /// &[217, 177, 162, 32], /// &[166, 234, 30, 218], /// &[90, 106, 9], /// &[216, 204], /// &[151, 213, 97], /// &[253, 78], /// &[91, 39, 191, 175], /// &[170, 232, 233, 2], /// &[35, 22, 217], /// &[198, 114, 17, 32], /// &[173, 114, 65], /// &[121, 222, 173, 25], /// &[144, 148, 79, 115], /// &[52, 73, 69, 137], /// &[91, 153], /// &[178, 112, 34, 95], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_vecs_length_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomVecs, I> { random_vecs_from_length_iterator(seed, &|seed_2| random_unsigned_range(seed_2, a, b), xs_gen) } /// Generates random [`Vec`]s with lengths in $[a, b]$, using elements from an iterator. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b]$. $a$ must be /// less than or equal to $b$. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = \\begin{cases} /// \frac{1}{b-a+1}\prod_{i=0}^{n-1}P(x_i) & \text{if} \\quad a \leq n \leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_vecs_length_inclusive_range; /// /// let xs = random_vecs_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11, 136][..], /// &[200, 235, 134, 203], /// &[223, 38, 235], /// &[217, 177, 162, 32], /// &[166, 234, 30, 218], /// &[90, 106, 9], /// &[216, 204], /// &[151, 213, 97], /// &[253, 78], /// &[91, 39, 191, 175], /// &[170, 232, 233, 2], /// &[35, 22, 217], /// &[198, 114, 17, 32], /// &[173, 114, 65], /// &[121, 222, 173, 25], /// &[144, 148, 79, 115], /// &[52, 73, 69, 137], /// &[91, 153], /// &[178, 112, 34, 95], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_vecs_length_inclusive_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomVecs, I> { random_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), xs_gen, ) } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomOrderedUniqueVecsLength2 where I::Item: Ord, { xs: I, } impl Iterator for RandomOrderedUniqueVecsLength2 where I::Item: Ord, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { let mut out = Vec::with_capacity(2); loop { let x = self.xs.next().unwrap(); if out.is_empty() { out.push(x); } else { match x.cmp(&out[0]) { Equal => {} Greater => { out.push(x); break; } Less => { out.insert(0, x); break; } } } } Some(out) } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomOrderedUniqueVecsFixedLengthGreaterThan2 where I::Item: Ord, { xs: RandomBTreeSetsFixedLength, } impl Iterator for RandomOrderedUniqueVecsFixedLengthGreaterThan2 where I::Item: Ord, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { Some(self.xs.next().unwrap().into_iter().collect()) } } /// Generates random [`Vec`]s of a fixed length, where the [`Vec`]s have no repeated elements, and /// the elements are in ascending order. /// /// This `struct` is created by [`random_ordered_unique_vecs_fixed_length`]; see its documentation /// for more. #[derive(Clone, Debug)] pub enum RandomOrderedUniqueVecsFixedLength where I::Item: Ord, { Zero, One(I), Two(RandomOrderedUniqueVecsLength2), GreaterThan2(RandomOrderedUniqueVecsFixedLengthGreaterThan2), } impl Iterator for RandomOrderedUniqueVecsFixedLength where I::Item: Ord, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { match self { Self::Zero => Some(vec![]), Self::One(xs) => xs.next().map(|x| vec![x]), Self::Two(xs) => xs.next(), Self::GreaterThan2(xs) => xs.next(), } } } /// Randomly generates [`Vec`]s of a given length, where the [`Vec`]s have no repeated elements, and /// the elements are in ascending order. /// /// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will /// hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// The above formula assumes that the [`Vec`] is valid, \emph{i.e.} its elements are strictly /// increasing. The probability of an invalid [`Vec`] is zero. /// /// If `len` is 0, the output consists of the empty list, repeated. /// /// `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs_fixed_length; /// /// let xss = random_ordered_unique_vecs_fixed_length( /// 2, /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 100), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[24, 95], /// &[71, 99], /// &[53, 93], /// &[34, 85], /// &[2, 48], /// &[11, 55], /// &[18, 48], /// &[90, 93], /// &[67, 93], /// &[93, 95] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs_fixed_length( len: u64, xs: I, ) -> RandomOrderedUniqueVecsFixedLength where I::Item: Ord, { match len { 0 => RandomOrderedUniqueVecsFixedLength::Zero, 1 => RandomOrderedUniqueVecsFixedLength::One(xs), 2 => RandomOrderedUniqueVecsFixedLength::Two(RandomOrderedUniqueVecsLength2 { xs }), len => RandomOrderedUniqueVecsFixedLength::GreaterThan2( RandomOrderedUniqueVecsFixedLengthGreaterThan2 { xs: random_b_tree_sets_fixed_length(len, xs), }, ), } } /// Generates random [`Vec`]s with lengths from an iterator, where the [`Vec`]s have no repeated /// elements, and the elements are in ascending order. #[derive(Clone, Debug)] pub struct RandomOrderedUniqueVecs, J: Iterator> { xs: RandomBTreeSets, } impl, J: Iterator> Iterator for RandomOrderedUniqueVecs { type Item = Vec; #[inline] fn next(&mut self) -> Option> { Some(self.xs.next().unwrap().into_iter().collect()) } } /// Generates random [`Vec`]s using elements from an iterator and with lengths from another /// iterator, where the [`Vec`]s have no repeated elements, and the elements are in ascending order. /// /// The input iterator must generate at least many distinct elements as any number generated by the /// lengths iterator; otherwise, this iterator will hang. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P(n)\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// The above formula assumes that the [`Vec`] is valid, \emph{i.e.} its elements are strictly /// increasing. The probability of an invalid [`Vec`] is zero. /// /// `lengths` and `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs_from_length_iterator; /// use malachite_base::vecs::random_values_from_vec; /// /// let xs = random_ordered_unique_vecs_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[11, 85][..], /// &[134, 136, 200, 235], /// &[203, 223], /// &[38, 177, 217, 235], /// &[32, 162, 166, 234], /// &[30, 218], /// &[], /// &[90, 106], /// &[], /// &[9, 151, 204, 216], /// &[78, 97, 213, 253], /// &[39, 91], /// &[170, 175, 191, 232], /// &[2, 233], /// &[22, 35, 198, 217], /// &[17, 32, 114, 173], /// &[65, 114, 121, 222], /// &[], /// &[25, 144, 148, 173], /// &[] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs_from_length_iterator< T: Ord, I: Iterator, J: Iterator, >( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, ) -> RandomOrderedUniqueVecs { RandomOrderedUniqueVecs { xs: random_b_tree_sets_from_length_iterator(seed, lengths_gen, xs_gen), } } /// Generates random [`Vec`]s using elements from an iterator, where the [`Vec`]s have no repeated /// elements, and the elements are in ascending order. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in [`geometric_random_unsigneds`]. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs; /// /// let xs = random_ordered_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235], /// &[30, 90, 218, 234], /// &[9, 106, 204, 216], /// &[151], /// &[], /// &[78, 91, 97, 213, 253], /// &[39, 191], /// &[170, 175, 232, 233], /// &[], /// &[2, 22, 35, 114, 198, 217], /// &[], /// &[], /// &[17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222], /// &[52, 69, 73, 91, 115, 137, 153, 178], /// &[], /// &[34, 95, 112], /// &[], /// &[106, 130, 167, 168, 197], /// &[86, 101, 122, 150, 172, 177, 207, 218, 221] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomOrderedUniqueVecs, I> where I::Item: Ord, { random_ordered_unique_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, xs_gen, ) } /// Generates random [`Vec`]s with a minimum length, using elements from an iterator, where the /// [`Vec`]s have no repeated elements, and the elements are in ascending order. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}) = n!P_g(n)\prod\_{i=0}^{n-1}P(x\_i), /// $$ /// where $P_g(n)$ is the probability function described in /// [`geometric_random_unsigned_inclusive_range`], with $a$ equal to `min_length` and `b` to /// `u64::MAX`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less /// than or equal to `min_length`, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs_min_length; /// /// let xs = /// random_ordered_unique_vecs_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::, 6, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[11, 85][..], /// &[30, 32, 38, 90, 134, 136, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235], /// &[9, 106, 151, 204, 213, 216], /// &[39, 78, 91, 97, 191, 253], /// &[170, 175, 232], /// &[2, 233], /// &[17, 22, 32, 35, 114, 198, 217], /// &[65, 114, 121, 173], /// &[25, 79, 144, 148, 173, 222], /// &[52, 115], /// &[34, 69, 73, 91, 112, 137, 153, 178], /// &[95, 106], /// &[167, 197], /// &[74, 86, 101, 115, 122, 130, 150, 168, 172, 177, 207, 218, 221], /// &[9, 48, 52, 109, 123, 133, 159, 201, 247, 250], /// &[196, 235], /// &[40, 68, 97, 104, 190], /// &[7, 216], /// &[11, 24, 43, 112, 157, 216, 217], /// &[29, 51, 55, 65, 84, 89, 103, 135, 191, 206, 211] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs_min_length( seed: Seed, min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomOrderedUniqueVecs, I> where I::Item: Ord, { random_ordered_unique_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, xs_gen, ) } /// Generates random [`Vec`]s with lengths in $[a, b)$, using elements from an iterator, where the /// [`Vec`]s have no repeated elements, and the elements are in ascending order. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs_length_range; /// /// let xs = /// random_ordered_unique_vecs_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[11, 85, 136][..], /// &[134, 200, 203, 235], /// &[38, 223, 235], /// &[32, 162, 177, 217], /// &[30, 166, 218, 234], /// &[9, 90, 106], /// &[204, 216], /// &[97, 151, 213], /// &[78, 253], /// &[39, 91, 175, 191], /// &[2, 170, 232, 233], /// &[22, 35, 217], /// &[17, 32, 114, 198], /// &[65, 114, 173], /// &[25, 121, 173, 222], /// &[79, 115, 144, 148], /// &[52, 69, 73, 137], /// &[91, 153], /// &[34, 95, 112, 178], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs_length_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomOrderedUniqueVecs, I> where I::Item: Ord, { random_ordered_unique_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), xs_gen, ) } /// Generates random [`Vec`]s with lengths in $[a, b]$, using elements from an iterator, where the /// [`Vec`]s have no repeated elements, and the elements are in ascending order. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b]$. $a$ must be /// less than or equal to $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// $$ /// P((x\_i)\_{i=0}^{n-1}, a, b) = \frac{n!}{b - a + 1}\prod\_{i=0}^{n-1}P(x\_i). /// $$ /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_ordered_unique_vecs_length_inclusive_range; /// /// let xs = random_ordered_unique_vecs_length_inclusive_range( /// EXAMPLE_SEED, /// 2, /// 4, /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[11, 85, 136][..], /// &[134, 200, 203, 235], /// &[38, 223, 235], /// &[32, 162, 177, 217], /// &[30, 166, 218, 234], /// &[9, 90, 106], /// &[204, 216], /// &[97, 151, 213], /// &[78, 253], /// &[39, 91, 175, 191], /// &[2, 170, 232, 233], /// &[22, 35, 217], /// &[17, 32, 114, 198], /// &[65, 114, 173], /// &[25, 121, 173, 222], /// &[79, 115, 144, 148], /// &[52, 69, 73, 137], /// &[91, 153], /// &[34, 95, 112, 178], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_ordered_unique_vecs_length_inclusive_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomOrderedUniqueVecs, I> where I::Item: Ord, { random_ordered_unique_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), xs_gen, ) } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomUniqueVecsLength2 where I::Item: Eq, { xs: I, } impl Iterator for RandomUniqueVecsLength2 where I::Item: Eq, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { let mut out = Vec::with_capacity(2); loop { let x = self.xs.next().unwrap(); if out.is_empty() { out.push(x); } else if x != out[0] { out.push(x); return Some(out); } } } } /// Generates random [`Vec`]s with lengths from an iterator, where the [`Vec`]s have no repeated /// elements. #[derive(Clone, Debug)] pub struct RandomUniqueVecs, J: Iterator> { lengths: I, xs: J, } impl, J: Iterator> Iterator for RandomUniqueVecs { type Item = Vec; fn next(&mut self) -> Option> { // We avoid cloning the T values. We first move them into a HashMap, then into a // Vec>, then into the output Vec. let len = usize::exact_from(self.lengths.next().unwrap()); let mut xs_to_indices = HashMap::with_capacity(len); let mut i = 0; while i < len { xs_to_indices .entry(self.xs.next().unwrap()) .or_insert_with(|| { i += 1; i - 1 }); } let mut out = Vec::with_capacity(len); out.resize_with(len, || None); for (x, i) in xs_to_indices { out[i] = Some(x); } Some(out.into_iter().map(Option::unwrap).collect()) } } /// Generates random [`Vec`]s using elements from an iterator and with lengths from another /// iterator, where the [`Vec`]s have no repeated elements. /// /// The input iterator must generate at least many distinct elements as any number generated by the /// lengths iterator; otherwise, this iterator will hang. /// /// `lengths` and `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs_from_length_iterator; /// use malachite_base::vecs::random_values_from_vec; /// /// let xs = random_unique_vecs_from_length_iterator( /// EXAMPLE_SEED, /// &|seed| random_values_from_vec(seed, vec![0, 2, 4]), /// &random_primitive_ints::, /// ); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11][..], /// &[136, 200, 235, 134], /// &[203, 223], /// &[38, 235, 217, 177], /// &[162, 32, 166, 234], /// &[30, 218], /// &[], /// &[90, 106], /// &[], /// &[9, 216, 204, 151], /// &[213, 97, 253, 78], /// &[91, 39], /// &[191, 175, 170, 232], /// &[233, 2], /// &[35, 22, 217, 198], /// &[114, 17, 32, 173], /// &[114, 65, 121, 222], /// &[], /// &[173, 25, 144, 148], /// &[] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs_from_length_iterator< T: Eq + Hash, I: Iterator, J: Iterator, >( seed: Seed, lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, ) -> RandomUniqueVecs { RandomUniqueVecs { lengths: lengths_gen(seed.fork("lengths")), xs: xs_gen(seed.fork("xs")), } } /// Generates random [`Vec`]s of a fixed length, where the [`Vec`]s have no repeated elements. /// /// This `enum` is created by [`random_unique_vecs_fixed_length`]; see its documentation for more. #[derive(Clone, Debug)] pub enum RandomUniqueVecsFixedLength where I::Item: Eq + Hash, { Zero, One(I), Two(RandomUniqueVecsLength2), GreaterThan2(RandomUniqueVecs, I>), } impl Iterator for RandomUniqueVecsFixedLength where I::Item: Eq + Hash, { type Item = Vec; #[inline] fn next(&mut self) -> Option> { match self { Self::Zero => Some(vec![]), Self::One(xs) => xs.next().map(|x| vec![x]), Self::Two(xs) => xs.next(), Self::GreaterThan2(xs) => xs.next(), } } } /// Randomly generates [`Vec`]s of a given length, where the [`Vec`]s have no repeated elements. /// /// The input iterator must generate at least `len` distinct elements; otherwise, this iterator will /// hang. /// /// If `len` is 0, the output consists of the empty list, repeated. /// /// `xs` must be infinite. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_unsigned_inclusive_range; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs_fixed_length; /// /// let xss = random_unique_vecs_fixed_length( /// 2, /// random_unsigned_inclusive_range::(EXAMPLE_SEED, 1, 100), /// ) /// .take(10) /// .collect_vec(); /// assert_eq!( /// xss.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[95, 24], /// &[99, 71], /// &[93, 53], /// &[85, 34], /// &[48, 2], /// &[55, 11], /// &[48, 18], /// &[90, 93], /// &[67, 93], /// &[93, 95] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs_fixed_length( len: u64, xs: I, ) -> RandomUniqueVecsFixedLength where I::Item: Eq + Hash, { match len { 0 => RandomUniqueVecsFixedLength::Zero, 1 => RandomUniqueVecsFixedLength::One(xs), 2 => RandomUniqueVecsFixedLength::Two(RandomUniqueVecsLength2 { xs }), len => RandomUniqueVecsFixedLength::GreaterThan2(RandomUniqueVecs { lengths: repeat(len), xs, }), } } /// Generates random [`Vec`]s using elements from an iterator, where the [`Vec`]s have no repeated /// elements. /// /// The lengths of the [`Vec`]s are sampled from a geometric distribution with a specified mean $m$, /// equal to `mean_length_numerator / mean_length_denominator`. $m$ must be greater than 0. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, or, if after being /// reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs; /// /// let xs = random_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[][..], /// &[85, 11, 136, 200, 235, 134, 203, 223, 38, 217, 177, 162, 32, 166], /// &[234, 30, 218, 90], /// &[106, 9, 216, 204], /// &[151], /// &[], /// &[213, 97, 253, 78, 91], /// &[39, 191], /// &[175, 170, 232, 233], /// &[], /// &[2, 35, 22, 217, 198, 114], /// &[], /// &[], /// &[17, 32, 173, 114, 65, 121, 222, 25, 144, 148, 79], /// &[115, 52, 73, 69, 137, 91, 153, 178], /// &[], /// &[112, 34, 95], /// &[], /// &[106, 167, 197, 130, 168], /// &[122, 207, 172, 177, 86, 150, 221, 218, 101] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs( seed: Seed, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomUniqueVecs, I> where I::Item: Eq + Hash, { random_unique_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigneds(seed_2, mean_length_numerator, mean_length_denominator) }, xs_gen, ) } /// Generates random [`Vec`]s with a minimum length, using elements from an iterator, where the /// [`Vec`]s have no repeated elements. /// /// Strictly speaking, the input iterator must generate infinitely many distinct elements. In /// practice it only needs to generate $k$ distinct elements, where $k$ is the largest length /// actually sampled from the geometric distribution. For example, if `mean_length_numerator / /// mean_length_denominator` is significantly lower than 256, then it's ok to use /// `random_unsigneds::`. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if `mean_length_numerator` or `mean_length_denominator` are zero, if their ratio is less /// than or equal to `min_length`, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs_min_length; /// /// let xs = random_unique_vecs_min_length(EXAMPLE_SEED, 2, &random_primitive_ints::, 6, 1); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11][..], /// &[136, 200, 235, 134, 203, 223, 38, 217, 177, 162, 32, 166, 234, 30, 218, 90], /// &[106, 9, 216, 204, 151, 213], /// &[97, 253, 78, 91, 39, 191], /// &[175, 170, 232], /// &[233, 2], /// &[35, 22, 217, 198, 114, 17, 32], /// &[173, 114, 65, 121], /// &[222, 173, 25, 144, 148, 79], /// &[115, 52], /// &[73, 69, 137, 91, 153, 178, 112, 34], /// &[95, 106], /// &[167, 197], /// &[130, 168, 122, 207, 172, 177, 86, 150, 221, 218, 101, 115, 74], /// &[9, 123, 109, 52, 201, 159, 247, 250, 48, 133], /// &[235, 196], /// &[40, 97, 104, 68, 190], /// &[216, 7], /// &[216, 157, 43, 112, 217, 24, 11], /// &[103, 211, 84, 135, 55, 29, 206, 89, 65, 191, 51] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs_min_length( seed: Seed, min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, ) -> RandomUniqueVecs, I> where I::Item: Eq + Hash, { random_unique_vecs_from_length_iterator( seed, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, min_length, u64::MAX, mean_length_numerator, mean_length_denominator, ) }, xs_gen, ) } /// Generates random [`Vec`]s with lengths in $[a, b)$, using elements from an iterator, where the /// [`Vec`]s have no repeated elements. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b)$. $a$ must be /// less than $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs_length_range; /// /// let xs = random_unique_vecs_length_range(EXAMPLE_SEED, 2, 5, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11, 136][..], /// &[200, 235, 134, 203], /// &[223, 38, 235], /// &[217, 177, 162, 32], /// &[166, 234, 30, 218], /// &[90, 106, 9], /// &[216, 204], /// &[151, 213, 97], /// &[253, 78], /// &[91, 39, 191, 175], /// &[170, 232, 233, 2], /// &[35, 22, 217], /// &[198, 114, 17, 32], /// &[173, 114, 65], /// &[121, 222, 173, 25], /// &[144, 148, 79, 115], /// &[52, 73, 69, 137], /// &[91, 153], /// &[178, 112, 34, 95], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs_length_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomUniqueVecs, I> where I::Item: Eq + Hash, { random_unique_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_range(seed_2, a, b), xs_gen, ) } /// Generates random [`Vec`]s with lengths in $[a, b]$, using elements from an iterator, where the /// [`Vec`]s have no repeated elements. /// /// The lengths of the [`Vec`]s are sampled from a uniform distribution on $[a, b]$. $a$ must be /// less than or equal to $b$. /// /// The input iterator must generate at least $b$ distinct elements. /// /// `xs_gen` must be infinite. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::vecs::random::random_unique_vecs_length_inclusive_range; /// /// let xs = /// random_unique_vecs_length_inclusive_range(EXAMPLE_SEED, 2, 4, &random_primitive_ints::); /// let values = xs.take(20).collect_vec(); /// assert_eq!( /// values.iter().map(Vec::as_slice).collect_vec().as_slice(), /// &[ /// &[85, 11, 136][..], /// &[200, 235, 134, 203], /// &[223, 38, 235], /// &[217, 177, 162, 32], /// &[166, 234, 30, 218], /// &[90, 106, 9], /// &[216, 204], /// &[151, 213, 97], /// &[253, 78], /// &[91, 39, 191, 175], /// &[170, 232, 233, 2], /// &[35, 22, 217], /// &[198, 114, 17, 32], /// &[173, 114, 65], /// &[121, 222, 173, 25], /// &[144, 148, 79, 115], /// &[52, 73, 69, 137], /// &[91, 153], /// &[178, 112, 34, 95], /// &[106, 167] /// ] /// ); /// ``` #[inline] pub fn random_unique_vecs_length_inclusive_range( seed: Seed, a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, ) -> RandomUniqueVecs, I> where I::Item: Eq + Hash, { random_unique_vecs_from_length_iterator( seed, &|seed_2| random_unsigned_inclusive_range(seed_2, a, b), xs_gen, ) } ================================================ FILE: malachite-base/tests/bools/constants.rs ================================================ // Copyright © 2026 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 malachite_base::comparison::traits::{Max, Min}; use malachite_base::named::Named; #[test] fn test_min() { assert_eq!(bool::MIN, false); } #[test] fn test_max() { assert_eq!(bool::MAX, true); } #[test] pub fn test_named() { assert_eq!(bool::NAME, "bool"); } ================================================ FILE: malachite-base/tests/bools/exhaustive.rs ================================================ // Copyright © 2026 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::bools::exhaustive::exhaustive_bools; #[test] fn test_exhaustive_bools() { assert_eq!(exhaustive_bools().collect_vec(), &[false, true]); } ================================================ FILE: malachite-base/tests/bools/not_assign.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::NotAssign; use malachite_base::test_util::generators::bool_gen; #[test] fn test_not_assign() { let test = |mut b: bool, out| { b.not_assign(); assert_eq!(b, out); }; test(false, true); test(true, false); } #[test] fn not_assign_properties() { bool_gen().test_properties(|b| { let mut mut_b = b; mut_b.not_assign(); assert_ne!(mut_b, b); assert_eq!(mut_b, !b); mut_b.not_assign(); assert_eq!(mut_b, b); }); } ================================================ FILE: malachite-base/tests/bools/random/get_weighted_random_bool.rs ================================================ // Copyright © 2026 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 malachite_base::bools::random::get_weighted_random_bool; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; fn get_weighted_random_bool_helper(n: u64, d: u64, out: bool) { assert_eq!( get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), n, d), out ); } #[test] fn test_get_weighted_random_bool() { get_weighted_random_bool_helper(0, 1, false); get_weighted_random_bool_helper(1, 1, true); get_weighted_random_bool_helper(1, 2, false); get_weighted_random_bool_helper(1, 100, false); get_weighted_random_bool_helper(99, 100, true); } #[test] #[should_panic] fn get_weighted_random_bool_fail_1() { get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 0, 0); } #[test] #[should_panic] fn get_weighted_random_bool_fail_2() { get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 0); } #[test] #[should_panic] fn get_weighted_random_bool_fail_3() { get_weighted_random_bool(&mut VariableRangeGenerator::new(EXAMPLE_SEED), 2, 1); } ================================================ FILE: malachite-base/tests/bools/random/random_bools.rs ================================================ // Copyright © 2026 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 malachite_base::bools::random::random_bools; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{MomentStats, uniform_bool_assertions}; #[test] fn test_random_bools() { uniform_bool_assertions( random_bools(EXAMPLE_SEED), false, true, &[ true, false, false, false, true, true, true, false, true, true, true, true, false, true, true, true, true, false, true, false, ], &[(true, 500473), (false, 499527)], (false, Some(true)), (true, None), MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.5), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.9999999999999998), }, MomentStats { mean: NiceFloat(0.5004730000000077), standard_deviation: NiceFloat(0.5000000262710417), skewness: NiceFloat(-0.0018920008465908307), excess_kurtosis: NiceFloat(-1.999996420332894), }, ); } ================================================ FILE: malachite-base/tests/bools/random/weighted_random_bools.rs ================================================ // Copyright © 2026 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::bools::random::weighted_random_bools; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; fn weighted_random_bools_helper( p_numerator: u64, p_denominator: u64, expected_values: &[bool], expected_common_values: &[(bool, usize)], expected_median: (bool, Option), ) { let xs = weighted_random_bools(EXAMPLE_SEED, p_numerator, p_denominator); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_weighted_random_bools() { // p = 0 weighted_random_bools_helper(0, 1, &[false; 20], &[(false, 1000000)], (false, None)); // p = 1 weighted_random_bools_helper(1, 1, &[true; 20], &[(true, 1000000)], (true, None)); // p = 1/2 weighted_random_bools_helper( 1, 2, &[ false, true, true, true, false, false, false, true, false, false, false, false, true, false, false, false, false, true, false, true, ], &[(false, 500473), (true, 499527)], (false, None), ); // p = 1/51 weighted_random_bools_helper( 1, 51, &[ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], &[(false, 980406), (true, 19594)], (false, None), ); // w = 50/51 weighted_random_bools_helper( 50, 51, &[ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, ], &[(true, 980602), (false, 19398)], (true, None), ); } #[test] #[should_panic] fn weighted_random_bools_fail_1() { weighted_random_bools(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn weighted_random_bools_fail_2() { weighted_random_bools(EXAMPLE_SEED, 2, 1); } ================================================ FILE: malachite-base/tests/chars/char_type.rs ================================================ // Copyright © 2026 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::chars::CharType; use malachite_base::chars::exhaustive::chars_increasing; use std::collections::HashSet; #[test] fn test_char_type() { let char_types = [ CharType::AsciiLower, CharType::AsciiUpper, CharType::AsciiNumeric, CharType::AsciiNonAlphanumericGraphic, CharType::NonAsciiGraphic, CharType::NonGraphic, ]; let mut remaining_chars: HashSet<_> = chars_increasing().collect(); let mut n = remaining_chars.len(); let mut frequencies = Vec::new(); for &char_type in &char_types { remaining_chars.retain(|&c| !char_type.contains(c)); let frequency = n - remaining_chars.len(); n = remaining_chars.len(); frequencies.push((char_type, frequency)); } assert_eq!(n, 0); assert_eq!( frequencies, &[ (CharType::AsciiLower, 26), (CharType::AsciiUpper, 26), (CharType::AsciiNumeric, 10), (CharType::AsciiNonAlphanumericGraphic, 33), (CharType::NonAsciiGraphic, 157383), (CharType::NonGraphic, 954586) ] ); let first_chars = char_types.iter().map(|&char_type| { ( char_type, chars_increasing().find(|&c| char_type.contains(c)).unwrap(), ) }); assert_eq!( first_chars.collect_vec(), &[ (CharType::AsciiLower, 'a'), (CharType::AsciiUpper, 'A'), (CharType::AsciiNumeric, '0'), (CharType::AsciiNonAlphanumericGraphic, ' '), (CharType::NonAsciiGraphic, '¡'), (CharType::NonGraphic, '\u{0}') ] ); let last_chars = char_types.iter().map(|&char_type| { ( char_type, chars_increasing() .rev() .find(|&c| char_type.contains(c)) .unwrap(), ) }); assert_eq!( last_chars.collect_vec(), &[ (CharType::AsciiLower, 'z'), (CharType::AsciiUpper, 'Z'), (CharType::AsciiNumeric, '9'), (CharType::AsciiNonAlphanumericGraphic, '~'), (CharType::NonAsciiGraphic, '𳑹'), (CharType::NonGraphic, '\u{10ffff}') ] ); } ================================================ FILE: malachite-base/tests/chars/constants.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; #[test] fn test_min() { assert_eq!(char::MIN, '\u{0}'); } #[test] fn test_max() { assert_eq!(char::MAX, '\u{10ffff}'); } #[test] pub fn test_named() { assert_eq!(bool::NAME, "bool"); } ================================================ FILE: malachite-base/tests/chars/crement/char_to_contiguous_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::constants::{ CHAR_JUST_ABOVE_SURROGATES, CHAR_JUST_BELOW_SURROGATES, NUMBER_OF_CHARS, }; use malachite_base::chars::crement::{char_to_contiguous_range, contiguous_range_to_char}; use malachite_base::test_util::generators::{char_gen, char_pair_gen}; #[test] fn test_char_to_contiguous_range() { let test = |c, out| { assert_eq!(char_to_contiguous_range(c), out); }; test('\u{0}', 0); test('a', 97); test('A', 65); test(CHAR_JUST_BELOW_SURROGATES, 55295); test(CHAR_JUST_ABOVE_SURROGATES, 55296); test(char::MAX, 1112063); } #[test] fn char_to_contiguous_range_properties() { char_gen().test_properties_no_exhaustive_limit(|c| { let u = char_to_contiguous_range(c); assert_eq!(contiguous_range_to_char(u), Some(c)); assert!(u < NUMBER_OF_CHARS); }); char_pair_gen().test_properties(|(c, d)| { assert_eq!( c.cmp(&d), char_to_contiguous_range(c).cmp(&char_to_contiguous_range(d)) ); }); } ================================================ FILE: malachite-base/tests/chars/crement/contiguous_range_to_char.rs ================================================ // Copyright © 2026 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 malachite_base::chars::constants::{ CHAR_JUST_ABOVE_SURROGATES, CHAR_JUST_BELOW_SURROGATES, NUMBER_OF_CHARS, }; use malachite_base::chars::crement::{char_to_contiguous_range, contiguous_range_to_char}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_2, unsigned_pair_gen_var_1, }; #[test] fn test_contiguous_range_to_char() { let test = |u, out| { assert_eq!(contiguous_range_to_char(u), out); }; test(0, Some('\u{0}')); test(97, Some('a')); test(65, Some('A')); test(55295, Some(CHAR_JUST_BELOW_SURROGATES)); test(55296, Some(CHAR_JUST_ABOVE_SURROGATES)); test(NUMBER_OF_CHARS - 1, Some(char::MAX)); test(NUMBER_OF_CHARS, None); test(u32::MAX, None); } #[test] fn contiguous_range_to_char_properties() { unsigned_gen().test_properties(|u| { assert_eq!(contiguous_range_to_char(u).is_some(), u < NUMBER_OF_CHARS); }); unsigned_gen_var_2().test_properties(|u| { assert_eq!( char_to_contiguous_range(contiguous_range_to_char(u).unwrap()), u ); }); unsigned_pair_gen_var_1().test_properties(|(u, v)| { assert_eq!( u.cmp(&v), contiguous_range_to_char(u).cmp(&contiguous_range_to_char(v)) ); }); } ================================================ FILE: malachite-base/tests/chars/crement/crement.rs ================================================ // Copyright © 2026 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 malachite_base::chars::constants::{CHAR_JUST_ABOVE_SURROGATES, CHAR_JUST_BELOW_SURROGATES}; use malachite_base::chars::crement::{decrement_char, increment_char}; use malachite_base::test_util::generators::{char_gen_var_1, char_gen_var_2}; #[test] fn test_increment_char() { let test = |mut c: char, out| { increment_char(&mut c); assert_eq!(c, out); }; test('\u{0}', '\u{1}'); test('a', 'b'); test('A', 'B'); test(CHAR_JUST_BELOW_SURROGATES, CHAR_JUST_ABOVE_SURROGATES); test('\u{10fffe}', char::MAX); } #[test] #[should_panic] fn increment_char_fail() { let mut c = char::MAX; increment_char(&mut c); } #[test] fn test_decrement_char() { let test = |mut c: char, out| { decrement_char(&mut c); assert_eq!(c, out); }; test('\u{1}', '\u{0}'); test('b', 'a'); test('B', 'A'); test(CHAR_JUST_ABOVE_SURROGATES, CHAR_JUST_BELOW_SURROGATES); test(char::MAX, '\u{10fffe}'); } #[test] #[should_panic] fn decrement_char_fail() { let mut c = '\u{0}'; decrement_char(&mut c); } #[test] fn increment_char_properties() { char_gen_var_1().test_properties_no_exhaustive_limit(|c| { let mut mut_c = c; increment_char(&mut mut_c); assert_ne!(mut_c, c); decrement_char(&mut mut_c); assert_eq!(mut_c, c); }); } #[test] fn decrement_char_properties() { char_gen_var_2().test_properties_no_exhaustive_limit(|c| { let mut mut_c = c; decrement_char(&mut mut_c); assert_ne!(mut_c, c); increment_char(&mut mut_c); assert_eq!(mut_c, c); }); } ================================================ FILE: malachite-base/tests/chars/exhaustive/ascii_chars_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::chars::exhaustive::ascii_chars_increasing; #[test] fn test_ascii_chars_increasing() { assert_eq!( ascii_chars_increasing().collect::(), "\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\u{12}\ \u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f} !\"#$%&\'()*\ +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u{7f}" ); assert_eq!(ascii_chars_increasing().count(), 1 << 7); } ================================================ FILE: malachite-base/tests/chars/exhaustive/chars_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::chars::constants::NUMBER_OF_CHARS; use malachite_base::chars::exhaustive::chars_increasing; use malachite_base::num::conversion::traits::ExactFrom; #[test] fn test_chars_increasing() { assert_eq!( chars_increasing().take(200).collect::(), "\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\u{12}\ \u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f} !\"#$%&\'()*\ +,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u{7f}\ \u{80}\u{81}\u{82}\u{83}\u{84}\u{85}\u{86}\u{87}\u{88}\u{89}\u{8a}\u{8b}\u{8c}\u{8d}\u{8e}\ \u{8f}\u{90}\u{91}\u{92}\u{93}\u{94}\u{95}\u{96}\u{97}\u{98}\u{99}\u{9a}\u{9b}\u{9c}\u{9d}\ \u{9e}\u{9f}\u{a0}¡¢£¤¥¦§¨©ª«¬\u{ad}®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇ" ); assert_eq!( chars_increasing().rev().take(200).collect::(), "\u{10ffff}\u{10fffe}\u{10fffd}\u{10fffc}\u{10fffb}\u{10fffa}\u{10fff9}\u{10fff8}\u{10fff7}\ \u{10fff6}\u{10fff5}\u{10fff4}\u{10fff3}\u{10fff2}\u{10fff1}\u{10fff0}\u{10ffef}\u{10ffee}\ \u{10ffed}\u{10ffec}\u{10ffeb}\u{10ffea}\u{10ffe9}\u{10ffe8}\u{10ffe7}\u{10ffe6}\u{10ffe5}\ \u{10ffe4}\u{10ffe3}\u{10ffe2}\u{10ffe1}\u{10ffe0}\u{10ffdf}\u{10ffde}\u{10ffdd}\u{10ffdc}\ \u{10ffdb}\u{10ffda}\u{10ffd9}\u{10ffd8}\u{10ffd7}\u{10ffd6}\u{10ffd5}\u{10ffd4}\u{10ffd3}\ \u{10ffd2}\u{10ffd1}\u{10ffd0}\u{10ffcf}\u{10ffce}\u{10ffcd}\u{10ffcc}\u{10ffcb}\u{10ffca}\ \u{10ffc9}\u{10ffc8}\u{10ffc7}\u{10ffc6}\u{10ffc5}\u{10ffc4}\u{10ffc3}\u{10ffc2}\u{10ffc1}\ \u{10ffc0}\u{10ffbf}\u{10ffbe}\u{10ffbd}\u{10ffbc}\u{10ffbb}\u{10ffba}\u{10ffb9}\u{10ffb8}\ \u{10ffb7}\u{10ffb6}\u{10ffb5}\u{10ffb4}\u{10ffb3}\u{10ffb2}\u{10ffb1}\u{10ffb0}\u{10ffaf}\ \u{10ffae}\u{10ffad}\u{10ffac}\u{10ffab}\u{10ffaa}\u{10ffa9}\u{10ffa8}\u{10ffa7}\u{10ffa6}\ \u{10ffa5}\u{10ffa4}\u{10ffa3}\u{10ffa2}\u{10ffa1}\u{10ffa0}\u{10ff9f}\u{10ff9e}\u{10ff9d}\ \u{10ff9c}\u{10ff9b}\u{10ff9a}\u{10ff99}\u{10ff98}\u{10ff97}\u{10ff96}\u{10ff95}\u{10ff94}\ \u{10ff93}\u{10ff92}\u{10ff91}\u{10ff90}\u{10ff8f}\u{10ff8e}\u{10ff8d}\u{10ff8c}\u{10ff8b}\ \u{10ff8a}\u{10ff89}\u{10ff88}\u{10ff87}\u{10ff86}\u{10ff85}\u{10ff84}\u{10ff83}\u{10ff82}\ \u{10ff81}\u{10ff80}\u{10ff7f}\u{10ff7e}\u{10ff7d}\u{10ff7c}\u{10ff7b}\u{10ff7a}\u{10ff79}\ \u{10ff78}\u{10ff77}\u{10ff76}\u{10ff75}\u{10ff74}\u{10ff73}\u{10ff72}\u{10ff71}\u{10ff70}\ \u{10ff6f}\u{10ff6e}\u{10ff6d}\u{10ff6c}\u{10ff6b}\u{10ff6a}\u{10ff69}\u{10ff68}\u{10ff67}\ \u{10ff66}\u{10ff65}\u{10ff64}\u{10ff63}\u{10ff62}\u{10ff61}\u{10ff60}\u{10ff5f}\u{10ff5e}\ \u{10ff5d}\u{10ff5c}\u{10ff5b}\u{10ff5a}\u{10ff59}\u{10ff58}\u{10ff57}\u{10ff56}\u{10ff55}\ \u{10ff54}\u{10ff53}\u{10ff52}\u{10ff51}\u{10ff50}\u{10ff4f}\u{10ff4e}\u{10ff4d}\u{10ff4c}\ \u{10ff4b}\u{10ff4a}\u{10ff49}\u{10ff48}\u{10ff47}\u{10ff46}\u{10ff45}\u{10ff44}\u{10ff43}\ \u{10ff42}\u{10ff41}\u{10ff40}\u{10ff3f}\u{10ff3e}\u{10ff3d}\u{10ff3c}\u{10ff3b}\u{10ff3a}\ \u{10ff39}\u{10ff38}" ); assert_eq!( chars_increasing().count(), usize::exact_from(NUMBER_OF_CHARS) ); } ================================================ FILE: malachite-base/tests/chars/exhaustive/exhaustive_ascii_chars.rs ================================================ // Copyright © 2026 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 malachite_base::chars::exhaustive::exhaustive_ascii_chars; #[test] fn test_exhaustive_ascii_chars() { assert_eq!( exhaustive_ascii_chars().collect::(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !\"#$%&\'()*+,-./:;<=>?@[\\\ ]^_`{|}~\u{0}\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\ \u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}\u{7f}" ); assert_eq!(exhaustive_ascii_chars().count(), 1 << 7); } ================================================ FILE: malachite-base/tests/chars/exhaustive/exhaustive_chars.rs ================================================ // Copyright © 2026 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::chars::constants::NUMBER_OF_CHARS; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::num::conversion::traits::ExactFrom; #[test] fn test_exhaustive_chars() { assert_eq!( exhaustive_chars().take(200).collect::(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !\"#$%&\'()*+,-./:;<=>?@[\\\ ]^_`{|}~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóô\ õö÷øùúûüýþÿĀāĂ㥹ĆćĈĉĊ" ); assert_eq!( exhaustive_chars().count(), usize::exact_from(NUMBER_OF_CHARS) ); let mut chars = exhaustive_chars() .skip(usize::exact_from(NUMBER_OF_CHARS) - 200) .collect_vec(); chars.reverse(); assert_eq!( chars.iter().collect::(), "\u{10ffff}\u{10fffe}\u{10fffd}\u{10fffc}\u{10fffb}\u{10fffa}\u{10fff9}\u{10fff8}\u{10fff7}\ \u{10fff6}\u{10fff5}\u{10fff4}\u{10fff3}\u{10fff2}\u{10fff1}\u{10fff0}\u{10ffef}\u{10ffee}\ \u{10ffed}\u{10ffec}\u{10ffeb}\u{10ffea}\u{10ffe9}\u{10ffe8}\u{10ffe7}\u{10ffe6}\u{10ffe5}\ \u{10ffe4}\u{10ffe3}\u{10ffe2}\u{10ffe1}\u{10ffe0}\u{10ffdf}\u{10ffde}\u{10ffdd}\u{10ffdc}\ \u{10ffdb}\u{10ffda}\u{10ffd9}\u{10ffd8}\u{10ffd7}\u{10ffd6}\u{10ffd5}\u{10ffd4}\u{10ffd3}\ \u{10ffd2}\u{10ffd1}\u{10ffd0}\u{10ffcf}\u{10ffce}\u{10ffcd}\u{10ffcc}\u{10ffcb}\u{10ffca}\ \u{10ffc9}\u{10ffc8}\u{10ffc7}\u{10ffc6}\u{10ffc5}\u{10ffc4}\u{10ffc3}\u{10ffc2}\u{10ffc1}\ \u{10ffc0}\u{10ffbf}\u{10ffbe}\u{10ffbd}\u{10ffbc}\u{10ffbb}\u{10ffba}\u{10ffb9}\u{10ffb8}\ \u{10ffb7}\u{10ffb6}\u{10ffb5}\u{10ffb4}\u{10ffb3}\u{10ffb2}\u{10ffb1}\u{10ffb0}\u{10ffaf}\ \u{10ffae}\u{10ffad}\u{10ffac}\u{10ffab}\u{10ffaa}\u{10ffa9}\u{10ffa8}\u{10ffa7}\u{10ffa6}\ \u{10ffa5}\u{10ffa4}\u{10ffa3}\u{10ffa2}\u{10ffa1}\u{10ffa0}\u{10ff9f}\u{10ff9e}\u{10ff9d}\ \u{10ff9c}\u{10ff9b}\u{10ff9a}\u{10ff99}\u{10ff98}\u{10ff97}\u{10ff96}\u{10ff95}\u{10ff94}\ \u{10ff93}\u{10ff92}\u{10ff91}\u{10ff90}\u{10ff8f}\u{10ff8e}\u{10ff8d}\u{10ff8c}\u{10ff8b}\ \u{10ff8a}\u{10ff89}\u{10ff88}\u{10ff87}\u{10ff86}\u{10ff85}\u{10ff84}\u{10ff83}\u{10ff82}\ \u{10ff81}\u{10ff80}\u{10ff7f}\u{10ff7e}\u{10ff7d}\u{10ff7c}\u{10ff7b}\u{10ff7a}\u{10ff79}\ \u{10ff78}\u{10ff77}\u{10ff76}\u{10ff75}\u{10ff74}\u{10ff73}\u{10ff72}\u{10ff71}\u{10ff70}\ \u{10ff6f}\u{10ff6e}\u{10ff6d}\u{10ff6c}\u{10ff6b}\u{10ff6a}\u{10ff69}\u{10ff68}\u{10ff67}\ \u{10ff66}\u{10ff65}\u{10ff64}\u{10ff63}\u{10ff62}\u{10ff61}\u{10ff60}\u{10ff5f}\u{10ff5e}\ \u{10ff5d}\u{10ff5c}\u{10ff5b}\u{10ff5a}\u{10ff59}\u{10ff58}\u{10ff57}\u{10ff56}\u{10ff55}\ \u{10ff54}\u{10ff53}\u{10ff52}\u{10ff51}\u{10ff50}\u{10ff4f}\u{10ff4e}\u{10ff4d}\u{10ff4c}\ \u{10ff4b}\u{10ff4a}\u{10ff49}\u{10ff48}\u{10ff47}\u{10ff46}\u{10ff45}\u{10ff44}\u{10ff43}\ \u{10ff42}\u{10ff41}\u{10ff40}\u{10ff3f}\u{10ff3e}\u{10ff3d}\u{10ff3c}\u{10ff3b}\u{10ff3a}\ \u{10ff39}\u{10ff38}" ); assert_eq!( exhaustive_chars().skip(94).take(200).collect::(), "~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùú\ ûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕ\ ŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨ" ); assert_eq!( exhaustive_chars() .skip(141698) .take(200) .collect::(), "𮜾𮜿𮝀𮝁𮝂𮝃𮝄𮝅𮝆𮝇𮝈𮝉𮝊𮝋𮝌𮝍𮝎𮝏𮝐𮝑𮝒𮝓𮝔𮝕𮝖𮝗𮝘𮝙𮝚𮝛𮝜𮝝𮝞𮝟𮝠𮝡𮝢𮝣𮝤𮝥𮝦𮝧𮝨𮝩𮝪𮝫𮝬𮝭𮝮𮝯𮝰𮝱𮝲𮝳𮝴𮝵𮝶𮝷𮝸𮝹𮝺𮝻𮝼𮝽𮝾𮝿𮞀𮞁𮞂𮞃𮞄𮞅𮞆𮞇𮞈𮞉𮞊𮞋𮞌𮞍𮞎𮞏𮞐𮞑𮞒𮞓𮞔𮞕𮞖\ 𮞗𮞘𮞙𮞚𮞛𮞜𮞝𮞞𮞟𮞠𮞡𮞢𮞣𮞤𮞥𮞦𮞧𮞨𮞩𮞪𮞫𮞬𮞭𮞮𮞯𮞰𮞱𮞲𮞳𮞴𮞵𮞶𮞷𮞸𮞹𮞺𮞻𮞼𮞽𮞾𮞿𮟀𮟁𮟂𮟃𮟄𮟅𮟆𮟇𮟈𮟉𮟊𮟋𮟌𮟍𮟎𮟏𮟐𮟑𮟒𮟓𮟔𮟕𮟖𮟗𮟘𮟙𮟚𮟛𮟜𮟝𮟞𮟟𮟠𮟡𮟢𮟣𮟤𮟥𮟦𮟧𮟨𮟩𮟪𮟫𮟬𮟭𮟮𮟯𮟰\ 𮟱𮟲𮟳𮟴𮟵𮟶𮟷𮟸𮟹𮟺𮟻𮟼𮟽𮟾𮟿𮠀𮠁𮠂𮠃𮠄𮠅" ); } ================================================ FILE: malachite-base/tests/chars/is_graphic.rs ================================================ // Copyright © 2026 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::chars::char_is_graphic; use malachite_base::chars::exhaustive::{ascii_chars_increasing, chars_increasing}; use malachite_base::iterators::matching_intervals_in_iterator; #[test] fn test_is_graphic() { let test = |c, out| { assert_eq!(char_is_graphic(c), out); }; test(' ', true); test('a', true); test('A', true); test('0', true); test('!', true); test('ñ', true); test('\0', false); test('\n', false); test('\u{5f771}', false); assert_eq!( ascii_chars_increasing() .filter(|&c| char_is_graphic(c)) .count(), 95 ); assert_eq!( chars_increasing().filter(|&c| char_is_graphic(c)).count(), 157478 ); assert_eq!( matching_intervals_in_iterator(chars_increasing(), |&c| { char_is_graphic(c) }) .iter() .map(|i| (i.0 as u32, i.1 as u32)) .collect_vec(), &[ (32, 126), (161, 172), (174, 767), (880, 887), (890, 895), (900, 906), (908, 908), (910, 929), (931, 1154), (1162, 1327), (1329, 1366), (1369, 1418), (1421, 1423), (1470, 1470), (1472, 1472), (1475, 1475), (1478, 1478), (1488, 1514), (1519, 1524), (1542, 1551), (1563, 1563), (1565, 1610), (1632, 1647), (1649, 1749), (1758, 1758), (1765, 1766), (1769, 1769), (1774, 1805), (1808, 1808), (1810, 1839), (1869, 1957), (1969, 1969), (1984, 2026), (2036, 2042), (2046, 2069), (2074, 2074), (2084, 2084), (2088, 2088), (2096, 2110), (2112, 2136), (2142, 2142), (2144, 2154), (2160, 2191), (2208, 2249), (2307, 2361), (2363, 2363), (2365, 2368), (2377, 2380), (2382, 2384), (2392, 2401), (2404, 2432), (2434, 2435), (2437, 2444), (2447, 2448), (2451, 2472), (2474, 2480), (2482, 2482), (2486, 2489), (2493, 2493), (2495, 2496), (2503, 2504), (2507, 2508), (2510, 2510), (2524, 2525), (2527, 2529), (2534, 2557), (2563, 2563), (2565, 2570), (2575, 2576), (2579, 2600), (2602, 2608), (2610, 2611), (2613, 2614), (2616, 2617), (2622, 2624), (2649, 2652), (2654, 2654), (2662, 2671), (2674, 2676), (2678, 2678), (2691, 2691), (2693, 2701), (2703, 2705), (2707, 2728), (2730, 2736), (2738, 2739), (2741, 2745), (2749, 2752), (2761, 2761), (2763, 2764), (2768, 2768), (2784, 2785), (2790, 2801), (2809, 2809), (2818, 2819), (2821, 2828), (2831, 2832), (2835, 2856), (2858, 2864), (2866, 2867), (2869, 2873), (2877, 2877), (2880, 2880), (2887, 2888), (2891, 2892), (2908, 2909), (2911, 2913), (2918, 2935), (2947, 2947), (2949, 2954), (2958, 2960), (2962, 2965), (2969, 2970), (2972, 2972), (2974, 2975), (2979, 2980), (2984, 2986), (2990, 3001), (3007, 3007), (3009, 3010), (3014, 3016), (3018, 3020), (3024, 3024), (3046, 3066), (3073, 3075), (3077, 3084), (3086, 3088), (3090, 3112), (3114, 3129), (3133, 3133), (3137, 3140), (3160, 3162), (3164, 3165), (3168, 3169), (3174, 3183), (3191, 3200), (3202, 3212), (3214, 3216), (3218, 3240), (3242, 3251), (3253, 3257), (3261, 3262), (3265, 3265), (3267, 3268), (3292, 3294), (3296, 3297), (3302, 3311), (3313, 3315), (3330, 3340), (3342, 3344), (3346, 3386), (3389, 3389), (3391, 3392), (3398, 3400), (3402, 3404), (3406, 3407), (3412, 3414), (3416, 3425), (3430, 3455), (3458, 3459), (3461, 3478), (3482, 3505), (3507, 3515), (3517, 3517), (3520, 3526), (3536, 3537), (3544, 3550), (3558, 3567), (3570, 3572), (3585, 3632), (3634, 3635), (3647, 3654), (3663, 3675), (3713, 3714), (3716, 3716), (3718, 3722), (3724, 3747), (3749, 3749), (3751, 3760), (3762, 3763), (3773, 3773), (3776, 3780), (3782, 3782), (3792, 3801), (3804, 3807), (3840, 3863), (3866, 3892), (3894, 3894), (3896, 3896), (3898, 3911), (3913, 3948), (3967, 3967), (3973, 3973), (3976, 3980), (4030, 4037), (4039, 4044), (4046, 4058), (4096, 4140), (4145, 4145), (4152, 4152), (4155, 4156), (4159, 4183), (4186, 4189), (4193, 4208), (4213, 4225), (4227, 4228), (4231, 4236), (4238, 4252), (4254, 4293), (4295, 4295), (4301, 4301), (4304, 4680), (4682, 4685), (4688, 4694), (4696, 4696), (4698, 4701), (4704, 4744), (4746, 4749), (4752, 4784), (4786, 4789), (4792, 4798), (4800, 4800), (4802, 4805), (4808, 4822), (4824, 4880), (4882, 4885), (4888, 4954), (4960, 4988), (4992, 5017), (5024, 5109), (5112, 5117), (5120, 5759), (5761, 5788), (5792, 5880), (5888, 5905), (5919, 5937), (5941, 5942), (5952, 5969), (5984, 5996), (5998, 6000), (6016, 6067), (6070, 6070), (6078, 6085), (6087, 6088), (6100, 6108), (6112, 6121), (6128, 6137), (6144, 6154), (6160, 6169), (6176, 6264), (6272, 6276), (6279, 6312), (6314, 6314), (6320, 6389), (6400, 6430), (6435, 6438), (6441, 6443), (6448, 6449), (6451, 6456), (6464, 6464), (6468, 6509), (6512, 6516), (6528, 6571), (6576, 6601), (6608, 6618), (6622, 6678), (6681, 6682), (6686, 6741), (6743, 6743), (6753, 6753), (6755, 6756), (6765, 6770), (6784, 6793), (6800, 6809), (6816, 6829), (6916, 6963), (6974, 6977), (6981, 6988), (6990, 7018), (7028, 7039), (7042, 7073), (7078, 7079), (7086, 7141), (7143, 7143), (7146, 7148), (7150, 7150), (7164, 7211), (7220, 7221), (7227, 7241), (7245, 7306), (7312, 7354), (7357, 7367), (7379, 7379), (7393, 7393), (7401, 7404), (7406, 7411), (7413, 7415), (7418, 7418), (7424, 7615), (7680, 7957), (7960, 7965), (7968, 8005), (8008, 8013), (8016, 8023), (8025, 8025), (8027, 8027), (8029, 8029), (8031, 8061), (8064, 8116), (8118, 8132), (8134, 8147), (8150, 8155), (8157, 8175), (8178, 8180), (8182, 8190), (8208, 8231), (8240, 8286), (8304, 8305), (8308, 8334), (8336, 8348), (8352, 8385), (8448, 8587), (8592, 9257), (9280, 9290), (9312, 11123), (11126, 11502), (11506, 11507), (11513, 11557), (11559, 11559), (11565, 11565), (11568, 11623), (11631, 11632), (11648, 11670), (11680, 11686), (11688, 11694), (11696, 11702), (11704, 11710), (11712, 11718), (11720, 11726), (11728, 11734), (11736, 11742), (11776, 11869), (11904, 11929), (11931, 12019), (12032, 12245), (12272, 12287), (12289, 12329), (12336, 12351), (12353, 12438), (12443, 12543), (12549, 12591), (12593, 12686), (12688, 12773), (12783, 12830), (12832, 42124), (42128, 42182), (42192, 42539), (42560, 42606), (42611, 42611), (42622, 42653), (42656, 42735), (42738, 42743), (42752, 42972), (42993, 43009), (43011, 43013), (43015, 43018), (43020, 43044), (43047, 43051), (43056, 43065), (43072, 43127), (43136, 43203), (43214, 43225), (43250, 43262), (43264, 43301), (43310, 43334), (43346, 43346), (43359, 43388), (43395, 43442), (43444, 43445), (43450, 43451), (43454, 43455), (43457, 43469), (43471, 43481), (43486, 43492), (43494, 43518), (43520, 43560), (43567, 43568), (43571, 43572), (43584, 43586), (43588, 43595), (43597, 43597), (43600, 43609), (43612, 43643), (43645, 43695), (43697, 43697), (43701, 43702), (43705, 43709), (43712, 43712), (43714, 43714), (43739, 43755), (43758, 43765), (43777, 43782), (43785, 43790), (43793, 43798), (43808, 43814), (43816, 43822), (43824, 43883), (43888, 44004), (44006, 44007), (44009, 44012), (44016, 44025), (44032, 55203), (55216, 55238), (55243, 55291), (63744, 64109), (64112, 64217), (64256, 64262), (64275, 64279), (64285, 64285), (64287, 64310), (64312, 64316), (64318, 64318), (64320, 64321), (64323, 64324), (64326, 64975), (65008, 65023), (65040, 65049), (65072, 65106), (65108, 65126), (65128, 65131), (65136, 65140), (65142, 65276), (65281, 65437), (65440, 65470), (65474, 65479), (65482, 65487), (65490, 65495), (65498, 65500), (65504, 65510), (65512, 65518), (65532, 65533), (65536, 65547), (65549, 65574), (65576, 65594), (65596, 65597), (65599, 65613), (65616, 65629), (65664, 65786), (65792, 65794), (65799, 65843), (65847, 65934), (65936, 65948), (65952, 65952), (66000, 66044), (66176, 66204), (66208, 66256), (66273, 66299), (66304, 66339), (66349, 66378), (66384, 66421), (66432, 66461), (66463, 66499), (66504, 66517), (66560, 66717), (66720, 66729), (66736, 66771), (66776, 66811), (66816, 66855), (66864, 66915), (66927, 66938), (66940, 66954), (66956, 66962), (66964, 66965), (66967, 66977), (66979, 66993), (66995, 67001), (67003, 67004), (67008, 67059), (67072, 67382), (67392, 67413), (67424, 67431), (67456, 67461), (67463, 67504), (67506, 67514), (67584, 67589), (67592, 67592), (67594, 67637), (67639, 67640), (67644, 67644), (67647, 67669), (67671, 67742), (67751, 67759), (67808, 67826), (67828, 67829), (67835, 67867), (67871, 67897), (67903, 67929), (67968, 68023), (68028, 68047), (68050, 68096), (68112, 68115), (68117, 68119), (68121, 68149), (68160, 68168), (68176, 68184), (68192, 68255), (68288, 68324), (68331, 68342), (68352, 68405), (68409, 68437), (68440, 68466), (68472, 68497), (68505, 68508), (68521, 68527), (68608, 68680), (68736, 68786), (68800, 68850), (68858, 68899), (68912, 68921), (68928, 68965), (68974, 68997), (69006, 69007), (69216, 69246), (69248, 69289), (69293, 69293), (69296, 69297), (69314, 69319), (69328, 69336), (69376, 69415), (69424, 69445), (69457, 69465), (69488, 69505), (69510, 69513), (69552, 69579), (69600, 69622), (69632, 69632), (69634, 69687), (69703, 69709), (69714, 69743), (69745, 69746), (69749, 69749), (69762, 69810), (69815, 69816), (69819, 69820), (69822, 69825), (69840, 69864), (69872, 69881), (69891, 69926), (69932, 69932), (69942, 69959), (69968, 70002), (70004, 70006), (70018, 70069), (70079, 70079), (70081, 70088), (70093, 70094), (70096, 70111), (70113, 70132), (70144, 70161), (70163, 70190), (70194, 70195), (70200, 70205), (70207, 70208), (70272, 70278), (70280, 70280), (70282, 70285), (70287, 70301), (70303, 70313), (70320, 70366), (70368, 70370), (70384, 70393), (70402, 70403), (70405, 70412), (70415, 70416), (70419, 70440), (70442, 70448), (70450, 70451), (70453, 70457), (70461, 70461), (70463, 70463), (70465, 70468), (70471, 70472), (70475, 70476), (70480, 70480), (70493, 70499), (70528, 70537), (70539, 70539), (70542, 70542), (70544, 70581), (70583, 70583), (70585, 70586), (70602, 70602), (70604, 70605), (70609, 70609), (70611, 70613), (70615, 70616), (70656, 70711), (70720, 70721), (70725, 70725), (70727, 70747), (70749, 70749), (70751, 70753), (70784, 70831), (70833, 70834), (70841, 70841), (70843, 70844), (70846, 70846), (70849, 70849), (70852, 70855), (70864, 70873), (71040, 71086), (71088, 71089), (71096, 71099), (71102, 71102), (71105, 71131), (71168, 71218), (71227, 71228), (71230, 71230), (71233, 71236), (71248, 71257), (71264, 71276), (71296, 71338), (71340, 71340), (71342, 71343), (71352, 71353), (71360, 71369), (71376, 71395), (71424, 71450), (71454, 71454), (71456, 71457), (71462, 71462), (71472, 71494), (71680, 71726), (71736, 71736), (71739, 71739), (71840, 71922), (71935, 71942), (71945, 71945), (71948, 71955), (71957, 71958), (71960, 71983), (71985, 71989), (71991, 71992), (71999, 72002), (72004, 72006), (72016, 72025), (72096, 72103), (72106, 72147), (72156, 72159), (72161, 72164), (72192, 72192), (72203, 72242), (72249, 72250), (72255, 72262), (72272, 72272), (72279, 72280), (72284, 72329), (72343, 72343), (72346, 72354), (72368, 72440), (72448, 72457), (72545, 72545), (72549, 72549), (72551, 72551), (72640, 72673), (72688, 72697), (72704, 72712), (72714, 72751), (72766, 72766), (72768, 72773), (72784, 72812), (72816, 72847), (72873, 72873), (72881, 72881), (72884, 72884), (72960, 72966), (72968, 72969), (72971, 73008), (73030, 73030), (73040, 73049), (73056, 73061), (73063, 73064), (73066, 73102), (73107, 73108), (73110, 73110), (73112, 73112), (73120, 73129), (73136, 73179), (73184, 73193), (73440, 73458), (73461, 73464), (73474, 73488), (73490, 73525), (73534, 73535), (73539, 73561), (73648, 73648), (73664, 73713), (73727, 74649), (74752, 74862), (74864, 74868), (74880, 75075), (77712, 77810), (77824, 78895), (78913, 78918), (78944, 82938), (82944, 83526), (90368, 90397), (90410, 90412), (90416, 90425), (92160, 92728), (92736, 92766), (92768, 92777), (92782, 92862), (92864, 92873), (92880, 92909), (92917, 92917), (92928, 92975), (92983, 92997), (93008, 93017), (93019, 93025), (93027, 93047), (93053, 93071), (93504, 93561), (93760, 93850), (93856, 93880), (93883, 93907), (93952, 94026), (94032, 94087), (94099, 94111), (94176, 94179), (94194, 94198), (94208, 101589), (101631, 101662), (101760, 101874), (110576, 110579), (110581, 110587), (110589, 110590), (110592, 110882), (110898, 110898), (110928, 110930), (110933, 110933), (110948, 110951), (110960, 111355), (113664, 113770), (113776, 113788), (113792, 113800), (113808, 113817), (113820, 113820), (113823, 113823), (117760, 118012), (118016, 118451), (118458, 118480), (118496, 118512), (118608, 118723), (118784, 119029), (119040, 119078), (119081, 119140), (119146, 119148), (119171, 119172), (119180, 119209), (119214, 119274), (119296, 119361), (119365, 119365), (119488, 119507), (119520, 119539), (119552, 119638), (119648, 119672), (119808, 119892), (119894, 119964), (119966, 119967), (119970, 119970), (119973, 119974), (119977, 119980), (119982, 119993), (119995, 119995), (119997, 120003), (120005, 120069), (120071, 120074), (120077, 120084), (120086, 120092), (120094, 120121), (120123, 120126), (120128, 120132), (120134, 120134), (120138, 120144), (120146, 120485), (120488, 120779), (120782, 121343), (121399, 121402), (121453, 121460), (121462, 121475), (121477, 121483), (122624, 122654), (122661, 122666), (122928, 122989), (123136, 123180), (123191, 123197), (123200, 123209), (123214, 123215), (123536, 123565), (123584, 123627), (123632, 123641), (123647, 123647), (124112, 124139), (124144, 124153), (124368, 124397), (124400, 124410), (124415, 124415), (124608, 124638), (124640, 124642), (124644, 124645), (124647, 124653), (124656, 124660), (124670, 124671), (124896, 124902), (124904, 124907), (124909, 124910), (124912, 124926), (124928, 125124), (125127, 125135), (125184, 125251), (125259, 125259), (125264, 125273), (125278, 125279), (126065, 126132), (126209, 126269), (126464, 126467), (126469, 126495), (126497, 126498), (126500, 126500), (126503, 126503), (126505, 126514), (126516, 126519), (126521, 126521), (126523, 126523), (126530, 126530), (126535, 126535), (126537, 126537), (126539, 126539), (126541, 126543), (126545, 126546), (126548, 126548), (126551, 126551), (126553, 126553), (126555, 126555), (126557, 126557), (126559, 126559), (126561, 126562), (126564, 126564), (126567, 126570), (126572, 126578), (126580, 126583), (126585, 126588), (126590, 126590), (126592, 126601), (126603, 126619), (126625, 126627), (126629, 126633), (126635, 126651), (126704, 126705), (126976, 127019), (127024, 127123), (127136, 127150), (127153, 127167), (127169, 127183), (127185, 127221), (127232, 127405), (127462, 127490), (127504, 127547), (127552, 127560), (127568, 127569), (127584, 127589), (127744, 128728), (128732, 128748), (128752, 128764), (128768, 128985), (128992, 129003), (129008, 129008), (129024, 129035), (129040, 129095), (129104, 129113), (129120, 129159), (129168, 129197), (129200, 129211), (129216, 129217), (129232, 129240), (129280, 129623), (129632, 129645), (129648, 129660), (129664, 129674), (129678, 129734), (129736, 129736), (129741, 129756), (129759, 129770), (129775, 129784), (129792, 129938), (129940, 130042), (131072, 173791), (173824, 178205), (178208, 183981), (183984, 191456), (191472, 192093), (194560, 195101), (196608, 201546), (201552, 210041) ][..] ); } ================================================ FILE: malachite-base/tests/chars/random/graphic_weighted_random_ascii_chars.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::graphic_weighted_random_ascii_chars; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn graphic_weighted_random_ascii_chars_helper( p_numerator: u64, p_denominator: u64, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = graphic_weighted_random_ascii_chars(EXAMPLE_SEED, p_numerator, p_denominator); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_graphic_weighted_random_ascii_chars() { // p = 1/2 graphic_weighted_random_ascii_chars_helper( 1, 2, "\u{1b}x\u{8}1\r4\u{2}N\u{11}\u{11}(\u{13}bcXr$g)\t7/E\u{11}+fY\u{10}Po\u{1}\u{17}\u{17}\ \u{13}o\u{1}.\u{0}\u{b}\u{3}$\u{6}\nV2R.\u{f}\u{5}\u{19}$\u{1f}V=\u{1c}\u{6}\u{15}\u{6}\ \u{11}\r\u{19}6\u{2}\u{19}=\u{12}\u{18}Dq\u{6}S<\u{6}\u{1d}C\u{b}M\u{8}\u{15}\u{16}\u{f}W_\ \u{0}\u{12}%\u{18}\u{10}\u{10}OX?\u{1f}\u{12}b\u{c}}\u{10}rJa\u{e}D\u{1e}`o635\u{2}Q:w\u{3}\ \u{1}3m\u{5}Y\u{1f}=\u{7}8\tn\r\u{1}\nq\u{13}\u{3}\t\u{f}fR:/\u{f}2\u{2}\u{1c}6\u{13}\u{13}\ z\u{15}r\u{f}\u{4}<\u{1d}pr\u{2}+UFFc;8P:", &[ ('d', 10548), ('C', 10506), ('7', 10501), ('R', 10486), ('D', 10484), ('q', 10476), ('1', 10468), ('6', 10463), ('\'', 10452), ('$', 10448), ], ('N', None), ); } #[test] #[should_panic] fn graphic_weighted_random_ascii_chars_fail_1() { graphic_weighted_random_ascii_chars(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn graphic_weighted_random_ascii_chars_fail_2() { graphic_weighted_random_ascii_chars(EXAMPLE_SEED, 2, 1); } ================================================ FILE: malachite-base/tests/chars/random/graphic_weighted_random_char_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn graphic_weighted_random_char_inclusive_range_helper( a: char, b: char, p_numerator: u64, p_denominator: u64, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = graphic_weighted_random_char_inclusive_range( EXAMPLE_SEED, a, b, p_numerator, p_denominator, ); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_graphic_weighted_random_char_inclusive_range() { // 'a', '\u{7f}', p = 1/2 graphic_weighted_random_char_inclusive_range_helper( 'a', '\u{7f}', 1, 2, "\u{7f}y\u{7f}g\u{7f}c\u{7f}k\u{7f}\u{7f}}\u{7f}ccjlybr\u{7f}tue\u{7f}}ye\u{7f}oz\u{7f}\ \u{7f}\u{7f}\u{7f}d\u{7f}f\u{7f}\u{7f}\u{7f}f\u{7f}\u{7f}fmxr\u{7f}\u{7f}\u{7f}g\u{7f}hy\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}q\u{7f}\u{7f}t\u{7f}\u{7f}pk\u{7f}oh\u{7f}\u{7f}i\ \u{7f}q\u{7f}\u{7f}\u{7f}\u{7f}nf\u{7f}\u{7f}l\u{7f}\u{7f}\u{7f}sqf\u{7f}\u{7f}t\u{7f}d\ \u{7f}emm\u{7f}|\u{7f}{z|wu\u{7f}dsc\u{7f}\u{7f}f{\u{7f}t\u{7f}r\u{7f}t\u{7f}q\u{7f}\u{7f}\ \u{7f}h\u{7f}\u{7f}\u{7f}\u{7f}klx~\u{7f}x\u{7f}\u{7f}c\u{7f}\u{7f}u\u{7f}l\u{7f}\u{7f}y\ \u{7f}~d\u{7f}~\u{7f}f\u{7f}\u{7f}m\u{7f}xf\u{7f}lkvcu{e\u{7f}\u{7f}b\u{7f}\u{7f}yh\u{7f}\ \u{7f}nz\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}e\u{7f}vu\u{7f}\u{7f}}\u{7f}y\u{7f}u\u{7f}\u{7f}", &[ ('\u{7f}', 499332), ('a', 16868), ('t', 16831), ('j', 16829), ('r', 16822), ('i', 16816), ('f', 16806), ('{', 16780), ('s', 16763), ('d', 16749), ], ('~', None), ); // 'a', '\u{7f}', p = 1/51 graphic_weighted_random_char_inclusive_range_helper( 'a', '\u{7f}', 1, 51, "\u{7f}\u{7f}y\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}g\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}c\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}k\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}", &[ ('\u{7f}', 980198), ('h', 697), ('n', 691), ('i', 681), ('w', 680), ('r', 677), ('a', 675), ('|', 674), ('q', 673), ('e', 670), ], ('\u{7f}', None), ); // 'a', '\u{7f}', p = 50/51 graphic_weighted_random_char_inclusive_range_helper( 'a', '\u{7f}', 50, 51, "ygck}ccjlybrtue}yeozdfffmxrghyqtpkohiqnflsqftdemm|{z|wudscf{trtqh\u{7f}klx~xculy~d~fmxflkv\ cu{ebyhnzevu}yuzvtuz}{b~yyzin}zsjthazlcluvu}a\u{7f}yvhhbgevdxo}unwjqepanjmpckouxtwwbi{nla\ \u{7f}cs{vphyrdaqhzndmqdqg\u{7f}{{mfwk|xf", &[ ('a', 32996), ('f', 32964), ('q', 32960), ('{', 32942), ('s', 32886), ('t', 32809), ('d', 32768), ('n', 32767), ('p', 32766), ('i', 32765), ], ('p', None), ); // '\u{100}', '\u{3ff}', p = 1/2 graphic_weighted_random_char_inclusive_range_helper( '\u{100}', '\u{3ff}', 1, 2, "\u{31b}ǘ\u{324}ɂ\u{35a}Ŝ\u{367}Ȣ\u{337}\u{342}Ι\u{36e}Ƙƣʅΰǟ˳ˊ\u{315}ȇʰɥ\u{32c}ΈϞƃ\u{30b}ʌμ\ \u{346}\u{36a}\u{328}\u{334}Ƣ\u{380}ϳ\u{32e}\u{359}\u{36b}Ϫ\u{333}\u{312}ǰɪŗŽ\u{302}\u{305}\ \u{32e}ƽ\u{357}ɥϻ\u{349}\u{35f}\u{316}\u{33a}\u{383}\u{301}\u{31d}ƚ\u{360}\u{35d}ʧ\u{30c}\ \u{30c}ƙϮ\u{34a}șϒ\u{367}\u{35f}Ϣ\u{308}ć\u{353}\u{333}\u{381}\u{30f}ɾɢ\u{367}\u{340}ǧ\ \u{356}\u{30c}\u{351}ǁʴȶ\u{33e}\u{358}Ɛ\u{351}ď\u{366}ȭˬɂ\u{38b}ϰ\u{342}ȁʺċλǿ\u{30c}αăǰ\ \u{31c}\u{327}ʹʃ\u{34a}Ű\u{36a}ǐ\u{33f}Ƭ\u{34c}ɖ\u{361}\u{335}\u{318}Ͼ\u{349}\u{35d}\u{330}\ \u{35c}ƾƱǒȆ\u{320}Ɉ\u{348}\u{324}Ϫ\u{31d}\u{35c}ʶ\u{332}ť\u{33d}\u{300}ˍ\u{326}ďǑ\u{329}ɶ\ \u{33d}Ɂ\u{31f}\u{363}ȭ\u{320}ƭğ\u{321}Ⱦ˹ĺǗʋdž˺\u{31a}\u{35c}ʐ\u{304}\u{365}Ǎŋ\u{34f}\u{31f}\ ɽɷ\u{31e}\u{32a}\u{31a}\u{307}\u{319}ϲ\u{310}Ÿȃ\u{369}\u{359}Ĩ\u{33e}Ş\u{38d}˭\u{31e}\ \u{321}", &[ ('\u{326}', 4271), ('\u{357}', 4238), ('\u{33b}', 4235), ('\u{36b}', 4235), ('\u{348}', 4228), ('\u{30b}', 4225), ('\u{304}', 4224), ('\u{30d}', 4224), ('\u{327}', 4221), ('\u{325}', 4217), ], ('\u{319}', None), ); // '\u{100}', '\u{3ff}', p = 1/51 graphic_weighted_random_char_inclusive_range_helper( '\u{100}', '\u{3ff}', 1, 51, "\u{31b}\u{324}ǘ\u{35a}\u{367}\u{337}\u{342}\u{36e}\u{315}\u{32c}\u{30b}\u{346}\u{36a}\ \u{328}\u{334}\u{380}\u{32e}\u{359}\u{36b}\u{333}\u{312}\u{302}\u{305}\u{32e}\u{357}\u{349}\ \u{35f}\u{316}\u{33a}\u{383}\u{301}\u{31d}\u{360}\u{35d}\u{30c}\u{30c}\u{34a}\u{367}ɂ\ \u{35f}\u{308}\u{353}\u{333}\u{381}\u{30f}\u{367}\u{340}\u{356}\u{30c}\u{351}\u{33e}\u{358}\ \u{351}\u{366}\u{38b}\u{342}\u{30c}\u{31c}\u{327}\u{34a}\u{36a}\u{33f}\u{34c}\u{361}\u{335}\ \u{318}\u{349}\u{35d}\u{330}\u{35c}\u{320}\u{348}\u{324}\u{31d}\u{35c}\u{332}\u{33d}\u{300}\ \u{326}\u{329}\u{33d}\u{31f}\u{363}\u{320}\u{321}\u{31a}\u{35c}\u{304}\u{365}\u{34f}\u{31f}\ \u{31e}\u{32a}\u{31a}\u{307}\u{319}\u{310}\u{369}\u{359}\u{33e}\u{38d}\u{31e}\u{321}\u{339}\ \u{330}\u{30f}\u{303}\u{345}Ŝ\u{32f}\u{35f}\u{33e}\u{30c}\u{313}\u{365}\u{356}\u{36c}\ \u{36f}\u{304}\u{314}\u{369}\u{310}\u{339}\u{33f}\u{354}\u{347}\u{378}\u{366}\u{380}Ȣ\ \u{326}\u{313}\u{383}\u{36c}\u{336}\u{357}\u{31e}\u{324}\u{317}\u{351}\u{323}\u{328}\u{330}\ \u{307}\u{336}\u{326}\u{32a}\u{350}\u{342}\u{315}\u{36b}\u{32b}\u{382}\u{34b}\u{33d}\u{34a}\ \u{314}\u{322}\u{311}\u{364}\u{34c}\u{322}\u{337}\u{30c}\u{362}\u{317}\u{300}\u{348}\u{367}\ \u{35b}\u{353}\u{32e}\u{328}\u{346}\u{328}\u{324}\u{329}\u{379}\u{366}\u{328}\u{30f}\u{31e}\ \u{368}\u{368}\u{38b}\u{318}\u{353}\u{35d}\u{31e}\u{360}\u{33c}\u{315}\u{33c}\u{31f}\u{323}\ \u{38b}\u{379}\u{38d}\u{365}\u{340}", &[ ('\u{30d}', 8469), ('\u{326}', 8280), ('\u{327}', 8268), ('\u{357}', 8250), ('\u{30c}', 8244), ('\u{325}', 8242), ('\u{30a}', 8232), ('\u{30b}', 8232), ('\u{35d}', 8222), ('\u{36b}', 8221), ], ('\u{33b}', None), ); // '\u{100}', '\u{3ff}', p = 50/51 graphic_weighted_random_char_inclusive_range_helper( '\u{100}', '\u{3ff}', 50, 51, "ǘɂŜȢΙƘƣʅΰǟ˳ˊȇʰɥΈϞƃʌμƢϳϪǰɪŗŽƽɥϻƚʧƙϮșϒϢćɾɢǧǁʴȶƐďȭˬɂϰȁʺċλǿαăǰʹʃŰǐƬɖϾ\u{31b}ƾƱǒȆɈϪʶťˍďǑɶɁȭƭğȾ˹\ ĺǗʋdž˺ʐǍŋɽɷϲŸȃĨŞ˭ƪřœɃˡϹƤǁĥɨʎʄˬıɐƺˀǍǷěέƼȞŞȩǀ΄ʱDZȭ\u{324}ʚǃϧśŅˊljΰϿǟϵȟǘĹϋȎʜɴϻϝͺĪƕ˪ϥŪˍʸĻέ˙ĠĢĄšǝ˿Ί\ \u{35a}ΗʩNJŰŦʝŋƶˈąŠɂŻDZƲɛΚʜťγ\u{367}ϽϹčLJīϥſʏȵ", &[ ('Ώ', 1637), ('Ɣ', 1627), ('ɭ', 1618), ('Έ', 1616), ('Ɯ', 1613), ('Ȓ', 1610), ('Ǧ', 1609), ('˵', 1608), ('˷', 1607), ('ƒ', 1606), ], ('ɉ', None), ); } #[test] #[should_panic] fn graphic_weighted_random_char_inclusive_range_fail_1() { graphic_weighted_random_char_inclusive_range(EXAMPLE_SEED, 'a', '\u{80}', 1, 0); } #[test] #[should_panic] fn graphic_weighted_random_char_inclusive_range_fail_2() { graphic_weighted_random_char_inclusive_range(EXAMPLE_SEED, 'a', '\u{80}', 2, 1); } #[test] #[should_panic] fn graphic_weighted_random_char_inclusive_range_fail_3() { graphic_weighted_random_char_inclusive_range(EXAMPLE_SEED, '\u{80}', 'a', 1, 1); } #[test] #[should_panic] fn graphic_weighted_random_char_inclusive_range_fail_4() { graphic_weighted_random_char_inclusive_range(EXAMPLE_SEED, 'a', 'z', 1, 1); } ================================================ FILE: malachite-base/tests/chars/random/graphic_weighted_random_char_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::graphic_weighted_random_char_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn graphic_weighted_random_char_range_helper( a: char, b: char, p_numerator: u64, p_denominator: u64, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = graphic_weighted_random_char_range(EXAMPLE_SEED, a, b, p_numerator, p_denominator); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_graphic_weighted_random_char_range() { // 'a', '\u{80}', p = 1/2 graphic_weighted_random_char_range_helper( 'a', '\u{80}', 1, 2, "\u{7f}y\u{7f}g\u{7f}c\u{7f}k\u{7f}\u{7f}}\u{7f}ccjlybr\u{7f}tue\u{7f}}ye\u{7f}oz\u{7f}\ \u{7f}\u{7f}\u{7f}d\u{7f}f\u{7f}\u{7f}\u{7f}f\u{7f}\u{7f}fmxr\u{7f}\u{7f}\u{7f}g\u{7f}hy\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}q\u{7f}\u{7f}t\u{7f}\u{7f}pk\u{7f}oh\u{7f}\u{7f}i\ \u{7f}q\u{7f}\u{7f}\u{7f}\u{7f}nf\u{7f}\u{7f}l\u{7f}\u{7f}\u{7f}sqf\u{7f}\u{7f}t\u{7f}d\ \u{7f}emm\u{7f}|\u{7f}{z|wu\u{7f}dsc\u{7f}\u{7f}f{\u{7f}t\u{7f}r\u{7f}t\u{7f}q\u{7f}\u{7f}\ \u{7f}h\u{7f}\u{7f}\u{7f}\u{7f}klx~\u{7f}x\u{7f}\u{7f}c\u{7f}\u{7f}u\u{7f}l\u{7f}\u{7f}y\ \u{7f}~d\u{7f}~\u{7f}f\u{7f}\u{7f}m\u{7f}xf\u{7f}lkvcu{e\u{7f}\u{7f}b\u{7f}\u{7f}yh\u{7f}\ \u{7f}nz\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}e\u{7f}vu\u{7f}\u{7f}}\u{7f}y\u{7f}u\u{7f}\u{7f}", &[ ('\u{7f}', 499332), ('a', 16868), ('t', 16831), ('j', 16829), ('r', 16822), ('i', 16816), ('f', 16806), ('{', 16780), ('s', 16763), ('d', 16749), ], ('~', None), ); // 'a', '\u{80}', p = 1/51 graphic_weighted_random_char_range_helper( 'a', '\u{80}', 1, 51, "\u{7f}\u{7f}y\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}g\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}c\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}k\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\ \u{7f}\u{7f}", &[ ('\u{7f}', 980198), ('h', 697), ('n', 691), ('i', 681), ('w', 680), ('r', 677), ('a', 675), ('|', 674), ('q', 673), ('e', 670), ], ('\u{7f}', None), ); // 'a', '\u{80}', p = 50/51 graphic_weighted_random_char_range_helper( 'a', '\u{80}', 50, 51, "ygck}ccjlybrtue}yeozdfffmxrghyqtpkohiqnflsqftdemm|{z|wudscf{trtqh\u{7f}klx~xculy~d~fmxflkv\ cu{ebyhnzevu}yuzvtuz}{b~yyzin}zsjthazlcluvu}a\u{7f}yvhhbgevdxo}unwjqepanjmpckouxtwwbi{nla\ \u{7f}cs{vphyrdaqhzndmqdqg\u{7f}{{mfwk|xf", &[ ('a', 32996), ('f', 32964), ('q', 32960), ('{', 32942), ('s', 32886), ('t', 32809), ('d', 32768), ('n', 32767), ('p', 32766), ('i', 32765), ], ('p', None), ); // '\u{100}', '\u{400}', w = 1/2 graphic_weighted_random_char_range_helper( '\u{100}', '\u{400}', 1, 2, "\u{31b}ǘ\u{324}ɂ\u{35a}Ŝ\u{367}Ȣ\u{337}\u{342}Ι\u{36e}Ƙƣʅΰǟ˳ˊ\u{315}ȇʰɥ\u{32c}ΈϞƃ\u{30b}ʌμ\ \u{346}\u{36a}\u{328}\u{334}Ƣ\u{380}ϳ\u{32e}\u{359}\u{36b}Ϫ\u{333}\u{312}ǰɪŗŽ\u{302}\u{305}\ \u{32e}ƽ\u{357}ɥϻ\u{349}\u{35f}\u{316}\u{33a}\u{383}\u{301}\u{31d}ƚ\u{360}\u{35d}ʧ\u{30c}\ \u{30c}ƙϮ\u{34a}șϒ\u{367}\u{35f}Ϣ\u{308}ć\u{353}\u{333}\u{381}\u{30f}ɾɢ\u{367}\u{340}ǧ\ \u{356}\u{30c}\u{351}ǁʴȶ\u{33e}\u{358}Ɛ\u{351}ď\u{366}ȭˬɂ\u{38b}ϰ\u{342}ȁʺċλǿ\u{30c}αăǰ\ \u{31c}\u{327}ʹʃ\u{34a}Ű\u{36a}ǐ\u{33f}Ƭ\u{34c}ɖ\u{361}\u{335}\u{318}Ͼ\u{349}\u{35d}\u{330}\ \u{35c}ƾƱǒȆ\u{320}Ɉ\u{348}\u{324}Ϫ\u{31d}\u{35c}ʶ\u{332}ť\u{33d}\u{300}ˍ\u{326}ďǑ\u{329}ɶ\ \u{33d}Ɂ\u{31f}\u{363}ȭ\u{320}ƭğ\u{321}Ⱦ˹ĺǗʋdž˺\u{31a}\u{35c}ʐ\u{304}\u{365}Ǎŋ\u{34f}\u{31f}\ ɽɷ\u{31e}\u{32a}\u{31a}\u{307}\u{319}ϲ\u{310}Ÿȃ\u{369}\u{359}Ĩ\u{33e}Ş\u{38d}˭\u{31e}\ \u{321}", &[ ('\u{326}', 4271), ('\u{357}', 4238), ('\u{33b}', 4235), ('\u{36b}', 4235), ('\u{348}', 4228), ('\u{30b}', 4225), ('\u{304}', 4224), ('\u{30d}', 4224), ('\u{327}', 4221), ('\u{325}', 4217), ], ('\u{319}', None), ); // '\u{100}', '\u{400}', p = 1/51 graphic_weighted_random_char_range_helper( '\u{100}', '\u{400}', 1, 51, "\u{31b}\u{324}ǘ\u{35a}\u{367}\u{337}\u{342}\u{36e}\u{315}\u{32c}\u{30b}\u{346}\u{36a}\ \u{328}\u{334}\u{380}\u{32e}\u{359}\u{36b}\u{333}\u{312}\u{302}\u{305}\u{32e}\u{357}\u{349}\ \u{35f}\u{316}\u{33a}\u{383}\u{301}\u{31d}\u{360}\u{35d}\u{30c}\u{30c}\u{34a}\u{367}ɂ\ \u{35f}\u{308}\u{353}\u{333}\u{381}\u{30f}\u{367}\u{340}\u{356}\u{30c}\u{351}\u{33e}\u{358}\ \u{351}\u{366}\u{38b}\u{342}\u{30c}\u{31c}\u{327}\u{34a}\u{36a}\u{33f}\u{34c}\u{361}\u{335}\ \u{318}\u{349}\u{35d}\u{330}\u{35c}\u{320}\u{348}\u{324}\u{31d}\u{35c}\u{332}\u{33d}\u{300}\ \u{326}\u{329}\u{33d}\u{31f}\u{363}\u{320}\u{321}\u{31a}\u{35c}\u{304}\u{365}\u{34f}\u{31f}\ \u{31e}\u{32a}\u{31a}\u{307}\u{319}\u{310}\u{369}\u{359}\u{33e}\u{38d}\u{31e}\u{321}\u{339}\ \u{330}\u{30f}\u{303}\u{345}Ŝ\u{32f}\u{35f}\u{33e}\u{30c}\u{313}\u{365}\u{356}\u{36c}\ \u{36f}\u{304}\u{314}\u{369}\u{310}\u{339}\u{33f}\u{354}\u{347}\u{378}\u{366}\u{380}Ȣ\ \u{326}\u{313}\u{383}\u{36c}\u{336}\u{357}\u{31e}\u{324}\u{317}\u{351}\u{323}\u{328}\u{330}\ \u{307}\u{336}\u{326}\u{32a}\u{350}\u{342}\u{315}\u{36b}\u{32b}\u{382}\u{34b}\u{33d}\u{34a}\ \u{314}\u{322}\u{311}\u{364}\u{34c}\u{322}\u{337}\u{30c}\u{362}\u{317}\u{300}\u{348}\u{367}\ \u{35b}\u{353}\u{32e}\u{328}\u{346}\u{328}\u{324}\u{329}\u{379}\u{366}\u{328}\u{30f}\u{31e}\ \u{368}\u{368}\u{38b}\u{318}\u{353}\u{35d}\u{31e}\u{360}\u{33c}\u{315}\u{33c}\u{31f}\u{323}\ \u{38b}\u{379}\u{38d}\u{365}\u{340}", &[ ('\u{30d}', 8469), ('\u{326}', 8280), ('\u{327}', 8268), ('\u{357}', 8250), ('\u{30c}', 8244), ('\u{325}', 8242), ('\u{30a}', 8232), ('\u{30b}', 8232), ('\u{35d}', 8222), ('\u{36b}', 8221), ], ('\u{33b}', None), ); // '\u{100}', '\u{400}', p = 50/51 graphic_weighted_random_char_range_helper( '\u{100}', '\u{400}', 50, 51, "ǘɂŜȢΙƘƣʅΰǟ˳ˊȇʰɥΈϞƃʌμƢϳϪǰɪŗŽƽɥϻƚʧƙϮșϒϢćɾɢǧǁʴȶƐďȭˬɂϰȁʺċλǿαăǰʹʃŰǐƬɖϾ\u{31b}ƾƱǒȆɈϪʶťˍďǑɶɁȭƭğȾ˹\ ĺǗʋdž˺ʐǍŋɽɷϲŸȃĨŞ˭ƪřœɃˡϹƤǁĥɨʎʄˬıɐƺˀǍǷěέƼȞŞȩǀ΄ʱDZȭ\u{324}ʚǃϧśŅˊljΰϿǟϵȟǘĹϋȎʜɴϻϝͺĪƕ˪ϥŪˍʸĻέ˙ĠĢĄšǝ˿Ί\ \u{35a}ΗʩNJŰŦʝŋƶˈąŠɂŻDZƲɛΚʜťγ\u{367}ϽϹčLJīϥſʏȵ", &[ ('Ώ', 1637), ('Ɣ', 1627), ('ɭ', 1618), ('Έ', 1616), ('Ɯ', 1613), ('Ȓ', 1610), ('Ǧ', 1609), ('˵', 1608), ('˷', 1607), ('ƒ', 1606), ], ('ɉ', None), ); } #[test] #[should_panic] fn graphic_weighted_random_char_range_fail_1() { graphic_weighted_random_char_range(EXAMPLE_SEED, 'a', '\u{80}', 1, 0); } #[test] #[should_panic] fn graphic_weighted_random_char_range_fail_2() { graphic_weighted_random_char_range(EXAMPLE_SEED, 'a', '\u{80}', 2, 1); } #[test] #[should_panic] fn graphic_weighted_random_char_range_fail_3() { graphic_weighted_random_char_range(EXAMPLE_SEED, '\u{80}', 'a', 1, 1); } #[test] #[should_panic] fn graphic_weighted_random_char_range_fail_4() { graphic_weighted_random_char_range(EXAMPLE_SEED, 'a', 'z', 1, 1); } ================================================ FILE: malachite-base/tests/chars/random/graphic_weighted_random_chars.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::graphic_weighted_random_chars; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn graphic_weighted_random_chars_helper( p_numerator: u64, p_denominator: u64, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = graphic_weighted_random_chars(EXAMPLE_SEED, p_numerator, p_denominator); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_graphic_weighted_random_chars() { // p = 1/2 graphic_weighted_random_chars_helper( 1, 2, "\u{90141}𗄡\u{3a6f5}𭼭\u{d9ae0}礜\u{e9c8d}깬\u{3b5ce}\u{d5d73}ꅉ\u{8ea12}杼쭗𫆬╳𲐕𡺽⢏\u{3b038}𲣍𮛊瀊\ \u{74682}𰥶𲛂ՠ\u{c9ca4}𥐷𨫉\u{c76d1}\u{55d29}\u{f10a9}\u{38719}𥧻\u{f48f9}𤜖\u{1943f}\u{38880}\ \u{5d11b}𠡩\u{e2590}\u{c30b6}𰭝🈱𰠲厨\u{fc1b9}\u{ad565}\u{70791}𠀓\u{ed09c}𩰦⋘\u{1b138}\u{3596f}\ \u{6457d}\u{798a6}\u{b3ee3}\u{f9067}\u{77896}𑇫\u{eeda4}\u{f41c9}𐤚\u{37247}\u{da9a4}⎖𡙄\ \u{a2ae4}摕𮨱\u{aa868}\u{77563}𖭨\u{feca2}𰊗\u{707ed}\u{4f05d}\u{6a423}\u{cae98}蚆𓈧\u{1c058}\ \u{103a5d}𥍎\u{6185a}\u{7e601}\u{55835}𓪞𤪨𠷯\u{c80f7}\u{d7686}뛕\u{15f71}䂇\u{8c53b}𡴬Ở쀖\ \u{3cec3}𝓩\u{648a3}𪔭𪣂𓑫憒쇝\u{6b44b}𭋋㆐쬾\u{5a137}\u{8a66b}𣌺𲙃\u{11e7c}𪪯\u{a0d66}𐓍\u{d0f11}ჷ\ \u{6d431}𡙫\u{70e7a}\u{c27cf}\u{a1819}𭕍\u{b3f9e}\u{44b14}\u{d5c59}\u{87e6d}𜵐𦀢죍呶\u{9f484}𫪬\ \u{1000c5}\u{56709}䍪\u{bcc29}\u{8fb24}𧠨\u{53577}姖\u{f3a83}\u{a6dad}𭩝\u{e42cf}𦠄𰒁\u{f61a3}𫵥\ \u{b56a5}𐌞\u{c789e}\u{e83ec}䆞\u{45ddc}𪠊𒐆\u{db711}𲪃𳇴뎒𡟨𘋯𓃸𥙨\u{ce6cc}\u{5a49d}㨟\u{92ece}\ \u{c7883}ֆ뇫\u{bbf05}\u{85be0}𩬳𦜟\u{edae}\u{b7331}\u{fd6e7}\u{12bbe}\u{ae977}𘇶\u{c77c5}𝓈譀\ \u{426f7}\u{9fda3}𢷏\u{ce98c}𘁉\u{6b0b9}𝆵\u{cc4fa}\u{49c49}", &[ ('𗎫', 13), ('𧯐', 13), ('𪬏', 13), ('𲍾', 13), ('Ẅ', 12), ('罚', 12), ('뛱', 12), ('ﬢ', 12), ('𘀧', 12), ('𛰸', 12), ], ('𱎧', None), ); // p = 1/51 graphic_weighted_random_chars_helper( 1, 51, "\u{90141}\u{3a6f5}𗄡\u{d9ae0}\u{e9c8d}\u{3b5ce}\u{d5d73}\u{8ea12}\u{3b038}\u{74682}\ \u{c9ca4}\u{c76d1}\u{55d29}\u{f10a9}\u{38719}\u{f48f9}\u{1943f}\u{38880}\u{5d11b}\u{e2590}\ \u{c30b6}\u{fc1b9}\u{ad565}\u{70791}\u{ed09c}\u{1b138}\u{3596f}\u{6457d}\u{798a6}\u{b3ee3}\ \u{f9067}\u{77896}\u{eeda4}\u{f41c9}\u{37247}\u{da9a4}\u{a2ae4}\u{aa868}𭼭\u{77563}\ \u{feca2}\u{707ed}\u{4f05d}\u{6a423}\u{cae98}\u{1c058}\u{103a5d}\u{6185a}\u{7e601}\ \u{55835}\u{c80f7}\u{d7686}\u{15f71}\u{8c53b}\u{3cec3}\u{648a3}\u{6b44b}\u{5a137}\u{8a66b}\ \u{11e7c}\u{a0d66}\u{d0f11}\u{6d431}\u{70e7a}\u{c27cf}\u{a1819}\u{b3f9e}\u{44b14}\u{d5c59}\ \u{87e6d}\u{9f484}\u{1000c5}\u{56709}\u{bcc29}\u{8fb24}\u{53577}\u{f3a83}\u{a6dad}\ \u{e42cf}\u{f61a3}\u{b56a5}\u{c789e}\u{e83ec}\u{45ddc}\u{db711}\u{ce6cc}\u{5a49d}\u{92ece}\ \u{c7883}\u{bbf05}\u{85be0}\u{edae}\u{b7331}\u{fd6e7}\u{12bbe}\u{ae977}\u{c77c5}\u{426f7}\ \u{9fda3}\u{ce98c}\u{6b0b9}\u{cc4fa}\u{49c49}\u{fefd4}\u{49ed9}\u{78198}\u{4473f}\u{366ef}\ 礜\u{bd970}\u{ea269}\u{9212c}\u{71474}\u{3d023}\u{5a63f}\u{55acd}\u{fa199}\u{bb388}\ \u{101b0}\u{9d8ed}\u{eb14a}\u{fa5db}\u{e338b}\u{f9cd0}\u{2f1db}\u{8e5ec}\u{37c8e}\u{771fa}\ \u{b74cb}깬\u{aab2a}\u{e024b}\u{10d4e8}\u{92de4}\u{fa12f}\u{42b42}\u{1a2f2}\u{afd94}\ \u{8318f}\u{73fd1}\u{44439}\u{72279}\u{103ded}\u{7ad52}\u{1098eb}\u{f3200}\u{97125}\ \u{8165f}\u{c26b9}\u{ad664}\u{b0861}\u{cd9f9}\u{d068f}\u{f9180}\u{c6a23}\u{ba7a0}\u{896a0}\ \u{a2ae2}\u{109104}\u{d8e4d}\u{53bb5}\u{10be12}\u{cf22d}\u{d361f}\u{a126c}\u{c6710}\ \u{68b09}\u{bd7b6}\u{7894a}\u{c4004}\u{51bea}\u{506d1}\u{b9e4e}\u{a300c}\u{fbea6}\u{f0f37}\ \u{565c6}\u{1184c}\u{1c479}\u{359ab}\u{38f38}\u{198e3}\u{ad730}\u{7df6f}\u{540ee}\u{14e95}\ \u{3e57d}\u{fded1}\u{4613f}\u{bdc98}\u{567d6}\u{7f434}\u{b47aa}\u{8adc0}\u{f6f1d}\u{e2068}\ \u{b8913}\u{3401b}\u{e9f10}\u{debe0}", &[ ('\u{7cb51}', 9), ('\u{9f2b9}', 9), ('\u{39d1d}', 8), ('\u{3f6cd}', 8), ('\u{654c8}', 8), ('\u{66ab5}', 8), ('\u{6cbc3}', 8), ('\u{7cf6b}', 8), ('\u{9d925}', 8), ('\u{a99f8}', 8), ], ('\u{99011}', None), ); // p = 50/51 graphic_weighted_random_chars_helper( 50, 51, "𗄡𭼭礜깬ꅉ杼쭗𫆬╳𲐕𡺽⢏𲣍𮛊瀊𰥶𲛂ՠ𥐷𨫉𥧻𤜖𠡩𰭝🈱𰠲厨𠀓𩰦⋘𑇫𐤚⎖𡙄摕𮨱𖭨𰊗蚆𓈧𥍎𓪞𤪨𠷯뛕䂇𡴬Ở쀖𝓩𪔭𪣂𓑫憒쇝𭋋㆐쬾𣌺𲙃𪪯𐓍ჷ𡙫𭕍\u{90141}𜵐𦀢죍呶𫪬䍪𧠨姖𭩝𦠄𰒁𫵥𐌞䆞𪠊\ 𒐆𲪃𳇴뎒𡟨𘋯𓃸𥙨㨟ֆ뇫𩬳𦜟𘇶𝓈譀𢷏𘁉𝆵鎋彔𮂔𥌴𠵀𘯴𥷀𱠪𫃗𬁵𑄷蠃𰱩𨨜鐔𛇛ㅐ耂𤁤ꔺ𥚍𦖇歠𠝼퉫𤰃𤋡笃羼𠼆\u{3a6f5}𗼌𡝿𓳸𢏼𰮬𫽩敃置𥟓𢚩𢇠𣗡𗎫ᕵ붏삇𓡫𦬓闑贛𧴈𒾭𬱞𤉀𨯝𣘉𑨬𫸊𮂺𢽋掟𞡙\ ✄㕵굜𖪢𥘀㾒\u{d9ae0}𖭤𱹜褱𓖫𭗺𦢓𐽺튕䯷𘳏𩶇𞹔𗟦釽쥐達헷𦩫𳈂𫛘\u{e9c8d}𗮶𠃅𘱜裳𦃿Ǐ𪥈𲜳䖇", &[ ('𗔓', 20), ('𲍾', 20), ('ﱠ', 19), ('𓕋', 19), ('𬏄', 19), ('𳅸', 19), ('䦯', 18), ('幋', 18), ('跠', 18), ('𗢹', 18), ], ('🂄', Some('🂅')), ); } #[test] #[should_panic] fn graphic_weighted_random_chars_fail_1() { graphic_weighted_random_chars(EXAMPLE_SEED, 0, 0); } #[test] #[should_panic] fn graphic_weighted_random_chars_fail_2() { graphic_weighted_random_chars(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn graphic_weighted_random_chars_fail_3() { graphic_weighted_random_chars(EXAMPLE_SEED, 2, 1); } ================================================ FILE: malachite-base/tests/chars/random/random_ascii_chars.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::random_ascii_chars; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; #[test] fn test_random_ascii_chars() { let xs = random_ascii_chars(EXAMPLE_SEED); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), ( "q^\u{17}bF\\4T!/\u{1}q6\n/\u{11}Y\\wB\\r\\^\u{15}3\'.\'r\u{7}$\u{17}S:\rr@I(\u{10}\ \u{11}}\u{b}\u{7}0z5.n1\u{10}At<9.w\\?b\u{15}(\\hJ\u{10}cO\\^5Edc\u{1f}kq{t=z./\u{5}x\ \u{1}dZrJ%\u{5}`=VU_\u{7f}b;\u{13}\u{6}U.k\r\u{6}PBk]$p\u{1a}+FOH.\r,a\u{1}=DZZ\u{16}\ \u{18}cY\t\u{1e}\u{19}&<,\u{13}%\u{c}{Z!$Z,\u{17}\u{8}?\u{3}\u{4}]\u{1}H\u{c}(K*|l\ \u{15}8^:\u{e}\u{7f}D(P\u{1}XEk!$\u{14}/];E9d\u{e})|v\u{e}W*).\u{19}\u{11}5\u{7f}b8\ \u{18}:", &[ ('\u{2}', 8077), ('y', 8039), ('0', 8015), ('q', 7966), ('\u{8}', 7937), ('M', 7933), ('2', 7928), ('[', 7927), ('R', 7925), ('f', 7924) ][..], ('?', None) ) ); } ================================================ FILE: malachite-base/tests/chars/random/random_char_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::random_char_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn random_char_inclusive_range_helper( a: char, b: char, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = random_char_inclusive_range(EXAMPLE_SEED, a, b); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_char_inclusive_range() { random_char_inclusive_range_helper( 'a', 'a', "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaa", &[('a', 1000000)], ('a', None), ); random_char_inclusive_range_helper( 'a', 'c', "babcbbabacbabccabacccbaccbbbaacaccbabbaccacabcbbccbbbacabbbcabbcbbbcbcbbcabbbcabcbaacabbbc\ bccccccbacabaacbcababbaabcacabbbabaaacbccccbccabbaaacabaabccacabccccabbcacccaaccaccaccbbbca\ abcbaabcccbccbbbabc", &[('b', 333784), ('c', 333516), ('a', 332700)], ('b', None), ); random_char_inclusive_range_helper( 'a', 'z', "rlewrsgkdlbeouylrelopxqkoonftexoshqulgvonioatekqesxybqjsrbsajhpzzvzpcxcuyfkcsrexwwcjymyxhj\ pxkbyhasvvkwucaopwwpxyncdkvllxbdavqlxlsaxglzyhrulnqvqdipeklnnbgdhejggrhwgjjmmpndcjsvlqypdqq\ odasmavfvcmxcvoopcr", &[ ('x', 38904), ('q', 38795), ('s', 38687), ('w', 38660), ('d', 38655), ('f', 38647), ('a', 38592), ('n', 38569), ('j', 38531), ('z', 38530), ], ('n', None), ); random_char_inclusive_range_helper( '!', '9', "2,%723\'+$,\"%/59,2%,/081+//.&4%8/3(15,\'6/.)/!4%+1%389\"1*32\"3!*(060#8#59&+#32%877#*9-98\ (*08+\"9(!366+75#!/077089.#$+6,,8\"$!61,8,3!8\',9(25,.161$)0%+,..\"\'$(%*\'\'2(7\'**--0.$#*\ 36,190$11/$!3-!6&6#-8#6//0#2#5\"!", &[ ('8', 40444), ('1', 40300), ('7', 40244), ('3', 40201), ('&', 40174), ('$', 40171), ('.', 40117), ('*', 40111), ('!', 40107), ('#', 40076), ], ('-', None), ); random_char_inclusive_range_helper( '\u{D7FF}', '\u{E000}', "\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\ \u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\ \u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\ \u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\ \u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\ \u{e000}\u{d7ff}", &[('\u{e000}', 500473), ('\u{d7ff}', 499527)], ('\u{e000}', None), ); } #[test] #[should_panic] fn random_char_inclusive_range_fail() { random_char_inclusive_range(EXAMPLE_SEED, 'b', 'a'); } ================================================ FILE: malachite-base/tests/chars/random/random_char_range.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::random_char_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn random_char_range_helper( a: char, b: char, expected_values: &str, expected_common_values: &[(char, usize)], expected_median: (char, Option), ) { let xs = random_char_range(EXAMPLE_SEED, a, b); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_char_range() { random_char_range_helper( 'a', 'b', "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaa", &[('a', 1000000)], ('a', None), ); random_char_range_helper( 'a', 'd', "babcbbabacbabccabacccbaccbbbaacaccbabbaccacabcbbccbbbacabbbcabbcbbbcbcbbcabbbcabcbaacabbbc\ bccccccbacabaacbcababbaabcacabbbabaaacbccccbccabbaaacabaabccacabccccabbcacccaaccaccaccbbbca\ abcbaabcccbccbbbabc", &[('b', 333784), ('c', 333516), ('a', 332700)], ('b', None), ); random_char_range_helper( 'a', 'z', "rlewrsgkdlbeouylrelopxqkoonftexoshqulgvonioatekqesxybqjsrbsajhpvpcxcuyfkcsrexwwcjymyxhjpxk\ byhasvvkwucaopwwpxyncdkvllxbdavqlxlsaxglyhrulnqvqdipeklnnbgdhejggrhwgjjmmpndcjsvlqypdqqodas\ mavfvcmxcvoopcrcuba", &[ ('x', 40444), ('q', 40300), ('w', 40244), ('s', 40201), ('f', 40174), ('d', 40171), ('n', 40117), ('j', 40111), ('a', 40107), ('c', 40076), ], ('m', None), ); random_char_range_helper( '!', '9', "2,%723\'+$,\"%/5,2%,/081+//.&4%8/3(15,\'6/.)/!4%+1%38\"1*32\"3!*(060#8#5&+#32%877#*-8(*08+\ \"(!366+75#!/07708.#$+6,,8\"$!61,8,3!8\',(25,.161$)0%+,..\"\'$(%*\'\'2(7\'**--0.$#*36,10$11\ /$!3-!6&6#-8#6//0#2#5\"!#8/)%238/", &[ ('8', 42093), ('1', 42031), ('$', 41908), ('3', 41887), ('&', 41836), ('7', 41830), ('!', 41753), ('.', 41753), ('*', 41699), ('+', 41673), ], ('-', None), ); random_char_range_helper( '\u{D7FF}', '\u{E001}', "\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\ \u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\ \u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\ \u{e000}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\ \u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{d7ff}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\ \u{e000}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{d7ff}\u{e000}\ \u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{d7ff}\ \u{e000}\u{d7ff}\u{d7ff}\u{e000}\u{e000}\u{e000}\u{d7ff}\u{e000}\u{d7ff}\u{e000}\u{e000}\ \u{e000}\u{d7ff}", &[('\u{e000}', 500473), ('\u{d7ff}', 499527)], ('\u{e000}', None), ); } #[test] #[should_panic] fn random_char_range_fail() { random_char_range(EXAMPLE_SEED, 'a', 'a'); } ================================================ FILE: malachite-base/tests/chars/random/random_chars.rs ================================================ // Copyright © 2026 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 malachite_base::chars::random::random_chars; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; #[test] fn test_random_chars() { let xs = random_chars(EXAMPLE_SEED); let values = xs.clone().take(200).collect::(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_str(), common_values.as_slice(), median), ( "\u{5f771}\u{87234}\u{bcd36}\u{9e195}\u{5da07}\u{36553}\u{45028}\u{1cdfd}\u{d8530}\ \u{c7f2e}\u{ba4bc}\u{ff677}\u{a12e2}\u{d775c}\u{f827b}\u{bdf7a}簅\u{15aca}\u{4e5e2}\ \u{bb286}\u{18eeb}\u{bac4f}\u{5b55a}\u{65709}\u{b2626}\u{31a93}\u{8757b}\u{b3524}\ \u{fcc17}\u{32c01}\u{aada8}\u{57e7c}\u{eb738}栨\u{51a21}\u{ef6af}\u{b9caa}\u{d5099}\ \u{e397f}\u{32518}\u{6952d}\u{93ad5}\u{65c6e}\u{dc7bd}\u{aec4c}\u{dd524}\u{c0bc1}\ \u{795d0}\u{dbb9d}\u{a50fb}紐\u{4effe}\u{794af}\u{1b5a0}\u{56be3}\u{78fc9}\u{5870a}\ \u{106f48}\u{dfffa}\u{3cc01}\u{91290}\u{4628e}\u{bee71}\u{70e90}\u{b48bb}\u{3a445}\ \u{10a645}𬆠\u{e59de}\u{61b5a}\u{f4783}\u{c5ab2}幔\u{fdb07}\u{abccb}\u{ba750}\u{88d5a}\ \u{a706e}\u{969a2}\u{1089e3}\u{102189}\u{5f066}\u{10ea66}\u{435bb}\u{bcbd6}\u{4bc59}𱆞\ \u{f50a0}\u{47bc1}\u{5fd98}\u{91a7a}\u{100a8d}\u{e0017}\u{9db06}\u{1ab04}\u{780f6}ㅚ\ \u{5fc0a}\u{fb714}\u{c62cd}\u{b22dc}\u{10364e}\u{ee477}\u{f0983}\u{b5c36}\u{41f7b}\ \u{bdf28}\u{b27f7}\u{94dc8}\u{73381}\u{34609}\u{52911}\u{e56bf}\u{100af4}\u{396ff}\ \u{1051a8}𬅑\u{815dc}\u{fd1e7}\u{e6e9c}攠\u{eceaa}\u{10029d}\u{5e236}\u{d963b}\u{bbb1a}\ \u{108b67}\u{e5bc3}\u{97108}𢔱\u{9f166}\u{dedb4}\u{52752}\u{45bf5}\u{86d73}\u{ff2fd}쫵\ \u{78f74}\u{93bc0}\u{c308f}\u{e8b6}\u{89619}\u{1cdf9}\u{b9c86}\u{9f375}\u{c2487}\ \u{e1c3e}\u{f6e29}\u{79cc5}𬑎\u{9a803}\u{bf22e}\u{7e88e}\u{c50e8}\u{58c32}\u{79248}𰥦\ \u{b238b}\u{104b92}\u{8cc78}\u{eecc5}𢇡\u{e1fb6}\u{625ab}\u{a1988}䮨\u{bbaa5}\u{143be}\ \u{a12d4}\u{1028e1}\u{1c105}\u{9493f}\u{efa70}\u{13487}紋\u{b1948}\u{89052}\u{8c3cb}\ \u{b82d2}\u{729c3}\u{10c5ba}\u{dec07}𰢫\u{d277f}\u{3e5dc}\u{52431}\u{4867e}\u{75774}𪲨\ \u{b865a}\u{105191}\u{93891}\u{c4975}\u{c2f58}\u{d387c}\u{157dd}\u{77a83}\u{d6eec}\ \u{b2581}\u{9bb09}", &[ ('\u{1e21d}', 8), ('\u{bd934}', 8), ('\u{dc941}', 8), ('䄡', 7), ('霜', 7), ('𐊩', 7), ('𣡝', 7), ('𦇍', 7), ('𩩻', 7), ('𰊻', 7) ][..], ('\u{88629}', Some('\u{8862a}')) ) ); } ================================================ FILE: malachite-base/tests/comparison/macros.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, signed_triple_gen, unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; use std::cmp::{max, min}; #[test] pub fn test_min() { assert_eq!(min!(4), 4); assert_eq!(min!(4, 5, 6), 4); } #[test] pub fn test_max() { assert_eq!(max!(4), 4); assert_eq!(max!(4, 5, 6), 6); } fn unsigned_max_properties_helper() { unsigned_gen::().test_properties(|x| { assert_eq!(max!(x), x); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(max!(x, y), max(x, y)); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert_eq!(max!(x, y, z), max(max(x, y), z)); assert_eq!(max!(x, y, z), max(x, max(y, z))); }); } fn signed_max_properties_helper() { signed_gen::().test_properties(|x| { assert_eq!(max!(x), x); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(max!(x, y), max(x, y)); }); signed_triple_gen::().test_properties(|(x, y, z)| { assert_eq!(max!(x, y, z), max(max(x, y), z)); assert_eq!(max!(x, y, z), max(x, max(y, z))); }); } #[test] fn max_properties() { apply_fn_to_unsigneds!(unsigned_max_properties_helper); apply_fn_to_signeds!(signed_max_properties_helper); } fn unsigned_min_properties_helper() { unsigned_gen::().test_properties(|x| { assert_eq!(min!(x), x); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(min!(x, y), min(x, y)); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert_eq!(min!(x, y, z), min(min(x, y), z)); assert_eq!(min!(x, y, z), min(x, min(y, z))); }); } fn signed_min_properties_helper() { signed_gen::().test_properties(|x| { assert_eq!(min!(x), x); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(min!(x, y), min(x, y)); }); signed_triple_gen::().test_properties(|(x, y, z)| { assert_eq!(min!(x, y, z), min(min(x, y), z)); assert_eq!(min!(x, y, z), min(x, min(y, z))); }); } #[test] fn min_properties() { apply_fn_to_unsigneds!(unsigned_min_properties_helper); apply_fn_to_signeds!(signed_min_properties_helper); } ================================================ FILE: malachite-base/tests/extra_variadic/mod.rs ================================================ // Copyright © 2026 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::{RulerSequence, ruler_sequence}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::{RandomUnsignedRange, random_unsigned_range}; use malachite_base::random::Seed; use malachite_base::sets::random::{RandomBTreeSetsFixedLength, random_b_tree_sets_fixed_length}; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairs, clone_helper, exhaustive_dependent_pairs, }; use malachite_base::tuples::random::next_helper; use malachite_base::unions::UnionFromStrError; use malachite_base::vecs::ExhaustiveVecPermutations; use malachite_base::vecs::exhaustive::{ ExhaustiveOrderedUniqueCollections, ExhaustiveUniqueVecsGenerator, LexFixedLengthVecsOutput, UniqueIndices, exhaustive_ordered_unique_vecs_fixed_length, fixed_length_ordered_unique_indices_helper, next_bit_pattern, unique_indices, validate_oi_map, }; 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] ); ================================================ FILE: malachite-base/tests/iterators/bit_distributor/bit_map_as_slice.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; fn bit_distributor_helper(bit_distributor: &BitDistributor, bit_map: &[usize]) { assert_eq!(bit_distributor.bit_map_as_slice(), bit_map); } #[test] fn test_bit_map_as_slice() { bit_distributor_helper( &BitDistributor::new(&[BitDistributorOutputType::normal(1)]), &[0; 64], ); bit_distributor_helper( &BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]), &[ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, ], ); bit_distributor_helper( &BitDistributor::new(&[BitDistributorOutputType::normal(1); 3]), &[ 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, ], ); bit_distributor_helper( &BitDistributor::new(&[BitDistributorOutputType::normal(1); 5]), &[ 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, ], ); bit_distributor_helper( &BitDistributor::new(&[BitDistributorOutputType::normal(2); 2]), &[ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(2), ]), &[ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(1), ]), &[ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(3), ]), &[ 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]), &[ 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ]), &[ 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]), &[ 2, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ], ); bit_distributor_helper( &BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]), &[ 3, 2, 1, 3, 0, 1, 0, 2, 1, 0, 1, 0, 1, 0, 1, 3, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 3, ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1)]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( &bit_distributor, &[ 0, 0, 0, 0, 0, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]); bit_distributor.set_max_bits(&[1], 2); bit_distributor_helper( &bit_distributor, &[ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]); bit_distributor.set_max_bits(&[0], 2); bit_distributor_helper( &bit_distributor, &[ 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[0], 2); bit_distributor_helper( &bit_distributor, &[ 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[1], 2); bit_distributor_helper( &bit_distributor, &[ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 5]); bit_distributor.set_max_bits(&[0], 2); bit_distributor.set_max_bits(&[1], 1); bit_distributor.set_max_bits(&[2], 5); bit_distributor.set_max_bits(&[3], 3); bit_distributor.set_max_bits(&[4], 4); bit_distributor_helper( &bit_distributor, &[ 4, 3, 2, 1, 0, 4, 3, 2, 0, 4, 3, 2, 4, 2, 2, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, usize::MAX, ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(2); 2]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( &bit_distributor, &[ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( &bit_distributor, &[ 2, 1, 0, 2, 0, 0, 0, 1, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, ], ); } ================================================ FILE: malachite-base/tests/iterators/bit_distributor/get_output.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; fn bit_distributor_helper(mut bit_distributor: BitDistributor, expected_outputs: &[&[usize]]) { let mut outputs = Vec::new(); for _ in 0..20 { outputs.push( (0..bit_distributor.output_types.len()) .map(|i| bit_distributor.get_output(i)) .collect::>(), ); bit_distributor.increment_counter(); } assert_eq!(outputs, expected_outputs); } #[test] fn test_get_output() { bit_distributor_helper( BitDistributor::new(&[BitDistributorOutputType::normal(1)]), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); bit_distributor_helper( BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]), &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[1, 4], &[1, 5], ], ); bit_distributor_helper( BitDistributor::new(&[BitDistributorOutputType::normal(1); 3]), &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 3, 0], &[0, 3, 1], ], ); bit_distributor_helper( BitDistributor::new(&[BitDistributorOutputType::normal(1); 5]), &[ &[0, 0, 0, 0, 0], &[0, 0, 0, 0, 1], &[0, 0, 0, 1, 0], &[0, 0, 0, 1, 1], &[0, 0, 1, 0, 0], &[0, 0, 1, 0, 1], &[0, 0, 1, 1, 0], &[0, 0, 1, 1, 1], &[0, 1, 0, 0, 0], &[0, 1, 0, 0, 1], &[0, 1, 0, 1, 0], &[0, 1, 0, 1, 1], &[0, 1, 1, 0, 0], &[0, 1, 1, 0, 1], &[0, 1, 1, 1, 0], &[0, 1, 1, 1, 1], &[1, 0, 0, 0, 0], &[1, 0, 0, 0, 1], &[1, 0, 0, 1, 0], &[1, 0, 0, 1, 1], ], ); bit_distributor_helper( BitDistributor::new(&[BitDistributorOutputType::normal(2); 2]), &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[2, 2], &[2, 3], &[3, 0], &[3, 1], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(2), ]), &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[1, 4], &[1, 5], &[1, 6], &[1, 7], &[0, 8], &[0, 9], &[0, 10], &[0, 11], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(1), ]), &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[5, 0], &[5, 1], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(3), ]), &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[1, 4], &[1, 5], &[1, 6], &[1, 7], &[2, 0], &[2, 1], &[2, 2], &[2, 3], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]), &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[1, 4], &[1, 5], &[1, 6], &[1, 7], &[2, 0], &[2, 1], &[2, 2], &[2, 3], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ]), &[ &[0, 0], &[1, 0], &[2, 0], &[3, 0], &[0, 1], &[1, 1], &[2, 1], &[3, 1], &[4, 0], &[5, 0], &[6, 0], &[7, 0], &[4, 1], &[5, 1], &[6, 1], &[7, 1], &[0, 2], &[1, 2], &[2, 2], &[3, 2], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]), &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[2, 0, 0], &[2, 0, 1], &[2, 1, 0], &[2, 1, 1], ], ); bit_distributor_helper( BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]), &[ &[0, 0, 0, 0], &[0, 0, 0, 1], &[0, 0, 1, 0], &[0, 0, 1, 1], &[0, 1, 0, 0], &[0, 1, 0, 1], &[0, 1, 1, 0], &[0, 1, 1, 1], &[0, 0, 0, 2], &[0, 0, 0, 3], &[0, 0, 1, 2], &[0, 0, 1, 3], &[0, 1, 0, 2], &[0, 1, 0, 3], &[0, 1, 1, 2], &[0, 1, 1, 3], &[1, 0, 0, 0], &[1, 0, 0, 1], &[1, 0, 1, 0], &[1, 0, 1, 1], ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1)]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( bit_distributor, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]); bit_distributor.set_max_bits(&[1], 2); bit_distributor_helper( bit_distributor, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[5, 0], &[5, 1], ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 2]); bit_distributor.set_max_bits(&[0], 2); bit_distributor_helper( bit_distributor, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[1, 4], &[1, 5], ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[0], 2); bit_distributor_helper( bit_distributor, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[1, 4], &[1, 5], &[1, 6], &[1, 7], &[2, 0], &[2, 1], &[2, 2], &[2, 3], ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[1], 2); bit_distributor_helper( bit_distributor, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[2, 2], &[2, 3], &[3, 0], &[3, 1], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[4, 2], &[4, 3], ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(1); 5]); bit_distributor.set_max_bits(&[0], 2); bit_distributor.set_max_bits(&[1], 1); bit_distributor.set_max_bits(&[2], 5); bit_distributor.set_max_bits(&[3], 3); bit_distributor.set_max_bits(&[4], 4); bit_distributor_helper( bit_distributor, &[ &[0, 0, 0, 0, 0], &[0, 0, 0, 0, 1], &[0, 0, 0, 1, 0], &[0, 0, 0, 1, 1], &[0, 0, 1, 0, 0], &[0, 0, 1, 0, 1], &[0, 0, 1, 1, 0], &[0, 0, 1, 1, 1], &[0, 1, 0, 0, 0], &[0, 1, 0, 0, 1], &[0, 1, 0, 1, 0], &[0, 1, 0, 1, 1], &[0, 1, 1, 0, 0], &[0, 1, 1, 0, 1], &[0, 1, 1, 1, 0], &[0, 1, 1, 1, 1], &[1, 0, 0, 0, 0], &[1, 0, 0, 0, 1], &[1, 0, 0, 1, 0], &[1, 0, 0, 1, 1], ], ); let mut bit_distributor = BitDistributor::new(&[BitDistributorOutputType::normal(2); 2]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( bit_distributor, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[2, 2], &[2, 3], &[3, 0], &[3, 1], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], ], ); let mut bit_distributor = BitDistributor::new(&[ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ]); bit_distributor.set_max_bits(&[0], 5); bit_distributor_helper( bit_distributor, &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[2, 0, 0], &[2, 0, 1], &[2, 1, 0], &[2, 1, 1], ], ); } #[test] #[should_panic] fn get_output_fail() { let bd = BitDistributor::new(&[BitDistributorOutputType::normal(2); 3]); bd.get_output(4); } ================================================ FILE: malachite-base/tests/iterators/bit_distributor/increment_counter.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; #[test] fn test_increment_counter() { let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(1)]); let mut outputs = Vec::new(); for _ in 0..20 { outputs.push(bd.get_output(0)); bd.increment_counter(); } assert_eq!( outputs, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] ); } ================================================ FILE: malachite-base/tests/iterators/bit_distributor/new.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; #[test] fn test_bit_distributor() { BitDistributor::new(&[BitDistributorOutputType::normal(1)]); } #[test] #[should_panic] fn bit_distributor_fail_1() { BitDistributor::new(&[]); } #[test] #[should_panic] fn bit_distributor_fail_2() { BitDistributor::new(&[BitDistributorOutputType::tiny(); 2]); } ================================================ FILE: malachite-base/tests/iterators/bit_distributor/set_max_bits.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::bit_distributor::{BitDistributor, BitDistributorOutputType}; #[test] fn test_set_max_bits() { let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(2); 3]); assert_eq!( bd.bit_map_as_slice(), &[ 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2, 1, 1 ][..] ); bd.set_max_bits(&[0, 2], 5); assert_eq!( bd.bit_map_as_slice(), &[ 2, 2, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ][..] ); } #[test] #[should_panic] fn set_max_bits_fail_1() { let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(2); 3]); bd.set_max_bits(&[0], 0); } #[test] #[should_panic] fn set_max_bits_fail_2() { let mut bd = BitDistributor::new(&[BitDistributorOutputType::normal(2); 3]); bd.set_max_bits(&[0, 3], 2); } ================================================ FILE: malachite-base/tests/iterators/comparison/delta_directions.rs ================================================ // Copyright © 2026 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::comparison::delta_directions; use std::cmp::Ordering::{self, *}; fn delta_directions_helper(xs: &[u8], result: &[Ordering]) { assert_eq!(delta_directions(xs.iter()).collect_vec(), result); assert_eq!(result.len(), xs.len().saturating_sub(1)); assert_eq!( delta_directions(xs.iter().rev()) .map(Ordering::reverse) .collect_vec(), result.iter().copied().rev().collect_vec() ); } #[test] fn test_delta_directions() { delta_directions_helper(&[], &[]); delta_directions_helper(&[5], &[]); delta_directions_helper(&[5, 6], &[Greater]); delta_directions_helper(&[5, 5], &[Equal]); delta_directions_helper(&[5, 4], &[Less]); delta_directions_helper(&[1, 2, 3, 4], &[Greater; 3]); delta_directions_helper(&[1, 2, 2, 4], &[Greater, Equal, Greater]); delta_directions_helper(&[1, 3, 2, 4], &[Greater, Less, Greater]); delta_directions_helper( &[3, 1, 4, 1, 5, 9], &[Less, Greater, Less, Greater, Greater], ); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_strictly_ascending.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{ is_strictly_ascending, is_strictly_descending, is_weakly_ascending, is_weakly_descending, }; fn is_strictly_ascending_helper(xs: &[u8], result: bool) { assert_eq!(is_strictly_ascending(xs.iter()), result); assert_eq!(is_strictly_descending(xs.iter().rev()), result); if xs.len() < 2 { assert!(result); } if result { assert!(is_weakly_ascending(xs.iter())); if xs.len() > 1 { assert!(!is_weakly_descending(xs.iter())); } } } #[test] fn test_is_strictly_ascending() { is_strictly_ascending_helper(&[], true); is_strictly_ascending_helper(&[5], true); is_strictly_ascending_helper(&[5, 6], true); is_strictly_ascending_helper(&[5, 5], false); is_strictly_ascending_helper(&[5, 4], false); is_strictly_ascending_helper(&[1, 2, 3, 4], true); is_strictly_ascending_helper(&[1, 2, 2, 4], false); is_strictly_ascending_helper(&[1, 3, 2, 4], false); is_strictly_ascending_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_strictly_descending.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{ is_strictly_ascending, is_strictly_descending, is_weakly_ascending, is_weakly_descending, }; fn is_strictly_descending_helper(xs: &[u8], result: bool) { assert_eq!(is_strictly_descending(xs.iter()), result); assert_eq!(is_strictly_ascending(xs.iter().rev()), result); if xs.len() < 2 { assert!(result); } if result { assert!(is_weakly_descending(xs.iter())); if xs.len() > 1 { assert!(!is_weakly_ascending(xs.iter())); } } } #[test] fn test_is_strictly_descending() { is_strictly_descending_helper(&[], true); is_strictly_descending_helper(&[5], true); is_strictly_descending_helper(&[6, 5], true); is_strictly_descending_helper(&[6, 6], false); is_strictly_descending_helper(&[6, 7], false); is_strictly_descending_helper(&[4, 3, 2, 1], true); is_strictly_descending_helper(&[4, 2, 2, 1], false); is_strictly_descending_helper(&[4, 2, 3, 1], false); is_strictly_descending_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_strictly_zigzagging.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{ is_strictly_zigzagging, is_weakly_ascending, is_weakly_descending, is_weakly_zigzagging, }; fn is_strictly_zigzagging_helper(xs: &[u8], result: bool) { assert_eq!(is_strictly_zigzagging(xs.iter()), result); assert_eq!(is_strictly_zigzagging(xs.iter().rev()), result); if xs.len() < 2 { assert!(result); } if result { assert!(is_weakly_zigzagging(xs.iter())); if xs.len() > 2 { assert!(!is_weakly_ascending(xs.iter())); assert!(!is_weakly_descending(xs.iter())); } } } #[test] fn test_is_strictly_zigzagging() { is_strictly_zigzagging_helper(&[], true); is_strictly_zigzagging_helper(&[5], true); is_strictly_zigzagging_helper(&[5, 6], true); is_strictly_zigzagging_helper(&[5, 5], false); is_strictly_zigzagging_helper(&[5, 4], true); is_strictly_zigzagging_helper(&[1, 2, 3, 4], false); is_strictly_zigzagging_helper(&[1, 2, 2, 4], false); is_strictly_zigzagging_helper(&[1, 3, 2, 4], true); is_strictly_zigzagging_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_weakly_ascending.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{ is_strictly_ascending, is_weakly_ascending, is_weakly_descending, }; fn is_weakly_ascending_helper(xs: &[u8], result: bool) { assert_eq!(is_weakly_ascending(xs.iter()), result); assert_eq!(is_weakly_descending(xs.iter().rev()), result); if xs.len() < 2 { assert!(result); } if !result { assert!(!is_strictly_ascending(xs.iter())); } } #[test] fn test_is_weakly_ascending() { is_weakly_ascending_helper(&[], true); is_weakly_ascending_helper(&[5], true); is_weakly_ascending_helper(&[5, 6], true); is_weakly_ascending_helper(&[5, 5], true); is_weakly_ascending_helper(&[5, 4], false); is_weakly_ascending_helper(&[1, 2, 3, 4], true); is_weakly_ascending_helper(&[1, 2, 2, 4], true); is_weakly_ascending_helper(&[1, 3, 2, 4], false); is_weakly_ascending_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_weakly_descending.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{ is_strictly_descending, is_weakly_ascending, is_weakly_descending, }; fn is_weakly_descending_helper(xs: &[u8], result: bool) { assert_eq!(is_weakly_descending(xs.iter()), result); assert_eq!(is_weakly_ascending(xs.iter().rev()), result); if xs.len() < 2 { assert!(result); } if !result { assert!(!is_strictly_descending(xs.iter())); } } #[test] fn test_is_weakly_descending() { is_weakly_descending_helper(&[], true); is_weakly_descending_helper(&[5], true); is_weakly_descending_helper(&[6, 5], true); is_weakly_descending_helper(&[6, 6], true); is_weakly_descending_helper(&[6, 7], false); is_weakly_descending_helper(&[4, 3, 2, 1], true); is_weakly_descending_helper(&[4, 2, 2, 1], true); is_weakly_descending_helper(&[4, 2, 3, 1], false); is_weakly_descending_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/comparison/is_weakly_zigzagging.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{is_strictly_zigzagging, is_weakly_zigzagging}; fn is_weakly_zigzagging_helper(xs: &[u8], result: bool) { assert_eq!(is_weakly_zigzagging(xs.iter()), result); assert_eq!(is_weakly_zigzagging(xs.iter().rev()), result); if xs.len() < 3 { assert!(result); } if !result { assert!(!is_strictly_zigzagging(xs.iter())); } } #[test] fn test_is_weakly_zigzagging() { is_weakly_zigzagging_helper(&[], true); is_weakly_zigzagging_helper(&[5], true); is_weakly_zigzagging_helper(&[5, 6], true); is_weakly_zigzagging_helper(&[5, 5], true); is_weakly_zigzagging_helper(&[5, 4], true); is_weakly_zigzagging_helper(&[1, 2, 3, 4], false); is_weakly_zigzagging_helper(&[1, 2, 2, 4], true); is_weakly_zigzagging_helper(&[1, 3, 2, 4], true); is_weakly_zigzagging_helper(&[3, 1, 4, 1, 5, 9], false); } ================================================ FILE: malachite-base/tests/iterators/count_is_at_least.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::count_is_at_least; use std::iter::repeat; fn count_is_at_least_helper(xs: &[u8], n: usize, result: bool) { assert_eq!(count_is_at_least(xs.iter(), n), result); assert_eq!(count_is_at_least(xs.iter().rev(), n), result); } #[test] fn test_count_is_at_least() { count_is_at_least_helper(&[], 0, true); count_is_at_least_helper(&[], 1, false); count_is_at_least_helper(&[5], 0, true); count_is_at_least_helper(&[5], 1, true); count_is_at_least_helper(&[5], 2, false); count_is_at_least_helper(&[1, 2, 3, 4], 4, true); count_is_at_least_helper(&[1, 2, 3, 4], 5, false); count_is_at_least_helper(&[4; 100], 90, true); count_is_at_least_helper(&[4; 100], 101, false); assert_eq!(count_is_at_least(repeat(10), 20), true); } ================================================ FILE: malachite-base/tests/iterators/count_is_at_most.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::count_is_at_most; use std::iter::repeat; fn count_is_at_most_helper(xs: &[u8], n: usize, result: bool) { assert_eq!(count_is_at_most(xs.iter(), n), result); assert_eq!(count_is_at_most(xs.iter().rev(), n), result); } #[test] fn test_count_is_at_most() { count_is_at_most_helper(&[], 0, true); count_is_at_most_helper(&[], 1, true); count_is_at_most_helper(&[5], 0, false); count_is_at_most_helper(&[5], 1, true); count_is_at_most_helper(&[5], 2, true); count_is_at_most_helper(&[1, 2, 3, 4], 3, false); count_is_at_most_helper(&[1, 2, 3, 4], 4, true); count_is_at_most_helper(&[1, 2, 3, 4], 5, true); count_is_at_most_helper(&[4; 100], 120, true); count_is_at_most_helper(&[4; 100], 90, false); assert_eq!(count_is_at_most(repeat(10), 20), false); } ================================================ FILE: malachite-base/tests/iterators/first_and_last.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::first_and_last; fn first_and_last_helper(xs: &[u8], result: Option<(u8, u8)>) { assert_eq!(first_and_last(&mut xs.iter().copied()), result); } #[test] fn test_first_and_last() { first_and_last_helper(&[1, 2, 10, 11, 12, 7, 8, 16, 5], Some((1, 5))); first_and_last_helper(&[5], Some((5, 5))); first_and_last_helper(&[], None); } ================================================ FILE: malachite-base/tests/iterators/is_constant.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::{is_weakly_ascending, is_weakly_descending}; use malachite_base::iterators::is_constant; fn is_constant_helper(xs: &[u8], result: bool) { assert_eq!(is_constant(xs.iter()), result); assert_eq!(is_constant(xs.iter().rev()), result); assert_eq!( is_weakly_ascending(xs.iter()) && is_weakly_descending(xs.iter()), result ); if xs.len() < 2 { assert!(result); } } #[test] fn test_is_constant() { is_constant_helper(&[], true); is_constant_helper(&[5], true); is_constant_helper(&[5, 6], false); is_constant_helper(&[5, 5], true); is_constant_helper(&[5, 4], false); is_constant_helper(&[1; 4], true); is_constant_helper(&[1, 2, 3, 4], false); is_constant_helper(&[1, 2, 2, 4], false); is_constant_helper(&[4; 100], true); assert_eq!(is_constant([1, 2].into_iter().cycle()), false); } ================================================ FILE: malachite-base/tests/iterators/is_unique.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::is_unique; fn is_unique_helper(xs: &[u8], result: bool) { assert_eq!(is_unique(xs.iter()), result); assert_eq!(is_unique(xs.iter().rev()), result); } #[test] fn test_is_unique() { is_unique_helper(&[], true); is_unique_helper(&[5], true); is_unique_helper(&[5, 6], true); is_unique_helper(&[5, 5], false); is_unique_helper(&[5, 4], true); is_unique_helper(&[1, 2, 3, 4], true); is_unique_helper(&[1, 2, 2, 4], false); is_unique_helper(&[1, 2, 3, 1], false); is_unique_helper(&[4; 100], false); assert_eq!(is_unique([1, 2].iter().cycle()), false); } ================================================ FILE: malachite-base/tests/iterators/iter_windows.rs ================================================ // Copyright © 2026 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::iter_windows; use std::fmt::Debug; fn iter_windows_helper(size: usize, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { let windows = iter_windows(size, xs) .map(|ws| ws.iter().cloned().collect_vec()) .collect_vec(); assert_eq!( windows.iter().map(Vec::as_slice).collect_vec().as_slice(), out ); } #[test] fn test_iter_windows() { iter_windows_helper(1, 0..=5, &[&[0], &[1], &[2], &[3], &[4], &[5]]); iter_windows_helper(2, 0..=5, &[&[0, 1], &[1, 2], &[2, 3], &[3, 4], &[4, 5]]); iter_windows_helper(3, 0..=5, &[&[0, 1, 2], &[1, 2, 3], &[2, 3, 4], &[3, 4, 5]]); iter_windows_helper(4, 0..=5, &[&[0, 1, 2, 3], &[1, 2, 3, 4], &[2, 3, 4, 5]]); iter_windows_helper(5, 0..=5, &[&[0, 1, 2, 3, 4], &[1, 2, 3, 4, 5]]); iter_windows_helper(6, 0..=5, &[&[0, 1, 2, 3, 4, 5]]); iter_windows_helper(7, 0..=5, &[]); } #[test] #[should_panic] fn iter_windows_fail() { iter_windows(0, 0..10); } ================================================ FILE: malachite-base/tests/iterators/iterator_cache.rs ================================================ // Copyright © 2026 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::__std_iter::empty; use malachite_base::iterators::iterator_cache::IteratorCache; use malachite_base::nevers::Never; use malachite_base::num::exhaustive::exhaustive_signeds; #[test] fn test_iterator_cache() { let mut xs = IteratorCache::new(empty::()); assert_eq!(xs.known_len(), None); assert_eq!(xs.get(1), None); assert_eq!(xs.known_len(), Some(0)); assert_eq!(xs.get(0), None); let mut xs = IteratorCache::new([1, 2, 3].iter().copied()); assert_eq!(xs.known_len(), None); assert_eq!(xs.get(1), Some(&2)); assert_eq!(xs.assert_get(1), &2); assert_eq!(xs.known_len(), None); assert_eq!(xs.get(0), Some(&1)); assert_eq!(xs.assert_get(0), &1); assert_eq!(xs.get(3), None); assert_eq!(xs.known_len(), Some(3)); assert_eq!(xs.get(2), Some(&3)); assert_eq!(xs.assert_get(2), &3); let mut xs = IteratorCache::new(exhaustive_signeds::()); assert_eq!(xs.get(1), Some(&1)); assert_eq!(xs.assert_get(1), &1); assert_eq!(xs.known_len(), None); assert_eq!(xs.get(0), Some(&0)); assert_eq!(xs.assert_get(0), &0); assert_eq!(xs.get(3), Some(&2)); assert_eq!(xs.assert_get(3), &2); assert_eq!(xs.get(100), Some(&-50)); assert_eq!(xs.assert_get(100), &-50); assert_eq!(xs.known_len(), None); } #[test] #[should_panic] fn iterator_cache_fail() { IteratorCache::new(empty::()).assert_get(0); } ================================================ FILE: malachite-base/tests/iterators/matching_intervals_in_iterator.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::matching_intervals_in_iterator; fn matching_intervals_in_iterator_helper bool>(xs: &[u8], f: F, result: &[(u8, u8)]) { assert_eq!( matching_intervals_in_iterator(xs.iter().copied(), f).as_slice(), result ); } #[test] fn test_matching_intervals_in_iterator() { let xs = &[1, 2, 10, 11, 12, 7, 8, 16, 5]; matching_intervals_in_iterator_helper(xs, |&x| x >= 10, &[(10, 12), (16, 16)]); matching_intervals_in_iterator_helper(xs, |&x| x < 10, &[(1, 2), (7, 8), (5, 5)]); matching_intervals_in_iterator_helper(xs, |&x| x >= 100, &[]); matching_intervals_in_iterator_helper(xs, |&x| x < 100, &[(1, 5)]); } ================================================ FILE: malachite-base/tests/iterators/nonzero_values.rs ================================================ // Copyright © 2026 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::nonzero_values; #[test] pub fn test_nonzero_values() { let test = |xs: &[u32], out: &[u32]| { assert_eq!(nonzero_values(xs.iter().copied()).collect_vec(), out); }; test(&[], &[]); test(&[1, 2, 3], &[1, 2, 3]); test(&[1, 0, 3], &[1, 3]); test(&[1, 2, 0, 0, 0], &[1, 2]); test(&[0, 0, 0], &[]); } ================================================ FILE: malachite-base/tests/iterators/prefix_to_string.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::prefix_to_string; #[test] fn test_prefix_to_string() { let test = |xs: &[u32], max_len: usize, out: &str| { assert_eq!(prefix_to_string(xs.iter(), max_len), out); }; test(&[], 1, "[]"); test(&[1, 2, 3, 4], 1, "[1, ...]"); test(&[1, 2, 3, 4], 2, "[1, 2, ...]"); test(&[1, 2, 3, 4], 3, "[1, 2, 3, ...]"); test(&[1, 2, 3, 4], 4, "[1, 2, 3, 4]"); test(&[1, 2, 3, 4], 10, "[1, 2, 3, 4]"); } #[test] #[should_panic] fn prefix_to_string_fail() { prefix_to_string([1, 2, 3].iter(), 0); } ================================================ FILE: malachite-base/tests/iterators/thue_morse_sequence.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::thue_morse_sequence; #[test] pub fn test_thue_morse_sequence() { let s: String = thue_morse_sequence() .take(1000) .map(|b| if b { '1' } else { '0' }) .collect(); assert_eq!( s, "01101001100101101001011001101001100101100110100101101001100101101001011001101001011010011\ 001011001101001100101101001011001101001100101100110100101101001100101100110100110010110100\ 101100110100101101001100101101001011001101001100101100110100101101001100101101001011001101\ 001011010011001011001101001100101101001011001101001011010011001011010010110011010011001011\ 001101001011010011001011001101001100101101001011001101001100101100110100101101001100101101\ 001011001101001011010011001011001101001100101101001011001101001100101100110100101101001100\ 101100110100110010110100101100110100101101001100101101001011001101001100101100110100101101\ 001100101100110100110010110100101100110100110010110011010010110100110010110100101100110100\ 101101001100101100110100110010110100101100110100101101001100101101001011001101001100101100\ 110100101101001100101101001011001101001011010011001011001101001100101101001011001101001100\ 101100110100101101001100101100110100110010110100101100110100101101001100101101001011001101\ 00110010110" ); } ================================================ FILE: malachite-base/tests/iterators/with_special_value.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::iterators::with_special_value; use malachite_base::num::random::random_primitive_ints; use malachite_base::options::random::random_options; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::fmt::Debug; fn with_special_value_helper( special_value: I::Item, p_special_numerator: u64, p_special_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_median: (I::Item, Option), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = with_special_value( EXAMPLE_SEED, special_value, p_special_numerator, p_special_denominator, xs_gen, ); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_with_special_value() { // special_value = 0, p = 1/2 with_special_value_helper( 0, 1, 2, &random_primitive_ints::, &[0, 0, 0, 85, 0, 11, 0, 0, 0, 136, 200, 235, 0, 0, 134, 0, 0, 0, 0, 0], &[ (0, 501536), (81, 2080), (208, 2071), (35, 2070), (211, 2051), (112, 2043), (162, 2043), (143, 2041), (220, 2040), (73, 2038), ], (0, None), ); // special_value = 0, p = 50/51 with_special_value_helper( 0, 50, 51, &random_primitive_ints::, &[0; 20], &[ (0, 980537), (18, 101), (25, 99), (116, 97), (226, 97), (237, 97), (23, 95), (185, 95), (30, 94), (73, 94), ], (0, None), ); // p = special_value = 0, 1/51 with_special_value_helper( 0, 1, 51, &random_primitive_ints::, &[ 85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32, 166, 234, 30, 218, 90, 106, ], &[ (0, 23543), (58, 4029), (81, 4001), (194, 3979), (66, 3971), (64, 3969), (143, 3965), (4, 3962), (196, 3951), (208, 3939), ], (125, None), ); // special_value = 0, p = 1/11 with_special_value_helper( Some(0), 1, 11, &|seed| random_options(seed, 1, 11, &random_primitive_ints::), &[ Some(229), Some(58), Some(126), Some(0), Some(192), Some(140), Some(235), Some(50), Some(162), Some(5), Some(14), Some(107), Some(218), Some(0), Some(96), Some(86), Some(51), Some(240), Some(0), Some(186), ], &[ (Some(0), 94315), (None, 82945), (Some(186), 3381), (Some(193), 3376), (Some(55), 3364), (Some(83), 3364), (Some(245), 3360), (Some(148), 3352), (Some(143), 3345), (Some(136), 3339), ], (Some(101), None), ); } #[test] #[should_panic] fn with_special_value_fail_1() { with_special_value(EXAMPLE_SEED, 0, 1, 0, &random_primitive_ints::); } #[test] #[should_panic] fn with_special_value_fail_2() { with_special_value(EXAMPLE_SEED, 0, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/iterators/with_special_values.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::iterators::with_special_values; use malachite_base::num::random::random_primitive_ints; use malachite_base::options::random::random_options; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::fmt::Debug; fn with_special_values_helper( special_values: &[I::Item], p_special_numerator: u64, p_special_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[I::Item], expected_common_values: &[(I::Item, usize)], expected_median: (I::Item, Option), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = with_special_values( EXAMPLE_SEED, special_values.to_vec(), p_special_numerator, p_special_denominator, xs_gen, ); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_with_special_values() { // special_values = &[0, 1, 2], p = 1/2 with_special_values_helper( &[0, 1, 2], 1, 2, &random_primitive_ints::, &[2, 0, 2, 85, 0, 11, 1, 2, 0, 136, 200, 235, 0, 0, 134, 2, 0, 0, 0, 0], &[ (2, 168816), (0, 168721), (1, 167914), (81, 2080), (208, 2071), (35, 2070), (211, 2051), (112, 2043), (162, 2043), (143, 2041), ], (2, None), ); // special_values = &[0, 1], p = 50/51 with_special_values_helper( &[0, 1], 50, 51, &random_primitive_ints::, &[0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0], &[ (1, 490697), (0, 489910), (18, 101), (25, 99), (116, 97), (226, 97), (237, 97), (23, 95), (185, 95), (30, 94), ], (1, None), ); // p = special_values = &[0, 1, 2, 3], 1/51 with_special_values_helper( &[0, 1, 2, 3], 1, 51, &random_primitive_ints::, &[ 85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32, 166, 234, 30, 218, 90, 106, ], &[ (2, 8933), (0, 8779), (1, 8736), (3, 8736), (58, 4029), (81, 4001), (194, 3979), (66, 3971), (64, 3969), (143, 3965), ], (125, None), ); // special_values = &[None, Some(0), Some(1)], p = 1/11 with_special_values_helper( &[None, Some(0), Some(1)], 1, 11, &|seed| random_options(seed, 1, 11, &random_primitive_ints::), &[ Some(229), Some(58), Some(126), Some(1), Some(192), Some(140), Some(235), Some(50), Some(162), Some(5), Some(14), Some(107), Some(218), None, Some(96), Some(86), Some(51), Some(240), Some(1), Some(186), ], &[ (None, 113578), (Some(1), 33583), (Some(0), 33308), (Some(186), 3381), (Some(193), 3376), (Some(55), 3364), (Some(83), 3364), (Some(245), 3360), (Some(148), 3352), (Some(143), 3345), ], (Some(101), None), ); } #[test] #[should_panic] fn with_special_values_fail_1() { with_special_values(EXAMPLE_SEED, vec![0, 1], 1, 0, &random_primitive_ints::); } #[test] #[should_panic] fn with_special_values_fail_2() { with_special_values(EXAMPLE_SEED, vec![0, 1], 2, 1, &random_primitive_ints::); } #[test] #[should_panic] fn with_special_values_fail_3() { with_special_values(EXAMPLE_SEED, vec![], 1, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/lib.rs ================================================ // Copyright © 2026 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 . #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::trivially_copy_pass_by_ref )] #![allow( clippy::assertions_on_constants, // Compile-time asserts still useful clippy::bool_assert_comparison, // Often clearer than using ! clippy::cognitive_complexity, clippy::excessive_precision, clippy::float_cmp, clippy::too_many_arguments, clippy::upper_case_acronyms, unstable_name_collisions )] extern crate core; extern crate itertools; #[macro_use] extern crate malachite_base; #[macro_use] extern crate maplit; extern crate rand; extern crate rand_chacha; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; const SAMPLE_OUTPUT_TYPES_2: [[BitDistributorOutputType; 2]; 4] = [ [BitDistributorOutputType::normal(1); 2], [BitDistributorOutputType::normal(2); 2], [BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(2)], [BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny()], ]; const SAMPLE_OUTPUT_TYPES_3: [[BitDistributorOutputType; 3]; 9] = [ [BitDistributorOutputType::normal(1); 3], [BitDistributorOutputType::normal(2); 3], [ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(3), ], [ BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ], [ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ], [ BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ], [ BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ], [ BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ], [ BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ], ]; pub mod bools { pub mod constants; pub mod exhaustive; pub mod not_assign; pub mod random { pub mod get_weighted_random_bool; pub mod random_bools; pub mod weighted_random_bools; } } pub mod comparison { pub mod macros; } pub mod chars { pub mod char_type; pub mod constants; pub mod crement { pub mod char_to_contiguous_range; pub mod contiguous_range_to_char; #[allow(clippy::module_inception)] pub mod crement; } pub mod exhaustive { pub mod ascii_chars_increasing; pub mod chars_increasing; pub mod exhaustive_ascii_chars; pub mod exhaustive_chars; } pub mod is_graphic; pub mod random { pub mod graphic_weighted_random_ascii_chars; pub mod graphic_weighted_random_char_inclusive_range; pub mod graphic_weighted_random_char_range; pub mod graphic_weighted_random_chars; pub mod random_ascii_chars; pub mod random_char_inclusive_range; pub mod random_char_range; pub mod random_chars; } } pub mod extra_variadic; pub mod iterators { pub mod bit_distributor { pub mod bit_map_as_slice; pub mod get_output; pub mod increment_counter; pub mod new; pub mod set_max_bits; } pub mod comparison { pub mod delta_directions; pub mod is_strictly_ascending; pub mod is_strictly_descending; pub mod is_strictly_zigzagging; pub mod is_weakly_ascending; pub mod is_weakly_descending; pub mod is_weakly_zigzagging; } pub mod count_is_at_least; pub mod count_is_at_most; pub mod first_and_last; pub mod is_constant; pub mod is_unique; pub mod iter_windows; pub mod iterator_cache; pub mod matching_intervals_in_iterator; pub mod nonzero_values; pub mod prefix_to_string; pub mod thue_morse_sequence; pub mod with_special_value; pub mod with_special_values; } pub mod named; pub mod nevers { #[allow(clippy::module_inception)] pub mod nevers; } pub mod num { pub mod arithmetic { pub mod abs; pub mod abs_diff; pub mod add_mul; pub mod arithmetic_checked_shl; pub mod arithmetic_checked_shr; pub mod binomial_coefficient; pub mod ceiling; pub mod checked_abs; pub mod checked_add_mul; pub mod checked_neg; pub mod checked_pow; pub mod checked_square; pub mod checked_sub_mul; pub mod coprime_with; pub mod div_exact; pub mod div_mod; pub mod div_round; pub mod divisible_by; pub mod divisible_by_power_of_2; pub mod eq_mod; pub mod eq_mod_power_of_2; pub mod extended_gcd; pub mod factorial; pub mod floor; pub mod gcd; pub mod is_power_of_2; pub mod kronecker_symbol; pub mod lcm; pub mod log_base; pub mod log_base_2; pub mod log_base_power_of_2; pub mod mod_add; pub mod mod_inverse; pub mod mod_is_reduced; pub mod mod_mul; pub mod mod_neg; pub mod mod_op; pub mod mod_pow; pub mod mod_power_of_2; pub mod mod_power_of_2_add; pub mod mod_power_of_2_inverse; pub mod mod_power_of_2_is_reduced; pub mod mod_power_of_2_mul; pub mod mod_power_of_2_neg; pub mod mod_power_of_2_pow; pub mod mod_power_of_2_shl; pub mod mod_power_of_2_shr; pub mod mod_power_of_2_square; pub mod mod_power_of_2_sub; pub mod mod_shl; pub mod mod_shr; pub mod mod_square; pub mod mod_sub; pub mod neg; pub mod next_power_of_2; pub mod overflowing_abs; pub mod overflowing_add; pub mod overflowing_add_mul; pub mod overflowing_div; pub mod overflowing_mul; pub mod overflowing_neg; pub mod overflowing_pow; pub mod overflowing_square; pub mod overflowing_sub; pub mod overflowing_sub_mul; pub mod parity; pub mod pow; pub mod power_of_2; pub mod primorial; pub mod reciprocal; pub mod root; pub mod rotate; pub mod round_to_multiple; pub mod round_to_multiple_of_power_of_2; pub mod saturating_abs; pub mod saturating_add; pub mod saturating_add_mul; pub mod saturating_mul; pub mod saturating_neg; pub mod saturating_pow; pub mod saturating_square; pub mod saturating_sub; pub mod saturating_sub_mul; pub mod shl_round; pub mod shr_round; pub mod sign; pub mod sqrt; pub mod square; pub mod sub_mul; pub mod wrapping_abs; pub mod wrapping_add; pub mod wrapping_add_mul; pub mod wrapping_div; pub mod wrapping_mul; pub mod wrapping_neg; pub mod wrapping_pow; pub mod wrapping_square; pub mod wrapping_sub; pub mod wrapping_sub_mul; pub mod x_mul_y_to_zz; pub mod xx_add_yy_to_zz; pub mod xx_div_mod_y_to_qr; pub mod xx_sub_yy_to_zz; pub mod xxx_add_yyy_to_zzz; pub mod xxx_sub_yyy_to_zzz; pub mod xxxx_add_yyyy_to_zzzz; } pub mod basic { pub mod constants; } pub mod comparison { pub mod cmp_abs; pub mod eq_abs; } pub mod conversion { pub mod digits { pub mod general_digits { pub mod from_digits; pub mod to_digits; } pub mod power_of_2_digits { pub mod from_power_of_2_digits; pub mod power_of_2_digit_iterable; pub mod to_power_of_2_digits; } } pub mod froms { pub mod convertible_from; pub mod from; pub mod overflowing_from; pub mod rounding_from; pub mod saturating_from; pub mod try_from_and_exact_from; pub mod wrapping_from; } pub mod half { pub mod join_halves; pub mod lower_half; pub mod split_in_half; pub mod upper_half; } pub mod is_integer; pub mod mantissa_and_exponent { pub mod integer_mantissa_and_exponent; pub mod raw_mantissa_and_exponent; pub mod sci_mantissa_and_exponent; } pub mod slice { pub mod from_other_type_slice; pub mod vec_from_other_type; pub mod vec_from_other_type_slice; } pub mod string { pub mod from_sci_string; pub mod from_string; pub mod options { pub mod from_sci_string_options; pub mod to_sci_options; } pub mod to_sci; pub mod to_string; } } pub mod exhaustive { pub mod exhaustive_finite_primitive_floats; pub mod exhaustive_natural_signeds; pub mod exhaustive_negative_finite_primitive_floats; pub mod exhaustive_negative_primitive_floats; pub mod exhaustive_negative_signeds; pub mod exhaustive_nonzero_finite_primitive_floats; pub mod exhaustive_nonzero_finite_primitive_floats_in_range; pub mod exhaustive_nonzero_primitive_floats; pub mod exhaustive_nonzero_signeds; pub mod exhaustive_positive_finite_primitive_floats; pub mod exhaustive_positive_finite_primitive_floats_in_range; pub mod exhaustive_positive_primitive_floats; pub mod exhaustive_positive_primitive_ints; pub mod exhaustive_primitive_float_inclusive_range; pub mod exhaustive_primitive_float_range; pub mod exhaustive_primitive_floats; pub mod exhaustive_primitive_floats_with_sci_exponent; pub mod exhaustive_primitive_floats_with_sci_exponent_and_precision; pub mod exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range; pub mod exhaustive_primitive_floats_with_sci_exponent_in_range; pub mod exhaustive_signed_inclusive_range; pub mod exhaustive_signed_range; pub mod exhaustive_signeds; pub mod exhaustive_unsigneds; pub mod finite_primitive_floats_increasing; pub mod negative_finite_primitive_floats_increasing; pub mod negative_primitive_floats_increasing; pub mod nonzero_finite_primitive_floats_increasing; pub mod nonzero_primitive_floats_increasing; pub mod positive_finite_primitive_floats_increasing; pub mod positive_primitive_floats_increasing; pub mod primitive_float_increasing_inclusive_range; pub mod primitive_float_increasing_range; pub mod primitive_floats_increasing; pub mod primitive_int_increasing_inclusive_range; pub mod primitive_int_increasing_range; } pub mod factorization { pub mod factor; pub mod is_power; pub mod is_prime; pub mod is_square; pub mod prime_indicator_sequence; pub mod prime_indicator_sequence_less_than; pub mod prime_sieve; pub mod primes; pub mod primitive_root_prime; } pub mod float { pub mod basic { pub mod abs_negative_zero; pub mod from_ordered_representation; pub mod is_negative_zero; pub mod max_precision_for_sci_exponent; pub mod next_higher; pub mod next_lower; pub mod precision; pub mod to_ordered_representation; } pub mod nice_float { pub mod cmp; pub mod cmp_abs; pub mod eq; pub mod eq_abs; pub mod from_str; pub mod hash; pub mod to_string; } } pub mod iterators { pub mod bit_distributor_sequence; pub mod iterator_to_bit_chunks; pub mod ruler_sequence; } pub mod logic { pub mod bit_access { pub mod assign_bit; pub mod clear_bit; pub mod flip_bit; pub mod get_bit; pub mod set_bit; } pub mod bit_block_access { pub mod assign_bits; pub mod get_bits; } pub mod bit_convertible { pub mod from_bits; pub mod to_bits; } pub mod bit_iterable; pub mod bit_scan { pub mod index_of_next_false_bit; pub mod index_of_next_true_bit; } pub mod get_highest_bit; pub mod hamming_distance; pub mod low_mask; pub mod not_assign; pub mod significant_bits; } pub mod random { pub mod geometric { pub mod geometric_random_natural_signeds; pub mod geometric_random_negative_signeds; pub mod geometric_random_nonzero_signeds; pub mod geometric_random_positive_signeds; pub mod geometric_random_positive_unsigneds; pub mod geometric_random_signed_inclusive_range; pub mod geometric_random_signed_range; pub mod geometric_random_signeds; pub mod geometric_random_unsigned_inclusive_range; pub mod geometric_random_unsigned_range; pub mod geometric_random_unsigneds; pub mod get_geometric_random_signed_from_inclusive_range; pub mod mean; } pub mod random_finite_primitive_floats; pub mod random_highest_bit_set_unsigneds; pub mod random_natural_signeds; pub mod random_negative_finite_primitive_floats; pub mod random_negative_primitive_floats; pub mod random_negative_signeds; pub mod random_nonzero_finite_primitive_floats; pub mod random_nonzero_primitive_floats; pub mod random_nonzero_signeds; pub mod random_positive_finite_primitive_floats; pub mod random_positive_primitive_floats; pub mod random_positive_signeds; pub mod random_positive_unsigneds; pub mod random_primitive_float_inclusive_range; pub mod random_primitive_float_range; pub mod random_primitive_floats; pub mod random_primitive_ints; pub mod random_signed_bit_chunks; pub mod random_signed_inclusive_range; pub mod random_signed_range; pub mod random_unsigned_bit_chunks; pub mod random_unsigned_inclusive_range; pub mod random_unsigned_range; pub mod random_unsigneds_less_than; pub mod special_random_finite_primitive_floats; pub mod special_random_negative_finite_primitive_floats; pub mod special_random_negative_primitive_floats; pub mod special_random_nonzero_finite_primitive_floats; pub mod special_random_nonzero_primitive_floats; pub mod special_random_positive_finite_primitive_floats; pub mod special_random_positive_primitive_floats; pub mod special_random_primitive_float_inclusive_range; pub mod special_random_primitive_float_range; pub mod special_random_primitive_floats; pub mod striped { pub mod get_striped_bool_vec; pub mod get_striped_unsigned_vec; pub mod striped_bit_source; pub mod striped_random_bool_vecs; pub mod striped_random_bool_vecs_from_length_iterator; pub mod striped_random_bool_vecs_length_inclusive_range; pub mod striped_random_bool_vecs_length_range; pub mod striped_random_bool_vecs_min_length; pub mod striped_random_fixed_length_bool_vecs; pub mod striped_random_fixed_length_unsigned_vecs; pub mod striped_random_natural_signeds; pub mod striped_random_negative_signeds; pub mod striped_random_nonzero_signeds; pub mod striped_random_positive_signeds; pub mod striped_random_positive_unsigneds; pub mod striped_random_signed_inclusive_range; pub mod striped_random_signed_range; pub mod striped_random_signeds; pub mod striped_random_unsigned_bit_chunks; pub mod striped_random_unsigned_inclusive_range; pub mod striped_random_unsigned_range; pub mod striped_random_unsigned_vecs; pub mod striped_random_unsigned_vecs_from_length_iterator; pub mod striped_random_unsigned_vecs_length_inclusive_range; pub mod striped_random_unsigned_vecs_length_range; pub mod striped_random_unsigned_vecs_min_length; pub mod striped_random_unsigneds; } pub mod variable_range_generator { pub mod next_bit_chunk; pub mod next_bool; pub mod next_in_inclusive_range; pub mod next_in_range; pub mod next_less_than; } } } pub mod options { pub mod exhaustive { pub mod exhaustive_options; pub mod exhaustive_somes; } pub mod option_from_str; pub mod random { pub mod random_options; pub mod random_somes; } } pub mod orderings { pub mod exhaustive; pub mod ordering_from_str; pub mod random; } pub mod random { pub mod fork; pub mod from_bytes; pub mod get_rng; pub mod next; } pub mod rational_sequences { pub mod access { pub mod get; pub mod mutate; } pub mod basic { pub mod component_len; pub mod is_empty; pub mod is_finite; pub mod iter; pub mod len; } pub mod comparison { pub mod cmp; pub mod eq; pub mod hash; } pub mod conversion { pub mod clone; pub mod from_vec; pub mod from_vecs; pub mod to_vecs; } pub mod exhaustive; pub mod random; pub mod to_string; } pub mod rounding_modes { pub mod clone; pub mod cmp; pub mod eq; pub mod exhaustive; pub mod from_str; pub mod hash; pub mod neg; pub mod random; pub mod size; pub mod to_string; } pub mod sets { pub mod exhaustive { pub mod exhaustive_b_tree_sets; pub mod exhaustive_b_tree_sets_fixed_length; pub mod exhaustive_b_tree_sets_length_inclusive_range; pub mod exhaustive_b_tree_sets_length_range; pub mod exhaustive_b_tree_sets_min_length; #[cfg(feature = "std")] pub mod exhaustive_hash_sets; #[cfg(feature = "std")] pub mod exhaustive_hash_sets_fixed_length; #[cfg(feature = "std")] pub mod exhaustive_hash_sets_length_inclusive_range; #[cfg(feature = "std")] pub mod exhaustive_hash_sets_length_range; #[cfg(feature = "std")] pub mod exhaustive_hash_sets_min_length; pub mod lex_b_tree_sets; pub mod lex_b_tree_sets_fixed_length; pub mod lex_b_tree_sets_length_inclusive_range; pub mod lex_b_tree_sets_length_range; pub mod lex_b_tree_sets_min_length; #[cfg(feature = "std")] pub mod lex_hash_sets; #[cfg(feature = "std")] pub mod lex_hash_sets_fixed_length; #[cfg(feature = "std")] pub mod lex_hash_sets_length_inclusive_range; #[cfg(feature = "std")] pub mod lex_hash_sets_length_range; #[cfg(feature = "std")] pub mod lex_hash_sets_min_length; pub mod shortlex_b_tree_sets; pub mod shortlex_b_tree_sets_length_inclusive_range; pub mod shortlex_b_tree_sets_length_range; pub mod shortlex_b_tree_sets_min_length; #[cfg(feature = "std")] pub mod shortlex_hash_sets; #[cfg(feature = "std")] pub mod shortlex_hash_sets_length_inclusive_range; #[cfg(feature = "std")] pub mod shortlex_hash_sets_length_range; #[cfg(feature = "std")] pub mod shortlex_hash_sets_min_length; } pub mod random { pub mod random_b_tree_sets; pub mod random_b_tree_sets_fixed_length; pub mod random_b_tree_sets_from_length_iterator; pub mod random_b_tree_sets_length_inclusive_range; pub mod random_b_tree_sets_length_range; pub mod random_b_tree_sets_min_length; pub mod random_hash_sets; pub mod random_hash_sets_fixed_length; pub mod random_hash_sets_from_length_iterator; pub mod random_hash_sets_length_inclusive_range; pub mod random_hash_sets_length_range; pub mod random_hash_sets_min_length; } } pub mod slices { pub mod exhaustive_slice_permutations; pub mod min_repeating_len; pub mod random_slice_permutations; pub mod slice_leading_zeros; pub mod slice_move_left; pub mod slice_set_zero; pub mod slice_test_zero; pub mod slice_trailing_zeros; pub mod split_into_chunks; } pub mod strings { pub mod exhaustive { pub mod exhaustive_fixed_length_strings; pub mod exhaustive_fixed_length_strings_using_chars; pub mod exhaustive_strings; pub mod exhaustive_strings_using_chars; pub mod lex_fixed_length_strings; pub mod lex_fixed_length_strings_using_chars; pub mod shortlex_strings; pub mod shortlex_strings_using_chars; } pub mod random { pub mod random_fixed_length_strings; pub mod random_fixed_length_strings_using_chars; pub mod random_strings; pub mod random_strings_using_chars; } pub mod string_is_subset; pub mod string_sort; pub mod string_unique; pub mod strings_from_char_vecs; pub mod to_binary_string; pub mod to_debug_string; pub mod to_lower_hex_string; pub mod to_octal_string; pub mod to_upper_hex_string; } pub mod tuples { pub mod exhaustive { pub mod exhaustive_custom_tuples; pub mod exhaustive_dependent_pairs; pub mod exhaustive_ordered_unique_tuples; pub mod exhaustive_tuples_1_input; pub mod exhaustive_tuples_custom_output; pub mod exhaustive_tuples_from_single; pub mod exhaustive_unique_tuples; pub mod exhaustive_units; pub mod lex_custom_tuples; pub mod lex_dependent_pairs; pub mod lex_ordered_unique_tuples; pub mod lex_tuples; pub mod lex_tuples_from_single; pub mod lex_unique_tuples; } pub mod random { pub mod random_custom_tuples; pub mod random_ordered_unique_tuples; pub mod random_tuples; pub mod random_tuples_from_single; pub mod random_unique_tuples; pub mod random_units; } pub mod singletons; } pub mod unions { pub mod clone; pub mod debug; pub mod display; pub mod eq; pub mod exhaustive { pub mod exhaustive_unions; pub mod lex_unions; } pub mod from_str; pub mod ord; pub mod random { pub mod random_unions; } pub mod unwrap; } pub mod vecs { pub mod exhaustive { pub mod exhaustive_combined_k_compositions; pub mod exhaustive_ordered_unique_vecs; pub mod exhaustive_ordered_unique_vecs_fixed_length; pub mod exhaustive_ordered_unique_vecs_length_inclusive_range; pub mod exhaustive_ordered_unique_vecs_length_range; pub mod exhaustive_ordered_unique_vecs_min_length; pub mod exhaustive_unique_vecs; pub mod exhaustive_unique_vecs_fixed_length; pub mod exhaustive_unique_vecs_length_inclusive_range; pub mod exhaustive_unique_vecs_length_range; pub mod exhaustive_unique_vecs_min_length; pub mod exhaustive_vecs; pub mod exhaustive_vecs_fixed_length_from_single; pub mod exhaustive_vecs_fixed_length_m_inputs; pub mod exhaustive_vecs_from_length_iterator; pub mod exhaustive_vecs_length_inclusive_range; pub mod exhaustive_vecs_length_n; pub mod exhaustive_vecs_length_range; pub mod exhaustive_vecs_min_length; pub mod lex_k_compositions; pub mod lex_ordered_unique_vecs; pub mod lex_ordered_unique_vecs_fixed_length; pub mod lex_ordered_unique_vecs_length_inclusive_range; pub mod lex_ordered_unique_vecs_length_range; pub mod lex_ordered_unique_vecs_min_length; pub mod lex_unique_vecs; pub mod lex_unique_vecs_fixed_length; pub mod lex_unique_vecs_length_inclusive_range; pub mod lex_unique_vecs_length_range; pub mod lex_unique_vecs_min_length; pub mod lex_vecs_fixed_length_from_single; pub mod lex_vecs_fixed_length_m_inputs; pub mod lex_vecs_length_n; pub mod next_bit_pattern; pub mod shortlex_ordered_unique_vecs; pub mod shortlex_ordered_unique_vecs_length_inclusive_range; pub mod shortlex_ordered_unique_vecs_length_range; pub mod shortlex_ordered_unique_vecs_min_length; pub mod shortlex_unique_vecs; pub mod shortlex_unique_vecs_length_inclusive_range; pub mod shortlex_unique_vecs_length_range; pub mod shortlex_unique_vecs_min_length; pub mod shortlex_vecs; pub mod shortlex_vecs_from_length_iterator; pub mod shortlex_vecs_length_inclusive_range; pub mod shortlex_vecs_length_range; pub mod shortlex_vecs_min_length; } pub mod exhaustive_vec_permutations; pub mod random { pub mod random_ordered_unique_vecs; pub mod random_ordered_unique_vecs_fixed_length; pub mod random_ordered_unique_vecs_from_length_iterator; pub mod random_ordered_unique_vecs_length_inclusive_range; pub mod random_ordered_unique_vecs_length_range; pub mod random_ordered_unique_vecs_min_length; pub mod random_unique_vecs; pub mod random_unique_vecs_fixed_length; pub mod random_unique_vecs_from_length_iterator; pub mod random_unique_vecs_length_inclusive_range; pub mod random_unique_vecs_length_range; pub mod random_unique_vecs_min_length; pub mod random_vecs; pub mod random_vecs_fixed_length; pub mod random_vecs_fixed_length_from_single; pub mod random_vecs_fixed_length_m_inputs; pub mod random_vecs_from_length_iterator; pub mod random_vecs_length_inclusive_range; pub mod random_vecs_length_range; pub mod random_vecs_min_length; } pub mod random_values_from_vec; pub mod random_vec_permutations; pub mod vec_delete_left; pub mod vec_from_str; pub mod vec_pad_left; } ================================================ FILE: malachite-base/tests/named/mod.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::rounding_modes::RoundingMode; #[test] pub fn test_named() { fn test(out: &str) { assert_eq!(T::NAME, out); } test::("String"); test::("RoundingMode"); } ================================================ FILE: malachite-base/tests/nevers/nevers.rs ================================================ // Copyright © 2026 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::nevers::nevers; #[test] fn test_nevers() { assert_eq!(nevers().collect_vec(), &[]); } ================================================ FILE: malachite-base/tests/num/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen_var_1}; use std::cmp::Ordering::*; fn abs_signed_helper() { let test = |n: T, out| { assert_eq!(n.abs(), out); let mut n = n; n.abs_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::ONE); test(T::exact_from(100), T::exact_from(100)); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); } fn abs_primitive_float_helper() { let test = |n: T, out| { assert_eq!(NiceFloat(n.abs()), NiceFloat(out)); let mut n = n; n.abs_assign(); assert_eq!(NiceFloat(n), NiceFloat(out)); }; test(T::ZERO, T::ZERO); test(T::NEGATIVE_ZERO, T::ZERO); test(T::INFINITY, T::INFINITY); test(T::NEGATIVE_INFINITY, T::INFINITY); test(T::NAN, T::NAN); test(T::ONE, T::ONE); test(T::NEGATIVE_ONE, T::ONE); test(T::from(100.0f32), T::from(100.0f32)); test(T::from(-100.0f32), T::from(100.0f32)); } #[test] fn test_abs() { apply_fn_to_signeds!(abs_signed_helper); apply_fn_to_primitive_floats!(abs_primitive_float_helper); } fn abs_assign_properties_signed_helper< U, S: ExactFrom + PrimitiveSigned + UnsignedAbs, >() { signed_gen_var_1::().test_properties(|n| { let mut abs = n; abs.abs_assign(); assert_eq!(abs, n.abs()); assert_eq!(abs.abs(), abs); assert_eq!(abs == n, n >= S::ZERO); assert_eq!(S::exact_from(n.unsigned_abs()), abs); }); } fn abs_assign_properties_primitive_float_helper() { primitive_float_gen::().test_properties(|f| { let mut abs = f; abs.abs_assign(); assert_eq!(NiceFloat(abs), NiceFloat(f.abs())); assert_eq!(NiceFloat(abs.abs()), NiceFloat(abs)); assert_eq!(NiceFloat(abs) == NiceFloat(f), f.sign() != Less); }); } #[test] fn abs_assign_properties() { apply_fn_to_unsigned_signed_pairs!(abs_assign_properties_signed_helper); apply_fn_to_primitive_floats!(abs_assign_properties_primitive_float_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AbsDiff, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, unsigned_gen, unsigned_pair_gen_var_27, }; use std::cmp::{max, min}; #[test] fn test_abs_diff() { fn test_unsigned(x: T, y: T, out: T) { assert_eq!(x.abs_diff(y), out); let mut x = x; x.abs_diff_assign(y); assert_eq!(x, out); } test_unsigned::(1, 100, 99); test_unsigned::(100, 1, 99); test_unsigned::(10, 10, 0); test_unsigned::(0, u32::MAX, u32::MAX); test_unsigned::(u32::MAX, 0, u32::MAX); test_unsigned::(u32::MAX, u32::MAX, 0); fn test_signed, U: PrimitiveUnsigned>( x: T, y: T, out: U, ) { assert_eq!(x.abs_diff(y), out); } test_signed::(1, 100, 99); test_signed::(1, -100, 101); test_signed::(-1, 100, 101); test_signed::(-1, -100, 99); test_signed::(100, 1, 99); test_signed::(100, -1, 101); test_signed::(-100, 1, 101); test_signed::(-100, -1, 99); test_signed::(10, 10, 0); test_signed::(10, -10, 20); test_signed::(-10, 10, 20); test_signed::(-10, -10, 0); test_signed::(0, i32::MAX, u32::exact_from(i32::MAX)); test_signed::(0, -i32::MAX, u32::exact_from(i32::MAX)); test_signed::(i32::MAX, 0, u32::exact_from(i32::MAX)); test_signed::(-i32::MAX, 0, u32::exact_from(i32::MAX)); test_signed::(i32::MAX, i32::MAX, 0); test_signed::(i32::MAX, -i32::MAX, u32::MAX - 1); test_signed::(-i32::MAX, i32::MAX, u32::MAX - 1); test_signed::(-i32::MAX, -i32::MAX, 0); test_signed::(i64::MIN, i64::MAX, u64::MAX); test_signed::(i64::MIN, -i64::MAX, 1); } fn abs_diff_properties_unsigned_helper() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let diff = x.abs_diff(y); let mut mut_x = x; mut_x.abs_diff_assign(y); assert_eq!(mut_x, diff); assert_eq!(y.abs_diff(x), diff); assert_eq!(max(x, y) - min(x, y), diff); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.abs_diff(T::ZERO), x); assert_eq!(T::ZERO.abs_diff(x), x); assert_eq!(x.abs_diff(x), T::ZERO); }); } fn abs_diff_properties_signed_helper< U: PrimitiveUnsigned, T: AbsDiff + UnsignedAbs + PrimitiveSigned, >() { signed_pair_gen::().test_properties(|(x, y)| { let diff = x.abs_diff(y); assert_eq!(y.abs_diff(x), diff); }); signed_gen::().test_properties(|x| { assert_eq!(x.abs_diff(T::ZERO), x.unsigned_abs()); assert_eq!(T::ZERO.abs_diff(x), x.unsigned_abs()); assert_eq!(x.abs_diff(x), U::ZERO); }); } #[test] fn abs_diff_properties() { apply_fn_to_unsigneds!(abs_diff_properties_unsigned_helper); apply_fn_to_unsigned_signed_pairs!(abs_diff_properties_signed_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_triple_gen, signed_pair_gen, signed_triple_gen_var_1, unsigned_pair_gen_var_27, unsigned_triple_gen_var_1, }; #[test] fn test_add_mul() { fn test_i(x: T, y: T, z: T, out: T) { assert_eq!(x.add_mul(y, z), out); let mut x = x; x.add_mul_assign(y, z); assert_eq!(x, out); } test_i::(2, 3, 7, 23); test_i::(7, 5, 10, 57); test_i::(123, 456, 789, 359907); test_i::(123, -456, 789, -359661); test_i::(-123, 456, 789, 359661); test_i::(127, -2, 100, -73); test_i::(-127, 2, 100, 73); test_i::(-128, 1, 0, -128); fn test_f(x: T, y: T, z: T, out: T) { assert_eq!(NiceFloat(x.add_mul(y, z)), NiceFloat(out)); let mut x = x; x.add_mul_assign(y, z); assert_eq!(NiceFloat(x), NiceFloat(out)); } test_f::(1.0, 2.0, 3.0, 7.0); test_f::(1.0, f32::INFINITY, 2.0, f32::INFINITY); test_f::(f32::NAN, 1.0, 2.0, f32::NAN); } fn add_mul_properties_helper_unsigned() { unsigned_triple_gen_var_1::().test_properties(|(x, y, z)| { let result = x.add_mul(y, z); let mut x_alt = x; x_alt.add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.add_mul(z, y), result); assert_eq!(result.sub_mul(y, z), x); assert_eq!(x.checked_add_mul(y, z), Some(result)); assert_eq!(x.saturating_add_mul(y, z), result); assert_eq!(x.wrapping_add_mul(y, z), result); assert_eq!(x.overflowing_add_mul(y, z), (result, false)); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.add_mul(T::ZERO, b), a); assert_eq!(a.add_mul(b, T::ZERO), a); }); } fn add_mul_properties_helper_signed() { signed_triple_gen_var_1::().test_properties(|(x, y, z)| { let result = x.add_mul(y, z); let mut x_alt = x; x_alt.add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.add_mul(z, y), result); assert_eq!(result.sub_mul(y, z), x); assert_eq!(x.checked_add_mul(y, z), Some(result)); assert_eq!(x.saturating_add_mul(y, z), result); assert_eq!(x.wrapping_add_mul(y, z), result); assert_eq!(x.overflowing_add_mul(y, z), (result, false)); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.add_mul(T::ZERO, b), a); assert_eq!(a.add_mul(b, T::ZERO), a); }); } fn add_mul_properties_helper_primitive_float() { primitive_float_triple_gen::().test_properties(|(x, y, z)| { let result = x.add_mul(y, z); let mut x_alt = x; x_alt.add_mul_assign(y, z); assert_eq!(NiceFloat(x_alt), NiceFloat(result)); assert_eq!(NiceFloat(x.add_mul(z, y)), NiceFloat(result)); }); } #[test] fn add_mul_properties() { apply_fn_to_unsigneds!(add_mul_properties_helper_unsigned); apply_fn_to_signeds!(add_mul_properties_helper_signed); apply_fn_to_primitive_floats!(add_mul_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/arithmetic_checked_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, ArithmeticCheckedShr}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, signed_pair_gen_var_2, signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_gen_var_5, unsigned_pair_gen_var_2, unsigned_signed_pair_gen_var_1, }; use std::ops::Shr; #[test] fn test_arithmetic_checked_shl() { fn test + PrimitiveInt, U: PrimitiveInt>( t: T, u: U, out: Option, ) { assert_eq!(t.arithmetic_checked_shl(u), out); } test::(0, 0, Some(0)); test::(3, 6, Some(192)); test::(3, 7, None); test::(3, 100, None); test::(0, 100, Some(0)); test::(100, -3, Some(12)); test::(100, -100, Some(0)); test::(3, 5, Some(96)); test::(3, 6, None); test::(-3, 5, Some(-96)); test::(-3, 6, None); test::(3, 100, None); test::(-3, 100, None); test::(0, 100, Some(0)); test::(3, 5, Some(96)); test::(3, 6, None); test::(-3, 5, Some(-96)); test::(-3, 6, None); test::(3, 100, None); test::(-3, 100, None); test::(0, 100, Some(0)); test::(100, -3, Some(12)); test::(-100, -3, Some(-13)); test::(100, -100, Some(0)); test::(-100, -100, Some(-1)); } fn arithmetic_checked_shl_properties_helper_unsigned_unsigned< T: ArithmeticCheckedShl + PrimitiveUnsigned + Shr, U: PrimitiveUnsigned, >() where u64: ExactFrom, { unsigned_pair_gen_var_2::().test_properties(|(n, u)| { if let Some(shifted) = n.arithmetic_checked_shl(u) { assert!(shifted >= n); if n != T::ZERO { assert_eq!(shifted >> u, n); } } else { assert_ne!(n, T::ZERO); assert!(LeadingZeros::leading_zeros(n) < u64::exact_from(u)); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shl(U::ZERO), Some(n)); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(T::ZERO.arithmetic_checked_shl(u), Some(T::ZERO)); }); } // Type repetition to avoid long line #[allow( clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds, clippy::multiple_bound_locations )] fn arithmetic_checked_shl_properties_helper_unsigned_signed< T: ArithmeticCheckedShl + ArithmeticCheckedShr, U: PrimitiveSigned, >() where u64: ExactFrom, T: PrimitiveUnsigned, { unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = n.arithmetic_checked_shl(i); if shifted.is_none() { assert_ne!(n, T::ZERO); } if i != U::MIN { assert_eq!(n.arithmetic_checked_shr(-i), shifted); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shl(U::ZERO), Some(n)); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.arithmetic_checked_shl(i), Some(T::ZERO)); }); } fn arithmetic_checked_shl_properties_helper_signed_unsigned< T: ArithmeticCheckedShl + PrimitiveSigned + Shr, U: PrimitiveUnsigned, >() where u64: ExactFrom, { signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { if let Some(shifted) = n.arithmetic_checked_shl(u) { assert!(shifted.ge_abs(&n)); if n != T::ZERO { assert_eq!(shifted >> u, n); } } else { assert_ne!(n, T::ZERO); } }); signed_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shl(U::ZERO), Some(n)); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(T::ZERO.arithmetic_checked_shl(u), Some(T::ZERO)); }); } fn arithmetic_checked_shl_properties_helper_signed_signed< T: ArithmeticCheckedShl + ArithmeticCheckedShr + PrimitiveSigned, U: PrimitiveSigned, >() where u64: ExactFrom, { signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = n.arithmetic_checked_shl(i); if shifted.is_none() { assert_ne!(n, T::ZERO); } if i != U::MIN { assert_eq!(n.arithmetic_checked_shr(-i), shifted); } }); signed_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shl(U::ZERO), Some(n)); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.arithmetic_checked_shl(i), Some(T::ZERO)); }); } #[test] fn arithmetic_checked_shl_properties() { apply_fn_to_unsigneds_and_unsigneds!( arithmetic_checked_shl_properties_helper_unsigned_unsigned ); apply_fn_to_unsigneds_and_signeds!(arithmetic_checked_shl_properties_helper_unsigned_signed); apply_fn_to_signeds_and_unsigneds!(arithmetic_checked_shl_properties_helper_signed_unsigned); apply_fn_to_signeds_and_signeds!(arithmetic_checked_shl_properties_helper_signed_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/arithmetic_checked_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, ArithmeticCheckedShr}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, signed_pair_gen_var_2, unsigned_gen, unsigned_signed_pair_gen_var_1, }; #[test] fn test_arithmetic_checked_shr() { fn test + PrimitiveInt, U: PrimitiveInt>( t: T, u: U, out: Option, ) { assert_eq!(t.arithmetic_checked_shr(u), out); } test::(100, 3, Some(12)); test::(100, 100, Some(0)); test::(3, -5, Some(96)); test::(3, -6, None); test::(-3, -5, Some(-96)); test::(-3, -6, None); test::(3, -100, None); test::(-3, -100, None); test::(0, -100, Some(0)); test::(100, 3, Some(12)); test::(-100, 3, Some(-13)); test::(100, 100, Some(0)); test::(-100, 100, Some(-1)); } // Type repetition to avoid long line #[allow( clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds, clippy::multiple_bound_locations )] fn arithmetic_checked_shr_properties_helper_unsigned_signed< T: ArithmeticCheckedShl + ArithmeticCheckedShr, U: PrimitiveSigned, >() where u64: ExactFrom, T: PrimitiveUnsigned, { unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = n.arithmetic_checked_shr(i); if shifted.is_none() { assert_ne!(n, T::ZERO); } if i != U::MIN { assert_eq!(n.arithmetic_checked_shl(-i), shifted); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shr(U::ZERO), Some(n)); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.arithmetic_checked_shr(i), Some(T::ZERO)); }); } fn arithmetic_checked_shr_properties_helper_signed_signed< T: ArithmeticCheckedShl + ArithmeticCheckedShr + PrimitiveSigned, U: PrimitiveSigned, >() where u64: ExactFrom, { signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = n.arithmetic_checked_shr(i); if shifted.is_none() { assert_ne!(n, T::ZERO); } if i != U::MIN { assert_eq!(n.arithmetic_checked_shl(-i), shifted); } }); signed_gen::().test_properties(|n| { assert_eq!(n.arithmetic_checked_shr(U::ZERO), Some(n)); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.arithmetic_checked_shr(i), Some(T::ZERO)); }); } #[test] fn arithmetic_checked_shr_properties() { apply_fn_to_unsigneds_and_signeds!(arithmetic_checked_shr_properties_helper_unsigned_signed); apply_fn_to_signeds_and_signeds!(arithmetic_checked_shr_properties_helper_signed_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::BinomialCoefficient; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_2, signed_pair_gen_var_11, signed_pair_gen_var_12, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_28, unsigned_pair_gen_var_44, }; use std::panic::catch_unwind; #[test] fn test_binomial_coefficient() { fn test_u(n: T, k: T, out: T) { assert_eq!(T::binomial_coefficient(n, k), out); } test_u::(0, 0, 1); test_u::(1, 0, 1); test_u::(1, 1, 1); test_u::(2, 0, 1); test_u::(2, 1, 2); test_u::(2, 2, 1); test_u::(3, 0, 1); test_u::(3, 1, 3); test_u::(3, 2, 3); test_u::(3, 3, 1); test_u::(4, 0, 1); test_u::(4, 1, 4); test_u::(4, 2, 6); test_u::(4, 3, 4); test_u::(4, 4, 1); test_u::(1, 2, 0); test_u::(10, 5, 252); test_u::(100, 50, 100891344545564193334812497256); fn test_i(n: T, k: T, out: T) { assert_eq!(T::binomial_coefficient(n, k), out); } test_i::(0, 0, 1); test_i::(1, 0, 1); test_i::(1, 1, 1); test_i::(2, 0, 1); test_i::(2, 1, 2); test_i::(2, 2, 1); test_i::(3, 0, 1); test_i::(3, 1, 3); test_i::(3, 2, 3); test_i::(3, 3, 1); test_i::(4, 0, 1); test_i::(4, 1, 4); test_i::(4, 2, 6); test_i::(4, 3, 4); test_i::(4, 4, 1); test_i::(1, 2, 0); test_i::(10, 5, 252); test_i::(100, 50, 100891344545564193334812497256); test_i::(-1, 0, 1); test_i::(-1, 1, -1); test_i::(-2, 0, 1); test_i::(-2, 1, -2); test_i::(-2, 2, 3); test_i::(-3, 0, 1); test_i::(-3, 1, -3); test_i::(-3, 2, 6); test_i::(-3, 3, -10); test_i::(-1, 2, 1); test_i::(-10, 5, -2002); test_i::(-80, 50, 1828256793482238093393785743858493760); test_i::(-128, 1, -128); test_i::(-2, 127, -128); } #[test] pub fn binomial_coefficient_fail() { assert_panic!(u8::binomial_coefficient(11, 5)); assert_panic!(u128::binomial_coefficient(1000000, 1000)); assert_panic!(i8::binomial_coefficient(11, 5)); assert_panic!(i128::binomial_coefficient(1000000, 1000)); assert_panic!(i8::binomial_coefficient(1, -1)); } #[test] fn test_checked_binomial_coefficient() { fn test_u(n: T, k: T, out: Option) { assert_eq!(T::checked_binomial_coefficient(n, k), out); } test_u::(0, 0, Some(1)); test_u::(1, 0, Some(1)); test_u::(1, 1, Some(1)); test_u::(2, 0, Some(1)); test_u::(2, 1, Some(2)); test_u::(2, 2, Some(1)); test_u::(3, 0, Some(1)); test_u::(3, 1, Some(3)); test_u::(3, 2, Some(3)); test_u::(3, 3, Some(1)); test_u::(4, 0, Some(1)); test_u::(4, 1, Some(4)); test_u::(4, 2, Some(6)); test_u::(4, 3, Some(4)); test_u::(4, 4, Some(1)); test_u::(1, 2, Some(0)); test_u::(10, 5, Some(252)); test_u::(100, 50, Some(100891344545564193334812497256)); test_u::(11, 5, None); test_u::(1000000, 1000, None); fn test_i(n: T, k: T, out: Option) { assert_eq!(T::checked_binomial_coefficient(n, k), out); } test_i::(0, 0, Some(1)); test_i::(1, 0, Some(1)); test_i::(1, 1, Some(1)); test_i::(2, 0, Some(1)); test_i::(2, 1, Some(2)); test_i::(2, 2, Some(1)); test_i::(3, 0, Some(1)); test_i::(3, 1, Some(3)); test_i::(3, 2, Some(3)); test_i::(3, 3, Some(1)); test_i::(4, 0, Some(1)); test_i::(4, 1, Some(4)); test_i::(4, 2, Some(6)); test_i::(4, 3, Some(4)); test_i::(4, 4, Some(1)); test_i::(1, 2, Some(0)); test_i::(10, 5, Some(252)); test_i::(100, 50, Some(100891344545564193334812497256)); test_i::(-1, 0, Some(1)); test_i::(-1, 1, Some(-1)); test_i::(-2, 0, Some(1)); test_i::(-2, 1, Some(-2)); test_i::(-2, 2, Some(3)); test_i::(-3, 0, Some(1)); test_i::(-3, 1, Some(-3)); test_i::(-3, 2, Some(6)); test_i::(-3, 3, Some(-10)); test_i::(-1, 2, Some(1)); test_i::(-10, 5, Some(-2002)); test_i::(-80, 50, Some(1828256793482238093393785743858493760)); test_i::(-128, 1, Some(-128)); test_i::(-2, 127, Some(-128)); test_i::(11, 5, None); test_i::(1000000, 1000, None); test_i::(1, -1, None); } fn binomial_coefficient_helper_unsigned() { unsigned_pair_gen_var_44::().test_properties(|(n, k)| { let b = T::binomial_coefficient(n, k); assert_eq!(b == T::ZERO, n < k); if n >= k { assert_eq!(T::binomial_coefficient(n, n - k), b); } if n != T::ZERO && k != T::ZERO { let c = T::binomial_coefficient(n - T::ONE, k - T::ONE); assert_eq!(T::binomial_coefficient(n - T::ONE, k) + c, b); let gcd = n.gcd(k); assert_eq!(c / (k / gcd) * (n / gcd), b); } }); unsigned_gen::().test_properties(|n| { assert_eq!(T::binomial_coefficient(n, T::ZERO), T::ONE); assert_eq!(T::binomial_coefficient(n, T::ONE), n); }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(T::binomial_coefficient(n, n), T::ONE); assert_eq!(T::binomial_coefficient(n, n - T::ONE), n); assert_eq!(T::binomial_coefficient(T::ZERO, n), T::ZERO); }); } fn binomial_coefficient_helper_signed() { signed_pair_gen_var_12::().test_properties(|(n, k)| { let b = T::binomial_coefficient(n, k); assert_eq!(b == T::ZERO, n >= T::ZERO && n < k); if n >= k { assert_eq!(T::binomial_coefficient(n, n - k), b); } if n != T::MIN && k != T::ZERO && let Some(c) = T::checked_binomial_coefficient(n - T::ONE, k) { assert_eq!(c + T::binomial_coefficient(n - T::ONE, k - T::ONE), b); } if n != T::MIN && let Some(s) = (n - T::ONE).checked_add(k) && let Some(mut b_alt) = T::checked_binomial_coefficient(s, k) { if k.odd() { b_alt.neg_assign(); } assert_eq!(T::binomial_coefficient(-n, k), b_alt); } }); signed_gen::().test_properties(|n| { assert_eq!(T::binomial_coefficient(n, T::ONE), n); assert_eq!(T::binomial_coefficient(n, T::ZERO), T::ONE); }); signed_gen_var_2::().test_properties(|n| { assert_eq!(T::binomial_coefficient(n, n), T::ONE); if n != T::ZERO { assert_eq!(T::binomial_coefficient(n, n - T::ONE), n); assert_eq!(T::binomial_coefficient(T::ZERO, n), T::ZERO); } }); } #[test] fn binomial_coefficient_properties() { apply_fn_to_unsigneds!(binomial_coefficient_helper_unsigned); apply_fn_to_signeds!(binomial_coefficient_helper_signed); } fn checked_binomial_coefficient_helper_unsigned() { unsigned_pair_gen_var_28::().test_properties(|(n, k)| { if let Some(b) = T::checked_binomial_coefficient(n, k) { assert_eq!(T::binomial_coefficient(n, k), b); } }); } fn checked_binomial_coefficient_helper_signed() { signed_pair_gen_var_11::().test_properties(|(n, k)| { if let Some(b) = T::checked_binomial_coefficient(n, k) { assert_eq!(T::binomial_coefficient(n, k), b); } }); } #[test] fn checked_binomial_coefficient_properties() { apply_fn_to_unsigneds!(checked_binomial_coefficient_helper_unsigned); apply_fn_to_signeds!(checked_binomial_coefficient_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; fn ceiling_assign_primitive_float_helper() { let test = |n: T, out| { assert_eq!(NiceFloat(n.ceiling()), NiceFloat(out)); let mut n = n; n.ceiling_assign(); assert_eq!(NiceFloat(n), NiceFloat(out)); }; test(T::ZERO, T::ZERO); test(T::NEGATIVE_ZERO, T::NEGATIVE_ZERO); test(T::INFINITY, T::INFINITY); test(T::NEGATIVE_INFINITY, T::NEGATIVE_INFINITY); test(T::NAN, T::NAN); test(T::ONE, T::ONE); test(T::NEGATIVE_ONE, T::NEGATIVE_ONE); test(T::from(1.5f32), T::from(2.0f32)); test(T::from(-1.5f32), T::from(-1.0f32)); } #[test] fn test_ceiling() { apply_fn_to_primitive_floats!(ceiling_assign_primitive_float_helper); } fn ceiling_assign_properties_helper() { primitive_float_gen::().test_properties(|f| { let mut ceiling = f; ceiling.ceiling_assign(); assert_eq!(NiceFloat(ceiling), NiceFloat(f.ceiling())); assert_eq!(NiceFloat(ceiling.ceiling()), NiceFloat(ceiling)); assert_eq!(NiceFloat(-ceiling), NiceFloat((-f).floor())); assert_eq!(f.sign(), ceiling.sign()); }); } #[test] fn ceiling_assign_properties() { apply_fn_to_primitive_floats!(ceiling_assign_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; fn checked_abs_helper() { let test = |n: T, out| { assert_eq!(n.checked_abs(), out); }; test(T::ZERO, Some(T::ZERO)); test(T::ONE, Some(T::ONE)); test(T::exact_from(100), Some(T::exact_from(100))); test(T::NEGATIVE_ONE, Some(T::ONE)); test(T::exact_from(-100), Some(T::exact_from(100))); test(T::MIN, None); } #[test] fn test_checked_abs() { apply_fn_to_signeds!(checked_abs_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_checked_add_mul() { fn test(x: T, y: T, z: T, out: Option) { assert_eq!(x.checked_add_mul(y, z), out); } test::(2, 3, 7, Some(23)); test::(7, 5, 10, Some(57)); test::(123, 456, 789, Some(359907)); test::(123, -456, 789, Some(-359661)); test::(-123, 456, 789, Some(359661)); test::(127, -2, 100, Some(-73)); test::(-127, 2, 100, Some(73)); test::(-128, 1, 0, Some(-128)); test::(2, 20, 20, None); test::(-127, -2, 100, None); test::(127, 1, 100, None); test::(-127, -1, 100, None); test::(-127, -10, 100, None); } fn checked_add_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.checked_add_mul(y, z); assert_eq!(x.checked_add_mul(z, y), result); assert_eq!(result.is_none(), x.overflowing_add_mul(y, z).1); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.checked_add_mul(T::ZERO, b), Some(a)); assert_eq!(a.checked_add_mul(T::ONE, b), a.checked_add(b)); assert_eq!(T::ZERO.checked_add_mul(a, b), a.checked_mul(b)); assert_eq!(a.checked_add_mul(b, T::ZERO), Some(a)); assert_eq!(a.checked_add_mul(b, T::ONE), a.checked_add(b)); }); } fn checked_add_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.checked_add_mul(y, z); assert_eq!(x.checked_add_mul(z, y), result); assert_eq!(result.is_none(), x.overflowing_add_mul(y, z).1); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.checked_add_mul(T::ZERO, b), Some(a)); assert_eq!(a.checked_add_mul(T::ONE, b), a.checked_add(b)); assert_eq!(T::ZERO.checked_add_mul(a, b), a.checked_mul(b)); assert_eq!(a.checked_add_mul(b, T::ZERO), Some(a)); assert_eq!(a.checked_add_mul(b, T::ONE), a.checked_add(b)); }); } #[test] fn checked_add_mul_properties() { apply_fn_to_unsigneds!(checked_add_mul_properties_helper_unsigned); apply_fn_to_signeds!(checked_add_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; fn checked_neg_helper() { let test = |n: T, out| { assert_eq!(n.checked_neg(), out); }; test(T::ZERO, Some(T::ZERO)); test(T::ONE, Some(T::NEGATIVE_ONE)); test(T::exact_from(100), Some(T::exact_from(-100))); test(T::NEGATIVE_ONE, Some(T::ONE)); test(T::exact_from(-100), Some(T::exact_from(100))); test(T::MIN, None); } #[test] fn test_checked_neg() { apply_fn_to_signeds!(checked_neg_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; #[test] fn test_checked_pow() { fn test(x: T, y: u64, out: Option) { assert_eq!(x.checked_pow(y), out); } test::(0, 0, Some(1)); test::(123, 0, Some(1)); test::(123, 1, Some(123)); test::(0, 123, Some(0)); test::(1, 123, Some(1)); test::(-1, 123, Some(-1)); test::(-1, 124, Some(1)); test::(3, 3, Some(27)); test::(-10, 9, Some(-1000000000)); test::(-10, 10, None); test::(-10, 9, None); test::(10, 9, None); test::(123, 456, None); test::(0, u64::MAX, Some(0)); test::(1, u64::MAX, Some(1)); test::(123, u64::MAX, None); test::(0, u64::MAX, Some(0)); test::(1, u64::MAX, Some(1)); test::(-1, u64::MAX, Some(-1)); test::(-1, u64::MAX - 1, Some(1)); test::(123, u64::MAX, None); test::(-123, u64::MAX, None); test::(-123, u64::MAX - 1, None); } fn checked_pow_properties_helper_unsigned() { unsigned_pair_gen::().test_properties(|(x, y)| { let power = x.checked_pow(y); if let Some(power) = power { if y != 0 { assert!(power >= x); } assert_eq!(power, x.pow(y)); } }); } fn checked_pow_properties_helper_signed() { signed_unsigned_pair_gen::().test_properties(|(x, y)| { let power = x.checked_pow(y); if let Some(power) = power { assert_eq!(power, x.pow(y)); } }); } #[test] fn checked_pow_properties() { apply_fn_to_unsigneds!(checked_pow_properties_helper_unsigned); apply_fn_to_signeds!(checked_pow_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; #[test] fn test_checked_square() { fn test(x: T, out: Option) { assert_eq!(x.checked_square(), out); } test::(0, Some(0)); test::(1, Some(1)); test::(2, Some(4)); test::(3, Some(9)); test::(10, Some(100)); test::(123, Some(15129)); test::(1000, Some(1000000)); test::(-1, Some(1)); test::(-2, Some(4)); test::(-3, Some(9)); test::(-10, Some(100)); test::(-123, Some(15129)); test::(-1000, Some(1000000)); test::(1000, None); test::(-1000, None); } fn unsigned_checked_square_properties_helper() { unsigned_gen::().test_properties(|x| { let square = x.checked_square(); assert_eq!(square, x.checked_pow(2)); if let Some(square) = square { assert_eq!(x.square(), square); } }); } fn signed_checked_square_properties_helper() { signed_gen::().test_properties(|x| { let square = x.checked_square(); assert_eq!(square, x.checked_pow(2)); if let Some(square) = square { assert_eq!(x.square(), square); } }); } #[test] fn checked_square_properties() { apply_fn_to_unsigneds!(unsigned_checked_square_properties_helper); apply_fn_to_signeds!(signed_checked_square_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_checked_sub_mul() { fn test(x: T, y: T, z: T, out: Option) { assert_eq!(x.checked_sub_mul(y, z), out); } test::(100, 3, 7, Some(79)); test::(60, 5, 10, Some(10)); test::(1000000, 456, 789, Some(640216)); test::(123, -456, 789, Some(359907)); test::(-123, 456, 789, Some(-359907)); test::(127, 2, 100, Some(-73)); test::(-127, -2, 100, Some(73)); test::(-128, 1, 0, Some(-128)); test::(2, 10, 5, None); test::(-127, 2, 100, None); test::(-127, 1, 100, None); test::(127, -1, 100, None); test::(127, -10, 100, None); } fn checked_sub_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.checked_sub_mul(y, z); assert_eq!(x.checked_sub_mul(z, y), result); assert_eq!(result.is_none(), x.overflowing_sub_mul(y, z).1); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.checked_sub_mul(T::ZERO, b), Some(a)); assert_eq!(a.checked_sub_mul(T::ONE, b), a.checked_sub(b)); assert_eq!(a.checked_sub_mul(b, T::ZERO), Some(a)); assert_eq!(a.checked_sub_mul(b, T::ONE), a.checked_sub(b)); }); } fn checked_sub_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.checked_sub_mul(y, z); assert_eq!(x.checked_sub_mul(z, y), result); assert_eq!(result.is_none(), x.overflowing_sub_mul(y, z).1); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.checked_sub_mul(T::ZERO, b), Some(a)); assert_eq!(a.checked_sub_mul(T::ONE, b), a.checked_sub(b)); assert_eq!(a.checked_sub_mul(b, T::ZERO), Some(a)); assert_eq!(a.checked_sub_mul(b, T::ONE), a.checked_sub(b)); }); } #[test] fn checked_sub_mul_properties() { apply_fn_to_unsigneds!(checked_sub_mul_properties_helper_unsigned); apply_fn_to_signeds!(checked_sub_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::coprime_with::{ coprime_with_check_2, coprime_with_check_2_3, coprime_with_check_2_3_5, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{unsigned_gen, unsigned_pair_gen_var_27}; #[test] fn test_coprime_with() { fn test(x: T, y: T, out: bool) { assert_eq!(x.coprime_with(y), out); } test::(0, 0, false); test::(0, 1, true); test::(0, 6, false); test::(6, 0, false); test::(1, 6, true); test::(6, 1, true); test::(8, 12, false); test::(54, 24, false); test::(42, 56, false); test::(48, 18, false); test::(3, 5, true); test::(12, 60, false); test::(12, 90, false); test::(25, 14, true); } fn coprime_with_properties_helper() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let c = x.coprime_with(y); assert_eq!(x.gcd(y) == T::ONE, c); assert_eq!(coprime_with_check_2(x, y), c); assert_eq!(coprime_with_check_2_3(x, y), c); assert_eq!(coprime_with_check_2_3_5(x, y), c); assert_eq!(y.coprime_with(x), c); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.coprime_with(x), x == T::ONE); assert!(x.coprime_with(T::ONE)); assert_eq!(x.coprime_with(T::ZERO), x == T::ONE); if x != T::MAX { assert!(x.coprime_with(x + T::ONE)); } }); } #[test] fn coprime_with_properties() { apply_fn_to_unsigneds!(coprime_with_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_6, signed_pair_gen_var_3, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_11, }; use std::panic::catch_unwind; #[test] fn test_div_exact() { fn test(x: T, y: T, out: T) { assert_eq!(x.div_exact(y), out); let mut x = x; x.div_exact_assign(y); assert_eq!(x, out); } test::(0, 123, 0); test::(123, 1, 123); test::(123, 123, 1); test::(56088, 123, 456); test::(0, 1000000000000, 0); test::(1000000000000, 1, 1000000000000); test::(1000000000000, 1000000000000, 1); test::(123000000000000, 1000000000000, 123); test::(123000000000000, 123, 1000000000000); test::(121932631112635269000000, 123456789000, 987654321000); test::(0x1fffffffe, 0xffffffff, 2); test::(18446744065119617025, 0xffffffff, 0xffffffff); test::(0, -123, 0); test::(123, -1, -123); test::(123, -123, -1); test::(56088, -123, -456); test::(0, -1000000000000, 0); test::(1000000000000, -1, -1000000000000); test::(1000000000000, -1000000000000, -1); test::(123000000000000, -1000000000000, -123); test::(123000000000000, -123, -1000000000000); test::(121932631112635269000000, -123456789000, -987654321000); test::(0x1fffffffe, -0xffffffff, -2); test::(18446744065119617025, -0xffffffff, -0xffffffff); test::(-123, 1, -123); test::(-123, 123, -1); test::(-56088, 123, -456); test::(-1000000000000, 1, -1000000000000); test::(-1000000000000, 1000000000000, -1); test::(-123000000000000, 1000000000000, -123); test::(-123000000000000, 123, -1000000000000); test::(-121932631112635269000000, 123456789000, -987654321000); test::(-0x1fffffffe, 0xffffffff, -2); test::(-18446744065119617025, 0xffffffff, -0xffffffff); test::(-123, -1, 123); test::(-123, -123, 1); test::(-56088, -123, 456); test::(-1000000000000, -1, 1000000000000); test::(-1000000000000, -1000000000000, 1); test::(-123000000000000, -1000000000000, 123); test::(-123000000000000, -123, 1000000000000); test::(-121932631112635269000000, -123456789000, 987654321000); test::(-0x1fffffffe, -0xffffffff, 2); test::(-18446744065119617025, -0xffffffff, 0xffffffff); } fn div_exact_fail_helper() { assert_panic!(T::ONE.div_exact(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.div_exact_assign(T::ZERO); }); } #[test] pub fn div_exact_fail() { apply_fn_to_primitive_ints!(div_exact_fail_helper); } fn div_exact_properties_helper_unsigned() { unsigned_pair_gen_var_11::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.div_exact_assign(y); let q = mut_x; assert_eq!(x.div_exact(y), q); assert_eq!(x.div_round(y, Exact).0, q); assert_eq!(q * y, x); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.div_exact(T::ONE), x); assert_panic!(x.div_exact(T::ZERO)); assert_panic!({ let mut y = x; y.div_exact_assign(T::ZERO); }); }); unsigned_gen_var_1::().test_properties(|x| { assert_eq!(T::ZERO.div_exact(x), T::ZERO); assert_eq!(x.div_exact(x), T::ONE); }); } fn div_exact_properties_helper_signed() { signed_pair_gen_var_3::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.div_exact_assign(y); let q = mut_x; assert_eq!(x.div_exact(y), q); assert_eq!(x.div_round(y, Exact).0, q); assert_eq!(q * y, x); if x != T::MIN { assert_eq!((-x).div_exact(y), -q); } if y != T::MIN && q != T::MIN { assert_eq!(x.div_exact(-y), -q); } }); signed_gen::().test_properties(|x| { assert_eq!(x.div_exact(T::ONE), x); assert_panic!(x.div_exact(T::ZERO)); assert_panic!({ let mut y = x; y.div_exact_assign(T::ZERO); }); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(T::ZERO.div_exact(x), T::ZERO); assert_eq!(x.div_exact(x), T::ONE); }); } #[test] fn div_exact_properties() { apply_fn_to_unsigneds!(div_exact_properties_helper_unsigned); apply_fn_to_signeds!(div_exact_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_6, signed_pair_gen_var_4, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_12, }; use std::panic::catch_unwind; #[test] fn test_div_mod_and_div_rem_unsigned() { fn test(n: T, d: T, q: T, r: T) { assert_eq!(n.div_mod(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.div_assign_mod(d), r); assert_eq!(mut_n, q); assert_eq!(n.div_rem(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.div_assign_rem(d), r); assert_eq!(mut_n, q); } test::(0, 1, 0, 0); test::(0, 123, 0, 0); test::(1, 1, 1, 0); test::(123, 1, 123, 0); test::(123, 123, 1, 0); test::(123, 456, 0, 123); test::(456, 123, 3, 87); test::(u32::MAX, 1, u32::MAX, 0); test::(0xffffffff, 0xffffffff, 1, 0); test::(1000000000000, 1, 1000000000000, 0); test::(1000000000000, 3, 333333333333, 1); test::(1000000000000, 123, 8130081300, 100); test::(1000000000000, 0xffffffff, 232, 3567587560); test::(1000000000000000000000000, 1, 1000000000000000000000000, 0); test::(1000000000000000000000000, 3, 333333333333333333333333, 1); test::(1000000000000000000000000, 123, 8130081300813008130081, 37); test::( 1000000000000000000000000, 0xffffffff, 232830643708079, 3167723695, ); test::( 1000000000000000000000000, 1234567890987, 810000006723, 530068894399, ); test::( 253640751230376270397812803167, 2669936877441, 94998781946290113, 1520301762334, ); test::(3768477692975601, 11447376614057827956, 0, 3768477692975601); test::(3356605361737854, 3081095617839357, 1, 275509743898497); test::( 1098730198198174614195, 953382298040157850476, 1, 145347900158016763719, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 1, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(123, 1000000000000000000000000, 0, 123); } fn div_mod_and_div_rem_properties_helper_unsigned() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut mut_x = x; let r = mut_x.div_assign_mod(y); let q = mut_x; assert_eq!(x.div_mod(y), (q, r)); let mut mut_x = x; let r_alt = mut_x.div_assign_rem(y); let q_alt = mut_x; assert_eq!((q_alt, r_alt), (q, r)); assert_eq!(x.div_rem(y), (q, r)); assert_eq!((x / y, x % y), (q, r)); assert!(r < y); assert_eq!(q * y + r, x); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.div_mod(T::ONE), (x, T::ZERO)); assert_panic!(x.div_mod(T::ZERO)); assert_panic!({ let mut y = x; y.div_assign_mod(T::ZERO) }); }); unsigned_gen_var_1::().test_properties(|x| { assert_eq!(x.div_mod(x), (T::ONE, T::ZERO)); assert_eq!(T::ZERO.div_mod(x), (T::ZERO, T::ZERO)); if x > T::ONE { assert_eq!(T::ONE.div_mod(x), (T::ZERO, T::ONE)); } }); } #[test] fn test_div_mod_signed() { fn test(n: T, d: T, q: T, r: T) { assert_eq!(n.div_mod(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.div_assign_mod(d), r); assert_eq!(mut_n, q); } test::(0, 1, 0, 0); test::(0, 123, 0, 0); test::(1, 1, 1, 0); test::(123, 1, 123, 0); test::(123, 123, 1, 0); test::(123, 456, 0, 123); test::(456, 123, 3, 87); test::(0xffffffff, 1, 0xffffffff, 0); test::(0xffffffff, 0xffffffff, 1, 0); test::(1000000000000, 1, 1000000000000, 0); test::(1000000000000, 3, 333333333333, 1); test::(1000000000000, 123, 8130081300, 100); test::(1000000000000, 0xffffffff, 232, 3567587560); test::(1000000000000000000000000, 1, 1000000000000000000000000, 0); test::(1000000000000000000000000, 3, 333333333333333333333333, 1); test::(1000000000000000000000000, 123, 8130081300813008130081, 37); test::( 1000000000000000000000000, 0xffffffff, 232830643708079, 3167723695, ); test::( 1000000000000000000000000, 1234567890987, 810000006723, 530068894399, ); test::( 253640751230376270397812803167, 2669936877441, 94998781946290113, 1520301762334, ); test::(3768477692975601, 11447376614057827956, 0, 3768477692975601); test::(3356605361737854, 3081095617839357, 1, 275509743898497); test::( 1098730198198174614195, 953382298040157850476, 1, 145347900158016763719, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 1, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(123, 1000000000000000000000000, 0, 123); test::(0, -1, 0, 0); test::(0, -123, 0, 0); test::(1, -1, -1, 0); test::(123, -1, -123, 0); test::(123, -123, -1, 0); test::(123, -456, -1, -333); test::(456, -123, -4, -36); test::(0xffffffff, -1, -0xffffffff, 0); test::(0xffffffff, -0xffffffff, -1, 0); test::(1000000000000, -1, -1000000000000, 0); test::(1000000000000, -3, -333333333334, -2); test::(1000000000000, -123, -8130081301, -23); test::(1000000000000, -0xffffffff, -233, -727379735); test::(1000000000000000000000000, -1, -1000000000000000000000000, 0); test::(1000000000000000000000000, -3, -333333333333333333333334, -2); test::( 1000000000000000000000000, -123, -8130081300813008130082, -86, ); test::( 1000000000000000000000000, -0xffffffff, -232830643708080, -1127243600, ); test::( 1000000000000000000000000, -1234567890987, -810000006724, -704498996588, ); test::( 253640751230376270397812803167, -2669936877441, -94998781946290114, -1149635115107, ); test::( 3768477692975601, -11447376614057827956, -1, -11443608136364852355, ); test::(3356605361737854, -3081095617839357, -2, -2805585873940860); test::( 1098730198198174614195, -953382298040157850476, -2, -808034397882141086757, ); test::( 69738658860594537152875081748, -69738658860594537152875081748, -1, 0, ); test::(1000000000000000000000000, -1000000000000000000000000, -1, 0); test::(0, -1000000000000000000000000, 0, 0); test::( 123, -1000000000000000000000000, -1, -999999999999999999999877, ); test::(-1, 1, -1, 0); test::(-123, 1, -123, 0); test::(-123, 123, -1, 0); test::(-123, 456, -1, 333); test::(-456, 123, -4, 36); test::(-0xffffffff, -1, 0xffffffff, 0); test::(-0xffffffff, 0xffffffff, -1, 0); test::(-1000000000000, 1, -1000000000000, 0); test::(-1000000000000, 3, -333333333334, 2); test::(-1000000000000, 123, -8130081301, 23); test::(-1000000000000, 0xffffffff, -233, 727379735); test::(-1000000000000000000000000, 1, -1000000000000000000000000, 0); test::(-1000000000000000000000000, 3, -333333333333333333333334, 2); test::(-1000000000000000000000000, 123, -8130081300813008130082, 86); test::( -1000000000000000000000000, 0xffffffff, -232830643708080, 1127243600, ); test::( -1000000000000000000000000, 1234567890987, -810000006724, 704498996588, ); test::( -253640751230376270397812803167, 2669936877441, -94998781946290114, 1149635115107, ); test::( -3768477692975601, 11447376614057827956, -1, 11443608136364852355, ); test::(-3356605361737854, 3081095617839357, -2, 2805585873940860); test::( -1098730198198174614195, 953382298040157850476, -2, 808034397882141086757, ); test::( -69738658860594537152875081748, 69738658860594537152875081748, -1, 0, ); test::(-1000000000000000000000000, 1000000000000000000000000, -1, 0); test::( -123, 1000000000000000000000000, -1, 999999999999999999999877, ); test::(-1, -1, 1, 0); test::(-123, -1, 123, 0); test::(-123, -123, 1, 0); test::(-123, -456, 0, -123); test::(-456, -123, 3, -87); test::(-0xffffffff, -1, 0xffffffff, 0); test::(-0xffffffff, -0xffffffff, 1, 0); test::(-1000000000000, -1, 1000000000000, 0); test::(-1000000000000, -3, 333333333333, -1); test::(-1000000000000, -123, 8130081300, -100); test::(-1000000000000, -0xffffffff, 232, -3567587560); test::(-1000000000000000000000000, -1, 1000000000000000000000000, 0); test::(-1000000000000000000000000, -3, 333333333333333333333333, -1); test::( -1000000000000000000000000, -123, 8130081300813008130081, -37, ); test::( -1000000000000000000000000, -0xffffffff, 232830643708079, -3167723695, ); test::( -1000000000000000000000000, -1234567890987, 810000006723, -530068894399, ); test::( -253640751230376270397812803167, -2669936877441, 94998781946290113, -1520301762334, ); test::( -3768477692975601, -11447376614057827956, 0, -3768477692975601, ); test::(-3356605361737854, -3081095617839357, 1, -275509743898497); test::( -1098730198198174614195, -953382298040157850476, 1, -145347900158016763719, ); test::( -69738658860594537152875081748, -69738658860594537152875081748, 1, 0, ); test::(-1000000000000000000000000, -1000000000000000000000000, 1, 0); test::(-123, -1000000000000000000000000, 0, -123); } fn div_mod_fail_helper() { assert_panic!(T::ONE.div_mod(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.div_assign_mod(T::ZERO); }); } fn div_mod_signed_fail_helper() { assert_panic!(T::MIN.div_mod(T::NEGATIVE_ONE)); assert_panic!({ let mut n = T::MIN; n.div_assign_mod(T::NEGATIVE_ONE); }); } #[test] pub fn div_mod_fail() { apply_fn_to_primitive_ints!(div_mod_fail_helper); apply_fn_to_signeds!(div_mod_signed_fail_helper); } fn div_mod_properties_helper_signed() { signed_pair_gen_var_4::().test_properties(|(x, y)| { let mut mut_x = x; let r = mut_x.div_assign_mod(y); let q = mut_x; assert_eq!(x.div_mod(y), (q, r)); let (q_alt, r_alt) = (x.div_round(y, Floor).0, x.mod_op(y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); assert!(r.lt_abs(&y)); assert!(r == T::ZERO || (r > T::ZERO) == (y > T::ZERO)); if let Some(product) = q.checked_mul(y) { assert_eq!(product + r, x); } else if q > T::ZERO { assert_eq!((q - T::ONE) * y + r + y, x); } else { assert_eq!((q + T::ONE) * y + r - y, x); } if x != T::MIN { let (neg_q, neg_r) = (-x).div_mod(y); assert_eq!(x.ceiling_div_mod(y), (-neg_q, -neg_r)); } if y != T::MIN && (x != T::MIN || y != T::ONE) { let (neg_q, r) = x.div_mod(-y); assert_eq!(x.ceiling_div_mod(y), (-neg_q, r)); } }); signed_gen::().test_properties(|x| { let (q, r) = x.div_mod(T::ONE); assert_eq!(q, x); assert_eq!(r, T::ZERO); if x != T::MIN { let (q, r) = x.div_mod(T::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, T::ZERO); } assert_panic!(x.div_mod(T::ZERO)); assert_panic!({ let mut y = x; y.div_assign_mod(T::ZERO) }); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(x.div_mod(T::ONE), (x, T::ZERO)); assert_eq!(x.div_mod(x), (T::ONE, T::ZERO)); assert_eq!(T::ZERO.div_mod(x), (T::ZERO, T::ZERO)); if x != T::MIN { assert_eq!(x.div_mod(T::NEGATIVE_ONE), (-x, T::ZERO)); assert_eq!(x.div_mod(-x), (T::NEGATIVE_ONE, T::ZERO)); } if x > T::ONE { assert_eq!(T::ONE.div_mod(x), (T::ZERO, T::ONE)); assert_eq!(T::NEGATIVE_ONE.div_mod(x), (T::NEGATIVE_ONE, x - T::ONE)); } }); } #[test] fn div_mod_properties() { apply_fn_to_unsigneds!(div_mod_and_div_rem_properties_helper_unsigned); apply_fn_to_signeds!(div_mod_properties_helper_signed); } #[test] fn test_div_rem_signed() { fn test(n: T, d: T, q: T, r: T) { assert_eq!(n.div_rem(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.div_assign_rem(d), r); assert_eq!(mut_n, q); } test::(0, 1, 0, 0); test::(0, 123, 0, 0); test::(1, 1, 1, 0); test::(123, 1, 123, 0); test::(123, 123, 1, 0); test::(123, 456, 0, 123); test::(456, 123, 3, 87); test::(0xffffffff, 1, 0xffffffff, 0); test::(0xffffffff, 0xffffffff, 1, 0); test::(1000000000000, 1, 1000000000000, 0); test::(1000000000000, 3, 333333333333, 1); test::(1000000000000, 123, 8130081300, 100); test::(1000000000000, 0xffffffff, 232, 3567587560); test::(1000000000000000000000000, 1, 1000000000000000000000000, 0); test::(1000000000000000000000000, 3, 333333333333333333333333, 1); test::(1000000000000000000000000, 123, 8130081300813008130081, 37); test::( 1000000000000000000000000, 0xffffffff, 232830643708079, 3167723695, ); test::( 1000000000000000000000000, 1234567890987, 810000006723, 530068894399, ); test::( 253640751230376270397812803167, 2669936877441, 94998781946290113, 1520301762334, ); test::(3768477692975601, 11447376614057827956, 0, 3768477692975601); test::(3356605361737854, 3081095617839357, 1, 275509743898497); test::( 1098730198198174614195, 953382298040157850476, 1, 145347900158016763719, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 1, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(123, 1000000000000000000000000, 0, 123); test::(0, -1, 0, 0); test::(0, -123, 0, 0); test::(1, -1, -1, 0); test::(123, -1, -123, 0); test::(123, -123, -1, 0); test::(123, -456, 0, 123); test::(456, -123, -3, 87); test::(0xffffffff, -1, -0xffffffff, 0); test::(0xffffffff, -0xffffffff, -1, 0); test::(1000000000000, -1, -1000000000000, 0); test::(1000000000000, -3, -333333333333, 1); test::(1000000000000, -123, -8130081300, 100); test::(1000000000000, -0xffffffff, -232, 3567587560); test::(1000000000000000000000000, -1, -1000000000000000000000000, 0); test::(1000000000000000000000000, -3, -333333333333333333333333, 1); test::(1000000000000000000000000, -123, -8130081300813008130081, 37); test::( 1000000000000000000000000, -0xffffffff, -232830643708079, 3167723695, ); test::( 1000000000000000000000000, -1234567890987, -810000006723, 530068894399, ); test::( 253640751230376270397812803167, -2669936877441, -94998781946290113, 1520301762334, ); test::(3768477692975601, -11447376614057827956, 0, 3768477692975601); test::(3356605361737854, -3081095617839357, -1, 275509743898497); test::( 1098730198198174614195, -953382298040157850476, -1, 145347900158016763719, ); test::( 69738658860594537152875081748, -69738658860594537152875081748, -1, 0, ); test::(1000000000000000000000000, -1000000000000000000000000, -1, 0); test::(0, -1000000000000000000000000, 0, 0); test::(123, -1000000000000000000000000, 0, 123); test::(-1, 1, -1, 0); test::(-123, 1, -123, 0); test::(-123, 123, -1, 0); test::(-123, 456, 0, -123); test::(-456, 123, -3, -87); test::(-0xffffffff, 1, -0xffffffff, 0); test::(-0xffffffff, 0xffffffff, -1, 0); test::(-1000000000000, 1, -1000000000000, 0); test::(-1000000000000, 3, -333333333333, -1); test::(-1000000000000, 123, -8130081300, -100); test::(-1000000000000, 0xffffffff, -232, -3567587560); test::(-1000000000000000000000000, 1, -1000000000000000000000000, 0); test::(-1000000000000000000000000, 3, -333333333333333333333333, -1); test::( -1000000000000000000000000, 123, -8130081300813008130081, -37, ); test::( -1000000000000000000000000, 0xffffffff, -232830643708079, -3167723695, ); test::( -1000000000000000000000000, 1234567890987, -810000006723, -530068894399, ); test::( -253640751230376270397812803167, 2669936877441, -94998781946290113, -1520301762334, ); test::( -3768477692975601, 11447376614057827956, 0, -3768477692975601, ); test::(-3356605361737854, 3081095617839357, -1, -275509743898497); test::( -1098730198198174614195, 953382298040157850476, -1, -145347900158016763719, ); test::( -69738658860594537152875081748, 69738658860594537152875081748, -1, 0, ); test::(-1000000000000000000000000, 1000000000000000000000000, -1, 0); test::(-123, 1000000000000000000000000, 0, -123); test::(-1, -1, 1, 0); test::(-123, -1, 123, 0); test::(-123, -123, 1, 0); test::(-123, -456, 0, -123); test::(-456, -123, 3, -87); test::(-0xffffffff, -1, 0xffffffff, 0); test::(-0xffffffff, -0xffffffff, 1, 0); test::(-1000000000000, -1, 1000000000000, 0); test::(-1000000000000, -3, 333333333333, -1); test::(-1000000000000, -123, 8130081300, -100); test::(-1000000000000, -0xffffffff, 232, -3567587560); test::(-1000000000000000000000000, -1, 1000000000000000000000000, 0); test::(-1000000000000000000000000, -3, 333333333333333333333333, -1); test::( -1000000000000000000000000, -123, 8130081300813008130081, -37, ); test::( -1000000000000000000000000, -0xffffffff, 232830643708079, -3167723695, ); test::( -1000000000000000000000000, -1234567890987, 810000006723, -530068894399, ); test::( -253640751230376270397812803167, -2669936877441, 94998781946290113, -1520301762334, ); test::( -3768477692975601, -11447376614057827956, 0, -3768477692975601, ); test::(-3356605361737854, -3081095617839357, 1, -275509743898497); test::( -1098730198198174614195, -953382298040157850476, 1, -145347900158016763719, ); test::( -69738658860594537152875081748, -69738658860594537152875081748, 1, 0, ); test::(-1000000000000000000000000, -1000000000000000000000000, 1, 0); test::(-123, -1000000000000000000000000, 0, -123); } fn div_rem_fail_helper() { assert_panic!(T::ONE.div_rem(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.div_assign_rem(T::ZERO); }); } fn div_rem_signed_fail_helper() { assert_panic!(T::MIN.div_rem(T::NEGATIVE_ONE)); assert_panic!({ let mut n = T::MIN; n.div_assign_rem(T::NEGATIVE_ONE); }); } #[test] pub fn div_rem_fail() { apply_fn_to_primitive_ints!(div_rem_fail_helper); apply_fn_to_signeds!(div_rem_signed_fail_helper); } fn div_rem_properties_helper_signed() { signed_pair_gen_var_4::().test_properties(|(x, y)| { let mut mut_x = x; let r = mut_x.div_assign_rem(y); let q = mut_x; assert_eq!(x.div_rem(y), (q, r)); assert_eq!((x / y, x % y), (q, r)); assert!(r.lt_abs(&y)); assert!(r == T::ZERO || (r > T::ZERO) == (x > T::ZERO)); assert_eq!(q * y + r, x); if x != T::MIN { assert_eq!((-x).div_rem(y), (-q, -r)); } if y != T::MIN && (x != T::MIN || y != T::ONE) { assert_eq!(x.div_rem(-y), (-q, r)); } }); signed_gen::().test_properties(|x| { let (q, r) = x.div_rem(T::ONE); assert_eq!(q, x); assert_eq!(r, T::ZERO); if x != T::MIN { let (q, r) = x.div_rem(T::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, T::ZERO); } assert_panic!(x.div_rem(T::ZERO)); assert_panic!({ let mut y = x; y.div_assign_rem(T::ZERO) }); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(x.div_rem(T::ONE), (x, T::ZERO)); assert_eq!(x.div_rem(x), (T::ONE, T::ZERO)); assert_eq!(T::ZERO.div_rem(x), (T::ZERO, T::ZERO)); if x != T::MIN { assert_eq!(x.div_rem(T::NEGATIVE_ONE), (-x, T::ZERO)); assert_eq!(x.div_rem(-x), (T::NEGATIVE_ONE, T::ZERO)); } if x > T::ONE { assert_eq!(T::ONE.div_rem(x), (T::ZERO, T::ONE)); assert_eq!(T::NEGATIVE_ONE.div_rem(x), (T::ZERO, T::NEGATIVE_ONE)); } }); } #[test] fn div_rem_properties() { apply_fn_to_signeds!(div_rem_properties_helper_signed); } #[test] fn test_ceiling_div_neg_mod() { fn test(n: T, d: T, q: T, r: T) { assert_eq!(n.ceiling_div_neg_mod(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.ceiling_div_assign_neg_mod(d), r); assert_eq!(mut_n, q); } test::(0, 1, 0, 0); test::(0, 123, 0, 0); test::(1, 1, 1, 0); test::(123, 1, 123, 0); test::(123, 123, 1, 0); test::(123, 456, 1, 333); test::(456, 123, 4, 36); test::(0xffffffff, 1, 0xffffffff, 0); test::(0xffffffff, 0xffffffff, 1, 0); test::(1000000000000, 1, 1000000000000, 0); test::(1000000000000, 3, 333333333334, 2); test::(1000000000000, 123, 8130081301, 23); test::(1000000000000, 0xffffffff, 233, 727379735); test::(1000000000000000000000000, 1, 1000000000000000000000000, 0); test::(1000000000000000000000000, 3, 333333333333333333333334, 2); test::(1000000000000000000000000, 123, 8130081300813008130082, 86); test::( 1000000000000000000000000, 0xffffffff, 232830643708080, 1127243600, ); test::( 1000000000000000000000000, 1234567890987, 810000006724, 704498996588, ); test::( 253640751230376270397812803167, 2669936877441, 94998781946290114, 1149635115107, ); test::( 3768477692975601, 11447376614057827956, 1, 11443608136364852355, ); test::(3356605361737854, 3081095617839357, 2, 2805585873940860); test::( 1098730198198174614195, 953382298040157850476, 2, 808034397882141086757, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 1, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(123, 1000000000000000000000000, 1, 999999999999999999999877); } fn ceiling_div_neg_mod_fail_helper() { assert_panic!(T::ONE.ceiling_div_neg_mod(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.ceiling_div_assign_neg_mod(T::ZERO); }); } #[test] pub fn ceiling_div_neg_mod_fail() { apply_fn_to_unsigneds!(ceiling_div_neg_mod_fail_helper); } fn ceiling_div_neg_mod_properties_helper() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut mut_x = x; let r = mut_x.ceiling_div_assign_neg_mod(y); let q = mut_x; assert_eq!(x.ceiling_div_neg_mod(y), (q, r)); let (q_alt, r_alt) = (x.div_round(y, Ceiling).0, x.neg_mod(y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); assert!(r < y); if let Some(product) = q.checked_mul(y) { assert_eq!(product - r, x); } else { assert_eq!((q - T::ONE) * y - r + y, x); } }); unsigned_gen::().test_properties(|x| { assert_eq!(x.ceiling_div_neg_mod(T::ONE), (x, T::ZERO)); assert_panic!(x.ceiling_div_neg_mod(T::ZERO)); assert_panic!({ let mut y = x; y.ceiling_div_assign_neg_mod(T::ZERO) }); }); unsigned_gen_var_1::().test_properties(|x| { assert_eq!(x.ceiling_div_neg_mod(x), (T::ONE, T::ZERO)); assert_eq!(T::ZERO.ceiling_div_neg_mod(x), (T::ZERO, T::ZERO)); if x > T::ONE { assert_eq!(T::ONE.ceiling_div_neg_mod(x), (T::ONE, x - T::ONE)); } }); } #[test] fn ceiling_div_neg_mod_properties() { apply_fn_to_unsigneds!(ceiling_div_neg_mod_properties_helper); } #[test] fn test_ceiling_div_mod() { fn test(n: T, d: T, q: T, r: T) { assert_eq!(n.ceiling_div_mod(d), (q, r)); let mut mut_n = n; assert_eq!(mut_n.ceiling_div_assign_mod(d), r); assert_eq!(mut_n, q); } test::(0, 1, 0, 0); test::(0, 123, 0, 0); test::(1, 1, 1, 0); test::(123, 1, 123, 0); test::(123, 123, 1, 0); test::(123, 456, 1, -333); test::(456, 123, 4, -36); test::(0xffffffff, 1, 0xffffffff, 0); test::(0xffffffff, 0xffffffff, 1, 0); test::(1000000000000, 1, 1000000000000, 0); test::(1000000000000, 3, 333333333334, -2); test::(1000000000000, 123, 8130081301, -23); test::(1000000000000, 0xffffffff, 233, -727379735); test::(1000000000000000000000000, 1, 1000000000000000000000000, 0); test::(1000000000000000000000000, 3, 333333333333333333333334, -2); test::(1000000000000000000000000, 123, 8130081300813008130082, -86); test::( 1000000000000000000000000, 0xffffffff, 232830643708080, -1127243600, ); test::( 1000000000000000000000000, 1234567890987, 810000006724, -704498996588, ); test::( 253640751230376270397812803167, 2669936877441, 94998781946290114, -1149635115107, ); test::( 3768477692975601, 11447376614057827956, 1, -11443608136364852355, ); test::(3356605361737854, 3081095617839357, 2, -2805585873940860); test::( 1098730198198174614195, 953382298040157850476, 2, -808034397882141086757, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 1, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(123, 1000000000000000000000000, 1, -999999999999999999999877); test::(0, -1, 0, 0); test::(0, -123, 0, 0); test::(1, -1, -1, 0); test::(123, -1, -123, 0); test::(123, -123, -1, 0); test::(123, -456, 0, 123); test::(456, -123, -3, 87); test::(0xffffffff, -1, -0xffffffff, 0); test::(0xffffffff, -0xffffffff, -1, 0); test::(1000000000000, -1, -1000000000000, 0); test::(1000000000000, -3, -333333333333, 1); test::(1000000000000, -123, -8130081300, 100); test::(1000000000000, -0xffffffff, -232, 3567587560); test::(1000000000000000000000000, -1, -1000000000000000000000000, 0); test::(1000000000000000000000000, -3, -333333333333333333333333, 1); test::(1000000000000000000000000, -123, -8130081300813008130081, 37); test::( 1000000000000000000000000, -0xffffffff, -232830643708079, 3167723695, ); test::( 1000000000000000000000000, -1234567890987, -810000006723, 530068894399, ); test::( 253640751230376270397812803167, -2669936877441, -94998781946290113, 1520301762334, ); test::(3768477692975601, -11447376614057827956, 0, 3768477692975601); test::(3356605361737854, -3081095617839357, -1, 275509743898497); test::( 1098730198198174614195, -953382298040157850476, -1, 145347900158016763719, ); test::( 69738658860594537152875081748, -69738658860594537152875081748, -1, 0, ); test::(1000000000000000000000000, -1000000000000000000000000, -1, 0); test::(0, -1000000000000000000000000, 0, 0); test::(123, -1000000000000000000000000, 0, 123); test::(-1, 1, -1, 0); test::(-123, 1, -123, 0); test::(-123, 123, -1, 0); test::(-123, 456, 0, -123); test::(-456, 123, -3, -87); test::(-0xffffffff, 1, -0xffffffff, 0); test::(-0xffffffff, 0xffffffff, -1, 0); test::(-1000000000000, 1, -1000000000000, 0); test::(-1000000000000, 3, -333333333333, -1); test::(-1000000000000, 123, -8130081300, -100); test::(-1000000000000, 0xffffffff, -232, -3567587560); test::(-1000000000000000000000000, 1, -1000000000000000000000000, 0); test::(-1000000000000000000000000, 3, -333333333333333333333333, -1); test::( -1000000000000000000000000, 123, -8130081300813008130081, -37, ); test::( -1000000000000000000000000, 0xffffffff, -232830643708079, -3167723695, ); test::( -1000000000000000000000000, 1234567890987, -810000006723, -530068894399, ); test::( -253640751230376270397812803167, 2669936877441, -94998781946290113, -1520301762334, ); test::( -3768477692975601, 11447376614057827956, 0, -3768477692975601, ); test::(-3356605361737854, 3081095617839357, -1, -275509743898497); test::( -1098730198198174614195, 953382298040157850476, -1, -145347900158016763719, ); test::( -69738658860594537152875081748, 69738658860594537152875081748, -1, 0, ); test::(-1000000000000000000000000, 1000000000000000000000000, -1, 0); test::(0, 1000000000000000000000000, 0, 0); test::(-123, 1000000000000000000000000, 0, -123); test::(-1, -1, 1, 0); test::(-123, -1, 123, 0); test::(-123, -123, 1, 0); test::(-123, -456, 1, 333); test::(-456, -123, 4, 36); test::(-0xffffffff, -1, 0xffffffff, 0); test::(-0xffffffff, -0xffffffff, 1, 0); test::(-1000000000000, -1, 1000000000000, 0); test::(-1000000000000, -3, 333333333334, 2); test::(-1000000000000, -123, 8130081301, 23); test::(-1000000000000, -0xffffffff, 233, 727379735); test::(-1000000000000000000000000, -1, 1000000000000000000000000, 0); test::(-1000000000000000000000000, -3, 333333333333333333333334, 2); test::(-1000000000000000000000000, -123, 8130081300813008130082, 86); test::( -1000000000000000000000000, -0xffffffff, 232830643708080, 1127243600, ); test::( -1000000000000000000000000, -1234567890987, 810000006724, 704498996588, ); test::( -253640751230376270397812803167, -2669936877441, 94998781946290114, 1149635115107, ); test::( -3768477692975601, -11447376614057827956, 1, 11443608136364852355, ); test::(-3356605361737854, -3081095617839357, 2, 2805585873940860); test::( -1098730198198174614195, -953382298040157850476, 2, 808034397882141086757, ); test::( -69738658860594537152875081748, -69738658860594537152875081748, 1, 0, ); test::(-1000000000000000000000000, -1000000000000000000000000, 1, 0); test::(0, -1000000000000000000000000, 0, 0); test::( -123, -1000000000000000000000000, 1, 999999999999999999999877, ); } fn ceiling_div_mod_fail_helper() { assert_panic!(T::ONE.ceiling_div_mod(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.ceiling_div_assign_mod(T::ZERO); }); assert_panic!(T::MIN.ceiling_div_mod(T::NEGATIVE_ONE)); assert_panic!({ let mut n = T::MIN; n.ceiling_div_assign_mod(T::NEGATIVE_ONE); }); } #[test] pub fn ceiling_div_mod_fail() { apply_fn_to_signeds!(ceiling_div_mod_fail_helper); } fn ceiling_div_mod_properties_helper() { signed_pair_gen_var_4::().test_properties(|(x, y)| { let mut mut_x = x; let r = mut_x.ceiling_div_assign_mod(y); let q = mut_x; assert_eq!(x.ceiling_div_mod(y), (q, r)); let (q_alt, r_alt) = (x.div_round(y, Ceiling).0, x.ceiling_mod(y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); assert!(r.lt_abs(&y)); assert!(r == T::ZERO || (r > T::ZERO) != (y > T::ZERO)); if let Some(product) = q.checked_mul(y) { assert_eq!(product + r, x); } else if q > T::ZERO { assert_eq!((q - T::ONE) * y + r + y, x); } else { assert_eq!((q + T::ONE) * y + r - y, x); } if x != T::MIN { let (neg_q, neg_r) = (-x).ceiling_div_mod(y); assert_eq!(x.div_mod(y), (-neg_q, -neg_r)); } if y != T::MIN && (x != T::MIN || y != T::ONE) { let (neg_q, r) = x.ceiling_div_mod(-y); assert_eq!(x.div_mod(y), (-neg_q, r)); } }); signed_gen::().test_properties(|x| { let (q, r) = x.ceiling_div_mod(T::ONE); assert_eq!(q, x); assert_eq!(r, T::ZERO); if x != T::MIN { let (q, r) = x.ceiling_div_mod(T::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, T::ZERO); } assert_panic!(x.ceiling_div_mod(T::ZERO)); assert_panic!({ let mut y = x; y.ceiling_div_assign_mod(T::ZERO) }); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(x.ceiling_div_mod(T::ONE), (x, T::ZERO)); if x != T::MIN { assert_eq!(x.ceiling_div_mod(T::NEGATIVE_ONE), (-x, T::ZERO)); } assert_eq!(x.ceiling_div_mod(x), (T::ONE, T::ZERO)); if x != T::MIN { assert_eq!(x.ceiling_div_mod(-x), (T::NEGATIVE_ONE, T::ZERO)); } assert_eq!(T::ZERO.ceiling_div_mod(x), (T::ZERO, T::ZERO)); }); } #[test] fn ceiling_div_mod_properties() { apply_fn_to_signeds!(ceiling_div_mod_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_pair_gen_var_3, signed_pair_gen_var_5, signed_rounding_mode_pair_gen, signed_rounding_mode_pair_gen_var_1, signed_rounding_mode_pair_gen_var_2, signed_rounding_mode_pair_gen_var_3, signed_signed_rounding_mode_triple_gen_var_1, unsigned_pair_gen_var_11, unsigned_pair_gen_var_12, unsigned_pair_gen_var_13, unsigned_rounding_mode_pair_gen, unsigned_rounding_mode_pair_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_div_round_unsigned() { fn test(n: T, d: T, rm: RoundingMode, q: T, o: Ordering) { assert_eq!(n.div_round(d, rm), (q, o)); let mut mut_n = n; assert_eq!(mut_n.div_round_assign(d, rm), o); assert_eq!(mut_n, q); } test::(0, 1, Down, 0, Equal); test::(0, 1, Floor, 0, Equal); test::(0, 1, Up, 0, Equal); test::(0, 1, Ceiling, 0, Equal); test::(0, 1, Nearest, 0, Equal); test::(0, 1, Exact, 0, Equal); test::(0, 123, Down, 0, Equal); test::(0, 123, Floor, 0, Equal); test::(0, 123, Up, 0, Equal); test::(0, 123, Ceiling, 0, Equal); test::(0, 123, Nearest, 0, Equal); test::(0, 123, Exact, 0, Equal); test::(1, 1, Down, 1, Equal); test::(1, 1, Floor, 1, Equal); test::(1, 1, Up, 1, Equal); test::(1, 1, Ceiling, 1, Equal); test::(1, 1, Nearest, 1, Equal); test::(1, 1, Exact, 1, Equal); test::(123, 1, Down, 123, Equal); test::(123, 1, Floor, 123, Equal); test::(123, 1, Up, 123, Equal); test::(123, 1, Ceiling, 123, Equal); test::(123, 1, Nearest, 123, Equal); test::(123, 1, Exact, 123, Equal); test::(123, 2, Down, 61, Less); test::(123, 2, Floor, 61, Less); test::(123, 2, Up, 62, Greater); test::(123, 2, Ceiling, 62, Greater); test::(123, 2, Nearest, 62, Greater); test::(125, 2, Down, 62, Less); test::(125, 2, Floor, 62, Less); test::(125, 2, Up, 63, Greater); test::(125, 2, Ceiling, 63, Greater); test::(125, 2, Nearest, 62, Less); test::(123, 123, Down, 1, Equal); test::(123, 123, Floor, 1, Equal); test::(123, 123, Up, 1, Equal); test::(123, 123, Ceiling, 1, Equal); test::(123, 123, Nearest, 1, Equal); test::(123, 123, Exact, 1, Equal); test::(123, 456, Down, 0, Less); test::(123, 456, Floor, 0, Less); test::(123, 456, Up, 1, Greater); test::(123, 456, Ceiling, 1, Greater); test::(123, 456, Nearest, 0, Less); test::(1000000000000, 1, Down, 1000000000000, Equal); test::(1000000000000, 1, Floor, 1000000000000, Equal); test::(1000000000000, 1, Up, 1000000000000, Equal); test::(1000000000000, 1, Ceiling, 1000000000000, Equal); test::(1000000000000, 1, Nearest, 1000000000000, Equal); test::(1000000000000, 1, Exact, 1000000000000, Equal); test::(1000000000000, 3, Down, 333333333333, Less); test::(1000000000000, 3, Floor, 333333333333, Less); test::(1000000000000, 3, Up, 333333333334, Greater); test::(1000000000000, 3, Ceiling, 333333333334, Greater); test::(1000000000000, 3, Nearest, 333333333333, Less); test::(999999999999, 2, Down, 499999999999, Less); test::(999999999999, 2, Floor, 499999999999, Less); test::(999999999999, 2, Up, 500000000000, Greater); test::(999999999999, 2, Ceiling, 500000000000, Greater); test::(999999999999, 2, Nearest, 500000000000, Greater); test::(1000000000001, 2, Down, 500000000000, Less); test::(1000000000001, 2, Floor, 500000000000, Less); test::(1000000000001, 2, Up, 500000000001, Greater); test::(1000000000001, 2, Ceiling, 500000000001, Greater); test::(1000000000001, 2, Nearest, 500000000000, Less); test::( 1000000000000000000000000, 0xffffffff, Down, 232830643708079, Less, ); test::( 1000000000000000000000000, 0xffffffff, Floor, 232830643708079, Less, ); test::( 1000000000000000000000000, 0xffffffff, Up, 232830643708080, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Ceiling, 232830643708080, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Nearest, 232830643708080, Greater, ); test::( 1000000000000000000000000, 1000000000000, Down, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Floor, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Up, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Ceiling, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Nearest, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Exact, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000001, Down, 999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Floor, 999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Up, 1000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Ceiling, 1000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Nearest, 999999999999, Less, ); test::( 2999999999999999999999999, 2000000000000000000000000, Nearest, 1, Less, ); test::( 3000000000000000000000000, 2000000000000000000000000, Nearest, 2, Greater, ); test::( 3000000000000000000000001, 2000000000000000000000000, Nearest, 2, Greater, ); } #[test] fn test_div_round_signed() { fn test(n: T, d: T, rm: RoundingMode, q: T, o: Ordering) { assert_eq!(n.div_round(d, rm), (q, o)); let mut mut_n = n; assert_eq!(mut_n.div_round_assign(d, rm), o); assert_eq!(mut_n, q); } test::(0, 1, Down, 0, Equal); test::(0, 1, Floor, 0, Equal); test::(0, 1, Up, 0, Equal); test::(0, 1, Ceiling, 0, Equal); test::(0, 1, Nearest, 0, Equal); test::(0, 1, Exact, 0, Equal); test::(0, 123, Down, 0, Equal); test::(0, 123, Floor, 0, Equal); test::(0, 123, Up, 0, Equal); test::(0, 123, Ceiling, 0, Equal); test::(0, 123, Nearest, 0, Equal); test::(0, 123, Exact, 0, Equal); test::(1, 1, Down, 1, Equal); test::(1, 1, Floor, 1, Equal); test::(1, 1, Up, 1, Equal); test::(1, 1, Ceiling, 1, Equal); test::(1, 1, Nearest, 1, Equal); test::(1, 1, Exact, 1, Equal); test::(123, 1, Down, 123, Equal); test::(123, 1, Floor, 123, Equal); test::(123, 1, Up, 123, Equal); test::(123, 1, Ceiling, 123, Equal); test::(123, 1, Nearest, 123, Equal); test::(123, 1, Exact, 123, Equal); test::(123, 2, Down, 61, Less); test::(123, 2, Floor, 61, Less); test::(123, 2, Up, 62, Greater); test::(123, 2, Ceiling, 62, Greater); test::(123, 2, Nearest, 62, Greater); test::(125, 2, Down, 62, Less); test::(125, 2, Floor, 62, Less); test::(125, 2, Up, 63, Greater); test::(125, 2, Ceiling, 63, Greater); test::(125, 2, Nearest, 62, Less); test::(123, 123, Down, 1, Equal); test::(123, 123, Floor, 1, Equal); test::(123, 123, Up, 1, Equal); test::(123, 123, Ceiling, 1, Equal); test::(123, 123, Nearest, 1, Equal); test::(123, 123, Exact, 1, Equal); test::(123, 456, Down, 0, Less); test::(123, 456, Floor, 0, Less); test::(123, 456, Up, 1, Greater); test::(123, 456, Ceiling, 1, Greater); test::(123, 456, Nearest, 0, Less); test::(1000000000000, 1, Down, 1000000000000, Equal); test::(1000000000000, 1, Floor, 1000000000000, Equal); test::(1000000000000, 1, Up, 1000000000000, Equal); test::(1000000000000, 1, Ceiling, 1000000000000, Equal); test::(1000000000000, 1, Nearest, 1000000000000, Equal); test::(1000000000000, 1, Exact, 1000000000000, Equal); test::(1000000000000, 3, Down, 333333333333, Less); test::(1000000000000, 3, Floor, 333333333333, Less); test::(1000000000000, 3, Up, 333333333334, Greater); test::(1000000000000, 3, Ceiling, 333333333334, Greater); test::(1000000000000, 3, Nearest, 333333333333, Less); test::(999999999999, 2, Down, 499999999999, Less); test::(999999999999, 2, Floor, 499999999999, Less); test::(999999999999, 2, Up, 500000000000, Greater); test::(999999999999, 2, Ceiling, 500000000000, Greater); test::(999999999999, 2, Nearest, 500000000000, Greater); test::(1000000000001, 2, Down, 500000000000, Less); test::(1000000000001, 2, Floor, 500000000000, Less); test::(1000000000001, 2, Up, 500000000001, Greater); test::(1000000000001, 2, Ceiling, 500000000001, Greater); test::(1000000000001, 2, Nearest, 500000000000, Less); test::( 1000000000000000000000000, 0xffffffff, Down, 232830643708079, Less, ); test::( 1000000000000000000000000, 0xffffffff, Floor, 232830643708079, Less, ); test::( 1000000000000000000000000, 0xffffffff, Up, 232830643708080, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Ceiling, 232830643708080, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Nearest, 232830643708080, Greater, ); test::( 1000000000000000000000000, 1000000000000, Down, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Floor, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Up, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Ceiling, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Nearest, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Exact, 1000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000001, Down, 999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Floor, 999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Up, 1000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Ceiling, 1000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Nearest, 999999999999, Less, ); test::( 2999999999999999999999999, 2000000000000000000000000, Nearest, 1, Less, ); test::( 3000000000000000000000000, 2000000000000000000000000, Nearest, 2, Greater, ); test::( 3000000000000000000000001, 2000000000000000000000000, Nearest, 2, Greater, ); test::(0, -1, Down, 0, Equal); test::(0, -1, Floor, 0, Equal); test::(0, -1, Up, 0, Equal); test::(0, -1, Ceiling, 0, Equal); test::(0, -1, Nearest, 0, Equal); test::(0, -1, Exact, 0, Equal); test::(0, -123, Down, 0, Equal); test::(0, -123, Floor, 0, Equal); test::(0, -123, Up, 0, Equal); test::(0, -123, Ceiling, 0, Equal); test::(0, -123, Nearest, 0, Equal); test::(0, -123, Exact, 0, Equal); test::(1, -1, Down, -1, Equal); test::(1, -1, Floor, -1, Equal); test::(1, -1, Up, -1, Equal); test::(1, -1, Ceiling, -1, Equal); test::(1, -1, Nearest, -1, Equal); test::(1, -1, Exact, -1, Equal); test::(123, -1, Down, -123, Equal); test::(123, -1, Floor, -123, Equal); test::(123, -1, Up, -123, Equal); test::(123, -1, Ceiling, -123, Equal); test::(123, -1, Nearest, -123, Equal); test::(123, -1, Exact, -123, Equal); test::(123, -2, Down, -61, Greater); test::(123, -2, Floor, -62, Less); test::(123, -2, Up, -62, Less); test::(123, -2, Ceiling, -61, Greater); test::(123, -2, Nearest, -62, Less); test::(125, -2, Down, -62, Greater); test::(125, -2, Floor, -63, Less); test::(125, -2, Up, -63, Less); test::(125, -2, Ceiling, -62, Greater); test::(125, -2, Nearest, -62, Greater); test::(123, -123, Down, -1, Equal); test::(123, -123, Floor, -1, Equal); test::(123, -123, Up, -1, Equal); test::(123, -123, Ceiling, -1, Equal); test::(123, -123, Nearest, -1, Equal); test::(123, -123, Exact, -1, Equal); test::(123, -456, Down, 0, Greater); test::(123, -456, Floor, -1, Less); test::(123, -456, Up, -1, Less); test::(123, -456, Ceiling, 0, Greater); test::(123, -456, Nearest, 0, Greater); test::(1000000000000, -1, Down, -1000000000000, Equal); test::(1000000000000, -1, Floor, -1000000000000, Equal); test::(1000000000000, -1, Up, -1000000000000, Equal); test::(1000000000000, -1, Ceiling, -1000000000000, Equal); test::(1000000000000, -1, Nearest, -1000000000000, Equal); test::(1000000000000, -1, Exact, -1000000000000, Equal); test::(1000000000000, -3, Down, -333333333333, Greater); test::(1000000000000, -3, Floor, -333333333334, Less); test::(1000000000000, -3, Up, -333333333334, Less); test::(1000000000000, -3, Ceiling, -333333333333, Greater); test::(1000000000000, -3, Nearest, -333333333333, Greater); test::(999999999999, -2, Down, -499999999999, Greater); test::(999999999999, -2, Floor, -500000000000, Less); test::(999999999999, -2, Up, -500000000000, Less); test::(999999999999, -2, Ceiling, -499999999999, Greater); test::(999999999999, -2, Nearest, -500000000000, Less); test::(1000000000001, -2, Down, -500000000000, Greater); test::(1000000000001, -2, Floor, -500000000001, Less); test::(1000000000001, -2, Up, -500000000001, Less); test::(1000000000001, -2, Ceiling, -500000000000, Greater); test::(1000000000001, -2, Nearest, -500000000000, Greater); test::( 1000000000000000000000000, -0xffffffff, Down, -232830643708079, Greater, ); test::( 1000000000000000000000000, -0xffffffff, Floor, -232830643708080, Less, ); test::( 1000000000000000000000000, -0xffffffff, Up, -232830643708080, Less, ); test::( 1000000000000000000000000, -0xffffffff, Ceiling, -232830643708079, Greater, ); test::( 1000000000000000000000000, -0xffffffff, Nearest, -232830643708080, Less, ); test::( 1000000000000000000000000, -1000000000000, Down, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Floor, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Up, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Ceiling, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Nearest, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Exact, -1000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000001, Down, -999999999999, Greater, ); test::( 1000000000000000000000000, -1000000000001, Floor, -1000000000000, Less, ); test::( 1000000000000000000000000, -1000000000001, Up, -1000000000000, Less, ); test::( 1000000000000000000000000, -1000000000001, Ceiling, -999999999999, Greater, ); test::( 1000000000000000000000000, -1000000000001, Nearest, -999999999999, Greater, ); test::( 2999999999999999999999999, -2000000000000000000000000, Nearest, -1, Greater, ); test::( 3000000000000000000000000, -2000000000000000000000000, Nearest, -2, Less, ); test::( 3000000000000000000000001, -2000000000000000000000000, Nearest, -2, Less, ); test::(-1, 1, Down, -1, Equal); test::(-1, 1, Floor, -1, Equal); test::(-1, 1, Up, -1, Equal); test::(-1, 1, Ceiling, -1, Equal); test::(-1, 1, Nearest, -1, Equal); test::(-1, 1, Exact, -1, Equal); test::(-123, 1, Down, -123, Equal); test::(-123, 1, Floor, -123, Equal); test::(-123, 1, Up, -123, Equal); test::(-123, 1, Ceiling, -123, Equal); test::(-123, 1, Nearest, -123, Equal); test::(-123, 1, Exact, -123, Equal); test::(-123, 2, Down, -61, Greater); test::(-123, 2, Floor, -62, Less); test::(-123, 2, Up, -62, Less); test::(-123, 2, Ceiling, -61, Greater); test::(-123, 2, Nearest, -62, Less); test::(-125, 2, Down, -62, Greater); test::(-125, 2, Floor, -63, Less); test::(-125, 2, Up, -63, Less); test::(-125, 2, Ceiling, -62, Greater); test::(-125, 2, Nearest, -62, Greater); test::(-123, 123, Down, -1, Equal); test::(-123, 123, Floor, -1, Equal); test::(-123, 123, Up, -1, Equal); test::(-123, 123, Ceiling, -1, Equal); test::(-123, 123, Nearest, -1, Equal); test::(-123, 123, Exact, -1, Equal); test::(-123, 456, Down, 0, Greater); test::(-123, 456, Floor, -1, Less); test::(-123, 456, Up, -1, Less); test::(-123, 456, Ceiling, 0, Greater); test::(-123, 456, Nearest, 0, Greater); test::(-1000000000000, 1, Down, -1000000000000, Equal); test::(-1000000000000, 1, Floor, -1000000000000, Equal); test::(-1000000000000, 1, Up, -1000000000000, Equal); test::(-1000000000000, 1, Ceiling, -1000000000000, Equal); test::(-1000000000000, 1, Nearest, -1000000000000, Equal); test::(-1000000000000, 1, Exact, -1000000000000, Equal); test::(-1000000000000, 3, Down, -333333333333, Greater); test::(-1000000000000, 3, Floor, -333333333334, Less); test::(-1000000000000, 3, Up, -333333333334, Less); test::(-1000000000000, 3, Ceiling, -333333333333, Greater); test::(-1000000000000, 3, Nearest, -333333333333, Greater); test::(-999999999999, 2, Down, -499999999999, Greater); test::(-999999999999, 2, Floor, -500000000000, Less); test::(-999999999999, 2, Up, -500000000000, Less); test::(-999999999999, 2, Ceiling, -499999999999, Greater); test::(-999999999999, 2, Nearest, -500000000000, Less); test::(-1000000000001, 2, Down, -500000000000, Greater); test::(-1000000000001, 2, Floor, -500000000001, Less); test::(-1000000000001, 2, Up, -500000000001, Less); test::(-1000000000001, 2, Ceiling, -500000000000, Greater); test::(-1000000000001, 2, Nearest, -500000000000, Greater); test::( -1000000000000000000000000, 0xffffffff, Down, -232830643708079, Greater, ); test::( -1000000000000000000000000, 0xffffffff, Floor, -232830643708080, Less, ); test::( -1000000000000000000000000, 0xffffffff, Up, -232830643708080, Less, ); test::( -1000000000000000000000000, 0xffffffff, Ceiling, -232830643708079, Greater, ); test::( -1000000000000000000000000, 0xffffffff, Nearest, -232830643708080, Less, ); test::( -1000000000000000000000000, 1000000000000, Down, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Floor, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Up, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Ceiling, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Nearest, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Exact, -1000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000001, Down, -999999999999, Greater, ); test::( -1000000000000000000000000, 1000000000001, Floor, -1000000000000, Less, ); test::( -1000000000000000000000000, 1000000000001, Up, -1000000000000, Less, ); test::( -1000000000000000000000000, 1000000000001, Ceiling, -999999999999, Greater, ); test::( -1000000000000000000000000, 1000000000001, Nearest, -999999999999, Greater, ); test::( -2999999999999999999999999, 2000000000000000000000000, Nearest, -1, Greater, ); test::( -3000000000000000000000000, 2000000000000000000000000, Nearest, -2, Less, ); test::( -3000000000000000000000001, 2000000000000000000000000, Nearest, -2, Less, ); test::(-1, -1, Down, 1, Equal); test::(-1, -1, Floor, 1, Equal); test::(-1, -1, Up, 1, Equal); test::(-1, -1, Ceiling, 1, Equal); test::(-1, -1, Nearest, 1, Equal); test::(-1, -1, Exact, 1, Equal); test::(-123, -1, Down, 123, Equal); test::(-123, -1, Floor, 123, Equal); test::(-123, -1, Up, 123, Equal); test::(-123, -1, Ceiling, 123, Equal); test::(-123, -1, Nearest, 123, Equal); test::(-123, -1, Exact, 123, Equal); test::(-123, -2, Down, 61, Less); test::(-123, -2, Floor, 61, Less); test::(-123, -2, Up, 62, Greater); test::(-123, -2, Ceiling, 62, Greater); test::(-123, -2, Nearest, 62, Greater); test::(-125, -2, Down, 62, Less); test::(-125, -2, Floor, 62, Less); test::(-125, -2, Up, 63, Greater); test::(-125, -2, Ceiling, 63, Greater); test::(-125, -2, Nearest, 62, Less); test::(-123, -123, Down, 1, Equal); test::(-123, -123, Floor, 1, Equal); test::(-123, -123, Up, 1, Equal); test::(-123, -123, Ceiling, 1, Equal); test::(-123, -123, Nearest, 1, Equal); test::(-123, -123, Exact, 1, Equal); test::(-123, -456, Down, 0, Less); test::(-123, -456, Floor, 0, Less); test::(-123, -456, Up, 1, Greater); test::(-123, -456, Ceiling, 1, Greater); test::(-123, -456, Nearest, 0, Less); test::(-1000000000000, -1, Down, 1000000000000, Equal); test::(-1000000000000, -1, Floor, 1000000000000, Equal); test::(-1000000000000, -1, Up, 1000000000000, Equal); test::(-1000000000000, -1, Ceiling, 1000000000000, Equal); test::(-1000000000000, -1, Nearest, 1000000000000, Equal); test::(-1000000000000, -1, Exact, 1000000000000, Equal); test::(-1000000000000, -3, Down, 333333333333, Less); test::(-1000000000000, -3, Floor, 333333333333, Less); test::(-1000000000000, -3, Up, 333333333334, Greater); test::(-1000000000000, -3, Ceiling, 333333333334, Greater); test::(-1000000000000, -3, Nearest, 333333333333, Less); test::(-999999999999, -2, Down, 499999999999, Less); test::(-999999999999, -2, Floor, 499999999999, Less); test::(-999999999999, -2, Up, 500000000000, Greater); test::(-999999999999, -2, Ceiling, 500000000000, Greater); test::(-999999999999, -2, Nearest, 500000000000, Greater); test::(-1000000000001, -2, Down, 500000000000, Less); test::(-1000000000001, -2, Floor, 500000000000, Less); test::(-1000000000001, -2, Up, 500000000001, Greater); test::(-1000000000001, -2, Ceiling, 500000000001, Greater); test::(-1000000000001, -2, Nearest, 500000000000, Less); test::( -1000000000000000000000000, -0xffffffff, Down, 232830643708079, Less, ); test::( -1000000000000000000000000, -0xffffffff, Floor, 232830643708079, Less, ); test::( -1000000000000000000000000, -0xffffffff, Up, 232830643708080, Greater, ); test::( -1000000000000000000000000, -0xffffffff, Ceiling, 232830643708080, Greater, ); test::( -1000000000000000000000000, -0xffffffff, Nearest, 232830643708080, Greater, ); test::( -1000000000000000000000000, -1000000000000, Down, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Floor, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Up, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Ceiling, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Nearest, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Exact, 1000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000001, Down, 999999999999, Less, ); test::( -1000000000000000000000000, -1000000000001, Floor, 999999999999, Less, ); test::( -1000000000000000000000000, -1000000000001, Up, 1000000000000, Greater, ); test::( -1000000000000000000000000, -1000000000001, Ceiling, 1000000000000, Greater, ); test::( -1000000000000000000000000, -1000000000001, Nearest, 999999999999, Less, ); test::( -2999999999999999999999999, -2000000000000000000000000, Nearest, 1, Less, ); test::( -3000000000000000000000000, -2000000000000000000000000, Nearest, 2, Greater, ); test::( -3000000000000000000000001, -2000000000000000000000000, Nearest, 2, Greater, ); test::(-128, 1, Down, -128, Equal); test::(-128, 1, Up, -128, Equal); test::(-128, 1, Floor, -128, Equal); test::(-128, 1, Ceiling, -128, Equal); test::(-128, 1, Nearest, -128, Equal); test::(-128, 1, Exact, -128, Equal); } fn div_round_fail_helper() { assert_panic!(T::exact_from(10).div_round(T::ZERO, Floor)); assert_panic!(T::exact_from(10).div_round(T::exact_from(3), Exact)); assert_panic!(T::exact_from(10).div_round_assign(T::ZERO, Floor)); assert_panic!(T::exact_from(10).div_round_assign(T::exact_from(3), Exact)); } fn div_round_signed_fail_helper() { assert_panic!(T::MIN.div_round(T::NEGATIVE_ONE, Floor)); assert_panic!({ let mut n = T::MIN; n.div_round_assign(T::NEGATIVE_ONE, Floor); }); } #[test] fn div_round_fail() { apply_fn_to_primitive_ints!(div_round_fail_helper); apply_fn_to_signeds!(div_round_signed_fail_helper); } fn div_round_properties_helper_unsigned() { unsigned_unsigned_rounding_mode_triple_gen_var_1::().test_properties(|(x, y, rm)| { let mut mut_x = x; let o = mut_x.div_round_assign(y, rm); let q = mut_x; assert_eq!(x.div_round(y, rm), (q, o)); assert!(q <= x); assert_eq!(x.divisible_by(y), o == Equal); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } if let Some(product) = q.checked_mul(y) { assert_eq!(product.cmp(&x), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(x.div_round(y, rm), (q, Equal)); } } else { assert_panic!(x.div_round(y, Exact)); } }); unsigned_pair_gen_var_12::().test_properties(|(x, y)| { assert_eq!(x.ceiling_div_neg_mod(y).0, x.div_round(y, Ceiling).0); }); unsigned_pair_gen_var_11::().test_properties(|(x, y)| { let q = x.div_exact(y); let o = Equal; assert_eq!(x.div_round(y, Down), (q, o)); assert_eq!(x.div_round(y, Up), (q, o)); assert_eq!(x.div_round(y, Floor), (q, o)); assert_eq!(x.div_round(y, Ceiling), (q, o)); assert_eq!(x.div_round(y, Nearest), (q, o)); assert_eq!(x.div_round(y, Exact), (q, o)); }); unsigned_pair_gen_var_13::().test_properties(|(x, y)| { let down = x.div_round(y, Down); assert_eq!(down.1, Less); let up = (down.0 + T::ONE, Greater); assert_eq!(x.div_round(y, Up), up); assert_eq!(x.div_round(y, Floor), down); assert_eq!(x.div_round(y, Ceiling), up); let nearest = x.div_round(y, Nearest); assert!(nearest == down || nearest == up); }); unsigned_rounding_mode_pair_gen::().test_properties(|(x, rm)| { assert_eq!(x.div_round(T::ONE, rm), (x, Equal)); assert_panic!(x.div_round(T::ZERO, rm)); assert_panic!({ let mut y = x; y.div_round_assign(T::ZERO, rm) }); }); unsigned_rounding_mode_pair_gen_var_1::().test_properties(|(x, rm)| { assert_eq!(T::ZERO.div_round(x, rm), (T::ZERO, Equal)); assert_eq!(x.div_round(x, rm), (T::ONE, Equal)); }); } fn div_round_properties_helper_signed() { signed_signed_rounding_mode_triple_gen_var_1::().test_properties(|(x, y, rm)| { let mut mut_x = x; let o = mut_x.div_round_assign(y, rm); let q = mut_x; assert_eq!(x.div_round(y, rm), (q, o)); assert!(q.le_abs(&x)); assert_eq!(x.divisible_by(y), o == Equal); if x != T::MIN { let (q_alt, o_alt) = (-x).div_round(y, -rm); assert_eq!(-q_alt, q); assert_eq!(o_alt.reverse(), o); } if y != T::MIN && (x != T::MIN || (y != T::ONE && y != T::NEGATIVE_ONE)) { let (q_alt, o_alt) = x.div_round(-y, -rm); assert_eq!(-q_alt, q); assert_eq!(o_alt.reverse(), o); } match ((x >= T::ZERO) == (y >= T::ZERO), rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if let Some(product) = q.checked_mul(y) { assert_eq!(product.cmp(&x), if y >= T::ZERO { o } else { o.reverse() }); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(x.div_round(y, rm), (q, Equal)); } } else { assert_panic!(x.div_round(y, Exact)); } }); signed_pair_gen_var_3::().test_properties(|(x, y)| { let q = x.div_exact(y); let o = Equal; assert_eq!(x.div_round(y, Down), (q, o)); assert_eq!(x.div_round(y, Up), (q, o)); assert_eq!(x.div_round(y, Floor), (q, o)); assert_eq!(x.div_round(y, Ceiling), (q, o)); assert_eq!(x.div_round(y, Nearest), (q, o)); assert_eq!(x.div_round(y, Exact), (q, o)); }); signed_pair_gen_var_5::().test_properties(|(x, y)| { let down = x.div_round(y, Down); let up = if (x >= T::ZERO) == (y >= T::ZERO) { (down.0 + T::ONE, Greater) } else { (down.0 - T::ONE, Less) }; let floor = x.div_round(y, Floor); let ceiling = (floor.0 + T::ONE, Greater); assert_eq!(x.div_round(y, Up), up); assert_eq!(x.div_round(y, Ceiling), ceiling); let nearest = x.div_round(y, Nearest); assert!(nearest == down || nearest == up); }); signed_rounding_mode_pair_gen::().test_properties(|(x, rm)| { assert_eq!(x.div_round(T::ONE, rm), (x, Equal)); assert_panic!(x.div_round(T::ZERO, rm)); assert_panic!({ let mut y = x; y.div_round_assign(T::ZERO, rm) }); }); signed_rounding_mode_pair_gen_var_2::().test_properties(|(x, rm)| { assert_eq!(x.div_round(T::NEGATIVE_ONE, rm), (-x, Equal)); }); signed_rounding_mode_pair_gen_var_1::().test_properties(|(x, rm)| { assert_eq!(T::ZERO.div_round(x, rm), (T::ZERO, Equal)); assert_eq!(x.div_round(x, rm), (T::ONE, Equal)); }); signed_rounding_mode_pair_gen_var_3::().test_properties(|(x, rm)| { assert_eq!(x.div_round(-x, rm), (T::NEGATIVE_ONE, Equal)); assert_eq!((-x).div_round(x, rm), (T::NEGATIVE_ONE, Equal)); }); } #[test] fn div_round_properties() { apply_fn_to_unsigneds!(div_round_properties_helper_unsigned); apply_fn_to_signeds!(div_round_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_6, signed_pair_gen, signed_pair_gen_var_3, signed_pair_gen_var_5, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_11, unsigned_pair_gen_var_13, unsigned_pair_gen_var_27, }; #[test] fn test_divisible_by() { fn test(x: T, y: T, out: bool) { assert_eq!(x.divisible_by(y), out); } test::(0, 0, true); test::(1, 0, false); test::(1000000000000, 0, false); test::(0, 1, true); test::(0, 123, true); test::(1, 1, true); test::(123, 1, true); test::(123, 123, true); test::(123, 456, false); test::(456, 123, false); test::(369, 123, true); test::(0xffffffff, 1, true); test::(u32::MAX, u32::MAX, true); test::(1000000000000, 1, true); test::(1000000000000, 3, false); test::(1000000000002, 3, true); test::(1000000000000, 123, false); test::(1000000000000, 0xffffffff, false); test::(1000000000000000000000000, 1, true); test::(1000000000000000000000000, 3, false); test::(1000000000000000000000002, 3, true); test::(1000000000000000000000000, 123, false); test::(1000000000000000000000000, 0xffffffff, false); test::(1000000000000000000000000, 1000000000000, true); test::(1000000000000000000000000, 1000000000001, false); test::(1000000000000, 0, false); test::(0, -1, true); test::(0, -123, true); test::(1, -1, true); test::(123, -1, true); test::(123, -123, true); test::(123, -456, false); test::(456, -123, false); test::(369, -123, true); test::(0xffffffff, -1, true); test::(0xffffffff, -0xffffffff, true); test::(1000000000000, -1, true); test::(1000000000000, -3, false); test::(1000000000002, -3, true); test::(1000000000000, -123, false); test::(1000000000000, -0xffffffff, false); test::(1000000000000000000000000, -1, true); test::(1000000000000000000000000, -3, false); test::(1000000000000000000000002, -3, true); test::(1000000000000000000000000, -123, false); test::(1000000000000000000000000, -0xffffffff, false); test::(1000000000000000000000000, -1000000000000, true); test::(1000000000000000000000000, -1000000000001, false); test::(-1, 0, false); test::(-1000000000000, 0, false); test::(-1, 1, true); test::(-123, 1, true); test::(-123, 123, true); test::(-123, 456, false); test::(-456, 123, false); test::(-369, 123, true); test::(-0xffffffff, 1, true); test::(-0xffffffff, 0xffffffff, true); test::(-1000000000000, 1, true); test::(-1000000000000, 3, false); test::(-1000000000002, 3, true); test::(-1000000000000, 123, false); test::(-1000000000000, 0xffffffff, false); test::(-1000000000000000000000000, 1, true); test::(-1000000000000000000000000, 3, false); test::(-1000000000000000000000002, 3, true); test::(-1000000000000000000000000, 123, false); test::(-1000000000000000000000000, 0xffffffff, false); test::(-1000000000000000000000000, 1000000000000, true); test::(-1000000000000000000000000, 1000000000001, false); test::(-1, -1, true); test::(-123, -1, true); test::(-123, -123, true); test::(-123, -456, false); test::(-456, -123, false); test::(-369, -123, true); test::(-0xffffffff, -1, true); test::(-0xffffffff, -0xffffffff, true); test::(-1000000000000, -1, true); test::(-1000000000000, -3, false); test::(-1000000000002, -3, true); test::(-1000000000000, -123, false); test::(-1000000000000, -0xffffffff, false); test::(-1000000000000000000000000, -1, true); test::(-1000000000000000000000000, -3, false); test::(-1000000000000000000000002, -3, true); test::(-1000000000000000000000000, -123, false); test::(-1000000000000000000000000, -0xffffffff, false); test::(-1000000000000000000000000, -1000000000000, true); test::(-1000000000000000000000000, -1000000000001, false); } fn divisible_by_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let divisible = x.divisible_by(y); assert_eq!(x == T::ZERO || y != T::ZERO && x % y == T::ZERO, divisible); }); unsigned_pair_gen_var_11::().test_properties(|(x, y)| { assert!(x.divisible_by(y)); assert!(x == T::ZERO || y != T::ZERO && x % y == T::ZERO); }); unsigned_pair_gen_var_13::().test_properties(|(x, y)| { assert!(!x.divisible_by(y)); assert!(x != T::ZERO && (y == T::ZERO || x % y != T::ZERO)); }); unsigned_gen::().test_properties(|n| { assert!(n.divisible_by(T::ONE)); }); unsigned_gen_var_1::().test_properties(|n| { assert!(!n.divisible_by(T::ZERO)); assert!(T::ZERO.divisible_by(n)); if n > T::ONE { assert!(!T::ONE.divisible_by(n)); } assert!(n.divisible_by(n)); }); } fn divisible_by_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let divisible = x.divisible_by(y); assert_eq!( x == T::ZERO || x == T::MIN && y == T::NEGATIVE_ONE || y != T::ZERO && x % y == T::ZERO, divisible ); if x != T::MIN { assert_eq!((-x).divisible_by(y), divisible); } if y != T::MIN { assert_eq!(x.divisible_by(-y), divisible); } }); signed_pair_gen_var_3::().test_properties(|(x, y)| { assert!(x.divisible_by(y)); assert!( x == T::ZERO || x == T::MIN && y == T::NEGATIVE_ONE || y != T::ZERO && x % y == T::ZERO ); }); signed_pair_gen_var_5::().test_properties(|(x, y)| { assert!(!x.divisible_by(y)); assert!( x != T::ZERO && (x != T::MIN || y != T::NEGATIVE_ONE) && (y == T::ZERO || x % y != T::ZERO) ); }); signed_gen::().test_properties(|n| { assert!(n.divisible_by(T::ONE)); assert!(n.divisible_by(T::NEGATIVE_ONE)); }); signed_gen_var_6::().test_properties(|n| { assert!(!n.divisible_by(T::ZERO)); assert!(T::ZERO.divisible_by(n)); if n > T::ONE { assert!(!T::ONE.divisible_by(n)); } assert!(n.divisible_by(n)); }); } #[test] fn divisible_by_properties() { apply_fn_to_unsigneds!(divisible_by_properties_helper_unsigned); apply_fn_to_signeds!(divisible_by_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_8, signed_unsigned_pair_gen_var_9, unsigned_gen, unsigned_pair_gen_var_2, unsigned_pair_gen_var_14, unsigned_pair_gen_var_15, }; fn divisible_by_power_of_2_primitive_helper() { let test = |n: T, pow, out| { assert_eq!(n.divisible_by_power_of_2(pow), out); }; test(T::ZERO, 0, true); test(T::ZERO, 10, true); test(T::ZERO, 100, true); test(T::exact_from(123), 0, true); test(T::exact_from(123), 1, false); if T::WIDTH >= u64::WIDTH { test(T::exact_from(1000000000000u64), 0, true); test(T::exact_from(1000000000000u64), 12, true); test(T::exact_from(1000000000000u64), 13, false); } test(T::MAX, 0, true); test(T::MAX, 1, false); test(T::power_of_2(T::WIDTH >> 1), 0, true); test(T::power_of_2(T::WIDTH >> 1), T::WIDTH >> 1, true); test(T::power_of_2(T::WIDTH >> 1), (T::WIDTH >> 1) + 1, false); } fn divisible_by_power_of_2_signed_helper() { let test = |n: T, pow, out| { assert_eq!(n.divisible_by_power_of_2(pow), out); }; test(T::exact_from(-123), 0, true); test(T::exact_from(-123), 1, false); if T::WIDTH >= u64::WIDTH { test(T::exact_from(-1000000000000i64), 0, true); test(T::exact_from(-1000000000000i64), 12, true); test(T::exact_from(-1000000000000i64), 13, false); } test(T::MIN + T::ONE, 0, true); test(T::MIN + T::ONE, 1, false); test(T::MIN, 0, true); test(T::MIN, T::WIDTH - 1, true); test(T::MIN, T::WIDTH, false); } #[test] fn test_divisible_by_power_of_2() { apply_fn_to_primitive_ints!(divisible_by_power_of_2_primitive_helper); apply_fn_to_signeds!(divisible_by_power_of_2_signed_helper); } fn divisible_by_power_of_2_properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(x, pow)| { let divisible = x.divisible_by_power_of_2(pow); if x != T::ZERO { assert_eq!(x.trailing_zeros() >= pow, divisible); } }); unsigned_pair_gen_var_15::().test_properties(|(x, pow)| { assert!(x.divisible_by_power_of_2(pow)); if x != T::ZERO { assert!(x.trailing_zeros() >= pow); } }); unsigned_pair_gen_var_14::().test_properties(|(x, pow)| { assert!(!x.divisible_by_power_of_2(pow)); if x != T::ZERO { assert!(x.trailing_zeros() < pow); } }); unsigned_gen::().test_properties(|x| { assert!(x.divisible_by_power_of_2(0)); }); unsigned_gen().test_properties(|pow| { assert!(T::ZERO.divisible_by_power_of_2(pow)); }); } fn divisible_by_power_of_2_properties_helper_signed() { signed_unsigned_pair_gen_var_1::().test_properties(|(x, pow)| { let divisible = x.divisible_by_power_of_2(pow); if x != T::ZERO { assert_eq!(x.trailing_zeros() >= pow, divisible); } if x != T::MIN { assert_eq!((-x).divisible_by_power_of_2(pow), divisible); } }); signed_unsigned_pair_gen_var_9::().test_properties(|(x, pow)| { assert!(x.divisible_by_power_of_2(pow)); if x != T::ZERO { assert!(x.trailing_zeros() >= pow); } if x != T::MIN { assert!((-x).divisible_by_power_of_2(pow)); } }); signed_unsigned_pair_gen_var_8::().test_properties(|(x, pow)| { assert!(!x.divisible_by_power_of_2(pow)); if x != T::ZERO { assert!(x.trailing_zeros() < pow); } if x != T::MIN { assert!(!(-x).divisible_by_power_of_2(pow)); } }); signed_gen::().test_properties(|x| { assert!(x.divisible_by_power_of_2(0)); }); unsigned_gen().test_properties(|pow| { assert!(T::ZERO.divisible_by_power_of_2(pow)); }); } #[test] fn divisible_by_power_of_2_properties() { apply_fn_to_unsigneds!(divisible_by_power_of_2_properties_helper_unsigned); apply_fn_to_signeds!(divisible_by_power_of_2_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_pair_gen, signed_quadruple_gen, signed_triple_gen, signed_triple_gen_var_4, signed_triple_gen_var_5, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_10, unsigned_triple_gen_var_7, unsigned_triple_gen_var_8, unsigned_triple_gen_var_19, }; #[test] fn test_eq_mod() { fn test(x: T, y: T, m: T, out: bool) { assert_eq!(x.eq_mod(y, m), out); } test::(0, 0, 0, true); test::(0, 1, 0, false); test::(57, 57, 0, true); test::(57, 58, 0, false); test::(1000000000000, 57, 0, false); test::(0, 256, 256, true); test::(0, 256, 512, false); test::(13, 23, 10, true); test::(13, 24, 10, false); test::(13, 21, 1, true); test::(13, 21, 2, true); test::(13, 21, 4, true); test::(13, 21, 8, true); test::(13, 21, 16, false); test::(13, 21, 3, false); test::(1000000000001, 1, 4096, true); test::(1000000000001, 1, 8192, false); test::(12345678987654321, 321, 1000, true); test::(12345678987654321, 322, 1000, false); test::(1234, 1234, 1000000000000, true); test::(1234, 1235, 1000000000000, false); test::(1000000001234, 1000000002234, 1000, true); test::(1000000001234, 1000000002235, 1000, false); test::(1000000001234, 1234, 1000000000000, true); test::(1000000001234, 1235, 1000000000000, false); test::(1000000001234, 5000000001234, 1000000000000, true); test::(1000000001234, 5000000001235, 1000000000000, false); test::(0, -1, 0, false); test::(57, -57, 0, false); test::(57, -58, 0, false); test::(1000000000000, -57, 0, false); test::(0, -256, 256, true); test::(0, -256, 512, false); test::(13, -27, 10, true); test::(13, -28, 10, false); test::(29, -27, 1, true); test::(29, -27, 2, true); test::(29, -27, 4, true); test::(29, -27, 8, true); test::(29, -27, 16, false); test::(29, -27, 3, false); test::(999999999999, -1, 4096, true); test::(999999999999, -1, 8192, false); test::(12345678987654321, -679, 1000, true); test::(12345678987654321, -680, 1000, false); test::(1000000001234, -999999999766, 1000, true); test::(1000000001234, -999999999767, 1000, false); test::(1000000001234, -999999998766, 1000000000000, true); test::(1000000001234, -999999998767, 1000000000000, false); test::(-57, 57, 0, false); test::(-57, 58, 0, false); test::(-1000000000000, 57, 0, false); test::(-13, 27, 10, true); test::(-13, 28, 10, false); test::(-29, 27, 1, true); test::(-29, 27, 2, true); test::(-29, 27, 4, true); test::(-29, 27, 8, true); test::(-29, 27, 16, false); test::(-29, 27, 3, false); test::(-999999999999, 1, 4096, true); test::(-999999999999, 1, 8192, false); test::(-12345678987654321, 679, 1000, true); test::(-12345678987654321, 680, 1000, false); test::(-1000000001234, 999999999766, 1000, true); test::(-1000000001234, 999999999767, 1000, false); test::(-1000000001234, 999999998766, 1000000000000, true); test::(-1000000001234, 999999998767, 1000000000000, false); test::(-57, -57, 0, true); test::(-57, -58, 0, false); test::(-1000000000000, -57, 0, false); test::(-13, -23, 10, true); test::(-13, -24, 10, false); test::(-13, -21, 1, true); test::(-13, -21, 2, true); test::(-13, -21, 4, true); test::(-13, -21, 8, true); test::(-13, -21, 16, false); test::(-13, -21, 3, false); test::(-1000000000001, -1, 4096, true); test::(-1000000000001, -1, 8192, false); test::(-12345678987654321, -321, 1000, true); test::(-12345678987654321, -322, 1000, false); test::(-1234, -1234, 1000000000000, true); test::(-1234, -1235, 1000000000000, false); test::(-1000000001234, -1000000002234, 1000, true); test::(-1000000001234, -1000000002235, 1000, false); test::(-1000000001234, -1234, 1000000000000, true); test::(-1000000001234, -1235, 1000000000000, false); test::(-1000000001234, -5000000001234, 1000000000000, true); test::(-1000000001234, -5000000001235, 1000000000000, false); test::(0, 256, -256, true); test::(0, 256, -512, false); test::(13, 23, -10, true); test::(13, 24, -10, false); test::(13, 21, -1, true); test::(13, 21, -2, true); test::(13, 21, -4, true); test::(13, 21, -8, true); test::(13, 21, -16, false); test::(13, 21, -3, false); test::(1000000000001, 1, -4096, true); test::(1000000000001, 1, -8192, false); test::(12345678987654321, 321, -1000, true); test::(12345678987654321, 322, -1000, false); test::(1234, 1234, -1000000000000, true); test::(1234, 1235, -1000000000000, false); test::(1000000001234, 1000000002234, -1000, true); test::(1000000001234, 1000000002235, -1000, false); test::(1000000001234, 1234, -1000000000000, true); test::(1000000001234, 1235, -1000000000000, false); test::(1000000001234, 5000000001234, -1000000000000, true); test::(1000000001234, 5000000001235, -1000000000000, false); test::(0, -256, -256, true); test::(0, -256, -512, false); test::(13, -27, -10, true); test::(13, -28, -10, false); test::(29, -27, -1, true); test::(29, -27, -2, true); test::(29, -27, -4, true); test::(29, -27, -8, true); test::(29, -27, -16, false); test::(29, -27, -3, false); test::(999999999999, -1, -4096, true); test::(999999999999, -1, -8192, false); test::(12345678987654321, -679, -1000, true); test::(12345678987654321, -680, -1000, false); test::(1000000001234, -999999999766, -1000, true); test::(1000000001234, -999999999767, -1000, false); test::(1000000001234, -999999998766, -1000000000000, true); test::(1000000001234, -999999998767, -1000000000000, false); test::(-13, 27, -10, true); test::(-13, 28, -10, false); test::(-29, 27, -1, true); test::(-29, 27, -2, true); test::(-29, 27, -4, true); test::(-29, 27, -8, true); test::(-29, 27, -16, false); test::(-29, 27, -3, false); test::(-999999999999, 1, -4096, true); test::(-999999999999, 1, -8192, false); test::(-12345678987654321, 679, -1000, true); test::(-12345678987654321, 680, -1000, false); test::(-1000000001234, 999999999766, -1000, true); test::(-1000000001234, 999999999767, -1000, false); test::(-1000000001234, 999999998766, -1000000000000, true); test::(-1000000001234, 999999998767, -1000000000000, false); test::(-13, -23, -10, true); test::(-13, -24, -10, false); test::(-13, -21, -1, true); test::(-13, -21, -2, true); test::(-13, -21, -4, true); test::(-13, -21, -8, true); test::(-13, -21, -16, false); test::(-13, -21, -3, false); test::(-1000000000001, -1, -4096, true); test::(-1000000000001, -1, -8192, false); test::(-12345678987654321, -321, -1000, true); test::(-12345678987654321, -322, -1000, false); test::(-1234, -1234, -1000000000000, true); test::(-1234, -1235, -1000000000000, false); test::(-1000000001234, -1000000002234, -1000, true); test::(-1000000001234, -1000000002235, -1000, false); test::(-1000000001234, -1234, -1000000000000, true); test::(-1000000001234, -1235, -1000000000000, false); test::(-1000000001234, -5000000001234, -1000000000000, true); test::(-1000000001234, -5000000001235, -1000000000000, false); } fn eq_mod_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, m)| { let equal = x.eq_mod(y, m); assert_eq!(y.eq_mod(x, m), equal); }); unsigned_triple_gen_var_7::().test_properties(|(x, y, m)| { assert!(x.eq_mod(y, m)); assert!(y.eq_mod(x, m)); }); unsigned_triple_gen_var_8::().test_properties(|(x, y, m)| { assert!(!x.eq_mod(y, m)); assert!(!y.eq_mod(x, m)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert!(x.eq_mod(y, T::ONE)); assert_eq!(x.eq_mod(y, T::ZERO), x == y); assert_eq!(x.eq_mod(T::ZERO, y), x.divisible_by(y)); assert!(x.eq_mod(x, y)); }); unsigned_quadruple_gen_var_10::().test_properties(|(x, y, z, m)| { if x.eq_mod(y, m) && y.eq_mod(z, m) { assert!(x.eq_mod(z, m)); } }); } fn eq_mod_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >() { signed_triple_gen::().test_properties(|(x, y, m)| { let equal = x.eq_mod(y, m); assert_eq!(y.eq_mod(x, m), equal); if x != S::MIN && y != S::MIN { assert_eq!((-x).eq_mod(-y, m), equal); } if m != S::MIN { assert_eq!(x.eq_mod(y, -m), equal); } }); signed_triple_gen_var_4::().test_properties(|(x, y, m)| { assert!(x.eq_mod(y, m)); assert!(y.eq_mod(x, m)); }); signed_triple_gen_var_5::().test_properties(|(x, y, m)| { assert!(!x.eq_mod(y, m)); assert!(!y.eq_mod(x, m)); }); signed_pair_gen::().test_properties(|(x, y)| { assert!(x.eq_mod(y, S::ONE)); assert_eq!(x.eq_mod(y, S::ZERO), x == y); assert_eq!(x.eq_mod(S::ZERO, y), x.divisible_by(y)); assert!(x.eq_mod(x, y)); }); signed_quadruple_gen::().test_properties(|(x, y, z, m)| { if x.eq_mod(y, m) && y.eq_mod(z, m) { assert!(x.eq_mod(z, m)); } }); } #[test] fn eq_mod_properties() { apply_fn_to_unsigneds!(eq_mod_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(eq_mod_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_pair_gen, signed_signed_signed_unsigned_quadruple_gen_var_1, signed_signed_unsigned_triple_gen_var_1, signed_signed_unsigned_triple_gen_var_2, signed_signed_unsigned_triple_gen_var_3, signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_2, unsigned_triple_gen_var_4, unsigned_triple_gen_var_9, unsigned_triple_gen_var_10, }; fn eq_mod_power_of_2_primitive_helper() { let test = |n: T, other, pow, out| { assert_eq!(n.eq_mod_power_of_2(other, pow), out); }; test(T::ZERO, T::power_of_2(T::WIDTH >> 1), T::WIDTH >> 1, true); test( T::ZERO, T::power_of_2(T::WIDTH >> 1), (T::WIDTH >> 1) + 1, false, ); test(T::exact_from(13), T::exact_from(21), 0, true); test(T::exact_from(13), T::exact_from(21), 1, true); test(T::exact_from(13), T::exact_from(21), 2, true); test(T::exact_from(13), T::exact_from(21), 3, true); test(T::exact_from(13), T::exact_from(21), 4, false); test(T::exact_from(13), T::exact_from(21), 100, false); test(T::MAX, T::MAX, T::WIDTH, true); test(T::MAX, T::MAX, 100, true); if T::WIDTH >= u64::WIDTH { test(T::exact_from(1000000000001u64), T::ONE, 12, true); test(T::exact_from(1000000000001u64), T::ONE, 13, false); test( T::exact_from(281474976710672u64), T::exact_from(844424930131984u64), 49, true, ); test( T::exact_from(281474976710672u64), T::exact_from(844424930131984u64), 50, false, ); } } fn eq_mod_power_of_2_signed_helper() { let test = |n: T, other, pow, out| { assert_eq!(n.eq_mod_power_of_2(other, pow), out); }; test(T::ZERO, -T::power_of_2(T::WIDTH >> 1), T::WIDTH >> 1, true); test( T::ZERO, -T::power_of_2(T::WIDTH >> 1), (T::WIDTH >> 1) + 1, false, ); test(T::exact_from(-13), T::exact_from(27), 0, true); test(T::exact_from(-13), T::exact_from(27), 1, true); test(T::exact_from(-13), T::exact_from(27), 2, true); test(T::exact_from(-13), T::exact_from(27), 3, true); test(T::exact_from(-13), T::exact_from(27), 4, false); test(T::exact_from(-13), T::exact_from(27), 100, false); test(T::exact_from(13), T::exact_from(-27), 0, true); test(T::exact_from(13), T::exact_from(-27), 1, true); test(T::exact_from(13), T::exact_from(-27), 2, true); test(T::exact_from(13), T::exact_from(-27), 3, true); test(T::exact_from(13), T::exact_from(-27), 4, false); test(T::exact_from(13), T::exact_from(-27), 100, false); test( T::NEGATIVE_ONE, T::power_of_2(T::WIDTH >> 1) - T::ONE, T::WIDTH >> 1, true, ); test( T::power_of_2(T::WIDTH >> 1) - T::ONE, T::NEGATIVE_ONE, T::WIDTH >> 1, true, ); if T::WIDTH >= u64::WIDTH { test( T::exact_from(-1000000000001i64), T::exact_from(4095), 13, true, ); test( T::exact_from(-1000000000001i64), T::exact_from(4095), 14, false, ); test( T::exact_from(1000000000001i64), T::exact_from(-4095), 13, true, ); test( T::exact_from(1000000000001i64), T::exact_from(-4095), 14, false, ); } test(T::exact_from(-13), T::exact_from(-21), 0, true); test(T::exact_from(-13), T::exact_from(-21), 1, true); test(T::exact_from(-13), T::exact_from(-21), 2, true); test(T::exact_from(-13), T::exact_from(-21), 3, true); test(T::exact_from(-13), T::exact_from(-21), 4, false); test(T::exact_from(-13), T::exact_from(-21), 100, false); test( T::power_of_2(T::WIDTH >> 1) - T::ONE, T::power_of_2(T::WIDTH >> 1) - T::ONE, T::WIDTH >> 1, true, ); if T::WIDTH >= u64::WIDTH { test(T::exact_from(-1000000000001i64), T::NEGATIVE_ONE, 12, true); test(T::exact_from(-1000000000001i64), T::NEGATIVE_ONE, 13, false); test( T::exact_from(-281474976710672i64), T::exact_from(-844424930131984i64), 49, true, ); test( T::exact_from(-281474976710672i64), T::exact_from(-844424930131984i64), 50, false, ); } if T::WIDTH >= u128::WIDTH { test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 64, true, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050663395328000i128), 64, false, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 65, false, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 128, false, ); test( T::exact_from(5633680281231555440641310720i128), T::exact_from(-5634717283396403096794955776i128), 80, true, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 64, true, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050663395328000i128), 64, false, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 65, false, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 128, false, ); test( T::exact_from(-5633680281231555440641310720i128), T::exact_from(5634717283396403096794955776i128), 80, true, ); } } #[test] fn test_eq_mod_power_of_2() { apply_fn_to_primitive_ints!(eq_mod_power_of_2_primitive_helper); apply_fn_to_signeds!(eq_mod_power_of_2_signed_helper); } fn eq_mod_power_of_2_properties_helper_unsigned() { unsigned_triple_gen_var_4::().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(y, pow); assert_eq!(y.eq_mod_power_of_2(x, pow), eq_mod_power_of_2); assert_eq!( x.mod_power_of_2(pow) == y.mod_power_of_2(pow), eq_mod_power_of_2 ); }); unsigned_triple_gen_var_9::().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(y, pow)); assert!(y.eq_mod_power_of_2(x, pow)); assert_eq!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); unsigned_triple_gen_var_10::().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(y, pow)); assert!(!y.eq_mod_power_of_2(x, pow)); assert_ne!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(n, pow)); assert_eq!( n.eq_mod_power_of_2(T::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( T::ZERO.eq_mod_power_of_2(n, pow), n.divisible_by_power_of_2(pow) ); }); unsigned_quadruple_gen_var_2::().test_properties(|(x, y, z, pow)| { if x.eq_mod_power_of_2(y, pow) && y.eq_mod_power_of_2(z, pow) { assert!(x.eq_mod_power_of_2(z, pow)); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(y, 0)); }); } fn eq_mod_power_of_2_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { signed_signed_unsigned_triple_gen_var_2::().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(y, pow); assert_eq!(y.eq_mod_power_of_2(x, pow), eq_mod_power_of_2); assert_eq!( U::wrapping_from(x).mod_power_of_2(pow) == U::wrapping_from(y).mod_power_of_2(pow), eq_mod_power_of_2, ); }); signed_signed_unsigned_triple_gen_var_1::().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(y, pow)); assert!(y.eq_mod_power_of_2(x, pow)); assert_eq!( U::wrapping_from(x).mod_power_of_2(pow), U::wrapping_from(y).mod_power_of_2(pow), ); }); signed_signed_unsigned_triple_gen_var_3::().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(y, pow)); assert!(!y.eq_mod_power_of_2(x, pow)); assert_ne!( U::wrapping_from(x).mod_power_of_2(pow), U::wrapping_from(y).mod_power_of_2(pow), ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(n, pow)); assert_eq!( n.eq_mod_power_of_2(S::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( S::ZERO.eq_mod_power_of_2(n, pow), n.divisible_by_power_of_2(pow) ); }); signed_signed_signed_unsigned_quadruple_gen_var_1::().test_properties( |(x, y, z, pow)| { if x.eq_mod_power_of_2(y, pow) && y.eq_mod_power_of_2(z, pow) { assert!(x.eq_mod_power_of_2(z, pow)); } }, ); signed_pair_gen::().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(y, 0)); }); } #[test] fn eq_mod_power_of_2_properties() { apply_fn_to_unsigneds!(eq_mod_power_of_2_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(eq_mod_power_of_2_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::extended_gcd::extended_gcd_unsigned_binary; use malachite_base::num::arithmetic::traits::{ExtendedGcd, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, unsigned_gen, unsigned_pair_gen_var_27, }; use malachite_base::test_util::num::arithmetic::extended_gcd::extended_gcd_unsigned_euclidean; use std::cmp::min; #[test] fn test_extended_gcd() { fn test_u< U: ExtendedGcd + PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >( a: U, b: U, gcd: U, x: S, y: S, ) { assert_eq!(a.extended_gcd(b), (gcd, x, y)); assert_eq!(extended_gcd_unsigned_euclidean(a, b), (gcd, x, y)); assert_eq!(extended_gcd_unsigned_binary::(a, b), (gcd, x, y)); } test_u::(0, 0, 0, 0, 0); test_u::(0, 1, 1, 0, 1); test_u::(1, 0, 1, 1, 0); test_u::(1, 1, 1, 0, 1); test_u::(0, 6, 6, 0, 1); test_u::(6, 0, 6, 1, 0); test_u::(1, 6, 1, 1, 0); test_u::(6, 1, 1, 0, 1); test_u::(6, 6, 6, 0, 1); test_u::(8, 12, 4, -1, 1); test_u::(54, 24, 6, 1, -2); test_u::(42, 56, 14, -1, 1); test_u::(48, 18, 6, -1, 3); test_u::(3, 5, 1, 2, -1); test_u::(12, 60, 12, 1, 0); test_u::(12, 90, 6, -7, 1); test_u::(240, 46, 2, -9, 47); fn test_s + PrimitiveSigned>( a: S, b: S, gcd: U, x: S, y: S, ) { assert_eq!(a.extended_gcd(b), (gcd, x, y)); } test_s::<_, i8>(0, 0, 0, 0, 0); test_s::<_, i8>(0, 1, 1, 0, 1); test_s::<_, i8>(0, -1, 1, 0, -1); test_s::<_, i8>(1, 0, 1, 1, 0); test_s::<_, i8>(-1, 0, 1, -1, 0); test_s::<_, i8>(1, 1, 1, 0, 1); test_s::<_, i8>(1, -1, 1, 0, -1); test_s::<_, i8>(-1, 1, 1, 0, 1); test_s::<_, i8>(-1, -1, 1, 0, -1); test_s::<_, i16>(0, 6, 6, 0, 1); test_s::<_, i16>(0, -6, 6, 0, -1); test_s::<_, i32>(6, 0, 6, 1, 0); test_s::<_, i32>(-6, 0, 6, -1, 0); test_s::<_, i64>(1, 6, 1, 1, 0); test_s::<_, i64>(1, -6, 1, 1, 0); test_s::<_, i64>(-1, 6, 1, -1, 0); test_s::<_, i64>(-1, -6, 1, -1, 0); test_s::<_, isize>(6, 1, 1, 0, 1); test_s::<_, isize>(6, -1, 1, 0, -1); test_s::<_, isize>(-6, 1, 1, 0, 1); test_s::<_, isize>(-6, -1, 1, 0, -1); test_s::<_, i128>(6, 6, 6, 0, 1); test_s::<_, i128>(6, -6, 6, 0, -1); test_s::<_, i128>(-6, 6, 6, 0, 1); test_s::<_, i128>(-6, -6, 6, 0, -1); test_s::<_, i128>(8, 12, 4, -1, 1); test_s::<_, i8>(54, 24, 6, 1, -2); test_s::<_, i16>(42, 56, 14, -1, 1); test_s::<_, i32>(48, 18, 6, -1, 3); test_s::<_, i64>(3, 5, 1, 2, -1); test_s::<_, i128>(12, 90, 6, -7, 1); test_s::<_, i16>(240, 46, 2, -9, 47); test_s::<_, i16>(240, -46, 2, -9, -47); test_s::<_, i16>(-240, 46, 2, 9, 47); test_s::<_, i16>(-240, -46, 2, 9, -47); test_s::<_, i8>(-128, -128, 128, 0, -1); test_s::<_, i8>(0, -128, 128, 0, -1); test_s::<_, i8>(-128, 0, 128, -1, 0); test_s::<_, isize>(12, 60, 12, 1, 0); test_s::<_, isize>(-12, 60, 12, -1, 0); test_s::<_, isize>(12, -60, 12, 1, 0); test_s::<_, isize>(-12, -60, 12, -1, 0); test_s::<_, isize>(60, 12, 12, 0, 1); test_s::<_, isize>(-60, 12, 12, 0, 1); test_s::<_, isize>(60, -12, 12, 0, -1); test_s::<_, isize>(-60, -12, 12, 0, -1); } fn extended_gcd_properties_helper_unsigned< U: ExtendedGcd + PrimitiveUnsigned + WrappingFrom, S: TryFrom + PrimitiveSigned + UnsignedAbs + WrappingFrom, >() { unsigned_pair_gen_var_27::().test_properties(|(a, b)| { let (gcd, x, y) = a.extended_gcd(b); assert_eq!(a.gcd(b), gcd); assert_eq!( S::wrapping_from(a) .wrapping_mul(x) .wrapping_add(S::wrapping_from(b).wrapping_mul(y)), S::wrapping_from(gcd) ); if let (Ok(a), Ok(b), Ok(gcd)) = (S::try_from(a), S::try_from(b), S::try_from(gcd)) && let (Some(ax), Some(by)) = (a.checked_mul(x), b.checked_mul(y)) { assert_eq!(ax + by, gcd); } // uniqueness if a != U::ZERO && b != U::ZERO && gcd != min(a, b) { assert!(x.unsigned_abs() <= (b / gcd) >> 1); assert!(y.unsigned_abs() <= (a / gcd) >> 1); } let reverse = b.extended_gcd(a); if a == b { assert_eq!(reverse, (gcd, x, y)); } else { assert_eq!(reverse, (gcd, y, x)); } assert_eq!(extended_gcd_unsigned_euclidean(a, b), (gcd, x, y)); assert_eq!(extended_gcd_unsigned_binary::(a, b), (gcd, x, y)); }); unsigned_gen::().test_properties(|x| { if x != U::ZERO { assert_eq!(x.extended_gcd(x), (x, S::ZERO, S::ONE)); assert_eq!(x.extended_gcd(U::ZERO), (x, S::ONE, S::ZERO)); assert_eq!(U::ZERO.extended_gcd(x), (x, S::ZERO, S::ONE)); } if x != U::ONE { assert_eq!(U::ONE.extended_gcd(x), (U::ONE, S::ONE, S::ZERO)); } assert_eq!(x.extended_gcd(U::ONE), (U::ONE, S::ZERO, S::ONE)); }); } fn extended_gcd_properties_helper_signed< U: TryFrom + PrimitiveUnsigned, S: ExtendedGcd + PrimitiveSigned + UnsignedAbs, >() { signed_pair_gen::().test_properties(|(a, b)| { let (gcd, x, y) = a.extended_gcd(b); assert!(gcd >= U::ZERO); let abs_a = a.unsigned_abs(); let abs_b = b.unsigned_abs(); assert_eq!(abs_a.gcd(abs_b), gcd); let s_gcd = a.wrapping_mul(x).wrapping_add(b.wrapping_mul(y)); assert_eq!(s_gcd.unsigned_abs(), gcd); if let (Some(ax), Some(by)) = (a.checked_mul(x), b.checked_mul(y)) { assert_eq!(U::exact_from(ax + by), gcd); } // uniqueness if a != S::ZERO && b != S::ZERO && gcd != min(abs_a, abs_b) { assert!(x.unsigned_abs() <= (abs_b / gcd) >> 1); assert!(y.unsigned_abs() <= (abs_a / gcd) >> 1); } let reverse = b.extended_gcd(a); if a == b { assert_eq!(reverse, (gcd, x, y)); } else if b != S::MIN && a == -b { assert_eq!(reverse, (gcd, x, -y)); } else { assert_eq!(reverse, (gcd, y, x)); } }); signed_gen::().test_properties(|x| { if x != S::ZERO { assert_eq!( x.extended_gcd(x), ( x.unsigned_abs(), S::ZERO, if x >= S::ZERO { S::ONE } else { S::NEGATIVE_ONE } ) ); if x != S::MIN { assert_eq!( x.extended_gcd(-x), ( x.unsigned_abs(), S::ZERO, if x < S::ZERO { S::ONE } else { S::NEGATIVE_ONE } ) ); } assert_eq!( x.extended_gcd(S::ZERO), ( x.unsigned_abs(), if x >= S::ZERO { S::ONE } else { S::NEGATIVE_ONE }, S::ZERO ) ); assert_eq!( S::ZERO.extended_gcd(x), ( x.unsigned_abs(), S::ZERO, if x >= S::ZERO { S::ONE } else { S::NEGATIVE_ONE } ) ); } if x.unsigned_abs() != U::ONE { assert_eq!(S::ONE.extended_gcd(x), (U::ONE, S::ONE, S::ZERO)); } assert_eq!(x.extended_gcd(S::ONE), (U::ONE, S::ZERO, S::ONE)); }); } #[test] fn extended_gcd_properties() { apply_fn_to_unsigned_signed_pairs!(extended_gcd_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(extended_gcd_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::factorial::checked_multifactorial_naive; use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_23, unsigned_gen_var_24, unsigned_gen_var_25, unsigned_pair_gen_var_12, unsigned_pair_gen_var_43, }; use malachite_base::test_util::num::arithmetic::factorial::{ checked_double_factorial_naive, checked_factorial_naive, checked_subfactorial_naive, }; use std::panic::catch_unwind; #[test] fn test_factorial() { fn test(n: u64, out: T) { assert_eq!(T::factorial(n), out); } test::(0, 1); test::(1, 1); test::(2, 2); test::(3, 6); test::(4, 24); test::(5, 120); test::(10, 3628800); } fn factorial_fail_helper() { assert_panic!(T::factorial(100)); } #[test] fn factorial_fail() { apply_fn_to_unsigneds!(factorial_fail_helper); } #[test] fn test_checked_factorial() { fn test(n: u64, out: Option) { assert_eq!(T::checked_factorial(n), out); assert_eq!(checked_factorial_naive(n), out); } test::(0, Some(1)); test::(1, Some(1)); test::(2, Some(2)); test::(3, Some(6)); test::(4, Some(24)); test::(5, Some(120)); test::(10, Some(3628800)); test::(6, None); test::(100, None); } #[test] fn test_double_factorial() { fn test(n: u64, out: T) { assert_eq!(T::double_factorial(n), out); } test::(0, 1); test::(1, 1); test::(2, 2); test::(3, 3); test::(4, 8); test::(5, 15); test::(6, 48); test::(7, 105); test::(19, 654729075); test::(20, 3715891200); } fn double_factorial_fail_helper() { assert_panic!(T::double_factorial(100)); } #[test] fn double_factorial_fail() { apply_fn_to_unsigneds!(double_factorial_fail_helper); } #[test] fn test_checked_double_factorial() { fn test(n: u64, out: Option) { assert_eq!(T::checked_double_factorial(n), out); assert_eq!(checked_double_factorial_naive(n), out); } test::(0, Some(1)); test::(1, Some(1)); test::(2, Some(2)); test::(3, Some(3)); test::(4, Some(8)); test::(5, Some(15)); test::(6, Some(48)); test::(7, Some(105)); test::(19, Some(654729075)); test::(20, Some(3715891200)); test::(8, None); test::(100, None); } #[test] fn test_multifactorial() { fn test(n: u64, m: u64, out: T) { assert_eq!(T::multifactorial(n, m), out); } test::(0, 1, 1); test::(1, 1, 1); test::(2, 1, 2); test::(3, 1, 6); test::(4, 1, 24); test::(5, 1, 120); test::(0, 2, 1); test::(1, 2, 1); test::(2, 2, 2); test::(3, 2, 3); test::(4, 2, 8); test::(5, 2, 15); test::(6, 2, 48); test::(7, 2, 105); test::(0, 3, 1); test::(1, 3, 1); test::(2, 3, 2); test::(3, 3, 3); test::(4, 3, 4); test::(5, 3, 10); test::(6, 3, 18); test::(7, 3, 28); test::(8, 3, 80); test::(9, 3, 162); test::(10, 1, 3628800); test::(20, 2, 3715891200); test::(25, 3, 608608000); } fn multifactorial_fail_helper() { assert_panic!(T::multifactorial(1, 0)); assert_panic!(T::multifactorial(100, 1)); } #[test] fn multifactorial_fail() { apply_fn_to_unsigneds!(multifactorial_fail_helper); } #[test] fn test_checked_multifactorial() { fn test(n: u64, m: u64, out: Option) { assert_eq!(T::checked_multifactorial(n, m), out); assert_eq!(checked_multifactorial_naive(n, m), out); } test::(0, 1, Some(1)); test::(1, 1, Some(1)); test::(2, 1, Some(2)); test::(3, 1, Some(6)); test::(4, 1, Some(24)); test::(5, 1, Some(120)); test::(0, 2, Some(1)); test::(1, 2, Some(1)); test::(2, 2, Some(2)); test::(3, 2, Some(3)); test::(4, 2, Some(8)); test::(5, 2, Some(15)); test::(6, 2, Some(48)); test::(7, 2, Some(105)); test::(0, 3, Some(1)); test::(1, 3, Some(1)); test::(2, 3, Some(2)); test::(3, 3, Some(3)); test::(4, 3, Some(4)); test::(5, 3, Some(10)); test::(6, 3, Some(18)); test::(7, 3, Some(28)); test::(8, 3, Some(80)); test::(9, 3, Some(162)); test::(10, 1, Some(3628800)); test::(20, 2, Some(3715891200)); test::(25, 3, Some(608608000)); test::(6, 1, None); test::(8, 2, None); test::(10, 3, None); test::(100, 1, None); test::(100, 2, None); test::(100, 3, None); } fn checked_multifactorial_fail_helper() { assert_panic!(T::checked_multifactorial(1, 0)); } #[test] fn checked_multifactorial_fail() { apply_fn_to_unsigneds!(checked_multifactorial_fail_helper); } #[test] fn test_subfactorial() { fn test(n: u64, out: T) { assert_eq!(T::subfactorial(n), out); } test::(0, 1); test::(1, 0); test::(2, 1); test::(3, 2); test::(4, 9); test::(5, 44); test::(10, 1334961); } fn subfactorial_fail_helper() { assert_panic!(T::subfactorial(100)); } #[test] fn subfactorial_fail() { apply_fn_to_unsigneds!(subfactorial_fail_helper); } #[test] fn test_checked_subfactorial() { fn test(n: u64, out: Option) { assert_eq!(T::checked_subfactorial(n), out); assert_eq!(checked_subfactorial_naive(n), out); } test::(0, Some(1)); test::(1, Some(0)); test::(2, Some(1)); test::(3, Some(2)); test::(4, Some(9)); test::(5, Some(44)); test::(10, Some(1334961)); test::(6, None); test::(100, None); } fn factorial_properties_helper() { unsigned_gen_var_23::().test_properties(|n| { let f = T::factorial(n); assert_eq!(T::checked_factorial(n), Some(f)); assert_eq!(T::multifactorial(n, 1), f); assert_ne!(f, T::ZERO); if n != 0 { assert_eq!(f / T::factorial(n - 1), T::exact_from(n)); } }); } #[test] fn factorial_properties() { apply_fn_to_unsigneds!(factorial_properties_helper); } fn checked_factorial_properties_helper() { unsigned_gen().test_properties(|n| { let of = T::checked_factorial(n); assert_eq!(checked_factorial_naive(n), of); assert_eq!(T::checked_multifactorial(n, 1), of); assert_ne!(of, Some(T::ZERO)); if let Some(f) = of { assert_eq!(T::factorial(n), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_factorial(n + 1).is_none()); } }); } #[test] fn checked_factorial_properties() { apply_fn_to_unsigneds!(checked_factorial_properties_helper); } fn double_factorial_properties_helper() { unsigned_gen_var_24::().test_properties(|n| { let f = T::double_factorial(n); assert_eq!(T::checked_double_factorial(n), Some(f)); assert_eq!(T::multifactorial(n, 2), f); assert_ne!(f, T::ZERO); if n > 1 { assert_eq!(f / T::double_factorial(n - 2), T::exact_from(n)); } }); } #[test] fn double_factorial_properties() { apply_fn_to_unsigneds!(double_factorial_properties_helper); } fn checked_double_factorial_properties_helper() { unsigned_gen().test_properties(|n| { let of = T::checked_double_factorial(n); assert_eq!(checked_double_factorial_naive(n), of); assert_eq!(T::checked_multifactorial(n, 2), of); assert_ne!(of, Some(T::ZERO)); if let Some(f) = of { assert_eq!(T::double_factorial(n), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_double_factorial(n + 1).is_none()); } }); } #[test] fn checked_double_factorial_properties() { apply_fn_to_unsigneds!(checked_double_factorial_properties_helper); } fn multifactorial_properties_helper() { unsigned_pair_gen_var_43::().test_properties(|(n, m)| { let f = T::multifactorial(n, m); assert_eq!(T::checked_multifactorial(n, m), Some(f)); assert_ne!(f, T::ZERO); if n >= m { assert_eq!(f / T::multifactorial(n - m, m), T::exact_from(n)); } }); } #[test] fn multifactorial_properties() { apply_fn_to_unsigneds!(multifactorial_properties_helper); } fn checked_multifactorial_properties_helper() { unsigned_pair_gen_var_12::().test_properties(|(n, m)| { let of = T::checked_multifactorial(n, m); assert_eq!(checked_multifactorial_naive(n, m), of); assert_ne!(of, Some(T::ZERO)); if let Some(f) = of { assert_eq!(T::multifactorial(n, m), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_multifactorial(n + 1, m).is_none()); } }); } #[test] fn checked_multifactorial_properties() { apply_fn_to_unsigneds!(checked_multifactorial_properties_helper); } fn subfactorial_properties_helper() { unsigned_gen_var_25::().test_properties(|n| { let f = T::subfactorial(n); assert_eq!(T::checked_subfactorial(n), Some(f)); if n != 1 { assert_ne!(f, T::ZERO); } if n != 0 && n != 2 { let g = if n.even() { f - T::ONE } else { f + T::ONE }; assert_eq!(g / T::subfactorial(n - 1), T::exact_from(n)); } }); } #[test] fn subfactorial_properties() { apply_fn_to_unsigneds!(subfactorial_properties_helper); } fn checked_subfactorial_properties_helper() { unsigned_gen().test_properties(|n| { let of = T::checked_subfactorial(n); assert_eq!(checked_subfactorial_naive(n), of); if n != 1 { assert_ne!(of, Some(T::ZERO)); } if let Some(f) = of { assert_eq!(T::subfactorial(n), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_subfactorial(n + 1).is_none()); } }); } #[test] fn checked_subfactorial_properties() { apply_fn_to_unsigneds!(checked_subfactorial_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/floor.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; fn floor_assign_primitive_float_helper() { let test = |n: T, out| { assert_eq!(NiceFloat(n.floor()), NiceFloat(out)); let mut n = n; n.floor_assign(); assert_eq!(NiceFloat(n), NiceFloat(out)); }; test(T::ZERO, T::ZERO); test(T::NEGATIVE_ZERO, T::NEGATIVE_ZERO); test(T::INFINITY, T::INFINITY); test(T::NEGATIVE_INFINITY, T::NEGATIVE_INFINITY); test(T::NAN, T::NAN); test(T::ONE, T::ONE); test(T::NEGATIVE_ONE, T::NEGATIVE_ONE); test(T::from(1.5f32), T::from(1.0f32)); test(T::from(-1.5f32), T::from(-2.0f32)); } #[test] fn test_floor_assign() { apply_fn_to_primitive_floats!(floor_assign_primitive_float_helper); } fn floor_assign_properties_helper() { primitive_float_gen::().test_properties(|f| { let mut floor = f; floor.floor_assign(); assert_eq!(NiceFloat(floor), NiceFloat(f.floor())); assert_eq!(NiceFloat(floor.floor()), NiceFloat(floor)); assert_eq!(NiceFloat(-floor), NiceFloat((-f).ceiling())); assert_eq!(f.sign(), floor.sign()); }); } #[test] fn floor_assign_properties() { apply_fn_to_primitive_floats!(floor_assign_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::gcd::{gcd_binary, gcd_euclidean, gcd_fast_a, gcd_fast_b}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_gcd() { fn test(x: T, y: T, out: T) { assert_eq!(x.gcd(y), out); let mut x = x; x.gcd_assign(y); assert_eq!(x, out); } test::(0, 0, 0); test::(0, 6, 6); test::(6, 0, 6); test::(1, 6, 1); test::(6, 1, 1); test::(8, 12, 4); test::(54, 24, 6); test::(42, 56, 14); test::(48, 18, 6); test::(3, 5, 1); test::(12, 60, 12); test::(12, 90, 6); } fn gcd_properties_helper() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let gcd = x.gcd(y); assert_eq!(gcd_euclidean(x, y), gcd); assert_eq!(gcd_binary(x, y), gcd); assert_eq!(gcd_fast_a(x, y), gcd); assert_eq!(gcd_fast_b(x, y), gcd); let mut x_mut = x; x_mut.gcd_assign(y); assert_eq!(x_mut, gcd); assert_eq!(y.gcd(x), gcd); assert!(x.divisible_by(gcd)); assert!(y.divisible_by(gcd)); if gcd != T::ZERO { assert!((x.div_exact(gcd)).coprime_with(y.div_exact(gcd))); } assert_eq!(gcd == T::ZERO, x == T::ZERO && y == T::ZERO); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.gcd(x), x); assert_eq!(x.gcd(T::ONE), T::ONE); assert_eq!(x.gcd(T::ZERO), x); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert_eq!(x.gcd(y).gcd(z), x.gcd(y.gcd(z))); }); } #[test] fn gcd_properties() { apply_fn_to_unsigneds!(gcd_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::test_util::generators::primitive_float_gen; fn is_power_of_2_helper() { let test = |n: T, out| { assert_eq!(n.is_power_of_2(), out); }; test(T::ZERO, false); test(T::NEGATIVE_ZERO, false); test(T::INFINITY, false); test(T::NEGATIVE_INFINITY, false); test(T::NAN, false); test(T::NEGATIVE_ONE, false); test(T::from(1.5f32), false); test(T::from(-1.5f32), false); test(T::ONE, true); test(T::TWO, true); test(T::from(4.0f32), true); test(T::from(0.5f32), true); test(T::from(0.25f32), true); } #[test] fn test_is_power_of_2() { apply_fn_to_primitive_floats!(is_power_of_2_helper); } fn is_power_of_2_properties_helper() { primitive_float_gen::().test_properties(|f| { if f.is_power_of_2() { assert_eq!(f.precision(), 1); assert_eq!(T::power_of_2(f.checked_log_base_2().unwrap()), f); } }); } #[test] fn is_power_of_2_properties() { apply_fn_to_primitive_floats!(is_power_of_2_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::kronecker_symbol::{ jacobi_symbol_unsigned_double_fast_2, jacobi_symbol_unsigned_simple, }; use malachite_base::num::arithmetic::traits::{ModPowerOf2, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, WrappingFrom}; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_13, signed_pair_gen, signed_pair_gen_var_8, signed_pair_gen_var_9, signed_pair_gen_var_10, signed_triple_gen, signed_triple_gen_var_6, signed_triple_gen_var_7, unsigned_gen, unsigned_gen_var_22, unsigned_pair_gen_var_27, unsigned_pair_gen_var_40, unsigned_pair_gen_var_41, unsigned_pair_gen_var_42, unsigned_quadruple_gen_var_12, unsigned_triple_gen_var_19, unsigned_triple_gen_var_22, unsigned_triple_gen_var_23, }; use malachite_base::test_util::num::arithmetic::kronecker_symbol::{ jacobi_symbol_unsigned_double_fast_1, jacobi_symbol_unsigned_double_simple, jacobi_symbol_unsigned_fast_1, jacobi_symbol_unsigned_fast_2_1, jacobi_symbol_unsigned_fast_2_2, jacobi_symbol_unsigned_fast_2_3, jacobi_symbol_unsigned_fast_2_4, }; use std::panic::catch_unwind; #[test] fn test_jacobi_symbol() { fn test_u(a: T, n: T, s: i8) { assert_eq!(a.legendre_symbol(n), s); assert_eq!(a.jacobi_symbol(n), s); assert_eq!(a.kronecker_symbol(n), s); assert_eq!(jacobi_symbol_unsigned_simple(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_1(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_1(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_2(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_3(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_4(a, n), s); } test_u::(0, 1, 1); test_u::(0, 3, 0); test_u::(1, 3, 1); test_u::(2, 3, -1); test_u::(0, 5, 0); test_u::(1, 5, 1); test_u::(2, 5, -1); test_u::(3, 5, -1); test_u::(4, 5, 1); test_u::(0, 7, 0); test_u::(1, 7, 1); test_u::(2, 7, 1); test_u::(3, 7, -1); test_u::(4, 7, 1); test_u::(5, 7, -1); test_u::(6, 7, -1); test_u::(0, 9, 0); test_u::(1, 9, 1); test_u::(2, 9, 1); test_u::(3, 9, 0); test_u::(4, 9, 1); test_u::(5, 9, 1); test_u::(6, 9, 0); test_u::(7, 9, 1); test_u::(8, 9, 1); test_u::(7, 7, 0); test_u::(8, 7, 1); test_u::(9, 7, 1); test_u::(10, 7, -1); test_u::(11, 7, 1); test_u::(12, 7, -1); test_u::(13, 7, -1); test_u::(9, 9, 0); test_u::(10, 9, 1); test_u::(11, 9, 1); test_u::(12, 9, 0); test_u::(13, 9, 1); test_u::(14, 9, 1); test_u::(15, 9, 0); test_u::(16, 9, 1); test_u::(17, 9, 1); test_u::(1001, 9907, -1); test_u::(10908, 9907, -1); fn test_s + PrimitiveSigned>( a: S, n: S, s: i8, ) { assert_eq!(a.legendre_symbol(n), s); assert_eq!(a.jacobi_symbol(n), s); assert_eq!(a.kronecker_symbol(n), s); } test_s::(0, 1, 1); test_s::(0, 3, 0); test_s::(1, 3, 1); test_s::(2, 3, -1); test_s::(0, 5, 0); test_s::(1, 5, 1); test_s::(2, 5, -1); test_s::(3, 5, -1); test_s::(4, 5, 1); test_s::(0, 7, 0); test_s::(1, 7, 1); test_s::(2, 7, 1); test_s::(3, 7, -1); test_s::(4, 7, 1); test_s::(5, 7, -1); test_s::(6, 7, -1); test_s::(0, 9, 0); test_s::(1, 9, 1); test_s::(2, 9, 1); test_s::(3, 9, 0); test_s::(4, 9, 1); test_s::(5, 9, 1); test_s::(6, 9, 0); test_s::(7, 9, 1); test_s::(8, 9, 1); test_s::(7, 7, 0); test_s::(8, 7, 1); test_s::(9, 7, 1); test_s::(10, 7, -1); test_s::(11, 7, 1); test_s::(12, 7, -1); test_s::(13, 7, -1); test_s::(9, 9, 0); test_s::(10, 9, 1); test_s::(11, 9, 1); test_s::(12, 9, 0); test_s::(13, 9, 1); test_s::(14, 9, 1); test_s::(15, 9, 0); test_s::(16, 9, 1); test_s::(17, 9, 1); test_s::(-7, 7, 0); test_s::(-6, 7, 1); test_s::(-5, 7, 1); test_s::(-4, 7, -1); test_s::(-3, 7, 1); test_s::(-2, 7, -1); test_s::(-1, 7, -1); test_s::(-9, 9, 0); test_s::(-8, 9, 1); test_s::(-7, 9, 1); test_s::(-6, 9, 0); test_s::(-5, 9, 1); test_s::(-4, 9, 1); test_s::(-3, 9, 0); test_s::(-2, 9, 1); test_s::(-1, 9, 1); test_s::(1001, 9907, -1); test_s::(10908, 9907, -1); test_s::(-8906, 9907, -1); } fn jacobi_symbol_fail_helper() { assert_panic!(T::ONE.jacobi_symbol(T::TWO)); } fn jacobi_symbol_fail_helper_signed() { assert_panic!(T::ONE.jacobi_symbol(T::NEGATIVE_ONE)); } #[test] fn jacobi_symbol_fail() { apply_fn_to_primitive_ints!(jacobi_symbol_fail_helper); apply_fn_to_signeds!(jacobi_symbol_fail_helper_signed); } #[test] fn test_jacobi_symbol_unsigned_double() { fn test + JoinHalves + PrimitiveUnsigned>( x_1: T, x_0: T, y_1: T, y_0: T, s: i8, ) { assert_eq!( jacobi_symbol_unsigned_double_simple::(x_1, x_0, y_1, y_0), s ); assert_eq!(jacobi_symbol_unsigned_double_fast_1(x_1, x_0, y_1, y_0), s); assert_eq!(jacobi_symbol_unsigned_double_fast_2(x_1, x_0, y_1, y_0), s); } // - fast_1: y_1 == T::ZERO || y_0 == T::ZERO first time // - fast_2: y_1 == T::ZERO && y_0 == T::ONE test::(0, 0, 0, 1, 1); // - fast_1: y_1 != T::ZERO && y_0 != T::ZERO first time // - fast_1: x_1 != T::ZERO && x_0 != T::ZERO // - fast_1: x_0 != T::ZERO first time // - fast_1: c != T::WIDTH first time // - fast_1: diff_0 != T::ZERO && diff_1 != T::ZERO // - fast_1: diff_1.get_highest_bit() // - fast_1: y_1 != T::ZERO && y_0 != T::ZERO second time // - fast_1: x_0 == T::ZERO second time // - fast_1: c != T::WIDTH second time // - fast_1: bit.even() // - fast_2: y_1 != T::ZERO || y_0 != T::ONE // - fast_2: x_0 != T::ZERO first time // - fast_2: x_0.odd() // - fast_2: x_1 == T::ZERO second time // - fast_2: y_1 != T::ZERO // - fast_2: skip_loop // - fast_2: y_0 != T::ONE second time // - fast_2: x_0 == T::ZERO fourth time // - fast_2: x_1 != T::ZERO fourth time // - fast_2: !bit.get_bit(1) test::(0, 3, 2, 3, 1); // - fast_1: x_1 == T::ZERO || x_0 == T::ZERO // - fast_2: x_0 == T::ZERO first time // - fast_2: x_1 == T::ZERO first time test::(0, 0, 0, 3, 0); // - fast_1: t != T::ZERO // - fast_1: c == T::WIDTH third time // - fast_2: y_0 == T::ONE second time test::(0, 1, 1, 1, 1); // - fast_1: c != T::WIDTH third time test::(0, 1, 1, 3, 1); // - fast_1: x_0 == T::ZERO first time // - fast_2: x_1 != T::ZERO first time // - fast_2: y_0 == T::ONE first time test::(1, 0, 0, 3, 1); // - fast_1: bit.odd() // - fast_2: x_1 != T::ZERO second time // - fast_2: !skip_loop // - fast_2: x_0 != T::ZERO fourth time // - fast_2: bit.get_bit(1) test::(1, 1, 0, 3, -1); // - fast_1: t == T::ZERO // - fast_2: x_1 == y_1 first time // - fast_2: x_1 == y_1 second time // - fast_2: x_0 >= y_0 // - fast_2: x_0 == T::ZERO third time test::(1, 1, 1, 1, 0); // - fast_1: y_1 == T::ZERO || y_0 == T::ZERO second time test::(0, 1, 2, 1, 1); // - fast_1: x_0 != T::ZERO second time // - fast_1: c == T::WIDTH second time // - fast_2: x_1 != y_1 first time // - fast_2: x_1 != T::ZERO third time // - fast_2: y_0 == T::ZERO test::(1, 1, 2, 1, 1); // - fast_1: !diff_1.get_highest_bit() test::(2, 1, 0, 3, 0); // - fast_1: diff_0 == T::ZERO || diff_1 == T::ZERO test::(2, 1, 2, 1, 0); // - fast_1: c == T::WIDTH first time // - fast_2: x_0.even() // - fast_2: y_0 != T::ZERO test::(242, 128, 173, 173, -1); // - fast_2: y_1 == T::ZERO test::(0, 1, 0, 3, 1); // - fast_2: x_0 < y_0 // - fast_2: x_0 != T::ZERO third time // - fast_2: x_0 == T::ONE test::(1, 1, 1, 3, 1); // - fast_2: x_0 != T::ONE test::(1, 1, 1, 7, -1); // - fast_2: x_1 != y_1 second time test::(1, 1, 2, 3, 1); // - fast_2: x_0 == T::ZERO second time test::(2, 1, 1, 1, 1); // - fast_2: x_0 != T::ZERO second time // - fast_2: x_1 == T::ZERO third time test::(2, 1, 1, 3, -1); // - fast_2: y_0 != T::ONE first time test::(3, 0, 0, 3, 0); } // Odd n is already tested in test_jacobi_symbol, so here we just test even n #[test] fn test_kronecker_symbol() { fn test_u(a: T, n: T, s: i8) { assert_eq!(a.kronecker_symbol(n), s); } test_u::(0, 2, 0); test_u::(1, 2, 1); test_u::(2, 2, 0); test_u::(3, 2, -1); test_u::(4, 2, 0); test_u::(5, 2, -1); test_u::(6, 2, 0); test_u::(7, 2, 1); test_u::(0, 4, 0); test_u::(1, 4, 1); test_u::(2, 4, 0); test_u::(3, 4, 1); test_u::(0, 6, 0); test_u::(1, 6, 1); test_u::(2, 6, 0); test_u::(3, 6, 0); test_u::(4, 6, 0); test_u::(5, 6, 1); test_u::(6, 6, 0); test_u::(7, 6, 1); test_u::(8, 6, 0); test_u::(9, 6, 0); test_u::(10, 6, 0); test_u::(11, 6, 1); test_u::(12, 6, 0); test_u::(13, 6, -1); test_u::(14, 6, 0); test_u::(15, 6, 0); test_u::(16, 6, 0); test_u::(17, 6, -1); test_u::(18, 6, 0); test_u::(19, 6, -1); test_u::(20, 6, 0); test_u::(21, 6, 0); test_u::(22, 6, 0); test_u::(23, 6, -1); test_u::(1001, 9908, -1); test_u::(10909, 9908, -1); fn test_s + PrimitiveSigned>( a: S, n: S, s: i8, ) { assert_eq!(a.kronecker_symbol(n), s); } test_s::(0, 2, 0); test_s::(1, 2, 1); test_s::(2, 2, 0); test_s::(3, 2, -1); test_s::(4, 2, 0); test_s::(5, 2, -1); test_s::(6, 2, 0); test_s::(7, 2, 1); test_s::(0, 4, 0); test_s::(1, 4, 1); test_s::(2, 4, 0); test_s::(3, 4, 1); test_s::(0, 6, 0); test_s::(1, 6, 1); test_s::(2, 6, 0); test_s::(3, 6, 0); test_s::(4, 6, 0); test_s::(5, 6, 1); test_s::(6, 6, 0); test_s::(7, 6, 1); test_s::(8, 6, 0); test_s::(9, 6, 0); test_s::(10, 6, 0); test_s::(11, 6, 1); test_s::(12, 6, 0); test_s::(13, 6, -1); test_s::(14, 6, 0); test_s::(15, 6, 0); test_s::(16, 6, 0); test_s::(17, 6, -1); test_s::(18, 6, 0); test_s::(19, 6, -1); test_s::(20, 6, 0); test_s::(21, 6, 0); test_s::(22, 6, 0); test_s::(23, 6, -1); test_s::(-1, 2, 1); test_s::(-2, 2, 0); test_s::(-3, 2, -1); test_s::(-4, 2, 0); test_s::(-5, 2, -1); test_s::(-6, 2, 0); test_s::(-7, 2, 1); test_s::(-1, 4, 1); test_s::(-2, 4, 0); test_s::(-3, 4, 1); test_s::(-1, 6, -1); test_s::(-2, 6, 0); test_s::(-3, 6, 0); test_s::(-4, 6, 0); test_s::(-5, 6, -1); test_s::(-6, 6, 0); test_s::(-7, 6, -1); test_s::(-8, 6, 0); test_s::(-9, 6, 0); test_s::(-10, 6, 0); test_s::(-11, 6, -1); test_s::(-12, 6, 0); test_s::(-13, 6, 1); test_s::(-14, 6, 0); test_s::(-15, 6, 0); test_s::(-16, 6, 0); test_s::(-17, 6, 1); test_s::(-18, 6, 0); test_s::(-19, 6, 1); test_s::(-20, 6, 0); test_s::(-21, 6, 0); test_s::(-22, 6, 0); test_s::(-23, 6, 1); test_s::(0, -2, 0); test_s::(1, -2, 1); test_s::(2, -2, 0); test_s::(3, -2, -1); test_s::(4, -2, 0); test_s::(5, -2, -1); test_s::(6, -2, 0); test_s::(7, -2, 1); test_s::(0, -4, 0); test_s::(1, -4, 1); test_s::(2, -4, 0); test_s::(3, -4, 1); test_s::(0, -6, 0); test_s::(1, -6, 1); test_s::(2, -6, 0); test_s::(3, -6, 0); test_s::(4, -6, 0); test_s::(5, -6, 1); test_s::(6, -6, 0); test_s::(7, -6, 1); test_s::(8, -6, 0); test_s::(9, -6, 0); test_s::(10, -6, 0); test_s::(11, -6, 1); test_s::(12, -6, 0); test_s::(13, -6, -1); test_s::(14, -6, 0); test_s::(15, -6, 0); test_s::(16, -6, 0); test_s::(17, -6, -1); test_s::(18, -6, 0); test_s::(19, -6, -1); test_s::(20, -6, 0); test_s::(21, -6, 0); test_s::(22, -6, 0); test_s::(23, -6, -1); test_s::(-1, -2, -1); test_s::(-2, -2, 0); test_s::(-3, -2, 1); test_s::(-4, -2, 0); test_s::(-5, -2, 1); test_s::(-6, -2, 0); test_s::(-7, -2, -1); test_s::(-1, -4, -1); test_s::(-2, -4, 0); test_s::(-3, -4, -1); test_s::(-1, -6, 1); test_s::(-2, -6, 0); test_s::(-3, -6, 0); test_s::(-4, -6, 0); test_s::(-5, -6, 1); test_s::(-6, -6, 0); test_s::(-7, -6, 1); test_s::(-8, -6, 0); test_s::(-9, -6, 0); test_s::(-10, -6, 0); test_s::(-11, -6, 1); test_s::(-12, -6, 0); test_s::(-13, -6, -1); test_s::(-14, -6, 0); test_s::(-15, -6, 0); test_s::(-16, -6, 0); test_s::(-17, -6, -1); test_s::(-18, -6, 0); test_s::(-19, -6, -1); test_s::(-20, -6, 0); test_s::(-21, -6, 0); test_s::(-22, -6, 0); test_s::(-23, -6, -1); test_s::(1001, -9908, -1); test_s::(10909, -9908, -1); test_s::(-8907, -9908, 1); } fn jacobi_symbol_properties_helper_unsigned() { unsigned_pair_gen_var_40::().test_properties(|(a, n)| { let s = a.jacobi_symbol(n); assert_eq!(a.legendre_symbol(n), s); assert_eq!(a.kronecker_symbol(n), s); assert_eq!(jacobi_symbol_unsigned_simple(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_1(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_1(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_2(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_3(a, n), s); assert_eq!(jacobi_symbol_unsigned_fast_2_4(a, n), s); assert!(s.le_abs(&1i8)); if let Some(b) = a.checked_add(n) { assert_eq!(b.jacobi_symbol(n), s); } if let Some(b) = a.checked_sub(n) { assert_eq!(b.jacobi_symbol(n), s); } assert_eq!(s != 0, a.coprime_with(n)); if let Some(b) = a.checked_mul(T::TWO) { let n_mod_8: u8 = n.mod_power_of_2(3).wrapping_into(); assert_eq!( b.jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { s } else { -s } ); } }); unsigned_pair_gen_var_41::().test_properties(|(m, n)| { let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); let m_mod_4: u8 = m.mod_power_of_2(2).wrapping_into(); assert_eq!( m.jacobi_symbol(n) * n.jacobi_symbol(m), if n_mod_4 == 1 || m_mod_4 == 1 { 1 } else { -1 } ); }); unsigned_triple_gen_var_22::().test_properties(|(a, b, n)| { if let Some(c) = a.checked_mul(b) { assert_eq!(c.jacobi_symbol(n), a.jacobi_symbol(n) * b.jacobi_symbol(n)); } }); unsigned_triple_gen_var_23::().test_properties(|(a, m, n)| { if let Some(o) = m.checked_mul(n) { assert_eq!(a.jacobi_symbol(o), a.jacobi_symbol(m) * a.jacobi_symbol(n)); } }); unsigned_gen_var_22::().test_properties(|n| { if n != T::ONE { assert_eq!(T::ZERO.jacobi_symbol(n), 0); assert_eq!(n.jacobi_symbol(n), 0); } assert_eq!(T::ONE.jacobi_symbol(n), 1); assert_eq!(n.jacobi_symbol(T::ONE), 1); let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); assert_eq!( (n - T::ONE).jacobi_symbol(n), if n_mod_4 == 1 { 1 } else { -1 } ); let n_mod_8: u8 = n.mod_power_of_2(3).wrapping_into(); assert_eq!( T::TWO.jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { 1 } else { -1 } ); }); } fn jacobi_symbol_properties_double_helper_unsigned< T: PrimitiveUnsigned, D: HasHalf + JoinHalves + PrimitiveUnsigned, >() { unsigned_quadruple_gen_var_12::().test_properties(|(x_1, x_0, y_1, y_0)| { let s = jacobi_symbol_unsigned_double_simple::(x_1, x_0, y_1, y_0); assert_eq!(jacobi_symbol_unsigned_double_fast_1(x_1, x_0, y_1, y_0), s); assert_eq!(jacobi_symbol_unsigned_double_fast_2(x_1, x_0, y_1, y_0), s); }); } fn jacobi_symbol_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: ModPowerOf2 + PrimitiveSigned + UnsignedAbs + WrappingFrom, >() { signed_pair_gen_var_8::().test_properties(|(a, n)| { let s = a.jacobi_symbol(n); assert_eq!(a.legendre_symbol(n), s); assert_eq!(a.kronecker_symbol(n), s); assert!(s.le_abs(&1i8)); if let Some(b) = a.checked_add(n) { assert_eq!(b.jacobi_symbol(n), s); } if let Some(b) = a.checked_sub(n) { assert_eq!(b.jacobi_symbol(n), s); } assert_eq!(s != 0, a.unsigned_abs().coprime_with(n.unsigned_abs())); if let Some(b) = a.checked_mul(S::TWO) { let n_mod_8: u8 = n.mod_power_of_2(3).wrapping_into(); assert_eq!( b.jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { s } else { -s } ); } if let Some(b) = a.checked_neg() { let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); assert_eq!(b.jacobi_symbol(n), if n_mod_4 == 1 { s } else { -s }); } }); signed_pair_gen_var_9::().test_properties(|(m, n)| { let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); let m_mod_4: u8 = m.mod_power_of_2(2).wrapping_into(); assert_eq!( m.jacobi_symbol(n) * n.jacobi_symbol(m), if n_mod_4 == 1 || m_mod_4 == 1 { 1 } else { -1 } ); }); signed_triple_gen_var_6::().test_properties(|(a, b, n)| { if let Some(c) = a.checked_mul(b) { assert_eq!(c.jacobi_symbol(n), a.jacobi_symbol(n) * b.jacobi_symbol(n)); } }); signed_triple_gen_var_7::().test_properties(|(a, m, n)| { if let Some(o) = m.checked_mul(n) { assert_eq!(a.jacobi_symbol(o), a.jacobi_symbol(m) * a.jacobi_symbol(n)); } }); signed_gen_var_13::().test_properties(|n| { if n != S::ONE { assert_eq!(S::ZERO.jacobi_symbol(n), 0); assert_eq!(n.jacobi_symbol(n), 0); } assert_eq!(S::ONE.jacobi_symbol(n), 1); assert_eq!(n.jacobi_symbol(S::ONE), 1); let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); assert_eq!( S::NEGATIVE_ONE.jacobi_symbol(n), if n_mod_4 == 1 { 1 } else { -1 } ); let n_mod_8: u8 = n.mod_power_of_2(3).wrapping_into(); assert_eq!( S::TWO.jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { 1 } else { -1 } ); }); } #[test] fn jacobi_symbol_properties() { apply_fn_to_unsigneds!(jacobi_symbol_properties_helper_unsigned); jacobi_symbol_properties_double_helper_unsigned::(); jacobi_symbol_properties_double_helper_unsigned::(); jacobi_symbol_properties_double_helper_unsigned::(); jacobi_symbol_properties_double_helper_unsigned::(); apply_fn_to_unsigned_signed_pairs!(jacobi_symbol_properties_helper_signed); } fn kronecker_symbol_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(a, n)| { let s = a.kronecker_symbol(n); assert!(s.le_abs(&1i8)); assert_eq!(s != 0, a.coprime_with(n)); let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); if n_mod_4 == 2 { if let Some(four_n) = n.checked_mul(T::from(4u8)) { if let Some(b) = a.checked_add(four_n) { assert_eq!(b.kronecker_symbol(n), s); } if let Some(b) = a.checked_sub(four_n) { assert_eq!(b.kronecker_symbol(n), s); } } } else { if let Some(b) = a.checked_add(n) { assert_eq!(b.kronecker_symbol(n), s); } if let Some(b) = a.checked_sub(n) { assert_eq!(b.kronecker_symbol(n), s); } } let a_mod_4: u8 = a.mod_power_of_2(2).wrapping_into(); if a != T::ZERO && a_mod_4 != 3 { if a_mod_4 == 2 { if let Some(four_a) = a.checked_mul(T::from(4u8)) { if let Some(m) = n.checked_add(four_a) { assert_eq!(a.kronecker_symbol(m), s); } if let Some(m) = n.checked_sub(four_a) { assert_eq!(a.kronecker_symbol(m), s); } } } else { if let Some(m) = n.checked_add(a) { assert_eq!(a.kronecker_symbol(m), s); } if let Some(m) = n.checked_sub(a) { assert_eq!(a.kronecker_symbol(m), s); } } } }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { if let Some(p) = x.checked_mul(y) { assert_eq!( p.kronecker_symbol(z), x.kronecker_symbol(z) * y.kronecker_symbol(z) ); } if let Some(p) = y.checked_mul(z) { assert_eq!( x.kronecker_symbol(p), x.kronecker_symbol(y) * x.kronecker_symbol(z) ); } }); unsigned_pair_gen_var_42::().test_properties(|(m, n)| { let n_odd = if n == T::ZERO { T::ONE } else { n >> n.trailing_zeros() }; let m_odd = if m == T::ZERO { T::ONE } else { m >> m.trailing_zeros() }; let n_odd_mod_4: u8 = n_odd.mod_power_of_2(2).wrapping_into(); let m_odd_mod_4: u8 = m_odd.mod_power_of_2(2).wrapping_into(); let p = if n_odd_mod_4 == 1 || m_odd_mod_4 == 1 { 1 } else { -1 }; assert_eq!(m.kronecker_symbol(n) * n.kronecker_symbol(m), p); }); unsigned_gen().test_properties(|n| { if n != T::ONE { assert_eq!(T::ZERO.kronecker_symbol(n), 0); assert_eq!(n.kronecker_symbol(n), 0); } assert_eq!(T::ONE.kronecker_symbol(n), 1); assert_eq!(n.kronecker_symbol(T::ONE), 1); }); } fn kronecker_symbol_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: ModPowerOf2 + PrimitiveSigned + UnsignedAbs + WrappingFrom, >() { signed_pair_gen::().test_properties(|(a, n)| { let s = a.kronecker_symbol(n); assert!(s.le_abs(&1i8)); assert_eq!(s != 0, a.unsigned_abs().coprime_with(n.unsigned_abs())); let n_mod_4: u8 = n.mod_power_of_2(2).wrapping_into(); if n_mod_4 == 2 { if let Some(four_n) = n.checked_mul(S::from(4i8)) { if let Some(b) = a.checked_add(four_n) && (n > S::ZERO || a.sign() == b.sign()) { assert_eq!(b.kronecker_symbol(n), s); } if let Some(b) = a.checked_sub(four_n) && (n > S::ZERO || a.sign() == b.sign()) { assert_eq!(b.kronecker_symbol(n), s); } } } else { if let Some(b) = a.checked_add(n) && (n > S::ZERO || a.sign() == b.sign()) { assert_eq!(b.kronecker_symbol(n), s); } if let Some(b) = a.checked_sub(n) && (n > S::ZERO || a.sign() == b.sign()) { assert_eq!(b.kronecker_symbol(n), s); } } let a_mod_4: u8 = a.mod_power_of_2(2).wrapping_into(); if a != S::ZERO && a_mod_4 != 3 && let Some(abs_a) = a.checked_abs() { if a_mod_4 == 2 { if let Some(four_abs_a) = abs_a.checked_mul(S::from(4i8)) { if let Some(m) = n.checked_add(four_abs_a) { assert_eq!(a.kronecker_symbol(m), s); } if let Some(m) = n.checked_sub(four_abs_a) { assert_eq!(a.kronecker_symbol(m), s); } } } else { if let Some(m) = n.checked_add(abs_a) { assert_eq!(a.kronecker_symbol(m), s); } if let Some(m) = n.checked_sub(abs_a) { assert_eq!(a.kronecker_symbol(m), s); } } } let m = a; if let Some(m_abs) = m.checked_abs() { let m_odd = if m == S::ZERO { S::ONE } else { m >> m.trailing_zeros() }; let m_odd_mod_4: u8 = m_odd.mod_power_of_2(2).wrapping_into(); // -m won't overflow since m.checked_abs() is Some let m_star = if m_odd_mod_4 == 1 { m } else { -m }; assert_eq!(m_star.kronecker_symbol(n), n.kronecker_symbol(m_abs)); } }); signed_triple_gen::().test_properties(|(x, y, z)| { if !(z == S::NEGATIVE_ONE && (x == S::ZERO && y < S::ZERO || x < S::ZERO && y == S::ZERO)) && let Some(p) = x.checked_mul(y) { assert_eq!( p.kronecker_symbol(z), x.kronecker_symbol(z) * y.kronecker_symbol(z) ); } let y_odd_mod_4: u8 = if y == S::ZERO { 0 } else { (y >> y.trailing_zeros()).mod_power_of_2(2).wrapping_into() }; let z_odd_mod_4: u8 = if z == S::ZERO { 0 } else { (z >> z.trailing_zeros()).mod_power_of_2(2).wrapping_into() }; if !(x == S::NEGATIVE_ONE && (y == S::ZERO && z_odd_mod_4 == 3 || y_odd_mod_4 == 3 && z == S::ZERO)) && let Some(p) = y.checked_mul(z) { assert_eq!( x.kronecker_symbol(p), x.kronecker_symbol(y) * x.kronecker_symbol(z) ); } }); signed_pair_gen_var_10::().test_properties(|(m, n)| { let n_odd = if n == S::ZERO { S::ONE } else { n >> n.trailing_zeros() }; let m_odd = if m == S::ZERO { S::ONE } else { m >> m.trailing_zeros() }; let n_odd_mod_4: u8 = n_odd.mod_power_of_2(2).wrapping_into(); let m_odd_mod_4: u8 = m_odd.mod_power_of_2(2).wrapping_into(); let p = if n_odd_mod_4 == 1 || m_odd_mod_4 == 1 { 1 } else { -1 }; assert_eq!( m.kronecker_symbol(n) * n.kronecker_symbol(m), if m < S::ZERO && n < S::ZERO { -p } else { p } ); if let Some(m_abs) = m.checked_abs() { assert_eq!(m.kronecker_symbol(n) * n.kronecker_symbol(m_abs), p); } }); signed_gen().test_properties(|n| { if n != S::ONE && n != S::NEGATIVE_ONE { assert_eq!(S::ZERO.kronecker_symbol(n), 0); assert_eq!(n.kronecker_symbol(n), 0); } assert_eq!(S::ONE.kronecker_symbol(n), 1); assert_eq!(n.kronecker_symbol(S::ONE), 1); let n_odd = if n == S::ZERO { S::ONE } else { n >> n.trailing_zeros() }; let n_odd_mod_4: u8 = n_odd.mod_power_of_2(2).wrapping_into(); assert_eq!( S::NEGATIVE_ONE.kronecker_symbol(n), if n_odd_mod_4 == 1 { 1 } else { -1 } ); assert_eq!( n.kronecker_symbol(S::NEGATIVE_ONE), if n >= S::ZERO { 1 } else { -1 } ); }); } #[test] fn kronecker_symbol_properties() { apply_fn_to_unsigneds!(kronecker_symbol_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(kronecker_symbol_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_33, unsigned_pair_gen_var_34, unsigned_triple_gen_var_19, }; use std::panic::catch_unwind; #[test] fn test_lcm() { fn test(x: T, y: T, out: T) { assert_eq!(x.lcm(y), out); let mut x = x; x.lcm_assign(y); assert_eq!(x, out); } test::(0, 0, 0); test::(0, 6, 0); test::(6, 0, 0); test::(1, 6, 6); test::(6, 1, 6); test::(8, 12, 24); test::(54, 24, 216); test::(42, 56, 168); test::(48, 18, 144); test::(3, 5, 15); test::(12, 60, 60); test::(12, 90, 180); } fn lcm_fail_helper() { assert_panic!(T::MAX.lcm(T::TWO)); assert_panic!({ let mut x = T::MAX; x.lcm_assign(T::TWO); }); } #[test] fn lcm_fail() { apply_fn_to_unsigneds!(lcm_fail_helper); } #[test] fn test_checked_lcm() { fn test(x: T, y: T, out: Option) { assert_eq!(x.checked_lcm(y), out); } test::(0, 0, Some(0)); test::(0, 6, Some(0)); test::(6, 0, Some(0)); test::(1, 6, Some(6)); test::(6, 1, Some(6)); test::(8, 12, Some(24)); test::(54, 24, Some(216)); test::(42, 56, Some(168)); test::(48, 18, Some(144)); test::(3, 5, Some(15)); test::(12, 60, Some(60)); test::(12, 90, Some(180)); test::(usize::MAX, 2, None); } fn lcm_properties_helper() { unsigned_pair_gen_var_34::().test_properties(|(x, y)| { let lcm = x.lcm(y); let mut x_mut = x; x_mut.lcm_assign(y); assert_eq!(x_mut, lcm); assert_eq!(y.lcm(x), lcm); assert!(lcm.divisible_by(x)); assert!(lcm.divisible_by(y)); let gcd = x.gcd(y); if x != T::ZERO { assert_eq!(lcm / x * gcd, y); } if y != T::ZERO { assert_eq!(lcm / y * gcd, x); } if gcd != T::ZERO { assert_eq!(x / gcd * y, lcm); } }); unsigned_gen::().test_properties(|x| { assert_eq!(x.lcm(x), x); assert_eq!(x.lcm(T::ONE), x); assert_eq!(x.lcm(T::ZERO), T::ZERO); }); } #[test] fn lcm_properties() { apply_fn_to_unsigneds!(lcm_properties_helper); } fn checked_lcm_properties_helper() { unsigned_pair_gen_var_33::().test_properties(|(x, y)| { let lcm = x.checked_lcm(y); assert_eq!(y.checked_lcm(x), lcm); if let Some(lcm) = lcm { assert_eq!(x.lcm(y), lcm); } }); unsigned_gen::().test_properties(|x| { assert_eq!(x.checked_lcm(x), Some(x)); assert_eq!(x.checked_lcm(T::ONE), Some(x)); assert_eq!(x.checked_lcm(T::ZERO), Some(T::ZERO)); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { if x != T::ZERO && y != T::ZERO && z != T::ZERO { assert_eq!( x.checked_lcm(y).and_then(|n| n.checked_lcm(z)), y.checked_lcm(z).and_then(|n| x.checked_lcm(n)) ); } }); } #[test] fn checked_lcm_properties() { apply_fn_to_unsigneds!(checked_lcm_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::log_base::{ceiling_log_base_naive, checked_log_base_naive}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen_var_1, unsigned_gen_var_6, unsigned_pair_gen_var_24, }; use std::panic::catch_unwind; fn floor_log_base_helper() { let test = |n: T, base, out| { assert_eq!(n.floor_log_base(base), out); }; test(T::ONE, T::TWO, 0); test(T::ONE, T::exact_from(5), 0); test(T::TWO, T::TWO, 1); test(T::TWO, T::exact_from(3), 0); test(T::exact_from(3), T::TWO, 1); test(T::exact_from(3), T::exact_from(3), 1); test(T::exact_from(3), T::exact_from(4), 0); test(T::exact_from(100), T::exact_from(2), 6); test(T::exact_from(100), T::exact_from(3), 4); test(T::exact_from(100), T::exact_from(4), 3); test(T::exact_from(100), T::exact_from(5), 2); test(T::exact_from(100), T::exact_from(10), 2); test(T::exact_from(100), T::exact_from(11), 1); } #[test] fn test_floor_log_base() { apply_fn_to_unsigneds!(floor_log_base_helper); } fn floor_log_base_fail_helper() { assert_panic!(T::ZERO.floor_log_base(T::TWO)); assert_panic!(T::TWO.floor_log_base(T::ZERO)); assert_panic!(T::TWO.floor_log_base(T::ONE)); } #[test] fn floor_log_base_fail() { apply_fn_to_unsigneds!(floor_log_base_fail_helper); } fn ceiling_log_base_helper() { let test = |n: T, pow, out| { assert_eq!(n.ceiling_log_base(pow), out); }; test(T::ONE, T::TWO, 0); test(T::ONE, T::exact_from(5), 0); test(T::TWO, T::TWO, 1); test(T::TWO, T::exact_from(3), 1); test(T::exact_from(3), T::TWO, 2); test(T::exact_from(3), T::exact_from(3), 1); test(T::exact_from(3), T::exact_from(4), 1); test(T::exact_from(100), T::exact_from(2), 7); test(T::exact_from(100), T::exact_from(3), 5); test(T::exact_from(100), T::exact_from(4), 4); test(T::exact_from(100), T::exact_from(5), 3); test(T::exact_from(100), T::exact_from(10), 2); test(T::exact_from(100), T::exact_from(11), 2); } #[test] fn test_ceiling_log_base() { apply_fn_to_unsigneds!(ceiling_log_base_helper); } fn ceiling_log_base_fail_helper() { assert_panic!(T::ZERO.ceiling_log_base(T::TWO)); assert_panic!(T::TWO.ceiling_log_base(T::ZERO)); assert_panic!(T::TWO.ceiling_log_base(T::ONE)); } #[test] fn ceiling_log_base_fail() { apply_fn_to_unsigneds!(ceiling_log_base_fail_helper); } fn checked_log_base_helper() { let test = |n: T, pow, out| { assert_eq!(n.checked_log_base(pow), out); }; test(T::ONE, T::TWO, Some(0)); test(T::ONE, T::exact_from(5), Some(0)); test(T::TWO, T::TWO, Some(1)); test(T::TWO, T::exact_from(3), None); test(T::exact_from(3), T::TWO, None); test(T::exact_from(3), T::exact_from(3), Some(1)); test(T::exact_from(3), T::exact_from(4), None); test(T::exact_from(100), T::exact_from(2), None); test(T::exact_from(100), T::exact_from(3), None); test(T::exact_from(100), T::exact_from(4), None); test(T::exact_from(100), T::exact_from(5), None); test(T::exact_from(100), T::exact_from(10), Some(2)); test(T::exact_from(100), T::exact_from(11), None); } #[test] fn test_checked_log_base() { apply_fn_to_unsigneds!(checked_log_base_helper); } fn checked_log_base_fail_helper() { assert_panic!(T::ZERO.checked_log_base(T::TWO)); assert_panic!(T::TWO.checked_log_base(T::ZERO)); assert_panic!(T::TWO.checked_log_base(T::ONE)); } #[test] fn checked_log_base_fail() { apply_fn_to_unsigneds!(checked_log_base_fail_helper); } fn floor_log_base_properties_helper() { unsigned_pair_gen_var_24::().test_properties(|(n, base)| { let floor_log = n.floor_log_base(base); assert!(floor_log < T::WIDTH); assert_eq!(floor_log == 0, n < base); if let Some(pow) = base.checked_pow(floor_log) { assert!(pow <= n); } if let Some(pow) = base.checked_pow(floor_log + 1) { assert!(pow > n); } let ceiling_log = n.ceiling_log_base(base); assert!(ceiling_log == floor_log || ceiling_log == floor_log + 1); }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.floor_log_base(T::TWO), n.floor_log_base_2()); }); unsigned_gen_var_6().test_properties(|n| { assert_eq!(T::ONE.floor_log_base(n), 0); assert_eq!(n.floor_log_base(n), 1); }); } #[test] fn floor_log_base_properties() { apply_fn_to_unsigneds!(floor_log_base_properties_helper); } fn ceiling_log_base_properties_helper() { unsigned_pair_gen_var_24::().test_properties(|(n, base)| { let ceiling_log = n.ceiling_log_base(base); assert!(ceiling_log <= T::WIDTH); assert_eq!(ceiling_log, ceiling_log_base_naive(n, base)); assert_eq!(ceiling_log == 0, n == T::ONE); if let Some(pow) = base.checked_pow(ceiling_log) { assert!(pow >= n); } if n != T::ONE && let Some(pow) = base.checked_pow(ceiling_log - 1) { assert!(pow < n); } let floor_log = n.floor_log_base(base); assert!(ceiling_log == floor_log || ceiling_log == floor_log + 1); }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.ceiling_log_base(T::TWO), n.ceiling_log_base_2()); }); unsigned_gen_var_6().test_properties(|n| { assert_eq!(T::ONE.ceiling_log_base(n), 0); assert_eq!(n.ceiling_log_base(n), 1); }); } #[test] fn ceiling_log_base_properties() { apply_fn_to_unsigneds!(ceiling_log_base_properties_helper); } fn checked_log_base_properties_helper() { unsigned_pair_gen_var_24::().test_properties(|(n, base)| { let checked_log = n.checked_log_base(base); assert_eq!(checked_log, checked_log_base_naive(n, base)); if let Some(log) = checked_log { assert_eq!(base.pow(log), n); assert!(log <= T::WIDTH); assert_eq!(log == 0, n == T::ONE); assert_eq!(n.floor_log_base(base), log); assert_eq!(n.ceiling_log_base(base), log); } }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.checked_log_base(T::TWO), n.checked_log_base_2()); }); unsigned_gen_var_6().test_properties(|n| { assert_eq!(T::ONE.checked_log_base(n), Some(0)); assert_eq!(n.checked_log_base(n), Some(1)); }); } #[test] fn checked_log_base_properties() { apply_fn_to_unsigneds!(checked_log_base_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{primitive_float_gen_var_18, unsigned_gen_var_1}; use std::panic::catch_unwind; fn floor_log_base_2_helper_unsigned() { let test = |n: T, out| { assert_eq!(n.floor_log_base_2(), out); }; test(T::ONE, 0); test(T::TWO, 1); test(T::exact_from(3), 1); test(T::exact_from(4), 2); test(T::exact_from(5), 2); test(T::exact_from(100), 6); test(T::exact_from(128), 7); test(T::MAX, T::WIDTH - 1); } fn floor_log_base_2_helper_primitive_float() { let test = |n: T, out| { assert_eq!(n.floor_log_base_2(), out); }; test(T::ONE, 0); test(T::TWO, 1); test(T::from(3.0f32), 1); test(T::from(4.0f32), 2); test(T::from(5.0f32), 2); test(T::from(100.0f32), 6); test(T::from(128.0f32), 7); test(T::from(0.4f32), -2); test(T::from(0.5f32), -1); test(T::from(0.6f32), -1); test(T::MAX_FINITE, T::MAX_EXPONENT); test(T::MIN_POSITIVE_SUBNORMAL, T::MIN_EXPONENT); } #[test] fn test_floor_log_base_2() { apply_fn_to_unsigneds!(floor_log_base_2_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_2_helper_primitive_float); } fn floor_log_base_2_fail_helper_unsigned() { assert_panic!(T::ZERO.floor_log_base_2()); } fn floor_log_base_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.floor_log_base_2()); assert_panic!(T::NAN.floor_log_base_2()); assert_panic!(T::INFINITY.floor_log_base_2()); assert_panic!(T::NEGATIVE_INFINITY.floor_log_base_2()); } #[test] fn floor_log_base_2_fail() { apply_fn_to_unsigneds!(floor_log_base_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_2_fail_helper_primitive_float); } fn ceiling_log_base_2_helper_unsigned() { let test = |n: T, out| { assert_eq!(n.ceiling_log_base_2(), out); }; test(T::ONE, 0); test(T::TWO, 1); test(T::exact_from(3), 2); test(T::exact_from(4), 2); test(T::exact_from(5), 3); test(T::exact_from(100), 7); test(T::exact_from(128), 7); test(T::MAX, T::WIDTH); } fn ceiling_log_base_2_helper_primitive_float() { let test = |n: T, out| { assert_eq!(n.ceiling_log_base_2(), out); }; test(T::ONE, 0); test(T::TWO, 1); test(T::from(3.0f32), 2); test(T::from(4.0f32), 2); test(T::from(5.0f32), 3); test(T::from(100.0f32), 7); test(T::from(128.0f32), 7); test(T::from(0.4f32), -1); test(T::from(0.5f32), -1); test(T::from(0.6f32), 0); test(T::MAX_FINITE, T::MAX_EXPONENT + 1); test(T::MIN_POSITIVE_SUBNORMAL, T::MIN_EXPONENT); } #[test] fn test_ceiling_log_base_2() { apply_fn_to_unsigneds!(ceiling_log_base_2_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_2_helper_primitive_float); } fn ceiling_log_base_2_fail_helper_unsigned() { assert_panic!(T::ZERO.ceiling_log_base_2()); } fn ceiling_log_base_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.ceiling_log_base_2()); assert_panic!(T::NAN.ceiling_log_base_2()); assert_panic!(T::INFINITY.ceiling_log_base_2()); assert_panic!(T::NEGATIVE_INFINITY.ceiling_log_base_2()); } #[test] fn ceiling_log_base_2_fail() { apply_fn_to_unsigneds!(ceiling_log_base_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_2_fail_helper_primitive_float); } fn checked_log_base_2_helper_unsigned() { let test = |n: T, out| { assert_eq!(n.checked_log_base_2(), out); }; test(T::ONE, Some(0)); test(T::TWO, Some(1)); test(T::exact_from(3), None); test(T::exact_from(4), Some(2)); test(T::exact_from(5), None); test(T::exact_from(100), None); test(T::exact_from(128), Some(7)); test(T::MAX, None); } fn checked_log_base_2_helper_primitive_float() { let test = |n: T, out| { assert_eq!(n.checked_log_base_2(), out); }; test(T::ONE, Some(0)); test(T::TWO, Some(1)); test(T::from(3.0f32), None); test(T::from(4.0f32), Some(2)); test(T::from(5.0f32), None); test(T::from(100.0f32), None); test(T::from(128.0f32), Some(7)); test(T::from(0.4f32), None); test(T::from(0.5f32), Some(-1)); test(T::from(0.6f32), None); test(T::MAX_FINITE, None); test(T::MIN_POSITIVE_SUBNORMAL, Some(T::MIN_EXPONENT)); } #[test] fn test_checked_log_base_2() { apply_fn_to_unsigneds!(checked_log_base_2_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_2_helper_primitive_float); } fn checked_log_base_2_fail_helper_unsigned() { assert_panic!(T::ZERO.checked_log_base_2()); } fn checked_log_base_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.checked_log_base_2()); assert_panic!(T::NAN.checked_log_base_2()); assert_panic!(T::INFINITY.checked_log_base_2()); assert_panic!(T::NEGATIVE_INFINITY.checked_log_base_2()); } #[test] fn checked_log_base_2_fail() { apply_fn_to_unsigneds!(checked_log_base_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_2_fail_helper_primitive_float); } fn floor_log_base_2_properties_helper_unsigned() { unsigned_gen_var_1::().test_properties(|n| { let floor_log_base_2 = n.floor_log_base_2(); assert_eq!(floor_log_base_2, n.significant_bits() - 1); assert!(floor_log_base_2 < T::WIDTH); assert_eq!(floor_log_base_2 == 0, n == T::ONE); assert!(T::power_of_2(floor_log_base_2) <= n); if floor_log_base_2 < T::WIDTH - 1 { assert!(T::power_of_2(floor_log_base_2 + 1) > n); } let ceiling_log_base_2 = n.ceiling_log_base_2(); if n.is_power_of_2() { assert_eq!(ceiling_log_base_2, floor_log_base_2); } else { assert_eq!(ceiling_log_base_2, floor_log_base_2 + 1); } }); } fn floor_log_base_2_properties_helper_primitive_float() { primitive_float_gen_var_18::().test_properties(|n| { let floor_log_base_2 = n.floor_log_base_2(); assert!(floor_log_base_2 <= T::MAX_EXPONENT); assert!(floor_log_base_2 >= T::MIN_EXPONENT); assert_eq!(floor_log_base_2 == 0, n >= T::ONE && n < T::TWO); assert!(T::power_of_2(floor_log_base_2) <= n); if floor_log_base_2 < T::MAX_EXPONENT { assert!(T::power_of_2(floor_log_base_2 + 1) > n); } let ceiling_log_base_2 = n.ceiling_log_base_2(); if n.is_power_of_2() { assert_eq!(ceiling_log_base_2, floor_log_base_2); } else { assert_eq!(ceiling_log_base_2, floor_log_base_2 + 1); } }); } #[test] fn floor_log_base_2_properties() { apply_fn_to_unsigneds!(floor_log_base_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_2_properties_helper_primitive_float); } fn ceiling_log_base_2_properties_helper_unsigned() { unsigned_gen_var_1::().test_properties(|n| { let ceiling_log_base_2 = n.ceiling_log_base_2(); assert!(ceiling_log_base_2 <= T::WIDTH); assert_eq!(ceiling_log_base_2 == 0, n == T::ONE); if ceiling_log_base_2 < T::WIDTH { assert!(T::power_of_2(ceiling_log_base_2) >= n); } if ceiling_log_base_2 != 0 { assert!(T::power_of_2(ceiling_log_base_2 - 1) < n); } let floor_log_base_2 = n.floor_log_base_2(); if n.is_power_of_2() { assert_eq!(floor_log_base_2, ceiling_log_base_2); } else { assert_eq!(floor_log_base_2, ceiling_log_base_2 - 1); } }); } fn ceiling_log_base_2_properties_helper_primitive_float() { primitive_float_gen_var_18::().test_properties(|n| { let ceiling_log_base_2 = n.ceiling_log_base_2(); assert!(ceiling_log_base_2 <= T::MAX_EXPONENT + 1); assert!(ceiling_log_base_2 >= T::MIN_EXPONENT); assert_eq!(ceiling_log_base_2 == 0, n > T::ONE / T::TWO && n <= T::ONE); if ceiling_log_base_2 < T::MAX_EXPONENT { assert!(T::power_of_2(ceiling_log_base_2) >= n); } if ceiling_log_base_2 > T::MIN_EXPONENT { assert!(T::power_of_2(ceiling_log_base_2 - 1) < n); } let floor_log_base_2 = n.floor_log_base_2(); if n.is_power_of_2() { assert_eq!(floor_log_base_2, ceiling_log_base_2); } else { assert_eq!(floor_log_base_2, ceiling_log_base_2 - 1); } }); } #[test] fn ceiling_log_base_2_properties() { apply_fn_to_unsigneds!(ceiling_log_base_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_2_properties_helper_primitive_float); } fn checked_log_base_2_properties_helper_unsigned() { unsigned_gen_var_1::().test_properties(|n| { let checked_log_base_2 = n.checked_log_base_2(); assert_eq!(checked_log_base_2.is_some(), n.is_power_of_2()); if let Some(log_base_2) = checked_log_base_2 { assert_eq!(T::power_of_2(log_base_2), n); assert!(log_base_2 <= T::WIDTH); assert_eq!(log_base_2 == 0, n == T::ONE); assert_eq!(n.floor_log_base_2(), log_base_2); assert_eq!(n.ceiling_log_base_2(), log_base_2); } }); } fn checked_log_base_2_properties_helper_primitive_float() { primitive_float_gen_var_18::().test_properties(|n| { let checked_log_base_2 = n.checked_log_base_2(); assert_eq!(checked_log_base_2.is_some(), n.is_power_of_2()); if let Some(log_base_2) = checked_log_base_2 { assert_eq!(T::power_of_2(log_base_2), n); assert!(log_base_2 <= T::MAX_EXPONENT); assert!(log_base_2 >= T::MIN_EXPONENT); assert_eq!(log_base_2 == 0, n == T::ONE); assert_eq!(n.floor_log_base_2(), log_base_2); assert_eq!(n.ceiling_log_base_2(), log_base_2); } }); } #[test] fn checked_log_base_2_properties() { apply_fn_to_unsigneds!(checked_log_base_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_2_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::log_base_power_of_2::ceiling_log_base_power_of_2_naive; use malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ primitive_float_gen_var_18, primitive_float_unsigned_pair_gen_var_3, unsigned_gen_var_1, unsigned_gen_var_11, unsigned_pair_gen_var_21, }; use std::panic::catch_unwind; fn floor_log_base_power_of_2_helper_unsigned() { let test = |n: T, pow, out| { assert_eq!(n.floor_log_base_power_of_2(pow), out); }; test(T::ONE, 1, 0); test(T::ONE, 5, 0); test(T::TWO, 1, 1); test(T::TWO, 2, 0); test(T::exact_from(3), 1, 1); test(T::exact_from(3), 2, 0); test(T::exact_from(4), 1, 2); test(T::exact_from(4), 2, 1); test(T::exact_from(4), 3, 0); test(T::exact_from(5), 1, 2); test(T::exact_from(5), 2, 1); test(T::exact_from(5), 3, 0); test(T::exact_from(100), 1, 6); test(T::exact_from(100), 2, 3); test(T::exact_from(100), 3, 2); test(T::exact_from(100), 4, 1); test(T::exact_from(100), 7, 0); test(T::exact_from(128), 1, 7); test(T::exact_from(128), 2, 3); test(T::exact_from(128), 3, 2); test(T::exact_from(128), 4, 1); test(T::exact_from(128), 7, 1); test(T::MAX, 1, T::WIDTH - 1); } fn floor_log_base_power_of_2_helper_primitive_float() { let test = |n: T, pow, out| { assert_eq!(n.floor_log_base_power_of_2(pow), out); }; test(T::ONE, 1, 0); test(T::ONE, 5, 0); test(T::TWO, 1, 1); test(T::TWO, 2, 0); test(T::from(3.0f32), 1, 1); test(T::from(3.0f32), 2, 0); test(T::from(4.0f32), 1, 2); test(T::from(4.0f32), 2, 1); test(T::from(4.0f32), 3, 0); test(T::from(5.0f32), 1, 2); test(T::from(5.0f32), 2, 1); test(T::from(5.0f32), 3, 0); test(T::from(100.0f32), 1, 6); test(T::from(100.0f32), 2, 3); test(T::from(100.0f32), 3, 2); test(T::from(100.0f32), 4, 1); test(T::from(100.0f32), 7, 0); test(T::from(128.0f32), 1, 7); test(T::from(128.0f32), 2, 3); test(T::from(128.0f32), 3, 2); test(T::from(128.0f32), 4, 1); test(T::from(128.0f32), 7, 1); test(T::from(0.1f32), 1, -4); test(T::from(0.1f32), 2, -2); test(T::from(0.1f32), 3, -2); test(T::from(0.1f32), 4, -1); test(T::MIN_POSITIVE_SUBNORMAL, 1, T::MIN_EXPONENT); test(T::MAX_FINITE, 1, T::MAX_EXPONENT); } #[test] fn test_floor_log_base_power_of_2() { apply_fn_to_unsigneds!(floor_log_base_power_of_2_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_power_of_2_helper_primitive_float); } fn floor_log_base_power_of_2_fail_helper_unsigned() { assert_panic!(T::ZERO.floor_log_base_power_of_2(2)); assert_panic!(T::TWO.floor_log_base_power_of_2(0)); } fn floor_log_base_power_of_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.floor_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_ONE.floor_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_INFINITY.floor_log_base_power_of_2(2)); assert_panic!(T::INFINITY.floor_log_base_power_of_2(2)); assert_panic!(T::NAN.floor_log_base_power_of_2(2)); assert_panic!(T::TWO.floor_log_base_power_of_2(0)); } #[test] fn floor_log_base_power_of_2_fail() { apply_fn_to_unsigneds!(floor_log_base_power_of_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_power_of_2_fail_helper_primitive_float); } fn ceiling_log_base_power_of_2_helper_unsigned() { let test = |n: T, pow, out| { assert_eq!(n.ceiling_log_base_power_of_2(pow), out); }; test(T::ONE, 1, 0); test(T::ONE, 5, 0); test(T::TWO, 1, 1); test(T::TWO, 2, 1); test(T::exact_from(3), 1, 2); test(T::exact_from(3), 2, 1); test(T::exact_from(4), 1, 2); test(T::exact_from(4), 2, 1); test(T::exact_from(4), 3, 1); test(T::exact_from(5), 1, 3); test(T::exact_from(5), 2, 2); test(T::exact_from(5), 3, 1); test(T::exact_from(100), 1, 7); test(T::exact_from(100), 2, 4); test(T::exact_from(100), 3, 3); test(T::exact_from(100), 4, 2); test(T::exact_from(100), 7, 1); test(T::exact_from(128), 1, 7); test(T::exact_from(128), 2, 4); test(T::exact_from(128), 3, 3); test(T::exact_from(128), 4, 2); test(T::exact_from(128), 7, 1); test(T::MAX, 1, T::WIDTH); } fn ceiling_log_base_power_of_2_helper_primitive_float() { let test = |n: T, pow, out| { assert_eq!(n.ceiling_log_base_power_of_2(pow), out); }; test(T::ONE, 1, 0); test(T::ONE, 5, 0); test(T::TWO, 1, 1); test(T::TWO, 2, 1); test(T::from(3.0f32), 1, 2); test(T::from(3.0f32), 2, 1); test(T::from(4.0f32), 1, 2); test(T::from(4.0f32), 2, 1); test(T::from(4.0f32), 3, 1); test(T::from(5.0f32), 1, 3); test(T::from(5.0f32), 2, 2); test(T::from(5.0f32), 3, 1); test(T::from(100.0f32), 1, 7); test(T::from(100.0f32), 2, 4); test(T::from(100.0f32), 3, 3); test(T::from(100.0f32), 4, 2); test(T::from(100.0f32), 7, 1); test(T::from(128.0f32), 1, 7); test(T::from(128.0f32), 2, 4); test(T::from(128.0f32), 3, 3); test(T::from(128.0f32), 4, 2); test(T::from(128.0f32), 7, 1); test(T::from(0.1f32), 1, -3); test(T::from(0.1f32), 2, -1); test(T::from(0.1f32), 3, -1); test(T::from(0.1f32), 4, 0); test(T::MIN_POSITIVE_SUBNORMAL, 1, T::MIN_EXPONENT); test(T::MAX_FINITE, 1, T::MAX_EXPONENT + 1); } #[test] fn test_ceiling_log_base_power_of_2() { apply_fn_to_unsigneds!(ceiling_log_base_power_of_2_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_power_of_2_helper_primitive_float); } fn ceiling_log_base_power_of_2_fail_helper_unsigned() { assert_panic!(T::ZERO.ceiling_log_base_power_of_2(2)); assert_panic!(T::TWO.ceiling_log_base_power_of_2(0)); } fn ceiling_log_base_power_of_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.ceiling_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_ONE.ceiling_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_INFINITY.ceiling_log_base_power_of_2(2)); assert_panic!(T::INFINITY.ceiling_log_base_power_of_2(2)); assert_panic!(T::NAN.ceiling_log_base_power_of_2(2)); assert_panic!(T::TWO.ceiling_log_base_power_of_2(0)); } #[test] fn ceiling_log_base_power_of_2_fail() { apply_fn_to_unsigneds!(ceiling_log_base_power_of_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_power_of_2_fail_helper_primitive_float); } fn checked_log_base_power_of_2_helper_unsigned() { let test = |n: T, pow, out| { assert_eq!(n.checked_log_base_power_of_2(pow), out); }; test(T::ONE, 1, Some(0)); test(T::ONE, 5, Some(0)); test(T::TWO, 1, Some(1)); test(T::TWO, 2, None); test(T::exact_from(3), 1, None); test(T::exact_from(3), 2, None); test(T::exact_from(4), 1, Some(2)); test(T::exact_from(4), 2, Some(1)); test(T::exact_from(4), 3, None); test(T::exact_from(5), 1, None); test(T::exact_from(5), 2, None); test(T::exact_from(5), 3, None); test(T::exact_from(100), 1, None); test(T::exact_from(100), 2, None); test(T::exact_from(100), 3, None); test(T::exact_from(100), 4, None); test(T::exact_from(100), 7, None); test(T::exact_from(128), 1, Some(7)); test(T::exact_from(128), 2, None); test(T::exact_from(128), 3, None); test(T::exact_from(128), 4, None); test(T::exact_from(128), 7, Some(1)); test(T::MAX, 1, None); } fn checked_log_base_power_of_2_helper_primitive_float() { let test = |n: T, pow, out| { assert_eq!(n.checked_log_base_power_of_2(pow), out); }; test(T::ONE, 1, Some(0)); test(T::ONE, 5, Some(0)); test(T::TWO, 1, Some(1)); test(T::TWO, 2, None); test(T::from(3.0f32), 1, None); test(T::from(3.0f32), 2, None); test(T::from(4.0f32), 1, Some(2)); test(T::from(4.0f32), 2, Some(1)); test(T::from(4.0f32), 3, None); test(T::from(5.0f32), 1, None); test(T::from(5.0f32), 2, None); test(T::from(5.0f32), 3, None); test(T::from(100.0f32), 1, None); test(T::from(100.0f32), 2, None); test(T::from(100.0f32), 3, None); test(T::from(100.0f32), 4, None); test(T::from(100.0f32), 7, None); test(T::from(128.0f32), 1, Some(7)); test(T::from(128.0f32), 2, None); test(T::from(128.0f32), 3, None); test(T::from(128.0f32), 4, None); test(T::from(128.0f32), 7, Some(1)); test(T::from(0.1f32), 1, None); test(T::from(0.1f32), 2, None); test(T::from(0.1f32), 3, None); test(T::from(0.1f32), 4, None); test(T::MIN_POSITIVE_SUBNORMAL, 1, Some(T::MIN_EXPONENT)); test(T::MAX_FINITE, 1, None); } #[test] fn test_checked_log_base_power_of_2() { apply_fn_to_unsigneds!(checked_log_base_power_of_2_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_power_of_2_helper_primitive_float); } fn checked_log_base_power_of_2_fail_helper_unsigned() { assert_panic!(T::ZERO.checked_log_base_power_of_2(2)); assert_panic!(T::TWO.checked_log_base_power_of_2(0)); } fn checked_log_base_power_of_2_fail_helper_primitive_float() { assert_panic!(T::ZERO.checked_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_ONE.checked_log_base_power_of_2(2)); assert_panic!(T::NEGATIVE_INFINITY.checked_log_base_power_of_2(2)); assert_panic!(T::INFINITY.checked_log_base_power_of_2(2)); assert_panic!(T::NAN.checked_log_base_power_of_2(2)); assert_panic!(T::TWO.checked_log_base_power_of_2(0)); } #[test] fn checked_log_base_power_of_2_fail() { apply_fn_to_unsigneds!(checked_log_base_power_of_2_fail_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_power_of_2_fail_helper_primitive_float); } fn floor_log_base_power_of_2_properties_helper_unsigned() { unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { let floor_log = n.floor_log_base_power_of_2(pow); assert!(floor_log < T::WIDTH); assert_eq!(floor_log == 0, n.significant_bits() - 1 < pow); if pow < T::WIDTH { assert_eq!(n.floor_log_base(T::power_of_2(pow)), floor_log); } let product = floor_log * pow; if product < T::WIDTH { assert!(T::power_of_2(product) <= n); } let product_2 = product + pow; if product_2 < T::WIDTH { assert!(T::power_of_2(product_2) > n); } let ceiling_log = n.ceiling_log_base_power_of_2(pow); if n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.floor_log_base_power_of_2(1), n.floor_log_base_2()); assert_eq!(n.floor_log_base_power_of_2(T::WIDTH), 0); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.floor_log_base_power_of_2(pow), 0); if pow < T::WIDTH { assert_eq!(T::power_of_2(pow).floor_log_base_power_of_2(pow), 1); } }); } fn floor_log_base_power_of_2_properties_helper_primitive_float() { primitive_float_unsigned_pair_gen_var_3::().test_properties(|(n, pow)| { let floor_log = n.floor_log_base_power_of_2(pow); assert!(floor_log <= T::MAX_EXPONENT); assert!(floor_log >= T::MIN_EXPONENT); let i_pow = i64::exact_from(pow); if i_pow >= T::MIN_EXPONENT && i_pow <= T::MAX_EXPONENT { assert_eq!(floor_log == 0, n >= T::ONE && n < T::power_of_2(i_pow)); } let product = floor_log * i_pow; if product >= T::MIN_EXPONENT && product <= T::MAX_EXPONENT { assert!(T::power_of_2(product) <= n); } let product_2 = product + i_pow; if product_2 >= T::MIN_EXPONENT && product_2 <= T::MAX_EXPONENT { assert!(T::power_of_2(product_2) > n); } let ceiling_log = n.ceiling_log_base_power_of_2(pow); if n.is_power_of_2() && n.floor_log_base_2().divisible_by(i_pow) { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } }); primitive_float_gen_var_18::().test_properties(|n| { assert_eq!(n.floor_log_base_power_of_2(1), n.floor_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.floor_log_base_power_of_2(pow), 0); }); } #[test] fn floor_log_base_power_of_2_properties_unsigned() { apply_fn_to_unsigneds!(floor_log_base_power_of_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(floor_log_base_power_of_2_properties_helper_primitive_float); } fn ceiling_log_base_power_of_2_properties_helper_unsigned() { unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { let ceiling_log = n.ceiling_log_base_power_of_2(pow); assert!(ceiling_log <= T::WIDTH); assert_eq!(ceiling_log, ceiling_log_base_power_of_2_naive(n, pow)); assert_eq!(ceiling_log == 0, n == T::ONE); if pow < T::WIDTH { assert_eq!(n.ceiling_log_base(T::power_of_2(pow)), ceiling_log); } let product = ceiling_log * pow; if product < T::WIDTH { assert!(T::power_of_2(product) >= n); } if product != 0 { assert!(T::power_of_2(product - pow) < n); } let floor_log = n.floor_log_base_power_of_2(pow); if n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.ceiling_log_base_power_of_2(1), n.ceiling_log_base_2()); assert_eq!( n.ceiling_log_base_power_of_2(T::WIDTH), u64::from(n != T::ONE) ); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.ceiling_log_base_power_of_2(pow), 0); if pow < T::WIDTH { assert_eq!(T::power_of_2(pow).ceiling_log_base_power_of_2(pow), 1); } }); } fn ceiling_log_base_power_of_2_properties_helper_primitive_float() { primitive_float_unsigned_pair_gen_var_3::().test_properties(|(n, pow)| { let ceiling_log = n.ceiling_log_base_power_of_2(pow); assert!(ceiling_log <= T::MAX_EXPONENT + 1); assert!(ceiling_log >= T::MIN_EXPONENT); let i_pow = i64::exact_from(pow); if i_pow >= T::MIN_EXPONENT && i_pow <= T::MAX_EXPONENT { assert_eq!( ceiling_log == 0, n > T::ONE / T::power_of_2(i_pow) && n <= T::ONE ); } let product = ceiling_log * i_pow; if product >= T::MIN_EXPONENT && product <= T::MAX_EXPONENT { assert!(T::power_of_2(product) >= n); } let product_2 = product - i_pow; if product_2 >= T::MIN_EXPONENT && product_2 <= T::MAX_EXPONENT { assert!(T::power_of_2(product_2) < n); } let floor_log = n.floor_log_base_power_of_2(pow); if n.is_power_of_2() && n.floor_log_base_2().divisible_by(i_pow) { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } }); primitive_float_gen_var_18::().test_properties(|n| { assert_eq!(n.ceiling_log_base_power_of_2(1), n.ceiling_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.ceiling_log_base_power_of_2(pow), 0); }); } #[test] fn ceiling_log_base_power_of_2_properties() { apply_fn_to_unsigneds!(ceiling_log_base_power_of_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(ceiling_log_base_power_of_2_properties_helper_primitive_float); } fn checked_log_base_power_of_2_properties_helper_unsigned() { unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { let checked_log = n.checked_log_base_power_of_2(pow); assert_eq!( checked_log.is_some(), n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) ); if pow < T::WIDTH { assert_eq!(n.checked_log_base(T::power_of_2(pow)), checked_log); } if let Some(log) = checked_log { assert_eq!(T::power_of_2(log * pow), n); assert!(log <= T::WIDTH); assert_eq!(log == 0, n == T::ONE); assert_eq!(n.floor_log_base_power_of_2(pow), log); assert_eq!(n.ceiling_log_base_power_of_2(pow), log); } }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(n.checked_log_base_power_of_2(1), n.checked_log_base_2()); assert_eq!( n.checked_log_base_power_of_2(T::WIDTH), if n == T::ONE { Some(0) } else { None } ); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.checked_log_base_power_of_2(pow), Some(0)); if pow < T::WIDTH { assert_eq!(T::power_of_2(pow).checked_log_base_power_of_2(pow), Some(1)); } }); } fn checked_log_base_power_of_2_properties_helper_primitive_float() { primitive_float_unsigned_pair_gen_var_3::().test_properties(|(n, pow)| { let checked_log = n.checked_log_base_power_of_2(pow); let i_pow = i64::exact_from(pow); assert_eq!( checked_log.is_some(), n.is_power_of_2() && n.checked_log_base_2().unwrap().divisible_by(i_pow) ); if let Some(log) = checked_log { assert_eq!(T::power_of_2(log * i_pow), n); assert!(log <= T::MAX_EXPONENT); assert!(log >= T::MIN_EXPONENT); assert_eq!(log == 0, n == T::ONE); assert_eq!(n.floor_log_base_power_of_2(pow), log); assert_eq!(n.ceiling_log_base_power_of_2(pow), log); } }); primitive_float_gen_var_18::().test_properties(|n| { assert_eq!(n.checked_log_base_power_of_2(1), n.checked_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(T::ONE.checked_log_base_power_of_2(pow), Some(0)); let i_pow = i64::exact_from(pow); if i_pow >= T::MIN_EXPONENT && i_pow <= T::MAX_EXPONENT { assert_eq!( T::power_of_2(i_pow).checked_log_base_power_of_2(pow), Some(1) ); } }); } #[test] fn checked_log_base_power_of_2_properties() { apply_fn_to_unsigneds!(checked_log_base_power_of_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(checked_log_base_power_of_2_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_4, unsigned_triple_gen_var_12, }; use std::panic::catch_unwind; fn mod_add_helper() { let test = |x: T, y: T, m, out| { assert_eq!(x.mod_add(y, m), out); let mut x = x; x.mod_add_assign(y, m); assert_eq!(x, out); }; test(T::ZERO, T::ZERO, T::ONE, T::ZERO); test( T::ZERO, T::exact_from(3), T::exact_from(5), T::exact_from(3), ); test( T::exact_from(7), T::exact_from(5), T::exact_from(10), T::TWO, ); test( T::exact_from(100), T::exact_from(100), T::exact_from(123), T::exact_from(77), ); test(T::MAX - T::ONE, T::ONE, T::MAX, T::ZERO); test(T::MAX - T::ONE, T::MAX - T::ONE, T::MAX, T::MAX - T::TWO); } #[test] fn test_mod_add() { apply_fn_to_unsigneds!(mod_add_helper); } fn mod_add_fail_helper() { assert_panic!(T::ZERO.mod_add(T::ZERO, T::ZERO)); assert_panic!(T::from(123u8).mod_add(T::from(200u8), T::from(200u8))); assert_panic!(T::from(200u8).mod_add(T::from(123u8), T::from(200u8))); } #[test] fn mod_add_fail() { apply_fn_to_unsigneds!(mod_add_fail_helper); } fn mod_add_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_add_assign(T::ZERO, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_add_assign(T::from(200u8), T::from(200u8)); }); assert_panic!({ let mut x = T::from(200u8); x.mod_add_assign(T::from(123u8), T::from(200u8)); }); } #[test] fn mod_add_assign_fail() { apply_fn_to_unsigneds!(mod_add_assign_fail_helper); } fn mod_add_properties_helper() { unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let sum = x.mod_add(y, m); assert!(sum.mod_is_reduced(&m)); let mut x_alt = x; x_alt.mod_add_assign(y, m); assert_eq!(x_alt, sum); assert_eq!(sum.mod_sub(y, m), x); assert_eq!(sum.mod_sub(x, m), y); assert_eq!(y.mod_add(x, m), sum); assert_eq!(x.mod_sub(y.mod_neg(m), m), sum); }); unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert_eq!(x.mod_add(T::ZERO, m), x); assert_eq!(T::ZERO.mod_add(x, m), x); assert_eq!(x.mod_add(x.mod_neg(m), m), T::ZERO); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_panic!(x.mod_add(y, T::ZERO)); assert_panic!({ let mut x = x; x.mod_add_assign(y, T::ZERO); }); }); unsigned_quadruple_gen_var_4::().test_properties(|(x, y, z, m)| { assert_eq!(x.mod_add(y, m).mod_add(z, m), x.mod_add(y.mod_add(z, m), m)); }); } #[test] fn mod_add_properties() { apply_fn_to_unsigneds!(mod_add_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_inverse::mod_inverse_binary; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_6, unsigned_pair_gen_var_38, }; use malachite_base::test_util::num::arithmetic::mod_inverse::mod_inverse_euclidean; use std::panic::catch_unwind; fn mod_inverse_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { let test = |n: U, m, out| { assert_eq!(n.mod_inverse(m), out); assert_eq!(mod_inverse_euclidean::(n, m), out); assert_eq!(mod_inverse_binary::(n, m), out); }; test(U::ONE, U::exact_from(5), Some(U::ONE)); test(U::exact_from(7), U::exact_from(10), Some(U::exact_from(3))); test(U::exact_from(6), U::exact_from(10), None); test( U::exact_from(100), U::exact_from(101), Some(U::exact_from(100)), ); test(U::ONE, U::MAX, Some(U::ONE)); test(U::MAX - U::ONE, U::MAX, Some(U::MAX - U::ONE)); } #[test] fn test_mod_inverse() { apply_fn_to_unsigned_signed_pairs!(mod_inverse_helper); } fn mod_inverse_fail_helper() { assert_panic!(T::ZERO.mod_inverse(T::ZERO)); assert_panic!(T::ZERO.mod_inverse(T::from(10u8))); assert_panic!(T::from(123u8).mod_inverse(T::from(123u8))); } #[test] fn mod_inverse_fail() { apply_fn_to_unsigneds!(mod_inverse_fail_helper); } fn mod_inverse_properties_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { unsigned_pair_gen_var_38::().test_properties(|(n, m)| { assert!(n.mod_is_reduced(&m)); let inverse = n.mod_inverse(m); assert_eq!(mod_inverse_euclidean::(n, m), inverse); assert_eq!(mod_inverse_binary::(n, m), inverse); assert_eq!(inverse.is_some(), n.coprime_with(m)); if let Some(inverse) = inverse { assert!(inverse.mod_is_reduced(&m)); assert_eq!(inverse.mod_inverse(m), Some(n)); assert_eq!(n.mod_mul(inverse, m), U::ONE); assert_eq!((m - n).mod_inverse(m), Some(m - inverse)); } }); unsigned_gen_var_6::().test_properties(|m| { assert_eq!(U::ONE.mod_inverse(m), Some(U::ONE)); assert_eq!((m - U::ONE).mod_inverse(m), Some(m - U::ONE)); }); unsigned_gen::().test_properties(|x| { assert_panic!(x.mod_inverse(U::ZERO)); }); } #[test] fn mod_inverse_properties() { apply_fn_to_unsigned_signed_pairs!(mod_inverse_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::unsigned_pair_gen_var_12; use std::panic::catch_unwind; fn mod_is_reduced_helper() { let test = |n: T, m, out| { assert_eq!(n.mod_is_reduced(&m), out); }; test(T::ZERO, T::exact_from(5), true); test(T::exact_from(100), T::exact_from(100), false); test(T::exact_from(100), T::exact_from(101), true); test(T::MAX - T::ONE, T::MAX - T::ONE, false); test(T::MAX - T::ONE, T::MAX, true); test(T::MAX, T::MAX, false); } #[test] fn test_mod_is_reduced() { apply_fn_to_unsigneds!(mod_is_reduced_helper); } fn mod_is_reduced_fail_helper() { assert_panic!(T::ZERO.mod_is_reduced(&T::ZERO)); } #[test] fn mod_is_reduced_fail() { apply_fn_to_unsigneds!(mod_is_reduced_fail_helper); } fn mod_is_reduced_properties_helper() { unsigned_pair_gen_var_12::().test_properties(|(n, m)| { assert_eq!(n.mod_is_reduced(&m), n % m == n); }); } #[test] fn mod_is_reduced_properties() { apply_fn_to_unsigneds!(mod_is_reduced_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_mul::{ fast_mod_mul, limbs_invert_limb_u32, limbs_invert_limb_u64, mod_preinverted_double, naive_mod_mul, test_invert_u32_table, test_invert_u64_table, }; use malachite_base::num::arithmetic::traits::ModMulPrecomputed; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::test_util::generators::{ unsigned_gen_var_12, unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_4, unsigned_quadruple_gen_var_5, unsigned_triple_gen_var_12, }; use malachite_base::test_util::num::arithmetic::mod_mul::limbs_invert_limb_naive; use std::panic::catch_unwind; #[test] fn test_test_invert_u32_table() { test_invert_u32_table(); } #[test] fn test_test_invert_u64_table() { test_invert_u64_table(); } #[test] fn test_limbs_invert_limb_u32() { let test = |x, out| { assert_eq!(limbs_invert_limb_u32(x), out); assert_eq!(limbs_invert_limb_naive::(x), out); }; test(0x80000000, u32::MAX); test(0x80000001, 0xfffffffc); test(u32::MAX - 1, 2); test(u32::MAX, 1); test(0x89abcdef, 0xdc08767e); } #[test] #[should_panic] fn limbs_invert_limb_u32_fail() { limbs_invert_limb_u32(123); } #[test] fn test_limbs_invert_limb_u64() { let test = |x, out| { assert_eq!(limbs_invert_limb_u64(x), out); assert_eq!(limbs_invert_limb_naive::(x), out); }; test(0x8000000000000000, u64::MAX); test(0x8000000000000001, 0xfffffffffffffffc); test(0xfffffffffffffffe, 2); test(u64::MAX, 1); test(0x89abcdefedcba987, 0xdc08767b33d7ec8f); } #[test] #[should_panic] fn limbs_invert_limb_u64_fail() { limbs_invert_limb_u64(123); } #[test] fn test_mod_preinverted_double() { fn test< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >( x_1: T, x_0: T, d: T, out: T, ) { let d_inv = limbs_invert_limb_naive::(d << LeadingZeros::leading_zeros(d)); assert_eq!(mod_preinverted_double::(x_1, x_0, d, d_inv), out); assert_eq!(T::exact_from(DT::join_halves(x_1, x_0) % DT::from(d)), out); } test::(0, 0, 1, 0); test::(0, 1, 1, 0); test::(1, 0, 2, 0); test::(1, 7, 2, 1); test::(0x78, 0x9a, 0xbc, 0x2a); test::(0x12, 0x34, 0x33, 0x13); } fn mod_mul_helper() { let test = |x: T, y: T, m, out| { assert_eq!(x.mod_mul(y, m), out); let mut mut_x = x; mut_x.mod_mul_assign(y, m); assert_eq!(mut_x, out); let data = T::precompute_mod_mul_data(&m); assert_eq!(x.mod_mul_precomputed(y, m, &data), out); let mut mut_x = x; mut_x.mod_mul_precomputed_assign(y, m, &data); assert_eq!(mut_x, out); assert_eq!(naive_mod_mul(x, y, m), out); }; test(T::ZERO, T::ZERO, T::ONE, T::ZERO); test(T::TWO, T::exact_from(3), T::exact_from(7), T::exact_from(6)); test( T::exact_from(7), T::exact_from(3), T::exact_from(10), T::ONE, ); test( T::exact_from(100), T::exact_from(100), T::exact_from(123), T::exact_from(37), ); test(T::MAX - T::ONE, T::MAX - T::ONE, T::MAX, T::ONE); } #[test] fn test_mod_mul() { apply_fn_to_unsigneds!(mod_mul_helper); } fn mod_mul_fail_helper() { assert_panic!(T::ZERO.mod_mul(T::ZERO, T::ZERO)); assert_panic!(T::from(123u8).mod_mul(T::from(200u8), T::from(200u8))); assert_panic!(T::from(200u8).mod_mul(T::from(123u8), T::from(200u8))); } #[test] fn mod_mul_fail() { apply_fn_to_unsigneds!(mod_mul_fail_helper); } fn mod_mul_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_mul_assign(T::ZERO, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_mul_assign(T::from(200u8), T::from(200u8)); }); assert_panic!({ let mut x = T::from(200u8); x.mod_mul_assign(T::from(123u8), T::from(200u8)); }); } #[test] fn mod_mul_assign_fail() { apply_fn_to_unsigneds!(mod_mul_assign_fail_helper); } #[test] fn invert_limb_u32_properties() { unsigned_gen_var_12().test_properties(|x| { let inverse = limbs_invert_limb_u32(x); assert_eq!(limbs_invert_limb_naive::(x), inverse); assert_ne!(inverse, 0); }); } #[test] fn invert_limb_u64_properties() { unsigned_gen_var_12().test_properties(|x| { let inverse = limbs_invert_limb_u64(x); assert_eq!(limbs_invert_limb_naive::(x), inverse); assert_ne!(inverse, 0); }); } fn mod_mul_preinverted_properties_helper< T: TryFrom
+ PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >() { unsigned_quadruple_gen_var_5::().test_properties(|(x_1, x_0, d, d_inv)| { let r = mod_preinverted_double::(x_1, x_0, d, d_inv); let n = DT::join_halves(x_1, x_0); assert_eq!(T::exact_from(n % DT::from(d)), r); assert!(r < d); let q = DT::join_halves(x_1, x_0) / DT::from(d); assert_eq!(q * DT::from(d) + DT::from(r), n); }); } #[test] fn mod_mul_preinverted_properties() { mod_mul_preinverted_properties_helper::(); mod_mul_preinverted_properties_helper::(); mod_mul_preinverted_properties_helper::(); mod_mul_preinverted_properties_helper::(); } fn mod_mul_properties_helper() { unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let product = x.mod_mul(y, m); assert!(product.mod_is_reduced(&m)); let mut x_alt = x; x_alt.mod_mul_assign(y, m); assert_eq!(x_alt, product); let data = T::precompute_mod_mul_data(&m); assert_eq!(x.mod_mul_precomputed(y, m, &data), product); let mut x_alt = x; x_alt.mod_mul_precomputed_assign(y, m, &data); assert_eq!(x_alt, product); assert_eq!(naive_mod_mul(x, y, m), product); assert_eq!(y.mod_mul(x, m), product); assert_eq!(x.mod_mul(y.mod_neg(m), m), product.mod_neg(m)); assert_eq!(x.mod_neg(m).mod_mul(y, m), product.mod_neg(m)); }); unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert_eq!(x.mod_mul(T::ZERO, m), T::ZERO); assert_eq!(T::ZERO.mod_mul(x, m), T::ZERO); if m > T::ONE { assert_eq!(x.mod_mul(T::ONE, m), x); assert_eq!(T::ONE.mod_mul(x, m), x); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_panic!(x.mod_mul(y, T::ZERO)); assert_panic!({ let mut x = x; x.mod_mul_assign(y, T::ZERO); }); }); unsigned_quadruple_gen_var_4::().test_properties(|(x, y, z, m)| { assert_eq!(x.mod_mul(y, m).mod_mul(z, m), x.mod_mul(y.mod_mul(z, m), m)); assert_eq!( x.mod_mul(y.mod_add(z, m), m), x.mod_mul(y, m).mod_add(x.mod_mul(z, m), m) ); assert_eq!( x.mod_add(y, m).mod_mul(z, m), x.mod_mul(z, m).mod_add(y.mod_mul(z, m), m) ); }); } fn mod_mul_properties_fast_helper< T: TryFrom
+ ModMulPrecomputed + PrimitiveUnsigned, DT: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, >() { unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { let product = x.mod_mul(y, m); assert_eq!( fast_mod_mul::(x, y, m, T::precompute_mod_mul_data(&m)), product ); }); } #[test] fn mod_mul_properties() { apply_fn_to_unsigneds!(mod_mul_properties_helper); mod_mul_properties_fast_helper::(); mod_mul_properties_fast_helper::(); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_1, unsigned_gen_var_6, unsigned_pair_gen_var_16, }; use std::panic::catch_unwind; fn mod_neg_helper() { let test = |n: T, m, out| { assert_eq!(n.mod_neg(m), out); let mut n = n; n.mod_neg_assign(m); assert_eq!(n, out); }; test(T::ZERO, T::exact_from(5), T::ZERO); test(T::exact_from(7), T::exact_from(10), T::exact_from(3)); test(T::exact_from(100), T::exact_from(101), T::ONE); test(T::MAX - T::ONE, T::MAX, T::ONE); test(T::ONE, T::MAX, T::MAX - T::ONE); } #[test] fn test_mod_neg() { apply_fn_to_unsigneds!(mod_neg_helper); } fn mod_neg_fail_helper() { assert_panic!(T::ZERO.mod_neg(T::ZERO)); assert_panic!(T::from(123u8).mod_neg(T::from(123u8))); } #[test] fn mod_neg_fail() { apply_fn_to_unsigneds!(mod_neg_fail_helper); } fn mod_neg_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_neg_assign(T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_neg_assign(T::from(123u8)); }); } #[test] fn mod_neg_assign_fail() { apply_fn_to_unsigneds!(mod_neg_assign_fail_helper); } fn mod_neg_properties_helper() { unsigned_pair_gen_var_16::().test_properties(|(n, m)| { assert!(n.mod_is_reduced(&m)); let neg = n.mod_neg(m); assert!(neg.mod_is_reduced(&m)); let mut n_alt = n; n_alt.mod_neg_assign(m); assert_eq!(n_alt, neg); assert_eq!(neg.mod_neg(m), n); assert_eq!(n.mod_add(neg, m), T::ZERO); assert_eq!(n == neg, n == T::ZERO || m.even() && n == m >> 1); }); unsigned_gen_var_1::().test_properties(|m| { assert_eq!(T::ZERO.mod_neg(m), T::ZERO); }); unsigned_gen_var_6::().test_properties(|m| { assert_eq!(T::ONE.mod_neg(m), m - T::ONE); assert_eq!((m - T::ONE).mod_neg(m), T::ONE); }); unsigned_gen::().test_properties(|x| { assert_panic!(x.mod_neg(T::ZERO)); }); } #[test] fn mod_neg_properties() { apply_fn_to_unsigneds!(mod_neg_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_6, signed_pair_gen_var_4, signed_pair_gen_var_6, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_12, }; use std::panic::catch_unwind; #[test] fn test_mod_op_unsigned() { fn test(n: T, d: T, r: T) { assert_eq!(n.mod_op(d), r); let mut mut_n = n; mut_n.mod_assign(d); assert_eq!(mut_n, r); } test::(0, 1, 0); test::(0, 123, 0); test::(1, 1, 0); test::(123, 1, 0); test::(123, 123, 0); test::(123, 456, 123); test::(456, 123, 87); test::(u32::MAX, 1, 0); test::(0xffffffff, 0xffffffff, 0); test::(1000000000000, 1, 0); test::(1000000000000, 3, 1); test::(1000000000000, 123, 100); test::(1000000000000, 0xffffffff, 3567587560); test::(1000000000000000000000000, 1, 0); test::(1000000000000000000000000, 3, 1); test::(1000000000000000000000000, 123, 37); test::(1000000000000000000000000, 0xffffffff, 3167723695); test::(1000000000000000000000000, 1234567890987, 530068894399); test::(253640751230376270397812803167, 2669936877441, 1520301762334); test::(3768477692975601, 11447376614057827956, 3768477692975601); test::(3356605361737854, 3081095617839357, 275509743898497); test::( 1098730198198174614195, 953382298040157850476, 145347900158016763719, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 0); test::(0, 1000000000000000000000000, 0); test::(123, 1000000000000000000000000, 123); } #[test] fn test_div_mod_signed() { fn test(n: T, d: T, r: T) { assert_eq!(n.mod_op(d), r); let mut mut_n = n; mut_n.mod_assign(d); assert_eq!(mut_n, r); } test::(0, 1, 0); test::(0, 123, 0); test::(1, 1, 0); test::(123, 1, 0); test::(123, 123, 0); test::(123, 456, 123); test::(456, 123, 87); test::(0xffffffff, 1, 0); test::(0xffffffff, 0xffffffff, 0); test::(1000000000000, 1, 0); test::(1000000000000, 3, 1); test::(1000000000000, 123, 100); test::(1000000000000, 0xffffffff, 3567587560); test::(1000000000000000000000000, 1, 0); test::(1000000000000000000000000, 3, 1); test::(1000000000000000000000000, 123, 37); test::(1000000000000000000000000, 0xffffffff, 3167723695); test::(1000000000000000000000000, 1234567890987, 530068894399); test::(253640751230376270397812803167, 2669936877441, 1520301762334); test::(3768477692975601, 11447376614057827956, 3768477692975601); test::(3356605361737854, 3081095617839357, 275509743898497); test::( 1098730198198174614195, 953382298040157850476, 145347900158016763719, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 0); test::(0, 1000000000000000000000000, 0); test::(123, 1000000000000000000000000, 123); test::(0, -1, 0); test::(0, -123, 0); test::(1, -1, 0); test::(123, -1, 0); test::(123, -123, 0); test::(123, -456, -333); test::(456, -123, -36); test::(0xffffffff, -1, 0); test::(0xffffffff, -0xffffffff, 0); test::(1000000000000, -1, 0); test::(1000000000000, -3, -2); test::(1000000000000, -123, -23); test::(1000000000000, -0xffffffff, -727379735); test::(1000000000000000000000000, -1, 0); test::(1000000000000000000000000, -3, -2); test::(1000000000000000000000000, -123, -86); test::(1000000000000000000000000, -0xffffffff, -1127243600); test::(1000000000000000000000000, -1234567890987, -704498996588); test::( 253640751230376270397812803167, -2669936877441, -1149635115107, ); test::( 3768477692975601, -11447376614057827956, -11443608136364852355, ); test::(3356605361737854, -3081095617839357, -2805585873940860); test::( 1098730198198174614195, -953382298040157850476, -808034397882141086757, ); test::( 69738658860594537152875081748, -69738658860594537152875081748, 0, ); test::(1000000000000000000000000, -1000000000000000000000000, 0); test::(0, -1000000000000000000000000, 0); test::(123, -1000000000000000000000000, -999999999999999999999877); test::(-1, 1, 0); test::(-123, 1, 0); test::(-123, 123, 0); test::(-123, 456, 333); test::(-456, 123, 36); test::(-0xffffffff, -1, 0); test::(-0xffffffff, 0xffffffff, 0); test::(-1000000000000, 1, 0); test::(-1000000000000, 3, 2); test::(-1000000000000, 123, 23); test::(-1000000000000, 0xffffffff, 727379735); test::(-1000000000000000000000000, 1, 0); test::(-1000000000000000000000000, 3, 2); test::(-1000000000000000000000000, 123, 86); test::(-1000000000000000000000000, 0xffffffff, 1127243600); test::(-1000000000000000000000000, 1234567890987, 704498996588); test::( -253640751230376270397812803167, 2669936877441, 1149635115107, ); test::( -3768477692975601, 11447376614057827956, 11443608136364852355, ); test::(-3356605361737854, 3081095617839357, 2805585873940860); test::( -1098730198198174614195, 953382298040157850476, 808034397882141086757, ); test::( -69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(-1000000000000000000000000, 1000000000000000000000000, 0); test::(-123, 1000000000000000000000000, 999999999999999999999877); test::(-1, -1, 0); test::(-123, -1, 0); test::(-123, -123, 0); test::(-123, -456, -123); test::(-456, -123, -87); test::(-0xffffffff, -1, 0); test::(-0xffffffff, -0xffffffff, 0); test::(-1000000000000, -1, 0); test::(-1000000000000, -3, -1); test::(-1000000000000, -123, -100); test::(-1000000000000, -0xffffffff, -3567587560); test::(-1000000000000000000000000, -1, 0); test::(-1000000000000000000000000, -3, -1); test::(-1000000000000000000000000, -123, -37); test::(-1000000000000000000000000, -0xffffffff, -3167723695); test::(-1000000000000000000000000, -1234567890987, -530068894399); test::( -253640751230376270397812803167, -2669936877441, -1520301762334, ); test::(-3768477692975601, -11447376614057827956, -3768477692975601); test::(-3356605361737854, -3081095617839357, -275509743898497); test::( -1098730198198174614195, -953382298040157850476, -145347900158016763719, ); test::( -69738658860594537152875081748, -69738658860594537152875081748, 0, ); test::(-1000000000000000000000000, -1000000000000000000000000, 0); test::(-123, -1000000000000000000000000, -123); test::(-128, -1, 0); } fn mod_fail_helper() { assert_panic!(T::ONE.mod_op(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.mod_assign(T::ZERO); }); } #[test] pub fn mod_fail() { apply_fn_to_primitive_ints!(mod_fail_helper); } #[test] fn test_neg_mod() { fn test(n: T, d: T, r: T) { assert_eq!(n.neg_mod(d), r); let mut mut_n = n; mut_n.neg_mod_assign(d); assert_eq!(mut_n, r); } test::(0, 1, 0); test::(0, 123, 0); test::(1, 1, 0); test::(123, 1, 0); test::(123, 123, 0); test::(123, 456, 333); test::(456, 123, 36); test::(0xffffffff, 1, 0); test::(0xffffffff, 0xffffffff, 0); test::(1000000000000, 1, 0); test::(1000000000000, 3, 2); test::(1000000000000, 123, 23); test::(1000000000000, 0xffffffff, 727379735); test::(1000000000000000000000000, 1, 0); test::(1000000000000000000000000, 3, 2); test::(1000000000000000000000000, 123, 86); test::(1000000000000000000000000, 0xffffffff, 1127243600); test::(1000000000000000000000000, 1234567890987, 704498996588); test::(253640751230376270397812803167, 2669936877441, 1149635115107); test::(3768477692975601, 11447376614057827956, 11443608136364852355); test::(3356605361737854, 3081095617839357, 2805585873940860); test::( 1098730198198174614195, 953382298040157850476, 808034397882141086757, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 0); test::(0, 1000000000000000000000000, 0); test::(123, 1000000000000000000000000, 999999999999999999999877); } fn neg_mod_fail_helper() { assert_panic!(T::ONE.neg_mod(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.neg_mod_assign(T::ZERO); }); } #[test] pub fn neg_mod_fail() { apply_fn_to_unsigneds!(neg_mod_fail_helper); } #[test] fn test_ceiling_mod() { fn test(n: T, d: T, r: T) { assert_eq!(n.ceiling_mod(d), r); let mut mut_n = n; mut_n.ceiling_mod_assign(d); assert_eq!(mut_n, r); } test::(0, 1, 0); test::(0, 123, 0); test::(1, 1, 0); test::(123, 1, 0); test::(123, 123, 0); test::(123, 456, -333); test::(456, 123, -36); test::(0xffffffff, 1, 0); test::(0xffffffff, 0xffffffff, 0); test::(1000000000000, 1, 0); test::(1000000000000, 3, -2); test::(1000000000000, 123, -23); test::(1000000000000, 0xffffffff, -727379735); test::(1000000000000000000000000, 1, 0); test::(1000000000000000000000000, 3, -2); test::(1000000000000000000000000, 123, -86); test::(1000000000000000000000000, 0xffffffff, -1127243600); test::(1000000000000000000000000, 1234567890987, -704498996588); test::( 253640751230376270397812803167, 2669936877441, -1149635115107, ); test::( 3768477692975601, 11447376614057827956, -11443608136364852355, ); test::(3356605361737854, 3081095617839357, -2805585873940860); test::( 1098730198198174614195, 953382298040157850476, -808034397882141086757, ); test::( 69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(1000000000000000000000000, 1000000000000000000000000, 0); test::(0, 1000000000000000000000000, 0); test::(123, 1000000000000000000000000, -999999999999999999999877); test::(0, -1, 0); test::(0, -123, 0); test::(1, -1, 0); test::(123, -1, 0); test::(123, -123, 0); test::(123, -456, 123); test::(456, -123, 87); test::(0xffffffff, -1, 0); test::(0xffffffff, -0xffffffff, 0); test::(1000000000000, -1, 0); test::(1000000000000, -3, 1); test::(1000000000000, -123, 100); test::(1000000000000, -0xffffffff, 3567587560); test::(1000000000000000000000000, -1, 0); test::(1000000000000000000000000, -3, 1); test::(1000000000000000000000000, -123, 37); test::(1000000000000000000000000, -0xffffffff, 3167723695); test::(1000000000000000000000000, -1234567890987, 530068894399); test::( 253640751230376270397812803167, -2669936877441, 1520301762334, ); test::(3768477692975601, -11447376614057827956, 3768477692975601); test::(3356605361737854, -3081095617839357, 275509743898497); test::( 1098730198198174614195, -953382298040157850476, 145347900158016763719, ); test::( 69738658860594537152875081748, -69738658860594537152875081748, 0, ); test::(1000000000000000000000000, -1000000000000000000000000, 0); test::(0, -1000000000000000000000000, 0); test::(123, -1000000000000000000000000, 123); test::(-1, 1, 0); test::(-123, 1, 0); test::(-123, 123, 0); test::(-123, 456, -123); test::(-456, 123, -87); test::(-0xffffffff, 1, 0); test::(-0xffffffff, 0xffffffff, 0); test::(-1000000000000, 1, 0); test::(-1000000000000, 3, -1); test::(-1000000000000, 123, -100); test::(-1000000000000, 0xffffffff, -3567587560); test::(-1000000000000000000000000, 1, 0); test::(-1000000000000000000000000, 3, -1); test::(-1000000000000000000000000, 123, -37); test::(-1000000000000000000000000, 0xffffffff, -3167723695); test::(-1000000000000000000000000, 1234567890987, -530068894399); test::( -253640751230376270397812803167, 2669936877441, -1520301762334, ); test::(-3768477692975601, 11447376614057827956, -3768477692975601); test::(-3356605361737854, 3081095617839357, -275509743898497); test::( -1098730198198174614195, 953382298040157850476, -145347900158016763719, ); test::( -69738658860594537152875081748, 69738658860594537152875081748, 0, ); test::(-1000000000000000000000000, 1000000000000000000000000, 0); test::(0, 1000000000000000000000000, 0); test::(-123, 1000000000000000000000000, -123); test::(-1, -1, 0); test::(-123, -1, 0); test::(-123, -123, 0); test::(-123, -456, 333); test::(-456, -123, 36); test::(-0xffffffff, -1, 0); test::(-0xffffffff, -0xffffffff, 0); test::(-1000000000000, -1, 0); test::(-1000000000000, -3, 2); test::(-1000000000000, -123, 23); test::(-1000000000000, -0xffffffff, 727379735); test::(-1000000000000000000000000, -1, 0); test::(-1000000000000000000000000, -3, 2); test::(-1000000000000000000000000, -123, 86); test::(-1000000000000000000000000, -0xffffffff, 1127243600); test::(-1000000000000000000000000, -1234567890987, 704498996588); test::( -253640751230376270397812803167, -2669936877441, 1149635115107, ); test::( -3768477692975601, -11447376614057827956, 11443608136364852355, ); test::(-3356605361737854, -3081095617839357, 2805585873940860); test::( -1098730198198174614195, -953382298040157850476, 808034397882141086757, ); test::( -69738658860594537152875081748, -69738658860594537152875081748, 0, ); test::(-1000000000000000000000000, -1000000000000000000000000, 0); test::(0, -1000000000000000000000000, 0); test::(-123, -1000000000000000000000000, 999999999999999999999877); test::(-128, -1, 0); } fn ceiling_mod_fail_helper() { assert_panic!(T::ONE.ceiling_mod(T::ZERO)); assert_panic!({ let mut n = T::ONE; n.ceiling_mod_assign(T::ZERO); }); } #[test] pub fn ceiling_mod_fail() { apply_fn_to_signeds!(ceiling_mod_fail_helper); } fn mod_properties_helper_unsigned() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.mod_assign(y); let r = mut_x; assert_eq!(x.mod_op(y), r); let mut mut_x = x; mut_x %= y; assert_eq!(mut_x, r); assert_eq!(x % y, r); assert_eq!(x.div_mod(y).1, r); assert_eq!(x.div_rem(y).1, r); assert!(r < y); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.mod_op(T::ONE), T::ZERO); assert_panic!(x.mod_op(T::ZERO)); assert_panic!({ let mut y = x; y.mod_assign(T::ZERO); }); }); unsigned_gen_var_1::().test_properties(|x| { assert_eq!(x.mod_op(x), T::ZERO); assert_eq!(T::ZERO.mod_op(x), T::ZERO); if x > T::ONE { assert_eq!(T::ONE.mod_op(x), T::ONE); } }); } fn mod_properties_helper_signed() { signed_pair_gen_var_6::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.mod_assign(y); let r = mut_x; assert_eq!(x.mod_op(y), r); assert!(r.lt_abs(&y)); assert!(r == T::ZERO || (r > T::ZERO) == (y > T::ZERO)); if x != T::MIN { assert_eq!(x.ceiling_mod(y), -(-x).mod_op(y)); } if y != T::MIN { assert_eq!(x.ceiling_mod(y), x.mod_op(-y)); } }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!(x.mod_op(y), x.div_mod(y).1); }); signed_gen::().test_properties(|x| { assert_eq!(x.mod_op(T::ONE), T::ZERO); assert_eq!(x.mod_op(T::NEGATIVE_ONE), T::ZERO); assert_panic!(x.mod_op(T::ZERO)); assert_panic!({ let mut y = x; y.mod_assign(T::ZERO); }); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(x.mod_op(T::ONE), T::ZERO); assert_eq!(x.mod_op(x), T::ZERO); assert_eq!(T::ZERO.mod_op(x), T::ZERO); assert_eq!(x.mod_op(T::NEGATIVE_ONE), T::ZERO); if x != T::MIN { assert_eq!(x.mod_op(-x), T::ZERO); } if x > T::ONE { assert_eq!(T::ONE.mod_op(x), T::ONE); assert_eq!(T::NEGATIVE_ONE.mod_op(x), x - T::ONE); } }); } #[test] fn mod_properties() { apply_fn_to_unsigneds!(mod_properties_helper_unsigned); apply_fn_to_signeds!(mod_properties_helper_signed); } fn neg_mod_properties_helper() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.neg_mod_assign(y); let r = mut_x; assert_eq!(x.neg_mod(y), r); assert_eq!(x.ceiling_div_neg_mod(y).1, r); assert!(r < y); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.neg_mod(T::ONE), T::ZERO); assert_panic!(x.neg_mod(T::ZERO)); assert_panic!({ let mut y = x; y.neg_mod_assign(T::ZERO); }); }); unsigned_gen_var_1::().test_properties(|x| { assert_eq!(x.neg_mod(x), T::ZERO); assert_eq!(T::ZERO.neg_mod(x), T::ZERO); if x > T::ONE { assert_eq!(T::ONE.neg_mod(x), x - T::ONE); } }); } #[test] fn neg_mod_properties() { apply_fn_to_unsigneds!(neg_mod_properties_helper); } fn ceiling_mod_properties_helper() { signed_pair_gen_var_6::().test_properties(|(x, y)| { let mut mut_x = x; mut_x.ceiling_mod_assign(y); let r = mut_x; assert_eq!(x.ceiling_mod(y), r); assert!(r.lt_abs(&y)); assert!(r == T::ZERO || (r > T::ZERO) != (y > T::ZERO)); if x != T::MIN { assert_eq!(x.mod_op(y), -(-x).ceiling_mod(y)); } if y != T::MIN { assert_eq!(x.mod_op(y), x.ceiling_mod(-y)); } }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!(x.ceiling_mod(y), x.ceiling_div_mod(y).1); }); signed_gen::().test_properties(|x| { assert_eq!(x.ceiling_mod(T::ONE), T::ZERO); assert_eq!(x.ceiling_mod(T::NEGATIVE_ONE), T::ZERO); }); signed_gen_var_6::().test_properties(|x| { assert_eq!(x.ceiling_mod(T::ONE), T::ZERO); assert_eq!(x.ceiling_mod(T::NEGATIVE_ONE), T::ZERO); assert_eq!(x.ceiling_mod(x), T::ZERO); if x != T::MIN { assert_eq!(x.ceiling_mod(-x), T::ZERO); } assert_eq!(T::ZERO.ceiling_mod(x), T::ZERO); }); } #[test] fn ceiling_mod_properties() { apply_fn_to_signeds!(ceiling_mod_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_pow::simple_binary_mod_pow; use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen, unsigned_pair_gen_var_12, unsigned_pair_gen_var_16, unsigned_quadruple_gen_var_6, unsigned_quadruple_gen_var_7, unsigned_triple_gen_var_14, unsigned_triple_gen_var_15, }; use malachite_base::test_util::num::arithmetic::mod_pow::naive_mod_pow; use std::panic::catch_unwind; fn mod_pow_helper() { let test = |x: T, exp: u64, m, out| { assert_eq!(naive_mod_pow(x, exp, m), out); assert_eq!(simple_binary_mod_pow(x, exp, m), out); assert_eq!(x.mod_pow(exp, m), out); let mut mut_x = x; mut_x.mod_pow_assign(exp, m); assert_eq!(mut_x, out); let data = T::precompute_mod_pow_data(&m); assert_eq!(x.mod_pow_precomputed(exp, m, &data), out); let mut mut_x = x; mut_x.mod_pow_precomputed_assign(exp, m, &data); assert_eq!(mut_x, out); }; test(T::ZERO, 0, T::ONE, T::ZERO); test(T::ZERO, 0, T::exact_from(10), T::ONE); test(T::ZERO, 1, T::exact_from(10), T::ZERO); test(T::TWO, 10, T::exact_from(10), T::exact_from(4)); if T::WIDTH > u8::WIDTH { test(T::exact_from(4), 13, T::exact_from(497), T::exact_from(445)); test( T::exact_from(10), 1000, T::exact_from(30), T::exact_from(10), ); test(T::TWO, 340, T::exact_from(341), T::ONE); test(T::exact_from(5), 216, T::exact_from(217), T::ONE); } if T::WIDTH > u16::WIDTH { test( T::TWO, 1000000, T::exact_from(1000000000), T::exact_from(747109376), ); } } #[test] fn test_mod_pow() { apply_fn_to_unsigneds!(mod_pow_helper); } fn mod_pow_fail_helper() { assert_panic!(T::ZERO.mod_pow(10, T::ZERO)); assert_panic!(T::from(123u8).mod_pow(10, T::from(123u8))); } #[test] fn mod_pow_fail() { apply_fn_to_unsigneds!(mod_pow_fail_helper); } fn mod_pow_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_pow_assign(10, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_pow_assign(10, T::from(123u8)); }); } #[test] fn mod_pow_assign_fail() { apply_fn_to_unsigneds!(mod_pow_assign_fail_helper); } fn mod_pow_properties_helper_helper T>( x: T, exp: u64, m: T, f: F, ) { assert!(x.mod_is_reduced(&m)); let power = x.mod_pow(exp, m); assert!(power.mod_is_reduced(&m)); let mut x_alt = x; x_alt.mod_pow_assign(exp, m); assert_eq!(x_alt, power); let data = T::precompute_mod_pow_data(&m); assert_eq!(x.mod_pow_precomputed(exp, m, &data), power); let mut x_alt = x; x_alt.mod_pow_precomputed_assign(exp, m, &data); assert_eq!(x_alt, power); assert_eq!(f(x, exp, m), power); if exp.even() { assert_eq!(x.mod_neg(m).mod_pow(exp, m), power); } else { assert_eq!(x.mod_neg(m).mod_pow(exp, m), power.mod_neg(m)); } } fn mod_pow_properties_helper() { unsigned_triple_gen_var_15::().test_properties(|(x, exp, m)| { mod_pow_properties_helper_helper(x, exp, m, simple_binary_mod_pow); }); unsigned_triple_gen_var_14::() .test_properties(|(x, exp, m)| mod_pow_properties_helper_helper(x, exp, m, naive_mod_pow)); unsigned_pair_gen_var_12::().test_properties(|(exp, m)| { assert_eq!(T::ZERO.mod_pow(exp, m), T::from(exp == 0 && m != T::ONE)); if m != T::ONE { assert_eq!(T::ONE.mod_pow(exp, m), T::ONE); } }); unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert_eq!(x.mod_pow(0, m), T::from(m != T::ONE)); assert_eq!(x.mod_pow(1, m), x); assert_eq!(x.mod_pow(2, m), x.mod_mul(x, m)); }); unsigned_pair_gen::().test_properties(|(x, y)| { assert_panic!(x.mod_pow(y, T::ZERO)); assert_panic!({ let mut x = x; x.mod_pow_assign(y, T::ZERO); }); }); unsigned_quadruple_gen_var_6::().test_properties(|(x, y, exp, m)| { assert_eq!( x.mod_mul(y, m).mod_pow(exp, m), x.mod_pow(exp, m).mod_mul(y.mod_pow(exp, m), m) ); }); unsigned_quadruple_gen_var_7::().test_properties(|(x, e, f, m)| { if let Some(sum) = e.checked_add(f) { assert_eq!( x.mod_pow(sum, m), x.mod_pow(e, m).mod_mul(x.mod_pow(f, m), m) ); } if let Some(product) = e.checked_mul(f) { assert_eq!(x.mod_pow(product, m), x.mod_pow(e, m).mod_pow(f, m)); } }); } #[test] fn mod_pow_properties() { apply_fn_to_unsigneds!(mod_pow_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2IsReduced}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_4, signed_unsigned_pair_gen_var_10, signed_unsigned_pair_gen_var_11, unsigned_gen, unsigned_pair_gen_var_2, unsigned_pair_gen_var_20, unsigned_triple_gen_var_4, unsigned_triple_gen_var_13, }; use std::cmp::min; use std::fmt::Debug; use std::panic::catch_unwind; #[test] fn test_mod_power_of_2_and_rem_power_of_2_unsigned() { fn test(x: T, pow: u64, out: T) { assert_eq!(x.mod_power_of_2(pow), out); let mut mut_x = x; mut_x.mod_power_of_2_assign(pow); assert_eq!(mut_x, out); assert_eq!(x.rem_power_of_2(pow), out); let mut mut_x = x; mut_x.rem_power_of_2_assign(pow); assert_eq!(mut_x, out); } test::(0, 0, 0); test::(260, 8, 4); test::(1611, 4, 11); test::(123, 100, 123); test::(1000000000000, 0, 0); test::(1000000000000, 12, 0); test::(1000000000001, 12, 1); test::(999999999999, 12, 4095); test::(1000000000000, 15, 4096); test::(1000000000000, 100, 1000000000000); test::(1000000000000000000000000, 40, 1020608380928); test::(1000000000000000000000000, 64, 2003764205206896640); test::(u32::MAX, 31, 0x7fffffff); test::(u32::MAX, 32, u32::MAX); test::(0xffffffff, 33, 0xffffffff); test::(0x100000000, 31, 0); test::(0x100000000, 32, 0); test::(0x100000000, 33, 0x100000000); test::(0x100000001, 31, 1); test::(0x100000001, 32, 1); test::(0x100000001, 33, 0x100000001); } #[test] fn test_mod_power_of_2_signed() { fn test + PrimitiveSigned>( x: S, pow: u64, out: U, ) { assert_eq!(x.mod_power_of_2(pow), out); } test::<_, i8>(0, 0, 0); test::<_, i16>(2, 1, 0); test::<_, i32>(260, 8, 4); test::<_, i16>(1611, 4, 11); test::<_, i8>(123, 100, 123); test::<_, i64>(1000000000000, 0, 0); test::<_, i64>(1000000000000, 12, 0); test::<_, i64>(1000000000001, 12, 1); test::<_, i64>(999999999999, 12, 4095); test::<_, i64>(1000000000000, 15, 4096); test::<_, i64>(1000000000000, 100, 1000000000000); test::<_, i128>(1000000000000000000000000, 40, 1020608380928); test::<_, i128>(1000000000000000000000000, 64, 2003764205206896640); test::<_, i32>(0x7fffffff, 30, 0x3fffffff); test::<_, i32>(0x7fffffff, 31, 0x7fffffff); test::<_, isize>(0x7fffffff, 32, 0x7fffffff); test::<_, i64>(0x80000000, 30, 0); test::<_, i64>(0x80000000, 31, 0); test::<_, i64>(0x80000000, 32, 0x80000000); test::<_, i64>(0x80000001, 30, 1); test::<_, i64>(0x80000001, 31, 1); test::<_, i64>(0x80000001, 32, 0x80000001); test::<_, i64>(0xffffffff, 31, 0x7fffffff); test::<_, i64>(0xffffffff, 32, 0xffffffff); test::<_, i64>(0xffffffff, 33, 0xffffffff); test::<_, i64>(0x100000000, 31, 0); test::<_, i64>(0x100000000, 32, 0); test::<_, i64>(0x100000000, 33, 0x100000000); test::<_, i64>(0x100000001, 31, 1); test::<_, i64>(0x100000001, 32, 1); test::<_, i64>(0x100000001, 33, 0x100000001); test::<_, i8>(-2, 1, 0); test::<_, i16>(-260, 8, 252); test::<_, i32>(-1611, 4, 5); test::<_, i128>(-123, 100, 1267650600228229401496703205253); test::<_, i64>(-1000000000000, 0, 0); test::<_, i64>(-1000000000000, 12, 0); test::<_, i64>(-1000000000001, 12, 4095); test::<_, i64>(-999999999999, 12, 1); test::<_, i64>(-1000000000000, 15, 0x7000); test::<_, i128>(-1000000000000, 100, 1267650600228229400496703205376); test::<_, i128>(-1000000000000000000000000, 40, 78903246848); test::<_, i128>(-1000000000000000000000000, 64, 16442979868502654976); test::<_, i32>(-0x7fffffff, 30, 1); test::<_, i32>(-0x7fffffff, 31, 1); test::<_, i32>(-0x7fffffff, 32, 0x80000001); test::<_, isize>(-0x80000000, 30, 0); test::<_, isize>(-0x80000000, 31, 0); test::<_, isize>(-0x80000000, 32, 0x80000000); test::<_, i64>(-0x80000001, 30, 0x3fffffff); test::<_, i64>(-0x80000001, 31, 0x7fffffff); test::<_, i64>(-0x80000001, 32, 0x7fffffff); test::<_, i64>(-0xffffffff, 31, 1); test::<_, i64>(-0xffffffff, 32, 1); test::<_, i64>(-0xffffffff, 33, 0x100000001); test::<_, i64>(-0x100000000, 31, 0); test::<_, i64>(-0x100000000, 32, 0); test::<_, i64>(-0x100000000, 33, 0x100000000); test::<_, i64>(-0x100000001, 31, 0x7fffffff); test::<_, i64>(-0x100000001, 32, 0xffffffff); test::<_, i64>(-0x100000001, 33, 0xffffffff); } fn mod_power_of_2_signed_fail_helper() { assert_panic!(T::NEGATIVE_ONE.mod_power_of_2(200)); } #[test] fn mod_power_of_2_signed_fail() { apply_fn_to_signeds!(mod_power_of_2_signed_fail_helper); } #[test] fn test_mod_power_of_2_assign_signed() { fn test(x: T, pow: u64, out: T) { let mut mut_x = x; mut_x.mod_power_of_2_assign(pow); assert_eq!(mut_x, out); } test::(0, 0, 0); test::(2, 1, 0); test::(260, 8, 4); test::(1611, 4, 11); test::(123, 100, 123); test::(1000000000000, 0, 0); test::(1000000000000, 12, 0); test::(1000000000001, 12, 1); test::(999999999999, 12, 4095); test::(1000000000000, 15, 4096); test::(1000000000000, 100, 1000000000000); test::(1000000000000000000000000, 40, 1020608380928); test::(1000000000000000000000000, 64, 2003764205206896640); test::(0x7fffffff, 30, 0x3fffffff); test::(0x7fffffff, 31, 0x7fffffff); test::(0x7fffffff, 32, 0x7fffffff); test::(0x80000000, 30, 0); test::(0x80000000, 31, 0); test::(0x80000000, 32, 0x80000000); test::(0x80000001, 30, 1); test::(0x80000001, 31, 1); test::(0x80000001, 32, 0x80000001); test::(0xffffffff, 31, 0x7fffffff); test::(0xffffffff, 32, 0xffffffff); test::(0xffffffff, 33, 0xffffffff); test::(0x100000000, 31, 0); test::(0x100000000, 32, 0); test::(0x100000000, 33, 0x100000000); test::(0x100000001, 31, 1); test::(0x100000001, 32, 1); test::(0x100000001, 33, 0x100000001); test::(-2, 1, 0); test::(-260, 8, 252); test::(-1611, 4, 5); test::(-123, 100, 1267650600228229401496703205253); test::(-1000000000000, 0, 0); test::(-1000000000000, 12, 0); test::(-1000000000001, 12, 4095); test::(-999999999999, 12, 1); test::(-1000000000000, 15, 0x7000); test::(-1000000000000, 100, 1267650600228229400496703205376); test::(-1000000000000000000000000, 40, 78903246848); test::(-1000000000000000000000000, 64, 16442979868502654976); test::(-0x7fffffff, 30, 1); test::(-0x7fffffff, 31, 1); test::(-0x7fffffff, 32, 0x80000001); test::(-0x80000000, 30, 0); test::(-0x80000000, 31, 0); test::(-0x80000000, 32, 0x80000000); test::(-0x80000001, 30, 0x3fffffff); test::(-0x80000001, 31, 0x7fffffff); test::(-0x80000001, 32, 0x7fffffff); test::(-0xffffffff, 31, 1); test::(-0xffffffff, 32, 1); test::(-0xffffffff, 33, 0x100000001); test::(-0x100000000, 31, 0); test::(-0x100000000, 32, 0); test::(-0x100000000, 33, 0x100000000); test::(-0x100000001, 31, 0x7fffffff); test::(-0x100000001, 32, 0xffffffff); test::(-0x100000001, 33, 0xffffffff); } fn mod_power_of_2_assign_signed_fail_helper() { assert_panic!({ let mut x = T::NEGATIVE_ONE; x.mod_power_of_2_assign(200); }); assert_panic!({ let mut x = T::MIN; x.mod_power_of_2_assign(T::WIDTH); }); } #[test] fn mod_power_of_2_assign_signed_fail() { apply_fn_to_signeds!(mod_power_of_2_assign_signed_fail_helper); } #[test] fn test_rem_power_of_2_signed() { fn test(x: T, pow: u64, out: T) { assert_eq!(x.rem_power_of_2(pow), out); let mut mut_x = x; mut_x.rem_power_of_2_assign(pow); assert_eq!(mut_x, out); } test::(0, 0, 0); test::(2, 1, 0); test::(260, 8, 4); test::(1611, 4, 11); test::(123, 100, 123); test::(1000000000000, 0, 0); test::(1000000000000, 12, 0); test::(1000000000001, 12, 1); test::(999999999999, 12, 4095); test::(1000000000000, 15, 4096); test::(1000000000000, 100, 1000000000000); test::(1000000000000000000000000, 40, 1020608380928); test::(1000000000000000000000000, 64, 2003764205206896640); test::(0x7fffffff, 30, 0x3fffffff); test::(0x7fffffff, 31, 0x7fffffff); test::(0x7fffffff, 32, 0x7fffffff); test::(0x80000000, 30, 0); test::(0x80000000, 31, 0); test::(0x80000000, 32, 0x80000000); test::(0x80000001, 30, 1); test::(0x80000001, 31, 1); test::(0x80000001, 32, 0x80000001); test::(0xffffffff, 31, 0x7fffffff); test::(0xffffffff, 32, 0xffffffff); test::(0xffffffff, 33, 0xffffffff); test::(0x100000000, 31, 0); test::(0x100000000, 32, 0); test::(0x100000000, 33, 0x100000000); test::(0x100000001, 31, 1); test::(0x100000001, 32, 1); test::(0x100000001, 33, 0x100000001); test::(-2, 1, 0); test::(-260, 8, -4); test::(-1611, 4, -11); test::(-123, 100, -123); test::(-1000000000000, 0, 0); test::(-1000000000000, 12, 0); test::(-1000000000001, 12, -1); test::(-999999999999, 12, -4095); test::(-1000000000000, 15, -4096); test::(-1000000000000, 100, -1000000000000); test::(-1000000000000000000000000, 40, -1020608380928); test::(-1000000000000000000000000, 64, -2003764205206896640); test::(-0x7fffffff, 30, -0x3fffffff); test::(-0x7fffffff, 31, -0x7fffffff); test::(-0x7fffffff, 32, -0x7fffffff); test::(-0x80000000, 30, 0); test::(-0x80000000, 31, 0); test::(-0x80000000, 32, -0x80000000); test::(-0x80000001, 30, -1); test::(-0x80000001, 31, -1); test::(-0x80000001, 32, -0x80000001); test::(-0xffffffff, 31, -0x7fffffff); test::(-0xffffffff, 32, -0xffffffff); test::(-0xffffffff, 33, -0xffffffff); test::(-0x100000000, 31, 0); test::(-0x100000000, 32, 0); test::(-0x100000000, 33, -0x100000000); test::(-0x100000001, 31, -1); test::(-0x100000001, 32, -1); test::(-0x100000001, 33, -0x100000001); } #[test] fn test_neg_mod_power_of_2_unsigned() { fn test(x: T, pow: u64, out: T) { assert_eq!(x.neg_mod_power_of_2(pow), out); let mut mut_x = x; mut_x.neg_mod_power_of_2_assign(pow); assert_eq!(mut_x, out); } test::(0, 0, 0); test::(260, 8, 252); test::(1611, 4, 5); test::(1, 32, u32::MAX); test::(123, 100, 1267650600228229401496703205253); test::(1000000000000, 0, 0); test::(1000000000000, 12, 0); test::(1000000000001, 12, 4095); test::(999999999999, 12, 1); test::(1000000000000, 15, 0x7000); test::(1000000000000, 100, 1267650600228229400496703205376); test::(1000000000000000000000000, 40, 78903246848); test::(1000000000000000000000000, 64, 16442979868502654976); test::(u32::MAX, 31, 1); test::(0xffffffff, 32, 1); test::(0xffffffff, 33, 0x100000001); test::(0x100000000, 31, 0); test::(0x100000000, 32, 0); test::(0x100000000, 33, 0x100000000); test::(0x100000001, 31, 0x7fffffff); test::(0x100000001, 32, 0xffffffff); test::(0x100000001, 33, 0xffffffff); } fn neg_mod_power_of_2_fail_helper() { assert_panic!(T::ONE.neg_mod_power_of_2(200)); assert_panic!(T::MAX.neg_mod_power_of_2(T::WIDTH + 1)); assert_panic!({ let mut x = T::ONE; x.neg_mod_power_of_2_assign(200); }); assert_panic!({ let mut x = T::MAX; x.neg_mod_power_of_2_assign(T::WIDTH + 1); }); } #[test] fn neg_mod_power_of_2_fail() { apply_fn_to_unsigneds!(neg_mod_power_of_2_fail_helper); } #[test] fn test_ceiling_mod_power_of_2_signed() { fn test(x: T, pow: u64, out: T) { assert_eq!(x.ceiling_mod_power_of_2(pow), out); let mut mut_x = x; mut_x.ceiling_mod_power_of_2_assign(pow); assert_eq!(mut_x, out); } test::(0, 0, 0); test::(2, 1, 0); test::(260, 8, -252); test::(1611, 4, -5); test::(123, 100, -1267650600228229401496703205253); test::(1000000000000, 0, 0); test::(1000000000000, 12, 0); test::(1000000000001, 12, -4095); test::(999999999999, 12, -1); test::(1000000000000, 15, -0x7000); test::(1000000000000, 100, -1267650600228229400496703205376); test::(1000000000000000000000000, 40, -78903246848); test::(1000000000000000000000000, 64, -16442979868502654976); test::(0x7fffffff, 30, -1); test::(0x7fffffff, 31, -1); test::(0x7fffffff, 32, -0x80000001); test::(0x80000000, 30, 0); test::(0x80000000, 31, 0); test::(0x80000000, 32, -0x80000000); test::(0x80000001, 30, -0x3fffffff); test::(0x80000001, 31, -0x7fffffff); test::(0x80000001, 32, -0x7fffffff); test::(0xffffffff, 31, -1); test::(0xffffffff, 32, -1); test::(0xffffffff, 33, -0x100000001); test::(0x100000000, 31, 0); test::(0x100000000, 32, 0); test::(0x100000000, 33, -0x100000000); test::(0x100000001, 31, -0x7fffffff); test::(0x100000001, 32, -0xffffffff); test::(0x100000001, 33, -0xffffffff); test::(-2, 1, 0); test::(-260, 8, -4); test::(-1611, 4, -11); test::(-123, 100, -123); test::(-1000000000000, 0, 0); test::(-1000000000000, 12, 0); test::(-1000000000001, 12, -1); test::(-999999999999, 12, -4095); test::(-1000000000000, 15, -4096); test::(-1000000000000, 100, -1000000000000); test::(-1000000000000000000000000, 40, -1020608380928); test::(-1000000000000000000000000, 64, -2003764205206896640); test::(-0x7fffffff, 30, -0x3fffffff); test::(-0x7fffffff, 31, -0x7fffffff); test::(-0x7fffffff, 32, -0x7fffffff); test::(-0x80000000, 31, 0); test::(-0x80000000, 30, 0); test::(-0x80000000, 31, 0); test::(-0x80000000, 32, -0x80000000); test::(-0x80000001, 30, -1); test::(-0x80000001, 31, -1); test::(-0x80000001, 32, -0x80000001); test::(-0xffffffff, 31, -0x7fffffff); test::(-0xffffffff, 32, -0xffffffff); test::(-0xffffffff, 33, -0xffffffff); test::(-0x100000000, 31, 0); test::(-0x100000000, 32, 0); test::(-0x100000000, 33, -0x100000000); test::(-0x100000001, 31, -1); test::(-0x100000001, 32, -1); test::(-0x100000001, 33, -0x100000001); } fn ceiling_mod_power_of_2_fail_helper() { assert_panic!(T::ONE.ceiling_mod_power_of_2(T::WIDTH)); assert_panic!(T::MIN.ceiling_mod_power_of_2(T::WIDTH)); assert_panic!({ let mut x = T::ONE; x.ceiling_mod_power_of_2_assign(T::WIDTH); }); assert_panic!({ let mut x = T::MIN; x.ceiling_mod_power_of_2_assign(T::WIDTH); }); } #[test] fn ceiling_mod_power_of_2_fail() { apply_fn_to_signeds!(ceiling_mod_power_of_2_fail_helper); } fn mod_power_of_2_properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { let mut mut_n = n; mut_n.mod_power_of_2_assign(pow); let result = mut_n; assert!(result.mod_power_of_2_is_reduced(pow)); assert_eq!(n.mod_power_of_2(pow), result); let mut mut_n = n; mut_n.rem_power_of_2_assign(pow); assert_eq!(mut_n, result); assert_eq!(n.rem_power_of_2(pow), result); assert!(result <= n); assert_eq!(result == T::ZERO, n.divisible_by_power_of_2(pow)); assert_eq!(result.mod_power_of_2(pow), result); }); unsigned_triple_gen_var_4::().test_properties(|(x, y, pow)| { assert_eq!( x.wrapping_add(y).mod_power_of_2(pow), x.mod_power_of_2(pow) .wrapping_add(y.mod_power_of_2(pow)) .mod_power_of_2(pow) ); assert_eq!( x.wrapping_mul(y).mod_power_of_2(pow), x.mod_power_of_2(pow) .wrapping_mul(y.mod_power_of_2(pow)) .mod_power_of_2(pow) ); }); unsigned_triple_gen_var_13::().test_properties(|(n, u, v)| { assert_eq!( n.mod_power_of_2(u).mod_power_of_2(v), n.mod_power_of_2(min(u, v)) ); }); unsigned_gen::().test_properties(|n| { assert_eq!(n.mod_power_of_2(0), T::ZERO); }); unsigned_gen().test_properties(|pow| { assert_eq!(T::ZERO.mod_power_of_2(pow), T::ZERO); }); } fn mod_power_of_2_properties_helper_signed() where ::Output: ExactFrom + PrimitiveUnsigned, { signed_unsigned_pair_gen_var_10::().test_properties(|(n, pow)| { let result = n.mod_power_of_2(pow); assert!(result.mod_power_of_2_is_reduced(pow)); assert_eq!( result == ::Output::ZERO, n.divisible_by_power_of_2(pow) ); assert_eq!(result.mod_power_of_2(pow), result); }); signed_unsigned_pair_gen_var_4::().test_properties(|(n, pow)| { let mut mut_n = n; mut_n.mod_power_of_2_assign(pow); let result = mut_n; assert_eq!( n.mod_power_of_2(pow), ::Output::exact_from(result) ); assert!(result >= T::ZERO); assert_eq!(result == T::ZERO, n.divisible_by_power_of_2(pow)); assert_eq!( result.mod_power_of_2(pow), ::Output::exact_from(result) ); }); signed_gen::().test_properties(|n| { assert_eq!(n.mod_power_of_2(0), ::Output::ZERO); }); unsigned_gen().test_properties(|pow| { assert_eq!( T::ZERO.mod_power_of_2(pow), ::Output::ZERO ); }); } #[test] fn mod_power_of_2_properties() { apply_fn_to_unsigneds!(mod_power_of_2_properties_helper_unsigned); apply_fn_to_signeds!(mod_power_of_2_properties_helper_signed); } fn rem_power_of_2_properties_helper() { signed_unsigned_pair_gen_var_1::().test_properties(|(n, pow)| { let mut mut_n = n; mut_n.rem_power_of_2_assign(pow); let result = mut_n; assert_eq!(n.rem_power_of_2(pow), result); if n != T::MIN { assert_eq!((-n).rem_power_of_2(pow), -result); } assert!(result.le_abs(&n)); assert_eq!(result == T::ZERO, n.divisible_by_power_of_2(pow)); assert_eq!(result.rem_power_of_2(pow), result); assert!(result == T::ZERO || (result > T::ZERO) == (n > T::ZERO)); }); signed_gen::().test_properties(|n| { assert_eq!(n.rem_power_of_2(0), T::ZERO); }); unsigned_gen().test_properties(|pow| { assert_eq!(T::ZERO.rem_power_of_2(pow), T::ZERO); }); } #[test] fn rem_power_of_2_properties() { apply_fn_to_signeds!(rem_power_of_2_properties_helper); } fn neg_mod_power_of_2_properties_helper() { unsigned_pair_gen_var_20::().test_properties(|(n, pow)| { let mut mut_n = n; mut_n.neg_mod_power_of_2_assign(pow); let result = mut_n; assert!(result.mod_power_of_2_is_reduced(pow)); assert_eq!(n.neg_mod_power_of_2(pow), result); assert_eq!(result == T::ZERO, n.divisible_by_power_of_2(pow)); assert!( result .wrapping_add(n.mod_power_of_2(pow)) .divisible_by_power_of_2(pow) ); assert_eq!(result.neg_mod_power_of_2(pow), n.mod_power_of_2(pow)); }); unsigned_gen::().test_properties(|n| { assert_eq!(n.neg_mod_power_of_2(0), T::ZERO); }); unsigned_gen().test_properties(|pow| { assert_eq!(T::ZERO.neg_mod_power_of_2(pow), T::ZERO); }); } #[test] fn neg_mod_power_of_2_properties() { apply_fn_to_unsigneds!(neg_mod_power_of_2_properties_helper); } fn ceiling_mod_power_of_2_properties_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { signed_unsigned_pair_gen_var_11::().test_properties(|(n, pow)| { let mut mut_n = n; mut_n.ceiling_mod_power_of_2_assign(pow); let result = mut_n; assert_eq!(n.ceiling_mod_power_of_2(pow), result); assert!(result <= S::ZERO); assert_eq!(result == S::ZERO, n.divisible_by_power_of_2(pow)); }); signed_gen::().test_properties(|n| { assert_eq!(n.ceiling_mod_power_of_2(0), S::ZERO); }); unsigned_gen().test_properties(|pow| { assert_eq!(S::ZERO.ceiling_mod_power_of_2(pow), S::ZERO); }); } #[test] fn ceiling_mod_power_of_2_properties() { apply_fn_to_unsigned_signed_pairs!(ceiling_mod_power_of_2_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_17, unsigned_quadruple_gen_var_3, unsigned_triple_gen_var_11, }; use std::panic::catch_unwind; fn mod_power_of_2_add_helper() { let test = |x: T, y: T, pow, out| { assert_eq!(x.mod_power_of_2_add(y, pow), out); let mut x = x; x.mod_power_of_2_add_assign(y, pow); assert_eq!(x, out); }; test(T::ZERO, T::ZERO, 0, T::ZERO); test(T::ZERO, T::ONE, 1, T::ONE); test(T::ONE, T::ONE, 1, T::ZERO); test(T::ZERO, T::TWO, 5, T::TWO); test(T::exact_from(10), T::exact_from(14), 4, T::exact_from(8)); test(T::exact_from(100), T::exact_from(200), 8, T::exact_from(44)); test(T::MAX, T::ONE, T::WIDTH, T::ZERO); test(T::MAX, T::MAX, T::WIDTH, T::MAX - T::ONE); } #[test] fn test_mod_power_of_2_add() { apply_fn_to_unsigneds!(mod_power_of_2_add_helper); } fn mod_power_of_2_add_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_add(T::ZERO, 0)); assert_panic!(T::ZERO.mod_power_of_2_add(T::ONE, 0)); assert_panic!(T::from(123u8).mod_power_of_2_add(T::from(200u8), 7)); assert_panic!(T::from(200u8).mod_power_of_2_add(T::from(123u8), 7)); } #[test] fn mod_power_of_2_add_fail() { apply_fn_to_unsigneds!(mod_power_of_2_add_fail_helper); } fn mod_power_of_2_add_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_add_assign(T::ZERO, 0); }); assert_panic!({ let mut x = T::ZERO; x.mod_power_of_2_add_assign(T::ONE, 0); }); assert_panic!({ let mut x = T::from(123u8); x.mod_power_of_2_add_assign(T::from(200u8), 7); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_add_assign(T::from(123u8), 7); }); } #[test] fn mod_power_of_2_add_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_add_assign_fail_helper); } fn mod_power_of_2_add_properties_helper() { unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let sum = x.mod_power_of_2_add(y, pow); assert!(sum.mod_power_of_2_is_reduced(pow)); let mut x_alt = x; x_alt.mod_power_of_2_add_assign(y, pow); assert_eq!(x_alt, sum); assert_eq!(sum.mod_power_of_2_sub(y, pow), x); assert_eq!(sum.mod_power_of_2_sub(x, pow), y); assert_eq!(y.mod_power_of_2_add(x, pow), sum); assert_eq!(x.mod_power_of_2_sub(y.mod_power_of_2_neg(pow), pow), sum); }); unsigned_pair_gen_var_17::().test_properties(|(x, pow)| { assert_eq!(x.mod_power_of_2_add(T::ZERO, pow), x); assert_eq!(T::ZERO.mod_power_of_2_add(x, pow), x); assert_eq!( x.mod_power_of_2_add(x.mod_power_of_2_neg(pow), pow), T::ZERO ); }); unsigned_quadruple_gen_var_3::().test_properties(|(x, y, z, pow)| { assert_eq!( x.mod_power_of_2_add(y, pow).mod_power_of_2_add(z, pow), x.mod_power_of_2_add(y.mod_power_of_2_add(z, pow), pow) ); }); } #[test] fn mod_power_of_2_add_properties() { apply_fn_to_unsigneds!(mod_power_of_2_add_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::mod_power_of_2_inverse::mod_power_of_2_inverse_fast; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{unsigned_gen_var_3, unsigned_pair_gen_var_39}; use malachite_base::test_util::num::arithmetic::mod_power_of_2_inverse::*; use std::panic::catch_unwind; fn mod_power_of_2_inverse_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { let test = |n: U, pow, out| { assert_eq!(n.mod_power_of_2_inverse(pow), out); assert_eq!(mod_power_of_2_inverse_euclidean::(n, pow), out); assert_eq!(mod_power_of_2_inverse_fast(n, pow), out); }; test(U::ONE, 5, Some(U::ONE)); test(U::exact_from(7), 5, Some(U::exact_from(23))); test(U::exact_from(31), 5, Some(U::exact_from(31))); test(U::ONE, U::WIDTH, Some(U::ONE)); test(U::MAX, U::WIDTH, Some(U::MAX)); } #[test] fn test_mod_power_of_2_inverse() { apply_fn_to_unsigned_signed_pairs!(mod_power_of_2_inverse_helper); } fn mod_power_of_2_inverse_fail_helper() { assert_panic!(T::ZERO.mod_power_of_2_inverse(5)); assert_panic!(T::from(30u8).mod_power_of_2_inverse(3)); assert_panic!(T::from(3u8).mod_power_of_2_inverse(200)); assert_panic!(T::ONE.mod_power_of_2_inverse(0)); assert_panic!(T::from(200u8).mod_power_of_2_inverse(7)); } #[test] fn mod_power_of_2_inverse_fail() { apply_fn_to_unsigneds!(mod_power_of_2_inverse_fail_helper); } fn mod_power_of_2_inverse_properties_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { unsigned_pair_gen_var_39::().test_properties(|(n, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let inverse = n.mod_power_of_2_inverse(pow); assert_eq!(mod_power_of_2_inverse_euclidean::(n, pow), inverse); assert_eq!(mod_power_of_2_inverse_fast(n, pow), inverse); assert_eq!(inverse.is_some(), n.odd()); if let Some(inverse) = inverse { assert!(inverse.mod_power_of_2_is_reduced(pow)); assert_eq!(inverse.mod_power_of_2_inverse(pow), Some(n)); assert_eq!(n.mod_power_of_2_mul(inverse, pow), U::ONE); assert_eq!( n.mod_power_of_2_neg(pow).mod_power_of_2_inverse(pow), Some(inverse.mod_power_of_2_neg(pow)) ); } }); unsigned_gen_var_3::().test_properties(|pow| { assert_eq!(U::ONE.mod_power_of_2_inverse(pow), Some(U::ONE)); assert_eq!( U::low_mask(pow).mod_power_of_2_inverse(pow), Some(U::low_mask(pow)) ); }); } #[test] fn mod_power_of_2_inverse_properties() { apply_fn_to_unsigned_signed_pairs!(mod_power_of_2_inverse_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::unsigned_pair_gen_var_2; fn mod_power_of_2_is_reduced_helper() { let test = |n: T, pow, out| { assert_eq!(n.mod_power_of_2_is_reduced(pow), out); }; test(T::ZERO, 5, true); test(T::exact_from(100), 5, false); test(T::exact_from(100), 8, true); test(T::MAX, T::WIDTH - 1, false); test(T::MAX, T::WIDTH, true); } #[test] fn test_mod_power_of_2_is_reduced() { apply_fn_to_unsigneds!(mod_power_of_2_is_reduced_helper); } fn mod_power_of_2_is_reduced_properties_helper() { unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { assert_eq!(n.mod_power_of_2_is_reduced(pow), n.mod_power_of_2(pow) == n); }); } #[test] fn mod_power_of_2_is_reduced_properties() { apply_fn_to_unsigneds!(mod_power_of_2_is_reduced_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_17, unsigned_quadruple_gen_var_3, unsigned_triple_gen_var_11, }; use std::panic::catch_unwind; fn mod_power_of_2_mul_helper() { let test = |x: T, y: T, pow, out| { assert_eq!(x.mod_power_of_2_mul(y, pow), out); let mut x = x; x.mod_power_of_2_mul_assign(y, pow); assert_eq!(x, out); }; test(T::ZERO, T::ZERO, 0, T::ZERO); test(T::ZERO, T::ONE, 1, T::ZERO); test(T::ONE, T::ONE, 1, T::ONE); test(T::exact_from(3), T::TWO, 5, T::exact_from(6)); test(T::exact_from(10), T::exact_from(14), 4, T::exact_from(12)); test(T::exact_from(100), T::exact_from(200), 8, T::exact_from(32)); test(T::ONE << (T::WIDTH - 1), T::TWO, T::WIDTH, T::ZERO); test(T::MAX, T::MAX, T::WIDTH, T::ONE); } #[test] fn test_mod_power_of_2_mul() { apply_fn_to_unsigneds!(mod_power_of_2_mul_helper); } fn mod_power_of_2_mul_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_mul(T::ZERO, 0)); assert_panic!(T::ZERO.mod_power_of_2_mul(T::ONE, 0)); assert_panic!(T::from(123u8).mod_power_of_2_mul(T::from(200u8), 7)); assert_panic!(T::from(200u8).mod_power_of_2_mul(T::from(123u8), 7)); } #[test] fn mod_power_of_2_mul_fail() { apply_fn_to_unsigneds!(mod_power_of_2_mul_fail_helper); } fn mod_power_of_2_mul_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_mul_assign(T::ZERO, 0); }); assert_panic!({ let mut x = T::ZERO; x.mod_power_of_2_mul_assign(T::ONE, 0); }); assert_panic!({ let mut x = T::from(123u8); x.mod_power_of_2_mul_assign(T::from(200u8), 7); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_mul_assign(T::from(123u8), 7); }); } #[test] fn mod_power_of_2_mul_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_mul_assign_fail_helper); } fn mod_power_of_2_mul_properties_helper() { unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let product = x.mod_power_of_2_mul(y, pow); assert!(product.mod_power_of_2_is_reduced(pow)); let mut x_alt = x; x_alt.mod_power_of_2_mul_assign(y, pow); assert_eq!(x_alt, product); assert_eq!(y.mod_power_of_2_mul(x, pow), product); assert_eq!( x.mod_power_of_2_mul(y.mod_power_of_2_neg(pow), pow), product.mod_power_of_2_neg(pow) ); assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_mul(y, pow), product.mod_power_of_2_neg(pow) ); }); unsigned_pair_gen_var_17::().test_properties(|(x, pow)| { assert_eq!(x.mod_power_of_2_mul(T::ZERO, pow), T::ZERO); assert_eq!(T::ZERO.mod_power_of_2_mul(x, pow), T::ZERO); if pow != 0 { assert_eq!(x.mod_power_of_2_mul(T::ONE, pow), x); assert_eq!(T::ONE.mod_power_of_2_mul(x, pow), x); } }); unsigned_quadruple_gen_var_3::().test_properties(|(x, y, z, pow)| { assert_eq!( x.mod_power_of_2_mul(y, pow).mod_power_of_2_mul(z, pow), x.mod_power_of_2_mul(y.mod_power_of_2_mul(z, pow), pow) ); assert_eq!( x.mod_power_of_2_mul(y.mod_power_of_2_add(z, pow), pow), x.mod_power_of_2_mul(y, pow) .mod_power_of_2_add(x.mod_power_of_2_mul(z, pow), pow) ); assert_eq!( x.mod_power_of_2_add(y, pow).mod_power_of_2_mul(z, pow), x.mod_power_of_2_mul(z, pow) .mod_power_of_2_add(y.mod_power_of_2_mul(z, pow), pow) ); }); } #[test] fn mod_power_of_2_mul_properties() { apply_fn_to_unsigneds!(mod_power_of_2_mul_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::unsigned_pair_gen_var_17; use std::panic::catch_unwind; fn mod_power_of_2_neg_helper() { let test = |n: T, pow, out| { assert_eq!(n.mod_power_of_2_neg(pow), out); let mut n = n; n.mod_power_of_2_neg_assign(pow); assert_eq!(n, out); }; test(T::ZERO, 5, T::ZERO); test(T::exact_from(10), 4, T::exact_from(6)); test(T::exact_from(100), 8, T::exact_from(156)); test(T::ONE, T::WIDTH, T::MAX); test(T::MAX, T::WIDTH, T::ONE); } #[test] fn test_mod_power_of_2_neg() { apply_fn_to_unsigneds!(mod_power_of_2_neg_helper); } fn mod_power_of_2_neg_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_neg(0)); assert_panic!(T::from(200u8).mod_power_of_2_neg(7)); } #[test] fn mod_power_of_2_neg_fail() { apply_fn_to_unsigneds!(mod_power_of_2_neg_fail_helper); } fn mod_power_of_2_neg_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_neg_assign(0); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_neg_assign(7); }); } #[test] fn mod_power_of_2_neg_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_neg_assign_fail_helper); } fn mod_power_of_2_neg_properties_helper() { unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let neg = n.mod_power_of_2_neg(pow); assert!(neg.mod_power_of_2_is_reduced(pow)); let mut n_alt = n; n_alt.mod_power_of_2_neg_assign(pow); assert_eq!(n_alt, neg); assert_eq!(neg, n.wrapping_neg().mod_power_of_2(pow)); assert_eq!(neg.mod_power_of_2_neg(pow), n); assert_eq!(n.mod_power_of_2_add(neg, pow), T::ZERO); assert_eq!(n == neg, n == T::ZERO || n == T::power_of_2(pow - 1)); }); } #[test] fn mod_power_of_2_neg_properties() { apply_fn_to_unsigneds!(mod_power_of_2_neg_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_17, unsigned_pair_gen_var_23, unsigned_quadruple_gen_var_8, unsigned_quadruple_gen_var_9, unsigned_triple_gen_var_16, }; use std::panic::catch_unwind; fn mod_power_of_2_pow_helper() { let test = |x: T, exp: u64, pow: u64, out| { assert_eq!(x.mod_power_of_2_pow(exp, pow), out); let mut mut_x = x; mut_x.mod_power_of_2_pow_assign(exp, pow); assert_eq!(mut_x, out); }; test(T::ZERO, 0, 0, T::ZERO); test(T::ZERO, 0, 3, T::ONE); test(T::ZERO, 1, 3, T::ZERO); test(T::TWO, 2, 3, T::exact_from(4)); test(T::exact_from(5), 13, 3, T::exact_from(5)); test(T::exact_from(7), 1000, 6, T::ONE); test(T::exact_from(101), 1000000, 8, T::ONE); } #[test] fn test_mod_power_of_2_pow() { apply_fn_to_unsigneds!(mod_power_of_2_pow_helper); } fn mod_power_of_2_pow_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_pow(10, 0)); assert_panic!(T::from(200u8).mod_power_of_2_pow(10, 7)); } #[test] fn mod_power_of_2_pow_fail() { apply_fn_to_unsigneds!(mod_power_of_2_pow_fail_helper); } fn mod_power_of_2_pow_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_pow_assign(10, 0); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_pow_assign(10, 7); }); } #[test] fn mod_power_of_2_pow_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_pow_assign_fail_helper); } fn mod_power_of_2_pow_properties_helper() { unsigned_triple_gen_var_16::().test_properties(|(x, exp, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); let power = x.mod_power_of_2_pow(exp, pow); assert!(power.mod_power_of_2_is_reduced(pow)); let mut x_alt = x; x_alt.mod_power_of_2_pow_assign(exp, pow); assert_eq!(x_alt, power); if exp.even() { assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_pow(exp, pow), power ); } else { assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_pow(exp, pow), power.mod_power_of_2_neg(pow) ); } }); unsigned_pair_gen_var_23::().test_properties(|(exp, pow)| { assert_eq!( T::ZERO.mod_power_of_2_pow(exp, pow), T::from(exp == 0 && pow != 0) ); if pow != 0 { assert_eq!(T::ONE.mod_power_of_2_pow(exp, pow), T::ONE); } }); unsigned_pair_gen_var_17::().test_properties(|(x, pow)| { assert_eq!(x.mod_power_of_2_pow(0, pow), T::from(pow != 0)); assert_eq!(x.mod_power_of_2_pow(1, pow), x); assert_eq!(x.mod_power_of_2_pow(2, pow), x.mod_power_of_2_mul(x, pow)); }); unsigned_quadruple_gen_var_8::().test_properties(|(x, y, exp, pow)| { assert_eq!( x.mod_power_of_2_mul(y, pow).mod_power_of_2_pow(exp, pow), x.mod_power_of_2_pow(exp, pow) .mod_power_of_2_mul(y.mod_power_of_2_pow(exp, pow), pow) ); }); unsigned_quadruple_gen_var_9::().test_properties(|(x, e, f, pow)| { if let Some(sum) = e.checked_add(f) { assert_eq!( x.mod_power_of_2_pow(sum, pow), x.mod_power_of_2_pow(e, pow) .mod_power_of_2_mul(x.mod_power_of_2_pow(f, pow), pow) ); } if let Some(product) = e.checked_mul(f) { assert_eq!( x.mod_power_of_2_pow(product, pow), x.mod_power_of_2_pow(e, pow).mod_power_of_2_pow(f, pow) ); } }); } #[test] fn mod_power_of_2_pow_properties() { apply_fn_to_unsigneds!(mod_power_of_2_pow_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_12, unsigned_pair_gen_var_17, unsigned_pair_gen_var_23, unsigned_signed_unsigned_triple_gen_var_1, unsigned_triple_gen_var_17, }; use std::panic::catch_unwind; #[test] fn test_mod_power_of_2_shl() { fn test< T: ModPowerOf2Shl + ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveInt, >( t: T, u: U, pow: u64, out: T, ) { assert_eq!(t.mod_power_of_2_shl(u, pow), out); let mut t = t; t.mod_power_of_2_shl_assign(u, pow); assert_eq!(t, out); } test::(0, 0, 0, 0); test::(0, 0, 5, 0); test::(12, 2, 5, 16); test::(10, 100, 4, 0); test::(10, -2, 4, 2); test::(10, -100, 4, 0); test::(10, -100, 4, 0); } fn mod_power_of_2_shl_fail_helper< T: PrimitiveUnsigned + ModPowerOf2Shl, U: PrimitiveInt, >() { assert_panic!(T::ONE.mod_power_of_2_shl(U::TWO, 0)); assert_panic!(T::from(200u8).mod_power_of_2_shl(U::TWO, 7)); } #[test] fn mod_power_of_2_shl_fail() { apply_fn_to_unsigneds_and_primitive_ints!(mod_power_of_2_shl_fail_helper); } fn mod_power_of_2_shl_assign_fail_helper< T: PrimitiveUnsigned + ModPowerOf2ShlAssign, U: PrimitiveInt, >() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_shl_assign(U::TWO, 0); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_shl_assign(U::TWO, 7); }); } #[test] fn mod_power_of_2_shl_assign_fail() { apply_fn_to_unsigneds_and_primitive_ints!(mod_power_of_2_shl_assign_fail_helper); } fn mod_power_of_2_shl_properties_unsigned_unsigned_helper< T: ArithmeticCheckedShl + ModPowerOf2Shl + ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_triple_gen_var_17::().test_properties(|(n, u, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let shifted = n.mod_power_of_2_shl(u, pow); assert!(shifted.mod_power_of_2_is_reduced(pow)); let mut shifted_alt = n; shifted_alt.mod_power_of_2_shl_assign(u, pow); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shl(u) { assert_eq!(shifted_alt.mod_power_of_2(pow), shifted); } }); unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert_eq!(n.mod_power_of_2_shl(U::ZERO, pow), n); }); unsigned_pair_gen_var_23::().test_properties(|(u, pow)| { assert_eq!(T::ZERO.mod_power_of_2_shl(u, pow), T::ZERO); }); } fn mod_power_of_2_shl_properties_unsigned_signed_helper< T: ArithmeticCheckedShl + ModPowerOf2Shl + ModPowerOf2Shr + ModPowerOf2ShlAssign + PrimitiveUnsigned, U: PrimitiveSigned, >() { unsigned_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let shifted = n.mod_power_of_2_shl(i, pow); assert!(shifted.mod_power_of_2_is_reduced(pow)); let mut shifted_alt = n; shifted_alt.mod_power_of_2_shl_assign(i, pow); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shl(i) { assert_eq!(shifted_alt.mod_power_of_2(pow), shifted); } if i != U::MIN { assert_eq!(n.mod_power_of_2_shr(-i, pow), shifted); } }); unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert_eq!(n.mod_power_of_2_shl(U::ZERO, pow), n); }); signed_unsigned_pair_gen_var_12::().test_properties(|(i, pow)| { assert_eq!(T::ZERO.mod_power_of_2_shl(i, pow), T::ZERO); }); } #[test] fn mod_power_of_2_shl_properties() { apply_fn_to_unsigneds_and_unsigneds!(mod_power_of_2_shl_properties_unsigned_unsigned_helper); apply_fn_to_unsigneds_and_signeds!(mod_power_of_2_shl_properties_unsigned_signed_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShr, ModPowerOf2Shl, ModPowerOf2Shr, ModPowerOf2ShrAssign, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_12, unsigned_pair_gen_var_17, unsigned_signed_unsigned_triple_gen_var_1, }; use std::panic::catch_unwind; #[test] fn test_mod_power_of_2_shr() { fn test< T: ModPowerOf2Shr + ModPowerOf2ShrAssign + PrimitiveUnsigned, U: PrimitiveSigned, >( t: T, u: U, pow: u64, out: T, ) { assert_eq!(t.mod_power_of_2_shr(u, pow), out); let mut t = t; t.mod_power_of_2_shr_assign(u, pow); assert_eq!(t, out); } test::(0, 0, 0, 0); test::(0, 0, 5, 0); test::(12, -2, 5, 16); test::(10, -100, 4, 0); test::(10, 2, 4, 2); test::(10, 100, 4, 0); test::(10, 100, 4, 0); } fn mod_power_of_2_shr_fail_helper< T: PrimitiveUnsigned + ModPowerOf2Shr, U: PrimitiveSigned, >() { assert_panic!(T::ONE.mod_power_of_2_shr(U::TWO, 0)); assert_panic!(T::from(200u8).mod_power_of_2_shr(U::TWO, 7)); } #[test] fn mod_power_of_2_shr_fail() { apply_fn_to_unsigneds_and_signeds!(mod_power_of_2_shr_fail_helper); } fn mod_power_of_2_shr_assign_fail_helper< T: PrimitiveUnsigned + ModPowerOf2ShrAssign, U: PrimitiveSigned, >() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_shr_assign(U::TWO, 0); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_shr_assign(U::TWO, 7); }); } #[test] fn mod_power_of_2_shr_assign_fail() { apply_fn_to_unsigneds_and_signeds!(mod_power_of_2_shr_assign_fail_helper); } fn mod_power_of_2_shl_properties_helper< T: ArithmeticCheckedShr + ModPowerOf2Shl + ModPowerOf2Shr + ModPowerOf2ShrAssign + PrimitiveUnsigned, U: PrimitiveSigned, >() { unsigned_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let shifted = n.mod_power_of_2_shr(i, pow); assert!(shifted.mod_power_of_2_is_reduced(pow)); let mut shifted_alt = n; shifted_alt.mod_power_of_2_shr_assign(i, pow); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shr(i) { assert_eq!(shifted_alt.mod_power_of_2(pow), shifted); } if i != U::MIN { assert_eq!(n.mod_power_of_2_shl(-i, pow), shifted); } }); unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert_eq!(n.mod_power_of_2_shr(U::ZERO, pow), n); }); signed_unsigned_pair_gen_var_12::().test_properties(|(i, pow)| { assert_eq!(T::ZERO.mod_power_of_2_shr(i, pow), T::ZERO); }); } #[test] fn mod_power_of_2_shl_properties() { apply_fn_to_unsigneds_and_signeds!(mod_power_of_2_shl_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen_var_9, unsigned_pair_gen_var_17, unsigned_triple_gen_var_11, }; use std::panic::catch_unwind; fn mod_power_of_2_square_helper() { let test = |x: T, pow: u64, out| { assert_eq!(x.mod_power_of_2_square(pow), out); let mut mut_x = x; mut_x.mod_power_of_2_square_assign(pow); assert_eq!(mut_x, out); }; test(T::ZERO, 0, T::ZERO); test(T::ZERO, 2, T::ZERO); test(T::ONE, 2, T::ONE); test(T::TWO, 2, T::ZERO); test(T::TWO, 3, T::exact_from(4)); test(T::exact_from(5), 3, T::ONE); test(T::exact_from(100), 8, T::exact_from(16)); } #[test] fn test_mod_power_of_2_square() { apply_fn_to_unsigneds!(mod_power_of_2_square_helper); } fn mod_power_of_2_square_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_square(0)); assert_panic!(T::from(200u8).mod_power_of_2_square(7)); } #[test] fn mod_power_of_2_square_fail() { apply_fn_to_unsigneds!(mod_power_of_2_square_fail_helper); } fn mod_power_of_2_square_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_square_assign(0); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_square_assign(7); }); } #[test] fn mod_power_of_2_square_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_square_assign_fail_helper); } fn mod_power_of_2_square_properties_helper() { unsigned_pair_gen_var_17::().test_properties(|(x, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); let square = x.mod_power_of_2_square(pow); assert!(square.mod_power_of_2_is_reduced(pow)); let mut x_alt = x; x_alt.mod_power_of_2_square_assign(pow); assert_eq!(x_alt, square); assert_eq!(x.mod_power_of_2_pow(2, pow), x.mod_power_of_2_mul(x, pow)); assert_eq!(x.mod_power_of_2_neg(pow).mod_power_of_2_square(pow), square); }); unsigned_gen_var_9::().test_properties(|pow| { assert_eq!(T::ZERO.mod_power_of_2_square(pow), T::ZERO); if pow != 0 { assert_eq!(T::ONE.mod_power_of_2_square(pow), T::ONE); } }); unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert_eq!( x.mod_power_of_2_mul(y, pow).mod_power_of_2_square(pow), x.mod_power_of_2_square(pow) .mod_power_of_2_mul(y.mod_power_of_2_square(pow), pow) ); }); } #[test] fn mod_power_of_2_square_properties() { apply_fn_to_unsigneds!(mod_power_of_2_square_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{unsigned_pair_gen_var_17, unsigned_triple_gen_var_11}; use std::panic::catch_unwind; fn mod_power_of_2_sub_helper() { let test = |x: T, y: T, pow, out| { assert_eq!(x.mod_power_of_2_sub(y, pow), out); let mut x = x; x.mod_power_of_2_sub_assign(y, pow); assert_eq!(x, out); }; test(T::ZERO, T::ZERO, 0, T::ZERO); test(T::ZERO, T::ONE, 1, T::ONE); test(T::ONE, T::ONE, 1, T::ZERO); test(T::exact_from(5), T::TWO, 5, T::exact_from(3)); test(T::exact_from(10), T::exact_from(14), 4, T::exact_from(12)); test( T::exact_from(100), T::exact_from(200), 8, T::exact_from(156), ); test(T::ZERO, T::ONE, T::WIDTH, T::MAX); test(T::ONE, T::MAX, T::WIDTH, T::TWO); } #[test] fn test_mod_power_of_2_sub() { apply_fn_to_unsigneds!(mod_power_of_2_sub_helper); } fn mod_power_of_2_sub_fail_helper() { assert_panic!(T::ONE.mod_power_of_2_sub(T::ZERO, 0)); assert_panic!(T::ZERO.mod_power_of_2_sub(T::ONE, 0)); assert_panic!(T::from(123u8).mod_power_of_2_sub(T::from(200u8), 7)); assert_panic!(T::from(200u8).mod_power_of_2_sub(T::from(123u8), 7)); } #[test] fn mod_power_of_2_sub_fail() { apply_fn_to_unsigneds!(mod_power_of_2_sub_fail_helper); } fn mod_power_of_2_sub_assign_fail_helper() { assert_panic!({ let mut x = T::ONE; x.mod_power_of_2_sub_assign(T::ZERO, 0); }); assert_panic!({ let mut x = T::ZERO; x.mod_power_of_2_sub_assign(T::ONE, 0); }); assert_panic!({ let mut x = T::from(123u8); x.mod_power_of_2_sub_assign(T::from(200u8), 7); }); assert_panic!({ let mut x = T::from(200u8); x.mod_power_of_2_sub_assign(T::from(123u8), 7); }); } #[test] fn mod_power_of_2_sub_assign_fail() { apply_fn_to_unsigneds!(mod_power_of_2_sub_assign_fail_helper); } fn mod_power_of_2_sub_properties_helper() { unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let diff = x.mod_power_of_2_sub(y, pow); assert!(diff.mod_power_of_2_is_reduced(pow)); let mut x_alt = x; x_alt.mod_power_of_2_sub_assign(y, pow); assert_eq!(x_alt, diff); assert_eq!(diff.mod_power_of_2_add(y, pow), x); assert_eq!(diff.mod_power_of_2_sub(x, pow), y.mod_power_of_2_neg(pow)); assert_eq!(y.mod_power_of_2_sub(x, pow), diff.mod_power_of_2_neg(pow)); assert_eq!(x.mod_power_of_2_add(y.mod_power_of_2_neg(pow), pow), diff); }); unsigned_pair_gen_var_17::().test_properties(|(x, pow)| { assert_eq!(x.mod_power_of_2_sub(T::ZERO, pow), x); assert_eq!( T::ZERO.mod_power_of_2_sub(x, pow), x.mod_power_of_2_neg(pow) ); assert_eq!(x.mod_power_of_2_sub(x, pow), T::ZERO); }); } #[test] fn mod_power_of_2_sub_properties() { apply_fn_to_unsigneds!(mod_power_of_2_sub_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, ModShl, ModShlAssign, ModShr}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_gen_var_5, signed_unsigned_pair_gen_var_13, unsigned_gen_var_5, unsigned_pair_gen_var_2, unsigned_pair_gen_var_16, unsigned_pair_gen_var_25, unsigned_signed_pair_gen_var_1, unsigned_signed_unsigned_triple_gen_var_2, unsigned_triple_gen_var_18, }; use std::panic::catch_unwind; #[test] fn test_mod_shl() { fn test< T: ModShl + ModShlAssign + PrimitiveUnsigned, U: PrimitiveInt, >( t: T, u: U, m: T, out: T, ) { assert_eq!(t.mod_shl(u, m), out); let mut t = t; t.mod_shl_assign(u, m); assert_eq!(t, out); } test::(0, 0, 1, 0); test::(0, 0, 5, 0); test::(8, 2, 10, 2); test::(10, 100, 17, 7); test::(10, -2, 15, 2); test::(10, -100, 19, 0); test::(10, -100, 19, 0); } fn mod_shl_fail_helper, U: PrimitiveInt>() { assert_panic!(T::ZERO.mod_shl(U::TWO, T::ZERO)); assert_panic!(T::from(123u8).mod_shl(U::TWO, T::from(123u8))); } #[test] fn mod_shl_fail() { apply_fn_to_unsigneds_and_primitive_ints!(mod_shl_fail_helper); } fn mod_shl_assign_fail_helper, U: PrimitiveInt>() { assert_panic!({ let mut x = T::ZERO; x.mod_shl_assign(U::TWO, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_shl_assign(U::TWO, T::from(123u8)); }); } #[test] fn mod_shl_assign_fail() { apply_fn_to_unsigneds_and_primitive_ints!(mod_shl_assign_fail_helper); } fn mod_shl_properties_unsigned_unsigned_helper< T: ArithmeticCheckedShl + ModShl + ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_triple_gen_var_18::().test_properties(|(n, u, m)| { assert!(n.mod_is_reduced(&m)); let shifted = n.mod_shl(u, m); assert!(shifted.mod_is_reduced(&m)); let mut shifted_alt = n; shifted_alt.mod_shl_assign(u, m); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shl(u) { assert_eq!(shifted_alt % m, shifted); } }); unsigned_pair_gen_var_16::().test_properties(|(n, m)| { assert_eq!(n.mod_shl(U::ZERO, m), n); }); unsigned_pair_gen_var_25::().test_properties(|(u, m)| { assert_eq!(T::ZERO.mod_shl(u, m), T::ZERO); }); unsigned_pair_gen_var_2::().test_properties(|(n, u)| { assert_panic!(n.mod_shl(u, T::ZERO)); assert_panic!({ let mut n = n; n.mod_shl_assign(u, T::ZERO); }); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(T::ZERO.mod_shl(u, T::ONE), T::ZERO); }); } fn mod_shl_properties_unsigned_signed_helper< T: ArithmeticCheckedShl + ModShl + ModShr + ModShlAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { unsigned_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, m)| { assert!(n.mod_is_reduced(&m)); let shifted = n.mod_shl(i, m); assert!(shifted.mod_is_reduced(&m)); let mut shifted_alt = n; shifted_alt.mod_shl_assign(i, m); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shl(i) { assert_eq!(shifted_alt % m, shifted); } if i != S::MIN { assert_eq!(n.mod_shr(-i, m), shifted); } }); unsigned_pair_gen_var_16::().test_properties(|(n, m)| { assert_eq!(n.mod_shl(S::ZERO, m), n); }); signed_unsigned_pair_gen_var_13::().test_properties(|(i, m)| { assert_eq!(T::ZERO.mod_shl(i, m), T::ZERO); }); unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { assert_panic!(n.mod_shl(i, T::ZERO)); assert_panic!({ let mut n = n; n.mod_shl_assign(i, T::ZERO); }); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.mod_shl(i, T::ONE), T::ZERO); }); } #[test] fn mod_shl_properties() { apply_fn_to_unsigneds_and_unsigneds!(mod_shl_properties_unsigned_unsigned_helper); apply_fn_to_unsigneds_and_unsigned_signed_pairs!(mod_shl_properties_unsigned_signed_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShr, ModShl, ModShr, ModShrAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::test_util::generators::{ signed_gen_var_5, signed_unsigned_pair_gen_var_13, unsigned_pair_gen_var_16, unsigned_signed_pair_gen_var_1, unsigned_signed_unsigned_triple_gen_var_2, }; use std::panic::catch_unwind; #[test] fn test_mod_shr() { fn test< T: ModShr + ModShrAssign + PrimitiveUnsigned, U: PrimitiveInt, >( t: T, i: U, m: T, out: T, ) { assert_eq!(t.mod_shr(i, m), out); let mut t = t; t.mod_shr_assign(i, m); assert_eq!(t, out); } test::(0, 0, 1, 0); test::(0, 0, 5, 0); test::(8, -2, 10, 2); test::(10, -100, 17, 7); test::(10, 2, 15, 2); test::(10, 100, 19, 0); test::(10, 100, 19, 0); } fn mod_shr_fail_helper, U: PrimitiveSigned>() { assert_panic!(T::ZERO.mod_shr(U::TWO, T::ZERO)); assert_panic!(T::from(123u8).mod_shr(U::TWO, T::from(123u8))); } #[test] fn mod_shr_fail() { apply_fn_to_unsigneds_and_signeds!(mod_shr_fail_helper); } fn mod_shr_assign_fail_helper, U: PrimitiveSigned>() { assert_panic!({ let mut x = T::ZERO; x.mod_shr_assign(U::TWO, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_shr_assign(U::TWO, T::from(123u8)); }); } #[test] fn mod_shr_assign_fail() { apply_fn_to_unsigneds_and_signeds!(mod_shr_assign_fail_helper); } fn mod_shr_properties_helper< T: ArithmeticCheckedShr + ModShl + ModShr + ModShrAssign + PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { unsigned_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, m)| { assert!(n.mod_is_reduced(&m)); let shifted = n.mod_shr(i, m); assert!(shifted.mod_is_reduced(&m)); let mut shifted_alt = n; shifted_alt.mod_shr_assign(i, m); assert_eq!(shifted_alt, shifted); if let Some(shifted_alt) = n.arithmetic_checked_shr(i) { assert_eq!(shifted_alt % m, shifted); } if i != S::MIN { assert_eq!(n.mod_shl(-i, m), shifted); } }); unsigned_pair_gen_var_16::().test_properties(|(n, m)| { assert_eq!(n.mod_shr(S::ZERO, m), n); }); signed_unsigned_pair_gen_var_13::().test_properties(|(i, m)| { assert_eq!(T::ZERO.mod_shr(i, m), T::ZERO); }); unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| { assert_panic!(n.mod_shr(i, T::ZERO)); assert_panic!({ let mut n = n; n.mod_shr_assign(i, T::ZERO); }); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(T::ZERO.mod_shl(i, T::ONE), T::ZERO); }); } #[test] fn mod_shr_properties() { apply_fn_to_unsigneds_and_unsigned_signed_pairs!(mod_shr_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_16, unsigned_triple_gen_var_12, }; use std::panic::catch_unwind; fn mod_square_helper() { let test = |x: T, m, out| { assert_eq!(x.mod_mul(x, m), out); assert_eq!(x.mod_square(m), out); let mut mut_x = x; mut_x.mod_square_assign(m); assert_eq!(mut_x, out); let data = T::precompute_mod_pow_data(&m); assert_eq!(x.mod_square_precomputed(m, &data), out); let mut mut_x = x; mut_x.mod_square_precomputed_assign(m, &data); assert_eq!(mut_x, out); }; test(T::ZERO, T::ONE, T::ZERO); test(T::ONE, T::exact_from(10), T::ONE); test(T::TWO, T::exact_from(10), T::exact_from(4)); if T::WIDTH > u8::WIDTH { test(T::exact_from(100), T::exact_from(497), T::exact_from(60)); test(T::exact_from(200), T::exact_from(497), T::exact_from(240)); test(T::exact_from(300), T::exact_from(497), T::exact_from(43)); } } #[test] fn test_mod_square() { apply_fn_to_unsigneds!(mod_square_helper); } fn mod_square_fail_helper() { assert_panic!(T::ZERO.mod_square(T::ZERO)); assert_panic!(T::from(123u8).mod_square(T::from(123u8))); } #[test] fn mod_square_fail() { apply_fn_to_unsigneds!(mod_square_fail_helper); } fn mod_square_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_square_assign(T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_square_assign(T::from(123u8)); }); } #[test] fn mod_square_assign_fail() { apply_fn_to_unsigneds!(mod_square_assign_fail_helper); } fn mod_square_properties_helper() { unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert!(x.mod_is_reduced(&m)); let square = x.mod_square(m); assert!(square.mod_is_reduced(&m)); let mut x_alt = x; x_alt.mod_square_assign(m); assert_eq!(x_alt, square); let data = T::precompute_mod_pow_data(&m); assert_eq!(x.mod_square_precomputed(m, &data), square); let mut x_alt = x; x_alt.mod_square_precomputed_assign(m, &data); assert_eq!(x_alt, square); assert_eq!(x.mod_mul(x, m), square); assert_eq!(x.mod_neg(m).mod_square(m), square); }); unsigned_gen_var_1::().test_properties(|m| { assert_eq!(T::ZERO.mod_square(m), T::ZERO); if m != T::ONE { assert_eq!(T::ONE.mod_square(m), T::ONE); } }); unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert_eq!( x.mod_mul(y, m).mod_square(m), x.mod_square(m).mod_mul(y.mod_square(m), m) ); }); unsigned_gen::().test_properties(|x| { assert_panic!(x.mod_square(T::ZERO)); }); } #[test] fn mod_square_properties() { apply_fn_to_unsigneds!(mod_square_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_16, unsigned_pair_gen_var_27, unsigned_triple_gen_var_12, }; use std::panic::catch_unwind; fn mod_sub_helper() { let test = |x: T, y: T, m, out| { assert_eq!(x.mod_sub(y, m), out); let mut x = x; x.mod_sub_assign(y, m); assert_eq!(x, out); }; test(T::ZERO, T::ZERO, T::ONE, T::ZERO); test(T::exact_from(4), T::exact_from(3), T::exact_from(5), T::ONE); test( T::exact_from(7), T::exact_from(9), T::exact_from(10), T::exact_from(8), ); test( T::exact_from(100), T::exact_from(120), T::exact_from(123), T::exact_from(103), ); test(T::ZERO, T::ONE, T::MAX, T::MAX - T::ONE); test(T::MAX - T::TWO, T::MAX - T::ONE, T::MAX, T::MAX - T::ONE); } #[test] fn test_mod_sub() { apply_fn_to_unsigneds!(mod_sub_helper); } fn mod_sub_fail_helper() { assert_panic!(T::ZERO.mod_sub(T::ZERO, T::ZERO)); assert_panic!(T::from(123u8).mod_sub(T::from(200u8), T::from(200u8))); assert_panic!(T::from(200u8).mod_sub(T::from(123u8), T::from(200u8))); } #[test] fn mod_sub_fail() { apply_fn_to_unsigneds!(mod_sub_fail_helper); } fn mod_sub_assign_fail_helper() { assert_panic!({ let mut x = T::ZERO; x.mod_sub_assign(T::ZERO, T::ZERO); }); assert_panic!({ let mut x = T::from(123u8); x.mod_sub_assign(T::from(200u8), T::from(200u8)); }); assert_panic!({ let mut x = T::from(200u8); x.mod_sub_assign(T::from(123u8), T::from(200u8)); }); } #[test] fn mod_sub_assign_fail() { apply_fn_to_unsigneds!(mod_sub_assign_fail_helper); } fn mod_sub_properties_helper() { unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let diff = x.mod_sub(y, m); assert!(diff.mod_is_reduced(&m)); let mut x_alt = x; x_alt.mod_sub_assign(y, m); assert_eq!(x_alt, diff); assert_eq!(diff.mod_add(y, m), x); assert_eq!(diff.mod_sub(x, m), y.mod_neg(m)); assert_eq!(y.mod_sub(x, m), diff.mod_neg(m)); assert_eq!(x.mod_add(y.mod_neg(m), m), diff); }); unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert_eq!(x.mod_sub(T::ZERO, m), x); assert_eq!(T::ZERO.mod_sub(x, m), x.mod_neg(m)); assert_eq!(x.mod_sub(x, m), T::ZERO); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_panic!(x.mod_sub(y, T::ZERO)); assert_panic!({ let mut x = x; x.mod_sub_assign(y, T::ZERO); }); }); } #[test] fn mod_sub_properties() { apply_fn_to_unsigneds!(mod_sub_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen_var_1}; fn neg_assign_helper_signed() { let test = |n: T, out| { let mut n = n; n.neg_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::NEGATIVE_ONE); test(T::exact_from(100), T::exact_from(-100)); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); } fn neg_assign_helper_primitive_float() { let test = |x: T, out| { let mut x = x; x.neg_assign(); assert_eq!(NiceFloat(x), NiceFloat(out)); }; test(T::ZERO, T::NEGATIVE_ZERO); test(T::NEGATIVE_ZERO, T::ZERO); test(T::INFINITY, T::NEGATIVE_INFINITY); test(T::NEGATIVE_INFINITY, T::INFINITY); test(T::NAN, T::NAN); test(T::ONE, T::NEGATIVE_ONE); test(T::from(100.0), T::from(-100.0)); test(T::NEGATIVE_ONE, T::ONE); test(T::from(-100.0), T::from(100.0)); } #[test] fn test_neg_assign() { apply_fn_to_signeds!(neg_assign_helper_signed); apply_fn_to_primitive_floats!(neg_assign_helper_primitive_float); } fn neg_assign_properties_helper_signed() { signed_gen_var_1::().test_properties(|n| { let mut neg = n; neg.neg_assign(); assert_eq!(neg, -n); assert_eq!(-neg, n); assert_eq!(neg == n, n == T::ZERO); assert_eq!(n + neg, T::ZERO); }); } fn neg_assign_properties_helper_primitive_float() { primitive_float_gen::().test_properties(|x| { let mut neg = x; neg.neg_assign(); assert_eq!(NiceFloat(neg), NiceFloat(-x)); assert_eq!(NiceFloat(-neg), NiceFloat(x)); assert_eq!(NiceFloat(neg) == NiceFloat(x), x.is_nan()); if x.is_finite() { assert_eq!(x + neg, T::ZERO); } }); } #[test] fn neg_assign_properties() { apply_fn_to_signeds!(neg_assign_properties_helper_signed); apply_fn_to_primitive_floats!(neg_assign_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{primitive_float_gen_var_19, unsigned_gen_var_14}; use std::panic::catch_unwind; fn next_power_of_2_helper_unsigned() { let test = |n: T, out| { assert_eq!(n.next_power_of_2(), out); let mut n = n; n.next_power_of_2_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ONE); test(T::ONE, T::ONE); test(T::exact_from(7), T::exact_from(8)); test(T::exact_from(8), T::exact_from(8)); test(T::exact_from(10), T::exact_from(16)); test((T::MAX >> 1u64) + T::ONE, (T::MAX >> 1u64) + T::ONE); test( (T::MAX >> 1u64) - T::exact_from(10), (T::MAX >> 1u64) + T::ONE, ); } fn next_power_of_2_helper_primitive_float() { let test = |n: T, out| { assert_eq!(NiceFloat(n.next_power_of_2()), NiceFloat(out)); let mut n = n; n.next_power_of_2_assign(); assert_eq!(NiceFloat(n), NiceFloat(out)); }; test(T::ZERO, T::MIN_POSITIVE_SUBNORMAL); test(T::ONE, T::ONE); test(T::from(7.0f32), T::from(8.0f32)); test(T::from(8.0f32), T::from(8.0f32)); test(T::from(10.0f32), T::from(16.0f32)); test(T::from(0.1f32), T::from(0.125f32)); test(T::from(0.01f32), T::from(0.015625f32)); test( T::power_of_2(T::MAX_EXPONENT), T::power_of_2(T::MAX_EXPONENT), ); } #[test] fn test_next_power_of_2() { apply_fn_to_unsigneds!(next_power_of_2_helper_unsigned); apply_fn_to_primitive_floats!(next_power_of_2_helper_primitive_float); } fn next_power_of_2_fail_helper_primitive_float() { assert_panic!(T::NEGATIVE_ZERO.next_power_of_2()); assert_panic!(T::INFINITY.next_power_of_2()); assert_panic!(T::NEGATIVE_INFINITY.next_power_of_2()); assert_panic!(T::NAN.next_power_of_2()); assert_panic!(T::NEGATIVE_ONE.next_power_of_2()); assert_panic!(T::MAX_FINITE.next_power_of_2()); let test = |x: T| { let mut x = x; x.next_power_of_2_assign(); }; assert_panic!(test(T::NEGATIVE_ZERO)); assert_panic!(test(T::INFINITY)); assert_panic!(test(T::NEGATIVE_INFINITY)); assert_panic!(test(T::NAN)); assert_panic!(test(T::NEGATIVE_ONE)); assert_panic!(test(T::MAX_FINITE)); } #[test] fn next_power_of_2_fail() { apply_fn_to_primitive_floats!(next_power_of_2_fail_helper_primitive_float); } fn next_power_of_2_properties_helper_unsigned() { unsigned_gen_var_14::().test_properties(|n| { let p = n.next_power_of_2(); assert!(p >= n); assert!(p >> 1 <= n); assert!(p.is_power_of_2()); let mut n = n; n.next_power_of_2_assign(); assert_eq!(n, p); }); } fn next_power_of_2_properties_helper_primitive_float() { primitive_float_gen_var_19::().test_properties(|x| { let p = x.next_power_of_2(); assert!(p >= x); assert!(p / T::TWO <= x); assert!(p.is_power_of_2()); let mut x = x; x.next_power_of_2_assign(); assert_eq!(x, p); }); } #[test] fn next_power_of_2_properties() { apply_fn_to_unsigneds!(next_power_of_2_properties_helper_unsigned); apply_fn_to_primitive_floats!(next_power_of_2_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::generators::signed_gen; fn overflowing_abs_helper() { let test = |n: T, out, overflow| { assert_eq!(n.overflowing_abs(), (out, overflow)); let mut n = n; assert_eq!(n.overflowing_abs_assign(), overflow); assert_eq!(n, out); }; test(T::ZERO, T::ZERO, false); test(T::ONE, T::ONE, false); test(T::exact_from(100), T::exact_from(100), false); test(T::MAX, T::MAX, false); test(T::NEGATIVE_ONE, T::ONE, false); test(T::exact_from(-100), T::exact_from(100), false); test(T::MIN, T::MIN, true); } #[test] fn test_overflowing_abs() { apply_fn_to_signeds!(overflowing_abs_helper); } fn overflowing_abs_properties_helper() { signed_gen::().test_properties(|n| { let mut abs = n; let overflow = abs.overflowing_abs_assign(); assert_eq!((abs, overflow), n.overflowing_abs()); assert_eq!(abs, n.wrapping_abs()); if n != T::MIN { assert_eq!(n.abs(), abs); } assert_eq!(abs == n, n >= T::ZERO || n == T::MIN); assert_eq!(n == T::MIN, overflow); }); } #[test] fn overflowing_abs_properties() { apply_fn_to_signeds!(overflowing_abs_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_overflowing_add() { fn test(x: T, y: T, out: T, overflow: bool) { assert_eq!(x.overflowing_add(y), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_add_assign(y), overflow); assert_eq!(x, out); } test::(123, 456, 579, false); test::(123, 200, 67, true); test::(123, -456, -333, false); test::(123, 45, -88, true); test::(-123, -45, 88, true); } fn overflowing_add_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut sum = x; let overflow = sum.overflowing_add_assign(y); assert_eq!((sum, overflow), x.overflowing_add(y)); assert_eq!(x.wrapping_add(y), sum); if !overflow { assert_eq!(sum, x + y); } }); } fn overflowing_add_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut sum = x; let overflow = sum.overflowing_add_assign(y); assert_eq!((sum, overflow), x.overflowing_add(y)); assert_eq!(x.wrapping_add(y), sum); if !overflow { assert_eq!(sum, x + y); } }); } #[test] fn overflowing_add_properties() { apply_fn_to_unsigneds!(overflowing_add_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_add_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_overflowing_add_mul() { fn test(x: T, y: T, z: T, out: T, overflow: bool) { assert_eq!(x.overflowing_add_mul(y, z), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_add_mul_assign(y, z), overflow); assert_eq!(x, out); } test::(2, 3, 7, 23, false); test::(7, 5, 10, 57, false); test::(123, 456, 789, 359907, false); test::(123, -456, 789, -359661, false); test::(-123, 456, 789, 359661, false); test::(127, -2, 100, -73, false); test::(-127, 2, 100, 73, false); test::(-128, 1, 0, -128, false); test::(2, 20, 20, 146, true); test::(-127, -2, 100, -71, true); test::(127, 1, 100, -29, true); test::(-127, -1, 100, 29, true); test::(-127, -10, 100, -103, true); } fn overflowing_add_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let (result, overflow) = x.overflowing_add_mul(y, z); let mut x_alt = x; assert_eq!(x_alt.overflowing_add_mul_assign(y, z), overflow); assert_eq!(x_alt, result); assert_eq!(x.overflowing_add_mul(z, y), (result, overflow)); assert_eq!(result.overflowing_sub_mul(y, z), (x, overflow)); assert_eq!(x.wrapping_add_mul(y, z), result); assert_eq!(x.checked_add_mul(y, z).is_none(), overflow); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.overflowing_add_mul(T::ZERO, b), (a, false)); assert_eq!(a.overflowing_add_mul(T::ONE, b), a.overflowing_add(b)); assert_eq!(T::ZERO.overflowing_add_mul(a, b), a.overflowing_mul(b)); assert_eq!(a.overflowing_add_mul(b, T::ZERO), (a, false)); assert_eq!(a.overflowing_add_mul(b, T::ONE), a.overflowing_add(b)); }); } fn overflowing_add_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let (result, overflow) = x.overflowing_add_mul(y, z); let mut x_alt = x; assert_eq!(x_alt.overflowing_add_mul_assign(y, z), overflow); assert_eq!(x_alt, result); assert_eq!(x.overflowing_add_mul(z, y), (result, overflow)); assert_eq!(result.overflowing_sub_mul(y, z), (x, overflow)); assert_eq!(x.wrapping_add_mul(y, z), result); assert_eq!(x.checked_add_mul(y, z).is_none(), overflow); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.overflowing_add_mul(T::ZERO, b), (a, false)); assert_eq!(a.overflowing_add_mul(T::ONE, b), a.overflowing_add(b)); assert_eq!(T::ZERO.overflowing_add_mul(a, b), a.overflowing_mul(b)); assert_eq!(a.overflowing_add_mul(b, T::ZERO), (a, false)); assert_eq!(a.overflowing_add_mul(b, T::ONE), a.overflowing_add(b)); }); } #[test] fn overflowing_add_mul_properties() { apply_fn_to_unsigneds!(overflowing_add_mul_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_add_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_div.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen_var_6, unsigned_pair_gen_var_12}; use std::panic::catch_unwind; #[test] fn test_overflowing_div() { fn test(x: T, y: T, out: T, overflow: bool) { assert_eq!(x.overflowing_div(y), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_div_assign(y), overflow); assert_eq!(x, out); } test::(0, 5, 0, false); test::(123, 456, 0, false); test::(100, 3, 33, false); test::(100, -3, -33, false); test::(-100, 3, -33, false); test::(-100, -3, 33, false); test::(-128, -1, -128, true); } fn overflowing_div_assign_fail_helper() { assert_panic!({ let mut n = T::ONE; n.overflowing_div_assign(T::ZERO); }); } #[test] fn overflowing_div_assign_fail() { apply_fn_to_primitive_ints!(overflowing_div_assign_fail_helper); } fn overflowing_div_properties_helper_unsigned() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut quotient = x; let overflow = quotient.overflowing_div_assign(y); assert_eq!((quotient, overflow), x.overflowing_div(y)); assert_eq!(x.wrapping_div(y), quotient); assert!(!overflow); assert_eq!(quotient, x / y); }); } fn overflowing_div_properties_helper_signed() { signed_pair_gen_var_6::().test_properties(|(x, y)| { let mut quotient = x; let overflow = quotient.overflowing_div_assign(y); assert_eq!((quotient, overflow), x.overflowing_div(y)); assert_eq!(x.wrapping_div(y), quotient); if !overflow { assert_eq!(quotient, x / y); } }); } #[test] fn overflowing_div_properties() { apply_fn_to_unsigneds!(overflowing_div_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_div_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_overflowing_mul() { fn test(x: T, y: T, out: T, overflow: bool) { assert_eq!(x.overflowing_mul(y), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_mul_assign(y), overflow); assert_eq!(x, out); } test::(123, 456, 56088, false); test::(123, 200, 24, true); test::(123, -45, -5535, false); test::(123, 45, -97, true); test::(-123, 45, 97, true); } fn overflowing_mul_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut product = x; let overflow = product.overflowing_mul_assign(y); assert_eq!((product, overflow), x.overflowing_mul(y)); assert_eq!(x.wrapping_mul(y), product); if !overflow { assert_eq!(product, x * y); } }); } fn overflowing_mul_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut product = x; let overflow = product.overflowing_mul_assign(y); assert_eq!((product, overflow), x.overflowing_mul(y)); assert_eq!(x.wrapping_mul(y), product); if !overflow { assert_eq!(product, x * y); } }); } #[test] fn overflowing_mul_properties() { apply_fn_to_unsigneds!(overflowing_mul_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; fn unsigned_overflowing_neg_helper() { let test = |n: T, out, overflow| { assert_eq!(n.overflowing_neg(), (out, overflow)); let mut n = n; assert_eq!(n.overflowing_neg_assign(), overflow); assert_eq!(n, out); }; test(T::ZERO, T::ZERO, false); test(T::ONE, T::MAX, true); test( T::exact_from(100), T::MAX - T::exact_from(100) + T::ONE, true, ); test(T::MAX, T::ONE, true); } fn signed_overflowing_neg_helper() { let test = |n: T, out, overflow| { assert_eq!(n.overflowing_neg(), (out, overflow)); let mut n = n; assert_eq!(n.overflowing_neg_assign(), overflow); assert_eq!(n, out); }; test(T::ZERO, T::ZERO, false); test(T::ONE, T::NEGATIVE_ONE, false); test(T::exact_from(100), T::exact_from(-100), false); test(T::MAX, T::MIN + T::ONE, false); test(T::NEGATIVE_ONE, T::ONE, false); test(T::exact_from(-100), T::exact_from(100), false); test(T::MIN, T::MIN, true); } #[test] fn test_overflowing_neg() { apply_fn_to_unsigneds!(unsigned_overflowing_neg_helper); apply_fn_to_signeds!(signed_overflowing_neg_helper); } fn overflowing_neg_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let mut neg = n; let overflow = neg.overflowing_neg_assign(); assert_eq!((neg, overflow), n.overflowing_neg()); assert_eq!(neg, n.wrapping_neg()); assert_eq!(neg == n, n == T::ZERO || n == T::power_of_2(T::WIDTH - 1)); assert_eq!(n != T::ZERO, overflow); }); } fn overflowing_neg_properties_helper_signed() { signed_gen::().test_properties(|n| { let mut neg = n; let overflow = neg.overflowing_neg_assign(); assert_eq!((neg, overflow), n.overflowing_neg()); assert_eq!(neg, n.wrapping_neg()); assert_eq!(neg == n, n == T::ZERO || n == T::MIN); assert_eq!(n == T::MIN, overflow); }); } #[test] fn overflowing_neg_properties() { apply_fn_to_unsigneds!(overflowing_neg_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_neg_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; #[test] fn test_overflowing_pow() { fn test(x: T, y: u64, out: T, overflow: bool) { assert_eq!(x.overflowing_pow(y), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_pow_assign(y), overflow); assert_eq!(x, out); } test::(0, 0, 1, false); test::(123, 0, 1, false); test::(123, 1, 123, false); test::(0, 123, 0, false); test::(1, 123, 1, false); test::(-1, 123, -1, false); test::(-1, 124, 1, false); test::(3, 3, 27, false); test::(-10, 9, -1000000000, false); test::(-10, 10, 1410065408, true); test::(-10, 9, 13824, true); test::(10, 9, -13824, true); test::(123, 456, 2409344748064316129, true); test::(0, u64::MAX, 0, false); test::(1, u64::MAX, 1, false); test::(123, u64::MAX, 3449391168254631603, true); test::(0, u64::MAX, 0, false); test::(1, u64::MAX, 1, false); test::(-1, u64::MAX, -1, false); test::(-1, u64::MAX - 1, 1, false); test::(123, u64::MAX, 3449391168254631603, true); test::(-123, u64::MAX, -3449391168254631603, true); test::(-123, u64::MAX - 1, 4527249702272692521, true); } fn overflowing_pow_properties_helper_unsigned() { unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; let overflow = power.overflowing_pow_assign(y); assert_eq!((power, overflow), x.overflowing_pow(y)); assert_eq!(x.wrapping_pow(y), power); assert_eq!(x.checked_pow(y).is_none(), overflow); if !overflow { assert_eq!(power, x.pow(y)); } }); } fn overflowing_pow_properties_helper_signed() { signed_unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; let overflow = power.overflowing_pow_assign(y); assert_eq!((power, overflow), x.overflowing_pow(y)); assert_eq!(x.wrapping_pow(y), power); assert_eq!(x.checked_pow(y).is_none(), overflow); if !overflow { assert_eq!(power, x.pow(y)); } }); } #[test] fn overflowing_pow_properties() { apply_fn_to_unsigneds!(overflowing_pow_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_pow_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; #[test] fn test_overflowing_square() { fn test(x: T, out: T, overflow: bool) { assert_eq!(x.overflowing_square(), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_square_assign(), overflow); assert_eq!(x, out); } test::(0, 0, false); test::(1, 1, false); test::(2, 4, false); test::(3, 9, false); test::(10, 100, false); test::(123, 15129, false); test::(1000, 1000000, false); test::(-1, 1, false); test::(-2, 4, false); test::(-3, 9, false); test::(-10, 100, false); test::(-123, 15129, false); test::(-1000, 1000000, false); test::(1000, 16960, true); test::(-1000, 16960, true); } fn overflowing_square_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { let mut square = x; let overflow = square.overflowing_square_assign(); assert_eq!((square, overflow), x.overflowing_square()); assert_eq!((square, overflow), x.overflowing_pow(2)); assert_eq!(x.wrapping_square(), square); assert_eq!(x.checked_square().is_none(), overflow); if !overflow { assert_eq!(square, x.square()); } }); } fn overflowing_square_properties_helper_signed() { signed_gen::().test_properties(|x| { let mut square = x; let overflow = square.overflowing_square_assign(); assert_eq!((square, overflow), x.overflowing_square()); assert_eq!((square, overflow), x.overflowing_pow(2)); assert_eq!(x.wrapping_square(), square); assert_eq!(x.checked_square().is_none(), overflow); if !overflow { assert_eq!(square, x.square()); } }); } #[test] fn overflowing_square_properties() { apply_fn_to_unsigneds!(overflowing_square_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_square_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_overflowing_sub() { fn test(x: T, y: T, out: T, overflow: bool) { assert_eq!(x.overflowing_sub(y), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_sub_assign(y), overflow); assert_eq!(x, out); } test::(456, 123, 333, false); test::(123, 200, 179, true); test::(123, -456, 579, false); test::(123, -45, -88, true); test::(-123, 45, 88, true); } fn overflowing_sub_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut diff = x; let overflow = diff.overflowing_sub_assign(y); assert_eq!((diff, overflow), x.overflowing_sub(y)); assert_eq!(x.wrapping_sub(y), diff); if !overflow { assert_eq!(diff, x - y); } }); } fn overflowing_sub_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut diff = x; let overflow = diff.overflowing_sub_assign(y); assert_eq!((diff, overflow), x.overflowing_sub(y)); assert_eq!(x.wrapping_sub(y), diff); if !overflow { assert_eq!(diff, x - y); } }); } #[test] fn overflowing_sub_properties() { apply_fn_to_unsigneds!(overflowing_sub_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_sub_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/overflowing_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_overflowing_sub_mul() { fn test(x: T, y: T, z: T, out: T, overflow: bool) { assert_eq!(x.overflowing_sub_mul(y, z), (out, overflow)); let mut x = x; assert_eq!(x.overflowing_sub_mul_assign(y, z), overflow); assert_eq!(x, out); } test::(100, 3, 7, 79, false); test::(60, 5, 10, 10, false); test::(1000000, 456, 789, 640216, false); test::(123, -456, 789, 359907, false); test::(-123, 456, 789, -359907, false); test::(127, 2, 100, -73, false); test::(-127, -2, 100, 73, false); test::(-128, 1, 0, -128, false); test::(2, 10, 5, 208, true); test::(-127, 2, 100, -71, true); test::(-127, 1, 100, 29, true); test::(127, -1, 100, -29, true); test::(127, -10, 100, 103, true); } fn overflowing_sub_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let (result, overflow) = x.overflowing_sub_mul(y, z); let mut x_alt = x; assert_eq!(x_alt.overflowing_sub_mul_assign(y, z), overflow); assert_eq!(x_alt, result); assert_eq!(x.overflowing_sub_mul(z, y), (result, overflow)); assert_eq!(result.overflowing_add_mul(y, z), (x, overflow)); assert_eq!(x.wrapping_sub_mul(y, z), result); assert_eq!(x.checked_sub_mul(y, z).is_none(), overflow); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.overflowing_sub_mul(T::ZERO, b), (a, false)); assert_eq!(a.overflowing_sub_mul(T::ONE, b), a.overflowing_sub(b)); assert_eq!(a.overflowing_sub_mul(b, T::ZERO), (a, false)); assert_eq!(a.overflowing_sub_mul(b, T::ONE), a.overflowing_sub(b)); }); } fn overflowing_sub_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let (result, overflow) = x.overflowing_sub_mul(y, z); let mut x_alt = x; assert_eq!(x_alt.overflowing_sub_mul_assign(y, z), overflow); assert_eq!(x_alt, result); assert_eq!(x.overflowing_sub_mul(z, y), (result, overflow)); assert_eq!(result.overflowing_add_mul(y, z), (x, overflow)); assert_eq!(x.wrapping_sub_mul(y, z), result); assert_eq!(x.checked_sub_mul(y, z).is_none(), overflow); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.overflowing_sub_mul(T::ZERO, b), (a, false)); assert_eq!(a.overflowing_sub_mul(T::ONE, b), a.overflowing_sub(b)); assert_eq!(a.overflowing_sub_mul(b, T::ZERO), (a, false)); assert_eq!(a.overflowing_sub_mul(b, T::ONE), a.overflowing_sub(b)); }); } #[test] fn overflowing_sub_mul_properties() { apply_fn_to_unsigneds!(overflowing_sub_mul_properties_helper_unsigned); apply_fn_to_signeds!(overflowing_sub_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; fn even_primitive_helper() { let test = |n: T, out| { assert_eq!(n.even(), out); }; test(T::ZERO, true); test(T::ONE, false); test(T::TWO, true); test(T::exact_from(123), false); test(T::exact_from(124), true); test(T::MAX, false); } fn even_signed_helper() { let test = |n: T, out| { assert_eq!(n.even(), out); }; test(T::NEGATIVE_ONE, false); test(T::exact_from(-123), false); test(T::exact_from(-124), true); test(T::MIN, true); } #[test] fn test_even() { apply_fn_to_primitive_ints!(even_primitive_helper); apply_fn_to_signeds!(even_signed_helper); } fn odd_primitive_helper() { let test = |n: T, out| { assert_eq!(n.odd(), out); }; test(T::ZERO, false); test(T::ONE, true); test(T::TWO, false); test(T::exact_from(123), true); test(T::exact_from(124), false); test(T::MAX, true); } fn odd_signed_helper() { let test = |n: T, out| { assert_eq!(n.odd(), out); }; test(T::NEGATIVE_ONE, true); test(T::exact_from(-123), true); test(T::exact_from(-124), false); test(T::MIN, false); } #[test] fn test_odd() { apply_fn_to_primitive_ints!(odd_primitive_helper); apply_fn_to_signeds!(odd_signed_helper); } fn even_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { let even = x.even(); assert_eq!(x.divisible_by(T::TWO), even); assert_eq!(!x.odd(), even); if x != T::MAX { assert_eq!((x + T::ONE).odd(), even); } if x != T::ZERO { assert_eq!((x - T::ONE).odd(), even); } }); } fn even_properties_helper_signed() { signed_gen::().test_properties(|x| { let even = x.even(); assert_eq!(x.divisible_by(T::TWO), even); assert_eq!(!x.odd(), even); if x != T::MAX { assert_eq!((x + T::ONE).odd(), even); } if x != T::MIN { assert_eq!((x - T::ONE).odd(), even); assert_eq!((-x).even(), even); } }); } #[test] fn even_properties() { apply_fn_to_unsigneds!(even_properties_helper_unsigned); apply_fn_to_signeds!(even_properties_helper_signed); } fn odd_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { let odd = x.odd(); assert_ne!(x.divisible_by(T::TWO), odd); assert_eq!(!x.even(), odd); if x != T::MAX { assert_eq!((x + T::ONE).even(), odd); } if x != T::ZERO { assert_eq!((x - T::ONE).even(), odd); } }); } fn odd_properties_helper_signed() { signed_gen::().test_properties(|x| { let odd = x.odd(); assert_ne!(x.divisible_by(T::TWO), odd); assert_eq!(!x.even(), odd); if x != T::MAX { assert_eq!((x + T::ONE).even(), odd); } if x != T::MIN { assert_eq!((x - T::ONE).even(), odd); assert_eq!((-x).odd(), odd); } }); } #[test] fn odd_properties() { apply_fn_to_unsigneds!(odd_properties_helper_unsigned); apply_fn_to_signeds!(odd_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_pair_gen, primitive_float_signed_pair_gen, signed_unsigned_pair_gen_var_15, unsigned_pair_gen_var_29, }; #[test] fn test_pow() { fn test_primitive_int(x: T, y: u64, out: T) { assert_eq!(x.pow(y), out); let mut x = x; x.pow_assign(y); assert_eq!(x, out); } test_primitive_int::(0, 0, 1); test_primitive_int::(123, 0, 1); test_primitive_int::(123, 1, 123); test_primitive_int::(0, 123, 0); test_primitive_int::(1, 123, 1); test_primitive_int::(-1, 123, -1); test_primitive_int::(-1, 124, 1); test_primitive_int::(3, 3, 27); test_primitive_int::(-10, 9, -1000000000); test_primitive_int::(-10, 8, 100000000); fn test_i64_primitive_float(x: T, y: i64, out: T) { assert_eq!(NiceFloat(x.pow(y)), NiceFloat(out)); let mut x = x; x.pow_assign(y); assert_eq!(NiceFloat(x), NiceFloat(out)); } test_i64_primitive_float::(2.0, 5, 32.0); fn test_primitive_float_primitive_float(x: T, y: T, out: T) { assert_eq!(NiceFloat(x.pow(y)), NiceFloat(out)); let mut x = x; x.pow_assign(y); assert_eq!(NiceFloat(x), NiceFloat(out)); } test_primitive_float_primitive_float::(2.0, 5.0, 32.0); } fn pow_assign_properties_helper_unsigned() { unsigned_pair_gen_var_29::().test_properties(|(x, y)| { let mut power = x; power.pow_assign(y); assert_eq!(power, x.pow(y)); if x > T::ONE { assert_eq!(power.checked_log_base(x), Some(y)); } if y != 0 { assert_eq!(power.checked_root(y), Some(x)); } }); } fn pow_assign_properties_helper_signed() { signed_unsigned_pair_gen_var_15::().test_properties(|(x, y)| { let mut power = x; power.pow_assign(y); assert_eq!(power, x.pow(y)); if y != 0 { assert_eq!( power.checked_root(y), Some(if y.even() { x.abs() } else { x }) ); } }); } fn pow_assign_properties_helper_primitive_float() { primitive_float_signed_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.pow_assign(y); assert_eq!(NiceFloat(power), NiceFloat(x.pow(y))); }); primitive_float_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.pow_assign(y); assert_eq!(NiceFloat(power), NiceFloat(x.pow(y))); }); } #[test] fn pow_assign_properties() { apply_fn_to_unsigneds!(pow_assign_properties_helper_unsigned); apply_fn_to_signeds!(pow_assign_properties_helper_signed); apply_fn_to_primitive_floats!(pow_assign_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen_var_11, unsigned_gen_var_15, unsigned_gen_var_16, unsigned_gen_var_30, }; use std::panic::catch_unwind; fn power_of_2_primitive_int_helper() { let test = |pow, out| { assert_eq!(T::power_of_2(pow), out); }; test(0, T::ONE); test(1, T::TWO); test(2, T::exact_from(4)); test(3, T::exact_from(8)); } fn power_of_2_unsigned_helper() { let test = |pow, out| { assert_eq!(T::power_of_2(pow), out); }; test(T::WIDTH - 1, T::ONE << (T::WIDTH - 1)); } fn power_of_2_primitive_float_helper() { let test = |pow, out| { assert_eq!(T::power_of_2(pow), out); }; test(0, T::ONE); test(1, T::TWO); test(-1, T::from(0.5f32)); test(2, T::from(4.0f32)); test(-2, T::from(0.25f32)); test(T::MIN_EXPONENT, T::MIN_POSITIVE_SUBNORMAL); } #[test] fn test_power_of_2() { apply_fn_to_primitive_ints!(power_of_2_primitive_int_helper); apply_fn_to_unsigneds!(power_of_2_unsigned_helper); apply_fn_to_primitive_floats!(power_of_2_primitive_float_helper); } fn power_of_2_unsigned_fail_helper() { assert_panic!(T::power_of_2(T::WIDTH)); } fn power_of_2_signed_fail_helper() { assert_panic!(T::power_of_2(T::WIDTH - 1)); } fn power_of_2_primitive_float_fail_helper() { assert_panic!(T::power_of_2(T::MAX_EXPONENT + 1)); assert_panic!(T::power_of_2(T::MIN_EXPONENT - 1)); assert_panic!(T::power_of_2(10000u64)); assert_panic!(T::power_of_2(-10000i64)); } #[test] fn power_of_2_fail() { apply_fn_to_unsigneds!(power_of_2_unsigned_fail_helper); apply_fn_to_signeds!(power_of_2_signed_fail_helper); apply_fn_to_primitive_floats!(power_of_2_primitive_float_fail_helper); } fn power_of_2_properties_helper_unsigned() { unsigned_gen_var_15::().test_properties(|pow| { let mut n = T::power_of_2(pow); assert_eq!(n.checked_log_base_2(), Some(pow)); assert!(n.is_power_of_2()); n.clear_bit(pow); assert_eq!(n, T::ZERO); }); } fn power_of_2_properties_helper_signed + PrimitiveUnsigned, S: PrimitiveSigned>() { unsigned_gen_var_16::().test_properties(|pow| { let mut n = S::power_of_2(pow); assert_eq!(U::exact_from(n), U::power_of_2(pow)); n.clear_bit(pow); assert_eq!(n, S::ZERO); }); } fn power_of_2_properties_helper_primitive_float() { unsigned_gen_var_30::().test_properties(|pow| { let n = T::power_of_2(pow); assert!(n > T::ZERO); assert!(n.is_power_of_2()); }); signed_gen_var_11::().test_properties(|pow| { let n = T::power_of_2(pow); assert!(n > T::ZERO); assert!(n.is_power_of_2()); }); } #[test] fn power_of_2_properties() { apply_fn_to_unsigneds!(power_of_2_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(power_of_2_properties_helper_signed); apply_fn_to_primitive_floats!(power_of_2_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::traits::Primes; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_27, unsigned_gen_var_28, }; use malachite_base::test_util::num::arithmetic::primorial::{ checked_primorial_naive, checked_product_of_first_n_primes_naive, }; use std::panic::catch_unwind; #[test] fn test_primorial() { fn test(n: u64, out: T) { assert_eq!(T::primorial(n), out); } test::(0, 1); test::(1, 1); test::(2, 2); test::(3, 6); test::(4, 6); test::(5, 30); test::(20, 9699690); } fn primorial_fail_helper() { assert_panic!(T::primorial(200)); } #[test] fn primorial_fail() { apply_fn_to_unsigneds!(primorial_fail_helper); } #[test] fn test_checked_primorial() { fn test(n: u64, out: Option) { assert_eq!(T::checked_primorial(n), out); assert_eq!(checked_primorial_naive(n), out); } test::(0, Some(1)); test::(1, Some(1)); test::(2, Some(2)); test::(3, Some(6)); test::(4, Some(6)); test::(5, Some(30)); test::(20, Some(9699690)); test::(11, None); test::(200, None); } #[test] fn test_product_of_first_n_primes() { fn test(n: u64, out: T) { assert_eq!(T::product_of_first_n_primes(n), out); } test::(0, 1); test::(1, 2); test::(2, 6); test::(3, 30); test::(4, 210); test::(9, 223092870); } fn product_of_first_n_primes_fail_helper() { assert_panic!(T::product_of_first_n_primes(100)); } #[test] fn product_of_first_n_primes_fail() { apply_fn_to_unsigneds!(product_of_first_n_primes_fail_helper); } #[test] fn test_checked_product_of_first_n_primes() { fn test(n: u64, out: Option) { assert_eq!(T::checked_product_of_first_n_primes(n), out); assert_eq!(checked_product_of_first_n_primes_naive(n), out); } test::(0, Some(1)); test::(1, Some(2)); test::(2, Some(6)); test::(3, Some(30)); test::(4, Some(210)); test::(9, Some(223092870)); test::(5, None); test::(100, None); } fn primorial_properties_helper() { unsigned_gen_var_27::().test_properties(|n| { let f = T::primorial(n); assert_eq!(T::checked_primorial(n), Some(f)); assert_ne!(f, T::ZERO); // TODO compare with primorial(n - 1) depending on whether n is prime }); } #[test] fn primorial_properties() { apply_fn_to_unsigneds!(primorial_properties_helper); } fn checked_primorial_properties_helper() { unsigned_gen().test_properties(|n| { let of = T::checked_primorial(n); assert_eq!(checked_primorial_naive(n), of); assert_ne!(of, Some(T::ZERO)); if let Some(f) = of { assert_eq!(T::primorial(n), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_primorial(n + 1).is_none()); } }); } #[test] fn checked_primorial_properties() { apply_fn_to_unsigneds!(checked_primorial_properties_helper); } fn product_of_first_n_primes_properties_helper() { unsigned_gen_var_28::().test_properties(|n| { let f = T::product_of_first_n_primes(n); assert_eq!(T::checked_product_of_first_n_primes(n), Some(f)); assert_ne!(f, T::ZERO); if n != 0 { let p = u64::primes().nth(usize::exact_from(n) - 1).unwrap(); assert_eq!(T::primorial(p), f); assert_eq!(f / T::product_of_first_n_primes(n - 1), T::exact_from(p)); } }); } #[test] fn product_of_first_n_primes_properties() { apply_fn_to_unsigneds!(product_of_first_n_primes_properties_helper); } fn checked_product_of_first_n_primes_properties_helper() { unsigned_gen().test_properties(|n| { let of = T::checked_product_of_first_n_primes(n); assert_eq!(checked_product_of_first_n_primes_naive(n), of); assert_ne!(of, Some(T::ZERO)); if let Some(f) = of { assert_eq!(T::product_of_first_n_primes(n), f); } if n != u64::MAX && of.is_none() { assert!(T::checked_product_of_first_n_primes(n + 1).is_none()); } }); } #[test] fn checked_product_of_first_n_primes_properties() { apply_fn_to_unsigneds!(checked_product_of_first_n_primes_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; #[test] fn test_reciprocal() { fn test(x: T, out: T) { assert_eq!(NiceFloat(x.reciprocal()), NiceFloat(out)); let mut x = x; x.reciprocal_assign(); assert_eq!(NiceFloat(x), NiceFloat(out)); } test::(f32::NAN, f32::NAN); test::(f32::INFINITY, 0.0); test::(f32::NEGATIVE_INFINITY, -0.0); test::(0.0, f32::INFINITY); test::(-0.0, f32::NEGATIVE_INFINITY); test::(1.0, 1.0); test::(-1.0, -1.0); test::(0.5, 2.0); test::(-0.5, -2.0); test::(core::f32::consts::SQRT_2, 0.70710677); test::(-core::f32::consts::SQRT_2, -0.70710677); test::(core::f32::consts::PI, std::f32::consts::FRAC_1_PI); test::(-core::f32::consts::PI, -std::f32::consts::FRAC_1_PI); test::(f64::NAN, f64::NAN); test::(f64::INFINITY, 0.0); test::(f64::NEGATIVE_INFINITY, -0.0); test::(0.0, f64::INFINITY); test::(-0.0, f64::NEGATIVE_INFINITY); test::(1.0, 1.0); test::(-1.0, -1.0); test::(0.5, 2.0); test::(-0.5, -2.0); test::(core::f64::consts::SQRT_2, 0.7071067811865475); test::(-core::f64::consts::SQRT_2, -0.7071067811865475); test::(core::f64::consts::PI, std::f64::consts::FRAC_1_PI); test::(-core::f64::consts::PI, -std::f64::consts::FRAC_1_PI); } fn reciprocal_properties_helper() { primitive_float_gen::().test_properties(|x| { let mut reciprocal = x; reciprocal.reciprocal_assign(); assert_eq!(NiceFloat(reciprocal), NiceFloat(x.reciprocal())); assert_eq!(NiceFloat(reciprocal), NiceFloat(x.pow(-1))); assert_eq!(NiceFloat((-x).reciprocal()), NiceFloat(-reciprocal)); }); } #[test] fn reciprocal_properties() { apply_fn_to_primitive_floats!(reciprocal_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::root::{ cbrt_chebyshev_approx_u32, cbrt_chebyshev_approx_u64, fast_ceiling_root_u32, fast_ceiling_root_u64, fast_checked_root_u32, fast_checked_root_u64, fast_floor_cbrt_u32, fast_floor_cbrt_u64, fast_floor_root_u32, fast_floor_root_u64, fast_root_rem_u32, fast_root_rem_u64, floor_root_approx_and_refine, }; use malachite_base::num::arithmetic::root::{ ceiling_root_binary, checked_root_binary, floor_root_binary, root_rem_binary, }; use malachite_base::num::arithmetic::traits::{ CeilingRoot, CheckedRoot, FloorRoot, Parity, RootRem, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_2, signed_unsigned_pair_gen_var_18, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_32, }; use std::ops::Neg; use std::panic::catch_unwind; #[test] fn test_floor_root() { fn test_u(n: T, exp: u64, out: T) { assert_eq!(n.floor_root(exp), out); assert_eq!(floor_root_binary(n, exp), out); let mut n = n; n.floor_root_assign(exp); assert_eq!(n, out); } test_u::(0, 1, 0); test_u::(1, 1, 1); test_u::(2, 1, 2); test_u::(100, 1, 100); test_u::(0, 2, 0); test_u::(1, 2, 1); test_u::(2, 2, 1); test_u::(3, 2, 1); test_u::(4, 2, 2); test_u::(5, 2, 2); test_u::(0, 3, 0); test_u::(1, 3, 1); test_u::(2, 3, 1); test_u::(7, 3, 1); test_u::(8, 3, 2); test_u::(9, 3, 2); test_u::(10, 2, 3); test_u::(100, 2, 10); test_u::(100, 3, 4); test_u::(1000000000, 2, 31622); test_u::(1000000000, 3, 1000); test_u::(1000000000, 4, 177); test_u::(1000000000, 5, 63); test_u::(1000000000, 6, 31); test_u::(1000000000, 7, 19); test_u::(1000000000, 8, 13); test_u::(1000000000, 9, 10); test_u::(1000000000, 10, 7); fn test_i(n: T, exp: u64, out: T) { assert_eq!(n.floor_root(exp), out); let mut n = n; n.floor_root_assign(exp); assert_eq!(n, out); } test_i::(0, 1, 0); test_i::(1, 1, 1); test_i::(2, 1, 2); test_i::(100, 1, 100); test_i::(0, 2, 0); test_i::(0, 2, 0); test_i::(1, 2, 1); test_i::(2, 2, 1); test_i::(3, 2, 1); test_i::(4, 2, 2); test_i::(5, 2, 2); test_i::(0, 3, 0); test_i::(1, 3, 1); test_i::(2, 3, 1); test_i::(7, 3, 1); test_i::(8, 3, 2); test_i::(9, 3, 2); test_i::(10, 2, 3); test_i::(100, 2, 10); test_i::(100, 3, 4); test_i::(1000000000, 2, 31622); test_i::(1000000000, 3, 1000); test_i::(1000000000, 4, 177); test_i::(1000000000, 5, 63); test_i::(1000000000, 6, 31); test_i::(1000000000, 7, 19); test_i::(1000000000, 8, 13); test_i::(1000000000, 9, 10); test_i::(1000000000, 10, 7); test_i::(-1, 1, -1); test_i::(-2, 1, -2); test_i::(-100, 1, -100); test_i::(-1, 3, -1); test_i::(-2, 3, -2); test_i::(-7, 3, -2); test_i::(-8, 3, -2); test_i::(-9, 3, -3); test_i::(-100, 3, -5); test_i::(-1000000000, 3, -1000); test_i::(-1000000000, 5, -64); test_i::(-1000000000, 7, -20); test_i::(-1000000000, 9, -10); } fn floor_root_fail_helper_unsigned() { assert_panic!(T::ONE.floor_root(0)); } fn floor_root_fail_helper_signed() { assert_panic!(T::ONE.floor_root(0)); assert_panic!(T::NEGATIVE_ONE.floor_root(0)); assert_panic!(T::NEGATIVE_ONE.floor_root(2)); assert_panic!(T::NEGATIVE_ONE.floor_root(4)); assert_panic!(T::NEGATIVE_ONE.floor_root(100)); } #[test] pub fn floor_root_fail() { apply_fn_to_unsigneds!(floor_root_fail_helper_unsigned); apply_fn_to_signeds!(floor_root_fail_helper_signed); } #[test] fn test_ceiling_root() { fn test_u(n: T, exp: u64, out: T) { assert_eq!(n.ceiling_root(exp), out); assert_eq!(ceiling_root_binary(n, exp), out); let mut n = n; n.ceiling_root_assign(exp); assert_eq!(n, out); } test_u::(0, 1, 0); test_u::(1, 1, 1); test_u::(2, 1, 2); test_u::(100, 1, 100); test_u::(0, 2, 0); test_u::(1, 2, 1); test_u::(2, 2, 2); test_u::(3, 2, 2); test_u::(4, 2, 2); test_u::(5, 2, 3); test_u::(0, 3, 0); test_u::(1, 3, 1); test_u::(2, 3, 2); test_u::(7, 3, 2); test_u::(8, 3, 2); test_u::(9, 3, 3); test_u::(10, 2, 4); test_u::(100, 2, 10); test_u::(100, 3, 5); test_u::(1000000000, 2, 31623); test_u::(1000000000, 3, 1000); test_u::(1000000000, 4, 178); test_u::(1000000000, 5, 64); test_u::(1000000000, 6, 32); test_u::(1000000000, 7, 20); test_u::(1000000000, 8, 14); test_u::(1000000000, 9, 10); test_u::(1000000000, 10, 8); fn test_i(n: T, exp: u64, out: T) { assert_eq!(n.ceiling_root(exp), out); let mut n = n; n.ceiling_root_assign(exp); assert_eq!(n, out); } test_i::(0, 1, 0); test_i::(1, 1, 1); test_i::(2, 1, 2); test_i::(100, 1, 100); test_i::(0, 2, 0); test_i::(1, 2, 1); test_i::(2, 2, 2); test_i::(3, 2, 2); test_i::(4, 2, 2); test_i::(5, 2, 3); test_i::(0, 3, 0); test_i::(1, 3, 1); test_i::(2, 3, 2); test_i::(7, 3, 2); test_i::(8, 3, 2); test_i::(9, 3, 3); test_i::(10, 2, 4); test_i::(100, 2, 10); test_i::(100, 3, 5); test_i::(1000000000, 2, 31623); test_i::(1000000000, 3, 1000); test_i::(1000000000, 4, 178); test_i::(1000000000, 5, 64); test_i::(1000000000, 6, 32); test_i::(1000000000, 7, 20); test_i::(1000000000, 8, 14); test_i::(1000000000, 9, 10); test_i::(1000000000, 10, 8); test_i::(-1, 1, -1); test_i::(-2, 1, -2); test_i::(-100, 1, -100); test_i::(-1, 3, -1); test_i::(-2, 3, -1); test_i::(-7, 3, -1); test_i::(-8, 3, -2); test_i::(-9, 3, -2); test_i::(-100, 3, -4); test_i::(-1000000000, 3, -1000); test_i::(-1000000000, 5, -63); test_i::(-1000000000, 7, -19); test_i::(-1000000000, 9, -10); } fn ceiling_root_fail_helper_unsigned() { assert_panic!(T::ONE.ceiling_root(0)); } fn ceiling_root_fail_helper_signed() { assert_panic!(T::ONE.ceiling_root(0)); assert_panic!(T::NEGATIVE_ONE.ceiling_root(0)); assert_panic!(T::NEGATIVE_ONE.ceiling_root(2)); assert_panic!(T::NEGATIVE_ONE.ceiling_root(4)); assert_panic!(T::NEGATIVE_ONE.ceiling_root(100)); } #[test] pub fn ceiling_root_fail() { apply_fn_to_unsigneds!(ceiling_root_fail_helper_unsigned); apply_fn_to_signeds!(ceiling_root_fail_helper_signed); } #[test] fn test_checked_root() { fn test_u(n: T, exp: u64, out: Option) { assert_eq!(n.checked_root(exp), out); assert_eq!(checked_root_binary(n, exp), out); } test_u::(0, 1, Some(0)); test_u::(1, 1, Some(1)); test_u::(2, 1, Some(2)); test_u::(100, 1, Some(100)); test_u::(0, 2, Some(0)); test_u::(1, 2, Some(1)); test_u::(2, 2, None); test_u::(3, 2, None); test_u::(4, 2, Some(2)); test_u::(5, 2, None); test_u::(0, 3, Some(0)); test_u::(1, 3, Some(1)); test_u::(2, 3, None); test_u::(7, 3, None); test_u::(8, 3, Some(2)); test_u::(9, 3, None); test_u::(10, 2, None); test_u::(100, 2, Some(10)); test_u::(100, 3, None); test_u::(1000000000, 2, None); test_u::(1000000000, 3, Some(1000)); test_u::(1000000000, 4, None); test_u::(1000000000, 5, None); test_u::(1000000000, 6, None); test_u::(1000000000, 7, None); test_u::(1000000000, 8, None); test_u::(1000000000, 9, Some(10)); test_u::(1000000000, 10, None); fn test_i(n: T, exp: u64, out: Option) { assert_eq!(n.checked_root(exp), out); } test_i::(0, 1, Some(0)); test_i::(1, 1, Some(1)); test_i::(2, 1, Some(2)); test_i::(100, 1, Some(100)); test_i::(0, 2, Some(0)); test_i::(1, 2, Some(1)); test_i::(2, 2, None); test_i::(3, 2, None); test_i::(4, 2, Some(2)); test_i::(5, 2, None); test_i::(0, 3, Some(0)); test_i::(1, 3, Some(1)); test_i::(2, 3, None); test_i::(7, 3, None); test_i::(8, 3, Some(2)); test_i::(9, 3, None); test_i::(10, 2, None); test_i::(100, 2, Some(10)); test_i::(100, 3, None); test_i::(1000000000, 2, None); test_i::(1000000000, 3, Some(1000)); test_i::(1000000000, 4, None); test_i::(1000000000, 5, None); test_i::(1000000000, 6, None); test_i::(1000000000, 7, None); test_i::(1000000000, 8, None); test_i::(1000000000, 9, Some(10)); test_i::(1000000000, 10, None); test_i::(-1, 1, Some(-1)); test_i::(-2, 1, Some(-2)); test_i::(-100, 1, Some(-100)); test_i::(-1, 3, Some(-1)); test_i::(-2, 3, None); test_i::(-7, 3, None); test_i::(-8, 3, Some(-2)); test_i::(-9, 3, None); test_i::(-100, 3, None); test_i::(-1000000000, 3, Some(-1000)); test_i::(-1000000000, 5, None); test_i::(-1000000000, 7, None); test_i::(-1000000000, 9, Some(-10)); } fn checked_root_fail_helper_unsigned() { assert_panic!(T::ONE.checked_root(0)); } fn checked_root_fail_helper_signed() { assert_panic!(T::ONE.checked_root(0)); assert_panic!(T::NEGATIVE_ONE.checked_root(0)); assert_panic!(T::NEGATIVE_ONE.checked_root(2)); assert_panic!(T::NEGATIVE_ONE.checked_root(4)); assert_panic!(T::NEGATIVE_ONE.checked_root(100)); } #[test] pub fn checked_root_fail() { apply_fn_to_unsigneds!(checked_root_fail_helper_unsigned); apply_fn_to_signeds!(checked_root_fail_helper_signed); } #[test] fn test_root_rem() { fn test(n: T, exp: u64, out_root: T, out_rem: T) { assert_eq!(n.root_rem(exp), (out_root, out_rem)); assert_eq!(root_rem_binary(n, exp), (out_root, out_rem)); let mut n = n; assert_eq!(n.root_assign_rem(exp), out_rem); assert_eq!(n, out_root); } test::(0, 1, 0, 0); test::(1, 1, 1, 0); test::(2, 1, 2, 0); test::(100, 1, 100, 0); test::(0, 2, 0, 0); test::(1, 2, 1, 0); test::(2, 2, 1, 1); test::(3, 2, 1, 2); test::(4, 2, 2, 0); test::(5, 2, 2, 1); test::(0, 3, 0, 0); test::(1, 3, 1, 0); test::(2, 3, 1, 1); test::(7, 3, 1, 6); test::(8, 3, 2, 0); test::(9, 3, 2, 1); test::(10, 2, 3, 1); test::(100, 2, 10, 0); test::(100, 3, 4, 36); test::(1000000000, 2, 31622, 49116); test::(1000000000, 3, 1000, 0); test::(1000000000, 4, 177, 18493759); test::(1000000000, 5, 63, 7563457); test::(1000000000, 6, 31, 112496319); test::(1000000000, 7, 19, 106128261); test::(1000000000, 8, 13, 184269279); test::(1000000000, 9, 10, 0); test::(1000000000, 10, 7, 717524751); } fn root_rem_fail_helper() { assert_panic!(T::ONE.root_rem(0)); } #[test] pub fn root_rem_fail() { apply_fn_to_unsigneds!(root_rem_fail_helper); } fn floor_root_properties_helper_unsigned() { unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { let root = n.floor_root(exp); let mut n_alt = n; n_alt.floor_root_assign(exp); assert_eq!(n_alt, root); assert_eq!(floor_root_binary(n, exp), root); let pow = root.pow(exp); let ceiling_root = n.ceiling_root(exp); if pow == n { assert_eq!(ceiling_root, root); } else { assert_eq!(ceiling_root, root + T::ONE); } assert!(pow <= n); if exp != 1 && let Some(next_pow) = (root + T::ONE).checked_pow(exp) { assert!(next_pow > n); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.floor_root(2), n.floor_sqrt()); assert_eq!(n.floor_root(1), n); let cbrt = n.floor_root(3); let mut n_alt = n; n_alt.floor_root_assign(3); assert_eq!(n_alt, cbrt); assert_eq!(floor_root_binary(n, 3), cbrt); let cube = cbrt.pow(3); let ceiling_cbrt = n.ceiling_root(3); if cube == n { assert_eq!(ceiling_cbrt, cbrt); } else { assert_eq!(ceiling_cbrt, cbrt + T::ONE); } assert!(cube <= n); if let Some(next_cube) = (cbrt + T::ONE).checked_pow(3) { assert!(next_cube > n); } }); } fn floor_root_properties_helper_signed() { signed_unsigned_pair_gen_var_18::().test_properties(|(n, exp)| { let root = n.floor_root(exp); let mut n_alt = n; n_alt.floor_root_assign(exp); assert_eq!(n_alt, root); if let Some(pow) = root.checked_pow(exp) { let ceiling_root = n.ceiling_root(exp); if pow == n { assert_eq!(ceiling_root, root); } else { assert_eq!(ceiling_root, root + T::ONE); } assert!(pow <= n); } if exp.odd() && n != T::MIN { assert_eq!(-(-n).ceiling_root(exp), root); } }); signed_gen::().test_properties(|n| { assert_eq!(n.floor_root(1), n); let cbrt = n.floor_root(3); let mut n_alt = n; n_alt.floor_root_assign(3); assert_eq!(n_alt, cbrt); if let Some(cube) = cbrt.checked_pow(3) { let ceiling_cbrt = n.ceiling_root(3); if cube == n { assert_eq!(ceiling_cbrt, cbrt); } else { assert_eq!(ceiling_cbrt, cbrt + T::ONE); } assert!(cube <= n); } if n != T::MIN { assert_ne!((-n).ceiling_root(3), T::MIN); assert_eq!(-(-n).ceiling_root(3), cbrt); } }); signed_gen_var_2::().test_properties(|n| { assert_eq!(n.floor_root(2), n.floor_sqrt()); }); } macro_rules! floor_root_approx_and_refine_helper { ($t:ty) => { #[allow(clippy::cast_lossless)] unsigned_pair_gen_var_32::<$t, u64>().test_properties(|(n, exp)| { assert_eq!( floor_root_approx_and_refine(|x| x as f64, |f| f as $t, n, exp), n.floor_root(exp), ); }); #[allow(clippy::cast_lossless)] unsigned_gen::<$t>().test_properties(|n| { assert_eq!( floor_root_approx_and_refine(|x| x as f64, |f| f as $t, n, 3), n.floor_root(3), ); }); }; } #[test] fn floor_root_properties() { apply_fn_to_unsigneds!(floor_root_properties_helper_unsigned); apply_fn_to_signeds!(floor_root_properties_helper_signed); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(cbrt_chebyshev_approx_u32(n), n.floor_root(3)); assert_eq!(fast_floor_cbrt_u32(n), n.floor_root(3)); }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!(cbrt_chebyshev_approx_u64(n), n.floor_root(3)); assert_eq!(fast_floor_cbrt_u64(n), n.floor_root(3)); }); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_floor_root_u32(n, exp), n.floor_root(exp)); }); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_floor_root_u64(n, exp), n.floor_root(exp)); }); apply_to_unsigneds!(floor_root_approx_and_refine_helper); } fn ceiling_root_properties_helper_unsigned() { unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { let root = n.ceiling_root(exp); let mut n_alt = n; n_alt.ceiling_root_assign(exp); assert_eq!(n_alt, root); assert_eq!(ceiling_root_binary(n, exp), root); if let Some(pow) = root.checked_pow(exp) { let floor_root = n.floor_root(exp); if pow == n { assert_eq!(floor_root, root); } else { assert_eq!(floor_root, root - T::ONE); } assert!(pow >= n); } if exp != 1 && n != T::ZERO { assert!((root - T::ONE).pow(exp) < n); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.ceiling_root(2), n.ceiling_sqrt()); assert_eq!(n.ceiling_root(1), n); let cbrt = n.ceiling_root(3); let mut n_alt = n; n_alt.ceiling_root_assign(3); assert_eq!(n_alt, cbrt); assert_eq!(ceiling_root_binary(n, 3), cbrt); if let Some(cube) = cbrt.checked_pow(3) { let floor_cbrt = n.floor_root(3); if cube == n { assert_eq!(floor_cbrt, cbrt); } else { assert_eq!(floor_cbrt, cbrt - T::ONE); } assert!(cube >= n); } if n != T::ZERO { assert!((cbrt - T::ONE).pow(3) < n); } }); } fn ceiling_root_properties_helper_signed() { signed_unsigned_pair_gen_var_18::().test_properties(|(n, exp)| { let root = n.ceiling_root(exp); let mut n_alt = n; n_alt.ceiling_root_assign(exp); assert_eq!(n_alt, root); if let Some(pow) = root.checked_pow(exp) { let floor_root = n.floor_root(exp); if pow == n { assert_eq!(floor_root, root); } else { assert_eq!(floor_root, root - T::ONE); } assert!(pow >= n); } if exp.odd() && n != T::MIN { assert_eq!(-(-n).floor_root(exp), root); } }); signed_gen::().test_properties(|n| { assert_eq!(n.ceiling_root(1), n); let cbrt = n.ceiling_root(3); let mut n_alt = n; n_alt.ceiling_root_assign(3); assert_eq!(n_alt, cbrt); if let Some(cube) = cbrt.checked_pow(3) { let floor_cbrt = n.floor_root(3); if cube == n { assert_eq!(floor_cbrt, cbrt); } else { assert_eq!(floor_cbrt, cbrt - T::ONE); } assert!(cube >= n); } if n != T::MIN { assert_eq!(-(-n).floor_root(3), cbrt); } }); signed_gen_var_2::().test_properties(|n| { assert_eq!(n.ceiling_root(2), n.ceiling_sqrt()); }); } #[test] fn ceiling_root_properties() { apply_fn_to_unsigneds!(ceiling_root_properties_helper_unsigned); apply_fn_to_signeds!(ceiling_root_properties_helper_signed); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_ceiling_root_u32(n, exp), n.ceiling_root(exp)); }); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_ceiling_root_u64(n, exp), n.ceiling_root(exp)); }); } fn checked_root_properties_helper_unsigned() { unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { let root = n.checked_root(exp); assert_eq!(checked_root_binary(n, exp), root); if let Some(root) = root { assert_eq!(root.pow(exp), n); assert_eq!(n.floor_root(exp), root); assert_eq!(n.ceiling_root(exp), root); } }); unsigned_gen::().test_properties(|n| { assert_eq!(n.checked_root(2), n.checked_sqrt()); assert_eq!(n.checked_root(1), Some(n)); let cbrt = n.checked_root(3); assert_eq!(checked_root_binary(n, 3), cbrt); if let Some(cbrt) = cbrt { assert_eq!(cbrt.pow(3), n); assert_eq!(n.floor_root(3), cbrt); assert_eq!(n.ceiling_root(3), cbrt); } }); } fn checked_root_properties_helper_signed() { signed_unsigned_pair_gen_var_18::().test_properties(|(n, exp)| { let root = n.checked_root(exp); if let Some(root) = root { assert_eq!(root.pow(exp), n); assert_eq!(n.floor_root(exp), root); assert_eq!(n.ceiling_root(exp), root); } if exp.odd() && n != T::MIN { assert_eq!((-n).checked_root(exp).map(Neg::neg), root); } }); signed_gen::().test_properties(|n| { assert_eq!(n.checked_root(1), Some(n)); let cbrt = n.checked_root(3); if let Some(cbrt) = cbrt { assert_eq!(cbrt.pow(3), n); assert_eq!(n.floor_root(3), cbrt); assert_eq!(n.ceiling_root(3), cbrt); } if n != T::MIN { assert_eq!((-n).checked_root(3).map(Neg::neg), cbrt); } }); signed_gen_var_2::().test_properties(|n| { assert_eq!(n.checked_root(2), n.checked_sqrt()); }); } #[test] fn checked_root_properties() { apply_fn_to_unsigneds!(checked_root_properties_helper_unsigned); apply_fn_to_signeds!(checked_root_properties_helper_signed); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_checked_root_u32(n, exp), n.checked_root(exp)); }); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_checked_root_u64(n, exp), n.checked_root(exp)); }); } fn root_rem_properties_helper() { unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { let (root, rem) = n.root_rem(exp); let mut n_alt = n; assert_eq!(n_alt.root_assign_rem(exp), rem); assert_eq!(n_alt, root); assert_eq!(root_rem_binary(n, exp), (root, rem)); assert_eq!(n.floor_root(exp), root); assert_eq!(root.pow(exp) + rem, n); }); unsigned_gen::().test_properties(|n| { assert_eq!(n.root_rem(2), n.sqrt_rem()); assert_eq!(n.root_rem(1), (n, T::ZERO)); let (cbrt, rem) = n.root_rem(3); let mut n_alt = n; assert_eq!(n_alt.root_assign_rem(3), rem); assert_eq!(n_alt, cbrt); assert_eq!(root_rem_binary(n, 3), (cbrt, rem)); assert_eq!(n.floor_root(3), cbrt); assert_eq!(cbrt.pow(3) + rem, n); }); } #[test] fn root_rem_properties() { apply_fn_to_unsigneds!(root_rem_properties_helper); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_root_rem_u32(n, exp), n.root_rem(exp)); }); unsigned_pair_gen_var_32::().test_properties(|(n, exp)| { assert_eq!(fast_root_rem_u64(n, exp), n.root_rem(exp)); }); } ================================================ FILE: malachite-base/tests/num/arithmetic/rotate.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegMod; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen, unsigned_gen, unsigned_pair_gen, }; #[test] fn test_rotate_left() { fn test(x: T, n: u64, out: T) { assert_eq!(x.rotate_left(n), out); let mut x = x; x.rotate_left_assign(n); assert_eq!(x, out); } test::(0, 0, 0); test::(100, 0, 100); test::(0xabcd, 0, 0xabcd); test::(0xabcd, 4, 0xbcda); test::(0xabcd, 8, 0xcdab); test::(0xabcd, 12, 0xdabc); test::(0xabcd, 16, 0xabcd); test::(0xabcd, 160, 0xabcd); test::(10, 0, 10); test::(10, 1, 20); test::(10, 2, 40); test::(10, 3, 80); test::(10, 4, -96); test::(10, 5, 65); test::(10, 6, -126); test::(10, 7, 5); test::(10, 8, 10); } #[test] fn test_rotate_right() { fn test(x: T, n: u64, out: T) { assert_eq!(x.rotate_right(n), out); let mut x = x; x.rotate_right_assign(n); assert_eq!(x, out); } test::(0, 0, 0); test::(100, 0, 100); test::(0xabcd, 0, 0xabcd); test::(0xabcd, 4, 0xdabc); test::(0xabcd, 8, 0xcdab); test::(0xabcd, 12, 0xbcda); test::(0xabcd, 16, 0xabcd); test::(0xabcd, 160, 0xabcd); test::(10, 0, 10); test::(10, 1, 5); test::(10, 2, -126); test::(10, 3, 65); test::(10, 4, -96); test::(10, 5, 80); test::(10, 6, 40); test::(10, 7, 20); test::(10, 8, 10); } fn rotate_left_properties_unsigned_helper() { unsigned_pair_gen::().test_properties(|(x, n)| { let rotated = x.rotate_left(n); let mut mut_x = x; mut_x.rotate_left_assign(n); assert_eq!(mut_x, rotated); if let Some(m) = n.checked_add(T::WIDTH) { assert_eq!(x.rotate_left(m), rotated); } assert_eq!(x.rotate_left(n & T::WIDTH_MASK), rotated); assert_eq!(x.rotate_right(n.neg_mod(T::WIDTH)), rotated); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.rotate_left(0), x); assert_eq!(x.rotate_left(T::WIDTH), x); }); unsigned_gen::().test_properties(|n| { assert_eq!(T::ZERO.rotate_left(n), T::ZERO); assert_eq!(T::MAX.rotate_left(n), T::MAX); }); } fn rotate_left_properties_signed_helper() { signed_unsigned_pair_gen::().test_properties(|(x, n)| { let rotated = x.rotate_left(n); let mut mut_x = x; mut_x.rotate_left_assign(n); assert_eq!(mut_x, rotated); if let Some(m) = n.checked_add(T::WIDTH) { assert_eq!(x.rotate_left(m), rotated); } assert_eq!(x.rotate_left(n & T::WIDTH_MASK), rotated); assert_eq!(x.rotate_right(n.neg_mod(T::WIDTH)), rotated); }); signed_gen::().test_properties(|x| { assert_eq!(x.rotate_left(0), x); assert_eq!(x.rotate_left(T::WIDTH), x); }); unsigned_gen::().test_properties(|n| { assert_eq!(T::ZERO.rotate_left(n), T::ZERO); assert_eq!(T::NEGATIVE_ONE.rotate_left(n), T::NEGATIVE_ONE); }); } #[test] fn rotate_left_properties() { apply_fn_to_unsigneds!(rotate_left_properties_unsigned_helper); apply_fn_to_signeds!(rotate_left_properties_signed_helper); } fn rotate_right_properties_unsigned_helper() { unsigned_pair_gen::().test_properties(|(x, n)| { let rotated = x.rotate_right(n); let mut mut_x = x; mut_x.rotate_right_assign(n); assert_eq!(mut_x, rotated); if let Some(m) = n.checked_add(T::WIDTH) { assert_eq!(x.rotate_right(m), rotated); } assert_eq!(x.rotate_right(n & T::WIDTH_MASK), rotated); assert_eq!(x.rotate_left(n.neg_mod(T::WIDTH)), rotated); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.rotate_right(0), x); assert_eq!(x.rotate_right(T::WIDTH), x); }); unsigned_gen::().test_properties(|n| { assert_eq!(T::ZERO.rotate_right(n), T::ZERO); assert_eq!(T::MAX.rotate_right(n), T::MAX); }); } fn rotate_right_properties_signed_helper() { signed_unsigned_pair_gen::().test_properties(|(x, n)| { let rotated = x.rotate_right(n); let mut mut_x = x; mut_x.rotate_right_assign(n); assert_eq!(mut_x, rotated); if let Some(m) = n.checked_add(T::WIDTH) { assert_eq!(x.rotate_right(m), rotated); } assert_eq!(x.rotate_right(n & T::WIDTH_MASK), rotated); assert_eq!(x.rotate_left(n.neg_mod(T::WIDTH)), rotated); }); signed_gen::().test_properties(|x| { assert_eq!(x.rotate_right(0), x); assert_eq!(x.rotate_right(T::WIDTH), x); }); unsigned_gen::().test_properties(|n| { assert_eq!(T::ZERO.rotate_right(n), T::ZERO); assert_eq!(T::NEGATIVE_ONE.rotate_right(n), T::NEGATIVE_ONE); }); } #[test] fn rotate_right_properties() { apply_fn_to_unsigneds!(rotate_right_properties_unsigned_helper); apply_fn_to_signeds!(rotate_right_properties_signed_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_pair_gen, signed_pair_gen_var_5, signed_rounding_mode_pair_gen, signed_signed_rounding_mode_triple_gen_var_2, unsigned_pair_gen_var_13, unsigned_pair_gen_var_27, unsigned_rounding_mode_pair_gen, unsigned_unsigned_rounding_mode_triple_gen_var_2, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_round_to_multiple_unsigned() { fn test(n: T, d: T, rm: RoundingMode, q: T, o: Ordering) { assert_eq!(n.round_to_multiple(d, rm), (q, o)); let mut mut_n = n; assert_eq!(mut_n.round_to_multiple_assign(d, rm), o); assert_eq!(mut_n, q); } test::(0, 1, Down, 0, Equal); test::(0, 1, Floor, 0, Equal); test::(0, 1, Up, 0, Equal); test::(0, 1, Ceiling, 0, Equal); test::(0, 1, Nearest, 0, Equal); test::(0, 1, Exact, 0, Equal); test::(0, 123, Down, 0, Equal); test::(0, 123, Floor, 0, Equal); test::(0, 123, Up, 0, Equal); test::(0, 123, Ceiling, 0, Equal); test::(0, 123, Nearest, 0, Equal); test::(0, 123, Exact, 0, Equal); test::(1, 1, Down, 1, Equal); test::(1, 1, Floor, 1, Equal); test::(1, 1, Up, 1, Equal); test::(1, 1, Ceiling, 1, Equal); test::(1, 1, Nearest, 1, Equal); test::(1, 1, Exact, 1, Equal); test::(123, 1, Down, 123, Equal); test::(123, 1, Floor, 123, Equal); test::(123, 1, Up, 123, Equal); test::(123, 1, Ceiling, 123, Equal); test::(123, 1, Nearest, 123, Equal); test::(123, 1, Exact, 123, Equal); test::(123, 2, Down, 122, Less); test::(123, 2, Floor, 122, Less); test::(123, 2, Up, 124, Greater); test::(123, 2, Ceiling, 124, Greater); test::(123, 2, Nearest, 124, Greater); test::(125, 2, Down, 124, Less); test::(125, 2, Floor, 124, Less); test::(125, 2, Up, 126, Greater); test::(125, 2, Ceiling, 126, Greater); test::(125, 2, Nearest, 124, Less); test::(123, 123, Down, 123, Equal); test::(123, 123, Floor, 123, Equal); test::(123, 123, Up, 123, Equal); test::(123, 123, Ceiling, 123, Equal); test::(123, 123, Nearest, 123, Equal); test::(123, 123, Exact, 123, Equal); test::(123, 456, Down, 0, Less); test::(123, 456, Floor, 0, Less); test::(123, 456, Up, 456, Greater); test::(123, 456, Ceiling, 456, Greater); test::(123, 456, Nearest, 0, Less); test::(1000000000000, 1, Down, 1000000000000, Equal); test::(1000000000000, 1, Floor, 1000000000000, Equal); test::(1000000000000, 1, Up, 1000000000000, Equal); test::(1000000000000, 1, Ceiling, 1000000000000, Equal); test::(1000000000000, 1, Nearest, 1000000000000, Equal); test::(1000000000000, 1, Exact, 1000000000000, Equal); test::(1000000000000, 3, Down, 999999999999, Less); test::(1000000000000, 3, Floor, 999999999999, Less); test::(1000000000000, 3, Up, 1000000000002, Greater); test::(1000000000000, 3, Ceiling, 1000000000002, Greater); test::(1000000000000, 3, Nearest, 999999999999, Less); test::(999999999999, 2, Down, 999999999998, Less); test::(999999999999, 2, Floor, 999999999998, Less); test::(999999999999, 2, Up, 1000000000000, Greater); test::(999999999999, 2, Ceiling, 1000000000000, Greater); test::(999999999999, 2, Nearest, 1000000000000, Greater); test::(1000000000001, 2, Down, 1000000000000, Less); test::(1000000000001, 2, Floor, 1000000000000, Less); test::(1000000000001, 2, Up, 1000000000002, Greater); test::(1000000000001, 2, Ceiling, 1000000000002, Greater); test::(1000000000001, 2, Nearest, 1000000000000, Less); test::( 1000000000000000000000000, 0xffffffff, Down, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, 0xffffffff, Floor, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, 0xffffffff, Up, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Ceiling, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Nearest, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 1000000000000, Down, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Floor, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Up, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Ceiling, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Nearest, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Exact, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000001, Down, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Floor, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Up, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Ceiling, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Nearest, 999999999999999999999999, Less, ); test::( 2999999999999999999999999, 2000000000000000000000000, Nearest, 2000000000000000000000000, Less, ); test::( 3000000000000000000000000, 2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::( 3000000000000000000000001, 2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::(0, 0, Floor, 0, Equal); test::(0, 0, Ceiling, 0, Equal); test::(0, 0, Down, 0, Equal); test::(0, 0, Up, 0, Equal); test::(0, 0, Nearest, 0, Equal); test::(0, 0, Exact, 0, Equal); test::(2, 0, Floor, 0, Less); test::(2, 0, Down, 0, Less); test::(2, 0, Nearest, 0, Less); } #[test] fn test_round_to_multiple_signed() { fn test(n: T, d: T, rm: RoundingMode, q: T, o: Ordering) { assert_eq!(n.round_to_multiple(d, rm), (q, o)); let mut mut_n = n; assert_eq!(mut_n.round_to_multiple_assign(d, rm), o); assert_eq!(mut_n, q); } test::(0, 1, Down, 0, Equal); test::(0, 1, Floor, 0, Equal); test::(0, 1, Up, 0, Equal); test::(0, 1, Ceiling, 0, Equal); test::(0, 1, Nearest, 0, Equal); test::(0, 1, Exact, 0, Equal); test::(0, 123, Down, 0, Equal); test::(0, 123, Floor, 0, Equal); test::(0, 123, Up, 0, Equal); test::(0, 123, Ceiling, 0, Equal); test::(0, 123, Nearest, 0, Equal); test::(0, 123, Exact, 0, Equal); test::(1, 1, Down, 1, Equal); test::(1, 1, Floor, 1, Equal); test::(1, 1, Up, 1, Equal); test::(1, 1, Ceiling, 1, Equal); test::(1, 1, Nearest, 1, Equal); test::(1, 1, Exact, 1, Equal); test::(123, 1, Down, 123, Equal); test::(123, 1, Floor, 123, Equal); test::(123, 1, Up, 123, Equal); test::(123, 1, Ceiling, 123, Equal); test::(123, 1, Nearest, 123, Equal); test::(123, 1, Exact, 123, Equal); test::(123, 2, Down, 122, Less); test::(123, 2, Floor, 122, Less); test::(123, 2, Up, 124, Greater); test::(123, 2, Ceiling, 124, Greater); test::(123, 2, Nearest, 124, Greater); test::(125, 2, Down, 124, Less); test::(125, 2, Floor, 124, Less); test::(125, 2, Up, 126, Greater); test::(125, 2, Ceiling, 126, Greater); test::(125, 2, Nearest, 124, Less); test::(123, 123, Down, 123, Equal); test::(123, 123, Floor, 123, Equal); test::(123, 123, Up, 123, Equal); test::(123, 123, Ceiling, 123, Equal); test::(123, 123, Nearest, 123, Equal); test::(123, 123, Exact, 123, Equal); test::(123, 456, Down, 0, Less); test::(123, 456, Floor, 0, Less); test::(123, 456, Up, 456, Greater); test::(123, 456, Ceiling, 456, Greater); test::(123, 456, Nearest, 0, Less); test::(1000000000000, 1, Down, 1000000000000, Equal); test::(1000000000000, 1, Floor, 1000000000000, Equal); test::(1000000000000, 1, Up, 1000000000000, Equal); test::(1000000000000, 1, Ceiling, 1000000000000, Equal); test::(1000000000000, 1, Nearest, 1000000000000, Equal); test::(1000000000000, 1, Exact, 1000000000000, Equal); test::(1000000000000, 3, Down, 999999999999, Less); test::(1000000000000, 3, Floor, 999999999999, Less); test::(1000000000000, 3, Up, 1000000000002, Greater); test::(1000000000000, 3, Ceiling, 1000000000002, Greater); test::(1000000000000, 3, Nearest, 999999999999, Less); test::(999999999999, 2, Down, 999999999998, Less); test::(999999999999, 2, Floor, 999999999998, Less); test::(999999999999, 2, Up, 1000000000000, Greater); test::(999999999999, 2, Ceiling, 1000000000000, Greater); test::(999999999999, 2, Nearest, 1000000000000, Greater); test::(1000000000001, 2, Down, 1000000000000, Less); test::(1000000000001, 2, Floor, 1000000000000, Less); test::(1000000000001, 2, Up, 1000000000002, Greater); test::(1000000000001, 2, Ceiling, 1000000000002, Greater); test::(1000000000001, 2, Nearest, 1000000000000, Less); test::( 1000000000000000000000000, 0xffffffff, Down, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, 0xffffffff, Floor, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, 0xffffffff, Up, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Ceiling, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 0xffffffff, Nearest, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 1000000000000, Down, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Floor, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Up, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Ceiling, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Nearest, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Exact, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000001, Down, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Floor, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, 1000000000001, Up, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Ceiling, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, 1000000000001, Nearest, 999999999999999999999999, Less, ); test::( 2999999999999999999999999, 2000000000000000000000000, Nearest, 2000000000000000000000000, Less, ); test::( 3000000000000000000000000, 2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::( 3000000000000000000000001, 2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::(0, -1, Down, 0, Equal); test::(0, -1, Floor, 0, Equal); test::(0, -1, Up, 0, Equal); test::(0, -1, Ceiling, 0, Equal); test::(0, -1, Nearest, 0, Equal); test::(0, -1, Exact, 0, Equal); test::(0, -123, Down, 0, Equal); test::(0, -123, Floor, 0, Equal); test::(0, -123, Up, 0, Equal); test::(0, -123, Ceiling, 0, Equal); test::(0, -123, Nearest, 0, Equal); test::(0, -123, Exact, 0, Equal); test::(1, -1, Down, 1, Equal); test::(1, -1, Floor, 1, Equal); test::(1, -1, Up, 1, Equal); test::(1, -1, Ceiling, 1, Equal); test::(1, -1, Nearest, 1, Equal); test::(1, -1, Exact, 1, Equal); test::(123, -1, Down, 123, Equal); test::(123, -1, Floor, 123, Equal); test::(123, -1, Up, 123, Equal); test::(123, -1, Ceiling, 123, Equal); test::(123, -1, Nearest, 123, Equal); test::(123, -1, Exact, 123, Equal); test::(123, -2, Down, 122, Less); test::(123, -2, Floor, 122, Less); test::(123, -2, Up, 124, Greater); test::(123, -2, Ceiling, 124, Greater); test::(123, -2, Nearest, 124, Greater); test::(125, -2, Down, 124, Less); test::(125, -2, Floor, 124, Less); test::(125, -2, Up, 126, Greater); test::(125, -2, Ceiling, 126, Greater); test::(125, -2, Nearest, 124, Less); test::(123, -123, Down, 123, Equal); test::(123, -123, Floor, 123, Equal); test::(123, -123, Up, 123, Equal); test::(123, -123, Ceiling, 123, Equal); test::(123, -123, Nearest, 123, Equal); test::(123, -123, Exact, 123, Equal); test::(123, -456, Down, 0, Less); test::(123, -456, Floor, 0, Less); test::(123, -456, Up, 456, Greater); test::(123, -456, Ceiling, 456, Greater); test::(123, -456, Nearest, 0, Less); test::(1000000000000, -1, Down, 1000000000000, Equal); test::(1000000000000, -1, Floor, 1000000000000, Equal); test::(1000000000000, -1, Up, 1000000000000, Equal); test::(1000000000000, -1, Ceiling, 1000000000000, Equal); test::(1000000000000, -1, Nearest, 1000000000000, Equal); test::(1000000000000, -1, Exact, 1000000000000, Equal); test::(1000000000000, -3, Down, 999999999999, Less); test::(1000000000000, -3, Floor, 999999999999, Less); test::(1000000000000, -3, Up, 1000000000002, Greater); test::(1000000000000, -3, Ceiling, 1000000000002, Greater); test::(1000000000000, -3, Nearest, 999999999999, Less); test::(999999999999, -2, Down, 999999999998, Less); test::(999999999999, -2, Floor, 999999999998, Less); test::(999999999999, -2, Up, 1000000000000, Greater); test::(999999999999, -2, Ceiling, 1000000000000, Greater); test::(999999999999, -2, Nearest, 1000000000000, Greater); test::(1000000000001, -2, Down, 1000000000000, Less); test::(1000000000001, -2, Floor, 1000000000000, Less); test::(1000000000001, -2, Up, 1000000000002, Greater); test::(1000000000001, -2, Ceiling, 1000000000002, Greater); test::(1000000000001, -2, Nearest, 1000000000000, Less); test::( 1000000000000000000000000, -0xffffffff, Down, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, -0xffffffff, Floor, 999999999999996832276305, Less, ); test::( 1000000000000000000000000, -0xffffffff, Up, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, -0xffffffff, Ceiling, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, -0xffffffff, Nearest, 1000000000000001127243600, Greater, ); test::( 1000000000000000000000000, 1000000000000, Down, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Floor, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Up, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000000, Ceiling, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Nearest, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, 1000000000000, Exact, 1000000000000000000000000, Equal, ); test::( 1000000000000000000000000, -1000000000001, Down, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, -1000000000001, Floor, 999999999999999999999999, Less, ); test::( 1000000000000000000000000, -1000000000001, Up, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, -1000000000001, Ceiling, 1000000000001000000000000, Greater, ); test::( 1000000000000000000000000, -1000000000001, Nearest, 999999999999999999999999, Less, ); test::( 2999999999999999999999999, -2000000000000000000000000, Nearest, 2000000000000000000000000, Less, ); test::( 3000000000000000000000000, -2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::( 3000000000000000000000001, -2000000000000000000000000, Nearest, 4000000000000000000000000, Greater, ); test::(-1, 1, Down, -1, Equal); test::(-1, 1, Floor, -1, Equal); test::(-1, 1, Up, -1, Equal); test::(-1, 1, Ceiling, -1, Equal); test::(-1, 1, Nearest, -1, Equal); test::(-1, 1, Exact, -1, Equal); test::(-123, 1, Down, -123, Equal); test::(-123, 1, Floor, -123, Equal); test::(-123, 1, Up, -123, Equal); test::(-123, 1, Ceiling, -123, Equal); test::(-123, 1, Nearest, -123, Equal); test::(-123, 1, Exact, -123, Equal); test::(-123, 2, Down, -122, Greater); test::(-123, 2, Floor, -124, Less); test::(-123, 2, Up, -124, Less); test::(-123, 2, Ceiling, -122, Greater); test::(-123, 2, Nearest, -124, Less); test::(-125, 2, Down, -124, Greater); test::(-125, 2, Floor, -126, Less); test::(-125, 2, Up, -126, Less); test::(-125, 2, Ceiling, -124, Greater); test::(-125, 2, Nearest, -124, Greater); test::(-123, 123, Down, -123, Equal); test::(-123, 123, Floor, -123, Equal); test::(-123, 123, Up, -123, Equal); test::(-123, 123, Ceiling, -123, Equal); test::(-123, 123, Nearest, -123, Equal); test::(-123, 123, Exact, -123, Equal); test::(-123, 456, Down, 0, Greater); test::(-123, 456, Floor, -456, Less); test::(-123, 456, Up, -456, Less); test::(-123, 456, Ceiling, 0, Greater); test::(-123, 456, Nearest, 0, Greater); test::(-1000000000000, 1, Down, -1000000000000, Equal); test::(-1000000000000, 1, Floor, -1000000000000, Equal); test::(-1000000000000, 1, Up, -1000000000000, Equal); test::(-1000000000000, 1, Ceiling, -1000000000000, Equal); test::(-1000000000000, 1, Nearest, -1000000000000, Equal); test::(-1000000000000, 1, Exact, -1000000000000, Equal); test::(-1000000000000, 3, Down, -999999999999, Greater); test::(-1000000000000, 3, Floor, -1000000000002, Less); test::(-1000000000000, 3, Up, -1000000000002, Less); test::(-1000000000000, 3, Ceiling, -999999999999, Greater); test::(-1000000000000, 3, Nearest, -999999999999, Greater); test::(-999999999999, 2, Down, -999999999998, Greater); test::(-999999999999, 2, Floor, -1000000000000, Less); test::(-999999999999, 2, Up, -1000000000000, Less); test::(-999999999999, 2, Ceiling, -999999999998, Greater); test::(-999999999999, 2, Nearest, -1000000000000, Less); test::(-1000000000001, 2, Down, -1000000000000, Greater); test::(-1000000000001, 2, Floor, -1000000000002, Less); test::(-1000000000001, 2, Up, -1000000000002, Less); test::(-1000000000001, 2, Ceiling, -1000000000000, Greater); test::(-1000000000001, 2, Nearest, -1000000000000, Greater); test::( -1000000000000000000000000, 0xffffffff, Down, -999999999999996832276305, Greater, ); test::( -1000000000000000000000000, 0xffffffff, Floor, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, 0xffffffff, Up, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, 0xffffffff, Ceiling, -999999999999996832276305, Greater, ); test::( -1000000000000000000000000, 0xffffffff, Nearest, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, 1000000000000, Down, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Floor, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Up, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Ceiling, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Nearest, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000000, Exact, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, 1000000000001, Down, -999999999999999999999999, Greater, ); test::( -1000000000000000000000000, 1000000000001, Floor, -1000000000001000000000000, Less, ); test::( -1000000000000000000000000, 1000000000001, Up, -1000000000001000000000000, Less, ); test::( -1000000000000000000000000, 1000000000001, Ceiling, -999999999999999999999999, Greater, ); test::( -1000000000000000000000000, 1000000000001, Nearest, -999999999999999999999999, Greater, ); test::( -2999999999999999999999999, 2000000000000000000000000, Nearest, -2000000000000000000000000, Greater, ); test::( -3000000000000000000000000, 2000000000000000000000000, Nearest, -4000000000000000000000000, Less, ); test::( -3000000000000000000000001, 2000000000000000000000000, Nearest, -4000000000000000000000000, Less, ); test::(-1, -1, Down, -1, Equal); test::(-1, -1, Floor, -1, Equal); test::(-1, -1, Up, -1, Equal); test::(-1, -1, Ceiling, -1, Equal); test::(-1, -1, Nearest, -1, Equal); test::(-1, -1, Exact, -1, Equal); test::(-123, -1, Down, -123, Equal); test::(-123, -1, Floor, -123, Equal); test::(-123, -1, Up, -123, Equal); test::(-123, -1, Ceiling, -123, Equal); test::(-123, -1, Nearest, -123, Equal); test::(-123, -1, Exact, -123, Equal); test::(-123, -2, Down, -122, Greater); test::(-123, -2, Floor, -124, Less); test::(-123, -2, Up, -124, Less); test::(-123, -2, Ceiling, -122, Greater); test::(-123, -2, Nearest, -124, Less); test::(-125, -2, Down, -124, Greater); test::(-125, -2, Floor, -126, Less); test::(-125, -2, Up, -126, Less); test::(-125, -2, Ceiling, -124, Greater); test::(-125, -2, Nearest, -124, Greater); test::(-123, -123, Down, -123, Equal); test::(-123, -123, Floor, -123, Equal); test::(-123, -123, Up, -123, Equal); test::(-123, -123, Ceiling, -123, Equal); test::(-123, -123, Nearest, -123, Equal); test::(-123, -123, Exact, -123, Equal); test::(-123, -456, Down, 0, Greater); test::(-123, -456, Floor, -456, Less); test::(-123, -456, Up, -456, Less); test::(-123, -456, Ceiling, 0, Greater); test::(-123, -456, Nearest, 0, Greater); test::(-1000000000000, -1, Down, -1000000000000, Equal); test::(-1000000000000, -1, Floor, -1000000000000, Equal); test::(-1000000000000, -1, Up, -1000000000000, Equal); test::(-1000000000000, -1, Ceiling, -1000000000000, Equal); test::(-1000000000000, -1, Nearest, -1000000000000, Equal); test::(-1000000000000, -1, Exact, -1000000000000, Equal); test::(-1000000000000, -3, Down, -999999999999, Greater); test::(-1000000000000, -3, Floor, -1000000000002, Less); test::(-1000000000000, -3, Up, -1000000000002, Less); test::(-1000000000000, -3, Ceiling, -999999999999, Greater); test::(-1000000000000, -3, Nearest, -999999999999, Greater); test::(-999999999999, -2, Down, -999999999998, Greater); test::(-999999999999, -2, Floor, -1000000000000, Less); test::(-999999999999, -2, Up, -1000000000000, Less); test::(-999999999999, -2, Ceiling, -999999999998, Greater); test::(-999999999999, -2, Nearest, -1000000000000, Less); test::(-1000000000001, -2, Down, -1000000000000, Greater); test::(-1000000000001, -2, Floor, -1000000000002, Less); test::(-1000000000001, -2, Up, -1000000000002, Less); test::(-1000000000001, -2, Ceiling, -1000000000000, Greater); test::(-1000000000001, -2, Nearest, -1000000000000, Greater); test::( -1000000000000000000000000, -0xffffffff, Down, -999999999999996832276305, Greater, ); test::( -1000000000000000000000000, -0xffffffff, Floor, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, -0xffffffff, Up, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, -0xffffffff, Ceiling, -999999999999996832276305, Greater, ); test::( -1000000000000000000000000, -0xffffffff, Nearest, -1000000000000001127243600, Less, ); test::( -1000000000000000000000000, -1000000000000, Down, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Floor, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Up, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Ceiling, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Nearest, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000000, Exact, -1000000000000000000000000, Equal, ); test::( -1000000000000000000000000, -1000000000001, Down, -999999999999999999999999, Greater, ); test::( -1000000000000000000000000, -1000000000001, Floor, -1000000000001000000000000, Less, ); test::( -1000000000000000000000000, -1000000000001, Up, -1000000000001000000000000, Less, ); test::( -1000000000000000000000000, -1000000000001, Ceiling, -999999999999999999999999, Greater, ); test::( -1000000000000000000000000, -1000000000001, Nearest, -999999999999999999999999, Greater, ); test::( -2999999999999999999999999, -2000000000000000000000000, Nearest, -2000000000000000000000000, Greater, ); test::( -3000000000000000000000000, -2000000000000000000000000, Nearest, -4000000000000000000000000, Less, ); test::( -3000000000000000000000001, -2000000000000000000000000, Nearest, -4000000000000000000000000, Less, ); test::(-128, 1, Down, -128, Equal); test::(-128, 1, Up, -128, Equal); test::(-128, 1, Floor, -128, Equal); test::(-128, 1, Ceiling, -128, Equal); test::(-128, 1, Nearest, -128, Equal); test::(-128, 1, Exact, -128, Equal); test::(-128, -1, Down, -128, Equal); test::(-128, -1, Up, -128, Equal); test::(-128, -1, Floor, -128, Equal); test::(-128, -1, Ceiling, -128, Equal); test::(-128, -1, Nearest, -128, Equal); test::(-128, -1, Exact, -128, Equal); test::(-128, -128, Down, -128, Equal); test::(-128, -128, Up, -128, Equal); test::(-128, -128, Floor, -128, Equal); test::(-128, -128, Ceiling, -128, Equal); test::(-128, -128, Nearest, -128, Equal); test::(-128, -128, Exact, -128, Equal); test::(0, 0, Floor, 0, Equal); test::(0, 0, Ceiling, 0, Equal); test::(0, 0, Down, 0, Equal); test::(0, 0, Up, 0, Equal); test::(0, 0, Nearest, 0, Equal); test::(0, 0, Exact, 0, Equal); test::(2, 0, Floor, 0, Less); test::(2, 0, Down, 0, Less); test::(2, 0, Nearest, 0, Less); test::(-2, 0, Ceiling, 0, Greater); test::(-2, 0, Down, 0, Greater); test::(-2, 0, Nearest, 0, Greater); } fn round_to_multiple_fail_helper() { assert_panic!(T::exact_from(10).round_to_multiple(T::ZERO, Up)); assert_panic!(T::exact_from(10).round_to_multiple(T::exact_from(3), Exact)); assert_panic!(T::MAX.round_to_multiple(T::TWO, Ceiling)); assert_panic!(T::ONE.round_to_multiple(T::ZERO, Up)); assert_panic!(T::ONE.round_to_multiple(T::ZERO, Ceiling)); assert_panic!(T::ONE.round_to_multiple(T::ZERO, Exact)); assert_panic!(T::exact_from(10).round_to_multiple_assign(T::ZERO, Up)); assert_panic!({ T::exact_from(10).round_to_multiple_assign(T::exact_from(3), Exact); }); assert_panic!({ let mut n = T::MAX; n.round_to_multiple_assign(T::TWO, Ceiling); }); assert_panic!({ let mut n = T::ONE; n.round_to_multiple_assign(T::ZERO, Up); }); assert_panic!({ let mut n = T::ONE; n.round_to_multiple_assign(T::ZERO, Ceiling); }); assert_panic!({ let mut n = T::ONE; n.round_to_multiple_assign(T::ZERO, Exact); }); } fn round_to_multiple_signed_fail_helper() { assert_panic!(T::MIN.round_to_multiple(T::exact_from(3), Floor)); assert_panic!(T::NEGATIVE_ONE.round_to_multiple(T::ZERO, Up)); assert_panic!(T::NEGATIVE_ONE.round_to_multiple(T::ZERO, Floor)); assert_panic!(T::NEGATIVE_ONE.round_to_multiple(T::ZERO, Exact)); assert_panic!({ let mut n = T::MIN; n.round_to_multiple_assign(T::exact_from(3), Floor); }); assert_panic!({ let mut n = T::NEGATIVE_ONE; n.round_to_multiple_assign(T::ZERO, Up); }); assert_panic!({ let mut n = T::NEGATIVE_ONE; n.round_to_multiple_assign(T::ZERO, Floor); }); assert_panic!({ let mut n = T::NEGATIVE_ONE; n.round_to_multiple_assign(T::ZERO, Exact); }); } #[test] fn round_to_multiple_fail() { apply_fn_to_primitive_ints!(round_to_multiple_fail_helper); apply_fn_to_signeds!(round_to_multiple_signed_fail_helper); } fn round_to_multiple_properties_helper_unsigned() { unsigned_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(x, y, rm)| { let (rounded, o) = x.round_to_multiple(y, rm); let mut mut_x = x; assert_eq!(mut_x.round_to_multiple_assign(y, rm), o); assert_eq!(mut_x, rounded); assert!(rounded.divisible_by(y)); assert_eq!(rounded.cmp(&x), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } match rm { Floor | Down => { assert!(rounded <= x); } Ceiling | Up => { assert!(rounded >= x); } Exact => assert_eq!(rounded, x), Nearest => { if y == T::ZERO { assert_eq!(rounded, T::ZERO); } else { let mut closest = None; let mut second_closest = None; if rounded <= x { if let Some(above) = rounded.checked_add(y) { closest = Some(x - rounded); second_closest = Some(above - x); } } else if let Some(below) = rounded.checked_sub(y) { closest = Some(rounded - x); second_closest = Some(x - below); } if let (Some(closest), Some(second_closest)) = (closest, second_closest) { assert!(closest <= second_closest); if closest == second_closest { assert!(rounded.div_exact(y).even()); } } } } } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(x.round_to_multiple(y, rm), (rounded, Equal)); } } else { assert_panic!(x.round_to_multiple(y, Exact)); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { if let Some(product) = x.checked_mul(y) { let xo = (product, Equal); assert_eq!(product.round_to_multiple(y, Down), xo); assert_eq!(product.round_to_multiple(y, Up), xo); assert_eq!(product.round_to_multiple(y, Floor), xo); assert_eq!(product.round_to_multiple(y, Ceiling), xo); assert_eq!(product.round_to_multiple(y, Nearest), xo); assert_eq!(product.round_to_multiple(y, Exact), xo); } }); unsigned_pair_gen_var_13::().test_properties(|(x, y)| { let down = x.round_to_multiple(y, Down); assert_eq!(down.1, Less); if let Some(up) = down.0.checked_add(y) { let up = (up, Greater); assert_eq!(x.round_to_multiple(y, Up), up); assert_eq!(x.round_to_multiple(y, Floor), down); assert_eq!(x.round_to_multiple(y, Ceiling), up); let nearest = x.round_to_multiple(y, Nearest); assert!(nearest == down || nearest == up); } }); unsigned_rounding_mode_pair_gen::().test_properties(|(n, rm)| { if rm == Floor || rm == Down || rm == Nearest { assert_eq!( n.round_to_multiple(T::ZERO, rm), (T::ZERO, if n == T::ZERO { Equal } else { Less }) ); } assert_eq!(T::ZERO.round_to_multiple(n, rm), (T::ZERO, Equal)); assert_eq!(n.round_to_multiple(T::ONE, rm), (n, Equal)); assert_eq!(n.round_to_multiple(n, rm), (n, Equal)); }); } fn round_to_multiple_properties_helper_signed< U: PrimitiveUnsigned, S: TryFrom + ConvertibleFrom + PrimitiveSigned + UnsignedAbs, >() { signed_signed_rounding_mode_triple_gen_var_2::().test_properties(|(x, y, rm)| { let (rounded, o) = x.round_to_multiple(y, rm); let mut mut_x = x; assert_eq!(mut_x.round_to_multiple_assign(y, rm), o); assert_eq!(mut_x, rounded); assert!(rounded.divisible_by(y)); assert_eq!(rounded.cmp(&x), o); match (x >= S::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } match rm { Floor => assert!(rounded <= x), Ceiling => assert!(rounded >= x), Down => assert!(rounded.le_abs(&x)), Up => assert!(rounded.ge_abs(&x)), Exact => assert_eq!(rounded, x), Nearest => { if y == S::ZERO { assert_eq!(rounded, S::ZERO); } else { let mut closest = None; let mut second_closest = None; let (o_above, o_below) = if y >= S::ZERO { (rounded.checked_add(y), rounded.checked_sub(y)) } else { (rounded.checked_sub(y), rounded.checked_add(y)) }; if rounded <= x { if let Some(above) = o_above { closest = x.checked_sub(rounded); second_closest = above.checked_sub(x); } } else if let Some(below) = o_below { closest = rounded.checked_sub(x); second_closest = x.checked_sub(below); } if let (Some(closest), Some(second_closest)) = (closest, second_closest) { assert!(closest <= second_closest); if closest == second_closest { assert!(rounded.div_exact(y).even()); } } } } } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(x.round_to_multiple(y, rm), (rounded, Equal)); } } else { assert_panic!(x.round_to_multiple(y, Exact)); } }); signed_pair_gen::().test_properties(|(x, y)| { if let Some(product) = x.checked_mul(y) { let xo = (product, Equal); assert_eq!(product.round_to_multiple(y, Down), xo); assert_eq!(product.round_to_multiple(y, Up), xo); assert_eq!(product.round_to_multiple(y, Floor), xo); assert_eq!(product.round_to_multiple(y, Ceiling), xo); assert_eq!(product.round_to_multiple(y, Nearest), xo); assert_eq!(product.round_to_multiple(y, Exact), xo); } }); signed_pair_gen_var_5::().test_properties(|(x, y)| { let down = x.round_to_multiple(y, Down); assert_eq!(down.1, if x >= S::ZERO { Less } else { Greater }); if let Some(up) = if (x >= S::ZERO) == (y >= S::ZERO) { down.0.checked_add(y) } else { down.0.checked_sub(y) } { let up = (up, if x >= S::ZERO { Greater } else { Less }); assert_eq!(x.round_to_multiple(y, Up), up); if x >= S::ZERO { assert_eq!(x.round_to_multiple(y, Floor), down); assert_eq!(x.round_to_multiple(y, Ceiling), up); } else { assert_eq!(x.round_to_multiple(y, Floor), up); assert_eq!(x.round_to_multiple(y, Ceiling), down); } let nearest = x.round_to_multiple(y, Nearest); assert!(nearest == down || nearest == up); } }); signed_rounding_mode_pair_gen::().test_properties(|(n, rm)| { if rm == Down || rm == Nearest || rm == if n >= S::ZERO { Floor } else { Ceiling } { assert_eq!( n.round_to_multiple(S::ZERO, rm), (S::ZERO, n.cmp(&S::ZERO).reverse()) ); } assert_eq!(S::ZERO.round_to_multiple(n, rm), (S::ZERO, Equal)); assert_eq!(n.round_to_multiple(S::ONE, rm), (n, Equal)); assert_eq!(n.round_to_multiple(n, rm), (n, Equal)); }); } #[test] fn round_to_multiple_properties() { apply_fn_to_unsigneds!(round_to_multiple_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(round_to_multiple_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_8, signed_unsigned_pair_gen_var_16, signed_unsigned_pair_gen_var_17, signed_unsigned_rounding_mode_triple_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_14, unsigned_pair_gen_var_21, unsigned_rounding_mode_pair_gen, unsigned_unsigned_rounding_mode_triple_gen_var_3, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_round_to_multiple_of_power_of_2() { fn test(n: T, pow: u64, rm: RoundingMode, out: T, o: Ordering) { assert_eq!(n.round_to_multiple_of_power_of_2(pow, rm), (out, o)); let mut n = n; assert_eq!(n.round_to_multiple_of_power_of_2_assign(pow, rm), o); assert_eq!(n, out); } test::(0, 10, Exact, 0, Equal); test::(17, 0, Exact, 17, Equal); test::(10, 2, Floor, 8, Less); test::(10, 2, Ceiling, 12, Greater); test::(10, 2, Down, 8, Less); test::(10, 2, Up, 12, Greater); test::(10, 2, Nearest, 8, Less); test::(12, 2, Exact, 12, Equal); test::(-10, 2, Floor, -12, Less); test::(-10, 2, Ceiling, -8, Greater); test::(-10, 2, Down, -8, Greater); test::(-10, 2, Up, -12, Less); test::(-10, 2, Nearest, -8, Greater); test::(-12, 2, Exact, -12, Equal); test::(0xff, 4, Down, 0xf0, Less); test::(0xff, 4, Floor, 0xf0, Less); test::(0xef, 4, Up, 0xf0, Greater); test::(0xef, 4, Ceiling, 0xf0, Greater); test::(0xe8, 4, Nearest, 0xe0, Less); test::(1, 8, Nearest, 0, Less); test::(0x7f, 4, Down, 0x70, Less); test::(0x7f, 4, Floor, 0x70, Less); test::(0x6f, 4, Up, 0x70, Greater); test::(0x6f, 4, Ceiling, 0x70, Greater); test::(0x68, 4, Nearest, 0x60, Less); test::(-0x7f, 4, Down, -0x70, Greater); test::(-0x7f, 4, Floor, -0x80, Less); test::(-0x7f, 4, Up, -0x80, Less); test::(-0x7f, 4, Ceiling, -0x70, Greater); test::(-0x78, 4, Nearest, -0x80, Less); } fn round_to_multiple_of_power_of_2_fail_helper() { assert_panic!(T::exact_from(10).round_to_multiple_of_power_of_2(4, Exact)); assert_panic!(T::MAX.round_to_multiple_of_power_of_2(4, Up)); assert_panic!(T::MAX.round_to_multiple_of_power_of_2(4, Ceiling)); assert_panic!(T::MAX.round_to_multiple_of_power_of_2(4, Nearest)); assert_panic!(T::ONE.round_to_multiple_of_power_of_2(T::WIDTH, Up)); assert_panic!(T::exact_from(10).round_to_multiple_of_power_of_2_assign(4, Exact)); assert_panic!({ let mut n = T::MAX; n.round_to_multiple_of_power_of_2_assign(4, Up); }); assert_panic!({ let mut n = T::MAX; n.round_to_multiple_of_power_of_2_assign(4, Ceiling); }); assert_panic!({ let mut n = T::MAX; n.round_to_multiple_of_power_of_2_assign(4, Nearest); }); assert_panic!({ let mut n = T::ONE; n.round_to_multiple_of_power_of_2_assign(T::WIDTH, Up); }); } fn round_to_multiple_of_power_of_2_signed_fail_helper() { assert_panic!((-T::MAX).round_to_multiple_of_power_of_2(T::WIDTH, Up)); assert_panic!((-T::MAX).round_to_multiple_of_power_of_2(T::WIDTH, Floor)); assert_panic!((-T::MAX).round_to_multiple_of_power_of_2_assign(T::WIDTH, Up)); assert_panic!({ (-T::MAX).round_to_multiple_of_power_of_2_assign(T::WIDTH, Floor); }); } #[test] fn round_to_multiple_of_power_of_2_fail() { apply_fn_to_primitive_ints!(round_to_multiple_of_power_of_2_fail_helper); apply_fn_to_signeds!(round_to_multiple_of_power_of_2_signed_fail_helper); } fn round_to_multiple_of_power_of_2_properties_helper_unsigned() { unsigned_unsigned_rounding_mode_triple_gen_var_3::().test_properties(|(n, pow, rm)| { let (rounded, o) = n.round_to_multiple_of_power_of_2(pow, rm); let mut mut_n = n; assert_eq!(mut_n.round_to_multiple_of_power_of_2_assign(pow, rm), o); assert_eq!(mut_n, rounded); assert!(rounded.divisible_by_power_of_2(pow)); assert_eq!(rounded.cmp(&n), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } match rm { Floor | Down => { assert!(rounded <= n); } Ceiling | Up => { assert!(rounded >= n); } Exact => assert_eq!(rounded, n), Nearest => { if let Some(k) = T::ONE.arithmetic_checked_shl(pow) { let mut closest = None; let mut second_closest = None; if rounded <= n { if let Some(above) = rounded.checked_add(k) { closest = Some(n - rounded); second_closest = Some(above - n); } } else if let Some(below) = rounded.checked_sub(k) { closest = Some(rounded - n); second_closest = Some(n - below); } if let (Some(closest), Some(second_closest)) = (closest, second_closest) { assert!(closest <= second_closest); if closest == second_closest { assert!(!rounded.get_bit(pow)); } } } } } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.round_to_multiple_of_power_of_2(pow, rm), (rounded, Equal)); } } else { assert_panic!(n.round_to_multiple_of_power_of_2(pow, Exact)); } }); unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { if pow < T::WIDTH && let Some(shifted) = n.arithmetic_checked_shl(pow) { let so = (shifted, Equal); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Down), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Up), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Floor), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Ceiling), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Nearest), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Exact), so); } }); unsigned_pair_gen_var_14::().test_properties(|(n, pow)| { let down = n.round_to_multiple_of_power_of_2(pow, Down); assert_eq!(down.1, Less); if let Some(k) = T::ONE.arithmetic_checked_shl(pow) && let Some(up) = down.0.checked_add(k) { let up = (up, Greater); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Up), up); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Floor), down); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Ceiling), up); let nearest = n.round_to_multiple_of_power_of_2(pow, Nearest); assert!(nearest == down || nearest == up); } }); unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { if let Some(shift) = pow.checked_add(T::WIDTH) { assert_eq!( n.round_to_multiple_of_power_of_2(shift, Down), (T::ZERO, if n == T::ZERO { Equal } else { Less }) ); assert_eq!( n.round_to_multiple_of_power_of_2(shift, Floor), (T::ZERO, if n == T::ZERO { Equal } else { Less }) ); if let Some(extra_shift) = shift.checked_add(1) { assert_eq!( n.round_to_multiple_of_power_of_2(extra_shift, Nearest), (T::ZERO, if n == T::ZERO { Equal } else { Less }) ); } } }); unsigned_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.round_to_multiple_of_power_of_2(0, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen().test_properties(|(pow, rm)| { assert_eq!( T::ZERO.round_to_multiple_of_power_of_2(pow, rm), (T::ZERO, Equal) ); }); } fn round_to_multiple_of_power_of_2_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { signed_unsigned_rounding_mode_triple_gen_var_1::().test_properties(|(n, pow, rm)| { let (rounded, o) = n.round_to_multiple_of_power_of_2(pow, rm); let mut mut_n = n; assert_eq!(mut_n.round_to_multiple_of_power_of_2_assign(pow, rm), o); assert_eq!(mut_n, rounded); assert!(rounded.divisible_by_power_of_2(pow)); assert_eq!(rounded.cmp(&n), o); match (n >= S::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } match rm { Floor => assert!(rounded <= n), Ceiling => assert!(rounded >= n), Down => assert!(rounded.le_abs(&n)), Up => assert!(rounded.ge_abs(&n)), Exact => assert_eq!(rounded, n), Nearest => { if let Some(k) = S::ONE.arithmetic_checked_shl(pow) { let mut closest = None; let mut second_closest = None; if rounded <= n { if let Some(above) = rounded.checked_add(k) { closest = Some(n - rounded); second_closest = Some(above - n); } } else if let Some(below) = rounded.checked_sub(k) { closest = Some(rounded - n); second_closest = Some(n - below); } if let (Some(closest), Some(second_closest)) = (closest, second_closest) { assert!(closest <= second_closest); if closest == second_closest { assert!(!rounded.get_bit(pow)); } } } } } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.round_to_multiple_of_power_of_2(pow, rm), (rounded, Equal)); } } else { assert_panic!(n.round_to_multiple_of_power_of_2(pow, Exact)); } }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, pow)| { if pow < S::WIDTH && let Some(shifted) = n.arithmetic_checked_shl(pow) { let so = (shifted, Equal); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Down), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Up), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Floor), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Ceiling), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Nearest), so); assert_eq!(shifted.round_to_multiple_of_power_of_2(pow, Exact), so); } }); signed_unsigned_pair_gen_var_8::().test_properties(|(n, pow)| { let down = n.round_to_multiple_of_power_of_2(pow, Down); assert_eq!(down.1, if n >= S::ZERO { Less } else { Greater }); if let Some(k) = S::ONE.arithmetic_checked_shl(pow) && let Some(up) = if n >= S::ZERO { down.0.checked_add(k) } else { down.0.checked_sub(k) } { let up = (up, if n >= S::ZERO { Greater } else { Less }); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Up), up); if n >= S::ZERO { assert_eq!(n.round_to_multiple_of_power_of_2(pow, Floor), down); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Ceiling), up); } else { assert_eq!(n.round_to_multiple_of_power_of_2(pow, Floor), up); assert_eq!(n.round_to_multiple_of_power_of_2(pow, Ceiling), down); } let nearest = n.round_to_multiple_of_power_of_2(pow, Nearest); assert!(nearest == down || nearest == up); } }); signed_unsigned_pair_gen_var_16::().test_properties(|(i, pow)| { if let Some(shift) = pow.checked_add(S::WIDTH - 1) { assert_eq!( i.round_to_multiple_of_power_of_2(shift, Down), (S::ZERO, if i == S::ZERO { Equal } else { Less }) ); assert_eq!( i.round_to_multiple_of_power_of_2(shift, Floor), (S::ZERO, if i == S::ZERO { Equal } else { Less }) ); if let Some(extra_shift) = shift.checked_add(1) { assert_eq!( i.round_to_multiple_of_power_of_2(extra_shift, Nearest), (S::ZERO, if i == S::ZERO { Equal } else { Less }) ); } } }); signed_unsigned_pair_gen_var_17::().test_properties(|(i, pow)| { if let Some(shift) = pow.checked_add(S::WIDTH - 1) { assert_eq!( i.round_to_multiple_of_power_of_2(shift, Down), (S::ZERO, if i == S::ZERO { Equal } else { Greater }) ); assert_eq!( i.round_to_multiple_of_power_of_2(shift, Ceiling), (S::ZERO, if i == S::ZERO { Equal } else { Greater }) ); if let Some(extra_shift) = shift.checked_add(1) { assert_eq!( i.round_to_multiple_of_power_of_2(extra_shift, Nearest), (S::ZERO, if i == S::ZERO { Equal } else { Greater }) ); } } }); signed_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.round_to_multiple_of_power_of_2(0, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen().test_properties(|(pow, rm)| { assert_eq!( S::ZERO.round_to_multiple_of_power_of_2(pow, rm), (S::ZERO, Equal) ); }); } #[test] fn round_to_multiple_of_power_of_2_properties() { apply_fn_to_unsigneds!(round_to_multiple_of_power_of_2_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(round_to_multiple_of_power_of_2_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::generators::signed_gen; fn saturating_abs_assign_helper() { let test = |n: T, out| { assert_eq!(n.saturating_abs(), out); let mut n = n; n.saturating_abs_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::ONE); test(T::exact_from(100), T::exact_from(100)); test(T::MAX, T::MAX); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); test(T::MIN, T::MAX); } #[test] fn test_saturating_abs_assign() { apply_fn_to_signeds!(saturating_abs_assign_helper); } fn saturating_abs_properties_helper() { signed_gen::().test_properties(|n| { let mut abs = n; abs.saturating_abs_assign(); assert_eq!(abs, n.saturating_abs()); assert_eq!(abs.saturating_abs(), abs); if n != T::MIN { assert_eq!(n.abs(), abs); } assert_eq!(abs == n, n >= T::ZERO); }); } #[test] fn saturating_abs_properties() { apply_fn_to_signeds!(saturating_abs_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_saturating_add() { fn test(x: T, y: T, out: T) { assert_eq!(x.saturating_add(y), out); let mut x = x; x.saturating_add_assign(y); assert_eq!(x, out); } test::(123, 456, 579); test::(123, 200, 255); test::(123, -456, -333); test::(123, 45, 127); test::(-123, -45, -128); } fn saturating_add_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut sum = x; sum.saturating_add_assign(y); assert_eq!(sum, x.saturating_add(y)); assert_eq!(y.saturating_add(x), sum); assert!(sum >= x); assert!(sum >= y); if sum < T::MAX { assert_eq!(sum, x + y); } }); } fn saturating_add_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut sum = x; sum.saturating_add_assign(y); assert_eq!(sum, x.saturating_add(y)); assert_eq!(y.saturating_add(x), sum); if sum > T::MIN && sum < T::MAX { assert_eq!(sum, x + y); } }); } #[test] fn saturating_add_properties() { apply_fn_to_unsigneds!(saturating_add_properties_helper_unsigned); apply_fn_to_signeds!(saturating_add_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_saturating_add_mul() { fn test(x: T, y: T, z: T, out: T) { assert_eq!(x.saturating_add_mul(y, z), out); let mut x = x; x.saturating_add_mul_assign(y, z); assert_eq!(x, out); } test::(2, 3, 7, 23); test::(7, 5, 10, 57); test::(123, 456, 789, 359907); test::(123, -456, 789, -359661); test::(-123, 456, 789, 359661); test::(127, -2, 100, -73); test::(-127, 2, 100, 73); test::(-128, 1, 0, -128); test::(2, 20, 20, 255); test::(-127, -2, 100, -128); test::(127, 1, 100, 127); test::(-127, -1, 100, -128); test::(-127, -10, 100, -128); } fn saturating_add_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.saturating_add_mul(y, z); let mut x_alt = x; x_alt.saturating_add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.saturating_add_mul(z, y), result); assert!(result >= x); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.saturating_add_mul(T::ZERO, b), a); assert_eq!(a.saturating_add_mul(T::ONE, b), a.saturating_add(b)); assert_eq!(T::ZERO.saturating_add_mul(a, b), a.saturating_mul(b)); assert_eq!(a.saturating_add_mul(b, T::ZERO), a); assert_eq!(a.saturating_add_mul(b, T::ONE), a.saturating_add(b)); }); } fn saturating_add_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.saturating_add_mul(y, z); let mut x_alt = x; x_alt.saturating_add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.saturating_add_mul(z, y), result); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.saturating_add_mul(T::ZERO, b), a); assert_eq!(a.saturating_add_mul(T::ONE, b), a.saturating_add(b)); assert_eq!(T::ZERO.saturating_add_mul(a, b), a.saturating_mul(b)); assert_eq!(a.saturating_add_mul(b, T::ZERO), a); assert_eq!(a.saturating_add_mul(b, T::ONE), a.saturating_add(b)); }); } #[test] fn saturating_add_mul_properties() { apply_fn_to_unsigneds!(saturating_add_mul_properties_helper_unsigned); apply_fn_to_signeds!(saturating_add_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_saturating_mul() { fn test(x: T, y: T, out: T) { assert_eq!(x.saturating_mul(y), out); let mut x = x; x.saturating_mul_assign(y); assert_eq!(x, out); } test::(123, 456, 56088); test::(123, 200, 255); test::(123, -45, -5535); test::(123, 45, 127); test::(-123, 45, -128); } fn saturating_mul_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut product = x; product.saturating_mul_assign(y); assert_eq!(product, x.saturating_mul(y)); assert_eq!(y.saturating_mul(x), product); assert!(product == T::ZERO || product >= x); assert!(product == T::ZERO || product >= y); if product < T::MAX { assert_eq!(product, x * y); } }); } fn saturating_mul_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut product = x; product.saturating_mul_assign(y); assert_eq!(product, x.saturating_mul(y)); assert_eq!(y.saturating_mul(x), product); if product > T::MIN && product < T::MAX { assert_eq!(product, x * y); } }); } #[test] fn saturating_mul_properties() { apply_fn_to_unsigneds!(saturating_mul_properties_helper_unsigned); apply_fn_to_signeds!(saturating_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::generators::signed_gen; fn saturating_neg_assign_helper() { let test = |n: T, out| { assert_eq!(n.saturating_neg(), out); let mut n = n; n.saturating_neg_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::NEGATIVE_ONE); test(T::exact_from(100), T::exact_from(-100)); test(T::MAX, T::MIN + T::ONE); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); test(T::MIN, T::MAX); } #[test] fn test_saturating_neg_assign() { apply_fn_to_signeds!(saturating_neg_assign_helper); } fn saturating_neg_properties_helper() { signed_gen::().test_properties(|n| { let mut neg = n; neg.saturating_neg_assign(); assert_eq!(neg, n.saturating_neg()); if n != T::MIN { assert_eq!(neg.saturating_neg(), n); } assert_eq!(neg == n, n == T::ZERO); }); } #[test] fn saturating_neg_properties() { apply_fn_to_signeds!(saturating_neg_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; #[test] fn test_saturating_pow() { fn test(x: T, y: u64, out: T) { assert_eq!(x.saturating_pow(y), out); let mut x = x; x.saturating_pow_assign(y); assert_eq!(x, out); } test::(0, 0, 1); test::(123, 0, 1); test::(123, 1, 123); test::(0, 123, 0); test::(1, 123, 1); test::(-1, 123, -1); test::(-1, 124, 1); test::(3, 3, 27); test::(-10, 9, -1000000000); test::(-10, 10, i32::MAX); test::(-10, 9, i16::MIN); test::(10, 9, i16::MAX); test::(123, 456, i64::MAX); test::(0, u64::MAX, 0); test::(1, u64::MAX, 1); test::(123, u64::MAX, u64::MAX); test::(0, u64::MAX, 0); test::(1, u64::MAX, 1); test::(-1, u64::MAX, -1); test::(-1, u64::MAX - 1, 1); test::(123, u64::MAX, i64::MAX); test::(-123, u64::MAX, i64::MIN); test::(-123, u64::MAX - 1, i64::MAX); } fn saturating_pow_properties_helper_unsigned() { unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.saturating_pow_assign(y); assert_eq!(power, x.saturating_pow(y)); if y != 0 { assert!(power >= x); } if power < T::MAX { assert_eq!(power, x.pow(y)); } }); } fn saturating_pow_properties_helper_signed() { signed_unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.saturating_pow_assign(y); assert_eq!(power, x.saturating_pow(y)); if power > T::MIN && power < T::MAX { assert_eq!(power, x.pow(y)); } }); } #[test] fn saturating_pow_properties() { apply_fn_to_unsigneds!(saturating_pow_properties_helper_unsigned); apply_fn_to_signeds!(saturating_pow_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; #[test] fn test_saturating_square() { fn test(x: T, out: T) { assert_eq!(x.saturating_square(), out); let mut x = x; x.saturating_square_assign(); assert_eq!(x, out); } test::(0, 0); test::(1, 1); test::(2, 4); test::(3, 9); test::(10, 100); test::(123, 15129); test::(1000, 1000000); test::(-1, 1); test::(-2, 4); test::(-3, 9); test::(-10, 100); test::(-123, 15129); test::(-1000, 1000000); test::(1000, u16::MAX); test::(-1000, i16::MAX); } fn saturating_square_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { let mut square = x; square.saturating_square_assign(); assert_eq!(square, x.saturating_square()); assert_eq!(square, x.saturating_pow(2)); assert!(square >= x); if square < T::MAX { assert_eq!(square, x.square()); } }); } fn saturating_square_properties_helper_signed() { signed_gen::().test_properties(|x| { let mut square = x; square.saturating_square_assign(); assert_eq!(square, x.saturating_square()); assert_eq!(square, x.saturating_pow(2)); if square > T::MIN && square < T::MAX { assert_eq!(square, x.square()); } }); } #[test] fn saturating_square_properties() { apply_fn_to_unsigneds!(saturating_square_properties_helper_unsigned); apply_fn_to_signeds!(saturating_square_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_saturating_sub() { fn test(x: T, y: T, out: T) { assert_eq!(x.saturating_sub(y), out); let mut x = x; x.saturating_sub_assign(y); assert_eq!(x, out); } test::(456, 123, 333); test::(123, 200, 0); test::(123, -456, 579); test::(123, -45, 127); test::(-123, 45, -128); } fn saturating_sub_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut diff = x; diff.saturating_sub_assign(y); assert_eq!(diff, x.saturating_sub(y)); assert!(diff <= x); if diff > T::ZERO { assert_eq!(diff, x - y); } }); } fn saturating_sub_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut diff = x; diff.saturating_sub_assign(y); assert_eq!(diff, x.saturating_sub(y)); if diff > T::MIN && diff < T::MAX { assert_eq!(diff, x - y); } }); } #[test] fn saturating_sub_properties() { apply_fn_to_unsigneds!(saturating_sub_properties_helper_unsigned); apply_fn_to_signeds!(saturating_sub_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_saturating_sub_mul() { fn test(x: T, y: T, z: T, out: T) { assert_eq!(x.saturating_sub_mul(y, z), out); let mut x = x; x.saturating_sub_mul_assign(y, z); assert_eq!(x, out); } test::(100, 3, 7, 79); test::(60, 5, 10, 10); test::(1000000, 456, 789, 640216); test::(123, -456, 789, 359907); test::(-123, 456, 789, -359907); test::(127, 2, 100, -73); test::(-127, -2, 100, 73); test::(-128, 1, 0, -128); test::(2, 10, 5, 0); test::(-127, 2, 100, -128); test::(-127, 1, 100, -128); test::(127, -1, 100, 127); test::(127, -10, 100, 127); } fn saturating_sub_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.saturating_sub_mul(y, z); let mut x_alt = x; x_alt.saturating_sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.saturating_sub_mul(z, y), result); assert!(result <= x); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.saturating_sub_mul(T::ZERO, b), a); assert_eq!(a.saturating_sub_mul(T::ONE, b), a.saturating_sub(b)); assert_eq!(a.saturating_sub_mul(b, T::ZERO), a); assert_eq!(a.saturating_sub_mul(b, T::ONE), a.saturating_sub(b)); }); } fn saturating_sub_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.saturating_sub_mul(y, z); let mut x_alt = x; x_alt.saturating_sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.saturating_sub_mul(z, y), result); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.saturating_sub_mul(T::ZERO, b), a); assert_eq!(a.saturating_sub_mul(T::ONE, b), a.saturating_sub(b)); assert_eq!(a.saturating_sub_mul(b, T::ZERO), a); assert_eq!(a.saturating_sub_mul(b, T::ONE), a.saturating_sub(b)); }); } #[test] fn saturating_sub_mul_properties() { apply_fn_to_unsigneds!(saturating_sub_mul_properties_helper_unsigned); apply_fn_to_signeds!(saturating_sub_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShr, ShlRound, ShlRoundAssign, ShrRound, UnsignedAbs, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_signed_rounding_mode_triple_gen_var_4, unsigned_rounding_mode_pair_gen, unsigned_signed_rounding_mode_triple_gen_var_2, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_shl_round() { fn test + ShlRoundAssign, U: PrimitiveInt>( t: T, u: U, rm: RoundingMode, out: T, o: Ordering, ) { assert_eq!(t.shl_round(u, rm), (out, o)); let mut t = t; assert_eq!(t.shl_round_assign(u, rm), o); assert_eq!(t, out); } test::(0, 0, Down, 0, Equal); test::(0, 0, Up, 0, Equal); test::(0, 0, Floor, 0, Equal); test::(0, 0, Ceiling, 0, Equal); test::(0, 0, Nearest, 0, Equal); test::(0, 0, Exact, 0, Equal); test::(0, -10, Down, 0, Equal); test::(0, -10, Up, 0, Equal); test::(0, -10, Floor, 0, Equal); test::(0, -10, Ceiling, 0, Equal); test::(0, -10, Nearest, 0, Equal); test::(0, -10, Exact, 0, Equal); test::(123, 0, Down, 123, Equal); test::(123, 0, Up, 123, Equal); test::(123, 0, Floor, 123, Equal); test::(123, 0, Ceiling, 123, Equal); test::(123, 0, Nearest, 123, Equal); test::(123, 0, Exact, 123, Equal); test::(245, -1, Down, 122, Less); test::(245, -1, Up, 123, Greater); test::(245, -1, Floor, 122, Less); test::(245, -1, Ceiling, 123, Greater); test::(245, -1, Nearest, 122, Less); test::(246, -1, Down, 123, Equal); test::(246, -1, Up, 123, Equal); test::(246, -1, Floor, 123, Equal); test::(246, -1, Ceiling, 123, Equal); test::(246, -1, Nearest, 123, Equal); test::(246, -1, Exact, 123, Equal); test::(247, -1, Down, 123, Less); test::(247, -1, Up, 124, Greater); test::(247, -1, Floor, 123, Less); test::(247, -1, Ceiling, 124, Greater); test::(247, -1, Nearest, 124, Greater); test::(491, -2, Down, 122, Less); test::(491, -2, Up, 123, Greater); test::(491, -2, Floor, 122, Less); test::(491, -2, Ceiling, 123, Greater); test::(491, -2, Nearest, 123, Greater); test::(492, -2, Down, 123, Equal); test::(492, -2, Up, 123, Equal); test::(492, -2, Floor, 123, Equal); test::(492, -2, Ceiling, 123, Equal); test::(492, -2, Nearest, 123, Equal); test::(492, -2, Exact, 123, Equal); test::(493, -2, Down, 123, Less); test::(493, -2, Up, 124, Greater); test::(493, -2, Floor, 123, Less); test::(493, -2, Ceiling, 124, Greater); test::(493, -2, Nearest, 123, Less); test::(4127195135, -25, Down, 122, Less); test::(4127195135, -25, Up, 123, Greater); test::(4127195135, -25, Floor, 122, Less); test::(4127195135, -25, Ceiling, 123, Greater); test::(4127195135, -25, Nearest, 123, Greater); test::(4127195136, -25, Down, 123, Equal); test::(4127195136, -25, Up, 123, Equal); test::(4127195136, -25, Floor, 123, Equal); test::(4127195136, -25, Ceiling, 123, Equal); test::(4127195136, -25, Nearest, 123, Equal); test::(4127195136, -25, Exact, 123, Equal); test::(4127195137, -25, Down, 123, Less); test::(4127195137, -25, Up, 124, Greater); test::(4127195137, -25, Floor, 123, Less); test::(4127195137, -25, Ceiling, 124, Greater); test::(4127195137, -25, Nearest, 123, Less); test::(8254390271, -26, Down, 122, Less); test::(8254390271, -26, Up, 123, Greater); test::(8254390271, -26, Floor, 122, Less); test::(8254390271, -26, Ceiling, 123, Greater); test::(8254390271, -26, Nearest, 123, Greater); test::(8254390272, -26, Down, 123, Equal); test::(8254390272, -26, Up, 123, Equal); test::(8254390272, -26, Floor, 123, Equal); test::(8254390272, -26, Ceiling, 123, Equal); test::(8254390272, -26, Nearest, 123, Equal); test::(8254390272, -26, Exact, 123, Equal); test::(8254390273, -26, Down, 123, Less); test::(8254390273, -26, Up, 124, Greater); test::(8254390273, -26, Floor, 123, Less); test::(8254390273, -26, Ceiling, 124, Greater); test::(8254390273, -26, Nearest, 123, Less); test::(0xffffffff, -1, Down, 0x7fffffff, Less); test::(0xffffffff, -1, Up, 0x80000000, Greater); test::(0xffffffff, -1, Floor, 0x7fffffff, Less); test::(0xffffffff, -1, Ceiling, 0x80000000, Greater); test::(0xffffffff, -1, Nearest, 0x80000000, Greater); test::(0x100000000, -1, Down, 0x80000000, Equal); test::(0x100000000, -1, Up, 0x80000000, Equal); test::(0x100000000, -1, Floor, 0x80000000, Equal); test::(0x100000000, -1, Ceiling, 0x80000000, Equal); test::(0x100000000, -1, Nearest, 0x80000000, Equal); test::(0x100000000, -1, Exact, 0x80000000, Equal); test::(0x100000001, -1, Down, 0x80000000, Less); test::(0x100000001, -1, Up, 0x80000001, Greater); test::(0x100000001, -1, Floor, 0x80000000, Less); test::(0x100000001, -1, Ceiling, 0x80000001, Greater); test::(0x100000001, -1, Nearest, 0x80000000, Less); test::(1000000000000, 0, Down, 1000000000000, Equal); test::(1000000000000, 0, Up, 1000000000000, Equal); test::(1000000000000, 0, Floor, 1000000000000, Equal); test::(1000000000000, 0, Ceiling, 1000000000000, Equal); test::(1000000000000, 0, Nearest, 1000000000000, Equal); test::(1000000000000, 0, Exact, 1000000000000, Equal); test::(7999999999999, -3, Down, 999999999999, Less); test::(7999999999999, -3, Up, 1000000000000, Greater); test::(7999999999999, -3, Floor, 999999999999, Less); test::(7999999999999, -3, Ceiling, 1000000000000, Greater); test::(7999999999999, -3, Nearest, 1000000000000, Greater); test::(8000000000000, -3, Down, 1000000000000, Equal); test::(8000000000000, -3, Up, 1000000000000, Equal); test::(8000000000000, -3, Floor, 1000000000000, Equal); test::(8000000000000, -3, Ceiling, 1000000000000, Equal); test::(8000000000000, -3, Nearest, 1000000000000, Equal); test::(8000000000000, -3, Exact, 1000000000000, Equal); test::(8000000000001, -3, Down, 1000000000000, Less); test::(8000000000001, -3, Up, 1000000000001, Greater); test::(8000000000001, -3, Floor, 1000000000000, Less); test::(8000000000001, -3, Ceiling, 1000000000001, Greater); test::(8000000000001, -3, Nearest, 1000000000000, Less); test::(1000000000000, -10, Down, 976562500, Equal); test::(1000000000000, -10, Up, 976562500, Equal); test::(1000000000000, -10, Floor, 976562500, Equal); test::(1000000000000, -10, Ceiling, 976562500, Equal); test::(1000000000000, -10, Nearest, 976562500, Equal); test::(1000000000000, -10, Exact, 976562500, Equal); test::(980657949, -72, Down, 0, Less); test::(980657949, -72, Up, 1, Greater); test::(980657949, -72, Floor, 0, Less); test::(980657949, -72, Ceiling, 1, Greater); test::(980657949, -72, Nearest, 0, Less); test::(0xffffffff, -31, Down, 1, Less); test::(0xffffffff, -31, Up, 2, Greater); test::(0xffffffff, -31, Floor, 1, Less); test::(0xffffffff, -31, Ceiling, 2, Greater); test::(0xffffffff, -31, Nearest, 2, Greater); test::(0xffffffff, -32, Down, 0, Less); test::(0xffffffff, -32, Up, 1, Greater); test::(0xffffffff, -32, Floor, 0, Less); test::(0xffffffff, -32, Ceiling, 1, Greater); test::(0xffffffff, -32, Nearest, 1, Greater); test::(0x100000000, -32, Down, 1, Equal); test::(0x100000000, -32, Up, 1, Equal); test::(0x100000000, -32, Floor, 1, Equal); test::(0x100000000, -32, Ceiling, 1, Equal); test::(0x100000000, -32, Nearest, 1, Equal); test::(0x100000000, -32, Exact, 1, Equal); test::(0x100000000, -33, Down, 0, Less); test::(0x100000000, -33, Up, 1, Greater); test::(0x100000000, -33, Floor, 0, Less); test::(0x100000000, -33, Ceiling, 1, Greater); test::(0x100000000, -33, Nearest, 0, Less); test::(0, 10, Exact, 0, Equal); test::(123, 1, Exact, 246, Equal); test::(123, 2, Exact, 492, Equal); test::(123, 25, Exact, 4127195136, Equal); test::(123, 26, Exact, 8254390272, Equal); test::(123, 100, Exact, 0, Equal); test::(0x80000000, 1, Exact, 0x100000000, Equal); test::(1000000000000, 3, Exact, 8000000000000, Equal); test::(1000000000000, 24, Exact, 16777216000000000000, Equal); test::(1000000000000, 25, Exact, 33554432000000000000, Equal); test::(1000000000000, 31, Exact, 2147483648000000000000, Equal); test::(1000000000000, 32, Exact, 4294967296000000000000, Equal); test::(1000000000000, 33, Exact, 8589934592000000000000, Equal); test::(1000000000000, 100, Exact, 0, Equal); test::(-123, 0, Down, -123, Equal); test::(-123, 0, Up, -123, Equal); test::(-123, 0, Floor, -123, Equal); test::(-123, 0, Ceiling, -123, Equal); test::(-123, 0, Nearest, -123, Equal); test::(-123, 0, Exact, -123, Equal); test::(-245, -1, Down, -122, Greater); test::(-245, -1, Up, -123, Less); test::(-245, -1, Floor, -123, Less); test::(-245, -1, Ceiling, -122, Greater); test::(-245, -1, Nearest, -122, Greater); test::(-246, -1, Down, -123, Equal); test::(-246, -1, Up, -123, Equal); test::(-246, -1, Floor, -123, Equal); test::(-246, -1, Ceiling, -123, Equal); test::(-246, -1, Nearest, -123, Equal); test::(-246, -1, Exact, -123, Equal); test::(-247, -1, Down, -123, Greater); test::(-247, -1, Up, -124, Less); test::(-247, -1, Floor, -124, Less); test::(-247, -1, Ceiling, -123, Greater); test::(-247, -1, Nearest, -124, Less); test::(-491, -2, Down, -122, Greater); test::(-491, -2, Up, -123, Less); test::(-491, -2, Floor, -123, Less); test::(-491, -2, Ceiling, -122, Greater); test::(-491, -2, Nearest, -123, Less); test::(-492, -2, Down, -123, Equal); test::(-492, -2, Up, -123, Equal); test::(-492, -2, Floor, -123, Equal); test::(-492, -2, Ceiling, -123, Equal); test::(-492, -2, Nearest, -123, Equal); test::(-492, -2, Exact, -123, Equal); test::(-493, -2, Down, -123, Greater); test::(-493, -2, Up, -124, Less); test::(-493, -2, Floor, -124, Less); test::(-493, -2, Ceiling, -123, Greater); test::(-493, -2, Nearest, -123, Greater); test::(-4127195135, -25, Down, -122, Greater); test::(-4127195135, -25, Up, -123, Less); test::(-4127195135, -25, Floor, -123, Less); test::(-4127195135, -25, Ceiling, -122, Greater); test::(-4127195135, -25, Nearest, -123, Less); test::(-4127195136, -25, Down, -123, Equal); test::(-4127195136, -25, Up, -123, Equal); test::(-4127195136, -25, Floor, -123, Equal); test::(-4127195136, -25, Ceiling, -123, Equal); test::(-4127195136, -25, Nearest, -123, Equal); test::(-4127195136, -25, Exact, -123, Equal); test::(-4127195137, -25, Down, -123, Greater); test::(-4127195137, -25, Up, -124, Less); test::(-4127195137, -25, Floor, -124, Less); test::(-4127195137, -25, Ceiling, -123, Greater); test::(-4127195137, -25, Nearest, -123, Greater); test::(-8254390271, -26, Down, -122, Greater); test::(-8254390271, -26, Up, -123, Less); test::(-8254390271, -26, Floor, -123, Less); test::(-8254390271, -26, Ceiling, -122, Greater); test::(-8254390271, -26, Nearest, -123, Less); test::(-8254390272, -26, Down, -123, Equal); test::(-8254390272, -26, Up, -123, Equal); test::(-8254390272, -26, Floor, -123, Equal); test::(-8254390272, -26, Ceiling, -123, Equal); test::(-8254390272, -26, Nearest, -123, Equal); test::(-8254390272, -26, Exact, -123, Equal); test::(-8254390273, -26, Down, -123, Greater); test::(-8254390273, -26, Up, -124, Less); test::(-8254390273, -26, Floor, -124, Less); test::(-8254390273, -26, Ceiling, -123, Greater); test::(-8254390273, -26, Nearest, -123, Greater); test::(-0xffffffff, -1, Down, -0x7fffffff, Greater); test::(-0xffffffff, -1, Up, -0x80000000, Less); test::(-0xffffffff, -1, Floor, -0x80000000, Less); test::(-0xffffffff, -1, Ceiling, -0x7fffffff, Greater); test::(-0xffffffff, -1, Nearest, -0x80000000, Less); test::(-0x100000000, -1, Down, -0x80000000, Equal); test::(-0x100000000, -1, Up, -0x80000000, Equal); test::(-0x100000000, -1, Floor, -0x80000000, Equal); test::(-0x100000000, -1, Ceiling, -0x80000000, Equal); test::(-0x100000000, -1, Nearest, -0x80000000, Equal); test::(-0x100000000, -1, Exact, -0x80000000, Equal); test::(-0x100000001, -1, Down, -0x80000000, Greater); test::(-0x100000001, -1, Up, -0x80000001, Less); test::(-0x100000001, -1, Floor, -0x80000001, Less); test::(-0x100000001, -1, Ceiling, -0x80000000, Greater); test::(-0x100000001, -1, Nearest, -0x80000000, Greater); test::(-1000000000000, 0, Down, -1000000000000, Equal); test::(-1000000000000, 0, Up, -1000000000000, Equal); test::(-1000000000000, 0, Floor, -1000000000000, Equal); test::(-1000000000000, 0, Ceiling, -1000000000000, Equal); test::(-1000000000000, 0, Nearest, -1000000000000, Equal); test::(-1000000000000, 0, Exact, -1000000000000, Equal); test::(-7999999999999, -3, Down, -999999999999, Greater); test::(-7999999999999, -3, Up, -1000000000000, Less); test::(-7999999999999, -3, Floor, -1000000000000, Less); test::(-7999999999999, -3, Ceiling, -999999999999, Greater); test::(-7999999999999, -3, Nearest, -1000000000000, Less); test::(-8000000000000, -3, Down, -1000000000000, Equal); test::(-8000000000000, -3, Up, -1000000000000, Equal); test::(-8000000000000, -3, Floor, -1000000000000, Equal); test::(-8000000000000, -3, Ceiling, -1000000000000, Equal); test::(-8000000000000, -3, Nearest, -1000000000000, Equal); test::(-8000000000000, -3, Exact, -1000000000000, Equal); test::(-8000000000001, -3, Down, -1000000000000, Greater); test::(-8000000000001, -3, Up, -1000000000001, Less); test::(-8000000000001, -3, Floor, -1000000000001, Less); test::(-8000000000001, -3, Ceiling, -1000000000000, Greater); test::(-8000000000001, -3, Nearest, -1000000000000, Greater); test::(-16777216000000000000, -24, Down, -1000000000000, Equal); test::(-16777216000000000000, -24, Up, -1000000000000, Equal); test::(-16777216000000000000, -24, Floor, -1000000000000, Equal); test::(-16777216000000000000, -24, Ceiling, -1000000000000, Equal); test::(-16777216000000000000, -24, Nearest, -1000000000000, Equal); test::(-16777216000000000000, -24, Exact, -1000000000000, Equal); test::(-33554432000000000000, -25, Down, -1000000000000, Equal); test::(-33554432000000000000, -25, Up, -1000000000000, Equal); test::(-33554432000000000000, -25, Floor, -1000000000000, Equal); test::(-33554432000000000000, -25, Ceiling, -1000000000000, Equal); test::(-33554432000000000000, -25, Nearest, -1000000000000, Equal); test::(-33554432000000000000, -25, Exact, -1000000000000, Equal); test::(-2147483648000000000000, -31, Down, -1000000000000, Equal); test::(-2147483648000000000000, -31, Up, -1000000000000, Equal); test::(-2147483648000000000000, -31, Floor, -1000000000000, Equal); test::(-2147483648000000000000, -31, Ceiling, -1000000000000, Equal); test::(-2147483648000000000000, -31, Nearest, -1000000000000, Equal); test::(-2147483648000000000000, -31, Exact, -1000000000000, Equal); test::(-4294967296000000000000, -32, Down, -1000000000000, Equal); test::(-4294967296000000000000, -32, Up, -1000000000000, Equal); test::(-4294967296000000000000, -32, Floor, -1000000000000, Equal); test::(-4294967296000000000000, -32, Ceiling, -1000000000000, Equal); test::(-4294967296000000000000, -32, Nearest, -1000000000000, Equal); test::(-4294967296000000000000, -32, Exact, -1000000000000, Equal); test::(-8589934592000000000000, -33, Down, -1000000000000, Equal); test::(-8589934592000000000000, -33, Up, -1000000000000, Equal); test::(-8589934592000000000000, -33, Floor, -1000000000000, Equal); test::(-8589934592000000000000, -33, Ceiling, -1000000000000, Equal); test::(-8589934592000000000000, -33, Nearest, -1000000000000, Equal); test::(-8589934592000000000000, -33, Exact, -1000000000000, Equal); test::(-1000000000000, -10, Down, -976562500, Equal); test::(-1000000000000, -10, Up, -976562500, Equal); test::(-1000000000000, -10, Floor, -976562500, Equal); test::(-1000000000000, -10, Ceiling, -976562500, Equal); test::(-1000000000000, -10, Nearest, -976562500, Equal); test::(-1000000000000, -10, Exact, -976562500, Equal); test::(-980657949, -72, Down, 0, Greater); test::(-980657949, -72, Up, -1, Less); test::(-980657949, -72, Floor, -1, Less); test::(-980657949, -72, Ceiling, 0, Greater); test::(-980657949, -72, Nearest, 0, Greater); test::(-0xffffffff, -31, Down, -1, Greater); test::(-0xffffffff, -31, Up, -2, Less); test::(-0xffffffff, -31, Floor, -2, Less); test::(-0xffffffff, -31, Ceiling, -1, Greater); test::(-0xffffffff, -31, Nearest, -2, Less); test::(-0xffffffff, -32, Down, 0, Greater); test::(-0xffffffff, -32, Up, -1, Less); test::(-0xffffffff, -32, Floor, -1, Less); test::(-0xffffffff, -32, Ceiling, 0, Greater); test::(-0xffffffff, -32, Nearest, -1, Less); test::(-0x100000000, -32, Down, -1, Equal); test::(-0x100000000, -32, Up, -1, Equal); test::(-0x100000000, -32, Floor, -1, Equal); test::(-0x100000000, -32, Ceiling, -1, Equal); test::(-0x100000000, -32, Nearest, -1, Equal); test::(-0x100000000, -32, Exact, -1, Equal); test::(-0x100000000, -33, Down, 0, Greater); test::(-0x100000000, -33, Up, -1, Less); test::(-0x100000000, -33, Floor, -1, Less); test::(-0x100000000, -33, Ceiling, 0, Greater); test::(-0x100000000, -33, Nearest, 0, Greater); test::(-123, 1, Exact, -246, Equal); test::(-123, 2, Exact, -492, Equal); test::(-123, 25, Exact, -4127195136, Equal); test::(-123, 26, Exact, -8254390272, Equal); test::(-0x80000000, 1, Exact, -0x100000000, Equal); test::(-1000000000000, 3, Exact, -8000000000000, Equal); test::(-1000000000000, 24, Exact, -16777216000000000000, Equal); test::(-1000000000000, 25, Exact, -33554432000000000000, Equal); test::(-1000000000000, 31, Exact, -2147483648000000000000, Equal); test::(-1000000000000, 32, Exact, -4294967296000000000000, Equal); test::(-1000000000000, 33, Exact, -8589934592000000000000, Equal); } fn shl_round_fail_helper< T: PrimitiveInt + ShlRound + ShlRoundAssign, U: PrimitiveSigned, >() { assert_panic!(T::exact_from(123).shl_round(U::NEGATIVE_ONE, Exact)); assert_panic!(T::exact_from(123).shl_round(U::exact_from(-100), Exact)); assert_panic!(T::exact_from(123).shl_round_assign(U::NEGATIVE_ONE, Exact)); assert_panic!(T::exact_from(123).shl_round_assign(U::exact_from(-100), Exact)); } #[test] fn shl_round_fail() { apply_fn_to_primitive_ints_and_signeds!(shl_round_fail_helper); } fn shl_round_properties_helper_unsigned_signed< T: ArithmeticCheckedShr + PrimitiveUnsigned + ShlRound + ShlRoundAssign + ShrRound, U: PrimitiveSigned, >() where u64: TryFrom<::Output>, { unsigned_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { let mut mut_n = n; let o = mut_n.shl_round_assign(i, rm); let shifted = mut_n; assert_eq!(n.shl_round(i, rm), (shifted, o)); if i < U::ZERO { assert!(shifted <= n); } if i != U::MIN { assert_eq!(n.shr_round(-i, rm), (shifted, o)); } assert_eq!( i >= U::ZERO || n.divisible_by_power_of_2(u64::exact_from(i.unsigned_abs())), o == Equal ); if i < U::ZERO && let Some(m) = shifted.arithmetic_checked_shr(i) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shl_round(i, rm), (shifted, Equal)); } } else { assert_panic!(n.shl_round(i, Exact)); } }); unsigned_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shl_round(U::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(T::ZERO.shl_round(i, rm), (T::ZERO, Equal)); }); } fn shl_round_properties_helper_signed_signed< T: ArithmeticCheckedShr + PrimitiveSigned + ShlRound + ShlRoundAssign + ShrRound, U: PrimitiveSigned, >() where u64: TryFrom<::Output>, { signed_signed_rounding_mode_triple_gen_var_4::().test_properties(|(n, i, rm)| { let mut mut_n = n; let o = mut_n.shl_round_assign(i, rm); let shifted = mut_n; assert_eq!(n.shl_round(i, rm), (shifted, o)); if i < U::ZERO { assert!(shifted.le_abs(&n)); } if i != U::MIN { assert_eq!(n.shr_round(-i, rm), (shifted, o)); } assert_eq!( i >= U::ZERO || n.divisible_by_power_of_2(u64::exact_from(i.unsigned_abs())), o == Equal ); if i < U::ZERO && let Some(m) = shifted.arithmetic_checked_shr(i) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shl_round(i, rm), (shifted, Equal)); } } else { assert_panic!(n.shl_round(i, Exact)); } }); signed_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shl_round(U::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(T::ZERO.shl_round(i, rm), (T::ZERO, Equal)); }); } #[test] fn shl_round_properties() { apply_fn_to_unsigneds_and_signeds!(shl_round_properties_helper_unsigned_signed); apply_fn_to_signeds_and_signeds!(shl_round_properties_helper_signed_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, ShlRound, ShrRound, ShrRoundAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_signed_rounding_mode_triple_gen_var_3, signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_8, signed_unsigned_pair_gen_var_16, signed_unsigned_pair_gen_var_17, signed_unsigned_rounding_mode_triple_gen_var_2, unsigned_pair_gen_var_2, unsigned_pair_gen_var_14, unsigned_pair_gen_var_21, unsigned_rounding_mode_pair_gen, unsigned_signed_rounding_mode_triple_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_4, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_shr_round() { fn test + ShrRoundAssign, U: PrimitiveInt>( t: T, u: U, rm: RoundingMode, out: T, o: Ordering, ) { assert_eq!(t.shr_round(u, rm), (out, o)); let mut t = t; assert_eq!(t.shr_round_assign(u, rm), o); assert_eq!(t, out); } test::(0, 0, Down, 0, Equal); test::(0, 0, Up, 0, Equal); test::(0, 0, Floor, 0, Equal); test::(0, 0, Ceiling, 0, Equal); test::(0, 0, Nearest, 0, Equal); test::(0, 0, Exact, 0, Equal); test::(0, 10, Down, 0, Equal); test::(0, 10, Up, 0, Equal); test::(0, 10, Floor, 0, Equal); test::(0, 10, Ceiling, 0, Equal); test::(0, 10, Nearest, 0, Equal); test::(0, 10, Exact, 0, Equal); test::(123, 0, Down, 123, Equal); test::(123, 0, Up, 123, Equal); test::(123, 0, Floor, 123, Equal); test::(123, 0, Ceiling, 123, Equal); test::(123, 0, Nearest, 123, Equal); test::(123, 0, Exact, 123, Equal); test::(245, 1, Down, 122, Less); test::(245, 1, Up, 123, Greater); test::(245, 1, Floor, 122, Less); test::(245, 1, Ceiling, 123, Greater); test::(245, 1, Nearest, 122, Less); test::(246, 1, Down, 123, Equal); test::(246, 1, Up, 123, Equal); test::(246, 1, Floor, 123, Equal); test::(246, 1, Ceiling, 123, Equal); test::(246, 1, Nearest, 123, Equal); test::(246, 1, Exact, 123, Equal); test::(247, 1, Down, 123, Less); test::(247, 1, Up, 124, Greater); test::(247, 1, Floor, 123, Less); test::(247, 1, Ceiling, 124, Greater); test::(247, 1, Nearest, 124, Greater); test::(491, 2, Down, 122, Less); test::(491, 2, Up, 123, Greater); test::(491, 2, Floor, 122, Less); test::(491, 2, Ceiling, 123, Greater); test::(491, 2, Nearest, 123, Greater); test::(492, 2, Down, 123, Equal); test::(492, 2, Up, 123, Equal); test::(492, 2, Floor, 123, Equal); test::(492, 2, Ceiling, 123, Equal); test::(492, 2, Nearest, 123, Equal); test::(492, 2, Exact, 123, Equal); test::(493, 2, Down, 123, Less); test::(493, 2, Up, 124, Greater); test::(493, 2, Floor, 123, Less); test::(493, 2, Ceiling, 124, Greater); test::(493, 2, Nearest, 123, Less); test::(4127195135, 25, Down, 122, Less); test::(4127195135, 25, Up, 123, Greater); test::(4127195135, 25, Floor, 122, Less); test::(4127195135, 25, Ceiling, 123, Greater); test::(4127195135, 25, Nearest, 123, Greater); test::(4127195136, 25, Down, 123, Equal); test::(4127195136, 25, Up, 123, Equal); test::(4127195136, 25, Floor, 123, Equal); test::(4127195136, 25, Ceiling, 123, Equal); test::(4127195136, 25, Nearest, 123, Equal); test::(4127195136, 25, Exact, 123, Equal); test::(4127195137, 25, Down, 123, Less); test::(4127195137, 25, Up, 124, Greater); test::(4127195137, 25, Floor, 123, Less); test::(4127195137, 25, Ceiling, 124, Greater); test::(4127195137, 25, Nearest, 123, Less); test::(8254390271, 26, Down, 122, Less); test::(8254390271, 26, Up, 123, Greater); test::(8254390271, 26, Floor, 122, Less); test::(8254390271, 26, Ceiling, 123, Greater); test::(8254390271, 26, Nearest, 123, Greater); test::(8254390272, 26, Down, 123, Equal); test::(8254390272, 26, Up, 123, Equal); test::(8254390272, 26, Floor, 123, Equal); test::(8254390272, 26, Ceiling, 123, Equal); test::(8254390272, 26, Nearest, 123, Equal); test::(8254390272, 26, Exact, 123, Equal); test::(8254390273, 26, Down, 123, Less); test::(8254390273, 26, Up, 124, Greater); test::(8254390273, 26, Floor, 123, Less); test::(8254390273, 26, Ceiling, 124, Greater); test::(8254390273, 26, Nearest, 123, Less); test::(0xffffffff, 1, Down, 0x7fffffff, Less); test::(0xffffffff, 1, Up, 0x80000000, Greater); test::(0xffffffff, 1, Floor, 0x7fffffff, Less); test::(0xffffffff, 1, Ceiling, 0x80000000, Greater); test::(0xffffffff, 1, Nearest, 0x80000000, Greater); test::(0x100000000, 1, Down, 0x80000000, Equal); test::(0x100000000, 1, Up, 0x80000000, Equal); test::(0x100000000, 1, Floor, 0x80000000, Equal); test::(0x100000000, 1, Ceiling, 0x80000000, Equal); test::(0x100000000, 1, Nearest, 0x80000000, Equal); test::(0x100000000, 1, Exact, 0x80000000, Equal); test::(0x100000001, 1, Down, 0x80000000, Less); test::(0x100000001, 1, Up, 0x80000001, Greater); test::(0x100000001, 1, Floor, 0x80000000, Less); test::(0x100000001, 1, Ceiling, 0x80000001, Greater); test::(0x100000001, 1, Nearest, 0x80000000, Less); test::(1000000000000, 0, Down, 1000000000000, Equal); test::(1000000000000, 0, Up, 1000000000000, Equal); test::(1000000000000, 0, Floor, 1000000000000, Equal); test::(1000000000000, 0, Ceiling, 1000000000000, Equal); test::(1000000000000, 0, Nearest, 1000000000000, Equal); test::(1000000000000, 0, Exact, 1000000000000, Equal); test::(7999999999999, 3, Down, 999999999999, Less); test::(7999999999999, 3, Up, 1000000000000, Greater); test::(7999999999999, 3, Floor, 999999999999, Less); test::(7999999999999, 3, Ceiling, 1000000000000, Greater); test::(7999999999999, 3, Nearest, 1000000000000, Greater); test::(8000000000000, 3, Down, 1000000000000, Equal); test::(8000000000000, 3, Up, 1000000000000, Equal); test::(8000000000000, 3, Floor, 1000000000000, Equal); test::(8000000000000, 3, Ceiling, 1000000000000, Equal); test::(8000000000000, 3, Nearest, 1000000000000, Equal); test::(8000000000000, 3, Exact, 1000000000000, Equal); test::(8000000000001, 3, Down, 1000000000000, Less); test::(8000000000001, 3, Up, 1000000000001, Greater); test::(8000000000001, 3, Floor, 1000000000000, Less); test::(8000000000001, 3, Ceiling, 1000000000001, Greater); test::(8000000000001, 3, Nearest, 1000000000000, Less); test::(1000000000000, 10, Down, 976562500, Equal); test::(1000000000000, 10, Up, 976562500, Equal); test::(1000000000000, 10, Floor, 976562500, Equal); test::(1000000000000, 10, Ceiling, 976562500, Equal); test::(1000000000000, 10, Nearest, 976562500, Equal); test::(1000000000000, 10, Exact, 976562500, Equal); test::(980657949, 72, Down, 0, Less); test::(980657949, 72, Up, 1, Greater); test::(980657949, 72, Floor, 0, Less); test::(980657949, 72, Ceiling, 1, Greater); test::(980657949, 72, Nearest, 0, Less); test::(0xffffffff, 31, Down, 1, Less); test::(0xffffffff, 31, Up, 2, Greater); test::(0xffffffff, 31, Floor, 1, Less); test::(0xffffffff, 31, Ceiling, 2, Greater); test::(0xffffffff, 31, Nearest, 2, Greater); test::(0xffffffff, 32, Down, 0, Less); test::(0xffffffff, 32, Up, 1, Greater); test::(0xffffffff, 32, Floor, 0, Less); test::(0xffffffff, 32, Ceiling, 1, Greater); test::(0xffffffff, 32, Nearest, 1, Greater); test::(0x100000000, 32, Down, 1, Equal); test::(0x100000000, 32, Up, 1, Equal); test::(0x100000000, 32, Floor, 1, Equal); test::(0x100000000, 32, Ceiling, 1, Equal); test::(0x100000000, 32, Nearest, 1, Equal); test::(0x100000000, 32, Exact, 1, Equal); test::(0x100000000, 33, Down, 0, Less); test::(0x100000000, 33, Up, 1, Greater); test::(0x100000000, 33, Floor, 0, Less); test::(0x100000000, 33, Ceiling, 1, Greater); test::(0x100000000, 33, Nearest, 0, Less); test::(0, -10, Exact, 0, Equal); test::(123, -1, Exact, 246, Equal); test::(123, -2, Exact, 492, Equal); test::(123, -25, Exact, 4127195136, Equal); test::(123, -26, Exact, 8254390272, Equal); test::(123, -100, Exact, 0, Equal); test::(0x80000000, -1, Exact, 0x100000000, Equal); test::(1000000000000, -3, Exact, 8000000000000, Equal); test::(1000000000000, -24, Exact, 16777216000000000000, Equal); test::(1000000000000, -25, Exact, 33554432000000000000, Equal); test::(1000000000000, -31, Exact, 2147483648000000000000, Equal); test::(1000000000000, -32, Exact, 4294967296000000000000, Equal); test::(1000000000000, -33, Exact, 8589934592000000000000, Equal); test::(1000000000000, -100, Exact, 0, Equal); test::(-123, 0, Down, -123, Equal); test::(-123, 0, Up, -123, Equal); test::(-123, 0, Floor, -123, Equal); test::(-123, 0, Ceiling, -123, Equal); test::(-123, 0, Nearest, -123, Equal); test::(-123, 0, Exact, -123, Equal); test::(-245, 1, Down, -122, Greater); test::(-245, 1, Up, -123, Less); test::(-245, 1, Floor, -123, Less); test::(-245, 1, Ceiling, -122, Greater); test::(-245, 1, Nearest, -122, Greater); test::(-246, 1, Down, -123, Equal); test::(-246, 1, Up, -123, Equal); test::(-246, 1, Floor, -123, Equal); test::(-246, 1, Ceiling, -123, Equal); test::(-246, 1, Nearest, -123, Equal); test::(-246, 1, Exact, -123, Equal); test::(-247, 1, Down, -123, Greater); test::(-247, 1, Up, -124, Less); test::(-247, 1, Floor, -124, Less); test::(-247, 1, Ceiling, -123, Greater); test::(-247, 1, Nearest, -124, Less); test::(-491, 2, Down, -122, Greater); test::(-491, 2, Up, -123, Less); test::(-491, 2, Floor, -123, Less); test::(-491, 2, Ceiling, -122, Greater); test::(-491, 2, Nearest, -123, Less); test::(-492, 2, Down, -123, Equal); test::(-492, 2, Up, -123, Equal); test::(-492, 2, Floor, -123, Equal); test::(-492, 2, Ceiling, -123, Equal); test::(-492, 2, Nearest, -123, Equal); test::(-492, 2, Exact, -123, Equal); test::(-493, 2, Down, -123, Greater); test::(-493, 2, Up, -124, Less); test::(-493, 2, Floor, -124, Less); test::(-493, 2, Ceiling, -123, Greater); test::(-493, 2, Nearest, -123, Greater); test::(-4127195135, 25, Down, -122, Greater); test::(-4127195135, 25, Up, -123, Less); test::(-4127195135, 25, Floor, -123, Less); test::(-4127195135, 25, Ceiling, -122, Greater); test::(-4127195135, 25, Nearest, -123, Less); test::(-4127195136, 25, Down, -123, Equal); test::(-4127195136, 25, Up, -123, Equal); test::(-4127195136, 25, Floor, -123, Equal); test::(-4127195136, 25, Ceiling, -123, Equal); test::(-4127195136, 25, Nearest, -123, Equal); test::(-4127195136, 25, Exact, -123, Equal); test::(-4127195137, 25, Down, -123, Greater); test::(-4127195137, 25, Up, -124, Less); test::(-4127195137, 25, Floor, -124, Less); test::(-4127195137, 25, Ceiling, -123, Greater); test::(-4127195137, 25, Nearest, -123, Greater); test::(-8254390271, 26, Down, -122, Greater); test::(-8254390271, 26, Up, -123, Less); test::(-8254390271, 26, Floor, -123, Less); test::(-8254390271, 26, Ceiling, -122, Greater); test::(-8254390271, 26, Nearest, -123, Less); test::(-8254390272, 26, Down, -123, Equal); test::(-8254390272, 26, Up, -123, Equal); test::(-8254390272, 26, Floor, -123, Equal); test::(-8254390272, 26, Ceiling, -123, Equal); test::(-8254390272, 26, Nearest, -123, Equal); test::(-8254390272, 26, Exact, -123, Equal); test::(-8254390273, 26, Down, -123, Greater); test::(-8254390273, 26, Up, -124, Less); test::(-8254390273, 26, Floor, -124, Less); test::(-8254390273, 26, Ceiling, -123, Greater); test::(-8254390273, 26, Nearest, -123, Greater); test::(-0xffffffff, 1, Down, -0x7fffffff, Greater); test::(-0xffffffff, 1, Up, -0x80000000, Less); test::(-0xffffffff, 1, Floor, -0x80000000, Less); test::(-0xffffffff, 1, Ceiling, -0x7fffffff, Greater); test::(-0xffffffff, 1, Nearest, -0x80000000, Less); test::(-0x100000000, 1, Down, -0x80000000, Equal); test::(-0x100000000, 1, Up, -0x80000000, Equal); test::(-0x100000000, 1, Floor, -0x80000000, Equal); test::(-0x100000000, 1, Ceiling, -0x80000000, Equal); test::(-0x100000000, 1, Nearest, -0x80000000, Equal); test::(-0x100000000, 1, Exact, -0x80000000, Equal); test::(-0x100000001, 1, Down, -0x80000000, Greater); test::(-0x100000001, 1, Up, -0x80000001, Less); test::(-0x100000001, 1, Floor, -0x80000001, Less); test::(-0x100000001, 1, Ceiling, -0x80000000, Greater); test::(-0x100000001, 1, Nearest, -0x80000000, Greater); test::(-1000000000000, 0, Down, -1000000000000, Equal); test::(-1000000000000, 0, Up, -1000000000000, Equal); test::(-1000000000000, 0, Floor, -1000000000000, Equal); test::(-1000000000000, 0, Ceiling, -1000000000000, Equal); test::(-1000000000000, 0, Nearest, -1000000000000, Equal); test::(-1000000000000, 0, Exact, -1000000000000, Equal); test::(-7999999999999, 3, Down, -999999999999, Greater); test::(-7999999999999, 3, Up, -1000000000000, Less); test::(-7999999999999, 3, Floor, -1000000000000, Less); test::(-7999999999999, 3, Ceiling, -999999999999, Greater); test::(-7999999999999, 3, Nearest, -1000000000000, Less); test::(-8000000000000, 3, Down, -1000000000000, Equal); test::(-8000000000000, 3, Up, -1000000000000, Equal); test::(-8000000000000, 3, Floor, -1000000000000, Equal); test::(-8000000000000, 3, Ceiling, -1000000000000, Equal); test::(-8000000000000, 3, Nearest, -1000000000000, Equal); test::(-8000000000000, 3, Exact, -1000000000000, Equal); test::(-8000000000001, 3, Down, -1000000000000, Greater); test::(-8000000000001, 3, Up, -1000000000001, Less); test::(-8000000000001, 3, Floor, -1000000000001, Less); test::(-8000000000001, 3, Ceiling, -1000000000000, Greater); test::(-8000000000001, 3, Nearest, -1000000000000, Greater); test::(-16777216000000000000, 24, Down, -1000000000000, Equal); test::(-16777216000000000000, 24, Up, -1000000000000, Equal); test::(-16777216000000000000, 24, Floor, -1000000000000, Equal); test::(-16777216000000000000, 24, Ceiling, -1000000000000, Equal); test::(-16777216000000000000, 24, Nearest, -1000000000000, Equal); test::(-16777216000000000000, 24, Exact, -1000000000000, Equal); test::(-33554432000000000000, 25, Down, -1000000000000, Equal); test::(-33554432000000000000, 25, Up, -1000000000000, Equal); test::(-33554432000000000000, 25, Floor, -1000000000000, Equal); test::(-33554432000000000000, 25, Ceiling, -1000000000000, Equal); test::(-33554432000000000000, 25, Nearest, -1000000000000, Equal); test::(-33554432000000000000, 25, Exact, -1000000000000, Equal); test::(-2147483648000000000000, 31, Down, -1000000000000, Equal); test::(-2147483648000000000000, 31, Up, -1000000000000, Equal); test::(-2147483648000000000000, 31, Floor, -1000000000000, Equal); test::(-2147483648000000000000, 31, Ceiling, -1000000000000, Equal); test::(-2147483648000000000000, 31, Nearest, -1000000000000, Equal); test::(-2147483648000000000000, 31, Exact, -1000000000000, Equal); test::(-4294967296000000000000, 32, Down, -1000000000000, Equal); test::(-4294967296000000000000, 32, Up, -1000000000000, Equal); test::(-4294967296000000000000, 32, Floor, -1000000000000, Equal); test::(-4294967296000000000000, 32, Ceiling, -1000000000000, Equal); test::(-4294967296000000000000, 32, Nearest, -1000000000000, Equal); test::(-4294967296000000000000, 32, Exact, -1000000000000, Equal); test::(-8589934592000000000000, 33, Down, -1000000000000, Equal); test::(-8589934592000000000000, 33, Up, -1000000000000, Equal); test::(-8589934592000000000000, 33, Floor, -1000000000000, Equal); test::(-8589934592000000000000, 33, Ceiling, -1000000000000, Equal); test::(-8589934592000000000000, 33, Nearest, -1000000000000, Equal); test::(-8589934592000000000000, 33, Exact, -1000000000000, Equal); test::(-1000000000000, 10, Down, -976562500, Equal); test::(-1000000000000, 10, Up, -976562500, Equal); test::(-1000000000000, 10, Floor, -976562500, Equal); test::(-1000000000000, 10, Ceiling, -976562500, Equal); test::(-1000000000000, 10, Nearest, -976562500, Equal); test::(-1000000000000, 10, Exact, -976562500, Equal); test::(-980657949, 72, Down, 0, Greater); test::(-980657949, 72, Up, -1, Less); test::(-980657949, 72, Floor, -1, Less); test::(-980657949, 72, Ceiling, 0, Greater); test::(-980657949, 72, Nearest, 0, Greater); test::(-0xffffffff, 31, Down, -1, Greater); test::(-0xffffffff, 31, Up, -2, Less); test::(-0xffffffff, 31, Floor, -2, Less); test::(-0xffffffff, 31, Ceiling, -1, Greater); test::(-0xffffffff, 31, Nearest, -2, Less); test::(-0xffffffff, 32, Down, 0, Greater); test::(-0xffffffff, 32, Up, -1, Less); test::(-0xffffffff, 32, Floor, -1, Less); test::(-0xffffffff, 32, Ceiling, 0, Greater); test::(-0xffffffff, 32, Nearest, -1, Less); test::(-0x100000000, 32, Down, -1, Equal); test::(-0x100000000, 32, Up, -1, Equal); test::(-0x100000000, 32, Floor, -1, Equal); test::(-0x100000000, 32, Ceiling, -1, Equal); test::(-0x100000000, 32, Nearest, -1, Equal); test::(-0x100000000, 32, Exact, -1, Equal); test::(-0x100000000, 33, Down, 0, Greater); test::(-0x100000000, 33, Up, -1, Less); test::(-0x100000000, 33, Floor, -1, Less); test::(-0x100000000, 33, Ceiling, 0, Greater); test::(-0x100000000, 33, Nearest, 0, Greater); test::(-123, -1, Exact, -246, Equal); test::(-123, -2, Exact, -492, Equal); test::(-123, -25, Exact, -4127195136, Equal); test::(-123, -26, Exact, -8254390272, Equal); test::(-0x80000000, -1, Exact, -0x100000000, Equal); test::(-1000000000000, -3, Exact, -8000000000000, Equal); test::(-1000000000000, -24, Exact, -16777216000000000000, Equal); test::(-1000000000000, -25, Exact, -33554432000000000000, Equal); test::(-1000000000000, -31, Exact, -2147483648000000000000, Equal); test::(-1000000000000, -32, Exact, -4294967296000000000000, Equal); test::(-1000000000000, -33, Exact, -8589934592000000000000, Equal); } fn shr_round_fail_helper< T: PrimitiveInt + ShrRound + ShrRoundAssign, U: PrimitiveInt, >() { assert_panic!(T::exact_from(123).shr_round(U::ONE, Exact)); assert_panic!(T::exact_from(123).shr_round(U::exact_from(100), Exact)); assert_panic!(T::exact_from(123).shr_round_assign(U::ONE, Exact)); assert_panic!(T::exact_from(123).shr_round_assign(U::exact_from(100), Exact)); } #[test] fn shr_round_fail() { apply_fn_to_primitive_ints_and_primitive_ints!(shr_round_fail_helper); } fn shr_round_properties_helper_unsigned_unsigned< T: ArithmeticCheckedShl + PrimitiveUnsigned + ShrRound + ShrRoundAssign, U: PrimitiveUnsigned, >() { unsigned_unsigned_rounding_mode_triple_gen_var_4::().test_properties(|(n, u, rm)| { let mut mut_n = n; let o = mut_n.shr_round_assign(u, rm); let shifted = mut_n; assert_eq!(n.shr_round(u, rm), (shifted, o)); assert!(shifted <= n); assert_eq!(n.divisible_by_power_of_2(u.exact_into()), o == Equal); if let Some(m) = shifted.arithmetic_checked_shl(u) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shr_round(u, rm), (shifted, Equal)); } } else { assert_panic!(n.shr_round(u, Exact)); } }); unsigned_pair_gen_var_2::().test_properties(|(n, u)| { if u < U::exact_from(T::WIDTH) { let no = (n, Equal); if let Some(shifted) = n.arithmetic_checked_shl(u) { assert_eq!(shifted.shr_round(u, Down), no); assert_eq!(shifted.shr_round(u, Up), no); assert_eq!(shifted.shr_round(u, Floor), no); assert_eq!(shifted.shr_round(u, Ceiling), no); assert_eq!(shifted.shr_round(u, Nearest), no); assert_eq!(shifted.shr_round(u, Exact), no); } } }); unsigned_pair_gen_var_14::().test_properties(|(n, u)| { let down = n.shr_round(u, Down); assert_eq!(down.1, Less); if let Some(up) = down.0.checked_add(T::ONE) { let up = (up, Greater); assert_eq!(n.shr_round(u, Up), up); assert_eq!(n.shr_round(u, Floor), down); assert_eq!(n.shr_round(u, Ceiling), up); let nearest = n.shr_round(u, Nearest); assert!(nearest == down || nearest == up); } }); unsigned_pair_gen_var_21::().test_properties(|(t, u)| { if let Some(shift) = u.checked_add(U::exact_from(T::WIDTH)) { assert_eq!(t.shr_round(shift, Down), (T::ZERO, Less)); assert_eq!(t.shr_round(shift, Floor), (T::ZERO, Less)); assert_eq!(t.shr_round(shift, Up), (T::ONE, Greater)); assert_eq!(t.shr_round(shift, Ceiling), (T::ONE, Greater)); if let Some(extra_shift) = shift.checked_add(U::ONE) { assert_eq!(t.shr_round(extra_shift, Nearest), (T::ZERO, Less)); } } }); unsigned_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shr_round(U::ZERO, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { assert_eq!(T::ZERO.shr_round(u, rm), (T::ZERO, Equal)); }); } fn shr_round_properties_helper_unsigned_signed< T: ArithmeticCheckedShl + PrimitiveUnsigned + ShlRound + ShrRound + ShrRoundAssign, U: PrimitiveSigned, >() { unsigned_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { let mut mut_n = n; let o = mut_n.shr_round_assign(i, rm); let shifted = mut_n; assert_eq!(n.shr_round(i, rm), (shifted, o)); if i >= U::ZERO { assert!(shifted <= n); } if i != U::MIN { assert_eq!(n.shl_round(-i, rm), (shifted, o)); } assert_eq!( i <= U::ZERO || n.divisible_by_power_of_2(i.exact_into()), o == Equal ); if i >= U::ZERO && let Some(m) = shifted.arithmetic_checked_shl(i) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shr_round(i, rm), (shifted, Equal)); } } else { assert_panic!(n.shr_round(i, Exact)); } }); unsigned_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shr_round(U::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(T::ZERO.shr_round(i, rm), (T::ZERO, Equal)); }); } fn shr_round_properties_helper_signed_unsigned< V: PrimitiveUnsigned, U: PrimitiveUnsigned + WrappingFrom, S: ArithmeticCheckedShl + PrimitiveSigned + ShrRound + ShrRoundAssign + WrappingFrom, >() { signed_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(n, u, rm)| { let mut mut_n = n; let o = mut_n.shr_round_assign(u, rm); let shifted = mut_n; assert_eq!(n.shr_round(u, rm), (shifted, o)); assert!(shifted.le_abs(&n)); if n != S::MIN { let (x, o_alt) = (-n).shr_round(u, -rm); if x != S::MIN { assert_eq!(-x, shifted); } assert_eq!(o_alt, o.reverse()); } assert_eq!(n.divisible_by_power_of_2(u.exact_into()), o == Equal); if let Some(m) = shifted.arithmetic_checked_shl(u) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shr_round(u, rm), (shifted, Equal)); } } else { assert_panic!(n.shr_round(u, Exact)); } }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { if u < V::exact_from(S::WIDTH) { let no = (n, Equal); if let Some(shifted) = n.arithmetic_checked_shl(u) { assert_eq!(shifted.shr_round(u, Down), no); assert_eq!(shifted.shr_round(u, Up), no); assert_eq!(shifted.shr_round(u, Floor), no); assert_eq!(shifted.shr_round(u, Ceiling), no); assert_eq!(shifted.shr_round(u, Nearest), no); assert_eq!(shifted.shr_round(u, Exact), no); } } }); signed_unsigned_pair_gen_var_8::().test_properties(|(n, u)| { let floor = n.shr_round(u, Floor); assert_eq!(floor.1, Less); if let Some(ceiling) = floor.0.checked_add(S::ONE) { let ceiling = (ceiling, Greater); assert_eq!(n.shr_round(u, Ceiling), ceiling); if n >= S::ZERO { assert_eq!(n.shr_round(u, Up), ceiling); assert_eq!(n.shr_round(u, Down), floor); } else { assert_eq!(n.shr_round(u, Up), floor); assert_eq!(n.shr_round(u, Down), ceiling); } let nearest = n.shr_round(u, Nearest); assert!(nearest == floor || nearest == ceiling); } }); signed_unsigned_pair_gen_var_16::().test_properties(|(i, u)| { if let Some(shift) = u.checked_add(V::exact_from(S::WIDTH - 1)) { assert_eq!(i.shr_round(shift, Down), (S::ZERO, Less)); assert_eq!(i.shr_round(shift, Floor), (S::ZERO, Less)); assert_eq!(i.shr_round(shift, Up), (S::ONE, Greater)); assert_eq!(i.shr_round(shift, Ceiling), (S::ONE, Greater)); if let Some(extra_shift) = shift.checked_add(V::ONE) { assert_eq!(i.shr_round(extra_shift, Nearest), (S::ZERO, Less)); } } }); signed_unsigned_pair_gen_var_17::().test_properties(|(i, u)| { if let Some(shift) = u.checked_add(V::exact_from(S::WIDTH - 1)) { assert_eq!(i.shr_round(shift, Down), (S::ZERO, Greater)); assert_eq!(i.shr_round(shift, Floor), (S::NEGATIVE_ONE, Less)); assert_eq!(i.shr_round(shift, Up), (S::NEGATIVE_ONE, Less)); assert_eq!(i.shr_round(shift, Ceiling), (S::ZERO, Greater)); if let Some(extra_shift) = shift.checked_add(V::ONE) { assert_eq!(i.shr_round(extra_shift, Nearest), (S::ZERO, Greater)); } } }); signed_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shr_round(V::ZERO, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { assert_eq!(S::ZERO.shr_round(u, rm), (S::ZERO, Equal)); }); } fn shr_round_properties_helper_signed_signed< T: ArithmeticCheckedShl + PrimitiveSigned + ShlRound + ShrRound + ShrRoundAssign, U: PrimitiveSigned, >() { signed_signed_rounding_mode_triple_gen_var_3::().test_properties(|(n, i, rm)| { let mut mut_n = n; let o = mut_n.shr_round_assign(i, rm); let shifted = mut_n; assert_eq!(n.shr_round(i, rm), (shifted, o)); if i >= U::ZERO { assert!(shifted.le_abs(&n)); } if i != U::MIN { assert_eq!(n.shl_round(-i, rm), (shifted, o)); } assert_eq!( i <= U::ZERO || n.divisible_by_power_of_2(i.exact_into()), o == Equal ); if i >= U::ZERO && let Some(m) = shifted.arithmetic_checked_shl(i) { assert_eq!(m.cmp(&n), o); } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(n.shr_round(i, rm), (shifted, Equal)); } } else { assert_panic!(n.shr_round(i, Exact)); } }); signed_rounding_mode_pair_gen::().test_properties(|(n, rm)| { assert_eq!(n.shr_round(U::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(T::ZERO.shr_round(i, rm), (T::ZERO, Equal)); }); } #[test] fn shr_round_properties() { apply_fn_to_unsigneds_and_unsigneds!(shr_round_properties_helper_unsigned_unsigned); apply_fn_to_unsigneds_and_signeds!(shr_round_properties_helper_unsigned_signed); apply_fn_to_unsigneds_and_unsigned_signed_pairs!(shr_round_properties_helper_signed_unsigned); apply_fn_to_signeds_and_signeds!(shr_round_properties_helper_signed_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; use std::cmp::Ordering::*; fn sign_helper_primitive_int() { let test = |n: T, out| { assert_eq!(n.sign(), out); }; test(T::ZERO, Equal); test(T::ONE, Greater); test(T::exact_from(100), Greater); test(T::MAX, Greater); } fn sign_helper_signed() { let test = |n: T, out| { assert_eq!(n.sign(), out); }; test(T::NEGATIVE_ONE, Less); test(T::exact_from(-100), Less); test(T::MIN, Less); } fn sign_helper_primitive_float() { let test = |n: T, out| { assert_eq!(n.sign(), out); }; test(T::ZERO, Greater); test(T::NEGATIVE_ZERO, Less); test(T::ONE, Greater); test(T::NEGATIVE_ONE, Less); test(T::INFINITY, Greater); test(T::NEGATIVE_INFINITY, Less); test(T::NAN, Equal); } #[test] fn test_sign() { apply_fn_to_primitive_ints!(sign_helper_primitive_int); apply_fn_to_signeds!(sign_helper_signed); apply_fn_to_primitive_floats!(sign_helper_primitive_float); } fn sign_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let sign = n.sign(); assert_ne!(sign, Less); assert_eq!(n.partial_cmp(&T::ZERO), Some(sign)); }); } fn sign_properties_helper_signed() { signed_gen::().test_properties(|n| { let sign = n.sign(); assert_eq!(n.partial_cmp(&T::ZERO), Some(sign)); if n != T::MIN { assert_eq!((-n).sign(), sign.reverse()); } }); } fn sign_properties_helper_primitive_float() { primitive_float_gen::().test_properties(|f| { let sign = f.sign(); if !f.is_nan() { assert_eq!((-f).sign(), sign.reverse()); } }); } #[test] fn sign_properties() { apply_fn_to_unsigneds!(sign_properties_helper_unsigned); apply_fn_to_signeds!(sign_properties_helper_signed); apply_fn_to_primitive_floats!(sign_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::sqrt::sqrt_rem_newton; use malachite_base::num::arithmetic::sqrt::{ ceiling_sqrt_binary, checked_sqrt_binary, floor_sqrt_binary, sqrt_rem_binary, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_gen, signed_gen_var_2, unsigned_gen, unsigned_gen_var_17, }; use std::panic::catch_unwind; #[test] fn test_sqrt_rem_newton() { fn test, S: PrimitiveSigned + WrappingFrom>( n: U, sqrt: U, rem: U, ) { let (actual_sqrt, actual_rem) = sqrt_rem_newton::(n); assert_eq!(actual_sqrt, sqrt); assert_eq!(actual_rem, rem); assert_eq!(n.sqrt_rem(), (sqrt, rem)); } // - no initial underestimate test::(2000000000, 44721, 32159); test::(u32::MAX, 65535, 131070); // - initial underestimate test::(1073741824, 32768, 0); test::(10000000000000000000, 3162277660, 1064924400); test::(u64::MAX, 4294967295, 8589934590); } #[test] fn sqrt_rem_newton_fail() { assert_panic!(sqrt_rem_newton::(1)); assert_panic!(sqrt_rem_newton::(1)); } #[test] fn test_floor_sqrt() { fn test_u(n: T, out: T) { assert_eq!(n.floor_sqrt(), out); assert_eq!(floor_sqrt_binary(n), out); let mut n = n; n.floor_sqrt_assign(); assert_eq!(n, out); } test_u::(0, 0); test_u::(1, 1); test_u::(2, 1); test_u::(3, 1); test_u::(4, 2); test_u::(5, 2); test_u::(10, 3); test_u::(100, 10); test_u::(1000000000, 31622); test_u::(152415765279683, 12345677); test_u::(152415765279684, 12345678); test_u::(152415765279685, 12345678); fn test_i(n: T, out: T) { assert_eq!(n.floor_sqrt(), out); let mut n = n; n.floor_sqrt_assign(); assert_eq!(n, out); } test_i::(0, 0); test_i::(1, 1); test_i::(2, 1); test_i::(3, 1); test_i::(4, 2); test_i::(5, 2); test_i::(10, 3); test_i::(100, 10); test_i::(1000000000, 31622); test_i::(152415765279683, 12345677); test_i::(152415765279684, 12345678); test_i::(152415765279685, 12345678); } fn floor_sqrt_fail_helper() { assert_panic!(T::NEGATIVE_ONE.floor_sqrt()); } #[test] pub fn floor_sqrt_fail() { apply_fn_to_signeds!(floor_sqrt_fail_helper); } #[test] fn test_ceiling_sqrt() { fn test_u(n: T, out: T) { assert_eq!(n.ceiling_sqrt(), out); assert_eq!(ceiling_sqrt_binary(n), out); let mut n = n; n.ceiling_sqrt_assign(); assert_eq!(n, out); } test_u::(0, 0); test_u::(1, 1); test_u::(2, 2); test_u::(3, 2); test_u::(4, 2); test_u::(5, 3); test_u::(10, 4); test_u::(100, 10); test_u::(1000000000, 31623); test_u::(152415765279683, 12345678); test_u::(152415765279684, 12345678); test_u::(152415765279685, 12345679); fn test_i(n: T, out: T) { assert_eq!(n.ceiling_sqrt(), out); let mut n = n; n.ceiling_sqrt_assign(); assert_eq!(n, out); } test_i::(0, 0); test_i::(1, 1); test_i::(2, 2); test_i::(3, 2); test_i::(4, 2); test_i::(5, 3); test_i::(10, 4); test_i::(100, 10); test_i::(1000000000, 31623); test_i::(152415765279683, 12345678); test_i::(152415765279684, 12345678); test_i::(152415765279685, 12345679); } fn ceiling_sqrt_fail_helper() { assert_panic!(T::NEGATIVE_ONE.ceiling_sqrt()); } #[test] pub fn ceiling_sqrt_fail() { apply_fn_to_signeds!(ceiling_sqrt_fail_helper); } #[test] fn test_checked_sqrt() { fn test_u(n: T, out: Option) { assert_eq!(n.checked_sqrt(), out); assert_eq!(checked_sqrt_binary(n), out); } test_u::(0, Some(0)); test_u::(1, Some(1)); test_u::(2, None); test_u::(3, None); test_u::(4, Some(2)); test_u::(5, None); test_u::(10, None); test_u::(100, Some(10)); test_u::(1000000000, None); test_u::(152415765279683, None); test_u::(152415765279684, Some(12345678)); test_u::(152415765279685, None); fn test_i(n: T, out: Option) { assert_eq!(n.checked_sqrt(), out); } test_i::(0, Some(0)); test_i::(1, Some(1)); test_i::(2, None); test_i::(3, None); test_i::(4, Some(2)); test_i::(5, None); test_i::(10, None); test_i::(100, Some(10)); test_i::(1000000000, None); test_i::(152415765279683, None); test_i::(152415765279684, Some(12345678)); test_i::(152415765279685, None); } fn checked_sqrt_fail_helper() { assert_panic!(T::NEGATIVE_ONE.checked_sqrt()); } #[test] pub fn checked_sqrt_fail() { apply_fn_to_signeds!(checked_sqrt_fail_helper); } #[test] fn test_sqrt_rem() { fn test(n: T, sqrt: T, rem: T) { let (actual_sqrt, actual_rem) = n.sqrt_rem(); assert_eq!(actual_sqrt, sqrt); assert_eq!(actual_rem, rem); assert_eq!(sqrt_rem_binary(n), (sqrt, rem)); let mut n = n; assert_eq!(n.sqrt_assign_rem(), rem); assert_eq!(n, sqrt); } test::(0, 0, 0); test::(1, 1, 0); test::(2, 1, 1); test::(3, 1, 2); test::(4, 2, 0); test::(5, 2, 1); test::(10, 3, 1); test::(100, 10, 0); test::(1000000000, 31622, 49116); test::(152415765279683, 12345677, 24691354); test::(152415765279684, 12345678, 0); test::(152415765279685, 12345678, 1); } #[test] fn test_sqrt() { fn test(n: T, out: T) { assert_eq!(NiceFloat(n.sqrt()), NiceFloat(out)); let mut n = n; n.sqrt_assign(); assert_eq!(NiceFloat(n), NiceFloat(out)); } test::(0.0, 0.0); test::(-0.0, -0.0); test::(1.0, 1.0); test::(f32::INFINITY, f32::INFINITY); test::(f32::NAN, f32::NAN); test::(2.0, std::f32::consts::SQRT_2); test::(-1.0, f32::NAN); test::(0.0, 0.0); test::(-0.0, -0.0); test::(1.0, 1.0); test::(f64::INFINITY, f64::INFINITY); test::(f64::NAN, f64::NAN); test::(2.0, std::f64::consts::SQRT_2); test::(-1.0, f64::NAN); } fn floor_sqrt_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let sqrt = n.floor_sqrt(); let mut n_alt = n; n_alt.floor_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(floor_sqrt_binary(n), sqrt); assert_eq!(n.floor_root(2), sqrt); let square = sqrt.square(); let ceiling_sqrt = n.ceiling_sqrt(); if square == n { assert_eq!(ceiling_sqrt, sqrt); } else { assert_eq!(ceiling_sqrt, sqrt + T::ONE); } assert!(square <= n); if let Some(next_square) = (sqrt + T::ONE).checked_square() { assert!(next_square > n); } }); } fn floor_sqrt_properties_helper_signed() { signed_gen_var_2::().test_properties(|n| { let sqrt = n.floor_sqrt(); let mut n_alt = n; n_alt.floor_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(n.floor_root(2), sqrt); let square = sqrt.square(); let ceiling_sqrt = n.ceiling_sqrt(); if square == n { assert_eq!(ceiling_sqrt, sqrt); } else { assert_eq!(ceiling_sqrt, sqrt + T::ONE); } assert!(square <= n); if let Some(next_square) = (sqrt + T::ONE).checked_square() { assert!(next_square > n); } }); } #[test] fn floor_sqrt_properties() { apply_fn_to_unsigneds!(floor_sqrt_properties_helper_unsigned); apply_fn_to_signeds!(floor_sqrt_properties_helper_signed); } fn ceiling_sqrt_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let sqrt = n.ceiling_sqrt(); let mut n_alt = n; n_alt.ceiling_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(ceiling_sqrt_binary(n), sqrt); assert_eq!(n.ceiling_root(2), sqrt); if let Some(square) = sqrt.checked_square() { let floor_sqrt = n.floor_sqrt(); if square == n { assert_eq!(floor_sqrt, sqrt); } else { assert_eq!(floor_sqrt, sqrt - T::ONE); } assert!(square >= n); } if n != T::ZERO { assert!((sqrt - T::ONE).square() < n); } }); } fn ceiling_sqrt_properties_helper_signed() { signed_gen_var_2::().test_properties(|n| { let sqrt = n.ceiling_sqrt(); let mut n_alt = n; n_alt.ceiling_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(n.ceiling_root(2), sqrt); if let Some(square) = sqrt.checked_square() { let floor_sqrt = n.floor_sqrt(); if square == n { assert_eq!(floor_sqrt, sqrt); } else { assert_eq!(floor_sqrt, sqrt - T::ONE); } assert!(square >= n); } if n != T::ZERO { assert!((sqrt - T::ONE).square() < n); } }); } #[test] fn ceiling_sqrt_properties() { apply_fn_to_unsigneds!(ceiling_sqrt_properties_helper_unsigned); apply_fn_to_signeds!(ceiling_sqrt_properties_helper_signed); } fn checked_sqrt_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let sqrt = n.checked_sqrt(); assert_eq!(checked_sqrt_binary(n), sqrt); assert_eq!(n.checked_root(2), sqrt); if let Some(sqrt) = sqrt { assert_eq!(sqrt.square(), n); assert_eq!(n.floor_sqrt(), sqrt); assert_eq!(n.ceiling_sqrt(), sqrt); } }); } fn checked_sqrt_properties_helper_signed() { signed_gen_var_2::().test_properties(|n| { let sqrt = n.checked_sqrt(); assert_eq!(n.checked_root(2), sqrt); if let Some(sqrt) = sqrt { assert_eq!(sqrt.square(), n); assert_eq!(n.floor_sqrt(), sqrt); assert_eq!(n.ceiling_sqrt(), sqrt); } }); } #[test] fn checked_sqrt_properties() { apply_fn_to_unsigneds!(checked_sqrt_properties_helper_unsigned); apply_fn_to_signeds!(checked_sqrt_properties_helper_signed); } fn sqrt_rem_properties_helper() { unsigned_gen::().test_properties(|n| { let (sqrt, rem) = n.sqrt_rem(); let mut n_alt = n; assert_eq!(n_alt.sqrt_assign_rem(), rem); assert_eq!(n_alt, sqrt); assert_eq!(sqrt_rem_binary(n), (sqrt, rem)); assert_eq!(n.root_rem(2), (sqrt, rem)); assert_eq!(n.floor_sqrt(), sqrt); assert!(rem <= sqrt << 1); assert_eq!(sqrt.square() + rem, n); }); } fn sqrt_rem_properties_helper_extra< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { unsigned_gen_var_17::().test_properties(|n| { assert_eq!(sqrt_rem_newton::(n), n.sqrt_rem()); }); } #[test] fn sqrt_rem_properties() { apply_fn_to_unsigneds!(sqrt_rem_properties_helper); sqrt_rem_properties_helper_extra::(); sqrt_rem_properties_helper_extra::(); } fn sqrt_assign_properties_helper() { primitive_float_gen::().test_properties(|f| { let mut sqrt = f; sqrt.sqrt_assign(); assert_eq!(NiceFloat(sqrt), NiceFloat(f.sqrt())); assert!(sqrt.is_nan() || sqrt >= T::ZERO); }); } #[test] fn sqrt_assign_properties() { apply_fn_to_primitive_floats!(sqrt_assign_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_gen, signed_gen_var_10, unsigned_gen_var_21, }; #[test] fn test_square() { fn test_i(x: T, out: T) { assert_eq!(x.square(), out); let mut x = x; x.square_assign(); assert_eq!(x, out); } test_i::(0, 0); test_i::(1, 1); test_i::(2, 4); test_i::(3, 9); test_i::(10, 100); test_i::(123, 15129); test_i::(1000, 1000000); test_i::(-1, 1); test_i::(-2, 4); test_i::(-3, 9); test_i::(-10, 100); test_i::(-123, 15129); test_i::(-1000, 1000000); fn test_f(x: T, out: T) { assert_eq!(NiceFloat(x.square()), NiceFloat(out)); let mut x = x; x.square_assign(); assert_eq!(NiceFloat(x), NiceFloat(out)); } test_f::(f32::NAN, f32::NAN); test_f::(f32::INFINITY, f32::INFINITY); test_f::(f32::NEGATIVE_INFINITY, f32::INFINITY); test_f::(0.0, 0.0); test_f::(-0.0, 0.0); test_f::(1.0, 1.0); test_f::(-1.0, 1.0); test_f::(0.5, 0.25); test_f::(-0.5, 0.25); test_f::(core::f32::consts::SQRT_2, 1.9999999); test_f::(-core::f32::consts::SQRT_2, 1.9999999); test_f::(core::f32::consts::PI, 9.869605); test_f::(-core::f32::consts::PI, 9.869605); test_f::(f64::NAN, f64::NAN); test_f::(f64::INFINITY, f64::INFINITY); test_f::(f64::NEGATIVE_INFINITY, f64::INFINITY); test_f::(0.0, 0.0); test_f::(-0.0, 0.0); test_f::(1.0, 1.0); test_f::(-1.0, 1.0); test_f::(0.5, 0.25); test_f::(-0.5, 0.25); test_f::(core::f64::consts::SQRT_2, 2.0000000000000004); test_f::(-core::f64::consts::SQRT_2, 2.0000000000000004); test_f::(core::f64::consts::PI, 9.869604401089358); test_f::(-core::f64::consts::PI, 9.869604401089358); } fn square_properties_helper_unsigned() { unsigned_gen_var_21::().test_properties(|x| { let mut square = x; square.square_assign(); assert_eq!(square, x.square()); assert_eq!(square, x.pow(2)); assert_eq!(square.checked_sqrt(), Some(x)); if x > T::ONE { assert_eq!(square.checked_log_base(x), Some(2)); } }); } fn square_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + UnsignedAbs + WrappingFrom, >() { signed_gen_var_10::().test_properties(|x| { let mut square = x; square.square_assign(); assert_eq!(square, x.square()); assert_eq!(square, x.pow(2)); if x != S::MIN { assert_eq!((-x).square(), square); } assert_eq!( U::wrapping_from(square).checked_sqrt().unwrap(), x.unsigned_abs() ); }); } fn square_properties_helper_primitive_float() { primitive_float_gen::().test_properties(|x| { let mut square = x; square.square_assign(); assert_eq!(NiceFloat(square), NiceFloat(x.square())); assert_eq!(NiceFloat(square), NiceFloat(x.pow(2))); assert_eq!(NiceFloat((-x).square()), NiceFloat(square)); }); } #[test] fn square_properties() { apply_fn_to_unsigneds!(square_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(square_properties_helper_signed); apply_fn_to_primitive_floats!(square_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_triple_gen, signed_pair_gen, signed_triple_gen_var_2, unsigned_pair_gen_var_27, unsigned_triple_gen_var_2, }; #[test] fn test_sub_mul() { fn test_i(x: T, y: T, z: T, out: T) { assert_eq!(x.sub_mul(y, z), out); let mut x = x; x.sub_mul_assign(y, z); assert_eq!(x, out); } test_i::(100, 3, 7, 79); test_i::(60, 5, 10, 10); test_i::(1000000, 456, 789, 640216); test_i::(123, -456, 789, 359907); test_i::(-123, 456, 789, -359907); test_i::(127, 2, 100, -73); test_i::(-127, -2, 100, 73); test_i::(-128, 1, 0, -128); fn test_f(x: T, y: T, z: T, out: T) { assert_eq!(NiceFloat(x.sub_mul(y, z)), NiceFloat(out)); let mut x = x; x.sub_mul_assign(y, z); assert_eq!(NiceFloat(x), NiceFloat(out)); } test_f::(1.0, 2.0, 3.0, -5.0); test_f::(1.0, f32::INFINITY, 2.0, f32::NEGATIVE_INFINITY); test_f::(f32::NAN, 1.0, 2.0, f32::NAN); } fn sub_mul_properties_helper_unsigned() { unsigned_triple_gen_var_2::().test_properties(|(x, y, z)| { let result = x.sub_mul(y, z); let mut x_alt = x; x_alt.sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.sub_mul(z, y), result); assert_eq!(result.add_mul(y, z), x); assert_eq!(x.checked_sub_mul(y, z), Some(result)); assert_eq!(x.saturating_sub_mul(y, z), result); assert_eq!(x.wrapping_sub_mul(y, z), result); assert_eq!(x.overflowing_sub_mul(y, z), (result, false)); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.sub_mul(T::ZERO, b), a); assert_eq!(a.sub_mul(b, T::ZERO), a); }); } fn sub_mul_properties_helper_signed() { signed_triple_gen_var_2::().test_properties(|(x, y, z)| { let result = x.sub_mul(y, z); let mut x_alt = x; x_alt.sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.sub_mul(z, y), result); assert_eq!(result.add_mul(y, z), x); assert_eq!(x.checked_sub_mul(y, z), Some(result)); assert_eq!(x.saturating_sub_mul(y, z), result); assert_eq!(x.wrapping_sub_mul(y, z), result); assert_eq!(x.overflowing_sub_mul(y, z), (result, false)); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.sub_mul(T::ZERO, b), a); assert_eq!(a.sub_mul(b, T::ZERO), a); }); } fn sub_mul_properties_helper_primitive_float() { primitive_float_triple_gen::().test_properties(|(x, y, z)| { let result = x.sub_mul(y, z); let mut x_alt = x; x_alt.sub_mul_assign(y, z); assert_eq!(NiceFloat(x_alt), NiceFloat(result)); assert_eq!(NiceFloat(x.sub_mul(z, y)), NiceFloat(result)); }); } #[test] fn sub_mul_properties() { apply_fn_to_unsigneds!(sub_mul_properties_helper_unsigned); apply_fn_to_signeds!(sub_mul_properties_helper_signed); apply_fn_to_primitive_floats!(sub_mul_properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::generators::signed_gen; fn wrapping_abs_helper() { let test = |n: T, out| { assert_eq!(n.wrapping_abs(), out); let mut n = n; n.wrapping_abs_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::ONE); test(T::exact_from(100), T::exact_from(100)); test(T::MAX, T::MAX); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); test(T::MIN, T::MIN); } #[test] fn test_wrapping_abs() { apply_fn_to_signeds!(wrapping_abs_helper); } fn wrapping_abs_properties_helper() { signed_gen::().test_properties(|n| { let mut abs = n; abs.wrapping_abs_assign(); assert_eq!(abs, n.wrapping_abs()); assert_eq!(abs.wrapping_abs(), abs); if n != T::MIN { assert_eq!(n.abs(), abs); } assert_eq!(abs == n, n >= T::ZERO || n == T::MIN); }); } #[test] fn wrapping_abs_properties() { apply_fn_to_signeds!(wrapping_abs_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_wrapping_add() { fn test(x: T, y: T, out: T) { assert_eq!(x.wrapping_add(y), out); let mut x = x; x.wrapping_add_assign(y); assert_eq!(x, out); } test::(123, 456, 579); test::(123, 200, 67); test::(123, -456, -333); test::(123, 45, -88); test::(-123, -45, 88); } fn wrapping_add_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut sum = x; sum.wrapping_add_assign(y); assert_eq!(sum, x.wrapping_add(y)); assert_eq!(sum, x.wrapping_sub(y.wrapping_neg())); assert_eq!(sum.wrapping_sub(x), y); assert_eq!(sum.wrapping_sub(y), x); assert_eq!(y.wrapping_add(x), sum); }); } fn wrapping_add_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut sum = x; sum.wrapping_add_assign(y); assert_eq!(sum, x.wrapping_add(y)); assert_eq!(sum, x.wrapping_sub(y.wrapping_neg())); assert_eq!(sum.wrapping_sub(x), y); assert_eq!(sum.wrapping_sub(y), x); assert_eq!(y.wrapping_add(x), sum); }); } #[test] fn wrapping_add_properties() { apply_fn_to_unsigneds!(wrapping_add_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_add_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_wrapping_add_mul() { fn test(x: T, y: T, z: T, out: T) { assert_eq!(x.wrapping_add_mul(y, z), out); let mut x = x; x.wrapping_add_mul_assign(y, z); assert_eq!(x, out); } test::(2, 3, 7, 23); test::(7, 5, 10, 57); test::(123, 456, 789, 359907); test::(123, -456, 789, -359661); test::(-123, 456, 789, 359661); test::(127, -2, 100, -73); test::(-127, 2, 100, 73); test::(-128, 1, 0, -128); test::(2, 20, 20, 146); test::(-127, -2, 100, -71); test::(127, 1, 100, -29); test::(-127, -1, 100, 29); test::(-127, -10, 100, -103); } fn wrapping_add_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.wrapping_add_mul(y, z); let mut x_alt = x; x_alt.wrapping_add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.wrapping_add_mul(z, y), result); assert_eq!(result.wrapping_sub_mul(y, z), x); assert_eq!(x.overflowing_add_mul(y, z).0, result); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.wrapping_add_mul(T::ZERO, b), a); assert_eq!(a.wrapping_add_mul(T::ONE, b), a.wrapping_add(b)); assert_eq!(T::ZERO.wrapping_add_mul(a, b), a.wrapping_mul(b)); assert_eq!(a.wrapping_add_mul(b, T::ZERO), a); assert_eq!(a.wrapping_add_mul(b, T::ONE), a.wrapping_add(b)); }); } fn wrapping_add_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.wrapping_add_mul(y, z); let mut x_alt = x; x_alt.wrapping_add_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.wrapping_add_mul(z, y), result); assert_eq!(result.wrapping_sub_mul(y, z), x); assert_eq!(x.overflowing_add_mul(y, z).0, result); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.wrapping_add_mul(T::ZERO, b), a); assert_eq!(a.wrapping_add_mul(T::ONE, b), a.wrapping_add(b)); assert_eq!(T::ZERO.wrapping_add_mul(a, b), a.wrapping_mul(b)); assert_eq!(a.wrapping_add_mul(b, T::ZERO), a); assert_eq!(a.wrapping_add_mul(b, T::ONE), a.wrapping_add(b)); }); } #[test] fn wrapping_add_mul_properties() { apply_fn_to_unsigneds!(wrapping_add_mul_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_add_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_div.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen_var_6, unsigned_gen, unsigned_pair_gen_var_12, }; use std::panic::catch_unwind; #[test] fn test_wrapping_div() { fn test(x: T, y: T, out: T) { assert_eq!(x.wrapping_div(y), out); let mut x = x; x.wrapping_div_assign(y); assert_eq!(x, out); } test::(0, 5, 0); test::(123, 456, 0); test::(100, 3, 33); test::(100, -3, -33); test::(-100, 3, -33); test::(-100, -3, 33); test::(-128, -1, -128); } fn wrapping_div_assign_fail_helper() { assert_panic!({ let mut n = T::ONE; n.wrapping_div_assign(T::ZERO); }); } #[test] fn wrapping_div_assign_fail() { apply_fn_to_primitive_ints!(wrapping_div_assign_fail_helper); } fn wrapping_div_properties_helper_unsigned() { unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let mut quotient = x; quotient.wrapping_div_assign(y); assert_eq!(quotient, x.wrapping_div(y)); assert_eq!(x / y, quotient); }); unsigned_gen::().test_properties(|x| { assert_panic!(x.wrapping_div(T::ZERO)); assert_panic!({ let mut y = x; y.wrapping_div_assign(T::ZERO); }); }); } fn wrapping_div_properties_helper_signed() { signed_pair_gen_var_6::().test_properties(|(x, y)| { let mut quotient = x; quotient.wrapping_div_assign(y); assert_eq!(quotient, x.wrapping_div(y)); if x != T::MIN || y != T::NEGATIVE_ONE { assert_eq!(x / y, quotient); } }); signed_gen::().test_properties(|x| { assert_panic!(x.wrapping_div(T::ZERO)); assert_panic!({ let mut y = x; y.wrapping_div_assign(T::ZERO); }); }); } #[test] fn wrapping_div_properties() { apply_fn_to_unsigneds!(wrapping_div_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_div_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_wrapping_mul() { fn test(x: T, y: T, out: T) { assert_eq!(x.wrapping_mul(y), out); let mut x = x; x.wrapping_mul_assign(y); assert_eq!(x, out); } test::(123, 456, 56088); test::(123, 200, 24); test::(123, -45, -5535); test::(123, 45, -97); test::(-123, 45, 97); } fn wrapping_mul_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut product = x; product.wrapping_mul_assign(y); assert_eq!(product, x.wrapping_mul(y)); assert_eq!(y.wrapping_mul(x), product); }); } fn wrapping_mul_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut product = x; product.wrapping_mul_assign(y); assert_eq!(product, x.wrapping_mul(y)); assert_eq!(y.wrapping_mul(x), product); }); } #[test] fn wrapping_mul_properties() { apply_fn_to_unsigneds!(wrapping_mul_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; fn unsigned_wrapping_neg_helper() { let test = |n: T, out| { assert_eq!(n.wrapping_neg(), out); let mut n = n; n.wrapping_neg_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::MAX); test(T::exact_from(100), T::MAX - T::exact_from(100) + T::ONE); test(T::MAX, T::ONE); } fn signed_wrapping_neg_helper() { let test = |n: T, out| { assert_eq!(n.wrapping_neg(), out); let mut n = n; n.wrapping_neg_assign(); assert_eq!(n, out); }; test(T::ZERO, T::ZERO); test(T::ONE, T::NEGATIVE_ONE); test(T::exact_from(100), T::exact_from(-100)); test(T::MAX, T::MIN + T::ONE); test(T::NEGATIVE_ONE, T::ONE); test(T::exact_from(-100), T::exact_from(100)); test(T::MIN, T::MIN); } #[test] fn test_wrapping_neg() { apply_fn_to_unsigneds!(unsigned_wrapping_neg_helper); apply_fn_to_signeds!(signed_wrapping_neg_helper); } fn wrapping_neg_properties_helper_unsigned() { unsigned_gen::().test_properties(|n| { let mut neg = n; neg.wrapping_neg_assign(); assert_eq!(neg, n.wrapping_neg()); assert_eq!(neg.wrapping_neg(), n); assert_eq!(neg == n, n == T::ZERO || n == T::power_of_2(T::WIDTH - 1)); assert_eq!(n.wrapping_add(neg), T::ZERO); }); } fn wrapping_neg_properties_helper_signed() { signed_gen::().test_properties(|n| { let mut neg = n; neg.wrapping_neg_assign(); assert_eq!(neg, n.wrapping_neg()); assert_eq!(neg.wrapping_neg(), n); assert_eq!(neg == n, n == T::ZERO || n == T::MIN); assert_eq!(n.wrapping_add(neg), T::ZERO); }); } #[test] fn wrapping_neg_properties() { apply_fn_to_unsigneds!(wrapping_neg_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_neg_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_unsigned_pair_gen, unsigned_pair_gen}; #[test] fn test_wrapping_pow() { fn test(x: T, y: u64, out: T) { assert_eq!(x.wrapping_pow(y), out); let mut x = x; x.wrapping_pow_assign(y); assert_eq!(x, out); } test::(0, 0, 1); test::(123, 0, 1); test::(123, 1, 123); test::(0, 123, 0); test::(1, 123, 1); test::(-1, 123, -1); test::(-1, 124, 1); test::(3, 3, 27); test::(-10, 9, -1000000000); test::(-10, 10, 1410065408); test::(-10, 9, 13824); test::(10, 9, -13824); test::(123, 456, 2409344748064316129); test::(0, u64::MAX, 0); test::(1, u64::MAX, 1); test::(123, u64::MAX, 3449391168254631603); test::(0, u64::MAX, 0); test::(1, u64::MAX, 1); test::(-1, u64::MAX, -1); test::(-1, u64::MAX - 1, 1); test::(123, u64::MAX, 3449391168254631603); test::(-123, u64::MAX, -3449391168254631603); test::(-123, u64::MAX - 1, 4527249702272692521); } fn wrapping_pow_properties_helper_unsigned() { unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.wrapping_pow_assign(y); assert_eq!(power, x.wrapping_pow(y)); }); } fn wrapping_pow_properties_helper_signed() { signed_unsigned_pair_gen::().test_properties(|(x, y)| { let mut power = x; power.wrapping_pow_assign(y); assert_eq!(power, x.wrapping_pow(y)); if x != T::MIN { let neg_pow = (-x).wrapping_pow(y); if y.even() { assert_eq!(neg_pow, power); } else { assert_eq!(neg_pow, power.wrapping_neg()); } } }); } #[test] fn wrapping_pow_properties() { apply_fn_to_unsigneds!(wrapping_pow_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_pow_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; #[test] fn test_wrapping_square() { fn test(x: T, out: T) { assert_eq!(x.wrapping_square(), out); let mut x = x; x.wrapping_square_assign(); assert_eq!(x, out); } test::(0, 0); test::(1, 1); test::(2, 4); test::(3, 9); test::(10, 100); test::(123, 15129); test::(1000, 1000000); test::(-1, 1); test::(-2, 4); test::(-3, 9); test::(-10, 100); test::(-123, 15129); test::(-1000, 1000000); test::(1000, 16960); test::(-1000, 16960); } fn wrapping_square_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { let mut square = x; square.wrapping_square_assign(); assert_eq!(square, x.wrapping_square()); assert_eq!(square, x.wrapping_pow(2)); }); } fn wrapping_square_properties_helper_signed() { signed_gen::().test_properties(|x| { let mut square = x; square.wrapping_square_assign(); assert_eq!(square, x.wrapping_square()); assert_eq!(square, x.wrapping_pow(2)); if x != T::MIN { assert_eq!((-x).wrapping_square(), square); } }); } #[test] fn saturating_square_properties() { apply_fn_to_unsigneds!(wrapping_square_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_square_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; #[test] fn test_wrapping_sub() { fn test(x: T, y: T, out: T) { assert_eq!(x.wrapping_sub(y), out); let mut x = x; x.wrapping_sub_assign(y); assert_eq!(x, out); } test::(456, 123, 333); test::(123, 200, 179); test::(123, -456, 579); test::(123, -45, -88); test::(-123, 45, 88); } fn wrapping_sub_properties_helper_unsigned() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let mut diff = x; diff.wrapping_sub_assign(y); assert_eq!(diff, x.wrapping_sub(y)); assert_eq!(diff, x.wrapping_add(y.wrapping_neg())); assert_eq!(diff.wrapping_add(y), x); assert_eq!(y.wrapping_sub(x), diff.wrapping_neg()); }); } fn wrapping_sub_properties_helper_signed() { signed_pair_gen::().test_properties(|(x, y)| { let mut diff = x; diff.wrapping_sub_assign(y); assert_eq!(diff, x.wrapping_sub(y)); assert_eq!(diff, x.wrapping_add(y.wrapping_neg())); assert_eq!(diff.wrapping_add(y), x); assert_eq!(y.wrapping_sub(x), diff.wrapping_neg()); }); } #[test] fn wrapping_sub_properties() { apply_fn_to_unsigneds!(wrapping_sub_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_sub_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/wrapping_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_pair_gen, signed_triple_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_wrapping_sub_mul() { fn test(x: T, y: T, z: T, out: T) { assert_eq!(x.wrapping_sub_mul(y, z), out); let mut x = x; x.wrapping_sub_mul_assign(y, z); assert_eq!(x, out); } test::(100, 3, 7, 79); test::(60, 5, 10, 10); test::(1000000, 456, 789, 640216); test::(123, -456, 789, 359907); test::(-123, 456, 789, -359907); test::(127, 2, 100, -73); test::(-127, -2, 100, 73); test::(-128, 1, 0, -128); test::(2, 10, 5, 208); test::(-127, 2, 100, -71); test::(-127, 1, 100, 29); test::(127, -1, 100, -29); test::(127, -10, 100, 103); } fn wrapping_sub_mul_properties_helper_unsigned() { unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = x.wrapping_sub_mul(y, z); let mut x_alt = x; x_alt.wrapping_sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.wrapping_sub_mul(z, y), result); assert_eq!(result.wrapping_add_mul(y, z), x); assert_eq!(x.overflowing_sub_mul(y, z).0, result); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { assert_eq!(a.wrapping_sub_mul(T::ZERO, b), a); assert_eq!(a.wrapping_sub_mul(T::ONE, b), a.wrapping_sub(b)); assert_eq!( T::ZERO.wrapping_sub_mul(a, b), a.wrapping_mul(b).wrapping_neg() ); assert_eq!(a.wrapping_sub_mul(b, T::ZERO), a); assert_eq!(a.wrapping_sub_mul(b, T::ONE), a.wrapping_sub(b)); }); } fn wrapping_sub_mul_properties_helper_signed() { signed_triple_gen::().test_properties(|(x, y, z)| { let result = x.wrapping_sub_mul(y, z); let mut x_alt = x; x_alt.wrapping_sub_mul_assign(y, z); assert_eq!(x_alt, result); assert_eq!(x.wrapping_sub_mul(z, y), result); assert_eq!(result.wrapping_add_mul(y, z), x); assert_eq!(x.overflowing_sub_mul(y, z).0, result); }); signed_pair_gen::().test_properties(|(a, b)| { assert_eq!(a.wrapping_sub_mul(T::ZERO, b), a); assert_eq!(a.wrapping_sub_mul(T::ONE, b), a.wrapping_sub(b)); assert_eq!( T::ZERO.wrapping_sub_mul(a, b), a.wrapping_mul(b).wrapping_neg() ); assert_eq!(a.wrapping_sub_mul(b, T::ZERO), a); assert_eq!(a.wrapping_sub_mul(b, T::ONE), a.wrapping_sub(b)); }); } #[test] fn wrapping_sub_mul_properties() { apply_fn_to_unsigneds!(wrapping_sub_mul_properties_helper_unsigned); apply_fn_to_signeds!(wrapping_sub_mul_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/arithmetic/x_mul_y_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::x_mul_y_to_zz::explicit_x_mul_y_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] fn test_x_mul_y_to_zz() { fn test(x: T, y: T, z_1: T, z_0: T) { assert_eq!(T::x_mul_y_to_zz(x, y), (z_1, z_0)); assert_eq!(explicit_x_mul_y_to_zz(x, y), (z_1, z_0)); } test::(0, 0, 0, 0); test::(15, 3, 0, 45); test::(0x78, 0x9a, 0x48, 0x30); test::(u8::MAX, 0, 0, 0); test::(u8::MAX, 1, 0, u8::MAX); test(u16::MAX, u16::MAX, u16::MAX - 1, 1); } fn x_mul_y_to_zz_properties_helper() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let p = T::x_mul_y_to_zz(x, y); assert_eq!(explicit_x_mul_y_to_zz(x, y), p); assert_eq!(T::x_mul_y_to_zz(y, x), p); }); unsigned_gen::().test_properties(|x| { assert_eq!(T::x_mul_y_to_zz(x, T::ZERO), (T::ZERO, T::ZERO)); assert_eq!(T::x_mul_y_to_zz(T::ZERO, x), (T::ZERO, T::ZERO)); assert_eq!(T::x_mul_y_to_zz(x, T::ONE), (T::ZERO, x)); assert_eq!(T::x_mul_y_to_zz(T::ONE, x), (T::ZERO, x)); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let product_1 = T::x_mul_y_to_zz(x, y).1; let product_2 = T::x_mul_y_to_zz(y, z).1; assert_eq!(product_1.wrapping_mul(z), x.wrapping_mul(product_2)); }); } #[test] fn x_mul_y_to_zz_properties() { apply_fn_to_unsigneds!(x_mul_y_to_zz_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xx_add_yy_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_add_yy_to_zz::explicit_xx_add_yy_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_10, unsigned_sextuple_gen_var_1, }; #[test] fn test_xx_add_yy_to_zz() { fn test(x_1: T, x_0: T, y_1: T, y_0: T, z_1: T, z_0: T) { assert_eq!(T::xx_add_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); assert_eq!(explicit_xx_add_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); } test::(0, 0, 0, 0, 0, 0); test::(0x12, 0x34, 0x33, 0x33, 0x45, 0x67); test::(0x78, 0x9a, 0xbc, 0xde, 0x35, 0x78); test::(u8::MAX, u8::MAX, 0, 1, 0, 0); test( u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX - 1, ); } fn xx_add_yy_to_zz_properties_helper() { unsigned_quadruple_gen_var_10::().test_properties(|(x_1, x_0, y_1, y_0)| { let (z_1, z_0) = T::xx_add_yy_to_zz(x_1, x_0, y_1, y_0); assert_eq!(explicit_xx_add_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); assert_eq!(T::xx_sub_yy_to_zz(z_1, z_0, y_1, y_0), (x_1, x_0)); assert_eq!(T::xx_sub_yy_to_zz(z_1, z_0, x_1, x_0), (y_1, y_0)); assert_eq!(T::xx_add_yy_to_zz(y_1, y_0, x_1, x_0), (z_1, z_0)); assert_eq!(T::xx_add_yy_to_zz(x_1, y_0, y_1, x_0), (z_1, z_0)); let (neg_y_1, neg_y_0) = T::xx_sub_yy_to_zz(T::ZERO, T::ZERO, y_1, y_0); assert_eq!(T::xx_sub_yy_to_zz(x_1, x_0, neg_y_1, neg_y_0), (z_1, z_0)); }); unsigned_pair_gen_var_27::().test_properties(|(x_1, x_0)| { assert_eq!(T::xx_add_yy_to_zz(x_1, x_0, T::ZERO, T::ZERO), (x_1, x_0)); assert_eq!(T::xx_add_yy_to_zz(T::ZERO, T::ZERO, x_1, x_0), (x_1, x_0)); let (neg_x_1, neg_x_0) = T::xx_sub_yy_to_zz(T::ZERO, T::ZERO, x_1, x_0); assert_eq!( T::xx_add_yy_to_zz(x_1, x_0, neg_x_1, neg_x_0), (T::ZERO, T::ZERO) ); }); unsigned_sextuple_gen_var_1::().test_properties(|(x_1, x_0, y_1, y_0, z_1, z_0)| { let (sum_1_1, sum_1_0) = T::xx_add_yy_to_zz(x_1, x_0, y_1, y_0); let (sum_2_1, sum_2_0) = T::xx_add_yy_to_zz(y_1, y_0, z_1, z_0); assert_eq!( T::xx_add_yy_to_zz(sum_1_1, sum_1_0, z_1, z_0), T::xx_add_yy_to_zz(x_1, x_0, sum_2_1, sum_2_0) ); }); } #[test] fn xx_add_yy_to_zz_properties() { apply_fn_to_unsigneds!(xx_add_yy_to_zz_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xx_div_mod_y_to_qr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_div_mod_y_to_qr::explicit_xx_div_mod_y_to_qr; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{unsigned_gen_var_1, unsigned_triple_gen_var_15}; use std::panic::catch_unwind; #[test] fn test_xx_div_mod_y_to_qr() { fn test(x_1: T, x_0: T, y: T, q: T, r: T) { assert_eq!(T::xx_div_mod_y_to_qr(x_1, x_0, y), (q, r)); assert_eq!(explicit_xx_div_mod_y_to_qr(x_1, x_0, y), (q, r)); } test::(0, 0, 1, 0, 0); test::(0, 1, 1, 1, 0); test::(1, 0, 2, 0x8000, 0); test::(1, 7, 2, 0x8003, 1); test::(0x78, 0x9a, 0xbc, 0xa4, 0x2a); test::(0x12, 0x34, 0x33, 0x5a5a5a5a5a5a5a5b, 0x13); } fn xx_div_mod_y_to_qr_fail_helper() { assert_panic!(T::xx_div_mod_y_to_qr( T::exact_from(3), T::exact_from(5), T::ZERO )); assert_panic!(T::xx_div_mod_y_to_qr( T::exact_from(3), T::exact_from(5), T::TWO )); } #[test] fn xx_div_mod_y_to_qr_fail() { apply_fn_to_unsigneds!(xx_div_mod_y_to_qr_fail_helper); } fn xx_div_mod_y_to_qr_properties_helper() { unsigned_triple_gen_var_15::().test_properties(|(x_1, x_0, y)| { let (q, r) = T::xx_div_mod_y_to_qr(x_1, x_0, y); assert_eq!(explicit_xx_div_mod_y_to_qr(x_1, x_0, y), (q, r)); assert!(r < y); let (product_1, product_0) = T::x_mul_y_to_zz(q, y); assert_eq!( T::xx_add_yy_to_zz(product_1, product_0, T::ZERO, r), (x_1, x_0) ); }); unsigned_gen_var_1::().test_properties(|a| { assert_eq!( T::xx_div_mod_y_to_qr(T::ZERO, T::ZERO, a), (T::ZERO, T::ZERO) ); assert_eq!(T::xx_div_mod_y_to_qr(T::ZERO, a, a), (T::ONE, T::ZERO)); }); } #[test] fn xx_div_mod_y_to_qr_properties() { apply_fn_to_unsigneds!(xx_div_mod_y_to_qr_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xx_sub_yy_to_zz.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::xx_sub_yy_to_zz::explicit_xx_sub_yy_to_zz; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_10, }; #[test] fn test_xx_sub_yy_to_zz() { fn test(x_1: T, x_0: T, y_1: T, y_0: T, z_1: T, z_0: T) { assert_eq!(T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); assert_eq!(explicit_xx_sub_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); } test::(0, 0, 0, 0, 0, 0); test::(0x67, 0x89, 0x33, 0x33, 0x34, 0x56); test::(0x78, 0x9a, 0xbc, 0xde, 0xbb, 0xbc); test::(0, 0, 0, 1, u8::MAX, u8::MAX); test(u16::MAX, u16::MAX, u16::MAX, u16::MAX, 0, 0); } fn xx_sub_yy_to_zz_properties_helper() { unsigned_quadruple_gen_var_10::().test_properties(|(x_1, x_0, y_1, y_0)| { let (z_1, z_0) = T::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); assert_eq!(explicit_xx_sub_yy_to_zz(x_1, x_0, y_1, y_0), (z_1, z_0)); assert_eq!(T::xx_add_yy_to_zz(z_1, z_0, y_1, y_0), (x_1, x_0)); assert_eq!( T::xx_sub_yy_to_zz(z_1, z_0, x_1, x_0), T::xx_sub_yy_to_zz(T::ZERO, T::ZERO, y_1, y_0) ); assert_eq!( T::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0), T::xx_sub_yy_to_zz(T::ZERO, T::ZERO, z_1, z_0) ); let (neg_y_1, neg_y_0) = T::xx_sub_yy_to_zz(T::ZERO, T::ZERO, y_1, y_0); assert_eq!(T::xx_add_yy_to_zz(x_1, x_0, neg_y_1, neg_y_0), (z_1, z_0)); }); unsigned_pair_gen_var_27::().test_properties(|(x_1, x_0)| { assert_eq!(T::xx_sub_yy_to_zz(x_1, x_0, T::ZERO, T::ZERO), (x_1, x_0)); assert_eq!(T::xx_sub_yy_to_zz(x_1, x_0, x_1, x_0), (T::ZERO, T::ZERO)); }); } #[test] fn xx_sub_yy_to_zz_properties() { apply_fn_to_unsigneds!(xx_sub_yy_to_zz_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xxx_add_yyy_to_zzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_nonuple_gen_var_1, unsigned_sextuple_gen_var_1, unsigned_triple_gen_var_19, }; #[test] #[allow(clippy::too_many_arguments)] fn test_xxx_add_yyy_to_zzz() { fn test( x_2: T, x_1: T, x_0: T, y_2: T, y_1: T, y_0: T, z_2: T, z_1: T, z_0: T, ) { assert_eq!( T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0), (z_2, z_1, z_0) ); } test::(0, 0, 0, 0, 0, 0, 0, 0, 0); test::(0x12, 0x34, 0x56, 0x33, 0x33, 0x33, 0x45, 0x67, 0x89); test::(0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc, 0x57, 0x99, 0x98); test::(u8::MAX, u8::MAX, u8::MAX, 0, 0, 1, 0, 0, 0); test( u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX - 1, ); } fn xxx_add_yyy_to_zzz_properties_helper() { unsigned_sextuple_gen_var_1::().test_properties(|(x_2, x_1, x_0, y_2, y_1, y_0)| { let (z_2, z_1, z_0) = T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0); assert_eq!( T::xxx_sub_yyy_to_zzz(z_2, z_1, z_0, y_2, y_1, y_0), (x_2, x_1, x_0) ); assert_eq!( T::xxx_sub_yyy_to_zzz(z_2, z_1, z_0, x_2, x_1, x_0), (y_2, y_1, y_0) ); assert_eq!( T::xxx_add_yyy_to_zzz(y_2, y_1, y_0, x_2, x_1, x_0), (z_2, z_1, z_0) ); let (neg_y_2, neg_y_1, neg_y_0) = T::xxx_sub_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, y_2, y_1, y_0); assert_eq!( T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, neg_y_2, neg_y_1, neg_y_0), (z_2, z_1, z_0) ); }); unsigned_triple_gen_var_19::().test_properties(|(x_2, x_1, x_0)| { assert_eq!( T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, T::ZERO, T::ZERO, T::ZERO), (x_2, x_1, x_0) ); assert_eq!( T::xxx_add_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, x_2, x_1, x_0), (x_2, x_1, x_0) ); let (neg_x_2, neg_x_1, neg_x_0) = T::xxx_sub_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, x_2, x_1, x_0); assert_eq!( T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, neg_x_2, neg_x_1, neg_x_0), (T::ZERO, T::ZERO, T::ZERO) ); }); unsigned_nonuple_gen_var_1::().test_properties( |(x_2, x_1, x_0, y_2, y_1, y_0, z_2, z_1, z_0)| { let (sum_1_2, sum_1_1, sum_1_0) = T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0); let (sum_2_2, sum_2_1, sum_2_0) = T::xxx_add_yyy_to_zzz(y_2, y_1, y_0, z_2, z_1, z_0); assert_eq!( T::xxx_add_yyy_to_zzz(sum_1_2, sum_1_1, sum_1_0, z_2, z_1, z_0), T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, sum_2_2, sum_2_1, sum_2_0) ); }, ); } #[test] fn xxx_add_yyy_to_zzz_properties() { apply_fn_to_unsigneds!(xxx_add_yyy_to_zzz_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xxx_sub_yyy_to_zzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_sextuple_gen_var_1, unsigned_triple_gen_var_19, }; #[test] #[allow(clippy::too_many_arguments)] fn test_xxx_sub_yyy_to_zzz() { fn test( x_2: T, x_1: T, x_0: T, y_2: T, y_1: T, y_0: T, z_2: T, z_1: T, z_0: T, ) { assert_eq!( T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0), (z_2, z_1, z_0) ); } test::(0, 0, 0, 0, 0, 0, 0, 0, 0); test::(0x67, 0x89, 0xab, 0x33, 0x33, 0x33, 0x34, 0x56, 0x78); test::(0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc, 0x99, 0x9b, 0xe0); test::(0, 0, 0, 0, 0, 1, u8::MAX, u8::MAX, u8::MAX); test( u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, 0, 0, 0, ); } fn xxx_sub_yyy_to_zzz_properties_helper() { unsigned_sextuple_gen_var_1::().test_properties(|(x_2, x_1, x_0, y_2, y_1, y_0)| { let (z_2, z_1, z_0) = T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, y_2, y_1, y_0); assert_eq!( T::xxx_add_yyy_to_zzz(z_2, z_1, z_0, y_2, y_1, y_0), (x_2, x_1, x_0) ); assert_eq!( T::xxx_sub_yyy_to_zzz(z_2, z_1, z_0, x_2, x_1, x_0), T::xxx_sub_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, y_2, y_1, y_0) ); assert_eq!( T::xxx_sub_yyy_to_zzz(y_2, y_1, y_0, x_2, x_1, x_0), T::xxx_sub_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, z_2, z_1, z_0) ); let (neg_y_2, neg_y_1, neg_y_0) = T::xxx_sub_yyy_to_zzz(T::ZERO, T::ZERO, T::ZERO, y_2, y_1, y_0); assert_eq!( T::xxx_add_yyy_to_zzz(x_2, x_1, x_0, neg_y_2, neg_y_1, neg_y_0), (z_2, z_1, z_0) ); }); unsigned_triple_gen_var_19::().test_properties(|(x_2, x_1, x_0)| { assert_eq!( T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, T::ZERO, T::ZERO, T::ZERO), (x_2, x_1, x_0) ); assert_eq!( T::xxx_sub_yyy_to_zzz(x_2, x_1, x_0, x_2, x_1, x_0), (T::ZERO, T::ZERO, T::ZERO) ); }); } #[test] fn xxx_sub_yyy_to_zzz_properties() { apply_fn_to_unsigneds!(xxx_sub_yyy_to_zzz_properties_helper); } ================================================ FILE: malachite-base/tests/num/arithmetic/xxxx_add_yyyy_to_zzzz.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ unsigned_duodecuple_gen_var_1, unsigned_octuple_gen_var_1, unsigned_quadruple_gen_var_10, }; #[test] #[allow(clippy::too_many_arguments)] fn test_xxxx_add_yyyy_to_zzzz() { fn test( x_3: T, x_2: T, x_1: T, x_0: T, y_3: T, y_2: T, y_1: T, y_0: T, z_3: T, z_2: T, z_1: T, z_0: T, ) { assert_eq!( T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0), (z_3, z_2, z_1, z_0) ); } test::(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); test::( 0x12, 0x34, 0x56, 0x78, 0x33, 0x33, 0x33, 0x33, 0x45, 0x67, 0x89, 0xab, ); test::( 0x78, 0x9a, 0xbc, 0xde, 0xfe, 0xdc, 0xba, 0x98, 0x77, 0x77, 0x77, 0x76, ); test::(u8::MAX, u8::MAX, u8::MAX, u8::MAX, 0, 0, 0, 1, 0, 0, 0, 0); test( u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX, u16::MAX - 1, ); } fn xxxx_sub_yyyy_to_zzzz( x_3: T, x_2: T, x_1: T, x_0: T, y_3: T, y_2: T, y_1: T, y_0: T, ) -> (T, T, T, T) { let (z_0, borrow_1) = x_0.overflowing_sub(y_0); let (mut z_1, mut borrow_2) = x_1.overflowing_sub(y_1); if borrow_1 { borrow_2 |= z_1.overflowing_sub_assign(T::ONE); } let (mut z_2, mut borrow_3) = x_2.overflowing_sub(y_2); if borrow_2 { borrow_3 |= z_2.overflowing_sub_assign(T::ONE); } let mut z_3 = x_3.wrapping_sub(y_3); if borrow_3 { z_3.wrapping_sub_assign(T::ONE); } (z_3, z_2, z_1, z_0) } fn xxxx_add_yyyy_to_zzzz_properties_helper() { unsigned_octuple_gen_var_1::().test_properties( |(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0)| { let (z_3, z_2, z_1, z_0) = T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0); assert_eq!( xxxx_sub_yyyy_to_zzzz(z_3, z_2, z_1, z_0, y_3, y_2, y_1, y_0), (x_3, x_2, x_1, x_0) ); assert_eq!( xxxx_sub_yyyy_to_zzzz(z_3, z_2, z_1, z_0, x_3, x_2, x_1, x_0), (y_3, y_2, y_1, y_0) ); assert_eq!( T::xxxx_add_yyyy_to_zzzz(y_3, y_2, y_1, y_0, x_3, x_2, x_1, x_0), (z_3, z_2, z_1, z_0) ); let (neg_y_3, neg_y_2, neg_y_1, neg_y_0) = xxxx_sub_yyyy_to_zzzz(T::ZERO, T::ZERO, T::ZERO, T::ZERO, y_3, y_2, y_1, y_0); assert_eq!( xxxx_sub_yyyy_to_zzzz(x_3, x_2, x_1, x_0, neg_y_3, neg_y_2, neg_y_1, neg_y_0), (z_3, z_2, z_1, z_0) ); }, ); unsigned_quadruple_gen_var_10::().test_properties(|(x_3, x_2, x_1, x_0)| { assert_eq!( T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, T::ZERO, T::ZERO, T::ZERO, T::ZERO), (x_3, x_2, x_1, x_0) ); assert_eq!( T::xxxx_add_yyyy_to_zzzz(T::ZERO, T::ZERO, T::ZERO, T::ZERO, x_3, x_2, x_1, x_0), (x_3, x_2, x_1, x_0) ); let (neg_x_3, neg_x_2, neg_x_1, neg_x_0) = xxxx_sub_yyyy_to_zzzz(T::ZERO, T::ZERO, T::ZERO, T::ZERO, x_3, x_2, x_1, x_0); assert_eq!( T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, neg_x_3, neg_x_2, neg_x_1, neg_x_0), (T::ZERO, T::ZERO, T::ZERO, T::ZERO) ); }); unsigned_duodecuple_gen_var_1::().test_properties( |(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0, z_3, z_2, z_1, z_0)| { let (sum_1_3, sum_1_2, sum_1_1, sum_1_0) = T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, y_3, y_2, y_1, y_0); let (sum_2_3, sum_2_2, sum_2_1, sum_2_0) = T::xxxx_add_yyyy_to_zzzz(y_3, y_2, y_1, y_0, z_3, z_2, z_1, z_0); assert_eq!( T::xxxx_add_yyyy_to_zzzz(sum_1_3, sum_1_2, sum_1_1, sum_1_0, z_3, z_2, z_1, z_0), T::xxxx_add_yyyy_to_zzzz(x_3, x_2, x_1, x_0, sum_2_3, sum_2_2, sum_2_1, sum_2_0) ); }, ); } #[test] fn xxxx_add_yyyy_to_zzzz_properties() { apply_fn_to_unsigneds!(xxxx_add_yyyy_to_zzzz_properties_helper); } ================================================ FILE: malachite-base/tests/num/basic/constants.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Two, Zero, }; use malachite_base::num::float::NiceFloat; macro_rules! test_unsigned_constants { ($t: ident) => { assert_eq!($t::ZERO, 0); assert_eq!($t::ONE, 1); assert_eq!($t::TWO, 2); }; } macro_rules! test_signed_constants { ($t: ident) => { test_unsigned_constants!($t); assert_eq!($t::NEGATIVE_ONE, -1); }; } macro_rules! test_float_constants { ($t: ident) => { assert_eq!($t::ZERO, 0.0); assert_eq!($t::ONE, 1.0); assert_eq!($t::TWO, 2.0); assert_eq!($t::NEGATIVE_ONE, -1.0); assert_eq!($t::NEGATIVE_ZERO, -0.0); assert_eq!($t::ONE_HALF, 0.5); }; } #[test] fn test_constants() { apply_to_unsigneds!(test_unsigned_constants); apply_to_signeds!(test_signed_constants); apply_to_primitive_floats!(test_float_constants); } #[test] fn test_width_constants() { assert_eq!(u8::WIDTH, 8); assert_eq!(u8::LOG_WIDTH, 3); assert_eq!(u8::WIDTH_MASK, 0x7); assert_eq!(u16::WIDTH, 16); assert_eq!(u16::LOG_WIDTH, 4); assert_eq!(u16::WIDTH_MASK, 0xf); assert_eq!(u32::WIDTH, 32); assert_eq!(u32::LOG_WIDTH, 5); assert_eq!(u32::WIDTH_MASK, 0x1f); assert_eq!(u64::WIDTH, 64); assert_eq!(u64::LOG_WIDTH, 6); assert_eq!(u64::WIDTH_MASK, 0x3f); assert_eq!(u128::WIDTH, 128); assert_eq!(u128::LOG_WIDTH, 7); assert_eq!(u128::WIDTH_MASK, 0x7f); assert_eq!(i8::WIDTH, 8); assert_eq!(i8::LOG_WIDTH, 3); assert_eq!(i8::WIDTH_MASK, 0x7); assert_eq!(i16::WIDTH, 16); assert_eq!(i16::LOG_WIDTH, 4); assert_eq!(i16::WIDTH_MASK, 0xf); assert_eq!(i32::WIDTH, 32); assert_eq!(i32::LOG_WIDTH, 5); assert_eq!(i32::WIDTH_MASK, 0x1f); assert_eq!(i64::WIDTH, 64); assert_eq!(i64::LOG_WIDTH, 6); assert_eq!(i64::WIDTH_MASK, 0x3f); assert_eq!(i128::WIDTH, 128); assert_eq!(i128::LOG_WIDTH, 7); assert_eq!(i128::WIDTH_MASK, 0x7f); } #[test] fn test_other_float_constants() { assert_eq!(f32::WIDTH, 32); assert_eq!(f32::EXPONENT_WIDTH, 8); assert_eq!(f32::MANTISSA_WIDTH, 23); assert_eq!(f32::MIN_NORMAL_EXPONENT, -126); assert_eq!(f32::MIN_EXPONENT, -149); assert_eq!(f32::MAX_EXPONENT, 127); assert_eq!(NiceFloat(f32::MIN_POSITIVE_SUBNORMAL), NiceFloat(1.0e-45)); assert_eq!(NiceFloat(f32::MAX_SUBNORMAL), NiceFloat(1.1754942e-38)); assert_eq!( NiceFloat(f32::MIN_POSITIVE_NORMAL), NiceFloat(1.1754944e-38) ); assert_eq!(NiceFloat(f32::MAX_FINITE), NiceFloat(3.4028235e38)); assert_eq!(NiceFloat(Infinity::INFINITY), NiceFloat(f32::INFINITY)); assert_eq!( NiceFloat(f32::NEGATIVE_INFINITY), NiceFloat(f32::NEG_INFINITY) ); assert_eq!(NiceFloat(NaN::NAN), NiceFloat(f32::NAN)); assert_eq!(f32::SMALLEST_UNREPRESENTABLE_UINT, 0x1000001); assert_eq!(f32::LARGEST_ORDERED_REPRESENTATION, 0xff000001); assert_eq!(f64::WIDTH, 64); assert_eq!(f64::EXPONENT_WIDTH, 11); assert_eq!(f64::MANTISSA_WIDTH, 52); assert_eq!(f64::MIN_NORMAL_EXPONENT, -1022); assert_eq!(f64::MIN_EXPONENT, -1074); assert_eq!(f64::MAX_EXPONENT, 1023); assert_eq!(NiceFloat(f64::MIN_POSITIVE_SUBNORMAL), NiceFloat(5.0e-324)); assert_eq!( NiceFloat(f64::MAX_SUBNORMAL), NiceFloat(2.225073858507201e-308) ); assert_eq!( NiceFloat(f64::MIN_POSITIVE_NORMAL), NiceFloat(2.2250738585072014e-308) ); assert_eq!( NiceFloat(f64::MAX_FINITE), NiceFloat(1.7976931348623157e308) ); assert_eq!(NiceFloat(Infinity::INFINITY), NiceFloat(f64::INFINITY)); assert_eq!( NiceFloat(f64::NEGATIVE_INFINITY), NiceFloat(f64::NEG_INFINITY) ); assert_eq!(NiceFloat(NaN::NAN), NiceFloat(f64::NAN)); assert_eq!(f32::SMALLEST_UNREPRESENTABLE_UINT, 0x1000001); assert_eq!(f64::LARGEST_ORDERED_REPRESENTATION, 0xffe0000000000001); } #[test] pub fn test_named() { fn test(out: &str) { assert_eq!(T::NAME, out); } test::("u8"); test::("u16"); test::("u32"); test::("u64"); test::("u128"); test::("usize"); test::("i8"); test::("i16"); test::("i32"); test::("i64"); test::("i128"); test::("isize"); test::("f32"); test::("f64"); } ================================================ FILE: malachite-base/tests/num/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::comparison::traits::OrdAbs; use malachite_base::test_util::generators::{signed_gen, signed_pair_gen, signed_triple_gen}; use std::cmp::Ordering::{self, *}; #[test] pub fn test_cmp_abs() { fn test(x: T, y: T, cmp: Ordering) { assert_eq!(x.cmp_abs(&y), cmp); assert_eq!(x.partial_cmp_abs(&y), Some(cmp)); assert_eq!(x.lt_abs(&y), cmp == Less); assert_eq!(x.gt_abs(&y), cmp == Greater); assert_eq!(x.le_abs(&y), cmp != Greater); assert_eq!(x.ge_abs(&y), cmp != Less); } test(123i64, 123i64, Equal); test(123i64, 456i64, Less); test(456i64, 123i64, Greater); test(123i64, -123i64, Equal); test(123i64, -456i64, Less); test(456i64, -123i64, Greater); test(-123i64, 123i64, Equal); test(-123i64, 456i64, Less); test(-456i64, 123i64, Greater); test(-123i64, -123i64, Equal); test(-123i64, -456i64, Less); test(-456i64, -123i64, Greater); } fn properties_helper_signed() where ::Output: Ord, { signed_pair_gen::().test_properties(|(x, y)| { let cmp = x.cmp_abs(&y); assert_eq!(x.unsigned_abs().cmp(&y.unsigned_abs()), cmp); if x != T::MIN { assert_eq!((-x).cmp_abs(&y), cmp); } if y != T::MIN { assert_eq!(x.cmp_abs(&-y), cmp); } assert_eq!(x.partial_cmp_abs(&y), Some(cmp)); assert_eq!(x.lt_abs(&y), cmp == Less); assert_eq!(x.gt_abs(&y), cmp == Greater); assert_eq!(x.le_abs(&y), cmp != Greater); assert_eq!(x.ge_abs(&y), cmp != Less); assert_eq!(y.cmp_abs(&x), cmp.reverse()); }); signed_gen::().test_properties(|x| { assert_eq!(x.cmp_abs(&x), Equal); assert!(x.le_abs(&x)); assert!(x.ge_abs(&x)); assert!(!x.lt_abs(&x)); assert!(!x.gt_abs(&x)); assert!(x.le_abs(&T::MIN)); assert!(x.ge_abs(&T::ZERO)); }); signed_triple_gen::().test_properties(|(x, y, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); } #[test] fn ord_abs_properties() { apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::generators::{ primitive_float_gen_var_11, primitive_float_pair_gen, primitive_float_triple_gen, signed_gen, signed_pair_gen, signed_triple_gen, }; #[test] pub fn test_eq_abs() { fn test(x: T, y: T, eq: bool) { assert_eq!(x.eq_abs(&y), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(y.ne_abs(&x), !eq); } test(123i64, 123i64, true); test(123i64, 456i64, false); test(123i64, -123i64, true); test(123i64, -456i64, false); test(-123i64, 123i64, true); test(-123i64, 456i64, false); test(-123i64, -123i64, true); test(-123i64, -456i64, false); test(123.0, 123.0, true); test(123.0, 456.0, false); test(123.0, -123.0, true); test(123.0, -456.0, false); test(-123.0, 123.0, true); test(-123.0, 456.0, false); test(-123.0, -123.0, true); test(-123.0, -456.0, false); test(123.0, f64::NAN, false); test(f64::NAN, f64::NAN, false); test(123.0, f64::INFINITY, false); test(123.0, f64::NEGATIVE_INFINITY, false); test(f64::INFINITY, f64::INFINITY, true); test(f64::INFINITY, f64::NEGATIVE_INFINITY, true); test(f64::NEGATIVE_INFINITY, f64::INFINITY, true); test(f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, true); test(123.0, 0.0, false); test(123.0, -0.0, false); test(0.0, 0.0, true); test(0.0, -0.0, true); test(-0.0, 0.0, true); test(-0.0, -0.0, true); } fn properties_helper_signed() where ::Output: Eq, { signed_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.unsigned_abs().eq(&y.unsigned_abs()), eq); if x != T::MIN { assert_eq!((-x).eq_abs(&y), eq); } if y != T::MIN { assert_eq!(x.eq_abs(&-y), eq); } assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.ne_abs(&y), !eq); }); signed_gen::().test_properties(|x| { assert!(x.eq_abs(&x)); assert!(!x.ne_abs(&x)); }); signed_triple_gen::().test_properties(|(x, y, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); } fn properties_helper_primitive_float() { primitive_float_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.abs().eq(&y.abs()), eq); assert_eq!((-x).eq_abs(&y), eq); assert_eq!(x.eq_abs(&-y), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.ne_abs(&y), !eq); }); primitive_float_gen_var_11::().test_properties(|x| { assert!(x.eq_abs(&x)); assert!(!x.ne_abs(&x)); }); primitive_float_triple_gen::().test_properties(|(x, y, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); } #[test] fn eq_abs_properties() { apply_fn_to_signeds!(properties_helper_signed); apply_fn_to_primitive_floats!(properties_helper_primitive_float); } ================================================ FILE: malachite-base/tests/num/conversion/digits/general_digits/from_digits.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{Digits, SaturatingFrom}; use malachite_base::slices::{slice_leading_zeros, slice_trailing_zeros}; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_10, unsigned_vec_unsigned_pair_gen_var_7, unsigned_vec_unsigned_pair_gen_var_8, unsigned_vec_unsigned_pair_gen_var_9, }; use std::panic::catch_unwind; #[test] pub fn test_from_digits_asc() { fn test_ok + PrimitiveUnsigned, U: PrimitiveUnsigned>( base: U, digits: &[U], out: T, ) { assert_eq!(T::from_digits_asc(&base, digits.iter().copied()), Some(out)); } test_ok::(64, &[], 0); test_ok::(64, &[0, 0, 0], 0); test_ok::(64, &[2], 2); test_ok::(8, &[3, 7, 1], 123); test_ok::(256, &[64, 66, 15], 1000000); test_ok::(256, &[64, 66, 15], 1000000); test_ok::(2, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1], 1000); test_ok::(3, &[], 0); test_ok::(3, &[2], 2); test_ok::(3, &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2], 123456); test_ok::(10, &[6, 5, 4, 3, 2, 1], 123456); test_ok::(100, &[56, 34, 12], 123456); test_ok::(123, &[87, 19, 8], 123456); test_ok::(123, &[87, 19, 8, 0, 0, 0], 123456); fn test_err + PrimitiveUnsigned, U: PrimitiveUnsigned>(base: U, digits: &[U]) { assert_eq!(T::from_digits_asc(&base, digits.iter().copied()), None); } test_err::(64, &[1; 1000]); test_err::(2, &[2]); test_err::(1000, &[1, 2, 3]); } fn from_digits_asc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() { assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_digits_asc(&U::ZERO, digits.iter().copied()); }); assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_digits_asc(&U::ONE, digits.iter().copied()); }); } #[test] pub fn test_from_digits_desc() { fn test_ok + PrimitiveUnsigned, U: PrimitiveUnsigned>( base: U, digits: &[U], out: T, ) { assert_eq!( T::from_digits_desc(&base, digits.iter().copied()), Some(out) ); } test_ok::(64, &[], 0); test_ok::(64, &[0, 0, 0], 0); test_ok::(64, &[2], 2); test_ok::(8, &[1, 7, 3], 123); test_ok::(256, &[15, 66, 64], 1000000); test_ok::(256, &[15, 66, 64], 1000000); test_ok::(2, &[1, 1, 1, 1, 1, 0, 1, 0, 0, 0], 1000); test_ok::(3, &[], 0); test_ok::(3, &[2], 2); test_ok::(3, &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 123456); test_ok::(10, &[1, 2, 3, 4, 5, 6], 123456); test_ok::(100, &[12, 34, 56], 123456); test_ok::(123, &[8, 19, 87], 123456); test_ok::(123, &[0, 0, 0, 8, 19, 87], 123456); fn test_err + PrimitiveUnsigned, U: PrimitiveUnsigned>(base: U, digits: &[U]) { assert_eq!(T::from_digits_desc(&base, digits.iter().copied()), None); } test_err::(64, &[1; 1000]); test_err::(2, &[2]); test_err::(1000, &[1, 2, 3]); } fn from_digits_desc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() { assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_digits_desc(&U::ZERO, digits.iter().copied()); }); assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_digits_desc(&U::ONE, digits.iter().copied()); }); } #[test] fn from_digits_asc_fail() { apply_fn_to_unsigneds_and_unsigneds!(from_digits_asc_fail_helper); } #[test] fn from_digits_desc_fail() { apply_fn_to_unsigneds_and_unsigneds!(from_digits_desc_fail_helper); } fn from_digits_asc_helper< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() { unsigned_vec_unsigned_pair_gen_var_9::().test_properties(|(digits, base)| { T::from_digits_asc(&base, digits.iter().copied()); }); unsigned_vec_unsigned_pair_gen_var_8::().test_properties(|(digits, base)| { let n = T::from_digits_asc(&base, digits.iter().copied()).unwrap(); assert_eq!( T::from_digits_desc(&base, digits.iter().rev().copied()).unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); assert_eq!( Digits::::to_digits_asc(&n, &base), &digits[..digits.len() - trailing_zeros] ); }); unsigned_pair_gen_var_10::().test_properties(|(base, u)| { assert_eq!( T::from_digits_asc(&base, repeat_n(U::ZERO, u)).unwrap(), T::ZERO ); }); } #[test] fn from_digits_asc_properties() { apply_fn_to_unsigneds_and_unsigneds!(from_digits_asc_helper); } fn from_digits_desc_helper< T: Digits + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() { unsigned_vec_unsigned_pair_gen_var_9::().test_properties(|(digits, base)| { T::from_digits_asc(&base, digits.iter().copied()); }); unsigned_vec_unsigned_pair_gen_var_7::().test_properties(|(digits, base)| { let n = T::from_digits_desc(&base, digits.iter().copied()).unwrap(); assert_eq!( T::from_digits_asc(&base, digits.iter().rev().copied()).unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); assert_eq!( Digits::::to_digits_desc(&n, &base), &digits[leading_zeros..] ); }); unsigned_pair_gen_var_10::().test_properties(|(base, u)| { assert_eq!( T::from_digits_desc(&base, repeat_n(U::ZERO, u)).unwrap(), T::ZERO ); }); } #[test] fn from_digits_desc_properties() { apply_fn_to_unsigneds_and_unsigneds!(from_digits_desc_helper); } ================================================ FILE: malachite-base/tests/num/conversion/digits/general_digits/to_digits.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::digits::general_digits::unsigned_to_digits_asc_naive; use malachite_base::num::conversion::traits::{Digits, ExactFrom, SaturatingFrom, WrappingFrom}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_4, unsigned_pair_gen_var_6, }; use std::panic::catch_unwind; #[test] pub fn test_to_digits_asc() { fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>(x: T, base: U, out: &[U]) { assert_eq!(x.to_digits_asc(&base), out); } test::(0, 64, &[]); test::(2, 64, &[2]); test::(123, 8, &[3, 7, 1]); test::(1000000, 256, &[64, 66, 15]); test::(1000000, 256, &[64, 66, 15]); test::(1000, 2, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1]); test::(0, 3, &[]); test::(2, 3, &[2]); test::(123456, 3, &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2]); test::(123456, 10, &[6, 5, 4, 3, 2, 1]); test::(123456, 100, &[56, 34, 12]); test::(123456, 123, &[87, 19, 8]); } fn to_digits_asc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() { assert_panic!(T::exact_from(100).to_digits_asc(&U::ZERO)); assert_panic!(T::exact_from(100).to_digits_asc(&U::ONE)); if T::WIDTH < U::WIDTH { assert_panic!(T::exact_from(100).to_digits_asc(&U::power_of_2(T::WIDTH))); } } #[test] fn to_digits_asc_fail() { apply_fn_to_unsigneds_and_unsigneds!(to_digits_asc_fail_helper); } #[test] pub fn test_to_digits_desc() { fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>(x: T, base: U, out: &[U]) { assert_eq!(x.to_digits_desc(&base), out); } test::(0, 64, &[]); test::(2, 64, &[2]); test::(123, 8, &[1, 7, 3]); test::(1000000, 256, &[15, 66, 64]); test::(1000000, 256, &[15, 66, 64]); test::(1000, 2, &[1, 1, 1, 1, 1, 0, 1, 0, 0, 0]); test::(0, 3, &[]); test::(2, 3, &[2]); test::(123456, 3, &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0]); test::(123456, 10, &[1, 2, 3, 4, 5, 6]); test::(123456, 100, &[12, 34, 56]); test::(123456, 123, &[8, 19, 87]); } fn to_digits_desc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() { assert_panic!(T::exact_from(100).to_digits_desc(&U::ZERO)); assert_panic!(T::exact_from(100).to_digits_desc(&U::ONE)); if T::WIDTH < U::WIDTH { assert_panic!(T::exact_from(100).to_digits_desc(&U::power_of_2(T::WIDTH))); } } #[test] fn to_digits_desc_fail() { apply_fn_to_unsigneds_and_unsigneds!(to_digits_desc_fail_helper); } fn to_digits_asc_helper< T: Digits + ExactFrom + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom + WrappingFrom, >() { unsigned_pair_gen_var_6::().test_properties(|(u, base)| { let digits = u.to_digits_asc(&base); assert_eq!(unsigned_to_digits_asc_naive(&u, base), digits); assert_eq!( T::from_digits_asc(&base, digits.iter().copied()).unwrap(), u ); if u != T::ZERO { assert_ne!(*digits.last().unwrap(), U::ZERO); } assert_eq!( digits.iter().copied().rev().collect_vec(), u.to_digits_desc(&base) ); if u != T::ZERO { assert_eq!( u64::exact_from(digits.len()), u.floor_log_base(T::exact_from(base)) + 1 ); } assert!(digits.iter().all(|&digit| digit <= base)); }); unsigned_gen::().test_properties(|u| { assert_eq!( u.to_digits_asc(&U::TWO) .into_iter() .map(|digit| digit == U::ONE) .collect_vec(), u.to_bits_asc() ); }); unsigned_gen_var_4::().test_properties(|base| { assert!(T::ZERO.to_digits_asc(&base).is_empty()); }); } #[test] fn to_digits_asc_properties() { apply_fn_to_unsigneds_and_unsigneds!(to_digits_asc_helper); } fn to_digits_desc_helper< T: Digits + ExactFrom + PrimitiveUnsigned, U: PrimitiveUnsigned + SaturatingFrom, >() { unsigned_pair_gen_var_6::().test_properties(|(u, base)| { let digits = u.to_digits_desc(&base); assert_eq!( T::from_digits_desc(&base, digits.iter().copied()).unwrap(), u ); if u != T::ZERO { assert_ne!(digits[0], U::ZERO); } assert_eq!( digits.iter().copied().rev().collect_vec(), u.to_digits_asc(&base) ); if u != T::ZERO { assert_eq!( u64::exact_from(digits.len()), u.floor_log_base(T::exact_from(base)) + 1 ); } assert!(digits.iter().all(|&digit| digit <= base)); }); unsigned_gen::().test_properties(|u| { assert_eq!( u.to_digits_desc(&U::TWO) .into_iter() .map(|digit| digit == U::ONE) .collect_vec(), u.to_bits_desc() ); }); unsigned_gen_var_4::().test_properties(|base| { assert!(T::ZERO.to_digits_desc(&base).is_empty()); }); } #[test] fn to_digits_desc_properties() { apply_fn_to_unsigneds_and_unsigneds!(to_digits_desc_helper); } ================================================ FILE: malachite-base/tests/num/conversion/digits/power_of_2_digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::slices::{slice_leading_zeros, slice_trailing_zeros}; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_5, unsigned_vec_unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_3, unsigned_vec_unsigned_pair_gen_var_6, }; use std::panic::catch_unwind; #[test] pub fn test_from_power_of_2_digits_asc() { fn test_ok + PrimitiveUnsigned, U: PrimitiveUnsigned>( log_base: u64, digits: &[U], out: T, ) { assert_eq!( T::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(), out ); } test_ok::(6, &[], 0); test_ok::(6, &[2], 2); test_ok::(3, &[3, 7, 1], 123); test_ok::(8, &[64, 66, 15], 1000000); test_ok::(8, &[64, 66, 15], 1000000); test_ok::(1, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1], 1000); fn test_err + PrimitiveUnsigned, U: PrimitiveUnsigned>( log_base: u64, digits: &[U], ) { assert_eq!( T::from_power_of_2_digits_asc(log_base, digits.iter().copied()), None ); } test_err::(4, &[1; 100]); test_err::(1, &[2]); } fn from_power_of_2_digits_asc_fail_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_power_of_2_digits_asc(U::WIDTH + 1, digits.iter().copied()); }); assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_power_of_2_digits_asc(0, digits.iter().copied()); }); } #[test] fn from_power_of_2_digits_asc_fail() { apply_fn_to_unsigneds_and_unsigneds!(from_power_of_2_digits_asc_fail_helper); } #[test] pub fn test_from_power_of_2_digits_desc() { fn test_ok + PrimitiveUnsigned, U: PrimitiveUnsigned>( log_base: u64, digits: &[U], out: T, ) { assert_eq!( T::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(), out ); } test_ok::(6, &[], 0); test_ok::(6, &[2], 2); test_ok::(3, &[1, 7, 3], 123); test_ok::(8, &[15, 66, 64], 1000000); test_ok::(8, &[15, 66, 64], 1000000); test_ok::(1, &[1, 1, 1, 1, 1, 0, 1, 0, 0, 0], 1000); fn test_err + PrimitiveUnsigned, U: PrimitiveUnsigned>( log_base: u64, digits: &[U], ) { assert_eq!( T::from_power_of_2_digits_desc(log_base, digits.iter().copied()), None ); } test_err::(4, &[1; 100]); test_err::(1, &[2]); } fn from_power_of_2_digits_desc_fail_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_power_of_2_digits_desc(U::WIDTH + 1, digits.iter().copied()); }); assert_panic!({ let digits: &[U] = &[U::ONE]; T::from_power_of_2_digits_desc(0, digits.iter().copied()); }); } #[test] fn from_power_of_2_digits_desc_fail() { apply_fn_to_unsigneds_and_unsigneds!(from_power_of_2_digits_desc_fail_helper); } fn from_power_of_2_digits_asc_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_vec_unsigned_pair_gen_var_6::().test_properties(|(digits, log_base)| { T::from_power_of_2_digits_asc(log_base, digits.iter().copied()); }); unsigned_vec_unsigned_pair_gen_var_2::().test_properties(|(digits, log_base)| { let n = T::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(); assert_eq!( T::from_power_of_2_digits_desc(log_base, digits.iter().rev().copied()).unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base), &digits[..digits.len() - trailing_zeros] ); }); unsigned_pair_gen_var_5::().test_properties(|(u, log_base)| { assert_eq!( T::from_power_of_2_digits_asc(log_base, repeat_n(U::ZERO, u)).unwrap(), T::ZERO ); }); } #[test] fn from_power_of_2_digits_asc_properties() { apply_fn_to_unsigneds_and_unsigneds!(from_power_of_2_digits_asc_helper); } fn from_power_of_2_digits_desc_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_vec_unsigned_pair_gen_var_6::().test_properties(|(digits, log_base)| { T::from_power_of_2_digits_desc(log_base, digits.iter().copied()); }); unsigned_vec_unsigned_pair_gen_var_3::().test_properties(|(digits, log_base)| { let n = T::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(); assert_eq!( T::from_power_of_2_digits_asc(log_base, digits.iter().rev().copied()).unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base), &digits[leading_zeros..] ); }); unsigned_pair_gen_var_5::().test_properties(|(u, log_base)| { assert_eq!( T::from_power_of_2_digits_desc(log_base, repeat_n(U::ZERO, u)).unwrap(), T::ZERO ); }); } #[test] fn from_power_of_2_digits_desc_properties() { apply_fn_to_unsigneds_and_unsigneds!(from_power_of_2_digits_desc_helper); } ================================================ FILE: malachite-base/tests/num/conversion/digits/power_of_2_digits/power_of_2_digit_iterable.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivRound; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, PowerOf2Digits, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::common::test_double_ended_iterator_size_hint; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_4, unsigned_pair_gen_var_5, unsigned_triple_gen_var_3, unsigned_unsigned_bool_vec_triple_gen_var_1, }; use std::panic::catch_unwind; #[test] pub fn test_power_of_2_digits() { assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&107u32, 2), &[3, 2, 2, 1] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(107u32, 2); assert_eq!(digits.next(), Some(3)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(2)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 3); assert_eq!(digits.get_digit(1), 2); assert_eq!(digits.get_digit(2), 2); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 0); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(107u32, 2); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), Some(3)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(0u8, 5); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&105u32, 1), &[1, 0, 0, 1, 0, 1, 1] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(105u32, 1); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 1); assert_eq!(digits.get_digit(1), 0); assert_eq!(digits.get_digit(2), 0); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 1); assert_eq!(digits.get_digit(6), 1); assert_eq!(digits.get_digit(7), 0); assert_eq!(digits.get_digit(8), 0); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(105u32, 1); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(0)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); } fn power_of_2_digits_fail_helper< T: PowerOf2DigitIterable + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { assert_panic!(PowerOf2DigitIterable::::power_of_2_digits( T::exact_from(107), 0 )); assert_panic!(PowerOf2DigitIterable::::power_of_2_digits( T::exact_from(107), 200 )); } #[test] fn power_of_2_digits_fail() { apply_fn_to_unsigneds_and_unsigneds!(power_of_2_digits_fail_helper); } fn power_of_2_digit_iterable_helper< T: PowerOf2DigitIterable + PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() where >::PowerOf2DigitIterator: Clone, { unsigned_pair_gen_var_4::().test_properties(|(u, log_base)| { test_double_ended_iterator_size_hint( PowerOf2DigitIterable::::power_of_2_digits(u, log_base), usize::exact_from(u.significant_bits().div_round(log_base, Ceiling).0), ); }); unsigned_unsigned_bool_vec_triple_gen_var_1::().test_properties( |(u, log_base, ref bs)| { let mut digits = PowerOf2DigitIterable::::power_of_2_digits(u, log_base); let mut digit_vec = Vec::new(); let mut i = 0; for &b in bs { if b { digit_vec.insert(i, digits.next().unwrap()); i += 1; } else { digit_vec.insert(i, digits.next_back().unwrap()); } } assert!(digits.next().is_none()); assert!(digits.next_back().is_none()); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&u, log_base), digit_vec ); }, ); unsigned_triple_gen_var_3::().test_properties(|(u, log_base, i)| { let digits = PowerOf2DigitIterable::::power_of_2_digits(u, log_base); if i < u.significant_bits().div_round(log_base, Ceiling).0 { assert_eq!( digits.get_digit(i), PowerOf2Digits::::to_power_of_2_digits_asc(&u, log_base)[usize::exact_from(i)] ); } else { assert_eq!(digits.get_digit(i), U::ZERO); } }); unsigned_pair_gen_var_5::().test_properties(|(i, log_base)| { let digits = PowerOf2DigitIterable::::power_of_2_digits(T::ZERO, log_base); assert_eq!(digits.get_digit(i), U::ZERO); }); } #[test] fn power_of_2_digit_iterable_properties() { apply_fn_to_unsigneds_and_unsigneds!(power_of_2_digit_iterable_helper); } ================================================ FILE: malachite-base/tests/num/conversion/digits/power_of_2_digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::DivRound; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, PowerOf2Digits}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_3, unsigned_pair_gen_var_4, }; use std::panic::catch_unwind; #[test] pub fn test_to_power_of_2_digits_asc() { fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>( x: T, log_base: u64, out: &[U], ) { assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&x, log_base), out ); } test::(0, 6, &[]); test::(2, 6, &[2]); test::(123, 3, &[3, 7, 1]); test::(1000000, 8, &[64, 66, 15]); test::(1000000, 8, &[64, 66, 15]); test::(1000, 1, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1]); } fn to_power_of_2_digits_asc_fail_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { assert_panic!(PowerOf2Digits::::to_power_of_2_digits_asc( &T::exact_from(100), U::WIDTH + 1 )); assert_panic!(PowerOf2Digits::::to_power_of_2_digits_asc( &T::exact_from(100), 0 )); } #[test] fn to_power_of_2_digits_asc_fail() { apply_fn_to_unsigneds_and_unsigneds!(to_power_of_2_digits_asc_fail_helper); } #[test] pub fn test_to_power_of_2_digits_desc() { fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>( x: T, log_base: u64, out: &[U], ) { assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&x, log_base), out ); } test::(0, 6, &[]); test::(2, 6, &[2]); test::(123, 3, &[1, 7, 3]); test::(1000000, 8, &[15, 66, 64]); test::(1000000, 8, &[15, 66, 64]); test::(1000, 1, &[1, 1, 1, 1, 1, 0, 1, 0, 0, 0]); } fn to_power_of_2_digits_desc_fail_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { assert_panic!(PowerOf2Digits::::to_power_of_2_digits_desc( &T::exact_from(100), U::WIDTH + 1 )); assert_panic!(PowerOf2Digits::::to_power_of_2_digits_desc( &T::exact_from(100), 0 )); } #[test] fn to_power_of_2_digits_desc_fail() { apply_fn_to_unsigneds_and_unsigneds!(to_power_of_2_digits_desc_fail_helper); } fn to_power_of_2_digits_asc_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_pair_gen_var_4::().test_properties(|(u, log_base)| { let digits = PowerOf2Digits::::to_power_of_2_digits_asc(&u, log_base); assert_eq!( T::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(), u ); if u != T::ZERO { assert_ne!(*digits.last().unwrap(), U::ZERO); } assert_eq!( digits.iter().copied().rev().collect_vec(), u.to_power_of_2_digits_desc(log_base) ); if u != T::ZERO { assert_eq!( u64::exact_from(digits.len()), u.floor_log_base_power_of_2(log_base) + 1 ); } assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); }); unsigned_gen::().test_properties(|u| { assert_eq!( u.to_power_of_2_digits_asc(1) .into_iter() .map(|digit: U| digit == U::ONE) .collect_vec(), u.to_bits_asc() ); }); unsigned_gen_var_3::().test_properties(|log_base| { assert!(PowerOf2Digits::::to_power_of_2_digits_asc(&T::ZERO, log_base).is_empty()); }); } #[test] fn to_power_of_2_digits_asc_properties() { apply_fn_to_unsigneds_and_unsigneds!(to_power_of_2_digits_asc_helper); } fn to_power_of_2_digits_desc_helper< T: PowerOf2Digits + PrimitiveUnsigned, U: PrimitiveUnsigned, >() { unsigned_pair_gen_var_4::().test_properties(|(u, log_base)| { let digits = PowerOf2Digits::::to_power_of_2_digits_desc(&u, log_base); assert_eq!( T::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(), u ); if u != T::ZERO { assert_ne!(digits[0], U::ZERO); } if u != T::ZERO { assert_eq!( u64::exact_from(digits.len()), u.floor_log_base_power_of_2(log_base) + 1 ); } assert_eq!( digits.len(), usize::exact_from(u.significant_bits().div_round(log_base, Ceiling).0) ); assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); }); unsigned_gen::().test_properties(|u| { assert_eq!( u.to_power_of_2_digits_desc(1) .into_iter() .map(|digit: U| digit == U::ONE) .collect_vec(), u.to_bits_desc() ); }); unsigned_gen_var_3::().test_properties(|log_base| { assert!(PowerOf2Digits::::to_power_of_2_digits_desc(&T::ZERO, log_base).is_empty()); }); } #[test] fn to_power_of_2_digits_desc_properties() { apply_fn_to_unsigneds_and_unsigneds!(to_power_of_2_digits_desc_helper); } ================================================ FILE: malachite-base/tests/num/conversion/froms/convertible_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; use std::fmt::Debug; #[test] pub fn test_convertible_from() { fn test_single + Copy + Debug>(n: T) { assert!(T::convertible_from(n)); } test_single(0u8); test_single(5u64); test_single(1000u32); test_single(123u8); test_single(-123i16); test_single(i64::MIN); test_single(usize::MAX); fn test_double>(n_in: T, convertible: bool) { assert_eq!(U::convertible_from(n_in), convertible); } test_double::<_, u16>(0u8, true); test_double::<_, i32>(1000u16, true); test_double::<_, i8>(-5i16, true); test_double::<_, u64>(255u8, true); test_double::<_, u32>(-1i8, false); test_double::<_, u16>(u32::MAX, false); test_double::<_, u32>(i32::MIN, false); test_double::<_, u16>(i32::MIN, false); test_double::<_, i16>(i32::MIN, false); test_double::<_, u32>(-5i32, false); test_double::<_, i32>(3000000000u32, false); test_double::<_, i8>(-1000i16, false); test_double::<_, u8>(0.0f32, true); test_double::<_, u8>(-0.0f32, true); test_double::<_, u8>(123.0f32, true); test_double::<_, i8>(-123.0f32, true); test_double::<_, u8>(-123.0f32, false); test_double::<_, u8>(500.0f32, false); test_double::<_, u8>(123.1f32, false); test_double::<_, u8>(f32::NAN, false); test_double::<_, u8>(f32::INFINITY, false); test_double::<_, u8>(f32::NEGATIVE_INFINITY, false); test_double::<_, u8>(255.0f32, true); test_double::<_, u8>(256.0f32, false); test_double::<_, i8>(127.0f32, true); test_double::<_, i8>(128.0f32, false); test_double::<_, i8>(-128.0f32, true); test_double::<_, i8>(-129.0f32, false); test_double::<_, f32>(0u8, true); test_double::<_, f32>(123u8, true); test_double::<_, f32>(-123i8, true); test_double::<_, f32>(u128::MAX, false); test_double::<_, f32>(i128::MIN, true); test_double::<_, f32>(i128::MIN + 1, false); test_double::<_, f32>(u32::MAX, false); test_double::<_, f32>(i32::MIN, true); test_double::<_, f32>(i32::MIN + 1, false); } fn convertible_from_helper_primitive_int_unsigned< T: TryFrom + ConvertibleFrom + PrimitiveInt, U: PrimitiveUnsigned, >() { unsigned_gen::().test_properties(|u| { let convertible = T::convertible_from(u); assert_eq!(convertible, T::try_from(u).is_ok()); }); } fn convertible_from_helper_primitive_int_signed< T: TryFrom + ConvertibleFrom + PrimitiveInt, U: PrimitiveSigned, >() { signed_gen::().test_properties(|i| { let convertible = T::convertible_from(i); assert_eq!(convertible, T::try_from(i).is_ok()); }); } fn convertible_from_helper_primitive_int_primitive_float< T: TryFrom> + ConvertibleFrom + PrimitiveInt, U: PrimitiveFloat, >() { primitive_float_gen::().test_properties(|f| { let convertible = T::convertible_from(f); assert_eq!(convertible, T::try_from(NiceFloat(f)).is_ok()); }); } fn convertible_from_helper_primitive_float_unsigned< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveUnsigned, >() where NiceFloat: TryFrom, { unsigned_gen::().test_properties(|u| { let convertible = T::convertible_from(u); assert_eq!(convertible, NiceFloat::::try_from(u).is_ok()); }); } fn convertible_from_helper_primitive_float_signed< T: ConvertibleFrom + PrimitiveFloat, U: PrimitiveSigned, >() where NiceFloat: TryFrom, { signed_gen::().test_properties(|i| { let convertible = T::convertible_from(i); assert_eq!(convertible, NiceFloat::::try_from(i).is_ok()); }); } #[test] fn convertible_from_properties() { apply_fn_to_primitive_ints_and_unsigneds!(convertible_from_helper_primitive_int_unsigned); apply_fn_to_primitive_ints_and_signeds!(convertible_from_helper_primitive_int_signed); apply_fn_to_primitive_ints_and_primitive_floats!( convertible_from_helper_primitive_int_primitive_float ); apply_fn_to_primitive_floats_and_unsigneds!(convertible_from_helper_primitive_float_unsigned); apply_fn_to_primitive_floats_and_signeds!(convertible_from_helper_primitive_float_signed); } ================================================ FILE: malachite-base/tests/num/conversion/froms/from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ FromOtherTypeSlice, JoinHalves, SplitInHalf, VecFromOtherType, VecFromOtherTypeSlice, }; use std::fmt::Debug; fn split_in_half_helper(n: T, out: (T::Half, T::Half)) where T::Half: PrimitiveUnsigned, { assert_eq!(n.split_in_half(), out); } #[test] pub fn test_split_in_half() { split_in_half_helper(0u64, (0u32, 0u32)); split_in_half_helper(1u64, (0u32, 1u32)); split_in_half_helper(u16::from(u8::MAX), (0, u8::MAX)); split_in_half_helper(u16::from(u8::MAX) + 1, (1, 0)); split_in_half_helper(u16::MAX, (u8::MAX, u8::MAX)); split_in_half_helper(258u16, (1u8, 2u8)); split_in_half_helper(0xabcd1234u32, (0xabcd, 0x1234)); } fn lower_half_helper(n: T, out: T::Half) where T::Half: PrimitiveUnsigned, { assert_eq!(n.lower_half(), out); } #[test] pub fn test_lower_half() { lower_half_helper(0u64, 0u32); lower_half_helper(1u64, 1u32); lower_half_helper(u16::from(u8::MAX), u8::MAX); lower_half_helper(u16::from(u8::MAX) + 1, 0); lower_half_helper(u16::MAX, u8::MAX); lower_half_helper(258u16, 2u8); lower_half_helper(0xabcd1234u32, 0x1234); } fn upper_half_helper(n: T, out: T::Half) where T::Half: PrimitiveUnsigned, { assert_eq!(n.upper_half(), out); } #[test] pub fn test_upper_half() { upper_half_helper(0u64, 0u32); upper_half_helper(1u64, 0u32); upper_half_helper(u16::from(u8::MAX), 0); upper_half_helper(u16::from(u8::MAX) + 1, 1); upper_half_helper(u16::MAX, u8::MAX); upper_half_helper(258u16, 1u8); upper_half_helper(0xabcd1234u32, 0xabcd); } fn join_halves_helper(upper: T::Half, lower: T::Half, out: T) { assert_eq!(T::join_halves(upper, lower), out); } #[test] pub fn test_join_halves() { join_halves_helper(0u32, 0u32, 0u64); join_halves_helper(0u32, 1u32, 1u64); join_halves_helper(0, u8::MAX, u16::from(u8::MAX)); join_halves_helper(1, 0, u16::from(u8::MAX) + 1); join_halves_helper(u8::MAX, u8::MAX, u16::MAX); join_halves_helper(1, 2, 258u16); join_halves_helper(0xabcd, 0x1234, 0xabcd1234u32); } #[test] pub fn test_from_other_type_slice() { fn test>(slice: &[T], n: U) { assert_eq!(U::from_other_type_slice(slice), n); } test::(&[], 0); test::(&[123], 123); test::(&[123, 456], 123); test::(&[0xab], 0xab); test::(&[0xab, 0xcd], 0xcdab); test::(&[0xab, 0xcd, 0xef], 0xcdab); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67], 0x67452301efcdab, ); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xff], 0x8967452301efcdab, ); test::(&[], 0); test::(&[0xabcd, 0xef01], 0xcd); test::(&[0x1234567890a9cdef012345678909bcde], 0xde); } #[test] pub fn test_vec_from_other_type_slice() { fn test>(slice: &[T], vec: &[U]) { assert_eq!(U::vec_from_other_type_slice(slice), vec); } test::(&[123, 456], &[123, 456]); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xff], &[0xcdab, 0x01ef, 0x4523, 0x8967, 0xff], ); test::(&[0xab], &[0xab]); test::( &[0xcdab, 0x01ef, 0x4523, 0x8967], &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89], ); } #[test] pub fn test_vec_from_other_type() { fn test>(value: T, vec: &[U]) { assert_eq!(U::vec_from_other_type(value), vec); } test::(123, &[123]); test::(0xab, &[0xab]); test::(0xcdab, &[0xab, 0xcd]); } ================================================ FILE: malachite-base/tests/num/conversion/froms/overflowing_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, OverflowingFrom, WrappingFrom}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use std::fmt::Debug; #[test] pub fn test_overflowing_from() { fn test_single>(n: T) { assert_eq!(T::overflowing_from(n), (n, false)); } test_single(0u8); test_single(5u64); test_single(1000u32); test_single(123u8); test_single(-123i16); test_single(i64::MIN); test_single(usize::MAX); fn test_double>(n_in: T, n_out: (U, bool)) { assert_eq!(U::overflowing_from(n_in), n_out); } test_double(0u8, (0u16, false)); test_double(1000u16, (1000i32, false)); test_double(-5i16, (-5i8, false)); test_double(255u8, (255u64, false)); test_double(-1i8, (u32::MAX, true)); test_double(u32::MAX, (u16::MAX, true)); test_double(i32::MIN, (0x80000000u32, true)); test_double(i32::MIN, (0u16, true)); test_double(i32::MIN, (0i16, true)); test_double(-5i32, (0xfffffffbu32, true)); test_double(3000000000u32, (-1294967296i32, true)); test_double(-1000i16, (24i8, true)); } fn overflowing_from_helper_primitive_int_unsigned< T: ConvertibleFrom + OverflowingFrom + WrappingFrom + PrimitiveInt, U: PrimitiveUnsigned, >() { unsigned_gen::().test_properties(|u| { let result = T::overflowing_from(u); assert_eq!(result, (T::wrapping_from(u), !T::convertible_from(u))); }); } fn overflowing_from_helper_primitive_int_signed< T: ConvertibleFrom + OverflowingFrom + WrappingFrom + PrimitiveInt, U: PrimitiveSigned, >() { signed_gen::().test_properties(|i| { let result = T::overflowing_from(i); assert_eq!(result, (T::wrapping_from(i), !T::convertible_from(i))); }); } #[test] fn overflowing_from_properties() { apply_fn_to_primitive_ints_and_unsigneds!(overflowing_from_helper_primitive_int_unsigned); apply_fn_to_primitive_ints_and_signeds!(overflowing_from_helper_primitive_int_signed); } ================================================ FILE: malachite-base/tests/num/conversion/froms/rounding_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ primitive_float_gen_var_13, primitive_float_gen_var_14, primitive_float_gen_var_15, primitive_float_gen_var_16, primitive_float_gen_var_17, primitive_float_rounding_mode_pair_gen_var_3, signed_gen_var_7, signed_gen_var_8, signed_gen_var_9, signed_rounding_mode_pair_gen_var_4, unsigned_gen_var_18, unsigned_gen_var_19, unsigned_gen_var_20, unsigned_rounding_mode_pair_gen_var_2, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] pub fn test_rounding_from() { fn test_from_floating_point>( n_in: T, rm: RoundingMode, n_out: U, o: Ordering, ) { assert_eq!(U::rounding_from(n_in, rm), (n_out, o)); } test_from_floating_point::(0.0, Down, 0, Equal); test_from_floating_point::(0.0, Floor, 0, Equal); test_from_floating_point::(0.0, Up, 0, Equal); test_from_floating_point::(0.0, Ceiling, 0, Equal); test_from_floating_point::(0.0, Nearest, 0, Equal); test_from_floating_point::(0.0, Exact, 0, Equal); test_from_floating_point::(-0.0, Down, 0, Equal); test_from_floating_point::(-0.0, Floor, 0, Equal); test_from_floating_point::(-0.0, Up, 0, Equal); test_from_floating_point::(-0.0, Ceiling, 0, Equal); test_from_floating_point::(-0.0, Nearest, 0, Equal); test_from_floating_point::(-0.0, Exact, 0, Equal); test_from_floating_point::(100.0, Down, 100, Equal); test_from_floating_point::(100.0, Floor, 100, Equal); test_from_floating_point::(100.0, Up, 100, Equal); test_from_floating_point::(100.0, Ceiling, 100, Equal); test_from_floating_point::(100.0, Nearest, 100, Equal); test_from_floating_point::(100.0, Exact, 100, Equal); test_from_floating_point::(100.1, Down, 100, Less); test_from_floating_point::(100.1, Floor, 100, Less); test_from_floating_point::(100.1, Up, 101, Greater); test_from_floating_point::(100.1, Ceiling, 101, Greater); test_from_floating_point::(100.1, Nearest, 100, Less); test_from_floating_point::(100.9, Down, 100, Less); test_from_floating_point::(100.9, Floor, 100, Less); test_from_floating_point::(100.9, Up, 101, Greater); test_from_floating_point::(100.9, Ceiling, 101, Greater); test_from_floating_point::(100.9, Nearest, 101, Greater); test_from_floating_point::(100.5, Down, 100, Less); test_from_floating_point::(100.5, Floor, 100, Less); test_from_floating_point::(100.5, Up, 101, Greater); test_from_floating_point::(100.5, Ceiling, 101, Greater); test_from_floating_point::(100.5, Nearest, 100, Less); test_from_floating_point::(101.5, Down, 101, Less); test_from_floating_point::(101.5, Floor, 101, Less); test_from_floating_point::(101.5, Up, 102, Greater); test_from_floating_point::(101.5, Ceiling, 102, Greater); test_from_floating_point::(101.5, Nearest, 102, Greater); test_from_floating_point::(256.0, Down, 255, Less); test_from_floating_point::(256.0, Floor, 255, Less); test_from_floating_point::(256.0, Nearest, 255, Less); test_from_floating_point::(-100.0, Down, 0, Greater); test_from_floating_point::(-100.0, Ceiling, 0, Greater); test_from_floating_point::(-100.0, Nearest, 0, Greater); test_from_floating_point::(128.0, Down, 127, Less); test_from_floating_point::(128.0, Floor, 127, Less); test_from_floating_point::(128.0, Nearest, 127, Less); test_from_floating_point::(-129.0, Down, -128, Greater); test_from_floating_point::(-129.0, Ceiling, -128, Greater); test_from_floating_point::(-129.0, Nearest, -128, Greater); test_from_floating_point::(f32::INFINITY, Down, 255, Less); test_from_floating_point::(f32::INFINITY, Floor, 255, Less); test_from_floating_point::(f32::INFINITY, Nearest, 255, Less); test_from_floating_point::(f32::NEGATIVE_INFINITY, Down, 0, Greater); test_from_floating_point::(f32::NEGATIVE_INFINITY, Ceiling, 0, Greater); test_from_floating_point::(f32::NEGATIVE_INFINITY, Nearest, 0, Greater); test_from_floating_point::(f32::INFINITY, Down, 127, Less); test_from_floating_point::(f32::INFINITY, Floor, 127, Less); test_from_floating_point::(f32::INFINITY, Nearest, 127, Less); test_from_floating_point::(f32::NEGATIVE_INFINITY, Down, -128, Greater); test_from_floating_point::(f32::NEGATIVE_INFINITY, Ceiling, -128, Greater); test_from_floating_point::(f32::NEGATIVE_INFINITY, Nearest, -128, Greater); fn test_from_primitive_int>( n_in: T, rm: RoundingMode, n_out: U, o: Ordering, ) { let (x, actual_o) = U::rounding_from(n_in, rm); assert_eq!((NiceFloat(x), actual_o), (NiceFloat(n_out), o)); } test_from_primitive_int::(0, Down, 0.0, Equal); test_from_primitive_int::(0, Floor, 0.0, Equal); test_from_primitive_int::(0, Up, 0.0, Equal); test_from_primitive_int::(0, Ceiling, 0.0, Equal); test_from_primitive_int::(0, Nearest, 0.0, Equal); test_from_primitive_int::(0, Exact, 0.0, Equal); test_from_primitive_int::(100, Down, 100.0, Equal); test_from_primitive_int::(100, Floor, 100.0, Equal); test_from_primitive_int::(100, Up, 100.0, Equal); test_from_primitive_int::(100, Ceiling, 100.0, Equal); test_from_primitive_int::(100, Nearest, 100.0, Equal); test_from_primitive_int::(100, Exact, 100.0, Equal); test_from_primitive_int::(-100, Down, -100.0, Equal); test_from_primitive_int::(-100, Floor, -100.0, Equal); test_from_primitive_int::(-100, Up, -100.0, Equal); test_from_primitive_int::(-100, Ceiling, -100.0, Equal); test_from_primitive_int::(-100, Nearest, -100.0, Equal); test_from_primitive_int::(-100, Exact, -100.0, Equal); test_from_primitive_int::(i32::MIN, Down, -2147483600.0, Equal); test_from_primitive_int::(i32::MIN, Floor, -2147483600.0, Equal); test_from_primitive_int::(i32::MIN, Up, -2147483600.0, Equal); test_from_primitive_int::(i32::MIN, Ceiling, -2147483600.0, Equal); test_from_primitive_int::(i32::MIN, Nearest, -2147483600.0, Equal); test_from_primitive_int::(i32::MIN, Exact, -2147483600.0, Equal); test_from_primitive_int::(i32::MAX, Down, 2147483500.0, Less); test_from_primitive_int::(i32::MAX, Floor, 2147483500.0, Less); test_from_primitive_int::(i32::MAX, Up, 2147483600.0, Greater); test_from_primitive_int::(i32::MAX, Ceiling, 2147483600.0, Greater); test_from_primitive_int::(i32::MAX, Nearest, 2147483600.0, Greater); test_from_primitive_int::(u128::MAX, Down, 3.4028235e38, Less); test_from_primitive_int::(u128::MAX, Floor, 3.4028235e38, Less); test_from_primitive_int::(u128::MAX, Up, f32::INFINITY, Greater); test_from_primitive_int::(u128::MAX, Ceiling, f32::INFINITY, Greater); test_from_primitive_int::(u128::MAX, Nearest, 3.4028235e38, Less); } #[test] fn exact_from_fail() { assert_panic!(u8::rounding_from(100.1f32, Exact)); assert_panic!(u8::rounding_from(256.0f32, Exact)); assert_panic!(u8::rounding_from(256.0f32, Up)); assert_panic!(u8::rounding_from(256.0f32, Ceiling)); assert_panic!(u8::rounding_from(-100.0f32, Exact)); assert_panic!(u8::rounding_from(-100.0f32, Up)); assert_panic!(u8::rounding_from(-100.0f32, Floor)); assert_panic!(i8::rounding_from(128.0f32, Exact)); assert_panic!(i8::rounding_from(128.0f32, Up)); assert_panic!(i8::rounding_from(128.0f32, Ceiling)); assert_panic!(i8::rounding_from(-129.0f32, Exact)); assert_panic!(i8::rounding_from(-129.0f32, Up)); assert_panic!(i8::rounding_from(-129.0f32, Floor)); assert_panic!(u8::rounding_from(f32::NAN, Down)); assert_panic!(u8::rounding_from(f32::NAN, Floor)); assert_panic!(u8::rounding_from(f32::NAN, Up)); assert_panic!(u8::rounding_from(f32::NAN, Ceiling)); assert_panic!(u8::rounding_from(f32::NAN, Nearest)); assert_panic!(u8::rounding_from(f32::NAN, Exact)); assert_panic!(u8::rounding_from(f32::INFINITY, Up)); assert_panic!(u8::rounding_from(f32::INFINITY, Ceiling)); assert_panic!(u8::rounding_from(f32::INFINITY, Exact)); assert_panic!(u8::rounding_from(f32::NEGATIVE_INFINITY, Up)); assert_panic!(u8::rounding_from(f32::NEGATIVE_INFINITY, Floor)); assert_panic!(u8::rounding_from(f32::NEGATIVE_INFINITY, Exact)); assert_panic!(i8::rounding_from(f32::INFINITY, Up)); assert_panic!(i8::rounding_from(f32::INFINITY, Ceiling)); assert_panic!(i8::rounding_from(f32::INFINITY, Exact)); assert_panic!(i8::rounding_from(f32::NEGATIVE_INFINITY, Up)); assert_panic!(i8::rounding_from(f32::NEGATIVE_INFINITY, Floor)); assert_panic!(i8::rounding_from(f32::NEGATIVE_INFINITY, Exact)); assert_panic!(u8::rounding_from(f32::NAN, Down)); assert_panic!(f32::rounding_from(u32::MAX, Exact)); assert_panic!(f32::rounding_from(u128::MAX, Exact)); } fn rounding_from_helper_unsigned_primitive_float< T: ConvertibleFrom + PrimitiveUnsigned + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >() where NiceFloat: TryFrom, { primitive_float_rounding_mode_pair_gen_var_3::().test_properties(|(f, rm)| { let (rounded, o) = T::rounding_from(f, rm); match (f >= U::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(T::rounding_from(f, rm), (rounded, Equal)); } } else { assert_panic!(T::rounding_from(f, Exact)); } }); primitive_float_gen_var_13::().test_properties(|f| { let no = T::rounding_from(f, Exact); assert_eq!(no, T::rounding_from(f, Floor)); assert_eq!(no, T::rounding_from(f, Ceiling)); assert_eq!(no, T::rounding_from(f, Down)); assert_eq!(no, T::rounding_from(f, Up)); assert_eq!(no, T::rounding_from(f, Nearest)); }); let f_max = U::rounding_from(T::MAX, Down).0; primitive_float_gen_var_15::().test_properties(|f| { if f >= U::ZERO && f <= f_max { let n_floor = T::rounding_from(f, Floor); assert_eq!(n_floor.1, Less); if let Some(n_ceiling) = n_floor.0.checked_add(T::ONE) { let n_ceiling = (n_ceiling, Greater); assert_eq!(n_ceiling, T::rounding_from(f, Ceiling)); assert_eq!(n_floor, T::rounding_from(f, Down)); assert_eq!(n_ceiling, T::rounding_from(f, Up)); let n_nearest = T::rounding_from(f, Nearest); assert!(n_nearest == n_floor || n_nearest == n_ceiling); } } }); primitive_float_gen_var_16::().test_properties(|f| { let floor = T::rounding_from(f, Floor); let ceiling = (floor.0 + T::ONE, Greater); let nearest = T::rounding_from(f, Nearest); assert_eq!(nearest, if floor.0.even() { floor } else { ceiling }); }); } fn rounding_from_helper_signed_primitive_float< T: ConvertibleFrom + PrimitiveSigned + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >() where NiceFloat: TryFrom, { primitive_float_rounding_mode_pair_gen_var_3::().test_properties(|(f, rm)| { let (rounded, o) = T::rounding_from(f, rm); match (f >= U::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(T::rounding_from(f, rm), (rounded, Equal)); } } else { assert_panic!(T::rounding_from(f, Exact)); } }); primitive_float_gen_var_14::().test_properties(|f| { let no = T::rounding_from(f, Exact); assert_eq!(no, T::rounding_from(f, Floor)); assert_eq!(no, T::rounding_from(f, Ceiling)); assert_eq!(no, T::rounding_from(f, Down)); assert_eq!(no, T::rounding_from(f, Up)); assert_eq!(no, T::rounding_from(f, Nearest)); }); let f_min = U::rounding_from(T::MIN, Down).0; let f_max = U::rounding_from(T::MAX, Down).0; primitive_float_gen_var_15::().test_properties(|f| { if f >= f_min && f <= f_max { let n_floor = T::rounding_from(f, Floor); if let Some(n_ceiling) = n_floor.0.checked_add(T::ONE) { let n_ceiling = (n_ceiling, Greater); assert_eq!(n_ceiling, T::rounding_from(f, Ceiling)); if f >= U::ZERO { assert_eq!(n_floor, T::rounding_from(f, Down)); assert_eq!(n_ceiling, T::rounding_from(f, Up)); } else { assert_eq!(n_ceiling, T::rounding_from(f, Down)); assert_eq!(n_floor, T::rounding_from(f, Up)); } let n_nearest = T::rounding_from(f, Nearest); assert!(n_nearest == n_floor || n_nearest == n_ceiling); } } }); primitive_float_gen_var_17::().test_properties(|f| { let floor = T::rounding_from(f, Floor); let ceiling = (floor.0 + T::ONE, Greater); let nearest = T::rounding_from(f, Nearest); assert_eq!(nearest, if floor.0.even() { floor } else { ceiling }); }); } fn rounding_from_helper_primitive_float_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: TryFrom> + PrimitiveUnsigned + RoundingFrom, >() { unsigned_rounding_mode_pair_gen_var_2::().test_properties(|(u, rm)| { let (rounded, o) = T::rounding_from(u, rm); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(T::rounding_from(u, rm), (rounded, Equal)); } } else { assert_panic!(T::rounding_from(u, Exact)); } }); unsigned_gen_var_18::().test_properties(|u| { let (f, o) = T::rounding_from(u, Exact); let (f_alt, o_alt) = T::rounding_from(u, Floor); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(u, Ceiling); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(u, Down); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(u, Up); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(u, Nearest); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); assert_eq!(U::rounding_from(f, Exact), (u, Equal)); }); if U::WIDTH > T::MANTISSA_WIDTH { unsigned_gen_var_19::().test_properties(|u| { let (f_below, o) = T::rounding_from(u, Floor); assert_eq!(o, Less); let f_above = f_below.next_higher(); let (f_alt, o) = T::rounding_from(u, Ceiling); assert_eq!(NiceFloat(f_alt), NiceFloat(f_above)); assert_eq!(o, Greater); let (f_alt, o) = T::rounding_from(u, Down); assert_eq!(NiceFloat(f_alt), NiceFloat(f_below)); assert_eq!(o, Less); let (f_alt, o) = T::rounding_from(u, Up); assert_eq!(NiceFloat(f_alt), NiceFloat(f_above)); assert_eq!(o, Greater); let (f_nearest, o) = T::rounding_from(u, Nearest); assert!( (NiceFloat(f_nearest), o) == (NiceFloat(f_below), Less) || (NiceFloat(f_nearest), o) == (NiceFloat(f_above), Greater) ); }); unsigned_gen_var_20::().test_properties(|u| { let (floor, o) = T::rounding_from(u, Floor); assert_eq!(o, Less); let ceiling = floor.next_higher(); let (nearest, o) = T::rounding_from(u, Nearest); assert_eq!( (NiceFloat(nearest), o), if floor.to_bits().even() { (NiceFloat(floor), Less) } else { (NiceFloat(ceiling), Greater) } ); }); } } fn rounding_from_helper_primitive_float_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned + WrappingFrom, S: TryFrom> + PrimitiveSigned + RoundingFrom + WrappingFrom, >() { signed_rounding_mode_pair_gen_var_4::().test_properties(|(i, rm)| { let (rounded, o) = T::rounding_from(i, rm); match (i >= S::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!(T::rounding_from(i, rm), (rounded, Equal)); } } else { assert_panic!(T::rounding_from(i, Exact)); } }); signed_gen_var_7::().test_properties(|i| { let (f, o) = T::rounding_from(i, Exact); let (f_alt, o_alt) = T::rounding_from(i, Floor); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(i, Ceiling); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(i, Down); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(i, Up); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); let (f_alt, o_alt) = T::rounding_from(i, Nearest); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); assert_eq!(S::rounding_from(f, Exact), (i, Equal)); }); if S::WIDTH > T::MANTISSA_WIDTH { signed_gen_var_8::().test_properties(|i| { let (f_below, o) = T::rounding_from(i, Floor); assert_eq!(o, Less); let f_above = f_below.next_higher(); let (f_alt, o_alt) = T::rounding_from(i, Ceiling); assert_eq!(NiceFloat(f_alt), NiceFloat(f_above)); assert_eq!(o_alt, Greater); if i >= S::ZERO { let (f_alt, o_alt) = T::rounding_from(i, Down); assert_eq!(NiceFloat(f_below), NiceFloat(f_alt)); assert_eq!(o_alt, Less); let (f_alt, o_alt) = T::rounding_from(i, Up); assert_eq!(NiceFloat(f_above), NiceFloat(f_alt)); assert_eq!(o_alt, Greater); } else { let (f_alt, o_alt) = T::rounding_from(i, Down); assert_eq!(NiceFloat(f_above), NiceFloat(f_alt)); assert_eq!(o_alt, Greater); let (f_alt, o_alt) = T::rounding_from(i, Up); assert_eq!(NiceFloat(f_below), NiceFloat(f_alt)); assert_eq!(o_alt, Less); } let (f_nearest, o_alt) = T::rounding_from(i, Nearest); assert!( (NiceFloat(f_nearest), o_alt) == (NiceFloat(f_below), Less) || (NiceFloat(f_nearest), o_alt) == (NiceFloat(f_above), Greater) ); }); signed_gen_var_9::().test_properties(|i| { let (floor, o) = T::rounding_from(i, Floor); assert_eq!(o, Less); let ceiling = floor.next_higher(); let (nearest, o) = T::rounding_from(i, Nearest); assert_eq!( (NiceFloat(nearest), o), if floor.to_bits().even() { (NiceFloat(floor), Less) } else { (NiceFloat(ceiling), Greater) } ); }); } } #[test] fn rounding_from_properties() { apply_fn_to_unsigneds_and_primitive_floats!(rounding_from_helper_unsigned_primitive_float); apply_fn_to_signeds_and_primitive_floats!(rounding_from_helper_signed_primitive_float); apply_fn_to_primitive_floats_and_unsigneds!(rounding_from_helper_primitive_float_unsigned); apply_fn_to_primitive_floats_and_unsigned_signed_pairs!( rounding_from_helper_primitive_float_signed ); } ================================================ FILE: malachite-base/tests/num/conversion/froms/saturating_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, SaturatingFrom}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use std::fmt::Debug; #[test] pub fn test_saturating_from() { fn test_single>(n: T) { assert_eq!(T::saturating_from(n), n); } test_single(0u8); test_single(5u64); test_single(1000u32); test_single(123u8); test_single(-123i16); test_single(i64::MIN); test_single(usize::MAX); fn test_double>(n_in: T, n_out: U) { assert_eq!(U::saturating_from(n_in), n_out); } test_double(0u8, 0u16); test_double(1000u16, 1000i32); test_double(-5i16, -5i8); test_double(255u8, 255u64); test_double(-1i8, 0u32); test_double(u32::MAX, u16::MAX); test_double(i32::MIN, 0u32); test_double(i32::MIN, 0u16); test_double(i32::MIN, i16::MIN); test_double(-5i32, 0u32); test_double(3000000000u32, i32::MAX); test_double(-1000i16, i8::MIN); } fn saturating_from_helper_primitive_int_unsigned< T: TryFrom + ConvertibleFrom + SaturatingFrom + PrimitiveInt, U: TryFrom + PrimitiveUnsigned, >() { unsigned_gen::().test_properties(|u| { let result = T::saturating_from(u); if let Ok(u_u) = T::try_from(u) { assert_eq!(result, u_u); } if let Ok(result_t) = U::try_from(result) { assert!(result_t <= u); assert_eq!(result_t == u, T::convertible_from(u)); } }); } fn saturating_from_helper_primitive_int_signed< T: TryFrom + ConvertibleFrom + SaturatingFrom + PrimitiveInt, U: TryFrom + PrimitiveSigned, >() { signed_gen::().test_properties(|i| { let result = T::saturating_from(i); if let Ok(i_u) = T::try_from(i) { assert_eq!(result, i_u); } if let Ok(result_t) = U::try_from(result) { assert!(result_t.le_abs(&i)); assert_eq!(result_t == i, T::convertible_from(i)); } }); } #[test] fn saturating_from_properties() { apply_fn_to_primitive_ints_and_unsigneds!(saturating_from_helper_primitive_int_unsigned); apply_fn_to_primitive_ints_and_signeds!(saturating_from_helper_primitive_int_signed); } ================================================ FILE: malachite-base/tests/num/conversion/froms/try_from_and_exact_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::from::{ PrimitiveFloatFromSignedError, PrimitiveFloatFromUnsignedError, SignedFromFloatError, UnsignedFromFloatError, }; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_13, primitive_float_gen_var_14, signed_gen, signed_gen_var_7, unsigned_gen, unsigned_gen_var_18, }; use std::fmt::Debug; use std::panic::catch_unwind; #[allow(clippy::needless_pass_by_value)] #[test] pub fn test_try_from() { fn test_double_primitive_int< T: PrimitiveFloat, U: TryFrom, Error = E> + Copy + Debug + Eq, E: Debug + Eq, >( n_in: T, n_out: Result, ) { assert_eq!(U::try_from(NiceFloat(n_in)), n_out); } test_double_primitive_int::<_, u8, _>(0.0f32, Ok(0)); test_double_primitive_int::<_, u8, _>(-0.0f32, Ok(0)); test_double_primitive_int::<_, u8, _>(123.0f32, Ok(123)); test_double_primitive_int::<_, i8, _>(-123.0f32, Ok(-123)); test_double_primitive_int::<_, u8, _>(-123.0f32, Err(UnsignedFromFloatError::FloatNegative)); test_double_primitive_int::<_, u8, _>( 500.0f32, Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange), ); test_double_primitive_int::<_, u8, _>( 123.1f32, Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange), ); test_double_primitive_int::<_, u8, _>( f32::NAN, Err(UnsignedFromFloatError::FloatInfiniteOrNan), ); test_double_primitive_int::<_, u8, _>( f32::INFINITY, Err(UnsignedFromFloatError::FloatInfiniteOrNan), ); test_double_primitive_int::<_, u8, _>( f32::NEGATIVE_INFINITY, Err(UnsignedFromFloatError::FloatInfiniteOrNan), ); test_double_primitive_int::<_, u8, _>(255.0f32, Ok(255)); test_double_primitive_int::<_, u8, _>( 256.0f32, Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange), ); test_double_primitive_int::<_, i8, _>(127.0f32, Ok(127)); test_double_primitive_int::<_, i8, _>( 128.0f32, Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange), ); test_double_primitive_int::<_, i8, _>(-128.0f32, Ok(-128)); test_double_primitive_int::<_, i8, _>( -129.0f32, Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange), ); fn test_double_primitive_float( n_in: T, n_out: Result, ) where NiceFloat: TryFrom, { assert_eq!(NiceFloat::::try_from(n_in), n_out.map(NiceFloat)); } test_double_primitive_float::<_, f32, _>(0u8, Ok(0.0)); test_double_primitive_float::<_, f32, _>(123u8, Ok(123.0)); test_double_primitive_float::<_, f32, _>(-123i8, Ok(-123.0)); test_double_primitive_float::<_, f32, _>(u128::MAX, Err(PrimitiveFloatFromUnsignedError)); test_double_primitive_float::<_, f32, _>(i128::MIN, Ok(-1.7014118e38)); test_double_primitive_float::<_, f32, _>(i128::MIN + 1, Err(PrimitiveFloatFromSignedError)); test_double_primitive_float::<_, f32, _>(u32::MAX, Err(PrimitiveFloatFromUnsignedError)); test_double_primitive_float::<_, f32, _>(i32::MIN, Ok(-2147483600.0)); test_double_primitive_float::<_, f32, _>(i32::MIN + 1, Err(PrimitiveFloatFromSignedError)); } #[test] pub fn test_exact_from() { fn test_single>(n: T) { assert_eq!(T::exact_from(n), n); } test_single(0u8); test_single(5u64); test_single(1000u32); test_single(123u8); test_single(-123i16); test_single(i64::MIN); test_single(usize::MAX); fn test_double_primitive_int< T: PrimitiveFloat, U: Copy + Debug + Eq + TryFrom>, >( n_in: T, n_out: U, ) { assert_eq!(U::exact_from(NiceFloat(n_in)), n_out); } test_double_primitive_int(0.0f32, 0u8); test_double_primitive_int(-0.0f32, 0u8); test_double_primitive_int(123.0f32, 123u8); test_double_primitive_int(-123.0f32, -123i8); test_double_primitive_int(255.0f32, 255u8); test_double_primitive_int(127.0f32, 127i8); test_double_primitive_int(-128.0f32, -128i8); fn test_double_primitive_float(n_in: T, n_out: U) where NiceFloat: TryFrom, { assert_eq!(NiceFloat::::exact_from(n_in), NiceFloat(n_out)); } test_double_primitive_float(0u8, 0.0f32); test_double_primitive_float(123u8, 123.0f32); test_double_primitive_float(-123i8, -123.0f32); test_double_primitive_float(i128::MIN, -1.7014118e38f32); test_double_primitive_float(i32::MIN, -2147483600.0f32); } #[test] fn exact_from_fail() { assert_panic!(u32::exact_from(-1i8)); assert_panic!(u16::exact_from(u32::MAX)); assert_panic!(u32::exact_from(i32::MIN)); assert_panic!(u16::exact_from(i32::MIN)); assert_panic!(i16::exact_from(i32::MIN)); assert_panic!(u32::exact_from(-5i32)); assert_panic!(i32::exact_from(3000000000u32)); assert_panic!(i8::exact_from(-1000i16)); assert_panic!(u8::exact_from(NiceFloat(-123.0f32))); assert_panic!(u8::exact_from(NiceFloat(500.0f32))); assert_panic!(u8::exact_from(NiceFloat(123.1f32))); assert_panic!(u8::exact_from(NiceFloat(f32::NAN))); assert_panic!(u8::exact_from(NiceFloat(f32::INFINITY))); assert_panic!(u8::exact_from(NiceFloat(f32::NEGATIVE_INFINITY))); assert_panic!(u8::exact_from(NiceFloat(256.0f32))); assert_panic!(i8::exact_from(NiceFloat(128.0f32))); assert_panic!(i8::exact_from(NiceFloat(-129.0f32))); assert_panic!(NiceFloat::::exact_from(u128::MAX)); assert_panic!(NiceFloat::::exact_from(i128::MIN + 1)); assert_panic!(NiceFloat::::exact_from(u32::MAX)); assert_panic!(NiceFloat::::exact_from(i32::MIN + 1)); } fn try_from_and_exact_from_helper_unsigned_primitive_float< T: TryFrom, Error = UnsignedFromFloatError> + PrimitiveUnsigned + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >() where NiceFloat: TryFrom, { primitive_float_gen::().test_properties(|f| { let f = NiceFloat(f); let result = T::try_from(f); if let Ok(u) = result { assert_eq!(u, T::exact_from(f)); assert_eq!( NiceFloat(f.0.abs_negative_zero()), NiceFloat::::exact_from(u) ); } }); primitive_float_gen_var_13::().test_properties(|f| { let f = NiceFloat(f); let u = T::exact_from(f); assert_eq!(NiceFloat::::exact_from(u), f); assert_eq!(T::try_from(f).unwrap(), u); assert_eq!(T::rounding_from(f.0, Exact).0, u); }); } fn try_from_and_exact_from_helper_signed_primitive_float< T: TryFrom, Error = SignedFromFloatError> + PrimitiveSigned + RoundingFrom, U: PrimitiveFloat + RoundingFrom, >() where NiceFloat: TryFrom, { primitive_float_gen::().test_properties(|f| { let f = NiceFloat(f); let result = T::try_from(f); if let Ok(i) = result { assert_eq!(i, T::exact_from(f)); assert_eq!( NiceFloat(f.0.abs_negative_zero()), NiceFloat::::exact_from(i) ); } }); primitive_float_gen_var_14::().test_properties(|f| { let f = NiceFloat(f); let i = T::exact_from(f); assert_eq!(NiceFloat::::exact_from(i), f); assert_eq!(T::try_from(f).unwrap(), i); assert_eq!(T::rounding_from(f.0, Exact).0, i); }); } fn try_from_and_exact_from_helper_primitive_float_unsigned< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveUnsigned + RoundingFrom + TryFrom>, >() where NiceFloat: TryFrom, { unsigned_gen::().test_properties(|u| { let result = NiceFloat::::try_from(u); if let Ok(f) = result { assert_eq!(f, NiceFloat::::exact_from(u)); assert_eq!(u, U::exact_from(f)); } }); unsigned_gen_var_18::().test_properties(|u| { let f = NiceFloat::::exact_from(u); assert_eq!(U::exact_from(f), u); assert_eq!(NiceFloat::::try_from(u).unwrap(), f); assert_eq!(NiceFloat(T::rounding_from(u, Exact).0), f); }); } fn try_from_and_exact_from_helper_primitive_float_signed< T: ConvertibleFrom + PrimitiveFloat + RoundingFrom, U: PrimitiveSigned + RoundingFrom + TryFrom>, >() where NiceFloat: TryFrom, { signed_gen::().test_properties(|i| { let result = NiceFloat::::try_from(i); if let Ok(f) = result { assert_eq!(f, NiceFloat::::exact_from(i)); assert_eq!(i, U::exact_from(f)); } }); signed_gen_var_7::().test_properties(|i| { let f = NiceFloat::::exact_from(i); assert_eq!(U::exact_from(f), i); assert_eq!(NiceFloat::::try_from(i).unwrap(), f); assert_eq!(NiceFloat(T::rounding_from(i, Exact).0), f); }); } #[test] fn try_from_and_exact_from_properties() { apply_fn_to_unsigneds_and_primitive_floats!( try_from_and_exact_from_helper_unsigned_primitive_float ); apply_fn_to_signeds_and_primitive_floats!( try_from_and_exact_from_helper_signed_primitive_float ); apply_fn_to_primitive_floats_and_unsigneds!( try_from_and_exact_from_helper_primitive_float_unsigned ); apply_fn_to_primitive_floats_and_signeds!( try_from_and_exact_from_helper_primitive_float_signed ); } ================================================ FILE: malachite-base/tests/num/conversion/froms/wrapping_from.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{OverflowingFrom, WrappingFrom}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use std::fmt::Debug; #[test] pub fn test_wrapping_from() { fn test_single>(n: T) { assert_eq!(T::wrapping_from(n), n); } test_single(0u8); test_single(5u64); test_single(1000u32); test_single(123u8); test_single(-123i16); test_single(i64::MIN); test_single(usize::MAX); fn test_double>(n_in: T, n_out: U) { assert_eq!(U::wrapping_from(n_in), n_out); } test_double(0u8, 0u16); test_double(1000u16, 1000i32); test_double(-5i16, -5i8); test_double(255u8, 255u64); test_double(-1i8, u32::MAX); test_double(u32::MAX, u16::MAX); test_double(i32::MIN, 0x80000000u32); test_double(i32::MIN, 0u16); test_double(i32::MIN, 0i16); test_double(-5i32, 0xfffffffbu32); test_double(3000000000u32, -1294967296i32); test_double(-1000i16, 24i8); } fn wrapping_from_helper_primitive_int_unsigned< T: OverflowingFrom + WrappingFrom + PrimitiveInt, U: PrimitiveUnsigned, >() { unsigned_gen::().test_properties(|u| { let result = T::wrapping_from(u); assert_eq!(result, T::overflowing_from(u).0); }); } fn wrapping_from_helper_primitive_int_signed< T: OverflowingFrom + WrappingFrom + PrimitiveInt, U: PrimitiveSigned, >() { signed_gen::().test_properties(|i| { let result = T::wrapping_from(i); assert_eq!(result, T::overflowing_from(i).0); }); } #[test] fn wrapping_from_properties() { apply_fn_to_primitive_ints_and_unsigneds!(wrapping_from_helper_primitive_int_unsigned); apply_fn_to_primitive_ints_and_signeds!(wrapping_from_helper_primitive_int_signed); } ================================================ FILE: malachite-base/tests/num/conversion/half/join_halves.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::test_util::generators::{unsigned_gen, unsigned_pair_gen_var_27}; fn join_halves_helper(upper: T::Half, lower: T::Half, out: T) { assert_eq!(T::join_halves(upper, lower), out); } #[test] pub fn test_join_halves() { join_halves_helper(0u32, 0u32, 0u64); join_halves_helper(0u32, 1u32, 1u64); join_halves_helper(0, u8::MAX, u16::from(u8::MAX)); join_halves_helper(1, 0, u16::from(u8::MAX) + 1); join_halves_helper(u8::MAX, u8::MAX, u16::MAX); join_halves_helper(1, 2, 258u16); join_halves_helper(0xabcd, 0x1234, 0xabcd1234u32); } fn join_halves_properties_helper< T: From + HasHalf + JoinHalves + PrimitiveUnsigned + SplitInHalf, HT: PrimitiveUnsigned, >() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let joined = T::join_halves(x, y); assert_eq!((T::from(x) << (T::WIDTH >> 1)) + T::from(y), joined); assert_eq!(joined.upper_half(), x); assert_eq!(joined.lower_half(), y); }); unsigned_gen::().test_properties(|x| { assert_eq!(T::join_halves(HT::ZERO, x), T::from(x)); }); } #[test] fn join_halves_properties() { join_halves_properties_helper::(); join_halves_properties_helper::(); join_halves_properties_helper::(); join_halves_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/conversion/half/lower_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::test_util::generators::unsigned_gen; fn lower_half_test_helper(n: T, out: T::Half) where T::Half: PrimitiveUnsigned, { assert_eq!(n.lower_half(), out); } #[test] pub fn test_lower_half() { lower_half_test_helper(0u64, 0u32); lower_half_test_helper(1u64, 1u32); lower_half_test_helper(u16::from(u8::MAX), u8::MAX); lower_half_test_helper(u16::from(u8::MAX) + 1, 0); lower_half_test_helper(u16::MAX, u8::MAX); lower_half_test_helper(258u16, 2u8); lower_half_test_helper(0xabcd1234u32, 0x1234); } fn lower_half_properties_helper() { unsigned_gen::().test_properties(|n| { let lower = n.lower_half(); assert_eq!(T::join_halves(n.upper_half(), lower), n); }); } #[test] fn lower_half_properties() { lower_half_properties_helper::(); lower_half_properties_helper::(); lower_half_properties_helper::(); lower_half_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/conversion/half/split_in_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::test_util::generators::unsigned_gen; fn split_in_half_test_helper(n: T, out: (T::Half, T::Half)) where T::Half: PrimitiveUnsigned, { assert_eq!(n.split_in_half(), out); } #[test] pub fn test_split_in_half() { split_in_half_test_helper(0u64, (0u32, 0u32)); split_in_half_test_helper(1u64, (0u32, 1u32)); split_in_half_test_helper(u16::from(u8::MAX), (0, u8::MAX)); split_in_half_test_helper(u16::from(u8::MAX) + 1, (1, 0)); split_in_half_test_helper(u16::MAX, (u8::MAX, u8::MAX)); split_in_half_test_helper(258u16, (1u8, 2u8)); split_in_half_test_helper(0xabcd1234u32, (0xabcd, 0x1234)); } fn split_in_half_properties_helper() { unsigned_gen::().test_properties(|n| { let (upper, lower) = n.split_in_half(); assert_eq!(T::join_halves(upper, lower), n); }); } #[test] fn split_in_half_properties() { split_in_half_properties_helper::(); split_in_half_properties_helper::(); split_in_half_properties_helper::(); split_in_half_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/conversion/half/upper_half.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::test_util::generators::unsigned_gen; fn upper_half_test_helper(n: T, out: T::Half) where T::Half: PrimitiveUnsigned, { assert_eq!(n.upper_half(), out); } #[test] pub fn test_upper_half() { upper_half_test_helper(0u64, 0u32); upper_half_test_helper(1u64, 0u32); upper_half_test_helper(u16::from(u8::MAX), 0); upper_half_test_helper(u16::from(u8::MAX) + 1, 1); upper_half_test_helper(u16::MAX, u8::MAX); upper_half_test_helper(258u16, 1u8); upper_half_test_helper(0xabcd1234u32, 0xabcd); } fn upper_half_properties_helper() { unsigned_gen::().test_properties(|n| { let upper = n.upper_half(); assert_eq!(T::join_halves(upper, n.lower_half()), n); }); } #[test] fn upper_half_properties() { upper_half_properties_helper::(); upper_half_properties_helper::(); upper_half_properties_helper::(); upper_half_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{primitive_float_gen, signed_gen, unsigned_gen}; #[test] pub fn test_is_integer() { fn test_u(u: T, is_integer: bool) { assert_eq!(u.is_integer(), is_integer); } test_u::(0, true); test_u::(1, true); test_u::(100, true); fn test_i(i: T, is_integer: bool) { assert_eq!(i.is_integer(), is_integer); } test_i::(0, true); test_i::(1, true); test_i::(100, true); test_i::(-1, true); test_i::(-100, true); fn test_f(f: T, is_integer: bool) { assert_eq!(f.is_integer(), is_integer); } test_f::(0.0, true); test_f::(1.0, true); test_f::(100.0, true); test_f::(-1.0, true); test_f::(-100.0, true); test_f::(0.1, false); test_f::(100.1, false); test_f::(-0.1, false); test_f::(-100.1, false); test_f::(f32::NAN, false); test_f::(f32::INFINITY, false); test_f::(f32::NEGATIVE_INFINITY, false); } fn is_integer_unsigned() { unsigned_gen::().test_properties(|u| { assert!(u.is_integer()); }); } fn is_integer_signed() { signed_gen::().test_properties(|i| { assert!(i.is_integer()); }); } fn is_integer_primitive_float() { primitive_float_gen::().test_properties(|f| { assert_eq!( f.is_integer(), f.is_finite() && (f == T::ZERO || f.integer_exponent() >= 0) ); }); } #[test] fn is_integer_properties() { apply_fn_to_unsigneds!(is_integer_unsigned); apply_fn_to_signeds!(is_integer_signed); apply_fn_to_primitive_floats!(is_integer_primitive_float); } ================================================ FILE: malachite-base/tests/num/conversion/mantissa_and_exponent/integer_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, unsigned_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_30, unsigned_signed_pair_gen_var_1, unsigned_signed_pair_gen_var_2, }; use std::cmp::Ordering::*; use std::panic::catch_unwind; #[test] pub fn test_integer_mantissa_and_exponent() { fn test_unsigned(x: T, mantissa: T, exponent: u64) { assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!(x.integer_mantissa_and_exponent(), (mantissa, exponent)); } test_unsigned::(1, 1, 0); test_unsigned::(2, 1, 1); test_unsigned::(3, 3, 0); test_unsigned::(100, 25, 2); test_unsigned::(65536, 1, 16); fn test_primitive_float(x: T, mantissa: u64, exponent: i64) { assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!(x.integer_mantissa_and_exponent(), (mantissa, exponent)); } test_primitive_float::(1.0, 1, 0); test_primitive_float::(core::f32::consts::PI, 13176795, -22); test_primitive_float::(0.1, 13421773, -27); test_primitive_float::(10.0, 5, 1); test_primitive_float::(f32::MIN_POSITIVE_SUBNORMAL, 1, -149); test_primitive_float::(f32::MAX_SUBNORMAL, 0x7fffff, -149); test_primitive_float::(f32::MIN_POSITIVE_NORMAL, 1, -126); test_primitive_float::(f32::MAX_FINITE, 0xffffff, 104); test_primitive_float::(1.0, 1, 0); test_primitive_float::(core::f64::consts::PI, 884279719003555, -48); test_primitive_float::(0.1, 3602879701896397, -55); test_primitive_float::(10.0, 5, 1); test_primitive_float::(f64::MIN_POSITIVE_SUBNORMAL, 1, -1074); test_primitive_float::(f64::MAX_SUBNORMAL, 0xfffffffffffff, -1074); test_primitive_float::(f64::MIN_POSITIVE_NORMAL, 1, -1022); test_primitive_float::(f64::MAX_FINITE, 0x1fffffffffffff, 971); } fn integer_mantissa_and_exponent_unsigned_fail_helper() { assert_panic!(T::ZERO.integer_mantissa_and_exponent()); } fn integer_mantissa_and_exponent_primitive_float_fail_helper() { assert_panic!(T::NAN.integer_mantissa_and_exponent()); assert_panic!(T::INFINITY.integer_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_INFINITY.integer_mantissa_and_exponent()); assert_panic!(T::ZERO.integer_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_ZERO.integer_mantissa_and_exponent()); } #[test] pub fn integer_mantissa_and_exponent_fail() { apply_fn_to_unsigneds!(integer_mantissa_and_exponent_unsigned_fail_helper); apply_fn_to_primitive_floats!(integer_mantissa_and_exponent_primitive_float_fail_helper); } #[test] pub fn test_from_integer_mantissa_and_exponent() { fn test_unsigned(mantissa: T, exponent: u64, x: Option) { assert_eq!(T::from_integer_mantissa_and_exponent(mantissa, exponent), x); } test_unsigned::(0, 0, Some(0)); test_unsigned::(1, 0, Some(1)); test_unsigned::(1, 1, Some(2)); test_unsigned::(3, 0, Some(3)); test_unsigned::(25, 2, Some(100)); test_unsigned::(1, 16, Some(65536)); test_unsigned::(1, 100, None); fn test_primitive_float(mantissa: u64, exponent: i64, x: Option) { assert_eq!( T::from_integer_mantissa_and_exponent(mantissa, exponent).map(NiceFloat), x.map(NiceFloat) ); } test_primitive_float::(0, 5, Some(0.0)); test_primitive_float::(1, 0, Some(1.0)); test_primitive_float::(4, -2, Some(1.0)); test_primitive_float::(13176795, -22, Some(core::f32::consts::PI)); test_primitive_float::(13421773, -27, Some(0.1)); test_primitive_float::(5, 1, Some(10.0)); test_primitive_float::(1, -149, Some(f32::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(4, -151, Some(f32::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(0x7fffff, -149, Some(f32::MAX_SUBNORMAL)); test_primitive_float::(1, -126, Some(f32::MIN_POSITIVE_NORMAL)); test_primitive_float::(0xffffff, 104, Some(f32::MAX_FINITE)); test_primitive_float::(1, 127, Some(1.7014118e38)); test_primitive_float::(5, 10000, None); test_primitive_float::(5, -10000, None); test_primitive_float::(u64::MAX, -32, None); // precision too high test_primitive_float::(3, -150, None); // precision too high test_primitive_float::(1, 128, None); // precision too high test_primitive_float::(0, 5, Some(0.0)); test_primitive_float::(1, 0, Some(1.0)); test_primitive_float::(4, -2, Some(1.0)); test_primitive_float::(884279719003555, -48, Some(core::f64::consts::PI)); test_primitive_float::(3602879701896397, -55, Some(0.1)); test_primitive_float::(5, 1, Some(10.0)); test_primitive_float::(1, -1074, Some(f64::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(4, -1076, Some(f64::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(0xfffffffffffff, -1074, Some(f64::MAX_SUBNORMAL)); test_primitive_float::(1, -1022, Some(f64::MIN_POSITIVE_NORMAL)); test_primitive_float::(0x1fffffffffffff, 971, Some(f64::MAX_FINITE)); test_primitive_float::(1, 1023, Some(8.98846567431158e307)); test_primitive_float::(5, 10000, None); test_primitive_float::(5, -10000, None); test_primitive_float::(u64::MAX, -64, None); // precision too high test_primitive_float::(3, -1075, None); // precision too high test_primitive_float::(1, 1024, None); // precision too high } fn integer_mantissa_and_exponent_properties_helper_unsigned() { unsigned_gen_var_1::().test_properties(|x| { let (mantissa, exponent) = x.integer_mantissa_and_exponent(); assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!( T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(), x ); assert!(exponent < T::WIDTH); assert!(mantissa.odd()); }); } fn integer_mantissa_and_exponent_properties_helper_primitive_float() { primitive_float_gen_var_12::().test_properties(|x| { let (mantissa, exponent) = x.integer_mantissa_and_exponent(); assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); assert_eq!( NiceFloat(T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap()), NiceFloat(x.abs()) ); assert!(exponent >= T::MIN_EXPONENT); assert!(exponent <= T::MAX_EXPONENT); assert!(mantissa.significant_bits() <= T::MANTISSA_WIDTH + 1); assert!(mantissa.odd()); }); } #[test] fn integer_mantissa_and_exponent_properties() { apply_fn_to_unsigneds!(integer_mantissa_and_exponent_properties_helper_unsigned); apply_fn_to_primitive_floats!(integer_mantissa_and_exponent_properties_helper_primitive_float); } fn from_integer_mantissa_and_exponent_properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { T::from_integer_mantissa_and_exponent(mantissa, exponent); }); unsigned_pair_gen_var_30::().test_properties(|(mantissa, exponent)| { let f = T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(); if mantissa.odd() { assert_eq!(f.integer_mantissa_and_exponent(), (mantissa, exponent)); } }); } fn from_integer_mantissa_and_exponent_properties_helper_primitive_float() { unsigned_signed_pair_gen_var_1().test_properties(|(mantissa, exponent)| { T::from_integer_mantissa_and_exponent(mantissa, exponent); }); unsigned_signed_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { let f = T::from_integer_mantissa_and_exponent(mantissa, exponent).unwrap(); assert!(!f.is_nan()); assert_eq!(f.sign(), Greater); if !f.is_nan() && mantissa.odd() { assert_eq!(f.integer_mantissa_and_exponent(), (mantissa, exponent)); } }); } #[test] fn from_integer_mantissa_and_exponent_properties() { apply_fn_to_unsigneds!(from_integer_mantissa_and_exponent_properties_helper_unsigned); apply_fn_to_primitive_floats!( from_integer_mantissa_and_exponent_properties_helper_primitive_float ); } ================================================ FILE: malachite-base/tests/num/conversion/mantissa_and_exponent/raw_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::{primitive_float_gen, unsigned_pair_gen_var_26}; use std::cmp::Ordering::*; use std::panic::catch_unwind; #[test] pub fn test_raw_mantissa_and_exponent() { fn test(x: T, mantissa: u64, exponent: u64) { assert_eq!(x.raw_mantissa(), mantissa); assert_eq!(x.raw_exponent(), exponent); assert_eq!(x.raw_mantissa_and_exponent(), (mantissa, exponent)); } test::(0.0, 0, 0); test::(-0.0, 0, 0); test::(f32::NAN, 0x400000, 255); test::(f32::INFINITY, 0, 255); test::(f32::NEGATIVE_INFINITY, 0, 255); test::(1.0, 0, 127); test::(core::f32::consts::PI, 4788187, 128); test::(0.1, 5033165, 123); test::(10.0, 2097152, 130); test::(f32::MIN_POSITIVE_SUBNORMAL, 1, 0); test::(f32::MAX_SUBNORMAL, 0x7fffff, 0); test::(f32::MIN_POSITIVE_NORMAL, 0, 1); test::(f32::MAX_FINITE, 0x7fffff, 254); test::(0.0, 0, 0); test::(-0.0, 0, 0); test::(f64::NAN, 0x8000000000000, 2047); test::(f64::INFINITY, 0, 2047); test::(f64::NEGATIVE_INFINITY, 0, 2047); test::(1.0, 0, 1023); test::(core::f64::consts::PI, 2570638124657944, 1024); test::(0.1, 2702159776422298, 1019); test::(10.0, 1125899906842624, 1026); test::(f64::MIN_POSITIVE_SUBNORMAL, 1, 0); test::(f64::MAX_SUBNORMAL, 0xfffffffffffff, 0); test::(f64::MIN_POSITIVE_NORMAL, 0, 1); test::(f64::MAX_FINITE, 0xfffffffffffff, 2046); } #[test] pub fn test_raw_exponent() { fn test(x: T, exponent: u64) { assert_eq!(x.raw_exponent(), exponent); } test::(0.0, 0); test::(-0.0, 0); test::(f32::NAN, 255); test::(f32::INFINITY, 255); test::(f32::NEGATIVE_INFINITY, 255); test::(1.0, 127); test::(core::f32::consts::PI, 128); test::(0.1, 123); test::(10.0, 130); test::(f32::MIN_POSITIVE_SUBNORMAL, 0); test::(f32::MAX_SUBNORMAL, 0); test::(f32::MIN_POSITIVE_NORMAL, 1); test::(f32::MAX_FINITE, 254); test::(0.0, 0); test::(-0.0, 0); test::(f64::NAN, 2047); test::(f64::INFINITY, 2047); test::(f64::NEGATIVE_INFINITY, 2047); test::(1.0, 1023); test::(core::f64::consts::PI, 1024); test::(0.1, 1019); test::(10.0, 1026); test::(f64::MIN_POSITIVE_SUBNORMAL, 0); test::(f64::MAX_SUBNORMAL, 0); test::(f64::MIN_POSITIVE_NORMAL, 1); test::(f64::MAX_FINITE, 2046); } pub fn test_from_raw_mantissa_and_exponent() { fn test(mantissa: u64, exponent: u64, x: T) { assert_eq!( NiceFloat(T::from_raw_mantissa_and_exponent(mantissa, exponent)), NiceFloat(x) ); } test::(0, 0, 0.0); test::(0x400000, 255, f32::NAN); test::(0, 255, f32::INFINITY); test::(0, 127, 1.0); test::(4788187, 128, core::f32::consts::PI); test::(5033165, 123, 0.1); test::(2097152, 130, 10.0); test::(1, 0, f32::MIN_POSITIVE_SUBNORMAL); test::(0x7fffff, 0, f32::MAX_SUBNORMAL); test::(0, 1, f32::MIN_POSITIVE_NORMAL); test::(0x7fffff, 254, f32::MAX_FINITE); test::(0, 0, 0.0); test::(0x8000000000000, 2047, f64::NAN); test::(0, 2047, f64::INFINITY); test::(0, 1023, 1.0); test::(2570638124657944, 1024, core::f64::consts::PI); test::(2702159776422298, 1019, 0.1); test::(1125899906842624, 1026, 10.0); test::(1, 0, f64::MIN_POSITIVE_SUBNORMAL); test::(0xfffffffffffff, 0, f64::MAX_SUBNORMAL); test::(0, 1, f64::MIN_POSITIVE_NORMAL); test::(0xfffffffffffff, 2046, f64::MAX_FINITE); } fn from_raw_mantissa_and_exponent_fail_helper() { assert_panic!(T::from_raw_mantissa_and_exponent( u64::power_of_2(T::MANTISSA_WIDTH), 0 )); assert_panic!(T::from_raw_mantissa_and_exponent( 0, u64::power_of_2(T::EXPONENT_WIDTH) )); } #[test] pub fn from_raw_mantissa_and_exponent_fail() { apply_fn_to_primitive_floats!(from_raw_mantissa_and_exponent_fail_helper); } fn raw_mantissa_and_exponent_properties_helper() { primitive_float_gen::().test_properties(|x| { let (mantissa, exponent) = x.raw_mantissa_and_exponent(); assert_eq!(x.raw_mantissa(), mantissa); assert_eq!(x.raw_exponent(), exponent); assert_eq!( NiceFloat(T::from_raw_mantissa_and_exponent(mantissa, exponent)), NiceFloat(x.abs()) ); assert!(exponent.significant_bits() <= T::EXPONENT_WIDTH); assert!(mantissa.significant_bits() <= T::MANTISSA_WIDTH); }); } #[test] fn raw_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(raw_mantissa_and_exponent_properties_helper); } fn from_raw_mantissa_and_exponent_properties_helper() { unsigned_pair_gen_var_26::().test_properties(|(mantissa, exponent)| { let f = T::from_raw_mantissa_and_exponent(mantissa, exponent); assert!(f.is_nan() || f.sign() == Greater); if !f.is_nan() { assert_eq!(f.raw_mantissa_and_exponent(), (mantissa, exponent)); } }); } #[test] fn from_raw_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(from_raw_mantissa_and_exponent_properties_helper); } ================================================ FILE: malachite-base/tests/num/conversion/mantissa_and_exponent/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::mantissa_and_exponent::{ from_sci_mantissa_and_exponent_round, sci_mantissa_and_exponent_round, }; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, primitive_float_signed_pair_gen_var_1, primitive_float_signed_pair_gen_var_2, primitive_float_unsigned_pair_gen_var_1, primitive_float_unsigned_pair_gen_var_2, primitive_float_unsigned_rounding_mode_triple_gen_var_1, primitive_float_unsigned_rounding_mode_triple_gen_var_2, unsigned_gen_var_1, unsigned_rounding_mode_pair_gen_var_1, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] pub fn test_sci_mantissa_and_exponent() { fn test_unsigned, U: PrimitiveFloat>( x: T, mantissa: U, exponent: u64, ) { assert_eq!(NiceFloat(x.sci_mantissa()), NiceFloat(mantissa)); assert_eq!(SciMantissaAndExponent::::sci_exponent(x), exponent); let (actual_mantissa, actual_exponent) = x.sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); } test_unsigned::(1, 1.0, 0); test_unsigned::(2, 1.0, 1); test_unsigned::(3, 1.5, 1); test_unsigned::(100, 1.5625, 6); test_unsigned::(65536, 1.0, 16); test_unsigned::(u16::MAX, 1.9999695, 15); test_unsigned::(u32::MAX, 1.0, 32); test_unsigned::(u64::MAX, 1.0, 64); test_unsigned::(u16::MAX, 1.999969482421875, 15); test_unsigned::(u32::MAX, 1.9999999995343387, 31); test_unsigned::(u64::MAX, 1.0, 64); fn test_primitive_float(x: T, mantissa: T, exponent: i64) { assert_eq!(NiceFloat(x.sci_mantissa()), NiceFloat(mantissa)); assert_eq!(x.sci_exponent(), exponent); let (actual_mantissa, actual_exponent) = x.sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); } test_primitive_float::(1.0, 1.0, 0); test_primitive_float::(core::f32::consts::PI, core::f32::consts::FRAC_PI_2, 1); test_primitive_float::(0.1, 1.6, -4); test_primitive_float::(10.0, 1.25, 3); test_primitive_float::(f32::MIN_POSITIVE_SUBNORMAL, 1.0, -149); test_primitive_float::(f32::MAX_SUBNORMAL, 1.9999998, -127); test_primitive_float::(f32::MIN_POSITIVE_NORMAL, 1.0, -126); test_primitive_float::(f32::MAX_FINITE, 1.9999999, 127); test_primitive_float::(1.0, 1.0, 0); test_primitive_float::(core::f64::consts::PI, core::f64::consts::FRAC_PI_2, 1); test_primitive_float::(0.1, 1.6, -4); test_primitive_float::(10.0, 1.25, 3); test_primitive_float::(f64::MIN_POSITIVE_SUBNORMAL, 1.0, -1074); test_primitive_float::(f64::MAX_SUBNORMAL, 1.9999999999999996, -1023); test_primitive_float::(f64::MIN_POSITIVE_NORMAL, 1.0, -1022); test_primitive_float::(f64::MAX_FINITE, 1.9999999999999998, 1023); } fn sci_mantissa_and_exponent_fail_helper_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >() { assert_panic!(SciMantissaAndExponent::::sci_mantissa_and_exponent( T::ZERO )); } fn sci_mantissa_and_exponent_fail_helper_primitive_float() { assert_panic!(T::NAN.sci_mantissa_and_exponent()); assert_panic!(T::INFINITY.sci_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_INFINITY.sci_mantissa_and_exponent()); assert_panic!(T::ZERO.sci_mantissa_and_exponent()); assert_panic!(T::NEGATIVE_ZERO.sci_mantissa_and_exponent()); } #[test] pub fn sci_mantissa_and_exponent_fail() { apply_fn_to_unsigneds_and_primitive_floats!(sci_mantissa_and_exponent_fail_helper_unsigned); apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_fail_helper_primitive_float); } #[test] pub fn test_sci_mantissa_and_exponent_round() { fn test, U: PrimitiveFloat>( x: T, rm: RoundingMode, out: Option<(U, u64, Ordering)>, ) { assert_eq!( sci_mantissa_and_exponent_round::(x, rm).map(|(m, e, o)| (NiceFloat(m), e, o)), out.map(|(m, e, o)| (NiceFloat(m), e, o)) ); } test::(1, Floor, Some((1.0, 0, Equal))); test::(1, Down, Some((1.0, 0, Equal))); test::(1, Ceiling, Some((1.0, 0, Equal))); test::(1, Up, Some((1.0, 0, Equal))); test::(1, Nearest, Some((1.0, 0, Equal))); test::(1, Exact, Some((1.0, 0, Equal))); test::(2, Floor, Some((1.0, 1, Equal))); test::(3, Floor, Some((1.5, 1, Equal))); test::(100, Floor, Some((1.5625, 6, Equal))); test::(65536, Floor, Some((1.0, 16, Equal))); test::(u16::MAX, Floor, Some((1.9999695, 15, Equal))); test::(u16::MAX, Down, Some((1.9999695, 15, Equal))); test::(u16::MAX, Ceiling, Some((1.9999695, 15, Equal))); test::(u16::MAX, Up, Some((1.9999695, 15, Equal))); test::(u16::MAX, Nearest, Some((1.9999695, 15, Equal))); test::(u16::MAX, Exact, Some((1.9999695, 15, Equal))); test::(u32::MAX, Floor, Some((1.9999999, 31, Less))); test::(u32::MAX, Down, Some((1.9999999, 31, Less))); test::(u32::MAX, Ceiling, Some((1.0, 32, Greater))); test::(u32::MAX, Up, Some((1.0, 32, Greater))); test::(u32::MAX, Nearest, Some((1.0, 32, Greater))); test::(u32::MAX, Exact, None); test::(u64::MAX, Floor, Some((1.9999999, 63, Less))); test::(u64::MAX, Down, Some((1.9999999, 63, Less))); test::(u64::MAX, Ceiling, Some((1.0, 64, Greater))); test::(u64::MAX, Up, Some((1.0, 64, Greater))); test::(u64::MAX, Nearest, Some((1.0, 64, Greater))); test::(u64::MAX, Exact, None); test::(u16::MAX, Floor, Some((1.999969482421875, 15, Equal))); test::(u16::MAX, Down, Some((1.999969482421875, 15, Equal))); test::(u16::MAX, Ceiling, Some((1.999969482421875, 15, Equal))); test::(u16::MAX, Up, Some((1.999969482421875, 15, Equal))); test::(u16::MAX, Nearest, Some((1.999969482421875, 15, Equal))); test::(u16::MAX, Exact, Some((1.999969482421875, 15, Equal))); test::(u32::MAX, Floor, Some((1.9999999995343387, 31, Equal))); test::(u32::MAX, Down, Some((1.9999999995343387, 31, Equal))); test::(u32::MAX, Ceiling, Some((1.9999999995343387, 31, Equal))); test::(u32::MAX, Up, Some((1.9999999995343387, 31, Equal))); test::(u32::MAX, Nearest, Some((1.9999999995343387, 31, Equal))); test::(u32::MAX, Exact, Some((1.9999999995343387, 31, Equal))); test::(u64::MAX, Floor, Some((1.9999999999999998, 63, Less))); test::(u64::MAX, Down, Some((1.9999999999999998, 63, Less))); test::(u64::MAX, Ceiling, Some((1.0, 64, Greater))); test::(u64::MAX, Up, Some((1.0, 64, Greater))); test::(u64::MAX, Nearest, Some((1.0, 64, Greater))); test::(u64::MAX, Exact, None); } fn sci_mantissa_and_exponent_round_fail_helper() { assert_panic!(sci_mantissa_and_exponent_round::(T::ZERO, Floor)); } #[test] pub fn sci_mantissa_and_exponent_round_fail() { apply_fn_to_unsigneds_and_primitive_floats!(sci_mantissa_and_exponent_round_fail_helper); } #[test] pub fn test_from_sci_mantissa_and_exponent() { fn test_unsigned, U: PrimitiveFloat>( mantissa: U, exponent: u64, x: Option, ) { assert_eq!(T::from_sci_mantissa_and_exponent(mantissa, exponent), x); } test_unsigned::(1.0, 0, Some(1)); test_unsigned::(1.0, 1, Some(2)); test_unsigned::(1.5, 0, Some(2)); test_unsigned::(1.5, 1, Some(3)); test_unsigned::(1.5626, 6, Some(100)); test_unsigned::(1.0, 16, Some(65536)); test_unsigned::(1.0, 100, None); test_unsigned::(1.0, 32, None); fn test_primitive_float(mantissa: T, exponent: i64, x: Option) { assert_eq!( T::from_sci_mantissa_and_exponent(mantissa, exponent).map(NiceFloat), x.map(NiceFloat) ); } test_primitive_float::(1.0, 0, Some(1.0)); test_primitive_float::(std::f32::consts::FRAC_PI_2, 1, Some(core::f32::consts::PI)); test_primitive_float::(1.6, -4, Some(0.1)); test_primitive_float::(1.25, 3, Some(10.0)); test_primitive_float::(1.0, -149, Some(f32::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(1.9999998, -127, Some(f32::MAX_SUBNORMAL)); test_primitive_float::(1.0, -126, Some(f32::MIN_POSITIVE_NORMAL)); test_primitive_float::(1.9999999, 127, Some(f32::MAX_FINITE)); test_primitive_float::(2.0, 1, None); test_primitive_float::(1.1, -2000, None); test_primitive_float::(1.1, 2000, None); test_primitive_float::(1.999, -149, None); // precision too high test_primitive_float::(1.0, 0, Some(1.0)); test_primitive_float::(std::f64::consts::FRAC_PI_2, 1, Some(core::f64::consts::PI)); test_primitive_float::(1.6, -4, Some(0.1)); test_primitive_float::(1.25, 3, Some(10.0)); test_primitive_float::(1.0, -1074, Some(f64::MIN_POSITIVE_SUBNORMAL)); test_primitive_float::(1.9999999999999996, -1023, Some(f64::MAX_SUBNORMAL)); test_primitive_float::(1.0, -1022, Some(f64::MIN_POSITIVE_NORMAL)); test_primitive_float::(1.9999999999999998, 1023, Some(f64::MAX_FINITE)); test_primitive_float::(2.0, 1, None); test_primitive_float::(1.1, -2000, None); test_primitive_float::(1.1, 2000, None); test_primitive_float::(1.999, -1074, None); // precision too high } #[test] pub fn test_from_sci_mantissa_and_exponent_round() { fn test( mantissa: U, exponent: u64, rm: RoundingMode, xo: Option<(T, Ordering)>, ) { assert_eq!( from_sci_mantissa_and_exponent_round::(mantissa, exponent, rm), xo ); } test::(1.0, 0, Floor, Some((1, Equal))); test::(1.0, 0, Down, Some((1, Equal))); test::(1.0, 0, Ceiling, Some((1, Equal))); test::(1.0, 0, Up, Some((1, Equal))); test::(1.0, 0, Nearest, Some((1, Equal))); test::(1.0, 0, Exact, Some((1, Equal))); test::(1.25, 0, Floor, Some((1, Less))); test::(1.25, 0, Down, Some((1, Less))); test::(1.25, 0, Ceiling, Some((2, Greater))); test::(1.25, 0, Up, Some((2, Greater))); test::(1.25, 0, Nearest, Some((1, Less))); test::(1.25, 0, Exact, None); test::(1.5, 0, Floor, Some((1, Less))); test::(1.5, 0, Down, Some((1, Less))); test::(1.5, 0, Ceiling, Some((2, Greater))); test::(1.5, 0, Up, Some((2, Greater))); test::(1.5, 0, Nearest, Some((2, Greater))); test::(1.5, 0, Exact, None); test::(1.75, 0, Floor, Some((1, Less))); test::(1.75, 0, Down, Some((1, Less))); test::(1.75, 0, Ceiling, Some((2, Greater))); test::(1.75, 0, Up, Some((2, Greater))); test::(1.75, 0, Nearest, Some((2, Greater))); test::(1.75, 0, Exact, None); test::(1.5, 1, Floor, Some((3, Equal))); test::(1.5, 1, Down, Some((3, Equal))); test::(1.5, 1, Ceiling, Some((3, Equal))); test::(1.5, 1, Up, Some((3, Equal))); test::(1.5, 1, Nearest, Some((3, Equal))); test::(1.5, 1, Exact, Some((3, Equal))); test::(1.0, 100, Floor, None); test::(1.0, 100, Down, None); test::(1.0, 100, Ceiling, None); test::(1.0, 100, Up, None); test::(1.0, 100, Nearest, None); test::(1.0, 100, Exact, None); } fn from_sci_mantissa_and_exponent_round_fail_helper() { assert_panic!(from_sci_mantissa_and_exponent_round::( U::ZERO, 0, Floor )); } #[test] pub fn from_sci_mantissa_and_exponent_round_fail() { apply_fn_to_unsigneds_and_primitive_floats!(from_sci_mantissa_and_exponent_round_fail_helper); } fn sci_mantissa_and_exponent_properties_helper_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >() { unsigned_gen_var_1::().test_properties(|x| { let (mantissa, exponent) = SciMantissaAndExponent::::sci_mantissa_and_exponent(x); assert_eq!(NiceFloat(x.sci_mantissa()), NiceFloat(mantissa)); assert_eq!(SciMantissaAndExponent::::sci_exponent(x), exponent); assert_eq!( sci_mantissa_and_exponent_round(x, Nearest).map(|(m, e, _)| (NiceFloat(m), e)), Some((NiceFloat(mantissa), exponent)) ); assert!(exponent <= T::WIDTH); assert!(mantissa >= U::ONE); assert!(mantissa < U::TWO); }); } fn sci_mantissa_and_exponent_properties_helper_primitive_float() { primitive_float_gen_var_12::().test_properties(|x| { let (mantissa, exponent) = x.sci_mantissa_and_exponent(); assert_eq!(NiceFloat(x.sci_mantissa()), NiceFloat(mantissa)); assert_eq!(x.sci_exponent(), exponent); assert_eq!( NiceFloat(T::from_sci_mantissa_and_exponent(mantissa, exponent).unwrap()), NiceFloat(x.abs()) ); assert!(exponent >= T::MIN_EXPONENT); assert!(exponent <= T::MAX_EXPONENT); assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); let precision = x.precision(); assert_eq!(mantissa.precision(), precision); assert!(precision <= T::max_precision_for_sci_exponent(exponent)); }); } #[test] fn sci_mantissa_and_exponent_properties() { apply_fn_to_unsigneds_and_primitive_floats!( sci_mantissa_and_exponent_properties_helper_unsigned ); apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_properties_helper_primitive_float); } fn sci_mantissa_and_exponent_properties_round_helper() { unsigned_rounding_mode_pair_gen_var_1::().test_properties(|(x, rm)| { if let Some((mantissa, exponent, o)) = sci_mantissa_and_exponent_round::(x, rm) { assert!(mantissa >= U::ONE); assert!(mantissa < U::TWO); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!( sci_mantissa_and_exponent_round(x, rm), Some((mantissa, exponent, Equal)) ); } } else { assert!(sci_mantissa_and_exponent_round::(x, Exact).is_none(),); } } }); unsigned_gen_var_1::().test_properties(|n| { let (floor_mantissa, floor_exponent, o_floor) = sci_mantissa_and_exponent_round::(n, Floor).unwrap(); assert_ne!(o_floor, Greater); assert_eq!( sci_mantissa_and_exponent_round::(n, Down).unwrap(), (floor_mantissa, floor_exponent, o_floor) ); let (ceiling_mantissa, ceiling_exponent, o_ceiling) = sci_mantissa_and_exponent_round::(n, Ceiling).unwrap(); assert_ne!(o_ceiling, Less); assert_eq!( sci_mantissa_and_exponent_round::(n, Up).unwrap(), (ceiling_mantissa, ceiling_exponent, o_ceiling) ); let (nearest_mantissa, nearest_exponent, o_nearest) = sci_mantissa_and_exponent_round::(n, Nearest).unwrap(); if let Some((mantissa, exponent, o)) = sci_mantissa_and_exponent_round::(n, Exact) { assert_eq!(o, Equal); assert_eq!(floor_mantissa, mantissa); assert_eq!(ceiling_mantissa, mantissa); assert_eq!(nearest_mantissa, mantissa); assert_eq!(floor_exponent, exponent); assert_eq!(ceiling_exponent, exponent); assert_eq!(nearest_exponent, exponent); } else { assert_ne!( (floor_mantissa, floor_exponent), (ceiling_mantissa, ceiling_exponent) ); assert!( (nearest_mantissa, nearest_exponent, o_nearest) == (floor_mantissa, floor_exponent, Less) || (nearest_mantissa, nearest_exponent, o_nearest) == (ceiling_mantissa, ceiling_exponent, Greater) ); if ceiling_mantissa == U::ONE { assert_eq!(floor_mantissa, U::TWO.next_lower()); assert_eq!(floor_exponent, ceiling_exponent - 1); } else { assert_eq!(floor_mantissa, ceiling_mantissa.next_lower()); assert_eq!(floor_exponent, ceiling_exponent); } } }); } #[test] fn sci_mantissa_and_exponent_round_properties() { apply_fn_to_unsigneds_and_primitive_floats!(sci_mantissa_and_exponent_properties_round_helper); } fn from_sci_mantissa_and_exponent_properties_helper_unsigned< T: PrimitiveUnsigned + SciMantissaAndExponent, U: PrimitiveFloat, >() { primitive_float_unsigned_pair_gen_var_1::().test_properties(|(m, e)| { T::from_sci_mantissa_and_exponent(m, e); }); primitive_float_unsigned_pair_gen_var_2::().test_properties(|(m, e)| { assert!(m >= U::ONE && m < U::TWO); let on = T::from_sci_mantissa_and_exponent(m, e); assert_eq!( from_sci_mantissa_and_exponent_round(m, e, Nearest).map(|p| p.0), on ); }); } fn from_sci_mantissa_and_exponent_properties_helper_primitive_float() { primitive_float_signed_pair_gen_var_1().test_properties(|(mantissa, exponent)| { T::from_sci_mantissa_and_exponent(mantissa, exponent); }); primitive_float_signed_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { let f = T::from_sci_mantissa_and_exponent(mantissa, exponent).unwrap(); assert!(!f.is_nan()); assert_eq!(f.sign(), Greater); assert_eq!(f.sci_mantissa_and_exponent(), (mantissa, exponent)); }); } #[test] fn from_sci_mantissa_and_exponent_properties() { apply_fn_to_unsigneds_and_primitive_floats!( from_sci_mantissa_and_exponent_properties_helper_unsigned ); apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_properties_helper_primitive_float); } fn from_sci_mantissa_and_exponent_properties_round_helper< T: PrimitiveUnsigned, U: PrimitiveFloat, >() { primitive_float_unsigned_rounding_mode_triple_gen_var_1::().test_properties( |(m, e, rm)| { let on = from_sci_mantissa_and_exponent_round::(m, e, rm); if let Some((x, o)) = on { assert!(m >= U::ONE && m < U::TWO); if o == Equal { for rm in exhaustive_rounding_modes() { assert_eq!( from_sci_mantissa_and_exponent_round::(m, e, rm), Some((x, Equal)) ); } } else { assert!(from_sci_mantissa_and_exponent_round::(m, e, Exact).is_none()); } } }, ); primitive_float_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(m, e, rm)| { assert!(m >= U::ONE && m < U::TWO); from_sci_mantissa_and_exponent_round::(m, e, rm); }); primitive_float_unsigned_pair_gen_var_2::().test_properties(|(m, e)| { if let Some(ceiling_n) = from_sci_mantissa_and_exponent_round::(m, e, Ceiling) { assert_eq!( from_sci_mantissa_and_exponent_round::(m, e, Up).unwrap(), ceiling_n ); let floor_n = from_sci_mantissa_and_exponent_round::(m, e, Floor).unwrap(); assert_eq!( from_sci_mantissa_and_exponent_round::(m, e, Down).unwrap(), floor_n ); let nearest_n = from_sci_mantissa_and_exponent_round::(m, e, Nearest).unwrap(); if let Some(n) = from_sci_mantissa_and_exponent_round::(m, e, Exact) { assert_eq!(floor_n, n); assert_eq!(ceiling_n, n); assert_eq!(nearest_n, n); } else { assert!(nearest_n == floor_n || nearest_n == ceiling_n); if floor_n.0 != T::MAX { assert_eq!(ceiling_n.0, floor_n.0 + T::ONE); } } } }); } #[test] fn from_sci_mantissa_and_exponent_round_properties() { apply_fn_to_unsigneds_and_primitive_floats!( from_sci_mantissa_and_exponent_properties_round_helper ); } ================================================ FILE: malachite-base/tests/num/conversion/slice/from_other_type_slice.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{FromOtherTypeSlice, VecFromOtherTypeSlice}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; use std::fmt::Debug; #[test] pub fn test_from_other_type_slice() { fn test>(slice: &[T], n: U) { assert_eq!(U::from_other_type_slice(slice), n); } test::(&[], 0); test::(&[123], 123); test::(&[123, 456], 123); test::(&[0xab], 0xab); test::(&[0xab, 0xcd], 0xcdab); test::(&[0xab, 0xcd, 0xef], 0xcdab); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67], 0x67452301efcdab, ); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xff], 0x8967452301efcdab, ); test::(&[], 0); test::(&[0xabcd, 0xef01], 0xcd); test::(&[0x1234567890abcdef012345678909bcde], 0xde); } fn from_other_type_slice_helper< T: PrimitiveUnsigned + FromOtherTypeSlice + VecFromOtherTypeSlice, U: PrimitiveUnsigned, >() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << U::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |xs| { let value = T::from_other_type_slice(&xs); let ys = T::vec_from_other_type_slice(&xs); if xs.is_empty() { assert_eq!(value, T::ZERO); } else { assert_eq!(value, ys[0]); } }); } #[test] fn from_other_type_slice_properties() { apply_fn_to_unsigneds_and_unsigneds!(from_other_type_slice_helper); } ================================================ FILE: malachite-base/tests/num/conversion/slice/vec_from_other_type.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ FromOtherTypeSlice, VecFromOtherType, VecFromOtherTypeSlice, }; use malachite_base::test_util::generators::unsigned_gen; use std::fmt::Debug; #[test] pub fn test_vec_from_other_type() { fn test>(value: T, vec: &[U]) { assert_eq!(U::vec_from_other_type(value), vec); } test::(123, &[123]); test::(0xab, &[0xab]); test::(0xcdab, &[0xab, 0xcd]); } fn vec_from_other_type_helper< T: PrimitiveUnsigned + FromOtherTypeSlice, U: PrimitiveUnsigned + VecFromOtherType + VecFromOtherTypeSlice, >() { unsigned_gen::().test_properties(|x| { let xs = U::vec_from_other_type(x); assert_eq!(U::vec_from_other_type_slice(&[x]), xs); assert_eq!(T::from_other_type_slice(&xs), x); }); } #[test] fn vec_from_other_type_properties() { apply_fn_to_unsigneds_and_unsigneds!(vec_from_other_type_helper); } ================================================ FILE: malachite-base/tests/num/conversion/slice/vec_from_other_type_slice.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegModPowerOf2; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::VecFromOtherTypeSlice; use malachite_base::slices::slice_test_zero; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; use std::fmt::Debug; #[test] pub fn test_vec_from_other_type_slice() { fn test>(slice: &[T], vec: &[U]) { assert_eq!(U::vec_from_other_type_slice(slice), vec); } test::(&[123, 456], &[123, 456]); test::( &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xff], &[0xcdab, 0x01ef, 0x4523, 0x8967, 0xff], ); test::(&[0xab], &[0xab]); test::( &[0xcdab, 0x01ef, 0x4523, 0x8967], &[0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89], ); } fn vec_from_other_type_slice_helper< T: PrimitiveUnsigned + VecFromOtherTypeSlice, U: PrimitiveUnsigned + VecFromOtherTypeSlice, >() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << U::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |xs| { let ys = T::vec_from_other_type_slice(&xs); let xs_alt = U::vec_from_other_type_slice(&ys); if U::WIDTH >= T::WIDTH { assert_eq!(xs_alt, xs); } else { let number_of_extra_zeros = xs.len().neg_mod_power_of_2(T::LOG_WIDTH - U::LOG_WIDTH); let (xs_alt_lo, xs_alt_hi) = xs_alt.split_at(xs.len()); assert_eq!(xs_alt_hi.len(), number_of_extra_zeros); assert_eq!(xs_alt_lo, xs); assert!(slice_test_zero(xs_alt_hi)); } }); } #[test] fn vec_from_other_type_slice_properties() { apply_fn_to_unsigneds_and_unsigneds!(vec_from_other_type_slice_helper); } ================================================ FILE: malachite-base/tests/num/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, string_from_sci_string_options_pair_gen, string_from_sci_string_options_pair_gen_var_1, string_gen, string_gen_var_13, unsigned_gen, }; #[test] pub fn test_from_sci_string() { fn test(s: &str, out: Option) { assert_eq!(T::from_sci_string(s), out); assert_eq!( T::from_sci_string_with_options(s, FromSciStringOptions::default()), out ); } test::("0", Some(0)); test::("00", Some(0)); test::("+0", Some(0)); test::("-0", Some(0)); test::("0.00", Some(0)); test::("0e1", Some(0)); test::("0e+1", Some(0)); test::("0e-1", Some(0)); test::("+0e+1", Some(0)); test::("-0e+1", Some(0)); test::("+0.0e+1", Some(0)); test::("-0.0e+1", Some(0)); test::(".0", Some(0)); test::(".00", Some(0)); test::(".00e0", Some(0)); test::(".00e1", Some(0)); test::(".00e-1", Some(0)); test::("-.0", Some(0)); test::("-.00", Some(0)); test::("-.00e0", Some(0)); test::("-.00e1", Some(0)); test::("-.00e-1", Some(0)); test::("+.0", Some(0)); test::("+.00", Some(0)); test::("+.00e0", Some(0)); test::("+.00e1", Some(0)); test::("+.00e-1", Some(0)); test::("123", Some(123)); test::("00123", Some(123)); test::("+123", Some(123)); test::("123.00", Some(123)); test::("123e0", Some(123)); test::("12.3e1", Some(123)); test::("1.23e2", Some(123)); test::("1.23E2", Some(123)); test::("1.23e+2", Some(123)); test::("1.23E+2", Some(123)); test::(".123e3", Some(123)); test::("0.123e3", Some(123)); test::("+0.123e3", Some(123)); test::("0.0123e4", Some(123)); test::("1230e-1", Some(123)); test::("12300e-2", Some(123)); test::("12300E-2", Some(123)); test::("123.4", Some(123)); test::("123.8", Some(124)); test::("123.5", Some(124)); test::("124.5", Some(124)); test::("255.49", Some(255)); test::("255.5", None); test::("0.5", Some(0)); test::("0.51", Some(1)); test::("0.001", Some(0)); test::("1e-10", Some(0)); test::("-0.5", Some(0)); test::("-0.51", None); test::("-0.001", Some(0)); test::("-1e-10", Some(0)); test::("", None); test::("+", None); test::("-", None); test::("10e", None); test::("++1", None); test::("256", None); test::("-1", None); test::("1e10", None); test::("1.0.0", None); test::("1e++1", None); test::("1e0.1", None); test::("--.0", None); test::("++.0", None); test::("0.000a", None); test::("0.00ae-10", None); test::("0", Some(0)); test::("00", Some(0)); test::("+0", Some(0)); test::("-0", Some(0)); test::("0.00", Some(0)); test::("0e1", Some(0)); test::("0e+1", Some(0)); test::("0e-1", Some(0)); test::("+0e+1", Some(0)); test::("-0e+1", Some(0)); test::("+0.0e+1", Some(0)); test::("-0.0e+1", Some(0)); test::(".0", Some(0)); test::(".00", Some(0)); test::(".00e0", Some(0)); test::(".00e1", Some(0)); test::(".00e-1", Some(0)); test::("-.0", Some(0)); test::("-.00", Some(0)); test::("-.00e0", Some(0)); test::("-.00e1", Some(0)); test::("-.00e-1", Some(0)); test::("+.0", Some(0)); test::("+.00", Some(0)); test::("+.00e0", Some(0)); test::("+.00e1", Some(0)); test::("+.00e-1", Some(0)); test::("123", Some(123)); test::("00123", Some(123)); test::("+123", Some(123)); test::("123.00", Some(123)); test::("123e0", Some(123)); test::("12.3e1", Some(123)); test::("1.23e2", Some(123)); test::("1.23E2", Some(123)); test::("1.23e+2", Some(123)); test::("1.23E+2", Some(123)); test::(".123e3", Some(123)); test::("0.123e3", Some(123)); test::("+0.123e3", Some(123)); test::("0.0123e4", Some(123)); test::("1230e-1", Some(123)); test::("12300e-2", Some(123)); test::("12300E-2", Some(123)); test::("-123", Some(-123)); test::("-00123", Some(-123)); test::("-123.00", Some(-123)); test::("-123e0", Some(-123)); test::("-12.3e1", Some(-123)); test::("-1.23e2", Some(-123)); test::("-1.23E2", Some(-123)); test::("-1.23e+2", Some(-123)); test::("-1.23E+2", Some(-123)); test::("-.123e3", Some(-123)); test::("-0.123e3", Some(-123)); test::("-0.0123e4", Some(-123)); test::("-1230e-1", Some(-123)); test::("-12300e-2", Some(-123)); test::("-12300E-2", Some(-123)); test::("123.4", Some(123)); test::("123.8", Some(124)); test::("123.5", Some(124)); test::("124.5", Some(124)); test::("127.49", Some(127)); test::("127.5", None); test::("-123.4", Some(-123)); test::("-123.8", Some(-124)); test::("-123.5", Some(-124)); test::("-124.5", Some(-124)); test::("-127.49", Some(-127)); test::("-127.5", Some(-128)); test::("-128.51", None); test::("", None); test::("+", None); test::("-", None); test::("10e", None); test::("++1", None); test::("128", None); test::("-129", None); test::("1e10", None); test::("1.0.0", None); test::("1e++1", None); test::("1e0.1", None); test::("--.0", None); test::("++.0", None); test::(".+2", None); test::(".-2", None); test::("0.000a", None); test::("0.00ae-10", None); test::("0e10000000000000000000000000000", None); test::("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option) { assert_eq!(T::from_sci_string_with_options(s, options), out); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test::( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test::( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test::( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test::( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test::( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test::("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test::("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test::("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test::( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test::( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test::( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test::( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test::( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test::( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test::( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test::( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test::( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test::( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test::("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test::( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test::("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test::("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test::("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test::("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test::("1e+5", options, Some(32)); test::("1e5", options, Some(32)); options.set_base(3); test::("1e+5", options, Some(243)); test::("1e5", options, Some(243)); options.set_base(4); test::("1e+5", options, Some(1024)); test::("1e5", options, Some(1024)); options.set_base(5); test::("1e+5", options, Some(3125)); test::("1e5", options, Some(3125)); options.set_base(8); test::("1e+5", options, Some(32768)); test::("1e5", options, Some(32768)); options.set_base(16); test::("1e+5", options, Some(1048576)); test::("1e5", options, Some(485)); options.set_base(32); test::("1e+5", options, Some(33554432)); test::("1e5", options, Some(1477)); options.set_base(36); test::("1e+5", options, Some(60466176)); test::("1E+5", options, Some(60466176)); test::("1e5", options, Some(1805)); options.set_base(16); test::("ff", options, Some(255)); test::("fF", options, Some(255)); test::("Ff", options, Some(255)); test::("FF", options, Some(255)); options = FromSciStringOptions::default(); options.set_rounding_mode(Down); test::("123.4", options, Some(123)); options.set_rounding_mode(Floor); test::("123.4", options, Some(123)); options.set_rounding_mode(Up); test::("123.4", options, Some(124)); options.set_rounding_mode(Ceiling); test::("123.4", options, Some(124)); options.set_rounding_mode(Nearest); test::("123.4", options, Some(123)); options.set_rounding_mode(Exact); test::("123.4", options, None); options.set_rounding_mode(Down); test::("123.5", options, Some(123)); options.set_rounding_mode(Floor); test::("123.5", options, Some(123)); options.set_rounding_mode(Up); test::("123.5", options, Some(124)); options.set_rounding_mode(Ceiling); test::("123.5", options, Some(124)); options.set_rounding_mode(Nearest); test::("123.5", options, Some(124)); options.set_rounding_mode(Exact); test::("123.5", options, None); options.set_rounding_mode(Down); test::("0.4", options, Some(0)); options.set_rounding_mode(Floor); test::("0.4", options, Some(0)); options.set_rounding_mode(Up); test::("0.4", options, Some(1)); options.set_rounding_mode(Ceiling); test::("0.4", options, Some(1)); options.set_rounding_mode(Nearest); test::("0.4", options, Some(0)); options.set_rounding_mode(Exact); test::("0.4", options, None); options.set_rounding_mode(Down); test::("0.04", options, Some(0)); options.set_rounding_mode(Floor); test::("0.04", options, Some(0)); options.set_rounding_mode(Up); test::("0.04", options, Some(1)); options.set_rounding_mode(Ceiling); test::("0.04", options, Some(1)); options.set_rounding_mode(Nearest); test::("0.04", options, Some(0)); options.set_rounding_mode(Exact); test::("0.04", options, None); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test::("1.01", options, Some(1)); test::("1.1", options, Some(2)); test::("1.11", options, Some(2)); test::("0.01", options, Some(0)); test::("0.1", options, Some(0)); test::("0.11", options, Some(1)); options.set_base(3); // 1/2 is 0.111... test::("1.1", options, Some(1)); test::("1.11", options, Some(1)); test::("1.111", options, Some(1)); test::("1.112", options, Some(2)); test::("0.1", options, Some(0)); test::("0.11", options, Some(0)); test::("0.111", options, Some(0)); test::("0.112", options, Some(1)); options = FromSciStringOptions::default(); options.set_base(2); test::("2", options, None); test::("102", options, None); test::("12e4", options, None); test::("12e-4", options, None); test::("1.2", options, None); test::("0.2", options, None); test::("0.002", options, None); options = FromSciStringOptions::default(); options.set_rounding_mode(Exact); test::("1.5", options, None); test::("1.9999999999999999999999999999", options, None); options.set_base(2); test::( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test::( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test::( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test::( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test::( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test::( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test::( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test::( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test::( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test::( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test::("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test::( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test::("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test::("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test::("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test::("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test::("1e+5", options, Some(32)); test::("1e5", options, Some(32)); options.set_base(3); test::("1e+5", options, Some(243)); test::("1e5", options, Some(243)); options.set_base(4); test::("1e+5", options, Some(1024)); test::("1e5", options, Some(1024)); options.set_base(5); test::("1e+5", options, Some(3125)); test::("1e5", options, Some(3125)); options.set_base(8); test::("1e+5", options, Some(32768)); test::("1e5", options, Some(32768)); options.set_base(16); test::("1e+5", options, Some(1048576)); test::("1e5", options, Some(485)); options.set_base(32); test::("1e+5", options, Some(33554432)); test::("1e5", options, Some(1477)); options.set_base(36); test::("1e+5", options, Some(60466176)); test::("1E+5", options, Some(60466176)); test::("1e5", options, Some(1805)); options.set_base(2); test::("-1e+5", options, Some(-32)); test::("-1e5", options, Some(-32)); options.set_base(3); test::("-1e+5", options, Some(-243)); test::("-1e5", options, Some(-243)); options.set_base(4); test::("-1e+5", options, Some(-1024)); test::("-1e5", options, Some(-1024)); options.set_base(5); test::("-1e+5", options, Some(-3125)); test::("-1e5", options, Some(-3125)); options.set_base(8); test::("-1e+5", options, Some(-32768)); test::("-1e5", options, Some(-32768)); options.set_base(16); test::("-1e+5", options, Some(-1048576)); test::("-1e5", options, Some(-485)); options.set_base(32); test::("-1e+5", options, Some(-33554432)); test::("-1e5", options, Some(-1477)); options.set_base(36); test::("-1e+5", options, Some(-60466176)); test::("-1E+5", options, Some(-60466176)); test::("-1e5", options, Some(-1805)); options.set_base(16); test::("ff", options, Some(255)); test::("fF", options, Some(255)); test::("Ff", options, Some(255)); test::("FF", options, Some(255)); test::("-ff", options, Some(-255)); test::("-fF", options, Some(-255)); test::("-Ff", options, Some(-255)); test::("-FF", options, Some(-255)); options = FromSciStringOptions::default(); options.set_rounding_mode(Down); test::("123.4", options, Some(123)); options.set_rounding_mode(Floor); test::("123.4", options, Some(123)); options.set_rounding_mode(Up); test::("123.4", options, Some(124)); options.set_rounding_mode(Ceiling); test::("123.4", options, Some(124)); options.set_rounding_mode(Nearest); test::("123.4", options, Some(123)); options.set_rounding_mode(Exact); test::("123.4", options, None); options.set_rounding_mode(Down); test::("-123.4", options, Some(-123)); options.set_rounding_mode(Floor); test::("-123.4", options, Some(-124)); options.set_rounding_mode(Up); test::("-123.4", options, Some(-124)); options.set_rounding_mode(Ceiling); test::("-123.4", options, Some(-123)); options.set_rounding_mode(Nearest); test::("-123.4", options, Some(-123)); options.set_rounding_mode(Exact); test::("-123.4", options, None); options.set_rounding_mode(Down); test::("123.5", options, Some(123)); options.set_rounding_mode(Floor); test::("123.5", options, Some(123)); options.set_rounding_mode(Up); test::("123.5", options, Some(124)); options.set_rounding_mode(Ceiling); test::("123.5", options, Some(124)); options.set_rounding_mode(Nearest); test::("123.5", options, Some(124)); options.set_rounding_mode(Exact); test::("123.5", options, None); options.set_rounding_mode(Down); test::("-123.5", options, Some(-123)); options.set_rounding_mode(Floor); test::("-123.5", options, Some(-124)); options.set_rounding_mode(Up); test::("-123.5", options, Some(-124)); options.set_rounding_mode(Ceiling); test::("-123.5", options, Some(-123)); options.set_rounding_mode(Nearest); test::("-123.5", options, Some(-124)); options.set_rounding_mode(Exact); test::("-123.5", options, None); options.set_rounding_mode(Down); test::("0.4", options, Some(0)); options.set_rounding_mode(Floor); test::("0.4", options, Some(0)); options.set_rounding_mode(Up); test::("0.4", options, Some(1)); options.set_rounding_mode(Ceiling); test::("0.4", options, Some(1)); options.set_rounding_mode(Nearest); test::("0.4", options, Some(0)); options.set_rounding_mode(Exact); test::("0.4", options, None); options.set_rounding_mode(Down); test::("-0.4", options, Some(0)); options.set_rounding_mode(Floor); test::("-0.4", options, Some(-1)); options.set_rounding_mode(Up); test::("-0.4", options, Some(-1)); options.set_rounding_mode(Ceiling); test::("-0.4", options, Some(0)); options.set_rounding_mode(Nearest); test::("-0.4", options, Some(0)); options.set_rounding_mode(Exact); test::("-0.4", options, None); options.set_rounding_mode(Down); test::("0.04", options, Some(0)); options.set_rounding_mode(Floor); test::("0.04", options, Some(0)); options.set_rounding_mode(Up); test::("0.04", options, Some(1)); options.set_rounding_mode(Ceiling); test::("0.04", options, Some(1)); options.set_rounding_mode(Nearest); test::("0.04", options, Some(0)); options.set_rounding_mode(Exact); test::("0.04", options, None); options.set_rounding_mode(Down); test::("-0.04", options, Some(0)); options.set_rounding_mode(Floor); test::("-0.04", options, Some(-1)); options.set_rounding_mode(Up); test::("-0.04", options, Some(-1)); options.set_rounding_mode(Ceiling); test::("-0.04", options, Some(0)); options.set_rounding_mode(Nearest); test::("-0.04", options, Some(0)); options.set_rounding_mode(Exact); test::("-0.04", options, None); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test::("1.01", options, Some(1)); test::("1.1", options, Some(2)); test::("1.11", options, Some(2)); test::("0.01", options, Some(0)); test::("0.1", options, Some(0)); test::("0.11", options, Some(1)); test::("-1.01", options, Some(-1)); test::("-1.1", options, Some(-2)); test::("-1.11", options, Some(-2)); test::("-0.01", options, Some(0)); test::("-0.1", options, Some(0)); test::("-0.11", options, Some(-1)); options.set_base(3); // 1/2 is 0.111... test::("1.1", options, Some(1)); test::("1.11", options, Some(1)); test::("1.111", options, Some(1)); test::("1.112", options, Some(2)); test::("0.1", options, Some(0)); test::("0.11", options, Some(0)); test::("0.111", options, Some(0)); test::("0.112", options, Some(1)); test::("-1.1", options, Some(-1)); test::("-1.11", options, Some(-1)); test::("-1.111", options, Some(-1)); test::("-1.112", options, Some(-2)); test::("-0.1", options, Some(0)); test::("-0.11", options, Some(0)); test::("-0.111", options, Some(0)); test::("-0.112", options, Some(-1)); options = FromSciStringOptions::default(); options.set_base(2); test::("2", options, None); test::("102", options, None); test::("12e4", options, None); test::("12e-4", options, None); test::("1.2", options, None); test::("0.2", options, None); test::("0.002", options, None); test::("-2", options, None); test::("-102", options, None); test::("-12e4", options, None); test::("-12e-4", options, None); test::("-1.2", options, None); test::("-0.2", options, None); test::("-0.002", options, None); options.set_base(25); options.set_rounding_mode(Ceiling); test::(".be.2", options, None); options = FromSciStringOptions::default(); options.set_rounding_mode(Exact); test::("1.5", options, None); test::("1.9999999999999999999999999999", options, None); test::("-1.5", options, None); test::("-1.9999999999999999999999999999", options, None); } fn from_sci_string_helper_helper(s: &str) { if let Some(x) = T::from_sci_string(s) { assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string(), s); } } fn from_sci_string_helper() { string_gen().test_properties(|s| { from_sci_string_helper_helper::(&s); }); string_gen_var_13().test_properties(|s| { from_sci_string_helper_helper::(&s); }); } fn from_sci_string_helper_unsigned() { unsigned_gen::().test_properties(|x| { assert_eq!(T::from_sci_string(&x.to_string()).unwrap(), x); }); } fn from_sci_string_helper_signed() { signed_gen::().test_properties(|x| { assert_eq!(T::from_sci_string(&x.to_string()).unwrap(), x); }); } #[test] fn from_sci_string_properties() { apply_fn_to_primitive_ints!(from_sci_string_helper); apply_fn_to_unsigneds!(from_sci_string_helper_unsigned); apply_fn_to_signeds!(from_sci_string_helper_signed); } fn from_sci_string_with_options_helper_helper( s: &str, options: FromSciStringOptions, ) { if let Some(x) = T::from_sci_string_with_options(s, options) { assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string_base(options.get_base()), s.to_lowercase()); } } fn from_sci_string_with_options_helper() { string_from_sci_string_options_pair_gen().test_properties(|(s, options)| { from_sci_string_with_options_helper_helper::(&s, options); }); string_from_sci_string_options_pair_gen_var_1().test_properties(|(s, options)| { from_sci_string_with_options_helper_helper::(&s, options); }); } #[test] fn from_sci_string_with_options_properties() { apply_fn_to_primitive_ints!(from_sci_string_with_options_helper); } ================================================ FILE: malachite-base/tests/num/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::string::from_string::digit_from_display_byte; use malachite_base::num::conversion::string::to_string::{ digit_to_display_byte_lower, digit_to_display_byte_upper, }; use malachite_base::test_util::generators::{unsigned_gen, unsigned_gen_var_10}; #[test] fn test_digit_from_display_byte() { let test_ok = |x, y| { assert_eq!(digit_from_display_byte(x).unwrap(), y); }; test_ok(b'0', 0); test_ok(b'1', 1); test_ok(b'2', 2); test_ok(b'3', 3); test_ok(b'4', 4); test_ok(b'5', 5); test_ok(b'6', 6); test_ok(b'7', 7); test_ok(b'8', 8); test_ok(b'9', 9); test_ok(b'a', 10); test_ok(b'b', 11); test_ok(b'c', 12); test_ok(b'x', 33); test_ok(b'y', 34); test_ok(b'z', 35); test_ok(b'A', 10); test_ok(b'B', 11); test_ok(b'C', 12); test_ok(b'X', 33); test_ok(b'Y', 34); test_ok(b'Z', 35); let test_err = |x| { assert!(digit_from_display_byte(x).is_none()); }; test_err(b' '); test_err(b'!'); } #[test] fn digit_from_display_byte_properties() { unsigned_gen().test_properties(|b| { assert_eq!( digit_from_display_byte(b).is_some(), b.is_ascii_alphanumeric() ); }); unsigned_gen_var_10().test_properties(|b| { let digit = digit_from_display_byte(b).unwrap(); assert!(b.is_ascii_alphanumeric()); // Both of the following conditions include numeric chars. if !char::from(b).is_uppercase() { assert_eq!(digit_to_display_byte_lower(digit), Some(b)); } if !char::from(b).is_lowercase() { assert_eq!(digit_to_display_byte_upper(digit), Some(b)); } }); } ================================================ FILE: malachite-base/tests/num/conversion/string/options/from_sci_string_options.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::{ from_sci_string_options_gen, from_sci_string_options_rounding_mode_pair_gen, from_sci_string_options_unsigned_pair_gen_var_1, }; #[test] fn from_sci_string_options_properties() { from_sci_string_options_gen().test_properties(|options| { let mut options_alt = options; let base = options.get_base(); assert!(base >= 2); assert!(base <= 36); options_alt.set_base(base); assert_eq!(options_alt, options); let rounding_mode = options.get_rounding_mode(); options_alt.set_rounding_mode(rounding_mode); assert_eq!(options_alt, options); }); from_sci_string_options_unsigned_pair_gen_var_1().test_properties(|(mut options, base)| { let old_options = options; let old_base = options.get_base(); options.set_base(base); assert_eq!(options.get_base(), base); options.set_base(old_base); assert_eq!(options, old_options); }); from_sci_string_options_rounding_mode_pair_gen().test_properties(|(mut options, rm)| { let old_options = options; let old_rm = options.get_rounding_mode(); options.set_rounding_mode(rm); assert_eq!(options.get_rounding_mode(), rm); options.set_rounding_mode(old_rm); assert_eq!(options, old_options); }); } ================================================ FILE: malachite-base/tests/num/conversion/string/options/to_sci_options.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::string::options::SciSizeOptions; use malachite_base::test_util::generators::{ to_sci_options_bool_pair_gen, to_sci_options_gen, to_sci_options_rounding_mode_pair_gen, to_sci_options_signed_pair_gen_var_1, to_sci_options_unsigned_pair_gen_var_1, to_sci_options_unsigned_pair_gen_var_2, to_sci_options_unsigned_pair_gen_var_3, }; #[test] fn to_sci_options_properties() { to_sci_options_gen().test_properties(|options| { let mut options_alt = options; let base = options.get_base(); assert!(base >= 2); assert!(base <= 36); options_alt.set_base(base); assert_eq!(options_alt, options); let rounding_mode = options.get_rounding_mode(); options_alt.set_rounding_mode(rounding_mode); assert_eq!(options_alt, options); let size_options = options.get_size_options(); match size_options { SciSizeOptions::Complete => options_alt.set_size_complete(), SciSizeOptions::Precision(p) => options_alt.set_precision(p), SciSizeOptions::Scale(s) => options_alt.set_scale(s), } assert_eq!(options_alt, options); let neg_exp_threshold = options.get_neg_exp_threshold(); assert!(neg_exp_threshold < 0); options_alt.set_neg_exp_threshold(neg_exp_threshold); assert_eq!(options_alt, options); let lowercase = options.get_lowercase(); if lowercase { options_alt.set_lowercase(); } else { options_alt.set_uppercase(); } assert_eq!(options_alt, options); let e_lowercase = options.get_e_lowercase(); if e_lowercase { options_alt.set_e_lowercase(); } else { options_alt.set_e_uppercase(); } assert_eq!(options_alt, options); let force_exponent_plus_sign = options.get_force_exponent_plus_sign(); options_alt.set_force_exponent_plus_sign(force_exponent_plus_sign); assert_eq!(options_alt, options); let include_trailing_zeros = options.get_include_trailing_zeros(); options_alt.set_include_trailing_zeros(include_trailing_zeros); assert_eq!(options_alt, options); let mut options = options; let old_options = options; let old_lowercase = options.get_lowercase(); options.set_lowercase(); assert!(options.get_lowercase()); if old_lowercase { options.set_lowercase(); } else { options.set_uppercase(); } assert_eq!(options, old_options); let old_lowercase = options.get_lowercase(); options.set_uppercase(); assert!(!options.get_lowercase()); if old_lowercase { options.set_lowercase(); } else { options.set_uppercase(); } assert_eq!(options, old_options); let old_e_lowercase = options.get_e_lowercase(); options.set_e_lowercase(); assert!(options.get_e_lowercase()); if old_e_lowercase { options.set_e_lowercase(); } else { options.set_e_uppercase(); } assert_eq!(options, old_options); let old_e_lowercase = options.get_e_lowercase(); options.set_e_uppercase(); assert!(!options.get_e_lowercase()); if old_e_lowercase { options.set_e_lowercase(); } else { options.set_e_uppercase(); } assert_eq!(options, old_options); }); to_sci_options_unsigned_pair_gen_var_1().test_properties(|(mut options, base)| { let old_options = options; let old_base = options.get_base(); options.set_base(base); assert_eq!(options.get_base(), base); options.set_base(old_base); assert_eq!(options, old_options); }); to_sci_options_rounding_mode_pair_gen().test_properties(|(mut options, rm)| { let old_options = options; let old_rm = options.get_rounding_mode(); options.set_rounding_mode(rm); assert_eq!(options.get_rounding_mode(), rm); options.set_rounding_mode(old_rm); assert_eq!(options, old_options); }); to_sci_options_gen().test_properties(|mut options| { let old_options = options; let old_size_options = options.get_size_options(); options.set_size_complete(); assert_eq!(options.get_size_options(), SciSizeOptions::Complete); match old_size_options { SciSizeOptions::Complete => options.set_size_complete(), SciSizeOptions::Precision(p) => options.set_precision(p), SciSizeOptions::Scale(s) => options.set_scale(s), } assert_eq!(options, old_options); }); to_sci_options_unsigned_pair_gen_var_3().test_properties(|(mut options, precision)| { let old_options = options; let old_size_options = options.get_size_options(); options.set_precision(precision); assert_eq!( options.get_size_options(), SciSizeOptions::Precision(precision) ); match old_size_options { SciSizeOptions::Complete => options.set_size_complete(), SciSizeOptions::Precision(p) => options.set_precision(p), SciSizeOptions::Scale(s) => options.set_scale(s), } assert_eq!(options, old_options); }); to_sci_options_unsigned_pair_gen_var_2().test_properties(|(mut options, scale)| { let old_options = options; let old_size_options = options.get_size_options(); options.set_scale(scale); assert_eq!(options.get_size_options(), SciSizeOptions::Scale(scale)); match old_size_options { SciSizeOptions::Complete => options.set_size_complete(), SciSizeOptions::Precision(p) => options.set_precision(p), SciSizeOptions::Scale(s) => options.set_scale(s), } assert_eq!(options, old_options); }); to_sci_options_signed_pair_gen_var_1().test_properties(|(mut options, neg_exp_threshold)| { let old_options = options; let old_neg_exp_threshold = options.get_neg_exp_threshold(); options.set_neg_exp_threshold(neg_exp_threshold); assert_eq!(options.get_neg_exp_threshold(), neg_exp_threshold); options.set_neg_exp_threshold(old_neg_exp_threshold); assert_eq!(options, old_options); }); to_sci_options_bool_pair_gen().test_properties(|(mut options, b)| { let old_options = options; let old_force_exponent_plus_sign = options.get_force_exponent_plus_sign(); options.set_force_exponent_plus_sign(b); assert_eq!(options.get_force_exponent_plus_sign(), b); options.set_force_exponent_plus_sign(old_force_exponent_plus_sign); assert_eq!(options, old_options); let old_include_trailing_zeros = options.get_include_trailing_zeros(); options.set_include_trailing_zeros(b); assert_eq!(options.get_include_trailing_zeros(), b); options.set_include_trailing_zeros(old_include_trailing_zeros); assert_eq!(options, old_options); }); } ================================================ FILE: malachite-base/tests/num/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{FloorLogBase, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::{ FromSciStringOptions, SciSizeOptions, ToSciOptions, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{ signed_gen, signed_to_sci_options_pair_gen_var_1, unsigned_gen, unsigned_to_sci_options_pair_gen_var_1, }; use malachite_base::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use std::collections::HashMap; use std::panic::catch_unwind; #[test] pub fn test_to_sci() { fn test(x: T, out: &str) { assert_eq!(x.to_sci().to_string(), out); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), out ); } test::(0, "0"); test::(1, "1"); test::(10, "10"); test::(100, "100"); test::(1000, "1000"); test::(10000, "10000"); test::(100000, "100000"); test::(1000000, "1000000"); test::(10000000, "10000000"); test::(100000000, "100000000"); test::(1000000000, "1000000000"); test::(10000000000, "10000000000"); test::(100000000000, "100000000000"); test::(1000000000000, "1000000000000"); test::(10000000000000, "10000000000000"); test::(100000000000000, "100000000000000"); test::(1000000000000000, "1000000000000000"); test::(10000000000000000, "1e16"); test::(100000000000000000, "1e17"); test::(u64::MAX, "1.844674407370955e19"); test::(u128::MAX, "3.402823669209385e38"); test::(999999999999999, "999999999999999"); test::(9999999999999999, "9999999999999999"); test::(99999999999999999, "1e17"); test::(999999999999999999, "1e18"); test::(0, "0"); test::(1, "1"); test::(10, "10"); test::(100, "100"); test::(1000, "1000"); test::(10000, "10000"); test::(100000, "100000"); test::(1000000, "1000000"); test::(10000000, "10000000"); test::(100000000, "100000000"); test::(1000000000, "1000000000"); test::(10000000000, "10000000000"); test::(100000000000, "100000000000"); test::(1000000000000, "1000000000000"); test::(10000000000000, "10000000000000"); test::(100000000000000, "100000000000000"); test::(1000000000000000, "1000000000000000"); test::(10000000000000000, "1e16"); test::(100000000000000000, "1e17"); test::(i64::MAX, "9.223372036854776e18"); test::(i128::MAX, "1.701411834604692e38"); test::(-1, "-1"); test::(-10, "-10"); test::(-100, "-100"); test::(-1000, "-1000"); test::(-10000, "-10000"); test::(-100000, "-100000"); test::(-1000000, "-1000000"); test::(-10000000, "-10000000"); test::(-100000000, "-100000000"); test::(-1000000000, "-1000000000"); test::(-10000000000, "-10000000000"); test::(-100000000000, "-100000000000"); test::(-1000000000000, "-1000000000000"); test::(-10000000000000, "-10000000000000"); test::(-100000000000000, "-100000000000000"); test::(-1000000000000000, "-1000000000000000"); test::(-10000000000000000, "-1e16"); test::(-100000000000000000, "-1e17"); test::(i64::MIN, "-9.223372036854776e18"); test::(i128::MIN, "-1.701411834604692e38"); test::(999999999999999, "999999999999999"); test::(9999999999999999, "9999999999999999"); test::(99999999999999999, "1e17"); test::(999999999999999999, "1e18"); } #[test] pub fn test_to_sci_with_options() { fn test(x: T, options: ToSciOptions, out: &str) { assert_eq!(x.to_sci_with_options(options).to_string(), out); } // For tests with the default options, see `test_to_sci` let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test::(0, options, "0.000000000000000"); test::(1, options, "1.000000000000000"); test::(10, options, "10.00000000000000"); test::(100, options, "100.0000000000000"); test::(1000, options, "1000.000000000000"); test::(10000, options, "10000.00000000000"); test::(100000, options, "100000.0000000000"); test::(1000000, options, "1000000.000000000"); test::(10000000, options, "10000000.00000000"); test::(100000000, options, "100000000.0000000"); test::(1000000000, options, "1000000000.000000"); test::(10000000000, options, "10000000000.00000"); test::(100000000000, options, "100000000000.0000"); test::(1000000000000, options, "1000000000000.000"); test::(10000000000000, options, "10000000000000.00"); test::(100000000000000, options, "100000000000000.0"); test::(1000000000000000, options, "1000000000000000"); test::(10000000000000000, options, "1.000000000000000e16"); test::(100000000000000000, options, "1.000000000000000e17"); test::(u64::MAX, options, "1.844674407370955e19"); test::(u128::MAX, options, "3.402823669209385e38"); test::(999999999999999, options, "999999999999999.0"); test::(9999999999999999, options, "9999999999999999"); test::(99999999999999999, options, "1.000000000000000e17"); test::(999999999999999999, options, "1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test::(u128::MAX, options, "1e128"); options.set_base(3); test::(u128::MAX, options, "2.022011021210021e80"); options.set_base(4); test::(u128::MAX, options, "1e64"); options.set_base(5); test::(u128::MAX, options, "1.103111044120131e55"); options.set_base(8); test::(u128::MAX, options, "4e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test::(u128::MAX, options, "1e+32"); options.set_base(32); test::(u128::MAX, options, "8e+25"); options.set_base(36); test::(u128::MAX, options, "f.5lxx1zz5pnorynqe+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test::(u128::MAX, options, "2.022011021210021e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test::(u128::MAX, options, "F.5LXX1ZZ5PNORYNQe+24"); options.set_lowercase(); options.set_e_uppercase(); test::(u128::MAX, options, "f.5lxx1zz5pnorynqE+24"); options.set_uppercase(); test::(u128::MAX, options, "F.5LXX1ZZ5PNORYNQE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test::( u128::MAX, options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", ); options.set_base(3); test::( u128::MAX, options, "202201102121002021012000211012011021221022212021111001022110211020010021100121010", ); options.set_base(4); test::( u128::MAX, options, "3333333333333333333333333333333333333333333333333333333333333333", ); options.set_base(5); test::( u128::MAX, options, "11031110441201303134210404233413032443021130230130231310", ); options.set_base(8); test::( u128::MAX, options, "3777777777777777777777777777777777777777777", ); options.set_base(16); test::(u128::MAX, options, "ffffffffffffffffffffffffffffffff"); options.set_base(32); test::(u128::MAX, options, "7vvvvvvvvvvvvvvvvvvvvvvvvv"); options.set_base(36); test::(u128::MAX, options, "f5lxx1zz5pnorynqglhzmsp33"); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test::(0, options, "0.000"); test::(1, options, "1.000"); test::(10, options, "10.00"); test::(100, options, "100.0"); test::(1000, options, "1000"); test::(10000, options, "1.000e4"); test::(9, options, "9.000"); test::(99, options, "99.00"); test::(999, options, "999.0"); test::(9999, options, "9999"); test::(99999, options, "1.000e5"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "1e4"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "1e1"); test::(100, options, "1e2"); test::(1000, options, "1e3"); test::(10000, options, "1e4"); test::(9, options, "9"); test::(99, options, "1e2"); test::(999, options, "1e3"); test::(9999, options, "1e4"); test::(99999, options, "1e5"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "1e1"); test::(100, options, "1e2"); test::(1000, options, "1e3"); test::(10000, options, "1e4"); test::(9, options, "9"); test::(99, options, "1e2"); test::(999, options, "1e3"); test::(9999, options, "1e4"); test::(99999, options, "1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test::(0, options, "0.00"); test::(1, options, "1.00"); test::(10, options, "10.00"); test::(100, options, "100.00"); test::(1000, options, "1000.00"); test::(10000, options, "10000.00"); test::(9, options, "9.00"); test::(99, options, "99.00"); test::(999, options, "999.00"); test::(9999, options, "9999.00"); test::(99999, options, "99999.00"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test::(123, options, "1.2e2"); options.set_rounding_mode(Down); test::(123, options, "1.2e2"); options.set_rounding_mode(Floor); test::(123, options, "1.2e2"); options.set_rounding_mode(Up); test::(123, options, "1.3e2"); options.set_rounding_mode(Ceiling); test::(123, options, "1.3e2"); options.set_rounding_mode(Nearest); test::(135, options, "1.4e2"); options.set_rounding_mode(Down); test::(135, options, "1.3e2"); options.set_rounding_mode(Floor); test::(135, options, "1.3e2"); options.set_rounding_mode(Up); test::(135, options, "1.4e2"); options.set_rounding_mode(Ceiling); test::(135, options, "1.4e2"); options.set_rounding_mode(Exact); test::(140, options, "1.4e2"); options.set_rounding_mode(Nearest); test::(999, options, "1e3"); options.set_rounding_mode(Down); test::(999, options, "9.9e2"); options.set_rounding_mode(Floor); test::(999, options, "9.9e2"); options.set_rounding_mode(Up); test::(999, options, "1e3"); options.set_rounding_mode(Ceiling); test::(999, options, "1e3"); let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test::(0, options, "0.000000000000000"); test::(1, options, "1.000000000000000"); test::(10, options, "10.00000000000000"); test::(100, options, "100.0000000000000"); test::(1000, options, "1000.000000000000"); test::(10000, options, "10000.00000000000"); test::(100000, options, "100000.0000000000"); test::(1000000, options, "1000000.000000000"); test::(10000000, options, "10000000.00000000"); test::(100000000, options, "100000000.0000000"); test::(1000000000, options, "1000000000.000000"); test::(10000000000, options, "10000000000.00000"); test::(100000000000, options, "100000000000.0000"); test::(1000000000000, options, "1000000000000.000"); test::(10000000000000, options, "10000000000000.00"); test::(100000000000000, options, "100000000000000.0"); test::(1000000000000000, options, "1000000000000000"); test::(10000000000000000, options, "1.000000000000000e16"); test::(100000000000000000, options, "1.000000000000000e17"); test::(i64::MAX, options, "9.223372036854776e18"); test::(i128::MAX, options, "1.701411834604692e38"); test::(-1, options, "-1.000000000000000"); test::(-10, options, "-10.00000000000000"); test::(-100, options, "-100.0000000000000"); test::(-1000, options, "-1000.000000000000"); test::(-10000, options, "-10000.00000000000"); test::(-100000, options, "-100000.0000000000"); test::(-1000000, options, "-1000000.000000000"); test::(-10000000, options, "-10000000.00000000"); test::(-100000000, options, "-100000000.0000000"); test::(-1000000000, options, "-1000000000.000000"); test::(-10000000000, options, "-10000000000.00000"); test::(-100000000000, options, "-100000000000.0000"); test::(-1000000000000, options, "-1000000000000.000"); test::(-10000000000000, options, "-10000000000000.00"); test::(-100000000000000, options, "-100000000000000.0"); test::(-1000000000000000, options, "-1000000000000000"); test::(-10000000000000000, options, "-1.000000000000000e16"); test::(-100000000000000000, options, "-1.000000000000000e17"); test::(i64::MIN, options, "-9.223372036854776e18"); test::(i128::MIN, options, "-1.701411834604692e38"); test::(999999999999999, options, "999999999999999.0"); test::(9999999999999999, options, "9999999999999999"); test::(99999999999999999, options, "1.000000000000000e17"); test::(999999999999999999, options, "1.000000000000000e18"); test::(-999999999999999, options, "-999999999999999.0"); test::(-9999999999999999, options, "-9999999999999999"); test::(-99999999999999999, options, "-1.000000000000000e17"); test::(-999999999999999999, options, "-1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test::(i128::MAX, options, "1e127"); test::(i128::MIN, options, "-1e127"); options.set_base(3); test::(i128::MAX, options, "1.01100201022001e80"); test::(i128::MIN, options, "-1.01100201022001e80"); options.set_base(4); test::(i128::MAX, options, "2e63"); test::(i128::MIN, options, "-2e63"); options.set_base(5); test::(i128::MAX, options, "3.013030220323124e54"); test::(i128::MIN, options, "-3.013030220323124e54"); options.set_base(8); test::(i128::MAX, options, "2e42"); test::(i128::MIN, options, "-2e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test::(i128::MAX, options, "8e+31"); test::(i128::MIN, options, "-8e+31"); options.set_base(32); test::(i128::MAX, options, "4e+25"); test::(i128::MIN, options, "-4e+25"); options.set_base(36); test::(i128::MAX, options, "7.ksyyizzkutudzbve+24"); test::(i128::MIN, options, "-7.ksyyizzkutudzbve+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test::(i128::MAX, options, "1.01100201022001e+80"); test::(i128::MIN, options, "-1.01100201022001e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test::(i128::MAX, options, "7.KSYYIZZKUTUDZBVe+24"); test::(i128::MIN, options, "-7.KSYYIZZKUTUDZBVe+24"); options.set_lowercase(); options.set_e_uppercase(); test::(i128::MAX, options, "7.ksyyizzkutudzbvE+24"); test::(i128::MIN, options, "-7.ksyyizzkutudzbvE+24"); options.set_uppercase(); test::(i128::MAX, options, "7.KSYYIZZKUTUDZBVE+24"); test::(i128::MIN, options, "-7.KSYYIZZKUTUDZBVE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test::( i128::MAX, options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", ); test::( i128::MIN, options, "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", ); options.set_base(3); test::( i128::MAX, options, "101100201022001010121000102002120122110122221010202000122201220121120010200022001", ); test::( i128::MIN, options, "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", ); options.set_base(4); test::( i128::MAX, options, "1333333333333333333333333333333333333333333333333333333333333333", ); test::( i128::MIN, options, "-2000000000000000000000000000000000000000000000000000000000000000", ); options.set_base(5); test::( i128::MAX, options, "3013030220323124042102424341431241221233040112312340402", ); test::( i128::MIN, options, "-3013030220323124042102424341431241221233040112312340403", ); options.set_base(8); test::( i128::MAX, options, "1777777777777777777777777777777777777777777", ); test::( i128::MIN, options, "-2000000000000000000000000000000000000000000", ); options.set_base(16); test::(i128::MAX, options, "7fffffffffffffffffffffffffffffff"); test::(i128::MIN, options, "-80000000000000000000000000000000"); options.set_base(32); test::(i128::MAX, options, "3vvvvvvvvvvvvvvvvvvvvvvvvv"); test::(i128::MIN, options, "-40000000000000000000000000"); options.set_base(36); test::(i128::MAX, options, "7ksyyizzkutudzbv8aqztecjj"); test::(i128::MIN, options, "-7ksyyizzkutudzbv8aqztecjk"); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test::(0, options, "0.000"); test::(1, options, "1.000"); test::(10, options, "10.00"); test::(100, options, "100.0"); test::(1000, options, "1000"); test::(10000, options, "1.000e4"); test::(-1, options, "-1.000"); test::(-10, options, "-10.00"); test::(-100, options, "-100.0"); test::(-1000, options, "-1000"); test::(-10000, options, "-1.000e4"); test::(9, options, "9.000"); test::(99, options, "99.00"); test::(999, options, "999.0"); test::(9999, options, "9999"); test::(99999, options, "1.000e5"); test::(-9, options, "-9.000"); test::(-99, options, "-99.00"); test::(-999, options, "-999.0"); test::(-9999, options, "-9999"); test::(-99999, options, "-1.000e5"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "1e4"); test::(-1, options, "-1"); test::(-10, options, "-10"); test::(-100, options, "-100"); test::(-1000, options, "-1000"); test::(-10000, options, "-1e4"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "1e5"); test::(-9, options, "-9"); test::(-99, options, "-99"); test::(-999, options, "-999"); test::(-9999, options, "-9999"); test::(-99999, options, "-1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "1e1"); test::(100, options, "1e2"); test::(1000, options, "1e3"); test::(10000, options, "1e4"); test::(-1, options, "-1"); test::(-10, options, "-1e1"); test::(-100, options, "-1e2"); test::(-1000, options, "-1e3"); test::(-10000, options, "-1e4"); test::(9, options, "9"); test::(99, options, "1e2"); test::(999, options, "1e3"); test::(9999, options, "1e4"); test::(99999, options, "1e5"); test::(-9, options, "-9"); test::(-99, options, "-1e2"); test::(-999, options, "-1e3"); test::(-9999, options, "-1e4"); test::(-99999, options, "-1e5"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "1e1"); test::(100, options, "1e2"); test::(1000, options, "1e3"); test::(10000, options, "1e4"); test::(-1, options, "-1"); test::(-10, options, "-1e1"); test::(-100, options, "-1e2"); test::(-1000, options, "-1e3"); test::(-10000, options, "-1e4"); test::(9, options, "9"); test::(99, options, "1e2"); test::(999, options, "1e3"); test::(9999, options, "1e4"); test::(99999, options, "1e5"); test::(-9, options, "-9"); test::(-99, options, "-1e2"); test::(-999, options, "-1e3"); test::(-9999, options, "-1e4"); test::(-99999, options, "-1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test::(0, options, "0.00"); test::(1, options, "1.00"); test::(10, options, "10.00"); test::(100, options, "100.00"); test::(1000, options, "1000.00"); test::(10000, options, "10000.00"); test::(-1, options, "-1.00"); test::(-10, options, "-10.00"); test::(-100, options, "-100.00"); test::(-1000, options, "-1000.00"); test::(-10000, options, "-10000.00"); test::(9, options, "9.00"); test::(99, options, "99.00"); test::(999, options, "999.00"); test::(9999, options, "9999.00"); test::(99999, options, "99999.00"); test::(-9, options, "-9.00"); test::(-99, options, "-99.00"); test::(-999, options, "-999.00"); test::(-9999, options, "-9999.00"); test::(-99999, options, "-99999.00"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(-1, options, "-1"); test::(-10, options, "-10"); test::(-100, options, "-100"); test::(-1000, options, "-1000"); test::(-10000, options, "-10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); test::(-9, options, "-9"); test::(-99, options, "-99"); test::(-999, options, "-999"); test::(-9999, options, "-9999"); test::(-99999, options, "-99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(-1, options, "-1"); test::(-10, options, "-10"); test::(-100, options, "-100"); test::(-1000, options, "-1000"); test::(-10000, options, "-10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); test::(-9, options, "-9"); test::(-99, options, "-99"); test::(-999, options, "-999"); test::(-9999, options, "-9999"); test::(-99999, options, "-99999"); options.set_include_trailing_zeros(false); test::(0, options, "0"); test::(1, options, "1"); test::(10, options, "10"); test::(100, options, "100"); test::(1000, options, "1000"); test::(10000, options, "10000"); test::(-1, options, "-1"); test::(-10, options, "-10"); test::(-100, options, "-100"); test::(-1000, options, "-1000"); test::(-10000, options, "-10000"); test::(9, options, "9"); test::(99, options, "99"); test::(999, options, "999"); test::(9999, options, "9999"); test::(99999, options, "99999"); test::(-9, options, "-9"); test::(-99, options, "-99"); test::(-999, options, "-999"); test::(-9999, options, "-9999"); test::(-99999, options, "-99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test::(123, options, "1.2e2"); test::(-123, options, "-1.2e2"); options.set_rounding_mode(Down); test::(123, options, "1.2e2"); test::(-123, options, "-1.2e2"); options.set_rounding_mode(Floor); test::(123, options, "1.2e2"); test::(-123, options, "-1.3e2"); options.set_rounding_mode(Up); test::(123, options, "1.3e2"); test::(-123, options, "-1.3e2"); options.set_rounding_mode(Ceiling); test::(123, options, "1.3e2"); test::(-123, options, "-1.2e2"); options.set_rounding_mode(Nearest); test::(135, options, "1.4e2"); test::(-135, options, "-1.4e2"); options.set_rounding_mode(Down); test::(135, options, "1.3e2"); test::(-135, options, "-1.3e2"); options.set_rounding_mode(Floor); test::(135, options, "1.3e2"); test::(-135, options, "-1.4e2"); options.set_rounding_mode(Up); test::(135, options, "1.4e2"); test::(-135, options, "-1.4e2"); options.set_rounding_mode(Ceiling); test::(135, options, "1.4e2"); test::(-135, options, "-1.3e2"); options.set_rounding_mode(Exact); test::(140, options, "1.4e2"); test::(-140, options, "-1.4e2"); options.set_rounding_mode(Nearest); test::(999, options, "1e3"); test::(-999, options, "-1e3"); options.set_rounding_mode(Down); test::(999, options, "9.9e2"); test::(-999, options, "-9.9e2"); options.set_rounding_mode(Floor); test::(999, options, "9.9e2"); test::(-999, options, "-1e3"); options.set_rounding_mode(Up); test::(999, options, "1e3"); test::(-999, options, "-1e3"); options.set_rounding_mode(Ceiling); test::(999, options, "1e3"); test::(-999, options, "-9.9e2"); } fn to_sci_with_options_fail_helper() { assert_panic!({ let mut options = ToSciOptions::default(); options.set_rounding_mode(Exact); options.set_precision(2); T::wrapping_from(123u8) .to_sci_with_options(options) .to_string() }); } #[test] pub fn to_sci_with_options_fail() { apply_fn_to_primitive_ints!(to_sci_with_options_fail_helper); } fn to_sci_helper_unsigned() { let mut powers_of_10 = HashMap::new(); let ten = T::from(10u8); let default_p = 16; unsigned_gen::().test_properties(|x| { assert!(x.fmt_sci_valid(ToSciOptions::default())); let s = x.to_sci().to_string(); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), s ); assert!(string_is_subset(&s, DECIMAL_SCI_STRING_CHARS)); assert!(!s.starts_with('.')); assert!(!s.ends_with('.')); assert!(!s.contains('-')); assert!(!s.contains('+')); assert!(!s.contains('E')); assert!(s.chars().filter(|&c| c == '.').count() <= 1); if let Some(x_from) = T::from_sci_string(&s) { if x == T::ZERO { assert_eq!(x_from, T::ZERO); } else { let log = x.floor_log_base(ten); if log < default_p { assert_eq!(x_from, x); } else { let pow = *powers_of_10 .entry(log - default_p + 1) .or_insert_with_key(|&p| ten.pow(p)); assert_eq!(x.round_to_multiple(pow, Nearest).0, x_from); } } } else { assert_eq!(x.significant_bits(), T::WIDTH); } }); } fn to_sci_helper_signed() where ::Output: PrimitiveUnsigned, { let mut powers_of_10 = HashMap::new(); let ten = T::from(10); let u_ten = ::Output::from(10u8); let default_p = 16; signed_gen::().test_properties(|x| { assert!(x.fmt_sci_valid(ToSciOptions::default())); let s = x.to_sci().to_string(); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), s ); assert!(string_is_subset(&s, DECIMAL_SCI_STRING_CHARS)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains('E')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); assert!(!s.contains("e-")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 1); assert!(s.chars().filter(|&c| c == '+').count() <= 1); if let Some(x_from) = T::from_sci_string(&s) { if x == T::ZERO { assert_eq!(x_from, T::ZERO); } else { let log = x.unsigned_abs().floor_log_base(u_ten); if log < default_p { assert_eq!(x_from, x); } else { let pow = *powers_of_10 .entry(log - default_p + 1) .or_insert_with_key(|&p| ten.pow(p)); assert_eq!(x.round_to_multiple(pow, Nearest).0, x_from); } } } else { assert!(x.significant_bits() >= T::WIDTH - 1); } }); } #[test] fn to_sci_properties() { apply_fn_to_unsigneds!(to_sci_helper_unsigned); apply_fn_to_signeds!(to_sci_helper_signed); } fn to_sci_with_options_helper_unsigned() { let mut powers = HashMap::new(); let mut chars = HashMap::new(); unsigned_to_sci_options_pair_gen_var_1::().test_properties(|(x, options)| { assert!(x.fmt_sci_valid(options)); let s = x.to_sci_with_options(options).to_string(); let cs: &mut String = chars.entry(options.get_base()).or_insert_with_key(|&base| { let mut cs = "+-.0123456789".to_string(); if base > 10 { let limit = usize::from(base - 10); for c in ('a'..='z').take(limit) { cs.push(c); } for c in ('A'..='Z').take(limit) { cs.push(c); } } if base < 15 { cs.push('e'); cs.push('E'); } cs }); assert!(string_is_subset(&s, cs)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('.')); assert!(!s.contains('-')); assert!(!s.contains("++")); assert!(!s.contains("+.")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '+').count() <= 1); let mut from_options = FromSciStringOptions::default(); from_options.set_base(options.get_base()); if let Some(x_from) = T::from_sci_string_with_options(&s, from_options) { if x == T::ZERO { assert_eq!(x_from, T::ZERO); } else { let base = T::from(options.get_base()); let scale = match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => None, SciSizeOptions::Precision(p) => { let log = x.floor_log_base(base); if log >= p { Some(log - p + 1) } else { None } } }; if let Some(scale) = scale { let pow = *powers .entry((base, scale)) .or_insert_with(|| base.pow(scale)); assert_eq!( x.round_to_multiple(pow, options.get_rounding_mode()).0, x_from ); } else { assert_eq!(x_from, x); } } } else { assert_eq!(x.significant_bits(), T::WIDTH); } }); } fn to_sci_with_options_helper_signed() where ::Output: PrimitiveUnsigned, { let mut powers = HashMap::new(); let mut chars = HashMap::new(); signed_to_sci_options_pair_gen_var_1::().test_properties(|(x, options)| { assert!(x.fmt_sci_valid(options)); let s = x.to_sci_with_options(options).to_string(); let cs: &mut String = chars.entry(options.get_base()).or_insert_with_key(|&base| { let mut cs = "+-.0123456789".to_string(); if base > 10 { let limit = usize::from(base - 10); for c in ('a'..='z').take(limit) { cs.push(c); } for c in ('A'..='Z').take(limit) { cs.push(c); } } if base < 15 { cs.push('e'); cs.push('E'); } cs }); assert!(string_is_subset(&s, cs)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); assert!(!s.contains("e-")); assert!(!s.contains("E-")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 1); assert!(s.chars().filter(|&c| c == '+').count() <= 1); let mut from_options = FromSciStringOptions::default(); from_options.set_base(options.get_base()); if let Some(x_from) = T::from_sci_string_with_options(&s, from_options) { if x == T::ZERO { assert_eq!(x_from, T::ZERO); } else { let base = T::wrapping_from(options.get_base()); let u_base = ::Output::from(options.get_base()); let scale = match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => None, SciSizeOptions::Precision(p) => { let log = x.unsigned_abs().floor_log_base(u_base); if log >= p { Some(log - p + 1) } else { None } } }; if let Some(scale) = scale { let pow = *powers .entry((base, scale)) .or_insert_with(|| base.pow(scale)); assert_eq!( x.round_to_multiple(pow, options.get_rounding_mode()).0, x_from ); } else { assert_eq!(x_from, x); } } } else { assert!(x.significant_bits() >= T::WIDTH - 1); } }); } #[test] fn to_sci_with_options_properties() { apply_fn_to_unsigneds!(to_sci_with_options_helper_unsigned); apply_fn_to_signeds!(to_sci_with_options_helper_signed); } ================================================ FILE: malachite-base/tests/num/conversion/string/to_string.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::arithmetic::traits::{SaturatingSubAssign, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::to_string::{ BaseFmtWrapper, digit_to_display_byte_lower, digit_to_display_byte_upper, }; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::strings::{ ToBinaryString, ToLowerHexString, ToOctalString, ToUpperHexString, string_is_subset, }; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_2, signed_unsigned_pair_gen_var_5, signed_unsigned_pair_gen_var_6, signed_unsigned_unsigned_triple_gen_var_3, unsigned_gen, unsigned_gen_var_7, unsigned_gen_var_8, unsigned_pair_gen_var_2, unsigned_pair_gen_var_8, unsigned_pair_gen_var_9, unsigned_triple_gen_var_6, }; use malachite_base::test_util::num::conversion::string::to_string::{ to_string_base_signed_naive, to_string_base_unsigned_naive, }; use std::cmp::max; use std::fmt::{Debug, Display}; use std::panic::catch_unwind; fn test_padding_unsigned(s: &str, s_padded: &str, width: usize) { assert!(s_padded.ends_with(&s)); assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); if s.len() < width { let diff = s_padded.len() - s.len(); assert!(s_padded[..diff].chars().all(|c| c == '0')); assert_eq!(&s_padded[diff..], s); } } fn test_padding_signed(mut s: &str, mut s_padded: &str, mut width: usize) { assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); let negative = s.starts_with('-'); assert_eq!(s_padded.starts_with('-'), negative); if negative { s = &s[1..]; s_padded = &s_padded[1..]; width.saturating_sub_assign(1); } test_padding_unsigned(s, s_padded, width); } #[test] fn test_digit_to_display_byte_lower() { let test_ok = |x, y| { assert_eq!(digit_to_display_byte_lower(x).unwrap(), y); }; test_ok(0, b'0'); test_ok(1, b'1'); test_ok(2, b'2'); test_ok(3, b'3'); test_ok(4, b'4'); test_ok(5, b'5'); test_ok(6, b'6'); test_ok(7, b'7'); test_ok(8, b'8'); test_ok(9, b'9'); test_ok(10, b'a'); test_ok(11, b'b'); test_ok(12, b'c'); test_ok(33, b'x'); test_ok(34, b'y'); test_ok(35, b'z'); let test_err = |x| { assert!(digit_to_display_byte_lower(x).is_none()); }; test_err(36); test_err(100); } #[test] fn digit_to_display_byte_lower_properties() { unsigned_gen().test_properties(|b| { assert_eq!(digit_to_display_byte_lower(b).is_some(), b < 36); }); unsigned_gen_var_7().test_properties(|b| { let display_byte = digit_to_display_byte_lower(b).unwrap(); assert!(display_byte.is_ascii_digit() || display_byte.is_ascii_lowercase()); let display_byte_upper = digit_to_display_byte_upper(b).unwrap(); assert_eq!(display_byte == display_byte_upper, b < 10); assert_eq!( char::from(display_byte).to_ascii_uppercase(), char::from(display_byte_upper) ); }); } #[test] fn test_digit_to_display_byte_upper() { let test_ok = |x, y| { assert_eq!(digit_to_display_byte_upper(x).unwrap(), y); }; test_ok(0, b'0'); test_ok(1, b'1'); test_ok(2, b'2'); test_ok(3, b'3'); test_ok(4, b'4'); test_ok(5, b'5'); test_ok(6, b'6'); test_ok(7, b'7'); test_ok(8, b'8'); test_ok(9, b'9'); test_ok(10, b'A'); test_ok(11, b'B'); test_ok(12, b'C'); test_ok(33, b'X'); test_ok(34, b'Y'); test_ok(35, b'Z'); let test_err = |x| { assert!(digit_to_display_byte_upper(x).is_none()); }; test_err(36); test_err(100); } #[test] fn digit_to_display_byte_upper_properties() { unsigned_gen().test_properties(|b| { assert_eq!( digit_to_display_byte_upper(b).is_some(), (0..36).contains(&b) ); }); unsigned_gen_var_7().test_properties(|b| { let display_byte = digit_to_display_byte_upper(b).unwrap(); assert!(display_byte.is_ascii_digit() || display_byte.is_ascii_uppercase()); let display_byte_lower = digit_to_display_byte_lower(b).unwrap(); assert_eq!(display_byte == display_byte_lower, b < 10); assert_eq!( char::from(display_byte).to_ascii_lowercase(), char::from(display_byte_lower) ); }); } #[test] pub fn test_to_string_base() { fn test_u(x: T, base: u8, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { assert_eq!(x.to_string_base(base), out); assert_eq!(to_string_base_unsigned_naive(x, base), out); assert_eq!(format!("{}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:?}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:00}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(x, base)), out); } test_u::(0, 2, "0"); test_u::(0, 3, "0"); test_u::(0, 10, "0"); test_u::(0, 16, "0"); test_u::(0, 17, "0"); test_u::(2, 3, "2"); test_u::(2, 10, "2"); test_u::(2, 16, "2"); test_u::(2, 17, "2"); test_u::(123, 8, "173"); test_u::(1000000, 10, "1000000"); test_u::(1000000, 20, "65000"); test_u::(1000000, 36, "lfls"); test_u::(1000, 2, "1111101000"); test_u::(1000, 3, "1101001"); test_u::(1000, 4, "33220"); test_u::(1000, 10, "1000"); test_u::(1000, 20, "2a0"); test_u::(1000, 36, "rs"); fn test_u_width(x: T, base: u8, width: usize, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { let s = x.to_string_base(base); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, base), width = width), out ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(x, base), width = width), out ); test_padding_unsigned(&s, out, width); } test_u_width::(0, 2, 0, "0"); test_u_width::(0, 2, 1, "0"); test_u_width::(0, 2, 2, "00"); test_u_width::(0, 2, 5, "00000"); test_u_width::(1000000, 36, 0, "lfls"); test_u_width::(1000000, 36, 1, "lfls"); test_u_width::(1000000, 36, 2, "lfls"); test_u_width::(1000000, 36, 3, "lfls"); test_u_width::(1000000, 36, 4, "lfls"); test_u_width::(1000000, 36, 5, "0lfls"); test_u_width::(1000000, 36, 6, "00lfls"); fn test_i(x: T, base: u8, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom<::Output>, ::Output: PrimitiveUnsigned, { assert_eq!(x.to_string_base(base), out); assert_eq!(to_string_base_signed_naive(x, base), out); assert_eq!(format!("{}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:?}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:00}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(x, base)), out); } test_i::(0, 2, "0"); test_i::(0, 3, "0"); test_i::(0, 10, "0"); test_i::(0, 16, "0"); test_i::(0, 17, "0"); test_i::(2, 3, "2"); test_i::(2, 10, "2"); test_i::(2, 16, "2"); test_i::(2, 17, "2"); test_i::(123, 8, "173"); test_i::(1000000, 10, "1000000"); test_i::(1000000, 20, "65000"); test_i::(1000000, 36, "lfls"); test_i::(1000, 2, "1111101000"); test_i::(1000, 3, "1101001"); test_i::(1000, 4, "33220"); test_i::(1000, 10, "1000"); test_i::(1000, 20, "2a0"); test_i::(1000, 36, "rs"); test_i::(-2, 3, "-2"); test_i::(-2, 10, "-2"); test_i::(-2, 16, "-2"); test_i::(-2, 17, "-2"); test_i::(-123, 8, "-173"); test_i::(-1000000, 10, "-1000000"); test_i::(-1000000, 20, "-65000"); test_i::(-1000000, 36, "-lfls"); test_i::(-1000, 2, "-1111101000"); test_i::(-1000, 3, "-1101001"); test_i::(-1000, 4, "-33220"); test_i::(-1000, 10, "-1000"); test_i::(-1000, 20, "-2a0"); test_i::(-1000, 36, "-rs"); fn test_i_width(x: T, base: u8, width: usize, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { let s = x.to_string_base(base); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, base), width = width), out ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(x, base), width = width), out ); test_padding_signed(&s, out, width); } test_i_width::(0, 2, 0, "0"); test_i_width::(0, 2, 1, "0"); test_i_width::(0, 2, 2, "00"); test_i_width::(0, 2, 5, "00000"); test_i_width::(1000000, 36, 0, "lfls"); test_i_width::(1000000, 36, 1, "lfls"); test_i_width::(1000000, 36, 2, "lfls"); test_i_width::(1000000, 36, 3, "lfls"); test_i_width::(1000000, 36, 4, "lfls"); test_i_width::(1000000, 36, 5, "0lfls"); test_i_width::(1000000, 36, 6, "00lfls"); test_i_width::(-1000000, 36, 0, "-lfls"); test_i_width::(-1000000, 36, 1, "-lfls"); test_i_width::(-1000000, 36, 2, "-lfls"); test_i_width::(-1000000, 36, 3, "-lfls"); test_i_width::(-1000000, 36, 4, "-lfls"); test_i_width::(-1000000, 36, 5, "-lfls"); test_i_width::(-1000000, 36, 6, "-0lfls"); } fn to_string_base_fail_helper() { assert_panic!(T::exact_from(100).to_string_base(0)); assert_panic!(T::exact_from(100).to_string_base(1)); assert_panic!(T::exact_from(100).to_string_base(37)); assert_panic!(T::exact_from(100).to_string_base(100)); } #[test] fn to_string_base_fail() { apply_fn_to_primitive_ints!(to_string_base_fail_helper); } fn to_string_base_helper_unsigned() where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { unsigned_pair_gen_var_8::().test_properties(|(x, base)| { let s = x.to_string_base(base); assert_eq!(to_string_base_unsigned_naive(x, base), s); assert_eq!(format!("{}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(x.to_string_base_upper(base), s.to_uppercase()); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset(&s, "0123456789abcdefghijklmnopqrstuvwxyz")); if x != T::ZERO { assert!(!s.starts_with('0')); } }); unsigned_gen::().test_properties(|x| { assert_eq!(x.to_string_base(10), x.to_string()); assert_eq!(x.to_string_base(2), x.to_binary_string()); assert_eq!(x.to_string_base(8), x.to_octal_string()); assert_eq!(x.to_string_base(16), x.to_lower_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(T::ZERO.to_string_base(base), "0"); assert_eq!(T::ONE.to_string_base(base), "1"); assert_eq!(T::exact_from(base).to_string_base(base), "10"); }); unsigned_triple_gen_var_6::().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(x, base); let s = x.to_string_base(base); let s_padded = format!("{fx:0width$}"); assert_eq!(format!("{fx:0width$?}"), s_padded); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "0123456789abcdefghijklmnopqrstuvwxyz" )); test_padding_unsigned(&s, &s_padded, width); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 16), width = width), format!("{x:0width$x}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:0width$}", BaseFmtWrapper::new(T::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); } fn to_string_base_helper_signed() where BaseFmtWrapper: Debug + Display, u8: WrappingFrom<::Output>, ::Output: PrimitiveUnsigned, { signed_unsigned_pair_gen_var_5::().test_properties(|(x, base)| { let s = x.to_string_base(base); assert_eq!(to_string_base_signed_naive(x, base), s); assert_eq!(format!("{}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(x.to_string_base_upper(base), s.to_uppercase()); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s, "-0123456789abcdefghijklmnopqrstuvwxyz" )); assert_eq!(x < T::ZERO, s.starts_with('-')); assert!(!s.starts_with("-0")); if x != T::ZERO { assert!(!s.starts_with('0')); } }); signed_gen::().test_properties(|x| { assert_eq!(x.to_string_base(10), x.to_string()); }); signed_gen_var_2::().test_properties(|x| { assert_eq!(x.to_string_base(2), x.to_binary_string()); assert_eq!(x.to_string_base(8), x.to_octal_string()); assert_eq!(x.to_string_base(16), x.to_lower_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(T::ZERO.to_string_base(base), "0"); assert_eq!(T::ONE.to_string_base(base), "1"); assert_eq!(T::NEGATIVE_ONE.to_string_base(base), "-1"); assert_eq!(T::exact_from(base).to_string_base(base), "10"); }); signed_unsigned_unsigned_triple_gen_var_3::().test_properties( |(x, base, width)| { let fx = BaseFmtWrapper::new(x, base); let s = x.to_string_base(base); let s_padded = format!("{fx:0width$}"); assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); assert_eq!(format!("{fx:0width$?}"), s_padded); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "-0123456789abcdefghijklmnopqrstuvwxyz" )); test_padding_signed(&s, &s_padded, width); }, ); signed_unsigned_pair_gen_var_6::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(x, 16), width = width), format!("{x:0width$x}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:0width$}", BaseFmtWrapper::new(T::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); } #[test] fn to_string_base_properties() { apply_fn_to_unsigneds!(to_string_base_helper_unsigned); apply_fn_to_signeds!(to_string_base_helper_signed); } #[test] pub fn test_to_string_base_upper() { fn test_u(x: T, base: u8, out: &str) where BaseFmtWrapper: Debug + Display, { assert_eq!(x.to_string_base_upper(base), out); assert_eq!(format!("{:#}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(x, base)), out); } test_u::(0, 2, "0"); test_u::(0, 3, "0"); test_u::(0, 10, "0"); test_u::(0, 16, "0"); test_u::(0, 17, "0"); test_u::(2, 3, "2"); test_u::(2, 10, "2"); test_u::(2, 16, "2"); test_u::(2, 17, "2"); test_u::(123, 8, "173"); test_u::(1000000, 10, "1000000"); test_u::(1000000, 20, "65000"); test_u::(1000000, 36, "LFLS"); test_u::(1000, 2, "1111101000"); test_u::(1000, 3, "1101001"); test_u::(1000, 4, "33220"); test_u::(1000, 10, "1000"); test_u::(1000, 20, "2A0"); test_u::(1000, 36, "RS"); fn test_u_width(x: T, base: u8, width: usize, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { let s = x.to_string_base_upper(base); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, base), width = width), out ); assert_eq!( format!("{:#0width$?}", BaseFmtWrapper::new(x, base), width = width), out ); test_padding_unsigned(&s, out, width); } test_u_width::(0, 2, 0, "0"); test_u_width::(0, 2, 1, "0"); test_u_width::(0, 2, 2, "00"); test_u_width::(0, 2, 5, "00000"); test_u_width::(1000000, 36, 0, "LFLS"); test_u_width::(1000000, 36, 1, "LFLS"); test_u_width::(1000000, 36, 2, "LFLS"); test_u_width::(1000000, 36, 3, "LFLS"); test_u_width::(1000000, 36, 4, "LFLS"); test_u_width::(1000000, 36, 5, "0LFLS"); test_u_width::(1000000, 36, 6, "00LFLS"); fn test_i(x: T, base: u8, out: &str) where BaseFmtWrapper: Debug + Display, { assert_eq!(x.to_string_base_upper(base), out); assert_eq!(format!("{:#}", BaseFmtWrapper::new(x, base)), out); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(x, base)), out); } test_i::(0, 2, "0"); test_i::(0, 3, "0"); test_i::(0, 10, "0"); test_i::(0, 16, "0"); test_i::(0, 17, "0"); test_i::(2, 3, "2"); test_i::(2, 10, "2"); test_i::(2, 16, "2"); test_i::(2, 17, "2"); test_i::(123, 8, "173"); test_i::(1000000, 10, "1000000"); test_i::(1000000, 20, "65000"); test_i::(1000000, 36, "LFLS"); test_i::(1000, 2, "1111101000"); test_i::(1000, 3, "1101001"); test_i::(1000, 4, "33220"); test_i::(1000, 10, "1000"); test_i::(1000, 20, "2A0"); test_i::(1000, 36, "RS"); test_i::(-2, 3, "-2"); test_i::(-2, 10, "-2"); test_i::(-2, 16, "-2"); test_i::(-2, 17, "-2"); test_i::(-123, 8, "-173"); test_i::(-1000000, 10, "-1000000"); test_i::(-1000000, 20, "-65000"); test_i::(-1000000, 36, "-LFLS"); test_i::(-1000, 2, "-1111101000"); test_i::(-1000, 3, "-1101001"); test_i::(-1000, 4, "-33220"); test_i::(-1000, 10, "-1000"); test_i::(-1000, 20, "-2A0"); test_i::(-1000, 36, "-RS"); fn test_i_width(x: T, base: u8, width: usize, out: &str) where BaseFmtWrapper: Debug + Display, u8: WrappingFrom, { let s = x.to_string_base_upper(base); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, base), width = width), out ); assert_eq!( format!("{:#0width$?}", BaseFmtWrapper::new(x, base), width = width), out ); test_padding_signed(&s, out, width); } test_i_width::(0, 2, 0, "0"); test_i_width::(0, 2, 1, "0"); test_i_width::(0, 2, 2, "00"); test_i_width::(0, 2, 5, "00000"); test_i_width::(1000000, 36, 0, "LFLS"); test_i_width::(1000000, 36, 1, "LFLS"); test_i_width::(1000000, 36, 2, "LFLS"); test_i_width::(1000000, 36, 3, "LFLS"); test_i_width::(1000000, 36, 4, "LFLS"); test_i_width::(1000000, 36, 5, "0LFLS"); test_i_width::(1000000, 36, 6, "00LFLS"); test_i_width::(-1000000, 36, 0, "-LFLS"); test_i_width::(-1000000, 36, 1, "-LFLS"); test_i_width::(-1000000, 36, 2, "-LFLS"); test_i_width::(-1000000, 36, 3, "-LFLS"); test_i_width::(-1000000, 36, 4, "-LFLS"); test_i_width::(-1000000, 36, 5, "-LFLS"); test_i_width::(-1000000, 36, 6, "-0LFLS"); } fn to_string_base_upper_fail_helper() { assert_panic!(T::exact_from(100).to_string_base_upper(0)); assert_panic!(T::exact_from(100).to_string_base_upper(1)); assert_panic!(T::exact_from(100).to_string_base_upper(37)); assert_panic!(T::exact_from(100).to_string_base_upper(100)); } #[test] fn to_string_base_upper_fail() { apply_fn_to_primitive_ints!(to_string_base_upper_fail_helper); } fn to_string_base_upper_helper_unsigned() where BaseFmtWrapper: Debug + Display, { unsigned_pair_gen_var_8::().test_properties(|(x, base)| { let s = x.to_string_base_upper(base); assert_eq!(format!("{:#}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:#00}", BaseFmtWrapper::new(x, base)), s); assert_eq!(x.to_string_base(base), s.to_lowercase()); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset(&s, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")); if x != T::ZERO { assert!(!s.starts_with('0')); } }); unsigned_gen::().test_properties(|x| { assert_eq!(x.to_string_base_upper(10), x.to_string()); assert_eq!(x.to_string_base_upper(2), x.to_binary_string()); assert_eq!(x.to_string_base_upper(8), x.to_octal_string()); assert_eq!(x.to_string_base_upper(16), x.to_upper_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(T::ZERO.to_string_base_upper(base), "0"); assert_eq!(T::ONE.to_string_base_upper(base), "1"); assert_eq!(T::exact_from(base).to_string_base_upper(base), "10"); }); unsigned_triple_gen_var_6::().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(x, base); let s = x.to_string_base_upper(base); let s_padded = format!("{fx:#0width$}"); assert_eq!(format!("{fx:#0width$?}"), s_padded); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); test_padding_unsigned(&s, &s_padded, width); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 16), width = width), format!("{x:0width$X}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:#0width$}", BaseFmtWrapper::new(T::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); } fn to_string_base_upper_helper_signed() where BaseFmtWrapper: Debug + Display, { signed_unsigned_pair_gen_var_5::().test_properties(|(x, base)| { let s = x.to_string_base_upper(base); assert_eq!(format!("{:#}", BaseFmtWrapper::new(x, base)), s); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(x, base)), s); assert_eq!(x.to_string_base(base), s.to_lowercase()); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s, "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); assert_eq!(x < T::ZERO, s.starts_with('-')); assert!(!s.starts_with("-0")); if x != T::ZERO { assert!(!s.starts_with('0')); } }); signed_gen::().test_properties(|x| { assert_eq!(x.to_string_base_upper(10), x.to_string()); }); signed_gen_var_2::().test_properties(|x| { assert_eq!(x.to_string_base_upper(2), x.to_binary_string()); assert_eq!(x.to_string_base_upper(8), x.to_octal_string()); assert_eq!(x.to_string_base_upper(16), x.to_upper_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(T::ZERO.to_string_base_upper(base), "0"); assert_eq!(T::ONE.to_string_base_upper(base), "1"); assert_eq!(T::NEGATIVE_ONE.to_string_base_upper(base), "-1"); assert_eq!(T::exact_from(base).to_string_base_upper(base), "10"); }); signed_unsigned_unsigned_triple_gen_var_3::().test_properties( |(x, base, width)| { let fx = BaseFmtWrapper::new(x, base); let s = x.to_string_base_upper(base); let s_padded = format!("{fx:#0width$}"); assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); assert_eq!(format!("{fx:#0width$?}"), s_padded); assert_eq!(T::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); test_padding_signed(&s, &s_padded, width); }, ); signed_unsigned_pair_gen_var_6::().test_properties(|(x, width)| { assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(x, 16), width = width), format!("{x:0width$X}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:#0width$}", BaseFmtWrapper::new(T::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); } #[test] fn to_string_base_upper_properties() { apply_fn_to_unsigneds!(to_string_base_upper_helper_unsigned); apply_fn_to_signeds!(to_string_base_upper_helper_signed); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_finite_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_finite_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_finite_primitive_floats::(), out); } #[test] fn test_exhaustive_finite_primitive_floats() { exhaustive_finite_primitive_floats_helper::(&[ 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, ]); exhaustive_finite_primitive_floats_helper::(&[ 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_natural_signeds.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::{exhaustive_natural_signeds, exhaustive_negative_signeds}; fn exhaustive_natural_signeds_helper() where i8: ExactFrom, { let xs = exhaustive_natural_signeds::() .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!( xs, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] ); assert!(itertools::equal( xs, exhaustive_negative_signeds::() .map(|x| !i8::exact_from(x)) .take(20) )); } fn exhaustive_natural_signeds_long_helper(last_20: &[T]) { let expected_len = usize::power_of_2(T::WIDTH - 1); let xs = exhaustive_natural_signeds::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_natural_signeds() { apply_fn_to_signeds!(exhaustive_natural_signeds_helper); exhaustive_natural_signeds_long_helper::(&[ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, ]); exhaustive_natural_signeds_long_helper::(&[ 32748, 32749, 32750, 32751, 0x7ff0, 0x7ff1, 0x7ff2, 0x7ff3, 0x7ff4, 0x7ff5, 0x7ff6, 0x7ff7, 0x7ff8, 0x7ff9, 0x7ffa, 0x7ffb, 0x7ffc, 0x7ffd, i16::MAX - 1, i16::MAX, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_negative_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_negative_finite_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_negative_finite_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper( exhaustive_negative_finite_primitive_floats::(), out, ); } #[test] fn test_exhaustive_negative_finite_primitive_floats() { exhaustive_negative_finite_primitive_floats_helper::(&[ -1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, -0.75, -1.625, -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, -1.4375, -6.0, -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, -2.125, -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, -0.6875, -1.40625, -2.875, -1.46875, -0.375, -1.53125, -3.125, ]); exhaustive_negative_finite_primitive_floats_helper::(&[ -1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, -0.75, -1.625, -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, -1.4375, -6.0, -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, -2.125, -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, -0.6875, -1.40625, -2.875, -1.46875, -0.375, -1.53125, -3.125, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_negative_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::exhaustive_negative_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_negative_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_negative_primitive_floats::(), out); } #[test] fn test_exhaustive_negative_primitive_floats() { exhaustive_negative_primitive_floats_helper::(&[ f32::NEGATIVE_INFINITY, -1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, -0.75, -1.625, -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, -1.4375, -6.0, -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, -2.125, -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, -0.6875, -1.40625, -2.875, -1.46875, -0.375, -1.53125, ]); exhaustive_negative_primitive_floats_helper::(&[ f64::NEGATIVE_INFINITY, -1.0, -2.0, -1.5, -0.5, -1.25, -3.0, -1.75, -4.0, -1.125, -2.5, -1.375, -0.75, -1.625, -3.5, -1.875, -0.25, -1.0625, -2.25, -1.1875, -0.625, -1.3125, -2.75, -1.4375, -6.0, -1.5625, -3.25, -1.6875, -0.875, -1.8125, -3.75, -1.9375, -8.0, -1.03125, -2.125, -1.09375, -0.5625, -1.15625, -2.375, -1.21875, -5.0, -1.28125, -2.625, -1.34375, -0.6875, -1.40625, -2.875, -1.46875, -0.375, -1.53125, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_negative_signeds.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::{exhaustive_natural_signeds, exhaustive_negative_signeds}; fn exhaustive_negative_signeds_helper() where i8: ExactFrom, { let xs = exhaustive_negative_signeds::() .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!( xs, &[ -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20 ] ); assert!(itertools::equal( xs, exhaustive_natural_signeds::() .map(|x| !i8::exact_from(x)) .take(20) )); } fn exhaustive_negative_signeds_long_helper(last_20: &[T]) { let expected_len = usize::power_of_2(T::WIDTH - 1); let xs = exhaustive_negative_signeds::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_negative_signeds() { apply_fn_to_signeds!(exhaustive_negative_signeds_helper); exhaustive_negative_signeds_long_helper::(&[ -109, -110, -111, -112, -113, -114, -115, -116, -117, -118, -119, -120, -121, -122, -123, -124, -125, -126, -127, -128, ]); exhaustive_negative_signeds_long_helper::(&[ -32749, -32750, -32751, -0x7ff0, -0x7ff1, -0x7ff2, -0x7ff3, -0x7ff4, -0x7ff5, -0x7ff6, -0x7ff7, -0x7ff8, -0x7ff9, -0x7ffa, -0x7ffb, -0x7ffc, -0x7ffd, -0x7ffe, i16::MIN + 1, i16::MIN, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_nonzero_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_nonzero_finite_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_nonzero_finite_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper( exhaustive_nonzero_finite_primitive_floats::(), out, ); } #[test] fn test_exhaustive_nonzero_finite_primitive_floats() { exhaustive_nonzero_finite_primitive_floats_helper::(&[ 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, 1.5625, -1.5625, ]); exhaustive_nonzero_finite_primitive_floats_helper::(&[ 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, 1.5625, -1.5625, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_nonzero_finite_primitive_floats_in_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_nonzero_finite_primitive_floats_in_range; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; use std::panic::catch_unwind; fn exhaustive_nonzero_finite_primitive_floats_in_range_helper( a: T, b: T, out: &[T], ) { exhaustive_primitive_floats_helper_helper( exhaustive_nonzero_finite_primitive_floats_in_range::(a, b), out, ); } #[test] fn test_exhaustive_nonzero_finite_primitive_floats_in_range() { exhaustive_nonzero_finite_primitive_floats_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::(5.0, 5.0, &[5.0]); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( 1.0, 6.0, &[ 1.0, 2.0, 1.5, 4.0, 1.25, 3.0, 1.75, 1.125, 1.375, 2.5, 1.625, 6.0, 1.875, 3.5, 1.0625, 2.25, 1.1875, 2.75, 1.3125, 5.0, 1.4375, 3.25, 1.5625, 1.6875, 1.8125, 3.75, 1.9375, 4.5, 1.03125, 2.125, 1.09375, 5.5, 1.15625, 2.375, 1.21875, 4.25, 1.28125, 2.625, 1.34375, 1.40625, 1.46875, 2.875, 1.53125, 4.75, 1.59375, 3.125, 1.65625, 3.375, 1.71875, 3.625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -6.0, -1.0, &[ -1.0, -2.0, -1.5, -4.0, -1.25, -3.0, -1.75, -1.125, -1.375, -2.5, -1.625, -6.0, -1.875, -3.5, -1.0625, -2.25, -1.1875, -2.75, -1.3125, -5.0, -1.4375, -3.25, -1.5625, -1.6875, -1.8125, -3.75, -1.9375, -4.5, -1.03125, -2.125, -1.09375, -5.5, -1.15625, -2.375, -1.21875, -4.25, -1.28125, -2.625, -1.34375, -1.40625, -1.46875, -2.875, -1.53125, -4.75, -1.59375, -3.125, -1.65625, -3.375, -1.71875, -3.625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -6.0, 6.0, &[ 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, 1.5625, -1.5625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -0.1, 10.0, &[ 1.0, -0.0625, 2.0, -0.03125, 1.5, -0.09375, 0.5, -0.015625, 1.25, -0.078125, 3.0, -0.046875, 1.75, -0.0703125, 4.0, -0.0078125, 1.125, -0.0859375, 2.5, -0.0390625, 1.375, -0.06640625, 0.75, -0.0234375, 1.625, -0.07421875, 3.5, -0.0546875, 1.875, -0.08203125, 0.25, -0.00390625, 1.0625, -0.08984375, 2.25, -0.03515625, 1.1875, -0.09765625, 0.625, -0.01953125, 1.3125, -0.064453125, 2.75, -0.04296875, 1.4375, -0.068359375, 6.0, -0.01171875, 1.5625, -0.072265625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::(5.0, 5.0, &[5.0]); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( 1.0, 6.0, &[ 1.0, 2.0, 1.5, 4.0, 1.25, 3.0, 1.75, 1.125, 1.375, 2.5, 1.625, 6.0, 1.875, 3.5, 1.0625, 2.25, 1.1875, 2.75, 1.3125, 5.0, 1.4375, 3.25, 1.5625, 1.6875, 1.8125, 3.75, 1.9375, 4.5, 1.03125, 2.125, 1.09375, 5.5, 1.15625, 2.375, 1.21875, 4.25, 1.28125, 2.625, 1.34375, 1.40625, 1.46875, 2.875, 1.53125, 4.75, 1.59375, 3.125, 1.65625, 3.375, 1.71875, 3.625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -6.0, -1.0, &[ -1.0, -2.0, -1.5, -4.0, -1.25, -3.0, -1.75, -1.125, -1.375, -2.5, -1.625, -6.0, -1.875, -3.5, -1.0625, -2.25, -1.1875, -2.75, -1.3125, -5.0, -1.4375, -3.25, -1.5625, -1.6875, -1.8125, -3.75, -1.9375, -4.5, -1.03125, -2.125, -1.09375, -5.5, -1.15625, -2.375, -1.21875, -4.25, -1.28125, -2.625, -1.34375, -1.40625, -1.46875, -2.875, -1.53125, -4.75, -1.59375, -3.125, -1.65625, -3.375, -1.71875, -3.625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -6.0, 6.0, &[ 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, 1.5625, -1.5625, ], ); exhaustive_nonzero_finite_primitive_floats_in_range_helper::( -0.1, 10.0, &[ 1.0, -0.0625, 2.0, -0.03125, 1.5, -0.09375, 0.5, -0.015625, 1.25, -0.078125, 3.0, -0.046875, 1.75, -0.0703125, 4.0, -0.0078125, 1.125, -0.0859375, 2.5, -0.0390625, 1.375, -0.06640625, 0.75, -0.0234375, 1.625, -0.07421875, 3.5, -0.0546875, 1.875, -0.08203125, 0.25, -0.00390625, 1.0625, -0.08984375, 2.25, -0.03515625, 1.1875, -0.09765625, 0.625, -0.01953125, 1.3125, -0.064453125, 2.75, -0.04296875, 1.4375, -0.068359375, 6.0, -0.01171875, 1.5625, -0.072265625, ], ); } fn exhaustive_nonzero_finite_primitive_floats_in_range_fail_helper() { assert_panic!(exhaustive_nonzero_finite_primitive_floats_in_range::( T::from(1.2), T::from(1.1), )); assert_panic!(exhaustive_nonzero_finite_primitive_floats_in_range::( T::ONE, T::INFINITY, )); assert_panic!(exhaustive_nonzero_finite_primitive_floats_in_range::( T::ONE, T::NAN, )); } #[test] fn exhaustive_nonzero_finite_primitive_floats_in_range_fail() { apply_fn_to_primitive_floats!(exhaustive_nonzero_finite_primitive_floats_in_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_nonzero_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::exhaustive_nonzero_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_nonzero_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_nonzero_primitive_floats::(), out); } #[test] fn test_exhaustive_nonzero_primitive_floats() { exhaustive_nonzero_primitive_floats_helper::(&[ f32::INFINITY, f32::NEGATIVE_INFINITY, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, ]); exhaustive_nonzero_primitive_floats_helper::(&[ f64::INFINITY, f64::NEGATIVE_INFINITY, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, -6.0, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_nonzero_signeds.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::exhaustive_nonzero_signeds; fn exhaustive_nonzero_signeds_helper() where i8: ExactFrom, { assert_eq!( exhaustive_nonzero_signeds::() .map(i8::exact_from) .take(20) .collect_vec(), &[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10] ); } fn exhaustive_nonzero_signeds_long_helper(last_20: &[T]) { let expected_len = usize::power_of_2(T::WIDTH) - 1; let xs = exhaustive_nonzero_signeds::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_nonzero_signeds() { apply_fn_to_signeds!(exhaustive_nonzero_signeds_helper); exhaustive_nonzero_signeds_long_helper::(&[ -118, 119, -119, 120, -120, 121, -121, 122, -122, 123, -123, 124, -124, 125, -125, 126, -126, 127, -127, -128, ]); exhaustive_nonzero_signeds_long_helper::(&[ -0x7ff6, 0x7ff7, -0x7ff7, 0x7ff8, -0x7ff8, 0x7ff9, -0x7ff9, 0x7ffa, -0x7ffa, 0x7ffb, -0x7ffb, 0x7ffc, -0x7ffc, 0x7ffd, -0x7ffd, i16::MAX - 1, -0x7ffe, i16::MAX, i16::MIN + 1, i16::MIN, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_positive_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_positive_finite_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_positive_finite_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper( exhaustive_positive_finite_primitive_floats::(), out, ); } #[test] fn test_exhaustive_positive_finite_primitive_floats() { exhaustive_positive_finite_primitive_floats_helper::(&[ 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, 3.125, ]); exhaustive_positive_finite_primitive_floats_helper::(&[ 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, 3.125, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_positive_finite_primitive_floats_in_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_positive_finite_primitive_floats_in_range; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; use std::panic::catch_unwind; fn exhaustive_positive_finite_primitive_floats_in_range_helper( a: T, b: T, out: &[T], ) { exhaustive_primitive_floats_helper_helper( exhaustive_positive_finite_primitive_floats_in_range::(a, b), out, ); } #[test] fn test_exhaustive_positive_finite_primitive_floats_in_range() { exhaustive_positive_finite_primitive_floats_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::(5.0, 5.0, &[5.0]); exhaustive_positive_finite_primitive_floats_in_range_helper::( 1.0, 6.0, &[ 1.0, 2.0, 1.5, 4.0, 1.25, 3.0, 1.75, 1.125, 1.375, 2.5, 1.625, 6.0, 1.875, 3.5, 1.0625, 2.25, 1.1875, 2.75, 1.3125, 5.0, 1.4375, 3.25, 1.5625, 1.6875, 1.8125, 3.75, 1.9375, 4.5, 1.03125, 2.125, 1.09375, 5.5, 1.15625, 2.375, 1.21875, 4.25, 1.28125, 2.625, 1.34375, 1.40625, 1.46875, 2.875, 1.53125, 4.75, 1.59375, 3.125, 1.65625, 3.375, 1.71875, 3.625, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::( 0.01, 100.0, &[ 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, 3.125, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::( 255.9, 256.1, &[ 255.9375, 256.0, 255.90625, 255.96875, 255.92188, 256.0625, 255.95312, 256.03125, 255.98438, 256.09375, 255.91406, 255.92969, 255.94531, 256.01562, 255.96094, 255.97656, 255.99219, 256.04688, 255.90234, 255.91016, 255.91797, 256.07812, 255.92578, 256.0078, 255.9336, 256.02344, 255.9414, 255.94922, 255.95703, 256.03906, 255.96484, 256.0547, 255.97266, 256.0703, 255.98047, 255.98828, 255.9961, 256.08594, 255.90039, 256.0039, 255.9043, 256.01172, 255.9082, 255.91211, 255.91602, 256.01953, 255.91992, 255.92383, 255.92773, 256.02734, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::(5.0, 5.0, &[5.0]); exhaustive_positive_finite_primitive_floats_in_range_helper::( 1.0, 6.0, &[ 1.0, 2.0, 1.5, 4.0, 1.25, 3.0, 1.75, 1.125, 1.375, 2.5, 1.625, 6.0, 1.875, 3.5, 1.0625, 2.25, 1.1875, 2.75, 1.3125, 5.0, 1.4375, 3.25, 1.5625, 1.6875, 1.8125, 3.75, 1.9375, 4.5, 1.03125, 2.125, 1.09375, 5.5, 1.15625, 2.375, 1.21875, 4.25, 1.28125, 2.625, 1.34375, 1.40625, 1.46875, 2.875, 1.53125, 4.75, 1.59375, 3.125, 1.65625, 3.375, 1.71875, 3.625, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::( 0.01, 100.0, &[ 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, 3.125, ], ); exhaustive_positive_finite_primitive_floats_in_range_helper::( 255.9, 256.1, &[ 255.9375, 256.0, 255.90625, 255.96875, 255.921875, 256.0625, 255.953125, 256.03125, 255.984375, 256.09375, 255.9140625, 255.9296875, 255.9453125, 256.015625, 255.9609375, 255.9765625, 255.9921875, 256.046875, 255.90234375, 255.91015625, 255.91796875, 256.078125, 255.92578125, 256.0078125, 255.93359375, 256.0234375, 255.94140625, 255.94921875, 255.95703125, 256.0390625, 255.96484375, 256.0546875, 255.97265625, 256.0703125, 255.98046875, 255.98828125, 255.99609375, 256.0859375, 255.900390625, 256.00390625, 255.904296875, 256.01171875, 255.908203125, 255.912109375, 255.916015625, 256.01953125, 255.919921875, 255.923828125, 255.927734375, 256.02734375, ], ); } fn exhaustive_positive_finite_primitive_floats_in_range_fail_helper() { assert_panic!(exhaustive_positive_finite_primitive_floats_in_range::( T::from(1.2), T::from(1.1), )); assert_panic!(exhaustive_positive_finite_primitive_floats_in_range::( T::from(-1.1), T::from(1.1), )); assert_panic!(exhaustive_positive_finite_primitive_floats_in_range::( T::ONE, T::INFINITY, )); assert_panic!(exhaustive_positive_finite_primitive_floats_in_range::( T::ONE, T::NAN, )); } #[test] fn exhaustive_positive_finite_primitive_floats_in_range_fail() { apply_fn_to_primitive_floats!(exhaustive_positive_finite_primitive_floats_in_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_positive_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_positive_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_positive_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_positive_primitive_floats::(), out); } #[test] fn test_exhaustive_positive_primitive_floats() { exhaustive_positive_primitive_floats_helper::(&[ f32::INFINITY, 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, ]); exhaustive_positive_primitive_floats_helper::(&[ f64::INFINITY, 1.0, 2.0, 1.5, 0.5, 1.25, 3.0, 1.75, 4.0, 1.125, 2.5, 1.375, 0.75, 1.625, 3.5, 1.875, 0.25, 1.0625, 2.25, 1.1875, 0.625, 1.3125, 2.75, 1.4375, 6.0, 1.5625, 3.25, 1.6875, 0.875, 1.8125, 3.75, 1.9375, 8.0, 1.03125, 2.125, 1.09375, 0.5625, 1.15625, 2.375, 1.21875, 5.0, 1.28125, 2.625, 1.34375, 0.6875, 1.40625, 2.875, 1.46875, 0.375, 1.53125, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_positive_primitive_ints.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::exhaustive_positive_primitive_ints; fn exhaustive_positive_primitive_ints_helper() where u8: ExactFrom, { assert_eq!( exhaustive_positive_primitive_ints::() .map(u8::exact_from) .take(20) .collect_vec(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] ); } fn exhaustive_positive_primitive_ints_long_helper(last_20: &[T]) { let expected_len = if T::MIN == T::ZERO { usize::power_of_2(T::WIDTH) - 1 } else { usize::power_of_2(T::WIDTH - 1) - 1 }; let xs = exhaustive_positive_primitive_ints::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_positive_primitive_ints() { apply_fn_to_primitive_ints!(exhaustive_positive_primitive_ints_helper); exhaustive_positive_primitive_ints_long_helper::(&[ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ]); exhaustive_positive_primitive_ints_long_helper::(&[ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, ]); exhaustive_positive_primitive_ints_long_helper::(&[ 65516, 65517, 65518, 65519, 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9, 0xfffa, 0xfffb, 0xfffc, 0xfffd, u16::MAX - 1, u16::MAX, ]); exhaustive_positive_primitive_ints_long_helper::(&[ 32748, 32749, 32750, 32751, 0x7ff0, 0x7ff1, 0x7ff2, 0x7ff3, 0x7ff4, 0x7ff5, 0x7ff6, 0x7ff7, 0x7ff8, 0x7ff9, 0x7ffa, 0x7ffb, 0x7ffc, 0x7ffd, i16::MAX - 1, i16::MAX, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_float_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::exhaustive_primitive_float_inclusive_range; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; use std::panic::catch_unwind; fn exhaustive_primitive_float_inclusive_range_helper(a: T, b: T, out: &[T]) { exhaustive_primitive_floats_helper_helper( exhaustive_primitive_float_inclusive_range::(a, b), out, ); } #[allow(clippy::approx_constant)] #[test] fn test_exhaustive_primitive_float_inclusive_range() { exhaustive_primitive_float_inclusive_range_helper::(1.0, 1.0, &[1.0]); exhaustive_primitive_float_inclusive_range_helper::( 1.0, 2.0, &[ 1.0, 2.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, ], ); exhaustive_primitive_float_inclusive_range_helper::( -0.1, 0.1, &[ 0.0, -0.0, 0.0625, -0.0625, 0.03125, -0.03125, 0.09375, -0.09375, 0.015625, -0.015625, 0.078125, -0.078125, 0.046875, -0.046875, 0.0703125, -0.0703125, 0.0078125, -0.0078125, 0.0859375, -0.0859375, 0.0390625, -0.0390625, 0.06640625, -0.06640625, 0.0234375, -0.0234375, 0.07421875, -0.07421875, 0.0546875, -0.0546875, 0.08203125, -0.08203125, 0.00390625, -0.00390625, 0.08984375, -0.08984375, 0.03515625, -0.03515625, 0.09765625, -0.09765625, 0.01953125, -0.01953125, 0.064453125, -0.064453125, 0.04296875, -0.04296875, 0.068359375, -0.068359375, 0.01171875, -0.01171875, ], ); exhaustive_primitive_float_inclusive_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_float_inclusive_range_helper::( 100.0, 101.0, &[ 100.0, 101.0, 100.5, 100.25, 100.75, 100.125, 100.375, 100.625, 100.875, 100.0625, 100.1875, 100.3125, 100.4375, 100.5625, 100.6875, 100.8125, 100.9375, 100.03125, 100.09375, 100.15625, 100.21875, 100.28125, 100.34375, 100.40625, 100.46875, 100.53125, 100.59375, 100.65625, 100.71875, 100.78125, 100.84375, 100.90625, 100.96875, 100.015625, 100.046875, 100.078125, 100.109375, 100.140625, 100.171875, 100.203125, 100.234375, 100.265625, 100.296875, 100.328125, 100.359375, 100.390625, 100.421875, 100.453125, 100.484375, 100.515625, ], ); exhaustive_primitive_float_inclusive_range_helper::( 1.0e38, f32::INFINITY, &[ f32::INFINITY, 1.2760589e38, 1.7014118e38, 1.0633824e38, 1.4887354e38, 1.1697206e38, 2.5521178e38, 1.3823971e38, 2.1267648e38, 1.5950736e38, 2.9774707e38, 1.0102133e38, 1.1165515e38, 1.2228898e38, 1.9140883e38, 1.329228e38, 1.4355662e38, 1.5419045e38, 2.3394413e38, 1.6482427e38, 1.0367978e38, 1.089967e38, 2.7647942e38, 1.1431361e38, 3.1901472e38, 1.1963052e38, 1.80775e38, 1.2494743e38, 1.3026434e38, 1.3558126e38, 2.0204266e38, 1.4089817e38, 2.233103e38, 1.4621508e38, 2.4457795e38, 1.5153199e38, 1.568489e38, 1.6216582e38, 2.658456e38, 1.6748273e38, 2.8711325e38, 1.0235056e38, 3.083809e38, 1.0500901e38, 1.0766747e38, 1.1032592e38, 3.2964854e38, 1.1298438e38, 1.1564284e38, 1.1830129e38, ], ); exhaustive_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, 1.0e-45, -1.0e-45], ); exhaustive_primitive_float_inclusive_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, 1.0e-45], ); exhaustive_primitive_float_inclusive_range_helper::( 0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, 1.0e-45], ); exhaustive_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -0.0, &[-0.0, -1.0e-45], ); exhaustive_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, &[0.0, -0.0, -1.0e-45], ); exhaustive_primitive_float_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, &[ f32::INFINITY, f32::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, ], ); exhaustive_primitive_float_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, &[f32::NEGATIVE_INFINITY], ); exhaustive_primitive_float_inclusive_range_helper::( f32::INFINITY, f32::INFINITY, &[f32::INFINITY], ); exhaustive_primitive_float_inclusive_range_helper::(0.0, 0.0, &[0.0]); exhaustive_primitive_float_inclusive_range_helper::(-0.0, -0.0, &[-0.0]); exhaustive_primitive_float_inclusive_range_helper::(-0.0, 0.0, &[0.0, -0.0]); exhaustive_primitive_float_inclusive_range_helper::(1.0, 1.0, &[1.0]); exhaustive_primitive_float_inclusive_range_helper::( 1.0, 2.0, &[ 1.0, 2.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, ], ); exhaustive_primitive_float_inclusive_range_helper::( -0.1, 0.1, &[ 0.0, -0.0, 0.0625, -0.0625, 0.03125, -0.03125, 0.09375, -0.09375, 0.015625, -0.015625, 0.078125, -0.078125, 0.046875, -0.046875, 0.0703125, -0.0703125, 0.0078125, -0.0078125, 0.0859375, -0.0859375, 0.0390625, -0.0390625, 0.06640625, -0.06640625, 0.0234375, -0.0234375, 0.07421875, -0.07421875, 0.0546875, -0.0546875, 0.08203125, -0.08203125, 0.00390625, -0.00390625, 0.08984375, -0.08984375, 0.03515625, -0.03515625, 0.09765625, -0.09765625, 0.01953125, -0.01953125, 0.064453125, -0.064453125, 0.04296875, -0.04296875, 0.068359375, -0.068359375, 0.01171875, -0.01171875, ], ); exhaustive_primitive_float_inclusive_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_float_inclusive_range_helper::( 100.0, 101.0, &[ 100.0, 101.0, 100.5, 100.25, 100.75, 100.125, 100.375, 100.625, 100.875, 100.0625, 100.1875, 100.3125, 100.4375, 100.5625, 100.6875, 100.8125, 100.9375, 100.03125, 100.09375, 100.15625, 100.21875, 100.28125, 100.34375, 100.40625, 100.46875, 100.53125, 100.59375, 100.65625, 100.71875, 100.78125, 100.84375, 100.90625, 100.96875, 100.015625, 100.046875, 100.078125, 100.109375, 100.140625, 100.171875, 100.203125, 100.234375, 100.265625, 100.296875, 100.328125, 100.359375, 100.390625, 100.421875, 100.453125, 100.484375, 100.515625, ], ); exhaustive_primitive_float_inclusive_range_helper::( 1.0e308, f64::INFINITY, &[ f64::INFINITY, 1.348269851146737e308, 1.1235582092889474e308, 1.5729814930045264e308, 1.0112023883600527e308, 1.2359140302178422e308, 1.4606256720756317e308, 1.6853373139334212e308, 1.0673802988245e308, 1.1797361197533948e308, 1.2920919406822896e308, 1.4044477616111843e308, 1.516803582540079e308, 1.6291594034689738e308, 1.7415152243978685e308, 1.0392913435922764e308, 1.0954692540567238e308, 1.1516471645211711e308, 1.2078250749856185e308, 1.2640029854500659e308, 1.3201808959145132e308, 1.3763588063789606e308, 1.432536716843408e308, 1.4887146273078554e308, 1.5448925377723027e308, 1.6010704482367501e308, 1.6572483587011975e308, 1.7134262691656448e308, 1.7696041796300922e308, 1.0252468659761645e308, 1.0533358212083882e308, 1.081424776440612e308, 1.1095137316728356e308, 1.1376026869050593e308, 1.165691642137283e308, 1.1937805973695067e308, 1.2218695526017303e308, 1.249958507833954e308, 1.2780474630661777e308, 1.3061364182984014e308, 1.334225373530625e308, 1.3623143287628488e308, 1.3904032839950725e308, 1.4184922392272961e308, 1.4465811944595198e308, 1.4746701496917435e308, 1.5027591049239672e308, 1.5308480601561909e308, 1.5589370153884146e308, 1.5870259706206383e308, ], ); exhaustive_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, 5.0e-324, -5.0e-324], ); exhaustive_primitive_float_inclusive_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, 5.0e-324], ); exhaustive_primitive_float_inclusive_range_helper::( 0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, 5.0e-324], ); exhaustive_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, &[-0.0, -5.0e-324], ); exhaustive_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, &[0.0, -0.0, -5.0e-324], ); exhaustive_primitive_float_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, &[ f64::INFINITY, f64::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, ], ); exhaustive_primitive_float_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, &[f64::NEGATIVE_INFINITY], ); exhaustive_primitive_float_inclusive_range_helper::( f64::INFINITY, f64::INFINITY, &[f64::INFINITY], ); exhaustive_primitive_float_inclusive_range_helper::(0.0, 0.0, &[0.0]); exhaustive_primitive_float_inclusive_range_helper::(-0.0, -0.0, &[-0.0]); exhaustive_primitive_float_inclusive_range_helper::(-0.0, 0.0, &[0.0, -0.0]); } fn exhaustive_primitive_float_inclusive_range_fail_helper() { assert_panic!(exhaustive_primitive_float_inclusive_range::( T::ONE, T::ZERO )); assert_panic!(exhaustive_primitive_float_inclusive_range::( T::ONE, T::NAN )); } #[test] fn exhaustive_primitive_float_inclusive_range_fail() { apply_fn_to_primitive_floats!(exhaustive_primitive_float_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_float_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::exhaustive_primitive_float_range; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; use std::panic::catch_unwind; fn exhaustive_primitive_float_range_helper(a: T, b: T, out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_primitive_float_range::(a, b), out); } #[allow(clippy::approx_constant)] #[test] fn test_exhaustive_primitive_float_range() { exhaustive_primitive_float_range_helper::(1.0, 1.0, &[]); exhaustive_primitive_float_range_helper::( 1.0, 2.0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, 1.546875, ], ); exhaustive_primitive_float_range_helper::( -0.1, 0.1, &[ 0.0, -0.0, 0.0625, -0.0625, 0.03125, -0.03125, 0.09375, -0.09375, 0.015625, -0.015625, 0.078125, -0.078125, 0.046875, -0.046875, 0.0703125, -0.0703125, 0.0078125, -0.0078125, 0.0859375, -0.0859375, 0.0390625, -0.0390625, 0.06640625, -0.06640625, 0.0234375, -0.0234375, 0.07421875, -0.07421875, 0.0546875, -0.0546875, 0.08203125, -0.08203125, 0.00390625, -0.00390625, 0.08984375, -0.08984375, 0.03515625, -0.03515625, 0.09765625, -0.09765625, 0.01953125, -0.01953125, 0.064453125, -0.064453125, 0.04296875, -0.04296875, 0.068359375, -0.068359375, 0.01171875, -0.01171875, ], ); exhaustive_primitive_float_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_float_range_helper::( 100.0, 101.0, &[ 100.0, 100.5, 100.25, 100.75, 100.125, 100.375, 100.625, 100.875, 100.0625, 100.1875, 100.3125, 100.4375, 100.5625, 100.6875, 100.8125, 100.9375, 100.03125, 100.09375, 100.15625, 100.21875, 100.28125, 100.34375, 100.40625, 100.46875, 100.53125, 100.59375, 100.65625, 100.71875, 100.78125, 100.84375, 100.90625, 100.96875, 100.015625, 100.046875, 100.078125, 100.109375, 100.140625, 100.171875, 100.203125, 100.234375, 100.265625, 100.296875, 100.328125, 100.359375, 100.390625, 100.421875, 100.453125, 100.484375, 100.515625, 100.546875, ], ); exhaustive_primitive_float_range_helper::( 1.0e38, f32::INFINITY, &[ 1.2760589e38, 1.7014118e38, 1.0633824e38, 1.4887354e38, 1.1697206e38, 2.5521178e38, 1.3823971e38, 2.1267648e38, 1.5950736e38, 2.9774707e38, 1.0102133e38, 1.1165515e38, 1.2228898e38, 1.9140883e38, 1.329228e38, 1.4355662e38, 1.5419045e38, 2.3394413e38, 1.6482427e38, 1.0367978e38, 1.089967e38, 2.7647942e38, 1.1431361e38, 3.1901472e38, 1.1963052e38, 1.80775e38, 1.2494743e38, 1.3026434e38, 1.3558126e38, 2.0204266e38, 1.4089817e38, 2.233103e38, 1.4621508e38, 2.4457795e38, 1.5153199e38, 1.568489e38, 1.6216582e38, 2.658456e38, 1.6748273e38, 2.8711325e38, 1.0235056e38, 3.083809e38, 1.0500901e38, 1.0766747e38, 1.1032592e38, 3.2964854e38, 1.1298438e38, 1.1564284e38, 1.1830129e38, 1.754581e38, ], ); exhaustive_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, -1.0e-45], ); exhaustive_primitive_float_range_helper::(-0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0]); exhaustive_primitive_float_range_helper::(0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0]); exhaustive_primitive_float_range_helper::(-f32::MIN_POSITIVE_SUBNORMAL, -0.0, &[-1.0e-45]); exhaustive_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, &[-0.0, -1.0e-45], ); exhaustive_primitive_float_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, &[ f32::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, ], ); exhaustive_primitive_float_range_helper::( f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, &[], ); exhaustive_primitive_float_range_helper::(f32::INFINITY, f32::INFINITY, &[]); exhaustive_primitive_float_range_helper::(0.0, 0.0, &[]); exhaustive_primitive_float_range_helper::(-0.0, -0.0, &[]); exhaustive_primitive_float_range_helper::(-0.0, 0.0, &[-0.0]); exhaustive_primitive_float_range_helper::(1.0, 1.0, &[]); exhaustive_primitive_float_range_helper::( 1.0, 2.0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, 1.546875, ], ); exhaustive_primitive_float_range_helper::( -0.1, 0.1, &[ 0.0, -0.0, 0.0625, -0.0625, 0.03125, -0.03125, 0.09375, -0.09375, 0.015625, -0.015625, 0.078125, -0.078125, 0.046875, -0.046875, 0.0703125, -0.0703125, 0.0078125, -0.0078125, 0.0859375, -0.0859375, 0.0390625, -0.0390625, 0.06640625, -0.06640625, 0.0234375, -0.0234375, 0.07421875, -0.07421875, 0.0546875, -0.0546875, 0.08203125, -0.08203125, 0.00390625, -0.00390625, 0.08984375, -0.08984375, 0.03515625, -0.03515625, 0.09765625, -0.09765625, 0.01953125, -0.01953125, 0.064453125, -0.064453125, 0.04296875, -0.04296875, 0.068359375, -0.068359375, 0.01171875, -0.01171875, ], ); exhaustive_primitive_float_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_float_range_helper::( 100.0, 101.0, &[ 100.0, 100.5, 100.25, 100.75, 100.125, 100.375, 100.625, 100.875, 100.0625, 100.1875, 100.3125, 100.4375, 100.5625, 100.6875, 100.8125, 100.9375, 100.03125, 100.09375, 100.15625, 100.21875, 100.28125, 100.34375, 100.40625, 100.46875, 100.53125, 100.59375, 100.65625, 100.71875, 100.78125, 100.84375, 100.90625, 100.96875, 100.015625, 100.046875, 100.078125, 100.109375, 100.140625, 100.171875, 100.203125, 100.234375, 100.265625, 100.296875, 100.328125, 100.359375, 100.390625, 100.421875, 100.453125, 100.484375, 100.515625, 100.546875, ], ); exhaustive_primitive_float_range_helper::( 1.0e308, f64::INFINITY, &[ 1.348269851146737e308, 1.1235582092889474e308, 1.5729814930045264e308, 1.0112023883600527e308, 1.2359140302178422e308, 1.4606256720756317e308, 1.6853373139334212e308, 1.0673802988245e308, 1.1797361197533948e308, 1.2920919406822896e308, 1.4044477616111843e308, 1.516803582540079e308, 1.6291594034689738e308, 1.7415152243978685e308, 1.0392913435922764e308, 1.0954692540567238e308, 1.1516471645211711e308, 1.2078250749856185e308, 1.2640029854500659e308, 1.3201808959145132e308, 1.3763588063789606e308, 1.432536716843408e308, 1.4887146273078554e308, 1.5448925377723027e308, 1.6010704482367501e308, 1.6572483587011975e308, 1.7134262691656448e308, 1.7696041796300922e308, 1.0252468659761645e308, 1.0533358212083882e308, 1.081424776440612e308, 1.1095137316728356e308, 1.1376026869050593e308, 1.165691642137283e308, 1.1937805973695067e308, 1.2218695526017303e308, 1.249958507833954e308, 1.2780474630661777e308, 1.3061364182984014e308, 1.334225373530625e308, 1.3623143287628488e308, 1.3904032839950725e308, 1.4184922392272961e308, 1.4465811944595198e308, 1.4746701496917435e308, 1.5027591049239672e308, 1.5308480601561909e308, 1.5589370153884146e308, 1.5870259706206383e308, 1.615114925852862e308, ], ); exhaustive_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0, -5.0e-324], ); exhaustive_primitive_float_range_helper::(-0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, -0.0]); exhaustive_primitive_float_range_helper::(0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0]); exhaustive_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, &[-5.0e-324], ); exhaustive_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, &[-0.0, -5.0e-324], ); exhaustive_primitive_float_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, &[ f64::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, -1.4375, 6.0, ], ); exhaustive_primitive_float_range_helper::( f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, &[], ); exhaustive_primitive_float_range_helper::(f64::INFINITY, f64::INFINITY, &[]); exhaustive_primitive_float_range_helper::(0.0, 0.0, &[]); exhaustive_primitive_float_range_helper::(-0.0, -0.0, &[]); exhaustive_primitive_float_range_helper::(-0.0, 0.0, &[-0.0]); } fn exhaustive_primitive_float_range_fail_helper() { assert_panic!(exhaustive_primitive_float_range::(T::ONE, T::ZERO)); assert_panic!(exhaustive_primitive_float_range::(T::ONE, T::NAN)); } #[test] fn exhaustive_primitive_float_range_fail() { apply_fn_to_primitive_floats!(exhaustive_primitive_float_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::exhaustive_primitive_floats; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; fn exhaustive_primitive_floats_helper(out: &[T]) { exhaustive_primitive_floats_helper_helper(exhaustive_primitive_floats::(), out); } #[test] fn test_exhaustive_primitive_floats() { exhaustive_primitive_floats_helper::(&[ f32::NAN, f32::INFINITY, f32::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, ]); exhaustive_primitive_floats_helper::(&[ f64::NAN, f64::INFINITY, f64::NEGATIVE_INFINITY, 0.0, -0.0, 1.0, -1.0, 2.0, -2.0, 1.5, -1.5, 0.5, -0.5, 1.25, -1.25, 3.0, -3.0, 1.75, -1.75, 4.0, -4.0, 1.125, -1.125, 2.5, -2.5, 1.375, -1.375, 0.75, -0.75, 1.625, -1.625, 3.5, -3.5, 1.875, -1.875, 0.25, -0.25, 1.0625, -1.0625, 2.25, -2.25, 1.1875, -1.1875, 0.625, -0.625, 1.3125, -1.3125, 2.75, -2.75, 1.4375, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_floats_with_sci_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_primitive_floats_with_sci_exponent; use malachite_base::test_util::num::exhaustive::*; use std::panic::catch_unwind; fn exhaustive_primitive_floats_with_sci_exponent_helper( sci_exponent: i64, out: &[T], ) { exhaustive_primitive_floats_helper_helper_with_limit( 20, exhaustive_primitive_floats_with_sci_exponent::(sci_exponent), out, ); } #[test] fn test_exhaustive_primitive_floats_with_sci_exponent() { exhaustive_primitive_floats_with_sci_exponent_helper::( 0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::( 4, &[ 16.0, 24.0, 20.0, 28.0, 18.0, 22.0, 26.0, 30.0, 17.0, 19.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0, 16.5, 17.5, 18.5, 19.5, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::( -4, &[ 0.0625, 0.09375, 0.078125, 0.109375, 0.0703125, 0.0859375, 0.1015625, 0.1171875, 0.06640625, 0.07421875, 0.08203125, 0.08984375, 0.09765625, 0.10546875, 0.11328125, 0.12109375, 0.064453125, 0.068359375, 0.072265625, 0.076171875, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::(-149, &[1.0e-45]); exhaustive_primitive_floats_with_sci_exponent_helper::(-148, &[3.0e-45, 4.0e-45]); exhaustive_primitive_floats_with_sci_exponent_helper::( -147, &[6.0e-45, 8.0e-45, 7.0e-45, 1.0e-44], ); exhaustive_primitive_floats_with_sci_exponent_helper::( 127, &[ 1.7014118e38, 2.5521178e38, 2.1267648e38, 2.9774707e38, 1.9140883e38, 2.3394413e38, 2.7647942e38, 3.1901472e38, 1.80775e38, 2.0204266e38, 2.233103e38, 2.4457795e38, 2.658456e38, 2.8711325e38, 3.083809e38, 3.2964854e38, 1.754581e38, 1.8609192e38, 1.9672574e38, 2.0735957e38, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::( 0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::( 4, &[ 16.0, 24.0, 20.0, 28.0, 18.0, 22.0, 26.0, 30.0, 17.0, 19.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0, 16.5, 17.5, 18.5, 19.5, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::( -4, &[ 0.0625, 0.09375, 0.078125, 0.109375, 0.0703125, 0.0859375, 0.1015625, 0.1171875, 0.06640625, 0.07421875, 0.08203125, 0.08984375, 0.09765625, 0.10546875, 0.11328125, 0.12109375, 0.064453125, 0.068359375, 0.072265625, 0.076171875, ], ); exhaustive_primitive_floats_with_sci_exponent_helper::(-1074, &[5.0e-324]); exhaustive_primitive_floats_with_sci_exponent_helper::(-1073, &[1.0e-323, 1.5e-323]); exhaustive_primitive_floats_with_sci_exponent_helper::( -1072, &[2.0e-323, 3.0e-323, 2.5e-323, 3.5e-323], ); exhaustive_primitive_floats_with_sci_exponent_helper::( 1023, &[ 8.98846567431158e307, 1.348269851146737e308, 1.1235582092889474e308, 1.5729814930045264e308, 1.0112023883600527e308, 1.2359140302178422e308, 1.4606256720756317e308, 1.6853373139334212e308, 9.550244778956053e307, 1.0673802988245e308, 1.1797361197533948e308, 1.2920919406822896e308, 1.4044477616111843e308, 1.516803582540079e308, 1.6291594034689738e308, 1.7415152243978685e308, 9.269355226633816e307, 9.83113433127829e307, 1.0392913435922764e308, 1.0954692540567238e308, ], ); } fn exhaustive_primitive_floats_with_sci_exponent_fail_helper() { assert_panic!(exhaustive_primitive_floats_with_sci_exponent::(10000)); assert_panic!(exhaustive_primitive_floats_with_sci_exponent::(-10000)); } #[test] fn exhaustive_primitive_floats_with_sci_exponent_fail() { apply_fn_to_primitive_floats!(exhaustive_primitive_floats_with_sci_exponent_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_floats_with_sci_exponent_and_precision.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_primitive_floats_with_sci_exponent_and_precision; use malachite_base::test_util::num::exhaustive::*; use std::panic::catch_unwind; fn exhaustive_primitive_floats_with_sci_exponent_and_precision_helper( sci_exponent: i64, precision: u64, out: &[T], ) { exhaustive_primitive_floats_helper_helper_with_limit( 20, exhaustive_primitive_floats_with_sci_exponent_and_precision::(sci_exponent, precision), out, ); } #[test] fn test_exhaustive_primitive_floats_with_sci_exponent_and_precision() { exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 1, &[1.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 2, &[1.5]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 3, &[1.25, 1.75]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 0, 4, &[1.125, 1.375, 1.625, 1.875], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 0, 5, &[1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 1, &[16.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 2, &[24.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 3, &[20.0, 28.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 4, 4, &[18.0, 22.0, 26.0, 30.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 4, 5, &[17.0, 19.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-4, 1, &[0.0625]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-4, 2, &[0.09375]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 3, &[0.078125, 0.109375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 4, &[0.0703125, 0.0859375, 0.1015625, 0.1171875], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 5, &[ 0.06640625, 0.07421875, 0.08203125, 0.08984375, 0.09765625, 0.10546875, 0.11328125, 0.12109375, ], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-149, 1, &[1.0e-45]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-148, 1, &[3.0e-45]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-148, 2, &[4.0e-45]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-147, 1, &[6.0e-45]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-147, 2, &[8.0e-45]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -147, 3, &[7.0e-45, 1.0e-44], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 1, &[1.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 2, &[1.5]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(0, 3, &[1.25, 1.75]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 0, 4, &[1.125, 1.375, 1.625, 1.875], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 0, 5, &[1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 1, &[16.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 2, &[24.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(4, 3, &[20.0, 28.0]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 4, 4, &[18.0, 22.0, 26.0, 30.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( 4, 5, &[17.0, 19.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-4, 1, &[0.0625]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::(-4, 2, &[0.09375]); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 3, &[0.078125, 0.109375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 4, &[0.0703125, 0.0859375, 0.1015625, 0.1171875], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -4, 5, &[ 0.06640625, 0.07421875, 0.08203125, 0.08984375, 0.09765625, 0.10546875, 0.11328125, 0.12109375, ], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1074, 1, &[5.0e-324], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1073, 1, &[1.0e-323], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1073, 2, &[1.5e-323], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1072, 1, &[2.0e-323], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1072, 2, &[3.0e-323], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_helper::( -1072, 3, &[2.5e-323, 3.5e-323], ); } fn exhaustive_primitive_floats_with_sci_exponent_and_precision_fail_helper() { assert_panic!(exhaustive_primitive_floats_with_sci_exponent_and_precision::(0, 0)); assert_panic!(exhaustive_primitive_floats_with_sci_exponent_and_precision::(0, 100)); assert_panic!(exhaustive_primitive_floats_with_sci_exponent_and_precision::(10000, 1)); assert_panic!(exhaustive_primitive_floats_with_sci_exponent_and_precision::(-10000, 1)); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision::(T::MIN_EXPONENT, 2) ); } #[test] fn exhaustive_primitive_floats_with_sci_exponent_and_precision_fail() { apply_fn_to_primitive_floats!( exhaustive_primitive_floats_with_sci_exponent_and_precision_fail_helper ); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::*; use malachite_base::test_util::num::exhaustive::*; use std::panic::catch_unwind; fn exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper< T: PrimitiveFloat, >( a: T, b: T, sci_exponent: i64, precision: u64, out: &[T], ) { exhaustive_primitive_floats_helper_helper_with_limit( 20, exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( a, b, sci_exponent, precision, ), out, ); } #[test] fn test_exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range() { exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 2, &[3.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 3, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 4, &[2.75], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 5, &[2.875, 3.125], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 6, &[2.8125, 2.9375, 3.0625], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, 7, &[2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 2, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 3, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 4, &[1920.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 5, &[1984.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 6, &[1952.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 7, &[1904.0, 1936.0, 1968.0, 2000.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 2, &[8.0e-45], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 3, &[7.0e-45, 1.0e-44], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1.0, 1.99, 0, 1, &[1.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 2, &[3.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 3, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 4, &[2.75], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 5, &[2.875, 3.125], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 6, &[2.8125, 2.9375, 3.0625], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, 7, &[2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 2, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 3, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 4, &[1920.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 5, &[1984.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 6, &[1952.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1900.0, 2000.0, 10, 7, &[1904.0, 1936.0, 1968.0, 2000.0], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 1, &[], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 2, &[8.407790785948902e-45], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 7.0e-45, 1.0e-44, -147, 3, &[7.006492321624085e-45, 9.80908925027372e-45], ); exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_helper::( 1.0, 1.99, 0, 1, &[1.0], ); } fn exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_fail_helper< T: PrimitiveFloat, >() { assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.1), T::from(1.2), 0, 0 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.1), T::from(1.2), 0, 100 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.1), T::from(1.2), 10000, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.1), T::from(1.2), -10000, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::MIN_POSITIVE_SUBNORMAL, T::MIN_POSITIVE_SUBNORMAL, T::MIN_EXPONENT, 2 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.2), T::from(1.1), 0, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(1.1), T::from(1.2), 1, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(0.1), T::from(1.2), 1, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::from(-1.2), T::from(1.1), 0, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::ONE, T::INFINITY, 0, 1 ) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range::( T::ONE, T::NAN, 0, 1 ) ); } #[test] fn exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_fail() { apply_fn_to_primitive_floats!( exhaustive_primitive_floats_with_sci_exponent_and_precision_in_range_fail_helper ); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_primitive_floats_with_sci_exponent_in_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::exhaustive_primitive_floats_with_sci_exponent_in_range; use malachite_base::test_util::num::exhaustive::exhaustive_primitive_floats_helper_helper; use std::panic::catch_unwind; fn exhaustive_primitive_floats_with_sci_exponent_in_range_helper( a: T, b: T, sci_exponent: i64, out: &[T], ) { exhaustive_primitive_floats_helper_helper( exhaustive_primitive_floats_with_sci_exponent_in_range::(a, b, sci_exponent), out, ); } #[test] fn test_exhaustive_primitive_floats_with_sci_exponent_in_range() { exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( core::f32::consts::E, core::f32::consts::PI, 1, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1900.0, 2000.0, 10, &[ 1920.0, 1984.0, 1952.0, 1904.0, 1936.0, 1968.0, 2000.0, 1912.0, 1928.0, 1944.0, 1960.0, 1976.0, 1992.0, 1900.0, 1908.0, 1916.0, 1924.0, 1932.0, 1940.0, 1948.0, 1956.0, 1964.0, 1972.0, 1980.0, 1988.0, 1996.0, 1902.0, 1906.0, 1910.0, 1914.0, 1918.0, 1922.0, 1926.0, 1930.0, 1934.0, 1938.0, 1942.0, 1946.0, 1950.0, 1954.0, 1958.0, 1962.0, 1966.0, 1970.0, 1974.0, 1978.0, 1982.0, 1986.0, 1990.0, 1994.0, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 7.0e-45, 1.0e-44, -147, &[8.0e-45, 7.0e-45, 1.0e-44], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1000000.0, 1000001.0, 19, &[ 1000000.0, 1000001.0, 1000000.5, 1000000.25, 1000000.75, 1000000.1, 1000000.4, 1000000.6, 1000000.9, 1000000.06, 1000000.2, 1000000.3, 1000000.44, 1000000.56, 1000000.7, 1000000.8, 1000000.94, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1.0, 1.99, 0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, 1.546875, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::(5.0, 5.0, 2, &[5.0]); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( core::f64::consts::E, core::f64::consts::PI, 1, &[ 3.0, 2.75, 2.875, 3.125, 2.8125, 2.9375, 3.0625, 2.71875, 2.78125, 2.84375, 2.90625, 2.96875, 3.03125, 3.09375, 2.734375, 2.765625, 2.796875, 2.828125, 2.859375, 2.890625, 2.921875, 2.953125, 2.984375, 3.015625, 3.046875, 3.078125, 3.109375, 3.140625, 2.7265625, 2.7421875, 2.7578125, 2.7734375, 2.7890625, 2.8046875, 2.8203125, 2.8359375, 2.8515625, 2.8671875, 2.8828125, 2.8984375, 2.9140625, 2.9296875, 2.9453125, 2.9609375, 2.9765625, 2.9921875, 3.0078125, 3.0234375, 3.0390625, 3.0546875, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1900.0, 2000.0, 10, &[ 1920.0, 1984.0, 1952.0, 1904.0, 1936.0, 1968.0, 2000.0, 1912.0, 1928.0, 1944.0, 1960.0, 1976.0, 1992.0, 1900.0, 1908.0, 1916.0, 1924.0, 1932.0, 1940.0, 1948.0, 1956.0, 1964.0, 1972.0, 1980.0, 1988.0, 1996.0, 1902.0, 1906.0, 1910.0, 1914.0, 1918.0, 1922.0, 1926.0, 1930.0, 1934.0, 1938.0, 1942.0, 1946.0, 1950.0, 1954.0, 1958.0, 1962.0, 1966.0, 1970.0, 1974.0, 1978.0, 1982.0, 1986.0, 1990.0, 1994.0, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 7.0e-45, 1.0e-44, -147, &[ 8.407790785948902e-45, 7.006492321624085e-45, 9.80908925027372e-45, 7.707141553786494e-45, 9.108440018111311e-45, 7.35681693770529e-45, 8.057466169867698e-45, 8.758115402030107e-45, 9.458764634192515e-45, 7.181654629664687e-45, 7.531979245745892e-45, 7.882303861827096e-45, 8.2326284779083e-45, 8.582953093989505e-45, 8.933277710070709e-45, 9.283602326151913e-45, 9.633926942233117e-45, 9.984251558314322e-45, 7.094073475644386e-45, 7.269235783684989e-45, 7.444398091725591e-45, 7.619560399766193e-45, 7.794722707806795e-45, 7.969885015847397e-45, 8.145047323887999e-45, 8.320209631928601e-45, 8.495371939969203e-45, 8.670534248009806e-45, 8.845696556050408e-45, 9.02085886409101e-45, 9.196021172131612e-45, 9.371183480172214e-45, 9.546345788212816e-45, 9.721508096253418e-45, 9.89667040429402e-45, 7.050282898634236e-45, 7.137864052654537e-45, 7.225445206674838e-45, 7.313026360695139e-45, 7.40060751471544e-45, 7.488188668735741e-45, 7.575769822756042e-45, 7.663350976776343e-45, 7.750932130796644e-45, 7.838513284816945e-45, 7.926094438837247e-45, 8.013675592857548e-45, 8.101256746877849e-45, 8.18883790089815e-45, 8.276419054918451e-45, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1000000.0, 1000001.0, 19, &[ 1000000.0, 1000001.0, 1000000.5, 1000000.25, 1000000.75, 1000000.125, 1000000.375, 1000000.625, 1000000.875, 1000000.0625, 1000000.1875, 1000000.3125, 1000000.4375, 1000000.5625, 1000000.6875, 1000000.8125, 1000000.9375, 1000000.03125, 1000000.09375, 1000000.15625, 1000000.21875, 1000000.28125, 1000000.34375, 1000000.40625, 1000000.46875, 1000000.53125, 1000000.59375, 1000000.65625, 1000000.71875, 1000000.78125, 1000000.84375, 1000000.90625, 1000000.96875, 1000000.015625, 1000000.046875, 1000000.078125, 1000000.109375, 1000000.140625, 1000000.171875, 1000000.203125, 1000000.234375, 1000000.265625, 1000000.296875, 1000000.328125, 1000000.359375, 1000000.390625, 1000000.421875, 1000000.453125, 1000000.484375, 1000000.515625, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::( 1.0, 1.99, 0, &[ 1.0, 1.5, 1.25, 1.75, 1.125, 1.375, 1.625, 1.875, 1.0625, 1.1875, 1.3125, 1.4375, 1.5625, 1.6875, 1.8125, 1.9375, 1.03125, 1.09375, 1.15625, 1.21875, 1.28125, 1.34375, 1.40625, 1.46875, 1.53125, 1.59375, 1.65625, 1.71875, 1.78125, 1.84375, 1.90625, 1.96875, 1.015625, 1.046875, 1.078125, 1.109375, 1.140625, 1.171875, 1.203125, 1.234375, 1.265625, 1.296875, 1.328125, 1.359375, 1.390625, 1.421875, 1.453125, 1.484375, 1.515625, 1.546875, ], ); exhaustive_primitive_floats_with_sci_exponent_in_range_helper::(5.0, 5.0, 2, &[5.0]); } fn exhaustive_primitive_floats_with_sci_exponent_in_range_fail_helper() { assert_panic!(exhaustive_primitive_floats_with_sci_exponent_in_range::( T::from(1.1), T::from(1.2), 10000, )); assert_panic!(exhaustive_primitive_floats_with_sci_exponent_in_range::( T::from(1.1), T::from(1.2), -10000, )); assert_panic!(exhaustive_primitive_floats_with_sci_exponent_in_range::( T::from(-1.2), T::from(1.1), 0, ) .for_each(|_| {})); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_in_range::(T::ONE, T::INFINITY, 0,) .for_each(|_| {}) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_in_range::(T::ONE, T::NAN, 0) .for_each(|_| {}) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_in_range::(T::from(1.2), T::from(1.1), 0,) .for_each(|_| {}) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_in_range::(T::from(1.1), T::from(1.2), 1,) .for_each(|_| {}) ); assert_panic!( exhaustive_primitive_floats_with_sci_exponent_in_range::(T::from(0.1), T::from(1.2), 1,) .for_each(|_| {}) ); } #[test] fn exhaustive_primitive_floats_with_sci_exponent_in_range_fail() { apply_fn_to_primitive_floats!( exhaustive_primitive_floats_with_sci_exponent_in_range_fail_helper ); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_signed_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::exhaustive::exhaustive_signed_inclusive_range; use std::panic::catch_unwind; fn expected_range_len(a: T, b: T) -> usize where usize: WrappingFrom, { usize::wrapping_from(b).wrapping_sub(usize::wrapping_from(a)) + 1 } fn exhaustive_signed_inclusive_range_helper_helper(a: T, b: T, values: &[i8]) where i8: ExactFrom, usize: WrappingFrom, { let xs = exhaustive_signed_inclusive_range::(a, b) .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!(xs, values); if T::WIDTH <= u16::WIDTH { assert_eq!( exhaustive_signed_inclusive_range(a, b).count(), expected_range_len(a, b) ); } } fn exhaustive_signed_inclusive_range_rev_helper(a: T, b: T, rev_values: &[T]) where usize: WrappingFrom, { let len = expected_range_len(a, b); assert_eq!(exhaustive_signed_inclusive_range(a, b).count(), len); let mut tail = exhaustive_signed_inclusive_range::(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(tail, rev_values); } fn exhaustive_signed_inclusive_range_helper() where i8: ExactFrom, usize: WrappingFrom, { exhaustive_signed_inclusive_range_helper_helper(T::ZERO, T::ZERO, &[0]); exhaustive_signed_inclusive_range_helper_helper( T::ZERO, T::exact_from(9), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ); exhaustive_signed_inclusive_range_helper_helper( T::exact_from(10), T::exact_from(19), &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_inclusive_range_helper_helper( T::ZERO, T::MAX, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_inclusive_range_helper_helper( T::ZERO, T::MAX - T::ONE, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_inclusive_range_helper_helper( T::exact_from(-20), T::exact_from(-11), &[-11, -12, -13, -14, -15, -16, -17, -18, -19, -20], ); exhaustive_signed_inclusive_range_helper_helper( T::exact_from(-100), T::exact_from(99), &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); exhaustive_signed_inclusive_range_helper_helper( T::MIN, T::MAX, &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); exhaustive_signed_inclusive_range_helper_helper( T::MIN + T::ONE, T::MAX - T::ONE, &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); } #[test] fn test_exhaustive_signed_inclusive_range() { apply_fn_to_signeds!(exhaustive_signed_inclusive_range_helper); exhaustive_signed_inclusive_range_rev_helper::( i8::MIN, i8::MAX, &[ -128, -127, 127, -126, 126, -125, 125, -124, 124, -123, 123, -122, 122, -121, 121, -120, 120, -119, 119, -118, ], ); exhaustive_signed_inclusive_range_rev_helper::( i8::MIN + 1, i8::MAX - 1, &[ -127, -126, 126, -125, 125, -124, 124, -123, 123, -122, 122, -121, 121, -120, 120, -119, 119, -118, 118, -117, ], ); exhaustive_signed_inclusive_range_rev_helper::( i16::MIN, i16::MAX, &[ -32768, -32767, 32767, -32766, 32766, -32765, 32765, -32764, 32764, -32763, 32763, -32762, 32762, -32761, 32761, -32760, 32760, -32759, 32759, -32758, ], ); exhaustive_signed_inclusive_range_rev_helper::( i16::MIN + 1, i16::MAX - 1, &[ -32767, -32766, 32766, -32765, 32765, -32764, 32764, -32763, 32763, -32762, 32762, -32761, 32761, -32760, 32760, -32759, 32759, -32758, 32758, -32757, ], ); } fn exhaustive_signed_inclusive_range_fail_helper() { assert_panic!(exhaustive_signed_inclusive_range::(T::ONE, T::ZERO)); } #[test] fn exhaustive_signed_inclusive_range_fail() { apply_fn_to_signeds!(exhaustive_signed_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_signed_range.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::exhaustive::exhaustive_signed_range; use std::panic::catch_unwind; fn expected_range_len(a: T, b: T) -> usize where usize: WrappingFrom, { usize::wrapping_from(b).wrapping_sub(usize::wrapping_from(a)) } fn exhaustive_signed_range_helper_helper(a: T, b: T, values: &[i8]) where i8: ExactFrom, usize: WrappingFrom, { let xs = exhaustive_signed_range::(a, b) .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!(xs, values); if T::WIDTH <= u16::WIDTH { assert_eq!( exhaustive_signed_range(a, b).count(), expected_range_len(a, b) ); } } fn exhaustive_signed_range_rev_helper(a: T, b: T, rev_values: &[T]) where usize: WrappingFrom, { let len = expected_range_len(a, b); assert_eq!(exhaustive_signed_range(a, b).count(), len); let mut tail = exhaustive_signed_range::(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(tail, rev_values); } fn exhaustive_signed_range_helper() where i8: ExactFrom, usize: WrappingFrom, { exhaustive_signed_range_helper_helper(T::ZERO, T::ZERO, &[]); exhaustive_signed_range_helper_helper(T::ZERO, T::ONE, &[0]); exhaustive_signed_range_helper_helper( T::ZERO, T::exact_from(10), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ); exhaustive_signed_range_helper_helper( T::exact_from(10), T::exact_from(20), &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_range_helper_helper( T::ZERO, T::MAX, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_range_helper_helper( T::ZERO, T::MAX - T::ONE, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); exhaustive_signed_range_helper_helper( T::exact_from(-20), T::exact_from(-10), &[-11, -12, -13, -14, -15, -16, -17, -18, -19, -20], ); exhaustive_signed_range_helper_helper( T::exact_from(-100), T::exact_from(100), &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); exhaustive_signed_range_helper_helper( T::MIN, T::MAX, &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); exhaustive_signed_range_helper_helper( T::MIN + T::ONE, T::MAX - T::ONE, &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10], ); } #[test] fn test_exhaustive_signed_range() { apply_fn_to_signeds!(exhaustive_signed_range_helper); exhaustive_signed_range_rev_helper::( i8::MIN, i8::MAX, &[ -128, -127, -126, 126, -125, 125, -124, 124, -123, 123, -122, 122, -121, 121, -120, 120, -119, 119, -118, 118, ], ); exhaustive_signed_range_rev_helper::( i8::MIN + 1, i8::MAX - 1, &[ -127, -126, -125, 125, -124, 124, -123, 123, -122, 122, -121, 121, -120, 120, -119, 119, -118, 118, -117, 117, ], ); exhaustive_signed_range_rev_helper::( i16::MIN, i16::MAX, &[ -32768, -32767, -32766, 32766, -32765, 32765, -32764, 32764, -32763, 32763, -32762, 32762, -32761, 32761, -32760, 32760, -32759, 32759, -32758, 32758, ], ); exhaustive_signed_range_rev_helper::( i16::MIN + 1, i16::MAX - 1, &[ -32767, -32766, -32765, 32765, -32764, 32764, -32763, 32763, -32762, 32762, -32761, 32761, -32760, 32760, -32759, 32759, -32758, 32758, -32757, 32757, ], ); } fn exhaustive_signed_range_fail_helper() { assert_panic!(exhaustive_signed_range::(T::ONE, T::ZERO)); } #[test] fn exhaustive_signed_range_fail() { apply_fn_to_signeds!(exhaustive_signed_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_signeds.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::exhaustive_signeds; fn exhaustive_signeds_helper() where i8: ExactFrom, { assert_eq!( exhaustive_signeds::() .map(i8::exact_from) .take(20) .collect_vec(), &[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10] ); } fn exhaustive_signeds_long_helper(last_20: &[T]) { let expected_len = usize::power_of_2(T::WIDTH); let xs = exhaustive_signeds::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_signeds() { apply_fn_to_signeds!(exhaustive_signeds_helper); exhaustive_signeds_long_helper::(&[ -118, 119, -119, 120, -120, 121, -121, 122, -122, 123, -123, 124, -124, 125, -125, 126, -126, 127, -127, -128, ]); exhaustive_signeds_long_helper::(&[ -0x7ff6, 0x7ff7, -0x7ff7, 0x7ff8, -0x7ff8, 0x7ff9, -0x7ff9, 0x7ffa, -0x7ffa, 0x7ffb, -0x7ffb, 0x7ffc, -0x7ffc, 0x7ffd, -0x7ffd, i16::MAX - 1, -0x7ffe, i16::MAX, i16::MIN + 1, i16::MIN, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/exhaustive_unsigneds.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::exhaustive::exhaustive_unsigneds; fn exhaustive_unsigneds_helper() where u8: ExactFrom, { assert_eq!( exhaustive_unsigneds::() .map(u8::exact_from) .take(20) .collect_vec(), &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] ); } fn exhaustive_unsigneds_long_helper(last_20: &[T]) { let expected_len = usize::power_of_2(T::WIDTH); let xs = exhaustive_unsigneds::(); assert_eq!(xs.clone().count(), expected_len); assert_eq!(xs.skip(expected_len - 20).collect_vec(), last_20); } #[test] fn test_exhaustive_unsigneds() { apply_fn_to_unsigneds!(exhaustive_unsigneds_helper); exhaustive_unsigneds_long_helper::(&[ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ]); exhaustive_unsigneds_long_helper::(&[ 65516, 65517, 65518, 65519, 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff7, 0xfff8, 0xfff9, 0xfffa, 0xfffb, 0xfffc, 0xfffd, u16::MAX - 1, u16::MAX, ]); } ================================================ FILE: malachite-base/tests/num/exhaustive/finite_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::finite_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn finite_primitive_floats_increasing_helper(first_20: &[T], last_20: &[T]) { exhaustive_primitive_floats_helper_helper_with_reverse( finite_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_finite_primitive_floats_increasing() { finite_primitive_floats_increasing_helper::( &[ -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, -3.4028196e38, ], &[ 3.4028196e38, 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, ], ); finite_primitive_floats_increasing_helper::( &[ -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, -1.797693134862312e308, ], &[ 1.797693134862312e308, 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/negative_finite_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::negative_finite_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn negative_finite_primitive_floats_increasing_helper( first_20: &[T], last_20: &[T], ) { exhaustive_primitive_floats_helper_helper_with_reverse( negative_finite_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_negative_finite_primitive_floats_increasing() { negative_finite_primitive_floats_increasing_helper::( &[ -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, -3.4028196e38, ], &[ -2.8e-44, -2.7e-44, -2.5e-44, -2.4e-44, -2.2e-44, -2.1e-44, -2.0e-44, -1.8e-44, -1.7e-44, -1.5e-44, -1.4e-44, -1.3e-44, -1.1e-44, -1.0e-44, -8.0e-45, -7.0e-45, -6.0e-45, -4.0e-45, -3.0e-45, -1.0e-45, ], ); negative_finite_primitive_floats_increasing_helper::( &[ -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, -1.797693134862312e308, ], &[ -1.0e-322, -9.4e-323, -9.0e-323, -8.4e-323, -8.0e-323, -7.4e-323, -7.0e-323, -6.4e-323, -6.0e-323, -5.4e-323, -5.0e-323, -4.4e-323, -4.0e-323, -3.5e-323, -3.0e-323, -2.5e-323, -2.0e-323, -1.5e-323, -1.0e-323, -5.0e-324, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/negative_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::negative_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn negative_primitive_floats_increasing_helper(first_20: &[T], last_20: &[T]) { exhaustive_primitive_floats_helper_helper_with_reverse( negative_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_negative_primitive_floats_increasing() { negative_primitive_floats_increasing_helper::( &[ f32::NEGATIVE_INFINITY, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, ], &[ -2.8e-44, -2.7e-44, -2.5e-44, -2.4e-44, -2.2e-44, -2.1e-44, -2.0e-44, -1.8e-44, -1.7e-44, -1.5e-44, -1.4e-44, -1.3e-44, -1.1e-44, -1.0e-44, -8.0e-45, -7.0e-45, -6.0e-45, -4.0e-45, -3.0e-45, -1.0e-45, ], ); negative_primitive_floats_increasing_helper::( &[ f64::NEGATIVE_INFINITY, -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, ], &[ -1.0e-322, -9.4e-323, -9.0e-323, -8.4e-323, -8.0e-323, -7.4e-323, -7.0e-323, -6.4e-323, -6.0e-323, -5.4e-323, -5.0e-323, -4.4e-323, -4.0e-323, -3.5e-323, -3.0e-323, -2.5e-323, -2.0e-323, -1.5e-323, -1.0e-323, -5.0e-324, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/nonzero_finite_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::nonzero_finite_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn nonzero_finite_primitive_floats_increasing_helper( first_20: &[T], last_20: &[T], ) { exhaustive_primitive_floats_helper_helper_with_reverse( nonzero_finite_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_nonzero_finite_primitive_floats_increasing() { nonzero_finite_primitive_floats_increasing_helper::( &[ -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, -3.4028196e38, ], &[ 3.4028196e38, 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, ], ); nonzero_finite_primitive_floats_increasing_helper::( &[ -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, -1.797693134862312e308, ], &[ 1.797693134862312e308, 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/nonzero_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::nonzero_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn nonzero_primitive_floats_increasing_helper(first_20: &[T], last_20: &[T]) { exhaustive_primitive_floats_helper_helper_with_reverse( nonzero_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_nonzero_primitive_floats_increasing() { nonzero_primitive_floats_increasing_helper::( &[ f32::NEGATIVE_INFINITY, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, ], &[ 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, f32::INFINITY, ], ); nonzero_primitive_floats_increasing_helper::( &[ f64::NEGATIVE_INFINITY, -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, ], &[ 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, f64::INFINITY, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/positive_finite_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::positive_finite_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn positive_finite_primitive_floats_increasing_helper( first_20: &[T], last_20: &[T], ) { exhaustive_primitive_floats_helper_helper_with_reverse( positive_finite_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_positive_finite_primitive_floats_increasing() { positive_finite_primitive_floats_increasing_helper::( &[ 1.0e-45, 3.0e-45, 4.0e-45, 6.0e-45, 7.0e-45, 8.0e-45, 1.0e-44, 1.1e-44, 1.3e-44, 1.4e-44, 1.5e-44, 1.7e-44, 1.8e-44, 2.0e-44, 2.1e-44, 2.2e-44, 2.4e-44, 2.5e-44, 2.7e-44, 2.8e-44, ], &[ 3.4028196e38, 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, ], ); positive_finite_primitive_floats_increasing_helper::( &[ 5.0e-324, 1.0e-323, 1.5e-323, 2.0e-323, 2.5e-323, 3.0e-323, 3.5e-323, 4.0e-323, 4.4e-323, 5.0e-323, 5.4e-323, 6.0e-323, 6.4e-323, 7.0e-323, 7.4e-323, 8.0e-323, 8.4e-323, 9.0e-323, 9.4e-323, 1.0e-322, ], &[ 1.797693134862312e308, 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/positive_primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::exhaustive::positive_primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn positive_primitive_floats_increasing_helper(first_20: &[T], last_20: &[T]) { exhaustive_primitive_floats_helper_helper_with_reverse( positive_primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_positive_primitive_floats_increasing() { positive_primitive_floats_increasing_helper::( &[ 1.0e-45, 3.0e-45, 4.0e-45, 6.0e-45, 7.0e-45, 8.0e-45, 1.0e-44, 1.1e-44, 1.3e-44, 1.4e-44, 1.5e-44, 1.7e-44, 1.8e-44, 2.0e-44, 2.1e-44, 2.2e-44, 2.4e-44, 2.5e-44, 2.7e-44, 2.8e-44, ], &[ 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, f32::INFINITY, ], ); positive_primitive_floats_increasing_helper::( &[ 5.0e-324, 1.0e-323, 1.5e-323, 2.0e-323, 2.5e-323, 3.0e-323, 3.5e-323, 4.0e-323, 4.4e-323, 5.0e-323, 5.4e-323, 6.0e-323, 6.4e-323, 7.0e-323, 7.4e-323, 8.0e-323, 8.4e-323, 9.0e-323, 9.4e-323, 1.0e-322, ], &[ 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, f64::INFINITY, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/primitive_float_increasing_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::primitive_float_increasing_inclusive_range; use malachite_base::test_util::num::exhaustive::*; use std::panic::catch_unwind; fn primitive_float_increasing_inclusive_range_helper( a: T, b: T, first_20: &[T], last_20: &[T], ) { exhaustive_primitive_floats_helper_helper_with_reverse( primitive_float_increasing_inclusive_range::(a, b), first_20, last_20, ); } #[allow(clippy::approx_constant)] #[test] fn test_primitive_float_increasing_inclusive_range() { primitive_float_increasing_inclusive_range_helper::(1.0, 1.0, &[1.0], &[1.0]); primitive_float_increasing_inclusive_range_helper::( 1.0, 2.0, &[ 1.0, 1.0000001, 1.0000002, 1.0000004, 1.0000005, 1.0000006, 1.0000007, 1.0000008, 1.000001, 1.0000011, 1.0000012, 1.0000013, 1.0000014, 1.0000015, 1.0000017, 1.0000018, 1.0000019, 1.000002, 1.0000021, 1.0000023, ], &[ 1.9999977, 1.9999979, 1.999998, 1.9999981, 1.9999982, 1.9999983, 1.9999985, 1.9999986, 1.9999987, 1.9999988, 1.9999989, 1.999999, 1.9999992, 1.9999993, 1.9999994, 1.9999995, 1.9999996, 1.9999998, 1.9999999, 2.0, ], ); primitive_float_increasing_inclusive_range_helper::( -0.1, 0.1, &[ -0.1, -0.099999994, -0.09999999, -0.09999998, -0.09999997, -0.099999964, -0.09999996, -0.09999995, -0.09999994, -0.099999934, -0.09999993, -0.09999992, -0.09999991, -0.099999905, -0.0999999, -0.09999989, -0.09999988, -0.099999875, -0.09999987, -0.09999986, ], &[ 0.09999986, 0.09999987, 0.099999875, 0.09999988, 0.09999989, 0.0999999, 0.099999905, 0.09999991, 0.09999992, 0.09999993, 0.099999934, 0.09999994, 0.09999995, 0.09999996, 0.099999964, 0.09999997, 0.09999998, 0.09999999, 0.099999994, 0.1, ], ); primitive_float_increasing_inclusive_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ core::f32::consts::E, 2.718282, 2.7182822, 2.7182825, 2.7182827, 2.718283, 2.7182832, 2.7182834, 2.7182837, 2.718284, 2.7182841, 2.7182844, 2.7182846, 2.7182848, 2.718285, 2.7182853, 2.7182856, 2.7182858, 2.718286, 2.7182863, ], &[ 3.1415882, 3.1415884, 3.1415887, 3.141589, 3.1415892, 3.1415894, 3.1415896, 3.1415899, 3.14159, 3.1415904, 3.1415906, 3.1415908, 3.141591, 3.1415913, 3.1415915, 3.1415918, 3.141592, 3.1415923, 3.1415925, core::f32::consts::PI, ], ); primitive_float_increasing_inclusive_range_helper::( 100.0, 101.0, &[ 100.0, 100.00001, 100.000015, 100.00002, 100.00003, 100.00004, 100.000046, 100.00005, 100.00006, 100.00007, 100.00008, 100.000084, 100.00009, 100.0001, 100.00011, 100.000114, 100.00012, 100.00013, 100.00014, 100.000145, ], &[ 100.999855, 100.99986, 100.99987, 100.99988, 100.999886, 100.99989, 100.9999, 100.99991, 100.999916, 100.99992, 100.99993, 100.99994, 100.99995, 100.999954, 100.99996, 100.99997, 100.99998, 100.999985, 100.99999, 101.0, ], ); primitive_float_increasing_inclusive_range_helper::( 1.0e38, f32::INFINITY, &[ 1.0e38, 1.0000001e38, 1.0000002e38, 1.0000003e38, 1.0000004e38, 1.0000005e38, 1.0000006e38, 1.0000007e38, 1.0000008e38, 1.0000009e38, 1.000001e38, 1.0000011e38, 1.0000012e38, 1.0000013e38, 1.0000014e38, 1.0000015e38, 1.0000016e38, 1.0000017e38, 1.0000018e38, 1.0000019e38, ], &[ 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, f32::INFINITY, ], ); primitive_float_increasing_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, &[-1.0e-45, -0.0, 0.0, 1.0e-45], &[-1.0e-45, -0.0, 0.0, 1.0e-45], ); primitive_float_increasing_inclusive_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, &[-0.0, 0.0, 1.0e-45], &[-0.0, 0.0, 1.0e-45], ); primitive_float_increasing_inclusive_range_helper::( 0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0, 1.0e-45], &[0.0, 1.0e-45], ); primitive_float_increasing_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -0.0, &[-1.0e-45, -0.0], &[-1.0e-45, -0.0], ); primitive_float_increasing_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, &[-1.0e-45, -0.0, 0.0], &[-1.0e-45, -0.0, 0.0], ); primitive_float_increasing_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, &[ f32::NEGATIVE_INFINITY, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, ], &[ 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, f32::INFINITY, ], ); primitive_float_increasing_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, &[f32::NEGATIVE_INFINITY], &[f32::NEGATIVE_INFINITY], ); primitive_float_increasing_inclusive_range_helper::( f32::INFINITY, f32::INFINITY, &[f32::INFINITY], &[f32::INFINITY], ); primitive_float_increasing_inclusive_range_helper::(0.0, 0.0, &[0.0], &[0.0]); primitive_float_increasing_inclusive_range_helper::(-0.0, -0.0, &[-0.0], &[-0.0]); primitive_float_increasing_inclusive_range_helper::(-0.0, 0.0, &[-0.0, 0.0], &[-0.0, 0.0]); primitive_float_increasing_inclusive_range_helper::(1.0, 1.0, &[1.0], &[1.0]); primitive_float_increasing_inclusive_range_helper::( 1.0, 2.0, &[ 1.0, 1.0000000000000002, 1.0000000000000004, 1.0000000000000007, 1.0000000000000009, 1.000000000000001, 1.0000000000000013, 1.0000000000000016, 1.0000000000000018, 1.000000000000002, 1.0000000000000022, 1.0000000000000024, 1.0000000000000027, 1.0000000000000029, 1.000000000000003, 1.0000000000000033, 1.0000000000000036, 1.0000000000000038, 1.000000000000004, 1.0000000000000042, ], &[ 1.9999999999999958, 1.999999999999996, 1.9999999999999962, 1.9999999999999964, 1.9999999999999967, 1.999999999999997, 1.9999999999999971, 1.9999999999999973, 1.9999999999999976, 1.9999999999999978, 1.999999999999998, 1.9999999999999982, 1.9999999999999984, 1.9999999999999987, 1.999999999999999, 1.9999999999999991, 1.9999999999999993, 1.9999999999999996, 1.9999999999999998, 2.0, ], ); primitive_float_increasing_inclusive_range_helper::( -0.1, 0.1, &[ -0.1, -0.09999999999999999, -0.09999999999999998, -0.09999999999999996, -0.09999999999999995, -0.09999999999999994, -0.09999999999999992, -0.09999999999999991, -0.0999999999999999, -0.09999999999999988, -0.09999999999999987, -0.09999999999999985, -0.09999999999999984, -0.09999999999999983, -0.09999999999999981, -0.0999999999999998, -0.09999999999999978, -0.09999999999999977, -0.09999999999999976, -0.09999999999999974, ], &[ 0.09999999999999974, 0.09999999999999976, 0.09999999999999977, 0.09999999999999978, 0.0999999999999998, 0.09999999999999981, 0.09999999999999983, 0.09999999999999984, 0.09999999999999985, 0.09999999999999987, 0.09999999999999988, 0.0999999999999999, 0.09999999999999991, 0.09999999999999992, 0.09999999999999994, 0.09999999999999995, 0.09999999999999996, 0.09999999999999998, 0.09999999999999999, 0.1, ], ); primitive_float_increasing_inclusive_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ core::f64::consts::E, 2.7182818284590455, 2.718281828459046, 2.7182818284590464, 2.718281828459047, 2.7182818284590473, 2.7182818284590478, 2.718281828459048, 2.7182818284590486, 2.718281828459049, 2.7182818284590495, 2.71828182845905, 2.7182818284590504, 2.718281828459051, 2.7182818284590513, 2.7182818284590518, 2.718281828459052, 2.7182818284590526, 2.718281828459053, 2.7182818284590535, ], &[ 3.1415926535897847, 3.141592653589785, 3.1415926535897856, 3.141592653589786, 3.1415926535897865, 3.141592653589787, 3.1415926535897873, 3.141592653589788, 3.1415926535897882, 3.1415926535897887, 3.141592653589789, 3.1415926535897896, 3.14159265358979, 3.1415926535897905, 3.141592653589791, 3.1415926535897913, 3.141592653589792, 3.1415926535897922, 3.1415926535897927, core::f64::consts::PI, ], ); primitive_float_increasing_inclusive_range_helper::( 100.0, 101.0, &[ 100.0, 100.00000000000001, 100.00000000000003, 100.00000000000004, 100.00000000000006, 100.00000000000007, 100.00000000000009, 100.0000000000001, 100.00000000000011, 100.00000000000013, 100.00000000000014, 100.00000000000016, 100.00000000000017, 100.00000000000018, 100.0000000000002, 100.00000000000021, 100.00000000000023, 100.00000000000024, 100.00000000000026, 100.00000000000027, ], &[ 100.99999999999973, 100.99999999999974, 100.99999999999976, 100.99999999999977, 100.99999999999979, 100.9999999999998, 100.99999999999982, 100.99999999999983, 100.99999999999984, 100.99999999999986, 100.99999999999987, 100.99999999999989, 100.9999999999999, 100.99999999999991, 100.99999999999993, 100.99999999999994, 100.99999999999996, 100.99999999999997, 100.99999999999999, 101.0, ], ); primitive_float_increasing_inclusive_range_helper::( 1.0e308, f64::INFINITY, &[ 1.0e308, 1.0000000000000002e308, 1.0000000000000004e308, 1.0000000000000006e308, 1.0000000000000008e308, 1.000000000000001e308, 1.0000000000000012e308, 1.0000000000000014e308, 1.0000000000000016e308, 1.0000000000000018e308, 1.000000000000002e308, 1.0000000000000022e308, 1.0000000000000024e308, 1.0000000000000026e308, 1.0000000000000028e308, 1.000000000000003e308, 1.0000000000000032e308, 1.0000000000000034e308, 1.0000000000000036e308, 1.0000000000000038e308, ], &[ 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, f64::INFINITY, ], ); primitive_float_increasing_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, &[-5.0e-324, -0.0, 0.0, 5.0e-324], &[-5.0e-324, -0.0, 0.0, 5.0e-324], ); primitive_float_increasing_inclusive_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, &[-0.0, 0.0, 5.0e-324], &[-0.0, 0.0, 5.0e-324], ); primitive_float_increasing_inclusive_range_helper::( 0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0, 5.0e-324], &[0.0, 5.0e-324], ); primitive_float_increasing_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, &[-5.0e-324, -0.0], &[-5.0e-324, -0.0], ); primitive_float_increasing_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, &[-5.0e-324, -0.0, 0.0], &[-5.0e-324, -0.0, 0.0], ); primitive_float_increasing_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, &[ f64::NEGATIVE_INFINITY, -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, ], &[ 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, f64::INFINITY, ], ); primitive_float_increasing_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, &[f64::NEGATIVE_INFINITY], &[f64::NEGATIVE_INFINITY], ); primitive_float_increasing_inclusive_range_helper::( f64::INFINITY, f64::INFINITY, &[f64::INFINITY], &[f64::INFINITY], ); primitive_float_increasing_inclusive_range_helper::(0.0, 0.0, &[0.0], &[0.0]); primitive_float_increasing_inclusive_range_helper::(-0.0, -0.0, &[-0.0], &[-0.0]); primitive_float_increasing_inclusive_range_helper::(-0.0, 0.0, &[-0.0, 0.0], &[-0.0, 0.0]); } fn primitive_float_increasing_inclusive_range_fail_helper() { assert_panic!(primitive_float_increasing_inclusive_range::( T::ONE, T::ZERO )); assert_panic!(primitive_float_increasing_inclusive_range::( T::ONE, T::NAN )); } #[test] fn primitive_float_increasing_inclusive_range_fail() { apply_fn_to_primitive_floats!(primitive_float_increasing_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/primitive_float_increasing_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::primitive_float_increasing_range; use malachite_base::test_util::num::exhaustive::*; use std::panic::catch_unwind; fn primitive_float_increasing_range_helper( a: T, b: T, first_20: &[T], last_20: &[T], ) { exhaustive_primitive_floats_helper_helper_with_reverse( primitive_float_increasing_range::(a, b), first_20, last_20, ); } #[allow(clippy::approx_constant)] #[test] fn test_primitive_float_increasing_range() { primitive_float_increasing_range_helper::(1.0, 1.0, &[], &[]); primitive_float_increasing_range_helper::( 1.0, 2.0, &[ 1.0, 1.0000001, 1.0000002, 1.0000004, 1.0000005, 1.0000006, 1.0000007, 1.0000008, 1.000001, 1.0000011, 1.0000012, 1.0000013, 1.0000014, 1.0000015, 1.0000017, 1.0000018, 1.0000019, 1.000002, 1.0000021, 1.0000023, ], &[ 1.9999976, 1.9999977, 1.9999979, 1.999998, 1.9999981, 1.9999982, 1.9999983, 1.9999985, 1.9999986, 1.9999987, 1.9999988, 1.9999989, 1.999999, 1.9999992, 1.9999993, 1.9999994, 1.9999995, 1.9999996, 1.9999998, 1.9999999, ], ); primitive_float_increasing_range_helper::( -0.1, 0.1, &[ -0.1, -0.099999994, -0.09999999, -0.09999998, -0.09999997, -0.099999964, -0.09999996, -0.09999995, -0.09999994, -0.099999934, -0.09999993, -0.09999992, -0.09999991, -0.099999905, -0.0999999, -0.09999989, -0.09999988, -0.099999875, -0.09999987, -0.09999986, ], &[ 0.09999985, 0.09999986, 0.09999987, 0.099999875, 0.09999988, 0.09999989, 0.0999999, 0.099999905, 0.09999991, 0.09999992, 0.09999993, 0.099999934, 0.09999994, 0.09999995, 0.09999996, 0.099999964, 0.09999997, 0.09999998, 0.09999999, 0.099999994, ], ); primitive_float_increasing_range_helper::( core::f32::consts::E, core::f32::consts::PI, &[ core::f32::consts::E, 2.718282, 2.7182822, 2.7182825, 2.7182827, 2.718283, 2.7182832, 2.7182834, 2.7182837, 2.718284, 2.7182841, 2.7182844, 2.7182846, 2.7182848, 2.718285, 2.7182853, 2.7182856, 2.7182858, 2.718286, 2.7182863, ], &[ 3.141588, 3.1415882, 3.1415884, 3.1415887, 3.141589, 3.1415892, 3.1415894, 3.1415896, 3.1415899, 3.14159, 3.1415904, 3.1415906, 3.1415908, 3.141591, 3.1415913, 3.1415915, 3.1415918, 3.141592, 3.1415923, 3.1415925, ], ); primitive_float_increasing_range_helper::( 100.0, 101.0, &[ 100.0, 100.00001, 100.000015, 100.00002, 100.00003, 100.00004, 100.000046, 100.00005, 100.00006, 100.00007, 100.00008, 100.000084, 100.00009, 100.0001, 100.00011, 100.000114, 100.00012, 100.00013, 100.00014, 100.000145, ], &[ 100.99985, 100.999855, 100.99986, 100.99987, 100.99988, 100.999886, 100.99989, 100.9999, 100.99991, 100.999916, 100.99992, 100.99993, 100.99994, 100.99995, 100.999954, 100.99996, 100.99997, 100.99998, 100.999985, 100.99999, ], ); primitive_float_increasing_range_helper::( 1.0e38, f32::INFINITY, &[ 1.0e38, 1.0000001e38, 1.0000002e38, 1.0000003e38, 1.0000004e38, 1.0000005e38, 1.0000006e38, 1.0000007e38, 1.0000008e38, 1.0000009e38, 1.000001e38, 1.0000011e38, 1.0000012e38, 1.0000013e38, 1.0000014e38, 1.0000015e38, 1.0000016e38, 1.0000017e38, 1.0000018e38, 1.0000019e38, ], &[ 3.4028196e38, 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, ], ); primitive_float_increasing_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, &[-1.0e-45, -0.0, 0.0], &[-1.0e-45, -0.0, 0.0], ); primitive_float_increasing_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, &[-0.0, 0.0], &[-0.0, 0.0], ); primitive_float_increasing_range_helper::( 0.0, f32::MIN_POSITIVE_SUBNORMAL, &[0.0], &[0.0], ); primitive_float_increasing_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -0.0, &[-1.0e-45], &[-1.0e-45], ); primitive_float_increasing_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, &[-1.0e-45, -0.0], &[-1.0e-45, -0.0], ); primitive_float_increasing_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, &[ f32::NEGATIVE_INFINITY, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, ], &[ 3.4028196e38, 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, ], ); primitive_float_increasing_range_helper::( f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, &[], &[], ); primitive_float_increasing_range_helper::(f32::INFINITY, f32::INFINITY, &[], &[]); primitive_float_increasing_range_helper::(0.0, 0.0, &[], &[]); primitive_float_increasing_range_helper::(-0.0, -0.0, &[], &[]); primitive_float_increasing_range_helper::(-0.0, 0.0, &[-0.0], &[-0.0]); primitive_float_increasing_range_helper::(1.0, 1.0, &[], &[]); primitive_float_increasing_range_helper::( 1.0, 2.0, &[ 1.0, 1.0000000000000002, 1.0000000000000004, 1.0000000000000007, 1.0000000000000009, 1.000000000000001, 1.0000000000000013, 1.0000000000000016, 1.0000000000000018, 1.000000000000002, 1.0000000000000022, 1.0000000000000024, 1.0000000000000027, 1.0000000000000029, 1.000000000000003, 1.0000000000000033, 1.0000000000000036, 1.0000000000000038, 1.000000000000004, 1.0000000000000042, ], &[ 1.9999999999999956, 1.9999999999999958, 1.999999999999996, 1.9999999999999962, 1.9999999999999964, 1.9999999999999967, 1.999999999999997, 1.9999999999999971, 1.9999999999999973, 1.9999999999999976, 1.9999999999999978, 1.999999999999998, 1.9999999999999982, 1.9999999999999984, 1.9999999999999987, 1.999999999999999, 1.9999999999999991, 1.9999999999999993, 1.9999999999999996, 1.9999999999999998, ], ); primitive_float_increasing_range_helper::( -0.1, 0.1, &[ -0.1, -0.09999999999999999, -0.09999999999999998, -0.09999999999999996, -0.09999999999999995, -0.09999999999999994, -0.09999999999999992, -0.09999999999999991, -0.0999999999999999, -0.09999999999999988, -0.09999999999999987, -0.09999999999999985, -0.09999999999999984, -0.09999999999999983, -0.09999999999999981, -0.0999999999999998, -0.09999999999999978, -0.09999999999999977, -0.09999999999999976, -0.09999999999999974, ], &[ 0.09999999999999973, 0.09999999999999974, 0.09999999999999976, 0.09999999999999977, 0.09999999999999978, 0.0999999999999998, 0.09999999999999981, 0.09999999999999983, 0.09999999999999984, 0.09999999999999985, 0.09999999999999987, 0.09999999999999988, 0.0999999999999999, 0.09999999999999991, 0.09999999999999992, 0.09999999999999994, 0.09999999999999995, 0.09999999999999996, 0.09999999999999998, 0.09999999999999999, ], ); primitive_float_increasing_range_helper::( core::f64::consts::E, core::f64::consts::PI, &[ core::f64::consts::E, 2.7182818284590455, 2.718281828459046, 2.7182818284590464, 2.718281828459047, 2.7182818284590473, 2.7182818284590478, 2.718281828459048, 2.7182818284590486, 2.718281828459049, 2.7182818284590495, 2.71828182845905, 2.7182818284590504, 2.718281828459051, 2.7182818284590513, 2.7182818284590518, 2.718281828459052, 2.7182818284590526, 2.718281828459053, 2.7182818284590535, ], &[ 3.1415926535897842, 3.1415926535897847, 3.141592653589785, 3.1415926535897856, 3.141592653589786, 3.1415926535897865, 3.141592653589787, 3.1415926535897873, 3.141592653589788, 3.1415926535897882, 3.1415926535897887, 3.141592653589789, 3.1415926535897896, 3.14159265358979, 3.1415926535897905, 3.141592653589791, 3.1415926535897913, 3.141592653589792, 3.1415926535897922, 3.1415926535897927, ], ); primitive_float_increasing_range_helper::( 100.0, 101.0, &[ 100.0, 100.00000000000001, 100.00000000000003, 100.00000000000004, 100.00000000000006, 100.00000000000007, 100.00000000000009, 100.0000000000001, 100.00000000000011, 100.00000000000013, 100.00000000000014, 100.00000000000016, 100.00000000000017, 100.00000000000018, 100.0000000000002, 100.00000000000021, 100.00000000000023, 100.00000000000024, 100.00000000000026, 100.00000000000027, ], &[ 100.99999999999972, 100.99999999999973, 100.99999999999974, 100.99999999999976, 100.99999999999977, 100.99999999999979, 100.9999999999998, 100.99999999999982, 100.99999999999983, 100.99999999999984, 100.99999999999986, 100.99999999999987, 100.99999999999989, 100.9999999999999, 100.99999999999991, 100.99999999999993, 100.99999999999994, 100.99999999999996, 100.99999999999997, 100.99999999999999, ], ); primitive_float_increasing_range_helper::( 1.0e308, f64::INFINITY, &[ 1.0e308, 1.0000000000000002e308, 1.0000000000000004e308, 1.0000000000000006e308, 1.0000000000000008e308, 1.000000000000001e308, 1.0000000000000012e308, 1.0000000000000014e308, 1.0000000000000016e308, 1.0000000000000018e308, 1.000000000000002e308, 1.0000000000000022e308, 1.0000000000000024e308, 1.0000000000000026e308, 1.0000000000000028e308, 1.000000000000003e308, 1.0000000000000032e308, 1.0000000000000034e308, 1.0000000000000036e308, 1.0000000000000038e308, ], &[ 1.797693134862312e308, 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, ], ); primitive_float_increasing_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, &[-5.0e-324, -0.0, 0.0], &[-5.0e-324, -0.0, 0.0], ); primitive_float_increasing_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, &[-0.0, 0.0], &[-0.0, 0.0], ); primitive_float_increasing_range_helper::( 0.0, f64::MIN_POSITIVE_SUBNORMAL, &[0.0], &[0.0], ); primitive_float_increasing_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, &[-5.0e-324], &[-5.0e-324], ); primitive_float_increasing_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, &[-5.0e-324, -0.0], &[-5.0e-324, -0.0], ); primitive_float_increasing_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, &[ f64::NEGATIVE_INFINITY, -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, ], &[ 1.797693134862312e308, 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, ], ); primitive_float_increasing_range_helper::( f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, &[], &[], ); primitive_float_increasing_range_helper::(f64::INFINITY, f64::INFINITY, &[], &[]); primitive_float_increasing_range_helper::(0.0, 0.0, &[], &[]); primitive_float_increasing_range_helper::(-0.0, -0.0, &[], &[]); primitive_float_increasing_range_helper::(-0.0, 0.0, &[-0.0], &[-0.0]); } fn primitive_float_increasing_range_fail_helper() { assert_panic!(primitive_float_increasing_range::(T::ONE, T::ZERO)); assert_panic!(primitive_float_increasing_range::(T::ONE, T::NAN)); } #[test] fn primitive_float_increasing_range_fail() { apply_fn_to_primitive_floats!(primitive_float_increasing_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/primitive_floats_increasing.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::exhaustive::primitive_floats_increasing; use malachite_base::test_util::num::exhaustive::*; fn primitive_floats_increasing_helper(first_20: &[T], last_20: &[T]) { exhaustive_primitive_floats_helper_helper_with_reverse( primitive_floats_increasing::(), first_20, last_20, ); } #[test] fn test_primitive_floats_increasing() { primitive_floats_increasing_helper::( &[ f32::NEGATIVE_INFINITY, -3.4028235e38, -3.4028233e38, -3.402823e38, -3.4028229e38, -3.4028227e38, -3.4028225e38, -3.4028222e38, -3.402822e38, -3.4028218e38, -3.4028216e38, -3.4028214e38, -3.4028212e38, -3.402821e38, -3.4028208e38, -3.4028206e38, -3.4028204e38, -3.4028202e38, -3.40282e38, -3.4028198e38, ], &[ 3.4028198e38, 3.40282e38, 3.4028202e38, 3.4028204e38, 3.4028206e38, 3.4028208e38, 3.402821e38, 3.4028212e38, 3.4028214e38, 3.4028216e38, 3.4028218e38, 3.402822e38, 3.4028222e38, 3.4028225e38, 3.4028227e38, 3.4028229e38, 3.402823e38, 3.4028233e38, 3.4028235e38, f32::INFINITY, ], ); primitive_floats_increasing_helper::( &[ f64::NEGATIVE_INFINITY, -1.7976931348623157e308, -1.7976931348623155e308, -1.7976931348623153e308, -1.7976931348623151e308, -1.797693134862315e308, -1.7976931348623147e308, -1.7976931348623145e308, -1.7976931348623143e308, -1.7976931348623141e308, -1.797693134862314e308, -1.7976931348623137e308, -1.7976931348623135e308, -1.7976931348623133e308, -1.7976931348623131e308, -1.797693134862313e308, -1.7976931348623127e308, -1.7976931348623125e308, -1.7976931348623123e308, -1.7976931348623121e308, ], &[ 1.7976931348623121e308, 1.7976931348623123e308, 1.7976931348623125e308, 1.7976931348623127e308, 1.797693134862313e308, 1.7976931348623131e308, 1.7976931348623133e308, 1.7976931348623135e308, 1.7976931348623137e308, 1.797693134862314e308, 1.7976931348623141e308, 1.7976931348623143e308, 1.7976931348623145e308, 1.7976931348623147e308, 1.797693134862315e308, 1.7976931348623151e308, 1.7976931348623153e308, 1.7976931348623155e308, 1.7976931348623157e308, f64::INFINITY, ], ); } ================================================ FILE: malachite-base/tests/num/exhaustive/primitive_int_increasing_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::exhaustive::primitive_int_increasing_inclusive_range; use std::panic::catch_unwind; fn expected_range_len(a: T, b: T) -> usize where usize: WrappingFrom, { usize::wrapping_from(b).wrapping_sub(usize::wrapping_from(a)) + 1 } fn primitive_int_increasing_inclusive_range_helper_helper( a: T, b: T, values: &[i8], ) where i8: ExactFrom, usize: WrappingFrom, { let xs = primitive_int_increasing_inclusive_range::(a, b) .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!(xs, values); if T::WIDTH <= u16::WIDTH { let len = expected_range_len(a, b); assert_eq!(primitive_int_increasing_inclusive_range(a, b).count(), len); let mut init = primitive_int_increasing_inclusive_range::(a, b) .rev() .skip(len.saturating_sub(20)) .map(i8::exact_from) .collect_vec(); init.reverse(); assert_eq!(xs, init); } } fn primitive_int_increasing_inclusive_range_rev_helper( a: T, b: T, rev_values: &[T], ) where usize: WrappingFrom, { let xs = primitive_int_increasing_inclusive_range::(a, b) .rev() .take(20) .collect_vec(); assert_eq!(xs, rev_values); if T::WIDTH <= u16::WIDTH { let len = expected_range_len(a, b); assert_eq!( primitive_int_increasing_inclusive_range(a, b).rev().count(), len ); let mut tail = primitive_int_increasing_inclusive_range::(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(xs, tail); } } fn primitive_int_increasing_inclusive_range_helper() where i8: ExactFrom, usize: WrappingFrom, { primitive_int_increasing_inclusive_range_helper_helper( T::exact_from(5), T::exact_from(5), &[5], ); primitive_int_increasing_inclusive_range_helper_helper( T::ONE, T::exact_from(6), &[1, 2, 3, 4, 5, 6], ); primitive_int_increasing_inclusive_range_helper_helper( T::exact_from(10), T::exact_from(19), &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); primitive_int_increasing_inclusive_range_helper_helper( T::ZERO, T::MAX, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); primitive_int_increasing_inclusive_range_helper_helper( T::ZERO, T::MAX - T::ONE, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); } fn primitive_int_increasing_inclusive_range_helper_signed() where i8: ExactFrom, usize: WrappingFrom, { primitive_int_increasing_inclusive_range_helper_helper( T::exact_from(-20), T::exact_from(-11), &[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11], ); primitive_int_increasing_inclusive_range_helper_helper( T::exact_from(-100), T::exact_from(99), &[ -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, ], ); } #[test] fn test_primitive_int_increasing_inclusive_range() { apply_fn_to_primitive_ints!(primitive_int_increasing_inclusive_range_helper); apply_fn_to_signeds!(primitive_int_increasing_inclusive_range_helper_signed); primitive_int_increasing_inclusive_range_rev_helper::( 0, u8::MAX, &[ 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, ], ); primitive_int_increasing_inclusive_range_rev_helper::( 0, u8::MAX - 1, &[ 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, ], ); primitive_int_increasing_inclusive_range_rev_helper::( 0, u16::MAX, &[ 65535, 65534, 65533, 65532, 65531, 65530, 65529, 65528, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65517, 65516, ], ); primitive_int_increasing_inclusive_range_rev_helper::( 0, u16::MAX - 1, &[ 65534, 65533, 65532, 65531, 65530, 65529, 65528, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65517, 65516, 65515, ], ); primitive_int_increasing_inclusive_range_helper_helper::( i8::MIN, i8::MAX, &[ -128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, ], ); primitive_int_increasing_inclusive_range_helper_helper::( i8::MIN + 1, i8::MAX - 1, &[ -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, ], ); primitive_int_increasing_inclusive_range_rev_helper::( i8::MIN, i8::MAX, &[ 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, ], ); primitive_int_increasing_inclusive_range_rev_helper::( i8::MIN + 1, i8::MAX - 1, &[ 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, ], ); primitive_int_increasing_inclusive_range_rev_helper::( i16::MIN, i16::MAX, &[ 32767, 32766, 32765, 32764, 32763, 32762, 32761, 32760, 32759, 32758, 32757, 32756, 32755, 32754, 32753, 32752, 32751, 32750, 32749, 32748, ], ); primitive_int_increasing_inclusive_range_rev_helper::( i16::MIN + 1, i16::MAX - 1, &[ 32766, 32765, 32764, 32763, 32762, 32761, 32760, 32759, 32758, 32757, 32756, 32755, 32754, 32753, 32752, 32751, 32750, 32749, 32748, 32747, ], ); } fn primitive_int_increasing_inclusive_range_fail_helper() { assert_panic!(primitive_int_increasing_inclusive_range::( T::ONE, T::ZERO )); } #[test] fn primitive_int_increasing_inclusive_range_fail() { apply_fn_to_primitive_ints!(primitive_int_increasing_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/exhaustive/primitive_int_increasing_range.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::exhaustive::primitive_int_increasing_range; use std::panic::catch_unwind; fn expected_range_len(a: T, b: T) -> usize where usize: WrappingFrom, { usize::wrapping_from(b).wrapping_sub(usize::wrapping_from(a)) } fn primitive_int_increasing_range_helper_helper(a: T, b: T, values: &[i8]) where i8: ExactFrom, usize: WrappingFrom, { let xs = primitive_int_increasing_range::(a, b) .map(i8::exact_from) .take(20) .collect_vec(); assert_eq!(xs, values); if T::WIDTH <= u16::WIDTH { let len = expected_range_len(a, b); assert_eq!(primitive_int_increasing_range(a, b).count(), len); let mut init = primitive_int_increasing_range::(a, b) .rev() .skip(len.saturating_sub(20)) .map(i8::exact_from) .collect_vec(); init.reverse(); assert_eq!(xs, init); } } fn primitive_int_increasing_range_rev_helper(a: T, b: T, rev_values: &[T]) where usize: WrappingFrom, { let xs = primitive_int_increasing_range::(a, b) .rev() .take(20) .collect_vec(); assert_eq!(xs, rev_values); if T::WIDTH <= u16::WIDTH { let len = expected_range_len(a, b); assert_eq!(primitive_int_increasing_range(a, b).rev().count(), len); let mut tail = primitive_int_increasing_range::(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(xs, tail); } } fn primitive_int_increasing_range_helper() where i8: ExactFrom, usize: WrappingFrom, { primitive_int_increasing_range_helper_helper(T::exact_from(5), T::exact_from(5), &[]); primitive_int_increasing_range_helper_helper(T::exact_from(5), T::exact_from(6), &[5]); primitive_int_increasing_range_helper_helper(T::ONE, T::exact_from(7), &[1, 2, 3, 4, 5, 6]); primitive_int_increasing_range_helper_helper( T::exact_from(10), T::exact_from(20), &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); primitive_int_increasing_range_helper_helper( T::ZERO, T::MAX, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); primitive_int_increasing_range_helper_helper( T::ZERO, T::MAX - T::ONE, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], ); } fn primitive_int_increasing_range_helper_signed() where i8: ExactFrom, usize: WrappingFrom, { primitive_int_increasing_range_helper_helper( T::exact_from(-20), T::exact_from(-10), &[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11], ); primitive_int_increasing_range_helper_helper( T::exact_from(-100), T::exact_from(100), &[ -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, ], ); } #[test] fn test_primitive_int_increasing_range() { apply_fn_to_primitive_ints!(primitive_int_increasing_range_helper); apply_fn_to_signeds!(primitive_int_increasing_range_helper_signed); primitive_int_increasing_range_rev_helper::( 0, u8::MAX, &[ 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, ], ); primitive_int_increasing_range_rev_helper::( 0, u8::MAX - 1, &[ 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, ], ); primitive_int_increasing_range_rev_helper::( 0, u16::MAX, &[ 65534, 65533, 65532, 65531, 65530, 65529, 65528, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65517, 65516, 65515, ], ); primitive_int_increasing_range_rev_helper::( 0, u16::MAX - 1, &[ 65533, 65532, 65531, 65530, 65529, 65528, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65517, 65516, 65515, 65514, ], ); primitive_int_increasing_range_helper_helper::( i8::MIN, i8::MAX, &[ -128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, ], ); primitive_int_increasing_range_helper_helper::( i8::MIN + 1, i8::MAX - 1, &[ -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, ], ); primitive_int_increasing_range_rev_helper::( i8::MIN, i8::MAX, &[ 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, ], ); primitive_int_increasing_range_rev_helper::( i8::MIN + 1, i8::MAX - 1, &[ 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, ], ); primitive_int_increasing_range_rev_helper::( i16::MIN, i16::MAX, &[ 32766, 32765, 32764, 32763, 32762, 32761, 32760, 32759, 32758, 32757, 32756, 32755, 32754, 32753, 32752, 32751, 32750, 32749, 32748, 32747, ], ); primitive_int_increasing_range_rev_helper::( i16::MIN + 1, i16::MAX - 1, &[ 32765, 32764, 32763, 32762, 32761, 32760, 32759, 32758, 32757, 32756, 32755, 32754, 32753, 32752, 32751, 32750, 32749, 32748, 32747, 32746, ], ); } fn primitive_int_increasing_range_fail_helper() { assert_panic!(primitive_int_increasing_range::(T::ONE, T::ZERO)); } #[test] fn primitive_int_increasing_range_fail() { apply_fn_to_primitive_ints!(primitive_int_increasing_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/factorization/factor.rs ================================================ // Copyright © 2026 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 crate::itertools::Itertools; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::exhaustive::exhaustive_positive_primitive_ints; use malachite_base::num::factorization::traits::{Factor, IsPrime}; use malachite_base::test_util::generators::unsigned_gen_var_1; use malachite_base::test_util::num::factorization::factor::factor_naive; use std::panic::catch_unwind; fn factor_helper() where ::FACTORS: IntoIterator, { let test = |n: u64, out: &[(u64, u8)]| { if let Ok(n) = T::try_from(n) { let factors = n .factor() .into_iter() .map(|(f, e)| { let f: u64 = f.wrapping_into(); (f, e) }) .collect_vec(); assert_eq!(factors, out); let factors_alt = factor_naive(n) .into_iter() .map(|(f, e)| { let f: u64 = f.wrapping_into(); (f, e) }) .collect_vec(); assert_eq!(factors_alt, out); } }; // - in n_factor_trial_range_u32 // - p * p > n in n_factor_trial_range_u32 // - cofactor == 1 in u32::factor // - in n_factor_trial_range_u64 // - p * p > n in n_factor_trial_range_u64 // - cofactor == 1 in u64::factor test(1, &[]); // - cofactor != 1 in u32::factor // - cofactor.is_prime() in u32::factor // - cofactor != 1 in u64::factor // - cofactor.is_prime() in u64::factor test(2, &[(2, 1)]); test(3, &[(3, 1)]); // - p * p <= n in n_factor_trial_range_u32 // - in n_remove2_precomp_u32 // - p == 2 in n_remove2_precomp_u32 // - exp != 0 in n_remove2_precomp_u32 // - exp != 0 in n_factor_trial_range_u32 // - p * p <= n in n_factor_trial_range_u64 // - in n_remove2_precomp_u64 // - p == 2 in n_remove2_precomp_u64 // - exp != 0 in n_remove2_precomp_u64 // - exp != 0 in n_factor_trial_range_u64 test(4, &[(2, 2)]); // - exp == 0 in n_remove2_precomp_u32 // - exp == 0 in n_factor_trial_range_u32 // - exp == 0 in n_remove2_precomp_u64 // - exp == 0 in n_factor_trial_range_u64 test(5, &[(5, 1)]); test(6, &[(2, 1), (3, 1)]); test(7, &[(7, 1)]); test(8, &[(2, 3)]); // - p != 2 in n_remove2_precomp_u32 // - in n_divrem2_precomp_u32 // - a >= n in n_divrem2_precomp_u32 // - !n.get_highest_bit() in n_divrem2_precomp_u32 // - n != 1 in n_divrem2_precomp_u32 // - 0 <= r < n first time in n_divrem2_precomp_u32 // - r == 0 in n_remove2_precomp_u32 // - p != 2 in n_remove2_precomp_u64 // - in n_divrem2_precomp_u64 // - a >= n in n_divrem2_precomp_u64 // - !n.get_highest_bit() in n_divrem2_precomp_u64 // - n != 1 in n_divrem2_precomp_u64 // - 0 <= r < n first time in n_divrem2_precomp_u64 // - r == 0 in n_remove2_precomp_u64 test(9, &[(3, 2)]); test(10, &[(2, 1), (5, 1)]); // - r != 0 in n_remove2_precomp_u32 // - r != 0 in n_remove2_precomp_u64 test(u64::power_of_2(4) - 1, &[(3, 1), (5, 1)]); test(u64::power_of_2(5) - 1, &[(31, 1)]); test(u64::power_of_2(6) - 1, &[(3, 2), (7, 1)]); test(u64::power_of_2(7) - 1, &[(127, 1)]); test(u64::power_of_2(8) - 1, &[(3, 1), (5, 1), (17, 1)]); test(u64::power_of_2(9) - 1, &[(7, 1), (73, 1)]); test(u64::power_of_2(10) - 1, &[(3, 1), (11, 1), (31, 1)]); test(u64::power_of_2(11) - 1, &[(23, 1), (89, 1)]); test(u64::power_of_2(12) - 1, &[(3, 2), (5, 1), (7, 1), (13, 1)]); test(u64::power_of_2(13) - 1, &[(8191, 1)]); test(u64::power_of_2(14) - 1, &[(3, 1), (43, 1), (127, 1)]); test(u64::power_of_2(15) - 1, &[(7, 1), (31, 1), (151, 1)]); test( u64::power_of_2(16) - 1, &[(3, 1), (5, 1), (17, 1), (257, 1)], ); test(u64::power_of_2(17) - 1, &[(131071, 1)]); test(u64::power_of_2(18) - 1, &[(3, 3), (7, 1), (19, 1), (73, 1)]); test(u64::power_of_2(19) - 1, &[(524287, 1)]); test( u64::power_of_2(20) - 1, &[(3, 1), (5, 2), (11, 1), (31, 1), (41, 1)], ); test(u64::power_of_2(21) - 1, &[(7, 2), (127, 1), (337, 1)]); test( u64::power_of_2(22) - 1, &[(3, 1), (23, 1), (89, 1), (683, 1)], ); test(u64::power_of_2(23) - 1, &[(47, 1), (178481, 1)]); test( u64::power_of_2(24) - 1, &[(3, 2), (5, 1), (7, 1), (13, 1), (17, 1), (241, 1)], ); test(u64::power_of_2(25) - 1, &[(31, 1), (601, 1), (1801, 1)]); // - r >= n first time in n_divrem2_precomp_u32 // - r >= n second time in n_divrem2_precomp_u32 // - r >= n first time in n_divrem2_precomp_u64 // - r >= n second time in n_divrem2_precomp_u64 test(u64::power_of_2(26) - 1, &[(3, 1), (2731, 1), (8191, 1)]); test(u64::power_of_2(27) - 1, &[(7, 1), (73, 1), (262657, 1)]); test( u64::power_of_2(28) - 1, &[(3, 1), (5, 1), (29, 1), (43, 1), (113, 1), (127, 1)], ); test(u64::power_of_2(29) - 1, &[(233, 1), (1103, 1), (2089, 1)]); test( u64::power_of_2(30) - 1, &[(3, 2), (7, 1), (11, 1), (31, 1), (151, 1), (331, 1)], ); test(u64::power_of_2(31) - 1, &[(2147483647, 1)]); test( u64::power_of_2(32) - 1, &[(3, 1), (5, 1), (17, 1), (257, 1), (65537, 1)], ); test( u64::power_of_2(33) - 1, &[(7, 1), (23, 1), (89, 1), (599479, 1)], ); // - !cofactor.is_prime() in u64::factor // - factor >= cutoff in u64::factor // - in n_factor_power235_u64 // - t != 0 first time in n_factor_power235_u64 // - t != 0 second time in n_factor_power235_u64 // - t == 0 third time in n_factor_power235_u64 // - cofactor == 0 in u64::factor // - factor >= cutoff && !factor.is_prime() in u64::factor // - in n_factor_one_line_u64 // - in n_is_square_u64 // - IS_SQUARE_MOD64[(x % 64) as usize] != 0 in n_is_square_u64 // - IS_SQUARE_MOD63[(x % 63) as usize] == 0 in n_is_square_u64 // - !n_is_square_u64(mmod) in n_factor_one_line_u64 // - IS_SQUARE_MOD63[(x % 63) as usize] != 0 in n_is_square_u64 // - IS_SQUARE_MOD65[(x % 65) as usize] == 0 in n_is_square_u64 // - IS_SQUARE_MOD64[(x % 64) as usize] == 0 in n_is_square_u64 // - IS_SQUARE_MOD65[(x % 65) as usize] != 0 in n_is_square_u64 // - n_is_square_u64(mmod) in n_factor_one_line_u64 // - found factor in u64::factor // - factor < cutoff in u64::factor test(u64::power_of_2(34) - 1, &[(3, 1), (43691, 1), (131071, 1)]); test( u64::power_of_2(35) - 1, &[(31, 1), (71, 1), (127, 1), (122921, 1)], ); test( u64::power_of_2(36) - 1, &[(3, 3), (5, 1), (7, 1), (13, 1), (19, 1), (37, 1), (73, 1), (109, 1)], ); test(u64::power_of_2(37) - 1, &[(223, 1), (616318177, 1)]); test(u64::power_of_2(38) - 1, &[(3, 1), (174763, 1), (524287, 1)]); test( u64::power_of_2(39) - 1, &[(7, 1), (79, 1), (8191, 1), (121369, 1)], ); test( u64::power_of_2(40) - 1, &[(3, 1), (5, 2), (11, 1), (17, 1), (31, 1), (41, 1), (61681, 1)], ); test(u64::power_of_2(41) - 1, &[(13367, 1), (164511353, 1)]); test( u64::power_of_2(42) - 1, &[(3, 2), (7, 2), (43, 1), (127, 1), (337, 1), (5419, 1)], ); test( u64::power_of_2(43) - 1, &[(431, 1), (9719, 1), (2099863, 1)], ); test( u64::power_of_2(44) - 1, &[(3, 1), (5, 1), (23, 1), (89, 1), (397, 1), (683, 1), (2113, 1)], ); test( u64::power_of_2(45) - 1, &[(7, 1), (31, 1), (73, 1), (151, 1), (631, 1), (23311, 1)], ); // - t == 0 first time in n_factor_power235_u64 test( u64::power_of_2(46) - 1, &[(3, 1), (47, 1), (178481, 1), (2796203, 1)], ); test( u64::power_of_2(47) - 1, &[(2351, 1), (4513, 1), (13264529, 1)], ); test( u64::power_of_2(48) - 1, &[(3, 2), (5, 1), (7, 1), (13, 1), (17, 1), (97, 1), (241, 1), (257, 1), (673, 1)], ); test(u64::power_of_2(49) - 1, &[(127, 1), (4432676798593, 1)]); test( u64::power_of_2(50) - 1, &[(3, 1), (11, 1), (31, 1), (251, 1), (601, 1), (1801, 1), (4051, 1)], ); test( u64::power_of_2(51) - 1, &[(7, 1), (103, 1), (2143, 1), (11119, 1), (131071, 1)], ); test( u64::power_of_2(52) - 1, &[(3, 1), (5, 1), (53, 1), (157, 1), (1613, 1), (2731, 1), (8191, 1)], ); // - in n_factor_pp1_wrapper_u64 // - bits >= 31 in n_factor_pp1_wrapper_u64 // - in n_factor_squfof_u64 // - in ll_factor_squfof_u64 // - n_hi == 0 in ll_factor_squfof_u64 // - q != 0 && num != 0 in ll_factor_squfof_u64 // - q > l in ll_factor_squfof_u64 // - i.even() in ll_factor_squfof_u64 // - !n_is_square_u64(q) in ll_factor_squfof_u64 // - i.odd() in ll_factor_squfof_u64 // - q <= l in ll_factor_squfof_u64 // - q.odd() && q > l2 in ll_factor_squfof_u64 // - q.odd() && q <= l2 in ll_factor_squfof_u64 // - q.odd() && q <= l2 && qupto < 50 in ll_factor_squfof_u64 // - q.even() first time in ll_factor_squfof_u64 // - q.even() && qupto < 50 in ll_factor_squfof_u64 // - n_is_square_u64(q) in ll_factor_squfof_u64 // - qupto != 0 in ll_factor_squfof_u64 // - r != qarr[j] in ll_factor_squfof_u64 // - done in ll_factor_squfof_u64 // - !finished_loop in ll_factor_squfof_u64 first time // - sqrt_hi == 0 in ll_factor_squfof_u64 // - p != pnext in ll_factor_squfof_u64 // - p == pnext in ll_factor_squfof_u64 // - !finished_loop in ll_factor_squfof_u64 second time // - q.even() second time in ll_factor_squfof_u64 // - factor != 0 first time in n_factor_squfof_u64 // - !finished_loop in n_factor_squfof_u64 test( u64::power_of_2(53) - 1, &[(6361, 1), (69431, 1), (20394401, 1)], ); // - t == 0 second time in n_factor_power235_u64 test( u64::power_of_2(54) - 1, &[(3, 4), (7, 1), (19, 1), (73, 1), (87211, 1), (262657, 1)], ); // - -n <= r < 0 in n_divrem2_precomp_u64 test( u64::power_of_2(55) - 1, &[(23, 1), (31, 1), (89, 1), (881, 1), (3191, 1), (201961, 1)], ); // - 0 <= r < n second time in n_divrem2_precomp_u64 test( u64::power_of_2(56) - 1, &[(3, 1), (5, 1), (17, 1), (29, 1), (43, 1), (113, 1), (127, 1), (15790321, 1)], ); // - r < -n in n_divrem2_precomp_u64 // - r < 0 in n_divrem2_precomp_u64 // - t != 0 third time in n_factor_power235_u64 // - t.even() in n_factor_power235_u64 // - t & 2 == 0 in n_factor_power235_u64 // - t & 4 == 0 in n_factor_power235_u64 // - in n_factor_pp1_u64 // - n.odd() in n_factor_pp1_u64 // - pr < sqrt in n_factor_pp1_u64 first time // - in n_pp1_pow_ui_u64 // - exp & bit == 0 in n_pp1_pow_ui_u64 // - exp & bit != 0 in n_pp1_pow_ui_u64 // - pr >= sqrt in n_factor_pp1_u64 first time // - in n_pp1_factor_u64 // - norm != 0 in n_pp1_factor_u64 // - x != 0 in n_pp1_factor_u64 // - factor != 0 first time in n_factor_pp1_u64 // - factor != 1 first time in n_factor_pp1_u64 // - factor != 0 in n_factor_pp1_wrapper_u64 test( u64::power_of_2(57) - 1, &[(7, 1), (32377, 1), (524287, 1), (1212847, 1)], ); test( u64::power_of_2(58) - 1, &[(3, 1), (59, 1), (233, 1), (1103, 1), (2089, 1), (3033169, 1)], ); // - factor < cutoff || factor.is_prime() in u64::factor test(u64::power_of_2(59) - 1, &[(179951, 1), (3203431780337, 1)]); test( u64::power_of_2(60) - 1, &[ (3, 2), (5, 2), (7, 1), (11, 1), (13, 1), (31, 1), (41, 1), (61, 1), (151, 1), (331, 1), (1321, 1), ], ); test(u64::power_of_2(61) - 1, &[(2305843009213693951, 1)]); // - t.odd() in n_factor_power235_u64 // - n != y.square() in n_factor_power235_u64 // - t & 4 != 0 in n_factor_power235_u64 // - n != y.pow(5) in n_factor_power235_u64 // - t & 2 != 0 in n_factor_power235_u64 // - n != y.pow(3) in n_factor_power235_u64 test( u64::power_of_2(62) - 1, &[(3, 1), (715827883, 1), (2147483647, 1)], ); test( u64::power_of_2(63) - 1, &[(7, 2), (73, 1), (127, 1), (337, 1), (92737, 1), (649657, 1)], ); test( u64::MAX, &[(3, 1), (5, 1), (17, 1), (257, 1), (641, 1), (65537, 1), (6700417, 1)], ); test(u64::power_of_2(4) + 1, &[(17, 1)]); test(u64::power_of_2(5) + 1, &[(3, 1), (11, 1)]); test(u64::power_of_2(6) + 1, &[(5, 1), (13, 1)]); test(u64::power_of_2(7) + 1, &[(3, 1), (43, 1)]); test(u64::power_of_2(8) + 1, &[(257, 1)]); test(u64::power_of_2(9) + 1, &[(3, 3), (19, 1)]); test(u64::power_of_2(10) + 1, &[(5, 2), (41, 1)]); test(u64::power_of_2(11) + 1, &[(3, 1), (683, 1)]); test(u64::power_of_2(12) + 1, &[(17, 1), (241, 1)]); test(u64::power_of_2(13) + 1, &[(3, 1), (2731, 1)]); test(u64::power_of_2(14) + 1, &[(5, 1), (29, 1), (113, 1)]); test(u64::power_of_2(15) + 1, &[(3, 2), (11, 1), (331, 1)]); test(u64::power_of_2(16) + 1, &[(65537, 1)]); test(u64::power_of_2(17) + 1, &[(3, 1), (43691, 1)]); test( u64::power_of_2(18) + 1, &[(5, 1), (13, 1), (37, 1), (109, 1)], ); test(u64::power_of_2(19) + 1, &[(3, 1), (174763, 1)]); test(u64::power_of_2(20) + 1, &[(17, 1), (61681, 1)]); test(u64::power_of_2(21) + 1, &[(3, 2), (43, 1), (5419, 1)]); test(u64::power_of_2(22) + 1, &[(5, 1), (397, 1), (2113, 1)]); test(u64::power_of_2(23) + 1, &[(3, 1), (2796203, 1)]); test(u64::power_of_2(24) + 1, &[(97, 1), (257, 1), (673, 1)]); test( u64::power_of_2(25) + 1, &[(3, 1), (11, 1), (251, 1), (4051, 1)], ); test( u64::power_of_2(26) + 1, &[(5, 1), (53, 1), (157, 1), (1613, 1)], ); test(u64::power_of_2(27) + 1, &[(3, 4), (19, 1), (87211, 1)]); test(u64::power_of_2(28) + 1, &[(17, 1), (15790321, 1)]); test(u64::power_of_2(29) + 1, &[(3, 1), (59, 1), (3033169, 1)]); test( u64::power_of_2(30) + 1, &[(5, 2), (13, 1), (41, 1), (61, 1), (1321, 1)], ); test(u64::power_of_2(31) + 1, &[(3, 1), (715827883, 1)]); test(u64::power_of_2(32) + 1, &[(641, 1), (6700417, 1)]); test( u64::power_of_2(33) + 1, &[(3, 2), (67, 1), (683, 1), (20857, 1)], ); test( u64::power_of_2(34) + 1, &[(5, 1), (137, 1), (953, 1), (26317, 1)], ); test( u64::power_of_2(35) + 1, &[(3, 1), (11, 1), (43, 1), (281, 1), (86171, 1)], ); test( u64::power_of_2(36) + 1, &[(17, 1), (241, 1), (433, 1), (38737, 1)], ); test(u64::power_of_2(37) + 1, &[(3, 1), (1777, 1), (25781083, 1)]); test( u64::power_of_2(38) + 1, &[(5, 1), (229, 1), (457, 1), (525313, 1)], ); test(u64::power_of_2(39) + 1, &[(3, 2), (2731, 1), (22366891, 1)]); test(u64::power_of_2(40) + 1, &[(257, 1), (4278255361, 1)]); test(u64::power_of_2(41) + 1, &[(3, 1), (83, 1), (8831418697, 1)]); test( u64::power_of_2(42) + 1, &[(5, 1), (13, 1), (29, 1), (113, 1), (1429, 1), (14449, 1)], ); test(u64::power_of_2(43) + 1, &[(3, 1), (2932031007403, 1)]); test( u64::power_of_2(44) + 1, &[(17, 1), (353, 1), (2931542417, 1)], ); test( u64::power_of_2(45) + 1, &[(3, 3), (11, 1), (19, 1), (331, 1), (18837001, 1)], ); test( u64::power_of_2(46) + 1, &[(5, 1), (277, 1), (1013, 1), (1657, 1), (30269, 1)], ); test( u64::power_of_2(47) + 1, &[(3, 1), (283, 1), (165768537521, 1)], ); // - r == qarr[j] in ll_factor_squfof_u64 // - !done in ll_factor_squfof_u64 // - r != 1 in ll_factor_squfof_u64 test( u64::power_of_2(48) + 1, &[(193, 1), (65537, 1), (22253377, 1)], ); test( u64::power_of_2(49) + 1, &[(3, 1), (43, 1), (4363953127297, 1)], ); test( u64::power_of_2(50) + 1, &[(5, 3), (41, 1), (101, 1), (8101, 1), (268501, 1)], ); test( u64::power_of_2(51) + 1, &[(3, 2), (307, 1), (2857, 1), (6529, 1), (43691, 1)], ); test( u64::power_of_2(52) + 1, &[(17, 1), (858001, 1), (308761441, 1)], ); test( u64::power_of_2(53) + 1, &[(3, 1), (107, 1), (28059810762433, 1)], ); test( u64::power_of_2(54) + 1, &[(5, 1), (13, 1), (37, 1), (109, 1), (246241, 1), (279073, 1)], ); test( u64::power_of_2(55) + 1, &[(3, 1), (11, 2), (683, 1), (2971, 1), (48912491, 1)], ); test( u64::power_of_2(56) + 1, &[(257, 1), (5153, 1), (54410972897, 1)], ); // - q.odd() in ll_factor_squfof_u64 test( u64::power_of_2(57) + 1, &[(3, 2), (571, 1), (174763, 1), (160465489, 1)], ); test( u64::power_of_2(58) + 1, &[(5, 1), (107367629, 1), (536903681, 1)], ); test( u64::power_of_2(59) + 1, &[(3, 1), (2833, 1), (37171, 1), (1824726041, 1)], ); test( u64::power_of_2(60) + 1, &[(17, 1), (241, 1), (61681, 1), (4562284561, 1)], ); test(u64::power_of_2(61) + 1, &[(3, 1), (768614336404564651, 1)]); test( u64::power_of_2(62) + 1, &[(5, 1), (5581, 1), (8681, 1), (49477, 1), (384773, 1)], ); test( u64::power_of_2(63) + 1, &[(3, 3), (19, 1), (43, 1), (5419, 1), (77158673929, 1)], ); test(99, &[(3, 2), (11, 1)]); test(999, &[(3, 3), (37, 1)]); test(9999, &[(3, 2), (11, 1), (101, 1)]); test(99999, &[(3, 2), (41, 1), (271, 1)]); test(999999, &[(3, 3), (7, 1), (11, 1), (13, 1), (37, 1)]); test(9999999, &[(3, 2), (239, 1), (4649, 1)]); test(99999999, &[(3, 2), (11, 1), (73, 1), (101, 1), (137, 1)]); test(999999999, &[(3, 4), (37, 1), (333667, 1)]); test(9999999999, &[(3, 2), (11, 1), (41, 1), (271, 1), (9091, 1)]); test(99999999999, &[(3, 2), (21649, 1), (513239, 1)]); test( 999999999999, &[(3, 3), (7, 1), (11, 1), (13, 1), (37, 1), (101, 1), (9901, 1)], ); test(9999999999999, &[(3, 2), (53, 1), (79, 1), (265371653, 1)]); test( 99999999999999, &[(3, 2), (11, 1), (239, 1), (4649, 1), (909091, 1)], ); test( 999999999999999, &[(3, 3), (31, 1), (37, 1), (41, 1), (271, 1), (2906161, 1)], ); test( 9999999999999999, &[(3, 2), (11, 1), (17, 1), (73, 1), (101, 1), (137, 1), (5882353, 1)], ); // - x == 0 in n_pp1_factor_u64 // - factor == 0 first time in n_factor_pp1_u64 // - pr >= b1 in n_factor_pp1_u64 // - factor == 0 in n_factor_pp1_wrapper_u64 // - qupto == 0 in ll_factor_squfof_u64 test(99999999999999999, &[(3, 2), (2071723, 1), (5363222357, 1)]); test( 999999999999999999, &[(3, 4), (7, 1), (11, 1), (13, 1), (19, 1), (37, 1), (52579, 1), (333667, 1)], ); test(9999999999999999999, &[(3, 2), (1111111111111111111, 1)]); test(11, &[(11, 1)]); test(101, &[(101, 1)]); test(1001, &[(7, 1), (11, 1), (13, 1)]); test(10001, &[(73, 1), (137, 1)]); test(100001, &[(11, 1), (9091, 1)]); test(1000001, &[(101, 1), (9901, 1)]); test(10000001, &[(11, 1), (909091, 1)]); test(100000001, &[(17, 1), (5882353, 1)]); test(1000000001, &[(7, 1), (11, 1), (13, 1), (19, 1), (52579, 1)]); test(10000000001, &[(101, 1), (3541, 1), (27961, 1)]); test(100000000001, &[(11, 2), (23, 1), (4093, 1), (8779, 1)]); test(1000000000001, &[(73, 1), (137, 1), (99990001, 1)]); test(10000000000001, &[(11, 1), (859, 1), (1058313049, 1)]); test( 100000000000001, &[(29, 1), (101, 1), (281, 1), (121499449, 1)], ); test( 1000000000000001, &[(7, 1), (11, 1), (13, 1), (211, 1), (241, 1), (2161, 1), (9091, 1)], ); test( 10000000000000001, &[(353, 1), (449, 1), (641, 1), (1409, 1), (69857, 1)], ); test( 100000000000000001, &[(11, 1), (103, 1), (4013, 1), (21993833369, 1)], ); test( 1000000000000000001, &[(101, 1), (9901, 1), (999999000001, 1)], ); test(10000000000000000001, &[(11, 1), (909090909090909091, 1)]); test(13 * 13, &[(13, 2)]); test(251 * 251, &[(251, 2)]); // - !cofactor.is_prime() in u32::factor // - factor >= cutoff in u32::factor // - in n_factor_power235_u32 // - t != 0 first time in n_factor_power235_u32 // - t != 0 second time in n_factor_power235_u32 // - t != 0 third time in n_factor_power235_u32 // - t.odd() in n_factor_power235_u32 // - n == y.square() in n_factor_power235_u32 // - cofactor != 0 in u32::factor // - factor < cutoff || factor.is_prime() in u32::factor // - n == y.square() in n_factor_power235_u64 // - cofactor != 0 in u64::factor test(65521 * 65521, &[(65521, 2)]); test(4294967291 * 4294967291, &[(4294967291, 2)]); // - t == 0 second time in n_factor_power235_u32 // - cofactor == 0 in u32::factor // - factor >= cutoff && !factor.is_prime() in u32::factor // - found factor in u32::factor // - factor < cutoff in u32::factor test(2624473402, &[(2, 1), (36107, 1), (36343, 1)]); test( 9255318658858690055, &[(5, 1), (11, 1), (151, 1), (1114427291855351, 1)], ); test( 17556177092145474537, &[(3, 4), (37, 1), (1663, 1), (125399, 1), (28090333, 1)], ); // - pr < b1 in n_factor_pp1_u64 // - pr < sqrt in n_factor_pp1_u64 second time // - factor != 0 second time in n_factor_pp1_u64 // - factor == 1 second time in n_factor_pp1_u64 // - pr >= sqrt in n_factor_pp1_u64 second time // - factor != 1 second time in n_factor_pp1_u64 test( 9037524565425377627, &[(63793, 1), (3293177, 1), (43019107, 1)], ); // - t == 0 third time in n_factor_power235_u32 test(2989205357, &[(53783, 1), (55579, 1)]); // - t == 0 first time in n_factor_power235_u32 test(3703249699, &[(33107, 1), (111857, 1)]); // - t.even() in n_factor_power235_u32 // - t & 2 == 0 in n_factor_power235_u32 // - t & 4 == 0 in n_factor_power235_u32 test(3763227521, &[(38317, 1), (98213, 1)]); // - t & 2 != 0 in n_factor_power235_u32 // - n != y.pow(3) in n_factor_power235_u32 test(2574439811, &[(40961, 1), (62851, 1)]); // - n != y.square() in n_factor_power235_u32 test(3819439849, &[(56659, 1), (67411, 1)]); // - factor == 1 first time in n_factor_pp1_u64 test( 13303824785927286386, &[(2, 1), (41681503, 1), (159589072231, 1)], ); // - norm == 0 in n_pp1_factor_u64 test(10520651756201345771, &[(3995749, 1), (2632961118479, 1)]); // - finished_loop in ll_factor_squfof_u64 first time // - factor == 0 first time in n_factor_squfof_u64 // - factor == 0 second time in n_factor_squfof_u64 // - factor != 0 second time in n_factor_squfof_u64 // - rem != 0 in n_factor_squfof_u64 // - factor != 1 && factor != n in n_factor_squfof_u64 test(3090502153497041509, &[(1036310063, 1), (2982217643, 1)]); // - rem == 0 in n_factor_squfof_u64 // - factor == 1 || factor == n in n_factor_squfof_u64 test( 9489796947312579142, &[(2, 1), (7, 2), (2968261, 1), (32623365239, 1)], ); // - n_hi != 0 in ll_factor_squfof_u64 // - in limbs_sqrt_rem_to_out_u64 // - xs_hi != 0 in limbs_sqrt_rem_to_out_u64 // - xs_hi != 0 && shift != 0 in limbs_sqrt_rem_to_out_u64 test( 11309902016914315274, &[(2, 1), (1662217, 1), (3402053407261, 1)], ); // - t & 4 != 0 in n_factor_power235_u32 // - n != y.pow(5) in n_factor_power235_u32 test(764502619, &[(27509, 1), (27791, 1)]); // - bits < 31 in n_factor_pp1_wrapper_u64 // - q == 0 || num == 0 in ll_factor_squfof_u64 test(568345381095148801, &[(27457, 4)]); // - n == y.pow(3) in n_factor_power235_u64 test(20699471212993, &[(27457, 3)]); // - r == 1 in ll_factor_squfof_u64 test( 17600775324697324735, &[(5, 1), (6862897, 1), (512925527651, 1)], ); // - factor == 0 second time in n_factor_pp1_u64 test(7716102188277442009, &[(155049901, 1), (49765282909, 1)]); // - q.even() && qupto >= 50 in ll_factor_squfof_u64 test( 11711972945807393444, &[(2, 2), (17, 1), (16481, 1), (2530543, 1), (4129751, 1)], ); // - q.odd() && q <= l2 && qupto >= 50 in ll_factor_squfof_u64 test( 5117728824117767206, &[(2, 1), (255121, 1), (1219831, 1), (8222453, 1)], ); // primorials test(210, &[(2, 1), (3, 1), (5, 1), (7, 1)]); test(30030, &[(2, 1), (3, 1), (5, 1), (7, 1), (11, 1), (13, 1)]); test( 223092870, &[(2, 1), (3, 1), (5, 1), (7, 1), (11, 1), (13, 1), (17, 1), (19, 1), (23, 1)], ); test( 614889782588491410, &[ (2, 1), (3, 1), (5, 1), (7, 1), (11, 1), (13, 1), (17, 1), (19, 1), (23, 1), (29, 1), (31, 1), (37, 1), (41, 1), (43, 1), (47, 1), ], ); } #[test] fn test_factor() { factor_helper::(); factor_helper::(); factor_helper::(); factor_helper::(); factor_helper::(); } fn factor_fail_helper() { assert_panic!(T::ZERO.factor()); } #[test] pub fn factor_fail() { factor_fail_helper::(); factor_fail_helper::(); factor_fail_helper::(); factor_fail_helper::(); factor_fail_helper::(); } fn factor_properties_helper_helper(n: T, test_naive: bool) where ::FACTORS: IntoIterator, { let factors = n.factor().into_iter().collect_vec(); if test_naive { assert_eq!(factor_naive(n), factors); } for &(p, e) in &factors { assert!(p.is_prime()); assert_ne!(e, 0); } assert_eq!( T::product(factors.into_iter().map(|(p, e)| p.pow(u64::from(e)))), n ); } fn factor_properties_helper_1() where ::FACTORS: IntoIterator, { if T::WIDTH < u32::WIDTH { for n in exhaustive_positive_primitive_ints::() { factor_properties_helper_helper(n, true); } } else { for n in exhaustive_positive_primitive_ints::().take(10_000_000) { factor_properties_helper_helper(n, true); } unsigned_gen_var_1::().test_properties(|n| { factor_properties_helper_helper(n, false); }); } } #[test] fn factor_properties() { factor_properties_helper_1::(); factor_properties_helper_1::(); factor_properties_helper_1::(); factor_properties_helper_1::(); factor_properties_helper_1::(); } ================================================ FILE: malachite-base/tests/num/factorization/is_power.rs ================================================ // Copyright © 2026 William Youmans // // 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 malachite_base::num::arithmetic::traits::CheckedSquare; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::traits::{ExpressAsPower, Factor}; use malachite_base::num::random::random_unsigned_bit_chunks; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_15, unsigned_gen, unsigned_pair_gen_var_29, }; const NUM_TESTS: usize = 1000; const BITS: u64 = 64; #[test] fn test_perfect_squares() { // Test that squares pass the test let iter = random_unsigned_bit_chunks::(EXAMPLE_SEED, BITS / 2).take(NUM_TESTS); for d in iter { if let Some(d_squared) = d.checked_square() { let res = d_squared.express_as_power(); assert!(res.is_some()); let (base, exp) = res.unwrap(); assert_eq!(base.pow(u32::exact_from(exp)), d_squared); } } } #[test] fn test_perfect_cubes() { let iter = random_unsigned_bit_chunks::(EXAMPLE_SEED, BITS / 3).take(NUM_TESTS); for d in iter { if let Some(d_pow) = d.checked_pow(3) { let res = d_pow.express_as_power(); assert!(res.is_some()); let (base, exp) = res.unwrap(); assert_eq!(base.pow(u32::exact_from(exp)), d_pow); } } } #[test] fn test_perfect_fifth_powers() { let iter = random_unsigned_bit_chunks::(EXAMPLE_SEED, BITS / 5).take(NUM_TESTS); for d in iter { if let Some(d_pow) = d.checked_pow(5) { let res = d_pow.express_as_power(); assert!(res.is_some()); let (base, exp) = res.unwrap(); assert_eq!(base.pow(u32::exact_from(exp)), d_pow); } } } #[test] fn test_exhaustive_other_powers() { // Exhaustively test all other powers This tests all bases from 2 up to 2^(WORD_BITS/5) and all // their powers let max_base = 1u64 << (64 / 5); // Limit to prevent excessive test time for d in 2..max_base { let mut n = d * d; // Start with d^2 // Keep multiplying by d until we overflow loop { let result = n.express_as_power(); if let Some((base, exp)) = result { assert_eq!(base.pow(u32::exact_from(exp)), n); } // Try to multiply by d, break if overflow match n.checked_mul(d) { Some(next_n) => n = next_n, None => break, // Overflow occurred } } } } #[test] fn test_non_perfect_powers() { let iter = random_unsigned_bit_chunks::(EXAMPLE_SEED, 64).take(NUM_TESTS); for d in iter { // naive perfect power testing by factoring if d.factor().into_iter().count() != 1 { assert!(d.express_as_power().is_none()); } } } #[test] fn test_edge_cases() { // non-perfect powers let non_pows: [u64; 5] = [2, 3, 6, 11, 15]; for x in non_pows { assert_eq!(x.express_as_power(), None); } let pows: [u64; 12] = [0, 1, 4, 8, 9, 16, 25, 32, 64, 81, 100, 128]; for x in pows { let (base, exp) = x.express_as_power().unwrap(); assert_eq!(x, base.pow(u32::exact_from(exp))); } } #[test] fn test_signed() { assert_eq!(0i8.express_as_power().unwrap(), (0, 2)); assert_eq!(1i16.express_as_power().unwrap(), (1, 2)); assert_eq!(4i32.express_as_power().unwrap(), (2, 2)); assert_eq!(8i64.express_as_power().unwrap(), (2, 3)); assert_eq!((-1i32).express_as_power(), None); // 64 = 2^6 = 4^3 but 3 is the largest odd exponent, so -64 = (-4)^3 where in the unsigned case // we expect 2^6. etc. assert_eq!((-64i32).express_as_power().unwrap(), (-4, 3)); assert_eq!((-4096i64).express_as_power().unwrap(), (-16, 3)); assert_eq!((-3486784401i64).express_as_power().unwrap(), (-81, 5)); } fn express_as_power_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { if let Some((p, e)) = x.express_as_power() { assert!(e > 1); assert_eq!(p.pow(e), x); if x > T::ONE { assert!(p.express_as_power().is_none()); } } }); unsigned_pair_gen_var_29::().test_properties(|(x, y)| { if y > 1 { let power = x.pow(y); let ope = power.express_as_power(); assert!(ope.is_some()); let (p, e) = ope.unwrap(); assert_eq!(p.pow(e), power); if x.express_as_power().is_none() { assert_eq!(x, p); assert_eq!(y, e); } } }); } fn express_as_power_properties_helper_signed() { signed_gen::().test_properties(|x| { if let Some((p, e)) = x.express_as_power() { assert!(e > 1); assert_eq!(p.pow(e), x); if x > T::ONE { assert!(p.express_as_power().is_none()); } } }); signed_unsigned_pair_gen_var_15::().test_properties(|(x, y)| { if x != T::NEGATIVE_ONE && y > 1 { let power = x.pow(y); let ope = power.express_as_power(); assert!(ope.is_some()); let (p, e) = ope.unwrap(); assert_eq!(p.pow(e), power); if x >= T::ZERO && x.express_as_power().is_none() { assert!(x.eq_abs(&p)); assert_eq!(y, e); } } }); } #[test] fn express_as_power_properties() { apply_fn_to_unsigneds!(express_as_power_properties_helper_unsigned); apply_fn_to_signeds!(express_as_power_properties_helper_signed); } fn is_power_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { assert_eq!(x.is_power(), x.express_as_power().is_some()); }); unsigned_pair_gen_var_29::().test_properties(|(x, y)| { if y > 1 { assert!(x.pow(y).is_power()); } }); } fn is_power_properties_helper_signed() { signed_gen::().test_properties(|x| { assert_eq!(x.is_power(), x.express_as_power().is_some()); }); signed_unsigned_pair_gen_var_15::().test_properties(|(x, y)| { if x != T::NEGATIVE_ONE && y > 1 { assert!(x.pow(y).is_power()); } }); } #[test] fn is_power_properties() { apply_fn_to_unsigneds!(is_power_properties_helper_unsigned); apply_fn_to_signeds!(is_power_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/factorization/is_prime.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::num::factorization::traits::IsPrime; use malachite_base::test_util::generators::{unsigned_gen, unsigned_pair_gen_var_50}; use malachite_base::test_util::num::factorization::is_prime::is_prime_naive; fn is_prime_helper() { let test = |n: u64, out| { if let Ok(n) = T::try_from(n) { assert_eq!(n.is_prime(), out); assert_eq!(is_prime_naive(n), out); } }; // - in u32::is_prime // - n < 11 in u32::is_prime // - in u64::is_prime // - n < 11 in u64::is_prime test(0, false); test(1, false); test(2, true); test(3, true); test(4, false); test(5, true); test(6, false); test(7, true); test(8, false); test(9, false); test(10, false); // - n >= 11 in u32::is_prime // - prime factor <= 7 in u32::is_prime // - n >= 11 in u64::is_prime // - prime factor <= 7 in u64::is_prime test(u64::power_of_2(4) - 1, false); // - no prime factor <= 7 in u32::is_prime // - n < 121 in u32::is_prime // - no prime factor <= 7 in u64::is_prime // - n < 121 in u64::is_prime test(u64::power_of_2(5) - 1, true); test(u64::power_of_2(6) - 1, false); // - n >= 121 in u32::is_prime // - no prime factor <= 53 in u32::is_prime // - n < 3481 in u32::is_prime // - n >= 121 in u64::is_prime // - no prime factor <= 53 in u64::is_prime // - n < 3481 in u64::is_prime test(u64::power_of_2(7) - 1, true); test(u64::power_of_2(8) - 1, false); test(u64::power_of_2(9) - 1, false); test(u64::power_of_2(10) - 1, false); // - prime factor <= 53 in u32::is_prime // - prime factor <= 53 in u64::is_prime test(u64::power_of_2(11) - 1, false); test(u64::power_of_2(12) - 1, false); // - n >= 3481 in u32::is_prime // - n <= 1000000 or no prime factor <= 149 in u32::is_prime // - in n_is_probabprime_u32 // - FLINT_ODDPRIME_SMALL_CUTOFF <= n < FLINT_PRIMES_TAB_DEFAULT_CUTOFF in n_is_probabprime_u32 // - in n_is_oddprime_binary_u32 // - in n_prime_pi_bounds_u32 // - n >= PRIME_PI_ODD_LOOKUP_CUTOFF in n_prime_pi_bounds_u32 // - n < primes[prime_hi as usize] in n_is_oddprime_binary_u32 // - primes[(prime_lo + diff) as usize] > n in n_is_oddprime_binary_u32 // - diff > 1 in n_is_oddprime_binary_u32 // - diff <= diff2 in n_is_oddprime_binary_u32 // - primes[(prime_lo + diff) as usize] <= n in n_is_oddprime_binary_u32 // - diff <= 1 in n_is_oddprime_binary_u32 // - n >= 3481 in u64::is_prime // - n <= 1000000 or no prime factor <= 149 in u64::is_prime // - in n_is_probabprime_u64 // - FLINT_ODDPRIME_SMALL_CUTOFF <= n < FLINT_PRIMES_TAB_DEFAULT_CUTOFF in n_is_probabprime_u64 // - in n_is_oddprime_binary_u64 // - in n_prime_pi_bounds_u64 // - n >= PRIME_PI_ODD_LOOKUP_CUTOFF in n_prime_pi_bounds_u64 // - n < primes[prime_hi as usize] in n_is_oddprime_binary_u64 // - primes[(prime_lo + diff) as usize] > n in n_is_oddprime_binary_u64 // - diff > 1 in n_is_oddprime_binary_u64 // - diff <= diff2 in n_is_oddprime_binary_u64 // - primes[(prime_lo + diff) as usize] <= n in n_is_oddprime_binary_u64 // - diff <= 1 in n_is_oddprime_binary_u64 test(u64::power_of_2(13) - 1, true); test(u64::power_of_2(14) - 1, false); test(u64::power_of_2(15) - 1, false); test(u64::power_of_2(16) - 1, false); test(u64::power_of_2(17) - 1, true); test(u64::power_of_2(18) - 1, false); test(u64::power_of_2(19) - 1, true); test(u64::power_of_2(20) - 1, false); test(u64::power_of_2(21) - 1, false); test(u64::power_of_2(22) - 1, false); test(u64::power_of_2(23) - 1, false); test(u64::power_of_2(24) - 1, false); test(u64::power_of_2(25) - 1, false); test(u64::power_of_2(26) - 1, false); test(u64::power_of_2(27) - 1, false); test(u64::power_of_2(28) - 1, false); // - n >= FLINT_PRIMES_TAB_DEFAULT_CUTOFF in n_is_probabprime_u32 // - n >= 9080191 in n_is_probabprime_u32 // - in n_is_strong_probabprime2_preinv_u32 // - a > 1 && a != n - 1 in n_is_strong_probabprime2_preinv_u32 // - in n_powmod2_ui_preinv_u32 // - exp != 0 in n_powmod2_ui_preinv_u32 // - a != 0 in n_powmod2_ui_preinv_u32 // - a < n in n_powmod2_ui_preinv_u32 // - exp.odd() in n_powmod2_ui_preinv_u32 // - y == 1 in n_is_strong_probabprime2_preinv_u32 // - y != 1 in n_is_strong_probabprime2_preinv_u32 // - n >= FLINT_PRIMES_TAB_DEFAULT_CUTOFF in n_is_probabprime_u64 // - n < 1050535501 in n_is_probabprime_u64 // - n >= 341531 in n_is_probabprime_u64 // - in n_is_strong_probabprime_precomp_u64 // - a >= n in n_is_strong_probabprime_precomp_u64 // - in n_mod2_precomp_u64 // - a >= n in n_mod2_precomp_u64 // - ni >= 0 in n_mod2_precomp_u64 // - n != 1 in n_mod2_precomp_u64 // - rem >= 0 in n_mod2_precomp_u64 first time // - a > 1 && a != n - 1 n_is_strong_probabprime_precomp_u64 // - in n_powmod_ui_precomp_u64 // - n != 1 in n_powmod_ui_precomp_u64 // - exp.odd() in n_powmod_ui_precomp_u64 // - in n_mulmod_precomp_u64 // - n > rem in n_mulmod_precomp_u64 // - exp != 0 in n_powmod_ui_precomp_u64 // - exp == 0 in n_powmod_ui_precomp_u64 // - y != 1 n_is_strong_probabprime_precomp_u64 test(u64::power_of_2(29) - 1, false); test(u64::power_of_2(30) - 1, false); // - n >= 1050535501 in n_is_probabprime_u64 // - in n_is_probabprime_bpsw_u64 // - n > 1 in n_is_probabprime_bpsw_u64 // - n.odd() in n_is_probabprime_bpsw_u64 // - nm10 == 3 || nm10 == 7 in n_is_probabprime_bpsw_u64 // - in n_is_probabprime_fermat_u64 // - n.significant_bits() <= FLINT_D_BITS_U64 in n_is_probabprime_fermat_u64 // - in n_powmod_u64 // - in n_powmod_precomp_u64 // - exp >= 0 in n_powmod_precomp_u64 // - exp.even() in n_powmod_ui_precomp_u64 // - in n_is_probabprime_fibonacci_u64 // - i64::wrapping_from(n).gt_abs(&3) in n_is_probabprime_fibonacci_u64 // - n.significant_bits() <= FLINT_D_BITS_U64 in n_is_probabprime_fibonacci_u64 // - in fchain_precomp_u64 // - m & power != 0 in fchain_precomp_u64 // - m & power == 0 in fchain_precomp_u64 test(u64::power_of_2(31) - 1, true); test(u64::power_of_2(32) - 1, false); test(u64::power_of_2(33) - 1, false); test(u64::power_of_2(34) - 1, false); test(u64::power_of_2(35) - 1, false); test(u64::power_of_2(36) - 1, false); // - nm10 != 3 && nm10 != 7 in n_is_probabprime_bpsw_u64 // - n.significant_bits() <= FLINT_D_BITS_U64 in n_is_probabprime_bpsw_u64 // - a < n in n_is_strong_probabprime_precomp_u64 // - y == 1 n_is_strong_probabprime_precomp_u64 // - n_is_strong_probabprime_precomp_u64(n, npre, 2, d) in n_is_probabprime_bpsw_u64 // - in n_is_probabprime_lucas_u64 // - d.gcd(n % d) == 1 in n_is_probabprime_lucas_u64 // - i.even() in n_is_probabprime_lucas_u64 // - !neg_d in n_is_probabprime_lucas_u64 first time // - jacobi != -1 in n_is_probabprime_lucas_u64 // - i.odd() in n_is_probabprime_lucas_u64 // - neg_d in n_is_probabprime_lucas_u64 first time // - jacobi == -1 in n_is_probabprime_lucas_u64 // - j < 100 in n_is_probabprime_lucas_u64 // - neg_d in n_is_probabprime_lucas_u64 second time // - q >= 0 && n >= 52 in n_is_probabprime_lucas_u64 // - n > FLINT_D_BITS_U64 in n_is_probabprime_lucas_u64 // - in lchain2_preinv_u64 // - m & power != 0 in lchain2_preinv_u64 // - m & power == 0 in lchain2_preinv_u64 test(u64::power_of_2(37) - 1, false); test(u64::power_of_2(38) - 1, false); test(u64::power_of_2(39) - 1, false); test(u64::power_of_2(40) - 1, false); test(u64::power_of_2(41) - 1, false); test(u64::power_of_2(42) - 1, false); test(u64::power_of_2(43) - 1, false); test(u64::power_of_2(44) - 1, false); test(u64::power_of_2(45) - 1, false); test(u64::power_of_2(46) - 1, false); test(u64::power_of_2(47) - 1, false); test(u64::power_of_2(48) - 1, false); // - n > 1000000 and prime factor <= 149 in u64::is_prime test(u64::power_of_2(49) - 1, false); test(u64::power_of_2(50) - 1, false); test(u64::power_of_2(51) - 1, false); test(u64::power_of_2(52) - 1, false); test(u64::power_of_2(53) - 1, false); test(u64::power_of_2(54) - 1, false); test(u64::power_of_2(55) - 1, false); test(u64::power_of_2(56) - 1, false); test(u64::power_of_2(57) - 1, false); test(u64::power_of_2(58) - 1, false); // - n.significant_bits() > FLINT_D_BITS_U64 in n_is_probabprime_fermat_u64 // - in n_powmod2_ui_preinv_u64 // - exp != 0 in n_powmod2_ui_preinv_u64 // - a != 0 in n_powmod2_ui_preinv_u64 // - a < 0 in n_powmod2_ui_preinv_u64 // - exp.odd() in n_powmod2_ui_preinv_u64 // - n.significant_bits() > FLINT_D_BITS_U64 in n_is_probabprime_fibonacci_u64 // - in fchain2_preinv_u64 // - m & power != 0 in fchain2_preinv_u64 // - m & power == 0 in fchain2_preinv_u64 test(u64::power_of_2(59) - 1, false); test(u64::power_of_2(60) - 1, false); // - n.significant_bits() > FLINT_D_BITS_U64 in n_is_probabprime_bpsw_u64 // - in n_is_strong_probabprime2_preinv_u64 // - a > 1 && a != n - 1 in n_is_strong_probabprime2_preinv_u64 // - y == 1 in n_is_strong_probabprime2_preinv_u64 // - n_is_strong_probabprime2_preinv_u64(n, ninv, 2, d) in n_is_probabprime_bpsw_u64 // - !neg_d in n_is_probabprime_lucas_u64 second time // - q < 0 in n_is_probabprime_lucas_u64 // - q < 0 && n >= 52 in n_is_probabprime_lucas_u64 test(u64::power_of_2(61) - 1, true); test(u64::power_of_2(62) - 1, false); test(u64::power_of_2(63) - 1, false); test(u64::MAX, false); test(u64::power_of_2(4) + 1, true); test(u64::power_of_2(5) + 1, false); test(u64::power_of_2(6) + 1, false); test(u64::power_of_2(7) + 1, false); test(u64::power_of_2(8) + 1, true); test(u64::power_of_2(9) + 1, false); test(u64::power_of_2(10) + 1, false); test(u64::power_of_2(11) + 1, false); test(u64::power_of_2(12) + 1, false); test(u64::power_of_2(13) + 1, false); test(u64::power_of_2(14) + 1, false); test(u64::power_of_2(15) + 1, false); test(u64::power_of_2(16) + 1, true); test(u64::power_of_2(17) + 1, false); test(u64::power_of_2(18) + 1, false); test(u64::power_of_2(19) + 1, false); test(u64::power_of_2(20) + 1, false); test(u64::power_of_2(21) + 1, false); test(u64::power_of_2(22) + 1, false); test(u64::power_of_2(23) + 1, false); // - n > 1000000 and prime factor <= 149 in u32::is_prime test(u64::power_of_2(24) + 1, false); test(u64::power_of_2(25) + 1, false); test(u64::power_of_2(26) + 1, false); test(u64::power_of_2(27) + 1, false); test(u64::power_of_2(28) + 1, false); test(u64::power_of_2(29) + 1, false); test(u64::power_of_2(30) + 1, false); test(u64::power_of_2(31) + 1, false); test(u64::power_of_2(32) + 1, false); test(u64::power_of_2(33) + 1, false); test(u64::power_of_2(34) + 1, false); test(u64::power_of_2(35) + 1, false); test(u64::power_of_2(36) + 1, false); test(u64::power_of_2(37) + 1, false); test(u64::power_of_2(38) + 1, false); test(u64::power_of_2(39) + 1, false); // - rem < 0 first time in n_mulmod_precomp_u64 // - rem >= 0 second time in n_mulmod_precomp_u64 test(u64::power_of_2(40) + 1, false); test(u64::power_of_2(41) + 1, false); test(u64::power_of_2(42) + 1, false); test(u64::power_of_2(43) + 1, false); test(u64::power_of_2(44) + 1, false); test(u64::power_of_2(45) + 1, false); test(u64::power_of_2(46) + 1, false); test(u64::power_of_2(47) + 1, false); test(u64::power_of_2(48) + 1, false); test(u64::power_of_2(49) + 1, false); test(u64::power_of_2(50) + 1, false); test(u64::power_of_2(51) + 1, false); test(u64::power_of_2(52) + 1, false); test(u64::power_of_2(53) + 1, false); test(u64::power_of_2(54) + 1, false); test(u64::power_of_2(55) + 1, false); test(u64::power_of_2(56) + 1, false); test(u64::power_of_2(57) + 1, false); test(u64::power_of_2(58) + 1, false); test(u64::power_of_2(59) + 1, false); test(u64::power_of_2(60) + 1, false); test(u64::power_of_2(61) + 1, false); test(u64::power_of_2(62) + 1, false); test(u64::power_of_2(63) + 1, false); test(u64::power_of_2(4) - 3, true); test(u64::power_of_2(5) - 1, true); test(u64::power_of_2(6) - 3, true); test(u64::power_of_2(7) - 1, true); test(u64::power_of_2(8) - 5, true); test(u64::power_of_2(9) - 3, true); test(u64::power_of_2(10) - 3, true); test(u64::power_of_2(11) - 9, true); // - n < FLINT_ODDPRIME_SMALL_CUTOFF in n_is_probabprime_u32 // - in n_is_oddprime_small_u32 // - n < FLINT_ODDPRIME_SMALL_CUTOFF in n_is_probabprime_u64 // - in n_is_oddprime_small_u64 test(u64::power_of_2(12) - 3, true); test(u64::power_of_2(13) - 1, true); test(u64::power_of_2(14) - 3, true); test(u64::power_of_2(15) - 19, true); test(u64::power_of_2(16) - 15, true); test(u64::power_of_2(17) - 1, true); test(u64::power_of_2(18) - 5, true); test(u64::power_of_2(19) - 1, true); // - n < 9080191 in n_is_probabprime_u32 test(u64::power_of_2(20) - 3, true); // - exp.even() in n_powmod2_ui_preinv_u32 test(u64::power_of_2(21) - 9, true); test(u64::power_of_2(22) - 3, true); test(u64::power_of_2(23) - 15, true); test(u64::power_of_2(24) - 3, true); test(u64::power_of_2(25) - 39, true); test(u64::power_of_2(26) - 5, true); test(u64::power_of_2(27) - 39, true); test(u64::power_of_2(28) - 57, true); test(u64::power_of_2(29) - 3, true); test(u64::power_of_2(30) - 35, true); test(u64::power_of_2(31) - 1, true); test(u64::power_of_2(32) - 5, true); test(u64::power_of_2(33) - 9, true); test(u64::power_of_2(34) - 41, true); test(u64::power_of_2(35) - 31, true); test(u64::power_of_2(36) - 5, true); test(u64::power_of_2(37) - 25, true); test(u64::power_of_2(38) - 45, true); test(u64::power_of_2(39) - 7, true); test(u64::power_of_2(40) - 87, true); test(u64::power_of_2(41) - 21, true); test(u64::power_of_2(42) - 11, true); test(u64::power_of_2(43) - 57, true); test(u64::power_of_2(44) - 17, true); test(u64::power_of_2(45) - 55, true); test(u64::power_of_2(46) - 21, true); test(u64::power_of_2(47) - 115, true); test(u64::power_of_2(48) - 59, true); test(u64::power_of_2(49) - 81, true); test(u64::power_of_2(50) - 27, true); test(u64::power_of_2(51) - 129, true); test(u64::power_of_2(52) - 47, true); // - rem < 0 second time in n_mulmod_precomp_u64 test(u64::power_of_2(53) - 111, true); // - exp.even() in n_powmod2_ui_preinv_u64 test(u64::power_of_2(54) - 33, true); test(u64::power_of_2(55) - 55, true); // - y != 1 in n_is_strong_probabprime2_preinv_u64 test(u64::power_of_2(56) - 5, true); test(u64::power_of_2(57) - 13, true); test(u64::power_of_2(58) - 27, true); test(u64::power_of_2(59) - 55, true); test(u64::power_of_2(60) - 93, true); test(u64::power_of_2(61) - 1, true); test(u64::power_of_2(62) - 57, true); test(u64::power_of_2(63) - 25, true); test(u64::MAX - 58, true); test(u64::power_of_2(5) + 5, true); test(u64::power_of_2(6) + 3, true); test(u64::power_of_2(7) + 3, true); test(u64::power_of_2(9) + 9, true); test(u64::power_of_2(10) + 7, true); test(u64::power_of_2(11) + 5, true); test(u64::power_of_2(12) + 3, true); test(u64::power_of_2(13) + 17, true); test(u64::power_of_2(14) + 27, true); // - diff > diff2 in n_is_oddprime_binary_u32 // - diff > diff2 in n_is_oddprime_binary_u64 test(u64::power_of_2(15) + 3, true); test(u64::power_of_2(17) + 29, true); test(u64::power_of_2(18) + 3, true); test(u64::power_of_2(19) + 21, true); test(u64::power_of_2(20) + 7, true); test(u64::power_of_2(21) + 17, true); test(u64::power_of_2(22) + 15, true); test(u64::power_of_2(23) + 9, true); test(u64::power_of_2(24) + 43, true); test(u64::power_of_2(25) + 35, true); test(u64::power_of_2(26) + 15, true); test(u64::power_of_2(27) + 29, true); test(u64::power_of_2(28) + 3, true); test(u64::power_of_2(29) + 11, true); test(u64::power_of_2(30) + 3, true); test(u64::power_of_2(31) + 11, true); test(u64::power_of_2(32) + 15, true); test(u64::power_of_2(33) + 17, true); test(u64::power_of_2(34) + 25, true); test(u64::power_of_2(35) + 53, true); test(u64::power_of_2(36) + 31, true); test(u64::power_of_2(37) + 9, true); test(u64::power_of_2(38) + 7, true); test(u64::power_of_2(39) + 23, true); test(u64::power_of_2(40) + 15, true); test(u64::power_of_2(41) + 27, true); test(u64::power_of_2(42) + 15, true); test(u64::power_of_2(43) + 29, true); test(u64::power_of_2(44) + 7, true); test(u64::power_of_2(45) + 59, true); test(u64::power_of_2(46) + 15, true); test(u64::power_of_2(47) + 5, true); test(u64::power_of_2(48) + 21, true); test(u64::power_of_2(49) + 69, true); test(u64::power_of_2(50) + 55, true); test(u64::power_of_2(51) + 21, true); test(u64::power_of_2(52) + 21, true); test(u64::power_of_2(53) + 5, true); test(u64::power_of_2(54) + 159, true); test(u64::power_of_2(55) + 3, true); test(u64::power_of_2(56) + 81, true); test(u64::power_of_2(57) + 9, true); test(u64::power_of_2(58) + 69, true); test(u64::power_of_2(59) + 131, true); test(u64::power_of_2(60) + 33, true); test(u64::power_of_2(61) + 15, true); test(u64::power_of_2(62) + 135, true); test(u64::power_of_2(63) + 29, true); test(11, true); test(101, true); test(1001, false); test(10001, false); test(100001, false); test(1000001, false); test(10000001, false); test(100000001, false); test(1000000001, false); test(10000000001, false); test(100000000001, false); test(1000000000001, false); test(10000000000001, false); test(100000000000001, false); test(1000000000000001, false); // - !n_is_strong_probabprime2_preinv_u64(n, ninv, 2, d) in n_is_probabprime_bpsw_u64 test(10000000000000001, false); test(100000000000000001, false); test(1000000000000000001, false); test(10000000000000000001, false); test(11, true); test(101, true); test(1009, true); test(10007, true); test(100003, true); test(1000003, true); test(10000019, true); test(100000007, true); test(1000000007, true); test(10000000019, true); test(100000000003, true); // - 0 <= rem <= n in n_mulmod_precomp_u64 test(1000000000039, true); test(10000000000037, true); test(100000000000031, true); test(1000000000000037, true); test(10000000000000061, true); test(100000000000000003, true); test(1000000000000000003, true); test(10000000000000000051, true); test(97, true); test(997, true); test(9973, true); test(99991, true); test(999983, true); test(9999991, true); test(99999989, true); test(999999937, true); test(9999999967, true); test(99999999977, true); test(999999999989, true); test(9999999999971, true); test(99999999999973, true); test(999999999999989, true); test(9999999999999937, true); test(99999999999999997, true); test(999999999999999989, true); test(9999999999999999961, true); test(1000003, true); test(5509785649208481923, true); test(8435959509307532899, true); test(15455033058440548141, true); test(13200125384684540339, true); // - a <= 1 || a == n - 1 n_is_strong_probabprime_precomp_u64 test(6855593, true); // - !n_is_strong_probabprime_precomp_u64(n, npre, 2, d) in n_is_probabprime_bpsw_u64 test(1050535501, false); test(1114427291855351, true); } #[test] fn test_is_prime() { is_prime_helper::(); is_prime_helper::(); is_prime_helper::(); is_prime_helper::(); is_prime_helper::(); } fn is_prime_properties_helper_helper(n: T) { let is_prime = n.is_prime(); assert_eq!(is_prime_naive(n), is_prime); } fn is_prime_properties_helper_1() { if T::WIDTH < u32::WIDTH { for n in exhaustive_unsigneds::() { is_prime_properties_helper_helper(n); } } else { for n in exhaustive_unsigneds::().take(10_000_000) { is_prime_properties_helper_helper(n); } unsigned_gen::().test_properties(|n| { is_prime_properties_helper_helper(n); }); } } fn is_prime_properties_helper_2 + IsPrime + PrimitiveUnsigned>() { unsigned_pair_gen_var_50::().test_properties(|(a, b)| { assert!(!(DT::from(a) * DT::from(b)).is_prime()); }); } #[test] fn is_prime_properties() { is_prime_properties_helper_1::(); is_prime_properties_helper_1::(); is_prime_properties_helper_1::(); is_prime_properties_helper_1::(); is_prime_properties_helper_1::(); is_prime_properties_helper_2::(); is_prime_properties_helper_2::(); } ================================================ FILE: malachite-base/tests/num/factorization/is_square.rs ================================================ // Copyright © 2026 William Youmans // // 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::factorization::traits::IsSquare; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_4, signed_gen_var_10, unsigned_gen, unsigned_gen_var_21, unsigned_pair_gen_var_27, }; fn is_square_properties_helper_unsigned() { unsigned_gen::().test_properties(|x| { assert_eq!(x.is_square(), x.checked_sqrt().is_some()); }); unsigned_gen_var_21::().test_properties(|x| { assert!(x.square().is_square()); }); // 1 < x < 2^32 avoids overflow and consecutive squares (0, 1). unsigned_pair_gen_var_27::().test_properties(|(mut x, mut y)| { // test non squares in interval (x^2, (x+1)^2) x.mod_power_of_2_assign(T::WIDTH >> 1); y.mod_power_of_2_assign(T::WIDTH >> 1); if x != T::ZERO { let sqr = x.square(); let non_sqr = sqr + (y % (x << 1u32)) + T::ONE; assert!(!non_sqr.is_square()); } }); } fn is_square_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom + UnsignedAbs, >() { signed_gen::().test_properties(|x| { assert_eq!(x.is_square(), x >= S::ZERO && x.unsigned_abs().is_square()); }); signed_gen_var_10::().test_properties(|x| { assert!(x.square().is_square()); }); // test negative signed integers are non square and positive signed integer squares are squares. signed_gen_var_4::().test_properties(|x| { assert!(!x.is_square()); }); } #[test] fn is_square_properties() { apply_fn_to_unsigneds!(is_square_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(is_square_properties_helper_signed); } #[test] fn test_is_square() { assert!(0u8.is_square()); assert!(0u16.is_square()); assert!(0u32.is_square()); assert!(0u64.is_square()); assert!(1u64.is_square()); assert!(4u64.is_square()); assert!(9u64.is_square()); assert!(16u64.is_square()); assert!(25u64.is_square()); assert!(0i8.is_square()); assert!(0i16.is_square()); assert!(0i32.is_square()); assert!(0i64.is_square()); assert!(1i64.is_square()); assert!(4i64.is_square()); assert!(9i64.is_square()); assert!(16i64.is_square()); assert!(25i64.is_square()); assert!(!(-1i64).is_square()); assert!(!(-4i64).is_square()); assert!(!(-9i64).is_square()); assert!(!(-16i64).is_square()); assert!(!(-25i64).is_square()); } ================================================ FILE: malachite-base/tests/num/factorization/prime_indicator_sequence.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::primes::prime_indicator_sequence; #[test] pub fn test_prime_indicator_sequence() { let s: String = prime_indicator_sequence() .take(1000) .map(|b| if b { '1' } else { '0' }) .collect(); assert_eq!( s, "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ 000000010001010001010001000000000000010001000001010000000001010000010000010001000001000001\ 010000000001010001010000000000010000000000010001010001000001010000000001000001000001000001\ 010000010001010000000001000000000000010001010001000000000000010000010000000001010001000001\ 000000010000010000010001000001000000010001000000010000000001010000000001010000010001000001\ 000000010001010001000000000001000000010001000000010001000001000000000001010000000000000000\ 010000010000000001000001000001010000010000000001000001000001010000010000010001010000000000\ 010000000001010001000001000001010000000000010001000001000000010000000001000000010000000001\ 000000010000010000010001000000010000010001000000010001000000000000010000000001000000000001\ 010000000001010001010000000001000000000000010001010001000000000000010001010001000000000000\ 000000010001000000010000000001000000010001000001000001000000000000010001000001000001000000\ 01000001000" ); } ================================================ FILE: malachite-base/tests/num/factorization/prime_indicator_sequence_less_than.rs ================================================ // Copyright © 2026 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 crate::itertools::Itertools; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::primes::{ prime_indicator_sequence, prime_indicator_sequence_less_than, }; use malachite_base::test_util::generators::unsigned_gen_var_5; fn test_prime_indicator_sequence_helper(limit: u64, out: &str) { let s: String = prime_indicator_sequence_less_than(limit) .take(1000) .map(|b| if b { '1' } else { '0' }) .collect(); assert_eq!(s, out); } #[test] pub fn test_prime_indicator_sequence_less_than() { test_prime_indicator_sequence_helper(0, ""); test_prime_indicator_sequence_helper(1, ""); test_prime_indicator_sequence_helper(2, "0"); test_prime_indicator_sequence_helper(3, "01"); test_prime_indicator_sequence_helper(4, "011"); test_prime_indicator_sequence_helper(5, "0110"); test_prime_indicator_sequence_helper(6, "01101"); test_prime_indicator_sequence_helper(7, "011010"); test_prime_indicator_sequence_helper(8, "0110101"); test_prime_indicator_sequence_helper(9, "01101010"); test_prime_indicator_sequence_helper(10, "011010100"); test_prime_indicator_sequence_helper( 100, "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ 0000000100", ); test_prime_indicator_sequence_helper( 1000, "01101010001010001010001000001010000010001010001000001000001010000010001010000010001000001\ 000000010001010001010001000000000000010001000001010000000001010000010000010001000001000001\ 010000000001010001010000000000010000000000010001010001000001010000000001000001000001000001\ 010000010001010000000001000000000000010001010001000000000000010000010000000001010001000001\ 000000010000010000010001000001000000010001000000010000000001010000000001010000010001000001\ 000000010001010001000000000001000000010001000000010001000001000000000001010000000000000000\ 010000010000000001000001000001010000010000000001000001000001010000010000010001010000000000\ 010000000001010001000001000001010000000000010001000001000000010000000001000000010000000001\ 000000010000010000010001000000010000010001000000010001000000000000010000000001000000000001\ 010000000001010001010000000001000000000000010001010001000000000000010001010001000000000000\ 000000010001000000010000000001000000010001000001000001000000000000010001000001000001000000\ 0100000100", ); } #[test] fn prime_indicator_sequence_less_than_properties() { unsigned_gen_var_5().test_properties(|limit| { let bs = prime_indicator_sequence_less_than(limit).collect_vec(); let len = usize::exact_from(limit.saturating_sub(1)); assert_eq!(bs.len(), len); assert_eq!(prime_indicator_sequence().take(len).collect_vec(), bs); }); } ================================================ FILE: malachite-base/tests/num/factorization/prime_sieve.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::prime_sieve::{ limbs_prime_sieve_size, limbs_prime_sieve_u32, limbs_prime_sieve_u64, }; use malachite_base::test_util::generators::unsigned_gen_var_26; use malachite_base::test_util::num::factorization::prime_sieve::{ limbs_prime_sieve_naive_1, limbs_prime_sieve_naive_2, }; #[test] fn test_limbs_prime_sieve_u32() { let test = |n, out, out_sieve: &[u32]| { let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_u32(&mut sieve, n), out); assert_eq!(sieve, out_sieve); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); }; let test_large = |n, out| { let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_u32(&mut sieve, n), out); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); }; // - size <= BLOCK_SIZE << 1 // - limbs == 0 in first_block_primesieve // - (bits + 1) & Limb::WIDTH_MASK != 0 in first_block_primesieve // - (bits + 1) & Limb::WIDTH_MASK != 0 test(5, 1, &[4294967294]); // - (bits + 1) & Limb::WIDTH_MASK == 0 in first_block_primesieve // - (bits + 1) & Limb::WIDTH_MASK == 0 test(97, 23, &[1762821248]); // - limbs != 0 in first_block_primesieve // - offset == 0 first time in fill_bitpattern test(101, 24, &[1762821248, 4294967294]); // - n_to_bit(SEED_LIMIT + 1) >= Limb::WIDTH in first_block_primesieve // - bit_array[index] & mask == 0 in first_block_primesieve // - lindex <= bits first time in first_block_primesieve // - lindex > bits second time in first_block_primesieve // - lindex > bits first time in first_block_primesieve test(121, 28, &[1762821248, 4294967264]); // - lindex <= bits second time in first_block_primesieve test(187, 40, &[1762821248, 4069837280]); // - limbs != 0 first time in fill_bitpattern // - limbs == 0 second time in fill_bitpattern test(197, 43, &[1762821248, 848611808, 4294967294]); // - limbs != 0 second time in fill_bitpattern test(293, 60, &[1762821248, 848611808, 3299549660, 4294967294]); // - bit_array[index] & mask != 0 in first_block_primesieve test( 529, 97, &[1762821248, 848611808, 3299549660, 2510511646, 3093902182, 4294954649], ); test( 10000, 1227, &[ 1762821248, 848611808, 3299549660, 2510511646, 3093902182, 1255657113, 1921893675, 1704310490, 2276511454, 3933052807, 3442636201, 1062642164, 1957128923, 4248324347, 2716726959, 3686403537, 3525810597, 3469209982, 3144777046, 3941341117, 1482358003, 990820275, 2682219599, 3848526070, 2757661436, 4267419563, 1005886333, 361623151, 3991325978, 3193600964, 3397105325, 3613891391, 535771113, 3287706519, 969495549, 1870576883, 3526745072, 3584421084, 3585498683, 3975838511, 3365889969, 3532586489, 1037283151, 3414129786, 4285215436, 4005484237, 1590667644, 3585963000, 3148695799, 570277455, 4005035495, 1580573621, 2816195785, 3656121683, 788406134, 4288601775, 3209020842, 1475950840, 3242065846, 4101944926, 1238805919, 2074062642, 2532965119, 3010383198, 4133027549, 1790162093, 3623277869, 1878747087, 3720235807, 3033363191, 4214476775, 2614931297, 3853071358, 3216472538, 3950886702, 2080282321, 2138895219, 667676511, 2805099227, 1743386524, 4235696025, 1592700903, 3706043128, 3619639167, 2080028206, 4197678553, 2138431973, 2627728235, 2372861911, 1911355103, 1566205629, 3013582698, 1609955564, 4047489974, 4125088590, 3923174885, 3200773946, 3589010553, 3953720370, 2080348909, 1828150423, 2537461567, 2647369563, 4126591959, 4294967295, ], ); // - size > BLOCK_SIZE << 1 // - offset != 0 first time in fill_bitpattern // - offset != 0 second time in fill_bitpattern // - offset <= Limb::WIDTH in fill_bitpattern // - offset != Limb::WIDTH in fill_bitpattern // - offset > 70 - 2 * Limb::WIDTH in fill_bitpattern // - sieve[index] & mask == 0 in block_resieve // - lindex <= bits + off in block_resieve // - lindex < off first time in block_resieve // - lindex < off second time in block_resieve // - sieve[index] & mask != 0 in block_resieve // - lindex >= off first time in block_resieve // - lindex >= off second time in block_resieve // - lindex > bits + off in block_resieve // - off >= size test_large(400000, 33858); // - Limb::WIDTH < offset < 2 * Limb::WIDTH in fill_bitpattern // - offset > 70 - Limb::WIDTH in fill_bitpattern test_large(400037, 33861); // - offset <= 70 - 2 * Limb::WIDTH in fill_bitpattern test_large(400325, 33885); // - offset <= 70 - Limb::WIDTH in fill_bitpattern // - offset != 70 - Limb::WIDTH in fill_bitpattern test_large(400421, 33891); // - offset >= 2 * Limb::WIDTH in fill_bitpattern test_large(400517, 33896); // - offset == 70 - Limb::WIDTH in fill_bitpattern test_large(401477, 33963); // - offset == 0 second time in fill_bitpattern test_large(401573, 33969); // - offset == Limb::WIDTH in fill_bitpattern test_large(401669, 33975); } #[test] fn test_limbs_prime_sieve_u64() { let test = |n, out, out_sieve: &[u64]| { let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_u64(&mut sieve, n), out); assert_eq!(sieve, out_sieve); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); }; let test_large = |n, out| { let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_u64(&mut sieve, n), out); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); }; // - offset == 0 first time in fill_bitpattern // - limbs == 0 first time in fill_bitpattern // - limbs != 0 first time in fill_bitpattern // - limbs == 0 second time in fill_bitpattern // - limbs != 0 second time in fill_bitpattern test(197, 43, &[3644759964122252416, 18446744073709551614]); test( 10000, 1227, &[ 3644759964122252416, 10782565419096678876, 5393006238418678630, 7319957818701628715, 16892333181782511326, 4564013345173304745, 18246414135122684635, 15832982633990452911, 14900143419172559269, 16927931203039886678, 4255540678821084403, 16529293611135626319, 18328427464153273084, 1553159608027356029, 13716411700845399322, 15521545339038054061, 14120591978486773737, 8034066538108113917, 15394971334399613936, 17076096382507834939, 15172343443912353713, 14663575776206761807, 17203423806843728588, 15401593811256715644, 2449323022019807479, 6788512015120334311, 15702923061497674953, 18419404369980956534, 6339160591512749482, 17617719310405205942, 8908031218484161951, 12929497386370857727, 7688687648106938077, 8069157299743544621, 13028195705955437343, 11231044406116339687, 13814644363045188606, 8934744539092860718, 2867648781191279475, 7487788107672218331, 6840598294930364313, 15546231849291725560, 18028892106335630894, 11286006834239234533, 8209207660800573399, 12943239133267650237, 17383837070827845868, 16849907831688649550, 15414682953334648634, 8935030532378000434, 10898314446950063255, 17723577510488942427, 18446744073709551615, ], ); // - offset != 0 first time in fill_bitpattern // - m21 != 0 in fill_bitpattern // - m21 < Limb::WIDTH in fill_bitpattern // - m21 <= 110 - Limb::WIDTH in fill_bitpattern // - offset != 0 second time in fill_bitpattern // - offset >= 2 * Limb::WIDTH in fill_bitpattern test_large(800000, 63949); // - m21 >= Limb::WIDTH in fill_bitpattern // - offset <= Limb::WIDTH in fill_bitpattern // - offset != Limb::WIDTH in fill_bitpattern // - offset <= 182 - 2 * Limb::WIDTH in fill_bitpattern test_large(800069, 63953); // - m21 > 110 - Limb::WIDTH in fill_bitpattern // - Limb::WIDTH < offset < 2 * Limb::WIDTH in fill_bitpattern // - offset <= 182 - Limb::WIDTH in fill_bitpattern // - offset != 182 - Limb::WIDTH in fill_bitpattern test_large(800261, 63971); // - offset > 182 - 2 * Limb::WIDTH in fill_bitpattern test_large(801797, 64088); // - offset > 182 - Limb::WIDTH in fill_bitpattern test_large(801989, 64100); // - m21 == 0 in fill_bitpattern test_large(805061, 64323); // - off < size // - offset == Limb::WIDTH in fill_bitpattern test_large(1800005, 135070); // - offset == 182 - Limb::WIDTH in fill_bitpattern test_large(1808261, 135646); // - offset == 0 second time in fill_bitpattern test_large(1808453, 135656); } #[test] fn limbs_prime_sieve_properties() { unsigned_gen_var_26().test_properties(|n: u64| { let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; let out = limbs_prime_sieve_u32(&mut sieve, n); assert!(out < n); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve = vec![0; limbs_prime_sieve_size::(n)]; let out = limbs_prime_sieve_u64(&mut sieve, n); assert!(out < n); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_1::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); let mut sieve_alt = vec![0; limbs_prime_sieve_size::(n)]; assert_eq!(limbs_prime_sieve_naive_2::(&mut sieve_alt, n), out); assert_eq!(sieve, sieve_alt); }); } ================================================ FILE: malachite-base/tests/num/factorization/primes.rs ================================================ // Copyright © 2026 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::comparison::is_strictly_ascending; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::factorization::traits::{IsPrime, Primes}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_pair_gen_var_28, unsigned_triple_gen_var_24, }; use malachite_base::test_util::num::factorization::primes::primes_naive; fn test_primes_less_than_helper() { let test = |n: u8, out: &[u8]| { let n = T::from(n); let out = out.iter().map(|&x| T::from(x)).collect_vec(); assert_eq!(T::primes_less_than(&n).collect_vec(), out); assert_eq!(T::primes().take_while(|&p| p < n).collect_vec(), out); assert_eq!( primes_naive::().take_while(|&p| p < n).collect_vec(), out ); }; test(0, &[]); test(1, &[]); test(2, &[]); test(3, &[2]); test(4, &[2, 3]); test(5, &[2, 3]); test(6, &[2, 3, 5]); test(7, &[2, 3, 5]); test(8, &[2, 3, 5, 7]); test(9, &[2, 3, 5, 7]); test(10, &[2, 3, 5, 7]); test( 100, &[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, ], ); } #[test] fn test_primes_less_than() { apply_fn_to_unsigneds!(test_primes_less_than_helper); } fn test_primes_less_than_or_equal_to_helper() { let test = |n: u8, out: &[u8]| { let n = T::from(n); let out = out.iter().map(|&x| T::from(x)).collect_vec(); assert_eq!(T::primes_less_than_or_equal_to(&n).collect_vec(), out); assert_eq!(T::primes().take_while(|&p| p <= n).collect_vec(), out); assert_eq!( primes_naive::().take_while(|&p| p <= n).collect_vec(), out ); }; test(0, &[]); test(1, &[]); test(2, &[2]); test(3, &[2, 3]); test(4, &[2, 3]); test(5, &[2, 3, 5]); test(6, &[2, 3, 5]); test(7, &[2, 3, 5, 7]); test(8, &[2, 3, 5, 7]); test(9, &[2, 3, 5, 7]); test(10, &[2, 3, 5, 7]); test( 100, &[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, ], ); } #[test] fn test_primes_less_than_or_equal_to() { apply_fn_to_unsigneds!(test_primes_less_than_or_equal_to_helper); } #[test] fn test_primes() { let expected = &[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, ]; for p in expected { assert!(p.is_prime()); } assert_eq!(u16::primes().take(1000).collect_vec(), expected); assert_eq!(primes_naive::().take(1000).collect_vec(), expected); assert_eq!(u8::primes().count(), 54); assert_eq!(u16::primes().count(), 6542); const U32_PRIME_COUNT: usize = 203280221; assert_eq!(u32::primes().count(), U32_PRIME_COUNT); assert_eq!( u32::primes_less_than_or_equal_to(&u32::MAX).count(), U32_PRIME_COUNT ); assert_eq!( u64::primes_less_than_or_equal_to(&u64::wrapping_from(u32::MAX)).count(), U32_PRIME_COUNT ); } fn primes_less_than_properties_helper() { unsigned_gen_var_5::().test_properties(|n| { let ps = T::primes_less_than(&n).collect_vec(); for p in &ps { let p: u64 = p.wrapping_into(); assert!(p.is_prime()); } assert!(is_strictly_ascending(ps.iter())); assert_eq!( T::primes_less_than_or_equal_to(&n.saturating_sub(T::ONE)).collect_vec(), ps ); assert_eq!(T::primes().take_while(|&p| p < n).collect_vec(), ps); assert_eq!(primes_naive::().take_while(|&p| p < n).collect_vec(), ps); }); } #[test] fn primes_less_than_properties() { apply_fn_to_unsigneds!(primes_less_than_properties_helper); } fn primes_less_than_or_equal_to_properties_helper() { unsigned_gen_var_5::().test_properties(|n| { let ps = T::primes_less_than_or_equal_to(&n).collect_vec(); for p in &ps { let p: u64 = p.wrapping_into(); assert!(p.is_prime()); } assert!(is_strictly_ascending(ps.iter())); assert_eq!( T::primes_less_than(&n.saturating_add(T::ONE)).collect_vec(), ps ); assert_eq!(T::primes().take_while(|&p| p <= n).collect_vec(), ps); assert_eq!( primes_naive::().take_while(|&p| p <= n).collect_vec(), ps ); }); } #[test] fn primes_less_than_or_equal_to_properties() { apply_fn_to_unsigneds!(primes_less_than_or_equal_to_properties_helper); } // TODO replace with real version once available fn next_prime_after(mut n: T) -> T { loop { n += T::ONE; if n.is_prime() { return n; } } } fn primes_less_than_jump_after_properties_helper() { let mut config = GenConfig::new(); config.insert("mean_small_n", 10000); unsigned_triple_gen_var_24::().test_properties_with_config( &config, |(size, jump, skip)| { let mut ps = T::primes_less_than(&size); for _ in 0..skip { ps.next(); } if ps.jump_after(jump) { let p = ps.next().unwrap(); assert!(p.is_prime()); assert_eq!(p, next_prime_after(jump)); } else { assert!(ps.next().is_none()); } }, ); } #[test] fn primes_less_than_jump_after_properties() { primes_less_than_jump_after_properties_helper::(); primes_less_than_jump_after_properties_helper::(); primes_less_than_jump_after_properties_helper::(); primes_less_than_jump_after_properties_helper::(); primes_less_than_jump_after_properties_helper::(); } fn primes_jump_after_properties_helper() { let mut config = GenConfig::new(); config.insert("mean_small_n", 10000); unsigned_pair_gen_var_28::().test_properties_with_config(&config, |(jump, skip)| { let mut ps = T::primes(); for _ in 0..skip { ps.next(); } if ps.jump_after(jump) { let p = ps.next().unwrap(); assert!(p.is_prime()); assert_eq!(p, next_prime_after(jump)); } else { assert!(ps.next().is_none()); } }); } #[test] fn primes_jump_after_properties() { let mut primes = u16::primes(); assert_eq!(primes.jump_after(u16::MAX), false); primes_jump_after_properties_helper::(); primes_jump_after_properties_helper::(); primes_jump_after_properties_helper::(); primes_jump_after_properties_helper::(); primes_jump_after_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/factorization/primitive_root_prime.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::factorization::traits::{IsPrime, PrimitiveRootPrime}; use malachite_base::test_util::generators::unsigned_gen_var_29; use std::fmt::Debug; use std::panic::catch_unwind; fn primitive_root_prime_helper + PrimitiveUnsigned>() { let test = |n: u64, out| { if let (Ok(n), Ok(out)) = (T::try_from(n), T::try_from(out)) { assert_eq!(n.primitive_root_prime(), out); } }; test(2, 1); test(3, 2); test(5, 2); test(7, 3); test(11, 2); test(191, 19); test(9223372036854775807, 2); test(8760810010780182161, 3); } #[test] fn test_primitive_root_prime() { primitive_root_prime_helper::(); primitive_root_prime_helper::(); primitive_root_prime_helper::(); primitive_root_prime_helper::(); primitive_root_prime_helper::(); } fn primitive_root_prime_fail_helper() { assert_panic!(T::ZERO.primitive_root_prime()); } #[test] pub fn primitive_root_prime_fail() { primitive_root_prime_fail_helper::(); primitive_root_prime_fail_helper::(); primitive_root_prime_fail_helper::(); primitive_root_prime_fail_helper::(); primitive_root_prime_fail_helper::(); } fn primitive_root_prime_properties_helper() where ::Output: Copy + Debug + PartialOrd, { unsigned_gen_var_29::().test_properties(|n| { let primitive_root = n.primitive_root_prime(); assert_ne!(primitive_root, T::ZERO); if n > T::TWO { assert_ne!(primitive_root, T::ONE); } assert!(primitive_root < n); }); } #[test] fn primitive_root_prime_properties() { primitive_root_prime_properties_helper::(); primitive_root_prime_properties_helper::(); primitive_root_prime_properties_helper::(); primitive_root_prime_properties_helper::(); primitive_root_prime_properties_helper::(); } ================================================ FILE: malachite-base/tests/num/float/basic/abs_negative_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; fn abs_negative_zero_helper() { let test = |n: T, out| { let out = NiceFloat(out); assert_eq!(NiceFloat(n.abs_negative_zero()), out); let mut n = n; n.abs_negative_zero_assign(); assert_eq!(NiceFloat(n), out); }; test(T::ZERO, T::ZERO); test(T::NEGATIVE_ZERO, T::ZERO); test(T::NAN, T::NAN); test(T::INFINITY, T::INFINITY); test(T::NEGATIVE_INFINITY, T::NEGATIVE_INFINITY); test(T::ONE, T::ONE); test(T::NEGATIVE_ONE, T::NEGATIVE_ONE); test(T::from(1.234), T::from(1.234)); test(T::from(-1.234), T::from(-1.234)); } #[test] fn test_abs_negative_zero() { apply_fn_to_primitive_floats!(abs_negative_zero_helper); } fn abs_negative_zero_properties_helper() { primitive_float_gen::().test_properties(|x| { let y = x.abs_negative_zero(); let x = NiceFloat(x); let y = NiceFloat(y); assert!(x == y || x == NiceFloat(T::NEGATIVE_ZERO) && y == NiceFloat(T::ZERO)); assert_eq!(NiceFloat(y.0.abs_negative_zero()), y); let mut x = x.0; x.abs_negative_zero_assign(); assert_eq!(NiceFloat(x), y); }); } #[test] fn abs_negative_zero_properties() { apply_fn_to_primitive_floats!(abs_negative_zero_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/from_ordered_representation.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{unsigned_gen_var_13, unsigned_pair_gen_var_22}; use std::panic::catch_unwind; #[allow(clippy::approx_constant)] #[test] pub fn test_from_ordered_representation() { fn test(n: u64, out: T) { assert_eq!(NiceFloat(T::from_ordered_representation(n)), NiceFloat(out)); } test::(0, f32::NEGATIVE_INFINITY); test::(1, -f32::MAX_FINITE); test::(1000000000, -458.42188); test::(1046478848, -10.0); test::(1060565029, -core::f32::consts::PI); test::(1073741824, -1.0); test::(1102263091, -0.1); test::(2130706432, -f32::MIN_POSITIVE_NORMAL); test::(2130706433, -f32::MAX_SUBNORMAL); test::(2139095039, -f32::MIN_POSITIVE_SUBNORMAL); test::(2139095040, -0.0); test::(2139095041, 0.0); test::(2139095042, f32::MIN_POSITIVE_SUBNORMAL); test::(2147483648, f32::MAX_SUBNORMAL); test::(2147483649, f32::MIN_POSITIVE_NORMAL); test::(3175926990, 0.1); test::(3204448256, 0.99999994); test::(3204448257, 1.0); test::(3204448258, 1.0000001); test::(3217625051, 3.1415925); test::(3217625052, core::f32::consts::PI); test::(3217625053, 3.141593); test::(3231711233, 10.0); test::(4278190080, f32::MAX_FINITE); test::(4278190081, f32::INFINITY); test::(0, f64::NEGATIVE_INFINITY); test::(1, -f64::MAX_FINITE); test::(4597049319638433792, -10.0); test::(4604611780675359464, -core::f64::consts::PI); test::(4611686018427387904, -1.0); test::(4626998257160447590, -0.1); test::(9214364837600034816, -f64::MIN_POSITIVE_NORMAL); test::(9214364837600034817, -f64::MAX_SUBNORMAL); test::(9218868437227405311, -f64::MIN_POSITIVE_SUBNORMAL); test::(9218868437227405312, -0.0); test::(9218868437227405313, 0.0); test::(9218868437227405314, f64::MIN_POSITIVE_SUBNORMAL); test::(9223372036854775808, f64::MAX_SUBNORMAL); test::(9223372036854775809, f64::MIN_POSITIVE_NORMAL); test::(10000000000000000000, 1.9261352099337372e-256); test::(13810738617294363035, 0.1); test::(13826050856027422720, 0.9999999999999999); test::(13826050856027422721, 1.0); test::(13826050856027422722, 1.0000000000000002); test::(13833125093779451160, 3.1415926535897927); test::(13833125093779451161, core::f64::consts::PI); test::(13833125093779451162, 3.1415926535897936); test::(13840687554816376833, 10.0); test::(18437736874454810624, f64::MAX_FINITE); test::(18437736874454810625, f64::INFINITY); } #[test] pub fn from_ordered_representation_fail() { assert_panic!(f32::from_ordered_representation(4278190082)); assert_panic!(f32::from_ordered_representation(u64::MAX)); assert_panic!(f64::from_ordered_representation(18437736874454810626)); assert_panic!(f64::from_ordered_representation(u64::MAX)); } fn from_ordered_representation_properties_helper() { unsigned_gen_var_13::().test_properties(|x| { let f = T::from_ordered_representation(x); assert!(!f.is_nan()); assert_eq!(f.to_ordered_representation(), x); }); unsigned_pair_gen_var_22::().test_properties(|(x, y)| { assert_eq!( x.cmp(&y), NiceFloat(T::from_ordered_representation(x)) .cmp(&NiceFloat(T::from_ordered_representation(y))) ); }); } #[test] fn from_ordered_representation_properties() { apply_fn_to_primitive_floats!(from_ordered_representation_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/is_negative_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; fn is_negative_zero_helper() { let test = |n: T, out| { assert_eq!(n.is_negative_zero(), out); }; test(T::ZERO, false); test(T::NEGATIVE_ZERO, true); test(T::NAN, false); test(T::INFINITY, false); test(T::NEGATIVE_INFINITY, false); test(T::ONE, false); test(T::NEGATIVE_ONE, false); test(T::from(1.234), false); test(T::from(-1.234), false); } #[test] fn test_is_negative_zero() { apply_fn_to_primitive_floats!(is_negative_zero_helper); } fn is_negative_zero_properties_helper() { primitive_float_gen::().test_properties(|x| { assert_eq!( x.is_negative_zero(), NiceFloat(x) != NiceFloat(x.abs_negative_zero()) ); }); } #[test] fn is_negative_zero_properties() { apply_fn_to_primitive_floats!(is_negative_zero_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/max_precision_for_sci_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::signed_gen_var_11; use std::panic::catch_unwind; #[test] fn max_precision_for_sci_exponent() { fn test(n: i64, out: u64) { assert_eq!(T::max_precision_for_sci_exponent(n), out); } test::(0, 24); test::(127, 24); test::(-149, 1); test::(-148, 2); test::(-147, 3); test::(0, 53); test::(1023, 53); test::(-1074, 1); test::(-1073, 2); test::(-1072, 3); } fn max_precision_for_sci_exponent_fail_helper() { assert_panic!(T::max_precision_for_sci_exponent(10000)); assert_panic!(T::max_precision_for_sci_exponent(-10000)); } #[test] pub fn max_precision_for_sci_exponent_fail() { apply_fn_to_primitive_floats!(max_precision_for_sci_exponent_fail_helper); } fn max_precision_for_sci_exponent_properties_helper() { signed_gen_var_11::().test_properties(|exp| { let p = T::max_precision_for_sci_exponent(exp); assert_ne!(p, 0); assert!(p <= u64::exact_from(T::MAX_EXPONENT)); }); } #[test] fn max_precision_for_sci_exponent_properties() { apply_fn_to_primitive_floats!(max_precision_for_sci_exponent_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/next_higher.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen_var_9; use std::panic::catch_unwind; #[allow(clippy::approx_constant)] #[test] pub fn test_next_higher() { fn test(x: T, out: T) { assert_eq!(NiceFloat(x.next_higher()), NiceFloat(out)); } test::(f32::NEGATIVE_INFINITY, -f32::MAX_FINITE); test::(-f32::MAX_FINITE, -3.4028233e38); test::(-458.42188, -458.42184); test::(-10.0, -9.999999); test::(-core::f32::consts::PI, -3.1415925); test::(-1.0, -0.99999994); test::(-0.1, -0.099999994); test::(-f32::MIN_POSITIVE_NORMAL, -f32::MAX_SUBNORMAL); test::(-f32::MAX_SUBNORMAL, -1.1754941e-38); test::(-f32::MIN_POSITIVE_SUBNORMAL, -0.0); test::(-0.0, 0.0); test::(0.0, f32::MIN_POSITIVE_SUBNORMAL); test::(f32::MIN_POSITIVE_SUBNORMAL, 3.0e-45); test::(f32::MAX_SUBNORMAL, f32::MIN_POSITIVE_NORMAL); test::(f32::MIN_POSITIVE_NORMAL, 1.1754945e-38); test::(0.1, 0.10000001); test::(0.99999994, 1.0); test::(1.0, 1.0000001); test::(1.0000001, 1.0000002); test::(3.1415925, core::f32::consts::PI); test::(core::f32::consts::PI, 3.141593); test::(3.141593, 3.1415932); test::(10.0, 10.000001); test::(f32::MAX_FINITE, f32::INFINITY); test::(f64::NEGATIVE_INFINITY, -f64::MAX_FINITE); test::(-f64::MAX_FINITE, -1.7976931348623155e308); test::(-10.0, -9.999999999999998); test::(-core::f64::consts::PI, -3.1415926535897927); test::(-1.0, -0.9999999999999999); test::(-0.1, -0.09999999999999999); test::(-f64::MIN_POSITIVE_NORMAL, -f64::MAX_SUBNORMAL); test::(-f64::MAX_SUBNORMAL, -2.2250738585072004e-308); test::(-f64::MIN_POSITIVE_SUBNORMAL, -0.0); test::(-0.0, 0.0); test::(0.0, f64::MIN_POSITIVE_SUBNORMAL); test::(f64::MIN_POSITIVE_SUBNORMAL, 1.0e-323); test::(f64::MAX_SUBNORMAL, f64::MIN_POSITIVE_NORMAL); test::(f64::MIN_POSITIVE_NORMAL, 2.225073858507202e-308); test::(1.9261352099337372e-256, 1.9261352099337375e-256); test::(0.1, 0.10000000000000002); test::(0.9999999999999999, 1.0); test::(1.0, 1.0000000000000002); test::(1.0000000000000002, 1.0000000000000004); test::(3.1415926535897927, core::f64::consts::PI); test::(core::f64::consts::PI, 3.1415926535897936); test::(3.1415926535897936, 3.141592653589794); test::(10.0, 10.000000000000002); test::(f64::MAX_FINITE, f64::INFINITY); } fn next_higher_fail_helper() { assert_panic!(T::NAN.next_higher()); assert_panic!(T::INFINITY.next_higher()); } #[test] pub fn next_higher_fail() { apply_fn_to_primitive_floats!(next_higher_fail_helper); } fn next_higher_properties_helper() { primitive_float_gen_var_9::().test_properties(|x| { let y = x.next_higher(); assert_eq!( x.to_ordered_representation() + 1, y.to_ordered_representation() ); assert_eq!(NiceFloat(y.next_lower()), NiceFloat(x)); }); } #[test] fn next_higher_properties() { apply_fn_to_primitive_floats!(next_higher_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/next_lower.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen_var_10; use std::panic::catch_unwind; #[allow(clippy::approx_constant)] #[test] pub fn test_next_lower() { fn test(x: T, out: T) { assert_eq!(NiceFloat(x.next_lower()), NiceFloat(out)); } test::(-f32::MAX_FINITE, f32::NEGATIVE_INFINITY); test::(-458.42188, -458.4219); test::(-10.0, -10.000001); test::(-core::f32::consts::PI, -3.141593); test::(-1.0, -1.0000001); test::(-0.1, -0.10000001); test::(-f32::MIN_POSITIVE_NORMAL, -1.1754945e-38); test::(-f32::MAX_SUBNORMAL, -f32::MIN_POSITIVE_NORMAL); test::(-f32::MIN_POSITIVE_SUBNORMAL, -3.0e-45); test::(-0.0, -f32::MIN_POSITIVE_SUBNORMAL); test::(0.0, -0.0); test::(f32::MIN_POSITIVE_SUBNORMAL, 0.0); test::(f32::MAX_SUBNORMAL, 1.1754941e-38); test::(f32::MIN_POSITIVE_NORMAL, f32::MAX_SUBNORMAL); test::(0.1, 0.099999994); test::(0.99999994, 0.9999999); test::(1.0, 0.99999994); test::(1.0000001, 1.0); test::(3.1415925, 3.1415923); test::(core::f32::consts::PI, 3.1415925); test::(3.141593, core::f32::consts::PI); test::(10.0, 9.999999); test::(f32::MAX_FINITE, 3.4028233e38); test::(f32::INFINITY, f32::MAX_FINITE); test::(-f64::MAX_FINITE, f64::NEGATIVE_INFINITY); test::(-10.0, -10.000000000000002); test::(-core::f64::consts::PI, -3.1415926535897936); test::(-1.0, -1.0000000000000002); test::(-0.1, -0.10000000000000002); test::(-f64::MIN_POSITIVE_NORMAL, -2.225073858507202e-308); test::(-f64::MAX_SUBNORMAL, -f64::MIN_POSITIVE_NORMAL); test::(-f64::MIN_POSITIVE_SUBNORMAL, -1.0e-323); test::(-0.0, -f64::MIN_POSITIVE_SUBNORMAL); test::(0.0, -0.0); test::(f64::MIN_POSITIVE_SUBNORMAL, 0.0); test::(f64::MAX_SUBNORMAL, 2.2250738585072004e-308); test::(f64::MIN_POSITIVE_NORMAL, f64::MAX_SUBNORMAL); test::(1.9261352099337372e-256, 1.926135209933737e-256); test::(0.1, 0.09999999999999999); test::(0.9999999999999999, 0.9999999999999998); test::(1.0, 0.9999999999999999); test::(1.0000000000000002, 1.0); test::(3.1415926535897927, 3.1415926535897922); test::(core::f64::consts::PI, 3.1415926535897927); test::(3.1415926535897936, core::f64::consts::PI); test::(10.0, 9.999999999999998); test::(f64::MAX_FINITE, 1.7976931348623155e308); test::(f64::INFINITY, f64::MAX_FINITE); } fn next_lower_fail_helper() { assert_panic!(T::NAN.next_lower()); assert_panic!(T::NEGATIVE_INFINITY.next_lower()); } #[test] pub fn next_lower_fail() { apply_fn_to_primitive_floats!(next_lower_fail_helper); } fn next_lower_properties_helper() { primitive_float_gen_var_10::().test_properties(|x| { let y = x.next_lower(); assert_eq!( x.to_ordered_representation() - 1, y.to_ordered_representation() ); assert_eq!(NiceFloat(y.next_higher()), NiceFloat(x)); }); } #[test] fn next_lower_properties() { apply_fn_to_primitive_floats!(next_lower_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/precision.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::test_util::generators::primitive_float_gen_var_12; use std::panic::catch_unwind; fn precision_helper() { let test = |n: T, out| { assert_eq!(n.precision(), out); }; test(T::ONE, 1); test(T::NEGATIVE_ONE, 1); test(T::from(3.0), 2); test(T::from(1.5), 2); test(T::from(1.234), 23); test(T::from(-1.234), 23); } #[test] fn test_precision() { apply_fn_to_primitive_floats!(precision_helper); } fn precision_fail_helper() { assert_panic!(T::NAN.precision()); assert_panic!(T::INFINITY.precision()); assert_panic!(T::NEGATIVE_INFINITY.precision()); assert_panic!(T::ZERO.precision()); assert_panic!(T::NEGATIVE_ZERO.precision()); } #[test] pub fn precision_fail() { apply_fn_to_primitive_floats!(precision_fail_helper); } fn precision_properties_helper() { primitive_float_gen_var_12::().test_properties(|x| { let precision = x.precision(); assert_ne!(precision, 0); assert!(precision <= T::max_precision_for_sci_exponent(x.sci_exponent())); assert_eq!((-x).precision(), precision); }); } #[test] fn precision_properties() { apply_fn_to_primitive_floats!(precision_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/basic/to_ordered_representation.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_gen_var_11, primitive_float_pair_gen_var_1, }; use std::panic::catch_unwind; #[allow(clippy::approx_constant)] #[test] pub fn test_to_ordered_representation() { fn test(x: T, out: u64) { assert_eq!(x.to_ordered_representation(), out); } test::(f32::NEGATIVE_INFINITY, 0); test::(-f32::MAX_FINITE, 1); test::(-458.42188, 1000000000); test::(-10.0, 1046478848); test::(-core::f32::consts::PI, 1060565029); test::(-1.0, 1073741824); test::(-0.1, 1102263091); test::(-f32::MIN_POSITIVE_NORMAL, 2130706432); test::(-f32::MAX_SUBNORMAL, 2130706433); test::(-f32::MIN_POSITIVE_SUBNORMAL, 2139095039); test::(-0.0, 2139095040); test::(0.0, 2139095041); test::(f32::MIN_POSITIVE_SUBNORMAL, 2139095042); test::(f32::MAX_SUBNORMAL, 2147483648); test::(f32::MIN_POSITIVE_NORMAL, 2147483649); test::(0.1, 3175926990); test::(0.99999994, 3204448256); test::(1.0, 3204448257); test::(1.0000001, 3204448258); test::(3.1415925, 3217625051); test::(core::f32::consts::PI, 3217625052); test::(3.141593, 3217625053); test::(10.0, 3231711233); test::(f32::MAX_FINITE, 4278190080); test::(f32::INFINITY, 4278190081); test::(f64::NEGATIVE_INFINITY, 0); test::(-f64::MAX_FINITE, 1); test::(-10.0, 4597049319638433792); test::(-core::f64::consts::PI, 4604611780675359464); test::(-1.0, 4611686018427387904); test::(-0.1, 4626998257160447590); test::(-f64::MIN_POSITIVE_NORMAL, 9214364837600034816); test::(-f64::MAX_SUBNORMAL, 9214364837600034817); test::(-f64::MIN_POSITIVE_SUBNORMAL, 9218868437227405311); test::(-0.0, 9218868437227405312); test::(0.0, 9218868437227405313); test::(f64::MIN_POSITIVE_SUBNORMAL, 9218868437227405314); test::(f64::MAX_SUBNORMAL, 9223372036854775808); test::(f64::MIN_POSITIVE_NORMAL, 9223372036854775809); test::(1.9261352099337372e-256, 10000000000000000000); test::(0.1, 13810738617294363035); test::(0.9999999999999999, 13826050856027422720); test::(1.0, 13826050856027422721); test::(1.0000000000000002, 13826050856027422722); test::(3.1415926535897927, 13833125093779451160); test::(core::f64::consts::PI, 13833125093779451161); test::(3.1415926535897936, 13833125093779451162); test::(10.0, 13840687554816376833); test::(f64::MAX_FINITE, 18437736874454810624); test::(f64::INFINITY, 18437736874454810625); } fn to_ordered_representation_fail_helper() { assert_panic!(T::NAN.to_ordered_representation()); } #[test] pub fn to_ordered_representation_fail() { apply_fn_to_primitive_floats!(to_ordered_representation_fail_helper); } fn to_ordered_representation_properties_helper() { primitive_float_gen_var_11::().test_properties(|x| { let i = x.to_ordered_representation(); assert!(i <= T::LARGEST_ORDERED_REPRESENTATION); assert_eq!(NiceFloat(T::from_ordered_representation(i)), NiceFloat(x)); }); primitive_float_pair_gen_var_1::().test_properties(|(x, y)| { assert_eq!( NiceFloat(x).cmp(&NiceFloat(y)), x.to_ordered_representation() .cmp(&y.to_ordered_representation()) ); }); } #[test] fn to_ordered_representation_properties() { apply_fn_to_primitive_floats!(to_ordered_representation_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::common::test_cmp_helper; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_pair_gen, primitive_float_triple_gen, }; use std::cmp::Ordering::*; const TEST_STRINGS: [&str; 7] = ["-Infinity", "-5.0e5", "-0.0", "NaN", "0.0", "0.123", "Infinity"]; #[test] pub fn test_cmp() { test_cmp_helper::>(&TEST_STRINGS); test_cmp_helper::>(&TEST_STRINGS); } fn cmp_properties_helper() { primitive_float_pair_gen::().test_properties(|(x, y)| { let x = NiceFloat(x); let y = NiceFloat(y); let ord = x.cmp(&y); assert_eq!(y.cmp(&x).reverse(), ord); assert_eq!(NiceFloat(-y.0).cmp(&NiceFloat(-x.0)), ord); }); primitive_float_gen::().test_properties(|x| { let x = NiceFloat(x); assert_eq!(x.cmp(&x), Equal); }); primitive_float_triple_gen::().test_properties(|(x, y, z)| { let x = NiceFloat(x); let y = NiceFloat(y); let z = NiceFloat(z); if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); } #[test] pub fn cmp_properties() { apply_fn_to_primitive_floats!(cmp_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_pair_gen, primitive_float_triple_gen, }; use std::cmp::Ordering::*; #[test] pub fn test_cmp_abs() { let test = |s, t, cmp| { let u = NiceFloat(s); let v = NiceFloat(t); assert_eq!(u.cmp_abs(&v), cmp); assert_eq!(v.cmp_abs(&u), cmp.reverse()); assert_eq!(u.lt_abs(&v), cmp == Less); assert_eq!(u.gt_abs(&v), cmp == Greater); assert_eq!(u.le_abs(&v), cmp != Greater); assert_eq!(u.ge_abs(&v), cmp != Less); }; test(0.0, 0.0, Equal); test(0.0, f64::NAN, Greater); test(0.0, f64::INFINITY, Less); test(0.0, 5.0, Less); test(123.0, 123.0, Equal); test(123.0, 124.0, Less); test(123.0, 122.0, Greater); test(1000000000000.0, 123.0, Greater); test(123.0, 1000000000000.0, Less); test(1000000000000.0, 1000000000000.0, Equal); test(1000000000000.0, 0.0, Greater); test(0.5, 0.0, Greater); test(0.5, 0.5, Equal); test(0.0, -0.0, Equal); test(0.0, f64::NEGATIVE_INFINITY, Less); test(0.0, -5.0, Less); test(123.0, -123.0, Equal); test(123.0, -124.0, Less); test(123.0, -122.0, Greater); test(1000000000000.0, -123.0, Greater); test(123.0, -1000000000000.0, Less); test(1000000000000.0, -1000000000000.0, Equal); test(1000000000000.0, -0.0, Greater); test(0.5, -0.0, Greater); test(0.5, -0.5, Equal); test(-0.0, 0.0, Equal); test(-0.0, f64::NAN, Greater); test(-0.0, f64::INFINITY, Less); test(-0.0, 5.0, Less); test(-123.0, 123.0, Equal); test(-123.0, 124.0, Less); test(-123.0, 122.0, Greater); test(-1000000000000.0, 123.0, Greater); test(-123.0, 1000000000000.0, Less); test(-1000000000000.0, 1000000000000.0, Equal); test(-1000000000000.0, 0.0, Greater); test(-0.5, 0.0, Greater); test(-0.5, 0.5, Equal); test(-0.0, -0.0, Equal); test(-0.0, f64::NEGATIVE_INFINITY, Less); test(-0.0, -5.0, Less); test(-123.0, -123.0, Equal); test(-123.0, -124.0, Less); test(-123.0, -122.0, Greater); test(-1000000000000.0, -123.0, Greater); test(-123.0, -1000000000000.0, Less); test(-1000000000000.0, -1000000000000.0, Equal); test(-1000000000000.0, -0.0, Greater); test(-0.5, -0.0, Greater); test(-0.5, -0.5, Equal); } fn cmp_abs_properties_helper() { primitive_float_pair_gen::().test_properties(|(x, y)| { let x = NiceFloat(x); let y = NiceFloat(y); let cmp = x.cmp_abs(&y); assert_eq!(y.cmp_abs(&x).reverse(), cmp); assert_eq!(NiceFloat(-x.0).cmp_abs(&NiceFloat(-y.0)), cmp); assert_eq!(x.lt_abs(&y), cmp == Less); assert_eq!(x.gt_abs(&y), cmp == Greater); assert_eq!(x.le_abs(&y), cmp != Greater); assert_eq!(x.ge_abs(&y), cmp != Less); }); primitive_float_gen::().test_properties(|x| { let x = NiceFloat(x); assert_eq!(x.cmp_abs(&x), Equal); }); primitive_float_triple_gen::().test_properties(|(x, y, z)| { let x = NiceFloat(x); let y = NiceFloat(y); let z = NiceFloat(z); if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); } #[test] pub fn cmp_abs_properties() { apply_fn_to_primitive_floats!(cmp_abs_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/eq.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::common::test_eq_helper; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_pair_gen, primitive_float_triple_gen, }; const TEST_STRINGS: [&str; 7] = ["-Infinity", "-5.0e5", "-0.0", "NaN", "0.0", "0.123", "Infinity"]; #[test] pub fn test_eq() { test_eq_helper::>(&TEST_STRINGS); test_eq_helper::>(&TEST_STRINGS); } #[allow(clippy::eq_op)] fn eq_properties_helper() { primitive_float_pair_gen::().test_properties(|(x, y)| { let x = NiceFloat(x); let y = NiceFloat(y); assert_eq!(x == y, y == x); }); primitive_float_gen::().test_properties(|x| { let x = NiceFloat(x); assert_eq!(x, x); }); primitive_float_triple_gen::().test_properties(|(x, y, z)| { let x = NiceFloat(x); let y = NiceFloat(y); let z = NiceFloat(z); if x == y && x == z { assert_eq!(x, z); } }); } #[test] pub fn eq_properties() { apply_fn_to_primitive_floats!(eq_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_pair_gen, primitive_float_triple_gen, }; #[test] fn test_eq_abs() { let test = |s, t, eq| { let u = NiceFloat(s); let v = NiceFloat(t); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test(0.0, 0.0, true); test(0.0, f64::NAN, false); test(0.0, f64::NEGATIVE_INFINITY, false); test(0.0, 5.0, false); test(123.0, 123.0, true); test(123.0, 124.0, false); test(123.0, 122.0, false); test(1000000000000.0, 123.0, false); test(123.0, 1000000000000.0, false); test(1000000000000.0, 1000000000000.0, true); test(1000000000000.0, 0.0, false); test(0.5, 0.0, false); test(0.5, 0.5, true); test(0.0, -0.0, true); test(0.0, -f64::NAN, false); test(0.0, -f64::NEGATIVE_INFINITY, false); test(0.0, -5.0, false); test(123.0, -123.0, true); test(123.0, -124.0, false); test(123.0, -122.0, false); test(1000000000000.0, -123.0, false); test(123.0, -1000000000000.0, false); test(1000000000000.0, -1000000000000.0, true); test(1000000000000.0, -0.0, false); test(0.5, -0.0, false); test(0.5, -0.5, true); test(-0.0, 0.0, true); test(-0.0, f64::NAN, false); test(-0.0, f64::NEGATIVE_INFINITY, false); test(-0.0, 5.0, false); test(-123.0, 123.0, true); test(-123.0, 124.0, false); test(-123.0, 122.0, false); test(-1000000000000.0, 123.0, false); test(-123.0, 1000000000000.0, false); test(-1000000000000.0, 1000000000000.0, true); test(-1000000000000.0, 0.0, false); test(-0.5, 0.0, false); test(-0.5, 0.5, true); test(-0.0, -0.0, true); test(-0.0, -f64::NAN, false); test(-0.0, -f64::NEGATIVE_INFINITY, false); test(-0.0, -5.0, false); test(-123.0, -123.0, true); test(-123.0, -124.0, false); test(-123.0, -122.0, false); test(-1000000000000.0, -123.0, false); test(-123.0, -1000000000000.0, false); test(-1000000000000.0, -1000000000000.0, true); test(-1000000000000.0, -0.0, false); test(-0.5, -0.0, false); test(-0.5, -0.5, true); } #[allow(clippy::eq_op)] fn eq_abs_properties_helper() { primitive_float_pair_gen::().test_properties(|(x, y)| { let x = NiceFloat(x); let y = NiceFloat(y); let eq = x.eq_abs(&y); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(NiceFloat(x.0.abs()) == NiceFloat(y.0.abs()), eq); }); primitive_float_gen::().test_properties(|x| { let x = NiceFloat(x); assert!(x.eq_abs(&x)); }); primitive_float_triple_gen::().test_properties(|(x, y, z)| { let x = NiceFloat(x); let y = NiceFloat(y); let z = NiceFloat(z); if x.eq_abs(&y) && x.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); } #[test] pub fn eq_properties() { apply_fn_to_primitive_floats!(eq_abs_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/from_str.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{string_gen, string_gen_var_10}; use std::fmt::Debug; use std::str::FromStr; #[allow(clippy::approx_constant)] #[test] fn test_from_str() { fn test_ok(s: &str, out: NiceFloat) where ::Err: Debug, { assert_eq!(NiceFloat::::from_str(s).unwrap(), out); } test_ok::("NaN", NiceFloat(f32::NAN)); test_ok::("Infinity", NiceFloat(f32::INFINITY)); test_ok::("-Infinity", NiceFloat(f32::NEGATIVE_INFINITY)); test_ok::("0", NiceFloat(0.0)); test_ok::("00", NiceFloat(0.0)); test_ok::("0.", NiceFloat(0.0)); test_ok::(".0", NiceFloat(0.0)); test_ok::("1", NiceFloat(1.0)); test_ok::("1.0", NiceFloat(1.0)); test_ok::("1.0000", NiceFloat(1.0)); test_ok::("3.14", NiceFloat(3.14)); test_ok::("1e2", NiceFloat(100.0)); test_ok::("1e20", NiceFloat(1.0e20)); test_ok::("1.0e1000", NiceFloat(f32::INFINITY)); test_ok::("1.0e-1000", NiceFloat(0.0)); test_ok::("-0", NiceFloat(-0.0)); test_ok::("-00", NiceFloat(-0.0)); test_ok::("-0.", NiceFloat(-0.0)); test_ok::("-.0", NiceFloat(-0.0)); test_ok::("-1", NiceFloat(-1.0)); test_ok::("-1.0", NiceFloat(-1.0)); test_ok::("-1.0000", NiceFloat(-1.0)); test_ok::("-3.14", NiceFloat(-3.14)); test_ok::("-1e2", NiceFloat(-100.0)); test_ok::("-1e20", NiceFloat(-1.0e20)); test_ok::("-1.0e1000", NiceFloat(f32::NEGATIVE_INFINITY)); test_ok::("-1.0e-1000", NiceFloat(-0.0)); test_ok::("NaN", NiceFloat(f64::NAN)); test_ok::("Infinity", NiceFloat(f64::INFINITY)); test_ok::("-Infinity", NiceFloat(f64::NEGATIVE_INFINITY)); test_ok::("0", NiceFloat(0.0)); test_ok::("00", NiceFloat(0.0)); test_ok::("0.", NiceFloat(0.0)); test_ok::(".0", NiceFloat(0.0)); test_ok::("1", NiceFloat(1.0)); test_ok::("1.0", NiceFloat(1.0)); test_ok::("1.0000", NiceFloat(1.0)); test_ok::("3.14", NiceFloat(3.14)); test_ok::("1e2", NiceFloat(100.0)); test_ok::("1e20", NiceFloat(1.0e20)); test_ok::("1.0e1000", NiceFloat(f64::INFINITY)); test_ok::("1.0e-1000", NiceFloat(0.0)); test_ok::("-0", NiceFloat(-0.0)); test_ok::("-00", NiceFloat(-0.0)); test_ok::("-0.", NiceFloat(-0.0)); test_ok::("-.0", NiceFloat(-0.0)); test_ok::("-1", NiceFloat(-1.0)); test_ok::("-1.0", NiceFloat(-1.0)); test_ok::("-1.0000", NiceFloat(-1.0)); test_ok::("-3.14", NiceFloat(-3.14)); test_ok::("-1e2", NiceFloat(-100.0)); test_ok::("-1e20", NiceFloat(-1.0e20)); test_ok::("-1.0e1000", NiceFloat(f64::NEGATIVE_INFINITY)); test_ok::("-1.0e-1000", NiceFloat(-0.0)); let test_err = |s| { assert!(NiceFloat::::from_str(s).is_err()); assert!(NiceFloat::::from_str(s).is_err()); }; test_err("-"); test_err("."); test_err("e"); test_err("z"); test_err("0x01"); test_err(" 0 "); } #[allow(unused_must_use)] fn from_str_helper() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_length_d", 1); string_gen().test_properties_with_config(&config, |s| { NiceFloat::::from_str(&s); }); string_gen_var_10().test_properties_with_config(&config, |s| { NiceFloat::::from_str(&s); }); } #[test] fn from_str_properties() { apply_fn_to_primitive_floats!(from_str_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/hash.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::hash::hash; fn hash_properties_helper() { primitive_float_gen::().test_properties(|x| { let x = NiceFloat(x); assert_eq!(hash(&x), hash(&x.clone())); }); } #[test] fn hash_properties() { apply_fn_to_primitive_floats!(hash_properties_helper); } ================================================ FILE: malachite-base/tests/num/float/nice_float/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::num::float::PRIMITIVE_FLOAT_CHARS; use std::fmt::Debug; use std::str::FromStr; #[test] pub fn test_to_string() { fn test(x: T, out: &str) { assert_eq!(NiceFloat(x).to_string(), out); } test::(f32::NAN, "NaN"); test::(f32::INFINITY, "Infinity"); test::(f32::NEGATIVE_INFINITY, "-Infinity"); test::(0.0, "0.0"); test::(-0.0, "-0.0"); test::(1.0, "1.0"); test::(-1.0, "-1.0"); test::(123.0, "123.0"); test::(0.123, "0.123"); test::(1000.0, "1000.0"); test::(1000000.0, "1000000.0"); test::(1.0e20, "1.0e20"); test::(f32::MIN_POSITIVE_SUBNORMAL, "1.0e-45"); test::(f32::MAX_SUBNORMAL, "1.1754942e-38"); test::(f32::MIN_POSITIVE_NORMAL, "1.1754944e-38"); test::(f32::MAX_FINITE, "3.4028235e38"); test::(2.0f32.sqrt(), "1.4142135"); test::(std::f32::consts::E, "2.7182817"); test::(std::f32::consts::PI, "3.1415927"); test::(f64::NAN, "NaN"); test::(f64::INFINITY, "Infinity"); test::(f64::NEGATIVE_INFINITY, "-Infinity"); test::(0.0, "0.0"); test::(-0.0, "-0.0"); test::(1.0, "1.0"); test::(-1.0, "-1.0"); test::(123.0, "123.0"); test::(0.123, "0.123"); test::(1000.0, "1000.0"); test::(1000000.0, "1000000.0"); test::(1.0e100, "1.0e100"); test::(f64::MIN_POSITIVE_SUBNORMAL, "5.0e-324"); test::(f64::MAX_SUBNORMAL, "2.225073858507201e-308"); test::(f64::MIN_POSITIVE_NORMAL, "2.2250738585072014e-308"); test::(f64::MAX_FINITE, "1.7976931348623157e308"); test::(2.0f64.sqrt(), "1.4142135623730951"); test::(std::f64::consts::E, "2.718281828459045"); test::(std::f64::consts::PI, "3.141592653589793"); } fn to_string_properties_helper() where ::Err: Debug, { primitive_float_gen::().test_properties(|f| { let s = NiceFloat(f).to_string(); assert_eq!(NiceFloat::from_str(&s).unwrap(), NiceFloat(f)); assert!(string_is_subset(&s, PRIMITIVE_FLOAT_CHARS)); if f.is_finite() { assert!(s.contains('.')); assert_eq!(NiceFloat(T::from_str(&s).unwrap()), NiceFloat(f)); } }); } #[test] fn to_string_properties() { apply_fn_to_primitive_floats!(to_string_properties_helper); } ================================================ FILE: malachite-base/tests/num/iterators/bit_distributor_sequence.rs ================================================ // Copyright © 2026 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::BitDistributorOutputType; use malachite_base::num::iterators::bit_distributor_sequence; fn bit_distributor_sequence_helper( x_output_type: BitDistributorOutputType, y_output_type: BitDistributorOutputType, out: &[usize], ) { assert_eq!( bit_distributor_sequence(x_output_type, y_output_type) .take(50) .collect_vec(), out ); } #[test] fn test_bit_distributor_sequence() { bit_distributor_sequence_helper( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), &[ 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, ], ); bit_distributor_sequence_helper( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(2), &[ 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, ], ); bit_distributor_sequence_helper( BitDistributorOutputType::normal(2), BitDistributorOutputType::normal(1), &[ 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, 10, 11, 8, 9, 10, 11, 12, 13, 14, 15, 12, 13, 14, 15, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 9, ], ); bit_distributor_sequence_helper( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), &[ 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, ], ); bit_distributor_sequence_helper( BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), &[ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, ], ); } #[test] #[should_panic] fn test_bit_distributor_sequence_fail() { bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ); } ================================================ FILE: malachite-base/tests/num/iterators/iterator_to_bit_chunks.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::iterators::iterator_to_bit_chunks; use std::panic::{RefUnwindSafe, catch_unwind}; fn iterator_to_bit_chunks_helper>( xs: &[T], in_chunk_size: u64, out_chunk_size: u64, out: &[U], ) { assert_eq!( iterator_to_bit_chunks::<_, T, U>(xs.iter().copied(), in_chunk_size, out_chunk_size) .map(Option::unwrap) .collect_vec() .as_slice(), out ); } #[test] fn test_iterator_to_bit_chunks() { iterator_to_bit_chunks_helper::(&[123, 456], 10, 10, &[123, 456]); iterator_to_bit_chunks_helper::(&[123, 456], 10, 10, &[123, 456]); iterator_to_bit_chunks_helper::(&[123, 456], 10, 10, &[123, 456]); iterator_to_bit_chunks_helper::( &[0b000111111, 0b110010010], 9, 3, &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b000111111, 0b110010010], 9, 3, &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b000111111, 0b110010010], 9, 3, &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], 3, 9, &[0b000111111, 0b110010010], ); iterator_to_bit_chunks_helper::( &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], 3, 9, &[0b000111111, 0b110010010], ); iterator_to_bit_chunks_helper::( &[0b111, 0b111, 0b000, 0b010, 0b010, 0b110], 3, 9, &[0b000111111, 0b110010010], ); iterator_to_bit_chunks_helper::( &[0b1010101, 0b1111101, 0b0100001, 0b110010], 7, 6, &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b1010101, 0b1111101, 0b0100001, 0b110010], 7, 6, &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b1010101, 0b1111101, 0b0100001, 0b110010], 7, 6, &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], ); iterator_to_bit_chunks_helper::( &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], 6, 7, &[0b1010101, 0b1111101, 0b0100001, 0b110010], ); iterator_to_bit_chunks_helper::( &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], 6, 7, &[0b1010101, 0b1111101, 0b0100001, 0b110010], ); iterator_to_bit_chunks_helper::( &[0b010101, 0b111011, 0b000111, 0b010010, 0b110], 6, 7, &[0b1010101, 0b1111101, 0b0100001, 0b110010], ); // The output may have trailing zero chunks. iterator_to_bit_chunks_helper::(&[0b100], 32, 8, &[0b100, 0, 0, 0]); } fn test_iterator_to_bit_chunks_fail_helper< T: PrimitiveUnsigned + RefUnwindSafe, U: PrimitiveUnsigned + WrappingFrom, >() { let xs = [T::exact_from(12), T::exact_from(34)]; assert_panic!({ iterator_to_bit_chunks::<_, T, U>(xs.iter().copied(), 0, 4); }); assert_panic!({ iterator_to_bit_chunks::<_, T, U>(xs.iter().copied(), 4, 0); }); assert_panic!({ iterator_to_bit_chunks::<_, T, U>(xs.iter().copied(), T::WIDTH + 1, 4); }); assert_panic!({ iterator_to_bit_chunks::<_, T, U>(xs.iter().copied(), 4, U::WIDTH + 1); }); } #[test] fn iterator_to_bit_chunks_fail() { apply_fn_to_unsigneds_and_unsigneds!(test_iterator_to_bit_chunks_fail_helper); } ================================================ FILE: malachite-base/tests/num/iterators/ruler_sequence.rs ================================================ // Copyright © 2026 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::num::iterators::ruler_sequence; #[test] pub fn test_ruler_sequence() { assert_eq!( ruler_sequence::().take(100).collect_vec(), &[ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2 ] ); } ================================================ FILE: malachite-base/tests/num/logic/bit_access/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_bool_triple_gen_var_1, unsigned_unsigned_bool_triple_gen_var_1, }; use std::panic::catch_unwind; fn assign_bit_helper_unsigned() { let test = |n: u64, index, bit, out: u64| { let mut n = T::exact_from(n); n.assign_bit(index, bit); assert_eq!(n, T::exact_from(out)); }; test(100, 0, true, 101); test(0, 10, false, 0); test(0, 100, false, 0); test(101, 0, false, 100); if T::WIDTH >= u16::WIDTH { test(0, 10, true, 1024); test(1024, 10, false, 0); } if T::WIDTH >= u64::WIDTH { test(1000000000000, 10, true, 1000000001024); test(1000000001024, 10, false, 1000000000000); test(1000000001024, 100, false, 1000000001024); } } fn assign_bit_helper_signed() { assign_bit_helper_unsigned::(); let test = |n: i64, index, bit, out: i64| { let mut n = T::exact_from(n); n.assign_bit(index, bit); assert_eq!(n, T::exact_from(out)); }; test(-1, 5, true, -1); test(-1, 100, true, -1); test(-33, 5, true, -1); test(-32, 0, true, -31); test(-1, 5, false, -33); test(-31, 0, false, -32); if T::WIDTH >= u64::WIDTH { test(-1000000000000, 10, true, -999999998976); test(-1000000000000, 100, true, -1000000000000); test(-999999998976, 10, false, -1000000000000); } let mut n = T::ZERO; n.assign_bit(T::WIDTH - 1, true); assert_eq!(n, T::MIN); let mut n = T::MIN; n.assign_bit(T::WIDTH - 1, false); assert_eq!(n, T::ZERO); } #[test] fn test_assign_bit() { apply_fn_to_unsigneds!(assign_bit_helper_unsigned); apply_fn_to_signeds!(assign_bit_helper_signed); } fn assign_bit_fail_helper() { assert_panic!({ let mut n = T::exact_from(5); n.assign_bit(200, true); }); } fn assign_bit_fail_helper_signed() { assert_panic!({ let mut n = T::NEGATIVE_ONE; n.assign_bit(200, false); }); } #[test] fn assign_bit_fail() { apply_fn_to_primitive_ints!(assign_bit_fail_helper); apply_fn_to_signeds!(assign_bit_fail_helper_signed); } fn properties_helper_unsigned() { unsigned_unsigned_bool_triple_gen_var_1::().test_properties(|(mut n, index, bit)| { n.assign_bit(index, bit); }); } fn properties_helper_signed() { signed_unsigned_bool_triple_gen_var_1::().test_properties(|(mut n, index, bit)| { n.assign_bit(index, bit); }); } #[test] fn assign_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_access/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_4, unsigned_pair_gen_var_2, }; use std::panic::catch_unwind; fn clear_bit_helper_unsigned() { let test = |n: u64, index, out: u64| { let mut n = T::exact_from(n); n.clear_bit(index); assert_eq!(n, T::exact_from(out)); }; test(0, 10, 0); test(0, 100, 0); test(101, 0, 100); if T::WIDTH >= u16::WIDTH { test(1024, 10, 0); } if T::WIDTH >= u64::WIDTH { test(1000000001024, 10, 1000000000000); test(1000000001024, 100, 1000000001024); } } fn clear_bit_helper_signed() { clear_bit_helper_unsigned::(); let test = |n: i64, index, out: i64| { let mut n = T::exact_from(n); n.clear_bit(index); assert_eq!(n, T::exact_from(out)); }; test(-1, 5, -33); test(-31, 0, -32); if T::WIDTH >= u64::WIDTH { test(-999999998976, 10, -1000000000000); } let mut n = T::MIN; n.clear_bit(T::WIDTH - 1); assert_eq!(n, T::ZERO); } #[test] fn test_clear_bit() { apply_fn_to_unsigneds!(clear_bit_helper_unsigned); apply_fn_to_signeds!(clear_bit_helper_signed); } fn clear_bit_fail_helper() { assert_panic!({ let mut n = T::NEGATIVE_ONE; n.clear_bit(200); }); } #[test] fn clear_bit_fail() { apply_fn_to_signeds!(clear_bit_fail_helper); } fn properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(mut n, index)| { let old_n = n; n.clear_bit(index); let result = n; let mut n = old_n; n.assign_bit(index, false); assert_eq!(n, result); assert!(result <= old_n); if old_n.get_bit(index) { assert_ne!(result, old_n); let mut n = result; n.set_bit(index); assert_eq!(n, old_n); } else { assert_eq!(result, old_n); } }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_4::().test_properties(|(mut n, index)| { let old_n = n; n.clear_bit(index); let result = n; let mut n = old_n; n.assign_bit(index, false); assert_eq!(n, result); if old_n < T::ZERO && index == T::WIDTH - 1 { assert!(result >= T::ZERO); } else { assert!(result <= old_n); } if old_n.get_bit(index) { assert_ne!(result, old_n); let mut n = result; n.set_bit(index); assert_eq!(n, old_n); } else { assert_eq!(result, old_n); } let mut n = !old_n; n.set_bit(index); n.not_assign(); assert_eq!(n, result); }); } #[test] fn clear_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_access/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_2, unsigned_pair_gen_var_3, }; use std::panic::catch_unwind; fn flip_bit_helper_unsigned() { let test = |n: u64, index, out: u64| { let mut n = T::exact_from(n); n.flip_bit(index); assert_eq!(n, T::exact_from(out)); }; test(100, 0, 101); test(101, 0, 100); if T::WIDTH >= u16::WIDTH { test(0, 10, 1024); test(1024, 10, 0); } if T::WIDTH >= u64::WIDTH { test(1000000000000, 10, 1000000001024); test(1000000001024, 10, 1000000000000); } } fn flip_bit_helper_signed() { flip_bit_helper_unsigned::(); let test = |n: i64, index, out: i64| { let mut n = T::exact_from(n); n.flip_bit(index); assert_eq!(n, T::exact_from(out)); }; test(-1, 5, -33); test(-33, 5, -1); test(-32, 0, -31); test(-31, 0, -32); if T::WIDTH >= u64::WIDTH { test(-1000000000000, 10, -999999998976); test(-999999998976, 10, -1000000000000); } let mut n = T::ZERO; n.flip_bit(T::WIDTH - 1); assert_eq!(n, T::MIN); let mut n = T::MIN; n.flip_bit(T::WIDTH - 1); assert_eq!(n, T::ZERO); } #[test] fn test_flip_bit() { apply_fn_to_unsigneds!(flip_bit_helper_unsigned); apply_fn_to_signeds!(flip_bit_helper_signed); } fn flip_bit_fail_helper_unsigned() { assert_panic!(T::exact_from(5).flip_bit(200)); } fn flip_bit_fail_helper_signed() { assert_panic!(T::exact_from(5).flip_bit(200)); assert_panic!({ let mut n = T::NEGATIVE_ONE; n.flip_bit(200); }); } #[test] fn flip_bit_fail() { apply_fn_to_unsigneds!(flip_bit_fail_helper_unsigned); apply_fn_to_signeds!(flip_bit_fail_helper_signed); } fn properties_helper_unsigned() { unsigned_pair_gen_var_3::().test_properties(|(mut n, index)| { let old_n = n; n.flip_bit(index); assert_ne!(n, old_n); n.flip_bit(index); assert_eq!(n, old_n); }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_2::().test_properties(|(mut n, index)| { let old_n = n; n.flip_bit(index); assert_ne!(n, old_n); n.flip_bit(index); assert_eq!(n, old_n); }); } #[test] fn flip_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_access/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_pair_gen_var_2, }; fn test_helper_primitive_int() { let test = |n: u64, index, out| { assert_eq!(T::exact_from(n).get_bit(index), out); }; test(0, 0, false); test(0, 100, false); test(123, 2, false); test(123, 3, true); test(123, 100, false); if T::WIDTH >= u64::WIDTH { test(1000000000000, 12, true); test(1000000000000, 100, false); } } fn test_helper_signed() { let test = |n: i64, index, out| { assert_eq!(T::exact_from(n).get_bit(index), out); }; test(-123, 0, true); test(-123, 1, false); test(-123, 100, true); if T::WIDTH >= u64::WIDTH { test(-1000000000000, 12, true); test(-1000000000000, 100, true); test(-i64::from(u32::MAX), 0, true); test(-i64::from(u32::MAX), 1, false); test(-i64::from(u32::MAX), 31, false); test(-i64::from(u32::MAX), 32, true); test(-i64::from(u32::MAX), 33, true); test(-i64::from(u32::MAX) - 1, 0, false); test(-i64::from(u32::MAX) - 1, 31, false); test(-i64::from(u32::MAX) - 1, 32, true); test(-i64::from(u32::MAX) - 1, 33, true); } } #[test] fn test_get_bit() { apply_fn_to_primitive_ints!(test_helper_primitive_int); apply_fn_to_signeds!(test_helper_signed); } fn properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(n, index)| { let bit = n.get_bit(index); if index >= T::WIDTH { assert!(!bit); } else { assert_eq!(bit, !(!n).get_bit(index)); } }); unsigned_gen::().test_properties(|n| { let significant_bits = n.significant_bits(); assert!(!n.get_bit(significant_bits)); if n != T::ZERO { assert!(n.get_bit(significant_bits - 1)); } }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_1::().test_properties(|(n, index)| { let bit = n.get_bit(index); if index >= T::WIDTH { assert_eq!(bit, n < T::ZERO); } else { assert_eq!(bit, !(!n).get_bit(index)); } }); } #[test] fn get_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_access/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_3, unsigned_pair_gen_var_3, }; use std::panic::catch_unwind; fn set_bit_helper_unsigned() { let test = |n: u64, index, out: u64| { let mut n = T::exact_from(n); n.set_bit(index); assert_eq!(n, T::exact_from(out)); }; test(100, 0, 101); if T::WIDTH >= u16::WIDTH { test(0, 10, 1024); } if T::WIDTH >= u64::WIDTH { test(1000000000000, 10, 1000000001024); } } fn set_bit_helper_signed() { set_bit_helper_unsigned::(); let test = |n: i64, index, out: i64| { let mut n = T::exact_from(n); n.set_bit(index); assert_eq!(n, T::exact_from(out)); }; test(-1, 5, -1); test(-1, 100, -1); test(-33, 5, -1); test(-32, 0, -31); if T::WIDTH >= u64::WIDTH { test(-1000000000000, 10, -999999998976); test(-1000000000000, 100, -1000000000000); } let mut n = T::ZERO; n.set_bit(T::WIDTH - 1); assert_eq!(n, T::MIN); } #[test] fn test_set_bit() { apply_fn_to_unsigneds!(set_bit_helper_unsigned); apply_fn_to_signeds!(set_bit_helper_signed); } fn set_bit_fail_helper() { assert_panic!({ let mut n = T::exact_from(5); n.set_bit(200); }); } #[test] fn set_bit_fail() { apply_fn_to_primitive_ints!(set_bit_fail_helper); } fn properties_helper_unsigned() { unsigned_pair_gen_var_3::().test_properties(|(mut n, index)| { let old_n = n; n.set_bit(index); let result = n; let mut n = old_n; n.assign_bit(index, true); assert_eq!(n, result); assert_ne!(result, T::ZERO); assert!(result >= old_n); if old_n.get_bit(index) { assert_eq!(result, old_n); } else { assert_ne!(result, old_n); let mut n = result; n.clear_bit(index); assert_eq!(n, old_n); } }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_3::().test_properties(|(mut n, index)| { let old_n = n; n.set_bit(index); let result = n; let mut n = old_n; n.assign_bit(index, true); assert_eq!(n, result); assert_ne!(result, T::ZERO); if old_n >= T::ZERO && index == T::WIDTH - 1 { assert!(result < T::ZERO); } else { assert!(result >= old_n); } if old_n.get_bit(index) { assert_eq!(result, old_n); } else { assert_ne!(result, old_n); let mut n = result; n.clear_bit(index); assert_eq!(n, old_n); } let mut n = !old_n; n.clear_bit(index); n.not_assign(); assert_eq!(n, result); }); } #[test] fn set_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_block_access/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, signed_unsigned_unsigned_triple_gen_var_1, signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_7, unsigned_quadruple_gen_var_1, unsigned_triple_gen_var_4, }; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use std::cmp::min; use std::panic::catch_unwind; #[test] pub fn test_assign_bits_unsigned() { fn test + PrimitiveUnsigned>( x_in: T, start: u64, end: u64, bits: T, x_out: T, ) { let mut x = x_in; x.assign_bits(start, end, &bits); assert_eq!(x, x_out); let mut x = x_in; assign_bits_naive(&mut x, start, end, &bits); assert_eq!(x, x_out); } // - assign partially test(0xab5du16, 4, 8, 0xc, 0xabcd); test(0x5bcdu16, 12, 100, 0xa, 0xabcd); test(0xabcdu16, 5, 9, 10, 43853); test(0xabcdu16, 5, 5, 123, 0xabcd); // - assign zeros above width test(0xabcdu16, 100, 200, 0, 0xabcd); test(0xabcdu16, 8, 24, 0, 0xcd); // - assign everything test(0xabcdu16, 0, 100, 0x1234, 0x1234); test(0xab5du64, 4, 8, 0xc, 0xabcd); test(0x5bcdu64, 12, 100, 0xa, 0xabcd); test(0xabcdu64, 5, 9, 10, 43853); test(0xabcdu64, 5, 5, 123, 0xabcd); test(0xabcdu64, 100, 200, 0, 0xabcd); test(0xabcdu64, 0, 100, 0x1234, 0x1234); } #[test] pub fn test_assign_bits_signed() { fn test + PrimitiveSigned, U: PrimitiveUnsigned>( x_in: T, start: u64, end: u64, bits: U, x_out: T, ) { let mut x = x_in; x.assign_bits(start, end, &bits); assert_eq!(x, x_out); let mut x = x_in; assign_bits_naive(&mut x, start, end, &bits); assert_eq!(x, x_out); } // - *self >= 0 test(0x2b5di16, 4, 8, 0xc, 0x2bcd); // - *self < 0 // - assign within width test(-0x5413i16, 4, 8, 0xc, -0x5433); test(-0x54a3i16, 5, 9, 14, -21539); test(-0x5433i16, 5, 5, 0, -0x5433); // - assign ones above width test(-0x5433i16, 100, 104, 0xf, -0x5433); // - assign everything test(-57i8, 0, 8, 0xff, -1); test(0x2b5di64, 4, 8, 0xc, 0x2bcd); test(-0x5413i64, 4, 8, 0xc, -0x5433); test(-0x54a3i64, 5, 9, 14, -21539); test(-0x5433i64, 5, 5, 0, -0x5433); test(-0x5433i64, 100, 104, 0xf, -0x5433); test(-57i64, 0, 64, u64::MAX, -1); } fn assign_bits_fail_helper_unsigned + PrimitiveUnsigned>() { assert_panic!(T::exact_from(100).assign_bits(10, 5, &T::exact_from(3))); assert_panic!(T::exact_from(100).assign_bits(3, T::WIDTH + 3, &T::MAX)); } fn assign_bits_fail_helper_signed< U: PrimitiveUnsigned, S: BitBlockAccess + PrimitiveSigned, >() { assert_panic!(S::exact_from(100).assign_bits(7, 5, &U::exact_from(3))); assert_panic!(S::exact_from(100).assign_bits(0, S::WIDTH, &U::MAX)); assert_panic!(S::exact_from(-100).assign_bits(0, S::WIDTH + 1, &U::ZERO)); assert_panic!(S::exact_from(-100).assign_bits(S::WIDTH + 1, S::WIDTH + 2, &U::ZERO)); assert_panic!({ let half_width = S::WIDTH >> 1; S::exact_from(-100).assign_bits(half_width, 3 * half_width - 4, &U::ZERO); }); } #[test] fn assign_bits_fail() { apply_fn_to_unsigneds!(assign_bits_fail_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(assign_bits_fail_helper_signed); } fn properties_helper_unsigned + PrimitiveUnsigned>() { unsigned_quadruple_gen_var_1::().test_properties(|(n, start, end, bits)| { let mut mut_n = n; mut_n.assign_bits(start, end, &bits); let mut mut_n_alt = mut_n; mut_n_alt.assign_bits(start, end, &bits); assert_eq!(mut_n_alt, mut_n); let mut mut_n_alt = n; assign_bits_naive::(&mut mut_n_alt, start, end, &bits); assert_eq!(mut_n_alt, mut_n); assert_eq!(mut_n.get_bits(start, end), bits.mod_power_of_2(end - start)); }); unsigned_triple_gen_var_4::().test_properties(|(n, bits, start)| { let mut mut_n = n; mut_n.assign_bits(start, start, &bits); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_2::().test_properties(|(n, start)| { let mut mut_n = n; mut_n.assign_bits(start + T::WIDTH, start + (T::WIDTH << 1), &T::ZERO); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_7::().test_properties(|(start, end)| { let mut n = T::ZERO; n.assign_bits(start, end, &T::ZERO); assert_eq!(n, T::ZERO); }); } fn properties_helper_signed< U: BitBlockAccess + PrimitiveUnsigned, T: BitBlockAccess + PrimitiveSigned + UnsignedAbs, >() { signed_unsigned_unsigned_unsigned_quadruple_gen_var_1::().test_properties( |(n, start, end, bits)| { let mut mut_n = n; mut_n.assign_bits(start, end, &bits); let mut mut_n_alt = mut_n; mut_n_alt.assign_bits(start, end, &bits); assert_eq!(mut_n_alt, mut_n); let mut mut_n_alt = n; assign_bits_naive::(&mut mut_n_alt, start, end, &bits); assert_eq!(mut_n_alt, mut_n); assert_eq!(mut_n.get_bits(start, end), bits.mod_power_of_2(end - start)); assert_eq!(mut_n >= T::ZERO, n >= T::ZERO); }, ); signed_unsigned_unsigned_triple_gen_var_1::().test_properties(|(n, bits, start)| { let mut mut_n = n; mut_n.assign_bits(start, start, &bits); assert_eq!(mut_n, n); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, start)| { let mut mut_n = n; mut_n.assign_bits( start + T::WIDTH - 1, start + (T::WIDTH << 1) - 1, &(if n >= T::ZERO { U::ZERO } else { U::MAX }), ); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_7().test_properties(|(start, end)| { let mut n = T::ZERO; n.assign_bits(start, end, &U::ZERO); assert_eq!(n, T::ZERO); let mut n = T::NEGATIVE_ONE; n.assign_bits(start, min(end, start.saturating_add(T::WIDTH)), &U::MAX); assert_eq!(n, T::NEGATIVE_ONE); }); } #[test] fn assign_bits_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_block_access/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, signed_unsigned_unsigned_triple_gen_var_2, unsigned_gen_var_5, unsigned_pair_gen_var_2, unsigned_pair_gen_var_7, unsigned_triple_gen_var_5, }; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use std::panic::catch_unwind; #[test] pub fn test_get_bits_unsigned() { fn test + PrimitiveUnsigned>(x: T, start: u64, end: u64, out: T) { assert_eq!(x.get_bits(start, end), out); assert_eq!(get_bits_naive::(&x, start, end), out); } test(0xabcdu16, 4, 8, 0xc); test(0xabcdu16, 12, 100, 0xa); test(0xabcdu16, 5, 9, 14); test(0xabcdu16, 5, 5, 0); test(0xabcdu16, 100, 200, 0); test(0xabcdu64, 4, 8, 0xc); test(0xabcdu64, 12, 100, 0xa); test(0xabcdu64, 5, 9, 14); test(0xabcdu64, 5, 5, 0); test(0xabcdu64, 100, 200, 0); } #[test] pub fn test_get_bits_signed() { fn test + PrimitiveSigned, U: PrimitiveUnsigned>( x: T, start: u64, end: u64, out: U, ) { assert_eq!(x.get_bits(start, end), out); assert_eq!(get_bits_naive::(&x, start, end), out); } test(-0x5433i16, 4, 8, 0xc); test(-0x5433i16, 5, 9, 14); test(-0x5433i16, 5, 5, 0); test(-0x5433i16, 100, 104, 0xf); test(-0x5433i64, 4, 8, 0xc); test(-0x5433i64, 5, 9, 14); test(-0x5433i64, 5, 5, 0); test(-0x5433i64, 100, 104, 0xf); test(-1i8, 0, 8, 0xff); } fn get_bits_fail_helper() { assert_panic!(T::exact_from(100).get_bits(10, 5)); } fn get_bits_fail_helper_signed() { assert_panic!(T::exact_from(-100).get_bits(100, 300)); } #[test] fn get_bits_fail() { apply_fn_to_primitive_ints!(get_bits_fail_helper); apply_fn_to_signeds!(get_bits_fail_helper_signed); } fn properties_helper_unsigned + PrimitiveUnsigned>() { unsigned_triple_gen_var_5::().test_properties(|(n, start, end)| { let bits = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), bits); assert!(bits <= n); assert_eq!(n.get_bits(start + T::WIDTH, end + T::WIDTH), T::ZERO); let mut n_alt = n; n_alt.assign_bits(start, end, &bits); assert_eq!(n_alt, n); }); unsigned_pair_gen_var_2::().test_properties(|(n, start)| { assert_eq!(n.get_bits(start, start), T::ZERO); }); unsigned_pair_gen_var_7().test_properties(|(start, end)| { assert_eq!(T::ZERO.get_bits(start, end), T::ZERO); }); } fn properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: BitBlockAccess + PrimitiveSigned + WrappingFrom, >() { signed_unsigned_unsigned_triple_gen_var_2::().test_properties(|(n, start, end)| { let bits = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), bits); let mut n_alt = n; n_alt.assign_bits(start, end, &bits); assert_eq!(n_alt, n); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, start)| { assert_eq!(n.get_bits(start, start), U::ZERO); assert_eq!( n.get_bits(start + S::WIDTH, start + (S::WIDTH << 1)), if n >= S::ZERO { U::ZERO } else { U::MAX } ); }); unsigned_pair_gen_var_7().test_properties(|(start, end)| { assert_eq!(S::ZERO.get_bits(start, end), U::ZERO); }); unsigned_gen_var_5().test_properties(|start| { assert_eq!(S::NEGATIVE_ONE.get_bits(start, start + S::WIDTH), U::MAX); }); } #[test] fn get_bits_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_convertible/from_bits.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ bool_vec_gen_var_1, bool_vec_gen_var_2, bool_vec_gen_var_3, bool_vec_gen_var_4, unsigned_gen_var_5, }; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_asc_signed_naive, from_bits_asc_unsigned_naive, from_bits_desc_alt, }; use std::iter::once; use std::panic::catch_unwind; #[test] pub fn test_from_bits_asc() { fn test_unsigned(bits: &[bool], out: T) { assert_eq!(T::from_bits_asc(bits.iter().copied()), out); assert_eq!( from_bits_asc_unsigned_naive::(bits.iter().copied()), out ); assert_eq!(from_bits_asc_alt::(bits.iter().copied()), out); } test_unsigned(&[], 0u8); test_unsigned(&[false], 0u8); test_unsigned(&[false, false, false], 0u8); test_unsigned(&[false; 100], 0u8); test_unsigned(&[true], 1u16); test_unsigned(&[false, true], 2u32); test_unsigned(&[true, true], 3u64); test_unsigned(&[true, true, false, true, true, true, true], 123u16); test_unsigned( &[true, true, false, true, true, true, true, false, false, false], 123u16, ); test_unsigned(&[true; 8], u8::MAX); fn test_signed(bits: &[bool], out: T) { assert_eq!(T::from_bits_asc(bits.iter().copied()), out); assert_eq!( from_bits_asc_signed_naive::(bits.iter().copied()), out ); assert_eq!(from_bits_asc_alt::(bits.iter().copied()), out); } test_signed(&[], 0i8); test_signed(&[false], 0i8); test_signed(&[false, false, false], 0i8); test_signed(&[false; 100], 0i8); test_signed(&[true, false], 1i16); test_signed(&[false, true, false], 2i32); test_signed(&[true, true, false], 3i64); test_signed(&[true], -1i16); test_signed(&[true, true, true], -1i16); test_signed(&[true; 100], -1i16); test_signed(&[false, true], -2i32); test_signed(&[true, false, true], -3i64); test_signed(&[true, true, false, true, true, true, true, false], 123i16); test_signed( &[true, true, false, true, true, true, true, false, false, false, false], 123i16, ); test_signed( &[true, false, true, false, false, false, false, true], -123i16, ); test_signed( &[true, false, true, false, false, false, false, true, true, true, true], -123i16, ); test_signed(&[true, true, true, true, true, true, true, false], i8::MAX); test_signed( &[false, false, false, false, false, false, false, true], i8::MIN, ); } fn from_bits_asc_fail_helper_unsigned() { assert_panic!(T::from_bits_asc(repeat_n(true, 200))); } fn from_bits_asc_fail_helper_signed() { assert_panic!(T::from_bits_asc( repeat_n(false, 200).chain([true, false].iter().copied()) )); assert_panic!(T::from_bits_asc(repeat_n(false, 200).chain(once(true)))); } #[test] fn from_bits_asc_fail() { apply_fn_to_unsigneds!(from_bits_asc_fail_helper_unsigned); apply_fn_to_signeds!(from_bits_asc_fail_helper_signed); } #[test] pub fn test_from_bits_desc() { fn test_unsigned(bits: &[bool], out: T) { assert_eq!(T::from_bits_desc(bits.iter().copied()), out); assert_eq!(from_bits_desc_alt::(bits.iter().copied()), out); } test_unsigned(&[], 0u8); test_unsigned(&[false], 0u8); test_unsigned(&[false, false, false], 0u8); test_unsigned(&[false; 100], 0u8); test_unsigned(&[true], 1u16); test_unsigned(&[true, false], 2u32); test_unsigned(&[true, true], 3u64); test_unsigned(&[true, true, true, true, false, true, true], 123u16); test_unsigned( &[false, false, false, true, true, true, true, false, true, true], 123u16, ); test_unsigned(&[true; 8], u8::MAX); fn test_signed(bits: &[bool], out: T) { assert_eq!(T::from_bits_desc(bits.iter().copied()), out); assert_eq!(from_bits_desc_alt::(bits.iter().copied()), out); } test_signed(&[], 0i8); test_signed(&[false], 0i8); test_signed(&[false, false, false], 0i8); test_signed(&[false; 100], 0i8); test_signed(&[false, true], 1i16); test_signed(&[false, true, false], 2i32); test_signed(&[false, true, true], 3i64); test_signed(&[true], -1i16); test_signed(&[true, true, true], -1i16); test_signed(&[true; 100], -1i16); test_signed(&[true, false], -2i32); test_signed(&[true, false, true], -3i64); test_signed(&[false, true, true, true, true, false, true, true], 123i16); test_signed( &[false, false, false, false, true, true, true, true, false, true, true], 123i16, ); test_signed( &[true, false, false, false, false, true, false, true], -123i16, ); test_signed( &[true, true, true, true, false, false, false, false, true, false, true], -123i16, ); test_signed(&[false, true, true, true, true, true, true, true], i8::MAX); test_signed( &[true, false, false, false, false, false, false, false], i8::MIN, ); } fn from_bits_desc_fail_helper_unsigned() { assert_panic!(T::from_bits_desc(repeat_n(true, 200))); } fn from_bits_desc_fail_helper_signed() { assert_panic!(T::from_bits_desc( [false, true].iter().copied().chain(repeat_n(false, 200)) )); assert_panic!(T::from_bits_desc(once(true).chain(repeat_n(false, 200)))); } #[test] fn from_bits_desc_fail() { apply_fn_to_unsigneds!(from_bits_desc_fail_helper_unsigned); apply_fn_to_signeds!(from_bits_desc_fail_helper_signed); } fn from_bits_asc_properties_helper_unsigned() { bool_vec_gen_var_1::().test_properties(|bs| { let n = T::from_bits_asc(bs.iter().copied()); assert_eq!(from_bits_asc_unsigned_naive::(bs.iter().copied()), n); assert_eq!(from_bits_asc_alt::(bs.iter().copied()), n); let trailing_falses = bs.iter().rev().take_while(|&&bit| !bit).count(); let trimmed_bits = bs[..bs.len() - trailing_falses].to_vec(); assert_eq!(n.to_bits_asc(), trimmed_bits); }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO); }); } fn from_bits_asc_properties_helper_signed() { bool_vec_gen_var_2::().test_properties(|bs| { let n = T::from_bits_asc(bs.iter().copied()); assert_eq!(from_bits_asc_signed_naive::(bs.iter().copied()), n); assert_eq!(from_bits_asc_alt::(bs.iter().copied()), n); let trimmed_bits = if bs.iter().all(|&bit| !bit) { Vec::new() } else { let sign_bits = if *bs.last().unwrap() { bs.iter().rev().take_while(|&&bit| bit).count() } else { bs.iter().rev().take_while(|&&bit| !bit).count() }; bs[..=bs.len() - sign_bits].to_vec() }; assert_eq!(n.to_bits_asc(), trimmed_bits); }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::from_bits_asc(repeat_n(false, u)), T::ZERO); assert_eq!(T::from_bits_asc(repeat_n(true, u + 1)), T::NEGATIVE_ONE); }); } #[test] fn from_bits_asc_properties() { apply_fn_to_unsigneds!(from_bits_asc_properties_helper_unsigned); apply_fn_to_signeds!(from_bits_asc_properties_helper_signed); } fn from_bits_desc_properties_helper_unsigned() { bool_vec_gen_var_3::().test_properties(|bs| { let n = T::from_bits_desc(bs.iter().copied()); assert_eq!(from_bits_desc_alt::(bs.iter().copied()), n); let leading_falses = bs.iter().take_while(|&&bit| !bit).count(); let trimmed_bits = bs[leading_falses..].to_vec(); assert_eq!(n.to_bits_desc(), trimmed_bits); }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO); }); } fn from_bits_desc_properties_helper_signed() { bool_vec_gen_var_4::().test_properties(|bs| { let n = T::from_bits_desc(bs.iter().copied()); assert_eq!(from_bits_desc_alt::(bs.iter().copied()), n); let trimmed_bits = if bs.iter().all(|&bit| !bit) { Vec::new() } else { let sign_bits = if bs[0] { bs.iter().take_while(|&&bit| bit).count() } else { bs.iter().take_while(|&&bit| !bit).count() }; bs[sign_bits - 1..].to_vec() }; assert_eq!(n.to_bits_desc(), trimmed_bits); }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO); assert_eq!(T::from_bits_desc(repeat_n(true, u + 1)), T::NEGATIVE_ONE); }); } #[test] fn from_bits_desc_properties() { apply_fn_to_unsigneds!(from_bits_desc_properties_helper_unsigned); apply_fn_to_signeds!(from_bits_desc_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_convertible/to_bits.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::num::logic::bit_convertible::{ to_bits_asc_alt, to_bits_asc_signed_naive, to_bits_asc_unsigned_naive, to_bits_desc_alt, to_bits_desc_signed_naive, to_bits_desc_unsigned_naive, }; #[test] pub fn test_to_bits_asc() { fn test_unsigned(x: T, out: &[bool]) { assert_eq!(x.to_bits_asc(), out); assert_eq!(to_bits_asc_unsigned_naive(x), out); assert_eq!(to_bits_asc_alt(&x), out); assert_eq!(x.bits().collect_vec(), out); } test_unsigned(0u8, &[]); test_unsigned(1u16, &[true]); test_unsigned(2u32, &[false, true]); test_unsigned(3u64, &[true, true]); test_unsigned(123u16, &[true, true, false, true, true, true, true]); test_unsigned(u8::MAX, &[true; 8]); fn test_signed(x: T, out: &[bool]) { assert_eq!(x.to_bits_asc(), out); assert_eq!(to_bits_asc_signed_naive(x), out); assert_eq!(to_bits_asc_alt(&x), out); assert_eq!(x.bits().collect_vec(), out); } test_signed(0i8, &[]); test_signed(1i16, &[true, false]); test_signed(2i32, &[false, true, false]); test_signed(3i64, &[true, true, false]); test_signed(-1i16, &[true]); test_signed(-2i32, &[false, true]); test_signed(-3i64, &[true, false, true]); test_signed(123i16, &[true, true, false, true, true, true, true, false]); test_signed( -123i16, &[true, false, true, false, false, false, false, true], ); test_signed(i8::MAX, &[true, true, true, true, true, true, true, false]); test_signed( i8::MIN, &[false, false, false, false, false, false, false, true], ); } #[test] pub fn test_to_bits_desc() { fn test_unsigned(x: T, out: &[bool]) { assert_eq!(x.to_bits_desc(), out); assert_eq!(to_bits_desc_unsigned_naive(x), out); assert_eq!(to_bits_desc_alt(&x), out); assert_eq!(x.bits().rev().collect_vec(), out); } test_unsigned(0u8, &[]); test_unsigned(1u16, &[true]); test_unsigned(2u32, &[true, false]); test_unsigned(3u64, &[true, true]); test_unsigned(123u16, &[true, true, true, true, false, true, true]); test_unsigned(u8::MAX, &[true; 8]); fn test_signed(x: T, out: &[bool]) { assert_eq!(x.to_bits_desc(), out); assert_eq!(to_bits_desc_signed_naive(x), out); assert_eq!(to_bits_desc_alt(&x), out); assert_eq!(x.bits().rev().collect_vec(), out); } test_signed(0i8, &[]); test_signed(1i16, &[false, true]); test_signed(2i32, &[false, true, false]); test_signed(3i64, &[false, true, true]); test_signed(-1i16, &[true]); test_signed(-2i32, &[true, false]); test_signed(-3i64, &[true, false, true]); test_signed(123i16, &[false, true, true, true, true, false, true, true]); test_signed( -123i16, &[true, false, false, false, false, true, false, true], ); test_signed(i8::MAX, &[false, true, true, true, true, true, true, true]); test_signed( i8::MIN, &[true, false, false, false, false, false, false, false], ); } fn to_bits_asc_properties_helper_unsigned() { unsigned_gen::().test_properties(|u| { let bits = u.to_bits_asc(); assert_eq!(to_bits_asc_unsigned_naive(u), bits); assert_eq!(to_bits_asc_alt(&u), bits); assert_eq!(u.bits().collect::>(), bits); assert_eq!( bits.iter().copied().rev().collect::>(), u.to_bits_desc() ); assert_eq!(T::from_bits_asc(bits.iter().copied()), u); if u != T::ZERO { assert_eq!(*bits.last().unwrap(), true); } assert_eq!(bits.len(), usize::exact_from(u.significant_bits())); }); } fn to_bits_asc_properties_helper_signed() { signed_gen::().test_properties(|i| { let bits = i.to_bits_asc(); assert_eq!(to_bits_asc_signed_naive(i), bits); assert_eq!(to_bits_asc_alt(&i), bits); assert_eq!(i.bits().collect::>(), bits); assert_eq!( bits.iter().copied().rev().collect::>(), i.to_bits_desc() ); assert_eq!(T::from_bits_asc(bits.iter().copied()), i); if i != T::ZERO { assert_eq!(*bits.last().unwrap(), i < T::ZERO); } let bit_len = bits.len(); assert!(bit_len <= usize::exact_from(T::WIDTH)); if bit_len > 1 { assert_ne!(bits[bit_len - 1], bits[bit_len - 2]); } }); } #[test] fn to_bits_asc_properties() { apply_fn_to_unsigneds!(to_bits_asc_properties_helper_unsigned); apply_fn_to_signeds!(to_bits_asc_properties_helper_signed); } fn to_bits_desc_properties_helper_unsigned() { unsigned_gen::().test_properties(|u| { let bits = u.to_bits_desc(); assert_eq!(to_bits_desc_unsigned_naive(u), bits); assert_eq!(to_bits_desc_alt(&u), bits); assert_eq!(u.bits().rev().collect::>(), bits); assert_eq!( bits.iter().copied().rev().collect::>(), u.to_bits_asc() ); assert_eq!(T::from_bits_desc(bits.iter().copied()), u); if u != T::ZERO { assert_eq!(bits[0], true); } assert_eq!(bits.len(), usize::exact_from(u.significant_bits())); }); } fn to_bits_desc_properties_helper_signed() { signed_gen::().test_properties(|i| { let bits = i.to_bits_desc(); assert_eq!(to_bits_desc_signed_naive(i), bits); assert_eq!(to_bits_desc_alt(&i), bits); assert_eq!(i.bits().rev().collect::>(), bits); assert_eq!( bits.iter().copied().rev().collect::>(), i.to_bits_asc() ); assert_eq!(T::from_bits_desc(bits.iter().copied()), i); if i != T::ZERO { assert_eq!(bits[0], i < T::ZERO); } let bit_len = bits.len(); assert!(bit_len <= usize::exact_from(T::WIDTH)); if bit_len > 1 { assert_ne!(bits[0], bits[1]); } }); } #[test] fn to_bits_desc_properties() { apply_fn_to_unsigneds!(to_bits_desc_properties_helper_unsigned); apply_fn_to_signeds!(to_bits_desc_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_iterable.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::{BitIterable, SignificantBits}; use malachite_base::test_util::common::test_double_ended_iterator_size_hint; use malachite_base::test_util::generators::{ signed_bool_vec_pair_gen_var_1, signed_gen, signed_unsigned_pair_gen_var_1, unsigned_bool_vec_pair_gen_var_1, unsigned_gen, unsigned_gen_var_5, unsigned_pair_gen_var_2, }; use std::cmp::Ordering::*; use std::ops::Index; #[test] pub fn test_bits() { let mut bits = 105u8.bits(); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); assert_eq!(bits[0], true); assert_eq!(bits[1], false); assert_eq!(bits[2], false); assert_eq!(bits[3], true); assert_eq!(bits[4], false); assert_eq!(bits[5], true); assert_eq!(bits[6], true); assert_eq!(bits[7], false); assert_eq!(bits[8], false); let mut bits = 105u32.bits(); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); let mut bits = (-105i8).bits(); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); assert_eq!(bits[0], true); assert_eq!(bits[1], true); assert_eq!(bits[2], true); assert_eq!(bits[3], false); assert_eq!(bits[4], true); assert_eq!(bits[5], false); assert_eq!(bits[6], false); assert_eq!(bits[7], true); assert_eq!(bits[8], true); let mut bits = (-105i32).bits(); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); } fn bits_properties_helper_unsigned() where T::BitIterator: Clone + Index, { unsigned_gen::().test_properties(|n| { test_double_ended_iterator_size_hint(n.bits(), usize::exact_from(n.significant_bits())); }); unsigned_bool_vec_pair_gen_var_1::().test_properties(|(n, bs)| { let mut bits = n.bits(); let mut bit_vec = Vec::new(); let mut i = 0; for b in bs { if b { bit_vec.insert(i, bits.next().unwrap()); i += 1; } else { bit_vec.insert(i, bits.next_back().unwrap()); } } assert!(bits.next().is_none()); assert!(bits.next_back().is_none()); assert_eq!(n.to_bits_asc(), bit_vec); }); unsigned_pair_gen_var_2::().test_properties(|(n, u)| { if u < n.significant_bits() { assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]); } else { assert_eq!(n.bits()[u], false); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::ZERO.bits()[u], false); }); } fn bits_properties_helper_signed() where T::BitIterator: Clone + Index, ::Output: PrimitiveUnsigned + WrappingFrom, { signed_gen::().test_properties(|i| { let unsigned = ::Output::wrapping_from(i); let significant_bits = match i.sign() { Equal => 0, Greater => unsigned.significant_bits() + 1, Less => (!unsigned).significant_bits() + 1, }; test_double_ended_iterator_size_hint(i.bits(), usize::exact_from(significant_bits)); }); signed_bool_vec_pair_gen_var_1::().test_properties(|(n, bs)| { let mut bits = n.bits(); let mut bit_vec = Vec::new(); let mut i = 0; for b in bs { if b { bit_vec.insert(i, bits.next().unwrap()); i += 1; } else { bit_vec.insert(i, bits.next_back().unwrap()); } } assert!(bits.next().is_none()); assert!(bits.next_back().is_none()); assert_eq!(n.to_bits_asc(), bit_vec); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { if u < n.significant_bits() { assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]); } else { assert_eq!(n.bits()[u], n < T::ZERO); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(T::ZERO.bits()[u], false); }); } #[test] fn bits_properties() { apply_fn_to_unsigneds!(bits_properties_helper_unsigned); apply_fn_to_signeds!(bits_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_scan/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::test_util::generators::{ signed_gen_var_3, signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_pair_gen_var_2, }; #[test] pub fn test_index_of_next_false_bit() { fn test_unsigned(x: T, start: u64, out: Option) { assert_eq!(x.index_of_next_false_bit(start), out); } test_unsigned(0xb00000000u64, 0, Some(0)); test_unsigned(0xb00000000u64, 20, Some(20)); test_unsigned(0xb00000000u64, 31, Some(31)); test_unsigned(0xb00000000u64, 32, Some(34)); test_unsigned(0xb00000000u64, 33, Some(34)); test_unsigned(0xb00000000u64, 34, Some(34)); test_unsigned(0xb00000000u64, 35, Some(36)); test_unsigned(0xb00000000u64, 100, Some(100)); test_unsigned(0xb00000000u128, 0, Some(0)); test_unsigned(0xb00000000u128, 20, Some(20)); test_unsigned(0xb00000000u128, 31, Some(31)); test_unsigned(0xb00000000u128, 32, Some(34)); test_unsigned(0xb00000000u128, 33, Some(34)); test_unsigned(0xb00000000u128, 34, Some(34)); test_unsigned(0xb00000000u128, 35, Some(36)); test_unsigned(0xb00000000u128, 100, Some(100)); fn test_signed(x: T, start: u64, out: Option) { assert_eq!(x.index_of_next_false_bit(start), out); } test_signed(-0x500000000i64, 0, Some(0)); test_signed(-0x500000000i64, 20, Some(20)); test_signed(-0x500000000i64, 31, Some(31)); test_signed(-0x500000000i64, 32, Some(34)); test_signed(-0x500000000i64, 33, Some(34)); test_signed(-0x500000000i64, 34, Some(34)); test_signed(-0x500000000i64, 35, None); test_signed(-0x500000000i64, 100, None); test_signed(-0x500000000i128, 0, Some(0)); test_signed(-0x500000000i128, 20, Some(20)); test_signed(-0x500000000i128, 31, Some(31)); test_signed(-0x500000000i128, 32, Some(34)); test_signed(-0x500000000i128, 33, Some(34)); test_signed(-0x500000000i128, 34, Some(34)); test_signed(-0x500000000i128, 35, None); test_signed(-0x500000000i128, 100, None); } fn properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let result = n.index_of_next_false_bit(u).unwrap(); assert!(result >= u); assert!(!n.get_bit(result)); assert_eq!(result == u, !n.get_bit(u)); assert_eq!( (!n).index_of_next_true_bit(u), if result < T::WIDTH { Some(result) } else { None } ); }); unsigned_gen::().test_properties(|n| { assert_eq!( n.index_of_next_false_bit(0), Some(TrailingZeros::trailing_zeros(!n)) ); }); unsigned_gen::().test_properties(|u| { assert_eq!(T::ZERO.index_of_next_false_bit(u), Some(u)); }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let result = n.index_of_next_false_bit(u); assert_eq!( result.is_some(), if u >= T::WIDTH { n >= T::ZERO } else { n | T::low_mask(u) != T::NEGATIVE_ONE } ); if let Some(result) = result { assert!(result >= u); assert!(!n.get_bit(result)); assert_eq!(result == u, !n.get_bit(u)); } assert_eq!((!n).index_of_next_true_bit(u), result); }); signed_gen_var_3::().test_properties(|n| { assert_eq!( n.index_of_next_false_bit(0), Some(TrailingZeros::trailing_zeros(!n)) ); }); unsigned_gen::().test_properties(|u| { assert_eq!(T::ZERO.index_of_next_false_bit(u), Some(u)); assert_eq!(T::NEGATIVE_ONE.index_of_next_false_bit(u), None); }); } #[test] fn index_of_next_false_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/bit_scan/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::test_util::generators::{ signed_gen_var_3, signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_gen_var_1, unsigned_pair_gen_var_2, }; #[test] pub fn test_index_of_next_true_bit() { fn test_unsigned(x: T, start: u64, out: Option) { assert_eq!(x.index_of_next_true_bit(start), out); } test_unsigned(0xb00000000u64, 0, Some(32)); test_unsigned(0xb00000000u64, 20, Some(32)); test_unsigned(0xb00000000u64, 31, Some(32)); test_unsigned(0xb00000000u64, 32, Some(32)); test_unsigned(0xb00000000u64, 33, Some(33)); test_unsigned(0xb00000000u64, 34, Some(35)); test_unsigned(0xb00000000u64, 35, Some(35)); test_unsigned(0xb00000000u64, 36, None); test_unsigned(0xb00000000u64, 100, None); test_unsigned(0xb00000000u128, 0, Some(32)); test_unsigned(0xb00000000u128, 20, Some(32)); test_unsigned(0xb00000000u128, 31, Some(32)); test_unsigned(0xb00000000u128, 32, Some(32)); test_unsigned(0xb00000000u128, 33, Some(33)); test_unsigned(0xb00000000u128, 34, Some(35)); test_unsigned(0xb00000000u128, 35, Some(35)); test_unsigned(0xb00000000u128, 36, None); test_unsigned(0xb00000000u128, 100, None); fn test_signed(x: T, start: u64, out: Option) { assert_eq!(x.index_of_next_true_bit(start), out); } test_signed(-0x500000000i64, 0, Some(32)); test_signed(-0x500000000i64, 20, Some(32)); test_signed(-0x500000000i64, 31, Some(32)); test_signed(-0x500000000i64, 32, Some(32)); test_signed(-0x500000000i64, 33, Some(33)); test_signed(-0x500000000i64, 34, Some(35)); test_signed(-0x500000000i64, 35, Some(35)); test_signed(-0x500000000i64, 36, Some(36)); test_signed(-0x500000000i64, 100, Some(100)); test_signed(-0x500000000i128, 0, Some(32)); test_signed(-0x500000000i128, 20, Some(32)); test_signed(-0x500000000i128, 31, Some(32)); test_signed(-0x500000000i128, 32, Some(32)); test_signed(-0x500000000i128, 33, Some(33)); test_signed(-0x500000000i128, 34, Some(35)); test_signed(-0x500000000i128, 35, Some(35)); test_signed(-0x500000000i128, 36, Some(36)); test_signed(-0x500000000i128, 100, Some(100)); } fn properties_helper_unsigned() { unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let result = n.index_of_next_true_bit(u); assert_eq!(result.is_some(), u < n.significant_bits()); if let Some(result) = result { assert!(result >= u); assert!(n.get_bit(result)); assert_eq!(result == u, n.get_bit(u)); } }); unsigned_gen_var_1::().test_properties(|n| { assert_eq!( n.index_of_next_true_bit(0), Some(TrailingZeros::trailing_zeros(n)) ); }); unsigned_gen::().test_properties(|u| { assert_eq!(T::ZERO.index_of_next_true_bit(u), None); }); } fn properties_helper_signed() { signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let result = n.index_of_next_true_bit(u); assert_eq!( result.is_some(), if u >= T::WIDTH { n < T::ZERO } else { n >> u != T::ZERO } ); if let Some(result) = result { assert!(result >= u); assert!(n.get_bit(result)); assert_eq!(result == u, n.get_bit(u)); } assert_eq!((!n).index_of_next_false_bit(u), result); }); signed_gen_var_3::().test_properties(|n| { assert_eq!( n.index_of_next_true_bit(0), Some(TrailingZeros::trailing_zeros(n)) ); }); unsigned_gen::().test_properties(|u| { assert_eq!(T::ZERO.index_of_next_true_bit(u), None); assert_eq!(T::NEGATIVE_ONE.index_of_next_true_bit(u), Some(u)); }); } #[test] fn index_of_next_true_bit_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_signeds!(properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/get_highest_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; #[test] pub fn test_get_highest_bit() { assert_eq!(0u8.get_highest_bit(), false); assert_eq!(123u32.get_highest_bit(), false); assert_eq!(4000000000u32.get_highest_bit(), true); assert_eq!(2000000000i32.get_highest_bit(), false); assert_eq!((-2000000000i32).get_highest_bit(), true); } fn get_highest_bit_properties_helper_unsigned() { unsigned_gen::().test_properties(|u| { assert_eq!(u.get_highest_bit(), u >= T::power_of_2(T::WIDTH - 1)); }); } fn get_highest_bit_properties_helper_signed() { signed_gen::().test_properties(|i| { assert_eq!(i.get_highest_bit(), i < T::ZERO); }); } #[test] fn get_highest_bit_properties() { apply_fn_to_unsigneds!(get_highest_bit_properties_helper_unsigned); apply_fn_to_signeds!(get_highest_bit_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::{CountOnes, CountZeros}; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_2, signed_gen_var_4, signed_pair_gen, signed_pair_gen_var_1, signed_triple_gen_var_3, unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19, }; #[test] pub fn test_hamming_distance() { fn test(x: T, y: T, out: u64) { assert_eq!(x.hamming_distance(y), out); } test(123u16, 456u16, 6); test(0xffffu32, 0xffff0000u32, 32); test(0xffffu32, u32::MAX, 16); test(0xffff0000u32, u32::MAX, 16); } #[test] pub fn test_checked_hamming_distance() { fn test(x: T, y: T, out: Option) { assert_eq!(x.checked_hamming_distance(y), out); } test(123i32, 456i32, Some(6)); test(-123i32, -456i32, Some(7)); test(0i8, 127i8, Some(7)); test(0i8, -1i8, None); test(-1i8, -128i8, Some(7)); test(0i128, i128::MAX, Some(127)); test(0i128, -1i128, None); test(-1i128, i128::MIN, Some(127)); test(0xffffi32, 0x7fff0000i32, Some(31)); test(0xffffi32, i32::MAX, Some(15)); test(0x7fff0000i32, i32::MAX, Some(16)); } fn hamming_distance_properties_helper() { unsigned_pair_gen_var_27::().test_properties(|(x, y)| { let distance = x.hamming_distance(y); assert_eq!(y.hamming_distance(x), distance); assert_eq!(distance == 0, x == y); assert_eq!(CountOnes::count_ones(x ^ y), distance); assert_eq!((!x).hamming_distance(!y), distance); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert!(x.hamming_distance(z) <= x.hamming_distance(y) + y.hamming_distance(z)); }); unsigned_gen::().test_properties(|x| { assert_eq!(x.hamming_distance(x), 0); assert_eq!(x.hamming_distance(!x), T::WIDTH); assert_eq!(x.hamming_distance(T::ZERO), CountOnes::count_ones(x)); assert_eq!(T::ZERO.hamming_distance(x), CountOnes::count_ones(x)); }); } #[test] fn hamming_distance_properties() { apply_fn_to_unsigneds!(hamming_distance_properties_helper); } fn checked_hamming_distance_properties_helper() { signed_pair_gen::().test_properties(|(x, y)| { let distance = x.checked_hamming_distance(y); assert_eq!(y.checked_hamming_distance(x), distance); assert_eq!(distance == Some(0), x == y); assert_eq!((!x).checked_hamming_distance(!y), distance); }); signed_pair_gen_var_1::().test_properties(|(x, y)| { let distance = x.checked_hamming_distance(y).unwrap(); assert_eq!(y.checked_hamming_distance(x).unwrap(), distance); assert_eq!(distance == 0, x == y); assert_eq!(CountOnes::count_ones(x ^ y), distance); assert_eq!((!x).checked_hamming_distance(!y).unwrap(), distance); }); signed_triple_gen_var_3::().test_properties(|(x, y, z)| { assert!( x.checked_hamming_distance(z).unwrap() <= x.checked_hamming_distance(y).unwrap() + y.checked_hamming_distance(z).unwrap() ); }); signed_gen::().test_properties(|x| { assert_eq!(x.checked_hamming_distance(x), Some(0)); assert_eq!(x.checked_hamming_distance(!x), None); }); signed_gen_var_2::().test_properties(|x| { assert_eq!( x.checked_hamming_distance(T::ZERO), Some(CountOnes::count_ones(x)) ); assert_eq!( T::ZERO.checked_hamming_distance(x), Some(CountOnes::count_ones(x)) ); }); signed_gen_var_4::().test_properties(|x| { assert_eq!( x.checked_hamming_distance(T::NEGATIVE_ONE), Some(CountZeros::count_zeros(x)) ); assert_eq!( T::NEGATIVE_ONE.checked_hamming_distance(x), Some(CountZeros::count_zeros(x)) ); }); } #[test] fn checked_hamming_distance_properties() { apply_fn_to_signeds!(checked_hamming_distance_properties_helper); } ================================================ FILE: malachite-base/tests/num/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::unsigned_gen_var_9; use std::panic::catch_unwind; fn low_mask_primitive_helper() { let test = |bits, out| { assert_eq!(T::low_mask(bits), out); }; test(0, T::ZERO); test(1, T::ONE); test(2, T::exact_from(3)); test(3, T::exact_from(7)); } fn low_mask_unsigned_helper() { let test = |bits, out| { assert_eq!(T::low_mask(bits), out); }; test(T::WIDTH - 1, (T::ONE << (T::WIDTH - 1)) - T::ONE); test(T::WIDTH, T::MAX); } fn low_mask_signed_helper() { let test = |bits, out| { assert_eq!(T::low_mask(bits), out); }; test(T::WIDTH - 1, T::MAX); test(T::WIDTH, T::NEGATIVE_ONE); } #[test] fn test_low_mask() { apply_fn_to_primitive_ints!(low_mask_primitive_helper); apply_fn_to_unsigneds!(low_mask_unsigned_helper); apply_fn_to_signeds!(low_mask_signed_helper); } fn low_mask_fail_helper() { assert_panic!(T::low_mask(T::WIDTH + 1)); } #[test] fn low_mask_fail() { apply_fn_to_primitive_ints!(low_mask_fail_helper); } fn low_mask_properties_helper_unsigned() { unsigned_gen_var_9::().test_properties(|bits| { let n = T::low_mask(bits); assert_eq!(n.count_ones(), bits); assert_eq!(n.index_of_next_false_bit(0), Some(bits)); }); } fn low_mask_properties_helper_signed() { unsigned_gen_var_9::().test_properties(|bits| { let n = T::low_mask(bits); assert_eq!(n.count_ones(), bits); assert_eq!( n.index_of_next_false_bit(0), if bits == T::WIDTH { None } else { Some(bits) } ); }); } #[test] fn low_mask_properties() { apply_fn_to_unsigneds!(low_mask_properties_helper_unsigned); apply_fn_to_signeds!(low_mask_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/not_assign.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; fn not_assign_helper() { let test = |n: T| { let mut x = n; x.not_assign(); assert_eq!(x, !n); }; test(T::ZERO); test(T::ONE); test(T::exact_from(2)); test(T::exact_from(3)); test(T::exact_from(4)); test(T::exact_from(5)); test(T::exact_from(100)); test(T::exact_from(63)); test(T::exact_from(64)); test(T::MIN); test(T::MAX); } #[test] fn test_not_assign() { apply_fn_to_primitive_ints!(not_assign_helper); } fn not_assign_properties_helper_unsigned() { unsigned_gen::().test_properties(|u| { let mut x = u; x.not_assign(); assert_eq!(x, !u); x.not_assign(); assert_eq!(x, u); }); } fn not_assign_properties_helper_signed() { signed_gen::().test_properties(|i| { let mut x = i; x.not_assign(); assert_eq!(x, !i); x.not_assign(); assert_eq!(x, i); }); } #[test] fn not_assign_properties() { apply_fn_to_unsigneds!(not_assign_properties_helper_unsigned); apply_fn_to_signeds!(not_assign_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; fn significant_bits_helper() { let test = |n, out| { assert_eq!(T::exact_from(n).significant_bits(), out); }; test(0, 0); test(1, 1); test(2, 2); test(3, 2); test(4, 3); test(5, 3); test(100, 7); test(63, 6); test(64, 7); } fn significant_bits_helper_unsigned() { let test = |n: T, out: u64| { assert_eq!(n.significant_bits(), out); }; test(T::MAX, T::WIDTH); } fn significant_bits_helper_signed() { let test = |n: T, out: u64| { assert_eq!(n.significant_bits(), out); }; test(T::MAX, T::WIDTH - 1); test(T::MIN, T::WIDTH); } #[test] fn test_significant_bits() { apply_fn_to_primitive_ints!(significant_bits_helper); apply_fn_to_unsigneds!(significant_bits_helper_unsigned); apply_fn_to_signeds!(significant_bits_helper_signed); } fn significant_bits_properties_helper_unsigned() { unsigned_gen::().test_properties(|u| { let significant_bits = u.significant_bits(); assert!(significant_bits <= T::WIDTH); assert_eq!(significant_bits == 0, u == T::ZERO); if u != T::ZERO { assert_eq!(significant_bits, u.floor_log_base_2() + 1); } }); } fn significant_bits_properties_helper_signed() { signed_gen::().test_properties(|i| { let significant_bits = i.significant_bits(); assert!(significant_bits <= T::WIDTH); assert_eq!(significant_bits == 0, i == T::ZERO); assert_eq!(significant_bits == T::WIDTH, i == T::MIN); assert_eq!(i.wrapping_neg().significant_bits(), significant_bits); }); } #[test] fn significant_bits_properties() { apply_fn_to_unsigneds!(significant_bits_properties_helper_unsigned); apply_fn_to_signeds!(significant_bits_properties_helper_signed); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_natural_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_natural_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_natural_signeds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_natural_signeds::(EXAMPLE_SEED, um_numerator, um_denominator), T::ZERO, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_natural_signeds() { // i64, um = 1 / 64 let values = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; let common_values = &[(0, 984537), (1, 15210), (2, 253)]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.015624999999999944), standard_deviation: NiceFloat(0.12597277731716458), skewness: NiceFloat(8.186292482887549), excess_kurtosis: NiceFloat(69.01538461538773), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.015716000000000004), standard_deviation: NiceFloat(0.1263923388462427), skewness: NiceFloat(8.160460378454996), excess_kurtosis: NiceFloat(68.31033619043119), }; geometric_random_natural_signeds_helper::( 1, 64, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 1 let values = &[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, 0, 0, 2, 2, 0, 0, 1, 0, 3, 1]; let common_values = &[ (0, 500085), (1, 249510), (2, 125328), (3, 62428), (4, 31280), (5, 15676), (6, 7853), (7, 3994), (8, 1932), (9, 942), ]; let pop_median = (0, Some(1)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0006159999999573), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.1140569440125403), excess_kurtosis: NiceFloat(6.4341815215340805), }; geometric_random_natural_signeds_helper::( 1, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 12345/10000 let values = &[1, 3, 8, 2, 2, 0, 1, 1, 0, 0, 0, 0, 1, 1, 7, 0, 0, 3, 0, 0]; let common_values = &[ (0, 446911), (1, 246858), (2, 137217), (3, 75488), (4, 41605), (5, 23149), (6, 12981), (7, 7024), (8, 3848), (9, 2206), ]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.2344999999999997), standard_deviation: NiceFloat(1.6608703290744884), skewness: NiceFloat(2.088663960860256), excess_kurtosis: NiceFloat(6.362517141396456), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.2380129999999983), standard_deviation: NiceFloat(1.6649767517832197), skewness: NiceFloat(2.0942793135700466), excess_kurtosis: NiceFloat(6.469904862333731), }; geometric_random_natural_signeds_helper::( 12345, 10000, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 64 let values = &[53, 90, 125, 70, 18, 41, 109, 5, 96, 93, 33, 18, 89, 6, 17, 1, 1, 2, 123, 6]; let common_values = &[ (0, 17832), (1, 17626), (2, 17520), (3, 16976), (4, 16636), (5, 16395), (6, 16282), (7, 16231), (8, 15823), (9, 15338), ]; let pop_median = (36, None); let sample_median = (36, None); let pop_moment_stats = MomentStats { mean: NiceFloat(43.60377071780361), standard_deviation: NiceFloat(33.66417209656191), skewness: NiceFloat(0.6750025251723596), excess_kurtosis: NiceFloat(-0.5593715461161066), }; let sample_moment_stats = MomentStats { mean: NiceFloat(43.58636099999891), standard_deviation: NiceFloat(33.66410490492275), skewness: NiceFloat(0.6756300365723926), excess_kurtosis: NiceFloat(-0.5577628868956519), }; geometric_random_natural_signeds_helper::( 64, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 1000 let values = &[24, 115, 120, 25, 104, 87, 80, 112, 37, 35, 68, 76, 40, 37, 117, 65, 124, 119, 0, 91]; let common_values = &[ (0, 8435), (4, 8343), (1, 8333), (5, 8306), (18, 8302), (8, 8298), (11, 8272), (2, 8267), (7, 8259), (3, 8248), ]; let pop_median = (61, None); let sample_median = (61, None); let pop_moment_stats = MomentStats { mean: NiceFloat(62.13580429363961), standard_deviation: NiceFloat(36.93417606567501), skewness: NiceFloat(0.044319234592297266), excess_kurtosis: NiceFloat(-1.197434568717292), }; let sample_moment_stats = MomentStats { mean: NiceFloat(62.1484240000004), standard_deviation: NiceFloat(36.919219186555864), skewness: NiceFloat(0.04244530182494719), excess_kurtosis: NiceFloat(-1.196858045789015), }; geometric_random_natural_signeds_helper::( 1000, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_natural_signeds_fail_helper() { assert_panic!(geometric_random_natural_signeds::(EXAMPLE_SEED, 0, 1)); assert_panic!(geometric_random_natural_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_natural_signeds::( EXAMPLE_SEED, u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_natural_signeds_fail() { apply_fn_to_signeds!(geometric_random_natural_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_negative_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_negative_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, negative_truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_negative_signeds_helper< U: CheckedToF64 + PrimitiveUnsigned, S: CheckedToF64 + PrimitiveSigned + UnsignedAbs + WrappingFrom, >( abs_um_numerator: u64, abs_um_denominator: u64, expected_values: &[S], expected_common_values: &[(S, usize)], expected_pop_median: (S, Option), expected_sample_median: (S, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { negative_truncated_geometric_dist_assertions( geometric_random_negative_signeds::(EXAMPLE_SEED, abs_um_numerator, abs_um_denominator), S::NEGATIVE_ONE, S::MIN, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_negative_signeds() { // i64, um = -65 / 64 let values = &[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2]; let common_values = &[(-1, 984537), (-2, 15210), (-3, 253)]; let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-1.015625), standard_deviation: NiceFloat(0.12597277731716458), skewness: NiceFloat(-8.186292482887549), excess_kurtosis: NiceFloat(69.01538461538773), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0157160000000027), standard_deviation: NiceFloat(0.12639233884624257), skewness: NiceFloat(-8.160460378454992), excess_kurtosis: NiceFloat(68.31033619043166), }; geometric_random_negative_signeds_helper::<_, i64>( 65, 64, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = -12345/10000 let values = &[-1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1]; let common_values = &[ (-1, 809395), (-2, 154707), (-3, 29037), (-4, 5577), (-5, 1053), (-6, 185), (-7, 40), (-8, 5), (-9, 1), ]; let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-1.2345), standard_deviation: NiceFloat(0.538042981554448), skewness: NiceFloat(-2.730265146765687), excess_kurtosis: NiceFloat(9.45434777164341), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1.2349320000000084), standard_deviation: NiceFloat(0.5376590410783139), skewness: NiceFloat(-2.716807176148366), excess_kurtosis: NiceFloat(9.308727522629948), }; geometric_random_negative_signeds_helper::<_, i64>( 12345, 10000, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = -2 let values = &[-2, -1, -1, -4, -5, -5, -2, -1, -1, -2, -1, -1, -3, -3, -1, -1, -2, -1, -4, -2]; let common_values = &[ (-1, 500085), (-2, 249510), (-3, 125328), (-4, 62428), (-5, 31280), (-6, 15676), (-7, 7853), (-8, 3994), (-9, 1932), (-10, 942), ]; let pop_median = (-2, Some(-1)); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-2.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(-2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-2.0006159999998947), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(-2.114056944012543), excess_kurtosis: NiceFloat(6.4341815215340645), }; geometric_random_negative_signeds_helper::<_, i64>( 2, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = -64 let values = &[ -53, -56, -71, -20, -113, -87, -55, -44, -4, -17, -44, -36, -5, -25, -55, -9, -114, -24, -15, -76, ]; let common_values = &[ (-1, 18323), (-2, 17814), (-3, 17620), (-4, 17269), (-5, 17057), (-6, 16684), (-7, 16509), (-8, 16164), (-9, 15914), (-10, 15665), ]; let pop_median = (-37, None); let sample_median = (-37, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-44.32782748571844), standard_deviation: NiceFloat(33.57033730453578), skewness: NiceFloat(-0.6852077716881376), excess_kurtosis: NiceFloat(-0.5394700086619175), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-44.31098999999839), standard_deviation: NiceFloat(33.572216166252275), skewness: NiceFloat(-0.6830069791725721), excess_kurtosis: NiceFloat(-0.5435066974705061), }; geometric_random_negative_signeds_helper::<_, i8>( 64, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = -1000 let values = &[ -25, -111, -118, -26, -101, -88, -81, -112, -38, -36, -68, -76, -41, -36, -118, -66, -123, -120, -128, -92, ]; let common_values = &[ (-1, 8409), (-6, 8360), (-2, 8357), (-7, 8328), (-5, 8309), (-14, 8300), (-22, 8268), (-12, 8262), (-18, 8254), (-9, 8249), ]; let pop_median = (-62, None); let sample_median = (-63, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-63.134440160748206), standard_deviation: NiceFloat(36.934145822824206), skewness: NiceFloat(-0.04436357375743275), excess_kurtosis: NiceFloat(-1.1974286638022889), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-63.15733700000316), standard_deviation: NiceFloat(36.91734106024568), skewness: NiceFloat(-0.04254845146202895), excess_kurtosis: NiceFloat(-1.1968222027376492), }; geometric_random_negative_signeds_helper::<_, i8>( 1000, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_negative_signeds_fail_helper() { assert_panic!(geometric_random_negative_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_negative_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn geometric_random_negative_signeds_fail() { apply_fn_to_signeds!(geometric_random_negative_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_nonzero_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_nonzero_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, double_nonzero_truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_nonzero_signeds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_abs_mean: NiceFloat, expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { double_nonzero_truncated_geometric_dist_assertions( geometric_random_nonzero_signeds::(EXAMPLE_SEED, um_numerator, um_denominator), T::MIN, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_abs_mean, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_nonzero_signeds() { // i64, um = 65 / 64 let values = &[-1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1]; let common_values = &[(1, 492630), (-1, 491792), (2, 7695), (-2, 7623), (-3, 130), (3, 128), (4, 1), (-4, 1)]; let abs_mean = NiceFloat(1.0158400000000025); let pop_median = (-1, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(1.0234076808633008), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.863403263403264), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.0009760000000000123), standard_deviation: NiceFloat(1.0237422016660624), skewness: NiceFloat(-0.0015925396363277624), excess_kurtosis: NiceFloat(-1.8611455716465144), }; geometric_random_nonzero_signeds_helper::( 65, 64, values, common_values, abs_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 12345/10000 let values = &[-3, -1, -1, 2, -1, 1, -1, -1, -1, 1, 3, 2, -2, -1, 1, -1, -2, -1, -1, -1]; let common_values = &[ (1, 405592), (-1, 404788), (2, 76970), (-2, 76657), (-3, 14659), (3, 14550), (-4, 2798), (4, 2694), (5, 525), (-5, 504), ]; let abs_mean = NiceFloat(1.2340139999999655); let pop_median = (-1, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(1.3466553011071538), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-0.5329853284885049), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.0006879999999999908), standard_deviation: NiceFloat(1.3459834093804237), skewness: NiceFloat(-0.004555831860856982), excess_kurtosis: NiceFloat(-0.5314899892072216), }; geometric_random_nonzero_signeds_helper::( 12345, 10000, values, common_values, abs_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 2 let values = &[-2, -2, -2, 2, -3, 2, -1, -1, -1, 1, 1, 1, -2, -1, 1, -2, -1, -1, -2, -1]; let common_values = &[ (1, 250123), (-1, 250114), (2, 125321), (-2, 124779), (3, 62655), (-3, 62429), (4, 31220), (-4, 30972), (-5, 15670), (5, 15610), ]; let abs_mean = NiceFloat(1.9985919999999855); let pop_median = (-1, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(2.449489742783178), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(1.166666666666667), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.0027099999999999395), standard_deviation: NiceFloat(2.4473305141166697), skewness: NiceFloat(0.003736776778462254), excess_kurtosis: NiceFloat(1.1584370930225818), }; geometric_random_nonzero_signeds_helper::( 2, 1, values, common_values, abs_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 64 let values = &[ -3, -45, -90, 30, -33, -38, -25, 15, 40, -20, 42, -34, -74, -110, -15, 12, -76, -2, -6, -76, ]; let common_values = &[ (1, 9067), (-1, 9026), (-2, 8948), (2, 8915), (-3, 8837), (3, 8719), (5, 8571), (4, 8530), (-4, 8430), (6, 8385), ]; let abs_mean = NiceFloat(44.16314300000121); let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.15631902384873833), standard_deviation: NiceFloat(55.4586923219402), skewness: NiceFloat(-0.006558922726586753), excess_kurtosis: NiceFloat(-0.4026097866721505), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.15813500000000466), standard_deviation: NiceFloat(55.40978289585497), skewness: NiceFloat(-0.008649136036163145), excess_kurtosis: NiceFloat(-0.39765880957469824), }; geometric_random_nonzero_signeds_helper::( 64, 1, values, common_values, abs_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 1000 let values = &[29, -58, 40, 58, 29, 21, -101, 50, 126, -3, 13, 22, 22, 69, 70, 62, -82, -67, 91, 87]; let common_values = &[ (3, 4314), (-1, 4293), (-4, 4243), (2, 4240), (10, 4233), (-12, 4223), (-26, 4220), (7, 4203), (-7, 4198), (-19, 4196), ]; let abs_mean = NiceFloat(62.86584099999888); let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.4706257221678366), standard_deviation: NiceFloat(72.86493046408025), skewness: NiceFloat(-0.0005545932485799438), excess_kurtosis: NiceFloat(-1.1684399210707623), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5576419999999735), standard_deviation: NiceFloat(72.84782263187428), skewness: NiceFloat(0.0014314361576379332), excess_kurtosis: NiceFloat(-1.1671979175710692), }; geometric_random_nonzero_signeds_helper::( 1000, 1, values, common_values, abs_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_nonzero_signeds_fail_helper() { assert_panic!(geometric_random_nonzero_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_nonzero_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn geometric_random_nonzero_signeds_fail() { apply_fn_to_signeds!(geometric_random_nonzero_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_positive_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_positive_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_positive_signeds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_positive_signeds::(EXAMPLE_SEED, um_numerator, um_denominator), T::ONE, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_positive_signeds() { // i64, um = 65 / 64 let values = &[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]; let common_values = &[(1, 984537), (2, 15210), (3, 253)]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.015625), standard_deviation: NiceFloat(0.12597277731716458), skewness: NiceFloat(8.186292482887549), excess_kurtosis: NiceFloat(69.01538461538773), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0157160000000027), standard_deviation: NiceFloat(0.12639233884624257), skewness: NiceFloat(8.160460378454992), excess_kurtosis: NiceFloat(68.31033619043166), }; geometric_random_positive_signeds_helper::( 65, 64, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 12345/10000 let values = &[1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1]; let common_values = &[ (1, 809395), (2, 154707), (3, 29037), (4, 5577), (5, 1053), (6, 185), (7, 40), (8, 5), (9, 1), ]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.2345), standard_deviation: NiceFloat(0.538042981554448), skewness: NiceFloat(2.730265146765687), excess_kurtosis: NiceFloat(9.45434777164341), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.2349320000000084), standard_deviation: NiceFloat(0.5376590410783139), skewness: NiceFloat(2.716807176148366), excess_kurtosis: NiceFloat(9.308727522629948), }; geometric_random_positive_signeds_helper::( 12345, 10000, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 2 let values = &[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, 1, 1, 3, 3, 1, 1, 2, 1, 4, 2]; let common_values = &[ (1, 500085), (2, 249510), (3, 125328), (4, 62428), (5, 31280), (6, 15676), (7, 7853), (8, 3994), (9, 1932), (10, 942), ]; let pop_median = (1, Some(2)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.0006159999998947), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.114056944012543), excess_kurtosis: NiceFloat(6.4341815215340645), }; geometric_random_positive_signeds_helper::( 2, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 64 let values = &[53, 56, 71, 20, 113, 87, 55, 44, 4, 17, 44, 36, 5, 25, 55, 9, 114, 24, 15, 76]; let common_values = &[ (1, 18322), (2, 17831), (3, 17675), (4, 17346), (5, 17077), (6, 16664), (7, 16584), (8, 16201), (9, 15917), (10, 15785), ]; let pop_median = (36, None); let sample_median = (36, None); let pop_moment_stats = MomentStats { mean: NiceFloat(44.12320959250907), standard_deviation: NiceFloat(33.35507189836844), skewness: NiceFloat(0.6800692970056713), excess_kurtosis: NiceFloat(-0.5495345339552125), }; let sample_moment_stats = MomentStats { mean: NiceFloat(44.11083399999909), standard_deviation: NiceFloat(33.35932545284804), skewness: NiceFloat(0.6778762972570164), excess_kurtosis: NiceFloat(-0.5537033314075828), }; geometric_random_positive_signeds_helper::( 64, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 1000 let values = &[29, 119, 12, 28, 113, 91, 84, 117, 46, 36, 71, 83, 43, 50, 127, 69, 5, 124, 10, 95]; let common_values = &[ (3, 8464), (11, 8429), (9, 8411), (26, 8407), (6, 8397), (12, 8387), (2, 8383), (8, 8363), (1, 8326), (14, 8313), ]; let pop_median = (62, None); let sample_median = (62, None); let pop_moment_stats = MomentStats { mean: NiceFloat(62.65568926722266), standard_deviation: NiceFloat(36.64581386503865), skewness: NiceFloat(0.04401709622102498), excess_kurtosis: NiceFloat(-1.1974732777225838), }; let sample_moment_stats = MomentStats { mean: NiceFloat(62.68774500000057), standard_deviation: NiceFloat(36.63525108357442), skewness: NiceFloat(0.041814478066591894), excess_kurtosis: NiceFloat(-1.1973932602500912), }; geometric_random_positive_signeds_helper::( 1000, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_positive_signeds_fail_helper() { assert_panic!(geometric_random_positive_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_positive_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn geometric_random_positive_signeds_fail() { apply_fn_to_signeds!(geometric_random_positive_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_positive_unsigneds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_positive_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_positive_unsigneds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_positive_unsigneds::(EXAMPLE_SEED, um_numerator, um_denominator), T::ONE, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_positive_unsigneds() { // u64, um = 65 / 64 let values = &[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]; let common_values = &[(1, 984537), (2, 15210), (3, 253)]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.015625), standard_deviation: NiceFloat(0.12597277731716458), skewness: NiceFloat(8.186292482887549), excess_kurtosis: NiceFloat(69.01538461538773), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0157160000000027), standard_deviation: NiceFloat(0.12639233884624257), skewness: NiceFloat(8.160460378454992), excess_kurtosis: NiceFloat(68.31033619043166), }; geometric_random_positive_unsigneds_helper::( 65, 64, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, um = 12345/10000 let values = &[1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1]; let common_values = &[ (1, 809395), (2, 154707), (3, 29037), (4, 5577), (5, 1053), (6, 185), (7, 40), (8, 5), (9, 1), ]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.2345), standard_deviation: NiceFloat(0.538042981554448), skewness: NiceFloat(2.730265146765687), excess_kurtosis: NiceFloat(9.45434777164341), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.2349320000000084), standard_deviation: NiceFloat(0.5376590410783139), skewness: NiceFloat(2.716807176148366), excess_kurtosis: NiceFloat(9.308727522629948), }; geometric_random_positive_unsigneds_helper::( 12345, 10000, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, um = 2 let values = &[2, 1, 1, 4, 5, 5, 2, 1, 1, 2, 1, 1, 3, 3, 1, 1, 2, 1, 4, 2]; let common_values = &[ (1, 500085), (2, 249510), (3, 125328), (4, 62428), (5, 31280), (6, 15676), (7, 7853), (8, 3994), (9, 1932), (10, 942), ]; let pop_median = (1, Some(2)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.0006159999998947), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.114056944012543), excess_kurtosis: NiceFloat(6.4341815215340645), }; geometric_random_positive_unsigneds_helper::( 2, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, um = 64 let values = &[53, 56, 71, 20, 113, 87, 55, 44, 4, 17, 44, 36, 5, 25, 55, 9, 114, 24, 15, 76]; let common_values = &[ (1, 16172), (2, 15695), (3, 15520), (4, 15241), (5, 15089), (6, 14676), (7, 14543), (8, 14211), (9, 13961), (10, 13836), ]; let pop_median = (43, None); let sample_median = (43, None); let pop_moment_stats = MomentStats { mean: NiceFloat(59.318470051671945), standard_deviation: NiceFloat(53.06875861106282), skewness: NiceFloat(1.275790253790931), excess_kurtosis: NiceFloat(1.21378930742857), }; let sample_moment_stats = MomentStats { mean: NiceFloat(59.312081000000006), standard_deviation: NiceFloat(53.01872774251563), skewness: NiceFloat(1.2706951236419683), excess_kurtosis: NiceFloat(1.1982916278084028), }; geometric_random_positive_unsigneds_helper::( 64, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, um = 1000 let values = &[27, 115, 1, 27, 107, 217, 210, 242, 42, 36, 197, 207, 42, 43, 250, 195, 255, 122, 5, 221]; let common_values = &[ (6, 4501), (2, 4490), (8, 4461), (21, 4453), (10, 4449), (3, 4446), (11, 4440), (13, 4422), (12, 4415), (25, 4407), ]; let pop_median = (120, None); let sample_median = (120, None); let pop_moment_stats = MomentStats { mean: NiceFloat(122.58449448192029), standard_deviation: NiceFloat(73.49201840569208), skewness: NiceFloat(0.08835569448221604), excess_kurtosis: NiceFloat(-1.1892531716440173), }; let sample_moment_stats = MomentStats { mean: NiceFloat(122.63144799999775), standard_deviation: NiceFloat(73.49633071884523), skewness: NiceFloat(0.08793356388157667), excess_kurtosis: NiceFloat(-1.1900100973541539), }; geometric_random_positive_unsigneds_helper::( 1000, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_positive_unsigneds_fail_helper() { assert_panic!(geometric_random_positive_unsigneds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_positive_unsigneds::(EXAMPLE_SEED, 2, 3)); } #[test] fn geometric_random_positive_unsigneds_fail() { apply_fn_to_unsigneds!(geometric_random_positive_unsigneds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_signed_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_signed_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, double_truncated_geometric_dist_assertions, negative_truncated_geometric_dist_assertions, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_signed_inclusive_range_helper< U: CheckedToF64 + PrimitiveUnsigned, S: CheckedToF64 + PrimitiveSigned + UnsignedAbs + WrappingFrom<::Output>, >( a: S, b: S, abs_um_numerator: u64, abs_um_denominator: u64, expected_values: &[S], expected_common_values: &[(S, usize)], expected_natural_mean: Option>, expected_pop_median: (S, Option), expected_sample_median: (S, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let xs = geometric_random_signed_inclusive_range::( EXAMPLE_SEED, a, b, abs_um_numerator, abs_um_denominator, ); if a >= S::ZERO { assert!(expected_natural_mean.is_none()); truncated_geometric_dist_assertions( xs, a, b, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } else if b <= S::ONE { assert!(expected_natural_mean.is_none()); negative_truncated_geometric_dist_assertions( xs, b, a, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } else { double_truncated_geometric_dist_assertions( xs, a, b, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_natural_mean.unwrap(), expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } } #[test] fn test_geometric_random_signed_inclusive_range() { // i8, 5, 5, um = 10 (um is irrelevant here) let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; geometric_random_signed_inclusive_range_helper::<_, i8>( 5, 5, 10, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16, 1, 6, um = 3 let values = &[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, 4, 3, 3, 2, 4, 2, 5, 1, 5, 4]; let common_values = &[(1, 365286), (2, 243368), (3, 162008), (4, 108422), (5, 72522), (6, 48394)]; let pop_median = (2, None); let sample_median = (2, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.4225563909774435), standard_deviation: NiceFloat(1.4838791137635392), skewness: NiceFloat(0.8646161570662343), excess_kurtosis: NiceFloat(-0.2650814667635877), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.4247080000000336), standard_deviation: NiceFloat(1.4858025852532333), skewness: NiceFloat(0.8627980859656847), excess_kurtosis: NiceFloat(-0.27185507049284263), }; geometric_random_signed_inclusive_range_helper::<_, i16>( 1, 6, 3, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32, 10, 19, um = 30 let values = &[18, 13, 12, 14, 11, 14, 16, 12, 12, 12, 11, 11, 12, 16, 10, 12, 13, 17, 19, 18]; let common_values = &[ (10, 123089), (11, 117792), (12, 111339), (13, 106927), (14, 102009), (15, 96319), (16, 92170), (17, 86830), (18, 83895), (19, 79630), ]; let pop_median = (14, None); let sample_median = (14, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.099085006908673), standard_deviation: NiceFloat(2.8551273967321666), skewness: NiceFloat(0.17141556508548922), excess_kurtosis: NiceFloat(-1.1843121480092598), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.099542000000508), standard_deviation: NiceFloat(2.8550785526337443), skewness: NiceFloat(0.17230969046968866), excess_kurtosis: NiceFloat(-1.183362703825652), }; geometric_random_signed_inclusive_range_helper::<_, i32>( 10, 19, 30, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, -20, -11, um = 30 let values = &[ -17, -14, -12, -14, -12, -15, -16, -13, -12, -13, -19, -11, -11, -17, -11, -19, -13, -16, -20, -19, ]; let common_values = &[ (-11, 124528), (-12, 118758), (-13, 112479), (-14, 107215), (-15, 101400), (-16, 96120), (-17, 91622), (-18, 86347), (-19, 82852), (-20, 78679), ]; let pop_median = (-15, None); let sample_median = (-15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-15.078692813090253), standard_deviation: NiceFloat(2.853334884793182), skewness: NiceFloat(-0.18019334055480088), excess_kurtosis: NiceFloat(-1.1801134249293568), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-15.076649000000186), standard_deviation: NiceFloat(2.8539222266332365), skewness: NiceFloat(-0.18245914264956217), excess_kurtosis: NiceFloat(-1.1796684829530097), }; geometric_random_signed_inclusive_range_helper::<_, i64>( -20, -11, 30, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, -100, 99, um = 30 let values = &[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, 14, 48, -61, -60, 21, -55, -69, -26, -44, 6]; let common_values = &[ (0, 16949), (-1, 16668), (1, 16340), (-2, 15893), (2, 15885), (-3, 15421), (3, 15350), (4, 14937), (-4, 14913), (5, 14576), ]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.06416536680865222), standard_deviation: NiceFloat(35.06981580711165), skewness: NiceFloat(-0.009387535787624381), excess_kurtosis: NiceFloat(0.331207115680745), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.031523999999998706), standard_deviation: NiceFloat(34.99870187802065), skewness: NiceFloat(-0.009330685977635587), excess_kurtosis: NiceFloat(0.33242667080464994), }; geometric_random_signed_inclusive_range_helper::<_, i8>( -100, 99, 30, 1, values, common_values, Some(NiceFloat(26.065423999999997)), pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, i8::MIN, i8::MAX, um = 30 let values = &[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, 14, 48, -61, -60, 21, -55, -69, -26, -44, 6]; let common_values = &[ (0, 16612), (1, 16170), (-1, 16142), (2, 15527), (-2, 15450), (-3, 15004), (3, 14998), (4, 14694), (-4, 14522), (5, 14226), ]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.03203944371479178), standard_deviation: NiceFloat(38.608914337623204), skewness: NiceFloat(-0.006631455473213565), excess_kurtosis: NiceFloat(0.885187645693085), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.006649000000000714), standard_deviation: NiceFloat(38.52435386760686), skewness: NiceFloat(-0.002824821494549616), excess_kurtosis: NiceFloat(0.8938770112620578), }; geometric_random_signed_inclusive_range_helper::<_, i8>( i8::MIN, i8::MAX, 30, 1, values, common_values, Some(NiceFloat(28.03693899999907)), pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_signed_inclusive_range_fail_helper() { assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::TWO, T::ONE, 1, 1 )); assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::ONE, T::ZERO, 1, 1 )); assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), 1, 0 )); assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::ONE, T::exact_from(10), 9, 10 )); assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::exact_from(-10), T::NEGATIVE_ONE, 9, 10 )); assert_panic!(geometric_random_signed_inclusive_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_signed_inclusive_range_fail() { apply_fn_to_signeds!(geometric_random_signed_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_signed_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_signed_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, double_truncated_geometric_dist_assertions, negative_truncated_geometric_dist_assertions, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_signed_range_helper< U: CheckedToF64 + PrimitiveUnsigned, S: CheckedToF64 + PrimitiveSigned + UnsignedAbs + WrappingFrom<::Output>, >( a: S, b: S, abs_um_numerator: u64, abs_um_denominator: u64, expected_values: &[S], expected_common_values: &[(S, usize)], expected_natural_mean: Option>, expected_pop_median: (S, Option), expected_sample_median: (S, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let xs = geometric_random_signed_range::( EXAMPLE_SEED, a, b, abs_um_numerator, abs_um_denominator, ); if a >= S::ZERO { assert!(expected_natural_mean.is_none()); truncated_geometric_dist_assertions( xs, a, b - S::ONE, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } else if b <= S::ONE { assert!(expected_natural_mean.is_none()); negative_truncated_geometric_dist_assertions( xs, b - S::ONE, a, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } else { double_truncated_geometric_dist_assertions( xs, a, b - S::ONE, abs_um_numerator, abs_um_denominator, expected_values, expected_common_values, expected_natural_mean.unwrap(), expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } } #[test] fn test_geometric_random_signed_range() { // i8, 5, 6, um = 10 (um is irrelevant here) let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; geometric_random_signed_range_helper::<_, i8>( 5, 6, 10, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16, 1, 7, um = 3 let values = &[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, 4, 3, 3, 2, 4, 2, 5, 1, 5, 4]; let common_values = &[(1, 365286), (2, 243368), (3, 162008), (4, 108422), (5, 72522), (6, 48394)]; let pop_median = (2, None); let sample_median = (2, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.4225563909774435), standard_deviation: NiceFloat(1.4838791137635392), skewness: NiceFloat(0.8646161570662343), excess_kurtosis: NiceFloat(-0.2650814667635877), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.4247080000000336), standard_deviation: NiceFloat(1.4858025852532333), skewness: NiceFloat(0.8627980859656847), excess_kurtosis: NiceFloat(-0.27185507049284263), }; geometric_random_signed_range_helper::<_, i16>( 1, 7, 3, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32, 10, 20, um = 30 let values = &[18, 13, 12, 14, 11, 14, 16, 12, 12, 12, 11, 11, 12, 16, 10, 12, 13, 17, 19, 18]; let common_values = &[ (10, 123089), (11, 117792), (12, 111339), (13, 106927), (14, 102009), (15, 96319), (16, 92170), (17, 86830), (18, 83895), (19, 79630), ]; let pop_median = (14, None); let sample_median = (14, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.099085006908673), standard_deviation: NiceFloat(2.8551273967321666), skewness: NiceFloat(0.17141556508548922), excess_kurtosis: NiceFloat(-1.1843121480092598), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.099542000000508), standard_deviation: NiceFloat(2.8550785526337443), skewness: NiceFloat(0.17230969046968866), excess_kurtosis: NiceFloat(-1.183362703825652), }; geometric_random_signed_range_helper::<_, i32>( 10, 20, 30, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, -20, -10, um = 30 let values = &[ -17, -14, -12, -14, -12, -15, -16, -13, -12, -13, -19, -11, -11, -17, -11, -19, -13, -16, -20, -19, ]; let common_values = &[ (-11, 124528), (-12, 118758), (-13, 112479), (-14, 107215), (-15, 101400), (-16, 96120), (-17, 91622), (-18, 86347), (-19, 82852), (-20, 78679), ]; let pop_median = (-15, None); let sample_median = (-15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-15.078692813090253), standard_deviation: NiceFloat(2.853334884793182), skewness: NiceFloat(-0.18019334055480088), excess_kurtosis: NiceFloat(-1.1801134249293568), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-15.076649000000186), standard_deviation: NiceFloat(2.8539222266332365), skewness: NiceFloat(-0.18245914264956217), excess_kurtosis: NiceFloat(-1.1796684829530097), }; geometric_random_signed_range_helper::<_, i64>( -20, -10, 30, 1, values, common_values, None, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, -100, 100, um = 30 let values = &[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, 14, 48, -61, -60, 21, -55, -69, -26, -44, 6]; let common_values = &[ (0, 16949), (-1, 16668), (1, 16340), (-2, 15893), (2, 15885), (-3, 15421), (3, 15350), (4, 14937), (-4, 14913), (5, 14576), ]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.06416536680865222), standard_deviation: NiceFloat(35.06981580711165), skewness: NiceFloat(-0.009387535787624381), excess_kurtosis: NiceFloat(0.331207115680745), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.031523999999998706), standard_deviation: NiceFloat(34.99870187802065), skewness: NiceFloat(-0.009330685977635587), excess_kurtosis: NiceFloat(0.33242667080464994), }; geometric_random_signed_range_helper::<_, i8>( -100, 100, 30, 1, values, common_values, Some(NiceFloat(26.065423999999997)), pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, i8::MIN, i8::MAX, um = 30 let values = &[-32, -31, -88, 52, -40, 64, -36, -1, -7, 46, 14, 48, -61, -60, 21, -55, -69, -26, -44, 6]; let common_values = &[ (0, 16586), (1, 16346), (-1, 15948), (2, 15598), (-2, 15440), (-3, 15044), (3, 14965), (-4, 14646), (4, 14519), (-5, 14228), ]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.06490500492128823), standard_deviation: NiceFloat(38.55979597281242), skewness: NiceFloat(-0.013352031588210264), excess_kurtosis: NiceFloat(0.8755072180683543), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.025164000000001106), standard_deviation: NiceFloat(38.48004061181062), skewness: NiceFloat(-0.009040591966747374), excess_kurtosis: NiceFloat(0.8847001181957856), }; geometric_random_signed_range_helper::<_, i8>( i8::MIN, i8::MAX, 30, 1, values, common_values, Some(NiceFloat(27.9829300000005)), pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_signed_range_fail_helper() { assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::ONE, T::ONE, 1, 1 )); assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::ONE, T::ZERO, 1, 1 )); assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), 1, 0 )); assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::ONE, T::exact_from(10), 9, 10 )); assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::exact_from(-10), T::NEGATIVE_ONE, 9, 10 )); assert_panic!(geometric_random_signed_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_signed_range_fail() { apply_fn_to_signeds!(geometric_random_signed_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, double_truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_signeds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_natural_mean: NiceFloat, expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { double_truncated_geometric_dist_assertions( geometric_random_signeds::(EXAMPLE_SEED, um_numerator, um_denominator), T::MIN, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_natural_mean, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_signeds() { // i64, um = 1 / 64 let values = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let common_values = &[(0, 969281), (-1, 15234), (1, 14983), (-2, 267), (2, 230), (3, 3), (-3, 2)]; let natural_mean = NiceFloat(0.01570299999999922); let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(0.17815241017173997), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(34.507692307692416), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.0003219999999999915), standard_deviation: NiceFloat(0.17958265107166738), skewness: NiceFloat(-0.08440731496142939), excess_kurtosis: NiceFloat(34.08776956313593), }; geometric_random_signeds_helper::( 1, 64, values, common_values, natural_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 12345/10000 let values = &[-1, -1, 0, -3, 1, 0, 0, -4, 0, -6, 1, 4, 0, 1, -2, 4, -3, -3, 1, -3]; let common_values = &[ (0, 288130), (1, 159322), (-1, 158541), (-2, 88726), (2, 88078), (3, 48713), (-3, 48584), (-4, 26933), (4, 26804), (-5, 14960), ]; let natural_mean = NiceFloat(1.233504000000006); let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(2.3488253447202068), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(3.181258570698229), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.0021609999999999915), standard_deviation: NiceFloat(2.3469592749549535), skewness: NiceFloat(-0.007388197841520547), excess_kurtosis: NiceFloat(3.1771115107088255), }; geometric_random_signeds_helper::( 12345, 10000, values, common_values, natural_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, um = 2 let values = &[-5, 0, 0, 1, -1, -1, -4, 2, 4, 6, -2, -2, 0, -1, -9, -13, 0, -2, 0, -7]; let common_values = &[ (0, 200052), (-1, 133433), (1, 133168), (2, 89079), (-2, 88845), (3, 59306), (-3, 59229), (-4, 39537), (4, 39457), (-5, 26287), ]; let natural_mean = NiceFloat(1.9983939999999663); let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.0), standard_deviation: NiceFloat(3.4641016151377553), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(3.0833333333333304), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.004637999999999956), standard_deviation: NiceFloat(3.462957476064434), skewness: NiceFloat(-0.0014668264694796887), excess_kurtosis: NiceFloat(3.1056798270038826), }; geometric_random_signeds_helper::( 2, 1, values, common_values, natural_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 64 let values = &[ -58, -18, 80, -31, -85, -74, 114, 29, 46, -28, -5, -54, -73, -67, 96, 74, -67, -20, 93, -95, ]; let common_values = &[ (0, 8916), (1, 8897), (-1, 8830), (3, 8811), (-2, 8800), (2, 8757), (-4, 8491), (4, 8459), (-3, 8413), (-5, 8336), ]; let natural_mean = NiceFloat(43.609158999998506); let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.15811030451314936), standard_deviation: NiceFloat(55.48244935032745), skewness: NiceFloat(-0.006618243685084806), excess_kurtosis: NiceFloat(-0.3947891766587368), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.09556800000000087), standard_deviation: NiceFloat(55.48675459546383), skewness: NiceFloat(-0.007283472641276268), excess_kurtosis: NiceFloat(-0.3961004797032963), }; geometric_random_signeds_helper::( 64, 1, values, common_values, natural_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, um = 1000 let values = &[25, -53, 39, 32, 26, 13, -94, 45, 125, 119, 11, 15, 66, 68, 60, -71, -54, 83, 76, -33]; let common_values = &[ (-2, 4277), (1, 4263), (9, 4217), (-1, 4213), (5, 4207), (-4, 4207), (0, 4206), (-6, 4200), (19, 4199), (8, 4179), ]; let natural_mean = NiceFloat(62.13860000000173); let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.4686977489785049), standard_deviation: NiceFloat(72.71434769926142), skewness: NiceFloat(-0.0006359350720949359), excess_kurtosis: NiceFloat(-1.1608263148064384), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.446604999999992), standard_deviation: NiceFloat(72.6977982881445), skewness: NiceFloat(-0.0006088230606281416), excess_kurtosis: NiceFloat(-1.1593850084998423), }; geometric_random_signeds_helper::( 1000, 1, values, common_values, natural_mean, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_signeds_fail_helper() { assert_panic!(geometric_random_signeds::(EXAMPLE_SEED, 0, 1)); assert_panic!(geometric_random_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_signeds::( EXAMPLE_SEED, u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_signeds_fail() { apply_fn_to_signeds!(geometric_random_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_unsigned_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_unsigned_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_unsigned_inclusive_range_helper( a: T, b: T, um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED, a, b, um_numerator, um_denominator, ), a, b, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_unsigned_inclusive_range() { // u8, 5, 5, um = 10 (um is irrelevant here) let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; geometric_random_unsigned_inclusive_range_helper::( 5, 5, 10, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16, 1, 6, um = 3 let values = &[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, 4, 3, 3, 2, 4, 2, 5, 1, 5, 4]; let common_values = &[(1, 365286), (2, 243368), (3, 162008), (4, 108422), (5, 72522), (6, 48394)]; let pop_median = (2, None); let sample_median = (2, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.4225563909774435), standard_deviation: NiceFloat(1.4838791137635392), skewness: NiceFloat(0.8646161570662343), excess_kurtosis: NiceFloat(-0.2650814667635877), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.4247080000000336), standard_deviation: NiceFloat(1.4858025852532333), skewness: NiceFloat(0.8627980859656847), excess_kurtosis: NiceFloat(-0.27185507049284263), }; geometric_random_unsigned_inclusive_range_helper::( 1, 6, 3, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, 10, 19, um = 30 let values = &[18, 13, 12, 14, 11, 14, 16, 12, 12, 12, 11, 11, 12, 16, 10, 12, 13, 17, 19, 18]; let common_values = &[ (10, 123089), (11, 117792), (12, 111339), (13, 106927), (14, 102009), (15, 96319), (16, 92170), (17, 86830), (18, 83895), (19, 79630), ]; let pop_median = (14, None); let sample_median = (14, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.099085006908673), standard_deviation: NiceFloat(2.8551273967321666), skewness: NiceFloat(0.17141556508548922), excess_kurtosis: NiceFloat(-1.1843121480092598), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.099542000000508), standard_deviation: NiceFloat(2.8550785526337443), skewness: NiceFloat(0.17230969046968866), excess_kurtosis: NiceFloat(-1.183362703825652), }; geometric_random_unsigned_inclusive_range_helper::( 10, 19, 30, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, 0, u8::MAX, um = 1 let values = &[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, 0, 0, 2, 2, 0, 0, 1, 0, 3, 1]; let common_values = &[ (0, 500085), (1, 249510), (2, 125328), (3, 62428), (4, 31280), (5, 15676), (6, 7853), (7, 3994), (8, 1932), (9, 942), ]; let pop_median = (0, Some(1)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0006159999999573), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.1140569440125403), excess_kurtosis: NiceFloat(6.4341815215340805), }; geometric_random_unsigned_inclusive_range_helper::( 0, u8::MAX, 1, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_unsigned_inclusive_range_fail_helper() { assert_panic!(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::TWO, T::ONE, 1, 1 )); assert_panic!(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), 1, 0 )); assert_panic!(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::ONE, T::exact_from(10), 9, 10 )); assert_panic!(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_unsigned_inclusive_range_fail() { apply_fn_to_unsigneds!(geometric_random_unsigned_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_unsigned_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_unsigned_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_unsigned_range_helper( a: T, b: T, um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_unsigned_range::(EXAMPLE_SEED, a, b, um_numerator, um_denominator), a, b - T::ONE, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_unsigned_range() { // u8, 5, 6, um = 10 (um is irrelevant here) let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; geometric_random_unsigned_range_helper::( 5, 6, 10, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16, 1, 7, um = 3 let values = &[2, 5, 2, 3, 4, 2, 5, 6, 1, 2, 4, 3, 3, 2, 4, 2, 5, 1, 5, 4]; let common_values = &[(1, 365286), (2, 243368), (3, 162008), (4, 108422), (5, 72522), (6, 48394)]; let pop_median = (2, None); let sample_median = (2, None); let pop_moment_stats = MomentStats { mean: NiceFloat(2.4225563909774435), standard_deviation: NiceFloat(1.4838791137635392), skewness: NiceFloat(0.8646161570662343), excess_kurtosis: NiceFloat(-0.2650814667635877), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.4247080000000336), standard_deviation: NiceFloat(1.4858025852532333), skewness: NiceFloat(0.8627980859656847), excess_kurtosis: NiceFloat(-0.27185507049284263), }; geometric_random_unsigned_range_helper::( 1, 7, 3, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, 10, 20, um = 30 let values = &[18, 13, 12, 14, 11, 14, 16, 12, 12, 12, 11, 11, 12, 16, 10, 12, 13, 17, 19, 18]; let common_values = &[ (10, 123089), (11, 117792), (12, 111339), (13, 106927), (14, 102009), (15, 96319), (16, 92170), (17, 86830), (18, 83895), (19, 79630), ]; let pop_median = (14, None); let sample_median = (14, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.099085006908673), standard_deviation: NiceFloat(2.8551273967321666), skewness: NiceFloat(0.17141556508548922), excess_kurtosis: NiceFloat(-1.1843121480092598), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.099542000000508), standard_deviation: NiceFloat(2.8550785526337443), skewness: NiceFloat(0.17230969046968866), excess_kurtosis: NiceFloat(-1.183362703825652), }; geometric_random_unsigned_range_helper::( 10, 20, 30, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, 0, u8::MAX, um = 1 let values = &[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, 0, 0, 2, 2, 0, 0, 1, 0, 3, 1]; let common_values = &[ (0, 500085), (1, 249510), (2, 125328), (3, 62428), (4, 31280), (5, 15676), (6, 7853), (7, 3994), (8, 1932), (9, 942), ]; let pop_median = (0, Some(1)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0006159999999573), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.1140569440125403), excess_kurtosis: NiceFloat(6.4341815215340805), }; geometric_random_unsigned_range_helper::( 0, u8::MAX, 1, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_unsigned_range_fail_helper() { assert_panic!(geometric_random_unsigned_range::( EXAMPLE_SEED, T::ONE, T::ONE, 1, 1 )); assert_panic!(geometric_random_unsigned_range::( EXAMPLE_SEED, T::ONE, T::ZERO, 1, 1 )); assert_panic!(geometric_random_unsigned_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), 1, 0 )); assert_panic!(geometric_random_unsigned_range::( EXAMPLE_SEED, T::ONE, T::exact_from(10), 9, 10 )); assert_panic!(geometric_random_unsigned_range::( EXAMPLE_SEED, T::ZERO, T::exact_from(10), u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_unsigned_range_fail() { apply_fn_to_unsigneds!(geometric_random_unsigned_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/geometric_random_unsigneds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, truncated_geometric_dist_assertions, }; use std::panic::catch_unwind; fn geometric_random_unsigneds_helper( um_numerator: u64, um_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { truncated_geometric_dist_assertions( geometric_random_unsigneds::(EXAMPLE_SEED, um_numerator, um_denominator), T::ZERO, T::MAX, um_numerator, um_denominator, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_geometric_random_unsigneds() { // u64, um = 1 / 64 let values = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; let common_values = &[(0, 984537), (1, 15210), (2, 253)]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.015624999999999944), standard_deviation: NiceFloat(0.12597277731716458), skewness: NiceFloat(8.186292482887549), excess_kurtosis: NiceFloat(69.01538461538773), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.015716000000000004), standard_deviation: NiceFloat(0.1263923388462427), skewness: NiceFloat(8.160460378454996), excess_kurtosis: NiceFloat(68.31033619043119), }; geometric_random_unsigneds_helper::( 1, 64, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, um = 1 let values = &[1, 0, 0, 3, 4, 4, 1, 0, 0, 1, 0, 0, 2, 2, 0, 0, 1, 0, 3, 1]; let common_values = &[ (0, 500085), (1, 249510), (2, 125328), (3, 62428), (4, 31280), (5, 15676), (6, 7853), (7, 3994), (8, 1932), (9, 942), ]; let pop_median = (0, Some(1)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(std::f64::consts::SQRT_2), skewness: NiceFloat(2.1213203435596424), excess_kurtosis: NiceFloat(6.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0006159999999573), standard_deviation: NiceFloat(1.414547850547892), skewness: NiceFloat(2.1140569440125403), excess_kurtosis: NiceFloat(6.4341815215340805), }; geometric_random_unsigneds_helper::( 1, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, um = 12345/10000 let values = &[1, 3, 8, 2, 2, 0, 1, 1, 0, 0, 0, 0, 1, 1, 7, 0, 0, 3, 0, 0]; let common_values = &[ (0, 446911), (1, 246858), (2, 137217), (3, 75488), (4, 41605), (5, 23149), (6, 12981), (7, 7024), (8, 3848), (9, 2206), ]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.2344999999999997), standard_deviation: NiceFloat(1.6608703290744884), skewness: NiceFloat(2.088663960860256), excess_kurtosis: NiceFloat(6.362517141396456), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.2380129999999983), standard_deviation: NiceFloat(1.6649767517832197), skewness: NiceFloat(2.0942793135700466), excess_kurtosis: NiceFloat(6.469904862333731), }; geometric_random_unsigneds_helper::( 12345, 10000, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, um = 64 let values = &[181, 90, 125, 70, 146, 41, 109, 5, 224, 93, 33, 18, 89, 6, 17, 1, 129, 2, 123, 134]; let common_values = &[ (0, 15734), (1, 15591), (2, 15469), (3, 14917), (4, 14672), (5, 14340), (6, 14329), (7, 14274), (8, 13841), (9, 13586), ]; let pop_median = (43, None); let sample_median = (43, None); let pop_moment_stats = MomentStats { mean: NiceFloat(59.070796734994865), standard_deviation: NiceFloat(53.608086324088696), skewness: NiceFloat(1.2637908431790819), excess_kurtosis: NiceFloat(1.1650093560615717), }; let sample_moment_stats = MomentStats { mean: NiceFloat(59.03148100000193), standard_deviation: NiceFloat(53.60145056863821), skewness: NiceFloat(1.2649824077121026), excess_kurtosis: NiceFloat(1.1705093182268955), }; geometric_random_unsigneds_helper::( 64, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, um = 1000 let values = &[ 24, 115, 248, 25, 104, 215, 208, 240, 37, 35, 196, 204, 40, 37, 245, 193, 252, 119, 0, 219, ]; let common_values = &[ (18, 4482), (11, 4469), (6, 4431), (25, 4426), (0, 4424), (3, 4415), (5, 4400), (8, 4400), (20, 4396), (10, 4386), ]; let pop_median = (119, None); let sample_median = (119, None); let pop_moment_stats = MomentStats { mean: NiceFloat(122.04742583121647), standard_deviation: NiceFloat(73.7795264500733), skewness: NiceFloat(0.08861336552406392), excess_kurtosis: NiceFloat(-1.1891899016227028), }; let sample_moment_stats = MomentStats { mean: NiceFloat(122.12244000000315), standard_deviation: NiceFloat(73.78371977939058), skewness: NiceFloat(0.08799741904573245), excess_kurtosis: NiceFloat(-1.1900813344800518), }; geometric_random_unsigneds_helper::( 1000, 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn geometric_random_unsigneds_fail_helper() { assert_panic!(geometric_random_unsigneds::(EXAMPLE_SEED, 0, 1)); assert_panic!(geometric_random_unsigneds::(EXAMPLE_SEED, 1, 0)); assert_panic!(geometric_random_unsigneds::( EXAMPLE_SEED, u64::MAX, u64::MAX - 1 )); } #[test] fn geometric_random_unsigneds_fail() { apply_fn_to_unsigneds!(geometric_random_unsigneds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/geometric/get_geometric_random_signed_from_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::random::VariableRangeGenerator; use malachite_base::num::random::geometric::get_geometric_random_signed_from_inclusive_range; use malachite_base::random::EXAMPLE_SEED; fn get_geometric_random_signed_from_inclusive_range_helper( a: i32, b: i32, abs_um_numerator: u64, abs_um_denominator: u64, out: i32, ) { assert_eq!( get_geometric_random_signed_from_inclusive_range( &mut VariableRangeGenerator::new(EXAMPLE_SEED), a, b, abs_um_numerator, abs_um_denominator ), out ); } #[test] fn test_get_geometric_random_signed_from_inclusive_range() { get_geometric_random_signed_from_inclusive_range_helper(0, 0, 2, 1, 0); get_geometric_random_signed_from_inclusive_range_helper(0, 1, 2, 1, 1); get_geometric_random_signed_from_inclusive_range_helper(0, 10, 2, 1, 1); get_geometric_random_signed_from_inclusive_range_helper(0, 10, 10, 1, 2); get_geometric_random_signed_from_inclusive_range_helper(-10, 10, 2, 1, -3); get_geometric_random_signed_from_inclusive_range_helper(-10, 10, 10, 1, 8); get_geometric_random_signed_from_inclusive_range_helper(100, 110, 101, 1, 101); get_geometric_random_signed_from_inclusive_range_helper(100, 110, 500, 1, 109); get_geometric_random_signed_from_inclusive_range_helper(-110, -100, 101, 1, -101); get_geometric_random_signed_from_inclusive_range_helper(-110, -100, 500, 1, -109); } #[test] #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_1() { get_geometric_random_signed_from_inclusive_range( &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 0, 1, 2, ); } #[test] #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_2() { get_geometric_random_signed_from_inclusive_range( &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 1, 0, ); } #[test] #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_3() { get_geometric_random_signed_from_inclusive_range( &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 0, 0, ); } #[test] #[should_panic] fn get_geometric_random_signed_from_inclusive_range_fail_4() { get_geometric_random_signed_from_inclusive_range( &mut VariableRangeGenerator::new(EXAMPLE_SEED), 1, 2, 1, 2, ); } ================================================ FILE: malachite-base/tests/num/random/geometric/mean.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::test_util::num::random::geometric::{ adjusted_mean_to_unadjusted_mean, unadjusted_mean_to_adjusted_mean, }; #[test] pub fn test_unadjusted_mean_to_adjusted_mean() { let test = |unadjusted_mean, limit, adjusted_mean| { assert_eq!( NiceFloat(unadjusted_mean_to_adjusted_mean(unadjusted_mean, limit)), NiceFloat(adjusted_mean) ); }; test(1.0e-45, 255.0, 0.0); test(0.001, 255.0, 0.000999999999999855); test(1.0, 255.0, 1.0); test(10.0, 255.0, 9.999999993517946); test(50.0, 255.0, 48.38067332601502); test(100.0, 255.0, 78.25417704300385); test(255.0, 255.0, 106.4745261876895); test(1000000.0, 255.0, 127.49458799160993); test(1.0000000000000002, 255.0, 1.0); test(10.000000006482054, 255.0, 10.000000000000002); test(51.95952531604177, 255.0, 50.0); test(192.50163549359422, 255.0, 100.00000000000001); test(10921.900023504326, 255.0, 127.0000000000199); test(546163.2639224805, 255.0, 127.49000008135106); } #[test] pub fn test_adjusted_mean_to_unadjusted_mean() { let test = |adjusted_mean, limit, unadjusted_mean| { assert_eq!( NiceFloat(adjusted_mean_to_unadjusted_mean(adjusted_mean, limit)), NiceFloat(unadjusted_mean) ); }; test(1.0, 255.0, 1.0000000000000002); test(10.0, 255.0, 10.000000006482054); test(50.0, 255.0, 51.95952531604177); test(100.0, 255.0, 192.50163549359422); test(127.0, 255.0, 10921.900023504326); test(127.49, 255.0, 546163.2639224805); test(0.000999999999999855, 255.0, 0.0009999999999998803); test(1.0, 255.0, 1.0000000000000002); test(9.999999993517946, 255.0, 10.0); test(48.38067332601502, 255.0, 50.0); test(78.25417704300385, 255.0, 100.0); test(106.4745261876895, 255.0, 255.0); test(127.49458799160993, 255.0, 1006078.1813340919); } ================================================ FILE: malachite-base/tests/num/random/random_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_finite_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_finite_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_finite_primitive_floats() { // f32 let values = &[ -2.3484663e-27, 2.287989e-18, -2.0729893e-12, 3.360012e28, -9.021723e-32, 3564911.2, -0.0000133769445, -1.8855448e18, 8.2494555e-29, 2.2178014e-38, -6.3067724e-34, 5.1996016e31, 7.613263e33, 0.00015323666, 9.476819e36, -0.0005665586, 8.8733265e-30, 0.09273135, -7.7748304e33, 4.3156234e-8, ]; let common_values = &[ (-66476.9, 2), (34.61204, 2), (73439.86, 2), (780.0361, 2), (-66297.14, 2), (0.2084277, 2), (13200.072, 2), (224535.31, 2), (3306.3638, 2), (5.7126203, 2), ]; let sample_median = (4.601795e-39, Some(4.606578e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871800306879315e34), standard_deviation: NiceFloat(1.8597574252028948e37), skewness: NiceFloat(-0.04588142291892213), excess_kurtosis: NiceFloat(174.30920632007357), }; random_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 3.1062066405583414e-146, 7.268713316268922e223, 1.1685126708702853e48, -1.0824685183946233e146, 3.1146051606615834e-306, 2.2453015573637678e249, 1.2548860979388688e-35, -8.287939157477945e-27, 2.1255041535787168e-13, 4.815129234795049e-64, 1.3850402674408149e-17, -1.2535717707589619e207, -1.4941028004491903e142, 4.3666119614549075e-51, -7.063699168119983e17, -7.062565582436956e90, 1.1662950933663384e-221, 2.1976577668343595e-97, -2.821294426687019e-137, 1.225091633874841e-222, ]; let common_values = &[ (3.637321705391, 1), (30.80883877248, 1), (915366460504.2, 1), (9256888.416622, 1), (-737164661.2491, 1), (-81413.95043198, 1), (-994938.9166069, 1), (1.4299272196643, 1), (12812252.479435, 1), (1598038.5592174, 1), ]; let sample_median = (2.7723065921722726e-308, Some(2.782073119497922e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581054e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_highest_bit_set_unsigneds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_highest_bit_set_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_highest_bit_set_unsigneds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_highest_bit_set_unsigneds(EXAMPLE_SEED), T::power_of_2(T::WIDTH - 1), T::MAX, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_highest_bit_set_unsigneds() { // u8 let values = &[ 241, 222, 151, 226, 198, 220, 180, 212, 161, 175, 129, 241, 182, 138, 175, 145, 217, 220, 247, 194, ]; let common_values = &[ (130, 8077), (249, 8039), (176, 8015), (241, 7966), (136, 7937), (205, 7933), (178, 7928), (219, 7927), (210, 7925), (230, 7924), ]; let pop_median = (191, Some(192)); let sample_median = (191, None); let pop_moment_stats = MomentStats { mean: NiceFloat(191.5), standard_deviation: NiceFloat(36.94928957368463), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001464933162425), }; let sample_moment_stats = MomentStats { mean: NiceFloat(191.47808899999873), standard_deviation: NiceFloat(36.961138429895456), skewness: NiceFloat(-0.00045403607545687984), excess_kurtosis: NiceFloat(-1.1998683031732567), }; random_highest_bit_set_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16 let values = &[ 61297, 55435, 52113, 36166, 34170, 60868, 44820, 44177, 56814, 43920, 62926, 52397, 56477, 62030, 53767, 54475, 41390, 52238, 49476, 64068, ]; let common_values = &[ (45680, 55), (43149, 54), (51767, 54), (41030, 53), (49628, 52), (51621, 52), (59748, 52), (62186, 52), (34198, 51), (36279, 51), ]; let pop_median = (49151, Some(49152)); let sample_median = (49162, None); let pop_moment_stats = MomentStats { mean: NiceFloat(49151.5), standard_deviation: NiceFloat(9459.306805997996), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000022351742), }; let sample_moment_stats = MomentStats { mean: NiceFloat(49155.96401899928), standard_deviation: NiceFloat(9454.356832489304), skewness: NiceFloat(-0.0012474540243074795), excess_kurtosis: NiceFloat(-1.1990519661334587), }; random_highest_bit_set_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32 let values = &[ 3964006257, 3276907976, 3451421022, 4073264610, 3109848542, 3140663214, 2279906674, 3612658596, 3508930337, 3808334112, 3115296257, 2693817273, 3135713082, 2512715495, 2304388648, 3178397234, 4176627051, 3554614631, 3618567415, 3594534402, ]; let common_values = &[ (2148512502, 2), (2152753653, 2), (2199919756, 2), (2200926180, 2), (2201533159, 2), (2203162873, 2), (2204334486, 2), (2243577040, 2), (2248172201, 2), (2250885871, 2), ]; let pop_median = (3221225471, Some(3221225472)); let sample_median = (3220111243, Some(3220113439)); let pop_moment_stats = MomentStats { mean: NiceFloat(3221225471.5), standard_deviation: NiceFloat(619925131.1265597), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3220061212.7312818), standard_deviation: NiceFloat(620056431.3063867), skewness: NiceFloat(0.0014601286400032912), excess_kurtosis: NiceFloat(-1.1999609793276904), }; random_highest_bit_set_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64 let values = &[ 11648792314704686961, 15902849618696487087, 12062424265687245175, 10193137694460908462, 9734517988917403762, 17618716774223412528, 12117930945561730236, 13095749177794802780, 13684732338925793861, 17489043124220843898, 18428543530713567946, 9663508144831389154, 14291728674867306832, 14157636121372894287, 11041743053466742106, 11652479517924728358, 15926995443195260196, 10797926927713903617, 9340643919610687288, 13527331835876139736, ]; let common_values = &[ (9223375360960685195, 1), (9223375840468297219, 1), (9223377246635142855, 1), (9223378573599571464, 1), (9223392818083847604, 1), (9223397883812499659, 1), (9223410046446842059, 1), (9223414297499376833, 1), (9223420250639904388, 1), (9223423782640535515, 1), ]; let pop_median = (13835058055282163711, Some(13835058055282163712)); let sample_median = (13835015978121017591, Some(13835016964896634362)); let pop_moment_stats = MomentStats { mean: NiceFloat(1.3835058055282164e19), standard_deviation: NiceFloat(2.6625581641570857e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.3835207839699462e19), standard_deviation: NiceFloat(2.6620357716239826e18), skewness: NiceFloat(-0.001163213633403464), excess_kurtosis: NiceFloat(-1.1990763518455725), }; random_highest_bit_set_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u128 let values = &[ 316819081939861044636107404782286008177, 259684029915037091022230980152781410491, 274570122163304294029662138603390933020, 227774850171603602876471193044002894743, 228075138265181566710552389938690625316, 212803339921546589345359493671973554838, 290482805477667929731925894842607922053, 194242323025343149803496343896337025882, 273877696450250650298202452211959786285, 202950956103661145939707262718357071703, 278510113161417516359560622970606220871, 245612405407790906538437072159901074531, 192996213236671200977298813427044737421, 311381173222019982206270836087375053399, 176738900463469569991939158243641249503, 288268669295331405536678348099056207715, 204463485514563745612349536646478672573, 185187345061019841391010982362414546856, 234567239495355551510783097995427525513, 322415362730128827224032220814663383318, ]; let common_values = &[ (170141233166538297897770214998043520489, 1), (170141477709687108748255943535626236844, 1), (170141963031764576849655827097535573872, 1), (170142211761517152257367037557307192382, 1), (170142224955858751899306474848524651318, 1), (170142344567707776674180030986486606478, 1), (170142519806846123597203111583658441461, 1), (170142677117909400976523007761944910786, 1), (170142818348199748232299322264932053448, 1), (170143268636071676474898792639923408007, 1), ]; let pop_median = ( 255211775190703847597530955573826158591, Some(255211775190703847597530955573826158592), ); let sample_median = ( 255126542430357640405925855455171138421, Some(255126579172819401755185863236353147245), ); let pop_moment_stats = MomentStats { mean: NiceFloat(2.5521177519070385e38), standard_deviation: NiceFloat(4.91155290355717e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2.5515158317195176e38), standard_deviation: NiceFloat(4.910082612813729e37), skewness: NiceFloat(0.0016680470828693357), excess_kurtosis: NiceFloat(-1.199401614583425), }; random_highest_bit_set_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_natural_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_natural_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_natural_signeds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_natural_signeds::(EXAMPLE_SEED), T::ZERO, T::MAX, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_natural_signeds() { // i8 let values = &[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, 1, 113, 54, 10, 47, 17, 89, 92, 119, 66]; let common_values = &[ (2, 8077), (121, 8039), (48, 8015), (113, 7966), (8, 7937), (77, 7933), (50, 7928), (91, 7927), (82, 7925), (102, 7924), ]; let pop_median = (63, Some(64)); let sample_median = (63, None); let pop_moment_stats = MomentStats { mean: NiceFloat(63.5), standard_deviation: NiceFloat(36.94928957368463), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001464933162425), }; let sample_moment_stats = MomentStats { mean: NiceFloat(63.478088999999315), standard_deviation: NiceFloat(36.96113842989552), skewness: NiceFloat(-0.000454036075457304), excess_kurtosis: NiceFloat(-1.1998683031732713), }; random_natural_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16 let values = &[ 28529, 22667, 19345, 3398, 1402, 28100, 12052, 11409, 24046, 11152, 30158, 19629, 23709, 29262, 20999, 21707, 8622, 19470, 16708, 31300, ]; let common_values = &[ (12912, 55), (10381, 54), (18999, 54), (8262, 53), (16860, 52), (18853, 52), (26980, 52), (29418, 52), (1430, 51), (3511, 51), ]; let pop_median = (16383, Some(16384)); let sample_median = (16394, None); let pop_moment_stats = MomentStats { mean: NiceFloat(16383.5), standard_deviation: NiceFloat(9459.306805997996), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000022351742), }; let sample_moment_stats = MomentStats { mean: NiceFloat(16387.96401900046), standard_deviation: NiceFloat(9454.356832489306), skewness: NiceFloat(-0.0012474540243073533), excess_kurtosis: NiceFloat(-1.199051966133461), }; random_natural_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32 let values = &[ 1816522609, 1129424328, 1303937374, 1925780962, 962364894, 993179566, 132423026, 1465174948, 1361446689, 1660850464, 967812609, 546333625, 988229434, 365231847, 156905000, 1030913586, 2029143403, 1407130983, 1471083767, 1447050754, ]; let common_values = &[ (1028854, 2), (5270005, 2), (52436108, 2), (53442532, 2), (54049511, 2), (55679225, 2), (56850838, 2), (96093392, 2), (100688553, 2), (103402223, 2), ]; let pop_median = (1073741823, Some(1073741824)); let sample_median = (1072627595, Some(1072629791)); let pop_moment_stats = MomentStats { mean: NiceFloat(1073741823.5), standard_deviation: NiceFloat(619925131.1265597), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1072577564.7313439), standard_deviation: NiceFloat(620056431.3063871), skewness: NiceFloat(0.0014601286400032305), excess_kurtosis: NiceFloat(-1.1999609793276922), }; random_natural_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64 let values = &[ 2425420277849911153, 6679477581841711279, 2839052228832469367, 969765657606132654, 511145952062627954, 8395344737368636720, 2894558908706954428, 3872377140940026972, 4461360302071018053, 8265671087366068090, 9205171493858792138, 440136107976613346, 5068356638012531024, 4934264084518118479, 1818371016611966298, 2429107481069952550, 6703623406340484388, 1574554890859127809, 117271882755911480, 4303959799021363928, ]; let common_values = &[ (3324105909387, 1), (3803613521411, 1), (5209780367047, 1), (6536744795656, 1), (20781229071796, 1), (25846957723851, 1), (38009592066251, 1), (42260644601025, 1), (48213785128580, 1), (51745785759707, 1), ]; let pop_median = (4611686018427387903, Some(4611686018427387904)); let sample_median = (4611643941266241783, Some(4611644928041858554)); let pop_moment_stats = MomentStats { mean: NiceFloat(4.611686018427388e18), standard_deviation: NiceFloat(2.6625581641570857e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(4.611835802844851e18), standard_deviation: NiceFloat(2.6620357716239764e18), skewness: NiceFloat(-0.0011632136334031786), excess_kurtosis: NiceFloat(-1.1990763518455585), }; random_natural_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128 let values = &[ 146677898479391812904420101066401902449, 89542846454567859290543676436897304763, 104428938702835062297974834887506827292, 57633666711134371144783889328118789015, 57933954804712334978865086222806519588, 42662156461077357613672189956089449110, 120341622017198698000238591126723816325, 24101139564873918071809040180452920154, 103736512989781418566515148496075680557, 32809772643191914208019959002472965975, 108368929700948284627873319254722115143, 75471221947321674806749768444016968803, 22855029776201969245611509711160631693, 141239989761550750474583532371490947671, 6597717003000338260251854527757143775, 118127485834862173804991044383172101987, 34322302054094513880662232930594566845, 15046161600550609659323678646530441128, 64426056034886319779095794279543419785, 152274179269659595492344917098779277590, ]; let common_values = &[ (49706069066166082911282159414761, 1), (294249217877016568639819742131116, 1), (779571295345117968523381651468144, 1), (1028301047920525679733841423086654, 1), (1041495389520167619171132640545590, 1), (1161107238544942492727270602500750, 1), (1336346376891865515807867774335733, 1), (1493657440169244835704046060805058, 1), (1634887730516500612018549047947720, 1), (2085175602444743211488924039302279, 1), ]; let pop_median = ( 85070591730234615865843651857942052863, Some(85070591730234615865843651857942052864), ); let sample_median = ( 84985358969888408674238551739287032693, Some(84985395712350170023498559520469041517), ); let pop_moment_stats = MomentStats { mean: NiceFloat(8.507059173023462e37), standard_deviation: NiceFloat(4.91155290355717e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(8.501039971148385e37), standard_deviation: NiceFloat(4.910082612813726e37), skewness: NiceFloat(0.0016680470828691063), excess_kurtosis: NiceFloat(-1.199401614583414), }; random_natural_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_negative_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_negative_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_negative_finite_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_negative_finite_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_negative_finite_primitive_floats() { // f32 let values = &[ -2.3484663e-27, -0.010641626, -5.8060583e-9, -2.8182442e-31, -10462.532, -821.12994, -6.303163e33, -9.50376e-15, -4.9561126e-11, -8.565163e-22, -6667.249, -8.632876e18, -1222.524, -2.8259287e25, -8.408057e32, -35.37676, -5.3312457e-35, -1.1431576e-12, -5.8021113e-15, -4.2578778e-14, ]; let common_values = &[ (-2.915314, 2), (-0.7262628, 2), (-1.3261845, 2), (-10.318969, 2), (-12496.082, 2), (-15.058022, 2), (-2.5221732, 2), (-20.562862, 2), (-203818.36, 2), (-26.077845, 2), ]; let sample_median = (-1.6313586, Some(-1.6313426)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.9935686121103762e36), standard_deviation: NiceFloat(1.8605029843851628e37), skewness: NiceFloat(-12.384333043431482), excess_kurtosis: NiceFloat(170.5284644692483), }; random_negative_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ -1.4470055025606618e146, -6.2410386896936294e-139, -3.235416846271215e118, -2.8486059576132576e243, -1.3007593490666564e274, -1.267802986597089e-253, -6.298463311550517e114, -2.71148919055391e49, -11845642624.881702, -6.049786340671396e-245, -9.268165817801774e-308, -7.204960592983619e278, -3.152983742246857e-31, -2.9080351183768945e-22, -5.397630931761668e186, -8.140466543599511e145, -1.5709219762031943e-140, -1.0805614483727634e203, -2.6257467421064505e300, -3.922358679765479e20, ]; let common_values = &[ (-4081294.15273, 1), (-75856946.7859, 1), (-0.785631131986, 1), (-10.70965140303, 1), (-306424.6626443, 1), (-314701.8184209, 1), (-449320.3879786, 1), (-590754505.6957, 1), (-642882447.5536, 1), (-88637.71469077, 1), ]; let sample_median = (-1.5131202036927986, Some(-1.511917932803396)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.3244537383462707e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_negative_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_negative_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_negative_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_negative_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_negative_primitive_floats() { // f32 let values = &[ -2.3484665e-27, -0.010641627, -5.8060587e-9, -2.8182444e-31, -10462.533, -821.13, -6.3031636e33, -9.5037605e-15, -4.956113e-11, -8.565164e-22, -6667.2495, -8.6328766e18, -1222.5242, -2.825929e25, -8.408058e32, -35.376762, -5.331246e-35, -1.1431577e-12, -5.8021117e-15, -4.257878e-14, ]; let common_values = &[ (-10.31897, 2), (-539.9892, 2), (-60148.51, 2), (-7.546873, 2), (-7606.816, 2), (-776.3078, 2), (-1.3261846, 2), (-12496.083, 2), (-2.5221734, 2), (-2.9153142, 2), ]; let sample_median = (-1.6313587, Some(-1.6313428)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.9935687709301062e36), standard_deviation: NiceFloat(1.8605031273250459e37), skewness: NiceFloat(-12.384332949727417), excess_kurtosis: NiceFloat(170.5284612507418), }; random_negative_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ -1.447005502560662e146, -6.24103868969363e-139, -3.2354168462712154e118, -2.848605957613258e243, -1.3007593490666566e274, -1.2678029865970891e-253, -6.298463311550518e114, -2.7114891905539105e49, -11845642624.881704, -6.049786340671397e-245, -9.268165817801776e-308, -7.20496059298362e278, -3.1529837422468573e-31, -2.908035118376895e-22, -5.397630931761669e186, -8.140466543599512e145, -1.5709219762031945e-140, -1.0805614483727636e203, -2.6257467421064508e300, -3.9223586797654796e20, ]; let common_values = &[ (-8417229.77625, 1), (-2.510958896e45, 1), (-3208093286.102, 1), (-362.2025556776, 1), (-46.55187627446, 1), (-466061517.8385, 1), (-5.171759573816, 1), (-6666772552.184, 1), (-675858.2909992, 1), (-732009733280.7, 1), ]; let sample_median = (-1.5131202036927989, Some(-1.5119179328033963)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.324453738346271e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_negative_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_negative_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_negative_signeds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_negative_signeds::(EXAMPLE_SEED), T::MIN, T::NEGATIVE_ONE, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_negative_signeds() { // i8 let values = &[ -15, -34, -105, -30, -58, -36, -76, -44, -95, -81, -127, -15, -74, -118, -81, -111, -39, -36, -9, -62, ]; let common_values = &[ (-126, 8077), (-7, 8039), (-80, 8015), (-15, 7966), (-120, 7937), (-51, 7933), (-78, 7928), (-37, 7927), (-46, 7925), (-26, 7924), ]; let pop_median = (-65, Some(-64)); let sample_median = (-65, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-64.5), standard_deviation: NiceFloat(36.94928957368463), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001464933162425), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-64.5219110000005), standard_deviation: NiceFloat(36.96113842989553), skewness: NiceFloat(-0.00045403607545706974), excess_kurtosis: NiceFloat(-1.1998683031732797), }; random_negative_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16 let values = &[ -4239, -10101, -13423, -29370, -31366, -4668, -20716, -21359, -8722, -21616, -2610, -13139, -9059, -3506, -11769, -11061, -24146, -13298, -16060, -1468, ]; let common_values = &[ (-19856, 55), (-13769, 54), (-22387, 54), (-24506, 53), (-3350, 52), (-5788, 52), (-13915, 52), (-15908, 52), (-4224, 51), (-6649, 51), ]; let pop_median = (-16385, Some(-16384)); let sample_median = (-16374, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-16384.5), standard_deviation: NiceFloat(9459.306805997996), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000022351742), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-16380.035980999151), standard_deviation: NiceFloat(9454.356832489315), skewness: NiceFloat(-0.0012474540243074617), excess_kurtosis: NiceFloat(-1.1990519661334669), }; random_negative_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32 let values = &[ -330961039, -1018059320, -843546274, -221702686, -1185118754, -1154304082, -2015060622, -682308700, -786036959, -486633184, -1179671039, -1601150023, -1159254214, -1782251801, -1990578648, -1116570062, -118340245, -740352665, -676399881, -700432894, ]; let common_values = &[ (-2599452, 2), (-30488905, 2), (-41127657, 2), (-47856776, 2), (-48474862, 2), (-49257777, 2), (-60585238, 2), (-63413113, 2), (-90112461, 2), (-92925255, 2), ]; let pop_median = (-1073741825, Some(-1073741824)); let sample_median = (-1074856053, Some(-1074853857)); let pop_moment_stats = MomentStats { mean: NiceFloat(-1073741824.5), standard_deviation: NiceFloat(619925131.1265597), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1074906083.2686987), standard_deviation: NiceFloat(620056431.3063879), skewness: NiceFloat(0.0014601286400033587), excess_kurtosis: NiceFloat(-1.199960979327699), }; random_negative_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64 let values = &[ -6797951759004864655, -2543894455013064529, -6384319808022306441, -8253606379248643154, -8712226084792147854, -828027299486139088, -6328813128147821380, -5350994895914748836, -4762011734783757755, -957700949488707718, -18200542995983670, -8783235928878162462, -4155015398842244784, -4289107952336657329, -7405001020242809510, -6794264555784823258, -2519748630514291420, -7648817145995647999, -9106100154098864328, -4919412237833411880, ]; let common_values = &[ (-32633775716835, 1), (-33530332767202, 1), (-40083601698629, 1), (-54667548368563, 1), (-55711023537196, 1), (-57995675195609, 1), (-60421027989814, 1), (-63506819698059, 1), (-68934218411234, 1), (-96764893067540, 1), ]; let pop_median = (-4611686018427387905, Some(-4611686018427387904)); let sample_median = (-4611728095588534025, Some(-4611727108812917254)); let pop_moment_stats = MomentStats { mean: NiceFloat(-4.611686018427388e18), standard_deviation: NiceFloat(2.6625581641570857e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-4.6115362340100536e18), standard_deviation: NiceFloat(2.662035771623978e18), skewness: NiceFloat(-0.0011632136334032948), excess_kurtosis: NiceFloat(-1.199076351845568), }; random_negative_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128 let values = &[ -23463284981077418827267202649482203279, -80598337005901372441143627278986800965, -65712244757634169433712468828377278436, -112507516749334860586903414387765316713, -112207228655756896752822217493077586140, -127479026999391874118015113759794656618, -49799561443270533731448712589160289403, -146040043895595313659878263535431185574, -66404670470687813165172155219808425171, -137331410817277317523667344713411139753, -61772253759520947103813984461161990585, -94669961513147556924937535271867136925, -147286153684267262486075794004723474035, -28901193698918481257103771344393158057, -163543466457468893471435449188126961953, -52013697625607057926696259332712003741, -135818881406374717851025070785289538883, -155095021859918622072363625069353664600, -105715127425582911952591509436340685943, -17867004190809636239342386617104828138, ]; let common_values = &[ (-5142203300700144436674870612888, 1), (-182426925066696407144329295811271, 1), (-609085828667135587396424148113815, 1), (-709584458395955034053916159170888, 1), (-793734383127263040096517829674535, 1), (-1015040108753864759296367578696398, 1), (-1102384056888326002883014030016669, 1), (-1302359298776052550565920555095243, 1), (-1597976831171503518058570309070626, 1), (-1756747886524482972001931222767918, 1), ]; let pop_median = ( -85070591730234615865843651857942052865, Some(-85070591730234615865843651857942052864), ); let sample_median = ( -85155824490580823057448751976597073035, Some(-85155787748119061708188744195415064211), ); let pop_moment_stats = MomentStats { mean: NiceFloat(-8.507059173023462e37), standard_deviation: NiceFloat(4.91155290355717e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-8.513078374898942e37), standard_deviation: NiceFloat(4.9100826128137265e37), skewness: NiceFloat(0.001668047082869008), excess_kurtosis: NiceFloat(-1.1994016145834168), }; random_negative_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_nonzero_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_nonzero_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_nonzero_finite_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_nonzero_finite_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_nonzero_finite_primitive_floats() { // f32 let values = &[ -2.3484663e-27, 2.287989e-18, -2.0729893e-12, 3.360012e28, -9.021723e-32, 3564911.2, -0.0000133769445, -1.8855448e18, 8.2494555e-29, 2.2178014e-38, -6.3067724e-34, 5.1996016e31, 7.613263e33, 0.00015323666, 9.476819e36, -0.0005665586, 8.8733265e-30, 0.09273135, -7.7748304e33, 4.3156234e-8, ]; let common_values = &[ (-66476.9, 2), (34.61204, 2), (73439.86, 2), (780.0361, 2), (-66297.14, 2), (0.2084277, 2), (13200.072, 2), (224535.31, 2), (3306.3638, 2), (5.7126203, 2), ]; let sample_median = (4.601795e-39, Some(4.606578e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871800306879315e34), standard_deviation: NiceFloat(1.8597574252028948e37), skewness: NiceFloat(-0.04588142291892213), excess_kurtosis: NiceFloat(174.30920632007357), }; random_nonzero_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 3.1062066405583414e-146, 7.268713316268922e223, 1.1685126708702853e48, -1.0824685183946233e146, 3.1146051606615834e-306, 2.2453015573637678e249, 1.2548860979388688e-35, -8.287939157477945e-27, 2.1255041535787168e-13, 4.815129234795049e-64, 1.3850402674408149e-17, -1.2535717707589619e207, -1.4941028004491903e142, 4.3666119614549075e-51, -7.063699168119983e17, -7.062565582436956e90, 1.1662950933663384e-221, 2.1976577668343595e-97, -2.821294426687019e-137, 1.225091633874841e-222, ]; let common_values = &[ (3.637321705391, 1), (30.80883877248, 1), (915366460504.2, 1), (9256888.416622, 1), (-737164661.2491, 1), (-81413.95043198, 1), (-994938.9166069, 1), (1.4299272196643, 1), (12812252.479435, 1), (1598038.5592174, 1), ]; let sample_median = (2.7723065921722726e-308, Some(2.782073119497922e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581054e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_nonzero_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_nonzero_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_nonzero_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_nonzero_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_nonzero_primitive_floats() { // f32 let values = &[ -2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, -6.306773e-34, 5.199601e31, 7.6132625e33, 0.00015323664, 9.4768183e36, -0.0005665587, 8.873326e-30, 0.09273134, -7.774831e33, 4.315623e-8, ]; let common_values = &[ (5.71262, 2), (780.036, 2), (224535.3, 2), (58.67172, 2), (73439.85, 2), (-58.01006, 2), (-66297.15, 2), (-66476.91, 2), (13200.071, 2), (3306.3635, 2), ]; let sample_median = (4.601794e-39, Some(4.606577e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871815997376882e34), standard_deviation: NiceFloat(1.8597574260800838e37), skewness: NiceFloat(-0.04588420234596291), excess_kurtosis: NiceFloat(174.30920609573673), }; random_nonzero_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 3.106206640558341e-146, 7.268713316268921e223, 1.1685126708702852e48, -1.0824685183946236e146, 3.114605160661583e-306, 2.2453015573637674e249, 1.2548860979388685e-35, -8.287939157477947e-27, 2.1255041535787165e-13, 4.815129234795048e-64, 1.3850402674408148e-17, -1.253571770758962e207, -1.4941028004491906e142, 4.366611961454907e-51, -7.063699168119985e17, -7.062565582436957e90, 1.1662950933663382e-221, 2.1976577668343592e-97, -2.8212944266870196e-137, 1.2250916338748408e-222, ]; let common_values = &[ (-9967188.16722, 1), (1808.830612999, 1), (32578528203.69, 1), (5643444.695113, 1), (812845035127.8, 1), (-13741970740.45, 1), (-1434325.082519, 1), (-33781527.93352, 1), (-374012916597.5, 1), (-46629353341.91, 1), ]; let sample_median = (2.772306592172272e-308, Some(2.7820731194979217e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581038e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_nonzero_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_nonzero_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, deleted_uniform_primitive_int_assertions, }; fn random_nonzero_signeds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { deleted_uniform_primitive_int_assertions( random_nonzero_signeds::(EXAMPLE_SEED), T::MIN, T::MAX, T::ZERO, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_nonzero_signeds() { // i8 let values = &[ 113, -17, 69, 108, -28, -46, -88, -95, 87, 32, 110, 83, -68, 34, 89, -18, 93, -56, -107, 115, ]; let common_values = &[ (-42, 4112), (86, 4092), (-90, 4063), (22, 4061), (126, 4061), (93, 4054), (55, 4053), (-65, 4052), (36, 4049), (42, 4047), ]; let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5019607843137255), standard_deviation: NiceFloat(74.04502469734098), skewness: NiceFloat(0.00007944171209676364), excess_kurtosis: NiceFloat(-1.207067080672989), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5131950000000044), standard_deviation: NiceFloat(74.04373630744782), skewness: NiceFloat(-0.00024235105395531954), excess_kurtosis: NiceFloat(-1.2065292546223), }; random_nonzero_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16 let values = &[ -4239, 27717, -11548, -24152, 8279, 21358, 8892, -4519, -14243, 29589, -27203, -13863, -28043, 18463, -22121, 8622, 9735, -28591, 32584, -32655, ]; let common_values = &[ (27447, 34), (-898, 33), (5606, 33), (5836, 33), (-15023, 33), (-197, 32), (3582, 32), (-7314, 32), (19279, 32), (20588, 32), ]; let pop_median = (-1, None); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5000076295109483), standard_deviation: NiceFloat(18918.757957822254), skewness: NiceFloat(1.2098327432880512e-9), excess_kurtosis: NiceFloat(-1.200027466379059), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.019281000000275), standard_deviation: NiceFloat(18918.558463263365), skewness: NiceFloat(-0.0001978759287576409), excess_kurtosis: NiceFloat(-1.1998315900739762), }; random_nonzero_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32 let values = &[ 1816522609, -1582771484, 1399726167, -296148292, 1939195997, -908487235, 1210028661, 565094807, -1873730041, -2140045496, 1999530985, -207351284, -147083662, -1197429209, -60545688, 1164671716, -1900807950, -1120015889, 130045419, -1296475448, ]; let common_values = &[ (20095656, 2), (29107328, 2), (83328146, 2), (96543416, 2), (-59532811, 2), (-72250103, 2), (-88423413, 2), (109257003, 2), (132308363, 2), (140940582, 2), ]; let pop_median = (-1, None); let sample_median = (-3037682, Some(-3035621)); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5000000001164153), standard_deviation: NiceFloat(1239850262.3974571), skewness: NiceFloat(2.8168398703367104e-19), excess_kurtosis: NiceFloat(-1.2000000004190956), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1708075.0735549931), standard_deviation: NiceFloat(1239705769.0057693), skewness: NiceFloat(0.0016706713036923025), excess_kurtosis: NiceFloat(-1.2008047456655335), }; random_nonzero_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64 let values = &[ -6797951759004864655, -1271947227506532265, -3901922961219270563, 2427063716414460533, -9191425414850861561, -890566981564077079, -5142919287782265230, 5002226935030621544, -4810431611861206798, -5568319649096903189, -4872912570782646188, 1513424385005459611, 2484972586252155822, -5374443828107932323, 4344958725064805398, 3252798961345668310, -7926092317508205845, -6066899635121005951, 6654913321726770291, -7940875872878966649, ]; let common_values = &[ (26914038281329, 1), (32553719576594, 1), (53892651831494, 1), (66354421349686, 1), (86226284907602, 1), (89837182726049, 1), (95691351770484, 1), (-45554336062456, 1), (-45700426911569, 1), (-50232881235535, 1), ]; let pop_median = (-1, None); let sample_median = (-5305218289400184, Some(-5271053954352614)); let pop_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(5.325116328314171e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.1999999999999997), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-5606718482239710.0), standard_deviation: NiceFloat(5.325063903618647e18), skewness: NiceFloat(0.0011248693866288532), excess_kurtosis: NiceFloat(-1.200551786344892), }; random_nonzero_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128 let values = &[ -23463284981077418827267202649482203279, 44771423227283929645271838218448652381, -16428061189408542358428117207094319609, 92274800069126412258941638023956901490, -102717367487498748896125496933502158606, 27917752305106984883503397141734686804, -99140989835634876684435608594951128146, 60003549963171791765607325839025294358, -111914544889959057594096246794876321045, -146483304948093240780207189413481284493, -153586157979719815495295783806580152035, 33018320828004690757952445968579104952, 24887066387352849554815992782110776358, 79085537771456044427857440036467563654, 19637669411666889498466854442215856999, -102694834600182680427466985752932389987, -85298529075242965442847250193117638905, -67944983823469089095474618642592431761, 105189689748742230503365861545668092951, -81854971460639281226116917410207070376, ]; let common_values = &[ (68570815139656170990830410045915, 1), (381682482227926990846204728028719, 1), (565207126752383841908924745713103, 1), (717866653939818807939025508430762, 1), (775173738585689418081884794376186, 1), (818497230601034032775791540657915, 1), (-307666299724089175945459600408325, 1), (-413570452196184856884474016102340, 1), (-789195894019805665974324122519229, 1), (-843024079296967638987633859098218, 1), ]; let pop_median = (-1, None); let sample_median = ( -10072503186589325235371920356302834, Some(-9899574809150113239535729822182407), ); let pop_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(9.82310580711434e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.1999999999999997), }; let sample_moment_stats = MomentStats { mean: NiceFloat(8.651168263124604e34), standard_deviation: NiceFloat(9.82707680675722e37), skewness: NiceFloat(0.00010083962773749455), excess_kurtosis: NiceFloat(-1.2019920806441844), }; random_nonzero_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_positive_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_positive_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_positive_finite_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_positive_finite_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_positive_finite_primitive_floats() { // f32 let values = &[ 9.5715654e26, 209.6476, 386935780.0, 7.965817e30, 0.00021030706, 0.0027270128, 3.4398167e-34, 2.3397111e14, 44567765000.0, 2.3479653e21, 0.00033502287, 2.4460542e-19, 0.0017637977, 7.956594e-26, 2.62625e-33, 0.059202384, 3.9310746e34, 1916542100000.0, 3.847343e14, 5.2843143e13, ]; let common_values = &[ (59.25553, 2), (68.23402, 2), (75936.53, 2), (9.581732, 2), (0.7711715, 2), (0.8694567, 2), (1.6738155, 2), (1168060.5, 2), (12.359466, 2), (146.89862, 2), ]; let sample_median = (1.3686414, Some(1.3686574)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0305910210122042e36), standard_deviation: NiceFloat(1.8908940416475047e37), skewness: NiceFloat(12.30495721768228), excess_kurtosis: NiceFloat(168.0100163146302), }; random_positive_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 1.553103320279171e-146, 3.399767269777243e138, 6.920999672956352e-119, 7.798612728071752e-244, 1.7297528302435229e-274, 1.6730698009459568e253, 3.494622700146595e-115, 7.870553878200458e-50, 1.88707572126009e-10, 3.680784346523073e244, 2.2006770848831818e307, 3.0495236892779565e-279, 7.105167957384262e30, 7.68196442827874e21, 4.043761560817649e-187, 2.743276189070554e-146, 1.4322725127932769e140, 2.0686074901798122e-203, 7.761683804525804e-301, 5.6617484237282776e-21, ]; let common_values = &[ (66730.2435683, 1), (2.857475472056, 1), (2042187757.012, 1), (206.7039373431, 1), (2621701.092576, 1), (27.03018555735, 1), (3.025032765206, 1), (454348736.2729, 1), (5683730270.934, 1), (79306986.55539, 1), ]; let sample_median = (1.4868797963072014, Some(1.488082067196604)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.3252967815615318e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_finite_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_positive_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_positive_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_positive_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_positive_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_positive_primitive_floats() { // f32 let values = &[ 9.5715654e26, 209.6476, 386935780.0, 7.965817e30, 0.00021030706, 0.0027270128, 3.4398167e-34, 2.3397111e14, 44567765000.0, 2.3479653e21, 0.00033502287, 2.4460542e-19, 0.0017637977, 7.956594e-26, 2.62625e-33, 0.059202384, 3.9310746e34, 1916542100000.0, 3.847343e14, 5.2843143e13, ]; let common_values = &[ (59.25553, 2), (68.23402, 2), (75936.53, 2), (9.581732, 2), (0.7711715, 2), (0.8694567, 2), (1.6738155, 2), (1168060.5, 2), (12.359466, 2), (146.89862, 2), ]; let sample_median = (1.3686414, Some(1.3686574)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0305910210122042e36), standard_deviation: NiceFloat(1.8908940416475047e37), skewness: NiceFloat(12.30495721768228), excess_kurtosis: NiceFloat(168.0100163146302), }; random_positive_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 1.553103320279171e-146, 3.399767269777243e138, 6.920999672956352e-119, 7.798612728071752e-244, 1.7297528302435229e-274, 1.6730698009459568e253, 3.494622700146595e-115, 7.870553878200458e-50, 1.88707572126009e-10, 3.680784346523073e244, 2.2006770848831818e307, 3.0495236892779565e-279, 7.105167957384262e30, 7.68196442827874e21, 4.043761560817649e-187, 2.743276189070554e-146, 1.4322725127932769e140, 2.0686074901798122e-203, 7.761683804525804e-301, 5.6617484237282776e-21, ]; let common_values = &[ (66730.2435683, 1), (2.857475472056, 1), (2042187757.012, 1), (206.7039373431, 1), (2621701.092576, 1), (27.03018555735, 1), (3.025032765206, 1), (454348736.2729, 1), (5683730270.934, 1), (79306986.55539, 1), ]; let sample_median = (1.4868797963072014, Some(1.488082067196604)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.3252967815615318e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_positive_signeds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_positive_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_positive_signeds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_positive_signeds::(EXAMPLE_SEED), T::ONE, T::MAX, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_positive_signeds() { // i8 let values = &[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, 1, 113, 54, 10, 47, 17, 89, 92, 119, 66]; let common_values = &[ (2, 8156), (121, 8095), (48, 8062), (113, 8024), (78, 8003), (8, 7997), (91, 7995), (77, 7994), (50, 7990), (102, 7989), ]; let pop_median = (64, None); let sample_median = (64, None); let pop_moment_stats = MomentStats { mean: NiceFloat(64.0), standard_deviation: NiceFloat(36.66060555964672), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001488095238095), }; let sample_moment_stats = MomentStats { mean: NiceFloat(63.982919000001765), standard_deviation: NiceFloat(36.67212767326611), skewness: NiceFloat(-0.0007589869063919588), excess_kurtosis: NiceFloat(-1.1997242130732357), }; random_positive_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16 let values = &[ 28529, 22667, 19345, 3398, 1402, 28100, 12052, 11409, 24046, 11152, 30158, 19629, 23709, 29262, 20999, 21707, 8622, 19470, 16708, 31300, ]; let common_values = &[ (12912, 55), (10381, 54), (18999, 54), (8262, 53), (16860, 52), (18853, 52), (26980, 52), (29418, 52), (1430, 51), (3511, 51), ]; let pop_median = (16384, None); let sample_median = (16394, None); let pop_moment_stats = MomentStats { mean: NiceFloat(16384.0), standard_deviation: NiceFloat(9459.018130863265), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000022353106), }; let sample_moment_stats = MomentStats { mean: NiceFloat(16388.51686199981), standard_deviation: NiceFloat(9454.07106153838), skewness: NiceFloat(-0.0012487208201804533), excess_kurtosis: NiceFloat(-1.1990539374536704), }; random_positive_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32 let values = &[ 1816522609, 1129424328, 1303937374, 1925780962, 962364894, 993179566, 132423026, 1465174948, 1361446689, 1660850464, 967812609, 546333625, 988229434, 365231847, 156905000, 1030913586, 2029143403, 1407130983, 1471083767, 1447050754, ]; let common_values = &[ (1028854, 2), (5270005, 2), (52436108, 2), (53442532, 2), (54049511, 2), (55679225, 2), (56850838, 2), (96093392, 2), (100688553, 2), (103402223, 2), ]; let pop_median = (1073741824, None); let sample_median = (1072627595, Some(1072629791)); let pop_moment_stats = MomentStats { mean: NiceFloat(1073741824.0), standard_deviation: NiceFloat(619925130.8378847), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1072577564.7313439), standard_deviation: NiceFloat(620056431.3063871), skewness: NiceFloat(0.0014601286400032305), excess_kurtosis: NiceFloat(-1.1999609793276922), }; random_positive_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64 let values = &[ 2425420277849911153, 6679477581841711279, 2839052228832469367, 969765657606132654, 511145952062627954, 8395344737368636720, 2894558908706954428, 3872377140940026972, 4461360302071018053, 8265671087366068090, 9205171493858792138, 440136107976613346, 5068356638012531024, 4934264084518118479, 1818371016611966298, 2429107481069952550, 6703623406340484388, 1574554890859127809, 117271882755911480, 4303959799021363928, ]; let common_values = &[ (3324105909387, 1), (3803613521411, 1), (5209780367047, 1), (6536744795656, 1), (20781229071796, 1), (25846957723851, 1), (38009592066251, 1), (42260644601025, 1), (48213785128580, 1), (51745785759707, 1), ]; let pop_median = (4611686018427387904, None); let sample_median = (4611643941266241783, Some(4611644928041858554)); let pop_moment_stats = MomentStats { mean: NiceFloat(4.611686018427388e18), standard_deviation: NiceFloat(2.6625581641570857e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(4.611835802844851e18), standard_deviation: NiceFloat(2.6620357716239764e18), skewness: NiceFloat(-0.0011632136334031786), excess_kurtosis: NiceFloat(-1.1990763518455585), }; random_positive_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128 let values = &[ 146677898479391812904420101066401902449, 89542846454567859290543676436897304763, 104428938702835062297974834887506827292, 57633666711134371144783889328118789015, 57933954804712334978865086222806519588, 42662156461077357613672189956089449110, 120341622017198698000238591126723816325, 24101139564873918071809040180452920154, 103736512989781418566515148496075680557, 32809772643191914208019959002472965975, 108368929700948284627873319254722115143, 75471221947321674806749768444016968803, 22855029776201969245611509711160631693, 141239989761550750474583532371490947671, 6597717003000338260251854527757143775, 118127485834862173804991044383172101987, 34322302054094513880662232930594566845, 15046161600550609659323678646530441128, 64426056034886319779095794279543419785, 152274179269659595492344917098779277590, ]; let common_values = &[ (49706069066166082911282159414761, 1), (294249217877016568639819742131116, 1), (779571295345117968523381651468144, 1), (1028301047920525679733841423086654, 1), (1041495389520167619171132640545590, 1), (1161107238544942492727270602500750, 1), (1336346376891865515807867774335733, 1), (1493657440169244835704046060805058, 1), (1634887730516500612018549047947720, 1), (2085175602444743211488924039302279, 1), ]; let pop_median = (85070591730234615865843651857942052864, None); let sample_median = ( 84985358969888408674238551739287032693, Some(84985395712350170023498559520469041517), ); let pop_moment_stats = MomentStats { mean: NiceFloat(8.507059173023462e37), standard_deviation: NiceFloat(4.91155290355717e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(8.501039971148385e37), standard_deviation: NiceFloat(4.910082612813726e37), skewness: NiceFloat(0.0016680470828691063), excess_kurtosis: NiceFloat(-1.199401614583414), }; random_positive_signeds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_positive_unsigneds.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_positive_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_positive_unsigneds_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_positive_unsigneds::(EXAMPLE_SEED), T::ONE, T::MAX, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_positive_unsigneds() { // u8 let values = &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ]; let common_values = &[ (214, 4112), (86, 4092), (166, 4063), (22, 4061), (126, 4061), (93, 4054), (55, 4053), (191, 4052), (36, 4049), (42, 4047), ]; let pop_median = (128, None); let sample_median = (128, None); let pop_moment_stats = MomentStats { mean: NiceFloat(128.0), standard_deviation: NiceFloat(73.6115932898254), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000369094488188), }; let sample_moment_stats = MomentStats { mean: NiceFloat(127.95426100000232), standard_deviation: NiceFloat(73.62056563848995), skewness: NiceFloat(0.0005293443118466251), excess_kurtosis: NiceFloat(-1.2003369218920343), }; random_positive_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16 let values = &[ 61297, 27717, 53988, 41384, 8279, 21358, 8892, 61017, 51293, 29589, 38333, 51673, 37493, 18463, 43415, 8622, 9735, 36945, 32584, 32881, ]; let common_values = &[ (27447, 34), (5606, 33), (5836, 33), (50513, 33), (64638, 33), (3582, 32), (19279, 32), (20588, 32), (27377, 32), (40163, 32), ]; let pop_median = (32768, None); let sample_median = (32764, None); let pop_moment_stats = MomentStats { mean: NiceFloat(32768.0), standard_deviation: NiceFloat(18918.32494346861), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000005588105), }; let sample_moment_stats = MomentStats { mean: NiceFloat(32769.087121000004), standard_deviation: NiceFloat(18919.668065423208), skewness: NiceFloat(0.00005282326597264531), excess_kurtosis: NiceFloat(-1.2002448370280603), }; random_positive_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32 let values = &[ 1816522609, 2712195812, 1399726167, 3998819004, 1939195997, 3386480061, 1210028661, 565094807, 2421237255, 2154921800, 1999530985, 4087616012, 4147883634, 3097538087, 4234421608, 1164671716, 2394159346, 3174951407, 130045419, 2998491848, ]; let common_values = &[ (20095656, 2), (29107328, 2), (83328146, 2), (96543416, 2), (109257003, 2), (132308363, 2), (140940582, 2), (168698132, 2), (182460287, 2), (184573980, 2), ]; let pop_median = (2147483648, None); let sample_median = (2150296456, Some(2150302375)); let pop_moment_stats = MomentStats { mean: NiceFloat(2147483648.0), standard_deviation: NiceFloat(1239850261.9644444), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2148696150.6876254), standard_deviation: NiceFloat(1239453907.667566), skewness: NiceFloat(-0.0016842295222180032), excess_kurtosis: NiceFloat(-1.2007050556559806), }; random_positive_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64 let values = &[ 11648792314704686961, 17174796846203019351, 14544821112490281053, 2427063716414460533, 9255318658858690055, 17556177092145474537, 13303824785927286386, 5002226935030621544, 13636312461848344818, 12878424424612648427, 13573831502926905428, 1513424385005459611, 2484972586252155822, 13072300245601619293, 4344958725064805398, 3252798961345668310, 10520651756201345771, 12379844438588545665, 6654913321726770291, 10505868200830584967, ]; let common_values = &[ (26914038281329, 1), (32553719576594, 1), (53892651831494, 1), (66354421349686, 1), (86226284907602, 1), (89837182726049, 1), (95691351770484, 1), (166741761063383, 1), (171574734234584, 1), (212518263578065, 1), ]; let pop_median = (9223372036854775808, None); let sample_median = (9228795451400314170, Some(9228799993322832549)); let pop_moment_stats = MomentStats { mean: NiceFloat(9.223372036854776e18), standard_deviation: NiceFloat(5.325116328314171e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(9.223151767642118e18), standard_deviation: NiceFloat(5.323459825978695e18), skewness: NiceFloat(-0.0007960342667556958), excess_kurtosis: NiceFloat(-1.2005689675667335), }; random_positive_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u128 let values = &[ 316819081939861044636107404782286008177, 44771423227283929645271838218448652381, 323854305731529921104946490224673891847, 92274800069126412258941638023956901490, 237564999433439714567249110498266052850, 27917752305106984883503397141734686804, 241141377085303586778938998836817083310, 60003549963171791765607325839025294358, 228367822030979405869278360636891890411, 193799061972845222683167418018286926963, 186696208941218647968078823625188059421, 33018320828004690757952445968579104952, 24887066387352849554815992782110776358, 79085537771456044427857440036467563654, 19637669411666889498466854442215856999, 237587532320755783035907621678835821469, 254983837845695498020527357238650572551, 272337383097469374367899988789175779695, 105189689748742230503365861545668092951, 258427395460299182237257690021561141080, ]; let common_values = &[ (68570815139656170990830410045915, 1), (381682482227926990846204728028719, 1), (565207126752383841908924745713103, 1), (717866653939818807939025508430762, 1), (775173738585689418081884794376186, 1), (818497230601034032775791540657915, 1), (1224023028796761386468452212527255, 1), (1379103576141836593923341631562888, 1), (1765193876177447622538546939111747, 1), (2049979073093489039458791025727172, 1), ]; let pop_median = (170141183460469231731687303715884105728, None); let sample_median = ( 170151864710150847082485192587168481404, Some(170151925651660504506169909296979843840), ); let pop_moment_stats = MomentStats { mean: NiceFloat(1.7014118346046923e38), standard_deviation: NiceFloat(9.82310580711434e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.702375633317502e38), standard_deviation: NiceFloat(9.815169783582294e37), skewness: NiceFloat(-0.0005571163134867303), excess_kurtosis: NiceFloat(-1.1992896928276262), }; random_positive_unsigneds_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_primitive_float_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_primitive_float_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn random_primitive_float_inclusive_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_primitive_float_inclusive_range::(EXAMPLE_SEED, a, b), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_primitive_float_inclusive_range() { // f32, a = 1.0, b = 2.0 let values = &[ 1.5463697, 1.6846209, 1.6517982, 1.6963725, 1.246657, 1.0557153, 1.8866968, 1.8430634, 1.0973871, 1.4662611, 1.8181343, 1.8396878, 1.7092294, 1.6617042, 1.7495066, 1.1922526, 1.9193928, 1.1640857, 1.2869775, 1.7921972, ]; let common_values = &[ (1.262395, 4), (1.619045, 4), (1.942131, 4), (1.0062196, 4), (1.0075867, 4), (1.0664382, 4), (1.0932482, 4), (1.1049225, 4), (1.1625684, 4), (1.1672009, 4), ]; let sample_median = (1.4996792, Some(1.4996796)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.4997834476890244), standard_deviation: NiceFloat(0.2887567306490316), skewness: NiceFloat(0.001395347389592521), excess_kurtosis: NiceFloat(-1.2017290675577252), }; random_primitive_float_inclusive_range_helper::( 1.0, 2.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1 let values = &[ 5.664681e-11, 1.2492925e-35, 2.3242339e-29, 4.699183e-7, -2.8244436e-36, -2.264039e-37, -0.0000017299129, 1.40616e-23, 2.7418007e-27, 1.5418819e-16, -1.8473076e-36, -2.4935917e-21, -3.373897e-37, -7.5386525e-15, -2.2595721e-7, -8.293393e-39, 0.0025248893, 1.1819218e-25, 2.3384073e-23, 3.1464167e-24, ]; let common_values = &[ (0.02590246, 2), (-0.09233444, 2), (0.001610253, 2), (0.010553952, 2), (0.020663222, 2), (0.031000609, 2), (1.30495e-38, 2), (1.409154e-8, 2), (2.599722e-7, 2), (3.67508e-29, 2), ]; let sample_median = (-1.472737e-39, Some(-1.471169e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.190292459186594e-6), standard_deviation: NiceFloat(0.007506907081695582), skewness: NiceFloat(-0.02559343794273501), excess_kurtosis: NiceFloat(84.97988219106435), }; random_primitive_float_inclusive_range_helper::( -0.1, 0.1, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π let values = &[ 2.811021, 3.0798163, 2.8497639, 2.9021935, 3.0803769, 3.0796993, 3.088304, 2.872187, 2.8092258, 2.7708528, 3.0054183, 2.7851858, 2.745991, 2.9290476, 2.913056, 2.899723, 2.9672115, 2.875196, 3.01054, 3.0299006, ]; let common_values = &[ (2.7395, 7), (2.7335808, 7), (2.8363338, 7), (3.0879333, 7), (2.760186, 6), (2.799341, 6), (2.933202, 6), (2.978166, 6), (3.012332, 6), (3.034496, 6), ]; let sample_median = (2.9301434, Some(2.930144)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9300705904196347), standard_deviation: NiceFloat(0.12218018336191779), skewness: NiceFloat(-0.0024072138827345158), excess_kurtosis: NiceFloat(-1.1980037439170255), }; random_primitive_float_inclusive_range_helper::( core::f32::consts::E, core::f32::consts::PI, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0 let values = &[ 100.96766, 100.552864, 100.684616, 100.34195, 100.725746, 100.24665, 100.79547, 100.21028, 100.7486, 100.09738, 100.360596, 100.518265, 100.83968, 100.47318, 100.16781, 100.6617, 100.48242, 100.192245, 100.84114, 100.095436, ]; let common_values = &[ (100.32666, 22), (100.33122, 22), (100.60651, 22), (100.29688, 21), (100.51455, 21), (100.75446, 21), (100.672554, 21), (100.863556, 21), (100.125, 20), (100.06987, 20), ]; let sample_median = (100.50014, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.5000247275421), standard_deviation: NiceFloat(0.2887172501103727), skewness: NiceFloat(0.0005303743867281354), excess_kurtosis: NiceFloat(-1.2019547226159832), }; random_primitive_float_inclusive_range_helper::( 100.0, 101.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0e38, b = Infinity let values = &[ 1.4647999e38, 3.1018272e38, 1.582411e38, 1.5544886e38, 1.5924082e38, 2.9619212e38, 2.8168304e38, 2.9816339e38, 1.2098325e38, 2.5528384e38, 1.0473973e38, 2.2168899e38, 1.8072246e38, 1.732986e38, 1.0828477e38, 1.3966511e38, 2.61352e38, 1.6959917e38, 1.727243e38, 2.8140436e38, ]; let common_values = &[ (1.223221e38, 4), (1.372136e38, 4), (1.0892582e38, 4), (1.4897022e38, 4), (1.5085965e38, 4), (1.5266252e38, 4), (1.8360457e38, 4), (2.5784374e38, 4), (2.6144523e38, 4), (2.7852527e38, 4), ]; let sample_median = (1.8507265e38, Some(1.8507311e38)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0095713198371904e38), standard_deviation: NiceFloat(7.129528670871142e37), skewness: NiceFloat(0.37808793164351623), excess_kurtosis: NiceFloat(-1.168840184381319), }; random_primitive_float_inclusive_range_helper::( 1.0e38, f32::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = f32::MIN_POSITIVE_SUBNORMAL let values = &[ -0.0, -1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, -0.0, -0.0, -1.0e-45, -0.0, -1.0e-45, 1.0e-45, 0.0, -0.0, -1.0e-45, -0.0, 0.0, 1.0e-45, ]; let common_values = &[(-0.0, 250314), (1.0e-45, 250015), (0.0, 249955), (-1.0e-45, 249716)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(4.18988240833055e-49), standard_deviation: NiceFloat(9.90601474026171e-46), skewness: NiceFloat(-0.00042250825585668007), excess_kurtosis: NiceFloat(-0.9989230633891024), }; random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = f32::MIN_POSITIVE_SUBNORMAL let values = &[ 0.0, -0.0, 0.0, 1.0e-45, 0.0, 0.0, -0.0, 0.0, -0.0, 1.0e-45, 0.0, -0.0, 0.0, 1.0e-45, 1.0e-45, -0.0, 0.0, -0.0, 1.0e-45, 1.0e-45, ]; let common_values = &[(0.0, 333784), (1.0e-45, 333516), (-0.0, 332700)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(4.673554586277644e-46), standard_deviation: NiceFloat(6.606692048548519e-46), skewness: NiceFloat(0.7062350975867705), excess_kurtosis: NiceFloat(-1.5012319869365465), }; random_primitive_float_inclusive_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 0.0, b = 0.0 let values = &[0.0; 20]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( 0.0, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = -f32::MIN_POSITIVE_SUBNORMAL let values = &[-1.0e-45; 20]; let common_values = &[(-1.0e-45, 1000000)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.401298464324817e-45), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = 0.0 let values = &[ -0.0, -1.0e-45, -0.0, 0.0, -0.0, -0.0, -1.0e-45, -0.0, -1.0e-45, 0.0, -0.0, -1.0e-45, -0.0, 0.0, 0.0, -1.0e-45, -0.0, -1.0e-45, 0.0, 0.0, ]; let common_values = &[(-0.0, 333784), (0.0, 333516), (-1.0e-45, 332700)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.662119990808644e-46), standard_deviation: NiceFloat(6.602643154251322e-46), skewness: NiceFloat(-0.7101318209186737), excess_kurtosis: NiceFloat(-1.4957127969187527), }; random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -Infinity, b = Infinity let values = &[ -2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, -6.306773e-34, 5.199601e31, 7.6132625e33, 0.00015323664, 9.4768183e36, -0.0005665587, 8.873326e-30, 0.09273134, -7.774831e33, 4.315623e-8, ]; let common_values = &[ (5.71262, 2), (780.036, 2), (224535.3, 2), (58.67172, 2), (73439.85, 2), (-58.01006, 2), (-66297.15, 2), (-66476.91, 2), (13200.071, 2), (3306.3635, 2), ]; let sample_median = (4.601794e-39, Some(4.606577e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871815997376882e34), standard_deviation: NiceFloat(1.8597574260800838e37), skewness: NiceFloat(-0.04588420234596291), excess_kurtosis: NiceFloat(174.30920609573673), }; random_primitive_float_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = -0.0 let values = &[-0.0; 20]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -0.0, -0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0 let values = &[ 1.5514873723431857, 1.027857700733222, 1.0138546387920868, 1.3122324563791183, 1.3405051829686652, 1.035872192413254, 1.1044047458079171, 1.1492076100807012, 1.6654435140088601, 1.0970321240173933, 1.7768534778894969, 1.7596944738316886, 1.4195592641558248, 1.6870312410839399, 1.6389477926482805, 1.7596601473487807, 1.5802838577448093, 1.6118733984422406, 1.6845629053029185, 1.7184068862055195, ]; let common_values = &[ (1.403773233, 1), (1.4279826281, 1), (1.00013172472, 1), (1.12691284792, 1), (1.18903919511, 1), (1.19748472183, 1), (1.22623118845, 1), (1.28755110409, 1), (1.29488660814, 1), (1.29653599853, 1), ]; let sample_median = (1.5009930608108493, Some(1.5009982675741425)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5004909167990677), standard_deviation: NiceFloat(0.288665614327161), skewness: NiceFloat(-0.0026087726173027), excess_kurtosis: NiceFloat(-1.199166529481062), }; random_primitive_float_inclusive_range_helper::( 1.0, 2.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1 let values = &[ -7.283095678343042e-164, 4.085787276271492e-169, -1.6885972585325658e-191, -1.5059586906723643e-66, -6.637230143944272e-36, 2.0111059084569595e-54, -3.2171834547379634e-195, -1.4304898186595632e-260, -5.910214544689135e-300, 4.248352948466203e-63, -3.6882240870537675e-31, 8.12900376877632e-277, 8.630695763640745e-286, -2.7842211494385523e-123, -4.271131813514248e-164, 1.613930919542087e-167, -5.39182068994581e-107, -1.4532461060667818e-9, -1.9793582955127234e-289, 5.420373932282823e-196, ]; let common_values = &[ (5.62015686679e-6, 1), (-0.09576016351376, 1), (-3.9141428595e-60, 1), (-4.5355157777e-28, 1), (0.008342058495796, 1), (0.012335893098144, 1), (0.014079819535342, 1), (0.014718940078426, 1), (0.031741597598458, 1), (0.033991243007763, 1), ]; let sample_median = (1.566509212534917e-309, Some(1.56863192120459e-309)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.4695816858634463e-7), standard_deviation: NiceFloat(0.002635102953882735), skewness: NiceFloat(0.27772415900587566), excess_kurtosis: NiceFloat(707.152044677798), }; random_primitive_float_inclusive_range_helper::( -0.1, 0.1, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π let values = &[ 2.8212565731454164, 3.103466176726195, 2.888459041537496, 2.94833744629582, 2.9285662350147255, 3.059002590500268, 2.808432051804475, 3.077033595571352, 3.0898242789403123, 3.093937352570613, 2.7596383425151814, 3.1049928702292573, 2.7453107067232327, 3.0779370799622736, 2.9748071250720396, 2.927927166467895, 2.81511226878185, 2.928920013122519, 2.964625285981546, 3.046598518604858, ]; let common_values = &[ (2.7683806707, 1), (2.8058681766, 1), (2.8522842725, 1), (2.8873246989, 1), (2.72492950364, 1), (2.73164898148, 1), (2.73476073924, 1), (2.73598990929, 1), (2.73653142351, 1), (2.74563905301, 1), ]; let sample_median = (2.930132942011006, Some(2.9301336276615912)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.929964069913902), standard_deviation: NiceFloat(0.12226749948876238), skewness: NiceFloat(-0.0013881669668324012), excess_kurtosis: NiceFloat(-1.2003731669148405), }; random_primitive_float_inclusive_range_helper::( core::f64::consts::E, core::f64::consts::PI, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0 let values = &[ 100.60719315639041, 100.52293238466861, 100.39773606616421, 100.15849325452957, 100.62446491275823, 100.00756963969552, 100.87724201202582, 100.41761898323166, 100.61748356221035, 100.19203505270988, 100.00337267247278, 100.15603343751732, 100.23002386168925, 100.77135404787671, 100.23327285882462, 100.27432542366292, 100.63224218858957, 100.47879402977489, 100.50368945395086, 100.4540267175569, ]; let common_values = &[ (100.49174834, 1), (100.95678412, 1), (100.029622688, 1), (100.110761848, 1), (100.163351429, 1), (100.241016737, 1), (100.334091318, 1), (100.374320788, 1), (100.375142847, 1), (100.403842534, 1), ]; let sample_median = (100.49938135068814, Some(100.49938267498312)); let sample_moment_stats = MomentStats { mean: NiceFloat(100.49957670089151), standard_deviation: NiceFloat(0.28876054194108447), skewness: NiceFloat(0.00047268031818767473), excess_kurtosis: NiceFloat(-1.2008323763153763), }; random_primitive_float_inclusive_range_helper::( 100.0, 101.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0e38, b = Infinity let values = &[ 1.3219190533477493e200, 3.652437632585123e180, 2.0420353527516904e248, 2.505458962964126e276, 2.659899792371364e116, 2.7125386559147274e90, 9.536479965391043e185, 9.567216720381635e239, 5.16993041287954e245, 4.939547529284952e179, 3.1175116898205872e224, 1.7555281884088452e42, 5.429209768108731e84, 1.0447670959436904e299, 1.9580250342195754e105, 8.848423533619703e204, 3.4434065546244285e79, 3.6093218170205304e216, 8.464035133686624e293, 1.22423660941592e120, ]; let common_values = &[ (2.141438721e116, 1), (8.7676954155e86, 1), (1.28439118539e55, 1), (1.79171075176e53, 1), (2.10333657725e74, 1), (2.3236426209e231, 1), (2.95823857742e58, 1), (3.1078914828e141, 1), (3.38975629714e61, 1), (4.28790184556e74, 1), ]; let sample_median = (1.2523958970084127e173, Some(1.2542732495420994e173)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.939399538027295e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( 1.0e38, f64::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = f64::MIN_POSITIVE_SUBNORMAL let values = &[ -0.0, -5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, -0.0, -0.0, -5.0e-324, -0.0, -5.0e-324, 5.0e-324, 0.0, -0.0, -5.0e-324, -0.0, 0.0, 5.0e-324, ]; let common_values = &[(-0.0, 250314), (5.0e-324, 250015), (0.0, 249955), (-5.0e-324, 249716)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = f64::MIN_POSITIVE_SUBNORMAL let values = &[ 0.0, -0.0, 0.0, 5.0e-324, 0.0, 0.0, -0.0, 0.0, -0.0, 5.0e-324, 0.0, -0.0, 0.0, 5.0e-324, 5.0e-324, -0.0, 0.0, -0.0, 5.0e-324, 5.0e-324, ]; let common_values = &[(0.0, 333784), (5.0e-324, 333516), (-0.0, 332700)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 0.0, b = 0.0 let values = &[0.0; 20]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( 0.0, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = -f64::MIN_POSITIVE_SUBNORMAL let values = &[-5.0e-324; 20]; let common_values = &[(-5.0e-324, 1000000)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = 0.0 let values = &[ -0.0, -5.0e-324, -0.0, 0.0, -0.0, -0.0, -5.0e-324, -0.0, -5.0e-324, 0.0, -0.0, -5.0e-324, -0.0, 0.0, 0.0, -5.0e-324, -0.0, -5.0e-324, 0.0, 0.0, ]; let common_values = &[(-0.0, 333784), (0.0, 333516), (-5.0e-324, 332700)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -Infinity, b = Infinity let values = &[ 3.106206640558341e-146, 7.268713316268921e223, 1.1685126708702852e48, -1.0824685183946236e146, 3.114605160661583e-306, 2.2453015573637674e249, 1.2548860979388685e-35, -8.287939157477947e-27, 2.1255041535787165e-13, 4.815129234795048e-64, 1.3850402674408148e-17, -1.253571770758962e207, -1.4941028004491906e142, 4.366611961454907e-51, -7.063699168119985e17, -7.062565582436957e90, 1.1662950933663382e-221, 2.1976577668343592e-97, -2.8212944266870196e-137, 1.2250916338748408e-222, ]; let common_values = &[ (-9967188.16722, 1), (1808.830612999, 1), (32578528203.69, 1), (5643444.695113, 1), (812845035127.8, 1), (-13741970740.45, 1), (-1434325.082519, 1), (-33781527.93352, 1), (-374012916597.5, 1), (-46629353341.91, 1), ]; let sample_median = (2.772306592172272e-308, Some(2.7820731194979217e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581038e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = 0.0 let values = &[ 0.0, -0.0, -0.0, -0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, -0.0, ]; let common_values = &[(0.0, 500473), (-0.0, 499527)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_inclusive_range_helper::( -0.0, 0.0, values, common_values, sample_median, sample_moment_stats, ); } fn random_primitive_float_inclusive_range_fail_helper() { assert_panic!(random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::ZERO )); assert_panic!(random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::NAN )); } #[test] fn random_primitive_float_inclusive_range_fail() { apply_fn_to_primitive_floats!(random_primitive_float_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_primitive_float_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_primitive_float_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn random_primitive_float_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_primitive_float_range::(EXAMPLE_SEED, a, b), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_primitive_float_range() { // f32, a = 1.0, b = 2.0 let values = &[ 1.5463697, 1.2951918, 1.7384838, 1.2143862, 1.1419607, 1.0917295, 1.7257521, 1.849941, 1.1442195, 1.363777, 1.052571, 1.0717841, 1.9104315, 1.3754328, 1.590667, 1.0705026, 1.8980603, 1.8630176, 1.0212592, 1.3380667, ]; let common_values = &[ (1.9376882, 5), (1.012385, 4), (1.439915, 4), (1.709473, 4), (1.754993, 4), (1.944844, 4), (1.971242, 4), (1.978845, 4), (1.0289025, 4), (1.0466498, 4), ]; let sample_median = (1.499921, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.49979057649457), standard_deviation: NiceFloat(0.2887387766808365), skewness: NiceFloat(0.0002622267624830283), excess_kurtosis: NiceFloat(-1.1997935828388204), }; random_primitive_float_range_helper::( 1.0, 2.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1 let values = &[ 5.664681e-11, 1.2492925e-35, 2.3242339e-29, 4.699183e-7, -2.8244436e-36, -2.264039e-37, -0.0000017299129, 1.40616e-23, 2.7418007e-27, 1.5418819e-16, -1.8473076e-36, -2.4935917e-21, -3.373897e-37, -7.5386525e-15, -2.2595721e-7, -8.293393e-39, 0.0025248893, 1.1819218e-25, 2.3384073e-23, 3.1464167e-24, ]; let common_values = &[ (0.02590246, 2), (-0.09233444, 2), (0.001610253, 2), (0.010553952, 2), (0.020663222, 2), (0.031000609, 2), (1.30495e-38, 2), (1.409154e-8, 2), (2.599722e-7, 2), (3.67508e-29, 2), ]; let sample_median = (-1.472737e-39, Some(-1.471169e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.190292459186594e-6), standard_deviation: NiceFloat(0.007506907081695582), skewness: NiceFloat(-0.02559343794273501), excess_kurtosis: NiceFloat(84.97988219106435), }; random_primitive_float_range_helper::( -0.1, 0.1, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π let values = &[ 2.811021, 3.0798163, 2.8497639, 2.9021935, 3.0803769, 3.0796993, 3.088304, 2.872187, 2.8092258, 2.7708528, 3.0054183, 2.7851858, 2.745991, 2.9290476, 2.913056, 2.899723, 2.9672115, 2.875196, 3.01054, 3.0299006, ]; let common_values = &[ (2.7395, 7), (2.7335808, 7), (2.8363338, 7), (3.0879333, 7), (2.760186, 6), (2.799341, 6), (2.933202, 6), (2.978166, 6), (3.012332, 6), (3.034496, 6), ]; let sample_median = (2.9301434, Some(2.930144)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9300705904196347), standard_deviation: NiceFloat(0.12218018336191779), skewness: NiceFloat(-0.0024072138827345158), excess_kurtosis: NiceFloat(-1.1980037439170255), }; random_primitive_float_range_helper::( core::f32::consts::E, core::f32::consts::PI, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0 let values = &[ 100.96766, 100.10573, 100.102974, 100.47697, 100.441444, 100.94259, 100.696365, 100.36691, 100.79254, 100.435005, 100.23124, 100.153755, 100.25385, 100.64986, 100.26314, 100.148544, 100.28187, 100.3743, 100.18771, 100.901344, ]; let common_values = &[ (100.15877, 24), (100.081535, 22), (100.26679, 21), (100.56587, 21), (100.894196, 21), (100.3593, 20), (100.4054, 20), (100.30979, 20), (100.45853, 20), (100.49529, 20), ]; let sample_median = (100.50088, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.50054111846543), standard_deviation: NiceFloat(0.2888116297082562), skewness: NiceFloat(-0.003221278138738849), excess_kurtosis: NiceFloat(-1.2016989304148467), }; random_primitive_float_range_helper::( 100.0, 101.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0e38, b = Infinity let values = &[ 1.4647999e38, 3.1018272e38, 1.582411e38, 1.5544886e38, 1.5924082e38, 2.9619212e38, 2.8168304e38, 2.9816339e38, 1.2098325e38, 2.5528384e38, 1.0473973e38, 2.2168899e38, 1.8072246e38, 1.732986e38, 1.0828477e38, 1.3966511e38, 2.61352e38, 1.6959917e38, 1.727243e38, 2.8140436e38, ]; let common_values = &[ (1.223221e38, 4), (1.372136e38, 4), (1.0892582e38, 4), (1.4897022e38, 4), (1.5085965e38, 4), (1.5266252e38, 4), (1.8360457e38, 4), (2.5784374e38, 4), (2.6144523e38, 4), (2.7852527e38, 4), ]; let sample_median = (1.8507265e38, Some(1.8507311e38)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0095713198371904e38), standard_deviation: NiceFloat(7.129528670871142e37), skewness: NiceFloat(0.37808793164351623), excess_kurtosis: NiceFloat(-1.168840184381319), }; random_primitive_float_range_helper::( 1.0e38, f32::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = f32::MIN_POSITIVE_SUBNORMAL let values = &[ -0.0, -1.0e-45, -0.0, 0.0, -0.0, -0.0, -1.0e-45, -0.0, -1.0e-45, 0.0, -0.0, -1.0e-45, -0.0, 0.0, 0.0, -1.0e-45, -0.0, -1.0e-45, 0.0, 0.0, ]; let common_values = &[(-0.0, 333784), (0.0, 333516), (-1.0e-45, 332700)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.662119990808644e-46), standard_deviation: NiceFloat(6.602643154251322e-46), skewness: NiceFloat(-0.7101318209186737), excess_kurtosis: NiceFloat(-1.4957127969187527), }; random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = f32::MIN_POSITIVE_SUBNORMAL let values = &[ 0.0, -0.0, -0.0, -0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, -0.0, ]; let common_values = &[(0.0, 500473), (-0.0, 499527)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 0.0, b = f32::MIN_POSITIVE_SUBNORMAL let values = &[0.0; 20]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( 0.0, f32::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = -0.0 let values = &[-1.0e-45; 20]; let common_values = &[(-1.0e-45, 1000000)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.401298464324817e-45), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -0.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = 0.0 let values = &[ -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -0.0, -0.0, -1.0e-45, -0.0, -0.0, -0.0, -0.0, -1.0e-45, -0.0, -0.0, -0.0, -0.0, -1.0e-45, -0.0, -1.0e-45, ]; let common_values = &[(-0.0, 500473), (-1.0e-45, 499527)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-6.9998641798878095e-46), standard_deviation: NiceFloat(7.006492689759787e-46), skewness: NiceFloat(-0.0018920008465908337), excess_kurtosis: NiceFloat(-1.9999964203328955), }; random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -Infinity, b = Infinity let values = &[ -2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, -6.306773e-34, 5.199601e31, 7.6132625e33, 0.00015323664, 9.4768183e36, -0.0005665587, 8.873326e-30, 0.09273134, -7.774831e33, 4.315623e-8, ]; let common_values = &[ (5.71262, 2), (780.036, 2), (224535.3, 2), (58.67172, 2), (73439.85, 2), (-58.01006, 2), (-66297.15, 2), (-66476.91, 2), (13200.071, 2), (3306.3635, 2), ]; let sample_median = (4.601794e-39, Some(4.606577e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871815997376882e34), standard_deviation: NiceFloat(1.8597574260800838e37), skewness: NiceFloat(-0.04588420234596291), excess_kurtosis: NiceFloat(174.30920609573673), }; random_primitive_float_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = 0.0 let values = &[-0.0; 20]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -0.0, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0 let values = &[ 1.5514873723431857, 1.7356480435333936, 1.2240680379087014, 1.5721098095143498, 1.445723211731554, 1.443348441346778, 1.128043347677334, 1.9657544165271619, 1.259133073045527, 1.9463717627559034, 1.827615676661706, 1.3546147198266414, 1.3547277462886724, 1.6644379935168552, 1.7300004987549573, 1.1347106338290753, 1.6337434960012935, 1.9398684976828995, 1.5480087631774717, 1.5114010060819247, ]; let common_values = &[ (1.3443697926, 1), (1.3820769412, 1), (1.4136496448, 1), (1.05230401048, 1), (1.06345642396, 1), (1.08636222403, 1), (1.08890959097, 1), (1.10364420294, 1), (1.17100333598, 1), (1.21003284406, 1), ]; let sample_median = (1.4997587655631748, Some(1.4997590736389839)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5002317198585347), standard_deviation: NiceFloat(0.2886284765385832), skewness: NiceFloat(0.0005691088300059665), excess_kurtosis: NiceFloat(-1.1997562526471726), }; random_primitive_float_range_helper::( 1.0, 2.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1 let values = &[ -7.283095678343042e-164, 4.085787276271492e-169, -1.6885972585325658e-191, -1.5059586906723643e-66, -6.637230143944272e-36, 2.0111059084569595e-54, -3.2171834547379634e-195, -1.4304898186595632e-260, -5.910214544689135e-300, 4.248352948466203e-63, -3.6882240870537675e-31, 8.12900376877632e-277, 8.630695763640745e-286, -2.7842211494385523e-123, -4.271131813514248e-164, 1.613930919542087e-167, -5.39182068994581e-107, -1.4532461060667818e-9, -1.9793582955127234e-289, 5.420373932282823e-196, ]; let common_values = &[ (5.62015686679e-6, 1), (-0.09576016351376, 1), (-3.9141428595e-60, 1), (-4.5355157777e-28, 1), (0.008342058495796, 1), (0.012335893098144, 1), (0.014079819535342, 1), (0.014718940078426, 1), (0.031741597598458, 1), (0.033991243007763, 1), ]; let sample_median = (1.566509212534917e-309, Some(1.56863192120459e-309)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.4695816858634463e-7), standard_deviation: NiceFloat(0.002635102953882735), skewness: NiceFloat(0.27772415900587566), excess_kurtosis: NiceFloat(707.152044677798), }; random_primitive_float_range_helper::( -0.1, 0.1, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π let values = &[ 2.8212565731454164, 3.103466176726195, 2.888459041537496, 2.94833744629582, 2.9285662350147255, 3.059002590500268, 2.808432051804475, 3.077033595571352, 3.0898242789403123, 3.093937352570613, 2.7596383425151814, 3.1049928702292573, 2.7453107067232327, 3.0779370799622736, 2.9748071250720396, 2.927927166467895, 2.81511226878185, 2.928920013122519, 2.964625285981546, 3.046598518604858, ]; let common_values = &[ (2.7683806707, 1), (2.8058681766, 1), (2.8522842725, 1), (2.8873246989, 1), (2.72492950364, 1), (2.73164898148, 1), (2.73476073924, 1), (2.73598990929, 1), (2.73653142351, 1), (2.74563905301, 1), ]; let sample_median = (2.930132942011006, Some(2.9301336276615912)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.929964069913902), standard_deviation: NiceFloat(0.12226749948876238), skewness: NiceFloat(-0.0013881669668324012), excess_kurtosis: NiceFloat(-1.2003731669148405), }; random_primitive_float_range_helper::( core::f64::consts::E, core::f64::consts::PI, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0 let values = &[ 100.29519182996388, 100.21438631278083, 100.09172953867444, 100.84994110175992, 100.36377705862755, 100.07178414494646, 100.37543295746225, 100.07050270922983, 100.86301766610865, 100.33806669965496, 100.35496099272225, 100.93577122524063, 100.00524419289253, 100.29363379918549, 100.98421354539467, 100.68228296091216, 100.93250012468873, 100.1553701412652, 100.95333990532461, 100.2218641465098, ]; let common_values = &[ (100.10137554, 1), (100.34387327, 1), (100.223865218, 1), (100.237336607, 1), (100.241016737, 1), (100.358275298, 1), (100.490668361, 1), (100.563824325, 1), (100.567992111, 1), (100.619353436, 1), ]; let sample_median = (100.49999381186375, Some(100.49999461609349)); let sample_moment_stats = MomentStats { mean: NiceFloat(100.4998603968099), standard_deviation: NiceFloat(0.28878031747138194), skewness: NiceFloat(-0.00018856944159801264), excess_kurtosis: NiceFloat(-1.2006169795569301), }; random_primitive_float_range_helper::( 100.0, 101.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0e38, b = Infinity let values = &[ 1.3219190533477493e200, 3.652437632585123e180, 2.0420353527516904e248, 2.505458962964126e276, 2.659899792371364e116, 2.7125386559147274e90, 9.536479965391043e185, 9.567216720381635e239, 5.16993041287954e245, 4.939547529284952e179, 3.1175116898205872e224, 1.7555281884088452e42, 5.429209768108731e84, 1.0447670959436904e299, 1.9580250342195754e105, 8.848423533619703e204, 3.4434065546244285e79, 3.6093218170205304e216, 8.464035133686624e293, 1.22423660941592e120, ]; let common_values = &[ (2.141438721e116, 1), (8.7676954155e86, 1), (1.28439118539e55, 1), (1.79171075176e53, 1), (2.10333657725e74, 1), (2.3236426209e231, 1), (2.95823857742e58, 1), (3.1078914828e141, 1), (3.38975629714e61, 1), (4.28790184556e74, 1), ]; let sample_median = (1.2523958970084127e173, Some(1.2542732495420994e173)); let sample_moment_stats = MomentStats { mean: NiceFloat(2.939399538027295e305), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( 1.0e38, f64::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = f64::MIN_POSITIVE_SUBNORMAL let values = &[ -0.0, -5.0e-324, -0.0, 0.0, -0.0, -0.0, -5.0e-324, -0.0, -5.0e-324, 0.0, -0.0, -5.0e-324, -0.0, 0.0, 0.0, -5.0e-324, -0.0, -5.0e-324, 0.0, 0.0, ]; let common_values = &[(-0.0, 333784), (0.0, 333516), (-5.0e-324, 332700)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = f64::MIN_POSITIVE_SUBNORMAL let values = &[ 0.0, -0.0, -0.0, -0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, -0.0, 0.0, -0.0, ]; let common_values = &[(0.0, 500473), (-0.0, 499527)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 0.0, b = f64::MIN_POSITIVE_SUBNORMAL let values = &[0.0; 20]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( 0.0, f64::MIN_POSITIVE_SUBNORMAL, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = -0.0 let values = &[-5.0e-324; 20]; let common_values = &[(-5.0e-324, 1000000)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = 0.0 let values = &[ -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -0.0, -0.0, -5.0e-324, -0.0, -0.0, -0.0, -0.0, -5.0e-324, -0.0, -0.0, -0.0, -0.0, -5.0e-324, -0.0, -5.0e-324, ]; let common_values = &[(-0.0, 500473), (-5.0e-324, 499527)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -Infinity, b = Infinity let values = &[ 3.106206640558341e-146, 7.268713316268921e223, 1.1685126708702852e48, -1.0824685183946236e146, 3.114605160661583e-306, 2.2453015573637674e249, 1.2548860979388685e-35, -8.287939157477947e-27, 2.1255041535787165e-13, 4.815129234795048e-64, 1.3850402674408148e-17, -1.253571770758962e207, -1.4941028004491906e142, 4.366611961454907e-51, -7.063699168119985e17, -7.062565582436957e90, 1.1662950933663382e-221, 2.1976577668343592e-97, -2.8212944266870196e-137, 1.2250916338748408e-222, ]; let common_values = &[ (-9967188.16722, 1), (1808.830612999, 1), (32578528203.69, 1), (5643444.695113, 1), (812845035127.8, 1), (-13741970740.45, 1), (-1434325.082519, 1), (-33781527.93352, 1), (-374012916597.5, 1), (-46629353341.91, 1), ]; let sample_median = (2.772306592172272e-308, Some(2.7820731194979217e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581038e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = 0.0 let values = &[-0.0; 20]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_float_range_helper::( -0.0, 0.0, values, common_values, sample_median, sample_moment_stats, ); } fn random_primitive_float_range_fail_helper() { assert_panic!(random_primitive_float_range::( EXAMPLE_SEED, T::ZERO, T::ZERO )); assert_panic!(random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::ZERO )); assert_panic!(random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::NAN )); } #[test] fn random_primitive_float_range_fail() { apply_fn_to_primitive_floats!(random_primitive_float_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; fn random_primitive_floats_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { random_primitive_floats_helper_helper( random_primitive_floats::(EXAMPLE_SEED), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_random_primitive_floats() { // f32 let values = &[ -2.3484665e-27, 2.2879888e-18, -2.0729896e-12, 3.3600117e28, -9.0217234e-32, 3564911.0, -0.000013376945, -1.885545e18, 8.249455e-29, 2.2178013e-38, -6.306773e-34, 5.199601e31, 7.6132625e33, 0.00015323664, 9.4768183e36, -0.0005665587, 8.873326e-30, 0.09273134, -7.774831e33, 4.315623e-8, ]; let common_values = &[ (5.71262, 2), (780.036, 2), (224535.3, 2), (58.67172, 2), (73439.85, 2), (-58.01006, 2), (-66297.15, 2), (-66476.91, 2), (13200.071, 2), (3306.3635, 2), ]; let sample_median = (4.601794e-39, Some(4.606577e-39)); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.871815997376882e34), standard_deviation: NiceFloat(1.8597574260800838e37), skewness: NiceFloat(-0.04588420234596291), excess_kurtosis: NiceFloat(174.30920609573673), }; random_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); // f64 let values = &[ 3.106206640558341e-146, 7.268713316268921e223, 1.1685126708702852e48, -1.0824685183946236e146, 3.114605160661583e-306, 2.2453015573637674e249, 1.2548860979388685e-35, -8.287939157477947e-27, 2.1255041535787165e-13, 4.815129234795048e-64, 1.3850402674408148e-17, -1.253571770758962e207, -1.4941028004491906e142, 4.366611961454907e-51, -7.063699168119985e17, -7.062565582436957e90, 1.1662950933663382e-221, 2.1976577668343592e-97, -2.8212944266870196e-137, 1.2250916338748408e-222, ]; let common_values = &[ (-9967188.16722, 1), (1808.830612999, 1), (32578528203.69, 1), (5643444.695113, 1), (812845035127.8, 1), (-13741970740.45, 1), (-1434325.082519, 1), (-33781527.93352, 1), (-374012916597.5, 1), (-46629353341.91, 1), ]; let sample_median = (2.772306592172272e-308, Some(2.7820731194979217e-308)); let sample_moment_stats = MomentStats { mean: NiceFloat(7.922018643581038e303), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_primitive_floats_helper::( values, common_values, sample_median, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_primitive_ints.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; fn random_primitive_ints_helper( expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_primitive_ints(EXAMPLE_SEED), T::MIN, T::MAX, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_primitive_ints() { // u8 let values = &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ]; let common_values = &[ (214, 4097), (86, 4078), (166, 4049), (22, 4048), (126, 4047), (55, 4040), (93, 4037), (191, 4036), (36, 4035), (42, 4032), ]; let pop_median = (127, Some(128)); let sample_median = (127, None); let pop_moment_stats = MomentStats { mean: NiceFloat(127.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(127.4588370000015), standard_deviation: NiceFloat(73.908735397844), skewness: NiceFloat(0.0004407839380447086), excess_kurtosis: NiceFloat(-1.200418003526934), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16 let values = &[ 61297, 27717, 53988, 41384, 8279, 21358, 8892, 61017, 51293, 29589, 38333, 51673, 37493, 18463, 43415, 8622, 9735, 36945, 32584, 32881, ]; let common_values = &[ (27447, 34), (5606, 33), (5836, 33), (50513, 33), (64638, 33), (3582, 32), (19279, 32), (20588, 32), (27377, 32), (40163, 32), ]; let pop_median = (32767, Some(32768)); let sample_median = (32764, None); let pop_moment_stats = MomentStats { mean: NiceFloat(32767.5), standard_deviation: NiceFloat(18918.61361860324), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000005587934), }; let sample_moment_stats = MomentStats { mean: NiceFloat(32768.5946480003), standard_deviation: NiceFloat(18919.97151989925), skewness: NiceFloat(0.00005872108073206368), excess_kurtosis: NiceFloat(-1.200244178722062), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32 let values = &[ 1816522609, 2712195812, 1399726167, 3998819004, 1939195997, 3386480061, 1210028661, 565094807, 2421237255, 2154921800, 1999530985, 4087616012, 4147883634, 3097538087, 4234421608, 1164671716, 2394159346, 3174951407, 130045419, 2998491848, ]; let common_values = &[ (20095656, 2), (29107328, 2), (83328146, 2), (96543416, 2), (109257003, 2), (132308363, 2), (140940582, 2), (168698132, 2), (182460287, 2), (184573980, 2), ]; let pop_median = (2147483647, Some(2147483648)); let sample_median = (2150296456, Some(2150302375)); let pop_moment_stats = MomentStats { mean: NiceFloat(2147483647.5), standard_deviation: NiceFloat(1239850262.2531195), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(2148696150.6876254), standard_deviation: NiceFloat(1239453907.667566), skewness: NiceFloat(-0.0016842295222180032), excess_kurtosis: NiceFloat(-1.2007050556559806), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64 let values = &[ 11648792314704686961, 17174796846203019351, 14544821112490281053, 2427063716414460533, 9255318658858690055, 17556177092145474537, 13303824785927286386, 5002226935030621544, 13636312461848344818, 12878424424612648427, 13573831502926905428, 1513424385005459611, 2484972586252155822, 13072300245601619293, 4344958725064805398, 3252798961345668310, 10520651756201345771, 12379844438588545665, 6654913321726770291, 10505868200830584967, ]; let common_values = &[ (26914038281329, 1), (32553719576594, 1), (53892651831494, 1), (66354421349686, 1), (86226284907602, 1), (89837182726049, 1), (95691351770484, 1), (166741761063383, 1), (171574734234584, 1), (212518263578065, 1), ]; let pop_median = (9223372036854775807, Some(9223372036854775808)); let sample_median = (9228795451400314170, Some(9228799993322832549)); let pop_moment_stats = MomentStats { mean: NiceFloat(9.223372036854776e18), standard_deviation: NiceFloat(5.325116328314171e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(9.223151767642118e18), standard_deviation: NiceFloat(5.323459825978695e18), skewness: NiceFloat(-0.0007960342667556958), excess_kurtosis: NiceFloat(-1.2005689675667335), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u128 let values = &[ 316819081939861044636107404782286008177, 44771423227283929645271838218448652381, 323854305731529921104946490224673891847, 92274800069126412258941638023956901490, 237564999433439714567249110498266052850, 27917752305106984883503397141734686804, 241141377085303586778938998836817083310, 60003549963171791765607325839025294358, 228367822030979405869278360636891890411, 193799061972845222683167418018286926963, 186696208941218647968078823625188059421, 33018320828004690757952445968579104952, 24887066387352849554815992782110776358, 79085537771456044427857440036467563654, 19637669411666889498466854442215856999, 237587532320755783035907621678835821469, 254983837845695498020527357238650572551, 272337383097469374367899988789175779695, 105189689748742230503365861545668092951, 258427395460299182237257690021561141080, ]; let common_values = &[ (68570815139656170990830410045915, 1), (381682482227926990846204728028719, 1), (565207126752383841908924745713103, 1), (717866653939818807939025508430762, 1), (775173738585689418081884794376186, 1), (818497230601034032775791540657915, 1), (1224023028796761386468452212527255, 1), (1379103576141836593923341631562888, 1), (1765193876177447622538546939111747, 1), (2049979073093489039458791025727172, 1), ]; let pop_median = ( 170141183460469231731687303715884105727, Some(170141183460469231731687303715884105728), ); let sample_median = ( 170151864710150847082485192587168481404, Some(170151925651660504506169909296979843840), ); let pop_moment_stats = MomentStats { mean: NiceFloat(1.7014118346046923e38), standard_deviation: NiceFloat(9.82310580711434e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.702375633317502e38), standard_deviation: NiceFloat(9.815169783582294e37), skewness: NiceFloat(-0.0005571163134867303), excess_kurtosis: NiceFloat(-1.1992896928276262), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8 let values = &[ 113, -17, 69, 108, -28, -46, -88, -95, 87, 32, 110, 83, -68, 34, 89, -18, 93, -56, -107, 115, ]; let common_values = &[ (-42, 4097), (86, 4078), (-90, 4049), (22, 4048), (126, 4047), (55, 4040), (93, 4037), (-65, 4036), (36, 4035), (42, 4032), ]; let pop_median = (-1, Some(0)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5135149999999996), standard_deviation: NiceFloat(73.89764871907164), skewness: NiceFloat(-0.00024093275514460485), excess_kurtosis: NiceFloat(-1.199484141789355), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16 let values = &[ -4239, 27717, -11548, -24152, 8279, 21358, 8892, -4519, -14243, 29589, -27203, -13863, -28043, 18463, -22121, 8622, 9735, -28591, 32584, -32655, ]; let common_values = &[ (27447, 34), (-898, 33), (5606, 33), (5836, 33), (-15023, 33), (-197, 32), (3582, 32), (-7314, 32), (19279, 32), (20588, 32), ]; let pop_median = (-1, Some(0)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(18918.61361860324), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000000005587934), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.11663199999982), standard_deviation: NiceFloat(18918.420140333936), skewness: NiceFloat(-0.00020582179614538415), excess_kurtosis: NiceFloat(-1.19980156293678), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32 let values = &[ 1816522609, -1582771484, 1399726167, -296148292, 1939195997, -908487235, 1210028661, 565094807, -1873730041, -2140045496, 1999530985, -207351284, -147083662, -1197429209, -60545688, 1164671716, -1900807950, -1120015889, 130045419, -1296475448, ]; let common_values = &[ (20095656, 2), (29107328, 2), (83328146, 2), (96543416, 2), (-59532811, 2), (-72250103, 2), (-88423413, 2), (109257003, 2), (132308363, 2), (140940582, 2), ]; let pop_median = (-1, Some(0)); let sample_median = (-3037682, Some(-3035621)); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(1239850262.2531195), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1708075.0735549931), standard_deviation: NiceFloat(1239705769.0057693), skewness: NiceFloat(0.0016706713036923025), excess_kurtosis: NiceFloat(-1.2008047456655335), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64 let values = &[ -6797951759004864655, -1271947227506532265, -3901922961219270563, 2427063716414460533, -9191425414850861561, -890566981564077079, -5142919287782265230, 5002226935030621544, -4810431611861206798, -5568319649096903189, -4872912570782646188, 1513424385005459611, 2484972586252155822, -5374443828107932323, 4344958725064805398, 3252798961345668310, -7926092317508205845, -6066899635121005951, 6654913321726770291, -7940875872878966649, ]; let common_values = &[ (26914038281329, 1), (32553719576594, 1), (53892651831494, 1), (66354421349686, 1), (86226284907602, 1), (89837182726049, 1), (95691351770484, 1), (-45554336062456, 1), (-45700426911569, 1), (-50232881235535, 1), ]; let pop_median = (-1, Some(0)); let sample_median = (-5305218289400184, Some(-5271053954352614)); let pop_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(5.325116328314171e18), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-5606718482239710.0), standard_deviation: NiceFloat(5.325063903618647e18), skewness: NiceFloat(0.0011248693866288532), excess_kurtosis: NiceFloat(-1.200551786344892), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128 let values = &[ -23463284981077418827267202649482203279, 44771423227283929645271838218448652381, -16428061189408542358428117207094319609, 92274800069126412258941638023956901490, -102717367487498748896125496933502158606, 27917752305106984883503397141734686804, -99140989835634876684435608594951128146, 60003549963171791765607325839025294358, -111914544889959057594096246794876321045, -146483304948093240780207189413481284493, -153586157979719815495295783806580152035, 33018320828004690757952445968579104952, 24887066387352849554815992782110776358, 79085537771456044427857440036467563654, 19637669411666889498466854442215856999, -102694834600182680427466985752932389987, -85298529075242965442847250193117638905, -67944983823469089095474618642592431761, 105189689748742230503365861545668092951, -81854971460639281226116917410207070376, ]; let common_values = &[ (68570815139656170990830410045915, 1), (381682482227926990846204728028719, 1), (565207126752383841908924745713103, 1), (717866653939818807939025508430762, 1), (775173738585689418081884794376186, 1), (818497230601034032775791540657915, 1), (-307666299724089175945459600408325, 1), (-413570452196184856884474016102340, 1), (-789195894019805665974324122519229, 1), (-843024079296967638987633859098218, 1), ]; let pop_median = (-1, Some(0)); let sample_median = ( -10072503186589325235371920356302834, Some(-9899574809150113239535729822182407), ); let pop_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(9.82310580711434e37), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2), }; let sample_moment_stats = MomentStats { mean: NiceFloat(8.651168263124604e34), standard_deviation: NiceFloat(9.82707680675722e37), skewness: NiceFloat(0.00010083962773749455), excess_kurtosis: NiceFloat(-1.2019920806441844), }; random_primitive_ints_helper::( values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } ================================================ FILE: malachite-base/tests/num/random/random_signed_bit_chunks.rs ================================================ // Copyright © 2026 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, assert_equal, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_signed_bit_chunks; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_signed_bit_chunks_helper( chunk_size: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let (min, max) = if chunk_size < T::WIDTH { (T::ZERO, T::low_mask(chunk_size)) } else { (T::MIN, T::MAX) }; let xs = random_signed_bit_chunks(EXAMPLE_SEED, chunk_size); uniform_primitive_int_assertions( xs.clone(), min, max, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); if chunk_size != 0 { assert_equal( random_bools(EXAMPLE_SEED) .chunks(usize::exact_from(chunk_size)) .into_iter() .take(1000000) .map(|bs| { T::from_bits_asc( bs.chain(repeat_n(false, usize::exact_from(T::WIDTH - chunk_size))), ) }), xs.take(1000000), ); } } #[test] fn test_random_signed_bit_chunks() { // i16, chunk_size = 1 let values = &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0]; let common_values = &[(1, 500473), (0, 499527)]; let pop_median = (0, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.5), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.9999999999999998), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.5004730000000077), standard_deviation: NiceFloat(0.5000000262710417), skewness: NiceFloat(-0.0018920008465908307), excess_kurtosis: NiceFloat(-1.999996420332894), }; random_signed_bit_chunks_helper::( 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32, chunk_size = 2 let values = &[1, 0, 3, 1, 3, 3, 2, 3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 2, 3]; let common_values = &[(1, 250314), (3, 250015), (2, 249955), (0, 249716)]; let pop_median = (1, Some(2)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.5), standard_deviation: NiceFloat(1.118033988749895), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.3599999999999999), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.5002690000000294), standard_deviation: NiceFloat(1.117793888470597), skewness: NiceFloat(-0.00003155128630032229), excess_kurtosis: NiceFloat(-1.3594490446207492), }; random_signed_bit_chunks_helper::( 2, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, chunk_size = 3 let values = &[1, 6, 5, 7, 6, 3, 1, 2, 4, 5, 1, 2, 6, 5, 4, 6, 0, 5, 6, 0]; let common_values = &[ (3, 125437), (6, 125372), (7, 125322), (4, 125116), (0, 125049), (5, 124759), (2, 124542), (1, 124403), ]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(2.29128784747792), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.238095238095238), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.503543000000029), standard_deviation: NiceFloat(2.291658067611209), skewness: NiceFloat(-0.002350008016990765), excess_kurtosis: NiceFloat(-1.2376569368178467), }; random_signed_bit_chunks_helper::( 3, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i128, chunk_size = 7 let values = &[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, 1, 113, 54, 10, 47, 17, 89, 92, 119, 66]; let common_values = &[ (2, 8077), (121, 8039), (48, 8015), (113, 7966), (8, 7937), (77, 7933), (50, 7928), (91, 7927), (82, 7925), (102, 7924), ]; let pop_median = (63, Some(64)); let sample_median = (63, None); let pop_moment_stats = MomentStats { mean: NiceFloat(63.5), standard_deviation: NiceFloat(36.94928957368463), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001464933162425), }; let sample_moment_stats = MomentStats { mean: NiceFloat(63.478088999999315), standard_deviation: NiceFloat(36.96113842989552), skewness: NiceFloat(-0.000454036075457304), excess_kurtosis: NiceFloat(-1.1998683031732713), }; random_signed_bit_chunks_helper::( 7, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, chunk_size = 8 let values = &[ 113, -17, 69, 108, -28, -46, -88, -95, 87, 32, 110, 83, -68, 34, 89, -18, 93, -56, -107, 115, ]; let common_values = &[ (-42, 4097), (86, 4078), (-90, 4049), (22, 4048), (126, 4047), (55, 4040), (93, 4037), (-65, 4036), (36, 4035), (42, 4032), ]; let pop_median = (-1, Some(0)); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5135149999999996), standard_deviation: NiceFloat(73.89764871907164), skewness: NiceFloat(-0.00024093275514460485), excess_kurtosis: NiceFloat(-1.199484141789355), }; random_signed_bit_chunks_helper::( 8, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_signed_bit_chunks_fail_helper() { assert_panic!(random_signed_bit_chunks::(EXAMPLE_SEED, 0)); assert_panic!(random_signed_bit_chunks::(EXAMPLE_SEED, T::WIDTH + 1)); } #[test] fn random_signed_bit_chunks_fail() { apply_fn_to_signeds!(random_signed_bit_chunks_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_signed_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_signed_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_signed_inclusive_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_signed_inclusive_range::(EXAMPLE_SEED, a, b), a, b, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_signed_inclusive_range() { // i8, 5, 5 let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_signed_inclusive_range_helper::( 5, 5, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16, 1, 6 let values = &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1]; let common_values = &[(4, 167408), (1, 167104), (5, 166935), (6, 166549), (3, 166068), (2, 165936)]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(1.707825127659933), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2685714285714285), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.5007809999998676), standard_deviation: NiceFloat(1.7081165966354217), skewness: NiceFloat(-0.0024015945144963404), excess_kurtosis: NiceFloat(-1.2685533575767198), }; random_signed_inclusive_range_helper::( 1, 6, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32, 10, 19 let values = &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15]; let common_values = &[ (15, 100442), (12, 100144), (16, 100118), (18, 100047), (11, 100023), (14, 100011), (10, 99996), (19, 99936), (17, 99715), (13, 99568), ]; let pop_median = (14, Some(15)); let sample_median = (15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.49978199999957), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_signed_inclusive_range_helper::( 10, 19, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, -20, -11 let values = &[ -19, -13, -15, -16, -14, -16, -18, -12, -19, -13, -15, -20, -18, -14, -17, -15, -18, -18, -11, -15, ]; let common_values = &[ (-15, 100442), (-18, 100144), (-14, 100118), (-12, 100047), (-19, 100023), (-16, 100011), (-20, 99996), (-11, 99936), (-13, 99715), (-17, 99568), ]; let pop_median = (-16, Some(-15)); let sample_median = (-15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-15.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-15.50021800000043), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_signed_inclusive_range_helper::( -20, -11, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, -100, 99 let values = &[13, -31, 8, 68, 61, -13, -68, 10, -17, 88, -66, -11, -7, 49, 15, 89, 49, 17, 46, -69]; let common_values = &[ (-33, 5190), (66, 5182), (87, 5176), (-73, 5172), (-7, 5169), (91, 5167), (-84, 5136), (26, 5132), (-12, 5125), (-14, 5125), ]; let pop_median = (-1, Some(0)); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(57.73430522661548), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000600015000376), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5228260000000045), standard_deviation: NiceFloat(57.74415076317745), skewness: NiceFloat(0.00018970091170297907), excess_kurtosis: NiceFloat(-1.2011004127418898), }; random_signed_inclusive_range_helper::( -100, 99, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, i8::MIN, i8::MAX let values = &[ -15, 111, -59, -20, 100, 82, 40, 33, -41, -96, -18, -45, 60, -94, -39, 110, -35, 72, 21, -13, ]; let common_values = &[ (86, 4097), (-42, 4078), (38, 4049), (-106, 4048), (-2, 4047), (-73, 4040), (-35, 4037), (63, 4036), (-92, 4035), (-86, 4032), ]; let pop_median = (-1, Some(0)); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5411629999999936), standard_deviation: NiceFloat(73.90873539784404), skewness: NiceFloat(0.00044078393804460487), excess_kurtosis: NiceFloat(-1.200418003526936), }; random_signed_inclusive_range_helper::( i8::MIN, i8::MAX, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_signed_inclusive_range_fail_helper() { assert_panic!(random_signed_inclusive_range::( EXAMPLE_SEED, T::TWO, T::ONE )); } #[test] fn random_signed_inclusive_range_fail() { apply_fn_to_signeds!(random_signed_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_signed_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_signed_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_signed_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_signed_range::(EXAMPLE_SEED, a, b), a, b - T::ONE, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_signed_range() { // i8, 5, 6 let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_signed_range_helper::( 5, 6, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i16, 1, 7 let values = &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1]; let common_values = &[(4, 167408), (1, 167104), (5, 166935), (6, 166549), (3, 166068), (2, 165936)]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(1.707825127659933), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2685714285714285), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.5007809999998676), standard_deviation: NiceFloat(1.7081165966354217), skewness: NiceFloat(-0.0024015945144963404), excess_kurtosis: NiceFloat(-1.2685533575767198), }; random_signed_range_helper::( 1, 7, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i32, 10, 20 let values = &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15]; let common_values = &[ (15, 100442), (12, 100144), (16, 100118), (18, 100047), (11, 100023), (14, 100011), (10, 99996), (19, 99936), (17, 99715), (13, 99568), ]; let pop_median = (14, Some(15)); let sample_median = (15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.49978199999957), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_signed_range_helper::( 10, 20, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i64, -20, -10 let values = &[ -19, -13, -15, -16, -14, -16, -18, -12, -19, -13, -15, -20, -18, -14, -17, -15, -18, -18, -11, -15, ]; let common_values = &[ (-15, 100442), (-18, 100144), (-14, 100118), (-12, 100047), (-19, 100023), (-16, 100011), (-20, 99996), (-11, 99936), (-13, 99715), (-17, 99568), ]; let pop_median = (-16, Some(-15)); let sample_median = (-15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-15.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-15.50021800000043), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_signed_range_helper::( -20, -10, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, -100, 100 let values = &[13, -31, 8, 68, 61, -13, -68, 10, -17, 88, -66, -11, -7, 49, 15, 89, 49, 17, 46, -69]; let common_values = &[ (-33, 5190), (66, 5182), (87, 5176), (-73, 5172), (-7, 5169), (91, 5167), (-84, 5136), (26, 5132), (-12, 5125), (-14, 5125), ]; let pop_median = (-1, Some(0)); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-0.5), standard_deviation: NiceFloat(57.73430522661548), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000600015000376), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5228260000000045), standard_deviation: NiceFloat(57.74415076317745), skewness: NiceFloat(0.00018970091170297907), excess_kurtosis: NiceFloat(-1.2011004127418898), }; random_signed_range_helper::( -100, 100, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // i8, i8::MIN, i8::MAX let values = &[ -15, 111, -59, -20, 100, 82, 40, 33, -41, -96, -18, -45, 60, -94, -39, 110, -35, 72, 21, -13, ]; let common_values = &[ (86, 4112), (-42, 4092), (38, 4063), (-2, 4061), (-106, 4061), (-35, 4054), (-73, 4054), (63, 4052), (-92, 4049), (-86, 4047), ]; let pop_median = (-1, None); let sample_median = (-1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(-1.0), standard_deviation: NiceFloat(73.6115932898254), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000369094488188), }; let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0481689999999793), standard_deviation: NiceFloat(73.61930013623301), skewness: NiceFloat(0.0005380412105164722), excess_kurtosis: NiceFloat(-1.2003531635142872), }; random_signed_range_helper::( i8::MIN, i8::MAX, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_signed_range_fail_helper() { assert_panic!(random_signed_range::(EXAMPLE_SEED, T::TWO, T::TWO)); } #[test] fn random_signed_range_fail() { apply_fn_to_signeds!(random_signed_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_unsigned_bit_chunks.rs ================================================ // Copyright © 2026 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, assert_equal}; use malachite_base::bools::random::random_bools; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_unsigned_bit_chunks; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_unsigned_bit_chunks_helper( chunk_size: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { let xs = random_unsigned_bit_chunks(EXAMPLE_SEED, chunk_size); uniform_primitive_int_assertions( xs.clone(), T::ZERO, T::low_mask(chunk_size), expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); if chunk_size != 0 { assert_equal( random_bools(EXAMPLE_SEED) .chunks(usize::exact_from(chunk_size)) .into_iter() .take(1000000) .map(T::from_bits_asc), xs.take(1000000), ); } } #[test] fn test_random_unsigned_bit_chunks() { // u16, chunk_size = 1 let values = &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0]; let common_values = &[(1, 500473), (0, 499527)]; let pop_median = (0, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.5), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.9999999999999998), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.5004730000000077), standard_deviation: NiceFloat(0.5000000262710417), skewness: NiceFloat(-0.0018920008465908307), excess_kurtosis: NiceFloat(-1.999996420332894), }; random_unsigned_bit_chunks_helper::( 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, chunk_size = 2 let values = &[1, 0, 3, 1, 3, 3, 2, 3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 2, 3]; let common_values = &[(1, 250314), (3, 250015), (2, 249955), (0, 249716)]; let pop_median = (1, Some(2)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.5), standard_deviation: NiceFloat(1.118033988749895), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.3599999999999999), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.5002690000000294), standard_deviation: NiceFloat(1.117793888470597), skewness: NiceFloat(-0.00003155128630032229), excess_kurtosis: NiceFloat(-1.3594490446207492), }; random_unsigned_bit_chunks_helper::( 2, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, chunk_size = 3 let values = &[1, 6, 5, 7, 6, 3, 1, 2, 4, 5, 1, 2, 6, 5, 4, 6, 0, 5, 6, 0]; let common_values = &[ (3, 125437), (6, 125372), (7, 125322), (4, 125116), (0, 125049), (5, 124759), (2, 124542), (1, 124403), ]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(2.29128784747792), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.238095238095238), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.503543000000029), standard_deviation: NiceFloat(2.291658067611209), skewness: NiceFloat(-0.002350008016990765), excess_kurtosis: NiceFloat(-1.2376569368178467), }; random_unsigned_bit_chunks_helper::( 3, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u128, chunk_size = 7 let values = &[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, 1, 113, 54, 10, 47, 17, 89, 92, 119, 66]; let common_values = &[ (2, 8077), (121, 8039), (48, 8015), (113, 7966), (8, 7937), (77, 7933), (50, 7928), (91, 7927), (82, 7925), (102, 7924), ]; let pop_median = (63, Some(64)); let sample_median = (63, None); let pop_moment_stats = MomentStats { mean: NiceFloat(63.5), standard_deviation: NiceFloat(36.94928957368463), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2001464933162425), }; let sample_moment_stats = MomentStats { mean: NiceFloat(63.478088999999315), standard_deviation: NiceFloat(36.96113842989552), skewness: NiceFloat(-0.000454036075457304), excess_kurtosis: NiceFloat(-1.1998683031732713), }; random_unsigned_bit_chunks_helper::( 7, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, chunk_size = 8 let values = &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ]; let common_values = &[ (214, 4097), (86, 4078), (166, 4049), (22, 4048), (126, 4047), (55, 4040), (93, 4037), (191, 4036), (36, 4035), (42, 4032), ]; let pop_median = (127, Some(128)); let sample_median = (127, None); let pop_moment_stats = MomentStats { mean: NiceFloat(127.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(127.4588370000015), standard_deviation: NiceFloat(73.908735397844), skewness: NiceFloat(0.0004407839380447086), excess_kurtosis: NiceFloat(-1.200418003526934), }; random_unsigned_bit_chunks_helper::( 8, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_unsigned_bit_chunks_fail_helper() { assert_panic!(random_unsigned_bit_chunks::(EXAMPLE_SEED, 0)); assert_panic!(random_unsigned_bit_chunks::(EXAMPLE_SEED, T::WIDTH + 1)); } #[test] fn random_unsigned_bit_chunks_fail() { apply_fn_to_unsigneds!(random_unsigned_bit_chunks_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_unsigned_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_unsigned_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_unsigned_inclusive_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_unsigned_inclusive_range::(EXAMPLE_SEED, a, b), a, b, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_unsigned_inclusive_range() { // u8, 5, 5 let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_unsigned_inclusive_range_helper::( 5, 5, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16, 1, 6 let values = &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1]; let common_values = &[(4, 167408), (1, 167104), (5, 166935), (6, 166549), (3, 166068), (2, 165936)]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(1.707825127659933), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2685714285714285), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.5007809999998676), standard_deviation: NiceFloat(1.7081165966354217), skewness: NiceFloat(-0.0024015945144963404), excess_kurtosis: NiceFloat(-1.2685533575767198), }; random_unsigned_inclusive_range_helper::( 1, 6, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, 10, 19 let values = &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15]; let common_values = &[ (15, 100442), (12, 100144), (16, 100118), (18, 100047), (11, 100023), (14, 100011), (10, 99996), (19, 99936), (17, 99715), (13, 99568), ]; let pop_median = (14, Some(15)); let sample_median = (15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.49978199999957), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_unsigned_inclusive_range_helper::( 10, 19, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, 0, u8::MAX let values = &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ]; let common_values = &[ (214, 4097), (86, 4078), (166, 4049), (22, 4048), (126, 4047), (55, 4040), (93, 4037), (191, 4036), (36, 4035), (42, 4032), ]; let pop_median = (127, Some(128)); let sample_median = (127, None); let pop_moment_stats = MomentStats { mean: NiceFloat(127.5), standard_deviation: NiceFloat(73.90027063549903), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.200036621652552), }; let sample_moment_stats = MomentStats { mean: NiceFloat(127.4588370000015), standard_deviation: NiceFloat(73.908735397844), skewness: NiceFloat(0.0004407839380447086), excess_kurtosis: NiceFloat(-1.200418003526934), }; random_unsigned_inclusive_range_helper::( 0, u8::MAX, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_unsigned_inclusive_range_fail_helper() { assert_panic!(random_unsigned_inclusive_range::( EXAMPLE_SEED, T::TWO, T::ONE )); } #[test] fn random_unsigned_inclusive_range_fail() { apply_fn_to_unsigneds!(random_unsigned_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_unsigned_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_unsigned_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_unsigned_range_helper( a: T, b: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_unsigned_range::(EXAMPLE_SEED, a, b), a, b - T::ONE, expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_unsigned_range() { // u8, 5, 6 let values = &[5; 20]; let common_values = &[(5, 1000000)]; let pop_median = (5, None); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_unsigned_range_helper::( 5, 6, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16, 1, 7 let values = &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1]; let common_values = &[(4, 167408), (1, 167104), (5, 166935), (6, 166549), (3, 166068), (2, 165936)]; let pop_median = (3, Some(4)); let sample_median = (4, None); let pop_moment_stats = MomentStats { mean: NiceFloat(3.5), standard_deviation: NiceFloat(1.707825127659933), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2685714285714285), }; let sample_moment_stats = MomentStats { mean: NiceFloat(3.5007809999998676), standard_deviation: NiceFloat(1.7081165966354217), skewness: NiceFloat(-0.0024015945144963404), excess_kurtosis: NiceFloat(-1.2685533575767198), }; random_unsigned_range_helper::( 1, 7, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, 10, 20 let values = &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15]; let common_values = &[ (15, 100442), (12, 100144), (16, 100118), (18, 100047), (11, 100023), (14, 100011), (10, 99996), (19, 99936), (17, 99715), (13, 99568), ]; let pop_median = (14, Some(15)); let sample_median = (15, None); let pop_moment_stats = MomentStats { mean: NiceFloat(14.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(14.49978199999957), standard_deviation: NiceFloat(2.8719356191409076), skewness: NiceFloat(-0.00016199543215732692), excess_kurtosis: NiceFloat(-1.2237431734377722), }; random_unsigned_range_helper::( 10, 20, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u8, 0, u8::MAX let values = &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ]; let common_values = &[ (214, 4112), (86, 4092), (166, 4063), (22, 4061), (126, 4061), (55, 4054), (93, 4054), (191, 4052), (36, 4049), (42, 4047), ]; let pop_median = (127, None); let sample_median = (127, None); let pop_moment_stats = MomentStats { mean: NiceFloat(127.0), standard_deviation: NiceFloat(73.6115932898254), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2000369094488188), }; let sample_moment_stats = MomentStats { mean: NiceFloat(126.95183099999818), standard_deviation: NiceFloat(73.61930013623306), skewness: NiceFloat(0.0005380412105163868), excess_kurtosis: NiceFloat(-1.200353163514298), }; random_unsigned_range_helper::( 0, u8::MAX, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_unsigned_range_fail_helper() { assert_panic!(random_unsigned_range::(EXAMPLE_SEED, T::TWO, T::TWO)); } #[test] fn random_unsigned_range_fail() { apply_fn_to_unsigneds!(random_unsigned_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/random_unsigneds_less_than.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::random_unsigneds_less_than; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::{ CheckedToF64, MomentStats, uniform_primitive_int_assertions, }; use std::panic::catch_unwind; fn random_unsigneds_less_than_helper( limit: T, expected_values: &[T], expected_common_values: &[(T, usize)], expected_pop_median: (T, Option), expected_sample_median: (T, Option), expected_pop_moment_stats: MomentStats, expected_sample_moment_stats: MomentStats, ) { uniform_primitive_int_assertions( random_unsigneds_less_than(EXAMPLE_SEED, limit), T::ZERO, limit.wrapping_sub(T::ONE), expected_values, expected_common_values, expected_pop_median, expected_sample_median, expected_pop_moment_stats, expected_sample_moment_stats, ); } #[test] fn test_random_unsigneds_less_than() { // u8, limit = 1 let values = &[0; 20]; let common_values = &[(0, 1000000)]; let pop_median = (0, None); let sample_median = (0, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_unsigneds_less_than_helper::( 1, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u16, limit = 2 let values = &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0]; let common_values = &[(1, 500473), (0, 499527)]; let pop_median = (0, Some(1)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.5), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.9999999999999998), }; let sample_moment_stats = MomentStats { mean: NiceFloat(0.5004730000000077), standard_deviation: NiceFloat(0.5000000262710417), skewness: NiceFloat(-0.0018920008465908307), excess_kurtosis: NiceFloat(-1.999996420332894), }; random_unsigneds_less_than_helper::( 2, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u32, limit = 3 let values = &[1, 0, 1, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 2, 2, 0, 1, 0, 2, 2]; let common_values = &[(1, 333784), (2, 333516), (0, 332700)]; let pop_median = (1, None); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(0.816496580927726), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.5), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.0008159999999369), standard_deviation: NiceFloat(0.8162205586482172), skewness: NiceFloat(-0.0014985805078073927), excess_kurtosis: NiceFloat(-1.498982317720307), }; random_unsigneds_less_than_helper::( 3, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u64, limit = 4 let values = &[1, 0, 3, 1, 3, 3, 2, 3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 2, 3]; let common_values = &[(1, 250314), (3, 250015), (2, 249955), (0, 249716)]; let pop_median = (1, Some(2)); let sample_median = (1, None); let pop_moment_stats = MomentStats { mean: NiceFloat(1.5), standard_deviation: NiceFloat(1.118033988749895), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.3599999999999999), }; let sample_moment_stats = MomentStats { mean: NiceFloat(1.5002690000000294), standard_deviation: NiceFloat(1.117793888470597), skewness: NiceFloat(-0.00003155128630032229), excess_kurtosis: NiceFloat(-1.3594490446207492), }; random_unsigneds_less_than_helper::( 4, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); // u128, limit = 10 let values = &[1, 7, 5, 4, 6, 4, 2, 8, 1, 7, 5, 0, 2, 6, 3, 5, 2, 2, 9, 5]; let common_values = &[ (5, 100442), (2, 100144), (6, 100118), (8, 100047), (1, 100023), (4, 100011), (0, 99996), (9, 99936), (7, 99715), (3, 99568), ]; let pop_median = (4, Some(5)); let sample_median = (5, None); let pop_moment_stats = MomentStats { mean: NiceFloat(4.5), standard_deviation: NiceFloat(2.8722813232690143), skewness: NiceFloat(0.0), excess_kurtosis: NiceFloat(-1.2242424242424241), }; let sample_moment_stats = MomentStats { mean: NiceFloat(4.499781999999947), standard_deviation: NiceFloat(2.8719356191409156), skewness: NiceFloat(-0.00016199543215745585), excess_kurtosis: NiceFloat(-1.2237431734377897), }; random_unsigneds_less_than_helper::( 10, values, common_values, pop_median, sample_median, pop_moment_stats, sample_moment_stats, ); } fn random_unsigneds_less_than_fail_helper() { assert_panic!(random_unsigneds_less_than::(EXAMPLE_SEED, T::ZERO)); } #[test] fn random_unsigneds_less_than_fail() { apply_fn_to_unsigneds!(random_unsigneds_less_than_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_finite_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_finite_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_finite_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64, mean zero P = 1/4 let values = &[ 0.0, 1.0, 1.0, -0.0, 1.0, -1.0, 0.0, -1.0, 0.0, -0.0, -1.0, -0.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.5, -0.0, 0.0, -1.0, 1.0, -1.0, -1.0, -1.0, 0.0, 1.0, -1.0, -0.5, -1.0, -0.0, 0.0, 0.0, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (0.0, 125637), (-0.0, 124572), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), (4.0, 75), (-1.25, 48), (1.75, 44), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0007401249999999665), standard_deviation: NiceFloat(0.8901654924701277), skewness: NiceFloat(-0.00169030138949471), excess_kurtosis: NiceFloat(-1.371049776159086), }; special_random_finite_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 1.0, 1.25, 3.0, 0.0, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, -0.0, -6.5, -1.0, -1.0, 0.0, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, 0.0, -0.1875, -7.5, -0.0, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, -0.0, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (0.0, 50351), (-0.0, 49873), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), (-0.25, 18537), (0.125, 9445), (-0.375, 9395), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.8271329178933905), standard_deviation: NiceFloat(427.372166726293), skewness: NiceFloat(-141.119016305626), excess_kurtosis: NiceFloat(144205.19930780405), }; special_random_finite_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.65625, 0.0000014255784, 0.013183594, -0.8125, -74240.0, -0.0078125, -0.03060913, 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, -59392.0, -1.75, -41.1875, 0.30940247, -0.0009765625, -1536.0, 0.2109375, 0.0014648438, 2.1129381e-8, -0.037109375, 5242880.0, -0.21386719, 134.21094, 4.184082, -1561370.0, -2.1420419e-7, 0.38085938, -0.007003784, -37748736.0, -6448.0, 28.25, -6.703125, -4.483364, -3.1757812, 0.000003915804, -0.020751953, 0.00011110306, -0.000053405256, 0.00019985437, -35.40625, 0.005859375, 0.0078125, 28.25, 30.0, -0.20776367, -144.0, -0.109375, -6144.0, ]; let common_values = &[ (0.0, 5098), (-0.0, 4891), (1.0, 2559), (-1.0, 2528), (0.5, 2362), (-2.0, 2312), (-1.5, 2306), (2.0, 2304), (1.5, 2275), (-0.5, 2243), (-3.0, 2204), (-4.0, 2163), (-0.25, 2129), (0.75, 2103), (3.0, 2081), (0.25, 2070), (-0.75, 2047), (4.0, 2038), (-6.0, 1943), (-8.0, 1918), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.736310580536276e31), standard_deviation: NiceFloat(6.494074857946111e34), skewness: NiceFloat(-779.0012319222365), excess_kurtosis: NiceFloat(633402.0042901832), }; special_random_finite_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64, mean zero P = 1/4 let values = &[ 0.0, 1.0, 1.0, -0.0, 1.0, -1.0, 0.0, -1.0, 0.0, -0.0, -1.0, -0.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.5, -0.0, 0.0, -1.0, 1.0, -1.0, -1.0, -1.0, 0.0, 1.0, -1.0, -0.5, -1.0, -0.0, 0.0, 0.0, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (0.0, 125637), (-0.0, 124572), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), (4.0, 75), (-1.25, 48), (1.75, 44), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0007401249999999665), standard_deviation: NiceFloat(0.8901654924701277), skewness: NiceFloat(-0.00169030138949471), excess_kurtosis: NiceFloat(-1.371049776159086), }; special_random_finite_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 1.0, 1.25, 3.0, 0.0, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, -0.0, -6.5, -1.0, -1.0, 0.0, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, 0.0, -0.1875, -7.5, -0.0, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, -0.0, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (0.0, 50351), (-0.0, 49873), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), (-0.25, 18537), (0.125, 9445), (-0.375, 9395), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.8271329178933905), standard_deviation: NiceFloat(427.372166726293), skewness: NiceFloat(-141.119016305626), excess_kurtosis: NiceFloat(144205.19930780405), }; special_random_finite_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.7709910366684198, 1.2504315236583352e-6, 0.00830078125, -0.8125, -85504.0, -0.0078125, -0.018890380859375, 2.5721821784973145, 5.75, -0.00003814697265625, -0.4375, -24064.0, -43008.0, -1.75, -54.6875, 0.4641265869140625, -0.0014760522753931582, -1536.0, 0.1484375, 0.00146484375, 1.9383151084184647e-8, -0.060546875, 7340032.0, -0.1982421875, 203.0546875, 4.57177734375, -1555162.0, -2.0675361156463623e-7, 0.279296875, -0.0045928955078125, -46137344.0, -5712.0, 17.75, -5.265625, -7.966220855712891, -2.99609375, 5.397188942879438e-6, -0.017333984375, 0.00011491775512695312, -0.00005845972555107437, 0.00020831823348999023, -46.78125, 0.005859375, 0.0078125, 27.25, 30.0, -0.175537109375, -208.0, -0.109375, -6144.0, ]; let common_values = &[ (0.0, 5098), (-0.0, 4891), (1.0, 2396), (-1.0, 2336), (-2.0, 2200), (-1.5, 2169), (0.5, 2116), (2.0, 2108), (-0.5, 2101), (1.5, 2085), (-3.0, 2000), (4.0, 1993), (3.0, 1969), (-0.25, 1955), (0.75, 1946), (0.25, 1917), (-4.0, 1882), (-0.75, 1863), (8.0, 1826), (-6.0, 1782), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.053229374417263e38), standard_deviation: NiceFloat(7.053232003373143e41), skewness: NiceFloat(-999.9984999989927), excess_kurtosis: NiceFloat(999995.0000005187), }; special_random_finite_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_finite_primitive_floats_fail_helper() { assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1, 1, 10 )); assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1, 1, 10 )); assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1, 1, 10 )); assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0, 1, 10 )); assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 1, 0 )); assert_panic!(special_random_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 2, 1 )); } #[test] fn special_random_finite_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_finite_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_negative_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_negative_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_negative_finite_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_negative_finite_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_negative_finite_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, ]; let common_values = &[ (-1.0, 954991), (-1.5, 14672), (-2.0, 14586), (-0.5, 14578), (-3.0, 243), (-0.25, 228), (-4.0, 226), (-0.75, 207), (-1.25, 127), (-1.75, 118), (-6.0, 6), (-0.125, 4), (-2.5, 3), (-8.0, 3), (-0.625, 3), (-0.375, 2), (-0.875, 2), (-3.5, 1), ]; let sample_median = (-1.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0157463749999305), standard_deviation: NiceFloat(0.15870215416222863), skewness: NiceFloat(-5.805128395366302), excess_kurtosis: NiceFloat(73.03005686221248), }; special_random_negative_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 1, mean precision = 2 let values = &[ -1.0, -1.5, -3.125, -1.0, -1.0, -2.0, -2.0, -1.0, -3.0, -1.0, -2.0, -3.0, -4.0, -1.5, -1.625, -2.0, -0.125, -1.0, -0.375, -1.5, -6.375, -4.0, -6.875, -0.5, -0.234375, -1.0, -0.2421875, -6.0, -0.75, -6.0, -6.0, -2.0, -0.21875, -2.0, -0.875, -0.875, -6.0, -16.0, -27.0, -2.25, -1.5, -1.5, -8.75, -4.0, -0.25, -1.5, -0.375, -0.375, -1.0, -0.09375, ]; let common_values = &[ (-1.0, 166355), (-2.0, 83686), (-0.5, 83270), (-1.5, 82925), (-3.0, 41733), (-0.75, 41659), (-4.0, 41550), (-0.25, 41388), (-1.75, 21006), (-6.0, 20858), (-0.125, 20779), (-8.0, 20769), (-0.375, 20764), (-1.25, 20753), (-12.0, 10512), (-2.5, 10508), (-0.0625, 10447), (-0.625, 10414), (-0.1875, 10394), (-16.0, 10354), ]; let sample_median = (-1.03125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.654060290573151), standard_deviation: NiceFloat(374.2183970257817), skewness: NiceFloat(-257.0774178486101), excess_kurtosis: NiceFloat(79059.24924350459), }; special_random_negative_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 10, mean precision = 10 let values = &[ -0.80126953, -0.0000013709068, -0.015609741, -0.98552704, -65536.0, -0.008257866, -0.017333984, -2.25, -7.7089844, -0.00004425831, -0.40625, -24576.0, -37249.0, -1.1991882, -32.085938, -0.4375, -0.0012359619, -1536.0, -0.22912993, -0.0015716553, -1.6662057e-8, -0.044523954, -5694464.0, -0.125, -180.0, -5.625, -1572864.0, -1.9092113e-7, -0.28466797, -0.0068359375, -56737790.0, -4813.375, -20.954966, -4.0, -7.3125, -3.6040926, -0.000007293769, -0.018554688, -0.00009602308, -0.000038146973, -0.00022888184, -36.324017, -0.0068359375, -0.008168057, -20.0, -21.398438, -0.21679688, -176.0, -0.11355591, -6144.0, ]; let common_values = &[ (-1.0, 5117), (-1.5, 4684), (-2.0, 4643), (-0.5, 4592), (-3.0, 4327), (-0.75, 4245), (-0.25, 4231), (-4.0, 4186), (-8.0, 3995), (-0.375, 3923), (-6.0, 3869), (-0.125, 3864), (-0.0625, 3534), (-16.0, 3502), (-0.1875, 3489), (-12.0, 3418), (-24.0, 3293), (-32.0, 3244), (-0.09375, 3209), (-0.03125, 3152), ]; let sample_median = (-1.4882812, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.110316815188854e31), standard_deviation: NiceFloat(5.291057687231236e34), skewness: NiceFloat(-817.3228282694379), excess_kurtosis: NiceFloat(702102.631759681), }; special_random_negative_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, ]; let common_values = &[ (-1.0, 954991), (-1.5, 14672), (-2.0, 14586), (-0.5, 14578), (-3.0, 243), (-0.25, 228), (-4.0, 226), (-0.75, 207), (-1.25, 127), (-1.75, 118), (-6.0, 6), (-0.125, 4), (-2.5, 3), (-8.0, 3), (-0.625, 3), (-0.375, 2), (-0.875, 2), (-3.5, 1), ]; let sample_median = (-1.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0157463749999305), standard_deviation: NiceFloat(0.15870215416222863), skewness: NiceFloat(-5.805128395366302), excess_kurtosis: NiceFloat(73.03005686221248), }; special_random_negative_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1, mean precision = 2 let values = &[ -1.0, -1.5, -3.125, -1.0, -1.0, -2.0, -2.0, -1.0, -3.0, -1.0, -2.0, -3.0, -4.0, -1.5, -1.625, -2.0, -0.125, -1.0, -0.375, -1.5, -6.375, -4.0, -6.875, -0.5, -0.234375, -1.0, -0.2421875, -6.0, -0.75, -6.0, -6.0, -2.0, -0.21875, -2.0, -0.875, -0.875, -6.0, -16.0, -27.0, -2.25, -1.5, -1.5, -8.75, -4.0, -0.25, -1.5, -0.375, -0.375, -1.0, -0.09375, ]; let common_values = &[ (-1.0, 166355), (-2.0, 83686), (-0.5, 83270), (-1.5, 82925), (-3.0, 41733), (-0.75, 41659), (-4.0, 41550), (-0.25, 41388), (-1.75, 21006), (-6.0, 20858), (-0.125, 20779), (-8.0, 20769), (-0.375, 20764), (-1.25, 20753), (-12.0, 10512), (-2.5, 10508), (-0.0625, 10447), (-0.625, 10414), (-0.1875, 10394), (-16.0, 10354), ]; let sample_median = (-1.03125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.654060290573151), standard_deviation: NiceFloat(374.2183970257817), skewness: NiceFloat(-257.0774178486101), excess_kurtosis: NiceFloat(79059.24924350459), }; special_random_negative_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 10, mean precision = 10 let values = &[ -0.80126953125, -1.3709068298339844e-6, -0.0156097412109375, -0.9855270385742188, -86113.82421875, -0.012808799743652344, -0.028076171875, -2.75, -7.009765625, -0.000045569613575935364, -0.34375, -24576.0, -33101.0, -1.066680908203125, -53.0390625, -0.3125, -0.0018768310546875, -1536.0, -0.15994291007518768, -0.0014495849609375, -2.5660824576334562e-8, -0.04374957084655762, -6583296.0, -0.125, -156.0, -7.125, -1572864.0, -1.525198978780118e-7, -0.32763671875, -0.0048828125, -47710208.0, -6821.875, -19.824071884155273, -4.0, -4.6875, -2.3686094284057617, -6.33427407592535e-6, -0.0185546875, -0.00007218122482299805, -0.00003814697265625, -0.0001373291015625, -36.43232345581055, -0.0048828125, -0.011424465501870706, -28.0, -18.0546875, -0.2207733978284523, -144.0, -0.083648681640625, -4360.2293701171875, ]; let common_values = &[ (-1.0, 4779), (-1.5, 4356), (-2.0, 4315), (-0.5, 4233), (-3.0, 4023), (-0.25, 3931), (-0.75, 3911), (-4.0, 3866), (-8.0, 3705), (-0.375, 3612), (-6.0, 3588), (-0.125, 3538), (-0.0625, 3271), (-16.0, 3264), (-0.1875, 3199), (-12.0, 3152), (-24.0, 3033), (-32.0, 2974), (-0.09375, 2963), (-0.03125, 2937), ]; let sample_median = (-1.484375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.352183416672257e38), standard_deviation: NiceFloat(5.3521788476440196e41), skewness: NiceFloat(-999.9984999986674), excess_kurtosis: NiceFloat(999995.0000000936), }; special_random_negative_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_negative_finite_primitive_floats_fail_helper() { assert_panic!(special_random_negative_finite_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1 )); assert_panic!(special_random_negative_finite_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1 )); assert_panic!(special_random_negative_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1 )); assert_panic!(special_random_negative_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0 )); } #[test] fn special_random_negative_finite_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_negative_finite_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_negative_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::random::special_random_negative_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, NAN_MOMENT_STATS}; use std::panic::catch_unwind; fn special_random_negative_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_negative_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_negative_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f32::NEGATIVE_INFINITY, -1.5, -1.0, f32::NEGATIVE_INFINITY, -1.0, -1.0, f32::NEGATIVE_INFINITY, -1.0, f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, -1.0, f32::NEGATIVE_INFINITY, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, f32::NEGATIVE_INFINITY, -1.0, f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, -1.0, -1.0, -1.0, -1.0, -1.0, f32::NEGATIVE_INFINITY, -1.0, -1.0, -0.5, -1.0, f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, -1.0, ]; let common_values = &[ (-1.0, 716268), (f32::NEGATIVE_INFINITY, 250209), (-2.0, 10938), (-0.5, 10888), (-1.5, 10871), (-4.0, 172), (-0.25, 165), (-3.0, 161), (-0.75, 155), (-1.25, 75), (-1.75, 74), (-0.375, 6), (-3.5, 4), (-0.125, 4), (-8.0, 3), (-0.875, 2), (-1.875, 2), (-6.0, 1), (-0.625, 1), (-1.125, 1), ]; let sample_median = (-1.0, None); special_random_negative_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ -1.0, -1.0, -3.0, f32::NEGATIVE_INFINITY, -1.0, -1.0, -2.0, -2.0, -1.0, -3.0, -1.0, -3.0, -3.0, f32::NEGATIVE_INFINITY, -6.0, -1.125, -1.25, f32::NEGATIVE_INFINITY, -3.0, -0.125, -1.0, -0.25, -1.75, -4.0, -4.0, -4.0, -0.75, -0.125, -1.0, f32::NEGATIVE_INFINITY, -0.125, -6.0, f32::NEGATIVE_INFINITY, -0.5, -4.0, -6.5, -2.0, -0.21875, -2.0, -0.5, -0.5, -4.0, -16.0, -16.0, -3.0, -1.0, f32::NEGATIVE_INFINITY, -1.0, -10.0, -6.0, ]; let common_values = &[ (-1.0, 151036), (f32::NEGATIVE_INFINITY, 100224), (-0.5, 75239), (-2.0, 74939), (-1.5, 74396), (-0.25, 37669), (-0.75, 37538), (-3.0, 37523), (-4.0, 37411), (-0.375, 18737), (-6.0, 18708), (-0.125, 18698), (-1.25, 18586), (-8.0, 18570), (-1.75, 18339), (-3.5, 9676), (-0.0625, 9668), (-16.0, 9474), (-0.875, 9416), (-12.0, 9376), ]; let sample_median = (-1.5, None); special_random_negative_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ -0.6328125, -9.536743e-7, -0.013671875, -0.6875, -70208.0, -0.01550293, -0.028625488, -3.3095703, -5.775879, -0.000034958124, -0.4375, -31678.0, -49152.0, -1.0, -49.885254, -0.40625, -0.0015869141, -1889.5625, -0.14140439, -0.001449585, -1.4901161e-8, -0.03125, -5750784.0, -0.17578125, -248.0, -5.4375, -1892352.0, -1.5280966e-7, -0.2826419, -0.0057373047, -51642370.0, -6384.0, -27.875542, -6.152041, -6.0, -2.796875, -0.0000057816505, -0.029174805, -0.00011384487, -0.000039815903, -0.00012207031, -48.0, -0.00390625, -0.01171875, -20.0, -21.625, -0.171875, -197.0, -0.11743164, -5532.0, ]; let common_values = &[ (f32::NEGATIVE_INFINITY, 9989), (-1.0, 5059), (-2.0, 4689), (-0.5, 4622), (-1.5, 4576), (-4.0, 4280), (-3.0, 4153), (-0.25, 4130), (-0.75, 4105), (-8.0, 3912), (-6.0, 3841), (-0.125, 3772), (-0.375, 3663), (-16.0, 3536), (-0.1875, 3530), (-0.0625, 3441), (-12.0, 3433), (-0.09375, 3185), (-0.03125, 3176), (-32.0, 3094), ]; let sample_median = (-1.5, None); special_random_negative_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f64::NEGATIVE_INFINITY, -1.5, -1.0, f64::NEGATIVE_INFINITY, -1.0, -1.0, f64::NEGATIVE_INFINITY, -1.0, f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, -1.0, f64::NEGATIVE_INFINITY, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, f64::NEGATIVE_INFINITY, -1.0, f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, -1.0, -1.0, -1.0, -1.0, -1.0, f64::NEGATIVE_INFINITY, -1.0, -1.0, -0.5, -1.0, f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, -1.0, ]; let common_values = &[ (-1.0, 716268), (f64::NEGATIVE_INFINITY, 250209), (-2.0, 10938), (-0.5, 10888), (-1.5, 10871), (-4.0, 172), (-0.25, 165), (-3.0, 161), (-0.75, 155), (-1.25, 75), (-1.75, 74), (-0.375, 6), (-3.5, 4), (-0.125, 4), (-8.0, 3), (-0.875, 2), (-1.875, 2), (-6.0, 1), (-0.625, 1), (-1.125, 1), ]; let sample_median = (-1.0, None); special_random_negative_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ -1.0, -1.0, -3.0, f64::NEGATIVE_INFINITY, -1.0, -1.0, -2.0, -2.0, -1.0, -3.0, -1.0, -3.0, -3.0, f64::NEGATIVE_INFINITY, -6.0, -1.125, -1.25, f64::NEGATIVE_INFINITY, -3.0, -0.125, -1.0, -0.25, -1.75, -4.0, -4.0, -4.0, -0.75, -0.125, -1.0, f64::NEGATIVE_INFINITY, -0.125, -6.0, f64::NEGATIVE_INFINITY, -0.5, -4.0, -6.5, -2.0, -0.21875, -2.0, -0.5, -0.5, -4.0, -16.0, -16.0, -3.0, -1.0, f64::NEGATIVE_INFINITY, -1.0, -10.0, -6.0, ]; let common_values = &[ (-1.0, 151036), (f64::NEGATIVE_INFINITY, 100224), (-0.5, 75239), (-2.0, 74939), (-1.5, 74396), (-0.25, 37669), (-0.75, 37538), (-3.0, 37523), (-4.0, 37411), (-0.375, 18737), (-6.0, 18708), (-0.125, 18698), (-1.25, 18586), (-8.0, 18570), (-1.75, 18339), (-3.5, 9676), (-0.0625, 9668), (-16.0, 9474), (-0.875, 9416), (-12.0, 9376), ]; let sample_median = (-1.5, None); special_random_negative_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ -0.6328125, -9.5367431640625e-7, -0.013671875, -0.6875, -70208.0, -0.0155029296875, -0.02862548828125, -3.3095703125, -5.77587890625, -0.0000349581241607666, -0.4375, -31678.0, -49152.0, -1.0, -49.88525390625, -0.40625, -0.0015869140625, -1889.5625, -0.141404390335083, -0.0014495849609375, -1.4901161193847656e-8, -0.03125, -5750784.0, -0.17578125, -248.0, -5.4375, -1892352.0, -1.528096618130803e-7, -0.2826418876647949, -0.0057373046875, -51642368.0, -6384.0, -27.87554168701172, -6.152040958404541, -6.0, -2.796875, -5.781650543212891e-6, -0.0291748046875, -0.0001138448715209961, -0.00003981590270996094, -0.0001220703125, -48.0, -0.00390625, -0.01171875, -20.0, -21.625, -0.171875, -205.175663292408, -0.118408203125, -6436.0, ]; let common_values = &[ (f64::NEGATIVE_INFINITY, 9989), (-1.0, 4750), (-2.0, 4357), (-0.5, 4257), (-1.5, 4256), (-4.0, 3955), (-3.0, 3844), (-0.25, 3812), (-0.75, 3799), (-8.0, 3628), (-6.0, 3535), (-0.125, 3447), (-0.375, 3398), (-16.0, 3257), (-0.1875, 3234), (-12.0, 3202), (-0.0625, 3182), (-0.09375, 2957), (-0.03125, 2919), (-32.0, 2805), ]; let sample_median = (-1.516387939453125, Some(-1.5162887573242188)); special_random_negative_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); } fn special_random_negative_primitive_floats_fail_helper() { assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1, 1, 10 )); assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1, 1, 10 )); assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1, 1, 10 )); assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0, 1, 10 )); assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 1, 0 )); assert_panic!(special_random_negative_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 2, 1 )); } #[test] fn special_random_negative_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_negative_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_nonzero_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_nonzero_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_nonzero_finite_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_nonzero_finite_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_nonzero_finite_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ -1.5, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -0.5, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 0.5, -1.0, 1.0, -1.5, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.5, 1.0, -1.0, 1.0, 1.0, 1.0, ]; let common_values = &[ (1.0, 478216), (-1.0, 476955), (-2.0, 7440), (-1.5, 7332), (0.5, 7303), (-0.5, 7275), (1.5, 7189), (2.0, 7170), (0.25, 120), (4.0, 116), (-4.0, 114), (3.0, 111), (-3.0, 107), (0.75, 105), (-0.25, 103), (-0.75, 103), (-1.25, 62), (1.75, 61), (1.25, 50), (-1.75, 39), ]; let sample_median = (0.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000541124999999992), standard_deviation: NiceFloat(1.0278732889234226), skewness: NiceFloat(-0.0043076036065952585), excess_kurtosis: NiceFloat(-1.7844456265500606), }; special_random_nonzero_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 1, mean precision = 2 let values = &[ -1.0, -1.0, -3.0, 1.0, -1.0, 2.0, -2.0, -1.0, -3.0, 1.0, 3.0, 3.0, -6.0, -1.125, 1.25, -3.0, -0.125, -1.0, -0.25, -1.75, 4.0, 4.0, -4.0, -0.75, 0.125, -1.0, -0.125, 6.0, 0.5, -4.0, -6.5, 2.0, -0.21875, 2.0, 0.5, -0.5, 4.0, -16.0, 16.0, -3.0, 1.0, 1.0, 10.0, -6.0, 0.25, 1.0, -0.390625, 0.375, 1.5, 0.09375, ]; let common_values = &[ (1.0, 84345), (-1.0, 83427), (-0.5, 42050), (2.0, 41730), (-2.0, 41718), (0.5, 41631), (1.5, 41446), (-1.5, 41312), (3.0, 20932), (-0.25, 20908), (-3.0, 20854), (-0.75, 20853), (-4.0, 20831), (0.25, 20819), (0.75, 20775), (4.0, 20696), (0.125, 10518), (0.375, 10492), (-6.0, 10471), (8.0, 10359), ]; let sample_median = (0.001953125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.14825837830007416), standard_deviation: NiceFloat(371.086277437807), skewness: NiceFloat(-124.2604097831067), excess_kurtosis: NiceFloat(123898.81502837151), }; special_random_nonzero_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 10, mean precision = 10 let values = &[ -0.6328125, -9.536743e-7, -0.013671875, 0.6875, -70208.0, 0.01550293, -0.028625488, -3.3095703, -5.775879, 0.000034958124, 0.4375, 31678.0, -49152.0, -1.0, 49.885254, -0.40625, -0.0015869141, -1889.5625, -0.14140439, -0.001449585, 1.4901161e-8, 0.03125, -5750784.0, -0.17578125, 248.0, -5.4375, -1892352.0, 1.5280966e-7, 0.2826419, -0.0057373047, -51642370.0, 6384.0, -27.875542, 6.152041, 6.0, -2.796875, 0.0000057816505, -0.029174805, 0.00011384487, -0.000039815903, 0.00012207031, 48.0, 0.00390625, -0.01171875, 20.0, 21.625, -0.171875, 197.0, 0.11743164, 5532.0, ]; let common_values = &[ (-1.0, 2552), (1.0, 2548), (2.0, 2409), (-0.5, 2367), (-2.0, 2335), (1.5, 2326), (0.5, 2308), (-1.5, 2290), (-4.0, 2193), (4.0, 2130), (-3.0, 2106), (3.0, 2096), (0.25, 2092), (-0.25, 2085), (-0.75, 2084), (0.75, 2065), (8.0, 2008), (6.0, 1972), (-8.0, 1945), (-0.125, 1922), ]; let sample_median = (1.6940659e-20, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.7799889499291132e31), standard_deviation: NiceFloat(6.206676176137639e34), skewness: NiceFloat(-784.8389177089807), excess_kurtosis: NiceFloat(789333.7989913624), }; special_random_nonzero_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ -1.5, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -0.5, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 0.5, -1.0, 1.0, -1.5, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.5, 1.0, -1.0, 1.0, 1.0, 1.0, ]; let common_values = &[ (1.0, 478216), (-1.0, 476955), (-2.0, 7440), (-1.5, 7332), (0.5, 7303), (-0.5, 7275), (1.5, 7189), (2.0, 7170), (0.25, 120), (4.0, 116), (-4.0, 114), (3.0, 111), (-3.0, 107), (0.75, 105), (-0.25, 103), (-0.75, 103), (-1.25, 62), (1.75, 61), (1.25, 50), (-1.75, 39), ]; let sample_median = (0.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000541124999999992), standard_deviation: NiceFloat(1.0278732889234226), skewness: NiceFloat(-0.0043076036065952585), excess_kurtosis: NiceFloat(-1.7844456265500606), }; special_random_nonzero_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1, mean precision = 2 let values = &[ -1.0, -1.0, -3.0, 1.0, -1.0, 2.0, -2.0, -1.0, -3.0, 1.0, 3.0, 3.0, -6.0, -1.125, 1.25, -3.0, -0.125, -1.0, -0.25, -1.75, 4.0, 4.0, -4.0, -0.75, 0.125, -1.0, -0.125, 6.0, 0.5, -4.0, -6.5, 2.0, -0.21875, 2.0, 0.5, -0.5, 4.0, -16.0, 16.0, -3.0, 1.0, 1.0, 10.0, -6.0, 0.25, 1.0, -0.390625, 0.375, 1.5, 0.09375, ]; let common_values = &[ (1.0, 84345), (-1.0, 83427), (-0.5, 42050), (2.0, 41730), (-2.0, 41718), (0.5, 41631), (1.5, 41446), (-1.5, 41312), (3.0, 20932), (-0.25, 20908), (-3.0, 20854), (-0.75, 20853), (-4.0, 20831), (0.25, 20819), (0.75, 20775), (4.0, 20696), (0.125, 10518), (0.375, 10492), (-6.0, 10471), (8.0, 10359), ]; let sample_median = (0.001953125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.14825837830007416), standard_deviation: NiceFloat(371.086277437807), skewness: NiceFloat(-124.2604097831067), excess_kurtosis: NiceFloat(123898.81502837151), }; special_random_nonzero_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 10, mean precision = 10 let values = &[ -0.6328125, -9.5367431640625e-7, -0.013671875, 0.6875, -70208.0, 0.0155029296875, -0.02862548828125, -3.3095703125, -5.77587890625, 0.0000349581241607666, 0.4375, 31678.0, -49152.0, -1.0, 49.88525390625, -0.40625, -0.0015869140625, -1889.5625, -0.141404390335083, -0.0014495849609375, 1.4901161193847656e-8, 0.03125, -5750784.0, -0.17578125, 248.0, -5.4375, -1892352.0, 1.528096618130803e-7, 0.2826418876647949, -0.0057373046875, -51642368.0, 6384.0, -27.87554168701172, 6.152040958404541, 6.0, -2.796875, 5.781650543212891e-6, -0.0291748046875, 0.0001138448715209961, -0.00003981590270996094, 0.0001220703125, 48.0, 0.00390625, -0.01171875, 20.0, 21.625, -0.171875, 205.175663292408, 0.118408203125, 6436.0, ]; let common_values = &[ (-1.0, 2444), (1.0, 2346), (2.0, 2250), (1.5, 2165), (-0.5, 2156), (-2.0, 2155), (0.5, 2150), (-1.5, 2135), (4.0, 2036), (-4.0, 1965), (0.75, 1957), (-0.25, 1953), (3.0, 1950), (-3.0, 1943), (0.25, 1899), (-0.75, 1878), (8.0, 1866), (6.0, 1819), (-8.0, 1804), (0.125, 1779), ]; let sample_median = (2.3597808514912774e-20, Some(2.371692252312041e-20)); let sample_moment_stats = MomentStats { mean: NiceFloat(5.965455610813376e38), standard_deviation: NiceFloat(5.9654493406037485e41), skewness: NiceFloat(999.998499997817), excess_kurtosis: NiceFloat(999994.9999989544), }; special_random_nonzero_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_nonzero_finite_primitive_floats_fail_helper() { assert_panic!(special_random_nonzero_finite_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1 )); assert_panic!(special_random_nonzero_finite_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1 )); assert_panic!(special_random_nonzero_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1 )); assert_panic!(special_random_nonzero_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0 )); } #[test] fn special_random_nonzero_finite_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_nonzero_finite_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_nonzero_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::random::special_random_nonzero_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, NAN_MOMENT_STATS}; use std::panic::catch_unwind; fn special_random_nonzero_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_nonzero_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_nonzero_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f32::INFINITY, 1.0, 1.0, f32::NEGATIVE_INFINITY, 1.0, -1.0, f32::INFINITY, -1.0, f32::INFINITY, f32::NEGATIVE_INFINITY, -1.0, f32::NEGATIVE_INFINITY, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, f32::INFINITY, -1.5, f32::NEGATIVE_INFINITY, f32::INFINITY, -1.0, 1.0, -1.0, -1.0, -1.0, f32::INFINITY, 1.0, -1.0, -0.5, -1.0, f32::NEGATIVE_INFINITY, f32::INFINITY, f32::INFINITY, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (f32::INFINITY, 125637), (f32::NEGATIVE_INFINITY, 124572), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), (4.0, 75), (-1.25, 48), (1.75, 44), ]; let sample_median = (0.5, None); special_random_nonzero_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.25, 3.0, f32::INFINITY, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, f32::NEGATIVE_INFINITY, -6.5, -1.0, -1.0, f32::INFINITY, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, f32::INFINITY, -0.1875, -7.5, f32::NEGATIVE_INFINITY, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, f32::NEGATIVE_INFINITY, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (f32::INFINITY, 50351), (f32::NEGATIVE_INFINITY, 49873), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), (-0.25, 18537), (0.125, 9445), (-0.375, 9395), ]; let sample_median = (0.0048828125, None); special_random_nonzero_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.65625, 0.0000014255784, 0.013183594, -0.8125, -74240.0, -0.0078125, -0.03060913, 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, -59392.0, -1.75, -41.1875, 0.30940247, -0.0009765625, -1536.0, 0.2109375, 0.0014648438, 2.1129381e-8, -0.037109375, 5242880.0, -0.21386719, 134.21094, 4.184082, -1561370.0, -2.1420419e-7, 0.38085938, -0.007003784, -37748736.0, -6448.0, 28.25, -6.703125, -4.483364, -3.1757812, 0.000003915804, -0.020751953, 0.00011110306, -0.000053405256, 0.00019985437, -35.40625, 0.005859375, 0.0078125, 28.25, 30.0, -0.20776367, -144.0, -0.109375, -6144.0, ]; let common_values = &[ (f32::INFINITY, 5098), (f32::NEGATIVE_INFINITY, 4891), (1.0, 2559), (-1.0, 2528), (0.5, 2362), (-2.0, 2312), (-1.5, 2306), (2.0, 2304), (1.5, 2275), (-0.5, 2243), (-3.0, 2204), (-4.0, 2163), (-0.25, 2129), (0.75, 2103), (3.0, 2081), (0.25, 2070), (-0.75, 2047), (4.0, 2038), (-6.0, 1943), (-8.0, 1918), ]; let sample_median = (2.1684043e-19, None); special_random_nonzero_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f64::INFINITY, 1.0, 1.0, f64::NEGATIVE_INFINITY, 1.0, -1.0, f64::INFINITY, -1.0, f64::INFINITY, f64::NEGATIVE_INFINITY, -1.0, f64::NEGATIVE_INFINITY, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, f64::INFINITY, -1.5, f64::NEGATIVE_INFINITY, f64::INFINITY, -1.0, 1.0, -1.0, -1.0, -1.0, f64::INFINITY, 1.0, -1.0, -0.5, -1.0, f64::NEGATIVE_INFINITY, f64::INFINITY, f64::INFINITY, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (f64::INFINITY, 125637), (f64::NEGATIVE_INFINITY, 124572), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), (4.0, 75), (-1.25, 48), (1.75, 44), ]; let sample_median = (0.5, None); special_random_nonzero_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.25, 3.0, f64::INFINITY, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, f64::NEGATIVE_INFINITY, -6.5, -1.0, -1.0, f64::INFINITY, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, f64::INFINITY, -0.1875, -7.5, f64::NEGATIVE_INFINITY, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, f64::NEGATIVE_INFINITY, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (f64::INFINITY, 50351), (f64::NEGATIVE_INFINITY, 49873), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), (-0.25, 18537), (0.125, 9445), (-0.375, 9395), ]; let sample_median = (0.0048828125, None); special_random_nonzero_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.7709910366684198, 1.2504315236583352e-6, 0.00830078125, -0.8125, -85504.0, -0.0078125, -0.018890380859375, 2.5721821784973145, 5.75, -0.00003814697265625, -0.4375, -24064.0, -43008.0, -1.75, -54.6875, 0.4641265869140625, -0.0014760522753931582, -1536.0, 0.1484375, 0.00146484375, 1.9383151084184647e-8, -0.060546875, 7340032.0, -0.1982421875, 203.0546875, 4.57177734375, -1555162.0, -2.0675361156463623e-7, 0.279296875, -0.0045928955078125, -46137344.0, -5712.0, 17.75, -5.265625, -7.966220855712891, -2.99609375, 5.397188942879438e-6, -0.017333984375, 0.00011491775512695312, -0.00005845972555107437, 0.00020831823348999023, -46.78125, 0.005859375, 0.0078125, 27.25, 30.0, -0.175537109375, -208.0, -0.109375, -6144.0, ]; let common_values = &[ (f64::INFINITY, 5098), (f64::NEGATIVE_INFINITY, 4891), (1.0, 2396), (-1.0, 2336), (-2.0, 2200), (-1.5, 2169), (0.5, 2116), (2.0, 2108), (-0.5, 2101), (1.5, 2085), (-3.0, 2000), (4.0, 1993), (3.0, 1969), (-0.25, 1955), (0.75, 1946), (0.25, 1917), (-4.0, 1882), (-0.75, 1863), (8.0, 1826), (-6.0, 1782), ]; let sample_median = (2.1519930816179568e-19, Some(2.168404344971009e-19)); special_random_nonzero_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); } fn special_random_nonzero_primitive_floats_fail_helper() { assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1, 1, 10 )); assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1, 1, 10 )); assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1, 1, 10 )); assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0, 1, 10 )); assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 1, 0 )); assert_panic!(special_random_nonzero_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 2, 1 )); } #[test] fn special_random_nonzero_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_nonzero_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_positive_finite_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_positive_finite_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_positive_finite_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_positive_finite_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ]; let common_values = &[ (1.0, 954991), (1.5, 14672), (2.0, 14586), (0.5, 14578), (3.0, 243), (0.25, 228), (4.0, 226), (0.75, 207), (1.25, 127), (1.75, 118), (6.0, 6), (0.125, 4), (2.5, 3), (8.0, 3), (0.625, 3), (0.375, 2), (0.875, 2), (3.5, 1), ]; let sample_median = (1.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0157463749999305), standard_deviation: NiceFloat(0.15870215416222863), skewness: NiceFloat(5.805128395366302), excess_kurtosis: NiceFloat(73.03005686221248), }; special_random_positive_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 1, mean precision = 2 let values = &[ 1.0, 1.5, 3.125, 1.0, 1.0, 2.0, 2.0, 1.0, 3.0, 1.0, 2.0, 3.0, 4.0, 1.5, 1.625, 2.0, 0.125, 1.0, 0.375, 1.5, 6.375, 4.0, 6.875, 0.5, 0.234375, 1.0, 0.2421875, 6.0, 0.75, 6.0, 6.0, 2.0, 0.21875, 2.0, 0.875, 0.875, 6.0, 16.0, 27.0, 2.25, 1.5, 1.5, 8.75, 4.0, 0.25, 1.5, 0.375, 0.375, 1.0, 0.09375, ]; let common_values = &[ (1.0, 166355), (2.0, 83686), (0.5, 83270), (1.5, 82925), (3.0, 41733), (0.75, 41659), (4.0, 41550), (0.25, 41388), (1.75, 21006), (6.0, 20858), (0.125, 20779), (8.0, 20769), (0.375, 20764), (1.25, 20753), (12.0, 10512), (2.5, 10508), (0.0625, 10447), (0.625, 10414), (0.1875, 10394), (16.0, 10354), ]; let sample_median = (1.03125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.654060290573151), standard_deviation: NiceFloat(374.2183970257817), skewness: NiceFloat(257.0774178486101), excess_kurtosis: NiceFloat(79059.24924350459), }; special_random_positive_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f32, mean abs of exponent = 10, mean precision = 10 let values = &[ 0.80126953, 0.0000013709068, 0.015609741, 0.98552704, 65536.0, 0.008257866, 0.017333984, 2.25, 7.7089844, 0.00004425831, 0.40625, 24576.0, 37249.0, 1.1991882, 32.085938, 0.4375, 0.0012359619, 1536.0, 0.22912993, 0.0015716553, 1.6662057e-8, 0.044523954, 5694464.0, 0.125, 180.0, 5.625, 1572864.0, 1.9092113e-7, 0.28466797, 0.0068359375, 56737790.0, 4813.375, 20.954966, 4.0, 7.3125, 3.6040926, 0.000007293769, 0.018554688, 0.00009602308, 0.000038146973, 0.00022888184, 36.324017, 0.0068359375, 0.008168057, 20.0, 21.398438, 0.21679688, 176.0, 0.11355591, 6144.0, ]; let common_values = &[ (1.0, 5117), (1.5, 4684), (2.0, 4643), (0.5, 4592), (3.0, 4327), (0.75, 4245), (0.25, 4231), (4.0, 4186), (8.0, 3995), (0.375, 3923), (6.0, 3869), (0.125, 3864), (0.0625, 3534), (16.0, 3502), (0.1875, 3489), (12.0, 3418), (24.0, 3293), (32.0, 3244), (0.09375, 3209), (0.03125, 3152), ]; let sample_median = (1.4882812, None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.110316815188854e31), standard_deviation: NiceFloat(5.291057687231236e34), skewness: NiceFloat(817.3228282694379), excess_kurtosis: NiceFloat(702102.631759681), }; special_random_positive_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64 let values = &[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ]; let common_values = &[ (1.0, 954991), (1.5, 14672), (2.0, 14586), (0.5, 14578), (3.0, 243), (0.25, 228), (4.0, 226), (0.75, 207), (1.25, 127), (1.75, 118), (6.0, 6), (0.125, 4), (2.5, 3), (8.0, 3), (0.625, 3), (0.375, 2), (0.875, 2), (3.5, 1), ]; let sample_median = (1.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0157463749999305), standard_deviation: NiceFloat(0.15870215416222863), skewness: NiceFloat(5.805128395366302), excess_kurtosis: NiceFloat(73.03005686221248), }; special_random_positive_finite_primitive_floats_helper::( 1, 64, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 1, mean precision = 2 let values = &[ 1.0, 1.5, 3.125, 1.0, 1.0, 2.0, 2.0, 1.0, 3.0, 1.0, 2.0, 3.0, 4.0, 1.5, 1.625, 2.0, 0.125, 1.0, 0.375, 1.5, 6.375, 4.0, 6.875, 0.5, 0.234375, 1.0, 0.2421875, 6.0, 0.75, 6.0, 6.0, 2.0, 0.21875, 2.0, 0.875, 0.875, 6.0, 16.0, 27.0, 2.25, 1.5, 1.5, 8.75, 4.0, 0.25, 1.5, 0.375, 0.375, 1.0, 0.09375, ]; let common_values = &[ (1.0, 166355), (2.0, 83686), (0.5, 83270), (1.5, 82925), (3.0, 41733), (0.75, 41659), (4.0, 41550), (0.25, 41388), (1.75, 21006), (6.0, 20858), (0.125, 20779), (8.0, 20769), (0.375, 20764), (1.25, 20753), (12.0, 10512), (2.5, 10508), (0.0625, 10447), (0.625, 10414), (0.1875, 10394), (16.0, 10354), ]; let sample_median = (1.03125, None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.654060290573151), standard_deviation: NiceFloat(374.2183970257817), skewness: NiceFloat(257.0774178486101), excess_kurtosis: NiceFloat(79059.24924350459), }; special_random_positive_finite_primitive_floats_helper::( 1, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // f64, mean abs of exponent = 10, mean precision = 10 let values = &[ 0.80126953125, 1.3709068298339844e-6, 0.0156097412109375, 0.9855270385742188, 86113.82421875, 0.012808799743652344, 0.028076171875, 2.75, 7.009765625, 0.000045569613575935364, 0.34375, 24576.0, 33101.0, 1.066680908203125, 53.0390625, 0.3125, 0.0018768310546875, 1536.0, 0.15994291007518768, 0.0014495849609375, 2.5660824576334562e-8, 0.04374957084655762, 6583296.0, 0.125, 156.0, 7.125, 1572864.0, 1.525198978780118e-7, 0.32763671875, 0.0048828125, 47710208.0, 6821.875, 19.824071884155273, 4.0, 4.6875, 2.3686094284057617, 6.33427407592535e-6, 0.0185546875, 0.00007218122482299805, 0.00003814697265625, 0.0001373291015625, 36.43232345581055, 0.0048828125, 0.011424465501870706, 28.0, 18.0546875, 0.2207733978284523, 144.0, 0.083648681640625, 4360.2293701171875, ]; let common_values = &[ (1.0, 4779), (1.5, 4356), (2.0, 4315), (0.5, 4233), (3.0, 4023), (0.25, 3931), (0.75, 3911), (4.0, 3866), (8.0, 3705), (0.375, 3612), (6.0, 3588), (0.125, 3538), (0.0625, 3271), (16.0, 3264), (0.1875, 3199), (12.0, 3152), (24.0, 3033), (32.0, 2974), (0.09375, 2963), (0.03125, 2937), ]; let sample_median = (1.484375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.352183416672257e38), standard_deviation: NiceFloat(5.3521788476440196e41), skewness: NiceFloat(999.9984999986674), excess_kurtosis: NiceFloat(999995.0000000936), }; special_random_positive_finite_primitive_floats_helper::( 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_positive_finite_primitive_floats_fail_helper() { assert_panic!(special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1 )); assert_panic!(special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1 )); assert_panic!(special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1 )); assert_panic!(special_random_positive_finite_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0 )); } #[test] fn special_random_positive_finite_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_positive_finite_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_positive_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::random::special_random_positive_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, NAN_MOMENT_STATS}; use std::panic::catch_unwind; fn special_random_positive_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_positive_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_positive_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f32::INFINITY, 1.5, 1.0, f32::INFINITY, 1.0, 1.0, f32::INFINITY, 1.0, f32::INFINITY, f32::INFINITY, 1.0, f32::INFINITY, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, f32::INFINITY, 1.0, f32::INFINITY, f32::INFINITY, 1.0, 1.0, 1.0, 1.0, 1.0, f32::INFINITY, 1.0, 1.0, 0.5, 1.0, f32::INFINITY, f32::INFINITY, f32::INFINITY, 1.0, ]; let common_values = &[ (1.0, 716268), (f32::INFINITY, 250209), (2.0, 10938), (0.5, 10888), (1.5, 10871), (4.0, 172), (0.25, 165), (3.0, 161), (0.75, 155), (1.25, 75), (1.75, 74), (0.375, 6), (3.5, 4), (0.125, 4), (8.0, 3), (0.875, 2), (1.875, 2), (6.0, 1), (0.625, 1), (1.125, 1), ]; let sample_median = (1.0, None); special_random_positive_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.0, 3.0, f32::INFINITY, 1.0, 1.0, 2.0, 2.0, 1.0, 3.0, 1.0, 3.0, 3.0, f32::INFINITY, 6.0, 1.125, 1.25, f32::INFINITY, 3.0, 0.125, 1.0, 0.25, 1.75, 4.0, 4.0, 4.0, 0.75, 0.125, 1.0, f32::INFINITY, 0.125, 6.0, f32::INFINITY, 0.5, 4.0, 6.5, 2.0, 0.21875, 2.0, 0.5, 0.5, 4.0, 16.0, 16.0, 3.0, 1.0, f32::INFINITY, 1.0, 10.0, 6.0, ]; let common_values = &[ (1.0, 151036), (f32::INFINITY, 100224), (0.5, 75239), (2.0, 74939), (1.5, 74396), (0.25, 37669), (0.75, 37538), (3.0, 37523), (4.0, 37411), (0.375, 18737), (6.0, 18708), (0.125, 18698), (1.25, 18586), (8.0, 18570), (1.75, 18339), (3.5, 9676), (0.0625, 9668), (16.0, 9474), (0.875, 9416), (12.0, 9376), ]; let sample_median = (1.5, None); special_random_positive_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.6328125, 9.536743e-7, 0.013671875, 0.6875, 70208.0, 0.01550293, 0.028625488, 3.3095703, 5.775879, 0.000034958124, 0.4375, 31678.0, 49152.0, 1.0, 49.885254, 0.40625, 0.0015869141, 1889.5625, 0.14140439, 0.001449585, 1.4901161e-8, 0.03125, 5750784.0, 0.17578125, 248.0, 5.4375, 1892352.0, 1.5280966e-7, 0.2826419, 0.0057373047, 51642370.0, 6384.0, 27.875542, 6.152041, 6.0, 2.796875, 0.0000057816505, 0.029174805, 0.00011384487, 0.000039815903, 0.00012207031, 48.0, 0.00390625, 0.01171875, 20.0, 21.625, 0.171875, 197.0, 0.11743164, 5532.0, ]; let common_values = &[ (f32::INFINITY, 9989), (1.0, 5059), (2.0, 4689), (0.5, 4622), (1.5, 4576), (4.0, 4280), (3.0, 4153), (0.25, 4130), (0.75, 4105), (8.0, 3912), (6.0, 3841), (0.125, 3772), (0.375, 3663), (16.0, 3536), (0.1875, 3530), (0.0625, 3441), (12.0, 3433), (0.09375, 3185), (0.03125, 3176), (32.0, 3094), ]; let sample_median = (1.5, None); special_random_positive_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f64::INFINITY, 1.5, 1.0, f64::INFINITY, 1.0, 1.0, f64::INFINITY, 1.0, f64::INFINITY, f64::INFINITY, 1.0, f64::INFINITY, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, f64::INFINITY, 1.0, f64::INFINITY, f64::INFINITY, 1.0, 1.0, 1.0, 1.0, 1.0, f64::INFINITY, 1.0, 1.0, 0.5, 1.0, f64::INFINITY, f64::INFINITY, f64::INFINITY, 1.0, ]; let common_values = &[ (1.0, 716268), (f64::INFINITY, 250209), (2.0, 10938), (0.5, 10888), (1.5, 10871), (4.0, 172), (0.25, 165), (3.0, 161), (0.75, 155), (1.25, 75), (1.75, 74), (0.375, 6), (3.5, 4), (0.125, 4), (8.0, 3), (0.875, 2), (1.875, 2), (6.0, 1), (0.625, 1), (1.125, 1), ]; let sample_median = (1.0, None); special_random_positive_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.0, 3.0, f64::INFINITY, 1.0, 1.0, 2.0, 2.0, 1.0, 3.0, 1.0, 3.0, 3.0, f64::INFINITY, 6.0, 1.125, 1.25, f64::INFINITY, 3.0, 0.125, 1.0, 0.25, 1.75, 4.0, 4.0, 4.0, 0.75, 0.125, 1.0, f64::INFINITY, 0.125, 6.0, f64::INFINITY, 0.5, 4.0, 6.5, 2.0, 0.21875, 2.0, 0.5, 0.5, 4.0, 16.0, 16.0, 3.0, 1.0, f64::INFINITY, 1.0, 10.0, 6.0, ]; let common_values = &[ (1.0, 151036), (f64::INFINITY, 100224), (0.5, 75239), (2.0, 74939), (1.5, 74396), (0.25, 37669), (0.75, 37538), (3.0, 37523), (4.0, 37411), (0.375, 18737), (6.0, 18708), (0.125, 18698), (1.25, 18586), (8.0, 18570), (1.75, 18339), (3.5, 9676), (0.0625, 9668), (16.0, 9474), (0.875, 9416), (12.0, 9376), ]; let sample_median = (1.5, None); special_random_positive_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.6328125, 9.5367431640625e-7, 0.013671875, 0.6875, 70208.0, 0.0155029296875, 0.02862548828125, 3.3095703125, 5.77587890625, 0.0000349581241607666, 0.4375, 31678.0, 49152.0, 1.0, 49.88525390625, 0.40625, 0.0015869140625, 1889.5625, 0.141404390335083, 0.0014495849609375, 1.4901161193847656e-8, 0.03125, 5750784.0, 0.17578125, 248.0, 5.4375, 1892352.0, 1.528096618130803e-7, 0.2826418876647949, 0.0057373046875, 51642368.0, 6384.0, 27.87554168701172, 6.152040958404541, 6.0, 2.796875, 5.781650543212891e-6, 0.0291748046875, 0.0001138448715209961, 0.00003981590270996094, 0.0001220703125, 48.0, 0.00390625, 0.01171875, 20.0, 21.625, 0.171875, 205.175663292408, 0.118408203125, 6436.0, ]; let common_values = &[ (f64::INFINITY, 9989), (1.0, 4750), (2.0, 4357), (0.5, 4257), (1.5, 4256), (4.0, 3955), (3.0, 3844), (0.25, 3812), (0.75, 3799), (8.0, 3628), (6.0, 3535), (0.125, 3447), (0.375, 3398), (16.0, 3257), (0.1875, 3234), (12.0, 3202), (0.0625, 3182), (0.09375, 2957), (0.03125, 2919), (32.0, 2805), ]; let sample_median = (1.5162887573242188, Some(1.516387939453125)); special_random_positive_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); } fn special_random_positive_primitive_floats_fail_helper() { assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1, 1, 10 )); assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1, 1, 10 )); assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1, 1, 10 )); assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0, 1, 10 )); assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 1, 0 )); assert_panic!(special_random_positive_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 2, 1 )); } #[test] fn special_random_positive_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_positive_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_primitive_float_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_primitive_float_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_primitive_float_inclusive_range_helper( a: T, b: T, mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, a, b, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_primitive_float_inclusive_range() { // f32, a = 1.0, b = 2.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 2.0, 2.0, 2.0, 1.0, 1.5, 2.0, 1.0, 1.0, 1.5, 2.0, 1.28125, 1.0, 2.0, 1.0, 1.4375, 1.8125, 1.6875, 1.0, 1.75, 1.875, 2.0, 1.0, 2.0, 1.0, 1.75, 2.0, 2.0, 2.0, 2.0, 1.75, 2.0, 1.5, 1.484375, 2.0, 1.0, 2.0, 1.75, 2.0, 1.25, 1.0, 1.5, 1.25, 1.546875, 1.0, 2.0, 2.0, 2.0, 1.4921875, 2.0, 2.0, ]; let common_values = &[ (2.0, 332566), (1.0, 222413), (1.5, 148427), (1.25, 49546), (1.75, 49274), (1.875, 16717), (1.125, 16593), (1.375, 16567), (1.625, 16551), (1.8125, 5566), (1.5625, 5553), (1.9375, 5543), (1.1875, 5451), (1.4375, 5383), (1.6875, 5367), (1.3125, 5361), (1.0625, 5322), (1.21875, 1873), (1.34375, 1871), (1.40625, 1865), ]; let sample_median = (1.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5553208489836596), standard_deviation: NiceFloat(0.3974073963635055), skewness: NiceFloat(-0.20042532167244795), excess_kurtosis: NiceFloat(-1.5078861004584492), }; special_random_primitive_float_inclusive_range_helper::( 1.0, 2.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0, b = 2.0, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.0, 2.0, 1.0, 1.640625, 1.375, 2.0, 1.90625, 2.0, 2.0, 1.25, 1.0, 2.0, 2.0, 1.9375, 1.5, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1.96875, 2.0, 1.1479492, 1.4569855, 1.2559814, 1.5579834, 2.0, 2.0, 1.2250977, 1.1882324, 1.5, 2.0, 1.6498959, 2.0, 1.1252441, 2.0, 2.0, 2.0, 1.0336914, 2.0, 2.0, 2.0, 2.0, 1.5, 1.375, 2.0, 1.0, 1.125, ]; let common_values = &[ (2.0, 476330), (1.0, 52792), (1.5, 47801), (1.25, 22022), (1.75, 21892), (1.875, 10017), (1.625, 9986), (1.375, 9985), (1.125, 9951), (1.8125, 4622), (1.4375, 4596), (1.1875, 4577), (1.9375, 4552), (1.5625, 4549), (1.3125, 4532), (1.0625, 4507), (1.6875, 4455), (1.96875, 2147), (1.15625, 2105), (1.28125, 2098), ]; let sample_median = (1.9371719, Some(1.9371796)); let sample_moment_stats = MomentStats { mean: NiceFloat(1.712172784260269), standard_deviation: NiceFloat(0.34826759681331443), skewness: NiceFloat(-0.7989590190130814), excess_kurtosis: NiceFloat(-0.8454122824548973), }; special_random_primitive_float_inclusive_range_helper::( 1.0, 2.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1, mean abs of exponent = 5, mean precision = 2, mean zero P = 1/10 let values = &[ 0.09375, 0.01171875, 0.01171875, -0.0, -0.09375, -0.01171875, -0.01171875, -0.03125, 0.03125, 0.0625, -0.0625, -0.07525635, -0.0625, 0.0, -0.09375, -0.09375, -0.09375, -0.0, 0.07525635, -0.078125, -0.05078125, 0.0625, 0.09375, 0.09375, -0.024414062, 0.09375, -0.001953125, 0.078125, 0.05078125, -0.0, -0.0625, -0.09375, 0.0, 0.024414062, -0.03125, -0.0043945312, -0.09375, 0.001953125, -0.09375, -0.003540039, -0.03125, 0.0625, -0.046875, 0.09375, -0.0625, 0.03125, 0.0, -0.0146484375, 0.0043945312, 0.09375, ]; let common_values = &[ (0.0625, 74962), (-0.0625, 74736), (-0.0, 50351), (0.09375, 50309), (-0.09375, 50178), (0.0, 49873), (0.03125, 37782), (-0.03125, 37678), (0.078125, 33219), (-0.078125, 33138), (0.046875, 25130), (-0.046875, 25053), (0.015625, 18743), (-0.015625, 18692), (0.0234375, 12593), (-0.0234375, 12549), (0.0703125, 11091), (0.0859375, 11088), (-0.0859375, 11060), (-0.0703125, 11055), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0000674789649248169), standard_deviation: NiceFloat(0.05672019953597066), skewness: NiceFloat(-0.001702872258409426), excess_kurtosis: NiceFloat(-1.109977309372344), }; special_random_primitive_float_inclusive_range_helper::( -0.1, 0.1, 5, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.0041503906, 0.0625, 0.00042547443, -0.0041503906, -0.0625, -0.00042547443, -0.0027618408, 0.0027618408, 0.09375, -0.09375, -0.083244324, -0.076171875, -0.00023269653, -0.00043609738, -0.0029296875, 0.083244324, -0.011459351, -0.05419922, 0.076171875, 0.00023269653, 0.00043609738, -0.000006198883, 0.0029296875, -0.0008621216, 0.011459351, 0.05419922, -0.00035095215, -0.0625, 0.000006198883, -0.0008010864, -0.00030517578, -0.00008274312, 0.0008621216, -0.0029296875, -0.04892564, -0.013671875, 0.00035095215, -0.0009398293, 0.0625, -0.07344723, 0.0008010864, -0.01953125, 0.00030517578, 0.00008274312, 0.0029296875, 0.04892564, -0.006134033, -0.0070343018, -0.005493164, -0.0000029057264, ]; let common_values = &[ (0.0625, 7060), (-0.0625, 7045), (0.09375, 6481), (-0.09375, 6468), (0.03125, 6186), (-0.03125, 6171), (0.078125, 5831), (-0.078125, 5813), (0.046875, 5527), (-0.046875, 5516), (0.015625, 5112), (-0.015625, 5103), (-0.0, 5098), (0.0, 4891), (0.0234375, 4821), (-0.0234375, 4810), (0.0078125, 4681), (-0.0078125, 4678), (0.01171875, 4123), (-0.01171875, 4120), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000022248151599295377), standard_deviation: NiceFloat(0.035382441406785786), skewness: NiceFloat(0.0002929225243710825), excess_kurtosis: NiceFloat(1.5823949638933827), }; special_random_primitive_float_inclusive_range_helper::( -0.1, 0.1, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π, mean abs of exponent = 3, mean precision = 2, mean zero P = 1/10 let values = &[ 3.0, 2.859375, 3.0234375, 3.0, 2.75, 3.0, 3.0, 3.0, 2.75, 2.75, 3.078125, 3.0, 3.0, 3.0, 2.84375, 2.84375, 2.96875, 3.0, 3.125, 2.8125, 3.0, 3.0, 3.03125, 3.0, 3.125, 3.125, 2.875, 3.0, 2.75, 2.875, 3.0, 2.75, 2.9140625, 2.734375, 3.0, 3.0, 3.125, 2.9257812, 3.125, 3.0, 2.75, 3.125, 2.9921875, 3.0, 2.75, 3.0, 3.0, 3.0195312, 3.0, 2.8125, ]; let common_values = &[ (3.0, 333251), (2.75, 222162), (3.125, 74149), (2.875, 74011), (3.0625, 33262), (2.8125, 33146), (2.9375, 33097), (2.90625, 9548), (2.78125, 9377), (2.71875, 9327), (3.03125, 9327), (3.09375, 9323), (2.84375, 9315), (2.96875, 9265), (2.859375, 3186), (3.015625, 3185), (2.796875, 3180), (3.046875, 3160), (3.140625, 3157), (2.765625, 3152), ]; let sample_median = (3.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.923236772231216), standard_deviation: NiceFloat(0.12616339323242115), skewness: NiceFloat(-0.17689588042510748), excess_kurtosis: NiceFloat(-1.2738593390011854), }; special_random_primitive_float_inclusive_range_helper::( core::f32::consts::E, core::f32::consts::PI, 3, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.9238281, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462658, 3.140625, 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.0214844, 2.970642, 3.0179443, 2.968872, 2.75, 2.9763536, 2.875, 2.890625, 2.8388672, 2.7814941, 3.087654, 3.1065063, 2.817566, 2.8125, 2.7746582, 2.746338, 3.0207214, 2.75, 2.9852295, 3.0, 2.9980469, 3.006958, 2.875, 2.8632812, 2.9277344, 3.088623, 2.8376465, 3.0, 3.0, 3.0117188, 2.75, 2.8125, 3.0, 3.0, 3.140625, ]; let common_values = &[ (3.0, 103073), (2.75, 94168), (2.875, 43152), (3.125, 42886), (3.0625, 26213), (2.8125, 25982), (2.9375, 25799), (2.90625, 10203), (2.71875, 10186), (2.84375, 10149), (3.09375, 10141), (3.03125, 10134), (2.78125, 10085), (2.96875, 10085), (3.046875, 4666), (2.734375, 4649), (2.765625, 4649), (3.109375, 4629), (2.859375, 4606), (3.140625, 4590), ]; let sample_median = (2.9375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.925577550306893), standard_deviation: NiceFloat(0.12565616542944752), skewness: NiceFloat(-0.016691773531483878), excess_kurtosis: NiceFloat(-1.2405888218124512), }; special_random_primitive_float_inclusive_range_helper::( core::f32::consts::E, core::f32::consts::PI, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0, mean abs of exponent = 7, mean precision = 2, mean zero P = 1/10 let values = &[ 100.0, 100.5625, 100.40625, 100.0, 101.0, 100.0, 100.0, 100.0, 101.0, 101.0, 100.8125, 100.0, 100.0, 100.0, 100.375, 100.875, 100.875, 100.0, 100.5, 100.75, 100.0, 100.0, 100.875, 100.0, 100.5, 100.5, 100.5, 100.0, 101.0, 100.5, 100.0, 101.0, 100.46875, 100.1875, 100.0, 100.0, 100.5, 100.546875, 100.5, 100.0, 101.0, 100.5, 100.96875, 100.0, 101.0, 100.0, 100.0, 100.296875, 100.0, 100.75, ]; let common_values = &[ (100.0, 333338), (101.0, 222241), (100.5, 148191), (100.75, 49867), (100.25, 49679), (100.625, 16568), (100.875, 16322), (100.125, 16318), (100.375, 16281), (100.6875, 5585), (100.3125, 5557), (100.5625, 5547), (100.1875, 5520), (100.9375, 5484), (100.0625, 5464), (100.8125, 5438), (100.4375, 5236), (100.71875, 1933), (100.09375, 1868), (100.34375, 1863), ]; let sample_median = (100.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.44460313228277), standard_deviation: NiceFloat(0.3974843507339211), skewness: NiceFloat(0.19977351658386902), excess_kurtosis: NiceFloat(-1.5086143196425152), }; special_random_primitive_float_inclusive_range_helper::( 100.0, 101.0, 7, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0, mean abs of exponent = 10, mean precision = 10, mean zero P = // 1/100 let values = &[ 100.82031, 100.5625, 100.0, 100.71875, 100.75, 100.5, 100.9375, 100.88427, 100.9375, 100.5, 100.0, 101.0, 100.0, 100.125, 101.0, 100.46094, 100.51196, 100.46338, 100.80127, 101.0, 100.0, 100.5, 100.1875, 100.01172, 100.569336, 100.59958, 100.50122, 100.06665, 100.25, 100.31543, 100.47949, 100.94539, 101.0, 100.47705, 100.75, 100.72206, 100.59912, 100.5, 100.796875, 100.44531, 100.44629, 100.42285, 100.0, 100.0, 100.802734, 101.0, 100.25, 100.75, 100.0, 100.13281, ]; let common_values = &[ (100.0, 108217), (101.0, 98713), (100.5, 90150), (100.75, 40946), (100.25, 40858), (100.875, 18753), (100.125, 18677), (100.625, 18429), (100.375, 18424), (100.1875, 8582), (100.6875, 8505), (100.5625, 8500), (100.8125, 8480), (100.9375, 8342), (100.4375, 8341), (100.0625, 8329), (100.3125, 8269), (100.90625, 3936), (100.28125, 3920), (100.21875, 3910), ]; let sample_median = (100.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.49535768898696), standard_deviation: NiceFloat(0.32868306867221864), skewness: NiceFloat(0.008975981158852992), excess_kurtosis: NiceFloat(-1.221929691547448), }; special_random_primitive_float_inclusive_range_helper::( 100.0, 101.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0e38, b = Infinity, mean abs of exponent = 129, mean precision = 2, mean zero P = // 1/10 let values = &[ 2.5521178e38, 1.0633824e38, 1.0633824e38, f32::INFINITY, 1.2760589e38, 1.7014118e38, 1.2349359e38, 1.7014118e38, 1.0633824e38, 1.4887354e38, 1.0633824e38, 1.1697206e38, 1.329228e38, f32::INFINITY, 1.3026434e38, 1.2760589e38, 1.2760589e38, f32::INFINITY, 1.4887354e38, 1.7014118e38, 1.5419045e38, 2.5521178e38, 2.5521178e38, 3.2964854e38, 1.7014118e38, 1.0633824e38, 1.2760589e38, 1.2228898e38, 1.3823971e38, f32::INFINITY, 1.1763668e38, 1.2760589e38, f32::INFINITY, 1.5950736e38, 1.4887354e38, 1.2760589e38, 2.9774707e38, 2.179934e38, 2.3394413e38, 2.5521178e38, 2.1267648e38, 2.9774707e38, 1.0633824e38, 1.7014118e38, 1.7014118e38, 1.2760589e38, f32::INFINITY, 1.5809505e38, 1.1697206e38, 2.7647942e38, ]; let common_values = &[ (1.2760589e38, 171851), (1.7014118e38, 128688), (f32::INFINITY, 100224), (2.5521178e38, 85928), (1.4887354e38, 57285), (1.0633824e38, 57158), (2.9774707e38, 28779), (2.1267648e38, 28453), (1.1697206e38, 25497), (1.3823971e38, 25299), (1.5950736e38, 25002), (2.3394413e38, 9529), (1.9140883e38, 9502), (3.1901472e38, 9420), (2.7647942e38, 9406), (1.1165515e38, 7388), (1.329228e38, 7368), (1.2228898e38, 7328), (1.4355662e38, 7281), (1.6482427e38, 7214), ]; let sample_median = (1.6482427e38, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( 1.0e38, f32::INFINITY, 129, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = f32::MIN_POSITIVE_SUBNORMAL, mean abs of exponent // = 150, mean precision = 2, mean zero P = 1/10 let values = &[ 1.0e-45, 1.0e-45, 1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, 1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, -0.0, -1.0e-45, -1.0e-45, 0.0, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, 0.0, -1.0e-45, 1.0e-45, 1.0e-45, ]; let common_values = &[(1.0e-45, 450531), (-1.0e-45, 449245), (-0.0, 50351), (0.0, 49873)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8020698251216835e-48), standard_deviation: NiceFloat(1.3292224464360085e-45), skewness: NiceFloat(-0.0025604536978191587), excess_kurtosis: NiceFloat(-1.8886053342505447), }; special_random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = f32::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 150, mean precision = // 2, mean zero P = 1/10 let values = &[ 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, ]; let common_values = &[(1.0e-45, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.2608547270363571e-45), standard_deviation: NiceFloat(4.2080794564999146e-46), skewness: NiceFloat(-2.662524701673921), excess_kurtosis: NiceFloat(5.089037787023615), }; special_random_primitive_float_inclusive_range_helper::( -0.0, f32::MIN_POSITIVE_SUBNORMAL, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 0.0, b = 0.0, mean abs of exponent = 150, mean precision = 2, mean zero P = 1/10 let values = &[0.0; 50]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( 0.0, 0.0, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // -f32::MIN_POSITIVE_SUBNORMAL, b = -f32::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 150, // mean precision = 2, mean zero P = 1/10 let values = &[-1.0e-45; 50]; let common_values = &[(-1.0e-45, 1000000)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.401298464324817e-45), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -f32::MIN_POSITIVE_SUBNORMAL, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = 0.0, mean abs of exponent = 150, mean precision = // 2, mean zero P = 1/10 let values = &[ -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, ]; let common_values = &[(-1.0e-45, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.2608547270363571e-45), standard_deviation: NiceFloat(4.2080794564999146e-46), skewness: NiceFloat(2.662524701673921), excess_kurtosis: NiceFloat(5.089037787023615), }; special_random_primitive_float_inclusive_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 0.0, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -Infinity, b = Infinity, mean abs of exponent = 1, mean precision = 2, mean zero P = // 1/10 let values = &[ 12.0, 1.5, 0.75, -0.0, -12.0, -1.5, -0.75, -4.0, 4.0, 2.0, -2.0, -1.2041016, -2.0, f32::NEGATIVE_INFINITY, -0.75, -0.75, -3.0, 0.0, 1.2041016, -40.0, -0.6875, 2.0, 0.75, 0.75, -1.3125, 3.0, -2.0, 40.0, 0.6875, -0.0, -0.5, -1.5, f32::NEGATIVE_INFINITY, 1.3125, -0.125, -1.125, -0.046875, 2.0, -1.5, -1.9375, -1.0, 0.5, -0.75, 1.5, -1.0, 0.125, f32::INFINITY, -1.875, 1.125, 0.046875, ]; let common_values = &[ (1.0, 49888), (-1.0, 49745), (1.5, 33700), (-1.5, 33609), (f32::NEGATIVE_INFINITY, 25322), (0.5, 25189), (-0.0, 25144), (-0.5, 25121), (f32::INFINITY, 24924), (0.0, 24834), (2.0, 24770), (-2.0, 24716), (3.0, 16990), (-3.0, 16941), (0.75, 16655), (-0.75, 16611), (4.0, 12510), (0.25, 12465), (-4.0, 12461), (-0.25, 12430), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = -0.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[-0.0; 50]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -0.0, -0.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 2.0, 2.0, 2.0, 1.0, 1.5, 2.0, 1.0, 1.0, 1.5, 2.0, 1.28125, 1.0, 2.0, 1.0, 1.4375, 1.8125, 1.6875, 1.0, 1.75, 1.875, 2.0, 1.0, 2.0, 1.0, 1.75, 2.0, 2.0, 2.0, 2.0, 1.75, 2.0, 1.5, 1.484375, 2.0, 1.0, 2.0, 1.75, 2.0, 1.25, 1.0, 1.5, 1.25, 1.546875, 1.0, 2.0, 2.0, 2.0, 1.4921875, 2.0, 2.0, ]; let common_values = &[ (2.0, 332566), (1.0, 222394), (1.5, 148417), (1.75, 49426), (1.25, 49385), (1.375, 16729), (1.625, 16608), (1.125, 16560), (1.875, 16529), (1.8125, 5619), (1.5625, 5582), (1.6875, 5424), (1.9375, 5418), (1.4375, 5415), (1.0625, 5401), (1.3125, 5359), (1.1875, 5325), (1.09375, 1909), (1.65625, 1901), (1.96875, 1893), ]; let sample_median = (1.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5552951797578527), standard_deviation: NiceFloat(0.39732291679015563), skewness: NiceFloat(-0.2001600069371136), excess_kurtosis: NiceFloat(-1.5071515332005163), }; special_random_primitive_float_inclusive_range_helper::( 1.0, 2.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.0, 2.0, 1.0, 1.640625, 1.375, 2.0, 1.90625, 2.0, 2.0, 1.25, 1.0, 2.0, 2.0, 1.9375, 1.5, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1.96875, 2.0, 1.14794921875, 1.4569854736328125, 1.2559814453125, 1.5579833984375, 2.0, 2.0, 1.22509765625, 1.0812369697232498, 1.5, 2.0, 1.1291658878326416, 2.0, 1.666259765625, 2.0, 2.0, 2.0, 1.03857421875, 2.0, 2.0, 2.0, 2.0, 1.5, 1.125, 2.0, 1.0, 1.4247607216238976, ]; let common_values = &[ (2.0, 476330), (1.0, 47627), (1.5, 43214), (1.75, 19860), (1.25, 19849), (1.875, 9069), (1.625, 9023), (1.125, 8975), (1.375, 8966), (1.5625, 4216), (1.4375, 4204), (1.3125, 4172), (1.1875, 4093), (1.9375, 4059), (1.8125, 4047), (1.6875, 4030), (1.0625, 4007), (1.09375, 1944), (1.28125, 1938), (1.53125, 1903), ]; let sample_median = (1.9375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.714502436478215), standard_deviation: NiceFloat(0.34632959887726134), skewness: NiceFloat(-0.804949565136136), excess_kurtosis: NiceFloat(-0.8346071411985774), }; special_random_primitive_float_inclusive_range_helper::( 1.0, 2.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1, mean abs of exponent = 5, mean precision = 2, mean zero P = 1/10 let values = &[ 0.09375, 0.01171875, 0.01171875, -0.0, -0.09375, -0.01171875, -0.01171875, -0.03125, 0.03125, 0.0625, -0.0625, -0.07525634765625, -0.0625, 0.0, -0.09375, -0.09375, -0.09375, -0.0, 0.07525634765625, -0.078125, -0.05078125, 0.0625, 0.09375, 0.09375, -0.0244140625, 0.09375, -0.001953125, 0.078125, 0.05078125, -0.0, -0.0625, -0.09375, 0.0, 0.0244140625, -0.03125, -0.00439453125, -0.09375, 0.001953125, -0.09375, -0.0035400390625, -0.03125, 0.0625, -0.046875, 0.09375, -0.0625, 0.03125, 0.0, -0.0146484375, 0.00439453125, 0.09375, ]; let common_values = &[ (0.0625, 74957), (-0.0625, 74731), (-0.0, 50351), (0.09375, 50307), (-0.09375, 50176), (0.0, 49873), (0.03125, 37778), (-0.03125, 37674), (0.078125, 33218), (-0.078125, 33137), (0.046875, 25128), (-0.046875, 25051), (0.015625, 18742), (-0.015625, 18691), (0.0234375, 12592), (-0.0234375, 12548), (0.0859375, 11149), (-0.0859375, 11121), (0.0703125, 11027), (-0.0703125, 10991), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.00006747896492481727), standard_deviation: NiceFloat(0.05672798899804289), skewness: NiceFloat(-0.001703150825150012), excess_kurtosis: NiceFloat(-1.1100263487007116), }; special_random_primitive_float_inclusive_range_helper::( -0.1, 0.1, 5, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.005245480002486147, 0.0625, 0.00037892110412940383, -0.005245480002486147, -0.0625, -0.00037892110412940383, -0.0025482177734375, 0.0025482177734375, 0.08385447226464748, -0.08385447226464748, -0.07456207275390625, -0.076171875, -0.000156402587890625, -0.0004252493381500244, -0.0029296875, 0.07456207275390625, -0.012820055672818853, -0.05615234375, 0.076171875, 0.000156402587890625, 0.0004252493381500244, -6.198883056640625e-6, 0.0029296875, -0.00057220458984375, 0.012820055672818853, 0.05615234375, -0.0003814697265625, -0.0625, 6.198883056640625e-6, -0.00092315673828125, -0.00030517578125, -0.00007461127825081348, 0.00057220458984375, -0.0029296875, -0.05444455146789551, -0.009765625, 0.0003814697265625, -0.0007852371782064438, 0.0625, -0.07266771433324948, 0.00092315673828125, -0.02317537716589868, 0.00030517578125, 0.00007461127825081348, 0.0029296875, 0.05444455146789551, -0.007110595703125, -0.00537109375, -0.0072021484375, -2.2798776626586914e-6, ]; let common_values = &[ (0.0625, 6407), (-0.0625, 6393), (0.09375, 5870), (-0.09375, 5858), (0.03125, 5626), (-0.03125, 5611), (0.078125, 5277), (-0.078125, 5260), (-0.0, 5098), (0.046875, 4988), (-0.046875, 4978), (0.0, 4891), (0.015625, 4680), (-0.015625, 4672), (0.0234375, 4384), (-0.0234375, 4374), (0.0078125, 4263), (-0.0078125, 4260), (0.01171875, 3729), (-0.01171875, 3726), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000022298181036079024), standard_deviation: NiceFloat(0.035440202565071834), skewness: NiceFloat(0.00030138197742575316), excess_kurtosis: NiceFloat(1.5712669731678002), }; special_random_primitive_float_inclusive_range_helper::( -0.1, 0.1, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π, mean abs of exponent = 3, mean precision = 2, mean zero P = 1/10 let values = &[ 3.0, 2.859375, 3.0234375, 3.0, 2.75, 3.0, 3.0, 3.0, 2.75, 2.75, 3.078125, 3.0, 3.0, 3.0, 2.84375, 2.84375, 2.96875, 3.0, 3.125, 2.8125, 3.0, 3.0, 3.03125, 3.0, 3.125, 3.125, 2.875, 3.0, 2.75, 2.875, 3.0, 2.75, 2.9140625, 2.734375, 3.0, 3.0, 3.125, 2.92578125, 3.125, 3.0, 2.75, 3.125, 2.9921875, 3.0, 2.75, 3.0, 3.0, 3.01953125, 3.0, 2.8125, ]; let common_values = &[ (3.0, 333198), (2.75, 222142), (3.125, 74385), (2.875, 73751), (2.9375, 33356), (2.8125, 33246), (3.0625, 32891), (3.03125, 9479), (2.71875, 9381), (2.84375, 9352), (2.90625, 9344), (2.78125, 9342), (2.96875, 9313), (3.09375, 9258), (2.765625, 3221), (2.921875, 3214), (3.015625, 3204), (3.046875, 3175), (2.859375, 3165), (2.734375, 3163), ]; let sample_median = (3.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9232526079986494), standard_deviation: NiceFloat(0.1262248827883599), skewness: NiceFloat(-0.17691898540367232), excess_kurtosis: NiceFloat(-1.2742881322265622), }; special_random_primitive_float_inclusive_range_helper::( core::f64::consts::E, core::f64::consts::PI, 3, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.923828125, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462657928466797, 3.140625, 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.021484375, 2.97064208984375, 3.0179443359375, 2.9688720703125, 2.75, 2.97635555267334, 2.875, 2.890625, 2.8388671875, 2.781494140625, 3.0876541137695312, 3.10650634765625, 2.81756591796875, 2.8125, 2.774658203125, 2.746337890625, 3.086890615457378, 2.75, 2.7857666015625, 2.9739707708358765, 2.7529093623161316, 2.7723388671875, 3.125, 2.94140625, 2.916015625, 2.776611328125, 2.823486328125, 3.0, 3.0, 3.135541538707912, 2.75, 3.0625, 2.734408974647522, 3.0, 2.789327871054411, ]; let common_values = &[ (3.0, 91105), (2.75, 83336), (2.875, 38014), (3.125, 37964), (3.0625, 23196), (2.9375, 22929), (2.8125, 22922), (3.09375, 9177), (2.78125, 9003), (2.84375, 8943), (2.90625, 8936), (2.71875, 8920), (3.03125, 8913), (2.96875, 8854), (2.765625, 4212), (2.859375, 4171), (2.953125, 4126), (2.890625, 4119), (3.015625, 4090), (2.984375, 4082), ]; let sample_median = (2.9375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9261256924208183), standard_deviation: NiceFloat(0.12519730680807895), skewness: NiceFloat(-0.016892719700380622), excess_kurtosis: NiceFloat(-1.2338524787684633), }; special_random_primitive_float_inclusive_range_helper::( core::f64::consts::E, core::f64::consts::PI, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0, mean abs of exponent = 7, mean precision = 2, mean zero P = 1/10 let values = &[ 100.0, 100.5625, 100.40625, 100.0, 101.0, 100.0, 100.0, 100.0, 101.0, 101.0, 100.8125, 100.0, 100.0, 100.0, 100.375, 100.875, 100.875, 100.0, 100.5, 100.75, 100.0, 100.0, 100.875, 100.0, 100.5, 100.5, 100.5, 100.0, 101.0, 100.5, 100.0, 101.0, 100.46875, 100.1875, 100.0, 100.0, 100.5, 100.546875, 100.5, 100.0, 101.0, 100.5, 100.96875, 100.0, 101.0, 100.0, 100.0, 100.296875, 100.0, 100.75, ]; let common_values = &[ (100.0, 333198), (101.0, 222142), (100.5, 148136), (100.75, 49930), (100.25, 49563), (100.375, 16456), (100.875, 16346), (100.625, 16343), (100.125, 16324), (100.6875, 5638), (100.5625, 5588), (100.1875, 5508), (100.8125, 5478), (100.4375, 5449), (100.3125, 5420), (100.9375, 5417), (100.0625, 5309), (100.71875, 1910), (100.21875, 1891), (100.09375, 1867), ]; let sample_median = (100.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.44459040083368), standard_deviation: NiceFloat(0.39739652839770573), skewness: NiceFloat(0.20000867844534617), excess_kurtosis: NiceFloat(-1.5079346005477923), }; special_random_primitive_float_inclusive_range_helper::( 100.0, 101.0, 7, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0, mean abs of exponent = 10, mean precision = 10, mean zero P = // 1/100 let values = &[ 100.8203125, 100.5625, 100.0, 100.71875, 100.75, 100.5, 100.9375, 100.88426971435547, 100.9375, 100.5, 100.0, 101.0, 100.0, 100.125, 101.0, 100.4609375, 100.511962890625, 100.46337890625, 100.80126953125, 101.0, 100.27350997924805, 100.5, 100.8125, 100.37109375, 100.3251953125, 100.13284301757812, 100.032470703125, 100.916748046875, 100.75, 100.0087890625, 100.2373046875, 100.59933795747929, 101.0, 100.89990234375, 100.71137285232544, 100.55885925889015, 100.15478515625, 100.5, 100.421875, 100.3671875, 100.8330078125, 100.9619140625, 100.0, 100.0, 100.72769894078374, 101.0, 100.25, 100.2837815284729, 100.0, 100.6954902857542, ]; let common_values = &[ (100.0, 91387), (101.0, 83529), (100.5, 76188), (100.25, 34644), (100.75, 34560), (100.375, 15817), (100.875, 15798), (100.125, 15698), (100.625, 15638), (100.6875, 7188), (100.9375, 7169), (100.5625, 7154), (100.1875, 7093), (100.0625, 7081), (100.3125, 7073), (100.8125, 7055), (100.4375, 6967), (100.34375, 3371), (100.59375, 3321), (100.21875, 3291), ]; let sample_median = (100.5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.49597550384374), standard_deviation: NiceFloat(0.3229907369466344), skewness: NiceFloat(0.007882298769431025), excess_kurtosis: NiceFloat(-1.2073173945999414), }; special_random_primitive_float_inclusive_range_helper::( 100.0, 101.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0e38, b = Infinity, mean abs of exponent = 129, mean precision = 2, mean zero P = // 1/10 let values = &[ 4.0833884030512616e39, 1.0633823966279327e38, 1.0633823966279327e38, f64::INFINITY, 1.2760588759535192e38, 2.722258935367508e39, 2.1121432853022313e39, 1.0889035741470031e40, 3.2667107224410092e40, 1.0633823966279327e38, 1.0633823966279327e38, 1.3823971156163125e38, 3.828176627860558e38, f64::INFINITY, 1.3026434358692176e38, 3.402823669209385e38, 1.361129467683754e39, f64::INFINITY, 2.0416942015256308e39, 6.80564733841877e38, 1.5419044751105024e38, 4.0833884030512616e39, 2.5521177519070385e38, 1.1484529883581673e39, 1.7014118346046923e38, 1.4887353552791058e38, 1.361129467683754e39, 6.380294379767596e38, 4.253529586511731e38, f64::INFINITY, 4.519375185668714e38, 3.402823669209385e38, f64::INFINITY, 1.3823971156163125e38, 3.2667107224410092e40, 3.48449143727041e41, 2.9774707105582116e38, 7.443676776395529e38, 3.190147189883798e38, 2.5521177519070385e38, 1.9055812547572554e40, 3.4028236692093846e39, 1.0633823966279327e38, 6.80564733841877e38, 1.7014118346046923e38, 1.2760588759535192e38, f64::INFINITY, 1.4879045877817402e38, 1.595073594941899e38, 8.166776806102523e40, ]; let common_values = &[ (f64::INFINITY, 100224), (1.2760588759535192e38, 74870), (1.7014118346046923e38, 56023), (3.402823669209385e38, 42298), (2.5521177519070385e38, 37662), (6.80564733841877e38, 31926), (5.104235503814077e38, 28139), (1.0633823966279327e38, 25142), (1.4887353552791058e38, 25038), (1.361129467683754e39, 23671), (1.0208471007628154e39, 21048), (2.722258935367508e39, 17641), (2.0416942015256308e39, 15983), (5.444517870735016e39, 13496), (2.1267647932558654e38, 12408), (2.9774707105582116e38, 12336), (4.0833884030512616e39, 11938), (1.169720636290726e38, 11049), (1.595073594941899e38, 10950), (1.3823971156163125e38, 10907), ]; let sample_median = (5.84860318145363e38, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( 1.0e38, f64::INFINITY, 129, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = f64::MIN_POSITIVE_SUBNORMAL, mean abs of exponent // = 1075, mean precision = 2, mean zero P = 1/10 let values = &[ 5.0e-324, 5.0e-324, 5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, 5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, -0.0, -5.0e-324, -5.0e-324, 0.0, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, 0.0, -5.0e-324, 5.0e-324, 5.0e-324, ]; let common_values = &[(5.0e-324, 450531), (-5.0e-324, 449245), (-0.0, 50351), (0.0, 49873)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = f64::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 1075, mean precision = // 2, mean zero P = 1/10 let values = &[ 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, ]; let common_values = &[(5.0e-324, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -0.0, f64::MIN_POSITIVE_SUBNORMAL, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 0.0, b = 0.0, mean abs of exponent = 1075, mean precision = 2, mean zero P = 1/10 let values = &[0.0; 50]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( 0.0, 0.0, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // -f64::MIN_POSITIVE_SUBNORMAL, b = -f64::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 1075, // mean precision = 2, mean zero P = 1/10 let values = &[-5.0e-324; 50]; let common_values = &[(-5.0e-324, 1000000)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -f64::MIN_POSITIVE_SUBNORMAL, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = 0.0, mean abs of exponent = 1075, mean precision = // 2, mean zero P = 1/10 let values = &[ -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, ]; let common_values = &[(-5.0e-324, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 0.0, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -Infinity, b = Infinity, mean abs of exponent = 1, mean precision = 2, mean zero P = // 1/10 let values = &[ 12.0, 1.5, 0.75, -0.0, -12.0, -1.5, -0.75, -4.0, 4.0, 2.0, -2.0, -1.2041015625, -2.0, f64::NEGATIVE_INFINITY, -0.75, -0.75, -3.0, 0.0, 1.2041015625, -40.0, -0.6875, 2.0, 0.75, 0.75, -1.3125, 3.0, -2.0, 40.0, 0.6875, -0.0, -0.5, -1.5, f64::NEGATIVE_INFINITY, 1.3125, -0.125, -1.125, -0.046875, 2.0, -1.5, -1.9375, -1.0, 0.5, -0.75, 1.5, -1.0, 0.125, f64::INFINITY, -1.875, 1.125, 0.046875, ]; let common_values = &[ (1.0, 49883), (-1.0, 49740), (1.5, 33699), (-1.5, 33608), (f64::NEGATIVE_INFINITY, 25322), (0.5, 25188), (-0.0, 25144), (-0.5, 25120), (f64::INFINITY, 24924), (0.0, 24834), (2.0, 24765), (-2.0, 24711), (3.0, 16988), (-3.0, 16939), (0.75, 16654), (-0.75, 16610), (4.0, 12510), (0.25, 12465), (-4.0, 12461), (-0.25, 12430), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = -0.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[-0.0; 50]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_inclusive_range_helper::( -0.0, -0.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_primitive_float_inclusive_range_fail_helper() { assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::ZERO, 1, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::NAN, 1, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 0, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 0, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::from(100.0), T::from(101.0), 6, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 1, 2, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 1, 0, 1, 10 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 2, 1, 2, 1 )); assert_panic!(special_random_primitive_float_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 2, 1, 1, 0 )); } #[test] fn special_random_primitive_float_inclusive_range_fail() { apply_fn_to_primitive_floats!(special_random_primitive_float_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_primitive_float_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::special_random_primitive_float_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats}; use std::panic::catch_unwind; fn special_random_primitive_float_range_helper( a: T, b: T, mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_primitive_float_range::( EXAMPLE_SEED, a, b, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_primitive_float_range() { // f32, a = 1.0, b = 2.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 1.0, 1.28125, 1.609375, 1.0, 1.5, 1.0, 1.0, 1.0, 1.5, 1.5, 1.71875, 1.0, 1.0, 1.0, 1.9375, 1.9375, 1.9375, 1.0, 1.25, 1.375, 1.0, 1.0, 1.3125, 1.0, 1.25, 1.25, 1.75, 1.0, 1.5, 1.75, 1.0, 1.5, 1.484375, 1.65625, 1.0, 1.0, 1.75, 1.5234375, 1.75, 1.0, 1.5, 1.25, 1.515625, 1.0, 1.5, 1.0, 1.0, 1.4140625, 1.0, 1.875, ]; let common_values = &[ (1.0, 333222), (1.5, 222154), (1.75, 74130), (1.25, 74019), (1.375, 25091), (1.875, 24869), (1.625, 24805), (1.125, 24731), (1.4375, 8353), (1.8125, 8307), (1.5625, 8208), (1.6875, 8156), (1.0625, 8145), (1.3125, 8117), (1.1875, 8108), (1.9375, 8080), (1.03125, 2799), (1.96875, 2798), (1.15625, 2785), (1.28125, 2779), ]; let sample_median = (1.3359375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.3333245906621964), standard_deviation: NiceFloat(0.29800120914228473), skewness: NiceFloat(0.27868047434467813), excess_kurtosis: NiceFloat(-1.2068148586621514), }; special_random_primitive_float_range_helper::( 1.0, 2.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0, b = 2.0, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 1.4101562, 1.90625, 1.0, 1.953125, 1.875, 1.75, 1.46875, 1.3115959, 1.46875, 1.25, 1.0, 1.5, 1.0, 1.5625, 1.5, 1.5117188, 1.1158447, 1.2253418, 1.1882324, 1.5, 1.1991673, 1.75, 1.15625, 1.2519531, 1.0668945, 1.6660919, 1.0096436, 1.2796631, 1.875, 1.6987305, 1.8608398, 1.3996582, 1.5, 1.1125488, 1.419461, 1.25, 1.0681152, 1.75, 1.1171875, 1.4804688, 1.7055664, 1.3237305, 1.0, 1.0, 1.84375, 1.5, 1.125, 1.3097513, 1.0, 1.375, ]; let common_values = &[ (1.0, 100845), (1.5, 91973), (1.75, 42129), (1.25, 41726), (1.125, 19270), (1.625, 19149), (1.875, 19012), (1.375, 18836), (1.8125, 8852), (1.1875, 8822), (1.3125, 8722), (1.0625, 8692), (1.4375, 8630), (1.6875, 8623), (1.9375, 8620), (1.5625, 8431), (1.71875, 4047), (1.09375, 3974), (1.40625, 3949), (1.90625, 3941), ]; let sample_median = (1.4912109, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.449574181673412), standard_deviation: NiceFloat(0.29612085814559613), skewness: NiceFloat(0.029341331332504897), excess_kurtosis: NiceFloat(-1.1487737412063284), }; special_random_primitive_float_range_helper::( 1.0, 2.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1, mean abs of exponent = 5, mean precision = 2, mean zero P = 1/10 let values = &[ 0.09375, 0.01171875, 0.01171875, -0.0, -0.09375, -0.01171875, -0.01171875, -0.03125, 0.03125, 0.0625, -0.0625, -0.07525635, -0.0625, 0.0, -0.09375, -0.09375, -0.09375, -0.0, 0.07525635, -0.078125, -0.05078125, 0.0625, 0.09375, 0.09375, -0.024414062, 0.09375, -0.001953125, 0.078125, 0.05078125, -0.0, -0.0625, -0.09375, 0.0, 0.024414062, -0.03125, -0.0043945312, -0.09375, 0.001953125, -0.09375, -0.003540039, -0.03125, 0.0625, -0.046875, 0.09375, -0.0625, 0.03125, 0.0, -0.0146484375, 0.0043945312, 0.09375, ]; let common_values = &[ (0.0625, 74962), (-0.0625, 74736), (-0.0, 50351), (0.09375, 50309), (-0.09375, 50178), (0.0, 49873), (0.03125, 37782), (-0.03125, 37678), (0.078125, 33219), (-0.078125, 33138), (0.046875, 25130), (-0.046875, 25053), (0.015625, 18743), (-0.015625, 18692), (0.0234375, 12593), (-0.0234375, 12549), (0.0703125, 11091), (0.0859375, 11088), (-0.0859375, 11060), (-0.0703125, 11055), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0000674789649248169), standard_deviation: NiceFloat(0.05672019953597066), skewness: NiceFloat(-0.001702872258409426), excess_kurtosis: NiceFloat(-1.109977309372344), }; special_random_primitive_float_range_helper::( -0.1, 0.1, 5, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.1, b = 0.1, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.0041503906, 0.0625, 0.00042547443, -0.0041503906, -0.0625, -0.00042547443, -0.0027618408, 0.0027618408, 0.09375, -0.09375, -0.083244324, -0.076171875, -0.00023269653, -0.00043609738, -0.0029296875, 0.083244324, -0.011459351, -0.05419922, 0.076171875, 0.00023269653, 0.00043609738, -0.000006198883, 0.0029296875, -0.0008621216, 0.011459351, 0.05419922, -0.00035095215, -0.0625, 0.000006198883, -0.0008010864, -0.00030517578, -0.00008274312, 0.0008621216, -0.0029296875, -0.04892564, -0.013671875, 0.00035095215, -0.0009398293, 0.0625, -0.07344723, 0.0008010864, -0.01953125, 0.00030517578, 0.00008274312, 0.0029296875, 0.04892564, -0.006134033, -0.0070343018, -0.005493164, -0.0000029057264, ]; let common_values = &[ (0.0625, 7060), (-0.0625, 7045), (0.09375, 6481), (-0.09375, 6468), (0.03125, 6186), (-0.03125, 6171), (0.078125, 5831), (-0.078125, 5813), (0.046875, 5527), (-0.046875, 5516), (0.015625, 5112), (-0.015625, 5103), (-0.0, 5098), (0.0, 4891), (0.0234375, 4821), (-0.0234375, 4810), (0.0078125, 4681), (-0.0078125, 4678), (0.01171875, 4123), (-0.01171875, 4120), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000022248151599295377), standard_deviation: NiceFloat(0.035382441406785786), skewness: NiceFloat(0.0002929225243710825), excess_kurtosis: NiceFloat(1.5823949638933827), }; special_random_primitive_float_range_helper::( -0.1, 0.1, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π, mean abs of exponent = 3, mean precision = 2, mean zero P = 1/10 let values = &[ 3.0, 2.859375, 3.0234375, 3.0, 2.75, 3.0, 3.0, 3.0, 2.75, 2.75, 3.078125, 3.0, 3.0, 3.0, 2.84375, 2.84375, 2.96875, 3.0, 3.125, 2.8125, 3.0, 3.0, 3.03125, 3.0, 3.125, 3.125, 2.875, 3.0, 2.75, 2.875, 3.0, 2.75, 2.9140625, 2.734375, 3.0, 3.0, 3.125, 2.9257812, 3.125, 3.0, 2.75, 3.125, 2.9921875, 3.0, 2.75, 3.0, 3.0, 3.0195312, 3.0, 2.8125, ]; let common_values = &[ (3.0, 333251), (2.75, 222162), (3.125, 74149), (2.875, 74011), (3.0625, 33262), (2.8125, 33146), (2.9375, 33097), (2.90625, 9548), (2.78125, 9377), (2.71875, 9327), (3.03125, 9327), (3.09375, 9323), (2.84375, 9315), (2.96875, 9265), (2.859375, 3186), (3.015625, 3185), (2.796875, 3180), (3.046875, 3160), (3.140625, 3157), (2.765625, 3152), ]; let sample_median = (3.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.923236772231216), standard_deviation: NiceFloat(0.12616339323242115), skewness: NiceFloat(-0.17689588042510748), excess_kurtosis: NiceFloat(-1.2738593390011854), }; special_random_primitive_float_range_helper::( core::f32::consts::E, core::f32::consts::PI, 3, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = e, b = π, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.9238281, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462658, 3.140625, 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.0214844, 2.970642, 3.0179443, 2.968872, 2.75, 2.9763536, 2.875, 2.890625, 2.8388672, 2.7814941, 3.087654, 3.1065063, 2.817566, 2.8125, 2.7746582, 2.746338, 3.0207214, 2.75, 2.9852295, 3.0, 2.9980469, 3.006958, 2.875, 2.8632812, 2.9277344, 3.088623, 2.8376465, 3.0, 3.0, 3.0117188, 2.75, 2.8125, 3.0, 3.0, 3.140625, ]; let common_values = &[ (3.0, 103073), (2.75, 94168), (2.875, 43152), (3.125, 42886), (3.0625, 26213), (2.8125, 25982), (2.9375, 25799), (2.90625, 10203), (2.71875, 10186), (2.84375, 10149), (3.09375, 10141), (3.03125, 10134), (2.78125, 10085), (2.96875, 10085), (3.046875, 4666), (2.734375, 4649), (2.765625, 4649), (3.109375, 4629), (2.859375, 4606), (3.140625, 4590), ]; let sample_median = (2.9375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.925577550306893), standard_deviation: NiceFloat(0.12565616542944752), skewness: NiceFloat(-0.016691773531483878), excess_kurtosis: NiceFloat(-1.2405888218124512), }; special_random_primitive_float_range_helper::( core::f32::consts::E, core::f32::consts::PI, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0, mean abs of exponent = 7, mean precision = 2, mean zero P = 1/10 let values = &[ 100.0, 100.28125, 100.609375, 100.0, 100.5, 100.0, 100.0, 100.0, 100.5, 100.5, 100.71875, 100.0, 100.0, 100.0, 100.9375, 100.9375, 100.9375, 100.0, 100.25, 100.375, 100.0, 100.0, 100.3125, 100.0, 100.25, 100.25, 100.75, 100.0, 100.5, 100.75, 100.0, 100.5, 100.484375, 100.65625, 100.0, 100.0, 100.75, 100.52344, 100.75, 100.0, 100.5, 100.25, 100.515625, 100.0, 100.5, 100.0, 100.0, 100.41406, 100.0, 100.875, ]; let common_values = &[ (100.0, 333428), (100.5, 222283), (100.25, 74406), (100.75, 73829), (100.375, 25079), (100.625, 25046), (100.875, 24767), (100.125, 24656), (100.3125, 8323), (100.8125, 8256), (100.4375, 8240), (100.1875, 8213), (100.9375, 8177), (100.5625, 8174), (100.0625, 8080), (100.6875, 8059), (100.34375, 2831), (100.90625, 2811), (100.84375, 2797), (100.03125, 2781), ]; let sample_median = (100.33276, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.3331636999286), standard_deviation: NiceFloat(0.29794394613548436), skewness: NiceFloat(0.27963401436978874), excess_kurtosis: NiceFloat(-1.2056484413996), }; special_random_primitive_float_range_helper::( 100.0, 101.0, 7, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 100.0, b = 101.0, mean abs of exponent = 10, mean precision = 10, mean zero P = // 1/100 let values = &[ 100.41016, 100.90625, 100.0, 100.953125, 100.875, 100.75, 100.46875, 100.0, 100.59375, 100.25, 100.0, 100.5, 100.0, 100.5625, 100.5, 100.24609, 100.3822, 100.41431, 100.40991, 100.5, 100.5, 100.25, 100.46875, 100.009766, 100.78467, 100.64989, 100.06262, 100.12927, 100.125, 100.833496, 100.01904, 100.0, 100.5, 100.11841, 100.6875, 100.75, 100.849365, 100.25, 100.44531, 100.58984, 100.3999, 100.13916, 100.0, 100.0, 100.382324, 100.5, 100.875, 100.3125, 100.0, 100.70117, ]; let common_values = &[ (100.0, 110530), (100.5, 100839), (100.75, 45914), (100.25, 45828), (100.625, 20971), (100.875, 20919), (100.125, 20849), (100.375, 20809), (100.8125, 9612), (100.3125, 9504), (100.9375, 9489), (100.1875, 9482), (100.0625, 9475), (100.6875, 9471), (100.4375, 9432), (100.5625, 9376), (100.40625, 4413), (100.59375, 4409), (100.03125, 4369), (100.21875, 4315), ]; let sample_median = (100.48999, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.44491497797223), standard_deviation: NiceFloat(0.29627860462288247), skewness: NiceFloat(0.0334721390871067), excess_kurtosis: NiceFloat(-1.1467496174419634), }; special_random_primitive_float_range_helper::( 100.0, 101.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 1.0e38, b = Infinity, mean abs of exponent = 129, mean precision = 2, mean zero P = // 1/10 let values = &[ 1.7014118e38, 2.179934e38, 2.7382097e38, 1.2760589e38, 1.4887354e38, 1.2760589e38, 1.2760589e38, 1.2760589e38, 1.4887354e38, 1.0633824e38, 1.5020276e38, 1.7014118e38, 1.7014118e38, 1.7014118e38, 1.80775e38, 3.2964854e38, 3.2964854e38, 1.2760589e38, 1.1697206e38, 2.3394413e38, 1.2760589e38, 1.7014118e38, 1.4089817e38, 1.2760589e38, 2.1267648e38, 1.1697206e38, 1.1697206e38, 1.7014118e38, 2.5521178e38, 2.1267648e38, 1.7014118e38, 1.0633824e38, 2.2596876e38, 1.4754431e38, 1.2760589e38, 1.7014118e38, 2.1267648e38, 3.0705167e38, 2.9774707e38, 1.2760589e38, 1.0633824e38, 2.1267648e38, 1.0168594e38, 1.7014118e38, 2.5521178e38, 1.2760589e38, 1.2760589e38, 1.4654739e38, 1.7014118e38, 1.9140883e38, ]; let common_values = &[ (1.2760589e38, 190486), (1.7014118e38, 142730), (2.5521178e38, 95012), (1.4887354e38, 63724), (1.0633824e38, 63427), (2.1267648e38, 31749), (2.9774707e38, 31613), (1.3823971e38, 28489), (1.1697206e38, 28187), (1.5950736e38, 28108), (1.9140883e38, 10758), (3.1901472e38, 10750), (2.3394413e38, 10610), (2.7647942e38, 10493), (1.329228e38, 8248), (1.1165515e38, 8201), (1.5419045e38, 8177), (1.0102133e38, 8147), (1.4355662e38, 8096), (1.6482427e38, 8021), ]; let sample_median = (1.5286122e38, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.7213254069804385e38), standard_deviation: NiceFloat(5.915470456567596e37), skewness: NiceFloat(1.0016210709928859), excess_kurtosis: NiceFloat(-0.11636872848929292), }; special_random_primitive_float_range_helper::( 1.0e38, f32::INFINITY, 129, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = 3.0e-45, mean abs of exponent = 150, mean // precision = 2, mean zero P = 1/10 let values = &[ 1.0e-45, 1.0e-45, 1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, 1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, 1.0e-45, -0.0, -1.0e-45, -1.0e-45, 0.0, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, -1.0e-45, 1.0e-45, 0.0, -1.0e-45, 1.0e-45, 1.0e-45, ]; let common_values = &[(1.0e-45, 450531), (-1.0e-45, 449245), (-0.0, 50351), (0.0, 49873)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8020698251216835e-48), standard_deviation: NiceFloat(1.3292224464360085e-45), skewness: NiceFloat(-0.0025604536978191587), excess_kurtosis: NiceFloat(-1.8886053342505447), }; special_random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, 3.0e-45, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = 3.0e-45, mean abs of exponent = 150, mean precision = 2, mean zero P = // 1/10 let values = &[ 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, -0.0, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 1.0e-45, 0.0, 1.0e-45, 1.0e-45, 1.0e-45, ]; let common_values = &[(1.0e-45, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.2608547270363571e-45), standard_deviation: NiceFloat(4.2080794564999146e-46), skewness: NiceFloat(-2.662524701673921), excess_kurtosis: NiceFloat(5.089037787023615), }; special_random_primitive_float_range_helper::( -0.0, 3.0e-45, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = 0.0, b = f32::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 150, mean precision = // 2, mean zero P = 1/10 let values = &[0.0; 50]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( 0.0, f32::MIN_POSITIVE_SUBNORMAL, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // -f32::MIN_POSITIVE_SUBNORMAL, b = -0.0, mean abs of exponent = 150, mean precision = 2, mean // zero P = 1/10 let values = &[-1.0e-45; 50]; let common_values = &[(-1.0e-45, 1000000)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.401298464324817e-45), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, -0.0, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -f32::MIN_POSITIVE_SUBNORMAL, b = f32::MIN_POSITIVE_SUBNORMAL, mean abs of exponent // = 150, mean precision = 2, mean zero P = 1/10 let values = &[ -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -0.0, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, -1.0e-45, 0.0, -1.0e-45, -1.0e-45, -1.0e-45, ]; let common_values = &[(-1.0e-45, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (-1.0e-45, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.2608547270363571e-45), standard_deviation: NiceFloat(4.2080794564999146e-46), skewness: NiceFloat(2.662524701673921), excess_kurtosis: NiceFloat(5.089037787023615), }; special_random_primitive_float_range_helper::( -f32::MIN_POSITIVE_SUBNORMAL, f32::MIN_POSITIVE_SUBNORMAL, 150, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -Infinity, b = Infinity, mean abs of exponent = 1, mean precision = 2, mean zero P = // 1/10 let values = &[ 12.0, 1.5, 0.75, 0.0, -12.0, -1.5, -0.75, -4.0, 4.0, 2.0, -2.0, -1.2041016, -2.0, f32::NEGATIVE_INFINITY, -0.75, -0.75, -3.0, 0.0, 1.2041016, -40.0, -0.6875, 2.0, 0.75, 0.75, -1.3125, 3.0, -2.0, 40.0, 0.6875, f32::NEGATIVE_INFINITY, -0.5, -1.5, -0.0, 1.3125, -0.125, -1.125, -0.046875, 2.0, -1.5, -1.9375, -1.0, 0.5, -0.75, 1.5, -1.0, 0.125, 0.0, -1.875, 1.125, 0.046875, ]; let common_values = &[ (1.0, 49888), (-1.0, 49745), (1.5, 33700), (f32::NEGATIVE_INFINITY, 33640), (-1.5, 33609), (0.0, 33393), (-0.0, 33191), (0.5, 25189), (-0.5, 25121), (2.0, 24770), (-2.0, 24716), (3.0, 16990), (-3.0, 16941), (0.75, 16655), (-0.75, 16611), (4.0, 12510), (0.25, 12465), (-4.0, 12461), (-0.25, 12430), (1.75, 11179), ]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( f32::NEGATIVE_INFINITY, f32::INFINITY, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f32, a = -0.0, b = 0.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[-0.0; 50]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -0.0, 0.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[ 1.0, 1.28125, 1.609375, 1.0, 1.5, 1.0, 1.0, 1.0, 1.5, 1.5, 1.71875, 1.0, 1.0, 1.0, 1.9375, 1.9375, 1.9375, 1.0, 1.25, 1.375, 1.0, 1.0, 1.3125, 1.0, 1.25, 1.25, 1.75, 1.0, 1.5, 1.75, 1.0, 1.5, 1.484375, 1.65625, 1.0, 1.0, 1.75, 1.5234375, 1.75, 1.0, 1.5, 1.25, 1.515625, 1.0, 1.5, 1.0, 1.0, 1.4140625, 1.0, 1.875, ]; let common_values = &[ (1.0, 333198), (1.5, 222142), (1.25, 74116), (1.75, 74020), (1.625, 24916), (1.375, 24899), (1.875, 24889), (1.125, 24789), (1.8125, 8258), (1.0625, 8253), (1.9375, 8239), (1.5625, 8179), (1.6875, 8158), (1.1875, 8148), (1.4375, 8140), (1.3125, 8094), (1.40625, 2826), (1.84375, 2825), (1.34375, 2802), (1.78125, 2781), ]; let sample_median = (1.3359375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.3334110677410675), standard_deviation: NiceFloat(0.29815058562815744), skewness: NiceFloat(0.27918114410601663), excess_kurtosis: NiceFloat(-1.206767297925903), }; special_random_primitive_float_range_helper::( 1.0, 2.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0, b = 2.0, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 1.41015625, 1.90625, 1.0, 1.953125, 1.875, 1.75, 1.46875, 1.3115959167480469, 1.46875, 1.25, 1.0, 1.5, 1.0, 1.5625, 1.5, 1.51171875, 1.1158447265625, 1.225341796875, 1.188232421875, 1.5, 1.199167251586914, 1.75, 1.15625, 1.251953125, 1.06689453125, 1.6660919189453125, 1.0096435546875, 1.2796630859375, 1.875, 1.69873046875, 1.86083984375, 1.3819717407022836, 1.5, 1.802490234375, 1.909928560256958, 1.2957243919372559, 1.401123046875, 1.75, 1.3671875, 1.95703125, 1.14501953125, 1.59130859375, 1.0, 1.0, 1.825472442433238, 1.5, 1.375, 1.7292792797088623, 1.0, 1.852405808866024, ]; let common_values = &[ (1.0, 90973), (1.5, 83219), (1.75, 38074), (1.25, 37805), (1.875, 17372), (1.375, 17334), (1.625, 17115), (1.125, 17095), (1.3125, 7927), (1.6875, 7879), (1.4375, 7873), (1.5625, 7861), (1.9375, 7859), (1.8125, 7831), (1.1875, 7812), (1.0625, 7625), (1.84375, 3620), (1.34375, 3611), (1.28125, 3607), (1.15625, 3558), ]; let sample_median = (1.4921875, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.4546223996766015), standard_deviation: NiceFloat(0.29563414647088554), skewness: NiceFloat(0.02445210407687687), excess_kurtosis: NiceFloat(-1.1474911308258557), }; special_random_primitive_float_range_helper::( 1.0, 2.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1, mean abs of exponent = 5, mean precision = 2, mean zero P = 1/10 let values = &[ 0.09375, 0.01171875, 0.01171875, -0.0, -0.09375, -0.01171875, -0.01171875, -0.03125, 0.03125, 0.0625, -0.0625, -0.07525634765625, -0.0625, 0.0, -0.09375, -0.09375, -0.09375, -0.0, 0.07525634765625, -0.078125, -0.05078125, 0.0625, 0.09375, 0.09375, -0.0244140625, 0.09375, -0.001953125, 0.078125, 0.05078125, -0.0, -0.0625, -0.09375, 0.0, 0.0244140625, -0.03125, -0.00439453125, -0.09375, 0.001953125, -0.09375, -0.0035400390625, -0.03125, 0.0625, -0.046875, 0.09375, -0.0625, 0.03125, 0.0, -0.0146484375, 0.00439453125, 0.09375, ]; let common_values = &[ (0.0625, 74957), (-0.0625, 74731), (-0.0, 50351), (0.09375, 50307), (-0.09375, 50176), (0.0, 49873), (0.03125, 37778), (-0.03125, 37674), (0.078125, 33218), (-0.078125, 33137), (0.046875, 25128), (-0.046875, 25051), (0.015625, 18742), (-0.015625, 18691), (0.0234375, 12592), (-0.0234375, 12548), (0.0859375, 11149), (-0.0859375, 11121), (0.0703125, 11027), (-0.0703125, 10991), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.00006747896492481727), standard_deviation: NiceFloat(0.05672798899804289), skewness: NiceFloat(-0.001703150825150012), excess_kurtosis: NiceFloat(-1.1100263487007116), }; special_random_primitive_float_range_helper::( -0.1, 0.1, 5, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.1, b = 0.1, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 0.005245480002486147, 0.0625, 0.00037892110412940383, -0.005245480002486147, -0.0625, -0.00037892110412940383, -0.0025482177734375, 0.0025482177734375, 0.08385447226464748, -0.08385447226464748, -0.07456207275390625, -0.076171875, -0.000156402587890625, -0.0004252493381500244, -0.0029296875, 0.07456207275390625, -0.012820055672818853, -0.05615234375, 0.076171875, 0.000156402587890625, 0.0004252493381500244, -6.198883056640625e-6, 0.0029296875, -0.00057220458984375, 0.012820055672818853, 0.05615234375, -0.0003814697265625, -0.0625, 6.198883056640625e-6, -0.00092315673828125, -0.00030517578125, -0.00007461127825081348, 0.00057220458984375, -0.0029296875, -0.05444455146789551, -0.009765625, 0.0003814697265625, -0.0007852371782064438, 0.0625, -0.07266771433324948, 0.00092315673828125, -0.02317537716589868, 0.00030517578125, 0.00007461127825081348, 0.0029296875, 0.05444455146789551, -0.007110595703125, -0.00537109375, -0.0072021484375, -2.2798776626586914e-6, ]; let common_values = &[ (0.0625, 6407), (-0.0625, 6393), (0.09375, 5870), (-0.09375, 5858), (0.03125, 5626), (-0.03125, 5611), (0.078125, 5277), (-0.078125, 5260), (-0.0, 5098), (0.046875, 4988), (-0.046875, 4978), (0.0, 4891), (0.015625, 4680), (-0.015625, 4672), (0.0234375, 4384), (-0.0234375, 4374), (0.0078125, 4263), (-0.0078125, 4260), (0.01171875, 3729), (-0.01171875, 3726), ]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000022298181036079024), standard_deviation: NiceFloat(0.035440202565071834), skewness: NiceFloat(0.00030138197742575316), excess_kurtosis: NiceFloat(1.5712669731678002), }; special_random_primitive_float_range_helper::( -0.1, 0.1, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π, mean abs of exponent = 3, mean precision = 2, mean zero P = 1/10 let values = &[ 3.0, 2.859375, 3.0234375, 3.0, 2.75, 3.0, 3.0, 3.0, 2.75, 2.75, 3.078125, 3.0, 3.0, 3.0, 2.84375, 2.84375, 2.96875, 3.0, 3.125, 2.8125, 3.0, 3.0, 3.03125, 3.0, 3.125, 3.125, 2.875, 3.0, 2.75, 2.875, 3.0, 2.75, 2.9140625, 2.734375, 3.0, 3.0, 3.125, 2.92578125, 3.125, 3.0, 2.75, 3.125, 2.9921875, 3.0, 2.75, 3.0, 3.0, 3.01953125, 3.0, 2.8125, ]; let common_values = &[ (3.0, 333198), (2.75, 222142), (3.125, 74385), (2.875, 73751), (2.9375, 33356), (2.8125, 33246), (3.0625, 32891), (3.03125, 9479), (2.71875, 9381), (2.84375, 9352), (2.90625, 9344), (2.78125, 9342), (2.96875, 9313), (3.09375, 9258), (2.765625, 3221), (2.921875, 3214), (3.015625, 3204), (3.046875, 3175), (2.859375, 3165), (2.734375, 3163), ]; let sample_median = (3.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9232526079986494), standard_deviation: NiceFloat(0.1262248827883599), skewness: NiceFloat(-0.17691898540367232), excess_kurtosis: NiceFloat(-1.2742881322265622), }; special_random_primitive_float_range_helper::( core::f64::consts::E, core::f64::consts::PI, 3, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = e, b = π, mean abs of exponent = 10, mean precision = 10, mean zero P = 1/100 let values = &[ 2.923828125, 2.953125, 3.0, 2.8671875, 2.8125, 3.125, 3.015625, 2.8462657928466797, 3.140625, 2.875, 3.0, 2.75, 3.0, 2.71875, 2.75, 3.021484375, 2.97064208984375, 3.0179443359375, 2.9688720703125, 2.75, 2.97635555267334, 2.875, 2.890625, 2.8388671875, 2.781494140625, 3.0876541137695312, 3.10650634765625, 2.81756591796875, 2.8125, 2.774658203125, 2.746337890625, 3.086890615457378, 2.75, 2.7857666015625, 2.9739707708358765, 2.7529093623161316, 2.7723388671875, 3.125, 2.94140625, 2.916015625, 2.776611328125, 2.823486328125, 3.0, 3.0, 3.135541538707912, 2.75, 3.0625, 2.734408974647522, 3.0, 2.789327871054411, ]; let common_values = &[ (3.0, 91105), (2.75, 83336), (2.875, 38014), (3.125, 37964), (3.0625, 23196), (2.9375, 22929), (2.8125, 22922), (3.09375, 9177), (2.78125, 9003), (2.84375, 8943), (2.90625, 8936), (2.71875, 8920), (3.03125, 8913), (2.96875, 8854), (2.765625, 4212), (2.859375, 4171), (2.953125, 4126), (2.890625, 4119), (3.015625, 4090), (2.984375, 4082), ]; let sample_median = (2.9375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9261256924208183), standard_deviation: NiceFloat(0.12519730680807895), skewness: NiceFloat(-0.016892719700380622), excess_kurtosis: NiceFloat(-1.2338524787684633), }; special_random_primitive_float_range_helper::( core::f64::consts::E, core::f64::consts::PI, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0, mean abs of exponent = 7, mean precision = 2, mean zero P = 1/10 let values = &[ 100.0, 100.28125, 100.609375, 100.0, 100.5, 100.0, 100.0, 100.0, 100.5, 100.5, 100.71875, 100.0, 100.0, 100.0, 100.9375, 100.9375, 100.9375, 100.0, 100.25, 100.375, 100.0, 100.0, 100.3125, 100.0, 100.25, 100.25, 100.75, 100.0, 100.5, 100.75, 100.0, 100.5, 100.484375, 100.65625, 100.0, 100.0, 100.75, 100.5234375, 100.75, 100.0, 100.5, 100.25, 100.515625, 100.0, 100.5, 100.0, 100.0, 100.4140625, 100.0, 100.875, ]; let common_values = &[ (100.0, 333198), (100.5, 222142), (100.25, 74116), (100.75, 74020), (100.625, 24916), (100.375, 24899), (100.875, 24889), (100.125, 24789), (100.8125, 8258), (100.0625, 8253), (100.9375, 8239), (100.5625, 8179), (100.6875, 8158), (100.1875, 8148), (100.4375, 8140), (100.3125, 8094), (100.40625, 2826), (100.84375, 2825), (100.34375, 2802), (100.78125, 2781), ]; let sample_median = (100.3359375, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.33341106774094), standard_deviation: NiceFloat(0.29815058562814944), skewness: NiceFloat(0.27918114410604106), excess_kurtosis: NiceFloat(-1.2067672979256399), }; special_random_primitive_float_range_helper::( 100.0, 101.0, 7, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 100.0, b = 101.0, mean abs of exponent = 10, mean precision = 10, mean zero P = // 1/100 let values = &[ 100.41015625, 100.90625, 100.0, 100.953125, 100.875, 100.75, 100.46875, 100.31159591674805, 100.46875, 100.25, 100.0, 100.5, 100.0, 100.5625, 100.5, 100.51171875, 100.1158447265625, 100.225341796875, 100.188232421875, 100.5, 100.19916725158691, 100.75, 100.15625, 100.251953125, 100.06689453125, 100.66609191894531, 100.0096435546875, 100.2796630859375, 100.875, 100.69873046875, 100.86083984375, 100.38197174070228, 100.5, 100.802490234375, 100.90992856025696, 100.83274569362402, 100.740478515625, 100.25, 100.9140625, 100.32421875, 100.45556640625, 100.36865234375, 100.0, 100.0, 100.09102300740778, 100.5, 100.125, 100.27702021598816, 100.0, 100.45081884413958, ]; let common_values = &[ (100.0, 91410), (100.5, 83666), (100.25, 38155), (100.75, 38107), (100.625, 17631), (100.125, 17378), (100.375, 17229), (100.875, 17035), (100.6875, 7968), (100.1875, 7924), (100.5625, 7918), (100.3125, 7917), (100.4375, 7914), (100.8125, 7806), (100.0625, 7786), (100.9375, 7756), (100.40625, 3664), (100.59375, 3645), (100.71875, 3629), (100.09375, 3596), ]; let sample_median = (100.4921875, None); let sample_moment_stats = MomentStats { mean: NiceFloat(100.45411484815686), standard_deviation: NiceFloat(0.2957014655624591), skewness: NiceFloat(0.026064278269824867), excess_kurtosis: NiceFloat(-1.1480623934899934), }; special_random_primitive_float_range_helper::( 100.0, 101.0, 10, 1, 10, 1, 1, 100, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 1.0e38, b = Infinity, mean abs of exponent = 129, mean precision = 2, mean zero P = // 1/10 let values = &[ 1.78405961588245e44, 2.2322523270013563e41, 7.009816758571332e40, 2.1778071482940062e40, 1.4887353552791058e38, 5.575186299632656e42, 1.2760588759535192e38, 3.402823669209385e38, 8.166776806102523e39, 2.0416942015256308e39, 6.424531087467318e41, 1.7014118346046923e38, 2.722258935367508e39, 2.722258935367508e39, 5.274376687274546e39, 3.2964854295465914e38, 2.4457795122442452e38, 1.361129467683754e39, 2.3819765684465692e39, 1.914088313930279e38, 1.2760588759535192e38, 6.80564733841877e38, 1.089966956543631e38, 3.402823669209385e38, 2.9774707105582116e38, 5.954941421116423e38, 1.169720636290726e38, 1.7014118346046923e38, 1.6333553612205046e40, 2.9774707105582116e38, 2.722258935367508e39, 2.0416942015256308e39, 3.9557825154559096e39, 8.336917989562992e39, 5.444517870735016e39, 4.3556142965880123e40, 1.9055812547572554e40, 1.026164012745955e39, 3.4028236692093846e39, 1.2760588759535192e38, 1.3066842889764037e41, 4.7639531368931385e39, 1.2295358961010472e38, 1.7014118346046923e38, 1.6725558898897967e43, 1.2760588759535192e38, 1.2760588759535192e38, 1.6098350440189294e44, 1.7014118346046923e38, 3.743106036130323e39, ]; let common_values = &[ (1.2760588759535192e38, 83417), (1.7014118346046923e38, 62258), (3.402823669209385e38, 46943), (2.5521177519070385e38, 41660), (6.80564733841877e38, 35196), (5.104235503814077e38, 31368), (1.4887353552791058e38, 27818), (1.0633823966279327e38, 27639), (1.361129467683754e39, 26292), (1.0208471007628154e39, 23299), (2.722258935367508e39, 19745), (2.0416942015256308e39, 17625), (5.444517870735016e39, 14949), (2.9774707105582116e38, 13963), (2.1267647932558654e38, 13727), (4.0833884030512616e39, 13082), (1.169720636290726e38, 12430), (1.3823971156163125e38, 12379), (1.595073594941899e38, 12359), (1.0889035741470031e40, 11070), ]; let sample_median = (4.253529586511731e38, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.5180886046975516e45), standard_deviation: NiceFloat(1.9464007021815662e48), skewness: NiceFloat(500.41964668581875), excess_kurtosis: NiceFloat(285116.05539365485), }; special_random_primitive_float_range_helper::( 1.0e38, f64::INFINITY, 129, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = 1.0e-323, mean abs of exponent = 1075, mean // precision = 2, mean zero P = 1/10 let values = &[ 5.0e-324, 5.0e-324, 5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, 5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, 5.0e-324, -0.0, -5.0e-324, -5.0e-324, 0.0, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, -5.0e-324, 5.0e-324, 0.0, -5.0e-324, 5.0e-324, 5.0e-324, ]; let common_values = &[(5.0e-324, 450531), (-5.0e-324, 449245), (-0.0, 50351), (0.0, 49873)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, 1.0e-323, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = 1.0e-323, mean abs of exponent = 1075, mean precision = 2, mean zero P = // 1/10 let values = &[ 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, -0.0, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 5.0e-324, 0.0, 5.0e-324, 5.0e-324, 5.0e-324, ]; let common_values = &[(5.0e-324, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -0.0, 1.0e-323, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = 0.0, b = f64::MIN_POSITIVE_SUBNORMAL, mean abs of exponent = 1075, mean precision = // 2, mean zero P = 1/10 let values = &[0.0; 50]; let common_values = &[(0.0, 1000000)]; let sample_median = (0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( 0.0, f64::MIN_POSITIVE_SUBNORMAL, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // -f64::MIN_POSITIVE_SUBNORMAL, b = -0.0, mean abs of exponent = 1075, mean precision = 2, mean // zero P = 1/10 let values = &[-5.0e-324; 50]; let common_values = &[(-5.0e-324, 1000000)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, -0.0, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -f64::MIN_POSITIVE_SUBNORMAL, b = f64::MIN_POSITIVE_SUBNORMAL, mean abs of exponent // = 1075, mean precision = 2, mean zero P = 1/10 let values = &[ -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -0.0, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, -5.0e-324, 0.0, -5.0e-324, -5.0e-324, -5.0e-324, ]; let common_values = &[(-5.0e-324, 899776), (-0.0, 50351), (0.0, 49873)]; let sample_median = (-5.0e-324, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.0e-324), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -f64::MIN_POSITIVE_SUBNORMAL, f64::MIN_POSITIVE_SUBNORMAL, 1075, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -Infinity, b = Infinity, mean abs of exponent = 1, mean precision = 2, mean zero P = // 1/10 let values = &[ 12.0, 1.5, 0.75, 0.0, -12.0, -1.5, -0.75, -4.0, 4.0, 2.0, -2.0, -1.2041015625, -2.0, f64::NEGATIVE_INFINITY, -0.75, -0.75, -3.0, 0.0, 1.2041015625, -40.0, -0.6875, 2.0, 0.75, 0.75, -1.3125, 3.0, -2.0, 40.0, 0.6875, f64::NEGATIVE_INFINITY, -0.5, -1.5, -0.0, 1.3125, -0.125, -1.125, -0.046875, 2.0, -1.5, -1.9375, -1.0, 0.5, -0.75, 1.5, -1.0, 0.125, 0.0, -1.875, 1.125, 0.046875, ]; let common_values = &[ (1.0, 49883), (-1.0, 49740), (1.5, 33699), (f64::NEGATIVE_INFINITY, 33640), (-1.5, 33608), (0.0, 33393), (-0.0, 33191), (0.5, 25188), (-0.5, 25120), (2.0, 24765), (-2.0, 24711), (3.0, 16988), (-3.0, 16939), (0.75, 16654), (-0.75, 16610), (4.0, 12510), (0.25, 12465), (-4.0, 12461), (-0.25, 12430), (1.75, 11176), ]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( f64::NEGATIVE_INFINITY, f64::INFINITY, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); // f64, a = -0.0, b = 0.0, mean abs of exponent = 1, mean precision = 2, mean zero P = 1/10 let values = &[-0.0; 50]; let common_values = &[(-0.0, 1000000)]; let sample_median = (-0.0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; special_random_primitive_float_range_helper::( -0.0, 0.0, 1, 1, 2, 1, 1, 10, values, common_values, sample_median, sample_moment_stats, ); } fn special_random_primitive_float_range_fail_helper() { assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::ZERO, 1, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::ONE, 1, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::NAN, 1, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 0, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 0, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::from(100.0), T::from(101.0), 6, 1, 2, 1, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 1, 2, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 1, 0, 1, 10 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 2, 1, 2, 1 )); assert_panic!(special_random_primitive_float_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, 2, 1, 1, 0 )); } #[test] fn special_random_primitive_float_range_fail() { apply_fn_to_primitive_floats!(special_random_primitive_float_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/special_random_primitive_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::random::special_random_primitive_floats; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::num::random::special_random_primitive_floats_helper_helper; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, NAN_MOMENT_STATS}; use std::panic::catch_unwind; fn special_random_primitive_floats_helper( mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, expected_values: &[T], expected_common_values: &[(T, usize)], expected_median: (T, Option), expected_moment_stats: MomentStats, ) { special_random_primitive_floats_helper_helper( special_random_primitive_floats::( EXAMPLE_SEED, mean_exponent_numerator, mean_exponent_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ), expected_values, expected_common_values, expected_median, expected_moment_stats, ); } #[test] fn test_special_random_primitive_floats() { // f32, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f32::INFINITY, 1.0, 1.0, f32::INFINITY, 1.0, -1.0, f32::INFINITY, -1.0, f32::INFINITY, 0.0, -1.0, f32::INFINITY, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.5, f32::NEGATIVE_INFINITY, 0.0, -1.0, 1.0, -1.0, -1.0, -1.0, -0.0, 1.0, -1.0, -0.5, -1.0, f32::INFINITY, f32::NEGATIVE_INFINITY, f32::INFINITY, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (f32::INFINITY, 50304), (f32::NEGATIVE_INFINITY, 50127), (-0.0, 49984), (f32::NAN, 49926), (0.0, 49868), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), ]; let sample_median = (f32::NAN, None); special_random_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.25, 3.0, f32::INFINITY, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, f32::INFINITY, -6.5, -1.0, -1.0, f32::INFINITY, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, f32::INFINITY, -0.1875, -7.5, 0.0, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, f32::INFINITY, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (f32::NEGATIVE_INFINITY, 20096), (0.0, 20064), (f32::INFINITY, 20042), (-0.0, 20022), (f32::NAN, 20000), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), ]; let sample_median = (f32::NAN, None); special_random_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f32, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.65625, 0.0000014255784, 0.013183594, -0.8125, -74240.0, -0.0078125, -0.03060913, 3.331552, 4.75, -0.000038146973, -0.3125, -27136.0, -59392.0, -1.75, -41.1875, 0.30940247, -0.0009765625, -1536.0, 0.2109375, 0.0014648438, 2.1129381e-8, -0.037109375, 5242880.0, -0.21386719, 134.21094, 4.184082, -1561370.0, -2.1420419e-7, 0.38085938, -0.007003784, -37748736.0, -6448.0, 28.25, -6.703125, -4.483364, -3.1757812, 0.000003915804, -0.020751953, 0.00011110306, -0.000053405256, 0.00019985437, -35.40625, 0.005859375, 0.0078125, 28.25, 30.0, -0.20776367, -144.0, -0.109375, -6144.0, ]; let common_values = &[ (1.0, 2559), (-1.0, 2528), (0.5, 2362), (-2.0, 2312), (-1.5, 2306), (2.0, 2304), (1.5, 2275), (-0.5, 2243), (-3.0, 2204), (-4.0, 2163), (-0.25, 2129), (0.75, 2103), (3.0, 2081), (0.25, 2070), (f32::INFINITY, 2053), (-0.75, 2047), (4.0, 2038), (0.0, 2034), (f32::NEGATIVE_INFINITY, 1982), (-0.0, 1961), ]; let sample_median = (f32::NAN, None); special_random_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1/64, mean precision = 65/64, mean special P = 1/4 let values = &[ f64::INFINITY, 1.0, 1.0, f64::INFINITY, 1.0, -1.0, f64::INFINITY, -1.0, f64::INFINITY, 0.0, -1.0, f64::INFINITY, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.5, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.5, f64::NEGATIVE_INFINITY, 0.0, -1.0, 1.0, -1.0, -1.0, -1.0, -0.0, 1.0, -1.0, -0.5, -1.0, f64::INFINITY, f64::NEGATIVE_INFINITY, f64::INFINITY, 1.0, ]; let common_values = &[ (1.0, 358244), (-1.0, 357926), (f64::INFINITY, 50304), (f64::NEGATIVE_INFINITY, 50127), (-0.0, 49984), (f64::NAN, 49926), (0.0, 49868), (2.0, 5538), (1.5, 5500), (0.5, 5497), (-1.5, 5454), (-2.0, 5379), (-0.5, 5357), (0.75, 102), (3.0, 98), (-4.0, 95), (-0.25, 91), (-0.75, 87), (-3.0, 86), (0.25, 79), ]; let sample_median = (f64::NAN, None); special_random_primitive_floats_helper::( 1, 64, 65, 64, 1, 4, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 1, mean precision = 2, mean special P = 1/10 let values = &[ 1.0, 1.25, 3.0, f64::INFINITY, -1.0, -1.0, -2.0, -3.5, 1.0, 2.0, -1.5, -2.5, -2.0, f64::INFINITY, -6.5, -1.0, -1.0, f64::INFINITY, 3.0, -0.21875, -1.0, 0.25, 1.5, 5.25, -4.0, 7.0, -0.5, 0.1875, 1.25, f64::INFINITY, -0.1875, -7.5, 0.0, 0.75, -7.0, -6.0, -3.0, 0.234375, -2.0, -0.875, -0.75, 6.0, -24.0, 24.0, -2.0, 1.5, f64::INFINITY, -1.25, 14.0, 5.0, ]; let common_values = &[ (1.0, 74789), (-1.0, 74702), (1.5, 38119), (-0.5, 37713), (2.0, 37640), (-1.5, 37613), (-2.0, 37333), (0.5, 37027), (f64::NEGATIVE_INFINITY, 20096), (0.0, 20064), (f64::INFINITY, 20042), (-0.0, 20022), (f64::NAN, 20000), (0.75, 19050), (4.0, 18892), (0.25, 18875), (-3.0, 18866), (3.0, 18821), (-0.75, 18725), (-4.0, 18663), ]; let sample_median = (f64::NAN, None); special_random_primitive_floats_helper::( 1, 1, 2, 1, 1, 10, values, common_values, sample_median, NAN_MOMENT_STATS, ); // f64, mean abs of exponent = 10, mean precision = 10, mean special P = 1/100 let values = &[ 0.7709910366684198, 1.2504315236583352e-6, 0.00830078125, -0.8125, -85504.0, -0.0078125, -0.018890380859375, 2.5721821784973145, 5.75, -0.00003814697265625, -0.4375, -24064.0, -43008.0, -1.75, -54.6875, 0.4641265869140625, -0.0014760522753931582, -1536.0, 0.1484375, 0.00146484375, 1.9383151084184647e-8, -0.060546875, 7340032.0, -0.1982421875, 203.0546875, 4.57177734375, -1555162.0, -2.0675361156463623e-7, 0.279296875, -0.0045928955078125, -46137344.0, -5712.0, 17.75, -5.265625, -7.966220855712891, -2.99609375, 5.397188942879438e-6, -0.017333984375, 0.00011491775512695312, -0.00005845972555107437, 0.00020831823348999023, -46.78125, 0.005859375, 0.0078125, 27.25, 30.0, -0.175537109375, -208.0, -0.109375, -6144.0, ]; let common_values = &[ (1.0, 2396), (-1.0, 2336), (-2.0, 2200), (-1.5, 2169), (0.5, 2116), (2.0, 2108), (-0.5, 2101), (1.5, 2085), (f64::INFINITY, 2053), (0.0, 2034), (-3.0, 2000), (4.0, 1993), (f64::NEGATIVE_INFINITY, 1982), (3.0, 1969), (-0.0, 1961), (f64::NAN, 1959), (-0.25, 1955), (0.75, 1946), (0.25, 1917), (-4.0, 1882), ]; let sample_median = (f64::NAN, None); special_random_primitive_floats_helper::( 10, 1, 10, 1, 1, 100, values, common_values, sample_median, NAN_MOMENT_STATS, ); } fn special_random_primitive_floats_fail_helper() { assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 0, 1, 10, 1, 1, 10 )); assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 1, 0, 10, 1, 1, 10 )); assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 1, 1, 10 )); assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 10, 1, 1, 0, 1, 10 )); assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 1, 0 )); assert_panic!(special_random_primitive_floats::( EXAMPLE_SEED, 10, 1, 10, 1, 2, 1 )); } #[test] fn special_random_primitive_floats_fail() { apply_fn_to_primitive_floats!(special_random_primitive_floats_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/get_striped_bool_vec.rs ================================================ // Copyright © 2026 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 malachite_base::num::random::striped::{StripedBitSource, get_striped_bool_vec}; use malachite_base::random::EXAMPLE_SEED; pub(crate) fn bool_slice_to_string(bs: &[bool]) -> String { bs.iter().map(|&b| if b { '1' } else { '0' }).collect() } fn get_striped_bool_vec_helper(m_numerator: u64, m_denominator: u64, len: u64, out: &str) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let bits = bool_slice_to_string(&get_striped_bool_vec(&mut bit_source, len)); assert_eq!(bits, out); } #[test] fn test_get_striped_bool_vec() { get_striped_bool_vec_helper(2, 1, 0, ""); get_striped_bool_vec_helper( 2, 1, 50, "00110011000110101010010110100100000110000111010111", ); get_striped_bool_vec_helper( 10, 1, 50, "00011111111111000000011111111111111000000000001111", ); get_striped_bool_vec_helper( 11, 10, 50, "01010101010101101000111001010101010101111010101010", ); } ================================================ FILE: malachite-base/tests/num/random/striped/get_striped_unsigned_vec.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::{StripedBitSource, get_striped_unsigned_vec}; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; fn get_striped_unsigned_vec_helper( m_numerator: u64, m_denominator: u64, len: u64, out: &[&str], ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let xs = get_striped_unsigned_vec::(&mut bit_source, len) .iter() .map(T::to_binary_string) .collect_vec(); assert_eq!(xs, out); } #[test] fn test_get_striped_unsigned_vec() { get_striped_unsigned_vec_helper::(2, 1, 0, &[]); get_striped_unsigned_vec_helper::( 2, 1, 100, &[ "11001100", "1011000", "10100101", "100101", "11000", "10101110", "100111", "11000000", "10010001", "11000", "11000100", "10001011", "1001", ], ); get_striped_unsigned_vec_helper::( 10, 1, 100, &[ "11111000", "111111", "11100000", "11111111", "111", "11000000", "11111111", "0", "0", "11111000", "11111111", "11111111", "11", ], ); get_striped_unsigned_vec_helper::( 11, 10, 100, &[ "10101010", "1101010", "1110001", "10101010", "11101010", "1010101", "1010101", "10101011", "1010101", "1010101", "1010101", "1101101", "1101", ], ); get_striped_unsigned_vec_helper::( 2, 1, 130, &[ "1100000000100111101011100001100000100101101001010101100011001100", "1100110010001011010100110100110001011110001000001100010010001", "10", ], ); get_striped_unsigned_vec_helper::( 10, 1, 130, &[ "11111111110000000000011111111111111000000011111111111000", "1100000111111111111111000000001111111111111111111111100000000000", "11", ], ); get_striped_unsigned_vec_helper::( 11, 10, 130, &[ "1010101101010101010101011110101010101010011100010110101010101010", "101101010101011010110101001110101101101010101010101010101010101", "1", ], ); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_bit_source.rs ================================================ // Copyright © 2026 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 malachite_base::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; const BIT_STRING_LENGTH: usize = 80; fn generate_string(bit_source: &mut StripedBitSource) -> String { let mut string = String::with_capacity(BIT_STRING_LENGTH); for bit in bit_source.take(BIT_STRING_LENGTH) { if bit { string.push('1'); } else { string.push('0'); } } string } fn striped_bit_source_helper(m_numerator: u64, m_denominator: u64, bit_string: &str) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); assert_eq!(generate_string(&mut bit_source), bit_string); } #[test] pub fn test_striped_bit_source() { striped_bit_source_helper( 4, 1, "00000001011001100000000111100000000011111111110000111011000000000000111111111111", ); striped_bit_source_helper( 10, 1, "00011111111111000000011111111111111000000000001111111111000000000000000000011111", ); striped_bit_source_helper( 1000000, 1, "00000000000000000000000000000000000000000000000000000000000000000000000000000000", ); striped_bit_source_helper( 2, 1, "00110011000110101010010110100100000110000111010111100100000000111000100100011000", ); striped_bit_source_helper( 5, 4, "01010010110101001100101101011010101010001010101011010010101010010001101000010000", ); striped_bit_source_helper( 11, 10, "01010101010101101000111001010101010101111010101010101010110101011010101010101010", ); } #[test] #[should_panic] fn new_fail_1() { StripedBitSource::new(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn new_fail_2() { StripedBitSource::new(EXAMPLE_SEED, 1, 1); } #[test] #[should_panic] fn new_fail_3() { StripedBitSource::new(EXAMPLE_SEED, 2, 3); } #[test] pub fn test_end_block() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 1000000, 1); let mut strings = Vec::with_capacity(5); for _ in 0..5 { strings.push(generate_string(&mut bit_source)); bit_source.end_block(); } assert_eq!( strings, &[ "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "11111111111111111111111111111111111111111111111111111111111111111111111111111111", "00000000000000000000000000000000000000000000000000000000000000000000000000000000" ] ); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_bool_vecs.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::striped::striped_random_bool_vecs; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_bool_vecs_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_bool_vecs( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_length_numerator, mean_length_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_bool_vecs() { striped_random_bool_vecs_helper( 2, 1, 4, 1, &[ "", "00110011000110", "0001", "0110", "0", "", "00111", "10", "0100", "", "111010", "", "", "01111101000", "11001100", "", "100", "", "01011", "000111111", ], &[ ("", 199913), ("1", 80247), ("0", 79926), ("10", 32241), ("00", 32110), ("11", 31988), ("01", 31834), ("001", 12991), ("111", 12989), ("010", 12807), ], ("0100011111011", None), ); striped_random_bool_vecs_helper( 10, 1, 4, 1, &[ "", "00000000000000", "0000", "0001", "0", "", "00011", "11", "0000", "", "111111", "", "", "01111111100", "11111000", "", "111", "", "00000", "000111111", ], &[ ("", 199913), ("1", 80247), ("0", 79926), ("11", 57775), ("00", 57583), ("000", 41616), ("111", 41544), ("0000", 29747), ("1111", 29589), ("11111", 21524), ], ("00000001111", None), ); striped_random_bool_vecs_helper( 11, 10, 4, 1, &[ "", "01011010101010", "0110", "0101", "0", "", "01101", "10", "0101", "", "100101", "", "", "01101011010", "10101010", "", "101", "", "01010", "010101001", ], &[ ("", 199913), ("1", 80247), ("0", 79926), ("10", 58377), ("01", 58287), ("010", 42404), ("101", 42353), ("1010", 30704), ("0101", 30613), ("10101", 22466), ], ("010101", None), ); striped_random_bool_vecs_helper( 2, 1, 10, 1, &[ "0011001100011000100110001011", "000101000001011110", "0011001101000011111", "000", "011011101100", "1", "00111100000001010011001111101", "11110", "01", "10110001011", "111100001101100101000100011011", "01010", "0111", "00110101", "11111011001", "0011", "110111111", "000101101", "0110111011110110011001000", "1", ], &[ ("", 90709), ("0", 41449), ("1", 41338), ("00", 18773), ("10", 18748), ("11", 18731), ("01", 18531), ("001", 8685), ("111", 8639), ("010", 8624), ], ("011011101010", None), ); striped_random_bool_vecs_helper( 10, 1, 10, 1, &[ "0000000000000000000111000000", "000000111111110000", "0001111111111100000", "000", "000000000000", "1", "00000000000001111111111111111", "11111", "00", "10000001111", "111111111101111111111111000000", "00000", "0000", "00000000", "11000011111", "0001", "111111111", "000000000", "0000000001100111111111111", "1", ], &[ ("", 90709), ("0", 41449), ("1", 41338), ("00", 33629), ("11", 33603), ("111", 27832), ("000", 27669), ("1111", 22666), ("0000", 22522), ("11111", 18708), ], ( "00111111111110000000000011111000000001", Some("001111111111100000000000111110011111"), ), ); striped_random_bool_vecs_helper( 11, 10, 10, 1, &[ "0101101010101011010100101010", "011010110101101010", "0101010101010101011", "010", "010110101010", "1", "01010101001101011010101010101", "10101", "01", "10101010101", "101101010110101001010101001010", "01010", "0101", "01010101", "10101101010", "0101", "101011010", "010010101", "0101010101010101010101011", "1", ], &[ ("", 90709), ("0", 41449), ("1", 41338), ("10", 34030), ("01", 33878), ("010", 28388), ("101", 28324), ("1010", 23483), ("0101", 23162), ("10101", 19518), ], ("01011010", None), ); striped_random_bool_vecs_helper( 2, 1, 1, 4, &["", "", "0", "0", "00", "", "", "", "", "", "", "", "01", "0", "", "11", "", "", "", ""], &[ ("", 800023), ("1", 80189), ("0", 79739), ("00", 8218), ("01", 8023), ("11", 7972), ("10", 7920), ("001", 819), ("110", 812), ("101", 810), ], ("", None), ); striped_random_bool_vecs_helper( 10, 1, 1, 4, &["", "", "0", "0", "00", "", "", "", "", "", "", "", "00", "0", "", "11", "", "", "", ""], &[ ("", 800023), ("1", 80189), ("0", 79739), ("00", 14590), ("11", 14351), ("000", 2591), ("111", 2530), ("01", 1651), ("10", 1541), ("1111", 460), ], ("", None), ); striped_random_bool_vecs_helper( 11, 10, 1, 4, &["", "", "0", "0", "01", "", "", "", "", "", "", "", "01", "0", "", "10", "", "", "", ""], &[ ("", 800023), ("1", 80189), ("0", 79739), ("01", 14758), ("10", 14493), ("101", 2640), ("010", 2614), ("00", 1483), ("11", 1399), ("0101", 467), ], ("", None), ); } #[test] #[should_panic] fn striped_random_bool_vecs_fail_1() { striped_random_bool_vecs(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_fail_2() { striped_random_bool_vecs(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_fail_3() { striped_random_bool_vecs(EXAMPLE_SEED, 4, 1, 0, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_fail_4() { striped_random_bool_vecs(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_bool_vecs_fail_5() { striped_random_bool_vecs(EXAMPLE_SEED, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_bool_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::striped::striped_random_bool_vecs_from_length_iterator; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::vecs::random_values_from_vec; use std::iter::repeat; fn striped_random_bool_vecs_from_length_iterator_helper>( lengths_gen: &dyn Fn(Seed) -> I, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_bool_vecs_from_length_iterator( EXAMPLE_SEED, lengths_gen, mean_stripe_numerator, mean_stripe_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_bool_vecs_from_length_iterator() { striped_random_bool_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 2, 1, &[ "00", "0110", "00", "0110", "0001", "11", "", "01", "", "1110", "0110", "11", "1000", "01", "0100", "0001", "1010", "", "0000", "", ], &[ ("", 333820), ("00", 83428), ("10", 83346), ("11", 83184), ("01", 83167), ("0010", 20955), ("0001", 20940), ("1110", 20921), ("1011", 20912), ("0011", 20870), ], ("0011", None), ); striped_random_bool_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 10, 1, &[ "00", "0000", "00", "0000", "0000", "11", "", "00", "", "1111", "0001", "11", "1100", "00", "0000", "0000", "1110", "", "0000", "", ], &[ ("", 333820), ("11", 149822), ("00", 149788), ("0000", 121534), ("1111", 121330), ("01", 16807), ("10", 16708), ("0011", 13644), ("1110", 13490), ("0001", 13454), ], ("0000", None), ); striped_random_bool_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 11, 10, &[ "01", "0100", "01", "0101", "0101", "10", "", "01", "", "1001", "0101", "10", "1101", "01", "0101", "0110", "1010", "", "0010", "", ], &[ ("", 333820), ("01", 151459), ("10", 151370), ("0101", 125515), ("1010", 124901), ("11", 15160), ("00", 15136), ("0010", 12625), ("1011", 12598), ("1001", 12494), ], ("01", None), ); striped_random_bool_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 2, 1, &[ "001100110001", "00", "0111011001110100", "00", "0010100000101111001100110100", "", "1110000000", "01101110", "10", "", "001110000111", "1111", "", "", "11", "010100", "", "01", "", "00", ], &[ ("", 333981), ("11", 56301), ("01", 55922), ("00", 55472), ("10", 55087), ("0101", 9537), ("0100", 9341), ("0010", 9326), ("1011", 9314), ("0001", 9297), ], ("00111111100101", Some("0011111110010100")), ); striped_random_bool_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 10, 1, &[ "000000000000", "00", "0000000111000000", "00", "0000011111111000000111111111", "", "1110000000", "00000000", "11", "", "000000000000", "1111", "", "", "11", "011111", "", "00", "", "00", ], &[ ("", 333981), ("00", 100383), ("11", 100353), ("1111", 53920), ("0000", 53883), ("000000", 29226), ("111111", 29014), ("00000000", 15928), ("11111111", 15670), ("10", 11035), ], ("000000", None), ); striped_random_bool_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 11, 10, &[ "010110101010", "01", "0100101011010101", "01", "0010100101001010101010101010", "", "1010101101", "01011010", "10", "", "010101010101", "1100", "", "", "10", "010110", "", "01", "", "01", ], &[ ("", 333981), ("10", 101326), ("01", 101218), ("0101", 55895), ("1010", 55433), ("101010", 30661), ("010101", 30567), ("01010101", 17148), ("10101010", 16775), ("00", 10176), ], ("0101", None), ); } #[test] #[should_panic] fn striped_random_bool_vecs_from_length_iterator_fail_1() { striped_random_bool_vecs_from_length_iterator(EXAMPLE_SEED, &|_| repeat(1), 1, 0); } #[test] #[should_panic] fn striped_random_bool_vecs_from_length_iterator_fail_2() { striped_random_bool_vecs_from_length_iterator(EXAMPLE_SEED, &|_| repeat(1), 2, 3); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_bool_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::striped::striped_random_bool_vecs_length_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_bool_vecs_length_inclusive_range_helper( a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_bool_vecs_length_inclusive_range( EXAMPLE_SEED, a, b, mean_stripe_numerator, mean_stripe_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_bool_vecs_length_inclusive_range() { striped_random_bool_vecs_length_inclusive_range_helper( 3, 9, 2, 1, &[ "00110011", "01110011", "00100110", "00010111", "001010000", "110", "0100", "1110011", "011001011", "111000", "111110010", "0001001", "00011110", "00000", "1110101", "0011001", "11111", "01000010", "01001110", "10111", ], &[ ("001", 18041), ("110", 18008), ("111", 17919), ("100", 17906), ("011", 17905), ("000", 17819), ("010", 17792), ("101", 17782), ("0111", 9023), ("1011", 9023), ], ("100", None), ); striped_random_bool_vecs_length_inclusive_range_helper( 3, 9, 10, 1, &[ "00000000", "00000000", "00000111", "01111111", "000001111", "111", "0001", "1111110", "000000000", "111000", "111111111", "0000000", "00000000", "00000", "1110000", "0000000", "11111", "00000000", "01111110", "11111", ], &[ ("000", 58009), ("111", 57974), ("1111", 52110), ("0000", 51905), ("00000", 47047), ("11111", 46660), ("111111", 42411), ("000000", 41880), ("0000000", 38018), ("1111111", 37708), ], ("100", None), ); striped_random_bool_vecs_length_inclusive_range_helper( 3, 9, 11, 10, &[ "01011010", "01010101", "00101011", "01010101", "001010010", "101", "0010", "1010101", "010101010", "101010", "100101011", "0101010", "01010101", "01001", "1101011", "0101010", "10101", "01010101", "01010101", "10101", ], &[ ("010", 59241), ("101", 59092), ("1010", 53578), ("0101", 53360), ("01010", 48685), ("10101", 48527), ("010101", 44471), ("101010", 44350), ("0101010", 40536), ("1010101", 40115), ], ("100", None), ); } #[test] #[should_panic] fn striped_random_bool_vecs_length_inclusive_range_fail_1() { striped_random_bool_vecs_length_inclusive_range(EXAMPLE_SEED, 3, 10, 1, 0); } #[test] #[should_panic] fn striped_random_bool_vecs_length_inclusive_range_fail_2() { striped_random_bool_vecs_length_inclusive_range(EXAMPLE_SEED, 3, 10, 2, 3); } #[test] #[should_panic] fn striped_random_bool_vecs_length_inclusive_range_fail_3() { striped_random_bool_vecs_length_inclusive_range(EXAMPLE_SEED, 2, 1, 4, 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_bool_vecs_length_range.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::striped::striped_random_bool_vecs_length_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_bool_vecs_length_range_helper( a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_bool_vecs_length_range( EXAMPLE_SEED, a, b, mean_stripe_numerator, mean_stripe_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_bool_vecs_length_range() { striped_random_bool_vecs_length_range_helper( 3, 10, 2, 1, &[ "00110011", "01110011", "00100110", "00010111", "001010000", "110", "0100", "1110011", "011001011", "111000", "111110010", "0001001", "00011110", "00000", "1110101", "0011001", "11111", "01000010", "01001110", "10111", ], &[ ("001", 18041), ("110", 18008), ("111", 17919), ("100", 17906), ("011", 17905), ("000", 17819), ("010", 17792), ("101", 17782), ("0111", 9023), ("1011", 9023), ], ("100", None), ); striped_random_bool_vecs_length_range_helper( 3, 10, 10, 1, &[ "00000000", "00000000", "00000111", "01111111", "000001111", "111", "0001", "1111110", "000000000", "111000", "111111111", "0000000", "00000000", "00000", "1110000", "0000000", "11111", "00000000", "01111110", "11111", ], &[ ("000", 58009), ("111", 57974), ("1111", 52110), ("0000", 51905), ("00000", 47047), ("11111", 46660), ("111111", 42411), ("000000", 41880), ("0000000", 38018), ("1111111", 37708), ], ("100", None), ); striped_random_bool_vecs_length_range_helper( 3, 10, 11, 10, &[ "01011010", "01010101", "00101011", "01010101", "001010010", "101", "0010", "1010101", "010101010", "101010", "100101011", "0101010", "01010101", "01001", "1101011", "0101010", "10101", "01010101", "01010101", "10101", ], &[ ("010", 59241), ("101", 59092), ("1010", 53578), ("0101", 53360), ("01010", 48685), ("10101", 48527), ("010101", 44471), ("101010", 44350), ("0101010", 40536), ("1010101", 40115), ], ("100", None), ); } #[test] #[should_panic] fn striped_random_bool_vecs_length_range_fail_1() { striped_random_bool_vecs_length_range(EXAMPLE_SEED, 3, 10, 1, 0); } #[test] #[should_panic] fn striped_random_bool_vecs_length_range_fail_2() { striped_random_bool_vecs_length_range(EXAMPLE_SEED, 3, 10, 2, 3); } #[test] #[should_panic] fn striped_random_bool_vecs_length_range_fail_3() { striped_random_bool_vecs_length_range(EXAMPLE_SEED, 1, 1, 4, 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_bool_vecs_min_length.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::striped::striped_random_bool_vecs_min_length; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_bool_vecs_min_length_helper( min_length: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_bool_vecs_min_length( EXAMPLE_SEED, min_length, mean_stripe_numerator, mean_stripe_denominator, mean_length_numerator, mean_length_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_bool_vecs_min_length() { striped_random_bool_vecs_min_length_helper( 0, 2, 1, 4, 1, &[ "", "00110011000110", "0001", "0110", "0", "", "00111", "10", "0100", "", "111010", "", "", "01111101000", "11001100", "", "100", "", "01011", "000111111", ], &[ ("", 199913), ("1", 80247), ("0", 79926), ("10", 32241), ("00", 32110), ("11", 31988), ("01", 31834), ("001", 12991), ("111", 12989), ("010", 12807), ], ("0100011111011", None), ); striped_random_bool_vecs_min_length_helper( 3, 10, 1, 4, 1, &[ "0000", "00000", "00000", "00000", "0000", "10001", "000", "111", "0000", "111", "110", "000", "0000", "0001111", "111", "01111", "111", "00000011", "0000", "1111", ], &[ ("000", 202463), ("111", 202257), ("0000", 91181), ("1111", 91085), ("00000", 41060), ("11111", 41041), ("100", 22693), ("110", 22484), ("001", 22434), ("011", 22270), ], ("100", None), ); striped_random_bool_vecs_min_length_helper( 0, 11, 10, 4, 1, &[ "", "01011010101010", "0110", "0101", "0", "", "01101", "10", "0101", "", "100101", "", "", "01101011010", "10101010", "", "101", "", "01010", "010101001", ], &[ ("", 199913), ("1", 80247), ("0", 79926), ("10", 58377), ("01", 58287), ("010", 42404), ("101", 42353), ("1010", 30704), ("0101", 30613), ("10101", 22466), ], ("010101", None), ); striped_random_bool_vecs_min_length_helper( 3, 2, 1, 10, 1, &[ "00110011", "01110011101100111010000101", "011111010000", "01100110010", "0111", "110", "000000011", "101110", "011000111100000", "111", "101011001100", "0000", "010", "000010100111010000011", "1110010011010111", "010", "11100100", "010", "010111100101", "10000010011001110111111110100", ], &[ ("011", 15722), ("101", 15676), ("110", 15638), ("100", 15613), ("010", 15610), ("111", 15603), ("000", 15516), ("001", 15471), ("0110", 7099), ("1010", 6906), ], ("100", None), ); striped_random_bool_vecs_min_length_helper( 0, 10, 1, 10, 1, &[ "0000000000000000000111000000", "000000111111110000", "0001111111111100000", "000", "000000000000", "1", "00000000000001111111111111111", "11111", "00", "10000001111", "111111111101111111111111000000", "00000", "0000", "00000000", "11000011111", "0001", "111111111", "000000000", "0000000001100111111111111", "1", ], &[ ("", 90709), ("0", 41449), ("1", 41338), ("00", 33629), ("11", 33603), ("111", 27832), ("000", 27669), ("1111", 22666), ("0000", 22522), ("11111", 18708), ], ( "00111111111110000000000011111000000001", Some("001111111111100000000000111110011111"), ), ); striped_random_bool_vecs_min_length_helper( 3, 11, 10, 10, 1, &[ "01011010", "01010101101010010101011010", "011010110101", "01010101010", "0101", "101", "010110101", "100101", "010101010101001", "110", "101001010101", "0101", "010", "010101010101010101101", "1010110101001010", "010", "10110101", "010", "010101010101", "10101001010101010100101011010", ], &[ ("101", 51809), ("010", 51385), ("0101", 41252), ("1010", 40909), ("01010", 33103), ("10101", 32685), ("101010", 25995), ("010101", 25896), ("0101010", 20699), ("1010101", 20622), ], ("100", None), ); } #[test] #[should_panic] fn striped_random_bool_vecs_min_length_fail_1() { striped_random_bool_vecs_min_length(EXAMPLE_SEED, 3, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_min_length_fail_2() { striped_random_bool_vecs_min_length(EXAMPLE_SEED, 3, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_min_length_fail_3() { striped_random_bool_vecs_min_length(EXAMPLE_SEED, 3, 4, 1, 3, 1); } #[test] #[should_panic] fn striped_random_bool_vecs_min_length_fail_4() { striped_random_bool_vecs_min_length(EXAMPLE_SEED, 1, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_bool_vecs_min_length_fail_5() { striped_random_bool_vecs_min_length(EXAMPLE_SEED, 0, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_fixed_length_bool_vecs.rs ================================================ // Copyright © 2026 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 crate::num::random::striped::get_striped_bool_vec::bool_slice_to_string; use itertools::Itertools; use malachite_base::num::random::striped::striped_random_fixed_length_bool_vecs; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_fixed_length_bool_vecs_helper( len: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let xs = striped_random_fixed_length_bool_vecs( EXAMPLE_SEED, len, mean_stripe_numerator, mean_stripe_denominator, ); let values = xs .clone() .take(20) .map(|bs| bool_slice_to_string(&bs)) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()) .into_iter() .map(|(bs, freq)| (bool_slice_to_string(&bs), freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let median_lo = bool_slice_to_string(&median_lo); let median_hi = median_hi.map(|bs| bool_slice_to_string(&bs)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_fixed_length_bool_vecs() { striped_random_fixed_length_bool_vecs_helper(0, 10, 1, &[""; 20], &[("", 1000000)], ("", None)); striped_random_fixed_length_bool_vecs_helper( 1, 10, 1, &[ "0", "0", "0", "0", "0", "1", "0", "1", "0", "1", "1", "0", "0", "0", "1", "0", "1", "0", "0", "1", ], &[("1", 500079), ("0", 499921)], ("1", None), ); striped_random_fixed_length_bool_vecs_helper( 2, 10, 1, &[ "00", "00", "00", "00", "00", "11", "00", "11", "00", "11", "11", "00", "00", "00", "11", "00", "11", "00", "01", "11", ], &[("11", 449989), ("00", 449537), ("01", 50384), ("10", 50090)], ("10", None), ); striped_random_fixed_length_bool_vecs_helper( 5, 10, 1, &[ "00000", "00000", "00000", "00000", "00011", "11000", "00000", "11111", "01111", "11111", "10000", "00011", "00000", "00000", "11000", "00000", "11111", "00000", "00000", "11111", ], &[ ("11111", 328176), ("00000", 327532), ("00001", 36685), ("10000", 36616), ("00111", 36602), ("01111", 36495), ("11110", 36487), ("11000", 36446), ("00011", 36354), ("11100", 36250), ], ("10000", None), ); } #[test] #[should_panic] fn striped_random_fixed_length_bool_vecs_fail_1() { striped_random_fixed_length_bool_vecs(EXAMPLE_SEED, 5, 1, 0); } #[test] #[should_panic] fn striped_random_fixed_length_bool_vecs_fail_2() { striped_random_fixed_length_bool_vecs(EXAMPLE_SEED, 5, 2, 3); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_fixed_length_unsigned_vecs.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::striped_random_fixed_length_unsigned_vecs; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_fixed_length_unsigned_vecs_helper( len: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_fixed_length_unsigned_vecs::( EXAMPLE_SEED, len, mean_stripe_numerator, mean_stripe_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_fixed_length_unsigned_vecs() { striped_random_fixed_length_unsigned_vecs_helper::( 0, 10, 1, &[&[][..]; 20], &[(&[], 1000000)], (&[], None), ); striped_random_fixed_length_unsigned_vecs_helper::( 1, 10, 1, &[ &["0"], &["0"], &["11100000"], &["11111110"], &["11100000"], &["111111"], &["11100000"], &["11111111"], &["11111100"], &["11111111"], &["11111111"], &["0"], &["11110000"], &["0"], &["11111111"], &["11110000"], &["111"], &["0"], &["100"], &["11111111"], ], &[ (&["0"], 238932), (&["11111111"], 238695), (&["11100000"], 26922), (&["1111111"], 26791), (&["11000000"], 26775), (&["11"], 26754), (&["111"], 26726), (&["11110000"], 26662), (&["11111"], 26607), (&["1111"], 26594), ], (&["1111111"], None), ); striped_random_fixed_length_unsigned_vecs_helper::( 2, 10, 1, &[ &["0", "0"], &["1110000", "0"], &["11111000", "111"], &["11111100", "11111"], &["0", "0"], &["11111111", "11111"], &["0", "0"], &["1111", "11111100"], &["0", "1"], &["1111111", "0"], &["11111111", "11111"], &["11111100", "1"], &["0", "0"], &["110000", "11111111"], &["11111", "0"], &["0", "0"], &["11111111", "11111111"], &["0", "0"], &["1000", "0"], &["11111111", "11111111"], ], &[ (&["0", "0"], 103184), (&["11111111", "11111111"], 102963), (&["0", "11111111"], 11776), (&["11111000", "11111111"], 11585), (&["0", "11111110"], 11579), (&["11111110", "11111111"], 11542), (&["11000000", "11111111"], 11499), (&["1111", "0"], 11487), (&["11111111", "1111111"], 11483), (&["11111111", "1"], 11459), ], (&["1111111", "11111111"], None), ); striped_random_fixed_length_unsigned_vecs_helper::( 5, 10, 1, &[ &["0", "0", "111000", "0", "11111110"], &["11111100", "0", "11111000", "11111111", "11111111"], &["0", "11111100", "11111111", "1111111", "11100000"], &["0", "1000", "0", "11111110", "11111111"], &["10000000", "111", "11111100", "11111111", "11111111"], &["11001111", "0", "11110000", "11111111", "11111111"], &["0", "0", "0", "0", "10000000"], &["1", "0", "0", "11100000", "11111111"], &["0", "0", "0", "0", "11111100"], &["1110111", "0", "11110000", "1110", "11010000"], &["1111101", "11111111", "11111111", "11111111", "111111"], &["0", "1111", "100000", "11111111", "11"], &["10000000", "11111111", "11101111", "11111111", "11111111"], &["11111100", "111111", "0", "0", "1111"], &["11111111", "1", "11111111", "11111111", "11111"], &["0", "11100000", "11111111", "1", "1100"], &["11111111", "1110111", "0", "11111100", "1"], &["11111110", "111", "0", "0", "0"], &["11110000", "11", "10000000", "11111111", "11000011"], &["1", "10000000", "11111111", "11111111", "111"], ], &[ (&["0", "0", "0", "0", "0"], 8118), ( &["11111111", "11111111", "11111111", "11111111", "11111111"], 8057, ), (&["0", "11000000", "11111111", "11111111", "11111111"], 972), (&["11111111", "11111111", "11111111", "111", "0"], 961), (&["11111111", "11111111", "11111111", "11111", "0"], 955), ( &["11111100", "11111111", "11111111", "11111111", "11111111"], 948, ), (&["0", "0", "0", "0", "11111110"], 947), (&["0", "0", "10000000", "11111111", "11111111"], 946), (&["11111111", "1111", "0", "0", "0"], 944), (&["0", "0", "0", "11111111", "11111111"], 944), ], ( &["1111111", "11111111", "11111111", "10000001", "11111100"], Some(&["1111111", "11111111", "11111111", "10000001", "11111111"]), ), ); } #[test] #[should_panic] fn striped_random_fixed_length_unsigned_vecs_fail_1() { striped_random_fixed_length_unsigned_vecs::(EXAMPLE_SEED, 5, 1, 0); } #[test] #[should_panic] fn striped_random_fixed_length_unsigned_vecs_fail_2() { striped_random_fixed_length_unsigned_vecs::(EXAMPLE_SEED, 5, 2, 3); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_natural_signeds.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_natural_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_natural_signeds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_natural_signeds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_natural_signeds() { // i8, m = 4 let values = &[ "0", "101100", "110000", "1111100", "1111", "1111110", "0", "111", "11101", "1100000", "1111111", "1100000", "0", "10", "1000011", "111111", "1", "0", "1111", "1", ]; let common_values = &[ ("0", 89042), ("1111111", 88624), ("11111", 29871), ("1111000", 29848), ("1000000", 29802), ("1111110", 29796), ("1100000", 29664), ("1110000", 29649), ("111", 29644), ("111111", 29621), ]; let sample_median = (64, None); let sample_moment_stats = MomentStats { mean: NiceFloat(63.526448000001764), standard_deviation: NiceFloat(47.66137677522695), skewness: NiceFloat(-0.0011056592983105758), excess_kurtosis: NiceFloat(-1.5649370173869874), }; striped_random_natural_signeds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 2 let values = &[ "11001", "11100", "101010", "1001011", "101101", "1111100", "111100", "10100", "1101", "1111111", "1100011", "1101101", "1100", "100", "1100001", "100011", "110100", "110101", "110100", "10011", ]; let common_values = &[ ("11010", 8131), ("1111", 8059), ("1010101", 8004), ("1001101", 7998), ("11011", 7993), ("1110111", 7978), ("1010100", 7959), ("111", 7958), ("1011010", 7953), ("1100011", 7947), ]; let sample_median = (64, None); let sample_moment_stats = MomentStats { mean: NiceFloat(63.555225000001755), standard_deviation: NiceFloat(36.938359582441294), skewness: NiceFloat(-0.0007106807748730345), excess_kurtosis: NiceFloat(-1.2008391146615376), }; striped_random_natural_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 5/4 let values = &[ "101001", "100101", "100110", "1101001", "101101", "1010101", "111010", "101010", "10110", "1010101", "1001000", "1001011", "1000", "11100", "1111010", "101101", "110101", "101010", "100101", "100010", ]; let common_values = &[ ("101010", 131212), ("1010101", 131202), ("1001010", 33119), ("1011010", 33073), ("10101", 32947), ("100101", 32868), ("1010010", 32851), ("101011", 32817), ("101001", 32765), ("110101", 32761), ]; let sample_median = (65, None); let sample_moment_stats = MomentStats { mean: NiceFloat(63.51375499999882), standard_deviation: NiceFloat(27.10334306669828), skewness: NiceFloat(-0.0017292127163026868), excess_kurtosis: NiceFloat(-1.1007498380278757), }; striped_random_natural_signeds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 32 let values = &[ "11111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111110000000000000000000000000000000000000", "111111111111111111111111111111111111111111111111111111111", "111111111000000000000000000000000000000000000001100000000111111", "11111111111111100000", "11111111111111111", "111111111111", "111111111111111111111111111111111111111111111111111100000000000", "111111111111100000000000000000000000000000000000000000000000000", "111111111000000000000000000000000000000000000000000000000000000", "1111111111111111111111111111100000000000000", "1000000011111111111111111111", "111111000000000000000111111111111111111111111111111111111111111", "0", "11111111111100000000000000000000000000000000000000", "111111111111111111111110000000000000000001111111", "1111111111111111111111111111111111111111111111111111111111111", "1111111", ]; let common_values = &[ ( "111111111111111111111111111111111111111111111111111111111111111", 69948, ), ("0", 69809), ( "111111111111111111111111111111111111111111111111111111111111000", 2383, ), ( "11111111111111111111111111111111111111111111111111111111111", 2362, ), ("11111111111111111111111", 2334), ( "111111111111111100000000000000000000000000000000000000000000000", 2334, ), ( "100000000000000000000000000000000000000000000000000000000000000", 2328, ), ( "111111111111111111111111111111100000000000000000000000000000000", 2327, ), ("111111111", 2320), ("11", 2318), ]; let sample_median = (4611686018427387904, None); let sample_moment_stats = MomentStats { mean: NiceFloat(4.614976015729421e18), standard_deviation: NiceFloat(4.4270184647985137e18), skewness: NiceFloat(-0.0014267894129673844), excess_kurtosis: NiceFloat(-1.9430528242638783), }; striped_random_natural_signeds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 2 let values = &[ "1100110001101010100101101001000001100001110101111001000000001", "111011011100111110111000010111001101001101010010111011001100", "11110000010100111000110001101100111001001010101110001000100000", "110010001100111101011100111111100001001110001100001001000000011", "1100110011001011000001001111001010100010110100011010010001", "111000101110010000110100101010100100111001100100001101010011011", "10000011110001100010001010101101101100100000010011101111010", "1110110110110011010011011010000111001101110110010001101011110", "11010010000001101100111000010011100101110010101101001100110000", "110000010001000110001011100111001101110010001111000110001111001", "100011101111011001001101101011100000110001110100111011011011111", "111101111100000110000001010001001101011110011110110100010110010", "1010001010011101001011011111100101110000001010101000111100001", "11110011011100110101011110010001110100010111001010000100011101", "110001001100111101011111000100111101011110111101110011010100111", "1111011101101101011111011010011011001011010001101011100101", "11111101110101010010000100011110100110100000110100101000110111", "10101011010100000101011100111011000001101010001000101111111010", "110000111110001111000001110011101110100001101011111010100110", "1101010111111111000111001111000111110001111110100101000001111", ]; let common_values = &[ ("10101000110110101100110011001101011011101", 1), ("1110100010100111110111100000011111000010100", 1), ("10011111100110010100000010001100001001111011", 1), ("10111110110011101010110111100010100101101100", 1), ("110101001100100110010011010000011100100111011", 1), ("1001000111011010110011001111101001111101110011", 1), ("1010101100111011110111011011011100011101010101", 1), ("1100110000110110000100011110000110101010110010", 1), ("1100110011000110101101111111111110111011101001", 1), ("1101011001000111111110011010000001001001000110", 1), ]; let sample_median = (4616064909372870741, Some(4616067528870766644)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.614689648935556e18), standard_deviation: NiceFloat(2.6622250799886193e18), skewness: NiceFloat(-0.0006757801147527129), excess_kurtosis: NiceFloat(-1.199752325803772), }; striped_random_natural_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 33/32 let values = &[ "10101010101010101010101101010101010101010101010101010101010101", "10101010101010100010101010010101101010101010101011010101011010", "10101010010101011010101010101010101101010101010101010101010101", "101010101010101010101101010101010101010101010101010101010101010", "10101010101010101010101011010101010101001010010101001010101010", "101010101010101010101010101010101010100101010010101010110101010", "10101010101010101010101010101010101010101010101010110101010101", "10101010101010101010010101010101010101010101010101010101010101", "10101010010101010101010101010101010101010101010101010101010101", "101010101100101010101010101010101010101010101010101010010101010", "101010101010101010101010101010101011001010101010101101010101010", "101101010101010011010101010101010101010101010101010101010101010", "10101001010101010101011010101010101010101010101010101010101010", "10101010101010101011010010010110101010101010101010101010101010", "101010101010101010110101010101010101010101010010101010101010101", "10101010101010101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101011010101010101", "10101010101010101010101010101010101010101101010101010101010101", "10101010101010101011011010100101010101001010101010101010101010", "10101010101010101010101010101011010101010101010101010101010101", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 74299, ), ( "10101010101010101010101010101010101010101010101010101010101010", 74072, ), ( "101010101010101010101010010101010101010101010101010101010101010", 2429, ), ( "101010101010101010101010101010101010101010101010101010101011010", 2419, ), ( "101010101011010101010101010101010101010101010101010101010101010", 2419, ), ( "101010101010101010101001010101010101010101010101010101010101010", 2411, ), ( "101010101010101010101010101010101010101010101010010101010101010", 2393, ), ( "101010101001010101010101010101010101010101010101010101010101010", 2390, ), ( "10101010101010101010101010101001010101010101010101010101010101", 2389, ), ( "10101010101010101010101010101010101010101010101010101010100101", 2389, ), ]; let sample_median = (5281221163029801642, Some(5281221163029804373)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.613154278246113e18), standard_deviation: NiceFloat(1.599140542162029e18), skewness: NiceFloat(-0.0019511120341977268), excess_kurtosis: NiceFloat(-1.7372862317601716), }; striped_random_natural_signeds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_natural_signeds_fail_helper() { assert_panic!(striped_random_natural_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_natural_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_natural_signeds_fail() { apply_fn_to_signeds!(striped_random_natural_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_negative_signeds.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_negative_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_negative_signeds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_negative_signeds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_negative_signeds() { // i8, m = 4 let values = &[ "10000000", "10101100", "10110000", "11111100", "10001111", "11111110", "10000000", "10000111", "10011101", "11100000", "11111111", "11100000", "10000000", "10000010", "11000011", "10111111", "10000001", "10000000", "10001111", "10000001", ]; let common_values = &[ ("10000000", 89042), ("11111111", 88624), ("10011111", 29871), ("11111000", 29848), ("11000000", 29802), ("11111110", 29796), ("11100000", 29664), ("11110000", 29649), ("10000111", 29644), ("10111111", 29621), ]; let sample_median = (-64, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-64.47355199999896), standard_deviation: NiceFloat(47.66137677522698), skewness: NiceFloat(-0.0011056592983105659), excess_kurtosis: NiceFloat(-1.5649370173869896), }; striped_random_negative_signeds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 2 let values = &[ "10011001", "10011100", "10101010", "11001011", "10101101", "11111100", "10111100", "10010100", "10001101", "11111111", "11100011", "11101101", "10001100", "10000100", "11100001", "10100011", "10110100", "10110101", "10110100", "10010011", ]; let common_values = &[ ("10011010", 8131), ("10001111", 8059), ("11010101", 8004), ("11001101", 7998), ("10011011", 7993), ("11110111", 7978), ("11010100", 7959), ("10000111", 7958), ("11011010", 7953), ("11100011", 7947), ]; let sample_median = (-64, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-64.44477500000217), standard_deviation: NiceFloat(36.93835958244133), skewness: NiceFloat(-0.0007106807748731826), excess_kurtosis: NiceFloat(-1.2008391146615451), }; striped_random_negative_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 5/4 let values = &[ "10101001", "10100101", "10100110", "11101001", "10101101", "11010101", "10111010", "10101010", "10010110", "11010101", "11001000", "11001011", "10001000", "10011100", "11111010", "10101101", "10110101", "10101010", "10100101", "10100010", ]; let common_values = &[ ("10101010", 131212), ("11010101", 131202), ("11001010", 33119), ("11011010", 33073), ("10010101", 32947), ("10100101", 32868), ("11010010", 32851), ("10101011", 32817), ("10101001", 32765), ("10110101", 32761), ]; let sample_median = (-63, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-64.48624499999755), standard_deviation: NiceFloat(27.103343066698287), skewness: NiceFloat(-0.0017292127163029483), excess_kurtosis: NiceFloat(-1.1007498380278833), }; striped_random_negative_signeds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 32 let values = &[ "1000000000000000000000000000000000011111111111111111111111111111", "1000000111111111111111111111111111111111111111111111111111111111", "1000000000000000000000000000000000001111111111111111111111111111", "1111111111111111111111111110000000000000000000000000000000000000", "1000000111111111111111111111111111111111111111111111111111111111", "1111111111000000000000000000000000000000000000001100000000111111", "1000000000000000000000000000000000000000000011111111111111100000", "1000000000000000000000000000000000000000000000011111111111111111", "1000000000000000000000000000000000000000000000000000111111111111", "1111111111111111111111111111111111111111111111111111100000000000", "1111111111111100000000000000000000000000000000000000000000000000", "1111111111000000000000000000000000000000000000000000000000000000", "1000000000000000000001111111111111111111111111111100000000000000", "1000000000000000000000000000000000001000000011111111111111111111", "1111111000000000000000111111111111111111111111111111111111111111", "1000000000000000000000000000000000000000000000000000000000000000", "1000000000000011111111111100000000000000000000000000000000000000", "1000000000000000111111111111111111111110000000000000000001111111", "1001111111111111111111111111111111111111111111111111111111111111", "1000000000000000000000000000000000000000000000000000000001111111", ]; let common_values = &[ ( "1111111111111111111111111111111111111111111111111111111111111111", 69948, ), ( "1000000000000000000000000000000000000000000000000000000000000000", 69809, ), ( "1111111111111111111111111111111111111111111111111111111111111000", 2383, ), ( "1000011111111111111111111111111111111111111111111111111111111111", 2362, ), ( "1111111111111111100000000000000000000000000000000000000000000000", 2334, ), ( "1000000000000000000000000000000000000000011111111111111111111111", 2334, ), ( "1100000000000000000000000000000000000000000000000000000000000000", 2328, ), ( "1111111111111111111111111111111100000000000000000000000000000000", 2327, ), ( "1000000000000000000000000000000000000000000000000000000111111111", 2320, ), ( "1000000000000000000000000000000000000000000000000000000000000011", 2318, ), ]; let sample_median = (-4611686018427387904, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.608396021125303e18), standard_deviation: NiceFloat(4.4270184647985106e18), skewness: NiceFloat(-0.0014267894129673469), excess_kurtosis: NiceFloat(-1.9430528242638716), }; striped_random_negative_signeds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 2 let values = &[ "1001100110001101010100101101001000001100001110101111001000000001", "1000111011011100111110111000010111001101001101010010111011001100", "1011110000010100111000110001101100111001001010101110001000100000", "1110010001100111101011100111111100001001110001100001001000000011", "1000001100110011001011000001001111001010100010110100011010010001", "1111000101110010000110100101010100100111001100100001101010011011", "1000010000011110001100010001010101101101100100000010011101111010", "1001110110110110011010011011010000111001101110110010001101011110", "1011010010000001101100111000010011100101110010101101001100110000", "1110000010001000110001011100111001101110010001111000110001111001", "1100011101111011001001101101011100000110001110100111011011011111", "1111101111100000110000001010001001101011110011110110100010110010", "1001010001010011101001011011111100101110000001010101000111100001", "1011110011011100110101011110010001110100010111001010000100011101", "1110001001100111101011111000100111101011110111101110011010100111", "1000001111011101101101011111011010011011001011010001101011100101", "1011111101110101010010000100011110100110100000110100101000110111", "1010101011010100000101011100111011000001101010001000101111111010", "1000110000111110001111000001110011101110100001101011111010100110", "1001101010111111111000111001111000111110001111110100101000001111", ]; let common_values = &[ ( "1111111111111111111101100100101101000010000101001100011100001011", 1, ), ( "1111111111111111111101010010001100000001111011100011001110010101", 1, ), ( "1111111111111111111101000101011100111011001010001100011011001010", 1, ), ( "1111111111111111111100101001000100000101110101000111010111100101", 1, ), ( "1111111111111111111100000101111010110010101111000000001111000010", 1, ), ( "1111111111111111111010001000001010110110111101111011110111000001", 1, ), ( "1111111111111111110111101001011000111000100110110000000111010011", 1, ), ( "1111111111111111110110001001110101000111010110110110001100010111", 1, ), ( "1111111111111111110101100100101011001110101010101111101001011101", 1, ), ( "1111111111111111101110111110101110101010000001001011010001101111", 1, ), ]; let sample_median = (-4607307127481905067, Some(-4607304507984009164)); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.6086823879191747e18), standard_deviation: NiceFloat(2.66222507998862e18), skewness: NiceFloat(-0.0006757801147528804), excess_kurtosis: NiceFloat(-1.1997523258037708), }; striped_random_negative_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 33/32 let values = &[ "1010101010101010101010101101010101010101010101010101010101010101", "1010101010101010100010101010010101101010101010101011010101011010", "1010101010010101011010101010101010101101010101010101010101010101", "1101010101010101010101101010101010101010101010101010101010101010", "1010101010101010101010101011010101010101001010010101001010101010", "1101010101010101010101010101010101010100101010010101010110101010", "1010101010101010101010101010101010101010101010101010110101010101", "1010101010101010101010010101010101010101010101010101010101010101", "1010101010010101010101010101010101010101010101010101010101010101", "1101010101100101010101010101010101010101010101010101010010101010", "1101010101010101010101010101010101011001010101010101101010101010", "1101101010101010011010101010101010101010101010101010101010101010", "1010101001010101010101011010101010101010101010101010101010101010", "1010101010101010101011010010010110101010101010101010101010101010", "1101010101010101010110101010101010101010101010010101010101010101", "1010101010101010101010101010101010101010101010101010101010101010", "1010101010101010101010101010101010101010101010101011010101010101", "1010101010101010101010101010101010101010101101010101010101010101", "1010101010101010101011011010100101010101001010101010101010101010", "1010101010101010101010101010101011010101010101010101010101010101", ]; let common_values = &[ ( "1101010101010101010101010101010101010101010101010101010101010101", 74299, ), ( "1010101010101010101010101010101010101010101010101010101010101010", 74072, ), ( "1101010101010101010101010010101010101010101010101010101010101010", 2429, ), ( "1101010101011010101010101010101010101010101010101010101010101010", 2419, ), ( "1101010101010101010101010101010101010101010101010101010101011010", 2419, ), ( "1101010101010101010101001010101010101010101010101010101010101010", 2411, ), ( "1101010101010101010101010101010101010101010101010010101010101010", 2393, ), ( "1101010101001010101010101010101010101010101010101010101010101010", 2390, ), ( "1010101010101010101010101010101010101010101010101010101010100101", 2389, ), ( "1010101010101010101010101010101001010101010101010101010101010101", 2389, ), ]; let sample_median = (-3942150873824974166, Some(-3942150873824971435)); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.610217758608903e18), standard_deviation: NiceFloat(1.5991405421620288e18), skewness: NiceFloat(-0.0019511120341977582), excess_kurtosis: NiceFloat(-1.7372862317601778), }; striped_random_negative_signeds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_negative_signeds_fail_helper() { assert_panic!(striped_random_negative_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_negative_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_negative_signeds_fail() { apply_fn_to_signeds!(striped_random_negative_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_nonzero_signeds.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_nonzero_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_nonzero_signeds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_nonzero_signeds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_nonzero_signeds() { // i8, m = 4 let values = &[ "1100001", "1000000", "1100000", "10000111", "1111", "10000001", "1111000", "100011", "111101", "11111100", "11111111", "11100001", "1", "101111", "10111000", "111111", "1101100", "1111110", "111100", "1", ]; let common_values = &[ ("1111111", 46633), ("11111111", 46592), ("10000000", 46404), ("11000000", 15765), ("11111100", 15719), ("10011111", 15717), ("111111", 15661), ("1111100", 15658), ("11111", 15657), ("1111", 15644), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.47311899999999013), standard_deviation: NiceFloat(81.62164912267556), skewness: NiceFloat(0.0008208424524866476), excess_kurtosis: NiceFloat(-1.1132122689325452), }; striped_random_nonzero_signeds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 2 let values = &[ "1110111", "1000010", "1010011", "10011100", "10110", "10000100", "1100001", "100110", "11101", "11100110", "11100000", "11111010", "11011", "101100", "10101011", "10110", "1011110", "1110101", "10001", "10100", ]; let common_values = &[ ("11010110", 4078), ("1100000", 4059), ("1100100", 4058), ("11000100", 4050), ("11100100", 4049), ("11101011", 4048), ("10011000", 4048), ("11111110", 4044), ("1010111", 4040), ("11110100", 4039), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5178119999999826), standard_deviation: NiceFloat(74.01861596576973), skewness: NiceFloat(0.000735155416319748), excess_kurtosis: NiceFloat(-1.2058601704389202), }; striped_random_nonzero_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 5/4 let values = &[ "1010100", "1001010", "1101101", "10010101", "110101", "10101010", "1000010", "101001", "110110", "11011101", "11011001", "11110101", "1010", "10101", "10110101", "111010", "1101001", "1101010", "100110", "101001", ]; let common_values = &[ ("11010101", 66214), ("10101010", 65618), ("1010101", 65486), ("101010", 65185), ("10100101", 16584), ("11010010", 16518), ("1011010", 16486), ("1101010", 16481), ("110101", 16475), ("10010101", 16471), ]; let sample_median = (-5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5124420000000011), standard_deviation: NiceFloat(69.49222913654884), skewness: NiceFloat(0.0016761512574253166), excess_kurtosis: NiceFloat(-1.4630127076308237), }; striped_random_nonzero_signeds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 32 let values = &[ "111000000000000000000000000000001111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111100000000000000000000000000011", "1000000000000000011111111111111111111111111111111111111111111111", "111111111111111111111111111111100000000000000000000000000", "1000000000000000000000000000000001111111000000000000000000011111", "111111111111111111111000000000000000000011111111111111111111111", "111111111111111000000000010000001111111111", "1000000000000000", "1111111111001111111111111111111111111111111111111111111110000000", "1111111111111111111111111111111111111111111111111111111111111111", "1100000000000000000000000000000000000000000000000000000000000000", "11111111111111111111111111111000000000000000001111111", "111111111111111111111111111111111111111111111111111111", "1000000000000001111111100000011111111111111111111111111111000000", "111111111111111111000", "111111110000001000000000000000000000000000000000000000000000000", "111111111111111111111111111111111111111100000000000001111111111", "111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111", ]; let common_values = &[ ( "1111111111111111111111111111111111111111111111111111111111111111", 36249, ), ( "1000000000000000000000000000000000000000000000000000000000000000", 35940, ), ( "111111111111111111111111111111111111111111111111111111111111111", 35831, ), ( "111111111111111111111111111111111111111111111111111000000000000", 1244, ), ( "1000000000000000000000000000000000000000111111111111111111111111", 1243, ), ( "111111111111111111100000000000000000000000000000000000000000000", 1236, ), ( "1000000000000000000000000000000000000001111111111111111111111111", 1231, ), ( "111111111111111111111110000000000000000000000000000000000000000", 1229, ), ( "1000000000000000000000000000000111111111111111111111111111111111", 1228, ), ( "1111111111111111111111111111111111000000000000000000000000000000", 1226, ), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(4290456766772419.0), standard_deviation: NiceFloat(6.503574909103916e18), skewness: NiceFloat(-0.0008033470716056729), excess_kurtosis: NiceFloat(-1.0564362595467798), }; striped_random_nonzero_signeds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 2 let values = &[ "111011100001010110001110001011000010001111010011001110110011001", "111111110100110110100110101000101101000011101011011100101000100", "110111111101001101101001110111101010101111111011100100000100111", "1000110000101001011011100011110101111000101110000001001010011110", "1111111001111100000101110010111000110111101100000010010000110", "1011101011101000100100010110110000010100100110010000101111101011", "110111111011000111010100010011001001010111010010000110110001011", "1110111111011000100010000110111111011111000110110100101011011", "11001110010100010000000011111011101000011001110000011101001011", "1111111000011000100101100000001111001100100011111000000011001110", "1101011111111010011011100100011000000100001100111000011000011010", "1101101001110110010110110101111101111010001011011100001000011111", "1101110000100110011011100110000000011010100111111110001010", "1011001000101100011000110011000001110001101010111010010000100", "1000111011101001000111101001100000111100100111100111001010111100", "11101000100000101100011100101110111000100010100001001101110000", "110100010100010101000011000111011101000100100100011111010000011", "100000011111110101100111000100100111101101110010011101110110001", "10100101100000110010110100110100011010011101101100010", "10111110011011000011000011001010101000101001100001001000000110", ]; let common_values = &[ ("1000001000001111111111101100101100110101100101", 1), ("1101011110010101110000100010110110000010001101", 1), ("1101111000110100001101000000011011000101001001", 1), ("1111000011101100001000100110000111101110100011", 1), ("10011000001111100110100111011000010001100001111", 1), ( "1111111111111111101111101000011101000100001010110001100101110110", 1, ), ( "1111111111111111101011111111000001110100011010010001100100101000", 1, ), ("11010000001000101001101001110011011011010000011", 1), ("11101111110000011100000111100110000000001011010", 1), ("100011011110110010100010110100001001100100001000", 1), ]; let sample_median = (-8123231271792388, Some(-8096687505746509)); let sample_moment_stats = MomentStats { mean: NiceFloat(91581052023966.92), standard_deviation: NiceFloat(5.31973124263762e18), skewness: NiceFloat(0.0012453230455855707), excess_kurtosis: NiceFloat(-1.1981323295909574), }; striped_random_nonzero_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 33/32 let values = &[ "101010100101010101010101010101010101010101010101010101010101010", "101010101010101010101010101010110101010101010101010101010101010", "101010100101010101010101010101010101010101010101010101010101010", "1010101010010101010101010101010101010101010101010101010101010110", "11010101010101010101010101010101010101010101010101010101011010", "1010101010101010101010101011010100101010101010101010100101010101", "101010110101010101010101010101010101010101010101010101010101010", "10101010101010101010101001010101010101010101010101010101010101", "10101010101010101010101010101010101010101010101001101010101010", "1101010101010101010101010101010101010011010101101010101010101010", "1101010101010101011010101010101010101010101010101010101010101010", "1101010101010101010101010101010101010101010101010101010101010101", "10101010101010101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101010101010101010", "1010101010101010101010101010101010101010101010101011010101010101", "10100101010101010101010101010101010101010101010101010101010101", "101001010101010101010101010101010101010101010101010101010101101", "101010101010101010111010101010110101010101010101010101010101010", "10101010101101010101010101010101010101010101010101010101010101", "10101010101010101010101101010010101010110101010101101010101010", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 37342, ), ( "10101010101010101010101010101010101010101010101010101010101010", 37241, ), ( "1101010101010101010101010101010101010101010101010101010101010101", 37189, ), ( "1010101010101010101010101010101010101010101010101010101010101010", 37109, ), ( "1010101010101010101010101010101010101001010101010101010101010101", 1241, ), ( "1101010101010101010101010101010101010110101010101010101010101010", 1239, ), ( "10101010101010101010101010101010101010101010101010101010100101", 1235, ), ( "1010101010101010101010101010101010101011010101010101010101010101", 1233, ), ( "1101011010101010101010101010101010101010101010101010101010101010", 1231, ), ( "1101010101010101010101010101010101010101010101010101010101010010", 1227, ), ]; let sample_median = (-1489184412743849302, Some(-1489184412721829206)); let sample_moment_stats = MomentStats { mean: NiceFloat(-2366723010422570.0), standard_deviation: NiceFloat(4.878981868385203e18), skewness: NiceFloat(0.0014056588570288651), excess_kurtosis: NiceFloat(-1.6132504884076841), }; striped_random_nonzero_signeds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_nonzero_signeds_fail_helper() { assert_panic!(striped_random_nonzero_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_nonzero_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_nonzero_signeds_fail() { apply_fn_to_signeds!(striped_random_nonzero_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_positive_signeds.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_positive_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_positive_signeds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_positive_signeds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_positive_signeds() { // i8, m = 4 let values = &[ "101100", "110000", "1111100", "1111", "1111110", "111", "11101", "1100000", "1111111", "1100000", "10", "1000011", "111111", "1", "1111", "1", "1111111", "1111111", "111111", "101", ]; let common_values = &[ ("1111111", 97287), ("1111000", 32824), ("11111", 32718), ("1111110", 32708), ("1000000", 32633), ("1100000", 32625), ("111111", 32619), ("1110000", 32582), ("1111", 32563), ("111", 32542), ]; let sample_median = (67, None); let sample_moment_stats = MomentStats { mean: NiceFloat(69.74119900000126), standard_deviation: NiceFloat(45.39301881973154), skewness: NiceFloat(-0.14669679109094702), excess_kurtosis: NiceFloat(-1.4928149640100892), }; striped_random_positive_signeds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 2 let values = &[ "11001", "11100", "101010", "1001011", "101101", "1111100", "111100", "10100", "1101", "1111111", "1100011", "1101101", "1100", "100", "1100001", "100011", "110100", "110101", "110100", "10011", ]; let common_values = &[ ("11010", 8196), ("1111", 8123), ("1001101", 8065), ("11011", 8056), ("1010101", 8053), ("1110111", 8043), ("1010100", 8019), ("111", 8015), ("101100", 8003), ("1111010", 8002), ]; let sample_median = (64, None); let sample_moment_stats = MomentStats { mean: NiceFloat(64.04460499999882), standard_deviation: NiceFloat(36.65530083091763), skewness: NiceFloat(-0.0005788615669167611), excess_kurtosis: NiceFloat(-1.2009597413001147), }; striped_random_positive_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 5/4 let values = &[ "101001", "100101", "100110", "1101001", "101101", "1010101", "111010", "101010", "10110", "1010101", "1001000", "1001011", "1000", "11100", "1111010", "101101", "110101", "101010", "100101", "100010", ]; let common_values = &[ ("101010", 131218), ("1010101", 131204), ("1001010", 33121), ("1011010", 33074), ("10101", 32947), ("100101", 32868), ("1010010", 32851), ("101011", 32817), ("101001", 32765), ("110101", 32762), ]; let sample_median = (65, None); let sample_moment_stats = MomentStats { mean: NiceFloat(63.51510099999881), standard_deviation: NiceFloat(27.102051665528496), skewness: NiceFloat(-0.0016063884661944201), excess_kurtosis: NiceFloat(-1.1009870884906956), }; striped_random_positive_signeds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 32 let values = &[ "11111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111110000000000000000000000000000000000000", "111111111111111111111111111111111111111111111111111111111", "111111111000000000000000000000000000000000000001100000000111111", "11111111111111100000", "11111111111111111", "111111111111", "111111111111111111111111111111111111111111111111111100000000000", "111111111111100000000000000000000000000000000000000000000000000", "111111111000000000000000000000000000000000000000000000000000000", "1111111111111111111111111111100000000000000", "1000000011111111111111111111", "111111000000000000000111111111111111111111111111111111111111111", "11111111111100000000000000000000000000000000000000", "111111111111111111111110000000000000000001111111", "1111111111111111111111111111111111111111111111111111111111111", "1111111", "111111111111111111100000000000000000000000000000000000000000000", ]; let common_values = &[ ( "111111111111111111111111111111111111111111111111111111111111111", 75198, ), ( "111111111111111111111111111111111111111111111111111111111111000", 2569, ), ( "11111111111111111111111111111111111111111111111111111111111", 2529, ), ( "111111111111111100000000000000000000000000000000000000000000000", 2513, ), ("11111111111111111111111", 2507), ("111111111", 2503), ( "100000000000000000000000000000000000000000000000000000000000000", 2502, ), ( "111111111111111110000000000000000000000000000000000000000000000", 2501, ), ("111111111111111111111111111", 2500), ( "111111111110000000000000000000000000000000000000000000000000000", 2491, ), ]; let sample_median = (8070450532250024960, Some(8070450532250024967)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.959974637374284e18), standard_deviation: NiceFloat(4.3991106930140626e18), skewness: NiceFloat(-0.15099815742030892), excess_kurtosis: NiceFloat(-1.9150786144831098), }; striped_random_positive_signeds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 2 let values = &[ "1100110001101010100101101001000001100001110101111001000000001", "111011011100111110111000010111001101001101010010111011001100", "11110000010100111000110001101100111001001010101110001000100000", "110010001100111101011100111111100001001110001100001001000000011", "1100110011001011000001001111001010100010110100011010010001", "111000101110010000110100101010100100111001100100001101010011011", "10000011110001100010001010101101101100100000010011101111010", "1110110110110011010011011010000111001101110110010001101011110", "11010010000001101100111000010011100101110010101101001100110000", "110000010001000110001011100111001101110010001111000110001111001", "100011101111011001001101101011100000110001110100111011011011111", "111101111100000110000001010001001101011110011110110100010110010", "1010001010011101001011011111100101110000001010101000111100001", "11110011011100110101011110010001110100010111001010000100011101", "110001001100111101011111000100111101011110111101110011010100111", "1111011101101101011111011010011011001011010001101011100101", "11111101110101010010000100011110100110100000110100101000110111", "10101011010100000101011100111011000001101010001000101111111010", "110000111110001111000001110011101110100001101011111010100110", "1101010111111111000111001111000111110001111110100101000001111", ]; let common_values = &[ ("10101000110110101100110011001101011011101", 1), ("1110100010100111110111100000011111000010100", 1), ("10011111100110010100000010001100001001111011", 1), ("10111110110011101010110111100010100101101100", 1), ("110101001100100110010011010000011100100111011", 1), ("1001000111011010110011001111101001111101110011", 1), ("1010101100111011110111011011011100011101010101", 1), ("1100110000110110000100011110000110101010110010", 1), ("1100110011000110101101111111111110111011101001", 1), ("1101011001000111111110011010000001001001000110", 1), ]; let sample_median = (4616064909372870741, Some(4616067528870766644)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.614689648935556e18), standard_deviation: NiceFloat(2.6622250799886193e18), skewness: NiceFloat(-0.0006757801147527129), excess_kurtosis: NiceFloat(-1.199752325803772), }; striped_random_positive_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 33/32 let values = &[ "10101010101010101010101101010101010101010101010101010101010101", "10101010101010100010101010010101101010101010101011010101011010", "10101010010101011010101010101010101101010101010101010101010101", "101010101010101010101101010101010101010101010101010101010101010", "10101010101010101010101011010101010101001010010101001010101010", "101010101010101010101010101010101010100101010010101010110101010", "10101010101010101010101010101010101010101010101010110101010101", "10101010101010101010010101010101010101010101010101010101010101", "10101010010101010101010101010101010101010101010101010101010101", "101010101100101010101010101010101010101010101010101010010101010", "101010101010101010101010101010101011001010101010101101010101010", "101101010101010011010101010101010101010101010101010101010101010", "10101001010101010101011010101010101010101010101010101010101010", "10101010101010101011010010010110101010101010101010101010101010", "101010101010101010110101010101010101010101010010101010101010101", "10101010101010101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101011010101010101", "10101010101010101010101010101010101010101101010101010101010101", "10101010101010101011011010100101010101001010101010101010101010", "10101010101010101010101010101011010101010101010101010101010101", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 74299, ), ( "10101010101010101010101010101010101010101010101010101010101010", 74072, ), ( "101010101010101010101010010101010101010101010101010101010101010", 2429, ), ( "101010101010101010101010101010101010101010101010101010101011010", 2419, ), ( "101010101011010101010101010101010101010101010101010101010101010", 2419, ), ( "101010101010101010101001010101010101010101010101010101010101010", 2411, ), ( "101010101010101010101010101010101010101010101010010101010101010", 2393, ), ( "101010101001010101010101010101010101010101010101010101010101010", 2390, ), ( "10101010101010101010101010101001010101010101010101010101010101", 2389, ), ( "10101010101010101010101010101010101010101010101010101010100101", 2389, ), ]; let sample_median = (5281221163029801642, Some(5281221163029804373)); let sample_moment_stats = MomentStats { mean: NiceFloat(4.613154278246113e18), standard_deviation: NiceFloat(1.599140542162029e18), skewness: NiceFloat(-0.0019511120341977268), excess_kurtosis: NiceFloat(-1.7372862317601716), }; striped_random_positive_signeds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_positive_signeds_fail_helper() { assert_panic!(striped_random_positive_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_positive_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_positive_signeds_fail() { apply_fn_to_signeds!(striped_random_positive_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_positive_unsigneds.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_positive_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_positive_unsigneds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_positive_unsigneds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_positive_unsigneds() { // u8, m = 4 let values = &[ "1", "1001100", "1111111", "11000011", "10000000", "1111", "1110110", "11111000", "11111111", "11111101", "1111001", "11110000", "11", "1111111", "1", "11010011", "10000111", "111", "1111001", "10110000", ]; let common_values = &[ ("11111111", 71334), ("11110000", 24018), ("11100000", 24001), ("11111", 23981), ("11111110", 23965), ("111111", 23924), ("11111100", 23919), ("1111", 23888), ("11", 23829), ("111", 23815), ]; let sample_median = (131, None); let sample_moment_stats = MomentStats { mean: NiceFloat(136.63338500000273), standard_deviation: NiceFloat(92.21339578256648), skewness: NiceFloat(-0.10902316932402645), excess_kurtosis: NiceFloat(-1.5167077828673536), }; striped_random_positive_unsigneds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, m = 2 let values = &[ "110011", "1110010", "1010110", "10110100", "1000001", "11000011", "101000", "110111", "11", "11000100", "10111001", "11111011", "111101", "1110011", "10100110", "1010010", "1110110", "110011", "11111", "1010011", ]; let common_values = &[ ("1000100", 4120), ("10100100", 4099), ("11100100", 4077), ("10100010", 4054), ("11011010", 4054), ("1010100", 4051), ("10010010", 4044), ("10001011", 4041), ("11100011", 4032), ("10110", 4028), ]; let sample_median = (128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(128.1168509999991), standard_deviation: NiceFloat(73.48547444875528), skewness: NiceFloat(-0.0006394544560910719), excess_kurtosis: NiceFloat(-1.1968013589588233), }; striped_random_positive_unsigneds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, m = 5/4 let values = &[ "1010010", "1101010", "110010", "10010100", "1010101", "10111010", "1010100", "1011010", "1010110", "10001101", "10000100", "11100011", "1010", "1001011", "10101010", "1010110", "1010001", "1010100", "1010101", "1010101", ]; let common_values = &[ ("1010101", 105176), ("10101010", 104735), ("10101101", 26535), ("11010101", 26470), ("1010010", 26421), ("101010", 26383), ("1001010", 26310), ("10010101", 26290), ("10110101", 26230), ("10101001", 26220), ]; let sample_median = (130, None); let sample_moment_stats = MomentStats { mean: NiceFloat(127.53545100000133), standard_deviation: NiceFloat(54.22647275765827), skewness: NiceFloat(-0.0014575581250140023), excess_kurtosis: NiceFloat(-1.1009413456646224), }; striped_random_positive_unsigneds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 32 let values = &[ "111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111", "1111111111111111111111100000000000000000000000000000000000000000", "11111111111111111111111111111111111111111111111111111111111111", "1111000000000000000000000000000000000000001100000000111111111111", "111111111111111000000000000", "1111111111111111111111111", "111111111111111111111", "1111111111111111111111111111111111111111111000000000000000000000", "1110000000000000000000000000000000000000000000000000000000000111", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111000000000000000000000000000", "100000001111111111111111111111111000000000", "1111111000000000000000000000000000000000000000000000000000000000", "1111", "1111111111111111111111111111111111111111111111111111000", "1111111111111111110000000011111111111111111", "111111111111111111111111100", "1111111111111111111111111111111111111111111111111111111111111111", ]; let common_values = &[ ( "1111111111111111111111111111111111111111111111111111111111111111", 72952, ), ("111111111111111111111111111111", 2474), ( "1111111111111111111111111110000000000000000000000000000000000000", 2456, ), ("111111111", 2437), ("11111111111111111111111111111111111", 2417), ( "1111111111111111111111111111111111111111111111100000000000000000", 2414, ), ( "1111111000000000000000000000000000000000000000000000000000000000", 2410, ), ("111111111111111111111111111111111111", 2408), ("111111111111111111111111111111111111111111111111111", 2404), ( "1111111111111111111111111111111111111111111111111111111111111100", 2399, ), ]; let sample_median = (16140901064496103427, Some(16140901064496103487)); let sample_moment_stats = MomentStats { mean: NiceFloat(9.903368730390014e18), standard_deviation: NiceFloat(8.801310214580938e18), skewness: NiceFloat(-0.14740544458518143), excess_kurtosis: NiceFloat(-1.916675806061043), }; striped_random_positive_unsigneds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 2 let values = &[ "11001100011010101001011010010000011000011101011110010000000011", "11101101110011111011100001011100110100110101001011101100110011", "1111101011000111001110010011000110110101010001110111011111100", "1011100110000101000110000000111101100011100111101101111111000000", "110011001100101100000100111100101010001011010001101001000111000", "1010001101111001011010101011011000110011011110010101100100000100", "111100011000100010101011011011001000000100111011110100111011", "100100110010110010010111100011001000100110111001010000100101101", "1101100111000010011100101110010101101001100110000011111011", "1101110011101000110001100100011011100001110011100001101110001000", "1101100100110110101110000011000111010011101101101111111101111100", "1111001111110101110110010100001100001001011101001101101011101011", "111010010110111111001011100000010101010001111000010000110010001", "11010101111001000111010001011100101000010001110110001001100111", "1101011111000100111101011110111101110011010100111111100001000100", "100101000001001011001001101001011100101000110101111110111010101", "110111101110000101100101111100101101011100100010101011010100000", "101011100111011000001101010001000101111111010001100001111100011", "1111100011000100010111100101000001010110011001010100000000011", "11100111100011111000111111010010100000111110101001010111011001", ]; let common_values = &[ ("11011011101110000001110101101011110010111101", 1), ("111100000110100100110100100001100010110000010", 1), ("1011110101111010110111100110111101111101111011", 1), ("1110100010111110000100101010110100101101110111", 1), ("10111011110000001110101010110111111001011011100", 1), ("11000001010110011001100110101011001100000111111", 1), ("100100100011101001001000001010010111100010110100", 1), ("100110100101010111001000010010100111110111010110", 1), ("110110101100010110011100011100110111001111000000", 1), ("111001100010011111010011111010110100101110001000", 1), ]; let sample_median = (9232300347074497346, Some(9232359143244030439)); let sample_moment_stats = MomentStats { mean: NiceFloat(9.22650235650532e18), standard_deviation: NiceFloat(5.325785817923598e18), skewness: NiceFloat(-0.0012562071401776408), excess_kurtosis: NiceFloat(-1.1996143045434082), }; striped_random_positive_unsigneds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 33/32 let values = &[ "101010101010101010101011010101010101010101010101010101010101010", "101010101010101110101010110101001010101010101010010101010010101", "101010010101011010101010101010101101010101010101010101010101010", "1010101010101010100101010101010101010101010101010101010101010101", "101010101010101010101101010101010100101001010100101010101010101", "1010101010101010101010101010101011010101101010101001010101010101", "101010101010101010101010101010101010101010101101010101010101010", "101010101010110101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101010101010101011", "1001010101010101010101010101010101010101010100101010101010101010", "1010101010101010101010101100101010101010110101010101010010101010", "1010011010101010101010101010101010101010101010101010101010010101", "101010101001010101010101010101010101010101010101010101010101010", "101010010110110100101010101010101010101010101010101010101010101", "1010110101010101010101010101010010101010101010101010101010101010", "101010101010101010101010101010101010101010101010101010101010101", "101010101010101010101010101010101101010101010101010101010101010", "101010101010101010101010010101010101010101010101010101010101010", "110110101001010101010010101010101010101010101010101010101010101", "101010101010010101010101010101010101010101010101010101010101010", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 72208, ), ( "1010101010101010101010101010101010101010101010101010101010101010", 71633, ), ( "1010101010101010101010101010101010101010101010101010101010101001", 2387, ), ( "101010101010101010101010101010101010110101010101010101010101010", 2371, ), ( "101010101010101010101001010101010101010101010101010101010101010", 2350, ), ( "1010101010101010101010101010101010101010101010101010101010100101", 2343, ), ( "1010101010101010101010101010101001010101010101010101010101010101", 2321, ), ( "101010101010101010101010101010101010101001010101010101010101010", 2317, ), ( "1010101010101010101010101010101010101010100101010101010101010101", 2316, ), ( "1010101010101010101101010101010101010101010101010101010101010101", 2314, ), ]; let sample_median = (10184128240689698133, Some(10184139957360479594)); let sample_moment_stats = MomentStats { mean: NiceFloat(9.22742898450889e18), standard_deviation: NiceFloat(3.1984799302251884e18), skewness: NiceFloat(-0.0008313832988426654), excess_kurtosis: NiceFloat(-1.7364190763714287), }; striped_random_positive_unsigneds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_positive_unsigneds_fail_helper() { assert_panic!(striped_random_positive_unsigneds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_positive_unsigneds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_positive_unsigneds_fail() { apply_fn_to_unsigneds!(striped_random_positive_unsigneds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_signed_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_signed_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_signed_inclusive_range_helper< U: PrimitiveUnsigned + WrappingFrom, S: CheckedToF64 + PrimitiveSigned + WrappingFrom, >( a: S, b: S, m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (S, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_signed_inclusive_range::( EXAMPLE_SEED, a, b, m_numerator, m_denominator, ); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_signed_inclusive_range() { // i16, 50, 200, m = 4 let values = &[ "110010", "11000000", "10100110", "110111", "111111", "11001000", "1111000", "111111", "110010", "1111111", "111110", "11000001", "111101", "110111", "11001000", "110011", "111111", "11000011", "11000000", "11000000", ]; let common_values = &[ ("11001000", 187162), ("11000000", 79165), ("111111", 78685), ("110010", 70343), ("110011", 70101), ("110111", 26718), ("111100", 26467), ("111110", 26443), ("111000", 26309), ("11000001", 26222), ]; let sample_median = (128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(126.78841600000145), standard_deviation: NiceFloat(62.97286483710745), skewness: NiceFloat(-0.01241704115437865), excess_kurtosis: NiceFloat(-1.7551228249647437), }; striped_random_signed_inclusive_range_helper::( 50, 200, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i16, -200, -50, m = 4 let values = &[ "1111111111001110", "1111111101000000", "1111111101011010", "1111111111001001", "1111111111000001", "1111111100111000", "1111111110001000", "1111111111000001", "1111111111001110", "1111111110000001", "1111111111000010", "1111111100111111", "1111111111000011", "1111111111001001", "1111111100111000", "1111111111001101", "1111111111000001", "1111111100111101", "1111111101000000", "1111111101000000", ]; let common_values = &[ ("1111111100111000", 187162), ("1111111101000000", 79165), ("1111111111000001", 78685), ("1111111111001110", 70343), ("1111111111001101", 70101), ("1111111111001001", 26718), ("1111111111000100", 26467), ("1111111111000010", 26443), ("1111111111001000", 26309), ("1111111100111111", 26222), ]; let sample_median = (-128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-126.78841600000145), standard_deviation: NiceFloat(62.97286483710745), skewness: NiceFloat(0.01241704115437865), excess_kurtosis: NiceFloat(-1.7551228249647437), }; striped_random_signed_inclusive_range_helper::( -200, -50, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i16, -50, 200, m = 4 let values = &[ "1111111111001110", "1111111111001111", "11000111", "11111", "1111111111111111", "11000011", "1000000", "11000001", "1111111", "11000011", "11000100", "1111111111111111", "11001000", "1111111111010010", "1111111111110100", "1111111111011111", "1111111111111111", "1111111111001111", "1111111111111111", "1111111111010000", ]; let common_values = &[ ("1111111111001110", 93920), ("11001000", 93547), ("1111111111111111", 79262), ("1111111111010000", 70793), ("11000000", 39521), ("0", 33351), ("1111111111001111", 23264), ("1111111111111001", 19879), ("1111111111100000", 19842), ("1111111111110001", 19780), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(42.632988000001404), standard_deviation: NiceFloat(91.45288785939469), skewness: NiceFloat(0.7466366203634324), excess_kurtosis: NiceFloat(-1.0394231672402725), }; striped_random_signed_inclusive_range_helper::( -50, 200, 4, 1, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_signed_inclusive_range_fail_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { assert_panic!(striped_random_signed_inclusive_range::( EXAMPLE_SEED, S::TWO, S::ONE, 5, 1, )); assert_panic!(striped_random_signed_inclusive_range::( EXAMPLE_SEED, S::NEGATIVE_ONE, S::from(-2i8), 5, 1, )); assert_panic!(striped_random_signed_inclusive_range::( EXAMPLE_SEED, S::ONE, S::TWO, 1, 1, )); } #[test] fn striped_random_signed_inclusive_range_fail() { apply_fn_to_unsigned_signed_pairs!(striped_random_signed_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_signed_range.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_signed_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_signed_range_helper< U: PrimitiveUnsigned + WrappingFrom, S: CheckedToF64 + PrimitiveSigned + WrappingFrom, >( a: S, b: S, m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (S, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_signed_range::(EXAMPLE_SEED, a, b, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_signed_range() { // i16, 50, 201, m = 4 let values = &[ "110010", "11000000", "10100110", "110111", "111111", "11001000", "1111000", "111111", "110010", "1111111", "111110", "11000001", "111101", "110111", "11001000", "110011", "111111", "11000011", "11000000", "11000000", ]; let common_values = &[ ("11001000", 187162), ("11000000", 79165), ("111111", 78685), ("110010", 70343), ("110011", 70101), ("110111", 26718), ("111100", 26467), ("111110", 26443), ("111000", 26309), ("11000001", 26222), ]; let sample_median = (128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(126.78841600000145), standard_deviation: NiceFloat(62.97286483710745), skewness: NiceFloat(-0.01241704115437865), excess_kurtosis: NiceFloat(-1.7551228249647437), }; striped_random_signed_range_helper::( 50, 201, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i16, -200, -49, m = 4 let values = &[ "1111111111001110", "1111111101000000", "1111111101011010", "1111111111001001", "1111111111000001", "1111111100111000", "1111111110001000", "1111111111000001", "1111111111001110", "1111111110000001", "1111111111000010", "1111111100111111", "1111111111000011", "1111111111001001", "1111111100111000", "1111111111001101", "1111111111000001", "1111111100111101", "1111111101000000", "1111111101000000", ]; let common_values = &[ ("1111111100111000", 187162), ("1111111101000000", 79165), ("1111111111000001", 78685), ("1111111111001110", 70343), ("1111111111001101", 70101), ("1111111111001001", 26718), ("1111111111000100", 26467), ("1111111111000010", 26443), ("1111111111001000", 26309), ("1111111100111111", 26222), ]; let sample_median = (-128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-126.78841600000145), standard_deviation: NiceFloat(62.97286483710745), skewness: NiceFloat(0.01241704115437865), excess_kurtosis: NiceFloat(-1.7551228249647437), }; striped_random_signed_range_helper::( -200, -49, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i16, -50, 201, m = 4 let values = &[ "1111111111001110", "1111111111001111", "11000111", "11111", "1111111111111111", "11000011", "1000000", "11000001", "1111111", "11000011", "11000100", "1111111111111111", "11001000", "1111111111010010", "1111111111110100", "1111111111011111", "1111111111111111", "1111111111001111", "1111111111111111", "1111111111010000", ]; let common_values = &[ ("1111111111001110", 93920), ("11001000", 93547), ("1111111111111111", 79262), ("1111111111010000", 70793), ("11000000", 39521), ("0", 33351), ("1111111111001111", 23264), ("1111111111111001", 19879), ("1111111111100000", 19842), ("1111111111110001", 19780), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(42.632988000001404), standard_deviation: NiceFloat(91.45288785939469), skewness: NiceFloat(0.7466366203634324), excess_kurtosis: NiceFloat(-1.0394231672402725), }; striped_random_signed_range_helper::( -50, 201, 4, 1, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_signed_range_fail_helper< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { assert_panic!(striped_random_signed_range::( EXAMPLE_SEED, S::TWO, S::TWO, 5, 1, )); assert_panic!(striped_random_signed_range::( EXAMPLE_SEED, S::NEGATIVE_ONE, S::NEGATIVE_ONE, 5, 1, )); assert_panic!(striped_random_signed_range::( EXAMPLE_SEED, S::ONE, S::TWO, 1, 1, )); } #[test] fn striped_random_signed_range_fail() { apply_fn_to_unsigned_signed_pairs!(striped_random_signed_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_signeds.rs ================================================ // Copyright © 2026 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::num::basic::signeds::PrimitiveSigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_signeds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_signeds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_signeds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_signeds() { // i8, m = 4 let values = &[ "1100001", "1000000", "1100000", "10000111", "1111", "10000001", "1111000", "100011", "111101", "11111100", "11111111", "11100001", "1", "101111", "10111000", "111111", "1101100", "1111110", "111100", "1", ]; let common_values = &[ ("11111111", 44563), ("1111111", 44533), ("0", 44507), ("10000000", 44366), ("11000000", 15052), ("10011111", 15027), ("111111", 15014), ("11111100", 15003), ("1111100", 14976), ("1111", 14944), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.4694119999999954), standard_deviation: NiceFloat(79.79176643677252), skewness: NiceFloat(0.00030165230376920274), excess_kurtosis: NiceFloat(-1.0255715724465873), }; striped_random_signeds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 2 let values = &[ "1110111", "1000010", "1010011", "10011100", "10110", "10000100", "1100001", "100110", "11101", "11100110", "11100000", "11111010", "11011", "101100", "10101011", "10110", "1011110", "1110101", "10001", "10100", ]; let common_values = &[ ("11010110", 4062), ("1100000", 4043), ("1100100", 4038), ("11100100", 4031), ("11000100", 4030), ("11111110", 4027), ("111110", 4027), ("11110100", 4027), ("10011000", 4026), ("1010111", 4025), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5196209999999974), standard_deviation: NiceFloat(73.87620855668304), skewness: NiceFloat(0.0007310111483160227), excess_kurtosis: NiceFloat(-1.1989696073332987), }; striped_random_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i8, m = 5/4 let values = &[ "1010100", "1001010", "1101101", "10010101", "110101", "10101010", "1000010", "101001", "110110", "11011101", "11011001", "11110101", "1010", "10101", "10110101", "111010", "1101001", "1101010", "100110", "101001", ]; let common_values = &[ ("11010101", 66213), ("10101010", 65616), ("1010101", 65484), ("101010", 65183), ("10100101", 16584), ("11010010", 16518), ("1011010", 16486), ("1101010", 16481), ("110101", 16475), ("10010101", 16471), ]; let sample_median = (-5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.512405000000015), standard_deviation: NiceFloat(69.49166061626981), skewness: NiceFloat(0.0016729618125163213), excess_kurtosis: NiceFloat(-1.4629834926857006), }; striped_random_signeds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 32 let values = &[ "111000000000000000000000000000001111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111100000000000000000000000000011", "1000000000000000011111111111111111111111111111111111111111111111", "111111111111111111111111111111100000000000000000000000000", "1000000000000000000000000000000001111111000000000000000000011111", "111111111111111111111000000000000000000011111111111111111111111", "111111111111111000000000010000001111111111", "1000000000000000", "1111111111001111111111111111111111111111111111111111111110000000", "1111111111111111111111111111111111111111111111111111111111111111", "1100000000000000000000000000000000000000000000000000000000000000", "11111111111111111111111111111000000000000000001111111", "111111111111111111111111111111111111111111111111111111", "1000000000000001111111100000011111111111111111111111111111000000", "111111111111111111000", "111111110000001000000000000000000000000000000000000000000000000", "111111111111111111111111111111111111111100000000000001111111111", "111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111", ]; let common_values = &[ ( "1111111111111111111111111111111111111111111111111111111111111111", 35069, ), ( "1000000000000000000000000000000000000000000000000000000000000000", 34751, ), ("0", 34639), ( "111111111111111111111111111111111111111111111111111111111111111", 34560, ), ( "111111111111111111111111111111111111111111111111111000000000000", 1200, ), ( "111111111111111111100000000000000000000000000000000000000000000", 1194, ), ( "1000000000000000000000000000000000000000111111111111111111111111", 1192, ), ( "111111111111111111111110000000000000000000000000000000000000000", 1188, ), ( "1000000000000000000000000000000000000000000000000000000000000111", 1188, ), ( "1000000000000000000000000000000111111111111111111111111111111111", 1187, ), ]; let sample_median = (-1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(1478194767948927.5), standard_deviation: NiceFloat(6.390112936152263e18), skewness: NiceFloat(-0.00034103406624165104), excess_kurtosis: NiceFloat(-0.9868005073632049), }; striped_random_signeds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 2 let values = &[ "111011100001010110001110001011000010001111010011001110110011001", "111111110100110110100110101000101101000011101011011100101000100", "110111111101001101101001110111101010101111111011100100000100111", "1000110000101001011011100011110101111000101110000001001010011110", "1111111001111100000101110010111000110111101100000010010000110", "1011101011101000100100010110110000010100100110010000101111101011", "110111111011000111010100010011001001010111010010000110110001011", "1110111111011000100010000110111111011111000110110100101011011", "11001110010100010000000011111011101000011001110000011101001011", "1111111000011000100101100000001111001100100011111000000011001110", "1101011111111010011011100100011000000100001100111000011000011010", "1101101001110110010110110101111101111010001011011100001000011111", "1101110000100110011011100110000000011010100111111110001010", "1011001000101100011000110011000001110001101010111010010000100", "1000111011101001000111101001100000111100100111100111001010111100", "11101000100000101100011100101110111000100010100001001101110000", "110100010100010101000011000111011101000100100100011111010000011", "100000011111110101100111000100100111101101110010011101110110001", "10100101100000110010110100110100011010011101101100010", "10111110011011000011000011001010101000101001100001001000000110", ]; let common_values = &[ ("1000001000001111111111101100101100110101100101", 1), ("1101011110010101110000100010110110000010001101", 1), ("1101111000110100001101000000011011000101001001", 1), ("1111000011101100001000100110000111101110100011", 1), ("10011000001111100110100111011000010001100001111", 1), ( "1111111111111111101111101000011101000100001010110001100101110110", 1, ), ( "1111111111111111101011111111000001110100011010010001100100101000", 1, ), ("11010000001000101001101001110011011011010000011", 1), ("11101111110000011100000111100110000000001011010", 1), ("100011011110110010100010110100001001100100001000", 1), ]; let sample_median = (-8123231271792388, Some(-8096687505746509)); let sample_moment_stats = MomentStats { mean: NiceFloat(91581052023966.92), standard_deviation: NiceFloat(5.31973124263762e18), skewness: NiceFloat(0.0012453230455855707), excess_kurtosis: NiceFloat(-1.1981323295909574), }; striped_random_signeds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // i64, m = 33/32 let values = &[ "101010100101010101010101010101010101010101010101010101010101010", "101010101010101010101010101010110101010101010101010101010101010", "101010100101010101010101010101010101010101010101010101010101010", "1010101010010101010101010101010101010101010101010101010101010110", "11010101010101010101010101010101010101010101010101010101011010", "1010101010101010101010101011010100101010101010101010100101010101", "101010110101010101010101010101010101010101010101010101010101010", "10101010101010101010101001010101010101010101010101010101010101", "10101010101010101010101010101010101010101010101001101010101010", "1101010101010101010101010101010101010011010101101010101010101010", "1101010101010101011010101010101010101010101010101010101010101010", "1101010101010101010101010101010101010101010101010101010101010101", "10101010101010101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101010101010101010", "1010101010101010101010101010101010101010101010101011010101010101", "10100101010101010101010101010101010101010101010101010101010101", "101001010101010101010101010101010101010101010101010101010101101", "101010101010101010111010101010110101010101010101010101010101010", "10101010101101010101010101010101010101010101010101010101010101", "10101010101010101010101101010010101010110101010101101010101010", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 37342, ), ( "10101010101010101010101010101010101010101010101010101010101010", 37241, ), ( "1101010101010101010101010101010101010101010101010101010101010101", 37189, ), ( "1010101010101010101010101010101010101010101010101010101010101010", 37109, ), ( "1010101010101010101010101010101010101001010101010101010101010101", 1241, ), ( "1101010101010101010101010101010101010110101010101010101010101010", 1239, ), ( "10101010101010101010101010101010101010101010101010101010100101", 1235, ), ( "1010101010101010101010101010101010101011010101010101010101010101", 1233, ), ( "1101011010101010101010101010101010101010101010101010101010101010", 1231, ), ( "1101010101010101010101010101010101010101010101010101010101010010", 1227, ), ]; let sample_median = (-1489184412743849302, Some(-1489184412721829206)); let sample_moment_stats = MomentStats { mean: NiceFloat(-2366723010422570.0), standard_deviation: NiceFloat(4.878981868385203e18), skewness: NiceFloat(0.0014056588570288651), excess_kurtosis: NiceFloat(-1.6132504884076841), }; striped_random_signeds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_signeds_fail_helper() { assert_panic!(striped_random_signeds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_signeds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_signeds_fail() { apply_fn_to_signeds!(striped_random_signeds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_bit_chunks.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_unsigned_bit_chunks; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_unsigned_bit_chunks_helper( chunk_size: u64, m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_unsigned_bit_chunks::( EXAMPLE_SEED, chunk_size, m_numerator, m_denominator, ); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_unsigned_bit_chunks() { // u8, chunk_size = 0, m = 4 let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = (0, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_unsigned_bit_chunks_helper::( 0, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, chunk_size = 3, m = 4 let values = &[ "0", "0", "0", "101", "11", "100", "11", "11", "0", "111", "111", "100", "0", "11", "111", "0", "0", "1", "0", "0", ]; let common_values = &[ ("111", 281415), ("0", 280832), ("110", 94370), ("11", 93804), ("100", 93374), ("1", 93351), ("10", 31559), ("101", 31295), ]; let sample_median = (4, None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.5039770000000354), standard_deviation: NiceFloat(2.8721055747415143), skewness: NiceFloat(-0.0024668908296986798), excess_kurtosis: NiceFloat(-1.6474519863189017), }; striped_random_unsigned_bit_chunks_helper::( 3, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // chunk_size = 1, u8, m = 2 let values = &[ "0", "0", "0", "1", "0", "1", "0", "0", "0", "1", "1", "1", "0", "0", "1", "0", "0", "0", "0", "0", ]; let common_values = &[("1", 500454), ("0", 499546)]; let sample_median = (1, None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.500454000000004), standard_deviation: NiceFloat(0.5000000438840368), skewness: NiceFloat(-0.0018160007486136712), excess_kurtosis: NiceFloat(-1.9999967021412284), }; striped_random_unsigned_bit_chunks_helper::( 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // chunk_size = 6, u8, m = 5/4 let values = &[ "10100", "10110", "10100", "100110", "10010", "101101", "10101", "10001", "10101", "101001", "101101", "101010", "11011", "1101", "100001", "11110", "111", "101", "10110", "10010", ]; let common_values = &[ ("101010", 164180), ("10101", 164004), ("101011", 41169), ("101101", 41127), ("10010", 41114), ("100101", 40919), ("1010", 40893), ("110101", 40851), ("10110", 40844), ("101001", 40812), ]; let sample_median = (32, None); let sample_moment_stats = MomentStats { mean: NiceFloat(31.51096499999948), standard_deviation: NiceFloat(13.555827954398234), skewness: NiceFloat(-0.0016679039370573313), excess_kurtosis: NiceFloat(-1.0970963271830174), }; striped_random_unsigned_bit_chunks_helper::( 6, 5, 4, values, common_values, sample_median, sample_moment_stats, ); // chunk_size = 45, u64, m = 32 let values = &[ "11111111111", "111111111111111111111", "0", "111111111111111111111111111000000000000000000", "111111111", "111111111111111111111111111111111100000000000", "0", "1111111111111111111111111111111111", "1100000000111111111111111111111111111111", "111111111111111111100000000000000011111111111", "111111111111111111111111111111111111111100000", "111111111111111111111111111111111111111111111", "11111111111111111111111111", "1111111", "111111111111111110000000000000000000000000000", "11111111111111", "0", "11111111111111111111111111111", "11111111111111111111111111111111111111111111", "1000000011111111111111111111111110000000", ]; let common_values = &[ ("0", 123843), ("111111111111111111111111111111111111111111111", 123659), ("111111111111111100000000000000000000000000000", 4110), ("111111110000000000000000000000000000000000000", 4093), ("111111111111111111111111111111111", 4092), ("1111111111111111111111111111111111", 4081), ("11111111111111111111111111111111111111", 4078), ("1111111", 4072), ("111111111111111111111000000000000000000000000", 4057), ("111111111111111111111111111111111111111110000", 4051), ]; let sample_median = (17592186044416, None); let sample_moment_stats = MomentStats { mean: NiceFloat(17607908125347.086), standard_deviation: NiceFloat(16886338134364.322), skewness: NiceFloat(-0.0018748788166730555), excess_kurtosis: NiceFloat(-1.9429442153094645), }; striped_random_unsigned_bit_chunks_helper::( 45, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // chunk_size = 4, u64, m = 2 let values = &[ "11", "110", "11", "1100", "101", "1010", "110", "100", "101", "1101", "1111", "1100", "111", "11", "1101", "100", "1", "10", "0", "0", ]; let common_values = &[ ("1110", 62873), ("1010", 62820), ("1000", 62739), ("100", 62694), ("1001", 62689), ("110", 62619), ("1011", 62601), ("11", 62507), ("1100", 62467), ("101", 62457), ]; let sample_median = (8, None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.5009610000000775), standard_deviation: NiceFloat(4.606733799393635), skewness: NiceFloat(-0.0007329768450960305), excess_kurtosis: NiceFloat(-1.20818908668768), }; striped_random_unsigned_bit_chunks_helper::( 4, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // chunk_size = 10, u64, m = 33/32 let values = &[ "101010101", "101010101", "101011010", "1010101010", "101010101", "1010101010", "101010101", "101010101", "101010001", "1010101001", "1010110101", "1010101010", "101101010", "101101010", "1010101101", "101011010", "101010101", "101010010", "101010101", "101010101", ]; let common_values = &[ ("1010101010", 379066), ("101010101", 378152), ("1010110101", 12071), ("101011010", 12069), ("101001010", 12042), ("1011010101", 11977), ("101010110", 11960), ("1001010101", 11941), ("1010010101", 11934), ("100101010", 11903), ]; let sample_median = (565, None); let sample_moment_stats = MomentStats { mean: NiceFloat(511.639053000003), standard_deviation: NiceFloat(177.48758065877436), skewness: NiceFloat(-0.0017256448985827214), excess_kurtosis: NiceFloat(-1.734924505103183), }; striped_random_unsigned_bit_chunks_helper::( 10, 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_unsigned_bit_chunks_fail_helper() { assert_panic!(striped_random_unsigned_bit_chunks::( EXAMPLE_SEED, 4, 1, 0 )); assert_panic!(striped_random_unsigned_bit_chunks::( EXAMPLE_SEED, 4, 2, 3 )); assert_panic!(striped_random_unsigned_bit_chunks::( EXAMPLE_SEED, 200, 4, 1 )); } #[test] fn striped_random_unsigned_bit_chunks_fail() { apply_fn_to_unsigneds!(striped_random_unsigned_bit_chunks_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_unsigned_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_unsigned_inclusive_range_helper( a: T, b: T, m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_unsigned_inclusive_range::( EXAMPLE_SEED, a, b, m_numerator, m_denominator, ); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_unsigned_inclusive_range() { // u8, 5, 5, m = 4 let values = &["101"; 20]; let common_values = &[("101", 1000000)]; let sample_median = (5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_unsigned_inclusive_range_helper::( 5, 5, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, 0, 7, m = 4 let values = &[ "0", "0", "0", "101", "11", "100", "11", "11", "0", "111", "111", "100", "0", "11", "111", "0", "0", "1", "0", "0", ]; let common_values = &[ ("111", 281415), ("0", 280832), ("110", 94370), ("11", 93804), ("100", 93374), ("1", 93351), ("10", 31559), ("101", 31295), ]; let sample_median = (4, None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.5039770000000354), standard_deviation: NiceFloat(2.8721055747415143), skewness: NiceFloat(-0.0024668908296986798), excess_kurtosis: NiceFloat(-1.6474519863189017), }; striped_random_unsigned_inclusive_range_helper::( 0, 7, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, 1, 6, m = 4 let values = &[ "1", "1", "1", "110", "1", "110", "10", "11", "11", "100", "100", "110", "1", "1", "110", "1", "1", "11", "1", "1", ]; let common_values = &[ ("110", 375034), ("1", 374765), ("100", 93832), ("11", 93634), ("101", 31588), ("10", 31147), ]; let sample_median = (4, None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.5014329999999694), standard_deviation: NiceFloat(2.207774177939804), skewness: NiceFloat(-0.0014160236801414635), excess_kurtosis: NiceFloat(-1.753353488243057), }; striped_random_unsigned_inclusive_range_helper::( 1, 6, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u16, 10000, 20000, m = 4 let values = &[ "10011100011111", "11010011001111", "10011100011100", "100111000011111", "11111100000000", "10011100111100", "10011110110000", "100000000000111", "11111111111111", "10101111001111", "100111000000000", "11000000000111", "11111111000000", "100000000001111", "100000000101100", "100011110000000", "100100011110010", "100011000000111", "100110111111111", "11111111110100", ]; let common_values = &[ ("100111000100000", 70337), ("100111000000000", 16785), ("10011111111111", 12552), ("10011100010000", 11029), ("10011100011111", 11017), ("100000000000000", 10528), ("11111111111111", 8012), ("100111000000111", 5466), ("100111000000001", 5462), ("100111000001111", 5448), ]; let sample_median = (16383, None); let sample_moment_stats = MomentStats { mean: NiceFloat(15546.241523000184), standard_deviation: NiceFloat(3460.441923849274), skewness: NiceFloat(-0.39481033379336405), excess_kurtosis: NiceFloat(-1.1600583805474893), }; striped_random_unsigned_inclusive_range_helper::( 10000, 20000, 4, 1, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_unsigned_inclusive_range_fail_helper() { assert_panic!(striped_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::TWO, T::ONE, 5, 1, )); assert_panic!(striped_random_unsigned_inclusive_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, )); } #[test] fn striped_random_unsigned_inclusive_range_fail() { apply_fn_to_unsigneds!(striped_random_unsigned_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_range.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_unsigned_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_unsigned_range_helper( a: T, b: T, m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_unsigned_range::(EXAMPLE_SEED, a, b, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_unsigned_range() { // u8, 5, 6, m = 4 let values = &["101"; 20]; let common_values = &[("101", 1000000)]; let sample_median = (5, None); let sample_moment_stats = MomentStats { mean: NiceFloat(5.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_unsigned_range_helper::( 5, 6, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, 0, 8, m = 4 let values = &[ "0", "0", "0", "101", "11", "100", "11", "11", "0", "111", "111", "100", "0", "11", "111", "0", "0", "1", "0", "0", ]; let common_values = &[ ("111", 281415), ("0", 280832), ("110", 94370), ("11", 93804), ("100", 93374), ("1", 93351), ("10", 31559), ("101", 31295), ]; let sample_median = (4, None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.5039770000000354), standard_deviation: NiceFloat(2.8721055747415143), skewness: NiceFloat(-0.0024668908296986798), excess_kurtosis: NiceFloat(-1.6474519863189017), }; striped_random_unsigned_range_helper::( 0, 8, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, 1, 7, m = 4 let values = &[ "1", "1", "1", "110", "1", "110", "10", "11", "11", "100", "100", "110", "1", "1", "110", "1", "1", "11", "1", "1", ]; let common_values = &[ ("110", 375034), ("1", 374765), ("100", 93832), ("11", 93634), ("101", 31588), ("10", 31147), ]; let sample_median = (4, None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.5014329999999694), standard_deviation: NiceFloat(2.207774177939804), skewness: NiceFloat(-0.0014160236801414635), excess_kurtosis: NiceFloat(-1.753353488243057), }; striped_random_unsigned_range_helper::( 1, 7, 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u16, 10000, 20001, m = 4 let values = &[ "10011100011111", "11010011001111", "10011100011100", "100111000011111", "11111100000000", "10011100111100", "10011110110000", "100000000000111", "11111111111111", "10101111001111", "100111000000000", "11000000000111", "11111111000000", "100000000001111", "100000000101100", "100011110000000", "100100011110010", "100011000000111", "100110111111111", "11111111110100", ]; let common_values = &[ ("100111000100000", 70337), ("100111000000000", 16785), ("10011111111111", 12552), ("10011100010000", 11029), ("10011100011111", 11017), ("100000000000000", 10528), ("11111111111111", 8012), ("100111000000111", 5466), ("100111000000001", 5462), ("100111000001111", 5448), ]; let sample_median = (16383, None); let sample_moment_stats = MomentStats { mean: NiceFloat(15546.241523000184), standard_deviation: NiceFloat(3460.441923849274), skewness: NiceFloat(-0.39481033379336405), excess_kurtosis: NiceFloat(-1.1600583805474893), }; striped_random_unsigned_range_helper::( 10000, 20001, 4, 1, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_unsigned_range_fail_helper() { assert_panic!(striped_random_unsigned_range::( EXAMPLE_SEED, T::TWO, T::TWO, 5, 1, )); assert_panic!(striped_random_unsigned_range::( EXAMPLE_SEED, T::ONE, T::TWO, 1, 1, )); } #[test] fn striped_random_unsigned_range_fail() { apply_fn_to_unsigneds!(striped_random_unsigned_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_vecs.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::striped_random_unsigned_vecs; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_unsigned_vecs_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_unsigned_vecs::( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_length_numerator, mean_length_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_unsigned_vecs() { striped_random_unsigned_vecs_helper::( 2, 1, 4, 1, &[ &[], &[ "11001100", "11000", "11001", "10111101", "10111110", "110000", "11010011", "11", "1110110", "11100011", "1", "1100101", "10111110", "11010111", ], &["101110", "1111000", "10110010", "11101110"], &["10110110", "11000010", "11111010", "1100110"], &["1000"], &[], &["10100000", "100101", "1000010", "1100110", "11000111"], &["111", "11100001"], &["1010110", "10101110", "10111000", "10111101"], &[], &["101011", "10", "1110101", "1110001", "11101111", "10001001"], &[], &[], &[ "10000100", "11110101", "11011100", "10011111", "10001000", "11001111", "1111000", "11010111", "1101001", "111110", "1100100", ], &[ "10101", "11011001", "10100000", "10100001", "1101100", "1101111", "10100011", "11110101", ], &[], &["10111111", "100111", "1111110"], &[], &["11000", "11110010", "11111", "1110011", "11110011"], &[ "10001110", "10011", "1100101", "111100", "10110111", "1101110", "100001", "10000000", "10101100", ], ], &[ (&[], 199913), (&["11010010"], 689), (&["11"], 688), (&["11110111"], 681), (&["10000110"], 673), (&["110010"], 672), (&["11101111"], 671), (&["1000100"], 670), (&["1111101"], 670), (&["11110010"], 670), ], (&["1100000"], None), ); striped_random_unsigned_vecs_helper::( 10, 1, 4, 1, &[ &[], &[ "0", "0", "111000", "0", "11111110", "10000001", "11111111", "11", "0", "0", "0", "11111111", "11111111", "11111", ], &["11110000", "11111111", "11111101", "1111111"], &["0", "0", "11100000", "1"], &["11111110"], &[], &["0", "0", "10011000", "11111111", "111"], &["11111111", "11111111"], &["0", "0", "0", "0"], &[], &["11111111", "11111110", "11111111", "11111111", "11111", "0"], &[], &[], &[ "0", "0", "0", "0", "11111100", "111011", "0", "1111000", "111", "1101000", "11011111", ], &[ "11111111", "11111111", "11111111", "11111", "11000000", "11", "11001000", "11111111", ], &[], &["1", "11100000", "11111111"], &[], &["1000", "0", "0", "11111111", "1111"], &["0", "10000000", "111", "10000000", "111111", "0", "0", "11111000", "11111111"], ], &[ (&[], 199913), (&["0"], 38129), (&["11111111"], 38051), (&["0", "0"], 13204), (&["11111111", "11111111"], 13153), (&["0", "0", "0"], 4662), (&["11111111", "11111111", "11111111"], 4549), (&["1"], 4369), (&["11111100"], 4338), (&["11111"], 4311), ], (&["11100", "11111110", "111111", "0"], None), ); striped_random_unsigned_vecs_helper::( 11, 10, 4, 1, &[ &[], &[ "1011010", "11010101", "1001010", "10110101", "11010110", "10101010", "10101010", "1101010", "10100101", "10101010", "10011010", "1010010", "1010101", "1010101", ], &["10101010", "1010110", "101011", "1010101"], &["1010100", "1010101", "1010101", "10101010"], &["1101010"], &[], &["1001010", "1010101", "1010101", "1010101", "1001001"], &["10101011", "10101010"], &["10101010", "10101101", "10101010", "1011010"], &[], &["10101011", "10101010", "10101010", "11010", "11010", "1010111"], &[], &[], &[ "10101010", "1001011", "11010101", "1010010", "1010101", "10101010", "101010", "1010101", "10101001", "1101010", "1010101", ], &[ "1010101", "1010101", "1010101", "10110101", "10100100", "10110100", "10101010", "10101010", ], &[], &["1010101", "10100101", "10101010"], &[], &["10101010", "1010100", "1101010", "10100101", "1001010"], &[ "10101100", "10101010", "10101010", "10010101", "10101010", "10101101", "10101010", "1001010", "1010101", ], ], &[ (&[], 199913), (&["1010101"], 41088), (&["10101010"], 40900), (&["1010101", "1010101"], 15274), (&["10101010", "10101010"], 15212), (&["10101010", "10101010", "10101010"], 5901), (&["1010101", "1010101", "1010101"], 5641), (&["10101001"], 4206), (&["10100101"], 4201), (&["10101101"], 4181), ], (&["1010101", "10110101"], None), ); } #[test] #[should_panic] fn striped_random_unsigned_vecs_fail_1() { striped_random_unsigned_vecs::(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_fail_2() { striped_random_unsigned_vecs::(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_fail_3() { striped_random_unsigned_vecs::(EXAMPLE_SEED, 4, 1, 0, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_fail_4() { striped_random_unsigned_vecs::(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_unsigned_vecs_fail_5() { striped_random_unsigned_vecs::(EXAMPLE_SEED, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::striped::striped_random_unsigned_vecs_from_length_iterator; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::vecs::random_values_from_vec; use std::iter::repeat; fn striped_random_unsigned_vecs_from_length_iterator_helper< T: PrimitiveUnsigned, I: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_unsigned_vecs_from_length_iterator::( EXAMPLE_SEED, lengths_gen, mean_stripe_numerator, mean_stripe_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_unsigned_vecs_from_length_iterator() { striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 2, 1, &[ &["11001100", "11000"], &["110010", "1111010", "1111101", "1100001"], &["1001100", "1111"], &["10110000", "11011", "1111", "101000"], &["11100110", "1111011", "10001101", "111110"], &["100111", "11101011"], &[], &["1100010", "101011"], &[], &["10100111", "100000", "1110011", "11111111"], &["1011010", "100010", "1100100", "1110110"], &["10000111", "11101111"], &["1100011", "11100101", "10001010", "11011011"], &["1001000", "11011101"], &["10100000", "101110", "11101110", "111101"], &["1100010", "1001111", "1100001", "100"], &["100111", "11100010", "110011", "11011110"], &[], &["10100", "11001011", "11100000", "1001101"], &[], ], &[ (&[], 333820), (&["11110010", "1100111"], 17), (&["10010101", "101"], 16), (&["11010100", "1100001"], 16), (&["1111101", "11100000"], 16), (&["11111111", "1111000"], 16), (&["101100", "110101"], 15), (&["1010111", "1010000"], 15), (&["10101", "1111110"], 15), (&["11110111", "10000"], 15), ], ( &["111111", "11110001", "11111010", "10100110"], Some(&["111111", "11110010"]), ), ); striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 10, 1, &[ &["0", "0"], &["1110000", "0", "11111100", "11"], &["11111110", "1111"], &["0", "0", "0", "11111000"], &["0", "0", "1111110", "0"], &["11011111", "11111111"], &[], &["11110000", "11111111"], &[], &["11111111", "11000011", "11111", "0"], &["0", "10000000", "11111001", "1111111"], &["11111111", "11111111"], &["11111111", "11111111", "11111111", "11111111"], &["0", "10000"], &["0", "0", "0", "11111100"], &["0", "0", "0", "0"], &["11111111", "0", "11110001", "11111111"], &[], &["10111100", "11", "10110100", "11101111"], &[], ], &[ (&[], 333820), (&["11111111", "11111111"], 34254), (&["0", "0"], 34215), (&["11111111", "11111111", "11111111", "11111111"], 6413), (&["0", "0", "0", "0"], 6336), (&["11111111", "11111"], 3951), (&["111111", "0"], 3891), (&["11111110", "11111111"], 3890), (&["11111111", "0"], 3889), (&["11111111", "1111"], 3878), ], (&["1", "0", "11111110", "11111111"], None), ); striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), 11, 10, &[ &["1011010", "11010101"], &["1101010", "10010101", "1010010", "10101010"], &["10101010", "10101010"], &["11010100", "10101010", "101010", "1101011"], &["10101010", "10101010", "10101010", "1001010"], &["10110101", "1010010"], &[], &["1001010", "1010101"], &[], &["1010101", "10110101", "10101010", "1010110"], &["1010100", "1010101", "1010101", "10010101"], &["1001001", "1010101"], &["1010101", "100101", "1010101", "1010101"], &["10110100", "10101010"], &["10101010", "10101010", "10111100", "11100"], &["10101010", "10001010", "1010110", "10100101"], &["10101011", "1101010", "1010101", "10110101"], &[], &["10101010", "1010100", "10110101", "10101010"], &[], ], &[ (&[], 333820), (&["1010101", "1010101"], 39945), (&["10101010", "10101010"], 39772), (&["1010101", "1010101", "1010101", "1010101"], 8708), (&["10101010", "10101010", "10101010", "10101010"], 8700), (&["1010010", "1010101"], 4100), (&["1010101", "10110101"], 4090), (&["1010101", "11010101"], 4089), (&["1010101", "10101101"], 4080), (&["1010110", "1010101"], 4060), ], (&["1010101", "1010101", "1010101", "10110101"], None), ); striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 2, 1, &[ &[ "11001100", "11000", "11001", "10111101", "10111110", "110000", "11010011", "11", "1110110", "11100011", "1", "1100101", ], &["1111100", "10101111"], &[ "1011100", "11110000", "1100100", "11011101", "1001001", "111101", "101", "10011001", "11111011", "10010111", "1110110", "1101111", "100110", "1110", "11011111", "1100011", ], &["11001010", "10101"], &[ "1101110", "1101111", "1000101", "10100000", "101110", "11101110", "111101", "10110001", "10100111", "110000", "10", "1110110", "111", "1110011", "10001000", "1100010", "11001", "10111100", "10101001", "11001000", "110", "1101", "1100101", "1111011", "11011", "10101101", "11111111", "10011110", ], &[], &[ "11110001", "1100011", "11001000", "1111111", "11001100", "11001101", "11100011", "11011000", "110101", "10000111", ], &[ "11011100", "10111010", "10000101", "0", "10110010", "10010010", "10111000", "10010100", ], &["11010001", "1111000"], &[], &[ "1010100", "10101110", "1000001", "1001011", "1011100", "10110100", "11001000", "1101", "10010101", "10111011", "1111000", "1011", ], &["1010011", "111001", "10101111", "1100101"], &[], &[], &["10010001", "11010001"], &["10111110", "11101111", "11101011", "10010", "1101101", "1010110"], &[], &["100110", "10001010"], &[], &["1101100", "11000"], ], &[ (&[], 333981), (&["1", "10011100"], 13), (&["11111011", "110100"], 13), (&["110000", "10110111"], 13), (&["1100110", "10011000"], 13), (&["11101100", "11011100"], 13), (&["1", "100101"], 12), (&["100010", "101100"], 12), (&["1010", "11000011"], 12), (&["1100101", "1001101"], 12), ], (&["111111", "10101111"], None), ); striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 10, 1, &[ &[ "0", "0", "111000", "0", "11111110", "10000001", "11111111", "11", "0", "0", "0", "11111111", ], &["0", "11000000"], &[ "11100000", "11111111", "11111011", "11111111", "0", "0", "11100000", "1", "11111111", "11111111", "11111111", "11001", "0", "11111110", "11111111", "11111111", ], &["0", "0"], &[ "0", "0", "100000", "0", "0", "0", "11111100", "11111111", "11111111", "11111111", "11111111", "111111", "1000000", "11111100", "1111111", "10001000", "1111111", "1001", "10", "0", "0", "0", "11111111", "11100001", "10111111", "1", "11111000", "1111111", ], &[], &[ "11111111", "11011111", "11111111", "11111111", "11", "11000000", "11111111", "11111111", "11110000", "11111111", ], &["11111110", "0", "0", "11100000", "11111111", "1111", "0", "11111111"], &["11110011", "11111111"], &[], &[ "10001000", "11111111", "11", "11111110", "0", "11111100", "11111111", "11111111", "11111111", "11", "11111111", "11111", ], &["11111111", "1100001", "0", "11100000"], &[], &[], &["11111111", "11111111"], &["11111000", "1111111", "0", "10000000", "111", "1111"], &[], &["0", "0"], &[], &["0", "0"], ], &[ (&[], 333981), (&["0", "0"], 22998), (&["11111111", "11111111"], 22759), (&["11111111", "11111111", "11111111", "11111111"], 2851), (&["0", "0", "0", "0"], 2788), (&["11111111", "111111"], 2626), (&["1111", "0"], 2620), (&["111", "0"], 2615), (&["111111", "0"], 2608), (&["11111000", "11111111"], 2608), ], ( &["1", "0", "11111000", "1", "1111100", "0", "0", "100000"], Some(&["1", "0", "11111000", "1", "10000000", "11111111", "11111111", "11111111"]), ), ); striped_random_unsigned_vecs_from_length_iterator_helper::( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), 11, 10, &[ &[ "1011010", "11010101", "1001010", "10110101", "11010110", "10101010", "10101010", "1101010", "10100101", "10101010", "10011010", "1010010", ], &["10101010", "10101010"], &[ "10101010", "1010010", "10101001", "1010101", "10101011", "10101010", "10101010", "1010101", "10110101", "1010010", "1010101", "1010101", "1010101", "10010010", "10101010", "10101010", ], &["1001010", "10101010"], &[ "10101010", "10010110", "10101010", "10101010", "10101010", "10111100", "11100", "1010101", "1000101", "10101011", "11010010", "10101010", "1011010", "1010101", "10101101", "1101010", "1010101", "10101001", "10101010", "10101010", "10101010", "10101010", "100101", "10100101", "1010101", "1010101", "1010101", "10010101", ], &[], &[ "1010101", "1010101", "10101101", "1010110", "1101010", "11010101", "10100110", "10101010", "10101010", "11010100", ], &[ "10101010", "10110110", "10101010", "101010", "1010101", "1010101", "10101010", "10101010", ], &["10010101", "10101010"], &[], &[ "10101010", "1001010", "1010101", "1011101", "10010101", "10101010", "10101010", "10101010", "10101010", "10110101", "10010100", "1010101", ], &["1010101", "1010101", "1010101", "1010101"], &[], &[], &["1010101", "1001010"], &["1001010", "10101101", "11010010", "10101010", "1101010", "1010101"], &[], &["10000100", "10101010"], &[], &["10101010", "101010"], ], &[ (&[], 333981), (&["10101010", "10101010"], 26752), (&["1010101", "1010101"], 26461), (&["10101010", "10101010", "10101010", "10101010"], 3857), (&["1010101", "1010101", "1010101", "1010101"], 3852), (&["10101010", "1010010"], 2802), (&["1010110", "1010101"], 2776), (&["1010101", "10100101"], 2768), (&["1010101", "10010101"], 2739), (&["10101011", "10101010"], 2730), ], (&["1010101", "1010101", "10010101", "10101010"], None), ); } #[test] #[should_panic] fn striped_random_unsigned_vecs_from_length_iterator_fail_1() { striped_random_unsigned_vecs_from_length_iterator::(EXAMPLE_SEED, &|_| repeat(1), 1, 0); } #[test] #[should_panic] fn striped_random_unsigned_vecs_from_length_iterator_fail_2() { striped_random_unsigned_vecs_from_length_iterator::(EXAMPLE_SEED, &|_| repeat(1), 2, 3); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::striped_random_unsigned_vecs_length_inclusive_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_unsigned_vecs_length_inclusive_range_helper( a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_unsigned_vecs_length_inclusive_range::( EXAMPLE_SEED, a, b, mean_stripe_numerator, mean_stripe_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_unsigned_vecs_length_inclusive_range() { striped_random_unsigned_vecs_length_inclusive_range_helper::( 3, 5, 2, 1, &[ &["11001100", "11000", "11001", "10111101"], &["10000010", "10011110", "1011001", "11111000", "10011"], &["1110010", "11111000", "1101011", "110"], &["1000010", "10111001", "11100000", "11001001", "10111010"], &["11011000", "1010", "11101011", "10011011", "10001"], &["10111111", "10110100", "1111011", "110011"], &["11100010", "11110000", "111101"], &["1010011", "10100011", "10001110", "10000100"], &["1010110", "100", "11101010"], &["11000101", "10111101", "100111", "11110110", "10100"], &["1110011", "1111111", "100010", "111110", "11100011"], &["1000100", "10110001", "1100", "11011110"], &["1010110", "110111", "11111001", "11110010", "10011010"], &["11110110", "110110", "1011010", "11111111"], &["1111011", "11100010", "11000111", "10010000", "11111111"], &["11001110", "11001000", "1110000", "10011100", "101000"], &["111001", "10001100", "10100", "11101001", "11111101"], &["10010000", "10010101", "11000100"], &["10110100", "1110110", "111001", "10101100", "1000110"], &["1101", "1011010", "11100010"], ], &[ (&["1001110", "1011", "11000"], 3), (&["1011010", "10011", "100010"], 3), (&["1100010", "101000", "1000010"], 3), (&["1110111", "101000", "100101"], 3), (&["10110", "1100010", "10011111"], 3), (&["11001", "1011", "10110011"], 3), (&["11001", "1110010", "1000101"], 3), (&["101001", "101000", "1110000"], 3), (&["1100101", "1111001", "11100"], 3), (&["10010000", "1110110", "1011111"], 3), ], ( &["1111111", "11110100", "1010100", "1100"], Some(&["1111111", "11110100", "1100001"]), ), ); striped_random_unsigned_vecs_length_inclusive_range_helper::( 3, 5, 10, 1, &[ &["0", "0", "111000", "0"], &["11111100", "11", "11111111", "111", "0"], &["0", "0", "11111100", "11111111"], &["0", "111111", "0", "1000", "0"], &["11111100", "11111111", "1111111", "11111000", "11"], &["11111111", "11111111", "11001111", "0"], &["11100000", "11111111", "11111111"], &["11111111", "11111111", "11111111", "11111111"], &["0", "10", "0"], &["11111111", "1111111", "0", "0", "0"], &["11111111", "11111111", "1111", "10000", "11111111"], &["11000000", "111011", "1000000", "11111011"], &["10", "0", "0", "0", "11111111"], &["111100", "10000000", "11111100", "1111"], &["11111111", "1", "1000000", "0", "0"], &["11110000", "11111111", "0", "0", "111100"], &["11111111", "111", "11111100", "11111111", "1111111"], &["0", "10000000", "11111111"], &["11110000", "10011111", "11111111", "11011111", "1"], &["11111", "11110000", "111"], ], &[ (&["0", "0", "0"], 14915), (&["11111111", "11111111", "11111111"], 14783), (&["0", "0", "0", "0"], 6456), (&["11111111", "11111111", "11111111", "11111111"], 6260), (&["0", "0", "0", "0", "0"], 2738), ( &["11111111", "11111111", "11111111", "11111111", "11111111"], 2722, ), (&["11111111", "111111", "0"], 1721), (&["11111111", "11111111", "1111"], 1717), (&["0", "0", "10000000"], 1708), (&["11110000", "11111111", "11111111"], 1707), ], (&["10000000", "0", "0"], None), ); striped_random_unsigned_vecs_length_inclusive_range_helper::( 3, 5, 11, 10, &[ &["1011010", "11010101", "1001010", "10110101"], &["1010010", "10101010", "10101010", "101010", "10110101"], &["10101010", "1101010", "1001010", "1010101"], &["10101010", "10101010", "1011010", "10101101", "1010100"], &["1010010", "1010101", "1010101", "10101001", "101010"], &["10010101", "10101010", "10101010", "10101010"], &["11011010", "1010110", "1010101"], &["1010101", "1011011", "1010101", "10110101"], &["1010110", "1010101", "1010101"], &["10010101", "10010111", "10100011", "10101010", "1101000"], &["1010101", "1001011", "1010101", "10101001", "10101010"], &["1010110", "10110101", "10101010", "1010100"], &["10101010", "10101010", "10101010", "10101010", "100101"], &["1001010", "10101011", "10101010", "10101010"], &["1010101", "10101010", "10101010", "1011010", "10101101"], &["1010110", "10101010", "1100100", "1010101", "1010101"], &["10100101", "1010110", "100101", "1010101", "1010101"], &["1010110", "1010101", "10101101"], &["10101010", "10101010", "1010100", "1010101", "11010101"], &["1010101", "10101", "1010101"], ], &[ (&["10101010", "10101010", "10101010"], 18583), (&["1010101", "1010101", "1010101"], 18554), (&["1010101", "1010101", "1010101", "1010101"], 8801), (&["10101010", "10101010", "10101010", "10101010"], 8734), ( &["1010101", "1010101", "1010101", "1010101", "1010101"], 4002, ), ( &["10101010", "10101010", "10101010", "10101010", "10101010"], 3983, ), (&["1101010", "1010101", "1010101"], 1971), (&["10110101", "10101010", "10101010"], 1953), (&["1010101", "10101101", "10101010"], 1936), (&["1010101", "10110101", "10101010"], 1934), ], ( &["10000101", "101010", "10101010"], Some(&["10000101", "1001010", "1001001", "100101"]), ), ); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_inclusive_range_fail_1() { striped_random_unsigned_vecs_length_inclusive_range::(EXAMPLE_SEED, 3, 10, 1, 0); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_inclusive_range_fail_2() { striped_random_unsigned_vecs_length_inclusive_range::(EXAMPLE_SEED, 3, 10, 2, 3); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_inclusive_range_fail_3() { striped_random_unsigned_vecs_length_inclusive_range::(EXAMPLE_SEED, 2, 1, 4, 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_vecs_length_range.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::striped_random_unsigned_vecs_length_range; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_unsigned_vecs_length_range_helper( a: u64, b: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_unsigned_vecs_length_range::( EXAMPLE_SEED, a, b, mean_stripe_numerator, mean_stripe_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_unsigned_vecs_length_range() { striped_random_unsigned_vecs_length_range_helper::( 3, 6, 2, 1, &[ &["11001100", "11000", "11001", "10111101"], &["10000010", "10011110", "1011001", "11111000", "10011"], &["1110010", "11111000", "1101011", "110"], &["1000010", "10111001", "11100000", "11001001", "10111010"], &["11011000", "1010", "11101011", "10011011", "10001"], &["10111111", "10110100", "1111011", "110011"], &["11100010", "11110000", "111101"], &["1010011", "10100011", "10001110", "10000100"], &["1010110", "100", "11101010"], &["11000101", "10111101", "100111", "11110110", "10100"], &["1110011", "1111111", "100010", "111110", "11100011"], &["1000100", "10110001", "1100", "11011110"], &["1010110", "110111", "11111001", "11110010", "10011010"], &["11110110", "110110", "1011010", "11111111"], &["1111011", "11100010", "11000111", "10010000", "11111111"], &["11001110", "11001000", "1110000", "10011100", "101000"], &["111001", "10001100", "10100", "11101001", "11111101"], &["10010000", "10010101", "11000100"], &["10110100", "1110110", "111001", "10101100", "1000110"], &["1101", "1011010", "11100010"], ], &[ (&["1001110", "1011", "11000"], 3), (&["1011010", "10011", "100010"], 3), (&["1100010", "101000", "1000010"], 3), (&["1110111", "101000", "100101"], 3), (&["10110", "1100010", "10011111"], 3), (&["11001", "1011", "10110011"], 3), (&["11001", "1110010", "1000101"], 3), (&["101001", "101000", "1110000"], 3), (&["1100101", "1111001", "11100"], 3), (&["10010000", "1110110", "1011111"], 3), ], ( &["1111111", "11110100", "1010100", "1100"], Some(&["1111111", "11110100", "1100001"]), ), ); striped_random_unsigned_vecs_length_range_helper::( 3, 6, 10, 1, &[ &["0", "0", "111000", "0"], &["11111100", "11", "11111111", "111", "0"], &["0", "0", "11111100", "11111111"], &["0", "111111", "0", "1000", "0"], &["11111100", "11111111", "1111111", "11111000", "11"], &["11111111", "11111111", "11001111", "0"], &["11100000", "11111111", "11111111"], &["11111111", "11111111", "11111111", "11111111"], &["0", "10", "0"], &["11111111", "1111111", "0", "0", "0"], &["11111111", "11111111", "1111", "10000", "11111111"], &["11000000", "111011", "1000000", "11111011"], &["10", "0", "0", "0", "11111111"], &["111100", "10000000", "11111100", "1111"], &["11111111", "1", "1000000", "0", "0"], &["11110000", "11111111", "0", "0", "111100"], &["11111111", "111", "11111100", "11111111", "1111111"], &["0", "10000000", "11111111"], &["11110000", "10011111", "11111111", "11011111", "1"], &["11111", "11110000", "111"], ], &[ (&["0", "0", "0"], 14915), (&["11111111", "11111111", "11111111"], 14783), (&["0", "0", "0", "0"], 6456), (&["11111111", "11111111", "11111111", "11111111"], 6260), (&["0", "0", "0", "0", "0"], 2738), ( &["11111111", "11111111", "11111111", "11111111", "11111111"], 2722, ), (&["11111111", "111111", "0"], 1721), (&["11111111", "11111111", "1111"], 1717), (&["0", "0", "10000000"], 1708), (&["11110000", "11111111", "11111111"], 1707), ], (&["10000000", "0", "0"], None), ); striped_random_unsigned_vecs_length_range_helper::( 3, 6, 11, 10, &[ &["1011010", "11010101", "1001010", "10110101"], &["1010010", "10101010", "10101010", "101010", "10110101"], &["10101010", "1101010", "1001010", "1010101"], &["10101010", "10101010", "1011010", "10101101", "1010100"], &["1010010", "1010101", "1010101", "10101001", "101010"], &["10010101", "10101010", "10101010", "10101010"], &["11011010", "1010110", "1010101"], &["1010101", "1011011", "1010101", "10110101"], &["1010110", "1010101", "1010101"], &["10010101", "10010111", "10100011", "10101010", "1101000"], &["1010101", "1001011", "1010101", "10101001", "10101010"], &["1010110", "10110101", "10101010", "1010100"], &["10101010", "10101010", "10101010", "10101010", "100101"], &["1001010", "10101011", "10101010", "10101010"], &["1010101", "10101010", "10101010", "1011010", "10101101"], &["1010110", "10101010", "1100100", "1010101", "1010101"], &["10100101", "1010110", "100101", "1010101", "1010101"], &["1010110", "1010101", "10101101"], &["10101010", "10101010", "1010100", "1010101", "11010101"], &["1010101", "10101", "1010101"], ], &[ (&["10101010", "10101010", "10101010"], 18583), (&["1010101", "1010101", "1010101"], 18554), (&["1010101", "1010101", "1010101", "1010101"], 8801), (&["10101010", "10101010", "10101010", "10101010"], 8734), ( &["1010101", "1010101", "1010101", "1010101", "1010101"], 4002, ), ( &["10101010", "10101010", "10101010", "10101010", "10101010"], 3983, ), (&["1101010", "1010101", "1010101"], 1971), (&["10110101", "10101010", "10101010"], 1953), (&["1010101", "10101101", "10101010"], 1936), (&["1010101", "10110101", "10101010"], 1934), ], ( &["10000101", "101010", "10101010"], Some(&["10000101", "1001010", "1001001", "100101"]), ), ); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_range_fail_1() { striped_random_unsigned_vecs_length_range::(EXAMPLE_SEED, 3, 10, 1, 0); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_range_fail_2() { striped_random_unsigned_vecs_length_range::(EXAMPLE_SEED, 3, 10, 2, 3); } #[test] #[should_panic] fn striped_random_unsigned_vecs_length_range_fail_3() { striped_random_unsigned_vecs_length_range::(EXAMPLE_SEED, 1, 1, 4, 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigned_vecs_min_length.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::striped::striped_random_unsigned_vecs_min_length; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn striped_random_unsigned_vecs_min_length_helper( min_length: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[&str]], expected_common_values: &[(&[&str], usize)], expected_median: (&[&str], Option<&[&str]>), ) { let xss = striped_random_unsigned_vecs_min_length::( EXAMPLE_SEED, min_length, mean_stripe_numerator, mean_stripe_denominator, mean_length_numerator, mean_length_denominator, ); let values = xss .clone() .take(20) .map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }) .collect_vec(); let common_values = common_values_map_debug(1000000, 10, xss.clone()) .into_iter() .map(|(xs, freq)| { ( xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(), freq, ) }) .collect_vec(); let (median_lo, median_hi) = median(xss.take(1000000)); let median_lo = median_lo .into_iter() .map(|x: T| x.to_binary_string()) .collect_vec(); let median_hi = median_hi.map(|xs| { xs.into_iter() .map(|x: T| x.to_binary_string()) .collect_vec() }); let values = values .iter() .map(|xs| xs.iter().map(String::as_str).collect_vec()) .collect_vec(); let common_values = common_values .iter() .map(|(xs, freq)| (xs.iter().map(String::as_str).collect_vec(), *freq)) .collect_vec(); let median_lo = median_lo.iter().map(String::as_str).collect_vec(); let median_hi = median_hi .as_ref() .map(|xs| xs.iter().map(String::as_str).collect_vec()); assert_eq!( ( values.iter().map(Vec::as_slice).collect_vec().as_slice(), common_values .iter() .map(|(xs, f)| (xs.as_slice(), *f)) .collect_vec() .as_slice(), (median_lo.as_slice(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_striped_random_unsigned_vecs() { striped_random_unsigned_vecs_min_length_helper::( 0, 2, 1, 4, 1, &[ &[], &[ "11001100", "11000", "11001", "10111101", "10111110", "110000", "11010011", "11", "1110110", "11100011", "1", "1100101", "10111110", "11010111", ], &["101110", "1111000", "10110010", "11101110"], &["10110110", "11000010", "11111010", "1100110"], &["1000"], &[], &["10100000", "100101", "1000010", "1100110", "11000111"], &["111", "11100001"], &["1010110", "10101110", "10111000", "10111101"], &[], &["101011", "10", "1110101", "1110001", "11101111", "10001001"], &[], &[], &[ "10000100", "11110101", "11011100", "10011111", "10001000", "11001111", "1111000", "11010111", "1101001", "111110", "1100100", ], &[ "10101", "11011001", "10100000", "10100001", "1101100", "1101111", "10100011", "11110101", ], &[], &["10111111", "100111", "1111110"], &[], &["11000", "11110010", "11111", "1110011", "11110011"], &[ "10001110", "10011", "1100101", "111100", "10110111", "1101110", "100001", "10000000", "10101100", ], ], &[ (&[], 199913), (&["11010010"], 689), (&["11"], 688), (&["11110111"], 681), (&["10000110"], 673), (&["110010"], 672), (&["11101111"], 671), (&["1000100"], 670), (&["1111101"], 670), (&["11110010"], 670), ], (&["1100000"], None), ); striped_random_unsigned_vecs_min_length_helper::( 3, 2, 1, 4, 1, &[ &["11001100", "11000", "11001", "10111101"], &["10000010", "10011110", "1011001", "11111000", "10011"], &["1110010", "11111000", "1101011", "110", "10100001"], &["1000110", "11111", "110110", "1000101", "1101100"], &["1010", "11101011", "10011011", "10001"], &["10111111", "10110100", "1111011", "110011", "1110001"], &["11110000", "111101", "1010110"], &["10100011", "10001110", "10000100"], &["1010110", "100", "11101010", "11100010"], &["10111101", "100111", "11110110"], &["101001", "10001100", "10000000"], &["1000100", "1111100", "11000110"], &["10001000", "1100010", "11001", "10111100"], &["10101100", "1101110", "11110010", "11100101", "110101", "1001", "11001001"], &["1001011", "1", "10000100"], &["11000100", "10001111", "100001", "11111111", "110001"], &["10010001", "11100001", "111000"], &[ "10100010", "10001100", "11100111", "11010110", "101101", "100", "10010000", "10010101", ], &["1110110", "10110100", "1110110", "111001"], &["10100111", "1110010", "1101", "1011010"], ], &[ (&["111100", "11", "1111"], 3), (&["10000111", "100011", "110"], 3), (&["10101011", "1001101", "1"], 3), (&["10011", "1111000", "111"], 3), (&["10", "10111", "11111000"], 3), (&["11010000", "1001010", "11"], 3), (&["101", "1001110", "1110111"], 3), (&["101", "1001111", "10111101"], 3), (&["111000", "1010011", "1010"], 3), (&["111011", "0", "1110101"], 3), ], ( &["1111111", "11011110", "10110011"], Some(&["1111111", "11011110", "10111100"]), ), ); striped_random_unsigned_vecs_min_length_helper::( 0, 10, 1, 4, 1, &[ &[], &[ "0", "0", "111000", "0", "11111110", "10000001", "11111111", "11", "0", "0", "0", "11111111", "11111111", "11111", ], &["11110000", "11111111", "11111101", "1111111"], &["0", "0", "11100000", "1"], &["11111110"], &[], &["0", "0", "10011000", "11111111", "111"], &["11111111", "11111111"], &["0", "0", "0", "0"], &[], &["11111111", "11111110", "11111111", "11111111", "11111", "0"], &[], &[], &[ "0", "0", "0", "0", "11111100", "111011", "0", "1111000", "111", "1101000", "11011111", ], &[ "11111111", "11111111", "11111111", "11111", "11000000", "11", "11001000", "11111111", ], &[], &["1", "11100000", "11111111"], &[], &["1000", "0", "0", "11111111", "1111"], &["0", "10000000", "111", "10000000", "111111", "0", "0", "11111000", "11111111"], ], &[ (&[], 199913), (&["0"], 38129), (&["11111111"], 38051), (&["0", "0"], 13204), (&["11111111", "11111111"], 13153), (&["0", "0", "0"], 4662), (&["11111111", "11111111", "11111111"], 4549), (&["1"], 4369), (&["11111100"], 4338), (&["11111"], 4311), ], (&["11100", "11111110", "111111", "0"], None), ); striped_random_unsigned_vecs_min_length_helper::( 3, 10, 1, 4, 1, &[ &["0", "0", "111000", "0"], &["11111100", "11", "11111111", "111", "0"], &["0", "0", "11111100", "11111111", "1111111"], &["11000000", "11111111", "11110111", "11111111", "1"], &["0", "10000000", "111", "11111100"], &["11111111", "11111111", "11001111", "0", "11110000"], &["0", "0", "0"], &["11111111", "11111111", "11111111"], &["0", "10", "0", "0"], &["1111111", "0", "0"], &["11111111", "11111111", "11111111"], &["11100000", "11011111", "1"], &["10000000", "1110111", "10000000", "11110110"], &["100", "0", "0", "0", "11111110", "11000011", "1111111"], &["11111001", "11111", "0"], &["11111100", "1111111", "11111111", "11111111", "1111"], &["11111111", "1", "0"], &["11110000", "0", "11110000", "111", "0", "0", "11111111", "1111111"], &["0", "11110000", "10011111", "11111111"], &["10111111", "11", "11100000", "1111"], ], &[ (&["0", "0", "0"], 22115), (&["11111111", "11111111", "11111111"], 21981), (&["0", "0", "0", "0"], 4887), (&["11111111", "11111111", "11111111", "11111111"], 4789), (&["0", "11000000", "11111111"], 2545), (&["11110000", "11111111", "11111111"], 2537), (&["11111111", "11111111", "1111"], 2536), (&["1111111", "0", "0"], 2524), (&["11111111", "111111", "0"], 2524), (&["10000000", "11111111", "11111111"], 2524), ], ( &["10000000", "0", "0", "0", "100", "0", "0", "11111000", "11111111"], Some(&["10000000", "0", "0", "0", "100", "11111110", "11111111", "11111", "11100000"]), ), ); striped_random_unsigned_vecs_min_length_helper::( 0, 11, 10, 4, 1, &[ &[], &[ "1011010", "11010101", "1001010", "10110101", "11010110", "10101010", "10101010", "1101010", "10100101", "10101010", "10011010", "1010010", "1010101", "1010101", ], &["10101010", "1010110", "101011", "1010101"], &["1010100", "1010101", "1010101", "10101010"], &["1101010"], &[], &["1001010", "1010101", "1010101", "1010101", "1001001"], &["10101011", "10101010"], &["10101010", "10101101", "10101010", "1011010"], &[], &["10101011", "10101010", "10101010", "11010", "11010", "1010111"], &[], &[], &[ "10101010", "1001011", "11010101", "1010010", "1010101", "10101010", "101010", "1010101", "10101001", "1101010", "1010101", ], &[ "1010101", "1010101", "1010101", "10110101", "10100100", "10110100", "10101010", "10101010", ], &[], &["1010101", "10100101", "10101010"], &[], &["10101010", "1010100", "1101010", "10100101", "1001010"], &[ "10101100", "10101010", "10101010", "10010101", "10101010", "10101101", "10101010", "1001010", "1010101", ], ], &[ (&[], 199913), (&["1010101"], 41088), (&["10101010"], 40900), (&["1010101", "1010101"], 15274), (&["10101010", "10101010"], 15212), (&["10101010", "10101010", "10101010"], 5901), (&["1010101", "1010101", "1010101"], 5641), (&["10101001"], 4206), (&["10100101"], 4201), (&["10101101"], 4181), ], (&["1010101", "10110101"], None), ); striped_random_unsigned_vecs_min_length_helper::( 3, 11, 10, 4, 1, &[ &["1011010", "11010101", "1001010", "10110101"], &["1010010", "10101010", "10101010", "101010", "10110101"], &["10101010", "1101010", "1001010", "1010101", "1010101"], &["10101010", "1011010", "10101101", "1010100", "10101001"], &["10101010", "10101010", "1010110", "11010101"], &["10010101", "10101010", "10101010", "10101010", "10010010"], &["1010110", "1010101", "1010101"], &["1011011", "1010101", "10110101"], &["1010110", "1010101", "1010101", "110101"], &["10010111", "10100011", "10101010"], &["11010001", "10101010", "10110100"], &["10101010", "1010010", "1010101"], &["1010010", "10010101", "10101010", "1010110"], &["10101010", "10101010", "10101010", "10101010", "10110100", "10110101", "1010100"], &["1010101", "1010101", "1010101"], &["1010100", "1010101", "10110101", "1011010", "10101001"], &["10101011", "110110", "1010101"], &[ "10101010", "1001010", "10101101", "1001010", "10101010", "10101010", "1010110", "1010101", ], &["1011010", "1010101", "1010101", "10101011"], &["1010101", "1010101", "10101010", "11101010"], ], &[ (&["10101010", "10101010", "10101010"], 27990), (&["1010101", "1010101", "1010101"], 27615), (&["10101010", "10101010", "10101010", "10101010"], 6458), (&["1010101", "1010101", "1010101", "1010101"], 6439), (&["10101010", "1011010", "1010101"], 2932), (&["10101010", "10101010", "101010"], 2904), (&["10100101", "10101010", "10101010"], 2904), (&["10110101", "10101010", "10101010"], 2878), (&["1010101", "1010101", "10010101"], 2877), (&["10101010", "10101010", "1001010"], 2864), ], ( &["10001001", "10101010", "11010100", "1010010", "1010101"], Some(&["10001001", "10101010", "11010110", "10101010", "10101010"]), ), ); } #[test] #[should_panic] fn striped_random_unsigned_vecs_min_length_fail_1() { striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 3, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_min_length_fail_2() { striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 3, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_min_length_fail_3() { striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 3, 4, 1, 3, 1); } #[test] #[should_panic] fn striped_random_unsigned_vecs_min_length_fail_4() { striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 1, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_unsigned_vecs_min_length_fail_5() { striped_random_unsigned_vecs_min_length::(EXAMPLE_SEED, 0, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/num/random/striped/striped_random_unsigneds.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::float::NiceFloat; use malachite_base::num::random::striped::striped_random_unsigneds; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToBinaryString; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{CheckedToF64, MomentStats, moment_stats}; use std::panic::catch_unwind; fn striped_random_unsigneds_helper( m_numerator: u64, m_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (T, Option), expected_sample_moment_stats: MomentStats, ) { let xs = striped_random_unsigneds::(EXAMPLE_SEED, m_numerator, m_denominator); let actual_values = xs .clone() .map(|x| x.to_binary_string()) .take(20) .collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .iter() .map(|(x, frequency)| (x.to_binary_string(), *frequency)) .collect_vec(); let actual_sample_median = median(xs.clone().take(1000000)); let actual_sample_moment_stats = moment_stats(xs.take(1000000)); assert_eq!( ( actual_values, actual_common_values, actual_sample_median, actual_sample_moment_stats ), ( expected_values .iter() .map(ToString::to_string) .collect_vec(), expected_common_values .iter() .map(|(x, frequency)| (x.to_string(), *frequency)) .collect_vec(), expected_sample_median, expected_sample_moment_stats ) ); } #[test] fn test_striped_random_unsigneds() { // u8, m = 4 let values = &[ "1", "1001100", "1111111", "11000011", "0", "10000000", "1111", "1110110", "0", "11111000", "11111111", "11111101", "1111001", "0", "11110000", "11", "0", "1111111", "1", "0", ]; let common_values = &[ ("0", 66602), ("11111111", 66546), ("11100000", 22466), ("11110000", 22460), ("11111", 22373), ("111111", 22356), ("11111100", 22356), ("11111110", 22352), ("1111", 22281), ("11000000", 22273), ]; let sample_median = (128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(127.56886100000068), standard_deviation: NiceFloat(95.37976309187316), skewness: NiceFloat(-0.0013289716890443589), excess_kurtosis: NiceFloat(-1.5650405989826497), }; striped_random_unsigneds_helper::( 4, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, m = 2 let values = &[ "110011", "1110010", "1010110", "10110100", "1000001", "11000011", "101000", "110111", "11", "11000100", "10111001", "11111011", "111101", "1110011", "10100110", "1010010", "1110110", "110011", "11111", "1010011", ]; let common_values = &[ ("1000100", 4102), ("10100100", 4091), ("11100100", 4062), ("10100010", 4038), ("11011010", 4037), ("1010100", 4028), ("10001011", 4028), ("10010010", 4024), ("11100011", 4019), ("1101011", 4010), ]; let sample_median = (128, None); let sample_moment_stats = MomentStats { mean: NiceFloat(127.61267700000472), standard_deviation: NiceFloat(73.77702717610372), skewness: NiceFloat(-0.0007666301824401424), excess_kurtosis: NiceFloat(-1.196710018532242), }; striped_random_unsigneds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // u8, m = 5/4 let values = &[ "1010010", "1101010", "110010", "10010100", "1010101", "10111010", "1010100", "1011010", "1010110", "10001101", "10000100", "11100011", "1010", "1001011", "10101010", "1010110", "1010001", "1010100", "1010101", "1010101", ]; let common_values = &[ ("1010101", 105174), ("10101010", 104734), ("10101101", 26535), ("11010101", 26470), ("1010010", 26420), ("101010", 26383), ("1001010", 26310), ("10010101", 26290), ("10110101", 26229), ("10101001", 26220), ]; let sample_median = (130, None); let sample_moment_stats = MomentStats { mean: NiceFloat(127.53448699999743), standard_deviation: NiceFloat(54.22754686756281), skewness: NiceFloat(-0.0015080269385326522), excess_kurtosis: NiceFloat(-1.1008502131352262), }; striped_random_unsigneds_helper::( 5, 4, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 32 let values = &[ "111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111", "1111111111111111111111100000000000000000000000000000000000000000", "11111111111111111111111111111111111111111111111111111111111111", "1111000000000000000000000000000000000000001100000000111111111111", "111111111111111000000000000", "1111111111111111111111111", "111111111111111111111", "1111111111111111111111111111111111111111111000000000000000000000", "1110000000000000000000000000000000000000000000000000000000000111", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111000000000000000000000000000", "100000001111111111111111111111111000000000", "1111111000000000000000000000000000000000000000000000000000000000", "1111", "1111111111111111111111111111111111111111111111111111000", "1111111111111111110000000011111111111111111", "0", "111111111111111111111111100", ]; let common_values = &[ ( "1111111111111111111111111111111111111111111111111111111111111111", 68034, ), ("0", 67854), ("111111111111111111111111111111", 2299), ( "1111111111111111111111111110000000000000000000000000000000000000", 2298, ), ("111111111", 2270), ("111111111111111111111111111111111111", 2255), ("111111111111", 2254), ( "1111111111111111111111111111111111111111111111100000000000000000", 2245, ), ( "1111111111111110000000000000000000000000000000000000000000000000", 2240, ), ( "1111111111111111111111111111111111111111111111111111111111000000", 2237, ), ]; let sample_median = (9223372036854775808, None); let sample_moment_stats = MomentStats { mean: NiceFloat(9.232321508867713e18), standard_deviation: NiceFloat(8.854393011414399e18), skewness: NiceFloat(-0.00195547778002319), excess_kurtosis: NiceFloat(-1.9432719051653975), }; striped_random_unsigneds_helper::( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 2 let values = &[ "11001100011010101001011010010000011000011101011110010000000011", "11101101110011111011100001011100110100110101001011101100110011", "1111101011000111001110010011000110110101010001110111011111100", "1011100110000101000110000000111101100011100111101101111111000000", "110011001100101100000100111100101010001011010001101001000111000", "1010001101111001011010101011011000110011011110010101100100000100", "111100011000100010101011011011001000000100111011110100111011", "100100110010110010010111100011001000100110111001010000100101101", "1101100111000010011100101110010101101001100110000011111011", "1101110011101000110001100100011011100001110011100001101110001000", "1101100100110110101110000011000111010011101101101111111101111100", "1111001111110101110110010100001100001001011101001101101011101011", "111010010110111111001011100000010101010001111000010000110010001", "11010101111001000111010001011100101000010001110110001001100111", "1101011111000100111101011110111101110011010100111111100001000100", "100101000001001011001001101001011100101000110101111110111010101", "110111101110000101100101111100101101011100100010101011010100000", "101011100111011000001101010001000101111111010001100001111100011", "1111100011000100010111100101000001010110011001010100000000011", "11100111100011111000111111010010100000111110101001010111011001", ]; let common_values = &[ ("11011011101110000001110101101011110010111101", 1), ("111100000110100100110100100001100010110000010", 1), ("1011110101111010110111100110111101111101111011", 1), ("1110100010111110000100101010110100101101110111", 1), ("10111011110000001110101010110111111001011011100", 1), ("11000001010110011001100110101011001100000111111", 1), ("100100100011101001001000001010010111100010110100", 1), ("100110100101010111001000010010100111110111010110", 1), ("110110101100010110011100011100110111001111000000", 1), ("111001100010011111010011111010110100101110001000", 1), ]; let sample_median = (9232300347074497346, Some(9232359143244030439)); let sample_moment_stats = MomentStats { mean: NiceFloat(9.22650235650532e18), standard_deviation: NiceFloat(5.325785817923598e18), skewness: NiceFloat(-0.0012562071401776408), excess_kurtosis: NiceFloat(-1.1996143045434082), }; striped_random_unsigneds_helper::( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // u64, m = 33/32 let values = &[ "101010101010101010101011010101010101010101010101010101010101010", "101010101010101110101010110101001010101010101010010101010010101", "101010010101011010101010101010101101010101010101010101010101010", "1010101010101010100101010101010101010101010101010101010101010101", "101010101010101010101101010101010100101001010100101010101010101", "1010101010101010101010101010101011010101101010101001010101010101", "101010101010101010101010101010101010101010101101010101010101010", "101010101010110101010101010101010101010101010101010101010101010", "10101010101010101010101010101010101010101010101010101010101011", "1001010101010101010101010101010101010101010100101010101010101010", "1010101010101010101010101100101010101010110101010101010010101010", "1010011010101010101010101010101010101010101010101010101010010101", "101010101001010101010101010101010101010101010101010101010101010", "101010010110110100101010101010101010101010101010101010101010101", "1010110101010101010101010101010010101010101010101010101010101010", "101010101010101010101010101010101010101010101010101010101010101", "101010101010101010101010101010101101010101010101010101010101010", "101010101010101010101010010101010101010101010101010101010101010", "110110101001010101010010101010101010101010101010101010101010101", "101010101010010101010101010101010101010101010101010101010101010", ]; let common_values = &[ ( "101010101010101010101010101010101010101010101010101010101010101", 72208, ), ( "1010101010101010101010101010101010101010101010101010101010101010", 71633, ), ( "1010101010101010101010101010101010101010101010101010101010101001", 2387, ), ( "101010101010101010101010101010101010110101010101010101010101010", 2371, ), ( "101010101010101010101001010101010101010101010101010101010101010", 2350, ), ( "1010101010101010101010101010101010101010101010101010101010100101", 2343, ), ( "1010101010101010101010101010101001010101010101010101010101010101", 2321, ), ( "101010101010101010101010101010101010101001010101010101010101010", 2317, ), ( "1010101010101010101010101010101010101010100101010101010101010101", 2316, ), ( "1010101010101010101101010101010101010101010101010101010101010101", 2314, ), ]; let sample_median = (10184128240689698133, Some(10184139957360479594)); let sample_moment_stats = MomentStats { mean: NiceFloat(9.22742898450889e18), standard_deviation: NiceFloat(3.1984799302251884e18), skewness: NiceFloat(-0.0008313832988426654), excess_kurtosis: NiceFloat(-1.7364190763714287), }; striped_random_unsigneds_helper::( 33, 32, values, common_values, sample_median, sample_moment_stats, ); } fn striped_random_unsigneds_fail_helper() { assert_panic!(striped_random_unsigneds::(EXAMPLE_SEED, 1, 0)); assert_panic!(striped_random_unsigneds::(EXAMPLE_SEED, 2, 3)); } #[test] fn striped_random_unsigneds_fail() { apply_fn_to_unsigneds!(striped_random_unsigneds_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/variable_range_generator/next_bit_chunk.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_bit_chunk_helper(chunk_size: u64, expected_values: &[T]) { let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_bit_chunk::(chunk_size)); } assert_eq!(xs, expected_values); } #[test] fn test_next_bit_chunk() { next_bit_chunk_helper::( 1, &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0], ); next_bit_chunk_helper::( 2, &[1, 0, 3, 1, 3, 3, 2, 3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 2, 3], ); next_bit_chunk_helper::( 3, &[1, 6, 5, 7, 6, 3, 1, 2, 4, 5, 1, 2, 6, 5, 4, 6, 0, 5, 6, 0], ); next_bit_chunk_helper::( 7, &[113, 94, 23, 98, 70, 92, 52, 84, 33, 47, 1, 113, 54, 10, 47, 17, 89, 92, 119, 66], ); next_bit_chunk_helper::( 8, &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ], ); } fn next_bit_chunk_fail_helper() { assert_panic!({ let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_bit_chunk::(0) }); assert_panic!({ let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_bit_chunk::(T::WIDTH + 1) }); } #[test] fn next_bit_chunk_fail() { apply_fn_to_unsigneds!(next_bit_chunk_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/variable_range_generator/next_bool.rs ================================================ // Copyright © 2026 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 malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; #[test] fn test_next_bool() { let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(100); for _ in 0..100 { xs.push(range_generator.next_bool()); } assert_eq!( xs, &[ true, false, true, false, true, true, true, true, true, false, true, false, false, true, false, false, false, true, true, false, false, true, true, true, false, false, true, false, false, false, false, true, true, false, true, false, true, false, true, true, true, true, true, false, false, false, true, true, false, false, false, true, false, true, true, false, true, false, true, false, true, false, false, true, true, false, true, false, true, false, true, false, true, true, false, false, false, false, true, true, false, true, true, false, false, true, true, true, true, false, true, true, true, false, true, false, true, false, true, true ] ); } ================================================ FILE: malachite-base/tests/num/random/variable_range_generator/next_in_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_in_inclusive_range_helper(a: T, b: T, expected_values: &[T]) { let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_in_inclusive_range(a, b)); } assert_eq!(xs, expected_values); } #[test] fn test_next_in_inclusive_range() { next_in_inclusive_range_helper::(5, 5, &[5; 20]); next_in_inclusive_range_helper::( 1, 6, &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1], ); next_in_inclusive_range_helper::( 10, 19, &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15], ); next_in_inclusive_range_helper::( 0, u8::MAX, &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ], ); } fn next_in_inclusive_range_fail_helper() { assert_panic!({ let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_in_inclusive_range(T::TWO, T::ONE); }); } #[test] fn next_in_inclusive_range_fail() { apply_fn_to_unsigneds!(next_in_inclusive_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/variable_range_generator/next_in_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_in_range_helper(a: T, b: T, expected_values: &[T]) { let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_in_range(a, b)); } assert_eq!(xs, expected_values); } #[test] fn test_next_in_range() { next_in_range_helper::(5, 6, &[5; 20]); next_in_range_helper::( 1, 7, &[2, 6, 4, 2, 3, 5, 6, 2, 3, 6, 5, 1, 6, 1, 3, 6, 3, 1, 5, 1], ); next_in_range_helper::( 10, 20, &[11, 17, 15, 14, 16, 14, 12, 18, 11, 17, 15, 10, 12, 16, 13, 15, 12, 12, 19, 15], ); next_in_range_helper::( 0, u8::MAX, &[ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, ], ); } fn next_in_range_fail_helper() { assert_panic!({ let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_in_range(T::TWO, T::TWO); }); } #[test] fn next_in_range_fail() { apply_fn_to_unsigneds!(next_in_range_fail_helper); } ================================================ FILE: malachite-base/tests/num/random/variable_range_generator/next_less_than.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::random::EXAMPLE_SEED; use std::panic::catch_unwind; fn next_less_than_helper(limit: T, expected_values: &[T]) { let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); let mut xs = Vec::with_capacity(20); for _ in 0..20 { xs.push(range_generator.next_less_than(limit)); } assert_eq!(xs, expected_values); } #[test] fn test_next_less_than() { next_less_than_helper::(1, &[0; 20]); next_less_than_helper::( 2, &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0], ); next_less_than_helper::( 3, &[1, 0, 1, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 2, 2, 0, 1, 0, 2, 2], ); next_less_than_helper::( 4, &[1, 0, 3, 1, 3, 3, 2, 3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 2, 3], ); next_less_than_helper::( 10, &[1, 7, 5, 4, 6, 4, 2, 8, 1, 7, 5, 0, 2, 6, 3, 5, 2, 2, 9, 5], ); } fn next_less_than_fail_helper() { assert_panic!({ let mut range_generator = VariableRangeGenerator::new(EXAMPLE_SEED); range_generator.next_less_than(T::ZERO); }); } #[test] fn next_less_than_fail() { apply_fn_to_unsigneds!(next_less_than_fail_helper); } ================================================ FILE: malachite-base/tests/options/exhaustive/exhaustive_options.rs ================================================ // Copyright © 2026 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::nevers::Never; use malachite_base::options::exhaustive::exhaustive_options; use std::fmt::Debug; fn exhaustive_options_helper(xs: &[T], out: &[Option]) { assert_eq!( exhaustive_options(xs.iter().cloned()) .collect_vec() .as_slice(), out ); } #[test] fn test_exhaustive_options() { exhaustive_options_helper::(&[], &[None]); exhaustive_options_helper(&[5], &[None, Some(5)]); exhaustive_options_helper(&[1, 2, 3], &[None, Some(1), Some(2), Some(3)]); exhaustive_options_helper( &[Some(2), None, Some(5)], &[None, Some(Some(2)), Some(None), Some(Some(5))], ); } ================================================ FILE: malachite-base/tests/options/exhaustive/exhaustive_somes.rs ================================================ // Copyright © 2026 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::nevers::Never; use malachite_base::options::exhaustive::exhaustive_somes; use std::fmt::Debug; fn exhaustive_somes_helper(xs: &[T], out: &[Option]) { assert_eq!( exhaustive_somes(xs.iter().cloned()) .collect_vec() .as_slice(), out ); } #[test] fn test_exhaustive_somes() { exhaustive_somes_helper::(&[], &[]); exhaustive_somes_helper(&[5], &[Some(5)]); exhaustive_somes_helper(&[1, 2, 3], &[Some(1), Some(2), Some(3)]); exhaustive_somes_helper( &[Some(2), None, Some(5)], &[Some(Some(2)), Some(None), Some(Some(5))], ); } ================================================ FILE: malachite-base/tests/options/option_from_str.rs ================================================ // Copyright © 2026 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 malachite_base::nevers::Never; use malachite_base::options::{option_from_str, option_from_str_custom}; use malachite_base::orderings::ordering_from_str; use std::cmp::Ordering::*; use std::fmt::Debug; use std::str::FromStr; #[allow(clippy::needless_pass_by_value)] fn option_from_str_helper(s: &str, out: Option>) { assert_eq!(option_from_str(s), out); } #[test] fn test_option_from_str() { option_from_str_helper::("Some(false)", Some(Some(false))); option_from_str_helper::("Some(5)", Some(Some(5))); option_from_str_helper::("None", Some(None)); option_from_str_helper::("Some(hi)", None); option_from_str_helper::("abc", None); } #[allow(clippy::needless_pass_by_value)] fn option_from_str_custom_helper( f: &dyn Fn(&str) -> Option, s: &str, out: Option>, ) { assert_eq!(option_from_str_custom(f, s), out); } #[test] fn test_option_from_str_custom() { option_from_str_custom_helper(&ordering_from_str, "Some(Less)", Some(Some(Less))); option_from_str_custom_helper( &option_from_str, "Some(Some(false))", Some(Some(Some(false))), ); option_from_str_custom_helper(&option_from_str::, "Some(None)", Some(Some(None))); option_from_str_custom_helper(&option_from_str::, "None", Some(None)); option_from_str_custom_helper(&ordering_from_str, "Some(hi)", None); option_from_str_custom_helper(&ordering_from_str, "abc", None); } ================================================ FILE: malachite-base/tests/options/random/random_options.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::num::random::random_primitive_ints; use malachite_base::options::random::random_options; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::fmt::Debug; fn random_options_helper( p_none_numerator: u64, p_none_denominator: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[Option], expected_common_values: &[(Option, usize)], expected_median: (Option, Option>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_options(EXAMPLE_SEED, p_none_numerator, p_none_denominator, xs_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_options() { // p = 1/2 random_options_helper( 1, 2, &random_primitive_ints::, &[ Some(85), Some(11), Some(136), None, Some(200), None, Some(235), Some(134), Some(203), None, None, None, Some(223), Some(38), None, Some(235), Some(217), Some(177), Some(162), Some(32), ], &[ (None, 500454), (Some(81), 2076), (Some(208), 2066), (Some(35), 2065), (Some(211), 2045), (Some(112), 2042), (Some(143), 2039), (Some(162), 2037), (Some(170), 2036), (Some(58), 2035), ], (None, None), ); // p = 50/51 random_options_helper( 50, 51, &random_primitive_ints::, &[None; 20], &[ (None, 980283), (Some(18), 102), (Some(25), 99), (Some(237), 98), (Some(116), 97), (Some(226), 97), (Some(23), 95), (Some(185), 95), (Some(30), 94), (Some(73), 94), ], (None, None), ); // p = 1/51 random_options_helper( 1, 51, &random_primitive_ints::, &[ Some(85), Some(11), Some(136), Some(200), Some(235), Some(134), Some(203), Some(223), Some(38), Some(235), Some(217), Some(177), Some(162), Some(32), Some(166), Some(234), Some(30), Some(218), Some(90), Some(106), ], &[ (None, 19543), (Some(58), 4030), (Some(81), 4001), (Some(194), 3981), (Some(66), 3973), (Some(64), 3969), (Some(143), 3965), (Some(4), 3964), (Some(196), 3952), (Some(208), 3941), ], (Some(125), None), ); // p = 1/11 random_options_helper( 1, 11, &|seed| random_options(seed, 1, 11, &random_primitive_ints::), &[ Some(Some(229)), Some(Some(58)), Some(Some(126)), Some(Some(192)), Some(Some(140)), Some(Some(235)), Some(Some(50)), Some(Some(162)), Some(Some(5)), Some(Some(14)), Some(Some(107)), Some(Some(218)), Some(Some(96)), Some(Some(86)), Some(Some(51)), None, Some(Some(240)), Some(Some(186)), Some(Some(180)), Some(Some(152)), ], &[ (None, 90592), (Some(None), 83007), (Some(Some(186)), 3385), (Some(Some(193)), 3377), (Some(Some(83)), 3366), (Some(Some(55)), 3365), (Some(Some(245)), 3362), (Some(Some(148)), 3354), (Some(Some(143)), 3345), (Some(Some(136)), 3341), ], (Some(Some(101)), None), ); } #[test] #[should_panic] fn random_options_fail_1() { random_options(EXAMPLE_SEED, 1, 0, &random_primitive_ints::); } #[test] #[should_panic] fn random_options_fail_2() { random_options(EXAMPLE_SEED, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/options/random/random_somes.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::num::random::random_primitive_ints; use malachite_base::options::random::random_somes; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::fmt::Debug; fn random_somes_helper( xs: I, expected_values: &[Option], expected_common_values: &[(Option, usize)], expected_median: (Option, Option>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_somes(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_somes() { random_somes_helper( random_primitive_ints::(EXAMPLE_SEED), &[ Some(113), Some(239), Some(69), Some(108), Some(228), Some(210), Some(168), Some(161), Some(87), Some(32), Some(110), Some(83), Some(188), Some(34), Some(89), Some(238), Some(93), Some(200), Some(149), Some(115), ], &[ (Some(214), 4097), (Some(86), 4078), (Some(166), 4049), (Some(22), 4048), (Some(126), 4047), (Some(55), 4040), (Some(93), 4037), (Some(191), 4036), (Some(36), 4035), (Some(42), 4032), ], (Some(127), None), ); random_somes_helper( random_somes(random_primitive_ints::(EXAMPLE_SEED)), &[ Some(Some(113)), Some(Some(239)), Some(Some(69)), Some(Some(108)), Some(Some(228)), Some(Some(210)), Some(Some(168)), Some(Some(161)), Some(Some(87)), Some(Some(32)), Some(Some(110)), Some(Some(83)), Some(Some(188)), Some(Some(34)), Some(Some(89)), Some(Some(238)), Some(Some(93)), Some(Some(200)), Some(Some(149)), Some(Some(115)), ], &[ (Some(Some(214)), 4097), (Some(Some(86)), 4078), (Some(Some(166)), 4049), (Some(Some(22)), 4048), (Some(Some(126)), 4047), (Some(Some(55)), 4040), (Some(Some(93)), 4037), (Some(Some(191)), 4036), (Some(Some(36)), 4035), (Some(Some(42)), 4032), ], (Some(Some(127)), None), ); } ================================================ FILE: malachite-base/tests/orderings/exhaustive.rs ================================================ // Copyright © 2026 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::orderings::exhaustive::{exhaustive_orderings, orderings_increasing}; use std::cmp::Ordering::*; #[test] fn test_orderings_increasing() { assert_eq!( orderings_increasing().collect_vec(), &[Less, Equal, Greater] ); } #[test] fn test_exhaustive_orderings() { assert_eq!( exhaustive_orderings().collect_vec(), &[Equal, Less, Greater] ); } ================================================ FILE: malachite-base/tests/orderings/ordering_from_str.rs ================================================ // Copyright © 2026 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 malachite_base::orderings::ordering_from_str; use std::cmp::Ordering::*; #[test] fn test_from_str() { let test = |s, out| { assert_eq!(ordering_from_str(s), out); }; test("Equal", Some(Equal)); test("Less", Some(Less)); test("Greater", Some(Greater)); test("", None); test("abc", None); test("Lesser", None); } ================================================ FILE: malachite-base/tests/orderings/random.rs ================================================ // Copyright © 2026 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::orderings::random::random_orderings; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::cmp::Ordering::*; #[test] fn test_random_orderings() { let xs = random_orderings(EXAMPLE_SEED); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), ( &[ Less, Equal, Less, Greater, Less, Less, Equal, Less, Equal, Greater, Less, Equal, Less, Greater, Greater, Equal, Less, Equal, Greater, Greater ][..], &[(Less, 333784), (Greater, 333516), (Equal, 332700)][..], (Equal, None) ) ); } ================================================ FILE: malachite-base/tests/random/fork.rs ================================================ // Copyright © 2026 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 malachite_base::random::{EXAMPLE_SEED, Seed}; #[test] fn test_fork() { assert_eq!( EXAMPLE_SEED.fork("first"), Seed::from_bytes([ 0x20, 0x18, 0x1, 0x3d, 0x96, 0x4d, 0x3e, 0x98, 0x10, 0x9d, 0x35, 0x75, 0x22, 0x89, 0xf7, 0xe9, 0xbe, 0x2f, 0x9c, 0x15, 0x95, 0x42, 0x1a, 0x79, 0x52, 0xf, 0x56, 0x9a, 0x7b, 0x8c, 0xd9, 0x34 ]) ); assert_eq!( EXAMPLE_SEED.fork("second"), Seed::from_bytes([ 0xe0, 0x36, 0x88, 0x58, 0x6d, 0x67, 0x33, 0xea, 0xf2, 0x1c, 0x88, 0xf9, 0xe3, 0xbd, 0x52, 0xc0, 0xe5, 0xad, 0x61, 0x81, 0x21, 0xd8, 0x2f, 0x8e, 0xcd, 0xf, 0x89, 0x9d, 0x32, 0xc5, 0x35, 0x83 ]) ); } ================================================ FILE: malachite-base/tests/random/from_bytes.rs ================================================ // Copyright © 2026 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 malachite_base::random::EXAMPLE_SEED; use malachite_base::random::Seed; #[test] fn test_from_bytes() { assert_eq!(Seed::from_bytes(EXAMPLE_SEED.bytes), EXAMPLE_SEED); } ================================================ FILE: malachite-base/tests/random/get_rng.rs ================================================ // Copyright © 2026 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 malachite_base::random::EXAMPLE_SEED; use rand_chacha::rand_core::RngCore; #[test] fn test_get_rng() { let mut bytes = [0; 32]; EXAMPLE_SEED.get_rng().fill_bytes(&mut bytes); assert_eq!( bytes, [ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, 189, 149, 217, 201, 117, 146, 31, 72, 151, 169, 174, 33 ] ); } ================================================ FILE: malachite-base/tests/random/next.rs ================================================ // Copyright © 2026 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 malachite_base::random::{EXAMPLE_SEED, Seed}; #[test] fn test_next() { assert_eq!( EXAMPLE_SEED.next(), Seed::from_bytes([ 113, 239, 69, 108, 228, 210, 168, 161, 87, 32, 110, 83, 188, 34, 89, 238, 93, 200, 149, 115, 189, 149, 217, 201, 117, 146, 31, 72, 151, 169, 174, 33 ]) ); } ================================================ FILE: malachite-base/tests/rational_sequences/access/get.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{ unsigned_rational_sequence_unsigned_pair_gen_var_1, unsigned_rational_sequence_unsigned_pair_gen_var_2, }; #[test] pub fn test_get() { fn test(non_repeating: &[u8], repeating: &[u8], index: usize, out: Option<&u8>) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.get(index), out); } test(&[], &[], 0, None); test(&[1, 2, 3], &[], 0, Some(&1)); test(&[1, 2, 3], &[], 1, Some(&2)); test(&[1, 2, 3], &[], 2, Some(&3)); test(&[1, 2, 3], &[], 3, None); test(&[1, 2, 3], &[4], 3, Some(&4)); test(&[1, 2, 3], &[4], 100, Some(&4)); } #[test] pub fn test_index() { fn test(non_repeating: &[u8], repeating: &[u8], index: usize, out: u8) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs[index], out); } test(&[1, 2, 3], &[], 0, 1); test(&[1, 2, 3], &[], 1, 2); test(&[1, 2, 3], &[], 2, 3); test(&[1, 2, 3], &[4], 3, 4); test(&[1, 2, 3], &[4], 100, 4); } #[allow(clippy::unnecessary_operation)] #[test] #[should_panic] fn index_fail_1() { RationalSequence::::from_vec(vec![])[0]; } #[allow(clippy::unnecessary_operation)] #[test] #[should_panic] fn index_fail_2() { RationalSequence::from_vec(vec![1, 2, 3])[3]; } #[test] fn get_properties() { unsigned_rational_sequence_unsigned_pair_gen_var_1::().test_properties( |(xs, index)| { assert_eq!(xs.get(index), xs.iter().nth(index)); }, ); } #[test] fn index_properties() { unsigned_rational_sequence_unsigned_pair_gen_var_2::().test_properties(|(xs, index)| { let x = xs[index]; assert_eq!(xs.iter().nth(index).unwrap(), &x); assert_eq!(xs.get(index), Some(&x)); }); } ================================================ FILE: malachite-base/tests/rational_sequences/access/mutate.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::large_type_gen_var_22; #[test] pub fn test_mutate() { fn test( non_repeating: &[u8], repeating: &[u8], index: usize, new_value: u8, out: u8, non_repeating_out: &[u8], repeating_out: &[u8], ) { let mut xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!( xs.mutate(index, |x| { *x = new_value; out }), out ); assert_eq!( xs, RationalSequence::from_slices(non_repeating_out, repeating_out) ); } test(&[1, 2, 3], &[], 0, 5, 6, &[5, 2, 3], &[]); test(&[1, 2, 3], &[], 1, 5, 6, &[1, 5, 3], &[]); test(&[1, 2, 3], &[], 2, 5, 6, &[1, 2, 5], &[]); test( &[1, 2, 3], &[4, 5, 6], 3, 100, 6, &[1, 2, 3, 100], &[5, 6, 4], ); test( &[1, 2, 3], &[4, 5, 6], 10, 100, 6, &[1, 2, 3, 4, 5, 6, 4, 5, 6, 4, 100], &[6, 4, 5], ); } #[test] #[should_panic] fn mutate_fail_1() { RationalSequence::::from_vec(vec![]).mutate(0, |_| {}); } #[test] #[should_panic] fn mutate_fail_2() { RationalSequence::from_vec(vec![1, 2, 3]).mutate(3, |_| {}); } #[test] fn mutate_properties() { large_type_gen_var_22::().test_properties(|(mut xs, index, y, z)| { let xs_old = xs.clone(); let x_old = xs[index]; assert_eq!( xs.mutate(index, |x| { *x = y; z }), z ); assert_eq!(xs[index], y); xs.mutate(index, |x| { *x = x_old; }); assert_eq!(xs, xs_old); }); } ================================================ FILE: malachite-base/tests/rational_sequences/basic/component_len.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{unsigned_rational_sequence_gen, unsigned_vec_gen}; #[test] pub fn test_component_len() { fn test(non_repeating: &[u8], repeating: &[u8], out: usize) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.component_len(), out); } test(&[], &[], 0); test(&[1, 2, 3], &[], 3); test(&[], &[1, 2, 3], 3); test(&[1, 2, 3], &[4, 5, 6], 6); } #[test] fn component_len_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { xs.component_len(); }); unsigned_vec_gen::().test_properties(|xs| { assert_eq!(RationalSequence::from_slice(&xs).component_len(), xs.len()); }); } ================================================ FILE: malachite-base/tests/rational_sequences/basic/is_empty.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; #[test] pub fn test_is_empty() { fn test(non_repeating: &[u8], repeating: &[u8], out: bool) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.is_empty(), out); } test(&[], &[], true); test(&[1, 2, 3], &[], false); test(&[], &[1, 2, 3], false); test(&[1, 2, 3], &[4, 5, 6], false); } #[test] fn is_empty_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { let empty = xs.is_empty(); assert_eq!(empty, xs == RationalSequence::from_vec(vec![])); assert_eq!(empty, xs.component_len() == 0); }); } ================================================ FILE: malachite-base/tests/rational_sequences/basic/is_finite.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{unsigned_rational_sequence_gen, unsigned_vec_gen}; #[test] pub fn test_is_finite() { fn test(non_repeating: &[u8], repeating: &[u8], out: bool) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.is_finite(), out); } test(&[], &[], true); test(&[1, 2, 3], &[], true); test(&[], &[1, 2, 3], false); test(&[1, 2, 3], &[4, 5, 6], false); } #[test] fn is_finite_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { assert_eq!(xs.is_finite(), xs.slices_ref().1.is_empty()); }); unsigned_vec_gen::().test_properties(|xs| { assert!(RationalSequence::from_slice(&xs).is_finite()); }); } ================================================ FILE: malachite-base/tests/rational_sequences/basic/iter.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::{count_is_at_least, prefix_to_string}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{unsigned_rational_sequence_gen, unsigned_vec_gen}; #[test] pub fn test_iter() { fn test(non_repeating: &[u8], repeating: &[u8], out: &str) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(prefix_to_string(xs.iter(), 10), out); } test(&[], &[], "[]"); test(&[1, 2, 3], &[], "[1, 2, 3]"); test(&[], &[1, 2, 3], "[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, ...]"); test( &[1, 2, 3], &[4, 5, 6], "[1, 2, 3, 4, 5, 6, 4, 5, 6, 4, ...]", ); } #[test] fn iter_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { let mut it = xs.iter(); if let Some(len) = xs.len() { assert_eq!(it.count(), len); } else { assert!(count_is_at_least(&mut it, 20)); } let non_rep_len = xs.slices_ref().0.len(); let rep_len = xs.slices_ref().1.len(); assert!(Iterator::eq( xs.iter().take(non_rep_len), xs.slices_ref().0.iter() )); assert!(Iterator::eq( xs.iter().skip(non_rep_len).take(rep_len), xs.slices_ref().1.iter() )); }); unsigned_vec_gen::().test_properties(|xs| { assert!(Iterator::eq( xs.iter(), RationalSequence::from_slice(&xs).iter() )); }); } ================================================ FILE: malachite-base/tests/rational_sequences/basic/len.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{unsigned_rational_sequence_gen, unsigned_vec_gen}; #[test] pub fn test_len() { fn test(non_repeating: &[u8], repeating: &[u8], out: Option) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.len(), out); } test(&[], &[], Some(0)); test(&[1, 2, 3], &[], Some(3)); test(&[], &[1, 2, 3], None); test(&[1, 2, 3], &[4, 5, 6], None); } #[test] fn len_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { assert_eq!(xs.len().is_some(), xs.is_finite()); }); unsigned_vec_gen::().test_properties(|xs| { assert_eq!(RationalSequence::from_slice(&xs).len(), Some(xs.len())); }); } ================================================ FILE: malachite-base/tests/rational_sequences/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{ unsigned_rational_sequence_gen, unsigned_rational_sequence_pair_gen, unsigned_rational_sequence_triple_gen, }; use std::cmp::Ordering::*; #[test] fn test_cmp() { let xs = &[ RationalSequence::from_vec(vec![]), RationalSequence::from_vec(vec![1, 2, 3]), RationalSequence::from_vecs(vec![], vec![1, 2, 3]), RationalSequence::from_vecs(vec![1, 2, 3], vec![4, 5, 6]), RationalSequence::from_vec(vec![1, 2, 4]), ]; for (i, x) in xs.iter().enumerate() { for (j, y) in xs.iter().enumerate() { assert_eq!(i.cmp(&j), x.clone().cmp(&y.clone())); } } } #[test] fn cmp_properties() { unsigned_rational_sequence_pair_gen::().test_properties(|(xs, ys)| { let ord = xs.cmp(&ys); assert_eq!(ys.cmp(&xs).reverse(), ord); assert_eq!(xs == ys, xs.cmp(&ys) == Equal); }); let empty = RationalSequence::from_vec(vec![]); unsigned_rational_sequence_gen::().test_properties(|xs| { assert_eq!(xs.cmp(&xs), Equal); assert!(xs >= empty); }); unsigned_rational_sequence_triple_gen::().test_properties(|(xs, ys, zs)| { if xs < ys && ys < zs { assert!(xs < zs); } else if xs > ys && ys > zs { assert!(xs > zs); } }); } ================================================ FILE: malachite-base/tests/rational_sequences/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{ unsigned_rational_sequence_gen, unsigned_rational_sequence_pair_gen, unsigned_rational_sequence_triple_gen, }; #[test] fn test_eq() { let xs = &[ RationalSequence::from_vec(vec![]), RationalSequence::from_vec(vec![1, 2, 3]), RationalSequence::from_vecs(vec![], vec![1, 2, 3]), RationalSequence::from_vecs(vec![1, 2, 3], vec![4, 5, 6]), ]; for (i, x) in xs.iter().enumerate() { for (j, y) in xs.iter().enumerate() { assert_eq!(i == j, x.clone() == y.clone()); } } } #[test] fn eq_properties() { unsigned_rational_sequence_pair_gen::().test_properties(|(xs, ys)| { assert_eq!(xs == ys, ys == xs); }); unsigned_rational_sequence_gen::().test_properties(|xs| { assert_eq!(xs, xs); }); unsigned_rational_sequence_triple_gen::().test_properties(|(xs, ys, zs)| { if xs == ys && ys == zs { assert_eq!(xs, zs); } }); } ================================================ FILE: malachite-base/tests/rational_sequences/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::unsigned_rational_sequence_gen; use malachite_base::test_util::hash::hash; #[test] fn hash_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { assert_eq!(hash(&xs), hash(&xs.clone())); }); } ================================================ FILE: malachite-base/tests/rational_sequences/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::{ unsigned_rational_sequence_gen, unsigned_rational_sequence_pair_gen, }; #[test] #[allow(clippy::redundant_clone)] fn test_clone() { let test = |nr: &[u8], r: &[u8]| { let xs = RationalSequence::from_slices(nr, r); let xs_clone = xs.clone(); assert!(xs.is_valid()); assert_eq!(xs_clone, xs); }; test(&[], &[]); test(&[1, 2, 3], &[]); test(&[], &[1, 2, 3]); test(&[1, 2, 3], &[4, 5, 5]); } #[test] fn test_clone_from() { let test = |nr_1: &[u8], r_1: &[u8], nr_2: &[u8], r_2: &[u8]| { let mut x = RationalSequence::from_slices(nr_1, r_1); let y = RationalSequence::from_slices(nr_2, r_2); x.clone_from(&y); assert!(x.is_valid()); assert_eq!(x, y); }; test(&[], &[], &[1, 2, 3], &[4, 5, 6]); test(&[], &[1, 2, 3], &[1, 2, 3], &[]); } #[allow(clippy::redundant_clone)] #[test] fn clone_and_clone_from_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { let mut_xs = xs.clone(); assert!(mut_xs.is_valid()); assert_eq!(mut_xs, xs); }); unsigned_rational_sequence_pair_gen::().test_properties(|(xs, ys)| { let mut mut_xs = xs.clone(); mut_xs.clone_from(&ys); assert!(mut_xs.is_valid()); assert_eq!(mut_xs, ys); }); } ================================================ FILE: malachite-base/tests/rational_sequences/conversion/from_vec.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::unsigned_vec_gen; #[test] pub fn test_from_vec_and_from_slice() { fn test(non_repeating: &[u8], out: &str) { assert_eq!(RationalSequence::from_slice(non_repeating).to_string(), out); assert_eq!( RationalSequence::from_vec(non_repeating.to_vec()).to_string(), out ); } test(&[], "[]"); test(&[1, 2, 3], "[1, 2, 3]"); } #[test] fn from_vec_and_from_slice_properties() { unsigned_vec_gen::().test_properties(|xs| { let rs = RationalSequence::from_slice(&xs); assert!(rs.is_valid()); assert_eq!(rs.to_string(), xs.to_debug_string()); assert!(rs.is_finite()); assert_eq!(RationalSequence::from_vec(xs), rs); }); } ================================================ FILE: malachite-base/tests/rational_sequences/conversion/from_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::{RationalSequence, rational_sequence_is_reduced}; use malachite_base::test_util::generators::unsigned_vec_pair_gen; #[test] pub fn test_from_vecs_and_from_slices() { fn test(non_repeating: &[u8], repeating: &[u8], out: &str) { assert_eq!( RationalSequence::from_slices(non_repeating, repeating).to_string(), out ); assert_eq!( RationalSequence::from_vecs(non_repeating.to_vec(), repeating.to_vec()).to_string(), out ); } test(&[], &[], "[]"); test(&[1, 2, 3], &[], "[1, 2, 3]"); test(&[], &[1, 2, 3], "[[1, 2, 3]]"); test(&[1, 2, 3], &[4, 5, 6], "[1, 2, 3, [4, 5, 6]]"); test(&[1, 2], &[3, 4, 3, 4], "[1, 2, [3, 4]]"); test(&[1, 2, 3], &[4, 3, 4, 3], "[1, 2, [3, 4]]"); test(&[1, 2, 3, 4], &[3, 4, 3, 4], "[1, 2, [3, 4]]"); } #[test] fn from_vec_and_from_slice_properties() { unsigned_vec_pair_gen::().test_properties(|(xs, ys)| { let rs = RationalSequence::from_slices(&xs, &ys); assert!(rs.is_valid()); assert_eq!(RationalSequence::from_vecs(xs.clone(), ys.clone()), rs); if rational_sequence_is_reduced(&xs, &ys) { assert_eq!(rs.into_vecs(), (xs, ys)); } }); } ================================================ FILE: malachite-base/tests/rational_sequences/conversion/to_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::generators::unsigned_rational_sequence_gen; #[test] pub fn test_to_vecs_into_vecs_and_slices_ref() { fn test(non_repeating: &[u8], repeating: &[u8], o_xs: &[u8], o_ys: &[u8]) { let xs = RationalSequence::from_slices(non_repeating, repeating); let (out_xs, out_ys) = xs.to_vecs(); assert_eq!(out_xs, o_xs); assert_eq!(out_ys, o_ys); let (out_xs, out_ys) = xs.clone().into_vecs(); assert_eq!(out_xs, o_xs); assert_eq!(out_ys, o_ys); let (out_xs, out_ys) = xs.slices_ref(); assert_eq!(out_xs, o_xs); assert_eq!(out_ys, o_ys); } test(&[], &[], &[], &[]); test(&[1, 2, 3], &[], &[1, 2, 3], &[]); test(&[], &[1, 2, 3], &[], &[1, 2, 3]); test(&[1, 2, 3], &[4, 5, 6], &[1, 2, 3], &[4, 5, 6]); } #[test] fn to_vecs_into_vecs_and_slices_ref_properties() { unsigned_rational_sequence_gen::().test_properties(|rxs| { let (xs, ys) = rxs.to_vecs(); let (xs_alt, ys_alt) = rxs.clone().into_vecs(); assert_eq!(xs_alt, xs); assert_eq!(ys_alt, ys); let (xs_alt, ys_alt) = rxs.slices_ref(); assert_eq!(xs_alt, xs); assert_eq!(ys_alt, ys); assert_eq!(RationalSequence::from_vecs(xs, ys), rxs); }); } ================================================ FILE: malachite-base/tests/rational_sequences/exhaustive.rs ================================================ // Copyright © 2026 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::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::rational_sequences::exhaustive::exhaustive_rational_sequences; use malachite_base::strings::ToDebugString; use malachite_base::tuples::exhaustive::exhaustive_units; use std::fmt::{Display, Formatter, Result}; #[derive(Clone, Eq, PartialEq)] struct Unit(()); impl Display for Unit { fn fmt(&self, f: &mut Formatter) -> Result { f.write_str("()") } } #[test] fn test_exhaustive_rational_sequences() { assert_eq!( exhaustive_rational_sequences(nevers()) .collect_vec() .to_debug_string(), "[[]]" ); assert_eq!( exhaustive_rational_sequences(exhaustive_units().map(Unit)) .take(20) .collect_vec() .to_debug_string(), "[[], [[()]], [()], [(), ()], [(), (), (), ()], [(), (), ()], [(), (), (), (), ()], \ [(), (), (), (), (), ()], [(), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), ()], [(), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], \ [(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()]]" ); assert_eq!( exhaustive_rational_sequences(exhaustive_bools()) .take(20) .collect_vec() .to_debug_string(), "[[], [[false]], [false], [[true]], [false, [true]], [true], [true, [false]], \ [false, false, false], [false, false, false, [true]], [[false, false, true]], \ [false, [false, false, true]], [[false, true]], [false, [false, true]], \ [false, false, false, [false, false, true]], [false, false, false, [false, true]], \ [false, false], [false, false, true], [false, false, true, [false]], \ [false, false, [true]], [false, true]]" ); assert_eq!( exhaustive_rational_sequences(exhaustive_unsigneds::()) .take(20) .collect_vec() .to_debug_string(), "[[], [[0]], [0], [[1]], [0, [1]], [1], [1, [0]], [0, 0, 0], [0, 0, 0, [1]], [[2]], \ [0, [2]], [[3]], [0, [3]], [1, [2]], [0, 0, 0, [2]], [1, [3]], [0, 0, 0, [3]], [2], \ [2, [0]], [0, 0]]" ); } ================================================ FILE: malachite-base/tests/rational_sequences/random.rs ================================================ // Copyright © 2026 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::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::rational_sequences::RationalSequence; use malachite_base::rational_sequences::random::random_rational_sequences; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; #[test] fn test_random_rational_sequences() { let xs = random_rational_sequences(EXAMPLE_SEED, &random_primitive_ints::, 4, 1); let values = xs .clone() .map(|x| RationalSequence::to_string(&x)) .take(20) .collect_vec(); let values = values.iter().map(String::as_str).collect_vec(); let common_values = common_values_map(1000000, 10, xs.clone()) .into_iter() .map(|(x, freq)| (x.to_string(), freq)) .collect_vec(); let common_values = common_values .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.take(1000000)); let (median_lo, median_hi) = ( median_lo.to_string(), median_hi.map(|x| RationalSequence::to_string(&x)), ); let actual_median = (median_lo.as_str(), median_hi.as_deref()); assert_eq!( (values.as_slice(), common_values.as_slice(), actual_median), ( &[ "[[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32]]", "[166, 234, 30, 218, [90, 106, 9, 216]]", "[204]", "[151, 213, 97, 253, 78, [91, 39]]", "[191, 175, 170, 232]", "[233, 2, 35, 22, 217, 198]", "[[114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144]]", "[148, 79, 115, 52, 73, 69, 137, 91]", "[153, 178, 112]", "[34, 95, 106, 167, 197, [130, 168, 122, 207, 172, 177, 86, 150, 221]]", "[218, [101]]", "[115, 74, 9, 123, 109, 52, 201]", "[159, 247, 250, 48, 133, 235, 196, 40, [97]]", "[104, 68, 190, [216, 7, 216, 157, 43, 43, 112]]", "[]", "[217, 24, 11, 103, 211, [84, 135]]", "[[55, 29, 206, 89, 65, 191, 51, 9, 79]]", "[[148, 34]]", "[22, 22, 62, 3, 114, 118, 20, 47, 194, 50, 32, [120, 176, 166, 23]]", "[204, 248, 177, 238, 237, 222, 154, 113, [225, 65]]" ][..], &[ ("[]", 39885), ("[[243]]", 157), ("[68]", 154), ("[1]", 153), ("[120]", 153), ("[71]", 152), ("[[40]]", 152), ("[[158]]", 151), ("[[169]]", 151), ("[[183]]", 151) ][..], ( "[122, 194, 41, 122, [232]]", Some("[[122, 194, 89, 228, 124, 219]]") ) ) ); } ================================================ FILE: malachite-base/tests/rational_sequences/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{unsigned_rational_sequence_gen, unsigned_vec_gen}; #[test] pub fn test_to_string() { fn test(non_repeating: &[u8], repeating: &[u8], out: &str) { let xs = RationalSequence::from_slices(non_repeating, repeating); assert_eq!(xs.to_string(), out); assert_eq!(xs.to_debug_string(), out); } test(&[], &[], "[]"); test(&[1, 2, 3], &[], "[1, 2, 3]"); test(&[], &[1, 2, 3], "[[1, 2, 3]]"); test(&[1, 2, 3], &[4, 5, 6], "[1, 2, 3, [4, 5, 6]]"); } #[test] fn to_string_properties() { unsigned_rational_sequence_gen::().test_properties(|xs| { let s = xs.to_string(); assert_eq!(xs.to_debug_string(), s); assert!(string_is_subset(&s, " ,0123456789[]")); }); unsigned_vec_gen::().test_properties(|xs| { assert_eq!( RationalSequence::from_slice(&xs).to_string(), xs.to_debug_string() ); }); } ================================================ FILE: malachite-base/tests/rounding_modes/clone.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{rounding_mode_gen, rounding_mode_pair_gen}; #[test] #[allow(clippy::clone_on_copy)] fn test_clone() { let test = |rm: RoundingMode| { let cloned = rm.clone(); assert_eq!(cloned, rm); }; test(Down); test(Up); test(Floor); test(Ceiling); test(Nearest); test(Exact); } #[test] fn test_clone_from() { let test = |mut x: RoundingMode, y: RoundingMode| { x.clone_from(&y); assert_eq!(x, y); }; test(Exact, Floor); test(Up, Ceiling); } #[test] fn clone_and_clone_from_properties() { rounding_mode_gen().test_properties(|rm| { assert_eq!(rm.clone(), rm); }); rounding_mode_pair_gen().test_properties(|(x, y)| { let mut mut_x = x; mut_x.clone_from(&y); assert_eq!(mut_x, y); }); } ================================================ FILE: malachite-base/tests/rounding_modes/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::common::test_cmp_helper; use malachite_base::test_util::generators::{ rounding_mode_gen, rounding_mode_pair_gen, rounding_mode_triple_gen, }; use std::cmp::Ordering::*; #[test] fn test_cmp() { test_cmp_helper::(&["Down", "Up", "Floor", "Ceiling", "Nearest", "Exact"]); } #[test] fn cmp_properties() { rounding_mode_pair_gen().test_properties(|(x, y)| { let ord = x.cmp(&y); assert_eq!(y.cmp(&x).reverse(), ord); }); rounding_mode_gen().test_properties(|x| { assert_eq!(x.cmp(&x), Equal); }); rounding_mode_triple_gen().test_properties(|(x, y, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); } ================================================ FILE: malachite-base/tests/rounding_modes/eq.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::common::test_eq_helper; use malachite_base::test_util::generators::{ rounding_mode_gen, rounding_mode_pair_gen, rounding_mode_triple_gen, }; #[test] fn test_eq() { test_eq_helper::(&["Down", "Up", "Floor", "Ceiling", "Nearest", "Exact"]); } #[test] #[allow(clippy::eq_op)] fn eq_properties() { rounding_mode_pair_gen().test_properties(|(x, y)| { assert_eq!(x == y, y == x); }); rounding_mode_gen().test_properties(|rm| { assert_eq!(rm, rm); }); rounding_mode_triple_gen().test_properties(|(x, y, z)| { if x == y && x == z { assert_eq!(x, z); } }); } ================================================ FILE: malachite-base/tests/rounding_modes/exhaustive.rs ================================================ // Copyright © 2026 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::rounding_modes::RoundingMode::*; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; #[test] fn test_exhaustive_rounding_modes() { assert_eq!( exhaustive_rounding_modes().collect_vec(), &[Down, Up, Floor, Ceiling, Nearest, Exact] ); } ================================================ FILE: malachite-base/tests/rounding_modes/from_str.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{string_gen, string_gen_var_2}; use std::str::FromStr; #[test] fn test_from_str() { let test = |s, out| { assert_eq!(RoundingMode::from_str(s), out); }; test("Down", Ok(Down)); test("Up", Ok(Up)); test("Floor", Ok(Floor)); test("Ceiling", Ok(Ceiling)); test("Nearest", Ok(Nearest)); test("Exact", Ok(Exact)); test("", Err("".to_string())); test("abc", Err("abc".to_string())); test("Uptown", Err("Uptown".to_string())); } #[allow(clippy::needless_pass_by_value)] fn from_str_helper(s: String) { let result = RoundingMode::from_str(&s); if let Ok(result) = result { assert_eq!(result.to_string(), s); } } #[test] fn from_str_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_length_d", 1); string_gen().test_properties_with_config(&config, from_str_helper); string_gen_var_2().test_properties_with_config(&config, from_str_helper); } ================================================ FILE: malachite-base/tests/rounding_modes/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::rounding_mode_gen; use malachite_base::test_util::hash::hash; #[test] fn hash_properties() { rounding_mode_gen().test_properties(|rm| { assert_eq!(hash(&rm), hash(&rm.clone())); }); } ================================================ FILE: malachite-base/tests/rounding_modes/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::rounding_mode_gen; #[test] fn test_neg() { let test = |mut rm: RoundingMode, out| { assert_eq!(-rm, out); rm.neg_assign(); assert_eq!(rm, out); }; test(Down, Down); test(Up, Up); test(Floor, Ceiling); test(Ceiling, Floor); test(Nearest, Nearest); test(Exact, Exact); } #[test] fn neg_properties() { rounding_mode_gen().test_properties(|rm| { assert_eq!(-(-rm), rm); let mut rm_alt = rm; rm_alt.neg_assign(); assert_eq!(rm_alt, -rm); }); } ================================================ FILE: malachite-base/tests/rounding_modes/random.rs ================================================ // Copyright © 2026 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::random::EXAMPLE_SEED; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::stats::common_values_map::common_values_map; #[test] fn test_random_rounding_modes() { let xs = random_rounding_modes(EXAMPLE_SEED); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, xs.clone()); assert_eq!( (values.as_slice(), common_values.as_slice()), ( &[ Up, Exact, Ceiling, Up, Floor, Nearest, Exact, Up, Floor, Exact, Nearest, Down, Exact, Down, Floor, Exact, Floor, Down, Nearest, Down ][..], &[ (Ceiling, 167408), (Down, 167104), (Nearest, 166935), (Exact, 166549), (Floor, 166068), (Up, 165936) ][..] ) ); } ================================================ FILE: malachite-base/tests/rounding_modes/size.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode; use std::mem::size_of; #[test] fn test_size() { assert_eq!(size_of::(), 1); } ================================================ FILE: malachite-base/tests/rounding_modes/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::rounding_mode_gen; use malachite_base::test_util::rounding_modes::ROUNDING_MODE_CHARS; use std::str::FromStr; #[test] fn test_to_string() { let test = |rm: RoundingMode, out| { assert_eq!(rm.to_string(), out); }; test(Down, "Down"); test(Up, "Up"); test(Floor, "Floor"); test(Ceiling, "Ceiling"); test(Nearest, "Nearest"); test(Exact, "Exact"); } #[test] fn to_string_properties() { rounding_mode_gen().test_properties(|rm| { let s = rm.to_string(); assert_eq!(RoundingMode::from_str(&s), Ok(rm)); assert!(string_is_subset(&s, ROUNDING_MODE_CHARS)); }); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_b_tree_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_b_tree_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn exhaustive_b_tree_sets_helper(xs: I, out: &[BTreeSet]) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_helper_helper(exhaustive_b_tree_sets(xs), out); } fn exhaustive_b_tree_sets_small_helper( xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_small_helper_helper(exhaustive_b_tree_sets(xs), out_len, out); } #[test] fn test_exhaustive_b_tree_sets() { exhaustive_b_tree_sets_small_helper(nevers(), 1, &[btreeset! {}]); exhaustive_b_tree_sets_small_helper(exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}]); exhaustive_b_tree_sets_small_helper( exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); exhaustive_b_tree_sets_small_helper( 1..=6, 64, &[ btreeset! {}, btreeset! {1}, btreeset! {2}, btreeset! {1, 2}, btreeset! {3}, btreeset! {1, 3}, btreeset! {2, 3}, btreeset! {1, 2, 3}, btreeset! {4}, btreeset! {1, 4}, btreeset! {2, 4}, btreeset! {1, 2, 4}, btreeset! {3, 4}, btreeset! {1, 3, 4}, btreeset! {2, 3, 4}, btreeset! {1, 2, 3, 4}, btreeset! {5}, btreeset! {1, 5}, btreeset! {2, 5}, btreeset! {1, 2, 5}, ], ); exhaustive_b_tree_sets_small_helper( 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'a', 'b'}, btreeset! {'c'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); exhaustive_b_tree_sets_helper( exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'a', 'b'}, btreeset! {'c'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, btreeset! {'d'}, btreeset! {'a', 'd'}, btreeset! {'b', 'd'}, btreeset! {'a', 'b', 'd'}, btreeset! {'c', 'd'}, btreeset! {'a', 'c', 'd'}, btreeset! {'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'e'}, btreeset! {'a', 'e'}, btreeset! {'b', 'e'}, btreeset! {'a', 'b', 'e'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_b_tree_sets_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_fixed_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_fixed_length; use std::collections::BTreeSet; use std::fmt::Debug; fn exhaustive_b_tree_sets_fixed_length_helper( len: u64, xs: I, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_helper_helper(exhaustive_b_tree_sets_fixed_length(len, xs), out); } fn exhaustive_b_tree_sets_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_small_helper_helper( exhaustive_b_tree_sets_fixed_length(len, xs), out_len, out, ); } #[test] fn test_exhaustive_b_tree_sets_fixed_length() { // This demonstrates that 0 ^ 0 == 1: exhaustive_b_tree_sets_fixed_length_small_helper(0, nevers(), 1, &[btreeset! {}]); exhaustive_b_tree_sets_fixed_length_small_helper(1, nevers(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper(2, nevers(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper(5, nevers(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper(1, exhaustive_units(), 1, &[btreeset! {()}]); exhaustive_b_tree_sets_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper( 0, exhaustive_unsigneds::(), 1, &[btreeset! {}], ); exhaustive_b_tree_sets_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ btreeset! {0}, btreeset! {1}, btreeset! {2}, btreeset! {3}, btreeset! {4}, btreeset! {5}, btreeset! {6}, btreeset! {7}, btreeset! {8}, btreeset! {9}, btreeset! {10}, btreeset! {11}, btreeset! {12}, btreeset! {13}, btreeset! {14}, btreeset! {15}, btreeset! {16}, btreeset! {17}, btreeset! {18}, btreeset! {19}, ], ); exhaustive_b_tree_sets_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ btreeset! {0}, btreeset! {1}, btreeset! {2}, btreeset! {3}, btreeset! {4}, btreeset! {5}, btreeset! {6}, btreeset! {7}, btreeset! {8}, btreeset! {9}, btreeset! {10}, btreeset! {11}, btreeset! {12}, btreeset! {13}, btreeset! {14}, btreeset! {15}, btreeset! {16}, btreeset! {17}, btreeset! {18}, btreeset! {19}, ], ); exhaustive_b_tree_sets_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ btreeset! {0, 1}, btreeset! {0, 2}, btreeset! {1, 2}, btreeset! {0, 3}, btreeset! {1, 3}, btreeset! {2, 3}, btreeset! {0, 4}, btreeset! {1, 4}, btreeset! {2, 4}, btreeset! {3, 4}, btreeset! {0, 5}, btreeset! {1, 5}, btreeset! {2, 5}, btreeset! {3, 5}, btreeset! {4, 5}, btreeset! {0, 6}, btreeset! {1, 6}, btreeset! {2, 6}, btreeset! {3, 6}, btreeset! {4, 6}, ], ); exhaustive_b_tree_sets_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ btreeset! {0, 1, 2}, btreeset! {0, 1, 3}, btreeset! {0, 2, 3}, btreeset! {1, 2, 3}, btreeset! {0, 1, 4}, btreeset! {0, 2, 4}, btreeset! {1, 2, 4}, btreeset! {0, 3, 4}, btreeset! {1, 3, 4}, btreeset! {2, 3, 4}, btreeset! {0, 1, 5}, btreeset! {0, 2, 5}, btreeset! {1, 2, 5}, btreeset! {0, 3, 5}, btreeset! {1, 3, 5}, btreeset! {2, 3, 5}, btreeset! {0, 4, 5}, btreeset! {1, 4, 5}, btreeset! {2, 4, 5}, btreeset! {3, 4, 5}, ], ); exhaustive_b_tree_sets_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'd'}, btreeset! {'b', 'd'}, btreeset! {'c', 'd'}, btreeset! {'a', 'e'}, btreeset! {'b', 'e'}, btreeset! {'c', 'e'}, btreeset! {'d', 'e'}, btreeset! {'a', 'f'}, btreeset! {'b', 'f'}, btreeset! {'c', 'f'}, btreeset! {'d', 'f'}, btreeset! {'e', 'f'}, btreeset! {'a', 'g'}, btreeset! {'b', 'g'}, btreeset! {'c', 'g'}, btreeset! {'d', 'g'}, btreeset! {'e', 'g'}, ], ); exhaustive_b_tree_sets_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[btreeset! {false}, btreeset! {true}], ); exhaustive_b_tree_sets_fixed_length_small_helper( 2, exhaustive_bools(), 1, &[btreeset! {false, true}], ); exhaustive_b_tree_sets_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); exhaustive_b_tree_sets_fixed_length_small_helper( 4, 1..=6, 15, &[ btreeset! {1, 2, 3, 4}, btreeset! {1, 2, 3, 5}, btreeset! {1, 2, 4, 5}, btreeset! {1, 3, 4, 5}, btreeset! {2, 3, 4, 5}, btreeset! {1, 2, 3, 6}, btreeset! {1, 2, 4, 6}, btreeset! {1, 3, 4, 6}, btreeset! {2, 3, 4, 6}, btreeset! {1, 2, 5, 6}, btreeset! {1, 3, 5, 6}, btreeset! {2, 3, 5, 6}, btreeset! {1, 4, 5, 6}, btreeset! {2, 4, 5, 6}, btreeset! {3, 4, 5, 6}, ], ); exhaustive_b_tree_sets_fixed_length_helper( 2, exhaustive_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ btreeset! {vec![0, 1], vec![0, 2]}, btreeset! {vec![0, 1], vec![1, 2]}, btreeset! {vec![0, 2], vec![1, 2]}, btreeset! {vec![0, 1], vec![0, 3]}, btreeset! {vec![0, 2], vec![0, 3]}, btreeset! {vec![1, 2], vec![0, 3]}, btreeset! {vec![0, 1], vec![1, 3]}, btreeset! {vec![0, 2], vec![1, 3]}, btreeset! {vec![1, 2], vec![1, 3]}, btreeset! {vec![0, 3], vec![1, 3]}, btreeset! {vec![0, 1], vec![2, 3]}, btreeset! {vec![0, 2], vec![2, 3]}, btreeset! {vec![1, 2], vec![2, 3]}, btreeset! {vec![0, 3], vec![2, 3]}, btreeset! {vec![1, 3], vec![2, 3]}, btreeset! {vec![0, 1], vec![0, 4]}, btreeset! {vec![0, 2], vec![0, 4]}, btreeset! {vec![1, 2], vec![0, 4]}, btreeset! {vec![0, 3], vec![0, 4]}, btreeset! {vec![1, 3], vec![0, 4]}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_b_tree_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn exhaustive_b_tree_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_small_helper_helper( exhaustive_b_tree_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_b_tree_sets_length_inclusive_range() { exhaustive_b_tree_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[btreeset! {}]); exhaustive_b_tree_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); exhaustive_b_tree_sets_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); exhaustive_b_tree_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_b_tree_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); exhaustive_b_tree_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[btreeset! {false, true}], ); exhaustive_b_tree_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_b_tree_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn exhaustive_b_tree_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_small_helper_helper( exhaustive_b_tree_sets_length_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_b_tree_sets_length_range() { exhaustive_b_tree_sets_length_range_small_helper(0, 5, nevers(), 1, &[btreeset! {}]); exhaustive_b_tree_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); exhaustive_b_tree_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); exhaustive_b_tree_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_b_tree_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); exhaustive_b_tree_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); exhaustive_b_tree_sets_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[btreeset! {false, true}], ); exhaustive_b_tree_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_b_tree_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_b_tree_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn exhaustive_b_tree_sets_min_length_helper( min_length: u64, xs: I, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_helper_helper(exhaustive_b_tree_sets_min_length(min_length, xs), out); } fn exhaustive_b_tree_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Ord, { exhaustive_b_tree_sets_small_helper_helper( exhaustive_b_tree_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_exhaustive_b_tree_sets_min_length() { exhaustive_b_tree_sets_min_length_small_helper(0, nevers(), 1, &[btreeset! {}]); exhaustive_b_tree_sets_min_length_small_helper(4, nevers(), 0, &[]); exhaustive_b_tree_sets_min_length_small_helper( 0, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); exhaustive_b_tree_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_b_tree_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); exhaustive_b_tree_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); exhaustive_b_tree_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'a', 'b'}, btreeset! {'c'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); exhaustive_b_tree_sets_min_length_small_helper( 2, 'a'..='c', 4, &[ btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); exhaustive_b_tree_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'a', 'b'}, btreeset! {'c'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, btreeset! {'d'}, btreeset! {'a', 'd'}, btreeset! {'b', 'd'}, btreeset! {'a', 'b', 'd'}, btreeset! {'c', 'd'}, btreeset! {'a', 'c', 'd'}, btreeset! {'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'e'}, btreeset! {'a', 'e'}, btreeset! {'b', 'e'}, btreeset! {'a', 'b', 'e'}, ], ); exhaustive_b_tree_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'b', 'd'}, btreeset! {'a', 'c', 'd'}, btreeset! {'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'a', 'b', 'e'}, btreeset! {'a', 'c', 'e'}, btreeset! {'b', 'c', 'e'}, btreeset! {'a', 'b', 'c', 'e'}, btreeset! {'a', 'd', 'e'}, btreeset! {'b', 'd', 'e'}, btreeset! {'a', 'b', 'd', 'e'}, btreeset! {'c', 'd', 'e'}, btreeset! {'a', 'c', 'd', 'e'}, btreeset! {'b', 'c', 'd', 'e'}, btreeset! {'a', 'b', 'c', 'd', 'e'}, btreeset! {'a', 'b', 'f'}, btreeset! {'a', 'c', 'f'}, btreeset! {'b', 'c', 'f'}, btreeset! {'a', 'b', 'c', 'f'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_hash_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_hash_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn exhaustive_hash_sets_helper(xs: I, out: &[HashSet]) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(exhaustive_hash_sets(xs), out); } fn exhaustive_hash_sets_small_helper( xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper(exhaustive_hash_sets(xs), out_len, out); } #[test] fn test_exhaustive_hash_sets() { exhaustive_hash_sets_small_helper(nevers(), 1, &[hashset! {}]); exhaustive_hash_sets_small_helper(exhaustive_units(), 2, &[hashset! {}, hashset! {()}]); exhaustive_hash_sets_small_helper( exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {true}, hashset! {false, true}], ); exhaustive_hash_sets_small_helper( 1..=6, 64, &[ hashset! {}, hashset! {1}, hashset! {2}, hashset! {1, 2}, hashset! {3}, hashset! {1, 3}, hashset! {2, 3}, hashset! {1, 2, 3}, hashset! {4}, hashset! {1, 4}, hashset! {2, 4}, hashset! {1, 2, 4}, hashset! {3, 4}, hashset! {1, 3, 4}, hashset! {2, 3, 4}, hashset! {1, 2, 3, 4}, hashset! {5}, hashset! {1, 5}, hashset! {2, 5}, hashset! {1, 2, 5}, ], ); exhaustive_hash_sets_small_helper( 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'a', 'b'}, hashset! {'c'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, ], ); exhaustive_hash_sets_helper( exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'a', 'b'}, hashset! {'c'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, hashset! {'d'}, hashset! {'a', 'd'}, hashset! {'b', 'd'}, hashset! {'a', 'b', 'd'}, hashset! {'c', 'd'}, hashset! {'a', 'c', 'd'}, hashset! {'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'e'}, hashset! {'a', 'e'}, hashset! {'b', 'e'}, hashset! {'a', 'b', 'e'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_hash_sets_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::sets::exhaustive::exhaustive_hash_sets_fixed_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_fixed_length; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn exhaustive_hash_sets_fixed_length_helper( len: u64, xs: I, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(exhaustive_hash_sets_fixed_length(len, xs), out); } fn exhaustive_hash_sets_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( exhaustive_hash_sets_fixed_length(len, xs), out_len, out, ); } #[test] fn test_exhaustive_hash_sets_fixed_length() { // This demonstrates that 0 ^ 0 == 1: exhaustive_hash_sets_fixed_length_small_helper(0, nevers(), 1, &[hashset! {}]); exhaustive_hash_sets_fixed_length_small_helper(1, nevers(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper(2, nevers(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper(5, nevers(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper(1, exhaustive_units(), 1, &[hashset! {()}]); exhaustive_hash_sets_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper( 0, exhaustive_unsigneds::(), 1, &[hashset! {}], ); exhaustive_hash_sets_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ hashset! {0}, hashset! {1}, hashset! {2}, hashset! {3}, hashset! {4}, hashset! {5}, hashset! {6}, hashset! {7}, hashset! {8}, hashset! {9}, hashset! {10}, hashset! {11}, hashset! {12}, hashset! {13}, hashset! {14}, hashset! {15}, hashset! {16}, hashset! {17}, hashset! {18}, hashset! {19}, ], ); exhaustive_hash_sets_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ hashset! {0}, hashset! {1}, hashset! {2}, hashset! {3}, hashset! {4}, hashset! {5}, hashset! {6}, hashset! {7}, hashset! {8}, hashset! {9}, hashset! {10}, hashset! {11}, hashset! {12}, hashset! {13}, hashset! {14}, hashset! {15}, hashset! {16}, hashset! {17}, hashset! {18}, hashset! {19}, ], ); exhaustive_hash_sets_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ hashset! {0, 1}, hashset! {0, 2}, hashset! {1, 2}, hashset! {0, 3}, hashset! {1, 3}, hashset! {2, 3}, hashset! {0, 4}, hashset! {1, 4}, hashset! {2, 4}, hashset! {3, 4}, hashset! {0, 5}, hashset! {1, 5}, hashset! {2, 5}, hashset! {3, 5}, hashset! {4, 5}, hashset! {0, 6}, hashset! {1, 6}, hashset! {2, 6}, hashset! {3, 6}, hashset! {4, 6}, ], ); exhaustive_hash_sets_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ hashset! {0, 1, 2}, hashset! {0, 1, 3}, hashset! {0, 2, 3}, hashset! {1, 2, 3}, hashset! {0, 1, 4}, hashset! {0, 2, 4}, hashset! {1, 2, 4}, hashset! {0, 3, 4}, hashset! {1, 3, 4}, hashset! {2, 3, 4}, hashset! {0, 1, 5}, hashset! {0, 2, 5}, hashset! {1, 2, 5}, hashset! {0, 3, 5}, hashset! {1, 3, 5}, hashset! {2, 3, 5}, hashset! {0, 4, 5}, hashset! {1, 4, 5}, hashset! {2, 4, 5}, hashset! {3, 4, 5}, ], ); exhaustive_hash_sets_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'd'}, hashset! {'b', 'd'}, hashset! {'c', 'd'}, hashset! {'a', 'e'}, hashset! {'b', 'e'}, hashset! {'c', 'e'}, hashset! {'d', 'e'}, hashset! {'a', 'f'}, hashset! {'b', 'f'}, hashset! {'c', 'f'}, hashset! {'d', 'f'}, hashset! {'e', 'f'}, hashset! {'a', 'g'}, hashset! {'b', 'g'}, hashset! {'c', 'g'}, hashset! {'d', 'g'}, hashset! {'e', 'g'}, ], ); exhaustive_hash_sets_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[hashset! {false}, hashset! {true}], ); exhaustive_hash_sets_fixed_length_small_helper( 2, exhaustive_bools(), 1, &[hashset! {false, true}], ); exhaustive_hash_sets_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); exhaustive_hash_sets_fixed_length_small_helper( 4, 1..=6, 15, &[ hashset! {1, 2, 3, 4}, hashset! {1, 2, 3, 5}, hashset! {1, 2, 4, 5}, hashset! {1, 3, 4, 5}, hashset! {2, 3, 4, 5}, hashset! {1, 2, 3, 6}, hashset! {1, 2, 4, 6}, hashset! {1, 3, 4, 6}, hashset! {2, 3, 4, 6}, hashset! {1, 2, 5, 6}, hashset! {1, 3, 5, 6}, hashset! {2, 3, 5, 6}, hashset! {1, 4, 5, 6}, hashset! {2, 4, 5, 6}, hashset! {3, 4, 5, 6}, ], ); exhaustive_hash_sets_fixed_length_helper( 2, exhaustive_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ hashset! {vec![0, 1], vec![0, 2]}, hashset! {vec![0, 1], vec![1, 2]}, hashset! {vec![0, 2], vec![1, 2]}, hashset! {vec![0, 1], vec![0, 3]}, hashset! {vec![0, 2], vec![0, 3]}, hashset! {vec![1, 2], vec![0, 3]}, hashset! {vec![0, 1], vec![1, 3]}, hashset! {vec![0, 2], vec![1, 3]}, hashset! {vec![1, 2], vec![1, 3]}, hashset! {vec![0, 3], vec![1, 3]}, hashset! {vec![0, 1], vec![2, 3]}, hashset! {vec![0, 2], vec![2, 3]}, hashset! {vec![1, 2], vec![2, 3]}, hashset! {vec![0, 3], vec![2, 3]}, hashset! {vec![1, 3], vec![2, 3]}, hashset! {vec![0, 1], vec![0, 4]}, hashset! {vec![0, 2], vec![0, 4]}, hashset! {vec![1, 2], vec![0, 4]}, hashset! {vec![0, 3], vec![0, 4]}, hashset! {vec![1, 3], vec![0, 4]}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_hash_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_hash_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn exhaustive_hash_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( exhaustive_hash_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_hash_sets_length_inclusive_range() { exhaustive_hash_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[hashset! {}]); exhaustive_hash_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); exhaustive_hash_sets_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); exhaustive_hash_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_hash_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); exhaustive_hash_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[hashset! {false, true}], ); exhaustive_hash_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_hash_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_hash_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn exhaustive_hash_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( exhaustive_hash_sets_length_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_hash_sets_length_range() { exhaustive_hash_sets_length_range_small_helper(0, 5, nevers(), 1, &[hashset! {}]); exhaustive_hash_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); exhaustive_hash_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); exhaustive_hash_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_hash_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); exhaustive_hash_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); exhaustive_hash_sets_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[hashset! {false, true}], ); exhaustive_hash_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/exhaustive_hash_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::exhaustive_hash_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn exhaustive_hash_sets_min_length_helper( min_length: u64, xs: I, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(exhaustive_hash_sets_min_length(min_length, xs), out); } fn exhaustive_hash_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( exhaustive_hash_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_exhaustive_hash_sets_min_length() { exhaustive_hash_sets_min_length_small_helper(0, nevers(), 1, &[hashset! {}]); exhaustive_hash_sets_min_length_small_helper(4, nevers(), 0, &[]); exhaustive_hash_sets_min_length_small_helper( 0, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); exhaustive_hash_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_hash_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {true}, hashset! {false, true}], ); exhaustive_hash_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[hashset! {false}, hashset! {true}, hashset! {false, true}], ); exhaustive_hash_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'a', 'b'}, hashset! {'c'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, ], ); exhaustive_hash_sets_min_length_small_helper( 2, 'a'..='c', 4, &[hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}], ); exhaustive_hash_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'a', 'b'}, hashset! {'c'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, hashset! {'d'}, hashset! {'a', 'd'}, hashset! {'b', 'd'}, hashset! {'a', 'b', 'd'}, hashset! {'c', 'd'}, hashset! {'a', 'c', 'd'}, hashset! {'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'e'}, hashset! {'a', 'e'}, hashset! {'b', 'e'}, hashset! {'a', 'b', 'e'}, ], ); exhaustive_hash_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ hashset! {'a', 'b', 'c'}, hashset! {'a', 'b', 'd'}, hashset! {'a', 'c', 'd'}, hashset! {'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'a', 'b', 'e'}, hashset! {'a', 'c', 'e'}, hashset! {'b', 'c', 'e'}, hashset! {'a', 'b', 'c', 'e'}, hashset! {'a', 'd', 'e'}, hashset! {'b', 'd', 'e'}, hashset! {'a', 'b', 'd', 'e'}, hashset! {'c', 'd', 'e'}, hashset! {'a', 'c', 'd', 'e'}, hashset! {'b', 'c', 'd', 'e'}, hashset! {'a', 'b', 'c', 'd', 'e'}, hashset! {'a', 'b', 'f'}, hashset! {'a', 'c', 'f'}, hashset! {'b', 'c', 'f'}, hashset! {'a', 'b', 'c', 'f'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_b_tree_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_b_tree_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn lex_b_tree_sets_helper(xs: I, out: &[BTreeSet]) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_helper_helper(lex_b_tree_sets(xs), out); } fn lex_b_tree_sets_small_helper( xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper(lex_b_tree_sets(xs), out_len, out); } #[test] fn test_lex_b_tree_sets() { lex_b_tree_sets_small_helper(nevers(), 1, &[btreeset! {}]); lex_b_tree_sets_small_helper(exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}]); lex_b_tree_sets_small_helper( exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {false, true}, btreeset! {true}], ); lex_b_tree_sets_small_helper( 1..=6, 64, &[ btreeset! {}, btreeset! {1}, btreeset! {1, 2}, btreeset! {1, 2, 3}, btreeset! {1, 2, 3, 4}, btreeset! {1, 2, 3, 4, 5}, btreeset! {1, 2, 3, 4, 5, 6}, btreeset! {1, 2, 3, 4, 6}, btreeset! {1, 2, 3, 5}, btreeset! {1, 2, 3, 5, 6}, btreeset! {1, 2, 3, 6}, btreeset! {1, 2, 4}, btreeset! {1, 2, 4, 5}, btreeset! {1, 2, 4, 5, 6}, btreeset! {1, 2, 4, 6}, btreeset! {1, 2, 5}, btreeset! {1, 2, 5, 6}, btreeset! {1, 2, 6}, btreeset! {1, 3}, btreeset! {1, 3, 4}, ], ); lex_b_tree_sets_small_helper( 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'a', 'b'}, btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'c'}, btreeset! {'b'}, btreeset! {'b', 'c'}, btreeset! {'c'}, ], ); lex_b_tree_sets_helper( exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'a', 'b'}, btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd', 'e'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_b_tree_sets_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::sets::exhaustive::lex_b_tree_sets_fixed_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_fixed_length; use std::collections::BTreeSet; use std::fmt::Debug; fn lex_b_tree_sets_fixed_length_helper(len: u64, xs: I, out: &[BTreeSet]) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_helper_helper(lex_b_tree_sets_fixed_length(len, xs), out); } fn lex_b_tree_sets_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper(lex_b_tree_sets_fixed_length(len, xs), out_len, out); } #[test] fn test_lex_b_tree_sets_fixed_length() { lex_b_tree_sets_fixed_length_small_helper(0, nevers(), 1, &[btreeset! {}]); lex_b_tree_sets_fixed_length_small_helper(1, nevers(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper(2, nevers(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper(5, nevers(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper(1, exhaustive_units(), 1, &[btreeset! {()}]); lex_b_tree_sets_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper(0, exhaustive_unsigneds::(), 1, &[btreeset! {}]); lex_b_tree_sets_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ btreeset! {0}, btreeset! {1}, btreeset! {2}, btreeset! {3}, btreeset! {4}, btreeset! {5}, btreeset! {6}, btreeset! {7}, btreeset! {8}, btreeset! {9}, btreeset! {10}, btreeset! {11}, btreeset! {12}, btreeset! {13}, btreeset! {14}, btreeset! {15}, btreeset! {16}, btreeset! {17}, btreeset! {18}, btreeset! {19}, ], ); lex_b_tree_sets_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ btreeset! {0}, btreeset! {1}, btreeset! {2}, btreeset! {3}, btreeset! {4}, btreeset! {5}, btreeset! {6}, btreeset! {7}, btreeset! {8}, btreeset! {9}, btreeset! {10}, btreeset! {11}, btreeset! {12}, btreeset! {13}, btreeset! {14}, btreeset! {15}, btreeset! {16}, btreeset! {17}, btreeset! {18}, btreeset! {19}, ], ); lex_b_tree_sets_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ btreeset! {0, 1}, btreeset! {0, 2}, btreeset! {0, 3}, btreeset! {0, 4}, btreeset! {0, 5}, btreeset! {0, 6}, btreeset! {0, 7}, btreeset! {0, 8}, btreeset! {0, 9}, btreeset! {0, 10}, btreeset! {0, 11}, btreeset! {0, 12}, btreeset! {0, 13}, btreeset! {0, 14}, btreeset! {0, 15}, btreeset! {0, 16}, btreeset! {0, 17}, btreeset! {0, 18}, btreeset! {0, 19}, btreeset! {0, 20}, ], ); lex_b_tree_sets_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ btreeset! {0, 1, 2}, btreeset! {0, 1, 3}, btreeset! {0, 1, 4}, btreeset! {0, 1, 5}, btreeset! {0, 1, 6}, btreeset! {0, 1, 7}, btreeset! {0, 1, 8}, btreeset! {0, 1, 9}, btreeset! {0, 1, 10}, btreeset! {0, 1, 11}, btreeset! {0, 1, 12}, btreeset! {0, 1, 13}, btreeset! {0, 1, 14}, btreeset! {0, 1, 15}, btreeset! {0, 1, 16}, btreeset! {0, 1, 17}, btreeset! {0, 1, 18}, btreeset! {0, 1, 19}, btreeset! {0, 1, 20}, btreeset! {0, 1, 21}, ], ); lex_b_tree_sets_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'a', 'd'}, btreeset! {'a', 'e'}, btreeset! {'a', 'f'}, btreeset! {'a', 'g'}, btreeset! {'a', 'h'}, btreeset! {'a', 'i'}, btreeset! {'a', 'j'}, btreeset! {'a', 'k'}, btreeset! {'a', 'l'}, btreeset! {'a', 'm'}, btreeset! {'a', 'n'}, btreeset! {'a', 'o'}, btreeset! {'a', 'p'}, btreeset! {'a', 'q'}, btreeset! {'a', 'r'}, btreeset! {'a', 's'}, btreeset! {'a', 't'}, btreeset! {'a', 'u'}, ], ); lex_b_tree_sets_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[btreeset! {false}, btreeset! {true}], ); lex_b_tree_sets_fixed_length_small_helper(2, exhaustive_bools(), 1, &[btreeset! {false, true}]); lex_b_tree_sets_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); lex_b_tree_sets_fixed_length_small_helper( 4, 1..=6, 15, &[ btreeset! {1, 2, 3, 4}, btreeset! {1, 2, 3, 5}, btreeset! {1, 2, 3, 6}, btreeset! {1, 2, 4, 5}, btreeset! {1, 2, 4, 6}, btreeset! {1, 2, 5, 6}, btreeset! {1, 3, 4, 5}, btreeset! {1, 3, 4, 6}, btreeset! {1, 3, 5, 6}, btreeset! {1, 4, 5, 6}, btreeset! {2, 3, 4, 5}, btreeset! {2, 3, 4, 6}, btreeset! {2, 3, 5, 6}, btreeset! {2, 4, 5, 6}, btreeset! {3, 4, 5, 6}, ], ); lex_b_tree_sets_fixed_length_helper( 2, lex_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ btreeset! {vec![0, 1], vec![0, 2]}, btreeset! {vec![0, 1], vec![0, 3]}, btreeset! {vec![0, 1], vec![0, 4]}, btreeset! {vec![0, 1], vec![0, 5]}, btreeset! {vec![0, 1], vec![0, 6]}, btreeset! {vec![0, 1], vec![0, 7]}, btreeset! {vec![0, 1], vec![0, 8]}, btreeset! {vec![0, 1], vec![0, 9]}, btreeset! {vec![0, 1], vec![0, 10]}, btreeset! {vec![0, 1], vec![0, 11]}, btreeset! {vec![0, 1], vec![0, 12]}, btreeset! {vec![0, 1], vec![0, 13]}, btreeset! {vec![0, 1], vec![0, 14]}, btreeset! {vec![0, 1], vec![0, 15]}, btreeset! {vec![0, 1], vec![0, 16]}, btreeset! {vec![0, 1], vec![0, 17]}, btreeset! {vec![0, 1], vec![0, 18]}, btreeset! {vec![0, 1], vec![0, 19]}, btreeset! {vec![0, 1], vec![0, 20]}, btreeset! {vec![0, 1], vec![0, 21]}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_b_tree_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_b_tree_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn lex_b_tree_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( lex_b_tree_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_b_tree_sets_length_inclusive_range() { lex_b_tree_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[btreeset! {}]); lex_b_tree_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); lex_b_tree_sets_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); lex_b_tree_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_b_tree_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); lex_b_tree_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[btreeset! {false, true}], ); lex_b_tree_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_b_tree_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_b_tree_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn lex_b_tree_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( lex_b_tree_sets_length_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_b_tree_sets_length_range() { lex_b_tree_sets_length_range_small_helper(0, 5, nevers(), 1, &[btreeset! {}]); lex_b_tree_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); lex_b_tree_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); lex_b_tree_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_b_tree_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); lex_b_tree_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); lex_b_tree_sets_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[btreeset! {false, true}], ); lex_b_tree_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_b_tree_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_b_tree_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn lex_b_tree_sets_min_length_helper( min_length: u64, xs: I, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_helper_helper(lex_b_tree_sets_min_length(min_length, xs), out); } fn lex_b_tree_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( lex_b_tree_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_lex_b_tree_sets_min_length() { lex_b_tree_sets_min_length_small_helper(0, nevers(), 1, &[btreeset! {}]); lex_b_tree_sets_min_length_small_helper(4, nevers(), 0, &[]); lex_b_tree_sets_min_length_small_helper( 0, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); lex_b_tree_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); lex_b_tree_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {false, true}, btreeset! {true}], ); lex_b_tree_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[btreeset! {false}, btreeset! {false, true}, btreeset! {true}], ); lex_b_tree_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'a', 'b'}, btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'c'}, btreeset! {'b'}, btreeset! {'b', 'c'}, btreeset! {'c'}, ], ); lex_b_tree_sets_min_length_small_helper( 2, 'a'..='c', 4, &[ btreeset! {'a', 'b'}, btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, ], ); lex_b_tree_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'a', 'b'}, btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd', 'e'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, ], ); lex_b_tree_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'b', 'c', 'd'}, btreeset! {'a', 'b', 'c', 'd', 'e'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, btreeset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', }, btreeset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', }, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_hash_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_hash_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn lex_hash_sets_helper(xs: I, out: &[HashSet]) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(lex_hash_sets(xs), out); } fn lex_hash_sets_small_helper(xs: I, out_len: usize, out: &[HashSet]) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper(lex_hash_sets(xs), out_len, out); } #[test] fn test_lex_hash_sets() { lex_hash_sets_small_helper(nevers(), 1, &[hashset! {}]); lex_hash_sets_small_helper(exhaustive_units(), 2, &[hashset! {}, hashset! {()}]); lex_hash_sets_small_helper( exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {false, true}, hashset! {true}], ); lex_hash_sets_small_helper( 1..=6, 64, &[ hashset! {}, hashset! {1}, hashset! {1, 2}, hashset! {1, 2, 3}, hashset! {1, 2, 3, 4}, hashset! {1, 2, 3, 4, 5}, hashset! {1, 2, 3, 4, 5, 6}, hashset! {1, 2, 3, 4, 6}, hashset! {1, 2, 3, 5}, hashset! {1, 2, 3, 5, 6}, hashset! {1, 2, 3, 6}, hashset! {1, 2, 4}, hashset! {1, 2, 4, 5}, hashset! {1, 2, 4, 5, 6}, hashset! {1, 2, 4, 6}, hashset! {1, 2, 5}, hashset! {1, 2, 5, 6}, hashset! {1, 2, 6}, hashset! {1, 3}, hashset! {1, 3, 4}, ], ); lex_hash_sets_small_helper( 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'a', 'b'}, hashset! {'a', 'b', 'c'}, hashset! {'a', 'c'}, hashset! {'b'}, hashset! {'b', 'c'}, hashset! {'c'}, ], ); lex_hash_sets_helper( exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'a', 'b'}, hashset! {'a', 'b', 'c'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd', 'e'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_hash_sets_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::sets::exhaustive::lex_hash_sets_fixed_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_fixed_length; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn lex_hash_sets_fixed_length_helper(len: u64, xs: I, out: &[HashSet]) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(lex_hash_sets_fixed_length(len, xs), out); } fn lex_hash_sets_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper(lex_hash_sets_fixed_length(len, xs), out_len, out); } #[test] fn test_lex_hash_sets_fixed_length() { lex_hash_sets_fixed_length_small_helper(0, nevers(), 1, &[hashset! {}]); lex_hash_sets_fixed_length_small_helper(1, nevers(), 0, &[]); lex_hash_sets_fixed_length_small_helper(2, nevers(), 0, &[]); lex_hash_sets_fixed_length_small_helper(5, nevers(), 0, &[]); lex_hash_sets_fixed_length_small_helper(1, exhaustive_units(), 1, &[hashset! {()}]); lex_hash_sets_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); lex_hash_sets_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); lex_hash_sets_fixed_length_small_helper(0, exhaustive_unsigneds::(), 1, &[hashset! {}]); lex_hash_sets_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ hashset! {0}, hashset! {1}, hashset! {2}, hashset! {3}, hashset! {4}, hashset! {5}, hashset! {6}, hashset! {7}, hashset! {8}, hashset! {9}, hashset! {10}, hashset! {11}, hashset! {12}, hashset! {13}, hashset! {14}, hashset! {15}, hashset! {16}, hashset! {17}, hashset! {18}, hashset! {19}, ], ); lex_hash_sets_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ hashset! {0}, hashset! {1}, hashset! {2}, hashset! {3}, hashset! {4}, hashset! {5}, hashset! {6}, hashset! {7}, hashset! {8}, hashset! {9}, hashset! {10}, hashset! {11}, hashset! {12}, hashset! {13}, hashset! {14}, hashset! {15}, hashset! {16}, hashset! {17}, hashset! {18}, hashset! {19}, ], ); lex_hash_sets_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ hashset! {0, 1}, hashset! {0, 2}, hashset! {0, 3}, hashset! {0, 4}, hashset! {0, 5}, hashset! {0, 6}, hashset! {0, 7}, hashset! {0, 8}, hashset! {0, 9}, hashset! {0, 10}, hashset! {0, 11}, hashset! {0, 12}, hashset! {0, 13}, hashset! {0, 14}, hashset! {0, 15}, hashset! {0, 16}, hashset! {0, 17}, hashset! {0, 18}, hashset! {0, 19}, hashset! {0, 20}, ], ); lex_hash_sets_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ hashset! {0, 1, 2}, hashset! {0, 1, 3}, hashset! {0, 1, 4}, hashset! {0, 1, 5}, hashset! {0, 1, 6}, hashset! {0, 1, 7}, hashset! {0, 1, 8}, hashset! {0, 1, 9}, hashset! {0, 1, 10}, hashset! {0, 1, 11}, hashset! {0, 1, 12}, hashset! {0, 1, 13}, hashset! {0, 1, 14}, hashset! {0, 1, 15}, hashset! {0, 1, 16}, hashset! {0, 1, 17}, hashset! {0, 1, 18}, hashset! {0, 1, 19}, hashset! {0, 1, 20}, hashset! {0, 1, 21}, ], ); lex_hash_sets_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'a', 'd'}, hashset! {'a', 'e'}, hashset! {'a', 'f'}, hashset! {'a', 'g'}, hashset! {'a', 'h'}, hashset! {'a', 'i'}, hashset! {'a', 'j'}, hashset! {'a', 'k'}, hashset! {'a', 'l'}, hashset! {'a', 'm'}, hashset! {'a', 'n'}, hashset! {'a', 'o'}, hashset! {'a', 'p'}, hashset! {'a', 'q'}, hashset! {'a', 'r'}, hashset! {'a', 's'}, hashset! {'a', 't'}, hashset! {'a', 'u'}, ], ); lex_hash_sets_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[hashset! {false}, hashset! {true}], ); lex_hash_sets_fixed_length_small_helper(2, exhaustive_bools(), 1, &[hashset! {false, true}]); lex_hash_sets_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); lex_hash_sets_fixed_length_small_helper( 4, 1..=6, 15, &[ hashset! {1, 2, 3, 4}, hashset! {1, 2, 3, 5}, hashset! {1, 2, 3, 6}, hashset! {1, 2, 4, 5}, hashset! {1, 2, 4, 6}, hashset! {1, 2, 5, 6}, hashset! {1, 3, 4, 5}, hashset! {1, 3, 4, 6}, hashset! {1, 3, 5, 6}, hashset! {1, 4, 5, 6}, hashset! {2, 3, 4, 5}, hashset! {2, 3, 4, 6}, hashset! {2, 3, 5, 6}, hashset! {2, 4, 5, 6}, hashset! {3, 4, 5, 6}, ], ); lex_hash_sets_fixed_length_helper( 2, lex_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ hashset! {vec![0, 1], vec![0, 2]}, hashset! {vec![0, 1], vec![0, 3]}, hashset! {vec![0, 1], vec![0, 4]}, hashset! {vec![0, 1], vec![0, 5]}, hashset! {vec![0, 1], vec![0, 6]}, hashset! {vec![0, 1], vec![0, 7]}, hashset! {vec![0, 1], vec![0, 8]}, hashset! {vec![0, 1], vec![0, 9]}, hashset! {vec![0, 1], vec![0, 10]}, hashset! {vec![0, 1], vec![0, 11]}, hashset! {vec![0, 1], vec![0, 12]}, hashset! {vec![0, 1], vec![0, 13]}, hashset! {vec![0, 1], vec![0, 14]}, hashset! {vec![0, 1], vec![0, 15]}, hashset! {vec![0, 1], vec![0, 16]}, hashset! {vec![0, 1], vec![0, 17]}, hashset! {vec![0, 1], vec![0, 18]}, hashset! {vec![0, 1], vec![0, 19]}, hashset! {vec![0, 1], vec![0, 20]}, hashset! {vec![0, 1], vec![0, 21]}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_hash_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_hash_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn lex_hash_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( lex_hash_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_hash_sets_length_inclusive_range() { lex_hash_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[hashset! {}]); lex_hash_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); lex_hash_sets_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); lex_hash_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_hash_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); lex_hash_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[hashset! {false, true}], ); lex_hash_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_hash_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_hash_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn lex_hash_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper(lex_hash_sets_length_range(a, b, xs), out_len, out); } #[test] fn test_lex_hash_sets_length_range() { lex_hash_sets_length_range_small_helper(0, 5, nevers(), 1, &[hashset! {}]); lex_hash_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); lex_hash_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); lex_hash_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_hash_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); lex_hash_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); lex_hash_sets_length_range_small_helper(2, 4, exhaustive_bools(), 1, &[hashset! {false, true}]); lex_hash_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/lex_hash_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::lex_hash_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn lex_hash_sets_min_length_helper( min_length: u64, xs: I, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(lex_hash_sets_min_length(min_length, xs), out); } fn lex_hash_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( lex_hash_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_lex_hash_sets_min_length() { lex_hash_sets_min_length_small_helper(0, nevers(), 1, &[hashset! {}]); lex_hash_sets_min_length_small_helper(4, nevers(), 0, &[]); lex_hash_sets_min_length_small_helper(0, exhaustive_units(), 2, &[hashset! {}, hashset! {()}]); lex_hash_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); lex_hash_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {false, true}, hashset! {true}], ); lex_hash_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[hashset! {false}, hashset! {false, true}, hashset! {true}], ); lex_hash_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'a', 'b'}, hashset! {'a', 'b', 'c'}, hashset! {'a', 'c'}, hashset! {'b'}, hashset! {'b', 'c'}, hashset! {'c'}, ], ); lex_hash_sets_min_length_small_helper( 2, 'a'..='c', 4, &[hashset! {'a', 'b'}, hashset! {'a', 'b', 'c'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}], ); lex_hash_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'a', 'b'}, hashset! {'a', 'b', 'c'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd', 'e'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, ], ); lex_hash_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ hashset! {'a', 'b', 'c'}, hashset! {'a', 'b', 'c', 'd'}, hashset! {'a', 'b', 'c', 'd', 'e'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}, hashset! {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'}, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q' }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', }, hashset! { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', }, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_b_tree_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_b_tree_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn shortlex_b_tree_sets_helper(xs: I, out: &[BTreeSet]) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_helper_helper(shortlex_b_tree_sets(xs), out); } fn shortlex_b_tree_sets_small_helper( xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper(shortlex_b_tree_sets(xs), out_len, out); } #[test] fn test_shortlex_b_tree_sets() { shortlex_b_tree_sets_small_helper(nevers(), 1, &[btreeset! {}]); shortlex_b_tree_sets_small_helper(exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}]); shortlex_b_tree_sets_small_helper( exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); shortlex_b_tree_sets_small_helper( 1..=6, 64, &[ btreeset! {}, btreeset! {1}, btreeset! {2}, btreeset! {3}, btreeset! {4}, btreeset! {5}, btreeset! {6}, btreeset! {1, 2}, btreeset! {1, 3}, btreeset! {1, 4}, btreeset! {1, 5}, btreeset! {1, 6}, btreeset! {2, 3}, btreeset! {2, 4}, btreeset! {2, 5}, btreeset! {2, 6}, btreeset! {3, 4}, btreeset! {3, 5}, btreeset! {3, 6}, btreeset! {4, 5}, ], ); shortlex_b_tree_sets_small_helper( 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}, btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); shortlex_b_tree_sets_helper( exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}, btreeset! {'d'}, btreeset! {'e'}, btreeset! {'f'}, btreeset! {'g'}, btreeset! {'h'}, btreeset! {'i'}, btreeset! {'j'}, btreeset! {'k'}, btreeset! {'l'}, btreeset! {'m'}, btreeset! {'n'}, btreeset! {'o'}, btreeset! {'p'}, btreeset! {'q'}, btreeset! {'r'}, btreeset! {'s'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_b_tree_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_b_tree_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn shortlex_b_tree_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( shortlex_b_tree_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_b_tree_sets_length_inclusive_range() { shortlex_b_tree_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[btreeset! {}]); shortlex_b_tree_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); shortlex_b_tree_sets_length_inclusive_range_small_helper( 0, 5, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); shortlex_b_tree_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_b_tree_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); shortlex_b_tree_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[btreeset! {false, true}], ); shortlex_b_tree_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_b_tree_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_b_tree_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_b_tree_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn shortlex_b_tree_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( shortlex_b_tree_sets_length_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_b_tree_sets_length_range() { shortlex_b_tree_sets_length_range_small_helper(0, 5, nevers(), 1, &[btreeset! {}]); shortlex_b_tree_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); shortlex_b_tree_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); shortlex_b_tree_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_b_tree_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); shortlex_b_tree_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[btreeset! {}, btreeset! {false}, btreeset! {true}], ); shortlex_b_tree_sets_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[btreeset! {false, true}], ); shortlex_b_tree_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_b_tree_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_b_tree_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_b_tree_sets_helper_helper, exhaustive_b_tree_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::BTreeSet; use std::fmt::Debug; fn shortlex_b_tree_sets_min_length_helper( min_length: u64, xs: I, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_helper_helper(shortlex_b_tree_sets_min_length(min_length, xs), out); } fn shortlex_b_tree_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[BTreeSet], ) where I::Item: Clone + Debug + Eq + Ord, { exhaustive_b_tree_sets_small_helper_helper( shortlex_b_tree_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_shortlex_b_tree_sets_min_length() { shortlex_b_tree_sets_min_length_small_helper(0, nevers(), 1, &[btreeset! {}]); shortlex_b_tree_sets_min_length_small_helper(4, nevers(), 0, &[]); shortlex_b_tree_sets_min_length_small_helper( 0, exhaustive_units(), 2, &[btreeset! {}, btreeset! {()}], ); shortlex_b_tree_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); shortlex_b_tree_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[btreeset! {}, btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); shortlex_b_tree_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[btreeset! {false}, btreeset! {true}, btreeset! {false, true}], ); shortlex_b_tree_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}, btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); shortlex_b_tree_sets_min_length_small_helper( 2, 'a'..='c', 4, &[ btreeset! {'a', 'b'}, btreeset! {'a', 'c'}, btreeset! {'b', 'c'}, btreeset! {'a', 'b', 'c'}, ], ); shortlex_b_tree_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ btreeset! {}, btreeset! {'a'}, btreeset! {'b'}, btreeset! {'c'}, btreeset! {'d'}, btreeset! {'e'}, btreeset! {'f'}, btreeset! {'g'}, btreeset! {'h'}, btreeset! {'i'}, btreeset! {'j'}, btreeset! {'k'}, btreeset! {'l'}, btreeset! {'m'}, btreeset! {'n'}, btreeset! {'o'}, btreeset! {'p'}, btreeset! {'q'}, btreeset! {'r'}, btreeset! {'s'}, ], ); shortlex_b_tree_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ btreeset! {'a', 'b', 'c'}, btreeset! {'a', 'b', 'd'}, btreeset! {'a', 'b', 'e'}, btreeset! {'a', 'b', 'f'}, btreeset! {'a', 'b', 'g'}, btreeset! {'a', 'b', 'h'}, btreeset! {'a', 'b', 'i'}, btreeset! {'a', 'b', 'j'}, btreeset! {'a', 'b', 'k'}, btreeset! {'a', 'b', 'l'}, btreeset! {'a', 'b', 'm'}, btreeset! {'a', 'b', 'n'}, btreeset! {'a', 'b', 'o'}, btreeset! {'a', 'b', 'p'}, btreeset! {'a', 'b', 'q'}, btreeset! {'a', 'b', 'r'}, btreeset! {'a', 'b', 's'}, btreeset! {'a', 'b', 't'}, btreeset! {'a', 'b', 'u'}, btreeset! {'a', 'b', 'v'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_hash_sets.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_hash_sets; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn shortlex_hash_sets_helper(xs: I, out: &[HashSet]) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(shortlex_hash_sets(xs).take(20), out); } fn shortlex_hash_sets_small_helper( xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper(shortlex_hash_sets(xs), out_len, out); } #[test] fn test_shortlex_hash_sets() { shortlex_hash_sets_small_helper(nevers(), 1, &[hashset! {}]); shortlex_hash_sets_small_helper(exhaustive_units(), 2, &[hashset! {}, hashset! {()}]); shortlex_hash_sets_small_helper( exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {true}, hashset! {false, true}], ); shortlex_hash_sets_small_helper( 1..=6, 64, &[ hashset! {}, hashset! {1}, hashset! {2}, hashset! {3}, hashset! {4}, hashset! {5}, hashset! {6}, hashset! {1, 2}, hashset! {1, 3}, hashset! {1, 4}, hashset! {1, 5}, hashset! {1, 6}, hashset! {2, 3}, hashset! {2, 4}, hashset! {2, 5}, hashset! {2, 6}, hashset! {3, 4}, hashset! {3, 5}, hashset! {3, 6}, hashset! {4, 5}, ], ); shortlex_hash_sets_small_helper( 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'c'}, hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, ], ); shortlex_hash_sets_helper( exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'c'}, hashset! {'d'}, hashset! {'e'}, hashset! {'f'}, hashset! {'g'}, hashset! {'h'}, hashset! {'i'}, hashset! {'j'}, hashset! {'k'}, hashset! {'l'}, hashset! {'m'}, hashset! {'n'}, hashset! {'o'}, hashset! {'p'}, hashset! {'q'}, hashset! {'r'}, hashset! {'s'}, ], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_hash_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_hash_sets_length_inclusive_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn shortlex_hash_sets_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( shortlex_hash_sets_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_hash_sets_length_inclusive_range() { shortlex_hash_sets_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[hashset! {}]); shortlex_hash_sets_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); shortlex_hash_sets_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); shortlex_hash_sets_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_hash_sets_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); shortlex_hash_sets_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[hashset! {false, true}], ); shortlex_hash_sets_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_hash_sets_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_hash_sets_length_range; use malachite_base::test_util::sets::exhaustive::exhaustive_hash_sets_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn shortlex_hash_sets_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( shortlex_hash_sets_length_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_hash_sets_length_range() { shortlex_hash_sets_length_range_small_helper(0, 5, nevers(), 1, &[hashset! {}]); shortlex_hash_sets_length_range_small_helper(6, 10, nevers(), 0, &[]); shortlex_hash_sets_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); shortlex_hash_sets_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_hash_sets_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); shortlex_hash_sets_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[hashset! {}, hashset! {false}, hashset! {true}], ); shortlex_hash_sets_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[hashset! {false, true}], ); shortlex_hash_sets_length_range_small_helper( 1, 2, 'a'..='c', 3, &[hashset! {'a'}, hashset! {'b'}, hashset! {'c'}], ); } ================================================ FILE: malachite-base/tests/sets/exhaustive/shortlex_hash_sets_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::sets::exhaustive::shortlex_hash_sets_min_length; use malachite_base::test_util::sets::exhaustive::{ exhaustive_hash_sets_helper_helper, exhaustive_hash_sets_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn shortlex_hash_sets_min_length_helper( min_length: u64, xs: I, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_helper_helper(shortlex_hash_sets_min_length(min_length, xs), out); } fn shortlex_hash_sets_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[HashSet], ) where I::Item: Clone + Debug + Eq + Hash, { exhaustive_hash_sets_small_helper_helper( shortlex_hash_sets_min_length(min_length, xs), out_len, out, ); } #[test] fn test_shortlex_hash_sets_min_length() { shortlex_hash_sets_min_length_small_helper(0, nevers(), 1, &[hashset! {}]); shortlex_hash_sets_min_length_small_helper(4, nevers(), 0, &[]); shortlex_hash_sets_min_length_small_helper( 0, exhaustive_units(), 2, &[hashset! {}, hashset! {()}], ); shortlex_hash_sets_min_length_small_helper(5, exhaustive_units(), 0, &[]); shortlex_hash_sets_min_length_small_helper( 0, exhaustive_bools(), 4, &[hashset! {}, hashset! {false}, hashset! {true}, hashset! {false, true}], ); shortlex_hash_sets_min_length_small_helper( 1, exhaustive_bools(), 3, &[hashset! {false}, hashset! {true}, hashset! {false, true}], ); shortlex_hash_sets_min_length_small_helper( 0, 'a'..='c', 8, &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'c'}, hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}, ], ); shortlex_hash_sets_min_length_small_helper( 2, 'a'..='c', 4, &[hashset! {'a', 'b'}, hashset! {'a', 'c'}, hashset! {'b', 'c'}, hashset! {'a', 'b', 'c'}], ); shortlex_hash_sets_min_length_helper( 0, exhaustive_ascii_chars(), &[ hashset! {}, hashset! {'a'}, hashset! {'b'}, hashset! {'c'}, hashset! {'d'}, hashset! {'e'}, hashset! {'f'}, hashset! {'g'}, hashset! {'h'}, hashset! {'i'}, hashset! {'j'}, hashset! {'k'}, hashset! {'l'}, hashset! {'m'}, hashset! {'n'}, hashset! {'o'}, hashset! {'p'}, hashset! {'q'}, hashset! {'r'}, hashset! {'s'}, ], ); shortlex_hash_sets_min_length_helper( 3, exhaustive_ascii_chars(), &[ hashset! {'a', 'b', 'c'}, hashset! {'a', 'b', 'd'}, hashset! {'a', 'b', 'e'}, hashset! {'a', 'b', 'f'}, hashset! {'a', 'b', 'g'}, hashset! {'a', 'b', 'h'}, hashset! {'a', 'b', 'i'}, hashset! {'a', 'b', 'j'}, hashset! {'a', 'b', 'k'}, hashset! {'a', 'b', 'l'}, hashset! {'a', 'b', 'm'}, hashset! {'a', 'b', 'n'}, hashset! {'a', 'b', 'o'}, hashset! {'a', 'b', 'p'}, hashset! {'a', 'b', 'q'}, hashset! {'a', 'b', 'r'}, hashset! {'a', 'b', 's'}, hashset! {'a', 'b', 't'}, hashset! {'a', 'b', 'u'}, hashset! {'a', 'b', 'v'}, ], ); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_b_tree_sets; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_helper>( xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) { let xs = random_b_tree_sets( EXAMPLE_SEED, xs_gen, mean_length_numerator, mean_length_denominator, ); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets() { random_b_tree_sets_helper( &random_primitive_ints::, 4, 1, &[ btreeset! {}, btreeset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, btreeset! {30, 90, 218, 234}, btreeset! {9, 106, 204, 216}, btreeset! {151}, btreeset! {}, btreeset! {78, 91, 97, 213, 253}, btreeset! {39, 191}, btreeset! {170, 175, 232, 233}, btreeset! {}, btreeset! {2, 22, 35, 114, 198, 217}, btreeset! {}, btreeset! {}, btreeset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, btreeset! {52, 69, 73, 91, 115, 137, 153, 178}, btreeset! {}, btreeset! {34, 95, 112}, btreeset! {}, btreeset! {106, 130, 167, 168, 197}, btreeset! {86, 101, 122, 150, 172, 177, 207, 218, 221}, ], &[ (btreeset! {}, 199913), (btreeset! {7}, 705), (btreeset! {25}, 689), (btreeset! {184}, 681), (btreeset! {213}, 681), (btreeset! {255}, 676), (btreeset! {215}, 675), (btreeset! {54}, 673), (btreeset! {122}, 672), (btreeset! {207}, 672), ], ( btreeset! {27, 31, 211, 238}, Some(btreeset! {27, 31, 247, 251}), ), ); random_b_tree_sets_helper( &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ btreeset! {}, btreeset! {1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141}, btreeset! {0, 1, 10, 99}, btreeset! {2, 12, 36, 77}, btreeset! {1}, btreeset! {}, btreeset! {1, 5, 9, 19, 103}, btreeset! {6, 7}, btreeset! {15, 18, 51, 159}, btreeset! {}, btreeset! {2, 26, 40, 52, 64, 75}, btreeset! {}, btreeset! {}, btreeset! {3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67}, btreeset! {1, 14, 16, 24, 29, 41, 47, 52}, btreeset! {}, btreeset! {11, 13, 62}, btreeset! {}, btreeset! {3, 14, 42, 47, 109}, btreeset! {5, 13, 16, 25, 37, 41, 42, 86, 96}, ], &[ (btreeset! {}, 199913), (btreeset! {0}, 4861), (btreeset! {1}, 4593), (btreeset! {2}, 4498), (btreeset! {3}, 4405), (btreeset! {4}, 4330), (btreeset! {5}, 4078), (btreeset! {6}, 4050), (btreeset! {7}, 3858), (btreeset! {8}, 3848), ], ( btreeset! {3, 9, 14, 22, 36, 56, 107}, Some(btreeset! {3, 9, 14, 22, 42, 54, 73, 150}), ), ); random_b_tree_sets_helper( &random_primitive_ints::, 1, 4, &[ btreeset! {}, btreeset! {}, btreeset! {85}, btreeset! {11}, btreeset! {136, 200}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {134, 235}, btreeset! {203}, btreeset! {}, btreeset! {38, 223}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, ], &[ (btreeset! {}, 800023), (btreeset! {162}, 692), (btreeset! {235}, 690), (btreeset! {90}, 688), (btreeset! {65}, 687), (btreeset! {249}, 686), (btreeset! {175}, 684), (btreeset! {108}, 683), (btreeset! {211}, 682), (btreeset! {237}, 680), ], (btreeset! {}, None), ); random_b_tree_sets_helper( &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ btreeset! {}, btreeset! {'g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'}, btreeset! {'ª', '´', 'Ã', 'ä'}, btreeset! {'½', 'Á', 'Ï', 'ý'}, btreeset! {'j'}, btreeset! {}, btreeset! {'u', '½', 'Â', 'Ñ', 'ï'}, btreeset! {'x', 'õ'}, btreeset! {'¡', 'Â', 'ù', 'Ċ'}, btreeset! {}, btreeset! {'b', 'r', 's', '¬', 'Â', 'Ñ'}, btreeset! {}, btreeset! {}, btreeset! {'j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'}, btreeset! {'b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'}, btreeset! {}, btreeset! {'«', '¹', 'Î'}, btreeset! {}, btreeset! {'~', '¯', '´', 'Ý', 'â'}, btreeset! {'g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'}, ], &[ (btreeset! {}, 199913), (btreeset! {'Ó'}, 1270), (btreeset! {'Â'}, 1249), (btreeset! {'§'}, 1244), (btreeset! {'¿'}, 1243), (btreeset! {'õ'}, 1241), (btreeset! {'ĉ'}, 1234), (btreeset! {'¤'}, 1232), (btreeset! {'¼'}, 1232), (btreeset! {'Ì'}, 1229), ], ( btreeset! {'o', 'v', '¢', '±', 'Ä', 'Ć'}, Some(btreeset! {'o', 'v', '¢', '³', 'ã'}), ), ); } #[test] #[should_panic] fn random_b_tree_sets_fail_1() { random_b_tree_sets(EXAMPLE_SEED, &random_primitive_ints::, 0, 1); } #[test] #[should_panic] fn random_b_tree_sets_fail_2() { random_b_tree_sets(EXAMPLE_SEED, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_b_tree_sets_fail_3() { random_b_tree_sets( EXAMPLE_SEED, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets_fixed_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::sets::random::random_b_tree_sets_fixed_length; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_fixed_length_helper( len: u64, xs: I, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_b_tree_sets_fixed_length(len, xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets_fixed_length() { random_b_tree_sets_fixed_length_helper( 0, random_primitive_ints::(EXAMPLE_SEED), &repeat_n(btreeset! {}, 20).collect_vec(), &[(btreeset! {}, 1000000)], (btreeset! {}, None), ); random_b_tree_sets_fixed_length_helper( 1, random_bools(EXAMPLE_SEED), &[ btreeset! {true}, btreeset! {false}, btreeset! {false}, btreeset! {false}, btreeset! {true}, btreeset! {true}, btreeset! {true}, btreeset! {false}, btreeset! {true}, btreeset! {true}, btreeset! {true}, btreeset! {true}, btreeset! {false}, btreeset! {true}, btreeset! {true}, btreeset! {true}, btreeset! {true}, btreeset! {false}, btreeset! {true}, btreeset! {false}, ], &[(btreeset! {true}, 500473), (btreeset! {false}, 499527)], (btreeset! {true}, None), ); random_b_tree_sets_fixed_length_helper( 3, random_primitive_ints::(EXAMPLE_SEED), &[ btreeset! {69, 113, 239}, btreeset! {108, 210, 228}, btreeset! {87, 161, 168}, btreeset! {32, 83, 110}, btreeset! {34, 89, 188}, btreeset! {93, 200, 238}, btreeset! {115, 149, 189}, btreeset! {149, 201, 217}, btreeset! {31, 117, 146}, btreeset! {72, 151, 169}, btreeset! {7, 33, 174}, btreeset! {38, 81, 144}, btreeset! {72, 113, 127}, btreeset! {107, 128, 233}, btreeset! {12, 46, 119}, btreeset! {18, 164, 243}, btreeset! {59, 114, 174}, btreeset! {39, 174, 247}, btreeset! {104, 160, 184}, btreeset! {37, 100, 252}, ], &[ (btreeset! {57, 142, 207}, 7), (btreeset! {32, 68, 169}, 6), (btreeset! {36, 70, 195}, 6), (btreeset! {125, 168, 194}, 6), (btreeset! {0, 97, 205}, 5), (btreeset! {2, 33, 227}, 5), (btreeset! {5, 46, 239}, 5), (btreeset! {9, 68, 189}, 5), (btreeset! {9, 78, 240}, 5), (btreeset! {1, 110, 203}, 5), ], (btreeset! {52, 133, 241}, Some(btreeset! {52, 133, 242})), ); random_b_tree_sets_fixed_length_helper( 2, random_b_tree_sets_fixed_length(2, random_primitive_ints::(EXAMPLE_SEED)), &[ btreeset! {btreeset!{69, 108}, btreeset!{113, 239}}, btreeset! {btreeset!{161, 168}, btreeset!{210, 228}}, btreeset! {btreeset!{32, 87}, btreeset!{83, 110}}, btreeset! {btreeset!{34, 188}, btreeset!{89, 238}}, btreeset! {btreeset!{93, 200}, btreeset!{115, 149}}, btreeset! {btreeset!{149, 189}, btreeset!{201, 217}}, btreeset! {btreeset!{31, 72}, btreeset!{117, 146}}, btreeset! {btreeset!{33, 174}, btreeset!{151, 169}}, btreeset! {btreeset!{7, 38}, btreeset!{81, 144}}, btreeset! {btreeset!{72, 127}, btreeset!{113, 128}}, btreeset! {btreeset!{46, 119}, btreeset!{107, 233}}, btreeset! {btreeset!{12, 18}, btreeset!{164, 243}}, btreeset! {btreeset!{59, 247}, btreeset!{114, 174}}, btreeset! {btreeset!{39, 174}, btreeset!{160, 184}}, btreeset! {btreeset!{37, 104}, btreeset!{100, 252}}, btreeset! {btreeset!{69, 107}, btreeset!{122, 228}}, btreeset! {btreeset!{142, 179}, btreeset!{242, 248}}, btreeset! {btreeset!{61, 189}, btreeset!{233, 239}}, btreeset! {btreeset!{7, 192}, btreeset!{85, 235}}, btreeset! {btreeset!{90, 200}, btreeset!{178, 185}}, ], &[ (btreeset! {btreeset!{0, 78}, btreeset!{34, 52}}, 2), (btreeset! {btreeset!{1, 58}, btreeset!{6, 112}}, 2), (btreeset! {btreeset!{1, 63}, btreeset!{8, 154}}, 2), (btreeset! {btreeset!{1, 97}, btreeset!{7, 250}}, 2), (btreeset! {btreeset!{2, 33}, btreeset!{40, 81}}, 2), (btreeset! {btreeset!{3, 160}, btreeset!{7, 29}}, 2), (btreeset! {btreeset!{3, 32}, btreeset!{12, 60}}, 2), (btreeset! {btreeset!{6, 130}, btreeset!{7, 20}}, 2), (btreeset! {btreeset!{6, 68}, btreeset!{7, 126}}, 2), (btreeset! {btreeset!{6, 77}, btreeset!{36, 54}}, 2), ], ( btreeset! {btreeset!{40, 193}, btreeset!{94, 142}}, Some(btreeset! {btreeset!{40, 193}, btreeset!{97, 243}}), ), ); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets_from_length_iterator.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::bools::random::random_bools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_b_tree_sets_from_length_iterator; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::vecs::random_values_from_vec; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_from_length_iterator_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) { let xs = random_b_tree_sets_from_length_iterator(EXAMPLE_SEED, lengths_gen, xs_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets_from_length_iterator() { random_b_tree_sets_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2]), &random_bools, &[ btreeset! {false, true}, btreeset! {}, btreeset! {false, true}, btreeset! {false, true}, btreeset! {}, btreeset! {false, true}, btreeset! {false, true}, btreeset! {}, btreeset! {false, true}, btreeset! {false, true}, btreeset! {}, btreeset! {false, true}, btreeset! {}, btreeset! {false, true}, btreeset! {false, true}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {false, true}, btreeset! {}, ], &[(btreeset! {false, true}, 500363), (btreeset! {}, 499637)], (btreeset! {false, true}, None), ); random_b_tree_sets_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), &random_primitive_ints::, &[ btreeset! {11, 38, 85, 134, 136, 162, 177, 200, 203, 217, 223, 235}, btreeset! {32, 166}, btreeset! {9, 30, 39, 78, 90, 91, 97, 106, 151, 191, 204, 213, 216, 218, 234, 253}, btreeset! {170, 175}, btreeset! { 2, 17, 22, 25, 32, 34, 35, 52, 65, 69, 73, 79, 91, 112, 114, 115, 121, 137, 144, 148, 153, 173, 178, 198, 217, 222, 232, 233, }, btreeset! {}, btreeset! {95, 106, 122, 130, 167, 168, 172, 177, 197, 207}, btreeset! {9, 74, 86, 101, 115, 150, 218, 221}, btreeset! {109, 123}, btreeset! {}, btreeset! {40, 48, 52, 97, 104, 133, 159, 196, 201, 235, 247, 250}, btreeset! {7, 68, 190, 216}, btreeset! {}, btreeset! {}, btreeset! {157, 216}, btreeset! {11, 24, 43, 103, 112, 217}, btreeset! {}, btreeset! {84, 211}, btreeset! {}, btreeset! {55, 135}, ], &[ (btreeset! {}, 333981), (btreeset! {33, 163}, 22), (btreeset! {76, 233}, 19), (btreeset! {5, 42}, 18), (btreeset! {76, 79}, 18), (btreeset! {32, 134}, 18), (btreeset! {69, 234}, 18), (btreeset! {74, 164}, 18), (btreeset! {86, 192}, 18), (btreeset! {99, 145}, 18), ], (btreeset! {12, 190}, None), ); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_b_tree_sets_length_inclusive_range; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_length_inclusive_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) { let xs = random_b_tree_sets_length_inclusive_range(EXAMPLE_SEED, a, b, xs_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets_length_inclusive_range() { random_b_tree_sets_length_inclusive_range_helper( 2, 3, &random_primitive_ints::, &[ btreeset! {11, 85, 136}, btreeset! {200, 235}, btreeset! {134, 203, 223}, btreeset! {38, 217, 235}, btreeset! {162, 177}, btreeset! {32, 166, 234}, btreeset! {30, 90, 218}, btreeset! {9, 106}, btreeset! {151, 204, 216}, btreeset! {97, 213, 253}, btreeset! {78, 91}, btreeset! {39, 175, 191}, btreeset! {170, 232}, btreeset! {2, 35, 233}, btreeset! {22, 198, 217}, btreeset! {17, 114}, btreeset! {32, 173}, btreeset! {65, 114}, btreeset! {121, 173, 222}, btreeset! {25, 144}, ], &[ (btreeset! {106, 108}, 34), (btreeset! {224, 237}, 34), (btreeset! {51, 132}, 32), (btreeset! {82, 117}, 32), (btreeset! {72, 108}, 31), (btreeset! {142, 194}, 31), (btreeset! {0, 34}, 30), (btreeset! {12, 208}, 30), (btreeset! {15, 141}, 30), (btreeset! {30, 248}, 30), ], (btreeset! {62, 131, 203}, Some(btreeset! {62, 131, 205})), ); random_b_tree_sets_length_inclusive_range_helper( 2, 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ btreeset! {0, 1, 5}, btreeset! {1, 4}, btreeset! {2, 4, 6}, btreeset! {0, 1, 2}, btreeset! {9, 13}, btreeset! {0, 2, 7}, btreeset! {4, 6, 7}, btreeset! {0, 6}, btreeset! {0, 1, 3}, btreeset! {1, 2, 5}, btreeset! {0, 1}, btreeset! {0, 1, 4}, btreeset! {0, 2}, btreeset! {0, 2, 12}, btreeset! {1, 2, 3}, btreeset! {3, 9}, btreeset! {0, 1}, btreeset! {1, 2}, btreeset! {0, 1, 11}, btreeset! {1, 6}, ], &[ (btreeset! {0, 1}, 103032), (btreeset! {0, 1, 2}, 84142), (btreeset! {0, 2}, 66185), (btreeset! {0, 1, 3}, 52638), (btreeset! {0, 3}, 42990), (btreeset! {1, 2}, 40380), (btreeset! {0, 1, 4}, 33815), (btreeset! {0, 2, 3}, 31257), (btreeset! {0, 4}, 28088), (btreeset! {1, 3}, 26214), ], (btreeset! {0, 3}, None), ); random_b_tree_sets_length_inclusive_range_helper( 2, 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ btreeset! {'c', 'q', 'v'}, btreeset! {'e', 'i'}, btreeset! {'g', 'p', 's'}, btreeset! {'m', 'n', 't'}, btreeset! {'o', 'z'}, btreeset! {'f', 'k', 'm'}, btreeset! {'q', 'u', 'y'}, btreeset! {'k', 'x'}, btreeset! {'h', 'n', 'u'}, btreeset! {'a', 'j', 'n'}, btreeset! {'w', 'z'}, btreeset! {'b', 'l', 'w'}, btreeset! {'l', 'u'}, btreeset! {'e', 'l', 'n'}, btreeset! {'k', 'u', 'v'}, btreeset! {'c', 'h'}, btreeset! {'i', 'y'}, btreeset! {'m', 'r'}, btreeset! {'m', 's', 'y'}, btreeset! {'e', 'l'}, ], &[ (btreeset! {'l', 'x'}, 1640), (btreeset! {'o', 't'}, 1636), (btreeset! {'b', 'p'}, 1630), (btreeset! {'m', 'v'}, 1623), (btreeset! {'h', 'u'}, 1621), (btreeset! {'a', 'x'}, 1614), (btreeset! {'d', 'f'}, 1613), (btreeset! {'e', 'r'}, 1613), (btreeset! {'o', 'p'}, 1612), (btreeset! {'c', 'i'}, 1611), ], (btreeset! {'g', 'j'}, None), ); } #[test] #[should_panic] fn random_b_tree_sets_length_inclusive_range_fail() { random_b_tree_sets_length_inclusive_range(EXAMPLE_SEED, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets_length_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_b_tree_sets_length_range; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_length_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) { let xs = random_b_tree_sets_length_range(EXAMPLE_SEED, a, b, xs_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets_length_range() { random_b_tree_sets_length_range_helper( 2, 4, &random_primitive_ints::, &[ btreeset! {11, 85, 136}, btreeset! {200, 235}, btreeset! {134, 203, 223}, btreeset! {38, 217, 235}, btreeset! {162, 177}, btreeset! {32, 166, 234}, btreeset! {30, 90, 218}, btreeset! {9, 106}, btreeset! {151, 204, 216}, btreeset! {97, 213, 253}, btreeset! {78, 91}, btreeset! {39, 175, 191}, btreeset! {170, 232}, btreeset! {2, 35, 233}, btreeset! {22, 198, 217}, btreeset! {17, 114}, btreeset! {32, 173}, btreeset! {65, 114}, btreeset! {121, 173, 222}, btreeset! {25, 144}, ], &[ (btreeset! {106, 108}, 34), (btreeset! {224, 237}, 34), (btreeset! {51, 132}, 32), (btreeset! {82, 117}, 32), (btreeset! {72, 108}, 31), (btreeset! {142, 194}, 31), (btreeset! {0, 34}, 30), (btreeset! {12, 208}, 30), (btreeset! {15, 141}, 30), (btreeset! {30, 248}, 30), ], (btreeset! {62, 131, 203}, Some(btreeset! {62, 131, 205})), ); random_b_tree_sets_length_range_helper( 2, 4, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ btreeset! {0, 1, 5}, btreeset! {1, 4}, btreeset! {2, 4, 6}, btreeset! {0, 1, 2}, btreeset! {9, 13}, btreeset! {0, 2, 7}, btreeset! {4, 6, 7}, btreeset! {0, 6}, btreeset! {0, 1, 3}, btreeset! {1, 2, 5}, btreeset! {0, 1}, btreeset! {0, 1, 4}, btreeset! {0, 2}, btreeset! {0, 2, 12}, btreeset! {1, 2, 3}, btreeset! {3, 9}, btreeset! {0, 1}, btreeset! {1, 2}, btreeset! {0, 1, 11}, btreeset! {1, 6}, ], &[ (btreeset! {0, 1}, 103032), (btreeset! {0, 1, 2}, 84142), (btreeset! {0, 2}, 66185), (btreeset! {0, 1, 3}, 52638), (btreeset! {0, 3}, 42990), (btreeset! {1, 2}, 40380), (btreeset! {0, 1, 4}, 33815), (btreeset! {0, 2, 3}, 31257), (btreeset! {0, 4}, 28088), (btreeset! {1, 3}, 26214), ], (btreeset! {0, 3}, None), ); random_b_tree_sets_length_range_helper( 2, 4, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ btreeset! {'c', 'q', 'v'}, btreeset! {'e', 'i'}, btreeset! {'g', 'p', 's'}, btreeset! {'m', 'n', 't'}, btreeset! {'o', 'z'}, btreeset! {'f', 'k', 'm'}, btreeset! {'q', 'u', 'y'}, btreeset! {'k', 'x'}, btreeset! {'h', 'n', 'u'}, btreeset! {'a', 'j', 'n'}, btreeset! {'w', 'z'}, btreeset! {'b', 'l', 'w'}, btreeset! {'l', 'u'}, btreeset! {'e', 'l', 'n'}, btreeset! {'k', 'u', 'v'}, btreeset! {'c', 'h'}, btreeset! {'i', 'y'}, btreeset! {'m', 'r'}, btreeset! {'m', 's', 'y'}, btreeset! {'e', 'l'}, ], &[ (btreeset! {'l', 'x'}, 1640), (btreeset! {'o', 't'}, 1636), (btreeset! {'b', 'p'}, 1630), (btreeset! {'m', 'v'}, 1623), (btreeset! {'h', 'u'}, 1621), (btreeset! {'a', 'x'}, 1614), (btreeset! {'d', 'f'}, 1613), (btreeset! {'e', 'r'}, 1613), (btreeset! {'o', 'p'}, 1612), (btreeset! {'c', 'i'}, 1611), ], (btreeset! {'g', 'j'}, None), ); } #[test] #[should_panic] fn random_b_tree_sets_length_range_fail() { random_b_tree_sets_length_range(EXAMPLE_SEED, 2, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/sets/random/random_b_tree_sets_min_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_b_tree_sets_min_length; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::collections::BTreeSet; use std::fmt::Debug; fn random_b_tree_sets_min_length_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[BTreeSet], expected_common_values: &[(BTreeSet, usize)], expected_median: (BTreeSet, Option>), ) { let xs = random_b_tree_sets_min_length( EXAMPLE_SEED, min_length, xs_gen, mean_length_numerator, mean_length_denominator, ); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_b_tree_sets_min_length() { random_b_tree_sets_min_length_helper( 0, &random_primitive_ints::, 4, 1, &[ btreeset! {}, btreeset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, btreeset! {30, 90, 218, 234}, btreeset! {9, 106, 204, 216}, btreeset! {151}, btreeset! {}, btreeset! {78, 91, 97, 213, 253}, btreeset! {39, 191}, btreeset! {170, 175, 232, 233}, btreeset! {}, btreeset! {2, 22, 35, 114, 198, 217}, btreeset! {}, btreeset! {}, btreeset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, btreeset! {52, 69, 73, 91, 115, 137, 153, 178}, btreeset! {}, btreeset! {34, 95, 112}, btreeset! {}, btreeset! {106, 130, 167, 168, 197}, btreeset! {86, 101, 122, 150, 172, 177, 207, 218, 221}, ], &[ (btreeset! {}, 199913), (btreeset! {7}, 705), (btreeset! {25}, 689), (btreeset! {184}, 681), (btreeset! {213}, 681), (btreeset! {255}, 676), (btreeset! {215}, 675), (btreeset! {54}, 673), (btreeset! {122}, 672), (btreeset! {207}, 672), ], ( btreeset! {27, 31, 211, 238}, Some(btreeset! {27, 31, 247, 251}), ), ); random_b_tree_sets_min_length_helper( 3, &random_primitive_ints::, 7, 1, &[ btreeset! {11, 85, 136}, btreeset! { 9, 30, 32, 38, 90, 106, 134, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235 }, btreeset! {78, 97, 151, 204, 213, 216, 253}, btreeset! {39, 91, 170, 175, 191, 232, 233}, btreeset! {2, 22, 35, 217}, btreeset! {17, 114, 198}, btreeset! {25, 32, 65, 114, 121, 144, 173, 222}, btreeset! {52, 73, 79, 115, 148}, btreeset! {34, 69, 91, 112, 137, 153, 178}, btreeset! {95, 106, 167}, btreeset! {86, 122, 130, 150, 168, 172, 177, 197, 207}, btreeset! {101, 218, 221}, btreeset! {9, 74, 115}, btreeset! {40, 48, 52, 97, 104, 109, 123, 133, 159, 196, 201, 235, 247, 250}, btreeset! {7, 11, 24, 43, 68, 103, 112, 157, 190, 216, 217}, btreeset! {84, 135, 211}, btreeset! {29, 55, 65, 89, 191, 206}, btreeset! {9, 51, 79}, btreeset! {3, 20, 22, 34, 62, 114, 118, 148}, btreeset! {23, 32, 47, 50, 120, 166, 176, 177, 194, 204, 238, 248}, ], &[ (btreeset! {5, 128, 142}, 4), (btreeset! {137, 145, 160}, 4), (btreeset! {2, 4, 52}, 3), (btreeset! {1, 5, 192}, 3), (btreeset! {12, 41, 58}, 3), (btreeset! {2, 95, 171}, 3), (btreeset! {20, 86, 94}, 3), (btreeset! {21, 43, 50}, 3), (btreeset! {3, 81, 122}, 3), (btreeset! {31, 54, 79}, 3), ], ( btreeset! {26, 138, 167}, Some(btreeset! {26, 138, 167, 173, 211}), ), ); random_b_tree_sets_min_length_helper( 0, &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ btreeset! {}, btreeset! {1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141}, btreeset! {0, 1, 10, 99}, btreeset! {2, 12, 36, 77}, btreeset! {1}, btreeset! {}, btreeset! {1, 5, 9, 19, 103}, btreeset! {6, 7}, btreeset! {15, 18, 51, 159}, btreeset! {}, btreeset! {2, 26, 40, 52, 64, 75}, btreeset! {}, btreeset! {}, btreeset! {3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67}, btreeset! {1, 14, 16, 24, 29, 41, 47, 52}, btreeset! {}, btreeset! {11, 13, 62}, btreeset! {}, btreeset! {3, 14, 42, 47, 109}, btreeset! {5, 13, 16, 25, 37, 41, 42, 86, 96}, ], &[ (btreeset! {}, 199913), (btreeset! {0}, 4861), (btreeset! {1}, 4593), (btreeset! {2}, 4498), (btreeset! {3}, 4405), (btreeset! {4}, 4330), (btreeset! {5}, 4078), (btreeset! {6}, 4050), (btreeset! {7}, 3858), (btreeset! {8}, 3848), ], ( btreeset! {3, 9, 14, 22, 36, 56, 107}, Some(btreeset! {3, 9, 14, 22, 42, 54, 73, 150}), ), ); random_b_tree_sets_min_length_helper( 3, &|seed| geometric_random_unsigneds::(seed, 32, 1), 7, 1, &[ btreeset! {1, 14, 42}, btreeset! {0, 1, 9, 10, 12, 16, 17, 19, 21, 36, 41, 68, 77, 79, 99, 124, 141}, btreeset! {1, 2, 5, 9, 12, 19, 103}, btreeset! {6, 7, 15, 18, 51, 52, 159}, btreeset! {2, 40, 64, 75}, btreeset! {26, 34, 67}, btreeset! {4, 5, 7, 30, 31, 43, 49, 51}, btreeset! {3, 14, 16, 24, 47}, btreeset! {1, 11, 13, 29, 41, 52, 62}, btreeset! {3, 47, 109}, btreeset! {13, 14, 16, 25, 37, 41, 42, 86, 96}, btreeset! {5, 20, 42}, btreeset! {2, 74, 82}, btreeset! {3, 6, 7, 11, 17, 20, 36, 45, 56, 66, 76, 80, 89, 127}, btreeset! {1, 6, 10, 13, 19, 23, 25, 32, 41, 43, 97}, btreeset! {7, 41, 134}, btreeset! {9, 10, 25, 26, 47, 105}, btreeset! {68, 94, 109}, btreeset! {1, 3, 9, 13, 28, 43, 44, 84}, btreeset! {0, 4, 5, 6, 7, 13, 31, 32, 37, 42, 50, 75}, ], &[ (btreeset! {0, 2, 5}, 42), (btreeset! {0, 1, 8}, 39), (btreeset! {0, 3, 4}, 38), (btreeset! {1, 3, 9}, 38), (btreeset! {0, 1, 7}, 35), (btreeset! {0, 2, 8}, 34), (btreeset! {1, 2, 12}, 34), (btreeset! {0, 1, 2}, 33), (btreeset! {1, 2, 3}, 33), (btreeset! {1, 3, 4}, 33), ], ( btreeset! {3, 8, 14, 19, 25, 36, 52, 64, 71}, Some(btreeset! {3, 8, 14, 19, 25, 38, 58, 61}), ), ); random_b_tree_sets_min_length_helper( 0, &random_primitive_ints::, 1, 4, &[ btreeset! {}, btreeset! {}, btreeset! {85}, btreeset! {11}, btreeset! {136, 200}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {134, 235}, btreeset! {203}, btreeset! {}, btreeset! {38, 223}, btreeset! {}, btreeset! {}, btreeset! {}, btreeset! {}, ], &[ (btreeset! {}, 800023), (btreeset! {162}, 692), (btreeset! {235}, 690), (btreeset! {90}, 688), (btreeset! {65}, 687), (btreeset! {249}, 686), (btreeset! {175}, 684), (btreeset! {108}, 683), (btreeset! {211}, 682), (btreeset! {237}, 680), ], (btreeset! {}, None), ); random_b_tree_sets_min_length_helper( 3, &random_primitive_ints::, 13, 4, &[ btreeset! {11, 85, 136}, btreeset! {134, 200, 235}, btreeset! {38, 203, 223, 235}, btreeset! {32, 162, 177, 217}, btreeset! {30, 90, 166, 218, 234}, btreeset! {9, 106, 216}, btreeset! {151, 204, 213}, btreeset! {78, 97, 253}, btreeset! {39, 91, 191}, btreeset! {170, 175, 232}, btreeset! {2, 35, 233}, btreeset! {22, 198, 217}, btreeset! {17, 32, 65, 114, 173}, btreeset! {25, 121, 173, 222}, btreeset! {79, 144, 148}, btreeset! {52, 69, 73, 115, 137}, btreeset! {91, 153, 178}, btreeset! {34, 95, 112}, btreeset! {106, 167, 197}, btreeset! {122, 130, 168}, ], &[ (btreeset! {10, 87, 204}, 6), (btreeset! {15, 40, 115}, 6), (btreeset! {108, 193, 199}, 6), (btreeset! {1, 22, 70}, 5), (btreeset! {1, 8, 212}, 5), (btreeset! {2, 40, 169}, 5), (btreeset! {2, 58, 211}, 5), (btreeset! {3, 29, 186}, 5), (btreeset! {3, 97, 112}, 5), (btreeset! {11, 66, 140}, 5), ], (btreeset! {49, 78, 193}, Some(btreeset! {49, 78, 193, 215})), ); random_b_tree_sets_min_length_helper( 0, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ btreeset! {}, btreeset! {'g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'}, btreeset! {'ª', '´', 'Ã', 'ä'}, btreeset! {'½', 'Á', 'Ï', 'ý'}, btreeset! {'j'}, btreeset! {}, btreeset! {'u', '½', 'Â', 'Ñ', 'ï'}, btreeset! {'x', 'õ'}, btreeset! {'¡', 'Â', 'ù', 'Ċ'}, btreeset! {}, btreeset! {'b', 'r', 's', '¬', 'Â', 'Ñ'}, btreeset! {}, btreeset! {}, btreeset! {'j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'}, btreeset! {'b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'}, btreeset! {}, btreeset! {'«', '¹', 'Î'}, btreeset! {}, btreeset! {'~', '¯', '´', 'Ý', 'â'}, btreeset! {'g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'}, ], &[ (btreeset! {}, 199913), (btreeset! {'Ó'}, 1270), (btreeset! {'Â'}, 1249), (btreeset! {'§'}, 1244), (btreeset! {'¿'}, 1243), (btreeset! {'õ'}, 1241), (btreeset! {'ĉ'}, 1234), (btreeset! {'¤'}, 1232), (btreeset! {'¼'}, 1232), (btreeset! {'Ì'}, 1229), ], ( btreeset! {'o', 'v', '¢', '±', 'Ä', 'Ć'}, Some(btreeset! {'o', 'v', '¢', '³', 'ã'}), ), ); random_b_tree_sets_min_length_helper( 3, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 7, 1, &[ btreeset! {'g', 'q', 'á'}, btreeset! { 'g', 'ª', '³', '´', '»', '½', 'À', 'Á', 'Ã', 'È', 'Ï', 'â', 'ä', 'ì', 'ñ', 'Ā', 'ą', }, btreeset! {'j', 'u', '½', 'Â', 'Ñ', 'ï', 'ý'}, btreeset! {'x', '¡', '¬', 'Â', 'õ', 'ù', 'Ċ'}, btreeset! {'b', 's', '¬', 'Ñ'}, btreeset! {'n', 'r', 'Â'}, btreeset! {'t', '¬', 'º', '¿', 'Ø', 'Þ', 'ô', 'ü'}, btreeset! {'j', 'k', '±', 'Á', 'è'}, btreeset! {'b', '«', '¹', 'Î', 'Ü', 'æ', 'ā'}, btreeset! {'~', '´', 'Î'}, btreeset! {'g', '¯', 'Î', 'Ý', 'Þ', 'â', 'æ', 'é', 'ö'}, btreeset! {'¼', 'Ç', 'Ü'}, btreeset! {'¡', '§', 'Ì'}, btreeset! {'d', 'm', 'z', '{', '¨', '®', '±', '¼', 'Ë', 'Ü', 'ê', 'ì', 'ý', 'þ'}, btreeset! {'x', 'ª', '½', 'À', 'Õ', 'ì', 'ï', 'û', 'ă', 'Ą', 'ċ'}, btreeset! {'¢', '«', 'Ć'}, btreeset! {'{', '¢', '½', 'È', 'ä', 'ÿ'}, btreeset! {'Ë', 'Õ', 'ê'}, btreeset! {'p', '¨', '°', 'º', 'Å', 'Ó', '×', 'ü'}, btreeset! {'d', 'k', 'o', 'v', '¥', '±', 'Ä', 'È', 'Ê', 'ß', 'æ', 'Ć'}, ], &[ (btreeset! {'m', 'u', 'w'}, 6), (btreeset! {'b', 'n', 'Ã'}, 6), (btreeset! {'g', '®', 'Ý'}, 6), (btreeset! {'x', 'Ä', 'î'}, 6), (btreeset! {'º', 'Ú', '÷'}, 6), (btreeset! {'a', 'w', 'ø'}, 5), (btreeset! {'c', 'e', 'Þ'}, 5), (btreeset! {'d', 't', 'Ã'}, 5), (btreeset! {'m', 'r', 'È'}, 5), (btreeset! {'w', '{', '³'}, 5), ], ( btreeset! {'o', 's', '×', 'Ý', 'Þ', 'ß', 'î', 'ù'}, Some(btreeset! {'o', 's', '×', 'à', 'ã', 'ò', 'ċ'}), ), ); } #[test] #[should_panic] fn random_b_tree_sets_min_length_fail_1() { random_b_tree_sets_min_length(EXAMPLE_SEED, 3, &random_primitive_ints::, 3, 1); } #[test] #[should_panic] fn random_b_tree_sets_min_length_fail_2() { random_b_tree_sets_min_length(EXAMPLE_SEED, 1, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_b_tree_sets_min_length_fail_3() { random_b_tree_sets_min_length( EXAMPLE_SEED, 0, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_hash_sets; use std::collections::HashSet; use std::fmt::Debug; fn random_hash_sets_helper>( xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[HashSet], ) { let xs = random_hash_sets( EXAMPLE_SEED, xs_gen, mean_length_numerator, mean_length_denominator, ); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets() { random_hash_sets_helper( &random_primitive_ints::, 4, 1, &[ hashset! {}, hashset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, hashset! {30, 90, 218, 234}, hashset! {9, 106, 204, 216}, hashset! {151}, hashset! {}, hashset! {78, 91, 97, 213, 253}, hashset! {39, 191}, hashset! {170, 175, 232, 233}, hashset! {}, hashset! {2, 22, 35, 114, 198, 217}, hashset! {}, hashset! {}, hashset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, hashset! {52, 69, 73, 91, 115, 137, 153, 178}, hashset! {}, hashset! {34, 95, 112}, hashset! {}, hashset! {106, 130, 167, 168, 197}, hashset! {86, 101, 122, 150, 172, 177, 207, 218, 221}, ], ); random_hash_sets_helper( &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ hashset! {}, hashset! {1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141}, hashset! {0, 1, 10, 99}, hashset! {2, 12, 36, 77}, hashset! {1}, hashset! {}, hashset! {1, 5, 9, 19, 103}, hashset! {6, 7}, hashset! {15, 18, 51, 159}, hashset! {}, hashset! {2, 26, 40, 52, 64, 75}, hashset! {}, hashset! {}, hashset! {3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67}, hashset! {1, 14, 16, 24, 29, 41, 47, 52}, hashset! {}, hashset! {11, 13, 62}, hashset! {}, hashset! {3, 14, 42, 47, 109}, hashset! {5, 13, 16, 25, 37, 41, 42, 86, 96}, ], ); random_hash_sets_helper( &random_primitive_ints::, 1, 4, &[ hashset! {}, hashset! {}, hashset! {85}, hashset! {11}, hashset! {136, 200}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {134, 235}, hashset! {203}, hashset! {}, hashset! {38, 223}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, ], ); random_hash_sets_helper( &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ hashset! {}, hashset! {'g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'}, hashset! {'ª', '´', 'Ã', 'ä'}, hashset! {'½', 'Á', 'Ï', 'ý'}, hashset! {'j'}, hashset! {}, hashset! {'u', '½', 'Â', 'Ñ', 'ï'}, hashset! {'x', 'õ'}, hashset! {'¡', 'Â', 'ù', 'Ċ'}, hashset! {}, hashset! {'b', 'r', 's', '¬', 'Â', 'Ñ'}, hashset! {}, hashset! {}, hashset! {'j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'}, hashset! {'b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'}, hashset! {}, hashset! {'«', '¹', 'Î'}, hashset! {}, hashset! {'~', '¯', '´', 'Ý', 'â'}, hashset! {'g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'}, ], ); } #[test] #[should_panic] fn random_hash_sets_fail_1() { random_hash_sets(EXAMPLE_SEED, &random_primitive_ints::, 0, 1); } #[test] #[should_panic] fn random_hash_sets_fail_2() { random_hash_sets(EXAMPLE_SEED, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_hash_sets_fail_3() { random_hash_sets( EXAMPLE_SEED, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets_fixed_length.rs ================================================ // Copyright © 2026 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, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::sets::random::random_hash_sets_fixed_length; use malachite_base::vecs::random::random_ordered_unique_vecs_fixed_length; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn random_hash_sets_fixed_length_helper( len: u64, xs: I, expected_values: &[HashSet], ) where I::Item: Debug + Eq + Hash, { let xs = random_hash_sets_fixed_length(len, xs); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets_fixed_length() { random_hash_sets_fixed_length_helper( 0, random_primitive_ints::(EXAMPLE_SEED), &repeat_n(hashset! {}, 20).collect_vec(), ); random_hash_sets_fixed_length_helper( 1, random_bools(EXAMPLE_SEED), &[ hashset! {true}, hashset! {false}, hashset! {false}, hashset! {false}, hashset! {true}, hashset! {true}, hashset! {true}, hashset! {false}, hashset! {true}, hashset! {true}, hashset! {true}, hashset! {true}, hashset! {false}, hashset! {true}, hashset! {true}, hashset! {true}, hashset! {true}, hashset! {false}, hashset! {true}, hashset! {false}, ], ); random_hash_sets_fixed_length_helper( 3, random_primitive_ints::(EXAMPLE_SEED), &[ hashset! {69, 113, 239}, hashset! {108, 210, 228}, hashset! {87, 161, 168}, hashset! {32, 83, 110}, hashset! {34, 89, 188}, hashset! {93, 200, 238}, hashset! {115, 149, 189}, hashset! {149, 201, 217}, hashset! {31, 117, 146}, hashset! {72, 151, 169}, hashset! {7, 33, 174}, hashset! {38, 81, 144}, hashset! {72, 113, 127}, hashset! {107, 128, 233}, hashset! {12, 46, 119}, hashset! {18, 164, 243}, hashset! {59, 114, 174}, hashset! {39, 174, 247}, hashset! {104, 160, 184}, hashset! {37, 100, 252}, ], ); random_hash_sets_fixed_length_helper( 2, random_ordered_unique_vecs_fixed_length(2, random_primitive_ints::(EXAMPLE_SEED)), &[ hashset! {vec![69, 108], vec![113, 239]}, hashset! {vec![161, 168], vec![210, 228]}, hashset! {vec![32, 87], vec![83, 110]}, hashset! {vec![34, 188], vec![89, 238]}, hashset! {vec![93, 200], vec![115, 149]}, hashset! {vec![149, 189], vec![201, 217]}, hashset! {vec![31, 72], vec![117, 146]}, hashset! {vec![33, 174], vec![151, 169]}, hashset! {vec![7, 38], vec![81, 144]}, hashset! {vec![72, 127], vec![113, 128]}, hashset! {vec![46, 119], vec![107, 233]}, hashset! {vec![12, 18], vec![164, 243]}, hashset! {vec![59, 247], vec![114, 174]}, hashset! {vec![39, 174], vec![160, 184]}, hashset! {vec![37, 104], vec![100, 252]}, hashset! {vec![69, 107], vec![122, 228]}, hashset! {vec![142, 179], vec![242, 248]}, hashset! {vec![61, 189], vec![233, 239]}, hashset! {vec![7, 192], vec![85, 235]}, hashset! {vec![90, 200], vec![178, 185]}, ], ); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets_from_length_iterator.rs ================================================ // Copyright © 2026 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::bools::random::random_bools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_hash_sets_from_length_iterator; use malachite_base::vecs::random_values_from_vec; use std::collections::HashSet; use std::fmt::Debug; use std::hash::Hash; fn random_hash_sets_from_length_iterator_helper< T: Clone + Debug + Eq + Hash, I: Clone + Iterator, J: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, expected_values: &[HashSet], ) { let xs = random_hash_sets_from_length_iterator(EXAMPLE_SEED, lengths_gen, xs_gen); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets_from_length_iterator() { random_hash_sets_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2]), &random_bools, &[ hashset! {false, true}, hashset! {}, hashset! {false, true}, hashset! {false, true}, hashset! {}, hashset! {false, true}, hashset! {false, true}, hashset! {}, hashset! {false, true}, hashset! {false, true}, hashset! {}, hashset! {false, true}, hashset! {}, hashset! {false, true}, hashset! {false, true}, hashset! {}, hashset! {}, hashset! {}, hashset! {false, true}, hashset! {}, ], ); random_hash_sets_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), &random_primitive_ints::, &[ hashset! {11, 38, 85, 134, 136, 162, 177, 200, 203, 217, 223, 235}, hashset! {32, 166}, hashset! {9, 30, 39, 78, 90, 91, 97, 106, 151, 191, 204, 213, 216, 218, 234, 253}, hashset! {170, 175}, hashset! { 2, 17, 22, 25, 32, 34, 35, 52, 65, 69, 73, 79, 91, 112, 114, 115, 121, 137, 144, 148, 153, 173, 178, 198, 217, 222, 232, 233, }, hashset! {}, hashset! {95, 106, 122, 130, 167, 168, 172, 177, 197, 207}, hashset! {9, 74, 86, 101, 115, 150, 218, 221}, hashset! {109, 123}, hashset! {}, hashset! {40, 48, 52, 97, 104, 133, 159, 196, 201, 235, 247, 250}, hashset! {7, 68, 190, 216}, hashset! {}, hashset! {}, hashset! {157, 216}, hashset! {11, 24, 43, 103, 112, 217}, hashset! {}, hashset! {84, 211}, hashset! {}, hashset! {55, 135}, ], ); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets_length_inclusive_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_hash_sets_length_inclusive_range; use std::collections::HashSet; use std::fmt::Debug; fn random_hash_sets_length_inclusive_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[HashSet], ) { let xs = random_hash_sets_length_inclusive_range(EXAMPLE_SEED, a, b, xs_gen); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets_length_inclusive_range() { random_hash_sets_length_inclusive_range_helper( 2, 3, &random_primitive_ints::, &[ hashset! {11, 85, 136}, hashset! {200, 235}, hashset! {134, 203, 223}, hashset! {38, 217, 235}, hashset! {162, 177}, hashset! {32, 166, 234}, hashset! {30, 90, 218}, hashset! {9, 106}, hashset! {151, 204, 216}, hashset! {97, 213, 253}, hashset! {78, 91}, hashset! {39, 175, 191}, hashset! {170, 232}, hashset! {2, 35, 233}, hashset! {22, 198, 217}, hashset! {17, 114}, hashset! {32, 173}, hashset! {65, 114}, hashset! {121, 173, 222}, hashset! {25, 144}, ], ); random_hash_sets_length_inclusive_range_helper( 2, 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ hashset! {0, 1, 5}, hashset! {1, 4}, hashset! {2, 4, 6}, hashset! {0, 1, 2}, hashset! {9, 13}, hashset! {0, 2, 7}, hashset! {4, 6, 7}, hashset! {0, 6}, hashset! {0, 1, 3}, hashset! {1, 2, 5}, hashset! {0, 1}, hashset! {0, 1, 4}, hashset! {0, 2}, hashset! {0, 2, 12}, hashset! {1, 2, 3}, hashset! {3, 9}, hashset! {0, 1}, hashset! {1, 2}, hashset! {0, 1, 11}, hashset! {1, 6}, ], ); random_hash_sets_length_inclusive_range_helper( 2, 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ hashset! {'c', 'q', 'v'}, hashset! {'e', 'i'}, hashset! {'g', 'p', 's'}, hashset! {'m', 'n', 't'}, hashset! {'o', 'z'}, hashset! {'f', 'k', 'm'}, hashset! {'q', 'u', 'y'}, hashset! {'k', 'x'}, hashset! {'h', 'n', 'u'}, hashset! {'a', 'j', 'n'}, hashset! {'w', 'z'}, hashset! {'b', 'l', 'w'}, hashset! {'l', 'u'}, hashset! {'e', 'l', 'n'}, hashset! {'k', 'u', 'v'}, hashset! {'c', 'h'}, hashset! {'i', 'y'}, hashset! {'m', 'r'}, hashset! {'m', 's', 'y'}, hashset! {'e', 'l'}, ], ); } #[test] #[should_panic] fn random_hash_sets_length_inclusive_range_fail() { random_hash_sets_length_inclusive_range(EXAMPLE_SEED, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets_length_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_hash_sets_length_range; use std::collections::HashSet; use std::fmt::Debug; fn random_hash_sets_length_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[HashSet], ) { let xs = random_hash_sets_length_range(EXAMPLE_SEED, a, b, xs_gen); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets_length_range() { random_hash_sets_length_range_helper( 2, 4, &random_primitive_ints::, &[ hashset! {11, 85, 136}, hashset! {200, 235}, hashset! {134, 203, 223}, hashset! {38, 217, 235}, hashset! {162, 177}, hashset! {32, 166, 234}, hashset! {30, 90, 218}, hashset! {9, 106}, hashset! {151, 204, 216}, hashset! {97, 213, 253}, hashset! {78, 91}, hashset! {39, 175, 191}, hashset! {170, 232}, hashset! {2, 35, 233}, hashset! {22, 198, 217}, hashset! {17, 114}, hashset! {32, 173}, hashset! {65, 114}, hashset! {121, 173, 222}, hashset! {25, 144}, ], ); random_hash_sets_length_range_helper( 2, 4, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ hashset! {0, 1, 5}, hashset! {1, 4}, hashset! {2, 4, 6}, hashset! {0, 1, 2}, hashset! {9, 13}, hashset! {0, 2, 7}, hashset! {4, 6, 7}, hashset! {0, 6}, hashset! {0, 1, 3}, hashset! {1, 2, 5}, hashset! {0, 1}, hashset! {0, 1, 4}, hashset! {0, 2}, hashset! {0, 2, 12}, hashset! {1, 2, 3}, hashset! {3, 9}, hashset! {0, 1}, hashset! {1, 2}, hashset! {0, 1, 11}, hashset! {1, 6}, ], ); random_hash_sets_length_range_helper( 2, 4, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ hashset! {'c', 'q', 'v'}, hashset! {'e', 'i'}, hashset! {'g', 'p', 's'}, hashset! {'m', 'n', 't'}, hashset! {'o', 'z'}, hashset! {'f', 'k', 'm'}, hashset! {'q', 'u', 'y'}, hashset! {'k', 'x'}, hashset! {'h', 'n', 'u'}, hashset! {'a', 'j', 'n'}, hashset! {'w', 'z'}, hashset! {'b', 'l', 'w'}, hashset! {'l', 'u'}, hashset! {'e', 'l', 'n'}, hashset! {'k', 'u', 'v'}, hashset! {'c', 'h'}, hashset! {'i', 'y'}, hashset! {'m', 'r'}, hashset! {'m', 's', 'y'}, hashset! {'e', 'l'}, ], ); } #[test] #[should_panic] fn random_hash_sets_length_range_fail() { random_hash_sets_length_range(EXAMPLE_SEED, 2, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/sets/random/random_hash_sets_min_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::sets::random::random_hash_sets_min_length; use std::collections::HashSet; use std::fmt::Debug; fn random_hash_sets_min_length_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[HashSet], ) { let xs = random_hash_sets_min_length( EXAMPLE_SEED, min_length, xs_gen, mean_length_numerator, mean_length_denominator, ); let values = xs.take(20).collect_vec(); assert_eq!(values.as_slice(), expected_values); } #[test] fn test_random_hash_sets_min_length() { random_hash_sets_min_length_helper( 0, &random_primitive_ints::, 4, 1, &[ hashset! {}, hashset! {11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235}, hashset! {30, 90, 218, 234}, hashset! {9, 106, 204, 216}, hashset! {151}, hashset! {}, hashset! {78, 91, 97, 213, 253}, hashset! {39, 191}, hashset! {170, 175, 232, 233}, hashset! {}, hashset! {2, 22, 35, 114, 198, 217}, hashset! {}, hashset! {}, hashset! {17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222}, hashset! {52, 69, 73, 91, 115, 137, 153, 178}, hashset! {}, hashset! {34, 95, 112}, hashset! {}, hashset! {106, 130, 167, 168, 197}, hashset! {86, 101, 122, 150, 172, 177, 207, 218, 221}, ], ); random_hash_sets_min_length_helper( 3, &random_primitive_ints::, 7, 1, &[ hashset! {11, 85, 136}, hashset! { 9, 30, 32, 38, 90, 106, 134, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235 }, hashset! {78, 97, 151, 204, 213, 216, 253}, hashset! {39, 91, 170, 175, 191, 232, 233}, hashset! {2, 22, 35, 217}, hashset! {17, 114, 198}, hashset! {25, 32, 65, 114, 121, 144, 173, 222}, hashset! {52, 73, 79, 115, 148}, hashset! {34, 69, 91, 112, 137, 153, 178}, hashset! {95, 106, 167}, hashset! {86, 122, 130, 150, 168, 172, 177, 197, 207}, hashset! {101, 218, 221}, hashset! {9, 74, 115}, hashset! {40, 48, 52, 97, 104, 109, 123, 133, 159, 196, 201, 235, 247, 250}, hashset! {7, 11, 24, 43, 68, 103, 112, 157, 190, 216, 217}, hashset! {84, 135, 211}, hashset! {29, 55, 65, 89, 191, 206}, hashset! {9, 51, 79}, hashset! {3, 20, 22, 34, 62, 114, 118, 148}, hashset! {23, 32, 47, 50, 120, 166, 176, 177, 194, 204, 238, 248}, ], ); random_hash_sets_min_length_helper( 0, &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ hashset! {}, hashset! {1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141}, hashset! {0, 1, 10, 99}, hashset! {2, 12, 36, 77}, hashset! {1}, hashset! {}, hashset! {1, 5, 9, 19, 103}, hashset! {6, 7}, hashset! {15, 18, 51, 159}, hashset! {}, hashset! {2, 26, 40, 52, 64, 75}, hashset! {}, hashset! {}, hashset! {3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67}, hashset! {1, 14, 16, 24, 29, 41, 47, 52}, hashset! {}, hashset! {11, 13, 62}, hashset! {}, hashset! {3, 14, 42, 47, 109}, hashset! {5, 13, 16, 25, 37, 41, 42, 86, 96}, ], ); random_hash_sets_min_length_helper( 3, &|seed| geometric_random_unsigneds::(seed, 32, 1), 7, 1, &[ hashset! {1, 14, 42}, hashset! {0, 1, 9, 10, 12, 16, 17, 19, 21, 36, 41, 68, 77, 79, 99, 124, 141}, hashset! {1, 2, 5, 9, 12, 19, 103}, hashset! {6, 7, 15, 18, 51, 52, 159}, hashset! {2, 40, 64, 75}, hashset! {26, 34, 67}, hashset! {4, 5, 7, 30, 31, 43, 49, 51}, hashset! {3, 14, 16, 24, 47}, hashset! {1, 11, 13, 29, 41, 52, 62}, hashset! {3, 47, 109}, hashset! {13, 14, 16, 25, 37, 41, 42, 86, 96}, hashset! {5, 20, 42}, hashset! {2, 74, 82}, hashset! {3, 6, 7, 11, 17, 20, 36, 45, 56, 66, 76, 80, 89, 127}, hashset! {1, 6, 10, 13, 19, 23, 25, 32, 41, 43, 97}, hashset! {7, 41, 134}, hashset! {9, 10, 25, 26, 47, 105}, hashset! {68, 94, 109}, hashset! {1, 3, 9, 13, 28, 43, 44, 84}, hashset! {0, 4, 5, 6, 7, 13, 31, 32, 37, 42, 50, 75}, ], ); random_hash_sets_min_length_helper( 0, &random_primitive_ints::, 1, 4, &[ hashset! {}, hashset! {}, hashset! {85}, hashset! {11}, hashset! {136, 200}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, hashset! {134, 235}, hashset! {203}, hashset! {}, hashset! {38, 223}, hashset! {}, hashset! {}, hashset! {}, hashset! {}, ], ); random_hash_sets_min_length_helper( 3, &random_primitive_ints::, 13, 4, &[ hashset! {11, 85, 136}, hashset! {134, 200, 235}, hashset! {38, 203, 223, 235}, hashset! {32, 162, 177, 217}, hashset! {30, 90, 166, 218, 234}, hashset! {9, 106, 216}, hashset! {151, 204, 213}, hashset! {78, 97, 253}, hashset! {39, 91, 191}, hashset! {170, 175, 232}, hashset! {2, 35, 233}, hashset! {22, 198, 217}, hashset! {17, 32, 65, 114, 173}, hashset! {25, 121, 173, 222}, hashset! {79, 144, 148}, hashset! {52, 69, 73, 115, 137}, hashset! {91, 153, 178}, hashset! {34, 95, 112}, hashset! {106, 167, 197}, hashset! {122, 130, 168}, ], ); random_hash_sets_min_length_helper( 0, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ hashset! {}, hashset! {'g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'}, hashset! {'ª', '´', 'Ã', 'ä'}, hashset! {'½', 'Á', 'Ï', 'ý'}, hashset! {'j'}, hashset! {}, hashset! {'u', '½', 'Â', 'Ñ', 'ï'}, hashset! {'x', 'õ'}, hashset! {'¡', 'Â', 'ù', 'Ċ'}, hashset! {}, hashset! {'b', 'r', 's', '¬', 'Â', 'Ñ'}, hashset! {}, hashset! {}, hashset! {'j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'}, hashset! {'b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'}, hashset! {}, hashset! {'«', '¹', 'Î'}, hashset! {}, hashset! {'~', '¯', '´', 'Ý', 'â'}, hashset! {'g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'}, ], ); random_hash_sets_min_length_helper( 3, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 7, 1, &[ hashset! {'g', 'q', 'á'}, hashset! { 'g', 'ª', '³', '´', '»', '½', 'À', 'Á', 'Ã', 'È', 'Ï', 'â', 'ä', 'ì', 'ñ', 'Ā', 'ą', }, hashset! {'j', 'u', '½', 'Â', 'Ñ', 'ï', 'ý'}, hashset! {'x', '¡', '¬', 'Â', 'õ', 'ù', 'Ċ'}, hashset! {'b', 's', '¬', 'Ñ'}, hashset! {'n', 'r', 'Â'}, hashset! {'t', '¬', 'º', '¿', 'Ø', 'Þ', 'ô', 'ü'}, hashset! {'j', 'k', '±', 'Á', 'è'}, hashset! {'b', '«', '¹', 'Î', 'Ü', 'æ', 'ā'}, hashset! {'~', '´', 'Î'}, hashset! {'g', '¯', 'Î', 'Ý', 'Þ', 'â', 'æ', 'é', 'ö'}, hashset! {'¼', 'Ç', 'Ü'}, hashset! {'¡', '§', 'Ì'}, hashset! {'d', 'm', 'z', '{', '¨', '®', '±', '¼', 'Ë', 'Ü', 'ê', 'ì', 'ý', 'þ'}, hashset! {'x', 'ª', '½', 'À', 'Õ', 'ì', 'ï', 'û', 'ă', 'Ą', 'ċ'}, hashset! {'¢', '«', 'Ć'}, hashset! {'{', '¢', '½', 'È', 'ä', 'ÿ'}, hashset! {'Ë', 'Õ', 'ê'}, hashset! {'p', '¨', '°', 'º', 'Å', 'Ó', '×', 'ü'}, hashset! {'d', 'k', 'o', 'v', '¥', '±', 'Ä', 'È', 'Ê', 'ß', 'æ', 'Ć'}, ], ); } #[test] #[should_panic] fn random_hash_sets_min_length_fail_1() { random_hash_sets_min_length(EXAMPLE_SEED, 3, &random_primitive_ints::, 3, 1); } #[test] #[should_panic] fn random_hash_sets_min_length_fail_2() { random_hash_sets_min_length(EXAMPLE_SEED, 1, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_hash_sets_min_length_fail_3() { random_hash_sets_min_length( EXAMPLE_SEED, 0, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/slices/exhaustive_slice_permutations.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Factorial; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::slices::exhaustive_slice_permutations; fn exhaustive_slice_permutations_helper(cs: &str, out: &[&str]) { let cs = cs.chars().collect_vec(); let css: Vec = exhaustive_slice_permutations(&cs) .map(|ds| ds.into_iter().copied().collect()) .collect(); assert_eq!(css.len(), usize::factorial(u64::wrapping_from(cs.len()))); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_slice_permutations() { exhaustive_slice_permutations_helper("", &[""]); exhaustive_slice_permutations_helper("1", &["1"]); exhaustive_slice_permutations_helper("12", &["12", "21"]); exhaustive_slice_permutations_helper("123", &["123", "132", "213", "231", "312", "321"]); exhaustive_slice_permutations_helper( "1234", &[ "1234", "1243", "1324", "1342", "1423", "1432", "2134", "2143", "2314", "2341", "2413", "2431", "3124", "3142", "3214", "3241", "3412", "3421", "4123", "4132", "4213", "4231", "4312", "4321", ], ); exhaustive_slice_permutations_helper( "12345", &[ "12345", "12354", "12435", "12453", "12534", "12543", "13245", "13254", "13425", "13452", "13524", "13542", "14235", "14253", "14325", "14352", "14523", "14532", "15234", "15243", "15324", "15342", "15423", "15432", "21345", "21354", "21435", "21453", "21534", "21543", "23145", "23154", "23415", "23451", "23514", "23541", "24135", "24153", "24315", "24351", "24513", "24531", "25134", "25143", "25314", "25341", "25413", "25431", "31245", "31254", "31425", "31452", "31524", "31542", "32145", "32154", "32415", "32451", "32514", "32541", "34125", "34152", "34215", "34251", "34512", "34521", "35124", "35142", "35214", "35241", "35412", "35421", "41235", "41253", "41325", "41352", "41523", "41532", "42135", "42153", "42315", "42351", "42513", "42531", "43125", "43152", "43215", "43251", "43512", "43521", "45123", "45132", "45213", "45231", "45312", "45321", "51234", "51243", "51324", "51342", "51423", "51432", "52134", "52143", "52314", "52341", "52413", "52431", "53124", "53142", "53214", "53241", "53412", "53421", "54123", "54132", "54213", "54231", "54312", "54321", ], ); exhaustive_slice_permutations_helper( "abcd", &[ "abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac", "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca", "dcab", "dcba", ], ); } ================================================ FILE: malachite-base/tests/slices/min_repeating_len.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::min_repeating_len; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen, unsigned_vec_gen_var_4}; #[test] fn test_min_repeating_len() { let test = |xs: &[u32], out| { assert_eq!(min_repeating_len(xs), out); }; test(&[1, 2, 1, 2, 1, 2], 2); test(&[1, 2, 1, 2, 1, 3], 6); test(&[5, 5, 5], 1); test(&[100], 1); } #[test] #[should_panic] fn min_repeating_len_fail() { min_repeating_len::(&[]); } #[test] fn min_repeating_len_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen_var_4::().test_properties_with_config(&config, |xs| { let len = xs.len(); let repeating_len = min_repeating_len(&xs); assert_ne!(repeating_len, 0); assert!(len.divisible_by(repeating_len)); let rep = &xs[..repeating_len]; assert_eq!(min_repeating_len(rep), repeating_len); assert!(Iterator::eq(rep.iter().cycle().take(len), xs.iter())); }); unsigned_gen::().test_properties_with_config(&config, |x| { assert_eq!(min_repeating_len(&[x]), 1); }); } ================================================ FILE: malachite-base/tests/slices/random_slice_permutations.rs ================================================ // Copyright © 2026 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::random::EXAMPLE_SEED; use malachite_base::slices::random_slice_permutations; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; fn random_slice_permutations_helper( cs: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let cs = cs.chars().collect_vec(); let ss = random_slice_permutations(EXAMPLE_SEED, &cs).map(|ds| ds.into_iter().copied().collect()); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_slice_permutations() { random_slice_permutations_helper("", &[""; 20], &[("", 1000000)], ("", None)); random_slice_permutations_helper("a", &["a"; 20], &[("a", 1000000)], ("a", None)); random_slice_permutations_helper( "ab", &[ "ba", "ab", "ab", "ab", "ab", "ba", "ba", "ba", "ba", "ab", "ba", "ab", "ab", "ba", "ab", "ab", "ba", "ab", "ba", "ab", ], &[("ba", 500291), ("ab", 499709)], ("ba", None), ); random_slice_permutations_helper( "abc", &[ "bac", "cba", "cba", "cba", "cba", "acb", "acb", "bca", "acb", "bac", "abc", "bac", "bac", "acb", "cba", "abc", "bca", "cab", "acb", "bac", ], &[ ("abc", 167957), ("bac", 167073), ("cba", 166362), ("acb", 166331), ("cab", 166166), ("bca", 166111), ], ("bac", None), ); random_slice_permutations_helper( "abcd", &[ "dacb", "cbad", "cdab", "cbad", "cdab", "bcda", "bcda", "acbd", "bcda", "dbca", "bdac", "dbac", "dbca", "bcad", "cadb", "dacb", "acbd", "dbac", "bdca", "abdc", ], &[ ("dbca", 41992), ("bcda", 41855), ("cdab", 41827), ("dcab", 41818), ("abcd", 41809), ("badc", 41804), ("cadb", 41803), ("adbc", 41763), ("cbad", 41706), ("dbac", 41697), ], ("bdca", None), ); random_slice_permutations_helper( "abcdefghij", &[ "daiehfcbjg", "bhagejicdf", "fdaibchgje", "bicdfhgaej", "bdfihjagec", "chdjbafeig", "cgajbfdieh", "jecbhafgid", "aedjgchfbi", "hacjiefdgb", "ahgdfcbije", "cibdehfjag", "fgdebchjai", "gieajbdfch", "deagfjihcb", "hjfgdbacie", "jdghacbfie", "cebaihjfdg", "jgdbchfeai", "cjahbegdif", ], &[ ("afdhbciejg", 5), ("afegijbcdh", 5), ("afgcedhjbi", 5), ("agbijhcfde", 5), ("ahejcigbfd", 5), ("ahjcgfdebi", 5), ("aihecgdfbj", 5), ("ajfghdcbei", 5), ("badicjhgfe", 5), ("bfdacehijg", 5), ], ("ejicadfgbh", Some("ejicadgbfh")), ); } ================================================ FILE: malachite-base/tests/slices/random_values_from_slice.rs ================================================ // Copyright © 2026 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 malachite_base::nevers::Never; use malachite_base::random::EXAMPLE_SEED; use malachite_base::slices::random_values_from_slice; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; #[test] fn test_random_values_from_slice() { let test = |slice: &[u32], values: &[u32], common_values: &[(u32, usize)], actual_median: (u32, Option)| { let xs = random_values_from_slice(EXAMPLE_SEED, slice).cloned(); let expected_values = xs.clone().take(20).collect_vec(); let expected_common_values = common_values_map_debug(1000000, 10, xs.clone()); let expected_median = median(xs.take(1000000)); assert_eq!( ( expected_values.as_slice(), expected_common_values.as_slice(), expected_median ), (values, common_values, actual_median) ); }; test(&[5], &[5; 20], &[(5, 1000000)], (5, None)); test( &[0, 1], &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0], &[(1, 500473), (0, 499527)], (1, None), ); test( &[1, 1, 1, 10], &[ 1, 1, 10, 1, 10, 10, 1, 10, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1, 1, 10, ], &[(1, 749985), (10, 250015)], (1, None), ); test( &[2, 3, 5, 7, 11], &[ 3, 7, 3, 5, 11, 3, 5, 11, 2, 2, 5, 5, 2, 11, 2, 11, 5, 11, 5, 3, ], &[ (2, 200420), (7, 200369), (11, 200347), (5, 199589), (3, 199275), ], (5, None), ); } #[test] #[should_panic] fn random_values_from_slice_fail() { random_values_from_slice::(EXAMPLE_SEED, &[]); } ================================================ FILE: malachite-base/tests/slices/slice_leading_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::{slice_leading_zeros, slice_test_zero, slice_trailing_zeros}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; #[test] fn test_slice_leading_zeros() { let test = |xs: &[u32], out| { assert_eq!(slice_leading_zeros(xs), out); }; test(&[], 0); test(&[0], 1); test(&[0, 0, 0], 3); test(&[123], 0); test(&[123, 0], 0); test(&[0, 123, 0, 0, 0], 1); test(&[1, 2, 3], 0); test(&[0, 0, 0, 1, 2, 3], 3); } #[test] fn slice_leading_zeros_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |xs| { let leading_zeros = slice_leading_zeros(&xs); assert!(leading_zeros <= xs.len()); assert_eq!(leading_zeros == xs.len(), slice_test_zero(&xs)); let mut new_xs = xs; new_xs.reverse(); assert_eq!(slice_trailing_zeros(&new_xs), leading_zeros); }); } ================================================ FILE: malachite-base/tests/slices/slice_move_left.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_move_left; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_vec_gen, unsigned_vec_unsigned_pair_gen_var_1, }; use malachite_base::test_util::slices::slice_move_left_naive; #[test] fn test_slice_move_left() { let test = |xs_in: &[u32], amount, xs_out: &[u32]| { let mut xs = xs_in.to_vec(); slice_move_left(&mut xs, amount); assert_eq!(xs, xs_out); let mut xs = xs_in.to_vec(); slice_move_left_naive::(&mut xs, amount); assert_eq!(xs, xs_out); }; test(&[], 0, &[]); test(&[1], 0, &[1]); test(&[1], 1, &[1]); test(&[1, 2, 3], 0, &[1, 2, 3]); test(&[1, 2, 3], 1, &[2, 3, 3]); test(&[1, 2, 3], 2, &[3, 2, 3]); test(&[1, 2, 3], 3, &[1, 2, 3]); test(&[1, 2, 3, 4, 5, 6], 2, &[3, 4, 5, 6, 5, 6]); } #[test] #[should_panic] fn slice_move_left_fail_1() { let xs = &mut []; slice_move_left::(xs, 1); } #[test] #[should_panic] fn slice_move_left_fail_2() { let xs = &mut [1, 2, 3]; slice_move_left::(xs, 4); } #[test] fn slice_move_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_unsigned_pair_gen_var_1::().test_properties_with_config( &config, |(mut xs, amount)| { let old_xs = xs.clone(); slice_move_left(&mut xs, amount); let boundary = old_xs.len() - amount; let (xs_lo, xs_hi) = xs.split_at(boundary); assert_eq!(xs_lo, &old_xs[amount..]); assert_eq!(xs_hi, &old_xs[boundary..]); let mut xs_alt = old_xs; slice_move_left_naive(&mut xs_alt, amount); assert_eq!(xs_alt, xs); }, ); unsigned_vec_gen::().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); slice_move_left(&mut xs, 0); assert_eq!(xs, old_xs); let mut xs = old_xs.clone(); slice_move_left(&mut xs, old_xs.len()); assert_eq!(xs, old_xs); }); } ================================================ FILE: malachite-base/tests/slices/slice_set_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::{slice_set_zero, slice_test_zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; #[test] fn test_slice_set_zero() { let test = |xs: &[u32], out: &[u32]| { let mut mut_xs = xs.to_vec(); slice_set_zero(&mut mut_xs); assert_eq!(mut_xs, out); }; test(&[], &[]); test(&[0], &[0]); test(&[0, 0, 0], &[0, 0, 0]); test(&[123], &[0]); test(&[123, 0], &[0, 0]); test(&[0, 123, 0, 0, 0], &[0, 0, 0, 0, 0]); } #[test] fn slice_set_zero_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); slice_set_zero(&mut xs); assert_eq!(old_xs.len(), xs.len()); assert!(slice_test_zero(&xs)); }); } ================================================ FILE: malachite-base/tests/slices/slice_test_zero.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::{slice_set_zero, slice_test_zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; #[test] fn test_slice_test_zero() { let test = |xs: &[u32], out| { assert_eq!(slice_test_zero(xs), out); }; test(&[], true); test(&[0], true); test(&[0, 0, 0], true); test(&[123], false); test(&[123, 0], false); test(&[0, 123, 0, 0, 0], false); } #[test] fn slice_test_zero_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |xs| { let xs_are_zero = slice_test_zero(&xs); let mut new_xs = xs.clone(); slice_set_zero(&mut new_xs); assert_eq!(xs == new_xs, xs_are_zero); }); } ================================================ FILE: malachite-base/tests/slices/slice_trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::{slice_leading_zeros, slice_test_zero, slice_trailing_zeros}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; #[test] fn test_slice_trailing_zeros() { let test = |xs: &[u32], out| { assert_eq!(slice_trailing_zeros(xs), out); }; test(&[], 0); test(&[0], 1); test(&[0, 0, 0], 3); test(&[123], 0); test(&[123, 0], 1); test(&[0, 123, 0, 0, 0], 3); test(&[1, 2, 3], 0); test(&[1, 2, 3, 0, 0, 0], 3); } #[test] fn slice_trailing_zeros_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_gen::().test_properties_with_config(&config, |xs| { let trailing_zeros = slice_trailing_zeros(&xs); assert!(trailing_zeros <= xs.len()); assert_eq!(trailing_zeros == xs.len(), slice_test_zero(&xs)); let mut new_xs = xs; new_xs.reverse(); assert_eq!(slice_leading_zeros(&new_xs), trailing_zeros); }); } ================================================ FILE: malachite-base/tests/slices/split_into_chunks.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_set_zero; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_unsigned_unsigned_triple_gen_var_2; #[test] fn test_split_into_chunks() { let xs = &[0, 1, 2, 3, 4, 5, 6, 7]; split_into_chunks!(xs, 3, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[0, 1, 2]); assert_eq!(xs_2, &[3, 4, 5]); assert_eq!(xs_3, &[6, 7]); split_into_chunks!(xs, 3, [xs_1], xs_2); assert_eq!(xs_1, &[0, 1, 2]); assert_eq!(xs_2, &[3, 4, 5, 6, 7]); split_into_chunks!(xs, 1, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[0]); assert_eq!(xs_2, &[1]); assert_eq!(xs_3, &[2, 3, 4, 5, 6, 7]); split_into_chunks!(xs, 0, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[]); assert_eq!(xs_2, &[]); assert_eq!(xs_3, &[0, 1, 2, 3, 4, 5, 6, 7]); split_into_chunks!(xs, 5, [], xs_1); assert_eq!(xs_1, &[0, 1, 2, 3, 4, 5, 6, 7]); } #[test] #[should_panic] fn split_into_chunks_fail() { let xs = &[0, 1, 2, 3, 4, 5, 6, 7]; split_into_chunks!(xs, 5, [_xs_1, _xs_2], _xs_3); } #[test] fn test_split_into_chunks_mut() { let xs = &mut [0, 1, 2, 3, 4, 5, 6, 7]; split_into_chunks_mut!(xs, 3, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[0, 1, 2]); assert_eq!(xs_2, &[3, 4, 5]); assert_eq!(xs_3, &[6, 7]); split_into_chunks_mut!(xs, 3, [xs_1], xs_2); assert_eq!(xs_1, &[0, 1, 2]); assert_eq!(xs_2, &[3, 4, 5, 6, 7]); split_into_chunks_mut!(xs, 1, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[0]); assert_eq!(xs_2, &[1]); assert_eq!(xs_3, &[2, 3, 4, 5, 6, 7]); split_into_chunks_mut!(xs, 0, [xs_1, xs_2], xs_3); assert_eq!(xs_1, &[]); assert_eq!(xs_2, &[]); assert_eq!(xs_3, &[0, 1, 2, 3, 4, 5, 6, 7]); split_into_chunks_mut!(xs, 5, [], xs_1); assert_eq!(xs_1, &[0, 1, 2, 3, 4, 5, 6, 7]); split_into_chunks_mut!(xs, 3, [_xs_1, xs_2], _xs_3); slice_set_zero(xs_2); assert_eq!(xs, &[0, 1, 2, 0, 0, 0, 6, 7]); } #[test] #[should_panic] fn split_into_chunks_mut_fail() { let xs = &mut [0, 1, 2, 3, 4, 5, 6, 7]; split_into_chunks_mut!(xs, 5, [_xs_1, _xs_2], _xs_3); } macro_rules! split_into_chunks_helper { ($xs: expr, $len: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {{ split_into_chunks!($xs, $len, [$($xs_i),*], $xs_last); $( assert_eq!($xs_i.len(), $len); )* assert_eq!($xs_last.len(), $xs.len() - ($n - 1) * $len); let mut xs_alt = Vec::with_capacity($xs.len()); $( xs_alt.extend($xs_i.iter().cloned()); )* xs_alt.extend($xs_last.iter().cloned()); assert_eq!(xs_alt, $xs); }} } #[test] fn split_into_chunks_properties() { let mut config = GenConfig::new(); config.insert("small_unsigned_mean_n", 8); config.insert("small_unsigned_mean_d", 1); config.insert("mean_stripe_n", u8::WIDTH << 1); config.insert("mean_stripe_d", 1); unsigned_vec_unsigned_unsigned_triple_gen_var_2::().test_properties_with_config( &config, |(xs, len, n)| match n { 0 => split_into_chunks_helper!(xs, len, 1, [], xs_1), 1 => split_into_chunks_helper!(xs, len, 2, [xs_1], xs_2), 2 => split_into_chunks_helper!(xs, len, 3, [xs_1, xs_2], xs_3), 3 => { split_into_chunks_helper!(xs, len, 4, [xs_1, xs_2, xs_3], xs_4); } 4 => { split_into_chunks_helper!(xs, len, 5, [xs_1, xs_2, xs_3, xs_4], xs_5); } 5 => split_into_chunks_helper!(xs, len, 6, [xs_1, xs_2, xs_3, xs_4, xs_5], xs_6), 6 => split_into_chunks_helper!(xs, len, 7, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6], xs_7), 7 => split_into_chunks_helper!( xs, len, 8, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6, xs_7], xs_8 ), _ => {} }, ); } macro_rules! split_into_chunks_mut_helper { ($xs: expr, $len: expr, $n: expr, [$($xs_i: ident),*], $xs_last: ident) => {{ let xs_len = $xs.len(); split_into_chunks_mut!($xs, $len, [$($xs_i),*], $xs_last); $( assert_eq!($xs_i.len(), $len); )* assert_eq!($xs_last.len(), xs_len - ($n - 1) * $len); let mut xs_alt = Vec::with_capacity(xs_len); $( xs_alt.extend($xs_i.iter().cloned()); )* xs_alt.extend($xs_last.iter().cloned()); assert_eq!(xs_alt, $xs); }} } #[test] fn split_into_chunks_mut_properties() { let mut config = GenConfig::new(); config.insert("small_unsigned_mean_n", 8); config.insert("small_unsigned_mean_d", 1); config.insert("mean_stripe_n", u8::WIDTH << 1); config.insert("mean_stripe_d", 1); unsigned_vec_unsigned_unsigned_triple_gen_var_2::().test_properties_with_config( &config, |(mut xs, len, n)| match n { 0 => split_into_chunks_mut_helper!(xs, len, 1, [], xs_1), 1 => split_into_chunks_mut_helper!(xs, len, 2, [xs_1], xs_2), 2 => split_into_chunks_mut_helper!(xs, len, 3, [xs_1, xs_2], xs_3), 3 => { split_into_chunks_mut_helper!(xs, len, 4, [xs_1, xs_2, xs_3], xs_4); } 4 => { split_into_chunks_mut_helper!(xs, len, 5, [xs_1, xs_2, xs_3, xs_4], xs_5); } 5 => split_into_chunks_mut_helper!(xs, len, 6, [xs_1, xs_2, xs_3, xs_4, xs_5], xs_6), 6 => { split_into_chunks_mut_helper!( xs, len, 7, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6], xs_7 ); } 7 => split_into_chunks_mut_helper!( xs, len, 8, [xs_1, xs_2, xs_3, xs_4, xs_5, xs_6, xs_7], xs_8 ), _ => {} }, ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/exhaustive_fixed_length_strings.rs ================================================ // Copyright © 2026 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::strings::exhaustive::exhaustive_fixed_length_strings; fn exhaustive_fixed_length_strings_helper(len: u64, out: &[&str]) { let css = exhaustive_fixed_length_strings(len).take(20).collect_vec(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_fixed_length_strings() { exhaustive_fixed_length_strings_helper(0, &[""]); exhaustive_fixed_length_strings_helper( 1, &[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", ], ); exhaustive_fixed_length_strings_helper( 2, &[ "aa", "ab", "ba", "bb", "ac", "ad", "bc", "bd", "ca", "cb", "da", "db", "cc", "cd", "dc", "dd", "ae", "af", "be", "bf", ], ); exhaustive_fixed_length_strings_helper( 3, &[ "aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb", "aac", "aad", "abc", "abd", "bac", "bad", "bbc", "bbd", "aca", "acb", "ada", "adb", ], ); exhaustive_fixed_length_strings_helper( 10, &[ "aaaaaaaaaa", "aaaaaaaaab", "aaaaaaaaba", "aaaaaaaabb", "aaaaaaabaa", "aaaaaaabab", "aaaaaaabba", "aaaaaaabbb", "aaaaaabaaa", "aaaaaabaab", "aaaaaababa", "aaaaaababb", "aaaaaabbaa", "aaaaaabbab", "aaaaaabbba", "aaaaaabbbb", "aaaaabaaaa", "aaaaabaaab", "aaaaabaaba", "aaaaabaabb", ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/exhaustive_fixed_length_strings_using_chars.rs ================================================ // Copyright © 2026 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::strings::exhaustive::exhaustive_fixed_length_strings_using_chars; use std::iter::{empty, once}; fn exhaustive_fixed_length_strings_using_chars_helper>( len: u64, cs: I, out: &[&str], ) { let css = exhaustive_fixed_length_strings_using_chars(len, cs) .take(20) .collect_vec(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_fixed_length_strings_using_chars() { exhaustive_fixed_length_strings_using_chars_helper(0, empty(), &[""]); exhaustive_fixed_length_strings_using_chars_helper(1, empty(), &[]); exhaustive_fixed_length_strings_using_chars_helper(0, once('q'), &[""]); exhaustive_fixed_length_strings_using_chars_helper(1, once('q'), &["q"]); exhaustive_fixed_length_strings_using_chars_helper(2, once('q'), &["qq"]); exhaustive_fixed_length_strings_using_chars_helper(3, once('q'), &["qqq"]); exhaustive_fixed_length_strings_using_chars_helper(10, once('q'), &["qqqqqqqqqq"]); exhaustive_fixed_length_strings_using_chars_helper(0, ['x', 'y'].iter().copied(), &[""]); exhaustive_fixed_length_strings_using_chars_helper(1, ['x', 'y'].iter().copied(), &["x", "y"]); exhaustive_fixed_length_strings_using_chars_helper( 2, ['x', 'y'].iter().copied(), &["xx", "xy", "yx", "yy"], ); exhaustive_fixed_length_strings_using_chars_helper( 3, ['x', 'y'].iter().copied(), &["xxx", "xxy", "xyx", "xyy", "yxx", "yxy", "yyx", "yyy"], ); exhaustive_fixed_length_strings_using_chars_helper( 10, ['x', 'y'].iter().copied(), &[ "xxxxxxxxxx", "xxxxxxxxxy", "xxxxxxxxyx", "xxxxxxxxyy", "xxxxxxxyxx", "xxxxxxxyxy", "xxxxxxxyyx", "xxxxxxxyyy", "xxxxxxyxxx", "xxxxxxyxxy", "xxxxxxyxyx", "xxxxxxyxyy", "xxxxxxyyxx", "xxxxxxyyxy", "xxxxxxyyyx", "xxxxxxyyyy", "xxxxxyxxxx", "xxxxxyxxxy", "xxxxxyxxyx", "xxxxxyxxyy", ], ); exhaustive_fixed_length_strings_using_chars_helper(0, ['c', 'a', 't'].iter().copied(), &[""]); exhaustive_fixed_length_strings_using_chars_helper( 1, ['c', 'a', 't'].iter().copied(), &["c", "a", "t"], ); exhaustive_fixed_length_strings_using_chars_helper( 2, ['c', 'a', 't'].iter().copied(), &["cc", "ca", "ac", "aa", "ct", "at", "tc", "ta", "tt"], ); exhaustive_fixed_length_strings_using_chars_helper( 3, ['c', 'a', 't'].iter().copied(), &[ "ccc", "cca", "cac", "caa", "acc", "aca", "aac", "aaa", "cct", "cat", "act", "aat", "ctc", "cta", "atc", "ata", "ctt", "att", "tcc", "tca", ], ); exhaustive_fixed_length_strings_using_chars_helper( 10, ['c', 'a', 't'].iter().copied(), &[ "cccccccccc", "ccccccccca", "ccccccccac", "ccccccccaa", "cccccccacc", "cccccccaca", "cccccccaac", "cccccccaaa", "ccccccaccc", "ccccccacca", "ccccccacac", "ccccccacaa", "ccccccaacc", "ccccccaaca", "ccccccaaac", "ccccccaaaa", "cccccacccc", "cccccaccca", "cccccaccac", "cccccaccaa", ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/exhaustive_strings.rs ================================================ // Copyright © 2026 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::strings::exhaustive::exhaustive_strings; #[test] fn test_exhaustive_strings() { let ss = exhaustive_strings().take(20).collect_vec(); assert_eq!( ss.iter().map(String::as_str).collect_vec().as_slice(), &[ "", "a", "b", "aaa", "c", "aa", "d", "aaaa", "e", "ab", "f", "aab", "g", "ba", "h", "aaaaa", "i", "bb", "j", "aba" ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/exhaustive_strings_using_chars.rs ================================================ // Copyright © 2026 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::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::strings::exhaustive::exhaustive_strings_using_chars; use std::iter::{empty, once}; fn exhaustive_strings_using_chars_helper>(cs: I, out: &[&str]) { let ss = exhaustive_strings_using_chars(cs).take(20).collect_vec(); assert_eq!(ss.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_strings_using_chars() { exhaustive_strings_using_chars_helper(empty(), &[""]); exhaustive_strings_using_chars_helper( once('a'), &[ "", "a", "aa", "aaaa", "aaa", "aaaaa", "aaaaaa", "aaaaaaaaa", "aaaaaaa", "aaaaaaaa", "aaaaaaaaaa", "aaaaaaaaaaaa", "aaaaaaaaaaa", "aaaaaaaaaaaaa", "aaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaa", ], ); exhaustive_strings_using_chars_helper( "ab".chars(), &[ "", "a", "b", "aaa", "aa", "aab", "ab", "aaaaa", "ba", "aba", "bb", "aaaa", "abb", "aaab", "baa", "aaaaaaa", "bab", "aaba", "bba", "aaaab", ], ); exhaustive_strings_using_chars_helper( "xyz".chars(), &[ "", "x", "y", "xxx", "z", "xx", "xy", "xxxxx", "yx", "xxy", "yy", "xxxx", "xz", "xyx", "yz", "xxxxxx", "zx", "xyy", "zy", "xxxy", ], ); exhaustive_strings_using_chars_helper( exhaustive_ascii_chars(), &[ "", "a", "b", "aaa", "c", "aa", "d", "aaaa", "e", "ab", "f", "aab", "g", "ba", "h", "aaaaa", "i", "bb", "j", "aba", ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/lex_fixed_length_strings.rs ================================================ // Copyright © 2026 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::strings::exhaustive::lex_fixed_length_strings; fn lex_fixed_length_strings_helper(len: u64, out: &[&str]) { let css = lex_fixed_length_strings(len).take(20).collect_vec(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_lex_fixed_length_strings() { lex_fixed_length_strings_helper(0, &[""]); lex_fixed_length_strings_helper( 1, &[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", ], ); lex_fixed_length_strings_helper( 2, &[ "aa", "ab", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq", "ar", "as", "at", ], ); lex_fixed_length_strings_helper( 3, &[ "aaa", "aab", "aac", "aad", "aae", "aaf", "aag", "aah", "aai", "aaj", "aak", "aal", "aam", "aan", "aao", "aap", "aaq", "aar", "aas", "aat", ], ); lex_fixed_length_strings_helper( 10, &[ "aaaaaaaaaa", "aaaaaaaaab", "aaaaaaaaac", "aaaaaaaaad", "aaaaaaaaae", "aaaaaaaaaf", "aaaaaaaaag", "aaaaaaaaah", "aaaaaaaaai", "aaaaaaaaaj", "aaaaaaaaak", "aaaaaaaaal", "aaaaaaaaam", "aaaaaaaaan", "aaaaaaaaao", "aaaaaaaaap", "aaaaaaaaaq", "aaaaaaaaar", "aaaaaaaaas", "aaaaaaaaat", ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/lex_fixed_length_strings_using_chars.rs ================================================ // Copyright © 2026 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::strings::exhaustive::lex_fixed_length_strings_using_chars; use std::iter::{empty, once}; fn lex_fixed_length_strings_using_chars_helper>( len: u64, cs: I, out: &[&str], ) { let css = lex_fixed_length_strings_using_chars(len, cs) .take(20) .collect_vec(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_lex_fixed_length_strings_using_chars() { lex_fixed_length_strings_using_chars_helper(0, empty(), &[""]); lex_fixed_length_strings_using_chars_helper(1, empty(), &[]); lex_fixed_length_strings_using_chars_helper(0, once('q'), &[""]); lex_fixed_length_strings_using_chars_helper(1, once('q'), &["q"]); lex_fixed_length_strings_using_chars_helper(2, once('q'), &["qq"]); lex_fixed_length_strings_using_chars_helper(3, once('q'), &["qqq"]); lex_fixed_length_strings_using_chars_helper(10, once('q'), &["qqqqqqqqqq"]); lex_fixed_length_strings_using_chars_helper(0, ['x', 'y'].iter().copied(), &[""]); lex_fixed_length_strings_using_chars_helper(1, ['x', 'y'].iter().copied(), &["x", "y"]); lex_fixed_length_strings_using_chars_helper( 2, ['x', 'y'].iter().copied(), &["xx", "xy", "yx", "yy"], ); lex_fixed_length_strings_using_chars_helper( 3, ['x', 'y'].iter().copied(), &["xxx", "xxy", "xyx", "xyy", "yxx", "yxy", "yyx", "yyy"], ); lex_fixed_length_strings_using_chars_helper( 10, ['x', 'y'].iter().copied(), &[ "xxxxxxxxxx", "xxxxxxxxxy", "xxxxxxxxyx", "xxxxxxxxyy", "xxxxxxxyxx", "xxxxxxxyxy", "xxxxxxxyyx", "xxxxxxxyyy", "xxxxxxyxxx", "xxxxxxyxxy", "xxxxxxyxyx", "xxxxxxyxyy", "xxxxxxyyxx", "xxxxxxyyxy", "xxxxxxyyyx", "xxxxxxyyyy", "xxxxxyxxxx", "xxxxxyxxxy", "xxxxxyxxyx", "xxxxxyxxyy", ], ); lex_fixed_length_strings_using_chars_helper(0, ['c', 'a', 't'].iter().copied(), &[""]); lex_fixed_length_strings_using_chars_helper( 1, ['c', 'a', 't'].iter().copied(), &["c", "a", "t"], ); lex_fixed_length_strings_using_chars_helper( 2, ['c', 'a', 't'].iter().copied(), &["cc", "ca", "ct", "ac", "aa", "at", "tc", "ta", "tt"], ); lex_fixed_length_strings_using_chars_helper( 3, ['c', 'a', 't'].iter().copied(), &[ "ccc", "cca", "cct", "cac", "caa", "cat", "ctc", "cta", "ctt", "acc", "aca", "act", "aac", "aaa", "aat", "atc", "ata", "att", "tcc", "tca", ], ); lex_fixed_length_strings_using_chars_helper( 10, ['c', 'a', 't'].iter().copied(), &[ "cccccccccc", "ccccccccca", "ccccccccct", "ccccccccac", "ccccccccaa", "ccccccccat", "cccccccctc", "ccccccccta", "cccccccctt", "cccccccacc", "cccccccaca", "cccccccact", "cccccccaac", "cccccccaaa", "cccccccaat", "cccccccatc", "cccccccata", "cccccccatt", "ccccccctcc", "ccccccctca", ], ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/shortlex_strings.rs ================================================ // Copyright © 2026 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::strings::exhaustive::shortlex_strings; #[test] fn test_shortlex_strings() { let ss = shortlex_strings().take(20).collect_vec(); assert_eq!( ss.iter().map(String::as_str).collect_vec().as_slice(), &[ "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", ] ); } ================================================ FILE: malachite-base/tests/strings/exhaustive/shortlex_strings_using_chars.rs ================================================ // Copyright © 2026 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::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::strings::exhaustive::shortlex_strings_using_chars; use std::iter::{empty, once}; fn shortlex_strings_using_chars_helper>(cs: I, out: &[&str]) { let ss = shortlex_strings_using_chars(cs).take(20).collect_vec(); assert_eq!(ss.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_shortlex_strings_using_chars() { shortlex_strings_using_chars_helper(empty(), &[""]); shortlex_strings_using_chars_helper( once('a'), &[ "", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa", "aaaaaaa", "aaaaaaaa", "aaaaaaaaa", "aaaaaaaaaa", "aaaaaaaaaaa", "aaaaaaaaaaaa", "aaaaaaaaaaaaa", "aaaaaaaaaaaaaa", "aaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaa", ], ); shortlex_strings_using_chars_helper( "ab".chars(), &[ "", "a", "b", "aa", "ab", "ba", "bb", "aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb", "aaaa", "aaab", "aaba", "aabb", "abaa", ], ); shortlex_strings_using_chars_helper( "xyz".chars(), &[ "", "x", "y", "z", "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz", "xxx", "xxy", "xxz", "xyx", "xyy", "xyz", "xzx", ], ); shortlex_strings_using_chars_helper( exhaustive_ascii_chars(), &[ "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", ], ); } ================================================ FILE: malachite-base/tests/strings/random/random_fixed_length_strings.rs ================================================ // Copyright © 2026 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::random::EXAMPLE_SEED; use malachite_base::strings::random::random_fixed_length_strings; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; fn random_fixed_length_strings_helper( len: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let ss = random_fixed_length_strings(EXAMPLE_SEED, len); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_fixed_length_strings() { random_fixed_length_strings_helper(0, &[""; 20], &[("", 1000000)], ("", None)); random_fixed_length_strings_helper( 1, &[ "\u{5f771}", "\u{87234}", "\u{bcd36}", "\u{9e195}", "\u{5da07}", "\u{36553}", "\u{45028}", "\u{1cdfd}", "\u{d8530}", "\u{c7f2e}", "\u{ba4bc}", "\u{ff677}", "\u{a12e2}", "\u{d775c}", "\u{f827b}", "\u{bdf7a}", "簅", "\u{15aca}", "\u{4e5e2}", "\u{bb286}", ], &[ ("\u{1e21d}", 8), ("\u{bd934}", 8), ("\u{dc941}", 8), ("䄡", 7), ("霜", 7), ("\u{ee5a}", 7), ("𐊩", 7), ("\u{163a4}", 7), ("\u{1e7ff}", 7), ("𣡝", 7), ], ("\u{88629}", Some("\u{8862a}")), ); random_fixed_length_strings_helper( 2, &[ "\u{5f771}\u{87234}", "\u{bcd36}\u{9e195}", "\u{5da07}\u{36553}", "\u{45028}\u{1cdfd}", "\u{d8530}\u{c7f2e}", "\u{ba4bc}\u{ff677}", "\u{a12e2}\u{d775c}", "\u{f827b}\u{bdf7a}", "簅\u{15aca}", "\u{4e5e2}\u{bb286}", "\u{18eeb}\u{bac4f}", "\u{5b55a}\u{65709}", "\u{b2626}\u{31a93}", "\u{8757b}\u{b3524}", "\u{fcc17}\u{32c01}", "\u{aada8}\u{57e7c}", "\u{eb738}栨", "\u{51a21}\u{ef6af}", "\u{b9caa}\u{d5099}", "\u{e397f}\u{32518}", ], &[ ("\u{6}욵", 1), ("\u{19}此", 1), ("\u{1c}훶", 1), ("+쳭", 1), (">\u{f454}", 1), ("B韧", 1), ("¦×", 1), ("Ϊǔ", 1), ("ӚĐ", 1), ("ۥä", 1), ], ("\u{882fd}\u{b44d9}", Some("\u{882fe}\u{6d6a7}")), ); random_fixed_length_strings_helper( 3, &[ "\u{5f771}\u{87234}\u{bcd36}", "\u{9e195}\u{5da07}\u{36553}", "\u{45028}\u{1cdfd}\u{d8530}", "\u{c7f2e}\u{ba4bc}\u{ff677}", "\u{a12e2}\u{d775c}\u{f827b}", "\u{bdf7a}簅\u{15aca}", "\u{4e5e2}\u{bb286}\u{18eeb}", "\u{bac4f}\u{5b55a}\u{65709}", "\u{b2626}\u{31a93}\u{8757b}", "\u{b3524}\u{fcc17}\u{32c01}", "\u{aada8}\u{57e7c}\u{eb738}", "栨\u{51a21}\u{ef6af}", "\u{b9caa}\u{d5099}\u{e397f}", "\u{32518}\u{6952d}\u{93ad5}", "\u{65c6e}\u{dc7bd}\u{aec4c}", "\u{dd524}\u{c0bc1}\u{795d0}", "\u{dbb9d}\u{a50fb}紐", "\u{4effe}\u{794af}\u{1b5a0}", "\u{56be3}\u{78fc9}\u{5870a}", "\u{106f48}\u{dfffa}\u{3cc01}", ], &[ ("\u{19}此\u{2f2bd}", 1), ("(\u{6c2b8}\u{f70}", 1), ("+쳭\u{93ded}", 1), (",\u{e5cc2}\u{ea33}", 1), ("6\u{a341e}엕", 1), (">\u{f454}\u{5e168}", 1), ("G\u{47b77}䊹", 1), ("K\u{58609}\u{e08e}", 1), ("O┑\u{37d86}", 1), ("R\u{f41e}\u{41c45}", 1), ], ( "\u{884b7}\u{6ad70}\u{3d86d}", Some("\u{884b8}\u{10f66a}\u{da539}"), ), ); random_fixed_length_strings_helper( 10, &[ "\u{5f771}\u{87234}\u{bcd36}\u{9e195}\u{5da07}\u{36553}\u{45028}\u{1cdfd}\u{d8530}\ \u{c7f2e}", "\u{ba4bc}\u{ff677}\u{a12e2}\u{d775c}\u{f827b}\u{bdf7a}簅\u{15aca}\u{4e5e2}\u{bb286}", "\u{18eeb}\u{bac4f}\u{5b55a}\u{65709}\u{b2626}\u{31a93}\u{8757b}\u{b3524}\u{fcc17}\ \u{32c01}", "\u{aada8}\u{57e7c}\u{eb738}栨\u{51a21}\u{ef6af}\u{b9caa}\u{d5099}\u{e397f}\u{32518}", "\u{6952d}\u{93ad5}\u{65c6e}\u{dc7bd}\u{aec4c}\u{dd524}\u{c0bc1}\u{795d0}\u{dbb9d}\ \u{a50fb}", "紐\u{4effe}\u{794af}\u{1b5a0}\u{56be3}\u{78fc9}\u{5870a}\u{106f48}\u{dfffa}\u{3cc01}", "\u{91290}\u{4628e}\u{bee71}\u{70e90}\u{b48bb}\u{3a445}\u{10a645}𬆠\u{e59de}\u{61b5a}", "\u{f4783}\u{c5ab2}幔\u{fdb07}\u{abccb}\u{ba750}\u{88d5a}\u{a706e}\u{969a2}\u{1089e3}", "\u{102189}\u{5f066}\u{10ea66}\u{435bb}\u{bcbd6}\u{4bc59}𱆞\u{f50a0}\u{47bc1}\u{5fd98}", "\u{91a7a}\u{100a8d}\u{e0017}\u{9db06}\u{1ab04}\u{780f6}ㅚ\u{5fc0a}\u{fb714}\u{c62cd}", "\u{b22dc}\u{10364e}\u{ee477}\u{f0983}\u{b5c36}\u{41f7b}\u{bdf28}\u{b27f7}\u{94dc8}\ \u{73381}", "\u{34609}\u{52911}\u{e56bf}\u{100af4}\u{396ff}\u{1051a8}𬅑\u{815dc}\u{fd1e7}\u{e6e9c}", "攠\u{eceaa}\u{10029d}\u{5e236}\u{d963b}\u{bbb1a}\u{108b67}\u{e5bc3}\u{97108}𢔱", "\u{9f166}\u{dedb4}\u{52752}\u{45bf5}\u{86d73}\u{ff2fd}쫵\u{78f74}\u{93bc0}\u{c308f}", "\u{e8b6}\u{89619}\u{1cdf9}\u{b9c86}\u{9f375}\u{c2487}\u{e1c3e}\u{f6e29}\u{79cc5}𬑎", "\u{9a803}\u{bf22e}\u{7e88e}\u{c50e8}\u{58c32}\u{79248}𰥦\u{b238b}\u{104b92}\u{8cc78}", "\u{eecc5}𢇡\u{e1fb6}\u{625ab}\u{a1988}䮨\u{bbaa5}\u{143be}\u{a12d4}\u{1028e1}", "\u{1c105}\u{9493f}\u{efa70}\u{13487}紋\u{b1948}\u{89052}\u{8c3cb}\u{b82d2}\u{729c3}", "\u{10c5ba}\u{dec07}𰢫\u{d277f}\u{3e5dc}\u{52431}\u{4867e}\u{75774}𪲨\u{b865a}", "\u{105191}\u{93891}\u{c4975}\u{c2f58}\u{d387c}\u{157dd}\u{77a83}\u{d6eec}\u{b2581}\ \u{9bb09}", ], &[ ("崕浆\u{3da8f}뽑\u{d3fa5}\u{3139e}X\u{48918}\u{108376}♟", 1), ("馑霸\u{fdd49}\u{d2b16}튞ଓ儳輋韨\u{be78f}", 1), ("𨟿\u{a025e}\u{4d531}席ےᥒ\"𤭉\u{b30a9}\u{988d4}", 1), ( "\u{c6771}\u{c979e}᳇\u{f4e2}能Ŷ\u{474f6}\u{f872}窚\u{6ad4b}", 1, ), ("+쳭\u{93ded}\u{84fa9}㱆\u{b3aac}곖𦸌\u{593c4}\u{57c2f}", 1), ( "w\u{6bb08}\u{e8b68}\u{f961c}\u{c362e}\u{2e6b}\u{95326}\u{7ff5b}受\u{f715}", 1, ), ( "ȵ\u{48470}\u{104dcc}扞×ⴞ\u{1ebce}\u{1065e4}\u{34780}\u{46560}", 1, ), ("ɿ\u{13f25}\u{bb3ca}垾\u{7f077}酓\u{3f2d3}\u{86f0b}壪床", 1), ( "ӯ\u{83676}\u{d50cb}ꧏ\u{f9dcd}\u{d1466}\u{1de8e}\u{13bb5}搜\u{592}", 1, ), ( "\u{5cb}\u{cc480}ⶺǠ\u{95c2c}\u{6d588}㬪𪮊\u{147b9}\u{d7fa9}", 1, ), ], ( "\u{880b8}\u{7ba91}\u{615f9}𝟂\u{1a34d}\u{4bb86}\u{363e3}\u{f113b}\u{fada1}\u{88aa9}", Some("\u{880b8}\u{9f3aa}\u{d7dab}𪿾\u{100550}\u{fd341}𬐿鄓𬫦\u{e718}"), ), ); } ================================================ FILE: malachite-base/tests/strings/random/random_fixed_length_strings_using_chars.rs ================================================ // Copyright © 2026 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::chars::random::{random_ascii_chars, random_char_inclusive_range}; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::random::random_fixed_length_strings_using_chars; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use std::iter::repeat; fn random_fixed_length_strings_using_chars_helper>( len: u64, cs: I, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let ss = random_fixed_length_strings_using_chars(len, cs); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_fixed_length_strings_using_chars() { random_fixed_length_strings_using_chars_helper( 0, repeat('a'), &[""; 20], &[("", 1000000)], ("", None), ); random_fixed_length_strings_using_chars_helper( 1, repeat('a'), &["a"; 20], &[("a", 1000000)], ("a", None), ); random_fixed_length_strings_using_chars_helper( 2, repeat('a'), &["aa"; 20], &[("aa", 1000000)], ("aa", None), ); random_fixed_length_strings_using_chars_helper( 3, repeat('a'), &["aaa"; 20], &[("aaa", 1000000)], ("aaa", None), ); random_fixed_length_strings_using_chars_helper( 10, repeat('a'), &["aaaaaaaaaa"; 20], &[("aaaaaaaaaa", 1000000)], ("aaaaaaaaaa", None), ); random_fixed_length_strings_using_chars_helper( 1, random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'), &[ "b", "a", "b", "c", "b", "b", "a", "b", "a", "c", "b", "a", "b", "c", "c", "a", "b", "a", "c", "c", ], &[("b", 333784), ("c", 333516), ("a", 332700)], ("b", None), ); random_fixed_length_strings_using_chars_helper( 2, random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'), &[ "ba", "bc", "bb", "ab", "ac", "ba", "bc", "ca", "ba", "cc", "cb", "ac", "cb", "bb", "aa", "ca", "cc", "ba", "bb", "ac", ], &[ ("cb", 111755), ("aa", 111436), ("cc", 111255), ("bb", 111161), ("ab", 111154), ("ba", 111089), ("ca", 110836), ("bc", 110731), ("ac", 110583), ], ("bb", None), ); random_fixed_length_strings_using_chars_helper( 3, random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'), &[ "bab", "cbb", "aba", "cba", "bcc", "aba", "ccc", "bac", "cbb", "baa", "cac", "cba", "bba", "cca", "cab", "cbb", "ccb", "bba", "cab", "bbc", ], &[ ("bab", 37526), ("ccb", 37346), ("acb", 37337), ("bca", 37271), ("cbb", 37251), ("bba", 37211), ("aab", 37170), ("caa", 37142), ("bbb", 37096), ("abc", 37095), ], ("bbb", None), ); random_fixed_length_strings_using_chars_helper( 10, random_char_inclusive_range(EXAMPLE_SEED, 'a', 'c'), &[ "babcbbabac", "babccabacc", "cbaccbbbaa", "caccbabbac", "cacabcbbcc", "bbbacabbbc", "abbcbbbcbc", "bbcabbbcab", "cbaacabbbc", "bccccccbac", "abaacbcaba", "bbaabcacab", "bbabaaacbc", "cccbccabba", "aacabaabcc", "acabccccab", "bcacccaacc", "accaccbbbc", "aabcbaabcc", "cbccbbbabc", ], &[ ("caacabbbba", 38), ("cbaaacbaab", 37), ("bcacbbabca", 36), ("bcbacaabba", 36), ("aabaaccbaa", 35), ("abcbccaaab", 35), ("bcbcbbbbba", 35), ("aabccaaaca", 34), ("abacaaabba", 34), ("baccbabbcb", 34), ], ("bbbbbbbacc", None), ); random_fixed_length_strings_using_chars_helper( 1, random_ascii_chars(EXAMPLE_SEED), &[ "q", "^", "\u{17}", "b", "F", "\\", "4", "T", "!", "/", "\u{1}", "q", "6", "\n", "/", "\u{11}", "Y", "\\", "w", "B", ], &[ ("\u{2}", 8077), ("y", 8039), ("0", 8015), ("q", 7966), ("\u{8}", 7937), ("M", 7933), ("2", 7928), ("[", 7927), ("R", 7925), ("f", 7924), ], ("?", None), ); random_fixed_length_strings_using_chars_helper( 2, random_ascii_chars(EXAMPLE_SEED), &[ "q^", "\u{17}b", "F\\", "4T", "!/", "\u{1}q", "6\n", "/\u{11}", "Y\\", "wB", "\\r", "\\^", "\u{15}3", "\'.", "\'r", "\u{7}$", "\u{17}S", ":\r", "r@", "I(", ], &[ ("c5", 91), ("\u{1c} ", 90), ("GN", 90), ("a2", 90), ("\u{13}%", 89), ("o\u{14}", 89), ("(u", 88), ("X2", 88), ("\u{10}e", 87), ("\u{1e}f", 87), ], ("@\u{2}", None), ); random_fixed_length_strings_using_chars_helper( 3, random_ascii_chars(EXAMPLE_SEED), &[ "q^\u{17}", "bF\\", "4T!", "/\u{1}q", "6\n/", "\u{11}Y\\", "wB\\", "r\\^", "\u{15}3\'", ".\'r", "\u{7}$\u{17}", "S:\r", "r@I", "(\u{10}\u{11}", "}\u{b}\u{7}", "0z5", ".n1", "\u{10}At", "<9.", "w\\?", ], &[ ("$7\u{5}", 7), ("*\u{1c}\u{1e}", 7), ("\u{e}sb", 6), ("\u{10}+g", 6), ("\u{13}`\u{14}", 6), ("\u{13}oF", 6), ("\u{15}[[", 6), ("\u{1c}Ve", 6), ("\u{1e}<7", 6), ("\"*K", 6), ], ("?}^", None), ); random_fixed_length_strings_using_chars_helper( 10, random_ascii_chars(EXAMPLE_SEED), &[ "q^\u{17}bF\\4T!/", "\u{1}q6\n/\u{11}Y\\wB", "\\r\\^\u{15}3\'.\'r", "\u{7}$\u{17}S:\rr@I(", "\u{10}\u{11}}\u{b}\u{7}0z5.n", "1\u{10}At<9.w\\?", "b\u{15}(\\hJ\u{10}cO\\", "^5Edc\u{1f}kq{t", "=z./\u{5}x\u{1}dZr", "J%\u{5}`=VU_\u{7f}b", ";\u{13}\u{6}U.k\r\u{6}PB", "k]$p\u{1a}+FOH.", "\r,a\u{1}=DZZ\u{16}\u{18}", "cY\t\u{1e}\u{19}&<,\u{13}%", "\u{c}{Z!$Z,\u{17}\u{8}?", "\u{3}\u{4}]\u{1}H\u{c}(K*|", "l\u{15}8^:\u{e}\u{7f}D(P", "\u{1}XEk!$\u{14}/];", "E9d\u{e})|v\u{e}W*", ").\u{19}\u{11}5\u{7f}b8\u{18}:", ], &[ ("\u{0}\u{0}\u{1})\u{19}\\\u{10};bj", 1), ("\u{0}\u{0}\u{3}\u{7};sV\u{e}2}", 1), ("\u{0}\u{0}\u{5}\tmrh\u{1f}{E", 1), ("\u{0}\u{0}\n\n\u{2}\"\u{13}ftF", 1), ("\u{0}\u{0}\r+I^a\u{6}>R", 1), ("\u{0}\u{0}\ry#hUV8+", 1), ("\u{0}\u{0}\u{e}\"^\u{6},+\u{10}[", 1), ("\u{0}\u{0}\u{11}J\u{0}\u{11}5kiy", 1), ("\u{0}\u{0}\u{12}\u{4}txo}{7", 1), ("\u{0}\u{0}\u{13}Gb;}ex|", 1), ], ( "@\u{b}\u{c}t\u{11}\u{b}\u{e}NV&", Some("@\u{b}\u{e}FN+o}X\u{4}"), ), ); } ================================================ FILE: malachite-base/tests/strings/random/random_strings.rs ================================================ // Copyright © 2026 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::random::EXAMPLE_SEED; use malachite_base::strings::random::random_strings; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; fn random_strings_helper( mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let ss = random_strings(EXAMPLE_SEED, mean_length_numerator, mean_length_denominator); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_strings() { random_strings_helper( 4, 1, &[ "", "\u{81355}\u{a331d}\u{b707b}\u{1354b}\u{b16ac}𣙘\u{67377}\u{4aaa4}\u{a6d6e}\u{45616}\ \u{7725f}\u{41e2d}\u{d6b59}\u{de165}", "\u{c2d29}\u{695af}\u{98fd7}\u{10ca51}", "\u{bec46}\u{c0bec}\u{cb677}\u{71318}", "\u{755e1}", "", "𫮜\u{a2f84}柂\u{f5560}\u{6737b}", "\u{8442e}\u{a6883}", "\u{49cf2}\u{32d2b}\u{1e6e5}\u{1084bd}", "", "\u{85172}\u{103bd2}\u{bffa3}\u{c792c}\u{4c421}\u{905ef}", "", "", "\u{c0f92}匥\u{105164}𦤃\u{8ebb2}\u{9e650}\u{399cd}\u{51328}\u{61706}\u{1096f6}\ \u{d9e03}", "\u{ac5ce}\u{db625}\u{f1185}\u{f170e}\u{b7772}\u{dfa6f}\u{f65d0}\u{10c939}", "", "\u{3e110}𪐛\u{84380}", "", "\u{46189}\u{5832d}ꌍ𫁜\u{1083cd}", "\u{102636}\u{c0f80}\u{cacb1}\u{89486}\u{1ad3c}𖢸\u{b7896}\u{3dadc}\u{82b15}", ], &[ ("", 199913), ("姑", 4), ("\u{36097}", 4), ("\u{3d772}", 4), ("\u{40698}", 4), ("\u{6e63c}", 4), ("\u{7d354}", 4), ("\u{8465e}", 4), ("\u{9090b}", 4), ("\u{929c5}", 4), ], ( "\u{667cc}\u{850e8}\u{42572}𪩋\u{637c9}\u{ef6f1}", Some("\u{667cc}\u{a3e1a}\u{bead8}𢰏\u{d2d0b}"), ), ); random_strings_helper( 10, 1, &[ "\u{81355}\u{a331d}\u{b707b}\u{1354b}\u{b16ac}𣙘\u{67377}\u{4aaa4}\u{a6d6e}\u{45616}\ \u{7725f}\u{41e2d}\u{d6b59}\u{de165}\u{c2d29}\u{695af}\u{98fd7}\u{10ca51}\u{bec46}\ \u{c0bec}\u{cb677}\u{71318}\u{755e1}𫮜\u{a2f84}柂\u{f5560}\u{6737b}", "\u{8442e}\u{a6883}\u{49cf2}\u{32d2b}\u{1e6e5}\u{1084bd}\u{85172}\u{103bd2}\u{bffa3}\ \u{c792c}\u{4c421}\u{905ef}\u{c0f92}匥\u{105164}𦤃\u{8ebb2}\u{9e650}", "\u{399cd}\u{51328}\u{61706}\u{1096f6}\u{d9e03}\u{ac5ce}\u{db625}\u{f1185}\u{f170e}\ \u{b7772}\u{dfa6f}\u{f65d0}\u{10c939}\u{3e110}𪐛\u{84380}\u{46189}\u{5832d}ꌍ", "𫁜\u{1083cd}\u{102636}", "\u{c0f80}\u{cacb1}\u{89486}\u{1ad3c}𖢸\u{b7896}\u{3dadc}\u{82b15}\u{e01b7}\u{53091}\ \u{eafa3}\u{e6a8c}", "\u{af3e0}", "\u{56c4c}\u{b06f5}\u{76039}\u{49cbf}\u{103396}\u{99695}\u{fb2c5}\u{1269b}\u{d63a8}\ \u{7b2ad}\u{62abc}\u{426cf}\u{917bd}\u{3ef1e}\u{900a7}𤧏\u{1079f9}\u{41860}\u{9861d}\ \u{cbfd1}\u{48859}\u{5826c}\u{b5d68}\u{9d637}\u{10039d}\u{8e8d5}𡩔\u{50c19}\u{b9d8e}", "\u{f97c0}\u{5e025}\u{71838}\u{bdfd5}\u{d2042}", "\u{bdb07}\u{54a51}", "𞠮\u{f718c}轜\u{511f8}\u{d45cc}\u{cdcb6}\u{51127}\u{62ef1}𗛜\u{5a889}\u{4f824}", "\u{e4fc5}𛂮\u{67155}\u{990bb}\u{54368}\u{1ec21}\u{155e9}\u{cda02}𥵯\u{ac392}\u{41517}\ \u{6d7f1}\u{101067}\u{127d7}\u{76266}\u{e4c58}\u{ba16f}\u{50d46}\u{69b8a}\u{b8556}\ \u{e2a57}\u{c71bb}\u{b2276}\u{db65b}\u{72eba}\u{9ce32}𨚕쬽\u{b14b4}\u{721f3}", "\u{e92d0}\u{79265}\u{3413c}\u{8a37b}\u{3b281}", "\u{1038bc}\u{105572}\u{60004}\u{2f067}", "\u{8d937}\u{a77ba}\u{5cdfa}\u{d281b}\u{4fad0}\u{926dd}탘\u{589d1}", "\u{4c96e}\u{31c01}\u{d7b70}\u{3b41a}\u{fa158}\u{37ba2}\u{f7772}\u{51268}\u{a5a58}\ \u{6dac7}\u{13515}", "\u{94c1f}\u{72cc7}\u{4e95e}\u{ce473}", "\u{10125f}\u{e1343}\u{ff236}\u{883de}凴\u{6274f}\u{ada6c}\u{b0b8b}\u{7f144}", "𠛾\u{72db9}\u{a49b2}𓅹\u{7fe45}\u{fb3c5}\u{86a5e}\u{b91ae}\u{7ef4b}", "\u{4e11e}\u{48ae3}\u{8e62a}\u{6a125}\u{692a6}\u{d811f}\u{1a0d4}\u{70978}\u{1b985}\ \u{d83b6}\u{82dff}\u{41a7f}\u{94b31}깥\u{87f4b}\u{aa0ce}\u{f6b18}⠋\u{ded9c}𬟺\u{10df0a}\ \u{b9982}\u{adaaa}𠰮\u{10db78}", "\u{1c15b}", ], &[ ("", 90709), ("瞁", 4), ("\u{7cb3d}", 4), ("\u{844e7}", 4), ("摄", 3), ("覨", 3), ("霮", 3), ("鬻", 3), ("뀳", 3), ("𥛋", 3), ], ( "\u{7abb9}⼥\u{8df6b}\u{6f616}\u{7661d}\u{68c62}", Some( "\u{7abb9}\u{6e013}\u{10c6dc}\u{5be7a}\u{99103}\u{f9c20}\u{108e71}\u{12917}\ \u{9f018}𥱗", ), ), ); random_strings_helper( 1, 4, &[ "", "", "\u{81355}", "\u{a331d}", "\u{b707b}\u{1354b}", "", "", "", "", "", "", "", "\u{b16ac}𣙘", "\u{67377}", "", "\u{4aaa4}\u{a6d6e}", "", "", "", "", ], &[ ("", 800023), ("\u{4a9ab}", 5), ("悧", 4), ("𦹝", 4), ("𱩖", 4), ("\u{1b9f0}", 4), ("\u{56b1b}", 4), ("\u{61e16}", 4), ("\u{8a520}", 4), ("\u{959f7}", 4), ], ("", None), ); } #[test] #[should_panic] fn random_strings_fail_1() { random_strings(EXAMPLE_SEED, 0, 1); } #[test] #[should_panic] fn random_strings_fail_2() { random_strings(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_strings_fail_3() { random_strings(EXAMPLE_SEED, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/strings/random/random_strings_using_chars.rs ================================================ // Copyright © 2026 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::chars::random::{random_ascii_chars, random_char_inclusive_range}; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::strings::random::random_strings_using_chars; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use std::iter::repeat; fn random_strings_using_chars_helper>( cs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let ss = random_strings_using_chars( EXAMPLE_SEED, cs_gen, mean_length_numerator, mean_length_denominator, ); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_strings_using_chars() { random_strings_using_chars_helper( &|_| repeat('a'), 4, 1, &[ "", "aaaaaaaaaaaaaa", "aaaa", "aaaa", "a", "", "aaaaa", "aa", "aaaa", "", "aaaaaa", "", "", "aaaaaaaaaaa", "aaaaaaaa", "", "aaa", "", "aaaaa", "aaaaaaaaa", ], &[ ("", 199913), ("a", 160173), ("aa", 128173), ("aaa", 102460), ("aaaa", 81463), ("aaaaa", 65695), ("aaaaaa", 52495), ("aaaaaaa", 41943), ("aaaaaaaa", 33396), ("aaaaaaaaa", 27035), ], ("aaa", None), ); random_strings_using_chars_helper( &|seed| random_char_inclusive_range(seed, 'a', 'c'), 4, 1, &[ "", "bbbbcaaacacaca", "cccb", "acca", "b", "", "cbcac", "cb", "cbba", "", "ccacca", "", "", "acacbcccccc", "baccbccb", "", "bcc", "", "cbbca", "aacbaabbc", ], &[ ("", 199913), ("c", 53448), ("a", 53374), ("b", 53351), ("ab", 14396), ("aa", 14370), ("cb", 14345), ("cc", 14252), ("ba", 14240), ("ac", 14237), ], ("b", None), ); random_strings_using_chars_helper( &random_ascii_chars, 4, 1, &[ "", "U\u{16} D<]ae_M,O\u{1d}V", "(\u{10}&U", "{P-K", "Z", "", "\u{4}X\u{19}_,", "\u{1d},", "?\'[N", "", "|}*\u{15}zt", "", "", "\u{2}FXHmX\\\u{8} ZJ", "\u{b}\u{14}OwV\u{19} R", "", "|4\u{e}", "", "M$E\u{12}n", "J)\u{16}\u{1c}\u{11}_T\u{1d}-", ], &[ ("", 199913), ("\u{c}", 1334), ("~", 1322), ("R", 1318), ("o", 1312), ("=", 1310), ("\u{1d}", 1310), ("}", 1308), ("\u{10}", 1306), ("\u{1e}", 1306), ], ("/x\u{b}", Some("/x\u{f}")), ); random_strings_using_chars_helper( &random_ascii_chars, 1, 4, &[ "", "", "U", "\u{16}", " D", "", "", "", "", "", "", "", "<]", "a", "", "e_", "", "", "", "", ], &[ ("", 800023), ("<", 1334), ("$", 1329), ("\u{b}", 1319), ("%", 1313), ("v", 1309), ("A", 1308), ("\u{1a}", 1308), ("d", 1307), ("B", 1306), ], ("", None), ); } #[test] #[should_panic] fn random_strings_using_chars_fail_1() { random_strings_using_chars(EXAMPLE_SEED, &random_ascii_chars, 0, 1); } #[test] #[should_panic] fn random_strings_using_chars_fail_2() { random_strings_using_chars(EXAMPLE_SEED, &random_ascii_chars, 1, 0); } #[test] #[should_panic] fn random_strings_using_chars_fail_3() { random_strings_using_chars(EXAMPLE_SEED, &random_ascii_chars, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-base/tests/strings/string_is_subset.rs ================================================ // Copyright © 2026 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 malachite_base::strings::{string_is_subset, string_sort, string_unique}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::string_pair_gen; #[test] fn test_string_is_subset() { let test = |s, t, out| { assert_eq!(string_is_subset(s, t), out); }; test("", "Hello, world!", true); test("o, well", "Hello, world!", true); test("MMM", "Mississippi", true); test("Hello, World!", "Hello, world!", false); test("j", "Mississippi", false); test( "abcdefghijklmnopqrstuvwxyz", "A quick brown fox jumps over the lazy dog", true, ); } #[test] fn string_is_subset_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_length_d", 1); string_pair_gen().test_properties_with_config(&config, |(s, t)| { let is_subset = string_is_subset(&s, &t); assert_eq!( string_is_subset(&string_sort(&s), &string_sort(&t)), is_subset ); assert_eq!( string_is_subset(&string_unique(&s), &string_unique(&t)), is_subset ); assert_eq!( is_subset && string_is_subset(&t, &s), string_sort(&string_unique(&s)) == string_sort(&string_unique(&t)) ); }); } ================================================ FILE: malachite-base/tests/strings/string_sort.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::comparison::is_weakly_ascending; use malachite_base::strings::{string_is_subset, string_sort, string_unique}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::string_gen; #[test] fn test_string_sort() { let test = |s, out| { assert_eq!(string_sort(s), out); }; test("", ""); test("x", "x"); test("Hello, world!", " !,Hdellloorw"); test("Mississippi", "Miiiippssss"); test( "A quick brown fox jumps over the lazy dog", " Aabcdeefghijklmnoooopqrrstuuvwxyz", ); } #[test] fn string_sort_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_length_d", 1); string_gen().test_properties_with_config(&config, |s| { let t = string_sort(&s); assert!(is_weakly_ascending(t.chars())); assert_eq!(s.len(), t.len()); assert_eq!(string_sort(&t), t); assert_eq!(string_unique(&t), string_sort(&string_unique(&s))); assert!(string_is_subset(&s, &t)); assert!(string_is_subset(&t, &s)); }); } ================================================ FILE: malachite-base/tests/strings/string_unique.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::is_unique; use malachite_base::strings::{string_is_subset, string_unique}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::string_gen; #[test] fn test_string_unique() { let test = |s, out| { assert_eq!(string_unique(s), out); }; test("", ""); test("x", "x"); test("xxxxxxxxx", "x"); test("Hello, world!", "Helo, wrd!"); test("Mississippi", "Misp"); test( "A quick brown fox jumps over the lazy dog", "A quickbrownfxjmpsvethlazydg", ); } #[test] fn string_unique_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_length_d", 1); string_gen().test_properties_with_config(&config, |s| { let t = string_unique(&s); assert!(is_unique(t.chars())); assert!(t.len() <= s.len()); assert_eq!(string_unique(&t), t); assert!(string_is_subset(&s, &t)); assert!(string_is_subset(&t, &s)); }); } ================================================ FILE: malachite-base/tests/strings/strings_from_char_vecs.rs ================================================ // Copyright © 2026 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::strings::strings_from_char_vecs; use std::iter::repeat; fn strings_from_char_vecs_helper>>(css: I, out: &[&str]) { let css = strings_from_char_vecs(css).take(20).collect_vec(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_strings_from_char_vecs() { strings_from_char_vecs_helper([].iter().cloned(), &[]); strings_from_char_vecs_helper([vec!['a']].iter().cloned(), &["a"]); strings_from_char_vecs_helper( [vec!['a', 'b'], vec!['c', 'd']].iter().cloned(), &["ab", "cd"], ); strings_from_char_vecs_helper( repeat(vec!['c', 'a', 't']), &[ "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", "cat", ], ); } ================================================ FILE: malachite-base/tests/strings/to_binary_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToBinaryString; #[test] pub fn test_to_binary_string() { assert_eq!(5u32.to_binary_string(), "101"); assert_eq!( (-5i32).to_binary_string(), "11111111111111111111111111111011" ); } ================================================ FILE: malachite-base/tests/strings/to_debug_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToDebugString; #[test] pub fn test_to_debug_string() { let empty: &[Option] = &[]; assert_eq!(empty.to_debug_string(), "[]"); assert_eq!([1, 2, 3].to_debug_string(), "[1, 2, 3]"); assert_eq!( [vec![2, 3], vec![], vec![4]].to_debug_string(), "[[2, 3], [], [4]]" ); assert_eq!(Some(5).to_debug_string(), "Some(5)"); } ================================================ FILE: malachite-base/tests/strings/to_lower_hex_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToLowerHexString; #[test] pub fn test_to_lower_hex_string() { assert_eq!(50u32.to_lower_hex_string(), "32"); assert_eq!((-100i32).to_lower_hex_string(), "ffffff9c"); } ================================================ FILE: malachite-base/tests/strings/to_octal_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToOctalString; #[test] pub fn test_to_octal_string() { assert_eq!(50u32.to_octal_string(), "62"); assert_eq!((-100i32).to_octal_string(), "37777777634"); } ================================================ FILE: malachite-base/tests/strings/to_upper_hex_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToUpperHexString; #[test] pub fn test_to_upper_hex_string() { assert_eq!(50u32.to_upper_hex_string(), "32"); assert_eq!((-100i32).to_upper_hex_string(), "FFFFFF9C"); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_custom_tuples.rs ================================================ // Copyright © 2026 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 crate::SAMPLE_OUTPUT_TYPES_3; use crate::extra_variadic::{ exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, exhaustive_triples_xyx, exhaustive_triples_xyx_custom_output, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::tuples::exhaustive::exhaustive_pairs; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; #[allow(clippy::needless_pass_by_value)] fn exhaustive_triples_xxy_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, X, Y)], ) { let ts = exhaustive_triples_xxy(xs.clone(), ys.clone()); assert_eq!(ts.clone().take(20).collect_vec(), out); assert_eq!(ts.count(), out_len); let output_types = SAMPLE_OUTPUT_TYPES_3; let ts = exhaustive_triples_xxy_custom_output( xs.clone(), ys.clone(), output_types[0][0], output_types[0][1], output_types[0][2], ); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); for alt_output_types in &output_types[1..] { let ts = exhaustive_triples_xxy_custom_output( xs.clone(), ys.clone(), alt_output_types[0], alt_output_types[1], alt_output_types[2], ); ts.clone().take(20).for_each(drop); assert_eq!(ts.count(), out_len); } } #[test] fn test_exhaustive_triples_xxy() { exhaustive_triples_xxy_helper(nevers(), nevers(), 0, &[]); exhaustive_triples_xxy_helper(nevers(), 0..4, 0, &[]); exhaustive_triples_xxy_helper(once('a'), once(1), 1, &[('a', 'a', 1)]); exhaustive_triples_xxy_helper( once('a'), 0..4, 4, &[('a', 'a', 0), ('a', 'a', 1), ('a', 'a', 2), ('a', 'a', 3)], ); exhaustive_triples_xxy_helper( exhaustive_unsigneds::(), 'a'..'e', 1 << 18, &[ (0, 0, 'a'), (0, 0, 'b'), (0, 1, 'a'), (0, 1, 'b'), (1, 0, 'a'), (1, 0, 'b'), (1, 1, 'a'), (1, 1, 'b'), (0, 0, 'c'), (0, 0, 'd'), (0, 1, 'c'), (0, 1, 'd'), (1, 0, 'c'), (1, 0, 'd'), (1, 1, 'c'), (1, 1, 'd'), (0, 2, 'a'), (0, 2, 'b'), (0, 3, 'a'), (0, 3, 'b'), ], ); exhaustive_triples_xxy_helper( exhaustive_bools(), 0..4, 16, &[ (false, false, 0), (false, false, 1), (false, true, 0), (false, true, 1), (true, false, 0), (true, false, 1), (true, true, 0), (true, true, 1), (false, false, 2), (false, false, 3), (false, true, 2), (false, true, 3), (true, false, 2), (true, false, 3), (true, true, 2), (true, true, 3), ], ); exhaustive_triples_xxy_helper( 'a'..'f', 0..3, 75, &[ ('a', 'a', 0), ('a', 'a', 1), ('a', 'b', 0), ('a', 'b', 1), ('b', 'a', 0), ('b', 'a', 1), ('b', 'b', 0), ('b', 'b', 1), ('a', 'a', 2), ('a', 'b', 2), ('b', 'a', 2), ('b', 'b', 2), ('a', 'c', 0), ('a', 'c', 1), ('a', 'd', 0), ('a', 'd', 1), ('b', 'c', 0), ('b', 'c', 1), ('b', 'd', 0), ('b', 'd', 1), ], ); exhaustive_triples_xxy_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 27, &[ ('a', 'a', Equal), ('a', 'a', Less), ('a', 'b', Equal), ('a', 'b', Less), ('b', 'a', Equal), ('b', 'a', Less), ('b', 'b', Equal), ('b', 'b', Less), ('a', 'a', Greater), ('a', 'b', Greater), ('b', 'a', Greater), ('b', 'b', Greater), ('a', 'c', Equal), ('a', 'c', Less), ('b', 'c', Equal), ('b', 'c', Less), ('a', 'c', Greater), ('b', 'c', Greater), ('c', 'a', Equal), ('c', 'a', Less), ], ); exhaustive_triples_xxy_helper( exhaustive_pairs(exhaustive_orderings(), exhaustive_bools()), exhaustive_triples_from_single([Less, Greater].iter().copied()), 288, &[ ((Equal, false), (Equal, false), (Less, Less, Less)), ((Equal, false), (Equal, false), (Less, Less, Greater)), ((Equal, false), (Equal, true), (Less, Less, Less)), ((Equal, false), (Equal, true), (Less, Less, Greater)), ((Equal, true), (Equal, false), (Less, Less, Less)), ((Equal, true), (Equal, false), (Less, Less, Greater)), ((Equal, true), (Equal, true), (Less, Less, Less)), ((Equal, true), (Equal, true), (Less, Less, Greater)), ((Equal, false), (Equal, false), (Less, Greater, Less)), ((Equal, false), (Equal, false), (Less, Greater, Greater)), ((Equal, false), (Equal, true), (Less, Greater, Less)), ((Equal, false), (Equal, true), (Less, Greater, Greater)), ((Equal, true), (Equal, false), (Less, Greater, Less)), ((Equal, true), (Equal, false), (Less, Greater, Greater)), ((Equal, true), (Equal, true), (Less, Greater, Less)), ((Equal, true), (Equal, true), (Less, Greater, Greater)), ((Equal, false), (Less, false), (Less, Less, Less)), ((Equal, false), (Less, false), (Less, Less, Greater)), ((Equal, false), (Less, true), (Less, Less, Less)), ((Equal, false), (Less, true), (Less, Less, Greater)), ], ); } #[allow(clippy::needless_pass_by_value)] fn exhaustive_triples_xyx_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, Y, X)], ) { let ts = exhaustive_triples_xyx(xs.clone(), ys.clone()); assert_eq!(ts.clone().take(20).collect_vec(), out); assert_eq!(ts.count(), out_len); let output_types = SAMPLE_OUTPUT_TYPES_3; let ts = exhaustive_triples_xyx_custom_output( xs.clone(), ys.clone(), output_types[0][0], output_types[0][1], output_types[0][2], ); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); for alt_output_types in &output_types[1..] { let ts = exhaustive_triples_xyx_custom_output( xs.clone(), ys.clone(), alt_output_types[0], alt_output_types[1], alt_output_types[2], ); ts.clone().take(20).for_each(drop); assert_eq!(ts.count(), out_len); } } #[test] fn test_exhaustive_triples_xyx() { exhaustive_triples_xyx_helper(nevers(), nevers(), 0, &[]); exhaustive_triples_xyx_helper(nevers(), 0..4, 0, &[]); exhaustive_triples_xyx_helper(once('a'), once(1), 1, &[('a', 1, 'a')]); exhaustive_triples_xyx_helper( once('a'), 0..4, 4, &[('a', 0, 'a'), ('a', 1, 'a'), ('a', 2, 'a'), ('a', 3, 'a')], ); exhaustive_triples_xyx_helper( exhaustive_unsigneds::(), 'a'..'e', 1 << 18, &[ (0, 'a', 0), (0, 'a', 1), (0, 'b', 0), (0, 'b', 1), (1, 'a', 0), (1, 'a', 1), (1, 'b', 0), (1, 'b', 1), (0, 'a', 2), (0, 'a', 3), (0, 'b', 2), (0, 'b', 3), (1, 'a', 2), (1, 'a', 3), (1, 'b', 2), (1, 'b', 3), (0, 'c', 0), (0, 'c', 1), (0, 'd', 0), (0, 'd', 1), ], ); exhaustive_triples_xyx_helper( exhaustive_bools(), 0..4, 16, &[ (false, 0, false), (false, 0, true), (false, 1, false), (false, 1, true), (true, 0, false), (true, 0, true), (true, 1, false), (true, 1, true), (false, 2, false), (false, 2, true), (false, 3, false), (false, 3, true), (true, 2, false), (true, 2, true), (true, 3, false), (true, 3, true), ], ); exhaustive_triples_xyx_helper( 'a'..'f', 0..3, 75, &[ ('a', 0, 'a'), ('a', 0, 'b'), ('a', 1, 'a'), ('a', 1, 'b'), ('b', 0, 'a'), ('b', 0, 'b'), ('b', 1, 'a'), ('b', 1, 'b'), ('a', 0, 'c'), ('a', 0, 'd'), ('a', 1, 'c'), ('a', 1, 'd'), ('b', 0, 'c'), ('b', 0, 'd'), ('b', 1, 'c'), ('b', 1, 'd'), ('a', 2, 'a'), ('a', 2, 'b'), ('b', 2, 'a'), ('b', 2, 'b'), ], ); exhaustive_triples_xyx_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 27, &[ ('a', Equal, 'a'), ('a', Equal, 'b'), ('a', Less, 'a'), ('a', Less, 'b'), ('b', Equal, 'a'), ('b', Equal, 'b'), ('b', Less, 'a'), ('b', Less, 'b'), ('a', Equal, 'c'), ('a', Less, 'c'), ('b', Equal, 'c'), ('b', Less, 'c'), ('a', Greater, 'a'), ('a', Greater, 'b'), ('b', Greater, 'a'), ('b', Greater, 'b'), ('a', Greater, 'c'), ('b', Greater, 'c'), ('c', Equal, 'a'), ('c', Equal, 'b'), ], ); exhaustive_triples_xyx_helper( exhaustive_pairs(exhaustive_orderings(), exhaustive_bools()), exhaustive_triples_from_single([Less, Greater].iter().copied()), 288, &[ ((Equal, false), (Less, Less, Less), (Equal, false)), ((Equal, false), (Less, Less, Less), (Equal, true)), ((Equal, false), (Less, Less, Greater), (Equal, false)), ((Equal, false), (Less, Less, Greater), (Equal, true)), ((Equal, true), (Less, Less, Less), (Equal, false)), ((Equal, true), (Less, Less, Less), (Equal, true)), ((Equal, true), (Less, Less, Greater), (Equal, false)), ((Equal, true), (Less, Less, Greater), (Equal, true)), ((Equal, false), (Less, Less, Less), (Less, false)), ((Equal, false), (Less, Less, Less), (Less, true)), ((Equal, false), (Less, Less, Greater), (Less, false)), ((Equal, false), (Less, Less, Greater), (Less, true)), ((Equal, true), (Less, Less, Less), (Less, false)), ((Equal, true), (Less, Less, Less), (Less, true)), ((Equal, true), (Less, Less, Greater), (Less, false)), ((Equal, true), (Less, Less, Greater), (Less, true)), ((Equal, false), (Less, Greater, Less), (Equal, false)), ((Equal, false), (Less, Greater, Less), (Equal, true)), ((Equal, false), (Less, Greater, Greater), (Equal, false)), ((Equal, false), (Less, Greater, Greater), (Equal, true)), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_dependent_pairs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, chain}; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::num::exhaustive::exhaustive_positive_primitive_ints; use malachite_base::num::iterators::{bit_distributor_sequence, ruler_sequence}; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairsYsGenerator, exhaustive_dependent_pairs, exhaustive_dependent_pairs_stop_after_empty_ys, }; use std::collections::HashMap; use std::fmt::Debug; use std::iter::{Cloned, once, repeat}; use std::slice::Iter; #[derive(Clone, Debug)] struct ExhaustiveGeneratorFromMap { map: HashMap, } impl ExhaustiveDependentPairsYsGenerator>> for ExhaustiveGeneratorFromMap { #[inline] fn get_ys(&self, x: &X) -> Cloned> { self.map[x].iter().cloned() } } fn exhaustive_dependent_pairs_finite_ys_helper( xs: I, map: HashMap, out_ruler: &[(I::Item, Y)], out_normal_normal: &[(I::Item, Y)], out_tiny_normal: &[(I::Item, Y)], ) where I::Item: Clone + Debug + Eq + Hash, Y: Clone + Debug + Eq, { let xss_ruler = exhaustive_dependent_pairs( ruler_sequence(), xs.clone(), ExhaustiveGeneratorFromMap { map: map.clone() }, ) .take(20) .collect_vec(); assert_eq!(xss_ruler.as_slice(), out_ruler); let xss_normal_normal = exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), xs.clone(), ExhaustiveGeneratorFromMap { map: map.clone() }, ) .take(20) .collect_vec(); assert_eq!(xss_normal_normal.as_slice(), out_normal_normal); let xss_tiny_normal = exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), xs, ExhaustiveGeneratorFromMap { map }, ) .take(20) .collect_vec(); assert_eq!(xss_tiny_normal.as_slice(), out_tiny_normal); } #[test] fn test_exhaustive_dependent_pairs() { exhaustive_dependent_pairs_finite_ys_helper( [1, 2, 3].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[200, 201, 202][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (2, 200), (1, 101), (3, 300), (1, 102), (2, 201), (2, 202), (3, 301), (3, 302)], &[(1, 100), (2, 200), (1, 101), (2, 201), (3, 300), (1, 102), (3, 301), (3, 302), (2, 202)], &[(1, 100), (2, 200), (3, 300), (1, 101), (1, 102), (2, 201), (3, 301), (3, 302), (2, 202)], ); exhaustive_dependent_pairs_finite_ys_helper( ["cat", "dog", "mouse", "dog", "cat"].iter().copied(), hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] }, &[ ("cat", 2), ("dog", 20), ("cat", 3), ("mouse", 30), ("cat", 4), ("mouse", 40), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ], &[ ("cat", 2), ("dog", 20), ("cat", 3), ("mouse", 30), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ("mouse", 40), ("cat", 4), ], &[ ("cat", 2), ("dog", 20), ("mouse", 30), ("dog", 20), ("cat", 3), ("mouse", 40), ("cat", 2), ("cat", 4), ("cat", 3), ("cat", 4), ], ); exhaustive_dependent_pairs_finite_ys_helper( [1, 2, 3, 2, 3, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (3, 300), (1, 101), (3, 300), (1, 102), (3, 301), (3, 302), (3, 301), (3, 302)], &[(1, 100), (3, 300), (1, 101), (3, 301), (3, 300), (1, 102), (3, 301), (3, 302), (3, 302)], &[(1, 100), (3, 300), (3, 300), (1, 101), (1, 102), (3, 301), (3, 301), (3, 302), (3, 302)], ); exhaustive_dependent_pairs_finite_ys_helper( [].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], &[], &[], ); exhaustive_dependent_pairs_finite_ys_helper( [2, 2, 2, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], &[], &[], ); } fn exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( xs: I, map: HashMap, out_ruler: &[(I::Item, Y)], out_normal_normal: &[(I::Item, Y)], out_tiny_normal: &[(I::Item, Y)], ) where I::Item: Clone + Debug + Eq + Hash, Y: Clone + Debug + Eq, { let xss_ruler = exhaustive_dependent_pairs_stop_after_empty_ys( ruler_sequence(), xs.clone(), ExhaustiveGeneratorFromMap { map: map.clone() }, ) .take(20) .collect_vec(); assert_eq!(xss_ruler.as_slice(), out_ruler); let xss_normal_normal = exhaustive_dependent_pairs_stop_after_empty_ys( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), xs.clone(), ExhaustiveGeneratorFromMap { map: map.clone() }, ) .take(20) .collect_vec(); assert_eq!(xss_normal_normal.as_slice(), out_normal_normal); let xss_tiny_normal = exhaustive_dependent_pairs_stop_after_empty_ys( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), xs, ExhaustiveGeneratorFromMap { map }, ) .take(20) .collect_vec(); assert_eq!(xss_tiny_normal.as_slice(), out_tiny_normal); } #[test] fn test_exhaustive_dependent_pairs_stop_after_empty_ys() { exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( [1, 2, 3].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[200, 201, 202][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (2, 200), (1, 101), (3, 300), (1, 102), (2, 201), (2, 202), (3, 301), (3, 302)], &[(1, 100), (2, 200), (1, 101), (2, 201), (3, 300), (1, 102), (3, 301), (3, 302), (2, 202)], &[(1, 100), (2, 200), (3, 300), (1, 101), (1, 102), (2, 201), (3, 301), (3, 302), (2, 202)], ); exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( ["cat", "dog", "mouse", "dog", "cat"].iter().copied(), hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] }, &[ ("cat", 2), ("dog", 20), ("cat", 3), ("mouse", 30), ("cat", 4), ("mouse", 40), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ], &[ ("cat", 2), ("dog", 20), ("cat", 3), ("mouse", 30), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ("mouse", 40), ("cat", 4), ], &[ ("cat", 2), ("dog", 20), ("mouse", 30), ("dog", 20), ("cat", 3), ("mouse", 40), ("cat", 2), ("cat", 4), ("cat", 3), ("cat", 4), ], ); // Notice difference from `exhaustive_dependent_pairs` exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( [1, 2, 3, 2, 3, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(1, 100)], &[(1, 100)], &[(1, 100)], ); exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( [].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], &[], &[], ); exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( [2, 2, 2, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], &[], &[], ); // With `exhaustive_dependent_pairs` this would hang exhaustive_dependent_pairs_finite_ys_stop_after_empty_ys_helper( chain(once(3), repeat(2)), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(3, 300)], &[(3, 300)], &[(3, 300)], ); } #[derive(Clone, Debug)] struct MultiplesGeneratorHelper { u: u64, step: u64, } impl Iterator for MultiplesGeneratorHelper { type Item = u64; fn next(&mut self) -> Option { let next = self.u; self.u += self.step; Some(next) } } #[derive(Clone, Debug)] struct MultiplesGenerator {} impl ExhaustiveDependentPairsYsGenerator for MultiplesGenerator { #[inline] fn get_ys(&self, x: &u64) -> MultiplesGeneratorHelper { MultiplesGeneratorHelper { u: *x, step: *x } } } #[test] fn test_exhaustive_dependent_pairs_infinite() { let xs = exhaustive_positive_primitive_ints::(); let xss_ruler = exhaustive_dependent_pairs(ruler_sequence(), xs.clone(), MultiplesGenerator {}) .take(50) .collect_vec(); assert_eq!( xss_ruler.as_slice(), &[ (1, 1), (2, 2), (1, 2), (3, 3), (1, 3), (2, 4), (1, 4), (4, 4), (1, 5), (2, 6), (1, 6), (3, 6), (1, 7), (2, 8), (1, 8), (5, 5), (1, 9), (2, 10), (1, 10), (3, 9), (1, 11), (2, 12), (1, 12), (4, 8), (1, 13), (2, 14), (1, 14), (3, 12), (1, 15), (2, 16), (1, 16), (6, 6), (1, 17), (2, 18), (1, 18), (3, 15), (1, 19), (2, 20), (1, 20), (4, 12), (1, 21), (2, 22), (1, 22), (3, 18), (1, 23), (2, 24), (1, 24), (5, 10), (1, 25), (2, 26) ] ); let xss_normal_normal = exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), xs.clone(), MultiplesGenerator {}, ) .take(50) .collect_vec(); assert_eq!( xss_normal_normal.as_slice(), &[ (1, 1), (2, 2), (1, 2), (2, 4), (3, 3), (4, 4), (3, 6), (4, 8), (1, 3), (2, 6), (1, 4), (2, 8), (3, 9), (4, 12), (3, 12), (4, 16), (5, 5), (6, 6), (5, 10), (6, 12), (7, 7), (8, 8), (7, 14), (8, 16), (5, 15), (6, 18), (5, 20), (6, 24), (7, 21), (8, 24), (7, 28), (8, 32), (1, 5), (2, 10), (1, 6), (2, 12), (3, 15), (4, 20), (3, 18), (4, 24), (1, 7), (2, 14), (1, 8), (2, 16), (3, 21), (4, 28), (3, 24), (4, 32), (5, 25), (6, 30) ] ); let xss_tiny_normal = exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), xs, MultiplesGenerator {}, ) .take(50) .collect_vec(); assert_eq!( xss_tiny_normal.as_slice(), &[ (1, 1), (2, 2), (3, 3), (4, 4), (1, 2), (2, 4), (3, 6), (4, 8), (5, 5), (6, 6), (7, 7), (8, 8), (5, 10), (6, 12), (7, 14), (8, 16), (1, 3), (2, 6), (3, 9), (4, 12), (1, 4), (2, 8), (3, 12), (4, 16), (5, 15), (6, 18), (7, 21), (8, 24), (5, 20), (6, 24), (7, 28), (8, 32), (1, 5), (2, 10), (3, 15), (4, 20), (1, 6), (2, 12), (3, 18), (4, 24), (5, 25), (6, 30), (7, 35), (8, 40), (5, 30), (6, 36), (7, 42), (8, 48), (1, 7), (2, 14) ] ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_ordered_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{ exhaustive_ordered_unique_quadruples, exhaustive_ordered_unique_quintuples, exhaustive_ordered_unique_triples, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_ordered_unique_pairs, exhaustive_units}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), exhaustive_ordered_unique_pairs, _exhaustive_ordered_unique_pairs_helper, exhaustive_ordered_unique_pairs_small_helper ); helpers!( (I::Item, I::Item, I::Item), exhaustive_ordered_unique_triples, exhaustive_ordered_unique_triples_helper, _exhaustive_ordered_unique_triples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), exhaustive_ordered_unique_quadruples, _exhaustive_ordered_unique_quadruples_helper, exhaustive_ordered_unique_quadruples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), exhaustive_ordered_unique_quintuples, _exhaustive_ordered_unique_quintuples_helper, exhaustive_ordered_unique_quintuples_small_helper ); #[test] fn test_exhaustive_ordered_unique_tuples() { exhaustive_ordered_unique_pairs_small_helper(nevers(), 0, &[]); exhaustive_ordered_unique_quintuples_small_helper(nevers(), 0, &[]); exhaustive_ordered_unique_pairs_small_helper(exhaustive_units(), 0, &[]); exhaustive_ordered_unique_quintuples_small_helper(exhaustive_units(), 0, &[]); exhaustive_ordered_unique_pairs_small_helper( exhaustive_unsigneds::(), 32640, &[ (0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (2, 3), (0, 4), (1, 4), (2, 4), (3, 4), (0, 5), (1, 5), (2, 5), (3, 5), (4, 5), (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), ], ); exhaustive_ordered_unique_triples_helper( exhaustive_unsigneds::(), &[ (0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3), (0, 1, 4), (0, 2, 4), (1, 2, 4), (0, 3, 4), (1, 3, 4), (2, 3, 4), (0, 1, 5), (0, 2, 5), (1, 2, 5), (0, 3, 5), (1, 3, 5), (2, 3, 5), (0, 4, 5), (1, 4, 5), (2, 4, 5), (3, 4, 5), ], ); exhaustive_ordered_unique_pairs_small_helper( exhaustive_ascii_chars(), 8128, &[ ('a', 'b'), ('a', 'c'), ('b', 'c'), ('a', 'd'), ('b', 'd'), ('c', 'd'), ('a', 'e'), ('b', 'e'), ('c', 'e'), ('d', 'e'), ('a', 'f'), ('b', 'f'), ('c', 'f'), ('d', 'f'), ('e', 'f'), ('a', 'g'), ('b', 'g'), ('c', 'g'), ('d', 'g'), ('e', 'g'), ], ); exhaustive_ordered_unique_pairs_small_helper(exhaustive_bools(), 1, &[(false, true)]); exhaustive_ordered_unique_quadruples_small_helper( 1..=6, 15, &[ (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5), (1, 2, 3, 6), (1, 2, 4, 6), (1, 3, 4, 6), (2, 3, 4, 6), (1, 2, 5, 6), (1, 3, 5, 6), (2, 3, 5, 6), (1, 4, 5, 6), (2, 4, 5, 6), (3, 4, 5, 6), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_tuples_1_input.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::exhaustive_triples_1_input; use crate::{SAMPLE_OUTPUT_TYPES_2, SAMPLE_OUTPUT_TYPES_3}; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::{exhaustive_positive_primitive_ints, exhaustive_unsigneds}; use malachite_base::tuples::exhaustive::exhaustive_pairs_1_input; use std::fmt::Debug; fn exhaustive_pairs_1_input_helper>( xs: &I, out_len: Option, out: &[(T, T)], ) where T: Clone + Debug + Eq, { let output_types = SAMPLE_OUTPUT_TYPES_2; let ps = exhaustive_pairs_1_input(xs.clone(), output_types[0][0], output_types[0][1]); assert_eq!(ps.clone().take(20).collect_vec(), out); if let Some(out_len) = out_len { assert_eq!(ps.count(), out_len); } for alt_output_types in &output_types[1..] { let ps = exhaustive_pairs_1_input(xs.clone(), alt_output_types[0], alt_output_types[1]); ps.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(ps.count(), out_len); } } } #[test] fn test_exhaustive_pairs_1_input() { exhaustive_pairs_1_input_helper(&nevers(), Some(0), &[]); exhaustive_pairs_1_input_helper( &exhaustive_unsigneds::(), Some(1 << 16), &[ (0, 0), (0, 1), (1, 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1), (3, 0), (3, 1), (2, 2), (2, 3), (3, 2), (3, 3), (0, 4), (0, 5), (1, 4), (1, 5), ], ); exhaustive_pairs_1_input_helper( &exhaustive_positive_primitive_ints::(), None, &[ (1, 1), (1, 2), (2, 1), (2, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 1), (3, 2), (4, 1), (4, 2), (3, 3), (3, 4), (4, 3), (4, 4), (1, 5), (1, 6), (2, 5), (2, 6), ], ); exhaustive_pairs_1_input_helper( &['x', 'y', 'z'].iter().copied(), Some(9), &[ ('x', 'x'), ('x', 'y'), ('y', 'x'), ('y', 'y'), ('x', 'z'), ('y', 'z'), ('z', 'x'), ('z', 'y'), ('z', 'z'), ], ); } fn exhaustive_triples_1_input_helper>( xs: &I, out_len: Option, out: &[(T, T, T)], ) where T: Clone + Debug + Eq, { let output_types = SAMPLE_OUTPUT_TYPES_3; let ps = exhaustive_triples_1_input( xs.clone(), output_types[0][0], output_types[0][1], output_types[0][2], ); assert_eq!(ps.clone().take(20).collect_vec(), out); if let Some(out_len) = out_len { assert_eq!(ps.count(), out_len); } for alt_output_types in &output_types[1..] { let ps = exhaustive_triples_1_input( xs.clone(), alt_output_types[0], alt_output_types[1], alt_output_types[2], ); ps.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(ps.count(), out_len); } } } #[test] fn test_exhaustive_triples_1_input() { exhaustive_triples_1_input_helper( &['x', 'y', 'z'].iter().copied(), Some(27), &[ ('x', 'x', 'x'), ('x', 'x', 'y'), ('x', 'y', 'x'), ('x', 'y', 'y'), ('y', 'x', 'x'), ('y', 'x', 'y'), ('y', 'y', 'x'), ('y', 'y', 'y'), ('x', 'x', 'z'), ('x', 'y', 'z'), ('y', 'x', 'z'), ('y', 'y', 'z'), ('x', 'z', 'x'), ('x', 'z', 'y'), ('y', 'z', 'x'), ('y', 'z', 'y'), ('x', 'z', 'z'), ('y', 'z', 'z'), ('z', 'x', 'x'), ('z', 'x', 'y'), ], ); exhaustive_triples_1_input_helper( &exhaustive_ascii_chars(), None, &[ ('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'b', 'a'), ('a', 'b', 'b'), ('b', 'a', 'a'), ('b', 'a', 'b'), ('b', 'b', 'a'), ('b', 'b', 'b'), ('a', 'a', 'c'), ('a', 'a', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('b', 'a', 'c'), ('b', 'a', 'd'), ('b', 'b', 'c'), ('b', 'b', 'd'), ('a', 'c', 'a'), ('a', 'c', 'b'), ('a', 'd', 'a'), ('a', 'd', 'b'), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_tuples_custom_output.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::exhaustive_triples_from_single; use crate::{SAMPLE_OUTPUT_TYPES_2, SAMPLE_OUTPUT_TYPES_3}; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::options::exhaustive::exhaustive_somes; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::tuples::exhaustive::{ exhaustive_pairs, exhaustive_pairs_custom_output, exhaustive_pairs_from_single, exhaustive_triples, exhaustive_triples_custom_output, }; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; #[allow(clippy::needless_pass_by_value)] fn exhaustive_pairs_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, Y)], ) { let ps = exhaustive_pairs(xs.clone(), ys.clone()); assert_eq!(ps.clone().take(20).collect_vec(), out); assert_eq!(ps.count(), out_len); let output_types = SAMPLE_OUTPUT_TYPES_2; let ps = exhaustive_pairs_custom_output( xs.clone(), ys.clone(), output_types[0][0], output_types[0][1], ); assert_eq!(ps.clone().take(20).collect_vec(), out); assert_eq!(ps.count(), out_len); for alt_output_types in &output_types[1..] { let ps = exhaustive_pairs_custom_output( xs.clone(), ys.clone(), alt_output_types[0], alt_output_types[1], ); ps.clone().take(20).for_each(drop); assert_eq!(ps.count(), out_len); } } #[test] fn test_exhaustive_pairs_and_exhaustive_pairs_custom_output() { exhaustive_pairs_helper(nevers(), nevers(), 0, &[]); exhaustive_pairs_helper(nevers(), 0..4, 0, &[]); exhaustive_pairs_helper(once('a'), once(1), 1, &[('a', 1)]); exhaustive_pairs_helper( once('a'), 0..4, 4, &[('a', 0), ('a', 1), ('a', 2), ('a', 3)], ); exhaustive_pairs_helper( exhaustive_unsigneds::(), 'a'..'e', 1024, &[ (0, 'a'), (0, 'b'), (1, 'a'), (1, 'b'), (0, 'c'), (0, 'd'), (1, 'c'), (1, 'd'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b'), (2, 'c'), (2, 'd'), (3, 'c'), (3, 'd'), (4, 'a'), (4, 'b'), (5, 'a'), (5, 'b'), ], ); exhaustive_pairs_helper( exhaustive_bools(), 0..4, 8, &[ (false, 0), (false, 1), (true, 0), (true, 1), (false, 2), (false, 3), (true, 2), (true, 3), ], ); exhaustive_pairs_helper( 'a'..'f', 0..3, 15, &[ ('a', 0), ('a', 1), ('b', 0), ('b', 1), ('a', 2), ('b', 2), ('c', 0), ('c', 1), ('d', 0), ('d', 1), ('c', 2), ('d', 2), ('e', 0), ('e', 1), ('e', 2), ], ); exhaustive_pairs_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 9, &[ ('a', Equal), ('a', Less), ('b', Equal), ('b', Less), ('a', Greater), ('b', Greater), ('c', Equal), ('c', Less), ('c', Greater), ], ); exhaustive_pairs_helper( exhaustive_pairs(exhaustive_orderings(), exhaustive_bools()), exhaustive_triples_from_single([Less, Greater].iter().copied()), 48, &[ ((Equal, false), (Less, Less, Less)), ((Equal, false), (Less, Less, Greater)), ((Equal, true), (Less, Less, Less)), ((Equal, true), (Less, Less, Greater)), ((Equal, false), (Less, Greater, Less)), ((Equal, false), (Less, Greater, Greater)), ((Equal, true), (Less, Greater, Less)), ((Equal, true), (Less, Greater, Greater)), ((Less, false), (Less, Less, Less)), ((Less, false), (Less, Less, Greater)), ((Less, true), (Less, Less, Less)), ((Less, true), (Less, Less, Greater)), ((Less, false), (Less, Greater, Less)), ((Less, false), (Less, Greater, Greater)), ((Less, true), (Less, Greater, Less)), ((Less, true), (Less, Greater, Greater)), ((Equal, false), (Greater, Less, Less)), ((Equal, false), (Greater, Less, Greater)), ((Equal, true), (Greater, Less, Less)), ((Equal, true), (Greater, Less, Greater)), ], ); } #[allow(clippy::needless_pass_by_value)] fn exhaustive_triples_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, Z: Clone + Debug + Eq, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[(X, Y, Z)], ) { let ts = exhaustive_triples(xs.clone(), ys.clone(), zs.clone()); assert_eq!(ts.clone().take(20).collect_vec(), out); assert_eq!(ts.count(), out_len); let output_types = SAMPLE_OUTPUT_TYPES_3; let ts = exhaustive_triples_custom_output( xs.clone(), ys.clone(), zs.clone(), output_types[0][0], output_types[0][1], output_types[0][2], ); assert_eq!(ts.clone().take(20).collect_vec(), out); assert_eq!(ts.count(), out_len); for alt_output_types in &output_types[1..] { let ts = exhaustive_triples_custom_output( xs.clone(), ys.clone(), zs.clone(), alt_output_types[0], alt_output_types[1], alt_output_types[2], ); ts.clone().take(20).for_each(drop); assert_eq!(ts.count(), out_len); } } #[test] fn test_exhaustive_triples_and_exhaustive_triples_custom_output() { exhaustive_triples_helper(nevers(), nevers(), nevers(), 0, &[]); exhaustive_triples_helper(nevers(), 0..4, 'a'..'f', 0, &[]); exhaustive_triples_helper(once('a'), once(false), once(5), 1, &[('a', false, 5)]); exhaustive_triples_helper( once('a'), once(false), 0..4, 4, &[('a', false, 0), ('a', false, 1), ('a', false, 2), ('a', false, 3)], ); exhaustive_triples_helper( exhaustive_unsigneds::(), exhaustive_pairs_from_single(exhaustive_bools()), 'a'..'e', 4096, &[ (0, (false, false), 'a'), (0, (false, false), 'b'), (0, (false, true), 'a'), (0, (false, true), 'b'), (1, (false, false), 'a'), (1, (false, false), 'b'), (1, (false, true), 'a'), (1, (false, true), 'b'), (0, (false, false), 'c'), (0, (false, false), 'd'), (0, (false, true), 'c'), (0, (false, true), 'd'), (1, (false, false), 'c'), (1, (false, false), 'd'), (1, (false, true), 'c'), (1, (false, true), 'd'), (0, (true, false), 'a'), (0, (true, false), 'b'), (0, (true, true), 'a'), (0, (true, true), 'b'), ], ); exhaustive_triples_helper( exhaustive_bools(), 0..3, 'a'..'d', 18, &[ (false, 0, 'a'), (false, 0, 'b'), (false, 1, 'a'), (false, 1, 'b'), (true, 0, 'a'), (true, 0, 'b'), (true, 1, 'a'), (true, 1, 'b'), (false, 0, 'c'), (false, 1, 'c'), (true, 0, 'c'), (true, 1, 'c'), (false, 2, 'a'), (false, 2, 'b'), (true, 2, 'a'), (true, 2, 'b'), (false, 2, 'c'), (true, 2, 'c'), ], ); exhaustive_triples_helper( 0..11, exhaustive_somes(0..12), 'a'..'n', 1716, &[ (0, Some(0), 'a'), (0, Some(0), 'b'), (0, Some(1), 'a'), (0, Some(1), 'b'), (1, Some(0), 'a'), (1, Some(0), 'b'), (1, Some(1), 'a'), (1, Some(1), 'b'), (0, Some(0), 'c'), (0, Some(0), 'd'), (0, Some(1), 'c'), (0, Some(1), 'd'), (1, Some(0), 'c'), (1, Some(0), 'd'), (1, Some(1), 'c'), (1, Some(1), 'd'), (0, Some(2), 'a'), (0, Some(2), 'b'), (0, Some(3), 'a'), (0, Some(3), 'b'), ], ); exhaustive_triples_helper( ['a', 'b', 'c'].iter().copied(), ["xx", "yy", "zz"].iter().copied(), 0..3, 27, &[ ('a', "xx", 0), ('a', "xx", 1), ('a', "yy", 0), ('a', "yy", 1), ('b', "xx", 0), ('b', "xx", 1), ('b', "yy", 0), ('b', "yy", 1), ('a', "xx", 2), ('a', "yy", 2), ('b', "xx", 2), ('b', "yy", 2), ('a', "zz", 0), ('a', "zz", 1), ('b', "zz", 0), ('b', "zz", 1), ('a', "zz", 2), ('b', "zz", 2), ('c', "xx", 0), ('c', "xx", 1), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_tuples_from_single.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{ exhaustive_octuples_from_single, exhaustive_quadruples_from_single, exhaustive_quintuples_from_single, exhaustive_triples_from_single, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_pairs_from_single, exhaustive_units}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), exhaustive_pairs_from_single, exhaustive_pairs_from_single_helper, exhaustive_pairs_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item), exhaustive_triples_from_single, exhaustive_triples_from_single_helper, _exhaustive_triples_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), exhaustive_quadruples_from_single, _exhaustive_quadruples_from_single_helper, exhaustive_quadruples_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), exhaustive_quintuples_from_single, _exhaustive_quintuples_from_single_helper, exhaustive_quintuples_from_single_small_helper ); helpers!( ( I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item ), exhaustive_octuples_from_single, _exhaustive_octuples_from_single_helper, exhaustive_octuples_from_single_small_helper ); #[test] fn test_exhaustive_tuples_from_single() { exhaustive_pairs_from_single_small_helper(nevers(), 0, &[]); exhaustive_quintuples_from_single_small_helper(nevers(), 0, &[]); exhaustive_pairs_from_single_small_helper(exhaustive_units(), 1, &[((), ())]); exhaustive_quintuples_from_single_small_helper(exhaustive_units(), 1, &[((), (), (), (), ())]); exhaustive_pairs_from_single_helper( exhaustive_unsigneds::(), &[ (0, 0), (0, 1), (1, 0), (1, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 0), (2, 1), (3, 0), (3, 1), (2, 2), (2, 3), (3, 2), (3, 3), (0, 4), (0, 5), (1, 4), (1, 5), ], ); exhaustive_triples_from_single_helper( exhaustive_unsigneds::(), &[ (0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1), (0, 0, 2), (0, 0, 3), (0, 1, 2), (0, 1, 3), (1, 0, 2), (1, 0, 3), (1, 1, 2), (1, 1, 3), (0, 2, 0), (0, 2, 1), (0, 3, 0), (0, 3, 1), ], ); exhaustive_pairs_from_single_small_helper( exhaustive_ascii_chars(), 0x4000, &[ ('a', 'a'), ('a', 'b'), ('b', 'a'), ('b', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('d', 'a'), ('d', 'b'), ('c', 'c'), ('c', 'd'), ('d', 'c'), ('d', 'd'), ('a', 'e'), ('a', 'f'), ('b', 'e'), ('b', 'f'), ], ); exhaustive_pairs_from_single_small_helper( exhaustive_bools(), 4, &[(false, false), (false, true), (true, false), (true, true)], ); exhaustive_quadruples_from_single_small_helper( exhaustive_bools(), 16, &[ (false, false, false, false), (false, false, false, true), (false, false, true, false), (false, false, true, true), (false, true, false, false), (false, true, false, true), (false, true, true, false), (false, true, true, true), (true, false, false, false), (true, false, false, true), (true, false, true, false), (true, false, true, true), (true, true, false, false), (true, true, false, true), (true, true, true, false), (true, true, true, true), ], ); exhaustive_octuples_from_single_small_helper( exhaustive_bools(), 256, &[ (false, false, false, false, false, false, false, false), (false, false, false, false, false, false, false, true), (false, false, false, false, false, false, true, false), (false, false, false, false, false, false, true, true), (false, false, false, false, false, true, false, false), (false, false, false, false, false, true, false, true), (false, false, false, false, false, true, true, false), (false, false, false, false, false, true, true, true), (false, false, false, false, true, false, false, false), (false, false, false, false, true, false, false, true), (false, false, false, false, true, false, true, false), (false, false, false, false, true, false, true, true), (false, false, false, false, true, true, false, false), (false, false, false, false, true, true, false, true), (false, false, false, false, true, true, true, false), (false, false, false, false, true, true, true, true), (false, false, false, true, false, false, false, false), (false, false, false, true, false, false, false, true), (false, false, false, true, false, false, true, false), (false, false, false, true, false, false, true, true), ], ); exhaustive_octuples_from_single_small_helper( 0..3, 6561, &[ (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 1, 0), (0, 0, 0, 0, 0, 0, 1, 1), (0, 0, 0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 1, 0, 1), (0, 0, 0, 0, 0, 1, 1, 0), (0, 0, 0, 0, 0, 1, 1, 1), (0, 0, 0, 0, 1, 0, 0, 0), (0, 0, 0, 0, 1, 0, 0, 1), (0, 0, 0, 0, 1, 0, 1, 0), (0, 0, 0, 0, 1, 0, 1, 1), (0, 0, 0, 0, 1, 1, 0, 0), (0, 0, 0, 0, 1, 1, 0, 1), (0, 0, 0, 0, 1, 1, 1, 0), (0, 0, 0, 0, 1, 1, 1, 1), (0, 0, 0, 1, 0, 0, 0, 0), (0, 0, 0, 1, 0, 0, 0, 1), (0, 0, 0, 1, 0, 0, 1, 0), (0, 0, 0, 1, 0, 0, 1, 1), ], ); exhaustive_pairs_from_single_helper( exhaustive_pairs_from_single(exhaustive_unsigneds::()), &[ ((0, 0), (0, 0)), ((0, 0), (0, 1)), ((0, 1), (0, 0)), ((0, 1), (0, 1)), ((0, 0), (1, 0)), ((0, 0), (1, 1)), ((0, 1), (1, 0)), ((0, 1), (1, 1)), ((1, 0), (0, 0)), ((1, 0), (0, 1)), ((1, 1), (0, 0)), ((1, 1), (0, 1)), ((1, 0), (1, 0)), ((1, 0), (1, 1)), ((1, 1), (1, 0)), ((1, 1), (1, 1)), ((0, 0), (0, 2)), ((0, 0), (0, 3)), ((0, 1), (0, 2)), ((0, 1), (0, 3)), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{ exhaustive_unique_quadruples, exhaustive_unique_quintuples, exhaustive_unique_triples, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_unique_pairs, exhaustive_units}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), exhaustive_unique_pairs, _exhaustive_unique_pairs_helper, exhaustive_unique_pairs_small_helper ); helpers!( (I::Item, I::Item, I::Item), exhaustive_unique_triples, exhaustive_unique_triples_helper, _exhaustive_unique_triples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), exhaustive_unique_quadruples, _exhaustive_unique_quadruples_helper, exhaustive_unique_quadruples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), exhaustive_unique_quintuples, _exhaustive_unique_quintuples_helper, exhaustive_unique_quintuples_small_helper ); #[test] fn test_exhaustive_unique_tuples() { exhaustive_unique_pairs_small_helper(nevers(), 0, &[]); exhaustive_unique_quintuples_small_helper(nevers(), 0, &[]); exhaustive_unique_pairs_small_helper(exhaustive_units(), 0, &[]); exhaustive_unique_quintuples_small_helper(exhaustive_units(), 0, &[]); exhaustive_unique_pairs_small_helper( exhaustive_unsigneds::(), 65280, &[ (0, 1), (1, 0), (0, 2), (2, 0), (1, 2), (2, 1), (0, 3), (3, 0), (1, 3), (3, 1), (2, 3), (3, 2), (0, 4), (4, 0), (1, 4), (4, 1), (2, 4), (4, 2), (3, 4), (4, 3), ], ); exhaustive_unique_triples_helper( exhaustive_unsigneds::(), &[ (0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 3), (1, 0, 2), (0, 3, 1), (1, 2, 0), (1, 2, 3), (2, 0, 1), (1, 0, 3), (2, 1, 0), (0, 3, 2), (1, 3, 0), (2, 0, 3), (3, 0, 1), (0, 2, 4), (3, 1, 0), (2, 3, 0), (3, 0, 2), (0, 1, 4), ], ); exhaustive_unique_pairs_small_helper( exhaustive_ascii_chars(), 16256, &[ ('a', 'b'), ('b', 'a'), ('a', 'c'), ('c', 'a'), ('b', 'c'), ('c', 'b'), ('a', 'd'), ('d', 'a'), ('b', 'd'), ('d', 'b'), ('c', 'd'), ('d', 'c'), ('a', 'e'), ('e', 'a'), ('b', 'e'), ('e', 'b'), ('c', 'e'), ('e', 'c'), ('d', 'e'), ('e', 'd'), ], ); exhaustive_unique_pairs_small_helper(exhaustive_bools(), 2, &[(false, true), (true, false)]); exhaustive_unique_quadruples_small_helper( 1..=6, 360, &[ (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 3), (1, 2, 4, 5), (1, 3, 2, 4), (1, 2, 5, 3), (1, 3, 4, 2), (1, 3, 4, 5), (1, 4, 2, 3), (1, 3, 2, 5), (1, 4, 3, 2), (1, 2, 5, 4), (2, 1, 3, 4), (1, 3, 5, 2), (2, 1, 4, 3), (2, 3, 4, 5), (2, 3, 1, 4), (1, 5, 2, 3), (2, 3, 4, 1), (1, 4, 2, 5), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/exhaustive_units.rs ================================================ // Copyright © 2026 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::tuples::exhaustive::exhaustive_units; #[test] fn test_exhaustive_units() { assert_eq!(exhaustive_units().collect_vec(), &[()]); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_custom_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{lex_triples_from_single, lex_triples_xxy, lex_triples_xyx}; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::tuples::exhaustive::lex_pairs; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; fn lex_triples_xxy_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, X, Y)], ) { let ts = lex_triples_xxy(xs, ys); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } #[test] fn test_lex_triples_xxy() { lex_triples_xxy_helper(nevers(), nevers(), 0, &[]); lex_triples_xxy_helper(nevers(), 0..4, 0, &[]); lex_triples_xxy_helper(once('a'), once(1), 1, &[('a', 'a', 1)]); lex_triples_xxy_helper( once('a'), 0..4, 4, &[('a', 'a', 0), ('a', 'a', 1), ('a', 'a', 2), ('a', 'a', 3)], ); lex_triples_xxy_helper( exhaustive_unsigneds::(), 'a'..'e', 1 << 18, &[ (0, 0, 'a'), (0, 0, 'b'), (0, 0, 'c'), (0, 0, 'd'), (0, 1, 'a'), (0, 1, 'b'), (0, 1, 'c'), (0, 1, 'd'), (0, 2, 'a'), (0, 2, 'b'), (0, 2, 'c'), (0, 2, 'd'), (0, 3, 'a'), (0, 3, 'b'), (0, 3, 'c'), (0, 3, 'd'), (0, 4, 'a'), (0, 4, 'b'), (0, 4, 'c'), (0, 4, 'd'), ], ); lex_triples_xxy_helper( exhaustive_bools(), 0..4, 16, &[ (false, false, 0), (false, false, 1), (false, false, 2), (false, false, 3), (false, true, 0), (false, true, 1), (false, true, 2), (false, true, 3), (true, false, 0), (true, false, 1), (true, false, 2), (true, false, 3), (true, true, 0), (true, true, 1), (true, true, 2), (true, true, 3), ], ); lex_triples_xxy_helper( 'a'..'f', 0..3, 75, &[ ('a', 'a', 0), ('a', 'a', 1), ('a', 'a', 2), ('a', 'b', 0), ('a', 'b', 1), ('a', 'b', 2), ('a', 'c', 0), ('a', 'c', 1), ('a', 'c', 2), ('a', 'd', 0), ('a', 'd', 1), ('a', 'd', 2), ('a', 'e', 0), ('a', 'e', 1), ('a', 'e', 2), ('b', 'a', 0), ('b', 'a', 1), ('b', 'a', 2), ('b', 'b', 0), ('b', 'b', 1), ], ); lex_triples_xxy_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 27, &[ ('a', 'a', Equal), ('a', 'a', Less), ('a', 'a', Greater), ('a', 'b', Equal), ('a', 'b', Less), ('a', 'b', Greater), ('a', 'c', Equal), ('a', 'c', Less), ('a', 'c', Greater), ('b', 'a', Equal), ('b', 'a', Less), ('b', 'a', Greater), ('b', 'b', Equal), ('b', 'b', Less), ('b', 'b', Greater), ('b', 'c', Equal), ('b', 'c', Less), ('b', 'c', Greater), ('c', 'a', Equal), ('c', 'a', Less), ], ); lex_triples_xxy_helper( lex_pairs(exhaustive_orderings(), exhaustive_bools()), lex_triples_from_single([Less, Greater].iter().copied()), 288, &[ ((Equal, false), (Equal, false), (Less, Less, Less)), ((Equal, false), (Equal, false), (Less, Less, Greater)), ((Equal, false), (Equal, false), (Less, Greater, Less)), ((Equal, false), (Equal, false), (Less, Greater, Greater)), ((Equal, false), (Equal, false), (Greater, Less, Less)), ((Equal, false), (Equal, false), (Greater, Less, Greater)), ((Equal, false), (Equal, false), (Greater, Greater, Less)), ((Equal, false), (Equal, false), (Greater, Greater, Greater)), ((Equal, false), (Equal, true), (Less, Less, Less)), ((Equal, false), (Equal, true), (Less, Less, Greater)), ((Equal, false), (Equal, true), (Less, Greater, Less)), ((Equal, false), (Equal, true), (Less, Greater, Greater)), ((Equal, false), (Equal, true), (Greater, Less, Less)), ((Equal, false), (Equal, true), (Greater, Less, Greater)), ((Equal, false), (Equal, true), (Greater, Greater, Less)), ((Equal, false), (Equal, true), (Greater, Greater, Greater)), ((Equal, false), (Less, false), (Less, Less, Less)), ((Equal, false), (Less, false), (Less, Less, Greater)), ((Equal, false), (Less, false), (Less, Greater, Less)), ((Equal, false), (Less, false), (Less, Greater, Greater)), ], ); } fn lex_triples_xyx_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, Y, X)], ) { let ts = lex_triples_xyx(xs, ys); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } #[test] fn test_lex_triples_xyx() { lex_triples_xyx_helper(nevers(), nevers(), 0, &[]); lex_triples_xyx_helper(nevers(), 0..4, 0, &[]); lex_triples_xyx_helper(once('a'), once(1), 1, &[('a', 1, 'a')]); lex_triples_xyx_helper( once('a'), 0..4, 4, &[('a', 0, 'a'), ('a', 1, 'a'), ('a', 2, 'a'), ('a', 3, 'a')], ); lex_triples_xyx_helper( exhaustive_unsigneds::(), 'a'..'e', 1 << 18, &[ (0, 'a', 0), (0, 'a', 1), (0, 'a', 2), (0, 'a', 3), (0, 'a', 4), (0, 'a', 5), (0, 'a', 6), (0, 'a', 7), (0, 'a', 8), (0, 'a', 9), (0, 'a', 10), (0, 'a', 11), (0, 'a', 12), (0, 'a', 13), (0, 'a', 14), (0, 'a', 15), (0, 'a', 16), (0, 'a', 17), (0, 'a', 18), (0, 'a', 19), ], ); lex_triples_xyx_helper( exhaustive_bools(), 0..4, 16, &[ (false, 0, false), (false, 0, true), (false, 1, false), (false, 1, true), (false, 2, false), (false, 2, true), (false, 3, false), (false, 3, true), (true, 0, false), (true, 0, true), (true, 1, false), (true, 1, true), (true, 2, false), (true, 2, true), (true, 3, false), (true, 3, true), ], ); lex_triples_xyx_helper( 'a'..'f', 0..3, 75, &[ ('a', 0, 'a'), ('a', 0, 'b'), ('a', 0, 'c'), ('a', 0, 'd'), ('a', 0, 'e'), ('a', 1, 'a'), ('a', 1, 'b'), ('a', 1, 'c'), ('a', 1, 'd'), ('a', 1, 'e'), ('a', 2, 'a'), ('a', 2, 'b'), ('a', 2, 'c'), ('a', 2, 'd'), ('a', 2, 'e'), ('b', 0, 'a'), ('b', 0, 'b'), ('b', 0, 'c'), ('b', 0, 'd'), ('b', 0, 'e'), ], ); lex_triples_xyx_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 27, &[ ('a', Equal, 'a'), ('a', Equal, 'b'), ('a', Equal, 'c'), ('a', Less, 'a'), ('a', Less, 'b'), ('a', Less, 'c'), ('a', Greater, 'a'), ('a', Greater, 'b'), ('a', Greater, 'c'), ('b', Equal, 'a'), ('b', Equal, 'b'), ('b', Equal, 'c'), ('b', Less, 'a'), ('b', Less, 'b'), ('b', Less, 'c'), ('b', Greater, 'a'), ('b', Greater, 'b'), ('b', Greater, 'c'), ('c', Equal, 'a'), ('c', Equal, 'b'), ], ); lex_triples_xyx_helper( lex_pairs(exhaustive_orderings(), exhaustive_bools()), lex_triples_from_single([Less, Greater].iter().copied()), 288, &[ ((Equal, false), (Less, Less, Less), (Equal, false)), ((Equal, false), (Less, Less, Less), (Equal, true)), ((Equal, false), (Less, Less, Less), (Less, false)), ((Equal, false), (Less, Less, Less), (Less, true)), ((Equal, false), (Less, Less, Less), (Greater, false)), ((Equal, false), (Less, Less, Less), (Greater, true)), ((Equal, false), (Less, Less, Greater), (Equal, false)), ((Equal, false), (Less, Less, Greater), (Equal, true)), ((Equal, false), (Less, Less, Greater), (Less, false)), ((Equal, false), (Less, Less, Greater), (Less, true)), ((Equal, false), (Less, Less, Greater), (Greater, false)), ((Equal, false), (Less, Less, Greater), (Greater, true)), ((Equal, false), (Less, Greater, Less), (Equal, false)), ((Equal, false), (Less, Greater, Less), (Equal, true)), ((Equal, false), (Less, Greater, Less), (Less, false)), ((Equal, false), (Less, Greater, Less), (Less, true)), ((Equal, false), (Less, Greater, Less), (Greater, false)), ((Equal, false), (Less, Greater, Less), (Greater, true)), ((Equal, false), (Less, Greater, Greater), (Equal, false)), ((Equal, false), (Less, Greater, Greater), (Equal, true)), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_dependent_pairs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, chain}; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairsYsGenerator, lex_dependent_pairs, lex_dependent_pairs_stop_after_empty_ys, }; use std::collections::HashMap; use std::fmt::Debug; use std::iter::{Cloned, once, repeat}; use std::slice::Iter; #[derive(Clone, Debug)] struct DPGeneratorFromMap { map: HashMap, } impl ExhaustiveDependentPairsYsGenerator>> for DPGeneratorFromMap { #[inline] fn get_ys(&self, x: &X) -> Cloned> { self.map[x].iter().cloned() } } fn lex_dependent_pairs_helper( xs: I, map: HashMap, out: &[(I::Item, Y)], ) where I::Item: Clone + Debug + Eq + Hash, Y: Clone + Debug + Eq, { let xss = lex_dependent_pairs(xs, DPGeneratorFromMap { map }) .take(20) .collect_vec(); assert_eq!(xss.as_slice(), out); } #[test] fn test_lex_dependent_pairs() { lex_dependent_pairs_helper( [1, 2, 3].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[200, 201, 202][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (1, 101), (1, 102), (2, 200), (2, 201), (2, 202), (3, 300), (3, 301), (3, 302)], ); lex_dependent_pairs_helper( ["cat", "dog", "mouse", "dog", "cat"].iter().copied(), hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] }, &[ ("cat", 2), ("cat", 3), ("cat", 4), ("dog", 20), ("mouse", 30), ("mouse", 40), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ], ); lex_dependent_pairs_helper( [1, 2, 3, 2, 3, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (1, 101), (1, 102), (3, 300), (3, 301), (3, 302), (3, 300), (3, 301), (3, 302)], ); lex_dependent_pairs_helper( [].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], ); lex_dependent_pairs_helper( [2, 2, 2, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], ); } fn lex_dependent_pairs_stop_after_empty_ys_helper( xs: I, map: HashMap, out: &[(I::Item, Y)], ) where I::Item: Clone + Debug + Eq + Hash, Y: Clone + Debug + Eq, { let xss = lex_dependent_pairs_stop_after_empty_ys(xs, DPGeneratorFromMap { map }) .take(20) .collect_vec(); assert_eq!(xss.as_slice(), out); } #[test] fn test_lex_dependent_pairs_stop_after_empty_ys() { lex_dependent_pairs_stop_after_empty_ys_helper( [1, 2, 3].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[200, 201, 202][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (1, 101), (1, 102), (2, 200), (2, 201), (2, 202), (3, 300), (3, 301), (3, 302)], ); lex_dependent_pairs_stop_after_empty_ys_helper( ["cat", "dog", "mouse", "dog", "cat"].iter().copied(), hashmap! { "cat" => &[2, 3, 4][..], "dog" => &[20][..], "mouse" => &[30, 40][..] }, &[ ("cat", 2), ("cat", 3), ("cat", 4), ("dog", 20), ("mouse", 30), ("mouse", 40), ("dog", 20), ("cat", 2), ("cat", 3), ("cat", 4), ], ); // Notice difference from `lex_dependent_pairs` lex_dependent_pairs_stop_after_empty_ys_helper( [1, 2, 3, 2, 3, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(1, 100), (1, 101), (1, 102)], ); lex_dependent_pairs_stop_after_empty_ys_helper( [].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], ); lex_dependent_pairs_stop_after_empty_ys_helper( [2, 2, 2, 2, 2].iter().copied(), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[], ); // With `lex_dependent_pairs` this would hang lex_dependent_pairs_stop_after_empty_ys_helper( chain(once(3), repeat(2)), hashmap! { 1 => &[100, 101, 102][..], 2 => &[][..], 3 => &[300, 301, 302][..] }, &[(3, 300), (3, 301), (3, 302)], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_ordered_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{ lex_ordered_unique_quadruples, lex_ordered_unique_quintuples, lex_ordered_unique_triples, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_units, lex_ordered_unique_pairs}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), lex_ordered_unique_pairs, _lex_ordered_unique_pairs_helper, lex_ordered_unique_pairs_small_helper ); helpers!( (I::Item, I::Item, I::Item), lex_ordered_unique_triples, lex_ordered_unique_triples_helper, _lex_ordered_unique_triples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), lex_ordered_unique_quadruples, _lex_ordered_unique_quadruples_helper, lex_ordered_unique_quadruples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), lex_ordered_unique_quintuples, _lex_ordered_unique_quintuples_helper, lex_ordered_unique_quintuples_small_helper ); #[test] fn test_lex_ordered_unique_tuples() { lex_ordered_unique_pairs_small_helper(nevers(), 0, &[]); lex_ordered_unique_quintuples_small_helper(nevers(), 0, &[]); lex_ordered_unique_pairs_small_helper(exhaustive_units(), 0, &[]); lex_ordered_unique_quintuples_small_helper(exhaustive_units(), 0, &[]); lex_ordered_unique_pairs_small_helper( exhaustive_unsigneds::(), 32640, &[ (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (0, 12), (0, 13), (0, 14), (0, 15), (0, 16), (0, 17), (0, 18), (0, 19), (0, 20), ], ); lex_ordered_unique_triples_helper( exhaustive_unsigneds::(), &[ (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 1, 5), (0, 1, 6), (0, 1, 7), (0, 1, 8), (0, 1, 9), (0, 1, 10), (0, 1, 11), (0, 1, 12), (0, 1, 13), (0, 1, 14), (0, 1, 15), (0, 1, 16), (0, 1, 17), (0, 1, 18), (0, 1, 19), (0, 1, 20), (0, 1, 21), ], ); lex_ordered_unique_pairs_small_helper( exhaustive_ascii_chars(), 8128, &[ ('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e'), ('a', 'f'), ('a', 'g'), ('a', 'h'), ('a', 'i'), ('a', 'j'), ('a', 'k'), ('a', 'l'), ('a', 'm'), ('a', 'n'), ('a', 'o'), ('a', 'p'), ('a', 'q'), ('a', 'r'), ('a', 's'), ('a', 't'), ('a', 'u'), ], ); lex_ordered_unique_pairs_small_helper(exhaustive_bools(), 1, &[(false, true)]); lex_ordered_unique_quadruples_small_helper( 1..=6, 15, &[ (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 3, 6), (1, 2, 4, 5), (1, 2, 4, 6), (1, 2, 5, 6), (1, 3, 4, 5), (1, 3, 4, 6), (1, 3, 5, 6), (1, 4, 5, 6), (2, 3, 4, 5), (2, 3, 4, 6), (2, 3, 5, 6), (2, 4, 5, 6), (3, 4, 5, 6), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{lex_triples, lex_triples_from_single}; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::options::exhaustive::exhaustive_somes; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::tuples::exhaustive::{lex_pairs, lex_pairs_from_single}; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; fn lex_pairs_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[(X, Y)], ) { let ps = lex_pairs(xs, ys); let ps_prefix = ps.clone().take(20).collect_vec(); assert_eq!(ps_prefix.as_slice(), out); assert_eq!(ps.count(), out_len); } #[test] fn test_lex_pairs() { lex_pairs_helper(nevers(), nevers(), 0, &[]); lex_pairs_helper(nevers(), 0..4, 0, &[]); lex_pairs_helper(once('a'), once(1), 1, &[('a', 1)]); lex_pairs_helper( once('a'), 0..4, 4, &[('a', 0), ('a', 1), ('a', 2), ('a', 3)], ); lex_pairs_helper( exhaustive_unsigneds::(), 'a'..'e', 1024, &[ (0, 'a'), (0, 'b'), (0, 'c'), (0, 'd'), (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd'), (2, 'a'), (2, 'b'), (2, 'c'), (2, 'd'), (3, 'a'), (3, 'b'), (3, 'c'), (3, 'd'), (4, 'a'), (4, 'b'), (4, 'c'), (4, 'd'), ], ); lex_pairs_helper( exhaustive_bools(), 0..4, 8, &[ (false, 0), (false, 1), (false, 2), (false, 3), (true, 0), (true, 1), (true, 2), (true, 3), ], ); lex_pairs_helper( 'a'..'f', 0..3, 15, &[ ('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2), ('c', 0), ('c', 1), ('c', 2), ('d', 0), ('d', 1), ('d', 2), ('e', 0), ('e', 1), ('e', 2), ], ); lex_pairs_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 9, &[ ('a', Equal), ('a', Less), ('a', Greater), ('b', Equal), ('b', Less), ('b', Greater), ('c', Equal), ('c', Less), ('c', Greater), ], ); lex_pairs_helper( lex_pairs(exhaustive_orderings(), exhaustive_bools()), lex_triples_from_single([Less, Greater].iter().copied()), 48, &[ ((Equal, false), (Less, Less, Less)), ((Equal, false), (Less, Less, Greater)), ((Equal, false), (Less, Greater, Less)), ((Equal, false), (Less, Greater, Greater)), ((Equal, false), (Greater, Less, Less)), ((Equal, false), (Greater, Less, Greater)), ((Equal, false), (Greater, Greater, Less)), ((Equal, false), (Greater, Greater, Greater)), ((Equal, true), (Less, Less, Less)), ((Equal, true), (Less, Less, Greater)), ((Equal, true), (Less, Greater, Less)), ((Equal, true), (Less, Greater, Greater)), ((Equal, true), (Greater, Less, Less)), ((Equal, true), (Greater, Less, Greater)), ((Equal, true), (Greater, Greater, Less)), ((Equal, true), (Greater, Greater, Greater)), ((Less, false), (Less, Less, Less)), ((Less, false), (Less, Less, Greater)), ((Less, false), (Less, Greater, Less)), ((Less, false), (Less, Greater, Greater)), ], ); } fn lex_triples_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, Z: Clone + Debug + Eq, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[(X, Y, Z)], ) { let ts = lex_triples(xs, ys, zs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } #[test] fn test_lex_triples() { lex_triples_helper(nevers(), nevers(), nevers(), 0, &[]); lex_triples_helper(nevers(), 0..4, 'a'..'f', 0, &[]); lex_triples_helper(once('a'), once(false), once(5), 1, &[('a', false, 5)]); lex_triples_helper( once('a'), once(false), 0..4, 4, &[('a', false, 0), ('a', false, 1), ('a', false, 2), ('a', false, 3)], ); lex_triples_helper( exhaustive_unsigneds::(), lex_pairs_from_single(exhaustive_bools()), 'a'..'e', 4096, &[ (0, (false, false), 'a'), (0, (false, false), 'b'), (0, (false, false), 'c'), (0, (false, false), 'd'), (0, (false, true), 'a'), (0, (false, true), 'b'), (0, (false, true), 'c'), (0, (false, true), 'd'), (0, (true, false), 'a'), (0, (true, false), 'b'), (0, (true, false), 'c'), (0, (true, false), 'd'), (0, (true, true), 'a'), (0, (true, true), 'b'), (0, (true, true), 'c'), (0, (true, true), 'd'), (1, (false, false), 'a'), (1, (false, false), 'b'), (1, (false, false), 'c'), (1, (false, false), 'd'), ], ); lex_triples_helper( exhaustive_bools(), 0..3, 'a'..'d', 18, &[ (false, 0, 'a'), (false, 0, 'b'), (false, 0, 'c'), (false, 1, 'a'), (false, 1, 'b'), (false, 1, 'c'), (false, 2, 'a'), (false, 2, 'b'), (false, 2, 'c'), (true, 0, 'a'), (true, 0, 'b'), (true, 0, 'c'), (true, 1, 'a'), (true, 1, 'b'), (true, 1, 'c'), (true, 2, 'a'), (true, 2, 'b'), (true, 2, 'c'), ], ); lex_triples_helper( 0..11, exhaustive_somes(0..12), 'a'..'n', 1716, &[ (0, Some(0), 'a'), (0, Some(0), 'b'), (0, Some(0), 'c'), (0, Some(0), 'd'), (0, Some(0), 'e'), (0, Some(0), 'f'), (0, Some(0), 'g'), (0, Some(0), 'h'), (0, Some(0), 'i'), (0, Some(0), 'j'), (0, Some(0), 'k'), (0, Some(0), 'l'), (0, Some(0), 'm'), (0, Some(1), 'a'), (0, Some(1), 'b'), (0, Some(1), 'c'), (0, Some(1), 'd'), (0, Some(1), 'e'), (0, Some(1), 'f'), (0, Some(1), 'g'), ], ); lex_triples_helper( ['a', 'b', 'c'].iter().copied(), ["xx", "yy", "zz"].iter().copied(), 0..3, 27, &[ ('a', "xx", 0), ('a', "xx", 1), ('a', "xx", 2), ('a', "yy", 0), ('a', "yy", 1), ('a', "yy", 2), ('a', "zz", 0), ('a', "zz", 1), ('a', "zz", 2), ('b', "xx", 0), ('b', "xx", 1), ('b', "xx", 2), ('b', "yy", 0), ('b', "yy", 1), ('b', "yy", 2), ('b', "zz", 0), ('b', "zz", 1), ('b', "zz", 2), ('c', "xx", 0), ('c', "xx", 1), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_tuples_from_single.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{ lex_octuples_from_single, lex_quadruples_from_single, lex_quintuples_from_single, lex_triples_from_single, }; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_units, lex_pairs_from_single}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), lex_pairs_from_single, lex_pairs_from_single_helper, lex_pairs_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item), lex_triples_from_single, lex_triples_from_single_helper, _lex_triples_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), lex_quadruples_from_single, _lex_quadruples_from_single_helper, lex_quadruples_from_single_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), lex_quintuples_from_single, _lex_quintuples_from_single_helper, lex_quintuples_from_single_small_helper ); helpers!( ( I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item, I::Item ), lex_octuples_from_single, _lex_octuples_from_single_helper, lex_octuples_from_single_small_helper ); #[test] fn test_lex_tuples_from_single() { lex_pairs_from_single_small_helper(nevers(), 0, &[]); lex_quintuples_from_single_small_helper(nevers(), 0, &[]); lex_pairs_from_single_small_helper(exhaustive_units(), 1, &[((), ())]); lex_quintuples_from_single_small_helper(exhaustive_units(), 1, &[((), (), (), (), ())]); lex_pairs_from_single_helper( exhaustive_unsigneds::(), &[ (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (0, 12), (0, 13), (0, 14), (0, 15), (0, 16), (0, 17), (0, 18), (0, 19), ], ); lex_triples_from_single_helper( exhaustive_unsigneds::(), &[ (0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 0, 5), (0, 0, 6), (0, 0, 7), (0, 0, 8), (0, 0, 9), (0, 0, 10), (0, 0, 11), (0, 0, 12), (0, 0, 13), (0, 0, 14), (0, 0, 15), (0, 0, 16), (0, 0, 17), (0, 0, 18), (0, 0, 19), ], ); lex_pairs_from_single_small_helper( exhaustive_ascii_chars(), 0x4000, &[ ('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e'), ('a', 'f'), ('a', 'g'), ('a', 'h'), ('a', 'i'), ('a', 'j'), ('a', 'k'), ('a', 'l'), ('a', 'm'), ('a', 'n'), ('a', 'o'), ('a', 'p'), ('a', 'q'), ('a', 'r'), ('a', 's'), ('a', 't'), ], ); lex_pairs_from_single_small_helper( exhaustive_bools(), 4, &[(false, false), (false, true), (true, false), (true, true)], ); lex_quadruples_from_single_small_helper( exhaustive_bools(), 16, &[ (false, false, false, false), (false, false, false, true), (false, false, true, false), (false, false, true, true), (false, true, false, false), (false, true, false, true), (false, true, true, false), (false, true, true, true), (true, false, false, false), (true, false, false, true), (true, false, true, false), (true, false, true, true), (true, true, false, false), (true, true, false, true), (true, true, true, false), (true, true, true, true), ], ); lex_octuples_from_single_small_helper( exhaustive_bools(), 256, &[ (false, false, false, false, false, false, false, false), (false, false, false, false, false, false, false, true), (false, false, false, false, false, false, true, false), (false, false, false, false, false, false, true, true), (false, false, false, false, false, true, false, false), (false, false, false, false, false, true, false, true), (false, false, false, false, false, true, true, false), (false, false, false, false, false, true, true, true), (false, false, false, false, true, false, false, false), (false, false, false, false, true, false, false, true), (false, false, false, false, true, false, true, false), (false, false, false, false, true, false, true, true), (false, false, false, false, true, true, false, false), (false, false, false, false, true, true, false, true), (false, false, false, false, true, true, true, false), (false, false, false, false, true, true, true, true), (false, false, false, true, false, false, false, false), (false, false, false, true, false, false, false, true), (false, false, false, true, false, false, true, false), (false, false, false, true, false, false, true, true), ], ); lex_octuples_from_single_small_helper( 0..3, 6561, &[ (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 0, 2), (0, 0, 0, 0, 0, 0, 1, 0), (0, 0, 0, 0, 0, 0, 1, 1), (0, 0, 0, 0, 0, 0, 1, 2), (0, 0, 0, 0, 0, 0, 2, 0), (0, 0, 0, 0, 0, 0, 2, 1), (0, 0, 0, 0, 0, 0, 2, 2), (0, 0, 0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 1, 0, 1), (0, 0, 0, 0, 0, 1, 0, 2), (0, 0, 0, 0, 0, 1, 1, 0), (0, 0, 0, 0, 0, 1, 1, 1), (0, 0, 0, 0, 0, 1, 1, 2), (0, 0, 0, 0, 0, 1, 2, 0), (0, 0, 0, 0, 0, 1, 2, 1), (0, 0, 0, 0, 0, 1, 2, 2), (0, 0, 0, 0, 0, 2, 0, 0), (0, 0, 0, 0, 0, 2, 0, 1), ], ); lex_pairs_from_single_helper( lex_pairs_from_single(exhaustive_unsigneds::()), &[ ((0, 0), (0, 0)), ((0, 0), (0, 1)), ((0, 0), (0, 2)), ((0, 0), (0, 3)), ((0, 0), (0, 4)), ((0, 0), (0, 5)), ((0, 0), (0, 6)), ((0, 0), (0, 7)), ((0, 0), (0, 8)), ((0, 0), (0, 9)), ((0, 0), (0, 10)), ((0, 0), (0, 11)), ((0, 0), (0, 12)), ((0, 0), (0, 13)), ((0, 0), (0, 14)), ((0, 0), (0, 15)), ((0, 0), (0, 16)), ((0, 0), (0, 17)), ((0, 0), (0, 18)), ((0, 0), (0, 19)), ], ); } ================================================ FILE: malachite-base/tests/tuples/exhaustive/lex_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{lex_unique_quadruples, lex_unique_quintuples, lex_unique_triples}; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::tuples::exhaustive::{exhaustive_units, lex_unique_pairs}; use std::fmt::Debug; macro_rules! helpers { ($t: ty, $ts: ident, $ts_helper: ident, $ts_small_helper: ident) => { fn $ts_helper(xs: I, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs).take(20).collect_vec(); assert_eq!(ts.as_slice(), out); } fn $ts_small_helper(xs: I, out_len: usize, out: &[$t]) where I::Item: Clone + Debug + Eq, { let ts = $ts(xs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } }; } helpers!( (I::Item, I::Item), lex_unique_pairs, _lex_unique_pairs_helper, lex_unique_pairs_small_helper ); helpers!( (I::Item, I::Item, I::Item), lex_unique_triples, lex_unique_triples_helper, _lex_unique_triples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item), lex_unique_quadruples, _lex_unique_quadruples_helper, lex_unique_quadruples_small_helper ); helpers!( (I::Item, I::Item, I::Item, I::Item, I::Item), lex_unique_quintuples, _lex_unique_quintuples_helper, lex_unique_quintuples_small_helper ); #[test] fn test_lex_unique_tuples() { lex_unique_pairs_small_helper(nevers(), 0, &[]); lex_unique_quintuples_small_helper(nevers(), 0, &[]); lex_unique_pairs_small_helper(exhaustive_units(), 0, &[]); lex_unique_quintuples_small_helper(exhaustive_units(), 0, &[]); lex_unique_pairs_small_helper( exhaustive_unsigneds::(), 65280, &[ (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (0, 12), (0, 13), (0, 14), (0, 15), (0, 16), (0, 17), (0, 18), (0, 19), (0, 20), ], ); lex_unique_triples_helper( exhaustive_unsigneds::(), &[ (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 1, 5), (0, 1, 6), (0, 1, 7), (0, 1, 8), (0, 1, 9), (0, 1, 10), (0, 1, 11), (0, 1, 12), (0, 1, 13), (0, 1, 14), (0, 1, 15), (0, 1, 16), (0, 1, 17), (0, 1, 18), (0, 1, 19), (0, 1, 20), (0, 1, 21), ], ); lex_unique_pairs_small_helper( exhaustive_ascii_chars(), 16256, &[ ('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e'), ('a', 'f'), ('a', 'g'), ('a', 'h'), ('a', 'i'), ('a', 'j'), ('a', 'k'), ('a', 'l'), ('a', 'm'), ('a', 'n'), ('a', 'o'), ('a', 'p'), ('a', 'q'), ('a', 'r'), ('a', 's'), ('a', 't'), ('a', 'u'), ], ); lex_unique_pairs_small_helper(exhaustive_bools(), 2, &[(false, true), (true, false)]); lex_unique_quadruples_small_helper( 1..=6, 360, &[ (1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 3, 6), (1, 2, 4, 3), (1, 2, 4, 5), (1, 2, 4, 6), (1, 2, 5, 3), (1, 2, 5, 4), (1, 2, 5, 6), (1, 2, 6, 3), (1, 2, 6, 4), (1, 2, 6, 5), (1, 3, 2, 4), (1, 3, 2, 5), (1, 3, 2, 6), (1, 3, 4, 2), (1, 3, 4, 5), (1, 3, 4, 6), (1, 3, 5, 2), (1, 3, 5, 4), ], ); } ================================================ FILE: malachite-base/tests/tuples/random/random_custom_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{random_triples_from_single, random_triples_xxy, random_triples_xyx}; use core::hash::Hash; use itertools::Itertools; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::tuples::random::random_pairs_from_single; use std::fmt::Debug; #[allow(clippy::type_complexity)] fn random_triples_xxy_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, expected_values: &[(X, X, Y)], expected_common_values: &[((X, X, Y), usize)], expected_median: ((X, X, Y), Option<(X, X, Y)>), ) { let xs = random_triples_xxy(EXAMPLE_SEED, xs_gen, ys_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_triples_xxy() { random_triples_xxy_helper( &random_primitive_ints::, &random_bools, &[ (85, 11, false), (136, 200, true), (235, 134, false), (203, 223, false), (38, 235, false), (217, 177, true), (162, 32, true), (166, 234, false), (30, 218, false), (90, 106, false), (9, 216, false), (204, 151, true), (213, 97, false), (253, 78, true), (91, 39, false), (191, 175, true), (170, 232, false), (233, 2, true), (35, 22, true), (217, 198, false), ], &[ ((87, 70, false), 23), ((36, 187, false), 23), ((228, 249, false), 22), ((130, 73, true), 20), ((67, 187, true), 20), ((89, 216, true), 20), ((132, 195, true), 20), ((145, 23, false), 20), ((24, 126, false), 20), ((146, 106, false), 20), ], ((127, 197, true), None), ); random_triples_xxy_helper( &|seed| random_pairs_from_single(random_primitive_ints::(seed)), &|seed| random_triples_from_single(random_primitive_ints::(seed)), &[ ((85, 11), (136, 200), (98, -88, -58)), ((235, 134), (203, 223), (40, 20, -4)), ((38, 235), (217, 177), (47, 87, -124)), ((162, 32), (166, 234), (72, 77, 63)), ((30, 218), (90, 106), (91, 108, 127)), ((9, 216), (204, 151), (53, -115, 84)), ((213, 97), (253, 78), (18, 10, 112)), ((91, 39), (191, 175), (-102, 104, 53)), ((170, 232), (233, 2), (75, -18, -107)), ((35, 22), (217, 198), (-66, 51, -109)), ((114, 17), (32, 173), (100, 114, -116)), ((114, 65), (121, 222), (2, 63, -67)), ((173, 25), (144, 148), (-34, 67, 119)), ((79, 115), (52, 73), (0, -33, 5)), ((69, 137), (91, 153), (-20, -24, 50)), ((178, 112), (34, 95), (44, -15, 21)), ((106, 167), (197, 130), (22, 94, 27)), ((168, 122), (207, 172), (-128, -36, 25)), ((177, 86), (150, 221), (-5, -13, 50)), ((218, 101), (115, 74), (-119, -21, 46)), ], &[ (((8, 24), (5, 3), (0, 54, 59)), 1), (((8, 72), (11, 57), (6, 5, 9)), 1), (((80, 9), (9, 5), (84, 9, 10)), 1), (((86, 2), (49, 4), (2, 0, 27)), 1), (((0, 2), (92, 5), (-49, 31, 7)), 1), (((1, 15), (12, 5), (51, 5, 47)), 1), (((1, 25), (3, 66), (70, 65, 7)), 1), (((1, 72), (2, 1), (8, 49, -10)), 1), (((1, 82), (6, 26), (86, 3, 70)), 1), (((1, 85), (14, 92), (3, 5, 53)), 1), ], ( ((128, 20), (243, 155), (-90, 7, -77)), Some(((128, 21), (19, 63), (52, 113, -21))), ), ); } #[allow(clippy::type_complexity)] fn random_triples_xyx_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, expected_values: &[(X, Y, X)], expected_common_values: &[((X, Y, X), usize)], expected_median: ((X, Y, X), Option<(X, Y, X)>), ) { let xs = random_triples_xyx(EXAMPLE_SEED, xs_gen, ys_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_triples_xyx() { random_triples_xyx_helper( &random_primitive_ints::, &random_bools, &[ (85, false, 11), (136, true, 200), (235, false, 134), (203, false, 223), (38, false, 235), (217, true, 177), (162, true, 32), (166, false, 234), (30, false, 218), (90, false, 106), (9, false, 216), (204, true, 151), (213, false, 97), (253, true, 78), (91, false, 39), (191, true, 175), (170, false, 232), (233, true, 2), (35, true, 22), (217, false, 198), ], &[ ((87, false, 70), 23), ((36, false, 187), 23), ((228, false, 249), 22), ((130, true, 73), 20), ((67, true, 187), 20), ((89, true, 216), 20), ((132, true, 195), 20), ((145, false, 23), 20), ((24, false, 126), 20), ((146, false, 106), 20), ], ((127, true, 141), None), ); random_triples_xyx_helper( &|seed| random_pairs_from_single(random_primitive_ints::(seed)), &|seed| random_triples_from_single(random_primitive_ints::(seed)), &[ ((85, 11), (98, -88, -58), (136, 200)), ((235, 134), (40, 20, -4), (203, 223)), ((38, 235), (47, 87, -124), (217, 177)), ((162, 32), (72, 77, 63), (166, 234)), ((30, 218), (91, 108, 127), (90, 106)), ((9, 216), (53, -115, 84), (204, 151)), ((213, 97), (18, 10, 112), (253, 78)), ((91, 39), (-102, 104, 53), (191, 175)), ((170, 232), (75, -18, -107), (233, 2)), ((35, 22), (-66, 51, -109), (217, 198)), ((114, 17), (100, 114, -116), (32, 173)), ((114, 65), (2, 63, -67), (121, 222)), ((173, 25), (-34, 67, 119), (144, 148)), ((79, 115), (0, -33, 5), (52, 73)), ((69, 137), (-20, -24, 50), (91, 153)), ((178, 112), (44, -15, 21), (34, 95)), ((106, 167), (22, 94, 27), (197, 130)), ((168, 122), (-128, -36, 25), (207, 172)), ((177, 86), (-5, -13, 50), (150, 221)), ((218, 101), (-119, -21, 46), (115, 74)), ], &[ (((8, 24), (0, 54, 59), (5, 3)), 1), (((8, 72), (6, 5, 9), (11, 57)), 1), (((80, 9), (84, 9, 10), (9, 5)), 1), (((86, 2), (2, 0, 27), (49, 4)), 1), (((0, 2), (-49, 31, 7), (92, 5)), 1), (((1, 15), (51, 5, 47), (12, 5)), 1), (((1, 25), (70, 65, 7), (3, 66)), 1), (((1, 72), (8, 49, -10), (2, 1)), 1), (((1, 82), (86, 3, 70), (6, 26)), 1), (((1, 85), (3, 5, 53), (14, 92)), 1), ], ( ((128, 20), (118, 50, 18), (55, 110)), Some(((128, 21), (-107, 66, -82), (216, 142))), ), ); } ================================================ FILE: malachite-base/tests/tuples/random/random_ordered_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::random_ordered_unique_triples; use core::hash::Hash; use itertools::Itertools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::tuples::random::random_ordered_unique_pairs; use std::fmt::Debug; #[allow(clippy::type_complexity)] fn random_ordered_unique_pairs_helper( xs: I, expected_values: &[(I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item), usize)], expected_median: ((I::Item, I::Item), Option<(I::Item, I::Item)>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_ordered_unique_pairs(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[allow(clippy::type_complexity)] fn random_ordered_unique_triples_helper( xs: I, expected_values: &[(I::Item, I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item, I::Item), usize)], expected_median: ( (I::Item, I::Item, I::Item), Option<(I::Item, I::Item, I::Item)>, ), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_ordered_unique_triples(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_ordered_unique_tuples() { random_ordered_unique_triples_helper( random_primitive_ints::(EXAMPLE_SEED), &[ (69, 113, 239), (108, 210, 228), (87, 161, 168), (32, 83, 110), (34, 89, 188), (93, 200, 238), (115, 149, 189), (149, 201, 217), (31, 117, 146), (72, 151, 169), (7, 33, 174), (38, 81, 144), (72, 113, 127), (107, 128, 233), (12, 46, 119), (18, 164, 243), (59, 114, 174), (39, 174, 247), (104, 160, 184), (37, 100, 252), ], &[ ((57, 142, 207), 7), ((32, 68, 169), 6), ((36, 70, 195), 6), ((125, 168, 194), 6), ((0, 97, 205), 5), ((2, 33, 227), 5), ((5, 46, 239), 5), ((9, 68, 189), 5), ((9, 78, 240), 5), ((1, 110, 203), 5), ], ((52, 133, 241), Some((52, 133, 242))), ); random_ordered_unique_pairs_helper( random_ordered_unique_pairs(random_primitive_ints::(EXAMPLE_SEED)), &[ ((69, 108), (113, 239)), ((161, 168), (210, 228)), ((32, 87), (83, 110)), ((34, 188), (89, 238)), ((93, 200), (115, 149)), ((149, 189), (201, 217)), ((31, 72), (117, 146)), ((33, 174), (151, 169)), ((7, 38), (81, 144)), ((72, 127), (113, 128)), ((46, 119), (107, 233)), ((12, 18), (164, 243)), ((59, 247), (114, 174)), ((39, 174), (160, 184)), ((37, 104), (100, 252)), ((69, 107), (122, 228)), ((142, 179), (242, 248)), ((61, 189), (233, 239)), ((7, 192), (85, 235)), ((90, 200), (178, 185)), ], &[ (((0, 78), (34, 52)), 2), (((1, 58), (6, 112)), 2), (((1, 63), (8, 154)), 2), (((1, 97), (7, 250)), 2), (((2, 33), (40, 81)), 2), (((3, 160), (7, 29)), 2), (((3, 32), (12, 60)), 2), (((6, 130), (7, 20)), 2), (((6, 68), (7, 126)), 2), (((6, 77), (36, 54)), 2), ], (((40, 193), (94, 142)), Some(((40, 193), (97, 243)))), ); } ================================================ FILE: malachite-base/tests/tuples/random/random_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::{random_triples, random_triples_from_single}; use core::hash::Hash; use itertools::Itertools; use malachite_base::bools::random::random_bools; use malachite_base::chars::random::random_ascii_chars; use malachite_base::num::random::geometric::geometric_random_signeds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::tuples::random::{random_pairs, random_pairs_from_single}; use malachite_base::tuples::singletons; use std::fmt::Debug; fn random_pairs_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, expected_values: &[(X, Y)], expected_common_values: &[((X, Y), usize)], expected_median: ((X, Y), Option<(X, Y)>), ) { let xs = random_pairs(EXAMPLE_SEED, xs_gen, ys_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_pairs() { random_pairs_helper( &random_primitive_ints::, &random_bools, &[ (85, false), (11, true), (136, false), (200, false), (235, false), (134, true), (203, true), (223, false), (38, false), (235, false), (217, false), (177, true), (162, false), (32, true), (166, false), (234, true), (30, false), (218, true), (90, true), (106, false), ], &[ ((81, true), 2077), ((58, false), 2074), ((220, false), 2064), ((14, false), 2053), ((194, true), 2050), ((66, false), 2050), ((71, true), 2049), ((208, false), 2043), ((7, true), 2041), ((64, true), 2038), ], ((127, true), None), ); random_pairs_helper( &|seed| random_pairs_from_single(random_primitive_ints::(seed)), &|seed| random_triples_from_single(random_primitive_ints::(seed)), &[ ((85, 11), (98, -88, -58)), ((136, 200), (40, 20, -4)), ((235, 134), (47, 87, -124)), ((203, 223), (72, 77, 63)), ((38, 235), (91, 108, 127)), ((217, 177), (53, -115, 84)), ((162, 32), (18, 10, 112)), ((166, 234), (-102, 104, 53)), ((30, 218), (75, -18, -107)), ((90, 106), (-66, 51, -109)), ((9, 216), (100, 114, -116)), ((204, 151), (2, 63, -67)), ((213, 97), (-34, 67, 119)), ((253, 78), (0, -33, 5)), ((91, 39), (-20, -24, 50)), ((191, 175), (44, -15, 21)), ((170, 232), (22, 94, 27)), ((233, 2), (-128, -36, 25)), ((35, 22), (-5, -13, 50)), ((217, 198), (-119, -21, 46)), ], &[ (((0, 5), (6, 7, 42)), 1), (((8, 8), (18, 5, 6)), 1), (((9, 1), (5, 3, 23)), 1), (((0, 0), (97, 7, 73)), 1), (((0, 2), (12, 20, 6)), 1), (((0, 99), (20, 8, 6)), 1), (((1, 81), (3, 21, 3)), 1), (((1, 83), (-6, 8, 8)), 1), (((1, 9), (-37, 9, 7)), 1), (((1, 9), (4, 95, 15)), 1), ], ( ((127, 197), (-18, 55, -20)), Some(((127, 197), (-8, -68, 49))), ), ); } #[allow(clippy::type_complexity)] fn random_triples_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, Z: Clone + Debug + Eq + Hash + Ord, K: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, zs_gen: &dyn Fn(Seed) -> K, expected_values: &[(X, Y, Z)], expected_common_values: &[((X, Y, Z), usize)], expected_median: ((X, Y, Z), Option<(X, Y, Z)>), ) { let xs = random_triples(EXAMPLE_SEED, xs_gen, ys_gen, zs_gen); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_triples() { random_triples_helper( &random_primitive_ints::, &random_ascii_chars, &|seed| geometric_random_signeds::(seed, 10, 1), &[ (85, 'b', 0), (11, 'P', -6), (136, '\u{1a}', -6), (200, 'F', 8), (235, 'B', 0), (134, '\u{2}', -3), (203, '\u{7f}', -17), (223, '\u{17}', 2), (38, 'W', 0), (235, '\u{8}', 2), (217, '\"', 9), (177, 'j', -6), (162, 't', 20), (32, 'g', -20), (166, '\u{16}', 43), (234, '6', 9), (30, '\u{7f}', -7), (218, 'j', -16), (90, '4', -29), (106, '$', -2), ], &[ ((54, '*', -1), 9), ((252, '\u{c}', 0), 9), ((253, '\u{6}', 0), 9), ((4, '~', 0), 8), ((51, '1', 1), 8), ((131, '!', 1), 8), ((138, 'i', 1), 8), ((185, 'q', 1), 8), ((58, '?', -2), 8), ((225, 'k', -4), 8), ], ((127, 'x', -2), None), ); random_triples_helper( &|seed| singletons(random_bools(seed)), &|seed| random_pairs_from_single(random_primitive_ints::(seed)), &|seed| random_triples_from_single(random_ascii_chars(seed)), &[ ((true,), (98, 168), ('(', '\u{15}', 'h')), ((false,), (198, 40), ('\u{7f}', '%', '\u{7f}')), ((true,), (20, 252), ('\u{13}', '\u{2}', '+')), ((false,), (47, 87), ('\u{1b}', 'v', '\r')), ((true,), (132, 72), ('\u{1b}', '\u{15}', 'I')), ((false,), (77, 63), ('$', '\u{1a}', '}')), ((true,), (91, 108), ('(', '\u{e}', '1')), ((false,), (127, 53), ('$', '/', 'O')), ((true,), (141, 84), ('\u{1f}', 'Z', '>')), ((true,), (18, 10), ('}', '\u{13}', '\\')), ((false,), (112, 154), ('\u{1a}', '\u{14}', 't')), ((true,), (104, 53), (' ', '`', '\u{2}')), ((false,), (75, 238), ('\u{17}', 'a', '8')), ((false,), (149, 190), ('H', ']', '*')), ((false,), (51, 147), ('i', '2', '}')), ((false,), (100, 114), ('\u{3}', '\u{f}', '\u{7f}')), ((false,), (140, 2), ('\u{f}', 'Y', 'D')), ((false,), (63, 189), ('m', '\\', '8')), ((false,), (222, 67), ('M', '\u{7}', '8')), ((true,), (119, 0), ('\u{13}', '.', '\"')), ], &[ (((true,), (57, 9), ('R', '}', 'Q')), 2), (((true,), (233, 229), ('t', '\u{b}', 'Q')), 2), (((false,), (236, 203), ('b', '\u{e}', '\u{e}')), 2), (((true,), (0, 0), ('{', '{', '4')), 1), (((true,), (0, 2), ('-', 'S', '{')), 1), (((true,), (0, 2), ('N', 'E', '-')), 1), (((true,), (0, 2), ('O', '3', 'S')), 1), (((true,), (0, 3), ('"', '/', 'P')), 1), (((true,), (0, 3), (';', 'M', 'W')), 1), (((true,), (0, 3), ('i', ']', 'P')), 1), ], ( ((false,), (255, 175), ('g', '\u{1e}', '4')), Some(((false,), (255, 176), ('\u{10}', 's', '\''))), ), ); } ================================================ FILE: malachite-base/tests/tuples/random/random_tuples_from_single.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::random_triples_from_single; use core::hash::Hash; use itertools::Itertools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::tuples::random::random_pairs_from_single; use std::fmt::Debug; #[allow(clippy::type_complexity)] fn random_pairs_from_single_helper( xs: I, expected_values: &[(I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item), usize)], expected_median: ((I::Item, I::Item), Option<(I::Item, I::Item)>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_pairs_from_single(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[allow(clippy::type_complexity)] fn random_triples_from_single_helper( xs: I, expected_values: &[(I::Item, I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item, I::Item), usize)], expected_median: ( (I::Item, I::Item, I::Item), Option<(I::Item, I::Item, I::Item)>, ), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_triples_from_single(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_tuples_from_single() { random_triples_from_single_helper( random_primitive_ints::(EXAMPLE_SEED), &[ (113, 239, 69), (108, 228, 210), (168, 161, 87), (32, 110, 83), (188, 34, 89), (238, 93, 200), (149, 115, 189), (149, 217, 201), (117, 146, 31), (72, 151, 169), (174, 33, 7), (38, 81, 144), (72, 127, 113), (128, 233, 107), (46, 119, 12), (18, 164, 243), (114, 174, 59), (247, 39, 174), (160, 184, 104), (37, 100, 252), ], &[ ((222, 60, 79), 4), ((26, 110, 13), 4), ((41, 254, 55), 4), ((109, 134, 76), 4), ((165, 174, 73), 4), ((236, 57, 174), 4), ((73, 168, 192), 4), ((89, 197, 244), 4), ((91, 170, 115), 4), ((142, 168, 231), 4), ], ((127, 253, 76), Some((127, 253, 86))), ); random_pairs_from_single_helper( random_pairs_from_single(random_primitive_ints::(EXAMPLE_SEED)), &[ ((113, 239), (69, 108)), ((228, 210), (168, 161)), ((87, 32), (110, 83)), ((188, 34), (89, 238)), ((93, 200), (149, 115)), ((189, 149), (217, 201)), ((117, 146), (31, 72)), ((151, 169), (174, 33)), ((7, 38), (81, 144)), ((72, 127), (113, 128)), ((233, 107), (46, 119)), ((12, 18), (164, 243)), ((114, 174), (59, 247)), ((39, 174), (160, 184)), ((104, 37), (100, 252)), ((228, 122), (107, 69)), ((242, 248), (179, 142)), ((239, 233), (61, 189)), ((235, 85), (192, 7)), ((200, 90), (185, 178)), ], &[ (((28, 96), (0, 11)), 2), (((2, 43), (64, 233)), 2), (((20, 33), (14, 10)), 2), (((223, 84), (7, 22)), 2), (((43, 33), (131, 6)), 2), (((6, 233), (45, 89)), 2), (((65, 26), (6, 146)), 2), (((71, 80), (68, 88)), 2), (((9, 85), (186, 55)), 2), (((96, 254), (9, 37)), 2), ], (((127, 243), (125, 130)), Some(((127, 243), (134, 100)))), ); } ================================================ FILE: malachite-base/tests/tuples/random/random_unique_tuples.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::random_unique_triples; use core::hash::Hash; use itertools::Itertools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::tuples::random::random_unique_pairs; use std::fmt::Debug; #[allow(clippy::type_complexity)] fn random_unique_pairs_helper( xs: I, expected_values: &[(I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item), usize)], expected_median: ((I::Item, I::Item), Option<(I::Item, I::Item)>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_unique_pairs(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[allow(clippy::type_complexity)] fn random_unique_triples_helper( xs: I, expected_values: &[(I::Item, I::Item, I::Item)], expected_common_values: &[((I::Item, I::Item, I::Item), usize)], expected_median: ( (I::Item, I::Item, I::Item), Option<(I::Item, I::Item, I::Item)>, ), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { let xs = random_unique_triples(xs); let values = xs.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, xs.clone()); let median = median(xs.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_unique_tuples() { random_unique_triples_helper( random_primitive_ints::(EXAMPLE_SEED), &[ (113, 239, 69), (108, 228, 210), (168, 161, 87), (32, 110, 83), (188, 34, 89), (238, 93, 200), (149, 115, 189), (149, 217, 201), (117, 146, 31), (72, 151, 169), (174, 33, 7), (38, 81, 144), (72, 127, 113), (128, 233, 107), (46, 119, 12), (18, 164, 243), (114, 174, 59), (247, 39, 174), (160, 184, 104), (37, 100, 252), ], &[ ((205, 0, 97), 4), ((102, 18, 19), 4), ((105, 70, 13), 4), ((22, 45, 192), 4), ((87, 100, 26), 4), ((15, 107, 109), 4), ((134, 245, 157), 4), ((138, 164, 179), 4), ((219, 253, 196), 4), ((237, 197, 239), 4), ], ((128, 16, 107), Some((128, 16, 116))), ); random_unique_pairs_helper( random_unique_pairs(random_primitive_ints::(EXAMPLE_SEED)), &[ ((113, 239), (69, 108)), ((228, 210), (168, 161)), ((87, 32), (110, 83)), ((188, 34), (89, 238)), ((93, 200), (149, 115)), ((189, 149), (217, 201)), ((117, 146), (31, 72)), ((151, 169), (174, 33)), ((7, 38), (81, 144)), ((72, 127), (113, 128)), ((233, 107), (46, 119)), ((12, 18), (164, 243)), ((114, 174), (59, 247)), ((39, 174), (160, 184)), ((104, 37), (100, 252)), ((228, 122), (107, 69)), ((242, 248), (179, 142)), ((239, 233), (61, 189)), ((235, 85), (192, 7)), ((200, 90), (185, 178)), ], &[ (((60, 12), (3, 32)), 2), (((0, 80), (88, 210)), 2), (((1, 3), (216, 183)), 2), (((159, 0), (69, 30)), 2), (((199, 6), (95, 79)), 2), (((2, 98), (221, 19)), 2), (((212, 65), (99, 2)), 2), (((3, 14), (61, 170)), 2), (((41, 155), (3, 72)), 2), (((47, 85), (69, 66)), 2), ], (((128, 41), (252, 44)), Some(((128, 42), (8, 241)))), ); } ================================================ FILE: malachite-base/tests/tuples/random/random_units.rs ================================================ // Copyright © 2026 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::tuples::random::random_units; #[test] fn test_random_units() { assert_eq!(random_units().take(20).collect_vec(), &[(); 20]); } ================================================ FILE: malachite-base/tests/tuples/singletons.rs ================================================ // Copyright © 2026 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::nevers::Never; use malachite_base::tuples::singletons; use std::fmt::Debug; fn singletons_helper(xs: &[T], out: &[(T,)]) { assert_eq!(singletons(xs.iter().cloned()).collect_vec().as_slice(), out); } #[test] fn test_singletons() { singletons_helper::(&[], &[]); singletons_helper(&[5], &[(5,)]); singletons_helper(&[1, 2, 3], &[(1,), (2,), (3,)]); singletons_helper(&[(2,), (1,), (5,)], &[((2,),), ((1,),), ((5,),)]); } ================================================ FILE: malachite-base/tests/unions/clone.rs ================================================ // Copyright © 2026 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 malachite_base::unions::Union2; #[allow(clippy::redundant_clone)] #[test] fn test_clone() { let test = |u: Union2, u32>| { let cloned = u.clone(); assert_eq!(cloned, u); }; test(Union2::A(vec![])); test(Union2::A(vec!['a', 'b', 'c'])); test(Union2::B(5)); } #[test] fn test_clone_from() { let test = |mut u: Union2, u32>, v: Union2, u32>| { u.clone_from(&v); assert_eq!(u, v); }; test(Union2::A(vec!['a', 'b', 'c']), Union2::A(vec![])); test(Union2::A(vec![]), Union2::A(vec!['a', 'b', 'c'])); test(Union2::B(5), Union2::B(6)); test(Union2::A(vec!['a', 'b', 'c']), Union2::B(6)); test(Union2::B(6), Union2::A(vec!['a', 'b', 'c'])); } ================================================ FILE: malachite-base/tests/unions/debug.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToDebugString; use malachite_base::unions::Union2; #[test] fn test_to_debug() { let test = |u: Union2, u32>, out| { assert_eq!(u.to_debug_string(), out); }; test(Union2::A(vec![]), "A([])"); test(Union2::A(vec!['a', 'b', 'c']), "A(['a', 'b', 'c'])"); test(Union2::B(5), "B(5)"); } ================================================ FILE: malachite-base/tests/unions/display.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; #[test] fn test_to_string() { let test = |u: Union3, out| { assert_eq!(u.to_string(), out); }; test(Union3::A('a'), "A(a)"); test(Union3::B(5), "B(5)"); test(Union3::C(false), "C(false)"); } ================================================ FILE: malachite-base/tests/unions/eq.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use malachite_base::test_util::common::test_eq_helper; #[test] fn test_eq() { test_eq_helper::>(&[ "B(8)", "A(d)", "C(true)", "B(5)", "C(false)", "A(a)", ]); } ================================================ FILE: malachite-base/tests/unions/exhaustive/exhaustive_unions.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use crate::extra_variadic::exhaustive_union3s; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::options::exhaustive::exhaustive_somes; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::unions::Union2; use malachite_base::unions::exhaustive::exhaustive_union2s; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; fn exhaustive_union2s_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[Union2], ) { let us = exhaustive_union2s(xs, ys); let us_prefix = us.clone().take(20).collect_vec(); assert_eq!(us_prefix.as_slice(), out); assert_eq!(us.count(), out_len); } #[test] fn test_exhaustive_union2s() { exhaustive_union2s_helper(nevers(), nevers(), 0, &[]); exhaustive_union2s_helper( nevers(), 0..4, 4, &[Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3)], ); exhaustive_union2s_helper(once('a'), once(1), 2, &[Union2::A('a'), Union2::B(1)]); exhaustive_union2s_helper( once('a'), 0..4, 5, &[Union2::A('a'), Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3)], ); exhaustive_union2s_helper( 'a'..'e', exhaustive_unsigneds::(), 260, &[ Union2::A('a'), Union2::B(0), Union2::A('b'), Union2::B(1), Union2::A('c'), Union2::B(2), Union2::A('d'), Union2::B(3), Union2::B(4), Union2::B(5), Union2::B(6), Union2::B(7), Union2::B(8), Union2::B(9), Union2::B(10), Union2::B(11), Union2::B(12), Union2::B(13), Union2::B(14), Union2::B(15), ], ); exhaustive_union2s_helper( exhaustive_bools(), 0..4, 6, &[ Union2::A(false), Union2::B(0), Union2::A(true), Union2::B(1), Union2::B(2), Union2::B(3), ], ); exhaustive_union2s_helper( 'a'..'f', 0..3, 8, &[ Union2::A('a'), Union2::B(0), Union2::A('b'), Union2::B(1), Union2::A('c'), Union2::B(2), Union2::A('d'), Union2::A('e'), ], ); exhaustive_union2s_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 6, &[ Union2::A('a'), Union2::B(Equal), Union2::A('b'), Union2::B(Less), Union2::A('c'), Union2::B(Greater), ], ); } fn exhaustive_union3s_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, Z: Clone + Debug + Eq, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[Union3], ) { let ts = exhaustive_union3s(xs, ys, zs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } #[test] fn test_exhaustive_union3s() { exhaustive_union3s_helper(nevers(), nevers(), nevers(), 0, &[]); exhaustive_union3s_helper( nevers(), 0..4, 'a'..'f', 9, &[ Union3::B(0), Union3::C('a'), Union3::B(1), Union3::C('b'), Union3::B(2), Union3::C('c'), Union3::B(3), Union3::C('d'), Union3::C('e'), ], ); exhaustive_union3s_helper( once('a'), once(false), once(5), 3, &[Union3::A('a'), Union3::B(false), Union3::C(5)], ); exhaustive_union3s_helper( once('a'), once(false), 0..4, 6, &[Union3::A('a'), Union3::B(false), Union3::C(0), Union3::C(1), Union3::C(2), Union3::C(3)], ); exhaustive_union3s_helper( exhaustive_bools(), 0..3, 'a'..'d', 8, &[ Union3::A(false), Union3::B(0), Union3::C('a'), Union3::A(true), Union3::B(1), Union3::C('b'), Union3::B(2), Union3::C('c'), ], ); exhaustive_union3s_helper( 0..11, exhaustive_somes(0..12), 'a'..'n', 36, &[ Union3::A(0), Union3::B(Some(0)), Union3::C('a'), Union3::A(1), Union3::B(Some(1)), Union3::C('b'), Union3::A(2), Union3::B(Some(2)), Union3::C('c'), Union3::A(3), Union3::B(Some(3)), Union3::C('d'), Union3::A(4), Union3::B(Some(4)), Union3::C('e'), Union3::A(5), Union3::B(Some(5)), Union3::C('f'), Union3::A(6), Union3::B(Some(6)), ], ); exhaustive_union3s_helper( ['a', 'b', 'c'].iter().copied(), ["xx", "yy", "zz"].iter().copied(), 0..3, 9, &[ Union3::A('a'), Union3::B("xx"), Union3::C(0), Union3::A('b'), Union3::B("yy"), Union3::C(1), Union3::A('c'), Union3::B("zz"), Union3::C(2), ], ); } ================================================ FILE: malachite-base/tests/unions/exhaustive/lex_unions.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use crate::extra_variadic::lex_union3s; use itertools::Itertools; use malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::options::exhaustive::exhaustive_somes; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::unions::Union2; use malachite_base::unions::exhaustive::lex_union2s; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::once; fn lex_union2s_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[Union2], ) { let us = lex_union2s(xs, ys); let us_prefix = us.clone().take(20).collect_vec(); assert_eq!(us_prefix.as_slice(), out); assert_eq!(us.count(), out_len); } #[test] fn test_lex_union2s() { lex_union2s_helper(nevers(), nevers(), 0, &[]); lex_union2s_helper( nevers(), 0..4, 4, &[Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3)], ); lex_union2s_helper(once('a'), once(1), 2, &[Union2::A('a'), Union2::B(1)]); lex_union2s_helper( once('a'), 0..4, 5, &[Union2::A('a'), Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3)], ); lex_union2s_helper( 'a'..'e', exhaustive_unsigneds::(), 260, &[ Union2::A('a'), Union2::A('b'), Union2::A('c'), Union2::A('d'), Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3), Union2::B(4), Union2::B(5), Union2::B(6), Union2::B(7), Union2::B(8), Union2::B(9), Union2::B(10), Union2::B(11), Union2::B(12), Union2::B(13), Union2::B(14), Union2::B(15), ], ); lex_union2s_helper( exhaustive_bools(), 0..4, 6, &[ Union2::A(false), Union2::A(true), Union2::B(0), Union2::B(1), Union2::B(2), Union2::B(3), ], ); lex_union2s_helper( 'a'..'f', 0..3, 8, &[ Union2::A('a'), Union2::A('b'), Union2::A('c'), Union2::A('d'), Union2::A('e'), Union2::B(0), Union2::B(1), Union2::B(2), ], ); lex_union2s_helper( ['a', 'b', 'c'].iter().copied(), exhaustive_orderings(), 6, &[ Union2::A('a'), Union2::A('b'), Union2::A('c'), Union2::B(Equal), Union2::B(Less), Union2::B(Greater), ], ); } fn lex_union3s_helper< X: Clone + Debug + Eq, I: Clone + Iterator, Y: Clone + Debug + Eq, J: Clone + Iterator, Z: Clone + Debug + Eq, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[Union3], ) { let ts = lex_union3s(xs, ys, zs); let ts_prefix = ts.clone().take(20).collect_vec(); assert_eq!(ts_prefix.as_slice(), out); assert_eq!(ts.count(), out_len); } #[test] fn test_lex_union3s() { lex_union3s_helper(nevers(), nevers(), nevers(), 0, &[]); lex_union3s_helper( nevers(), 0..4, 'a'..'f', 9, &[ Union3::B(0), Union3::B(1), Union3::B(2), Union3::B(3), Union3::C('a'), Union3::C('b'), Union3::C('c'), Union3::C('d'), Union3::C('e'), ], ); lex_union3s_helper( once('a'), once(false), once(5), 3, &[Union3::A('a'), Union3::B(false), Union3::C(5)], ); lex_union3s_helper( once('a'), once(false), 0..4, 6, &[Union3::A('a'), Union3::B(false), Union3::C(0), Union3::C(1), Union3::C(2), Union3::C(3)], ); lex_union3s_helper( exhaustive_bools(), 0..3, 'a'..'d', 8, &[ Union3::A(false), Union3::A(true), Union3::B(0), Union3::B(1), Union3::B(2), Union3::C('a'), Union3::C('b'), Union3::C('c'), ], ); lex_union3s_helper( 0..11, exhaustive_somes(0..12), 'a'..'n', 36, &[ Union3::A(0), Union3::A(1), Union3::A(2), Union3::A(3), Union3::A(4), Union3::A(5), Union3::A(6), Union3::A(7), Union3::A(8), Union3::A(9), Union3::A(10), Union3::B(Some(0)), Union3::B(Some(1)), Union3::B(Some(2)), Union3::B(Some(3)), Union3::B(Some(4)), Union3::B(Some(5)), Union3::B(Some(6)), Union3::B(Some(7)), Union3::B(Some(8)), ], ); lex_union3s_helper( ['a', 'b', 'c'].iter().copied(), ["xx", "yy", "zz"].iter().copied(), 0..3, 9, &[ Union3::A('a'), Union3::A('b'), Union3::A('c'), Union3::B("xx"), Union3::B("yy"), Union3::B("zz"), Union3::C(0), Union3::C(1), Union3::C(2), ], ); } ================================================ FILE: malachite-base/tests/unions/from_str.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use malachite_base::unions::UnionFromStrError; use std::result::Result; use std::str::FromStr; #[test] fn test_from_str() { let test = |s, out| { assert_eq!(Union3::from_str(s), out); }; test("A(a)", Ok(Union3::A('a'))); test("B(5)", Ok(Union3::B(5))); test("C(false)", Ok(Union3::C(false))); test("", Err(UnionFromStrError::Generic(String::new()))); test("xyz", Err(UnionFromStrError::Generic("xyz".to_string()))); test("D(a)", Err(UnionFromStrError::Generic("D(a)".to_string()))); test("A(a", Err(UnionFromStrError::Generic("A(a".to_string()))); let result: Result, _> = Union3::from_str("A(ab)"); if let Err(UnionFromStrError::Specific(Union3::A(_e))) = result { } else { panic!("wrong error variant") } let result: Result, _> = Union3::from_str("B(-1)"); if let Err(UnionFromStrError::Specific(Union3::B(_e))) = result { } else { panic!("wrong error variant") } let result: Result, _> = Union3::from_str("C(tralse)"); if let Err(UnionFromStrError::Specific(Union3::C(_e))) = result { } else { panic!("wrong error variant") } } ================================================ FILE: malachite-base/tests/unions/ord.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use malachite_base::test_util::common::test_cmp_helper; #[test] fn test_cmp() { test_cmp_helper::>(&[ "A(a)", "A(d)", "B(5)", "B(8)", "C(false)", "C(true)", ]); } ================================================ FILE: malachite-base/tests/unions/random/random_unions.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; use crate::extra_variadic::random_union3s; use core::hash::Hash; use itertools::Itertools; use malachite_base::bools::random::random_bools; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_unsigned_inclusive_range; use malachite_base::orderings::random::random_orderings; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::strings::random::random_strings_using_chars; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::unions::Union2; use malachite_base::unions::random::random_union2s; use std::cmp::Ordering::*; use std::fmt::Debug; fn random_union2s_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, expected_values: &[Union2], expected_common_values: &[(Union2, usize)], expected_median: (Union2, Option>), ) { let us = random_union2s(EXAMPLE_SEED, xs_gen, ys_gen); let values = us.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, us.clone()); let median = median(us.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_union2s() { random_union2s_helper( &|seed| random_char_inclusive_range(seed, 'a', 'z'), &|seed| random_unsigned_inclusive_range::(seed, 1, 10), &[ Union2::A('v'), Union2::B(3), Union2::A('c'), Union2::A('q'), Union2::A('i'), Union2::A('e'), Union2::A('p'), Union2::A('g'), Union2::A('s'), Union2::B(7), Union2::A('n'), Union2::A('t'), Union2::B(9), Union2::A('m'), Union2::A('z'), Union2::B(7), Union2::B(9), Union2::A('o'), Union2::A('m'), Union2::B(3), ], &[ (Union2::B(5), 50535), (Union2::B(4), 50190), (Union2::B(10), 50183), (Union2::B(3), 50068), (Union2::B(9), 50064), (Union2::B(6), 50002), (Union2::B(2), 49882), (Union2::B(1), 49807), (Union2::B(7), 49533), (Union2::B(8), 49495), ], (Union2::A('z'), None), ); random_union2s_helper( &random_bools, &|seed| geometric_random_unsigneds::(seed, 4, 1), &[ Union2::A(true), Union2::B(6), Union2::A(false), Union2::A(true), Union2::A(false), Union2::A(true), Union2::A(false), Union2::A(true), Union2::A(false), Union2::B(0), Union2::A(true), Union2::A(true), Union2::B(2), Union2::A(false), Union2::A(true), Union2::B(2), Union2::B(2), Union2::A(false), Union2::A(false), Union2::B(8), ], &[ (Union2::A(false), 250462), (Union2::A(true), 249779), (Union2::B(0), 100190), (Union2::B(1), 79510), (Union2::B(2), 63929), (Union2::B(3), 51260), (Union2::B(4), 41099), (Union2::B(5), 32494), (Union2::B(6), 26037), (Union2::B(7), 21139), ], (Union2::A(true), None), ); } #[allow(clippy::type_complexity)] fn random_union3s_helper< X: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, Y: Clone + Debug + Eq + Hash + Ord, J: Clone + Iterator, Z: Clone + Debug + Eq + Hash + Ord, K: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, zs_gen: &dyn Fn(Seed) -> K, expected_values: &[Union3], expected_common_values: &[(Union3, usize)], expected_median: (Union3, Option>), ) { let us = random_union3s(EXAMPLE_SEED, xs_gen, ys_gen, zs_gen); let values = us.clone().take(20).collect_vec(); let common_values = common_values_map_debug(1000000, 10, us.clone()); let median = median(us.take(1000000)); assert_eq!( (values.as_slice(), common_values.as_slice(), median), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_union3s() { random_union3s_helper( &|seed| random_char_inclusive_range(seed, 'a', 'z'), &|seed| random_unsigned_inclusive_range::(seed, 1, 10), &random_orderings, &[ Union3::C(Equal), Union3::A('v'), Union3::A('c'), Union3::A('q'), Union3::C(Greater), Union3::A('i'), Union3::B(3), Union3::C(Greater), Union3::B(7), Union3::C(Greater), Union3::C(Greater), Union3::C(Greater), Union3::B(9), Union3::C(Equal), Union3::A('e'), Union3::A('p'), Union3::A('g'), Union3::A('s'), Union3::C(Equal), Union3::A('n'), ], &[ (Union3::C(Less), 111378), (Union3::C(Greater), 111191), (Union3::C(Equal), 110903), (Union3::B(5), 33724), (Union3::B(10), 33503), (Union3::B(4), 33375), (Union3::B(9), 33348), (Union3::B(2), 33347), (Union3::B(6), 33288), (Union3::B(7), 33283), ], (Union3::B(5), None), ); random_union3s_helper( &random_bools, &|seed| geometric_random_unsigneds::(seed, 4, 1), &|seed| { random_strings_using_chars( seed, &|seed_2| random_char_inclusive_range(seed_2, 'a', 'z'), 4, 1, ) }, &[ Union3::C("qvfm".to_string()), Union3::A(true), Union3::A(false), Union3::A(true), Union3::C("kt".to_string()), Union3::A(false), Union3::B(6), Union3::C("auqoox".to_string()), Union3::B(0), Union3::C("ak".to_string()), Union3::C("".to_string()), Union3::C("dz".to_string()), Union3::B(2), Union3::C("ebaq".to_string()), Union3::A(true), Union3::A(false), Union3::A(true), Union3::A(false), Union3::C("gvqmloscuftfzjrn".to_string()), Union3::A(true), ], &[ (Union3::A(false), 166833), (Union3::A(true), 166495), (Union3::B(0), 66610), (Union3::C("".to_string()), 66483), (Union3::B(1), 53004), (Union3::B(2), 42754), (Union3::B(3), 34312), (Union3::B(4), 27360), (Union3::B(5), 21599), (Union3::B(6), 17332), ], (Union3::B(3), None), ); } ================================================ FILE: malachite-base/tests/unions/unwrap.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::Union3; #[test] fn test_unwrap() { let test = |u: Union3, out| { assert_eq!(u.unwrap(), out); }; test(Union3::A('a'), 'a'); test(Union3::B('b'), 'b'); test(Union3::C('c'), 'c'); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_combined_k_compositions.rs ================================================ // Copyright © 2026 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::vecs::exhaustive::exhaustive_combined_k_compositions; fn exhaustive_combined_k_compositions_helper( n_min: usize, n_max: usize, k: usize, out: &[&[usize]], ) { let xss = exhaustive_combined_k_compositions(n_min, n_max, k).collect_vec(); assert_eq!(xss.iter().map(Vec::as_slice).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_combined_k_compositions() { exhaustive_combined_k_compositions_helper( 3, 5, 3, &[ &[1, 1, 1], &[1, 1, 2], &[1, 2, 1], &[2, 1, 1], &[1, 1, 3], &[1, 2, 2], &[1, 3, 1], &[2, 1, 2], &[2, 2, 1], &[3, 1, 1], ], ); exhaustive_combined_k_compositions_helper( 6, 8, 5, &[ &[1, 1, 1, 1, 2], &[1, 1, 1, 1, 3], &[1, 1, 1, 2, 1], &[1, 1, 1, 1, 4], &[1, 1, 2, 1, 1], &[1, 1, 1, 2, 2], &[1, 2, 1, 1, 1], &[2, 1, 1, 1, 1], &[1, 1, 1, 3, 1], &[1, 1, 1, 2, 3], &[1, 1, 2, 1, 2], &[1, 1, 2, 2, 1], &[1, 1, 3, 1, 1], &[1, 1, 1, 3, 2], &[1, 2, 1, 1, 2], &[1, 2, 1, 2, 1], &[1, 2, 2, 1, 1], &[1, 1, 1, 4, 1], &[1, 3, 1, 1, 1], &[2, 1, 1, 1, 2], &[2, 1, 1, 2, 1], &[1, 1, 2, 1, 3], &[2, 1, 2, 1, 1], &[1, 1, 2, 2, 2], &[2, 2, 1, 1, 1], &[1, 1, 2, 3, 1], &[3, 1, 1, 1, 1], &[1, 1, 3, 1, 2], &[1, 1, 3, 2, 1], &[1, 1, 4, 1, 1], &[1, 2, 1, 1, 3], &[1, 2, 1, 2, 2], &[1, 2, 1, 3, 1], &[1, 2, 2, 1, 2], &[1, 2, 2, 2, 1], &[1, 2, 3, 1, 1], &[1, 3, 1, 1, 2], &[1, 3, 1, 2, 1], &[1, 3, 2, 1, 1], &[1, 4, 1, 1, 1], &[2, 1, 1, 1, 3], &[2, 1, 1, 2, 2], &[2, 1, 1, 3, 1], &[2, 1, 2, 1, 2], &[2, 1, 2, 2, 1], &[2, 1, 3, 1, 1], &[2, 2, 1, 1, 2], &[2, 2, 1, 2, 1], &[2, 2, 2, 1, 1], &[2, 3, 1, 1, 1], &[3, 1, 1, 1, 2], &[3, 1, 1, 2, 1], &[3, 1, 2, 1, 1], &[3, 2, 1, 1, 1], &[4, 1, 1, 1, 1], ], ); } #[test] #[should_panic] fn exhaustive_combined_k_compositions_fail() { exhaustive_combined_k_compositions(2, 1, 3); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_ordered_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs; use std::fmt::Debug; fn exhaustive_ordered_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_ordered_unique_vecs(xs), out); } fn exhaustive_ordered_unique_vecs_small_helper( xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_ordered_unique_vecs(xs), out_len, out); } #[test] fn test_exhaustive_ordered_unique_vecs() { exhaustive_ordered_unique_vecs_small_helper(nevers(), 1, &[&[]]); exhaustive_ordered_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); exhaustive_ordered_unique_vecs_small_helper( exhaustive_bools(), 4, &[&[], &[false], &[true], &[false, true]], ); exhaustive_ordered_unique_vecs_small_helper( 1..=6, 64, &[ &[], &[1], &[2], &[1, 2], &[3], &[1, 3], &[2, 3], &[1, 2, 3], &[4], &[1, 4], &[2, 4], &[1, 2, 4], &[3, 4], &[1, 3, 4], &[2, 3, 4], &[1, 2, 3, 4], &[5], &[1, 5], &[2, 5], &[1, 2, 5], ], ); exhaustive_ordered_unique_vecs_small_helper( 'a'..='c', 8, &[&[], &['a'], &['b'], &['a', 'b'], &['c'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); exhaustive_ordered_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['a', 'b'], &['c'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c'], &['d'], &['a', 'd'], &['b', 'd'], &['a', 'b', 'd'], &['c', 'd'], &['a', 'c', 'd'], &['b', 'c', 'd'], &['a', 'b', 'c', 'd'], &['e'], &['a', 'e'], &['b', 'e'], &['a', 'b', 'e'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_ordered_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_fixed_length; use std::fmt::Debug; fn exhaustive_ordered_unique_vecs_fixed_length_helper( len: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_ordered_unique_vecs_fixed_length(len, xs), out); } fn exhaustive_ordered_unique_vecs_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_ordered_unique_vecs_fixed_length(len, xs), out_len, out, ); } #[test] fn test_exhaustive_ordered_unique_vecs_fixed_length() { // This demonstrates that 0 ^ 0 == 1: exhaustive_ordered_unique_vecs_fixed_length_small_helper(0, nevers(), 1, &[&[]]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(1, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(2, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(5, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(1, exhaustive_units(), 1, &[&[()]]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 0, exhaustive_unsigneds::(), 1, &[&[]], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_ordered_unique_vecs_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ &[0, 1], &[0, 2], &[1, 2], &[0, 3], &[1, 3], &[2, 3], &[0, 4], &[1, 4], &[2, 4], &[3, 4], &[0, 5], &[1, 5], &[2, 5], &[3, 5], &[4, 5], &[0, 6], &[1, 6], &[2, 6], &[3, 6], &[4, 6], ], ); exhaustive_ordered_unique_vecs_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ &[0, 1, 2], &[0, 1, 3], &[0, 2, 3], &[1, 2, 3], &[0, 1, 4], &[0, 2, 4], &[1, 2, 4], &[0, 3, 4], &[1, 3, 4], &[2, 3, 4], &[0, 1, 5], &[0, 2, 5], &[1, 2, 5], &[0, 3, 5], &[1, 3, 5], &[2, 3, 5], &[0, 4, 5], &[1, 4, 5], &[2, 4, 5], &[3, 4, 5], ], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ &['a', 'b'], &['a', 'c'], &['b', 'c'], &['a', 'd'], &['b', 'd'], &['c', 'd'], &['a', 'e'], &['b', 'e'], &['c', 'e'], &['d', 'e'], &['a', 'f'], &['b', 'f'], &['c', 'f'], &['d', 'f'], &['e', 'f'], &['a', 'g'], &['b', 'g'], &['c', 'g'], &['d', 'g'], &['e', 'g'], ], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[&[false], &[true]], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 2, exhaustive_bools(), 1, &[&[false, true]], ); exhaustive_ordered_unique_vecs_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); exhaustive_ordered_unique_vecs_fixed_length_small_helper( 4, 1..=6, 15, &[ &[1, 2, 3, 4], &[1, 2, 3, 5], &[1, 2, 4, 5], &[1, 3, 4, 5], &[2, 3, 4, 5], &[1, 2, 3, 6], &[1, 2, 4, 6], &[1, 3, 4, 6], &[2, 3, 4, 6], &[1, 2, 5, 6], &[1, 3, 5, 6], &[2, 3, 5, 6], &[1, 4, 5, 6], &[2, 4, 5, 6], &[3, 4, 5, 6], ], ); exhaustive_ordered_unique_vecs_fixed_length_helper( 2, exhaustive_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ &[vec![0, 1], vec![0, 2]], &[vec![0, 1], vec![1, 2]], &[vec![0, 2], vec![1, 2]], &[vec![0, 1], vec![0, 3]], &[vec![0, 2], vec![0, 3]], &[vec![1, 2], vec![0, 3]], &[vec![0, 1], vec![1, 3]], &[vec![0, 2], vec![1, 3]], &[vec![1, 2], vec![1, 3]], &[vec![0, 3], vec![1, 3]], &[vec![0, 1], vec![2, 3]], &[vec![0, 2], vec![2, 3]], &[vec![1, 2], vec![2, 3]], &[vec![0, 3], vec![2, 3]], &[vec![1, 3], vec![2, 3]], &[vec![0, 1], vec![0, 4]], &[vec![0, 2], vec![0, 4]], &[vec![1, 2], vec![0, 4]], &[vec![0, 3], vec![0, 4]], &[vec![1, 3], vec![0, 4]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_ordered_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_ordered_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_ordered_unique_vecs_length_inclusive_range() { exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[&[], &[()]], ); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( 1, 0, exhaustive_bools(), 0, &[], ); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[&[false, true]], ); exhaustive_ordered_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_ordered_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_length_range; use std::fmt::Debug; fn exhaustive_ordered_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_ordered_unique_vecs_length_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_ordered_unique_vecs_length_range() { exhaustive_ordered_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); exhaustive_ordered_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[&[], &[()]], ); exhaustive_ordered_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_ordered_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); exhaustive_ordered_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); exhaustive_ordered_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[&[false, true]], ); exhaustive_ordered_unique_vecs_length_range_small_helper( 1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_ordered_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_ordered_unique_vecs_min_length; use std::fmt::Debug; fn exhaustive_ordered_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper( exhaustive_ordered_unique_vecs_min_length(min_length, xs), out, ); } fn exhaustive_ordered_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_ordered_unique_vecs_min_length(min_length, xs), out_len, out, ); } #[test] fn test_exhaustive_ordered_unique_vecs_min_length() { exhaustive_ordered_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); exhaustive_ordered_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); exhaustive_ordered_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); exhaustive_ordered_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_ordered_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 4, &[&[], &[false], &[true], &[false, true]], ); exhaustive_ordered_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 3, &[&[false], &[true], &[false, true]], ); exhaustive_ordered_unique_vecs_min_length_small_helper( 0, 'a'..='c', 8, &[&[], &['a'], &['b'], &['a', 'b'], &['c'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); exhaustive_ordered_unique_vecs_min_length_small_helper( 2, 'a'..='c', 4, &[&['a', 'b'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); exhaustive_ordered_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['a', 'b'], &['c'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c'], &['d'], &['a', 'd'], &['b', 'd'], &['a', 'b', 'd'], &['c', 'd'], &['a', 'c', 'd'], &['b', 'c', 'd'], &['a', 'b', 'c', 'd'], &['e'], &['a', 'e'], &['b', 'e'], &['a', 'b', 'e'], ], ); exhaustive_ordered_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'd'], &['a', 'c', 'd'], &['b', 'c', 'd'], &['a', 'b', 'c', 'd'], &['a', 'b', 'e'], &['a', 'c', 'e'], &['b', 'c', 'e'], &['a', 'b', 'c', 'e'], &['a', 'd', 'e'], &['b', 'd', 'e'], &['a', 'b', 'd', 'e'], &['c', 'd', 'e'], &['a', 'c', 'd', 'e'], &['b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'f'], &['a', 'c', 'f'], &['b', 'c', 'f'], &['a', 'b', 'c', 'f'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_unique_vecs; use std::fmt::Debug; fn exhaustive_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_unique_vecs(xs), out); } fn exhaustive_unique_vecs_small_helper( xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_unique_vecs(xs), out_len, out); } #[test] fn test_exhaustive_unique_vecs() { exhaustive_unique_vecs_small_helper(nevers(), 1, &[&[]]); exhaustive_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); exhaustive_unique_vecs_small_helper( exhaustive_bools(), 5, &[&[], &[false], &[true], &[false, true], &[true, false]], ); exhaustive_unique_vecs_small_helper( 1..=6, 1957, &[ &[], &[1], &[2], &[3], &[1, 2], &[1, 3], &[2, 1], &[1, 2, 3], &[3, 1], &[2, 3], &[3, 2], &[4], &[1, 3, 2], &[1, 4], &[2, 1, 3], &[3, 4], &[2, 3, 1], &[4, 1], &[3, 1, 2], &[2, 4], ], ); exhaustive_unique_vecs_small_helper( 'a'..='c', 16, &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['a', 'b', 'c'], &['c', 'a'], &['b', 'c'], &['c', 'b'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); exhaustive_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['a', 'b', 'c'], &['c', 'a'], &['b', 'c'], &['c', 'b'], &['d'], &['a', 'c', 'b'], &['a', 'd'], &['b', 'a', 'c'], &['c', 'd'], &['b', 'c', 'a'], &['d', 'a'], &['c', 'a', 'b'], &['b', 'd'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_fixed_length; use std::fmt::Debug; fn exhaustive_unique_vecs_fixed_length_helper(len: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_unique_vecs_fixed_length(len, xs), out); } fn exhaustive_unique_vecs_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_unique_vecs_fixed_length(len, xs), out_len, out); } #[test] fn test_exhaustive_unique_vecs_fixed_length() { // This demonstrates that 0 ^ 0 == 1: exhaustive_unique_vecs_fixed_length_small_helper(0, nevers(), 1, &[&[]]); exhaustive_unique_vecs_fixed_length_small_helper(1, nevers(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper(2, nevers(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper(5, nevers(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper(1, exhaustive_units(), 1, &[&[()]]); exhaustive_unique_vecs_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper(0, exhaustive_unsigneds::(), 1, &[&[]]); exhaustive_unique_vecs_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_unique_vecs_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_unique_vecs_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 65280, &[ &[0, 1], &[1, 0], &[0, 2], &[2, 0], &[1, 2], &[2, 1], &[0, 3], &[3, 0], &[1, 3], &[3, 1], &[2, 3], &[3, 2], &[0, 4], &[4, 0], &[1, 4], &[4, 1], &[2, 4], &[4, 2], &[3, 4], &[4, 3], ], ); exhaustive_unique_vecs_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ &[0, 1, 2], &[0, 1, 3], &[0, 2, 1], &[0, 2, 3], &[1, 0, 2], &[0, 3, 1], &[1, 2, 0], &[1, 2, 3], &[2, 0, 1], &[1, 0, 3], &[2, 1, 0], &[0, 3, 2], &[1, 3, 0], &[2, 0, 3], &[3, 0, 1], &[0, 2, 4], &[3, 1, 0], &[2, 3, 0], &[3, 0, 2], &[0, 1, 4], ], ); exhaustive_unique_vecs_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 16256, &[ &['a', 'b'], &['b', 'a'], &['a', 'c'], &['c', 'a'], &['b', 'c'], &['c', 'b'], &['a', 'd'], &['d', 'a'], &['b', 'd'], &['d', 'b'], &['c', 'd'], &['d', 'c'], &['a', 'e'], &['e', 'a'], &['b', 'e'], &['e', 'b'], &['c', 'e'], &['e', 'c'], &['d', 'e'], &['e', 'd'], ], ); exhaustive_unique_vecs_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[&[false], &[true]], ); exhaustive_unique_vecs_fixed_length_small_helper( 2, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); exhaustive_unique_vecs_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); exhaustive_unique_vecs_fixed_length_small_helper( 4, 1..=6, 360, &[ &[1, 2, 3, 4], &[1, 2, 3, 5], &[1, 2, 4, 3], &[1, 2, 4, 5], &[1, 3, 2, 4], &[1, 2, 5, 3], &[1, 3, 4, 2], &[1, 3, 4, 5], &[1, 4, 2, 3], &[1, 3, 2, 5], &[1, 4, 3, 2], &[1, 2, 5, 4], &[2, 1, 3, 4], &[1, 3, 5, 2], &[2, 1, 4, 3], &[2, 3, 4, 5], &[2, 3, 1, 4], &[1, 5, 2, 3], &[2, 3, 4, 1], &[1, 4, 2, 5], ], ); exhaustive_unique_vecs_fixed_length_helper( 2, exhaustive_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ &[vec![0, 1], vec![1, 0]], &[vec![1, 0], vec![0, 1]], &[vec![0, 1], vec![0, 2]], &[vec![0, 2], vec![0, 1]], &[vec![1, 0], vec![0, 2]], &[vec![0, 2], vec![1, 0]], &[vec![0, 1], vec![2, 0]], &[vec![2, 0], vec![0, 1]], &[vec![1, 0], vec![2, 0]], &[vec![2, 0], vec![1, 0]], &[vec![0, 2], vec![2, 0]], &[vec![2, 0], vec![0, 2]], &[vec![0, 1], vec![1, 2]], &[vec![1, 2], vec![0, 1]], &[vec![1, 0], vec![1, 2]], &[vec![1, 2], vec![1, 0]], &[vec![0, 2], vec![1, 2]], &[vec![1, 2], vec![0, 2]], &[vec![2, 0], vec![1, 2]], &[vec![1, 2], vec![2, 0]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn exhaustive_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_unique_vecs_length_inclusive_range() { exhaustive_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); exhaustive_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); exhaustive_unique_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[&[], &[()]], ); exhaustive_unique_vecs_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); exhaustive_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); exhaustive_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_length_range; use std::fmt::Debug; fn exhaustive_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_unique_vecs_length_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_unique_vecs_length_range() { exhaustive_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); exhaustive_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); exhaustive_unique_vecs_length_range_small_helper(0, 5, exhaustive_units(), 2, &[&[], &[()]]); exhaustive_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); exhaustive_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); exhaustive_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); exhaustive_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); exhaustive_unique_vecs_length_range_small_helper(1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']]); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_unique_vecs_min_length; use std::fmt::Debug; fn exhaustive_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_unique_vecs_min_length(min_length, xs), out); } fn exhaustive_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_unique_vecs_min_length(min_length, xs), out_len, out, ); } #[test] fn test_exhaustive_unique_vecs_min_length() { exhaustive_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); exhaustive_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); exhaustive_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); exhaustive_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); exhaustive_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 5, &[&[], &[false], &[true], &[false, true], &[true, false]], ); exhaustive_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 4, &[&[false], &[true], &[false, true], &[true, false]], ); exhaustive_unique_vecs_min_length_small_helper( 0, 'a'..='c', 16, &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['a', 'b', 'c'], &['c', 'a'], &['b', 'c'], &['c', 'b'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); exhaustive_unique_vecs_min_length_small_helper( 2, 'a'..='c', 12, &[ &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['a', 'b', 'c'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); exhaustive_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['a', 'b', 'c'], &['c', 'a'], &['b', 'c'], &['c', 'b'], &['d'], &['a', 'c', 'b'], &['a', 'd'], &['b', 'a', 'c'], &['c', 'd'], &['b', 'c', 'a'], &['d', 'a'], &['c', 'a', 'b'], &['b', 'd'], ], ); exhaustive_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'd'], &['a', 'c', 'b'], &['a', 'c', 'd'], &['b', 'a', 'c'], &['a', 'd', 'b'], &['b', 'c', 'a'], &['b', 'c', 'd'], &['c', 'a', 'b'], &['b', 'a', 'd'], &['c', 'b', 'a'], &['a', 'd', 'c'], &['b', 'd', 'a'], &['c', 'a', 'd'], &['d', 'a', 'b'], &['a', 'b', 'e'], &['d', 'b', 'a'], &['c', 'd', 'a'], &['d', 'a', 'c'], &['a', 'b', 'c', 'd'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_vecs; use std::fmt::Debug; fn exhaustive_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs(xs), out); } #[test] fn test_exhaustive_vecs() { exhaustive_vecs_helper(nevers(), &[&[]]); exhaustive_vecs_helper( exhaustive_units(), &[ &[], &[()], &[(), ()], &[(), (), (), ()], &[(), (), ()], &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], ], ); exhaustive_vecs_helper( exhaustive_bools(), &[ &[], &[false], &[true], &[false, false, false], &[false, false], &[false, false, true], &[false, true], &[false, false, false, false, false], &[true, false], &[false, true, false], &[true, true], &[false, false, false, false], &[false, true, true], &[false, false, false, true], &[true, false, false], &[false, false, false, false, false, false, false], &[true, false, true], &[false, false, true, false], &[true, true, false], &[false, false, false, false, true], ], ); exhaustive_vecs_helper( 'a'..='c', &[ &[], &['a'], &['b'], &['a', 'a', 'a'], &['c'], &['a', 'a'], &['a', 'b'], &['a', 'a', 'a', 'a', 'a'], &['b', 'a'], &['a', 'a', 'b'], &['b', 'b'], &['a', 'a', 'a', 'a'], &['a', 'c'], &['a', 'b', 'a'], &['b', 'c'], &['a', 'a', 'a', 'a', 'a', 'a'], &['c', 'a'], &['a', 'b', 'b'], &['c', 'b'], &['a', 'a', 'a', 'b'], ], ); exhaustive_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['a', 'a', 'a'], &['c'], &['a', 'a'], &['d'], &['a', 'a', 'a', 'a'], &['e'], &['a', 'b'], &['f'], &['a', 'a', 'b'], &['g'], &['b', 'a'], &['h'], &['a', 'a', 'a', 'a', 'a'], &['i'], &['b', 'b'], &['j'], &['a', 'b', 'a'], ], ); exhaustive_vecs_helper( exhaustive_unsigneds::(), &[ &[], &[0], &[1], &[0, 0, 0], &[2], &[0, 0], &[3], &[0, 0, 0, 0], &[4], &[0, 1], &[5], &[0, 0, 1], &[6], &[1, 0], &[7], &[0, 0, 0, 0, 0], &[8], &[1, 1], &[9], &[0, 1, 0], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_fixed_length_from_single.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_vecs_fixed_length_from_single; use std::fmt::Debug; fn exhaustive_vecs_fixed_length_from_single_helper(len: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_fixed_length_from_single(len, xs), out); } fn exhaustive_vecs_fixed_length_from_single_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_vecs_fixed_length_from_single(len, xs), out_len, out, ); } #[test] fn test_exhaustive_vecs_fixed_length_from_single() { // This demonstrates that 0 ^ 0 == 1: exhaustive_vecs_fixed_length_from_single_small_helper(0, nevers(), 1, &[&[]]); exhaustive_vecs_fixed_length_from_single_small_helper(1, nevers(), 0, &[]); exhaustive_vecs_fixed_length_from_single_small_helper(2, nevers(), 0, &[]); exhaustive_vecs_fixed_length_from_single_small_helper(5, nevers(), 0, &[]); exhaustive_vecs_fixed_length_from_single_small_helper(1, exhaustive_units(), 1, &[&[()]]); exhaustive_vecs_fixed_length_from_single_small_helper(2, exhaustive_units(), 1, &[&[(), ()]]); exhaustive_vecs_fixed_length_from_single_small_helper(5, exhaustive_units(), 1, &[&[(); 5]]); exhaustive_vecs_fixed_length_from_single_small_helper( 0, exhaustive_unsigneds::(), 1, &[&[]], ); exhaustive_vecs_fixed_length_from_single_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_vecs_fixed_length_from_single_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); exhaustive_vecs_fixed_length_from_single_small_helper( 2, exhaustive_unsigneds::(), 0x10000, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[1, 4], &[1, 5], ], ); exhaustive_vecs_fixed_length_from_single_helper( 3, exhaustive_unsigneds::(), &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 3, 0], &[0, 3, 1], ], ); exhaustive_vecs_fixed_length_from_single_small_helper( 2, exhaustive_ascii_chars(), 0x4000, &[ &['a', 'a'], &['a', 'b'], &['b', 'a'], &['b', 'b'], &['a', 'c'], &['a', 'd'], &['b', 'c'], &['b', 'd'], &['c', 'a'], &['c', 'b'], &['d', 'a'], &['d', 'b'], &['c', 'c'], &['c', 'd'], &['d', 'c'], &['d', 'd'], &['a', 'e'], &['a', 'f'], &['b', 'e'], &['b', 'f'], ], ); exhaustive_vecs_fixed_length_from_single_small_helper( 1, exhaustive_bools(), 2, &[&[false], &[true]], ); exhaustive_vecs_fixed_length_from_single_small_helper( 2, exhaustive_bools(), 4, &[&[false, false], &[false, true], &[true, false], &[true, true]], ); exhaustive_vecs_fixed_length_from_single_small_helper( 4, exhaustive_bools(), 16, &[ &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], &[false, true, false, true], &[false, true, true, false], &[false, true, true, true], &[true, false, false, false], &[true, false, false, true], &[true, false, true, false], &[true, false, true, true], &[true, true, false, false], &[true, true, false, true], &[true, true, true, false], &[true, true, true, true], ], ); exhaustive_vecs_fixed_length_from_single_small_helper( 10, exhaustive_bools(), 1024, &[ &[false, false, false, false, false, false, false, false, false, false], &[false, false, false, false, false, false, false, false, false, true], &[false, false, false, false, false, false, false, false, true, false], &[false, false, false, false, false, false, false, false, true, true], &[false, false, false, false, false, false, false, true, false, false], &[false, false, false, false, false, false, false, true, false, true], &[false, false, false, false, false, false, false, true, true, false], &[false, false, false, false, false, false, false, true, true, true], &[false, false, false, false, false, false, true, false, false, false], &[false, false, false, false, false, false, true, false, false, true], &[false, false, false, false, false, false, true, false, true, false], &[false, false, false, false, false, false, true, false, true, true], &[false, false, false, false, false, false, true, true, false, false], &[false, false, false, false, false, false, true, true, false, true], &[false, false, false, false, false, false, true, true, true, false], &[false, false, false, false, false, false, true, true, true, true], &[false, false, false, false, false, true, false, false, false, false], &[false, false, false, false, false, true, false, false, false, true], &[false, false, false, false, false, true, false, false, true, false], &[false, false, false, false, false, true, false, false, true, true], ], ); exhaustive_vecs_fixed_length_from_single_small_helper( 10, 0..3, 59049, &[ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 1], &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0], &[0, 0, 0, 0, 0, 0, 0, 1, 0, 1], &[0, 0, 0, 0, 0, 0, 0, 1, 1, 0], &[0, 0, 0, 0, 0, 0, 0, 1, 1, 1], &[0, 0, 0, 0, 0, 0, 1, 0, 0, 0], &[0, 0, 0, 0, 0, 0, 1, 0, 0, 1], &[0, 0, 0, 0, 0, 0, 1, 0, 1, 0], &[0, 0, 0, 0, 0, 0, 1, 0, 1, 1], &[0, 0, 0, 0, 0, 0, 1, 1, 0, 0], &[0, 0, 0, 0, 0, 0, 1, 1, 0, 1], &[0, 0, 0, 0, 0, 0, 1, 1, 1, 0], &[0, 0, 0, 0, 0, 0, 1, 1, 1, 1], &[0, 0, 0, 0, 0, 1, 0, 0, 0, 0], &[0, 0, 0, 0, 0, 1, 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1, 0, 0, 1, 0], &[0, 0, 0, 0, 0, 1, 0, 0, 1, 1], ], ); exhaustive_vecs_fixed_length_from_single_helper( 2, exhaustive_vecs_fixed_length_from_single(2, exhaustive_unsigneds::()), &[ &[vec![0, 0], vec![0, 0]], &[vec![0, 0], vec![0, 1]], &[vec![0, 1], vec![0, 0]], &[vec![0, 1], vec![0, 1]], &[vec![0, 0], vec![1, 0]], &[vec![0, 0], vec![1, 1]], &[vec![0, 1], vec![1, 0]], &[vec![0, 1], vec![1, 1]], &[vec![1, 0], vec![0, 0]], &[vec![1, 0], vec![0, 1]], &[vec![1, 1], vec![0, 0]], &[vec![1, 1], vec![0, 1]], &[vec![1, 0], vec![1, 0]], &[vec![1, 0], vec![1, 1]], &[vec![1, 1], vec![1, 0]], &[vec![1, 1], vec![1, 1]], &[vec![0, 0], vec![0, 2]], &[vec![0, 0], vec![0, 3]], &[vec![0, 1], vec![0, 2]], &[vec![0, 1], vec![0, 3]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_fixed_length_m_inputs.rs ================================================ // Copyright © 2026 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 crate::{SAMPLE_OUTPUT_TYPES_2, SAMPLE_OUTPUT_TYPES_3}; use itertools::Itertools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::{exhaustive_positive_primitive_ints, exhaustive_unsigneds}; use malachite_base::vecs::exhaustive::{ exhaustive_vecs_fixed_length_1_input, exhaustive_vecs_fixed_length_2_inputs, }; use std::fmt::Debug; use std::iter::empty; fn exhaustive_vecs_fixed_length_1_input_helper>( xs: &I, len: usize, out_len: Option, out: &[&[T]], ) where T: Clone + Debug + Eq, { let xss = if len == 2 { exhaustive_vecs_fixed_length_1_input(xs.clone(), &SAMPLE_OUTPUT_TYPES_2[0]) } else { assert_eq!(len, 3); exhaustive_vecs_fixed_length_1_input(xs.clone(), &SAMPLE_OUTPUT_TYPES_3[0]) }; let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } if len == 2 { for alt_output_types in &SAMPLE_OUTPUT_TYPES_2[1..] { let xss = exhaustive_vecs_fixed_length_1_input(xs.clone(), alt_output_types); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } else { assert_eq!(len, 3); for alt_output_types in &SAMPLE_OUTPUT_TYPES_3[1..] { let xss = exhaustive_vecs_fixed_length_1_input(xs.clone(), alt_output_types); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } } #[test] fn test_exhaustive_vecs_fixed_length_1_input() { exhaustive_vecs_fixed_length_1_input_helper(&nevers(), 2, Some(0), &[]); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_unsigneds::(), 2, Some(1 << 16), &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[0, 4], &[0, 5], &[1, 4], &[1, 5], ], ); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_positive_primitive_ints::(), 2, None, &[ &[1, 1], &[1, 2], &[2, 1], &[2, 2], &[1, 3], &[1, 4], &[2, 3], &[2, 4], &[3, 1], &[3, 2], &[4, 1], &[4, 2], &[3, 3], &[3, 4], &[4, 3], &[4, 4], &[1, 5], &[1, 6], &[2, 5], &[2, 6], ], ); exhaustive_vecs_fixed_length_1_input_helper( &['x', 'y', 'z'].iter().copied(), 2, Some(9), &[ &['x', 'x'], &['x', 'y'], &['y', 'x'], &['y', 'y'], &['x', 'z'], &['y', 'z'], &['z', 'x'], &['z', 'y'], &['z', 'z'], ], ); exhaustive_vecs_fixed_length_1_input_helper( &['x', 'y', 'z'].iter().copied(), 3, Some(27), &[ &['x', 'x', 'x'], &['x', 'x', 'y'], &['x', 'y', 'x'], &['x', 'y', 'y'], &['y', 'x', 'x'], &['y', 'x', 'y'], &['y', 'y', 'x'], &['y', 'y', 'y'], &['x', 'x', 'z'], &['x', 'y', 'z'], &['y', 'x', 'z'], &['y', 'y', 'z'], &['x', 'z', 'x'], &['x', 'z', 'y'], &['y', 'z', 'x'], &['y', 'z', 'y'], &['x', 'z', 'z'], &['y', 'z', 'z'], &['z', 'x', 'x'], &['z', 'x', 'y'], ], ); exhaustive_vecs_fixed_length_1_input_helper( &exhaustive_ascii_chars(), 3, None, &[ &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'b', 'a'], &['a', 'b', 'b'], &['b', 'a', 'a'], &['b', 'a', 'b'], &['b', 'b', 'a'], &['b', 'b', 'b'], &['a', 'a', 'c'], &['a', 'a', 'd'], &['a', 'b', 'c'], &['a', 'b', 'd'], &['b', 'a', 'c'], &['b', 'a', 'd'], &['b', 'b', 'c'], &['b', 'b', 'd'], &['a', 'c', 'a'], &['a', 'c', 'b'], &['a', 'd', 'a'], &['a', 'd', 'b'], ], ); } fn exhaustive_vecs_fixed_length_2_inputs_helper< T, I: Clone + Iterator, J: Clone + Iterator, >( xs: &I, ys: &J, len: usize, input_indices: &[usize], out_len: Option, out: &[&[T]], ) where T: Clone + Debug + Eq, { let output_configs: Vec<(BitDistributorOutputType, usize)> = if len == 2 { SAMPLE_OUTPUT_TYPES_2[0] .iter() .copied() .zip(input_indices.iter().copied()) .collect() } else { SAMPLE_OUTPUT_TYPES_3[0] .iter() .copied() .zip(input_indices.iter().copied()) .collect() }; let xss = exhaustive_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), &output_configs); let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } if len == 2 { for alt_output_types in &SAMPLE_OUTPUT_TYPES_2[1..] { let output_configs: Vec<(BitDistributorOutputType, usize)> = alt_output_types .iter() .copied() .zip(input_indices.iter().copied()) .collect(); let xss = exhaustive_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), &output_configs); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } else { assert_eq!(len, 3); for alt_output_types in &SAMPLE_OUTPUT_TYPES_3[1..] { let output_configs: Vec<(BitDistributorOutputType, usize)> = alt_output_types .iter() .copied() .zip(input_indices.iter().copied()) .collect(); let xss = exhaustive_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), &output_configs); xss.clone().take(20).for_each(drop); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } } } #[test] fn test_exhaustive_vecs_fixed_length_2_inputs() { exhaustive_vecs_fixed_length_2_inputs_helper(&nevers(), &nevers(), 2, &[0, 1], Some(0), &[]); exhaustive_vecs_fixed_length_2_inputs_helper( &empty(), &exhaustive_unsigneds::(), 2, &[0, 1], Some(0), &[], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_unsigneds::(), &exhaustive_positive_primitive_ints::(), 2, &[0, 1], None, &[ &[0, 1], &[0, 2], &[1, 1], &[1, 2], &[0, 3], &[0, 4], &[1, 3], &[1, 4], &[2, 1], &[2, 2], &[3, 1], &[3, 2], &[2, 3], &[2, 4], &[3, 3], &[3, 4], &[0, 5], &[0, 6], &[1, 5], &[1, 6], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 2, &[0, 1], Some(384), &[ &['a', 'x'], &['a', 'y'], &['b', 'x'], &['b', 'y'], &['a', 'z'], &['b', 'z'], &['c', 'x'], &['c', 'y'], &['d', 'x'], &['d', 'y'], &['c', 'z'], &['d', 'z'], &['e', 'x'], &['e', 'y'], &['f', 'x'], &['f', 'y'], &['e', 'z'], &['f', 'z'], &['g', 'x'], &['g', 'y'], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 3, &[0, 1, 1], Some(1152), &[ &['a', 'x', 'x'], &['a', 'x', 'y'], &['a', 'y', 'x'], &['a', 'y', 'y'], &['b', 'x', 'x'], &['b', 'x', 'y'], &['b', 'y', 'x'], &['b', 'y', 'y'], &['a', 'x', 'z'], &['a', 'y', 'z'], &['b', 'x', 'z'], &['b', 'y', 'z'], &['a', 'z', 'x'], &['a', 'z', 'y'], &['b', 'z', 'x'], &['b', 'z', 'y'], &['a', 'z', 'z'], &['b', 'z', 'z'], &['c', 'x', 'x'], &['c', 'x', 'y'], ], ); exhaustive_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), 3, &[0, 1, 0], Some(49152), &[ &['a', 'x', 'a'], &['a', 'x', 'b'], &['a', 'y', 'a'], &['a', 'y', 'b'], &['b', 'x', 'a'], &['b', 'x', 'b'], &['b', 'y', 'a'], &['b', 'y', 'b'], &['a', 'x', 'c'], &['a', 'x', 'd'], &['a', 'y', 'c'], &['a', 'y', 'd'], &['b', 'x', 'c'], &['b', 'x', 'd'], &['b', 'y', 'c'], &['b', 'y', 'd'], &['a', 'z', 'a'], &['a', 'z', 'b'], &['b', 'z', 'a'], &['b', 'z', 'b'], ], ); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_1() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_2() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[(BitDistributorOutputType::normal(1), 0)]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_3() { exhaustive_vecs_fixed_length_2_inputs(0..2, 0..3, &[(BitDistributorOutputType::normal(1), 1)]); } #[test] #[should_panic] fn exhaustive_vecs_fixed_length_2_inputs_fail_4() { exhaustive_vecs_fixed_length_2_inputs( 0..2, 0..3, &[ (BitDistributorOutputType::normal(1), 0), (BitDistributorOutputType::normal(1), 1), (BitDistributorOutputType::normal(1), 2), ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::vecs::exhaustive::exhaustive_vecs_from_length_iterator; use std::fmt::Debug; use std::iter::empty; fn exhaustive_vecs_from_element_iterator_helper, J: Clone + Iterator>( lengths: I, xs: J, out: &[&[J::Item]], ) where J::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_from_length_iterator(lengths, xs), out); } #[test] fn test_exhaustive_vecs_from_element_iterator() { exhaustive_vecs_from_element_iterator_helper(empty(), exhaustive_bools(), &[]); exhaustive_vecs_from_element_iterator_helper( [2, 1, 2].iter().copied(), exhaustive_bools(), &[ &[false, false], &[false], &[false, true], &[false, false], &[true, false], &[true], &[true, true], &[false, true], &[true, false], &[true, true], ], ); exhaustive_vecs_from_element_iterator_helper( exhaustive_unsigneds::().map(|u| u << 1), exhaustive_bools(), &[ &[], &[false, false], &[false, true], &[false, false, false, false, false, false], &[true, false], &[false, false, false, false], &[true, true], &[false, false, false, false, false, false, false, false], &[false, false, false, true], &[false, false, false, false, false, true], &[false, false, true, false], &[false, false, false, false, false, false, false, true], &[false, false, true, true], &[false, false, false, false, true, false], &[false, true, false, false], &[false, false, false, false, false, false, false, false, false, false, false, false], &[false, true, false, true], &[false, false, false, false, true, true], &[false, true, true, false], &[false, false, false, false, false, false, true, false], ], ); exhaustive_vecs_from_element_iterator_helper( [2, 1, 0, 2].iter().copied(), exhaustive_bools(), &[ &[false, false], &[false], &[false, true], &[], &[true, false], &[true], &[true, true], &[false, false], &[false, true], &[true, false], &[true, true], ], ); exhaustive_vecs_from_element_iterator_helper(empty(), exhaustive_unsigneds::(), &[]); exhaustive_vecs_from_element_iterator_helper( [2, 1, 2].iter().copied(), exhaustive_unsigneds::(), &[ &[0, 0], &[0], &[0, 1], &[0, 0], &[1, 0], &[1], &[1, 1], &[0, 2], &[0, 3], &[2], &[1, 2], &[0, 1], &[1, 3], &[3], &[2, 0], &[4], &[2, 1], &[5], &[3, 0], &[1, 0], ], ); exhaustive_vecs_from_element_iterator_helper( exhaustive_unsigneds::().map(|u| u << 1), exhaustive_unsigneds::(), &[ &[], &[0, 0], &[0, 1], &[0, 0, 0, 0, 0, 0], &[1, 0], &[0, 0, 0, 0], &[1, 1], &[0, 0, 0, 0, 0, 0, 0, 0], &[0, 2], &[0, 0, 0, 1], &[0, 3], &[0, 0, 0, 0, 0, 1], &[1, 2], &[0, 0, 1, 0], &[1, 3], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], &[2, 0], &[0, 0, 1, 1], &[2, 1], &[0, 0, 0, 0, 1, 0], ], ); exhaustive_vecs_from_element_iterator_helper( [2, 1, 0, 2].iter().copied(), exhaustive_unsigneds::(), &[ &[0, 0], &[0], &[0, 1], &[], &[1, 0], &[1], &[1, 1], &[0, 0], &[0, 2], &[2], &[0, 3], &[0, 1], &[1, 2], &[3], &[1, 3], &[4], &[2, 0], &[5], &[2, 1], &[1, 0], ], ); // Stops after first empty ys exhaustive_vecs_from_element_iterator_helper( [0, 0, 1, 0].iter().copied(), nevers(), &[&[], &[]], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_vecs_length_inclusive_range; use std::fmt::Debug; fn exhaustive_vecs_length_inclusive_range_helper( a: u64, b: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_length_inclusive_range(a, b, xs), out); } fn exhaustive_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( exhaustive_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_exhaustive_vecs_length_inclusive_range() { exhaustive_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); exhaustive_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); exhaustive_vecs_length_inclusive_range_small_helper(5, 3, exhaustive_bools(), 0, &[]); exhaustive_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 5, &[&[], &[()], &[(), ()], &[(), (), (), ()], &[(), (), ()]], ); exhaustive_vecs_length_inclusive_range_small_helper( 1, 1, exhaustive_bools(), 2, &[&[false], &[true]], ); exhaustive_vecs_length_inclusive_range_small_helper( 0, 2, exhaustive_bools(), 7, &[&[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true]], ); exhaustive_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 12, &[ &[false, false], &[false, false, false], &[false, true], &[true, false], &[true, true], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], ], ); exhaustive_vecs_length_inclusive_range_small_helper( 5, 7, 'a'..='c', 3159, &[ &['a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'b', 'b'], &['a', 'a', 'b', 'a', 'a'], &['a', 'a', 'b', 'a', 'b'], &['a', 'a', 'a', 'a', 'b', 'a'], &['a', 'a', 'b', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'a', 'b'], &['a', 'a', 'b', 'b', 'b'], &['a', 'a', 'a', 'a', 'b', 'b'], &['a', 'b', 'a', 'a', 'a'], &['a', 'a', 'a', 'b', 'a', 'a'], &['a', 'b', 'a', 'a', 'b'], &['a', 'a', 'a', 'b', 'a', 'b'], &['a', 'b', 'a', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'b', 'a'], ], ); exhaustive_vecs_length_inclusive_range_helper( 2, 3, exhaustive_unsigneds::(), &[ &[0, 0], &[0, 0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 0, 1], &[0, 2], &[0, 1, 0], &[0, 3], &[0, 1, 1], &[1, 2], &[1, 3], &[2, 0], &[1, 0, 0], &[2, 1], &[3, 0], &[3, 1], &[1, 0, 1], &[2, 2], &[2, 3], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_length_n.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::exhaustive_vecs_length_3; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::vecs::exhaustive::{ exhaustive_vecs_fixed_length_from_single, exhaustive_vecs_length_2, }; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::{empty, once}; fn exhaustive_vecs_length_2_helper, J: Iterator>( xs: I, ys: J, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_length_2(xs, ys), out); } fn exhaustive_vecs_length_2_finite_helper< T, I: Clone + Iterator, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_vecs_length_2(xs, ys), out_len, out); } #[test] fn test_exhaustive_vecs_length_2() { exhaustive_vecs_length_2_finite_helper(nevers(), nevers(), 0, &[]); exhaustive_vecs_length_2_finite_helper(empty(), 0..4, 0, &[]); exhaustive_vecs_length_2_finite_helper(once(0), once(1), 1, &[&[0, 1]]); exhaustive_vecs_length_2_finite_helper(once(0), 0..4, 4, &[&[0, 0], &[0, 1], &[0, 2], &[0, 3]]); exhaustive_vecs_length_2_finite_helper( exhaustive_unsigneds::(), 0..4, 1024, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[5, 0], &[5, 1], ], ); exhaustive_vecs_length_2_helper( exhaustive_unsigneds::(), 0..4, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[2, 3], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[5, 0], &[5, 1], ], ); exhaustive_vecs_length_2_finite_helper( 0..2, 0..4, 8, &[&[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[0, 3], &[1, 2], &[1, 3]], ); exhaustive_vecs_length_2_finite_helper( 0..5, 0..3, 15, &[ &[0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 2], &[1, 2], &[2, 0], &[2, 1], &[3, 0], &[3, 1], &[2, 2], &[3, 2], &[4, 0], &[4, 1], &[4, 2], ], ); exhaustive_vecs_length_2_finite_helper( ['a', 'b', 'c'].iter().copied(), ['x', 'y', 'z'].iter().copied(), 9, &[ &['a', 'x'], &['a', 'y'], &['b', 'x'], &['b', 'y'], &['a', 'z'], &['b', 'z'], &['c', 'x'], &['c', 'y'], &['c', 'z'], ], ); exhaustive_vecs_length_2_finite_helper( exhaustive_vecs_length_2(exhaustive_orderings(), [Less, Greater].iter().copied()), exhaustive_vecs_fixed_length_from_single(3, [Less, Greater].iter().copied()), 48, &[ &[vec![Equal, Less], vec![Less, Less, Less]], &[vec![Equal, Less], vec![Less, Less, Greater]], &[vec![Equal, Greater], vec![Less, Less, Less]], &[vec![Equal, Greater], vec![Less, Less, Greater]], &[vec![Equal, Less], vec![Less, Greater, Less]], &[vec![Equal, Less], vec![Less, Greater, Greater]], &[vec![Equal, Greater], vec![Less, Greater, Less]], &[vec![Equal, Greater], vec![Less, Greater, Greater]], &[vec![Less, Less], vec![Less, Less, Less]], &[vec![Less, Less], vec![Less, Less, Greater]], &[vec![Less, Greater], vec![Less, Less, Less]], &[vec![Less, Greater], vec![Less, Less, Greater]], &[vec![Less, Less], vec![Less, Greater, Less]], &[vec![Less, Less], vec![Less, Greater, Greater]], &[vec![Less, Greater], vec![Less, Greater, Less]], &[vec![Less, Greater], vec![Less, Greater, Greater]], &[vec![Equal, Less], vec![Greater, Less, Less]], &[vec![Equal, Less], vec![Greater, Less, Greater]], &[vec![Equal, Greater], vec![Greater, Less, Less]], &[vec![Equal, Greater], vec![Greater, Less, Greater]], ], ); } fn exhaustive_vecs_length_3_helper< T, I: Iterator, J: Iterator, K: Iterator, >( xs: I, ys: J, zs: K, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_length_3(xs, ys, zs), out); } fn exhaustive_vecs_length_3_finite_helper< T, I: Clone + Iterator, J: Clone + Iterator, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_vecs_length_3(xs, ys, zs), out_len, out); } #[test] fn test_exhaustive_vecs_length_3() { exhaustive_vecs_length_3_finite_helper(nevers(), nevers(), nevers(), 0, &[]); exhaustive_vecs_length_3_finite_helper(empty(), 0..4, 0..5, 0, &[]); exhaustive_vecs_length_3_finite_helper(once(0), once(1), once(5), 1, &[&[0, 1, 5]]); exhaustive_vecs_length_3_finite_helper( once(0), once(3), 0..4, 4, &[&[0, 3, 0], &[0, 3, 1], &[0, 3, 2], &[0, 3, 3]], ); exhaustive_vecs_length_3_finite_helper( exhaustive_unsigneds::(), 0..4, 0..4, 4096, &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 3, 0], &[0, 3, 1], ], ); exhaustive_vecs_length_3_helper( exhaustive_unsigneds::(), 0..4, 0..4, &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 3, 0], &[0, 3, 1], ], ); exhaustive_vecs_length_3_finite_helper( 0..2, 0..3, 0..3, 18, &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 1, 2], &[1, 0, 2], &[1, 1, 2], &[0, 2, 0], &[0, 2, 1], &[1, 2, 0], &[1, 2, 1], &[0, 2, 2], &[1, 2, 2], ], ); exhaustive_vecs_length_3_finite_helper( 0..11, 0..12, 0..13, 1716, &[ &[0, 0, 0], &[0, 0, 1], &[0, 1, 0], &[0, 1, 1], &[1, 0, 0], &[1, 0, 1], &[1, 1, 0], &[1, 1, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 2], &[0, 1, 3], &[1, 0, 2], &[1, 0, 3], &[1, 1, 2], &[1, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 3, 0], &[0, 3, 1], ], ); exhaustive_vecs_length_3_finite_helper( ['a', 'b', 'c'].iter().copied(), ['x', 'y', 'z'].iter().copied(), ['0', '1', '2'].iter().copied(), 27, &[ &['a', 'x', '0'], &['a', 'x', '1'], &['a', 'y', '0'], &['a', 'y', '1'], &['b', 'x', '0'], &['b', 'x', '1'], &['b', 'y', '0'], &['b', 'y', '1'], &['a', 'x', '2'], &['a', 'y', '2'], &['b', 'x', '2'], &['b', 'y', '2'], &['a', 'z', '0'], &['a', 'z', '1'], &['b', 'z', '0'], &['b', 'z', '1'], &['a', 'z', '2'], &['b', 'z', '2'], &['c', 'x', '0'], &['c', 'x', '1'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_vecs_length_range; use std::fmt::Debug; fn exhaustive_vecs_length_range_helper( a: u64, b: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_length_range(a, b, xs), out); } fn exhaustive_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(exhaustive_vecs_length_range(a, b, xs), out_len, out); } #[test] fn test_exhaustive_vecs_length_range() { exhaustive_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); exhaustive_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); exhaustive_vecs_length_range_small_helper( 0, 5, exhaustive_units(), 5, &[&[], &[()], &[(), ()], &[(), (), (), ()], &[(), (), ()]], ); exhaustive_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); exhaustive_vecs_length_range_small_helper(5, 3, exhaustive_bools(), 0, &[]); exhaustive_vecs_length_range_small_helper( 0, 3, exhaustive_bools(), 7, &[&[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true]], ); exhaustive_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 12, &[ &[false, false], &[false, false, false], &[false, true], &[true, false], &[true, true], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], ], ); exhaustive_vecs_length_range_small_helper( 5, 8, 'a'..='c', 3159, &[ &['a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'b', 'b'], &['a', 'a', 'b', 'a', 'a'], &['a', 'a', 'b', 'a', 'b'], &['a', 'a', 'a', 'a', 'b', 'a'], &['a', 'a', 'b', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'a', 'b'], &['a', 'a', 'b', 'b', 'b'], &['a', 'a', 'a', 'a', 'b', 'b'], &['a', 'b', 'a', 'a', 'a'], &['a', 'a', 'a', 'b', 'a', 'a'], &['a', 'b', 'a', 'a', 'b'], &['a', 'a', 'a', 'b', 'a', 'b'], &['a', 'b', 'a', 'b', 'a'], &['a', 'a', 'a', 'a', 'a', 'b', 'a'], ], ); exhaustive_vecs_length_range_helper( 2, 4, exhaustive_unsigneds::(), &[ &[0, 0], &[0, 0, 0], &[0, 1], &[1, 0], &[1, 1], &[0, 0, 1], &[0, 2], &[0, 1, 0], &[0, 3], &[0, 1, 1], &[1, 2], &[1, 3], &[2, 0], &[1, 0, 0], &[2, 1], &[3, 0], &[3, 1], &[1, 0, 1], &[2, 2], &[2, 3], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/exhaustive_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::exhaustive_vecs_min_length; use std::fmt::Debug; fn exhaustive_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(exhaustive_vecs_min_length(min_length, xs), out); } #[test] fn test_exhaustive_vecs_min_length() { exhaustive_vecs_min_length_helper(0, nevers(), &[&[]]); exhaustive_vecs_min_length_helper(4, nevers(), &[]); exhaustive_vecs_min_length_helper( 0, exhaustive_units(), &[ &[], &[()], &[(), ()], &[(), (), (), ()], &[(), (), ()], &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], ], ); exhaustive_vecs_min_length_helper( 5, exhaustive_units(), &[ &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[ (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[ (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ], &[ (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ], ], ); exhaustive_vecs_min_length_helper( 0, exhaustive_bools(), &[ &[], &[false], &[true], &[false, false, false], &[false, false], &[false, false, true], &[false, true], &[false, false, false, false, false], &[true, false], &[false, true, false], &[true, true], &[false, false, false, false], &[false, true, true], &[false, false, false, true], &[true, false, false], &[false, false, false, false, false, false, false], &[true, false, true], &[false, false, true, false], &[true, true, false], &[false, false, false, false, true], ], ); exhaustive_vecs_min_length_helper( 3, exhaustive_bools(), &[ &[false, false, false], &[false, false, false, false], &[false, false, true], &[false, false, false, false, false], &[false, true, false], &[false, false, false, true], &[false, true, true], &[false, false, false, false, false, false], &[true, false, false], &[false, false, true, false], &[true, false, true], &[false, false, false, false, true], &[true, true, false], &[false, false, true, true], &[true, true, true], &[false, false, false, false, false, false, false], &[false, true, false, false], &[false, false, false, true, false], &[false, true, false, true], &[false, false, false, false, false, true], ], ); exhaustive_vecs_min_length_helper( 0, 'a'..='c', &[ &[], &['a'], &['b'], &['a', 'a', 'a'], &['c'], &['a', 'a'], &['a', 'b'], &['a', 'a', 'a', 'a', 'a'], &['b', 'a'], &['a', 'a', 'b'], &['b', 'b'], &['a', 'a', 'a', 'a'], &['a', 'c'], &['a', 'b', 'a'], &['b', 'c'], &['a', 'a', 'a', 'a', 'a', 'a'], &['c', 'a'], &['a', 'b', 'b'], &['c', 'b'], &['a', 'a', 'a', 'b'], ], ); exhaustive_vecs_min_length_helper( 3, 'a'..='c', &[ &['a', 'a', 'a'], &['a', 'a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'a', 'a', 'a'], &['a', 'b', 'a'], &['a', 'a', 'a', 'b'], &['a', 'b', 'b'], &['a', 'a', 'a', 'a', 'a', 'a'], &['b', 'a', 'a'], &['a', 'a', 'b', 'a'], &['b', 'a', 'b'], &['a', 'a', 'a', 'a', 'b'], &['b', 'b', 'a'], &['a', 'a', 'b', 'b'], &['b', 'b', 'b'], &['a', 'a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'c'], &['a', 'b', 'a', 'a'], &['a', 'b', 'c'], &['a', 'a', 'a', 'b', 'a'], ], ); exhaustive_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['a', 'a', 'a'], &['c'], &['a', 'a'], &['d'], &['a', 'a', 'a', 'a'], &['e'], &['a', 'b'], &['f'], &['a', 'a', 'b'], &['g'], &['b', 'a'], &['h'], &['a', 'a', 'a', 'a', 'a'], &['i'], &['b', 'b'], &['j'], &['a', 'b', 'a'], ], ); exhaustive_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'a', 'a'], &['a', 'a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'a', 'a', 'a'], &['a', 'b', 'a'], &['a', 'a', 'a', 'b'], &['a', 'b', 'b'], &['a', 'a', 'a', 'a', 'a', 'a'], &['b', 'a', 'a'], &['a', 'a', 'b', 'a'], &['b', 'a', 'b'], &['a', 'a', 'a', 'a', 'b'], &['b', 'b', 'a'], &['a', 'a', 'b', 'b'], &['b', 'b', 'b'], &['a', 'a', 'a', 'a', 'a', 'a', 'a'], &['a', 'a', 'c'], &['a', 'b', 'a', 'a'], &['a', 'a', 'd'], &['a', 'a', 'a', 'b', 'a'], ], ); exhaustive_vecs_min_length_helper( 0, exhaustive_unsigneds::(), &[ &[], &[0], &[1], &[0, 0, 0], &[2], &[0, 0], &[3], &[0, 0, 0, 0], &[4], &[0, 1], &[5], &[0, 0, 1], &[6], &[1, 0], &[7], &[0, 0, 0, 0, 0], &[8], &[1, 1], &[9], &[0, 1, 0], ], ); exhaustive_vecs_min_length_helper( 3, exhaustive_unsigneds::(), &[ &[0, 0, 0], &[0, 0, 0, 0], &[0, 0, 1], &[0, 0, 0, 0, 0], &[0, 1, 0], &[0, 0, 0, 1], &[0, 1, 1], &[0, 0, 0, 0, 0, 0], &[1, 0, 0], &[0, 0, 1, 0], &[1, 0, 1], &[0, 0, 0, 0, 1], &[1, 1, 0], &[0, 0, 1, 1], &[1, 1, 1], &[0, 0, 0, 0, 0, 0, 0], &[0, 0, 2], &[0, 1, 0, 0], &[0, 0, 3], &[0, 0, 0, 1, 0], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_k_compositions.rs ================================================ // Copyright © 2026 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::vecs::exhaustive::lex_k_compositions; fn lex_k_compositions_helper(n: usize, k: usize, out: &[&[usize]]) { let xss = lex_k_compositions(n, k).collect_vec(); assert_eq!(xss.iter().map(Vec::as_slice).collect_vec().as_slice(), out); } #[test] fn test_lex_k_compositions() { lex_k_compositions_helper(0, 0, &[&[]]); lex_k_compositions_helper(0, 1, &[]); lex_k_compositions_helper(1, 0, &[]); lex_k_compositions_helper(1, 1, &[&[1]]); lex_k_compositions_helper(1, 2, &[]); lex_k_compositions_helper(2, 0, &[]); lex_k_compositions_helper(2, 1, &[&[2]]); lex_k_compositions_helper(2, 2, &[&[1, 1]]); lex_k_compositions_helper(2, 3, &[]); lex_k_compositions_helper(5, 0, &[]); lex_k_compositions_helper(5, 1, &[&[5]]); lex_k_compositions_helper(5, 2, &[&[1, 4], &[2, 3], &[3, 2], &[4, 1]]); lex_k_compositions_helper( 5, 3, &[&[1, 1, 3], &[1, 2, 2], &[1, 3, 1], &[2, 1, 2], &[2, 2, 1], &[3, 1, 1]], ); lex_k_compositions_helper( 5, 4, &[&[1, 1, 1, 2], &[1, 1, 2, 1], &[1, 2, 1, 1], &[2, 1, 1, 1]], ); lex_k_compositions_helper(5, 5, &[&[1, 1, 1, 1, 1]]); lex_k_compositions_helper(5, 6, &[]); lex_k_compositions_helper( 10, 5, &[ &[1, 1, 1, 1, 6], &[1, 1, 1, 2, 5], &[1, 1, 1, 3, 4], &[1, 1, 1, 4, 3], &[1, 1, 1, 5, 2], &[1, 1, 1, 6, 1], &[1, 1, 2, 1, 5], &[1, 1, 2, 2, 4], &[1, 1, 2, 3, 3], &[1, 1, 2, 4, 2], &[1, 1, 2, 5, 1], &[1, 1, 3, 1, 4], &[1, 1, 3, 2, 3], &[1, 1, 3, 3, 2], &[1, 1, 3, 4, 1], &[1, 1, 4, 1, 3], &[1, 1, 4, 2, 2], &[1, 1, 4, 3, 1], &[1, 1, 5, 1, 2], &[1, 1, 5, 2, 1], &[1, 1, 6, 1, 1], &[1, 2, 1, 1, 5], &[1, 2, 1, 2, 4], &[1, 2, 1, 3, 3], &[1, 2, 1, 4, 2], &[1, 2, 1, 5, 1], &[1, 2, 2, 1, 4], &[1, 2, 2, 2, 3], &[1, 2, 2, 3, 2], &[1, 2, 2, 4, 1], &[1, 2, 3, 1, 3], &[1, 2, 3, 2, 2], &[1, 2, 3, 3, 1], &[1, 2, 4, 1, 2], &[1, 2, 4, 2, 1], &[1, 2, 5, 1, 1], &[1, 3, 1, 1, 4], &[1, 3, 1, 2, 3], &[1, 3, 1, 3, 2], &[1, 3, 1, 4, 1], &[1, 3, 2, 1, 3], &[1, 3, 2, 2, 2], &[1, 3, 2, 3, 1], &[1, 3, 3, 1, 2], &[1, 3, 3, 2, 1], &[1, 3, 4, 1, 1], &[1, 4, 1, 1, 3], &[1, 4, 1, 2, 2], &[1, 4, 1, 3, 1], &[1, 4, 2, 1, 2], &[1, 4, 2, 2, 1], &[1, 4, 3, 1, 1], &[1, 5, 1, 1, 2], &[1, 5, 1, 2, 1], &[1, 5, 2, 1, 1], &[1, 6, 1, 1, 1], &[2, 1, 1, 1, 5], &[2, 1, 1, 2, 4], &[2, 1, 1, 3, 3], &[2, 1, 1, 4, 2], &[2, 1, 1, 5, 1], &[2, 1, 2, 1, 4], &[2, 1, 2, 2, 3], &[2, 1, 2, 3, 2], &[2, 1, 2, 4, 1], &[2, 1, 3, 1, 3], &[2, 1, 3, 2, 2], &[2, 1, 3, 3, 1], &[2, 1, 4, 1, 2], &[2, 1, 4, 2, 1], &[2, 1, 5, 1, 1], &[2, 2, 1, 1, 4], &[2, 2, 1, 2, 3], &[2, 2, 1, 3, 2], &[2, 2, 1, 4, 1], &[2, 2, 2, 1, 3], &[2, 2, 2, 2, 2], &[2, 2, 2, 3, 1], &[2, 2, 3, 1, 2], &[2, 2, 3, 2, 1], &[2, 2, 4, 1, 1], &[2, 3, 1, 1, 3], &[2, 3, 1, 2, 2], &[2, 3, 1, 3, 1], &[2, 3, 2, 1, 2], &[2, 3, 2, 2, 1], &[2, 3, 3, 1, 1], &[2, 4, 1, 1, 2], &[2, 4, 1, 2, 1], &[2, 4, 2, 1, 1], &[2, 5, 1, 1, 1], &[3, 1, 1, 1, 4], &[3, 1, 1, 2, 3], &[3, 1, 1, 3, 2], &[3, 1, 1, 4, 1], &[3, 1, 2, 1, 3], &[3, 1, 2, 2, 2], &[3, 1, 2, 3, 1], &[3, 1, 3, 1, 2], &[3, 1, 3, 2, 1], &[3, 1, 4, 1, 1], &[3, 2, 1, 1, 3], &[3, 2, 1, 2, 2], &[3, 2, 1, 3, 1], &[3, 2, 2, 1, 2], &[3, 2, 2, 2, 1], &[3, 2, 3, 1, 1], &[3, 3, 1, 1, 2], &[3, 3, 1, 2, 1], &[3, 3, 2, 1, 1], &[3, 4, 1, 1, 1], &[4, 1, 1, 1, 3], &[4, 1, 1, 2, 2], &[4, 1, 1, 3, 1], &[4, 1, 2, 1, 2], &[4, 1, 2, 2, 1], &[4, 1, 3, 1, 1], &[4, 2, 1, 1, 2], &[4, 2, 1, 2, 1], &[4, 2, 2, 1, 1], &[4, 3, 1, 1, 1], &[5, 1, 1, 1, 2], &[5, 1, 1, 2, 1], &[5, 1, 2, 1, 1], &[5, 2, 1, 1, 1], &[6, 1, 1, 1, 1], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_ordered_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs; use std::fmt::Debug; fn lex_ordered_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_ordered_unique_vecs(xs), out); } fn lex_ordered_unique_vecs_small_helper( xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_ordered_unique_vecs(xs), out_len, out); } #[test] fn test_lex_ordered_unique_vecs() { lex_ordered_unique_vecs_small_helper(nevers(), 1, &[&[]]); lex_ordered_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); lex_ordered_unique_vecs_small_helper( exhaustive_bools(), 4, &[&[], &[false], &[false, true], &[true]], ); lex_ordered_unique_vecs_small_helper( 1..=6, 64, &[ &[], &[1], &[1, 2], &[1, 2, 3], &[1, 2, 3, 4], &[1, 2, 3, 4, 5], &[1, 2, 3, 4, 5, 6], &[1, 2, 3, 4, 6], &[1, 2, 3, 5], &[1, 2, 3, 5, 6], &[1, 2, 3, 6], &[1, 2, 4], &[1, 2, 4, 5], &[1, 2, 4, 5, 6], &[1, 2, 4, 6], &[1, 2, 5], &[1, 2, 5, 6], &[1, 2, 6], &[1, 3], &[1, 3, 4], ], ); lex_ordered_unique_vecs_small_helper( 'a'..='c', 8, &[&[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['b'], &['b', 'c'], &['c']], ); lex_ordered_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_ordered_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_fixed_length; use std::fmt::Debug; fn lex_ordered_unique_vecs_fixed_length_helper(len: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_ordered_unique_vecs_fixed_length(len, xs), out); } fn lex_ordered_unique_vecs_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( lex_ordered_unique_vecs_fixed_length(len, xs), out_len, out, ); } #[test] fn test_lex_ordered_unique_vecs_fixed_length() { // This demonstrates that 0 ^ 0 == 1: lex_ordered_unique_vecs_fixed_length_small_helper(0, nevers(), 1, &[&[]]); lex_ordered_unique_vecs_fixed_length_small_helper(1, nevers(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper(2, nevers(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper(5, nevers(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper(1, exhaustive_units(), 1, &[&[()]]); lex_ordered_unique_vecs_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper(0, exhaustive_unsigneds::(), 1, &[&[]]); lex_ordered_unique_vecs_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_ordered_unique_vecs_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_ordered_unique_vecs_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 32640, &[ &[0, 1], &[0, 2], &[0, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[0, 8], &[0, 9], &[0, 10], &[0, 11], &[0, 12], &[0, 13], &[0, 14], &[0, 15], &[0, 16], &[0, 17], &[0, 18], &[0, 19], &[0, 20], ], ); lex_ordered_unique_vecs_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ &[0, 1, 2], &[0, 1, 3], &[0, 1, 4], &[0, 1, 5], &[0, 1, 6], &[0, 1, 7], &[0, 1, 8], &[0, 1, 9], &[0, 1, 10], &[0, 1, 11], &[0, 1, 12], &[0, 1, 13], &[0, 1, 14], &[0, 1, 15], &[0, 1, 16], &[0, 1, 17], &[0, 1, 18], &[0, 1, 19], &[0, 1, 20], &[0, 1, 21], ], ); lex_ordered_unique_vecs_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 8128, &[ &['a', 'b'], &['a', 'c'], &['a', 'd'], &['a', 'e'], &['a', 'f'], &['a', 'g'], &['a', 'h'], &['a', 'i'], &['a', 'j'], &['a', 'k'], &['a', 'l'], &['a', 'm'], &['a', 'n'], &['a', 'o'], &['a', 'p'], &['a', 'q'], &['a', 'r'], &['a', 's'], &['a', 't'], &['a', 'u'], ], ); lex_ordered_unique_vecs_fixed_length_small_helper( 1, exhaustive_bools(), 2, &[&[false], &[true]], ); lex_ordered_unique_vecs_fixed_length_small_helper(2, exhaustive_bools(), 1, &[&[false, true]]); lex_ordered_unique_vecs_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); lex_ordered_unique_vecs_fixed_length_small_helper( 4, 1..=6, 15, &[ &[1, 2, 3, 4], &[1, 2, 3, 5], &[1, 2, 3, 6], &[1, 2, 4, 5], &[1, 2, 4, 6], &[1, 2, 5, 6], &[1, 3, 4, 5], &[1, 3, 4, 6], &[1, 3, 5, 6], &[1, 4, 5, 6], &[2, 3, 4, 5], &[2, 3, 4, 6], &[2, 3, 5, 6], &[2, 4, 5, 6], &[3, 4, 5, 6], ], ); lex_ordered_unique_vecs_fixed_length_helper( 2, lex_ordered_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ &[vec![0, 1], vec![0, 2]], &[vec![0, 1], vec![0, 3]], &[vec![0, 1], vec![0, 4]], &[vec![0, 1], vec![0, 5]], &[vec![0, 1], vec![0, 6]], &[vec![0, 1], vec![0, 7]], &[vec![0, 1], vec![0, 8]], &[vec![0, 1], vec![0, 9]], &[vec![0, 1], vec![0, 10]], &[vec![0, 1], vec![0, 11]], &[vec![0, 1], vec![0, 12]], &[vec![0, 1], vec![0, 13]], &[vec![0, 1], vec![0, 14]], &[vec![0, 1], vec![0, 15]], &[vec![0, 1], vec![0, 16]], &[vec![0, 1], vec![0, 17]], &[vec![0, 1], vec![0, 18]], &[vec![0, 1], vec![0, 19]], &[vec![0, 1], vec![0, 20]], &[vec![0, 1], vec![0, 21]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_ordered_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn lex_ordered_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( lex_ordered_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_ordered_unique_vecs_length_inclusive_range() { lex_ordered_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); lex_ordered_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); lex_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[&[], &[()]], ); lex_ordered_unique_vecs_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); lex_ordered_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[&[false, true]], ); lex_ordered_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_ordered_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_length_range; use std::fmt::Debug; fn lex_ordered_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( lex_ordered_unique_vecs_length_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_ordered_unique_vecs_length_range() { lex_ordered_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); lex_ordered_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); lex_ordered_unique_vecs_length_range_small_helper(0, 5, exhaustive_units(), 2, &[&[], &[()]]); lex_ordered_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_ordered_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); lex_ordered_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); lex_ordered_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[&[false, true]], ); lex_ordered_unique_vecs_length_range_small_helper( 1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_ordered_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs_min_length; use std::fmt::Debug; fn lex_ordered_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_ordered_unique_vecs_min_length(min_length, xs), out); } fn lex_ordered_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( lex_ordered_unique_vecs_min_length(min_length, xs), out_len, out, ); } #[test] fn test_lex_ordered_unique_vecs_min_length() { lex_ordered_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); lex_ordered_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); lex_ordered_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); lex_ordered_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); lex_ordered_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 4, &[&[], &[false], &[false, true], &[true]], ); lex_ordered_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 3, &[&[false], &[false, true], &[true]], ); lex_ordered_unique_vecs_min_length_small_helper( 0, 'a'..='c', 8, &[&[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['b'], &['b', 'c'], &['c']], ); lex_ordered_unique_vecs_min_length_small_helper( 2, 'a'..='c', 4, &[&['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['b', 'c']], ); lex_ordered_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], ], ); lex_ordered_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', ], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_unique_vecs; use std::fmt::Debug; fn lex_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_unique_vecs(xs), out); } fn lex_unique_vecs_small_helper(xs: I, out_len: usize, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_unique_vecs(xs), out_len, out); } #[test] fn test_lex_unique_vecs() { lex_unique_vecs_small_helper(nevers(), 1, &[&[]]); lex_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); lex_unique_vecs_small_helper( exhaustive_bools(), 5, &[&[], &[false], &[false, true], &[true], &[true, false]], ); lex_unique_vecs_small_helper( 1..=6, 1957, &[ &[], &[1], &[1, 2], &[1, 2, 3], &[1, 2, 3, 4], &[1, 2, 3, 4, 5], &[1, 2, 3, 4, 5, 6], &[1, 2, 3, 4, 6], &[1, 2, 3, 4, 6, 5], &[1, 2, 3, 5], &[1, 2, 3, 5, 4], &[1, 2, 3, 5, 4, 6], &[1, 2, 3, 5, 6], &[1, 2, 3, 5, 6, 4], &[1, 2, 3, 6], &[1, 2, 3, 6, 4], &[1, 2, 3, 6, 4, 5], &[1, 2, 3, 6, 5], &[1, 2, 3, 6, 5, 4], &[1, 2, 4], ], ); lex_unique_vecs_small_helper( 'a'..='c', 16, &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['a', 'c', 'b'], &['b'], &['b', 'a'], &['b', 'a', 'c'], &['b', 'c'], &['b', 'c', 'a'], &['c'], &['c', 'a'], &['c', 'a', 'b'], &['c', 'b'], &['c', 'b', 'a'], ], ); lex_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_unique_vecs_fixed_length; use std::fmt::Debug; fn lex_unique_vecs_fixed_length_helper(len: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_unique_vecs_fixed_length(len, xs), out); } fn lex_unique_vecs_fixed_length_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_unique_vecs_fixed_length(len, xs), out_len, out); } #[test] fn test_lex_unique_vecs_fixed_length() { // This demonstrates that 0 ^ 0 == 1: lex_unique_vecs_fixed_length_small_helper(0, nevers(), 1, &[&[]]); lex_unique_vecs_fixed_length_small_helper(1, nevers(), 0, &[]); lex_unique_vecs_fixed_length_small_helper(2, nevers(), 0, &[]); lex_unique_vecs_fixed_length_small_helper(5, nevers(), 0, &[]); lex_unique_vecs_fixed_length_small_helper(1, exhaustive_units(), 1, &[&[()]]); lex_unique_vecs_fixed_length_small_helper(2, exhaustive_units(), 0, &[]); lex_unique_vecs_fixed_length_small_helper(5, exhaustive_units(), 0, &[]); lex_unique_vecs_fixed_length_small_helper(0, exhaustive_unsigneds::(), 1, &[&[]]); lex_unique_vecs_fixed_length_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_unique_vecs_fixed_length_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_unique_vecs_fixed_length_small_helper( 2, exhaustive_unsigneds::(), 65280, &[ &[0, 1], &[0, 2], &[0, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[0, 8], &[0, 9], &[0, 10], &[0, 11], &[0, 12], &[0, 13], &[0, 14], &[0, 15], &[0, 16], &[0, 17], &[0, 18], &[0, 19], &[0, 20], ], ); lex_unique_vecs_fixed_length_helper( 3, exhaustive_unsigneds::(), &[ &[0, 1, 2], &[0, 1, 3], &[0, 1, 4], &[0, 1, 5], &[0, 1, 6], &[0, 1, 7], &[0, 1, 8], &[0, 1, 9], &[0, 1, 10], &[0, 1, 11], &[0, 1, 12], &[0, 1, 13], &[0, 1, 14], &[0, 1, 15], &[0, 1, 16], &[0, 1, 17], &[0, 1, 18], &[0, 1, 19], &[0, 1, 20], &[0, 1, 21], ], ); lex_unique_vecs_fixed_length_small_helper( 2, exhaustive_ascii_chars(), 16256, &[ &['a', 'b'], &['a', 'c'], &['a', 'd'], &['a', 'e'], &['a', 'f'], &['a', 'g'], &['a', 'h'], &['a', 'i'], &['a', 'j'], &['a', 'k'], &['a', 'l'], &['a', 'm'], &['a', 'n'], &['a', 'o'], &['a', 'p'], &['a', 'q'], &['a', 'r'], &['a', 's'], &['a', 't'], &['a', 'u'], ], ); lex_unique_vecs_fixed_length_small_helper(1, exhaustive_bools(), 2, &[&[false], &[true]]); lex_unique_vecs_fixed_length_small_helper( 2, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); lex_unique_vecs_fixed_length_small_helper(4, exhaustive_bools(), 0, &[]); lex_unique_vecs_fixed_length_small_helper( 4, 1..=6, 360, &[ &[1, 2, 3, 4], &[1, 2, 3, 5], &[1, 2, 3, 6], &[1, 2, 4, 3], &[1, 2, 4, 5], &[1, 2, 4, 6], &[1, 2, 5, 3], &[1, 2, 5, 4], &[1, 2, 5, 6], &[1, 2, 6, 3], &[1, 2, 6, 4], &[1, 2, 6, 5], &[1, 3, 2, 4], &[1, 3, 2, 5], &[1, 3, 2, 6], &[1, 3, 4, 2], &[1, 3, 4, 5], &[1, 3, 4, 6], &[1, 3, 5, 2], &[1, 3, 5, 4], ], ); lex_unique_vecs_fixed_length_helper( 2, lex_unique_vecs_fixed_length(2, exhaustive_unsigneds::()), &[ &[vec![0, 1], vec![0, 2]], &[vec![0, 1], vec![0, 3]], &[vec![0, 1], vec![0, 4]], &[vec![0, 1], vec![0, 5]], &[vec![0, 1], vec![0, 6]], &[vec![0, 1], vec![0, 7]], &[vec![0, 1], vec![0, 8]], &[vec![0, 1], vec![0, 9]], &[vec![0, 1], vec![0, 10]], &[vec![0, 1], vec![0, 11]], &[vec![0, 1], vec![0, 12]], &[vec![0, 1], vec![0, 13]], &[vec![0, 1], vec![0, 14]], &[vec![0, 1], vec![0, 15]], &[vec![0, 1], vec![0, 16]], &[vec![0, 1], vec![0, 17]], &[vec![0, 1], vec![0, 18]], &[vec![0, 1], vec![0, 19]], &[vec![0, 1], vec![0, 20]], &[vec![0, 1], vec![0, 21]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn lex_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( lex_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_lex_unique_vecs_length_inclusive_range() { lex_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); lex_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); lex_unique_vecs_length_inclusive_range_small_helper(0, 4, exhaustive_units(), 2, &[&[], &[()]]); lex_unique_vecs_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); lex_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); lex_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_unique_vecs_length_range; use std::fmt::Debug; fn lex_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_unique_vecs_length_range(a, b, xs), out_len, out); } #[test] fn test_lex_unique_vecs_length_range() { lex_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); lex_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); lex_unique_vecs_length_range_small_helper(0, 5, exhaustive_units(), 2, &[&[], &[()]]); lex_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); lex_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); lex_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); lex_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); lex_unique_vecs_length_range_small_helper(1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']]); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_unique_vecs_min_length; use std::fmt::Debug; fn lex_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_unique_vecs_min_length(min_length, xs), out); } fn lex_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_unique_vecs_min_length(min_length, xs), out_len, out); } #[test] fn test_lex_unique_vecs_min_length() { lex_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); lex_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); lex_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); lex_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); lex_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 5, &[&[], &[false], &[false, true], &[true], &[true, false]], ); lex_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 4, &[&[false], &[false, true], &[true], &[true, false]], ); lex_unique_vecs_min_length_small_helper( 0, 'a'..='c', 16, &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['a', 'c', 'b'], &['b'], &['b', 'a'], &['b', 'a', 'c'], &['b', 'c'], &['b', 'c', 'a'], &['c'], &['c', 'a'], &['c', 'a', 'b'], &['c', 'b'], &['c', 'b', 'a'], ], ); lex_unique_vecs_min_length_small_helper( 2, 'a'..='c', 12, &[ &['a', 'b'], &['a', 'b', 'c'], &['a', 'c'], &['a', 'c', 'b'], &['b', 'a'], &['b', 'a', 'c'], &['b', 'c'], &['b', 'c', 'a'], &['c', 'a'], &['c', 'a', 'b'], &['c', 'b'], &['c', 'b', 'a'], ], ); lex_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['a', 'b'], &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], ], ); lex_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'c', 'd'], &['a', 'b', 'c', 'd', 'e'], &['a', 'b', 'c', 'd', 'e', 'f'], &['a', 'b', 'c', 'd', 'e', 'f', 'g'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'], &['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', ], &[ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', ], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_vecs_fixed_length_from_single.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::lex_vecs_fixed_length_from_single; use std::fmt::Debug; fn lex_vecs_fixed_length_from_single_helper(len: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_vecs_fixed_length_from_single(len, xs), out); } fn lex_vecs_fixed_length_from_single_small_helper( len: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_vecs_fixed_length_from_single(len, xs), out_len, out); } #[test] fn test_lex_vecs_fixed_length_from_single() { // This demonstrates that 0 ^ 0 == 1: lex_vecs_fixed_length_from_single_small_helper(0, nevers(), 1, &[&[]]); lex_vecs_fixed_length_from_single_small_helper(1, nevers(), 0, &[]); lex_vecs_fixed_length_from_single_small_helper(2, nevers(), 0, &[]); lex_vecs_fixed_length_from_single_small_helper(5, nevers(), 0, &[]); lex_vecs_fixed_length_from_single_small_helper(1, exhaustive_units(), 1, &[&[()]]); lex_vecs_fixed_length_from_single_small_helper(2, exhaustive_units(), 1, &[&[(), ()]]); lex_vecs_fixed_length_from_single_small_helper(5, exhaustive_units(), 1, &[&[(); 5]]); lex_vecs_fixed_length_from_single_small_helper(0, exhaustive_unsigneds::(), 1, &[&[]]); lex_vecs_fixed_length_from_single_small_helper( 1, exhaustive_unsigneds::(), 256, &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_vecs_fixed_length_from_single_helper( 1, exhaustive_unsigneds::(), &[ &[0], &[1], &[2], &[3], &[4], &[5], &[6], &[7], &[8], &[9], &[10], &[11], &[12], &[13], &[14], &[15], &[16], &[17], &[18], &[19], ], ); lex_vecs_fixed_length_from_single_small_helper( 2, exhaustive_unsigneds::(), 0x10000, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[0, 8], &[0, 9], &[0, 10], &[0, 11], &[0, 12], &[0, 13], &[0, 14], &[0, 15], &[0, 16], &[0, 17], &[0, 18], &[0, 19], ], ); lex_vecs_fixed_length_from_single_helper( 3, exhaustive_unsigneds::(), &[ &[0, 0, 0], &[0, 0, 1], &[0, 0, 2], &[0, 0, 3], &[0, 0, 4], &[0, 0, 5], &[0, 0, 6], &[0, 0, 7], &[0, 0, 8], &[0, 0, 9], &[0, 0, 10], &[0, 0, 11], &[0, 0, 12], &[0, 0, 13], &[0, 0, 14], &[0, 0, 15], &[0, 0, 16], &[0, 0, 17], &[0, 0, 18], &[0, 0, 19], ], ); lex_vecs_fixed_length_from_single_small_helper( 2, exhaustive_ascii_chars(), 0x4000, &[ &['a', 'a'], &['a', 'b'], &['a', 'c'], &['a', 'd'], &['a', 'e'], &['a', 'f'], &['a', 'g'], &['a', 'h'], &['a', 'i'], &['a', 'j'], &['a', 'k'], &['a', 'l'], &['a', 'm'], &['a', 'n'], &['a', 'o'], &['a', 'p'], &['a', 'q'], &['a', 'r'], &['a', 's'], &['a', 't'], ], ); lex_vecs_fixed_length_from_single_small_helper(1, exhaustive_bools(), 2, &[&[false], &[true]]); lex_vecs_fixed_length_from_single_small_helper( 2, exhaustive_bools(), 4, &[&[false, false], &[false, true], &[true, false], &[true, true]], ); lex_vecs_fixed_length_from_single_small_helper( 4, exhaustive_bools(), 16, &[ &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], &[false, true, false, true], &[false, true, true, false], &[false, true, true, true], &[true, false, false, false], &[true, false, false, true], &[true, false, true, false], &[true, false, true, true], &[true, true, false, false], &[true, true, false, true], &[true, true, true, false], &[true, true, true, true], ], ); lex_vecs_fixed_length_from_single_small_helper( 10, exhaustive_bools(), 1024, &[ &[false, false, false, false, false, false, false, false, false, false], &[false, false, false, false, false, false, false, false, false, true], &[false, false, false, false, false, false, false, false, true, false], &[false, false, false, false, false, false, false, false, true, true], &[false, false, false, false, false, false, false, true, false, false], &[false, false, false, false, false, false, false, true, false, true], &[false, false, false, false, false, false, false, true, true, false], &[false, false, false, false, false, false, false, true, true, true], &[false, false, false, false, false, false, true, false, false, false], &[false, false, false, false, false, false, true, false, false, true], &[false, false, false, false, false, false, true, false, true, false], &[false, false, false, false, false, false, true, false, true, true], &[false, false, false, false, false, false, true, true, false, false], &[false, false, false, false, false, false, true, true, false, true], &[false, false, false, false, false, false, true, true, true, false], &[false, false, false, false, false, false, true, true, true, true], &[false, false, false, false, false, true, false, false, false, false], &[false, false, false, false, false, true, false, false, false, true], &[false, false, false, false, false, true, false, false, true, false], &[false, false, false, false, false, true, false, false, true, true], ], ); lex_vecs_fixed_length_from_single_small_helper( 10, 0..3, 59049, &[ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 2], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 1], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 2], &[0, 0, 0, 0, 0, 0, 0, 0, 2, 0], &[0, 0, 0, 0, 0, 0, 0, 0, 2, 1], &[0, 0, 0, 0, 0, 0, 0, 0, 2, 2], &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0], &[0, 0, 0, 0, 0, 0, 0, 1, 0, 1], &[0, 0, 0, 0, 0, 0, 0, 1, 0, 2], &[0, 0, 0, 0, 0, 0, 0, 1, 1, 0], &[0, 0, 0, 0, 0, 0, 0, 1, 1, 1], &[0, 0, 0, 0, 0, 0, 0, 1, 1, 2], &[0, 0, 0, 0, 0, 0, 0, 1, 2, 0], &[0, 0, 0, 0, 0, 0, 0, 1, 2, 1], &[0, 0, 0, 0, 0, 0, 0, 1, 2, 2], &[0, 0, 0, 0, 0, 0, 0, 2, 0, 0], &[0, 0, 0, 0, 0, 0, 0, 2, 0, 1], ], ); lex_vecs_fixed_length_from_single_helper( 2, lex_vecs_fixed_length_from_single(2, exhaustive_unsigneds::()), &[ &[vec![0, 0], vec![0, 0]], &[vec![0, 0], vec![0, 1]], &[vec![0, 0], vec![0, 2]], &[vec![0, 0], vec![0, 3]], &[vec![0, 0], vec![0, 4]], &[vec![0, 0], vec![0, 5]], &[vec![0, 0], vec![0, 6]], &[vec![0, 0], vec![0, 7]], &[vec![0, 0], vec![0, 8]], &[vec![0, 0], vec![0, 9]], &[vec![0, 0], vec![0, 10]], &[vec![0, 0], vec![0, 11]], &[vec![0, 0], vec![0, 12]], &[vec![0, 0], vec![0, 13]], &[vec![0, 0], vec![0, 14]], &[vec![0, 0], vec![0, 15]], &[vec![0, 0], vec![0, 16]], &[vec![0, 0], vec![0, 17]], &[vec![0, 0], vec![0, 18]], &[vec![0, 0], vec![0, 19]], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_vecs_fixed_length_m_inputs.rs ================================================ // Copyright © 2026 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::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::{exhaustive_positive_primitive_ints, exhaustive_unsigneds}; use malachite_base::vecs::exhaustive::lex_vecs_fixed_length_2_inputs; use std::fmt::Debug; use std::iter::empty; fn lex_vecs_fixed_length_2_inputs_helper< T: Clone + Debug + Eq, I: Clone + Iterator, J: Clone + Iterator, >( xs: &I, ys: &J, output_to_input_map: &[usize], out_len: Option, out: &[&[T]], ) { let xss = lex_vecs_fixed_length_2_inputs(xs.clone(), ys.clone(), output_to_input_map); let xss_prefix = xss.clone().take(20).collect_vec(); assert_eq!( xss_prefix .iter() .map(Vec::as_slice) .collect_vec() .as_slice(), out ); if let Some(out_len) = out_len { assert_eq!(xss.count(), out_len); } } #[test] fn test_lex_vecs_fixed_length_2_inputs() { lex_vecs_fixed_length_2_inputs_helper(&nevers(), &nevers(), &[0, 1], Some(0), &[]); lex_vecs_fixed_length_2_inputs_helper( &empty(), &exhaustive_unsigneds::(), &[0, 1], Some(0), &[], ); lex_vecs_fixed_length_2_inputs_helper( &exhaustive_unsigneds::(), &exhaustive_positive_primitive_ints::(), &[0, 1], None, &[ &[0, 1], &[0, 2], &[0, 3], &[0, 4], &[0, 5], &[0, 6], &[0, 7], &[0, 8], &[0, 9], &[0, 10], &[0, 11], &[0, 12], &[0, 13], &[0, 14], &[0, 15], &[0, 16], &[0, 17], &[0, 18], &[0, 19], &[0, 20], ], ); lex_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), &[0, 1], Some(384), &[ &['a', 'x'], &['a', 'y'], &['a', 'z'], &['b', 'x'], &['b', 'y'], &['b', 'z'], &['c', 'x'], &['c', 'y'], &['c', 'z'], &['d', 'x'], &['d', 'y'], &['d', 'z'], &['e', 'x'], &['e', 'y'], &['e', 'z'], &['f', 'x'], &['f', 'y'], &['f', 'z'], &['g', 'x'], &['g', 'y'], ], ); lex_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), &[0, 1, 1], Some(1152), &[ &['a', 'x', 'x'], &['a', 'x', 'y'], &['a', 'x', 'z'], &['a', 'y', 'x'], &['a', 'y', 'y'], &['a', 'y', 'z'], &['a', 'z', 'x'], &['a', 'z', 'y'], &['a', 'z', 'z'], &['b', 'x', 'x'], &['b', 'x', 'y'], &['b', 'x', 'z'], &['b', 'y', 'x'], &['b', 'y', 'y'], &['b', 'y', 'z'], &['b', 'z', 'x'], &['b', 'z', 'y'], &['b', 'z', 'z'], &['c', 'x', 'x'], &['c', 'x', 'y'], ], ); lex_vecs_fixed_length_2_inputs_helper( &exhaustive_ascii_chars(), &['x', 'y', 'z'].iter().copied(), &[0, 1, 0], Some(49152), &[ &['a', 'x', 'a'], &['a', 'x', 'b'], &['a', 'x', 'c'], &['a', 'x', 'd'], &['a', 'x', 'e'], &['a', 'x', 'f'], &['a', 'x', 'g'], &['a', 'x', 'h'], &['a', 'x', 'i'], &['a', 'x', 'j'], &['a', 'x', 'k'], &['a', 'x', 'l'], &['a', 'x', 'm'], &['a', 'x', 'n'], &['a', 'x', 'o'], &['a', 'x', 'p'], &['a', 'x', 'q'], &['a', 'x', 'r'], &['a', 'x', 's'], &['a', 'x', 't'], ], ); } #[test] #[should_panic] fn lex_vecs_fixed_length_2_inputs_fail_1() { lex_vecs_fixed_length_2_inputs(0..2, 0..3, &[]); } #[test] #[should_panic] fn lex_vecs_fixed_length_2_inputs_fail_2() { lex_vecs_fixed_length_2_inputs(0..2, 0..3, &[0]); } #[test] #[should_panic] fn lex_vecs_fixed_length_2_inputs_fail_3() { lex_vecs_fixed_length_2_inputs(0..2, 0..3, &[1]); } #[test] #[should_panic] fn lex_vecs_fixed_length_2_inputs_fail_4() { lex_vecs_fixed_length_2_inputs(0..2, 0..3, &[0, 1, 2]); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/lex_vecs_length_n.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::lex_vecs_length_3; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::vecs::exhaustive::{ exhaustive_vecs_fixed_length_from_single, lex_vecs_length_2, }; use std::cmp::Ordering::*; use std::fmt::Debug; use std::iter::{empty, once}; fn lex_vecs_length_2_helper, J: Iterator>( xs: I, ys: J, out: &[&[T]], ) { exhaustive_vecs_helper_helper(lex_vecs_length_2(xs, ys), out); } fn lex_vecs_length_2_finite_helper< T: Clone + Debug + Eq, I: Clone + Iterator, J: Clone + Iterator, >( xs: I, ys: J, out_len: usize, out: &[&[T]], ) { exhaustive_vecs_small_helper_helper(lex_vecs_length_2(xs, ys), out_len, out); } #[test] fn test_lex_vecs_length_2() { lex_vecs_length_2_finite_helper(nevers(), nevers(), 0, &[]); lex_vecs_length_2_finite_helper(empty(), 0..4, 0, &[]); lex_vecs_length_2_finite_helper(once(0), once(1), 1, &[&[0, 1]]); lex_vecs_length_2_finite_helper(once(0), 0..4, 4, &[&[0, 0], &[0, 1], &[0, 2], &[0, 3]]); lex_vecs_length_2_finite_helper( exhaustive_unsigneds::(), 0..4, 1024, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[2, 2], &[2, 3], &[3, 0], &[3, 1], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[4, 2], &[4, 3], ], ); lex_vecs_length_2_helper( exhaustive_unsigneds::(), 0..4, &[ &[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3], &[2, 0], &[2, 1], &[2, 2], &[2, 3], &[3, 0], &[3, 1], &[3, 2], &[3, 3], &[4, 0], &[4, 1], &[4, 2], &[4, 3], ], ); lex_vecs_length_2_finite_helper( 0..2, 0..4, 8, &[&[0, 0], &[0, 1], &[0, 2], &[0, 3], &[1, 0], &[1, 1], &[1, 2], &[1, 3]], ); lex_vecs_length_2_finite_helper( 0..5, 0..3, 15, &[ &[0, 0], &[0, 1], &[0, 2], &[1, 0], &[1, 1], &[1, 2], &[2, 0], &[2, 1], &[2, 2], &[3, 0], &[3, 1], &[3, 2], &[4, 0], &[4, 1], &[4, 2], ], ); lex_vecs_length_2_finite_helper( ['a', 'b', 'c'].iter().copied(), ['x', 'y', 'z'].iter().copied(), 9, &[ &['a', 'x'], &['a', 'y'], &['a', 'z'], &['b', 'x'], &['b', 'y'], &['b', 'z'], &['c', 'x'], &['c', 'y'], &['c', 'z'], ], ); lex_vecs_length_2_finite_helper( lex_vecs_length_2(exhaustive_orderings(), [Less, Greater].iter().copied()), exhaustive_vecs_fixed_length_from_single(3, [Less, Greater].iter().copied()), 48, &[ &[vec![Equal, Less], vec![Less, Less, Less]], &[vec![Equal, Less], vec![Less, Less, Greater]], &[vec![Equal, Less], vec![Less, Greater, Less]], &[vec![Equal, Less], vec![Less, Greater, Greater]], &[vec![Equal, Less], vec![Greater, Less, Less]], &[vec![Equal, Less], vec![Greater, Less, Greater]], &[vec![Equal, Less], vec![Greater, Greater, Less]], &[vec![Equal, Less], vec![Greater, Greater, Greater]], &[vec![Equal, Greater], vec![Less, Less, Less]], &[vec![Equal, Greater], vec![Less, Less, Greater]], &[vec![Equal, Greater], vec![Less, Greater, Less]], &[vec![Equal, Greater], vec![Less, Greater, Greater]], &[vec![Equal, Greater], vec![Greater, Less, Less]], &[vec![Equal, Greater], vec![Greater, Less, Greater]], &[vec![Equal, Greater], vec![Greater, Greater, Less]], &[vec![Equal, Greater], vec![Greater, Greater, Greater]], &[vec![Less, Less], vec![Less, Less, Less]], &[vec![Less, Less], vec![Less, Less, Greater]], &[vec![Less, Less], vec![Less, Greater, Less]], &[vec![Less, Less], vec![Less, Greater, Greater]], ], ); } fn lex_vecs_length_3_helper< T, I: Iterator, J: Iterator, K: Iterator, >( xs: I, ys: J, zs: K, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(lex_vecs_length_3(xs, ys, zs), out); } fn lex_vecs_length_3_finite_helper< T, I: Clone + Iterator, J: Clone + Iterator, K: Clone + Iterator, >( xs: I, ys: J, zs: K, out_len: usize, out: &[&[T]], ) where T: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(lex_vecs_length_3(xs, ys, zs), out_len, out); } #[test] fn test_lex_vecs_length_3() { lex_vecs_length_3_finite_helper(nevers(), nevers(), nevers(), 0, &[]); lex_vecs_length_3_finite_helper(empty(), 0..4, 0..5, 0, &[]); lex_vecs_length_3_finite_helper(once(0), once(1), once(5), 1, &[&[0, 1, 5]]); lex_vecs_length_3_finite_helper( once(0), once(3), 0..4, 4, &[&[0, 3, 0], &[0, 3, 1], &[0, 3, 2], &[0, 3, 3]], ); lex_vecs_length_3_finite_helper( exhaustive_unsigneds::(), 0..4, 0..4, 4096, &[ &[0, 0, 0], &[0, 0, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 0], &[0, 1, 1], &[0, 1, 2], &[0, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 2, 2], &[0, 2, 3], &[0, 3, 0], &[0, 3, 1], &[0, 3, 2], &[0, 3, 3], &[1, 0, 0], &[1, 0, 1], &[1, 0, 2], &[1, 0, 3], ], ); lex_vecs_length_3_helper( exhaustive_unsigneds::(), 0..4, 0..4, &[ &[0, 0, 0], &[0, 0, 1], &[0, 0, 2], &[0, 0, 3], &[0, 1, 0], &[0, 1, 1], &[0, 1, 2], &[0, 1, 3], &[0, 2, 0], &[0, 2, 1], &[0, 2, 2], &[0, 2, 3], &[0, 3, 0], &[0, 3, 1], &[0, 3, 2], &[0, 3, 3], &[1, 0, 0], &[1, 0, 1], &[1, 0, 2], &[1, 0, 3], ], ); lex_vecs_length_3_finite_helper( 0..2, 0..3, 0..3, 18, &[ &[0, 0, 0], &[0, 0, 1], &[0, 0, 2], &[0, 1, 0], &[0, 1, 1], &[0, 1, 2], &[0, 2, 0], &[0, 2, 1], &[0, 2, 2], &[1, 0, 0], &[1, 0, 1], &[1, 0, 2], &[1, 1, 0], &[1, 1, 1], &[1, 1, 2], &[1, 2, 0], &[1, 2, 1], &[1, 2, 2], ], ); lex_vecs_length_3_finite_helper( 0..11, 0..12, 0..13, 1716, &[ &[0, 0, 0], &[0, 0, 1], &[0, 0, 2], &[0, 0, 3], &[0, 0, 4], &[0, 0, 5], &[0, 0, 6], &[0, 0, 7], &[0, 0, 8], &[0, 0, 9], &[0, 0, 10], &[0, 0, 11], &[0, 0, 12], &[0, 1, 0], &[0, 1, 1], &[0, 1, 2], &[0, 1, 3], &[0, 1, 4], &[0, 1, 5], &[0, 1, 6], ], ); lex_vecs_length_3_finite_helper( ['a', 'b', 'c'].iter().copied(), ['x', 'y', 'z'].iter().copied(), ['0', '1', '2'].iter().copied(), 27, &[ &['a', 'x', '0'], &['a', 'x', '1'], &['a', 'x', '2'], &['a', 'y', '0'], &['a', 'y', '1'], &['a', 'y', '2'], &['a', 'z', '0'], &['a', 'z', '1'], &['a', 'z', '2'], &['b', 'x', '0'], &['b', 'x', '1'], &['b', 'x', '2'], &['b', 'y', '0'], &['b', 'y', '1'], &['b', 'y', '2'], &['b', 'z', '0'], &['b', 'z', '1'], &['b', 'z', '2'], &['c', 'x', '0'], &['c', 'x', '1'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/next_bit_pattern.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::arithmetic::traits::BinomialCoefficient; use malachite_base::vecs::exhaustive::next_bit_pattern; fn pattern_to_string(pattern: &[bool]) -> String { let mut s = String::with_capacity(pattern.len()); for &b in pattern.iter().rev() { s.push(if b { '1' } else { '0' }); } s } fn next_bit_pattern_helper( width: usize, min_bits: usize, max_bits: usize, expected_patterns: &[&'static str], ) { assert!(min_bits <= max_bits); assert_ne!(max_bits, 0); assert!(width >= min_bits); let mut pattern: Vec = repeat_n(false, width).collect(); for b in &mut pattern[..min_bits] { *b = true; } let mut bit_count = min_bits; let mut patterns = Vec::new(); while pattern.len() == width { assert_eq!(pattern.iter().filter(|&&b| b).count(), bit_count); assert!(bit_count >= min_bits); assert!(bit_count <= max_bits); patterns.push(pattern_to_string(&pattern)); next_bit_pattern(&mut pattern, &mut bit_count, min_bits, max_bits); } assert_eq!( patterns.len(), (min_bits..=max_bits) .map(|b| usize::binomial_coefficient(width, b)) .sum() ); assert_eq!(patterns, expected_patterns); } #[test] fn test_next_bit_pattern() { next_bit_pattern_helper(5, 1, 1, &["00001", "00010", "00100", "01000", "10000"]); next_bit_pattern_helper( 5, 2, 2, &["00011", "00101", "00110", "01001", "01010", "01100", "10001", "10010", "10100", "11000"], ); next_bit_pattern_helper( 5, 3, 3, &["00111", "01011", "01101", "01110", "10011", "10101", "10110", "11001", "11010", "11100"], ); next_bit_pattern_helper(5, 4, 4, &["01111", "10111", "11011", "11101", "11110"]); next_bit_pattern_helper(5, 5, 5, &["11111"]); next_bit_pattern_helper( 5, 0, 1, &["00000", "00001", "00010", "00100", "01000", "10000"], ); next_bit_pattern_helper( 5, 1, 2, &[ "00001", "00010", "00011", "00100", "00101", "00110", "01000", "01001", "01010", "01100", "10000", "10001", "10010", "10100", "11000", ], ); next_bit_pattern_helper( 5, 2, 3, &[ "00011", "00101", "00110", "00111", "01001", "01010", "01011", "01100", "01101", "01110", "10001", "10010", "10011", "10100", "10101", "10110", "11000", "11001", "11010", "11100", ], ); next_bit_pattern_helper( 5, 3, 4, &[ "00111", "01011", "01101", "01110", "01111", "10011", "10101", "10110", "10111", "11001", "11010", "11011", "11100", "11101", "11110", ], ); next_bit_pattern_helper( 5, 4, 5, &["01111", "10111", "11011", "11101", "11110", "11111"], ); next_bit_pattern_helper( 5, 0, 2, &[ "00000", "00001", "00010", "00011", "00100", "00101", "00110", "01000", "01001", "01010", "01100", "10000", "10001", "10010", "10100", "11000", ], ); next_bit_pattern_helper( 5, 1, 3, &[ "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "11000", "11001", "11010", "11100", ], ); next_bit_pattern_helper( 5, 2, 4, &[ "00011", "00101", "00110", "00111", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", ], ); next_bit_pattern_helper( 5, 3, 5, &[ "00111", "01011", "01101", "01110", "01111", "10011", "10101", "10110", "10111", "11001", "11010", "11011", "11100", "11101", "11110", "11111", ], ); next_bit_pattern_helper( 5, 0, 3, &[ "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "11000", "11001", "11010", "11100", ], ); next_bit_pattern_helper( 5, 1, 4, &[ "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", ], ); next_bit_pattern_helper( 5, 2, 5, &[ "00011", "00101", "00110", "00111", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111", ], ); next_bit_pattern_helper( 5, 0, 4, &[ "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", ], ); next_bit_pattern_helper( 5, 1, 5, &[ "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111", ], ); next_bit_pattern_helper( 5, 0, 5, &[ "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111", ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_ordered_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs; use std::fmt::Debug; fn shortlex_ordered_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_ordered_unique_vecs(xs), out); } fn shortlex_ordered_unique_vecs_small_helper( xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(shortlex_ordered_unique_vecs(xs), out_len, out); } #[test] fn test_shortlex_ordered_unique_vecs() { shortlex_ordered_unique_vecs_small_helper(nevers(), 1, &[&[]]); shortlex_ordered_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); shortlex_ordered_unique_vecs_small_helper( exhaustive_bools(), 4, &[&[], &[false], &[true], &[false, true]], ); shortlex_ordered_unique_vecs_small_helper( 1..=6, 64, &[ &[], &[1], &[2], &[3], &[4], &[5], &[6], &[1, 2], &[1, 3], &[1, 4], &[1, 5], &[1, 6], &[2, 3], &[2, 4], &[2, 5], &[2, 6], &[3, 4], &[3, 5], &[3, 6], &[4, 5], ], ); shortlex_ordered_unique_vecs_small_helper( 'a'..='c', 8, &[&[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); shortlex_ordered_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_ordered_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_ordered_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_ordered_unique_vecs_length_inclusive_range() { shortlex_ordered_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[&[], &[()]], ); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( 1, 0, exhaustive_bools(), 0, &[], ); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 1, &[&[false, true]], ); shortlex_ordered_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_ordered_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_length_range; use std::fmt::Debug; fn shortlex_ordered_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_ordered_unique_vecs_length_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_ordered_unique_vecs_length_range() { shortlex_ordered_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); shortlex_ordered_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); shortlex_ordered_unique_vecs_length_range_small_helper( 0, 5, exhaustive_units(), 2, &[&[], &[()]], ); shortlex_ordered_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_ordered_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); shortlex_ordered_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); shortlex_ordered_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 1, &[&[false, true]], ); shortlex_ordered_unique_vecs_length_range_small_helper( 1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_ordered_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_ordered_unique_vecs_min_length; use std::fmt::Debug; fn shortlex_ordered_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_ordered_unique_vecs_min_length(min_length, xs), out); } fn shortlex_ordered_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_ordered_unique_vecs_min_length(min_length, xs), out_len, out, ); } #[test] fn test_shortlex_ordered_unique_vecs_min_length() { shortlex_ordered_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); shortlex_ordered_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); shortlex_ordered_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); shortlex_ordered_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); shortlex_ordered_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 4, &[&[], &[false], &[true], &[false, true]], ); shortlex_ordered_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 3, &[&[false], &[true], &[false, true]], ); shortlex_ordered_unique_vecs_min_length_small_helper( 0, 'a'..='c', 8, &[&[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); shortlex_ordered_unique_vecs_min_length_small_helper( 2, 'a'..='c', 4, &[&['a', 'b'], &['a', 'c'], &['b', 'c'], &['a', 'b', 'c']], ); shortlex_ordered_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); shortlex_ordered_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'd'], &['a', 'b', 'e'], &['a', 'b', 'f'], &['a', 'b', 'g'], &['a', 'b', 'h'], &['a', 'b', 'i'], &['a', 'b', 'j'], &['a', 'b', 'k'], &['a', 'b', 'l'], &['a', 'b', 'm'], &['a', 'b', 'n'], &['a', 'b', 'o'], &['a', 'b', 'p'], &['a', 'b', 'q'], &['a', 'b', 'r'], &['a', 'b', 's'], &['a', 'b', 't'], &['a', 'b', 'u'], &['a', 'b', 'v'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_unique_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_unique_vecs; use std::fmt::Debug; fn shortlex_unique_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_unique_vecs(xs), out); } fn shortlex_unique_vecs_small_helper(xs: I, out_len: usize, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(shortlex_unique_vecs(xs), out_len, out); } #[test] fn test_shortlex_unique_vecs() { shortlex_unique_vecs_small_helper(nevers(), 1, &[&[]]); shortlex_unique_vecs_small_helper(exhaustive_units(), 2, &[&[], &[()]]); shortlex_unique_vecs_small_helper( exhaustive_bools(), 5, &[&[], &[false], &[true], &[false, true], &[true, false]], ); shortlex_unique_vecs_small_helper( 1..=6, 1957, &[ &[], &[1], &[2], &[3], &[4], &[5], &[6], &[1, 2], &[1, 3], &[1, 4], &[1, 5], &[1, 6], &[2, 1], &[2, 3], &[2, 4], &[2, 5], &[2, 6], &[3, 1], &[3, 2], &[3, 4], ], ); shortlex_unique_vecs_small_helper( 'a'..='c', 16, &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['a', 'b', 'c'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); shortlex_unique_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn shortlex_unique_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_unique_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_unique_vecs_length_inclusive_range() { shortlex_unique_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); shortlex_unique_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); shortlex_unique_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 2, &[&[], &[()]], ); shortlex_unique_vecs_length_inclusive_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_unique_vecs_length_inclusive_range_small_helper( 0, 1, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); shortlex_unique_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); shortlex_unique_vecs_length_inclusive_range_small_helper( 1, 1, 'a'..='c', 3, &[&['a'], &['b'], &['c']], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_unique_vecs_length_range; use std::fmt::Debug; fn shortlex_unique_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(shortlex_unique_vecs_length_range(a, b, xs), out_len, out); } #[test] fn test_shortlex_unique_vecs_length_range() { shortlex_unique_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); shortlex_unique_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); shortlex_unique_vecs_length_range_small_helper(0, 5, exhaustive_units(), 2, &[&[], &[()]]); shortlex_unique_vecs_length_range_small_helper(1, 0, exhaustive_bools(), 0, &[]); shortlex_unique_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); shortlex_unique_vecs_length_range_small_helper( 0, 2, exhaustive_bools(), 3, &[&[], &[false], &[true]], ); shortlex_unique_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 2, &[&[false, true], &[true, false]], ); shortlex_unique_vecs_length_range_small_helper(1, 2, 'a'..='c', 3, &[&['a'], &['b'], &['c']]); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::{ exhaustive_vecs_helper_helper, exhaustive_vecs_small_helper_helper, }; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_unique_vecs_min_length; use std::fmt::Debug; fn shortlex_unique_vecs_min_length_helper( min_length: u64, xs: I, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_unique_vecs_min_length(min_length, xs), out); } fn shortlex_unique_vecs_min_length_small_helper( min_length: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_unique_vecs_min_length(min_length, xs), out_len, out, ); } #[test] fn test_shortlex_unique_vecs_min_length() { shortlex_unique_vecs_min_length_small_helper(0, nevers(), 1, &[&[]]); shortlex_unique_vecs_min_length_small_helper(4, nevers(), 0, &[]); shortlex_unique_vecs_min_length_small_helper(0, exhaustive_units(), 2, &[&[], &[()]]); shortlex_unique_vecs_min_length_small_helper(5, exhaustive_units(), 0, &[]); shortlex_unique_vecs_min_length_small_helper( 0, exhaustive_bools(), 5, &[&[], &[false], &[true], &[false, true], &[true, false]], ); shortlex_unique_vecs_min_length_small_helper( 1, exhaustive_bools(), 4, &[&[false], &[true], &[false, true], &[true, false]], ); shortlex_unique_vecs_min_length_small_helper( 0, 'a'..='c', 16, &[ &[], &['a'], &['b'], &['c'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['a', 'b', 'c'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); shortlex_unique_vecs_min_length_small_helper( 2, 'a'..='c', 12, &[ &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['a', 'b', 'c'], &['a', 'c', 'b'], &['b', 'a', 'c'], &['b', 'c', 'a'], &['c', 'a', 'b'], &['c', 'b', 'a'], ], ); shortlex_unique_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); shortlex_unique_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'b', 'c'], &['a', 'b', 'd'], &['a', 'b', 'e'], &['a', 'b', 'f'], &['a', 'b', 'g'], &['a', 'b', 'h'], &['a', 'b', 'i'], &['a', 'b', 'j'], &['a', 'b', 'k'], &['a', 'b', 'l'], &['a', 'b', 'm'], &['a', 'b', 'n'], &['a', 'b', 'o'], &['a', 'b', 'p'], &['a', 'b', 'q'], &['a', 'b', 'r'], &['a', 'b', 's'], &['a', 'b', 't'], &['a', 'b', 'u'], &['a', 'b', 'v'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_vecs.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_vecs; use std::fmt::Debug; fn shortlex_vecs_helper(xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_vecs(xs), out); } #[test] fn test_shortlex_vecs() { shortlex_vecs_helper(nevers(), &[&[]]); shortlex_vecs_helper( exhaustive_units(), &[ &[], &[()], &[(), ()], &[(), (), ()], &[(), (), (), ()], &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(); 16], &[(); 17], &[(); 18], &[(); 19], ], ); shortlex_vecs_helper( exhaustive_bools(), &[ &[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true], &[false, false, false], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], ], ); shortlex_vecs_helper( 'a'..='c', &[ &[], &['a'], &['b'], &['c'], &['a', 'a'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'b'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['c', 'c'], &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'c'], &['a', 'b', 'a'], &['a', 'b', 'b'], &['a', 'b', 'c'], &['a', 'c', 'a'], ], ); shortlex_vecs_helper( exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::num::exhaustive::exhaustive_unsigneds; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::vecs::exhaustive::shortlex_vecs_from_length_iterator; use std::fmt::Debug; use std::iter::empty; fn shortlex_vecs_from_element_iterator_helper, J: Clone + Iterator>( lengths: I, xs: J, out: &[&[J::Item]], ) where J::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_vecs_from_length_iterator(lengths, xs), out); } #[test] fn test_shortlex_vecs_from_element_iterator() { shortlex_vecs_from_element_iterator_helper(empty(), exhaustive_bools(), &[]); shortlex_vecs_from_element_iterator_helper( [2, 1, 2].iter().copied(), exhaustive_bools(), &[ &[false, false], &[false, true], &[true, false], &[true, true], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true], ], ); shortlex_vecs_from_element_iterator_helper( exhaustive_unsigneds::().map(|u| u << 1), exhaustive_bools(), &[ &[], &[false, false], &[false, true], &[true, false], &[true, true], &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], &[false, true, false, true], &[false, true, true, false], &[false, true, true, true], &[true, false, false, false], &[true, false, false, true], &[true, false, true, false], &[true, false, true, true], &[true, true, false, false], &[true, true, false, true], &[true, true, true, false], ], ); shortlex_vecs_from_element_iterator_helper( [2, 1, 0, 2].iter().copied(), exhaustive_bools(), &[ &[false, false], &[false, true], &[true, false], &[true, true], &[false], &[true], &[], &[false, false], &[false, true], &[true, false], &[true, true], ], ); // Stops after first empty ys shortlex_vecs_from_element_iterator_helper([0, 0, 1, 0].iter().copied(), nevers(), &[&[], &[]]); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_vecs_length_inclusive_range; use std::fmt::Debug; fn shortlex_vecs_length_inclusive_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper( shortlex_vecs_length_inclusive_range(a, b, xs), out_len, out, ); } #[test] fn test_shortlex_vecs_length_inclusive_range() { shortlex_vecs_length_inclusive_range_small_helper(0, 4, nevers(), 1, &[&[]]); shortlex_vecs_length_inclusive_range_small_helper(6, 9, nevers(), 0, &[]); shortlex_vecs_length_inclusive_range_small_helper(5, 3, exhaustive_bools(), 0, &[]); shortlex_vecs_length_inclusive_range_small_helper( 0, 4, exhaustive_units(), 5, &[&[], &[()], &[(), ()], &[(), (), ()], &[(), (), (), ()]], ); shortlex_vecs_length_inclusive_range_small_helper( 1, 1, exhaustive_bools(), 2, &[&[false], &[true]], ); shortlex_vecs_length_inclusive_range_small_helper( 0, 2, exhaustive_bools(), 7, &[&[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true]], ); shortlex_vecs_length_inclusive_range_small_helper( 2, 3, exhaustive_bools(), 12, &[ &[false, false], &[false, true], &[true, false], &[true, true], &[false, false, false], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], ], ); shortlex_vecs_length_inclusive_range_small_helper( 5, 7, 'a'..='c', 3159, &[ &['a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'a', 'c'], &['a', 'a', 'a', 'b', 'a'], &['a', 'a', 'a', 'b', 'b'], &['a', 'a', 'a', 'b', 'c'], &['a', 'a', 'a', 'c', 'a'], &['a', 'a', 'a', 'c', 'b'], &['a', 'a', 'a', 'c', 'c'], &['a', 'a', 'b', 'a', 'a'], &['a', 'a', 'b', 'a', 'b'], &['a', 'a', 'b', 'a', 'c'], &['a', 'a', 'b', 'b', 'a'], &['a', 'a', 'b', 'b', 'b'], &['a', 'a', 'b', 'b', 'c'], &['a', 'a', 'b', 'c', 'a'], &['a', 'a', 'b', 'c', 'b'], &['a', 'a', 'b', 'c', 'c'], &['a', 'a', 'c', 'a', 'a'], &['a', 'a', 'c', 'a', 'b'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_vecs_length_range.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_small_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_vecs_length_range; use std::fmt::Debug; fn shortlex_vecs_length_range_small_helper( a: u64, b: u64, xs: I, out_len: usize, out: &[&[I::Item]], ) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_small_helper_helper(shortlex_vecs_length_range(a, b, xs), out_len, out); } #[test] fn test_shortlex_vecs_length_range() { shortlex_vecs_length_range_small_helper(0, 5, nevers(), 1, &[&[]]); shortlex_vecs_length_range_small_helper(6, 10, nevers(), 0, &[]); shortlex_vecs_length_range_small_helper( 0, 5, exhaustive_units(), 5, &[&[], &[()], &[(), ()], &[(), (), ()], &[(), (), (), ()]], ); shortlex_vecs_length_range_small_helper(1, 1, exhaustive_bools(), 0, &[]); shortlex_vecs_length_range_small_helper(5, 3, exhaustive_bools(), 0, &[]); shortlex_vecs_length_range_small_helper( 0, 3, exhaustive_bools(), 7, &[&[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true]], ); shortlex_vecs_length_range_small_helper( 2, 4, exhaustive_bools(), 12, &[ &[false, false], &[false, true], &[true, false], &[true, true], &[false, false, false], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], ], ); shortlex_vecs_length_range_small_helper( 5, 8, 'a'..='c', 3159, &[ &['a', 'a', 'a', 'a', 'a'], &['a', 'a', 'a', 'a', 'b'], &['a', 'a', 'a', 'a', 'c'], &['a', 'a', 'a', 'b', 'a'], &['a', 'a', 'a', 'b', 'b'], &['a', 'a', 'a', 'b', 'c'], &['a', 'a', 'a', 'c', 'a'], &['a', 'a', 'a', 'c', 'b'], &['a', 'a', 'a', 'c', 'c'], &['a', 'a', 'b', 'a', 'a'], &['a', 'a', 'b', 'a', 'b'], &['a', 'a', 'b', 'a', 'c'], &['a', 'a', 'b', 'b', 'a'], &['a', 'a', 'b', 'b', 'b'], &['a', 'a', 'b', 'b', 'c'], &['a', 'a', 'b', 'c', 'a'], &['a', 'a', 'b', 'c', 'b'], &['a', 'a', 'b', 'c', 'c'], &['a', 'a', 'c', 'a', 'a'], &['a', 'a', 'c', 'a', 'b'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive/shortlex_vecs_min_length.rs ================================================ // Copyright © 2026 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 malachite_base::bools::exhaustive::exhaustive_bools; use malachite_base::chars::exhaustive::exhaustive_ascii_chars; use malachite_base::nevers::nevers; use malachite_base::test_util::vecs::exhaustive::exhaustive_vecs_helper_helper; use malachite_base::tuples::exhaustive::exhaustive_units; use malachite_base::vecs::exhaustive::shortlex_vecs_min_length; use std::fmt::Debug; fn shortlex_vecs_min_length_helper(min_length: u64, xs: I, out: &[&[I::Item]]) where I::Item: Clone + Debug + Eq, { exhaustive_vecs_helper_helper(shortlex_vecs_min_length(min_length, xs), out); } #[test] fn test_shortlex_vecs_min_length() { shortlex_vecs_min_length_helper(0, nevers(), &[&[]]); shortlex_vecs_min_length_helper(4, nevers(), &[]); shortlex_vecs_min_length_helper( 0, exhaustive_units(), &[ &[], &[()], &[(), ()], &[(), (), ()], &[(), (), (), ()], &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(); 16], &[(); 17], &[(); 18], &[(); 19], ], ); shortlex_vecs_min_length_helper( 5, exhaustive_units(), &[ &[(), (), (), (), ()], &[(), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(); 16], &[(); 17], &[(); 18], &[(); 19], &[(); 20], &[(); 21], &[(); 22], &[(); 23], &[(); 24], ], ); shortlex_vecs_min_length_helper( 0, exhaustive_bools(), &[ &[], &[false], &[true], &[false, false], &[false, true], &[true, false], &[true, true], &[false, false, false], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], ], ); shortlex_vecs_min_length_helper( 3, exhaustive_bools(), &[ &[false, false, false], &[false, false, true], &[false, true, false], &[false, true, true], &[true, false, false], &[true, false, true], &[true, true, false], &[true, true, true], &[false, false, false, false], &[false, false, false, true], &[false, false, true, false], &[false, false, true, true], &[false, true, false, false], &[false, true, false, true], &[false, true, true, false], &[false, true, true, true], &[true, false, false, false], &[true, false, false, true], &[true, false, true, false], &[true, false, true, true], ], ); shortlex_vecs_min_length_helper( 0, 'a'..='c', &[ &[], &['a'], &['b'], &['c'], &['a', 'a'], &['a', 'b'], &['a', 'c'], &['b', 'a'], &['b', 'b'], &['b', 'c'], &['c', 'a'], &['c', 'b'], &['c', 'c'], &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'c'], &['a', 'b', 'a'], &['a', 'b', 'b'], &['a', 'b', 'c'], &['a', 'c', 'a'], ], ); shortlex_vecs_min_length_helper( 3, 'a'..='c', &[ &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'c'], &['a', 'b', 'a'], &['a', 'b', 'b'], &['a', 'b', 'c'], &['a', 'c', 'a'], &['a', 'c', 'b'], &['a', 'c', 'c'], &['b', 'a', 'a'], &['b', 'a', 'b'], &['b', 'a', 'c'], &['b', 'b', 'a'], &['b', 'b', 'b'], &['b', 'b', 'c'], &['b', 'c', 'a'], &['b', 'c', 'b'], &['b', 'c', 'c'], &['c', 'a', 'a'], &['c', 'a', 'b'], ], ); shortlex_vecs_min_length_helper( 0, exhaustive_ascii_chars(), &[ &[], &['a'], &['b'], &['c'], &['d'], &['e'], &['f'], &['g'], &['h'], &['i'], &['j'], &['k'], &['l'], &['m'], &['n'], &['o'], &['p'], &['q'], &['r'], &['s'], ], ); shortlex_vecs_min_length_helper( 3, exhaustive_ascii_chars(), &[ &['a', 'a', 'a'], &['a', 'a', 'b'], &['a', 'a', 'c'], &['a', 'a', 'd'], &['a', 'a', 'e'], &['a', 'a', 'f'], &['a', 'a', 'g'], &['a', 'a', 'h'], &['a', 'a', 'i'], &['a', 'a', 'j'], &['a', 'a', 'k'], &['a', 'a', 'l'], &['a', 'a', 'm'], &['a', 'a', 'n'], &['a', 'a', 'o'], &['a', 'a', 'p'], &['a', 'a', 'q'], &['a', 'a', 'r'], &['a', 'a', 's'], &['a', 'a', 't'], ], ); } ================================================ FILE: malachite-base/tests/vecs/exhaustive_vec_permutations.rs ================================================ // Copyright © 2026 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::vecs::exhaustive_vec_permutations; fn exhaustive_vec_permutations_helper(cs: &str, out: &[&str]) { let cs = cs.chars().collect_vec(); let css: Vec = exhaustive_vec_permutations(cs) .map(|ds| ds.into_iter().collect()) .collect(); assert_eq!(css.iter().map(String::as_str).collect_vec().as_slice(), out); } #[test] fn test_exhaustive_vec_permutations() { exhaustive_vec_permutations_helper("", &[""]); exhaustive_vec_permutations_helper("1", &["1"]); exhaustive_vec_permutations_helper("12", &["12", "21"]); exhaustive_vec_permutations_helper("123", &["123", "132", "213", "231", "312", "321"]); exhaustive_vec_permutations_helper( "1234", &[ "1234", "1243", "1324", "1342", "1423", "1432", "2134", "2143", "2314", "2341", "2413", "2431", "3124", "3142", "3214", "3241", "3412", "3421", "4123", "4132", "4213", "4231", "4312", "4321", ], ); exhaustive_vec_permutations_helper( "12345", &[ "12345", "12354", "12435", "12453", "12534", "12543", "13245", "13254", "13425", "13452", "13524", "13542", "14235", "14253", "14325", "14352", "14523", "14532", "15234", "15243", "15324", "15342", "15423", "15432", "21345", "21354", "21435", "21453", "21534", "21543", "23145", "23154", "23415", "23451", "23514", "23541", "24135", "24153", "24315", "24351", "24513", "24531", "25134", "25143", "25314", "25341", "25413", "25431", "31245", "31254", "31425", "31452", "31524", "31542", "32145", "32154", "32415", "32451", "32514", "32541", "34125", "34152", "34215", "34251", "34512", "34521", "35124", "35142", "35214", "35241", "35412", "35421", "41235", "41253", "41325", "41352", "41523", "41532", "42135", "42153", "42315", "42351", "42513", "42531", "43125", "43152", "43215", "43251", "43512", "43521", "45123", "45132", "45213", "45231", "45312", "45321", "51234", "51243", "51324", "51342", "51423", "51432", "52134", "52143", "52314", "52341", "52413", "52431", "53124", "53142", "53214", "53241", "53412", "53421", "54123", "54132", "54213", "54231", "54312", "54321", ], ); exhaustive_vec_permutations_helper( "abcd", &[ "abcd", "abdc", "acbd", "acdb", "adbc", "adcb", "bacd", "badc", "bcad", "bcda", "bdac", "bdca", "cabd", "cadb", "cbad", "cbda", "cdab", "cdba", "dabc", "dacb", "dbac", "dbca", "dcab", "dcba", ], ); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs; use std::fmt::Debug; fn random_ordered_unique_vecs_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_ordered_unique_vecs( EXAMPLE_SEED, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs() { random_ordered_unique_vecs_helper( &random_primitive_ints::, 4, 1, &[ &[][..], &[11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235], &[30, 90, 218, 234], &[9, 106, 204, 216], &[151], &[], &[78, 91, 97, 213, 253], &[39, 191], &[170, 175, 232, 233], &[], &[2, 22, 35, 114, 198, 217], &[], &[], &[17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222], &[52, 69, 73, 91, 115, 137, 153, 178], &[], &[34, 95, 112], &[], &[106, 130, 167, 168, 197], &[86, 101, 122, 150, 172, 177, 207, 218, 221], ], &[ (&[], 199913), (&[7], 705), (&[25], 689), (&[184], 681), (&[213], 681), (&[255], 676), (&[215], 675), (&[54], 673), (&[122], 672), (&[207], 672), ], (&[27, 31, 211, 238], Some(&[27, 31, 247, 251])), ); random_ordered_unique_vecs_helper( &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ &[], &[1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141], &[0, 1, 10, 99], &[2, 12, 36, 77], &[1], &[], &[1, 5, 9, 19, 103], &[6, 7], &[15, 18, 51, 159], &[], &[2, 26, 40, 52, 64, 75], &[], &[], &[3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67], &[1, 14, 16, 24, 29, 41, 47, 52], &[], &[11, 13, 62], &[], &[3, 14, 42, 47, 109], &[5, 13, 16, 25, 37, 41, 42, 86, 96], ], &[ (&[], 199913), (&[0], 4861), (&[1], 4593), (&[2], 4498), (&[3], 4405), (&[4], 4330), (&[5], 4078), (&[6], 4050), (&[7], 3858), (&[8], 3848), ], ( &[3, 9, 14, 22, 36, 56, 107], Some(&[3, 9, 14, 22, 42, 54, 73, 150]), ), ); random_ordered_unique_vecs_helper( &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[134, 235], &[203], &[], &[38, 223], &[], &[], &[], &[], ], &[ (&[], 800023), (&[162], 692), (&[235], 690), (&[90], 688), (&[65], 687), (&[249], 686), (&[175], 684), (&[108], 683), (&[211], 682), (&[237], 680), ], (&[], None), ); random_ordered_unique_vecs_helper( &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ &[], &['g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'], &['ª', '´', 'Ã', 'ä'], &['½', 'Á', 'Ï', 'ý'], &['j'], &[], &['u', '½', 'Â', 'Ñ', 'ï'], &['x', 'õ'], &['¡', 'Â', 'ù', 'Ċ'], &[], &['b', 'r', 's', '¬', 'Â', 'Ñ'], &[], &[], &['j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'], &['b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'], &[], &['«', '¹', 'Î'], &[], &['~', '¯', '´', 'Ý', 'â'], &['g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'], ], &[ (&[], 199913), (&['Ó'], 1270), (&['Â'], 1249), (&['§'], 1244), (&['¿'], 1243), (&['õ'], 1241), (&['ĉ'], 1234), (&['¤'], 1232), (&['¼'], 1232), (&['Ì'], 1229), ], ( &['o', 'v', '¢', '±', 'Ä', 'Ć'], Some(&['o', 'v', '¢', '³', 'ã']), ), ); } #[test] #[should_panic] fn random_ordered_unique_vecs_fail_1() { random_ordered_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 0, 1); } #[test] #[should_panic] fn random_ordered_unique_vecs_fail_2() { random_ordered_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_ordered_unique_vecs_fail_3() { random_ordered_unique_vecs( EXAMPLE_SEED, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs_fixed_length; use std::fmt::Debug; fn random_ordered_unique_vecs_fixed_length_helper( len: u64, xs: I, expected_values: &[&[I::Item]], expected_common_values: &[(&[I::Item], usize)], expected_median: (&[I::Item], Option<&[I::Item]>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { random_vecs_helper_helper( random_ordered_unique_vecs_fixed_length(len, xs), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs_fixed_length() { random_ordered_unique_vecs_fixed_length_helper( 0, random_primitive_ints::(EXAMPLE_SEED), repeat_n(&[][..], 20).collect_vec().as_slice(), &[(&[], 1000000)], (&[], None), ); random_ordered_unique_vecs_fixed_length_helper( 1, random_bools(EXAMPLE_SEED), &[ &[true], &[false], &[false], &[false], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[false], ], &[(&[true], 500473), (&[false], 499527)], (&[true], None), ); random_ordered_unique_vecs_fixed_length_helper( 3, random_primitive_ints::(EXAMPLE_SEED), &[ &[69, 113, 239], &[108, 210, 228], &[87, 161, 168], &[32, 83, 110], &[34, 89, 188], &[93, 200, 238], &[115, 149, 189], &[149, 201, 217], &[31, 117, 146], &[72, 151, 169], &[7, 33, 174], &[38, 81, 144], &[72, 113, 127], &[107, 128, 233], &[12, 46, 119], &[18, 164, 243], &[59, 114, 174], &[39, 174, 247], &[104, 160, 184], &[37, 100, 252], ], &[ (&[57, 142, 207], 7), (&[32, 68, 169], 6), (&[36, 70, 195], 6), (&[125, 168, 194], 6), (&[0, 97, 205], 5), (&[2, 33, 227], 5), (&[5, 46, 239], 5), (&[9, 68, 189], 5), (&[9, 78, 240], 5), (&[1, 110, 203], 5), ], (&[52, 133, 241], Some(&[52, 133, 242])), ); random_ordered_unique_vecs_fixed_length_helper( 2, random_ordered_unique_vecs_fixed_length(2, random_primitive_ints::(EXAMPLE_SEED)), &[ &[vec![69, 108], vec![113, 239]], &[vec![161, 168], vec![210, 228]], &[vec![32, 87], vec![83, 110]], &[vec![34, 188], vec![89, 238]], &[vec![93, 200], vec![115, 149]], &[vec![149, 189], vec![201, 217]], &[vec![31, 72], vec![117, 146]], &[vec![33, 174], vec![151, 169]], &[vec![7, 38], vec![81, 144]], &[vec![72, 127], vec![113, 128]], &[vec![46, 119], vec![107, 233]], &[vec![12, 18], vec![164, 243]], &[vec![59, 247], vec![114, 174]], &[vec![39, 174], vec![160, 184]], &[vec![37, 104], vec![100, 252]], &[vec![69, 107], vec![122, 228]], &[vec![142, 179], vec![242, 248]], &[vec![61, 189], vec![233, 239]], &[vec![7, 192], vec![85, 235]], &[vec![90, 200], vec![178, 185]], ], &[ (&[vec![0, 78], vec![34, 52]], 2), (&[vec![1, 58], vec![6, 112]], 2), (&[vec![1, 63], vec![8, 154]], 2), (&[vec![1, 97], vec![7, 250]], 2), (&[vec![2, 33], vec![40, 81]], 2), (&[vec![3, 160], vec![7, 29]], 2), (&[vec![3, 32], vec![12, 60]], 2), (&[vec![6, 130], vec![7, 20]], 2), (&[vec![6, 68], vec![7, 126]], 2), (&[vec![6, 77], vec![36, 54]], 2), ], ( &[vec![40, 193], vec![94, 142]], Some(&[vec![40, 193], vec![97, 243]]), ), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::bools::random::random_bools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs_from_length_iterator; use malachite_base::vecs::random_values_from_vec; use std::fmt::Debug; fn random_ordered_unique_vecs_from_length_iterator_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_ordered_unique_vecs_from_length_iterator(EXAMPLE_SEED, lengths_gen, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs_from_length_iterator() { random_ordered_unique_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2]), &random_bools, &[ &[false, true], &[], &[false, true], &[false, true], &[], &[false, true], &[false, true], &[], &[false, true], &[false, true], &[], &[false, true], &[], &[false, true], &[false, true], &[], &[], &[], &[false, true], &[], ], &[(&[false, true], 500363), (&[], 499637)], (&[false, true], None), ); random_ordered_unique_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), &random_primitive_ints::, &[ &[11, 38, 85, 134, 136, 162, 177, 200, 203, 217, 223, 235], &[32, 166], &[9, 30, 39, 78, 90, 91, 97, 106, 151, 191, 204, 213, 216, 218, 234, 253], &[170, 175], &[ 2, 17, 22, 25, 32, 34, 35, 52, 65, 69, 73, 79, 91, 112, 114, 115, 121, 137, 144, 148, 153, 173, 178, 198, 217, 222, 232, 233, ], &[], &[95, 106, 122, 130, 167, 168, 172, 177, 197, 207], &[9, 74, 86, 101, 115, 150, 218, 221], &[109, 123], &[], &[40, 48, 52, 97, 104, 133, 159, 196, 201, 235, 247, 250], &[7, 68, 190, 216], &[], &[], &[157, 216], &[11, 24, 43, 103, 112, 217], &[], &[84, 211], &[], &[55, 135], ], &[ (&[], 333981), (&[33, 163], 22), (&[76, 233], 19), (&[5, 42], 18), (&[76, 79], 18), (&[32, 134], 18), (&[69, 234], 18), (&[74, 164], 18), (&[86, 192], 18), (&[99, 145], 18), ], (&[12, 190], None), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn random_ordered_unique_vecs_length_inclusive_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_ordered_unique_vecs_length_inclusive_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs_length_inclusive_range() { random_ordered_unique_vecs_length_inclusive_range_helper( 2, 3, &random_primitive_ints::, &[ &[11, 85, 136], &[200, 235], &[134, 203, 223], &[38, 217, 235], &[162, 177], &[32, 166, 234], &[30, 90, 218], &[9, 106], &[151, 204, 216], &[97, 213, 253], &[78, 91], &[39, 175, 191], &[170, 232], &[2, 35, 233], &[22, 198, 217], &[17, 114], &[32, 173], &[65, 114], &[121, 173, 222], &[25, 144], ], &[ (&[106, 108], 34), (&[224, 237], 34), (&[51, 132], 32), (&[82, 117], 32), (&[72, 108], 31), (&[142, 194], 31), (&[0, 34], 30), (&[12, 208], 30), (&[15, 141], 30), (&[30, 248], 30), ], (&[62, 131, 203], Some(&[62, 131, 205])), ); random_ordered_unique_vecs_length_inclusive_range_helper( 2, 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[0, 1, 5], &[1, 4], &[2, 4, 6], &[0, 1, 2], &[9, 13], &[0, 2, 7], &[4, 6, 7], &[0, 6], &[0, 1, 3], &[1, 2, 5], &[0, 1], &[0, 1, 4], &[0, 2], &[0, 2, 12], &[1, 2, 3], &[3, 9], &[0, 1], &[1, 2], &[0, 1, 11], &[1, 6], ], &[ (&[0, 1], 103032), (&[0, 1, 2], 84142), (&[0, 2], 66185), (&[0, 1, 3], 52638), (&[0, 3], 42990), (&[1, 2], 40380), (&[0, 1, 4], 33815), (&[0, 2, 3], 31257), (&[0, 4], 28088), (&[1, 3], 26214), ], (&[0, 3], None), ); random_ordered_unique_vecs_length_inclusive_range_helper( 2, 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['c', 'q', 'v'], &['e', 'i'], &['g', 'p', 's'], &['m', 'n', 't'], &['o', 'z'], &['f', 'k', 'm'], &['q', 'u', 'y'], &['k', 'x'], &['h', 'n', 'u'], &['a', 'j', 'n'], &['w', 'z'], &['b', 'l', 'w'], &['l', 'u'], &['e', 'l', 'n'], &['k', 'u', 'v'], &['c', 'h'], &['i', 'y'], &['m', 'r'], &['m', 's', 'y'], &['e', 'l'], ], &[ (&['l', 'x'], 1640), (&['o', 't'], 1636), (&['b', 'p'], 1630), (&['m', 'v'], 1623), (&['h', 'u'], 1621), (&['a', 'x'], 1614), (&['d', 'f'], 1613), (&['e', 'r'], 1613), (&['o', 'p'], 1612), (&['c', 'i'], 1611), ], (&['g', 'j'], None), ); } #[test] #[should_panic] fn random_ordered_unique_vecs_length_inclusive_range_fail() { random_ordered_unique_vecs_length_inclusive_range( EXAMPLE_SEED, 2, 1, &random_primitive_ints::, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs_length_range; use std::fmt::Debug; fn random_ordered_unique_vecs_length_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_ordered_unique_vecs_length_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs_length_range() { random_ordered_unique_vecs_length_range_helper( 2, 4, &random_primitive_ints::, &[ &[11, 85, 136], &[200, 235], &[134, 203, 223], &[38, 217, 235], &[162, 177], &[32, 166, 234], &[30, 90, 218], &[9, 106], &[151, 204, 216], &[97, 213, 253], &[78, 91], &[39, 175, 191], &[170, 232], &[2, 35, 233], &[22, 198, 217], &[17, 114], &[32, 173], &[65, 114], &[121, 173, 222], &[25, 144], ], &[ (&[106, 108], 34), (&[224, 237], 34), (&[51, 132], 32), (&[82, 117], 32), (&[72, 108], 31), (&[142, 194], 31), (&[0, 34], 30), (&[12, 208], 30), (&[15, 141], 30), (&[30, 248], 30), ], (&[62, 131, 203], Some(&[62, 131, 205])), ); random_ordered_unique_vecs_length_range_helper( 2, 4, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[0, 1, 5], &[1, 4], &[2, 4, 6], &[0, 1, 2], &[9, 13], &[0, 2, 7], &[4, 6, 7], &[0, 6], &[0, 1, 3], &[1, 2, 5], &[0, 1], &[0, 1, 4], &[0, 2], &[0, 2, 12], &[1, 2, 3], &[3, 9], &[0, 1], &[1, 2], &[0, 1, 11], &[1, 6], ], &[ (&[0, 1], 103032), (&[0, 1, 2], 84142), (&[0, 2], 66185), (&[0, 1, 3], 52638), (&[0, 3], 42990), (&[1, 2], 40380), (&[0, 1, 4], 33815), (&[0, 2, 3], 31257), (&[0, 4], 28088), (&[1, 3], 26214), ], (&[0, 3], None), ); random_ordered_unique_vecs_length_range_helper( 2, 4, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['c', 'q', 'v'], &['e', 'i'], &['g', 'p', 's'], &['m', 'n', 't'], &['o', 'z'], &['f', 'k', 'm'], &['q', 'u', 'y'], &['k', 'x'], &['h', 'n', 'u'], &['a', 'j', 'n'], &['w', 'z'], &['b', 'l', 'w'], &['l', 'u'], &['e', 'l', 'n'], &['k', 'u', 'v'], &['c', 'h'], &['i', 'y'], &['m', 'r'], &['m', 's', 'y'], &['e', 'l'], ], &[ (&['l', 'x'], 1640), (&['o', 't'], 1636), (&['b', 'p'], 1630), (&['m', 'v'], 1623), (&['h', 'u'], 1621), (&['a', 'x'], 1614), (&['d', 'f'], 1613), (&['e', 'r'], 1613), (&['o', 'p'], 1612), (&['c', 'i'], 1611), ], (&['g', 'j'], None), ); } #[test] #[should_panic] fn random_ordered_unique_vecs_length_range_fail() { random_ordered_unique_vecs_length_range(EXAMPLE_SEED, 2, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/vecs/random/random_ordered_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_ordered_unique_vecs_min_length; use std::fmt::Debug; fn random_ordered_unique_vecs_min_length_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_ordered_unique_vecs_min_length( EXAMPLE_SEED, min_length, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_ordered_unique_vecs_min_length() { random_ordered_unique_vecs_min_length_helper( 0, &random_primitive_ints::, 4, 1, &[ &[], &[11, 32, 38, 85, 134, 136, 162, 166, 177, 200, 203, 217, 223, 235], &[30, 90, 218, 234], &[9, 106, 204, 216], &[151], &[], &[78, 91, 97, 213, 253], &[39, 191], &[170, 175, 232, 233], &[], &[2, 22, 35, 114, 198, 217], &[], &[], &[17, 25, 32, 65, 79, 114, 121, 144, 148, 173, 222], &[52, 69, 73, 91, 115, 137, 153, 178], &[], &[34, 95, 112], &[], &[106, 130, 167, 168, 197], &[86, 101, 122, 150, 172, 177, 207, 218, 221], ], &[ (&[], 199913), (&[7], 705), (&[25], 689), (&[184], 681), (&[213], 681), (&[255], 676), (&[215], 675), (&[54], 673), (&[122], 672), (&[207], 672), ], (&[27, 31, 211, 238], Some(&[27, 31, 247, 251])), ); random_ordered_unique_vecs_min_length_helper( 3, &random_primitive_ints::, 7, 1, &[ &[11, 85, 136], &[9, 30, 32, 38, 90, 106, 134, 162, 166, 177, 200, 203, 217, 218, 223, 234, 235], &[78, 97, 151, 204, 213, 216, 253], &[39, 91, 170, 175, 191, 232, 233], &[2, 22, 35, 217], &[17, 114, 198], &[25, 32, 65, 114, 121, 144, 173, 222], &[52, 73, 79, 115, 148], &[34, 69, 91, 112, 137, 153, 178], &[95, 106, 167], &[86, 122, 130, 150, 168, 172, 177, 197, 207], &[101, 218, 221], &[9, 74, 115], &[40, 48, 52, 97, 104, 109, 123, 133, 159, 196, 201, 235, 247, 250], &[7, 11, 24, 43, 68, 103, 112, 157, 190, 216, 217], &[84, 135, 211], &[29, 55, 65, 89, 191, 206], &[9, 51, 79], &[3, 20, 22, 34, 62, 114, 118, 148], &[23, 32, 47, 50, 120, 166, 176, 177, 194, 204, 238, 248], ], &[ (&[5, 128, 142], 4), (&[137, 145, 160], 4), (&[2, 4, 52], 3), (&[1, 5, 192], 3), (&[12, 41, 58], 3), (&[2, 95, 171], 3), (&[20, 86, 94], 3), (&[21, 43, 50], 3), (&[3, 81, 122], 3), (&[31, 54, 79], 3), ], (&[26, 138, 167], Some(&[26, 138, 167, 173, 211])), ); random_ordered_unique_vecs_min_length_helper( 0, &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ &[], &[1, 9, 12, 14, 16, 17, 19, 21, 41, 42, 68, 79, 124, 141], &[0, 1, 10, 99], &[2, 12, 36, 77], &[1], &[], &[1, 5, 9, 19, 103], &[6, 7], &[15, 18, 51, 159], &[], &[2, 26, 40, 52, 64, 75], &[], &[], &[3, 4, 5, 7, 30, 31, 34, 43, 49, 51, 67], &[1, 14, 16, 24, 29, 41, 47, 52], &[], &[11, 13, 62], &[], &[3, 14, 42, 47, 109], &[5, 13, 16, 25, 37, 41, 42, 86, 96], ], &[ (&[], 199913), (&[0], 4861), (&[1], 4593), (&[2], 4498), (&[3], 4405), (&[4], 4330), (&[5], 4078), (&[6], 4050), (&[7], 3858), (&[8], 3848), ], ( &[3, 9, 14, 22, 36, 56, 107], Some(&[3, 9, 14, 22, 42, 54, 73, 150]), ), ); random_ordered_unique_vecs_min_length_helper( 3, &|seed| geometric_random_unsigneds::(seed, 32, 1), 7, 1, &[ &[1, 14, 42], &[0, 1, 9, 10, 12, 16, 17, 19, 21, 36, 41, 68, 77, 79, 99, 124, 141], &[1, 2, 5, 9, 12, 19, 103], &[6, 7, 15, 18, 51, 52, 159], &[2, 40, 64, 75], &[26, 34, 67], &[4, 5, 7, 30, 31, 43, 49, 51], &[3, 14, 16, 24, 47], &[1, 11, 13, 29, 41, 52, 62], &[3, 47, 109], &[13, 14, 16, 25, 37, 41, 42, 86, 96], &[5, 20, 42], &[2, 74, 82], &[3, 6, 7, 11, 17, 20, 36, 45, 56, 66, 76, 80, 89, 127], &[1, 6, 10, 13, 19, 23, 25, 32, 41, 43, 97], &[7, 41, 134], &[9, 10, 25, 26, 47, 105], &[68, 94, 109], &[1, 3, 9, 13, 28, 43, 44, 84], &[0, 4, 5, 6, 7, 13, 31, 32, 37, 42, 50, 75], ], &[ (&[0, 2, 5], 42), (&[0, 1, 8], 39), (&[0, 3, 4], 38), (&[1, 3, 9], 38), (&[0, 1, 7], 35), (&[0, 2, 8], 34), (&[1, 2, 12], 34), (&[0, 1, 2], 33), (&[1, 2, 3], 33), (&[1, 3, 4], 33), ], ( &[3, 8, 14, 19, 25, 36, 52, 64, 71], Some(&[3, 8, 14, 19, 25, 38, 58, 61]), ), ); random_ordered_unique_vecs_min_length_helper( 0, &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[134, 235], &[203], &[], &[38, 223], &[], &[], &[], &[], ], &[ (&[], 800023), (&[162], 692), (&[235], 690), (&[90], 688), (&[65], 687), (&[249], 686), (&[175], 684), (&[108], 683), (&[211], 682), (&[237], 680), ], (&[], None), ); random_ordered_unique_vecs_min_length_helper( 3, &random_primitive_ints::, 13, 4, &[ &[11, 85, 136], &[134, 200, 235], &[38, 203, 223, 235], &[32, 162, 177, 217], &[30, 90, 166, 218, 234], &[9, 106, 216], &[151, 204, 213], &[78, 97, 253], &[39, 91, 191], &[170, 175, 232], &[2, 35, 233], &[22, 198, 217], &[17, 32, 65, 114, 173], &[25, 121, 173, 222], &[79, 144, 148], &[52, 69, 73, 115, 137], &[91, 153, 178], &[34, 95, 112], &[106, 167, 197], &[122, 130, 168], ], &[ (&[10, 87, 204], 6), (&[15, 40, 115], 6), (&[108, 193, 199], 6), (&[1, 22, 70], 5), (&[1, 8, 212], 5), (&[2, 40, 169], 5), (&[2, 58, 211], 5), (&[3, 29, 186], 5), (&[3, 97, 112], 5), (&[11, 66, 140], 5), ], (&[49, 78, 193], Some(&[49, 78, 193, 215])), ); random_ordered_unique_vecs_min_length_helper( 0, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ &[], &['g', 'q', '³', '»', 'À', 'Á', 'Ã', 'È', 'á', 'â', 'ì', 'ñ', 'Ā', 'ą'], &['ª', '´', 'Ã', 'ä'], &['½', 'Á', 'Ï', 'ý'], &['j'], &[], &['u', '½', 'Â', 'Ñ', 'ï'], &['x', 'õ'], &['¡', 'Â', 'ù', 'Ċ'], &[], &['b', 'r', 's', '¬', 'Â', 'Ñ'], &[], &[], &['j', 'n', 't', '¬', 'º', '¿', 'Á', 'Ø', 'Þ', 'ô', 'ü'], &['b', 'k', '±', 'Î', 'Ü', 'æ', 'è', 'ā'], &[], &['«', '¹', 'Î'], &[], &['~', '¯', '´', 'Ý', 'â'], &['g', '¼', 'Ç', 'Î', 'Ü', 'Þ', 'æ', 'é', 'ö'], ], &[ (&[][..], 199913), (&['Ó'], 1270), (&['Â'], 1249), (&['§'], 1244), (&['¿'], 1243), (&['õ'], 1241), (&['ĉ'], 1234), (&['¤'], 1232), (&['¼'], 1232), (&['Ì'], 1229), ], ( &['o', 'v', '¢', '±', 'Ä', 'Ć'], Some(&['o', 'v', '¢', '³', 'ã']), ), ); random_ordered_unique_vecs_min_length_helper( 3, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 7, 1, &[ &['g', 'q', 'á'], &['g', 'ª', '³', '´', '»', '½', 'À', 'Á', 'Ã', 'È', 'Ï', 'â', 'ä', 'ì', 'ñ', 'Ā', 'ą'], &['j', 'u', '½', 'Â', 'Ñ', 'ï', 'ý'], &['x', '¡', '¬', 'Â', 'õ', 'ù', 'Ċ'], &['b', 's', '¬', 'Ñ'], &['n', 'r', 'Â'], &['t', '¬', 'º', '¿', 'Ø', 'Þ', 'ô', 'ü'], &['j', 'k', '±', 'Á', 'è'], &['b', '«', '¹', 'Î', 'Ü', 'æ', 'ā'], &['~', '´', 'Î'], &['g', '¯', 'Î', 'Ý', 'Þ', 'â', 'æ', 'é', 'ö'], &['¼', 'Ç', 'Ü'], &['¡', '§', 'Ì'], &['d', 'm', 'z', '{', '¨', '®', '±', '¼', 'Ë', 'Ü', 'ê', 'ì', 'ý', 'þ'], &['x', 'ª', '½', 'À', 'Õ', 'ì', 'ï', 'û', 'ă', 'Ą', 'ċ'], &['¢', '«', 'Ć'], &['{', '¢', '½', 'È', 'ä', 'ÿ'], &['Ë', 'Õ', 'ê'], &['p', '¨', '°', 'º', 'Å', 'Ó', '×', 'ü'], &['d', 'k', 'o', 'v', '¥', '±', 'Ä', 'È', 'Ê', 'ß', 'æ', 'Ć'], ], &[ (&['m', 'u', 'w'], 6), (&['b', 'n', 'Ã'], 6), (&['g', '®', 'Ý'], 6), (&['x', 'Ä', 'î'], 6), (&['º', 'Ú', '÷'], 6), (&['a', 'w', 'ø'], 5), (&['c', 'e', 'Þ'], 5), (&['d', 't', 'Ã'], 5), (&['m', 'r', 'È'], 5), (&['w', '{', '³'], 5), ], ( &['o', 's', '×', 'Ý', 'Þ', 'ß', 'î', 'ù'], Some(&['o', 's', '×', 'à', 'ã', 'ò', 'ċ']), ), ); } #[test] #[should_panic] fn random_ordered_unique_vecs_min_length_fail_1() { random_ordered_unique_vecs_min_length(EXAMPLE_SEED, 3, &random_primitive_ints::, 3, 1); } #[test] #[should_panic] fn random_ordered_unique_vecs_min_length_fail_2() { random_ordered_unique_vecs_min_length(EXAMPLE_SEED, 1, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_ordered_unique_vecs_min_length_fail_3() { random_ordered_unique_vecs_min_length( EXAMPLE_SEED, 0, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs; use std::fmt::Debug; fn random_unique_vecs_helper>( xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_unique_vecs( EXAMPLE_SEED, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs() { random_unique_vecs_helper( &random_primitive_ints::, 4, 1, &[ &[], &[85, 11, 136, 200, 235, 134, 203, 223, 38, 217, 177, 162, 32, 166], &[234, 30, 218, 90], &[106, 9, 216, 204], &[151], &[], &[213, 97, 253, 78, 91], &[39, 191], &[175, 170, 232, 233], &[], &[2, 35, 22, 217, 198, 114], &[], &[], &[17, 32, 173, 114, 65, 121, 222, 25, 144, 148, 79], &[115, 52, 73, 69, 137, 91, 153, 178], &[], &[112, 34, 95], &[], &[106, 167, 197, 130, 168], &[122, 207, 172, 177, 86, 150, 221, 218, 101], ], &[ (&[], 199913), (&[7], 705), (&[25], 689), (&[184], 681), (&[213], 681), (&[255], 676), (&[215], 675), (&[54], 673), (&[122], 672), (&[207], 672), ], (&[96], None), ); random_unique_vecs_helper( &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ &[], &[1, 14, 42, 12, 141, 19, 9, 68, 16, 79, 21, 17, 41, 124], &[10, 1, 99, 0], &[77, 36, 2, 12], &[1], &[], &[103, 9, 19, 1, 5], &[7, 6], &[51, 159, 15, 18], &[], &[52, 75, 40, 64, 2, 26], &[], &[], &[67, 34, 51, 30, 31, 49, 43, 7, 5, 4, 3], &[14, 47, 24, 16, 52, 29, 1, 41], &[], &[13, 11, 62], &[], &[47, 3, 109, 42, 14], &[37, 86, 25, 96, 41, 13, 16, 42, 5], ], &[ (&[], 199913), (&[0], 4861), (&[1], 4593), (&[2], 4498), (&[3], 4405), (&[4], 4330), (&[5], 4078), (&[6], 4050), (&[7], 3858), (&[8], 3848), ], (&[15, 3], None), ); random_unique_vecs_helper( &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[235, 134], &[203], &[], &[223, 38], &[], &[], &[], &[], ], &[ (&[][..], 800023), (&[162], 692), (&[235], 690), (&[90], 688), (&[65], 687), (&[249], 686), (&[175], 684), (&[108], 683), (&[211], 682), (&[237], 680), ], (&[], None), ); random_unique_vecs_helper( &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ &[], &['q', 'á', 'g', 'Á', 'À', 'È', '»', 'ì', '³', 'ą', 'â', 'Ã', 'ñ', 'Ā'], &['Ã', 'ª', 'ä', '´'], &['½', 'Á', 'Ï', 'ý'], &['j'], &[], &['ï', 'Ñ', 'u', 'Â', '½'], &['õ', 'x'], &['Â', 'ù', '¡', 'Ċ'], &[], &['¬', 'b', 'Ñ', 's', 'Â', 'r'], &[], &[], &['n', '¿', 'Þ', 'ô', 'Ø', 'º', 'ü', 't', '¬', 'j', 'Á'], &['±', 'è', 'k', 'æ', 'b', 'Î', 'ā', 'Ü'], &[], &['¹', '«', 'Î'], &[], &['~', '´', 'Ý', 'â', '¯'], &['é', 'æ', 'Þ', 'ö', 'g', 'Î', 'Ç', 'Ü', '¼'], ], &[ (&[], 199913), (&['Ó'], 1270), (&['Â'], 1249), (&['§'], 1244), (&['¿'], 1243), (&['õ'], 1241), (&['ĉ'], 1234), (&['¤'], 1232), (&['¼'], 1232), (&['Ì'], 1229), ], ( &['¶', 'Ă', 'ą', '®', 'Á', 'í', '¬', '¾', '¸', 'Ã', '}', 'ù', 'ý', '½', 'a'], Some(&['¶', 'Ă', 'ć']), ), ); } #[test] #[should_panic] fn random_unique_vecs_fail_1() { random_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 0, 1); } #[test] #[should_panic] fn random_unique_vecs_fail_2() { random_unique_vecs(EXAMPLE_SEED, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_unique_vecs_fail_3() { random_unique_vecs( EXAMPLE_SEED, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs_fixed_length; use std::fmt::Debug; fn random_unique_vecs_fixed_length_helper( len: u64, xs: I, expected_values: &[&[I::Item]], expected_common_values: &[(&[I::Item], usize)], expected_median: (&[I::Item], Option<&[I::Item]>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { random_vecs_helper_helper( random_unique_vecs_fixed_length(len, xs), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs_fixed_length() { random_unique_vecs_fixed_length_helper( 0, random_primitive_ints::(EXAMPLE_SEED), repeat_n(&[][..], 20).collect_vec().as_slice(), &[(&[], 1000000)], (&[], None), ); random_unique_vecs_fixed_length_helper( 1, random_bools(EXAMPLE_SEED), &[ &[true], &[false], &[false], &[false], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[false], ], &[(&[true], 500473), (&[false], 499527)], (&[true], None), ); random_unique_vecs_fixed_length_helper( 3, random_primitive_ints::(EXAMPLE_SEED), &[ &[113, 239, 69], &[108, 228, 210], &[168, 161, 87], &[32, 110, 83], &[188, 34, 89], &[238, 93, 200], &[149, 115, 189], &[149, 217, 201], &[117, 146, 31], &[72, 151, 169], &[174, 33, 7], &[38, 81, 144], &[72, 127, 113], &[128, 233, 107], &[46, 119, 12], &[18, 164, 243], &[114, 174, 59], &[247, 39, 174], &[160, 184, 104], &[37, 100, 252], ], &[ (&[205, 0, 97], 4), (&[102, 18, 19], 4), (&[105, 70, 13], 4), (&[22, 45, 192], 4), (&[87, 100, 26], 4), (&[15, 107, 109], 4), (&[134, 245, 157], 4), (&[138, 164, 179], 4), (&[219, 253, 196], 4), (&[237, 197, 239], 4), ], (&[128, 16, 107], Some(&[128, 16, 116])), ); random_unique_vecs_fixed_length_helper( 2, random_unique_vecs_fixed_length(2, random_primitive_ints::(EXAMPLE_SEED)), &[ &[vec![113, 239], vec![69, 108]], &[vec![228, 210], vec![168, 161]], &[vec![87, 32], vec![110, 83]], &[vec![188, 34], vec![89, 238]], &[vec![93, 200], vec![149, 115]], &[vec![189, 149], vec![217, 201]], &[vec![117, 146], vec![31, 72]], &[vec![151, 169], vec![174, 33]], &[vec![7, 38], vec![81, 144]], &[vec![72, 127], vec![113, 128]], &[vec![233, 107], vec![46, 119]], &[vec![12, 18], vec![164, 243]], &[vec![114, 174], vec![59, 247]], &[vec![39, 174], vec![160, 184]], &[vec![104, 37], vec![100, 252]], &[vec![228, 122], vec![107, 69]], &[vec![242, 248], vec![179, 142]], &[vec![239, 233], vec![61, 189]], &[vec![235, 85], vec![192, 7]], &[vec![200, 90], vec![185, 178]], ], &[ (&[vec![60, 12], vec![3, 32]], 2), (&[vec![0, 80], vec![88, 210]], 2), (&[vec![1, 3], vec![216, 183]], 2), (&[vec![159, 0], vec![69, 30]], 2), (&[vec![199, 6], vec![95, 79]], 2), (&[vec![2, 98], vec![221, 19]], 2), (&[vec![212, 65], vec![99, 2]], 2), (&[vec![3, 14], vec![61, 170]], 2), (&[vec![41, 155], vec![3, 72]], 2), (&[vec![47, 85], vec![69, 66]], 2), ], ( &[vec![128, 41], vec![252, 44]], Some(&[vec![128, 42], vec![8, 241]]), ), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::bools::random::random_bools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs_from_length_iterator; use malachite_base::vecs::random_values_from_vec; use std::fmt::Debug; fn random_unique_vecs_from_length_iterator_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_unique_vecs_from_length_iterator(EXAMPLE_SEED, lengths_gen, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs_from_length_iterator() { random_unique_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2]), &random_bools, &[ &[true, false], &[], &[true, false], &[true, false], &[], &[true, false], &[true, false], &[], &[true, false], &[false, true], &[], &[false, true], &[], &[false, true], &[false, true], &[], &[], &[], &[true, false], &[], ], &[(&[], 499637), (&[false, true], 250413), (&[true, false], 249950)], (&[false, true], None), ); random_unique_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), &random_primitive_ints::, &[ &[85, 11, 136, 200, 235, 134, 203, 223, 38, 217, 177, 162], &[32, 166], &[234, 30, 218, 90, 106, 9, 216, 204, 151, 213, 97, 253, 78, 91, 39, 191], &[175, 170], &[ 232, 233, 2, 35, 22, 217, 198, 114, 17, 32, 173, 65, 121, 222, 25, 144, 148, 79, 115, 52, 73, 69, 137, 91, 153, 178, 112, 34, ], &[], &[95, 106, 167, 197, 130, 168, 122, 207, 172, 177], &[86, 150, 221, 218, 101, 115, 74, 9], &[123, 109], &[], &[52, 201, 159, 247, 250, 48, 133, 235, 196, 40, 97, 104], &[68, 190, 216, 7], &[], &[], &[216, 157], &[43, 112, 217, 24, 11, 103], &[], &[211, 84], &[], &[135, 55], ], &[ (&[], 333981), (&[79, 76], 14), (&[234, 129], 14), (&[119, 62], 13), (&[33, 163], 13), (&[5, 42], 12), (&[28, 91], 12), (&[55, 25], 12), (&[152, 55], 12), (&[224, 77], 12), ], (&[63, 197, 169, 69, 240, 201], Some(&[63, 197, 181, 249])), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs_length_inclusive_range; use std::fmt::Debug; fn random_unique_vecs_length_inclusive_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_unique_vecs_length_inclusive_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs_length_inclusive_range() { random_unique_vecs_length_inclusive_range_helper( 2, 3, &random_primitive_ints::, &[ &[85, 11, 136], &[200, 235], &[134, 203, 223], &[38, 235, 217], &[177, 162], &[32, 166, 234], &[30, 218, 90], &[106, 9], &[216, 204, 151], &[213, 97, 253], &[78, 91], &[39, 191, 175], &[170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17], &[32, 173], &[114, 65], &[121, 222, 173], &[25, 144], ], &[ (&[149, 194], 23), (&[237, 224], 23), (&[109, 76], 21), (&[187, 29], 21), (&[96, 105], 21), (&[233, 132], 21), (&[25, 96], 20), (&[92, 85], 20), (&[108, 72], 20), (&[128, 48], 20), ], (&[127, 247], None), ); random_unique_vecs_length_inclusive_range_helper( 2, 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[5, 0, 1], &[1, 4], &[2, 4, 6], &[2, 0, 1], &[9, 13], &[0, 2, 7], &[4, 6, 7], &[6, 0], &[0, 1, 3], &[5, 1, 2], &[1, 0], &[0, 1, 4], &[2, 0], &[12, 0, 2], &[3, 1, 2], &[3, 9], &[1, 0], &[2, 1], &[11, 1, 0], &[1, 6], ], &[ (&[0, 1], 55434), (&[1, 0], 47598), (&[0, 2], 37211), (&[2, 0], 28974), (&[0, 3], 24737), (&[1, 2], 21227), (&[2, 1], 19153), (&[0, 1, 2], 18604), (&[3, 0], 18253), (&[0, 4], 16195), ], (&[1, 4], None), ); random_unique_vecs_length_inclusive_range_helper( 2, 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['v', 'c', 'q'], &['i', 'e'], &['p', 'g', 's'], &['n', 't', 'm'], &['z', 'o'], &['m', 'f', 'k'], &['q', 'y', 'u'], &['k', 'x'], &['h', 'u', 'n'], &['n', 'j', 'a'], &['w', 'z'], &['l', 'w', 'b'], &['l', 'u'], &['n', 'e', 'l'], &['v', 'k', 'u'], &['h', 'c'], &['y', 'i'], &['m', 'r'], &['m', 'y', 's'], &['l', 'e'], ], &[ (&['i', 'p'], 855), (&['o', 't'], 845), (&['c', 'i'], 842), (&['h', 'u'], 841), (&['x', 'l'], 841), (&['a', 'o'], 833), (&['g', 'h'], 833), (&['z', 'n'], 832), (&['j', 'n'], 831), (&['l', 'c'], 829), ], (&['m', 'z', 'l'], None), ); } #[test] #[should_panic] fn random_unique_vecs_length_inclusive_range_fail() { random_unique_vecs_length_inclusive_range(EXAMPLE_SEED, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs_length_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs_length_range; use std::fmt::Debug; fn random_unique_vecs_length_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_unique_vecs_length_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs_length_range() { random_unique_vecs_length_range_helper( 2, 4, &random_primitive_ints::, &[ &[85, 11, 136], &[200, 235], &[134, 203, 223], &[38, 235, 217], &[177, 162], &[32, 166, 234], &[30, 218, 90], &[106, 9], &[216, 204, 151], &[213, 97, 253], &[78, 91], &[39, 191, 175], &[170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17], &[32, 173], &[114, 65], &[121, 222, 173], &[25, 144], ], &[ (&[149, 194], 23), (&[237, 224], 23), (&[109, 76], 21), (&[187, 29], 21), (&[96, 105], 21), (&[233, 132], 21), (&[25, 96], 20), (&[92, 85], 20), (&[108, 72], 20), (&[128, 48], 20), ], (&[127, 247], None), ); random_unique_vecs_length_range_helper( 2, 4, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[5, 0, 1], &[1, 4], &[2, 4, 6], &[2, 0, 1], &[9, 13], &[0, 2, 7], &[4, 6, 7], &[6, 0], &[0, 1, 3], &[5, 1, 2], &[1, 0], &[0, 1, 4], &[2, 0], &[12, 0, 2], &[3, 1, 2], &[3, 9], &[1, 0], &[2, 1], &[11, 1, 0], &[1, 6], ], &[ (&[0, 1], 55434), (&[1, 0], 47598), (&[0, 2], 37211), (&[2, 0], 28974), (&[0, 3], 24737), (&[1, 2], 21227), (&[2, 1], 19153), (&[0, 1, 2], 18604), (&[3, 0], 18253), (&[0, 4], 16195), ], (&[1, 4], None), ); random_unique_vecs_length_range_helper( 2, 4, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['v', 'c', 'q'], &['i', 'e'], &['p', 'g', 's'], &['n', 't', 'm'], &['z', 'o'], &['m', 'f', 'k'], &['q', 'y', 'u'], &['k', 'x'], &['h', 'u', 'n'], &['n', 'j', 'a'], &['w', 'z'], &['l', 'w', 'b'], &['l', 'u'], &['n', 'e', 'l'], &['v', 'k', 'u'], &['h', 'c'], &['y', 'i'], &['m', 'r'], &['m', 'y', 's'], &['l', 'e'], ], &[ (&['i', 'p'], 855), (&['o', 't'], 845), (&['c', 'i'], 842), (&['h', 'u'], 841), (&['x', 'l'], 841), (&['a', 'o'], 833), (&['g', 'h'], 833), (&['z', 'n'], 832), (&['j', 'n'], 831), (&['l', 'c'], 829), ], (&['m', 'z', 'l'], None), ); } #[test] #[should_panic] fn random_unique_vecs_length_range_fail() { random_unique_vecs_length_range(EXAMPLE_SEED, 2, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/vecs/random/random_unique_vecs_min_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::exhaustive::exhaustive_chars; use malachite_base::chars::random::graphic_weighted_random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_unique_vecs_min_length; use std::fmt::Debug; fn random_unique_vecs_min_length_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_unique_vecs_min_length( EXAMPLE_SEED, min_length, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_unique_vecs_min_length() { random_unique_vecs_min_length_helper( 0, &random_primitive_ints::, 4, 1, &[ &[], &[85, 11, 136, 200, 235, 134, 203, 223, 38, 217, 177, 162, 32, 166], &[234, 30, 218, 90], &[106, 9, 216, 204], &[151], &[], &[213, 97, 253, 78, 91], &[39, 191], &[175, 170, 232, 233], &[], &[2, 35, 22, 217, 198, 114], &[], &[], &[17, 32, 173, 114, 65, 121, 222, 25, 144, 148, 79], &[115, 52, 73, 69, 137, 91, 153, 178], &[], &[112, 34, 95], &[], &[106, 167, 197, 130, 168], &[122, 207, 172, 177, 86, 150, 221, 218, 101], ], &[ (&[], 199913), (&[7], 705), (&[25], 689), (&[184], 681), (&[213], 681), (&[255], 676), (&[215], 675), (&[54], 673), (&[122], 672), (&[207], 672), ], (&[96], None), ); random_unique_vecs_min_length_helper( 3, &random_primitive_ints::, 7, 1, &[ &[85, 11, 136], &[200, 235, 134, 203, 223, 38, 217, 177, 162, 32, 166, 234, 30, 218, 90, 106, 9], &[216, 204, 151, 213, 97, 253, 78], &[91, 39, 191, 175, 170, 232, 233], &[2, 35, 22, 217], &[198, 114, 17], &[32, 173, 114, 65, 121, 222, 25, 144], &[148, 79, 115, 52, 73], &[69, 137, 91, 153, 178, 112, 34], &[95, 106, 167], &[197, 130, 168, 122, 207, 172, 177, 86, 150], &[221, 218, 101], &[115, 74, 9], &[123, 109, 52, 201, 159, 247, 250, 48, 133, 235, 196, 40, 97, 104], &[68, 190, 216, 7, 157, 43, 112, 217, 24, 11, 103], &[211, 84, 135], &[55, 29, 206, 89, 65, 191], &[51, 9, 79], &[148, 34, 22, 62, 3, 114, 118, 20], &[47, 194, 50, 32, 120, 176, 166, 23, 204, 248, 177, 238], ], &[ (&[8, 94, 244], 3), (&[233, 14, 180], 3), (&[46, 247, 166], 3), (&[84, 118, 223], 3), (&[4, 52, 2], 2), (&[80, 2, 0], 2), (&[1, 116, 5], 2), (&[1, 5, 192], 2), (&[1, 96, 39], 2), (&[20, 10, 9], 2), ], ( &[127, 218, 55, 167, 163, 19, 99, 71, 32, 117, 72, 38, 27, 29], Some(&[127, 218, 69, 59, 30, 91]), ), ); random_unique_vecs_min_length_helper( 0, &|seed| geometric_random_unsigneds::(seed, 32, 1), 4, 1, &[ &[], &[1, 14, 42, 12, 141, 19, 9, 68, 16, 79, 21, 17, 41, 124], &[10, 1, 99, 0], &[77, 36, 2, 12], &[1], &[], &[103, 9, 19, 1, 5], &[7, 6], &[51, 159, 15, 18], &[], &[52, 75, 40, 64, 2, 26], &[], &[], &[67, 34, 51, 30, 31, 49, 43, 7, 5, 4, 3], &[14, 47, 24, 16, 52, 29, 1, 41], &[], &[13, 11, 62], &[], &[47, 3, 109, 42, 14], &[37, 86, 25, 96, 41, 13, 16, 42, 5], ], &[ (&[], 199913), (&[0], 4861), (&[1], 4593), (&[2], 4498), (&[3], 4405), (&[4], 4330), (&[5], 4078), (&[6], 4050), (&[7], 3858), (&[8], 3848), ], (&[15, 3], None), ); random_unique_vecs_min_length_helper( 3, &|seed| geometric_random_unsigneds::(seed, 32, 1), 7, 1, &[ &[1, 14, 42], &[12, 141, 19, 9, 68, 16, 79, 21, 17, 41, 124, 10, 1, 99, 0, 77, 36], &[2, 12, 1, 103, 9, 19, 5], &[7, 6, 51, 159, 15, 18, 52], &[75, 40, 64, 2], &[26, 67, 34], &[51, 30, 31, 49, 43, 7, 5, 4], &[3, 14, 47, 24, 16], &[52, 29, 1, 41, 13, 11, 62], &[47, 3, 109], &[42, 14, 37, 86, 25, 96, 41, 13, 16], &[42, 5, 20], &[2, 82, 74], &[7, 76, 11, 17, 127, 36, 20, 56, 89, 45, 6, 80, 3, 66], &[23, 43, 1, 25, 6, 41, 19, 97, 10, 13, 32], &[41, 7, 134], &[47, 105, 26, 10, 9, 25], &[94, 68, 109], &[1, 9, 84, 3, 43, 44, 28, 13], &[13, 5, 0, 31, 50, 75, 32, 4, 7, 37, 42, 6], ], &[ (&[0, 1, 7], 13), (&[0, 2, 8], 12), (&[6, 2, 8], 12), (&[0, 2, 5], 11), (&[2, 7, 3], 11), (&[9, 3, 1], 11), (&[0, 9, 2], 10), (&[1, 8, 7], 10), (&[3, 5, 1], 10), (&[5, 0, 2], 10), ], (&[22, 28, 18, 89, 4, 52, 51], Some(&[22, 28, 19])), ); random_unique_vecs_min_length_helper( 0, &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[235, 134], &[203], &[], &[223, 38], &[], &[], &[], &[], ], &[ (&[], 800023), (&[162], 692), (&[235], 690), (&[90], 688), (&[65], 687), (&[249], 686), (&[175], 684), (&[108], 683), (&[211], 682), (&[237], 680), ], (&[], None), ); random_unique_vecs_min_length_helper( 3, &random_primitive_ints::, 13, 4, &[ &[85, 11, 136], &[200, 235, 134], &[203, 223, 38, 235], &[217, 177, 162, 32], &[166, 234, 30, 218, 90], &[106, 9, 216], &[204, 151, 213], &[97, 253, 78], &[91, 39, 191], &[175, 170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17, 32, 173, 65], &[121, 222, 173, 25], &[144, 148, 79], &[115, 52, 73, 69, 137], &[91, 153, 178], &[112, 34, 95], &[106, 167, 197], &[130, 168, 122], ], &[ (&[8, 57, 90], 4), (&[185, 30, 26], 4), (&[106, 20, 234], 4), (&[152, 245, 81], 4), (&[108, 192, 235], 4), (&[75, 2, 5], 3), (&[0, 106, 9], 3), (&[2, 91, 90], 3), (&[212, 1, 8], 3), (&[49, 5, 75], 3), ], (&[128, 38, 40], Some(&[128, 38, 42])), ); random_unique_vecs_min_length_helper( 0, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 4, 1, &[ &[], &['q', 'á', 'g', 'Á', 'À', 'È', '»', 'ì', '³', 'ą', 'â', 'Ã', 'ñ', 'Ā'], &['Ã', 'ª', 'ä', '´'], &['½', 'Á', 'Ï', 'ý'], &['j'], &[], &['ï', 'Ñ', 'u', 'Â', '½'], &['õ', 'x'], &['Â', 'ù', '¡', 'Ċ'], &[], &['¬', 'b', 'Ñ', 's', 'Â', 'r'], &[], &[], &['n', '¿', 'Þ', 'ô', 'Ø', 'º', 'ü', 't', '¬', 'j', 'Á'], &['±', 'è', 'k', 'æ', 'b', 'Î', 'ā', 'Ü'], &[], &['¹', '«', 'Î'], &[], &['~', '´', 'Ý', 'â', '¯'], &['é', 'æ', 'Þ', 'ö', 'g', 'Î', 'Ç', 'Ü', '¼'], ], &[ (&[], 199913), (&['Ó'], 1270), (&['Â'], 1249), (&['§'], 1244), (&['¿'], 1243), (&['õ'], 1241), (&['ĉ'], 1234), (&['¤'], 1232), (&['¼'], 1232), (&['Ì'], 1229), ], ( &['¶', 'Ă', 'ą', '®', 'Á', 'í', '¬', '¾', '¸', 'Ã', '}', 'ù', 'ý', '½', 'a'], Some(&['¶', 'Ă', 'ć']), ), ); random_unique_vecs_min_length_helper( 3, &|seed| { graphic_weighted_random_char_inclusive_range( seed, 'a', exhaustive_chars().nth(200).unwrap(), 1, 1, ) }, 7, 1, &[ &['q', 'á', 'g'], &['Á', 'À', 'È', '»', 'ì', '³', 'ą', 'â', 'g', 'Ã', 'ñ', 'Ā', 'ª', 'ä', '´', '½', 'Ï'], &['ý', 'j', 'ï', 'Ñ', 'u', 'Â', '½'], &['õ', 'x', 'Â', 'ù', '¡', 'Ċ', '¬'], &['b', 'Ñ', '¬', 's'], &['Â', 'r', 'n'], &['¿', 'Þ', 'ô', 'Ø', 'º', 'ü', 't', '¬'], &['j', 'Á', '±', 'è', 'k'], &['æ', 'b', 'Î', 'ā', 'Ü', '¹', '«'], &['Î', '~', '´'], &['Ý', 'â', '¯', 'é', 'æ', 'Þ', 'ö', 'g', 'Î'], &['Ç', 'Ü', '¼'], &['¡', '§', 'Ì'], &['±', 'd', 'ê', 'm', '®', 'ì', '¨', 'ý', 'þ', 'Ë', '{', 'Ü', 'z', '¼'], &['ï', 'ă', 'Ą', 'û', 'ª', 'ċ', 'x', 'À', 'ì', 'Õ', '½'], &['¢', '«', 'Ć'], &['{', 'È', 'ÿ', '½', '¢', 'ä'], &['Ë', 'Õ', 'ê'], &['º', 'ü', '×', '¨', 'Å', 'p', '°', 'Ó'], &['d', 'Ê', 'æ', 'ß', 'v', 'Ć', 'k', 'Ä', '±', 'È', '¥', 'o'], ], &[ (&['a', 'Ã', '¤'], 4), (&['Ā', 'Ì', 'k'], 4), (&['w', 'm', 'u'], 3), (&['a', 'k', 'Ä'], 3), (&['b', 'Ã', 'n'], 3), (&['c', '|', 'Æ'], 3), (&['d', 'm', 'ï'], 3), (&['d', 'z', '¢'], 3), (&['d', '¯', 't'], 3), (&['f', 'g', '¹'], 3), ], ( &['Ç', 'Ĉ', 's', 'ò', 'c', '¿', 'Å', 'Ô', 'Æ'], Some(&['Ç', 'Ĉ', 'v', '³', 'ò']), ), ); } #[test] #[should_panic] fn random_unique_vecs_min_length_fail_1() { random_unique_vecs_min_length(EXAMPLE_SEED, 3, &random_primitive_ints::, 3, 1); } #[test] #[should_panic] fn random_unique_vecs_min_length_fail_2() { random_unique_vecs_min_length(EXAMPLE_SEED, 1, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_unique_vecs_min_length_fail_3() { random_unique_vecs_min_length( EXAMPLE_SEED, 0, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::tuples::random::random_units; use malachite_base::vecs::random::random_vecs; use std::fmt::Debug; fn random_vecs_helper>( xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs( EXAMPLE_SEED, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs() { random_vecs_helper( &|_| random_units(), 4, 1, &[ &[], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), ()], &[(), (), (), ()], &[()], &[], &[(), (), (), (), ()], &[(), ()], &[(), (), (), ()], &[], &[(), (), (), (), (), ()], &[], &[], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[], &[(), (), ()], &[], &[(), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], ], &[ (&[], 199913), (&[()], 160173), (&[(), ()], 128173), (&[(), (), ()], 102460), (&[(), (), (), ()], 81463), (&[(), (), (), (), ()], 65695), (&[(), (), (), (), (), ()], 52495), (&[(), (), (), (), (), (), ()], 41943), (&[(), (), (), (), (), (), (), ()], 33396), (&[(), (), (), (), (), (), (), (), ()], 27035), ], (&[(), (), ()], None), ); random_vecs_helper( &random_primitive_ints::, 4, 1, &[ &[], &[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32], &[166, 234, 30, 218], &[90, 106, 9, 216], &[204], &[], &[151, 213, 97, 253, 78], &[91, 39], &[191, 175, 170, 232], &[], &[233, 2, 35, 22, 217, 198], &[], &[], &[114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144], &[148, 79, 115, 52, 73, 69, 137, 91], &[], &[153, 178, 112], &[], &[34, 95, 106, 167, 197], &[130, 168, 122, 207, 172, 177, 86, 150, 221], ], &[ (&[], 199913), (&[146], 693), (&[26], 692), (&[185], 688), (&[58], 683), (&[196], 683), (&[81], 678), (&[229], 675), (&[192], 673), (&[233], 673), ], (&[96], None), ); random_vecs_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1), 4, 1, &[ &[], &[5, 0, 0, 1, 1, 1, 4, 2, 4, 6, 2, 2, 0, 1], &[9, 13, 0, 0], &[2, 0, 7, 4], &[6], &[], &[7, 6, 0, 0, 0], &[1, 3], &[5, 1, 2, 1], &[], &[0, 0, 1, 4, 2, 0], &[], &[], &[12, 0, 0, 2, 3, 1, 1, 1, 2, 3, 3], &[9, 1, 0, 2, 1, 11, 1, 0], &[], &[1, 6, 0], &[], &[3, 18, 3, 3, 0], &[5, 1, 2, 5, 0, 0, 2, 3, 1], ], &[ (&[], 199913), (&[0], 53462), (&[1], 35352), (&[2], 23512), (&[3], 16118), (&[0, 0], 14371), (&[4], 10594), (&[0, 1], 9566), (&[1, 0], 9409), (&[5], 7157), ], (&[1], None), ); random_vecs_helper( &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[235, 134], &[203], &[], &[223, 38], &[], &[], &[], &[], ], &[ (&[], 800023), (&[8], 704), (&[162], 691), (&[81], 690), (&[211], 690), (&[108], 688), (&[235], 688), (&[35], 687), (&[65], 682), (&[208], 679), ], (&[], None), ); random_vecs_helper( &|seed| random_char_inclusive_range(seed, 'a', 'z'), 4, 1, &[ &[], &['v', 'c', 'q', 'i', 'e', 'p', 'g', 's', 'n', 't', 'm', 'z', 'o', 'm'], &['f', 'k', 'q', 'y'], &['u', 'k', 'x', 'h'], &['u'], &[], &['n', 'n', 'j', 'n', 'j'], &['a', 'w'], &['z', 'l', 'w', 'b'], &[], &['l', 'u', 'n', 'e', 'l', 'v'], &[], &[], &['k', 'u', 'h', 'c', 'y', 'i', 'm', 'r', 'm', 'y', 's'], &['l', 'e', 'a', 's', 'w', 'k', 'o', 'b'], &[], &['k', 'w', 'g'], &[], &['d', 'q', 'e', 'f', 'u'], &['z', 'r', 'g', 'j', 'k', 'r', 's', 'y', 'n'], ], &[ (&[], 199913), (&['o'], 6313), (&['y'], 6262), (&['q'], 6261), (&['j'], 6245), (&['p'], 6244), (&['g'], 6219), (&['x'], 6215), (&['e'], 6200), (&['t'], 6188), ], (&['j', 's', 'z'], None), ); } #[test] #[should_panic] fn random_vecs_fail_1() { random_vecs(EXAMPLE_SEED, &random_primitive_ints::, 0, 1); } #[test] #[should_panic] fn random_vecs_fail_2() { random_vecs(EXAMPLE_SEED, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_vecs_fail_3() { random_vecs( EXAMPLE_SEED, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_fixed_length.rs ================================================ // Copyright © 2026 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 crate::extra_variadic::random_vecs_length_3; use core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::{random_primitive_ints, random_unsigned_range}; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::{random_vecs_fixed_length_from_single, random_vecs_length_2}; use std::fmt::Debug; fn random_vecs_length_2_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_length_2(EXAMPLE_SEED, xs_gen, ys_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_length_2() { random_vecs_length_2_helper( &random_primitive_ints::, &|seed| random_unsigned_range(seed, 0, 10), &[ &[85, 2], &[11, 6], &[136, 8], &[200, 6], &[235, 8], &[134, 2], &[203, 4], &[223, 1], &[38, 2], &[235, 7], &[217, 5], &[177, 4], &[162, 8], &[32, 8], &[166, 4], &[234, 4], &[30, 3], &[218, 5], &[90, 6], &[106, 7], ], &[ (&[196, 6], 466), (&[162, 5], 457), (&[132, 5], 455), (&[200, 2], 455), (&[61, 3], 454), (&[117, 5], 453), (&[28, 0], 446), (&[148, 5], 446), (&[194, 9], 446), (&[44, 3], 444), ], (&[127, 9], None), ); random_vecs_length_2_helper( &|seed| random_vecs_fixed_length_from_single(2, random_primitive_ints::(seed)), &|seed| random_vecs_fixed_length_from_single(3, random_primitive_ints::(seed)), &[ &[vec![85, 11], vec![98, 168, 198]], &[vec![136, 200], vec![40, 20, 252]], &[vec![235, 134], vec![47, 87, 132]], &[vec![203, 223], vec![72, 77, 63]], &[vec![38, 235], vec![91, 108, 127]], &[vec![217, 177], vec![53, 141, 84]], &[vec![162, 32], vec![18, 10, 112]], &[vec![166, 234], vec![154, 104, 53]], &[vec![30, 218], vec![75, 238, 149]], &[vec![90, 106], vec![190, 51, 147]], &[vec![9, 216], vec![100, 114, 140]], &[vec![204, 151], vec![2, 63, 189]], &[vec![213, 97], vec![222, 67, 119]], &[vec![253, 78], vec![0, 223, 5]], &[vec![91, 39], vec![236, 232, 50]], &[vec![191, 175], vec![44, 241, 21]], &[vec![170, 232], vec![22, 94, 27]], &[vec![233, 2], vec![128, 220, 25]], &[vec![35, 22], vec![251, 243, 50]], &[vec![217, 198], vec![137, 235, 46]], ], &[ (&[vec![0, 5], vec![6, 7, 42]], 1), (&[vec![8, 8], vec![18, 5, 6]], 1), (&[vec![9, 1], vec![5, 3, 23]], 1), (&[vec![0, 0], vec![97, 7, 73]], 1), (&[vec![0, 2], vec![12, 20, 6]], 1), (&[vec![0, 99], vec![20, 8, 6]], 1), (&[vec![1, 81], vec![3, 21, 3]], 1), (&[vec![1, 9], vec![219, 9, 7]], 1), (&[vec![1, 9], vec![4, 95, 15]], 1), (&[vec![15, 2], vec![56, 0, 8]], 1), ], ( &[vec![127, 197], vec![162, 123, 217]], Some(&[vec![127, 197], vec![163, 170, 161]]), ), ); } fn random_vecs_length_3_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, K: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, zs_gen: &dyn Fn(Seed) -> K, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_length_3(EXAMPLE_SEED, xs_gen, ys_gen, zs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_length_3() { random_vecs_length_3_helper( &|seed| random_char_inclusive_range(seed, 'a', 'c'), &|seed| random_char_inclusive_range(seed, 'd', 'f'), &|seed| random_char_inclusive_range(seed, 'g', 'i'), &[ &['b', 'f', 'g'], &['b', 'd', 'i'], &['b', 'f', 'i'], &['b', 'e', 'i'], &['c', 'd', 'i'], &['a', 'f', 'i'], &['a', 'f', 'g'], &['a', 'f', 'g'], &['c', 'f', 'i'], &['a', 'e', 'i'], &['c', 'd', 'h'], &['a', 'd', 'h'], &['c', 'f', 'i'], &['a', 'f', 'i'], &['c', 'd', 'g'], &['c', 'd', 'h'], &['c', 'e', 'g'], &['b', 'e', 'h'], &['a', 'd', 'g'], &['c', 'd', 'g'], ], &[ (&['b', 'f', 'i'], 37416), (&['a', 'f', 'g'], 37345), (&['c', 'd', 'i'], 37278), (&['b', 'f', 'g'], 37274), (&['a', 'd', 'h'], 37207), (&['b', 'f', 'h'], 37188), (&['b', 'd', 'i'], 37153), (&['b', 'e', 'g'], 37117), (&['a', 'd', 'g'], 37092), (&['c', 'f', 'g'], 37068), ], (&['b', 'e', 'h'], None), ); random_vecs_length_3_helper( &|seed| random_vecs_fixed_length_from_single(1, random_primitive_ints::(seed)), &|seed| random_vecs_fixed_length_from_single(2, random_primitive_ints::(seed)), &|seed| random_vecs_fixed_length_from_single(3, random_primitive_ints::(seed)), &[ &[vec![85], vec![98, 168], vec![168, 10, 250]], &[vec![11], vec![198, 40], vec![95, 250, 79]], &[vec![136], vec![20, 252], vec![4, 171, 141]], &[vec![200], vec![47, 87], vec![189, 177, 169]], &[vec![235], vec![132, 72], vec![36, 73, 154]], &[vec![134], vec![77, 63], vec![62, 202, 17]], &[vec![203], vec![91, 108], vec![35, 189, 158]], &[vec![223], vec![127, 53], vec![31, 173, 175]], &[vec![38], vec![141, 84], vec![63, 225, 106]], &[vec![235], vec![18, 10], vec![40, 116, 16]], &[vec![217], vec![112, 154], vec![88, 112, 9]], &[vec![177], vec![104, 53], vec![227, 144, 93]], &[vec![162], vec![75, 238], vec![85, 90, 214]], &[vec![32], vec![149, 190], vec![31, 60, 254]], &[vec![166], vec![51, 147], vec![143, 44, 177]], &[vec![234], vec![100, 114], vec![205, 197, 53]], &[vec![30], vec![140, 2], vec![15, 184, 137]], &[vec![218], vec![63, 189], vec![75, 116, 140]], &[vec![90], vec![222, 67], vec![19, 119, 60]], &[vec![106], vec![119, 0], vec![219, 21, 164]], ], &[ (&[vec![0], vec![47, 4], vec![31, 6, 1]], 1), (&[vec![0], vec![5, 12], vec![9, 6, 54]], 1), (&[vec![6], vec![99, 35], vec![3, 2, 3]], 1), (&[vec![7], vec![7, 56], vec![6, 3, 76]], 1), (&[vec![7], vec![9, 5], vec![148, 1, 1]], 1), (&[vec![9], vec![61, 7], vec![9, 60, 8]], 1), (&[vec![0], vec![0, 55], vec![1, 12, 83]], 1), (&[vec![0], vec![1, 57], vec![60, 4, 55]], 1), (&[vec![0], vec![1, 8], vec![235, 0, 27]], 1), (&[vec![0], vec![73, 15], vec![0, 2, 11]], 1), ], ( &[vec![127], vec![241, 129], vec![232, 173, 11]], Some(&[vec![127], vec![241, 149], vec![219, 172, 49]]), ), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_fixed_length_from_single.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use itertools::{Itertools, repeat_n}; use malachite_base::bools::random::random_bools; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_vecs_fixed_length_from_single; use std::fmt::Debug; fn random_vecs_fixed_length_from_single_helper( len: u64, xs: I, expected_values: &[&[I::Item]], expected_common_values: &[(&[I::Item], usize)], expected_median: (&[I::Item], Option<&[I::Item]>), ) where I::Item: Clone + Debug + Eq + Hash + Ord, { random_vecs_helper_helper( random_vecs_fixed_length_from_single(len, xs), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_fixed_length_from_single() { random_vecs_fixed_length_from_single_helper( 0, random_primitive_ints::(EXAMPLE_SEED), repeat_n(&[][..], 20).collect_vec().as_slice(), &[(&[], 1000000)], (&[], None), ); random_vecs_fixed_length_from_single_helper( 1, random_bools(EXAMPLE_SEED), &[ &[true], &[false], &[false], &[false], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[true], &[true], &[true], &[false], &[true], &[false], ], &[(&[true], 500473), (&[false], 499527)], (&[true], None), ); random_vecs_fixed_length_from_single_helper( 3, random_primitive_ints::(EXAMPLE_SEED), &[ &[113, 239, 69], &[108, 228, 210], &[168, 161, 87], &[32, 110, 83], &[188, 34, 89], &[238, 93, 200], &[149, 115, 189], &[149, 217, 201], &[117, 146, 31], &[72, 151, 169], &[174, 33, 7], &[38, 81, 144], &[72, 127, 113], &[128, 233, 107], &[46, 119, 12], &[18, 164, 243], &[114, 174, 59], &[247, 39, 174], &[160, 184, 104], &[37, 100, 252], ], &[ (&[222, 60, 79], 4), (&[26, 110, 13], 4), (&[41, 254, 55], 4), (&[109, 134, 76], 4), (&[165, 174, 73], 4), (&[236, 57, 174], 4), (&[73, 168, 192], 4), (&[89, 197, 244], 4), (&[91, 170, 115], 4), (&[142, 168, 231], 4), ], (&[127, 253, 76], Some(&[127, 253, 86])), ); random_vecs_fixed_length_from_single_helper( 2, random_vecs_fixed_length_from_single(2, random_primitive_ints::(EXAMPLE_SEED)), &[ &[vec![113, 239], vec![69, 108]], &[vec![228, 210], vec![168, 161]], &[vec![87, 32], vec![110, 83]], &[vec![188, 34], vec![89, 238]], &[vec![93, 200], vec![149, 115]], &[vec![189, 149], vec![217, 201]], &[vec![117, 146], vec![31, 72]], &[vec![151, 169], vec![174, 33]], &[vec![7, 38], vec![81, 144]], &[vec![72, 127], vec![113, 128]], &[vec![233, 107], vec![46, 119]], &[vec![12, 18], vec![164, 243]], &[vec![114, 174], vec![59, 247]], &[vec![39, 174], vec![160, 184]], &[vec![104, 37], vec![100, 252]], &[vec![228, 122], vec![107, 69]], &[vec![242, 248], vec![179, 142]], &[vec![239, 233], vec![61, 189]], &[vec![235, 85], vec![192, 7]], &[vec![200, 90], vec![185, 178]], ], &[ (&[vec![28, 96], vec![0, 11]], 2), (&[vec![2, 43], vec![64, 233]], 2), (&[vec![20, 33], vec![14, 10]], 2), (&[vec![223, 84], vec![7, 22]], 2), (&[vec![43, 33], vec![131, 6]], 2), (&[vec![6, 233], vec![45, 89]], 2), (&[vec![65, 26], vec![6, 146]], 2), (&[vec![71, 80], vec![68, 88]], 2), (&[vec![9, 85], vec![186, 55]], 2), (&[vec![96, 254], vec![9, 37]], 2), ], ( &[vec![127, 243], vec![125, 130]], Some(&[vec![127, 243], vec![134, 100]]), ), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_fixed_length_m_inputs.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::num::random::{random_primitive_ints, random_unsigned_range}; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::{ random_vecs_fixed_length_2_inputs, random_vecs_fixed_length_from_single, }; use std::fmt::Debug; fn random_vecs_fixed_length_2_inputs_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( xs_gen: &dyn Fn(Seed) -> I, ys_gen: &dyn Fn(Seed) -> J, output_to_input_map: &[usize], expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_fixed_length_2_inputs(EXAMPLE_SEED, xs_gen, ys_gen, output_to_input_map), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_fixed_length_2_inputs() { random_vecs_fixed_length_2_inputs_helper( &random_primitive_ints::, &|seed| random_unsigned_range(seed, 0, 10), &[0, 0, 1], &[ &[85, 11, 2], &[136, 200, 6], &[235, 134, 8], &[203, 223, 6], &[38, 235, 8], &[217, 177, 2], &[162, 32, 4], &[166, 234, 1], &[30, 218, 2], &[90, 106, 7], &[9, 216, 5], &[204, 151, 4], &[213, 97, 8], &[253, 78, 8], &[91, 39, 4], &[191, 175, 4], &[170, 232, 3], &[233, 2, 5], &[35, 22, 6], &[217, 198, 7], ], &[ (&[156, 162, 3], 11), (&[248, 1, 7], 10), (&[178, 121, 1], 10), (&[36, 97, 6], 9), (&[46, 27, 2], 9), (&[64, 75, 6], 9), (&[135, 80, 5], 9), (&[215, 11, 3], 9), (&[39, 178, 7], 9), (&[75, 164, 6], 9), ], (&[127, 197, 7], None), ); random_vecs_fixed_length_2_inputs_helper( &|seed| random_vecs_fixed_length_from_single(2, random_primitive_ints::(seed)), &|seed| random_vecs_fixed_length_from_single(3, random_primitive_ints::(seed)), &[0, 1, 0], &[ &[vec![85, 11], vec![98, 168, 198], vec![136, 200]], &[vec![235, 134], vec![40, 20, 252], vec![203, 223]], &[vec![38, 235], vec![47, 87, 132], vec![217, 177]], &[vec![162, 32], vec![72, 77, 63], vec![166, 234]], &[vec![30, 218], vec![91, 108, 127], vec![90, 106]], &[vec![9, 216], vec![53, 141, 84], vec![204, 151]], &[vec![213, 97], vec![18, 10, 112], vec![253, 78]], &[vec![91, 39], vec![154, 104, 53], vec![191, 175]], &[vec![170, 232], vec![75, 238, 149], vec![233, 2]], &[vec![35, 22], vec![190, 51, 147], vec![217, 198]], &[vec![114, 17], vec![100, 114, 140], vec![32, 173]], &[vec![114, 65], vec![2, 63, 189], vec![121, 222]], &[vec![173, 25], vec![222, 67, 119], vec![144, 148]], &[vec![79, 115], vec![0, 223, 5], vec![52, 73]], &[vec![69, 137], vec![236, 232, 50], vec![91, 153]], &[vec![178, 112], vec![44, 241, 21], vec![34, 95]], &[vec![106, 167], vec![22, 94, 27], vec![197, 130]], &[vec![168, 122], vec![128, 220, 25], vec![207, 172]], &[vec![177, 86], vec![251, 243, 50], vec![150, 221]], &[vec![218, 101], vec![137, 235, 46], vec![115, 74]], ], &[ (&[vec![8, 24], vec![0, 54, 59], vec![5, 3]], 1), (&[vec![8, 72], vec![6, 5, 9], vec![11, 57]], 1), (&[vec![80, 9], vec![84, 9, 10], vec![9, 5]], 1), (&[vec![86, 2], vec![2, 0, 27], vec![49, 4]], 1), (&[vec![0, 2], vec![207, 31, 7], vec![92, 5]], 1), (&[vec![1, 15], vec![51, 5, 47], vec![12, 5]], 1), (&[vec![1, 25], vec![70, 65, 7], vec![3, 66]], 1), (&[vec![1, 72], vec![8, 49, 246], vec![2, 1]], 1), (&[vec![1, 82], vec![86, 3, 70], vec![6, 26]], 1), (&[vec![1, 85], vec![3, 5, 53], vec![14, 92]], 1), ], ( &[vec![128, 20], vec![252, 3, 74], vec![108, 132]], Some(&[vec![128, 21], vec![6, 87, 236], vec![223, 197]]), ), ); } #[test] #[should_panic] fn random_vecs_fixed_length_2_inputs_fail_1() { random_vecs_fixed_length_2_inputs( EXAMPLE_SEED, &|seed| random_unsigned_range::(seed, 0, 10), &|seed| random_unsigned_range(seed, 0, 5), &[], ); } #[test] #[should_panic] fn random_vecs_fixed_length_2_inputs_fail_2() { random_vecs_fixed_length_2_inputs( EXAMPLE_SEED, &|seed| random_unsigned_range::(seed, 0, 10), &|seed| random_unsigned_range(seed, 0, 5), &[0], ); } #[test] #[should_panic] fn random_vecs_fixed_length_2_inputs_fail_3() { random_vecs_fixed_length_2_inputs( EXAMPLE_SEED, &|seed| random_unsigned_range::(seed, 0, 10), &|seed| random_unsigned_range(seed, 0, 5), &[1], ); } #[test] #[should_panic] fn random_vecs_fixed_length_2_inputs_fail_4() { random_vecs_fixed_length_2_inputs( EXAMPLE_SEED, &|seed| random_unsigned_range::(seed, 0, 10), &|seed| random_unsigned_range(seed, 0, 5), &[0, 1, 2], ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_from_length_iterator.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::bools::random::random_bools; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::vecs::random::random_vecs_from_length_iterator; use malachite_base::vecs::random_values_from_vec; use std::fmt::Debug; fn random_vecs_from_length_iterator_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, J: Clone + Iterator, >( lengths_gen: &dyn Fn(Seed) -> I, xs_gen: &dyn Fn(Seed) -> J, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_from_length_iterator(EXAMPLE_SEED, lengths_gen, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_from_length_iterator() { random_vecs_from_length_iterator_helper( &|seed| random_values_from_vec(seed, vec![0, 2, 4]), &random_bools, &[ &[true, false], &[true, false, true, false], &[true, false], &[true, true, false, true], &[false, false, false, false], &[false, false], &[], &[false, true], &[], &[false, false, false, true], &[false, false, false, true], &[false, false], &[true, true, true, true], &[false, true], &[false, true, true, true], &[false, true, true, false], &[false, false, false, true], &[], &[true, true, false, true], &[], ], &[ (&[], 333820), (&[true, false], 83553), (&[false, false], 83348), (&[false, true], 83319), (&[true, true], 82905), (&[true, true, true, false], 21126), (&[false, false, false, true], 20940), (&[false, false, true, false], 20931), (&[true, true, false, true], 20925), (&[true, false, false, false], 20899), ], (&[false, false, true, true], None), ); random_vecs_from_length_iterator_helper( &|seed| geometric_random_unsigneds::(seed, 2, 1).map(|x| x << 1), &random_primitive_ints::, &[ &[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177], &[162, 32], &[166, 234, 30, 218, 90, 106, 9, 216, 204, 151, 213, 97, 253, 78, 91, 39], &[191, 175], &[ 170, 232, 233, 2, 35, 22, 217, 198, 114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144, 148, 79, 115, 52, 73, 69, 137, 91, 153, ], &[], &[178, 112, 34, 95, 106, 167, 197, 130, 168, 122], &[207, 172, 177, 86, 150, 221, 218, 101], &[115, 74], &[], &[9, 123, 109, 52, 201, 159, 247, 250, 48, 133, 235, 196], &[40, 97, 104, 68], &[], &[], &[190, 216], &[7, 216, 157, 43, 43, 112], &[], &[217, 24], &[], &[11, 103], ], &[ (&[], 333981), (&[198, 47], 13), (&[203, 121], 13), (&[77, 29], 12), (&[97, 58], 12), (&[174, 43], 12), (&[80, 107], 12), (&[100, 118], 12), (&[176, 218], 12), (&[203, 110], 12), ], (&[63, 135], None), ); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_length_inclusive_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::tuples::random::random_units; use malachite_base::vecs::random::random_vecs_length_inclusive_range; use std::fmt::Debug; fn random_vecs_length_inclusive_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_length_inclusive_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_length_inclusive_range() { random_vecs_length_inclusive_range_helper( 2, 3, &|_| random_units(), &[ &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), ()], &[(), ()], &[(), (), ()], &[(), ()], ], &[(&[(), (), ()], 500363), (&[(), ()], 499637)], (&[(), (), ()], None), ); random_vecs_length_inclusive_range_helper( 2, 3, &random_primitive_ints::, &[ &[85, 11, 136], &[200, 235], &[134, 203, 223], &[38, 235, 217], &[177, 162], &[32, 166, 234], &[30, 218, 90], &[106, 9], &[216, 204, 151], &[213, 97, 253], &[78, 91], &[39, 191, 175], &[170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17], &[32, 173], &[114, 65], &[121, 222, 173], &[25, 144], ], &[ (&[234, 192], 23), (&[0, 40], 19), (&[68, 88], 19), (&[188, 21], 19), (&[215, 22], 19), (&[221, 92], 19), (&[255, 26], 19), (&[34, 253], 19), (&[61, 159], 19), (&[155, 140], 19), ], (&[128, 5, 208], Some(&[128, 5, 239])), ); random_vecs_length_inclusive_range_helper( 2, 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[5, 0, 0], &[1, 1], &[1, 4, 2], &[4, 6, 2], &[2, 0], &[1, 9, 13], &[0, 0, 2], &[0, 7], &[4, 6, 7], &[6, 0, 0], &[0, 1], &[3, 5, 1], &[2, 1], &[0, 0, 1], &[4, 2, 0], &[12, 0], &[0, 2], &[3, 1], &[1, 1, 2], &[3, 3], ], &[ (&[0, 0], 55357), (&[0, 1], 37179), (&[1, 0], 37106), (&[0, 2], 24784), (&[2, 0], 24772), (&[1, 1], 24686), (&[0, 0, 0], 18703), (&[3, 0], 16656), (&[2, 1], 16622), (&[1, 2], 16275), ], (&[1, 3], None), ); random_vecs_length_inclusive_range_helper( 2, 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['v', 'c', 'q'], &['i', 'e'], &['p', 'g', 's'], &['n', 't', 'm'], &['z', 'o'], &['m', 'f', 'k'], &['q', 'y', 'u'], &['k', 'x'], &['h', 'u', 'n'], &['n', 'j', 'n'], &['j', 'a'], &['w', 'z', 'l'], &['w', 'b'], &['l', 'u', 'n'], &['e', 'l', 'v'], &['k', 'u'], &['h', 'c'], &['y', 'i'], &['m', 'r', 'm'], &['y', 's'], ], &[ (&['w', 'o'], 822), (&['f', 's'], 814), (&['w', 'u'], 810), (&['g', 'c'], 806), (&['w', 'f'], 806), (&['m', 'z'], 805), (&['q', 'k'], 805), (&['i', 'b'], 802), (&['u', 'k'], 800), (&['h', 'p'], 798), ], (&['m', 'z', 'w'], None), ); } #[test] #[should_panic] fn random_vecs_length_inclusive_range_fail() { random_vecs_length_inclusive_range(EXAMPLE_SEED, 2, 1, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_length_range.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::tuples::random::random_units; use malachite_base::vecs::random::random_vecs_length_range; use std::fmt::Debug; fn random_vecs_length_range_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( a: u64, b: u64, xs_gen: &dyn Fn(Seed) -> I, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_length_range(EXAMPLE_SEED, a, b, xs_gen), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_length_range() { random_vecs_length_range_helper( 2, 4, &|_| random_units(), &[ &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), ()], &[(), (), ()], &[(), (), ()], &[(), ()], &[(), ()], &[(), ()], &[(), (), ()], &[(), ()], ], &[(&[(), (), ()], 500363), (&[(), ()], 499637)], (&[(), (), ()], None), ); random_vecs_length_range_helper( 2, 4, &random_primitive_ints::, &[ &[85, 11, 136], &[200, 235], &[134, 203, 223], &[38, 235, 217], &[177, 162], &[32, 166, 234], &[30, 218, 90], &[106, 9], &[216, 204, 151], &[213, 97, 253], &[78, 91], &[39, 191, 175], &[170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17], &[32, 173], &[114, 65], &[121, 222, 173], &[25, 144], ], &[ (&[234, 192], 23), (&[0, 40], 19), (&[68, 88], 19), (&[188, 21], 19), (&[215, 22], 19), (&[221, 92], 19), (&[255, 26], 19), (&[34, 253], 19), (&[61, 159], 19), (&[155, 140], 19), ], (&[128, 5, 208], Some(&[128, 5, 239])), ); random_vecs_length_range_helper( 2, 4, &|seed| geometric_random_unsigneds::(seed, 2, 1), &[ &[5, 0, 0], &[1, 1], &[1, 4, 2], &[4, 6, 2], &[2, 0], &[1, 9, 13], &[0, 0, 2], &[0, 7], &[4, 6, 7], &[6, 0, 0], &[0, 1], &[3, 5, 1], &[2, 1], &[0, 0, 1], &[4, 2, 0], &[12, 0], &[0, 2], &[3, 1], &[1, 1, 2], &[3, 3], ], &[ (&[0, 0], 55357), (&[0, 1], 37179), (&[1, 0], 37106), (&[0, 2], 24784), (&[2, 0], 24772), (&[1, 1], 24686), (&[0, 0, 0], 18703), (&[3, 0], 16656), (&[2, 1], 16622), (&[1, 2], 16275), ], (&[1, 3], None), ); random_vecs_length_range_helper( 2, 4, &|seed| random_char_inclusive_range(seed, 'a', 'z'), &[ &['v', 'c', 'q'], &['i', 'e'], &['p', 'g', 's'], &['n', 't', 'm'], &['z', 'o'], &['m', 'f', 'k'], &['q', 'y', 'u'], &['k', 'x'], &['h', 'u', 'n'], &['n', 'j', 'n'], &['j', 'a'], &['w', 'z', 'l'], &['w', 'b'], &['l', 'u', 'n'], &['e', 'l', 'v'], &['k', 'u'], &['h', 'c'], &['y', 'i'], &['m', 'r', 'm'], &['y', 's'], ], &[ (&['w', 'o'], 822), (&['f', 's'], 814), (&['w', 'u'], 810), (&['g', 'c'], 806), (&['w', 'f'], 806), (&['m', 'z'], 805), (&['q', 'k'], 805), (&['i', 'b'], 802), (&['u', 'k'], 800), (&['h', 'p'], 798), ], (&['m', 'z', 'w'], None), ); } #[test] #[should_panic] fn random_vecs_length_range_fail() { random_vecs_length_range(EXAMPLE_SEED, 2, 2, &random_primitive_ints::); } ================================================ FILE: malachite-base/tests/vecs/random/random_vecs_min_length.rs ================================================ // Copyright © 2026 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 core::hash::Hash; use malachite_base::chars::random::random_char_inclusive_range; use malachite_base::num::random::geometric::geometric_random_unsigneds; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::test_util::vecs::random::random_vecs_helper_helper; use malachite_base::tuples::random::random_units; use malachite_base::vecs::random::random_vecs_min_length; use std::fmt::Debug; fn random_vecs_min_length_helper< T: Clone + Debug + Eq + Hash + Ord, I: Clone + Iterator, >( min_length: u64, xs_gen: &dyn Fn(Seed) -> I, mean_length_numerator: u64, mean_length_denominator: u64, expected_values: &[&[T]], expected_common_values: &[(&[T], usize)], expected_median: (&[T], Option<&[T]>), ) { random_vecs_helper_helper( random_vecs_min_length( EXAMPLE_SEED, min_length, xs_gen, mean_length_numerator, mean_length_denominator, ), expected_values, expected_common_values, expected_median, ); } #[test] fn test_random_vecs_min_length() { random_vecs_min_length_helper( 0, &|_| random_units(), 4, 1, &[ &[], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), ()], &[(), (), (), ()], &[()], &[], &[(), (), (), (), ()], &[(), ()], &[(), (), (), ()], &[], &[(), (), (), (), (), ()], &[], &[], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), ()], &[], &[(), (), ()], &[], &[(), (), (), (), ()], &[(), (), (), (), (), (), (), (), ()], ], &[ (&[], 199913), (&[()], 160173), (&[(), ()], 128173), (&[(), (), ()], 102460), (&[(), (), (), ()], 81463), (&[(), (), (), (), ()], 65695), (&[(), (), (), (), (), ()], 52495), (&[(), (), (), (), (), (), ()], 41943), (&[(), (), (), (), (), (), (), ()], 33396), (&[(), (), (), (), (), (), (), (), ()], 27035), ], (&[(), (), ()], None), ); random_vecs_min_length_helper( 3, &|_| random_units(), 7, 1, &[ &[(), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), (), ()], &[(), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), ()], &[(), (), (), (), (), (), ()], &[(), (), ()], &[(), (), (), (), (), (), (), (), ()], &[(), (), ()], &[(), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), ()], &[(), (), ()], &[(), (), (), (), (), ()], &[(), (), ()], &[(), (), (), (), (), (), (), ()], &[(), (), (), (), (), (), (), (), (), (), (), ()], ], &[ (&[(), (), ()], 199913), (&[(), (), (), ()], 160173), (&[(), (), (), (), ()], 128173), (&[(), (), (), (), (), ()], 102460), (&[(), (), (), (), (), (), ()], 81463), (&[(), (), (), (), (), (), (), ()], 65695), (&[(), (), (), (), (), (), (), (), ()], 52495), (&[(), (), (), (), (), (), (), (), (), ()], 41943), (&[(), (), (), (), (), (), (), (), (), (), ()], 33396), (&[(), (), (), (), (), (), (), (), (), (), (), ()], 27035), ], (&[(), (), (), (), (), ()], None), ); random_vecs_min_length_helper( 0, &random_primitive_ints::, 4, 1, &[ &[], &[85, 11, 136, 200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32], &[166, 234, 30, 218], &[90, 106, 9, 216], &[204], &[], &[151, 213, 97, 253, 78], &[91, 39], &[191, 175, 170, 232], &[], &[233, 2, 35, 22, 217, 198], &[], &[], &[114, 17, 32, 173, 114, 65, 121, 222, 173, 25, 144], &[148, 79, 115, 52, 73, 69, 137, 91], &[], &[153, 178, 112], &[], &[34, 95, 106, 167, 197], &[130, 168, 122, 207, 172, 177, 86, 150, 221], ], &[ (&[], 199913), (&[146], 693), (&[26], 692), (&[185], 688), (&[58], 683), (&[196], 683), (&[81], 678), (&[229], 675), (&[192], 673), (&[233], 673), ], (&[96], None), ); random_vecs_min_length_helper( 3, &random_primitive_ints::, 7, 1, &[ &[85, 11, 136], &[200, 235, 134, 203, 223, 38, 235, 217, 177, 162, 32, 166, 234, 30, 218, 90, 106], &[9, 216, 204, 151, 213, 97, 253], &[78, 91, 39, 191, 175, 170, 232], &[233, 2, 35, 22], &[217, 198, 114], &[17, 32, 173, 114, 65, 121, 222, 173], &[25, 144, 148, 79, 115], &[52, 73, 69, 137, 91, 153, 178], &[112, 34, 95], &[106, 167, 197, 130, 168, 122, 207, 172, 177], &[86, 150, 221], &[218, 101, 115], &[74, 9, 123, 109, 52, 201, 159, 247, 250, 48, 133, 235, 196, 40], &[97, 104, 68, 190, 216, 7, 216, 157, 43, 43, 112], &[217, 24, 11], &[103, 211, 84, 135, 55, 29], &[206, 89, 65], &[191, 51, 9, 79, 148, 34, 22, 22], &[62, 3, 114, 118, 20, 47, 194, 50, 32, 120, 176, 166], ], &[ (&[65, 71, 68], 3), (&[34, 39, 234], 3), (&[207, 218, 62], 3), (&[89, 175, 228], 3), (&[198, 166, 242], 3), (&[2, 94, 4], 2), (&[3, 91, 9], 2), (&[6, 3, 61], 2), (&[0, 18, 20], 2), (&[1, 48, 93], 2), ], (&[128, 11, 100, 4, 101, 167, 125], Some(&[128, 11, 104])), ); random_vecs_min_length_helper( 0, &|seed| geometric_random_unsigneds::(seed, 2, 1), 4, 1, &[ &[], &[5, 0, 0, 1, 1, 1, 4, 2, 4, 6, 2, 2, 0, 1], &[9, 13, 0, 0], &[2, 0, 7, 4], &[6], &[], &[7, 6, 0, 0, 0], &[1, 3], &[5, 1, 2, 1], &[], &[0, 0, 1, 4, 2, 0], &[], &[], &[12, 0, 0, 2, 3, 1, 1, 1, 2, 3, 3], &[9, 1, 0, 2, 1, 11, 1, 0], &[], &[1, 6, 0], &[], &[3, 18, 3, 3, 0], &[5, 1, 2, 5, 0, 0, 2, 3, 1], ], &[ (&[], 199913), (&[0], 53462), (&[1], 35352), (&[2], 23512), (&[3], 16118), (&[0, 0], 14371), (&[4], 10594), (&[0, 1], 9566), (&[1, 0], 9409), (&[5], 7157), ], (&[1], None), ); random_vecs_min_length_helper( 3, &|seed| geometric_random_unsigneds::(seed, 2, 1), 7, 1, &[ &[5, 0, 0], &[1, 1, 1, 4, 2, 4, 6, 2, 2, 0, 1, 9, 13, 0, 0, 2, 0], &[7, 4, 6, 7, 6, 0, 0], &[0, 1, 3, 5, 1, 2, 1], &[0, 0, 1, 4], &[2, 0, 12], &[0, 0, 2, 3, 1, 1, 1, 2], &[3, 3, 9, 1, 0], &[2, 1, 11, 1, 0, 1, 6], &[0, 3, 18], &[3, 3, 0, 5, 1, 2, 5, 0, 0], &[2, 3, 1], &[0, 2, 1], &[2, 3, 1, 3, 3, 0, 0, 7, 2, 0, 0, 4, 2, 1], &[0, 3, 1, 4, 2, 2, 1, 5, 0, 2, 0], &[2, 0, 0], &[1, 4, 1, 3, 3, 1], &[0, 0, 0], &[1, 4, 2, 1, 1, 0, 1, 0], &[0, 0, 1, 0, 2, 0, 7, 0, 0, 0, 2, 12], ], &[ (&[0, 0, 0], 7500), (&[1, 0, 0], 5048), (&[0, 0, 1], 4956), (&[0, 1, 0], 4876), (&[0, 0, 2], 3336), (&[0, 2, 0], 3320), (&[1, 1, 0], 3305), (&[2, 0, 0], 3303), (&[0, 1, 1], 3242), (&[1, 0, 1], 3239), ], ( &[1, 3, 1, 1, 4, 0, 2, 3], Some(&[1, 3, 1, 1, 4, 0, 4, 0, 0]), ), ); random_vecs_min_length_helper( 0, &random_primitive_ints::, 1, 4, &[ &[], &[], &[85], &[11], &[136, 200], &[], &[], &[], &[], &[], &[], &[], &[235, 134], &[203], &[], &[223, 38], &[], &[], &[], &[], ], &[ (&[], 800023), (&[8], 704), (&[162], 691), (&[81], 690), (&[211], 690), (&[108], 688), (&[235], 688), (&[35], 687), (&[65], 682), (&[208], 679), ], (&[], None), ); random_vecs_min_length_helper( 3, &random_primitive_ints::, 13, 4, &[ &[85, 11, 136], &[200, 235, 134], &[203, 223, 38, 235], &[217, 177, 162, 32], &[166, 234, 30, 218, 90], &[106, 9, 216], &[204, 151, 213], &[97, 253, 78], &[91, 39, 191], &[175, 170, 232], &[233, 2, 35], &[22, 217, 198], &[114, 17, 32, 173, 114], &[65, 121, 222, 173], &[25, 144, 148], &[79, 115, 52, 73, 69], &[137, 91, 153], &[178, 112, 34], &[95, 106, 167], &[197, 130, 168], ], &[ (&[34, 248, 94], 4), (&[155, 89, 108], 4), (&[232, 167, 146], 4), (&[255, 244, 186], 4), (&[0, 70, 96], 3), (&[18, 1, 93], 3), (&[30, 0, 90], 3), (&[50, 3, 37], 3), (&[82, 1, 99], 3), (&[9, 42, 49], 3), ], (&[127, 228, 182], Some(&[127, 228, 193])), ); random_vecs_min_length_helper( 0, &|seed| random_char_inclusive_range(seed, 'a', 'z'), 4, 1, &[ &[], &['v', 'c', 'q', 'i', 'e', 'p', 'g', 's', 'n', 't', 'm', 'z', 'o', 'm'], &['f', 'k', 'q', 'y'], &['u', 'k', 'x', 'h'], &['u'], &[], &['n', 'n', 'j', 'n', 'j'], &['a', 'w'], &['z', 'l', 'w', 'b'], &[], &['l', 'u', 'n', 'e', 'l', 'v'], &[], &[], &['k', 'u', 'h', 'c', 'y', 'i', 'm', 'r', 'm', 'y', 's'], &['l', 'e', 'a', 's', 'w', 'k', 'o', 'b'], &[], &['k', 'w', 'g'], &[], &['d', 'q', 'e', 'f', 'u'], &['z', 'r', 'g', 'j', 'k', 'r', 's', 'y', 'n'], ], &[ (&[], 199913), (&['o'], 6313), (&['y'], 6262), (&['q'], 6261), (&['j'], 6245), (&['p'], 6244), (&['g'], 6219), (&['x'], 6215), (&['e'], 6200), (&['t'], 6188), ], (&['j', 's', 'z'], None), ); random_vecs_min_length_helper( 3, &|seed| random_char_inclusive_range(seed, 'a', 'z'), 7, 1, &[ &['v', 'c', 'q'], &['i', 'e', 'p', 'g', 's', 'n', 't', 'm', 'z', 'o', 'm', 'f', 'k', 'q', 'y', 'u', 'k'], &['x', 'h', 'u', 'n', 'n', 'j', 'n'], &['j', 'a', 'w', 'z', 'l', 'w', 'b'], &['l', 'u', 'n', 'e'], &['l', 'v', 'k'], &['u', 'h', 'c', 'y', 'i', 'm', 'r', 'm'], &['y', 's', 'l', 'e', 'a'], &['s', 'w', 'k', 'o', 'b', 'k', 'w'], &['g', 'd', 'q'], &['e', 'f', 'u', 'z', 'r', 'g', 'j', 'k', 'r'], &['s', 'y', 'n'], &['f', 't', 's'], &['f', 'e', 's', 'p', 'j', 'n', 'h', 'n', 'r', 'f', 'i', 'u', 'k', 'p'], &['p', 'g', 'l', 'd', 'l', 'l', 'z', 's', 'w', 'w', 'l'], &['w', 'z', 'j'], &['j', 'j', 'y', 'g', 'e', 'z'], &['v', 'p', 'y'], &['u', 'q', 'l', 'h', 'r', 'r', 's', 'q'], &['b', 'n', 'e', 's', 'p', 'r', 'd', 'a', 'k', 'w', 'c', 'y'], ], &[ (&['b', 'c', 'j'], 25), (&['e', 'k', 'd'], 25), (&['a', 'x', 'n'], 24), (&['b', 'e', 'z'], 24), (&['c', 'c', 'b'], 24), (&['d', 'g', 'h'], 24), (&['g', 'l', 'i'], 24), (&['i', 'w', 'n'], 24), (&['j', 'd', 'w'], 24), (&['m', 'y', 'a'], 24), ], ( &['m', 'z', 'z', 'r', 'e', 'r'], Some(&['m', 'z', 'z', 'r', 'g', 'i']), ), ); } #[test] #[should_panic] fn random_vecs_min_length_fail_1() { random_vecs_min_length(EXAMPLE_SEED, 3, &random_primitive_ints::, 3, 1); } #[test] #[should_panic] fn random_vecs_min_length_fail_2() { random_vecs_min_length(EXAMPLE_SEED, 1, &random_primitive_ints::, 1, 0); } #[test] #[should_panic] fn random_vecs_min_length_fail_3() { random_vecs_min_length( EXAMPLE_SEED, 0, &random_primitive_ints::, u64::MAX, u64::MAX - 1, ); } ================================================ FILE: malachite-base/tests/vecs/random_values_from_vec.rs ================================================ // Copyright © 2026 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::nevers::Never; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map_debug; use malachite_base::test_util::stats::median; use malachite_base::vecs::random_values_from_vec; #[test] fn test_random_values_from_vec() { let test = |vec: Vec, values: &[u32], common_values: &[(u32, usize)], actual_median: (u32, Option)| { let xs = random_values_from_vec(EXAMPLE_SEED, vec); let expected_values = xs.clone().take(20).collect_vec(); let expected_common_values = common_values_map_debug(1000000, 10, xs.clone()); let expected_median = median(xs.take(1000000)); assert_eq!( ( expected_values.as_slice(), expected_common_values.as_slice(), expected_median ), (values, common_values, actual_median) ); }; test(vec![5], &[5; 20], &[(5, 1000000)], (5, None)); test( vec![0, 1], &[1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0], &[(1, 500473), (0, 499527)], (1, None), ); test( vec![1, 1, 1, 10], &[1, 1, 10, 1, 10, 10, 1, 10, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1, 1, 10], &[(1, 749985), (10, 250015)], (1, None), ); test( vec![2, 3, 5, 7, 11], &[3, 7, 3, 5, 11, 3, 5, 11, 2, 2, 5, 5, 2, 11, 2, 11, 5, 11, 5, 3], &[(2, 200420), (7, 200369), (11, 200347), (5, 199589), (3, 199275)], (5, None), ); } #[test] #[should_panic] fn random_values_from_vec_fail() { random_values_from_vec::(EXAMPLE_SEED, vec![]); } ================================================ FILE: malachite-base/tests/vecs/random_vec_permutations.rs ================================================ // Copyright © 2026 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::random::EXAMPLE_SEED; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::vecs::random_vec_permutations; fn random_vec_permutations_helper( cs: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_median: (&str, Option<&str>), ) { let ss = random_vec_permutations(EXAMPLE_SEED, cs.chars().collect_vec()) .map(|ds| ds.into_iter().collect()); let values = ss.clone().take(20).collect_vec(); let common_values = common_values_map(1000000, 10, ss.clone()); let (median_lo, median_hi) = median(ss.take(1000000)); assert_eq!( ( values.iter().map(String::as_str).collect_vec().as_slice(), common_values .iter() .map(|(s, f)| (s.as_str(), *f)) .collect_vec() .as_slice(), (median_lo.as_str(), median_hi.as_deref()) ), (expected_values, expected_common_values, expected_median) ); } #[test] fn test_random_vec_permutations() { random_vec_permutations_helper("", &[""; 20], &[("", 1000000)], ("", None)); random_vec_permutations_helper("a", &["a"; 20], &[("a", 1000000)], ("a", None)); random_vec_permutations_helper( "ab", &[ "ba", "ab", "ab", "ab", "ab", "ba", "ba", "ba", "ba", "ab", "ba", "ab", "ab", "ba", "ab", "ab", "ba", "ab", "ba", "ab", ], &[("ba", 500291), ("ab", 499709)], ("ba", None), ); random_vec_permutations_helper( "abc", &[ "bac", "cba", "cba", "cba", "cba", "acb", "acb", "bca", "acb", "bac", "abc", "bac", "bac", "acb", "cba", "abc", "bca", "cab", "acb", "bac", ], &[ ("abc", 167957), ("bac", 167073), ("cba", 166362), ("acb", 166331), ("cab", 166166), ("bca", 166111), ], ("bac", None), ); random_vec_permutations_helper( "abcd", &[ "dacb", "cbad", "cdab", "cbad", "cdab", "bcda", "bcda", "acbd", "bcda", "dbca", "bdac", "dbac", "dbca", "bcad", "cadb", "dacb", "acbd", "dbac", "bdca", "abdc", ], &[ ("dbca", 41992), ("bcda", 41855), ("cdab", 41827), ("dcab", 41818), ("abcd", 41809), ("badc", 41804), ("cadb", 41803), ("adbc", 41763), ("cbad", 41706), ("dbac", 41697), ], ("bdca", None), ); random_vec_permutations_helper( "abcdefghij", &[ "daiehfcbjg", "bhagejicdf", "fdaibchgje", "bicdfhgaej", "bdfihjagec", "chdjbafeig", "cgajbfdieh", "jecbhafgid", "aedjgchfbi", "hacjiefdgb", "ahgdfcbije", "cibdehfjag", "fgdebchjai", "gieajbdfch", "deagfjihcb", "hjfgdbacie", "jdghacbfie", "cebaihjfdg", "jgdbchfeai", "cjahbegdif", ], &[ ("afdhbciejg", 5), ("afegijbcdh", 5), ("afgcedhjbi", 5), ("agbijhcfde", 5), ("ahejcigbfd", 5), ("ahjcgfdebi", 5), ("aihecgdfbj", 5), ("ajfghdcbei", 5), ("badicjhgfe", 5), ("bfdacehijg", 5), ], ("ejicadfgbh", Some("ejicadgbfh")), ); } ================================================ FILE: malachite-base/tests/vecs/vec_delete_left.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_vec_gen, unsigned_vec_unsigned_pair_gen_var_1, }; use malachite_base::vecs::vec_delete_left; #[test] fn test_vec_delete_left() { let test = |xs: &[u32], delete_size: usize, out: &[u32]| { let mut mut_xs = xs.to_vec(); vec_delete_left(&mut mut_xs, delete_size); assert_eq!(mut_xs, out); }; test(&[], 0, &[]); test(&[1, 2, 3, 4, 5], 0, &[1, 2, 3, 4, 5]); test(&[1, 2, 3, 4, 5], 3, &[4, 5]); test(&[1, 2, 3, 4, 5], 5, &[]); } #[test] #[should_panic] fn vec_delete_left_fail_1() { let mut xs: Vec = Vec::new(); vec_delete_left(&mut xs, 1); } #[test] #[should_panic] fn vec_delete_left_fail_2() { let mut xs: Vec = vec![1, 2, 3]; vec_delete_left(&mut xs, 4); } #[test] fn vec_delete_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_unsigned_pair_gen_var_1::().test_properties_with_config( &config, |(mut xs, amount)| { let old_xs = xs.clone(); vec_delete_left(&mut xs, amount); assert_eq!(xs == old_xs, amount == 0); assert_eq!(xs.is_empty(), amount == old_xs.len()); assert_eq!(xs.len(), old_xs.len() - amount); assert_eq!(&old_xs[amount..], xs); }, ); unsigned_vec_gen::().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); vec_delete_left(&mut xs, old_xs.len()); assert!(xs.is_empty()); let mut xs = old_xs.clone(); vec_delete_left(&mut xs, 0); assert_eq!(xs, old_xs); }); } ================================================ FILE: malachite-base/tests/vecs/vec_from_str.rs ================================================ // Copyright © 2026 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 malachite_base::nevers::Never; use malachite_base::options::option_from_str; use malachite_base::orderings::ordering_from_str; use malachite_base::vecs::{vec_from_str, vec_from_str_custom}; use std::cmp::Ordering::*; use std::fmt::Debug; use std::str::FromStr; #[allow(clippy::needless_pass_by_value)] fn vec_from_str_helper(s: &str, out: Option>) { assert_eq!(vec_from_str(s), out); } #[test] fn test_vec_from_str() { vec_from_str_helper::("[]", Some(vec![])); vec_from_str_helper::("[5]", Some(vec![5])); vec_from_str_helper::("[5, 6, 7]", Some(vec![5, 6, 7])); vec_from_str_helper::("[false, false, true]", Some(vec![false, false, true])); vec_from_str_helper::("[a, b]", Some(vec!["a".to_string(), "b".to_string()])); vec_from_str_helper::("[a, b]", Some(vec!["a".to_string(), " b".to_string()])); vec_from_str_helper::("[a , b]", Some(vec!["a ".to_string(), "b".to_string()])); vec_from_str_helper::("[a,, b]", Some(vec!["a,".to_string(), "b".to_string()])); vec_from_str_helper::("[a ,,b]", Some(vec!["a ,,b".to_string()])); vec_from_str_helper::("[a,b]", Some(vec!["a,b".to_string()])); vec_from_str_helper::("[", None); vec_from_str_helper::("", None); vec_from_str_helper::("abc", None); vec_from_str_helper::("[false, false, true", None); vec_from_str_helper::("[false, false, true]", None); vec_from_str_helper::("[false, false, true,]", None); vec_from_str_helper::("[false, false, true] ", None); vec_from_str_helper::("[false, false, true ]", None); vec_from_str_helper::("[false, false, rue]", None); } #[allow(clippy::needless_pass_by_value)] fn vec_from_str_custom_helper( f: &dyn Fn(&str) -> Option, s: &str, out: Option>, ) { assert_eq!(vec_from_str_custom(f, s), out); } #[test] fn test_vec_from_str_custom() { vec_from_str_custom_helper( &ordering_from_str, "[Less, Greater]", Some(vec![Less, Greater]), ); vec_from_str_custom_helper( &option_from_str, "[Some(false), None]", Some(vec![Some(false), None]), ); vec_from_str_custom_helper( &vec_from_str, "[[], [3], [2, 5]]", Some(vec![vec![], vec![3], vec![2, 5]]), ); vec_from_str_custom_helper(&option_from_str::, "[Some(fals), None]", None); vec_from_str_custom_helper(&vec_from_str::, "[[], [3], [2, 5,]]", None); vec_from_str_custom_helper(&vec_from_str::, "[[], 3, [2, 5]]", None); vec_from_str_custom_helper(&vec_from_str::, "[[], [3], [true]]", None); } ================================================ FILE: malachite-base/tests/vecs/vec_pad_left.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_unsigned_triple_gen_var_1, }; use malachite_base::vecs::{vec_delete_left, vec_pad_left}; #[test] fn test_vec_pad_left() { let test = |xs: &[u32], pad_size: usize, pad_value: u32, out: &[u32]| { let mut mut_xs = xs.to_vec(); vec_pad_left(&mut mut_xs, pad_size, pad_value); assert_eq!(mut_xs, out); }; test(&[], 3, 6, &[6, 6, 6]); test(&[1, 2, 3], 0, 10, &[1, 2, 3]); test(&[1, 2, 3], 5, 10, &[10, 10, 10, 10, 10, 1, 2, 3]); } #[test] fn vec_pad_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); config.insert("mean_stripe_n", 16 << u8::LOG_WIDTH); config.insert("mean_stripe_d", 1); config.insert("small_unsigned_length_n", 32); config.insert("small_unsigned_length_d", 1); unsigned_vec_unsigned_unsigned_triple_gen_var_1::().test_properties_with_config( &config, |(mut xs, pad_size, pad_value)| { let old_xs = xs.clone(); vec_pad_left(&mut xs, pad_size, pad_value); assert_eq!(xs == old_xs, pad_size == 0); assert_eq!(xs.len(), old_xs.len() + pad_size); assert!(xs[..pad_size].iter().all(|&x| x == pad_value)); assert_eq!(&xs[pad_size..], old_xs); vec_delete_left(&mut xs, pad_size); assert_eq!(xs, old_xs); }, ); unsigned_vec_unsigned_pair_gen::().test_properties_with_config( &config, |(mut xs, pad_value)| { let old_xs = xs.clone(); vec_pad_left(&mut xs, 0, pad_value); assert_eq!(xs, old_xs); }, ); unsigned_pair_gen_var_2::().test_properties_with_config( &config, |(pad_value, pad_size)| { let mut xs = Vec::new(); vec_pad_left(&mut xs, pad_size, pad_value); assert_eq!(xs, vec![pad_value; pad_size]); }, ); } ================================================ FILE: malachite-bigint/Cargo.toml ================================================ [package] name = "malachite-bigint" version = "0.9.1" authors = ["Steve Shi "] rust-version.workspace = true edition.workspace = true license = "LGPL-3.0-only" description = "A drop-in num-bigint replacement based on malachite" repository = "https://github.com/mhogrefe/malachite" [dependencies] malachite-base = { version = "0.9.1", path = "../malachite-base", default-features = false } malachite-nz = { version = "0.9.1", path = "../malachite-nz", default-features = false } num-traits = { version = "0.2.19", default-features = false, features = ["i128"] } num-integer = { version = "0.1.46", default-features = false, features = ["i128"] } paste = "1.0.15" num-bigint = { version = "0.4", default-features = false, optional = true } [dev-dependencies] num-bigint = "0.4" [features] default = ["std"] std = ["malachite-base/std", "malachite-nz/std"] ================================================ FILE: malachite-bigint/README.md ================================================ # malachite-bigint A drop-in replacement for rust [num-bigint](https://github.com/rust-num/num-bigint) based on [malachite](https://github.com/mhogrefe/malachite) `Natural`. This is not an official malachite project. Please directly use malachite unless you need num-bigint compatibility. # Performance See https://github.com/tczajka/bigint-benchmark-rs # Acknowledgement `malachite-bigint` was created by [Steve Shi](https://github.com/qingshi163) to provide an alternative bigint implementation for [RustPython](https://github.com/RustPython/RustPython.git). This project is contributed to the malachite project and will be integrated to malachite 0.5.0. ================================================ FILE: malachite-bigint/src/bigint.rs ================================================ // Copyright © 2026 Steve Shi // // 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 alloc::string::String; use alloc::vec::Vec; use core::{ cmp::Ordering, fmt::Debug, iter::{Product, Sum}, ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }, str::FromStr, }; use malachite_base::{ num::{ arithmetic::traits::{ Abs, DivRem, DivRound, DivisibleBy, FloorRoot, Mod, Parity, UnsignedAbs, }, conversion::traits::{RoundingInto, ToStringBase}, logic::traits::BitAccess, }, rounding_modes::RoundingMode, }; use malachite_nz::integer::Integer; use num_integer::Roots; use num_traits::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero, }; use paste::paste; use crate::{ BigUint, ParseBigIntError, Sign::{Minus, NoSign, Plus}, ToBigUint, TryFromBigIntError, U32Digits, U64Digits, }; pub trait ToBigInt { fn to_bigint(&self) -> Option; } apply_to_primitives!(impl_primitive_convert{BigInt, _}); impl_primitive_convert!(BigInt, f32); impl_primitive_convert!(BigInt, f64); #[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] pub enum Sign { Minus, NoSign, Plus, } impl Neg for Sign { type Output = Self; #[inline] fn neg(self) -> Self::Output { match self { Minus => Plus, NoSign => NoSign, Plus => Minus, } } } #[repr(transparent)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct BigInt(Integer); apply_to_primitives!(forward_from{BigInt, _}); apply_to_primitives!(forward_try_into{BigInt, _}); impl_from!(BigInt, Integer); forward_unary_op!(BigInt, Not, not); forward_unary_op!(BigInt, Neg, neg); forward_binary_self!(BigInt, Add, add); forward_binary_self!(BigInt, Sub, sub); forward_binary_self!(BigInt, Mul, mul); forward_binary_self!(BigInt, Div, div); forward_binary_self!(BigInt, Rem, rem); forward_binary_self!(BigInt, BitAnd, bitand); forward_binary_self!(BigInt, BitOr, bitor); forward_binary_self!(BigInt, BitXor, bitxor); forward_assign_self!(BigInt, AddAssign, add_assign); forward_assign_self!(BigInt, SubAssign, sub_assign); forward_assign_self!(BigInt, MulAssign, mul_assign); forward_assign_self!(BigInt, DivAssign, div_assign); forward_assign_self!(BigInt, RemAssign, rem_assign); forward_assign_self!(BigInt, BitAndAssign, bitand_assign); forward_assign_self!(BigInt, BitOrAssign, bitor_assign); forward_assign_self!(BigInt, BitXorAssign, bitxor_assign); forward_pow_biguint!(BigInt); apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Add, add}); apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Sub, sub}); apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Mul, mul}); apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Div, div}); apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Rem, rem}); apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Add, add}); apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Sub, sub}); apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Mul, mul}); apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Div, div}); apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Rem, rem}); apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shl, shl}); apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shr, shr}); apply_to_primitives!(forward_assign_primitive_into{BigInt, _, AddAssign, add_assign}); apply_to_primitives!(forward_assign_primitive_into{BigInt, _, SubAssign, sub_assign}); apply_to_primitives!(forward_assign_primitive_into{BigInt, _, MulAssign, mul_assign}); apply_to_primitives!(forward_assign_primitive_into{BigInt, _, DivAssign, div_assign}); apply_to_primitives!(forward_assign_primitive_into{BigInt, _, RemAssign, rem_assign}); apply_to_primitives!(forward_assign_primitive{BigInt, _, ShlAssign, shl_assign}); apply_to_primitives!(forward_assign_primitive{BigInt, _, ShrAssign, shr_assign}); apply_to_unsigneds!(forward_pow_primitive{BigInt, _}); impl_product_iter_type!(BigInt); impl_sum_iter_type!(BigInt); forward_fmt!(BigInt, Debug, Display, Binary, Octal, LowerHex, UpperHex); impl CheckedAdd for BigInt { #[inline] fn checked_add(&self, v: &Self) -> Option { Some(self.add(v)) } } impl CheckedSub for BigInt { #[inline] fn checked_sub(&self, v: &Self) -> Option { Some(self.sub(v)) } } impl CheckedMul for BigInt { #[inline] fn checked_mul(&self, v: &Self) -> Option { Some(self.mul(v)) } } impl CheckedDiv for BigInt { #[inline] fn checked_div(&self, v: &Self) -> Option { (!v.is_zero()).then(|| self.div(v)) } } impl ToBigInt for BigInt { #[inline] fn to_bigint(&self) -> Option { Some(self.clone()) } } impl ToBigUint for BigInt { #[inline] fn to_biguint(&self) -> Option { (!self.is_negative()).then(|| self.magnitude().clone()) } } impl ToPrimitive for BigInt { apply_to_primitives!(impl_to_primitive_fn_try_into{_}); impl_to_primitive_fn_float!(f32); impl_to_primitive_fn_float!(f64); } impl FromPrimitive for BigInt { apply_to_primitives!(impl_from_primitive_fn_infallible{_}); impl_from_primitive_fn_float!(f32); impl_from_primitive_fn_float!(f64); } impl From for BigInt { #[inline] fn from(value: BigUint) -> Self { Integer::from(value.0).into() } } impl Zero for BigInt { #[inline] fn zero() -> Self { Self(::ZERO) } #[inline] fn is_zero(&self) -> bool { self.sign() == NoSign } } impl One for BigInt { #[inline] fn one() -> Self { Self(::ONE) } } impl Signed for BigInt { #[inline] fn abs(&self) -> Self { (&self.0).abs().into() } #[inline] fn abs_sub(&self, other: &Self) -> Self { if self <= other { Self::zero() } else { self - other } } #[inline] fn signum(&self) -> Self { match self.sign() { Minus => -Self::one(), NoSign => Self::zero(), Plus => Self::one(), } } #[inline] fn is_positive(&self) -> bool { self.sign() == Plus } #[inline] fn is_negative(&self) -> bool { self.sign() == Minus } } impl Num for BigInt { type FromStrRadixErr = ParseBigIntError; #[inline] fn from_str_radix(mut s: &str, radix: u32) -> Result { let sign = if s.starts_with('-') { let tail = &s[1..]; if !tail.starts_with('+') { s = tail; } Minus } else { Plus }; let u = BigUint::from_str_radix(s, radix)?; Ok(Self::from_biguint(sign, u)) } } impl num_integer::Integer for BigInt { #[inline] fn div_floor(&self, other: &Self) -> Self { (&self.0).div_round(&other.0, RoundingMode::Floor).0.into() } #[inline] fn mod_floor(&self, other: &Self) -> Self { (&self.0).mod_op(&other.0).into() } #[inline] fn gcd(&self, other: &Self) -> Self { self.magnitude().gcd(other.magnitude()).into() } #[inline] fn lcm(&self, other: &Self) -> Self { self.magnitude().lcm(other.magnitude()).into() } #[inline] fn divides(&self, other: &Self) -> bool { Self::is_multiple_of(self, other) } #[inline] fn is_multiple_of(&self, other: &Self) -> bool { (&self.0).divisible_by(&other.0) } #[inline] fn is_even(&self) -> bool { self.0.even() } #[inline] fn is_odd(&self) -> bool { self.0.odd() } #[inline] fn div_rem(&self, other: &Self) -> (Self, Self) { let (div, rem) = (&self.0).div_rem(&other.0); (div.into(), rem.into()) } } impl Roots for BigInt { #[inline] fn nth_root(&self, n: u32) -> Self { (&self.0).floor_root(u64::from(n)).into() } } impl FromStr for BigInt { type Err = ParseBigIntError; #[inline] fn from_str(s: &str) -> Result { Self::from_str_radix(s, 10) } } impl BigInt { #[inline] pub fn new(sign: Sign, digits: Vec) -> Self { Self::from_biguint(sign, BigUint::new(digits)) } #[inline] pub fn from_biguint(sign: Sign, mut abs: BigUint) -> Self { if sign == NoSign { abs = BigUint::zero(); } Integer::from_sign_and_abs(sign != Minus, abs.0).into() } #[inline] pub fn from_slice(sign: Sign, slice: &[u32]) -> Self { Self::from_biguint(sign, BigUint::from_slice(slice)) } #[inline] pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { if sign == NoSign { self.set_zero(); } else { *self = Self::from_slice(sign, slice); } } #[inline] pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> Self { Self::from_biguint(sign, BigUint::from_bytes_be(bytes)) } #[inline] pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> Self { Self::from_biguint(sign, BigUint::from_bytes_le(bytes)) } #[inline] pub fn from_signed_bytes_be(digits: &[u8]) -> Self { let is_negative = match digits.first().copied() { Some(x) => x > 0x7f, None => return Self::zero(), }; if is_negative { let mut v = Vec::from(digits); twos_complement_be(&mut v); let u = BigUint::from_bytes_be(v.as_slice()); Self::from_biguint(Minus, u) } else { let u = BigUint::from_bytes_be(digits); Self::from_biguint(Plus, u) } } #[inline] pub fn from_signed_bytes_le(digits: &[u8]) -> Self { let is_negative = match digits.last().copied() { Some(x) => x > 0x7f, None => return Self::zero(), }; if is_negative { let mut v = Vec::from(digits); twos_complement_le(&mut v); let u = BigUint::from_bytes_le(v.as_slice()); Self::from_biguint(Minus, u) } else { let u = BigUint::from_bytes_le(digits); Self::from_biguint(Plus, u) } } #[inline] pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option { let s = core::str::from_utf8(bytes).ok()?; Self::from_str_radix(s, radix).ok() } #[inline] pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option { BigUint::from_radix_be(buf, radix).map(|u| Self::from_biguint(sign, u)) } #[inline] pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option { BigUint::from_radix_le(buf, radix).map(|u| Self::from_biguint(sign, u)) } #[inline] pub fn to_bytes_be(&self) -> (Sign, Vec) { (self.sign(), self.magnitude().to_bytes_be()) } #[inline] pub fn to_bytes_le(&self) -> (Sign, Vec) { (self.sign(), self.magnitude().to_bytes_le()) } #[inline] pub fn to_u32_digits(&self) -> (Sign, Vec) { (self.sign(), self.magnitude().to_u32_digits()) } #[inline] pub fn to_u64_digits(&self) -> (Sign, Vec) { (self.sign(), self.magnitude().to_u64_digits()) } #[inline] pub fn iter_u32_digits(&self) -> U32Digits<'_> { self.magnitude().iter_u32_digits() } #[inline] pub fn iter_u64_digits(&self) -> U64Digits<'_> { self.magnitude().iter_u64_digits() } #[inline] pub fn to_signed_bytes_be(&self) -> Vec { let mut bytes = self.magnitude().to_bytes_be(); let first_byte = bytes.first().copied().unwrap_or(0); let is_negative = self.is_negative(); if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && is_negative) { // msb used by magnitude, extend by 1 byte bytes.insert(0, 0); } if self.is_negative() { twos_complement_be(&mut bytes); } bytes } #[inline] pub fn to_signed_bytes_le(&self) -> Vec { let mut bytes = self.magnitude().to_bytes_le(); let is_negative = self.is_negative(); let last_byte = bytes.last().copied().unwrap_or(0); if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) && is_negative) { // msb used by magnitude, extend by 1 byte bytes.push(0); } if self.is_negative() { twos_complement_le(&mut bytes); } bytes } #[inline] pub fn to_str_radix(&self, radix: u32) -> String { self.0.to_string_base(radix as u8) } #[inline] pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec) { (self.sign(), self.magnitude().to_radix_be(radix)) } #[inline] pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec) { (self.sign(), self.magnitude().to_radix_le(radix)) } #[inline] pub fn sign(&self) -> Sign { match <_ as malachite_base::num::arithmetic::traits::Sign>::sign(&self.0) { Ordering::Less => Minus, Ordering::Equal => NoSign, Ordering::Greater => Plus, } } #[inline] pub fn magnitude(&self) -> &BigUint { unsafe { core::mem::transmute(self.0.unsigned_abs_ref()) } } #[inline] pub fn into_parts(self) -> (Sign, BigUint) { (self.sign(), self.0.unsigned_abs().into()) } #[inline] pub fn bits(&self) -> u64 { self.magnitude().bits() } #[inline] pub fn to_biguint(&self) -> Option { match self.sign() { Plus => Some(self.magnitude().clone()), NoSign => Some(BigUint::zero()), Minus => None, } } #[inline] pub fn checked_add(&self, v: &Self) -> Option { Some(self + v) } #[inline] pub fn checked_sub(&self, v: &Self) -> Option { Some(self - v) } #[inline] pub fn checked_mul(&self, v: &Self) -> Option { Some(self * v) } #[inline] pub fn checked_div(&self, v: &Self) -> Option { if v.is_zero() { return None; } Some(self / v) } #[inline] pub fn pow(&self, exponent: u32) -> Self { Pow::pow(self, exponent) } #[inline] pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { assert!( !exponent.is_negative(), "negative exponentiation is not supported!" ); assert!( !modulus.is_zero(), "attempt to calculate with zero modulus!" ); let mut abs = self .magnitude() .modpow(exponent.magnitude(), modulus.magnitude()); if abs.is_zero() { return Self::zero(); } if (self.is_negative() && exponent.0.odd()) != modulus.is_negative() { abs = modulus.magnitude() - abs; } Self::from_biguint(modulus.sign(), abs) } #[inline] pub fn sqrt(&self) -> Self { Roots::sqrt(self) } #[inline] pub fn cbrt(&self) -> Self { Roots::cbrt(self) } #[inline] pub fn nth_root(&self, n: u32) -> Self { Roots::nth_root(self, n) } #[inline] pub fn trailing_zeros(&self) -> Option { self.magnitude().trailing_zeros() } #[inline] pub fn bit(&self, bit: u64) -> bool { self.0.get_bit(bit) } #[inline] pub fn set_bit(&mut self, bit: u64, value: bool) { if value { self.0.set_bit(bit); } else { self.0.clear_bit(bit); } } } /// Perform in-place two's complement of the given binary representation, in little-endian byte /// order. #[inline] fn twos_complement_le(digits: &mut [u8]) { twos_complement(digits); } /// Perform in-place two's complement of the given binary representation in big-endian byte order. #[inline] fn twos_complement_be(digits: &mut [u8]) { twos_complement(digits.iter_mut().rev()); } /// Perform in-place two's complement of the given digit iterator starting from the least /// significant byte. #[inline] fn twos_complement<'a, I>(digits: I) where I: IntoIterator, { let mut carry = true; for d in digits { *d = !*d; if carry { *d = d.wrapping_add(1); carry = d.is_zero(); } } } #[cfg(test)] mod test { use super::*; use alloc::{format, string::ToString}; #[test] fn test_float_convert_nearest() { let n25 = "10000000000000000000000000"; let val = BigInt::from_str(n25).unwrap(); let f = val.to_f64().unwrap(); assert_eq!(f.to_string(), n25); } #[test] fn test_to_f64() { use num_traits::ToPrimitive as NumToPrimitive; let test_cases = [ "123456789012345678901234567890", "999999999999999999999999999999", "170141183460469231731687303715884105727", "340282366920938463463374607431768211455", "12345678901234567890123456789012345678901234567890", "-123456789012345678901234567890", "-999999999999999999999999999999", "-170141183460469231731687303715884105728", "-12345678901234567890123456789012345678901234567890", "1208925819614629174706176", "1329227995784915872903807060280344576", "-1208925819614629174706176", "-1329227995784915872903807060280344576", // Overflow cases "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 9999999999999999999999999999999999999999999999999999", "-999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999", ]; for test_str in &test_cases { let malachite_val = BigInt::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_f64(), num_bigint_val.to_f64(), "to_f64 mismatch for {test_str}", ); } } #[test] fn test_to_f32() { use num_traits::ToPrimitive as NumToPrimitive; let test_cases = [ "12345678901234567890", "999999999999999999999999", "-12345678901234567890", "-999999999999999999999999", "340282366920938463463374607431768211455", ]; for test_str in &test_cases { let malachite_val = BigInt::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_f32(), num_bigint_val.to_f32(), "to_f32 mismatch for {test_str}", ); } } #[test] fn test_to_i64() { use num_traits::ToPrimitive as NumToPrimitive; let test_cases = [ "0", "123", "-456", "9223372036854775807", // i64::MAX "-9223372036854775808", // i64::MIN "9223372036854775808", // overflow "-9223372036854775809", // overflow ]; for test_str in &test_cases { let malachite_val = BigInt::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_i64(), num_bigint_val.to_i64(), "to_i64 mismatch for {test_str}", ); } } #[test] fn test_to_u64() { use num_traits::ToPrimitive as NumToPrimitive; let test_cases = [ "0", "123", "18446744073709551615", // u64::MAX "18446744073709551616", // overflow "-1", // negative ]; for test_str in &test_cases { let malachite_val = BigInt::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_u64(), num_bigint_val.to_u64(), "to_u64 mismatch for {test_str}", ); } } #[test] fn test_arithmetic() { let test_cases = [ ("123456789", "987654321"), ("999999999999999999", "1"), ("-123456789", "987654321"), ("123456789", "-987654321"), ("-123456789", "-987654321"), ]; for (a_str, b_str) in &test_cases { let ma = BigInt::from_str(a_str).unwrap(); let mb = BigInt::from_str(b_str).unwrap(); let na = num_bigint::BigInt::from_str(a_str).unwrap(); let nb = num_bigint::BigInt::from_str(b_str).unwrap(); assert_eq!((&ma + &mb).to_string(), (&na + &nb).to_string(), "add"); assert_eq!((&ma - &mb).to_string(), (&na - &nb).to_string(), "sub"); assert_eq!((&ma * &mb).to_string(), (&na * &nb).to_string(), "mul"); if *b_str != "0" { assert_eq!((&ma / &mb).to_string(), (&na / &nb).to_string(), "div"); assert_eq!((&ma % &mb).to_string(), (&na % &nb).to_string(), "rem"); } } } #[test] fn test_checked_arithmetic() { let test_cases = [ ("123456789", "987654321"), ("999999999999999999", "1"), ("-123456789", "987654321"), ]; for (a_str, b_str) in &test_cases { let ma = BigInt::from_str(a_str).unwrap(); let mb = BigInt::from_str(b_str).unwrap(); let na = num_bigint::BigInt::from_str(a_str).unwrap(); let nb = num_bigint::BigInt::from_str(b_str).unwrap(); assert_eq!( ma.checked_add(&mb).map(|v| v.to_string()), na.checked_add(&nb).map(|v| v.to_string()), "checked_add" ); assert_eq!( ma.checked_sub(&mb).map(|v| v.to_string()), na.checked_sub(&nb).map(|v| v.to_string()), "checked_sub" ); assert_eq!( ma.checked_mul(&mb).map(|v| v.to_string()), na.checked_mul(&nb).map(|v| v.to_string()), "checked_mul" ); assert_eq!( ma.checked_div(&mb).map(|v| v.to_string()), na.checked_div(&nb).map(|v| v.to_string()), "checked_div" ); } } #[test] fn test_sign() { use num_traits::Signed; let test_cases = [ "0", "123", "-456", "999999999999999999", "-999999999999999999", ]; for test_str in &test_cases { let ma = BigInt::from_str(test_str).unwrap(); let na = num_bigint::BigInt::from_str(test_str).unwrap(); assert_eq!( ma.is_positive(), na.is_positive(), "is_positive for {test_str}", ); assert_eq!( ma.is_negative(), na.is_negative(), "is_negative for {test_str}", ); assert_eq!( ma.abs().to_string(), na.abs().to_string(), "abs for {test_str}", ); } } #[test] fn test_pow() { use num_traits::Pow; let test_cases = [("2", 10u32), ("10", 20u32), ("-3", 5u32), ("123", 4u32)]; for (base_str, exp) in &test_cases { let ma = BigInt::from_str(base_str).unwrap(); let na = num_bigint::BigInt::from_str(base_str).unwrap(); assert_eq!( ma.pow(*exp).to_string(), na.pow(*exp).to_string(), "pow for {base_str}^{exp}", ); } } #[test] fn test_to_signed_bytes() { let sysmax = i64::MAX; let i = BigInt::from(sysmax); let b = i.to_signed_bytes_le(); let i2 = BigInt::from_signed_bytes_le(&b); assert_eq!(i, i2); } #[test] fn test_display_bigint() { let n = BigInt::from_str("1234567890").unwrap(); assert_eq!(format!("{n}"), "1234567890"); } } ================================================ FILE: malachite-bigint/src/biguint.rs ================================================ // Copyright © 2026 Steve Shi // // 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 alloc::string::String; use alloc::vec::Vec; use core::{ cmp::Ordering::{Equal, Greater, Less}, iter::{Product, Sum}, ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }, str::FromStr, }; use malachite_base::{ num::{ arithmetic::traits::{ DivRem, DivRound, DivisibleBy, FloorRoot, Gcd, Lcm, Mod, ModPow, Parity, }, conversion::traits::{Digits, FromStringBase, PowerOf2Digits, RoundingInto, ToStringBase}, logic::traits::{BitAccess, BitIterable, CountOnes, SignificantBits}, }, rounding_modes::RoundingMode, }; use malachite_nz::{integer::Integer, natural::Natural}; use num_integer::Roots; use num_traits::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, ToPrimitive, Unsigned, Zero, }; use paste::paste; use crate::{ParseBigIntError, ToBigInt, TryFromBigIntError, U32Digits, U64Digits}; pub trait ToBigUint { fn to_biguint(&self) -> Option; } apply_to_primitives!(impl_primitive_convert{BigUint, _}); impl_primitive_convert!(BigUint, f32); impl_primitive_convert!(BigUint, f64); #[repr(transparent)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct BigUint(pub(crate) Natural); apply_to_unsigneds!(forward_from{BigUint, _}); apply_to_signeds!(forward_try_from{BigUint, _}); apply_to_primitives!(forward_try_into{BigUint, _}); impl_from!(BigUint, Natural); forward_binary_self!(BigUint, Add, add); forward_binary_self!(BigUint, Sub, sub); forward_binary_self!(BigUint, Mul, mul); forward_binary_self!(BigUint, Div, div); forward_binary_self!(BigUint, Rem, rem); forward_binary_self!(BigUint, BitAnd, bitand); forward_binary_self!(BigUint, BitOr, bitor); forward_binary_self!(BigUint, BitXor, bitxor); forward_assign_self!(BigUint, AddAssign, add_assign); forward_assign_self!(BigUint, SubAssign, sub_assign); forward_assign_self!(BigUint, MulAssign, mul_assign); forward_assign_self!(BigUint, DivAssign, div_assign); forward_assign_self!(BigUint, RemAssign, rem_assign); forward_assign_self!(BigUint, BitAndAssign, bitand_assign); forward_assign_self!(BigUint, BitOrAssign, bitor_assign); forward_assign_self!(BigUint, BitXorAssign, bitxor_assign); forward_pow_biguint!(BigUint); apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Add, add}); apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Sub, sub}); apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Mul, mul}); apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Div, div}); apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Rem, rem}); apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Add, add}); apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Sub, sub}); apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Mul, mul}); apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Div, div}); apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Rem, rem}); apply_to_primitives!(forward_binary_right_primitive{BigUint, _, Shl, shl}); apply_to_primitives!(forward_binary_right_primitive{BigUint, _, Shr, shr}); apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, AddAssign, add_assign}); apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, SubAssign, sub_assign}); apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, MulAssign, mul_assign}); apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, DivAssign, div_assign}); apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, RemAssign, rem_assign}); apply_to_primitives!(forward_assign_primitive{BigUint, _, ShlAssign, shl_assign}); apply_to_primitives!(forward_assign_primitive{BigUint, _, ShrAssign, shr_assign}); apply_to_unsigneds!(forward_pow_primitive{BigUint, _}); impl_product_iter_type!(BigUint); impl_sum_iter_type!(BigUint); forward_fmt!(BigUint, Debug, Display, Binary, Octal, LowerHex, UpperHex); impl CheckedAdd for BigUint { #[inline] fn checked_add(&self, v: &Self) -> Option { Some(self.add(v)) } } impl CheckedSub for BigUint { #[inline] fn checked_sub(&self, v: &Self) -> Option { match self.cmp(v) { Less => None, Equal => Some(Self::zero()), Greater => Some(self.sub(v)), } } } impl CheckedMul for BigUint { #[inline] fn checked_mul(&self, v: &Self) -> Option { Some(self.mul(v)) } } impl CheckedDiv for BigUint { #[inline] fn checked_div(&self, v: &Self) -> Option { (!v.is_zero()).then(|| self.div(v)) } } impl ToBigUint for BigUint { #[inline] fn to_biguint(&self) -> Option { Some(self.clone()) } } impl ToBigInt for BigUint { #[inline] fn to_bigint(&self) -> Option { Some(Integer::from(&self.0).into()) } } impl ToPrimitive for BigUint { apply_to_primitives!(impl_to_primitive_fn_try_into{_}); impl_to_primitive_fn_float!(f32); impl_to_primitive_fn_float!(f64); } impl FromPrimitive for BigUint { apply_to_signeds!(impl_from_primitive_fn_try_from{_}); apply_to_unsigneds!(impl_from_primitive_fn_infallible{_}); impl_from_primitive_fn_float!(f32); impl_from_primitive_fn_float!(f64); } impl Zero for BigUint { #[inline] fn zero() -> Self { Self(::ZERO) } #[inline] fn is_zero(&self) -> bool { *self == Self::zero() } } impl One for BigUint { #[inline] fn one() -> Self { Self(::ONE) } } impl Unsigned for BigUint {} impl Num for BigUint { type FromStrRadixErr = ParseBigIntError; fn from_str_radix(s: &str, radix: u32) -> Result { let mut s = s; if s.starts_with('+') { let tail = &s[1..]; if !tail.starts_with('+') { s = tail; } } // FIXME: workaround, remove the check if malachite issue fixed // https://github.com/mhogrefe/malachite/issues/20 if radix == 16 && s.bytes().any(|x| { !matches!(x, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F' | b'_' ) }) { return Err(ParseBigIntError::invalid()); } // fast path if let Some(val) = Natural::from_string_base(radix as u8, s) { return Ok(val.into()); } if s.is_empty() { return Err(ParseBigIntError::empty()); } if s.starts_with('_') { // Must lead with a real digit! return Err(ParseBigIntError::invalid()); } let v: Vec = s.bytes().filter(|&x| x != b'_').collect(); let s = core::str::from_utf8(v.as_slice()).map_err(|_| ParseBigIntError::invalid())?; Natural::from_string_base(radix as u8, s) .map(Self) .ok_or_else(ParseBigIntError::invalid) } } impl num_integer::Integer for BigUint { #[inline] fn div_floor(&self, other: &Self) -> Self { (&self.0).div_round(&other.0, RoundingMode::Floor).0.into() } #[inline] fn mod_floor(&self, other: &Self) -> Self { (&self.0).mod_op(&other.0).into() } #[inline] fn gcd(&self, other: &Self) -> Self { (&self.0).gcd(&other.0).into() } #[inline] fn lcm(&self, other: &Self) -> Self { (&self.0).lcm(&other.0).into() } #[inline] fn divides(&self, other: &Self) -> bool { Self::is_multiple_of(self, other) } #[inline] fn is_multiple_of(&self, other: &Self) -> bool { (&self.0).divisible_by(&other.0) } #[inline] fn is_even(&self) -> bool { self.0.even() } #[inline] fn is_odd(&self) -> bool { self.0.odd() } #[inline] fn div_rem(&self, other: &Self) -> (Self, Self) { let (div, rem) = (&self.0).div_rem(&other.0); (div.into(), rem.into()) } } impl Roots for BigUint { #[inline] fn nth_root(&self, n: u32) -> Self { (&self.0).floor_root(u64::from(n)).into() } } impl FromStr for BigUint { type Err = ParseBigIntError; #[inline] fn from_str(s: &str) -> Result { Self::from_str_radix(s, 10) } } impl BigUint { // TODO consider passing &[u32] instead (breaking change) #[allow(clippy::needless_pass_by_value)] #[inline] pub fn new(digits: Vec) -> Self { Self::from_slice(digits.as_slice()) } #[inline] pub fn from_slice(slice: &[u32]) -> Self { let mut uint = Self::zero(); uint.assign_from_slice(slice); uint } #[inline] pub fn assign_from_slice(&mut self, slice: &[u32]) { // SAFETY: &[u32] cannot have any digit greater than 2^32 self.0 = unsafe { Natural::from_power_of_2_digits_asc(32, slice.iter().copied()).unwrap_unchecked() }; } #[inline] pub fn from_bytes_be(bytes: &[u8]) -> Self { // SAFETY: &[u8] cannot have any digit greater than 2^8 Self(unsafe { Natural::from_power_of_2_digits_desc(8, bytes.iter().copied()).unwrap_unchecked() }) } #[inline] pub fn from_bytes_le(bytes: &[u8]) -> Self { // SAFETY: &[u8] cannot have any digit greater than 2^8 Self(unsafe { Natural::from_power_of_2_digits_asc(8, bytes.iter().copied()).unwrap_unchecked() }) } #[inline] pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option { let s = core::str::from_utf8(bytes).ok()?; Self::from_str_radix(s, radix).ok() } #[inline] pub fn from_radix_be(bytes: &[u8], radix: u32) -> Option { if radix == 256 { Some(Self::from_bytes_be(bytes)) } else { Natural::from_digits_desc(&(radix as u8), bytes.iter().copied()).map(Self) } } #[inline] pub fn from_radix_le(bytes: &[u8], radix: u32) -> Option { if radix == 256 { Some(Self::from_bytes_le(bytes)) } else { Natural::from_digits_asc(&(radix as u8), bytes.iter().copied()).map(Self) } } #[inline] pub fn to_bytes_be(&self) -> Vec { self.0.to_power_of_2_digits_desc(8) } #[inline] pub fn to_bytes_le(&self) -> Vec { self.0.to_power_of_2_digits_asc(8) } #[inline] pub fn to_u32_digits(&self) -> Vec { self.0.to_power_of_2_digits_asc(32) } #[inline] pub fn to_u64_digits(&self) -> Vec { self.0.to_limbs_asc() } #[inline] pub fn iter_u32_digits(&self) -> U32Digits<'_> { U32Digits::new(self.0.limbs()) } #[inline] pub fn iter_u64_digits(&self) -> U64Digits<'_> { U64Digits::new(self.0.limbs()) } #[inline] pub fn to_str_radix(&self, radix: u32) -> String { self.0.to_string_base(radix as u8) } #[inline] pub fn to_radix_be(&self, radix: u32) -> Vec { debug_assert!(radix <= 256); if radix == 256 { self.to_bytes_be() } else { self.0.to_digits_desc(&(radix as u8)) } } #[inline] pub fn to_radix_le(&self, radix: u32) -> Vec { debug_assert!(radix <= 256); if radix == 256 { self.to_bytes_le() } else { self.0.to_digits_asc(&(radix as u8)) } } #[inline] pub fn bits(&self) -> u64 { self.0.significant_bits() } #[inline] pub fn pow(&self, exponent: u32) -> Self { Pow::pow(self, exponent) } #[inline] pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { if self >= modulus { let x = self % modulus; x.0.mod_pow(&exponent.0, &modulus.0).into() } else { (&self.0).mod_pow(&exponent.0, &modulus.0).into() } } #[inline] pub fn cbrt(&self) -> Self { Roots::cbrt(self) } #[inline] pub fn nth_root(&self, n: u32) -> Self { Roots::nth_root(self, n) } #[inline] pub fn trailing_zeros(&self) -> Option { self.0.trailing_zeros() } #[inline] pub fn trailing_ones(&self) -> u64 { self.0.bits().take_while(|&x| x).count() as u64 } #[inline] pub fn count_ones(&self) -> u64 { self.0.count_ones() } #[inline] pub fn bit(&self, bit: u64) -> bool { self.0.get_bit(bit) } #[inline] pub fn set_bit(&mut self, bit: u64, value: bool) { if value { self.0.set_bit(bit); } else { self.0.clear_bit(bit); } } } #[cfg(test)] mod test { use super::*; use alloc::format; #[test] fn test_from_string_base() { assert!(BigUint::from_str_radix("1000000000000000111111100112abcdefg", 16).is_err()); } #[test] fn test_display_biguint() { let x = BigUint::from_str_radix("1234567890", 10).unwrap(); assert_eq!(format!("{x}"), "1234567890"); } #[test] fn test_to_f64() { use num_traits::ToPrimitive; let test_cases = [ "123456789012345678901234567890", "999999999999999999999999999999", "340282366920938463463374607431768211455", "12345678901234567890123456789012345678901234567890", "1208925819614629174706176", "1329227995784915872903807060280344576", "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 9999999999999999999999999999999999999999999999999999", ]; for test_str in &test_cases { let malachite_val = BigUint::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_f64(), num_bigint_val.to_f64(), "to_f64 mismatch for {test_str}", ); } } #[test] fn test_to_f32() { use num_traits::ToPrimitive; let test_cases = [ "12345678901234567890", "999999999999999999999999", "340282366920938463463374607431768211455", ]; for test_str in &test_cases { let malachite_val = BigUint::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_f32(), num_bigint_val.to_f32(), "to_f32 mismatch for {test_str}", ); } } #[test] fn test_to_u64() { use num_traits::ToPrimitive; let test_cases = ["0", "123", "18446744073709551615", "18446744073709551616"]; for test_str in &test_cases { let malachite_val = BigUint::from_str(test_str).unwrap(); let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap(); assert_eq!( malachite_val.to_u64(), num_bigint_val.to_u64(), "to_u64 mismatch for {test_str}", ); } } #[test] fn test_arithmetic() { let test_cases = [ ("123456789", "987654321"), ("999999999999999999", "1"), ("1000000000000000000", "999999999999999999"), ]; for (a_str, b_str) in &test_cases { let ma = BigUint::from_str(a_str).unwrap(); let mb = BigUint::from_str(b_str).unwrap(); let na = num_bigint::BigUint::from_str(a_str).unwrap(); let nb = num_bigint::BigUint::from_str(b_str).unwrap(); assert_eq!((&ma + &mb).to_string(), (&na + &nb).to_string(), "add"); assert_eq!((&ma * &mb).to_string(), (&na * &nb).to_string(), "mul"); if ma >= mb { assert_eq!((&ma - &mb).to_string(), (&na - &nb).to_string(), "sub"); } if *b_str != "0" { assert_eq!((&ma / &mb).to_string(), (&na / &nb).to_string(), "div"); assert_eq!((&ma % &mb).to_string(), (&na % &nb).to_string(), "rem"); } } } #[test] fn test_pow() { use num_traits::Pow; let test_cases = [("2", 10u32), ("10", 20u32), ("123", 4u32)]; for (base_str, exp) in &test_cases { let ma = BigUint::from_str(base_str).unwrap(); let na = num_bigint::BigUint::from_str(base_str).unwrap(); assert_eq!( ma.pow(*exp).to_string(), na.pow(*exp).to_string(), "pow for {base_str}^{exp}", ); } } } ================================================ FILE: malachite-bigint/src/error.rs ================================================ // Copyright © 2026 Steve Shi // // 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 . #[derive(Debug, Clone, PartialEq, Eq)] pub struct ParseBigIntError { kind: BigIntErrorKind, } #[derive(Debug, Clone, PartialEq, Eq)] enum BigIntErrorKind { Empty, InvalidDigit, } impl ParseBigIntError { const fn __description(&self) -> &str { use BigIntErrorKind::*; match self.kind { Empty => "cannot parse integer from empty string", InvalidDigit => "invalid digit found in string", } } pub(crate) const fn empty() -> Self { Self { kind: BigIntErrorKind::Empty, } } pub(crate) const fn invalid() -> Self { Self { kind: BigIntErrorKind::InvalidDigit, } } } impl core::fmt::Display for ParseBigIntError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.__description().fmt(f) } } impl core::error::Error for ParseBigIntError { fn description(&self) -> &str { self.__description() } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TryFromBigIntError { original: T, } impl TryFromBigIntError { pub(crate) const fn new(original: T) -> Self { Self { original } } #[allow(clippy::unused_self)] const fn __description(&self) -> &str { "out of range conversion regarding big integer attempted" } pub fn into_original(self) -> T { self.original } } impl core::error::Error for TryFromBigIntError where T: core::fmt::Debug, { fn description(&self) -> &str { self.__description() } } impl core::fmt::Display for TryFromBigIntError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.__description().fmt(f) } } ================================================ FILE: malachite-bigint/src/iter.rs ================================================ // Copyright © 2026 Steve Shi // // 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 core::iter::FusedIterator; use malachite_nz::natural::conversion::to_limbs::LimbIterator; pub struct U32Digits<'a> { iter: LimbIterator<'a>, next_hi: Option, last_hi_is_zero: bool, len: usize, } impl<'a> U32Digits<'a> { #[inline] pub(crate) fn new(iter: LimbIterator<'a>) -> Self { let iter_len = iter.len(); let last_hi_is_zero = iter_len != 0 && (iter[iter_len - 1] >> 32) == 0; let len = iter_len * 2 - usize::from(last_hi_is_zero); Self { iter, next_hi: None, last_hi_is_zero, len, } } } impl Iterator for U32Digits<'_> { type Item = u32; #[inline] fn next(&mut self) -> Option { if self.len == 0 { return None; } self.len -= 1; self.next_hi.take().or_else(|| { let limb = self.iter.next()?; let hi = (limb >> 32) as u32; let lo = limb as u32; self.next_hi = Some(hi); Some(lo) }) } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn count(self) -> usize { self.len() } #[inline] fn last(self) -> Option { self.iter.most_significant().map(|limb| { if self.last_hi_is_zero { limb as u32 } else { (limb >> 32) as u32 } }) } } impl ExactSizeIterator for U32Digits<'_> { #[inline] fn len(&self) -> usize { self.len } } // TODO: DoubleEndedIterator impl FusedIterator for U32Digits<'_> {} pub struct U64Digits<'a> { iter: LimbIterator<'a>, } impl<'a> U64Digits<'a> { #[inline] pub(crate) const fn new(iter: LimbIterator<'a>) -> Self { Self { iter } } } impl Iterator for U64Digits<'_> { type Item = u64; #[inline] fn next(&mut self) -> Option { self.iter.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } #[inline] fn nth(&mut self, n: usize) -> Option { self.iter.nth(n) } #[inline] fn last(self) -> Option { self.iter.most_significant() } #[inline] fn count(self) -> usize { self.iter.count() } } impl DoubleEndedIterator for U64Digits<'_> { fn next_back(&mut self) -> Option { self.iter.next_back() } } impl ExactSizeIterator for U64Digits<'_> { #[inline] fn len(&self) -> usize { self.iter.len() } } impl FusedIterator for U64Digits<'_> {} #[test] fn test_iter_u32_digits() { let n = super::BigUint::from(5u8); let mut it = n.iter_u32_digits(); assert_eq!(it.len(), 1); assert_eq!(it.next(), Some(5)); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); let n = super::BigUint::from(112500000000u64); let mut it = n.iter_u32_digits(); assert_eq!(it.len(), 2); assert_eq!(it.next(), Some(830850304)); assert_eq!(it.len(), 1); assert_eq!(it.next(), Some(26)); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); } #[test] fn test_iter_u64_digits() { let n = super::BigUint::from(5u8); let mut it = n.iter_u64_digits(); assert_eq!(it.len(), 1); assert_eq!(it.next(), Some(5)); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); let n = super::BigUint::from(18_446_744_073_709_551_616u128); let mut it = n.iter_u64_digits(); assert_eq!(it.len(), 2); assert_eq!(it.next(), Some(0)); assert_eq!(it.len(), 1); assert_eq!(it.next(), Some(1)); assert_eq!(it.len(), 0); assert_eq!(it.next(), None); } ================================================ FILE: malachite-bigint/src/lib.rs ================================================ // Copyright © 2026 Steve Shi // // 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 . #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] extern crate alloc; #[macro_use] mod macros; mod bigint; mod biguint; mod error; mod iter; #[cfg(feature = "num-bigint")] mod num_bigint_conversion; pub use bigint::{BigInt, Sign, ToBigInt}; pub use biguint::{BigUint, ToBigUint}; pub use error::{ParseBigIntError, TryFromBigIntError}; pub use iter::{U32Digits, U64Digits}; ================================================ FILE: malachite-bigint/src/macros.rs ================================================ // Copyright © 2026 Steve Shi // // 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 . macro_rules! apply_to_unsigneds { ($m:tt{_$(,$args:ident)*}) => { $m!(u8 $(,$args)*); $m!(u16 $(,$args)*); $m!(u32 $(,$args)*); $m!(u64 $(,$args)*); $m!(usize $(,$args)*); $m!(u128 $(,$args)*); }; ($m:tt{$arg0:tt,_$(,$args:tt)*}) => { $m!($arg0, u8 $(,$args)*); $m!($arg0, u16 $(,$args)*); $m!($arg0, u32 $(,$args)*); $m!($arg0, u64 $(,$args)*); $m!($arg0, usize $(,$args)*); $m!($arg0, u128 $(,$args)*); } } macro_rules! apply_to_signeds { ($m:tt{_$(,$args:ident)*}) => { $m!(i8 $(,$args)*); $m!(i16 $(,$args)*); $m!(i32 $(,$args)*); $m!(i64 $(,$args)*); $m!(isize $(,$args)*); $m!(i128 $(,$args)*); }; ($m:tt{$arg0:tt,_$(,$args:tt)*}) => { $m!($arg0, i8 $(,$args)*); $m!($arg0, i16 $(,$args)*); $m!($arg0, i32 $(,$args)*); $m!($arg0, i64 $(,$args)*); $m!($arg0, isize $(,$args)*); $m!($arg0, i128 $(,$args)*); } } macro_rules! apply_to_primitives { ($m:tt{_$(,$args:ident)*}) => { apply_to_signeds!($m{_$(,$args)*}); apply_to_unsigneds!($m{_$(,$args)*}); }; ($m:tt{$arg0:tt,_$(,$args:tt)*}) => { apply_to_signeds!($m{$arg0, _$(,$args)*}); apply_to_unsigneds!($m{$arg0, _$(,$args)*}); }; } macro_rules! forward_from { ($lhs:ty, $rhs:ty) => { impl From<$rhs> for $lhs { #[inline] fn from(value: $rhs) -> Self { Self(<_ as From<_>>::from(value)) } } }; } macro_rules! forward_try_from { ($lhs:ty, $rhs:ty) => { impl TryFrom<$rhs> for $lhs { type Error = TryFromBigIntError<()>; #[inline] fn try_from(value: $rhs) -> Result { <_ as TryFrom<_>>::try_from(value) .map_err(|_| Self::Error::new(())) .map(Self) } } }; } macro_rules! forward_try_into { ($res:ty, $t:ty) => { impl TryFrom<$res> for $t { type Error = TryFromBigIntError<$res>; #[inline] fn try_from(value: $res) -> Result { <$t>::try_from(&value.0).map_err(|_| Self::Error::new(value)) } } impl TryFrom<&$res> for $t { type Error = TryFromBigIntError<()>; #[inline] fn try_from(value: &$res) -> Result { <$t>::try_from(&value.0).map_err(|_| Self::Error::new(())) } } }; } macro_rules! forward_unary_op { ($struct:tt, $trait:tt, $fn:ident) => { impl $trait for $struct { type Output = $struct; #[inline] fn $fn(mut self) -> Self::Output { self.0 = $trait::$fn(self.0); self } } impl $trait for &$struct { type Output = $struct; #[inline] fn $fn(self) -> Self::Output { $struct($trait::$fn(&self.0)) } } }; } macro_rules! impl_binary_op { ($lhs:ty, $rhs:ty, $output:ty, $trait:tt, $fn:ident, $expr:expr) => { impl $trait<$rhs> for $lhs { type Output = $output; #[inline] fn $fn(self, rhs: $rhs) -> Self::Output { $expr(self, rhs) } } }; } macro_rules! impl_assign_op { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident, $expr:expr) => { impl $trait<$rhs> for $lhs { #[inline] fn $fn(&mut self, rhs: $rhs) { $expr(self, rhs) } } }; } macro_rules! forward_binary_self { ($struct:ty, $trait:tt, $fn:ident) => { impl_binary_op!( $struct, $struct, $struct, $trait, $fn, |lhs: $struct, rhs: $struct| { $trait::$fn(lhs.0, rhs.0).into() } ); impl_binary_op!( &$struct, $struct, $struct, $trait, $fn, |lhs: &$struct, rhs: $struct| { $trait::$fn(&lhs.0, rhs.0).into() } ); impl_binary_op!( $struct, &$struct, $struct, $trait, $fn, |lhs: $struct, rhs: &$struct| { $trait::$fn(lhs.0, &rhs.0).into() } ); impl_binary_op!( &$struct, &$struct, $struct, $trait, $fn, |lhs: &$struct, rhs: &$struct| { $trait::$fn(&lhs.0, &rhs.0).into() } ); }; } macro_rules! forward_binary_right_primitive { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident) => { impl_binary_op!($lhs, $rhs, $lhs, $trait, $fn, |lhs: $lhs, rhs: $rhs| { $trait::$fn(lhs.0, rhs).into() }); impl_binary_op!(&$lhs, $rhs, $lhs, $trait, $fn, |lhs: &$lhs, rhs: $rhs| { $trait::$fn(&lhs.0, rhs).into() }); impl_binary_op!($lhs, &$rhs, $lhs, $trait, $fn, |lhs: $lhs, rhs: &$rhs| { $trait::$fn(lhs.0, *rhs).into() }); impl_binary_op!(&$lhs, &$rhs, $lhs, $trait, $fn, |lhs: &$lhs, rhs: &$rhs| { $trait::$fn(&lhs.0, *rhs).into() }); }; } macro_rules! forward_binary_right_primitive_into { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident) => { impl_binary_op!($lhs, $rhs, $lhs, $trait, $fn, |lhs: $lhs, rhs: $rhs| { $trait::$fn(lhs.0, <$lhs>::from(rhs).0).into() }); impl_binary_op!(&$lhs, $rhs, $lhs, $trait, $fn, |lhs: &$lhs, rhs: $rhs| { $trait::$fn(&lhs.0, <$lhs>::from(rhs).0).into() }); impl_binary_op!($lhs, &$rhs, $lhs, $trait, $fn, |lhs: $lhs, rhs: &$rhs| { $trait::$fn(lhs.0, <$lhs>::from(*rhs).0).into() }); impl_binary_op!(&$lhs, &$rhs, $lhs, $trait, $fn, |lhs: &$lhs, rhs: &$rhs| { $trait::$fn(&lhs.0, <$lhs>::from(*rhs).0).into() }); }; } macro_rules! forward_binary_left_primitive_into { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident) => { impl_binary_op!($lhs, $rhs, $rhs, $trait, $fn, |lhs: $lhs, rhs: $rhs| { $trait::$fn(<$rhs>::from(lhs).0, rhs.0).into() }); impl_binary_op!(&$lhs, $rhs, $rhs, $trait, $fn, |lhs: &$lhs, rhs: $rhs| { $trait::$fn(<$rhs>::from(*lhs).0, rhs.0).into() }); impl_binary_op!($lhs, &$rhs, $rhs, $trait, $fn, |lhs: $lhs, rhs: &$rhs| { $trait::$fn(<$rhs>::from(lhs).0, &rhs.0).into() }); impl_binary_op!(&$lhs, &$rhs, $rhs, $trait, $fn, |lhs: &$lhs, rhs: &$rhs| { $trait::$fn(<$rhs>::from(*lhs).0, &rhs.0).into() }); }; } macro_rules! forward_assign_self { ($struct:ty, $trait:tt, $fn:ident) => { impl_assign_op!( $struct, $struct, $trait, $fn, |lhs: &mut $struct, rhs: $struct| { $trait::$fn(&mut lhs.0, rhs.0).into() } ); impl_assign_op!( $struct, &$struct, $trait, $fn, |lhs: &mut $struct, rhs: &$struct| { $trait::$fn(&mut lhs.0, &rhs.0).into() } ); }; } macro_rules! forward_assign_primitive { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident) => { impl_assign_op!($lhs, $rhs, $trait, $fn, |lhs: &mut $lhs, rhs: $rhs| { $trait::$fn(&mut lhs.0, rhs).into() }); impl_assign_op!($lhs, &$rhs, $trait, $fn, |lhs: &mut $lhs, rhs: &$rhs| { $trait::$fn(&mut lhs.0, *rhs).into() }); }; } macro_rules! forward_assign_primitive_into { ($lhs:ty, $rhs:ty, $trait:tt, $fn:ident) => { impl_assign_op!($lhs, $rhs, $trait, $fn, |lhs: &mut $lhs, rhs: $rhs| { $trait::$fn(&mut lhs.0, <$lhs>::from(rhs).0).into() }); impl_assign_op!($lhs, &$rhs, $trait, $fn, |lhs: &mut $lhs, rhs: &$rhs| { $trait::$fn(&mut lhs.0, <$lhs>::from(*rhs).0).into() }); }; } macro_rules! forward_pow_primitive { ($lhs:ty, $rhs:ty) => { impl_binary_op!($lhs, $rhs, $lhs, Pow, pow, |lhs: $lhs, rhs: $rhs| { #[allow(clippy::cast_lossless)] <_ as malachite_base::num::arithmetic::traits::Pow>::pow(lhs.0, rhs as _).into() }); impl_binary_op!(&$lhs, $rhs, $lhs, Pow, pow, |lhs: &$lhs, rhs: $rhs| { #[allow(clippy::cast_lossless)] <_ as malachite_base::num::arithmetic::traits::Pow>::pow(&lhs.0, rhs as _).into() }); impl_binary_op!($lhs, &$rhs, $lhs, Pow, pow, |lhs: $lhs, rhs: &$rhs| { #[allow(clippy::cast_lossless)] <_ as malachite_base::num::arithmetic::traits::Pow>::pow(lhs.0, *rhs as _).into() }); impl_binary_op!(&$lhs, &$rhs, $lhs, Pow, pow, |lhs: &$lhs, rhs: &$rhs| { #[allow(clippy::cast_lossless)] <_ as malachite_base::num::arithmetic::traits::Pow>::pow(&lhs.0, *rhs as _).into() }); }; } macro_rules! forward_pow_biguint { ($lhs:ty) => { impl_binary_op!($lhs, BigUint, $lhs, Pow, pow, |lhs: $lhs, rhs: BigUint| { let exp = malachite_base::num::conversion::traits::SaturatingFrom::saturating_from(&rhs.0); <_ as malachite_base::num::arithmetic::traits::Pow>::pow(lhs.0, exp).into() }); impl_binary_op!( &$lhs, BigUint, $lhs, Pow, pow, |lhs: &$lhs, rhs: BigUint| { let exp = malachite_base::num::conversion::traits::SaturatingFrom::saturating_from( &rhs.0, ); <_ as malachite_base::num::arithmetic::traits::Pow>::pow(&lhs.0, exp).into() } ); impl_binary_op!( $lhs, &BigUint, $lhs, Pow, pow, |lhs: $lhs, rhs: &BigUint| { let exp = malachite_base::num::conversion::traits::SaturatingFrom::saturating_from( &rhs.0, ); <_ as malachite_base::num::arithmetic::traits::Pow>::pow(lhs.0, exp).into() } ); impl_binary_op!( &$lhs, &BigUint, $lhs, Pow, pow, |lhs: &$lhs, rhs: &BigUint| { let exp = malachite_base::num::conversion::traits::SaturatingFrom::saturating_from( &rhs.0, ); <_ as malachite_base::num::arithmetic::traits::Pow>::pow(&lhs.0, exp).into() } ); }; } macro_rules! impl_sum_iter_type { ($res:ty) => { impl Sum for $res where $res: Add, { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Zero::zero(), <$res>::add) } } }; } macro_rules! impl_product_iter_type { ($res:ty) => { impl Product for $res where $res: Mul, { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(One::one(), <$res>::mul) } } }; } macro_rules! impl_from_primitive_fn_infallible { ($t:ty) => { paste! { #[inline] fn [](n: $t) -> Option { Some(Self::from(n)) } } }; } macro_rules! impl_from_primitive_fn_try_from { ($t:ty) => { paste! { #[inline] fn [](n: $t) -> Option { Self::try_from(n).ok() } } }; } macro_rules! impl_from_primitive_fn_float { ($t:ty) => { paste! { #[inline] fn [](n: $t) -> Option { if !n.is_finite() { return None; } Some(Self(n.rounding_into(RoundingMode::Down).0)) } } }; } macro_rules! impl_primitive_convert { ($res:ty, $t:ty) => { paste! { impl [] for $t { #[inline] fn [](&self) -> Option<$res> { $res::[](*self) } } } }; } macro_rules! impl_to_primitive_fn_try_into { ($t:ty) => { paste! { #[inline] fn [](&self)-> Option<$t> { self.try_into().ok() } } }; } macro_rules! impl_to_primitive_fn_float { ($t:ty) => { paste! { #[inline] fn [](&self) -> Option<$t> { match (&self.0).rounding_into(RoundingMode::Nearest) { // returned value is $t::MAX but still less than the original (val, core::cmp::Ordering::Less) if val == $t::MAX => None, // returned value is $t::MIN but still greater than the original (val, core::cmp::Ordering::Greater) if val == $t::MIN => None, (val, _) => Some(val), } } } }; } macro_rules! forward_fmt { ($t:ty, $($trait:ident),*) => { $(impl core::fmt::$trait for $t { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { core::fmt::$trait::fmt(&self.0, f) } })* } } macro_rules! impl_from { ($wrapper:ty, $inner: ty) => { impl From<$inner> for $wrapper { fn from(value: $inner) -> Self { Self(value) } } impl From<$wrapper> for $inner { #[inline] fn from(value: $wrapper) -> Self { value.0 } } impl<'a> From<&'a $wrapper> for &'a $inner { #[inline] fn from(value: &'a $wrapper) -> Self { &value.0 } } impl<'a> From<&'a mut $wrapper> for &'a mut $inner { #[inline] fn from(value: &'a mut $wrapper) -> Self { &mut value.0 } } }; } ================================================ FILE: malachite-bigint/src/num_bigint_conversion.rs ================================================ // Copyright © 2026 Steve Shi // // 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 crate::{ BigInt, BigUint, Sign::{self, Minus, NoSign, Plus}, }; use malachite_nz::natural::Natural; use num_traits::ToPrimitive; impl From for BigUint { #[inline] fn from(value: num_bigint::BigUint) -> Self { if let Some(x) = value.to_u64() { Self::from(x) } else { let limbs = value.to_u64_digits(); Self(Natural::from_owned_limbs_asc(limbs)) } } } impl From for num_bigint::BigUint { #[inline] fn from(value: BigUint) -> Self { if let Some(x) = value.to_u64() { Self::from(x) } else { let digits = value.to_u32_digits(); Self::new(digits) } } } impl From for Sign { #[inline] fn from(value: num_bigint::Sign) -> Self { match value { num_bigint::Sign::Minus => Minus, num_bigint::Sign::NoSign => NoSign, num_bigint::Sign::Plus => Plus, } } } impl From for num_bigint::Sign { #[inline] fn from(value: Sign) -> Self { match value { Minus => num_bigint::Sign::Minus, NoSign => num_bigint::Sign::NoSign, Plus => num_bigint::Sign::Plus, } } } impl From for BigInt { #[inline] fn from(value: num_bigint::BigInt) -> Self { let (sign, abs) = value.into_parts(); Self::from_biguint(sign.into(), abs.into()) } } impl From for num_bigint::BigInt { #[inline] fn from(value: BigInt) -> Self { let (sign, abs) = value.into_parts(); Self::from_biguint(sign.into(), abs.into()) } } #[test] fn num_bigint_conversion_test() { let tester = |val: BigInt| { let numval = num_bigint::BigInt::from(val.clone()); let val2 = BigInt::from(numval); assert_eq!(val, val2); }; tester(50723.into()); tester(BigInt::from(-52321)); tester(0.into()); tester(BigInt::from(core::u64::MAX).pow(1000u32)); tester(BigInt::from(core::i64::MIN).pow(1000u32)); } ================================================ FILE: malachite-criterion-bench/Cargo.toml ================================================ [package] name = "malachite-criterion-bench" version = "0.8.1" authors = ["Mikhail Hogrefe "] autobenches = false rust-version.workspace = true edition.workspace = true [dependencies] malachite-base = { version = "0.9.1", path = "../malachite-base" } malachite-nz = { version = "0.9.1", default-features = false, path = "../malachite-nz" } num = "0.4.3" rug = { version = "1.28.1", default-features = false, features = ["integer", "serde"] } [dev-dependencies] criterion = "0.3" [[bench]] name = "natural_mul" harness = false ================================================ FILE: malachite-criterion-bench/benches/bin.rs ================================================ // Copyright © 2026 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 . criterion_group!{ name = benches; config = Criterion::default().significance_level(0.1).sample_size(10); targets = bench_mul } ================================================ FILE: malachite-criterion-bench/benches/natural_div.rs ================================================ // Copyright © 2026 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 . extern crate criterion; extern crate malachite_base; extern crate malachite_nz; extern crate num; extern crate rug; use criterion::*; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_nz::natural::random::get_random_natural_with_bits; use malachite_nz::natural::Natural; use num::BigUint; use std::str::FromStr; pub fn BigUint::from(n: &Natural) -> BigUint { BigUint::from_str(n.to_string().as_ref()).unwrap() } pub fn rug::Integer::from(n: &Natural) -> rug::Integer { rug::Integer::from_str(n.to_string().as_ref()).unwrap() } fn bench_div(c: &mut Criterion) { let mut group = c.benchmark_group("Natural / Natural"); let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); group.plot_config(plot_config); for &i in [1u64, 10, 100, 1000, 10000, 100000, 1000000, 10000000].iter() { let x = get_random_natural_with_bits( &mut random_primitive_ints(EXAMPLE_SEED.fork("a")), i << 1, ); let y = get_random_natural_with_bits(&mut random_primitive_ints(EXAMPLE_SEED.fork("b")), i); let x_num = BigUint::from(&x); let y_num = BigUint::from(&y); let x_rug = rug::Integer::from(&x); let y_rug = rug::Integer::from(&y); group.bench_function(BenchmarkId::new("malachite", i), |b| { b.iter_with_setup(|| (x.clone(), y.clone()), |(x, y)| x / y) }); group.bench_function(BenchmarkId::new("num", i), |b| { b.iter_with_setup(|| (x_num.clone(), y_num.clone()), |(x, y)| x / y) }); group.bench_function(BenchmarkId::new("rug", i), |b| { b.iter_with_setup(|| (x_rug.clone(), y_rug.clone()), |(x, y)| x / y) }); } group.finish(); } ================================================ FILE: malachite-criterion-bench/benches/natural_mul.rs ================================================ // Copyright © 2026 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 . extern crate criterion; extern crate malachite_base; extern crate malachite_nz; extern crate num; extern crate rug; use criterion::*; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_nz::natural::Natural; use malachite_nz::natural::random::get_random_natural_with_bits; use num::BigUint; use std::str::FromStr; pub fn natural_to_biguint(n: &Natural) -> BigUint { BigUint::from_str(n.to_string().as_ref()).unwrap() } pub fn natural_to_rug_integer(n: &Natural) -> rug::Integer { rug::Integer::from_str(n.to_string().as_ref()).unwrap() } fn bench_mul(c: &mut Criterion) { let mut group = c.benchmark_group("Natural * Natural"); let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); group.plot_config(plot_config); let sizes = [ 1u64, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, ]; for &i in sizes.iter() { let x = get_random_natural_with_bits(&mut random_primitive_ints(EXAMPLE_SEED.fork("a")), i); let y = get_random_natural_with_bits(&mut random_primitive_ints(EXAMPLE_SEED.fork("b")), i); let x_num = natural_to_biguint(&x); let y_num = natural_to_biguint(&y); let x_rug = natural_to_rug_integer(&x); let y_rug = natural_to_rug_integer(&y); group.bench_function(BenchmarkId::new("malachite", i), |b| { b.iter_with_setup(|| (x.clone(), y.clone()), |(x, y)| x * y) }); group.bench_function(BenchmarkId::new("num", i), |b| { b.iter_with_setup(|| (x_num.clone(), y_num.clone()), |(x, y)| x * y) }); group.bench_function(BenchmarkId::new("rug", i), |b| { b.iter_with_setup(|| (x_rug.clone(), y_rug.clone()), |(x, y)| x * y) }); } group.finish(); } criterion_group! { name = benches; config = Criterion::default().significance_level(0.1).sample_size(10); targets = bench_mul } criterion_main!(benches); ================================================ FILE: malachite-float/Cargo.toml ================================================ [package] name = "malachite-float" version = "0.9.1" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true description = "The arbitrary-precision floating-point type Float, with efficient algorithms partially derived from MPFR." readme = "README.md" homepage = "https://malachite.rs/" repository = "https://github.com/mhogrefe/malachite" license = "LGPL-3.0-only" keywords = ["mathematics", "math", "numerics", "bignum"] categories = ["mathematics"] [lib] name = "malachite_float" path = "src/lib.rs" [[bin]] name = "malachite_float_main" path = "src/bin.rs" [dependencies] itertools = { version = "0.14.0", default-features = false, features = ["use_alloc"] } malachite-base = { version = "0.9.1", default-features = false, path = "../malachite-base" } malachite-nz = { version = "0.9.1", default-features = false, features = ["float_helpers"], path = "../malachite-nz" } malachite-q = { version = "0.9.1", default-features = false, path = "../malachite-q" } serde = { version = "1.0.188", optional = true, default-features = false, features = ["alloc", "derive"] } serde_json = { version = "1.0.149", optional = true } num = { version = "0.4.3", optional = true, features = ["serde"] } rug = { version = "1.28.1", default-features = false, optional = true, features = ["float", "serde"] } [dev-dependencies] malachite-float = { path = ".", features = ["test_build"] } [features] default = ["std"] std = ["malachite-base/std", "malachite-nz/std", "malachite-q/std"] enable_serde = ["serde", "malachite-nz/enable_serde", "malachite-q/enable_serde"] random = ["malachite-base/random", "malachite-nz/random", "malachite-q/random"] 32_bit_limbs = ["malachite-nz/32_bit_limbs", "malachite-q/32_bit_limbs"] test_build = ["malachite-base/test_build", "malachite-nz/test_build", "malachite-q/test_build", "random", "serde", "serde_json", "num", "rug"] bin_build = ["test_build"] [package.metadata.docs.rs] features = ["random"] rustdoc-args = [ "--html-in-header", "katex-header.html" ] ================================================ FILE: malachite-float/README.md ================================================ - [crates.io](https://crates.io/crates/malachite-float) - [docs.rs](https://docs.rs/malachite-float/latest/malachite_float/) Rather than using this crate directly, use the [`malachite`](https://crates.io/crates/malachite) meta-crate. It re-exports all of this crate's public members. In `malachite-float`'s doctests you will frequently see import paths beginning with `malachite_float::`. When using the `malachite` crate, replace this part of the paths with `malachite::`. The import path of the `Float` type is shortened to `malachite::Float`. # malachite-float This crate defines [`Float`](https://docs.rs/malachite-float/latest/malachite_float/struct.Float.html)s. TODO Malachite is developed by Mikhail Hogrefe. Thanks to b4D8, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, shekohex, and skycloudd for additional contributions. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: malachite-float/katex-header.html ================================================ ================================================ FILE: malachite-float/rustfmt.toml ================================================ max_width = 100 array_width = 100 ================================================ FILE: malachite-float/src/arithmetic/abs.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ Float, float_either_infinity, float_either_zero, float_infinity, float_nan, float_negative_zero, float_zero, }; use malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; impl Float { /// If `self` is negative zero, returns positive zero; otherwise, returns `self`, taking `self` /// by value. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!( /// ComparableFloat(Float::NAN.abs_negative_zero()), /// ComparableFloat(Float::NAN) /// ); /// assert_eq!(Float::INFINITY.abs_negative_zero(), Float::INFINITY); /// assert_eq!( /// Float::NEGATIVE_INFINITY.abs_negative_zero(), /// Float::NEGATIVE_INFINITY /// ); /// assert_eq!( /// ComparableFloat(Float::ZERO.abs_negative_zero()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!( /// ComparableFloat(Float::NEGATIVE_ZERO.abs_negative_zero()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!(Float::ONE.abs_negative_zero(), Float::ONE); /// assert_eq!(Float::NEGATIVE_ONE.abs_negative_zero(), Float::NEGATIVE_ONE); /// ``` #[inline] pub const fn abs_negative_zero(mut self) -> Self { self.abs_negative_zero_assign(); self } /// If `self` is negative zero, returns positive zero; otherwise, returns `self`, taking `self` /// by reference. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!( /// ComparableFloat(Float::NAN.abs_negative_zero_ref()), /// ComparableFloat(Float::NAN) /// ); /// assert_eq!(Float::INFINITY.abs_negative_zero_ref(), Float::INFINITY); /// assert_eq!( /// Float::NEGATIVE_INFINITY.abs_negative_zero_ref(), /// Float::NEGATIVE_INFINITY /// ); /// assert_eq!( /// ComparableFloat(Float::ZERO.abs_negative_zero_ref()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!( /// ComparableFloat(Float::NEGATIVE_ZERO.abs_negative_zero_ref()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!(Float::ONE.abs_negative_zero_ref(), Float::ONE); /// assert_eq!( /// Float::NEGATIVE_ONE.abs_negative_zero_ref(), /// Float::NEGATIVE_ONE /// ); /// ``` pub fn abs_negative_zero_ref(&self) -> Self { match self { float_negative_zero!() => float_zero!(), x => x.clone(), } } /// If `self` is negative zero, replaces it with positive zero; otherwise, does nothing. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// let mut x = Float::NAN; /// x.abs_negative_zero_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN)); /// /// let mut x = Float::INFINITY; /// x.abs_negative_zero_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.abs_negative_zero_assign(); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::ZERO; /// x.abs_negative_zero_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO)); /// /// let mut x = Float::NEGATIVE_ZERO; /// x.abs_negative_zero_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO)); /// /// let mut x = Float::ONE; /// x.abs_negative_zero_assign(); /// assert_eq!(x, Float::ONE); /// /// let mut x = Float::NEGATIVE_ONE; /// x.abs_negative_zero_assign(); /// assert_eq!(x, Float::NEGATIVE_ONE); /// ``` pub const fn abs_negative_zero_assign(&mut self) { if let Self(Zero { sign }) = self { *sign = true; } } } impl Abs for Float { type Output = Self; /// Takes the absolute value of a [`Float`], taking the [`Float`] by value. /// /// $$ /// f(x) = |x|. /// $$ /// /// Special cases: /// - $f(\text{NaN}) = \text{NaN}$ /// - $f(\infty) = f(-\infty) = \infty$ /// - $f(0.0) = f(-0.0) = 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!( /// ComparableFloat(Float::NAN.abs()), /// ComparableFloat(Float::NAN) /// ); /// assert_eq!(Float::INFINITY.abs(), Float::INFINITY); /// assert_eq!(Float::NEGATIVE_INFINITY.abs(), Float::INFINITY); /// assert_eq!( /// ComparableFloat(Float::ZERO.abs()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!( /// ComparableFloat(Float::NEGATIVE_ZERO.abs()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!(Float::ONE.abs(), Float::ONE); /// assert_eq!(Float::NEGATIVE_ONE.abs(), Float::ONE); /// ``` #[inline] fn abs(mut self) -> Self { self.abs_assign(); self } } impl Abs for &Float { type Output = Float; /// Takes the absolute value of a [`Float`], taking the [`Float`] by reference. /// /// $$ /// f(x) = |x|. /// $$ /// /// Special cases: /// - $f(\text{NaN}) = \text{NaN}$ /// - $f(\infty) = f(-\infty) = \infty$ /// - $f(0.0) = f(-0.0) = 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!( /// ComparableFloat((&Float::NAN).abs()), /// ComparableFloat(Float::NAN) /// ); /// assert_eq!((&Float::INFINITY).abs(), Float::INFINITY); /// assert_eq!((&Float::NEGATIVE_INFINITY).abs(), Float::INFINITY); /// assert_eq!( /// ComparableFloat((&Float::ZERO).abs()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!( /// ComparableFloat((&Float::NEGATIVE_ZERO).abs()), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!((&Float::ONE).abs(), Float::ONE); /// assert_eq!((&Float::NEGATIVE_ONE).abs(), Float::ONE); /// ``` fn abs(self) -> Float { match self { float_nan!() => float_nan!(), float_either_infinity!() => float_infinity!(), float_either_zero!() => float_zero!(), Float(Finite { exponent, precision, significand, .. }) => Float(Finite { sign: true, exponent: *exponent, precision: *precision, significand: significand.clone(), }), } } } impl AbsAssign for Float { /// Replaces a [`Float`] with its absolute value. /// /// $$ /// x \gets |x|. /// $$ /// /// Special cases: /// - $\text{NaN} \gets \text{NaN}$ /// - $\infty \gets \infty$ /// - $-\infty \gets \infty$ /// - $0.0 \gets 0.0$ /// - $-0.0 \gets 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsAssign; /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// let mut x = Float::NAN; /// x.abs_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN)); /// /// let mut x = Float::INFINITY; /// x.abs_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.abs_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::ZERO; /// x.abs_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO)); /// /// let mut x = Float::NEGATIVE_ZERO; /// x.abs_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO)); /// /// let mut x = Float::ONE; /// x.abs_assign(); /// assert_eq!(x, Float::ONE); /// /// let mut x = Float::NEGATIVE_ONE; /// x.abs_assign(); /// assert_eq!(x, Float::ONE); /// ``` fn abs_assign(&mut self) { if let Self(Infinity { sign } | Zero { sign } | Finite { sign, .. }) = self { *sign = true; } } } ================================================ FILE: malachite-float/src/arithmetic/add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 2001, 2003-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ Float, float_either_zero, float_infinity, float_nan, float_negative_infinity, float_negative_zero, float_zero, }; use core::cmp::Ordering::{self, *}; use core::cmp::max; use core::mem::swap; use core::ops::{Add, AddAssign}; use malachite_base::num::arithmetic::traits::{CeilingLogBase2, IsPowerOf2, NegAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::{ExactFrom, SaturatingFrom}; use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_add::{ add_float_significands_in_place, add_float_significands_in_place_ref, add_float_significands_ref_ref, }; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::natural::arithmetic::float_sub::{ sub_float_significands_in_place, sub_float_significands_in_place_ref, sub_float_significands_ref_ref, }; use malachite_nz::platform::Limb; use malachite_q::Rational; // x and y must be finite, nonzero, and not sum to zero fn float_rational_sum_exponent_range(x: &Float, y: &Rational) -> (i64, i64) { let log_x_abs = i64::from(x.get_exponent().unwrap() - 1); let log_y_abs = y.floor_log_base_2_abs(); let m = max(log_x_abs, log_y_abs); if (*x > 0) == (*y > 0) { (m, m + 1) } else if log_x_abs.abs_diff(log_y_abs) > 1 { (m - 1, m) } else { let mut log_x_denominator = i64::exact_from(x.get_prec().unwrap()) .saturating_sub(log_x_abs) .saturating_sub(1); if log_x_denominator < 0 { log_x_denominator = 0; } let log_y_denominator = i64::exact_from(y.denominator_ref().ceiling_log_base_2()); let min_exp = log_x_denominator .checked_neg() .unwrap() .checked_sub(log_y_denominator) .unwrap(); if log_x_abs == log_y_abs { (min_exp, m - 1) } else { (min_exp, m) } } } // x and y must be finite, nonzero, and not sum to zero fn float_rational_sum_sign(x: &Float, y: &Rational) -> bool { match ((*x > 0), (*y > 0)) { (true, true) => true, (false, false) => false, _ => { if x.gt_abs(y) { *x > 0 } else { *y > 0 } } } } fn add_rational_prec_round_naive_ref_val( x: &Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x.clone(), Equal), (float_negative_zero!(), y) => { if y == 0u32 { (float_negative_zero!(), Equal) } else { Float::from_rational_prec_round(y, prec, rm) } } (float_zero!(), y) => Float::from_rational_prec_round(y, prec, rm), (x, y) => { let (mut sum, o) = Float::from_rational_prec_round(Rational::exact_from(x) + y, prec, rm); if rm == Floor && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } fn add_rational_prec_round_naive_ref_ref( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x.clone(), Equal), (float_negative_zero!(), y) => { if *y == 0u32 { (float_negative_zero!(), Equal) } else { Float::from_rational_prec_round_ref(y, prec, rm) } } (float_zero!(), y) => Float::from_rational_prec_round_ref(y, prec, rm), (x, y) => { let (mut sum, o) = Float::from_rational_prec_round(Rational::exact_from(x) + y, prec, rm); if rm == Floor && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } impl Float { pub(crate) fn add_prec_round_assign_helper( &mut self, other: Self, prec: u64, rm: RoundingMode, subtract: bool, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other, subtract) { (float_nan!(), _, _) | (_, float_nan!(), _) | (float_infinity!(), float_negative_infinity!(), false) | (float_negative_infinity!(), float_infinity!(), false) | (float_infinity!(), float_infinity!(), true) | (float_negative_infinity!(), float_negative_infinity!(), true) => { *self = float_nan!(); Equal } (float_infinity!(), _, _) | (_, float_infinity!(), false) | (_, float_negative_infinity!(), true) => { *self = float_infinity!(); Equal } (float_negative_infinity!(), _, _) | (_, float_negative_infinity!(), false) | (_, float_infinity!(), true) => { *self = float_negative_infinity!(); Equal } (float_zero!(), float_negative_zero!(), false) | (float_negative_zero!(), float_zero!(), false) | (float_zero!(), float_zero!(), true) | (float_negative_zero!(), float_negative_zero!(), true) => { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; Equal } (float_either_zero!(), mut z, subtract) => { if subtract { z.neg_assign(); } let o = z.set_prec_round(prec, rm); *self = z; o } (z, float_either_zero!(), _) => z.set_prec_round(prec, rm), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: mut y_sign, exponent: y_exp, precision: y_prec, significand: mut y, }), subtract, ) => { if subtract { y_sign.not_assign(); } let (o, swapped) = if *x_sign == y_sign { let (o, swapped) = add_float_significands_in_place( x, x_exp, *x_prec, &mut y, y_exp, y_prec, prec, if *x_sign { rm } else { -rm }, ); if *x_exp > Self::MAX_EXPONENT { return match (*x_sign, rm) { (_, Exact) => panic!("Inexact float addition"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } (o, swapped) } else { let (o, swapped, neg) = sub_float_significands_in_place( x, x_exp, *x_prec, &mut y, y_exp, y_prec, prec, if *x_sign { rm } else { -rm }, ); if *x_exp < Self::MIN_EXPONENT { let sign = *x_sign != neg; return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !(if swapped { y.is_power_of_2() } else { x.is_power_of_2() })) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } if *x_exp > Self::MAX_EXPONENT { return match (*x_sign != neg, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } _ => panic!("Invalid state"), }; } if *x == 0u32 { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return o; } if neg { x_sign.not_assign(); } (o, swapped) }; if swapped { swap(x, &mut y); } *x_prec = prec; if *x_sign { o } else { o.reverse() } } } } pub(crate) fn add_prec_round_assign_ref_helper( &mut self, other: &Self, prec: u64, rm: RoundingMode, subtract: bool, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other, subtract) { (x @ float_nan!(), _, _) | (x, float_nan!(), _) | (x @ float_infinity!(), float_negative_infinity!(), false) | (x @ float_negative_infinity!(), float_infinity!(), false) | (x @ float_infinity!(), float_infinity!(), true) | (x @ float_negative_infinity!(), float_negative_infinity!(), true) => { *x = float_nan!(); Equal } (x @ float_infinity!(), _, _) | (x, float_infinity!(), false) | (x, float_negative_infinity!(), true) => { *x = float_infinity!(); Equal } (x @ float_negative_infinity!(), _, _) | (x, float_negative_infinity!(), false) | (x, float_infinity!(), true) => { *x = float_negative_infinity!(); Equal } (x @ float_zero!(), float_negative_zero!(), false) | (x @ float_negative_zero!(), float_zero!(), false) | (x @ float_zero!(), float_zero!(), true) | (x @ float_negative_zero!(), float_negative_zero!(), true) => { *x = if rm == Floor { float_negative_zero!() } else { float_zero!() }; Equal } (x @ float_either_zero!(), z, subtract) => { let (new_x, mut o) = Self::from_float_prec_round_ref(z, prec, if subtract { -rm } else { rm }); *x = new_x; if subtract { x.neg_assign(); o = o.reverse(); } o } (z, float_either_zero!(), _) => z.set_prec_round(prec, rm), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), subtract, ) => { let mut y_sign = *y_sign; if subtract { y_sign.not_assign(); } let o = if *x_sign == y_sign { let o = add_float_significands_in_place_ref( x, x_exp, *x_prec, y, *y_exp, *y_prec, prec, if *x_sign { rm } else { -rm }, ); if *x_exp > Self::MAX_EXPONENT { return match (x_sign, rm) { (_, Exact) => panic!("Inexact float addition"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } o } else { let (o, neg) = sub_float_significands_in_place_ref( x, x_exp, *x_prec, y, *y_exp, *y_prec, prec, if *x_sign { rm } else { -rm }, ); if *x_exp < Self::MIN_EXPONENT { let sign = *x_sign != neg; return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } if *x_exp > Self::MAX_EXPONENT { return match (*x_sign != neg, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } _ => panic!("Invalid state"), }; } if *x == 0u32 { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return o; } if neg { x_sign.not_assign(); } o }; *x_prec = prec; if *x_sign { o } else { o.reverse() } } } } pub(crate) fn add_prec_round_ref_ref_helper( &self, other: &Self, prec: u64, rm: RoundingMode, subtract: bool, ) -> (Self, Ordering) { assert_ne!(prec, 0); match (self, other, subtract) { (float_nan!(), _, _) | (_, float_nan!(), _) | (float_infinity!(), float_negative_infinity!(), false) | (float_negative_infinity!(), float_infinity!(), false) | (float_infinity!(), float_infinity!(), true) | (float_negative_infinity!(), float_negative_infinity!(), true) => { (float_nan!(), Equal) } (float_infinity!(), _, _) | (_, float_infinity!(), false) | (_, float_negative_infinity!(), true) => (float_infinity!(), Equal), (float_negative_infinity!(), _, _) | (_, float_negative_infinity!(), false) | (_, float_infinity!(), true) => (float_negative_infinity!(), Equal), (float_zero!(), float_negative_zero!(), false) | (float_negative_zero!(), float_zero!(), false) | (float_zero!(), float_zero!(), true) | (float_negative_zero!(), float_negative_zero!(), true) => ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ), (float_either_zero!(), z, subtract) => { let (mut x, mut o) = Self::from_float_prec_round_ref(z, prec, if subtract { -rm } else { rm }); if subtract { x.neg_assign(); o = o.reverse(); } (x, o) } (z, float_either_zero!(), _) => Self::from_float_prec_round_ref(z, prec, rm), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), subtract, ) => { let mut y_sign = *y_sign; if subtract { y_sign.not_assign(); } if *x_sign == y_sign { let (sum, sum_exp, o) = add_float_significands_ref_ref( x, *x_exp, *x_prec, y, *y_exp, *y_prec, prec, if *x_sign { rm } else { -rm }, ); if sum_exp > Self::MAX_EXPONENT { return match (*x_sign, rm) { (_, Exact) => panic!("Inexact float addition"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } let sum = Self(Finite { sign: *x_sign, exponent: sum_exp, precision: prec, significand: sum, }); (sum, if *x_sign { o } else { o.reverse() }) } else { let (diff, diff_exp, o, neg) = sub_float_significands_ref_ref( x, *x_exp, *x_prec, y, *y_exp, *y_prec, prec, if *x_sign { rm } else { -rm }, ); if diff_exp < Self::MIN_EXPONENT { let sign = *x_sign != neg; return if rm == Nearest && diff_exp == Self::MIN_EXPONENT - 1 && (o == Less || !diff.is_power_of_2()) { if sign { (Self::min_positive_value_prec(prec), Greater) } else { (-Self::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up) => { (Self::min_positive_value_prec(prec), Greater) } (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), } }; } if diff_exp > Self::MAX_EXPONENT { return match (*x_sign != neg, rm) { (_, Exact) => panic!("Inexact float subtraction"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), _ => panic!("Invalid state"), }; } if diff == 0u32 { ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, o, ) } else { let diff = Self(Finite { sign: *x_sign != neg, exponent: diff_exp, precision: prec, significand: diff, }); (diff, if *x_sign == neg { o.reverse() } else { o }) } } } } } /// Adds two [`Float`]s, rounding the result to the specified precision and with the specified /// rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,-\infty,p,m)=f(-\infty,\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p,m)=0.0$ /// - $f(-0.0,-0.0,p,m)=-0.0$ /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,-x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.add_prec_round_assign(other, prec, rm); (self, o) } /// Adds two [`Float`]s, rounding the result to the specified precision and with the specified /// rounding mode. The first [`Float`] is taken by value and the second by reference. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,-\infty,p,m)=f(-\infty,\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p,m)=0.0$ /// - $f(-0.0,-0.0,p,m)=-0.0$ /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,-x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.add_prec_round_assign_ref(other, prec, rm); (self, o) } /// Adds two [`Float`]s, rounding the result to the specified precision and with the specified /// rounding mode. The first [`Float`] is taken by reference and the second by value. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,-\infty,p,m)=f(-\infty,\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p,m)=0.0$ /// - $f(-0.0,-0.0,p,m)=-0.0$ /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,-x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = other.add_prec_round_assign_ref(self, prec, rm); (other, o) } /// Adds two [`Float`]s, rounding the result to the specified precision and with the specified /// rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,-\infty,p,m)=f(-\infty,\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p,m)=0.0$ /// - $f(-0.0,-0.0,p,m)=-0.0$ /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,p,m)=f(-0.0,0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,-x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { self.add_prec_round_ref_ref_helper(other, prec, rm, false) } /// Adds two [`Float`]s, rounding the result to the nearest value of the specified precision. /// Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded sum is less than, equal to, or greater than the exact sum. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,-\infty,p)=f(-\infty,\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p)=0.0$ /// - $f(-0.0,-0.0,p)=-0.0$ /// - $f(0.0,-0.0,p)=f(-0.0,0.0,p)=0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_prec_round(other, prec, Nearest) } /// Adds two [`Float`]s, rounding the result to the nearest value of the specified precision. /// The first [`Float`] is taken by value and the second by reference. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,-\infty,p)=f(-\infty,\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p)=0.0$ /// - $f(-0.0,-0.0,p)=-0.0$ /// - $f(0.0,-0.0,p)=f(-0.0,0.0,p)=0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_prec_round_val_ref(other, prec, Nearest) } /// Adds two [`Float`]s, rounding the result to the nearest value of the specified precision. /// The first [`Float`] is taken by reference and the second by value. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,-\infty,p)=f(-\infty,\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p)=0.0$ /// - $f(-0.0,-0.0,p)=-0.0$ /// - $f(0.0,-0.0,p)=f(-0.0,0.0,p)=0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_prec_round_ref_val(other, prec, Nearest) } /// Adds two [`Float`]s, rounding the result to the nearest value of the specified precision. /// Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether /// the rounded sum is less than, equal to, or greater than the exact sum. Although `NaN`s are /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,-\infty,p)=f(-\infty,\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,p)=0.0$ /// - $f(-0.0,-0.0,p)=-0.0$ /// - $f(0.0,-0.0,p)=f(-0.0,0.0,p)=0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_prec_round_ref_ref(other, prec, Nearest) } /// Adds two [`Float`]s, rounding the result with the specified rounding mode. Both [`Float`]s /// are taken by value. An [`Ordering`] is also returned, indicating whether the rounded sum is /// less than, equal to, or greater than the exact sum. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,-\infty,m)=f(-\infty,\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,m)=0.0$ /// - $f(-0.0,-0.0,m)=-0.0$ /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(0.0,x,m)=f(x,0.0,m)=f(-0.0,x,m)=f(x,-0.0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round(other, prec, rm) } /// Adds two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by value and the second by reference. An [`Ordering`] is also returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,-\infty,m)=f(-\infty,\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,m)=0.0$ /// - $f(-0.0,-0.0,m)=-0.0$ /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(0.0,x,m)=f(x,0.0,m)=f(-0.0,x,m)=f(x,-0.0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_val_ref(other, prec, rm) } /// Adds two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by reference and the second by value. An [`Ordering`] is also returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,-\infty,m)=f(-\infty,\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,m)=0.0$ /// - $f(-0.0,-0.0,m)=-0.0$ /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(0.0,x,m)=f(x,0.0,m)=f(-0.0,x,m)=f(x,-0.0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_ref_val(other, prec, rm) } /// Adds two [`Float`]s, rounding the result with the specified rounding mode. Both [`Float`]s /// are taken by reference. An [`Ordering`] is also returned, indicating whether the rounded sum /// is less than, equal to, or greater than the exact sum. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,-\infty,m)=f(-\infty,\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0,m)=0.0$ /// - $f(-0.0,-0.0,m)=-0.0$ /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,-0.0,m)=f(-0.0,0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(0.0,x,m)=f(x,0.0,m)=f(-0.0,x,m)=f(x,-0.0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_ref_ref(other, prec, rm) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] on the right-hand side is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::add_prec_assign`] instead. If /// you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::add_round_assign`] instead. If both of these things are true, /// consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact addition. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign(Float::from(E), 5, Floor), Less); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign(Float::from(E), 5, Ceiling), Greater); /// assert_eq!(x.to_string(), "6.0"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign(Float::from(E), 5, Nearest), Less); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign(Float::from(E), 20, Floor), Less); /// assert_eq!(x.to_string(), "5.85987"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign(Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "5.85988"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign(Float::from(E), 20, Nearest), Less); /// assert_eq!(x.to_string(), "5.85987"); /// ``` #[inline] pub fn add_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering { self.add_prec_round_assign_helper(other, prec, rm, false) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] on the right-hand side is taken by /// reference. An [`Ordering`] is returned, indicating whether the rounded sum is less than, /// equal to, or greater than the exact sum. Although `NaN`s are not comparable to any /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::add_prec_assign_ref`] /// instead. If you know that your target precision is the maximum of the precisions of the two /// inputs, consider using [`Float::add_round_assign_ref`] instead. If both of these things are /// true, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact addition. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_round_assign_ref(&Float::from(E), 5, Floor), Less); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign_ref(&Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "6.0"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign_ref(&Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign_ref(&Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "5.85987"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign_ref(&Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "5.85988"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_prec_round_assign_ref(&Float::from(E), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "5.85987"); /// ``` #[inline] pub fn add_prec_round_assign_ref( &mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> Ordering { self.add_prec_round_assign_ref_helper(other, prec, rm, false) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] /// is returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_prec_round_assign`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_assign(Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_assign(Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "5.85987"); /// ``` #[inline] pub fn add_prec_assign(&mut self, other: Self, prec: u64) -> Ordering { self.add_prec_round_assign(other, prec, Nearest) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Float`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_prec_round_assign_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_assign_ref(&Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "5.8"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_prec_assign_ref(&Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "5.85987"); /// ``` #[inline] pub fn add_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { self.add_prec_round_assign_ref(other, prec, Nearest) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::add_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::add_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `+=` /// instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign(Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign(Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "5.859874482048839"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign(Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// ``` #[inline] pub fn add_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_assign(other, prec, rm) } /// Adds a [`Float`] to a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::add_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using /// [`Float::add_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign_ref(&Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign_ref(&Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "5.859874482048839"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.add_round_assign_ref(&Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// ``` #[inline] pub fn add_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_assign_ref(other, prec, rm) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,-x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.add_rational_prec_round_assign(other, prec, rm); (self, o) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by /// reference. An [`Ordering`] is also returned, indicating whether the rounded sum is less /// than, equal to, or greater than the exact sum. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,-x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.add_rational_prec_round_assign_ref(other, prec, rm); (self, o) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`] by /// value. An [`Ordering`] is also returned, indicating whether the rounded sum is less than, /// equal to, or greater than the exact sum. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,-x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) => (float_nan!(), Equal), (float_infinity!(), _) => (float_infinity!(), Equal), (float_negative_infinity!(), _) => (float_negative_infinity!(), Equal), (float_negative_zero!(), y) => { if y == 0u32 { (float_negative_zero!(), Equal) } else { Self::from_rational_prec_round(y, prec, rm) } } (float_zero!(), y) => Self::from_rational_prec_round(y, prec, rm), (_, y) if y == 0 => Self::from_float_prec_round_ref(self, prec, rm), (x, y) => { if (*x > 0) != (y > 0) && x.eq_abs(&y) { return ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ); } let (min_exponent, max_exponent) = float_rational_sum_exponent_range(x, &y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float addition"); return match (float_rational_sum_sign(x, &y), rm) { (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. return add_rational_prec_round_naive_ref_val(x, y, prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(&y, working_prec); if o == Equal { // Result is exact so we can add it directly! return self.add_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.add_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { let o = t.set_prec_round(prec, rm); return (t, o); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Adds a [`Float`] and a [`Rational`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by reference. /// An [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, /// or greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,-x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) => (float_nan!(), Equal), (float_infinity!(), _) => (float_infinity!(), Equal), (float_negative_infinity!(), _) => (float_negative_infinity!(), Equal), (float_negative_zero!(), y) => { if *y == 0u32 { (float_negative_zero!(), Equal) } else { Self::from_rational_prec_round_ref(y, prec, rm) } } (float_zero!(), y) => Self::from_rational_prec_round_ref(y, prec, rm), (_, y) if *y == 0 => Self::from_float_prec_round_ref(self, prec, rm), (x, y) => { if (*x > 0) != (*y > 0) && x.eq_abs(y) { return ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ); } let (min_exponent, max_exponent) = float_rational_sum_exponent_range(x, y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float addition"); return match (float_rational_sum_sign(x, y), rm) { (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. return add_rational_prec_round_naive_ref_ref(x, y, prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(y, working_prec); if o == Equal { // Result is exact so we can add it directly! return self.add_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.add_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { let o = t.set_prec_round(prec, rm); return (t, o); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Adds a [`Float`] and a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_rational_prec_round(other, prec, Nearest) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_rational_prec_round_val_ref(other, prec, Nearest) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_rational_prec_round_ref_val(other, prec, Nearest) } /// Adds a [`Float`] and a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,-x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.add_rational_prec_round_ref_ref(other, prec, Nearest) } /// Adds a [`Float`] and a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(0.0,x,m)=f(x,0,m)=f(-0.0,x,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.add_rational_prec_round(other, prec, rm) } /// Adds a [`Float`] and a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(0.0,x,m)=f(x,0,m)=f(-0.0,x,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.add_rational_prec_round_val_ref(other, prec, rm) } /// Adds a [`Float`] and a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by reference and the [`Float`] by value. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(0.0,x,m)=f(x,0,m)=f(-0.0,x,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.add_rational_prec_round_ref_val(other, prec, rm) } /// Adds a [`Float`] and a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(0.0,x,m)=f(x,0,m)=f(-0.0,x,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,-x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.add_rational_prec_round_ref_ref(other, prec, rm) } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result to the specified precision /// and with the specified rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is /// returned, indicating whether the rounded sum is less than, equal to, or greater than the /// exact sum. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::add_rational_prec_assign`] /// instead. If you know that your target precision is the precision of the [`Float`] input, /// consider using [`Float::add_rational_round_assign`] instead. If both of these things are /// true, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact addition. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.4"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "3.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.474922"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474926"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474926"); /// ``` /// /// This is mpfr_add_q from gmp_op.c, MPFR 4.2.0. #[inline] pub fn add_rational_prec_round_assign( &mut self, other: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (Self(NaN | Infinity { .. }), _) => Equal, (float_negative_zero!(), y) => { if y == 0u32 { Equal } else { let o; (*self, o) = Self::from_rational_prec_round(y, prec, rm); o } } (float_zero!(), y) => { let o; (*self, o) = Self::from_rational_prec_round(y, prec, rm); o } (_, y) if y == 0 => self.set_prec_round(prec, rm), (x, y) => { if (*x > 0) != (y > 0) && x.eq_abs(&y) { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return Equal; } let (min_exponent, max_exponent) = float_rational_sum_exponent_range(x, &y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float addition"); return match (float_rational_sum_sign(x, &y), rm) { (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. let (sum, o) = add_rational_prec_round_naive_ref_val(&*x, y, prec, rm); *self = sum; return o; } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(&y, working_prec); if o == Equal { // Result is exact so we can add it directly! return self.add_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let t = x.add_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { *self = t; return self.set_prec_round(prec, rm); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result to the specified precision /// and with the specified rounding mode. The [`Rational`] is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded sum is less than, equal to, or /// greater than the exact sum. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using /// [`Float::add_rational_prec_assign_ref`] instead. If you know that your target precision is /// the precision of the [`Float`] input, consider using /// [`Float::add_rational_round_assign_ref`] instead. If both of these things are true, consider /// using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact addition. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.4"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "3.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.474922"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474926"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474926"); /// ``` #[inline] pub fn add_rational_prec_round_assign_ref( &mut self, other: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (Self(NaN | Infinity { .. }), _) => Equal, (float_negative_zero!(), y) => { if *y == 0u32 { Equal } else { let o; (*self, o) = Self::from_rational_prec_round_ref(y, prec, rm); o } } (float_zero!(), y) => { let o; (*self, o) = Self::from_rational_prec_round_ref(y, prec, rm); o } (_, y) if *y == 0 => self.set_prec_round(prec, rm), (x, y) => { if (*x > 0) != (*y > 0) && x.eq_abs(y) { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return Equal; } let (min_exponent, max_exponent) = float_rational_sum_exponent_range(x, y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float addition"); return match (float_rational_sum_sign(x, y), rm) { (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. let (sum, o) = add_rational_prec_round_naive_ref_ref(&*x, y, prec, rm); *self = sum; return o; } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(y, working_prec); if o == Equal { // Result is exact so we can add it directly! return self.add_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let t = x.add_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { *self = t; return self.set_prec_round(prec, rm); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_assign(Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "4.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_assign(Rational::exact_from(1.5), 20), /// Greater /// ); /// assert_eq!(x.to_string(), "4.641594"); /// ``` #[inline] pub fn add_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering { self.add_rational_prec_round_assign(other, prec, Nearest) } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is returned, /// indicating whether the rounded sum is less than, equal to, or greater than the exact sum. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// If the sum is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::add_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_rational_prec_round_assign_ref`] instead. If you know that your target /// precision is the maximum of the precisions of the two inputs, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_assign_ref(&Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "4.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_prec_assign_ref(&Rational::exact_from(1.5), 20), /// Greater /// ); /// assert_eq!(x.to_string(), "4.641594"); /// ``` #[inline] pub fn add_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering { self.add_rational_prec_round_assign_ref(other, prec, Nearest) } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating whether /// the rounded sum is less than, equal to, or greater than the exact sum. Although `NaN`s are /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::add_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::add_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.474925986923125"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474925986923129"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "3.474925986923125"); /// ``` #[inline] pub fn add_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.add_rational_prec_round_assign(other, prec, rm) } /// Adds a [`Rational`] to a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned, indicating /// whether the rounded sum is less than, equal to, or greater than the exact sum. Although /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to /// `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x+y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x+y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x+y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::add_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::add_rational_prec_round_assign_ref`] instead. If you know you'll be using the /// `Nearest` rounding mode, consider using `+=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "3.474925986923125"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "3.474925986923129"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.add_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "3.474925986923125"); /// ``` #[inline] pub fn add_rational_round_assign_ref( &mut self, other: &Rational, rm: RoundingMode, ) -> Ordering { let prec = self.significant_bits(); self.add_rational_prec_round_assign_ref(other, prec, rm) } } impl Add for Float { type Output = Self; /// Adds two [`Float`]s, taking both by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,-\infty)=f(-\infty,\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0)=0.0$ /// - $f(-0.0,-0.0)=-0.0$ /// - $f(0.0,-0.0)=f(-0.0,0.0)=0.0$ /// - $f(0.0,x)=f(x,0.0)=f(-0.0,x)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round(other, prec, Nearest).0 } } impl Add<&Self> for Float { type Output = Self; /// Adds two [`Float`]s, taking the first by value and the second by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,-\infty)=f(-\infty,\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0)=0.0$ /// - $f(-0.0,-0.0)=-0.0$ /// - $f(0.0,-0.0)=f(-0.0,0.0)=0.0$ /// - $f(0.0,x)=f(x,0.0)=f(-0.0,x)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_val_ref(other, prec, Nearest).0 } } impl Add for &Float { type Output = Float; /// Adds two [`Float`]s, taking the first by reference and the second by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,-\infty)=f(-\infty,\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0)=0.0$ /// - $f(-0.0,-0.0)=-0.0$ /// - $f(0.0,-0.0)=f(-0.0,0.0)=0.0$ /// - $f(0.0,x)=f(x,0.0)=f(-0.0,x)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_ref_val(other, prec, Nearest).0 } } impl Add<&Float> for &Float { type Output = Float; /// Adds two [`Float`]s, taking both by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,-\infty)=f(-\infty,\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0.0)=0.0$ /// - $f(-0.0,-0.0)=-0.0$ /// - $f(0.0,-0.0)=f(-0.0,0.0)=0.0$ /// - $f(0.0,x)=f(x,0.0)=f(-0.0,x)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,-x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_ref_ref(other, prec, Nearest).0 } } impl AddAssign for Float { /// Adds a [`Float`] to a [`Float`] in place, taking the [`Float`] on the right-hand side by /// value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `+` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::add_round_assign`]. If you want both of these things, consider using /// [`Float::add_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x += Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x += Float::INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x += Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x += Float::NEGATIVE_INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x += Float::from(2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(1.5); /// x += Float::from(-2.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(-1.5); /// x += Float::from(2.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(-1.5); /// x += Float::from(-2.5); /// assert_eq!(x, -4.0); /// ``` #[inline] fn add_assign(&mut self, other: Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_assign(other, prec, Nearest); } } impl AddAssign<&Self> for Float { /// Adds a [`Float`] to a [`Float`] in place, taking the [`Float`] on the right-hand side by /// reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the sum /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `+` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_prec_assign_ref`] instead. If you want to specify the output precision, /// consider using [`Float::add_round_assign_ref`]. If you want both of these things, consider /// using [`Float::add_prec_round_assign_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x += &Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x += &Float::INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x += &Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x += &Float::NEGATIVE_INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x += &Float::from(2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(1.5); /// x += &Float::from(-2.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(-1.5); /// x += &Float::from(2.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(-1.5); /// x += &Float::from(-2.5); /// assert_eq!(x, -4.0); /// ``` #[inline] fn add_assign(&mut self, other: &Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.add_prec_round_assign_ref(other, prec, Nearest); } } impl Add for Float { type Output = Self; /// Adds a [`Float`] and a [`Rational`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(0.0,x)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.add_rational_prec_round(other, prec, Nearest).0 } } impl Add<&Rational> for Float { type Output = Self; /// Adds a [`Float`] and a [`Rational`], taking the [`Float`] by value and the [`Rational`] by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(0.0,x)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.add_rational_prec_round_val_ref(other, prec, Nearest).0 } } impl Add for &Float { type Output = Float; /// Adds a [`Float`] and a [`Rational`], taking the [`Float`] by reference and the [`Rational`] /// by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(0.0,x)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.add_rational_prec_round_ref_val(other, prec, Nearest).0 } } impl Add<&Rational> for &Float { type Output = Float; /// Adds a [`Float`] and a [`Rational`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(0.0,x)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.add_rational_prec_round_ref_ref(other, prec, Nearest).0 } } impl AddAssign for Float { /// Adds a [`Rational`] to a [`Float`] in place, taking the [`Rational`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `+` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_rational_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::add_rational_round_assign`]. If you want both of these things, /// consider using [`Float::add_rational_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x += Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x += Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x += Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(2.5); /// x += Rational::exact_from(1.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(2.5); /// x += Rational::exact_from(-1.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(-2.5); /// x += Rational::exact_from(1.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(-2.5); /// x += Rational::exact_from(-1.5); /// assert_eq!(x, -4.0); /// ``` #[inline] fn add_assign(&mut self, other: Rational) { let prec = self.significant_bits(); self.add_rational_prec_round_assign(other, prec, Nearest); } } impl AddAssign<&Rational> for Float { /// Adds a [`Rational`] to a [`Float`] in place, taking the [`Rational`] by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `+` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::add_rational_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::add_rational_round_assign`]. If you want both of these things, /// consider using [`Float::add_rational_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x += &Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x += &Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x += &Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(2.5); /// x += &Rational::exact_from(1.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(2.5); /// x += &Rational::exact_from(-1.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(-2.5); /// x += &Rational::exact_from(1.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(-2.5); /// x += &Rational::exact_from(-1.5); /// assert_eq!(x, -4.0); /// ``` #[inline] fn add_assign(&mut self, other: &Rational) { let prec = self.significant_bits(); self.add_rational_prec_round_assign_ref(other, prec, Nearest); } } impl Add for Rational { type Output = Float; /// Adds a [`Rational`] and a [`Float`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=\infty$ /// - $f(x,-\infty)=-\infty$ /// - $f(0,0.0)=0.0$ /// - $f(0,-0.0)=-0.0$ /// - $f(x,0.0)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.add_rational_prec_round(self, prec, Nearest).0 } } impl Add<&Float> for Rational { type Output = Float; /// Adds a [`Rational`] and a [`Float`], taking the [`Rational`] by value and the [`Float`] by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=\infty$ /// - $f(x,-\infty)=-\infty$ /// - $f(0,0.0)=0.0$ /// - $f(0,-0.0)=-0.0$ /// - $f(x,0.0)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.add_rational_prec_round_ref_val(self, prec, Nearest).0 } } impl Add for &Rational { type Output = Float; /// Adds a [`Rational`] and a [`Float`], taking the [`Rational`] by reference and the [`Float`] /// by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=\infty$ /// - $f(x,-\infty)=-\infty$ /// - $f(0,0.0)=0.0$ /// - $f(0,-0.0)=-0.0$ /// - $f(x,0.0)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.add_rational_prec_round_val_ref(self, prec, Nearest).0 } } impl Add<&Float> for &Rational { type Output = Float; /// Adds a [`Rational`] and a [`Float`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the sum is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x+y+\varepsilon. /// $$ /// - If $x+y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x+y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x+y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=\infty$ /// - $f(x,-\infty)=-\infty$ /// - $f(0,0.0)=0.0$ /// - $f(0,-0.0)=-0.0$ /// - $f(x,0.0)=f(x,0)=f(-0.0,x)=x$ /// - $f(x,-x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.add_rational_prec_round_ref_ref(self, prec, Nearest).0 } } ================================================ FILE: malachite-float/src/arithmetic/agm.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::basic::extended::{ExtendedFloat, agm_prec_round_normal_extended}; use crate::{ Float, emulate_float_float_to_float_fn, emulate_rational_rational_to_float_fn, float_either_infinity, float_either_zero, float_infinity, float_nan, float_zero, test_overflow, test_underflow, }; use alloc::borrow::Cow; use core::cmp::Ordering::{self, *}; use core::cmp::max; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ Agm, AgmAssign, CeilingLogBase2, ShrRoundAssign, Sign, Sqrt, SqrtAssign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero as ZeroTrait; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::natural::arithmetic::float_sub::exponent_shift_compare; use malachite_nz::platform::Limb; use malachite_q::Rational; // This is mpfr_cmp2 from cmp2.c, MPFR 4.3.0. fn cmp2_helper(b: &Float, c: &Float, cancel: &mut u64) -> Ordering { match (b, c) { ( Float(Finite { exponent: x_exp, precision: x_prec, significand: x, .. }), Float(Finite { exponent: y_exp, precision: y_prec, significand: y, .. }), ) => { let (o, c) = exponent_shift_compare( x.as_limbs_asc(), i64::from(*x_exp), *x_prec, y.as_limbs_asc(), i64::from(*y_exp), *y_prec, ); *cancel = c; o } _ => panic!(), } } fn agm_prec_round_normal( mut a: Float, mut b: Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if a < 0u32 || b < 0u32 { return (float_nan!(), Equal); } let mut working_prec = prec + prec.ceiling_log_base_2() + 15; // b (op2) and a (op1) are the 2 operands but we want b >= a match a.partial_cmp(&b).unwrap() { Equal => return Float::from_float_prec_round(a, prec, rm), Greater => swap(&mut a, &mut b), _ => {} } let mut scaleop = 0; let mut increment = Limb::WIDTH; let mut v; let mut scaleit; loop { let mut err: u64 = 0; let mut u; loop { let u_o; let v_o; (u, u_o) = a.mul_prec_ref_ref(&b, working_prec); (v, v_o) = a.add_prec_ref_ref(&b, working_prec); let u_overflow = test_overflow(&u, u_o); let v_overflow = test_overflow(&v, v_o); if u_overflow || v_overflow || test_underflow(&u, u_o) || test_underflow(&v, v_o) { assert_eq!(scaleop, 0); let e1 = a.get_exponent().unwrap(); let e2 = b.get_exponent().unwrap(); if u_overflow || v_overflow { // Let's recall that emin <= e1 <= e2 <= emax. There has been an overflow. Thus // e2 >= emax/2. If the mpfr_mul overflowed, then e1 + e2 > emax. If the // mpfr_add overflowed, then e2 = emax. We want: (e1 + scale) + (e2 + scale) <= // emax, i.e. scale <= (emax - e1 - e2) / 2. Let's take scale = min(floor((emax // - e1 - e2) / 2), -1). This is OK, as: // ``` // - emin <= scale <= -1. // - e1 + scale >= emin. Indeed: // * If e1 + e2 > emax, then // e1 + scale >= e1 + (emax - e1 - e2) / 2 - 1 // >= (emax + e1 - emax) / 2 - 1 // >= e1 / 2 - 1 >= emin. // * Otherwise, mpfr_mul didn't overflow, therefore // mpfr_add overflowed and e2 = emax, so that // e1 > emin (see restriction below). // e1 + scale > emin - 1, thus e1 + scale >= emin. // - e2 + scale <= emax, since scale < 0. // ``` let e_agm = e1 + e2; if e_agm > Float::MAX_EXPONENT { scaleop = -((e_agm - Float::MAX_EXPONENT + 1) / 2); assert!(scaleop < 0); } else { // The addition necessarily overflowed. assert_eq!(e2, Float::MAX_EXPONENT); // The case where e1 = emin and e2 = emax is not supported here. This would // mean that the precision of e2 would be huge (and possibly not supported // in practice anyway). assert!(e1 > Float::MIN_EXPONENT); // Note: this case is probably impossible to have in practice since we need // e2 = emax, and no overflow in the product. Since the product is >= // 2^(e1+e2-2), it implies e1 + e2 - 2 <= emax, thus e1 <= 2. Now to get an // overflow we need op1 >= 1/2 ulp(op2), which implies that the precision of // op2 should be at least emax-2. On a 64-bit computer this is impossible to // have, and would require a huge amount of memory on a 32-bit computer. scaleop = -1; } } else { // underflow only (in the multiplication) // // We have e1 + e2 <= emin (so, e1 <= e2 <= 0). We want: (e1 + scale) + (e2 + // scale) >= emin + 1, i.e. scale >= (emin + 1 - e1 - e2) / 2. let's take scale // = ceil((emin + 1 - e1 - e2) / 2). This is OK, as: 1. 1 <= scale <= emax. 2. // e1 + scale >= emin + 1 >= emin. 3. e2 + scale <= scale <= emax. assert!(e1 <= e2 && e2 <= 0); scaleop = (Float::MIN_EXPONENT + 2 - e1 - e2) / 2; assert!(scaleop > 0); } a <<= scaleop; b <<= scaleop; } else { break; } } u.sqrt_assign(); v >>= 1u32; scaleit = 0; let mut n: u64 = 1; let mut eq = 0; 'mid: while cmp2_helper(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 { let mut uf; let mut vf; loop { vf = (&u + &v) >> 1; // See proof in algorithms.tex if eq > working_prec >> 2 { // vf = V(k) let low_p = (working_prec + 1) >> 1; let (mut w, o) = v.sub_prec_ref_ref(&u, low_p); // e = V(k-1)-U(k-1) let mut underflow = test_underflow(&w, o); let o = w.square_round_assign(Nearest); // e = e^2 underflow |= test_underflow(&w, o); let o = w.shr_round_assign(4, Nearest); // e*= (1/2)^2*1/4 underflow |= test_underflow(&w, o); let o = w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k) underflow |= test_underflow(&w, o); let vf_exp = vf.get_exponent().unwrap(); if !underflow { v = vf.sub_prec(w, working_prec).0; // 0 or 1 err = u64::exact_from(vf_exp - v.get_exponent().unwrap()); break 'mid; } // There has been an underflow because of the cancellation between V(k-1) and // U(k-1). Let's use the conventional method. } // U(k) increases, so that U.V can overflow (but not underflow). uf = &u * &v; // For multiplication using Nearest, is_infinite is sufficient for overflow checking if uf.is_infinite() { let scale2 = -(((u.get_exponent().unwrap() + v.get_exponent().unwrap()) - Float::MAX_EXPONENT + 1) / 2); u <<= scale2; v <<= scale2; scaleit += scale2; } else { break; } } u = uf.sqrt(); swap(&mut v, &mut vf); n += 1; } // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the // final subtraction // // 18n+51 should not overflow since n is about log(p) err += (18 * n + 51).ceiling_log_base_2(); // we should have n+2 <= 2^(p/4) [see algorithms.tex] if (n + 2).ceiling_log_base_2() <= working_prec >> 2 && float_can_round(v.significand_ref().unwrap(), working_prec - err, prec, rm) { break; } working_prec += increment; increment = working_prec >> 1; } v.shr_prec_round(scaleop + scaleit, prec, rm) } fn agm_prec_round_ref_ref_normal( a: &Float, b: &Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if *a < 0u32 || *b < 0u32 { return (float_nan!(), Equal); } let mut working_prec = prec + prec.ceiling_log_base_2() + 15; let mut a = Cow::Borrowed(a); let mut b = Cow::Borrowed(b); // b (op2) and a (op1) are the 2 operands but we want b >= a match a.partial_cmp(&b).unwrap() { Equal => return Float::from_float_prec_round_ref(a.as_ref(), prec, rm), Greater => swap(&mut a, &mut b), _ => {} } let mut scaleop = 0; let mut increment = Limb::WIDTH; let mut v; let mut scaleit; loop { let mut err: u64 = 0; let mut u; loop { let u_o; let v_o; (u, u_o) = a.mul_prec_ref_ref(&b, working_prec); (v, v_o) = a.add_prec_ref_ref(&b, working_prec); let u_overflow = test_overflow(&u, u_o); let v_overflow = test_overflow(&v, v_o); if u_overflow || v_overflow || test_underflow(&u, u_o) || test_underflow(&v, v_o) { assert_eq!(scaleop, 0); let e1 = a.get_exponent().unwrap(); let e2 = b.get_exponent().unwrap(); if u_overflow || v_overflow { // Let's recall that emin <= e1 <= e2 <= emax. There has been an overflow. Thus // e2 >= emax/2. If the mpfr_mul overflowed, then e1 + e2 > emax. If the // mpfr_add overflowed, then e2 = emax. We want: (e1 + scale) + (e2 + scale) <= // emax, i.e. scale <= (emax - e1 - e2) / 2. Let's take scale = min(floor((emax // - e1 - e2) / 2), -1). This is OK, as: // ``` // - emin <= scale <= -1. // - e1 + scale >= emin. Indeed: // * If e1 + e2 > emax, then // e1 + scale >= e1 + (emax - e1 - e2) / 2 - 1 // >= (emax + e1 - emax) / 2 - 1 // >= e1 / 2 - 1 >= emin. // * Otherwise, mpfr_mul didn't overflow, therefore // mpfr_add overflowed and e2 = emax, so that // e1 > emin (see restriction below). // e1 + scale > emin - 1, thus e1 + scale >= emin. // - e2 + scale <= emax, since scale < 0. // ``` let e_agm = e1 + e2; if e_agm > Float::MAX_EXPONENT { scaleop = -((e_agm - Float::MAX_EXPONENT + 1) / 2); assert!(scaleop < 0); } else { // The addition necessarily overflowed. assert_eq!(e2, Float::MAX_EXPONENT); // The case where e1 = emin and e2 = emax is not supported here. This would // mean that the precision of e2 would be huge (and possibly not supported // in practice anyway). assert!(e1 > Float::MIN_EXPONENT); // Note: this case is probably impossible to have in practice since we need // e2 = emax, and no overflow in the product. Since the product is >= // 2^(e1+e2-2), it implies e1 + e2 - 2 <= emax, thus e1 <= 2. Now to get an // overflow we need op1 >= 1/2 ulp(op2), which implies that the precision of // op2 should be at least emax-2. On a 64-bit computer this is impossible to // have, and would require a huge amount of memory on a 32-bit computer. scaleop = -1; } } else { // underflow only (in the multiplication) // // We have e1 + e2 <= emin (so, e1 <= e2 <= 0). We want: (e1 + scale) + (e2 + // scale) >= emin + 1, i.e. scale >= (emin + 1 - e1 - e2) / 2. let's take scale // = ceil((emin + 1 - e1 - e2) / 2). This is OK, as: 1. 1 <= scale <= emax. 2. // e1 + scale >= emin + 1 >= emin. 3. e2 + scale <= scale <= emax. assert!(e1 <= e2 && e2 <= 0); scaleop = (Float::MIN_EXPONENT + 2 - e1 - e2) / 2; assert!(scaleop > 0); } *a.to_mut() <<= scaleop; *b.to_mut() <<= scaleop; } else { break; } } u.sqrt_assign(); v >>= 1u32; scaleit = 0; let mut n: u64 = 1; let mut eq = 0; 'mid: while cmp2_helper(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 { let mut uf; let mut vf; loop { vf = (&u + &v) >> 1; // See proof in algorithms.tex if eq > working_prec >> 2 { // vf = V(k) let low_p = (working_prec + 1) >> 1; let (mut w, o) = v.sub_prec_ref_ref(&u, low_p); // e = V(k-1)-U(k-1) let mut underflow = test_underflow(&w, o); let o = w.square_round_assign(Nearest); // e = e^2 underflow |= test_underflow(&w, o); let o = w.shr_round_assign(4, Nearest); // e*= (1/2)^2*1/4 underflow |= test_underflow(&w, o); let o = w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k) underflow |= test_underflow(&w, o); let vf_exp = vf.get_exponent().unwrap(); if !underflow { v = vf.sub_prec(w, working_prec).0; // 0 or 1 err = u64::exact_from(vf_exp - v.get_exponent().unwrap()); break 'mid; } // There has been an underflow because of the cancellation between V(k-1) and // U(k-1). Let's use the conventional method. } // U(k) increases, so that U.V can overflow (but not underflow). uf = &u * &v; // For multiplication using Nearest, is_infinite is sufficient for overflow checking if uf.is_infinite() { let scale2 = -(((u.get_exponent().unwrap() + v.get_exponent().unwrap()) - Float::MAX_EXPONENT + 1) / 2); u <<= scale2; v <<= scale2; scaleit += scale2; } else { break; } } u = uf.sqrt(); swap(&mut v, &mut vf); n += 1; } // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the // final subtraction // // 18n+51 should not overflow since n is about log(p) err += (18 * n + 51).ceiling_log_base_2(); // we should have n+2 <= 2^(p/4) [see algorithms.tex] if (n + 2).ceiling_log_base_2() <= working_prec >> 2 && float_can_round(v.significand_ref().unwrap(), working_prec - err, prec, rm) { break; } working_prec += increment; increment = working_prec >> 1; } v.shr_prec_round(scaleop + scaleit, prec, rm) } fn agm_rational_helper( x: &Rational, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let (x_lo, x_o) = Float::from_rational_prec_round_ref(x, working_prec, Floor); let (y_lo, y_o) = Float::from_rational_prec_round_ref(y, working_prec, Floor); if x_o == Equal && y_o == Equal { return agm_prec_round_normal(x_lo, y_lo, prec, rm); } let mut x_hi = x_lo.clone(); if x_o != Equal { x_hi.increment(); } let mut y_hi = y_lo.clone(); if y_o != Equal { y_hi.increment(); } let (agm_lo, mut o_lo) = agm_prec_round_normal(x_lo, y_lo, prec, rm); let (agm_hi, mut o_hi) = agm_prec_round_normal(x_hi, y_hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && agm_lo == agm_hi { return (agm_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } fn agm_rational_helper_extended( x: &Rational, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let (x_lo, x_o) = ExtendedFloat::from_rational_prec_round_ref(x, working_prec, Floor); let (y_lo, y_o) = ExtendedFloat::from_rational_prec_round_ref(y, working_prec, Floor); if x_o == Equal && y_o == Equal { let (agm, o) = agm_prec_round_normal_extended(x_lo, y_lo, prec, rm); return agm.into_float_helper(prec, rm, o); } let mut x_hi = x_lo.clone(); if x_o != Equal { x_hi.increment(); } let mut y_hi = y_lo.clone(); if y_o != Equal { y_hi.increment(); } let (agm_lo, mut o_lo) = agm_prec_round_normal_extended(x_lo, y_lo, prec, rm); let (agm_hi, mut o_hi) = agm_prec_round_normal_extended(x_hi, y_hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && agm_lo == agm_hi { return agm_lo.into_float_helper(prec, rm, o_lo); } working_prec += increment; increment = working_prec >> 1; } } impl Float { /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded AGM is less than, /// equal to, or greater than the exact AGM. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p,m)=\infty$ /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec`] instead. If you /// know that your target precision is the maximum of the precisions of the two inputs, consider /// using [`Float::agm_round`] instead. If both of these things are true, consider using /// [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Floor); /// assert_eq!(agm.to_string(), "13.0"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Ceiling); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Nearest); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Floor); /// assert_eq!(agm.to_string(), "13.45816"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Ceiling); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Nearest); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_round(self, other: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match (&self, &other) { (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal), (float_infinity!(), x) | (x, float_infinity!()) if *x > 0.0 => { (float_infinity!(), Equal) } (float_either_infinity!(), _) | (_, float_either_infinity!()) => (float_nan!(), Equal), (float_either_zero!(), _) | (_, float_either_zero!()) => (float_zero!(), Equal), _ => agm_prec_round_normal(self, other, prec, rm), } } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// specified precision and with the specified rounding mode. The first [`Float`] is taken by /// value and the second by reference. An [`Ordering`] is also returned, indicating whether the /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p,m)=\infty$ /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_val_ref`] instead. /// If you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::agm_round_val_ref`] instead. If both of these things are true, /// consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Floor); /// assert_eq!(agm.to_string(), "13.0"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Ceiling); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Nearest); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Floor); /// assert_eq!(agm.to_string(), "13.45816"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Ceiling); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Nearest); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_round_val_ref( mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let o = self.agm_prec_round_assign_ref(other, prec, rm); (self, o) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// specified precision and with the specified rounding mode. The first [`Float`] is taken by /// reference and the second by value. An [`Ordering`] is also returned, indicating whether the /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p,m)=\infty$ /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_ref_val`] instead. /// If you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::agm_round_ref_val`] instead. If both of these things are true, /// consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Floor); /// assert_eq!(agm.to_string(), "13.0"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 5, Ceiling); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 5, Nearest); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Floor); /// assert_eq!(agm.to_string(), "13.45816"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Ceiling); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Nearest); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_round_ref_val( &self, mut other: Self, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let o = other.agm_prec_round_assign_ref(self, prec, rm); (other, o) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded AGM is less /// than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p,m)=\infty$ /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_ref_ref`] instead. /// If you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::agm_round_ref_ref`] instead. If both of these things are true, /// consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Floor); /// assert_eq!(agm.to_string(), "13.0"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Ceiling); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Nearest); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Floor); /// assert_eq!(agm.to_string(), "13.45816"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Ceiling); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Nearest); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` /// /// This is mpfr_agm from agm.c, MPFR 4.3.0. #[inline] pub fn agm_prec_round_ref_ref( &self, other: &Self, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal), (float_infinity!(), x) | (x, float_infinity!()) if *x > 0.0 => { (float_infinity!(), Equal) } (float_either_infinity!(), _) | (_, float_either_infinity!()) => (float_nan!(), Equal), (float_either_zero!(), _) | (_, float_either_zero!()) => (float_zero!(), Equal), _ => agm_prec_round_ref_ref_normal(self, other, prec, rm), } } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// nearest value of the specified precision. Both [`Float`]s are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p)=\infty$ /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round`] instead. If you know that your target precision is the maximum of /// the precisions of the two inputs, consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec(Float::from(6), 5); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec(Float::from(6), 20); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec(self, other: Self, prec: u64) -> (Self, Ordering) { self.agm_prec_round(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// nearest value of the specified precision. The first [`Float`] is taken by value and the /// second by reference. An [`Ordering`] is also returned, indicating whether the rounded AGM is /// less than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p)=\infty$ /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round_val_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from(24).agm_prec_val_ref(&Float::from(6), 5); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from(24).agm_prec_val_ref(&Float::from(6), 20); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_val_ref(self, other: &Self, prec: u64) -> (Self, Ordering) { self.agm_prec_round_val_ref(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// nearest value of the specified precision. The first [`Float`] is taken by reference and the /// second by value. An [`Ordering`] is also returned, indicating whether the rounded AGM is /// less than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p)=\infty$ /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round_ref_val`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = (&Float::from(24)).agm_prec_ref_val(Float::from(6), 5); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = (&Float::from(24)).agm_prec_ref_val(Float::from(6), 20); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_ref_val(&self, other: Self, prec: u64) -> (Self, Ordering) { self.agm_prec_round_ref_val(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the /// nearest value of the specified precision. Both [`Float`]s are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,p)=\infty$ /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round_ref_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = (&Float::from(24)).agm_prec_ref_ref(&Float::from(6), 5); /// assert_eq!(agm.to_string(), "13.5"); /// assert_eq!(o, Greater); /// /// let (agm, o) = (&Float::from(24)).agm_prec_ref_ref(&Float::from(6), 20); /// assert_eq!(agm.to_string(), "13.45818"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) { self.agm_prec_round_ref_ref(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,m)=\infty$ /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$ /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::agm_prec_round`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round(Float::from(6), Floor); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315696"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round(Float::from(6), Ceiling); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round(Float::from(6), Nearest); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_round(self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the /// specified rounding mode. The first [`Float`] is taken by value and the second by reference. /// An [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, /// or greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,m)=\infty$ /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$ /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::agm_prec_round_val_ref`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_val_ref(&Float::from(6), Floor); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315696"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_val_ref(&Float::from(6), Ceiling); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_val_ref(&Float::from(6), Nearest); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_round_val_ref(self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_val_ref(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the /// specified rounding mode. The first [`Float`] is taken by reference and the second by value. /// An [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, /// or greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,m)=\infty$ /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$ /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::agm_prec_round_ref_val`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Floor); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315696"); /// assert_eq!(o, Less); /// /// let (agm, o) = /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Ceiling); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// /// let (agm, o) = /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Nearest); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_round_ref_val(&self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_ref_val(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty,m)=\infty$ /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$ /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::agm_prec_round_ref_ref`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::agm`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_ref_ref(&Float::from(6), Floor); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315696"); /// assert_eq!(o, Less); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_ref_ref(&Float::from(6), Ceiling); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// /// let (agm, o) = Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm_round_ref_ref(&Float::from(6), Nearest); /// assert_eq!(agm.to_string(), "13.45817148172561542076681315698"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn agm_round_ref_ref(&self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_ref_ref(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result to the specified precision and with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::agm_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_assign`] instead. If /// you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::agm_round_assign`] instead. If both of these things are true, /// consider using [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Floor), Less); /// assert_eq!(x.to_string(), "13.0"); /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Ceiling), Greater); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Nearest), Greater); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 20, Floor), Less); /// assert_eq!(x.to_string(), "13.45816"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign(Float::from(6), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "13.45818"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign(Float::from(6), 20, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "13.45818"); /// ``` #[inline] pub fn agm_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering { let o; let mut x = Self::ZERO; swap(&mut x, self); (*self, o) = x.agm_prec_round(other, prec, rm); o } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result to the specified precision and with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::agm_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_assign_ref`] /// instead. If you know that your target precision is the maximum of the precisions of the two /// inputs, consider using [`Float::agm_round_assign_ref`] instead. If both of these things are /// true, consider using [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_round_assign_ref(&Float::from(6), 5, Floor), Less); /// assert_eq!(x.to_string(), "13.0"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign_ref(&Float::from(6), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign_ref(&Float::from(6), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "13.45816"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "13.45818"); /// /// let mut x = Float::from(24); /// assert_eq!( /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "13.45818"); /// ``` #[inline] pub fn agm_prec_round_assign_ref( &mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> Ordering { let o; (*self, o) = self.agm_prec_round_ref_ref(other, prec, rm); o } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result to the nearest value of the specified precision. The /// [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, indicating /// whether the rounded AGM is less than, equal to, or greater than the exact AGM. Although /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to /// `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::agm_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round_assign`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_assign(Float::from(6), 5), Greater); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_assign(Float::from(6), 20), Greater); /// assert_eq!(x.to_string(), "13.45818"); /// ``` #[inline] pub fn agm_prec_assign(&mut self, other: Self, prec: u64) -> Ordering { self.agm_prec_round_assign(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result to the nearest value of the specified precision. The /// [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is returned, /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::agm_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_round_assign_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_assign_ref(&Float::from(6), 5), Greater); /// assert_eq!(x.to_string(), "13.5"); /// /// let mut x = Float::from(24); /// assert_eq!(x.agm_prec_assign_ref(&Float::from(6), 20), Greater); /// assert_eq!(x.to_string(), "13.45818"); /// ``` #[inline] pub fn agm_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { self.agm_prec_round_assign_ref(other, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result with the specified rounding mode. The [`Float`] on the /// right-hand side is taken by value. An [`Ordering`] is returned, indicating whether the /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::agm_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::agm_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign(Float::from(6), Floor), Less); /// assert_eq!(x.to_string(), "13.45817148172561542076681315696"); /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign(Float::from(6), Ceiling), Greater); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign(Float::from(6), Nearest), Greater); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// ``` #[inline] pub fn agm_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_assign(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and rounding the result with the specified rounding mode. The [`Float`] on the /// right-hand side is taken by reference. An [`Ordering`] is returned, indicating whether the /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the /// inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::agm_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using /// [`Float::agm_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using [`Float::agm_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the /// exact result is therefore irrational). /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Floor), Less); /// assert_eq!(x.to_string(), "13.45817148172561542076681315696"); /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Ceiling), Greater); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Nearest), Greater); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// ``` #[inline] pub fn agm_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_assign_ref(other, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the specified precision and with the specified rounding mode, and returning the result as a /// [`Float`]. Both [`Rational`]s are taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { Self::agm_rational_prec_round_val_ref(x, &y, prec, rm) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the specified precision and with the specified rounding mode, and returning the result as a /// [`Float`]. The first [`Rational`]s is taken by value and the second by reference. An /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (x.sign(), y.sign()) { (Equal, _) | (_, Equal) => return (float_zero!(), Equal), (Less, _) | (_, Less) => return (float_nan!(), Equal), _ => {} } if x == *y { return Self::from_rational_prec_round(x, prec, rm); } assert_ne!(rm, Exact, "Inexact AGM"); let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1); let x_overflow = x_exp > Self::MAX_EXPONENT; let y_overflow = y_exp > Self::MAX_EXPONENT; let x_underflow = x_exp < Self::MIN_EXPONENT; let y_underflow = y_exp < Self::MIN_EXPONENT; match (x_overflow, y_overflow, x_underflow, y_underflow) { (true, true, _, _) => Self::from_rational_prec_round(x, prec, rm), (_, _, true, true) if rm != Nearest || x_exp < Self::MIN_EXPONENT - 1 && y_exp < Self::MIN_EXPONENT - 1 => { Self::from_rational_prec_round(x, prec, rm) } (false, false, false, false) if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT => { agm_rational_helper(&x, y, prec, rm) } _ => agm_rational_helper_extended(&x, y, prec, rm), } } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the specified precision and with the specified rounding mode, and returning the result as a /// [`Float`]. The first [`Rational`]s is taken by reference and the second by value. An /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (x.sign(), y.sign()) { (Equal, _) | (_, Equal) => return (float_zero!(), Equal), (Less, _) | (_, Less) => return (float_nan!(), Equal), _ => {} } if *x == y { return Self::from_rational_prec_round(y, prec, rm); } assert_ne!(rm, Exact, "Inexact AGM"); let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1); let x_overflow = x_exp > Self::MAX_EXPONENT; let y_overflow = y_exp > Self::MAX_EXPONENT; let x_underflow = x_exp < Self::MIN_EXPONENT; let y_underflow = y_exp < Self::MIN_EXPONENT; match (x_overflow, y_overflow, x_underflow, y_underflow) { (true, true, _, _) => Self::from_rational_prec_round(y, prec, rm), (_, _, true, true) if rm != Nearest || x_exp < Self::MIN_EXPONENT - 1 && y_exp < Self::MIN_EXPONENT - 1 => { Self::from_rational_prec_round(y, prec, rm) } (false, false, false, false) if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT => { agm_rational_helper(x, &y, prec, rm) } _ => agm_rational_helper_extended(x, &y, prec, rm), } } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the specified precision and with the specified rounding mode, and returning the result as a /// [`Float`]. Both [`Rational`]s are taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$ /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (x.sign(), y.sign()) { (Equal, _) | (_, Equal) => return (float_zero!(), Equal), (Less, _) | (_, Less) => return (float_nan!(), Equal), _ => {} } if x == y { return Self::from_rational_prec_round_ref(x, prec, rm); } assert_ne!(rm, Exact, "Inexact AGM"); let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1); let x_overflow = x_exp > Self::MAX_EXPONENT; let y_overflow = y_exp > Self::MAX_EXPONENT; let x_underflow = x_exp < Self::MIN_EXPONENT; let y_underflow = y_exp < Self::MIN_EXPONENT; match (x_overflow, y_overflow, x_underflow, y_underflow) { (true, true, _, _) => Self::from_rational_prec_round_ref(x, prec, rm), (_, _, true, true) if rm != Nearest || x_exp < Self::MIN_EXPONENT - 1 && y_exp < Self::MIN_EXPONENT - 1 => { Self::from_rational_prec_round_ref(x, prec, rm) } (false, false, false, false) if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT => { agm_rational_helper(x, y, prec, rm) } _ => agm_rational_helper_extended(x, y, prec, rm), } } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the nearest value of the specified precision, and returning the result as a [`Float`]. Both /// [`Rational`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p)=f(x,0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Up`, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::agm_rational_prec_round_val_ref(x, &y, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the nearest value of the specified precision, and returning the result as a [`Float`]. The /// first [`Rational`] is taken by value and the second by reference. An [`Ordering`] is also /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p)=f(x,0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Up`, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::agm_rational_prec_round_val_ref(x, y, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the nearest value of the specified precision, and returning the result as a [`Float`]. The /// first [`Rational`] is taken by reference and the second by value. An [`Ordering`] is also /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p)=f(x,0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Up`, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::agm_rational_prec_round_ref_val(x, y, prec, Nearest) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to /// the nearest value of the specified precision, and returning the result as a [`Float`]. Both /// [`Rational`]s are taken by reference. An [`Ordering`] is also returned, indicating whether /// the rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$. /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0,x,p)=f(x,0,p)=0.0$ /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Up`, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::agm_rational_prec_round_ref_ref(x, y, prec, Nearest) } } impl Agm for Float { type Output = Self; /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking both by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty)=\infty$ /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::agm_prec`] /// instead. If you want to specify the output precision, consider using [`Float::agm_round`]. /// If you want both of these things, consider using [`Float::agm_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Agm; /// use malachite_float::Float; /// /// assert_eq!( /// Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm(Float::from(6)) /// .to_string(), /// "13.45817148172561542076681315698" /// ); /// ``` #[inline] fn agm(self, other: Self) -> Self { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round(other, prec, Nearest).0 } } impl Agm<&Self> for Float { type Output = Self; /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking the first by value /// and the second by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty)=\infty$ /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_val_ref`] instead. If you want to specify the output precision, consider /// using [`Float::agm_round_val_ref`]. If you want both of these things, consider using /// [`Float::agm_prec_round_val_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Agm; /// use malachite_float::Float; /// /// assert_eq!( /// Float::from_unsigned_prec(24u8, 100) /// .0 /// .agm(&Float::from(6)) /// .to_string(), /// "13.45817148172561542076681315698" /// ); /// ``` #[inline] fn agm(self, other: &Self) -> Self { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_val_ref(other, prec, Nearest).0 } } impl Agm for &Float { type Output = Float; /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking the first by /// reference and the second by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty)=\infty$ /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_ref_val`] instead. If you want to specify the output precision, consider /// using [`Float::agm_round_ref_val`]. If you want both of these things, consider using /// [`Float::agm_prec_round_ref_val`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Agm; /// use malachite_float::Float; /// /// assert_eq!( /// (&Float::from_unsigned_prec(24u8, 100).0) /// .agm(Float::from(6)) /// .to_string(), /// "13.45817148172561542076681315698" /// ); /// ``` #[inline] fn agm(self, other: Float) -> Float { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_ref_val(other, prec, Nearest).0 } } impl Agm<&Float> for &Float { type Output = Float; /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking both by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty)=\infty$ /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_ref_ref`] instead. If you want to specify the output precision, consider /// using [`Float::agm_round_ref_ref`]. If you want both of these things, consider using /// [`Float::agm_prec_round_ref_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Agm; /// use malachite_float::Float; /// /// assert_eq!( /// (&Float::from_unsigned_prec(24u8, 100).0) /// .agm(&Float::from(6)) /// .to_string(), /// "13.45817148172561542076681315698" /// ); /// ``` #[inline] fn agm(self, other: &Float) -> Float { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_ref_ref(other, prec, Nearest).0 } } impl AgmAssign for Float { /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and taking the [`Float`] on the right-hand side by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// See the [`Float::agm`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::agm_round_assign`]. If you want both of these things, consider using /// [`Float::agm_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AgmAssign; /// use malachite_float::Float; /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// x.agm_assign(Float::from(6)); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// ``` #[inline] fn agm_assign(&mut self, other: Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_assign(other, prec, Nearest); } } impl AgmAssign<&Self> for Float { /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in /// place, and taking the [`Float`] on the right-hand side by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed /// to be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// See the [`Float::agm`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::agm_prec_assign_ref`] instead. If you want to specify the output precision, /// consider using [`Float::agm_round_assign_ref`]. If you want both of these things, consider /// using [`Float::agm_prec_round_assign_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AgmAssign; /// use malachite_float::Float; /// /// let mut x = Float::from_unsigned_prec(24u8, 100).0; /// x.agm_assign(&Float::from(6)); /// assert_eq!(x.to_string(), "13.45817148172561542076681315698"); /// ``` #[inline] fn agm_assign(&mut self, other: &Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.agm_prec_round_assign_ref(other, prec, Nearest); } } /// Computes the arithmetic-geometric mean (AGM) of two primitive floats. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to /// be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a /// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$ /// - $f(\infty,\infty)=\infty$ /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::agm::primitive_float_agm; /// /// assert_eq!( /// NiceFloat(primitive_float_agm(24.0, 6.0)), /// NiceFloat(13.458171481725616) /// ); /// ``` #[allow(clippy::type_repetition_in_bounds)] #[inline] pub fn primitive_float_agm(x: T, y: T) -> T where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_float_float_to_float_fn(Float::agm_prec, x, y) } /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, returning the result as a /// primitive float. /// /// $$ /// f(x,y) = \text{AGM}(x,y)+\varepsilon /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta} /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon. /// $$ /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to /// be 0. /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a /// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(0,x)=f(x,0)=0.0$ /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::agm::primitive_float_agm_rational; /// use malachite_q::Rational; /// /// assert_eq!( /// NiceFloat(primitive_float_agm_rational::( /// &Rational::from_unsigneds(2u8, 3), /// &Rational::from_unsigneds(1u8, 5) /// )), /// NiceFloat(0.3985113702200345) /// ); /// ``` #[allow(clippy::type_repetition_in_bounds)] #[inline] pub fn primitive_float_agm_rational(x: &Rational, y: &Rational) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_rational_rational_to_float_fn(Float::agm_rational_prec_ref_ref, x, y) } ================================================ FILE: malachite-float/src/arithmetic/div.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::arithmetic::is_power_of_2::abs_is_power_of_2; use crate::conversion::from_natural::{from_natural_zero_exponent, from_natural_zero_exponent_ref}; use crate::{ Float, float_either_infinity, float_either_zero, float_infinity, float_nan, float_negative_infinity, float_negative_zero, float_zero, }; use core::cmp::Ordering::{self, *}; use core::cmp::max; use core::mem::swap; use core::ops::{Div, DivAssign}; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, FloorLogBase2, IsPowerOf2, NegAssign, Sign, }; use malachite_base::num::basic::traits::{ Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity, NegativeZero, Zero as ZeroTrait, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_div::{ div_float_significands_in_place, div_float_significands_in_place_ref, div_float_significands_ref_ref, div_float_significands_ref_val, }; use malachite_q::Rational; const DIV_RATIONAL_THRESHOLD: u64 = 50; const RATIONAL_DIV_THRESHOLD: u64 = 50; fn div_rational_prec_round_assign_naive( x: &mut Float, y: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *x, y) { (float_nan!(), _) => Equal, (Float(Infinity { sign }), y) => { if y < 0 { sign.not_assign(); }; Equal } (Float(Zero { sign }), y) => { match y.sign() { Equal => *x = float_nan!(), Greater => {} Less => sign.not_assign(), } Equal } (x, y) => { if y == 0 { *x = Float(Infinity { sign: *x > 0u32 }); Equal } else { let not_sign = *x < 0; let mut z = Float::ZERO; swap(x, &mut z); let (mut quotient, o) = Float::from_rational_prec_round(Rational::exact_from(z) / y, prec, rm); if quotient == 0u32 && not_sign { quotient.neg_assign(); } *x = quotient; o } } } } fn div_rational_prec_round_assign_naive_ref( x: &mut Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *x, y) { (float_nan!(), _) => Equal, (Float(Infinity { sign }), y) => { if *y < 0 { sign.not_assign(); }; Equal } (Float(Zero { sign }), y) => { match y.sign() { Equal => *x = float_nan!(), Greater => {} Less => sign.not_assign(), } Equal } (x, y) => { if *y == 0 { *x = Float(Infinity { sign: *x > 0u32 }); Equal } else { let not_sign = *x < 0; let mut z = Float::ZERO; swap(x, &mut z); let (mut quotient, o) = Float::from_rational_prec_round(Rational::exact_from(z) / y, prec, rm); if quotient == 0u32 && not_sign { quotient.neg_assign(); } *x = quotient; o } } } } pub_test! {div_rational_prec_round_naive( mut x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = div_rational_prec_round_assign_naive(&mut x, y, prec, rm); (x, o) }} pub_test! {div_rational_prec_round_naive_val_ref( mut x: Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = div_rational_prec_round_assign_naive_ref(&mut x, y, prec, rm); (x, o) }} pub_test! {div_rational_prec_round_naive_ref_val( x: &Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) => (float_nan!(), Equal), (Float(Infinity { sign }), y) => ( if y >= 0u32 { Float(Infinity { sign: *sign }) } else { Float(Infinity { sign: !*sign }) }, Equal, ), (Float(Zero { sign }), y) => ( match y.sign() { Equal => float_nan!(), Greater => Float(Zero { sign: *sign }), Less => Float(Zero { sign: !*sign }), }, Equal, ), (x, y) => { if y == 0 { (Float(Infinity { sign: *x > 0u32 }), Equal) } else { let (mut quotient, o) = Float::from_rational_prec_round(Rational::exact_from(x) / y, prec, rm); if quotient == 0u32 && *x < 0 { quotient.neg_assign(); } (quotient, o) } } } }} pub_test! {div_rational_prec_round_naive_ref_ref( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) => (float_nan!(), Equal), (Float(Infinity { sign }), y) => ( if *y >= 0u32 { Float(Infinity { sign: *sign }) } else { Float(Infinity { sign: !*sign }) }, Equal, ), (Float(Zero { sign }), y) => ( match y.sign() { Equal => float_nan!(), Greater => Float(Zero { sign: *sign }), Less => Float(Zero { sign: !*sign }), }, Equal, ), (x, y) => { if *y == 0 { (Float(Infinity { sign: *x > 0u32 }), Equal) } else { let (mut quotient, o) = Float::from_rational_prec_round(Rational::exact_from(x) / y, prec, rm); if quotient == 0u32 && *x < 0 { quotient.neg_assign(); } (quotient, o) } } } }} fn div_rational_prec_round_assign_direct( x: &mut Float, y: Rational, prec: u64, mut rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); if y == 0u32 { *x = match (*x).partial_cmp(&0u32) { Some(Greater) => Float::INFINITY, Some(Less) => Float::NEGATIVE_INFINITY, _ => Float::NAN, }; return Equal; } let sign = y >= 0; let (n, d) = y.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let o = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_assign(i128::from(log_d) - i128::from(log_n), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); *x >>= x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent(n), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(log_d) - 1, prec, rm, o, ) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); *x >>= x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent(d), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(log_n) + i128::from(d_exp) + 1, prec, rm, o, ) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); *x >>= x_exp; x.mul_prec_round_assign(d, mul_prec, Floor); let o = x.div_prec_round_assign(n, prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(d_exp), prec, rm, o, ) } }; if sign { o } else { x.neg_assign(); o.reverse() } } fn div_rational_prec_round_assign_direct_ref( x: &mut Float, y: &Rational, prec: u64, mut rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); if *y == 0u32 { *x = match (*x).partial_cmp(&0u32) { Some(Greater) => Float::INFINITY, Some(Less) => Float::NEGATIVE_INFINITY, _ => Float::NAN, }; return Equal; } let sign = *y >= 0; let (n, d) = y.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let o = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_assign(i128::from(log_d) - i128::from(log_n), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); *x >>= x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent_ref(n), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(log_d) - 1, prec, rm, o, ) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); *x >>= x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent_ref(d), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(log_n) + i128::from(d_exp) + 1, prec, rm, o, ) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); *x >>= x_exp; x.mul_prec_round_assign(d, mul_prec, Floor); let o = x.div_prec_round_assign(n, prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(d_exp), prec, rm, o, ) } }; if sign { o } else { x.neg_assign(); o.reverse() } } pub_test! {div_rational_prec_round_direct( mut x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = div_rational_prec_round_assign_direct(&mut x, y, prec, rm); (x, o) }} pub_test! {div_rational_prec_round_direct_val_ref( mut x: Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = div_rational_prec_round_assign_direct_ref(&mut x, y, prec, rm); (x, o) }} pub_test! {div_rational_prec_round_direct_ref_val( x: &Float, y: Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); let sign = y >= 0; if y == 0u32 { return ( match x.partial_cmp(&0u32) { Some(Greater) => Float::INFINITY, Some(Less) => Float::NEGATIVE_INFINITY, _ => Float::NAN, }, Equal, ); } let (n, d) = y.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_ref(i128::from(log_d) - i128::from(log_n), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut x = x >> x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent(n), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(log_d) - 1, prec, rm, o, ); (x, o) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut x = x >> x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent(d), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(log_n) + i128::from(d_exp) + 1, prec, rm, o, ); (x, o) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut x = x >> x_exp; x.mul_prec_round_assign(d, mul_prec, Floor); let o = x.div_prec_round_assign(n, prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(d_exp), prec, rm, o, ); (x, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} pub_test! {div_rational_prec_round_direct_ref_ref( x: &Float, y: &Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if *y == 0u32 { return ( match x.partial_cmp(&0u32) { Some(Greater) => Float::INFINITY, Some(Less) => Float::NEGATIVE_INFINITY, _ => Float::NAN, }, Equal, ); } let sign = *y >= 0; let (n, d) = y.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_ref(i128::from(log_d) - i128::from(log_n), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut x = x >> x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent_ref(n), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(log_d) - 1, prec, rm, o, ); (x, o) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut x = x >> x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent_ref(d), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(log_n) + i128::from(d_exp) + 1, prec, rm, o, ); (x, o) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = x.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut x = x >> x_exp; x.mul_prec_round_assign(d, mul_prec, Floor); let o = x.div_prec_round_assign(n, prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) - i128::from(n_exp) + i128::from(d_exp), prec, rm, o, ); (x, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} pub_test! {rational_div_float_prec_round_naive( x: Rational, y: Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (_, float_nan!()) => (float_nan!(), Equal), (x, Float(Infinity { sign })) => ( if x >= 0u32 { Float(Zero { sign }) } else { Float(Zero { sign: !sign }) }, Equal, ), (x, Float(Zero { sign })) => ( match x.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign }), Less => Float(Infinity { sign: !sign }), }, Equal, ), (x, y) => { let not_sign = y < 0; let (mut quotient, o) = Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); if quotient == 0u32 && not_sign { quotient.neg_assign(); } (quotient, o) } } }} pub_test! {rational_div_float_prec_round_naive_val_ref( x: Rational, y: &Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (_, float_nan!()) => (float_nan!(), Equal), (x, Float(Infinity { sign })) => ( if x >= 0u32 { Float(Zero { sign: *sign }) } else { Float(Zero { sign: !*sign }) }, Equal, ), (x, Float(Zero { sign })) => ( match x.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign: *sign }), Less => Float(Infinity { sign: !*sign }), }, Equal, ), (x, y) => { let (mut quotient, o) = Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); if quotient == 0u32 && *y < 0 { quotient.neg_assign(); } (quotient, o) } } }} pub_test! {rational_div_float_prec_round_naive_ref_val( x: &Rational, y: Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (_, float_nan!()) => (float_nan!(), Equal), (x, Float(Infinity { sign })) => ( if *x >= 0u32 { Float(Zero { sign }) } else { Float(Zero { sign: !sign }) }, Equal, ), (x, Float(Zero { sign })) => ( match x.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign }), Less => Float(Infinity { sign: !sign }), }, Equal, ), (x, y) => { let not_sign = y < 0; let (mut quotient, o) = Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); if quotient == 0u32 && not_sign { quotient.neg_assign(); } (quotient, o) } } }} pub_test! {rational_div_float_prec_round_naive_ref_ref( x: &Rational, y: &Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (_, float_nan!()) => (float_nan!(), Equal), (x, Float(Infinity { sign })) => ( if *x >= 0u32 { Float(Zero { sign: *sign }) } else { Float(Zero { sign: !*sign }) }, Equal, ), (x, Float(Zero { sign })) => ( match x.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign: *sign }), Less => Float(Infinity { sign: !*sign }), }, Equal, ), (x, y) => { let (mut quotient, o) = Float::from_rational_prec_round(x / Rational::exact_from(y), prec, rm); if quotient == 0u32 && *y < 0 { quotient.neg_assign(); } (quotient, o) } } }} pub_test! {rational_div_float_prec_round_direct( x: Rational, y: Float, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if x == 0u32 { return ( if y > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = x >= 0; let (n, d) = x.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let (mut quotient, o) = (y >> y_exp).reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(log_d) - i128::from(y_exp), prec, rm, o, ); (quotient, o) } (None, Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut quotient = from_natural_zero_exponent(n); let o = quotient.div_prec_round_assign(y >> y_exp, prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(n_exp) - i128::from(log_d) - i128::from(y_exp) + 1, prec, rm, o, ); (quotient, o) } (Some(log_n), None) => { let y_exp = y.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut y = y >> y_exp; let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); y.mul_prec_round_assign(from_natural_zero_exponent(d), mul_prec, Floor); let (mut quotient, o) = y.reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d_exp) - i128::from(y_exp) - 1, prec, rm, o, ); (quotient, o) } (None, None) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let mut quotient = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut y = y >> y_exp; y.mul_prec_round_assign(d, mul_prec, Floor); let o = quotient.div_prec_round_assign(y, prec, rm); let o = quotient.shl_prec_round_assign_helper( -i128::from(y_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (quotient, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} pub_test! {rational_div_float_prec_round_direct_val_ref( x: Rational, y: &Float, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if x == 0u32 { return ( if *y > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = x >= 0; let (n, d) = x.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let (mut quotient, o) = (y >> y_exp).reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(log_d) - i128::from(y_exp), prec, rm, o, ); (quotient, o) } (None, Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut quotient = from_natural_zero_exponent(n); let o = quotient.div_prec_round_assign(y >> y_exp, prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(n_exp) - i128::from(log_d) - i128::from(y_exp) + 1, prec, rm, o, ); (quotient, o) } (Some(log_n), None) => { let y_exp = y.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut y = y >> y_exp; let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); y.mul_prec_round_assign(from_natural_zero_exponent(d), mul_prec, Floor); let (mut quotient, o) = y.reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d_exp) - i128::from(y_exp) - 1, prec, rm, o, ); (quotient, o) } (None, None) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let mut quotient = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut y = y >> y_exp; y.mul_prec_round_assign(d, mul_prec, Floor); let o = quotient.div_prec_round_assign(y, prec, rm); let o = quotient.shl_prec_round_assign_helper( -i128::from(y_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (quotient, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} pub_test! {rational_div_float_prec_round_direct_ref_val( x: &Rational, y: Float, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if *x == 0u32 { return ( if y > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = *x >= 0; let (n, d) = x.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let (mut quotient, o) = (y >> y_exp).reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(log_d) - i128::from(y_exp), prec, rm, o, ); (quotient, o) } (None, Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut quotient = from_natural_zero_exponent_ref(n); let o = quotient.div_prec_round_assign(y >> y_exp, prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(n_exp) - i128::from(log_d) - i128::from(y_exp) + 1, prec, rm, o, ); (quotient, o) } (Some(log_n), None) => { let y_exp = y.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut y = y >> y_exp; let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); y.mul_prec_round_assign(from_natural_zero_exponent_ref(d), mul_prec, Floor); let (mut quotient, o) = y.reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d_exp) - i128::from(y_exp) - 1, prec, rm, o, ); (quotient, o) } (None, None) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let mut quotient = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut y = y >> y_exp; y.mul_prec_round_assign(d, mul_prec, Floor); let o = quotient.div_prec_round_assign(y, prec, rm); let o = quotient.shl_prec_round_assign_helper( -i128::from(y_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (quotient, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} pub_test! {rational_div_float_prec_round_direct_ref_ref( x: &Rational, y: &Float, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if *x == 0u32 { return ( if *y > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = *x >= 0; let (n, d) = x.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let (quotient, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let (mut quotient, o) = (y >> y_exp).reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(log_d) - i128::from(y_exp), prec, rm, o, ); (quotient, o) } (None, Some(log_d)) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut quotient = from_natural_zero_exponent_ref(n); let o = quotient.div_prec_round_assign(y >> y_exp, prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(n_exp) - i128::from(log_d) - i128::from(y_exp) + 1, prec, rm, o, ); (quotient, o) } (Some(log_n), None) => { let y_exp = y.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut y = y >> y_exp; let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); y.mul_prec_round_assign(from_natural_zero_exponent_ref(d), mul_prec, Floor); let (mut quotient, o) = y.reciprocal_prec_round(prec, rm); let o = quotient.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d_exp) - i128::from(y_exp) - 1, prec, rm, o, ); (quotient, o) } (None, None) => { let y_exp = y.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let mut quotient = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = y.get_min_prec().unwrap_or(1) + d.significant_bits(); let mut y = y >> y_exp; y.mul_prec_round_assign(d, mul_prec, Floor); let o = quotient.div_prec_round_assign(y, prec, rm); let o = quotient.shl_prec_round_assign_helper( -i128::from(y_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (quotient, o) } }; if sign { (quotient, o) } else { (-quotient, o.reverse()) } }} impl Float { /// Divides two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.div_prec_round_assign(other, prec, rm); (self, o) } /// Divides two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is are taken by value and the second by /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.div_prec_round_assign_ref(other, prec, rm); (self, o) } /// Divides two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is are taken by reference and the second by /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => ( Self(Infinity { sign: *x_sign == y_sign, }), Equal, ), ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => ( Self(Zero { sign: *x_sign == y_sign, }), Equal, ), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: mut y, }), ) => { if y.is_power_of_2() { let (mut quotient, mut o) = self.shr_prec_round_ref(y_exp - 1, prec, if y_sign { rm } else { -rm }); if !y_sign { quotient.neg_assign(); o = o.reverse(); } return (quotient, o); } let sign = *x_sign == y_sign; let exp_diff = *x_exp - y_exp; if exp_diff > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp_diff + 2 < Self::MIN_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), }; } let (quotient, exp_offset, o) = div_float_significands_ref_val( x, *x_prec, &mut y, y_prec, prec, if sign { rm } else { -rm }, ); let exp = exp_diff.checked_add(i32::exact_from(exp_offset)).unwrap(); if exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp < Self::MIN_EXPONENT { return if rm == Nearest && exp == Self::MIN_EXPONENT - 1 && (o == Less || !quotient.is_power_of_2()) { if sign { (Self::min_positive_value_prec(prec), Greater) } else { (-Self::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), } }; } ( Self(Finite { sign, exponent: exp, precision: prec, significand: quotient, }), if sign { o } else { o.reverse() }, ) } } } /// Divides two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => ( Self(Infinity { sign: x_sign == y_sign, }), Equal, ), ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => ( Self(Zero { sign: x_sign == y_sign, }), Equal, ), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), ) => { if y.is_power_of_2() { let (mut quotient, mut o) = self.shr_prec_round_ref(y_exp - 1, prec, if *y_sign { rm } else { -rm }); if !*y_sign { quotient.neg_assign(); o = o.reverse(); } return (quotient, o); } let sign = x_sign == y_sign; let exp_diff = *x_exp - y_exp; if exp_diff > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp_diff + 2 < Self::MIN_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), }; } let (quotient, exp_offset, o) = div_float_significands_ref_ref( x, *x_prec, y, *y_prec, prec, if sign { rm } else { -rm }, ); let exp = exp_diff.checked_add(i32::exact_from(exp_offset)).unwrap(); if exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp < Self::MIN_EXPONENT { return if rm == Nearest && exp == Self::MIN_EXPONENT - 1 && (o == Less || !quotient.is_power_of_2()) { if sign { (Self::min_positive_value_prec(prec), Greater) } else { (-Self::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), } }; } ( Self(Finite { sign, exponent: exp, precision: prec, significand: quotient, }), if sign { o } else { o.reverse() }, ) } } } /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. /// Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $0.00.0$ /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_prec_round(other, prec, Nearest) } /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. /// The first [`Float`] is taken by value and the second by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $0.00.0$ /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_prec_round_val_ref(other, prec, Nearest) } /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. /// The first [`Float`] is taken by reference and the second by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $0.00.0$ /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_prec_round_ref_val(other, prec, Nearest) } /// Divides two [`Float`]s, rounding the result to the nearest value of the specified precision. /// Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether /// the rounded quotient is less than, equal to, or greater than the exact quotient. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $0.00.0$ /// - $f(x,0.0,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,p)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,p)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_prec_round_ref_ref(other, prec, Nearest) } /// Divides two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round(other, prec, rm) } /// Divides two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by value and the second by reference. An [`Ordering`] is also returned, /// indicating whether the rounded quotient is less than, equal to, or greater than the exact /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_val_ref(other, prec, rm) } /// Divides two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by reference and the second by value. An [`Ordering`] is also returned, /// indicating whether the rounded quotient is less than, equal to, or greater than the exact /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_ref_val(other, prec, rm) } /// Divides two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded quotient is less than, equal to, or greater than the exact quotient. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm\infty,p,m)=f(\pm0.0,\pm0.0,p,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $0.00.0$ /// - $f(x,0.0,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=-\infty$ if $0.00.0$ /// - $f(x,-0.0,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x,m)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x,m)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_ref_ref(other, prec, rm) } /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the specified precision /// and with the specified rounding mode. The [`Float`] on the right-hand side is taken by /// value. An [`Ordering`] is returned, indicating whether the rounded quotient is less than, /// equal to, or greater than the exact quotient. Although `NaN`s are not comparable to any /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_assign`] instead. If /// you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::div_round_assign`] instead. If both of these things are true, /// consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), `prec`)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 5, Floor), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.12"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.19"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.12"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.155725"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.155727"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign(Float::from(E), 20, Nearest), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.155727"); /// ``` #[inline] pub fn div_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => { *self = float_nan!(); Equal } ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => { *self = Self(Infinity { sign: *x_sign == y_sign, }); Equal } ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => { *self = Self(Zero { sign: *x_sign == y_sign, }); Equal } (_, y) if abs_is_power_of_2(&y) => { let sign = y >= 0; let mut o = self.shr_prec_round_assign( y.get_exponent().unwrap() - 1, prec, if sign { rm } else { -rm }, ); if !sign { self.neg_assign(); o = o.reverse(); } o } ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: mut y, }), ) => { let sign = *x_sign == y_sign; let exp_diff = *x_exp - y_exp; if exp_diff > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if exp_diff + 2 < Self::MIN_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } }; } let (exp_offset, o) = div_float_significands_in_place( x, *x_prec, &mut y, y_prec, prec, if sign { rm } else { -rm }, ); *x_exp = exp_diff.checked_add(i32::exact_from(exp_offset)).unwrap(); if *x_exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if *x_exp < Self::MIN_EXPONENT { return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } *x_sign = sign; *x_prec = prec; if sign { o } else { o.reverse() } } } } /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the specified precision /// and with the specified rounding mode. The [`Float`] on the right-hand side is taken by /// reference. An [`Ordering`] is returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::div_prec_assign_ref`] /// instead. If you know that your target precision is the maximum of the precisions of the two /// inputs, consider using [`Float::div_round_assign_ref`] instead. If both of these things are /// true, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), `prec`)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Floor), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.12"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.19"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.12"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(quotient.to_string(), "1.155725"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.155727"); /// /// let mut quotient = Float::from(PI); /// assert_eq!( /// quotient.div_prec_round_assign_ref(&Float::from(E), 20, Nearest), /// Greater /// ); /// assert_eq!(quotient.to_string(), "1.155727"); /// ``` #[inline] pub fn div_prec_round_assign_ref( &mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => { *self = float_nan!(); Equal } ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => { *self = Self(Infinity { sign: x_sign == y_sign, }); Equal } ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => { *self = Self(Zero { sign: x_sign == y_sign, }); Equal } (_, y) if abs_is_power_of_2(y) => { let sign = *y >= 0; let mut o = self.shr_prec_round_assign( y.get_exponent().unwrap() - 1, prec, if sign { rm } else { -rm }, ); if !sign { self.neg_assign(); o = o.reverse(); } o } ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), ) => { let sign = x_sign == y_sign; let exp_diff = *x_exp - y_exp; if exp_diff > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if exp_diff + 2 < Self::MIN_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } }; } let (exp_offset, o) = div_float_significands_in_place_ref( x, *x_prec, y, *y_prec, prec, if sign { rm } else { -rm }, ); *x_exp = exp_diff.checked_add(i32::exact_from(exp_offset)).unwrap(); if *x_exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if *x_exp < Self::MIN_EXPONENT { return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float division"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } *x_sign = sign; *x_prec = prec; if sign { o } else { o.reverse() } } } } /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] /// is returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_prec_round_assign`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), `prec`)`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_prec_assign(Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "1.12"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_prec_assign(Float::from(E), 20), Greater); /// assert_eq!(x.to_string(), "1.155727"); /// ``` #[inline] pub fn div_prec_assign(&mut self, other: Self, prec: u64) -> Ordering { self.div_prec_round_assign(other, prec, Nearest) } /// Divides a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of the /// specified precision. The [`Float`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_prec_round_assign_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), `prec`)`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_prec_assign_ref(&Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "1.12"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_prec_assign_ref(&Float::from(E), 20), Greater); /// assert_eq!(x.to_string(), "1.155727"); /// ``` #[inline] pub fn div_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { self.div_prec_round_assign_ref(other, prec, Nearest) } /// Divides a [`Float`] by a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded quotient is less than, equal to, or greater than the exact /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::div_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::div_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `/=` /// instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign(Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "1.1557273497909217"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign(Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "1.155727349790922"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign(Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "1.1557273497909217"); /// ``` #[inline] pub fn div_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_assign(other, prec, rm) } /// Divides a [`Float`] by a [`Float`] in place, rounding the result with the specified rounding /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::div_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using /// [`Float::div_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "1.1557273497909217"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "1.155727349790922"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.div_round_assign_ref(&Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "1.1557273497909217"); /// ``` #[inline] pub fn div_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_assign_ref(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x>0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.div_rational_prec_round_assign(other, prec, rm); (self, o) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x>0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.div_rational_prec_round_assign_ref(other, prec, rm); (self, o) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`] /// by value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x>0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { div_rational_prec_round_naive_ref_val(self, other, prec, rm) } else { div_rational_prec_round_direct_ref_val(self, other, prec, rm) } } /// Divides a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=f(\pm0.0,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x>0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { div_rational_prec_round_naive_ref_ref(self, other, prec, rm) } else { div_rational_prec_round_direct_ref_ref(self, other, prec, rm) } } /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x>0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x>0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_rational_prec_round(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x>0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x>0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_rational_prec_round_val_ref(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x>0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x>0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_rational_prec_round_ref_val(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=f(\pm0.0,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x\geq 0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x>0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x>0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.div_rational_prec_round_ref_ref(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x>0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.div_rational_prec_round(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x>0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.div_rational_prec_round_val_ref(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x>0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.div_rational_prec_round_ref_val(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`], rounding the result with the specified rounding mode. /// The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=f(\pm0.0,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x\geq 0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x>0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x>0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.div_rational_prec_round_ref_ref(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::div_rational_prec_assign`] /// instead. If you know that your target precision is the precision of the [`Float`] input, /// consider using [`Float::div_rational_round_assign`] instead. If both of these things are /// true, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.0"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "9.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.42479"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477"); /// ``` #[inline] pub fn div_rational_prec_round_assign( &mut self, other: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { div_rational_prec_round_assign_naive(self, other, prec, rm) } else { div_rational_prec_round_assign_direct(self, other, prec, rm) } } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded quotient is less than, equal to, or /// greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using /// [`Float::div_rational_prec_assign_ref`] instead. If you know that your target precision is /// the precision of the [`Float`] input, consider using /// [`Float::div_rational_round_assign_ref`] instead. If both of these things are true, consider /// using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact division. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.0"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "9.5"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.42479"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477"); /// ``` #[inline] pub fn div_rational_prec_round_assign_ref( &mut self, other: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < DIV_RATIONAL_THRESHOLD { div_rational_prec_round_assign_naive_ref(self, other, prec, rm) } else { div_rational_prec_round_assign_direct_ref(self, other, prec, rm) } } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value of /// the specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded quotient is less than, equal to, or greater than the exact /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_assign(Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "2.1"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_assign(Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "2.094395"); /// ``` #[inline] pub fn div_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering { self.div_rational_prec_round_assign(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value of /// the specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::div_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_assign_ref(&Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "2.1"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_prec_assign_ref(&Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "2.094395"); /// ``` #[inline] pub fn div_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering { self.div_rational_prec_round_assign_ref(other, prec, Nearest) } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating /// whether the rounded quotient is less than, equal to, or greater than the exact quotient. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::div_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::div_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477796076938"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.42477796076939"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477796076938"); /// ``` #[inline] pub fn div_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.div_rational_prec_round_assign(other, prec, rm) } /// Divides a [`Float`] by a [`Rational`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned, /// indicating whether the rounded quotient is less than, equal to, or greater than the exact /// quotient. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::div_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::div_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `/=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477796076938"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "9.42477796076939"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.div_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "9.42477796076938"); /// ``` #[inline] pub fn div_rational_round_assign_ref( &mut self, other: &Rational, rm: RoundingMode, ) -> Ordering { let prec = self.significant_bits(); self.div_rational_prec_round_assign_ref(other, prec, rm) } /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Rational`] and the [`Float`] are both taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !y.is_normal() || max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { rational_div_float_prec_round_naive(x, y, prec, rm) } else { rational_div_float_prec_round_direct(x, y, prec, rm) } } /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Rational`] is taken by value and the [`Float`] by /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !y.is_normal() || max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { rational_div_float_prec_round_naive_val_ref(x, y, prec, rm) } else { rational_div_float_prec_round_direct_val_ref(x, y, prec, rm) } } /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Rational`] is taken by reference and the [`Float`] /// by value. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !y.is_normal() || max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { rational_div_float_prec_round_naive_ref_val(x, y, prec, rm) } else { rational_div_float_prec_round_direct_ref_val(x, y, prec, rm) } } /// Divides a [`Rational`] by a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Rational`] and the [`Float`] are both taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded quotient is less /// than, equal to, or greater than the exact quotient. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !y.is_normal() || max(x.significant_bits(), y.complexity()) < RATIONAL_DIV_THRESHOLD { rational_div_float_prec_round_naive_ref_ref(x, y, prec, rm) } else { rational_div_float_prec_round_direct_ref_ref(x, y, prec, rm) } } /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Rational`] and the [`Float`] are both are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p)=0.0$ if $x>0$ /// - $f(0,x,p)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::rational_div_float_prec_round(x, y, prec, Nearest) } /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Rational`] is taken by value and the [`Float`] by reference. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p)=0.0$ if $x>0$ /// - $f(0,x,p)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::rational_div_float_prec_round_val_ref(x, y, prec, Nearest) } /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Rational`] is taken by reference and the [`Float`] by value. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p)=0.0$ if $x>0$ /// - $f(0,x,p)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::rational_div_float_prec_round_ref_val(x, y, prec, Nearest) } /// Divides a [`Rational`] by a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Rational`] and the [`Float`] are both are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded quotient is less than, equal /// to, or greater than the exact quotient. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the quotient is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(x,\text{NaN},p)=f(0,\pm0.0,p)=\text{NaN}$ /// - $f(x,\infty,x,p)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p)=0.0$ if $x>0$ /// - $f(0,x,p)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { Self::rational_div_float_prec_round_ref_ref(x, y, prec, Nearest) } /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. /// The [`Rational`] and the [`Float`] are both are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,m)=0.0$ if $x>0$ /// - $f(0,x,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = y.significant_bits(); Self::rational_div_float_prec_round(x, y, prec, rm) } /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. /// The [`Rational`] is taken by value and the [`Float`] by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,m)=0.0$ if $x>0$ /// - $f(0,x,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = y.significant_bits(); Self::rational_div_float_prec_round_val_ref(x, y, prec, rm) } /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. /// The [`Rational`] is taken by reference and the [`Float`] by value. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,m)=0.0$ if $x>0$ /// - $f(0,x,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = y.significant_bits(); Self::rational_div_float_prec_round_ref_val(x, y, prec, rm) } /// Divides a [`Rational`] by a [`Float`], rounding the result with the specified rounding mode. /// The [`Rational`] and the [`Float`] are both are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded quotient is less than, equal to, or greater than /// the exact quotient. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x/y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x/y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x/y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(x,\text{NaN},m)=f(0,\pm0.0,m)=\text{NaN}$ /// - $f(x,\infty,x,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,m)=0.0$ if $x>0$ /// - $f(0,x,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = y.significant_bits(); Self::rational_div_float_prec_round_ref_ref(x, y, prec, rm) } } impl Div for Float { type Output = Self; /// Divides two [`Float`]s, taking both by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ /// - $f(\infty,x)=\infty$ if $0.00.0$ /// - $f(x,0.0)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=-\infty$ if $0.00.0$ /// - $f(x,-0.0)=\infty$ if $x<0.0$ /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round(other, prec, Nearest).0 } } impl Div<&Self> for Float { type Output = Self; /// Divides two [`Float`]s, taking the first by value and the second by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ /// - $f(\infty,x)=\infty$ if $0.00.0$ /// - $f(x,0.0)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=-\infty$ if $0.00.0$ /// - $f(x,-0.0)=\infty$ if $x<0.0$ /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_val_ref(other, prec, Nearest).0 } } impl Div for &Float { type Output = Float; /// Divides two [`Float`]s, taking the first by reference and the second by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ /// - $f(\infty,x)=\infty$ if $0.00.0$ /// - $f(x,0.0)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=-\infty$ if $0.00.0$ /// - $f(x,-0.0)=\infty$ if $x<0.0$ /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_ref_val(other, prec, Nearest).0 } } impl Div<&Float> for &Float { type Output = Float; /// Divides two [`Float`]s, taking both by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm\infty)=f(\pm0.0,\pm0.0) = \text{NaN}$ /// - $f(\infty,x)=\infty$ if $0.00.0$ /// - $f(x,0.0)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=-\infty$ if $0.00.0$ /// - $f(x,-0.0)=\infty$ if $x<0.0$ /// - $f(0.0,x)=0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(0.0,x)=-0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=-0.0$ if $x$ is not NaN and $x>0.0$ /// - $f(-0.0,x)=0.0$ if $x$ is not NaN and $x<0.0$ /// - $f(x,-\infty)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(x,-\infty)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_ref_ref(other, prec, Nearest).0 } } impl DivAssign for Float { /// Divides a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side by /// value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// x\gets = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `/` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::div_round_assign`]. If you want both of these things, consider using /// [`Float::div_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, /// }; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x /= Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x /= Float::ZERO; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x /= Float::NEGATIVE_ZERO; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x /= Float::ZERO; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x /= Float::NEGATIVE_ZERO; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x /= Float::INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x /= Float::from(2.5); /// assert_eq!(x.to_string(), "0.6"); /// /// let mut x = Float::from(1.5); /// x /= Float::from(-2.5); /// assert_eq!(x.to_string(), "-0.6"); /// /// let mut x = Float::from(-1.5); /// x /= Float::from(2.5); /// assert_eq!(x.to_string(), "-0.6"); /// /// let mut x = Float::from(-1.5); /// x /= Float::from(-2.5); /// assert_eq!(x.to_string(), "0.6"); /// ``` #[inline] fn div_assign(&mut self, other: Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_assign(other, prec, Nearest); } } impl DivAssign<&Self> for Float { /// Divides a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side by /// reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// quotient is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// x\gets = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `/` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::div_round_assign`]. If you want both of these things, consider using /// [`Float::div_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeZero, Zero, /// }; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x /= &Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x /= &Float::ZERO; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x /= &Float::NEGATIVE_ZERO; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x /= &Float::ZERO; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x /= &Float::NEGATIVE_ZERO; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x /= &Float::INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x /= &Float::from(2.5); /// assert_eq!(x.to_string(), "0.6"); /// /// let mut x = Float::from(1.5); /// x /= &Float::from(-2.5); /// assert_eq!(x.to_string(), "-0.6"); /// /// let mut x = Float::from(-1.5); /// x /= &Float::from(2.5); /// assert_eq!(x.to_string(), "-0.6"); /// /// let mut x = Float::from(-1.5); /// x /= &Float::from(-2.5); /// assert_eq!(x.to_string(), "0.6"); /// ``` #[inline] fn div_assign(&mut self, other: &Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.div_prec_round_assign_ref(other, prec, Nearest); } } impl Div for Float { type Output = Self; /// Divides a [`Float`] by a [`Rational`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x\geq 0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x>0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x>0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.div_rational_prec_round(other, prec, Nearest).0 } } impl Div<&Rational> for Float { type Output = Self; /// Divides a [`Float`] by a [`Rational`], taking the first by value and the second by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x\geq 0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x>0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x>0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.div_rational_prec_round_val_ref(other, prec, Nearest).0 } } impl Div for &Float { type Output = Float; /// Divides a [`Float`] by a [`Rational`], taking the first by reference and the second by /// value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x\geq 0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x>0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x>0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.div_rational_prec_round_ref_val(other, prec, Nearest).0 } } impl Div<&Rational> for &Float { type Output = Float; /// Divides a [`Float`] by a [`Rational`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=f(\pm0.0,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x\geq 0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x\geq 0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x>0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x>0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.div_rational_prec_round_ref_ref(other, prec, Nearest).0 } } impl DivAssign for Float { /// Divides a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `/` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_rational_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::div_rational_round_assign`]. If you want both of these things, /// consider using [`Float::div_rational_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x /= Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x /= Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x /= Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x /= Rational::exact_from(-1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x /= Rational::exact_from(-1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(2.5); /// x /= Rational::exact_from(1.5); /// assert_eq!(x.to_string(), "1.8"); /// ``` #[inline] fn div_assign(&mut self, other: Rational) { let prec = self.significant_bits(); self.div_rational_prec_round_assign(other, prec, Nearest); } } impl DivAssign<&Rational> for Float { /// Divides a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `/` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::div_rational_prec_assign_ref`] instead. If you want to specify the output /// precision, consider using [`Float::div_rational_round_assign_ref`]. If you want both of /// these things, consider using [`Float::div_rational_prec_round_assign_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x /= &Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x /= &Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x /= &Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x /= &Rational::exact_from(-1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x /= &Rational::exact_from(-1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(2.5); /// x /= &Rational::exact_from(1.5); /// assert_eq!(x.to_string(), "1.8"); /// ``` #[inline] fn div_assign(&mut self, other: &Rational) { let prec = self.significant_bits(); self.div_rational_prec_round_assign_ref(other, prec, Nearest); } } impl Div for Rational { type Output = Float; /// Divides a [`Rational`] by a [`Float`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); Float::rational_div_float_prec_round(self, other, prec, Nearest).0 } } impl Div<&Float> for Rational { type Output = Float; /// Divides a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`] by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); Float::rational_div_float_prec_round_val_ref(self, other, prec, Nearest).0 } } impl Div for &Rational { type Output = Float; /// Divides a [`Rational`] by a [`Float`], taking the [`Rational`] by reference and the /// [`Float`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); Float::rational_div_float_prec_round_ref_val(self, other, prec, Nearest).0 } } impl Div<&Float> for &Rational { type Output = Float; /// Divides a [`Rational`] by a [`Float`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the quotient /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x/y+\varepsilon. /// $$ /// - If $x/y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x/y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x/y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN},p,m)=f(0,\pm0.0,p,m)=\text{NaN}$ /// - $f(x,\infty,x,p,m)=0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,\infty,x,p,m)=-0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(x,-\infty,x,p,m)=-0.0$ if $x>0.0$ or $x=0.0$ /// - $f(x,-\infty,x,p,m)=0.0$ if $x<0.0$ or $x=-0.0$ /// - $f(0,x,p,m)=0.0$ if $x>0$ /// - $f(0,x,p,m)=-0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); Float::rational_div_float_prec_round_ref_ref(self, other, prec, Nearest).0 } } ================================================ FILE: malachite-float/src/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_nz::natural::LIMB_HIGH_BIT; impl IsPowerOf2 for Float { /// Determines whether a [`Float`] is an integer power of 2. /// /// $f(x) = (\exists n \in \Z : 2^n = x)$. /// /// [`Float`]s that are NaN, infinite, or zero are not powers of 2. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::IsPowerOf2; /// use malachite_base::num::basic::traits::{NaN, One, OneHalf, Two}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_power_of_2(), false); /// /// assert_eq!(Float::ONE.is_power_of_2(), true); /// assert_eq!(Float::TWO.is_power_of_2(), true); /// assert_eq!(Float::ONE_HALF.is_power_of_2(), true); /// assert_eq!(Float::from(1024).is_power_of_2(), true); /// /// assert_eq!(Float::from(3).is_power_of_2(), false); /// assert_eq!(Float::from(1025).is_power_of_2(), false); /// assert_eq!(Float::from(0.1f64).is_power_of_2(), false); /// ``` fn is_power_of_2(&self) -> bool { match self { Self(Finite { sign: true, significand, .. }) => { let mut first = true; for x in significand.limbs().rev() { if first { if x != LIMB_HIGH_BIT { return false; } first = false; } else if x != 0 { return false; } } true } _ => false, } } } pub(crate) fn abs_is_power_of_2(x: &Float) -> bool { match x { Float(Finite { significand, .. }) => { let mut first = true; for x in significand.limbs().rev() { if first { if x != LIMB_HIGH_BIT { return false; } first = false; } else if x != 0 { return false; } } true } _ => false, } } pub(crate) fn float_is_signed_min(f: &Float) -> bool { match f { Float(Finite { sign: false, exponent, significand, .. }) => { if *exponent != T::WIDTH as i32 { return false; } let mut first = true; for x in significand.limbs().rev() { if first { if x != LIMB_HIGH_BIT { return false; } first = false; } else if x != 0 { return false; } } true } _ => false, } } ================================================ FILE: malachite-float/src/arithmetic/ln.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999-2026 Free Software Foundation, Inc. // // Contributed by the Pascaline and Caramba projects, INRIA. // // 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::basic::extended::ExtendedFloat; use crate::{ Float, emulate_float_to_float_fn, emulate_rational_to_float_fn, float_either_zero, float_infinity, float_nan, float_negative_infinity, float_zero, }; use core::cmp::Ordering::{self, *}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ Agm, CeilingLogBase2, IsPowerOf2, Ln, LnAssign, Sign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero as ZeroTrait}; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; use malachite_q::Rational; // The computation of log(x) is done using the formula: if we want p bits of the result, // ``` // pi // log(x) ~ ------------- - m log 2 // 2 AG(1,4 / s) // ``` // where s = x 2^m > 2^(p/2). // // More precisely, if F(x) = int(1 / ln(1 - (1 - x ^ 2) * sin(t) ^ 2), t = 0..pi / 2), then for s >= // 1.26 we have log(s) < F(4 / s) < log(s) * (1 + 4 / s ^ 2) from which we deduce pi / 2 / AG(1, 4 / // s) * (1 - 4 / s ^ 2) < log(s) < pi / 2 / AG(1, 4 / s) so the relative error 4 / s ^ 2 is < 4 / 2 // ^ p i.e. 4 ulps. // // This is mpfr_log from log.c, MPFR 4.2.0. fn ln_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { if *x == 1u32 { return (Float::ZERO, Equal); } assert_ne!(rm, Exact, "Inexact ln"); let x_exp = i64::from(x.get_exponent().unwrap()); // use initial precision about q + 2 * lg(q) + cte let mut working_prec = prec + (prec.ceiling_log_base_2() << 1) + 10; let mut increment = Limb::WIDTH; let mut previous_m = 0; let mut x = x.clone(); loop { // Calculus of m (depends on p) let m = i64::exact_from((working_prec + 3) >> 1) .checked_sub(x_exp) .unwrap(); x <<= m - previous_m; previous_m = m; assert!(x.is_normal()); let tmp2 = Float::pi_prec(working_prec).0 / (Float::ONE.agm( const { Float::const_from_unsigned(4) } .div_prec_round_val_ref(&x, working_prec, Floor) .0, ) << 1u32); let exp2 = tmp2.get_exponent(); let tmp1 = tmp2 - Float::ln_2_prec(working_prec) .0 .mul_prec(Float::from(m), working_prec) .0; if let (Some(exp1), Some(exp2)) = (tmp1.get_exponent(), exp2) { let cancel = u64::saturating_from(exp2 - exp1); // we have 7 ulps of error from the above roundings, 4 ulps from the 4 / s ^ 2 second // order term, plus the canceled bits if float_can_round( tmp1.significand_ref().unwrap(), working_prec.saturating_sub(cancel).saturating_sub(4), prec, rm, ) { return Float::from_float_prec_round(tmp1, prec, rm); } working_prec += cancel + working_prec.ceiling_log_base_2(); } else { working_prec += working_prec.ceiling_log_base_2(); } working_prec += increment; increment = working_prec >> 1; } } // This is mpfr_log from log.c, MPFR 4.2.0. fn ln_prec_round_normal(mut x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { if x == 1u32 { return (Float::ZERO, Equal); } assert_ne!(rm, Exact, "Inexact ln"); let x_exp = i64::from(x.get_exponent().unwrap()); // use initial precision about q + 2 * lg(q) + cte let mut working_prec = prec + (prec.ceiling_log_base_2() << 1) + 10; let mut increment = Limb::WIDTH; let mut previous_m = 0; loop { // Calculus of m (depends on p) let m = i64::exact_from((working_prec + 3) >> 1) .checked_sub(x_exp) .unwrap(); x <<= m - previous_m; previous_m = m; assert!(x.is_normal()); let tmp2 = Float::pi_prec(working_prec).0 / (Float::ONE.agm( const { Float::const_from_unsigned(4) } .div_prec_round_val_ref(&x, working_prec, Floor) .0, ) << 1u32); let exp2 = tmp2.get_exponent(); let tmp1 = tmp2 - Float::ln_2_prec(working_prec) .0 .mul_prec(Float::from(m), working_prec) .0; if let (Some(exp1), Some(exp2)) = (tmp1.get_exponent(), exp2) { let cancel = u64::saturating_from(exp2 - exp1); // we have 7 ulps of error from the above roundings, 4 ulps from the 4 / s ^ 2 second // order term, plus the canceled bits if float_can_round( tmp1.significand_ref().unwrap(), working_prec.saturating_sub(cancel).saturating_sub(4), prec, rm, ) { return Float::from_float_prec_round(tmp1, prec, rm); } working_prec += cancel + working_prec.ceiling_log_base_2(); } else { working_prec += working_prec.ceiling_log_base_2(); } working_prec += increment; increment = working_prec >> 1; } } pub(crate) fn ln_prec_round_normal_extended( x: ExtendedFloat, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if x.exp == 1 && x.x.is_power_of_2() { return (Float::ZERO, Equal); } assert_ne!(rm, Exact, "Inexact ln"); let x_exp = x.exp; // use initial precision about q + 2 * lg(q) + cte let mut working_prec = prec + (prec.ceiling_log_base_2() << 1) + 10; let mut increment = Limb::WIDTH; let mut m = i64::exact_from((working_prec + 3) >> 1) .checked_sub(x.exp) .unwrap(); let mut previous_m = m; let mut x = Float::exact_from(x << m); let mut first = true; loop { if first { first = false; } else { // Calculus of m (depends on p) m = i64::exact_from((working_prec + 3) >> 1) .checked_sub(x_exp) .unwrap(); x <<= m - previous_m; previous_m = m; } assert!(x.is_normal()); let tmp2 = Float::pi_prec(working_prec).0 / (Float::ONE.agm( const { Float::const_from_unsigned(4) } .div_prec_round_val_ref(&x, working_prec, Floor) .0, ) << 1u32); let exp2 = tmp2.get_exponent(); let tmp1 = tmp2 - Float::ln_2_prec(working_prec) .0 .mul_prec(Float::from(m), working_prec) .0; if let (Some(exp1), Some(exp2)) = (tmp1.get_exponent(), exp2) { let cancel = u64::saturating_from(exp2 - exp1); // we have 7 ulps of error from the above roundings, 4 ulps from the 4 / s ^ 2 second // order term, plus the canceled bits if float_can_round( tmp1.significand_ref().unwrap(), working_prec.saturating_sub(cancel).saturating_sub(4), prec, rm, ) { return Float::from_float_prec_round(tmp1, prec, rm); } working_prec += cancel + working_prec.ceiling_log_base_2(); } else { working_prec += working_prec.ceiling_log_base_2(); } working_prec += increment; increment = working_prec >> 1; } } fn ln_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let (x_lo, x_o) = Float::from_rational_prec_round_ref(x, working_prec, Floor); if x_o == Equal { return ln_prec_round_normal(x_lo, prec, rm); } let mut x_hi = x_lo.clone(); x_hi.increment(); let (ln_lo, mut o_lo) = ln_prec_round_normal(x_lo, prec, rm); let (ln_hi, mut o_hi) = ln_prec_round_normal(x_hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && ln_lo == ln_hi { return (ln_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } fn ln_rational_helper_extended(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let (x_lo, x_o) = ExtendedFloat::from_rational_prec_round_ref(x, working_prec, Floor); if x_o == Equal { return ln_prec_round_normal_extended(x_lo, prec, rm); } let mut x_hi = x_lo.clone(); x_hi.increment(); let (ln_lo, mut o_lo) = ln_prec_round_normal_extended(x_lo, prec, rm); let (ln_hi, mut o_hi) = ln_prec_round_normal_extended(x_hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && ln_lo == ln_hi { return (ln_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } impl Float { /// Computes the natural logarithm of a [`Float`], rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] is taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded logarithm is less than, equal /// to, or greater than the exact logarithm. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p+1}$. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=\infty$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(\pm0.0,p,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::ln_prec`] instead. If you /// know that your target precision is the precision of the input, consider using /// [`Float::ln_round`] instead. If both of these things are true, consider using [`Float::ln`] /// instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(5, Floor); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(5, Ceiling); /// assert_eq!(ln.to_string(), "2.4"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(5, Nearest); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(20, Floor); /// assert_eq!(ln.to_string(), "2.302582"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(20, Ceiling); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round(20, Nearest); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match self { Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => { (float_nan!(), Equal) } float_either_zero!() => (float_negative_infinity!(), Equal), float_infinity!() => (float_infinity!(), Equal), _ => ln_prec_round_normal(self, prec, rm), } } /// Computes the natural logarithm of a [`Float`], rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded logarithm is less than, equal /// to, or greater than the exact logarithm. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p+1}$. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=\infty$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(\pm0.0,p,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::ln_prec_ref`] instead. If you /// know that your target precision is the precision of the input, consider using /// [`Float::ln_round_ref`] instead. If both of these things are true, consider using /// `(&Float).ln()`instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(5, Floor); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(5, Ceiling); /// assert_eq!(ln.to_string(), "2.4"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(5, Nearest); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(20, Floor); /// assert_eq!(ln.to_string(), "2.302582"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(20, Ceiling); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_prec_round_ref(20, Nearest); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match self { Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => { (float_nan!(), Equal) } float_either_zero!() => (float_negative_infinity!(), Equal), float_infinity!() => (float_infinity!(), Equal), _ => ln_prec_round_normal_ref(self, prec, rm), } } /// Computes the natural logarithm of a [`Float`], rounding the result to the nearest value of /// the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded logarithm is less than, equal to, or greater than the exact /// logarithm. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=\infty$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(\pm0.0,p,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_prec_round`] instead. If you know that your target precision is the precision of /// the input, consider using [`Float::ln`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_prec(5); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_prec(20); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_prec(self, prec: u64) -> (Self, Ordering) { self.ln_prec_round(prec, Nearest) } /// Computes the natural logarithm of a [`Float`], rounding the result to the nearest value of /// the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded logarithm is less than, equal to, or greater than /// the exact logarithm. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=\infty$ /// - $f(-\infty,p)=\text{NaN}$ /// - $f(\pm0.0,p)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_prec_round_ref`] instead. If you know that your target precision is the /// precision of the input, consider using `(&Float).ln()` instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_prec_ref(5); /// assert_eq!(ln.to_string(), "2.2"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_prec_ref(20); /// assert_eq!(ln.to_string(), "2.302586"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_prec_ref(&self, prec: u64) -> (Self, Ordering) { self.ln_prec_round_ref(prec, Nearest) } /// Computes the natural logarithm of a [`Float`], rounding the result with the specified /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating /// whether the rounded logarithm is less than, equal to, or greater than the exact logarithm. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=\infty$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(\pm0.0,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::ln_prec_round`] instead. /// If you know you'll be using the `Nearest` rounding mode, consider using [`Float::ln`] /// instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_round(Floor); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454684"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_round(Ceiling); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454687"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_round(Nearest); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454684"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn ln_round(self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.ln_prec_round(prec, rm) } /// Computes the natural logarithm of a [`Float`], rounding the result with the specified /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded logarithm is less than, equal to, or greater than the exact /// logarithm. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=\infty$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(\pm0.0,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::ln_prec_round_ref`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// `(&Float).ln()` instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100).0.ln_round_ref(Floor); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454684"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_round_ref(Ceiling); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454687"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::from_unsigned_prec(10u32, 100) /// .0 /// .ln_round_ref(Nearest); /// assert_eq!(ln.to_string(), "2.302585092994045684017991454684"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn ln_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.ln_prec_round_ref(prec, rm) } /// Computes the natural logarithm of a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. An [`Ordering`] is returned, indicating /// whether the rounded logarithm is less than, equal to, or greater than the exact logarithm. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::ln_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::ln_prec_assign`] instead. If /// you know that your target precision is the precision of the input, consider using /// [`Float::ln_round_assign`] instead. If both of these things are true, consider using /// [`Float::ln_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(5, Floor), Less); /// assert_eq!(x.to_string(), "2.2"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "2.4"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(5, Nearest), Less); /// assert_eq!(x.to_string(), "2.2"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(20, Floor), Less); /// assert_eq!(x.to_string(), "2.302582"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(20, Ceiling), Greater); /// assert_eq!(x.to_string(), "2.302586"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_round_assign(20, Nearest), Greater); /// assert_eq!(x.to_string(), "2.302586"); /// ``` #[inline] pub fn ln_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { let mut x = Self::ZERO; swap(self, &mut x); let o; (*self, o) = x.ln_prec_round(prec, rm); o } /// Computes the natural logarithm of a [`Float`] in place, rounding the result to the nearest /// value of the specified precision. An [`Ordering`] is returned, indicating whether the /// rounded logarithm is less than, equal to, or greater than the exact logarithm. Although /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to /// `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::ln_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_prec_round_assign`] instead. If you know that your target precision is the /// precision of the input, consider using [`Float::ln`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_assign(5), Less); /// assert_eq!(x.to_string(), "2.2"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_prec_assign(20), Greater); /// assert_eq!(x.to_string(), "2.302586"); /// ``` #[inline] pub fn ln_prec_assign(&mut self, prec: u64) -> Ordering { self.ln_prec_round_assign(prec, Nearest) } /// Computes the natural logarithm of a [`Float`] in place, rounding the result with the /// specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded /// logarithm is less than, equal to, or greater than the exact logarithm. Although `NaN`s are /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// x \gets \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \|ln{x}|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// /// See the [`Float::ln_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::ln_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::ln_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_round_assign(Floor), Less); /// assert_eq!(x.to_string(), "2.302585092994045684017991454684"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_round_assign(Ceiling), Greater); /// assert_eq!(x.to_string(), "2.302585092994045684017991454687"); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// assert_eq!(x.ln_round_assign(Nearest), Less); /// assert_eq!(x.to_string(), "2.302585092994045684017991454684"); /// ``` #[inline] pub fn ln_round_assign(&mut self, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.ln_prec_round_assign(prec, rm) } /// Computes the natural logarithm of a [`Rational`], rounding the result to the specified /// precision and with the specified rounding mode and returning the result as a [`Float`]. The /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded logarithm is less than, equal to, or greater than the exact logarithm. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |\ln{x}|\rfloor-p+1}$. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |\ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::ln_rational_prec`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor); /// assert_eq!(ln.to_string(), "-0.53"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Nearest); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Floor); /// assert_eq!(ln.to_string(), "-0.510826"); /// assert_eq!(o, Less); /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Ceiling); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::ln_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Nearest); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// ``` #[allow(clippy::needless_pass_by_value)] #[inline] pub fn ln_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) { Self::ln_rational_prec_round_ref(&x, prec, rm) } /// Computes the natural logarithm of a [`Rational`], rounding the result to the specified /// precision and with the specified rounding mode and returning the result as a [`Float`]. The /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded logarithm is less than, equal to, or greater than the exact logarithm. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |\ln{x}|\rfloor-p+1}$. /// - If $\ln{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |\ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::ln_rational_prec_ref`] /// instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor); /// assert_eq!(ln.to_string(), "-0.53"); /// assert_eq!(o, Less); /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Ceiling); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Nearest); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Floor); /// assert_eq!(ln.to_string(), "-0.510826"); /// assert_eq!(o, Less); /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Ceiling); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// /// let (ln, o) = /// Float::ln_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Nearest); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// ``` pub fn ln_rational_prec_round_ref( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { assert_ne!(prec, 0); match x.sign() { Equal => return (float_negative_infinity!(), Equal), Less => return (float_nan!(), Equal), Greater => {} } if *x == 1u32 { return (float_zero!(), Equal); } assert_ne!(rm, Exact, "Inexact ln"); let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); if x_exp >= Self::MAX_EXPONENT - 1 || x_exp <= Self::MIN_EXPONENT + 1 { ln_rational_helper_extended(x, prec, rm) } else { ln_rational_helper(x, prec, rm) } } /// Computes the natural logarithm of a [`Rational`], rounding the result to the nearest value /// of the specified precision and returning the result as a [`Float`]. The [`Rational`] is /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded logarithm /// is less than, equal to, or greater than the exact logarithm. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// |\ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_rational_prec_round`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::ln_rational_prec(Rational::from_unsigneds(3u8, 5), 5); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::ln_rational_prec(Rational::from_unsigneds(3u8, 5), 20); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) { Self::ln_rational_prec_round(x, prec, Nearest) } /// Computes the natural logarithm of a [`Rational`], rounding the result to the nearest value /// of the specified precision and returning the result as a [`Float`]. The [`Rational`] is /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded /// logarithm is less than, equal to, or greater than the exact logarithm. Although `NaN`s are /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// |\ln{x}|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_rational_prec_round_ref`] instead. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (ln, o) = Float::ln_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5); /// assert_eq!(ln.to_string(), "-0.5"); /// assert_eq!(o, Greater); /// /// let (ln, o) = Float::ln_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20); /// assert_eq!(ln.to_string(), "-0.510825"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn ln_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) { Self::ln_rational_prec_round_ref(x, prec, Nearest) } } impl Ln for Float { type Output = Self; /// Computes the natural logarithm of a [`Float`], taking it by value. /// /// If the output has a precision, it is the precision of the input. If the logarithm is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=\infty$ /// - $f(-\infty)=\text{NaN}$ /// - $f(\pm0.0)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::ln_prec`] /// instead. If you want to specify the output precision, consider using [`Float::ln_round`]. If /// you want both of these things, consider using [`Float::ln_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Ln; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!(Float::NAN.ln().is_nan()); /// assert_eq!(Float::INFINITY.ln(), Float::INFINITY); /// assert!(Float::NEGATIVE_INFINITY.ln().is_nan()); /// assert_eq!( /// Float::from_unsigned_prec(10u32, 100).0.ln().to_string(), /// "2.302585092994045684017991454684" /// ); /// assert!(Float::from_signed_prec(-10, 100).0.ln().is_nan()); /// ``` #[inline] fn ln(self) -> Self { let prec = self.significant_bits(); self.ln_prec_round(prec, Nearest).0 } } impl Ln for &Float { type Output = Float; /// Computes the natural logarithm of a [`Float`], taking it by reference. /// /// If the output has a precision, it is the precision of the input. If the logarithm is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=\infty$ /// - $f(-\infty)=\text{NaN}$ /// - $f(\pm0.0)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_prec_ref`] instead. If you want to specify the output precision, consider using /// [`Float::ln_round_ref`]. If you want both of these things, consider using /// [`Float::ln_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Ln; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!((&Float::NAN).ln().is_nan()); /// assert_eq!((&Float::INFINITY).ln(), Float::INFINITY); /// assert!((&Float::NEGATIVE_INFINITY).ln().is_nan()); /// assert_eq!( /// (&Float::from_unsigned_prec(10u32, 100).0).ln().to_string(), /// "2.302585092994045684017991454684" /// ); /// assert!((&Float::from_signed_prec(-10, 100).0).ln().is_nan()); /// ``` #[inline] fn ln(self) -> Float { let prec = self.significant_bits(); self.ln_prec_round_ref(prec, Nearest).0 } } impl LnAssign for Float { /// Computes the natural logarithm of a [`Float`] in place. /// /// If the output has a precision, it is the precision of the input. If the logarithm is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The logarithm of any nonzero negative number is `NaN`. /// /// $$ /// x\gets = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \ln{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// See the [`Float::ln`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::ln_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::ln_round_assign`]. If you want both of these things, consider using /// [`Float::ln_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LnAssign; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::NAN; /// x.ln_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x.ln_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.ln_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::from_unsigned_prec(10u32, 100).0; /// x.ln_assign(); /// assert_eq!(x.to_string(), "2.302585092994045684017991454684"); /// /// let mut x = Float::from_signed_prec(-10, 100).0; /// x.ln_assign(); /// assert!(x.is_nan()); /// ``` #[inline] fn ln_assign(&mut self) { let prec = self.significant_bits(); self.ln_prec_round_assign(prec, Nearest); } } /// Computes the natural logarithm of a primitive float. Using this function is more accurate than /// using the default `log` function or the one provided by `libm`. /// /// The reciprocal logarithm of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = \ln x+\varepsilon. /// $$ /// - If $\ln x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 \ln x\rfloor-p}$, /// where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53 if `T` is a /// [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=\infty$ /// - $f(-\infty)=\text{NaN}$ /// - $f(\pm0.0)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::ln::primitive_float_ln; /// /// assert!(primitive_float_ln(f32::NAN).is_nan()); /// assert_eq!( /// NiceFloat(primitive_float_ln(f32::INFINITY)), /// NiceFloat(f32::INFINITY) /// ); /// assert!(primitive_float_ln(f32::NEGATIVE_INFINITY).is_nan()); /// assert_eq!(NiceFloat(primitive_float_ln(10.0f32)), NiceFloat(2.3025851)); /// assert!(primitive_float_ln(-10.0f32).is_nan()); /// ``` #[inline] #[allow(clippy::type_repetition_in_bounds)] pub fn primitive_float_ln(x: T) -> T where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_float_to_float_fn(Float::ln_prec, x) } /// Computes the natural logarithm of a [`Rational`], returning a primitive float result. /// /// If the logarithm is equidistant from two primitive floats, the primitive float with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` rounding /// mode. /// /// The logarithm of any negative number is `NaN`. /// /// $$ /// f(x) = \ln{x}+\varepsilon. /// $$ /// - If $\ln{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\ln{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\ln{x}|\rfloor-p}$, /// where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53 if `T` is a /// [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(0)=-\infty$ /// /// Neither overflow nor underflow is possible. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeInfinity, Zero}; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::ln::primitive_float_ln_rational; /// use malachite_q::Rational; /// /// assert_eq!( /// NiceFloat(primitive_float_ln_rational::(&Rational::ZERO)), /// NiceFloat(f64::NEGATIVE_INFINITY) /// ); /// assert_eq!( /// NiceFloat(primitive_float_ln_rational::( /// &Rational::from_unsigneds(1u8, 3) /// )), /// NiceFloat(-1.0986122886681098) /// ); /// assert_eq!( /// NiceFloat(primitive_float_ln_rational::(&Rational::from(10000))), /// NiceFloat(9.210340371976184) /// ); /// assert_eq!( /// NiceFloat(primitive_float_ln_rational::(&Rational::from(-10000))), /// NiceFloat(f64::NAN) /// ); /// ``` #[inline] #[allow(clippy::type_repetition_in_bounds)] pub fn primitive_float_ln_rational(x: &Rational) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_rational_to_float_fn(Float::ln_rational_prec_ref, x) } ================================================ FILE: malachite-float/src/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . /// Absolute value of [`Float`](super::Float)s. pub mod abs; /// Addition of [`Float`](super::Float)s, and of [`Float`](super::Float)s with /// [`Rational`](malachite_q::Rational)s. pub mod add; /// Taking the AGM (arithmetic-geometric mean) of two [`Float`](super::Float)s, and of /// [`Float`](super::Float)s with [`Rational`](malachite_q::Rational)s. pub mod agm; /// Division of [`Float`](super::Float)s, of [`Float`](super::Float)s by /// [`Rational`](malachite_q::Rational)s, and of [`Rational`](malachite_q::Rational)s by /// [`Float`](super::Float)s. pub mod div; /// An implementation of [`IsPowerOf2`](malachite_base::num::arithmetic::traits::IsPowerOf2), a /// trait for determining whether a number is an integer power of 2. pub mod is_power_of_2; /// [`Ln`](malachite_base::num::arithmetic::traits::Ln) and /// [`SqrtAssign`](malachite_base::num::arithmetic::traits::LnAssign), traits for computing the /// natural logarithm of [`Float`](super::Float)s. pub mod ln; /// Multiplication of [`Float`](super::Float)s, and of [`Float`](super::Float)s with /// [`Rational`](malachite_q::Rational)s. pub mod mul; /// Negation of [`Float`](super::Float)s. pub mod neg; /// Implementations of [`PowerOf2`](malachite_base::num::arithmetic::traits::PowerOf2), a trait for /// computing a power of 2. pub mod power_of_2; /// Implementations of [`Reciprocal`](malachite_base::num::arithmetic::traits::Reciprocal) and /// [`ReciprocalAssign`](malachite_base::num::arithmetic::traits::ReciprocalAssign), traits for /// computing the reciprocal of a number. pub mod reciprocal; /// [`ReciprocalSqrt`](malachite_base::num::arithmetic::traits::ReciprocalSqrt) and /// [`ReciprocalSqrtAssign`](malachite_base::num::arithmetic::traits::ReciprocalSqrtAssign), traits /// for computing the reciprocal of the square root of [`Float`](super::Float)s. pub mod reciprocal_sqrt; /// Left-shifting a [`Float`](super::Float) (multiplying it by a power of 2). /// /// # shl /// ``` /// use malachite_base::num::basic::traits::{Infinity, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::ZERO << 10, 0); /// assert_eq!(Float::INFINITY << 10, Float::INFINITY); /// assert_eq!( /// (Float::from(std::f64::consts::PI) << 10u8).to_string(), /// "3216.990877275948" /// ); /// assert_eq!( /// (Float::from(std::f64::consts::PI) << -10i8).to_string(), /// "0.003067961575771282" /// ); /// /// assert_eq!(&Float::ZERO << 10, 0); /// assert_eq!(&Float::INFINITY << 10, Float::INFINITY); /// assert_eq!( /// (&Float::from(std::f64::consts::PI) << 10u8).to_string(), /// "3216.990877275948" /// ); /// assert_eq!( /// (&Float::from(std::f64::consts::PI) << -10i8).to_string(), /// "0.003067961575771282" /// ); /// ``` /// /// # shl_assign /// ``` /// use malachite_base::num::basic::traits::{Infinity, Zero}; /// use malachite_float::Float; /// /// let mut x = Float::ZERO; /// x <<= 10; /// assert_eq!(x, 0); /// /// let mut x = Float::INFINITY; /// x <<= 10; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(std::f64::consts::PI); /// x <<= 10; /// assert_eq!(x.to_string(), "3216.990877275948"); /// /// let mut x = Float::from(std::f64::consts::PI); /// x <<= -10; /// assert_eq!(x.to_string(), "0.003067961575771282"); /// ``` pub mod shl; /// Implementations of [`ShlRound`](malachite_base::num::arithmetic::traits::ShlRound) and /// [`ShlRoundAssign`](malachite_base::num::arithmetic::traits::ShlRoundAssign), traits for /// multiplying a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). For [`Float`](super::Float)s, /// rounding is only necessary in the cases of overflow and underflow. /// /// # shl_prec_round /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round(10u8, 10, Nearest); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round(-10i8, 10, Nearest); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round(u32::MAX, 10, Floor); /// assert_eq!(shifted.to_string(), "too_big"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round(u32::MAX, 10, Ceiling); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round_ref(10u8, 10, Nearest); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round_ref(-10i8, 10, Nearest); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round_ref(u32::MAX, 10, Floor); /// assert_eq!(shifted.to_string(), "too_big"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_round_ref(u32::MAX, 10, Ceiling); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// ``` /// /// # shl_prec_round_assign /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_round_assign(10u8, 10, Nearest), Less); /// assert_eq!(x.to_string(), "3216.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_round_assign(-10i8, 10, Nearest), Less); /// assert_eq!(x.to_string(), "0.003067"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_round_assign(u32::MAX, 10, Floor), Less); /// assert_eq!(x.to_string(), "too_big"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_round_assign(u32::MAX, 10, Ceiling), Greater); /// assert_eq!(x.to_string(), "Infinity"); /// ``` /// /// # shl_prec /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec(10u8, 10); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec(-10i8, 10); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec(u32::MAX, 10); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_ref(10u8, 10); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_ref(-10i8, 10); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_prec_ref(u32::MAX, 10); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// ``` /// /// # shl_prec_assign /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_assign(10u8, 10), Less); /// assert_eq!(x.to_string(), "3216.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_assign(-10i8, 10), Less); /// assert_eq!(x.to_string(), "0.003067"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_prec_assign(u32::MAX, 10), Greater); /// assert_eq!(x.to_string(), "Infinity"); /// ``` /// /// # shl_round /// ``` /// use malachite_base::num::arithmetic::traits::ShlRound; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_round(10u8, Nearest); /// assert_eq!(shifted.to_string(), "3216.990877275948"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_round(-10i8, Nearest); /// assert_eq!(shifted.to_string(), "0.003067961575771282"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_round(u32::MAX, Floor); /// assert_eq!(shifted.to_string(), "too_big"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shl_round(u32::MAX, Ceiling); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shl_round(10u8, Nearest); /// assert_eq!(shifted.to_string(), "3216.990877275948"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shl_round(-10i8, Nearest); /// assert_eq!(shifted.to_string(), "0.003067961575771282"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shl_round(u32::MAX, Floor); /// assert_eq!(shifted.to_string(), "too_big"); /// assert_eq!(o, Less); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shl_round(u32::MAX, Ceiling); /// assert_eq!(shifted.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// ``` /// /// # shl_round_assign /// ``` /// use malachite_base::num::arithmetic::traits::ShlRoundAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_round_assign(10u8, Nearest), Equal); /// assert_eq!(x.to_string(), "3216.990877275948"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_round_assign(-10i8, Nearest), Equal); /// assert_eq!(x.to_string(), "0.003067961575771282"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_round_assign(u32::MAX, Floor), Less); /// assert_eq!(x.to_string(), "too_big"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shl_round_assign(u32::MAX, Ceiling), Greater); /// assert_eq!(x.to_string(), "Infinity"); /// ``` pub mod shl_round; /// Right-shifting a [`Float`](super::Float) (dividing it by a power of 2). /// /// # shr /// ``` /// use malachite_base::num::basic::traits::{Infinity, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::ZERO >> 10, 0); /// assert_eq!(Float::INFINITY >> 10, Float::INFINITY); /// assert_eq!( /// (Float::from(std::f64::consts::PI) >> 10u8).to_string(), /// "0.003067961575771282" /// ); /// assert_eq!( /// (Float::from(std::f64::consts::PI) >> -10i8).to_string(), /// "3216.990877275948" /// ); /// /// assert_eq!(&Float::ZERO >> 10, 0); /// assert_eq!(&Float::INFINITY >> 10, Float::INFINITY); /// assert_eq!( /// (&Float::from(std::f64::consts::PI) >> 10u8).to_string(), /// "0.003067961575771282" /// ); /// assert_eq!( /// (&Float::from(std::f64::consts::PI) >> -10i8).to_string(), /// "3216.990877275948" /// ); /// ``` /// /// # shr_assign /// ``` /// use malachite_base::num::basic::traits::{Infinity, Zero}; /// use malachite_float::Float; /// /// let mut x = Float::ZERO; /// x >>= 10; /// assert_eq!(x, 0); /// /// let mut x = Float::INFINITY; /// x >>= 10; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(std::f64::consts::PI); /// x >>= 10; /// assert_eq!(x.to_string(), "0.003067961575771282"); /// /// let mut x = Float::from(std::f64::consts::PI); /// x >>= -10; /// assert_eq!(x.to_string(), "3216.990877275948"); /// ``` pub mod shr; /// Implementations of [`ShlRound`](malachite_base::num::arithmetic::traits::ShrRound) and /// [`ShrRoundAssign`](malachite_base::num::arithmetic::traits::ShrRoundAssign), traits for dividing /// a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). For [`Float`](super::Float)s, /// rounding is only necessary in the cases of overflow and underflow. /// /// # shr_prec_round /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round(10u8, 10, Nearest); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round(-10i8, 10, Nearest); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round(u32::MAX, 10, Floor); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round(u32::MAX, 10, Ceiling); /// assert_eq!(shifted.to_string(), "too_small"); /// assert_eq!(o, Greater); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round_ref(10u8, 10, Nearest); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round_ref(-10i8, 10, Nearest); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round_ref(u32::MAX, 10, Floor); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_round_ref(u32::MAX, 10, Ceiling); /// assert_eq!(shifted.to_string(), "too_small"); /// assert_eq!(o, Greater); /// ``` /// /// # shr_prec_round_assign /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_round_assign(10u8, 10, Nearest), Less); /// assert_eq!(x.to_string(), "0.003067"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_round_assign(-10i8, 10, Nearest), Less); /// assert_eq!(x.to_string(), "3216.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_round_assign(u32::MAX, 10, Floor), Less); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_round_assign(u32::MAX, 10, Ceiling), Greater); /// assert_eq!(x.to_string(), "too_small"); /// ``` /// /// # shr_prec /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec(10u8, 10); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec(-10i8, 10); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec(u32::MAX, 10); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_ref(10u8, 10); /// assert_eq!(shifted.to_string(), "0.003067"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_ref(-10i8, 10); /// assert_eq!(shifted.to_string(), "3216.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_prec_ref(u32::MAX, 10); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// ``` /// /// # shr_prec_assign /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_assign(10u8, 10), Less); /// assert_eq!(x.to_string(), "0.003067"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_assign(-10i8, 10), Less); /// assert_eq!(x.to_string(), "3216.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_prec_assign(u32::MAX, 10), Less); /// assert_eq!(x.to_string(), "0.0"); /// ``` /// /// # shr_round /// ``` /// use malachite_base::num::arithmetic::traits::ShrRound; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_round(10u8, Nearest); /// assert_eq!(shifted.to_string(), "0.003067961575771282"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_round(-10i8, Nearest); /// assert_eq!(shifted.to_string(), "3216.990877275948"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_round(u32::MAX, Floor); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = Float::from(std::f64::consts::PI).shr_round(u32::MAX, Ceiling); /// assert_eq!(shifted.to_string(), "too_small"); /// assert_eq!(o, Greater); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shr_round(10u8, Nearest); /// assert_eq!(shifted.to_string(), "0.003067961575771282"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shr_round(-10i8, Nearest); /// assert_eq!(shifted.to_string(), "3216.990877275948"); /// assert_eq!(o, Equal); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shr_round(u32::MAX, Floor); /// assert_eq!(shifted.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (shifted, o) = (&Float::from(std::f64::consts::PI)).shr_round(u32::MAX, Ceiling); /// assert_eq!(shifted.to_string(), "too_small"); /// assert_eq!(o, Greater); /// ``` /// /// # shr_round_assign /// ``` /// use malachite_base::num::arithmetic::traits::ShrRoundAssign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_round_assign(10u8, Nearest), Equal); /// assert_eq!(x.to_string(), "0.003067961575771282"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_round_assign(-10i8, Nearest), Equal); /// assert_eq!(x.to_string(), "3216.990877275948"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_round_assign(u32::MAX, Floor), Less); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.shr_round_assign(u32::MAX, Ceiling), Greater); /// assert_eq!(x.to_string(), "too_small"); /// ``` pub mod shr_round; /// An implementation of [`Sign`](malachite_base::num::arithmetic::traits::Sign), a trait for /// determining the sign of a number. pub mod sign; /// [`Sqrt`](malachite_base::num::arithmetic::traits::Sqrt) and /// [`SqrtAssign`](malachite_base::num::arithmetic::traits::SqrtAssign), traits for computing the /// square root of [`Float`](super::Float)s. pub mod sqrt; /// Squaring of [`Float`](super::Float)s. pub mod square; /// Subtraction of [`Float`](super::Float)s, of [`Float`](super::Float)s by /// [`Rational`](malachite_q::Rational)s, and of [`Rational`](malachite_q::Rational)s by /// [`Float`](super::Float)s. pub mod sub; ================================================ FILE: malachite-float/src/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::conversion::from_natural::{from_natural_zero_exponent, from_natural_zero_exponent_ref}; use crate::{ Float, float_either_infinity, float_either_zero, float_infinity, float_nan, float_negative_infinity, float_negative_zero, float_zero, }; use core::cmp::{ Ordering::{self, *}, max, }; use core::mem::swap; use core::ops::{Mul, MulAssign}; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, FloorLogBase2, IsPowerOf2, NegAssign, Sign, }; use malachite_base::num::basic::traits::{NegativeZero, Zero as ZeroTrait}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_mul::{ mul_float_significands_in_place, mul_float_significands_in_place_ref, mul_float_significands_ref_ref, }; use malachite_q::Rational; const MUL_RATIONAL_THRESHOLD: u64 = 50; fn mul_rational_prec_round_assign_naive( x: &mut Float, y: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *x, y) { (float_nan!(), _) => Equal, (Float(Infinity { sign }), y) => { match y.sign() { Equal => *x = float_nan!(), Greater => {} Less => { sign.not_assign(); } }; Equal } (Float(Zero { sign }), y) => { if y < 0 { sign.not_assign(); }; Equal } (x, y) => { let not_sign = *x < 0; let mut z = Float::ZERO; swap(x, &mut z); let (mut product, o) = Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm); if product == 0u32 && not_sign { product.neg_assign(); } *x = product; o } } } fn mul_rational_prec_round_assign_naive_ref( x: &mut Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *x, y) { (float_nan!(), _) => Equal, (Float(Infinity { sign }), y) => { match y.sign() { Equal => *x = float_nan!(), Greater => {} Less => { sign.not_assign(); } }; Equal } (Float(Zero { sign }), y) => { if *y < 0 { sign.not_assign(); }; Equal } (x, y) => { let not_sign = *x < 0; let mut z = Float::ZERO; swap(x, &mut z); let (mut product, o) = Float::from_rational_prec_round(Rational::exact_from(z) * y, prec, rm); if product == 0u32 && not_sign { product.neg_assign(); } *x = product; o } } } pub_test! {mul_rational_prec_round_naive( mut x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = mul_rational_prec_round_assign_naive(&mut x, y, prec, rm); (x, o) }} pub_test! {mul_rational_prec_round_naive_val_ref( mut x: Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = mul_rational_prec_round_assign_naive_ref(&mut x, y, prec, rm); (x, o) }} pub_test! {mul_rational_prec_round_naive_ref_val( x: &Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) => (float_nan!(), Equal), (Float(Infinity { sign }), y) => ( match y.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign: *sign }), Less => Float(Infinity { sign: !*sign }), }, Equal, ), (Float(Zero { sign }), y) => ( if y >= 0u32 { Float(Zero { sign: *sign }) } else { Float(Zero { sign: !*sign }) }, Equal, ), (x, y) => { let (mut product, o) = Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm); if product == 0u32 && *x < 0 { product.neg_assign(); } (product, o) } } }} pub_test! {mul_rational_prec_round_naive_ref_ref( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) => (float_nan!(), Equal), (Float(Infinity { sign }), y) => ( match y.sign() { Equal => float_nan!(), Greater => Float(Infinity { sign: *sign }), Less => Float(Infinity { sign: !*sign }), }, Equal, ), (Float(Zero { sign }), y) => ( if *y >= 0u32 { Float(Zero { sign: *sign }) } else { Float(Zero { sign: !*sign }) }, Equal, ), (x, y) => { let (mut product, o) = Float::from_rational_prec_round(Rational::exact_from(x) * y, prec, rm); if product == 0u32 && *x < 0 { product.neg_assign(); } (product, o) } } }} fn mul_rational_prec_round_assign_direct( x: &mut Float, y: Rational, prec: u64, mut rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); if y == 0u32 { *x = if *x > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }; return Equal; } let sign = y >= 0; let (n, d) = y.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let o = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_assign(i128::from(log_n) - i128::from(log_d), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); *x >>= x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent(n), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(log_d) + 1, prec, rm, o, ) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); *x >>= x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent(d), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(log_n) - i128::from(d_exp) - 1, prec, rm, o, ) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); *x >>= x_exp; x.mul_prec_round_assign(n, mul_prec, Floor); let o = x.div_prec_round_assign(d, prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ) } }; if sign { o } else { x.neg_assign(); o.reverse() } } fn mul_rational_prec_round_assign_direct_ref( x: &mut Float, y: &Rational, prec: u64, mut rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); if *y == 0u32 { *x = if *x > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }; return Equal; } let sign = *y >= 0; let (n, d) = y.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let o = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_assign(i128::from(log_n) - i128::from(log_d), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); *x >>= x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent_ref(n), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(log_d) + 1, prec, rm, o, ) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); *x >>= x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent_ref(d), prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(log_n) - i128::from(d_exp) - 1, prec, rm, o, ) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); *x >>= x_exp; x.mul_prec_round_assign(n, mul_prec, Floor); let o = x.div_prec_round_assign(d, prec, rm); x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ) } }; if sign { o } else { x.neg_assign(); o.reverse() } } pub_test! {mul_rational_prec_round_direct( mut x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = mul_rational_prec_round_assign_direct(&mut x, y, prec, rm); (x, o) }} pub_test! {mul_rational_prec_round_direct_val_ref( mut x: Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let o = mul_rational_prec_round_assign_direct_ref(&mut x, y, prec, rm); (x, o) }} pub_test! {mul_rational_prec_round_direct_ref_val( x: &Float, y: Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if y == 0u32 { return ( if *x > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = y >= 0; let (n, d) = y.into_numerator_and_denominator(); if !sign { rm.neg_assign(); } let (product, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_ref(i128::from(log_n) - i128::from(log_d), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut x = x >> x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent(n), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(log_d) + 1, prec, rm, o, ); (x, o) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut x = x >> x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent(d), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(log_n) - i128::from(d_exp) - 1, prec, rm, o, ); (x, o) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent(n); let d = from_natural_zero_exponent(d); let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); let mut x = x >> x_exp; x.mul_prec_round_assign(n, mul_prec, Floor); let o = x.div_prec_round_assign(d, prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (x, o) } }; if sign { (product, o) } else { (-product, o.reverse()) } }} pub_test! {mul_rational_prec_round_direct_ref_ref( x: &Float, y: &Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if *y == 0u32 { return ( if *x > 0u32 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal, ); } let sign = *y >= 0; let (n, d) = y.numerator_and_denominator_ref(); if !sign { rm.neg_assign(); } let (product, o) = match (n.checked_log_base_2(), d.checked_log_base_2()) { (Some(log_n), Some(log_d)) => { x.shl_prec_round_ref(i128::from(log_n) - i128::from(log_d), prec, rm) } (None, Some(log_d)) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let mut x = x >> x_exp; let o = x.mul_prec_round_assign(from_natural_zero_exponent_ref(n), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(log_d) + 1, prec, rm, o, ); (x, o) } (Some(log_n), None) => { let x_exp = x.get_exponent().unwrap(); let d_exp = d.floor_log_base_2(); let mut x = x >> x_exp; let o = x.div_prec_round_assign(from_natural_zero_exponent_ref(d), prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(log_n) - i128::from(d_exp) - 1, prec, rm, o, ); (x, o) } (None, None) => { let x_exp = x.get_exponent().unwrap(); let n_exp = n.floor_log_base_2(); let d_exp = d.floor_log_base_2(); let n = from_natural_zero_exponent_ref(n); let d = from_natural_zero_exponent_ref(d); let mul_prec = x.get_min_prec().unwrap_or(1) + n.significant_bits(); let mut x = x >> x_exp; x.mul_prec_round_assign(n, mul_prec, Floor); let o = x.div_prec_round_assign(d, prec, rm); let o = x.shl_prec_round_assign_helper( i128::from(x_exp) + i128::from(n_exp) - i128::from(d_exp), prec, rm, o, ); (x, o) } }; if sign { (product, o) } else { (-product, o.reverse()) } }} impl Float { /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded product is less than, equal to, or greater than the /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.mul_prec_round_assign(other, prec, rm); (self, o) } /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is are taken by value and the second by /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.mul_prec_round_assign_ref(other, prec, rm); (self, o) } /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is are taken by reference and the second by /// value. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = other.mul_prec_round_assign_ref(self, prec, rm); (other, o) } /// Multiplies two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded product is less than, equal to, or greater than the /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\pm\infty,\pm0.0,p,m)=f(\pm0.0,\pm\infty,p,m) = /// \text{NaN}$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p,m)=f(x,-\infty,p,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(0.0,x,p,m)=f(x,0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or /// $x>0.0$ /// - $f(-0.0,x,p,m)=f(x,-0.0,p,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or /// $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_zero!()) | (float_either_zero!(), float_either_infinity!()) => (float_nan!(), Equal), ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => ( Self(Infinity { sign: x_sign == y_sign, }), Equal, ), ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => ( Self(Zero { sign: x_sign == y_sign, }), Equal, ), ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), ) => { let sign = x_sign == y_sign; let exp_sum = x_exp + y_exp; if exp_sum - 1 > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp_sum < Self::MIN_EXPONENT - 1 { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Floor | Down | Nearest) => (float_zero!(), Less), (true, _) => (Self::min_positive_value_prec(prec), Greater), (false, Ceiling | Down | Nearest) => (float_negative_zero!(), Greater), (false, _) => (-Self::min_positive_value_prec(prec), Less), }; } let (product, exp_offset, o) = mul_float_significands_ref_ref( x, *x_prec, y, *y_prec, prec, if sign { rm } else { -rm }, ); let exp = exp_sum.checked_add(exp_offset).unwrap(); if exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } else if exp < Self::MIN_EXPONENT { return if rm == Nearest && exp == Self::MIN_EXPONENT - 1 && (o == Less || !product.is_power_of_2()) { if sign { (Self::min_positive_value_prec(prec), Greater) } else { (-Self::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), (true, _) => (float_zero!(), Less), (false, Floor | Up) => (-Self::min_positive_value_prec(prec), Less), (false, _) => (float_negative_zero!(), Greater), } }; } ( Self(Finite { sign, exponent: exp, precision: prec, significand: product, }), if sign { o } else { o.reverse() }, ) } } } /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified /// precision. Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating /// whether the rounded product is less than, equal to, or greater than the exact product. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) = /// \text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$ /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_prec_round(other, prec, Nearest) } /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified /// precision. The first [`Float`] is taken by value and the second by reference. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) = /// \text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$ /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_prec_round_val_ref(other, prec, Nearest) } /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified /// precision. The first [`Float`] is taken by reference and the second by value. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) = /// \text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$ /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_prec_round_ref_val(other, prec, Nearest) } /// Multiplies two [`Float`]s, rounding the result to the nearest value of the specified /// precision. Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded product is less than, equal to, or greater than the exact /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns /// a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\pm\infty,\pm0.0,p)=f(\pm0.0,\pm\infty,p) = /// \text{NaN}$ /// - $f(\infty,x,p)=f(x,\infty,p)=\infty$ if $x>0.0$ /// - $f(\infty,x,p)=f(x,\infty,p)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,p)=f(x,-\infty,p)=\infty$ if $x<0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,p)=f(x,0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,p)=f(x,-0.0,p)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_prec_round_ref_ref(other, prec, Nearest) } /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded product is less than, equal to, or greater than the exact product. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round(other, prec, rm) } /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by value and the second by reference. An [`Ordering`] is also returned, /// indicating whether the rounded product is less than, equal to, or greater than the exact /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns /// a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_val_ref(other, prec, rm) } /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. The first /// [`Float`] is taken by reference and the second by value. An [`Ordering`] is also returned, /// indicating whether the rounded product is less than, equal to, or greater than the exact /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function returns /// a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_ref_val(other, prec, rm) } /// Multiplies two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded product is less than, equal to, or greater than the exact product. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\pm\infty,\pm0.0,m)=f(\pm0.0,\pm\infty,m) = /// \text{NaN}$ /// - $f(\infty,x,m)=f(x,\infty,m)=\infty$ if $x>0.0$ /// - $f(\infty,x,m)=f(x,\infty,m)=-\infty$ if $x<0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=-\infty$ if $x>0.0$ /// - $f(-\infty,x,m)=f(x,-\infty,m)=\infty$ if $x<0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x,m)=f(x,0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x,m)=f(x,-0.0,m)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_ref_ref(other, prec, rm) } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is /// taken by value. An [`Ordering`] is returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_assign`] instead. If /// you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::mul_round_assign`] instead. If both of these things are true, /// consider using `*=` instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 5, Floor), /// Less /// ); /// assert_eq!(product.to_string(), "8.5"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(product.to_string(), "9.0"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(product.to_string(), "8.5"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(product.to_string(), "8.53973"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(product.to_string(), "8.53975"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign(Float::from(E), 20, Nearest), /// Less /// ); /// assert_eq!(product.to_string(), "8.53973"); /// ``` #[inline] pub fn mul_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_zero!()) | (float_either_zero!(), float_either_infinity!()) => { *self = float_nan!(); Equal } ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => { *self = Self(Infinity { sign: *x_sign == y_sign, }); Equal } ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => { *self = Self(Zero { sign: *x_sign == y_sign, }); Equal } ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: mut y, }), ) => { let sign = *x_sign == y_sign; let exp_sum = *x_exp + y_exp; if exp_sum - 1 > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if exp_sum < Self::MIN_EXPONENT - 1 { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Floor | Down | Nearest) => { *self = float_zero!(); Less } (true, _) => { *self = Self::min_positive_value_prec(prec); Greater } (false, Ceiling | Down | Nearest) => { *self = float_negative_zero!(); Greater } (false, _) => { *self = -Self::min_positive_value_prec(prec); Less } }; } let (exp_offset, o) = mul_float_significands_in_place( x, *x_prec, &mut y, y_prec, prec, if sign { rm } else { -rm }, ); *x_exp = exp_sum.checked_add(exp_offset).unwrap(); if *x_exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if *x_exp < Self::MIN_EXPONENT { return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } *x_sign = sign; *x_prec = prec; if sign { o } else { o.reverse() } } } } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is /// taken by reference. An [`Ordering`] is returned, indicating whether the rounded product is /// less than, equal to, or greater than the exact product. Although `NaN`s are not comparable /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns /// `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::mul_prec_assign_ref`] /// instead. If you know that your target precision is the maximum of the precisions of the two /// inputs, consider using [`Float::mul_round_assign_ref`] instead. If both of these things are /// true, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Floor), /// Less /// ); /// assert_eq!(product.to_string(), "8.5"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(product.to_string(), "9.0"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(product.to_string(), "8.5"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(product.to_string(), "8.53973"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(product.to_string(), "8.53975"); /// /// let mut product = Float::from(PI); /// assert_eq!( /// product.mul_prec_round_assign_ref(&Float::from(E), 20, Nearest), /// Less /// ); /// assert_eq!(product.to_string(), "8.53973"); /// ``` #[inline] pub fn mul_prec_round_assign_ref( &mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_zero!()) | (float_either_zero!(), float_either_infinity!()) => { *self = float_nan!(); Equal } ( Self(Infinity { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Infinity { sign: y_sign })) => { *self = Self(Infinity { sign: *x_sign == *y_sign, }); Equal } ( Self(Zero { sign: x_sign }), Self(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Self(Finite { sign: x_sign, .. }), Self(Zero { sign: y_sign })) => { *self = Self(Zero { sign: *x_sign == *y_sign, }); Equal } ( Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }), Self(Finite { sign: y_sign, exponent: y_exp, precision: y_prec, significand: y, }), ) => { let sign = x_sign == y_sign; let exp_sum = *x_exp + y_exp; if exp_sum - 1 > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if exp_sum < Self::MIN_EXPONENT - 1 { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Floor | Down | Nearest) => { *self = float_zero!(); Less } (true, _) => { *self = Self::min_positive_value_prec(prec); Greater } (false, Ceiling | Down | Nearest) => { *self = float_negative_zero!(); Greater } (false, _) => { *self = -Self::min_positive_value_prec(prec); Less } }; } let (exp_offset, o) = mul_float_significands_in_place_ref( x, *x_prec, y, *y_prec, prec, if sign { rm } else { -rm }, ); *x_exp = exp_sum.checked_add(exp_offset).unwrap(); if *x_exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } else if *x_exp < Self::MIN_EXPONENT { return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { if sign { *self = Self::min_positive_value_prec(prec); Greater } else { *self = -Self::min_positive_value_prec(prec); Less } } else { match (sign, rm) { (_, Exact) => panic!("Inexact Float multiplication"), (true, Ceiling | Up) => { *self = Self::min_positive_value_prec(prec); Greater } (true, _) => { *self = float_zero!(); Less } (false, Floor | Up) => { *self = -Self::min_positive_value_prec(prec); Less } (false, _) => { *self = float_negative_zero!(); Greater } } }; } *x_sign = sign; *x_prec = prec; if sign { o } else { o.reverse() } } } } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of /// the specified precision. The [`Float`] on the right-hand side is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_prec_round_assign`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_prec_assign(Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "8.5"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_prec_assign(Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "8.53973"); /// ``` #[inline] pub fn mul_prec_assign(&mut self, other: Self, prec: u64) -> Ordering { self.mul_prec_round_assign(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of /// the specified precision. The [`Float`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_prec_round_assign_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_prec_assign_ref(&Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "8.5"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_prec_assign_ref(&Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "8.53973"); /// ``` #[inline] pub fn mul_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { self.mul_prec_round_assign_ref(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is /// returned, indicating whether the rounded product is less than, equal to, or greater than the /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function /// sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::mul_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::mul_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `*=` /// instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign(Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "8.539734222673566"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign(Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "8.539734222673568"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign(Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "8.539734222673566"); /// ``` #[inline] pub fn mul_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_assign(other, prec, rm) } /// Multiplies a [`Float`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] /// is returned, indicating whether the rounded product is less than, equal to, or greater than /// the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::mul_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using /// [`Float::mul_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Floor), Less); /// assert_eq!(x.to_string(), "8.539734222673566"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Ceiling), Greater); /// assert_eq!(x.to_string(), "8.539734222673568"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.mul_round_assign_ref(&Float::from(E), Nearest), Less); /// assert_eq!(x.to_string(), "8.539734222673566"); /// ``` #[inline] pub fn mul_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_assign_ref(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x>0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.mul_rational_prec_round_assign(other, prec, rm); (self, o) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x>0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.mul_rational_prec_round_assign_ref(other, prec, rm); (self, o) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`] /// by value. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x>0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { mul_rational_prec_round_naive_ref_val(self, other, prec, rm) } else { mul_rational_prec_round_direct_ref_val(self, other, prec, rm) } } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded product is less /// than, equal to, or greater than the exact product. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(\pm\infty,0,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x>0$ /// - $f(\infty,x,p,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,p,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,p,m)=\infty$ if $x<0$ /// - $f(0.0,x,p,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,p,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,p,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { mul_rational_prec_round_naive_ref_ref(self, other, prec, rm) } else { mul_rational_prec_round_direct_ref_ref(self, other, prec, rm) } } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x>0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x>0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x\geq0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_rational_prec_round(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x>0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x>0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x\geq0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_rational_prec_round_val_ref(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x>0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x>0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x\geq0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_rational_prec_round_ref_val(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded product is less than, equal /// to, or greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(\pm\infty,0,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x>0$ /// - $f(\infty,x,p)=-\infty$ if $x<0$ /// - $f(-\infty,x,p)=-\infty$ if $x>0$ /// - $f(-\infty,x,p)=\infty$ if $x<0$ /// - $f(0.0,x,p)=0.0$ if $x\geq0$ /// - $f(0.0,x,p)=-0.0$ if $x<0$ /// - $f(-0.0,x,p)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,p)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.mul_rational_prec_round_ref_ref(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is /// also returned, indicating whether the rounded product is less than, equal to, or greater /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x>0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.mul_rational_prec_round(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is /// also returned, indicating whether the rounded product is less than, equal to, or greater /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x>0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.mul_rational_prec_round_val_ref(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is /// also returned, indicating whether the rounded product is less than, equal to, or greater /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x>0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.mul_rational_prec_round_ref_val(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is /// also returned, indicating whether the rounded product is less than, equal to, or greater /// than the exact product. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(\pm\infty,0,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x>0$ /// - $f(\infty,x,m)=-\infty$ if $x<0$ /// - $f(-\infty,x,m)=-\infty$ if $x>0$ /// - $f(-\infty,x,m)=\infty$ if $x<0$ /// - $f(0.0,x,m)=0.0$ if $x\geq0$ /// - $f(0.0,x,m)=-0.0$ if $x<0$ /// - $f(-0.0,x,m)=-0.0$ if $x\geq0$ /// - $f(-0.0,x,m)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.mul_rational_prec_round_ref_ref(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::mul_rational_prec_assign`] /// instead. If you know that your target precision is the precision of the [`Float`] input, /// consider using [`Float::mul_rational_round_assign`] instead. If both of these things are /// true, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.0"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.06"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "1.06"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047199"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197"); /// ``` #[inline] pub fn mul_rational_prec_round_assign( &mut self, other: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { mul_rational_prec_round_assign_naive(self, other, prec, rm) } else { mul_rational_prec_round_assign_direct(self, other, prec, rm) } } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded product is less than, equal to, or /// greater than the exact product. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using /// [`Float::mul_rational_prec_assign_ref`] instead. If you know that your target precision is /// the precision of the [`Float`] input, consider using /// [`Float::mul_rational_round_assign_ref`] instead. If both of these things are true, consider /// using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact multiplication. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.0"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.06"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "1.06"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047199"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197"); /// ``` #[inline] pub fn mul_rational_prec_round_assign_ref( &mut self, other: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { if !self.is_normal() || max(self.complexity(), other.significant_bits()) < MUL_RATIONAL_THRESHOLD { mul_rational_prec_round_assign_naive_ref(self, other, prec, rm) } else { mul_rational_prec_round_assign_direct_ref(self, other, prec, rm) } } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value /// of the specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded product is less than, equal to, or greater than the exact /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_assign(Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "4.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_assign(Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "4.712387"); /// ``` #[inline] pub fn mul_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering { self.mul_rational_prec_round_assign(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result to the nearest value /// of the specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded product is less than, equal to, or greater than the /// exact product. Although `NaN`s are not comparable to any [`Float`], whenever this function /// sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the product is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::mul_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits(), prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_assign_ref(&Rational::exact_from(1.5), 5), /// Greater /// ); /// assert_eq!(x.to_string(), "4.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_prec_assign_ref(&Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "4.712387"); /// ``` #[inline] pub fn mul_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering { self.mul_rational_prec_round_assign_ref(other, prec, Nearest) } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating /// whether the rounded product is less than, equal to, or greater than the exact product. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::mul_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::mul_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197551196597"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047197551196598"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047197551196598"); /// ``` #[inline] pub fn mul_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.mul_rational_prec_round_assign(other, prec, rm) } /// Multiplies a [`Float`] by a [`Rational`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned, /// indicating whether the rounded product is less than, equal to, or greater than the exact /// product. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $xy$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |xy|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::mul_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::mul_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `*=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "1.047197551196597"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047197551196598"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.mul_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "1.047197551196598"); /// ``` #[inline] pub fn mul_rational_round_assign_ref( &mut self, other: &Rational, rm: RoundingMode, ) -> Ordering { let prec = self.significant_bits(); self.mul_rational_prec_round_assign_ref(other, prec, rm) } } impl Mul for Float { type Output = Self; /// Multiplies two [`Float`]s, taking both by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$ /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$ /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$ /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round(other, prec, Nearest).0 } } impl Mul<&Self> for Float { type Output = Self; /// Multiplies two [`Float`]s, taking the first by value and the second by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$ /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$ /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$ /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_val_ref(other, prec, Nearest).0 } } impl Mul for &Float { type Output = Float; /// Multiplies two [`Float`]s, taking the first by reference and the second by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$ /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$ /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$ /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_ref_val(other, prec, Nearest).0 } } impl Mul<&Float> for &Float { type Output = Float; /// Multiplies two [`Float`]s, taking both by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\pm\infty,\pm0.0)=f(\pm0.0,\pm\infty) = \text{NaN}$ /// - $f(\infty,x)=f(x,\infty)=\infty$ if $x>0.0$ /// - $f(\infty,x)=f(x,\infty)=-\infty$ if $x<0.0$ /// - $f(-\infty,x)=f(x,-\infty)=-\infty$ if $x>0.0$ /// - $f(-\infty,x)=f(x,-\infty)=\infty$ if $x<0.0$ /// - $f(0.0,x)=f(x,0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(0.0,x)=f(x,0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// - $f(-0.0,x)=f(x,-0.0)=-0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=0.0$ or $x>0.0$ /// - $f(-0.0,x)=f(x,-0.0)=0.0$ if $x$ is not NaN or $\pm\infty$, and if $x=-0.0$ or $x<0.0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_ref_ref(other, prec, Nearest).0 } } impl MulAssign for Float { /// Multiplies a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side /// by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// x\gets = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `*` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::mul_round_assign`]. If you want both of these things, consider using /// [`Float::mul_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x *= Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x *= Float::INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x *= Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x *= Float::INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x *= Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x *= Float::ZERO; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x *= Float::from(2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(1.5); /// x *= Float::from(-2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x *= Float::from(2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x *= Float::from(-2.5); /// assert_eq!(x, 4.0); /// ``` #[inline] fn mul_assign(&mut self, other: Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_assign(other, prec, Nearest); } } impl MulAssign<&Self> for Float { /// Multiplies a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side /// by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// product is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// $$ /// x\gets = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `*` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::mul_round_assign`]. If you want both of these things, consider using /// [`Float::mul_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x *= &Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x *= &Float::INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x *= &Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x *= &Float::INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(-1.5); /// x *= &Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x *= &Float::ZERO; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x *= &Float::from(2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(1.5); /// x *= &Float::from(-2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x *= &Float::from(2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x *= &Float::from(-2.5); /// assert_eq!(x, 4.0); /// ``` #[inline] fn mul_assign(&mut self, other: &Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.mul_prec_round_assign_ref(other, prec, Nearest); } } impl Mul for Float { type Output = Self; /// Multiplies a [`Float`] by a [`Rational`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x>0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x>0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x\geq0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x\geq0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.mul_rational_prec_round(other, prec, Nearest).0 } } impl Mul<&Rational> for Float { type Output = Self; /// Multiplies a [`Float`] by a [`Rational`], taking the first by value and the second by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x>0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x>0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x\geq0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x\geq0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.mul_rational_prec_round_val_ref(other, prec, Nearest).0 } } impl Mul for &Float { type Output = Float; /// Multiplies a [`Float`] by a [`Rational`], taking the first by reference and the second by /// value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x>0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x>0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x\geq0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x\geq0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.mul_rational_prec_round_ref_val(other, prec, Nearest).0 } } impl Mul<&Rational> for &Float { type Output = Float; /// Multiplies a [`Float`] by a [`Rational`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=f(\pm\infty,0)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x>0$ /// - $f(\infty,x)=-\infty$ if $x<0$ /// - $f(-\infty,x)=-\infty$ if $x>0$ /// - $f(-\infty,x)=\infty$ if $x<0$ /// - $f(0.0,x)=0.0$ if $x\geq0$ /// - $f(0.0,x)=-0.0$ if $x<0$ /// - $f(-0.0,x)=-0.0$ if $x\geq0$ /// - $f(-0.0,x)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.mul_rational_prec_round_ref_ref(other, prec, Nearest).0 } } impl MulAssign for Float { /// Multiplies a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `*` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_rational_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::mul_rational_round_assign`]. If you want both of these things, /// consider using [`Float::mul_rational_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x *= Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x *= Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x *= Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x *= Rational::exact_from(-1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x *= Rational::exact_from(-1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(2.5); /// x *= Rational::exact_from(1.5); /// assert_eq!(x, 4.0); /// ``` #[inline] fn mul_assign(&mut self, other: Rational) { let prec = self.significant_bits(); self.mul_rational_prec_round_assign(other, prec, Nearest); } } impl MulAssign<&Rational> for Float { /// Multiplies a [`Float`] by a [`Rational`] in place, taking the [`Rational`] by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `*` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::mul_rational_prec_assign_ref`] instead. If you want to specify the output /// precision, consider using [`Float::mul_rational_round_assign_ref`]. If you want both of /// these things, consider using [`Float::mul_rational_prec_round_assign_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x *= &Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x *= &Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x *= &Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::INFINITY; /// x *= &Rational::exact_from(-1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x *= &Rational::exact_from(-1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(2.5); /// x *= &Rational::exact_from(1.5); /// assert_eq!(x, 4.0); /// ``` #[inline] fn mul_assign(&mut self, other: &Rational) { let prec = self.significant_bits(); self.mul_rational_prec_round_assign_ref(other, prec, Nearest); } } impl Mul for Rational { type Output = Float; /// Multiplies a [`Rational`] by a [`Float`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ /// - $f(x,\infty)=\infty$ if $x>0$ /// - $f(x,\infty)=-\infty$ if $x<0$ /// - $f(x,-\infty)=-\infty$ if $x>0$ /// - $f(x,-\infty)=\infty$ if $x<0$ /// - $f(x,0.0)=0.0$ if $x\geq0$ /// - $f(x,0.0)=-0.0$ if $x<0$ /// - $f(x,-0.0)=-0.0$ if $x\geq0$ /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.mul_rational_prec_round(self, prec, Nearest).0 } } impl Mul<&Float> for Rational { type Output = Float; /// Multiplies a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`] /// by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ /// - $f(x,\infty)=\infty$ if $x>0$ /// - $f(x,\infty)=-\infty$ if $x<0$ /// - $f(x,-\infty)=-\infty$ if $x>0$ /// - $f(x,-\infty)=\infty$ if $x<0$ /// - $f(x,0.0)=0.0$ if $x\geq0$ /// - $f(x,0.0)=-0.0$ if $x<0$ /// - $f(x,-0.0)=-0.0$ if $x\geq0$ /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.mul_rational_prec_round_ref_val(self, prec, Nearest).0 } } impl Mul for &Rational { type Output = Float; /// Multiplies a [`Rational`] by a [`Float`], taking the [`Rational`] by reference and the /// [`Float`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ /// - $f(x,\infty)=\infty$ if $x>0$ /// - $f(x,\infty)=-\infty$ if $x<0$ /// - $f(x,-\infty)=-\infty$ if $x>0$ /// - $f(x,-\infty)=\infty$ if $x<0$ /// - $f(x,0.0)=0.0$ if $x\geq0$ /// - $f(x,0.0)=-0.0$ if $x<0$ /// - $f(x,-0.0)=-0.0$ if $x\geq0$ /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.mul_rational_prec_round_val_ref(self, prec, Nearest).0 } } impl Mul<&Float> for &Rational { type Output = Float; /// Multiplies a [`Rational`] by a [`Float`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the product is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = xy+\varepsilon. /// $$ /// - If $xy$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $xy$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |xy|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=f(0,\pm\infty)=\text{NaN}$ /// - $f(x,\infty)=\infty$ if $x>0$ /// - $f(x,\infty)=-\infty$ if $x<0$ /// - $f(x,-\infty)=-\infty$ if $x>0$ /// - $f(x,-\infty)=\infty$ if $x<0$ /// - $f(x,0.0)=0.0$ if $x\geq0$ /// - $f(x,0.0)=-0.0$ if $x<0$ /// - $f(x,-0.0)=-0.0$ if $x\geq0$ /// - $f(x,-0.0)=0.0$ if $x<0$ /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); other.mul_rational_prec_round_ref_ref(self, prec, Nearest).0 } } ================================================ FILE: malachite-float/src/arithmetic/neg.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::float_nan; use core::ops::Neg; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::logic::traits::NotAssign; impl Neg for Float { type Output = Self; /// Negates a [`Float`], taking it by value. /// /// $$ /// f(x) = -x. /// $$ /// /// Special cases: /// - $f(\text{NaN}) = \text{NaN}$ /// - $f(\infty) = -\infty$ /// - $f(-\infty) = \infty$ /// - $f(0.0) = -0.0$ /// - $f(-0.0) = 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!(ComparableFloat(-Float::NAN), ComparableFloat(Float::NAN)); /// assert_eq!(-Float::INFINITY, Float::NEGATIVE_INFINITY); /// assert_eq!(-Float::NEGATIVE_INFINITY, Float::INFINITY); /// assert_eq!( /// ComparableFloat(-Float::ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// assert_eq!( /// ComparableFloat(-Float::NEGATIVE_ZERO), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!(-Float::ONE, Float::NEGATIVE_ONE); /// assert_eq!(-Float::NEGATIVE_ONE, Float::ONE); /// ``` #[inline] fn neg(mut self) -> Self { self.neg_assign(); self } } impl Neg for &Float { type Output = Float; /// Negates a [`Float`], taking it by reference. /// /// $$ /// f(x) = -x. /// $$ /// /// Special cases: /// - $f(\text{NaN}) = \text{NaN}$ /// - $f(\infty) = -\infty$ /// - $f(-\infty) = \infty$ /// - $f(0.0) = -0.0$ /// - $f(-0.0) = 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!(ComparableFloat(-&Float::NAN), ComparableFloat(Float::NAN)); /// assert_eq!(-&Float::INFINITY, Float::NEGATIVE_INFINITY); /// assert_eq!(-&Float::NEGATIVE_INFINITY, Float::INFINITY); /// assert_eq!( /// ComparableFloat(-&Float::ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// assert_eq!( /// ComparableFloat(-&Float::NEGATIVE_ZERO), /// ComparableFloat(Float::ZERO) /// ); /// assert_eq!(-&Float::ONE, Float::NEGATIVE_ONE); /// assert_eq!(-&Float::NEGATIVE_ONE, Float::ONE); /// ``` fn neg(self) -> Float { match self { float_nan!() => float_nan!(), Float(Infinity { sign }) => Float(Infinity { sign: !*sign }), Float(Zero { sign }) => Float(Zero { sign: !*sign }), Float(Finite { sign, exponent, precision, significand, }) => Float(Finite { sign: !*sign, exponent: *exponent, precision: *precision, significand: significand.clone(), }), } } } impl NegAssign for Float { /// Negates a [`Float`] in place. /// /// $$ /// x \gets -x. /// $$ /// /// Special cases: /// - $\text{NaN} \gets \text{NaN}$ /// - $\infty \gets -\infty$ /// - $-\infty \gets \infty$ /// - $0.0 \gets -0.0$ /// - $-0.0 \gets 0.0$ /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegAssign; /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// /// let mut x = Float::NAN; /// x.neg_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN)); /// /// let mut x = Float::INFINITY; /// x.neg_assign(); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.neg_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::ZERO; /// x.neg_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NEGATIVE_ZERO)); /// /// let mut x = Float::NEGATIVE_ZERO; /// x.neg_assign(); /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO)); /// /// let mut x = Float::ONE; /// x.neg_assign(); /// assert_eq!(x, Float::NEGATIVE_ONE); /// /// let mut x = Float::NEGATIVE_ONE; /// x.neg_assign(); /// assert_eq!(x, Float::ONE); /// ``` fn neg_assign(&mut self) { if let Self(Infinity { sign } | Zero { sign } | Finite { sign, .. }) = self { sign.not_assign(); } } } ================================================ FILE: malachite-float/src/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{PowerOf2, RoundToMultipleOfPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, Zero}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; impl Float { /// Raises 2 to an integer power, returning a [`Float`] with the specified precision and with /// the specified rounding mode. An [`Ordering`] is also returned, indicating whether the /// returned power is less than, equal to, or greater than the exact power. The ordering is /// usually `Equal`, but is `Less` or `Greater` if overflow or underflow occurs. /// /// $f(k) = 2^k$, and the result has precision `prec`. /// /// - If `pow` is greater than $2^{30}-2$ and `rm` is `Floor` or `Down`, the largest /// representable `Float` with the given precision is returned. /// - If `pow` is greater than $2^{30}-2$ and `rm` is `Ceiling` or `Up`, or `Nearest`, $\infty$ /// is returned. /// - If `pow` is less than $-2^{30}$ and `rm` is `Floor`, `Down`, or `Nearest`, positive zero /// is returned. /// - If `pow` is less than $-2^{30}$ and `rm` is `Ceiling` or `Up`, the smallest positive /// `Float` is returned. /// /// If you want the behavior of `Nearest` (that is, returning $\infty$ on overflow and positive /// zero on underflow), you can use `Float::power_of_2_prec` instead. /// /// If you need a [`Float`] with precision 1, then the [`PowerOf2`] implementation may be used /// instead. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and `pow` is greater than $2^{30}-2$ or less /// than $-2^{30}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (p, o) = Float::power_of_2_prec_round(0, 1, Nearest); /// assert_eq!(p.to_string(), "1.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(0, 100, Nearest); /// assert_eq!(p.to_string(), "1.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(100, 1, Nearest); /// assert_eq!(p.to_string(), "1.0e30"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(100, 100, Nearest); /// assert_eq!(p.to_string(), "1267650600228229401496703205376.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(-100, 1, Nearest); /// assert_eq!(p.to_string(), "8.0e-31"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(-100, 100, Nearest); /// assert_eq!(p.to_string(), "7.88860905221011805411728565283e-31"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec_round(i64::power_of_2(30) - 1, 10, Floor); /// assert_eq!(p.to_string(), "too_big"); /// assert_eq!(o, Less); /// /// let (p, o) = Float::power_of_2_prec_round(i64::power_of_2(30) - 1, 10, Ceiling); /// assert_eq!(p.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// /// let (p, o) = Float::power_of_2_prec_round(-i64::power_of_2(30) - 1, 10, Floor); /// assert_eq!(p.to_string(), "0.0"); /// assert_eq!(o, Less); /// /// let (p, o) = Float::power_of_2_prec_round(-i64::power_of_2(30) - 1, 10, Ceiling); /// assert_eq!(p.to_string(), "too_small"); /// assert_eq!(o, Greater); /// ``` pub fn power_of_2_prec_round(pow: i64, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); if let Ok(exponent) = i32::try_from(pow) && let Some(exponent) = exponent.checked_add(1) && (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&exponent) { return ( Self(Finite { sign: true, exponent, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }), Equal, ); } match (pow > 0, rm) { (_, Exact) => panic!("Inexact power_of_2"), (true, Ceiling | Up | Nearest) => (Self::INFINITY, Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Down | Nearest) => (Self::ZERO, Less), (false, Ceiling | Up) => (Self::min_positive_value_prec(prec), Greater), } } /// Raises 2 to an integer power, returning a [`Float`] with the specified precision. An /// [`Ordering`] is also returned, indicating whether the returned power is less than, equal to, /// or greater than the exact power. The ordering is usually `Equal`, but is `Greater` in the /// case of overflow and `Less` in the case of underflow. /// /// $f(k) = 2^k$, and the result has precision `prec`. /// /// If `pow` is greater than $2^{30}-2$, $\infty$ is returned. If `pow` is less than $-2^{30}$, /// positive zero is returned. If you want different overflow and underflow behavior, try using /// `Float::power_of_2_prec_round` instead. /// /// If you need a [`Float`] with precision 1, then the [`PowerOf2`] implementation may be used /// instead. /// /// # Panics /// Panics if `prec` is zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (p, o) = Float::power_of_2_prec(0, 1); /// assert_eq!(p.to_string(), "1.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(0, 100); /// assert_eq!(p.to_string(), "1.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(100, 1); /// assert_eq!(p.to_string(), "1.0e30"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(100, 100); /// assert_eq!(p.to_string(), "1267650600228229401496703205376.0"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(-100, 1); /// assert_eq!(p.to_string(), "8.0e-31"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(-100, 100); /// assert_eq!(p.to_string(), "7.88860905221011805411728565283e-31"); /// assert_eq!(o, Equal); /// /// let (p, o) = Float::power_of_2_prec(i64::power_of_2(30) - 1, 10); /// assert_eq!(p.to_string(), "Infinity"); /// assert_eq!(o, Greater); /// /// let (p, o) = Float::power_of_2_prec(-i64::power_of_2(30) - 1, 10); /// assert_eq!(p.to_string(), "0.0"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn power_of_2_prec(pow: i64, prec: u64) -> (Self, Ordering) { Self::power_of_2_prec_round(pow, prec, Nearest) } } impl PowerOf2 for Float { /// Raises 2 to an integer power, returning a [`Float`] with precision 1. /// /// To get a [`Float`] with a higher precision, try [`Float::power_of_2_prec`]. /// /// $f(k) = 2^k$. /// /// If `pow` is greater than $2^{30}-2$, $\infty$ is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_float::Float; /// /// assert_eq!(Float::power_of_2(0u64).to_string(), "1.0"); /// assert_eq!(Float::power_of_2(3u64).to_string(), "8.0"); /// assert_eq!(Float::power_of_2(100u64).to_string(), "1.0e30"); /// assert_eq!( /// Float::power_of_2(u64::power_of_2(30) - 1).to_string(), /// "Infinity" /// ); /// ``` fn power_of_2(pow: u64) -> Self { if let Ok(exponent) = i32::try_from(pow) && let Some(exponent) = exponent.checked_add(1) && exponent <= Self::MAX_EXPONENT { return Self(Finite { sign: true, exponent, precision: 1, significand: Natural::HIGH_BIT, }); } Self::INFINITY } } impl PowerOf2 for Float { /// Raises 2 to an integer power, returning a [`Float`] with precision 1. /// /// To get a [`Float`] with a higher precision, try [`Float::power_of_2_prec`]. /// /// $f(k) = 2^k$. /// /// If `pow` is greater than $2^{30}-2$, $\infty$ is returned. If `pow` is less than $-2^{30}$, /// positive zero is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_float::Float; /// /// assert_eq!(Float::power_of_2(0i64).to_string(), "1.0"); /// assert_eq!(Float::power_of_2(3i64).to_string(), "8.0"); /// assert_eq!(Float::power_of_2(100i64).to_string(), "1.0e30"); /// assert_eq!(Float::power_of_2(-3i64).to_string(), "0.1"); /// assert_eq!(Float::power_of_2(-100i64).to_string(), "8.0e-31"); /// assert_eq!( /// Float::power_of_2(i64::power_of_2(30) - 1).to_string(), /// "Infinity" /// ); /// assert_eq!( /// Float::power_of_2(-i64::power_of_2(30) - 1).to_string(), /// "0.0" /// ); /// ``` #[inline] fn power_of_2(pow: i64) -> Self { if let Ok(exponent) = i32::try_from(pow) && let Some(exponent) = exponent.checked_add(1) && (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&exponent) { return Self(Finite { sign: true, exponent, precision: 1, significand: Natural::HIGH_BIT, }); } if pow > 0 { Self::INFINITY } else { Self::ZERO } } } ================================================ FILE: malachite-float/src/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{Float, float_infinity, float_nan, float_negative_infinity}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ IsPowerOf2, NegAssign, Reciprocal, ReciprocalAssign, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_reciprocal::reciprocal_float_significand_ref; impl Float { /// Takes the reciprocal of a [`Float`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded reciprocal is less than, equal to, or greater than /// the exact reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=0.0$ /// - $f(-\infty,p,m)=-0.0$ /// - $f(0.0,p,m)=\infty$ /// - $f(-0.0,p,m)=-\infty$ /// /// Overflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// /// This function cannot underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec`] instead. If /// you know that your target precision is the precision of the input, consider using /// [`Float::reciprocal_round`] instead. If both of these things are true, consider using /// [`Float::reciprocal`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Floor); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Ceiling); /// assert_eq!(reciprocal.to_string(), "0.33"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(5, Nearest); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Floor); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Ceiling); /// assert_eq!(reciprocal.to_string(), "0.3183103"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round(20, Nearest); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_prec_round(mut self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { let o = self.reciprocal_prec_round_assign(prec, rm); (self, o) } /// Takes the reciprocal of a [`Float`], rounding the result to the specified precision and with /// the specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded reciprocal is less than, equal to, or greater than /// the exact reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=0.0$ /// - $f(-\infty,p,m)=-0.0$ /// - $f(0.0,p,m)=\infty$ /// - $f(-0.0,p,m)=-\infty$ /// /// Overflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// /// This function cannot underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec_ref`] /// instead. If you know that your target precision is the precision of the input, consider /// using [`Float::reciprocal_round_ref`] instead. If both of these things are true, consider /// using `(&Float)::reciprocal()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Floor); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Ceiling); /// assert_eq!(reciprocal.to_string(), "0.33"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(5, Nearest); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Floor); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Ceiling); /// assert_eq!(reciprocal.to_string(), "0.3183103"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_round_ref(20, Nearest); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match self { float_nan!() => (float_nan!(), Equal), Self(Zero { sign }) => (Self(Infinity { sign: *sign }), Equal), Self(Infinity { sign }) => (Self(Zero { sign: *sign }), Equal), Self(Finite { sign, exponent: exp, precision: x_prec, significand: x, }) => { if x.is_power_of_2() { let (reciprocal, o) = Self::ONE.shl_prec_round( i64::from(1 - exp), prec, if *sign { rm } else { -rm }, ); return if *sign { (reciprocal, o) } else { (-reciprocal, o.reverse()) }; } let sign = *sign; let (reciprocal, exp_offset, o) = reciprocal_float_significand_ref(x, *x_prec, prec, if sign { rm } else { -rm }); let exp = (1 - *exp).checked_add(i32::exact_from(exp_offset)).unwrap(); if exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float reciprocation"), (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } ( Self(Finite { sign, exponent: exp, precision: prec, significand: reciprocal, }), if sign { o } else { o.reverse() }, ) } } } /// Takes the reciprocal of a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded reciprocal is less than, equal to, or greater than the exact /// reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=0.0$ /// - $f(-\infty,p)=-0.0$ /// - $f(0.0,p)=\infty$ /// - $f(-0.0,p)=-\infty$ /// /// Overflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// /// This function cannot underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec_round`] instead. If you know that your target precision is the /// precision of the input, consider using [`Float::reciprocal`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec(5); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec(20); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_prec(self, prec: u64) -> (Self, Ordering) { self.reciprocal_prec_round(prec, Nearest) } /// Takes the reciprocal of a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded reciprocal is less than, equal to, or greater than the exact /// reciprocal. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=0.0$ /// - $f(-\infty,p)=-0.0$ /// - $f(0.0,p)=\infty$ /// - $f(-0.0,p)=-\infty$ /// /// Overflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// /// This function cannot underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec_round_ref`] instead. If you know that your target precision is the /// precision of the input, consider using `(&Float)::reciprocal()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_ref(5); /// assert_eq!(reciprocal.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_prec_ref(20); /// assert_eq!(reciprocal.to_string(), "0.3183098"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_prec_ref(&self, prec: u64) -> (Self, Ordering) { self.reciprocal_prec_round_ref(prec, Nearest) } /// Takes the reciprocal of a [`Float`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded reciprocal is less than, equal to, or greater than the exact reciprocal. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,y,m) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=0.0$ /// - $f(-\infty,m)=-0.0$ /// - $f(0.0,m)=\infty$ /// - $f(-0.0,m)=-\infty$ /// /// Overflow: /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// /// This function cannot underflow. /// /// If you want to specify an output precision, consider using [`Float::reciprocal_prec_round`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::reciprocal`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the /// output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Floor); /// assert_eq!(reciprocal.to_string(), "0.3183098861837905"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Ceiling); /// assert_eq!(reciprocal.to_string(), "0.318309886183791"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round(Nearest); /// assert_eq!(reciprocal.to_string(), "0.3183098861837905"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_round(self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.reciprocal_prec_round(prec, rm) } /// Takes the reciprocal of a [`Float`], rounding the result with the specified rounding mode. /// The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating whether /// the rounded reciprocal is less than, equal to, or greater than the exact reciprocal. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,y,m) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=0.0$ /// - $f(-\infty,m)=-0.0$ /// - $f(0.0,m)=\infty$ /// - $f(-0.0,m)=-\infty$ /// /// Overflow: /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// /// This function cannot underflow. /// /// If you want to specify an output precision, consider using /// [`Float::reciprocal_prec_round_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `(&Float)::reciprocal()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the /// output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Floor); /// assert_eq!(reciprocal.to_string(), "0.3183098861837905"); /// assert_eq!(o, Less); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Ceiling); /// assert_eq!(reciprocal.to_string(), "0.318309886183791"); /// assert_eq!(o, Greater); /// /// let (reciprocal, o) = Float::from(PI).reciprocal_round_ref(Nearest); /// assert_eq!(reciprocal.to_string(), "0.3183098861837905"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn reciprocal_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.reciprocal_prec_round_ref(prec, rm) } /// Takes the reciprocal of a [`Float`] in place, rounding the result to the specified precision /// and with the specified rounding mode. An [`Ordering`] is returned, indicating whether the /// rounded reciprocal is less than, equal to, or greater than the exact reciprocal. Although /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to /// `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::reciprocal_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_prec_assign`] /// instead. If you know that your target precision is the precision of the input, consider /// using [`Float::reciprocal_round_assign`] instead. If both of these things are true, consider /// using [`Float::reciprocal_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact reciprocation; /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(5, Floor), Less); /// assert_eq!(x.to_string(), "0.31"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.33"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(5, Nearest), Less); /// assert_eq!(x.to_string(), "0.31"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(20, Floor), Less); /// assert_eq!(x.to_string(), "0.3183098"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(20, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.3183103"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_round_assign(20, Nearest), Less); /// assert_eq!(x.to_string(), "0.3183098"); /// ``` #[inline] pub fn reciprocal_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match &mut *self { float_nan!() => Equal, Self(Zero { sign }) => { *self = Self(Infinity { sign: *sign }); Equal } Self(Infinity { sign }) => { *self = Self(Zero { sign: *sign }); Equal } Self(Finite { sign, exponent: exp, precision: x_prec, significand: x, }) => { if x.is_power_of_2() { let sign = *sign; let o; (*self, o) = Self::ONE.shl_prec_round( i64::from(1 - *exp), prec, if sign { rm } else { -rm }, ); return if sign { o } else { self.neg_assign(); o.reverse() }; } let sign = *sign; let (reciprocal, exp_offset, o) = reciprocal_float_significand_ref(x, *x_prec, prec, if sign { rm } else { -rm }); *exp = (1 - *exp).checked_add(i32::exact_from(exp_offset)).unwrap(); if *exp > Self::MAX_EXPONENT { return match (sign, rm) { (_, Exact) => panic!("Inexact Float reciprocation"), (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } *x_prec = prec; *x = reciprocal; if sign { o } else { o.reverse() } } } } /// Takes the reciprocal of a [`Float`] in place, rounding the result to the nearest value of /// the specified precision. An [`Ordering`] is returned, indicating whether the rounded /// reciprocal is less than, equal to, or greater than the exact reciprocal. Although `NaN`s are /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::reciprocal_prec`] documentation for information on special cases, overflow, /// and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec_round_assign`] instead. If you know that your target precision is /// the precision of the input, consider using [`Float::reciprocal`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_assign(5), Less); /// assert_eq!(x.to_string(), "0.31"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_prec_assign(20), Less); /// assert_eq!(x.to_string(), "0.3183098"); /// ``` #[inline] pub fn reciprocal_prec_assign(&mut self, prec: u64) -> Ordering { self.reciprocal_prec_round_assign(prec, Nearest) } /// Takes the reciprocal of a [`Float`] in place, rounding the result with the specified /// rounding mode. An [`Ordering`] is returned, indicating whether the rounded reciprocal is /// less than, equal to, or greater than the exact reciprocal. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// x \gets 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// /// See the [`Float::reciprocal_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::reciprocal_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using [`Float::reciprocal_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the /// output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_round_assign(Floor), Less); /// assert_eq!(x.to_string(), "0.3183098861837905"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_round_assign(Ceiling), Greater); /// assert_eq!(x.to_string(), "0.318309886183791"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_round_assign(Nearest), Less); /// assert_eq!(x.to_string(), "0.3183098861837905"); /// ``` #[inline] pub fn reciprocal_round_assign(&mut self, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.reciprocal_prec_round_assign(prec, rm) } } impl Reciprocal for Float { type Output = Self; /// Takes the reciprocal of a [`Float`], taking it by value. /// /// If the output has a precision, it is the precision of the input. If the reciprocal is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=-0.0$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=-\infty$ /// /// Overflow: /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// /// This function cannot underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec`] instead. If you want to specify the output precision, consider /// using [`Float::reciprocal_round`]. If you want both of these things, consider using /// [`Float::reciprocal_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Reciprocal; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!(Float::NAN.reciprocal().is_nan()); /// assert_eq!(Float::INFINITY.reciprocal().to_string(), "0.0"); /// assert_eq!(Float::NEGATIVE_INFINITY.reciprocal().to_string(), "-0.0"); /// assert_eq!(Float::from(1.5).reciprocal().to_string(), "0.8"); /// assert_eq!(Float::from(-1.5).reciprocal().to_string(), "-0.8"); /// ``` #[inline] fn reciprocal(self) -> Self { let prec = self.significant_bits(); self.reciprocal_prec_round(prec, Nearest).0 } } impl Reciprocal for &Float { type Output = Float; /// Takes the reciprocal of a [`Float`], taking it by reference. /// /// If the output has a precision, it is the precision of the input. If the reciprocal is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=-0.0$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=-\infty$ /// /// Overflow: /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// /// This function cannot underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec_ref`] instead. If you want to specify the output precision, /// consider using [`Float::reciprocal_round_ref`]. If you want both of these things, consider /// using [`Float::reciprocal_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Reciprocal; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!((&Float::NAN).reciprocal().is_nan()); /// assert_eq!((&Float::INFINITY).reciprocal().to_string(), "0.0"); /// assert_eq!((&Float::NEGATIVE_INFINITY).reciprocal().to_string(), "-0.0"); /// assert_eq!((&Float::from(1.5)).reciprocal().to_string(), "0.8"); /// assert_eq!((&Float::from(-1.5)).reciprocal().to_string(), "-0.8"); /// ``` #[inline] fn reciprocal(self) -> Float { let prec = self.significant_bits(); self.reciprocal_prec_round_ref(prec, Nearest).0 } } impl ReciprocalAssign for Float { /// Takes the reciprocal of a [`Float`] in place. /// /// If the output has a precision, it is the precision of the input. If the reciprocal is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = 1/x+\varepsilon. /// $$ /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the [`Float::reciprocal`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::reciprocal_round_assign`]. If you want both of these things, /// consider using [`Float::reciprocal_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalAssign; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::NAN; /// x.reciprocal_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "-0.0"); /// /// let mut x = Float::from(1.5); /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "0.8"); /// /// let mut x = Float::from(-1.5); /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "-0.8"); /// ``` #[inline] fn reciprocal_assign(&mut self) { let prec = self.significant_bits(); self.reciprocal_prec_round_assign(prec, Nearest); } } ================================================ FILE: malachite-float/src/arithmetic/reciprocal_sqrt.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 2008-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::arithmetic::sqrt::generic_sqrt_rational; use crate::conversion::from_natural::{ from_natural_prec_round_zero_exponent_ref, from_natural_zero_exponent, from_natural_zero_exponent_ref, }; use crate::conversion::from_rational::FROM_RATIONAL_THRESHOLD; use crate::{ Float, emulate_float_to_float_fn, emulate_rational_to_float_fn, float_either_zero, float_infinity, float_nan, float_zero, significand_bits, }; use core::cmp::Ordering::{self, *}; use core::cmp::max; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, CheckedSqrt, FloorLogBase2, IsPowerOf2, NegAssign, NegModPowerOf2, Parity, PowerOf2, Reciprocal, ReciprocalAssign, ReciprocalSqrt, ReciprocalSqrtAssign, RoundToMultipleOfPowerOf2, Sqrt, UnsignedAbs, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity, NegativeZero, Zero as ZeroTrait, }; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::LIMB_HIGH_BIT; use malachite_nz::natural::arithmetic::float_extras::{ float_can_round, limbs_float_can_round, limbs_significand_slice_add_limb_in_place, }; use malachite_nz::natural::arithmetic::float_reciprocal_sqrt::limbs_reciprocal_sqrt; use malachite_nz::natural::{Natural, bit_to_limb_count_ceiling, limb_to_bit_count}; use malachite_nz::platform::Limb; use malachite_q::Rational; fn from_reciprocal_rational_prec_round_ref_direct( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); let sign = *x >= 0; if let Some(pow) = x.numerator_ref().checked_log_base_2() { let n = x.denominator_ref(); let n_bits = n.significant_bits(); let (mut y, mut o) = from_natural_prec_round_zero_exponent_ref(n, prec, if sign { rm } else { -rm }); o = y.shr_prec_round_assign_helper( i128::from(pow) - i128::from(n_bits), prec, if sign { rm } else { -rm }, o, ); assert!( rm != Exact || o == Equal, "Inexact conversion from Rational to Float" ); if sign { (y, o) } else { (-y, o.reverse()) } } else { let x = x.reciprocal(); let mut exponent = i32::saturating_from(x.floor_log_base_2_abs()); if exponent >= Float::MAX_EXPONENT { return match (sign, rm) { (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater), (true, Floor | Down) => (Float::max_finite_value_with_prec(prec), Less), (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less), (false, Ceiling | Down) => (-Float::max_finite_value_with_prec(prec), Greater), (_, Exact) => panic!("Inexact conversion from Rational to Float"), }; } let (significand, o) = Integer::rounding_from(x << (i128::exact_from(prec) - i128::from(exponent) - 1), rm); let sign = significand >= 0; let mut significand = significand.unsigned_abs(); let away_from_0 = if sign { Greater } else { Less }; if o == away_from_0 && significand.is_power_of_2() { exponent += 1; if exponent >= Float::MAX_EXPONENT { return if sign { (Float::INFINITY, Greater) } else { (Float::NEGATIVE_INFINITY, Less) }; } } exponent += 1; if exponent < Float::MIN_EXPONENT { assert!(rm != Exact, "Inexact conversion from Rational to Float"); return if rm == Nearest && exponent == Float::MIN_EXPONENT - 1 && (o == away_from_0.reverse() || !significand.is_power_of_2()) { if sign { (Float::min_positive_value_prec(prec), Greater) } else { (-Float::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (true, Up | Ceiling) => (Float::min_positive_value_prec(prec), Greater), (true, Floor | Down | Nearest) => (Float::ZERO, Less), (false, Up | Floor) => (-Float::min_positive_value_prec(prec), Less), (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater), (_, Exact) => unreachable!(), } }; } significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); let target_bits = prec .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0; let current_bits = significand_bits(&significand); if current_bits > target_bits { significand >>= current_bits - target_bits; } ( Float(Finite { sign, exponent, precision: prec, significand, }), o, ) } } fn from_reciprocal_rational_prec_round_ref_using_div( x: &Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { let sign = *x >= 0; if !sign { rm.neg_assign(); } let (d, n) = x.numerator_and_denominator_ref(); let is_zero = *n == 0; let (f, o) = match ( if is_zero { None } else { n.checked_log_base_2() }, d.checked_log_base_2(), ) { (Some(log_n), Some(log_d)) => Float::power_of_2_prec_round( i64::saturating_from(i128::from(log_n) - i128::from(log_d)), prec, rm, ), (None, Some(log_d)) => { let (mut f, mut o) = from_natural_prec_round_zero_exponent_ref(n, prec, rm); o = f.shr_prec_round_assign_helper( i128::from(log_d) - i128::from(n.significant_bits()), prec, rm, o, ); (f, o) } (Some(log_n), None) => { let (mut f, mut o) = from_natural_zero_exponent_ref(d).reciprocal_prec_round(prec, rm); o = f.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d.significant_bits()), prec, rm, o, ); (f, o) } (None, None) => { let (mut f, mut o) = from_natural_zero_exponent_ref(n).div_prec_round( from_natural_zero_exponent_ref(d), prec, rm, ); o = f.shl_prec_round_assign_helper( i128::from(n.significant_bits()) - i128::from(d.significant_bits()), prec, rm, o, ); (f, o) } }; if sign { (f, o) } else { (-f, o.reverse()) } } pub_crate_test! { #[inline] from_reciprocal_rational_prec_round_ref( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if max(x.significant_bits(), prec) < FROM_RATIONAL_THRESHOLD { from_reciprocal_rational_prec_round_ref_direct(x, prec, rm) } else { from_reciprocal_rational_prec_round_ref_using_div(x, prec, rm) } }} pub_crate_test! { generic_reciprocal_sqrt_rational_ref( x: &Rational, prec: u64, rm: RoundingMode ) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; let mut end_shift = x.floor_log_base_2(); let x2; let reduced_x: &Rational; if end_shift.gt_abs(&0x3fff_0000) { end_shift &= !1; x2 = x >> end_shift; reduced_x = &x2; } else { end_shift = 0; reduced_x = x; } loop { let sqrt = from_reciprocal_rational_prec_round_ref(reduced_x, working_prec, Floor).0.sqrt(); // See algorithms.tex. Since we rounded down when computing fx, the absolute error of the // square root is bounded by (c_sqrt + k_fx)ulp(sqrt) <= 2ulp(sqrt). // // Experiments suggest that `working_prec` is low enough (that is, that the error is at most // 1 ulp), but I can only prove `working_prec - 1`. if float_can_round(sqrt.significand_ref().unwrap(), working_prec - 1, prec, rm) { let (mut sqrt, mut o) = Float::from_float_prec_round(sqrt, prec, rm); if end_shift != 0 { o = sqrt.shr_prec_round_assign_helper(end_shift >> 1, prec, rm, o); } return (sqrt, o); } working_prec += increment; increment = working_prec >> 1; } }} impl Float { /// Computes the reciprocal of the square root of a [`Float`], rounding the result to the /// specified precision and with the specified rounding mode. The [`Float`] is taken by value. /// An [`Ordering`] is also returned, indicating whether the rounded reciprocal square root is /// less than, equal to, or greater than the exact square root. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=0.0$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(0.0,p,m)=\infty$ /// - $f(-0.0,p,m)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_sqrt_prec`] /// instead. If you know that your target precision is the precision of the input, consider /// using [`Float::reciprocal_sqrt_round`] instead. If both of these things are true, consider /// using [`Float::reciprocal_sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(5, Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(5, Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.59"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(5, Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(20, Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(20, Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round(20, Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn reciprocal_sqrt_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { self.reciprocal_sqrt_prec_round_ref(prec, rm) } /// Computes the reciprocal of the square root of a [`Float`], rounding the result to the /// specified precision and with the specified rounding mode. The [`Float`] is taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded reciprocal /// square root is less than, equal to, or greater than the exact square root. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=0.0$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(0.0,p,m)=\infty$ /// - $f(-0.0,p,m)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_sqrt_prec_ref`] /// instead. If you know that your target precision is the precision of the input, consider /// using [`Float::reciprocal_sqrt_round_ref`] instead. If both of these things are true, /// consider using `(&Float).reciprocal_sqrt()`instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(5, Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(5, Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.59"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(5, Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(20, Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(20, Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_round_ref(20, Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// ``` /// /// This is mpfr_rec_sqrt from rec_sqrt.c, MPFR 4.3.0. #[inline] pub fn reciprocal_sqrt_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match self { Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal), float_infinity!() => (float_zero!(), Equal), float_either_zero!() => (float_infinity!(), Equal), Self(Finite { sign, exponent: x_exp, precision: x_prec, significand: x, .. }) => { if !sign { return (float_nan!(), Equal); } // Let u = U*2^e, where e = EXP(u), and 1/2 <= U < 1. If e is even, we compute an // approximation of X of (4U)^{-1/2}, and the result is X*2^(-(e-2)/2) [case s=1]. // If e is odd, we compute an approximation of X of (2U)^{-1/2}, and the result is // X*2^(-(e-1)/2) [case s=0]. // // parity of the exponent of u let mut s = i32::from(x_exp.even()); let in_len = bit_to_limb_count_ceiling(prec); // for the first iteration, if rp + 11 fits into rn limbs, we round up up to a full // limb to maximize the chance of rounding, while avoiding to allocate extra space let mut working_prec = max(prec + 11, limb_to_bit_count(in_len)); let mut increment = Limb::WIDTH; let mut out; loop { let working_limbs = bit_to_limb_count_ceiling(working_prec); out = alloc::vec![0; working_limbs]; limbs_reciprocal_sqrt( &mut out, working_prec, x.as_limbs_asc(), *x_prec, s == 1, ); // If the input was not truncated, the error is at most one ulp; if the input // was truncated, the error is at most two ulps (see algorithms.tex). if limbs_float_can_round( &out, working_prec - u64::from(working_prec < *x_prec), prec, rm, ) { assert_ne!(rm, Exact, "Inexact float reciprocal square root"); break; } // We detect only now the exact case where u = 2 ^ (2e), to avoid slowing down // the average case. This can happen only when the mantissa is exactly 1 / 2 and // the exponent is odd. if s == 0 && x.is_power_of_2() { let pl = limb_to_bit_count(working_limbs) - working_prec; // we should have x=111...111 limbs_significand_slice_add_limb_in_place(&mut out, Limb::power_of_2(pl)); *out.last_mut().unwrap() = LIMB_HIGH_BIT; s = 2; break; } working_prec += increment; increment = working_prec >> 1; } let reciprocal_sqrt = Self(Finite { sign: true, exponent: (s + 1 - x_exp) >> 1, precision: working_prec, significand: Natural::from_owned_limbs_asc(out), }); Self::from_float_prec_round(reciprocal_sqrt, prec, rm) } } } /// Computes the reciprocal of the square root of a [`Float`], rounding the result to the /// nearest value of the specified precision. The [`Float`] is taken by value. An [`Ordering`] /// is also returned, indicating whether the rounded reciprocal square root is less than, equal /// to, or greater than the exact square root. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// If the reciprocal square root is equidistant from two [`Float`]s with the specified /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See /// [`RoundingMode`] for a description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=0.0$ /// - $f(-\infty,p)=\text{NaN}$ /// - $f(0.0,p)=\infty$ /// - $f(-0.0,p)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec_round`] instead. If you know that your target precision is the /// precision of the input, consider using [`Float::reciprocal_sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec(5); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec(20); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn reciprocal_sqrt_prec(self, prec: u64) -> (Self, Ordering) { self.reciprocal_sqrt_prec_round(prec, Nearest) } /// Computes the reciprocal of the square root of a [`Float`], rounding the result to the /// nearest value of the specified precision. The [`Float`] is taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded reciprocal square root is less /// than, equal to, or greater than the exact square root. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// If the reciprocal square root is equidistant from two [`Float`]s with the specified /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See /// [`RoundingMode`] for a description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=0.0$ /// - $f(-\infty,p)=\text{NaN}$ /// - $f(0.0,p)=\infty$ /// - $f(-0.0,p)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec_round_ref`] instead. If you know that your target precision is /// the precision of the input, consider using `(&Float).reciprocal_sqrt()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_ref(5); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_prec_ref(20); /// assert_eq!(reciprocal_sqrt.to_string(), "0.56419"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn reciprocal_sqrt_prec_ref(&self, prec: u64) -> (Self, Ordering) { self.reciprocal_sqrt_prec_round_ref(prec, Nearest) } /// Computes the reciprocal of the square root of a [`Float`], rounding the result with the /// specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded reciprocal square root is less than, equal to, or greater /// than the exact square root. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=0.0$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(0.0,m)=\infty$ /// - $f(-0.0,m)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using /// [`Float::reciprocal_sqrt_prec_round`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using [`Float::reciprocal_sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round(Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547756"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round(Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547757"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round(Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547757"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn reciprocal_sqrt_round(self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round(prec, rm) } /// Computes the reciprocal of the square root of a [`Float`], rounding the result with the /// specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded reciprocal square root is less than, equal to, or /// greater than the exact square root. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=0.0$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(0.0,m)=\infty$ /// - $f(-0.0,m)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using /// [`Float::reciprocal_sqrt_prec_round_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `(&Float).reciprocal_sqrt()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round_ref(Floor); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547756"); /// assert_eq!(o, Less); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round_ref(Ceiling); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547757"); /// assert_eq!(o, Greater); /// /// let (reciprocal_sqrt, o) = Float::from(PI).reciprocal_sqrt_round_ref(Nearest); /// assert_eq!(reciprocal_sqrt.to_string(), "0.564189583547757"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn reciprocal_sqrt_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round_ref(prec, rm) } /// Computes the reciprocal of the square root of a [`Float`] in place, rounding the result to /// the specified precision and with the specified rounding mode. An [`Ordering`] is returned, /// indicating whether the rounded reciprocal square root is less than, equal to, or greater /// than the exact square root. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::reciprocal_sqrt_prec_round`] documentation for information on special /// cases, overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::reciprocal_sqrt_prec_assign`] /// instead. If you know that your target precision is the precision of the input, consider /// using [`Float::reciprocal_sqrt_round_assign`] instead. If both of these things are true, /// consider using [`Float::reciprocal_sqrt_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(5, Floor), Less); /// assert_eq!(x.to_string(), "0.56"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.59"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(5, Nearest), Less); /// assert_eq!(x.to_string(), "0.56"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(20, Floor), Less); /// assert_eq!(x.to_string(), "0.564189"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(20, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.56419"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_round_assign(20, Nearest), Greater); /// assert_eq!(x.to_string(), "0.56419"); /// ``` #[inline] pub fn reciprocal_sqrt_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { let (reciprocal_sqrt, o) = self.reciprocal_sqrt_prec_round_ref(prec, rm); *self = reciprocal_sqrt; o } /// Computes the reciprocal of the square root of a [`Float`] in place, rounding the result to /// the nearest value of the specified precision. An [`Ordering`] is returned, indicating /// whether the rounded square root is less than, equal to, or greater than the exact square /// root. Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// If the reciprocal square root is equidistant from two [`Float`]s with the specified /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See /// [`RoundingMode`] for a description of the `Nearest` rounding mode. /// /// $$ /// x \gets 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::reciprocal_sqrt_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec_round_assign`] instead. If you know that your target precision /// is the precision of the input, consider using [`Float::reciprocal_sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_assign(5), Less); /// assert_eq!(x.to_string(), "0.56"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_prec_assign(20), Greater); /// assert_eq!(x.to_string(), "0.56419"); /// ``` #[inline] pub fn reciprocal_sqrt_prec_assign(&mut self, prec: u64) -> Ordering { self.reciprocal_sqrt_prec_round_assign(prec, Nearest) } /// Computes the reciprocal of the square root of a [`Float`] in place, rounding the result with /// the specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded /// reciprocal square root is less than, equal to, or greater than the exact square root. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// x \gets 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$, where $p$ is the maximum precision of the /// inputs. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// /// See the [`Float::reciprocal_sqrt_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::reciprocal_sqrt_prec_round_assign`] instead. If you know you'll be using the /// `Nearest` rounding mode, consider using [`Float::reciprocal_sqrt_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_round_assign(Floor), Less); /// assert_eq!(x.to_string(), "0.564189583547756"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_round_assign(Ceiling), Greater); /// assert_eq!(x.to_string(), "0.564189583547757"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.reciprocal_sqrt_round_assign(Nearest), Greater); /// assert_eq!(x.to_string(), "0.564189583547757"); /// ``` #[inline] pub fn reciprocal_sqrt_round_assign(&mut self, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round_assign(prec, rm) } /// Computes the reciprocal of the square root of a [`Rational`], rounding the result to the /// specified precision and with the specified rounding mode and returning the result as a /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating /// whether the rounded reciprocal square root is less than, equal to, or greater than the exact /// reciprocal square root. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=\infty$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); if x == 0u32 { return (Self::INFINITY, Equal); } else if x < 0u32 { return (Self::NAN, Equal); } x.reciprocal_assign(); if let Some(sqrt) = (&x).checked_sqrt() { return Self::from_rational_prec_round(sqrt, prec, rm); } let (n, d) = x.numerator_and_denominator_ref(); match (n.checked_log_base_2(), d.checked_log_base_2()) { (_, Some(log_d)) if log_d.even() => { let n = x.into_numerator(); let n_exp = n.significant_bits(); let mut n = from_natural_zero_exponent(n); if n_exp.odd() { n <<= 1u32; } let (mut sqrt, o) = Self::exact_from(n).sqrt_prec_round(prec, rm); let o = sqrt.shr_prec_round_assign_helper( i128::from(log_d >> 1) - i128::from(n_exp >> 1), prec, rm, o, ); (sqrt, o) } (Some(log_n), _) if log_n.even() => { let d = x.into_denominator(); let d_exp = d.significant_bits(); let mut d = from_natural_zero_exponent(d); if d_exp.odd() { d <<= 1u32; } let (mut reciprocal_sqrt, o) = Self::exact_from(d).reciprocal_sqrt_prec_round(prec, rm); let o = reciprocal_sqrt.shl_prec_round_assign_helper( i128::from(log_n >> 1) - i128::from(d_exp >> 1), prec, rm, o, ); (reciprocal_sqrt, o) } _ => generic_sqrt_rational(x, prec, rm), } } /// Computes the reciprocal of the square root of a [`Rational`], rounding the result to the /// specified precision and with the specified rounding mode and returning the result as a /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded reciprocal square root is less than, equal to, or greater /// than the exact reciprocal square root. Although `NaN`s are not comparable to any [`Float`], /// whenever this function returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=\infty$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); if *x == 0u32 { return (Self::INFINITY, Equal); } else if *x < 0u32 { return (Self::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Self::from_rational_prec_round(sqrt.reciprocal(), prec, rm); } let (d, n) = x.numerator_and_denominator_ref(); match (n.checked_log_base_2(), d.checked_log_base_2()) { (_, Some(log_d)) if log_d.even() => { let n_exp = n.significant_bits(); let mut n = from_natural_zero_exponent_ref(n); if n_exp.odd() { n <<= 1u32; } let (mut sqrt, o) = Self::exact_from(n).sqrt_prec_round(prec, rm); let o = sqrt.shr_prec_round_assign_helper( i128::from(log_d >> 1) - i128::from(n_exp >> 1), prec, rm, o, ); (sqrt, o) } (Some(log_n), _) if log_n.even() => { let d_exp = d.significant_bits(); let mut d = from_natural_zero_exponent_ref(d); if d_exp.odd() { d <<= 1u32; } let (mut reciprocal_sqrt, o) = Self::exact_from(d).reciprocal_sqrt_prec_round(prec, rm); let o = reciprocal_sqrt.shl_prec_round_assign_helper( i128::from(log_n >> 1) - i128::from(d_exp >> 1), prec, rm, o, ); (reciprocal_sqrt, o) } _ => generic_reciprocal_sqrt_rational_ref(x, prec, rm), } } /// Computes the reciprocal of the square root of a [`Rational`], rounding the result to the /// nearest value of the specified precision and returning the result as a [`Float`]. The /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded reciprocal square root is less than, equal to, or greater than the exact reciprocal /// square root. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// If the reciprocal square root is equidistant from two [`Float`]s with the specified /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See /// [`RoundingMode`] for a description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=\infty$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { Self::reciprocal_sqrt_rational_prec_round(x, prec, Nearest) } /// Computes the reciprocal of the square root of a [`Rational`], rounding the result to the /// nearest value of the specified precision and returning the result as a [`Float`]. The /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded reciprocal square root is less than, equal to, or greater than the exact reciprocal /// square root. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// If the reciprocal square root is equidistant from two [`Float`]s with the specified /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See /// [`RoundingMode`] for a description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=\infty$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { Self::reciprocal_sqrt_rational_prec_round_ref(x, prec, Nearest) } } impl ReciprocalSqrt for Float { type Output = Self; /// Computes the reciprocal of the square root of a [`Float`], taking it by value. /// /// If the output has a precision, it is the precision of the input. If the reciprocal square /// root is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// $$ /// f(x) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=\text{NaN}$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec`] instead. If you want to specify the output precision, /// consider using [`Float::reciprocal_sqrt_round`]. If you want both of these things, consider /// using [`Float::reciprocal_sqrt_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalSqrt; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; /// use malachite_float::Float; /// /// assert!(Float::NAN.reciprocal_sqrt().is_nan()); /// assert_eq!(Float::INFINITY.reciprocal_sqrt(), Float::ZERO); /// assert!(Float::NEGATIVE_INFINITY.reciprocal_sqrt().is_nan()); /// assert_eq!(Float::from(1.5).reciprocal_sqrt().to_string(), "0.8"); /// assert!(Float::from(-1.5).reciprocal_sqrt().is_nan()); /// ``` #[inline] fn reciprocal_sqrt(self) -> Self { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round(prec, Nearest).0 } } impl ReciprocalSqrt for &Float { type Output = Float; /// Computes the reciprocal of the square root of a [`Float`], taking it by reference. /// /// If the output has a precision, it is the precision of the input. If the reciprocal square /// root is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// $$ /// f(x) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=\text{NaN}$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec_ref`] instead. If you want to specify the output precision, /// consider using [`Float::reciprocal_sqrt_round_ref`]. If you want both of these things, /// consider using [`Float::reciprocal_sqrt_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalSqrt; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; /// use malachite_float::Float; /// /// assert!((&Float::NAN).reciprocal_sqrt().is_nan()); /// assert_eq!((&Float::INFINITY).reciprocal_sqrt(), Float::ZERO); /// assert!((&Float::NEGATIVE_INFINITY).reciprocal_sqrt().is_nan()); /// assert_eq!((&Float::from(1.5)).reciprocal_sqrt().to_string(), "0.8"); /// assert!((&Float::from(-1.5)).reciprocal_sqrt().is_nan()); /// ``` #[inline] fn reciprocal_sqrt(self) -> Float { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round_ref(prec, Nearest).0 } } impl ReciprocalSqrtAssign for Float { /// Computes the reciprocal of the square root of a [`Float`] in place. /// /// If the output has a precision, it is the precision of the input. If the reciprocal square /// root is equidistant from two [`Float`]s with the specified precision, the [`Float`] with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// Using this function is more accurate than taking the square root and then the reciprocal, or /// vice versa. /// /// $$ /// x\gets = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// See the [`Float::reciprocal_sqrt`] documentation for information on special cases, overflow, /// and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::reciprocal_sqrt_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::reciprocal_sqrt_round_assign`]. If you want both of these things, /// consider using [`Float::reciprocal_sqrt_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalSqrtAssign; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; /// use malachite_float::Float; /// /// let mut x = Float::NAN; /// x.reciprocal_sqrt_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x.reciprocal_sqrt_assign(); /// assert_eq!(x, Float::ZERO); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.reciprocal_sqrt_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x.reciprocal_sqrt_assign(); /// assert_eq!(x.to_string(), "0.8"); /// /// let mut x = Float::from(-1.5); /// x.reciprocal_sqrt_assign(); /// assert!(x.is_nan()); /// ``` #[inline] fn reciprocal_sqrt_assign(&mut self) { let prec = self.significant_bits(); self.reciprocal_sqrt_prec_round_assign(prec, Nearest); } } /// Computes the reciprocal of the square root of a primitive float. Using this function is more /// accurate than using `powf(0.5)` or taking the square root and then the reciprocal, or vice /// versa. /// /// If the reciprocal square root is equidistant from two primitive floats, the primitive float with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// The reciprocal square root of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] /// and 53 if `T` is a [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=0.0$ /// - $f(-\infty)=\text{NaN}$ /// - $f(0.0)=\infty$ /// - $f(-0.0)=\infty$ /// /// Neither overflow nor underflow is possible. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::reciprocal_sqrt::primitive_float_reciprocal_sqrt; /// /// assert!(primitive_float_reciprocal_sqrt(f32::NAN).is_nan()); /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt(f32::INFINITY)), /// NiceFloat(0.0) /// ); /// assert!(primitive_float_reciprocal_sqrt(f32::NEGATIVE_INFINITY).is_nan()); /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt(3.0f32)), /// NiceFloat(0.57735026) /// ); /// assert!(primitive_float_reciprocal_sqrt(-3.0f32).is_nan()); /// ``` #[inline] #[allow(clippy::type_repetition_in_bounds)] pub fn primitive_float_reciprocal_sqrt(x: T) -> T where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_float_to_float_fn(Float::reciprocal_sqrt_prec, x) } /// Computes the reciprocal of the square root of a [`Rational`], returning a primitive float /// result. /// /// If the reciprocal square root is equidistant from two primitive floats, the primitive float with /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the /// `Nearest` rounding mode. /// /// The reciprocal square root of any negative number is `NaN`. /// /// $$ /// f(x) = 1/\sqrt{x}+\varepsilon. /// $$ /// - If $1/\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $1/\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// 1/\sqrt{x}\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] /// and 53 if `T` is a [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(0)=\infty$ /// /// Overflow: /// - If the absolute value of the result is too large to represent, $\infty$ is returned instead. /// - If the absolute value of the result is too small to represent, 0.0 is returned instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::reciprocal_sqrt::primitive_float_reciprocal_sqrt_rational; /// use malachite_q::Rational; /// /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt_rational::( /// &Rational::ZERO /// )), /// NiceFloat(f64::INFINITY) /// ); /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt_rational::( /// &Rational::from_unsigneds(1u8, 3) /// )), /// NiceFloat(1.7320508075688772) /// ); /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt_rational::( /// &Rational::from(10000) /// )), /// NiceFloat(0.01) /// ); /// assert_eq!( /// NiceFloat(primitive_float_reciprocal_sqrt_rational::( /// &Rational::from(-10000) /// )), /// NiceFloat(f64::NAN) /// ); /// ``` #[inline] #[allow(clippy::type_repetition_in_bounds)] pub fn primitive_float_reciprocal_sqrt_rational(x: &Rational) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_rational_to_float_fn(Float::reciprocal_sqrt_rational_prec_ref, x) } ================================================ FILE: malachite-float/src/arithmetic/shl.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::arithmetic::traits::{ShlRound, ShlRoundAssign}; use core::ops::{Shl, ShlAssign}; use malachite_base::rounding_modes::RoundingMode::*; macro_rules! impl_shl { ($t:ident) => { impl Shl<$t> for Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), taking it by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { self.shl_round(bits, Nearest).0 } } impl Shl<$t> for &Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), taking it by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { self.shl_round(bits, Nearest).0 } } impl ShlAssign<$t> for Float { /// Left-shifts a [`Float`] (multiplies it by a power of 2), in place. If the [`Float`] /// has a precision, the precision is unchanged. /// /// `NaN`, infinities, and zeros are unchanged. /// /// $$ /// x \gets x2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is assigned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is assigned instead. /// - If $0. use crate::Float; use crate::InnerFloat::Finite; use crate::malachite_base::num::logic::traits::SignificantBits; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShlRound, ShlRoundAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::SaturatingInto; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { pub(crate) fn shl_prec_round_assign_helper( &mut self, bits: T, prec: u64, rm: RoundingMode, previous_o: Ordering, ) -> Ordering { if let Self(Finite { significand, exponent, sign, precision, }) = self { let mut possibly_just_under_min = false; if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_add(bits) { possibly_just_under_min = true; if (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&new_exponent) { *exponent = new_exponent; return previous_o; } } assert!(rm != Exact, "Inexact Float left-shift"); if bits > T::ZERO { match (*sign, rm) { (true, Up | Ceiling | Nearest) => { *self = Self::INFINITY; Greater } (true, Floor | Down) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Up | Floor | Nearest) => { *self = Self::NEGATIVE_INFINITY; Less } (false, Ceiling | Down) => { *self = -Self::max_finite_value_with_prec(prec); Greater } (_, Exact) => unreachable!(), } } else if rm == Nearest && possibly_just_under_min && *exponent + >::saturating_into(bits) == Self::MIN_EXPONENT - 1 && (previous_o == if *sign { Less } else { Greater } || !significand.is_power_of_2()) { if *sign { *self = Self::min_positive_value_prec(*precision); Greater } else { *self = -Self::min_positive_value_prec(*precision); Less } } else { match (*sign, rm) { (true, Up | Ceiling) => { *self = Self::min_positive_value_prec(prec); Greater } (true, Floor | Down | Nearest) => { *self = Self::ZERO; Less } (false, Up | Floor) => { *self = -Self::min_positive_value_prec(prec); Less } (false, Ceiling | Down | Nearest) => { *self = Self::NEGATIVE_ZERO; Greater } (_, Exact) => unreachable!(), } } } else { Equal } } /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with the /// specified rounding mode and precision, and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p,m) = x2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0( mut self, bits: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let o = self.shl_prec_round_assign(bits, prec, rm); (self, o) } /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with the /// specified rounding mode and precision, and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p,m) = x2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0( &self, bits: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let mut x = self.clone(); let o = x.shl_prec_round_assign(bits, prec, rm); (x, o) } /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with /// the specified rounding mode and precision. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// x \gets x2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0( &mut self, bits: T, prec: u64, rm: RoundingMode, ) -> Ordering { if let Self(Finite { exponent, .. }) = self { let old_exponent = *exponent; *exponent = 0; let o = self.set_prec_round(prec, rm); self.shl_prec_round_assign_helper( >::saturating_into(bits).saturating_add(old_exponent), prec, rm, o, ) } else { Equal } } /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with the /// specified precision, and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p) = x2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0(self, bits: T, prec: u64) -> (Self, Ordering) { self.shl_prec_round(bits, prec, Nearest) } /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with the /// specified precision, and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p) = x2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0(&self, bits: T, prec: u64) -> (Self, Ordering) { self.shl_prec_round_ref(bits, prec, Nearest) } /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with /// the specified precision. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// x \gets x2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0(&mut self, bits: T, prec: u64) -> Ordering { self.shl_prec_round_assign(bits, prec, Nearest) } } fn shl_round_primitive_int_ref( x: &Float, bits: T, rm: RoundingMode, ) -> (Float, Ordering) { if let Float(Finite { significand, exponent, sign, precision, }) = x { let mut possibly_just_under_min = false; if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_add(bits) { possibly_just_under_min = true; if (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent) { return ( Float(Finite { significand: significand.clone(), exponent: new_exponent, sign: *sign, precision: *precision, }), Equal, ); } } assert!(rm != Exact, "Inexact Float left-shift"); if bits > T::ZERO { match (*sign, rm) { (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater), (true, Floor | Down) => (Float::max_finite_value_with_prec(*precision), Less), (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less), (false, Ceiling | Down) => { (-Float::max_finite_value_with_prec(*precision), Greater) } (_, Exact) => unreachable!(), } } else if rm == Nearest && possibly_just_under_min && *exponent + >::saturating_into(bits) == Float::MIN_EXPONENT - 1 && !significand.is_power_of_2() { if *sign { (Float::min_positive_value_prec(*precision), Greater) } else { (-Float::min_positive_value_prec(*precision), Less) } } else { match (*sign, rm) { (true, Up | Ceiling) => (Float::min_positive_value_prec(*precision), Greater), (true, Floor | Down | Nearest) => (Float::ZERO, Less), (false, Up | Floor) => (-Float::min_positive_value_prec(*precision), Less), (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater), (_, Exact) => unreachable!(), } } } else { (x.clone(), Equal) } } #[inline] fn shl_round_assign_primitive_int( x: &mut Float, bits: T, rm: RoundingMode, ) -> Ordering { x.shl_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal) } macro_rules! impl_natural_shl_round { ($t:ident) => { impl ShlRound<$t> for Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with /// the specified rounding mode and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x,k,m) = x2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0 (Float, Ordering) { let o = self.shl_round_assign(bits, rm); (self, o) } } impl ShlRound<$t> for &Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with /// the specified rounding mode and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x,k,m) = x2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0 (Float, Ordering) { shl_round_primitive_int_ref(self, bits, rm) } } impl ShlRoundAssign<$t> for Float { /// Left-shifts a [`Float`] (multiplies it by a power of 2), in place, rounding the /// result with the specified rounding mode. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// precision is unchanged. /// /// $$ /// x\gets x2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0 Ordering { shl_round_assign_primitive_int(self, bits, rm) } } }; } apply_to_primitive_ints!(impl_natural_shl_round); ================================================ FILE: malachite-float/src/arithmetic/shr.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign}; use core::ops::{Shr, ShrAssign}; use malachite_base::rounding_modes::RoundingMode::*; macro_rules! impl_shr { ($t:ident) => { impl Shr<$t> for Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), taking it by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x, k) = x/2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { self.shr_round(bits, Nearest).0 } } impl Shr<$t> for &Float { type Output = Float; /// Left-shifts a [`Float`] (multiplies it by a power of 2), taking it by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x, k) = x/2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { self.shr_round(bits, Nearest).0 } } impl ShrAssign<$t> for Float { /// Left-shifts a [`Float`] (multiplies it by a power of 2), in place. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// precision is unchanged. /// /// $$ /// x \gets x/2^k. /// $$ /// /// - If $f(x,k)\geq 2^{2^{30}-1}$, $\infty$ is assigned instead. /// - If $f(x,k)\leq -2^{2^{30}-1}$, $-\infty$ is assigned instead. /// - If $0. use crate::Float; use crate::InnerFloat::Finite; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShrRound, ShrRoundAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::SaturatingInto; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { pub(crate) fn shr_prec_round_assign_helper( &mut self, bits: T, prec: u64, rm: RoundingMode, previous_o: Ordering, ) -> Ordering { if let Self(Finite { significand, exponent, sign, precision, }) = self { let mut possibly_just_under_min = false; if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_sub(bits) { possibly_just_under_min = true; if (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&new_exponent) { *exponent = new_exponent; return previous_o; } } assert!(rm != Exact, "Inexact Float right-shift"); if bits < T::ZERO { match (*sign, rm) { (true, Up | Ceiling | Nearest) => { *self = Self::INFINITY; Greater } (true, Floor | Down) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Up | Floor | Nearest) => { *self = Self::NEGATIVE_INFINITY; Less } (false, Ceiling | Down) => { *self = -Self::max_finite_value_with_prec(prec); Greater } (_, Exact) => unreachable!(), } } else if rm == Nearest && possibly_just_under_min && *exponent - >::saturating_into(bits) == Self::MIN_EXPONENT - 1 && (previous_o == if *sign { Less } else { Greater } || !significand.is_power_of_2()) { if *sign { *self = Self::min_positive_value_prec(*precision); Greater } else { *self = -Self::min_positive_value_prec(*precision); Less } } else { match (*sign, rm) { (true, Up | Ceiling) => { *self = Self::min_positive_value_prec(prec); Greater } (true, Floor | Down | Nearest) => { *self = Self::ZERO; Less } (false, Up | Floor) => { *self = -Self::min_positive_value_prec(prec); Less } (false, Ceiling | Down | Nearest) => { *self = Self::NEGATIVE_ZERO; Greater } (_, Exact) => unreachable!(), } } } else { Equal } } /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified rounding mode and precision, and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p,m) = x/2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed /// exactly with the specified precision. /// /// # Examples /// See [here](super::shr_round#shr_prec_round). pub fn shr_prec_round( mut self, bits: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let o = self.shr_prec_round_assign(bits, prec, rm); (self, o) } /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified rounding mode and precision, and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p,m) = x/2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed /// exactly with the specified precision. /// /// # Examples /// See [here](super::shr_round#shr_prec_round). pub fn shr_prec_round_ref( &self, bits: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let mut x = self.clone(); let o = x.shr_prec_round_assign(bits, prec, rm); (x, o) } /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the /// specified rounding mode and precision. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// x \gets x/2^k. /// $$ /// /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`. /// - If $0>=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed /// exactly with the specified precision. /// /// # Examples /// See [here](super::shr_round#shr_prec_round). pub fn shr_prec_round_assign( &mut self, bits: T, prec: u64, rm: RoundingMode, ) -> Ordering { if let Self(Finite { exponent, .. }) = self { let old_exponent = *exponent; *exponent = 0; let o = self.set_prec_round(prec, rm); self.shr_prec_round_assign_helper( >::saturating_into(bits).saturating_sub(old_exponent), prec, rm, o, ) } else { Equal } } /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified precision, and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p) = x/2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::shr_round#shr_prec). #[inline] pub fn shr_prec(self, bits: T, prec: u64) -> (Self, Ordering) { self.shr_prec_round(bits, prec, Nearest) } /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified precision, and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// f(x,k,p) = x/2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::shr_round#shr_prec). #[inline] pub fn shr_prec_ref(&self, bits: T, prec: u64) -> (Self, Ordering) { self.shr_prec_round_ref(bits, prec, Nearest) } /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the /// specified precision. /// /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`. /// /// $$ /// x \gets x/2^k. /// $$ /// /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0>=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::shr_round#shr_prec). #[inline] pub fn shr_prec_assign(&mut self, bits: T, prec: u64) -> Ordering { self.shr_prec_round_assign(bits, prec, Nearest) } } fn shr_round_primitive_int_ref( x: &Float, bits: T, rm: RoundingMode, ) -> (Float, Ordering) { if let Float(Finite { significand, exponent, sign, precision, }) = x { let mut possibly_just_under_min = false; if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_sub(bits) { possibly_just_under_min = true; if (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent) { return ( Float(Finite { significand: significand.clone(), exponent: new_exponent, sign: *sign, precision: *precision, }), Equal, ); } } assert!(rm != Exact, "Inexact Float right-shift"); if bits < T::ZERO { match (*sign, rm) { (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater), (true, Floor | Down) => (Float::max_finite_value_with_prec(*precision), Less), (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less), (false, Ceiling | Down) => { (-Float::max_finite_value_with_prec(*precision), Greater) } (_, Exact) => unreachable!(), } } else if rm == Nearest && possibly_just_under_min && *exponent - >::saturating_into(bits) == Float::MIN_EXPONENT - 1 && !significand.is_power_of_2() { if *sign { (Float::min_positive_value_prec(*precision), Greater) } else { (-Float::min_positive_value_prec(*precision), Less) } } else { match (*sign, rm) { (true, Up | Ceiling) => (Float::min_positive_value_prec(*precision), Greater), (true, Floor | Down | Nearest) => (Float::ZERO, Less), (false, Up | Floor) => (-Float::min_positive_value_prec(*precision), Less), (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater), (_, Exact) => unreachable!(), } } } else { (x.clone(), Equal) } } fn shr_round_assign_primitive_int( x: &mut Float, bits: T, rm: RoundingMode, ) -> Ordering { x.shr_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal) } macro_rules! impl_natural_shr_round { ($t:ident) => { impl ShrRound<$t> for Float { type Output = Float; /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified rounding mode and taking the [`Float`] by value. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x,k,m) = x/2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if the result overflows or underflows and `rm` is `Exact`. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Float, Ordering) { let o = self.shr_round_assign(bits, rm); (self, o) } } impl ShrRound<$t> for &Float { type Output = Float; /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the /// specified rounding mode and taking the [`Float`] by reference. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// output has the same precision. /// /// $$ /// f(x,k,m) = x/2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0>` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if the result overflows or underflows and `rm` is `Exact`. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $t, rm: RoundingMode) -> (Float, Ordering) { shr_round_primitive_int_ref(self, bits, rm) } } impl ShrRoundAssign<$t> for Float { /// Right-shifts a [`Float`] (divides it by a power of 2), in place, rounding the result /// with the specified rounding mode. /// /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the /// precision is unchanged. /// /// $$ /// x\gets x/2^k. /// $$ /// /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ /// is returned instead. /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the /// input. /// - If $0>=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if the result overflows or underflows and `rm` is `Exact`. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shr_round_assign_primitive_int(self, bits, rm) } } }; } apply_to_primitive_ints!(impl_natural_shr_round); ================================================ FILE: malachite-float/src/arithmetic/sign.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; impl Sign for Float { /// Returns the sign of a [`Float`]. /// /// Returns `Greater` if the sign is positive and `Less` if the sign is negative. Never returns /// `Equal`. $\infty$ and positive zero have a positive sign, and $-\infty$ and negative zero /// have a negative sign. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is NaN. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Sign; /// use malachite_base::num::basic::traits::{ /// Infinity, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// assert_eq!(Float::INFINITY.sign(), Greater); /// assert_eq!(Float::NEGATIVE_INFINITY.sign(), Less); /// assert_eq!(Float::ZERO.sign(), Greater); /// assert_eq!(Float::NEGATIVE_ZERO.sign(), Less); /// assert_eq!(Float::ONE.sign(), Greater); /// assert_eq!(Float::NEGATIVE_ONE.sign(), Less); /// ``` fn sign(&self) -> Ordering { if let Self(Infinity { sign } | Zero { sign } | Finite { sign, .. }) = self { if *sign { Greater } else { Less } } else { panic!() } } } ================================================ FILE: malachite-float/src/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::conversion::from_natural::{from_natural_zero_exponent, from_natural_zero_exponent_ref}; use crate::{ Float, emulate_rational_to_float_fn, float_infinity, float_nan, float_negative_infinity, float_negative_zero, float_zero, }; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, CheckedSqrt, FloorLogBase2, Parity, Sqrt, SqrtAssign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::NaN as NanTrait; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::natural::arithmetic::float_sqrt::{ sqrt_float_significand_in_place, sqrt_float_significand_ref, }; use malachite_nz::platform::Limb; use malachite_q::Rational; pub_crate_test! { generic_sqrt_rational_ref(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; let mut end_shift = x.floor_log_base_2(); let x2; let reduced_x: &Rational; if end_shift.gt_abs(&0x3fff_0000) { end_shift &= !1; x2 = x >> end_shift; reduced_x = &x2; } else { end_shift = 0; reduced_x = x; } loop { let sqrt = Float::from_rational_prec_round_ref(reduced_x, working_prec, Floor).0.sqrt(); // See algorithms.tex. Since we rounded down when computing fx, the absolute error of the // square root is bounded by (c_sqrt + k_fx)ulp(sqrt) <= 2ulp(sqrt). // // Experiments suggest that `working_prec` is low enough (that is, that the error is at most // 1 ulp), but I can only prove `working_prec - 1`. if float_can_round(sqrt.significand_ref().unwrap(), working_prec - 1, prec, rm) { let (mut sqrt, mut o) = Float::from_float_prec_round(sqrt, prec, rm); if end_shift != 0 { o = sqrt.shl_prec_round_assign_helper(end_shift >> 1, prec, rm, o); } return (sqrt, o); } working_prec += increment; increment = working_prec >> 1; } }} pub(crate) fn generic_sqrt_rational( mut x: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; let mut end_shift = x.floor_log_base_2(); if end_shift.gt_abs(&0x3fff_0000) { end_shift &= !1; x >>= end_shift; } else { end_shift = 0; } loop { let sqrt = Float::from_rational_prec_round_ref(&x, working_prec, Floor) .0 .sqrt(); // See algorithms.tex. Since we rounded down when computing fx, the absolute error of the // square root is bounded by (c_sqrt + k_fx)ulp(sqrt) <= 2ulp(sqrt). // // Experiments suggest that `working_prec` is low enough (that is, that the error is at most // 1 ulp), but I can only prove `working_prec - 1`. if float_can_round(sqrt.significand_ref().unwrap(), working_prec - 1, prec, rm) { let (mut sqrt, mut o) = Float::from_float_prec_round(sqrt, prec, rm); if end_shift != 0 { o = sqrt.shl_prec_round_assign_helper(end_shift >> 1, prec, rm, o); } return (sqrt, o); } working_prec += increment; increment = working_prec >> 1; } } impl Float { /// Computes the square root of a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded square root is less than, equal to, or greater than /// the exact square root. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=\infty$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(0.0,p,m)=0.0$ /// - $f(-0.0,p,m)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::sqrt_prec`] instead. If you /// know that your target precision is the precision of the input, consider using /// [`Float::sqrt_round`] instead. If both of these things are true, consider using /// [`Float::sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(5, Floor); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(5, Ceiling); /// assert_eq!(sqrt.to_string(), "1.81"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(5, Nearest); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(20, Floor); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(20, Ceiling); /// assert_eq!(sqrt.to_string(), "1.772455"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round(20, Nearest); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_prec_round(mut self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { let o = self.sqrt_prec_round_assign(prec, rm); (self, o) } /// Computes the square root of a [`Float`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is /// also returned, indicating whether the rounded square root is less than, equal to, or greater /// than the exact square root. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\infty,p,m)=\infty$ /// - $f(-\infty,p,m)=\text{NaN}$ /// - $f(0.0,p,m)=0.0$ /// - $f(-0.0,p,m)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you know you'll be using `Nearest`, consider using [`Float::sqrt_prec_ref`] instead. If /// you know that your target precision is the precision of the input, consider using /// [`Float::sqrt_round_ref`] instead. If both of these things are true, consider using /// `(&Float).sqrt()`instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(5, Floor); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(5, Ceiling); /// assert_eq!(sqrt.to_string(), "1.81"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(5, Nearest); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(20, Floor); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(20, Ceiling); /// assert_eq!(sqrt.to_string(), "1.772455"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_round_ref(20, Nearest); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); match self { Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal), float_infinity!() => (float_infinity!(), Equal), float_zero!() => (float_zero!(), Equal), float_negative_zero!() => (float_negative_zero!(), Equal), Self(Finite { sign, exponent: x_exp, precision: x_prec, significand: x, .. }) => { if !sign { return (float_nan!(), Equal); } let (sqrt, exp, o) = sqrt_float_significand_ref(x, *x_exp, *x_prec, prec, rm); ( Self(Finite { sign: true, exponent: exp, precision: prec, significand: sqrt, }), o, ) } } } /// Computes the square root of a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned, /// indicating whether the rounded square root is less than, equal to, or greater than the exact /// square root. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// If the square root is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=\infty$ /// - $f(-\infty,p)=\text{NaN}$ /// - $f(0.0,p)=0.0$ /// - $f(-0.0,p)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sqrt_prec_round`] instead. If you know that your target precision is the precision /// of the input, consider using [`Float::sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_prec(5); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec(20); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_prec(self, prec: u64) -> (Self, Ordering) { self.sqrt_prec_round(prec, Nearest) } /// Computes the square root of a [`Float`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded square root is less than, equal to, or greater than the exact /// square root. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// If the square root is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\infty,p)=\infty$ /// - $f(-\infty,p)=\text{NaN}$ /// - $f(0.0,p)=0.0$ /// - $f(-0.0,p)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sqrt_prec_round_ref`] instead. If you know that your target precision is the /// precision of the input, consider using `(&Float).sqrt()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_ref(5); /// assert_eq!(sqrt.to_string(), "1.75"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_prec_ref(20); /// assert_eq!(sqrt.to_string(), "1.772453"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_prec_ref(&self, prec: u64) -> (Self, Ordering) { self.sqrt_prec_round_ref(prec, Nearest) } /// Computes the square root of a [`Float`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether /// the rounded square root is less than, equal to, or greater than the exact square root. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=\infty$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(0.0,m)=0.0$ /// - $f(-0.0,m)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::sqrt_prec_round`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_round(Floor); /// assert_eq!(sqrt.to_string(), "1.772453850905515"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_round(Ceiling); /// assert_eq!(sqrt.to_string(), "1.772453850905517"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_round(Nearest); /// assert_eq!(sqrt.to_string(), "1.772453850905515"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_round(self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.sqrt_prec_round(prec, rm) } /// Computes the square root of a [`Float`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating /// whether the rounded square root is less than, equal to, or greater than the exact square /// root. Although `NaN`s are not comparable to any [`Float`], whenever this function returns a /// `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\infty,m)=\infty$ /// - $f(-\infty,m)=\text{NaN}$ /// - $f(0.0,m)=0.0$ /// - $f(-0.0,m)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to specify an output precision, consider using [`Float::sqrt_prec_round_ref`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// `(&Float).sqrt()` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt, o) = Float::from(PI).sqrt_round_ref(Floor); /// assert_eq!(sqrt.to_string(), "1.772453850905515"); /// assert_eq!(o, Less); /// /// let (sqrt, o) = Float::from(PI).sqrt_round_ref(Ceiling); /// assert_eq!(sqrt.to_string(), "1.772453850905517"); /// assert_eq!(o, Greater); /// /// let (sqrt, o) = Float::from(PI).sqrt_round_ref(Nearest); /// assert_eq!(sqrt.to_string(), "1.772453850905515"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) { let prec = self.significant_bits(); self.sqrt_prec_round_ref(prec, rm) } /// Computes the square root of a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. An [`Ordering`] is returned, indicating /// whether the rounded square root is less than, equal to, or greater than the exact square /// root. Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sqrt_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::sqrt_prec_assign`] instead. /// If you know that your target precision is the precision of the input, consider using /// [`Float::sqrt_round_assign`] instead. If both of these things are true, consider using /// [`Float::sqrt_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the given /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(5, Floor), Less); /// assert_eq!(x.to_string(), "1.75"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "1.81"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(5, Nearest), Less); /// assert_eq!(x.to_string(), "1.75"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(20, Floor), Less); /// assert_eq!(x.to_string(), "1.772453"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(20, Ceiling), Greater); /// assert_eq!(x.to_string(), "1.772455"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_round_assign(20, Nearest), Less); /// assert_eq!(x.to_string(), "1.772453"); /// ``` #[inline] pub fn sqrt_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match self { Self(NaN | Infinity { sign: true } | Zero { .. }) => Equal, float_negative_infinity!() => { *self = float_nan!(); Equal } Self(Finite { sign, exponent: x_exp, precision: x_prec, significand: x, .. }) => { if !*sign { *self = float_nan!(); return Equal; } let o; (*x_exp, o) = sqrt_float_significand_in_place(x, *x_exp, *x_prec, prec, rm); *x_prec = prec; o } } } /// Computes the square root of a [`Float`] in place, rounding the result to the nearest value /// of the specified precision. An [`Ordering`] is returned, indicating whether the rounded /// square root is less than, equal to, or greater than the exact square root. Although `NaN`s /// are not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it /// also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// If the square root is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sqrt_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sqrt_prec_round_assign`] instead. If you know that your target precision is the /// precision of the input, consider using [`Float::sqrt`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_assign(5), Less); /// assert_eq!(x.to_string(), "1.75"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_prec_assign(20), Less); /// assert_eq!(x.to_string(), "1.772453"); /// ``` #[inline] pub fn sqrt_prec_assign(&mut self, prec: u64) -> Ordering { self.sqrt_prec_round_assign(prec, Nearest) } /// Computes the square root of a [`Float`] in place, rounding the result with the specified /// rounding mode. An [`Ordering`] is returned, indicating whether the rounded square root is /// less than, equal to, or greater than the exact square root. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// x \gets \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// /// See the [`Float::sqrt_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::sqrt_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using /// [`Float::sqrt_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Panics /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input /// precision. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_round_assign(Floor), Less); /// assert_eq!(x.to_string(), "1.772453850905515"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_round_assign(Ceiling), Greater); /// assert_eq!(x.to_string(), "1.772453850905517"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sqrt_round_assign(Nearest), Less); /// assert_eq!(x.to_string(), "1.772453850905515"); /// ``` #[inline] pub fn sqrt_round_assign(&mut self, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.sqrt_prec_round_assign(prec, rm) } /// Computes the square root of a [`Rational`], rounding the result to the specified precision /// and with the specified rounding mode and returning the result as a [`Float`]. The /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded square root is less than, equal to, or greater than the exact square root. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); if x < 0u32 { return (Self::NAN, Equal); } if let Some(sqrt) = (&x).checked_sqrt() { return Self::from_rational_prec_round(sqrt, prec, rm); } let (n, d) = x.numerator_and_denominator_ref(); match (n.checked_log_base_2(), d.checked_log_base_2()) { (_, Some(log_d)) if log_d.even() => { let n = x.into_numerator(); let n_exp = n.significant_bits(); let mut n = from_natural_zero_exponent(n); if n_exp.odd() { n <<= 1u32; } let (mut sqrt, o) = Self::exact_from(n).sqrt_prec_round(prec, rm); let o = sqrt.shr_prec_round_assign_helper( i128::from(log_d >> 1) - i128::from(n_exp >> 1), prec, rm, o, ); (sqrt, o) } (Some(log_n), _) if log_n.even() => { let d = x.into_denominator(); let d_exp = d.significant_bits(); let mut d = from_natural_zero_exponent(d); if d_exp.odd() { d <<= 1u32; } let (mut reciprocal_sqrt, o) = Self::exact_from(d).reciprocal_sqrt_prec_round(prec, rm); let o = reciprocal_sqrt.shl_prec_round_assign_helper( i128::from(log_n >> 1) - i128::from(d_exp >> 1), prec, rm, o, ); (reciprocal_sqrt, o) } _ => generic_sqrt_rational(x, prec, rm), } } /// Computes the square root of a [`Rational`], rounding the result to the specified precision /// and with the specified rounding mode and returning the result as a [`Float`]. The /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded square root is less than, equal to, or greater than the exact square root. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p+1}$. /// - If $\sqrt{x}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); if *x < 0u32 { return (Self::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Self::from_rational_prec_round(sqrt, prec, rm); } let (n, d) = x.numerator_and_denominator_ref(); match (n.checked_log_base_2(), d.checked_log_base_2()) { (_, Some(log_d)) if log_d.even() => { let n_exp = n.significant_bits(); let mut n = from_natural_zero_exponent_ref(n); if n_exp.odd() { n <<= 1u32; } let (mut sqrt, o) = Self::exact_from(n).sqrt_prec_round(prec, rm); let o = sqrt.shr_prec_round_assign_helper( i128::from(log_d >> 1) - i128::from(n_exp >> 1), prec, rm, o, ); (sqrt, o) } (Some(log_n), _) if log_n.even() => { let d_exp = d.significant_bits(); let mut d = from_natural_zero_exponent_ref(d); if d_exp.odd() { d <<= 1u32; } let (mut reciprocal_sqrt, o) = Self::exact_from(d).reciprocal_sqrt_prec_round(prec, rm); let o = reciprocal_sqrt.shl_prec_round_assign_helper( i128::from(log_n >> 1) - i128::from(d_exp >> 1), prec, rm, o, ); (reciprocal_sqrt, o) } _ => generic_sqrt_rational_ref(x, prec, rm), } } /// Computes the square root of a [`Rational`], rounding the result to the nearest value of the /// specified precision and returning the result as a [`Float`]. The [`Rational`] is taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded square root is less /// than, equal to, or greater than the exact square root. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// If the square root is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { Self::sqrt_rational_prec_round(x, prec, Nearest) } /// Computes the square root of a [`Rational`], rounding the result to the nearest value of the /// specified precision and returning the result as a [`Float`]. The [`Rational`] is taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded square root is /// less than, equal to, or greater than the exact square root. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The square root of any nonzero negative number is `NaN`. /// /// If the square root is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,p) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(0.0,p)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { Self::sqrt_rational_prec_round_ref(x, prec, Nearest) } } impl Sqrt for Float { type Output = Self; /// Computes the square root of a [`Float`], taking it by value. /// /// If the output has a precision, it is the precision of the input. If the square root is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The square root of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=\infty$ /// - $f(-\infty)=\text{NaN}$ /// - $f(0.0)=0.0$ /// - $f(-0.0)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::sqrt_prec`] /// instead. If you want to specify the output precision, consider using [`Float::sqrt_round`]. /// If you want both of these things, consider using [`Float::sqrt_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Sqrt; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!(Float::NAN.sqrt().is_nan()); /// assert_eq!(Float::INFINITY.sqrt(), Float::INFINITY); /// assert!(Float::NEGATIVE_INFINITY.sqrt().is_nan()); /// assert_eq!(Float::from(1.5).sqrt(), 1.0); /// assert!(Float::from(-1.5).sqrt().is_nan()); /// ``` #[inline] fn sqrt(self) -> Self { let prec = self.significant_bits(); self.sqrt_prec_round(prec, Nearest).0 } } impl Sqrt for &Float { type Output = Float; /// Computes the square root of a [`Float`], taking it by reference. /// /// If the output has a precision, it is the precision of the input. If the square root is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The square root of any nonzero negative number is `NaN`. /// /// $$ /// f(x) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\infty)=\infty$ /// - $f(-\infty)=\text{NaN}$ /// - $f(0.0)=0.0$ /// - $f(-0.0)=-0.0$ /// /// Neither overflow nor underflow is possible. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sqrt_prec_ref`] instead. If you want to specify the output precision, consider /// using [`Float::sqrt_round_ref`]. If you want both of these things, consider using /// [`Float::sqrt_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Sqrt; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!((&Float::NAN).sqrt().is_nan()); /// assert_eq!((&Float::INFINITY).sqrt(), Float::INFINITY); /// assert!((&Float::NEGATIVE_INFINITY).sqrt().is_nan()); /// assert_eq!((&Float::from(1.5)).sqrt(), 1.0); /// assert!((&Float::from(-1.5)).sqrt().is_nan()); /// ``` #[inline] fn sqrt(self) -> Float { let prec = self.significant_bits(); self.sqrt_prec_round_ref(prec, Nearest).0 } } impl SqrtAssign for Float { /// Computes the square root of a [`Float`] in place. /// /// If the output has a precision, it is the precision of the input. If the square root is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The square root of any nonzero negative number is `NaN`. /// /// $$ /// x\gets = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be /// 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// See the [`Float::sqrt`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sqrt_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::sqrt_round_assign`]. If you want both of these things, consider using /// [`Float::sqrt_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SqrtAssign; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::NAN; /// x.sqrt_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x.sqrt_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.sqrt_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x.sqrt_assign(); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(-1.5); /// x.sqrt_assign(); /// assert!(x.is_nan()); /// ``` #[inline] fn sqrt_assign(&mut self) { let prec = self.significant_bits(); self.sqrt_prec_round_assign(prec, Nearest); } } /// Computes the square root of a [`Rational`], returning a primitive float result. /// /// If the square root is equidistant from two primitive floats, the primitive float with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// The square root of any negative number is `NaN`. /// /// $$ /// f(x) = \sqrt{x}+\varepsilon. /// $$ /// - If $\sqrt{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $\sqrt{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 /// \sqrt{x}\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] /// and 53 if `T` is a [`f64`], but less if the output is subnormal). /// /// Special cases: /// - $f(0)=0.0$ /// /// Overflow: /// - If the absolute value of the result is too large to represent, $\infty$ is returned instead. /// - If the absolute value of the result is too small to represent, 0.0 is returned instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::arithmetic::sqrt::primitive_float_sqrt_rational; /// use malachite_q::Rational; /// /// assert_eq!( /// NiceFloat(primitive_float_sqrt_rational::(&Rational::ZERO)), /// NiceFloat(0.0) /// ); /// assert_eq!( /// NiceFloat(primitive_float_sqrt_rational::( /// &Rational::from_unsigneds(1u8, 3) /// )), /// NiceFloat(0.5773502691896257) /// ); /// assert_eq!( /// NiceFloat(primitive_float_sqrt_rational::(&Rational::from(10000))), /// NiceFloat(100.0) /// ); /// assert_eq!( /// NiceFloat(primitive_float_sqrt_rational::(&Rational::from( /// -10000 /// ))), /// NiceFloat(f64::NAN) /// ); /// ``` #[inline] #[allow(clippy::type_repetition_in_bounds)] pub fn primitive_float_sqrt_rational(x: &Rational) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { emulate_rational_to_float_fn(Float::sqrt_rational_prec_ref, x) } ================================================ FILE: malachite-float/src/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ Float, float_either_infinity, float_either_zero, float_infinity, float_nan, float_zero, }; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, IsPowerOf2, Square, SquareAssign, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_square::{ square_float_significand_in_place, square_float_significand_ref, }; impl Float { /// Squares a [`Float`], rounding the result to the specified precision and with the specified /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating /// whether the rounded square is less than, equal to, or greater than the exact square. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\pm\infty,p,m)=\infty$ /// - $f(\pm0.0,p,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.square_prec_round_assign(prec, rm); (self, o) } /// Squares a [`Float`], rounding the result to the specified precision and with the specified /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded square is less than, equal to, or greater than the exact /// square. Although `NaN`s are not comparable to any [`Float`], whenever this function returns /// a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,p,m) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p,m)=\text{NaN}$ /// - $f(\pm\infty,p,m)=\infty$ /// - $f(\pm0.0,p,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match self { float_nan!() => (float_nan!(), Equal), float_either_infinity!() => (float_infinity!(), Equal), float_either_zero!() => (float_zero!(), Equal), Self(Finite { exponent: x_exp, precision: x_prec, significand: x, .. }) => { let twice_exp = x_exp << 1; if twice_exp - 1 > Self::MAX_EXPONENT { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Ceiling | Up | Nearest => (float_infinity!(), Greater), _ => (Self::max_finite_value_with_prec(prec), Less), }; } else if twice_exp < Self::MIN_EXPONENT - 1 { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Floor | Down | Nearest => (float_zero!(), Less), _ => (Self::min_positive_value_prec(prec), Greater), }; } let (square, exp_offset, o) = square_float_significand_ref(x, *x_prec, prec, rm); let exp = x_exp .arithmetic_checked_shl(1u32) .unwrap() .checked_add(exp_offset) .unwrap(); if exp > Self::MAX_EXPONENT { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Ceiling | Up | Nearest => (float_infinity!(), Greater), _ => (Self::max_finite_value_with_prec(prec), Less), }; } else if exp < Self::MIN_EXPONENT { return if rm == Nearest && exp == Self::MIN_EXPONENT - 1 && (o == Less || !square.is_power_of_2()) { (Self::min_positive_value_prec(prec), Greater) } else { match rm { Exact => panic!("Inexact float squaring"), Ceiling | Up => (Self::min_positive_value_prec(prec), Greater), _ => (float_zero!(), Less), } }; } ( Self(Finite { sign: true, exponent: exp, precision: prec, significand: square, }), o, ) } } } /// Squares a [`Float`], rounding the result to the nearest value of the specified precision. /// The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded square is less than, equal to, or greater than the exact square. Although `NaN`s are /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,p) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\pm\infty,p)=\infty$ /// - $f(\pm0.0,p)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.square_prec_round(prec, Nearest) } /// Squares a [`Float`], rounding the result to the nearest value of the specified precision. /// The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating whether /// the rounded square is less than, equal to, or greater than the exact square. Although `NaN`s /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns /// `Equal`. /// /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,p) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},p)=\text{NaN}$ /// - $f(\pm\infty,p)=\infty$ /// - $f(\pm0.0,p)=0.0$ /// /// Overflow and underflow: /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.square_prec_round_ref(prec, Nearest) } /// Squares a [`Float`], rounding the result with the specified rounding mode. The [`Float`] is /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded square is /// less than, equal to, or greater than the exact square. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\pm\infty,m)=\infty$ /// - $f(\pm0.0,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.square_prec_round(prec, rm) } /// Squares a [`Float`], rounding the result with the specified rounding mode. The [`Float`] is /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded square /// is less than, equal to, or greater than the exact square. Although `NaN`s are not comparable /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// f(x,m) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input. /// /// If the output has a precision, it is the precision of the input. /// /// Special cases: /// - $f(\text{NaN},m)=\text{NaN}$ /// - $f(\pm\infty,m)=\infty$ /// - $f(\pm0.0,m)=0.0$ /// /// Overflow and underflow: /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is returned /// instead. /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.square_prec_round_ref(prec, rm) } /// Squares a [`Float`] in place, rounding the result to the specified precision and with the /// specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded square /// is less than, equal to, or greater than the exact square. Although `NaN`s are not comparable /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns /// `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::square_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::square_prec_assign`] instead. /// If you know that your target precision is the precision of the input, consider using /// [`Float::square_round_assign`] instead. If both of these things are true, consider using /// [`Float::square_assign`] instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact squaring; /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(5, Floor), Less); /// assert_eq!(x.to_string(), "9.5"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(5, Ceiling), Greater); /// assert_eq!(x.to_string(), "10.0"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(5, Nearest), Greater); /// assert_eq!(x.to_string(), "10.0"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(20, Floor), Less); /// assert_eq!(x.to_string(), "9.8696"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(20, Ceiling), Greater); /// assert_eq!(x.to_string(), "9.86961"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_round_assign(20, Nearest), Less); /// assert_eq!(x.to_string(), "9.8696"); /// ``` #[inline] pub fn square_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match self { float_nan!() => Equal, Self(Infinity { sign } | Zero { sign }) => { *sign = true; Equal } Self(Finite { sign: x_sign, exponent: x_exp, precision: x_prec, significand: x, }) => { let twice_exp = *x_exp << 1; if twice_exp - 1 > Self::MAX_EXPONENT { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Ceiling | Up | Nearest => { *self = float_infinity!(); Greater } _ => { *self = Self::max_finite_value_with_prec(prec); Less } }; } else if twice_exp < Self::MIN_EXPONENT - 1 { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Floor | Down | Nearest => { *self = float_zero!(); Less } _ => { *self = Self::min_positive_value_prec(prec); Greater } }; } let (exp_offset, o) = square_float_significand_in_place(x, *x_prec, prec, rm); *x_exp = x_exp .arithmetic_checked_shl(1u32) .unwrap() .checked_add(exp_offset) .unwrap(); if *x_exp > Self::MAX_EXPONENT { assert!(rm != Exact, "Inexact Float squaring"); return match rm { Ceiling | Up | Nearest => { *self = float_infinity!(); Greater } _ => { *self = Self::max_finite_value_with_prec(prec); Less } }; } else if *x_exp < Self::MIN_EXPONENT { return if rm == Nearest && *x_exp == Self::MIN_EXPONENT - 1 && (o == Less || !x.is_power_of_2()) { { *self = Self::min_positive_value_prec(prec); Greater } } else { match rm { Exact => panic!("Inexact float squaring"), Ceiling | Up => { *self = Self::min_positive_value_prec(prec); Greater } _ => { *self = float_zero!(); Less } } }; } *x_sign = true; *x_prec = prec; o } } } /// Squares a [`Float`] in place, rounding the result to the nearest value of the specified /// precision. An [`Ordering`] is returned, indicating whether the rounded square is less than, /// equal to, or greater than the exact square. Although `NaN`s are not comparable to any /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x \gets x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::square_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::square_prec_round_assign`] instead. If you know that your target precision is the /// precision of the input, consider using [`Float::square`] instead. /// /// # Worst-case complexity /// $T(n, m) = O(n \log n \log\log n + m)$ /// /// $M(n, m) = O(n \log n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `prec`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_assign(5), Greater); /// assert_eq!(x.to_string(), "10.0"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_prec_assign(20), Less); /// assert_eq!(x.to_string(), "9.8696"); /// ``` #[inline] pub fn square_prec_assign(&mut self, prec: u64) -> Ordering { self.square_prec_round_assign(prec, Nearest) } /// Squares a [`Float`] in place, rounding the result with the specified rounding mode. An /// [`Ordering`] is returned, indicating whether the rounded square is less than, equal to, or /// greater than the exact square. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input. See [`RoundingMode`] for a /// description of the possible rounding modes. /// /// $$ /// x \gets x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the precision of the input. /// /// See the [`Float::square_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::square_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using [`Float::square_assign`] instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the /// output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_round_assign(Floor), Less); /// assert_eq!(x.to_string(), "9.86960440108935"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_round_assign(Ceiling), Greater); /// assert_eq!(x.to_string(), "9.86960440108936"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.square_round_assign(Nearest), Greater); /// assert_eq!(x.to_string(), "9.86960440108936"); /// ``` #[inline] pub fn square_round_assign(&mut self, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.square_prec_round_assign(prec, rm) } } impl Square for Float { type Output = Self; /// Squares a [`Float`], taking it by value. /// /// If the output has a precision, it is the precision of the input. If the square is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\pm\infty)=\infty$ /// - $f(\pm0.0)=0.0$ /// /// Overflow and underflow: /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.square_prec_round(prec, Nearest).0 } } impl Square for &Float { type Output = Float; /// Squares a [`Float`], taking it by reference. /// /// If the output has a precision, it is the precision of the input. If the square is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x) = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN})=\text{NaN}$ /// - $f(\pm\infty)=\infty$ /// - $f(\pm0.0)=0.0$ /// /// Overflow and underflow: /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.square_prec_round_ref(prec, Nearest).0 } } impl SquareAssign for Float { /// Squares a [`Float`] in place. /// /// If the output has a precision, it is the precision of the input. If the square is /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x^2+\varepsilon. /// $$ /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the [`Float::square`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::square_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::square_round_assign`]. If you want both of these things, consider using /// [`Float::square_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SquareAssign; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::NAN; /// x.square_assign(); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x.square_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x.square_assign(); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::from(1.5); /// x.square_assign(); /// assert_eq!(x, 2.0); /// /// let mut x = Float::from(-1.5); /// x.square_assign(); /// assert_eq!(x, 2.0); /// ``` #[inline] fn square_assign(&mut self) { let prec = self.significant_bits(); self.square_prec_round_assign(prec, Nearest); } } ================================================ FILE: malachite-float/src/arithmetic/sub.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 2001, 2003-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::InnerFloat::{Infinity, NaN, Zero}; use crate::{ Float, float_infinity, float_nan, float_negative_infinity, float_negative_zero, float_zero, }; use core::cmp::Ordering::{self, *}; use core::cmp::max; use core::ops::{Sub, SubAssign}; use malachite_base::num::arithmetic::traits::{CeilingLogBase2, NegAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; use malachite_q::Rational; // x and y must be finite, nonzero, and not equal fn float_rational_diff_exponent_range(x: &Float, y: &Rational) -> (i64, i64) { let log_x_abs = i64::from(x.get_exponent().unwrap() - 1); let log_y_abs = y.floor_log_base_2_abs(); let m = max(log_x_abs, log_y_abs); if (*x > 0) != (*y > 0) { (m, m + 1) } else if log_x_abs.abs_diff(log_y_abs) > 1 { (m - 1, m) } else { let mut log_x_denominator = i64::exact_from(x.get_prec().unwrap()) .saturating_sub(log_x_abs) .saturating_sub(1); if log_x_denominator < 0 { log_x_denominator = 0; } let log_y_denominator = i64::exact_from(y.denominator_ref().ceiling_log_base_2()); let min_exp = log_x_denominator .checked_neg() .unwrap() .checked_sub(log_y_denominator) .unwrap(); if log_x_abs == log_y_abs { (min_exp, m - 1) } else { (min_exp, m) } } } // x and y must be finite, nonzero, and not sum to zero fn float_rational_diff_sign(x: &Float, y: &Rational) -> bool { match ((*x > 0), (*y < 0)) { (true, true) => true, (false, false) => false, _ => { if x.gt_abs(y) { *x > 0 } else { *y < 0 } } } } fn sub_rational_prec_round_naive_ref_val( x: &Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x.clone(), Equal), (float_negative_zero!(), y) => { if y == 0u32 { (float_negative_zero!(), Equal) } else { Float::from_rational_prec_round(-y, prec, rm) } } (float_zero!(), y) => Float::from_rational_prec_round(-y, prec, rm), (x, y) => { let (mut sum, o) = Float::from_rational_prec_round(Rational::exact_from(x) - y, prec, rm); if rm == Floor && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } fn sub_rational_prec_round_naive_ref_ref( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x.clone(), Equal), (float_negative_zero!(), y) => { if *y == 0u32 { (float_negative_zero!(), Equal) } else { let (f, o) = Float::from_rational_prec_round_ref(y, prec, -rm); (-f, o.reverse()) } } (float_zero!(), y) => { let (f, o) = Float::from_rational_prec_round_ref(y, prec, -rm); (-f, o.reverse()) } (x, y) => { let (mut sum, o) = Float::from_rational_prec_round(Rational::exact_from(x) - y, prec, rm); if rm == Floor && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } impl Float { /// Subtracts two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,\infty,p,m)=f(-\infty,-\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p,m)=0.0$ /// - $f(-0.0,0.0,p,m)=-0.0$ /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.sub_prec_round_assign(other, prec, rm); (self, o) } /// Subtracts two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is taken by value and the second by reference. /// An [`Ordering`] is also returned, indicating whether the rounded difference is less than, /// equal to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,\infty,p,m)=f(-\infty,-\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p,m)=0.0$ /// - $f(-0.0,0.0,p,m)=-0.0$ /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.sub_prec_round_assign_ref(other, prec, rm); (self, o) } /// Subtracts two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. The first [`Float`] is taken by reference and the second by value. /// An [`Ordering`] is also returned, indicating whether the rounded difference is less than, /// equal to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,\infty,p,m)=f(-\infty,-\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p,m)=0.0$ /// - $f(-0.0,0.0,p,m)=-0.0$ /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { self.add_prec_round_ref_val(-other, prec, rm) } /// Subtracts two [`Float`]s, rounding the result to the specified precision and with the /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(\infty,\infty,p,m)=f(-\infty,-\infty,p,m)= /// \text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p,m)=0.0$ /// - $f(-0.0,0.0,p,m)=-0.0$ /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p,m)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { self.add_prec_round_ref_ref_helper(other, prec, rm, true) } /// Subtracts two [`Float`]s, rounding the result to the nearest value of the specified /// precision. Both [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating /// whether the rounded difference is less than, equal to, or greater than the exact difference. /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` /// it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,\infty,p)=f(-\infty,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p)=0.0$ /// - $f(-0.0,0.0,p)=-0.0$ /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_prec_round(other, prec, Nearest) } /// Subtracts two [`Float`]s, rounding the result to the nearest value of the specified /// precision. The first [`Float`] is taken by value and the second by reference. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,\infty,p)=f(-\infty,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p)=0.0$ /// - $f(-0.0,0.0,p)=-0.0$ /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_prec_round_val_ref(other, prec, Nearest) } /// Subtracts two [`Float`]s, rounding the result to the nearest value of the specified /// precision. The first [`Float`] is taken by reference and the second by value. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,\infty,p)=f(-\infty,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p)=0.0$ /// - $f(-0.0,0.0,p)=-0.0$ /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_prec_round_ref_val(other, prec, Nearest) } /// Subtracts two [`Float`]s, rounding the result to the nearest value of the specified /// precision. Both [`Float`]s are taken by reference. An [`Ordering`] is also returned, /// indicating whether the rounded difference is less than, equal to, or greater than the exact /// difference. Although `NaN`s are not comparable to any [`Float`], whenever this function /// returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(\infty,\infty,p)=f(-\infty,-\infty,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,p)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,p)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,p)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,p)=0.0$ /// - $f(-0.0,0.0,p)=-0.0$ /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,p)=f(-0.0,-0.0,p,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,p)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,p)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_prec_round_ref_ref(other, prec, Nearest) } /// Subtracts two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by value. An [`Ordering`] is also returned, indicating whether the /// rounded difference is less than, equal to, or greater than the exact difference. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,\infty,m)=f(-\infty,-\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,m)=0.0$ /// - $f(-0.0,0.0,m)=-0.0$ /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); Self::sub_prec_round(self, other, prec, rm) } /// Subtracts two [`Float`]s, rounding the result with the specified rounding mode. The /// [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is also /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,\infty,m)=f(-\infty,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,m)=0.0$ /// - $f(-0.0,0.0,m)=-0.0$ /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_val_ref(other, prec, rm) } /// Subtracts two [`Float`]s, rounding the result with the specified rounding mode. The /// [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is also /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,\infty,m)=f(-\infty,-\infty,m)= \text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,m)=0.0$ /// - $f(-0.0,0.0,m)=-0.0$ /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_ref_val(other, prec, rm) } /// Subtracts two [`Float`]s, rounding the result with the specified rounding mode. Both /// [`Float`]s are taken by reference. An [`Ordering`] is also returned, indicating whether the /// rounded difference is less than, equal to, or greater than the exact difference. Although /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also /// returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// Special cases: /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(\infty,\infty,m)=f(-\infty,-\infty,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0,m)=0.0$ /// - $f(-0.0,0.0,m)=-0.0$ /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=0.0$ if $m$ is not `Floor` /// - $f(0.0,0.0,m)=f(-0.0,-0.0,m)=-0.0$ if $m$ is `Floor` /// - $f(x,x,m)=0.0$ if $x$ is finite and nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is finite and nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_ref_ref(other, prec, rm) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is /// taken by value. An [`Ordering`] is returned, indicating whether the rounded difference is /// less than, equal to, or greater than the exact difference. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::sub_prec_assign`] instead. If /// you know that your target precision is the maximum of the precisions of the two inputs, /// consider using [`Float::sub_round_assign`] instead. If both of these things are true, /// consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact subtraction. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign(Float::from(E), 5, Floor), Less); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign(Float::from(E), 5, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.44"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign(Float::from(E), 5, Nearest), Less); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign(Float::from(E), 20, Floor), Less); /// assert_eq!(x.to_string(), "0.4233108"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign(Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "0.4233112"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign(Float::from(E), 20, Nearest), Less); /// assert_eq!(x.to_string(), "0.4233108"); /// ``` #[inline] pub fn sub_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering { self.add_prec_round_assign_helper(other, prec, rm, true) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Float`] on the right-hand side is /// taken by reference. An [`Ordering`] is returned, indicating whether the rounded difference /// is less than, equal to, or greater than the exact difference. Although `NaN`s are not /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also /// returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_prec_round`] documentation for information on special cases, overflow, /// and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::sub_prec_assign_ref`] /// instead. If you know that your target precision is the maximum of the precisions of the two /// inputs, consider using [`Float::sub_round_assign`] instead. If both of these things are /// true, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact subtraction. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_round_assign_ref(&Float::from(E), 5, Floor), Less); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign_ref(&Float::from(E), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "0.44"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign_ref(&Float::from(E), 5, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign_ref(&Float::from(E), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "0.4233108"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign_ref(&Float::from(E), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "0.4233112"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_prec_round_assign_ref(&Float::from(E), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "0.4233108"); /// ``` #[inline] pub fn sub_prec_round_assign_ref( &mut self, other: &Self, prec: u64, rm: RoundingMode, ) -> Ordering { self.add_prec_round_assign_ref_helper(other, prec, rm, true) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of /// the specified precision. The [`Float`] on the right-hand side is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded difference is less than, equal to, /// or greater than the exact difference. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_prec_round_assign`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_assign(Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_assign(Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "0.4233108"); /// ``` #[inline] pub fn sub_prec_assign(&mut self, other: Self, prec: u64) -> Ordering { self.sub_prec_round_assign(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result to the nearest value of /// the specified precision. The [`Float`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded difference is less than, equal to, /// or greater than the exact difference. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_prec`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_prec_round_assign_ref`] instead. If you know that your target precision is the /// maximum of the precisions of the two inputs, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_assign_ref(&Float::from(E), 5), Less); /// assert_eq!(x.to_string(), "0.42"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_prec_assign_ref(&Float::from(E), 20), Less); /// assert_eq!(x.to_string(), "0.4233108"); /// ``` #[inline] pub fn sub_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { self.sub_prec_round_assign_ref(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::sub_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using [`Float::sub_prec_round_assign`] /// instead. If you know you'll be using the `Nearest` rounding mode, consider using `-=` /// instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign(Float::from(-E), Floor), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign(Float::from(-E), Ceiling), Greater); /// assert_eq!(x.to_string(), "5.859874482048839"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign(Float::from(-E), Nearest), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// ``` #[inline] pub fn sub_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_assign(other, prec, rm) } /// Subtracts a [`Float`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] /// is returned, indicating whether the rounded difference is less than, equal to, or greater /// than the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever /// this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the maximum of the precision of the inputs. See /// [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the maximum precision of the inputs. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. /// /// See the [`Float::sub_round`] documentation for information on special cases, overflow, and /// underflow. /// /// If you want to specify an output precision, consider using /// [`Float::sub_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Panics /// Panics if `rm` is `Exact` but the maximum precision of the inputs is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::{E, PI}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign_ref(&Float::from(-E), Floor), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign_ref(&Float::from(-E), Ceiling), Greater); /// assert_eq!(x.to_string(), "5.859874482048839"); /// /// let mut x = Float::from(PI); /// assert_eq!(x.sub_round_assign_ref(&Float::from(-E), Nearest), Less); /// assert_eq!(x.to_string(), "5.859874482048838"); /// ``` #[inline] pub fn sub_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_assign_ref(other, prec, rm) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// value. An [`Ordering`] is also returned, indicating whether the rounded difference is less /// than, equal to, or greater than the exact difference. Although `NaN`s are not comparable to /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.sub_rational_prec_round_assign(other, prec, rm); (self, o) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by value and the [`Rational`] by /// reference. An [`Ordering`] is also returned, indicating whether the rounded difference is /// less than, equal to, or greater than the exact difference. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let o = self.sub_rational_prec_round_assign_ref(other, prec, rm); (self, o) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] is taken by reference and the [`Rational`] /// by value. An [`Ordering`] is also returned, indicating whether the rounded difference is /// less than, equal to, or greater than the exact difference. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) => (float_nan!(), Equal), (float_infinity!(), _) => (float_infinity!(), Equal), (float_negative_infinity!(), _) => (float_negative_infinity!(), Equal), (float_negative_zero!(), y) => { let (diff, o) = Self::from_rational_prec_round(y, prec, -rm); (-diff, o.reverse()) } (float_zero!(), y) => { if y == 0u32 { (float_zero!(), Equal) } else { let (diff, o) = Self::from_rational_prec_round(y, prec, -rm); (-diff, o.reverse()) } } (_, y) if y == 0 => Self::from_float_prec_round_ref(self, prec, rm), (x, y) => { if *x == y { return ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ); } let (min_exponent, max_exponent) = float_rational_diff_exponent_range(x, &y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float subtraction"); return match (float_rational_diff_sign(x, &y), rm) { (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. return sub_rational_prec_round_naive_ref_val(x, y, prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(&y, working_prec); if o == Equal { // Result is exact so we can subtract it directly! return self.sub_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.sub_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { let o = t.set_prec_round(prec, rm); return (t, o); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the specified precision and /// with the specified rounding mode. The [`Float`] and the [`Rational`] are both taken by /// reference. An [`Ordering`] is also returned, indicating whether the rounded difference is /// less than, equal to, or greater than the exact difference. Although `NaN`s are not /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// f(x,y,p,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p,m)=\text{NaN}$ /// - $f(\infty,x,p,m)=\infty$ /// - $f(-\infty,x,p,m)=-\infty$ /// - $f(0.0,0,p,m)=0.0$ /// - $f(-0.0,0,p,m)=-0.0$ /// - $f(x,x,p,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,p,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { assert_ne!(prec, 0); match (self, other) { (float_nan!(), _) => (float_nan!(), Equal), (float_infinity!(), _) => (float_infinity!(), Equal), (float_negative_infinity!(), _) => (float_negative_infinity!(), Equal), (float_negative_zero!(), y) => { let (diff, o) = Self::from_rational_prec_round_ref(y, prec, -rm); (-diff, o.reverse()) } (float_zero!(), y) => { if *y == 0u32 { (float_zero!(), Equal) } else { let (diff, o) = Self::from_rational_prec_round_ref(y, prec, -rm); (-diff, o.reverse()) } } (_, y) if *y == 0 => Self::from_float_prec_round_ref(self, prec, rm), (x, y) => { if x == y { return ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ); } let (min_exponent, max_exponent) = float_rational_diff_exponent_range(x, y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float subtraction"); return match (float_rational_diff_sign(x, y), rm) { (true, Ceiling | Up | Nearest) => (float_infinity!(), Greater), (true, _) => (Self::max_finite_value_with_prec(prec), Less), (false, Floor | Up | Nearest) => (float_negative_infinity!(), Less), (false, _) => (-Self::max_finite_value_with_prec(prec), Greater), }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. return sub_rational_prec_round_naive_ref_ref(x, y, prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(y, working_prec); if o == Equal { // Result is exact so we can subtract it directly! return self.sub_prec_round_ref_val(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let mut t = x.sub_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { let o = t.set_prec_round(prec, rm); return (t, o); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by value. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_rational_prec_round(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by value and the [`Rational`] by reference. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_rational_prec_round_val_ref(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] is taken by reference and the [`Rational`] by value. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_rational_prec_round_ref_val(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result to the nearest value of the /// specified precision. The [`Float`] and the [`Rational`] are both are taken by reference. An /// [`Ordering`] is also returned, indicating whether the rounded difference is less than, equal /// to, or greater than the exact difference. Although `NaN`s are not comparable to any /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// f(x,y,p) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// Special cases: /// - $f(\text{NaN},x,p)=\text{NaN}$ /// - $f(\infty,x,p)=\infty$ /// - $f(-\infty,x,p)=-\infty$ /// - $f(0.0,0,p)=0.0$ /// - $f(-0.0,0,p)=-0.0$ /// - $f(x,x,p)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 (Self, Ordering) { self.sub_rational_prec_round_ref_ref(other, prec, Nearest) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] and the [`Rational`] are both are taken by value. An [`Ordering`] is /// also returned, indicating whether the rounded difference is less than, equal to, or greater /// than the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(x,0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x,m)=f(-0.0,x,m)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.sub_rational_prec_round(other, prec, rm) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by value and the [`Rational`] by reference. An [`Ordering`] is /// also returned, indicating whether the rounded difference is less than, equal to, or greater /// than the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(x,0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x,m)=f(-0.0,x,m)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.sub_rational_prec_round_val_ref(other, prec, rm) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] is taken by reference and the [`Rational`] by value. An [`Ordering`] is /// also returned, indicating whether the rounded difference is less than, equal to, or greater /// than the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(x,0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x,m)=f(-0.0,x,m)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.sub_rational_prec_round_ref_val(other, prec, rm) } /// Subtracts a [`Float`] by a [`Rational`], rounding the result with the specified rounding /// mode. The [`Float`] and the [`Rational`] are both are taken by reference. An [`Ordering`] is /// also returned, indicating whether the rounded difference is less than, equal to, or greater /// than the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever /// this function returns a `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the [`Float`] input. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// f(x,y,m) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the [`Float`] input. /// /// Special cases: /// - $f(\text{NaN},x,m)=\text{NaN}$ /// - $f(\infty,x,m)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x,m)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,0,m)=0.0$ /// - $f(-0.0,0,m)=-0.0$ /// - $f(x,0,m)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x,m)=f(-0.0,x,m)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x,m)=0.0$ if $x$ is nonzero and $m$ is not `Floor` /// - $f(x,x,m)=-0.0$ if $x$ is nonzero and $m$ is `Floor` /// /// Overflow and underflow: /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is /// returned instead, where `p` is the precision of the input. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is /// returned instead. /// - If $f(x,y,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$ /// is returned instead, where `p` is the precision of the input. /// - If $0 (Self, Ordering) { let prec = self.significant_bits(); self.sub_rational_prec_round_ref_ref(other, prec, rm) } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by value. An /// [`Ordering`] is returned, indicating whether the rounded difference is less than, equal to, /// or greater than the exact difference. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using [`Float::sub_rational_prec_assign`] /// instead. If you know that your target precision is the precision of the [`Float`] input, /// consider using [`Float::sub_rational_round_assign`] instead. If both of these things are /// true, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact subtraction. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.9"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "2.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.808258"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808262"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign(Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "2.808258"); /// ``` /// /// This is mpfr_sub_q from gmp_op.c, MPFR 4.2.0. #[inline] pub fn sub_rational_prec_round_assign( &mut self, other: Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (Self(NaN | Infinity { .. }), _) => Equal, (float_negative_zero!(), y) => { let o; (*self, o) = Self::from_rational_prec_round(y, prec, -rm); self.neg_assign(); o.reverse() } (float_zero!(), y) => { if y == 0u32 { Equal } else { let o; (*self, o) = Self::from_rational_prec_round(y, prec, -rm); self.neg_assign(); o.reverse() } } (_, y) if y == 0 => self.set_prec_round(prec, rm), (x, y) => { if *x == y { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return Equal; } let (min_exponent, max_exponent) = float_rational_diff_exponent_range(x, &y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float subtraction"); return match (float_rational_diff_sign(x, &y), rm) { (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. let (diff, o) = sub_rational_prec_round_naive_ref_val(&*x, y, prec, rm); *self = diff; return o; } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(&y, working_prec); if o == Equal { // Result is exact so we can subtract it directly! return self.sub_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let t = x.sub_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { *self = t; return self.set_prec_round(prec, rm); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result to the specified /// precision and with the specified rounding mode. The [`Rational`] is taken by reference. An /// [`Ordering`] is returned, indicating whether the rounded difference is less than, equal to, /// or greater than the exact difference. Although `NaN`s are not comparable to any [`Float`], /// whenever this function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// See [`RoundingMode`] for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_rational_prec_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you know you'll be using `Nearest`, consider using /// [`Float::sub_rational_prec_assign_ref`] instead. If you know that your target precision is /// the precision of the [`Float`] input, consider using /// [`Float::sub_rational_round_assign_ref`] instead. If both of these things are true, consider /// using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Panics /// Panics if `rm` is `Exact` but `prec` is too small for an exact subtraction. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.9"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 5, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "2.8"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.808258"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808262"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(1u8, 3), 20, Nearest), /// Less /// ); /// assert_eq!(x.to_string(), "2.808258"); /// ``` #[inline] pub fn sub_rational_prec_round_assign_ref( &mut self, other: &Rational, prec: u64, rm: RoundingMode, ) -> Ordering { assert_ne!(prec, 0); match (&mut *self, other) { (Self(NaN | Infinity { .. }), _) => Equal, (float_negative_zero!(), y) => { let o; (*self, o) = Self::from_rational_prec_round_ref(y, prec, -rm); self.neg_assign(); o.reverse() } (float_zero!(), y) => { if *y == 0u32 { Equal } else { let o; (*self, o) = Self::from_rational_prec_round_ref(y, prec, -rm); self.neg_assign(); o.reverse() } } (_, y) if *y == 0 => self.set_prec_round(prec, rm), (x, y) => { if *x == *y { *self = if rm == Floor { float_negative_zero!() } else { float_zero!() }; return Equal; } let (min_exponent, max_exponent) = float_rational_diff_exponent_range(x, y); if min_exponent >= i64::from(Self::MAX_EXPONENT) { assert!(rm != Exact, "Inexact Float subtraction"); return match (float_rational_diff_sign(x, y), rm) { (true, Ceiling | Up | Nearest) => { *self = float_infinity!(); Greater } (true, _) => { *self = Self::max_finite_value_with_prec(prec); Less } (false, Floor | Up | Nearest) => { *self = float_negative_infinity!(); Less } (false, _) => { *self = -Self::max_finite_value_with_prec(prec); Greater } }; } if max_exponent > i64::from(Self::MAX_EXPONENT) - 2 || min_exponent < i64::from(Self::MIN_EXPONENT - 2) { // If we can't rule out overflow or underflow, use slow-but-correct naive // algorithm. let (diff, o) = sub_rational_prec_round_naive_ref_ref(&*x, y, prec, rm); *self = diff; return o; } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; // working_prec grows as O([(1 + sqrt(3)) / 2] ^ n) ≈ O(1.366 ^ n). loop { // Error <= 1/2 ulp(q) let (q, o) = Self::from_rational_prec_ref(y, working_prec); if o == Equal { // Result is exact so we can subtract it directly! return self.sub_prec_round_assign(q, prec, rm); } let q_exp = q.get_exponent().unwrap(); let t = x.sub_prec_ref_val(q, working_prec).0; // Error on t is <= 1/2 ulp(t). // ``` // Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t))) // <= 2^(EXP(q)-EXP(t)) // If EXP(q)-EXP(t)<0, <= 2^0 // ``` // We can get 0, but we can't round since q is inexact if t != 0 { let m = u64::saturating_from(q_exp - t.get_exponent().unwrap()) .checked_add(1) .unwrap(); if working_prec >= m && float_can_round( t.significand_ref().unwrap(), working_prec - m, prec, rm, ) { *self = t; return self.set_prec_round(prec, rm); } } working_prec += increment; increment = working_prec >> 1; } } } } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result to the nearest value /// of the specified precision. The [`Rational`] is taken by value. An [`Ordering`] is returned, /// indicating whether the rounded difference is less than, equal to, or greater than the exact /// difference. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_rational_prec`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_rational_prec_round_assign`] instead. If you know that your target precision is /// the maximum of the precisions of the two inputs, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_assign(Rational::exact_from(1.5), 5), /// Less /// ); /// assert_eq!(x.to_string(), "1.62"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_assign(Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "1.641592"); /// ``` #[inline] pub fn sub_rational_prec_assign(&mut self, other: Rational, prec: u64) -> Ordering { self.sub_rational_prec_round_assign(other, prec, Nearest) } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result to the nearest value /// of the specified precision. The [`Rational`] is taken by reference. An [`Ordering`] is /// returned, indicating whether the rounded difference is less than, equal to, or greater than /// the exact difference. Although `NaN`s are not comparable to any [`Float`], whenever this /// function sets the [`Float`] to `NaN` it also returns `Equal`. /// /// If the difference is equidistant from two [`Float`]s with the specified precision, the /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a /// description of the `Nearest` rounding mode. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$. /// /// If the output has a precision, it is `prec`. /// /// See the [`Float::sub_rational_prec_val_ref`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_rational_prec_round_assign_ref`] instead. If you know that your target /// precision is the maximum of the precisions of the two inputs, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(other.significant_bits(), /// prec)`. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_assign_ref(&Rational::exact_from(1.5), 5), /// Less /// ); /// assert_eq!(x.to_string(), "1.62"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_prec_assign_ref(&Rational::exact_from(1.5), 20), /// Less /// ); /// assert_eq!(x.to_string(), "1.641592"); /// ``` #[inline] pub fn sub_rational_prec_assign_ref(&mut self, other: &Rational, prec: u64) -> Ordering { self.sub_rational_prec_round_assign_ref(other, prec, Nearest) } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by value. An [`Ordering`] is returned, indicating /// whether the rounded difference is less than, equal to, or greater than the exact difference. /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the /// [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::sub_rational_round`] documentation for information on special cases, /// overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::sub_rational_prec_round_assign`] instead. If you know you'll be using the `Nearest` /// rounding mode, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign(Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.808259320256457"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign(Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808259320256461"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign(Rational::from_unsigneds(1u8, 3), Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808259320256461"); /// ``` #[inline] pub fn sub_rational_round_assign(&mut self, other: Rational, rm: RoundingMode) -> Ordering { let prec = self.significant_bits(); self.sub_rational_prec_round_assign(other, prec, rm) } /// Subtracts a [`Rational`] by a [`Float`] in place, rounding the result with the specified /// rounding mode. The [`Rational`] is taken by reference. An [`Ordering`] is returned, /// indicating whether the rounded difference is less than, equal to, or greater than the exact /// difference. Although `NaN`s are not comparable to any [`Float`], whenever this function sets /// the [`Float`] to `NaN` it also returns `Equal`. /// /// The precision of the output is the precision of the input [`Float`]. See [`RoundingMode`] /// for a description of the possible rounding modes. /// /// $$ /// x \gets x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| < /// 2^{\lfloor\log_2 |x-y|\rfloor-p+1}$, where $p$ is the precision of the input [`Float`]. /// - If $x-y$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq /// 2^{\lfloor\log_2 |x-y|\rfloor-p}$, where $p$ is the precision of the input [`Float`]. /// /// If the output has a precision, it is the precision of the input [`Float`]. /// /// See the [`Float::sub_rational_round_val_ref`] documentation for information on special /// cases, overflow, and underflow. /// /// If you want to specify an output precision, consider using /// [`Float::sub_rational_prec_round_assign_ref`] instead. If you know you'll be using the /// `Nearest` rounding mode, consider using `-=` instead. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `rm` is `Exact` but the precision of the input [`Float`] is not high enough to /// represent the output. /// /// # Examples /// ``` /// use core::f64::consts::PI; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Floor), /// Less /// ); /// assert_eq!(x.to_string(), "2.808259320256457"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808259320256461"); /// /// let mut x = Float::from(PI); /// assert_eq!( /// x.sub_rational_round_assign_ref(&Rational::from_unsigneds(1u8, 3), Nearest), /// Greater /// ); /// assert_eq!(x.to_string(), "2.808259320256461"); /// ``` #[inline] pub fn sub_rational_round_assign_ref( &mut self, other: &Rational, rm: RoundingMode, ) -> Ordering { let prec = self.significant_bits(); self.sub_rational_prec_round_assign_ref(other, prec, rm) } } impl Sub for Float { type Output = Self; /// Subtracts two [`Float`]s, taking both by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,\infty)=f(-\infty,-\infty)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0)=0.0$ /// - $f(-0.0,0.0)=-0.0$ /// - $f(0.0,0.0)=f(-0.0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x)=f(-0.0,x)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round(other, prec, Nearest).0 } } impl Sub<&Self> for Float { type Output = Self; /// Subtracts two [`Float`]s, taking the first by value and the second by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,\infty)=f(-\infty,-\infty)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0)=0.0$ /// - $f(-0.0,0.0)=-0.0$ /// - $f(0.0,0.0)=f(-0.0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x)=f(-0.0,x)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_val_ref(other, prec, Nearest).0 } } impl Sub for &Float { type Output = Float; /// Subtracts two [`Float`]s, taking the first by reference and the second by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,\infty)=f(-\infty,-\infty)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0)=0.0$ /// - $f(-0.0,0.0)=-0.0$ /// - $f(0.0,0.0)=f(-0.0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x)=f(-0.0,x)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_ref_val(other, prec, Nearest).0 } } impl Sub<&Float> for &Float { type Output = Float; /// Subtracts two [`Float`]s, taking both by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// Special cases: /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(\infty,\infty)=f(-\infty,-\infty)=\text{NaN}$ /// - $f(\infty,x)=\infty$ if $x$ is not NaN or $\infty$ /// - $f(x,-\infty)=\infty$ if $x$ is not NaN or $-\infty$ /// - $f(-\infty,x)=-\infty$ if $x$ is not NaN or $-\infty$ /// - $f(x,\infty)=-\infty$ if $x$ is not NaN or $\infty$ /// - $f(0.0,-0.0)=0.0$ /// - $f(-0.0,0.0)=-0.0$ /// - $f(0.0,0.0)=f(-0.0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ if $x$ is not NaN and $x$ is nonzero /// - $f(0.0,x)=f(-0.0,x)=-x$ if $x$ is not NaN and $x$ is nonzero /// - $f(x,x)=0.0$ if $x$ is finite and nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_ref_ref(other, prec, Nearest).0 } } impl SubAssign for Float { /// Subtracts a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side /// by value. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x\gets = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `-` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::sub_round_assign`]. If you want both of these things, consider using /// [`Float::sub_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x -= Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x -= Float::INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(1.5); /// x -= Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x -= Float::INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x -= Float::from(2.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(1.5); /// x -= Float::from(-2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(-1.5); /// x -= Float::from(2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x -= Float::from(-2.5); /// assert_eq!(x, 1.0); /// ``` #[inline] fn sub_assign(&mut self, other: Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_assign(other, prec, Nearest); } } impl SubAssign<&Self> for Float { /// Subtracts a [`Float`] by a [`Float`] in place, taking the [`Float`] on the right-hand side /// by reference. /// /// If the output has a precision, it is the maximum of the precisions of the inputs. If the /// difference is equidistant from two [`Float`]s with the specified precision, the [`Float`] /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of /// the `Nearest` rounding mode. /// /// $$ /// x\gets = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the maximum precision of the inputs. /// /// See the `-` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_prec_assign`] instead. If you want to specify the output precision, consider /// using [`Float::sub_round_assign`]. If you want both of these things, consider using /// [`Float::sub_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_float::Float; /// /// let mut x = Float::from(1.5); /// x -= &Float::NAN; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x -= &Float::INFINITY; /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(1.5); /// x -= &Float::NEGATIVE_INFINITY; /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::INFINITY; /// x -= &Float::INFINITY; /// assert!(x.is_nan()); /// /// let mut x = Float::from(1.5); /// x -= &Float::from(2.5); /// assert_eq!(x, -1.0); /// /// let mut x = Float::from(1.5); /// x -= &Float::from(-2.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(-1.5); /// x -= &Float::from(2.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-1.5); /// x -= &Float::from(-2.5); /// assert_eq!(x, 1.0); /// ``` #[inline] fn sub_assign(&mut self, other: &Self) { let prec = max(self.significant_bits(), other.significant_bits()); self.sub_prec_round_assign_ref(other, prec, Nearest); } } impl Sub for Float { type Output = Self; /// Subtracts a [`Float`] by a [`Rational`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(x,0)=x$ /// - $f(0.0,x)=f(-0.0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.sub_rational_prec_round(other, prec, Nearest).0 } } impl Sub<&Rational> for Float { type Output = Self; /// Subtracts a [`Float`] by a [`Rational`], taking the first by value and the second by /// reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(x,0)=x$ /// - $f(0.0,x)=f(-0.0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Self { let prec = self.significant_bits(); self.sub_rational_prec_round_val_ref(other, prec, Nearest).0 } } impl Sub for &Float { type Output = Float; /// Subtracts a [`Float`] by a [`Rational`], taking the first by reference and the second by /// value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(x,0)=x$ /// - $f(0.0,x)=f(-0.0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.sub_rational_prec_round_ref_val(other, prec, Nearest).0 } } impl Sub<&Rational> for &Float { type Output = Float; /// Subtracts a [`Float`] by a [`Rational`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(\text{NaN},x)=\text{NaN}$ /// - $f(\infty,x)=\infty$ /// - $f(-\infty,x)=-\infty$ /// - $f(0.0,0)=0.0$ /// - $f(-0.0,0)=-0.0$ /// - $f(x,0)=x$ /// - $f(0.0,x)=f(-0.0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = self.significant_bits(); self.sub_rational_prec_round_ref_ref(other, prec, Nearest).0 } } impl SubAssign for Float { /// Subtracts a [`Rational`] by a [`Float`] in place, taking the [`Rational`] by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `-` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_rational_prec_assign`] instead. If you want to specify the output precision, /// consider using [`Float::sub_rational_round_assign`]. If you want both of these things, /// consider using [`Float::sub_rational_prec_round_assign`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x -= Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x -= Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x -= Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(2.5); /// x -= Rational::exact_from(1.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(2.5); /// x -= Rational::exact_from(-1.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(-2.5); /// x -= Rational::exact_from(1.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-2.5); /// x -= Rational::exact_from(-1.5); /// assert_eq!(x, -1.0); /// ``` #[inline] fn sub_assign(&mut self, other: Rational) { let prec = self.significant_bits(); self.sub_rational_prec_round_assign(other, prec, Nearest); } } impl SubAssign<&Rational> for Float { /// Subtracts a [`Rational`] by a [`Float`] in place, taking the [`Rational`] by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// x\gets = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// See the `-` documentation for information on special cases, overflow, and underflow. /// /// If you want to use a rounding mode other than `Nearest`, consider using /// [`Float::sub_rational_prec_assign_ref`] instead. If you want to specify the output /// precision, consider using [`Float::sub_rational_round_assign_ref`]. If you want both of /// these things, consider using [`Float::sub_rational_prec_round_assign_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// let mut x = Float::NAN; /// x -= &Rational::exact_from(1.5); /// assert!(x.is_nan()); /// /// let mut x = Float::INFINITY; /// x -= &Rational::exact_from(1.5); /// assert_eq!(x, Float::INFINITY); /// /// let mut x = Float::NEGATIVE_INFINITY; /// x -= &Rational::exact_from(1.5); /// assert_eq!(x, Float::NEGATIVE_INFINITY); /// /// let mut x = Float::from(2.5); /// x -= &Rational::exact_from(1.5); /// assert_eq!(x, 1.0); /// /// let mut x = Float::from(2.5); /// x -= &Rational::exact_from(-1.5); /// assert_eq!(x, 4.0); /// /// let mut x = Float::from(-2.5); /// x -= &Rational::exact_from(1.5); /// assert_eq!(x, -4.0); /// /// let mut x = Float::from(-2.5); /// x -= &Rational::exact_from(-1.5); /// assert_eq!(x, -1.0); /// ``` #[inline] fn sub_assign(&mut self, other: &Rational) { let prec = self.significant_bits(); self.sub_rational_prec_round_assign_ref(other, prec, Nearest); } } impl Sub for Rational { type Output = Float; /// Subtracts a [`Rational`] by a [`Float`], taking both by value. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=-\infty$ /// - $f(x,-\infty)=\infty$ /// - $f(0,0.0)=-0.0$ /// - $f(0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ /// - $f(0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); -other.sub_rational_prec_round(self, prec, Nearest).0 } } impl Sub<&Float> for Rational { type Output = Float; /// Subtracts a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`] /// by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=-\infty$ /// - $f(x,-\infty)=\infty$ /// - $f(0,0.0)=-0.0$ /// - $f(0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ /// - $f(0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); -other.sub_rational_prec_round_ref_val(self, prec, Nearest).0 } } impl Sub for &Rational { type Output = Float; /// Subtracts a [`Rational`] by a [`Float`], taking the [`Rational`] by value and the [`Float`] /// by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=-\infty$ /// - $f(x,-\infty)=\infty$ /// - $f(0,0.0)=-0.0$ /// - $f(0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ /// - $f(0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); -other.sub_rational_prec_round_val_ref(self, prec, Nearest).0 } } impl Sub<&Float> for &Rational { type Output = Float; /// Subtracts a [`Rational`] by a [`Float`], taking both by reference. /// /// If the output has a precision, it is the precision of the input [`Float`]. If the difference /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` /// rounding mode. /// /// $$ /// f(x,y) = x-y+\varepsilon. /// $$ /// - If $x-y$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0. /// - If $x-y$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x-y|\rfloor-p}$, /// where $p$ is the precision of the input [`Float`]. /// /// Special cases: /// - $f(x,\text{NaN})=\text{NaN}$ /// - $f(x,\infty)=-\infty$ /// - $f(x,-\infty)=\infty$ /// - $f(0,0.0)=-0.0$ /// - $f(0,-0.0)=0.0$ /// - $f(x,0.0)=f(x,-0.0)=x$ /// - $f(0,x)=-x$ /// - $f(x,x)=0.0$ if $x$ is nonzero /// /// Overflow and underflow: /// - If $f(x,y)\geq 2^{2^{30}-1}$, $\infty$ is returned instead. /// - If $f(x,y)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead. /// - If $0 Float { let prec = other.significant_bits(); -other.sub_rational_prec_round_ref_ref(self, prec, Nearest).0 } } ================================================ FILE: malachite-float/src/basic/classification.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{Float, float_either_zero}; use crate::{float_either_infinity, float_finite, float_nan, float_negative_zero, float_zero}; use core::num::FpCategory; impl Float { /// Determines whether a [`Float`] is NaN. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, One}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_nan(), true); /// assert_eq!(Float::ONE.is_nan(), false); /// ``` #[inline] pub const fn is_nan(&self) -> bool { matches!(self, float_nan!()) } /// Determines whether a [`Float`] is finite. /// /// NaN is not finite. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, One}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_finite(), false); /// assert_eq!(Float::INFINITY.is_finite(), false); /// assert_eq!(Float::ONE.is_finite(), true); /// ``` #[inline] pub const fn is_finite(&self) -> bool { matches!(self, Self(Zero { .. } | Finite { .. })) } /// Determines whether a [`Float`] is infinite. /// /// NaN is not infinite. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, One}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_infinite(), false); /// assert_eq!(Float::INFINITY.is_infinite(), true); /// assert_eq!(Float::ONE.is_infinite(), false); /// ``` #[inline] pub const fn is_infinite(&self) -> bool { matches!(self, float_either_infinity!()) } /// Determines whether a [`Float`] is positive zero. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_positive_zero(), false); /// assert_eq!(Float::INFINITY.is_positive_zero(), false); /// assert_eq!(Float::ONE.is_positive_zero(), false); /// assert_eq!(Float::ZERO.is_positive_zero(), true); /// assert_eq!(Float::NEGATIVE_ZERO.is_positive_zero(), false); /// ``` #[inline] pub const fn is_positive_zero(&self) -> bool { matches!(self, float_zero!()) } /// Determines whether a [`Float`] is negative zero. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_negative_zero(), false); /// assert_eq!(Float::INFINITY.is_negative_zero(), false); /// assert_eq!(Float::ONE.is_negative_zero(), false); /// assert_eq!(Float::ZERO.is_negative_zero(), false); /// assert_eq!(Float::NEGATIVE_ZERO.is_negative_zero(), true); /// ``` #[inline] pub const fn is_negative_zero(&self) -> bool { matches!(self, float_negative_zero!()) } /// Determines whether a [`Float`] is zero (positive or negative). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_zero(), false); /// assert_eq!(Float::INFINITY.is_zero(), false); /// assert_eq!(Float::ONE.is_zero(), false); /// assert_eq!(Float::ZERO.is_zero(), true); /// assert_eq!(Float::NEGATIVE_ZERO.is_zero(), true); /// ``` #[inline] pub const fn is_zero(&self) -> bool { matches!(self, float_either_zero!()) } /// Determines whether a [`Float`] is normal, that is, finite and nonzero. /// /// There is no notion of subnormal [`Float`]s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_normal(), false); /// assert_eq!(Float::INFINITY.is_normal(), false); /// assert_eq!(Float::ZERO.is_normal(), false); /// assert_eq!(Float::NEGATIVE_ZERO.is_normal(), false); /// assert_eq!(Float::ONE.is_normal(), true); /// ``` pub const fn is_normal(&self) -> bool { matches!(self, float_finite!()) } /// Determines whether a [`Float`]'s sign is positive. /// /// A NaN has no sign, so this function returns false when given a NaN. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_sign_positive(), false); /// assert_eq!(Float::INFINITY.is_sign_positive(), true); /// assert_eq!(Float::NEGATIVE_INFINITY.is_sign_positive(), false); /// assert_eq!(Float::ZERO.is_sign_positive(), true); /// assert_eq!(Float::NEGATIVE_ZERO.is_sign_positive(), false); /// assert_eq!(Float::ONE.is_sign_positive(), true); /// assert_eq!(Float::NEGATIVE_ONE.is_sign_positive(), false); /// ``` pub const fn is_sign_positive(&self) -> bool { match self { float_nan!() => false, Self(Infinity { sign } | Finite { sign, .. } | Zero { sign, .. }) => *sign, } } /// Determines whether a [`Float`]'s sign is negative. /// /// A NaN has no sign, so this function returns false when given a NaN. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.is_sign_negative(), false); /// assert_eq!(Float::INFINITY.is_sign_negative(), false); /// assert_eq!(Float::NEGATIVE_INFINITY.is_sign_negative(), true); /// assert_eq!(Float::ZERO.is_sign_negative(), false); /// assert_eq!(Float::NEGATIVE_ZERO.is_sign_negative(), true); /// assert_eq!(Float::ONE.is_sign_negative(), false); /// assert_eq!(Float::NEGATIVE_ONE.is_sign_negative(), true); /// ``` pub const fn is_sign_negative(&self) -> bool { match self { float_nan!() => false, Self(Infinity { sign } | Finite { sign, .. } | Zero { sign, .. }) => !*sign, } } /// Classifies a [`Float`] into one of several categories. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, /// }; /// use malachite_float::Float; /// use std::num::FpCategory; /// /// assert_eq!(Float::NAN.classify(), FpCategory::Nan); /// assert_eq!(Float::INFINITY.classify(), FpCategory::Infinite); /// assert_eq!(Float::NEGATIVE_INFINITY.classify(), FpCategory::Infinite); /// assert_eq!(Float::ZERO.classify(), FpCategory::Zero); /// assert_eq!(Float::NEGATIVE_ZERO.classify(), FpCategory::Zero); /// assert_eq!(Float::ONE.classify(), FpCategory::Normal); /// assert_eq!(Float::NEGATIVE_ONE.classify(), FpCategory::Normal); /// ``` pub const fn classify(&self) -> FpCategory { match self { float_nan!() => FpCategory::Nan, float_either_infinity!() => FpCategory::Infinite, Self(Zero { .. }) => FpCategory::Zero, _ => FpCategory::Normal, } } /// Turns a NaN into a `None` and wraps any non-NaN [`Float`] with a `Some`. The [`Float`] is /// taken by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.into_non_nan(), None); /// assert_eq!(Float::INFINITY.into_non_nan(), Some(Float::INFINITY)); /// assert_eq!(Float::ZERO.into_non_nan(), Some(Float::ZERO)); /// assert_eq!( /// Float::NEGATIVE_ZERO.into_non_nan(), /// Some(Float::NEGATIVE_ZERO) /// ); /// assert_eq!(Float::ONE.into_non_nan(), Some(Float::ONE)); /// ``` #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const pub fn into_non_nan(self) -> Option { match self { float_nan!() => None, x => Some(x), } } /// Turns a NaN into a `None` and wraps any non-NaN [`Float`] with a `Some`. The [`Float`] is /// taken by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.to_non_nan(), None); /// assert_eq!(Float::INFINITY.to_non_nan(), Some(Float::INFINITY)); /// assert_eq!(Float::ZERO.to_non_nan(), Some(Float::ZERO)); /// assert_eq!( /// Float::NEGATIVE_ZERO.to_non_nan(), /// Some(Float::NEGATIVE_ZERO) /// ); /// assert_eq!(Float::ONE.to_non_nan(), Some(Float::ONE)); /// ``` #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const pub fn to_non_nan(&self) -> Option { match self { float_nan!() => None, x => Some(x.clone()), } } /// Turns any [`Float`] that's NaN or infinite into a `None` and wraps any finite [`Float`] with /// a `Some`. The [`Float`] is taken by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.into_finite(), None); /// assert_eq!(Float::INFINITY.into_finite(), None); /// assert_eq!(Float::ZERO.into_finite(), Some(Float::ZERO)); /// assert_eq!( /// Float::NEGATIVE_ZERO.into_finite(), /// Some(Float::NEGATIVE_ZERO) /// ); /// assert_eq!(Float::ONE.into_finite(), Some(Float::ONE)); /// ``` #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const pub fn into_finite(self) -> Option { match self { Self(NaN | Infinity { .. }) => None, x => Some(x), } } /// Turns any [`Float`] that's NaN or infinite into a `None` and wraps any finite [`Float`] with /// a `Some`. The [`Float`] is taken by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeZero, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.to_finite(), None); /// assert_eq!(Float::INFINITY.to_finite(), None); /// assert_eq!(Float::ZERO.to_finite(), Some(Float::ZERO)); /// assert_eq!(Float::NEGATIVE_ZERO.to_finite(), Some(Float::NEGATIVE_ZERO)); /// assert_eq!(Float::ONE.to_finite(), Some(Float::ONE)); /// ``` pub fn to_finite(&self) -> Option { match self { Self(NaN | Infinity { .. }) => None, x => Some(x.clone()), } } } ================================================ FILE: malachite-float/src/basic/complexity.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use core::cmp::max; use malachite_base::num::logic::traits::SignificantBits; impl Float { /// Determines a [`Float`]'s complexity. The complexity is defined as follows: /// /// $$ /// f(\text{NaN}) = f(\pm\infty) = f(\pm 0.0) = 1, /// $$ /// /// and, if $x$ is finite and nonzero, /// /// $$ /// f(x) = \max(|\lfloor \log_2 x\rfloor|, p), /// $$ /// /// where $p$ is the precision of $x$. /// /// Informally, the complexity is proportional to the number of characters you would need to /// write the [`Float`] out without using exponents. /// /// See also the [`Float`] implementation of [`SignificantBits`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{NaN, One}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.complexity(), 1); /// assert_eq!(Float::ONE.complexity(), 1); /// assert_eq!(Float::one_prec(100).complexity(), 100); /// assert_eq!(Float::from(std::f64::consts::PI).complexity(), 50); /// assert_eq!(Float::power_of_2(100u64).complexity(), 100); /// assert_eq!(Float::power_of_2(-100i64).complexity(), 100); /// ``` pub fn complexity(&self) -> u64 { match self { Self(Finite { exponent, precision, .. }) => max(u64::from((exponent - 1).unsigned_abs()), *precision), _ => 1, } } } impl SignificantBits for &Float { /// Returns the number of significant bits of a [`Float`]. This is defined as follows: /// /// $$ /// f(\text{NaN}) = f(\pm\infty) = f(\pm 0.0) = 1, /// $$ /// /// and, if $x$ is finite and nonzero, /// /// $$ /// f(x) = p, /// $$ /// /// where $p$ is the precision of $x$. /// /// See also the [`complexity`](Float::complexity) function. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{NaN, One}; /// use malachite_base::num::logic::traits::SignificantBits; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.significant_bits(), 1); /// assert_eq!(Float::ONE.significant_bits(), 1); /// assert_eq!(Float::one_prec(100).significant_bits(), 100); /// assert_eq!(Float::from(std::f64::consts::PI).significant_bits(), 50); /// assert_eq!(Float::power_of_2(100u64).significant_bits(), 1); /// assert_eq!(Float::power_of_2(-100i64).significant_bits(), 1); /// ``` fn significant_bits(self) -> u64 { match self { Float(Finite { precision, .. }) => *precision, _ => 1, } } } ================================================ FILE: malachite-float/src/basic/constants.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use malachite_base::comparison::traits::{Max, Min}; use malachite_base::named::Named; use malachite_base::num::arithmetic::traits::{ IsPowerOf2, NegModPowerOf2, PowerOf2, RoundToMultipleOfPowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Two, Zero as ZeroTrait, }; use malachite_base::num::logic::traits::{BitScan, LowMask}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; #[doc(hidden)] #[macro_export] macro_rules! float_zero { () => { Float(Zero { sign: true }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_one { () => { Float(Finite { sign: true, exponent: 1, precision: 1, significand: Natural::HIGH_BIT, }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_two { () => { Float(Finite { sign: true, exponent: 2, precision: 1, significand: Natural::HIGH_BIT, }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_negative_one { () => { Float(Finite { sign: false, exponent: 1, precision: 1, significand: Natural::HIGH_BIT, }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_one_half { () => { Float(Finite { sign: true, exponent: 0, precision: 1, significand: Natural::HIGH_BIT, }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_negative_zero { () => { Float(Zero { sign: false }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_infinity { () => { Float(Infinity { sign: true }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_negative_infinity { () => { Float(Infinity { sign: false }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_nan { () => { Float(NaN) }; } #[doc(hidden)] #[macro_export] macro_rules! float_finite { () => { Float(Finite { .. }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_either_infinity { () => { Float(Infinity { .. }) }; } #[doc(hidden)] #[macro_export] macro_rules! float_either_zero { () => { Float(Zero { .. }) }; } /// The constant 0.0 (positive zero), with precision 1. impl ZeroTrait for Float { const ZERO: Self = float_zero!(); } /// The constant 1.0, with precision 1. impl One for Float { const ONE: Self = float_one!(); } /// The constant 2.0, with precision 1. impl Two for Float { const TWO: Self = float_two!(); } /// The constant -1.0, with precision 1. impl NegativeOne for Float { const NEGATIVE_ONE: Self = float_negative_one!(); } /// The constant 0.5, with precision 1. impl OneHalf for Float { const ONE_HALF: Self = float_one_half!(); } /// The constant -0.0, with precision 1. impl NegativeZero for Float { const NEGATIVE_ZERO: Self = float_negative_zero!(); } /// The constant $\infty$. impl InfinityTrait for Float { const INFINITY: Self = float_infinity!(); } /// The constant $-\infty$. impl NegativeInfinity for Float { const NEGATIVE_INFINITY: Self = float_negative_infinity!(); } /// The constant NaN. impl NaNTrait for Float { const NAN: Self = float_nan!(); } impl Default for Float { /// The default value of a [`Float`], NaN. fn default() -> Self { Self::NAN } } /// The lowest value representable by this type, $-\infty$. impl Min for Float { const MIN: Self = Self::NEGATIVE_INFINITY; } /// The highest value representable by this type, $\infty$. impl Max for Float { const MAX: Self = Self::INFINITY; } // Implements `Named` for `Float`. impl_named!(Float); impl Float { /// The minimum representable positive value, or $2^{-2^{30}}$, with precision 1. pub const MIN_POSITIVE: Self = Self(Finite { sign: true, exponent: Self::MIN_EXPONENT, precision: 1, significand: Natural::HIGH_BIT, }); /// Returns the minimum representable positive value, or $2^{-2^{30}}$, with the given /// precision. /// /// $$ /// f(p) = 2^{-2^{30}}, /// $$ /// /// and the output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::min_positive_value_prec(1).to_string(), "too_small"); /// assert_eq!(Float::min_positive_value_prec(10).to_string(), "too_small"); /// assert_eq!(Float::min_positive_value_prec(100).to_string(), "too_small"); /// /// assert_eq!(Float::min_positive_value_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::min_positive_value_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::min_positive_value_prec(100).get_prec(), Some(100)); /// ``` pub fn min_positive_value_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: true, exponent: Self::MIN_EXPONENT, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }) } /// Returns whether the absolute value of a `Float` is equal to the minimum representable /// positive value, or $2^{-2^{30}}$. /// /// $$ /// f(x) = (|x|=2^{-2^{30}}). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert!(Float::min_positive_value_prec(100).abs_is_min_positive_value()); /// assert!((-Float::min_positive_value_prec(100)).abs_is_min_positive_value()); /// assert!(!(Float::min_positive_value_prec(100) << 1u32).abs_is_min_positive_value()); /// ``` pub fn abs_is_min_positive_value(&self) -> bool { self.get_exponent() == Some(Self::MIN_EXPONENT) && self.significand_ref().unwrap().is_power_of_2() } /// There is no maximum finite [`Float`], but there is one for any given precision. This /// function returns that [`Float`]. /// /// $$ /// f(p) = (1-(1/2)^p)2^{2^{30}-1}, /// $$ /// where $p$ is `prec`. The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::max_finite_value_with_prec(1).to_string(), "too_big"); /// assert_eq!(Float::max_finite_value_with_prec(10).to_string(), "too_big"); /// assert_eq!( /// Float::max_finite_value_with_prec(100).to_string(), /// "too_big" /// ); /// /// assert_eq!(Float::max_finite_value_with_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::max_finite_value_with_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::max_finite_value_with_prec(100).get_prec(), Some(100)); /// ``` pub fn max_finite_value_with_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: true, exponent: Self::MAX_EXPONENT, precision: prec, significand: Natural::low_mask(prec) << prec.neg_mod_power_of_2(Limb::LOG_WIDTH), }) } /// Returns whether the absolute value of a `Float` is equal to the maximum representable finite /// value with that precision. /// /// $$ /// f(x) = (|x|=(1-(1/2)^p)2^{2^{30}-1}), /// $$ /// where $p$ is the precision of the $x$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert!(Float::max_finite_value_with_prec(100).abs_is_max_finite_value_with_prec()); /// assert!((-Float::max_finite_value_with_prec(100)).abs_is_max_finite_value_with_prec()); /// assert!( /// !(Float::max_finite_value_with_prec(100) >> 1u32).abs_is_max_finite_value_with_prec() /// ); /// ``` pub fn abs_is_max_finite_value_with_prec(&self) -> bool { if self.get_exponent() != Some(Self::MAX_EXPONENT) { return false; } let prec = self.get_prec().unwrap(); let lowest_1_index = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); self.significand_ref() .unwrap() .index_of_next_false_bit(lowest_1_index) .unwrap() == prec .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 } /// Returns the number 1, with the given precision. /// /// $$ /// f(p) = 1, /// $$ /// /// and the output has precision $p$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::one_prec(1), 1); /// assert_eq!(Float::one_prec(10), 1); /// assert_eq!(Float::one_prec(100), 1); /// /// assert_eq!(Float::one_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::one_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::one_prec(100).get_prec(), Some(100)); /// ``` pub fn one_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: true, exponent: 1, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }) } /// Returns the number 2, with the given precision. /// /// $$ /// f(p) = 2, /// $$ /// /// and the output has precision $p$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::two_prec(1), 2); /// assert_eq!(Float::two_prec(10), 2); /// assert_eq!(Float::two_prec(100), 2); /// /// assert_eq!(Float::two_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::two_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::two_prec(100).get_prec(), Some(100)); /// ``` pub fn two_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: true, exponent: 2, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }) } /// Returns the number $-1$, with the given precision. /// /// $$ /// f(p) = -1, /// $$ /// /// and the output has precision $p$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::negative_one_prec(1), -1); /// assert_eq!(Float::negative_one_prec(10), -1); /// assert_eq!(Float::negative_one_prec(100), -1); /// /// assert_eq!(Float::negative_one_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::negative_one_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::negative_one_prec(100).get_prec(), Some(100)); /// ``` pub fn negative_one_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: false, exponent: 1, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }) } /// Returns the number 0.5, with the given precision. /// /// $$ /// f(p) = 0.5, /// $$ /// /// and the output has precision $p$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::one_half_prec(1), 0.5); /// assert_eq!(Float::one_half_prec(10), 0.5); /// assert_eq!(Float::one_half_prec(100), 0.5); /// /// assert_eq!(Float::one_half_prec(1).get_prec(), Some(1)); /// assert_eq!(Float::one_half_prec(10).get_prec(), Some(10)); /// assert_eq!(Float::one_half_prec(100).get_prec(), Some(100)); /// ``` pub fn one_half_prec(prec: u64) -> Self { assert_ne!(prec, 0); Self(Finite { sign: true, exponent: 0, precision: prec, significand: Natural::power_of_2( prec.round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0 - 1, ), }) } } ================================================ FILE: malachite-float/src/basic/extended.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, NaN}; use crate::conversion::primitive_float_from_float::FloatFromFloatError; use crate::conversion::rational_from_float::RationalFromFloatError; use core::cmp::Ordering::{self, *}; use core::cmp::max; use core::mem::swap; use core::ops::{Add, Mul, Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{CeilingLogBase2, Parity, Sqrt, SqrtAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ExactFrom, SaturatingInto}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::natural::arithmetic::float_sub::exponent_shift_compare; use malachite_nz::platform::Limb; use malachite_q::Rational; pub_crate_test_struct! { #[derive(Clone)] ExtendedFloat { pub(crate) x: Float, pub(crate) exp: i64, }} impl ExtendedFloat { fn is_valid(&self) -> bool { if self.x == 0u32 && self.exp != 0 { return false; } let exp = self.x.get_exponent(); exp.is_none() || exp == Some(0) } fn from_rational_prec_round(value: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) { if value == 0 { return ( Self { x: Float::ZERO, exp: 0, }, Equal, ); } let exp = value.floor_log_base_2_abs() + 1; let (x, o) = Float::from_rational_prec_round(value >> exp, prec, rm); let new_exp = x.get_exponent().unwrap(); ( Self { x: x >> new_exp, exp: i64::from(new_exp) + exp, }, o, ) } pub(crate) fn from_rational_prec_round_ref( value: &Rational, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { if *value == 0 { return ( Self { x: Float::ZERO, exp: 0, }, Equal, ); } let exp = value.floor_log_base_2_abs() + 1; if exp >= i64::from(Float::MIN_EXPONENT) && exp <= i64::from(Float::MAX_EXPONENT) { let (x, o) = Float::from_rational_prec_round_ref(value, prec, rm); let exp = x.get_exponent().unwrap(); return ( Self { x: x >> exp, exp: i64::from(exp), }, o, ); } let (x, o) = Float::from_rational_prec_round(value >> exp, prec, rm); let new_exp = x.get_exponent().unwrap(); ( Self { x: x >> new_exp, exp: i64::from(new_exp) + exp, }, o, ) } fn add_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) { assert!(self.is_valid()); assert!(other.is_valid()); assert!(self.x.is_normal()); assert!(other.x.is_normal()); Self::from_rational_prec_round( Rational::exact_from(self) + Rational::exact_from(other), prec, Nearest, ) } fn sub_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) { assert!(self.is_valid()); assert!(other.is_valid()); assert!(self.x.is_normal()); assert!(other.x.is_normal()); Self::from_rational_prec_round( Rational::exact_from(self) - Rational::exact_from(other), prec, Nearest, ) } fn sub_prec(self, other: Self, prec: u64) -> (Self, Ordering) { assert!(self.is_valid()); assert!(other.is_valid()); assert!(self.x.is_normal()); assert!(other.x.is_normal()); Self::from_rational_prec_round( Rational::exact_from(self) - Rational::exact_from(other), prec, Nearest, ) } fn mul_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) { assert!(self.is_valid()); assert!(other.is_valid()); assert!(self.x.is_normal()); assert!(other.x.is_normal()); let (mut product, o) = self.x.mul_prec_ref_ref(&other.x, prec); let mut product_exp = self.exp + other.exp; let extra_exp = product.get_exponent().unwrap(); product >>= extra_exp; product_exp = product_exp.checked_add(i64::from(extra_exp)).unwrap(); ( Self { x: product, exp: product_exp, }, o, ) } fn div_prec_val_ref(self, other: &Self, prec: u64) -> (Self, Ordering) { assert!(self.is_valid()); assert!(other.is_valid()); assert!(self.x.is_normal()); assert!(other.x.is_normal()); let (mut quotient, o) = self.x.div_prec_ref_ref(&other.x, prec); let mut quotient_exp = self.exp - other.exp; let extra_exp = quotient.get_exponent().unwrap(); quotient >>= extra_exp; quotient_exp = quotient_exp.checked_add(i64::from(extra_exp)).unwrap(); ( Self { x: quotient, exp: quotient_exp, }, o, ) } fn div_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering { let mut x = Self { x: Float::ZERO, exp: 0, }; swap(self, &mut x); let (q, o) = x.div_prec_val_ref(other, prec); *self = q; o } fn square_round_assign(&mut self, rm: RoundingMode) -> Ordering { let mut x = Self { x: Float::ZERO, exp: 0, }; swap(self, &mut x); let (mut square, o) = x.x.square_round(rm); let mut square_exp = x.exp << 1; let extra_exp = square.get_exponent().unwrap(); square >>= extra_exp; square_exp = square_exp.checked_add(i64::from(extra_exp)).unwrap(); *self = Self { x: square, exp: square_exp, }; o } fn from_extended_float_prec_round(x: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { if let Ok(x) = Rational::try_from(&x) { Self::from_rational_prec_round(x, prec, rm) } else { (x, Equal) } } pub_crate_test! {from_extended_float_prec_round_ref( x: &Self, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { if let Ok(x) = Rational::try_from(x) { Self::from_rational_prec_round(x, prec, rm) } else { (x.clone(), Equal) } }} fn shr_prec_round( self, bits: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { // assumes no overflow or underflow let (out_x, o) = Self::from_extended_float_prec_round(self, prec, rm); let out_exp = i64::exact_from(i128::from(out_x.exp) - SaturatingInto::::saturating_into(bits)); ( Self { x: out_x.x, exp: out_exp, }, o, ) } fn shr_round_assign(&mut self, bits: T, _rm: RoundingMode) -> Ordering { // assumes no overflow or underflow if self.x.is_normal() { let out_exp = i64::exact_from( i128::from(self.exp) - SaturatingInto::::saturating_into(bits), ); self.exp = out_exp; } Equal } fn shl_round(mut self, bits: T, rm: RoundingMode) -> (Self, Ordering) { let o = self.shl_round_assign(bits, rm); (self, o) } fn shl_round_ref(&self, bits: T, _rm: RoundingMode) -> (Self, Ordering) { // assumes no overflow or underflow if self.x.is_normal() { let out_exp = i64::exact_from( i128::from(self.exp) + SaturatingInto::::saturating_into(bits), ); ( Self { x: self.x.clone(), exp: out_exp, }, Equal, ) } else { (self.clone(), Equal) } } fn shl_round_assign(&mut self, bits: T, _rm: RoundingMode) -> Ordering { // assumes no overflow or underflow if self.x.is_normal() { let out_exp = i64::exact_from( i128::from(self.exp) + SaturatingInto::::saturating_into(bits), ); self.exp = out_exp; } Equal } pub(crate) fn into_float_helper( mut self, prec: u64, rm: RoundingMode, previous_o: Ordering, ) -> (Float, Ordering) { let o = self .x .shl_prec_round_assign_helper(self.exp, prec, rm, previous_o); (self.x, o) } pub(crate) fn increment(&mut self) { self.x.increment(); if let Some(exp) = self.x.get_exponent() && exp == 1 { self.x >>= 1u32; self.exp = 0; } } } impl From for ExtendedFloat { fn from(value: Float) -> Self { if let Some(exp) = value.get_exponent() { Self { x: value >> exp, exp: i64::from(exp), } } else { Self { x: value, exp: 0 } } } } impl TryFrom for Float { type Error = FloatFromFloatError; fn try_from(value: ExtendedFloat) -> Result { if value.x.is_normal() { let y = value.x << value.exp; if y.is_normal() { Ok(y) } else { Err(if value.exp > 0 { FloatFromFloatError::Overflow } else { FloatFromFloatError::Underflow }) } } else { Ok(value.x) } } } impl TryFrom for Rational { type Error = RationalFromFloatError; fn try_from(value: ExtendedFloat) -> Result { Self::try_from(value.x).map(|x| x << value.exp) } } impl<'a> TryFrom<&'a ExtendedFloat> for Rational { type Error = RationalFromFloatError; fn try_from(value: &'a ExtendedFloat) -> Result { Self::try_from(&value.x).map(|x| x << value.exp) } } impl PartialEq for ExtendedFloat { fn eq(&self, other: &Self) -> bool { self.x == other.x && self.exp == other.exp } } impl PartialOrd for ExtendedFloat { fn partial_cmp(&self, other: &Self) -> Option { assert!(self.is_valid()); assert!(other.is_valid()); let self_sign = self.x > 0u32; let other_sign = other.x > 0u32; match self_sign.cmp(&other_sign) { Greater => Some(Greater), Less => Some(Less), Equal => match self.exp.cmp(&other.exp) { Greater => Some(if self_sign { Greater } else { Less }), Less => Some(if self_sign { Less } else { Greater }), Equal => self.x.partial_cmp(&other.x), }, } } } impl Add<&ExtendedFloat> for &ExtendedFloat { type Output = ExtendedFloat; fn add(self, other: &ExtendedFloat) -> Self::Output { let prec = max(self.x.significant_bits(), other.x.significant_bits()); self.add_prec_ref_ref(other, prec).0 } } impl Mul<&ExtendedFloat> for &ExtendedFloat { type Output = ExtendedFloat; fn mul(self, other: &ExtendedFloat) -> Self::Output { let prec = max(self.x.significant_bits(), other.x.significant_bits()); self.mul_prec_ref_ref(other, prec).0 } } impl SqrtAssign for ExtendedFloat { fn sqrt_assign(&mut self) { if self.exp.odd() { self.x <<= 1; self.exp = self.exp.checked_sub(1).unwrap(); } self.x.sqrt_assign(); self.exp >>= 1; if let Some(new_exp) = self.x.get_exponent() { self.exp = self.exp.checked_add(i64::from(new_exp)).unwrap(); self.x >>= new_exp; } assert!(self.is_valid()); } } impl Sqrt for ExtendedFloat { type Output = Self; fn sqrt(mut self) -> Self::Output { self.sqrt_assign(); self } } impl Shr for ExtendedFloat { type Output = Self; fn shr(mut self, bits: u32) -> Self::Output { self.shr_round_assign(bits, Nearest); self } } impl ShrAssign for ExtendedFloat { fn shr_assign(&mut self, bits: u32) { self.shr_round_assign(bits, Nearest); } } impl ShlAssign for ExtendedFloat { fn shl_assign(&mut self, bits: u32) { self.shl_round_assign(bits, Nearest); } } impl Shl for &ExtendedFloat { type Output = ExtendedFloat; fn shl(self, bits: T) -> ExtendedFloat { self.shl_round_ref(bits, Nearest).0 } } impl Shl for ExtendedFloat { type Output = Self; fn shl(self, bits: T) -> Self { self.shl_round(bits, Nearest).0 } } fn cmp2_helper_extended(b: &ExtendedFloat, c: &ExtendedFloat, cancel: &mut u64) -> Ordering { match (&b.x, &c.x) { ( Float(Finite { precision: x_prec, significand: x, .. }), Float(Finite { precision: y_prec, significand: y, .. }), ) => { let (o, c) = exponent_shift_compare( x.as_limbs_asc(), b.exp, *x_prec, y.as_limbs_asc(), c.exp, *y_prec, ); *cancel = c; o } _ => panic!(), } } pub(crate) fn agm_prec_round_normal_extended( mut a: ExtendedFloat, mut b: ExtendedFloat, prec: u64, rm: RoundingMode, ) -> (ExtendedFloat, Ordering) { if a.x < 0u32 || b.x < 0u32 { return ( ExtendedFloat { x: float_nan!(), exp: 0, }, Equal, ); } let q = prec; let mut working_prec = q + q.ceiling_log_base_2() + 15; // b (op2) and a (op1) are the 2 operands but we want b >= a match a.partial_cmp(&b).unwrap() { Equal => return ExtendedFloat::from_extended_float_prec_round(a, prec, rm), Greater => swap(&mut a, &mut b), _ => {} } let mut increment = Limb::WIDTH; let mut v; let mut scaleit; loop { let mut err: u64 = 0; let mut u = a.mul_prec_ref_ref(&b, working_prec).0; v = a.add_prec_ref_ref(&b, working_prec).0; u.sqrt_assign(); v >>= 1u32; scaleit = 0; let mut n: u64 = 1; let mut eq = 0; while cmp2_helper_extended(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 { let mut vf; vf = (&u + &v) >> 1; // See proof in algorithms.tex if eq > working_prec >> 2 { // vf = V(k) let low_p = (working_prec + 1) >> 1; let mut w = v.sub_prec_ref_ref(&u, low_p).0; // e = V(k-1)-U(k-1) w.square_round_assign(Nearest); // e = e^2 w.shr_round_assign(4, Nearest); // e*= (1/2)^2*1/4 w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k) let vf_exp = vf.exp; v = vf.sub_prec(w, working_prec).0; // 0 or 1 err = u64::exact_from(vf_exp - v.exp); break; } let uf = &u * &v; u = uf.sqrt(); swap(&mut v, &mut vf); n += 1; } // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the // final subtraction // // 18n+51 should not overflow since n is about log(p) err += (18 * n + 51).ceiling_log_base_2(); // we should have n+2 <= 2^(p/4) [see algorithms.tex] if (n + 2).ceiling_log_base_2() <= working_prec >> 2 && float_can_round(v.x.significand_ref().unwrap(), working_prec - err, q, rm) { break; } working_prec += increment; increment = working_prec >> 1; } v.shr_prec_round(scaleit, prec, rm) } pub_crate_test! {agm_prec_round_normal_ref_ref_extended<'a>( mut a: &'a ExtendedFloat, mut b: &'a ExtendedFloat, prec: u64, rm: RoundingMode, ) -> (ExtendedFloat, Ordering) { if a.x < 0u32 || b.x < 0u32 { return ( ExtendedFloat { x: float_nan!(), exp: 0, }, Equal, ); } let q = prec; let mut working_prec = q + q.ceiling_log_base_2() + 15; // b (op2) and a (op1) are the 2 operands but we want b >= a match a.partial_cmp(b).unwrap() { Equal => return ExtendedFloat::from_extended_float_prec_round_ref(a, prec, rm), Greater => swap(&mut a, &mut b), _ => {} } let mut increment = Limb::WIDTH; let mut v; let mut scaleit; loop { let mut err: u64 = 0; let mut u = a.mul_prec_ref_ref(b, working_prec).0; v = a.add_prec_ref_ref(b, working_prec).0; u.sqrt_assign(); v >>= 1u32; scaleit = 0; let mut n: u64 = 1; let mut eq = 0; while cmp2_helper_extended(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 { let mut vf; vf = (&u + &v) >> 1; // See proof in algorithms.tex if eq > working_prec >> 2 { // vf = V(k) let low_p = (working_prec + 1) >> 1; let mut w = v.sub_prec_ref_ref(&u, low_p).0; // e = V(k-1)-U(k-1) assert!(w.is_valid()); assert!(w.x.is_normal()); w.square_round_assign(Nearest); // e = e^2 assert!(w.is_valid()); assert!(w.x.is_normal()); w.shr_round_assign(4, Nearest); // e*= (1/2)^2*1/4 assert!(w.is_valid()); assert!(w.x.is_normal()); w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k) let vf_exp = vf.exp; v = vf.sub_prec(w, working_prec).0; // 0 or 1 err = u64::exact_from(vf_exp - v.exp); break; } let uf = &u * &v; u = uf.sqrt(); swap(&mut v, &mut vf); n += 1; } // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the // final subtraction // // 18n+51 should not overflow since n is about log(p) err += (18 * n + 51).ceiling_log_base_2(); // we should have n+2 <= 2^(p/4) [see algorithms.tex] if (n + 2).ceiling_log_base_2() <= working_prec >> 2 && float_can_round(v.x.significand_ref().unwrap(), working_prec - err, q, rm) { break; } working_prec += increment; increment = working_prec >> 1; } v.shr_prec_round(scaleit, prec, rm) }} ================================================ FILE: malachite-float/src/basic/get_and_set.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::Finite; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ NegAssign, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; const PREC_ROUND_THRESHOLD: u64 = 1500; impl Float { /// Gets the significand of a [`Float`], taking the [`Float`] by value. /// /// The significand is the smallest positive integer which is some power of 2 times the /// [`Float`], and whose number of significant bits is a multiple of the limb width. If the /// [`Float`] is NaN, infinite, or zero, then `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::arithmetic::traits::PowerOf2; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_float::Float; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::NAN.to_significand(), None); /// assert_eq!(Float::INFINITY.to_significand(), None); /// assert_eq!(Float::ZERO.to_significand(), None); /// /// #[cfg(not(feature = "32_bit_limbs"))] /// { /// assert_eq!(Float::ONE.to_significand(), Some(Natural::power_of_2(63))); /// assert_eq!( /// Float::from(std::f64::consts::PI).to_significand().unwrap(), /// 14488038916154245120u64 /// ); /// } /// ``` #[inline] pub fn to_significand(&self) -> Option { match self { Self(Finite { significand, .. }) => Some(significand.clone()), _ => None, } } /// Gets the significand of a [`Float`], taking the [`Float`] by reference. /// /// The significand is the smallest positive integer which is some power of 2 times the /// [`Float`], and whose number of significant bits is a multiple of the limb width. If the /// [`Float`] is NaN, infinite, or zero, then `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::arithmetic::traits::PowerOf2; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_float::Float; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::NAN.into_significand(), None); /// assert_eq!(Float::INFINITY.into_significand(), None); /// assert_eq!(Float::ZERO.into_significand(), None); /// /// #[cfg(not(feature = "32_bit_limbs"))] /// { /// assert_eq!(Float::ONE.into_significand(), Some(Natural::power_of_2(63))); /// assert_eq!( /// Float::from(std::f64::consts::PI) /// .into_significand() /// .unwrap(), /// 14488038916154245120u64 /// ); /// } /// ``` #[allow(clippy::missing_const_for_fn)] // destructor doesn't work with const #[inline] pub fn into_significand(self) -> Option { match self { Self(Finite { significand, .. }) => Some(significand), _ => None, } } /// Returns a reference to the significand of a [`Float`]. /// /// The significand is the smallest positive integer which is some power of 2 times the /// [`Float`], and whose number of significant bits is a multiple of the limb width. If the /// [`Float`] is NaN, infinite, or zero, then `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::arithmetic::traits::PowerOf2; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_float::Float; /// #[cfg(not(feature = "32_bit_limbs"))] /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::NAN.significand_ref(), None); /// assert_eq!(Float::INFINITY.significand_ref(), None); /// assert_eq!(Float::ZERO.significand_ref(), None); /// /// #[cfg(not(feature = "32_bit_limbs"))] /// { /// assert_eq!( /// *Float::ONE.significand_ref().unwrap(), /// Natural::power_of_2(63) /// ); /// assert_eq!( /// *Float::from(std::f64::consts::PI).significand_ref().unwrap(), /// 14488038916154245120u64 /// ); /// } /// ``` #[inline] pub const fn significand_ref(&self) -> Option<&Natural> { match self { Self(Finite { significand, .. }) => Some(significand), _ => None, } } /// Returns a [`Float`]'s exponent. /// /// $$ /// f(\text{NaN}) = f(\pm\infty) = f(\pm 0.0) = \text{None}, /// $$ /// /// and, if $x$ is finite and nonzero, /// /// $$ /// f(x) = \operatorname{Some}(\lfloor \log_2 |x| \rfloor + 1). /// $$ /// /// The output is in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{Infinity, NaN, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.get_exponent(), None); /// assert_eq!(Float::INFINITY.get_exponent(), None); /// assert_eq!(Float::ZERO.get_exponent(), None); /// /// assert_eq!(Float::ONE.get_exponent(), Some(1)); /// assert_eq!(Float::from(std::f64::consts::PI).get_exponent(), Some(2)); /// assert_eq!(Float::power_of_2(100u64).get_exponent(), Some(101)); /// assert_eq!(Float::power_of_2(-100i64).get_exponent(), Some(-99)); /// ``` #[inline] pub const fn get_exponent(&self) -> Option { match self { Self(Finite { exponent, .. }) => Some(*exponent), _ => None, } } /// Returns a [`Float`]'s precision. The precision is a positive integer denoting how many of /// the [`Float`]'s bits are significant. /// /// Only [`Float`]s that are finite and nonzero have a precision. For other [`Float`]s, `None` /// is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.get_prec(), None); /// assert_eq!(Float::INFINITY.get_prec(), None); /// assert_eq!(Float::ZERO.get_prec(), None); /// /// assert_eq!(Float::ONE.get_prec(), Some(1)); /// assert_eq!(Float::one_prec(100).get_prec(), Some(100)); /// assert_eq!(Float::from(std::f64::consts::PI).get_prec(), Some(50)); /// ``` #[inline] pub const fn get_prec(&self) -> Option { match self { Self(Finite { precision, .. }) => Some(*precision), _ => None, } } /// Returns the minimum precision necessary to represent the given [`Float`]'s value. /// /// For example, `Float:one_prec(100)` has a precision of 100, but its minimum precision is 1, /// because that's all that's necessary to represent the value 1. /// /// The minimum precision is always less than or equal to the actual precision. /// /// Only [`Float`]s that are finite and nonzero have a minimum precision. For other [`Float`]s, /// `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.get_min_prec(), None); /// assert_eq!(Float::INFINITY.get_min_prec(), None); /// assert_eq!(Float::ZERO.get_min_prec(), None); /// /// assert_eq!(Float::ONE.get_min_prec(), Some(1)); /// assert_eq!(Float::one_prec(100).get_min_prec(), Some(1)); /// assert_eq!(Float::from(std::f64::consts::PI).get_min_prec(), Some(50)); /// ``` pub fn get_min_prec(&self) -> Option { match self { Self(Finite { significand, .. }) => { Some(significand_bits(significand) - significand.trailing_zeros().unwrap()) } _ => None, } } /// Changes a [`Float`]'s precision. If the precision decreases, rounding may be necessary, and /// will use the provided [`RoundingMode`]. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the [`Float`] originally had the maximum exponent, it is possible for this function to /// overflow. This is even possible if `rm` is `Nearest`, even though infinity is never nearer /// to the exact result than any finite [`Float`] is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is [`Exact`] but setting the desired precision requires /// rounding. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let mut x = original_x.clone(); /// assert_eq!(x.set_prec_round(100, Exact), Equal); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// /// let mut x = original_x.clone(); /// assert_eq!(x.set_prec_round(10, Floor), Less); /// assert_eq!(x.to_string(), "0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// /// let mut x = original_x.clone(); /// assert_eq!(x.set_prec_round(10, Ceiling), Greater); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// ``` pub fn set_prec_round(&mut self, prec: u64, rm: RoundingMode) -> Ordering { assert_ne!(prec, 0); match self { Self(Finite { sign, exponent, precision, significand, }) => { let target_bits = prec .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0; let significant_bits = significand_bits(significand); let o; if target_bits > significant_bits { *significand <<= target_bits - significant_bits; o = Equal; } else { let limb_count = significand.limb_count(); let abs_rm = if *sign { rm } else { -rm }; o = significand .round_to_multiple_of_power_of_2_assign(significant_bits - prec, abs_rm); if significand.limb_count() > limb_count { if *exponent == Self::MAX_EXPONENT { return if *sign { *self = Self::INFINITY; Greater } else { *self = Self::NEGATIVE_INFINITY; Less }; } *significand >>= 1; *exponent += 1; } *significand >>= significant_bits - target_bits; } *precision = prec; if *sign { o } else { o.reverse() } } _ => Equal, } } /// Changes a [`Float`]'s precision. If the precision decreases, rounding may be necessary, and /// [`Nearest`] will be used. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the [`Float`] originally had the maximum exponent, it is possible for this function to /// overflow, even though infinity is never nearer to the exact result than any finite [`Float`] /// is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// To use a different rounding mode, try [`Float::set_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let mut x = original_x.clone(); /// assert_eq!(x.set_prec(100), Equal); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// /// let mut x = original_x.clone(); /// assert_eq!(x.set_prec(10), Greater); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// ``` #[inline] pub fn set_prec(&mut self, p: u64) -> Ordering { self.set_prec_round(p, Nearest) } /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the /// precision decreases, rounding may be necessary, and will use the provided [`RoundingMode`]. /// The input [`Float`] is taken by value. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the input [`Float`] has the maximum exponent, it is possible for this function to /// overflow. This is even possible if `rm` is `Nearest`, even though infinity is never nearer /// to the exact result than any finite [`Float`] is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is [`Exact`] but setting the desired precision requires /// rounding. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 100, Exact); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 10, Floor); /// assert_eq!(x.to_string(), "0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_float_prec_round(original_x.clone(), 10, Ceiling); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_float_prec_round(mut x: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { let o = x.set_prec_round(prec, rm); (x, o) } /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the /// precision decreases, rounding may be necessary, and will use the provided [`RoundingMode`]. /// The input [`Float`] is taken by reference. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the input [`Float`] has the maximum exponent, it is possible for this function to /// overflow. This is even possible if `rm` is `Nearest`, even though infinity is never nearer /// to the exact result than any finite [`Float`] is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is [`Exact`] but setting the desired precision requires /// rounding. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 100, Exact); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 10, Floor); /// assert_eq!(x.to_string(), "0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_float_prec_round_ref(&original_x, 10, Ceiling); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// ``` pub fn from_float_prec_round_ref(x: &Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) { if x.significant_bits() < PREC_ROUND_THRESHOLD { let mut x = x.clone(); let o = x.set_prec_round(prec, rm); return (x, o); } match x { Self(Finite { sign, exponent, significand, .. }) => { let (mut y, mut o) = Self::from_natural_prec_round_ref( significand, prec, if *sign { rm } else { -rm }, ); if !sign { y.neg_assign(); o = o.reverse(); } ( y >> (i32::exact_from(significand_bits(significand)) - exponent), o, ) } _ => (x.clone(), Equal), } } /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the /// precision decreases, rounding may be necessary, and will use [`Nearest`]. The input /// [`Float`] is taken by value. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the [`Float`] originally had the maximum exponent, it is possible for this function to /// overflow, even though infinity is never nearer to the exact result than any finite [`Float`] /// is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// To use a different rounding mode, try [`Float::from_float_prec_round`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let (x, o) = Float::from_float_prec(original_x.clone(), 100); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_float_prec(original_x.clone(), 10); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_float_prec(mut x: Self, prec: u64) -> (Self, Ordering) { let o = x.set_prec(prec); (x, o) } /// Creates a [`Float`] from another [`Float`], possibly with a different precision. If the /// precision decreases, rounding may be necessary, and will use [`Nearest`]. The input /// [`Float`] is taken by reference. /// /// Returns an [`Ordering`], indicating whether the final value is less than, greater than, or /// equal to the original value. /// /// If the [`Float`] originally had the maximum exponent, it is possible for this function to /// overflow, even though infinity is never nearer to the exact result than any finite [`Float`] /// is. This is to match the behavior of MPFR. /// /// This function never underflows. /// /// To use a different rounding mode, try [`Float::from_float_prec_round_ref`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let original_x = Float::from(1.0f64 / 3.0); /// assert_eq!(original_x.to_string(), "0.33333333333333331"); /// assert_eq!(original_x.get_prec(), Some(53)); /// /// let (x, o) = Float::from_float_prec_ref(&original_x, 100); /// assert_eq!(x.to_string(), "0.3333333333333333148296162562474"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_float_prec_ref(&original_x, 10); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_float_prec_ref(x: &Self, prec: u64) -> (Self, Ordering) { Self::from_float_prec_round_ref(x, prec, Nearest) } } ================================================ FILE: malachite-float/src/basic/mod.rs ================================================ // Copyright © 2026 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 . /// Classification of a [`Float`](super::Float) into several kinds. pub mod classification; /// Measuring the complexity to a [`Float`](super::Float). pub mod complexity; /// Various [`Float`](super::Float) constants. This module contains actual Rust constants like /// [`One`](super::Float#impl-One-for-Float), and functions like [`one`](super::Float::one_prec) /// which accept a precision. #[macro_use] pub mod constants; /// Floating-point numbers with a greater exponent range; for internal use only. pub mod extended; /// Getting and setting the components of a [`Float`](super::Float). pub mod get_and_set; /// Getting [`Float`](super::Float)'s ulp (unit in the last place). pub mod ulp; ================================================ FILE: malachite-float/src/basic/ulp.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::Finite; use crate::{Float, significand_bits}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, NegAssign, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, Zero}; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::bit_to_limb_count_floor; use malachite_nz::platform::Limb; impl Float { /// Gets a [`Float`]'s ulp (unit in last place, or unit of least precision). /// /// If the [`Float`] is positive, its ulp is the distance to the next-largest [`Float`] with the /// same precision; if it is negative, the next-smallest. (This definition works even if the /// [`Float`] is the largest in its binade. If the [`Float`] is the largest in its binade and /// has the maximum exponent, we can define its ulp to be the distance to the next-smallest /// [`Float`] with the same precision if positive, and to the next-largest [`Float`] with the /// same precision if negative.) /// /// If the [`Float`] is NaN, infinite, or zero, then `None` is returned. /// /// This function does not overflow or underflow, technically. But it is possible that a /// [`Float`]'s ulp is too small to represent, for example if the [`Float`] has the minimum /// exponent and its precision is greater than 1, or if the precision is extremely large in /// general. In such cases, `None` is returned. /// /// $$ /// f(\text{NaN}) = f(\pm\infty) = f(\pm 0.0) = \text{None}, /// $$ /// /// and, if $x$ is finite and nonzero, /// /// $$ /// f(x) = \operatorname{Some}(2^{\lfloor \log_2 |x| \rfloor-p+1}), /// $$ /// where $p$ is the precision of $x$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeOne, One, Zero}; /// use malachite_float::Float; /// /// assert_eq!(Float::NAN.ulp(), None); /// assert_eq!(Float::INFINITY.ulp(), None); /// assert_eq!(Float::ZERO.ulp(), None); /// /// let s = Float::ONE.ulp().map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("1.0")); /// /// let s = Float::one_prec(100).ulp().map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("2.0e-30")); /// /// let s = Float::from(std::f64::consts::PI) /// .ulp() /// .map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("4.0e-15")); /// /// let s = Float::power_of_2(100u64).ulp().map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("1.0e30")); /// /// let s = Float::power_of_2(-100i64).ulp().map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("8.0e-31")); /// /// let s = Float::NEGATIVE_ONE.ulp().map(|x| x.to_string()); /// assert_eq!(s.as_ref().map(|s| s.as_str()), Some("1.0")); /// ``` pub fn ulp(&self) -> Option { match self { Self(Finite { exponent, precision, .. }) => { let ulp_exponent = i64::from(*exponent).checked_sub(i64::try_from(*precision).ok()?)?; if i32::try_from(ulp_exponent).ok()? >= Self::MIN_EXPONENT - 1 { Some(Self::power_of_2(ulp_exponent)) } else { None } } _ => None, } } /// Increments a [`Float`] by its ulp. See [`Float::ulp`] for details. /// /// If the [`Float`] is positive and is the largest [`Float`] in its binade with its precision, /// then /// - If its exponent is not the maximum exponent, it will become the smallest [`Float`] in the /// next-higher binade, and its precision will increase by 1 (so that its ulp remains the /// same); /// - If its exponent is the maximum exponent, it will become $\infty$. /// /// If the [`Float`] is negative and is closer to zero than any other [`Float`] in its binade /// with its precision, then /// - If its precision is 1, it will become negative zero. /// - If its precision is greater than 1 and its exponent is not the minimum exponent, it will /// become the farthest-from-zero [`Float`] in the next-lower binade, and its precision will /// decrease by 1 (so that its ulp remains the same). /// - If its precision is greater than 1 and its exponent is the minimum exponent, it will /// become negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is NaN, infinite, or zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_float::Float; /// /// let mut x = Float::ONE; /// assert_eq!(x.to_string(), "1.0"); /// x.increment(); /// assert_eq!(x.to_string(), "2.0"); /// /// let mut x = Float::one_prec(100); /// assert_eq!(x.to_string(), "1.0"); /// x.increment(); /// assert_eq!(x.to_string(), "1.000000000000000000000000000002"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.to_string(), "3.141592653589793"); /// x.increment(); /// assert_eq!(x.to_string(), "3.141592653589797"); /// /// let mut x = Float::power_of_2(100u64); /// assert_eq!(x.to_string(), "1.0e30"); /// x.increment(); /// assert_eq!(x.to_string(), "3.0e30"); /// /// let mut x = Float::power_of_2(-100i64); /// assert_eq!(x.to_string(), "8.0e-31"); /// x.increment(); /// assert_eq!(x.to_string(), "1.6e-30"); /// /// let mut x = Float::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "-1.0"); /// x.increment(); /// assert_eq!(x.to_string(), "-0.0"); /// ``` pub fn increment(&mut self) { if self.is_sign_negative() { self.neg_assign(); self.decrement(); self.neg_assign(); } else if let Self(Finite { exponent, precision, significand, .. }) = self { let ulp = Limb::power_of_2(significand_bits(significand) - *precision); let limb_count = significand.limb_count(); significand.add_assign_at_limb( usize::wrapping_from(limb_count) - 1 - bit_to_limb_count_floor(*precision - 1), ulp, ); if significand.limb_count() > limb_count { if *exponent == Self::MAX_EXPONENT { *self = Self::INFINITY; return; } *significand >>= 1; *exponent += 1; if precision.divisible_by_power_of_2(Limb::LOG_WIDTH) { *significand <<= Limb::WIDTH; } *precision = precision.checked_add(1).unwrap(); } } else { panic!("Cannot increment float is non-finite or zero"); } } /// Decrements a [`Float`] by its ulp. See [`Float::ulp`] for details. /// /// If the [`Float`] is negative and is the largest [`Float`] in its binade with its precision, /// then /// - If its exponent is not the maximum exponent, it will become the closest-to-zero [`Float`] /// in the next-higher binade, and its precision will increase by 1 (so that its ulp remains /// the same); /// - If its exponent is the maximum exponent, it will become $-\infty$. /// /// If the [`Float`] is positive and is smaller than any other [`Float`] in its binade with its /// precision, then /// - If its precision is 1, it will become positive zero. /// - If its precision is greater than 1 and its exponent is not the minimum exponent, it will /// become the largest [`Float`] in the next-lower binade, and its precision will decrease by /// 1 (so that its ulp remains the same). /// - If its precision is greater than 1 and its exponent is the minimum exponent, it will /// become positive zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is NaN, infinite, or zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_float::Float; /// /// let mut x = Float::ONE; /// assert_eq!(x.to_string(), "1.0"); /// x.decrement(); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::one_prec(100); /// assert_eq!(x.to_string(), "1.0"); /// x.decrement(); /// assert_eq!(x.to_string(), "0.999999999999999999999999999998"); /// /// let mut x = Float::from(std::f64::consts::PI); /// assert_eq!(x.to_string(), "3.141592653589793"); /// x.decrement(); /// assert_eq!(x.to_string(), "3.14159265358979"); /// /// let mut x = Float::power_of_2(100u64); /// assert_eq!(x.to_string(), "1.0e30"); /// x.decrement(); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::power_of_2(-100i64); /// assert_eq!(x.to_string(), "8.0e-31"); /// x.decrement(); /// assert_eq!(x.to_string(), "0.0"); /// /// let mut x = Float::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "-1.0"); /// x.decrement(); /// assert_eq!(x.to_string(), "-2.0"); /// ``` pub fn decrement(&mut self) { if self.is_sign_negative() { self.neg_assign(); self.increment(); self.neg_assign(); } else if let Self(Finite { exponent, precision, significand, .. }) = self { let bits = significand_bits(significand); let ulp = Limb::power_of_2(bits - *precision); significand.sub_assign_at_limb( usize::wrapping_from(significand.limb_count()) - 1 - bit_to_limb_count_floor(*precision - 1), ulp, ); if *significand == 0u32 { *self = Self::ZERO; } else if significand.significant_bits() < bits { if *exponent == Self::MIN_EXPONENT { *self = Self::ZERO; return; } *significand <<= 1; *exponent -= 1; *precision = precision.checked_sub(1).unwrap(); if bits - *precision == Limb::WIDTH { *significand >>= Limb::WIDTH; } } } else { panic!("Cannot decrement float that is non-finite or zero"); } } } ================================================ FILE: malachite-float/src/bin.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #[cfg(feature = "bin_build")] extern crate itertools; #[cfg(feature = "bin_build")] #[macro_use] extern crate malachite_base; #[cfg(feature = "bin_build")] extern crate malachite_nz; #[cfg(feature = "bin_build")] extern crate malachite_q; #[cfg(feature = "bin_build")] extern crate num; #[cfg(feature = "bin_build")] extern crate rug; #[cfg(feature = "bin_build")] extern crate serde; #[cfg(feature = "bin_build")] extern crate serde_json; #[cfg(feature = "bin_build")] use crate::bin_util::demo_and_bench::register; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::Runner; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::cmd::read_command_line_arguments; // Examples: TODO // // ``` // cargo run --release --features bin_build -- -l 10000 -m special_random -d demo_from_naturals // -c "mean_bits_n 128 mean_bits_d 1" // ``` #[cfg(feature = "bin_build")] fn main() { let args = read_command_line_arguments("malachite-float test utils"); let mut runner = Runner::new(); register(&mut runner); if let Some(demo_key) = args.demo_key { runner.run_demo(&demo_key, args.generation_mode, &args.config, args.limit); } else if let Some(bench_key) = args.bench_key { runner.run_bench( &bench_key, args.generation_mode, &args.config, args.limit, &args.out, ); } else { panic!(); } } #[cfg(not(feature = "bin_build"))] fn main() {} #[cfg(feature = "bin_build")] pub mod bin_util { pub mod demo_and_bench; } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_2_float_complexity_bucketer, }; use malachite_float::test_util::generators::{float_gen, float_gen_rm, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_abs_negative_zero); register_demo!(runner, demo_float_abs_negative_zero_debug); register_demo!(runner, demo_float_abs_negative_zero_extreme); register_demo!(runner, demo_float_abs_negative_zero_extreme_debug); register_demo!(runner, demo_float_abs_negative_zero_ref); register_demo!(runner, demo_float_abs_negative_zero_ref_debug); register_demo!(runner, demo_float_abs_negative_zero_assign); register_demo!(runner, demo_float_abs_negative_zero_assign_debug); register_demo!(runner, demo_float_abs); register_demo!(runner, demo_float_abs_debug); register_demo!(runner, demo_float_abs_extreme); register_demo!(runner, demo_float_abs_extreme_debug); register_demo!(runner, demo_float_abs_ref); register_demo!(runner, demo_float_abs_ref_debug); register_demo!(runner, demo_float_abs_assign); register_demo!(runner, demo_float_abs_assign_debug); register_bench!( runner, benchmark_float_abs_negative_zero_evaluation_strategy ); register_bench!(runner, benchmark_float_abs_negative_zero_assign); register_bench!(runner, benchmark_float_abs_library_comparison); register_bench!(runner, benchmark_float_abs_evaluation_strategy); register_bench!(runner, benchmark_float_abs_assign); } fn demo_float_abs_negative_zero(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "abs_negative_zero({}) = {}", n.clone(), n.abs_negative_zero() ); } } fn demo_float_abs_negative_zero_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "abs_negative_zero({:#x}) = {:#x}", ComparableFloat(n.clone()), ComparableFloat(n.abs_negative_zero()) ); } } fn demo_float_abs_negative_zero_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!( "abs_negative_zero({}) = {}", n.clone(), n.abs_negative_zero() ); } } fn demo_float_abs_negative_zero_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!( "abs_negative_zero({:#x}) = {:#x}", ComparableFloat(n.clone()), ComparableFloat(n.abs_negative_zero()) ); } } fn demo_float_abs_negative_zero_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "abs_negative_zero_ref(&{}) = {}", n, n.abs_negative_zero_ref() ); } } fn demo_float_abs_negative_zero_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "abs_negative_zero(&{:#x}) = {:#x}", ComparableFloatRef(&n), ComparableFloat(n.abs_negative_zero_ref()) ); } } fn demo_float_abs_negative_zero_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_negative_zero_assign(); println!("n := {n_old}; n.abs_negative_zero_assign(); n = {n}"); } } fn demo_float_abs_negative_zero_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_negative_zero_assign(); println!( "n := {:#x}; n.abs_negative_zero_assign(); n = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn demo_float_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!("|{}| = {}", n.clone(), n.abs()); } } fn demo_float_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "|{:#x}| = {:#x}", ComparableFloat(n.clone()), ComparableFloat(n.abs()) ); } } fn demo_float_abs_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!("|{}| = {}", n.clone(), n.abs()); } } fn demo_float_abs_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!( "|{:#x}| = {:#x}", ComparableFloat(n.clone()), ComparableFloat(n.abs()) ); } } fn demo_float_abs_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!("|&{}| = {}", n, (&n).abs()); } } fn demo_float_abs_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "|&{:#x}| = {:#x}", ComparableFloatRef(&n), ComparableFloat((&n).abs()) ); } } fn demo_float_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_assign(); println!("n := {n_old}; n.abs_assign(); n = {n}"); } } fn demo_float_abs_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_assign(); println!( "n := {:#x}; n.abs_assign(); n = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn benchmark_float_abs_negative_zero_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs_negative_zero()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Rational.abs_negative_zero()", &mut |n| { no_out!(n.abs_negative_zero()); }), ("(&Rational).abs_negative_zero_ref()", &mut |n| { no_out!(n.abs_negative_zero_ref()); }), ], ); } fn benchmark_float_abs_negative_zero_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs_negative_zero_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |mut n| n.abs_negative_zero_assign())], ); } #[allow(unused_must_use)] fn benchmark_float_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.abs())), ("rug", &mut |(n, _)| no_out!(n.abs())), ], ); } fn benchmark_float_abs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Rational.abs()", &mut |n| no_out!(n.abs())), ("(&Rational).abs()", &mut |n| no_out!((&n).abs())), ], ); } fn benchmark_float_abs_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.abs_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |mut n| n.abs_assign())], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::add::{ add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_prec, rug_add_prec_round, rug_add_rational, rug_add_rational_prec, rug_add_rational_prec_round, rug_add_rational_round, rug_add_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_2_triple_float_float_primitive_int_max_complexity_bucketer, pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, triple_float_float_primitive_int_max_complexity_bucketer, triple_float_rational_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1, float_float_rounding_mode_triple_gen_var_1_rm, float_float_rounding_mode_triple_gen_var_29, float_float_unsigned_rounding_mode_quadruple_gen_var_1, float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm, float_float_unsigned_rounding_mode_quadruple_gen_var_5, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_float_unsigned_triple_gen_var_2, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_1, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_rounding_mode_triple_gen_var_7, float_rational_unsigned_rounding_mode_quadruple_gen_var_1, float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_6, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, float_rational_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_add); register_demo!(runner, demo_float_add_debug); register_demo!(runner, demo_float_add_extreme); register_demo!(runner, demo_float_add_extreme_debug); register_demo!(runner, demo_float_add_val_ref); register_demo!(runner, demo_float_add_val_ref_debug); register_demo!(runner, demo_float_add_ref_val); register_demo!(runner, demo_float_add_ref_val_debug); register_demo!(runner, demo_float_add_ref_ref); register_demo!(runner, demo_float_add_ref_ref_debug); register_demo!(runner, demo_float_add_assign); register_demo!(runner, demo_float_add_assign_debug); register_demo!(runner, demo_float_add_assign_ref); register_demo!(runner, demo_float_add_assign_ref_debug); register_demo!(runner, demo_float_add_prec); register_demo!(runner, demo_float_add_prec_debug); register_demo!(runner, demo_float_add_prec_extreme); register_demo!(runner, demo_float_add_prec_extreme_debug); register_demo!(runner, demo_float_add_prec_val_ref); register_demo!(runner, demo_float_add_prec_val_ref_debug); register_demo!(runner, demo_float_add_prec_ref_val); register_demo!(runner, demo_float_add_prec_ref_val_debug); register_demo!(runner, demo_float_add_prec_ref_ref); register_demo!(runner, demo_float_add_prec_ref_ref_debug); register_demo!(runner, demo_float_add_prec_assign); register_demo!(runner, demo_float_add_prec_assign_debug); register_demo!(runner, demo_float_add_prec_assign_ref); register_demo!(runner, demo_float_add_prec_assign_ref_debug); register_demo!(runner, demo_float_add_round); register_demo!(runner, demo_float_add_round_debug); register_demo!(runner, demo_float_add_round_extreme); register_demo!(runner, demo_float_add_round_extreme_debug); register_demo!(runner, demo_float_add_round_val_ref); register_demo!(runner, demo_float_add_round_val_ref_debug); register_demo!(runner, demo_float_add_round_ref_val); register_demo!(runner, demo_float_add_round_ref_val_debug); register_demo!(runner, demo_float_add_round_ref_ref); register_demo!(runner, demo_float_add_round_ref_ref_debug); register_demo!(runner, demo_float_add_round_assign); register_demo!(runner, demo_float_add_round_assign_debug); register_demo!(runner, demo_float_add_round_assign_ref); register_demo!(runner, demo_float_add_round_assign_ref_debug); register_demo!(runner, demo_float_add_prec_round); register_demo!(runner, demo_float_add_prec_round_debug); register_demo!(runner, demo_float_add_prec_round_extreme); register_demo!(runner, demo_float_add_prec_round_extreme_debug); register_demo!(runner, demo_float_add_prec_round_val_ref); register_demo!(runner, demo_float_add_prec_round_val_ref_debug); register_demo!(runner, demo_float_add_prec_round_ref_val); register_demo!(runner, demo_float_add_prec_round_ref_val_debug); register_demo!(runner, demo_float_add_prec_round_ref_ref); register_demo!(runner, demo_float_add_prec_round_ref_ref_debug); register_demo!(runner, demo_float_add_prec_round_assign); register_demo!(runner, demo_float_add_prec_round_assign_debug); register_demo!(runner, demo_float_add_prec_round_assign_ref); register_demo!(runner, demo_float_add_prec_round_assign_ref_debug); register_demo!(runner, demo_float_add_rational); register_demo!(runner, demo_float_add_rational_debug); register_demo!(runner, demo_float_add_rational_extreme); register_demo!(runner, demo_float_add_rational_extreme_debug); register_demo!(runner, demo_float_add_rational_val_ref); register_demo!(runner, demo_float_add_rational_val_ref_debug); register_demo!(runner, demo_float_add_rational_ref_val); register_demo!(runner, demo_float_add_rational_ref_val_debug); register_demo!(runner, demo_float_add_rational_ref_ref); register_demo!(runner, demo_float_add_rational_ref_ref_debug); register_demo!(runner, demo_float_add_rational_assign); register_demo!(runner, demo_float_add_rational_assign_debug); register_demo!(runner, demo_float_add_rational_assign_ref); register_demo!(runner, demo_float_add_rational_assign_ref_debug); register_demo!(runner, demo_rational_add_float); register_demo!(runner, demo_rational_add_float_debug); register_demo!(runner, demo_rational_add_float_extreme); register_demo!(runner, demo_rational_add_float_extreme_debug); register_demo!(runner, demo_rational_add_float_val_ref); register_demo!(runner, demo_rational_add_float_val_ref_debug); register_demo!(runner, demo_rational_add_float_ref_val); register_demo!(runner, demo_rational_add_float_ref_val_debug); register_demo!(runner, demo_rational_add_float_ref_ref); register_demo!(runner, demo_rational_add_float_ref_ref_debug); register_demo!(runner, demo_float_add_rational_prec); register_demo!(runner, demo_float_add_rational_prec_debug); register_demo!(runner, demo_float_add_rational_prec_extreme); register_demo!(runner, demo_float_add_rational_prec_extreme_debug); register_demo!(runner, demo_float_add_rational_prec_val_ref); register_demo!(runner, demo_float_add_rational_prec_val_ref_debug); register_demo!(runner, demo_float_add_rational_prec_ref_val); register_demo!(runner, demo_float_add_rational_prec_ref_val_debug); register_demo!(runner, demo_float_add_rational_prec_ref_ref); register_demo!(runner, demo_float_add_rational_prec_ref_ref_debug); register_demo!(runner, demo_float_add_rational_prec_assign); register_demo!(runner, demo_float_add_rational_prec_assign_debug); register_demo!(runner, demo_float_add_rational_prec_assign_ref); register_demo!(runner, demo_float_add_rational_prec_assign_ref_debug); register_demo!(runner, demo_float_add_rational_round); register_demo!(runner, demo_float_add_rational_round_debug); register_demo!(runner, demo_float_add_rational_round_extreme); register_demo!(runner, demo_float_add_rational_round_extreme_debug); register_demo!(runner, demo_float_add_rational_round_val_ref); register_demo!(runner, demo_float_add_rational_round_val_ref_debug); register_demo!(runner, demo_float_add_rational_round_ref_val); register_demo!(runner, demo_float_add_rational_round_ref_val_debug); register_demo!(runner, demo_float_add_rational_round_ref_ref); register_demo!(runner, demo_float_add_rational_round_ref_ref_debug); register_demo!(runner, demo_float_add_rational_round_assign); register_demo!(runner, demo_float_add_rational_round_assign_debug); register_demo!(runner, demo_float_add_rational_round_assign_ref); register_demo!(runner, demo_float_add_rational_round_assign_ref_debug); register_demo!(runner, demo_float_add_rational_prec_round); register_demo!(runner, demo_float_add_rational_prec_round_debug); register_demo!(runner, demo_float_add_rational_prec_round_extreme); register_demo!(runner, demo_float_add_rational_prec_round_extreme_debug); register_demo!(runner, demo_float_add_rational_prec_round_val_ref); register_demo!(runner, demo_float_add_rational_prec_round_val_ref_debug); register_demo!(runner, demo_float_add_rational_prec_round_ref_val); register_demo!(runner, demo_float_add_rational_prec_round_ref_val_debug); register_demo!(runner, demo_float_add_rational_prec_round_ref_ref); register_demo!(runner, demo_float_add_rational_prec_round_ref_ref_debug); register_demo!(runner, demo_float_add_rational_prec_round_assign); register_demo!(runner, demo_float_add_rational_prec_round_assign_debug); register_demo!(runner, demo_float_add_rational_prec_round_assign_ref); register_demo!(runner, demo_float_add_rational_prec_round_assign_ref_debug); register_bench!(runner, benchmark_float_add_evaluation_strategy); register_bench!(runner, benchmark_float_add_library_comparison); register_bench!(runner, benchmark_float_add_algorithms); register_bench!(runner, benchmark_float_add_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_library_comparison); register_bench!(runner, benchmark_float_add_prec_algorithms); register_bench!(runner, benchmark_float_add_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_round_evaluation_strategy); register_bench!(runner, benchmark_float_add_round_library_comparison); register_bench!(runner, benchmark_float_add_round_algorithms); register_bench!(runner, benchmark_float_add_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_add_prec_round_library_comparison); register_bench!(runner, benchmark_float_add_prec_round_algorithms); register_bench!( runner, benchmark_float_add_prec_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_float_add_rational_evaluation_strategy); register_bench!(runner, benchmark_float_add_rational_library_comparison); register_bench!(runner, benchmark_float_add_rational_algorithms); register_bench!( runner, benchmark_float_add_rational_assign_evaluation_strategy ); register_bench!(runner, benchmark_rational_add_float_evaluation_strategy); register_bench!(runner, benchmark_rational_add_float_library_comparison); register_bench!( runner, benchmark_float_add_rational_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_add_rational_prec_library_comparison); register_bench!(runner, benchmark_float_add_rational_prec_algorithms); register_bench!( runner, benchmark_float_add_rational_prec_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_add_rational_round_evaluation_strategy ); register_bench!( runner, benchmark_float_add_rational_round_library_comparison ); register_bench!(runner, benchmark_float_add_rational_round_algorithms); register_bench!( runner, benchmark_float_add_rational_round_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_add_rational_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_add_rational_prec_round_library_comparison ); register_bench!(runner, benchmark_float_add_rational_prec_round_algorithms); register_bench!( runner, benchmark_float_add_rational_prec_round_assign_evaluation_strategy ); } fn demo_float_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_float_add_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} + {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x + y) ); } } fn demo_float_add_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_float_add_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} + {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x + y) ); } } fn demo_float_add_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_float_add_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} + &{:#x} = {:#x}", ComparableFloat(x_old), ComparableFloatRef(&y), ComparableFloat(x + &y) ); } } fn demo_float_add_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_float_add_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} + {:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloat(y_old), ComparableFloat(&x + y) ); } } fn demo_float_add_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_float_add_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} + &{:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloatRef(&y), ComparableFloat(&x + &y) ); } } fn demo_float_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_float_add_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!( "x := {:#x}; x += {:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_add_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_float_add_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!( "x := {:#x}; x += &{:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_add_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_prec({}, {}) = {:?}", x_old, y_old, prec, x.add_prec(y, prec) ); } } fn demo_float_add_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_prec(y, prec); println!( "({:#x}).add_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_add_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_prec({}, {}) = {:?}", x_old, y_old, prec, x.add_prec(y, prec) ); } } fn demo_float_add_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_prec(y, prec); println!( "({:#x}).add_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_add_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_prec_val_ref(&{}, {}) = {:?}", x_old, y, prec, x.add_prec_val_ref(&y, prec) ); } } fn demo_float_add_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_prec_val_ref(&y, prec); println!( "({:#x}).add_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_add_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.add_prec_ref_val(y, prec) ); } } fn demo_float_add_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_prec_ref_val(y, prec); println!( "(&{:#x}).add_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_add_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).add_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.add_prec_ref_ref(&y, prec) ); } } fn demo_float_add_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_prec_ref_ref(&y, prec); println!( "(&{:#x}).add_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_add_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.add_prec_assign(y, prec); println!("x := {x_old}; x.add_prec_assign({y_old}, {prec}); x = {x}"); } } fn demo_float_add_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_prec_assign(y, prec); println!( "x := {:#x}; x.add_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, o, ComparableFloat(x) ); } } fn demo_float_add_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.add_prec_assign_ref(&y, prec); println!("x := {x_old}; x.add_prec_assign({y}, {prec}); x = {x}"); } } fn demo_float_add_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.add_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, o, ComparableFloat(x) ); } } fn demo_float_add_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_round({}, {}) = {:?}", x_old, y_old, rm, x.add_round(y, rm) ); } } fn demo_float_add_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_round(y, rm); println!( "({:#x}).add_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_add_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_29() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_round({}, {}) = {:?}", x_old, y_old, rm, x.add_round(y, rm) ); } } fn demo_float_add_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_29() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_round(y, rm); println!( "({:#x}).add_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_add_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.add_round_val_ref(&y, rm) ); } } fn demo_float_add_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_round_val_ref(&y, rm); println!( "({:#x}).add_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_add_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_round_ref_val({}, {}) = {:?}", x, y_old, rm, x.add_round_ref_val(y, rm) ); } } fn demo_float_add_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_round_ref_val(y, rm); println!( "(&{:#x}).add_round_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_add_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).add_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.add_round_ref_ref(&y, rm) ); } } fn demo_float_add_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_round_ref_ref(&y, rm); println!( "(&{:#x}).add_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_add_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.add_round_assign(y, rm); println!("x := {x_old}; x.add_round_assign({y_old}, {rm}); x = {x}"); } } fn demo_float_add_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_round_assign(y, rm); println!( "x := {:#x}; x.add_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), rm, o, ComparableFloat(x) ); } } fn demo_float_add_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.add_round_assign_ref(&y, rm); println!("x := {x_old}; x.add_round_assign({y}, {rm}); x = {x}"); } } fn demo_float_add_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_round_assign_ref(&y, rm); println!( "x := {:#x}; x.add_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), rm, o, ComparableFloat(x) ); } } fn demo_float_add_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.add_prec_round(y, prec, rm) ); } } fn demo_float_add_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_prec_round(y, prec, rm); println!( "({:#x}).add_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.add_prec_round(y, prec, rm) ); } } fn demo_float_add_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_prec_round(y, prec, rm); println!( "({:#x}).add_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_prec_round(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.add_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_add_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).add_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.add_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_add_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).add_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { println!( "({}).add_prec_round({}, {}, {}) = {:?}", x, y, prec, rm, x.add_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_add_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_prec_round_ref_ref(&y, prec, rm); println!( "({:#x}).add_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_prec_round_assign(y, prec, rm); println!("x := {x_old}; x.add_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_add_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.add_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_add_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_prec_round_assign_ref(&y, prec, rm); println!("x := {x_old}; x.add_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_add_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.add_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_add_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_float_add_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} + {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x + y) ); } } fn demo_float_add_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_float_add_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} + {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x + y) ); } } fn demo_float_add_rational_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_float_add_rational_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} + {} = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x + &y) ); } } fn demo_float_add_rational_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_float_add_rational_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} + {} = {:#x}", ComparableFloatRef(&x), y_old, ComparableFloat(&x + y) ); } } fn demo_float_add_rational_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_float_add_rational_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} + &{} = {:#x}", ComparableFloatRef(&x), y, ComparableFloat(&x + &y) ); } } fn demo_float_add_rational_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_float_add_rational_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!( "x := {:#x}; x += {}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_float_add_rational_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_float_add_rational_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!( "x := {:#x}; x += &{}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_rational_add_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_rational_add_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} + {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x + y) ); } } fn demo_rational_add_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_rational_add_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} + {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x + y) ); } } fn demo_rational_add_float_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_rational_add_float_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{} + &{:#x} = {:#x}", x_old, ComparableFloatRef(&y), ComparableFloat(x + &y) ); } } fn demo_rational_add_float_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_rational_add_float_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{} + {:#x} = {:#x}", x, ComparableFloat(y_old), ComparableFloat(&x + y) ); } } fn demo_rational_add_float_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_rational_add_float_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{} + &{:#x} = {:#x}", x, ComparableFloatRef(&y), ComparableFloat(&x + &y) ); } } fn demo_float_add_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.add_rational_prec(y, prec) ); } } fn demo_float_add_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_prec(y, prec); println!( "({:#x}).add_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.add_rational_prec(y, prec) ); } } fn demo_float_add_rational_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_prec(y, prec); println!( "({:#x}).add_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_rational_prec({}, &{}) = {:?}", x_old, y, prec, x.add_rational_prec_val_ref(&y, prec) ); } } fn demo_float_add_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_rational_prec_val_ref(&y, prec); println!( "({:#x}).add_rational_prec_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_rational_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.add_rational_prec_ref_val(y, prec) ); } } fn demo_float_add_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_rational_prec_ref_val(y, prec); println!( "(&{:#x}).add_rational_prec_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).add_rational_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.add_rational_prec_ref_ref(&y, prec) ); } } fn demo_float_add_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_rational_prec_ref_ref(&y, prec); println!( "(&{:#x}).add_rational_prec_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_prec_assign(y, prec); println!("x := {x_old}; x.add_rational_prec_assign({y_old}, {prec}) = {o:?}; x = {x}"); } } fn demo_float_add_rational_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_prec_assign(y, prec); println!( "x := {:#x}; x.add_rational_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, o, ComparableFloat(x) ); } } fn demo_float_add_rational_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_rational_prec_assign_ref(&y, prec); println!("x := {x_old}; x.add_rational_prec_assign_ref({y}, &{prec}) = {o:?}; x = {x}"); } } fn demo_float_add_rational_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_rational_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.add_rational_prec_assign(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, o, ComparableFloat(x) ); } } fn demo_float_add_rational_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.add_rational_round(y, rm) ); } } fn demo_float_add_rational_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_round(y, rm); println!( "({:#x}).add_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.add_rational_round(y, rm) ); } } fn demo_float_add_rational_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_round(y, rm); println!( "({:#x}).add_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_rational_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.add_rational_round_val_ref(&y, rm) ); } } fn demo_float_add_rational_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_rational_round_val_ref(&y, rm); println!( "({:#x}).add_rational_round_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_rational_round_ref_val(&{}, {}) = {:?}", x, y_old, rm, x.add_rational_round_ref_val(y, rm) ); } } fn demo_float_add_rational_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_rational_round_ref_val(y, rm); println!( "(&{:#x}).add_rational_round_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).add_rational_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.add_rational_round_ref_ref(&y, rm) ); } } fn demo_float_add_rational_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_rational_round_ref_ref(&y, rm); println!( "(&{:#x}).add_rational_round_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_round_assign(y, rm); println!("x := {x_old}; x.add_rational_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_add_rational_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_round_assign(y, rm); println!( "x := {:#x}; x.add_rational_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_add_rational_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_rational_round_assign_ref(&y, rm); println!("x := {x_old}; x.add_rational_round_assign_ref(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_add_rational_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_round_assign_ref(&y, rm); println!( "x := {:#x}; x.add_rational_round_assign_ref(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_add_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.add_rational_prec_round(y, prec, rm) ); } } fn demo_float_add_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_prec_round(y, prec, rm); println!( "({:#x}).add_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).add_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.add_rational_prec_round(y, prec, rm) ); } } fn demo_float_add_rational_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.add_rational_prec_round(y, prec, rm); println!( "({:#x}).add_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).add_rational_prec_round_val_ref(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.add_rational_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_add_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.add_rational_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).add_rational_prec_round_val_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).add_rational_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.add_rational_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_add_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.add_rational_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).add_rational_prec_round_ref_val({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).add_rational_prec_round_ref_ref(&{}, {}, {}) = {:?}", x, y, prec, rm, x.add_rational_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_add_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.add_rational_prec_round_ref_ref(&y, prec, rm); println!( "(&{:#x}).add_rational_prec_round_ref_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_add_rational_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_prec_round_assign(y, prec, rm); println!( "x := {x_old}; x.add_rational_prec_round_assign({y_old}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_add_rational_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.add_rational_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.add_rational_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, rm, o, ComparableFloat(x) ); } } fn demo_float_add_rational_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {x_old}; x.add_rational_prec_round_assign_ref(&{y}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_add_rational_prec_round_assign_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.add_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.add_rational_prec_round_assign_ref(&{}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float + Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float + Float", &mut |(x, y)| no_out!(x + y)), ("Float + &Float", &mut |(x, y)| no_out!(x + &y)), ("&Float + Float", &mut |(x, y)| no_out!(&x + y)), ("&Float + &Float", &mut |(x, y)| no_out!(&x + &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_add_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float + Float", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x + &y)), ("rug", &mut |((x, y), _)| no_out!(rug_add(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_add_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float + Float", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x + y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(add_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float += Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float += Float", &mut |(mut x, y)| x += y), ("Float += &Float", &mut |(mut x, y)| x += &y), ], ); } fn benchmark_float_add_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.add_prec(Float, u64)", &mut |(x, y, prec)| { no_out!(x.add_prec(y, prec)); }), ("Float.add_prec_val_ref(&Float, u64)", &mut |( x, y, prec, )| { no_out!(x.add_prec_val_ref(&y, prec)); }), ( "(&Float).add_prec_ref_val(Float, u64)", &mut |(x, y, prec)| no_out!(x.add_prec_ref_val(y, prec)), ), ( "(&Float).add_prec_ref_ref(&Float, u64)", &mut |(x, y, prec)| no_out!(x.add_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_add_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec(Float, u64)", BenchmarkType::Algorithms, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| no_out!(x.add_prec(y, prec))), ("naive", &mut |(x, y, prec)| { no_out!(add_prec_round_naive(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_add_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec(Float, u64)", BenchmarkType::LibraryComparison, float_float_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.add_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_add_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_add_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec_assign(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.add_prec_assign(Float, u64)", &mut |( mut x, y, prec, )| { no_out!(x.add_prec_assign(y, prec)); }), ( "Float.add_prec_assign_ref(&Float, u64)", &mut |(mut x, y, prec)| no_out!(x.add_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_add_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_round(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.add_round(Float, RoundingMode)", &mut |(x, y, rm)| { no_out!(x.add_round(y, rm)); }), ( "Float.add_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_round_val_ref(&y, rm)), ), ( "(&Float).add_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_round_ref_val(y, rm)), ), ( "(&Float).add_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_add_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_round(Float, RoundingMode)", BenchmarkType::LibraryComparison, float_float_rounding_mode_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.add_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_add_round(&x, &y, rm)); }), ], ); } fn benchmark_float_add_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_round(Float, RoundingMode)", BenchmarkType::Algorithms, float_float_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| no_out!(x.add_round(y, rm))), ("naive", &mut |(x, y, rm)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); add_prec_round_naive(x, y, max(xsb, ysb), rm); }), ], ); } fn benchmark_float_add_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_round_assign(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ( "Float.add_round_assign(Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.add_round_assign(y, rm)), ), ( "Float.add_round_assign_ref(&Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.add_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_add_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec_round(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_prec_round(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_prec_round(y, prec, rm)), ), ( "Float.add_prec_round_val_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).add_prec_round_ref_val(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).add_prec_round_ref_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_add_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec_round(Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.add_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_add_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_add_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec_round(Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_float_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.add_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(add_prec_round_naive(x, y, prec, rm)); }), ], ); } fn benchmark_float_add_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_prec_round_assign(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_prec_round_assign(Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.add_prec_round_assign(y, prec, rm)), ), ( "Float.add_prec_round_assign_ref(&Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.add_prec_round_assign_ref(&y, prec, rm)), ), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_add_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float + Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float + Rational", &mut |(x, y)| no_out!(x + y)), ("Float + &Rational", &mut |(x, y)| no_out!(x + &y)), ("&Float + Rational", &mut |(x, y)| no_out!(&x + y)), ("&Float + &Rational", &mut |(x, y)| no_out!(&x + &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_add_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float + Rational", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x + &y)), ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_add_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float + Rational", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x + y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(add_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_add_rational_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float += Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float += Rational", &mut |(mut x, y)| x += y), ("Float += &Rational", &mut |(mut x, y)| x += &y), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_add_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational + Float", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Rational + Float", &mut |(y, x)| no_out!(x + y)), ("Rational + &Float", &mut |(y, x)| no_out!(x + &y)), ("&Rational + Float", &mut |(y, x)| no_out!(&x + y)), ("&Rational + &Float", &mut |(y, x)| no_out!(&x + &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_add_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational + Float", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(&x + &y)), ("rug", &mut |((x, y), _)| no_out!(rug_add_rational(&x, &y))), ], ); } fn benchmark_float_add_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_rational_prec(Rational, u64)", &mut |(x, y, prec)| no_out!(x.add_rational_prec(y, prec)), ), ( "Float.add_rational_prec_val_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.add_rational_prec_val_ref(&y, prec)), ), ( "(&Float).add_rational_prec_ref_val(Rational, u64)", &mut |(x, y, prec)| no_out!(x.add_rational_prec_ref_val(y, prec)), ), ( "(&Float).add_rational_prec_ref_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.add_rational_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_add_rational_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec(Rational, u64)", BenchmarkType::LibraryComparison, float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.add_rational_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_add_rational_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_add_rational_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec(Rational, u64)", BenchmarkType::Algorithms, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| { no_out!(x.add_rational_prec(y, prec)); }), ("naive", &mut |(x, y, prec)| { no_out!(add_rational_prec_round_naive(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_add_rational_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec_assign(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_rational_prec_assign(Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.add_rational_prec_assign(y, prec)), ), ( "Float.add_rational_prec_assign_ref(&Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.add_rational_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_add_rational_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_round(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.add_rational_round(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_rational_round(y, rm)), ), ( "Float.add_rational_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_rational_round_val_ref(&y, rm)), ), ( "(&Float).add_rational_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_rational_round_ref_val(y, rm)), ), ( "(&Float).add_rational_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.add_rational_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_add_rational_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_round(Rational, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.add_rational_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_add_rational_round(&x, &y, rm)); }), ], ); } fn benchmark_float_add_rational_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_round(Rational, RoundingMode)", BenchmarkType::Algorithms, float_rational_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.add_rational_round(y, rm)); }), ("naive", &mut |(x, y, rm)| { let ysb = y.significant_bits(); add_rational_prec_round_naive(x, y, ysb, rm); }), ], ); } fn benchmark_float_add_rational_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_round_assign(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.add_rational_round_assign(Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.add_rational_round_assign(y, rm)), ), ( "Float.add_rational_round_assign_ref(&Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.add_rational_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_add_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_rational_prec_round(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_rational_prec_round(y, prec, rm)), ), ( "Float.add_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_rational_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).add_rational_prec_round_ref_val(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_rational_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).add_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.add_rational_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_add_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( "x", "y", "prec", ), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.add_rational_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_add_rational_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_add_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.add_rational_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(add_rational_prec_round_naive(x, y, prec, rm)); }), ], ); } fn benchmark_float_add_rational_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.add_rational_prec_round_assign(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.add_rational_prec_round_assign(Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.add_rational_prec_round_assign(y, prec, rm)), ), ( "Float.add_rational_prec_round_assign_ref(&Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| { no_out!(x.add_rational_prec_round_assign_ref(&y, prec, rm)); }, ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/agm.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Agm, AgmAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::pair_max_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::agm::{primitive_float_agm, primitive_float_agm_rational}; use malachite_float::basic::extended::ExtendedFloat; use malachite_float::basic::extended::agm_prec_round_normal_ref_ref_extended; use malachite_float::test_util::arithmetic::agm::{ rug_agm, rug_agm_prec, rug_agm_prec_round, rug_agm_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, pair_2_triple_float_float_primitive_int_max_complexity_bucketer, pair_float_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_float_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_33, float_float_rounding_mode_triple_gen_var_33_rm, float_float_rounding_mode_triple_gen_var_34, float_float_unsigned_rounding_mode_quadruple_gen_var_9, float_float_unsigned_rounding_mode_quadruple_gen_var_9_rm, float_float_unsigned_rounding_mode_quadruple_gen_var_10, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_float_unsigned_triple_gen_var_2, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, rational_rational_unsigned_rounding_mode_quadruple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::test_util::bench::bucketers::{ pair_rational_max_bit_bucketer, quadruple_1_2_3_rational_rational_primitive_int_max_bit_bucketer, triple_rational_rational_primitive_int_max_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_pair_gen, rational_rational_unsigned_triple_gen_var_2, }; use std::cmp::max; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_agm); register_demo!(runner, demo_float_agm_debug); register_demo!(runner, demo_float_agm_extreme); register_demo!(runner, demo_float_agm_extreme_debug); register_demo!(runner, demo_float_agm_val_ref); register_demo!(runner, demo_float_agm_val_ref_debug); register_demo!(runner, demo_float_agm_ref_val); register_demo!(runner, demo_float_agm_ref_val_debug); register_demo!(runner, demo_float_agm_ref_ref); register_demo!(runner, demo_float_agm_ref_ref_debug); register_demo!(runner, demo_float_agm_assign); register_demo!(runner, demo_float_agm_assign_debug); register_demo!(runner, demo_float_agm_assign_ref); register_demo!(runner, demo_float_agm_assign_ref_debug); register_demo!(runner, demo_float_agm_prec); register_demo!(runner, demo_float_agm_prec_debug); register_demo!(runner, demo_float_agm_prec_extreme); register_demo!(runner, demo_float_agm_prec_extreme_debug); register_demo!(runner, demo_float_agm_prec_val_ref); register_demo!(runner, demo_float_agm_prec_val_ref_debug); register_demo!(runner, demo_float_agm_prec_ref_val); register_demo!(runner, demo_float_agm_prec_ref_val_debug); register_demo!(runner, demo_float_agm_prec_ref_ref); register_demo!(runner, demo_float_agm_prec_ref_ref_debug); register_demo!(runner, demo_float_agm_prec_assign); register_demo!(runner, demo_float_agm_prec_assign_debug); register_demo!(runner, demo_float_agm_prec_assign_ref); register_demo!(runner, demo_float_agm_prec_assign_ref_debug); register_demo!(runner, demo_float_agm_round); register_demo!(runner, demo_float_agm_round_debug); register_demo!(runner, demo_float_agm_round_extreme); register_demo!(runner, demo_float_agm_round_extreme_debug); register_demo!(runner, demo_float_agm_round_val_ref); register_demo!(runner, demo_float_agm_round_val_ref_debug); register_demo!(runner, demo_float_agm_round_ref_val); register_demo!(runner, demo_float_agm_round_ref_val_debug); register_demo!(runner, demo_float_agm_round_ref_ref); register_demo!(runner, demo_float_agm_round_ref_ref_debug); register_demo!(runner, demo_float_agm_round_assign); register_demo!(runner, demo_float_agm_round_assign_debug); register_demo!(runner, demo_float_agm_round_assign_ref); register_demo!(runner, demo_float_agm_round_assign_ref_debug); register_demo!(runner, demo_float_agm_prec_round); register_demo!(runner, demo_float_agm_prec_round_debug); register_demo!(runner, demo_float_agm_prec_round_extreme); register_demo!(runner, demo_float_agm_prec_round_extreme_debug); register_demo!(runner, demo_float_agm_prec_round_val_ref); register_demo!(runner, demo_float_agm_prec_round_val_ref_debug); register_demo!(runner, demo_float_agm_prec_round_ref_val); register_demo!(runner, demo_float_agm_prec_round_ref_val_debug); register_demo!(runner, demo_float_agm_prec_round_ref_ref); register_demo!(runner, demo_float_agm_prec_round_ref_ref_debug); register_demo!(runner, demo_float_agm_prec_round_assign); register_demo!(runner, demo_float_agm_prec_round_assign_debug); register_demo!(runner, demo_float_agm_prec_round_assign_ref); register_demo!(runner, demo_float_agm_prec_round_assign_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_agm); register_demo!(runner, demo_agm_rational_prec); register_demo!(runner, demo_agm_rational_prec_debug); register_demo!(runner, demo_agm_rational_prec_val_ref); register_demo!(runner, demo_agm_rational_prec_val_ref_debug); register_demo!(runner, demo_agm_rational_prec_ref_val); register_demo!(runner, demo_agm_rational_prec_ref_val_debug); register_demo!(runner, demo_agm_rational_prec_ref_ref); register_demo!(runner, demo_agm_rational_prec_ref_ref_debug); register_demo!(runner, demo_agm_rational_prec_round); register_demo!(runner, demo_agm_rational_prec_round_debug); register_demo!(runner, demo_agm_rational_prec_round_val_ref); register_demo!(runner, demo_agm_rational_prec_round_val_ref_debug); register_demo!(runner, demo_agm_rational_prec_round_ref_val); register_demo!(runner, demo_agm_rational_prec_round_ref_val_debug); register_demo!(runner, demo_agm_rational_prec_round_ref_ref); register_demo!(runner, demo_agm_rational_prec_round_ref_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_agm_rational); register_bench!(runner, benchmark_float_agm_evaluation_strategy); register_bench!(runner, benchmark_float_agm_algorithms); register_bench!(runner, benchmark_float_agm_library_comparison); register_bench!(runner, benchmark_float_agm_assign_evaluation_strategy); register_bench!(runner, benchmark_float_agm_prec_evaluation_strategy); register_bench!(runner, benchmark_float_agm_prec_algorithms); register_bench!(runner, benchmark_float_agm_prec_library_comparison); register_bench!(runner, benchmark_float_agm_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_agm_round_evaluation_strategy); register_bench!(runner, benchmark_float_agm_round_algorithms); register_bench!(runner, benchmark_float_agm_round_library_comparison); register_bench!(runner, benchmark_float_agm_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_agm_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_agm_prec_round_algorithms); register_bench!(runner, benchmark_float_agm_prec_round_library_comparison); register_bench!( runner, benchmark_float_agm_prec_round_assign_evaluation_strategy ); register_primitive_float_benches!(runner, benchmark_primitive_float_agm); register_bench!(runner, benchmark_agm_rational_prec_evaluation_strategy); register_bench!( runner, benchmark_agm_rational_prec_round_evaluation_strategy ); register_primitive_float_benches!(runner, benchmark_primitive_float_agm_rational); } fn demo_float_agm(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("agm({}, {}) = {}", x_old, y_old, x.agm(y)); } } fn demo_float_agm_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "agm({:#x}, {:#x}) = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x.agm(y)) ); } } fn demo_float_agm_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("agm({}, {}) = {}", x_old, y_old, x.agm(y)); } } fn demo_float_agm_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "agm({:#x}, {:#x}) = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x.agm(y)) ); } } fn demo_float_agm_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("agm({}, &{}) = {}", x_old, y, x.agm(&y)); } } fn demo_float_agm_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "agm({:#x}, &{:#x}) = {:#x}", ComparableFloat(x_old), ComparableFloatRef(&y), ComparableFloat(x.agm(&y)) ); } } fn demo_float_agm_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("agm(&{}, {}) = {}", x, y_old, (&x).agm(y)); } } fn demo_float_agm_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "agm(&{:#x}, {:#x}) = {:#x}", ComparableFloatRef(&x), ComparableFloat(y_old), ComparableFloat((&x).agm(y)) ); } } fn demo_float_agm_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!("agm(&{}, &{}) = {}", x, y, (&x).agm(&y)); } } fn demo_float_agm_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!( "agm(&{:#x}, &{:#x}) = {:#x}", ComparableFloatRef(&x), ComparableFloatRef(&y), ComparableFloat((&x).agm(&y)) ); } } fn demo_float_agm_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.agm_assign(y.clone()); println!("x := {x_old}; x.agm_assign({y}); x = {x}"); } } fn demo_float_agm_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.agm_assign(y.clone()); println!( "x := {:#x}; x.agm_assign({:#x}); x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_agm_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.agm_assign(&y); println!("x := {x_old}; x.agm_assign(&{y}); x = {x}"); } } fn demo_float_agm_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.agm_assign(&y); println!( "x := {:#x}; x.agm_assign(&{:#x}); x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_agm_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_prec({}, {}) = {:?}", x_old, y_old, prec, x.agm_prec(y, prec) ); } } fn demo_float_agm_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_prec(y, prec); println!( "({:#x}).agm_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_prec({}, {}) = {:?}", x_old, y_old, prec, x.agm_prec(y, prec) ); } } fn demo_float_agm_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_prec(y, prec); println!( "({:#x}).agm_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).agm_prec_val_ref(&{}, {}) = {:?}", x_old, y, prec, x.agm_prec_val_ref(&y, prec) ); } } fn demo_float_agm_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (agm, o) = x.agm_prec_val_ref(&y, prec); println!( "({:#x}).agm_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).agm_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.agm_prec_ref_val(y, prec) ); } } fn demo_float_agm_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (agm, o) = x.agm_prec_ref_val(y, prec); println!( "(&{:#x}).agm_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).agm_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.agm_prec_ref_ref(&y, prec) ); } } fn demo_float_agm_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (agm, o) = x.agm_prec_ref_ref(&y, prec); println!( "(&{:#x}).agm_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.agm_prec_assign(y, prec); println!("x := {x_old}; x.agm_prec_assign({y_old}, {prec}); x = {x}"); } } fn demo_float_agm_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.agm_prec_assign(y, prec); println!( "x := {:#x}; x.agm_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, o, ComparableFloat(x) ); } } fn demo_float_agm_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.agm_prec_assign_ref(&y, prec); println!("x := {x_old}; x.agm_prec_assign({y}, {prec}); x = {x}"); } } fn demo_float_agm_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.agm_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.agm_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, o, ComparableFloat(x) ); } } fn demo_float_agm_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_round({}, {}) = {:?}", x_old, y_old, rm, x.agm_round(y, rm) ); } } fn demo_float_agm_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_round(y, rm); println!( "({:#x}).agm_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(agm), o ); } } fn demo_float_agm_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_round({}, {}) = {:?}", x_old, y_old, rm, x.agm_round(y, rm) ); } } fn demo_float_agm_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_round(y, rm); println!( "({:#x}).agm_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(agm), o ); } } fn demo_float_agm_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).agm_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.agm_round_val_ref(&y, rm) ); } } fn demo_float_agm_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let (agm, o) = x.agm_round_val_ref(&y, rm); println!( "({:#x}).agm_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), rm, ComparableFloat(agm), o ); } } fn demo_float_agm_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).agm_round_ref_val({}, {}) = {:?}", x, y_old, rm, x.agm_round_ref_val(y, rm) ); } } fn demo_float_agm_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let y_old = y.clone(); let (agm, o) = x.agm_round_ref_val(y, rm); println!( "(&{:#x}).agm_round_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), rm, ComparableFloat(agm), o ); } } fn demo_float_agm_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { println!( "(&{}).agm_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.agm_round_ref_ref(&y, rm) ); } } fn demo_float_agm_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let (agm, o) = x.agm_round_ref_ref(&y, rm); println!( "(&{:#x}).agm_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), rm, ComparableFloat(agm), o ); } } fn demo_float_agm_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.agm_round_assign(y, rm); println!("x := {x_old}; x.agm_round_assign({y_old}, {rm}); x = {x}"); } } fn demo_float_agm_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.agm_round_assign(y, rm); println!( "x := {:#x}; x.agm_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), rm, o, ComparableFloat(x) ); } } fn demo_float_agm_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); x.agm_round_assign_ref(&y, rm); println!("x := {x_old}; x.agm_round_assign({y}, {rm}); x = {x}"); } } fn demo_float_agm_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_33() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.agm_round_assign_ref(&y, rm); println!( "x := {:#x}; x.agm_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), rm, o, ComparableFloat(x) ); } } fn demo_float_agm_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.agm_prec_round(y, prec, rm) ); } } fn demo_float_agm_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_prec_round(y, prec, rm); println!( "({:#x}).agm_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).agm_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.agm_prec_round(y, prec, rm) ); } } fn demo_float_agm_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = x.agm_prec_round(y, prec, rm); println!( "({:#x}).agm_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).agm_prec_round(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.agm_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_agm_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let (agm, o) = x.agm_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).agm_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, rm, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).agm_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.agm_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_agm_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let y_old = y.clone(); let (agm, o) = x.agm_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).agm_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, rm, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { println!( "({}).agm_prec_round({}, {}, {}) = {:?}", x, y, prec, rm, x.agm_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_agm_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let (agm, o) = x.agm_prec_round_ref_ref(&y, prec, rm); println!( "({:#x}).agm_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, rm, ComparableFloat(agm), o ); } } fn demo_float_agm_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.agm_prec_round_assign(y, prec, rm); println!("x := {x_old}; x.agm_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_agm_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.agm_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.agm_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_agm_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.agm_prec_round_assign_ref(&y, prec, rm); println!("x := {x_old}; x.agm_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_agm_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.agm_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.agm_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_agm(gm: GenMode, config: &GenConfig, limit: usize) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, y) in primitive_float_pair_gen::().get(gm, config).take(limit) { println!( "primitive_float_agm({}, {}) = {}", NiceFloat(x), NiceFloat(y), NiceFloat(primitive_float_agm(x, y)) ); } } fn demo_agm_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "agm_rational_prec({}, {}, {}) = {:?}", x_old, y_old, prec, Float::agm_rational_prec(x, y, prec) ); } } fn demo_agm_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = Float::agm_rational_prec(x, y, prec); println!( "agm_rational_prec({}, {}, {}) = ({:#x}, {:?})", x_old, y_old, prec, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "agm_rational_prec_val_ref({}, {}, {}) = {:?}", x_old, y, prec, Float::agm_rational_prec_val_ref(x, &y, prec) ); } } fn demo_agm_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (agm, o) = Float::agm_rational_prec_val_ref(x, &y, prec); println!( "agm_rational_prec_val_ref({}, {}, {}) = ({:#x}, {:?})", x_old, y, prec, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "agm_rational_prec_ref_val({}, {}, {}) = {:?}", x, y_old, prec, Float::agm_rational_prec_ref_val(&x, y, prec) ); } } fn demo_agm_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); let (agm, o) = Float::agm_rational_prec_ref_val(&x, y, prec); println!( "agm_rational_prec_ref_val({}, {}, {}) = ({:#x}, {:?})", x, y_old, prec, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "agm_rational_prec_ref_ref({}, {}, {}) = {:?}", x, y, prec, Float::agm_rational_prec_ref_ref(&x, &y, prec) ); } } fn demo_agm_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in rational_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = Float::agm_rational_prec(x, y, prec); println!( "agm_rational_prec({}, {}, {}) = ({:#x}, {:?})", x_old, y_old, prec, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "agm_rational_prec_round({}, {}, {}, {:?}) = {:?}", x_old, y_old, prec, rm, Float::agm_rational_prec_round(x, y, prec, rm) ); } } fn demo_agm_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (agm, o) = Float::agm_rational_prec_round(x, y, prec, rm); println!( "agm_rational_prec_round({}, {}, {}, {:?}) = ({:#x}, {:?})", x_old, y_old, prec, rm, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "agm_rational_prec_round_val_ref({}, {}, {}, {:?}) = {:?}", x_old, y, prec, rm, Float::agm_rational_prec_round_val_ref(x, &y, prec, rm) ); } } fn demo_agm_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (agm, o) = Float::agm_rational_prec_round_val_ref(x, &y, prec, rm); println!( "agm_rational_prec_round_val_ref({}, {}, {}, {:?}) = ({:#x}, {:?})", x_old, y, prec, rm, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "agm_rational_prec_round_ref_val({}, {}, {}, {:?}) = {:?}", x, y_old, prec, rm, Float::agm_rational_prec_round_ref_val(&x, y, prec, rm) ); } } fn demo_agm_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (agm, o) = Float::agm_rational_prec_round_ref_val(&x, y, prec, rm); println!( "agm_rational_prec_round_ref_val({}, {}, {}, {:?}) = ({:#x}, {:?})", x, y_old, prec, rm, ComparableFloat(agm), o ); } } fn demo_agm_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { println!( "agm_rational_prec_round_ref_ref({}, {}, {}, {:?}) = {:?}", x, y, prec, rm, Float::agm_rational_prec_round_ref_ref(&x, &y, prec, rm) ); } } fn demo_agm_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() .get(gm, config) .take(limit) { let (agm, o) = Float::agm_rational_prec_round_ref_ref(&x, &y, prec, rm); println!( "agm_rational_prec_round_ref_ref({}, {}, {}, {:?}) = ({:#x}, {:?})", x, y, prec, rm, ComparableFloat(agm), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_agm_rational( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!( "primitive_float_agm_rational({}, {}) = {}", x, y, NiceFloat(primitive_float_agm_rational::(&x, &y)) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_agm_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm(Float)", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.agm(Float)", &mut |(x, y)| no_out!(x.agm(y))), ("Float.agm(&Float)", &mut |(x, y)| no_out!(x.agm(&y))), ("(&Float).agm(Float)", &mut |(x, y)| no_out!((&x).agm(y))), ("(&Float).agm(&Float)", &mut |(x, y)| no_out!((&x).agm(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_agm_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.agm(Float)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.agm(y))), ("extended", &mut |(x, y)| { let prec = max(x.significant_bits(), y.significant_bits()); agm_prec_round_normal_ref_ref_extended( &ExtendedFloat::from(x.clone()), &ExtendedFloat::from(y.clone()), prec, Nearest, ); }), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_agm_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm(Float)", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!((&x).agm(&y))), ("rug", &mut |((x, y), _)| no_out!(rug_agm(&x, &y))), ], ); } fn benchmark_float_agm_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_assign(Float)", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.agm_assign(Float)", &mut |(mut x, y)| x.agm_assign(y)), ("Float.agm_assign(&Float)", &mut |(mut x, y)| { x.agm_assign(&y); }), ], ); } fn benchmark_float_agm_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.agm_prec(Float, u64)", &mut |(x, y, prec)| { no_out!(x.agm_prec(y, prec)); }), ("Float.agm_prec_val_ref(&Float, u64)", &mut |( x, y, prec, )| { no_out!(x.agm_prec_val_ref(&y, prec)); }), ( "(&Float).agm_prec_ref_val(Float, u64)", &mut |(x, y, prec)| no_out!(x.agm_prec_ref_val(y, prec)), ), ( "(&Float).agm_prec_ref_ref(&Float, u64)", &mut |(x, y, prec)| no_out!(x.agm_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_agm_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec(Float, u64)", BenchmarkType::Algorithms, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| { no_out!(x.agm_prec(y, prec)); }), ("extended", &mut |(x, y, prec)| { agm_prec_round_normal_ref_ref_extended( &ExtendedFloat::from(x.clone()), &ExtendedFloat::from(y.clone()), prec, Nearest, ); }), ], ); } fn benchmark_float_agm_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec(Float, u64)", BenchmarkType::LibraryComparison, float_float_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.agm_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_agm_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_agm_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec_assign(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.agm_prec_assign(Float, u64)", &mut |( mut x, y, prec, )| { no_out!(x.agm_prec_assign(y, prec)); }), ( "Float.agm_prec_assign_ref(&Float, u64)", &mut |(mut x, y, prec)| no_out!(x.agm_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_agm_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_round(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_33().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.agm_round(Float, RoundingMode)", &mut |(x, y, rm)| { no_out!(x.agm_round(y, rm)); }), ( "Float.agm_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.agm_round_val_ref(&y, rm)), ), ( "(&Float).agm_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.agm_round_ref_val(y, rm)), ), ( "(&Float).agm_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.agm_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_agm_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_round(Float, RoundingMode)", BenchmarkType::Algorithms, float_float_rounding_mode_triple_gen_var_33().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.agm_round(y, rm)); }), ("extended", &mut |(x, y, rm)| { let prec = max(x.significant_bits(), y.significant_bits()); agm_prec_round_normal_ref_ref_extended( &ExtendedFloat::from(x.clone()), &ExtendedFloat::from(y.clone()), prec, rm, ); }), ], ); } fn benchmark_float_agm_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_round(Float, RoundingMode)", BenchmarkType::LibraryComparison, float_float_rounding_mode_triple_gen_var_33_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.agm_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_agm_round(&x, &y, rm)); }), ], ); } fn benchmark_float_agm_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_round_assign(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_33().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ( "Float.agm_round_assign(Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.agm_round_assign(y, rm)), ), ( "Float.agm_round_assign_ref(&Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.agm_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_agm_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec_round(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.agm_prec_round(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.agm_prec_round(y, prec, rm)), ), ( "Float.agm_prec_round_val_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.agm_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).agm_prec_round_ref_val(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.agm_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).agm_prec_round_ref_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.agm_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_agm_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec_round(Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_float_unsigned_rounding_mode_quadruple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.agm_prec_round(y, prec, rm)); }), ("extended", &mut |(x, y, prec, rm)| { agm_prec_round_normal_ref_ref_extended( &ExtendedFloat::from(x.clone()), &ExtendedFloat::from(y.clone()), prec, rm, ); }), ], ); } fn benchmark_float_agm_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec_round(Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_float_unsigned_rounding_mode_quadruple_gen_var_9_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.agm_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_agm_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_agm_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.agm_prec_round_assign(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.agm_prec_round_assign(Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.agm_prec_round_assign(y, prec, rm)), ), ( "Float.agm_prec_round_assign_ref(&Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.agm_prec_round_assign_ref(&y, prec, rm)), ), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_agm( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!("primitive_float_agm({})", T::NAME), BenchmarkType::EvaluationStrategy, primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_max_primitive_float_bucketer("x", "y"), &mut [("malachite", &mut |(x, y)| { no_out!(primitive_float_agm(x, y)); })], ); } fn benchmark_agm_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::agm_rational_prec(Rational, Rational, u64)", BenchmarkType::EvaluationStrategy, rational_rational_unsigned_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_rational_rational_primitive_int_max_bit_bucketer("x", "y", "prec"), &mut [ ( "Float::agm_rational_prec(Rational, Rational, u64)", &mut |(x, y, prec)| { no_out!(Float::agm_rational_prec(x, y, prec)); }, ), ( "Float::agm_rational_prec_val_ref(Rational, &Rational, u64)", &mut |(x, y, prec)| { no_out!(Float::agm_rational_prec_val_ref(x, &y, prec)); }, ), ( "Float::agm_rational_prec_ref_val(&Rational, Rational, u64)", &mut |(x, y, prec)| no_out!(Float::agm_rational_prec_ref_val(&x, y, prec)), ), ( "Float::agm_rational_prec_ref_ref(&Rational, &Rational, u64)", &mut |(x, y, prec)| no_out!(Float::agm_rational_prec_ref_ref(&x, &y, prec)), ), ], ); } fn benchmark_agm_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::agm_rational_prec_round(Rational, Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_rational_unsigned_rounding_mode_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_rational_rational_primitive_int_max_bit_bucketer("x", "y", "prec"), &mut [ ( "Float::agm_rational_prec_round(Rational, Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| { no_out!(Float::agm_rational_prec_round(x, y, prec, rm)); }, ), ( "Float::agm_rational_prec_round_val_ref(Rational, &Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| { no_out!(Float::agm_rational_prec_round_val_ref(x, &y, prec, rm)); }, ), ( "Float::agm_rational_prec_round_ref_val(&Rational, Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| { no_out!(Float::agm_rational_prec_round_ref_val(&x, y, prec, rm)); }, ), ( "Float::agm_rational_prec_round_ref_ref(&Rational, &Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| { no_out!(Float::agm_rational_prec_round_ref_ref(&x, &y, prec, rm)); }, ), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_agm_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!( "primitive_float_agm_rational_prec::<{}>(Rational, Rational)", T::NAME ), BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(primitive_float_agm_rational::(&x, &y)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/div.rs ================================================ // Copyright © 2026 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 core::cmp::max; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::div::{ div_rational_prec_round_direct, div_rational_prec_round_direct_ref_ref, div_rational_prec_round_direct_ref_val, div_rational_prec_round_direct_val_ref, div_rational_prec_round_naive, div_rational_prec_round_naive_ref_ref, div_rational_prec_round_naive_ref_val, div_rational_prec_round_naive_val_ref, rational_div_float_prec_round_direct, rational_div_float_prec_round_direct_ref_ref, rational_div_float_prec_round_direct_ref_val, rational_div_float_prec_round_direct_val_ref, rational_div_float_prec_round_naive, rational_div_float_prec_round_naive_ref_ref, rational_div_float_prec_round_naive_ref_val, rational_div_float_prec_round_naive_val_ref, }; use malachite_float::test_util::arithmetic::div::{ div_prec_round_naive, rug_div, rug_div_prec, rug_div_prec_round, rug_div_rational, rug_div_rational_prec, rug_div_rational_prec_round, rug_div_rational_round, rug_div_round, rug_rational_div_float_prec, rug_rational_div_float_prec_round, rug_rational_div_float_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_2_triple_float_float_primitive_int_max_complexity_bucketer, pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, triple_float_float_primitive_int_max_complexity_bucketer, triple_float_rational_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_23, float_float_rounding_mode_triple_gen_var_23_rm, float_float_rounding_mode_triple_gen_var_32, float_float_unsigned_rounding_mode_quadruple_gen_var_4, float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm, float_float_unsigned_rounding_mode_quadruple_gen_var_8, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_float_unsigned_triple_gen_var_2, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_rounding_mode_triple_gen_var_5, float_rational_rounding_mode_triple_gen_var_6, float_rational_rounding_mode_triple_gen_var_6_rm, float_rational_rounding_mode_triple_gen_var_10, float_rational_rounding_mode_triple_gen_var_11, float_rational_unsigned_rounding_mode_quadruple_gen_var_4, float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_5, float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_9, float_rational_unsigned_rounding_mode_quadruple_gen_var_10, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, float_rational_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_div); register_demo!(runner, demo_float_div_debug); register_demo!(runner, demo_float_div_extreme); register_demo!(runner, demo_float_div_extreme_debug); register_demo!(runner, demo_float_div_val_ref); register_demo!(runner, demo_float_div_val_ref_debug); register_demo!(runner, demo_float_div_ref_val); register_demo!(runner, demo_float_div_ref_val_debug); register_demo!(runner, demo_float_div_ref_ref); register_demo!(runner, demo_float_div_ref_ref_debug); register_demo!(runner, demo_float_div_assign); register_demo!(runner, demo_float_div_assign_debug); register_demo!(runner, demo_float_div_assign_ref); register_demo!(runner, demo_float_div_assign_ref_debug); register_demo!(runner, demo_float_div_prec); register_demo!(runner, demo_float_div_prec_debug); register_demo!(runner, demo_float_div_prec_extreme); register_demo!(runner, demo_float_div_prec_extreme_debug); register_demo!(runner, demo_float_div_prec_val_ref); register_demo!(runner, demo_float_div_prec_val_ref_debug); register_demo!(runner, demo_float_div_prec_ref_val); register_demo!(runner, demo_float_div_prec_ref_val_debug); register_demo!(runner, demo_float_div_prec_ref_ref); register_demo!(runner, demo_float_div_prec_ref_ref_debug); register_demo!(runner, demo_float_div_prec_assign); register_demo!(runner, demo_float_div_prec_assign_debug); register_demo!(runner, demo_float_div_prec_assign_ref); register_demo!(runner, demo_float_div_prec_assign_ref_debug); register_demo!(runner, demo_float_div_round); register_demo!(runner, demo_float_div_round_debug); register_demo!(runner, demo_float_div_round_extreme); register_demo!(runner, demo_float_div_round_extreme_debug); register_demo!(runner, demo_float_div_round_val_ref); register_demo!(runner, demo_float_div_round_val_ref_debug); register_demo!(runner, demo_float_div_round_ref_val); register_demo!(runner, demo_float_div_round_ref_val_debug); register_demo!(runner, demo_float_div_round_ref_ref); register_demo!(runner, demo_float_div_round_ref_ref_debug); register_demo!(runner, demo_float_div_round_assign); register_demo!(runner, demo_float_div_round_assign_debug); register_demo!(runner, demo_float_div_round_assign_ref); register_demo!(runner, demo_float_div_round_assign_ref_debug); register_demo!(runner, demo_float_div_prec_round); register_demo!(runner, demo_float_div_prec_round_debug); register_demo!(runner, demo_float_div_prec_round_extreme); register_demo!(runner, demo_float_div_prec_round_extreme_debug); register_demo!(runner, demo_float_div_prec_round_val_ref); register_demo!(runner, demo_float_div_prec_round_val_ref_debug); register_demo!(runner, demo_float_div_prec_round_ref_val); register_demo!(runner, demo_float_div_prec_round_ref_val_debug); register_demo!(runner, demo_float_div_prec_round_ref_ref); register_demo!(runner, demo_float_div_prec_round_ref_ref_debug); register_demo!(runner, demo_float_div_prec_round_assign); register_demo!(runner, demo_float_div_prec_round_assign_debug); register_demo!(runner, demo_float_div_prec_round_assign_ref); register_demo!(runner, demo_float_div_prec_round_assign_ref_debug); register_demo!(runner, demo_float_div_rational); register_demo!(runner, demo_float_div_rational_debug); register_demo!(runner, demo_float_div_rational_extreme); register_demo!(runner, demo_float_div_rational_extreme_debug); register_demo!(runner, demo_float_div_rational_val_ref); register_demo!(runner, demo_float_div_rational_val_ref_debug); register_demo!(runner, demo_float_div_rational_ref_val); register_demo!(runner, demo_float_div_rational_ref_val_debug); register_demo!(runner, demo_float_div_rational_ref_ref); register_demo!(runner, demo_float_div_rational_ref_ref_debug); register_demo!(runner, demo_float_div_rational_assign); register_demo!(runner, demo_float_div_rational_assign_debug); register_demo!(runner, demo_float_div_rational_assign_ref); register_demo!(runner, demo_float_div_rational_assign_ref_debug); register_demo!(runner, demo_rational_div_float); register_demo!(runner, demo_rational_div_float_debug); register_demo!(runner, demo_rational_div_float_extreme); register_demo!(runner, demo_rational_div_float_extreme_debug); register_demo!(runner, demo_rational_div_float_val_ref); register_demo!(runner, demo_rational_div_float_val_ref_debug); register_demo!(runner, demo_rational_div_float_ref_val); register_demo!(runner, demo_rational_div_float_ref_val_debug); register_demo!(runner, demo_rational_div_float_ref_ref); register_demo!(runner, demo_rational_div_float_ref_ref_debug); register_demo!(runner, demo_float_div_rational_prec); register_demo!(runner, demo_float_div_rational_prec_debug); register_demo!(runner, demo_float_div_rational_prec_extreme); register_demo!(runner, demo_float_div_rational_prec_extreme_debug); register_demo!(runner, demo_float_div_rational_prec_val_ref); register_demo!(runner, demo_float_div_rational_prec_val_ref_debug); register_demo!(runner, demo_float_div_rational_prec_ref_val); register_demo!(runner, demo_float_div_rational_prec_ref_val_debug); register_demo!(runner, demo_float_div_rational_prec_ref_ref); register_demo!(runner, demo_float_div_rational_prec_ref_ref_debug); register_demo!(runner, demo_float_div_rational_prec_assign); register_demo!(runner, demo_float_div_rational_prec_assign_debug); register_demo!(runner, demo_float_div_rational_prec_assign_ref); register_demo!(runner, demo_float_div_rational_prec_assign_ref_debug); register_demo!(runner, demo_rational_div_float_prec); register_demo!(runner, demo_rational_div_float_prec_debug); register_demo!(runner, demo_rational_div_float_prec_extreme); register_demo!(runner, demo_rational_div_float_prec_extreme_debug); register_demo!(runner, demo_rational_div_float_prec_val_ref); register_demo!(runner, demo_rational_div_float_prec_val_ref_debug); register_demo!(runner, demo_rational_div_float_prec_ref_val); register_demo!(runner, demo_rational_div_float_prec_ref_val_debug); register_demo!(runner, demo_rational_div_float_prec_ref_ref); register_demo!(runner, demo_rational_div_float_prec_ref_ref_debug); register_demo!(runner, demo_float_div_rational_round); register_demo!(runner, demo_float_div_rational_round_debug); register_demo!(runner, demo_float_div_rational_round_extreme); register_demo!(runner, demo_float_div_rational_round_extreme_debug); register_demo!(runner, demo_float_div_rational_round_val_ref); register_demo!(runner, demo_float_div_rational_round_val_ref_debug); register_demo!(runner, demo_float_div_rational_round_ref_val); register_demo!(runner, demo_float_div_rational_round_ref_val_debug); register_demo!(runner, demo_float_div_rational_round_ref_ref); register_demo!(runner, demo_float_div_rational_round_ref_ref_debug); register_demo!(runner, demo_float_div_rational_round_assign); register_demo!(runner, demo_float_div_rational_round_assign_debug); register_demo!(runner, demo_float_div_rational_round_assign_ref); register_demo!(runner, demo_float_div_rational_round_assign_ref_debug); register_demo!(runner, demo_rational_div_float_round); register_demo!(runner, demo_rational_div_float_round_debug); register_demo!(runner, demo_rational_div_float_round_extreme); register_demo!(runner, demo_rational_div_float_round_extreme_debug); register_demo!(runner, demo_rational_div_float_round_val_ref); register_demo!(runner, demo_rational_div_float_round_val_ref_debug); register_demo!(runner, demo_rational_div_float_round_ref_val); register_demo!(runner, demo_rational_div_float_round_ref_val_debug); register_demo!(runner, demo_rational_div_float_round_ref_ref); register_demo!(runner, demo_rational_div_float_round_ref_ref_debug); register_demo!(runner, demo_float_div_rational_prec_round); register_demo!(runner, demo_float_div_rational_prec_round_debug); register_demo!(runner, demo_float_div_rational_prec_round_extreme); register_demo!(runner, demo_float_div_rational_prec_round_extreme_debug); register_demo!(runner, demo_float_div_rational_prec_round_val_ref); register_demo!(runner, demo_float_div_rational_prec_round_val_ref_debug); register_demo!(runner, demo_float_div_rational_prec_round_ref_val); register_demo!(runner, demo_float_div_rational_prec_round_ref_val_debug); register_demo!(runner, demo_float_div_rational_prec_round_ref_ref); register_demo!(runner, demo_float_div_rational_prec_round_ref_ref_debug); register_demo!(runner, demo_float_div_rational_prec_round_assign); register_demo!(runner, demo_float_div_rational_prec_round_assign_debug); register_demo!(runner, demo_float_div_rational_prec_round_assign_ref); register_demo!(runner, demo_float_div_rational_prec_round_assign_ref_debug); register_demo!(runner, demo_rational_div_float_prec_round); register_demo!(runner, demo_rational_div_float_prec_round_debug); register_demo!(runner, demo_rational_div_float_prec_round_extreme); register_demo!(runner, demo_rational_div_float_prec_round_extreme_debug); register_demo!(runner, demo_rational_div_float_prec_round_val_ref); register_demo!(runner, demo_rational_div_float_prec_round_val_ref_debug); register_demo!(runner, demo_rational_div_float_prec_round_ref_val); register_demo!(runner, demo_rational_div_float_prec_round_ref_val_debug); register_demo!(runner, demo_rational_div_float_prec_round_ref_ref); register_demo!(runner, demo_rational_div_float_prec_round_ref_ref_debug); register_bench!(runner, benchmark_float_div_evaluation_strategy); register_bench!(runner, benchmark_float_div_library_comparison); register_bench!(runner, benchmark_float_div_algorithms); register_bench!(runner, benchmark_float_div_assign_evaluation_strategy); register_bench!(runner, benchmark_float_div_prec_evaluation_strategy); register_bench!(runner, benchmark_float_div_prec_library_comparison); register_bench!(runner, benchmark_float_div_prec_algorithms); register_bench!(runner, benchmark_float_div_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_div_round_evaluation_strategy); register_bench!(runner, benchmark_float_div_round_library_comparison); register_bench!(runner, benchmark_float_div_round_algorithms); register_bench!(runner, benchmark_float_div_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_div_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_div_prec_round_library_comparison); register_bench!(runner, benchmark_float_div_prec_round_algorithms); register_bench!( runner, benchmark_float_div_prec_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_float_div_rational_evaluation_strategy); register_bench!(runner, benchmark_float_div_rational_library_comparison); register_bench!(runner, benchmark_float_div_rational_algorithms); register_bench!( runner, benchmark_float_div_rational_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_div_rational_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_div_rational_prec_library_comparison); register_bench!(runner, benchmark_float_div_rational_prec_algorithms); register_bench!( runner, benchmark_float_div_rational_prec_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_div_rational_round_evaluation_strategy ); register_bench!( runner, benchmark_float_div_rational_round_library_comparison ); register_bench!(runner, benchmark_float_div_rational_round_algorithms); register_bench!( runner, benchmark_float_div_rational_round_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_div_rational_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_div_rational_prec_round_library_comparison ); register_bench!(runner, benchmark_float_div_rational_prec_round_algorithms); register_bench!( runner, benchmark_float_div_rational_prec_round_val_ref_algorithms ); register_bench!( runner, benchmark_float_div_rational_prec_round_ref_val_algorithms ); register_bench!( runner, benchmark_float_div_rational_prec_round_ref_ref_algorithms ); register_bench!( runner, benchmark_float_div_rational_prec_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_rational_div_float_evaluation_strategy); register_bench!(runner, benchmark_rational_div_float_library_comparison); register_bench!(runner, benchmark_rational_div_float_algorithms); register_bench!( runner, benchmark_rational_div_float_prec_evaluation_strategy ); register_bench!(runner, benchmark_rational_div_float_prec_library_comparison); register_bench!(runner, benchmark_rational_div_float_prec_algorithms); register_bench!( runner, benchmark_rational_div_float_round_evaluation_strategy ); register_bench!( runner, benchmark_rational_div_float_round_library_comparison ); register_bench!(runner, benchmark_rational_div_float_round_algorithms); register_bench!( runner, benchmark_rational_div_float_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_rational_div_float_prec_round_library_comparison ); register_bench!(runner, benchmark_rational_div_float_prec_round_algorithms); register_bench!( runner, benchmark_rational_div_float_prec_round_val_ref_algorithms ); register_bench!( runner, benchmark_rational_div_float_prec_round_ref_val_algorithms ); register_bench!( runner, benchmark_rational_div_float_prec_round_ref_ref_algorithms ); } fn demo_float_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_float_div_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} / {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x / y) ); } } fn demo_float_div_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_float_div_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} / {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x / y) ); } } fn demo_float_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_float_div_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} / &{:#x} = {:#x}", ComparableFloat(x_old), ComparableFloatRef(&y), ComparableFloat(x / &y) ); } } fn demo_float_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_float_div_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} / {:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloat(y_old), ComparableFloat(&x / y) ); } } fn demo_float_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_float_div_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} / &{:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloatRef(&y), ComparableFloat(&x / &y) ); } } fn demo_float_div_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= y.clone(); println!("x := {x_old}; x /= {y}; x = {x}"); } } fn demo_float_div_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= y.clone(); println!( "x := {:#x}; x /= {:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_div_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!("x := {x_old}; x /= &{y}; x = {x}"); } } fn demo_float_div_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!( "x := {:#x}; x /= &{:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_div_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_prec({}, {}) = {:?}", x_old, y_old, prec, x.div_prec(y, prec) ); } } fn demo_float_div_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_prec(y, prec); println!( "({:#x}).div_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_div_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_prec({}, {}) = {:?}", x_old, y_old, prec, x.div_prec(y, prec) ); } } fn demo_float_div_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_prec(y, prec); println!( "({:#x}).div_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_div_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_prec_val_ref(&{}, {}) = {:?}", x_old, y, prec, x.div_prec_val_ref(&y, prec) ); } } fn demo_float_div_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_prec_val_ref(&y, prec); println!( "({:#x}).div_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_div_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.div_prec_ref_val(y, prec) ); } } fn demo_float_div_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_prec_ref_val(y, prec); println!( "(&{:#x}).div_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_div_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).div_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.div_prec_ref_ref(&y, prec) ); } } fn demo_float_div_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.div_prec_ref_ref(&y, prec); println!( "(&{:#x}).div_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_div_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.div_prec_assign(y, prec); println!("x := {x_old}; x.div_prec_assign({y_old}, {prec}); x = {x}"); } } fn demo_float_div_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_prec_assign(y, prec); println!( "x := {:#x}; x.div_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, o, ComparableFloat(x) ); } } fn demo_float_div_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.div_prec_assign_ref(&y, prec); println!("x := {x_old}; x.div_prec_assign({y}, {prec}); x = {x}"); } } fn demo_float_div_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.div_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, o, ComparableFloat(x) ); } } fn demo_float_div_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_round({}, {}) = {:?}", x_old, y_old, rm, x.div_round(y, rm) ); } } fn demo_float_div_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_round(y, rm); println!( "({:#x}).div_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_div_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_32() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_round({}, {}) = {:?}", x_old, y_old, rm, x.div_round(y, rm) ); } } fn demo_float_div_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_32() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_round(y, rm); println!( "({:#x}).div_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_div_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.div_round_val_ref(&y, rm) ); } } fn demo_float_div_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_round_val_ref(&y, rm); println!( "({:#x}).div_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_div_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_round_ref_val({}, {}) = {:?}", x, y_old, rm, x.div_round_ref_val(y, rm) ); } } fn demo_float_div_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_round_ref_val(y, rm); println!( "(&{:#x}).div_round_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_div_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { println!( "(&{}).div_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.div_round_ref_ref(&y, rm) ); } } fn demo_float_div_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let (sum, o) = x.div_round_ref_ref(&y, rm); println!( "(&{:#x}).div_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_div_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.div_round_assign(y, rm); println!("x := {x_old}; x.div_round_assign({y_old}, {rm}); x = {x}"); } } fn demo_float_div_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_round_assign(y, rm); println!( "x := {:#x}; x.div_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), rm, o, ComparableFloat(x) ); } } fn demo_float_div_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); x.div_round_assign_ref(&y, rm); println!("x := {x_old}; x.div_round_assign({y}, {rm}); x = {x}"); } } fn demo_float_div_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_round_assign_ref(&y, rm); println!( "x := {:#x}; x.div_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), rm, o, ComparableFloat(x) ); } } fn demo_float_div_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.div_prec_round(y, prec, rm) ); } } fn demo_float_div_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_prec_round(y, prec, rm); println!( "({:#x}).div_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.div_prec_round(y, prec, rm) ); } } fn demo_float_div_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_prec_round(y, prec, rm); println!( "({:#x}).div_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_prec_round(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.div_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_div_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).div_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.div_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_div_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).div_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { println!( "({}).div_prec_round({}, {}, {}) = {:?}", x, y, prec, rm, x.div_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_div_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let (sum, o) = x.div_prec_round_ref_ref(&y, prec, rm); println!( "({:#x}).div_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_prec_round_assign(y, prec, rm); println!("x := {x_old}; x.div_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_div_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.div_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_div_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_prec_round_assign_ref(&y, prec, rm); println!("x := {x_old}; x.div_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_div_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.div_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_div_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_float_div_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} / {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x / y) ); } } fn demo_float_div_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_float_div_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} / {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x / y) ); } } fn demo_float_div_rational_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_float_div_rational_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} / {} = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x / &y) ); } } fn demo_float_div_rational_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_float_div_rational_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} / {} = {:#x}", ComparableFloatRef(&x), y_old, ComparableFloat(&x / y) ); } } fn demo_float_div_rational_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_float_div_rational_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} / &{} = {:#x}", ComparableFloatRef(&x), y, ComparableFloat(&x / &y) ); } } fn demo_float_div_rational_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= y.clone(); println!("x := {x_old}; x /= {y}; x = {x}"); } } fn demo_float_div_rational_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= y.clone(); println!( "x := {:#x}; x /= {}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_float_div_rational_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!("x := {x_old}; x /= &{y}; x = {x}"); } } fn demo_float_div_rational_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!( "x := {:#x}; x /= &{}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_rational_div_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_rational_div_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} / {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x / y) ); } } fn demo_rational_div_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_rational_div_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} / {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x / y) ); } } fn demo_rational_div_float_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_rational_div_float_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{} / &{:#x} = {:#x}", x_old, ComparableFloatRef(&y), ComparableFloat(x / &y) ); } } fn demo_rational_div_float_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_rational_div_float_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{} / {:#x} = {:#x}", x, ComparableFloat(y_old), ComparableFloat(&x / y) ); } } fn demo_rational_div_float_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_rational_div_float_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{} / &{:#x} = {:#x}", x, ComparableFloatRef(&y), ComparableFloat(&x / &y) ); } } fn demo_float_div_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.div_rational_prec(y, prec) ); } } fn demo_float_div_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_prec(y, prec); println!( "({:#x}).div_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.div_rational_prec(y, prec) ); } } fn demo_float_div_rational_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_prec(y, prec); println!( "({:#x}).div_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_rational_prec({}, &{}) = {:?}", x_old, y, prec, x.div_rational_prec_val_ref(&y, prec) ); } } fn demo_float_div_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_rational_prec_val_ref(&y, prec); println!( "({:#x}).div_rational_prec_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_rational_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.div_rational_prec_ref_val(y, prec) ); } } fn demo_float_div_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_rational_prec_ref_val(y, prec); println!( "(&{:#x}).div_rational_prec_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).div_rational_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.div_rational_prec_ref_ref(&y, prec) ); } } fn demo_float_div_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.div_rational_prec_ref_ref(&y, prec); println!( "(&{:#x}).div_rational_prec_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_prec_assign(y, prec); println!("x := {x_old}; x.div_rational_prec_assign({y_old}, {prec}) = {o:?}; x = {x}"); } } fn demo_float_div_rational_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_prec_assign(y, prec); println!( "x := {:#x}; x.div_rational_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, o, ComparableFloat(x) ); } } fn demo_float_div_rational_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_rational_prec_assign_ref(&y, prec); println!("x := {x_old}; x.div_rational_prec_assign_ref({y}, &{prec}) = {o:?}; x = {x}"); } } fn demo_float_div_rational_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_rational_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.div_rational_prec_assign(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, o, ComparableFloat(x) ); } } fn demo_rational_div_float_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_prec({}, {}, {}) = {:?}", x_old, y_old, prec, Float::rational_div_float_prec(x, y, prec) ); } } fn demo_rational_div_float_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec(x, y, prec); println!( "rational_div_float_prec({}, {:#x}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_prec({}, {}, {}) = {:?}", y_old, x_old, prec, Float::rational_div_float_prec(y, x, prec) ); } } fn demo_rational_div_float_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec(y, x, prec); println!( "rational_div_float_prec({}, {:#x}, {}) = ({:#x}, {:?})", y_old, ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "rational_div_float_prec({}, &{}, {}) = {:?}", x_old, y, prec, Float::rational_div_float_prec_val_ref(x, &y, prec) ); } } fn demo_rational_div_float_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = Float::rational_div_float_prec_val_ref(x, &y, prec); println!( "rational_div_float_prec_val_ref({}, &{:#x}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "rational_div_float_prec_ref_val(&{}, {}, {}) = {:?}", x, y_old, prec, Float::rational_div_float_prec_ref_val(&x, y, prec) ); } } fn demo_rational_div_float_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec_ref_val(&x, y, prec); println!( "rational_div_float_prec_ref_val(&{}, {:#x}, {}) = ({:#x}, {:?})", x, ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "rational_div_float_prec_ref_ref(&{}, &{}, {}) = {:?}", x, y, prec, Float::rational_div_float_prec_ref_ref(&x, &y, prec) ); } } fn demo_rational_div_float_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); println!( "rational_div_float_prec_ref_ref(&{}, &{:#x}, {}) = ({:#x}, {:?})", x, ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.div_rational_round(y, rm) ); } } fn demo_float_div_rational_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_round(y, rm); println!( "({:#x}).div_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.div_rational_round(y, rm) ); } } fn demo_float_div_rational_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_round(y, rm); println!( "({:#x}).div_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_rational_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.div_rational_round_val_ref(&y, rm) ); } } fn demo_float_div_rational_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_rational_round_val_ref(&y, rm); println!( "({:#x}).div_rational_round_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_rational_round_ref_val(&{}, {}) = {:?}", x, y_old, rm, x.div_rational_round_ref_val(y, rm) ); } } fn demo_float_div_rational_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_rational_round_ref_val(y, rm); println!( "(&{:#x}).div_rational_round_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { println!( "(&{}).div_rational_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.div_rational_round_ref_ref(&y, rm) ); } } fn demo_float_div_rational_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let (sum, o) = x.div_rational_round_ref_ref(&y, rm); println!( "(&{:#x}).div_rational_round_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_round_assign(y, rm); println!("x := {x_old}; x.div_rational_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_div_rational_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_round_assign(y, rm); println!( "x := {:#x}; x.div_rational_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_div_rational_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_rational_round_assign_ref(&y, rm); println!("x := {x_old}; x.div_rational_round_assign_ref(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_div_rational_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_round_assign_ref(&y, rm); println!( "x := {:#x}; x.div_rational_round_assign_ref(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_rational_div_float_round(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_round({}, {}, {}) = {:?}", x_old, y_old, rm, Float::rational_div_float_round(x, y, rm) ); } } fn demo_rational_div_float_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_round(x, y, rm); println!( "rational_div_float_round({}, {:#x}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_11() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_round({}, {}, {}) = {:?}", y_old, x_old, rm, Float::rational_div_float_round(y, x, rm) ); } } fn demo_rational_div_float_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_11() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_round(y, x, rm); println!( "rational_div_float_round({}, {:#x}, {}) = ({:#x}, {:?})", y_old, ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "rational_div_float_round_val_ref({}, &{}, {}) = {:?}", x_old, y, rm, Float::rational_div_float_round_val_ref(x, &y, rm) ); } } fn demo_rational_div_float_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = Float::rational_div_float_round_val_ref(x, &y, rm); println!( "rational_div_float_round_val_ref({}, &{:#x}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "rational_div_float_round_ref_val(&{}, &{}, {}) = {:?}", x, y_old, rm, Float::rational_div_float_round_ref_val(&x, y, rm) ); } } fn demo_rational_div_float_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = Float::rational_div_float_round_ref_val(&x, y, rm); println!( "rational_div_float_round_ref_val(&{}, {:#x}, {}) = ({:#x}, {:?})", x, ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "rational_div_float_round_ref_ref(&{}, &{}, {}) = {:?}", x, y, rm, Float::rational_div_float_round_ref_ref(&x, &y, rm) ); } } fn demo_rational_div_float_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, rm) in float_rational_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let (sum, o) = Float::rational_div_float_round_ref_ref(&x, &y, rm); println!( "rational_div_float_round_ref_ref(&{}, &{:#x}, {}) = ({:#x}, {:?})", x, ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.div_rational_prec_round(y, prec, rm) ); } } fn demo_float_div_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_prec_round(y, prec, rm); println!( "({:#x}).div_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).div_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.div_rational_prec_round(y, prec, rm) ); } } fn demo_float_div_rational_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.div_rational_prec_round(y, prec, rm); println!( "({:#x}).div_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).div_rational_prec_round_val_ref(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.div_rational_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_div_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.div_rational_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).div_rational_prec_round_val_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_rational_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.div_rational_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_div_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.div_rational_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).div_rational_prec_round_ref_val({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { println!( "(&{}).div_rational_prec_round_ref_ref(&{}, {}, {}) = {:?}", x, y, prec, rm, x.div_rational_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_div_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let (sum, o) = x.div_rational_prec_round_ref_ref(&y, prec, rm); println!( "(&{:#x}).div_rational_prec_round_ref_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_div_rational_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_prec_round_assign(y, prec, rm); println!( "x := {x_old}; x.div_rational_prec_round_assign({y_old}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_div_rational_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_rational_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.div_rational_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, rm, o, ComparableFloat(x) ); } } fn demo_float_div_rational_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {x_old}; x.div_rational_prec_round_assign_ref(&{y}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_div_rational_prec_round_assign_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.div_rational_prec_round_assign_ref(&{}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, rm, o, ComparableFloat(x) ); } } fn demo_rational_div_float_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_prec_round({}, {}, {}, {}) = {:?}", x_old, y_old, prec, rm, Float::rational_div_float_prec_round(x, y, prec, rm) ); } } fn demo_rational_div_float_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec_round(x, y, prec, rm); println!( "rational_div_float_rational_prec_round({}, {:#x}, {}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "rational_div_float_prec_round({}, {}, {}, {}) = {:?}", y_old, x_old, prec, rm, Float::rational_div_float_prec_round(y, x, prec, rm) ); } } fn demo_rational_div_float_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_10() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec_round(y, x, prec, rm); println!( "rational_div_float_prec_round({}, ({:#x}), {}, {}) = ({:#x}, {:?})", y_old, ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "Float::rational_div_float_prec_round_val_ref(&{}, {}, {}, {}) = {:?}", x_old, y, prec, rm, Float::rational_div_float_prec_round_val_ref(x, &y, prec, rm) ); } } fn demo_rational_div_float_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = Float::rational_div_float_prec_round_val_ref(x, &y, prec, rm); println!( "rational_div_float_prec_round_val_ref({}, &{:#x}, {}, {}) = ({:#x}, {:?})", x_old, ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "rational_div_float_prec_round_ref_val(&{}, {}, {}, {}) = {:?}", x, y_old, prec, rm, Float::rational_div_float_prec_round_ref_val(&x, y, prec, rm) ); } } fn demo_rational_div_float_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = Float::rational_div_float_prec_round_ref_val(&x, y, prec, rm); println!( "rational_div_float_prec_round_ref_val(&{}, {:#x}, {}, {}) = ({:#x}, {:?})", x, ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_rational_div_float_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { println!( "rational_div_float_prec_round_ref_ref(&{}, &{}, {}, {}) = {:?}", x, y, prec, rm, Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm) ); } } fn demo_rational_div_float_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_5() .get(gm, config) .take(limit) { let (sum, o) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); println!( "rational_div_float_prec_round_ref_ref(&{}, &{:#x}, {}, {}) = ({:#x}, {:?})", x, ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float / Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float / Float", &mut |(x, y)| no_out!(x / y)), ("Float / &Float", &mut |(x, y)| no_out!(x / &y)), ("&Float / Float", &mut |(x, y)| no_out!(&x / y)), ("&Float / &Float", &mut |(x, y)| no_out!(&x / &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float / Float", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x / &y)), ("rug", &mut |((x, y), _)| no_out!(rug_div(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_div_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float / Float", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x / y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(div_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_div_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float /= Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float /= Float", &mut |(mut x, y)| x /= y), ("Float /= &Float", &mut |(mut x, y)| x /= &y), ], ); } fn benchmark_float_div_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.div_prec(Float, u64)", &mut |(x, y, prec)| { no_out!(x.div_prec(y, prec)); }), ("Float.div_prec_val_ref(&Float, u64)", &mut |( x, y, prec, )| { no_out!(x.div_prec_val_ref(&y, prec)); }), ( "(&Float).div_prec_ref_val(Float, u64)", &mut |(x, y, prec)| no_out!(x.div_prec_ref_val(y, prec)), ), ( "(&Float).div_prec_ref_ref(&Float, u64)", &mut |(x, y, prec)| no_out!(x.div_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_div_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec(Float, u64)", BenchmarkType::LibraryComparison, float_float_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.div_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_div_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_div_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec(Float, u64)", BenchmarkType::Algorithms, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| no_out!(x.div_prec(y, prec))), ("naive", &mut |(x, y, prec)| { no_out!(div_prec_round_naive(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_div_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec_assign(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.div_prec_assign(Float, u64)", &mut |( mut x, y, prec, )| { no_out!(x.div_prec_assign(y, prec)); }), ( "Float.div_prec_assign_ref(&Float, u64)", &mut |(mut x, y, prec)| no_out!(x.div_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_div_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_round(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_23().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.div_round(Float, RoundingMode)", &mut |(x, y, rm)| { no_out!(x.div_round(y, rm)); }), ( "Float.div_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round_val_ref(&y, rm)), ), ( "(&Float).div_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round_ref_val(y, rm)), ), ( "(&Float).div_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_div_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_round(Float, RoundingMode)", BenchmarkType::LibraryComparison, float_float_rounding_mode_triple_gen_var_23_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.div_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_div_round(&x, &y, rm)); }), ], ); } fn benchmark_float_div_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_round(Float, RoundingMode)", BenchmarkType::Algorithms, float_float_rounding_mode_triple_gen_var_23().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| no_out!(x.div_round(y, rm))), ("naive", &mut |(x, y, rm)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); div_prec_round_naive(x, y, max(xsb, ysb), rm); }), ], ); } fn benchmark_float_div_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_round_assign(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_23().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ( "Float.div_round_assign(Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign(y, rm)), ), ( "Float.div_round_assign_ref(&Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_div_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec_round(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_prec_round(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_prec_round(y, prec, rm)), ), ( "Float.div_prec_round_val_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).div_prec_round_ref_val(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).div_prec_round_ref_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_div_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec_round(Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.div_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_div_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_div_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec_round(Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.div_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(div_prec_round_naive(x, y, prec, rm)); }), ], ); } fn benchmark_float_div_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_prec_round_assign(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_prec_round_assign(Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.div_prec_round_assign(y, prec, rm)), ), ( "Float.div_prec_round_assign_ref(&Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.div_prec_round_assign_ref(&y, prec, rm)), ), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_div_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float / Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float / Rational", &mut |(x, y)| no_out!(x / y)), ("Float / &Rational", &mut |(x, y)| no_out!(x / &y)), ("&Float / Rational", &mut |(x, y)| no_out!(&x / y)), ("&Float / &Rational", &mut |(x, y)| no_out!(&x / &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_div_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float / Rational", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x / &y)), ("rug", &mut |((x, y), _)| no_out!(rug_div_rational(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_div_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float / Rational", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x / y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(div_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ("direct", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(div_rational_prec_round_direct(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_div_rational_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float /= Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float /= Rational", &mut |(mut x, y)| x /= y), ("Float /= &Rational", &mut |(mut x, y)| x /= &y), ], ); } fn benchmark_float_div_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_rational_prec(Rational, u64)", &mut |(x, y, prec)| no_out!(x.div_rational_prec(y, prec)), ), ( "Float.div_rational_prec_val_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.div_rational_prec_val_ref(&y, prec)), ), ( "(&Float).div_rational_prec_ref_val(Rational, u64)", &mut |(x, y, prec)| no_out!(x.div_rational_prec_ref_val(y, prec)), ), ( "(&Float).div_rational_prec_ref_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.div_rational_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_div_rational_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec(Rational, u64)", BenchmarkType::LibraryComparison, float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.div_rational_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_div_rational_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_div_rational_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec(Rational, u64)", BenchmarkType::Algorithms, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| { no_out!(x.div_rational_prec(y, prec)); }), ("naive", &mut |(x, y, prec)| { no_out!(div_rational_prec_round_naive(x, y, prec, Nearest)); }), ("direct", &mut |(x, y, prec)| { no_out!(div_rational_prec_round_direct(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_div_rational_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_assign(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_rational_prec_assign(Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.div_rational_prec_assign(y, prec)), ), ( "Float.div_rational_prec_assign_ref(&Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.div_rational_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_div_rational_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_round(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.div_rational_round(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_rational_round(y, rm)), ), ( "Float.div_rational_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_rational_round_val_ref(&y, rm)), ), ( "(&Float).div_rational_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_rational_round_ref_val(y, rm)), ), ( "(&Float).div_rational_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_rational_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_div_rational_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_round(Rational, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.div_rational_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_div_rational_round(&x, &y, rm)); }), ], ); } fn benchmark_float_div_rational_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_round(Rational, RoundingMode)", BenchmarkType::Algorithms, float_rational_rounding_mode_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.div_rational_round(y, rm)); }), ("naive", &mut |(x, y, rm)| { let ysb = y.significant_bits(); div_rational_prec_round_naive(x, y, ysb, rm); }), ("direct", &mut |(x, y, rm)| { let ysb = y.significant_bits(); div_rational_prec_round_direct(x, y, ysb, rm); }), ], ); } fn benchmark_float_div_rational_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_round_assign(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.div_rational_round_assign(Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_rational_round_assign(y, rm)), ), ( "Float.div_rational_round_assign_ref(&Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_rational_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_div_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_rational_prec_round(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round(y, prec, rm)), ), ( "Float.div_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).div_rational_prec_round_ref_val(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).div_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_div_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( "x", "y", "prec", ), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_div_rational_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_div_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.div_rational_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_naive(x, y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_direct(x, y, prec, rm)); }), ], ); } fn benchmark_float_div_rational_prec_round_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.div_rational_prec_round_val_ref(&y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_naive_val_ref(x, &y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_direct_val_ref(x, &y, prec, rm)); }), ], ); } fn benchmark_float_div_rational_prec_round_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round_ref_val(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.div_rational_prec_round_ref_val(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_naive_ref_val(&x, y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_direct_ref_val(&x, y, prec, rm)); }), ], ); } fn benchmark_float_div_rational_prec_round_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.div_rational_prec_round_ref_ref(&y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_div_rational_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.div_rational_prec_round_assign(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.div_rational_prec_round_assign(Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.div_rational_prec_round_assign(y, prec, rm)), ), ( "Float.div_rational_prec_round_assign_ref(&Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| { no_out!(x.div_rational_prec_round_assign_ref(&y, prec, rm)); }, ), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_div_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Float", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Rational / Float", &mut |(y, x)| no_out!(x / y)), ("Rational / &Float", &mut |(y, x)| no_out!(x / &y)), ("&Rational / Float", &mut |(y, x)| no_out!(&x / y)), ("&Rational / &Float", &mut |(y, x)| no_out!(&x / &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_div_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Float", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(&x / &y)), ("rug", &mut |((x, y), _)| no_out!(rug_div_rational(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_div_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Float", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(y, x)| no_out!(x / y)), ("naive", &mut |(y, x)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(rational_div_float_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ("direct", &mut |(y, x)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(rational_div_float_prec_round_direct(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_rational_div_float_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec(Rational, Float, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float::rational_div_float_prec(Rational, Float, u64)", &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec(x, y, prec)), ), ( "Float::rational_div_float_prec_val_ref(Rational, &Float, u64)", &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_val_ref(x, &y, prec)), ), ( "Float::rational_div_float_prec_ref_val(&Rational, Float, u64)", &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_ref_val(&x, y, prec)), ), ( "Float::rational_div_float_prec_ref_ref(&Rational, &Float, u64)", &mut |(y, x, prec)| no_out!(Float::rational_div_float_prec_ref_ref(&x, &y, prec)), ), ], ); } fn benchmark_rational_div_float_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.rational_div_float_prec(Rational, Float, u64)", BenchmarkType::LibraryComparison, float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (y, x, prec))| { no_out!(Float::rational_div_float_prec_ref_ref(&x, &y, prec)); }), ("rug", &mut |((y, x, prec), _)| { no_out!(rug_rational_div_float_prec(&x, &y, prec)); }), ], ); } fn benchmark_rational_div_float_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec(Rational, Float, u64)", BenchmarkType::Algorithms, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(y, x, prec)| { no_out!(Float::rational_div_float_prec(x, y, prec)); }), ("naive", &mut |(y, x, prec)| { no_out!(rational_div_float_prec_round_naive(x, y, prec, Nearest)); }), ("direct", &mut |(y, x, prec)| { no_out!(rational_div_float_prec_round_direct(x, y, prec, Nearest)); }), ], ); } fn benchmark_rational_div_float_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_round(Rational, Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float::rational_div_float_round(Rational, Float, RoundingMode)", &mut |(y, x, rm)| no_out!(Float::rational_div_float_round(x, y, rm)), ), ( "Float::rational_div_float_round_val_ref(Rational, &Float, RoundingMode)", &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_val_ref(x, &y, rm)), ), ( "Float::rational_div_float_round_ref_val(&Rational, Float, RoundingMode)", &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_ref_val(&x, y, rm)), ), ( "Float::rational_div_float_round_ref_ref(&Rational, &Float, RoundingMode)", &mut |(y, x, rm)| no_out!(Float::rational_div_float_round_ref_ref(&x, &y, rm)), ), ], ); } fn benchmark_rational_div_float_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.rational_div_float_round(Rational, Float, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_rounding_mode_triple_gen_var_6_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (y, x, rm))| { no_out!(Float::rational_div_float_round_ref_ref(&x, &y, rm)); }), ("rug", &mut |((y, x, rm), _)| { no_out!(rug_rational_div_float_round(&x, &y, rm)); }), ], ); } fn benchmark_rational_div_float_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_round(Float, Float, RoundingMode)", BenchmarkType::Algorithms, float_rational_rounding_mode_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(y, x, rm)| { no_out!(Float::rational_div_float_round(x, y, rm)); }), ("naive", &mut |(y, x, rm)| { let ysb = y.significant_bits(); rational_div_float_prec_round_naive(x, y, ysb, rm); }), ("direct", &mut |(y, x, rm)| { let ysb = y.significant_bits(); rational_div_float_prec_round_direct(x, y, ysb, rm); }), ], ); } fn benchmark_rational_div_float_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float::rational_div_float_prec_round\ (Rational, Float, u64, RoundingMode)", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round(x, y, prec, rm)); }, ), ( "Float::rational_div_float_prec_round_val_ref\ (Rational, &Float, u64, RoundingMode)", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_val_ref( x, &y, prec, rm )); }, ), ( "Float::rational_div_float_prec_round_ref_val\ (&Rational, Float, u64, RoundingMode)", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_ref_val( &x, y, prec, rm )); }, ), ( "Float::rational_div_float_prec_round_ref_ref\ (&Rational, &Float, u64, RoundingMode)", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_ref_ref( &x, &y, prec, rm )); }, ), ], ); } fn benchmark_rational_div_float_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( "x", "y", "prec", ), &mut [ ("Malachite", &mut |(_, (y, x, prec, rm))| { no_out!(Float::rational_div_float_prec_round_ref_ref( &x, &y, prec, rm )); }), ("rug", &mut |((y, x, prec, rm), _)| { no_out!(rug_rational_div_float_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_rational_div_float_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec_round(Rational, Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round(x, y, prec, rm)); }), ("naive", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_naive(x, y, prec, rm)); }), ("direct", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_direct(x, y, prec, rm)); }), ], ); } fn benchmark_rational_div_float_prec_round_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec_round_val_ref(Rational, &Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_val_ref( x, &y, prec, rm )); }), ("naive", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_naive_val_ref(x, &y, prec, rm)); }), ("direct", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_direct_val_ref( x, &y, prec, rm )); }), ], ); } fn benchmark_rational_div_float_prec_round_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec_round_ref_val(&Rational, Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_ref_val( &x, y, prec, rm )); }), ("naive", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_naive_ref_val(&x, y, prec, rm)); }), ("direct", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_direct_ref_val( &x, y, prec, rm )); }), ], ); } fn benchmark_rational_div_float_prec_round_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::rational_div_float_prec_round_ref_ref(&Rational, &Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(y, x, prec, rm)| { no_out!(Float::rational_div_float_prec_round_ref_ref( &x, &y, prec, rm )); }), ("naive", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_naive_ref_ref( &x, &y, prec, rm )); }), ("direct", &mut |(y, x, prec, rm)| { no_out!(rational_div_float_prec_round_direct_ref_ref( &x, &y, prec, rm )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_is_power_of_2); register_demo!(runner, demo_float_is_power_of_2_debug); register_demo!(runner, demo_float_is_power_of_2_extreme); register_demo!(runner, demo_float_is_power_of_2_extreme_debug); register_bench!(runner, benchmark_float_is_power_of_2); } fn demo_float_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { if n.is_power_of_2() { println!("{n} is a power of 2"); } else { println!("{n} is not a power of 2"); } } } fn demo_float_is_power_of_2_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { if n.is_power_of_2() { println!("{:#x} is a power of 2", ComparableFloat(n)); } else { println!("{:#x} is not a power of 2", ComparableFloat(n)); } } } fn demo_float_is_power_of_2_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { if n.is_power_of_2() { println!("{n} is a power of 2"); } else { println!("{n} is not a power of 2"); } } } fn demo_float_is_power_of_2_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { if n.is_power_of_2() { println!("{:#x} is a power of 2", ComparableFloat(n)); } else { println!("{:#x} is not a power of 2", ComparableFloat(n)); } } } fn benchmark_float_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.is_power_of_2()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.is_power_of_2()))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/ln.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ln, LnAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; use malachite_float::Float; use malachite_float::arithmetic::ln::{primitive_float_ln, primitive_float_ln_rational}; use malachite_float::test_util::arithmetic::ln::{ rug_ln, rug_ln_prec, rug_ln_prec_round, rug_ln_round, }; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, pair_2_pair_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_rounding_mode_pair_gen_var_34, float_rounding_mode_pair_gen_var_34_rm, float_rounding_mode_pair_gen_var_35, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_19, float_unsigned_rounding_mode_triple_gen_var_19_rm, float_unsigned_rounding_mode_triple_gen_var_20, rational_unsigned_rounding_mode_triple_gen_var_6, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use malachite_q::test_util::bench::bucketers::{ pair_rational_bit_u64_max_bucketer, rational_bit_bucketer, triple_1_2_rational_bit_u64_max_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_ln); register_demo!(runner, demo_float_ln_debug); register_demo!(runner, demo_float_ln_extreme); register_demo!(runner, demo_float_ln_extreme_debug); register_demo!(runner, demo_float_ln_ref); register_demo!(runner, demo_float_ln_ref_debug); register_demo!(runner, demo_float_ln_assign); register_demo!(runner, demo_float_ln_assign_debug); register_demo!(runner, demo_float_ln_prec); register_demo!(runner, demo_float_ln_prec_debug); register_demo!(runner, demo_float_ln_prec_extreme); register_demo!(runner, demo_float_ln_prec_extreme_debug); register_demo!(runner, demo_float_ln_prec_ref); register_demo!(runner, demo_float_ln_prec_ref_debug); register_demo!(runner, demo_float_ln_prec_assign); register_demo!(runner, demo_float_ln_prec_assign_debug); register_demo!(runner, demo_float_ln_round); register_demo!(runner, demo_float_ln_round_debug); register_demo!(runner, demo_float_ln_round_extreme); register_demo!(runner, demo_float_ln_round_extreme_debug); register_demo!(runner, demo_float_ln_round_ref); register_demo!(runner, demo_float_ln_round_ref_debug); register_demo!(runner, demo_float_ln_round_assign); register_demo!(runner, demo_float_ln_round_assign_debug); register_demo!(runner, demo_float_ln_prec_round); register_demo!(runner, demo_float_ln_prec_round_debug); register_demo!(runner, demo_float_ln_prec_round_extreme); register_demo!(runner, demo_float_ln_prec_round_extreme_debug); register_demo!(runner, demo_float_ln_prec_round_ref); register_demo!(runner, demo_float_ln_prec_round_ref_debug); register_demo!(runner, demo_float_ln_prec_round_assign); register_demo!(runner, demo_float_ln_prec_round_assign_debug); register_primitive_float_demos!(runner, demo_primitive_float_ln); register_demo!(runner, demo_float_ln_rational_prec); register_demo!(runner, demo_float_ln_rational_prec_debug); register_demo!(runner, demo_float_ln_rational_prec_ref); register_demo!(runner, demo_float_ln_rational_prec_ref_debug); register_demo!(runner, demo_float_ln_rational_prec_round); register_demo!(runner, demo_float_ln_rational_prec_round_debug); register_demo!(runner, demo_float_ln_rational_prec_round_ref); register_demo!(runner, demo_float_ln_rational_prec_round_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_ln_rational); register_bench!(runner, benchmark_float_ln_evaluation_strategy); register_bench!(runner, benchmark_float_ln_library_comparison); register_bench!(runner, benchmark_float_ln_assign); register_bench!(runner, benchmark_float_ln_prec_evaluation_strategy); register_bench!(runner, benchmark_float_ln_prec_library_comparison); register_bench!(runner, benchmark_float_ln_prec_assign); register_bench!(runner, benchmark_float_ln_round_evaluation_strategy); register_bench!(runner, benchmark_float_ln_round_library_comparison); register_bench!(runner, benchmark_float_ln_round_assign); register_bench!(runner, benchmark_float_ln_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_ln_prec_round_library_comparison); register_bench!(runner, benchmark_float_ln_prec_round_assign); register_primitive_float_benches!(runner, benchmark_primitive_float_ln); register_bench!(runner, benchmark_float_ln_rational_prec_evaluation_strategy); register_bench!( runner, benchmark_float_ln_rational_prec_round_evaluation_strategy ); register_primitive_float_benches!(runner, benchmark_primitive_float_ln_rational); } fn demo_float_ln(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).ln() = {}", x_old, x.ln()); } } fn demo_float_ln_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).ln() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.ln()) ); } } fn demo_float_ln_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).ln() = {}", x_old, x.ln()); } } fn demo_float_ln_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).ln() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.ln()) ); } } fn demo_float_ln_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("(&{}).ln() = {}", x, (&x).ln()); } } fn demo_float_ln_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "(&{:#x}).ln() = {:#x}", ComparableFloatRef(&x), ComparableFloat((&x).ln()) ); } } fn demo_float_ln_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.ln_assign(); println!("x := {x_old}; x.ln_assign(); x = {x}"); } } fn demo_float_ln_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.ln_assign(); println!( "x := {:#x}; x.ln_assign(); x = {:#x}", ComparableFloat(x_old), ComparableFloat(x) ); } } fn demo_float_ln_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).ln_prec({}) = {:?}", x_old, prec, x.ln_prec(prec)); } } fn demo_float_ln_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_prec(prec); println!( "({:#x}).ln_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).ln_prec({}) = {:?}", x_old, prec, x.ln_prec(prec)); } } fn demo_float_ln_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_prec(prec); println!( "({:#x}).ln_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).ln_prec_ref({}) = {:?}", x, prec, x.ln_prec_ref(prec)); } } fn demo_float_ln_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (sum, o) = x.ln_prec_ref(prec); println!( "(&{:#x}).ln_prec_ref({}) = ({:#x}, {:?})", ComparableFloat(x), prec, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.ln_prec_assign(prec); println!("x := {x_old}; x.ln_prec_assign({prec}); x = {x}"); } } fn demo_float_ln_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let o = x.ln_prec_assign(prec); println!( "x := {:#x}; x.ln_prec_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, o, ComparableFloat(x) ); } } fn demo_float_ln_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); println!("({}).ln_round({}) = {:?}", x_old, rm, x.ln_round(rm)); } } fn demo_float_ln_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_round(rm); println!( "({:#x}).ln_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_ln_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_35() .get(gm, config) .take(limit) { let x_old = x.clone(); println!("({}).ln_round({}) = {:?}", x_old, rm, x.ln_round(rm)); } } fn demo_float_ln_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_35() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_round(rm); println!( "({:#x}).ln_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_ln_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { println!("(&{}).ln_round_ref({}) = {:?}", x, rm, x.ln_round_ref(rm)); } } fn demo_float_ln_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { let (sum, o) = x.ln_round_ref(rm); println!( "(&{:#x}).ln_round_ref({}) = ({:#x}, {:?})", ComparableFloat(x), rm, ComparableFloat(sum), o ); } } fn demo_float_ln_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); x.ln_round_assign(rm); println!("x := {x_old}; x.ln_round_assign({rm}); x = {x}"); } } fn demo_float_ln_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_34() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.ln_round_assign(rm); println!( "x := {:#x}; x.ln_round_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), rm, o, ComparableFloat(x) ); } } fn demo_float_ln_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).ln_prec_round({}, {}) = {:?}", x_old, prec, rm, x.ln_prec_round(prec, rm) ); } } fn demo_float_ln_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_prec_round(prec, rm); println!( "({:#x}).ln_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_20() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).ln_prec_round({}, {}) = {:?}", x_old, prec, rm, x.ln_prec_round(prec, rm) ); } } fn demo_float_ln_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_20() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.ln_prec_round(prec, rm); println!( "({:#x}).ln_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { println!( "({}).ln_prec_round_ref({}, {}) = {:?}", x, prec, rm, x.ln_prec_round_ref(prec, rm) ); } } fn demo_float_ln_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { let (sum, o) = x.ln_prec_round_ref(prec, rm); println!( "({:#x}).ln_prec_round_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(x), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_ln_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.ln_prec_round_assign(prec, rm); println!("x := {x_old}; x.ln_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_ln_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_19() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.ln_prec_round_assign(prec, rm); println!( "x := {:#x}; x.ln_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_ln(gm: GenMode, config: &GenConfig, limit: usize) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "primitive_float_ln({}) = {}", NiceFloat(x), NiceFloat(primitive_float_ln(x)) ); } } fn demo_float_ln_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::ln_rational_prec({}, {}) = {:?}", n.clone(), p, Float::ln_rational_prec(n, p) ); } } fn demo_float_ln_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::ln_rational_prec(n.clone(), p); println!( "Float::ln_rational_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_ln_rational_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::ln_rational_prec_ref(&{}, {}) = {:?}", n, p, Float::ln_rational_prec_ref(&n, p) ); } } fn demo_float_ln_rational_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::ln_rational_prec_ref(&n, p); println!( "Float::ln_rational_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_ln_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "Float::ln_rational_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::ln_rational_prec_round(n, p, rm) ); } } fn demo_float_ln_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let (f, o) = Float::ln_rational_prec_round(n.clone(), p, rm); println!( "Float::ln_rational_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_ln_rational_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "Float::ln_rational_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::ln_rational_prec_round_ref(&n, p, rm) ); } } fn demo_float_ln_rational_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_6() .get(gm, config) .take(limit) { let (f, o) = Float::ln_rational_prec_round_ref(&n, p, rm); println!( "Float::ln_rational_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_ln_rational( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for x in rational_gen().get(gm, config).take(limit) { println!( "primitive_float_ln_rational({}) = {:?}", x, NiceFloat(primitive_float_ln_rational::(&x)) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_ln_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.ln()", &mut |x| no_out!(x.ln())), ("(&Float).ln()", &mut |x| no_out!((&x).ln())), ], ); } fn benchmark_float_ln_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!((&x).ln())), ("rug", &mut |(x, _)| no_out!(rug_ln(&x))), ], ); } fn benchmark_float_ln_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ln_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.ln_assign()", &mut |mut x| x.ln_assign())], ); } fn benchmark_float_ln_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Float.ln_prec(u64)", &mut |(x, prec)| { no_out!(x.ln_prec(prec)); }), ("(&Float).ln_prec_ref(u64)", &mut |(x, prec)| { no_out!(x.ln_prec_ref(prec)); }), ], ); } fn benchmark_float_ln_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec))| { no_out!(x.ln_prec_ref(prec)); }), ("rug", &mut |((x, prec), _)| { no_out!(rug_ln_prec(&x, prec)); }), ], ); } fn benchmark_float_ln_prec_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ln_prec_assign(u64)", BenchmarkType::Single, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [("Float.ln_prec_assign(u64)", &mut |(mut x, prec)| { no_out!(x.ln_prec_assign(prec)); })], ); } fn benchmark_float_ln_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_round(RoundingMode)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_34().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Float.ln_round(RoundingMode)", &mut |(x, rm)| { no_out!(x.ln_round(rm)); }), ("(&Float).ln_round_ref(RoundingMode)", &mut |(x, rm)| { no_out!(x.ln_round_ref(rm)); }), ], ); } fn benchmark_float_ln_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_round(RoundingMode)", BenchmarkType::LibraryComparison, float_rounding_mode_pair_gen_var_34_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, rm))| { no_out!(x.ln_round_ref(rm)); }), ("rug", &mut |((x, rm), _)| no_out!(rug_ln_round(&x, rm))), ], ); } fn benchmark_float_ln_round_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ln_round_assign(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen_var_34().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Float.ln_round_assign(RoundingMode)", &mut |(mut x, rm)| { no_out!(x.ln_round_assign(rm)); })], ); } fn benchmark_float_ln_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_19().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ( "Float.ln_prec_round(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.ln_prec_round(prec, rm)), ), ( "(&Float).ln_prec_round_ref(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.ln_prec_round_ref(prec, rm)), ), ], ); } fn benchmark_float_ln_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_19_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec, rm))| { no_out!(x.ln_prec_round_ref(prec, rm)); }), ("rug", &mut |((x, prec, rm), _)| { no_out!(rug_ln_prec_round(&x, prec, rm)); }), ], ); } fn benchmark_float_ln_prec_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.ln_prec_round_assign(u64, RoundingMode)", BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_19().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [( "Float.ln_prec_round_assign(u64, RoundingMode)", &mut |(mut x, prec, rm)| no_out!(x.ln_prec_round_assign(prec, rm)), )], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_ln( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!("primitive_float_ln({})", T::NAME), BenchmarkType::EvaluationStrategy, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("malachite", &mut |x| { no_out!(primitive_float_ln(x)); })], ); } fn benchmark_float_ln_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::ln_rational_prec(Rational, u64)", &mut |(n, prec)| no_out!(Float::ln_rational_prec(n, prec)), ), ( "Float::ln_rational_prec_ref(&Rational, u64)", &mut |(n, prec)| no_out!(Float::ln_rational_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_ln_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::ln_rational_prec(Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::ln_rational_prec_round(n, prec, rm)), ), ( "Float::ln_rational_prec_ref(&Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::ln_rational_prec_round_ref(&n, prec, rm)), ), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_ln_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!("primitive_float_ln_rational_prec::<{}>(Rational)", T::NAME), BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(primitive_float_ln_rational::(&x)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs::register(runner); add::register(runner); agm::register(runner); div::register(runner); is_power_of_2::register(runner); ln::register(runner); mul::register(runner); neg::register(runner); power_of_2::register(runner); reciprocal::register(runner); reciprocal_sqrt::register(runner); shl::register(runner); shl_round::register(runner); shr::register(runner); shr_round::register(runner); sign::register(runner); sqrt::register(runner); square::register(runner); sub::register(runner); } mod abs; mod add; mod agm; mod div; mod is_power_of_2; mod ln; mod mul; mod neg; mod power_of_2; mod reciprocal; mod reciprocal_sqrt; mod shl; mod shl_round; mod shr; mod shr_round; mod sign; mod sqrt; mod square; mod sub; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::mul::{ mul_rational_prec_round_direct, mul_rational_prec_round_direct_ref_ref, mul_rational_prec_round_direct_ref_val, mul_rational_prec_round_direct_val_ref, mul_rational_prec_round_naive, mul_rational_prec_round_naive_ref_ref, mul_rational_prec_round_naive_ref_val, mul_rational_prec_round_naive_val_ref, }; use malachite_float::test_util::arithmetic::mul::{ mul_prec_round_naive, rug_mul, rug_mul_prec, rug_mul_prec_round, rug_mul_rational, rug_mul_rational_prec, rug_mul_rational_prec_round, rug_mul_rational_round, rug_mul_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_2_triple_float_float_primitive_int_max_complexity_bucketer, pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, triple_float_float_primitive_int_max_complexity_bucketer, triple_float_rational_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_16, float_float_rounding_mode_triple_gen_var_16_rm, float_float_rounding_mode_triple_gen_var_31, float_float_unsigned_rounding_mode_quadruple_gen_var_3, float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm, float_float_unsigned_rounding_mode_quadruple_gen_var_7, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_float_unsigned_triple_gen_var_2, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_rounding_mode_triple_gen_var_4, float_rational_rounding_mode_triple_gen_var_9, float_rational_unsigned_rounding_mode_quadruple_gen_var_3, float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_8, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, float_rational_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_mul); register_demo!(runner, demo_float_mul_debug); register_demo!(runner, demo_float_mul_extreme); register_demo!(runner, demo_float_mul_extreme_debug); register_demo!(runner, demo_float_mul_val_ref); register_demo!(runner, demo_float_mul_val_ref_debug); register_demo!(runner, demo_float_mul_ref_val); register_demo!(runner, demo_float_mul_ref_val_debug); register_demo!(runner, demo_float_mul_ref_ref); register_demo!(runner, demo_float_mul_ref_ref_debug); register_demo!(runner, demo_float_mul_assign); register_demo!(runner, demo_float_mul_assign_debug); register_demo!(runner, demo_float_mul_assign_ref); register_demo!(runner, demo_float_mul_assign_ref_debug); register_demo!(runner, demo_float_mul_prec); register_demo!(runner, demo_float_mul_prec_debug); register_demo!(runner, demo_float_mul_prec_extreme); register_demo!(runner, demo_float_mul_prec_extreme_debug); register_demo!(runner, demo_float_mul_prec_val_ref); register_demo!(runner, demo_float_mul_prec_val_ref_debug); register_demo!(runner, demo_float_mul_prec_ref_val); register_demo!(runner, demo_float_mul_prec_ref_val_debug); register_demo!(runner, demo_float_mul_prec_ref_ref); register_demo!(runner, demo_float_mul_prec_ref_ref_debug); register_demo!(runner, demo_float_mul_prec_assign); register_demo!(runner, demo_float_mul_prec_assign_debug); register_demo!(runner, demo_float_mul_prec_assign_ref); register_demo!(runner, demo_float_mul_prec_assign_ref_debug); register_demo!(runner, demo_float_mul_round); register_demo!(runner, demo_float_mul_round_debug); register_demo!(runner, demo_float_mul_round_extreme); register_demo!(runner, demo_float_mul_round_extreme_debug); register_demo!(runner, demo_float_mul_round_val_ref); register_demo!(runner, demo_float_mul_round_val_ref_debug); register_demo!(runner, demo_float_mul_round_ref_val); register_demo!(runner, demo_float_mul_round_ref_val_debug); register_demo!(runner, demo_float_mul_round_ref_ref); register_demo!(runner, demo_float_mul_round_ref_ref_debug); register_demo!(runner, demo_float_mul_round_assign); register_demo!(runner, demo_float_mul_round_assign_debug); register_demo!(runner, demo_float_mul_round_assign_ref); register_demo!(runner, demo_float_mul_round_assign_ref_debug); register_demo!(runner, demo_float_mul_prec_round); register_demo!(runner, demo_float_mul_prec_round_debug); register_demo!(runner, demo_float_mul_prec_round_extreme); register_demo!(runner, demo_float_mul_prec_round_extreme_debug); register_demo!(runner, demo_float_mul_prec_round_val_ref); register_demo!(runner, demo_float_mul_prec_round_val_ref_debug); register_demo!(runner, demo_float_mul_prec_round_ref_val); register_demo!(runner, demo_float_mul_prec_round_ref_val_debug); register_demo!(runner, demo_float_mul_prec_round_ref_ref); register_demo!(runner, demo_float_mul_prec_round_ref_ref_debug); register_demo!(runner, demo_float_mul_prec_round_assign); register_demo!(runner, demo_float_mul_prec_round_assign_debug); register_demo!(runner, demo_float_mul_prec_round_assign_ref); register_demo!(runner, demo_float_mul_prec_round_assign_ref_debug); register_demo!(runner, demo_float_mul_rational); register_demo!(runner, demo_float_mul_rational_debug); register_demo!(runner, demo_float_mul_rational_extreme); register_demo!(runner, demo_float_mul_rational_extreme_debug); register_demo!(runner, demo_float_mul_rational_val_ref); register_demo!(runner, demo_float_mul_rational_val_ref_debug); register_demo!(runner, demo_float_mul_rational_ref_val); register_demo!(runner, demo_float_mul_rational_ref_val_debug); register_demo!(runner, demo_float_mul_rational_ref_ref); register_demo!(runner, demo_float_mul_rational_ref_ref_debug); register_demo!(runner, demo_float_mul_rational_assign); register_demo!(runner, demo_float_mul_rational_assign_debug); register_demo!(runner, demo_float_mul_rational_assign_ref); register_demo!(runner, demo_float_mul_rational_assign_ref_debug); register_demo!(runner, demo_rational_mul_float); register_demo!(runner, demo_rational_mul_float_debug); register_demo!(runner, demo_rational_mul_float_extreme); register_demo!(runner, demo_rational_mul_float_extreme_debug); register_demo!(runner, demo_rational_mul_float_val_ref); register_demo!(runner, demo_rational_mul_float_val_ref_debug); register_demo!(runner, demo_rational_mul_float_ref_val); register_demo!(runner, demo_rational_mul_float_ref_val_debug); register_demo!(runner, demo_rational_mul_float_ref_ref); register_demo!(runner, demo_rational_mul_float_ref_ref_debug); register_demo!(runner, demo_float_mul_rational_prec); register_demo!(runner, demo_float_mul_rational_prec_debug); register_demo!(runner, demo_float_mul_rational_prec_extreme); register_demo!(runner, demo_float_mul_rational_prec_extreme_debug); register_demo!(runner, demo_float_mul_rational_prec_val_ref); register_demo!(runner, demo_float_mul_rational_prec_val_ref_debug); register_demo!(runner, demo_float_mul_rational_prec_ref_val); register_demo!(runner, demo_float_mul_rational_prec_ref_val_debug); register_demo!(runner, demo_float_mul_rational_prec_ref_ref); register_demo!(runner, demo_float_mul_rational_prec_ref_ref_debug); register_demo!(runner, demo_float_mul_rational_prec_assign); register_demo!(runner, demo_float_mul_rational_prec_assign_debug); register_demo!(runner, demo_float_mul_rational_prec_assign_ref); register_demo!(runner, demo_float_mul_rational_prec_assign_ref_debug); register_demo!(runner, demo_float_mul_rational_round); register_demo!(runner, demo_float_mul_rational_round_debug); register_demo!(runner, demo_float_mul_rational_round_extreme); register_demo!(runner, demo_float_mul_rational_round_extreme_debug); register_demo!(runner, demo_float_mul_rational_round_val_ref); register_demo!(runner, demo_float_mul_rational_round_val_ref_debug); register_demo!(runner, demo_float_mul_rational_round_ref_val); register_demo!(runner, demo_float_mul_rational_round_ref_val_debug); register_demo!(runner, demo_float_mul_rational_round_ref_ref); register_demo!(runner, demo_float_mul_rational_round_ref_ref_debug); register_demo!(runner, demo_float_mul_rational_round_assign); register_demo!(runner, demo_float_mul_rational_round_assign_debug); register_demo!(runner, demo_float_mul_rational_round_assign_ref); register_demo!(runner, demo_float_mul_rational_round_assign_ref_debug); register_demo!(runner, demo_float_mul_rational_prec_round); register_demo!(runner, demo_float_mul_rational_prec_round_debug); register_demo!(runner, demo_float_mul_rational_prec_round_extreme); register_demo!(runner, demo_float_mul_rational_prec_round_extreme_debug); register_demo!(runner, demo_float_mul_rational_prec_round_val_ref); register_demo!(runner, demo_float_mul_rational_prec_round_val_ref_debug); register_demo!(runner, demo_float_mul_rational_prec_round_ref_val); register_demo!(runner, demo_float_mul_rational_prec_round_ref_val_debug); register_demo!(runner, demo_float_mul_rational_prec_round_ref_ref); register_demo!(runner, demo_float_mul_rational_prec_round_ref_ref_debug); register_demo!(runner, demo_float_mul_rational_prec_round_assign); register_demo!(runner, demo_float_mul_rational_prec_round_assign_debug); register_demo!(runner, demo_float_mul_rational_prec_round_assign_ref); register_demo!(runner, demo_float_mul_rational_prec_round_assign_ref_debug); register_bench!(runner, benchmark_float_mul_evaluation_strategy); register_bench!(runner, benchmark_float_mul_library_comparison); register_bench!(runner, benchmark_float_mul_algorithms); register_bench!(runner, benchmark_float_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_library_comparison); register_bench!(runner, benchmark_float_mul_prec_algorithms); register_bench!(runner, benchmark_float_mul_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_round_evaluation_strategy); register_bench!(runner, benchmark_float_mul_round_library_comparison); register_bench!(runner, benchmark_float_mul_round_algorithms); register_bench!(runner, benchmark_float_mul_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_mul_prec_round_library_comparison); register_bench!(runner, benchmark_float_mul_prec_round_algorithms); register_bench!( runner, benchmark_float_mul_prec_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_float_mul_rational_evaluation_strategy); register_bench!(runner, benchmark_float_mul_rational_library_comparison); register_bench!(runner, benchmark_float_mul_rational_algorithms); register_bench!( runner, benchmark_float_mul_rational_assign_evaluation_strategy ); register_bench!(runner, benchmark_rational_mul_float_evaluation_strategy); register_bench!(runner, benchmark_rational_mul_float_library_comparison); register_bench!( runner, benchmark_float_mul_rational_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_mul_rational_prec_library_comparison); register_bench!(runner, benchmark_float_mul_rational_prec_algorithms); register_bench!( runner, benchmark_float_mul_rational_prec_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_mul_rational_round_evaluation_strategy ); register_bench!( runner, benchmark_float_mul_rational_round_library_comparison ); register_bench!(runner, benchmark_float_mul_rational_round_algorithms); register_bench!( runner, benchmark_float_mul_rational_round_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_mul_rational_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_mul_rational_prec_round_library_comparison ); register_bench!(runner, benchmark_float_mul_rational_prec_round_algorithms); register_bench!( runner, benchmark_float_mul_rational_prec_round_val_ref_algorithms ); register_bench!( runner, benchmark_float_mul_rational_prec_round_ref_val_algorithms ); register_bench!( runner, benchmark_float_mul_rational_prec_round_ref_ref_algorithms ); register_bench!( runner, benchmark_float_mul_rational_prec_round_assign_evaluation_strategy ); } fn demo_float_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_float_mul_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} * {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x * y) ); } } fn demo_float_mul_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_float_mul_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} * {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x * y) ); } } fn demo_float_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_float_mul_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} * &{:#x} = {:#x}", ComparableFloat(x_old), ComparableFloatRef(&y), ComparableFloat(x * &y) ); } } fn demo_float_mul_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_float_mul_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} * {:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloat(y_old), ComparableFloat(&x * y) ); } } fn demo_float_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_float_mul_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} * &{:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloatRef(&y), ComparableFloat(&x * &y) ); } } fn demo_float_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x *= {y}; x = {x}"); } } fn demo_float_mul_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!( "x := {:#x}; x *= {:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_mul_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x *= &{y}; x = {x}"); } } fn demo_float_mul_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!( "x := {:#x}; x *= &{:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_mul_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_prec({}, {}) = {:?}", x_old, y_old, prec, x.mul_prec(y, prec) ); } } fn demo_float_mul_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_prec(y, prec); println!( "({:#x}).mul_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_prec({}, {}) = {:?}", x_old, y_old, prec, x.mul_prec(y, prec) ); } } fn demo_float_mul_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_prec(y, prec); println!( "({:#x}).mul_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_prec_val_ref(&{}, {}) = {:?}", x_old, y, prec, x.mul_prec_val_ref(&y, prec) ); } } fn demo_float_mul_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_prec_val_ref(&y, prec); println!( "({:#x}).mul_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.mul_prec_ref_val(y, prec) ); } } fn demo_float_mul_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_prec_ref_val(y, prec); println!( "(&{:#x}).mul_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).mul_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.mul_prec_ref_ref(&y, prec) ); } } fn demo_float_mul_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.mul_prec_ref_ref(&y, prec); println!( "(&{:#x}).mul_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mul_prec_assign(y, prec); println!("x := {x_old}; x.mul_prec_assign({y_old}, {prec}); x = {x}"); } } fn demo_float_mul_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_prec_assign(y, prec); println!( "x := {:#x}; x.mul_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, o, ComparableFloat(x) ); } } fn demo_float_mul_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mul_prec_assign_ref(&y, prec); println!("x := {x_old}; x.mul_prec_assign({y}, {prec}); x = {x}"); } } fn demo_float_mul_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.mul_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, o, ComparableFloat(x) ); } } fn demo_float_mul_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_round({}, {}) = {:?}", x_old, y_old, rm, x.mul_round(y, rm) ); } } fn demo_float_mul_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_round(y, rm); println!( "({:#x}).mul_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_mul_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_31() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_round({}, {}) = {:?}", x_old, y_old, rm, x.mul_round(y, rm) ); } } fn demo_float_mul_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_31() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_round(y, rm); println!( "({:#x}).mul_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_mul_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.mul_round_val_ref(&y, rm) ); } } fn demo_float_mul_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_round_val_ref(&y, rm); println!( "({:#x}).mul_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_mul_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_round_ref_val({}, {}) = {:?}", x, y_old, rm, x.mul_round_ref_val(y, rm) ); } } fn demo_float_mul_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_round_ref_val(y, rm); println!( "(&{:#x}).mul_round_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), rm, ComparableFloat(sum), o ); } } fn demo_float_mul_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { println!( "(&{}).mul_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.mul_round_ref_ref(&y, rm) ); } } fn demo_float_mul_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let (sum, o) = x.mul_round_ref_ref(&y, rm); println!( "(&{:#x}).mul_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), rm, ComparableFloat(sum), o ); } } fn demo_float_mul_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mul_round_assign(y, rm); println!("x := {x_old}; x.mul_round_assign({y_old}, {rm}); x = {x}"); } } fn demo_float_mul_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_round_assign(y, rm); println!( "x := {:#x}; x.mul_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), rm, o, ComparableFloat(x) ); } } fn demo_float_mul_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mul_round_assign_ref(&y, rm); println!("x := {x_old}; x.mul_round_assign({y}, {rm}); x = {x}"); } } fn demo_float_mul_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_round_assign_ref(&y, rm); println!( "x := {:#x}; x.mul_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), rm, o, ComparableFloat(x) ); } } fn demo_float_mul_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.mul_prec_round(y, prec, rm) ); } } fn demo_float_mul_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_prec_round(y, prec, rm); println!( "({:#x}).mul_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.mul_prec_round(y, prec, rm) ); } } fn demo_float_mul_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_prec_round(y, prec, rm); println!( "({:#x}).mul_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_prec_round(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.mul_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_mul_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).mul_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.mul_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_mul_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).mul_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { println!( "({}).mul_prec_round({}, {}, {}) = {:?}", x, y, prec, rm, x.mul_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_mul_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let (sum, o) = x.mul_prec_round_ref_ref(&y, prec, rm); println!( "({:#x}).mul_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_prec_round_assign(y, prec, rm); println!("x := {x_old}; x.mul_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_mul_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.mul_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_mul_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_prec_round_assign_ref(&y, prec, rm); println!("x := {x_old}; x.mul_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_mul_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.mul_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_mul_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_float_mul_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} * {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x * y) ); } } fn demo_float_mul_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_float_mul_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} * {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x * y) ); } } fn demo_float_mul_rational_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_float_mul_rational_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} * {} = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x * &y) ); } } fn demo_float_mul_rational_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_float_mul_rational_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} * {} = {:#x}", ComparableFloatRef(&x), y_old, ComparableFloat(&x * y) ); } } fn demo_float_mul_rational_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_float_mul_rational_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} * &{} = {:#x}", ComparableFloatRef(&x), y, ComparableFloat(&x * &y) ); } } fn demo_float_mul_rational_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x *= {y}; x = {x}"); } } fn demo_float_mul_rational_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!( "x := {:#x}; x *= {}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_float_mul_rational_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x *= &{y}; x = {x}"); } } fn demo_float_mul_rational_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!( "x := {:#x}; x *= &{}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_rational_mul_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_rational_mul_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} * {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x * y) ); } } fn demo_rational_mul_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_rational_mul_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} * {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x * y) ); } } fn demo_rational_mul_float_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_rational_mul_float_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{} * &{:#x} = {:#x}", x_old, ComparableFloatRef(&y), ComparableFloat(x * &y) ); } } fn demo_rational_mul_float_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_rational_mul_float_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{} * {:#x} = {:#x}", x, ComparableFloat(y_old), ComparableFloat(&x * y) ); } } fn demo_rational_mul_float_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_rational_mul_float_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{} * &{:#x} = {:#x}", x, ComparableFloatRef(&y), ComparableFloat(&x * &y) ); } } fn demo_float_mul_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.mul_rational_prec(y, prec) ); } } fn demo_float_mul_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_prec(y, prec); println!( "({:#x}).mul_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.mul_rational_prec(y, prec) ); } } fn demo_float_mul_rational_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_prec(y, prec); println!( "({:#x}).mul_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_rational_prec({}, &{}) = {:?}", x_old, y, prec, x.mul_rational_prec_val_ref(&y, prec) ); } } fn demo_float_mul_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_rational_prec_val_ref(&y, prec); println!( "({:#x}).mul_rational_prec_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_rational_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.mul_rational_prec_ref_val(y, prec) ); } } fn demo_float_mul_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_rational_prec_ref_val(y, prec); println!( "(&{:#x}).mul_rational_prec_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).mul_rational_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.mul_rational_prec_ref_ref(&y, prec) ); } } fn demo_float_mul_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (sum, o) = x.mul_rational_prec_ref_ref(&y, prec); println!( "(&{:#x}).mul_rational_prec_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_prec_assign(y, prec); println!("x := {x_old}; x.mul_rational_prec_assign({y_old}, {prec}) = {o:?}; x = {x}"); } } fn demo_float_mul_rational_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_prec_assign(y, prec); println!( "x := {:#x}; x.mul_rational_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, o, ComparableFloat(x) ); } } fn demo_float_mul_rational_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_rational_prec_assign_ref(&y, prec); println!("x := {x_old}; x.mul_rational_prec_assign_ref({y}, &{prec}) = {o:?}; x = {x}"); } } fn demo_float_mul_rational_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_rational_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.mul_rational_prec_assign(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, o, ComparableFloat(x) ); } } fn demo_float_mul_rational_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.mul_rational_round(y, rm) ); } } fn demo_float_mul_rational_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_round(y, rm); println!( "({:#x}).mul_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.mul_rational_round(y, rm) ); } } fn demo_float_mul_rational_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_9() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_round(y, rm); println!( "({:#x}).mul_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_rational_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.mul_rational_round_val_ref(&y, rm) ); } } fn demo_float_mul_rational_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_rational_round_val_ref(&y, rm); println!( "({:#x}).mul_rational_round_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_rational_round_ref_val(&{}, {}) = {:?}", x, y_old, rm, x.mul_rational_round_ref_val(y, rm) ); } } fn demo_float_mul_rational_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_rational_round_ref_val(y, rm); println!( "(&{:#x}).mul_rational_round_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "(&{}).mul_rational_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.mul_rational_round_ref_ref(&y, rm) ); } } fn demo_float_mul_rational_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let (sum, o) = x.mul_rational_round_ref_ref(&y, rm); println!( "(&{:#x}).mul_rational_round_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_round_assign(y, rm); println!("x := {x_old}; x.mul_rational_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_mul_rational_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_round_assign(y, rm); println!( "x := {:#x}; x.mul_rational_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_mul_rational_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_rational_round_assign_ref(&y, rm); println!("x := {x_old}; x.mul_rational_round_assign_ref(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_mul_rational_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_round_assign_ref(&y, rm); println!( "x := {:#x}; x.mul_rational_round_assign_ref(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_mul_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.mul_rational_prec_round(y, prec, rm) ); } } fn demo_float_mul_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_prec_round(y, prec, rm); println!( "({:#x}).mul_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).mul_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.mul_rational_prec_round(y, prec, rm) ); } } fn demo_float_mul_rational_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (sum, o) = x.mul_rational_prec_round(y, prec, rm); println!( "({:#x}).mul_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).mul_rational_prec_round_val_ref(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.mul_rational_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_mul_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.mul_rational_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).mul_rational_prec_round_val_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).mul_rational_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.mul_rational_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_mul_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let y_old = y.clone(); let (sum, o) = x.mul_rational_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).mul_rational_prec_round_ref_val({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { println!( "(&{}).mul_rational_prec_round_ref_ref(&{}, {}, {}) = {:?}", x, y, prec, rm, x.mul_rational_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_mul_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let (sum, o) = x.mul_rational_prec_round_ref_ref(&y, prec, rm); println!( "(&{:#x}).mul_rational_prec_round_ref_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, rm, ComparableFloat(sum), o ); } } fn demo_float_mul_rational_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_prec_round_assign(y, prec, rm); println!( "x := {x_old}; x.mul_rational_prec_round_assign({y_old}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_mul_rational_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.mul_rational_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.mul_rational_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, rm, o, ComparableFloat(x) ); } } fn demo_float_mul_rational_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {x_old}; x.mul_rational_prec_round_assign_ref(&{y}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_mul_rational_prec_round_assign_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.mul_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.mul_rational_prec_round_assign_ref(&{}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float * Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float * Float", &mut |(x, y)| no_out!(x * y)), ("Float * &Float", &mut |(x, y)| no_out!(x * &y)), ("&Float * Float", &mut |(x, y)| no_out!(&x * y)), ("&Float * &Float", &mut |(x, y)| no_out!(&x * &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_mul_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float * Float", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x * &y)), ("rug", &mut |((x, y), _)| no_out!(rug_mul(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_mul_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float * Float", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x * y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(mul_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float *= Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float *= Float", &mut |(mut x, y)| x *= y), ("Float *= &Float", &mut |(mut x, y)| x *= &y), ], ); } fn benchmark_float_mul_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.mul_prec(Float, u64)", &mut |(x, y, prec)| { no_out!(x.mul_prec(y, prec)); }), ("Float.mul_prec_val_ref(&Float, u64)", &mut |( x, y, prec, )| { no_out!(x.mul_prec_val_ref(&y, prec)); }), ( "(&Float).mul_prec_ref_val(Float, u64)", &mut |(x, y, prec)| no_out!(x.mul_prec_ref_val(y, prec)), ), ( "(&Float).mul_prec_ref_ref(&Float, u64)", &mut |(x, y, prec)| no_out!(x.mul_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_mul_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec(Float, u64)", BenchmarkType::LibraryComparison, float_float_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.mul_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_mul_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_mul_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec(Float, u64)", BenchmarkType::Algorithms, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| no_out!(x.mul_prec(y, prec))), ("naive", &mut |(x, y, prec)| { no_out!(mul_prec_round_naive(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_mul_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec_assign(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.mul_prec_assign(Float, u64)", &mut |( mut x, y, prec, )| { no_out!(x.mul_prec_assign(y, prec)); }), ( "Float.mul_prec_assign_ref(&Float, u64)", &mut |(mut x, y, prec)| no_out!(x.mul_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_mul_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_round(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_16().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.mul_round(Float, RoundingMode)", &mut |(x, y, rm)| { no_out!(x.mul_round(y, rm)); }), ( "Float.mul_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_round_val_ref(&y, rm)), ), ( "(&Float).mul_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_round_ref_val(y, rm)), ), ( "(&Float).mul_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_mul_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_round(Float, RoundingMode)", BenchmarkType::LibraryComparison, float_float_rounding_mode_triple_gen_var_16_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.mul_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_mul_round(&x, &y, rm)); }), ], ); } fn benchmark_float_mul_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_round(Float, RoundingMode)", BenchmarkType::Algorithms, float_float_rounding_mode_triple_gen_var_16().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| no_out!(x.mul_round(y, rm))), ("naive", &mut |(x, y, rm)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); mul_prec_round_naive(x, y, max(xsb, ysb), rm); }), ], ); } fn benchmark_float_mul_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_round_assign(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_16().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ( "Float.mul_round_assign(Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.mul_round_assign(y, rm)), ), ( "Float.mul_round_assign_ref(&Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.mul_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_mul_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec_round(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_prec_round(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_prec_round(y, prec, rm)), ), ( "Float.mul_prec_round_val_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).mul_prec_round_ref_val(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).mul_prec_round_ref_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_mul_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec_round(Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.mul_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_mul_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_mul_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec_round(Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_float_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.mul_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_prec_round_naive(x, y, prec, rm)); }), ], ); } fn benchmark_float_mul_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_prec_round_assign(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_prec_round_assign(Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.mul_prec_round_assign(y, prec, rm)), ), ( "Float.mul_prec_round_assign_ref(&Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.mul_prec_round_assign_ref(&y, prec, rm)), ), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_mul_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float * Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float * Rational", &mut |(x, y)| no_out!(x * y)), ("Float * &Rational", &mut |(x, y)| no_out!(x * &y)), ("&Float * Rational", &mut |(x, y)| no_out!(&x * y)), ("&Float * &Rational", &mut |(x, y)| no_out!(&x * &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_mul_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float * Rational", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x * &y)), ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_mul_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float * Rational", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x * y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(mul_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ("direct", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(mul_rational_prec_round_direct(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_mul_rational_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float *= Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float *= Rational", &mut |(mut x, y)| x *= y), ("Float *= &Rational", &mut |(mut x, y)| x *= &y), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_mul_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational * Float", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Rational * Float", &mut |(y, x)| no_out!(x * y)), ("Rational * &Float", &mut |(y, x)| no_out!(x * &y)), ("&Rational * Float", &mut |(y, x)| no_out!(&x * y)), ("&Rational * &Float", &mut |(y, x)| no_out!(&x * &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_mul_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational * Float", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(&x * &y)), ("rug", &mut |((x, y), _)| no_out!(rug_mul_rational(&x, &y))), ], ); } fn benchmark_float_mul_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_rational_prec(Rational, u64)", &mut |(x, y, prec)| no_out!(x.mul_rational_prec(y, prec)), ), ( "Float.mul_rational_prec_val_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.mul_rational_prec_val_ref(&y, prec)), ), ( "(&Float).mul_rational_prec_ref_val(Rational, u64)", &mut |(x, y, prec)| no_out!(x.mul_rational_prec_ref_val(y, prec)), ), ( "(&Float).mul_rational_prec_ref_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.mul_rational_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_mul_rational_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec(Rational, u64)", BenchmarkType::LibraryComparison, float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.mul_rational_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_mul_rational_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_mul_rational_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec(Rational, u64)", BenchmarkType::Algorithms, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| { no_out!(x.mul_rational_prec(y, prec)); }), ("naive", &mut |(x, y, prec)| { no_out!(mul_rational_prec_round_naive(x, y, prec, Nearest)); }), ("direct", &mut |(x, y, prec)| { no_out!(mul_rational_prec_round_direct(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_mul_rational_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_assign(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_rational_prec_assign(Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.mul_rational_prec_assign(y, prec)), ), ( "Float.mul_rational_prec_assign_ref(&Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.mul_rational_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_mul_rational_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_round(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.mul_rational_round(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_rational_round(y, rm)), ), ( "Float.mul_rational_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_rational_round_val_ref(&y, rm)), ), ( "(&Float).mul_rational_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_rational_round_ref_val(y, rm)), ), ( "(&Float).mul_rational_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.mul_rational_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_mul_rational_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_round(Rational, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.mul_rational_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_mul_rational_round(&x, &y, rm)); }), ], ); } fn benchmark_float_mul_rational_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_round(Rational, RoundingMode)", BenchmarkType::Algorithms, float_rational_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.mul_rational_round(y, rm)); }), ("naive", &mut |(x, y, rm)| { let ysb = y.significant_bits(); mul_rational_prec_round_naive(x, y, ysb, rm); }), ("direct", &mut |(x, y, rm)| { let ysb = y.significant_bits(); mul_rational_prec_round_direct(x, y, ysb, rm); }), ], ); } fn benchmark_float_mul_rational_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_round_assign(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.mul_rational_round_assign(Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.mul_rational_round_assign(y, rm)), ), ( "Float.mul_rational_round_assign_ref(&Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.mul_rational_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_mul_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_rational_prec_round(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_rational_prec_round(y, prec, rm)), ), ( "Float.mul_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_rational_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).mul_rational_prec_round_ref_val(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_rational_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).mul_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.mul_rational_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_mul_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( "x", "y", "prec", ), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.mul_rational_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_mul_rational_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_mul_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.mul_rational_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_naive(x, y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_direct(x, y, prec, rm)); }), ], ); } fn benchmark_float_mul_rational_prec_round_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.mul_rational_prec_round_val_ref(&y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_naive_val_ref(x, &y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_direct_val_ref(x, &y, prec, rm)); }), ], ); } fn benchmark_float_mul_rational_prec_round_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Float).mul_rational_prec_round_ref_val(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.mul_rational_prec_round_ref_val(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_naive_ref_val(&x, y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_direct_ref_val(&x, y, prec, rm)); }), ], ); } fn benchmark_float_mul_rational_prec_round_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.mul_rational_prec_round_ref_ref(&y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm)); }), ("direct", &mut |(x, y, prec, rm)| { no_out!(mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_mul_rational_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.mul_rational_prec_round_assign(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.mul_rational_prec_round_assign(Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.mul_rational_prec_round_assign(y, prec, rm)), ), ( "Float.mul_rational_prec_round_assign_ref(&Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| { no_out!(x.mul_rational_prec_round_assign_ref(&y, prec, rm)); }, ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_2_float_complexity_bucketer, }; use malachite_float::test_util::generators::{float_gen, float_gen_rm, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_neg); register_demo!(runner, demo_float_neg_debug); register_demo!(runner, demo_float_neg_extreme); register_demo!(runner, demo_float_neg_extreme_debug); register_demo!(runner, demo_float_neg_ref); register_demo!(runner, demo_float_neg_ref_debug); register_demo!(runner, demo_float_neg_assign); register_demo!(runner, demo_float_neg_assign_debug); register_bench!(runner, benchmark_float_neg_library_comparison); register_bench!(runner, benchmark_float_neg_evaluation_strategy); register_bench!(runner, benchmark_float_neg_assign); } fn demo_float_neg(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!("-({}) = {}", n.clone(), -n); } } fn demo_float_neg_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "-({:#x}) = {:#x}", ComparableFloat(n.clone()), ComparableFloat(-n) ); } } fn demo_float_neg_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!("-({}) = {}", n.clone(), -n); } } fn demo_float_neg_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!( "-({:#x}) = {:#x}", ComparableFloat(n.clone()), ComparableFloat(-n) ); } } fn demo_float_neg_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!("-(&{}) = {}", n, -&n); } } fn demo_float_neg_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "-(&{:#x}) = {:#x}", ComparableFloatRef(&n), ComparableFloat(-&n) ); } } fn demo_float_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.neg_assign(); println!("n := {n_old}; n.neg_assign(); n = {n}"); } } fn demo_float_neg_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in float_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.neg_assign(); println!( "n := {:#x}; n.neg_assign(); n = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_neg_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Float", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(_, n)| no_out!(-n)), ("rug", &mut |(n, _)| no_out!(-n))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Float", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.neg()", &mut |n| no_out!(-n)), ("(&Float).neg()", &mut |n| no_out!(-&n))], ); } fn benchmark_float_neg_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.neg_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |mut n| n.neg_assign())], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::test_util::bench::bucketers::{ abs_pair_usize_convertible_max_bucketer, abs_triple_1_2_usize_convertible_max_bucketer, signed_abs_bucketer, unsigned_direct_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen_var_5, signed_unsigned_pair_gen_var_19, unsigned_gen_var_5, }; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::power_of_2::{ power_of_2_i64_naive, power_of_2_prec_naive, power_of_2_prec_round_naive, power_of_2_u64_naive, }; use malachite_float::test_util::generators::signed_unsigned_rounding_mode_triple_gen_var_5; use malachite_float::{ComparableFloat, Float}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_power_of_2_prec_round); register_demo!(runner, demo_float_power_of_2_prec_round_debug); register_demo!(runner, demo_float_power_of_2_prec); register_demo!(runner, demo_float_power_of_2_prec_debug); register_demo!(runner, demo_float_power_of_2_u64); register_demo!(runner, demo_float_power_of_2_u64_debug); register_demo!(runner, demo_float_power_of_2_i64); register_demo!(runner, demo_float_power_of_2_i64_debug); register_bench!(runner, benchmark_float_power_of_2_prec_round_algorithms); register_bench!(runner, benchmark_float_power_of_2_prec_algorithms); register_bench!(runner, benchmark_float_power_of_2_u64_algorithms); register_bench!(runner, benchmark_float_power_of_2_i64_algorithms); } fn demo_float_power_of_2_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in signed_unsigned_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { println!( "Float::power_of_2_prec_round({}, {}, {:?}) = {:?}", x, prec, rm, Float::power_of_2_prec_round(x, prec, rm) ); } } fn demo_float_power_of_2_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in signed_unsigned_rounding_mode_triple_gen_var_5() .get(gm, config) .take(limit) { let (p, o) = Float::power_of_2_prec_round(x, prec, rm); println!( "Float::power_of_2_prec_round({}, {}, {:?}) = ({:#x}, {:?})", x, prec, rm, ComparableFloat(p), o ); } } fn demo_float_power_of_2_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in signed_unsigned_pair_gen_var_19::() .get(gm, config) .take(limit) { println!( "Float::power_of_2_prec({}, {}) = {:?}", x, prec, Float::power_of_2_prec(x, prec) ); } } fn demo_float_power_of_2_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in signed_unsigned_pair_gen_var_19::() .get(gm, config) .take(limit) { let (p, o) = Float::power_of_2_prec(x, prec); println!( "Float::power_of_2_prec({}, {}) = ({:#x}, {:?})", x, prec, ComparableFloat(p), o ); } } fn demo_float_power_of_2_u64(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_5::().get(gm, config).take(limit) { println!("Float::power_of_2({}) = {}", x, Float::power_of_2(x)); } } fn demo_float_power_of_2_u64_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_5::().get(gm, config).take(limit) { println!( "Float::power_of_2({}) = {:#x}", x, ComparableFloat(Float::power_of_2(x)) ); } } fn demo_float_power_of_2_i64(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen_var_5::().get(gm, config).take(limit) { println!("Float::power_of_2({}) = {}", x, Float::power_of_2(x)); } } fn demo_float_power_of_2_i64_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen_var_5::().get(gm, config).take(limit) { println!( "Float::power_of_2({}) = {:#x}", x, ComparableFloat(Float::power_of_2(x)) ); } } fn benchmark_float_power_of_2_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.power_of_2_prec_round(i64, u64, RoundingMode)", BenchmarkType::Algorithms, signed_unsigned_rounding_mode_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &abs_triple_1_2_usize_convertible_max_bucketer("i", "p"), &mut [ ("default", &mut |(i, p, rm)| { no_out!(Float::power_of_2_prec_round(i, p, rm)); }), ("naive", &mut |(i, p, rm)| { no_out!(power_of_2_prec_round_naive(i, p, rm)); }), ], ); } fn benchmark_float_power_of_2_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.power_of_2_prec(i64, u64)", BenchmarkType::Algorithms, signed_unsigned_pair_gen_var_19::().get(gm, config), gm.name(), limit, file_name, &abs_pair_usize_convertible_max_bucketer("i", "p"), &mut [ ("default", &mut |(i, p)| { no_out!(Float::power_of_2_prec(i, p)); }), ("naive", &mut |(i, p)| no_out!(power_of_2_prec_naive(i, p))), ], ); } fn benchmark_float_power_of_2_u64_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.power_of_2(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |u| no_out!(Float::power_of_2(u))), ("naive", &mut |u| no_out!(power_of_2_u64_naive(u))), ], ); } fn benchmark_float_power_of_2_i64_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.power_of_2(i64)", BenchmarkType::Algorithms, signed_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &signed_abs_bucketer("x"), &mut [ ("default", &mut |i| no_out!(Float::power_of_2(i))), ("naive", &mut |i| no_out!(power_of_2_i64_naive(i))), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Reciprocal, ReciprocalAssign}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::reciprocal::{ reciprocal_prec_round_naive_1, reciprocal_prec_round_naive_2, rug_reciprocal, rug_reciprocal_prec, rug_reciprocal_prec_round, rug_reciprocal_round, }; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, pair_2_pair_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_rounding_mode_pair_gen_var_13, float_rounding_mode_pair_gen_var_13_rm, float_rounding_mode_pair_gen_var_23, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_3, float_unsigned_rounding_mode_triple_gen_var_3_rm, float_unsigned_rounding_mode_triple_gen_var_12, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_reciprocal); register_demo!(runner, demo_float_reciprocal_debug); register_demo!(runner, demo_float_reciprocal_extreme); register_demo!(runner, demo_float_reciprocal_extreme_debug); register_demo!(runner, demo_float_reciprocal_ref); register_demo!(runner, demo_float_reciprocal_ref_debug); register_demo!(runner, demo_float_reciprocal_assign); register_demo!(runner, demo_float_reciprocal_assign_debug); register_demo!(runner, demo_float_reciprocal_prec); register_demo!(runner, demo_float_reciprocal_prec_debug); register_demo!(runner, demo_float_reciprocal_prec_extreme); register_demo!(runner, demo_float_reciprocal_prec_extreme_debug); register_demo!(runner, demo_float_reciprocal_prec_ref); register_demo!(runner, demo_float_reciprocal_prec_ref_debug); register_demo!(runner, demo_float_reciprocal_prec_assign); register_demo!(runner, demo_float_reciprocal_prec_assign_debug); register_demo!(runner, demo_float_reciprocal_round); register_demo!(runner, demo_float_reciprocal_round_debug); register_demo!(runner, demo_float_reciprocal_round_extreme); register_demo!(runner, demo_float_reciprocal_round_extreme_debug); register_demo!(runner, demo_float_reciprocal_round_ref); register_demo!(runner, demo_float_reciprocal_round_ref_debug); register_demo!(runner, demo_float_reciprocal_round_assign); register_demo!(runner, demo_float_reciprocal_round_assign_debug); register_demo!(runner, demo_float_reciprocal_prec_round); register_demo!(runner, demo_float_reciprocal_prec_round_debug); register_demo!(runner, demo_float_reciprocal_prec_round_extreme); register_demo!(runner, demo_float_reciprocal_prec_round_extreme_debug); register_demo!(runner, demo_float_reciprocal_prec_round_ref); register_demo!(runner, demo_float_reciprocal_prec_round_ref_debug); register_demo!(runner, demo_float_reciprocal_prec_round_assign); register_demo!(runner, demo_float_reciprocal_prec_round_assign_debug); register_bench!(runner, benchmark_float_reciprocal_evaluation_strategy); register_bench!(runner, benchmark_float_reciprocal_library_comparison); register_bench!(runner, benchmark_float_reciprocal_algorithms); register_bench!(runner, benchmark_float_reciprocal_assign); register_bench!(runner, benchmark_float_reciprocal_prec_evaluation_strategy); register_bench!(runner, benchmark_float_reciprocal_prec_library_comparison); register_bench!(runner, benchmark_float_reciprocal_prec_algorithms); register_bench!(runner, benchmark_float_reciprocal_prec_assign); register_bench!(runner, benchmark_float_reciprocal_round_evaluation_strategy); register_bench!(runner, benchmark_float_reciprocal_round_library_comparison); register_bench!(runner, benchmark_float_reciprocal_round_algorithms); register_bench!(runner, benchmark_float_reciprocal_round_assign); register_bench!( runner, benchmark_float_reciprocal_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_prec_round_library_comparison ); register_bench!(runner, benchmark_float_reciprocal_prec_round_algorithms); register_bench!(runner, benchmark_float_reciprocal_prec_round_assign); } fn demo_float_reciprocal(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).reciprocal() = {}", x_old, x.reciprocal()); } } fn demo_float_reciprocal_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).reciprocal() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.reciprocal()) ); } } fn demo_float_reciprocal_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).reciprocal() = {}", x_old, x.reciprocal()); } } fn demo_float_reciprocal_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).reciprocal() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.reciprocal()) ); } } fn demo_float_reciprocal_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("(&{}).reciprocal() = {}", x, (&x).reciprocal()); } } fn demo_float_reciprocal_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "(&{:#x}).reciprocal() = {:#x}", ComparableFloatRef(&x), ComparableFloat((&x).reciprocal()) ); } } fn demo_float_reciprocal_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_assign(); println!("x := {x_old}; x.reciprocal_assign(); x = {x}"); } } fn demo_float_reciprocal_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_assign(); println!( "x := {:#x}; x.reciprocal_assign(); x = {:#x}", ComparableFloat(x_old), ComparableFloat(x) ); } } fn demo_float_reciprocal_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_prec({}) = {:?}", x_old, prec, x.reciprocal_prec(prec) ); } } fn demo_float_reciprocal_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_prec(prec); println!( "({:#x}).reciprocal_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_prec({}) = {:?}", x_old, prec, x.reciprocal_prec(prec) ); } } fn demo_float_reciprocal_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_prec(prec); println!( "({:#x}).reciprocal_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { println!( "(&{}).reciprocal_prec_ref({}) = {:?}", x, prec, x.reciprocal_prec_ref(prec) ); } } fn demo_float_reciprocal_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (sum, o) = x.reciprocal_prec_ref(prec); println!( "(&{:#x}).reciprocal_prec_ref({}) = ({:#x}, {:?})", ComparableFloat(x), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_prec_assign(prec); println!("x := {x_old}; x.reciprocal_prec_assign({prec}); x = {x}"); } } fn demo_float_reciprocal_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let o = x.reciprocal_prec_assign(prec); println!( "x := {:#x}; x.reciprocal_prec_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, o, ComparableFloat(x) ); } } fn demo_float_reciprocal_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_round({}) = {:?}", x_old, rm, x.reciprocal_round(rm) ); } } fn demo_float_reciprocal_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_round(rm); println!( "({:#x}).reciprocal_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_round({}) = {:?}", x_old, rm, x.reciprocal_round(rm) ); } } fn demo_float_reciprocal_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_23() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_round(rm); println!( "({:#x}).reciprocal_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { println!( "(&{}).reciprocal_round_ref({}) = {:?}", x, rm, x.reciprocal_round_ref(rm) ); } } fn demo_float_reciprocal_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { let (sum, o) = x.reciprocal_round_ref(rm); println!( "(&{:#x}).reciprocal_round_ref({}) = ({:#x}, {:?})", ComparableFloat(x), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); x.reciprocal_round_assign(rm); println!("x := {x_old}; x.reciprocal_round_assign({rm}); x = {x}"); } } fn demo_float_reciprocal_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_round_assign(rm); println!( "x := {:#x}; x.reciprocal_round_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), rm, o, ComparableFloat(x) ); } } fn demo_float_reciprocal_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_prec_round({}, {}) = {:?}", x_old, prec, rm, x.reciprocal_prec_round(prec, rm) ); } } fn demo_float_reciprocal_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_prec_round(prec, rm); println!( "({:#x}).reciprocal_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_12() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_prec_round({}, {}) = {:?}", x_old, prec, rm, x.reciprocal_prec_round(prec, rm) ); } } fn demo_float_reciprocal_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_12() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_prec_round(prec, rm); println!( "({:#x}).reciprocal_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "({}).reciprocal_prec_round_ref({}, {}) = {:?}", x, prec, rm, x.reciprocal_prec_round_ref(prec, rm) ); } } fn demo_float_reciprocal_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let (sum, o) = x.reciprocal_prec_round_ref(prec, rm); println!( "({:#x}).reciprocal_prec_round_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(x), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_prec_round_assign(prec, rm); println!("x := {x_old}; x.reciprocal_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_reciprocal_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_prec_round_assign(prec, rm); println!( "x := {:#x}; x.reciprocal_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, rm, o, ComparableFloat(x) ); } } fn benchmark_float_reciprocal_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.reciprocal()", &mut |x| no_out!(x.reciprocal())), ("(&Float).reciprocal()", &mut |x| no_out!((&x).reciprocal())), ], ); } fn benchmark_float_reciprocal_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!((&x).reciprocal())), ("rug", &mut |(x, _)| no_out!(rug_reciprocal(&x))), ], ); } fn benchmark_float_reciprocal_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal()", BenchmarkType::Algorithms, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.reciprocal())), ("naive 1", &mut |x| { let xsb = x.significant_bits(); no_out!(reciprocal_prec_round_naive_1(x, xsb, Nearest).0); }), ("naive 2", &mut |x| { let xsb = x.significant_bits(); no_out!(reciprocal_prec_round_naive_2(x, xsb, Nearest).0); }), ], ); } fn benchmark_float_reciprocal_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.reciprocal_assign()", &mut |mut x| { x.reciprocal_assign(); })], ); } fn benchmark_float_reciprocal_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Float.reciprocal_prec(u64)", &mut |(x, prec)| { no_out!(x.reciprocal_prec(prec)); }), ("(&Float).reciprocal_prec_ref(u64)", &mut |(x, prec)| { no_out!(x.reciprocal_prec_ref(prec)); }), ], ); } fn benchmark_float_reciprocal_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec))| { no_out!(x.reciprocal_prec_ref(prec)); }), ("rug", &mut |((x, prec), _)| { no_out!(rug_reciprocal_prec(&x, prec)); }), ], ); } fn benchmark_float_reciprocal_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec(u64)", BenchmarkType::Algorithms, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("default", &mut |(x, prec)| no_out!(x.reciprocal_prec(prec))), ("naive 1", &mut |(x, prec)| { no_out!(reciprocal_prec_round_naive_1(x, prec, Nearest)); }), ("naive 2", &mut |(x, prec)| { no_out!(reciprocal_prec_round_naive_2(x, prec, Nearest)); }), ], ); } fn benchmark_float_reciprocal_prec_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec_assign(u64)", BenchmarkType::Single, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [("Float.reciprocal_prec_assign(u64)", &mut |(mut x, prec)| { no_out!(x.reciprocal_prec_assign(prec)); })], ); } fn benchmark_float_reciprocal_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_round(RoundingMode)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Float.reciprocal_round(RoundingMode)", &mut |(x, rm)| { no_out!(x.reciprocal_round(rm)); }), ( "(&Float).reciprocal_round_ref(RoundingMode)", &mut |(x, rm)| no_out!(x.reciprocal_round_ref(rm)), ), ], ); } fn benchmark_float_reciprocal_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rounding_mode_pair_gen_var_13_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, rm))| { no_out!(x.reciprocal_round_ref(rm)); }), ("rug", &mut |((x, rm), _)| { no_out!(rug_reciprocal_round(&x, rm)); }), ], ); } fn benchmark_float_reciprocal_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_round(RoundingMode)", BenchmarkType::Algorithms, float_rounding_mode_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("default", &mut |(x, rm)| no_out!(x.reciprocal_round(rm))), ("naive 1", &mut |(x, rm)| { let xsb = x.significant_bits(); reciprocal_prec_round_naive_1(x, xsb, rm); }), ("naive 2", &mut |(x, rm)| { let xsb = x.significant_bits(); reciprocal_prec_round_naive_2(x, xsb, rm); }), ], ); } fn benchmark_float_reciprocal_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_round_assign(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [( "Float.reciprocal_round_assign(RoundingMode)", &mut |(mut x, rm)| no_out!(x.reciprocal_round_assign(rm)), )], ); } fn benchmark_float_reciprocal_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ( "Float.reciprocal_prec_round(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.reciprocal_prec_round(prec, rm)), ), ( "(&Float).reciprocal_prec_round_ref(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.reciprocal_prec_round_ref(prec, rm)), ), ], ); } fn benchmark_float_reciprocal_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec, rm))| { no_out!(x.reciprocal_prec_round_ref(prec, rm)); }), ("rug", &mut |((x, prec, rm), _)| { no_out!(rug_reciprocal_prec_round(&x, prec, rm)); }), ], ); } fn benchmark_float_reciprocal_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("default", &mut |(x, prec, rm)| { no_out!(x.reciprocal_prec_round(prec, rm)); }), ("naive 1", &mut |(x, prec, rm)| { no_out!(reciprocal_prec_round_naive_1(x, prec, rm)); }), ("naive 2", &mut |(x, prec, rm)| { no_out!(reciprocal_prec_round_naive_2(x, prec, rm)); }), ], ); } fn benchmark_float_reciprocal_prec_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_prec_round_assign(u64, RoundingMode)", BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [( "Float.reciprocal_prec_round_assign(u64, RoundingMode)", &mut |(mut x, prec, rm)| no_out!(x.reciprocal_prec_round_assign(prec, rm)), )], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/reciprocal_sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ReciprocalSqrt, ReciprocalSqrtAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::reciprocal_sqrt::{ primitive_float_reciprocal_sqrt, primitive_float_reciprocal_sqrt_rational, }; use malachite_float::test_util::arithmetic::reciprocal_sqrt::{ reciprocal_sqrt_rational_prec_round_generic, reciprocal_sqrt_rational_prec_round_simple, rug_reciprocal_sqrt, rug_reciprocal_sqrt_prec, rug_reciprocal_sqrt_prec_round, rug_reciprocal_sqrt_round, }; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, pair_2_pair_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_rounding_mode_pair_gen_var_30, float_rounding_mode_pair_gen_var_30_rm, float_rounding_mode_pair_gen_var_31, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_15, float_unsigned_rounding_mode_triple_gen_var_15_rm, float_unsigned_rounding_mode_triple_gen_var_16, rational_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::test_util::bench::bucketers::{ pair_rational_bit_u64_max_bucketer, rational_bit_bucketer, triple_1_2_rational_bit_u64_max_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_reciprocal_sqrt); register_demo!(runner, demo_float_reciprocal_sqrt_debug); register_demo!(runner, demo_float_reciprocal_sqrt_extreme); register_demo!(runner, demo_float_reciprocal_sqrt_extreme_debug); register_demo!(runner, demo_float_reciprocal_sqrt_ref); register_demo!(runner, demo_float_reciprocal_sqrt_ref_debug); register_demo!(runner, demo_float_reciprocal_sqrt_assign); register_demo!(runner, demo_float_reciprocal_sqrt_assign_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec); register_demo!(runner, demo_float_reciprocal_sqrt_prec_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_extreme); register_demo!(runner, demo_float_reciprocal_sqrt_prec_extreme_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_ref); register_demo!(runner, demo_float_reciprocal_sqrt_prec_ref_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_assign); register_demo!(runner, demo_float_reciprocal_sqrt_prec_assign_debug); register_demo!(runner, demo_float_reciprocal_sqrt_round); register_demo!(runner, demo_float_reciprocal_sqrt_round_debug); register_demo!(runner, demo_float_reciprocal_sqrt_round_extreme); register_demo!(runner, demo_float_reciprocal_sqrt_round_extreme_debug); register_demo!(runner, demo_float_reciprocal_sqrt_round_ref); register_demo!(runner, demo_float_reciprocal_sqrt_round_ref_debug); register_demo!(runner, demo_float_reciprocal_sqrt_round_assign); register_demo!(runner, demo_float_reciprocal_sqrt_round_assign_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_extreme); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_extreme_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_ref); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_ref_debug); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_assign); register_demo!(runner, demo_float_reciprocal_sqrt_prec_round_assign_debug); register_primitive_float_demos!(runner, demo_primitive_float_reciprocal_sqrt); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_debug); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_ref); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_ref_debug); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_round); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_round_debug); register_demo!(runner, demo_float_reciprocal_sqrt_rational_prec_round_ref); register_demo!( runner, demo_float_reciprocal_sqrt_rational_prec_round_ref_debug ); register_primitive_float_demos!(runner, demo_primitive_float_reciprocal_sqrt_rational); register_bench!(runner, benchmark_float_reciprocal_sqrt_evaluation_strategy); register_bench!(runner, benchmark_float_reciprocal_sqrt_library_comparison); register_bench!(runner, benchmark_float_reciprocal_sqrt_assign); register_bench!( runner, benchmark_float_reciprocal_sqrt_prec_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_sqrt_prec_library_comparison ); register_bench!(runner, benchmark_float_reciprocal_sqrt_prec_assign); register_bench!( runner, benchmark_float_reciprocal_sqrt_round_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_sqrt_round_library_comparison ); register_bench!(runner, benchmark_float_reciprocal_sqrt_round_assign); register_bench!( runner, benchmark_float_reciprocal_sqrt_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_sqrt_prec_round_library_comparison ); register_bench!(runner, benchmark_float_reciprocal_sqrt_prec_round_assign); register_primitive_float_benches!(runner, benchmark_primitive_float_reciprocal_sqrt); register_bench!( runner, benchmark_float_reciprocal_sqrt_rational_prec_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_sqrt_rational_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_reciprocal_sqrt_rational_prec_round_algorithms ); register_primitive_float_benches!(runner, benchmark_primitive_float_reciprocal_sqrt_rational); } fn demo_float_reciprocal_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).reciprocal_sqrt() = {}", x_old, x.reciprocal_sqrt()); } } fn demo_float_reciprocal_sqrt_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).reciprocal_sqrt() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.reciprocal_sqrt()) ); } } fn demo_float_reciprocal_sqrt_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).reciprocal_sqrt() = {}", x_old, x.reciprocal_sqrt()); } } fn demo_float_reciprocal_sqrt_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).reciprocal_sqrt() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.reciprocal_sqrt()) ); } } fn demo_float_reciprocal_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("(&{}).reciprocal_sqrt() = {}", x, (&x).reciprocal_sqrt()); } } fn demo_float_reciprocal_sqrt_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "(&{:#x}).reciprocal_sqrt() = {:#x}", ComparableFloatRef(&x), ComparableFloat((&x).reciprocal_sqrt()) ); } } fn demo_float_reciprocal_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_sqrt_assign(); println!("x := {x_old}; x.reciprocal_sqrt_assign(); x = {x}"); } } fn demo_float_reciprocal_sqrt_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_sqrt_assign(); println!( "x := {:#x}; x.reciprocal_sqrt_assign(); x = {:#x}", ComparableFloat(x_old), ComparableFloat(x) ); } } fn demo_float_reciprocal_sqrt_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_prec({}) = {:?}", x_old, prec, x.reciprocal_sqrt_prec(prec) ); } } fn demo_float_reciprocal_sqrt_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_prec(prec); println!( "({:#x}).reciprocal_sqrt_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_prec({}) = {:?}", x_old, prec, x.reciprocal_sqrt_prec(prec) ); } } fn demo_float_reciprocal_sqrt_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_prec(prec); println!( "({:#x}).reciprocal_sqrt_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { println!( "(&{}).reciprocal_sqrt_prec_ref({}) = {:?}", x, prec, x.reciprocal_sqrt_prec_ref(prec) ); } } fn demo_float_reciprocal_sqrt_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (sum, o) = x.reciprocal_sqrt_prec_ref(prec); println!( "(&{:#x}).reciprocal_sqrt_prec_ref({}) = ({:#x}, {:?})", ComparableFloat(x), prec, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.reciprocal_sqrt_prec_assign(prec); println!("x := {x_old}; x.reciprocal_sqrt_prec_assign({prec}); x = {x}"); } } fn demo_float_reciprocal_sqrt_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let o = x.reciprocal_sqrt_prec_assign(prec); println!( "x := {:#x}; x.reciprocal_sqrt_prec_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, o, ComparableFloat(x) ); } } fn demo_float_reciprocal_sqrt_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_round({}) = {:?}", x_old, rm, x.reciprocal_sqrt_round(rm) ); } } fn demo_float_reciprocal_sqrt_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_round(rm); println!( "({:#x}).reciprocal_sqrt_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_31() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_round({}) = {:?}", x_old, rm, x.reciprocal_sqrt_round(rm) ); } } fn demo_float_reciprocal_sqrt_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_31() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_round(rm); println!( "({:#x}).reciprocal_sqrt_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { println!( "(&{}).reciprocal_sqrt_round_ref({}) = {:?}", x, rm, x.reciprocal_sqrt_round_ref(rm) ); } } fn demo_float_reciprocal_sqrt_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { let (sum, o) = x.reciprocal_sqrt_round_ref(rm); println!( "(&{:#x}).reciprocal_sqrt_round_ref({}) = ({:#x}, {:?})", ComparableFloat(x), rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); x.reciprocal_sqrt_round_assign(rm); println!("x := {x_old}; x.reciprocal_sqrt_round_assign({rm}); x = {x}"); } } fn demo_float_reciprocal_sqrt_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_sqrt_round_assign(rm); println!( "x := {:#x}; x.reciprocal_sqrt_round_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), rm, o, ComparableFloat(x) ); } } fn demo_float_reciprocal_sqrt_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_prec_round({}, {}) = {:?}", x_old, prec, rm, x.reciprocal_sqrt_prec_round(prec, rm) ); } } fn demo_float_reciprocal_sqrt_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_prec_round(prec, rm); println!( "({:#x}).reciprocal_sqrt_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).reciprocal_sqrt_prec_round({}, {}) = {:?}", x_old, prec, rm, x.reciprocal_sqrt_prec_round(prec, rm) ); } } fn demo_float_reciprocal_sqrt_prec_round_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_16() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.reciprocal_sqrt_prec_round(prec, rm); println!( "({:#x}).reciprocal_sqrt_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { println!( "({}).reciprocal_sqrt_prec_round_ref({}, {}) = {:?}", x, prec, rm, x.reciprocal_sqrt_prec_round_ref(prec, rm) ); } } fn demo_float_reciprocal_sqrt_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { let (sum, o) = x.reciprocal_sqrt_prec_round_ref(prec, rm); println!( "({:#x}).reciprocal_sqrt_prec_round_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(x), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_reciprocal_sqrt_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_sqrt_prec_round_assign(prec, rm); println!("x := {x_old}; x.reciprocal_sqrt_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_reciprocal_sqrt_prec_round_assign_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_15() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.reciprocal_sqrt_prec_round_assign(prec, rm); println!( "x := {:#x}; x.reciprocal_sqrt_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_reciprocal_sqrt( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "primitive_float_reciprocal_sqrt({}) = {}", NiceFloat(x), NiceFloat(primitive_float_reciprocal_sqrt(x)) ); } } fn demo_float_reciprocal_sqrt_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::reciprocal_sqrt_rational_prec({}, {}) = {:?}", n.clone(), p, Float::reciprocal_sqrt_rational_prec(n, p) ); } } fn demo_float_reciprocal_sqrt_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::reciprocal_sqrt_rational_prec(n.clone(), p); println!( "Float::reciprocal_sqrt_rational_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_reciprocal_sqrt_rational_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::reciprocal_sqrt_rational_prec_ref(&{}, {}) = {:?}", n, p, Float::reciprocal_sqrt_rational_prec_ref(&n, p) ); } } fn demo_float_reciprocal_sqrt_rational_prec_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::reciprocal_sqrt_rational_prec_ref(&n, p); println!( "Float::reciprocal_sqrt_rational_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_reciprocal_sqrt_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "Float::reciprocal_sqrt_rational_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::reciprocal_sqrt_rational_prec_round(n, p, rm) ); } } fn demo_float_reciprocal_sqrt_rational_prec_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let (f, o) = Float::reciprocal_sqrt_rational_prec_round(n.clone(), p, rm); println!( "Float::reciprocal_sqrt_rational_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_reciprocal_sqrt_rational_prec_round_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "Float::reciprocal_sqrt_rational_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::reciprocal_sqrt_rational_prec_round_ref(&n, p, rm) ); } } fn demo_float_reciprocal_sqrt_rational_prec_round_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let (f, o) = Float::reciprocal_sqrt_rational_prec_round_ref(&n, p, rm); println!( "Float::reciprocal_sqrt_rational_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_reciprocal_sqrt_rational( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for x in rational_gen().get(gm, config).take(limit) { println!( "primitive_float_reciprocal_sqrt_rational({}) = {:?}", x, NiceFloat(primitive_float_reciprocal_sqrt_rational::(&x)) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_reciprocal_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.reciprocal_sqrt()", &mut |x| { no_out!(x.reciprocal_sqrt()); }), ("(&Float).reciprocal_sqrt()", &mut |x| { no_out!((&x).reciprocal_sqrt()); }), ], ); } fn benchmark_float_reciprocal_sqrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!((&x).reciprocal_sqrt())), ("rug", &mut |(x, _)| no_out!(rug_reciprocal_sqrt(&x))), ], ); } fn benchmark_float_reciprocal_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.reciprocal_sqrt_assign()", &mut |mut x| { x.reciprocal_sqrt_assign(); })], ); } fn benchmark_float_reciprocal_sqrt_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Float.reciprocal_sqrt_prec(u64)", &mut |(x, prec)| { no_out!(x.reciprocal_sqrt_prec(prec)); }), ( "(&Float).reciprocal_sqrt_prec_ref(u64)", &mut |(x, prec)| { no_out!(x.reciprocal_sqrt_prec_ref(prec)); }, ), ], ); } fn benchmark_float_reciprocal_sqrt_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec))| { no_out!(x.reciprocal_sqrt_prec_ref(prec)); }), ("rug", &mut |((x, prec), _)| { no_out!(rug_reciprocal_sqrt_prec(&x, prec)); }), ], ); } fn benchmark_float_reciprocal_sqrt_prec_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec_assign(u64)", BenchmarkType::Single, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [("Float.reciprocal_sqrt_prec_assign(u64)", &mut |( mut x, prec, )| { no_out!(x.reciprocal_sqrt_prec_assign(prec)); })], ); } fn benchmark_float_reciprocal_sqrt_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_round(RoundingMode)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_30().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ( "Float.reciprocal_sqrt_round(RoundingMode)", &mut |(x, rm)| { no_out!(x.reciprocal_sqrt_round(rm)); }, ), ( "(&Float).reciprocal_sqrt_round_ref(RoundingMode)", &mut |(x, rm)| { no_out!(x.reciprocal_sqrt_round_ref(rm)); }, ), ], ); } fn benchmark_float_reciprocal_sqrt_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_round(RoundingMode)", BenchmarkType::LibraryComparison, float_rounding_mode_pair_gen_var_30_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, rm))| { no_out!(x.reciprocal_sqrt_round_ref(rm)); }), ("rug", &mut |((x, rm), _)| { no_out!(rug_reciprocal_sqrt_round(&x, rm)); }), ], ); } fn benchmark_float_reciprocal_sqrt_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_round_assign(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen_var_30().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [( "Float.reciprocal_sqrt_round_assign(RoundingMode)", &mut |(mut x, rm)| { no_out!(x.reciprocal_sqrt_round_assign(rm)); }, )], ); } fn benchmark_float_reciprocal_sqrt_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_15().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ( "Float.reciprocal_sqrt_prec_round(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.reciprocal_sqrt_prec_round(prec, rm)), ), ( "(&Float).reciprocal_sqrt_prec_round_ref(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.reciprocal_sqrt_prec_round_ref(prec, rm)), ), ], ); } fn benchmark_float_reciprocal_sqrt_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_15_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec, rm))| { no_out!(x.reciprocal_sqrt_prec_round_ref(prec, rm)); }), ("rug", &mut |((x, prec, rm), _)| { no_out!(rug_reciprocal_sqrt_prec_round(&x, prec, rm)); }), ], ); } fn benchmark_float_reciprocal_sqrt_prec_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.reciprocal_sqrt_prec_round_assign(u64, RoundingMode)", BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_15().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [( "Float.reciprocal_sqrt_prec_round_assign(u64, RoundingMode)", &mut |(mut x, prec, rm)| no_out!(x.reciprocal_sqrt_prec_round_assign(prec, rm)), )], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_reciprocal_sqrt( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!("primitive_float_reciprocal_sqrt({})", T::NAME), BenchmarkType::EvaluationStrategy, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [("malachite", &mut |x| { no_out!(primitive_float_reciprocal_sqrt(x)); })], ); } fn benchmark_float_reciprocal_sqrt_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::reciprocal_sqrt_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::reciprocal_sqrt_rational_prec(Rational, u64)", &mut |(n, prec)| no_out!(Float::reciprocal_sqrt_rational_prec(n, prec)), ), ( "Float::reciprocal_sqrt_rational_prec_ref(&Rational, u64)", &mut |(n, prec)| no_out!(Float::reciprocal_sqrt_rational_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_reciprocal_sqrt_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::reciprocal_sqrt_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::reciprocal_sqrt_rational_prec(Rational, u64, RoundingMode)", &mut |(n, prec, rm)| { no_out!(Float::reciprocal_sqrt_rational_prec_round(n, prec, rm)); }, ), ( "Float::reciprocal_sqrt_rational_prec_ref(&Rational, u64, RoundingMode)", &mut |(n, prec, rm)| { no_out!(Float::reciprocal_sqrt_rational_prec_round_ref(&n, prec, rm)); }, ), ], ); } fn benchmark_float_reciprocal_sqrt_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::reciprocal_sqrt_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("default", &mut |(n, prec, rm)| { no_out!(Float::reciprocal_sqrt_rational_prec_round_ref(&n, prec, rm)); }), ("generic", &mut |(n, prec, rm)| { no_out!(reciprocal_sqrt_rational_prec_round_generic(&n, prec, rm)); }), ("simple", &mut |(n, prec, rm)| { no_out!(reciprocal_sqrt_rational_prec_round_simple(&n, prec, rm)); }), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_reciprocal_sqrt_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!( "primitive_float_reciprocal_sqrt_rational::<{}>(Rational)", T::NAME ), BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(primitive_float_reciprocal_sqrt_rational::(&x)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::shl::shl_naive; use malachite_float::test_util::bench::bucketers::{ pair_1_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen_var_2, float_signed_pair_gen_var_2_rm, float_signed_pair_gen_var_3, float_unsigned_pair_gen_var_2, float_unsigned_pair_gen_var_2_rm, float_unsigned_pair_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::ops::{Shl, ShlAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_shl_assign_unsigned); register_unsigned_demos!(runner, demo_float_shl_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shl_assign_signed); register_signed_demos!(runner, demo_float_shl_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shl_unsigned); register_unsigned_demos!(runner, demo_float_shl_unsigned_debug); register_unsigned_demos!(runner, demo_float_shl_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shl_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shl_signed); register_signed_demos!(runner, demo_float_shl_signed_debug); register_signed_demos!(runner, demo_float_shl_signed_extreme); register_signed_demos!(runner, demo_float_shl_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shl_unsigned_ref); register_unsigned_demos!(runner, demo_float_shl_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shl_signed_ref); register_signed_demos!(runner, demo_float_shl_signed_ref_debug); register_unsigned_benches!(runner, benchmark_float_shl_assign_unsigned); register_signed_benches!(runner, benchmark_float_shl_assign_signed); register_unsigned_benches!(runner, benchmark_float_shl_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_float_shl_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shl_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shl_signed_algorithms); register_bench!(runner, benchmark_float_shl_assign_u32_library_comparison); register_bench!(runner, benchmark_float_shl_u32_library_comparison); register_bench!(runner, benchmark_float_shl_assign_i32_library_comparison); register_bench!(runner, benchmark_float_shl_i32_library_comparison); } fn demo_float_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlAssign, { for (mut n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= u; println!("x := {n_old}; x <<= {u}; x = {n}"); } } fn demo_float_shl_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlAssign, { for (mut n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= u; println!( "x := {:#x}; x <<= {u}; x = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn demo_float_shl_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: ShlAssign, { for (mut n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= i; println!("x := {n_old}; x <<= {i}; x = {n}"); } } fn demo_float_shl_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlAssign, { for (mut n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= i; println!( "x := {:#x}; x <<= {i}; x = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn demo_float_shl_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, u, n << u); } } fn demo_float_shl_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} << {} = {:#x}", ComparableFloat(n_old), u, ComparableFloat(n << u) ); } } fn demo_float_shl_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, u, n << u); } } fn demo_float_shl_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} << {} = {:#x}", ComparableFloat(n_old), u, ComparableFloat(n << u) ); } } fn demo_float_shl_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shl, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, i, n << i); } } fn demo_float_shl_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shl, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} << {} = {:#x}", ComparableFloat(n_old), i, ComparableFloat(n << i) ); } } fn demo_float_shl_signed_extreme(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shl, { for (n, i) in float_signed_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, i, n << i); } } fn demo_float_shl_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shl, { for (n, i) in float_signed_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} << {} = {:#x}", ComparableFloat(n_old), i, ComparableFloat(n << i) ); } } fn demo_float_shl_unsigned_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, u, &n << u); } } fn demo_float_shl_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: Shl, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "&{:#x} << {} = {:#x}", ComparableFloatRef(&n), u, ComparableFloatRef(&(&n << u)) ); } } fn demo_float_shl_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Float: Shl, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, i, &n << i); } } fn demo_float_shl_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: Shl, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "&{:#x} << {} = {:#x}", ComparableFloatRef(&n), i, ComparableFloatRef(&(&n << i)) ); } } fn benchmark_float_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlAssign, { run_benchmark( &format!("Float <<= {}", T::NAME), BenchmarkType::Single, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n <<= u)], ); } fn benchmark_float_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlAssign, { run_benchmark( &format!("Float <<= {}", T::NAME), BenchmarkType::Single, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n <<= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shl, for<'a> &'a Float: Shl, { run_benchmark( &format!("Float << {}", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ (&format!("Float << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Float << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shl, for<'a> &'a Float: Shl, { run_benchmark( &format!("Float << {}", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ (&format!("Float << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Float << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shl_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shl, Rational: Shl, for<'a> &'a Float: Shl, { run_benchmark( &format!("Float << {}", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(x, y)| no_out!(x << y)), ("naive", &mut |(x, y)| no_out!(shl_naive(x, y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shl_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shl, Rational: Shl, for<'a> &'a Float: Shl, { run_benchmark( &format!("Float << {}", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(x, y)| no_out!(x << y)), ("naive", &mut |(x, y)| no_out!(shl_naive(x, y))), ], ); } fn benchmark_float_shl_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float <<= u32", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_shl_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float << u32", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } fn benchmark_float_shl_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float <<= i32", BenchmarkType::LibraryComparison, float_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_shl_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float << i32", BenchmarkType::LibraryComparison, float_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShlRound, ShlRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::shl_round::{ rug_shl_prec_round_signed, rug_shl_prec_round_unsigned, rug_shl_prec_signed, rug_shl_prec_unsigned, rug_shl_round_signed, rug_shl_round_unsigned, shl_prec_naive, shl_prec_round_naive, shl_round_naive, }; use malachite_float::test_util::bench::bucketers::{ pair_2_quadruple_1_float_complexity_bucketer, pair_2_triple_1_float_complexity_bucketer, quadruple_1_float_complexity_bucketer, triple_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_rounding_mode_triple_gen_var_1, float_signed_rounding_mode_triple_gen_var_2, float_signed_rounding_mode_triple_gen_var_3_rm, float_signed_unsigned_rounding_mode_quadruple_gen_var_1, float_signed_unsigned_rounding_mode_quadruple_gen_var_1_rm, float_signed_unsigned_rounding_mode_quadruple_gen_var_2, float_signed_unsigned_triple_gen_var_1, float_signed_unsigned_triple_gen_var_1_rm, float_signed_unsigned_triple_gen_var_2, float_unsigned_rounding_mode_triple_gen_var_5, float_unsigned_rounding_mode_triple_gen_var_6, float_unsigned_rounding_mode_triple_gen_var_7_rm, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1_rm, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2, float_unsigned_unsigned_triple_gen_var_1, float_unsigned_unsigned_triple_gen_var_1_rm, float_unsigned_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::ops::Shl; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_shl_prec_assign_unsigned); register_unsigned_demos!(runner, demo_float_shl_prec_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shl_prec_assign_signed); register_signed_demos!(runner, demo_float_shl_prec_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned_debug); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shl_prec_signed); register_signed_demos!(runner, demo_float_shl_prec_signed_debug); register_signed_demos!(runner, demo_float_shl_prec_signed_extreme); register_signed_demos!(runner, demo_float_shl_prec_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned_ref); register_unsigned_demos!(runner, demo_float_shl_prec_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shl_prec_signed_ref); register_signed_demos!(runner, demo_float_shl_prec_signed_ref_debug); register_unsigned_demos!(runner, demo_float_shl_prec_round_assign_unsigned); register_unsigned_demos!(runner, demo_float_shl_prec_round_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shl_prec_round_assign_signed); register_signed_demos!(runner, demo_float_shl_prec_round_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned_debug); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shl_prec_round_signed); register_signed_demos!(runner, demo_float_shl_prec_round_signed_debug); register_signed_demos!(runner, demo_float_shl_prec_round_signed_extreme); register_signed_demos!(runner, demo_float_shl_prec_round_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned_ref); register_unsigned_demos!(runner, demo_float_shl_prec_round_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shl_prec_round_signed_ref); register_signed_demos!(runner, demo_float_shl_prec_round_signed_ref_debug); register_unsigned_demos!(runner, demo_float_shl_round_assign_unsigned); register_unsigned_demos!(runner, demo_float_shl_round_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shl_round_assign_signed); register_signed_demos!(runner, demo_float_shl_round_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shl_round_unsigned); register_unsigned_demos!(runner, demo_float_shl_round_unsigned_debug); register_unsigned_demos!(runner, demo_float_shl_round_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shl_round_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shl_round_signed); register_signed_demos!(runner, demo_float_shl_round_signed_debug); register_signed_demos!(runner, demo_float_shl_round_signed_extreme); register_signed_demos!(runner, demo_float_shl_round_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shl_round_unsigned_ref); register_unsigned_demos!(runner, demo_float_shl_round_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shl_round_signed_ref); register_signed_demos!(runner, demo_float_shl_round_signed_ref_debug); register_unsigned_benches!(runner, benchmark_float_shl_prec_assign_unsigned); register_signed_benches!(runner, benchmark_float_shl_prec_assign_signed); register_unsigned_benches!( runner, benchmark_float_shl_prec_unsigned_evaluation_strategy ); register_signed_benches!(runner, benchmark_float_shl_prec_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shl_prec_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shl_prec_signed_algorithms); register_bench!( runner, benchmark_float_shl_prec_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shl_prec_assign_i32_library_comparison ); register_unsigned_benches!(runner, benchmark_float_shl_prec_round_assign_unsigned); register_signed_benches!(runner, benchmark_float_shl_prec_round_assign_signed); register_unsigned_benches!( runner, benchmark_float_shl_prec_round_unsigned_evaluation_strategy ); register_signed_benches!( runner, benchmark_float_shl_prec_round_signed_evaluation_strategy ); register_unsigned_benches!(runner, benchmark_float_shl_prec_round_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shl_prec_round_signed_algorithms); register_bench!( runner, benchmark_float_shl_prec_round_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shl_prec_round_assign_i32_library_comparison ); register_unsigned_benches!(runner, benchmark_float_shl_round_assign_unsigned); register_signed_benches!(runner, benchmark_float_shl_round_assign_signed); register_unsigned_benches!( runner, benchmark_float_shl_round_unsigned_evaluation_strategy ); register_signed_benches!(runner, benchmark_float_shl_round_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shl_round_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shl_round_signed_algorithms); register_bench!( runner, benchmark_float_shl_round_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shl_round_assign_i32_library_comparison ); } fn demo_float_shl_prec_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_assign(u, prec); println!("x := {n_old}; x.shl_prec_assign({u}, {prec}) = {o:?}; x = {n}"); } } fn demo_float_shl_prec_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_assign(u, prec); println!( "x := {:#x}; x.shl_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, o, ComparableFloat(n) ); } } fn demo_float_shl_prec_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_assign(u, prec); println!("x := {n_old}; x.shl_prec_assign({u}, {prec}) = {o:?}; x = {n}"); } } fn demo_float_shl_prec_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_assign(u, prec); println!( "x := {:#x}; x.shl_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, o, ComparableFloat(n) ); } } fn demo_float_shl_prec_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec({}, {}) = {:?}", n_old, u, prec, n.shl_prec(u, prec) ); } } fn demo_float_shl_prec_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec(u, prec); println!( "{:#x}.shl_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec({}, {}) = {:?}", n_old, u, prec, n.shl_prec(u, prec) ); } } fn demo_float_shl_prec_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec(u, prec); println!( "{:#x}.shl_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec({}, {}) = {:?}", n_old, u, prec, n.shl_prec(u, prec) ); } } fn demo_float_shl_prec_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec(u, prec); println!( "{:#x}.shl_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec({}, {}) = {:?}", n_old, u, prec, n.shl_prec(u, prec) ); } } fn demo_float_shl_prec_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec(u, prec); println!( "{:#x}.shl_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shl_prec_ref({}, {}) = {:?}", n, u, prec, n.shl_prec_ref(u, prec) ); } } fn demo_float_shl_prec_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shl_prec_ref(u, prec); println!( "{:#x}.shl_prec_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shl_prec_ref({}, {}) = {:?}", n, u, prec, n.shl_prec_ref(u, prec) ); } } fn demo_float_shl_prec_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shl_prec_ref(u, prec); println!( "{:#x}.shl_prec_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_round_assign(u, prec, rm); println!("x := {n_old}; x.shl_prec_round_assign({u}, {prec}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shl_prec_round_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_round_assign(u, prec, rm); println!( "x := {:#x}; x.shl_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, rm, o, ComparableFloat(n) ); } } fn demo_float_shl_prec_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_round_assign(u, prec, rm); println!("x := {n_old}; x.shl_prec_round_assign({u}, {prec}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shl_prec_round_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_prec_round_assign(u, prec, rm); println!( "x := {:#x}; x.shl_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, rm, o, ComparableFloat(n) ); } } fn demo_float_shl_prec_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shl_prec_round(u, prec, rm) ); } } fn demo_float_shl_prec_round_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec_round(u, prec, rm); println!( "{:#x}.shl_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shl_prec_round(u, prec, rm) ); } } fn demo_float_shl_prec_round_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec_round(u, prec, rm); println!( "{:#x}.shl_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shl_prec_round(u, prec, rm) ); } } fn demo_float_shl_prec_round_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec_round(u, prec, rm); println!( "{:#x}.shl_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shl_prec_round(u, prec, rm) ); } } fn demo_float_shl_prec_round_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_prec_round(u, prec, rm); println!( "{:#x}.shl_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shl_prec_round_ref({}, {}, {}) = {:?}", n, u, prec, rm, n.shl_prec_round_ref(u, prec, rm) ); } } fn demo_float_shl_prec_round_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shl_prec_round_ref(u, prec, rm); println!( "{:#x}.shl_prec_round_ref({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_prec_round_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shl_prec_round_ref({}, {}, {}) = {:?}", n, u, prec, rm, n.shl_prec_round_ref(u, prec, rm) ); } } fn demo_float_shl_prec_round_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shl_prec_round_ref(u, prec, rm); println!( "{:#x}.shl_prec_round_ref({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRoundAssign, { for (mut n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(u, rm); println!("x := {n_old}; x.shl_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shl_round_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRoundAssign, { for (mut n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(u, rm); println!( "x := {:#x}; x.shl_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, rm, o, ComparableFloat(n) ); } } fn demo_float_shl_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRoundAssign, { for (mut n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(i, rm); println!("x := {n_old}; x.shl_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shl_round_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRoundAssign, { for (mut n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(i, rm); println!( "x := {:#x}; x.shl_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), i, rm, o, ComparableFloat(n) ); } } fn demo_float_shl_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, u, rm, n.shl_round(u, rm) ); } } fn demo_float_shl_round_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_round(u, rm); println!( "{:#x}.shl_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_round_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, u, rm, n.shl_round(u, rm) ); } } fn demo_float_shl_round_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_round(u, rm); println!( "{:#x}.shl_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_round_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, i, rm, n.shl_round(i, rm) ); } } fn demo_float_shl_round_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_round(i, rm); println!( "{:#x}.shl_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), i, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_round_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, i, rm, n.shl_round(i, rm) ); } } fn demo_float_shl_round_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shl_round(i, rm); println!( "{:#x}.shl_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), i, rm, ComparableFloat(shifted), o ); } } fn demo_float_shl_round_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { println!( "(&{}).shl_round({}, {}) = {:?}", n, u, rm, (&n).shl_round(u, rm) ); } } fn demo_float_shl_round_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShlRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let (shifted, o) = (&n).shl_round(u, rm); println!( "(&{:#x}.shl_round({}, {}) = ({:#x}, {:?})", ComparableFloatRef(&n), u, rm, ComparableFloatRef(&shifted), o ); } } fn demo_float_shl_round_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).shl_round({}, {}) = {:?}", n, i, rm, (&n).shl_round(i, rm) ); } } fn demo_float_shl_round_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShlRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = (&n).shl_round(i, rm); println!( "(&{:#x}).shl_round({}, {}) = ({:#x}, {:?})", ComparableFloatRef(&n), i, rm, ComparableFloatRef(&shifted), o ); } } fn benchmark_float_shl_prec_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec_assign({}, u64)", T::NAME), BenchmarkType::Single, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec)| { no_out!(n.shl_prec_assign(u, prec)); })], ); } fn benchmark_float_shl_prec_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec_assign({}, u64)", T::NAME), BenchmarkType::Single, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec)| { no_out!(n.shl_prec_assign(u, prec)); })], ); } fn benchmark_float_shl_prec_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_prec({}, u64)", T::NAME), &mut |(n, u, prec)| no_out!(n.shl_prec(u, prec)), ), ( &format!("Float.shl_prec_ref({}, u64)", T::NAME), &mut |(n, u, prec)| no_out!(n.shl_prec_ref(u, prec)), ), ], ); } fn benchmark_float_shl_prec_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_prec({}, u64)", T::NAME), &mut |(n, i, prec)| no_out!(n.shl_prec(i, prec)), ), ( &format!("Float.shl_prec_ref({}, u64)", T::NAME), &mut |(n, i, prec)| no_out!(n.shl_prec_ref(i, prec)), ), ], ); } fn benchmark_float_shl_prec_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, { run_benchmark( &format!("Float.shl_prec({}, u64)", T::NAME), BenchmarkType::Algorithms, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec)| no_out!(n.shl_prec(u, prec))), ("naive", &mut |(n, u, prec)| { no_out!(shl_prec_naive(n, u, prec)); }), ], ); } fn benchmark_float_shl_prec_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, { run_benchmark( &format!("Float.shl_prec({}, u64)", T::NAME), BenchmarkType::Algorithms, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec)| no_out!(n.shl_prec(u, prec))), ("naive", &mut |(n, u, prec)| { no_out!(shl_prec_naive(n, u, prec)); }), ], ); } fn benchmark_float_shl_prec_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_prec(i32, u64)", BenchmarkType::LibraryComparison, float_unsigned_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, prec))| { no_out!(n.shl_prec(u, prec)); }), ("rug", &mut |((n, u, prec), _)| { no_out!(rug_shl_prec_unsigned(&n, u, prec)); }), ], ); } fn benchmark_float_shl_prec_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_prec(i32, u64)", BenchmarkType::LibraryComparison, float_signed_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, prec))| { no_out!(n.shl_prec(i, prec)); }), ("rug", &mut |((n, i, prec), _)| { no_out!(rug_shl_prec_signed(&n, i, prec)); }), ], ); } fn benchmark_float_shl_prec_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "Float.shl_prec_round_assign({}, u64, RoundingMode)", T::NAME ), BenchmarkType::Single, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec, rm)| { no_out!(n.shl_prec_round_assign(u, prec, rm)); })], ); } fn benchmark_float_shl_prec_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "Float.shl_prec_round_assign({}, u64, RoundingMode)", T::NAME ), BenchmarkType::Single, float_signed_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec, rm)| { no_out!(n.shl_prec_round_assign(u, prec, rm)); })], ); } fn benchmark_float_shl_prec_round_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), &mut |(n, u, prec, rm)| no_out!(n.shl_prec_round(u, prec, rm)), ), ( &format!("Float.shl_prec_round_ref({}, u64, RoundingMode)", T::NAME), &mut |(n, u, prec, rm)| no_out!(n.shl_prec_round_ref(u, prec, rm)), ), ], ); } fn benchmark_float_shl_prec_round_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), &mut |(n, i, prec, rm)| no_out!(n.shl_prec_round(i, prec, rm)), ), ( &format!("Float.shl_prec_round_ref({}, u64, RoundingMode)", T::NAME), &mut |(n, i, prec, rm)| no_out!(n.shl_prec_round_ref(i, prec, rm)), ), ], ); } fn benchmark_float_shl_prec_round_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, { run_benchmark( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec, rm)| { no_out!(n.shl_prec_round(u, prec, rm)); }), ("naive", &mut |(n, u, prec, rm)| { no_out!(shl_prec_round_naive(n, u, prec, rm)); }), ], ); } fn benchmark_float_shl_prec_round_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, { run_benchmark( &format!("Float.shl_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_signed_unsigned_rounding_mode_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec, rm)| { no_out!(n.shl_prec_round(u, prec, rm)); }), ("naive", &mut |(n, u, prec, rm)| { no_out!(shl_prec_round_naive(n, u, prec, rm)); }), ], ); } fn benchmark_float_shl_prec_round_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_prec_round(i32, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, prec, rm))| { no_out!(n.shl_prec_round(u, prec, rm)); }), ("rug", &mut |((n, u, prec, rm), _)| { no_out!(rug_shl_prec_round_unsigned(&n, u, prec, rm)); }), ], ); } fn benchmark_float_shl_prec_round_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_prec_round(i32, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_signed_unsigned_rounding_mode_quadruple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, prec, rm))| { no_out!(n.shl_prec_round(i, prec, rm)); }), ("rug", &mut |((n, i, prec, rm), _)| { no_out!(rug_shl_prec_round_signed(&n, i, prec, rm)); }), ], ); } fn benchmark_float_shl_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRoundAssign, { run_benchmark( &format!("Float.shl_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shl_round_assign(u, rm)); })], ); } fn benchmark_float_shl_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRoundAssign, { run_benchmark( &format!("Float.shl_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, float_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shl_round_assign(u, rm)); })], ); } fn benchmark_float_shl_round_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRound, for<'a> &'a Float: ShlRound, { run_benchmark( &format!("Float.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_round({}, RoundingMode)", T::NAME), &mut |(n, u, rm)| no_out!(n.shl_round(u, rm)), ), ( &format!("(&Float).shl_round({}, RoundingMode)", T::NAME), &mut |(n, u, rm)| no_out!((&n).shl_round(u, rm)), ), ], ); } fn benchmark_float_shl_round_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRound, for<'a> &'a Float: ShlRound, { run_benchmark( &format!("Float.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shl_round({}, RoundingMode)", T::NAME), &mut |(n, i, rm)| no_out!(n.shl_round(i, rm)), ), ( &format!("(&Float).shl_round({}, RoundingMode)", T::NAME), &mut |(n, i, rm)| no_out!((&n).shl_round(i, rm)), ), ], ); } fn benchmark_float_shl_round_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { run_benchmark( &format!("Float.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_unsigned_rounding_mode_triple_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, rm)| no_out!(n.shl_round(u, rm))), ("naive", &mut |(n, u, rm)| { no_out!(shl_round_naive(n, u, rm)); }), ], ); } fn benchmark_float_shl_round_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { run_benchmark( &format!("Float.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, rm)| no_out!(n.shl_round(u, rm))), ("naive", &mut |(n, u, rm)| { no_out!(shl_round_naive(n, u, rm)); }), ], ); } fn benchmark_float_shl_round_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_round(i32, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_7_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, rm))| { no_out!((&n).shl_round(u, rm)); }), ("rug", &mut |((n, u, rm), _)| { no_out!(rug_shl_round_unsigned(&n, u, rm)); }), ], ); } fn benchmark_float_shl_round_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shl_round(i32, RoundingMode)", BenchmarkType::LibraryComparison, float_signed_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, rm))| { no_out!((&n).shl_round(i, rm)); }), ("rug", &mut |((n, i, rm), _)| { no_out!(rug_shl_round_signed(&n, i, rm)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::shr::shr_naive; use malachite_float::test_util::bench::bucketers::{ pair_1_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen_var_2, float_signed_pair_gen_var_2_rm, float_signed_pair_gen_var_3, float_unsigned_pair_gen_var_2, float_unsigned_pair_gen_var_2_rm, float_unsigned_pair_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::ops::{Shr, ShrAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_shr_assign_unsigned); register_unsigned_demos!(runner, demo_float_shr_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shr_assign_signed); register_signed_demos!(runner, demo_float_shr_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shr_unsigned); register_unsigned_demos!(runner, demo_float_shr_unsigned_debug); register_unsigned_demos!(runner, demo_float_shr_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shr_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shr_signed); register_signed_demos!(runner, demo_float_shr_signed_debug); register_signed_demos!(runner, demo_float_shr_signed_extreme); register_signed_demos!(runner, demo_float_shr_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shr_unsigned_ref); register_unsigned_demos!(runner, demo_float_shr_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shr_signed_ref); register_signed_demos!(runner, demo_float_shr_signed_ref_debug); register_unsigned_benches!(runner, benchmark_float_shr_assign_unsigned); register_signed_benches!(runner, benchmark_float_shr_assign_signed); register_unsigned_benches!(runner, benchmark_float_shr_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_float_shr_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shr_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shr_signed_algorithms); register_bench!(runner, benchmark_float_shr_assign_u32_library_comparison); register_bench!(runner, benchmark_float_shr_u32_library_comparison); register_bench!(runner, benchmark_float_shr_assign_i32_library_comparison); register_bench!(runner, benchmark_float_shr_i32_library_comparison); } fn demo_float_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrAssign, { for (mut n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!("x := {n_old}; x >>= {u}; x = {n}"); } } fn demo_float_shr_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrAssign, { for (mut n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!( "x := {:#x}; x >>= {u}; x = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn demo_float_shr_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: ShrAssign, { for (mut n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= i; println!("x := {n_old}; x >>= {i}; x = {n}"); } } fn demo_float_shr_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrAssign, { for (mut n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= i; println!( "x := {:#x}; x >>= {i}; x = {:#x}", ComparableFloat(n_old), ComparableFloat(n) ); } } fn demo_float_shr_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_float_shr_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} >> {} = {:#x}", ComparableFloat(n_old), u, ComparableFloat(n >> u) ); } } fn demo_float_shr_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_float_shr_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} >> {} = {:#x}", ComparableFloat(n_old), u, ComparableFloat(n >> u) ); } } fn demo_float_shr_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shr, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, i, n >> i); } } fn demo_float_shr_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shr, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} >> {} = {:#x}", ComparableFloat(n_old), i, ComparableFloat(n >> i) ); } } fn demo_float_shr_signed_extreme(gm: GenMode, config: &GenConfig, limit: usize) where Float: Shr, { for (n, i) in float_signed_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, i, n >> i); } } fn demo_float_shr_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: Shr, { for (n, i) in float_signed_pair_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{:#x} >> {} = {:#x}", ComparableFloat(n_old), i, ComparableFloat(n >> i) ); } } fn demo_float_shr_unsigned_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, u, &n >> u); } } fn demo_float_shr_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: Shr, { for (n, u) in float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "&{:#x} >> {} = {:#x}", ComparableFloatRef(&n), u, ComparableFloatRef(&(&n >> u)) ); } } fn demo_float_shr_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Float: Shr, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, i, &n >> i); } } fn demo_float_shr_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: Shr, { for (n, i) in float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "&{:#x} >> {} = {:#x}", ComparableFloatRef(&n), i, ComparableFloatRef(&(&n >> i)) ); } } fn benchmark_float_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrAssign, { run_benchmark( &format!("Float >>= {}", T::NAME), BenchmarkType::Single, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n >>= u)], ); } fn benchmark_float_shr_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrAssign, { run_benchmark( &format!("Float >>= {}", T::NAME), BenchmarkType::Single, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n >>= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shr_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shr, for<'a> &'a Float: Shr, { run_benchmark( &format!("Float >> {}", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ (&format!("Float >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Float >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shr_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shr, for<'a> &'a Float: Shr, { run_benchmark( &format!("Float >> {}", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ (&format!("Float >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Float >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shr_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shr, Rational: Shr, for<'a> &'a Float: Shr, { run_benchmark( &format!("Float >> {}", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(x, y)| no_out!(x >> y)), ("naive", &mut |(x, y)| no_out!(shr_naive(x, y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_shr_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: Shr, Rational: Shr, for<'a> &'a Float: Shr, { run_benchmark( &format!("Float >> {}", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(x, y)| no_out!(x >> y)), ("naive", &mut |(x, y)| no_out!(shr_naive(x, y))), ], ); } fn benchmark_float_shr_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float >>= u32", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_shr_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float >> u32", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } fn benchmark_float_shr_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float >>= i32", BenchmarkType::LibraryComparison, float_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_shr_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float >> i32", BenchmarkType::LibraryComparison, float_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::shr_round::{ rug_shr_prec_round_signed, rug_shr_prec_round_unsigned, rug_shr_prec_signed, rug_shr_prec_unsigned, rug_shr_round_signed, rug_shr_round_unsigned, shr_prec_naive, shr_prec_round_naive, shr_round_naive, }; use malachite_float::test_util::bench::bucketers::{ pair_2_quadruple_1_float_complexity_bucketer, pair_2_triple_1_float_complexity_bucketer, quadruple_1_float_complexity_bucketer, triple_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_rounding_mode_triple_gen_var_4, float_signed_rounding_mode_triple_gen_var_5, float_signed_rounding_mode_triple_gen_var_6_rm, float_signed_unsigned_rounding_mode_quadruple_gen_var_3, float_signed_unsigned_rounding_mode_quadruple_gen_var_3_rm, float_signed_unsigned_rounding_mode_quadruple_gen_var_4, float_signed_unsigned_triple_gen_var_1, float_signed_unsigned_triple_gen_var_1_rm, float_signed_unsigned_triple_gen_var_2, float_unsigned_rounding_mode_triple_gen_var_8, float_unsigned_rounding_mode_triple_gen_var_9, float_unsigned_rounding_mode_triple_gen_var_10_rm, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3_rm, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4, float_unsigned_unsigned_triple_gen_var_1, float_unsigned_unsigned_triple_gen_var_1_rm, float_unsigned_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::ops::Shr; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_shr_prec_assign_unsigned); register_unsigned_demos!(runner, demo_float_shr_prec_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shr_prec_assign_signed); register_signed_demos!(runner, demo_float_shr_prec_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned_debug); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shr_prec_signed); register_signed_demos!(runner, demo_float_shr_prec_signed_debug); register_signed_demos!(runner, demo_float_shr_prec_signed_extreme); register_signed_demos!(runner, demo_float_shr_prec_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned_ref); register_unsigned_demos!(runner, demo_float_shr_prec_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shr_prec_signed_ref); register_signed_demos!(runner, demo_float_shr_prec_signed_ref_debug); register_unsigned_demos!(runner, demo_float_shr_prec_round_assign_unsigned); register_unsigned_demos!(runner, demo_float_shr_prec_round_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shr_prec_round_assign_signed); register_signed_demos!(runner, demo_float_shr_prec_round_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned_debug); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shr_prec_round_signed); register_signed_demos!(runner, demo_float_shr_prec_round_signed_debug); register_signed_demos!(runner, demo_float_shr_prec_round_signed_extreme); register_signed_demos!(runner, demo_float_shr_prec_round_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned_ref); register_unsigned_demos!(runner, demo_float_shr_prec_round_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shr_prec_round_signed_ref); register_signed_demos!(runner, demo_float_shr_prec_round_signed_ref_debug); register_unsigned_demos!(runner, demo_float_shr_round_assign_unsigned); register_unsigned_demos!(runner, demo_float_shr_round_assign_unsigned_debug); register_signed_demos!(runner, demo_float_shr_round_assign_signed); register_signed_demos!(runner, demo_float_shr_round_assign_signed_debug); register_unsigned_demos!(runner, demo_float_shr_round_unsigned); register_unsigned_demos!(runner, demo_float_shr_round_unsigned_debug); register_unsigned_demos!(runner, demo_float_shr_round_unsigned_extreme); register_unsigned_demos!(runner, demo_float_shr_round_unsigned_extreme_debug); register_signed_demos!(runner, demo_float_shr_round_signed); register_signed_demos!(runner, demo_float_shr_round_signed_debug); register_signed_demos!(runner, demo_float_shr_round_signed_extreme); register_signed_demos!(runner, demo_float_shr_round_signed_extreme_debug); register_unsigned_demos!(runner, demo_float_shr_round_unsigned_ref); register_unsigned_demos!(runner, demo_float_shr_round_unsigned_ref_debug); register_signed_demos!(runner, demo_float_shr_round_signed_ref); register_signed_demos!(runner, demo_float_shr_round_signed_ref_debug); register_unsigned_benches!(runner, benchmark_float_shr_prec_assign_unsigned); register_signed_benches!(runner, benchmark_float_shr_prec_assign_signed); register_unsigned_benches!( runner, benchmark_float_shr_prec_unsigned_evaluation_strategy ); register_signed_benches!(runner, benchmark_float_shr_prec_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shr_prec_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shr_prec_signed_algorithms); register_bench!( runner, benchmark_float_shr_prec_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shr_prec_assign_i32_library_comparison ); register_unsigned_benches!(runner, benchmark_float_shr_prec_round_assign_unsigned); register_signed_benches!(runner, benchmark_float_shr_prec_round_assign_signed); register_unsigned_benches!( runner, benchmark_float_shr_prec_round_unsigned_evaluation_strategy ); register_signed_benches!( runner, benchmark_float_shr_prec_round_signed_evaluation_strategy ); register_unsigned_benches!(runner, benchmark_float_shr_prec_round_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shr_prec_round_signed_algorithms); register_bench!( runner, benchmark_float_shr_prec_round_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shr_prec_round_assign_i32_library_comparison ); register_unsigned_benches!(runner, benchmark_float_shr_round_assign_unsigned); register_signed_benches!(runner, benchmark_float_shr_round_assign_signed); register_unsigned_benches!( runner, benchmark_float_shr_round_unsigned_evaluation_strategy ); register_signed_benches!(runner, benchmark_float_shr_round_signed_evaluation_strategy); register_unsigned_benches!(runner, benchmark_float_shr_round_unsigned_algorithms); register_signed_benches!(runner, benchmark_float_shr_round_signed_algorithms); register_bench!( runner, benchmark_float_shr_round_assign_u32_library_comparison ); register_bench!( runner, benchmark_float_shr_round_assign_i32_library_comparison ); } fn demo_float_shr_prec_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_assign(u, prec); println!("x := {n_old}; x.shr_prec_assign({u}, {prec}) = {o:?}; x = {n}"); } } fn demo_float_shr_prec_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_assign(u, prec); println!( "x := {:#x}; x.shr_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, o, ComparableFloat(n) ); } } fn demo_float_shr_prec_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_assign(u, prec); println!("x := {n_old}; x.shr_prec_assign({u}, {prec}) = {o:?}; x = {n}"); } } fn demo_float_shr_prec_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_assign(u, prec); println!( "x := {:#x}; x.shr_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, o, ComparableFloat(n) ); } } fn demo_float_shr_prec_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec({}, {}) = {:?}", n_old, u, prec, n.shr_prec(u, prec) ); } } fn demo_float_shr_prec_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec(u, prec); println!( "{:#x}.shr_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec({}, {}) = {:?}", n_old, u, prec, n.shr_prec(u, prec) ); } } fn demo_float_shr_prec_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec(u, prec); println!( "{:#x}.shr_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_signed(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec({}, {}) = {:?}", n_old, u, prec, n.shr_prec(u, prec) ); } } fn demo_float_shr_prec_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec(u, prec); println!( "{:#x}.shr_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec({}, {}) = {:?}", n_old, u, prec, n.shr_prec(u, prec) ); } } fn demo_float_shr_prec_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec(u, prec); println!( "{:#x}.shr_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shr_prec_ref({}, {}) = {:?}", n, u, prec, n.shr_prec_ref(u, prec) ); } } fn demo_float_shr_prec_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_unsigned_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shr_prec_ref(u, prec); println!( "{:#x}.shr_prec_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "{}.shr_prec_ref({}, {}) = {:?}", n, u, prec, n.shr_prec_ref(u, prec) ); } } fn demo_float_shr_prec_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec) in float_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let (shifted, o) = n.shr_prec_ref(u, prec); println!( "{:#x}.shr_prec_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_round_assign(u, prec, rm); println!("x := {n_old}; x.shr_prec_round_assign({u}, {prec}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shr_prec_round_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_round_assign(u, prec, rm); println!( "x := {:#x}; x.shr_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, rm, o, ComparableFloat(n) ); } } fn demo_float_shr_prec_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_round_assign(u, prec, rm); println!("x := {n_old}; x.shr_prec_round_assign({u}, {prec}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shr_prec_round_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_prec_round_assign(u, prec, rm); println!( "x := {:#x}; x.shr_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, prec, rm, o, ComparableFloat(n) ); } } fn demo_float_shr_prec_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shr_prec_round(u, prec, rm) ); } } fn demo_float_shr_prec_round_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec_round(u, prec, rm); println!( "{:#x}.shr_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shr_prec_round(u, prec, rm) ); } } fn demo_float_shr_prec_round_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec_round(u, prec, rm); println!( "{:#x}.shr_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_signed( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shr_prec_round(u, prec, rm) ); } } fn demo_float_shr_prec_round_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec_round(u, prec, rm); println!( "{:#x}.shr_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_prec_round({}, {}, {}) = {:?}", n_old, u, prec, rm, n.shr_prec_round(u, prec, rm) ); } } fn demo_float_shr_prec_round_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_prec_round(u, prec, rm); println!( "{:#x}.shr_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.shr_prec_round_ref({}, {}, {}) = {:?}", n, u, prec, rm, n.shr_prec_round_ref(u, prec, rm) ); } } fn demo_float_shr_prec_round_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let (shifted, o) = n.shr_prec_round_ref(u, prec, rm); println!( "{:#x}.shr_prec_round_ref({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_prec_round_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}.shr_prec_round_ref({}, {}, {}) = {:?}", n, u, prec, rm, n.shr_prec_round_ref(u, prec, rm) ); } } fn demo_float_shr_prec_round_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u, prec, rm) in float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .get(gm, config) .take(limit) { let (shifted, o) = n.shr_prec_round_ref(u, prec, rm); println!( "{:#x}.shr_prec_round_ref({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(n), u, prec, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRoundAssign, { for (mut n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(u, rm); println!("x := {n_old}; x.shr_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shr_round_assign_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRoundAssign, { for (mut n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(u, rm); println!( "x := {:#x}; x.shr_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), u, rm, o, ComparableFloat(n) ); } } fn demo_float_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRoundAssign, { for (mut n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(i, rm); println!("x := {n_old}; x.shr_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_float_shr_round_assign_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRoundAssign, { for (mut n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(i, rm); println!( "x := {:#x}; x.shr_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(n_old), i, rm, o, ComparableFloat(n) ); } } fn demo_float_shr_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, u, rm, n.shr_round(u, rm) ); } } fn demo_float_shr_round_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_round(u, rm); println!( "{:#x}.shr_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_round_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_9::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, u, rm, n.shr_round(u, rm) ); } } fn demo_float_shr_round_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_round(u, rm); println!( "{:#x}.shr_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), u, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_round_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, i, rm, n.shr_round(i, rm) ); } } fn demo_float_shr_round_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_round(i, rm); println!( "{:#x}.shr_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), i, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_round_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, i, rm, n.shr_round(i, rm) ); } } fn demo_float_shr_round_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let n_old = n.clone(); let (shifted, o) = n.shr_round(i, rm); println!( "{:#x}.shr_round({}, {}) = ({:#x}, {:?})", ComparableFloat(n_old), i, rm, ComparableFloat(shifted), o ); } } fn demo_float_shr_round_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, u, rm, (&n).shr_round(u, rm) ); } } fn demo_float_shr_round_unsigned_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShrRound, { for (n, u, rm) in float_unsigned_rounding_mode_triple_gen_var_8::() .get(gm, config) .take(limit) { let (shifted, o) = (&n).shr_round(u, rm); println!( "(&{:#x}.shr_round({}, {}) = ({:#x}, {:?})", ComparableFloatRef(&n), u, rm, ComparableFloatRef(&shifted), o ); } } fn demo_float_shr_round_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, i, rm, (&n).shr_round(i, rm) ); } } fn demo_float_shr_round_signed_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: ShrRound, { for (n, i, rm) in float_signed_rounding_mode_triple_gen_var_4::() .get(gm, config) .take(limit) { let (shifted, o) = (&n).shr_round(i, rm); println!( "(&{:#x}).shr_round({}, {}) = ({:#x}, {:?})", ComparableFloatRef(&n), i, rm, ComparableFloatRef(&shifted), o ); } } fn benchmark_float_shr_prec_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec_assign({}, u64)", T::NAME), BenchmarkType::Single, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec)| { no_out!(n.shr_prec_assign(u, prec)); })], ); } fn benchmark_float_shr_prec_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec_assign({}, u64)", T::NAME), BenchmarkType::Single, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec)| { no_out!(n.shr_prec_assign(u, prec)); })], ); } fn benchmark_float_shr_prec_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_prec({}, u64)", T::NAME), &mut |(n, u, prec)| no_out!(n.shr_prec(u, prec)), ), ( &format!("Float.shr_prec_ref({}, u64)", T::NAME), &mut |(n, u, prec)| no_out!(n.shr_prec_ref(u, prec)), ), ], ); } fn benchmark_float_shr_prec_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_prec({}, u64)", T::NAME), &mut |(n, i, prec)| no_out!(n.shr_prec(i, prec)), ), ( &format!("Float.shr_prec_ref({}, u64)", T::NAME), &mut |(n, i, prec)| no_out!(n.shr_prec_ref(i, prec)), ), ], ); } fn benchmark_float_shr_prec_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, { run_benchmark( &format!("Float.shr_prec({}, u64)", T::NAME), BenchmarkType::Algorithms, float_unsigned_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec)| no_out!(n.shr_prec(u, prec))), ("naive", &mut |(n, u, prec)| { no_out!(shr_prec_naive(n, u, prec)); }), ], ); } fn benchmark_float_shr_prec_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, { run_benchmark( &format!("Float.shr_prec({}, u64)", T::NAME), BenchmarkType::Algorithms, float_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec)| no_out!(n.shr_prec(u, prec))), ("naive", &mut |(n, u, prec)| { no_out!(shr_prec_naive(n, u, prec)); }), ], ); } fn benchmark_float_shr_prec_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_prec(i32, u64)", BenchmarkType::LibraryComparison, float_unsigned_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, prec))| { no_out!(n.shr_prec(u, prec)); }), ("rug", &mut |((n, u, prec), _)| { no_out!(rug_shr_prec_unsigned(&n, u, prec)); }), ], ); } fn benchmark_float_shr_prec_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_prec(i32, u64)", BenchmarkType::LibraryComparison, float_signed_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, prec))| { no_out!(n.shr_prec(i, prec)); }), ("rug", &mut |((n, i, prec), _)| { no_out!(rug_shr_prec_signed(&n, i, prec)); }), ], ); } fn benchmark_float_shr_prec_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "Float.shr_prec_round_assign({}, u64, RoundingMode)", T::NAME ), BenchmarkType::Single, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec, rm)| { no_out!(n.shr_prec_round_assign(u, prec, rm)); })], ); } fn benchmark_float_shr_prec_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "Float.shr_prec_round_assign({}, u64, RoundingMode)", T::NAME ), BenchmarkType::Single, float_signed_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, prec, rm)| { no_out!(n.shr_prec_round_assign(u, prec, rm)); })], ); } fn benchmark_float_shr_prec_round_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), &mut |(n, u, prec, rm)| no_out!(n.shr_prec_round(u, prec, rm)), ), ( &format!("Float.shr_prec_round_ref({}, u64, RoundingMode)", T::NAME), &mut |(n, u, prec, rm)| no_out!(n.shr_prec_round_ref(u, prec, rm)), ), ], ); } fn benchmark_float_shr_prec_round_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), &mut |(n, i, prec, rm)| no_out!(n.shr_prec_round(i, prec, rm)), ), ( &format!("Float.shr_prec_round_ref({}, u64, RoundingMode)", T::NAME), &mut |(n, i, prec, rm)| no_out!(n.shr_prec_round_ref(i, prec, rm)), ), ], ); } fn benchmark_float_shr_prec_round_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, { run_benchmark( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec, rm)| { no_out!(n.shr_prec_round(u, prec, rm)); }), ("naive", &mut |(n, u, prec, rm)| { no_out!(shr_prec_round_naive(n, u, prec, rm)); }), ], ); } fn benchmark_float_shr_prec_round_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, { run_benchmark( &format!("Float.shr_prec_round({}, u64, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_signed_unsigned_rounding_mode_quadruple_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &quadruple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, prec, rm)| { no_out!(n.shr_prec_round(u, prec, rm)); }), ("naive", &mut |(n, u, prec, rm)| { no_out!(shr_prec_round_naive(n, u, prec, rm)); }), ], ); } fn benchmark_float_shr_prec_round_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_prec_round(i32, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, prec, rm))| { no_out!(n.shr_prec_round(u, prec, rm)); }), ("rug", &mut |((n, u, prec, rm), _)| { no_out!(rug_shr_prec_round_unsigned(&n, u, prec, rm)); }), ], ); } fn benchmark_float_shr_prec_round_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_prec_round(i32, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_signed_unsigned_rounding_mode_quadruple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, prec, rm))| { no_out!(n.shr_prec_round(i, prec, rm)); }), ("rug", &mut |((n, i, prec, rm), _)| { no_out!(rug_shr_prec_round_signed(&n, i, prec, rm)); }), ], ); } fn benchmark_float_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRoundAssign, { run_benchmark( &format!("Float.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shr_round_assign(u, rm)); })], ); } fn benchmark_float_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRoundAssign, { run_benchmark( &format!("Float.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, float_signed_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [("Malachite", &mut |(mut n, u, rm)| { no_out!(n.shr_round_assign(u, rm)); })], ); } fn benchmark_float_shr_round_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRound, for<'a> &'a Float: ShrRound, { run_benchmark( &format!("Float.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_round({}, RoundingMode)", T::NAME), &mut |(n, u, rm)| no_out!(n.shr_round(u, rm)), ), ( &format!("(&Float).shr_round({}, RoundingMode)", T::NAME), &mut |(n, u, rm)| no_out!((&n).shr_round(u, rm)), ), ], ); } fn benchmark_float_shr_round_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRound, for<'a> &'a Float: ShrRound, { run_benchmark( &format!("Float.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, float_signed_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ( &format!("Float.shr_round({}, RoundingMode)", T::NAME), &mut |(n, i, rm)| no_out!(n.shr_round(i, rm)), ), ( &format!("(&Float).shr_round({}, RoundingMode)", T::NAME), &mut |(n, i, rm)| no_out!((&n).shr_round(i, rm)), ), ], ); } fn benchmark_float_shr_round_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { run_benchmark( &format!("Float.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_unsigned_rounding_mode_triple_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, rm)| no_out!(n.shr_round(u, rm))), ("naive", &mut |(n, u, rm)| { no_out!(shr_round_naive(n, u, rm)); }), ], ); } fn benchmark_float_shr_round_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { run_benchmark( &format!("Float.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::Algorithms, float_signed_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_float_complexity_bucketer("n"), &mut [ ("default", &mut |(n, u, rm)| no_out!(n.shr_round(u, rm))), ("naive", &mut |(n, u, rm)| { no_out!(shr_round_naive(n, u, rm)); }), ], ); } fn benchmark_float_shr_round_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_round(i32, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_10_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, u, rm))| { no_out!((&n).shr_round(u, rm)); }), ("rug", &mut |((n, u, rm), _)| { no_out!(rug_shr_round_unsigned(&n, u, rm)); }), ], ); } fn benchmark_float_shr_round_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.shr_round(i32, RoundingMode)", BenchmarkType::LibraryComparison, float_signed_rounding_mode_triple_gen_var_6_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_float_complexity_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, i, rm))| { no_out!((&n).shr_round(i, rm)); }), ("rug", &mut |((n, i, rm), _)| { no_out!(rug_shr_round_signed(&n, i, rm)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen_var_2, float_gen_var_14}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sign); register_demo!(runner, demo_float_sign_debug); register_demo!(runner, demo_float_sign_extreme); register_demo!(runner, demo_float_sign_extreme_debug); register_bench!(runner, benchmark_float_sign); } fn demo_float_sign(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_2().get(gm, config).take(limit) { match n.sign() { Less => println!("{n} is negative"), Equal => println!("{n} is zero"), Greater => println!("{n} is positive"), } } } fn demo_float_sign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_2().get(gm, config).take(limit) { match n.sign() { Less => println!("{:#x} is negative", ComparableFloat(n)), Equal => println!("{:#x} is zero", ComparableFloat(n)), Greater => println!("{:#x} is positive", ComparableFloat(n)), } } } fn demo_float_sign_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_14().get(gm, config).take(limit) { match n.sign() { Less => println!("{n} is negative"), Equal => println!("{n} is zero"), Greater => println!("{n} is positive"), } } } fn demo_float_sign_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_14().get(gm, config).take(limit) { match n.sign() { Less => println!("{:#x} is negative", ComparableFloat(n)), Equal => println!("{:#x} is zero", ComparableFloat(n)), Greater => println!("{:#x} is positive", ComparableFloat(n)), } } } fn benchmark_float_sign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.sign()", BenchmarkType::Single, float_gen_var_2().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.sign()))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Sqrt, SqrtAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::arithmetic::sqrt::primitive_float_sqrt_rational; use malachite_float::test_util::arithmetic::sqrt::{ rug_sqrt, rug_sqrt_prec, rug_sqrt_prec_round, rug_sqrt_round, sqrt_rational_prec_round_generic, sqrt_rational_prec_round_simple, }; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, pair_2_pair_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_rounding_mode_pair_gen_var_24, float_rounding_mode_pair_gen_var_24_rm, float_rounding_mode_pair_gen_var_29, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_13, float_unsigned_rounding_mode_triple_gen_var_13_rm, float_unsigned_rounding_mode_triple_gen_var_14, rational_unsigned_rounding_mode_triple_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::test_util::bench::bucketers::{ pair_rational_bit_u64_max_bucketer, rational_bit_bucketer, triple_1_2_rational_bit_u64_max_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt); register_demo!(runner, demo_float_sqrt_debug); register_demo!(runner, demo_float_sqrt_extreme); register_demo!(runner, demo_float_sqrt_extreme_debug); register_demo!(runner, demo_float_sqrt_ref); register_demo!(runner, demo_float_sqrt_ref_debug); register_demo!(runner, demo_float_sqrt_assign); register_demo!(runner, demo_float_sqrt_assign_debug); register_demo!(runner, demo_float_sqrt_prec); register_demo!(runner, demo_float_sqrt_prec_debug); register_demo!(runner, demo_float_sqrt_prec_extreme); register_demo!(runner, demo_float_sqrt_prec_extreme_debug); register_demo!(runner, demo_float_sqrt_prec_ref); register_demo!(runner, demo_float_sqrt_prec_ref_debug); register_demo!(runner, demo_float_sqrt_prec_assign); register_demo!(runner, demo_float_sqrt_prec_assign_debug); register_demo!(runner, demo_float_sqrt_round); register_demo!(runner, demo_float_sqrt_round_debug); register_demo!(runner, demo_float_sqrt_round_extreme); register_demo!(runner, demo_float_sqrt_round_extreme_debug); register_demo!(runner, demo_float_sqrt_round_ref); register_demo!(runner, demo_float_sqrt_round_ref_debug); register_demo!(runner, demo_float_sqrt_round_assign); register_demo!(runner, demo_float_sqrt_round_assign_debug); register_demo!(runner, demo_float_sqrt_prec_round); register_demo!(runner, demo_float_sqrt_prec_round_debug); register_demo!(runner, demo_float_sqrt_prec_round_extreme); register_demo!(runner, demo_float_sqrt_prec_round_extreme_debug); register_demo!(runner, demo_float_sqrt_prec_round_ref); register_demo!(runner, demo_float_sqrt_prec_round_ref_debug); register_demo!(runner, demo_float_sqrt_prec_round_assign); register_demo!(runner, demo_float_sqrt_prec_round_assign_debug); register_demo!(runner, demo_float_sqrt_rational_prec); register_demo!(runner, demo_float_sqrt_rational_prec_debug); register_demo!(runner, demo_float_sqrt_rational_prec_ref); register_demo!(runner, demo_float_sqrt_rational_prec_ref_debug); register_demo!(runner, demo_float_sqrt_rational_prec_round); register_demo!(runner, demo_float_sqrt_rational_prec_round_debug); register_demo!(runner, demo_float_sqrt_rational_prec_round_ref); register_demo!(runner, demo_float_sqrt_rational_prec_round_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_sqrt_rational); register_bench!(runner, benchmark_float_sqrt_evaluation_strategy); register_bench!(runner, benchmark_float_sqrt_library_comparison); register_bench!(runner, benchmark_float_sqrt_assign); register_bench!(runner, benchmark_float_sqrt_prec_evaluation_strategy); register_bench!(runner, benchmark_float_sqrt_prec_library_comparison); register_bench!(runner, benchmark_float_sqrt_prec_assign); register_bench!(runner, benchmark_float_sqrt_round_evaluation_strategy); register_bench!(runner, benchmark_float_sqrt_round_library_comparison); register_bench!(runner, benchmark_float_sqrt_round_assign); register_bench!(runner, benchmark_float_sqrt_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_sqrt_prec_round_library_comparison); register_bench!(runner, benchmark_float_sqrt_prec_round_assign); register_bench!( runner, benchmark_float_sqrt_rational_prec_evaluation_strategy ); register_bench!( runner, benchmark_float_sqrt_rational_prec_round_evaluation_strategy ); register_bench!(runner, benchmark_float_sqrt_rational_prec_round_algorithms); register_primitive_float_benches!(runner, benchmark_primitive_float_sqrt_rational); } fn demo_float_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).sqrt() = {}", x_old, x.sqrt()); } } fn demo_float_sqrt_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).sqrt() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.sqrt()) ); } } fn demo_float_sqrt_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).sqrt() = {}", x_old, x.sqrt()); } } fn demo_float_sqrt_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}).sqrt() = {:#x}", ComparableFloat(x_old), ComparableFloat(x.sqrt()) ); } } fn demo_float_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("(&{}).sqrt() = {}", x, (&x).sqrt()); } } fn demo_float_sqrt_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "(&{:#x}).sqrt() = {:#x}", ComparableFloatRef(&x), ComparableFloat((&x).sqrt()) ); } } fn demo_float_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.sqrt_assign(); println!("x := {x_old}; x.sqrt_assign(); x = {x}"); } } fn demo_float_sqrt_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.sqrt_assign(); println!( "x := {:#x}; x.sqrt_assign(); x = {:#x}", ComparableFloat(x_old), ComparableFloat(x) ); } } fn demo_float_sqrt_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).sqrt_prec({}) = {:?}", x_old, prec, x.sqrt_prec(prec)); } } fn demo_float_sqrt_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_prec(prec); println!( "({:#x}).sqrt_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).sqrt_prec({}) = {:?}", x_old, prec, x.sqrt_prec(prec)); } } fn demo_float_sqrt_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_prec(prec); println!( "({:#x}).sqrt_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { println!( "(&{}).sqrt_prec_ref({}) = {:?}", x, prec, x.sqrt_prec_ref(prec) ); } } fn demo_float_sqrt_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (sum, o) = x.sqrt_prec_ref(prec); println!( "(&{:#x}).sqrt_prec_ref({}) = ({:#x}, {:?})", ComparableFloat(x), prec, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.sqrt_prec_assign(prec); println!("x := {x_old}; x.sqrt_prec_assign({prec}); x = {x}"); } } fn demo_float_sqrt_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let o = x.sqrt_prec_assign(prec); println!( "x := {:#x}; x.sqrt_prec_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, o, ComparableFloat(x) ); } } fn demo_float_sqrt_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { let x_old = x.clone(); println!("({}).sqrt_round({}) = {:?}", x_old, rm, x.sqrt_round(rm)); } } fn demo_float_sqrt_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_round(rm); println!( "({:#x}).sqrt_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_29() .get(gm, config) .take(limit) { let x_old = x.clone(); println!("({}).sqrt_round({}) = {:?}", x_old, rm, x.sqrt_round(rm)); } } fn demo_float_sqrt_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_29() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_round(rm); println!( "({:#x}).sqrt_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { println!( "(&{}).sqrt_round_ref({}) = {:?}", x, rm, x.sqrt_round_ref(rm) ); } } fn demo_float_sqrt_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { let (sum, o) = x.sqrt_round_ref(rm); println!( "(&{:#x}).sqrt_round_ref({}) = ({:#x}, {:?})", ComparableFloat(x), rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { let x_old = x.clone(); x.sqrt_round_assign(rm); println!("x := {x_old}; x.sqrt_round_assign({rm}); x = {x}"); } } fn demo_float_sqrt_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_24() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sqrt_round_assign(rm); println!( "x := {:#x}; x.sqrt_round_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), rm, o, ComparableFloat(x) ); } } fn demo_float_sqrt_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sqrt_prec_round({}, {}) = {:?}", x_old, prec, rm, x.sqrt_prec_round(prec, rm) ); } } fn demo_float_sqrt_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_prec_round(prec, rm); println!( "({:#x}).sqrt_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_14() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sqrt_prec_round({}, {}) = {:?}", x_old, prec, rm, x.sqrt_prec_round(prec, rm) ); } } fn demo_float_sqrt_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_14() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.sqrt_prec_round(prec, rm); println!( "({:#x}).sqrt_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { println!( "({}).sqrt_prec_round_ref({}, {}) = {:?}", x, prec, rm, x.sqrt_prec_round_ref(prec, rm) ); } } fn demo_float_sqrt_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { let (sum, o) = x.sqrt_prec_round_ref(prec, rm); println!( "({:#x}).sqrt_prec_round_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(x), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_sqrt_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sqrt_prec_round_assign(prec, rm); println!("x := {x_old}; x.sqrt_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_sqrt_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_13() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sqrt_prec_round_assign(prec, rm); println!( "x := {:#x}; x.sqrt_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_sqrt_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::sqrt_rational_prec({}, {}) = {:?}", n.clone(), p, Float::sqrt_rational_prec(n, p) ); } } fn demo_float_sqrt_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::sqrt_rational_prec(n.clone(), p); println!( "Float::sqrt_rational_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_sqrt_rational_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::sqrt_rational_prec_ref(&{}, {}) = {:?}", n, p, Float::sqrt_rational_prec_ref(&n, p) ); } } fn demo_float_sqrt_rational_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::sqrt_rational_prec_ref(&n, p); println!( "Float::sqrt_rational_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_sqrt_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::sqrt_rational_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::sqrt_rational_prec_round(n, p, rm) ); } } fn demo_float_sqrt_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::sqrt_rational_prec_round(n.clone(), p, rm); println!( "Float::sqrt_rational_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_sqrt_rational_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::sqrt_rational_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::sqrt_rational_prec_round_ref(&n, p, rm) ); } } fn demo_float_sqrt_rational_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::sqrt_rational_prec_round_ref(&n, p, rm); println!( "Float::sqrt_rational_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_sqrt_rational( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { for x in rational_gen().get(gm, config).take(limit) { println!( "primitive_float_sqrt_rational({}) = {:?}", x, NiceFloat(primitive_float_sqrt_rational::(&x)) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.sqrt()", &mut |x| no_out!(x.sqrt())), ("(&Float).sqrt()", &mut |x| no_out!((&x).sqrt())), ], ); } fn benchmark_float_sqrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!((&x).sqrt())), ("rug", &mut |(x, _)| no_out!(rug_sqrt(&x))), ], ); } fn benchmark_float_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.sqrt_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.sqrt_assign()", &mut |mut x| x.sqrt_assign())], ); } fn benchmark_float_sqrt_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Float.sqrt_prec(u64)", &mut |(x, prec)| { no_out!(x.sqrt_prec(prec)); }), ("(&Float).sqrt_prec_ref(u64)", &mut |(x, prec)| { no_out!(x.sqrt_prec_ref(prec)); }), ], ); } fn benchmark_float_sqrt_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec))| { no_out!(x.sqrt_prec_ref(prec)); }), ("rug", &mut |((x, prec), _)| { no_out!(rug_sqrt_prec(&x, prec)); }), ], ); } fn benchmark_float_sqrt_prec_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec_assign(u64)", BenchmarkType::Single, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [("Float.sqrt_prec_assign(u64)", &mut |(mut x, prec)| { no_out!(x.sqrt_prec_assign(prec)); })], ); } fn benchmark_float_sqrt_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_round(RoundingMode)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_24().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Float.sqrt_round(RoundingMode)", &mut |(x, rm)| { no_out!(x.sqrt_round(rm)); }), ("(&Float).sqrt_round_ref(RoundingMode)", &mut |(x, rm)| { no_out!(x.sqrt_round_ref(rm)); }), ], ); } fn benchmark_float_sqrt_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_round(RoundingMode)", BenchmarkType::LibraryComparison, float_rounding_mode_pair_gen_var_24_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, rm))| { no_out!(x.sqrt_round_ref(rm)); }), ("rug", &mut |((x, rm), _)| no_out!(rug_sqrt_round(&x, rm))), ], ); } fn benchmark_float_sqrt_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_round_assign(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen_var_24().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Float.sqrt_round_assign(RoundingMode)", &mut |( mut x, rm, )| { no_out!(x.sqrt_round_assign(rm)); })], ); } fn benchmark_float_sqrt_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_13().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ( "Float.sqrt_prec_round(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.sqrt_prec_round(prec, rm)), ), ( "(&Float).sqrt_prec_round_ref(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.sqrt_prec_round_ref(prec, rm)), ), ], ); } fn benchmark_float_sqrt_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_13_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec, rm))| { no_out!(x.sqrt_prec_round_ref(prec, rm)); }), ("rug", &mut |((x, prec, rm), _)| { no_out!(rug_sqrt_prec_round(&x, prec, rm)); }), ], ); } fn benchmark_float_sqrt_prec_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sqrt_prec_round_assign(u64, RoundingMode)", BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_13().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [( "Float.sqrt_prec_round_assign(u64, RoundingMode)", &mut |(mut x, prec, rm)| no_out!(x.sqrt_prec_round_assign(prec, rm)), )], ); } fn benchmark_float_sqrt_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::sqrt_rational_prec(Rational, u64)", &mut |(n, prec)| no_out!(Float::sqrt_rational_prec(n, prec)), ), ( "Float::sqrt_rational_prec_ref(&Rational, u64)", &mut |(n, prec)| no_out!(Float::sqrt_rational_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_sqrt_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::sqrt_rational_prec(Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::sqrt_rational_prec_round(n, prec, rm)), ), ( "Float::sqrt_rational_prec_ref(&Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::sqrt_rational_prec_round_ref(&n, prec, rm)), ), ], ); } fn benchmark_float_sqrt_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("default", &mut |(n, prec, rm)| { no_out!(Float::sqrt_rational_prec_round_ref(&n, prec, rm)); }), ("generic", &mut |(n, prec, rm)| { no_out!(sqrt_rational_prec_round_generic(&n, prec, rm)); }), ("simple", &mut |(n, prec, rm)| { no_out!(sqrt_rational_prec_round_simple(&n, prec, rm)); }), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_sqrt_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { run_benchmark( &format!( "primitive_float_sqrt_rational_prec::<{}>(Rational)", T::NAME ), BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(primitive_float_sqrt_rational::(&x)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Square, SquareAssign}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::square::{ rug_square, rug_square_prec, rug_square_prec_round, rug_square_round, square_prec_round_naive, }; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, pair_2_float_complexity_bucketer, pair_2_pair_1_float_complexity_bucketer, pair_2_pair_float_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer, pair_float_primitive_int_max_complexity_bucketer, triple_1_2_float_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_rounding_mode_pair_gen_var_7, float_rounding_mode_pair_gen_var_7_rm, float_rounding_mode_pair_gen_var_22, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_2, float_unsigned_rounding_mode_triple_gen_var_2_rm, float_unsigned_rounding_mode_triple_gen_var_11, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_square); register_demo!(runner, demo_float_square_debug); register_demo!(runner, demo_float_square_extreme); register_demo!(runner, demo_float_square_extreme_debug); register_demo!(runner, demo_float_square_ref); register_demo!(runner, demo_float_square_ref_debug); register_demo!(runner, demo_float_square_assign); register_demo!(runner, demo_float_square_assign_debug); register_demo!(runner, demo_float_square_prec); register_demo!(runner, demo_float_square_prec_debug); register_demo!(runner, demo_float_square_prec_extreme); register_demo!(runner, demo_float_square_prec_extreme_debug); register_demo!(runner, demo_float_square_prec_ref); register_demo!(runner, demo_float_square_prec_ref_debug); register_demo!(runner, demo_float_square_prec_assign); register_demo!(runner, demo_float_square_prec_assign_debug); register_demo!(runner, demo_float_square_round); register_demo!(runner, demo_float_square_round_debug); register_demo!(runner, demo_float_square_round_extreme); register_demo!(runner, demo_float_square_round_extreme_debug); register_demo!(runner, demo_float_square_round_ref); register_demo!(runner, demo_float_square_round_ref_debug); register_demo!(runner, demo_float_square_round_assign); register_demo!(runner, demo_float_square_round_assign_debug); register_demo!(runner, demo_float_square_prec_round); register_demo!(runner, demo_float_square_prec_round_debug); register_demo!(runner, demo_float_square_prec_round_extreme); register_demo!(runner, demo_float_square_prec_round_extreme_debug); register_demo!(runner, demo_float_square_prec_round_ref); register_demo!(runner, demo_float_square_prec_round_ref_debug); register_demo!(runner, demo_float_square_prec_round_assign); register_demo!(runner, demo_float_square_prec_round_assign_debug); register_bench!(runner, benchmark_float_square_evaluation_strategy); register_bench!(runner, benchmark_float_square_library_comparison); register_bench!(runner, benchmark_float_square_algorithms); register_bench!(runner, benchmark_float_square_assign); register_bench!(runner, benchmark_float_square_prec_evaluation_strategy); register_bench!(runner, benchmark_float_square_prec_library_comparison); register_bench!(runner, benchmark_float_square_prec_algorithms); register_bench!(runner, benchmark_float_square_prec_assign); register_bench!(runner, benchmark_float_square_round_evaluation_strategy); register_bench!(runner, benchmark_float_square_round_library_comparison); register_bench!(runner, benchmark_float_square_round_algorithms); register_bench!(runner, benchmark_float_square_round_assign); register_bench!( runner, benchmark_float_square_prec_round_evaluation_strategy ); register_bench!(runner, benchmark_float_square_prec_round_library_comparison); register_bench!(runner, benchmark_float_square_prec_round_algorithms); register_bench!(runner, benchmark_float_square_prec_round_assign); } fn demo_float_square(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}) ^ 2 = {}", x_old, x.square()); } } fn demo_float_square_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}) ^ 2 = {:#x}", ComparableFloat(x_old), ComparableFloat(x.square()) ); } } fn demo_float_square_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}) ^ 2 = {}", x_old, x.square()); } } fn demo_float_square_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({:#x}) ^ 2 = {:#x}", ComparableFloat(x_old), ComparableFloat(x.square()) ); } } fn demo_float_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("(&{}) ^ 2 = {}", x, (&x).square()); } } fn demo_float_square_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "(&{:#x}) ^ 2 = {:#x}", ComparableFloatRef(&x), ComparableFloat((&x).square()) ); } } fn demo_float_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.square_assign(); println!("x := {x_old}; x ^= 2; x = {x}"); } } fn demo_float_square_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.square_assign(); println!( "x := {:#x}; x ^= 2; x = {:#x}", ComparableFloat(x_old), ComparableFloat(x) ); } } fn demo_float_square_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).square_prec({}) = {:?}", x_old, prec, x.square_prec(prec) ); } } fn demo_float_square_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.square_prec(prec); println!( "({:#x}).square_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_square_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).square_prec({}) = {:?}", x_old, prec, x.square_prec(prec) ); } } fn demo_float_square_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let (sum, o) = x.square_prec(prec); println!( "({:#x}).square_prec({}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, ComparableFloat(sum), o ); } } fn demo_float_square_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { println!( "(&{}).square_prec_ref({}) = {:?}", x, prec, x.square_prec_ref(prec) ); } } fn demo_float_square_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (sum, o) = x.square_prec_ref(prec); println!( "(&{:#x}).square_prec_ref({}) = ({:#x}, {:?})", ComparableFloat(x), prec, ComparableFloat(sum), o ); } } fn demo_float_square_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.square_prec_assign(prec); println!("x := {x_old}; x.square_prec_assign({prec}); x = {x}"); } } fn demo_float_square_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let o = x.square_prec_assign(prec); println!( "x := {:#x}; x.square_prec_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, o, ComparableFloat(x) ); } } fn demo_float_square_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).square_round({}) = {:?}", x_old, rm, x.square_round(rm) ); } } fn demo_float_square_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.square_round(rm); println!( "({:#x}).square_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_square_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_22() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).square_round({}) = {:?}", x_old, rm, x.square_round(rm) ); } } fn demo_float_square_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_22() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.square_round(rm); println!( "({:#x}).square_round({}) = ({:#x}, {:?})", ComparableFloat(x_old), rm, ComparableFloat(sum), o ); } } fn demo_float_square_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "(&{}).square_round_ref({}) = {:?}", x, rm, x.square_round_ref(rm) ); } } fn demo_float_square_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { let (sum, o) = x.square_round_ref(rm); println!( "(&{:#x}).square_round_ref({}) = ({:#x}, {:?})", ComparableFloat(x), rm, ComparableFloat(sum), o ); } } fn demo_float_square_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); x.square_round_assign(rm); println!("x := {x_old}; x.square_round_assign({rm}); x = {x}"); } } fn demo_float_square_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, rm) in float_rounding_mode_pair_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.square_round_assign(rm); println!( "x := {:#x}; x.square_round_assign({}) = {:?}; x = {:#x}", ComparableFloat(x_old), rm, o, ComparableFloat(x) ); } } fn demo_float_square_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).square_prec_round({}, {}) = {:?}", x_old, prec, rm, x.square_prec_round(prec, rm) ); } } fn demo_float_square_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.square_prec_round(prec, rm); println!( "({:#x}).square_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_square_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_11() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).square_prec_round({}, {}) = {:?}", x_old, prec, rm, x.square_prec_round(prec, rm) ); } } fn demo_float_square_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_11() .get(gm, config) .take(limit) { let x_old = x.clone(); let (sum, o) = x.square_prec_round(prec, rm); println!( "({:#x}).square_prec_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_square_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "({}).square_prec_round_ref({}, {}) = {:?}", x, prec, rm, x.square_prec_round_ref(prec, rm) ); } } fn demo_float_square_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let (sum, o) = x.square_prec_round_ref(prec, rm); println!( "({:#x}).square_prec_round_ref({}, {}) = ({:#x}, {:?})", ComparableFloat(x), prec, rm, ComparableFloat(sum), o ); } } fn demo_float_square_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.square_prec_round_assign(prec, rm); println!("x := {x_old}; x.square_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_square_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.square_prec_round_assign(prec, rm); println!( "x := {:#x}; x.square_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.square()", &mut |x| no_out!(x.square())), ("(&Float).square()", &mut |x| no_out!((&x).square())), ], ); } fn benchmark_float_square_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!((&x).square())), ("rug", &mut |(x, _)| no_out!(rug_square(&x))), ], ); } fn benchmark_float_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square()", BenchmarkType::Algorithms, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.square())), ("naive", &mut |x| { let xsb = x.significant_bits(); no_out!(square_prec_round_naive(x, xsb, Nearest).0); }), ], ); } fn benchmark_float_square_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.square_assign()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Float.square_assign()", &mut |mut x| x.square_assign())], ); } fn benchmark_float_square_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Float.square_prec(u64)", &mut |(x, prec)| { no_out!(x.square_prec(prec)); }), ("(&Float).square_prec_ref(u64)", &mut |(x, prec)| { no_out!(x.square_prec_ref(prec)); }), ], ); } fn benchmark_float_square_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec))| { no_out!(x.square_prec_ref(prec)); }), ("rug", &mut |((x, prec), _)| { no_out!(rug_square_prec(&x, prec)); }), ], ); } fn benchmark_float_square_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec(u64)", BenchmarkType::Algorithms, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("default", &mut |(x, prec)| no_out!(x.square_prec(prec))), ("naive", &mut |(x, prec)| { no_out!(square_prec_round_naive(x, prec, Nearest)); }), ], ); } fn benchmark_float_square_prec_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec_assign(u64)", BenchmarkType::Single, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [("Float.square_prec_assign(u64)", &mut |(mut x, prec)| { no_out!(x.square_prec_assign(prec)); })], ); } fn benchmark_float_square_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_round(RoundingMode)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Float.square_round(RoundingMode)", &mut |(x, rm)| { no_out!(x.square_round(rm)); }), ("(&Float).square_round_ref(RoundingMode)", &mut |(x, rm)| { no_out!(x.square_round_ref(rm)); }), ], ); } fn benchmark_float_square_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_round(RoundingMode)", BenchmarkType::LibraryComparison, float_rounding_mode_pair_gen_var_7_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, rm))| { no_out!(x.square_round_ref(rm)); }), ("rug", &mut |((x, rm), _)| no_out!(rug_square_round(&x, rm))), ], ); } fn benchmark_float_square_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_round(RoundingMode)", BenchmarkType::Algorithms, float_rounding_mode_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("default", &mut |(x, rm)| no_out!(x.square_round(rm))), ("naive", &mut |(x, rm)| { let xsb = x.significant_bits(); square_prec_round_naive(x, xsb, rm); }), ], ); } fn benchmark_float_square_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_round_assign(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Float.square_round_assign(RoundingMode)", &mut |( mut x, rm, )| { no_out!(x.square_round_assign(rm)); })], ); } fn benchmark_float_square_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ( "Float.square_prec_round(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.square_prec_round(prec, rm)), ), ( "(&Float).square_prec_round_ref(u64, RoundingMode)", &mut |(x, prec, rm)| no_out!(x.square_prec_round_ref(prec, rm)), ), ], ); } fn benchmark_float_square_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(_, (x, prec, rm))| { no_out!(x.square_prec_round_ref(prec, rm)); }), ("rug", &mut |((x, prec, rm), _)| { no_out!(rug_square_prec_round(&x, prec, rm)); }), ], ); } fn benchmark_float_square_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, float_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [ ("default", &mut |(x, prec, rm)| { no_out!(x.square_prec_round(prec, rm)); }), ("naive", &mut |(x, prec, rm)| { no_out!(square_prec_round_naive(x, prec, rm)); }), ], ); } fn benchmark_float_square_prec_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.square_prec_round_assign(u64, RoundingMode)", BenchmarkType::Single, float_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_primitive_int_max_complexity_bucketer("x", "prec"), &mut [( "Float.square_prec_round_assign(u64, RoundingMode)", &mut |(mut x, prec, rm)| no_out!(x.square_prec_round_assign(prec, rm)), )], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::arithmetic::add::add_prec_round_naive; use malachite_float::test_util::arithmetic::sub::sub_rational_prec_round_naive; use malachite_float::test_util::arithmetic::sub::{ rug_sub, rug_sub_prec, rug_sub_prec_round, rug_sub_rational, rug_sub_rational_prec, rug_sub_rational_prec_round, rug_sub_rational_round, rug_sub_round, }; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_2_pair_float_rational_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, pair_2_triple_1_2_float_max_complexity_bucketer, pair_2_triple_1_2_float_rational_max_complexity_bucketer, pair_2_triple_float_float_primitive_int_max_complexity_bucketer, pair_2_triple_float_rational_primitive_int_max_complexity_bucketer, pair_float_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer, quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer, triple_1_2_float_max_complexity_bucketer, triple_1_2_float_rational_max_complexity_bucketer, triple_float_float_primitive_int_max_complexity_bucketer, triple_float_rational_primitive_int_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1_rm, float_float_rounding_mode_triple_gen_var_2, float_float_rounding_mode_triple_gen_var_30, float_float_unsigned_rounding_mode_quadruple_gen_var_2, float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm, float_float_unsigned_rounding_mode_quadruple_gen_var_6, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_1_rm, float_float_unsigned_triple_gen_var_2, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_2, float_rational_rounding_mode_triple_gen_var_3_rm, float_rational_rounding_mode_triple_gen_var_8, float_rational_unsigned_rounding_mode_quadruple_gen_var_2, float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm, float_rational_unsigned_rounding_mode_quadruple_gen_var_7, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_1_rm, float_rational_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::max; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sub); register_demo!(runner, demo_float_sub_debug); register_demo!(runner, demo_float_sub_extreme); register_demo!(runner, demo_float_sub_extreme_debug); register_demo!(runner, demo_float_sub_val_ref); register_demo!(runner, demo_float_sub_val_ref_debug); register_demo!(runner, demo_float_sub_ref_val); register_demo!(runner, demo_float_sub_ref_val_debug); register_demo!(runner, demo_float_sub_ref_ref); register_demo!(runner, demo_float_sub_ref_ref_debug); register_demo!(runner, demo_float_sub_assign); register_demo!(runner, demo_float_sub_assign_debug); register_demo!(runner, demo_float_sub_assign_ref); register_demo!(runner, demo_float_sub_assign_ref_debug); register_demo!(runner, demo_float_sub_prec); register_demo!(runner, demo_float_sub_prec_debug); register_demo!(runner, demo_float_sub_prec_extreme); register_demo!(runner, demo_float_sub_prec_extreme_debug); register_demo!(runner, demo_float_sub_prec_val_ref); register_demo!(runner, demo_float_sub_prec_val_ref_debug); register_demo!(runner, demo_float_sub_prec_ref_val); register_demo!(runner, demo_float_sub_prec_ref_val_debug); register_demo!(runner, demo_float_sub_prec_ref_ref); register_demo!(runner, demo_float_sub_prec_ref_ref_debug); register_demo!(runner, demo_float_sub_prec_assign); register_demo!(runner, demo_float_sub_prec_assign_debug); register_demo!(runner, demo_float_sub_prec_assign_ref); register_demo!(runner, demo_float_sub_prec_assign_ref_debug); register_demo!(runner, demo_float_sub_round); register_demo!(runner, demo_float_sub_round_debug); register_demo!(runner, demo_float_sub_round_extreme); register_demo!(runner, demo_float_sub_round_extreme_debug); register_demo!(runner, demo_float_sub_round_val_ref); register_demo!(runner, demo_float_sub_round_val_ref_debug); register_demo!(runner, demo_float_sub_round_ref_val); register_demo!(runner, demo_float_sub_round_ref_val_debug); register_demo!(runner, demo_float_sub_round_ref_ref); register_demo!(runner, demo_float_sub_round_ref_ref_debug); register_demo!(runner, demo_float_sub_round_assign); register_demo!(runner, demo_float_sub_round_assign_debug); register_demo!(runner, demo_float_sub_round_assign_ref); register_demo!(runner, demo_float_sub_round_assign_ref_debug); register_demo!(runner, demo_float_sub_prec_round); register_demo!(runner, demo_float_sub_prec_round_debug); register_demo!(runner, demo_float_sub_prec_round_extreme); register_demo!(runner, demo_float_sub_prec_round_extreme_debug); register_demo!(runner, demo_float_sub_prec_round_val_ref); register_demo!(runner, demo_float_sub_prec_round_val_ref_debug); register_demo!(runner, demo_float_sub_prec_round_ref_val); register_demo!(runner, demo_float_sub_prec_round_ref_val_debug); register_demo!(runner, demo_float_sub_prec_round_ref_ref); register_demo!(runner, demo_float_sub_prec_round_ref_ref_debug); register_demo!(runner, demo_float_sub_prec_round_assign); register_demo!(runner, demo_float_sub_prec_round_assign_debug); register_demo!(runner, demo_float_sub_prec_round_assign_ref); register_demo!(runner, demo_float_sub_prec_round_assign_ref_debug); register_demo!(runner, demo_float_sub_rational); register_demo!(runner, demo_float_sub_rational_debug); register_demo!(runner, demo_float_sub_rational_extreme); register_demo!(runner, demo_float_sub_rational_extreme_debug); register_demo!(runner, demo_float_sub_rational_val_ref); register_demo!(runner, demo_float_sub_rational_val_ref_debug); register_demo!(runner, demo_float_sub_rational_ref_val); register_demo!(runner, demo_float_sub_rational_ref_val_debug); register_demo!(runner, demo_float_sub_rational_ref_ref); register_demo!(runner, demo_float_sub_rational_ref_ref_debug); register_demo!(runner, demo_float_sub_rational_assign); register_demo!(runner, demo_float_sub_rational_assign_debug); register_demo!(runner, demo_float_sub_rational_assign_ref); register_demo!(runner, demo_float_sub_rational_assign_ref_debug); register_demo!(runner, demo_rational_sub_float); register_demo!(runner, demo_rational_sub_float_debug); register_demo!(runner, demo_rational_sub_float_extreme); register_demo!(runner, demo_rational_sub_float_extreme_debug); register_demo!(runner, demo_rational_sub_float_val_ref); register_demo!(runner, demo_rational_sub_float_val_ref_debug); register_demo!(runner, demo_rational_sub_float_ref_val); register_demo!(runner, demo_rational_sub_float_ref_val_debug); register_demo!(runner, demo_rational_sub_float_ref_ref); register_demo!(runner, demo_rational_sub_float_ref_ref_debug); register_demo!(runner, demo_float_sub_rational_prec); register_demo!(runner, demo_float_sub_rational_prec_debug); register_demo!(runner, demo_float_sub_rational_prec_extreme); register_demo!(runner, demo_float_sub_rational_prec_extreme_debug); register_demo!(runner, demo_float_sub_rational_prec_val_ref); register_demo!(runner, demo_float_sub_rational_prec_val_ref_debug); register_demo!(runner, demo_float_sub_rational_prec_ref_val); register_demo!(runner, demo_float_sub_rational_prec_ref_val_debug); register_demo!(runner, demo_float_sub_rational_prec_ref_ref); register_demo!(runner, demo_float_sub_rational_prec_ref_ref_debug); register_demo!(runner, demo_float_sub_rational_prec_assign); register_demo!(runner, demo_float_sub_rational_prec_assign_debug); register_demo!(runner, demo_float_sub_rational_prec_assign_ref); register_demo!(runner, demo_float_sub_rational_prec_assign_ref_debug); register_demo!(runner, demo_float_sub_rational_round); register_demo!(runner, demo_float_sub_rational_round_debug); register_demo!(runner, demo_float_sub_rational_round_extreme); register_demo!(runner, demo_float_sub_rational_round_extreme_debug); register_demo!(runner, demo_float_sub_rational_round_val_ref); register_demo!(runner, demo_float_sub_rational_round_val_ref_debug); register_demo!(runner, demo_float_sub_rational_round_ref_val); register_demo!(runner, demo_float_sub_rational_round_ref_val_debug); register_demo!(runner, demo_float_sub_rational_round_ref_ref); register_demo!(runner, demo_float_sub_rational_round_ref_ref_debug); register_demo!(runner, demo_float_sub_rational_round_assign); register_demo!(runner, demo_float_sub_rational_round_assign_debug); register_demo!(runner, demo_float_sub_rational_round_assign_ref); register_demo!(runner, demo_float_sub_rational_round_assign_ref_debug); register_demo!(runner, demo_float_sub_rational_prec_round); register_demo!(runner, demo_float_sub_rational_prec_round_debug); register_demo!(runner, demo_float_sub_rational_prec_round_extreme); register_demo!(runner, demo_float_sub_rational_prec_round_extreme_debug); register_demo!(runner, demo_float_sub_rational_prec_round_val_ref); register_demo!(runner, demo_float_sub_rational_prec_round_val_ref_debug); register_demo!(runner, demo_float_sub_rational_prec_round_ref_val); register_demo!(runner, demo_float_sub_rational_prec_round_ref_val_debug); register_demo!(runner, demo_float_sub_rational_prec_round_ref_ref); register_demo!(runner, demo_float_sub_rational_prec_round_ref_ref_debug); register_demo!(runner, demo_float_sub_rational_prec_round_assign); register_demo!(runner, demo_float_sub_rational_prec_round_assign_debug); register_demo!(runner, demo_float_sub_rational_prec_round_assign_ref); register_demo!(runner, demo_float_sub_rational_prec_round_assign_ref_debug); register_bench!(runner, benchmark_float_sub_evaluation_strategy); register_bench!(runner, benchmark_float_sub_library_comparison); register_bench!(runner, benchmark_float_sub_algorithms); register_bench!(runner, benchmark_float_sub_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_library_comparison); register_bench!(runner, benchmark_float_sub_prec_algorithms); register_bench!(runner, benchmark_float_sub_prec_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_round_evaluation_strategy); register_bench!(runner, benchmark_float_sub_round_library_comparison); register_bench!(runner, benchmark_float_sub_round_algorithms); register_bench!(runner, benchmark_float_sub_round_assign_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_sub_prec_round_library_comparison); register_bench!(runner, benchmark_float_sub_prec_round_algorithms); register_bench!( runner, benchmark_float_sub_prec_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_float_sub_rational_evaluation_strategy); register_bench!(runner, benchmark_float_sub_rational_library_comparison); register_bench!(runner, benchmark_float_sub_rational_algorithms); register_bench!( runner, benchmark_float_sub_rational_assign_evaluation_strategy ); register_bench!(runner, benchmark_rational_sub_float_evaluation_strategy); register_bench!(runner, benchmark_rational_sub_float_library_comparison); register_bench!( runner, benchmark_float_sub_rational_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_sub_rational_prec_library_comparison); register_bench!(runner, benchmark_float_sub_rational_prec_algorithms); register_bench!( runner, benchmark_float_sub_rational_prec_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_sub_rational_round_evaluation_strategy ); register_bench!( runner, benchmark_float_sub_rational_round_library_comparison ); register_bench!(runner, benchmark_float_sub_rational_round_algorithms); register_bench!( runner, benchmark_float_sub_rational_round_assign_evaluation_strategy ); register_bench!( runner, benchmark_float_sub_rational_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_sub_rational_prec_round_library_comparison ); register_bench!(runner, benchmark_float_sub_rational_prec_round_algorithms); register_bench!( runner, benchmark_float_sub_rational_prec_round_assign_evaluation_strategy ); } fn demo_float_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_float_sub_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} - {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x - y) ); } } fn demo_float_sub_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_float_sub_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} - {:#x} = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), ComparableFloat(x - y) ); } } fn demo_float_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_float_sub_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} - &{:#x} = {:#x}", ComparableFloat(x_old), ComparableFloatRef(&y), ComparableFloat(x - &y) ); } } fn demo_float_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_float_sub_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} - {:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloat(y_old), ComparableFloat(&x - y) ); } } fn demo_float_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn demo_float_sub_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} - &{:#x} = {:#x}", ComparableFloatRef(&x), ComparableFloatRef(&y), ComparableFloat(&x - &y) ); } } fn demo_float_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_float_sub_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!( "x := {:#x}; x += {:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_float_sub_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!( "x := {:#x}; x += &{:#x}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_sub_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_prec({}, {}) = {:?}", x_old, y_old, prec, x.sub_prec(y, prec) ); } } fn demo_float_sub_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_prec(y, prec); println!( "({:#x}).sub_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_prec({}, {}) = {:?}", x_old, y_old, prec, x.sub_prec(y, prec) ); } } fn demo_float_sub_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_prec(y, prec); println!( "({:#x}).sub_prec({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_prec_val_ref(&{}, {}) = {:?}", x_old, y, prec, x.sub_prec_val_ref(&y, prec) ); } } fn demo_float_sub_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_prec_val_ref(&y, prec); println!( "({:#x}).sub_prec_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.sub_prec_ref_val(y, prec) ); } } fn demo_float_sub_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_prec_ref_val(y, prec); println!( "(&{:#x}).sub_prec_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).sub_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.sub_prec_ref_ref(&y, prec) ); } } fn demo_float_sub_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (diff, o) = x.sub_prec_ref_ref(&y, prec); println!( "(&{:#x}).sub_prec_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.sub_prec_assign(y, prec); println!("x := {x_old}; x.sub_prec_assign({y_old}, {prec}); x = {x}"); } } fn demo_float_sub_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_prec_assign(y, prec); println!( "x := {:#x}; x.sub_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, o, ComparableFloat(x) ); } } fn demo_float_sub_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); x.sub_prec_assign_ref(&y, prec); println!("x := {x_old}; x.sub_prec_assign({y}, {prec}); x = {x}"); } } fn demo_float_sub_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_float_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.sub_prec_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, o, ComparableFloat(x) ); } } fn demo_float_sub_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_round({}, {}) = {:?}", x_old, y_old, rm, x.sub_round(y, rm) ); } } fn demo_float_sub_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_round(y, rm); println!( "({:#x}).sub_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(diff), o ); } } fn demo_float_sub_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_round({}, {}) = {:?}", x_old, y_old, rm, x.sub_round(y, rm) ); } } fn demo_float_sub_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_30() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_round(y, rm); println!( "({:#x}).sub_round({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), rm, ComparableFloat(diff), o ); } } fn demo_float_sub_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.sub_round_val_ref(&y, rm) ); } } fn demo_float_sub_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_round_val_ref(&y, rm); println!( "({:#x}).sub_round_val_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), rm, ComparableFloat(diff), o ); } } fn demo_float_sub_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_round_ref_val({}, {}) = {:?}", x, y_old, rm, x.sub_round_ref_val(y, rm) ); } } fn demo_float_sub_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_round_ref_val(y, rm); println!( "(&{:#x}).sub_round_ref_val({:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), rm, ComparableFloat(diff), o ); } } fn demo_float_sub_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).sub_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.sub_round_ref_ref(&y, rm) ); } } fn demo_float_sub_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let (diff, o) = x.sub_round_ref_ref(&y, rm); println!( "(&{:#x}).sub_round_ref_ref(&{:#x}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), rm, ComparableFloat(diff), o ); } } fn demo_float_sub_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.sub_round_assign(y, rm); println!("x := {x_old}; x.sub_round_assign({y_old}, {rm}); x = {x}"); } } fn demo_float_sub_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_round_assign(y, rm); println!( "x := {:#x}; x.sub_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), rm, o, ComparableFloat(x) ); } } fn demo_float_sub_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); x.sub_round_assign_ref(&y, rm); println!("x := {x_old}; x.sub_round_assign({y}, {rm}); x = {x}"); } } fn demo_float_sub_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_float_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_round_assign_ref(&y, rm); println!( "x := {:#x}; x.sub_round_assign({:#x}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), rm, o, ComparableFloat(x) ); } } fn demo_float_sub_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.sub_prec_round(y, prec, rm) ); } } fn demo_float_sub_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_prec_round(y, prec, rm); println!( "({:#x}).sub_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.sub_prec_round(y, prec, rm) ); } } fn demo_float_sub_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_6() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_prec_round(y, prec, rm); println!( "({:#x}).sub_prec_round({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_prec_round(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.sub_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_sub_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).sub_prec_round_val_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), ComparableFloat(y), prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.sub_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_sub_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).sub_prec_round_ref_val({:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y_old), prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { println!( "({}).sub_prec_round({}, {}, {}) = {:?}", x, y, prec, rm, x.sub_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_sub_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let (diff, o) = x.sub_prec_round_ref_ref(&y, prec, rm); println!( "({:#x}).sub_prec_round_ref_ref(&{:#x}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), ComparableFloat(y), prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_prec_round_assign(y, prec, rm); println!("x := {x_old}; x.sub_prec_round({y_old}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_sub_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.sub_prec_round({:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y_old), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_sub_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_prec_round_assign_ref(&y, prec, rm); println!("x := {x_old}; x.sub_prec_round_ref(&{y}, {prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_sub_prec_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_float_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.sub_prec_round_ref(&{:#x}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_sub_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_float_sub_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} - {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x - y) ); } } fn demo_float_sub_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_float_sub_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{:#x} - {} = {:#x}", ComparableFloat(x_old), y_old, ComparableFloat(x - y) ); } } fn demo_float_sub_rational_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_float_sub_rational_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{:#x} - {} = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x - &y) ); } } fn demo_float_sub_rational_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_float_sub_rational_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{:#x} - {} = {:#x}", ComparableFloatRef(&x), y_old, ComparableFloat(&x - y) ); } } fn demo_float_sub_rational_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn demo_float_sub_rational_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{:#x} - &{} = {:#x}", ComparableFloatRef(&x), y, ComparableFloat(&x - &y) ); } } fn demo_float_sub_rational_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_float_sub_rational_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!( "x := {:#x}; x += {}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_float_sub_rational_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_float_sub_rational_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!( "x := {:#x}; x += &{}; x = {:#x}", ComparableFloat(x_old), y, ComparableFloat(x) ); } } fn demo_rational_sub_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_rational_sub_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} - {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x - y) ); } } fn demo_rational_sub_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_rational_sub_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} - {:#x} = {:#x}", x_old, ComparableFloat(y_old), ComparableFloat(x - y) ); } } fn demo_rational_sub_float_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_rational_sub_float_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{} - &{:#x} = {:#x}", x_old, ComparableFloatRef(&y), ComparableFloat(x - &y) ); } } fn demo_rational_sub_float_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_rational_sub_float_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "&{} - {:#x} = {:#x}", x, ComparableFloat(y_old), ComparableFloat(&x - y) ); } } fn demo_rational_sub_float_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn demo_rational_sub_float_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { println!( "&{} - &{:#x} = {:#x}", x, ComparableFloatRef(&y), ComparableFloat(&x - &y) ); } } fn demo_float_sub_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.sub_rational_prec(y, prec) ); } } fn demo_float_sub_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_prec(y, prec); println!( "({:#x}).sub_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_prec({}, {}) = {:?}", x_old, y_old, prec, x.sub_rational_prec(y, prec) ); } } fn demo_float_sub_rational_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_prec(y, prec); println!( "({:#x}).sub_rational_prec({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_rational_prec({}, &{}) = {:?}", x_old, y, prec, x.sub_rational_prec_val_ref(&y, prec) ); } } fn demo_float_sub_rational_prec_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_rational_prec_val_ref(&y, prec); println!( "({:#x}).sub_rational_prec_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_rational_prec_ref_val({}, {}) = {:?}", x, y_old, prec, x.sub_rational_prec_ref_val(y, prec) ); } } fn demo_float_sub_rational_prec_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_rational_prec_ref_val(y, prec); println!( "(&{:#x}).sub_rational_prec_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).sub_rational_prec_ref_ref(&{}, {}) = {:?}", x, y, prec, x.sub_rational_prec_ref_ref(&y, prec) ); } } fn demo_float_sub_rational_prec_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let (diff, o) = x.sub_rational_prec_ref_ref(&y, prec); println!( "(&{:#x}).sub_rational_prec_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_prec_assign(y, prec); println!("x := {x_old}; x.sub_rational_prec_assign({y_old}, {prec}) = {o:?}; x = {x}"); } } fn demo_float_sub_rational_prec_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_prec_assign(y, prec); println!( "x := {:#x}; x.sub_rational_prec_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, o, ComparableFloat(x) ); } } fn demo_float_sub_rational_prec_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_rational_prec_assign_ref(&y, prec); println!("x := {x_old}; x.sub_rational_prec_assign_ref({y}, &{prec}) = {o:?}; x = {x}"); } } fn demo_float_sub_rational_prec_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec) in float_rational_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_rational_prec_assign_ref(&y, prec); println!( "x := {:#x}; x.sub_rational_prec_assign(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, o, ComparableFloat(x) ); } } fn demo_float_sub_rational_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.sub_rational_round(y, rm) ); } } fn demo_float_sub_rational_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_round(y, rm); println!( "({:#x}).sub_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_round({}, {}) = {:?}", x_old, y_old, rm, x.sub_rational_round(y, rm) ); } } fn demo_float_sub_rational_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_8() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_round(y, rm); println!( "({:#x}).sub_rational_round({}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_rational_round_val_ref(&{}, {}) = {:?}", x_old, y, rm, x.sub_rational_round_val_ref(&y, rm) ); } } fn demo_float_sub_rational_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_rational_round_val_ref(&y, rm); println!( "({:#x}).sub_rational_round_val_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_rational_round_ref_val(&{}, {}) = {:?}", x, y_old, rm, x.sub_rational_round_ref_val(y, rm) ); } } fn demo_float_sub_rational_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_rational_round_ref_val(y, rm); println!( "(&{:#x}).sub_rational_round_ref_val({}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).sub_rational_round_ref_ref(&{}, {}) = {:?}", x, y, rm, x.sub_rational_round_ref_ref(&y, rm) ); } } fn demo_float_sub_rational_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let (diff, o) = x.sub_rational_round_ref_ref(&y, rm); println!( "(&{:#x}).sub_rational_round_ref_ref(&{}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_round_assign(y, rm); println!("x := {x_old}; x.sub_rational_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_sub_rational_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_round_assign(y, rm); println!( "x := {:#x}; x.sub_rational_round_assign({}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_sub_rational_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_rational_round_assign_ref(&y, rm); println!("x := {x_old}; x.sub_rational_round_assign_ref(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_sub_rational_round_assign_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in float_rational_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_round_assign_ref(&y, rm); println!( "x := {:#x}; x.sub_rational_round_assign_ref(&{}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, rm, o, ComparableFloat(x) ); } } fn demo_float_sub_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.sub_rational_prec_round(y, prec, rm) ); } } fn demo_float_sub_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_prec_round(y, prec, rm); println!( "({:#x}).sub_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).sub_rational_prec_round({}, {}, {}) = {:?}", x_old, y_old, prec, rm, x.sub_rational_prec_round(y, prec, rm) ); } } fn demo_float_sub_rational_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_7() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let (diff, o) = x.sub_rational_prec_round(y, prec, rm); println!( "({:#x}).sub_rational_prec_round({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y_old, prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).sub_rational_prec_round_val_ref(&{}, {}, {}) = {:?}", x_old, y, prec, rm, x.sub_rational_prec_round_val_ref(&y, prec, rm) ); } } fn demo_float_sub_rational_prec_round_val_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let (diff, o) = x.sub_rational_prec_round_val_ref(&y, prec, rm); println!( "({:#x}).sub_rational_prec_round_val_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x_old), y, prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).sub_rational_prec_round_ref_val({}, {}, {}) = {:?}", x, y_old, prec, rm, x.sub_rational_prec_round_ref_val(y, prec, rm) ); } } fn demo_float_sub_rational_prec_round_ref_val_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); let (diff, o) = x.sub_rational_prec_round_ref_val(y, prec, rm); println!( "(&{:#x}).sub_rational_prec_round_ref_val({}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y_old, prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).sub_rational_prec_round_ref_ref(&{}, {}, {}) = {:?}", x, y, prec, rm, x.sub_rational_prec_round_ref_ref(&y, prec, rm) ); } } fn demo_float_sub_rational_prec_round_ref_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let (diff, o) = x.sub_rational_prec_round_ref_ref(&y, prec, rm); println!( "(&{:#x}).sub_rational_prec_round_ref_ref(&{}, {}, {}) = ({:#x}, {:?})", ComparableFloat(x), y, prec, rm, ComparableFloat(diff), o ); } } fn demo_float_sub_rational_prec_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_prec_round_assign(y, prec, rm); println!( "x := {x_old}; x.sub_rational_prec_round_assign({y_old}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_sub_rational_prec_round_assign_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.sub_rational_prec_round_assign(y, prec, rm); println!( "x := {:#x}; x.sub_rational_prec_round_assign({}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y_old, prec, rm, o, ComparableFloat(x) ); } } fn demo_float_sub_rational_prec_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {x_old}; x.sub_rational_prec_round_assign_ref(&{y}, {prec}, {rm}) = {o:?}; \ x = {x}", ); } } fn demo_float_sub_rational_prec_round_assign_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut x, y, prec, rm) in float_rational_unsigned_rounding_mode_quadruple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.sub_rational_prec_round_assign_ref(&y, prec, rm); println!( "x := {:#x}; x.sub_rational_prec_round_assign_ref(&{}, {}, {}) = {:?}; x = {:#x}", ComparableFloat(x_old), y, prec, rm, o, ComparableFloat(x) ); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float - Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float - Float", &mut |(x, y)| no_out!(x - y)), ("Float - &Float", &mut |(x, y)| no_out!(x - &y)), ("&Float - Float", &mut |(x, y)| no_out!(&x - y)), ("&Float - &Float", &mut |(x, y)| no_out!(&x - &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_sub_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float - Float", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x - &y)), ("rug", &mut |((x, y), _)| no_out!(rug_sub(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_sub_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float - Float", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x - y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(add_prec_round_naive(x, -y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float -= Float", BenchmarkType::EvaluationStrategy, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Float -= Float", &mut |(mut x, y)| x -= y), ("Float -= &Float", &mut |(mut x, y)| x -= &y), ], ); } fn benchmark_float_sub_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.sub_prec(Float, u64)", &mut |(x, y, prec)| { no_out!(x.sub_prec(y, prec)); }), ("Float.sub_prec_val_ref(&Float, u64)", &mut |( x, y, prec, )| { no_out!(x.sub_prec_val_ref(&y, prec)); }), ( "(&Float).sub_prec_ref_val(Float, u64)", &mut |(x, y, prec)| no_out!(x.sub_prec_ref_val(y, prec)), ), ( "(&Float).sub_prec_ref_ref(&Float, u64)", &mut |(x, y, prec)| no_out!(x.sub_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_sub_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec(Float, u64)", BenchmarkType::LibraryComparison, float_float_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.sub_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_sub_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_sub_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec(Float, u64)", BenchmarkType::Algorithms, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| no_out!(x.sub_prec(y, prec))), ("naive", &mut |(x, y, prec)| { no_out!(add_prec_round_naive(x, -y, prec, Nearest)); }), ], ); } fn benchmark_float_sub_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec_assign(Float, u64)", BenchmarkType::EvaluationStrategy, float_float_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Float.sub_prec_assign(Float, u64)", &mut |( mut x, y, prec, )| { no_out!(x.sub_prec_assign(y, prec)); }), ( "Float.sub_prec_assign_ref(&Float, u64)", &mut |(mut x, y, prec)| no_out!(x.sub_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_sub_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_round(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Float.sub_round(Float, RoundingMode)", &mut |(x, y, rm)| { no_out!(x.sub_round(y, rm)); }), ( "Float.sub_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_round_val_ref(&y, rm)), ), ( "(&Float).sub_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_round_ref_val(y, rm)), ), ( "(&Float).sub_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_sub_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_round(Float, RoundingMode)", BenchmarkType::LibraryComparison, float_float_rounding_mode_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.sub_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_sub_round(&x, &y, rm)); }), ], ); } fn benchmark_float_sub_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_round(Float, RoundingMode)", BenchmarkType::Algorithms, float_float_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| no_out!(x.sub_round(y, rm))), ("naive", &mut |(x, y, rm)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); add_prec_round_naive(x, -y, max(xsb, ysb), rm); }), ], ); } fn benchmark_float_sub_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_round_assign(Float, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_max_complexity_bucketer("x", "y"), &mut [ ( "Float.sub_round_assign(Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.sub_round_assign(y, rm)), ), ( "Float.sub_round_assign_ref(&Float, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.sub_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_sub_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec_round(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_prec_round(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_prec_round(y, prec, rm)), ), ( "Float.sub_prec_round_val_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).sub_prec_round_ref_val(Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).sub_prec_round_ref_ref(&Float, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_sub_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec_round(Float, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.sub_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_sub_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_sub_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec_round(Float, u64, RoundingMode)", BenchmarkType::Algorithms, float_float_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.sub_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(add_prec_round_naive(x, -y, prec, rm)); }), ], ); } fn benchmark_float_sub_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_prec_round_assign(Float, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_float_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_prec_round_assign(Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.sub_prec_round_assign(y, prec, rm)), ), ( "Float.sub_prec_round_assign_ref(&Float, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.sub_prec_round_assign_ref(&y, prec, rm)), ), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_sub_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float - Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float - Rational", &mut |(x, y)| no_out!(x - y)), ("Float - &Rational", &mut |(x, y)| no_out!(x - &y)), ("&Float - Rational", &mut |(x, y)| no_out!(&x - y)), ("&Float - &Rational", &mut |(x, y)| no_out!(&x - &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_sub_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float - Rational", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(&x - &y)), ("rug", &mut |((x, y), _)| no_out!(rug_sub_rational(&x, &y))), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_float_sub_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float - Rational", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x - y)), ("naive", &mut |(x, y)| { let xsb = x.significant_bits(); let ysb = y.significant_bits(); no_out!(sub_rational_prec_round_naive(x, y, max(xsb, ysb), Nearest).0); }), ], ); } fn benchmark_float_sub_rational_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float -= Rational", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Float -= Rational", &mut |(mut x, y)| x -= y), ("Float -= &Rational", &mut |(mut x, y)| x -= &y), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_sub_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational - Float", BenchmarkType::EvaluationStrategy, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Rational - Float", &mut |(y, x)| no_out!(x - y)), ("Rational - &Float", &mut |(y, x)| no_out!(x - &y)), ("&Rational - Float", &mut |(y, x)| no_out!(&x - y)), ("&Rational - &Float", &mut |(y, x)| no_out!(&x - &y)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_rational_sub_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational - Float", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(&x - &y)), ("rug", &mut |((y, x), _)| no_out!(-rug_sub_rational(&y, &x))), ], ); } fn benchmark_float_sub_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_rational_prec(Rational, u64)", &mut |(x, y, prec)| no_out!(x.sub_rational_prec(y, prec)), ), ( "Float.sub_rational_prec_val_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.sub_rational_prec_val_ref(&y, prec)), ), ( "(&Float).sub_rational_prec_ref_val(Rational, u64)", &mut |(x, y, prec)| no_out!(x.sub_rational_prec_ref_val(y, prec)), ), ( "(&Float).sub_rational_prec_ref_ref(&Rational, u64)", &mut |(x, y, prec)| no_out!(x.sub_rational_prec_ref_ref(&y, prec)), ), ], ); } fn benchmark_float_sub_rational_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec(Rational, u64)", BenchmarkType::LibraryComparison, float_rational_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("Malachite", &mut |(_, (x, y, prec))| { no_out!(x.sub_rational_prec_ref_ref(&y, prec)); }), ("rug", &mut |((x, y, prec), _)| { no_out!(rug_sub_rational_prec(&x, &y, prec)); }), ], ); } fn benchmark_float_sub_rational_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec(Rational, u64)", BenchmarkType::Algorithms, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec)| { no_out!(x.sub_rational_prec(y, prec)); }), ("naive", &mut |(x, y, prec)| { no_out!(sub_rational_prec_round_naive(x, y, prec, Nearest)); }), ], ); } fn benchmark_float_sub_rational_prec_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec_assign(Rational, u64)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_rational_prec_assign(Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.sub_rational_prec_assign(y, prec)), ), ( "Float.sub_rational_prec_assign_ref(&Rational, u64)", &mut |(mut x, y, prec)| no_out!(x.sub_rational_prec_assign_ref(&y, prec)), ), ], ); } fn benchmark_float_sub_rational_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_round(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.sub_rational_round(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_rational_round(y, rm)), ), ( "Float.sub_rational_round_val_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_rational_round_val_ref(&y, rm)), ), ( "(&Float).sub_rational_round_ref_val(Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_rational_round_ref_val(y, rm)), ), ( "(&Float).sub_rational_round_ref_ref(&Float, RoundingMode)", &mut |(x, y, rm)| no_out!(x.sub_rational_round_ref_ref(&y, rm)), ), ], ); } fn benchmark_float_sub_rational_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_round(Rational, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_rounding_mode_triple_gen_var_3_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, rm))| { no_out!(x.sub_rational_round_ref_ref(&y, rm)); }), ("rug", &mut |((x, y, rm), _)| { no_out!(rug_sub_rational_round(&x, &y, rm)); }), ], ); } fn benchmark_float_sub_rational_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_round(Rational, RoundingMode)", BenchmarkType::Algorithms, float_rational_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.sub_rational_round(y, rm)); }), ("naive", &mut |(x, y, rm)| { let ysb = y.significant_bits(); sub_rational_prec_round_naive(x, y, ysb, rm); }), ], ); } fn benchmark_float_sub_rational_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_round_assign(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_float_rational_max_complexity_bucketer("x", "y"), &mut [ ( "Float.sub_rational_round_assign(Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.sub_rational_round_assign(y, rm)), ), ( "Float.sub_rational_round_assign_ref(&Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.sub_rational_round_assign_ref(&y, rm)), ), ], ); } fn benchmark_float_sub_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_rational_prec_round(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_rational_prec_round(y, prec, rm)), ), ( "Float.sub_rational_prec_round_val_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_rational_prec_round_val_ref(&y, prec, rm)), ), ( "(&Float).sub_rational_prec_round_ref_val(Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_rational_prec_round_ref_val(y, prec, rm)), ), ( "(&Float).sub_rational_prec_round_ref_ref(&Rational, u64, RoundingMode)", &mut |(x, y, prec, rm)| no_out!(x.sub_rational_prec_round_ref_ref(&y, prec, rm)), ), ], ); } fn benchmark_float_sub_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::LibraryComparison, float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer( "x", "y", "prec", ), &mut [ ("Malachite", &mut |(_, (x, y, prec, rm))| { no_out!(x.sub_rational_prec_round_ref_ref(&y, prec, rm)); }), ("rug", &mut |((x, y, prec, rm), _)| { no_out!(rug_sub_rational_prec_round(&x, &y, prec, rm)); }), ], ); } fn benchmark_float_sub_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::Algorithms, float_rational_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ("default", &mut |(x, y, prec, rm)| { no_out!(x.sub_rational_prec_round(y, prec, rm)); }), ("naive", &mut |(x, y, prec, rm)| { no_out!(sub_rational_prec_round_naive(x, y, prec, rm)); }), ], ); } fn benchmark_float_sub_rational_prec_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sub_rational_prec_round_assign(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_rational_unsigned_rounding_mode_quadruple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer("x", "y", "prec"), &mut [ ( "Float.sub_rational_prec_round_assign(Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| no_out!(x.sub_rational_prec_round_assign(y, prec, rm)), ), ( "Float.sub_rational_prec_round_assign_ref(&Rational, u64, RoundingMode)", &mut |(mut x, y, prec, rm)| { no_out!(x.sub_rational_prec_round_assign_ref(&y, prec, rm)); }, ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/classification.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_2_float_complexity_bucketer, }; use malachite_float::test_util::common::to_hex_string; use malachite_float::test_util::generators::{float_gen, float_gen_rm, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_is_nan); register_demo!(runner, demo_float_is_nan_debug); register_demo!(runner, demo_float_is_nan_extreme); register_demo!(runner, demo_float_is_nan_extreme_debug); register_demo!(runner, demo_float_is_finite); register_demo!(runner, demo_float_is_finite_debug); register_demo!(runner, demo_float_is_finite_extreme); register_demo!(runner, demo_float_is_finite_extreme_debug); register_demo!(runner, demo_float_is_infinite); register_demo!(runner, demo_float_is_infinite_debug); register_demo!(runner, demo_float_is_infinite_extreme); register_demo!(runner, demo_float_is_infinite_extreme_debug); register_demo!(runner, demo_float_is_positive_zero); register_demo!(runner, demo_float_is_positive_zero_debug); register_demo!(runner, demo_float_is_positive_zero_extreme); register_demo!(runner, demo_float_is_positive_zero_extreme_debug); register_demo!(runner, demo_float_is_negative_zero); register_demo!(runner, demo_float_is_negative_zero_debug); register_demo!(runner, demo_float_is_negative_zero_extreme); register_demo!(runner, demo_float_is_negative_zero_extreme_debug); register_demo!(runner, demo_float_is_zero); register_demo!(runner, demo_float_is_zero_debug); register_demo!(runner, demo_float_is_zero_extreme); register_demo!(runner, demo_float_is_zero_extreme_debug); register_demo!(runner, demo_float_is_normal); register_demo!(runner, demo_float_is_normal_debug); register_demo!(runner, demo_float_is_normal_extreme); register_demo!(runner, demo_float_is_normal_extreme_debug); register_demo!(runner, demo_float_is_sign_positive); register_demo!(runner, demo_float_is_sign_positive_debug); register_demo!(runner, demo_float_is_sign_positive_extreme); register_demo!(runner, demo_float_is_sign_positive_extreme_debug); register_demo!(runner, demo_float_is_sign_negative); register_demo!(runner, demo_float_is_sign_negative_debug); register_demo!(runner, demo_float_is_sign_negative_extreme); register_demo!(runner, demo_float_is_sign_negative_extreme_debug); register_demo!(runner, demo_float_classify); register_demo!(runner, demo_float_classify_debug); register_demo!(runner, demo_float_classify_extreme); register_demo!(runner, demo_float_classify_extreme_debug); register_demo!(runner, demo_float_into_non_nan); register_demo!(runner, demo_float_into_non_nan_debug); register_demo!(runner, demo_float_to_non_nan); register_demo!(runner, demo_float_to_non_nan_debug); register_demo!(runner, demo_float_to_non_nan_extreme); register_demo!(runner, demo_float_to_non_nan_extreme_debug); register_demo!(runner, demo_float_into_finite); register_demo!(runner, demo_float_into_finite_debug); register_demo!(runner, demo_float_to_finite); register_demo!(runner, demo_float_to_finite_debug); register_demo!(runner, demo_float_to_finite_extreme); register_demo!(runner, demo_float_to_finite_extreme_debug); register_bench!(runner, benchmark_float_is_nan_library_comparison); register_bench!(runner, benchmark_float_is_finite_library_comparison); register_bench!(runner, benchmark_float_is_infinite_library_comparison); register_bench!(runner, benchmark_float_is_positive_zero); register_bench!(runner, benchmark_float_is_negative_zero); register_bench!(runner, benchmark_float_is_zero_library_comparison); register_bench!(runner, benchmark_float_is_normal_library_comparison); register_bench!(runner, benchmark_float_is_sign_positive_library_comparison); register_bench!(runner, benchmark_float_is_sign_negative_library_comparison); register_bench!(runner, benchmark_float_classify_library_comparison); register_bench!(runner, benchmark_float_to_non_nan_evaluation_strategy); register_bench!(runner, benchmark_float_to_finite_evaluation_strategy); } fn demo_float_is_nan(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_nan() { println!("{x} is NaN"); } else { println!("{x} is not NaN"); } } } fn demo_float_is_nan_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_nan() { println!("{:#x} is NaN", ComparableFloat(x)); } else { println!("{:#x} is not NaN", ComparableFloat(x)); } } } fn demo_float_is_nan_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_nan() { println!("{x} is NaN"); } else { println!("{x} is not NaN"); } } } fn demo_float_is_nan_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_nan() { println!("{:#x} is NaN", ComparableFloat(x)); } else { println!("{:#x} is not NaN", ComparableFloat(x)); } } } fn demo_float_is_finite(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{x} is finite"); } else { println!("{x} is not finite"); } } } fn demo_float_is_finite_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is finite", ComparableFloat(x)); } else { println!("{:#x} is not finite", ComparableFloat(x)); } } } fn demo_float_is_finite_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{x} is finite"); } else { println!("{x} is not finite"); } } } fn demo_float_is_finite_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is finite", ComparableFloat(x)); } else { println!("{:#x} is not finite", ComparableFloat(x)); } } } fn demo_float_is_infinite(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{x} is infinite"); } else { println!("{x} is not infinite"); } } } fn demo_float_is_infinite_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_infinite() { println!("{:#x} is infinite", ComparableFloat(x)); } else { println!("{:#x} is not infinite", ComparableFloat(x)); } } } fn demo_float_is_infinite_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{x} is infinite"); } else { println!("{x} is not infinite"); } } } fn demo_float_is_infinite_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_infinite() { println!("{:#x} is infinite", ComparableFloat(x)); } else { println!("{:#x} is not infinite", ComparableFloat(x)); } } } fn demo_float_is_positive_zero(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is positive zero"); } else { println!("{x} is not positive zero"); } } } fn demo_float_is_positive_zero_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is positive zero", ComparableFloat(x)); } else { println!("{:#x} is not positive zero", ComparableFloat(x)); } } } fn demo_float_is_positive_zero_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is positive zero"); } else { println!("{x} is not positive zero"); } } } fn demo_float_is_positive_zero_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is positive zero", ComparableFloat(x)); } else { println!("{:#x} is not positive zero", ComparableFloat(x)); } } } fn demo_float_is_negative_zero(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is negative zero"); } else { println!("{x} is not negative zero"); } } } fn demo_float_is_negative_zero_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is negative zero", ComparableFloat(x)); } else { println!("{:#x} is not negative zero", ComparableFloat(x)); } } } fn demo_float_is_negative_zero_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is negative zero"); } else { println!("{x} is not negative zero"); } } } fn demo_float_is_negative_zero_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is negative zero", ComparableFloat(x)); } else { println!("{:#x} is not negative zero", ComparableFloat(x)); } } } fn demo_float_is_zero(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is zero"); } else { println!("{x} is not zero"); } } } fn demo_float_is_zero_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is zero", ComparableFloat(x)); } else { println!("{:#x} is not zero", ComparableFloat(x)); } } } fn demo_float_is_zero_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_zero() { println!("{x} is zero"); } else { println!("{x} is not zero"); } } } fn demo_float_is_zero_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_finite() { println!("{:#x} is zero", ComparableFloat(x)); } else { println!("{:#x} is not zero", ComparableFloat(x)); } } } fn demo_float_is_normal(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_normal() { println!("{x} is normal"); } else { println!("{x} is not normal"); } } } fn demo_float_is_normal_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_normal() { println!("{:#x} is normal", ComparableFloat(x)); } else { println!("{:#x} is not normal", ComparableFloat(x)); } } } fn demo_float_is_normal_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_normal() { println!("{x} is normal"); } else { println!("{x} is not normal"); } } } fn demo_float_is_normal_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_normal() { println!("{:#x} is normal", ComparableFloat(x)); } else { println!("{:#x} is not normal", ComparableFloat(x)); } } } fn demo_float_is_sign_positive(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_sign_positive() { println!("{x} has a positive sign"); } else { println!("{x} does not have a positive sign"); } } } fn demo_float_is_sign_positive_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_sign_positive() { println!("{:#x} has a positive sign", ComparableFloat(x)); } else { println!("{:#x} does not have a positive sign", ComparableFloat(x)); } } } fn demo_float_is_sign_positive_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_sign_positive() { println!("{x} has a positive sign"); } else { println!("{x} does not have a positive sign"); } } } fn demo_float_is_sign_positive_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_sign_positive() { println!("{:#x} has a positive sign", ComparableFloat(x)); } else { println!("{:#x} does not have a positive sign", ComparableFloat(x)); } } } fn demo_float_is_sign_negative(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_sign_negative() { println!("{x} has a negative sign"); } else { println!("{x} does not have a negative sign"); } } } fn demo_float_is_sign_negative_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.is_sign_negative() { println!("{:#x} has a negative sign", ComparableFloat(x)); } else { println!("{:#x} does not have a negative sign", ComparableFloat(x)); } } } fn demo_float_is_sign_negative_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_sign_negative() { println!("{x} has a negative sign"); } else { println!("{x} does not have a negative sign"); } } } fn demo_float_is_sign_negative_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { if x.is_sign_negative() { println!("{:#x} has a negative sign", ComparableFloat(x)); } else { println!("{:#x} does not have a negative sign", ComparableFloat(x)); } } } fn demo_float_classify(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("classify({}) = {:?}", x, x.classify()); } } fn demo_float_classify_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "classify({:#x}) = {:?}", ComparableFloatRef(&x), x.classify() ); } } fn demo_float_classify_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("classify({}) = {:?}", x, x.classify()); } } fn demo_float_classify_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "classify({:#x}) = {:?}", ComparableFloatRef(&x), x.classify() ); } } fn demo_float_into_non_nan(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("into_non_nan({}) = {:?}", x.clone(), x.into_non_nan()); } } fn demo_float_into_non_nan_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "into_non_nan({:#x}) = {:?}", ComparableFloat(x.clone()), x.into_non_nan() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_to_non_nan(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("to_non_nan({}) = {:?}", x, x.to_non_nan()); } } fn demo_float_to_non_nan_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "to_non_nan({:#x}) = {:?}", ComparableFloatRef(&x), x.to_non_nan() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_to_non_nan_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("to_non_nan({}) = {:?}", x, x.to_non_nan()); } } fn demo_float_to_non_nan_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "to_non_nan({:#x}) = {:?}", ComparableFloatRef(&x), x.to_non_nan() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_into_finite(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("into_finite({}) = {:?}", x.clone(), x.into_finite()); } } fn demo_float_into_finite_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "into_finite({:#x}) = {:?}", ComparableFloat(x.clone()), x.into_finite() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_to_finite(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("to_finite({}) = {:?}", x, x.to_finite()); } } fn demo_float_to_finite_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "to_finite({:#x}) = {:?}", ComparableFloatRef(&x), x.to_finite() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_to_finite_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("to_finite({}) = {:?}", x, x.to_finite()); } } fn demo_float_to_finite_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "to_finite({:#x}) = {:?}", ComparableFloatRef(&x), x.to_finite() .map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn benchmark_float_is_nan_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_nan()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_nan())), ("rug", &mut |(x, _)| no_out!(x.is_nan())), ], ); } fn benchmark_float_is_finite_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_finite()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_finite())), ("rug", &mut |(x, _)| no_out!(x.is_finite())), ], ); } fn benchmark_float_is_infinite_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_infinite()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_infinite())), ("rug", &mut |(x, _)| no_out!(x.is_infinite())), ], ); } fn benchmark_float_is_positive_zero( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_zero()", BenchmarkType::Single, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(_, x)| no_out!(x.is_positive_zero()))], ); } fn benchmark_float_is_negative_zero( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_zero()", BenchmarkType::Single, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(_, x)| no_out!(x.is_positive_zero()))], ); } fn benchmark_float_is_zero_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_zero()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_zero())), ("rug", &mut |(x, _)| no_out!(x.is_zero())), ], ); } fn benchmark_float_is_normal_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_normal()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_normal())), ("rug", &mut |(x, _)| no_out!(x.is_normal())), ], ); } fn benchmark_float_is_sign_positive_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_sign_positive()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_sign_positive())), ("rug", &mut |(x, _)| { let _ = !x.is_nan() && x.is_sign_positive(); }), ], ); } fn benchmark_float_is_sign_negative_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.is_sign_negative()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.is_sign_negative())), ("rug", &mut |(x, _)| { let _ = !x.is_nan() && x.is_sign_negative(); }), ], ); } fn benchmark_float_classify_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.classify()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.classify())), ("rug", &mut |(x, _)| no_out!(x.classify())), ], ); } fn benchmark_float_to_non_nan_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.to_non_nan()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("to_non_nan", &mut |x| no_out!(x.to_non_nan())), ("into_non_nan", &mut |x| no_out!(x.into_non_nan())), ], ); } fn benchmark_float_to_finite_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.to_finite()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("to_finite", &mut |x| no_out!(x.to_finite())), ("into_finite", &mut |x| no_out!(x.into_finite())), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/complexity.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_complexity); register_demo!(runner, demo_float_complexity_debug); register_demo!(runner, demo_float_complexity_extreme); register_demo!(runner, demo_float_complexity_extreme_debug); register_demo!(runner, demo_float_significant_bits); register_demo!(runner, demo_float_significant_bits_debug); register_demo!(runner, demo_float_significant_bits_extreme); register_demo!(runner, demo_float_significant_bits_extreme_debug); register_bench!(runner, benchmark_float_complexity); register_bench!(runner, benchmark_float_significant_bits); } fn demo_float_complexity(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("complexity({}) = {}", x, x.complexity()); } } fn demo_float_complexity_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "complexity({:#x}) = {}", ComparableFloatRef(&x), x.complexity() ); } } fn demo_float_complexity_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("complexity({}) = {}", x, x.complexity()); } } fn demo_float_complexity_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "complexity({:#x}) = {}", ComparableFloatRef(&x), x.complexity() ); } } fn demo_float_significant_bits(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("significant_bits({}) = {}", x, x.significant_bits()); } } fn demo_float_significant_bits_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "significant_bits({:#x}) = {}", ComparableFloatRef(&x), x.significant_bits() ); } } fn demo_float_significant_bits_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("significant_bits({}) = {}", x, x.significant_bits()); } } fn demo_float_significant_bits_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "significant_bits({:#x}) = {}", ComparableFloatRef(&x), x.significant_bits() ); } } fn benchmark_float_complexity(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.complexity()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.complexity()))], ); } fn benchmark_float_significant_bits( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.significant_bits()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.significant_bits()))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/constants.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_11; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::float_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_min_positive_value_prec); register_demo!(runner, demo_float_min_positive_value_prec_debug); register_demo!(runner, demo_float_abs_is_min_positive_value); register_demo!(runner, demo_float_abs_is_min_positive_value_debug); register_demo!(runner, demo_float_max_finite_value_with_prec); register_demo!(runner, demo_float_max_finite_value_with_prec_debug); register_demo!(runner, demo_float_abs_is_max_finite_value_with_prec); register_demo!(runner, demo_float_abs_is_max_finite_value_with_prec_debug); register_demo!(runner, demo_float_one_prec); register_demo!(runner, demo_float_one_prec_debug); register_demo!(runner, demo_float_two_prec); register_demo!(runner, demo_float_two_prec_debug); register_demo!(runner, demo_float_negative_one_prec); register_demo!(runner, demo_float_negative_one_prec_debug); register_demo!(runner, demo_float_one_half_prec); register_demo!(runner, demo_float_one_half_prec_debug); register_bench!(runner, benchmark_float_min_positive_value_prec); register_bench!(runner, benchmark_float_abs_is_min_positive_value); register_bench!(runner, benchmark_float_max_finite_value_with_prec); register_bench!(runner, benchmark_float_abs_is_max_finite_value_with_prec); register_bench!(runner, benchmark_float_one_prec_library_comparison); register_bench!(runner, benchmark_float_two_prec_library_comparison); register_bench!(runner, benchmark_float_negative_one_prec_library_comparison); register_bench!(runner, benchmark_float_one_half_prec_library_comparison); } fn demo_float_min_positive_value_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "min_positive_value_prec({}) = {}", p, Float::min_positive_value_prec(p) ); } } fn demo_float_min_positive_value_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "min_positive_value_prec({}) = {:#x}", p, ComparableFloat(Float::min_positive_value_prec(p)) ); } } fn demo_float_abs_is_min_positive_value(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.abs_is_min_positive_value() { println!("|{x}| is the minimum positive value"); } else { println!("|{x}| is not the minimum positive value"); } } } fn demo_float_abs_is_min_positive_value_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.abs_is_min_positive_value() { println!("|{:#x}| is the minimum positive value", ComparableFloat(x),); } else { println!( "|{:#x}| is not the minimum positive value", ComparableFloat(x), ); } } } fn demo_float_max_finite_value_with_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "max_finite_value_with_prec({}) = {}", p, Float::max_finite_value_with_prec(p) ); } } fn demo_float_max_finite_value_with_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "max_finite_value_with_prec({}) = {:#x}", p, ComparableFloat(Float::max_finite_value_with_prec(p)) ); } } fn demo_float_abs_is_max_finite_value_with_prec(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { if x.abs_is_max_finite_value_with_prec() { println!("|{x}| is the maximum positive value with its precision"); } else { println!("|{x}| is not the maximum positive value with its precision"); } } } fn demo_float_abs_is_max_finite_value_with_prec_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { if x.abs_is_max_finite_value_with_prec() { println!( "|{:#x}| is the maximum positive value with its precision", ComparableFloat(x) ); } else { println!( "|{:#x}| is not the maximum positive value with its precision", ComparableFloat(x) ); } } } fn demo_float_one_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("one_prec({}) = {}", p, Float::one_prec(p)); } } fn demo_float_one_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "one_prec({}) = {:#x}", p, ComparableFloat(Float::one_prec(p)) ); } } fn demo_float_two_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("two_prec({}) = {}", p, Float::two_prec(p)); } } fn demo_float_two_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "two_prec({}) = {:#x}", p, ComparableFloat(Float::two_prec(p)) ); } } fn demo_float_negative_one_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("negative_one_prec({}) = {}", p, Float::negative_one_prec(p)); } } fn demo_float_negative_one_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "negative_one_prec({}) = {:#x}", p, ComparableFloat(Float::negative_one_prec(p)) ); } } fn demo_float_one_half_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("one_half_prec({}) = {}", p, Float::one_half_prec(p)); } } fn demo_float_one_half_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "one_half_prec({}) = {:#x}", p, ComparableFloat(Float::one_half_prec(p)) ); } } fn benchmark_float_min_positive_value_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.min_positive_value_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| { no_out!(Float::min_positive_value_prec(p)); })], ); } fn benchmark_float_abs_is_min_positive_value( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.abs_is_min_positive_value()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(x.abs_is_min_positive_value()); })], ); } fn benchmark_float_max_finite_value_with_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.max_finite_value_with_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| { no_out!(Float::max_finite_value_with_prec(p)); })], ); } fn benchmark_float_abs_is_max_finite_value_with_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.abs_is_max_positive_value_with_prec()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(x.abs_is_max_finite_value_with_prec()); })], ); } fn benchmark_float_one_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.one_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::one_prec(p))), ("rug", &mut |p| { no_out!(rug::Float::with_val(u32::exact_from(p), 1.0)); }), ], ); } fn benchmark_float_two_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.two_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::two_prec(p))), ("rug", &mut |p| { no_out!(rug::Float::with_val(u32::exact_from(p), 2.0)); }), ], ); } fn benchmark_float_negative_one_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.negative_one_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::negative_one_prec(p))), ("rug", &mut |p| { no_out!(rug::Float::with_val(u32::exact_from(p), -1.0)); }), ], ); } fn benchmark_float_one_half_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.one_half_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::one_half_prec(p))), ("rug", &mut |p| { no_out!(rug::Float::with_val(u32::exact_from(p), 0.5)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/get_and_set.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, max_pair_1_complexity_pair_2_bucketer, max_triple_1_float_complexity_triple_2_bucketer, pair_2_float_complexity_bucketer, pair_2_max_pair_1_complexity_pair_2_bucketer, pair_2_max_triple_1_float_complexity_triple_2_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_1_rm, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1_rm, float_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_to_significand); register_demo!(runner, demo_float_to_significand_debug); register_demo!(runner, demo_float_to_significand_extreme); register_demo!(runner, demo_float_to_significand_extreme_debug); register_demo!(runner, demo_float_into_significand); register_demo!(runner, demo_float_into_significand_debug); register_demo!(runner, demo_float_significand_ref); register_demo!(runner, demo_float_significand_ref_debug); register_demo!(runner, demo_float_get_exponent); register_demo!(runner, demo_float_get_exponent_debug); register_demo!(runner, demo_float_get_exponent_extreme); register_demo!(runner, demo_float_get_exponent_extreme_debug); register_demo!(runner, demo_float_get_prec); register_demo!(runner, demo_float_get_prec_debug); register_demo!(runner, demo_float_get_prec_extreme); register_demo!(runner, demo_float_get_prec_extreme_debug); register_demo!(runner, demo_float_get_min_prec); register_demo!(runner, demo_float_get_min_prec_debug); register_demo!(runner, demo_float_get_min_prec_extreme); register_demo!(runner, demo_float_get_min_prec_extreme_debug); register_demo!(runner, demo_float_set_prec_round); register_demo!(runner, demo_float_set_prec_round_debug); register_demo!(runner, demo_float_set_prec_round_extreme); register_demo!(runner, demo_float_set_prec_round_extreme_debug); register_demo!(runner, demo_float_set_prec); register_demo!(runner, demo_float_set_prec_debug); register_demo!(runner, demo_float_set_prec_extreme); register_demo!(runner, demo_float_set_prec_extreme_debug); register_demo!(runner, demo_float_from_float_prec_round); register_demo!(runner, demo_float_from_float_prec_round_debug); register_demo!(runner, demo_float_from_float_prec_round_ref); register_demo!(runner, demo_float_from_float_prec_round_ref_debug); register_demo!(runner, demo_float_from_float_prec); register_demo!(runner, demo_float_from_float_prec_debug); register_demo!(runner, demo_float_from_float_prec_ref); register_demo!(runner, demo_float_from_float_prec_ref_debug); register_bench!(runner, benchmark_float_to_significand_evaluation_strategy); register_bench!(runner, benchmark_float_significand_ref_library_comparison); register_bench!(runner, benchmark_float_get_exponent_library_comparison); register_bench!(runner, benchmark_float_get_prec_library_comparison); register_bench!(runner, benchmark_float_get_min_prec); register_bench!(runner, benchmark_float_set_prec_round_library_comparison); register_bench!(runner, benchmark_float_set_prec_round_evaluation_strategy); register_bench!(runner, benchmark_float_set_prec_library_comparison); register_bench!(runner, benchmark_float_set_prec_evaluation_strategy); } fn demo_float_to_significand(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("to_significand({}) = {:?}", x, x.to_significand()); } } fn demo_float_to_significand_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "to_significand({:#x}) = {:?}", ComparableFloatRef(&x), x.to_significand() ); } } fn demo_float_to_significand_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("to_significand({}) = {:?}", x, x.to_significand()); } } fn demo_float_to_significand_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "to_significand({:#x}) = {:?}", ComparableFloatRef(&x), x.to_significand() ); } } fn demo_float_into_significand(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "into_significand({}) = {:?}", x.clone(), x.into_significand() ); } } fn demo_float_into_significand_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "into_significand({:#x}) = {:?}", ComparableFloat(x.clone()), x.into_significand() ); } } fn demo_float_significand_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("significand_ref({}) = {:?}", x, x.significand_ref()); } } fn demo_float_significand_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "significand_ref({:#x}) = {:?}", ComparableFloatRef(&x), x.significand_ref() ); } } fn demo_float_get_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("get_exponent({}) = {:?}", x, x.get_exponent()); } } fn demo_float_get_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "get_exponent({:#x}) = {:?}", ComparableFloatRef(&x), x.get_exponent() ); } } fn demo_float_get_exponent_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("get_exponent({}) = {:?}", x, x.get_exponent()); } } fn demo_float_get_exponent_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "get_exponent({:#x}) = {:?}", ComparableFloatRef(&x), x.get_exponent() ); } } fn demo_float_get_prec(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("get_prec({}) = {:?}", x, x.get_prec()); } } fn demo_float_get_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "get_prec({:#x}) = {:?}", ComparableFloatRef(&x), x.get_prec() ); } } fn demo_float_get_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("get_prec({}) = {:?}", x, x.get_prec()); } } fn demo_float_get_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "get_prec({:#x}) = {:?}", ComparableFloatRef(&x), x.get_prec() ); } } fn demo_float_get_min_prec(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("get_min_prec({}) = {:?}", x, x.get_min_prec()); } } fn demo_float_get_min_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "get_min_prec({:#x}) = {:?}", ComparableFloatRef(&x), x.get_min_prec() ); } } fn demo_float_get_min_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("get_min_prec({}) = {:?}", x, x.get_min_prec()); } } fn demo_float_get_min_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "get_min_prec({:#x}) = {:?}", ComparableFloatRef(&x), x.get_min_prec() ); } } fn demo_float_set_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let old_x = x.clone(); let o = x.set_prec_round(prec, rm); println!("x := {old_x}; x.set_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let old_x = x.clone(); let o = x.set_prec_round(prec, rm); println!( "x := {:#x}; x.set_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(old_x), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_set_prec_round_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let old_x = x.clone(); let o = x.set_prec_round(prec, rm); println!("x := {old_x}; x.set_prec_round({prec}, {rm}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_round_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_4() .get(gm, config) .take(limit) { let old_x = x.clone(); let o = x.set_prec_round(prec, rm); println!( "x := {:#x}; x.set_prec_round({}, {}) = {:?}; x = {:#x}", ComparableFloat(old_x), prec, rm, o, ComparableFloat(x) ); } } fn demo_float_set_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let old_x = x.clone(); let o = x.set_prec(prec); println!("x := {old_x}; x.set_prec({prec}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let old_x = x.clone(); let o = x.set_prec(prec); println!( "x := {:#x}; x.set_prec({}) = {:?}; x = {:#x}", ComparableFloat(old_x), prec, o, ComparableFloat(x) ); } } fn demo_float_set_prec_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let old_x = x.clone(); let o = x.set_prec(prec); println!("x := {old_x}; x.set_prec({prec}) = {o:?}; x = {x}"); } } fn demo_float_set_prec_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, prec) in float_unsigned_pair_gen_var_4().get(gm, config).take(limit) { let old_x = x.clone(); let o = x.set_prec(prec); println!( "x := {:#x}; x.set_prec({}) = {:?}; x = {:#x}", ComparableFloat(old_x), prec, o, ComparableFloat(x) ); } } fn demo_float_from_float_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (y, o) = Float::from_float_prec_round(x.clone(), prec, rm); println!("Float::from_float_prec_round({x}, {prec}, {rm}) = ({y}, {o:?})"); } } fn demo_float_from_float_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (y, o) = Float::from_float_prec_round(x.clone(), prec, rm); println!("Float::from_float_prec_round({x:#x}, {prec}, {rm}) = ({y:#x}, {o:?})"); } } fn demo_float_from_float_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (y, o) = Float::from_float_prec_round_ref(&x, prec, rm); println!("Float::from_float_prec_round_ref(&{x}, {prec}, {rm}) = ({y}, {o:?})"); } } fn demo_float_from_float_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec, rm) in float_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (y, o) = Float::from_float_prec_round_ref(&x, prec, rm); println!("Float::from_float_prec_round_ref(&{x:#x}, {prec}, {rm}) = ({y:#x}, {o:?})"); } } fn demo_float_from_float_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (y, o) = Float::from_float_prec(x.clone(), prec); println!("Float::from_float_prec({x}, {prec}) = ({y}, {o:?})"); } } fn demo_float_from_float_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (y, o) = Float::from_float_prec(x.clone(), prec); println!("Float::from_float_prec({x:#x}, {prec}) = ({y:#x}, {o:?})"); } } fn demo_float_from_float_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (y, o) = Float::from_float_prec_ref(&x, prec); println!("Float::from_float_prec_ref(&{x}, {prec}) = ({y}, {o:?})"); } } fn demo_float_from_float_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, prec) in float_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let (y, o) = Float::from_float_prec_ref(&x, prec); println!("Float::from_float_prec_ref(&{x:#x}, {prec}) = ({y:#x}, {o:?})"); } } fn benchmark_float_to_significand_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.to_significand()", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.to_significand()", &mut |x| { no_out!(x.to_significand()); }), ("Float.into_significand()", &mut |x| { no_out!(x.into_significand()); }), ("Float.significand_ref()", &mut |x| { no_out!(x.significand_ref()); }), ], ); } fn benchmark_float_significand_ref_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.significand_ref()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.significand_ref())), ("rug", &mut |(x, _)| no_out!(x.get_significand())), ], ); } fn benchmark_float_get_exponent_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.get_exponent()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.get_exponent())), ("rug", &mut |(x, _)| no_out!(x.get_exp())), ], ); } fn benchmark_float_get_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.get_prec()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, x)| no_out!(x.get_prec())), ("rug", &mut |(x, _)| no_out!(x.prec())), ], ); } fn benchmark_float_get_min_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.get_min_prec()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.get_min_prec()))], ); } fn benchmark_float_set_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.set_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, float_unsigned_rounding_mode_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_max_triple_1_float_complexity_triple_2_bucketer("x", "precision"), &mut [ ("Malachite", &mut |(_, (mut x, prec, rm))| { no_out!(x.set_prec_round(prec, rm)); }), ("rug", &mut |((mut x, prec, rm), _)| { no_out!(x.set_prec_round(u32::exact_from(prec), rm)); }), ], ); } fn benchmark_float_set_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.set_prec_round(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, float_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &max_triple_1_float_complexity_triple_2_bucketer("x", "precision"), &mut [ ("Float::set_prec_round", &mut |(mut x, prec, rm)| { no_out!(x.set_prec_round(prec, rm)); }), ("Float::from_float_prec_round", &mut |(x, prec, rm)| { no_out!(Float::from_float_prec_round(x, prec, rm)); }), ("Float::from_float_prec_round_ref", &mut |(x, prec, rm)| { no_out!(Float::from_float_prec_round_ref(&x, prec, rm)); }), ("clone and Float::set_prec_round", &mut |(x, prec, rm)| { let mut x = x.clone(); no_out!(x.set_prec_round(prec, rm)); }), ], ); } fn benchmark_float_set_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.set_prec(u64)", BenchmarkType::LibraryComparison, float_unsigned_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_max_pair_1_complexity_pair_2_bucketer("x", "precision"), &mut [ ("Malachite", &mut |(_, (mut x, prec))| { no_out!(x.set_prec(prec)); }), ("rug", &mut |((mut x, prec), _)| { no_out!(x.set_prec(u32::exact_from(prec))); }), ], ); } fn benchmark_float_set_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.set_prec(u64)", BenchmarkType::EvaluationStrategy, float_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &max_pair_1_complexity_pair_2_bucketer("x", "precision"), &mut [ ("Float::set_prec", &mut |(mut x, prec)| { no_out!(x.set_prec(prec)); }), ("Float::from_float_prec", &mut |(x, prec)| { no_out!(Float::from_float_prec(x, prec)); }), ("Float::from_float_prec_ref", &mut |(x, prec)| { no_out!(Float::from_float_prec_ref(&x, prec)); }), ("clone and Float::set_prec", &mut |(x, prec)| { let mut x = x.clone(); no_out!(x.set_prec(prec)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { classification::register(runner); complexity::register(runner); constants::register(runner); get_and_set::register(runner); overflow_and_underflow::register(runner); ulp::register(runner); } mod classification; mod complexity; mod constants; mod get_and_set; mod overflow_and_underflow; mod ulp; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/overflow_and_underflow.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_1_float_complexity_bucketer; use malachite_float::test_util::generators::float_ordering_pair_gen; use malachite_float::{test_overflow, test_underflow}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_test_overflow); register_demo!(runner, demo_float_test_overflow_debug); register_demo!(runner, demo_float_test_underflow); register_demo!(runner, demo_float_test_underflow_debug); register_bench!(runner, benchmark_float_test_overflow); register_bench!(runner, benchmark_float_test_underflow); } fn demo_float_test_overflow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, o) in float_ordering_pair_gen().get(gm, config).take(limit) { println!("test_overflow({}, {:?}) = {}", x, o, test_overflow(&x, o)); } } fn demo_float_test_overflow_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, o) in float_ordering_pair_gen().get(gm, config).take(limit) { println!( "test_overflow({:#x}, {:?}) = {}", ComparableFloatRef(&x), o, test_overflow(&x, o) ); } } fn demo_float_test_underflow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, o) in float_ordering_pair_gen().get(gm, config).take(limit) { println!("test_underflow({}, {:?}) = {}", x, o, test_underflow(&x, o)); } } fn demo_float_test_underflow_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, o) in float_ordering_pair_gen().get(gm, config).take(limit) { println!( "test_underflow({:#x}, {:?}) = {}", ComparableFloatRef(&x), o, test_underflow(&x, o) ); } } fn benchmark_float_test_overflow(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ulp()", BenchmarkType::Single, float_ordering_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(x, o)| no_out!(test_overflow(&x, o)))], ); } fn benchmark_float_test_underflow(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ulp()", BenchmarkType::Single, float_ordering_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(x, o)| no_out!(test_overflow(&x, o)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/basic/ulp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::common::to_hex_string; use malachite_float::test_util::generators::{ float_gen, float_gen_var_3, float_gen_var_12, float_gen_var_13, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_ulp); register_demo!(runner, demo_float_ulp_debug); register_demo!(runner, demo_float_ulp_extreme); register_demo!(runner, demo_float_ulp_extreme_debug); register_demo!(runner, demo_float_increment); register_demo!(runner, demo_float_increment_debug); register_demo!(runner, demo_float_increment_extreme); register_demo!(runner, demo_float_increment_extreme_debug); register_demo!(runner, demo_float_decrement); register_demo!(runner, demo_float_decrement_debug); register_demo!(runner, demo_float_decrement_extreme); register_demo!(runner, demo_float_decrement_extreme_debug); register_bench!(runner, benchmark_float_ulp); register_bench!(runner, benchmark_float_increment); register_bench!(runner, benchmark_float_decrement); } fn demo_float_ulp(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("ulp({}) = {:?}", x, x.ulp()); } } fn demo_float_ulp_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!( "ulp({:#x}) = {}", ComparableFloatRef(&x), x.ulp().map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_ulp_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("ulp({}) = {:?}", x, x.ulp()); } } fn demo_float_ulp_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "ulp({:#x}) = {}", ComparableFloatRef(&x), x.ulp().map_or("None".to_string(), |f| to_hex_string(&f)) ); } } fn demo_float_increment(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_3().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!("x := {old_x}; x.increment(); x = {x}"); } } fn demo_float_increment_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_3().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!( "x := {:#x}; x.increment(); x = {:#x}", ComparableFloat(old_x), ComparableFloat(x) ); } } fn demo_float_increment_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_13().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!("x := {old_x}; x.increment(); x = {x}"); } } fn demo_float_increment_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_13().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!( "x := {:#x}; x.increment(); x = {:#x}", ComparableFloat(old_x), ComparableFloat(x) ); } } fn demo_float_decrement(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_3().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!("x := {old_x}; x.increment(); x = {x}"); } } fn demo_float_decrement_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_3().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!( "x := {:#x}; x.increment(); x = {:#x}", ComparableFloat(old_x), ComparableFloat(x) ); } } fn demo_float_decrement_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_13().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!("x := {old_x}; x.increment(); x = {x}"); } } fn demo_float_decrement_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in float_gen_var_13().get(gm, config).take(limit) { let old_x = x.clone(); x.increment(); println!( "x := {:#x}; x.increment(); x = {:#x}", ComparableFloat(old_x), ComparableFloat(x) ); } } fn benchmark_float_ulp(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.ulp()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.ulp()))], ); } fn benchmark_float_increment(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.increment()", BenchmarkType::Single, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |mut x| x.increment())], ); } fn benchmark_float_decrement(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.decrement()", BenchmarkType::Single, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |mut x| x.decrement())], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_float_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp); register_demo!(runner, demo_float_partial_cmp_debug); register_demo!(runner, demo_float_partial_cmp_extreme); register_demo!(runner, demo_float_partial_cmp_extreme_debug); register_demo!(runner, demo_comparable_float_partial_cmp); register_demo!(runner, demo_comparable_float_partial_cmp_debug); register_demo!(runner, demo_comparable_float_partial_cmp_extreme); register_demo!(runner, demo_comparable_float_partial_cmp_extreme_debug); register_demo!(runner, demo_comparable_float_ref_partial_cmp); register_demo!(runner, demo_comparable_float_ref_partial_cmp_debug); register_bench!(runner, benchmark_float_partial_cmp_library_comparison); register_bench!(runner, benchmark_comparable_float_cmp); register_bench!(runner, benchmark_comparable_float_ref_cmp); } fn demo_float_partial_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{cx:#x} and {cy:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {cy:#x}"), Some(Equal) => println!("{cx:#x} = {cy:#x}"), Some(Greater) => println!("{cx:#x} > {cy:#x}"), } } } fn demo_float_partial_cmp_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{cx:#x} and {cy:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {cy:#x}"), Some(Equal) => println!("{cx:#x} = {cy:#x}"), Some(Greater) => println!("{cx:#x} > {cy:#x}"), } } } fn demo_comparable_float_partial_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); match cx.partial_cmp(&cy) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_comparable_float_partial_cmp_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x); let cy = ComparableFloat(y); match cx.partial_cmp(&cy) { None => println!("{cx} and {cy} are incomparable"), Some(Less) => println!("{cx:#x} < {cy:#x}"), Some(Equal) => println!("{cx:#x} = {cy:#x}"), Some(Greater) => println!("{cx:#x} > {cy:#x}"), } } } fn demo_comparable_float_partial_cmp_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); match cx.partial_cmp(&cy) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_comparable_float_partial_cmp_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x); let cy = ComparableFloat(y); match cx.partial_cmp(&cy) { None => println!("{cx} and {cy} are incomparable"), Some(Less) => println!("{cx:#x} < {cy:#x}"), Some(Equal) => println!("{cx:#x} = {cy:#x}"), Some(Greater) => println!("{cx:#x} > {cy:#x}"), } } } fn demo_comparable_float_ref_partial_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match cx.partial_cmp(&cy) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_comparable_float_ref_partial_cmp_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match cx.partial_cmp(&cy) { None => println!("{cx} and {cy} are incomparable"), Some(Less) => println!("{cx:#x} < {cy:#x}"), Some(Equal) => println!("{cx:#x} = {cy:#x}"), Some(Greater) => println!("{cx:#x} > {cy:#x}"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp(&Integer)", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_comparable_float_cmp(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "ComparableFloat.cmp(&ComparableFloat)", BenchmarkType::Single, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(ComparableFloat(x).cmp(&ComparableFloat(y))); })], ); } #[allow(unused_must_use)] fn benchmark_comparable_float_ref_cmp( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloatRef.cmp(&ComparableFloatRef)", BenchmarkType::Single, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(ComparableFloatRef(&x).cmp(&ComparableFloatRef(&y))); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_float_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_abs); register_demo!(runner, demo_float_partial_cmp_abs_debug); register_demo!(runner, demo_float_partial_cmp_abs_extreme); register_demo!(runner, demo_float_partial_cmp_abs_extreme_debug); register_demo!(runner, demo_comparable_float_partial_cmp_abs); register_demo!(runner, demo_comparable_float_partial_cmp_abs_debug); register_demo!(runner, demo_comparable_float_partial_cmp_abs_extreme); register_demo!(runner, demo_comparable_float_partial_cmp_abs_extreme_debug); register_demo!(runner, demo_comparable_float_ref_partial_cmp_abs); register_demo!(runner, demo_comparable_float_ref_partial_cmp_abs_debug); register_bench!(runner, benchmark_float_partial_cmp_abs_library_comparison); register_bench!(runner, benchmark_float_partial_cmp_abs_algorithms); register_bench!(runner, benchmark_comparable_float_cmp_abs_algorithms); register_bench!(runner, benchmark_comparable_float_ref_cmp_abs_algorithms); } fn demo_float_partial_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{cx:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{cy:#x}|"), } } } fn demo_float_partial_cmp_abs_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{cx:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{cy:#x}|"), } } } fn demo_comparable_float_partial_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); match cx.partial_cmp_abs(&cy) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_comparable_float_partial_cmp_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x); let cy = ComparableFloat(y); match cx.partial_cmp_abs(&cy) { None => println!("|{cx}| and |{cy}| are incomparable"), Some(Less) => println!("|{cx:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{cy:#x}|"), } } } fn demo_comparable_float_partial_cmp_abs_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); match cx.partial_cmp_abs(&cy) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_comparable_float_partial_cmp_abs_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x); let cy = ComparableFloat(y); match cx.partial_cmp_abs(&cy) { None => println!("|{cx}| and |{cy}| are incomparable"), Some(Less) => println!("|{cx:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{cy:#x}|"), } } } fn demo_comparable_float_ref_partial_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match cx.partial_cmp_abs(&cy) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_comparable_float_ref_partial_cmp_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); match cx.partial_cmp_abs(&cy) { None => println!("|{cx}| and |{cy}| are incomparable"), Some(Less) => println!("|{cx:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{cy:#x}|"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp_abs(&Integer)", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((x, y), _)| no_out!(x.cmp_abs(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp_abs(&Integer)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(x.partial_cmp_abs(&y)); }), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_comparable_float_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloat.cmp_abs(&ComparableFloat)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(ComparableFloat(x).cmp_abs(&ComparableFloat(y))); }), ("using abs", &mut |(x, y)| { no_out!(ComparableFloat(x.abs()).partial_cmp(&ComparableFloat(y.abs()))); }), ], ); } #[allow(unused_must_use)] fn benchmark_comparable_float_ref_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloatRef.cmp_abs(&ComparableFloatRef)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(ComparableFloatRef(&x).cmp_abs(&ComparableFloatRef(&y))); }), ("using abs", &mut |(x, y)| { no_out!(ComparableFloatRef(&x.abs()).partial_cmp(&ComparableFloatRef(&y.abs()))); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_max_complexity_bucketer, pair_float_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_eq); register_demo!(runner, demo_float_eq_debug); register_demo!(runner, demo_float_eq_extreme); register_demo!(runner, demo_float_eq_extreme_debug); register_demo!(runner, demo_comparable_float_eq); register_demo!(runner, demo_comparable_float_eq_debug); register_demo!(runner, demo_comparable_float_eq_extreme); register_demo!(runner, demo_comparable_float_eq_extreme_debug); register_demo!(runner, demo_comparable_float_ref_eq); register_demo!(runner, demo_comparable_float_ref_eq_debug); register_bench!(runner, benchmark_float_eq_library_comparison); register_bench!(runner, benchmark_comparable_float_eq); register_bench!(runner, benchmark_comparable_float_ref_eq); } fn demo_float_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_eq_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if x == y { println!("{cx:#x} = {cy:#x}"); } else { println!("{cx:#x} ≠ {cy:#x}"); } } } fn demo_float_eq_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_eq_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if x == y { println!("{cx:#x} = {cy:#x}"); } else { println!("{cx:#x} ≠ {cy:#x}"); } } } fn demo_comparable_float_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx == cy { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_comparable_float_eq_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx == cy { println!("{cx:#x} = {cy:#x}"); } else { println!("{cx:#x} ≠ {cy:#x}"); } } } fn demo_comparable_float_eq_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx == cy { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_comparable_float_eq_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx == cy { println!("{cx:#x} = {cy:#x}"); } else { println!("{cx:#x} ≠ {cy:#x}"); } } } fn demo_comparable_float_ref_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if cx == cy { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_comparable_float_ref_eq_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if cx == cy { println!("{cx:#x} = {cy:#x}"); } else { println!("{cx:#x} ≠ {cy:#x}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float == Float", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_comparable_float_eq(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "ComparableFloat == ComparableFloat", BenchmarkType::Single, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(ComparableFloat(x) == ComparableFloat(y)); })], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_comparable_float_ref_eq( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloatRef == ComparableFloatRef", BenchmarkType::Single, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(ComparableFloatRef(&x) == ComparableFloatRef(&y)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::pair_float_max_complexity_bucketer; use malachite_float::test_util::generators::{float_pair_gen, float_pair_gen_var_10}; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_eq_abs); register_demo!(runner, demo_float_eq_abs_debug); register_demo!(runner, demo_float_eq_abs_extreme); register_demo!(runner, demo_float_eq_abs_extreme_debug); register_demo!(runner, demo_comparable_float_eq_abs); register_demo!(runner, demo_comparable_float_eq_abs_debug); register_demo!(runner, demo_comparable_float_eq_abs_extreme); register_demo!(runner, demo_comparable_float_eq_abs_extreme_debug); register_demo!(runner, demo_comparable_float_ref_eq_abs); register_demo!(runner, demo_comparable_float_ref_eq_abs_debug); register_bench!(runner, benchmark_float_eq_abs_algorithms); register_bench!(runner, benchmark_comparable_float_eq_abs_algorithms); register_bench!(runner, benchmark_comparable_float_ref_eq_abs_algorithms); } fn demo_float_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{cx:#x}| = |{cy:#x}|"); } else { println!("|{cx:#x}| ≠ |{cy:#x}|"); } } } fn demo_float_eq_abs_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{cx:#x}| = |{cy:#x}|"); } else { println!("|{cx:#x}| ≠ |{cy:#x}|"); } } } fn demo_comparable_float_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx.eq_abs(&cy) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_comparable_float_eq_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx.eq_abs(&cy) { println!("|{cx:#x}| = |{cy:#x}|"); } else { println!("|{cx:#x}| ≠ |{cy:#x}|"); } } } fn demo_comparable_float_eq_abs_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx.eq_abs(&cy) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_comparable_float_eq_abs_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let cx = ComparableFloat(x.clone()); let cy = ComparableFloat(y.clone()); if cx.eq_abs(&cy) { println!("|{cx:#x}| = |{cy:#x}|"); } else { println!("|{cx:#x}| ≠ |{cy:#x}|"); } } } fn demo_comparable_float_ref_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if cx.eq_abs(&cy) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_comparable_float_ref_eq_abs_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); if cx.eq_abs(&cy) { println!("|{cx:#x}| = |{cy:#x}|"); } else { println!("|{cx:#x}| ≠ |{cy:#x}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.eq_abs(&Float)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_comparable_float_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloat.eq_abs(&ComparableFloat)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(ComparableFloat(x).eq_abs(&ComparableFloat(y))); }), ("default", &mut |(x, y)| { no_out!(ComparableFloat(x.abs()) == ComparableFloat(y.abs())); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_comparable_float_ref_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "ComparableFloatRef.eq_abs(&ComparableFloatRef)", BenchmarkType::Algorithms, float_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(ComparableFloatRef(&x).eq_abs(&ComparableFloatRef(&y))); }), ("default", &mut |(x, y)| { no_out!(ComparableFloatRef(&x.abs()) == ComparableFloatRef(&y.abs())); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_float_integer_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_eq_abs_integer); register_demo!(runner, demo_float_eq_abs_integer_debug); register_demo!(runner, demo_float_eq_abs_integer_extreme); register_demo!(runner, demo_float_eq_abs_integer_extreme_debug); register_demo!(runner, demo_integer_eq_abs_float); register_demo!(runner, demo_integer_eq_abs_float_debug); register_demo!(runner, demo_integer_eq_abs_float_extreme); register_demo!(runner, demo_integer_eq_abs_float_extreme_debug); register_bench!(runner, benchmark_float_eq_abs_integer_algorithms); register_bench!(runner, benchmark_integer_eq_abs_float_algorithms); } fn demo_float_eq_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:#x}|"); } else { println!("|{cx:#x}| ≠ |{y:#x}|"); } } } fn demo_float_eq_abs_integer_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_integer_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:#x}|"); } else { println!("|{cx:#x}| ≠ |{y:#x}|"); } } } fn demo_integer_eq_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_integer_eq_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:#x}| = |{cy:#x}|"); } else { println!("|{x:#x}| ≠ |{cy:#x}|"); } } } fn demo_integer_eq_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_integer_eq_abs_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:#x}| = |{cy:#x}|"); } else { println!("|{x:#x}| ≠ |{cy:#x}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.eq_abs(&Integer)", BenchmarkType::Algorithms, float_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_integer_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_eq_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_abs(&Float)", BenchmarkType::Algorithms, float_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_integer_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_float_natural_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_eq_abs_natural); register_demo!(runner, demo_float_eq_abs_natural_debug); register_demo!(runner, demo_float_eq_abs_natural_extreme); register_demo!(runner, demo_float_eq_abs_natural_extreme_debug); register_demo!(runner, demo_natural_eq_abs_float); register_demo!(runner, demo_natural_eq_abs_float_debug); register_demo!(runner, demo_natural_eq_abs_float_extreme); register_demo!(runner, demo_natural_eq_abs_float_extreme_debug); register_bench!(runner, benchmark_float_eq_abs_natural_algorithms); register_bench!(runner, benchmark_natural_eq_abs_float_algorithms); } fn demo_float_eq_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_natural_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:#x}|"); } else { println!("|{cx:#x}| ≠ |{y:#x}|"); } } } fn demo_float_eq_abs_natural_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_natural_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:#x}|"); } else { println!("|{cx:#x}| ≠ |{y:#x}|"); } } } fn demo_natural_eq_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_natural_eq_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:#x}| = |{cy:#x}|"); } else { println!("|{x:#x}| ≠ |{cy:#x}|"); } } } fn demo_natural_eq_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_natural_eq_abs_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:#x}| = |{cy:#x}|"); } else { println!("|{x:#x}| ≠ |{cy:#x}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.eq_abs(&Natural)", BenchmarkType::Algorithms, float_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_natural_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_eq_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_abs(&Float)", BenchmarkType::Algorithms, float_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_natural_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x == y.abs())), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_eq_abs_primitive_float); register_primitive_float_demos!(runner, demo_float_eq_abs_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_eq_abs_primitive_float_extreme); register_primitive_float_demos!(runner, demo_float_eq_abs_primitive_float_extreme_debug); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_float); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_float_extreme); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_float_extreme_debug); register_primitive_float_benches!(runner, benchmark_float_eq_abs_primitive_float_algorithms); register_primitive_float_benches!(runner, benchmark_primitive_float_eq_abs_float_algorithms); } fn demo_float_eq_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{}| = |{}|", x, NiceFloat(y)); } else { println!("|{}| ≠ |{}|", x, NiceFloat(y)); } } } fn demo_float_eq_abs_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{:#x}| = |{}|", cx, NiceFloat(y)); } else { println!("|{:#x}| ≠ |{}|", cx, NiceFloat(y)); } } } fn demo_float_eq_abs_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{}| = |{}|", x, NiceFloat(y)); } else { println!("|{}| ≠ |{}|", x, NiceFloat(y)); } } } fn demo_float_eq_abs_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{:#x}| = |{}|", cx, NiceFloat(y)); } else { println!("|{:#x}| ≠ |{}|", cx, NiceFloat(y)); } } } fn demo_primitive_float_eq_abs_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{}| = |{}|", NiceFloat(x), y); } else { println!("|{}| ≠ |{}|", NiceFloat(x), y); } } } fn demo_primitive_float_eq_abs_float_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{}| = |{:#x}|", NiceFloat(x), cy); } else { println!("|{}| ≠ |{:#x}|", NiceFloat(x), cy); } } } fn demo_primitive_float_eq_abs_float_extreme + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{}| = |{}|", NiceFloat(x), y); } else { println!("|{}| ≠ |{}|", NiceFloat(x), y); } } } fn demo_primitive_float_eq_abs_float_extreme_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{}| = |{:#x}|", NiceFloat(x), cy); } else { println!("|{}| ≠ |{:#x}|", NiceFloat(x), cy); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: EqAbs + PartialEq, { run_benchmark( &format!("Float.eq_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_primitive_float_eq_abs_float_algorithms< T: EqAbs + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_float_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::{ pair_float_signed_max_complexity_bucketer, pair_float_unsigned_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_var_5, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_eq_abs_unsigned); register_unsigned_demos!(runner, demo_float_eq_abs_unsigned_debug); register_unsigned_demos!(runner, demo_float_eq_abs_unsigned_extreme); register_unsigned_demos!(runner, demo_float_eq_abs_unsigned_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_eq_abs_float); register_unsigned_demos!(runner, demo_unsigned_eq_abs_float_debug); register_unsigned_demos!(runner, demo_unsigned_eq_abs_float_extreme); register_unsigned_demos!(runner, demo_unsigned_eq_abs_float_extreme_debug); register_signed_demos!(runner, demo_float_eq_abs_signed); register_signed_demos!(runner, demo_float_eq_abs_signed_debug); register_signed_demos!(runner, demo_float_eq_abs_signed_extreme); register_signed_demos!(runner, demo_float_eq_abs_signed_extreme_debug); register_signed_demos!(runner, demo_signed_eq_abs_float); register_signed_demos!(runner, demo_signed_eq_abs_float_debug); register_signed_demos!(runner, demo_signed_eq_abs_float_extreme); register_signed_demos!(runner, demo_signed_eq_abs_float_extreme_debug); register_unsigned_benches!(runner, benchmark_float_eq_abs_unsigned_algorithms); register_unsigned_benches!(runner, benchmark_unsigned_eq_abs_float_algorithms); register_signed_benches!(runner, benchmark_float_eq_abs_signed_algorithms); register_signed_benches!(runner, benchmark_signed_eq_abs_float_algorithms); } fn demo_float_eq_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Float: EqAbs, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:x}|"); } else { println!("|{cx:#x}| ≠ |{y:x}|"); } } } fn demo_float_eq_abs_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:x}|"); } else { println!("|{cx:#x}| ≠ |{y:x}|"); } } } fn demo_unsigned_eq_abs_float + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_unsigned_eq_abs_float_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:x}| = |{cy:#x}|"); } else { println!("|{x:x}| ≠ |{cy:#x}|"); } } } fn demo_unsigned_eq_abs_float_extreme + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_unsigned_eq_abs_float_extreme_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:x}| = |{cy:#x}|"); } else { println!("|{x:x}| ≠ |{cy:#x}|"); } } } fn demo_float_eq_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: EqAbs, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) where Float: EqAbs, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:x}|"); } else { println!("|{cx:#x}| ≠ |{y:x}|"); } } } fn demo_float_eq_abs_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: EqAbs, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y:x}|"); } else { println!("|{cx:#x}| ≠ |{y:x}|"); } } } fn demo_signed_eq_abs_float + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_signed_eq_abs_float_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:x}| = |{cy:#x}|"); } else { println!("|{x:x}| ≠ |{cy:#x}|"); } } } fn demo_signed_eq_abs_float_extreme + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_signed_eq_abs_float_extreme_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x:x}| = |{cy:#x}|"); } else { println!("|{x:x}| ≠ |{cy:#x}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: EqAbs + PartialEq, { run_benchmark( &format!("Float.eq_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_unsigned_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_unsigned_eq_abs_float_algorithms< T: EqAbs + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_unsigned_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x == y.abs())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: EqAbs + PartialEq<::Output>, { run_benchmark( &format!("Float.eq_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_signed_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs() == y.unsigned_abs()); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_signed_eq_abs_float_algorithms + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialEq, { run_benchmark( &format!("{}.eq_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_signed_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| { no_out!(x.unsigned_abs() == y.abs()); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/eq_abs_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_eq_abs_rational); register_demo!(runner, demo_float_eq_abs_rational_debug); register_demo!(runner, demo_float_eq_abs_rational_extreme); register_demo!(runner, demo_float_eq_abs_rational_extreme_debug); register_demo!(runner, demo_rational_eq_abs_float); register_demo!(runner, demo_rational_eq_abs_float_debug); register_demo!(runner, demo_rational_eq_abs_float_extreme); register_demo!(runner, demo_rational_eq_abs_float_extreme_debug); register_bench!(runner, benchmark_float_eq_abs_rational_algorithms); register_bench!(runner, benchmark_rational_eq_abs_float_algorithms); } fn demo_float_eq_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y}|"); } else { println!("|{cx:#x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_float_eq_abs_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x.eq_abs(&y) { println!("|{cx:#x}| = |{y}|"); } else { println!("|{cx:#x}| ≠ |{y}|"); } } } fn demo_rational_eq_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_rational_eq_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x}| = |{cy:#x}|"); } else { println!("|{x}| ≠ |{cy:#x}|"); } } } fn demo_rational_eq_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_rational_eq_abs_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x.eq_abs(&y) { println!("|{x}| = |{cy:#x}|"); } else { println!("|{x}| ≠ |{cy:#x}|"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_eq_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.eq_abs(&Rational)", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_eq_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.eq_abs(&Float)", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_comparable_float_hash); register_demo!(runner, demo_comparable_float_hash_debug); register_demo!(runner, demo_comparable_float_hash_extreme); register_demo!(runner, demo_comparable_float_hash_extreme_debug); register_demo!(runner, demo_comparable_float_ref_hash); register_demo!(runner, demo_comparable_float_ref_hash_debug); register_bench!(runner, benchmark_comparable_float_hash); register_bench!(runner, benchmark_comparable_float_ref_hash); } fn demo_comparable_float_hash(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("hash({}) = {}", x.clone(), hash(&ComparableFloat(x))); } } fn demo_comparable_float_hash_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let cx = ComparableFloat(x); println!("hash({:#x}) = {}", cx, hash(&cx)); } } fn demo_comparable_float_hash_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { println!("hash({}) = {}", x.clone(), hash(&ComparableFloat(x))); } } fn demo_comparable_float_hash_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen_var_12().get(gm, config).take(limit) { let cx = ComparableFloat(x); println!("hash({:#x}) = {}", cx, hash(&cx)); } } fn demo_comparable_float_ref_hash(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { println!("hash({}) = {}", x.clone(), hash(&ComparableFloatRef(&x))); } } fn demo_comparable_float_ref_hash_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in float_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); println!("hash({:#x}) = {}", cx, hash(&cx)); } } fn benchmark_comparable_float_hash(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float hash", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(hash(&ComparableFloat(x))))], ); } fn benchmark_comparable_float_ref_hash( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float hash", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(hash(&ComparableFloatRef(&x))))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); cmp_abs::register(runner); eq::register(runner); eq_abs::register(runner); eq_abs_integer::register(runner); eq_abs_natural::register(runner); eq_abs_primitive_float::register(runner); eq_abs_primitive_int::register(runner); eq_abs_rational::register(runner); hash::register(runner); partial_cmp_abs_integer::register(runner); partial_cmp_abs_natural::register(runner); partial_cmp_abs_primitive_float::register(runner); partial_cmp_abs_primitive_int::register(runner); partial_cmp_abs_rational::register(runner); partial_cmp_integer::register(runner); partial_cmp_natural::register(runner); partial_cmp_primitive_float::register(runner); partial_cmp_primitive_int::register(runner); partial_cmp_rational::register(runner); partial_eq_integer::register(runner); partial_eq_natural::register(runner); partial_eq_primitive_float::register(runner); partial_eq_primitive_int::register(runner); partial_eq_rational::register(runner); } mod cmp; mod cmp_abs; mod eq; mod eq_abs; mod eq_abs_integer; mod eq_abs_natural; mod eq_abs_primitive_float; mod eq_abs_primitive_int; mod eq_abs_rational; mod hash; mod partial_cmp_abs_integer; mod partial_cmp_abs_natural; mod partial_cmp_abs_primitive_float; mod partial_cmp_abs_primitive_int; mod partial_cmp_abs_rational; mod partial_cmp_integer; mod partial_cmp_natural; mod partial_cmp_primitive_float; mod partial_cmp_primitive_int; mod partial_cmp_rational; mod partial_eq_integer; mod partial_eq_natural; mod partial_eq_primitive_float; mod partial_eq_primitive_int; mod partial_eq_rational; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_float_integer_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_abs_integer); register_demo!(runner, demo_float_partial_cmp_abs_integer_debug); register_demo!(runner, demo_float_partial_cmp_abs_integer_extreme); register_demo!(runner, demo_float_partial_cmp_abs_integer_extreme_debug); register_demo!(runner, demo_integer_partial_cmp_abs_float); register_demo!(runner, demo_integer_partial_cmp_abs_float_debug); register_demo!(runner, demo_integer_partial_cmp_abs_float_extreme); register_demo!(runner, demo_integer_partial_cmp_abs_float_extreme_debug); register_bench!(runner, benchmark_float_partial_cmp_abs_integer_algorithms); register_bench!(runner, benchmark_integer_partial_cmp_abs_float_algorithms); } fn demo_float_partial_cmp_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_float_partial_cmp_abs_integer_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_integer_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_integer_partial_cmp_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_integer_partial_cmp_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } fn demo_integer_partial_cmp_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_integer_partial_cmp_abs_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp_abs(&Integer)", BenchmarkType::Algorithms, float_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_integer_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_partial_cmp_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp_abs(&Float)", BenchmarkType::Algorithms, float_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_integer_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| { no_out!(x.abs().partial_cmp_abs(&y.abs())); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_float_natural_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_abs_natural); register_demo!(runner, demo_float_partial_cmp_abs_natural_debug); register_demo!(runner, demo_float_partial_cmp_abs_natural_extreme); register_demo!(runner, demo_float_partial_cmp_abs_natural_extreme_debug); register_demo!(runner, demo_natural_partial_cmp_abs_float); register_demo!(runner, demo_natural_partial_cmp_abs_float_debug); register_demo!(runner, demo_natural_partial_cmp_abs_float_extreme); register_demo!(runner, demo_natural_partial_cmp_abs_float_extreme_debug); register_bench!(runner, benchmark_float_partial_cmp_abs_natural_algorithms); register_bench!(runner, benchmark_natural_partial_cmp_abs_float_algorithms); } fn demo_float_partial_cmp_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_natural_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_float_partial_cmp_abs_natural_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_natural_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_natural_partial_cmp_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_natural_partial_cmp_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } fn demo_natural_partial_cmp_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_natural_partial_cmp_abs_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp_abs(&Natural)", BenchmarkType::Algorithms, float_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_natural_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_partial_cmp_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp_abs(&Float)", BenchmarkType::Algorithms, float_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_natural_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x.partial_cmp(&y.abs()))), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_primitive_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_primitive_float_extreme); register_primitive_float_demos!( runner, demo_float_partial_cmp_abs_primitive_float_extreme_debug ); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_abs_float); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_abs_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_abs_float_extreme); register_primitive_float_demos!( runner, demo_primitive_float_partial_cmp_abs_float_extreme_debug ); register_primitive_float_benches!( runner, benchmark_float_partial_cmp_abs_primitive_float_algorithms ); register_primitive_float_benches!( runner, benchmark_primitive_float_partial_cmp_abs_float_algorithms ); } fn demo_float_partial_cmp_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{}| and |{}| are incomparable", x, NiceFloat(y)), Some(Less) => println!("|{}| < |{}|", x, NiceFloat(y)), Some(Equal) => println!("|{}| = |{}|", x, NiceFloat(y)), Some(Greater) => println!("|{}| > |{}|", x, NiceFloat(y)), } } } fn demo_float_partial_cmp_abs_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("{:#x} and |{}| are incomparable", cx, NiceFloat(y)), Some(Less) => println!("{:#x} < |{}|", cx, NiceFloat(y)), Some(Equal) => println!("{:#x} = |{}|", cx, NiceFloat(y)), Some(Greater) => println!("{:#x} > |{}|", cx, NiceFloat(y)), } } } fn demo_float_partial_cmp_abs_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{}| and |{}| are incomparable", x, NiceFloat(y)), Some(Less) => println!("|{}| < |{}|", x, NiceFloat(y)), Some(Equal) => println!("|{}| = |{}|", x, NiceFloat(y)), Some(Greater) => println!("|{}| > |{}|", x, NiceFloat(y)), } } } fn demo_float_partial_cmp_abs_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("{:#x} and |{}| are incomparable", cx, NiceFloat(y)), Some(Less) => println!("{:#x} < |{}|", cx, NiceFloat(y)), Some(Equal) => println!("{:#x} = |{}|", cx, NiceFloat(y)), Some(Greater) => println!("{:#x} > |{}|", cx, NiceFloat(y)), } } } fn demo_primitive_float_partial_cmp_abs_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{}| and |{}| are incomparable", NiceFloat(x), y), Some(Less) => println!("|{}| < |{}|", NiceFloat(x), y), Some(Equal) => println!("|{}| = |{}|", NiceFloat(x), y), Some(Greater) => println!("|{}| > |{}|", NiceFloat(x), y), } } } fn demo_primitive_float_partial_cmp_abs_float_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{}| and {:#x} are incomparable", NiceFloat(x), cy), Some(Less) => println!("|{}| < {:#x}", NiceFloat(x), cy), Some(Equal) => println!("|{}| = {:#x}", NiceFloat(x), cy), Some(Greater) => println!("|{}| > {:#x}", NiceFloat(x), cy), } } } fn demo_primitive_float_partial_cmp_abs_float_extreme + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{}| and |{}| are incomparable", NiceFloat(x), y), Some(Less) => println!("|{}| < |{}|", NiceFloat(x), y), Some(Equal) => println!("|{}| = |{}|", NiceFloat(x), y), Some(Greater) => println!("|{}| > |{}|", NiceFloat(x), y), } } } fn demo_primitive_float_partial_cmp_abs_float_extreme_debug< T: PartialOrdAbs + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{}| and {:#x} are incomparable", NiceFloat(x), cy), Some(Less) => println!("|{}| < {:#x}", NiceFloat(x), cy), Some(Equal) => println!("|{}| = {:#x}", NiceFloat(x), cy), Some(Greater) => println!("|{}| > {:#x}", NiceFloat(x), cy), } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Float.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_float_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_primitive_float_partial_cmp_abs_float_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_primitive_float_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_signed_max_complexity_bucketer, pair_2_pair_float_unsigned_max_complexity_bucketer, pair_float_signed_max_complexity_bucketer, pair_float_unsigned_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_rm, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_rm, float_unsigned_pair_gen_var_5, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_partial_cmp_abs_unsigned); register_unsigned_demos!(runner, demo_float_partial_cmp_abs_unsigned_debug); register_unsigned_demos!(runner, demo_float_partial_cmp_abs_unsigned_extreme); register_unsigned_demos!(runner, demo_float_partial_cmp_abs_unsigned_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_float); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_float_debug); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_float_extreme); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_float_extreme_debug); register_signed_demos!(runner, demo_float_partial_cmp_abs_signed); register_signed_demos!(runner, demo_float_partial_cmp_abs_signed_debug); register_signed_demos!(runner, demo_float_partial_cmp_abs_signed_extreme); register_signed_demos!(runner, demo_float_partial_cmp_abs_signed_extreme_debug); register_signed_demos!(runner, demo_signed_partial_cmp_abs_float); register_signed_demos!(runner, demo_signed_partial_cmp_abs_float_debug); register_signed_demos!(runner, demo_signed_partial_cmp_abs_float_extreme); register_signed_demos!(runner, demo_signed_partial_cmp_abs_float_extreme_debug); register_unsigned_benches!( runner, benchmark_float_partial_cmp_abs_unsigned_library_comparison ); register_unsigned_benches!(runner, benchmark_float_partial_cmp_abs_unsigned_algorithms); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_abs_float_library_comparison ); register_unsigned_benches!(runner, benchmark_unsigned_partial_cmp_abs_float_algorithms); register_signed_benches!( runner, benchmark_float_partial_cmp_abs_signed_library_comparison ); register_signed_benches!(runner, benchmark_float_partial_cmp_abs_signed_algorithms); register_signed_benches!( runner, benchmark_signed_partial_cmp_abs_float_library_comparison ); register_signed_benches!(runner, benchmark_signed_partial_cmp_abs_float_algorithms); } fn demo_float_partial_cmp_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_float_partial_cmp_abs_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_unsigned_partial_cmp_abs_float + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_unsigned_partial_cmp_abs_float_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } fn demo_unsigned_partial_cmp_abs_float_extreme + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_unsigned_partial_cmp_abs_float_extreme_debug< T: PartialOrdAbs + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:#x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } fn demo_float_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_float_partial_cmp_abs_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrdAbs, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y:#x} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y:#x}|"), Some(Equal) => println!("|{cx:#x}| = |{y:#x}|"), Some(Greater) => println!("|{cx:#x}| > |{y:#x}|"), } } } fn demo_signed_partial_cmp_abs_float + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_signed_partial_cmp_abs_float_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } fn demo_signed_partial_cmp_abs_float_extreme + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_signed_partial_cmp_abs_float_extreme_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x:x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x:#x}| < |{cy:#x}|"), Some(Equal) => println!("|{x:#x}| = |{cy:#x}|"), Some(Greater) => println!("|{x:#x}| > |{cy:#x}|"), } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_abs_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrdAbs, rug::Float: PartialOrd, { run_benchmark( &format!("Float.partial_cmp_abs(&{})", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((x, y), _)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Float.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_unsigned_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_unsigned_partial_cmp_abs_float_library_comparison< T: PartialOrdAbs + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Float)", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((y, x), _)| no_out!(x.partial_cmp(&y.abs()))), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_abs_float_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_unsigned_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| no_out!(x.partial_cmp(&y.abs()))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_abs_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrdAbs, rug::Float: PartialOrd<::Output>, { run_benchmark( &format!("Float.partial_cmp_abs(&{})", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((x, y), _)| { no_out!(x.abs().partial_cmp(&y.unsigned_abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrdAbs + PartialOrd<::Output>, { run_benchmark( &format!("Float.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, float_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_signed_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.unsigned_abs())); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_signed_partial_cmp_abs_float_library_comparison< T: PartialOrdAbs + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialOrd, { run_benchmark( &format!("{}.partial_cmp_abs(&Float)", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((y, x), _)| { no_out!(x.unsigned_abs().partial_cmp(&y.abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_abs_float_algorithms + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialOrd, { run_benchmark( &format!("{}.partial_cmp_abs(&Float)", T::NAME), BenchmarkType::Algorithms, float_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_float_signed_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| { no_out!(x.unsigned_abs().partial_cmp(&y.abs())); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_float_rational_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_abs_rational); register_demo!(runner, demo_float_partial_cmp_abs_rational_debug); register_demo!(runner, demo_float_partial_cmp_abs_rational_extreme); register_demo!(runner, demo_float_partial_cmp_abs_rational_extreme_debug); register_demo!(runner, demo_rational_partial_cmp_abs_float); register_demo!(runner, demo_rational_partial_cmp_abs_float_debug); register_demo!(runner, demo_rational_partial_cmp_abs_float_extreme); register_demo!(runner, demo_rational_partial_cmp_abs_float_extreme_debug); register_bench!(runner, benchmark_float_partial_cmp_abs_rational_algorithms); register_bench!(runner, benchmark_rational_partial_cmp_abs_float_algorithms); } fn demo_float_partial_cmp_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y}|"), Some(Equal) => println!("|{cx:#x}| = |{y}|"), Some(Greater) => println!("|{cx:#x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_float_partial_cmp_abs_rational_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp_abs(&y) { None => println!("|{cx:#x}| and {y} are incomparable"), Some(Less) => println!("|{cx:#x}| < |{y}|"), Some(Equal) => println!("|{cx:#x}| = |{y}|"), Some(Greater) => println!("|{cx:#x}| > |{y}|"), } } } fn demo_rational_partial_cmp_abs_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_rational_partial_cmp_abs_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x}| < |{cy:#x}|"), Some(Equal) => println!("|{x}| = |{cy:#x}|"), Some(Greater) => println!("|{x}| > |{cy:#x}|"), } } } fn demo_rational_partial_cmp_abs_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{y}| are incomparable"), Some(Less) => println!("|{x}| < |{y}|"), Some(Equal) => println!("|{x}| = |{y}|"), Some(Greater) => println!("|{x}| > |{y}|"), } } } fn demo_rational_partial_cmp_abs_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp_abs(&y) { None => println!("|{x}| and |{cy:#x}| are incomparable"), Some(Less) => println!("|{x}| < |{cy:#x}|"), Some(Equal) => println!("|{x}| = |{cy:#x}|"), Some(Greater) => println!("|{x}| > |{cy:#x}|"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp_abs(&Rational)", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_partial_cmp_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp_abs(&Float)", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("default", &mut |(y, x)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(y, x)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_2_pair_float_integer_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_rm, float_integer_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_integer); register_demo!(runner, demo_float_partial_cmp_integer_debug); register_demo!(runner, demo_float_partial_cmp_integer_extreme); register_demo!(runner, demo_float_partial_cmp_integer_extreme_debug); register_demo!(runner, demo_integer_partial_cmp_float); register_demo!(runner, demo_integer_partial_cmp_float_debug); register_demo!(runner, demo_integer_partial_cmp_float_extreme); register_demo!(runner, demo_integer_partial_cmp_float_extreme_debug); register_bench!( runner, benchmark_float_partial_cmp_integer_library_comparison ); register_bench!( runner, benchmark_integer_partial_cmp_float_library_comparison ); } fn demo_float_partial_cmp_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_float_partial_cmp_integer_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_integer_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_integer_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_integer_partial_cmp_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } fn demo_integer_partial_cmp_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_integer_partial_cmp_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp(&Integer)", BenchmarkType::LibraryComparison, float_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_integer_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp(&Float)", BenchmarkType::LibraryComparison, float_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_integer_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_2_pair_float_natural_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_rm, float_natural_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_natural); register_demo!(runner, demo_float_partial_cmp_natural_debug); register_demo!(runner, demo_float_partial_cmp_natural_extreme); register_demo!(runner, demo_float_partial_cmp_natural_extreme_debug); register_demo!(runner, demo_natural_partial_cmp_float); register_demo!(runner, demo_natural_partial_cmp_float_debug); register_demo!(runner, demo_natural_partial_cmp_float_extreme); register_demo!(runner, demo_natural_partial_cmp_float_extreme_debug); register_bench!( runner, benchmark_float_partial_cmp_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_cmp_float_library_comparison ); } fn demo_float_partial_cmp_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_natural_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_float_partial_cmp_natural_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_natural_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_natural_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_natural_partial_cmp_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } fn demo_natural_partial_cmp_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_natural_partial_cmp_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp(&Natural)", BenchmarkType::LibraryComparison, float_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_natural_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp(&Float)", BenchmarkType::LibraryComparison, float_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_natural_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_rm, float_primitive_float_pair_gen_var_1, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_partial_cmp_primitive_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_partial_cmp_primitive_float_extreme); register_primitive_float_demos!(runner, demo_float_partial_cmp_primitive_float_extreme_debug); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_float); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_float_extreme); register_primitive_float_demos!(runner, demo_primitive_float_partial_cmp_float_extreme_debug); register_primitive_float_benches!( runner, benchmark_float_partial_cmp_primitive_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_primitive_float_partial_cmp_float_library_comparison ); } fn demo_float_partial_cmp_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{} and {} are incomparable", x, NiceFloat(y)), Some(Less) => println!("{} < {}", x, NiceFloat(y)), Some(Equal) => println!("{} = {}", x, NiceFloat(y)), Some(Greater) => println!("{} > {}", x, NiceFloat(y)), } } } fn demo_float_partial_cmp_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{:#x} and {} are incomparable", cx, NiceFloat(y)), Some(Less) => println!("{:#x} < {}", cx, NiceFloat(y)), Some(Equal) => println!("{:#x} = {}", cx, NiceFloat(y)), Some(Greater) => println!("{:#x} > {}", cx, NiceFloat(y)), } } } fn demo_float_partial_cmp_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{} and {} are incomparable", x, NiceFloat(y)), Some(Less) => println!("{} < {}", x, NiceFloat(y)), Some(Equal) => println!("{} = {}", x, NiceFloat(y)), Some(Greater) => println!("{} > {}", x, NiceFloat(y)), } } } fn demo_float_partial_cmp_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{:#x} and {} are incomparable", cx, NiceFloat(y)), Some(Less) => println!("{:#x} < {}", cx, NiceFloat(y)), Some(Equal) => println!("{:#x} = {}", cx, NiceFloat(y)), Some(Greater) => println!("{:#x} > {}", cx, NiceFloat(y)), } } } fn demo_primitive_float_partial_cmp_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{} and {} are incomparable", NiceFloat(x), y), Some(Less) => println!("{} < {}", NiceFloat(x), y), Some(Equal) => println!("{} = {}", NiceFloat(x), y), Some(Greater) => println!("{} > {}", NiceFloat(x), y), } } } fn demo_primitive_float_partial_cmp_float_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{} and {:#x} are incomparable", NiceFloat(x), cy), Some(Less) => println!("{} < {:#x}", NiceFloat(x), cy), Some(Equal) => println!("{} = {:#x}", NiceFloat(x), cy), Some(Greater) => println!("{} > {:#x}", NiceFloat(x), cy), } } } fn demo_primitive_float_partial_cmp_float_extreme + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{} and {} are incomparable", NiceFloat(x), y), Some(Less) => println!("{} < {}", NiceFloat(x), y), Some(Equal) => println!("{} = {}", NiceFloat(x), y), Some(Greater) => println!("{} > {}", NiceFloat(x), y), } } } fn demo_primitive_float_partial_cmp_float_extreme_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{} and {:#x} are incomparable", NiceFloat(x), cy), Some(Less) => println!("{} < {:#x}", NiceFloat(x), cy), Some(Equal) => println!("{} = {:#x}", NiceFloat(x), cy), Some(Greater) => println!("{} > {:#x}", NiceFloat(x), cy), } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_primitive_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrd, rug::Float: PartialOrd, { run_benchmark( &format!("Float.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, float_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_primitive_float_partial_cmp_float_library_comparison< T: PartialOrd + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Float)", T::NAME), BenchmarkType::LibraryComparison, float_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_float_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((y, x), _)| no_out!(x.partial_cmp(&y))), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_signed_max_complexity_bucketer, pair_2_pair_float_unsigned_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_rm, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_rm, float_unsigned_pair_gen_var_5, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_partial_cmp_unsigned); register_unsigned_demos!(runner, demo_float_partial_cmp_unsigned_debug); register_unsigned_demos!(runner, demo_float_partial_cmp_unsigned_extreme); register_unsigned_demos!(runner, demo_float_partial_cmp_unsigned_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_float); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_float_debug); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_float_extreme); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_float_extreme_debug); register_signed_demos!(runner, demo_float_partial_cmp_signed); register_signed_demos!(runner, demo_float_partial_cmp_signed_debug); register_signed_demos!(runner, demo_float_partial_cmp_signed_extreme); register_signed_demos!(runner, demo_float_partial_cmp_signed_extreme_debug); register_signed_demos!(runner, demo_signed_partial_cmp_float); register_signed_demos!(runner, demo_signed_partial_cmp_float_debug); register_signed_demos!(runner, demo_signed_partial_cmp_float_extreme); register_signed_demos!(runner, demo_signed_partial_cmp_float_extreme_debug); register_unsigned_benches!( runner, benchmark_float_partial_cmp_unsigned_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_float_library_comparison ); register_signed_benches!( runner, benchmark_float_partial_cmp_signed_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_cmp_float_library_comparison ); } fn demo_float_partial_cmp_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_float_partial_cmp_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_unsigned_partial_cmp_float + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_unsigned_partial_cmp_float_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } fn demo_unsigned_partial_cmp_float_extreme + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_unsigned_partial_cmp_float_extreme_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } fn demo_float_partial_cmp_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: PartialOrd, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_float_partial_cmp_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y:#x} are incomparable"), Some(Less) => println!("{cx:#x} < {y:#x}"), Some(Equal) => println!("{cx:#x} = {y:#x}"), Some(Greater) => println!("{cx:#x} > {y:#x}"), } } } fn demo_signed_partial_cmp_float + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_signed_partial_cmp_float_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } fn demo_signed_partial_cmp_float_extreme + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_signed_partial_cmp_float_extreme_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x:x} and {cy:#x} are incomparable"), Some(Less) => println!("{x:#x} < {cy:#x}"), Some(Equal) => println!("{x:#x} = {cy:#x}"), Some(Greater) => println!("{x:#x} > {cy:#x}"), } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrd, rug::Float: PartialOrd, { run_benchmark( &format!("Float.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_unsigned_partial_cmp_float_library_comparison< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Float)", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((y, x), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_cmp_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialOrd, rug::Float: PartialOrd, { run_benchmark( &format!("Float.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_signed_partial_cmp_float_library_comparison< T: PartialOrd + PartialOrd + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Float)", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((y, x), _)| no_out!(x.partial_cmp(&y))), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_cmp_rational.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_rational_max_complexity_bucketer, pair_float_rational_max_complexity_bucketer, }; use malachite_float::test_util::comparison::partial_cmp_rational::float_partial_cmp_rational_alt; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_cmp_rational); register_demo!(runner, demo_float_partial_cmp_rational_debug); register_demo!(runner, demo_float_partial_cmp_rational_extreme); register_demo!(runner, demo_float_partial_cmp_rational_extreme_debug); register_demo!(runner, demo_rational_partial_cmp_float); register_demo!(runner, demo_rational_partial_cmp_float_debug); register_demo!(runner, demo_rational_partial_cmp_float_extreme); register_demo!(runner, demo_rational_partial_cmp_float_extreme_debug); register_bench!( runner, benchmark_float_partial_cmp_rational_library_comparison ); register_bench!(runner, benchmark_float_partial_cmp_rational_algorithms); register_bench!( runner, benchmark_rational_partial_cmp_float_library_comparison ); } fn demo_float_partial_cmp_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y} are incomparable"), Some(Less) => println!("{cx:#x} < {y}"), Some(Equal) => println!("{cx:#x} = {y}"), Some(Greater) => println!("{cx:#x} > {y}"), } } } fn demo_float_partial_cmp_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_float_partial_cmp_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); match x.partial_cmp(&y) { None => println!("{cx:#x} and {y} are incomparable"), Some(Less) => println!("{cx:#x} < {y}"), Some(Equal) => println!("{cx:#x} = {y}"), Some(Greater) => println!("{cx:#x} > {y}"), } } } fn demo_rational_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_rational_partial_cmp_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x} and {cy:#x} are incomparable"), Some(Less) => println!("{x} < {cy:#x}"), Some(Equal) => println!("{x} = {cy:#x}"), Some(Greater) => println!("{x} > {cy:#x}"), } } } fn demo_rational_partial_cmp_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { match x.partial_cmp(&y) { None => println!("{x} and {y} are incomparable"), Some(Less) => println!("{x} < {y}"), Some(Equal) => println!("{x} = {y}"), Some(Greater) => println!("{x} > {y}"), } } } fn demo_rational_partial_cmp_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); match x.partial_cmp(&y) { None => println!("{x} and {cy:#x} are incomparable"), Some(Less) => println!("{x} < {cy:#x}"), Some(Equal) => println!("{x} = {cy:#x}"), Some(Greater) => println!("{x} > {cy:#x}"), } } } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp(&Rational)", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.partial_cmp(&Rational)", BenchmarkType::Algorithms, float_rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp(&y))), ("alt", &mut |(x, y)| { no_out!(float_partial_cmp_rational_alt(&x, &y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp(&Float)", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_2_pair_float_integer_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_rm, float_integer_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_eq_integer); register_demo!(runner, demo_float_partial_eq_integer_debug); register_demo!(runner, demo_float_partial_eq_integer_extreme); register_demo!(runner, demo_float_partial_eq_integer_extreme_debug); register_demo!(runner, demo_integer_partial_eq_float); register_demo!(runner, demo_integer_partial_eq_float_debug); register_demo!(runner, demo_integer_partial_eq_float_extreme); register_demo!(runner, demo_integer_partial_eq_float_extreme_debug); register_bench!( runner, benchmark_float_partial_eq_integer_library_comparison ); register_bench!( runner, benchmark_integer_partial_eq_float_library_comparison ); } fn demo_float_partial_eq_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:#x}"); } else { println!("{cx:#x} ≠ {y:#x}"); } } } fn demo_float_partial_eq_integer_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_integer_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:#x}"); } else { println!("{cx:#x} ≠ {y:#x}"); } } } fn demo_integer_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_integer_partial_eq_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:#x} = {cy:#x}"); } else { println!("{x:#x} ≠ {cy:#x}"); } } } fn demo_integer_partial_eq_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_integer_partial_eq_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_integer_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:#x} = {cy:#x}"); } else { println!("{x:#x} ≠ {cy:#x}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float == Integer", BenchmarkType::LibraryComparison, float_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_integer_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer == Float", BenchmarkType::LibraryComparison, float_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_integer_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::pair_2_pair_float_natural_max_complexity_bucketer; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_rm, float_natural_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_eq_natural); register_demo!(runner, demo_float_partial_eq_natural_debug); register_demo!(runner, demo_float_partial_eq_natural_extreme); register_demo!(runner, demo_float_partial_eq_natural_extreme_debug); register_demo!(runner, demo_natural_partial_eq_float); register_demo!(runner, demo_natural_partial_eq_float_debug); register_demo!(runner, demo_natural_partial_eq_float_extreme); register_demo!(runner, demo_natural_partial_eq_float_extreme_debug); register_bench!( runner, benchmark_float_partial_eq_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_eq_float_library_comparison ); } fn demo_float_partial_eq_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_natural_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:#x}"); } else { println!("{cx:#x} ≠ {y:#x}"); } } } fn demo_float_partial_eq_natural_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_natural_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:#x}"); } else { println!("{cx:#x} ≠ {y:#x}"); } } } fn demo_natural_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_natural_partial_eq_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:#x} = {cy:#x}"); } else { println!("{x:#x} ≠ {cy:#x}"); } } } fn demo_natural_partial_eq_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_natural_partial_eq_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_natural_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:#x} = {cy:#x}"); } else { println!("{x:#x} ≠ {cy:#x}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float == Natural", BenchmarkType::LibraryComparison, float_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_natural_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural == Float", BenchmarkType::LibraryComparison, float_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_natural_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_rm, float_primitive_float_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_partial_eq_primitive_float); register_primitive_float_demos!(runner, demo_float_partial_eq_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_partial_eq_primitive_float_extreme); register_primitive_float_demos!(runner, demo_float_partial_eq_primitive_float_extreme_debug); register_primitive_float_demos!(runner, demo_primitive_float_partial_eq_float); register_primitive_float_demos!(runner, demo_primitive_float_partial_eq_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_partial_eq_float_extreme); register_primitive_float_demos!(runner, demo_primitive_float_partial_eq_float_extreme_debug); register_primitive_float_benches!( runner, benchmark_float_partial_eq_primitive_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_primitive_float_partial_eq_float_library_comparison ); } fn demo_float_partial_eq_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x == y { println!("{} = {}", x, NiceFloat(y)); } else { println!("{} ≠ {}", x, NiceFloat(y)); } } } fn demo_float_partial_eq_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{:#x} = {}", cx, NiceFloat(y)); } else { println!("{:#x} ≠ {}", cx, NiceFloat(y)); } } } fn demo_float_partial_eq_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { if x == y { println!("{} = {}", x, NiceFloat(y)); } else { println!("{} ≠ {}", x, NiceFloat(y)); } } } fn demo_float_partial_eq_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{:#x} = {}", cx, NiceFloat(y)); } else { println!("{:#x} ≠ {}", cx, NiceFloat(y)); } } } fn demo_primitive_float_partial_eq_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x == y { println!("{} = {}", NiceFloat(x), y); } else { println!("{} ≠ {}", NiceFloat(x), y); } } } fn demo_primitive_float_partial_eq_float_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{} = {:#x}", NiceFloat(x), cy); } else { println!("{} ≠ {:#x}", NiceFloat(x), cy); } } } fn demo_primitive_float_partial_eq_float_extreme + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { if x == y { println!("{} = {}", NiceFloat(x), y); } else { println!("{} ≠ {}", NiceFloat(x), y); } } } fn demo_primitive_float_partial_eq_float_extreme_debug + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_primitive_float_pair_gen_var_1::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{} = {:#x}", NiceFloat(x), cy); } else { println!("{} ≠ {:#x}", NiceFloat(x), cy); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_primitive_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialEq, rug::Float: PartialEq, { run_benchmark( &format!("Float == {}", T::NAME), BenchmarkType::LibraryComparison, float_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_primitive_float_partial_eq_float_library_comparison< T: PartialEq + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Float", T::NAME), BenchmarkType::LibraryComparison, float_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_primitive_float_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::Float; use malachite_float::test_util::bench::bucketers::{ pair_2_pair_float_signed_max_complexity_bucketer, pair_2_pair_float_unsigned_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_rm, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_rm, float_unsigned_pair_gen_var_5, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_partial_eq_unsigned); register_unsigned_demos!(runner, demo_float_partial_eq_unsigned_debug); register_unsigned_demos!(runner, demo_float_partial_eq_unsigned_extreme); register_unsigned_demos!(runner, demo_float_partial_eq_unsigned_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_partial_eq_float); register_unsigned_demos!(runner, demo_unsigned_partial_eq_float_debug); register_unsigned_demos!(runner, demo_unsigned_partial_eq_float_extreme); register_unsigned_demos!(runner, demo_unsigned_partial_eq_float_extreme_debug); register_signed_demos!(runner, demo_float_partial_eq_signed); register_signed_demos!(runner, demo_float_partial_eq_signed_debug); register_signed_demos!(runner, demo_float_partial_eq_signed_extreme); register_signed_demos!(runner, demo_float_partial_eq_signed_extreme_debug); register_signed_demos!(runner, demo_signed_partial_eq_float); register_signed_demos!(runner, demo_signed_partial_eq_float_debug); register_signed_demos!(runner, demo_signed_partial_eq_float_extreme); register_signed_demos!(runner, demo_signed_partial_eq_float_extreme_debug); register_unsigned_benches!( runner, benchmark_float_partial_eq_unsigned_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_eq_float_library_comparison ); register_signed_benches!(runner, benchmark_float_partial_eq_signed_library_comparison); register_signed_benches!(runner, benchmark_signed_partial_eq_float_library_comparison); } fn demo_float_partial_eq_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:x}"); } else { println!("{cx:#x} ≠ {y:x}"); } } } fn demo_float_partial_eq_unsigned_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_unsigned_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:x}"); } else { println!("{cx:#x} ≠ {y:x}"); } } } fn demo_unsigned_partial_eq_float + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_unsigned_partial_eq_float_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:x} = {cy:#x}"); } else { println!("{x:x} ≠ {cy:#x}"); } } } fn demo_unsigned_partial_eq_float_extreme + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_unsigned_partial_eq_float_extreme_debug + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:x} = {cy:#x}"); } else { println!("{x:x} ≠ {cy:#x}"); } } } fn demo_float_partial_eq_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: PartialEq, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_signed_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_signed_pair_gen::().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:x}"); } else { println!("{cx:#x} ≠ {y:x}"); } } } fn demo_float_partial_eq_signed_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_signed_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialEq, { for (x, y) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y:x}"); } else { println!("{cx:#x} ≠ {y:x}"); } } } fn demo_signed_partial_eq_float + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_signed_partial_eq_float_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen::().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:x} = {cy:#x}"); } else { println!("{x:x} ≠ {cy:#x}"); } } } fn demo_signed_partial_eq_float_extreme + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_signed_partial_eq_float_extreme_debug + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (y, x) in float_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x:x} = {cy:#x}"); } else { println!("{x:x} ≠ {cy:#x}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialEq, rug::Float: PartialEq, { run_benchmark( &format!("Float == {}", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_unsigned_partial_eq_float_library_comparison< T: PartialEq + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Float", T::NAME), BenchmarkType::LibraryComparison, float_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_unsigned_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: PartialEq, rug::Float: PartialEq, { run_benchmark( &format!("Float == {}", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_signed_partial_eq_float_library_comparison< T: PartialEq + PartialEq + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Float", T::NAME), BenchmarkType::LibraryComparison, float_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_signed_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/comparison/partial_eq_rational.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::bench::bucketers::*; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_rm, float_rational_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_partial_eq_rational); register_demo!(runner, demo_float_partial_eq_rational_debug); register_demo!(runner, demo_float_partial_eq_rational_extreme); register_demo!(runner, demo_float_partial_eq_rational_extreme_debug); register_demo!(runner, demo_rational_partial_eq_float); register_demo!(runner, demo_rational_partial_eq_float_debug); register_demo!(runner, demo_rational_partial_eq_float_extreme); register_demo!(runner, demo_rational_partial_eq_float_extreme_debug); register_bench!( runner, benchmark_float_partial_eq_rational_library_comparison ); register_bench!( runner, benchmark_rational_partial_eq_float_library_comparison ); } fn demo_float_partial_eq_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y}"); } else { println!("{cx:#x} ≠ {y}"); } } } fn demo_float_partial_eq_rational_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_float_partial_eq_rational_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cx = ComparableFloatRef(&x); if x == y { println!("{cx:#x} = {y}"); } else { println!("{cx:#x} ≠ {y}"); } } } fn demo_rational_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_rational_partial_eq_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x} = {cy:#x}"); } else { println!("{x} ≠ {cy:#x}"); } } } fn demo_rational_partial_eq_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_rational_partial_eq_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (y, x) in float_rational_pair_gen_var_2().get(gm, config).take(limit) { let cy = ComparableFloatRef(&y); if x == y { println!("{x} = {cy:#x}"); } else { println!("{x} ≠ {cy:#x}"); } } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_float_partial_eq_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float == Rational", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational == Float", BenchmarkType::LibraryComparison, float_rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_rational_max_complexity_bucketer("y", "x"), &mut [ ("Malachite", &mut |(_, (y, x))| no_out!(x == y)), ("rug", &mut |((y, x), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/gauss_constant.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_gauss_constant_prec_round); register_demo!(runner, demo_float_gauss_constant_prec_round_debug); register_demo!(runner, demo_float_gauss_constant_prec); register_demo!(runner, demo_float_gauss_constant_prec_debug); register_bench!(runner, benchmark_float_gauss_constant_prec_round); register_bench!(runner, benchmark_float_gauss_constant_prec); } fn demo_float_gauss_constant_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "gauss_constant_prec_round({}, {}) = {:?}", p, rm, Float::gauss_constant_prec_round(p, rm) ); } } fn demo_float_gauss_constant_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::gauss_constant_prec_round(p, rm); println!( "gauss_constant_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_gauss_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "gauss_constant_prec({}) = {:?}", p, Float::gauss_constant_prec(p) ); } } fn demo_float_gauss_constant_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::gauss_constant_prec(p); println!( "gauss_constant_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_gauss_constant_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::gauss_constant_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::gauss_constant_prec_round(p, rm)); })], ); } fn benchmark_float_gauss_constant_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::gauss_constant_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::gauss_constant_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/lemniscate_constant.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::lemniscate_constant::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_lemniscate_constant_prec_round); register_demo!(runner, demo_float_lemniscate_constant_prec_round_debug); register_demo!(runner, demo_float_lemniscate_constant_prec); register_demo!(runner, demo_float_lemniscate_constant_prec_debug); register_bench!( runner, benchmark_float_lemniscate_constant_prec_round_algorithms ); register_bench!(runner, benchmark_float_lemniscate_constant_prec_algorithms); } fn demo_float_lemniscate_constant_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "lemniscate_constant_prec_round({}, {}) = {:?}", p, rm, Float::lemniscate_constant_prec_round(p, rm) ); } } fn demo_float_lemniscate_constant_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::lemniscate_constant_prec_round(p, rm); println!( "lemniscate_constant_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_lemniscate_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "lemniscate_constant_prec({}) = {:?}", p, Float::lemniscate_constant_prec(p) ); } } fn demo_float_lemniscate_constant_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::lemniscate_constant_prec(p); println!( "lemniscate_constant_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_lemniscate_constant_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::lemniscate_constant_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::lemniscate_constant_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(lemniscate_constant_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_lemniscate_constant_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::lemniscate_constant_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| { no_out!(Float::lemniscate_constant_prec(p)); }), ("simple", &mut |p| { no_out!(lemniscate_constant_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/ln_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Two; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::ln_2::rug_ln_2_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_ln_2_prec_round); register_demo!(runner, demo_float_ln_2_prec_round_debug); register_demo!(runner, demo_float_ln_2_prec); register_demo!(runner, demo_float_ln_2_prec_debug); register_bench!(runner, benchmark_float_ln_2_prec_round_library_comparison); register_bench!(runner, benchmark_float_ln_2_prec_round_algorithms); register_bench!(runner, benchmark_float_ln_2_prec_library_comparison); register_bench!(runner, benchmark_float_ln_2_prec_algorithms); } fn demo_float_ln_2_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "ln_2_prec_round({}, {}) = {:?}", p, rm, Float::ln_2_prec_round(p, rm) ); } } fn demo_float_ln_2_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::ln_2_prec_round(p, rm); println!( "ln_2_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_ln_2_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("ln_2_prec({}) = {:?}", p, Float::ln_2_prec(p)); } } fn demo_float_ln_2_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::ln_2_prec(p); println!("ln_2_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_ln_2_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_2_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::ln_2_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_ln_2_prec_round( p, rug_round_exact_from_rounding_mode(rm) )); }), ], ); } fn benchmark_float_ln_2_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_2_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::ln_2_prec_round(p, rm)); }), ("using ln", &mut |(p, rm)| { no_out!(Float::ln_prec_round(Float::TWO, p, rm)); }), ], ); } fn benchmark_float_ln_2_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_2_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::ln_2_prec(p))), ("rug", &mut |p| { no_out!(rug_ln_2_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } fn benchmark_float_ln_2_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::ln_2_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::ln_2_prec(p))), ("using ln", &mut |p| { no_out!(Float::ln_prec(Float::TWO, p)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/log_2_e.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::log_2_e::log_2_e_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_log_2_e_prec_round); register_demo!(runner, demo_float_log_2_e_prec_round_debug); register_demo!(runner, demo_float_log_2_e_prec); register_demo!(runner, demo_float_log_2_e_prec_debug); register_bench!(runner, benchmark_float_log_2_e_prec_round_algorithms); register_bench!(runner, benchmark_float_log_2_e_prec_algorithms); } fn demo_float_log_2_e_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "log_2_e_prec_round({}, {}) = {:?}", p, rm, Float::log_2_e_prec_round(p, rm) ); } } fn demo_float_log_2_e_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::log_2_e_prec_round(p, rm); println!( "log_2_e_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_log_2_e_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("log_2_e_prec({}) = {:?}", p, Float::log_2_e_prec(p)); } } fn demo_float_log_2_e_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::log_2_e_prec(p); println!( "log_2_e_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_log_2_e_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::log_2_e_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::log_2_e_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(log_2_e_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_log_2_e_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::log_2_e_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::log_2_e_prec(p))), ("simple", &mut |p| { no_out!(log_2_e_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { gauss_constant::register(runner); lemniscate_constant::register(runner); ln_2::register(runner); log_2_e::register(runner); one_over_pi::register(runner); one_over_sqrt_pi::register(runner); one_over_sqrt_tau::register(runner); phi::register(runner); pi::register(runner); pi_over_2::register(runner); pi_over_3::register(runner); pi_over_4::register(runner); pi_over_6::register(runner); pi_over_8::register(runner); prime_constant::register(runner); prouhet_thue_morse_constant::register(runner); sqrt_2::register(runner); sqrt_2_over_2::register(runner); sqrt_3::register(runner); sqrt_3_over_3::register(runner); sqrt_pi::register(runner); tau::register(runner); two_over_pi::register(runner); two_over_sqrt_pi::register(runner); } mod gauss_constant; mod lemniscate_constant; mod ln_2; mod log_2_e; mod one_over_pi; mod one_over_sqrt_pi; mod one_over_sqrt_tau; mod phi; mod pi; mod pi_over_2; mod pi_over_3; mod pi_over_4; mod pi_over_6; mod pi_over_8; mod prime_constant; mod prouhet_thue_morse_constant; mod sqrt_2; mod sqrt_2_over_2; mod sqrt_3; mod sqrt_3_over_3; mod sqrt_pi; mod tau; mod two_over_pi; mod two_over_sqrt_pi; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/one_over_pi.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::one_over_pi::one_over_pi_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_one_over_pi_prec_round); register_demo!(runner, demo_float_one_over_pi_prec_round_debug); register_demo!(runner, demo_float_one_over_pi_prec); register_demo!(runner, demo_float_one_over_pi_prec_debug); register_bench!(runner, benchmark_float_one_over_pi_prec_round_algorithms); register_bench!(runner, benchmark_float_one_over_pi_prec_algorithms); } fn demo_float_one_over_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "one_over_pi_prec_round({}, {}) = {:?}", p, rm, Float::one_over_pi_prec_round(p, rm) ); } } fn demo_float_one_over_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::one_over_pi_prec_round(p, rm); println!( "one_over_pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_one_over_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("one_over_pi_prec({}) = {:?}", p, Float::one_over_pi_prec(p)); } } fn demo_float_one_over_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::one_over_pi_prec(p); println!( "one_over_pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_one_over_pi_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_pi_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::one_over_pi_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(one_over_pi_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_one_over_pi_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_pi_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::one_over_pi_prec(p))), ("simple", &mut |p| { no_out!(one_over_pi_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/one_over_sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::one_over_sqrt_pi::one_over_sqrt_pi_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_one_over_sqrt_pi_prec_round); register_demo!(runner, demo_float_one_over_sqrt_pi_prec_round_debug); register_demo!(runner, demo_float_one_over_sqrt_pi_prec); register_demo!(runner, demo_float_one_over_sqrt_pi_prec_debug); register_bench!( runner, benchmark_float_one_over_sqrt_pi_prec_round_algorithms ); register_bench!(runner, benchmark_float_one_over_sqrt_pi_prec_algorithms); } fn demo_float_one_over_sqrt_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "one_over_sqrt_pi_prec_round({}, {}) = {:?}", p, rm, Float::one_over_sqrt_pi_prec_round(p, rm) ); } } fn demo_float_one_over_sqrt_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::one_over_sqrt_pi_prec_round(p, rm); println!( "one_over_sqrt_pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_one_over_sqrt_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "one_over_sqrt_pi_prec({}) = {:?}", p, Float::one_over_sqrt_pi_prec(p) ); } } fn demo_float_one_over_sqrt_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::one_over_sqrt_pi_prec(p); println!( "one_over_sqrt_pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_one_over_sqrt_pi_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_sqrt_pi_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::one_over_sqrt_pi_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(one_over_sqrt_pi_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_one_over_sqrt_pi_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_sqrt_pi_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::one_over_sqrt_pi_prec(p))), ("simple", &mut |p| { no_out!(one_over_sqrt_pi_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/one_over_sqrt_tau.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::one_over_sqrt_tau::one_over_sqrt_tau_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_one_over_sqrt_tau_prec_round); register_demo!(runner, demo_float_one_over_sqrt_tau_prec_round_debug); register_demo!(runner, demo_float_one_over_sqrt_tau_prec); register_demo!(runner, demo_float_one_over_sqrt_tau_prec_debug); register_bench!( runner, benchmark_float_one_over_sqrt_tau_prec_round_algorithms ); register_bench!(runner, benchmark_float_one_over_sqrt_tau_prec_algorithms); } fn demo_float_one_over_sqrt_tau_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "one_over_sqrt_tau_prec_round({}, {}) = {:?}", p, rm, Float::one_over_sqrt_tau_prec_round(p, rm) ); } } fn demo_float_one_over_sqrt_tau_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::one_over_sqrt_tau_prec_round(p, rm); println!( "one_over_sqrt_tau_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_one_over_sqrt_tau_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "one_over_sqrt_tau_prec({}) = {:?}", p, Float::one_over_sqrt_tau_prec(p) ); } } fn demo_float_one_over_sqrt_tau_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::one_over_sqrt_tau_prec(p); println!( "one_over_sqrt_tau_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_one_over_sqrt_tau_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_sqrt_tau_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::one_over_sqrt_tau_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(one_over_sqrt_tau_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_one_over_sqrt_tau_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::one_over_sqrt_tau_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| { no_out!(Float::one_over_sqrt_tau_prec(p)); }), ("simple", &mut |p| { no_out!(one_over_sqrt_tau_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/phi.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_phi_prec_round); register_demo!(runner, demo_float_phi_prec_round_debug); register_demo!(runner, demo_float_phi_prec); register_demo!(runner, demo_float_phi_prec_debug); register_bench!(runner, benchmark_float_phi_prec_round); register_bench!(runner, benchmark_float_phi_prec); } fn demo_float_phi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "phi_prec_round({}, {}) = {:?}", p, rm, Float::phi_prec_round(p, rm) ); } } fn demo_float_phi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::phi_prec_round(p, rm); println!( "phi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_phi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("phi_prec({}) = {:?}", p, Float::phi_prec(p)); } } fn demo_float_phi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::phi_prec(p); println!("phi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_phi_prec_round(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::phi_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::phi_prec_round(p, rm)); })], ); } fn benchmark_float_phi_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::phi_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::phi_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::pi::rug_pi_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_prec_round); register_demo!(runner, demo_float_pi_prec_round_debug); register_demo!(runner, demo_float_pi_prec); register_demo!(runner, demo_float_pi_prec_debug); register_bench!(runner, benchmark_float_pi_prec_round_library_comparison); register_bench!(runner, benchmark_float_pi_prec_library_comparison); } fn demo_float_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_prec_round({}, {}) = {:?}", p, rm, Float::pi_prec_round(p, rm) ); } } fn demo_float_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_prec_round(p, rm); println!( "pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_prec({}) = {:?}", p, Float::pi_prec(p)); } } fn demo_float_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_prec(p); println!("pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_pi_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::pi_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_pi_prec_round(p, rug_round_exact_from_rounding_mode(rm))); }), ], ); } fn benchmark_float_pi_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::pi_prec(p))), ("rug", &mut |p| { no_out!(rug_pi_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi_over_2.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_over_2_prec_round); register_demo!(runner, demo_float_pi_over_2_prec_round_debug); register_demo!(runner, demo_float_pi_over_2_prec); register_demo!(runner, demo_float_pi_over_2_prec_debug); register_bench!(runner, benchmark_float_pi_over_2_prec_round); register_bench!(runner, benchmark_float_pi_over_2_prec); } fn demo_float_pi_over_2_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_over_2_prec_round({}, {}) = {:?}", p, rm, Float::pi_over_2_prec_round(p, rm) ); } } fn demo_float_pi_over_2_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_over_2_prec_round(p, rm); println!( "pi_over_2_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_over_2_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_over_2_prec({}) = {:?}", p, Float::pi_over_2_prec(p)); } } fn demo_float_pi_over_2_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_over_2_prec(p); println!( "pi_over_2_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_pi_over_2_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_2_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::pi_over_2_prec_round(p, rm)); })], ); } fn benchmark_float_pi_over_2_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::pi_over_2_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::pi_over_2_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi_over_3.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::pi_over_3::pi_over_3_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_over_3_prec_round); register_demo!(runner, demo_float_pi_over_3_prec_round_debug); register_demo!(runner, demo_float_pi_over_3_prec); register_demo!(runner, demo_float_pi_over_3_prec_debug); register_bench!(runner, benchmark_float_pi_over_3_prec_round_algorithms); register_bench!(runner, benchmark_float_pi_over_3_prec_algorithms); } fn demo_float_pi_over_3_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_over_3_prec_round({}, {}) = {:?}", p, rm, Float::pi_over_3_prec_round(p, rm) ); } } fn demo_float_pi_over_3_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_over_3_prec_round(p, rm); println!( "pi_over_3_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_over_3_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_over_3_prec({}) = {:?}", p, Float::pi_over_3_prec(p)); } } fn demo_float_pi_over_3_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_over_3_prec(p); println!( "pi_over_3_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_pi_over_3_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_3_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::pi_over_3_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(pi_over_3_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_pi_over_3_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_3_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::pi_over_3_prec(p))), ("simple", &mut |p| { no_out!(pi_over_3_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi_over_4.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_over_4_prec_round); register_demo!(runner, demo_float_pi_over_4_prec_round_debug); register_demo!(runner, demo_float_pi_over_4_prec); register_demo!(runner, demo_float_pi_over_4_prec_debug); register_bench!(runner, benchmark_float_pi_over_4_prec_round); register_bench!(runner, benchmark_float_pi_over_4_prec); } fn demo_float_pi_over_4_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_over_4_prec_round({}, {}) = {:?}", p, rm, Float::pi_over_4_prec_round(p, rm) ); } } fn demo_float_pi_over_4_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_over_4_prec_round(p, rm); println!( "pi_over_4_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_over_4_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_over_4_prec({}) = {:?}", p, Float::pi_over_4_prec(p)); } } fn demo_float_pi_over_4_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_over_4_prec(p); println!( "pi_over_4_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_pi_over_4_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_4_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::pi_over_4_prec_round(p, rm)); })], ); } fn benchmark_float_pi_over_4_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::pi_over_4_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::pi_over_4_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi_over_6.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_over_6_prec_round); register_demo!(runner, demo_float_pi_over_6_prec_round_debug); register_demo!(runner, demo_float_pi_over_6_prec); register_demo!(runner, demo_float_pi_over_6_prec_debug); register_bench!(runner, benchmark_float_pi_over_6_prec_round); register_bench!(runner, benchmark_float_pi_over_6_prec); } fn demo_float_pi_over_6_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_over_6_prec_round({}, {}) = {:?}", p, rm, Float::pi_over_6_prec_round(p, rm) ); } } fn demo_float_pi_over_6_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_over_6_prec_round(p, rm); println!( "pi_over_6_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_over_6_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_over_6_prec({}) = {:?}", p, Float::pi_over_6_prec(p)); } } fn demo_float_pi_over_6_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_over_6_prec(p); println!( "pi_over_6_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_pi_over_6_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_6_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::pi_over_6_prec_round(p, rm)); })], ); } fn benchmark_float_pi_over_6_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::pi_over_6_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::pi_over_6_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/pi_over_8.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_pi_over_8_prec_round); register_demo!(runner, demo_float_pi_over_8_prec_round_debug); register_demo!(runner, demo_float_pi_over_8_prec); register_demo!(runner, demo_float_pi_over_8_prec_debug); register_bench!(runner, benchmark_float_pi_over_8_prec_round); register_bench!(runner, benchmark_float_pi_over_8_prec); } fn demo_float_pi_over_8_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "pi_over_8_prec_round({}, {}) = {:?}", p, rm, Float::pi_over_8_prec_round(p, rm) ); } } fn demo_float_pi_over_8_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::pi_over_8_prec_round(p, rm); println!( "pi_over_8_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_pi_over_8_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("pi_over_8_prec({}) = {:?}", p, Float::pi_over_8_prec(p)); } } fn demo_float_pi_over_8_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::pi_over_8_prec(p); println!( "pi_over_8_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_pi_over_8_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::pi_over_8_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::pi_over_8_prec_round(p, rm)); })], ); } fn benchmark_float_pi_over_8_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::pi_over_8_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::pi_over_8_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/prime_constant.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::prime_constant::prime_constant_prec_round_naive; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_prime_constant_prec_round); register_demo!(runner, demo_float_prime_constant_prec_round_debug); register_demo!(runner, demo_float_prime_constant_prec); register_demo!(runner, demo_float_prime_constant_prec_debug); register_bench!(runner, benchmark_float_prime_constant_prec_round_algorithms); register_bench!(runner, benchmark_float_prime_constant_prec_algorithms); } fn demo_float_prime_constant_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "prime_constant_prec_round({}, {}) = {:?}", p, rm, Float::prime_constant_prec_round(p, rm) ); } } fn demo_float_prime_constant_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::prime_constant_prec_round(p, rm); println!( "prime_constant_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_prime_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "prime_constant_prec({}) = {:?}", p, Float::prime_constant_prec(p) ); } } fn demo_float_prime_constant_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::prime_constant_prec(p); println!( "prime_constant_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_prime_constant_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::prime_constant_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::prime_constant_prec_round(p, rm)); }), ("naive", &mut |(p, rm)| { no_out!(prime_constant_prec_round_naive(p, rm)); }), ], ); } fn benchmark_float_prime_constant_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::prime_constant_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::prime_constant_prec(p))), ("naive", &mut |p| { no_out!(prime_constant_prec_round_naive(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/prouhet_thue_morse_constant.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::prouhet_thue_morse_constant::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_prouhet_thue_morse_constant_prec_round); register_demo!( runner, demo_float_prouhet_thue_morse_constant_prec_round_debug ); register_demo!(runner, demo_float_prouhet_thue_morse_constant_prec); register_demo!(runner, demo_float_prouhet_thue_morse_constant_prec_debug); register_bench!( runner, benchmark_float_prouhet_thue_morse_constant_prec_round_algorithms ); register_bench!( runner, benchmark_float_prouhet_thue_morse_constant_prec_algorithms ); } fn demo_float_prouhet_thue_morse_constant_prec_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "prouhet_thue_morse_constant_prec_round({}, {}) = {:?}", p, rm, Float::prouhet_thue_morse_constant_prec_round(p, rm) ); } } fn demo_float_prouhet_thue_morse_constant_prec_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (tmc, o) = Float::prouhet_thue_morse_constant_prec_round(p, rm); println!( "prouhet_thue_morse_constant_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(tmc), o ); } } fn demo_float_prouhet_thue_morse_constant_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "prouhet_thue_morse_constant_prec({}) = {:?}", p, Float::prouhet_thue_morse_constant_prec(p) ); } } fn demo_float_prouhet_thue_morse_constant_prec_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (tmc, o) = Float::prouhet_thue_morse_constant_prec(p); println!( "prouhet_thue_morse_constant_prec({}) = ({:#x}, {:?})", p, ComparableFloat(tmc), o ); } } fn benchmark_float_prouhet_thue_morse_constant_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::prouhet_thue_morse_constant_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::prouhet_thue_morse_constant_prec_round(p, rm)); }), ("naive", &mut |(p, rm)| { no_out!(prouhet_thue_morse_constant_prec_round_naive(p, rm)); }), ], ); } fn benchmark_float_prouhet_thue_morse_constant_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::prouhet_thue_morse_constant_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| { no_out!(Float::prouhet_thue_morse_constant_prec(p)); }), ("naive", &mut |p| { no_out!(prouhet_thue_morse_constant_prec_round_naive(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/sqrt_2.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::sqrt_2::rug_sqrt_2_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt_2_prec_round); register_demo!(runner, demo_float_sqrt_2_prec_round_debug); register_demo!(runner, demo_float_sqrt_2_prec); register_demo!(runner, demo_float_sqrt_2_prec_debug); register_bench!(runner, benchmark_float_sqrt_2_prec_round_library_comparison); register_bench!(runner, benchmark_float_sqrt_2_prec_library_comparison); } fn demo_float_sqrt_2_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sqrt_2_prec_round({}, {}) = {:?}", p, rm, Float::sqrt_2_prec_round(p, rm) ); } } fn demo_float_sqrt_2_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::sqrt_2_prec_round(p, rm); println!( "sqrt_2_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_sqrt_2_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("sqrt_2_prec({}) = {:?}", p, Float::sqrt_2_prec(p)); } } fn demo_float_sqrt_2_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::sqrt_2_prec(p); println!("sqrt_2_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_sqrt_2_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_2_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::sqrt_2_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_sqrt_2_prec_round( p, rug_round_exact_from_rounding_mode(rm) )); }), ], ); } fn benchmark_float_sqrt_2_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_2_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::sqrt_2_prec(p))), ("rug", &mut |p| { no_out!(rug_sqrt_2_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/sqrt_2_over_2.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::sqrt_2_over_2::rug_sqrt_2_over_2_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt_2_over_2_prec_round); register_demo!(runner, demo_float_sqrt_2_over_2_prec_round_debug); register_demo!(runner, demo_float_sqrt_2_over_2_prec); register_demo!(runner, demo_float_sqrt_2_over_2_prec_debug); register_bench!( runner, benchmark_float_sqrt_2_over_2_prec_round_library_comparison ); register_bench!( runner, benchmark_float_sqrt_2_over_2_prec_library_comparison ); } fn demo_float_sqrt_2_over_2_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sqrt_2_over_2_prec_round({}, {}) = {:?}", p, rm, Float::sqrt_2_over_2_prec_round(p, rm) ); } } fn demo_float_sqrt_2_over_2_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::sqrt_2_over_2_prec_round(p, rm); println!( "sqrt_2_over_2_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_sqrt_2_over_2_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "sqrt_2_over_2_prec({}) = {:?}", p, Float::sqrt_2_over_2_prec(p) ); } } fn demo_float_sqrt_2_over_2_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::sqrt_2_over_2_prec(p); println!( "sqrt_2_over_2_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_sqrt_2_over_2_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_2_over_2_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::sqrt_2_over_2_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_sqrt_2_over_2_prec_round( p, rug_round_exact_from_rounding_mode(rm) )); }), ], ); } fn benchmark_float_sqrt_2_over_2_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_2_over_2_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::sqrt_2_over_2_prec(p))), ("rug", &mut |p| { no_out!(rug_sqrt_2_over_2_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/sqrt_3.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::sqrt_3::rug_sqrt_3_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt_3_prec_round); register_demo!(runner, demo_float_sqrt_3_prec_round_debug); register_demo!(runner, demo_float_sqrt_3_prec); register_demo!(runner, demo_float_sqrt_3_prec_debug); register_bench!(runner, benchmark_float_sqrt_3_prec_round_library_comparison); register_bench!(runner, benchmark_float_sqrt_3_prec_library_comparison); } fn demo_float_sqrt_3_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sqrt_3_prec_round({}, {}) = {:?}", p, rm, Float::sqrt_3_prec_round(p, rm) ); } } fn demo_float_sqrt_3_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::sqrt_3_prec_round(p, rm); println!( "sqrt_3_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_sqrt_3_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("sqrt_3_prec({}) = {:?}", p, Float::sqrt_3_prec(p)); } } fn demo_float_sqrt_3_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::sqrt_3_prec(p); println!("sqrt_3_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_sqrt_3_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_3_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::sqrt_3_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_sqrt_3_prec_round( p, rug_round_exact_from_rounding_mode(rm) )); }), ], ); } fn benchmark_float_sqrt_3_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_3_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::sqrt_3_prec(p))), ("rug", &mut |p| { no_out!(rug_sqrt_3_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/sqrt_3_over_3.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::common::rug_round_exact_from_rounding_mode; use malachite_float::test_util::constants::sqrt_3_over_3::rug_sqrt_3_over_3_prec_round; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt_3_over_3_prec_round); register_demo!(runner, demo_float_sqrt_3_over_3_prec_round_debug); register_demo!(runner, demo_float_sqrt_3_over_3_prec); register_demo!(runner, demo_float_sqrt_3_over_3_prec_debug); register_bench!( runner, benchmark_float_sqrt_3_over_3_prec_round_library_comparison ); register_bench!( runner, benchmark_float_sqrt_3_over_3_prec_library_comparison ); } fn demo_float_sqrt_3_over_3_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sqrt_3_over_3_prec_round({}, {}) = {:?}", p, rm, Float::sqrt_3_over_3_prec_round(p, rm) ); } } fn demo_float_sqrt_3_over_3_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::sqrt_3_over_3_prec_round(p, rm); println!( "sqrt_3_over_3_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_sqrt_3_over_3_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "sqrt_3_over_3_prec({}) = {:?}", p, Float::sqrt_3_over_3_prec(p) ); } } fn demo_float_sqrt_3_over_3_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::sqrt_3_over_3_prec(p); println!( "sqrt_3_over_3_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_sqrt_3_over_3_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_3_over_3_prec_round(u64, RoundingMode)", BenchmarkType::LibraryComparison, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("Malachite", &mut |(p, rm)| { no_out!(Float::sqrt_3_over_3_prec_round(p, rm)); }), ("rug", &mut |(p, rm)| { no_out!(rug_sqrt_3_over_3_prec_round( p, rug_round_exact_from_rounding_mode(rm) )); }), ], ); } fn benchmark_float_sqrt_3_over_3_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_3_over_3_prec(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |p| no_out!(Float::sqrt_3_over_3_prec(p))), ("rug", &mut |p| { no_out!(rug_sqrt_3_over_3_prec_round( p, rug_round_exact_from_rounding_mode(Nearest) )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; use malachite_float::test_util::constants::sqrt_pi::sqrt_pi_prec_round_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_sqrt_pi_prec_round); register_demo!(runner, demo_float_sqrt_pi_prec_round_debug); register_demo!(runner, demo_float_sqrt_pi_prec); register_demo!(runner, demo_float_sqrt_pi_prec_debug); register_bench!(runner, benchmark_float_sqrt_pi_prec_round_algorithms); register_bench!(runner, benchmark_float_sqrt_pi_prec_algorithms); } fn demo_float_sqrt_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sqrt_pi_prec_round({}, {}) = {:?}", p, rm, Float::sqrt_pi_prec_round(p, rm) ); } } fn demo_float_sqrt_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::sqrt_pi_prec_round(p, rm); println!( "sqrt_pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_sqrt_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("sqrt_pi_prec({}) = {:?}", p, Float::sqrt_pi_prec(p)); } } fn demo_float_sqrt_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::sqrt_pi_prec(p); println!( "sqrt_pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_sqrt_pi_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_pi_prec_round(u64, RoundingMode)", BenchmarkType::Algorithms, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [ ("default", &mut |(p, rm)| { no_out!(Float::sqrt_pi_prec_round(p, rm)); }), ("simple", &mut |(p, rm)| { no_out!(sqrt_pi_prec_round_simple(p, rm)); }), ], ); } fn benchmark_float_sqrt_pi_prec_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::sqrt_pi_prec(u64)", BenchmarkType::Algorithms, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |p| no_out!(Float::sqrt_pi_prec(p))), ("simple", &mut |p| { no_out!(sqrt_pi_prec_round_simple(p, Nearest)); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/tau.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_tau_prec_round); register_demo!(runner, demo_float_tau_prec_round_debug); register_demo!(runner, demo_float_tau_prec); register_demo!(runner, demo_float_tau_prec_debug); register_bench!(runner, benchmark_float_tau_prec_round); register_bench!(runner, benchmark_float_tau_prec); } fn demo_float_tau_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "tau_prec_round({}, {}) = {:?}", p, rm, Float::tau_prec_round(p, rm) ); } } fn demo_float_tau_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::tau_prec_round(p, rm); println!( "tau_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_tau_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("tau_prec({}) = {:?}", p, Float::tau_prec(p)); } } fn demo_float_tau_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::tau_prec(p); println!("tau_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o); } } fn benchmark_float_tau_prec_round(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::tau_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::tau_prec_round(p, rm)); })], ); } fn benchmark_float_tau_prec(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float::tau_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::tau_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/two_over_pi.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_two_over_pi_prec_round); register_demo!(runner, demo_float_two_over_pi_prec_round_debug); register_demo!(runner, demo_float_two_over_pi_prec); register_demo!(runner, demo_float_two_over_pi_prec_debug); register_bench!(runner, benchmark_float_two_over_pi_prec_round); register_bench!(runner, benchmark_float_two_over_pi_prec); } fn demo_float_two_over_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "two_over_pi_prec_round({}, {}) = {:?}", p, rm, Float::two_over_pi_prec_round(p, rm) ); } } fn demo_float_two_over_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::two_over_pi_prec_round(p, rm); println!( "two_over_pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_two_over_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!("two_over_pi_prec({}) = {:?}", p, Float::two_over_pi_prec(p)); } } fn demo_float_two_over_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::two_over_pi_prec(p); println!( "two_over_pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_two_over_pi_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::two_over_pi_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::two_over_pi_prec_round(p, rm)); })], ); } fn benchmark_float_two_over_pi_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::two_over_pi_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| no_out!(Float::two_over_pi_prec(p)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/constants/two_over_sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_1_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::Float; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_two_over_sqrt_pi_prec_round); register_demo!(runner, demo_float_two_over_sqrt_pi_prec_round_debug); register_demo!(runner, demo_float_two_over_sqrt_pi_prec); register_demo!(runner, demo_float_two_over_sqrt_pi_prec_debug); register_bench!(runner, benchmark_float_two_over_sqrt_pi_prec_round); register_bench!(runner, benchmark_float_two_over_sqrt_pi_prec); } fn demo_float_two_over_sqrt_pi_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "two_over_sqrt_pi_prec_round({}, {}) = {:?}", p, rm, Float::two_over_sqrt_pi_prec_round(p, rm) ); } } fn demo_float_two_over_sqrt_pi_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (p, rm) in unsigned_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let (pc, o) = Float::two_over_sqrt_pi_prec_round(p, rm); println!( "two_over_sqrt_pi_prec_round({}, {}) = ({:#x}, {:?})", p, rm, ComparableFloat(pc), o ); } } fn demo_float_two_over_sqrt_pi_prec(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { println!( "two_over_sqrt_pi_prec({}) = {:?}", p, Float::two_over_sqrt_pi_prec(p) ); } } fn demo_float_two_over_sqrt_pi_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for p in unsigned_gen_var_11().get(gm, config).take(limit) { let (pc, o) = Float::two_over_sqrt_pi_prec(p); println!( "two_over_sqrt_pi_prec({}) = ({:#x}, {:?})", p, ComparableFloat(pc), o ); } } fn benchmark_float_two_over_sqrt_pi_prec_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::two_over_sqrt_pi_prec_round(u64, RoundingMode)", BenchmarkType::Single, unsigned_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("prec"), &mut [("Malachite", &mut |(p, rm)| { no_out!(Float::two_over_sqrt_pi_prec_round(p, rm)); })], ); } fn benchmark_float_two_over_sqrt_pi_prec( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::two_over_sqrt_pi_prec(u64)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |p| { no_out!(Float::two_over_sqrt_pi_prec(p)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ pair_2_float_complexity_bucketer, pair_2_pair_float_max_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_rm, float_gen_var_12, float_pair_gen, float_pair_gen_rm, float_pair_gen_var_10, }; use malachite_float::{ComparableFloat, ComparableFloatRef}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_clone); register_demo!(runner, demo_float_clone_debug); register_demo!(runner, demo_float_clone_extreme); register_demo!(runner, demo_float_clone_extreme_debug); register_demo!(runner, demo_float_clone_from); register_demo!(runner, demo_float_clone_from_debug); register_demo!(runner, demo_float_clone_from_extreme); register_demo!(runner, demo_float_clone_from_extreme_debug); register_bench!(runner, benchmark_float_clone_library_comparison); register_bench!(runner, benchmark_float_clone_from_library_comparison); } fn demo_float_clone(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!("clone({}) = {}", n, n.clone()); } } fn demo_float_clone_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { println!( "clone({:#x}) = {:#x}", ComparableFloatRef(&n), ComparableFloat(n.clone()) ); } } fn demo_float_clone_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!("clone({}) = {}", n, n.clone()); } } fn demo_float_clone_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { println!( "clone({:#x}) = {:#x}", ComparableFloatRef(&n), ComparableFloat(n.clone()) ); } } fn demo_float_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } fn demo_float_clone_from_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!( "x := {:#x}; x.clone_from({:#x}); x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } fn demo_float_clone_from_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } fn demo_float_clone_from_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in float_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!( "x := {:#x}; x.clone_from({:#x}); x = {:#x}", ComparableFloat(x_old), ComparableFloat(y), ComparableFloat(x) ); } } #[allow(clippy::redundant_clone, unused_must_use)] fn benchmark_float_clone_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.clone()", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.clone())), ("rug", &mut |(n, _)| no_out!(n.clone())), ], ); } fn benchmark_float_clone_from_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.clone_from(&Float)", BenchmarkType::LibraryComparison, float_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_float_max_complexity_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x.clone_from(&y)), ("rug", &mut |((mut x, y), _)| x.clone_from(&y)), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ integer_unsigned_rounding_mode_triple_gen_var_3, integer_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, Float}; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_integer_bit_u64_max_bucketer, triple_1_2_integer_bit_u64_max_bucketer, }; use malachite_nz::test_util::generators::{integer_gen, integer_unsigned_pair_gen_var_6}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_from_integer_prec); register_demo!(runner, demo_float_from_integer_prec_debug); register_demo!(runner, demo_float_from_integer_prec_ref); register_demo!(runner, demo_float_from_integer_prec_ref_debug); register_demo!(runner, demo_float_from_integer_prec_round); register_demo!(runner, demo_float_from_integer_prec_round_debug); register_demo!(runner, demo_float_from_integer_prec_round_ref); register_demo!(runner, demo_float_from_integer_prec_round_ref_debug); register_demo!(runner, demo_float_try_from_integer); register_demo!(runner, demo_float_try_from_integer_debug); register_demo!(runner, demo_float_try_from_integer_ref); register_demo!(runner, demo_float_try_from_integer_ref_debug); register_demo!(runner, demo_float_convertible_from_integer); register_bench!( runner, benchmark_float_from_integer_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_from_integer_prec_library_comparison); register_bench!( runner, benchmark_float_from_integer_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_from_integer_prec_round_library_comparison ); register_bench!(runner, benchmark_float_try_from_integer_evaluation_strategy); register_bench!(runner, benchmark_float_convertible_from_integer); } fn demo_float_from_integer_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in integer_unsigned_pair_gen_var_6() .get(gm, config) .take(limit) { println!( "Float::from_integer_prec({}, {}) = {:?}", n.clone(), p, Float::from_integer_prec(n, p) ); } } fn demo_float_from_integer_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in integer_unsigned_pair_gen_var_6() .get(gm, config) .take(limit) { let (f, o) = Float::from_integer_prec(n.clone(), p); println!( "Float::from_integer_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_from_integer_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in integer_unsigned_pair_gen_var_6() .get(gm, config) .take(limit) { println!( "Float::from_integer_prec_ref(&{}, {}) = {:?}", n, p, Float::from_integer_prec_ref(&n, p) ); } } fn demo_float_from_integer_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in integer_unsigned_pair_gen_var_6() .get(gm, config) .take(limit) { let (f, o) = Float::from_integer_prec_ref(&n, p); println!( "Float::from_integer_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_from_integer_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in integer_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::from_integer_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::from_integer_prec_round(n, p, rm) ); } } fn demo_float_from_integer_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in integer_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::from_integer_prec_round(n.clone(), p, rm); println!( "Float::from_integer_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_from_integer_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in integer_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::from_integer_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::from_integer_prec_round_ref(&n, p, rm) ); } } fn demo_float_from_integer_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in integer_unsigned_rounding_mode_triple_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::from_integer_prec_round_ref(&n, p, rm); println!( "Float::from_integer_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_try_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("Float::try_from({}) = {:?}", x.clone(), Float::try_from(x)); } } fn demo_float_try_from_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!( "Float::try_from({}) = {:?}", x.clone(), Float::try_from(x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_try_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("Float::try_from(&{}) = {:?}", x, Float::try_from(&x)); } } fn demo_float_try_from_integer_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!( "Float::try_from(&{}) = {:?}", x, Float::try_from(&x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_convertible_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Float", x, if Float::convertible_from(&x) { "" } else { "not " }, ); } } fn benchmark_float_from_integer_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_integer_prec(Integer, u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_integer_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_integer_prec(Integer, u64)", &mut |(n, prec)| no_out!(Float::from_integer_prec(n, prec)), ), ( "Float::from_integer_prec_ref(&Integer, u64)", &mut |(n, prec)| no_out!(Float::from_integer_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_from_integer_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_integer_prec(Integer, u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_integer_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec)| { no_out!(Float::from_integer_prec(n, prec)); }), ("rug", &mut |(n, prec)| { no_out!(rug::Float::with_val( u32::exact_from(prec), rug::Integer::from(&n), )); }), ], ); } fn benchmark_float_from_integer_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_integer_prec_round(Integer, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_integer_prec(Integer, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_integer_prec_round(n, prec, rm)), ), ( "Float::from_integer_prec_ref(&Integer, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_integer_prec_round_ref(&n, prec, rm)), ), ], ); } fn benchmark_float_from_integer_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_integer_prec_round(Integer, u64, RoundingMode)", BenchmarkType::LibraryComparison, integer_unsigned_rounding_mode_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec, rm)| { no_out!(Float::from_integer_prec_round(n, prec, rm)); }), ("rug", &mut |(n, prec, rm)| { no_out!(rug::Float::with_val_round( u32::exact_from(prec), rug::Integer::from(&n), rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_try_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::try_from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Float::try_from(Integer)", &mut |x| { no_out!(Float::try_from(x)); }), ("Float::try_from(&Integer)", &mut |x| { no_out!(Float::try_from(&x)); }), ], ); } fn benchmark_float_convertible_from_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::convertible_from(Integer)", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Float::convertible_from(&x)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ natural_unsigned_rounding_mode_triple_gen_var_2, natural_unsigned_rounding_mode_triple_gen_var_3, }; use malachite_float::{ComparableFloat, Float}; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_natural_bit_u64_max_bucketer, triple_1_2_natural_bit_u64_max_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_7}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_from_natural_prec); register_demo!(runner, demo_float_from_natural_prec_debug); register_demo!(runner, demo_float_from_natural_prec_ref); register_demo!(runner, demo_float_from_natural_prec_ref_debug); register_demo!(runner, demo_float_from_natural_prec_round); register_demo!(runner, demo_float_from_natural_prec_round_debug); register_demo!(runner, demo_float_from_natural_prec_round_ref); register_demo!(runner, demo_float_from_natural_prec_round_ref_debug); register_demo!(runner, demo_float_try_from_natural); register_demo!(runner, demo_float_try_from_natural_debug); register_demo!(runner, demo_float_try_from_natural_ref); register_demo!(runner, demo_float_try_from_natural_ref_debug); register_demo!(runner, demo_float_convertible_from_natural); register_bench!( runner, benchmark_float_from_natural_prec_evaluation_strategy ); register_bench!(runner, benchmark_float_from_natural_prec_library_comparison); register_bench!( runner, benchmark_float_from_natural_prec_round_evaluation_strategy ); register_bench!( runner, benchmark_float_from_natural_prec_round_library_comparison ); register_bench!(runner, benchmark_float_try_from_natural_evaluation_strategy); register_bench!(runner, benchmark_float_convertible_from_natural); } fn demo_float_from_natural_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "Float::from_natural_prec({}, {}) = {:?}", n.clone(), p, Float::from_natural_prec(n, p) ); } } fn demo_float_from_natural_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { let (f, o) = Float::from_natural_prec(n.clone(), p); println!( "Float::from_natural_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_from_natural_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "Float::from_natural_prec_ref(&{}, {}) = {:?}", n, p, Float::from_natural_prec_ref(&n, p) ); } } fn demo_float_from_natural_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { let (f, o) = Float::from_natural_prec_ref(&n, p); println!( "Float::from_natural_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_from_natural_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in natural_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "Float::from_natural_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::from_natural_prec_round(n, p, rm) ); } } fn demo_float_from_natural_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in natural_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let (f, o) = Float::from_natural_prec_round(n.clone(), p, rm); println!( "Float::from_natural_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_from_natural_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in natural_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "Float::from_natural_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::from_natural_prec_round_ref(&n, p, rm) ); } } fn demo_float_from_natural_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in natural_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let (f, o) = Float::from_natural_prec_round_ref(&n, p, rm); println!( "Float::from_natural_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_try_from_natural(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("Float::try_from({}) = {:?}", x.clone(), Float::try_from(x)); } } fn demo_float_try_from_natural_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!( "Float::try_from({}) = {:?}", x.clone(), Float::try_from(x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_try_from_natural_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("Float::try_from(&{}) = {:?}", x, Float::try_from(&x)); } } fn demo_float_try_from_natural_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!( "Float::try_from(&{}) = {:?}", x, Float::try_from(&x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_convertible_from_natural(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Float", x, if Float::convertible_from(&x) { "" } else { "not " }, ); } } fn benchmark_float_from_natural_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_natural_prec(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_natural_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_natural_prec(Natural, u64)", &mut |(n, prec)| no_out!(Float::from_natural_prec(n, prec)), ), ( "Float::from_natural_prec_ref(&Natural, u64)", &mut |(n, prec)| no_out!(Float::from_natural_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_from_natural_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_natural_prec(Natural, u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_natural_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec)| { no_out!(Float::from_natural_prec(n, prec)); }), ("rug", &mut |(n, prec)| { no_out!(rug::Float::with_val( u32::exact_from(prec), rug::Integer::from(&n), )); }), ], ); } fn benchmark_float_from_natural_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_natural_prec_round(Natural, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_natural_prec(Natural, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_natural_prec_round(n, prec, rm)), ), ( "Float::from_natural_prec_ref(&Natural, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_natural_prec_round_ref(&n, prec, rm)), ), ], ); } fn benchmark_float_from_natural_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_natural_prec_round(Natural, u64, RoundingMode)", BenchmarkType::LibraryComparison, natural_unsigned_rounding_mode_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec, rm)| { no_out!(Float::from_natural_prec_round(n, prec, rm)); }), ("rug", &mut |(n, prec, rm)| { no_out!(rug::Float::with_val_round( u32::exact_from(prec), rug::Integer::from(&n), rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_try_from_natural_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::try_from(Natural)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Float::try_from(Natural)", &mut |x| { no_out!(Float::try_from(x)); }), ("Float::try_from(&Natural)", &mut |x| { no_out!(Float::try_from(&x)); }), ], ); } fn benchmark_float_convertible_from_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::convertible_from(Natural)", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Float::convertible_from(&x)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::{SignificantBits, TrailingZeros}; use malachite_base::test_util::bench::bucketers::{ pair_primitive_float_bit_u64_max_bucketer, primitive_float_bucketer, triple_1_2_primitive_float_bit_u64_max_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_unsigned_pair_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ primitive_float_unsigned_rounding_mode_triple_gen_var_3, primitive_float_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, Float}; use rug::Assign; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::{Ordering, max}; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_from_primitive_float); register_primitive_float_demos!(runner, demo_float_from_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_from_primitive_float_prec); register_primitive_float_demos!(runner, demo_float_from_primitive_float_prec_debug); register_primitive_float_demos!(runner, demo_float_from_primitive_float_prec_round); register_primitive_float_demos!(runner, demo_float_from_primitive_float_prec_round_debug); register_primitive_float_benches!( runner, benchmark_float_from_primitive_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_from_primitive_float_prec_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_from_primitive_float_prec_round_library_comparison ); } fn demo_float_from_primitive_float(gm: GenMode, config: &GenConfig, limit: usize) where Float: From, { for x in primitive_float_gen::().get(gm, config).take(limit) { println!("Float::from({}) = {}", NiceFloat(x), Float::from(x)); } } fn demo_float_from_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From, { for x in primitive_float_gen::().get(gm, config).take(limit) { println!( "Float::from({}) = {:#x}", NiceFloat(x), ComparableFloat(Float::from(x)) ); } } fn demo_float_from_primitive_float_prec( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, prec) in primitive_float_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "Float::from_primitive_float_prec({}, {}) = {:?}", NiceFloat(x), prec, Float::from_primitive_float_prec(x, prec) ); } } fn demo_float_from_primitive_float_prec_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, prec) in primitive_float_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let (x_out, o) = Float::from_primitive_float_prec(x, prec); println!( "Float::from_primitive_float_prec({}, {}) = ({:#x}, {:?})", NiceFloat(x), prec, ComparableFloat(x_out), o ); } } fn demo_float_from_primitive_float_prec_round( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From, { for (x, prec, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "Float::from_primitive_float_prec_round({}, {}, {}) = {:?}", NiceFloat(x), prec, rm, Float::from_primitive_float_prec_round(x, prec, rm) ); } } fn demo_float_from_primitive_float_prec_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From, { for (x, prec, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { let (x_out, o) = Float::from_primitive_float_prec_round(x, prec, rm); println!( "Float::from_primitive_float_prec_round({}, {}, {}) = ({:#x}, {:?})", NiceFloat(x), prec, rm, ComparableFloat(x_out), o ); } } #[allow(unused_must_use)] fn benchmark_float_from_primitive_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, rug::Float: Assign, { run_benchmark( &format!("Float::from({})", T::NAME), BenchmarkType::LibraryComparison, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("x"), &mut [ ("Malachite", &mut |x| no_out!(Float::from(x))), ("rug", &mut |x| { no_out!(rug::Float::with_val( if !x.is_finite() || x == T::ZERO { 1 } else { let n = x.integer_mantissa(); u32::exact_from(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }, x )); }), ], ); } fn benchmark_float_from_primitive_float_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, rug::Float: Assign, { run_benchmark( &format!("Float::from_primitive_float_prec({}, u64)", T::NAME), BenchmarkType::LibraryComparison, primitive_float_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_primitive_float_bit_u64_max_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(x, prec)| { no_out!(Float::from_primitive_float_prec(x, prec)); }), ("rug", &mut |(x, prec)| { no_out!(rug::Float::with_val(max(1, u32::exact_from(prec)), x)); }), ], ); } fn benchmark_float_from_primitive_float_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, rug::Float: AssignRound, { run_benchmark( &format!( "Float::from_primitive_float_prec_round({}, u64, RoundingMode)", T::NAME ), BenchmarkType::LibraryComparison, primitive_float_unsigned_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_primitive_float_bit_u64_max_bucketer("x", "prec"), &mut [ ("Malachite", &mut |(x, prec, rm)| { no_out!(Float::from_primitive_float_prec_round(x, prec, rm)); }), ("rug", &mut |(x, prec, rm)| { no_out!(rug::Float::with_val_round( max(1, u32::exact_from(prec)), x, rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::test_util::bench::bucketers::{ pair_1_bit_bucketer, pair_primitive_int_bit_u64_max_bucketer, signed_bit_bucketer, triple_1_2_primitive_int_bit_u64_max_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen_var_2, signed_unsigned_pair_gen_var_20, unsigned_gen, unsigned_pair_gen_var_32, unsigned_signed_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ signed_unsigned_rounding_mode_triple_gen_var_3, signed_unsigned_rounding_mode_triple_gen_var_4, unsigned_unsigned_rounding_mode_triple_gen_var_5, unsigned_unsigned_rounding_mode_triple_gen_var_6, }; use malachite_float::{ComparableFloat, Float}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use rug::Assign; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_float_from_unsigned); register_unsigned_demos!(runner, demo_float_from_unsigned_debug); register_unsigned_demos!(runner, demo_float_from_unsigned_prec); register_unsigned_demos!(runner, demo_float_from_unsigned_prec_debug); register_unsigned_demos!(runner, demo_float_from_unsigned_prec_round); register_unsigned_demos!(runner, demo_float_from_unsigned_prec_round_debug); register_demo!(runner, demo_float_const_from_unsigned); register_demo!(runner, demo_float_const_from_unsigned_debug); register_demo!(runner, demo_float_const_from_unsigned_times_power_of_2); register_demo!( runner, demo_float_const_from_unsigned_times_power_of_2_debug ); register_signed_demos!(runner, demo_float_from_signed); register_signed_demos!(runner, demo_float_from_signed_debug); register_signed_demos!(runner, demo_float_from_signed_prec); register_signed_demos!(runner, demo_float_from_signed_prec_debug); register_signed_demos!(runner, demo_float_from_signed_prec_round); register_signed_demos!(runner, demo_float_from_signed_prec_round_debug); register_demo!(runner, demo_float_const_from_signed); register_demo!(runner, demo_float_const_from_signed_debug); register_demo!(runner, demo_float_const_from_signed_times_power_of_2); register_demo!(runner, demo_float_const_from_signed_times_power_of_2_debug); register_unsigned_benches!(runner, benchmark_float_from_unsigned_library_comparison); register_unsigned_benches!( runner, benchmark_float_from_unsigned_prec_library_comparison ); register_unsigned_benches!( runner, benchmark_float_from_unsigned_prec_round_library_comparison ); register_bench!(runner, benchmark_float_const_from_unsigned); register_bench!(runner, benchmark_float_const_from_unsigned_times_power_of_2); register_signed_benches!(runner, benchmark_float_from_signed_library_comparison); register_signed_benches!(runner, benchmark_float_from_signed_prec_library_comparison); register_signed_benches!( runner, benchmark_float_from_signed_prec_round_library_comparison ); register_bench!(runner, benchmark_float_const_from_signed); register_bench!(runner, benchmark_float_const_from_signed_times_power_of_2); } fn demo_float_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Float: From, { for n in unsigned_gen::().get(gm, config).take(limit) { println!("Float::from({}) = {}", n, Float::from(n)); } } fn demo_float_from_unsigned_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: From, { for n in unsigned_gen::().get(gm, config).take(limit) { println!( "Float::from({:#x}) = {:#x}", n, ComparableFloat(Float::from(n)) ); } } fn demo_float_from_unsigned_prec( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: From, { for (n, p) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { println!( "Float::from_unsigned_prec({}, {}) = {:?}", n, p, Float::from_unsigned_prec(n, p) ); } } fn demo_float_from_unsigned_prec_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: From, { for (n, p) in unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { let (f, o) = Float::from_unsigned_prec(n, p); println!( "Float::from_unsigned_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_from_unsigned_prec_round( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: From, { for (n, p, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { println!( "Float::from_unsigned_prec_round({}, {}, {:?}) = {:?}", n, p, rm, Float::from_unsigned_prec_round(n, p, rm) ); } } fn demo_float_from_unsigned_prec_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: From, { for (n, p, rm) in unsigned_unsigned_rounding_mode_triple_gen_var_5::() .get(gm, config) .take(limit) { let (f, o) = Float::from_unsigned_prec_round(n, p, rm); println!( "Float::from_unsigned_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_const_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen().get(gm, config).take(limit) { println!( "Float::const_from_unsigned({}) = {}", n, Float::const_from_unsigned(n) ); } } fn demo_float_const_from_unsigned_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen().get(gm, config).take(limit) { println!( "Float::const_from_unsigned({:#x}) = {:#x}", n, ComparableFloat(Float::const_from_unsigned(n)) ); } } fn demo_float_const_from_unsigned_times_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in unsigned_signed_pair_gen_var_1().get(gm, config).take(limit) { println!( "Float::const_from_unsigned_times_power_of_2({}, {}) = {}", n, pow, Float::const_from_unsigned_times_power_of_2(n, pow) ); } } fn demo_float_const_from_unsigned_times_power_of_2_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in unsigned_signed_pair_gen_var_1().get(gm, config).take(limit) { println!( "Float::const_from_unsigned_times_power_of_2({:#x}, {}) = {:#x}", n, pow, Float::const_from_unsigned_times_power_of_2(n, pow) ); } } fn demo_float_from_signed(gm: GenMode, config: &GenConfig, limit: usize) where Float: From, { for n in signed_gen::().get(gm, config).take(limit) { println!("Float::from({}) = {}", n, Float::from(n)); } } fn demo_float_from_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) where Float: From, { for n in signed_gen::().get(gm, config).take(limit) { println!( "Float::from({:#x}) = {:#x}", n, ComparableFloat(Float::from(n)) ); } } fn demo_float_from_signed_prec(gm: GenMode, config: &GenConfig, limit: usize) where Integer: From, { for (n, p) in signed_unsigned_pair_gen_var_20::() .get(gm, config) .take(limit) { println!( "Float::from_signed_prec({}, {}) = {:?}", n, p, Float::from_signed_prec(n, p) ); } } fn demo_float_from_signed_prec_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: From, { for (n, p) in signed_unsigned_pair_gen_var_20::() .get(gm, config) .take(limit) { let (f, o) = Float::from_signed_prec(n, p); println!( "Float::from_signed_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_from_signed_prec_round( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: From, { for (n, p, rm) in signed_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { println!( "Float::from_signed_prec_round({}, {}, {:?}) = {:?}", n, p, rm, Float::from_signed_prec_round(n, p, rm) ); } } fn demo_float_from_signed_prec_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: From, { for (n, p, rm) in signed_unsigned_rounding_mode_triple_gen_var_3::() .get(gm, config) .take(limit) { let (f, o) = Float::from_signed_prec_round(n, p, rm); println!( "Float::from_signed_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_const_from_signed(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen().get(gm, config).take(limit) { println!( "Float::const_from_signed({}) = {}", n, Float::const_from_signed(n) ); } } fn demo_float_const_from_signed_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in signed_gen().get(gm, config).take(limit) { println!( "Float::const_from_signed({:#x}) = {:#x}", n, ComparableFloat(Float::const_from_signed(n)) ); } } fn demo_float_const_from_signed_times_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in signed_pair_gen_var_2().get(gm, config).take(limit) { println!( "Float::const_from_signed_times_power_of_2({}, {}) = {}", n, pow, Float::const_from_signed_times_power_of_2(n, pow) ); } } fn demo_float_const_from_signed_times_power_of_2_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow) in signed_pair_gen_var_2().get(gm, config).take(limit) { println!( "Float::const_from_signed_times_power_of_2({:#x}, {}) = {:#x}", n, pow, Float::const_from_signed_times_power_of_2(n, pow) ); } } #[allow(unused_must_use)] fn benchmark_float_from_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, rug::Float: Assign, { run_benchmark( &format!("Float::from({})", T::NAME), BenchmarkType::LibraryComparison, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |n| no_out!(Float::from(n))), ("rug", &mut |n| { no_out!(rug::Float::with_val( if n == T::ZERO { 1 } else { u32::exact_from(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }, n )); }), ], ); } fn benchmark_float_from_unsigned_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, Natural: From, rug::Float: Assign, { run_benchmark( &format!("Float::from_unsigned_prec({}, u64)", T::NAME), BenchmarkType::LibraryComparison, unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_primitive_int_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec)| { no_out!(Float::from_unsigned_prec(n, prec)); }), ("rug", &mut |(n, prec)| { no_out!(rug::Float::with_val(u32::exact_from(prec), n)); }), ], ); } fn benchmark_float_from_unsigned_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, Natural: From, rug::Float: AssignRound, { run_benchmark( &format!( "Float::from_unsigned_prec_round({}, u64, RoundingMode)", T::NAME ), BenchmarkType::LibraryComparison, unsigned_unsigned_rounding_mode_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_primitive_int_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec, rm)| { no_out!(Float::from_unsigned_prec_round(n, prec, rm)); }), ("rug", &mut |(n, prec, rm)| { no_out!(rug::Float::with_val_round( u32::exact_from(prec), n, rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } fn benchmark_float_const_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::const_from_unsigned(Limb)", BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(Float::const_from_unsigned(n)))], ); } fn benchmark_float_const_from_unsigned_times_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::const_from_unsigned_times_power_of_2(Limb)", BenchmarkType::Single, unsigned_signed_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(Float::const_from_unsigned_times_power_of_2(n, pow)); })], ); } #[allow(unused_must_use)] fn benchmark_float_from_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, rug::Float: Assign, { run_benchmark( &format!("Float::from({})", T::NAME), BenchmarkType::LibraryComparison, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |n| no_out!(Float::from(n))), ("rug", &mut |n| { no_out!(rug::Float::with_val( if n == T::ZERO { 1 } else { u32::exact_from(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }, n )); }), ], ); } fn benchmark_float_from_signed_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, Integer: From, rug::Float: Assign, { run_benchmark( &format!("Float::from_signed_prec({}, u64)", T::NAME), BenchmarkType::LibraryComparison, signed_unsigned_pair_gen_var_20::().get(gm, config), gm.name(), limit, file_name, &pair_primitive_int_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec)| { no_out!(Float::from_signed_prec(n, prec)); }), ("rug", &mut |(n, prec)| { no_out!(rug::Float::with_val(u32::exact_from(prec), n)); }), ], ); } fn benchmark_float_from_signed_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Float: From, Integer: From, rug::Float: AssignRound, { run_benchmark( &format!( "Float::from_signed_prec_round({}, u64, RoundingMode)", T::NAME ), BenchmarkType::LibraryComparison, signed_unsigned_rounding_mode_triple_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_primitive_int_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec, rm)| { no_out!(Float::from_signed_prec_round(n, prec, rm)); }), ("rug", &mut |(n, prec, rm)| { no_out!(rug::Float::with_val_round( u32::exact_from(prec), n, rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } fn benchmark_float_const_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::const_from_signed(Limb)", BenchmarkType::Single, signed_gen().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |n| no_out!(Float::const_from_signed(n)))], ); } fn benchmark_float_const_from_signed_times_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::const_from_signed_times_power_of_2(Limb)", BenchmarkType::Single, signed_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, pow)| { no_out!(Float::const_from_signed_times_power_of_2(n, pow)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::conversion::from_rational::{ from_rational_prec_round_direct, from_rational_prec_round_ref_direct, from_rational_prec_round_ref_using_div, from_rational_prec_round_using_div, }; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::generators::{ rational_unsigned_rounding_mode_triple_gen_var_1, rational_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_float::{ComparableFloat, Float}; use malachite_q::test_util::bench::bucketers::{ pair_rational_bit_u64_max_bucketer, rational_bit_bucketer, triple_1_2_rational_bit_u64_max_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_from_rational_prec); register_demo!(runner, demo_float_from_rational_prec_debug); register_demo!(runner, demo_float_from_rational_prec_ref); register_demo!(runner, demo_float_from_rational_prec_ref_debug); register_demo!(runner, demo_float_from_rational_prec_round); register_demo!(runner, demo_float_from_rational_prec_round_debug); register_demo!(runner, demo_float_from_rational_prec_round_ref); register_demo!(runner, demo_float_from_rational_prec_round_ref_debug); register_demo!(runner, demo_float_try_from_rational); register_demo!(runner, demo_float_try_from_rational_debug); register_demo!(runner, demo_float_try_from_rational_ref); register_demo!(runner, demo_float_try_from_rational_ref_debug); register_demo!(runner, demo_float_convertible_from_rational); register_bench!( runner, benchmark_float_from_rational_prec_evaluation_strategy ); register_bench!( runner, benchmark_float_from_rational_prec_library_comparison ); register_bench!( runner, benchmark_float_from_rational_prec_round_evaluation_strategy ); register_bench!(runner, benchmark_float_from_rational_prec_round_algorithms); register_bench!( runner, benchmark_float_from_rational_prec_round_ref_algorithms ); register_bench!( runner, benchmark_float_from_rational_prec_round_library_comparison ); register_bench!( runner, benchmark_float_try_from_rational_evaluation_strategy ); register_bench!(runner, benchmark_float_convertible_from_rational); } fn demo_float_from_rational_prec(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::from_rational_prec({}, {}) = {:?}", n.clone(), p, Float::from_rational_prec(n, p) ); } } fn demo_float_from_rational_prec_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::from_rational_prec(n.clone(), p); println!( "Float::from_rational_prec({}, {}) = ({:#x}, {:?})", n, p, ComparableFloat(f), o ); } } fn demo_float_from_rational_prec_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Float::from_rational_prec_ref(&{}, {}) = {:?}", n, p, Float::from_rational_prec_ref(&n, p) ); } } fn demo_float_from_rational_prec_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p) in rational_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let (f, o) = Float::from_rational_prec_ref(&n, p); println!( "Float::from_rational_prec_ref(&{}, {}) = {:x?}", n, p, (ComparableFloat(f), o) ); } } fn demo_float_from_rational_prec_round(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "Float::from_rational_prec_round({}, {}, {:?}) = {:?}", n.clone(), p, rm, Float::from_rational_prec_round(n, p, rm) ); } } fn demo_float_from_rational_prec_round_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (f, o) = Float::from_rational_prec_round(n.clone(), p, rm); println!( "Float::from_rational_prec_round({}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_from_rational_prec_round_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "Float::from_rational_prec_round_ref(&{}, {}, {:?}) = {:?}", n, p, rm, Float::from_rational_prec_round_ref(&n, p, rm) ); } } fn demo_float_from_rational_prec_round_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (n, p, rm) in rational_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let (f, o) = Float::from_rational_prec_round_ref(&n, p, rm); println!( "Float::from_rational_prec_round_ref(&{}, {}, {:?}) = {:x?}", n, p, rm, (ComparableFloat(f), o) ); } } fn demo_float_try_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("Float::try_from({}) = {:?}", x.clone(), Float::try_from(x)); } } fn demo_float_try_from_rational_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "Float::try_from({}) = {:?}", x.clone(), Float::try_from(x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_try_from_rational_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("Float::try_from(&{}) = {:?}", x, Float::try_from(&x)); } } fn demo_float_try_from_rational_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "Float::try_from(&{}) = {:?}", x, Float::try_from(&x).map(|f| format!("{:#x}", ComparableFloat(f))) ); } } fn demo_float_convertible_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Float", x, if Float::convertible_from(&x) { "" } else { "not " }, ); } } fn benchmark_float_from_rational_prec_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec(Rational, u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_rational_prec(Rational, u64)", &mut |(n, prec)| no_out!(Float::from_rational_prec(n, prec)), ), ( "Float::from_rational_prec_ref(&Rational, u64)", &mut |(n, prec)| no_out!(Float::from_rational_prec_ref(&n, prec)), ), ], ); } fn benchmark_float_from_rational_prec_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec(Rational, u64)", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec)| { no_out!(Float::from_rational_prec(n, prec)); }), ("rug", &mut |(n, prec)| { no_out!(rug::Float::with_val( u32::exact_from(prec), rug::Rational::from(&n), )); }), ], ); } fn benchmark_float_from_rational_prec_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ( "Float::from_rational_prec(Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_rational_prec_round(n, prec, rm)), ), ( "Float::from_rational_prec_ref(&Rational, u64, RoundingMode)", &mut |(n, prec, rm)| no_out!(Float::from_rational_prec_round_ref(&n, prec, rm)), ), ], ); } fn benchmark_float_from_rational_prec_round_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("default", &mut |(n, prec, rm)| { no_out!(Float::from_rational_prec_round(n, prec, rm)); }), ("direct", &mut |(n, prec, rm)| { no_out!(from_rational_prec_round_direct(n, prec, rm)); }), ("using div", &mut |(n, prec, rm)| { no_out!(from_rational_prec_round_using_div(n, prec, rm)); }), ], ); } fn benchmark_float_from_rational_prec_round_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec_round_ref(&Rational, u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("default", &mut |(n, prec, rm)| { no_out!(Float::from_rational_prec_round_ref(&n, prec, rm)); }), ("direct", &mut |(n, prec, rm)| { no_out!(from_rational_prec_round_ref_direct(&n, prec, rm)); }), ("using div", &mut |(n, prec, rm)| { no_out!(from_rational_prec_round_ref_using_div(&n, prec, rm)); }), ], ); } fn benchmark_float_from_rational_prec_round_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_rational_prec_round(Rational, u64, RoundingMode)", BenchmarkType::LibraryComparison, rational_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_u64_max_bucketer("n", "prec"), &mut [ ("Malachite", &mut |(n, prec, rm)| { no_out!(Float::from_rational_prec_round(n, prec, rm)); }), ("rug", &mut |(n, prec, rm)| { no_out!(rug::Float::with_val_round( u32::exact_from(prec), rug::Rational::from(&n), rug_round_try_from_rounding_mode(rm).unwrap() )); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_try_from_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::try_from(Rational)", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Float::try_from(Rational)", &mut |x| { no_out!(Float::try_from(x)); }), ("Float::try_from(&Rational)", &mut |x| { no_out!(Float::try_from(&x)); }), ], ); } fn benchmark_float_convertible_from_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::convertible_from(Rational)", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Float::convertible_from(&x)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/integer_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{float_gen, float_rounding_mode_pair_gen_var_2}; use malachite_float::{ComparableFloat, ComparableFloatRef}; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_rounding_from_float); register_demo!(runner, demo_integer_rounding_from_float_debug); register_demo!(runner, demo_integer_rounding_from_float_ref); register_demo!(runner, demo_integer_rounding_from_float_ref_debug); register_demo!(runner, demo_integer_try_from_float); register_demo!(runner, demo_integer_try_from_float_debug); register_demo!(runner, demo_integer_try_from_float_ref); register_demo!(runner, demo_integer_try_from_float_ref_debug); register_demo!(runner, demo_integer_convertible_from_float); register_demo!(runner, demo_integer_convertible_from_float_debug); register_bench!( runner, benchmark_integer_rounding_from_float_evaluation_strategy ); register_bench!(runner, benchmark_integer_try_from_float_evaluation_strategy); register_bench!(runner, benchmark_integer_convertible_from_float); } fn demo_integer_rounding_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::rounding_from({}, {}) = {:?}", f.clone(), rm, Integer::rounding_from(f, rm) ); } } fn demo_integer_rounding_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::rounding_from({:#x}, {}) = {:?}", ComparableFloat(f.clone()), rm, Integer::rounding_from(f, rm) ); } } fn demo_integer_rounding_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::rounding_from(&{}, {}) = {:?}", f, rm, Integer::rounding_from(&f, rm) ); } } fn demo_integer_rounding_from_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::rounding_from(&{:#x}, {}) = {:?}", ComparableFloatRef(&f), rm, Integer::rounding_from(&f, rm) ); } } fn demo_integer_try_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Integer::try_from({}) = {:?}", f.clone(), Integer::try_from(f) ); } } fn demo_integer_try_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Integer::try_from({:#x}) = {:?}", ComparableFloat(f.clone()), Integer::try_from(f) ); } } fn demo_integer_try_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!("Integer::try_from(&{}) = {:?}", f, Integer::try_from(&f)); } } fn demo_integer_try_from_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Integer::try_from(&{:#x}) = {:?}", ComparableFloatRef(&f), Integer::try_from(&f) ); } } fn demo_integer_convertible_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to an Integer", f, if Integer::convertible_from(&f) { "" } else { "not " }, ); } } fn demo_integer_convertible_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to an Integer", ComparableFloatRef(&f), if Integer::convertible_from(&f) { "" } else { "not " }, ); } } fn benchmark_integer_rounding_from_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::rounding_from(Float)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Integer::rounding_from(Float)", &mut |(f, rm)| { no_out!(Integer::rounding_from(f, rm)); }), ("Integer::rounding_from(&Float)", &mut |(f, rm)| { no_out!(Integer::rounding_from(&f, rm)); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_try_from_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::try_from(Float)", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Integer::try_from(Float)", &mut |f| { no_out!(Integer::try_from(f)); }), ("Integer::try_from(&Float)", &mut |f| { no_out!(Integer::try_from(&f)); }), ], ); } fn benchmark_integer_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::convertible_from(&Float)", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |f| no_out!(Integer::convertible_from(&f)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/integer_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IntegerMantissaAndExponent; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen_var_3, float_gen_var_13}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_signed_pair_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_integer_mantissa_and_exponent); register_demo!(runner, demo_float_integer_mantissa_and_exponent_debug); register_demo!(runner, demo_float_integer_mantissa_and_exponent_extreme); register_demo!( runner, demo_float_integer_mantissa_and_exponent_extreme_debug ); register_demo!(runner, demo_float_integer_mantissa_and_exponent_ref); register_demo!(runner, demo_float_integer_mantissa_and_exponent_ref_debug); register_demo!(runner, demo_float_integer_mantissa); register_demo!(runner, demo_float_integer_mantissa_debug); register_demo!(runner, demo_float_integer_mantissa_extreme); register_demo!(runner, demo_float_integer_mantissa_extreme_debug); register_demo!(runner, demo_float_integer_mantissa_ref); register_demo!(runner, demo_float_integer_mantissa_ref_debug); register_demo!(runner, demo_float_integer_exponent); register_demo!(runner, demo_float_integer_exponent_debug); register_demo!(runner, demo_float_integer_exponent_extreme); register_demo!(runner, demo_float_integer_exponent_extreme_debug); register_demo!(runner, demo_float_integer_exponent_ref); register_demo!(runner, demo_float_integer_exponent_ref_debug); register_demo!(runner, demo_float_from_integer_mantissa_and_exponent); register_demo!(runner, demo_float_from_integer_mantissa_and_exponent_debug); register_demo!(runner, demo_float_from_integer_mantissa_and_exponent_ref); register_demo!( runner, demo_float_from_integer_mantissa_and_exponent_ref_debug ); register_bench!( runner, benchmark_float_integer_mantissa_and_exponent_evaluation_strategy ); register_bench!(runner, benchmark_float_integer_mantissa_evaluation_strategy); register_bench!(runner, benchmark_float_integer_exponent_evaluation_strategy); register_bench!( runner, benchmark_float_from_integer_mantissa_and_exponent_evaluation_strategy ); } fn demo_float_integer_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.integer_mantissa_and_exponent() = {:?}", n.clone(), n.integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa_and_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.integer_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), n.integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa_and_exponent_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.integer_mantissa_and_exponent() = {:?}", n.clone(), n.integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa_and_exponent_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.integer_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), n.integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa_and_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{}).integer_mantissa_and_exponent() = {:?}", n, (&n).integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa_and_exponent_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).integer_mantissa_and_exponent() = {:?}", ComparableFloatRef(&n), (&n).integer_mantissa_and_exponent() ); } } fn demo_float_integer_mantissa(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.integer_mantissa() = {}", n.clone(), n.integer_mantissa() ); } } fn demo_float_integer_mantissa_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.integer_mantissa() = {:#x}", ComparableFloat(n.clone()), n.integer_mantissa() ); } } fn demo_float_integer_mantissa_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.integer_mantissa() = {}", n.clone(), n.integer_mantissa() ); } } fn demo_float_integer_mantissa_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.integer_mantissa() = {:#x}", ComparableFloat(n.clone()), n.integer_mantissa() ); } } fn demo_float_integer_mantissa_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("(&{}).integer_mantissa() = {}", n, (&n).integer_mantissa()); } } fn demo_float_integer_mantissa_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).integer_mantissa() = {:#x}", ComparableFloatRef(&n), (&n).integer_mantissa() ); } } fn demo_float_integer_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.integer_exponent() = {}", n.clone(), n.integer_exponent() ); } } fn demo_float_integer_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.integer_exponent() = {}", ComparableFloat(n.clone()), n.integer_exponent() ); } } fn demo_float_integer_exponent_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.integer_exponent() = {}", n.clone(), n.integer_exponent() ); } } fn demo_float_integer_exponent_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.integer_exponent() = {}", ComparableFloat(n.clone()), n.integer_exponent() ); } } fn demo_float_integer_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("{}.integer_exponent() = {}", n, (&n).integer_exponent()); } } fn demo_float_integer_exponent_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.integer_exponent() = {}", ComparableFloatRef(&n), (&n).integer_exponent() ); } } fn demo_float_from_integer_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n = > ::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); println!( "Float::from_integer_mantissa_and_exponent({}, {}) = {}", mantissa, exponent, n.unwrap() ); } } fn demo_float_from_integer_mantissa_and_exponent_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n = > ::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); println!( "Float::from_integer_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n.unwrap()) ); } } fn demo_float_from_integer_mantissa_and_exponent_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n = <&Float as IntegerMantissaAndExponent::> ::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); println!( "Float::from_integer_mantissa_and_exponent({}, {}) = {}", mantissa, exponent, n.unwrap() ); } } fn demo_float_from_integer_mantissa_and_exponent_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n = <&Float as IntegerMantissaAndExponent::> ::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); println!( "Float::from_integer_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n.unwrap()) ); } } fn benchmark_float_integer_mantissa_and_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.integer_mantissa_and_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.integer_mantissa_and_exponent()", &mut |x| { no_out!(x.integer_mantissa_and_exponent()); }), ("(&Float).integer_mantissa_and_exponent()", &mut |x| { no_out!((&x).integer_mantissa_and_exponent()); }), ], ); } fn benchmark_float_integer_mantissa_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.integer_mantissa()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.integer_mantissa()", &mut |x| { no_out!(x.integer_mantissa()); }), ("(&Float).integer_mantissa()", &mut |x| { no_out!((&x).integer_mantissa()); }), ], ); } fn benchmark_float_integer_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.integer_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.integer_exponent()", &mut |x| { no_out!(x.integer_exponent()); }), ("(&Float).integer_exponent()", &mut |x| { no_out!((&x).integer_exponent()); }), ], ); } fn benchmark_float_from_integer_mantissa_and_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_integer_mantissa_and_exponent(Float, i64)", BenchmarkType::EvaluationStrategy, natural_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ( "Float::from_integer_mantissa_and_exponent(Float, i64)", &mut |(mantissa, exponent)| { no_out!(>::from_integer_mantissa_and_exponent( mantissa, exponent )); }, ), ( "(&Float)::from_integer_mantissa_and_exponent(Float, i64)", &mut |(mantissa, exponent)| { no_out!(<&Float as IntegerMantissaAndExponent::< Natural, i64, Float, >>::from_integer_mantissa_and_exponent( mantissa, exponent )); }, ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloat; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_is_integer); register_demo!(runner, demo_float_is_integer_debug); register_demo!(runner, demo_float_is_integer_extreme); register_demo!(runner, demo_float_is_integer_extreme_debug); register_bench!(runner, benchmark_float_is_integer); } fn demo_float_is_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { if n.is_integer() { println!("{n} is an integer"); } else { println!("{n} is not an integer"); } } } fn demo_float_is_integer_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen().get(gm, config).take(limit) { if n.is_integer() { println!("{:#x} is an integer", ComparableFloat(n)); } else { println!("{:#x} is not an integer", ComparableFloat(n)); } } } fn demo_float_is_integer_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { if n.is_integer() { println!("{n} is an integer"); } else { println!("{n} is not an integer"); } } } fn demo_float_is_integer_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_12().get(gm, config).take(limit) { if n.is_integer() { println!("{:#x} is an integer", ComparableFloat(n)); } else { println!("{:#x} is not an integer", ComparableFloat(n)); } } } fn benchmark_float_is_integer(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Float.is_integer()", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); from_integer::register(runner); from_natural::register(runner); from_primitive_float::register(runner); from_primitive_int::register(runner); from_rational::register(runner); integer_from_float::register(runner); integer_mantissa_and_exponent::register(runner); is_integer::register(runner); natural_from_float::register(runner); primitive_float_from_float::register(runner); primitive_int_from_float::register(runner); rational_from_float::register(runner); raw_mantissa_and_exponent::register(runner); sci_mantissa_and_exponent::register(runner); string::register(runner); } mod clone; mod from_integer; mod from_natural; mod from_primitive_float; mod from_primitive_int; mod from_rational; mod integer_from_float; mod integer_mantissa_and_exponent; mod is_integer; mod natural_from_float; mod primitive_float_from_float; mod primitive_int_from_float; mod rational_from_float; mod raw_mantissa_and_exponent; mod sci_mantissa_and_exponent; mod string; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/natural_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{float_gen, float_rounding_mode_pair_gen_var_1}; use malachite_float::{ComparableFloat, ComparableFloatRef}; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_rounding_from_float); register_demo!(runner, demo_natural_rounding_from_float_debug); register_demo!(runner, demo_natural_rounding_from_float_ref); register_demo!(runner, demo_natural_rounding_from_float_ref_debug); register_demo!(runner, demo_natural_try_from_float); register_demo!(runner, demo_natural_try_from_float_debug); register_demo!(runner, demo_natural_try_from_float_ref); register_demo!(runner, demo_natural_try_from_float_ref_debug); register_demo!(runner, demo_natural_convertible_from_float); register_demo!(runner, demo_natural_convertible_from_float_debug); register_bench!( runner, benchmark_natural_rounding_from_float_evaluation_strategy ); register_bench!(runner, benchmark_natural_try_from_float_evaluation_strategy); register_bench!(runner, benchmark_natural_convertible_from_float); } fn demo_natural_rounding_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural::rounding_from({}, {}) = {:?}", f.clone(), rm, Natural::rounding_from(f, rm) ); } } fn demo_natural_rounding_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural::rounding_from({:#x}, {}) = {:?}", ComparableFloat(f.clone()), rm, Natural::rounding_from(f, rm) ); } } fn demo_natural_rounding_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural::rounding_from(&{}, {}) = {:?}", f, rm, Natural::rounding_from(&f, rm) ); } } fn demo_natural_rounding_from_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (f, rm) in float_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural::rounding_from(&{:#x}, {}) = {:?}", ComparableFloatRef(&f), rm, Natural::rounding_from(&f, rm) ); } } fn demo_natural_try_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Natural::try_from({}) = {:?}", f.clone(), Natural::try_from(f) ); } } fn demo_natural_try_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Natural::try_from({:#x}) = {:#x?}", ComparableFloat(f.clone()), Natural::try_from(f) ); } } fn demo_natural_try_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!("Natural::try_from(&{}) = {:?}", f, Natural::try_from(&f)); } } fn demo_natural_try_from_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Natural::try_from(&{:#x}) = {:#x?}", ComparableFloatRef(&f), Natural::try_from(&f) ); } } fn demo_natural_convertible_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Natural", f, if Natural::convertible_from(&f) { "" } else { "not " }, ); } } fn demo_natural_convertible_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to a Natural", ComparableFloatRef(&f), if Natural::convertible_from(&f) { "" } else { "not " }, ); } } fn benchmark_natural_rounding_from_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::rounding_from(Float)", BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ("Natural::rounding_from(Float)", &mut |(f, rm)| { no_out!(Natural::rounding_from(f, rm)); }), ("Natural::rounding_from(&Float)", &mut |(f, rm)| { no_out!(Natural::rounding_from(&f, rm)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_try_from_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::try_from(Float)", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Natural::try_from(Float)", &mut |f| { no_out!(Natural::try_from(f)); }), ("Natural::try_from(&Float)", &mut |f| { no_out!(Natural::try_from(&f)); }), ], ); } fn benchmark_natural_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::convertible_from(&Float)", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |f| no_out!(Natural::convertible_from(&f)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/primitive_float_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::conversion::primitive_float_from_float::FloatFromFloatError; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_rounding_mode_pair_gen_var_6, float_rounding_mode_pair_gen_var_20, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_primitive_float_rounding_from_float); register_primitive_float_demos!(runner, demo_primitive_float_rounding_from_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_rounding_from_float_extreme); register_primitive_float_demos!( runner, demo_primitive_float_rounding_from_float_extreme_debug ); register_primitive_float_demos!(runner, demo_primitive_float_rounding_from_float_ref); register_primitive_float_demos!(runner, demo_primitive_float_rounding_from_float_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float_extreme); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float_extreme_debug); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float_ref); register_primitive_float_demos!(runner, demo_primitive_float_try_from_float_ref_debug); register_primitive_float_demos!(runner, demo_primitive_float_convertible_from_float); register_primitive_float_demos!(runner, demo_primitive_float_convertible_from_float_debug); register_primitive_float_demos!(runner, demo_primitive_float_convertible_from_float_extreme); register_primitive_float_demos!( runner, demo_primitive_float_convertible_from_float_extreme_debug ); register_primitive_float_benches!(runner, benchmark_primitive_float_try_from_float); register_primitive_float_benches!(runner, benchmark_primitive_float_convertible_from_float); register_primitive_float_benches!(runner, benchmark_primitive_float_rounding_from_float); } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_6::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(x.clone(), rm); println!( "{}::rounding_from({}, {}) = ({}, {:?})", T::NAME, x, rm, NiceFloat(x_out), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_6::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(x.clone(), rm); println!( "{}::rounding_from({:#x}, {}) = ({}, {:?})", T::NAME, ComparableFloat(x), rm, NiceFloat(x_out), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float_extreme>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_20::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(x.clone(), rm); println!( "{}::rounding_from({}, {}) = ({}, {:?})", T::NAME, x, rm, NiceFloat(x_out), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float_extreme_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_20::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(x.clone(), rm); println!( "{}::rounding_from({:#x}, {}) = ({}, {:?})", T::NAME, ComparableFloat(x), rm, NiceFloat(x_out), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_6::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(&x, rm); println!( "{}::rounding_from(&{}, {}) = ({}, {:?})", T::NAME, x, rm, NiceFloat(x_out), o ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_rounding_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_6::() .get(gm, config) .take(limit) { let (x_out, o) = T::rounding_from(&x, rm); println!( "{}::rounding_from(&{:#x}, {}) = ({}, {:?})", T::NAME, ComparableFloatRef(&x), rm, NiceFloat(x_out), o ); } } fn demo_primitive_float_try_from_float< T: TryFrom + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x).map(NiceFloat) ); } } fn demo_primitive_float_try_from_float_debug< T: TryFrom + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x).map(NiceFloat) ); } } fn demo_primitive_float_try_from_float_extreme< T: TryFrom + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x).map(NiceFloat) ); } } fn demo_primitive_float_try_from_float_extreme_debug< T: TryFrom + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x).map(NiceFloat) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_try_from_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: TryFrom<&'a Float, Error = FloatFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x, T::try_from(&x).map(NiceFloat) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_try_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: TryFrom<&'a Float, Error = FloatFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloatRef(&x), T::try_from(&x).map(NiceFloat) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to an {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_convertible_from_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to an {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_convertible_from_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{} is {}convertible to an {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_primitive_float_convertible_from_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to an {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(unused_must_use)] fn benchmark_primitive_float_try_from_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(Float)", T::NAME), BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::try_from(x)))], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float>, { run_benchmark( &format!("{}::convertible_from(Float)", T::NAME), BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::convertible_from(&x)))], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_primitive_float_rounding_from_float + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float>, { run_benchmark( &format!("{}::rounding_from(Float, RoundingMode)", T::NAME), BenchmarkType::Single, float_rounding_mode_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(x, rm)| no_out!(T::rounding_from(x, rm)))], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/primitive_int_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError}; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_rounding_mode_pair_gen_var_4, float_rounding_mode_pair_gen_var_5, float_rounding_mode_pair_gen_var_18, float_rounding_mode_pair_gen_var_19, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_unsigned_rounding_from_float); register_unsigned_demos!(runner, demo_unsigned_rounding_from_float_debug); register_unsigned_demos!(runner, demo_unsigned_rounding_from_float_extreme); register_unsigned_demos!(runner, demo_unsigned_rounding_from_float_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_rounding_from_float_ref); register_unsigned_demos!(runner, demo_unsigned_rounding_from_float_ref_debug); register_unsigned_demos!(runner, demo_unsigned_try_from_float); register_unsigned_demos!(runner, demo_unsigned_try_from_float_debug); register_unsigned_demos!(runner, demo_unsigned_try_from_float_extreme); register_unsigned_demos!(runner, demo_unsigned_try_from_float_extreme_debug); register_unsigned_demos!(runner, demo_unsigned_try_from_float_ref); register_unsigned_demos!(runner, demo_unsigned_try_from_float_ref_debug); register_unsigned_demos!(runner, demo_unsigned_convertible_from_float); register_unsigned_demos!(runner, demo_unsigned_convertible_from_float_debug); register_unsigned_demos!(runner, demo_unsigned_convertible_from_float_extreme); register_unsigned_demos!(runner, demo_unsigned_convertible_from_float_extreme_debug); register_signed_demos!(runner, demo_signed_rounding_from_float); register_signed_demos!(runner, demo_signed_rounding_from_float_debug); register_signed_demos!(runner, demo_signed_rounding_from_float_ref); register_signed_demos!(runner, demo_signed_rounding_from_float_ref_debug); register_signed_demos!(runner, demo_signed_rounding_from_float_extreme); register_signed_demos!(runner, demo_signed_rounding_from_float_extreme_debug); register_signed_demos!(runner, demo_signed_try_from_float); register_signed_demos!(runner, demo_signed_try_from_float_debug); register_signed_demos!(runner, demo_signed_try_from_float_extreme); register_signed_demos!(runner, demo_signed_try_from_float_extreme_debug); register_signed_demos!(runner, demo_signed_try_from_float_ref); register_signed_demos!(runner, demo_signed_try_from_float_ref_debug); register_signed_demos!(runner, demo_signed_convertible_from_float); register_signed_demos!(runner, demo_signed_convertible_from_float_debug); register_signed_demos!(runner, demo_signed_convertible_from_float_extreme); register_signed_demos!(runner, demo_signed_convertible_from_float_extreme_debug); register_unsigned_benches!( runner, benchmark_unsigned_try_from_float_evaluation_strategy ); register_unsigned_benches!(runner, benchmark_unsigned_convertible_from_float); register_unsigned_benches!( runner, benchmark_unsigned_rounding_from_float_evaluation_strategy ); register_signed_benches!(runner, benchmark_signed_try_from_float_evaluation_strategy); register_signed_benches!(runner, benchmark_signed_convertible_from_float); register_signed_benches!( runner, benchmark_signed_rounding_from_float_evaluation_strategy ); } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, x.clone(), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({:#x}, {}) = {:?}", T::NAME, ComparableFloat(x.clone()), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float_extreme>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_18::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, x.clone(), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float_extreme_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_18::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({:#x}, {}) = {:?}", T::NAME, ComparableFloat(x.clone()), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}::rounding_from(&{}, {}) = {:?}", T::NAME, x, rm, T::rounding_from(&x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_rounding_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "{}::rounding_from(&{:#x}, {}) = {:?}", T::NAME, ComparableFloatRef(&x), rm, T::rounding_from(&x, rm) ); } } fn demo_unsigned_try_from_float< T: TryFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x) ); } } fn demo_unsigned_try_from_float_debug< T: TryFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x) ); } } fn demo_unsigned_try_from_float_extreme< T: TryFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x) ); } } fn demo_unsigned_try_from_float_extreme_debug< T: TryFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_try_from_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: TryFrom<&'a Float, Error = UnsignedFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!("{}::try_from({}) = {:?}", T::NAME, x, T::try_from(&x)); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_try_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: TryFrom<&'a Float, Error = UnsignedFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloatRef(&x), T::try_from(&x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_convertible_from_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to a {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_convertible_from_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_unsigned_convertible_from_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to a {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, x.clone(), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({:#x}, {}) = {:?}", T::NAME, ComparableFloat(x.clone()), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float_extreme>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, x.clone(), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float_extreme_debug>( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_19::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({:#x}, {}) = {:?}", T::NAME, ComparableFloat(x.clone()), rm, T::rounding_from(x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "{}::rounding_from(&{}, {}) = {:?}", T::NAME, x, rm, T::rounding_from(&x, rm) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_rounding_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, { for (x, rm) in float_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "{}::rounding_from(&{:#x}, {}) = {:?}", T::NAME, ComparableFloatRef(&x), rm, T::rounding_from(&x, rm) ); } } fn demo_signed_try_from_float + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x) ); } } fn demo_signed_try_from_float_debug< T: TryFrom + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x) ); } } fn demo_signed_try_from_float_extreme< T: TryFrom + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, x.clone(), T::try_from(x) ); } } fn demo_signed_try_from_float_extreme_debug< T: TryFrom + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in float_gen_var_12().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloat(x.clone()), T::try_from(x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_try_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> T: TryFrom<&'a Float, Error = SignedFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!("{}::try_from({}) = {:?}", T::NAME, x, T::try_from(&x)); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_try_from_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: TryFrom<&'a Float, Error = SignedFromFloatError>, { for x in float_gen().get(gm, config).take(limit) { println!( "{}::try_from({:#x}) = {:?}", T::NAME, ComparableFloatRef(&x), T::try_from(&x) ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to an {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_convertible_from_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to an {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_convertible_from_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{} is {}convertible to an {}", f, if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(clippy::type_repetition_in_bounds)] fn demo_signed_convertible_from_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> T: ConvertibleFrom<&'a Float>, { for f in float_gen_var_12().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to an {}", ComparableFloatRef(&f), if T::convertible_from(&f) { "" } else { "not " }, T::NAME ); } } #[allow(unused_must_use, clippy::type_repetition_in_bounds)] fn benchmark_unsigned_try_from_float_evaluation_strategy + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: TryFrom<&'a Float>, { run_benchmark( &format!("{}::try_from(Float)", T::NAME), BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ (&format!("{}::try_from(Float)", T::NAME), &mut |x| { no_out!(T::try_from(x)); }), (&format!("{}::try_from(&Float)", T::NAME), &mut |x| { no_out!(T::try_from(&x)); }), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_unsigned_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float>, { run_benchmark( &format!("{}::convertible_from(Float)", T::NAME), BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::convertible_from(&x)))], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_unsigned_rounding_from_float_evaluation_strategy< T: RoundingFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, Float: PartialOrd, { run_benchmark( &format!("{}::rounding_from(Float)", T::NAME), BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ( &format!("{}::rounding_from(Float)", T::NAME), &mut |(x, rm)| no_out!(T::rounding_from(x, rm)), ), ( &format!("{}::rounding_from(&Float)", T::NAME), &mut |(x, rm)| no_out!(T::rounding_from(&x, rm)), ), ], ); } #[allow(unused_must_use, clippy::type_repetition_in_bounds)] fn benchmark_signed_try_from_float_evaluation_strategy + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: TryFrom<&'a Float>, { run_benchmark( &format!("{}::try_from(Float)", T::NAME), BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ (&format!("{}::try_from(Float)", T::NAME), &mut |x| { no_out!(T::try_from(x)); }), (&format!("{}::try_from(&Float)", T::NAME), &mut |x| { no_out!(T::try_from(&x)); }), ], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_signed_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float>, { run_benchmark( &format!("{}::convertible_from(Float)", T::NAME), BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::convertible_from(&x)))], ); } #[allow(clippy::type_repetition_in_bounds)] fn benchmark_signed_rounding_from_float_evaluation_strategy< T: RoundingFrom + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, Float: PartialOrd, { run_benchmark( &format!("{}::rounding_from(Float)", T::NAME), BenchmarkType::EvaluationStrategy, float_rounding_mode_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ( &format!("{}::rounding_from(Float)", T::NAME), &mut |(x, rm)| no_out!(T::rounding_from(x, rm)), ), ( &format!("{}::rounding_from(&Float)", T::NAME), &mut |(x, rm)| no_out!(T::rounding_from(&x, rm)), ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/rational_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_2_float_complexity_bucketer, }; use malachite_float::test_util::generators::{float_gen, float_gen_rm}; use malachite_float::{ComparableFloat, ComparableFloatRef}; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_try_from_float); register_demo!(runner, demo_rational_try_from_float_debug); register_demo!(runner, demo_rational_try_from_float_ref); register_demo!(runner, demo_rational_try_from_float_ref_debug); register_demo!(runner, demo_rational_convertible_from_float); register_demo!(runner, demo_rational_convertible_from_float_debug); register_bench!( runner, benchmark_rational_try_from_float_evaluation_strategy ); register_bench!(runner, benchmark_rational_try_from_float_library_comparison); register_bench!(runner, benchmark_rational_convertible_from_float); } fn demo_rational_try_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Rational::try_from({}) = {:?}", f.clone(), Rational::try_from(f) ); } } fn demo_rational_try_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Rational::try_from({:#x}) = {:#x?}", ComparableFloat(f.clone()), Rational::try_from(f) ); } } fn demo_rational_try_from_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!("Rational::try_from(&{}) = {:?}", f, Rational::try_from(&f)); } } fn demo_rational_try_from_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "Rational::try_from(&{:#x}) = {:#x?}", ComparableFloatRef(&f), Rational::try_from(&f) ); } } fn demo_rational_convertible_from_float(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Rational", f, if Rational::convertible_from(&f) { "" } else { "not " }, ); } } fn demo_rational_convertible_from_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!( "{:#x} is {}convertible to a Rational", ComparableFloatRef(&f), if Rational::convertible_from(&f) { "" } else { "not " }, ); } } #[allow(unused_must_use)] fn benchmark_rational_try_from_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::try_from(Float)", BenchmarkType::EvaluationStrategy, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Rational::try_from(Float)", &mut |f| { no_out!(Rational::try_from(f)); }), ("Rational::try_from(&Float)", &mut |f| { no_out!(Rational::try_from(&f)); }), ], ); } #[allow(unused_must_use)] fn benchmark_rational_try_from_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::try_from(Float)", BenchmarkType::LibraryComparison, float_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_float_complexity_bucketer("x"), &mut [ ("Malachite", &mut |(_, f)| no_out!(Rational::try_from(f))), ("rug", &mut |(f, _)| no_out!(rug::Rational::try_from(&f))), ], ); } fn benchmark_rational_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::convertible_from(&Float)", BenchmarkType::Single, float_gen().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |f| { no_out!(Rational::convertible_from(&f)); })], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/raw_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::RawMantissaAndExponent; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::float_complexity_bucketer; use malachite_float::test_util::generators::{float_gen_var_3, float_gen_var_13}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_signed_pair_gen_var_4; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_raw_mantissa_and_exponent); register_demo!(runner, demo_float_raw_mantissa_and_exponent_debug); register_demo!(runner, demo_float_raw_mantissa_and_exponent_extreme); register_demo!(runner, demo_float_raw_mantissa_and_exponent_extreme_debug); register_demo!(runner, demo_float_raw_mantissa_and_exponent_ref); register_demo!(runner, demo_float_raw_mantissa_and_exponent_ref_debug); register_demo!(runner, demo_float_raw_mantissa); register_demo!(runner, demo_float_raw_mantissa_debug); register_demo!(runner, demo_float_raw_mantissa_extreme); register_demo!(runner, demo_float_raw_mantissa_extreme_debug); register_demo!(runner, demo_float_raw_mantissa_ref); register_demo!(runner, demo_float_raw_mantissa_ref_debug); register_demo!(runner, demo_float_raw_exponent); register_demo!(runner, demo_float_raw_exponent_debug); register_demo!(runner, demo_float_raw_exponent_extreme); register_demo!(runner, demo_float_raw_exponent_extreme_debug); register_demo!(runner, demo_float_raw_exponent_ref); register_demo!(runner, demo_float_raw_exponent_ref_debug); register_demo!(runner, demo_float_from_raw_mantissa_and_exponent); register_demo!(runner, demo_float_from_raw_mantissa_and_exponent_debug); register_demo!(runner, demo_float_from_raw_mantissa_and_exponent_ref); register_demo!(runner, demo_float_from_raw_mantissa_and_exponent_ref_debug); register_bench!( runner, benchmark_float_raw_mantissa_and_exponent_evaluation_strategy ); register_bench!(runner, benchmark_float_raw_mantissa_evaluation_strategy); register_bench!(runner, benchmark_float_raw_exponent_evaluation_strategy); register_bench!( runner, benchmark_float_from_raw_mantissa_and_exponent_evaluation_strategy ); } fn demo_float_raw_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.raw_mantissa_and_exponent() = {:?}", n.clone(), n.raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa_and_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.raw_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), n.raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa_and_exponent_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.raw_mantissa_and_exponent() = {:?}", n.clone(), n.raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa_and_exponent_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.raw_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), n.raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa_and_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{}).raw_mantissa_and_exponent() = {:?}", n, (&n).raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa_and_exponent_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).raw_mantissa_and_exponent() = {:?}", ComparableFloatRef(&n), (&n).raw_mantissa_and_exponent() ); } } fn demo_float_raw_mantissa(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("{}.raw_mantissa() = {}", n.clone(), n.raw_mantissa()); } } fn demo_float_raw_mantissa_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.raw_mantissa() = {:#x}", ComparableFloat(n.clone()), n.raw_mantissa() ); } } fn demo_float_raw_mantissa_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!("{}.raw_mantissa() = {}", n.clone(), n.raw_mantissa()); } } fn demo_float_raw_mantissa_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.raw_mantissa() = {:#x}", ComparableFloat(n.clone()), n.raw_mantissa() ); } } fn demo_float_raw_mantissa_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("(&{}).raw_mantissa() = {}", n, (&n).raw_mantissa()); } } fn demo_float_raw_mantissa_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).raw_mantissa() = {:#x}", ComparableFloatRef(&n), (&n).raw_mantissa() ); } } fn demo_float_raw_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("{}.raw_exponent() = {}", n.clone(), n.raw_exponent()); } } fn demo_float_raw_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.raw_exponent() = {}", ComparableFloat(n.clone()), n.raw_exponent() ); } } fn demo_float_raw_exponent_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!("{}.raw_exponent() = {}", n.clone(), n.raw_exponent()); } } fn demo_float_raw_exponent_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.raw_exponent() = {}", ComparableFloat(n.clone()), n.raw_exponent() ); } } fn demo_float_raw_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!("{}.raw_exponent() = {}", n, (&n).raw_exponent()); } } fn demo_float_raw_exponent_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.raw_exponent() = {}", ComparableFloatRef(&n), (&n).raw_exponent() ); } } fn demo_float_from_raw_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in natural_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let n = >::from_raw_mantissa_and_exponent( mantissa.clone(), exponent, ); println!("Float::from_raw_mantissa_and_exponent({mantissa}, {exponent}) = {n}"); } } fn demo_float_from_raw_mantissa_and_exponent_debug(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in natural_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let n = >::from_raw_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_raw_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n) ); } } fn demo_float_from_raw_mantissa_and_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in natural_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let n = <&Float as RawMantissaAndExponent>::from_raw_mantissa_and_exponent( mantissa.clone(), exponent, ); println!("Float::from_raw_mantissa_and_exponent({mantissa}, {exponent}) = {n}"); } } fn demo_float_from_raw_mantissa_and_exponent_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in natural_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { let n = <&Float as RawMantissaAndExponent>::from_raw_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_raw_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n) ); } } fn benchmark_float_raw_mantissa_and_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.raw_mantissa_and_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.raw_mantissa_and_exponent()", &mut |x| { no_out!(x.raw_mantissa_and_exponent()); }), ("(&Float).raw_mantissa_and_exponent()", &mut |x| { no_out!((&x).raw_mantissa_and_exponent()); }), ], ); } fn benchmark_float_raw_mantissa_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.raw_mantissa()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.raw_mantissa()", &mut |x| no_out!(x.raw_mantissa())), ("(&Float).raw_mantissa()", &mut |x| { no_out!((&x).raw_mantissa()); }), ], ); } fn benchmark_float_raw_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.raw_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.raw_exponent()", &mut |x| no_out!(x.raw_exponent())), ("(&Float).raw_exponent()", &mut |x| { no_out!((&x).raw_exponent()); }), ], ); } fn benchmark_float_from_raw_mantissa_and_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_raw_mantissa_and_exponent(Float, i32)", BenchmarkType::EvaluationStrategy, natural_signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ( "Float::from_raw_mantissa_and_exponent(Float, i32)", &mut |(mantissa, exponent)| { no_out!(>::from_raw_mantissa_and_exponent( mantissa, exponent )); }, ), ( "(&Float)::from_raw_mantissa_and_exponent(Float, i32)", &mut |(mantissa, exponent)| { no_out!(<&Float as RawMantissaAndExponent::< Natural, i32, Float, >>::from_raw_mantissa_and_exponent( mantissa, exponent )); }, ), ], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_1_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_signed_pair_gen_var_3; use malachite_base::test_util::runner::Runner; use malachite_float::test_util::bench::bucketers::{ float_complexity_bucketer, pair_1_float_complexity_bucketer, }; use malachite_float::test_util::generators::{ float_gen_var_3, float_gen_var_13, float_rounding_mode_pair_gen, float_rounding_mode_pair_gen_var_21, float_signed_pair_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_round); register_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_round_debug); register_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_round_extreme); register_primitive_float_demos!(runner, demo_sci_mantissa_and_exponent_round_extreme_debug); register_demo!(runner, demo_float_sci_mantissa_and_exponent_float); register_demo!(runner, demo_float_sci_mantissa_and_exponent_float_debug); register_demo!(runner, demo_float_sci_mantissa_and_exponent_float_extreme); register_demo!( runner, demo_float_sci_mantissa_and_exponent_float_extreme_debug ); register_demo!(runner, demo_float_sci_mantissa_and_exponent_float_ref); register_demo!(runner, demo_float_sci_mantissa_and_exponent_float_ref_debug); register_demo!(runner, demo_float_sci_mantissa_float); register_demo!(runner, demo_float_sci_mantissa_float_debug); register_demo!(runner, demo_float_sci_mantissa_float_extreme); register_demo!(runner, demo_float_sci_mantissa_float_extreme_debug); register_demo!(runner, demo_float_sci_mantissa_float_ref); register_demo!(runner, demo_float_sci_mantissa_float_ref_debug); register_demo!(runner, demo_float_sci_exponent_float); register_demo!(runner, demo_float_sci_exponent_float_debug); register_demo!(runner, demo_float_sci_exponent_float_extreme); register_demo!(runner, demo_float_sci_exponent_float_extreme_debug); register_demo!(runner, demo_float_sci_exponent_float_ref); register_demo!(runner, demo_float_sci_exponent_float_ref_debug); register_demo!(runner, demo_float_from_sci_mantissa_and_exponent_float); register_demo!( runner, demo_float_from_sci_mantissa_and_exponent_float_debug ); register_demo!(runner, demo_float_from_sci_mantissa_and_exponent_float_ref); register_demo!( runner, demo_float_from_sci_mantissa_and_exponent_float_ref_debug ); register_primitive_float_demos!(runner, demo_float_sci_mantissa_and_exponent_primitive_float); register_primitive_float_demos!( runner, demo_float_sci_mantissa_and_exponent_primitive_float_debug ); register_primitive_float_demos!( runner, demo_float_sci_mantissa_and_exponent_primitive_float_extreme ); register_primitive_float_demos!( runner, demo_float_sci_mantissa_and_exponent_primitive_float_extreme_debug ); register_primitive_float_demos!(runner, demo_float_sci_mantissa_primitive_float); register_primitive_float_demos!(runner, demo_float_sci_mantissa_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_sci_mantissa_primitive_float_extreme); register_primitive_float_demos!( runner, demo_float_sci_mantissa_primitive_float_extreme_debug ); register_primitive_float_demos!(runner, demo_float_sci_exponent_primitive_float); register_primitive_float_demos!(runner, demo_float_sci_exponent_primitive_float_debug); register_primitive_float_demos!(runner, demo_float_sci_exponent_primitive_float_extreme); register_primitive_float_demos!( runner, demo_float_sci_exponent_primitive_float_extreme_debug ); register_primitive_float_demos!( runner, demo_float_from_sci_mantissa_and_exponent_primitive_float ); register_primitive_float_demos!( runner, demo_float_from_sci_mantissa_and_exponent_primitive_float_debug ); register_primitive_float_benches!(runner, benchmark_sci_mantissa_and_exponent_round); register_bench!( runner, benchmark_float_sci_mantissa_and_exponent_float_evaluation_strategy ); register_bench!( runner, benchmark_float_sci_mantissa_float_evaluation_strategy ); register_bench!( runner, benchmark_float_sci_exponent_float_evaluation_strategy ); register_bench!( runner, benchmark_float_from_sci_mantissa_and_exponent_float_evaluation_strategy ); register_primitive_float_benches!( runner, benchmark_float_sci_mantissa_and_exponent_primitive_float ); register_primitive_float_benches!(runner, benchmark_float_sci_mantissa_primitive_float); register_primitive_float_benches!(runner, benchmark_float_sci_exponent_primitive_float); register_primitive_float_benches!( runner, benchmark_float_from_sci_mantissa_and_exponent_primitive_float ); } fn demo_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in float_rounding_mode_pair_gen().get(gm, config).take(limit) { println!( "{}.sci_mantissa_and_exponent_round({}) = {:?}", n.clone(), rm, n.sci_mantissa_and_exponent_round::(rm) ); } } fn demo_sci_mantissa_and_exponent_round_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in float_rounding_mode_pair_gen().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa_and_exponent_round({}) = {:?}", ComparableFloat(n.clone()), rm, n.sci_mantissa_and_exponent_round::(rm) ); } } fn demo_sci_mantissa_and_exponent_round_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in float_rounding_mode_pair_gen_var_21() .get(gm, config) .take(limit) { println!( "{}.sci_mantissa_and_exponent_round({}) = {:?}", n.clone(), rm, n.sci_mantissa_and_exponent_round::(rm) ); } } fn demo_sci_mantissa_and_exponent_round_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in float_rounding_mode_pair_gen_var_21() .get(gm, config) .take(limit) { println!( "{:#x}.sci_mantissa_and_exponent_round({}) = {:?}", ComparableFloat(n.clone()), rm, n.sci_mantissa_and_exponent_round::(rm) ); } } fn demo_float_sci_mantissa_and_exponent_float(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_mantissa_and_exponent() = {:?}", n.clone(), SciMantissaAndExponent::::sci_mantissa_and_exponent(n) ); } } fn demo_float_sci_mantissa_and_exponent_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), SciMantissaAndExponent::::sci_mantissa_and_exponent(n) ); } } fn demo_float_sci_mantissa_and_exponent_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.sci_mantissa_and_exponent() = {:?}", n.clone(), SciMantissaAndExponent::::sci_mantissa_and_exponent(n) ); } } fn demo_float_sci_mantissa_and_exponent_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa_and_exponent() = {:?}", ComparableFloat(n.clone()), SciMantissaAndExponent::::sci_mantissa_and_exponent(n) ); } } fn demo_float_sci_mantissa_and_exponent_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{}).sci_mantissa_and_exponent() = {:?}", n, SciMantissaAndExponent::::sci_mantissa_and_exponent(&n) ); } } fn demo_float_sci_mantissa_and_exponent_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).sci_mantissa_and_exponent() = {:?}", ComparableFloatRef(&n), SciMantissaAndExponent::::sci_mantissa_and_exponent(&n) ); } } fn demo_float_sci_mantissa_float(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_mantissa() = {}", n.clone(), SciMantissaAndExponent::::sci_mantissa(n) ); } } fn demo_float_sci_mantissa_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa() = {:#x}", ComparableFloat(n.clone()), ComparableFloat(SciMantissaAndExponent::::sci_mantissa(n)) ); } } fn demo_float_sci_mantissa_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.sci_mantissa() = {}", n.clone(), SciMantissaAndExponent::::sci_mantissa(n) ); } } fn demo_float_sci_mantissa_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa() = {:#x}", ComparableFloat(n.clone()), ComparableFloat(SciMantissaAndExponent::::sci_mantissa(n)) ); } } fn demo_float_sci_mantissa_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{}).sci_mantissa() = {}", n, SciMantissaAndExponent::::sci_mantissa(&n) ); } } fn demo_float_sci_mantissa_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "(&{:#x}).sci_mantissa() = {:#x}", ComparableFloatRef(&n), ComparableFloat(SciMantissaAndExponent::::sci_mantissa(&n)) ); } } fn demo_float_sci_exponent_float(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_exponent() = {}", n.clone(), SciMantissaAndExponent::::sci_exponent(n) ); } } fn demo_float_sci_exponent_float_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_exponent() = {}", ComparableFloat(n.clone()), SciMantissaAndExponent::::sci_exponent(n) ); } } fn demo_float_sci_exponent_float_extreme(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.sci_exponent() = {}", n.clone(), SciMantissaAndExponent::::sci_exponent(n) ); } } fn demo_float_sci_exponent_float_extreme_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.sci_exponent() = {}", ComparableFloat(n.clone()), SciMantissaAndExponent::::sci_exponent(n) ); } } fn demo_float_sci_exponent_float_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_exponent() = {}", n, SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_sci_exponent_float_ref_debug(gm: GenMode, config: &GenConfig, limit: usize) { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_exponent() = {}", ComparableFloatRef(&n), SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_from_sci_mantissa_and_exponent_float(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in float_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n = >::from_sci_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_sci_mantissa_and_exponent({}, {}) = {}", mantissa, exponent, n.unwrap() ); } } fn demo_float_from_sci_mantissa_and_exponent_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in float_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n = >::from_sci_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_sci_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n.unwrap()) ); } } fn demo_float_from_sci_mantissa_and_exponent_float_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in float_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n = <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_sci_mantissa_and_exponent({}, {}) = {}", mantissa, exponent, n.unwrap() ); } } fn demo_float_from_sci_mantissa_and_exponent_float_ref_debug( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mantissa, exponent) in float_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n = <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( mantissa.clone(), exponent, ); println!( "Float::from_sci_mantissa_and_exponent({:#x}, {}) = {:#x}", mantissa, exponent, ComparableFloat(n.unwrap()) ); } } fn demo_float_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { let (m, e) = SciMantissaAndExponent::::sci_mantissa_and_exponent(&n); println!( "{}.sci_mantissa_and_exponent() = {:?}", n, (NiceFloat(m), e) ); } } fn demo_float_sci_mantissa_and_exponent_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { let (m, e) = SciMantissaAndExponent::::sci_mantissa_and_exponent(&n); println!( "{:#x}.sci_mantissa_and_exponent() = {:?}", ComparableFloatRef(&n), (NiceFloat(m), e) ); } } fn demo_float_sci_mantissa_and_exponent_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { let (m, e) = SciMantissaAndExponent::::sci_mantissa_and_exponent(&n); println!( "{}.sci_mantissa_and_exponent() = {:?}", n, (NiceFloat(m), e) ); } } fn demo_float_sci_mantissa_and_exponent_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { let (m, e) = SciMantissaAndExponent::::sci_mantissa_and_exponent(&n); println!( "{:#x}.sci_mantissa_and_exponent() = {:?}", ComparableFloatRef(&n), (NiceFloat(m), e) ); } } fn demo_float_sci_mantissa_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_mantissa() = {}", n, NiceFloat(SciMantissaAndExponent::::sci_mantissa(&n)) ); } } fn demo_float_sci_mantissa_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa() = {}", ComparableFloatRef(&n), NiceFloat(SciMantissaAndExponent::::sci_mantissa(&n)) ); } } fn demo_float_sci_mantissa_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.sci_mantissa() = {}", n, NiceFloat(SciMantissaAndExponent::::sci_mantissa(&n)) ); } } fn demo_float_sci_mantissa_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.sci_mantissa() = {}", ComparableFloatRef(&n), NiceFloat(SciMantissaAndExponent::::sci_mantissa(&n)) ); } } fn demo_float_sci_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{}.sci_exponent() = {:?}", n, SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_sci_exponent_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_3().get(gm, config).take(limit) { println!( "{:#x}.sci_exponent() = {:?}", ComparableFloatRef(&n), SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_sci_exponent_primitive_float_extreme( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{}.sci_exponent() = {:?}", n, SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_sci_exponent_primitive_float_extreme_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for n in float_gen_var_13().get(gm, config).take(limit) { println!( "{:#x}.sci_exponent() = {:?}", ComparableFloatRef(&n), SciMantissaAndExponent::::sci_exponent(&n) ); } } fn demo_float_from_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for (mantissa, exponent) in primitive_float_signed_pair_gen_var_3() .get(gm, config) .take(limit) { let exponent = i32::exact_from(exponent); let n = <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( mantissa, exponent, ); println!( "Float::from_sci_mantissa_and_exponent({}, {}) = {}", NiceFloat(mantissa), exponent, n.unwrap() ); } } fn demo_float_from_sci_mantissa_and_exponent_primitive_float_debug( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Float: SciMantissaAndExponent, { for (mantissa, exponent) in primitive_float_signed_pair_gen_var_3() .get(gm, config) .take(limit) { let exponent = i32::exact_from(exponent); let n = <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( mantissa, exponent, ); println!( "Float::from_sci_mantissa_and_exponent({}, {}) = {:#x}", NiceFloat(mantissa), exponent, ComparableFloat(n.unwrap()) ); } } fn benchmark_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sci_mantissa_and_exponent_round(RoundingMode)", BenchmarkType::Single, float_rounding_mode_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [("Malachite", &mut |(x, rm)| { no_out!(x.sci_mantissa_and_exponent_round::(rm)); })], ); } fn benchmark_float_sci_mantissa_and_exponent_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sci_mantissa_and_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.sci_mantissa_and_exponent()", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa_and_exponent(x)); }), ("(&Float).sci_mantissa_and_exponent()", &mut |x| { no_out!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&x) ); }), ], ); } fn benchmark_float_sci_mantissa_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sci_mantissa()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.sci_mantissa()", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa(x)); }), ("(&Float).sci_mantissa()", &mut |x| { no_out!(<&Float as SciMantissaAndExponent>::sci_mantissa(&x)); }), ], ); } fn benchmark_float_sci_exponent_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float.sci_exponent()", BenchmarkType::EvaluationStrategy, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [ ("Float.sci_exponent()", &mut |x| { no_out!(SciMantissaAndExponent::::sci_exponent(x)); }), ("(&Float).sci_exponent()", &mut |x| { no_out!(<&Float as SciMantissaAndExponent>::sci_exponent(&x)); }), ], ); } fn benchmark_float_from_sci_mantissa_and_exponent_float_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Float::from_sci_mantissa_and_exponent(Float, i32)", BenchmarkType::EvaluationStrategy, float_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_float_complexity_bucketer("x"), &mut [ ( "Float::from_sci_mantissa_and_exponent(Float, i32)", &mut |(mantissa, exponent)| { no_out!(>::from_sci_mantissa_and_exponent( mantissa, exponent )); }, ), ( "(&Float)::from_sci_mantissa_and_exponent(Float, i32)", &mut |(mantissa, exponent)| { no_out!(<&Float as SciMantissaAndExponent::< Float, i32, Float, >>::from_sci_mantissa_and_exponent( mantissa, exponent )); }, ), ], ); } fn benchmark_float_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Float: SciMantissaAndExponent, { run_benchmark( "Float.sci_mantissa_and_exponent()", BenchmarkType::Single, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa_and_exponent(&x)); })], ); } fn benchmark_float_sci_mantissa_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Float: SciMantissaAndExponent, { run_benchmark( "Float.sci_mantissa()", BenchmarkType::Single, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(SciMantissaAndExponent::::sci_mantissa(&x)); })], ); } fn benchmark_float_sci_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Float: SciMantissaAndExponent, { run_benchmark( "Float.sci_exponent()", BenchmarkType::Single, float_gen_var_3().get(gm, config), gm.name(), limit, file_name, &float_complexity_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(SciMantissaAndExponent::::sci_exponent(&x)); })], ); } fn benchmark_float_from_sci_mantissa_and_exponent_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Float: SciMantissaAndExponent, { run_benchmark( "Float::from_sci_mantissa_and_exponent(Float, i32)", BenchmarkType::Single, primitive_float_signed_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [( &format!("Float::from_sci_mantissa_and_exponent({}, i32)", T::NAME), &mut |(mantissa, exponent)| { let exponent = i32::exact_from(exponent); no_out!(<&Float as SciMantissaAndExponent::< T, i32, Float, >>::from_sci_mantissa_and_exponent( mantissa, exponent ) ); }, )], ); } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/string/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { to_string::register(runner); } mod to_string; ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_float::ComparableFloatRef; use malachite_float::test_util::generators::float_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_float_to_string); } fn demo_float_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for f in float_gen().get(gm, config).take(limit) { println!("to_string({:x}) = {}", ComparableFloatRef(&f), f); println!("{}", rug::Float::exact_from(&f)); } } ================================================ FILE: malachite-float/src/bin_util/demo_and_bench/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); basic::register(runner); comparison::register(runner); constants::register(runner); conversion::register(runner); } mod arithmetic; mod basic; mod comparison; mod constants; mod conversion; ================================================ FILE: malachite-float/src/comparison/cmp.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloat, ComparableFloatRef, Float}; use core::cmp::Ordering::{self, *}; impl PartialOrd for Float { /// Compares two [`Float`]s. /// /// This implementation follows the IEEE 754 standard. `NaN` is not comparable to anything, not /// even itself. Positive zero is equal to negative zero. [`Float`]s with different precisions /// are equal if they represent the same numeric value. /// /// For different comparison behavior that provides a total order, consider using /// [`ComparableFloat`] or [`ComparableFloatRef`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// assert_eq!(Float::NAN.partial_cmp(&Float::NAN), None); /// assert_eq!(Float::ZERO.partial_cmp(&Float::NEGATIVE_ZERO), Some(Equal)); /// assert_eq!(Float::ONE.partial_cmp(&Float::one_prec(100)), Some(Equal)); /// assert!(Float::INFINITY > Float::ONE); /// assert!(Float::NEGATIVE_INFINITY < Float::ONE); /// assert!(Float::ONE_HALF < Float::ONE); /// assert!(Float::ONE_HALF > Float::NEGATIVE_ONE); /// ``` fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { (float_nan!(), _) | (_, float_nan!()) => None, (float_infinity!(), float_infinity!()) | (float_negative_infinity!(), float_negative_infinity!()) | (float_either_zero!(), float_either_zero!()) => Some(Equal), (float_infinity!(), _) | (_, float_negative_infinity!()) => Some(Greater), (float_negative_infinity!(), _) | (_, float_infinity!()) => Some(Less), (Self(Finite { sign, .. }), float_either_zero!()) => { Some(if *sign { Greater } else { Less }) } (float_either_zero!(), Self(Finite { sign, .. })) => { Some(if *sign { Less } else { Greater }) } ( Self(Finite { sign: s_x, exponent: e_x, significand: x, .. }), Self(Finite { sign: s_y, exponent: e_y, significand: y, .. }), ) => Some(s_x.cmp(s_y).then_with(|| { let abs_cmp = e_x.cmp(e_y).then_with(|| x.cmp_normalized_no_shift(y)); if *s_x { abs_cmp } else { abs_cmp.reverse() } })), } } } impl<'a> Ord for ComparableFloatRef<'a> { /// Compares two [`ComparableFloatRef`]s. /// /// This implementation does not follow the IEEE 754 standard. This is how /// [`ComparableFloatRef`]s are ordered, least to greatest: /// - $-\infty$ /// - Negative nonzero finite floats /// - Negative zero /// - NaN /// - Positive zero /// - Positive nonzero finite floats /// - $\infty$ /// /// When comparing two finite floats with the same numeric value but different precisions, the /// one with greater precision is ordered to be further from zero. /// /// For different comparison behavior that follows the IEEE 754 standard, consider just using /// [`Float`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_float::{ComparableFloatRef, Float}; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// ComparableFloatRef(&Float::NAN).partial_cmp(&ComparableFloatRef(&Float::NAN)), /// Some(Equal) /// ); /// assert!(ComparableFloatRef(&Float::ZERO) > ComparableFloatRef(&Float::NEGATIVE_ZERO)); /// assert!(ComparableFloatRef(&Float::ONE) < ComparableFloatRef(&Float::one_prec(100))); /// assert!(ComparableFloatRef(&Float::INFINITY) > ComparableFloatRef(&Float::ONE)); /// assert!(ComparableFloatRef(&Float::NEGATIVE_INFINITY) < ComparableFloatRef(&Float::ONE)); /// assert!(ComparableFloatRef(&Float::ONE_HALF) < ComparableFloatRef(&Float::ONE)); /// assert!(ComparableFloatRef(&Float::ONE_HALF) > ComparableFloatRef(&Float::NEGATIVE_ONE)); /// ``` fn cmp(&self, other: &Self) -> Ordering { match (&self.0, &other.0) { (float_nan!(), float_nan!()) | (float_infinity!(), float_infinity!()) | (float_negative_infinity!(), float_negative_infinity!()) => Equal, (Float(Zero { sign: s_x }), Float(Zero { sign: s_y })) => s_x.cmp(s_y), (float_infinity!(), _) | (_, float_negative_infinity!()) => Greater, (float_negative_infinity!(), _) | (_, float_infinity!()) => Less, (Float(NaN | Zero { .. }), Float(Finite { sign, .. })) | (Float(NaN), Float(Zero { sign })) => { if *sign { Less } else { Greater } } (Float(Finite { sign, .. } | Zero { sign }), Float(NaN)) | (Float(Finite { sign, .. }), Float(Zero { .. })) => { if *sign { Greater } else { Less } } ( Float(Finite { sign: s_x, exponent: e_x, precision: p_x, significand: x, }), Float(Finite { sign: s_y, exponent: e_y, precision: p_y, significand: y, }), ) => s_x.cmp(s_y).then_with(|| { let abs_cmp = e_x .cmp(e_y) .then_with(|| x.cmp_normalized_no_shift(y)) .then_with(|| p_x.cmp(p_y)); if *s_x { abs_cmp } else { abs_cmp.reverse() } }), } } } impl PartialOrd for ComparableFloatRef<'_> { /// Compares two [`ComparableFloatRef`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &ComparableFloatRef) -> Option { Some(self.cmp(other)) } } impl Ord for ComparableFloat { /// Compares two [`ComparableFloat`]s. /// /// This implementation does not follow the IEEE 754 standard. This is how [`ComparableFloat`]s /// are ordered, least to greatest: /// - $-\infty$ /// - Negative nonzero finite floats /// - Negative zero /// - NaN /// - Positive zero /// - Positive nonzero finite floats /// - $\infty$ /// /// When comparing two finite floats with the same numeric value but different precisions, the /// one with greater precision is ordered to be further from zero. /// /// For different comparison behavior that follows the IEEE 754 standard, consider just using /// [`Float`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_float::{ComparableFloat, Float}; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// ComparableFloat(Float::NAN).partial_cmp(&ComparableFloat(Float::NAN)), /// Some(Equal) /// ); /// assert!(ComparableFloat(Float::ZERO) > ComparableFloat(Float::NEGATIVE_ZERO)); /// assert!(ComparableFloat(Float::ONE) < ComparableFloat(Float::one_prec(100))); /// assert!(ComparableFloat(Float::INFINITY) > ComparableFloat(Float::ONE)); /// assert!(ComparableFloat(Float::NEGATIVE_INFINITY) < ComparableFloat(Float::ONE)); /// assert!(ComparableFloat(Float::ONE_HALF) < ComparableFloat(Float::ONE)); /// assert!(ComparableFloat(Float::ONE_HALF) > ComparableFloat(Float::NEGATIVE_ONE)); /// ``` #[inline] fn cmp(&self, other: &Self) -> Ordering { self.as_ref().cmp(&other.as_ref()) } } #[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for ComparableFloat { /// Compares two [`ComparableFloat`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.as_ref().cmp(&other.as_ref())) } } ================================================ FILE: malachite-float/src/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloat, ComparableFloatRef, Float}; use core::cmp::Ordering::{self, *}; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; impl PartialOrdAbs for Float { /// Compares the absolute values of two [`Float`]s. /// /// This implementation follows the IEEE 754 standard. `NaN` is not comparable to anything, not /// even itself. [`Float`]s with different precisions are equal if they represent the same /// numeric value. /// /// For different comparison behavior that provides a total order, consider using /// [`ComparableFloat`] or [`ComparableFloatRef`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// assert_eq!(Float::NAN.partial_cmp_abs(&Float::NAN), None); /// assert_eq!( /// Float::ZERO.partial_cmp_abs(&Float::NEGATIVE_ZERO), /// Some(Equal) /// ); /// assert_eq!( /// Float::ONE.partial_cmp_abs(&Float::one_prec(100)), /// Some(Equal) /// ); /// assert!(Float::INFINITY.gt_abs(&Float::ONE)); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&Float::ONE)); /// assert!(Float::ONE_HALF.lt_abs(&Float::ONE)); /// assert!(Float::ONE_HALF.lt_abs(&Float::NEGATIVE_ONE)); /// ``` fn partial_cmp_abs(&self, other: &Self) -> Option { match (self, other) { (float_nan!(), _) | (_, float_nan!()) => None, (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => Some(Equal), (float_either_infinity!(), _) | (_, float_either_zero!()) => Some(Greater), (_, float_either_infinity!()) | (float_either_zero!(), _) => Some(Less), ( Self(Finite { exponent: e_x, significand: x, .. }), Self(Finite { exponent: e_y, significand: y, .. }), ) => Some(e_x.cmp(e_y).then_with(|| x.cmp_normalized_no_shift(y))), } } } impl<'a> OrdAbs for ComparableFloatRef<'a> { /// Compares the absolute values of two [`ComparableFloatRef`]s. /// /// This implementation does not follow the IEEE 754 standard. This is how /// [`ComparableFloatRef`]s are ordered by absolute value, from least to greatest: /// - NaN /// - Positive and negative zero /// - Nonzero finite floats /// - $\infty$ and $-\infty$ /// /// For different comparison behavior that follows the IEEE 754 standard, consider just using /// [`Float`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::{ComparableFloatRef, Float}; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// ComparableFloatRef(&Float::NAN).partial_cmp_abs(&ComparableFloatRef(&Float::NAN)), /// Some(Equal) /// ); /// assert_eq!( /// ComparableFloatRef(&Float::ZERO) /// .partial_cmp_abs(&ComparableFloatRef(&Float::NEGATIVE_ZERO)), /// Some(Equal) /// ); /// assert!(ComparableFloatRef(&Float::ONE).lt_abs(&ComparableFloatRef(&Float::one_prec(100)))); /// assert!(ComparableFloatRef(&Float::INFINITY).gt_abs(&ComparableFloatRef(&Float::ONE))); /// assert!( /// ComparableFloatRef(&Float::NEGATIVE_INFINITY).gt_abs(&ComparableFloatRef(&Float::ONE)) /// ); /// assert!(ComparableFloatRef(&Float::ONE_HALF).lt_abs(&ComparableFloatRef(&Float::ONE))); /// assert!( /// ComparableFloatRef(&Float::ONE_HALF).lt_abs(&ComparableFloatRef(&Float::NEGATIVE_ONE)) /// ); /// ``` #[allow(clippy::match_same_arms)] fn cmp_abs(&self, other: &Self) -> Ordering { match (&self.0, &other.0) { (float_nan!(), float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => Equal, (float_either_infinity!(), _) | (_, float_nan!()) => Greater, (_, float_either_infinity!()) | (float_nan!(), _) => Less, (float_either_zero!(), _) => Less, (_, float_either_zero!()) => Greater, ( Float(Finite { exponent: e_x, precision: p_x, significand: x, .. }), Float(Finite { exponent: e_y, precision: p_y, significand: y, .. }), ) => e_x .cmp(e_y) .then_with(|| x.cmp_normalized_no_shift(y)) .then_with(|| p_x.cmp(p_y)), } } } impl PartialOrdAbs for ComparableFloatRef<'_> { /// Compares the absolute values of two [`ComparableFloatRef`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp_abs(&self, other: &ComparableFloatRef) -> Option { Some(self.cmp_abs(other)) } } impl OrdAbs for ComparableFloat { /// Compares the absolute values of two [`ComparableFloat`]s. /// /// This implementation does not follow the IEEE 754 standard. This is how [`ComparableFloat`]s /// are ordered by absolute value, from least to greatest: /// - NaN /// - Positive and negative zero /// - Nonzero finite floats /// - $\infty$ and $-\infty$ /// /// For different comparison behavior that follows the IEEE 754 standard, consider just using /// [`Float`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{ /// Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Zero, /// }; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::{ComparableFloat, Float}; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// ComparableFloat(Float::NAN).partial_cmp_abs(&ComparableFloat(Float::NAN)), /// Some(Equal) /// ); /// assert_eq!( /// ComparableFloat(Float::ZERO).partial_cmp_abs(&ComparableFloat(Float::NEGATIVE_ZERO)), /// Some(Equal) /// ); /// assert!(ComparableFloat(Float::ONE).lt_abs(&ComparableFloat(Float::one_prec(100)))); /// assert!(ComparableFloat(Float::INFINITY).gt_abs(&ComparableFloat(Float::ONE))); /// assert!(ComparableFloat(Float::NEGATIVE_INFINITY).gt_abs(&ComparableFloat(Float::ONE))); /// assert!(ComparableFloat(Float::ONE_HALF).lt_abs(&ComparableFloat(Float::ONE))); /// assert!(ComparableFloat(Float::ONE_HALF).lt_abs(&ComparableFloat(Float::NEGATIVE_ONE))); /// ``` #[inline] fn cmp_abs(&self, other: &Self) -> Ordering { self.as_ref().cmp_abs(&other.as_ref()) } } impl PartialOrdAbs for ComparableFloat { /// Compares the absolute values of two [`ComparableFloatRef`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp_abs(&self, other: &Self) -> Option { Some(self.as_ref().cmp_abs(&other.as_ref())) } } ================================================ FILE: malachite-float/src/comparison/eq.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloat, ComparableFloatRef, Float}; use core::cmp::Ordering::*; impl PartialEq for Float { /// Compares two [`Float`]s for equality. /// /// This implementation follows the IEEE 754 standard. `NaN` is not equal to anything, not even /// itself. Positive zero is equal to negative zero. [`Float`]s with different precisions are /// equal if they represent the same numeric value. /// /// For different equality behavior, consider using [`ComparableFloat`] or /// [`ComparableFloatRef`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::Float; /// /// assert_ne!(Float::NAN, Float::NAN); /// assert_eq!(Float::ZERO, Float::ZERO); /// assert_eq!(Float::NEGATIVE_ZERO, Float::NEGATIVE_ZERO); /// assert_eq!(Float::ZERO, Float::NEGATIVE_ZERO); /// /// assert_eq!(Float::ONE, Float::ONE); /// assert_ne!(Float::ONE, Float::TWO); /// assert_eq!(Float::ONE, Float::one_prec(100)); /// ``` fn eq(&self, other: &Self) -> bool { match (self, other) { (Self(Infinity { sign: s_x }), Self(Infinity { sign: s_y })) => s_x == s_y, (float_either_zero!(), float_either_zero!()) => true, ( Self(Finite { sign: s_x, exponent: e_x, significand: x, .. }), Self(Finite { sign: s_y, exponent: e_y, significand: y, .. }), ) => e_x == e_y && s_x == s_y && x.cmp_normalized_no_shift(y) == Equal, _ => false, } } } impl PartialEq for ComparableFloat { /// Compares two [`ComparableFloat`]s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// [`ComparableFloat`], `NaN`s are equal to themselves. There is a single, unique `NaN`; /// there's no concept of signalling `NaN`s. Positive and negative zero are two distinct values, /// not equal to each other. [`ComparableFloat`]s with different precisions are unequal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!(ComparableFloat(Float::NAN), ComparableFloat(Float::NAN)); /// assert_eq!(ComparableFloat(Float::ZERO), ComparableFloat(Float::ZERO)); /// assert_eq!( /// ComparableFloat(Float::NEGATIVE_ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// assert_ne!( /// ComparableFloat(Float::ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// /// assert_eq!(ComparableFloat(Float::ONE), ComparableFloat(Float::ONE)); /// assert_ne!(ComparableFloat(Float::ONE), ComparableFloat(Float::TWO)); /// assert_ne!( /// ComparableFloat(Float::ONE), /// ComparableFloat(Float::one_prec(100)) /// ); /// ``` #[inline] fn eq(&self, other: &Self) -> bool { self.as_ref() == other.as_ref() } } impl Eq for ComparableFloat {} impl<'a> PartialEq> for ComparableFloatRef<'_> { /// Compares two [`ComparableFloatRef`]s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// [`ComparableFloatRef`], `NaN`s are equal to themselves. There is a single, unique `NaN`; /// there's no concept of signalling `NaN`s. Positive and negative zero are two distinct values, /// not equal to each other. [`ComparableFloatRef`]s with different precisions are unequal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::{ComparableFloatRef, Float}; /// /// assert_eq!( /// ComparableFloatRef(&Float::NAN), /// ComparableFloatRef(&Float::NAN) /// ); /// assert_eq!( /// ComparableFloatRef(&Float::ZERO), /// ComparableFloatRef(&Float::ZERO) /// ); /// assert_eq!( /// ComparableFloatRef(&Float::NEGATIVE_ZERO), /// ComparableFloatRef(&Float::NEGATIVE_ZERO) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ZERO), /// ComparableFloatRef(&Float::NEGATIVE_ZERO) /// ); /// /// assert_eq!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::ONE) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::TWO) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::one_prec(100)) /// ); /// ``` fn eq(&self, other: &ComparableFloatRef<'a>) -> bool { match (&self.0, &other.0) { (float_nan!(), float_nan!()) => true, (Float(Infinity { sign: s_x }), Float(Infinity { sign: s_y })) | (Float(Zero { sign: s_x }), Float(Zero { sign: s_y })) => s_x == s_y, ( Float(Finite { sign: s_x, exponent: e_x, precision: p_x, significand: x, }), Float(Finite { sign: s_y, exponent: e_y, precision: p_y, significand: y, }), ) => s_x == s_y && e_x == e_y && p_x == p_y && x == y, _ => false, } } } impl Eq for ComparableFloatRef<'_> {} ================================================ FILE: malachite-float/src/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloat, ComparableFloatRef, Float}; use core::cmp::Ordering::*; use malachite_base::num::comparison::traits::EqAbs; impl EqAbs for Float { /// Compares the absolute values of two [`Float`]s for equality. /// /// This implementation follows the IEEE 754 standard. `NaN` is not equal to anything, not even /// itself. Positive zero is equal to negative zero. [`Float`]s with different precisions are /// equal if they represent the same numeric value. /// /// For different equality behavior, consider using [`ComparableFloat`] or /// [`ComparableFloatRef`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::Float; /// /// assert_ne!(Float::NAN, Float::NAN); /// assert_eq!(Float::ZERO, Float::ZERO); /// assert_eq!(Float::NEGATIVE_ZERO, Float::NEGATIVE_ZERO); /// assert_eq!(Float::ZERO, Float::NEGATIVE_ZERO); /// /// assert_eq!(Float::ONE, Float::ONE); /// assert_ne!(Float::ONE, Float::TWO); /// assert_eq!(Float::ONE, Float::one_prec(100)); /// ``` fn eq_abs(&self, other: &Self) -> bool { match (self, other) { (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => true, ( Self(Finite { exponent: e_x, significand: x, .. }), Self(Finite { exponent: e_y, significand: y, .. }), ) => e_x == e_y && x.cmp_normalized_no_shift(y) == Equal, _ => false, } } } impl EqAbs for ComparableFloat { /// Compares the absolute values of two [`ComparableFloat`]s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// [`ComparableFloat`], `NaN`s are equal to themselves. There is a single, unique `NaN`; /// there's no concept of signalling `NaN`s. [`ComparableFloat`]s with different precisions are /// unequal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::{ComparableFloat, Float}; /// /// assert_eq!(ComparableFloat(Float::NAN), ComparableFloat(Float::NAN)); /// assert_eq!(ComparableFloat(Float::ZERO), ComparableFloat(Float::ZERO)); /// assert_eq!( /// ComparableFloat(Float::NEGATIVE_ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// assert_ne!( /// ComparableFloat(Float::ZERO), /// ComparableFloat(Float::NEGATIVE_ZERO) /// ); /// /// assert_eq!(ComparableFloat(Float::ONE), ComparableFloat(Float::ONE)); /// assert_ne!(ComparableFloat(Float::ONE), ComparableFloat(Float::TWO)); /// assert_ne!( /// ComparableFloat(Float::ONE), /// ComparableFloat(Float::one_prec(100)) /// ); /// ``` #[inline] fn eq_abs(&self, other: &Self) -> bool { self.as_ref().eq_abs(&other.as_ref()) } } impl<'a> EqAbs> for ComparableFloatRef<'_> { /// Compares the absolute values of two [`ComparableFloatRef`]s for equality. /// /// This implementation ignores the IEEE 754 standard in favor of an equality operation that /// respects the expected properties of symmetry, reflexivity, and transitivity. Using /// [`ComparableFloatRef`], `NaN`s are equal to themselves. There is a single, unique `NaN`; /// there's no concept of signalling `NaN`s. [`ComparableFloatRef`]s with different precisions /// are unequal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NaN, NegativeZero, One, Two, Zero}; /// use malachite_float::{ComparableFloatRef, Float}; /// /// assert_eq!( /// ComparableFloatRef(&Float::NAN), /// ComparableFloatRef(&Float::NAN) /// ); /// assert_eq!( /// ComparableFloatRef(&Float::ZERO), /// ComparableFloatRef(&Float::ZERO) /// ); /// assert_eq!( /// ComparableFloatRef(&Float::NEGATIVE_ZERO), /// ComparableFloatRef(&Float::NEGATIVE_ZERO) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ZERO), /// ComparableFloatRef(&Float::NEGATIVE_ZERO) /// ); /// /// assert_eq!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::ONE) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::TWO) /// ); /// assert_ne!( /// ComparableFloatRef(&Float::ONE), /// ComparableFloatRef(&Float::one_prec(100)) /// ); /// ``` fn eq_abs(&self, other: &ComparableFloatRef<'a>) -> bool { match (&self.0, &other.0) { (float_nan!(), float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => true, ( Float(Finite { exponent: e_x, precision: p_x, significand: x, .. }), Float(Finite { exponent: e_y, precision: p_y, significand: y, .. }), ) => e_x == e_y && p_x == p_y && x == y, _ => false, } } } ================================================ FILE: malachite-float/src/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl EqAbs for Float { /// Determines whether the absolute value of a [`Float`] is equal to the absolute value of an /// [`Integer`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Integer`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Integer`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Float::from(123).eq_abs(&Integer::from(123))); /// assert!(Float::from(-123).eq_abs(&Integer::from(-123))); /// assert!(Float::ONE_HALF.ne_abs(&Integer::ONE)); /// ``` fn eq_abs(&self, other: &Integer) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { exponent, significand, .. }) => { *other != 0u32 && *exponent >= 0 && other.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(other.unsigned_abs_ref()) == Equal } _ => false, } } } impl EqAbs for Integer { /// Determines whether the absolute value of an [`Integer`] is equal to the absolute value of a /// [`Float`]. /// /// No [`Integer`] is equal to $\infty$, $-\infty$, or NaN. The [`Integer`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(123).eq_abs(&Float::from(123))); /// assert!(Integer::from(-123).eq_abs(&Float::from(-123))); /// assert!(Integer::ONE.ne_abs(&Float::ONE_HALF)); /// ``` #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } ================================================ FILE: malachite-float/src/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl EqAbs for Float { /// Determines whether the absolute value of a [`Float`] is equal to a [`Natural`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Natural`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Float::from(123).eq_abs(&Natural::from(123u32))); /// assert!(Float::ONE_HALF.ne_abs(&Natural::ONE)); /// ``` fn eq_abs(&self, other: &Natural) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { exponent, significand, .. }) => { *other != 0u32 && *exponent >= 0 && other.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(other) == Equal } _ => false, } } } impl EqAbs for Natural { /// Determines whether a [`Natural`] is equal to the absolute value of a [`Float`]. /// /// No [`Natural`] is equal to $\infty$, $-\infty$, or NaN. The [`Natural`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32).eq_abs(&Float::from(123))); /// assert!(Natural::ONE.ne_abs(&Float::ONE_HALF)); /// ``` #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } ================================================ FILE: malachite-float/src/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::*; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::natural::Natural; fn float_eq_abs_primitive_float(x: &Float, y: &T) -> bool { match x { float_nan!() => false, float_either_infinity!() => *y == T::INFINITY || *y == T::NEGATIVE_INFINITY, float_either_zero!() => *y == T::ZERO, Float(Finite { exponent, significand, .. }) => { y.is_finite() && *y != T::ZERO && i64::from(*exponent - 1) == y.sci_exponent() && significand.cmp_normalized(&Natural::from(y.integer_mantissa())) == Equal } } } macro_rules! impl_eq_abs_primitive_float { ($t: ident) => { impl EqAbs<$t> for Float { /// Determines whether the absolute value of a [`Float`] is equal to the absolute value /// of a primitive float. /// /// The [`Float`] $\infty$ is equal to the primitive float $\infty$, and the [`Float`] /// $-\infty$ is equal to the primitive float $-\infty$. The [`Float`] NaN is not equal /// to anything, not even the primitive float NaN. Every [`Float`] zero is equal to /// every primitive float zero, regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { float_eq_abs_primitive_float(self, other) } } impl EqAbs for $t { /// Determines whether a primitive float is equal to a [`Float`]. /// /// The primitive float $\infty$ is equal to the [`Float`] $\infty$, and the primitive /// float $-\infty$ is equal to the [`Float`] $-\infty$. The primitive float NaN is not /// equal to anything, not even the [`Float`] NaN. Every primitive float zero is equal /// to every [`Float`] zero, regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } }; } apply_to_primitive_floats!(impl_eq_abs_primitive_float); ================================================ FILE: malachite-float/src/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::natural::Natural; fn float_eq_abs_unsigned(x: &Float, y: &T) -> bool where Natural: From, { match x { float_either_zero!() => *y == T::ZERO, Float(Finite { exponent, significand, .. }) => { *y != T::ZERO && *exponent >= 0 && y.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(&Natural::from(*y)) == Equal } _ => false, } } macro_rules! impl_eq_abs_unsigned { ($t: ident) => { impl EqAbs<$t> for Float { /// Determines whether the absolute value of a [`Float`] is equal to an unsigned /// primitive integer. /// /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq_abs(&self, other: &$t) -> bool { float_eq_abs_unsigned(self, other) } } impl EqAbs for $t { /// Determines whether an unsigned primitive integer is equal to the absolute value of a /// [`Float`]. /// /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is /// equal to both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } }; } apply_to_unsigneds!(impl_eq_abs_unsigned); fn float_eq_abs_signed(x: &Float, y: &T) -> bool where Natural: From<::Output>, { match x { float_either_zero!() => *y == T::ZERO, Float(Finite { exponent, significand, .. }) => { *y != T::ZERO && *exponent >= 0 && y.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(&Natural::from(y.unsigned_abs())) == Equal } _ => false, } } macro_rules! impl_eq_abs_signed { ($t: ident) => { impl EqAbs<$t> for Float { /// Determines whether the absolute value of a [`Float`] is equal to the absolute value /// of a signed primitive integer. /// /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::eq_abs#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { float_eq_abs_signed(self, other) } } impl EqAbs for $t { /// Determines whether the absolute value of a signed primitive integer is equal to the /// absolute value of a [`Float`]. /// /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is /// equal to both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::eq_abs#eq_abs). #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } }; } apply_to_signeds!(impl_eq_abs_signed); ================================================ FILE: malachite-float/src/comparison/eq_abs_rational.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::CheckedLogBase2; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_q::Rational; impl EqAbs for Float { /// Determines whether the absolute value of a [`Float`] is equal to the absolute value of a /// [`Rational`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Rational`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Rational`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Float::from(123).eq_abs(&Rational::from(123))); /// assert!(Float::from(-123).eq_abs(&Rational::from(123))); /// assert!(Float::ONE_HALF.eq_abs(&Rational::ONE_HALF)); /// assert!(Float::from(1.0f64 / 3.0).ne_abs(&Rational::from_unsigneds(1u8, 3))); /// ``` #[inline] fn eq_abs(&self, other: &Rational) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { exponent, significand, .. }) => { *other != 0 && if let Some(log_d) = other.denominator_ref().checked_log_base_2() { let n = other.numerator_ref(); i64::from(*exponent) == i64::exact_from(n.significant_bits()) - i64::exact_from(log_d) && significand.cmp_normalized(n) == Equal } else { false } } _ => false, } } } impl EqAbs for Rational { /// Determines whether the absolute value of a [`Rational`] is equal to the absolute value of a /// [`Float`]. /// /// No [`Rational`] is equal to $\infty$, $-\infty$, or NaN. The [`Rational`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Rational::from(123).eq_abs(&Float::from(123))); /// assert!(Rational::from(-123).eq_abs(&Float::from(123))); /// assert!(Rational::ONE_HALF.eq_abs(&Float::ONE_HALF)); /// assert!(Rational::from_unsigneds(1u8, 3).ne_abs(&Float::from(1.0f64 / 3.0))); /// ``` #[inline] fn eq_abs(&self, other: &Float) -> bool { other.eq_abs(self) } } ================================================ FILE: malachite-float/src/comparison/hash.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloat, ComparableFloatRef, Float}; use core::hash::{Hash, Hasher}; impl Hash for ComparableFloat { /// Computes a hash of a `ComparableFloat`. /// /// The hash is compatible with `ComparableFloat` equality: all `NaN`s hash to the same value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. #[inline] fn hash(&self, state: &mut H) { self.as_ref().hash(state); } } impl Hash for ComparableFloatRef<'_> { /// Computes a hash of a `ComparableFloatRef`. /// /// The hash is compatible with `ComparableFloatRef` equality: all `NaN`s hash to the same /// value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. fn hash(&self, state: &mut H) { match self.0 { float_nan!() => "NaN".hash(state), Float(Infinity { sign }) => { if *sign { "Infinity".hash(state); } else { "-Infinity".hash(state); } } Float(Zero { sign }) => { if *sign { "0.0".hash(state); } else { "-0.0".hash(state); } } Float(Finite { sign, exponent, precision, significand, }) => { sign.hash(state); exponent.hash(state); precision.hash(state); significand.hash(state); } } } } ================================================ FILE: malachite-float/src/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// Comparison of [`Float`](crate::Float)s. pub mod cmp; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// and [`OrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) (traits for comparing /// the absolute values of numbers by order) for [`Float`](crate::Float)s. pub mod cmp_abs; /// Equality of [`Float`](crate::Float)s. pub mod eq; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers by equality) for [`Float`](crate::Float)s. pub mod eq_abs; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers for equality) for [`Float`](crate::Float)s and /// [`Integer`](malachite_nz::integer::Integer)s. pub mod eq_abs_integer; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers for equality) for [`Float`](crate::Float)s and /// [`Natural`](malachite_nz::natural::Natural)s. pub mod eq_abs_natural; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers for equality) for [`Float`](crate::Float)s and /// primitive floats. /// /// # eq_abs /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// /// assert!(Float::from(123).eq_abs(&123.0)); /// assert!(Float::ONE_HALF.eq_abs(&0.5)); /// assert!(Float::ONE_HALF.eq_abs(&-0.5)); /// assert!(Float::ONE_HALF.ne_abs(&0.4)); /// /// assert!(123.0.eq_abs(&Float::from(123))); /// assert!(0.5.eq_abs(&Float::ONE_HALF)); /// assert!((-0.5).eq_abs(&Float::ONE_HALF)); /// assert!(0.4.ne_abs(&Float::ONE_HALF)); /// ``` pub mod eq_abs_primitive_float; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers for equality) for [`Float`](crate::Float)s and /// primitive integers. /// /// # eq_abs /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_float::Float; /// /// assert!(Float::from(123).eq_abs(&123u64)); /// assert!(Float::ONE_HALF.ne_abs(&1u64)); /// /// assert!(Float::from(123).eq_abs(&123i64)); /// assert!(Float::from(-123).eq_abs(&123i64)); /// assert!(Float::ONE_HALF.ne_abs(&-1i64)); /// /// assert!(123u64.eq_abs(&Float::from(123))); /// assert!(1u64.ne_abs(&Float::ONE_HALF)); /// /// assert!(123i64.eq_abs(&Float::from(123))); /// assert!(123i64.eq_abs(&Float::from(-123))); /// assert!((-1i64).ne_abs(&Float::ONE_HALF)); /// ``` pub mod eq_abs_primitive_int; /// Implementations of [`EqAbs`](`malachite_base::num::comparison::traits::EqAbs`) (a trait for /// comparing the absolute values of numbers for equality) for [`Float`](crate::Float)s and /// [`Rational`](malachite_q::Rational)s. pub mod eq_abs_rational; /// Hashing of [`Float`](crate::Float)s. pub mod hash; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for [`Float`](crate::Float)s and /// [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_cmp_abs_integer; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for [`Float`](crate::Float)s and /// [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_cmp_abs_natural; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for [`Float`](crate::Float)s and /// primitive floats. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; /// use malachite_float::Float; /// /// assert!(Float::ONE_HALF.gt_abs(&0.4)); /// assert!(Float::ONE_HALF.lt_abs(&0.6)); /// assert!(Float::ONE_HALF.eq_abs(&-0.5)); /// /// assert!(0.4.lt_abs(&Float::ONE_HALF)); /// assert!(0.6.gt_abs(&Float::ONE_HALF)); /// assert!((-0.5).eq_abs(&Float::ONE_HALF)); /// ``` pub mod partial_cmp_abs_primitive_float; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for [`Float`](crate::Float)s and /// primitive integers. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// /// assert!(Float::from(80).lt_abs(&100u64)); /// assert!(Float::INFINITY.gt_abs(&100u64)); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&100u64)); /// /// assert!(100u64.gt_abs(&Float::from(80))); /// assert!(100u64.lt_abs(&Float::INFINITY)); /// assert!(100u64.lt_abs(&Float::NEGATIVE_INFINITY)); /// /// assert!(Float::from(80).lt_abs(&100i64)); /// assert!(Float::from(-80).lt_abs(&-100i64)); /// assert!(Float::INFINITY.gt_abs(&100i64)); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&-100i64)); /// /// assert!(100i64.gt_abs(&Float::from(80))); /// assert!(100i64.lt_abs(&Float::INFINITY)); /// assert!((-100i64).lt_abs(&Float::INFINITY)); /// assert!((-100i64).lt_abs(&Float::NEGATIVE_INFINITY)); /// ``` pub mod partial_cmp_abs_primitive_int; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for [`Float`](crate::Float)s and /// [`Rational`](malachite_q::Rational)s. pub mod partial_cmp_abs_rational; /// Comparison of [`Float`](crate::Float)s and [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_cmp_integer; /// Comparison of [`Float`](crate::Float)s and [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_cmp_natural; /// Comparison of [`Float`](crate::Float)s and primitive floats. /// /// # partial_cmp /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_float::Float; /// /// assert!(Float::ONE_HALF > 0.4); /// assert!(Float::ONE_HALF < 0.6); /// assert!(Float::ONE_HALF > -0.5); /// /// assert!(0.4 < Float::ONE_HALF); /// assert!(0.6 > Float::ONE_HALF); /// assert!(-0.5 < Float::ONE_HALF); /// ``` pub mod partial_cmp_primitive_float; /// Comparison of [`Float`](crate::Float)s and primitive integers. /// /// # partial_cmp /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// /// assert!(Float::from(80) < 100u64); /// assert!(Float::INFINITY > 100u64); /// assert!(Float::NEGATIVE_INFINITY < 100u64); /// /// assert!(100u64 > Float::from(80)); /// assert!(100u64 < Float::INFINITY); /// assert!(100u64 > Float::NEGATIVE_INFINITY); /// /// assert!(Float::from(80) < 100i64); /// assert!(Float::from(-80) > -100i64); /// assert!(Float::INFINITY > 100i64); /// assert!(Float::NEGATIVE_INFINITY < -100i64); /// /// assert!(100i64 > Float::from(80)); /// assert!(-100i64 < Float::from(-80)); /// assert!(-100i64 < Float::INFINITY); /// assert!(-100i64 > Float::NEGATIVE_INFINITY); /// ``` pub mod partial_cmp_primitive_int; /// Comparison of [`Float`](crate::Float)s and [`Rational`](malachite_q::Rational)s. pub mod partial_cmp_rational; /// Equality of [`Float`](crate::Float)s and [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_eq_integer; /// Equality of [`Float`](crate::Float)s and [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_eq_natural; /// Equality of [`Float`](crate::Float)s and primitive floats. /// /// # partial_eq /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_float::Float; /// /// assert!(Float::from(123) == 123.0); /// assert!(Float::ONE_HALF == 0.5); /// assert!(Float::ONE_HALF != -0.5); /// assert!(Float::ONE_HALF != 0.4); /// /// assert!(123.0 == Float::from(123)); /// assert!(0.5 == Float::ONE_HALF); /// assert!(-0.5 != Float::ONE_HALF); /// assert!(0.4 != Float::ONE_HALF); /// ``` pub mod partial_eq_primitive_float; /// Equality of [`Float`](crate::Float)s and primitive integers. /// /// # partial_eq /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_float::Float; /// /// assert!(Float::from(123) == 123u64); /// assert!(Float::ONE_HALF != 1u64); /// /// assert!(Float::from(123) == 123i64); /// assert!(Float::from(-123) == -123i64); /// assert!(Float::ONE_HALF != -1i64); /// /// assert!(123u64 == Float::from(123)); /// assert!(1u64 != Float::ONE_HALF); /// /// assert!(123i64 == Float::from(123)); /// assert!(-123i64 == Float::from(-123)); /// assert!(-1i64 != Float::ONE_HALF); /// ``` pub mod partial_eq_primitive_int; /// Equality of [`Float`](crate::Float)s and [`Rational`](malachite_q::Rational)s. pub mod partial_eq_rational; ================================================ FILE: malachite-float/src/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl PartialOrdAbs for Float { /// Compares the absolute values of a [`Float`] and an [`Integer`]. /// /// NaN is not comparable to any [`Integer`]. $\infty$ and $-\infty$ are greater in absolute /// value than any [`Integer`]. Both the [`Float`] zero and the [`Float`] negative zero are /// equal to the [`Integer`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Float::from(80).lt_abs(&Integer::from(100))); /// assert!(Float::from(-80).lt_abs(&Integer::from(-100))); /// assert!(Float::INFINITY.gt_abs(&Integer::from(100))); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&Integer::from(-100))); /// ``` fn partial_cmp_abs(&self, other: &Integer) -> Option { match (self, other) { (float_nan!(), _) => None, (Self(Infinity { .. }), _) => Some(Greater), (float_either_zero!(), y) => Some(if *y == 0 { Equal } else { Less }), ( Self(Finite { exponent: e_x, significand: x, .. }), y, ) => Some(if *other == 0 { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&other.significant_bits()) .then_with(|| x.cmp_normalized(y.unsigned_abs_ref())) }), } } } impl PartialOrdAbs for Integer { /// Compares the absolute values of an [`Integer`] and a [`Float`]. /// /// No [`Integer`] is comparable to NaN. Every [`Integer`] is smaller in absolute value than /// $\infty$ and $-\infty$. The [`Integer`] zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(100).gt_abs(&Float::from(80))); /// assert!(Integer::from(100).lt_abs(&Float::INFINITY)); /// assert!(Integer::from(-100).lt_abs(&Float::INFINITY)); /// assert!(Integer::from(-100).lt_abs(&Float::NEGATIVE_INFINITY)); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl PartialOrdAbs for Float { /// Compares the absolute value of a [`Float`] to a [`Natural`]. /// /// NaN is not comparable to any [`Natural`]. $\infty$ and $-\infty$ are greater in absolute /// value than any [`Natural`]. Both the [`Float`] zero and the [`Float`] negative zero are /// equal to the [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Float::from(80).lt_abs(&Natural::from(100u32))); /// assert!(Float::INFINITY.gt_abs(&Natural::from(100u32))); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&Natural::from(100u32))); /// ``` fn partial_cmp_abs(&self, other: &Natural) -> Option { match (self, other) { (float_nan!(), _) => None, (Self(Infinity { .. }), _) => Some(Greater), (float_either_zero!(), y) => Some(if *y == 0 { Equal } else { Less }), ( Self(Finite { exponent: e_x, significand: x, .. }), y, ) => Some(if *other == 0 { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&other.significant_bits()) .then_with(|| x.cmp_normalized(y)) }), } } } impl PartialOrdAbs for Natural { /// Compares a [`Natural`] to the absolute value of a [`Float`]. /// /// No [`Natural`] is comparable to NaN. Every [`Natural`] is smaller in absolute value than /// $\infty$ and $-\infty$. The [`Natural`] zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(100u32).gt_abs(&Float::from(80))); /// assert!(Natural::from(100u32).lt_abs(&Float::INFINITY)); /// assert!(Natural::from(100u32).lt_abs(&Float::NEGATIVE_INFINITY)); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_nz::natural::Natural; fn float_partial_cmp_abs_primitive_float(x: &Float, y: &T) -> Option { match (x, y) { (float_nan!(), _) => None, (_, y) if y.is_nan() => None, (Float(Infinity { .. }), y) if !y.is_finite() => Some(Equal), (Float(Infinity { .. }), _) => Some(Greater), (_, y) if !y.is_finite() => Some(Less), (float_either_zero!(), y) => Some(if *y == T::ZERO { Equal } else { Less }), (_, y) if *y == T::ZERO => Some(Greater), ( Float(Finite { exponent: e_x, significand: m_x, .. }), y, ) => Some( (i64::from(*e_x) - 1) .cmp(&y.sci_exponent()) .then_with(|| m_x.cmp_normalized(&Natural::from(y.integer_mantissa()))), ), } } macro_rules! impl_partial_cmp_abs_primitive_float { ($t: ident) => { impl PartialOrdAbs<$t> for Float { /// Compares the absolute values of a [`Float`] and a primitive float. /// /// The [`Float`] NaN is not comparable to any primitive float, not even the primitive /// float NaN. Every [`Float`] zero is equal to every primitive float zero, regardless /// of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { float_partial_cmp_abs_primitive_float(self, other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of a primitive float and a [`Float`]. /// /// The primitive float NaN is not comparable to any primitive float, not even the /// [`Float`] NaN. Every primitive float zero is equal to every [`Float`] zero, /// regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_partial_cmp_abs_primitive_float); ================================================ FILE: malachite-float/src/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_nz::natural::Natural; fn float_partial_cmp_abs_unsigned(x: &Float, y: &T) -> Option where Natural: From, { match (x, y) { (float_nan!(), _) => None, (Float(Infinity { .. }), _) => Some(Greater), (float_either_zero!(), y) => Some(if *y == T::ZERO { Equal } else { Less }), ( Float(Finite { exponent: e_x, significand: sig_x, .. }), y, ) => Some(if *y == T::ZERO { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&y.significant_bits()) .then_with(|| sig_x.cmp_normalized(&Natural::from(*y))) }), } } macro_rules! impl_from_unsigned { ($t: ident) => { impl PartialOrdAbs<$t> for Float { /// Compares the absolute values of a [`Float`] and an unsigned primitive integer. /// /// NaN is not comparable to any primitive integer. $\infty$ and $-\infty$ are greater /// in absolute value than any primitive integer. Both the [`Float`] zero and the /// [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { float_partial_cmp_abs_unsigned(self, other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of an unsigned primitive integer and a [`Float`]. /// /// No primitive integer is comparable to NaN. Every primitive integer is smaller in /// absolute value than $\infty$ and $-\infty$. The integer zero is equal to both the /// [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_from_unsigned); fn float_partial_cmp_abs_signed(x: &Float, y: &T) -> Option where Natural: From<::Output>, { match (x, y) { (float_nan!(), _) => None, (Float(Infinity { .. }), _) => Some(Greater), (float_either_zero!(), y) => Some(if *y == T::ZERO { Equal } else { Less }), ( Float(Finite { exponent: e_x, significand: sig_x, .. }), y, ) => Some(if *y == T::ZERO { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&y.significant_bits()) .then_with(|| sig_x.cmp_normalized(&Natural::from(y.unsigned_abs()))) }), } } macro_rules! impl_from_signed { ($t: ident) => { impl PartialOrdAbs<$t> for Float { /// Compares the absolute values of a [`Float`] and a signed primitive integer. /// /// NaN is not comparable to any primitive integer. $\infty$ and $-\infty$ are greater /// in absolute value than any primitive integer. Both the [`Float`] zero and the /// [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { float_partial_cmp_abs_signed(self, other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of a signed primitive integer and a [`Float`]. /// /// No primitive integer is comparable to NaN. Every primitive integer is smaller in /// absolute value than $\infty$ and $-\infty$. The integer zero is equal to both the /// [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_from_signed); ================================================ FILE: malachite-float/src/comparison/partial_cmp_abs_rational.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_q::Rational; impl PartialOrdAbs for Float { /// Compares the absolute values of a [`Float`] and a [`Rational`]. /// /// NaN is not comparable to any [`Rational`]. $\infty$ and $-\infty$ are greater in absolute /// value than any [`Rational`]. Both the [`Float`] zero and the [`Float`] negative zero are /// equal to the [`Rational`] zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Float::from(80).lt_abs(&Rational::from(100))); /// assert!(Float::from(-80).lt_abs(&Rational::from(-100))); /// assert!(Float::INFINITY.gt_abs(&Rational::from(100))); /// assert!(Float::NEGATIVE_INFINITY.gt_abs(&Rational::from(-100))); /// assert!(Float::from(1.0f64 / 3.0).lt_abs(&Rational::from_unsigneds(1u8, 3))); /// ``` fn partial_cmp_abs(&self, other: &Rational) -> Option { match (self, other) { (float_nan!(), _) => None, (float_either_infinity!(), _) => Some(Greater), (float_either_zero!(), y) => Some(if *y == 0 { Equal } else { Less }), ( Self(Finite { exponent: e_x, significand: significand_x, .. }), y, ) => Some(if *y == 0u32 { Greater } else { let e_x = i64::from(*e_x); let exp_cmp = (e_x - 1).cmp(&y.floor_log_base_2_abs()); if exp_cmp != Equal { return Some(exp_cmp); } let shift = e_x - i64::exact_from(significand_bits(significand_x)); let abs_shift = shift.unsigned_abs(); match shift.sign() { Equal => (significand_x * other.denominator_ref()).cmp(other.numerator_ref()), Greater => ((significand_x * other.denominator_ref()) << abs_shift) .cmp(other.numerator_ref()), Less => { let n_trailing_zeros = significand_x.trailing_zeros().unwrap(); if abs_shift <= n_trailing_zeros { ((significand_x >> abs_shift) * other.denominator_ref()) .cmp(other.numerator_ref()) } else { ((significand_x >> n_trailing_zeros) * other.denominator_ref()) .cmp(&(other.numerator_ref() << (abs_shift - n_trailing_zeros))) } } } }), } } } impl PartialOrdAbs for Rational { /// Compares the absolute values of a [`Rational`] and a [`Float`]. /// /// No [`Rational`] is comparable to NaN. Every [`Rational`] is smaller in absolute value than /// $\infty$ and $-\infty$. The [`Rational`] zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Rational::from(100).gt_abs(&Float::from(80))); /// assert!(Rational::from(-100).gt_abs(&Float::from(-80))); /// assert!(Rational::from(100).lt_abs(&Float::INFINITY)); /// assert!(Rational::from(-100).lt_abs(&Float::NEGATIVE_INFINITY)); /// assert!(Rational::from_unsigneds(1u8, 3).gt_abs(&Float::from(1.0f64 / 3.0))); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Float) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl PartialOrd for Float { /// Compares a [`Float`] to an [`Integer`]. /// /// NaN is not comparable to any [`Integer`]. $\infty$ is greater than any [`Integer`], and /// $-\infty$ is less. Both the [`Float`] zero and the [`Float`] negative zero are equal to the /// [`Integer`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Float::from(80) < Integer::from(100)); /// assert!(Float::from(-80) > Integer::from(-100)); /// assert!(Float::INFINITY > Integer::from(100)); /// assert!(Float::NEGATIVE_INFINITY < Integer::from(-100)); /// ``` fn partial_cmp(&self, other: &Integer) -> Option { match (self, other) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), y) => 0u32.partial_cmp(y), ( Self(Finite { sign: s_x, exponent: e_x, significand: x, .. }), y, ) => { let s_y = *other > 0; let s_cmp = s_x.cmp(&s_y); if s_cmp != Equal { return Some(s_cmp); } let abs_cmp = if *other == 0u32 { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&other.significant_bits()) .then_with(|| x.cmp_normalized(y.unsigned_abs_ref())) }; Some(if s_y { abs_cmp } else { abs_cmp.reverse() }) } } } } impl PartialOrd for Integer { /// Compares an [`Integer`] to a [`Float`]. /// /// No [`Integer`] is comparable to NaN. Every [`Integer`] is smaller than $\infty$ and greater /// than $-\infty$. The [`Integer`] zero is equal to both the [`Float`] zero and the [`Float`] /// negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(100) > Float::from(80)); /// assert!(Integer::from(-100) < Float::from(-80)); /// assert!(Integer::from(100) < Float::INFINITY); /// assert!(Integer::from(-100) > Float::NEGATIVE_INFINITY); /// ``` #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl PartialOrd for Float { /// Compares a [`Float`] to a [`Natural`]. /// /// NaN is not comparable to any [`Natural`]. $\infty$ is greater than any [`Natural`], and /// $-\infty$ is less. Both the [`Float`] zero and the [`Float`] negative zero are equal to the /// [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Float::from(80) < Natural::from(100u32)); /// assert!(Float::INFINITY > Natural::from(100u32)); /// assert!(Float::NEGATIVE_INFINITY < Natural::from(100u32)); /// ``` fn partial_cmp(&self, other: &Natural) -> Option { match (self, other) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), _) => Some(if *other == 0u32 { Equal } else { Less }), ( Self(Finite { sign: s_x, exponent: e_x, significand: x, .. }), y, ) => Some(if !s_x { Less } else if *other == 0u32 { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&other.significant_bits()) .then_with(|| x.cmp_normalized(y)) }), } } } impl PartialOrd for Natural { /// Compares a [`Natural`] to a [`Float`]. /// /// No [`Natural`] is comparable to NaN. Every [`Natural`] is smaller than $\infty$ and greater /// than $-\infty$. The [`Natural`] zero is equal to both the [`Float`] zero and the [`Float`] /// negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(100u32) > Float::from(80)); /// assert!(Natural::from(100u32) < Float::INFINITY); /// assert!(Natural::from(100u32) > Float::NEGATIVE_INFINITY); /// ``` #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_nz::natural::Natural; fn float_partial_cmp_primitive_float(x: &Float, y: &T) -> Option { match (x, y) { (float_nan!(), _) => None, (_, y) if y.is_nan() => None, (float_infinity!(), y) if *y == T::INFINITY => Some(Equal), (float_negative_infinity!(), y) if *y == T::NEGATIVE_INFINITY => Some(Equal), (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (_, y) if *y == T::NEGATIVE_INFINITY => Some(Greater), (_, y) if *y == T::INFINITY => Some(Less), (float_either_zero!(), y) => Some(if *y == T::ZERO { Equal } else if y.is_sign_positive() { Less } else { Greater }), (x, y) if *y == T::ZERO => Some(x.sign()), ( Float(Finite { sign: s_x, exponent: e_x, significand: m_x, .. }), y, ) => { let s_y = y.is_sign_positive(); Some(s_x.cmp(&s_y).then_with(|| { let abs_cmp = (i64::from(*e_x) - 1) .cmp(&y.sci_exponent()) .then_with(|| m_x.cmp_normalized(&Natural::from(y.integer_mantissa()))); if *s_x { abs_cmp } else { abs_cmp.reverse() } })) } } } macro_rules! impl_partial_cmp_primitive_float { ($t: ident) => { impl PartialOrd<$t> for Float { /// Compares a [`Float`] to a primitive float. /// /// The [`Float`] NaN is not comparable to any primitive float, not even the primitive /// float NaN. Every [`Float`] zero is equal to every primitive float zero, regardless /// of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { float_partial_cmp_primitive_float(self, other) } } impl PartialOrd for $t { /// Compares a primitive float to a [`Float`]. /// /// The primitive float NaN is not comparable to any primitive float, not even the /// [`Float`] NaN. Every primitive float zero is equal to every [`Float`] zero, /// regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_partial_cmp_primitive_float); ================================================ FILE: malachite-float/src/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_nz::natural::Natural; fn float_partial_cmp_unsigned(x: &Float, y: &T) -> Option where Natural: From, { match (x, y) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), _) => Some(if *y == T::ZERO { Equal } else { Less }), ( Float(Finite { sign: s_x, exponent: e_x, significand: sig_x, .. }), y, ) => Some(if !s_x { Less } else if *y == T::ZERO { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&y.significant_bits()) .then_with(|| sig_x.cmp_normalized(&Natural::from(*y))) }), } } macro_rules! impl_from_unsigned { ($t: ident) => { impl PartialOrd<$t> for Float { /// Compares a [`Float`] to an unsigned primitive integer. /// /// NaN is not comparable to any primitive integer. $\infty$ is greater than any /// primitive integer, and $-\infty$ is less. Both the [`Float`] zero and the [`Float`] /// negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { float_partial_cmp_unsigned(self, other) } } impl PartialOrd for $t { /// Compares an unsigned primitive integer to a [`Float`]. /// /// No integer is comparable to NaN. Every integer is smaller than $\infty$ and greater /// than $-\infty$. The integer zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_from_unsigned); fn float_partial_cmp_signed(x: &Float, y: &T) -> Option where Natural: From<::Output>, { match (x, y) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), _) => Some(T::ZERO.cmp(y)), ( Float(Finite { sign: s_x, exponent: e_x, significand: sig_x, .. }), y, ) => { let s_y = *y > T::ZERO; let s_cmp = s_x.cmp(&s_y); if s_cmp != Equal { return Some(s_cmp); } let abs_cmp = if *y == T::ZERO { Greater } else if *e_x <= 0 { Less } else { u64::from(e_x.unsigned_abs()) .cmp(&y.significant_bits()) .then_with(|| sig_x.cmp_normalized(&Natural::from(y.unsigned_abs()))) }; Some(if s_y { abs_cmp } else { abs_cmp.reverse() }) } } } macro_rules! impl_from_signed { ($t: ident) => { impl PartialOrd<$t> for Float { /// Compares a [`Float`] to a signed primitive integer. /// /// NaN is not comparable to any primitive integer. $\infty$ is greater than any /// primitive integer, and $-\infty$ is less. Both the [`Float`] zero and the [`Float`] /// negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { float_partial_cmp_signed(self, other) } } impl PartialOrd for $t { /// Compares a signed primitive integer to a [`Float`]. /// /// No integer is comparable to NaN. Every integer is smaller than $\infty$ and greater /// than $-\infty$. The integer zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_from_signed); ================================================ FILE: malachite-float/src/comparison/partial_cmp_rational.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::conversion::traits::ExactFrom; use malachite_q::Rational; impl PartialOrd for Float { /// Compares a [`Float`] to a [`Rational`]. /// /// NaN is not comparable to any [`Rational`]. $\infty$ is greater than any [`Rational`], and /// $-\infty$ is less. Both the [`Float`] zero and the [`Float`] negative zero are equal to the /// [`Rational`] zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Float::from(80) < Rational::from(100)); /// assert!(Float::from(-80) > Rational::from(-100)); /// assert!(Float::INFINITY > Rational::from(100)); /// assert!(Float::NEGATIVE_INFINITY < Rational::from(-100)); /// assert!(Float::from(1.0f64 / 3.0) < Rational::from_unsigneds(1u8, 3)); /// ``` fn partial_cmp(&self, other: &Rational) -> Option { match (self, other) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), y) => 0u32.partial_cmp(y), ( Self(Finite { sign: s_x, exponent: e_x, significand: significand_x, .. }), y, ) => Some(if *y == 0u32 { if *s_x { Greater } else { Less } } else { let s_cmp = s_x.cmp(&(*y > 0)); if s_cmp != Equal { return Some(s_cmp); } let e_x = i64::from(*e_x); let exp_cmp = (e_x - 1).cmp(&other.floor_log_base_2_abs()); if exp_cmp != Equal { return Some(if *s_x { exp_cmp } else { exp_cmp.reverse() }); } let shift = e_x - i64::exact_from(significand_bits(significand_x)); let abs_shift = shift.unsigned_abs(); let prod_cmp = match shift.sign() { Equal => (significand_x * other.denominator_ref()).cmp(other.numerator_ref()), Greater => ((significand_x * other.denominator_ref()) << abs_shift) .cmp(other.numerator_ref()), Less => { let n_trailing_zeros = significand_x.trailing_zeros().unwrap(); if abs_shift <= n_trailing_zeros { ((significand_x >> abs_shift) * other.denominator_ref()) .cmp(other.numerator_ref()) } else { ((significand_x >> n_trailing_zeros) * other.denominator_ref()) .cmp(&(other.numerator_ref() << (abs_shift - n_trailing_zeros))) } } }; if *s_x { prod_cmp } else { prod_cmp.reverse() } }), } } } impl PartialOrd for Rational { /// Compares an [`Rational`] to a [`Float`]. /// /// No [`Rational`] is comparable to NaN. Every [`Rational`] is smaller than $\infty$ and /// greater than $-\infty$. The [`Rational`] zero is equal to both the [`Float`] zero and the /// [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Rational::from(100) > Float::from(80)); /// assert!(Rational::from(-100) < Float::from(-80)); /// assert!(Rational::from(100) < Float::INFINITY); /// assert!(Rational::from(-100) > Float::NEGATIVE_INFINITY); /// assert!(Rational::from_unsigneds(1u8, 3) > Float::from(1.0f64 / 3.0)); /// ``` #[inline] fn partial_cmp(&self, other: &Float) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } ================================================ FILE: malachite-float/src/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl PartialEq for Float { /// Determines whether a [`Float`] is equal to an [`Integer`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Integer`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Integer`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Float::from(123) == Integer::from(123)); /// assert!(Float::from(-123) == Integer::from(-123)); /// assert!(Float::ONE_HALF != Integer::ONE); /// ``` fn eq(&self, other: &Integer) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { sign, exponent, significand, .. }) => { *other != 0u32 && *sign == (*other >= 0u32) && *exponent >= 0 && other.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(other.unsigned_abs_ref()) == Equal } _ => false, } } } impl PartialEq for Integer { /// Determines whether an [`Integer`] is equal to a [`Float`]. /// /// No [`Integer`] is equal to $\infty$, $-\infty$, or NaN. The [`Integer`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(123) == Float::from(123)); /// assert!(Integer::from(-123) == Float::from(-123)); /// assert!(Integer::ONE != Float::ONE_HALF); /// ``` #[inline] fn eq(&self, other: &Float) -> bool { other == self } } ================================================ FILE: malachite-float/src/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl PartialEq for Float { /// Determines whether a [`Float`] is equal to a [`Natural`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Natural`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Float::from(123) == Natural::from(123u32)); /// assert!(Float::ONE_HALF != Natural::ONE); /// ``` fn eq(&self, other: &Natural) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { sign, exponent, significand, .. }) => { *sign && *other != 0u32 && *exponent >= 0 && other.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(other) == Equal } _ => false, } } } impl PartialEq for Natural { /// Determines whether a [`Natural`] is equal to a [`Float`]. /// /// No [`Natural`] is equal to $\infty$, $-\infty$, or NaN. The [`Natural`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) == Float::from(123)); /// assert!(Natural::ONE != Float::ONE_HALF); /// ``` #[inline] fn eq(&self, other: &Float) -> bool { other == self } } ================================================ FILE: malachite-float/src/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use core::cmp::Ordering::*; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_nz::natural::Natural; fn float_partial_eq_primitive_float(x: &Float, y: &T) -> bool { match x { float_nan!() => false, float_infinity!() => *y == T::INFINITY, float_negative_infinity!() => *y == T::NEGATIVE_INFINITY, float_either_zero!() => *y == T::ZERO, Float(Finite { sign, exponent, significand, .. }) => { y.is_finite() && *y != T::ZERO && *sign == (*y > T::ZERO) && i64::from(*exponent - 1) == y.sci_exponent() && significand.cmp_normalized(&Natural::from(y.integer_mantissa())) == Equal } } } macro_rules! impl_partial_eq_primitive_float { ($t: ident) => { impl PartialEq<$t> for Float { /// Determines whether a [`Float`] is equal to a primitive float. /// /// The [`Float`] $\infty$ is equal to the primitive float $\infty$, and the [`Float`] /// $-\infty$ is equal to the primitive float $-\infty$. The [`Float`] NaN is not equal /// to anything, not even the primitive float NaN. Every [`Float`] zero is equal to /// every primitive float zero, regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[inline] fn eq(&self, other: &$t) -> bool { float_partial_eq_primitive_float(self, other) } } impl PartialEq for $t { /// Determines whether a primitive float is equal to a [`Float`]. /// /// The primitive float $\infty$ is equal to the [`Float`] $\infty$, and the primitive /// float $-\infty$ is equal to the [`Float`] $-\infty$. The primitive float NaN is not /// equal to anything, not even the [`Float`] NaN. Every primitive float zero is equal /// to every [`Float`] zero, regardless of sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[inline] fn eq(&self, other: &Float) -> bool { other == self } } }; } apply_to_primitive_floats!(impl_partial_eq_primitive_float); ================================================ FILE: malachite-float/src/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_nz::natural::Natural; fn float_partial_eq_unsigned(x: &Float, y: &T) -> bool where Natural: From, { match x { float_either_zero!() => *y == T::ZERO, Float(Finite { sign, exponent, significand, .. }) => { *y != T::ZERO && *sign && *exponent >= 0 && y.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(&Natural::from(*y)) == Equal } _ => false, } } macro_rules! impl_partial_eq_unsigned { ($t: ident) => { impl PartialEq<$t> for Float { /// Determines whether a [`Float`] is equal to an unsigned primitive integer. /// /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &$t) -> bool { float_partial_eq_unsigned(self, other) } } impl PartialEq for $t { /// Determines whether an unsigned primitive integer is equal to a [`Float`]. /// /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is /// equal to both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Float) -> bool { other == self } } }; } apply_to_unsigneds!(impl_partial_eq_unsigned); fn float_partial_eq_signed(x: &Float, y: &T) -> bool where Natural: From<::Output>, { match x { float_either_zero!() => *y == T::ZERO, Float(Finite { sign, exponent, significand, .. }) => { *y != T::ZERO && *sign == (*y >= T::ZERO) && *exponent >= 0 && y.significant_bits() == u64::from(exponent.unsigned_abs()) && significand.cmp_normalized(&Natural::from(y.unsigned_abs())) == Equal } _ => false, } } macro_rules! impl_partial_eq_signed { ($t: ident) => { impl PartialEq<$t> for Float { /// Determines whether a [`Float`] is equal to a signed primitive integer. /// /// $\infty$, $-\infty$, and NaN are not equal to any primitive integer. Both the /// [`Float`] zero and the [`Float`] negative zero are equal to the integer zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &$t) -> bool { float_partial_eq_signed(self, other) } } impl PartialEq for $t { /// Determines whether a signed primitive integer is equal to a [`Float`]. /// /// No primitive integer is equal to $\infty$, $-\infty$, or NaN. The integer zero is /// equal to both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Float) -> bool { other == self } } }; } apply_to_signeds!(impl_partial_eq_signed); ================================================ FILE: malachite-float/src/comparison/partial_eq_rational.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Zero}; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::CheckedLogBase2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_q::Rational; impl PartialEq for Float { /// Determines whether a [`Float`] is equal to a [`Rational`]. /// /// $\infty$, $-\infty$, and NaN are not equal to any [`Rational`]. Both the [`Float`] zero and /// the [`Float`] negative zero are equal to the [`Rational`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Float::from(123) == Rational::from(123)); /// assert!(Float::from(-123) == Rational::from(-123)); /// assert!(Float::ONE_HALF == Rational::ONE_HALF); /// assert!(Float::from(1.0f64 / 3.0) != Rational::from_unsigneds(1u8, 3)); /// ``` fn eq(&self, other: &Rational) -> bool { match self { float_either_zero!() => *other == 0u32, Self(Finite { sign, exponent, significand, .. }) => { *other != 0 && *sign == (*other > 0) && if let Some(log_d) = other.denominator_ref().checked_log_base_2() { let n = other.numerator_ref(); i64::from(*exponent) == i64::exact_from(n.significant_bits()) - i64::exact_from(log_d) && significand.cmp_normalized(n) == Equal } else { false } } _ => false, } } } impl PartialEq for Rational { /// Determines whether a [`Rational`] is equal to a [`Float`]. /// /// No [`Rational`] is equal to $\infty$, $-\infty$, or NaN. The [`Rational`] zero is equal to /// both the [`Float`] zero and the [`Float`] negative zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert!(Rational::from(123) == Float::from(123)); /// assert!(Rational::from(-123) == Float::from(-123)); /// assert!(Rational::ONE_HALF == Float::ONE_HALF); /// assert!(Rational::from_unsigneds(1u8, 3) != Float::from(1.0f64 / 3.0)); /// ``` #[inline] fn eq(&self, other: &Float) -> bool { other == self } } ================================================ FILE: malachite-float/src/constants/gauss_constant.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use core::cmp::Ordering::*; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of Gauss's constant, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = G+\varepsilon=1/\mathrm{AGM}(1,\sqrt{2})+\varepsilon, /// $$ /// where AGM is the arithmetic-geometric mean. /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (gauss_constant, o) = Float::gauss_constant_prec_round(100, Floor); /// assert_eq!( /// gauss_constant.to_string(), /// "0.834626841674073186281429732799" /// ); /// assert_eq!(o, Less); /// /// let (gauss_constant, o) = Float::gauss_constant_prec_round(100, Ceiling); /// assert_eq!(gauss_constant.to_string(), "0.8346268416740731862814297328"); /// assert_eq!(o, Greater); /// ``` pub fn gauss_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let sqrt_2_lo = Self::sqrt_2_prec_round(working_prec, Floor).0; let mut sqrt_2_hi = sqrt_2_lo.clone(); sqrt_2_hi.increment(); let lo = Self::ONE .agm_round(sqrt_2_hi, Ceiling) .0 .reciprocal_round(Floor) .0; let hi = Self::ONE .agm_round(sqrt_2_lo, Floor) .0 .reciprocal_round(Ceiling) .0; let (gauss_constant_lo, mut o_lo) = Self::from_float_prec_round(lo, prec, rm); let (gauss_constant_hi, mut o_hi) = Self::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && gauss_constant_lo == gauss_constant_hi { return (gauss_constant_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of Gauss's constant, $G=1/\mathrm{AGM}(1,\sqrt{2})$, with the given /// precision and rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also /// returned, indicating whether the rounded value is less than or greater than the exact value /// of the constant. (Since the constant is irrational, the rounded value is never equal to the /// exact value.) /// /// $$ /// x=G+\varepsilon=1/\mathrm{AGM}(1,\sqrt{2})+\varepsilon, /// $$ /// where AGM is the arithmetic-geometric mean. /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (gauss_constant, o) = Float::gauss_constant_prec(1); /// assert_eq!(gauss_constant.to_string(), "1.0"); /// assert_eq!(o, Greater); /// /// let (gauss_constant, o) = Float::gauss_constant_prec(10); /// assert_eq!(gauss_constant.to_string(), "0.835"); /// assert_eq!(o, Greater); /// /// let (gauss_constant, o) = Float::gauss_constant_prec(100); /// assert_eq!( /// gauss_constant.to_string(), /// "0.834626841674073186281429732799" /// ); /// assert_eq!(o, Less); /// ``` #[inline] pub fn gauss_constant_prec(prec: u64) -> (Self, Ordering) { Self::gauss_constant_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/lemniscate_constant.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of the lemniscate constant $\varpi$, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \varpi+\varepsilon=\pi G+\varepsilon, /// $$ /// where $G$ is Gauss's constant. /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+2}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec_round(100, Floor); /// assert_eq!( /// lemniscate_constant.to_string(), /// "2.62205755429211981046483958989" /// ); /// assert_eq!(o, Less); /// /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec_round(100, Ceiling); /// assert_eq!( /// lemniscate_constant.to_string(), /// "2.622057554292119810464839589893" /// ); /// assert_eq!(o, Greater); /// ``` pub fn lemniscate_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let lemniscate_constant = Self::pi_prec(working_prec).0 * Self::gauss_constant_prec(working_prec).0; if float_can_round( lemniscate_constant.significand_ref().unwrap(), working_prec - 2, prec, rm, ) { return Self::from_float_prec_round(lemniscate_constant, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of the lemniscate constant $\varpi$, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// $$ /// x = \varpi+\varepsilon=\pi G+\varepsilon, /// $$ /// where $G$ is Gauss's constant. /// - $|\varepsilon| < 2^{-p+1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(1); /// assert_eq!(lemniscate_constant.to_string(), "2.0"); /// assert_eq!(o, Less); /// /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(10); /// assert_eq!(lemniscate_constant.to_string(), "2.621"); /// assert_eq!(o, Less); /// /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(100); /// assert_eq!( /// lemniscate_constant.to_string(), /// "2.62205755429211981046483958989" /// ); /// assert_eq!(o, Less); /// ``` #[inline] pub fn lemniscate_constant_prec(prec: u64) -> (Self, Ordering) { Self::lemniscate_constant_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/ln_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use alloc::vec; use core::cmp::Ordering; use core::mem::swap; use malachite_base::num::arithmetic::traits::CeilingLogBase2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; // Auxiliary function: Compute the terms from n1 to n2 (excluded) 3 / 4 * sum((-1) ^ n * n! ^ 2 / 2 // ^ n / (2 * n + 1)!, n = n1...n2 - 1).s // // Numerator is T[0], denominator is Q[0], Compute P[0] only when need_P is non-zero. // // Need 1 + ceil(log(n2 - n1) / log(2)) cells in T[], P[], Q[]. // // This is S from const_log2.c, MPFR 4.2.0. fn sum(t: &mut [Integer], p: &mut [Integer], q: &mut [Integer], n1: u64, n2: u64, need_p: bool) { if n2 == n1 + 1 { p[0] = if n1 == 0 { const { Integer::const_from_unsigned(3) } } else { -Integer::from(n1) }; q[0] = ((Integer::from(n1) << 1u32) + Integer::ONE) << 2u32; t[0].clone_from(&p[0]); } else { let m = (n1 >> 1) + (n2 >> 1) + (n1 & 1 & n2); sum(t, p, q, n1, m, true); let (t_head, t_tail) = t.split_first_mut().unwrap(); let (p_head, p_tail) = p.split_first_mut().unwrap(); let (q_head, q_tail) = q.split_first_mut().unwrap(); sum(t_tail, p_tail, q_tail, m, n2, need_p); *t_head *= &q_tail[0]; t_tail[0] *= &*p_head; *t_head += &t_tail[0]; if need_p { *p_head *= &p_tail[0]; } *q_head *= &q_tail[0]; // remove common trailing zeros if any let mut tz = t_head.trailing_zeros().unwrap(); if tz != 0 { let mut qz = q_head.trailing_zeros().unwrap(); if qz < tz { tz = qz; } if need_p { qz = p_head.trailing_zeros().unwrap(); if qz < tz { tz = qz; } } // now tz = min(val(T), val(Q), val(P)) if tz != 0 { *t_head >>= tz; *q_head >>= tz; if need_p { *p_head >>= tz; } } } } } impl Float { /// Returns an approximation of the natural logarithm of 2, with the given precision and rounded /// using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \ln 2+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (l2, o) = Float::ln_2_prec_round(100, Floor); /// assert_eq!(l2.to_string(), "0.693147180559945309417232121458"); /// assert_eq!(o, Less); /// /// let (l2, o) = Float::ln_2_prec_round(100, Ceiling); /// assert_eq!(l2.to_string(), "0.693147180559945309417232121459"); /// assert_eq!(o, Greater); /// ``` /// /// This is mpfr_const_log2_internal from const_log2.c, MPFR 4.2.0. pub fn ln_2_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + prec.ceiling_log_base_2() + 3; let mut increment = Limb::WIDTH; loop { let big_n = working_prec / 3 + 1; // the following are needed for error analysis (see algorithms.tex) assert!(working_prec >= 3 && big_n >= 2); let lg_big_n = usize::wrapping_from(big_n.ceiling_log_base_2()) + 1; let mut scratch = vec![Integer::ZERO; 3 * lg_big_n]; split_into_chunks_mut!(scratch, lg_big_n, [t, p], q); sum(t, p, q, 0, big_n, false); let mut t0 = Integer::ZERO; let mut q0 = Integer::ZERO; swap(&mut t0, &mut t[0]); swap(&mut q0, &mut q[0]); let ln_2 = Self::from_integer_prec(t0, working_prec).0 / Self::from_integer_prec(q0, working_prec).0; if float_can_round(ln_2.significand_ref().unwrap(), working_prec - 2, prec, rm) { return Self::from_float_prec_round(ln_2, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of the natural logarithm of 2, with the given precision and rounded /// to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \ln 2+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (l2, o) = Float::ln_2_prec(1); /// assert_eq!(l2.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (l2, o) = Float::ln_2_prec(10); /// assert_eq!(l2.to_string(), "0.693"); /// assert_eq!(o, Greater); /// /// let (l2, o) = Float::ln_2_prec(100); /// assert_eq!(l2.to_string(), "0.693147180559945309417232121458"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn ln_2_prec(prec: u64) -> (Self, Ordering) { Self::ln_2_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/log_2_e.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::Reciprocal; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of the base-2 logarithm of $e$, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \log_2 e+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (log_2_e, o) = Float::log_2_e_prec_round(100, Floor); /// assert_eq!(log_2_e.to_string(), "1.442695040888963407359924681001"); /// assert_eq!(o, Less); /// /// let (log_2_e, o) = Float::log_2_e_prec_round(100, Ceiling); /// assert_eq!(log_2_e.to_string(), "1.442695040888963407359924681003"); /// assert_eq!(o, Greater); /// ``` pub fn log_2_e_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let log_2_e = Self::ln_2_prec_round(working_prec, Floor).0.reciprocal(); // See algorithms.tex. Since we rounded down when computing ln_2, the absolute error of // the inverse is bounded by (c_w + 2c_uk_u)ulp(log_e(2)) <= 4ulp(log_e(2)). if float_can_round( log_2_e.significand_ref().unwrap(), working_prec - 2, prec, rm, ) { return Self::from_float_prec_round(log_2_e, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of the base-2 logarithm of $e$, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// $$ /// x = \log_2 e+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (log_2_e, o) = Float::log_2_e_prec(1); /// assert_eq!(log_2_e.to_string(), "1.0"); /// assert_eq!(o, Less); /// /// let (log_2_e, o) = Float::log_2_e_prec(10); /// assert_eq!(log_2_e.to_string(), "1.443"); /// assert_eq!(o, Greater); /// /// let (log_2_e, o) = Float::log_2_e_prec(100); /// assert_eq!(log_2_e.to_string(), "1.442695040888963407359924681003"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn log_2_e_prec(prec: u64) -> (Self, Ordering) { Self::log_2_e_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/mod.rs ================================================ // Copyright © 2026 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 . /// Functions for approximating Gauss's constant, $G=1/\mathrm{AGM}(1,\sqrt{2})$. pub mod gauss_constant; /// Functions for approximating the lemniscate constant $\varpi=\pi G$, where $G$ is Gauss's /// constant. pub mod lemniscate_constant; /// Functions for approximating $\ln 2$. pub mod ln_2; /// Functions for approximating $\log_2 e$. pub mod log_2_e; /// Functions for approximating $1/\pi$. pub mod one_over_pi; /// Functions for approximating $1/\sqrt{\pi}$. pub mod one_over_sqrt_pi; /// Functions for approximating $1/\sqrt{\tau}=1/\sqrt{2\pi}$. pub mod one_over_sqrt_tau; /// Functions for approximating $\varphi$, the golden ratio. pub mod phi; /// Functions for approximating $\pi$. pub mod pi; /// Functions for approximating $\pi/2$. pub mod pi_over_2; /// Functions for approximating $\pi/3$. pub mod pi_over_3; /// Functions for approximating $\pi/4$. pub mod pi_over_4; /// Functions for approximating $\pi/6$. pub mod pi_over_6; /// Functions for approximating $\pi/8$. pub mod pi_over_8; /// Functions for approximating the prime constant (the constant whose $n$th bit is 1 if and only if /// $n$ is prime). pub mod prime_constant; /// Functions for approximating the Prouhet-Thue-Morse constant (the constant whose bits are the /// Thue-Morse sequence). pub mod prouhet_thue_morse_constant; /// Functions for approximating $\sqrt{2}$. pub mod sqrt_2; /// Functions for approximating $\sqrt{2}/2=\sqrt{1/2}=1/\sqrt{2}$. pub mod sqrt_2_over_2; /// Functions for approximating $\sqrt{3}$. pub mod sqrt_3; /// Functions for approximating $\sqrt{3}/3=\sqrt{1/3}=1/\sqrt{3}$. pub mod sqrt_3_over_3; /// Functions for approximating $\sqrt{\pi}$. pub mod sqrt_pi; /// Functions for approximating $\tau=2\pi$. pub mod tau; /// Functions for approximating $2/\pi$. pub mod two_over_pi; /// Functions for approximating $2/\sqrt{\pi}$. pub mod two_over_sqrt_pi; ================================================ FILE: malachite-float/src/constants/one_over_pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::Reciprocal; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $1/\pi$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 1/\pi+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_pi, o) = Float::one_over_pi_prec_round(100, Floor); /// assert_eq!(one_over_pi.to_string(), "0.3183098861837906715377675267449"); /// assert_eq!(o, Less); /// /// let (one_over_pi, o) = Float::one_over_pi_prec_round(100, Ceiling); /// assert_eq!(one_over_pi.to_string(), "0.3183098861837906715377675267453"); /// assert_eq!(o, Greater); /// ``` pub fn one_over_pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let one_over_pi = Self::pi_prec_round(working_prec, Floor).0.reciprocal(); // See algorithms.tex. Since we rounded down when computing pi, the absolute error of // the inverse is bounded by (c_w + 2c_uk_u)ulp(log_e(2)) <= 4ulp(pi). if float_can_round( one_over_pi.significand_ref().unwrap(), working_prec - 2, prec, rm, ) { return Self::from_float_prec_round(one_over_pi, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of $1/\pi$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 1/\pi+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_pi, o) = Float::one_over_pi_prec(1); /// assert_eq!(one_over_pi.to_string(), "0.2"); /// assert_eq!(o, Less); /// /// let (one_over_pi, o) = Float::one_over_pi_prec(10); /// assert_eq!(one_over_pi.to_string(), "0.3184"); /// assert_eq!(o, Greater); /// /// let (one_over_pi, o) = Float::one_over_pi_prec(100); /// assert_eq!(one_over_pi.to_string(), "0.3183098861837906715377675267449"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn one_over_pi_prec(prec: u64) -> (Self, Ordering) { Self::one_over_pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/one_over_sqrt_pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::ReciprocalSqrt; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $1/\sqrt{\pi}$, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 1/\sqrt{\pi}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec_round(100, Floor); /// assert_eq!( /// one_over_sqrt_pi.to_string(), /// "0.56418958354775628694807945156" /// ); /// assert_eq!(o, Less); /// /// let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec_round(100, Ceiling); /// assert_eq!( /// one_over_sqrt_pi.to_string(), /// "0.564189583547756286948079451561" /// ); /// assert_eq!(o, Greater); /// ``` pub fn one_over_sqrt_pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let one_over_sqrt_pi = Self::pi_prec_round(working_prec, Floor).0.reciprocal_sqrt(); if float_can_round( one_over_sqrt_pi.significand_ref().unwrap(), working_prec - 2, prec, rm, ) { return Self::from_float_prec_round(one_over_sqrt_pi, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of $1/\sqrt{\pi}$, with the given precision and rounded to the /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether /// the rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 1/\sqrt{\pi}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec(1); /// assert_eq!(one_over_sqrt_pi.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec(10); /// assert_eq!(one_over_sqrt_pi.to_string(), "0.564"); /// assert_eq!(o, Greater); /// /// let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec(100); /// assert_eq!( /// one_over_sqrt_pi.to_string(), /// "0.564189583547756286948079451561" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn one_over_sqrt_pi_prec(prec: u64) -> (Self, Ordering) { Self::one_over_sqrt_pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/one_over_sqrt_tau.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::ReciprocalSqrt; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $1/\sqrt{\tau}=1/\sqrt{2\pi}$, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 1/\sqrt{\tau}+\varepsilon=1/\sqrt{2\pi}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec_round(100, Floor); /// assert_eq!( /// one_over_sqrt_tau.to_string(), /// "0.3989422804014326779399460599341" /// ); /// assert_eq!(o, Less); /// /// let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec_round(100, Ceiling); /// assert_eq!( /// one_over_sqrt_tau.to_string(), /// "0.3989422804014326779399460599344" /// ); /// assert_eq!(o, Greater); /// ``` pub fn one_over_sqrt_tau_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let one_over_sqrt_tau = Self::tau_prec_round(working_prec, Floor) .0 .reciprocal_sqrt(); if float_can_round( one_over_sqrt_tau.significand_ref().unwrap(), working_prec - 2, prec, rm, ) { return Self::from_float_prec_round(one_over_sqrt_tau, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of $1/\sqrt{\tau}=1/\sqrt{2\pi}$, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// $$ /// x = 1/\sqrt{\tau}+\varepsilon=1/\sqrt{2\pi}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec(1); /// assert_eq!(one_over_sqrt_tau.to_string(), "0.5"); /// assert_eq!(o, Greater); /// /// let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec(10); /// assert_eq!(one_over_sqrt_tau.to_string(), "0.3989"); /// assert_eq!(o, Less); /// /// let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec(100); /// assert_eq!( /// one_over_sqrt_tau.to_string(), /// "0.3989422804014326779399460599344" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn one_over_sqrt_tau_prec(prec: u64) -> (Self, Ordering) { Self::one_over_sqrt_tau_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/phi.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering::{self, *}; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of the golden ratio, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// \varphi = \frac{1+\sqrt{2}}{2}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (phi, o) = Float::phi_prec_round(100, Floor); /// assert_eq!(phi.to_string(), "1.618033988749894848204586834364"); /// assert_eq!(o, Less); /// /// let (phi, o) = Float::phi_prec_round(100, Ceiling); /// assert_eq!(phi.to_string(), "1.618033988749894848204586834366"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn phi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { if prec == 1 { match rm { Floor | Down => (Self::ONE, Less), Ceiling | Up | Nearest => (Self::TWO, Greater), Exact => panic!("Inexact float square root"), } } else { let (sqrt_5, o) = Self::sqrt_prec_round(const { Self::const_from_unsigned(5) }, prec, rm); ((sqrt_5 + Self::ONE) >> 1u32, o) } } /// Returns an approximation of the golden ratio, with the given precision and rounded to the /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether /// the rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// \varphi = \frac{1+\sqrt{2}}{2}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (phi, o) = Float::phi_prec(1); /// assert_eq!(phi.to_string(), "2.0"); /// assert_eq!(o, Greater); /// /// let (phi, o) = Float::phi_prec(10); /// assert_eq!(phi.to_string(), "1.617"); /// assert_eq!(o, Less); /// /// let (phi, o) = Float::phi_prec(100); /// assert_eq!(phi.to_string(), "1.618033988749894848204586834366"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn phi_prec(prec: u64) -> (Self, Ordering) { Self::phi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{Sqrt, Square}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $\pi$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+2}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi, o) = Float::pi_prec_round(100, Floor); /// assert_eq!(pi.to_string(), "3.141592653589793238462643383279"); /// assert_eq!(o, Less); /// /// let (pi, o) = Float::pi_prec_round(100, Ceiling); /// assert_eq!(pi.to_string(), "3.141592653589793238462643383282"); /// assert_eq!(o, Greater); /// ``` /// // This is mpfr_const_pi_internal from const_pi.c, MPFR 4.2.0. #[inline] pub fn pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { // we need 9 * 2 ^ kmax - 4 >= px + 2 * kmax + 8 let mut kmax = 2; while ((prec + 2 * kmax + 12) / 9) >> kmax != 0 { kmax += 1; } // guarantees no recomputation for px <= 10000 let mut working_prec = prec + 3 * kmax + 14; let mut increment = Limb::WIDTH; loop { let mut a = Self::one_prec(working_prec); let mut big_a = a.clone(); let mut big_b = Self::one_half_prec(working_prec); let mut big_d = Self::one_prec(working_prec) >> 2; let mut k = 0; loop { let s = (&big_a + &big_b) >> 2; a = (a + big_b.sqrt()) >> 1; big_a = (&a).square(); big_b = (&big_a - s) << 1; let mut s = &big_a - &big_b; assert!(s < 1u32); let ip = i64::exact_from(working_prec); let cancel = if s == 0 { ip } else { i64::from(-s.get_exponent().unwrap()) }; s <<= k; big_d -= s; // stop when |A_k - B_k| <= 2 ^ (k - p) i.e. cancel >= p - k if cancel >= ip - i64::exact_from(k) { break; } k += 1; } let pi: Self = big_b / big_d; if float_can_round( pi.significand_ref().unwrap(), working_prec - (k << 1) - 8, prec, rm, ) { return Self::from_float_prec_round(pi, prec, rm); } working_prec += kmax + increment; increment = working_prec >> 1; } } /// Returns an approximation of $\pi$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p+1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi, o) = Float::pi_prec(1); /// assert_eq!(pi.to_string(), "4.0"); /// assert_eq!(o, Greater); /// /// let (pi, o) = Float::pi_prec(10); /// assert_eq!(pi.to_string(), "3.141"); /// assert_eq!(o, Less); /// /// let (pi, o) = Float::pi_prec(100); /// assert_eq!(pi.to_string(), "3.141592653589793238462643383279"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn pi_prec(prec: u64) -> (Self, Ordering) { Self::pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi_over_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $\pi/2$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/2+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_2, o) = Float::pi_over_2_prec_round(100, Floor); /// assert_eq!(pi_over_2.to_string(), "1.57079632679489661923132169164"); /// assert_eq!(o, Less); /// /// let (pi_over_2, o) = Float::pi_over_2_prec_round(100, Ceiling); /// assert_eq!(pi_over_2.to_string(), "1.570796326794896619231321691641"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_2_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::pi_prec_round(prec, rm); (pi >> 1u32, o) } /// Returns an approximation of $\pi/2$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/2+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_2, o) = Float::pi_over_2_prec(1); /// assert_eq!(pi_over_2.to_string(), "2.0"); /// assert_eq!(o, Greater); /// /// let (pi_over_2, o) = Float::pi_over_2_prec(10); /// assert_eq!(pi_over_2.to_string(), "1.57"); /// assert_eq!(o, Less); /// /// let (pi_over_2, o) = Float::pi_over_2_prec(100); /// assert_eq!(pi_over_2.to_string(), "1.57079632679489661923132169164"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn pi_over_2_prec(prec: u64) -> (Self, Ordering) { Self::pi_over_2_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi_over_3.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $\pi/3$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/3+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_3, o) = Float::pi_over_3_prec_round(100, Floor); /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461092"); /// assert_eq!(o, Less); /// /// let (pi_over_3, o) = Float::pi_over_3_prec_round(100, Ceiling); /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461094"); /// assert_eq!(o, Greater); /// ``` pub fn pi_over_3_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { const THREE: Float = Float::const_from_unsigned(3); let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_over_3 = Self::pi_prec(working_prec).0 / THREE; if float_can_round( pi_over_3.significand_ref().unwrap(), working_prec - 1, prec, rm, ) { return Self::from_float_prec_round(pi_over_3, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of $\pi/3$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/3+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_3, o) = Float::pi_over_3_prec(1); /// assert_eq!(pi_over_3.to_string(), "1.0"); /// assert_eq!(o, Less); /// /// let (pi_over_3, o) = Float::pi_over_3_prec(10); /// assert_eq!(pi_over_3.to_string(), "1.047"); /// assert_eq!(o, Less); /// /// let (pi_over_3, o) = Float::pi_over_3_prec(100); /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461094"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_3_prec(prec: u64) -> (Self, Ordering) { Self::pi_over_3_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi_over_4.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $\pi/4$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/4+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_4, o) = Float::pi_over_4_prec_round(100, Floor); /// assert_eq!(pi_over_4.to_string(), "0.78539816339744830961566084582"); /// assert_eq!(o, Less); /// /// let (pi_over_4, o) = Float::pi_over_4_prec_round(100, Ceiling); /// assert_eq!(pi_over_4.to_string(), "0.7853981633974483096156608458206"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_4_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::pi_prec_round(prec, rm); (pi >> 2u32, o) } /// Returns an approximation of $\pi/4$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/4+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_4, o) = Float::pi_over_4_prec(1); /// assert_eq!(pi_over_4.to_string(), "1.0"); /// assert_eq!(o, Greater); /// /// let (pi_over_4, o) = Float::pi_over_4_prec(10); /// assert_eq!(pi_over_4.to_string(), "0.785"); /// assert_eq!(o, Less); /// /// let (pi_over_4, o) = Float::pi_over_4_prec(100); /// assert_eq!(pi_over_4.to_string(), "0.78539816339744830961566084582"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn pi_over_4_prec(prec: u64) -> (Self, Ordering) { Self::pi_over_4_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi_over_6.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $\pi/6$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/6+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_6, o) = Float::pi_over_6_prec_round(100, Floor); /// assert_eq!(pi_over_6.to_string(), "0.523598775598298873077107230546"); /// assert_eq!(o, Less); /// /// let (pi_over_6, o) = Float::pi_over_6_prec_round(100, Ceiling); /// assert_eq!(pi_over_6.to_string(), "0.523598775598298873077107230547"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_6_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi_over_3, o) = Self::pi_over_3_prec_round(prec, rm); (pi_over_3 >> 1u32, o) } /// Returns an approximation of $\pi/6$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/6+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_6, o) = Float::pi_over_6_prec(1); /// assert_eq!(pi_over_6.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (pi_over_6, o) = Float::pi_over_6_prec(10); /// assert_eq!(pi_over_6.to_string(), "0.523"); /// assert_eq!(o, Less); /// /// let (pi_over_6, o) = Float::pi_over_6_prec(100); /// assert_eq!(pi_over_6.to_string(), "0.523598775598298873077107230547"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_6_prec(prec: u64) -> (Self, Ordering) { Self::pi_over_6_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/pi_over_8.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $\pi/8$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/8+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_8, o) = Float::pi_over_8_prec_round(100, Floor); /// assert_eq!(pi_over_8.to_string(), "0.3926990816987241548078304229099"); /// assert_eq!(o, Less); /// /// let (pi_over_8, o) = Float::pi_over_8_prec_round(100, Ceiling); /// assert_eq!(pi_over_8.to_string(), "0.3926990816987241548078304229103"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn pi_over_8_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::pi_prec_round(prec, rm); (pi >> 3u32, o) } /// Returns an approximation of $\pi/8$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \pi/8+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pi_over_8, o) = Float::pi_over_8_prec(1); /// assert_eq!(pi_over_8.to_string(), "0.5"); /// assert_eq!(o, Greater); /// /// let (pi_over_8, o) = Float::pi_over_8_prec(10); /// assert_eq!(pi_over_8.to_string(), "0.3926"); /// assert_eq!(o, Less); /// /// let (pi_over_8, o) = Float::pi_over_8_prec(100); /// assert_eq!(pi_over_8.to_string(), "0.3926990816987241548078304229099"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn pi_over_8_prec(prec: u64) -> (Self, Ordering) { Self::pi_over_8_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/prime_constant.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::factorization::primes::prime_indicator_sequence_less_than_or_equal_to; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of the prime constant, with the given precision and rounded using /// the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime. /// That is, /// $$ /// \rho = \sum_{p\ \text{prime}\}2^{-p}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational. It is unknown whether it is transcendental; see /// . /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pc, o) = Float::prime_constant_prec_round(100, Floor); /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542"); /// assert_eq!(o, Less); /// /// let (pc, o) = Float::prime_constant_prec_round(100, Ceiling); /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221546"); /// assert_eq!(o, Greater); /// ``` pub fn prime_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { // Strictly speaking, this call violates the preconditions for // `non_dyadic_from_bits_prec_round`, because the iterator passed in is finite. But since we // know exactly how many bits `non_dyadic_from_bits_prec_round` will read, we can get away // with this. Self::non_dyadic_from_bits_prec_round( prime_indicator_sequence_less_than_or_equal_to(if rm == Nearest { prec + 2 } else { prec + 1 }), prec, rm, ) } /// Returns an approximation of the prime constant, with the given precision and rounded to the /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether /// the rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime. /// That is, /// $$ /// \rho = \sum_{p\ \text{prime}\}2^{-p}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-2}$. /// /// The constant is irrational. It is unknown whether it is transcendental; see /// . /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (pc, o) = Float::prime_constant_prec(1); /// assert_eq!(pc.to_string(), "0.5"); /// assert_eq!(o, Greater); /// /// let (pc, o) = Float::prime_constant_prec(10); /// assert_eq!(pc.to_string(), "0.4146"); /// assert_eq!(o, Less); /// /// let (pc, o) = Float::prime_constant_prec(100); /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn prime_constant_prec(prec: u64) -> (Self, Ordering) { Self::prime_constant_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/prouhet_thue_morse_constant.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use alloc::vec; use core::cmp::Ordering::{self, *}; use malachite_base::iterators::thue_morse_sequence; use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::OneHalf; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::{Natural, bit_to_limb_count_ceiling}; use malachite_nz::platform::Limb; #[cfg(feature = "32_bit_limbs")] const LIMB_0: Limb = 0xd32d2cd2; #[cfg(feature = "32_bit_limbs")] const LIMB_1: Limb = 0x2cd2d32c; #[cfg(not(feature = "32_bit_limbs"))] const LIMB_0: Limb = 0xd32d2cd32cd2d32c; #[cfg(not(feature = "32_bit_limbs"))] const LIMB_1: Limb = 0x2cd2d32cd32d2cd2; impl Float { /// Returns an approximation of the Prouhet-Thue-Morse constant, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// The Prouhet-Thue-Morse constant is the real number whose bits are the Thue-Morse sequence. /// That is, /// $$ /// \tau = \sum_{k=0}^\infty\frac{t_n}{2^{n+1}}+\varepsilon, /// where $t_n$ is the Thue-Morse sequence. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-2}$. /// /// An alternative expression, from , is /// $$ /// \tau = \frac{1}{4}\left[2-\prod_{k=0}^\infty\left(1-\frac{1}{2^{2^k}}\right)\right]. /// $$ /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (tmc, o) = Float::prouhet_thue_morse_constant_prec_round(100, Floor); /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682584"); /// assert_eq!(o, Less); /// /// let (tmc, o) = Float::prouhet_thue_morse_constant_prec_round(100, Ceiling); /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682588"); /// assert_eq!(o, Greater); /// ``` pub fn prouhet_thue_morse_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); assert_ne!(rm, Exact); // If the result is 1/2 then the exponent is 0 rather than -1, so we handle that case // separately. if prec == 1 && (rm == Nearest || rm == Ceiling || rm == Up) { return (Self::ONE_HALF, Greater); } else if prec == 2 && (rm == Ceiling || rm == Up) { // TODO implement const_from_unsigned_prec_times_power_of_2 return (Self::one_half_prec(2), Greater); } let len = bit_to_limb_count_ceiling(prec); let mut limbs = vec![0; len]; let mut tms = thue_morse_sequence(); for (i, b) in (0..len).rev().zip(&mut tms) { limbs[i] = if b { limbs[i + 1] |= 1; LIMB_1 } else { LIMB_0 }; } let lsb = Limb::power_of_2(prec.neg_mod_power_of_2(Limb::LOG_WIDTH)); let mut next_tms = false; if lsb == 1 { next_tms = tms.next().unwrap(); if next_tms { limbs[0] |= 1; } } let increment = match rm { Up | Ceiling => true, Down | Floor => false, Nearest => match lsb { 1 => !next_tms, 2 => tms.next().unwrap(), _ => limbs[0] & (lsb >> 1) != 0, }, Exact => unreachable!(), }; limbs[0] &= !(lsb - 1); let mut significand = Natural::from_owned_limbs_asc(limbs); if increment { significand += Natural::from(lsb); } ( Self(Finite { sign: true, exponent: -1, precision: prec, significand, }), if increment { Greater } else { Less }, ) } /// Returns an approximation of the Prouhet-Thue-Morse constant, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// The Prouhet-Thue-Morse constant is the real number whose bits are the Thue-Morse sequence. /// That is, /// $$ /// \tau = \sum_{k=0}^\infty\frac{t_n}{2^{n+1}}+\varepsilon, /// $$ /// where $t_n$ is the Thue-Morse sequence. /// - $|\varepsilon| < 2^{-p-2}$. /// /// An alternative expression, from , is /// $$ /// \tau = \frac{1}{4}\left[2-\prod_{k=0}^\infty\left(1-\frac{1}{2^{2^k}}\right)\right]. /// $$ /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (tmc, o) = Float::prouhet_thue_morse_constant_prec(1); /// assert_eq!(tmc.to_string(), "0.5"); /// assert_eq!(o, Greater); /// /// let (tmc, o) = Float::prouhet_thue_morse_constant_prec(10); /// assert_eq!(tmc.to_string(), "0.4126"); /// assert_eq!(o, Greater); /// /// let (tmc, o) = Float::prouhet_thue_morse_constant_prec(100); /// assert_eq!(tmc.to_string(), "0.4124540336401075977833613682584"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn prouhet_thue_morse_constant_prec(prec: u64) -> (Self, Ordering) { Self::prouhet_thue_morse_constant_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/sqrt_2.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::basic::traits::Two; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of the square root of 2, with the given precision and rounded using /// the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{2}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_2, o) = Float::sqrt_2_prec_round(100, Floor); /// assert_eq!(sqrt_2.to_string(), "1.414213562373095048801688724209"); /// assert_eq!(o, Less); /// /// let (sqrt_2, o) = Float::sqrt_2_prec_round(100, Ceiling); /// assert_eq!(sqrt_2.to_string(), "1.414213562373095048801688724211"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_2_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { Self::sqrt_prec_round(Self::TWO, prec, rm) } /// Returns an approximation of the square root of 2, with the given precision and rounded to /// the nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{2}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_2, o) = Float::sqrt_2_prec(1); /// assert_eq!(sqrt_2.to_string(), "1.0"); /// assert_eq!(o, Less); /// /// let (sqrt_2, o) = Float::sqrt_2_prec(10); /// assert_eq!(sqrt_2.to_string(), "1.414"); /// assert_eq!(o, Less); /// /// let (sqrt_2, o) = Float::sqrt_2_prec(100); /// assert_eq!(sqrt_2.to_string(), "1.414213562373095048801688724209"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_2_prec(prec: u64) -> (Self, Ordering) { Self::sqrt_2_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/sqrt_2_over_2.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::basic::traits::Two; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of half of the square root of 2, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{2}/2+\varepsilon=\sqrt{1/2}+\varepsilon=1/\sqrt{2}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec_round(100, Floor); /// assert_eq!( /// sqrt_2_over_2.to_string(), /// "0.7071067811865475244008443621046" /// ); /// assert_eq!(o, Less); /// /// let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec_round(100, Ceiling); /// assert_eq!( /// sqrt_2_over_2.to_string(), /// "0.7071067811865475244008443621054" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_2_over_2_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (sqrt_2, o) = Self::sqrt_prec_round(Self::TWO, prec, rm); (sqrt_2 >> 1u32, o) } /// Returns an approximation of half of the square root of 2, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// $$ /// x = \sqrt{2}/2+\varepsilon=\sqrt{1/2}+\varepsilon=1/\sqrt{2}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec(1); /// assert_eq!(sqrt_2_over_2.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec(10); /// assert_eq!(sqrt_2_over_2.to_string(), "0.707"); /// assert_eq!(o, Less); /// /// let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec(100); /// assert_eq!( /// sqrt_2_over_2.to_string(), /// "0.7071067811865475244008443621046" /// ); /// assert_eq!(o, Less); /// ``` #[inline] pub fn sqrt_2_over_2_prec(prec: u64) -> (Self, Ordering) { Self::sqrt_2_over_2_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/sqrt_3.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of the square root of 3, with the given precision and rounded using /// the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{3}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_3, o) = Float::sqrt_3_prec_round(100, Floor); /// assert_eq!(sqrt_3.to_string(), "1.732050807568877293527446341505"); /// assert_eq!(o, Less); /// /// let (sqrt_3, o) = Float::sqrt_3_prec_round(100, Ceiling); /// assert_eq!(sqrt_3.to_string(), "1.732050807568877293527446341506"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_3_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { Self::sqrt_prec_round(const { Self::const_from_unsigned(3) }, prec, rm) } /// Returns an approximation of the square root of 3, with the given precision and rounded to /// the nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{3}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_3, o) = Float::sqrt_3_prec(1); /// assert_eq!(sqrt_3.to_string(), "2.0"); /// assert_eq!(o, Greater); /// /// let (sqrt_3, o) = Float::sqrt_3_prec(10); /// assert_eq!(sqrt_3.to_string(), "1.732"); /// assert_eq!(o, Greater); /// /// let (sqrt_3, o) = Float::sqrt_3_prec(100); /// assert_eq!(sqrt_3.to_string(), "1.732050807568877293527446341506"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_3_prec(prec: u64) -> (Self, Ordering) { Self::sqrt_3_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/sqrt_3_over_3.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of one third of the square root of 3, with the given precision and /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating /// whether the rounded value is less than or greater than the exact value of the constant. /// (Since the constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{3}/3+\varepsilon=\sqrt{1/3}+\varepsilon=1/\sqrt{3}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec_round(100, Floor); /// assert_eq!( /// sqrt_3_over_3.to_string(), /// "0.577350269189625764509148780501" /// ); /// assert_eq!(o, Less); /// /// let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec_round(100, Ceiling); /// assert_eq!( /// sqrt_3_over_3.to_string(), /// "0.577350269189625764509148780502" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_3_over_3_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { Self::reciprocal_sqrt_prec_round(const { Self::const_from_unsigned(3) }, prec, rm) } /// Returns an approximation of one third of the square root of 3, with the given precision and /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned, /// indicating whether the rounded value is less than or greater than the exact value of the /// constant. (Since the constant is irrational, the rounded value is never equal to the exact /// value.) /// /// $$ /// x = \sqrt{3}/3+\varepsilon=\sqrt{1/3}+\varepsilon=1/\sqrt{3}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and algebraic. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec(1); /// assert_eq!(sqrt_3_over_3.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec(10); /// assert_eq!(sqrt_3_over_3.to_string(), "0.577"); /// assert_eq!(o, Less); /// /// let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec(100); /// assert_eq!( /// sqrt_3_over_3.to_string(), /// "0.577350269189625764509148780502" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_3_over_3_prec(prec: u64) -> (Self, Ordering) { Self::sqrt_3_over_3_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/sqrt_pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::Sqrt; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::arithmetic::float_extras::float_can_round; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of $\sqrt{\pi}$, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{\pi}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_pi, o) = Float::sqrt_pi_prec_round(100, Floor); /// assert_eq!(sqrt_pi.to_string(), "1.77245385090551602729816748334"); /// assert_eq!(o, Less); /// /// let (sqrt_pi, o) = Float::sqrt_pi_prec_round(100, Ceiling); /// assert_eq!(sqrt_pi.to_string(), "1.772453850905516027298167483341"); /// assert_eq!(o, Greater); /// ``` pub fn sqrt_pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let sqrt_pi = Self::pi_prec_round(working_prec, Floor).0.sqrt(); // See algorithms.tex. Since we rounded down when computing pi, the absolute error of // the square root is bounded by (c_sqrt + k_fx)ulp(sqrt) <= 2ulp(sqrt). if float_can_round( sqrt_pi.significand_ref().unwrap(), working_prec - 1, prec, rm, ) { return Self::from_float_prec_round(sqrt_pi, prec, rm); } working_prec += increment; increment = working_prec >> 1; } } /// Returns an approximation of $\sqrt{\pi}$, with the given precision and rounded to the /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether /// the rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \sqrt{\pi}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (sqrt_pi, o) = Float::sqrt_pi_prec(1); /// assert_eq!(sqrt_pi.to_string(), "2.0"); /// assert_eq!(o, Greater); /// /// let (sqrt_pi, o) = Float::sqrt_pi_prec(10); /// assert_eq!(sqrt_pi.to_string(), "1.771"); /// assert_eq!(o, Less); /// /// let (sqrt_pi, o) = Float::sqrt_pi_prec(100); /// assert_eq!(sqrt_pi.to_string(), "1.772453850905516027298167483341"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn sqrt_pi_prec(prec: u64) -> (Self, Ordering) { Self::sqrt_pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/tau.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $\tau=2\pi$, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \tau=2\pi+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+3}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p+2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (tau, o) = Float::tau_prec_round(100, Floor); /// assert_eq!(tau.to_string(), "6.283185307179586476925286766559"); /// assert_eq!(o, Less); /// /// let (tau, o) = Float::tau_prec_round(100, Ceiling); /// assert_eq!(tau.to_string(), "6.283185307179586476925286766565"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn tau_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::pi_prec_round(prec, rm); (pi << 1u32, o) } /// Returns an approximation of $\tau=2\pi$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = \tau=2\pi+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p+2}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (tau, o) = Float::tau_prec(1); /// assert_eq!(tau.to_string(), "8.0"); /// assert_eq!(o, Greater); /// /// let (tau, o) = Float::tau_prec(10); /// assert_eq!(tau.to_string(), "6.28"); /// assert_eq!(o, Less); /// /// let (tau, o) = Float::tau_prec(100); /// assert_eq!(tau.to_string(), "6.283185307179586476925286766559"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn tau_prec(prec: u64) -> (Self, Ordering) { Self::tau_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/two_over_pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $2/\pi$, with the given precision and rounded using the given /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is /// less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 2/\pi+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (two_over_pi, o) = Float::two_over_pi_prec_round(100, Floor); /// assert_eq!(two_over_pi.to_string(), "0.63661977236758134307553505349"); /// assert_eq!(o, Less); /// /// let (two_over_pi, o) = Float::two_over_pi_prec_round(100, Ceiling); /// assert_eq!(two_over_pi.to_string(), "0.6366197723675813430755350534906"); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn two_over_pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::one_over_pi_prec_round(prec, rm); (pi << 1u32, o) } /// Returns an approximation of $2/\pi$, with the given precision and rounded to the nearest /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the /// rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 2/\pi+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p-1}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (two_over_pi, o) = Float::two_over_pi_prec(1); /// assert_eq!(two_over_pi.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (two_over_pi, o) = Float::two_over_pi_prec(10); /// assert_eq!(two_over_pi.to_string(), "0.637"); /// assert_eq!(o, Greater); /// /// let (two_over_pi, o) = Float::two_over_pi_prec(100); /// assert_eq!(two_over_pi.to_string(), "0.63661977236758134307553505349"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn two_over_pi_prec(prec: u64) -> (Self, Ordering) { Self::two_over_pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/constants/two_over_sqrt_pi.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 1999, 2001-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::Float; use core::cmp::Ordering; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Float { /// Returns an approximation of $2/\sqrt{pi}$, with the given precision and rounded using the /// given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded /// value is less than or greater than the exact value of the constant. (Since the constant is /// irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 2/\sqrt{pi}+\varepsilon. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or if `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec_round(100, Floor); /// assert_eq!( /// two_over_sqrt_pi.to_string(), /// "1.12837916709551257389615890312" /// ); /// assert_eq!(o, Less); /// /// let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec_round(100, Ceiling); /// assert_eq!( /// two_over_sqrt_pi.to_string(), /// "1.128379167095512573896158903122" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn two_over_sqrt_pi_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) { let (pi, o) = Self::one_over_sqrt_pi_prec_round(prec, rm); (pi << 1u32, o) } /// Returns an approximation of $2/\sqrt{pi}$, with the given precision and rounded to the /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether /// the rounded value is less than or greater than the exact value of the constant. (Since the /// constant is irrational, the rounded value is never equal to the exact value.) /// /// $$ /// x = 2/\sqrt{pi}+\varepsilon. /// $$ /// - $|\varepsilon| < 2^{-p}$. /// /// The constant is irrational and transcendental. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n (\log n)^2)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec(1); /// assert_eq!(two_over_sqrt_pi.to_string(), "1.0"); /// assert_eq!(o, Less); /// /// let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec(10); /// assert_eq!(two_over_sqrt_pi.to_string(), "1.129"); /// assert_eq!(o, Greater); /// /// let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec(100); /// assert_eq!( /// two_over_sqrt_pi.to_string(), /// "1.128379167095512573896158903122" /// ); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn two_over_sqrt_pi_prec(prec: u64) -> (Self, Ordering) { Self::two_over_sqrt_pi_prec_round(prec, Nearest) } } ================================================ FILE: malachite-float/src/conversion/from_bits.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use alloc::vec; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, NegModPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::LIMB_HIGH_BIT; use malachite_nz::natural::{Natural, bit_to_limb_count_ceiling}; use malachite_nz::platform::Limb; impl Float { /// Returns an approximation of a real number, given the number's bits. To avoid troublesome /// edge cases, the number should not be a dyadic rational (and the iterator of bits should /// therefore be infinite, and not eventually 0 or 1). Given this assumption, the rounding mode /// `Exact` should never be passed. /// /// The approximation has precision `prec` and is rounded according to the provided rounding /// mode. /// /// This function reads `prec + z` bits, or `prec + z + 1` bits if `rm` is `Nearest`, where `z` /// is the number of leading false bits in `bits`. /// /// This function always produces a value in the interval $[1/2,1]$. In particular, it never /// overflows or underflows. /// /// $$ /// f((x_k),p,m) = C+\varepsilon, /// $$ /// where /// $$ /// C=\sum_{k=0}^\infty x_k 2^{-(k+1)}. /// $$ /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p+1}$. /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero or `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// // Produces 10100100010000100000... /// struct Bits { /// b: bool, /// k: usize, /// j: usize, /// } /// /// impl Iterator for Bits { /// type Item = bool; /// /// fn next(&mut self) -> Option { /// Some(if self.b { /// self.b = false; /// self.j = self.k; /// true /// } else { /// self.j -= 1; /// if self.j == 0 { /// self.k += 1; /// self.b = true; /// } /// false /// }) /// } /// } /// /// impl Bits { /// fn new() -> Bits { /// Bits { /// b: true, /// k: 1, /// j: 1, /// } /// } /// } /// /// let (c, o) = Float::non_dyadic_from_bits_prec_round(Bits::new(), 100, Floor); /// assert_eq!(c.to_string(), "0.6416325606551538662938427702254"); /// assert_eq!(o, Less); /// /// let (c, o) = Float::non_dyadic_from_bits_prec_round(Bits::new(), 100, Ceiling); /// assert_eq!(c.to_string(), "0.641632560655153866293842770226"); /// assert_eq!(o, Greater); /// ``` pub fn non_dyadic_from_bits_prec_round>( mut bits: I, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { assert_ne!(prec, 0); assert_ne!(rm, Exact); let len = bit_to_limb_count_ceiling(prec); let mut limbs = vec![0; len]; let mut limbs_it = limbs.iter_mut().rev(); let mut x = limbs_it.next().unwrap(); let mut mask = LIMB_HIGH_BIT; let mut seen_one = false; let mut exponent: i32 = 0; let mut remaining = prec; for b in &mut bits { if !seen_one { if b { seen_one = true; } else { exponent = exponent.checked_sub(1).unwrap(); continue; } } if b { *x |= mask; } remaining -= 1; if remaining == 0 { break; } if mask == 1 { x = limbs_it.next().unwrap(); mask = LIMB_HIGH_BIT; } else { mask >>= 1; } } let mut significand = Natural::from_owned_limbs_asc(limbs); let increment = rm == Up || rm == Ceiling || (rm == Nearest && bits.next() == Some(true)); if increment { significand += Natural::from(Limb::power_of_2(prec.neg_mod_power_of_2(Limb::LOG_WIDTH))); if !significand .significant_bits() .divisible_by_power_of_2(Limb::LOG_WIDTH) { significand >>= 1; exponent += 1; } } ( Self(Finite { sign: true, exponent, precision: prec, significand, }), if increment { Greater } else { Less }, ) } /// Returns an approximation of a real number, given the number's bits. To avoid troublesome /// edge cases, the number should not be a dyadic rational (and the iterator of bits should /// therefore be infinite, and not eventually 0 or 1). /// /// The approximation has precision `prec` and is rounded according to the `Nearest` rounding /// mode. /// /// This function reads `prec + z + 1` bits, where `z` is the number of leading false bits in /// `bits`. /// /// This function always produces a value in the interval $[1/2,1]$. In particular, it never /// overflows or underflows. /// /// $$ /// f((x_k),p,m) = C+\varepsilon, /// $$ /// where /// $$ /// C=\sum_{k=0}^\infty x_k 2^{-(k+1)} /// $$ /// and $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$. /// /// The output has precision `prec`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// // Produces 10100100010000100000... /// struct Bits { /// b: bool, /// k: usize, /// j: usize, /// } /// /// impl Iterator for Bits { /// type Item = bool; /// /// fn next(&mut self) -> Option { /// Some(if self.b { /// self.b = false; /// self.j = self.k; /// true /// } else { /// self.j -= 1; /// if self.j == 0 { /// self.k += 1; /// self.b = true; /// } /// false /// }) /// } /// } /// /// impl Bits { /// fn new() -> Bits { /// Bits { /// b: true, /// k: 1, /// j: 1, /// } /// } /// } /// /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 1); /// assert_eq!(c.to_string(), "0.5"); /// assert_eq!(o, Less); /// /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 10); /// assert_eq!(c.to_string(), "0.642"); /// assert_eq!(o, Less); /// /// let (c, o) = Float::non_dyadic_from_bits_prec(Bits::new(), 100); /// assert_eq!(c.to_string(), "0.6416325606551538662938427702254"); /// assert_eq!(o, Less); /// ``` #[inline] pub fn non_dyadic_from_bits_prec>( bits: I, prec: u64, ) -> (Self, Ordering) { Self::non_dyadic_from_bits_prec_round(bits, prec, Nearest) } } ================================================ FILE: malachite-float/src/conversion/from_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::conversion::from_natural::{ from_natural_prec_round_zero_exponent, from_natural_zero_exponent, }; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{FloorLogBase2, UnsignedAbs}; use malachite_base::num::conversion::traits::{ConvertibleFrom, SaturatingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; pub(crate) fn from_integer_zero_exponent(n: Integer) -> Float { let sign = n >= 0; let f = from_natural_zero_exponent(n.unsigned_abs()); if sign { f } else { -f } } pub(crate) fn from_integer_prec_round_zero_exponent( x: Integer, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { let sign = x >= 0; let (f, o) = from_natural_prec_round_zero_exponent(x.unsigned_abs(), prec, if sign { rm } else { -rm }); if sign { (f, o) } else { (-f, o.reverse()) } } impl Float { /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by value. If the [`Float`] is /// nonzero, it has the specified precision. If rounding is needed, the specified rounding mode /// is used. An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_integer_prec`] instead. /// /// - If the [`Integer`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Integer`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this function /// overflows to $-\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds up to /// $-(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Integer` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_integer_prec_round(Integer::ZERO, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(123), 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(123), 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(123), 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(-123), 20, Exact); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(-123), 4, Floor); /// assert_eq!(x.to_string(), "-1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec_round(Integer::from(-123), 4, Ceiling); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_integer_prec_round(x: Integer, prec: u64, rm: RoundingMode) -> (Self, Ordering) { let sign = x >= 0; let (f, o) = Self::from_natural_prec_round(x.unsigned_abs(), prec, if sign { rm } else { -rm }); if sign { (f, o) } else { (-f, o.reverse()) } } /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by reference. If the /// [`Float`] is nonzero, it has the specified precision. If rounding is needed, the specified /// rounding mode is used. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_integer_prec_ref`] instead. /// /// - If the [`Integer`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Integer`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this function /// overflows to $-\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds up to /// $-(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Integer` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::ZERO, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(123), 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(123), 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(123), 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(-123), 20, Exact); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(-123), 4, Floor); /// assert_eq!(x.to_string(), "-1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec_round_ref(&Integer::from(-123), 4, Ceiling); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_integer_prec_round_ref( x: &Integer, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { let sign = *x >= 0; let (f, o) = Self::from_natural_prec_round_ref( x.unsigned_abs_ref(), prec, if sign { rm } else { -rm }, ); if sign { (f, o) } else { (-f, o.reverse()) } } /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by value. If the [`Float`] is /// nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// If you want the [`Float`]'s precision to be equal to the [`Integer`]'s number of significant /// bits, try just using `Float::try_from` instead. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_integer_prec_round`]. /// /// - If the [`Integer`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// - If the [`Integer`] rounds to a value less than or equal to -$2^{2^{30}-1}$), this function /// overflows to $\infty$. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_integer_prec(Integer::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec(Integer::from(123), 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec(Integer::from(123), 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec(Integer::from(-123), 20); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec(Integer::from(-123), 4); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_integer_prec(x: Integer, prec: u64) -> (Self, Ordering) { Self::from_integer_prec_round(x, prec, Nearest) } /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by reference. If the /// [`Float`] is nonzero, it has the specified precision. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the original /// value. /// /// If you want the [`Float`]'s precision to be equal to the [`Integer`]'s number of significant /// bits, try just using `Float::try_from` instead. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_integer_prec_round_ref`]. /// /// - If the [`Integer`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// - If the [`Integer`] rounds to a value less than or equal to -$2^{2^{30}-1}$), this function /// overflows to $\infty$. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_integer_prec_ref(&Integer::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_ref(&Integer::from(123), 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_ref(&Integer::from(123), 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_integer_prec_ref(&Integer::from(-123), 20); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_integer_prec_ref(&Integer::from(-123), 4); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_integer_prec_ref(x: &Integer, prec: u64) -> (Self, Ordering) { let sign = *x >= 0; let (f, o) = Self::from_natural_prec_ref(x.unsigned_abs_ref(), prec); if sign { (f, o) } else { (-f, o.reverse()) } } } impl TryFrom for Float { type Error = FloatConversionError; /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by value. /// /// If the [`Integer`] is nonzero, the precision of the [`Float`] is the minimum possible /// precision to represent the [`Integer`] exactly. If you want to specify some other precision, /// try [`Float::from_integer_prec`]. This may require rounding, which uses [`Nearest`] by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_integer_prec_round`]. /// /// If the absolue value of the [`Integer`] is greater than or equal to $2^{2^{30}-1}$, this /// function returns an overflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Float::try_from(Integer::ZERO).unwrap().to_string(), "0.0"); /// assert_eq!( /// Float::try_from(Integer::from(123)).unwrap().to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::try_from(Integer::from(123)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(Integer::from(10)).unwrap().to_string(), /// "10.0" /// ); /// assert_eq!( /// Float::try_from(Integer::from(10)).unwrap().get_prec(), /// Some(3) /// ); /// assert_eq!( /// Float::try_from(Integer::from(-123)).unwrap().to_string(), /// "-123.0" /// ); /// assert_eq!( /// Float::try_from(Integer::from(-123)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(Integer::from(-10)).unwrap().to_string(), /// "-10.0" /// ); /// assert_eq!( /// Float::try_from(Integer::from(-10)).unwrap().get_prec(), /// Some(3) /// ); /// ``` #[inline] fn try_from(n: Integer) -> Result { let sign = n >= 0; let abs = Self::try_from(n.unsigned_abs())?; Ok(if sign { abs } else { -abs }) } } impl TryFrom<&Integer> for Float { type Error = FloatConversionError; /// Converts an [`Integer`] to a [`Float`], taking the [`Integer`] by reference. /// /// If the [`Integer`] is nonzero, the precision of the [`Float`] is the minimum possible /// precision to represent the [`Integer`] exactly. If you want to specify some other precision, /// try [`Float::from_integer_prec`]. This may require rounding, which uses [`Nearest`] by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_integer_prec_round`]. /// /// If the absolue value of the [`Integer`] is greater than or equal to $2^{2^{30}-1}$, this /// function returns an overflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Float::try_from(&Integer::ZERO).unwrap().to_string(), "0.0"); /// assert_eq!( /// Float::try_from(&Integer::from(123)).unwrap().to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::try_from(&Integer::from(123)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(&Integer::from(10)).unwrap().to_string(), /// "10.0" /// ); /// assert_eq!( /// Float::try_from(&Integer::from(10)).unwrap().get_prec(), /// Some(3) /// ); /// assert_eq!( /// Float::try_from(&Integer::from(-123)).unwrap().to_string(), /// "-123.0" /// ); /// assert_eq!( /// Float::try_from(&Integer::from(-123)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(&Integer::from(-10)).unwrap().to_string(), /// "-10.0" /// ); /// assert_eq!( /// Float::try_from(&Integer::from(-10)).unwrap().get_prec(), /// Some(3) /// ); /// ``` #[inline] fn try_from(n: &Integer) -> Result { let sign = *n >= 0; let abs = Self::try_from(n.unsigned_abs())?; Ok(if sign { abs } else { -abs }) } } impl ConvertibleFrom<&Integer> for Float { /// Determines whether an [`Integer`] can be converted to an [`Float`], taking the [`Integer`] /// by reference. /// /// The [`Integer`]s that are convertible to [`Float`]s are those whose that would not overflow: /// that is, those whose absolute values are less than $2^{2^{30}-1}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Float::convertible_from(&Integer::ZERO), true); /// assert_eq!(Float::convertible_from(&Integer::from(3u8)), true); /// ``` #[inline] fn convertible_from(x: &Integer) -> bool { *x == 0 || (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains( &i32::saturating_from(x.unsigned_abs_ref().floor_log_base_2()).saturating_add(1), ) } } ================================================ FILE: malachite-float/src/conversion/from_natural.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ DivisibleByPowerOf2, FloorLogBase2, ModPowerOf2, NegModPowerOf2, PowerOf2, RoundToMultipleOfPowerOf2Assign, SaturatingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, Zero}; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::{Natural, bit_to_limb_count_ceiling}; use malachite_nz::platform::Limb; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; fn from_natural_prec_round_helper( x: &Natural, prec: u64, rm: RoundingMode, bits: u64, ) -> (Float, Ordering) { if *x == 0 { return (Float::ZERO, Equal); } let mut exponent = i32::saturating_from(bits); if exponent > Float::MAX_EXPONENT { return match rm { Up | Ceiling | Nearest => (Float::INFINITY, Greater), Floor | Down => (Float::max_finite_value_with_prec(prec), Less), Exact => panic!("Inexact conversion from Natural to Float"), }; } let mut needed_bits = prec; let sig_bits_in_highest_limb = bits.mod_power_of_2(Limb::LOG_WIDTH); let mut needed_limbs = 1; needed_bits.saturating_sub_assign(sig_bits_in_highest_limb); if needed_bits != 0 { needed_limbs += bit_to_limb_count_ceiling(needed_bits); } let mut rev_limbs = x.limbs().rev(); let mut significand = Natural::from_owned_limbs_desc( (&mut rev_limbs) .take(usize::exact_from(needed_limbs)) .collect(), ); significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); let mut mask_width = significand.significant_bits() - prec; let mut erased_limb = 0; if mask_width >= Limb::WIDTH { erased_limb = significand.limbs()[0]; significand >>= Limb::WIDTH; mask_width -= Limb::WIDTH; } let o = match rm { Exact => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); assert!(!inexact, "Inexact conversion from Natural"); Equal } Floor | Down => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); if inexact { significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); Less } else { Equal } } Ceiling | Up => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); if inexact { let original_limb_count = significand.limb_count(); significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); significand += Natural::power_of_2(mask_width); if significand.limb_count() > original_limb_count { if exponent == Float::MAX_EXPONENT { return (Float::INFINITY, Greater); } significand >>= 1; exponent += 1; } Greater } else { Equal } } Nearest => { let half_bit = x.get_bit(bits - prec - 1); let inexact_after_half = !x.divisible_by_power_of_2(bits - prec - 1); let inexact = half_bit || inexact_after_half; if half_bit && (inexact_after_half || x.get_bit(bits - prec)) { let original_limb_count = significand.limb_count(); significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); significand += Natural::power_of_2(mask_width); if significand.limb_count() > original_limb_count { if exponent == Float::MAX_EXPONENT { return (Float::INFINITY, Greater); } significand >>= 1; exponent += 1; } Greater } else if inexact { significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); Less } else { Equal } } }; ( Float(Finite { sign: true, exponent, precision: prec, significand, }), o, ) } fn from_natural_prec_round_helper_zero_exponent( x: &Natural, prec: u64, rm: RoundingMode, bits: u64, ) -> (Float, Ordering) { let mut needed_bits = prec; let sig_bits_in_highest_limb = bits.mod_power_of_2(Limb::LOG_WIDTH); let mut needed_limbs = 1; needed_bits.saturating_sub_assign(sig_bits_in_highest_limb); if needed_bits != 0 { needed_limbs += bit_to_limb_count_ceiling(needed_bits); } let mut rev_limbs = x.limbs().rev(); let mut significand = Natural::from_owned_limbs_desc((&mut rev_limbs).take(needed_limbs).collect()); significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); let mut mask_width = significand.significant_bits() - prec; let mut erased_limb = 0; if mask_width >= Limb::WIDTH { erased_limb = significand.limbs()[0]; significand >>= Limb::WIDTH; mask_width -= Limb::WIDTH; } let mut exponent = 0; let o = match rm { Exact => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); assert!(!inexact, "Inexact conversion from Natural"); Equal } Floor | Down => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); if inexact { significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); Less } else { Equal } } Ceiling | Up => { let inexact = erased_limb != 0 || !significand.divisible_by_power_of_2(mask_width) || rev_limbs.any(|y| y != 0); if inexact { let original_limb_count = significand.limb_count(); significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); significand += Natural::power_of_2(mask_width); if significand.limb_count() > original_limb_count { significand >>= 1; exponent += 1; } Greater } else { Equal } } Nearest => { let half_bit = x.get_bit(bits - prec - 1); let inexact_after_half = !x.divisible_by_power_of_2(bits - prec - 1); let inexact = half_bit || inexact_after_half; if half_bit && (inexact_after_half || x.get_bit(bits - prec)) { let original_limb_count = significand.limb_count(); significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); significand += Natural::power_of_2(mask_width); if significand.limb_count() > original_limb_count { significand >>= 1; exponent += 1; } Greater } else if inexact { significand.round_to_multiple_of_power_of_2_assign(mask_width, Floor); Less } else { Equal } } }; ( Float(Finite { sign: true, exponent, precision: prec, significand, }), o, ) } fn from_natural_prec_round_helper_no_round_zero_exponent( x: &Natural, prec: u64, bits: u64, ) -> Float { let mut needed_bits = prec; let sig_bits_in_highest_limb = bits.mod_power_of_2(Limb::LOG_WIDTH); let mut needed_limbs = 1; needed_bits.saturating_sub_assign(sig_bits_in_highest_limb); if needed_bits != 0 { needed_limbs += bit_to_limb_count_ceiling(needed_bits); } let mut rev_limbs = x.limbs().rev(); let mut significand = Natural::from_owned_limbs_desc((&mut rev_limbs).take(needed_limbs).collect()); significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); if significand.significant_bits() - prec >= Limb::WIDTH { significand >>= Limb::WIDTH; } Float(Finite { sign: true, exponent: 0, precision: prec, significand, }) } pub(crate) fn from_natural_prec_round_zero_exponent( x: Natural, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if x == 0u32 { return (Float::ZERO, Equal); } let bits = x.significant_bits(); let mut f = Float(Finite { sign: true, exponent: 0, precision: bits, significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), }); let o = f.set_prec_round(prec, rm); (f, o) } pub(crate) fn from_natural_prec_round_zero_exponent_ref( x: &Natural, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); if *x == 0u32 { return (Float::ZERO, Equal); } let bits = x.significant_bits(); if bits <= prec { let mut f = Float(Finite { sign: true, exponent: 0, precision: bits, significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), }); let o = f.set_prec_round(prec, rm); (f, o) } else { from_natural_prec_round_helper_zero_exponent(x, prec, rm, bits) } } pub(crate) fn from_natural_zero_exponent(x: Natural) -> Float { if x == 0 { Float::ZERO } else { let bits = x.significant_bits(); let prec = bits - x.trailing_zeros().unwrap(); from_natural_prec_round_zero_exponent(x, prec, Floor).0 } } pub(crate) fn from_natural_zero_exponent_ref(x: &Natural) -> Float { if *x == 0 { Float::ZERO } else { let bits = x.significant_bits(); let prec = bits - x.trailing_zeros().unwrap(); from_natural_prec_round_helper_no_round_zero_exponent(x, prec, bits) } } impl Float { /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. If the [`Float`] is /// nonzero, it has the specified precision. If rounding is needed, the specified rounding mode /// is used. An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_natural_prec`] instead. /// /// - If the [`Natural`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Natural` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_natural_prec_round(Natural::ZERO, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_round(Natural::from(123u32), 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_round(Natural::from(123u32), 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_natural_prec_round(Natural::from(123u32), 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_natural_prec_round(x: Natural, prec: u64, rm: RoundingMode) -> (Self, Ordering) { assert_ne!(prec, 0); if x == 0u32 { return (Self::ZERO, Equal); } let bits = x.significant_bits(); let bits_i32 = i32::saturating_from(bits); if bits_i32 <= Self::MAX_EXPONENT { let mut f = Self(Finite { sign: true, exponent: bits_i32, precision: bits, significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), }); let o = f.set_prec_round(prec, rm); return (f, o); } match rm { Up | Ceiling | Nearest => (Self::INFINITY, Greater), Floor | Down => (Self::max_finite_value_with_prec(prec), Less), Exact => panic!("Inexact conversion from Natural to Float"), } } /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. If the [`Float`] /// is nonzero, it has the specified precision. If rounding is needed, the specified rounding /// mode is used. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_natural_prec_ref`] instead. /// /// - If the [`Natural`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Natural` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::ZERO, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_natural_prec_round_ref(&Natural::from(123u32), 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` #[inline] pub fn from_natural_prec_round_ref( x: &Natural, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { assert_ne!(prec, 0); if *x == 0u32 { return (Self::ZERO, Equal); } let bits = x.significant_bits(); if bits <= prec { let bits_i32 = i32::saturating_from(bits); if bits_i32 <= Self::MAX_EXPONENT { let mut f = Self(Finite { sign: true, exponent: bits_i32, precision: bits, significand: x << bits.neg_mod_power_of_2(Limb::LOG_WIDTH), }); let o = f.set_prec_round(prec, rm); return (f, o); } match rm { Up | Ceiling | Nearest => (Self::INFINITY, Greater), Floor | Down => (Self::max_finite_value_with_prec(prec), Less), Exact => panic!("Inexact conversion from Natural to Float"), } } else { from_natural_prec_round_helper(x, prec, rm, bits) } } /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. If the [`Float`] is /// nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// If you want the [`Float`]'s precision to be equal to the [`Natural`]'s number of significant /// bits, try just using `Float::try_from` instead. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_natural_prec_round`]. /// /// - If the [`Natural`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_natural_prec(Natural::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec(Natural::from(123u32), 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_natural_prec(x: Natural, prec: u64) -> (Self, Ordering) { Self::from_natural_prec_round(x, prec, Nearest) } /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. If the [`Float`] /// is nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// If you want the [`Float`]'s precision to be equal to the [`Natural`]'s number of significant /// bits, try just using `Float::try_from` instead. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_natural_prec_round_ref`]. /// /// - If the [`Natural`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// /// # Worst-case complexity /// $T(m,n) = O(\max(m,n))$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $m$ is `n.significant_bits()`, and $n$ is /// `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_natural_prec_ref(&Natural::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_ref(&Natural::from(123u32), 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_natural_prec_ref(&Natural::from(123u32), 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_natural_prec_ref(x: &Natural, prec: u64) -> (Self, Ordering) { Self::from_natural_prec_round_ref(x, prec, Nearest) } } impl TryFrom for Float { type Error = FloatConversionError; /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by value. /// /// If the [`Natural`] is nonzero, the precision of the [`Float`] is the minimum possible /// precision to represent the [`Natural`] exactly. If you want to specify some other precision, /// try [`Float::from_natural_prec`]. This may require rounding, which uses [`Nearest`] by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_natural_prec_round`]. /// /// If the [`Natural`] is greater than or equal to $2^{2^{30}-1}$, this function returns an /// overflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::try_from(Natural::ZERO).unwrap().to_string(), "0.0"); /// assert_eq!( /// Float::try_from(Natural::from(123u32)).unwrap().to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::try_from(Natural::from(123u32)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(Natural::from(10u32)).unwrap().to_string(), /// "10.0" /// ); /// assert_eq!( /// Float::try_from(Natural::from(10u32)).unwrap().get_prec(), /// Some(3) /// ); /// ``` fn try_from(x: Natural) -> Result { if x == 0 { Ok(Self::ZERO) } else { let bits = x.significant_bits(); let prec = bits - x.trailing_zeros().unwrap(); let (f, o) = Self::from_natural_prec_round(x, prec, Floor); if o == Equal { Ok(f) } else { Err(FloatConversionError::Overflow) } } } } impl TryFrom<&Natural> for Float { type Error = FloatConversionError; /// Converts a [`Natural`] to a [`Float`], taking the [`Natural`] by reference. /// /// If the [`Natural`] is nonzero, the precision of the [`Float`] is the minimum possible /// precision to represent the [`Natural`] exactly. If you want to specify some other precision, /// try [`Float::from_natural_prec`]. This may require rounding, which uses [`Nearest`] by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_natural_prec_round`]. /// /// If the [`Natural`] is greater than or equal to $2^{2^{30}-1}$, this function returns an /// overflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::try_from(&Natural::ZERO).unwrap().to_string(), "0.0"); /// assert_eq!( /// Float::try_from(&Natural::from(123u32)).unwrap().to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::try_from(&Natural::from(123u32)).unwrap().get_prec(), /// Some(7) /// ); /// assert_eq!( /// Float::try_from(&Natural::from(10u32)).unwrap().to_string(), /// "10.0" /// ); /// assert_eq!( /// Float::try_from(&Natural::from(10u32)).unwrap().get_prec(), /// Some(3) /// ); /// ``` #[inline] fn try_from(x: &Natural) -> Result { if *x == 0 { Ok(Self::ZERO) } else { let bits = x.significant_bits(); let prec = bits - x.trailing_zeros().unwrap(); let (f, o) = Self::from_natural_prec_round_ref(x, prec, Floor); if o == Equal { Ok(f) } else { Err(FloatConversionError::Overflow) } } } } impl ConvertibleFrom<&Natural> for Float { /// Determines whether a [`Natural`] can be converted to an [`Float`], taking the [`Natural`] by /// reference. /// /// The [`Natural`]s that are convertible to [`Float`]s are those whose that would not overflow: /// that is, those that are less than $2^{2^{30}-1}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Float::convertible_from(&Natural::ZERO), true); /// assert_eq!(Float::convertible_from(&Natural::from(3u8)), true); /// ``` #[inline] fn convertible_from(x: &Natural) -> bool { *x == 0 || (Self::MIN_EXPONENT..=Self::MAX_EXPONENT) .contains(&i32::saturating_from(x.floor_log_base_2()).saturating_add(1)) } } ================================================ FILE: malachite-float/src/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Float; use core::cmp::Ordering::{self, *}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; use malachite_base::rounding_modes::RoundingMode; impl Float { /// Converts a primitive float to a [`Float`]. If the [`Float`] is nonzero and finite, it has /// the specified precision. If rounding is needed, the specified rounding mode is used. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, /// or greater than the original value. (Although a NaN is not comparable to any [`Float`], /// converting a NaN to a NaN will also return `Equal`, indicating an exact conversion.) /// /// If you're only using `Nearest`, try using [`Float::from_primitive_float_prec`] instead. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec, x.sci_exponent().abs())`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the primitive float cannot be exactly /// represented with the specified precision. /// /// # Examples /// See [here](super::from_primitive_float#from_primitive_float_prec_round). #[inline] pub fn from_primitive_float_prec_round( x: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { assert_ne!(prec, 0); if x.is_nan() { (Self::NAN, Equal) } else if !x.is_finite() { if x.is_sign_positive() { (Self::INFINITY, Equal) } else { (Self::NEGATIVE_INFINITY, Equal) } } else if x == T::ZERO { if x.is_sign_positive() { (Self::ZERO, Equal) } else { (Self::NEGATIVE_ZERO, Equal) } } else { let (m, e) = x.integer_mantissa_and_exponent(); if x.is_sign_positive() { let (f, o) = Self::from_unsigned_prec_round(m, prec, rm); (f << e, o) } else { let (abs, o) = Self::from_unsigned_prec_round(m, prec, -rm); (-(abs << e), o.reverse()) } } } /// Converts a primitive float to a [`Float`]. If the [`Float`] is nonzero and finite, it has /// the specified precision. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. (Although a NaN is not /// comparable to any [`Float`], converting a NaN to a NaN will also return `Equal`, indicating /// an exact conversion.) /// /// Rounding may occur, in which case `Nearest` is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_primitive_float_prec_round`]. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec, x.sci_exponent().abs())`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// See [here](super::from_primitive_float#from_primitive_float_prec). #[inline] pub fn from_primitive_float_prec(x: T, prec: u64) -> (Self, Ordering) { assert_ne!(prec, 0); if x.is_nan() { (Self::NAN, Equal) } else if !x.is_finite() { if x.is_sign_positive() { (Self::INFINITY, Equal) } else { (Self::NEGATIVE_INFINITY, Equal) } } else if x == T::ZERO { if x.is_sign_positive() { (Self::ZERO, Equal) } else { (Self::NEGATIVE_ZERO, Equal) } } else { let (m, e) = x.integer_mantissa_and_exponent(); if x.is_sign_positive() { let (f, o) = Self::from_unsigned_prec(m, prec); (f << e, o) } else { let (abs, o) = Self::from_unsigned_prec(m, prec); (-(abs << e), o.reverse()) } } } } macro_rules! impl_from_primitive_float { ($t: ident) => { impl From<$t> for Float { /// Converts a primitive float to a [`Float`]. /// /// If the primitive float is finite and nonzero, the precision of the [`Float`] is the /// minimum possible precision to represent the primitive float exactly. If you want to /// specify a different precision, try [`Float::from_primitive_float_prec`]. This may /// require rounding, which uses `Nearest` by default. To specify a rounding mode as /// well as a precision, try [`Float::from_primitive_float_prec_round`]. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.sci_exponent().abs()`. /// /// # Examples /// See [here](super::from_primitive_float#from). #[inline] fn from(x: $t) -> Float { if x.is_nan() { Float::NAN } else if !x.is_finite() { if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY } } else if x == 0.0 { if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO } } else { let (m, e) = x.integer_mantissa_and_exponent(); let abs = Float::from(m) << e; if x.is_sign_positive() { abs } else { -abs } } } } }; } apply_to_primitive_floats!(impl_from_primitive_float); ================================================ FILE: malachite-float/src/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use core::cmp::Ordering; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; const fn const_limb_significant_bits(x: Limb) -> u64 { Limb::WIDTH - (x.leading_zeros() as u64) } impl Float { /// Converts an unsigned primitive integer to a [`Float`], after multiplying it by the specified /// power of 2. /// /// The type of the integer is `u64`, unless the `32_bit_limbs` feature is set, in which case /// the type is `u32`. /// /// If the integer is nonzero, the precision of the [`Float`] is the minimum possible precision /// to represent the integer exactly. /// /// If you don't need to use this function in a const context, try just using `from` instead, /// followed by `>>` or `<<`. /// /// $$ /// f(x,k) = x2^k. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the result is too large or too small to be represented by a `Float`. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!( /// Float::const_from_unsigned_times_power_of_2(0, 0).to_string(), /// "0.0" /// ); /// assert_eq!( /// Float::const_from_unsigned_times_power_of_2(123, 0).to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::const_from_unsigned_times_power_of_2(123, 1).to_string(), /// "246.0" /// ); /// assert_eq!( /// Float::const_from_unsigned_times_power_of_2(123, -1).to_string(), /// "61.5" /// ); /// #[cfg(not(feature = "32_bit_limbs"))] /// { /// assert_eq!( /// Float::const_from_unsigned_times_power_of_2(884279719003555, -48).to_string(), /// "3.141592653589793" /// ); /// } /// ``` pub const fn const_from_unsigned_times_power_of_2(x: Limb, pow: i32) -> Self { if x == 0 { return Self::ZERO; } let bits = const_limb_significant_bits(x); let exponent = (bits as i32).saturating_add(pow); assert!(exponent <= Self::MAX_EXPONENT); assert!(exponent >= Self::MIN_EXPONENT); let prec = bits - x.trailing_zeros() as u64; Self(Finite { sign: true, exponent, precision: prec, significand: Natural::const_from(x << (Limb::WIDTH - bits)), }) } /// Converts an unsigned primitive integer to a [`Float`]. /// /// The type of the integer is `u64`, unless the `32_bit_limbs` feature is set, in which case /// the type is `u32`. /// /// If the integer is nonzero, the precision of the [`Float`] is the minimum possible precision /// to represent the integer exactly. /// /// If you don't need to use this function in a const context, try just using `from` instead; it /// will probably be slightly faster. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::const_from_unsigned(0).to_string(), "0.0"); /// assert_eq!(Float::const_from_unsigned(123).to_string(), "123.0"); /// ``` #[inline] pub const fn const_from_unsigned(x: Limb) -> Self { Self::const_from_unsigned_times_power_of_2(x, 0) } /// Converts a signed primitive integer to a [`Float`], after multiplying it by the specified /// power of 2. /// /// The type of the integer is `i64`, unless the `32_bit_limbs` feature is set, in which case /// the type is `i32`. /// /// If the integer is nonzero, the precision of the [`Float`] is the minimum possible precision /// to represent the integer exactly. /// /// If you don't need to use this function in a const context, try just using `from` instead, /// followed by `>>` or `<<`. /// /// $$ /// f(x,k) = x2^k. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the result is too large or too small to be represented by a `Float`. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!( /// Float::const_from_signed_times_power_of_2(0, 0).to_string(), /// "0.0" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(123, 0).to_string(), /// "123.0" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(123, 1).to_string(), /// "246.0" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(123, -1).to_string(), /// "61.5" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(-123, 0).to_string(), /// "-123.0" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(-123, 1).to_string(), /// "-246.0" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(-123, -1).to_string(), /// "-61.5" /// ); /// #[cfg(not(feature = "32_bit_limbs"))] /// { /// assert_eq!( /// Float::const_from_signed_times_power_of_2(884279719003555, -48).to_string(), /// "3.141592653589793" /// ); /// assert_eq!( /// Float::const_from_signed_times_power_of_2(-884279719003555, -48).to_string(), /// "-3.141592653589793" /// ); /// } /// ``` pub const fn const_from_signed_times_power_of_2(x: SignedLimb, pow: i32) -> Self { if x == 0 { return Self::ZERO; } let x_abs = x.unsigned_abs(); let bits = const_limb_significant_bits(x_abs); let exponent = (bits as i32).saturating_add(pow); assert!(exponent <= Self::MAX_EXPONENT); assert!(exponent >= Self::MIN_EXPONENT); let prec = bits - x_abs.trailing_zeros() as u64; Self(Finite { sign: x > 0, exponent, precision: prec, significand: Natural::const_from(x_abs << (Limb::WIDTH - bits)), }) } /// Converts a signed primitive integer to a [`Float`]. /// /// The type of the integer is `i64`, unless the `32_bit_limbs` feature is set, in which case /// the type is `i32`. /// /// If the integer is nonzero, the precision of the [`Float`] is the minimum possible precision /// to represent the integer exactly. /// /// If you don't need to use this function in a const context, try just using `from` instead; it /// will probably be slightly faster. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::const_from_signed(0).to_string(), "0.0"); /// assert_eq!(Float::const_from_signed(123).to_string(), "123.0"); /// assert_eq!(Float::const_from_signed(-123).to_string(), "-123.0"); /// ``` #[inline] pub const fn const_from_signed(x: SignedLimb) -> Self { Self::const_from_signed_times_power_of_2(x, 0) } /// Converts a primitive unsigned integer to a [`Float`]. If the [`Float`] is nonzero, it has /// the specified precision. If rounding is needed, the specified rounding mode is used. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, /// or greater than the original value. /// /// If you're only using `Nearest`, try using [`Float::from_unsigned_prec`] instead. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the primitive integer cannot be exactly /// represented with the specified precision. /// /// # Examples /// See [here](super::from_primitive_int#from_unsigned_prec_round). #[inline] pub fn from_unsigned_prec_round( x: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) where Natural: From, { Self::from_natural_prec_round(Natural::from(x), prec, rm) } /// Converts an unsigned primitive integer to a [`Float`]. If the [`Float`] is nonzero, it has /// the specified precision. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If you want the [`Float`]'s precision to be equal to the integer's number of significant /// bits, try just using `Float::from` instead. /// /// Rounding may occur, in which case `Nearest` is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_unsigned_prec_round`]. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// See [here](super::from_primitive_int#from_unsigned_prec). #[inline] pub fn from_unsigned_prec(x: T, prec: u64) -> (Self, Ordering) where Natural: From, { Self::from_natural_prec(Natural::from(x), prec) } /// Converts a primitive signed integer to a [`Float`]. If the [`Float`] is nonzero, it has the /// specified precision. If rounding is needed, the specified rounding mode is used. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, /// or greater than the original value. /// /// If you're only using `Nearest`, try using [`Float::from_signed_prec`] instead. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the primitive integer cannot be exactly /// represented with the specified precision. /// /// # Examples /// See [here](super::from_primitive_int#from_signed_prec_round). #[inline] pub fn from_signed_prec_round( x: T, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) where Integer: From, { Self::from_integer_prec_round(Integer::from(x), prec, rm) } /// Converts a signed primitive integer to a [`Float`]. If the [`Float`] is nonzero, it has the /// specified precision. An [`Ordering`] is also returned, indicating whether the returned value /// is less than, equal to, or greater than the original value. /// /// If you want the [`Float`]'s precision to be equal to the integer's number of significant /// bits, try just using `Float::from` instead. /// /// Rounding may occur, in which case `Nearest` is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_signed_prec_round`]. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// See [here](super::from_primitive_int#from_signed_prec). #[inline] pub fn from_signed_prec(x: T, prec: u64) -> (Self, Ordering) where Integer: From, { Self::from_integer_prec(Integer::from(x), prec) } } macro_rules! impl_from_unsigned { ($t: ident) => { impl From<$t> for Float { /// Converts an unsigned primitive integer to a [`Float`]. /// /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's /// number of significant bits. If you want to specify a different precision, try /// [`Float::from_unsigned_prec`]. This may require rounding, which uses `Nearest` by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_unsigned_prec_round`]. /// /// If you want to create a [`Float`] from an unsigned primitive integer in a const /// context, try [`Float::const_from_unsigned`] instead. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Float { Float::exact_from(Natural::from(u)) } } }; } apply_to_unsigneds!(impl_from_unsigned); macro_rules! impl_from_signed { ($t: ident) => { impl From<$t> for Float { /// Converts a signed primitive integer to a [`Float`]. /// /// If the integer is nonzero, the precision of the [`Float`] is equal to the integer's /// number of significant bits. If you want to specify a different precision, try /// [`Float::from_signed_prec`]. This may require rounding, which uses `Nearest` by /// default. To specify a rounding mode as well as a precision, try /// [`Float::from_signed_prec_round`]. /// /// If you want to create a [`Float`] from an signed primitive integer in a const /// context, try [`Float::const_from_signed`] instead. /// /// This function does not overflow or underflow. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(i: $t) -> Float { Float::exact_from(Integer::from(i)) } } }; } apply_to_signeds!(impl_from_signed); ================================================ FILE: malachite-float/src/conversion/from_rational.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::Finite; use crate::conversion::from_integer::{ from_integer_prec_round_zero_exponent, from_integer_zero_exponent, }; use crate::conversion::from_natural::{ from_natural_prec_round_zero_exponent, from_natural_prec_round_zero_exponent_ref, from_natural_zero_exponent, from_natural_zero_exponent_ref, }; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use core::cmp::max; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, IsPowerOf2, NegAssign, NegModPowerOf2, RoundToMultipleOfPowerOf2, UnsignedAbs, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, RoundingFrom, SaturatingFrom, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; pub_test! {from_rational_prec_round_direct( x: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); let sign = x >= 0; if let Some(pow) = x.denominator_ref().checked_log_base_2() { let n = x.into_numerator(); let n_bits = n.significant_bits(); let (mut y, mut o) = from_integer_prec_round_zero_exponent(Integer::from_sign_and_abs(sign, n), prec, rm); o = y.shr_prec_round_assign_helper(i128::from(pow) - i128::from(n_bits), prec, rm, o); assert!(rm != Exact || o == Equal, "Inexact conversion from Rational to Float"); (y, o) } else { let mut exponent = i32::saturating_from(x.floor_log_base_2_abs()); if exponent >= Float::MAX_EXPONENT { return match (sign, rm) { (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater), (true, Floor | Down) => (Float::max_finite_value_with_prec(prec), Less), (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less), (false, Ceiling | Down) => (-Float::max_finite_value_with_prec(prec), Greater), (_, Exact) => panic!("Inexact conversion from Rational to Float"), }; } let (significand, o) = Integer::rounding_from(x << (i128::exact_from(prec) - i128::from(exponent) - 1), rm); let sign = significand >= 0; let mut significand = significand.unsigned_abs(); let away_from_0 = if sign { Greater } else { Less }; if o == away_from_0 && significand.is_power_of_2() { exponent += 1; if exponent >= Float::MAX_EXPONENT { return if sign { (Float::INFINITY, Greater) } else { (Float::NEGATIVE_INFINITY, Less) }; } } exponent += 1; if exponent < Float::MIN_EXPONENT { assert!(rm != Exact, "Inexact conversion from Rational to Float"); return if rm == Nearest && exponent == Float::MIN_EXPONENT - 1 && (o == away_from_0.reverse() || !significand.is_power_of_2()) { if sign { (Float::min_positive_value_prec(prec), Greater) } else { (-Float::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (true, Up | Ceiling) => (Float::min_positive_value_prec(prec), Greater), (true, Floor | Down | Nearest) => (Float::ZERO, Less), (false, Up | Floor) => (-Float::min_positive_value_prec(prec), Less), (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater), (_, Exact) => unreachable!(), } }; } significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); let target_bits = prec .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0; let current_bits = significand_bits(&significand); if current_bits > target_bits { significand >>= current_bits - target_bits; } ( Float(Finite { sign, exponent, precision: prec, significand, }), o, ) } }} pub_test! {from_rational_prec_round_using_div( x: Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { let sign = x >= 0; if !sign { rm.neg_assign(); } let (n, d) = x.into_numerator_and_denominator(); let is_zero = n == 0; let (f, o) = match ( if is_zero { None } else { n.checked_log_base_2() }, d.checked_log_base_2(), ) { (Some(log_n), Some(log_d)) => Float::power_of_2_prec_round( i64::saturating_from(i128::from(log_n) - i128::from(log_d)), prec, rm, ), (None, Some(log_d)) => { let bits = n.significant_bits(); let (mut f, mut o) = from_natural_prec_round_zero_exponent(n, prec, rm); o = f.shr_prec_round_assign_helper( i128::from(log_d) - i128::from(bits), prec, rm, o, ); (f, o) } (Some(log_n), None) => { let bits = d.significant_bits(); let (mut f, mut o) = from_natural_zero_exponent(d).reciprocal_prec_round(prec, rm); o = f.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(bits), prec, rm, o, ); (f, o) } (None, None) => { let n_bits = n.significant_bits(); let d_bits = d.significant_bits(); let (mut f, mut o) = from_natural_zero_exponent(n).div_prec_round( from_natural_zero_exponent(d), prec, rm, ); o = f.shl_prec_round_assign_helper( i128::from(n_bits) - i128::from(d_bits), prec, rm, o, ); (f, o) } }; if sign { (f, o) } else { (-f, o.reverse()) } }} pub_test! {from_rational_prec_round_ref_direct( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); let sign = *x >= 0; if let Some(pow) = x.denominator_ref().checked_log_base_2() { let n = x.numerator_ref(); let n_bits = n.significant_bits(); let (mut y, mut o) = from_natural_prec_round_zero_exponent_ref(n, prec, if sign { rm } else { -rm }); o = y.shr_prec_round_assign_helper( i128::from(pow) - i128::from(n_bits), prec, if sign { rm } else { -rm }, o, ); assert!(rm != Exact || o == Equal, "Inexact conversion from Rational to Float"); if sign { (y, o) } else { (-y, o.reverse()) } } else { let mut exponent = i32::saturating_from(x.floor_log_base_2_abs()); if exponent >= Float::MAX_EXPONENT { return match (sign, rm) { (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater), (true, Floor | Down) => (Float::max_finite_value_with_prec(prec), Less), (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less), (false, Ceiling | Down) => (-Float::max_finite_value_with_prec(prec), Greater), (_, Exact) => panic!("Inexact conversion from Rational to Float"), }; } let (significand, o) = Integer::rounding_from(x << (i128::exact_from(prec) - i128::from(exponent) - 1), rm); let sign = significand >= 0; let mut significand = significand.unsigned_abs(); let away_from_0 = if sign { Greater } else { Less }; if o == away_from_0 && significand.is_power_of_2() { exponent += 1; if exponent >= Float::MAX_EXPONENT { return if sign { (Float::INFINITY, Greater) } else { (Float::NEGATIVE_INFINITY, Less) }; } } exponent += 1; if exponent < Float::MIN_EXPONENT { assert!(rm != Exact, "Inexact conversion from Rational to Float"); return if rm == Nearest && exponent == Float::MIN_EXPONENT - 1 && (o == away_from_0.reverse() || !significand.is_power_of_2()) { if sign { (Float::min_positive_value_prec(prec), Greater) } else { (-Float::min_positive_value_prec(prec), Less) } } else { match (sign, rm) { (true, Up | Ceiling) => (Float::min_positive_value_prec(prec), Greater), (true, Floor | Down | Nearest) => (Float::ZERO, Less), (false, Up | Floor) => (-Float::min_positive_value_prec(prec), Less), (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater), (_, Exact) => unreachable!(), } }; } significand <<= significand .significant_bits() .neg_mod_power_of_2(Limb::LOG_WIDTH); let target_bits = prec .round_to_multiple_of_power_of_2(Limb::LOG_WIDTH, Ceiling) .0; let current_bits = significand_bits(&significand); if current_bits > target_bits { significand >>= current_bits - target_bits; } ( Float(Finite { sign, exponent, precision: prec, significand, }), o, ) } }} pub_test! {from_rational_prec_round_ref_using_div( x: &Rational, prec: u64, mut rm: RoundingMode, ) -> (Float, Ordering) { let sign = *x >= 0; if !sign { rm.neg_assign(); } let (n, d) = x.numerator_and_denominator_ref(); let is_zero = *n == 0; let (f, o) = match ( if is_zero { None } else { n.checked_log_base_2() }, d.checked_log_base_2(), ) { (Some(log_n), Some(log_d)) => Float::power_of_2_prec_round( i64::saturating_from(i128::from(log_n) - i128::from(log_d)), prec, rm, ), (None, Some(log_d)) => { let (mut f, mut o) = from_natural_prec_round_zero_exponent_ref(n, prec, rm); o = f.shr_prec_round_assign_helper( i128::from(log_d) - i128::from(n.significant_bits()), prec, rm, o, ); (f, o) } (Some(log_n), None) => { let (mut f, mut o) = from_natural_zero_exponent_ref(d).reciprocal_prec_round(prec, rm); o = f.shl_prec_round_assign_helper( i128::from(log_n) - i128::from(d.significant_bits()), prec, rm, o, ); (f, o) } (None, None) => { let (mut f, mut o) = from_natural_zero_exponent_ref(n).div_prec_round( from_natural_zero_exponent_ref(d), prec, rm, ); o = f.shl_prec_round_assign_helper( i128::from(n.significant_bits()) - i128::from(d.significant_bits()), prec, rm, o, ); (f, o) } }; if sign { (f, o) } else { (-f, o.reverse()) } }} pub(crate) const FROM_RATIONAL_THRESHOLD: u64 = 100; impl Float { /// Converts a [`Rational`] to a [`Float`], taking the [`Rational`] by value. If the [`Float`] /// is nonzero, it has the specified precision. If rounding is needed, the specified rounding /// mode is used. An [`Ordering`] is also returned, indicating whether the returned value is /// less than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_rational_prec`] instead. /// /// - If the [`Rational`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Rational`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this /// function overflows to $-\infty$ if `rm` is `Floor`, `Up`, or `Nearest`, and rounds up to /// $-(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Rational`] rounds to a positive value less than $2^{-2^{30}}$), this function /// underflows to positive zero if `rm` is `Floor` or `Down`, rounds up to $2^{-2^{30}}$ if /// `rm` is `Ceiling` or `Up`, underflows to positive zero if `rm` is `Nearest` and the /// [`Rational`] rounds to a value less than or equal to $2^{-2^{30}-1}$, and rounds up to /// $2^{-2^{30}}$ if `rm` is `Nearest` and the [`Rational`] rounds to a value greater than /// $2^{-2^{30}-1}$. /// - If the [`Rational`] rounds to a negative value greater than $-2^{-2^{30}}$), this function /// underflows to negative zero if `rm` is `Ceiling` or `Down`, rounds down to $-2^{-2^{30}}$ /// if `rm` is `Floor` or `Up`, underflows to negative zero if `rm` is `Nearest` and the /// [`Rational`] rounds to a value greater than or equal to $-2^{-2^{30}-1}$, and rounds down /// to $-2^{-2^{30}}$ if `rm` is `Nearest` and the [`Rational`] rounds to a value less than /// $-2^{-2^{30}-1}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(n.significant_bits(), prec)`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Rational` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(1, 3), 10, Floor); /// assert_eq!(x.to_string(), "0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(1, 3), 10, Ceiling); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(1, 3), 10, Nearest); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(-1, 3), 10, Floor); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(-1, 3), 10, Ceiling); /// assert_eq!(x.to_string(), "-0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_round(Rational::from_signeds(-1, 3), 10, Nearest); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) { if max(x.significant_bits(), prec) < FROM_RATIONAL_THRESHOLD { from_rational_prec_round_direct(x, prec, rm) } else { from_rational_prec_round_using_div(x, prec, rm) } } /// Converts a [`Rational`] to a [`Float`], taking the [`Rational`] by value. If the [`Float`] /// is nonzero, it has the specified precision. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// If the [`Rational`] is dyadic (its denominator is a power of 2), then you can convert it to /// a [`Float`] using `try_from` instead. The precision of the resulting [`Float`] will be the /// number of significant bits of the [`Rational`]'s numerator. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_rational_prec_round`]. /// /// - If the [`Rational`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// - If the [`Rational`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this /// function overflows to $-\infty$. /// - If the [`Rational`] rounds to a positive value less than $2^{-2^{30}}$), this function /// underflows to positive zero if the [`Rational`] rounds to a value less than or equal to /// $2^{-2^{30}-1}$ and rounds up to $2^{-2^{30}}$ if the [`Rational`] rounds to a value /// greater than $2^{-2^{30}-1}$. /// - If the [`Rational`] rounds to a negative value greater than $2^{-2^{30}}$), this function /// underflows to negative zero if the [`Rational`] rounds to a value greater than or equal to /// $-2^{-2^{30}-1}$ and rounds down to $-2^{-2^{30}}$ if the [`Rational`] rounds to a value /// less than $-2^{-2^{30}-1}$. /// /// # Panics /// Panics if `prec` is zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), prec)`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_rational_prec(Rational::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_rational_prec(Rational::from_signeds(1, 3), 10); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec(Rational::from_signeds(1, 3), 100); /// assert_eq!(x.to_string(), "0.3333333333333333333333333333335"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec(Rational::from_signeds(-1, 3), 10); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_rational_prec(Rational::from_signeds(-1, 3), 100); /// assert_eq!(x.to_string(), "-0.3333333333333333333333333333335"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) { Self::from_rational_prec_round(x, prec, Nearest) } /// Converts a [`Rational`] to a [`Float`], taking the [`Rational`] by reference. If the /// [`Float`] is nonzero, it has the specified precision. If rounding is needed, the specified /// rounding mode is used. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If you're only using [`Nearest`], try using [`Float::from_rational_prec_ref`] instead. /// /// - If the [`Rational`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$ if `rm` is `Ceiling`, `Up`, or `Nearest`, and rounds down /// to $(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Rational`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this /// function overflows to $-\infty$ if `rm` is `Floor`, `Up`, or `Nearest`, and rounds up to /// $-(1-(1/2)^p)2^{2^{30}-1}$ otherwise, where $p$ is `prec`. /// - If the [`Rational`] rounds to a positive value less than $2^{-2^{30}}$), this function /// underflows to positive zero if `rm` is `Floor` or `Down`, rounds up to $2^{-2^{30}}$ if /// `rm` is `Ceiling` or `Up`, underflows to positive zero if `rm` is `Nearest` and the /// [`Rational`] rounds to a value less than or equal to $2^{-2^{30}-1}$, and rounds up to /// $2^{-2^{30}}$ if `rm` is `Nearest` and the [`Rational`] rounds to a value greater than /// $2^{-2^{30}-1}$. /// - If the [`Rational`] rounds to a negative value greater than $-2^{-2^{30}}$), this function /// underflows to negative zero if `rm` is `Ceiling` or `Down`, rounds down to $-2^{-2^{30}}$ /// if `rm` is `Floor` or `Up`, underflows to negative zero if `rm` is `Nearest` and the /// [`Rational`] rounds to a value greater than or equal to $-2^{-2^{30}-1}$, and rounds down /// to $-2^{-2^{30}}$ if `rm` is `Nearest` and the [`Rational`] rounds to a value less than /// $-2^{-2^{30}-1}$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), prec)`. /// /// # Panics /// Panics if `prec` is zero, or if `rm` is exact and the `Rational` cannot be exactly /// represented with the specified precision. /// /// # Examples /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_rational_prec_round_ref(&Rational::from_signeds(1, 3), 10, Floor); /// assert_eq!(x.to_string(), "0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = /// Float::from_rational_prec_round_ref(&Rational::from_signeds(1, 3), 10, Ceiling); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = /// Float::from_rational_prec_round_ref(&Rational::from_signeds(1, 3), 10, Nearest); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_round_ref(&Rational::from_signeds(-1, 3), 10, Floor); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = /// Float::from_rational_prec_round_ref(&Rational::from_signeds(-1, 3), 10, Ceiling); /// assert_eq!(x.to_string(), "-0.333"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = /// Float::from_rational_prec_round_ref(&Rational::from_signeds(-1, 3), 10, Nearest); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_rational_prec_round_ref( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Self, Ordering) { if max(x.significant_bits(), prec) < FROM_RATIONAL_THRESHOLD { from_rational_prec_round_ref_direct(x, prec, rm) } else { from_rational_prec_round_ref_using_div(x, prec, rm) } } /// Converts a [`Rational`] to a [`Float`], taking the [`Rational`] by reference. If the /// [`Float`] is nonzero, it has the specified precision. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the original /// value. /// /// If the [`Rational`] is dyadic (its denominator is a power of 2), then you can convert it to /// a [`Float`] using `try_from` instead. The precision of the resulting [`Float`] will be the /// number of significant bits of the [`Rational`]'s numerator. /// /// Rounding may occur, in which case [`Nearest`] is used by default. To specify a rounding mode /// as well as a precision, try [`Float::from_rational_prec_round_ref`]. /// /// - If the [`Rational`] rounds to a value greater than or equal to $2^{2^{30}-1}$), this /// function overflows to $\infty$. /// - If the [`Rational`] rounds to a value less than or equal to $-2^{2^{30}-1}$), this /// function overflows to $-\infty$. /// - If the [`Rational`] rounds to a positive value less than $2^{-2^{30}}$), this function /// underflows to positive zero if the [`Rational`] rounds to a value less than or equal to /// $2^{-2^{30}-1}$ and rounds up to $2^{-2^{30}}$ if the [`Rational`] rounds to a value /// greater than $2^{-2^{30}-1}$. /// - If the [`Rational`] rounds to a negative value greater than $2^{-2^{30}}$), this function /// underflows to negative zero if the [`Rational`] rounds to a value greater than or equal to /// $-2^{-2^{30}-1}$ and rounds down to $-2^{-2^{30}}$ if the [`Rational`] rounds to a value /// less than $-2^{-2^{30}-1}$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), prec)`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_rational_prec_ref(&Rational::ZERO, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_rational_prec_ref(&Rational::from_signeds(1, 3), 10); /// assert_eq!(x.to_string(), "0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_ref(&Rational::from_signeds(1, 3), 100); /// assert_eq!(x.to_string(), "0.3333333333333333333333333333335"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_rational_prec_ref(&Rational::from_signeds(-1, 3), 10); /// assert_eq!(x.to_string(), "-0.3335"); /// assert_eq!(x.get_prec(), Some(10)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_rational_prec_ref(&Rational::from_signeds(-1, 3), 100); /// assert_eq!(x.to_string(), "-0.3333333333333333333333333333335"); /// assert_eq!(x.get_prec(), Some(100)); /// assert_eq!(o, Less); /// ``` #[inline] pub fn from_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) { Self::from_rational_prec_round_ref(x, prec, Nearest) } } impl TryFrom for Float { type Error = FloatConversionError; /// Converts a [`Rational`] to an [`Float`], taking the [`Rational`] by value. If the /// [`Rational`]'s denominator is not a power of 2, or if the [`Rational`] is too far from zero /// or too close to zero to be represented as a [`Float`], an error is returned. /// /// The [`Float`]'s precision is the minimum number of bits needed to exactly represent the /// [`Rational`]. /// /// - If the [`Rational`] is greater than or equal to $2^{2^{30}-1}$), this function returns an /// overflow error. /// - If the [`Rational`] is less than or equal to $-2^{2^{30}-1}$), this function returns an /// overflow error. /// - If the [`Rational`] is positive and less than $2^{-2^{30}}$), this function returns an /// underflow error. /// - If the [`Rational`] is negative and greater than $-2^{-2^{30}}$), this function returns an /// underflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; /// use malachite_q::Rational; /// /// assert_eq!(Float::try_from(Rational::ZERO).unwrap(), 0); /// assert_eq!( /// Float::try_from(Rational::from_signeds(1, 8)).unwrap(), /// 0.125 /// ); /// assert_eq!( /// Float::try_from(Rational::from_signeds(-1, 8)).unwrap(), /// -0.125 /// ); /// /// assert_eq!( /// Float::try_from(Rational::from_signeds(1, 3)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// Float::try_from(Rational::from_signeds(-1, 3)), /// Err(FloatConversionError::Inexact) /// ); /// ``` fn try_from(x: Rational) -> Result { if x == 0u32 { return Ok(Self::ZERO); } if let Some(log_denominator) = x.denominator_ref().checked_log_base_2() { let exponent = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); if exponent > Self::MAX_EXPONENT { return Err(FloatConversionError::Overflow); } else if exponent < Self::MIN_EXPONENT { return Err(FloatConversionError::Underflow); } let n = Integer::from_sign_and_abs(x >= 0u32, x.into_numerator()); let n_bits = n.significant_bits(); Ok(from_integer_zero_exponent(n) >> (i128::from(log_denominator) - i128::from(n_bits))) } else { Err(FloatConversionError::Inexact) } } } impl TryFrom<&Rational> for Float { type Error = FloatConversionError; /// Converts a [`Rational`] to an [`Float`], taking the [`Rational`] by reference. If the /// [`Rational`]'s denominator is not a power of 2, or if the [`Rational`] is too far from zero /// or too close to zero to be represented as a [`Float`], an error is returned. /// /// The [`Float`]'s precision is the minimum number of bits needed to exactly represent the /// [`Rational`]. /// /// - If the [`Rational`] is greater than or equal to $2^{2^{30}-1}$), this function returns an /// overflow error. /// - If the [`Rational`] is less than or equal to $-2^{2^{30}-1}$), this function returns an /// overflow error. /// - If the [`Rational`] is positive and less than $2^{-2^{30}}$), this function returns an /// underflow error. /// - If the [`Rational`] is negative and greater than $-2^{-2^{30}}$), this function returns an /// underflow error. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_float::Float; /// use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; /// use malachite_q::Rational; /// /// assert_eq!(Float::try_from(&Rational::ZERO).unwrap(), 0); /// assert_eq!( /// Float::try_from(&Rational::from_signeds(1, 8)).unwrap(), /// 0.125 /// ); /// assert_eq!( /// Float::try_from(&Rational::from_signeds(-1, 8)).unwrap(), /// -0.125 /// ); /// /// assert_eq!( /// Float::try_from(&Rational::from_signeds(1, 3)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// Float::try_from(&Rational::from_signeds(-1, 3)), /// Err(FloatConversionError::Inexact) /// ); /// ``` fn try_from(x: &Rational) -> Result { if *x == 0u32 { return Ok(Self::ZERO); } if let Some(log_denominator) = x.denominator_ref().checked_log_base_2() { let exponent = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1); if exponent > Self::MAX_EXPONENT { return Err(FloatConversionError::Overflow); } else if exponent < Self::MIN_EXPONENT { return Err(FloatConversionError::Underflow); } let n = x.numerator_ref(); let n_bits = n.significant_bits(); let mut n = from_natural_zero_exponent_ref(n); if *x < 0 { n.neg_assign(); } Ok(n >> (i128::from(log_denominator) - i128::from(n_bits))) } else { Err(FloatConversionError::Inexact) } } } impl ConvertibleFrom<&Rational> for Float { /// Determines whether a [`Rational`] can be converted to an [`Float`], taking the [`Rational`] /// by reference. /// /// The [`Rational`]s that are convertible to [`Float`]s are precisely those whose denominators /// are powers of two, and would not overflow or underflow. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert_eq!(Float::convertible_from(&Rational::ZERO), true); /// assert_eq!(Float::convertible_from(&Rational::from_signeds(3, 8)), true); /// assert_eq!( /// Float::convertible_from(&Rational::from_signeds(-3, 8)), /// true /// ); /// /// assert_eq!( /// Float::convertible_from(&Rational::from_signeds(1, 3)), /// false /// ); /// assert_eq!( /// Float::convertible_from(&Rational::from_signeds(-1, 3)), /// false /// ); /// ``` #[inline] fn convertible_from(x: &Rational) -> bool { *x == 0 || x.denominator_ref().is_power_of_2() && (Self::MIN_EXPONENT..=Self::MAX_EXPONENT) .contains(&i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1)) } } ================================================ FILE: malachite-float/src/conversion/integer_from_float.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Zero}; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound}; use malachite_base::num::basic::traits::{One, Zero as ZeroTrait}; use malachite_base::num::conversion::from::SignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl RoundingFrom for Integer { /// Converts a [`Float`] to an [`Integer`], using a specified [`RoundingMode`] and taking the /// [`Float`] by value. An [`Ordering`] is also returned, indicating whether the returned value /// is less than, equal to, or greater than the original value. /// /// If the [`Float`] is NaN or infinite, the function will panic regardless of the rounding /// mode. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is NaN or /// infinite. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::rounding_from(Float::from(1.5), Floor).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Float::from(1.5), Ceiling).to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Float::from(1.5), Nearest).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Integer::rounding_from(Float::from(-1.5), Floor).to_debug_string(), /// "(-2, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Float::from(-1.5), Ceiling).to_debug_string(), /// "(-1, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Float::from(-1.5), Nearest).to_debug_string(), /// "(-2, Less)" /// ); /// ``` fn rounding_from(f: Float, rm: RoundingMode) -> (Self, Ordering) { match f { float_either_zero!() => (Self::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let abs_rm = if sign { rm } else { -rm }; let (abs_i, abs_o) = if exponent < 0 { match abs_rm { Floor | Down | Nearest => (Natural::ZERO, Less), Ceiling | Up => (Natural::ONE, Greater), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(&significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { significand.shr_round(sb - eb, abs_rm) } else { (significand << (eb - sb), Equal) } }; if sign { (Self::from(abs_i), abs_o) } else { (-abs_i, abs_o.reverse()) } } _ => panic!("Can't convert {f} to Integer using {rm}"), } } } impl RoundingFrom<&Float> for Integer { /// Converts a [`Float`] to an [`Integer`], using a specified [`RoundingMode`] and taking the /// [`Float`] by reference. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If the [`Float`] is NaN or infinite, the function will panic regardless of the rounding /// mode. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is NaN or /// infinite. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::rounding_from(&Float::from(1.5), Floor).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(&Float::from(1.5), Ceiling).to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(&Float::from(1.5), Nearest).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Integer::rounding_from(&Float::from(-1.5), Floor).to_debug_string(), /// "(-2, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(&Float::from(-1.5), Ceiling).to_debug_string(), /// "(-1, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(&Float::from(-1.5), Nearest).to_debug_string(), /// "(-2, Less)" /// ); /// ``` fn rounding_from(f: &Float, rm: RoundingMode) -> (Self, Ordering) { match f { float_either_zero!() => (Self::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { if *significand == 0u32 { (Self::ZERO, Equal) } else { let abs_rm = if *sign { rm } else { -rm }; let (abs_i, abs_o) = if *exponent < 0 { match abs_rm { Floor | Down | Nearest => (Natural::ZERO, Less), Ceiling | Up => (Natural::ONE, Greater), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { significand.shr_round(sb - eb, abs_rm) } else { (significand << (eb - sb), Equal) } }; if *sign { (Self::from(abs_i), abs_o) } else { (-abs_i, abs_o.reverse()) } } } _ => panic!("Can't convert {f} to Integer using {rm}"), } } } impl TryFrom for Integer { type Error = SignedFromFloatError; /// Converts a [`Float`] to an [`Integer`], taking the [`Float`] by value. If the [`Float`] is /// not equal to an integer, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::from::SignedFromFloatError::*; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::try_from(Float::ZERO).unwrap(), 0); /// assert_eq!(Integer::try_from(Float::from(123.0)).unwrap(), 123); /// assert_eq!(Integer::try_from(Float::from(-123.0)).unwrap(), -123); /// /// assert_eq!( /// Integer::try_from(Float::from(1.5)), /// Err(FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!(Integer::try_from(Float::INFINITY), Err(FloatInfiniteOrNan)); /// assert_eq!(Integer::try_from(Float::NAN), Err(FloatInfiniteOrNan)); /// ``` fn try_from(f: Float) -> Result { match f { Float(Zero { .. }) => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { if exponent <= 0 { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(&significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(Self::from_sign_and_abs(sign, significand >> bits)) } else { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(Self::from_sign_and_abs(sign, significand << (eb - sb))) } } } _ => Err(SignedFromFloatError::FloatInfiniteOrNan), } } } impl TryFrom<&Float> for Integer { type Error = SignedFromFloatError; /// Converts a [`Float`] to an [`Integer`], taking the [`Float`] by reference. If the [`Float`] /// is not equal to an integer, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::from::SignedFromFloatError::*; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::try_from(&Float::ZERO).unwrap(), 0); /// assert_eq!(Integer::try_from(&Float::from(123.0)).unwrap(), 123); /// assert_eq!(Integer::try_from(&Float::from(-123.0)).unwrap(), -123); /// /// assert_eq!( /// Integer::try_from(&Float::from(1.5)), /// Err(FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!(Integer::try_from(&Float::INFINITY), Err(FloatInfiniteOrNan)); /// assert_eq!(Integer::try_from(&Float::NAN), Err(FloatInfiniteOrNan)); /// ``` fn try_from(f: &Float) -> Result { match f { Float(Zero { .. }) => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { if *exponent <= 0 { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(Self::from_sign_and_abs(*sign, significand >> bits)) } else { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(Self::from_sign_and_abs(*sign, significand << (eb - sb))) } } } _ => Err(SignedFromFloatError::FloatInfiniteOrNan), } } } impl ConvertibleFrom<&Float> for Integer { /// Determines whether a [`Float`] can be converted to an [`Integer`], taking the [`Float`] by /// reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::convertible_from(&Float::ZERO), true); /// assert_eq!(Integer::convertible_from(&Float::from(123.0)), true); /// assert_eq!(Integer::convertible_from(&Float::from(-123.0)), true); /// /// assert_eq!(Integer::convertible_from(&Float::from(1.5)), false); /// assert_eq!(Integer::convertible_from(&Float::INFINITY), false); /// assert_eq!(Integer::convertible_from(&Float::NAN), false); /// ``` fn convertible_from(f: &Float) -> bool { match f { Float(Zero { .. }) => true, Float(Finite { exponent, significand, .. }) => { *significand == 0u32 || *exponent > 0 && { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); sb < eb || significand.divisible_by_power_of_2(sb - eb) } } _ => false, } } } ================================================ FILE: malachite-float/src/conversion/is_integer.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::conversion::traits::{ConvertibleFrom, IsInteger}; use malachite_nz::integer::Integer; impl IsInteger for &Float { /// Determines whether a [`Float`] is an integer. /// /// $f(x) = x \in \Z$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, OneHalf, Zero}; /// use malachite_base::num::conversion::traits::IsInteger; /// use malachite_float::Float; /// /// assert_eq!(Float::ZERO.is_integer(), true); /// assert_eq!(Float::ONE.is_integer(), true); /// assert_eq!(Float::from(100).is_integer(), true); /// assert_eq!(Float::from(-100).is_integer(), true); /// assert_eq!(Float::ONE_HALF.is_integer(), false); /// assert_eq!((-Float::ONE_HALF).is_integer(), false); /// ``` #[inline] fn is_integer(self) -> bool { Integer::convertible_from(self) } } ================================================ FILE: malachite-float/src/conversion/mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use core::cmp::{ Ordering::{self, *}, min, }; use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ ExactFrom, IntegerMantissaAndExponent, RawMantissaAndExponent, SciMantissaAndExponent, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; impl Float { /// Returns a [`Float`]'s scientific mantissa and exponent, rounding according to the specified /// rounding mode. An [`Ordering`] is also returned, indicating whether the mantissa and /// exponent represent a value that is less than, equal to, or greater than the original value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is /// a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as a float. The /// conversion might not be exact, so we round to the nearest float using the provided rounding /// mode. If the rounding mode is `Exact` but the conversion is not exact, `None` is returned. /// $$ /// f(x, r) \approx \left (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, /// \lfloor \log_2 x \rfloor\right ). /// $$ /// /// This function does not overflow or underflow. The returned exponent is always in the range /// $[-2^{30}, 2^{30}-1]$. Notice that although a [`Float`]'s maximum scientific exponent is /// $2^{30}-2$, this function may return an exponent one larger than this limit due to rounding. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use std::cmp::Ordering::{self, *}; /// /// let test = |x: Float, rm: RoundingMode, out: Option<(f32, i32, Ordering)>| { /// assert_eq!( /// x.sci_mantissa_and_exponent_round(rm) /// .map(|(m, e, o)| (NiceFloat(m), e, o)), /// out.map(|(m, e, o)| (NiceFloat(m), e, o)) /// ); /// }; /// test(Float::from(3u32), Floor, Some((1.5, 1, Equal))); /// test(Float::from(3u32), Down, Some((1.5, 1, Equal))); /// test(Float::from(3u32), Ceiling, Some((1.5, 1, Equal))); /// test(Float::from(3u32), Up, Some((1.5, 1, Equal))); /// test(Float::from(3u32), Nearest, Some((1.5, 1, Equal))); /// test(Float::from(3u32), Exact, Some((1.5, 1, Equal))); /// /// let x = Float::from(std::f64::consts::PI); /// test(x.clone(), Floor, Some((1.5707963, 1, Less))); /// test(x.clone(), Down, Some((1.5707963, 1, Less))); /// test(x.clone(), Ceiling, Some((1.5707964, 1, Greater))); /// test(x.clone(), Up, Some((1.5707964, 1, Greater))); /// test(x.clone(), Nearest, Some((1.5707964, 1, Greater))); /// test(x.clone(), Exact, None); /// /// test( /// Float::from(1000000000u32), /// Nearest, /// Some((1.8626451, 29, Equal)), /// ); /// test( /// Float::exact_from(Natural::from(10u32).pow(52)), /// Nearest, /// Some((1.670478, 172, Greater)), /// ); /// /// test(Float::exact_from(Natural::from(10u32).pow(52)), Exact, None); /// ``` pub fn sci_mantissa_and_exponent_round( &self, rm: RoundingMode, ) -> Option<(T, i32, Ordering)> { match self { Self(Finite { exponent, significand, .. }) => significand .sci_mantissa_and_exponent_round::(rm) .map(|(m, _, o)| { ( m, if o == Greater && m == T::ONE { *exponent } else { exponent - 1 }, o, ) }), _ => None, } } } impl RawMantissaAndExponent for Float { /// Returns the raw mantissa and exponent of a [`Float`], taking the [`Float`] by value. /// /// The raw exponent and raw mantissa are the actual bit patterns used to represent the /// components of `self`. When `self` is finite and nonzero, the raw mantissa is an integer /// whose number of significant bits is a multiple of the limb width, and which is equal to the /// absolute value of `self` multiplied by some integer power of 2. The raw exponent is one more /// than the floor of the base-2 logarithm of the absolute value of `self`. /// /// The inverse operation is [`Self::from_raw_mantissa_and_exponent`]. /// /// The raw exponent is in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not finite or not zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, RawMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// use malachite_q::Rational; /// /// if Limb::WIDTH == u64::WIDTH { /// let (m, e) = Float::ONE.raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "9223372036854775808"); /// assert_eq!(e, 1); /// /// let (m, e) = Float::from(std::f64::consts::PI).raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "14488038916154245120"); /// assert_eq!(e, 2); /// /// let (m, e) = /// Float::exact_from(Natural::from(3u32).pow(50u64)).raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "202070319366191015160784900114134073344"); /// assert_eq!(e, 80); /// /// let (m, e) = Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "286514342137199872022965541161805021184"); /// assert_eq!(e, -79); /// } /// ``` fn raw_mantissa_and_exponent(self) -> (Natural, i32) { if let Self(Finite { exponent, significand, .. }) = self { (significand, exponent) } else { panic!() } } /// Returns the raw exponent of a [`Float`], taking the [`Float`] by value. /// /// The raw exponent is one more than the floor of the base-2 logarithm of the absolute value of /// `self`. /// /// The raw exponent is in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not finite or not zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, RawMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Float::ONE.raw_exponent(), 1); /// assert_eq!(Float::from(std::f64::consts::PI).raw_exponent(), 2); /// assert_eq!( /// Float::exact_from(Natural::from(3u32).pow(50u64)).raw_exponent(), /// 80 /// ); /// assert_eq!( /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .raw_exponent(), /// -79 /// ); /// ``` fn raw_exponent(self) -> i32 { if let Self(Finite { exponent, .. }) = self { exponent } else { panic!() } } /// Constructs a [`Float`] from its raw mantissa and exponent. The resulting [`Float`] is /// positive and has the smallest precision possible. /// /// The number of significant bits of the raw mantissa must be divisible by the limb width. The /// raw exponent must be in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `raw_mantissa` is zero, if its number of significant bits is not divisible by the /// limb width, or if `raw_exponent` is out of range. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// if Limb::WIDTH == u64::WIDTH { /// assert_eq!( /// Float::from_raw_mantissa_and_exponent(Natural::from(9223372036854775808u64), 1), /// 1 /// ); /// assert_eq!( /// Float::from_raw_mantissa_and_exponent(Natural::from(14488038916154245120u64), 2), /// std::f64::consts::PI /// ); /// assert_eq!( /// Float::from_raw_mantissa_and_exponent( /// Natural::from_str("202070319366191015160784900114134073344").unwrap(), /// 80 /// ), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// Float::from_raw_mantissa_and_exponent( /// Natural::from_str("286514342137199872022965541161805021184").unwrap(), /// -79 /// ), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// } /// ``` fn from_raw_mantissa_and_exponent(raw_mantissa: Natural, raw_exponent: i32) -> Self { assert!(raw_exponent <= Self::MAX_EXPONENT); assert!(raw_exponent >= Self::MIN_EXPONENT); let bits = raw_mantissa.significant_bits(); assert_ne!(bits, 0); assert!(bits.divisible_by_power_of_2(Limb::LOG_WIDTH)); let precision = bits - min(raw_mantissa.trailing_zeros().unwrap(), Limb::WIDTH - 1); Self(Finite { sign: true, exponent: raw_exponent, significand: raw_mantissa, precision, }) } } impl RawMantissaAndExponent for &Float { /// Returns the raw mantissa and exponent of a [`Float`], taking the [`Float`] by reference. /// /// The raw exponent and raw mantissa are the actual bit patterns used to represent the /// components of `self`. When `self` is finite and nonzero, the raw mantissa is an integer /// whose number of significant bits is a multiple of the limb width, and which is equal to the /// absolute value of `self` multiplied by some integer power of 2. The raw exponent is one more /// than the floor of the base-2 logarithm of the absolute value of `self`. /// /// The raw exponent is in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// The inverse operation is [`Float::from_raw_mantissa_and_exponent`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`. /// /// # Panics /// Panics if the [`Float`] is not finite or not zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, RawMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// use malachite_q::Rational; /// /// if Limb::WIDTH == u64::WIDTH { /// let (m, e) = (&Float::ONE).raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "9223372036854775808"); /// assert_eq!(e, 1); /// /// let (m, e) = (&Float::from(std::f64::consts::PI)).raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "14488038916154245120"); /// assert_eq!(e, 2); /// /// let (m, e) = /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "202070319366191015160784900114134073344"); /// assert_eq!(e, 80); /// /// let (m, e) = (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0) /// .raw_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "286514342137199872022965541161805021184"); /// assert_eq!(e, -79); /// } /// ``` fn raw_mantissa_and_exponent(self) -> (Natural, i32) { if let Float(Finite { exponent, significand, .. }) = self { (significand.clone(), *exponent) } else { panic!() } } /// Returns the raw exponent of a [`Float`], taking the [`Float`] by reference. /// /// The raw exponent is one more than the floor of the base-2 logarithm of the absolute value of /// `self`. /// /// The raw exponent is in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not finite or not zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, RawMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!((&Float::ONE).raw_exponent(), 1); /// assert_eq!((&Float::from(std::f64::consts::PI)).raw_exponent(), 2); /// assert_eq!( /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).raw_exponent(), /// 80 /// ); /// assert_eq!( /// (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0).raw_exponent(), /// -79 /// ); /// ``` fn raw_exponent(self) -> i32 { if let Float(Finite { exponent, .. }) = self { *exponent } else { panic!() } } /// Constructs a [`Float`] from its raw mantissa and exponent. The resulting [`Float`] is /// positive and has the smallest precision possible. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// The number of significant bits of the raw mantissa must be divisible by the limb width. The /// raw exponent must be in the range $[-(2^{30}-1), 2^{30}-1]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `raw_mantissa` is zero, if its number of significant bits is not divisible by the /// limb width, or if `raw_exponent` is out of range. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::conversion::traits::RawMantissaAndExponent; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// if Limb::WIDTH == u64::WIDTH { /// assert_eq!( /// <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( /// Natural::from(9223372036854775808u64), /// 1 /// ), /// 1 /// ); /// assert_eq!( /// <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( /// Natural::from(14488038916154245120u64), /// 2 /// ), /// std::f64::consts::PI /// ); /// assert_eq!( /// <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( /// Natural::from_str("202070319366191015160784900114134073344").unwrap(), /// 80 /// ), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( /// Natural::from_str("286514342137199872022965541161805021184").unwrap(), /// -79 /// ), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// } /// ``` #[inline] fn from_raw_mantissa_and_exponent(raw_mantissa: Natural, raw_exponent: i32) -> Float { Float::from_raw_mantissa_and_exponent(raw_mantissa, raw_exponent) } } impl IntegerMantissaAndExponent for Float { /// Returns a [`Float`]'s integer mantissa and exponent, taking the [`Float`] by value. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = (\frac{|x|}{2^{e_i}}, e_i), /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The inverse operation is /// [`from_integer_mantissa_and_exponent`](IntegerMantissaAndExponent::from_integer_mantissa_and_exponent). /// /// The integer exponent is less than or equal to $2^{30}-2$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// Float::ONE.integer_mantissa_and_exponent(), /// (Natural::ONE, 0) /// ); /// assert_eq!( /// Float::from(std::f64::consts::PI).integer_mantissa_and_exponent(), /// (Natural::from(884279719003555u64), -48) /// ); /// assert_eq!( /// Float::exact_from(Natural::from(3u32).pow(50u64)).integer_mantissa_and_exponent(), /// (Natural::from_str("717897987691852588770249").unwrap(), 0) /// ); /// assert_eq!( /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .integer_mantissa_and_exponent(), /// ( /// Natural::from_str("1067349099133908271875104088939").unwrap(), /// -179 /// ) /// ); /// ``` fn integer_mantissa_and_exponent(self) -> (Natural, i64) { if let Self(Finite { exponent, significand, .. }) = self { let zeros = significand.trailing_zeros().unwrap(); let shifted = significand >> zeros; let bits = shifted.significant_bits(); ( shifted, i64::exact_from(i128::from(exponent) - i128::from(bits)), ) } else { panic!() } } /// Returns a [`Float`]'s integer exponent, taking the [`Float`] by value. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = e_i, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The integer exponent is less than or equal to $2^{30}-2$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Float::ONE.integer_exponent(), 0); /// assert_eq!(Float::from(std::f64::consts::PI).integer_exponent(), -48); /// assert_eq!( /// Float::exact_from(Natural::from(3u32).pow(50u64)).integer_exponent(), /// 0 /// ); /// assert_eq!( /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .integer_exponent(), /// -179 /// ); /// ``` fn integer_exponent(self) -> i64 { if let Self(Finite { exponent, significand, .. }) = self { i64::exact_from( i128::from(exponent) - i128::from( significand.significant_bits() - significand.trailing_zeros().unwrap(), ), ) } else { panic!() } } /// Constructs a [`Float`] from its integer mantissa and exponent. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// The input does not have to be reduced; that is, the mantissa does not have to be odd. If the /// inputs correspond to a number too large in absolute value or too close to zero to be /// represented by a [`Float`], `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `integer_mantissa.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// Float::from_integer_mantissa_and_exponent(Natural::ONE, 0).unwrap(), /// 1 /// ); /// assert_eq!( /// Float::from_integer_mantissa_and_exponent(Natural::from(884279719003555u64), -48) /// .unwrap(), /// std::f64::consts::PI /// ); /// assert_eq!( /// Float::from_integer_mantissa_and_exponent( /// Natural::from_str("717897987691852588770249").unwrap(), /// 0 /// ) /// .unwrap(), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// Float::from_integer_mantissa_and_exponent( /// Natural::from_str("1067349099133908271875104088939").unwrap(), /// -179 /// ) /// .unwrap(), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// ``` fn from_integer_mantissa_and_exponent( integer_mantissa: Natural, integer_exponent: i64, ) -> Option { let nonzero = integer_mantissa != 0u32; let x = Self::exact_from(integer_mantissa) << integer_exponent; if x.is_infinite() || (nonzero && x == 0) { None } else { Some(x) } } } impl IntegerMantissaAndExponent for &Float { /// Returns a [`Float`]'s integer mantissa and exponent, taking the [`Float`] by reference. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = (\frac{|x|}{2^{e_i}}, e_i), /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The inverse operation is /// [`from_integer_mantissa_and_exponent`](IntegerMantissaAndExponent::from_integer_mantissa_and_exponent). /// /// The integer exponent is less than or equal to $2^{30}-2$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// (&Float::ONE).integer_mantissa_and_exponent(), /// (Natural::ONE, 0) /// ); /// assert_eq!( /// (&Float::from(std::f64::consts::PI)).integer_mantissa_and_exponent(), /// (Natural::from(884279719003555u64), -48) /// ); /// assert_eq!( /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).integer_mantissa_and_exponent(), /// (Natural::from_str("717897987691852588770249").unwrap(), 0) /// ); /// assert_eq!( /// (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0) /// .integer_mantissa_and_exponent(), /// ( /// Natural::from_str("1067349099133908271875104088939").unwrap(), /// -179 /// ) /// ); /// ``` fn integer_mantissa_and_exponent(self) -> (Natural, i64) { if let Float(Finite { exponent, significand, .. }) = self { let zeros = significand.trailing_zeros().unwrap(); let shifted = significand >> zeros; let bits = shifted.significant_bits(); ( shifted, i64::exact_from(i128::from(*exponent) - i128::from(bits)), ) } else { panic!() } } /// Returns a [`Float`]'s integer exponent, taking the [`Float`] by reference. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// $$ /// f(x) = e_i, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The integer exponent is less than or equal to $2^{30}-2$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!((&Float::ONE).integer_exponent(), 0); /// assert_eq!((&Float::from(std::f64::consts::PI)).integer_exponent(), -48); /// assert_eq!( /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).integer_exponent(), /// 0 /// ); /// assert_eq!( /// (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0) /// .integer_exponent(), /// -179 /// ); /// ``` fn integer_exponent(self) -> i64 { if let Float(Finite { exponent, significand, .. }) = self { i64::exact_from( i128::from(*exponent) - i128::from( significand.significant_bits() - significand.trailing_zeros().unwrap(), ), ) } else { panic!() } } /// Constructs a [`Float`] from its integer mantissa and exponent. /// /// When $x$ is finite and nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and /// $m_i$ is an odd integer. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// The input does not have to be reduced; that is, the mantissa does not have to be odd. If the /// inputs correspond to a number too large in absolute value or too close to zero to be /// represented by a [`Float`], `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `integer_mantissa.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::ONE, /// 0 /// ) /// .unwrap(), /// 1 /// ); /// assert_eq!( /// <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::from(884279719003555u64), /// -48 /// ) /// .unwrap(), /// std::f64::consts::PI /// ); /// assert_eq!( /// <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::from_str("717897987691852588770249").unwrap(), /// 0 /// ) /// .unwrap(), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::from_str("1067349099133908271875104088939").unwrap(), /// -179 /// ) /// .unwrap(), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// ``` #[inline] fn from_integer_mantissa_and_exponent( integer_mantissa: Natural, integer_exponent: i64, ) -> Option { Float::from_integer_mantissa_and_exponent(integer_mantissa, integer_exponent) } } impl SciMantissaAndExponent for Float { /// Returns a [`Float`]'s scientific mantissa and exponent, taking the [`Float`] by value. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as /// a [`Float`]. /// $$ /// f(x) = (\frac{|x|}{2^{\lfloor \log_2 |x| \rfloor}}, \lfloor \log_2 |x| \rfloor). /// $$ /// /// The returned exponent is always in the range $[-2^{30}, 2^{30}-2]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Float::ONE.sci_mantissa_and_exponent(), (Float::ONE, 0)); /// /// let (m, e) = Float::from(std::f64::consts::PI).sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.570796326794897"); /// assert_eq!(e, 1); /// /// let (m, e) = Float::exact_from(Natural::from(3u32).pow(50u64)).sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.187662594419065093441695"); /// assert_eq!(e, 79); /// /// let (m, e) = Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.683979953059212693885095551367"); /// assert_eq!(e, -80); /// ``` #[inline] fn sci_mantissa_and_exponent(mut self) -> (Self, i32) { if let Self(Finite { sign, exponent, .. }) = &mut self { let old_exponent = *exponent; *exponent = 1; *sign = true; (self, old_exponent - 1) } else { panic!() } } /// Returns a [`Float`]'s scientific exponent, taking the [`Float`] by value. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. /// $$ /// f(x) = \lfloor \log_2 |x| \rfloor. /// $$ /// /// The returned exponent is always in the range $[-2^{30}, 2^{30}-2]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Float::ONE.sci_exponent(), 0); /// assert_eq!(Float::from(std::f64::consts::PI).sci_exponent(), 1); /// assert_eq!( /// Float::exact_from(Natural::from(3u32).pow(50u64)).sci_exponent(), /// 79 /// ); /// assert_eq!( /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100) /// .0 /// .sci_exponent(), /// -80 /// ); /// ``` #[inline] fn sci_exponent(self) -> i32 { self.raw_exponent() - 1 } /// Constructs a [`Float`] from its scientific mantissa and exponent. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// If the mantissa is zero or not finite, this function panics. If it is finite but not in the /// interval $[1, 2)$, `None` is returned. If the inputs correspond to a number too large in /// absolute value or too close to zero to be represented by a [`Float`], `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{FromStringBase, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Float::from_sci_mantissa_and_exponent(Float::ONE, 0).unwrap(), /// 1 /// ); /// assert_eq!( /// Float::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.921fb54442d18#53").unwrap(), /// 1 /// ) /// .unwrap(), /// std::f64::consts::PI /// ); /// assert_eq!( /// Float::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.300aa7e1b65fa13bc792#80").unwrap(), /// 79 /// ) /// .unwrap(), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// Float::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.af194f6982497a23f9dc546d6#100").unwrap(), /// -80 /// ) /// .unwrap(), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// ``` fn from_sci_mantissa_and_exponent(mut sci_mantissa: Self, sci_exponent: i32) -> Option { assert!(sci_mantissa.is_finite()); assert!(!sci_mantissa.is_zero()); if sci_mantissa.is_sign_negative() || (&sci_mantissa).raw_exponent() != 1 || !(Self::MIN_EXPONENT - 1..=Self::MAX_EXPONENT - 1).contains(&sci_exponent) { return None; } if let Self(Finite { exponent, .. }) = &mut sci_mantissa { *exponent = sci_exponent + 1; } else { panic!() } Some(sci_mantissa) } } impl SciMantissaAndExponent for &Float { /// Returns a [`Float`]'s scientific mantissa and exponent, taking the [`Float`] by reference. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as /// a [`Float`]. /// $$ /// f(x) = (\frac{|x|}{2^{\lfloor \log_2 |x| \rfloor}}, \lfloor \log_2 |x| \rfloor). /// $$ /// /// The returned exponent is always in the range $[-2^{30}, 2^{30}-2]$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!((&Float::ONE).sci_mantissa_and_exponent(), (Float::ONE, 0)); /// /// let (m, e): (Float, i32) = (&Float::from(std::f64::consts::PI)).sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.570796326794897"); /// assert_eq!(e, 1); /// /// let (m, e): (Float, i32) = /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.187662594419065093441695"); /// assert_eq!(e, 79); /// /// let (m, e): (Float, i32) = /// (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0) /// .sci_mantissa_and_exponent(); /// assert_eq!(m.to_string(), "1.683979953059212693885095551367"); /// assert_eq!(e, -80); /// ``` #[inline] fn sci_mantissa_and_exponent(self) -> (Float, i32) { if let Float(Finite { exponent, precision, significand, .. }) = self { ( Float(Finite { sign: true, exponent: 1, precision: *precision, significand: significand.clone(), }), exponent - 1, ) } else { panic!() } } /// Returns a [`Float`]'s scientific exponent, taking the [`Float`] by reference. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. /// $$ /// f(x) = \lfloor \log_2 |x| \rfloor. /// $$ /// /// The returned exponent is always in the range $[-2^{30}, 2^{30}-2]$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// <&Float as SciMantissaAndExponent>::sci_exponent(&Float::ONE), /// 0 /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::sci_exponent(&Float::from( /// std::f64::consts::PI /// )), /// 1 /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::sci_exponent(&Float::exact_from( /// Natural::from(3u32).pow(50u64) /// )), /// 79 /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::sci_exponent( /// &Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ), /// -80 /// ); /// ``` #[inline] fn sci_exponent(self) -> i32 { self.raw_exponent() - 1 } /// Constructs a [`Float`] from its scientific mantissa and exponent. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an integer /// and $m_s$ is a rational number with $1 \leq m_s < 2$. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// If the mantissa is zero or not finite, this function panics. If it is finite but not in the /// interval $[1, 2)$, this function returns `None`. /// /// If the mantissa is zero or not finite, this function panics. If it is finite but not in the /// interval $[1, 2)$, `None` is returned. If the inputs correspond to a number too large in /// absolute value or too close to zero to be represented by a [`Float`], `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{FromStringBase, SciMantissaAndExponent}; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Float::from_sci_mantissa_and_exponent(Float::ONE, 0).unwrap(), /// 1 /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.921fb54442d18#53").unwrap(), /// 1 /// ) /// .unwrap(), /// std::f64::consts::PI /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.300aa7e1b65fa13bc792#80").unwrap(), /// 79 /// ) /// .unwrap(), /// Natural::from(3u32).pow(50u64) /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// Float::from_string_base(16, "0x1.af194f6982497a23f9dc546d6#100").unwrap(), /// -80 /// ) /// .unwrap(), /// Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0 /// ); /// ``` #[inline] fn from_sci_mantissa_and_exponent(sci_mantissa: Float, sci_exponent: i32) -> Option { Float::from_sci_mantissa_and_exponent(sci_mantissa, sci_exponent) } } macro_rules! impl_mantissa_and_exponent { ($t:ident) => { impl SciMantissaAndExponent<$t, i32, Float> for &Float { /// Returns a [`Float`]'s scientific mantissa and exponent, taking the [`Float`] by /// value. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an /// integer and $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the /// rational mantissa as a primitive float. The conversion might not be exact, so we /// round to the nearest float using the `Nearest` rounding mode. To use other rounding /// modes, use /// [`sci_mantissa_and_exponent_round`](Float::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx (\frac{|x|}{2^{\lfloor \log_2 |x| \rfloor}}, /// \lfloor \log_2 |x| \rfloor). /// $$ /// /// The returned exponent is always in the range $[-2^{30}, 2^{30}-2]$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero or not finite. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($t, i32) { let (m, e, _) = self.sci_mantissa_and_exponent_round(Nearest).unwrap(); (m, e) } /// Constructs a [`Float`] from its scientific mantissa and exponent. /// /// When $x$ is finite and nonzero, we can write $|x| = 2^{e_s}m_s$, where $e_s$ is an /// integer and $m_s$ is a rational number with $1 \leq m_s < 2$. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// If the mantissa is zero or not finite, this function panics. If it is finite but not /// in the interval $[1, 2)$, `None` is returned. If the inputs correspond to a number /// too large in absolute value or too close to zero to be represented by a [`Float`], /// `None` is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_sci_mantissa_and_exponent). #[allow(clippy::manual_range_contains)] #[inline] fn from_sci_mantissa_and_exponent( sci_mantissa: $t, sci_exponent: i32, ) -> Option { assert!(sci_mantissa.is_finite()); assert_ne!(sci_mantissa, 0.0); if sci_mantissa < 1.0 || sci_mantissa >= 2.0 || sci_exponent > Float::MAX_EXPONENT - 1 || sci_exponent < Float::MIN_EXPONENT - 1 { None } else { let m = sci_mantissa.integer_mantissa(); (Float::from(m) << (i128::from(sci_exponent) - i128::from(m.significant_bits()) + 1)) .to_finite() } } } }; } apply_to_primitive_floats!(impl_mantissa_and_exponent); ================================================ FILE: malachite-float/src/conversion/mod.rs ================================================ // Copyright © 2026 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 . /// Functions for creating a [`Float`](crate::Float) from an infinite iterator of bits. pub mod from_bits; /// Implementations of the [`From`] trait for converting an /// [`Integer`](malachite_nz::integer::Integer) to a [`Float`](crate::Float). pub mod from_integer; /// Implementations of the [`From`] trait for converting an /// [`Natural`](malachite_nz::natural::Natural) to a [`Float`](crate::Float). pub mod from_natural; /// Various functions and implementations of the [`From`] trait for converting a primitive float to /// a [`Float`](crate::Float). /// /// # from /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_float::Float; /// /// assert_eq!(Float::from(f64::NAN).to_string(), "NaN"); /// assert_eq!(Float::from(f64::INFINITY).to_string(), "Infinity"); /// assert_eq!(Float::from(f64::NEGATIVE_INFINITY).to_string(), "-Infinity"); /// assert_eq!(Float::from(0.0).to_string(), "0.0"); /// assert_eq!(Float::from(-0.0).to_string(), "-0.0"); /// assert_eq!(Float::from(123.0).to_string(), "123.0"); /// assert_eq!(Float::from(-123.0).to_string(), "-123.0"); /// ``` /// /// # from_primitive_float_prec /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_primitive_float_prec(f64::NAN, 4); /// assert_eq!(x.to_string(), "NaN"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_primitive_float_prec(1.0 / 3.0, 4); /// assert_eq!(x.to_string(), "0.34"); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_primitive_float_prec(123.0, 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(o, Less); /// ``` /// /// # from_primitive_float_prec_round /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_primitive_float_prec_round(f64::NAN, 4, Floor); /// assert_eq!(x.to_string(), "NaN"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_primitive_float_prec_round(1.0 / 3.0, 4, Floor); /// assert_eq!(x.to_string(), "0.31"); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_primitive_float_prec_round(1.0 / 3.0, 4, Ceiling); /// assert_eq!(x.to_string(), "0.34"); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_primitive_float_prec_round(1.0 / 3.0, 4, Nearest); /// assert_eq!(x.to_string(), "0.34"); /// assert_eq!(o, Greater); /// ``` pub mod from_primitive_float; /// Various functions and implementations of the [`From`] trait for converting a primitive integer /// to a [`Float`](crate::Float). /// /// # from /// ``` /// use malachite_float::Float; /// /// assert_eq!(Float::from(0u32).to_string(), "0.0"); /// assert_eq!(Float::from(123u32).to_string(), "123.0"); /// assert_eq!(Float::from(123u32).get_prec(), Some(7)); /// /// assert_eq!(Float::from(0i32).to_string(), "0.0"); /// assert_eq!(Float::from(123i32).to_string(), "123.0"); /// assert_eq!(Float::from(123i32).get_prec(), Some(7)); /// assert_eq!(Float::from(-123i32).to_string(), "-123.0"); /// ``` /// /// # from_unsigned_prec /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_unsigned_prec(0u32, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_unsigned_prec(123u32, 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_unsigned_prec(123u32, 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// ``` /// /// # from_signed_prec /// ``` /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_signed_prec(0i32, 10); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec(123i32, 20); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec(123i32, 4); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_signed_prec(-123i32, 20); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec(-123i32, 4); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` /// /// # from_unsigned_prec_round /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_unsigned_prec_round(0u32, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_unsigned_prec_round(123u32, 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_unsigned_prec_round(123u32, 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_unsigned_prec_round(123u32, 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` /// /// # from_signed_prec_round /// ``` /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// let (x, o) = Float::from_signed_prec_round(0i32, 10, Exact); /// assert_eq!(x.to_string(), "0.0"); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec_round(123i32, 20, Exact); /// assert_eq!(x.to_string(), "123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec_round(123i32, 4, Floor); /// assert_eq!(x.to_string(), "1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_signed_prec_round(123i32, 4, Ceiling); /// assert_eq!(x.to_string(), "1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// /// let (x, o) = Float::from_signed_prec_round(-123i32, 20, Exact); /// assert_eq!(x.to_string(), "-123.0"); /// assert_eq!(x.get_prec(), Some(20)); /// assert_eq!(o, Equal); /// /// let (x, o) = Float::from_signed_prec_round(-123i32, 4, Floor); /// assert_eq!(x.to_string(), "-1.3e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Less); /// /// let (x, o) = Float::from_signed_prec_round(-123i32, 4, Ceiling); /// assert_eq!(x.to_string(), "-1.2e2"); /// assert_eq!(x.get_prec(), Some(4)); /// assert_eq!(o, Greater); /// ``` pub mod from_primitive_int; /// Implementations of the [`From`] trait for converting a [`Rational`](malachite_q::Rational) to a /// [`Float`](crate::Float). pub mod from_rational; /// Implementations of traits for converting a [`Float`](crate::Float) to an /// [`Integer`](malachite_nz::integer::Integer). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). pub mod integer_from_float; /// An implementation of [`IsInteger`](malachite_base::num::conversion::traits::IsInteger), a trait /// for determining whether a number is an integer. pub mod is_integer; /// Implementations of traits for converting [`Float`](crate::Float)s to and from /// mantissa-and-exponent representations. /// /// The traits are /// [`RawMantissaAndExponent`](malachite_base::num::conversion::traits::RawMantissaAndExponent), /// [`IntegerMantissaAndExponent`](malachite_base::num::conversion::traits::IntegerMantissaAndExponent), /// and [`SciMantissaAndExponent`](malachite_base::num::conversion::traits::SciMantissaAndExponent). /// /// Here are some examples of the macro-generated functions: /// /// # sci_mantissa_and_exponent /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let (m, e): (f64, i32) = (&Float::ONE).sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(1.0)); /// assert_eq!(e, 0); /// /// let (m, e): (f64, i32) = (&Float::from(std::f64::consts::PI)).sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(std::f64::consts::FRAC_PI_2)); /// assert_eq!(e, 1); /// /// let (m, e): (f64, i32) = /// (&Float::exact_from(Natural::from(3u32).pow(50u64))).sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(1.187662594419065)); /// assert_eq!(e, 79); /// /// let (m, e): (f64, i32) = (&Float::from_rational_prec(Rational::from(3u32).pow(-50i64), 100).0) /// .sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(1.6839799530592128)); /// assert_eq!(e, -80); /// ``` /// /// # from_sci_mantissa_and_exponent /// ``` /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_float::Float; /// /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent(1.0, 0) /// .unwrap() /// .to_string(), /// "1.0" /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// std::f64::consts::FRAC_PI_2, /// 1 /// ) /// .unwrap() /// .to_string(), /// "3.141592653589793" /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// 1.187662594419065, /// 79 /// ) /// .unwrap() /// .to_string(), /// "7.178979876918526e23" /// ); /// assert_eq!( /// <&Float as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( /// 1.6839799530592128, /// -80 /// ) /// .unwrap() /// .to_string(), /// "1.392955569098538e-24" /// ); /// ``` pub mod mantissa_and_exponent; /// Implementations of traits for converting a [`Float`](crate::Float) to a /// [`Natural`](malachite_nz::natural::Natural). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). pub mod natural_from_float; /// Functions and implementations of traits for converting a [`Float`](crate::Float) to a primitive /// float. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # convertible_from /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// /// assert_eq!(f32::convertible_from(&Float::NAN), true); /// assert_eq!(f32::convertible_from(&Float::INFINITY), true); /// assert_eq!(f32::convertible_from(&Float::ZERO), true); /// assert_eq!(f32::convertible_from(&Float::from(1.5)), true); /// assert_eq!(f32::convertible_from(&Float::from(-1.5)), true); /// assert_eq!(f32::convertible_from(&Float::from(123.0)), true); /// assert_eq!(f32::convertible_from(&Float::from(-123.0)), true); /// /// // Even though precision is high, the value is just 1.0 and can be converted /// assert_eq!(f32::convertible_from(&Float::one_prec(100)), true); /// /// let mut x = Float::one_prec(40); /// x.increment(); /// /// // precision too high for f32 /// assert_eq!(f32::convertible_from(&x), false); /// /// // but not for f64 /// assert_eq!(f64::convertible_from(&x), true); /// /// assert_eq!(f32::convertible_from(&Float::power_of_2(100u64)), true); /// assert_eq!(f32::convertible_from(&Float::power_of_2(1000u64)), false); /// assert_eq!(f64::convertible_from(&Float::power_of_2(1000u64)), true); /// assert_eq!(f64::convertible_from(&Float::power_of_2(10000u64)), false); /// ``` /// /// # try_from /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::float::NiceFloat; /// use malachite_float::conversion::primitive_float_from_float::FloatFromFloatError; /// use malachite_float::Float; /// /// assert_eq!( /// NiceFloat(f32::try_from(Float::NAN).unwrap()), /// NiceFloat(f32::NAN) /// ); /// assert_eq!(f32::try_from(Float::INFINITY), Ok(f32::INFINITY)); /// assert_eq!(f32::try_from(Float::ZERO), Ok(0.0)); /// assert_eq!(f32::try_from(Float::from(1.5)), Ok(1.5)); /// assert_eq!(f32::try_from(Float::from(-1.5)), Ok(-1.5)); /// assert_eq!(f32::try_from(Float::from(123.0)), Ok(123.0)); /// assert_eq!(f32::try_from(Float::from(-123.0)), Ok(-123.0)); /// /// // Even though precision is high, the value is just 1.0 and can be converted /// assert_eq!(f32::try_from(Float::one_prec(100)), Ok(1.0)); /// /// let mut x = Float::one_prec(40); /// x.increment(); /// /// // precision too high for f32 /// assert_eq!(f32::try_from(x.clone()), Err(FloatFromFloatError::Inexact)); /// /// // but not for f64 /// assert_eq!( /// NiceFloat(f64::try_from(x).unwrap()), /// NiceFloat(1.000000000001819) /// ); /// /// assert_eq!( /// NiceFloat(f32::try_from(Float::power_of_2(100u64)).unwrap()), /// NiceFloat(1.2676506e30) /// ); /// assert_eq!( /// f32::try_from(Float::power_of_2(1000u64)), /// Err(FloatFromFloatError::Overflow) /// ); /// assert_eq!( /// NiceFloat(f64::try_from(Float::power_of_2(1000u64)).unwrap()), /// NiceFloat(1.0715086071862673e301) /// ); /// assert_eq!( /// f64::try_from(Float::power_of_2(10000u64)), /// Err(FloatFromFloatError::Overflow) /// ); /// /// assert_eq!( /// NiceFloat(f32::try_from(&Float::NAN).unwrap()), /// NiceFloat(f32::NAN) /// ); /// assert_eq!(f32::try_from(&Float::INFINITY), Ok(f32::INFINITY)); /// assert_eq!(f32::try_from(&Float::ZERO), Ok(0.0)); /// assert_eq!(f32::try_from(&Float::from(1.5)), Ok(1.5)); /// assert_eq!(f32::try_from(&Float::from(-1.5)), Ok(-1.5)); /// assert_eq!(f32::try_from(&Float::from(123.0)), Ok(123.0)); /// assert_eq!(f32::try_from(&Float::from(-123.0)), Ok(-123.0)); /// /// // Even though precision is high, the value is just 1.0 and can be converted /// assert_eq!(f32::try_from(&Float::one_prec(100)), Ok(1.0)); /// /// let mut x = Float::one_prec(40); /// x.increment(); /// /// // precision too high for f32 /// assert_eq!(f32::try_from(&x), Err(FloatFromFloatError::Inexact)); /// /// // but not for f64 /// assert_eq!( /// NiceFloat(f64::try_from(&x).unwrap()), /// NiceFloat(1.000000000001819) /// ); /// /// assert_eq!( /// NiceFloat(f32::try_from(&Float::power_of_2(100u64)).unwrap()), /// NiceFloat(1.2676506e30) /// ); /// assert_eq!( /// f32::try_from(&Float::power_of_2(1000u64)), /// Err(FloatFromFloatError::Overflow) /// ); /// assert_eq!( /// NiceFloat(f64::try_from(&Float::power_of_2(1000u64)).unwrap()), /// NiceFloat(1.0715086071862673e301) /// ); /// assert_eq!( /// f64::try_from(&Float::power_of_2(10000u64)), /// Err(FloatFromFloatError::Overflow) /// ); /// ``` /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let f = Float::from_rational_prec(Rational::from_signeds(1, 3), 100).0; /// /// let (x, o) = f32::rounding_from(f.clone(), Floor); /// assert_eq!(NiceFloat(x), NiceFloat(0.3333333)); /// assert_eq!(o, Less); /// /// let (x, o) = f32::rounding_from(f.clone(), Ceiling); /// assert_eq!(NiceFloat(x), NiceFloat(0.33333334)); /// assert_eq!(o, Greater); /// /// let (x, o) = f32::rounding_from(f.clone(), Nearest); /// assert_eq!(NiceFloat(x), NiceFloat(0.33333334)); /// assert_eq!(o, Greater); /// /// let (x, o) = f32::rounding_from(&f, Floor); /// assert_eq!(NiceFloat(x), NiceFloat(0.3333333)); /// assert_eq!(o, Less); /// /// let (x, o) = f32::rounding_from(&f, Ceiling); /// assert_eq!(NiceFloat(x), NiceFloat(0.33333334)); /// assert_eq!(o, Greater); /// /// let (x, o) = f32::rounding_from(&f, Nearest); /// assert_eq!(NiceFloat(x), NiceFloat(0.33333334)); /// assert_eq!(o, Greater); /// ``` pub mod primitive_float_from_float; /// Functions and implementations of traits for converting a [`Float`](crate::Float) to a primitive /// integer. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_float::Float; /// use std::cmp::Ordering::*; /// /// assert_eq!(u8::rounding_from(Float::from(1.5), Floor), (1, Less)); /// assert_eq!(u8::rounding_from(Float::from(1.5), Ceiling), (2, Greater)); /// assert_eq!(u8::rounding_from(Float::from(1.5), Nearest), (2, Greater)); /// /// assert_eq!(u8::rounding_from(Float::from(256.0), Down), (255, Less)); /// assert_eq!(u8::rounding_from(Float::from(256.0), Floor), (255, Less)); /// assert_eq!(u8::rounding_from(Float::from(256.0), Nearest), (255, Less)); /// /// assert_eq!(u8::rounding_from(Float::from(-123.0), Down), (0, Greater)); /// assert_eq!( /// u8::rounding_from(Float::from(-123.0), Ceiling), /// (0, Greater) /// ); /// assert_eq!( /// u8::rounding_from(Float::from(-123.0), Nearest), /// (0, Greater) /// ); /// /// assert_eq!(i8::rounding_from(Float::from(1.5), Floor), (1, Less)); /// assert_eq!(i8::rounding_from(Float::from(1.5), Ceiling), (2, Greater)); /// assert_eq!(i8::rounding_from(Float::from(1.5), Nearest), (2, Greater)); /// /// assert_eq!(i8::rounding_from(Float::from(-1.5), Floor), (-2, Less)); /// assert_eq!(i8::rounding_from(Float::from(-1.5), Ceiling), (-1, Greater)); /// assert_eq!(i8::rounding_from(Float::from(-1.5), Nearest), (-2, Less)); /// /// assert_eq!(i8::rounding_from(Float::from(128.0), Down), (127, Less)); /// assert_eq!(i8::rounding_from(Float::from(128.0), Floor), (127, Less)); /// assert_eq!(i8::rounding_from(Float::from(128.0), Nearest), (127, Less)); /// /// assert_eq!( /// i8::rounding_from(Float::from(-129.0), Down), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(Float::from(-129.0), Ceiling), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(Float::from(-129.0), Nearest), /// (-128, Greater) /// ); /// /// assert_eq!(u8::rounding_from(&Float::from(1.5), Floor), (1, Less)); /// assert_eq!(u8::rounding_from(&Float::from(1.5), Ceiling), (2, Greater)); /// assert_eq!(u8::rounding_from(&Float::from(1.5), Nearest), (2, Greater)); /// /// assert_eq!(u8::rounding_from(&Float::from(256.0), Down), (255, Less)); /// assert_eq!(u8::rounding_from(&Float::from(256.0), Floor), (255, Less)); /// assert_eq!(u8::rounding_from(&Float::from(256.0), Nearest), (255, Less)); /// /// assert_eq!(u8::rounding_from(&Float::from(-123.0), Down), (0, Greater)); /// assert_eq!( /// u8::rounding_from(&Float::from(-123.0), Ceiling), /// (0, Greater) /// ); /// assert_eq!( /// u8::rounding_from(&Float::from(-123.0), Nearest), /// (0, Greater) /// ); /// /// assert_eq!(i8::rounding_from(&Float::from(1.5), Floor), (1, Less)); /// assert_eq!(i8::rounding_from(&Float::from(1.5), Ceiling), (2, Greater)); /// assert_eq!(i8::rounding_from(&Float::from(1.5), Nearest), (2, Greater)); /// /// assert_eq!(i8::rounding_from(&Float::from(-1.5), Floor), (-2, Less)); /// assert_eq!( /// i8::rounding_from(&Float::from(-1.5), Ceiling), /// (-1, Greater) /// ); /// assert_eq!(i8::rounding_from(&Float::from(-1.5), Nearest), (-2, Less)); /// /// assert_eq!(i8::rounding_from(&Float::from(128.0), Down), (127, Less)); /// assert_eq!(i8::rounding_from(&Float::from(128.0), Floor), (127, Less)); /// assert_eq!(i8::rounding_from(&Float::from(128.0), Nearest), (127, Less)); /// /// assert_eq!( /// i8::rounding_from(&Float::from(-129.0), Down), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(&Float::from(-129.0), Ceiling), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(&Float::from(-129.0), Nearest), /// (-128, Greater) /// ); /// ``` /// /// # try_from /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError}; /// use malachite_float::Float; /// /// assert_eq!(u8::try_from(Float::ZERO).unwrap(), 0); /// assert_eq!(u8::try_from(Float::from(123.0)).unwrap(), 123); /// /// assert_eq!( /// u8::try_from(Float::from(-123.0)), /// Err(UnsignedFromFloatError::FloatNegative) /// ); /// assert_eq!( /// u8::try_from(Float::from(256.0)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(Float::from(1.5)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(Float::INFINITY), /// Err(UnsignedFromFloatError::FloatInfiniteOrNan) /// ); /// assert_eq!( /// u8::try_from(Float::NAN), /// Err(UnsignedFromFloatError::FloatInfiniteOrNan) /// ); /// /// assert_eq!(i8::try_from(Float::ZERO).unwrap(), 0); /// assert_eq!(i8::try_from(Float::from(123.0)).unwrap(), 123); /// assert_eq!(i8::try_from(Float::from(-123.0)).unwrap(), -123); /// /// assert_eq!( /// i8::try_from(Float::from(128.0)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(Float::from(-129.0)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(Float::from(1.5)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(Float::INFINITY), /// Err(SignedFromFloatError::FloatInfiniteOrNan) /// ); /// assert_eq!( /// i8::try_from(Float::NAN), /// Err(SignedFromFloatError::FloatInfiniteOrNan) /// ); /// /// assert_eq!(u8::try_from(&Float::ZERO).unwrap(), 0); /// assert_eq!(u8::try_from(&Float::from(123.0)).unwrap(), 123); /// /// assert_eq!( /// u8::try_from(&Float::from(-123.0)), /// Err(UnsignedFromFloatError::FloatNegative) /// ); /// assert_eq!( /// u8::try_from(&Float::from(256.0)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(&Float::from(1.5)), /// Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// u8::try_from(&Float::INFINITY), /// Err(UnsignedFromFloatError::FloatInfiniteOrNan) /// ); /// assert_eq!( /// u8::try_from(&Float::NAN), /// Err(UnsignedFromFloatError::FloatInfiniteOrNan) /// ); /// /// assert_eq!(i8::try_from(&Float::ZERO).unwrap(), 0); /// assert_eq!(i8::try_from(&Float::from(123.0)).unwrap(), 123); /// assert_eq!(i8::try_from(&Float::from(-123.0)).unwrap(), -123); /// /// assert_eq!( /// i8::try_from(&Float::from(128.0)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(&Float::from(-129.0)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(&Float::from(1.5)), /// Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!( /// i8::try_from(&Float::INFINITY), /// Err(SignedFromFloatError::FloatInfiniteOrNan) /// ); /// assert_eq!( /// i8::try_from(&Float::NAN), /// Err(SignedFromFloatError::FloatInfiniteOrNan) /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// /// assert_eq!(u8::convertible_from(&Float::ZERO), true); /// assert_eq!(u8::convertible_from(&Float::from(123.0)), true); /// /// assert_eq!(u8::convertible_from(&Float::from(256.0)), false); /// assert_eq!(u8::convertible_from(&Float::from(-123.0)), false); /// assert_eq!(u8::convertible_from(&Float::from(1.5)), false); /// assert_eq!(u8::convertible_from(&Float::INFINITY), false); /// assert_eq!(u8::convertible_from(&Float::NAN), false); /// /// assert_eq!(i8::convertible_from(&Float::ZERO), true); /// assert_eq!(i8::convertible_from(&Float::from(123.0)), true); /// assert_eq!(i8::convertible_from(&Float::from(-123.0)), true); /// /// assert_eq!(i8::convertible_from(&Float::from(128.0)), false); /// assert_eq!(i8::convertible_from(&Float::from(-129.0)), false); /// assert_eq!(i8::convertible_from(&Float::from(1.5)), false); /// assert_eq!(i8::convertible_from(&Float::INFINITY), false); /// assert_eq!(i8::convertible_from(&Float::NAN), false); /// ``` pub mod primitive_int_from_float; /// Implementations of traits for converting a [`Float`](crate::Float) to a /// [`Rational`](malachite_q::Rational). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). pub mod rational_from_float; /// Implementations of traits for converting [`Float`](crate::Float)s to and from [`String`]s. /// /// Warning: these implementations are unstable and will definitely be changed in the future. pub mod string; ================================================ FILE: malachite-float/src/conversion/natural_from_float.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, Zero}; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound}; use malachite_base::num::basic::traits::{One, Zero as ZeroTrait}; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; impl RoundingFrom for Natural { /// Converts a [`Float`] to a [`Natural`], using a specified [`RoundingMode`] and taking the /// [`Float`] by value. An [`Ordering`] is also returned, indicating whether the returned value /// is less than, equal to, or greater than the original value. /// /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero when the /// [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// If the [`Float`] is NaN or $\infty$, the function will panic regardless of the rounding /// mode. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is less /// than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, or if the [`Float`] is NaN or /// $\infty$. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::rounding_from(Float::from(1.5), Floor).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(Float::from(1.5), Ceiling).to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Float::from(1.5), Nearest).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Natural::rounding_from(Float::NEGATIVE_INFINITY, Down).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Float::NEGATIVE_INFINITY, Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Float::NEGATIVE_INFINITY, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` fn rounding_from(f: Float, rm: RoundingMode) -> (Self, Ordering) { match f { float_either_zero!() => (Self::ZERO, Equal), float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (Self::ZERO, Greater), _ => panic!("Can't convert -Infinity to Natural using {rm}"), }, Float(Finite { sign, exponent, significand, .. }) => { if !sign { match rm { Ceiling | Down | Nearest => (Self::ZERO, Greater), _ => panic!("Cannot convert negative number to Natural using {rm}"), } } else if exponent < 0 { match rm { Floor | Down | Nearest => (Self::ZERO, Less), Ceiling | Up => (Self::ONE, Greater), Exact => panic!("Cannot convert Float to Natural using {rm}"), } } else { let sb = significand_bits(&significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) } } } _ => panic!("Can't convert {f} to Natural using {rm}"), } } } impl RoundingFrom<&Float> for Natural { /// Converts a [`Float`] to a [`Natural`], using a specified [`RoundingMode`] and taking the /// [`Float`] by reference. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero when the /// [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// If the [`Float`] is NaN or $\infty$, the function will panic regardless of the rounding /// mode. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] is less /// than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, or if the [`Float`] is NaN or /// $\infty$. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::rounding_from(&Float::from(1.5), Floor).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(&Float::from(1.5), Ceiling).to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Float::from(1.5), Nearest).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Natural::rounding_from(&Float::NEGATIVE_INFINITY, Down).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Float::NEGATIVE_INFINITY, Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Float::NEGATIVE_INFINITY, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` fn rounding_from(f: &Float, rm: RoundingMode) -> (Self, Ordering) { match f { float_either_zero!() => (Self::ZERO, Equal), float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (Self::ZERO, Greater), _ => panic!("Can't convert -Infinity to Natural using {rm}"), }, Float(Finite { sign, exponent, significand, .. }) => { if !sign { match rm { Ceiling | Down | Nearest => (Self::ZERO, Greater), _ => panic!("Cannot convert -Infinity to Natural using {rm}"), } } else if *exponent < 0 { match rm { Floor | Down | Nearest => (Self::ZERO, Less), Ceiling | Up => (Self::ONE, Greater), Exact => panic!("Cannot convert Float to Natural using {rm}"), } } else { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) } } } _ => panic!("Can't convert {f} to Natural using {rm}"), } } } impl TryFrom for Natural { type Error = UnsignedFromFloatError; /// Converts a [`Float`] to a [`Natural`], taking the [`Float`] by value. If the [`Float`] is /// not equal to a non-negative integer, an error is returned. /// /// Both positive and negative zero convert to a [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::from::UnsignedFromFloatError::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::try_from(Float::ZERO).unwrap(), 0); /// assert_eq!(Natural::try_from(Float::from(123.0)).unwrap(), 123); /// /// assert_eq!(Natural::try_from(Float::from(-123.0)), Err(FloatNegative)); /// assert_eq!( /// Natural::try_from(Float::from(1.5)), /// Err(FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!(Natural::try_from(Float::INFINITY), Err(FloatInfiniteOrNan)); /// assert_eq!(Natural::try_from(Float::NAN), Err(FloatInfiniteOrNan)); /// ``` fn try_from(f: Float) -> Result { match f { float_either_zero!() => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { if !sign { Err(UnsignedFromFloatError::FloatNegative) } else if exponent <= 0 { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(&significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(significand >> bits) } else { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(significand << (eb - sb)) } } } _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan), } } } impl TryFrom<&Float> for Natural { type Error = UnsignedFromFloatError; /// Converts a [`Float`] to a [`Natural`], taking the [`Float`] by reference. If the [`Float`] /// is not equal to a non-negative integer, an error is returned. /// /// Both positive and negative zero convert to a [`Natural`] zero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::from::UnsignedFromFloatError::*; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::try_from(&Float::ZERO).unwrap(), 0); /// assert_eq!(Natural::try_from(&Float::from(123.0)).unwrap(), 123); /// /// assert_eq!(Natural::try_from(&Float::from(-123.0)), Err(FloatNegative)); /// assert_eq!( /// Natural::try_from(&Float::from(1.5)), /// Err(FloatNonIntegerOrOutOfRange) /// ); /// assert_eq!(Natural::try_from(&Float::INFINITY), Err(FloatInfiniteOrNan)); /// assert_eq!(Natural::try_from(&Float::NAN), Err(FloatInfiniteOrNan)); /// ``` fn try_from(f: &Float) -> Result { match f { float_either_zero!() => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { if !*sign { Err(UnsignedFromFloatError::FloatNegative) } else if *exponent <= 0 { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(significand >> bits) } else { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(significand << (eb - sb)) } } } _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan), } } } impl ConvertibleFrom<&Float> for Natural { /// Determines whether a [`Float`] can be converted to a [`Natural`] (when the [`Float`] is /// non-negative and an integer), taking the [`Float`] by reference. /// /// Both positive and negative zero are convertible to a [`Natural`]. (Although negative zero is /// nominally negative, the real number it represents is zero, which is not negative.) /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::convertible_from(&Float::ZERO), true); /// assert_eq!(Natural::convertible_from(&Float::from(123.0)), true); /// /// assert_eq!(Natural::convertible_from(&Float::from(-123.0)), false); /// assert_eq!(Natural::convertible_from(&Float::from(1.5)), false); /// assert_eq!(Natural::convertible_from(&Float::INFINITY), false); /// assert_eq!(Natural::convertible_from(&Float::NAN), false); /// ``` fn convertible_from(f: &Float) -> bool { match f { float_either_zero!() => true, Float(Finite { sign, exponent, significand, .. }) => { *sign && *exponent > 0 && { let sb = significand_bits(significand); let eb = u64::from(exponent.unsigned_abs()); sb < eb || significand.divisible_by_power_of_2(sb - eb) } } _ => false, } } } ================================================ FILE: malachite-float/src/conversion/primitive_float_from_float.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, IsPowerOf2, ShrRound}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; fn primitive_float_rounding_from_float( f: Float, rm: RoundingMode, ) -> (T, Ordering) { match f { float_nan!() => (T::NAN, Equal), float_infinity!() => (T::INFINITY, Equal), float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal), float_zero!() => (T::ZERO, Equal), float_negative_zero!() => (T::NEGATIVE_ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let abs_rm = if sign { rm } else { -rm }; let (x, o) = { let exponent = i64::from(exponent) - 1; if exponent < T::MIN_EXPONENT { match abs_rm { Floor | Down => (T::ZERO, Less), Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater), Nearest => { if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() { (T::MIN_POSITIVE_SUBNORMAL, Greater) } else { (T::ZERO, Less) } } Exact => panic!("Float too small for exact conversion"), } } else if exponent > T::MAX_EXPONENT { match abs_rm { Floor | Down => (T::MAX_FINITE, Less), Ceiling | Up | Nearest => (T::INFINITY, Greater), Exact => panic!("Float too large for exact conversion"), } } else { let target_prec = T::max_precision_for_sci_exponent(exponent); let bits = significand_bits(&significand); let (mantissa, o) = significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm); let mantissa = u64::wrapping_from(&mantissa); if mantissa.significant_bits() > target_prec { if exponent == T::MAX_EXPONENT { match abs_rm { Floor | Down => (T::MAX_FINITE, Less), Ceiling | Up | Nearest => (T::INFINITY, Greater), Exact => { panic!("Float too large for exact conversion") } } } else { ( T::from_integer_mantissa_and_exponent( mantissa >> 1, exponent - i64::wrapping_from(target_prec) + 2, ) .unwrap(), o, ) } } else { ( T::from_integer_mantissa_and_exponent( mantissa, exponent - i64::wrapping_from(target_prec) + 1, ) .unwrap(), o, ) } } }; if sign { (x, o) } else { (-x, o.reverse()) } } } } fn primitive_float_rounding_from_float_ref( f: &Float, rm: RoundingMode, ) -> (T, Ordering) { match f { float_nan!() => (T::NAN, Equal), float_infinity!() => (T::INFINITY, Equal), float_negative_infinity!() => (T::NEGATIVE_INFINITY, Equal), float_zero!() => (T::ZERO, Equal), float_negative_zero!() => (T::NEGATIVE_ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let abs_rm = if *sign { rm } else { -rm }; let (x, o) = { let exponent = i64::from(*exponent) - 1; if exponent < T::MIN_EXPONENT { match abs_rm { Floor | Down => (T::ZERO, Less), Ceiling | Up => (T::MIN_POSITIVE_SUBNORMAL, Greater), Nearest => { if exponent == T::MIN_EXPONENT - 1 && !significand.is_power_of_2() { (T::MIN_POSITIVE_SUBNORMAL, Greater) } else { (T::ZERO, Less) } } Exact => panic!("Float too small for exact conversion"), } } else if exponent > T::MAX_EXPONENT { match abs_rm { Floor | Down => (T::MAX_FINITE, Less), Ceiling | Up | Nearest => (T::INFINITY, Greater), Exact => panic!("Float too large for exact conversion"), } } else { let target_prec = T::max_precision_for_sci_exponent(exponent); let bits = significand_bits(significand); let (mantissa, o) = significand.shr_round(i128::from(bits) - i128::from(target_prec), abs_rm); let mantissa = u64::wrapping_from(&mantissa); if mantissa.significant_bits() > target_prec { if exponent == T::MAX_EXPONENT { match abs_rm { Floor | Down => (T::MAX_FINITE, Less), Ceiling | Up | Nearest => (T::INFINITY, Greater), Exact => { panic!("Float too large for exact conversion") } } } else { ( T::from_integer_mantissa_and_exponent( mantissa >> 1, exponent - i64::wrapping_from(target_prec) + 2, ) .unwrap(), o, ) } } else { ( T::from_integer_mantissa_and_exponent( mantissa, exponent - i64::wrapping_from(target_prec) + 1, ) .unwrap(), o, ) } } }; if *sign { (x, o) } else { (-x, o.reverse()) } } } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum FloatFromFloatError { Overflow, Underflow, Inexact, } fn primitive_float_try_from_float(f: Float) -> Result { match f { float_nan!() => Ok(T::NAN), float_infinity!() => Ok(T::INFINITY), float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY), float_zero!() => Ok(T::ZERO), float_negative_zero!() => Ok(T::NEGATIVE_ZERO), Float(Finite { sign, exponent, significand, .. }) => { let x = { let exponent = i64::from(exponent) - 1; if exponent < T::MIN_EXPONENT { return Err(FloatFromFloatError::Underflow); } else if exponent > T::MAX_EXPONENT { return Err(FloatFromFloatError::Overflow); } let target_prec = T::max_precision_for_sci_exponent(exponent); let bits = significand_bits(&significand); if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) { return Err(FloatFromFloatError::Inexact); } let mantissa = u64::wrapping_from( &(significand >> (i128::from(bits) - i128::from(target_prec))), ); T::from_integer_mantissa_and_exponent( mantissa, exponent - i64::wrapping_from(target_prec) + 1, ) .unwrap() }; Ok(if sign { x } else { -x }) } } } fn primitive_float_try_from_float_ref( f: &Float, ) -> Result { match f { float_nan!() => Ok(T::NAN), float_infinity!() => Ok(T::INFINITY), float_negative_infinity!() => Ok(T::NEGATIVE_INFINITY), float_zero!() => Ok(T::ZERO), float_negative_zero!() => Ok(T::NEGATIVE_ZERO), Float(Finite { sign, exponent, significand, .. }) => { let x = if *significand == 0u32 { T::ZERO } else { let exponent = i64::from(*exponent) - 1; if exponent < T::MIN_EXPONENT { return Err(FloatFromFloatError::Underflow); } else if exponent > T::MAX_EXPONENT { return Err(FloatFromFloatError::Overflow); } let target_prec = T::max_precision_for_sci_exponent(exponent); let bits = significand_bits(significand); if bits > target_prec && !significand.divisible_by_power_of_2(bits - target_prec) { return Err(FloatFromFloatError::Inexact); } let mantissa = u64::wrapping_from( &(significand >> (i128::from(bits) - i128::from(target_prec))), ); T::from_integer_mantissa_and_exponent( mantissa, exponent - i64::wrapping_from(target_prec) + 1, ) .unwrap() }; Ok(if *sign { x } else { -x }) } } } fn primitive_float_convertible_from_float(f: &Float) -> bool { match f { Float(Finite { exponent, significand, .. }) => { let exponent = i64::from(*exponent) - 1; exponent >= T::MIN_EXPONENT && exponent <= T::MAX_EXPONENT && { let target_prec = T::max_precision_for_sci_exponent(exponent); let bits = significand_bits(significand); bits <= target_prec || significand.divisible_by_power_of_2(bits - target_prec) } } _ => true, } } macro_rules! impl_primitive_float_from { ($t: ident) => { impl RoundingFrom for $t { /// Converts a [`Float`] to a primitive float, using a specified [`RoundingMode`] and /// taking the [`Float`] by value. An [`Ordering`] is also returned, indicating whether /// the returned value is less than, equal to, or greater than the original value. /// (Although a NaN is not comparable to any [`Float`], converting a NaN to a NaN will /// also return `Equal`, indicating an exact conversion.) /// /// Overflow and underflow: /// - If the rounding mode is `Floor`, the largest primitive float less than or equal to /// the [`Float`] is returned. If the [`Float`] is greater than the maximum finite /// primitive float, then the maximum finite primitive float is returned. If it is /// smaller than the minimum finite primitive float, then $-\infty$ is returned. If it /// is between zero and the minimum positive primitive float, then positive zero is /// returned. /// - If the rounding mode is `Ceiling`, the smallest primitive float greater than or /// equal to the [`Float`] is returned. If the [`Float`] is greater than the maximum /// finite primitive float, then $\infty$ is returned. If it is smaller than the /// minimum finite primitive float, then the minimum finite primitive float is /// returned. If it is between zero and the maximum negative primitive float, then /// negative zero is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the /// [`Float`] is non-negative and as with `Ceiling` if the [`Float`] is negative. If /// the [`Float`] is between the maximum negative primitive float and the minimum /// positive primitive float, then positive zero is returned when the [`Float`] is /// non-negative and negative zero otherwise. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the /// [`Float`] is non-negative and as with `Floor` if the [`Float`] is negative. Zero /// is only returned when the [`Float`] is zero. /// - If the rounding mode is `Nearest`, then the nearest primitive float is returned. /// If the [`Float`] is exactly between two primitive floats, the primitive float with /// the zero least-significant bit in its representation is selected. If the [`Float`] /// is greater than the maximum finite primitive float, then $\infty$ is returned. If /// the [`Float`] is smaller than the minimum finite primitive float, then $-\infty$ /// is returned. If the [`Float`] is closer to zero than to any other primitive float /// (or if there is a tie between zero and another float), then positive or negative /// zero is returned, depending on the [`Float`]'s sign. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not exactly equal to any float of the target type, and /// `rm` is `Exact`. /// /// # Examples /// See [here](super::primitive_float_from_float#rounding_from). #[inline] fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) { primitive_float_rounding_from_float(f, rm) } } impl RoundingFrom<&Float> for $t { /// Converts a [`Float`] to a primitive float, using a specified [`RoundingMode`] and /// taking the [`Float`] by reference. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original /// value. (Although a NaN is not comparable to any [`Float`], converting a NaN to a NaN /// will also return `Equal`, indicating an exact conversion.) /// /// Overflow and underflow: /// - If the rounding mode is `Floor`, the largest primitive float less than or equal to /// the [`Float`] is returned. If the [`Float`] is greater than the maximum finite /// primitive float, then the maximum finite primitive float is returned. If it is /// smaller than the minimum finite primitive float, then $-\infty$ is returned. If it /// is between zero and the minimum positive primitive float, then positive zero is /// returned. /// - If the rounding mode is `Ceiling`, the smallest primitive float greater than or /// equal to the [`Float`] is returned. If the [`Float`] is greater than the maximum /// finite primitive float, then $\infty$ is returned. If it is smaller than the /// minimum finite primitive float, then the minimum finite primitive float is /// returned. If it is between zero and the maximum negative primitive float, then /// negative zero is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the /// [`Float`] is non-negative and as with `Ceiling` if the [`Float`] is negative. If /// the [`Float`] is between the maximum negative primitive float and the minimum /// positive primitive float, then positive zero is returned when the [`Float`] is /// non-negative and negative zero otherwise. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the /// [`Float`] is non-negative and as with `Floor` if the [`Float`] is negative. Zero /// is only returned when the [`Float`] is zero. /// - If the rounding mode is `Nearest`, then the nearest primitive float is returned. /// If the [`Float`] is exactly between two primitive floats, the primitive float with /// the zero least-significant bit in its representation is selected. If the [`Float`] /// is greater than the maximum finite primitive float, then $\infty$ is returned. If /// the [`Float`] is smaller than the minimum finite primitive float, then $-\infty$ /// is returned. If the [`Float`] is closer to zero than to any other primitive float /// (or if there is a tie between zero and another float), then positive or negative /// zero is returned, depending on the [`Float`]'s sign. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not exactly equal to any float of the target type, and /// `rm` is `Exact`. /// /// # Examples /// See [here](super::primitive_float_from_float#rounding_from). #[inline] fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) { primitive_float_rounding_from_float_ref(f, rm) } } impl TryFrom for $t { type Error = FloatFromFloatError; /// Converts a [`Float`] to a primitive float, taking the [`Float`] by value. If the /// [`Float`] is not equal to a primitive float of the given type, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_float_from_float#try_from). #[inline] fn try_from(f: Float) -> Result<$t, Self::Error> { primitive_float_try_from_float(f) } } impl TryFrom<&Float> for $t { type Error = FloatFromFloatError; /// Converts a [`Float`] to a primitive float, taking the [`Float`] by reference. If the /// [`Float`] is not equal to a primitive float of the given type, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_float_from_float#try_from). #[inline] fn try_from(f: &Float) -> Result<$t, Self::Error> { primitive_float_try_from_float_ref(f) } } impl ConvertibleFrom<&Float> for $t { /// Determines whether a [`Float`] can be converted to a primitive float, taking the /// [`Float`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_float_from_float#convertible_from). #[inline] fn convertible_from(f: &Float) -> bool { primitive_float_convertible_from_float::<$t>(f) } } }; } apply_to_primitive_floats!(impl_primitive_float_from); ================================================ FILE: malachite-float/src/conversion/primitive_int_from_float.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::arithmetic::is_power_of_2::float_is_signed_min; use crate::{Float, significand_bits}; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError}; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; #[allow(clippy::type_repetition_in_bounds)] fn unsigned_rounding_from_float(f: Float, rm: RoundingMode) -> (T, Ordering) where for<'a> T: TryFrom<&'a Natural>, { match f { float_nan!() => panic!("Can't convert NaN to {}", T::NAME), float_infinity!() => match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm), }, float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm), }, float_either_zero!() => (T::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(exponent); if !sign { match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm), } } else if exponent < 0 { match rm { Floor | Down | Nearest => (T::ZERO, Less), Ceiling | Up => (T::ONE, Greater), Exact => { panic!("Cannot convert Float to {} using {}", T::NAME, rm) } } } else if exponent > i64::wrapping_from(T::WIDTH) { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm), } } else { let sb = significand_bits(&significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&n) { (n, o) } else { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm), } }; (n, o) } } } } #[allow(clippy::type_repetition_in_bounds)] fn unsigned_rounding_from_float_ref( f: &Float, rm: RoundingMode, ) -> (T, Ordering) where for<'a> T: TryFrom<&'a Natural>, { match f { float_nan!() => panic!("Can't convert NaN to {}", T::NAME), float_infinity!() => match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm), }, float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm), }, float_either_zero!() => (T::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(*exponent); if !sign { match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm), } } else if exponent < 0 { match rm { Floor | Down | Nearest => (T::ZERO, Less), Ceiling | Up => (T::ONE, Greater), Exact => { panic!("Cannot convert Float to {} using {}", T::NAME, rm) } } } else if exponent > i64::wrapping_from(T::WIDTH) { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm), } } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&n) { (n, o) } else { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm), } }; (n, o) } } } } #[allow(clippy::type_repetition_in_bounds)] fn unsigned_try_from_float(f: Float) -> Result where for<'a> T: WrappingFrom<&'a Natural>, { match f { float_either_zero!() => Ok(T::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(exponent); if !sign { Err(UnsignedFromFloatError::FloatNegative) } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(&significand); let eb = exponent.unsigned_abs(); let n = if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(significand >> bits) } else { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(significand << (eb - sb)) }; n.map(|n| T::wrapping_from(&n)) } } _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan), } } #[allow(clippy::type_repetition_in_bounds)] fn unsigned_try_from_float_ref(f: &Float) -> Result where for<'a> T: WrappingFrom<&'a Natural>, { match f { float_either_zero!() => Ok(T::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(*exponent); if !sign { Err(UnsignedFromFloatError::FloatNegative) } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); let n = if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { Ok(significand >> bits) } else { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } } else { Ok(significand << (eb - sb)) }; n.map(|n| T::wrapping_from(&n)) } } _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan), } } fn unsigned_convertible_from_float(f: &Float) -> bool { match f { float_either_zero!() => true, Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(*exponent); *sign && exponent > 0 && exponent <= i64::wrapping_from(T::WIDTH) && { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); sb < eb || significand.divisible_by_power_of_2(sb - eb) } } _ => false, } } macro_rules! impl_unsigned_from { ($t: ident) => { impl RoundingFrom for $t { /// Converts a [`Float`] to an unsigned primitive integer, using a specified /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this /// function will panic. /// /// If the [`Float`] is greater than the maximum representable value of the unsigned /// type (including $\infty$), then it will be rounded to the maximum value when the /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will /// panic. /// /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`] /// is greater than the maximum representable value of the unsigned type and `rm` is not /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN. /// /// # Examples /// See [here](super::primitive_int_from_float#rounding_from). #[inline] fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) { unsigned_rounding_from_float(f, rm) } } impl RoundingFrom<&Float> for $t { /// Converts a [`Float`] to an unsigned primitive integer, using a specified /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this /// function will panic. /// /// If the [`Float`] is greater than the maximum representable value of the unsigned /// type (including $\infty$), then it will be rounded to the maximum value when the /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will /// panic. /// /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`] /// is greater than the maximum representable value of the unsigned type and `rm` is not /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN. /// /// # Examples /// See [here](super::primitive_int_from_float#rounding_from). #[inline] fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) { unsigned_rounding_from_float_ref(f, rm) } } impl TryFrom for $t { type Error = UnsignedFromFloatError; /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by value. /// If the [`Float`] is not equal to an unsigned primitive integer of the given type, an /// error is returned. /// /// Both positive and negative zero convert to a primitive unsigned integer zero. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#try_from). #[inline] fn try_from(f: Float) -> Result<$t, Self::Error> { unsigned_try_from_float(f) } } impl TryFrom<&Float> for $t { type Error = UnsignedFromFloatError; /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by /// reference. If the [`Float`] is not equal to an unsigned primitive integer of the /// given type, an error is returned. /// /// Both positive and negative zero convert to a primitive unsigned integer zero. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#try_from). #[inline] fn try_from(f: &Float) -> Result<$t, Self::Error> { unsigned_try_from_float_ref(f) } } impl ConvertibleFrom<&Float> for $t { /// Determines whether a [`Float`] can be converted to an unsigned primitive integer, /// taking the [`Float`] by reference. /// /// Both positive and negative zero are convertible to any unsigned primitive integer. /// (Although negative zero is nominally negative, the real number it represents is /// zero, which is not negative.) /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#convertible_from). #[inline] fn convertible_from(f: &Float) -> bool { unsigned_convertible_from_float::<$t>(f) } } }; } apply_to_unsigneds!(impl_unsigned_from); #[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)] fn signed_rounding_from_float(f: Float, rm: RoundingMode) -> (T, Ordering) where for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>, { match f { float_nan!() => panic!("Can't convert NaN to {}", T::NAME), float_infinity!() => match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm), }, float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm), }, float_either_zero!() => (T::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(exponent); if sign { if exponent < 0 { match rm { Floor | Down | Nearest => (T::ZERO, Less), Ceiling | Up => (T::ONE, Greater), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else if exponent >= i64::wrapping_from(T::WIDTH) { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(&significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&n) { (n, o) } else { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => { panic!("Cannot convert large Float to {} using {}", T::NAME, rm) } } }; (n, o) } } else if exponent < 0 { match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), Floor | Up => (T::NEGATIVE_ONE, Less), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else if exponent > i64::wrapping_from(T::WIDTH) { // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the // next else block handles it. match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(&significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, -rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&-n) { (n, o.reverse()) } else { match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => panic!( "Cannot convert large negative Float to {} using {}", T::NAME, rm ), } }; (n, o) } } } } #[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)] fn signed_rounding_from_float_ref(f: &Float, rm: RoundingMode) -> (T, Ordering) where for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>, { match f { float_nan!() => panic!("Can't convert NaN to {}", T::NAME), float_infinity!() => match rm { Floor | Down | Nearest => (T::MAX, Less), _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm), }, float_negative_infinity!() => match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm), }, float_either_zero!() => (T::ZERO, Equal), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(*exponent); if *sign { if exponent < 0 { match rm { Floor | Down | Nearest => (T::ZERO, Less), Ceiling | Up => (T::ONE, Greater), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else if exponent >= i64::wrapping_from(T::WIDTH) { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&n) { (n, o) } else { match rm { Floor | Down | Nearest => (T::MAX, Less), _ => { panic!("Cannot convert large Float to {} using {}", T::NAME, rm) } } }; (n, o) } } else if exponent < 0 { match rm { Ceiling | Down | Nearest => (T::ZERO, Greater), Floor | Up => (T::NEGATIVE_ONE, Less), Exact => { panic!("Cannot convert Float to Integer using {rm}") } } } else if exponent > i64::wrapping_from(T::WIDTH) { // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the // next else block handles it. match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => { panic!("Cannot convert Float to Integer using {rm}") } } } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); let (n, o) = if sb >= eb { significand.shr_round(sb - eb, -rm) } else { (significand << (eb - sb), Equal) }; let (n, o) = if let Ok(n) = T::try_from(&-n) { (n, o.reverse()) } else { match rm { Ceiling | Down | Nearest => (T::MIN, Greater), _ => panic!( "Cannot convert large negative Float to {} using {}", T::NAME, rm ), } }; (n, o) } } } } #[allow(clippy::type_repetition_in_bounds)] fn signed_try_from_float(f: Float) -> Result where for<'a> T: TryFrom<&'a Integer>, { match f { float_either_zero!() => Ok(T::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(exponent); if exponent <= 0 || (sign && exponent >= i64::wrapping_from(T::WIDTH) || !sign && exponent > i64::wrapping_from(T::WIDTH)) { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(&significand); let eb = exponent.unsigned_abs(); let i = Integer::from_sign_and_abs( sign, if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { significand >> bits } else { return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange); } } else { significand << (eb - sb) }, ); T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange) } } _ => Err(SignedFromFloatError::FloatInfiniteOrNan), } } #[allow(clippy::type_repetition_in_bounds)] fn signed_try_from_float_ref(f: &Float) -> Result where for<'a> T: TryFrom<&'a Integer>, { match f { float_either_zero!() => Ok(T::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let exponent = i64::from(*exponent); if exponent <= 0 || (*sign && exponent >= i64::wrapping_from(T::WIDTH) || !*sign && exponent > i64::wrapping_from(T::WIDTH)) { Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange) } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); let i = Integer::from_sign_and_abs( *sign, if sb >= eb { let bits = sb - eb; if significand.divisible_by_power_of_2(bits) { significand >> bits } else { return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange); } } else { significand << (eb - sb) }, ); T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange) } } _ => Err(SignedFromFloatError::FloatInfiniteOrNan), } } fn signed_convertible_from_float(f: &Float) -> bool { match f { float_either_zero!() => true, Float(Finite { exponent, significand, .. }) => { let exponent = i64::from(*exponent); if exponent <= 0 { return false; } if exponent >= i64::wrapping_from(T::WIDTH) { float_is_signed_min::(f) } else { let sb = significand_bits(significand); let eb = exponent.unsigned_abs(); sb < eb || significand.divisible_by_power_of_2(sb - eb) } } _ => false, } } macro_rules! impl_signed_from { ($t: ident) => { impl RoundingFrom for $t { /// Converts a [`Float`] to a signed primitive integer, using a specified /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// If the [`Float`] is less than the minimum representable value of the signed type /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// If the [`Float`] is greater than the maximum representable value of the signed type /// (including $\infty$), then it will be rounded to the maximum value when the /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will /// panic. /// /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] /// is smaller than the minimum representable value of the signed type and `rm` is not /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum /// representable value of the signed type and `rm` is not `Down`, `Floor`, or /// `Nearest`, or if the [`Float`] is NaN. /// /// # Examples /// See [here](super::primitive_int_from_float#rounding_from). #[inline] fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) { signed_rounding_from_float(f, rm) } } impl RoundingFrom<&Float> for $t { /// Converts a [`Float`] to a signed primitive integer, using a specified /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// If the [`Float`] is less than the minimum representable value of the signed type /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// If the [`Float`] is greater than the maximum representable value of the signed type /// (including $\infty$), then it will be rounded to the maximum value when the /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will /// panic. /// /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`] /// is smaller than the minimum representable value of the signed type and `rm` is not /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum /// representable value of the signed type and `rm` is not `Down`, `Floor`, or /// `Nearest`, or if the [`Float`] is NaN. /// /// # Examples /// See [here](super::primitive_int_from_float#rounding_from). #[inline] fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) { signed_rounding_from_float_ref(f, rm) } } impl TryFrom for $t { type Error = SignedFromFloatError; /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by value. /// If the [`Float`] is not equal to a signed primitive integer of the given type, an /// error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#try_from). #[inline] fn try_from(f: Float) -> Result<$t, Self::Error> { signed_try_from_float(f) } } impl TryFrom<&Float> for $t { type Error = SignedFromFloatError; /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by /// reference. If the [`Float`] is not equal to a signed primitive integer of the given /// type, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#try_from). #[inline] fn try_from(f: &Float) -> Result<$t, Self::Error> { signed_try_from_float_ref(f) } } impl ConvertibleFrom<&Float> for $t { /// Determines whether a [`Float`] can be converted to a signed primitive integer, /// taking the [`Float`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_float#convertible_from). #[inline] fn convertible_from(f: &Float) -> bool { signed_convertible_from_float::<$t>(f) } } }; } apply_to_signeds!(impl_signed_from); ================================================ FILE: malachite-float/src/conversion/rational_from_float.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Zero}; use crate::{Float, significand_bits}; use malachite_base::num::basic::traits::Zero as ZeroTrait; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_nz::integer::Integer; use malachite_q::Rational; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RationalFromFloatError; impl TryFrom for Rational { type Error = RationalFromFloatError; /// Converts a [`Float`] to a [`Rational`], taking the [`Float`] by value. If the [`Float`] is /// not finite, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_float::conversion::rational_from_float::RationalFromFloatError; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert_eq!(Rational::try_from(Float::ZERO).unwrap(), 0); /// assert_eq!( /// Rational::try_from(Float::from(1.5)).unwrap().to_string(), /// "3/2" /// ); /// assert_eq!( /// Rational::try_from(Float::from(-1.5)).unwrap().to_string(), /// "-3/2" /// ); /// /// assert_eq!( /// Rational::try_from(Float::INFINITY), /// Err(RationalFromFloatError) /// ); /// assert_eq!(Rational::try_from(Float::NAN), Err(RationalFromFloatError)); /// ``` fn try_from(x: Float) -> Result { match x { float_either_zero!() => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let bits = significand_bits(&significand); Ok(Self::from(Integer::from_sign_and_abs(sign, significand)) << (i128::from(exponent) - i128::from(bits))) } _ => Err(RationalFromFloatError), } } } impl TryFrom<&Float> for Rational { type Error = RationalFromFloatError; /// Converts a [`Float`] to a [`Rational`], taking the [`Float`] by reference. If the [`Float`] /// is not finite, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.complexity()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_float::conversion::rational_from_float::RationalFromFloatError; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert_eq!(Rational::try_from(&Float::ZERO).unwrap(), 0); /// assert_eq!( /// Rational::try_from(&Float::from(1.5)).unwrap().to_string(), /// "3/2" /// ); /// assert_eq!( /// Rational::try_from(&Float::from(-1.5)).unwrap().to_string(), /// "-3/2" /// ); /// /// assert_eq!( /// Rational::try_from(&Float::INFINITY), /// Err(RationalFromFloatError) /// ); /// assert_eq!(Rational::try_from(&Float::NAN), Err(RationalFromFloatError)); /// ``` fn try_from(x: &Float) -> Result { match x { float_either_zero!() => Ok(Self::ZERO), Float(Finite { sign, exponent, significand, .. }) => { let bits = significand_bits(significand); Ok( Self::from(Integer::from_sign_and_abs_ref(*sign, significand)) << (i128::from(*exponent) - i128::from(bits)), ) } _ => Err(RationalFromFloatError), } } } impl ConvertibleFrom<&Float> for Rational { /// Determines whether a [`Float`] can be converted to a [`Rational`] (which is when the /// [`Float`] is finite), taking the [`Float`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NaN, Zero}; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_float::Float; /// use malachite_q::Rational; /// /// assert_eq!(Rational::convertible_from(&Float::ZERO), true); /// assert_eq!(Rational::convertible_from(&Float::from(123.0)), true); /// assert_eq!(Rational::convertible_from(&Float::from(-123.0)), true); /// assert_eq!(Rational::convertible_from(&Float::from(1.5)), true); /// /// assert_eq!(Rational::convertible_from(&Float::INFINITY), false); /// assert_eq!(Rational::convertible_from(&Float::NAN), false); /// ``` #[inline] fn convertible_from(x: &Float) -> bool { x.is_finite() } } ================================================ FILE: malachite-float/src/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::Float; use alloc::string::{String, ToString}; use core::str::FromStr; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::{FromSciString, FromStringBase}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_q::Rational; fn reduce_exponent_in_hex_string(s: &str) -> Option<(String, i32)> { if let Some(exp_index) = s.find('E') { let tail = &s[exp_index + 1..]; let hash_index = tail.find('#').unwrap(); let tail = &tail[..hash_index]; let original_exponent = i32::from_str(tail).unwrap(); if original_exponent.unsigned_abs() < 20 { return None; } let mut new_s = s[..=exp_index].to_string(); new_s += "+20"; new_s += &s[exp_index + hash_index + 1..]; Some((new_s, (original_exponent << 2) - 80)) } else { None } } fn from_hex_string(s: &str) -> Float { match s { "NaN" => Float::NAN, "Infinity" => Float::INFINITY, "-Infinity" => Float::NEGATIVE_INFINITY, "0x0.0" => Float::ZERO, "-0x0.0" => Float::NEGATIVE_ZERO, s => { let (s, sign) = if let Some(s) = s.strip_prefix('-') { (s, false) } else { (s, true) }; let s = s.strip_prefix("0x").unwrap(); let hash_index = s.find('#').unwrap(); let precision = u64::from_str(&s[hash_index + 1..]).unwrap(); let mut options = FromSciStringOptions::default(); options.set_base(16); let x = if let Some((alt_s, exp_offset)) = reduce_exponent_in_hex_string(s) { let hash_index = alt_s.find('#').unwrap(); Float::from_rational_prec_round( Rational::from_sci_string_with_options(&alt_s[..hash_index], options).unwrap(), precision, Exact, ) .0 << exp_offset } else { Float::from_rational_prec_round( Rational::from_sci_string_with_options(&s[..hash_index], options).unwrap(), precision, Exact, ) .0 }; if sign { x } else { -x } } } } impl FromStringBase for Float { fn from_string_base(base: u8, s: &str) -> Option { assert_eq!(base, 16); Some(from_hex_string(s)) } } ================================================ FILE: malachite-float/src/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . pub mod from_string; pub mod to_string; ================================================ FILE: malachite-float/src/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::alloc::string::ToString; use crate::{ComparableFloat, ComparableFloatRef, Float}; use alloc::string::String; use core::fmt::{Debug, Display, Formatter, LowerHex, Result, Write}; use malachite_base::num::arithmetic::traits::{ Abs, ModPowerOf2, RoundToMultipleOfPowerOf2, ShrRound, }; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::traits::{ExactFrom, ToSci, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_q::Rational; fn replace_exponent_in_hex_string(s: &str, new_exponent: i32) -> String { let exp_index = s.find('E').unwrap_or_else(|| panic!("{s}")); let mut new_s = s[..exp_index].to_string(); if new_exponent > 0 { write!(new_s, "E+{new_exponent}").unwrap(); } else { write!(new_s, "E{new_exponent}").unwrap(); } new_s } impl Display for Float { fn fmt(&self, f: &mut Formatter) -> Result { match self { float_nan!() => write!(f, "NaN"), float_infinity!() => write!(f, "Infinity"), float_negative_infinity!() => write!(f, "-Infinity"), float_zero!() => write!(f, "0.0"), float_negative_zero!() => write!(f, "-0.0"), _ => { let exp = self.get_exponent().unwrap(); if exp.unsigned_abs() > 10000 { // The current slow implementation would take forever to try to convert a Float // with a very large or small exponent to a decimal string. Best to // short-circuit it for now. if *self < 0u32 { write!(f, "-")?; } return write!(f, "{}", if exp >= 0 { "too_big" } else { "too_small" }); } let mut lower = self.clone(); let mut higher = self.clone(); lower.decrement(); higher.increment(); let self_q = Rational::exact_from(self); let lower_q = Rational::exact_from(lower); let higher_q = Rational::exact_from(higher); let mut options = ToSciOptions::default(); for precision in 1.. { options.set_precision(precision); let s = self_q.to_sci_with_options(options).to_string(); let s_lower = lower_q.to_sci_with_options(options).to_string(); let s_higher = higher_q.to_sci_with_options(options).to_string(); if s != s_lower && s != s_higher { return if s.contains('.') { write!(f, "{s}") } else if let Some(i) = s.find('e') { write!(f, "{}.0e{}", &s[..i], &s[i + 1..]) } else { write!(f, "{s}.0") }; } } panic!(); } } } } impl Debug for Float { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl LowerHex for Float { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { match self { float_zero!() => f.write_str(if f.alternate() { "0x0.0" } else { "0.0" }), float_negative_zero!() => f.write_str(if f.alternate() { "-0x0.0" } else { "-0.0" }), Self(Finite { exponent, precision, .. }) => { if self.is_sign_negative() { f.write_char('-')?; } let mut options = ToSciOptions::default(); options.set_base(16); let m = u64::from(exponent.mod_power_of_2(2)); let mut p = precision.saturating_sub(m).shr_round(2, Ceiling).0; if m != 0 { p += 1; } options.set_precision(p); options.set_e_uppercase(); options.set_include_trailing_zeros(true); if f.alternate() { f.write_str("0x")?; } let pr = precision.round_to_multiple_of_power_of_2(5, Up).0; let s = if u64::from(exponent.unsigned_abs()) > (pr << 2) { let new_exponent = if *exponent > 0 { i32::exact_from(pr << 1) } else { -i32::exact_from(pr << 1) } + i32::wrapping_from(exponent.mod_power_of_2(2)); let mut s = Rational::exact_from(self >> (exponent - new_exponent)) .abs() .to_sci_with_options(options) .to_string(); s = replace_exponent_in_hex_string(&s, (exponent - 1).shr_round(2, Floor).0); s } else { Rational::exact_from(self) .abs() .to_sci_with_options(options) .to_string() }; if s.contains('.') { write!(f, "{s}") } else if let Some(i) = s.find('E') { write!(f, "{}.0E{}", &s[..i], &s[i + 1..]) } else { write!(f, "{s}.0") } } _ => Display::fmt(&self, f), } } } impl Display for ComparableFloat { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(&ComparableFloatRef(&self.0), f) } } impl Debug for ComparableFloat { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Debug::fmt(&ComparableFloatRef(&self.0), f) } } impl LowerHex for ComparableFloat { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { LowerHex::fmt(&ComparableFloatRef(&self.0), f) } } impl Display for ComparableFloatRef<'_> { fn fmt(&self, f: &mut Formatter) -> Result { if let x @ Float(Finite { precision, .. }) = &self.0 { write!(f, "{x}")?; f.write_char('#')?; write!(f, "{precision}") } else { Display::fmt(&self.0, f) } } } impl LowerHex for ComparableFloatRef<'_> { fn fmt(&self, f: &mut Formatter) -> Result { if let x @ Float(Finite { precision, .. }) = &self.0 { if f.alternate() { write!(f, "{x:#x}")?; } else { write!(f, "{x:x}")?; } f.write_char('#')?; write!(f, "{precision}") } else { LowerHex::fmt(&self.0, f) } } } impl Debug for ComparableFloatRef<'_> { #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } ================================================ FILE: malachite-float/src/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use alloc::vec::IntoIter; use core::iter::{Chain, Once, once}; use core::mem::swap; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::exhaustive::{ ExhaustiveSignedRange, PrimitiveIntIncreasingRange, exhaustive_signed_inclusive_range, primitive_int_increasing_inclusive_range, }; use malachite_base::num::iterators::{BitDistributorSequence, bit_distributor_sequence}; use malachite_base::num::logic::traits::{LowMask, NotAssign}; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, LexDependentPairs, exhaustive_dependent_pairs, lex_dependent_pairs, }; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::{ ExhaustiveNaturalRange, exhaustive_natural_inclusive_range, }; use malachite_nz::platform::Limb; /// Generates all finite positive [`Float`]s with a specified `sci_exponent` (one less than the raw /// exponent) and precision. /// /// This `struct` is created by [`exhaustive_positive_floats_with_sci_exponent_and_precision`]; see /// its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveFloatsWithSciExponentAndPrecision { exponent: i32, precision: u64, shift: u64, significands: ExhaustiveNaturalRange, } impl Iterator for ExhaustivePositiveFloatsWithSciExponentAndPrecision { type Item = Float; fn next(&mut self) -> Option { self.significands.next().map(|s| { Float(Finite { sign: true, exponent: self.exponent, precision: self.precision, significand: s << self.shift, }) }) } } /// Generates all finite positive [`Float`]s with a specified `sci_exponent` (one less than the raw /// exponent) and precision. /// /// Positive and negative zero are both excluded. /// /// A finite positive [`Float`] may be uniquely expressed as $x = m_s2^e_s$, where $1 \leq m_s < 2$ /// and $e_s$ is an integer; then $e_s$ is the sci-exponent. /// /// The output length is $2^{p-1}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if the precision is zero. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_positive_floats_with_sci_exponent_and_precision; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_positive_floats_with_sci_exponent_and_precision(0, 4) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &["1.0#4", "1.1#4", "1.2#4", "1.4#4", "1.5#4", "1.6#4", "1.8#4", "1.9#4"] /// ); /// /// assert_eq!( /// exhaustive_positive_floats_with_sci_exponent_and_precision(2, 5) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "4.0#5", "4.2#5", "4.5#5", "4.8#5", "5.0#5", "5.2#5", "5.5#5", "5.8#5", "6.0#5", /// "6.2#5", "6.5#5", "6.8#5", "7.0#5", "7.2#5", "7.5#5", "7.8#5" /// ] /// ); /// ``` pub fn exhaustive_positive_floats_with_sci_exponent_and_precision( sci_exponent: i32, prec: u64, ) -> ExhaustivePositiveFloatsWithSciExponentAndPrecision { assert!(sci_exponent < Float::MAX_EXPONENT); assert!(sci_exponent >= Float::MIN_EXPONENT - 1); assert_ne!(prec, 0); ExhaustivePositiveFloatsWithSciExponentAndPrecision { exponent: sci_exponent + 1, precision: prec, shift: prec.neg_mod_power_of_2(Limb::LOG_WIDTH), significands: exhaustive_natural_inclusive_range( Natural::power_of_2(prec - 1), Natural::low_mask(prec), ), } } #[derive(Clone, Debug)] struct FloatsWithSciExponentAndPrecisionGenerator { sci_exponent: i32, } impl ExhaustiveDependentPairsYsGenerator< u64, Float, ExhaustivePositiveFloatsWithSciExponentAndPrecision, > for FloatsWithSciExponentAndPrecisionGenerator { #[inline] fn get_ys(&self, &prec: &u64) -> ExhaustivePositiveFloatsWithSciExponentAndPrecision { exhaustive_positive_floats_with_sci_exponent_and_precision(self.sci_exponent, prec) } } #[inline] fn exhaustive_positive_floats_with_sci_exponent_helper( sci_exponent: i32, ) -> LexDependentPairs< u64, Float, FloatsWithSciExponentAndPrecisionGenerator, PrimitiveIntIncreasingRange, ExhaustivePositiveFloatsWithSciExponentAndPrecision, > { lex_dependent_pairs( primitive_int_increasing_inclusive_range(1, u64::MAX), FloatsWithSciExponentAndPrecisionGenerator { sci_exponent }, ) } /// Generates all finite positive [`Float`]s with a specified `sci_exponent` (one less than the raw /// exponent). /// /// This `struct` is created by [`exhaustive_positive_floats_with_sci_exponent`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveFloatsWithSciExponent( LexDependentPairs< u64, Float, FloatsWithSciExponentAndPrecisionGenerator, PrimitiveIntIncreasingRange, ExhaustivePositiveFloatsWithSciExponentAndPrecision, >, ); impl Iterator for ExhaustivePositiveFloatsWithSciExponent { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all finite positive [`Float`]s with a specified `sci_exponent` (one less than the raw /// exponent). /// /// Positive and negative zero are both excluded. /// /// A finite positive [`Float`] may be uniquely expressed as $x = m_s2^e_s$, where $1 \leq m_s < 2$ /// and $e_s$ is an integer; then $e_s$ is the sci-exponent. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if the precision is zero. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_positive_floats_with_sci_exponent; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_positive_floats_with_sci_exponent(0) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#1", "1.0#2", "1.5#2", "1.0#3", "1.2#3", "1.5#3", "1.8#3", "1.0#4", "1.1#4", /// "1.2#4", "1.4#4", "1.5#4", "1.6#4", "1.8#4", "1.9#4", "1.0#5", "1.06#5", "1.12#5", /// "1.19#5", "1.25#5" /// ] /// ); /// /// assert_eq!( /// exhaustive_positive_floats_with_sci_exponent(2) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "4.0#1", "4.0#2", "6.0#2", "4.0#3", "5.0#3", "6.0#3", "7.0#3", "4.0#4", "4.5#4", /// "5.0#4", "5.5#4", "6.0#4", "6.5#4", "7.0#4", "7.5#4", "4.0#5", "4.2#5", "4.5#5", /// "4.8#5", "5.0#5" /// ] /// ); /// ``` #[inline] pub fn exhaustive_positive_floats_with_sci_exponent( sci_exponent: i32, ) -> ExhaustivePositiveFloatsWithSciExponent { assert!(sci_exponent < Float::MAX_EXPONENT); assert!(sci_exponent >= Float::MIN_EXPONENT - 1); ExhaustivePositiveFloatsWithSciExponent(exhaustive_positive_floats_with_sci_exponent_helper( sci_exponent, )) } #[derive(Clone, Debug)] struct FloatsWithPrecisionAndSciExponentGenerator { precision: u64, } impl ExhaustiveDependentPairsYsGenerator< i32, Float, ExhaustivePositiveFloatsWithSciExponentAndPrecision, > for FloatsWithPrecisionAndSciExponentGenerator { #[inline] fn get_ys(&self, &exp: &i32) -> ExhaustivePositiveFloatsWithSciExponentAndPrecision { exhaustive_positive_floats_with_sci_exponent_and_precision(exp, self.precision) } } #[inline] fn exhaustive_floats_with_precision_helper( prec: u64, ) -> ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, FloatsWithPrecisionAndSciExponentGenerator, ExhaustiveSignedRange, ExhaustivePositiveFloatsWithSciExponentAndPrecision, > { exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_signed_inclusive_range(Float::MIN_EXPONENT, Float::MAX_EXPONENT), FloatsWithPrecisionAndSciExponentGenerator { precision: prec }, ) } /// Generates all finite positive [`Float`]s with a specified precision. /// /// This `struct` is created by [`exhaustive_positive_floats_with_precision`]; see its documentation /// for more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveFloatsWithPrecision( ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, FloatsWithPrecisionAndSciExponentGenerator, ExhaustiveSignedRange, ExhaustivePositiveFloatsWithSciExponentAndPrecision, >, ); impl Iterator for ExhaustivePositiveFloatsWithPrecision { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all finite positive [`Float`]s with a specified `precision`. /// /// Positive and negative zero are both excluded. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if the precision is zero. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_positive_floats_with_precision; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_positive_floats_with_precision(1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#1", "2.0#1", "0.5#1", "4.0#1", "0.2#1", "8.0#1", "0.1#1", "2.0e1#1", "0.06#1", /// "3.0e1#1", "0.03#1", "6.0e1#1", "0.02#1", "1.0e2#1", "0.008#1", "3.0e2#1", "0.004#1", /// "5.0e2#1", "0.002#1", "1.0e3#1" /// ] /// ); /// /// assert_eq!( /// exhaustive_positive_floats_with_precision(10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#10", /// "2.0#10", /// "1.002#10", /// "2.004#10", /// "0.5#10", /// "4.0#10", /// "0.501#10", /// "4.01#10", /// "1.004#10", /// "2.008#10", /// "1.006#10", /// "2.012#10", /// "0.502#10", /// "4.016#10", /// "0.503#10", /// "4.023#10", /// "0.25#10", /// "8.0#10", /// "0.2505#10", /// "8.02#10" /// ] /// ); /// ``` #[inline] pub fn exhaustive_positive_floats_with_precision( prec: u64, ) -> ExhaustivePositiveFloatsWithPrecision { assert_ne!(prec, 0); ExhaustivePositiveFloatsWithPrecision(exhaustive_floats_with_precision_helper(prec)) } /// Generates all [`Float`]s with a specified precision. (Since they have a precision, they are /// finite and nonzero.) /// /// This `struct` is created by [`exhaustive_floats_with_precision`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct ExhaustiveFloatsWithPrecision { toggle: bool, xs: ExhaustivePositiveFloatsWithPrecision, x: Float, } impl Iterator for ExhaustiveFloatsWithPrecision { type Item = Float; #[inline] fn next(&mut self) -> Option { self.toggle.not_assign(); Some(if self.toggle { self.x = self.xs.next().unwrap(); self.x.clone() } else { let mut out = Float::NAN; swap(&mut out, &mut self.x); -out }) } } /// Generates all [`Float`]s with a specified precision. (Since they have a precision, they are /// finite and nonzero.) /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if the precision is zero. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_floats_with_precision; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_floats_with_precision(1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#1", "-1.0#1", "2.0#1", "-2.0#1", "0.5#1", "-0.5#1", "4.0#1", "-4.0#1", "0.2#1", /// "-0.2#1", "8.0#1", "-8.0#1", "0.1#1", "-0.1#1", "2.0e1#1", "-2.0e1#1", "0.06#1", /// "-0.06#1", "3.0e1#1", "-3.0e1#1" /// ] /// ); /// /// assert_eq!( /// exhaustive_floats_with_precision(10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#10", /// "-1.0#10", /// "2.0#10", /// "-2.0#10", /// "1.002#10", /// "-1.002#10", /// "2.004#10", /// "-2.004#10", /// "0.5#10", /// "-0.5#10", /// "4.0#10", /// "-4.0#10", /// "0.501#10", /// "-0.501#10", /// "4.01#10", /// "-4.01#10", /// "1.004#10", /// "-1.004#10", /// "2.008#10", /// "-2.008#10" /// ] /// ); /// ``` #[inline] pub fn exhaustive_floats_with_precision(prec: u64) -> ExhaustiveFloatsWithPrecision { ExhaustiveFloatsWithPrecision { toggle: false, xs: exhaustive_positive_floats_with_precision(prec), x: Float::NAN, } } #[derive(Clone, Debug)] pub(crate) struct ExhaustivePositiveFiniteFloatsGenerator; impl ExhaustiveDependentPairsYsGenerator for ExhaustivePositiveFiniteFloatsGenerator { #[inline] fn get_ys(&self, &sci_exponent: &i32) -> ExhaustivePositiveFloatsWithSciExponent { exhaustive_positive_floats_with_sci_exponent(sci_exponent) } } #[inline] fn exhaustive_positive_finite_floats_helper() -> ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveSignedRange, ExhaustivePositiveFloatsWithSciExponent, > { exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_signed_inclusive_range(Float::MIN_EXPONENT, Float::MAX_EXPONENT), ExhaustivePositiveFiniteFloatsGenerator, ) } /// Generates all positive finite [`Float`]s. /// /// This `struct` is created by [`exhaustive_positive_finite_floats`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveFiniteFloats( ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveSignedRange, ExhaustivePositiveFloatsWithSciExponent, >, ); impl Iterator for ExhaustivePositiveFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all positive finite [`Float`]s. /// /// Positive and negative zero are both excluded. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_positive_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#1", "2.0#1", "1.0#2", "2.0#2", "0.5#1", "4.0#1", "0.5#2", "4.0#2", "1.5#2", /// "3.0#2", "1.0#3", "2.0#3", "0.8#2", "6.0#2", "0.5#3", "4.0#3", "0.2#1", "8.0#1", /// "0.2#2", "8.0#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_positive_finite_floats() -> ExhaustivePositiveFiniteFloats { ExhaustivePositiveFiniteFloats(exhaustive_positive_finite_floats_helper()) } /// Generates all negative finite [`Float`]s. /// /// This `struct` is created by [`exhaustive_negative_finite_floats`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct ExhaustiveNegativeFiniteFloats(ExhaustivePositiveFiniteFloats); impl Iterator for ExhaustiveNegativeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|f| -f) } } /// Generates all negative finite [`Float`]s. /// /// Positive and negative zero are both excluded. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_negative_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_negative_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-1.0#1", "-2.0#1", "-1.0#2", "-2.0#2", "-0.5#1", "-4.0#1", "-0.5#2", "-4.0#2", /// "-1.5#2", "-3.0#2", "-1.0#3", "-2.0#3", "-0.8#2", "-6.0#2", "-0.5#3", "-4.0#3", /// "-0.2#1", "-8.0#1", "-0.2#2", "-8.0#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_negative_finite_floats() -> ExhaustiveNegativeFiniteFloats { ExhaustiveNegativeFiniteFloats(exhaustive_positive_finite_floats()) } /// Generates all nonzero finite [`Float`]s. /// /// This `struct` is created by [`exhaustive_nonzero_finite_floats`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct ExhaustiveNonzeroFiniteFloats { toggle: bool, xs: ExhaustivePositiveFiniteFloats, x: Float, } impl Iterator for ExhaustiveNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.toggle.not_assign(); Some(if self.toggle { self.x = self.xs.next().unwrap(); self.x.clone() } else { let mut out = Float::NAN; swap(&mut out, &mut self.x); -out }) } } /// Generates all nonzero finite [`Float`]s. /// /// Positive and negative zero are both excluded. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_nonzero_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_nonzero_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.0#1", "-1.0#1", "2.0#1", "-2.0#1", "1.0#2", "-1.0#2", "2.0#2", "-2.0#2", "0.5#1", /// "-0.5#1", "4.0#1", "-4.0#1", "0.5#2", "-0.5#2", "4.0#2", "-4.0#2", "1.5#2", "-1.5#2", /// "3.0#2", "-3.0#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_nonzero_finite_floats() -> ExhaustiveNonzeroFiniteFloats { ExhaustiveNonzeroFiniteFloats { toggle: false, xs: exhaustive_positive_finite_floats(), x: Float::NAN, } } type ExhaustiveNonNegativeFiniteFloats = Chain, ExhaustivePositiveFiniteFloats>; /// Generates all non-negative finite [`Float`]s. /// /// Positive zero is included, but negative zero is not. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_non_negative_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_non_negative_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.0", "1.0#1", "2.0#1", "1.0#2", "2.0#2", "0.5#1", "4.0#1", "0.5#2", "4.0#2", "1.5#2", /// "3.0#2", "1.0#3", "2.0#3", "0.8#2", "6.0#2", "0.5#3", "4.0#3", "0.2#1", "8.0#1", /// "0.2#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_non_negative_finite_floats() -> ExhaustiveNonNegativeFiniteFloats { once(Float::ZERO).chain(exhaustive_positive_finite_floats()) } type ExhaustiveNonPositiveFiniteFloats = Chain, ExhaustiveNegativeFiniteFloats>; /// Generates all non-positive finite [`Float`]s. /// /// Negative zero is included, but positive zero is not. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_non_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_non_positive_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-0.0", "-1.0#1", "-2.0#1", "-1.0#2", "-2.0#2", "-0.5#1", "-4.0#1", "-0.5#2", "-4.0#2", /// "-1.5#2", "-3.0#2", "-1.0#3", "-2.0#3", "-0.8#2", "-6.0#2", "-0.5#3", "-4.0#3", /// "-0.2#1", "-8.0#1", "-0.2#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_non_positive_finite_floats() -> ExhaustiveNonPositiveFiniteFloats { once(Float::NEGATIVE_ZERO).chain(exhaustive_negative_finite_floats()) } type ExhaustiveFloats = Chain, ExhaustiveNonzeroFiniteFloats>; /// Generates all finite [`Float`]s. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_finite_floats() /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.0", "-0.0", "1.0#1", "-1.0#1", "2.0#1", "-2.0#1", "1.0#2", "-1.0#2", "2.0#2", /// "-2.0#2", "0.5#1", "-0.5#1", "4.0#1", "-4.0#1", "0.5#2", "-0.5#2", "4.0#2", "-4.0#2", /// "1.5#2", "-1.5#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_finite_floats() -> ExhaustiveFloats { alloc::vec![Float::ZERO, Float::NEGATIVE_ZERO] .into_iter() .chain(exhaustive_nonzero_finite_floats()) } /// Generates all [`Float`]s. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i)$ /// /// $M(i) = O(\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// ``` /// use itertools::Itertools; /// use malachite_float::exhaustive::exhaustive_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// exhaustive_floats() /// .take(50) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "NaN", /// "Infinity", /// "-Infinity", /// "0.0", /// "-0.0", /// "1.0#1", /// "-1.0#1", /// "2.0#1", /// "-2.0#1", /// "1.0#2", /// "-1.0#2", /// "2.0#2", /// "-2.0#2", /// "0.5#1", /// "-0.5#1", /// "4.0#1", /// "-4.0#1", /// "0.5#2", /// "-0.5#2", /// "4.0#2", /// "-4.0#2", /// "1.5#2", /// "-1.5#2", /// "3.0#2", /// "-3.0#2", /// "1.0#3", /// "-1.0#3", /// "2.0#3", /// "-2.0#3", /// "0.8#2", /// "-0.8#2", /// "6.0#2", /// "-6.0#2", /// "0.5#3", /// "-0.5#3", /// "4.0#3", /// "-4.0#3", /// "0.2#1", /// "-0.2#1", /// "8.0#1", /// "-8.0#1", /// "0.2#2", /// "-0.2#2", /// "8.0#2", /// "-8.0#2", /// "0.1#1", /// "-0.1#1", /// "2.0e1#1", /// "-2.0e1#1", /// "0.1#2" /// ] /// ); /// ``` #[inline] pub fn exhaustive_floats() -> ExhaustiveFloats { alloc::vec![ Float::NAN, Float::INFINITY, Float::NEGATIVE_INFINITY, Float::ZERO, Float::NEGATIVE_ZERO ] .into_iter() .chain(exhaustive_nonzero_finite_floats()) } ================================================ FILE: malachite-float/src/lib.rs ================================================ // Copyright © 2026 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 . //! This crate defines [`Float`]s, which are arbitrary-precision floating-point numbers. //! //! [`Float`]s are currently experimental. They are missing many important functions. However, the //! functions that are currently implemented are thoroughly tested and documented, with the //! exception of string conversion functions. The current string conversions are incomplete and //! will be changed in the future to match MPFR's behavior. //! //! # Demos and benchmarks //! This crate comes with a `bin` target that can be used for running demos and benchmarks. //! - Almost all of the public functions in this crate have an associated demo. Running a demo //! shows you a function's behavior on a large number of inputs. TODO //! - You can use a similar command to run benchmarks. TODO //! //! The list of available demos and benchmarks is not documented anywhere; you must find them by //! browsing through //! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-float/src/bin_util/demo_and_bench). //! //! # Features //! - `32_bit_limbs`: Sets the type of [`Limb`](malachite_nz#limbs) to [`u32`] instead of the //! default, [`u64`]. //! - `test_build`: A large proportion of the code in this crate is only used for testing. For a //! typical user, building this code would result in an unnecessarily long compilation time and //! an unnecessarily large binary. My solution is to only build this code when the `test_build` //! feature is enabled. If you want to run unit tests, you must enable `test_build`. However, //! doctests don't require it, since they only test the public interface. //! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also //! takes a long time to build. Enabling this feature also enables `test_build`. #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #![cfg_attr( not(any(feature = "test_build", feature = "random", feature = "std")), no_std )] extern crate alloc; #[macro_use] extern crate malachite_base; #[cfg(feature = "test_build")] extern crate itertools; #[cfg(feature = "test_build")] use crate::InnerFloat::Finite; use core::cmp::Ordering::{self, *}; use core::ops::Deref; #[cfg(feature = "test_build")] use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SciMantissaAndExponent}; #[cfg(feature = "test_build")] use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_q::Rational; /// A floating-point number. /// /// `Float`s are currently experimental. They are missing many important functions. However, the /// functions that are currently implemented are thoroughly tested and documented, with the /// exception of string conversion functions. The current string conversions are incomplete and will /// be changed in the future to match MPFR's behavior. /// /// `Float`s are similar to the primitive floats defined by the IEEE 754 standard. They include NaN, /// $\infty$ and $-\infty$, and positive and negative zero. There is only one NaN; there is no /// concept of a NaN payload. /// /// All the finite `Float`s are dyadic rationals (rational numbers whose denominator is a power of /// 2). A finite `Float` consists of several fields: /// - a sign, which denotes whether the `Float` is positive or negative; /// - a significand, which is a [`Natural`] number whose value is equal to the `Float`'s absolute /// value multiplied by a power of 2; /// - an exponent, which is one more than the floor of the base-2 logarithm of the `Float`'s /// absolute value; /// - and finally, a precision, which is greater than zero and indicates the number of significant /// bits. It is common to think of a `Float` as an approximation of some real number, and the /// precision indicates how good the approximation is intended to be. /// /// `Float`s inherit some odd behavior from the IEEE 754 standard regarding comparison. A `NaN` is /// not equal to any `Float`, including itself. Positive and negative zero compare as equal, despite /// being two distinct values. Additionally, (and this is not IEEE 754's fault), `Float`s with /// different precisions compare as equal if they represent the same numeric value. /// /// In many cases, the above behavior is unsatisfactory, so the [`ComparableFloat`] and /// [`ComparableFloat`] wrappers are provided. See their documentation for a description of their /// comparison behavior. /// /// In documentation, we will use the '$=$' sign to mean that two `Float`s are identical, writing /// things like $-\text{NaN}=\text{NaN}$ and $-(0.0) = -0.0$. /// /// The `Float` type is designed to be very similar to the `mpfr_t` type in /// [MPFR](https://www.mpfr.org/mpfr-current/mpfr.html#Nomenclature-and-Types), and all Malachite /// functions produce exactly the same result as their counterparts in MPFR, unless otherwise noted. /// /// Here are the structural difference between `Float` and `mpfr_t`: /// - `Float` can only represent a single `NaN` value, with no sign or payload. /// - Only finite, nonzero `Float`s have a significand, precision, and exponent. For other `Float`s, /// these concepts are undefined. In particular, unlike `mpfr_t` zeros, `Float` zeros do not have /// a precision. /// - The types of `mpfr_t` components are configuration- and platform-dependent. The types of /// `Float` components are platform-independent, although the `Limb` type is /// configuration-dependent: it is `u64` by default, but may be changed to `u32` using the /// `--32_bit_limbs` compiler flag. The type of the exponent is always `i32` and the type of the /// precision is always `u64`. The `Limb` type only has a visible effect on the functions that /// extract the raw significand. All other functions have the same interface when compiled with /// either `Limb` type. /// /// `Float`s whose precision is 64 bits or less can be represented without any memory allocation. /// (Unless Malachite is compiled with `32_bit_limbs`, in which case the limit is 32). #[derive(Clone)] pub struct Float(pub(crate) InnerFloat); // We want to limit the visibility of the `NaN`, `Zero`, `Infinity`, and `Finite` constructors to // within this crate. To do this, we wrap the `InnerFloat` enum in a struct that gets compiled away. #[derive(Clone)] pub(crate) enum InnerFloat { NaN, Infinity { sign: bool, }, Zero { sign: bool, }, Finite { sign: bool, exponent: i32, precision: u64, significand: Natural, }, } #[inline] pub(crate) fn significand_bits(significand: &Natural) -> u64 { significand.limb_count() << Limb::LOG_WIDTH } impl Float { /// The maximum raw exponent of any [`Float`], equal to $2^{30}-1$, or $1,073,741,823$. This is /// one more than the maximum scientific exponent. If we write a [`Float`] as $\pm m2^e$, with /// $1\leq m<2$ and $e$ an integer, we must have $e\leq 2^{30}-2$. If the result of a /// calculation would produce a [`Float`] with an exponent larger than this, then $\pm\infty$, /// the maximum finite float of the specified precision, or the minimum finite float of the /// specified pecision is returned instead, depending on the rounding mode. pub const MAX_EXPONENT: i32 = 0x3fff_ffff; /// The minimum raw exponent of any [`Float`], equal to $-(2^{30}-1)$, or $-1,073,741,823$. This /// is one more than the minimum scientific exponent. If we write a [`Float`] as $\pm m2^e$, /// with $1\leq m<2$ and $e$ an integer, we must have $e\geq -2^{30}$. If the result of a /// calculation would produce a [`Float`] with an exponent smaller than this, then $\pm0.0$, the /// minimum positive finite [`Float`], or the maximum negative finite [`Float`] is returned /// instead, depending on the rounding mode. pub const MIN_EXPONENT: i32 = -Self::MAX_EXPONENT; #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { match self { Self(Finite { precision, significand, exponent, .. }) => { if *precision == 0 || !significand.is_valid() || *exponent > Self::MAX_EXPONENT || *exponent < Self::MIN_EXPONENT { return false; } let bits = significand.significant_bits(); bits != 0 && bits.divisible_by_power_of_2(Limb::LOG_WIDTH) && *precision <= bits && bits - precision < Limb::WIDTH && significand.divisible_by_power_of_2(bits - precision) } _ => true, } } } /// `ComparableFloat` is a wrapper around a [`Float`], taking the [`Float`] by value. /// /// `CompatableFloat` has different comparison behavior than [`Float`]. See the [`Float`] /// documentation for its comparison behavior, which is largely derived from the IEEE 754 /// specification; the `ComparableFloat` behavior, on the other hand, is more mathematically /// well-behaved, and respects the principle that equality should be the finest equivalence /// relation: that is, that two equal objects should not be different in any way. /// /// To be more specific: when a [`Float`] is wrapped in a `ComparableFloat`, /// - `NaN` is not equal to any other [`Float`], but equal to itself; /// - Positive and negative zero are not equal to each other; /// - Ordering is total. Negative zero is ordered to be smaller than positive zero, and `NaN` is /// arbitrarily ordered to be between the two zeros; /// - Two [`Float`]s with different precisions but representing the same value are unequal, and the /// one with the greater precision is ordered to be larger; /// - The hashing function is compatible with equality. /// /// The analogous wrapper for primitive floats is /// [`NiceFloat`](malachite_base::num::float::NiceFloat). However, /// [`NiceFloat`](malachite_base::num::float::NiceFloat) also facilitates better string conversion, /// something that isn't necessary for [`Float`]s /// /// `ComparableFloat` owns its float. This is useful in many cases, for example if you want to use /// [`Float`]s as keys in a hash map. In other situations, it is better to use /// [`ComparableFloatRef`], which only has a reference to its float. #[derive(Clone)] pub struct ComparableFloat(pub Float); /// `ComparableFloatRef` is a wrapper around a [`Float`], taking the [`Float`] be reference. /// /// See the [`ComparableFloat`] documentation for details. #[derive(Clone)] pub struct ComparableFloatRef<'a>(pub &'a Float); impl ComparableFloat { pub const fn as_ref(&self) -> ComparableFloatRef<'_> { ComparableFloatRef(&self.0) } } impl Deref for ComparableFloat { type Target = Float; /// Allows a [`ComparableFloat`] to dereference to a [`Float`]. /// /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_float::{ComparableFloat, Float}; /// /// let x = ComparableFloat(Float::ONE); /// assert_eq!(*x, Float::ONE); /// ``` fn deref(&self) -> &Float { &self.0 } } impl Deref for ComparableFloatRef<'_> { type Target = Float; /// Allows a [`ComparableFloatRef`] to dereference to a [`Float`]. /// /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_float::{ComparableFloatRef, Float}; /// /// let x = Float::ONE; /// let y = ComparableFloatRef(&x); /// assert_eq!(*y, Float::ONE); /// ``` fn deref(&self) -> &Float { self.0 } } #[allow(clippy::type_repetition_in_bounds)] #[doc(hidden)] pub fn emulate_float_to_float_fn (Float, Ordering)>( f: F, x: T, ) -> T where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let x = Float::from(x); let (mut result, o) = f(x.clone(), T::MANTISSA_WIDTH + 1); if !result.is_normal() { return T::exact_from(&result); } let e = i64::from(<&Float as SciMantissaAndExponent>::sci_exponent(&result)); if e < T::MIN_NORMAL_EXPONENT { if e < T::MIN_EXPONENT { let rm = if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() { let down = if result > T::ZERO { Less } else { Greater }; if o == down { Up } else { Down } } else { Nearest }; return T::rounding_from(&result, rm).0; } result = f(x, T::max_precision_for_sci_exponent(e)).0; } if result > T::MAX_FINITE { T::INFINITY } else if result < -T::MAX_FINITE { T::NEGATIVE_INFINITY } else { T::exact_from(&result) } } #[allow(clippy::type_repetition_in_bounds)] #[doc(hidden)] pub fn emulate_float_float_to_float_fn< T: PrimitiveFloat, F: Fn(Float, Float, u64) -> (Float, Ordering), >( f: F, x: T, y: T, ) -> T where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let x = Float::from(x); let y = Float::from(y); let (mut result, o) = f(x.clone(), y.clone(), T::MANTISSA_WIDTH + 1); if !result.is_normal() { return T::exact_from(&result); } let e = i64::from(<&Float as SciMantissaAndExponent>::sci_exponent(&result)); if e < T::MIN_NORMAL_EXPONENT { if e < T::MIN_EXPONENT { let rm = if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() { let down = if result > T::ZERO { Less } else { Greater }; if o == down { Up } else { Down } } else { Nearest }; return T::rounding_from(&result, rm).0; } result = f(x, y, T::max_precision_for_sci_exponent(e)).0; } if result > T::MAX_FINITE { T::INFINITY } else if result < -T::MAX_FINITE { T::NEGATIVE_INFINITY } else { T::exact_from(&result) } } #[allow(clippy::type_repetition_in_bounds)] #[doc(hidden)] pub fn emulate_rational_to_float_fn (Float, Ordering)>( f: F, x: &Rational, ) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let (mut result, o) = f(x, T::MANTISSA_WIDTH + 1); if !result.is_normal() { return T::exact_from(&result); } let e = i64::from(<&Float as SciMantissaAndExponent>::sci_exponent(&result)); if e < T::MIN_NORMAL_EXPONENT { if e < T::MIN_EXPONENT { let rm = if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() { let down = if result > T::ZERO { Less } else { Greater }; if o == down { Up } else { Down } } else { Nearest }; return T::rounding_from(&result, rm).0; } result = f(x, T::max_precision_for_sci_exponent(e)).0; } if result > T::MAX_FINITE { T::INFINITY } else if result < -T::MAX_FINITE { T::NEGATIVE_INFINITY } else { T::exact_from(&result) } } #[allow(clippy::type_repetition_in_bounds)] #[doc(hidden)] pub fn emulate_rational_rational_to_float_fn< T: PrimitiveFloat, F: Fn(&Rational, &Rational, u64) -> (Float, Ordering), >( f: F, x: &Rational, y: &Rational, ) -> T where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let (mut result, o) = f(x, y, T::MANTISSA_WIDTH + 1); if !result.is_normal() { return T::exact_from(&result); } let e = i64::from(<&Float as SciMantissaAndExponent>::sci_exponent(&result)); if e < T::MIN_NORMAL_EXPONENT { if e < T::MIN_EXPONENT { let rm = if e == T::MIN_EXPONENT - 1 && result.significand_ref().unwrap().is_power_of_2() { let down = if result > T::ZERO { Less } else { Greater }; if o == down { Up } else { Down } } else { Nearest }; return T::rounding_from(&result, rm).0; } result = f(x, y, T::max_precision_for_sci_exponent(e)).0; } if result > T::MAX_FINITE { T::INFINITY } else if result < -T::MAX_FINITE { T::NEGATIVE_INFINITY } else { T::exact_from(&result) } } /// Given the `(Float, Ordering)` result of an operation, determines whether an overflow occurred. /// /// We're defining an overflow to occur whenever the actual result is outside the representable /// finite range, and is rounded to either infinity or to the maximum or minimum representable /// finite value. An overflow can present itself in four ways: /// - The result is $\infty$ and the `Ordering` is `Greater` /// - The result is $-\infty$ and the `Ordering` is `Less` /// - The result is the largest finite value (of any `Float` with its precision) and the `Ordering` /// is `Less` /// - The result is the smallest (most negative) finite value (of any `Float` with its precision) /// and the `Ordering` is `Greater` /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, One}; /// use malachite_float::{test_overflow, Float}; /// use std::cmp::Ordering::*; /// /// assert!(test_overflow(&Float::INFINITY, Greater)); /// assert!(test_overflow(&Float::NEGATIVE_INFINITY, Less)); /// assert!(test_overflow(&Float::max_finite_value_with_prec(10), Less)); /// assert!(test_overflow( /// &-Float::max_finite_value_with_prec(10), /// Greater /// )); /// /// assert!(!test_overflow(&Float::INFINITY, Equal)); /// assert!(!test_overflow(&Float::ONE, Less)); /// ``` pub fn test_overflow(result: &Float, o: Ordering) -> bool { if o == Equal { return false; } *result == Float::INFINITY && o == Greater || *result == Float::NEGATIVE_INFINITY && o == Less || *result > 0u32 && result.abs_is_max_finite_value_with_prec() && o == Less || *result < 0u32 && result.abs_is_max_finite_value_with_prec() && o == Greater } /// Given the `(Float, Ordering)` result of an operation, determines whether an underflow occurred. /// /// We're defining an underflow to occur whenever the actual result is outside the representable /// finite range, and is rounded to zero, to the minimum positive value, or to the maximum negative /// value. An underflow can present itself in four ways: /// - The result is $0.0$ or $-0.0$ and the `Ordering` is `Less` /// - The result is $0.0$ or $-0.0$ and the `Ordering` is `Greater` /// - The result is the smallest positive value and the `Ordering` is `Greater` /// - The result is the largest (least negative) negative value and the `Ordering` is `Less` /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_float::{test_underflow, Float}; /// use std::cmp::Ordering::*; /// /// assert!(test_underflow(&Float::ZERO, Less)); /// assert!(test_underflow(&Float::ZERO, Greater)); /// assert!(test_underflow(&Float::min_positive_value_prec(10), Greater)); /// assert!(test_underflow(&-Float::min_positive_value_prec(10), Less)); /// /// assert!(!test_underflow(&Float::ZERO, Equal)); /// assert!(!test_underflow(&Float::ONE, Less)); /// ``` pub fn test_underflow(result: &Float, o: Ordering) -> bool { if o == Equal { return false; } *result == 0u32 || *result > 0u32 && result.abs_is_min_positive_value() && o == Greater || *result < 0u32 && result.abs_is_min_positive_value() && o == Less } /// Traits for arithmetic. pub mod arithmetic; #[macro_use] /// Basic traits for working with [`Float`]s. pub mod basic; /// Traits for comparing [`Float`]s for equality or order. pub mod comparison; /// Functions that produce [`Float`] approximations of mathematical constants, using a given /// precision and rounding mode. pub mod constants; /// Traits for converting to and from [`Float`]s, including converting [`Float`]s to and from /// strings. pub mod conversion; /// Iterators that generate [`Float`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`Float`]s randomly. pub mod random; #[cfg(feature = "test_build")] pub mod test_util; ================================================ FILE: malachite-float/src/random/mod.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use malachite_base::bools::random::{ RandomBools, WeightedRandomBools, random_bools, weighted_random_bools, }; use malachite_base::iterators::{WithSpecialValues, with_special_values}; use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::logic::traits::{LowMask, SignificantBits}; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, geometric_random_signed_inclusive_range, }; use malachite_base::random::Seed; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ RandomNaturals, StripedRandomNaturalInclusiveRange, StripedRandomNaturals, UniformRandomNaturalRange, random_positive_naturals, striped_random_natural_inclusive_range, striped_random_positive_naturals, uniform_random_natural_inclusive_range, }; use malachite_nz::platform::Limb; /// Generates random positive finite [`Float`]s. /// /// This `struct` is created by [`random_positive_finite_floats`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomPositiveFiniteFloats> { exponents: GeometricRandomSignedRange, xs: I, } impl> Iterator for RandomPositiveFiniteFloats { type Item = Float; fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); let precision = x.significant_bits(); assert_ne!(precision, 0); Some(Float(Finite { sign: true, exponent: self.exponents.next().unwrap() + 1, precision, significand: x << precision.neg_mod_power_of_2(Limb::LOG_WIDTH), })) } } /// Generates random positive finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.9#3", /// "1.31e-6#6", /// "0.008#1", /// "0.5#1", /// "8.214e4#13", /// "0.01558827446#29", /// "0.02#1", /// "3.41#7", /// "4.598171165#33", /// "0.000033432058#23", /// "0.339299677376#37", /// "2.66e4#7", /// "3.0e4#1", /// "1.4#8", /// "37.4#9", /// "0.2#1", /// "0.0011108#13", /// "1066.0#10", /// "0.184#7", /// "0.00133230561#28" /// ] /// ); /// ``` pub fn random_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomPositiveFiniteFloats>> { RandomPositiveFiniteFloats { exponents: geometric_random_signed_inclusive_range( seed.fork("exponents"), Float::MIN_EXPONENT, Float::MAX_EXPONENT, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), xs: random_positive_naturals( seed.fork("significands"), mean_precision_numerator, mean_precision_denominator, ), } } /// Generates random positive finite [`Float`]s with a specified precision. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent) are more likely to be chosen. You /// can specify the mean absolute sci-exponent by passing the numerators and denominators of its /// means. /// /// But note that the specified mean is only approximate, since the distribution we are sampling is /// truncated geometric, and its exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual mean is slightly lower than the specified mean. /// - However, increasing the specified mean increases the actual mean, so this still works as a /// mechanism for controlling the sci-exponent. /// - The specified sci-exponent mean must be greater than 0, but it may be as high as you like. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n,) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `prec` is zero. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_positive_floats_with_precision; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_positive_floats_with_precision(EXAMPLE_SEED, 10, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.959#10", /// "1.889e-6#10", /// "0.01291#10", /// "0.71#10", /// "1.02e5#10", /// "0.01181#10", /// "0.01953#10", /// "3.082#10", /// "7.24#10", /// "0.00005597#10", /// "0.3877#10", /// "2.144e4#10", /// "5.856e4#10", /// "1.43#10", /// "62.19#10", /// "0.4658#10", /// "0.001659#10", /// "1914.0#10", /// "0.136#10", /// "0.001144#10" /// ] /// ); /// ``` pub fn random_positive_floats_with_precision( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, prec: u64, ) -> RandomPositiveFiniteFloats { assert_ne!(prec, 0); RandomPositiveFiniteFloats { exponents: geometric_random_signed_inclusive_range( seed.fork("exponents"), Float::MIN_EXPONENT, Float::MAX_EXPONENT, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), xs: uniform_random_natural_inclusive_range( seed.fork("significands"), Natural::power_of_2(prec - 1), Natural::low_mask(prec), ), } } /// Generates random negative finite [`Float`]s. /// /// This `struct` is created by [`random_negative_finite_floats`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomNegativeFiniteFloats>(RandomPositiveFiniteFloats); impl> Iterator for RandomNegativeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|f| -f) } } /// Generates random negative finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.9#3", /// "1.31e-6#6", /// "0.008#1", /// "0.5#1", /// "8.214e4#13", /// "0.01558827446#29", /// "0.02#1", /// "3.41#7", /// "4.598171165#33", /// "0.000033432058#23", /// "0.339299677376#37", /// "2.66e4#7", /// "3.0e4#1", /// "1.4#8", /// "37.4#9", /// "0.2#1", /// "0.0011108#13", /// "1066.0#10", /// "0.184#7", /// "0.00133230561#28" /// ] /// ); /// ``` #[inline] pub fn random_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomNegativeFiniteFloats>> { RandomNegativeFiniteFloats(random_positive_finite_floats( seed, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, )) } /// Generates random non-negative finite [`Float`]s. /// /// This `struct` is created by [`random_non_negative_finite_floats`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct RandomNonNegativeFiniteFloats> { bs: WeightedRandomBools, xs: RandomPositiveFiniteFloats, } impl> Iterator for RandomNonNegativeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { if self.bs.next().unwrap() { Some(Float::ZERO) } else { self.xs.next() } } } /// Generates random non-negative finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that a zero will be /// generated. You can also specify the mean absolute sci-exponent and precision by passing the /// numerators and denominators of their means of the nonzero [`Float`]s. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Positive zero is generated, but negative zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_non_negative_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_non_negative_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "1.11e5#5", /// "0.0310805#17", /// "9.594e6#14", /// "0.0", /// "0.0127#5", /// "0.01843#11", /// "2.0#5", /// "3.082#10", /// "0.87495#16", /// "10288.29527676#38", /// "9.22#10", /// "0.030048549#23", /// "311.452#19", /// "0.0", /// "1.07e3#7", /// "0.000965#9", /// "59159.522#27", /// "0.0", /// "0.000035#6", /// "2.0e1#1" /// ] /// ); /// ``` #[inline] pub fn random_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomNonNegativeFiniteFloats>> { RandomNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: random_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates random non-positive finite [`Float`]s. /// /// This `struct` is created by [`random_non_positive_finite_floats`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct RandomNonPositiveFiniteFloats> { bs: WeightedRandomBools, xs: RandomNegativeFiniteFloats, } impl> Iterator for RandomNonPositiveFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { if self.bs.next().unwrap() { Some(Float::NEGATIVE_ZERO) } else { self.xs.next() } } } /// Generates random non-positive finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that a zero will be /// generated. You can also specify the mean absolute sci-exponent and precision by passing the /// numerators and denominators of their means of the nonzero [`Float`]s. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Negative zero is generated, but positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_non_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_non_positive_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-1.11e5#5", /// "-0.0310805#17", /// "-9.594e6#14", /// "-0.0", /// "-0.0127#5", /// "-0.01843#11", /// "-2.0#5", /// "-3.082#10", /// "-0.87495#16", /// "-10288.29527676#38", /// "-9.22#10", /// "-0.030048549#23", /// "-311.452#19", /// "-0.0", /// "-1.07e3#7", /// "-0.000965#9", /// "-59159.522#27", /// "-0.0", /// "-0.000035#6", /// "-2.0e1#1" /// ] /// ); /// ``` #[inline] pub fn random_non_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomNonPositiveFiniteFloats>> { RandomNonPositiveFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: random_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates random nonzero finite [`Float`]s. /// /// This `struct` is created by [`random_nonzero_finite_floats`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomNonzeroFiniteFloats> { bs: RandomBools, xs: RandomPositiveFiniteFloats, } impl> Iterator for RandomNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } /// Generates random nonzero finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the mean absolute sci-exponent and precision by passing the numerators /// and denominators of their means. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_nonzero_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_nonzero_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-1.11e5#5", /// "-0.0310805#17", /// "-9.594e6#14", /// "0.0127#5", /// "-0.01843#11", /// "2.0#5", /// "-3.082#10", /// "-0.87495#16", /// "-10288.29527676#38", /// "9.22#10", /// "0.030048549#23", /// "311.452#19", /// "-1.07e3#7", /// "-0.000965#9", /// "59159.522#27", /// "-0.000035#6", /// "-2.0e1#1", /// "-120.0#5", /// "-9.6e2#5", /// "-358.2402#20" /// ] /// ); /// ``` #[inline] pub fn random_nonzero_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomNonzeroFiniteFloats>> { RandomNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates random finite [`Float`]s. /// /// This `struct` is created by [`random_finite_floats`]; see its documentation for more. #[derive(Clone, Debug)] pub struct RandomFiniteFloats> { bs: RandomBools, xs: RandomNonNegativeFiniteFloats, } impl> Iterator for RandomFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } /// Generates random finite [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that a zero will be /// generated. You can also specify the mean absolute sci-exponent and precision by passing the /// numerators and denominators of their means of the nonzero [`Float`]s. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// Positive zero and negative zero are both generated. `NaN` is not. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_finite_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-2.44#7", /// "-2.323395887e-8#30", /// "-0.086#6", /// "1009.377#20", /// "-0.00082#6", /// "1.98#10", /// "-1.9e-6#3", /// "-2.6819e5#14", /// "-0.0003386#10", /// "6.0#2", /// "0.0", /// "0.1#5", /// "-1.3665#13", /// "-3.0e9#2", /// "0.117#4", /// "-0.19#2", /// "-0.03#7", /// "-4.0e-6#2", /// "-114.0#6", /// "-4002.0#13" /// ] /// ); /// ``` #[inline] pub fn random_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomFiniteFloats>> { RandomFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } /// Generates random [`Float`]s. /// /// Simpler [`Float`]s (those with a lower absolute sci-exponent or precision) are more likely to be /// chosen. You can specify the numerator and denominator of the probability that a zero, an /// infinity, or a NaN will be generated. You can also specify the mean absolute sci-exponent and /// precision by passing the numerators and denominators of their means of the nonzero [`Float`]s. /// /// But note that the specified means are only approximate, since the distributions we are sampling /// are truncated geometric, and their exact means are somewhat annoying to deal with. The practical /// implications are that /// - The actual means are slightly lower than the specified means. /// - However, increasing the specified means increases the actual means, so this still works as a /// mechanism for controlling the sci-exponent and precision. /// - The specified sci-exponent mean must be greater than 0 and the precision mean greater than 2, /// but they may be as high as you like. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::random_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// random_floats(EXAMPLE_SEED, 10, 1, 10, 1, 1, 10) /// .take(50) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "7.203#10", /// "39.2#8", /// "0.0", /// "NaN", /// "-0.00003#2", /// "-5.0e2#1", /// "-0.0879#8", /// "-95.12#17", /// "0.38077#14", /// "0.000138037#15", /// "-0.109#7", /// "-10.312#12", /// "-13.68396900512259#51", /// "Infinity", /// "-0.34#4", /// "-7.3e-12#5", /// "-394584.0#16", /// "NaN", /// "13.5#5", /// "-0.0", /// "-0.0063#5", /// "0.06#1", /// "0.18933#12", /// "0.00004#6", /// "-4.819e-8#13", /// "1.15e3#6", /// "-1.91e7#7", /// "475.734#17", /// "1.1e-6#7", /// "Infinity", /// "-24.0#3", /// "-4.0e-15#1", /// "-Infinity", /// "0.5039#11", /// "-1.0e3#3", /// "-0.0000281#6", /// "-2.0e5#2", /// "6.43178e-6#20", /// "-0.00019#5", /// "-0.0", /// "-30.0#4", /// "0.2#1", /// "-0.00629938#18", /// "4.58278771862e-6#38", /// "-0.0002707085#19", /// "0.00001313#10", /// "NaN", /// "-0.0", /// "7.0e7#1", /// "20263.5#16" /// ] /// ); /// ``` #[inline] pub fn random_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues>>> { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { random_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } /// Generates striped random positive finite [`Float`]s. /// /// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_sci_exponent_abs_numerator / mean_sci_exponent_abs_denominator`; $m$ must be greater than /// 0. A striped bit sequence with the given stripe parameter is generated and truncated at the bit /// length. The highest bit is forced to be 1, and the [`Float`] is generated from the sequence and /// a random sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.94#4", /// "1.906e-6#11", /// "0.008#2", /// "0.5#3", /// "98332.0#21", /// "0.01416063310170989651#60", /// "0.023#2", /// "2.11#8", /// "4.00003028288443785#57", /// "0.000057221276833275#43", /// "0.25000005983747242139#63", /// "24576.0#12", /// "3.0e4#1", /// "1.98431#16", /// "33.5#12", /// "0.2#1", /// "0.0009768007#23", /// "1279.5#25", /// "0.125#7", /// "0.0014648735386622#42" /// ] /// ); /// ``` pub fn striped_random_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomPositiveFiniteFloats>> { RandomPositiveFiniteFloats { exponents: geometric_random_signed_inclusive_range( seed.fork("exponents"), Float::MIN_EXPONENT, Float::MAX_EXPONENT, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), xs: striped_random_positive_naturals( seed.fork("significands"), mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates striped random positive finite [`Float`]s with a specified precision. /// /// A striped bit sequence with the given stripe parameter is generated and truncated at the bit /// length. The highest bit is forced to be 1, and the [`Float`] is generated from the sequence and /// a random sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, or if `prec` is zero. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "0.94#4", /// "1.906e-6#11", /// "0.008#2", /// "0.5#3", /// "98332.0#21", /// "0.01416063310170989651#60", /// "0.023#2", /// "2.11#8", /// "4.00003028288443785#57", /// "0.000057221276833275#43", /// "0.25000005983747242139#63", /// "24576.0#12", /// "3.0e4#1", /// "1.98431#16", /// "33.5#12", /// "0.2#1", /// "0.0009768007#23", /// "1279.5#25", /// "0.125#7", /// "0.0014648735386622#42" /// ] /// ); /// ``` pub fn striped_random_positive_floats_with_precision( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, prec: u64, ) -> RandomPositiveFiniteFloats { assert_ne!(prec, 0); RandomPositiveFiniteFloats { exponents: geometric_random_signed_inclusive_range( seed.fork("exponents"), Float::MIN_EXPONENT, Float::MAX_EXPONENT, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), xs: striped_random_natural_inclusive_range( seed.fork("significands"), Natural::power_of_2(prec - 1), Natural::low_mask(prec), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random negative finite [`Float`]s. /// /// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random /// sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_negative_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_negative_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-0.94#4", /// "-1.906e-6#11", /// "-0.008#2", /// "-0.5#3", /// "-98332.0#21", /// "-0.01416063310170989651#60", /// "-0.023#2", /// "-2.11#8", /// "-4.00003028288443785#57", /// "-0.000057221276833275#43", /// "-0.25000005983747242139#63", /// "-24576.0#12", /// "-3.0e4#1", /// "-1.98431#16", /// "-33.5#12", /// "-0.2#1", /// "-0.0009768007#23", /// "-1279.5#25", /// "-0.125#7", /// "-0.0014648735386622#42" /// ] /// ); /// ``` pub fn striped_random_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomNegativeFiniteFloats>> { RandomNegativeFiniteFloats(striped_random_positive_finite_floats( seed, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, )) } /// Generates striped random non-negative finite [`Float`]s. /// /// Positive zero is generated with the specified probability. If the [`Float`] to be generated is /// nonzero, then the actual precision is chosen from a geometric distribution with mean $m$, where /// $m$ is `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped /// bit sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random /// sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Positive zero is generated, but negative zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_non_negative_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_non_negative_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "6.6e4#7", /// "0.021484375#26", /// "8.40496e6#19", /// "0.0", /// "0.0155065#16", /// "0.03121951#20", /// "3.94#6", /// "2.0038#15", /// "0.6171265#21", /// "16383.978515147231406#61", /// "12.0#14", /// "0.0195310124#31", /// "380.00023#25", /// "0.0", /// "1511.5#12", /// "0.00091559#14", /// "32799.999752045#46", /// "0.0", /// "0.0000305#6", /// "24.0#2" /// ] /// ); /// ``` #[inline] pub fn striped_random_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomNonNegativeFiniteFloats>> { RandomNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: striped_random_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates striped random non-positive finite [`Float`]s. /// /// Negative zero is generated with the specified probability. If the [`Float`] to be generated is /// nonzero, then the actual precision is chosen from a geometric distribution with mean $m$, where /// $m$ is `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped /// bit sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random /// sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Negative zero is generated, but positive zero is not. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_non_positive_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_non_positive_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-6.6e4#7", /// "-0.021484375#26", /// "-8.40496e6#19", /// "-0.0", /// "-0.0155065#16", /// "-0.03121951#20", /// "-3.94#6", /// "-2.0038#15", /// "-0.6171265#21", /// "-16383.978515147231406#61", /// "-12.0#14", /// "-0.0195310124#31", /// "-380.00023#25", /// "-0.0", /// "-1511.5#12", /// "-0.00091559#14", /// "-32799.999752045#46", /// "-0.0", /// "-0.0000305#6", /// "-24.0#2" /// ] /// ); /// ``` #[inline] pub fn striped_random_non_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomNonPositiveFiniteFloats>> { RandomNonPositiveFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: striped_random_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates striped random nonzero finite [`Float`]s. /// /// The actual precision is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random /// sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Neither positive nor negative zero is generated. `NaN` is not generated either. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_nonzero_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_nonzero_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-6.6e4#7", /// "-0.021484375#26", /// "-8.40496e6#19", /// "0.0155065#16", /// "-0.03121951#20", /// "3.94#6", /// "-2.0038#15", /// "-0.6171265#21", /// "-16383.978515147231406#61", /// "12.0#14", /// "0.0195310124#31", /// "380.00023#25", /// "-1511.5#12", /// "-0.00091559#14", /// "32799.999752045#46", /// "-0.0000305#6", /// "-24.0#2", /// "-64.0#9", /// "-7.6e2#7", /// "-287.76562497#34" /// ] /// ); /// ``` #[inline] pub fn striped_random_nonzero_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomNonzeroFiniteFloats>> { RandomNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: striped_random_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } /// Generates striped random finite [`Float`]s. /// /// Zero is generated with the specified probability. If the [`Float`] to be generated is nonzero, /// then the actual precision is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_stripe_numerator / mean_stripe_denominator`; $m$ must be greater than 0. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Float`] is generated from the sequence and a random /// sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// Both positive and negative zero are generated. `NaN` is not. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_finite_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_finite_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10) /// .take(20) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "-3.8921#14", /// "-2.60770320922795e-8#47", /// "-0.09375#11", /// "527.999999754#38", /// "-0.00051#7", /// "1.00385#17", /// "-1.9e-6#3", /// "-5.2427e5#16", /// "-0.000440707#18", /// "7.8#5", /// "0.0", /// "0.12451#12", /// "-1.992187#21", /// "-3.0e9#2", /// "0.0625#8", /// "-0.22#3", /// "-0.01562#11", /// "-3.8e-6#4", /// "-64.0#13", /// "-4064.0#19" /// ] /// ); /// ``` #[inline] pub fn striped_random_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomFiniteFloats>> { RandomFiniteFloats { bs: random_bools(seed.fork("bs")), xs: striped_random_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } /// Generates striped random finite [`Float`]s. /// /// Special values (NaN, infinities, and zeros) are generated with the specified probability. If the /// [`Float`] to be generated is finite and nonzero, then the actual precision is chosen from a /// geometric distribution with mean $m$, where $m$ is `mean_stripe_numerator / /// mean_stripe_denominator`; $m$ must be greater than 0. A striped bit sequence with the given /// stripe parameter is generated and truncated at the bit length. The highest bit is forced to be /// 1, and the [`Float`] is generated from the sequence and a random sci-exponent. /// /// See [`StripedBitSource`](malachite_base::num::random::striped::StripedBitSource) for information /// about generating striped random numbers. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_precision_numerator` or `mean_precision_denominator` are /// zero, or, if after being reduced to lowest terms, their sum is greater than or equal to /// $2^{64}$. /// /// ``` /// use itertools::Itertools; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_float::random::striped_random_floats; /// use malachite_float::ComparableFloat; /// /// // The number after the '#' is the precision. /// assert_eq!( /// striped_random_floats(EXAMPLE_SEED, 10, 1, 8, 1, 16, 1, 1, 10) /// .take(50) /// .map(|f| ComparableFloat(f).to_string()) /// .collect_vec() /// .as_slice(), /// &[ /// "7.9998#15", /// "32.8#9", /// "0.0", /// "NaN", /// "-0.00005#2", /// "-5.0e2#1", /// "-0.1249#10", /// "-127.4999852#28", /// "0.4999999#22", /// "0.000243902209#28", /// "-0.11719#11", /// "-9.96875#23", /// "-15.9844663292160586998132#75", /// "Infinity", /// "-0.48#5", /// "-1.41e-11#5", /// "-262144.0#21", /// "NaN", /// "8.875#12", /// "-0.0", /// "-0.00586#7", /// "0.06#1", /// "0.12695307#22", /// "0.00006098#10", /// "-3.073363e-8#22", /// "1024.0#9", /// "-3.1519e7#13", /// "483.9384763#31", /// "9.8324e-7#17", /// "Infinity", /// "-24.0#6", /// "-4.0e-15#1", /// "-Infinity", /// "0.6083984445#31", /// "-1.0e3#4", /// "-0.0000153#7", /// "-1.0e5#2", /// "3.8297144e-6#24", /// "-0.0001235#10", /// "-0.0", /// "-23.94#9", /// "0.2#1", /// "-0.007326125891#31", /// "3.818422533722416844e-6#61", /// "-0.00048828123727#34", /// "0.0000151538#16", /// "NaN", /// "-0.0", /// "7.0e7#1", /// "20423.984375#33" /// ] /// ); /// ``` #[inline] pub fn striped_random_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues>>> { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { striped_random_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } ================================================ FILE: malachite-float/src/test_util/arithmetic/add.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Infinity, NaN, Zero}; use crate::test_util::common::rug_float_significant_bits; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::cmp::max; pub fn rug_add_prec_round( x: &rug::Float, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); let o = sum.assign_round(x + y, rm); (sum, o) } #[inline] pub fn rug_add_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_add_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), rm, ) } #[inline] pub fn rug_add_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_add_prec_round(x, y, prec, Round::Nearest) } pub fn rug_add(x: &rug::Float, y: &rug::Float) -> rug::Float { rug_add_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), Round::Nearest, ) .0 } pub fn rug_add_rational_prec_round( x: &rug::Float, y: &rug::Rational, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); let o = sum.assign_round(x + y, rm); (sum, o) } pub fn rug_add_rational_round( x: &rug::Float, y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { rug_add_rational_prec_round(x, y, rug_float_significant_bits(x), rm) } pub fn rug_add_rational_prec( x: &rug::Float, y: &rug::Rational, prec: u64, ) -> (rug::Float, Ordering) { rug_add_rational_prec_round(x, y, prec, Round::Nearest) } pub fn rug_add_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { rug_add_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } pub fn add_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) | (_, float_nan!()) | (float_infinity!(), float_negative_infinity!()) | (float_negative_infinity!(), float_infinity!()) => (float_nan!(), Equal), (float_infinity!(), _) | (_, float_infinity!()) => (float_infinity!(), Equal), (float_negative_infinity!(), _) | (_, float_negative_infinity!()) => { (float_negative_infinity!(), Equal) } (float_zero!(), float_negative_zero!()) | (float_negative_zero!(), float_zero!()) => ( if rm == Floor { float_negative_zero!() } else { float_zero!() }, Equal, ), (float_either_zero!(), mut z) | (mut z, float_either_zero!()) => { let o = z.set_prec_round(prec, rm); (z, o) } (x, y) => { let (mut sum, o) = Float::from_rational_prec_round( Rational::exact_from(x) + Rational::exact_from(y), prec, rm, ); if rm == Floor && o == Equal && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } pub fn add_rational_prec_round_naive( x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x, Equal), (float_negative_zero!(), y) => { if y == 0u32 { (float_negative_zero!(), Equal) } else { Float::from_rational_prec_round(y, prec, rm) } } (float_zero!(), y) => Float::from_rational_prec_round(y, prec, rm), (x, y) => { let (mut sum, o) = Float::from_rational_prec_round(Rational::exact_from(x) + y, prec, rm); if rm == Floor && sum == 0u32 { sum.neg_assign(); } (sum, o) } } } ================================================ FILE: malachite-float/src/test_util/arithmetic/agm.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Infinity, NaN, Zero}; use crate::basic::extended::{ExtendedFloat, agm_prec_round_normal_ref_ref_extended}; use crate::test_util::common::rug_float_significant_bits; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::cmp::max; pub fn rug_agm_prec_round( x: &rug::Float, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut agm = rug::Float::with_val(u32::exact_from(prec), 0); let o = agm.assign_round(x.agm_ref(y), rm); (agm, o) } #[inline] pub fn rug_agm_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_agm_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), rm, ) } #[inline] pub fn rug_agm_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_agm_prec_round(x, y, prec, Round::Nearest) } pub fn rug_agm(x: &rug::Float, y: &rug::Float) -> rug::Float { rug_agm_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), Round::Nearest, ) .0 } pub fn agm_prec_round_extended( x: Float, y: Float, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (&x, &y) { (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal), (float_infinity!(), x) | (x, float_infinity!()) if *x > 0.0 => (float_infinity!(), Equal), (float_either_infinity!(), _) | (_, float_either_infinity!()) => (float_nan!(), Equal), (float_either_zero!(), _) | (_, float_either_zero!()) => (float_zero!(), Equal), _ => { let (x, o) = agm_prec_round_normal_ref_ref_extended( &ExtendedFloat::from(x), &ExtendedFloat::from(y), prec, rm, ); x.into_float_helper(prec, rm, o) } } } ================================================ FILE: malachite-float/src/test_util/arithmetic/div.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::max; pub fn div_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_infinity!()) | (float_either_zero!(), float_either_zero!()) => (float_nan!(), Equal), ( Float(Infinity { sign: x_sign }), Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => ( Float(Infinity { sign: x_sign == y_sign, }), Equal, ), ( Float(Zero { sign: x_sign }), Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => ( Float(Zero { sign: x_sign == y_sign, }), Equal, ), (x, y) => { let (mut quotient, o) = Float::from_rational_prec_round( Rational::exact_from(x) / Rational::exact_from(y), prec, rm, ); if rm == Floor && o == Equal && quotient == 0u32 { quotient.neg_assign(); } (quotient, o) } } } pub fn rug_div_prec_round( x: &rug::Float, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut quotient = rug::Float::with_val(u32::exact_from(prec), 0); let o = quotient.assign_round(x / y, rm); (quotient, o) } #[inline] pub fn rug_div_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_div_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), rm, ) } #[inline] pub fn rug_div_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_div_prec_round(x, y, prec, Round::Nearest) } pub fn rug_div(x: &rug::Float, y: &rug::Float) -> rug::Float { rug_div_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), Round::Nearest, ) .0 } pub fn rug_div_rational_prec_round( x: &rug::Float, y: &rug::Rational, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut quotient = rug::Float::with_val(u32::exact_from(prec), 0); let o = quotient.assign_round(x / y, rm); (quotient, o) } pub fn rug_div_rational_round( x: &rug::Float, y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { rug_div_rational_prec_round(x, y, rug_float_significant_bits(x), rm) } pub fn rug_div_rational_prec( x: &rug::Float, y: &rug::Rational, prec: u64, ) -> (rug::Float, Ordering) { rug_div_rational_prec_round(x, y, prec, Round::Nearest) } pub fn rug_div_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { rug_div_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } pub fn rug_rational_div_float_prec_round( x: &rug::Rational, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut quotient = rug::Float::with_val(u32::exact_from(prec), 0); let o = quotient.assign_round(x / y, rm); (quotient, o) } pub fn rug_rational_div_float_round( x: &rug::Rational, y: &rug::Float, rm: Round, ) -> (rug::Float, Ordering) { rug_rational_div_float_prec_round(x, y, rug_float_significant_bits(y), rm) } pub fn rug_rational_div_float_prec( x: &rug::Rational, y: &rug::Float, prec: u64, ) -> (rug::Float, Ordering) { rug_rational_div_float_prec_round(x, y, prec, Round::Nearest) } pub fn rug_rational_div_float(x: &rug::Rational, y: &rug::Float) -> rug::Float { rug_rational_div_float_prec_round(x, y, rug_float_significant_bits(y), Round::Nearest).0 } ================================================ FILE: malachite-float/src/test_util/arithmetic/ln.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::arithmetic::ln::ln_prec_round_normal_extended; use crate::basic::extended::ExtendedFloat; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering::{self, *}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use rug::float::Round; use rug::ops::AssignRound; pub fn rug_ln_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut ln = rug::Float::with_val(u32::exact_from(prec), 0); let o = ln.assign_round(x.ln_ref(), rm); (ln, o) } pub fn rug_ln_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_ln_prec_round(x, prec, Round::Nearest) } pub fn rug_ln_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_ln_prec_round(x, rug_float_significant_bits(x), rm) } pub fn rug_ln(x: &rug::Float) -> rug::Float { rug_ln_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } pub fn ln_prec_round_extended(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { assert_ne!(prec, 0); match x { Float(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => (float_nan!(), Equal), float_either_zero!() => (float_negative_infinity!(), Equal), float_infinity!() => (float_infinity!(), Equal), _ => ln_prec_round_normal_extended(ExtendedFloat::from(x), prec, rm), } } ================================================ FILE: malachite-float/src/test_util/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . pub mod add; pub mod agm; pub mod div; pub mod ln; pub mod mul; pub mod power_of_2; pub mod reciprocal; pub mod reciprocal_sqrt; pub mod shl; pub mod shl_round; pub mod shr; pub mod shr_round; pub mod sqrt; pub mod square; pub mod sub; ================================================ FILE: malachite-float/src/test_util/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::malachite_base::num::arithmetic::traits::NegAssign; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering::{self, *}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::max; pub fn mul_prec_round_naive(x: Float, y: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (float_nan!(), _) | (_, float_nan!()) | (float_either_infinity!(), float_either_zero!()) | (float_either_zero!(), float_either_infinity!()) => (float_nan!(), Equal), ( Float(Infinity { sign: x_sign }), Float(Finite { sign: y_sign, .. } | Infinity { sign: y_sign }), ) | (Float(Finite { sign: x_sign, .. }), Float(Infinity { sign: y_sign })) => ( Float(Infinity { sign: x_sign == y_sign, }), Equal, ), ( Float(Zero { sign: x_sign }), Float(Finite { sign: y_sign, .. } | Zero { sign: y_sign }), ) | (Float(Finite { sign: x_sign, .. }), Float(Zero { sign: y_sign })) => ( Float(Zero { sign: x_sign == y_sign, }), Equal, ), (x, y) => { let (mut product, o) = Float::from_rational_prec_round( Rational::exact_from(x) * Rational::exact_from(y), prec, rm, ); if rm == Floor && o == Equal && product == 0u32 { product.neg_assign(); } (product, o) } } } pub fn rug_mul_prec_round( x: &rug::Float, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut product = rug::Float::with_val(u32::exact_from(prec), 0); let o = product.assign_round(x * y, rm); (product, o) } #[inline] pub fn rug_mul_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_mul_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), rm, ) } #[inline] pub fn rug_mul_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_mul_prec_round(x, y, prec, Round::Nearest) } pub fn rug_mul(x: &rug::Float, y: &rug::Float) -> rug::Float { rug_mul_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), Round::Nearest, ) .0 } pub fn rug_mul_rational_prec_round( x: &rug::Float, y: &rug::Rational, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut product = rug::Float::with_val(u32::exact_from(prec), 0); let o = product.assign_round(x * y, rm); (product, o) } pub fn rug_mul_rational_round( x: &rug::Float, y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { rug_mul_rational_prec_round(x, y, rug_float_significant_bits(x), rm) } pub fn rug_mul_rational_prec( x: &rug::Float, y: &rug::Rational, prec: u64, ) -> (rug::Float, Ordering) { rug_mul_rational_prec_round(x, y, prec, Round::Nearest) } pub fn rug_mul_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { rug_mul_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } ================================================ FILE: malachite-float/src/test_util/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use std::cmp::Ordering; pub fn power_of_2_prec_round_naive(pow: i64, prec: u64, rm: RoundingMode) -> (Float, Ordering) { Float::from_rational_prec_round(Rational::power_of_2(pow), prec, rm) } pub fn power_of_2_prec_naive(pow: i64, prec: u64) -> (Float, Ordering) { Float::from_rational_prec_round(Rational::power_of_2(pow), prec, Nearest) } pub fn power_of_2_u64_naive(pow: u64) -> Float { Float::from_rational_prec_round(Rational::power_of_2(pow), 1, Nearest).0 } pub fn power_of_2_i64_naive(pow: i64) -> Float { Float::from_rational_prec_round(Rational::power_of_2(pow), 1, Nearest).0 } ================================================ FILE: malachite-float/src/test_util/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; pub fn reciprocal_prec_round_naive_1(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { Float::rational_div_float_prec_round(Rational::ONE, x, prec, rm) } pub fn reciprocal_prec_round_naive_2(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { Float::ONE.div_prec_round(x, prec, rm) } pub fn rug_reciprocal_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); let o = sum.assign_round(rug::Rational::ONE / x, rm); (sum, o) } pub fn rug_reciprocal_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_reciprocal_prec_round(x, prec, Round::Nearest) } pub fn rug_reciprocal_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_reciprocal_prec_round(x, rug_float_significant_bits(x), rm) } pub fn rug_reciprocal(x: &rug::Float) -> rug::Float { rug_reciprocal_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } ================================================ FILE: malachite-float/src/test_util/arithmetic/reciprocal_sqrt.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::arithmetic::reciprocal_sqrt::{ from_reciprocal_rational_prec_round_ref, generic_reciprocal_sqrt_rational_ref, }; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{CheckedSqrt, FloorLogBase2, Reciprocal}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{Infinity, NaN}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; pub fn rug_reciprocal_sqrt_prec_round( x: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut sum = rug::Float::with_val(u32::exact_from(prec), 0); let o = sum.assign_round(x.recip_sqrt_ref(), rm); (sum, o) } pub fn rug_reciprocal_sqrt_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_reciprocal_sqrt_prec_round(x, prec, Round::Nearest) } pub fn rug_reciprocal_sqrt_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_reciprocal_sqrt_prec_round(x, rug_float_significant_bits(x), rm) } pub fn rug_reciprocal_sqrt(x: &rug::Float) -> rug::Float { rug_reciprocal_sqrt_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } pub fn reciprocal_sqrt_rational_prec_round_generic( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if *x == 0u32 { return (Float::INFINITY, Equal); } else if *x < 0u32 { return (Float::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Float::from_rational_prec_round(sqrt.reciprocal(), prec, rm); } generic_reciprocal_sqrt_rational_ref(x, prec, rm) } pub fn reciprocal_sqrt_rational_prec_round_simple( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if *x == 0u32 { return (Float::INFINITY, Equal); } else if *x < 0u32 { return (Float::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Float::from_rational_prec_round(sqrt.reciprocal(), prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; let mut end_shift = x.floor_log_base_2(); let x2; let reduced_x: &Rational; if end_shift.gt_abs(&0x3fff_0000) { end_shift &= !1; x2 = x >> end_shift; reduced_x = &x2; } else { end_shift = 0; reduced_x = x; } loop { let qx_lower_bound = from_reciprocal_rational_prec_round_ref(reduced_x, working_prec, Floor).0; let mut qx_upper_bound = qx_lower_bound.clone(); qx_upper_bound.increment(); let lower_bound = qx_lower_bound.sqrt_round(Floor).0; let upper_bound = qx_upper_bound.sqrt_round(Ceiling).0; let (mut sqrt_1, mut o_1) = Float::from_float_prec_round(lower_bound, prec, rm); let (sqrt_2, mut o_2) = Float::from_float_prec_round(upper_bound, prec, rm); if o_1 == Equal { o_1 = o_2; } if o_2 == Equal { o_2 = o_1; } if o_1 == o_2 && sqrt_1 == sqrt_2 { if end_shift != 0 { o_1 = sqrt_1.shr_prec_round_assign_helper(end_shift >> 1, prec, rm, o_1); } return (sqrt_1, o_1); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/arithmetic/shl.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_q::Rational; use std::ops::Shl; pub fn shl_naive(x: Float, bits: T) -> Float where Rational: Shl, { if x.is_normal() { let prec = x.significant_bits(); Float::from_rational_prec(Rational::exact_from(x) << bits, prec).0 } else { x } } ================================================ FILE: malachite-float/src/test_util/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::ops::Shl; pub fn shl_prec_round_naive( x: Float, bits: T, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) where Rational: Shl, { if x.is_normal() { Float::from_rational_prec_round(Rational::exact_from(x) << bits, prec, rm) } else { (x, Equal) } } pub fn shl_prec_naive(x: Float, bits: T, prec: u64) -> (Float, Ordering) where Rational: Shl, { if x.is_normal() { Float::from_rational_prec_round(Rational::exact_from(x) << bits, prec, Nearest) } else { (x, Equal) } } pub fn shl_round_naive(x: Float, bits: T, rm: RoundingMode) -> (Float, Ordering) where Rational: Shl, { if x.is_normal() { let prec = x.significant_bits(); Float::from_rational_prec_round(Rational::exact_from(x) << bits, prec, rm) } else { (x, Equal) } } pub fn rug_shl_prec_round_unsigned( x: &rug::Float, u: u32, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x << u, rm); (shifted, o) } pub fn rug_shl_prec_round_signed( x: &rug::Float, i: i32, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x << i, rm); (shifted, o) } pub fn rug_shl_prec_unsigned(x: &rug::Float, u: u32, prec: u64) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x << u, Round::Nearest); (shifted, o) } pub fn rug_shl_prec_signed(x: &rug::Float, i: i32, prec: u64) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x << i, Round::Nearest); (shifted, o) } pub fn rug_shl_round_unsigned(x: &rug::Float, u: u32, rm: Round) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(x.prec(), 0); let o = shifted.assign_round(x << u, rm); (shifted, o) } pub fn rug_shl_round_signed(x: &rug::Float, i: i32, rm: Round) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(x.prec(), 0); let o = shifted.assign_round(x << i, rm); (shifted, o) } ================================================ FILE: malachite-float/src/test_util/arithmetic/shr.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_q::Rational; use std::ops::Shr; pub fn shr_naive(x: Float, bits: T) -> Float where Rational: Shr, { if x.is_normal() { let prec = x.significant_bits(); Float::from_rational_prec(Rational::exact_from(x) >> bits, prec).0 } else { x } } ================================================ FILE: malachite-float/src/test_util/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::ops::Shr; pub fn shr_prec_round_naive( x: Float, bits: T, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) where Rational: Shr, { if x.is_normal() { Float::from_rational_prec_round(Rational::exact_from(x) >> bits, prec, rm) } else { (x, Equal) } } pub fn shr_prec_naive(x: Float, bits: T, prec: u64) -> (Float, Ordering) where Rational: Shr, { if x.is_normal() { Float::from_rational_prec_round(Rational::exact_from(x) >> bits, prec, Nearest) } else { (x, Equal) } } pub fn shr_round_naive(x: Float, bits: T, rm: RoundingMode) -> (Float, Ordering) where Rational: Shr, { if x.is_normal() { let prec = x.significant_bits(); Float::from_rational_prec_round(Rational::exact_from(x) >> bits, prec, rm) } else { (x, Equal) } } pub fn rug_shr_prec_round_unsigned( x: &rug::Float, u: u32, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x >> u, rm); (shifted, o) } pub fn rug_shr_prec_round_signed( x: &rug::Float, i: i32, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x >> i, rm); (shifted, o) } pub fn rug_shr_prec_unsigned(x: &rug::Float, u: u32, prec: u64) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x >> u, Round::Nearest); (shifted, o) } pub fn rug_shr_prec_signed(x: &rug::Float, i: i32, prec: u64) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(u32::exact_from(prec), 0); let o = shifted.assign_round(x >> i, Round::Nearest); (shifted, o) } pub fn rug_shr_round_unsigned(x: &rug::Float, u: u32, rm: Round) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(x.prec(), 0); let o = shifted.assign_round(x >> u, rm); (shifted, o) } pub fn rug_shr_round_signed(x: &rug::Float, i: i32, rm: Round) -> (rug::Float, Ordering) { let mut shifted = rug::Float::with_val(x.prec(), 0); let o = shifted.assign_round(x >> i, rm); (shifted, o) } ================================================ FILE: malachite-float/src/test_util/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::arithmetic::sqrt::generic_sqrt_rational_ref; use crate::malachite_base::num::basic::traits::NaN; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{CheckedSqrt, FloorLogBase2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; pub fn rug_sqrt_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sqrt = rug::Float::with_val(u32::exact_from(prec), 0); let o = sqrt.assign_round(x.sqrt_ref(), rm); (sqrt, o) } pub fn rug_sqrt_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_sqrt_prec_round(x, prec, Round::Nearest) } pub fn rug_sqrt_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_sqrt_prec_round(x, rug_float_significant_bits(x), rm) } pub fn rug_sqrt(x: &rug::Float) -> rug::Float { rug_sqrt_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } pub fn sqrt_rational_prec_round_generic( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if *x < 0u32 { return (Float::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Float::from_rational_prec_round(sqrt, prec, rm); } generic_sqrt_rational_ref(x, prec, rm) } pub fn sqrt_rational_prec_round_simple( x: &Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { if *x < 0u32 { return (Float::NAN, Equal); } if let Some(sqrt) = x.checked_sqrt() { return Float::from_rational_prec_round(sqrt, prec, rm); } let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; let mut end_shift = x.floor_log_base_2(); let x2; let reduced_x: &Rational; if end_shift.gt_abs(&0x3fff_0000) { end_shift &= !1; x2 = x >> end_shift; reduced_x = &x2; } else { end_shift = 0; reduced_x = x; } loop { let qx_lower_bound = Float::from_rational_prec_round_ref(reduced_x, working_prec, Floor).0; let mut qx_upper_bound = qx_lower_bound.clone(); qx_upper_bound.increment(); let lower_bound = qx_lower_bound.sqrt_round(Floor).0; let upper_bound = qx_upper_bound.sqrt_round(Ceiling).0; let (mut sqrt_1, mut o_1) = Float::from_float_prec_round(lower_bound, prec, rm); let (sqrt_2, mut o_2) = Float::from_float_prec_round(upper_bound, prec, rm); if o_1 == Equal { o_1 = o_2; } if o_2 == Equal { o_2 = o_1; } if o_1 == o_2 && sqrt_1 == sqrt_2 { if end_shift != 0 { o_1 = sqrt_1.shl_prec_round_assign_helper(end_shift >> 1, prec, rm, o_1); } return (sqrt_1, o_1); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::test_util::common::rug_float_significant_bits; use core::cmp::Ordering; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use rug::float::Round; use rug::ops::AssignRound; pub fn square_prec_round_naive(x: Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) { x.clone().mul_prec_round(x, prec, rm) } pub fn rug_square_prec_round(x: &rug::Float, prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut square = rug::Float::with_val(u32::exact_from(prec), 0); let o = square.assign_round(x.square_ref(), rm); (square, o) } pub fn rug_square_prec(x: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_square_prec_round(x, prec, Round::Nearest) } pub fn rug_square_round(x: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_square_prec_round(x, rug_float_significant_bits(x), rm) } pub fn rug_square(x: &rug::Float) -> rug::Float { rug_square_prec_round(x, rug_float_significant_bits(x), Round::Nearest).0 } ================================================ FILE: malachite-float/src/test_util/arithmetic/sub.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Infinity, NaN, Zero}; use crate::test_util::common::rug_float_significant_bits; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_q::Rational; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::cmp::max; pub fn rug_sub_prec_round( x: &rug::Float, y: &rug::Float, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut diff = rug::Float::with_val(u32::exact_from(prec), 0); let o = diff.assign_round(x - y, rm); (diff, o) } #[inline] pub fn rug_sub_round(x: &rug::Float, y: &rug::Float, rm: Round) -> (rug::Float, Ordering) { rug_sub_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), rm, ) } #[inline] pub fn rug_sub_prec(x: &rug::Float, y: &rug::Float, prec: u64) -> (rug::Float, Ordering) { rug_sub_prec_round(x, y, prec, Round::Nearest) } pub fn rug_sub(x: &rug::Float, y: &rug::Float) -> rug::Float { rug_sub_prec_round( x, y, max(rug_float_significant_bits(x), rug_float_significant_bits(y)), Round::Nearest, ) .0 } pub fn rug_sub_rational_prec_round( x: &rug::Float, y: &rug::Rational, prec: u64, rm: Round, ) -> (rug::Float, Ordering) { let mut diff = rug::Float::with_val(u32::exact_from(prec), 0); let o = diff.assign_round(x - y, rm); (diff, o) } pub fn rug_sub_rational_round( x: &rug::Float, y: &rug::Rational, rm: Round, ) -> (rug::Float, Ordering) { rug_sub_rational_prec_round(x, y, rug_float_significant_bits(x), rm) } pub fn rug_sub_rational_prec( x: &rug::Float, y: &rug::Rational, prec: u64, ) -> (rug::Float, Ordering) { rug_sub_rational_prec_round(x, y, prec, Round::Nearest) } pub fn rug_sub_rational(x: &rug::Float, y: &rug::Rational) -> rug::Float { rug_sub_rational_prec_round(x, y, rug_float_significant_bits(x), Round::Nearest).0 } pub fn sub_rational_prec_round_naive( x: Float, y: Rational, prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { assert_ne!(prec, 0); match (x, y) { (x @ Float(NaN | Infinity { .. }), _) => (x, Equal), (float_negative_zero!(), y) => { if y == 0u32 { (float_negative_zero!(), Equal) } else { Float::from_rational_prec_round(-y, prec, rm) } } (float_zero!(), y) => Float::from_rational_prec_round(-y, prec, rm), (x, y) => { let (mut diff, o) = Float::from_rational_prec_round(Rational::exact_from(x) - y, prec, rm); if rm == Floor && diff == 0u32 { diff.neg_assign(); } (diff, o) } } } ================================================ FILE: malachite-float/src/test_util/bench/bucketers.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::bucketers::{Bucketer, float_size}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::Rational; use std::cmp::max; pub fn pair_1_float_complexity_bucketer(var_name: &str) -> Bucketer<'_, (Float, T)> { Bucketer { bucketing_function: &|(x, _)| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn pair_2_pair_1_float_complexity_bucketer( var_name: &str, ) -> Bucketer<'_, (T, (Float, U))> { Bucketer { bucketing_function: &|(_, (x, _))| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn pair_2_float_complexity_bucketer(var_name: &str) -> Bucketer<'_, (T, Float)> { Bucketer { bucketing_function: &|(_, x)| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn triple_1_float_complexity_bucketer(var_name: &str) -> Bucketer<'_, (Float, T, U)> { Bucketer { bucketing_function: &|(x, _, _)| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn pair_2_triple_1_float_complexity_bucketer( var_name: &str, ) -> Bucketer<'_, (V, (Float, T, U))> { Bucketer { bucketing_function: &|(_, (x, _, _))| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn quadruple_1_float_complexity_bucketer( var_name: &str, ) -> Bucketer<'_, (Float, T, U, V)> { Bucketer { bucketing_function: &|(x, _, _, _)| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn pair_2_quadruple_1_float_complexity_bucketer( var_name: &str, ) -> Bucketer<'_, (W, (Float, T, U, V))> { Bucketer { bucketing_function: &|(_, (x, _, _, _))| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn float_complexity_bucketer(var_name: &str) -> Bucketer<'_, Float> { Bucketer { bucketing_function: &|x| usize::exact_from(x.complexity()), bucketing_label: format!("{var_name}.complexity()"), } } pub fn pair_float_max_complexity_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Float)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.complexity())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.complexity())"), } } pub fn triple_1_2_float_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Float, T)> { Bucketer { bucketing_function: &|(x, y, _)| usize::exact_from(max(x.complexity(), y.complexity())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.complexity())"), } } pub fn pair_2_triple_1_2_float_max_complexity_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (U, (Float, Float, T))> { Bucketer { bucketing_function: &|(_, (x, y, _))| { usize::exact_from(max(x.complexity(), y.complexity())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.complexity())"), } } pub fn triple_1_2_float_rational_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Rational, T)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_triple_1_2_float_rational_max_complexity_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (U, (Float, Rational, T))> { Bucketer { bucketing_function: &|(_, (x, y, _))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, T)> { Bucketer { bucketing_function: &|(x, z)| usize::exact_from(max!(x.complexity(), z.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits)"), } } pub fn pair_2_pair_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (U, (Float, T))> { Bucketer { bucketing_function: &|(_, (x, z))| { usize::exact_from(max!(x.complexity(), z.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits)"), } } pub fn triple_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Float, Float, T)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits)" ), } } pub fn pair_2_triple_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (U, (Float, Float, T))> { Bucketer { bucketing_function: &|(_, (x, y, z))| { usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits)" ), } } pub fn triple_1_2_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, T, U)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max!(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_triple_1_2_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U, V>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (V, (Float, T, U))> { Bucketer { bucketing_function: &|(_, (x, y, _))| { usize::exact_from(max!(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Float, Float, T, U)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits())" ), } } pub fn pair_2_quadruple_1_2_3_float_float_primitive_int_max_complexity_bucketer< 'a, T: PrimitiveInt, U, V, >( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (V, (Float, Float, T, U))> { Bucketer { bucketing_function: &|(_, (x, y, z, _))| { usize::exact_from(max!(x.complexity(), y.complexity(), z.significant_bits())) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.complexity(), {z_name}.significant_bits())" ), } } pub fn quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer< 'a, T: PrimitiveInt, U, >( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Float, Rational, T, U)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!( x.complexity(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits())" ), } } pub fn pair_2_quadruple_1_2_3_float_rational_primitive_int_max_complexity_bucketer< 'a, T: PrimitiveInt, U, V, >( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (V, (Float, Rational, T, U))> { Bucketer { bucketing_function: &|(_, (x, y, z, _))| { usize::exact_from(max!( x.complexity(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits())" ), } } pub fn triple_float_rational_primitive_int_max_complexity_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Float, Rational, T)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!( x.complexity(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits)" ), } } pub fn pair_2_triple_float_rational_primitive_int_max_complexity_bucketer< 'a, T: PrimitiveInt, U, >( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (U, (Float, Rational, T))> { Bucketer { bucketing_function: &|(_, (x, y, z))| { usize::exact_from(max!( x.complexity(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.complexity(), {y_name}.significant_bits(), {z_name}.significant_bits)" ), } } pub fn pair_2_pair_float_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, Float))> { Bucketer { bucketing_function: &|(_, (x, y))| usize::exact_from(max(x.complexity(), y.complexity())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.complexity())"), } } pub fn pair_float_integer_max_complexity_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Integer)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_natural_max_complexity_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Natural)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_rational_max_complexity_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, Rational)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_unsigned_max_complexity_bucketer<'a, T: PrimitiveUnsigned>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, T)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_signed_max_complexity_bucketer<'a, T: PrimitiveSigned>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, T)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), y.significant_bits())), bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_integer_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, Integer))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_natural_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, Natural))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_rational_max_complexity_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, Rational))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_unsigned_max_complexity_bucketer<'a, T, U: PrimitiveUnsigned>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, U))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_signed_max_complexity_bucketer<'a, T, U: PrimitiveSigned>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, U))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_float_primitive_float_max_complexity_bucketer<'a, T, U: PrimitiveFloat>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, U))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.complexity(), u64::exact_from(float_size(*y)))) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn pair_float_primitive_float_max_complexity_bucketer<'a, T: PrimitiveFloat>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, T)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.complexity(), u64::exact_from(float_size(*y)))) }, bucketing_label: format!("max({x_name}.complexity(), {y_name}.significant_bits())"), } } pub fn max_triple_1_float_complexity_triple_2_bucketer<'a, T>( x_name: &'a str, p_name: &'a str, ) -> Bucketer<'a, (Float, u64, T)> { Bucketer { bucketing_function: &|(x, p, _)| usize::exact_from(max(x.complexity(), *p)), bucketing_label: format!("max({x_name}.complexity(), {p_name})"), } } pub fn pair_2_max_triple_1_float_complexity_triple_2_bucketer<'a, T, U>( x_name: &'a str, p_name: &'a str, ) -> Bucketer<'a, (T, (Float, u64, U))> { Bucketer { bucketing_function: &|(_, (x, p, _))| usize::exact_from(max(x.complexity(), *p)), bucketing_label: format!("max({x_name}.complexity(), {p_name})"), } } pub fn max_pair_1_complexity_pair_2_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Float, u64)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.complexity(), *y)), bucketing_label: format!("max({x_name}.complexity(), {y_name})"), } } pub fn pair_2_max_pair_1_complexity_pair_2_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Float, u64))> { Bucketer { bucketing_function: &|(_, (x, y))| usize::exact_from(max(x.complexity(), *y)), bucketing_label: format!("max({x_name}.complexity(), {y_name})"), } } ================================================ FILE: malachite-float/src/test_util/bench/mod.rs ================================================ // Copyright © 2026 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 . pub mod bucketers; ================================================ FILE: malachite-float/src/test_util/common/mod.rs ================================================ // Copyright © 2026 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 crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use crate::{ComparableFloatRef, Float, significand_bits}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity, NegativeZero, Zero as ZeroTrait, }; use malachite_base::num::conversion::traits::{ExactFrom, FromStringBase}; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use rug::float::{Round, Special}; use std::cmp::Ordering; // Can't have From impl due to orphan rule. We could define an impl in malachite-base where // RoundingMode is defined, but pulling in rug::float just for that purpose seems overkill. pub const fn rounding_mode_from_rug_round(rm: Round) -> RoundingMode { match rm { Round::Nearest => Nearest, Round::Zero => Down, Round::Up => Ceiling, Round::Down => Floor, Round::AwayZero => Up, _ => panic!(), } } #[allow(clippy::result_unit_err)] pub const fn rug_round_try_from_rounding_mode(rm: RoundingMode) -> Result { match rm { Floor => Ok(Round::Down), Ceiling => Ok(Round::Up), Down => Ok(Round::Zero), Up => Ok(Round::AwayZero), Nearest => Ok(Round::Nearest), Exact => Err(()), } } #[inline] pub fn rug_round_exact_from_rounding_mode(rm: RoundingMode) -> Round { rug_round_try_from_rounding_mode(rm).unwrap() } impl From<&rug::Float> for Float { fn from(x: &rug::Float) -> Self { if x.is_nan() { Self::NAN } else if x.is_infinite() { if x.is_sign_positive() { Self::INFINITY } else { Self::NEGATIVE_INFINITY } } else if x.is_zero() { if x.is_sign_positive() { Self::ZERO } else { Self::NEGATIVE_ZERO } } else { let mut significand = Natural::exact_from(&*x.get_significand().unwrap()); let precision = u64::from(x.prec()); if significand.significant_bits() - precision >= Limb::WIDTH { // can only happen when 32_bit_limbs is set significand >>= Limb::WIDTH; } let result = Self(Finite { sign: x.is_sign_positive(), exponent: x.get_exp().unwrap(), precision, significand, }); assert!(result.is_valid()); result } } } fn convert_prec(prec: u64) -> Result { u32::try_from(prec).map_err(|_| ()) } #[allow(clippy::unnecessary_wraps)] fn special_float(prec: u32, value: Special) -> Result { Ok(rug::Float::with_val_round(prec, value, Round::Zero).0) } pub fn rug_float_significant_bits(x: &rug::Float) -> u64 { if x.is_normal() { u64::from(x.prec()) } else { 1 } } impl TryFrom<&Float> for rug::Float { type Error = (); fn try_from(x: &Float) -> Result { match x { float_nan!() => special_float(1, Special::Nan), float_infinity!() => special_float(1, Special::Infinity), float_negative_infinity!() => special_float(1, Special::NegInfinity), float_zero!() => special_float(1, Special::Zero), float_negative_zero!() => special_float(1, Special::NegZero), Float(Finite { sign, exponent, precision, significand, }) => { let mut f = Self::with_val_round( convert_prec(*precision)?, rug::Integer::from(significand), Round::Zero, ) .0; f >>= i32::try_from( i64::exact_from(significand_bits(significand)) - i64::from(*exponent), ) .map_err(|_| ())?; if !sign { f = -f; } Ok(f) } } } } pub fn parse_hex_string(s_hex: &str) -> Float { let x = Float::from_string_base(16, s_hex).unwrap(); assert_eq!(format!("{:#x}", ComparableFloatRef(&x)), s_hex); x } pub fn to_hex_string(x: &Float) -> String { format!("{:#x}", ComparableFloatRef(x)) } pub const ORDERED_FLOAT_STRINGS: [&str; 21] = [ "-Infinity", "-3.1415926535897931", "-2.0", "-1.4142135623730951", "-1.0", "-1.0", "-1.0", "-0.5", "-0.33333333333333331", "-0.0", "NaN", "0.0", "0.33333333333333331", "0.5", "1.0", "1.0", "1.0", "1.4142135623730951", "2.0", "3.1415926535897931", "Infinity", ]; pub const ORDERED_FLOAT_HEX_STRINGS: [&str; 21] = [ "-Infinity", "-0x3.243f6a8885a30#53", "-0x2.0#1", "-0x1.6a09e667f3bcd#53", "-0x1.0000000000000000000000000#100", "-0x1.0#2", "-0x1.0#1", "-0x0.8#1", "-0x0.55555555555554#53", "-0x0.0", "NaN", "0x0.0", "0x0.55555555555554#53", "0x0.8#1", "0x1.0#1", "0x1.0#2", "0x1.0000000000000000000000000#100", "0x1.6a09e667f3bcd#53", "0x2.0#1", "0x3.243f6a8885a30#53", "Infinity", ]; pub const ORDERED_F32S: [f32; 17] = [ f32::NEGATIVE_INFINITY, -std::f32::consts::PI, -2.0, -std::f32::consts::SQRT_2, -1.0, -0.5, -1.0 / 3.0, -0.0, f32::NAN, 0.0, 1.0 / 3.0, 0.5, 1.0, std::f32::consts::SQRT_2, 2.0, std::f32::consts::PI, f32::INFINITY, ]; pub const ORDERED_F64S: [f64; 17] = [ f64::NEGATIVE_INFINITY, -std::f64::consts::PI, -2.0, -std::f64::consts::SQRT_2, -1.0, -0.5, -1.0 / 3.0, -0.0, f64::NAN, 0.0, 1.0 / 3.0, 0.5, 1.0, std::f64::consts::SQRT_2, 2.0, std::f64::consts::PI, f64::INFINITY, ]; // Tests that rounding with Floor and gradually increasing precision preserves all previous bits. pub fn test_constant (Float, Ordering)>(f: F, limit: u64) { let mut bit_index = Limb::WIDTH - 1; let mut significand = Natural::ZERO; for prec in 1..limit { let x = f(prec, Floor).0; let x_sig = x.significand_ref().unwrap(); if *x_sig != significand { significand.set_bit(bit_index); assert_eq!(*x_sig, significand); } if bit_index == 0 { significand <<= Limb::WIDTH; bit_index = Limb::WIDTH - 1; } else { bit_index -= 1; } } } ================================================ FILE: malachite-float/src/test_util/comparison/mod.rs ================================================ // Copyright © 2026 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 . pub mod partial_cmp_rational; ================================================ FILE: malachite-float/src/test_util/comparison/partial_cmp_rational.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::{Finite, Infinity, NaN, Zero}; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; pub fn float_partial_cmp_rational_alt(x: &Float, other: &Rational) -> Option { match (x, other) { (float_nan!(), _) => None, (float_infinity!(), _) => Some(Greater), (float_negative_infinity!(), _) => Some(Less), (float_either_zero!(), y) => 0u32.partial_cmp(y), ( Float(Finite { sign: s_x, exponent: e_x, .. }), y, ) => Some(if *y == 0u32 { if *s_x { Greater } else { Less } } else { let s_cmp = s_x.cmp(&(*y > 0)); if s_cmp != Equal { return Some(s_cmp); } let ord_cmp = (i64::from(*e_x) - 1).cmp(&other.floor_log_base_2_abs()); if ord_cmp == Equal { Rational::try_from(x).unwrap().cmp(other) } else if *s_x { ord_cmp } else { ord_cmp.reverse() } }), } } ================================================ FILE: malachite-float/src/test_util/constants/lemniscate_constant.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn lemniscate_constant_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_lo = Float::pi_prec_round(working_prec, Floor).0; let mut pi_hi = pi_lo.clone(); pi_hi.increment(); let g_lo = Float::gauss_constant_prec_round(working_prec, Floor).0; let mut g_hi = g_lo.clone(); g_hi.increment(); let lo = pi_lo.mul_round(g_lo, Floor).0; let hi = pi_hi.mul_round(g_hi, Ceiling).0; let (lemniscate_constant_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (lemniscate_constant_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && lemniscate_constant_lo == lemniscate_constant_hi { return (lemniscate_constant_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/ln_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::{Constant, Round}; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_ln_2_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut ln_2 = rug::Float::with_val(u32::exact_from(prec), 0); let o = ln_2.assign_round(Constant::Log2, rm); (ln_2, o) } ================================================ FILE: malachite-float/src/test_util/constants/log_2_e.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn log_2_e_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let ln_2_lo = Float::ln_2_prec_round(working_prec, Floor).0; let mut ln_2_hi = ln_2_lo.clone(); ln_2_hi.increment(); let lo = ln_2_hi.reciprocal_round(Floor).0; let hi = ln_2_lo.reciprocal_round(Ceiling).0; let (log_2_e_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (log_2_e_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && log_2_e_lo == log_2_e_hi { return (log_2_e_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/mod.rs ================================================ // Copyright © 2026 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 . pub mod lemniscate_constant; pub mod ln_2; pub mod log_2_e; pub mod one_over_pi; pub mod one_over_sqrt_pi; pub mod one_over_sqrt_tau; pub mod pi; pub mod pi_over_3; pub mod prime_constant; pub mod prouhet_thue_morse_constant; pub mod sqrt_2; pub mod sqrt_2_over_2; pub mod sqrt_3; pub mod sqrt_3_over_3; pub mod sqrt_pi; ================================================ FILE: malachite-float/src/test_util/constants/one_over_pi.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn one_over_pi_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_lo = Float::pi_prec_round(working_prec, Floor).0; let mut pi_hi = pi_lo.clone(); pi_hi.increment(); let lo = pi_hi.reciprocal_round(Floor).0; let hi = pi_lo.reciprocal_round(Ceiling).0; let (one_over_pi_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (one_over_pi_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && one_over_pi_lo == one_over_pi_hi { return (one_over_pi_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/one_over_sqrt_pi.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn one_over_sqrt_pi_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_lo = Float::pi_prec_round(working_prec, Floor).0; let mut pi_hi = pi_lo.clone(); pi_hi.increment(); let lo = pi_hi.reciprocal_sqrt_round(Floor).0; let hi = pi_lo.reciprocal_sqrt_round(Ceiling).0; let (one_over_sqrt_pi_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (one_over_sqrt_pi_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && one_over_sqrt_pi_lo == one_over_sqrt_pi_hi { return (one_over_sqrt_pi_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/one_over_sqrt_tau.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn one_over_sqrt_tau_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let tau_lo = Float::tau_prec_round(working_prec, Floor).0; let mut tau_hi = tau_lo.clone(); tau_hi.increment(); let lo = tau_hi.reciprocal_sqrt_round(Floor).0; let hi = tau_lo.reciprocal_sqrt_round(Ceiling).0; let (one_over_sqrt_tau_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (one_over_sqrt_tau_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && one_over_sqrt_tau_lo == one_over_sqrt_tau_hi { return (one_over_sqrt_tau_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::{Constant, Round}; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_pi_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut pi = rug::Float::with_val(u32::exact_from(prec), 0); let o = pi.assign_round(Constant::Pi, rm); (pi, o) } ================================================ FILE: malachite-float/src/test_util/constants/pi_over_3.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn pi_over_3_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { const THREE: Float = Float::const_from_unsigned(3); let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_lo = Float::pi_prec_round(working_prec, Floor).0; let mut pi_hi = pi_lo.clone(); pi_hi.increment(); let lo = pi_lo.div_round(THREE, Floor).0; let hi = pi_hi.div_round(THREE, Ceiling).0; let (pi_over_3_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (pi_over_3_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && pi_over_3_lo == pi_over_3_hi { return (pi_over_3_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/constants/prime_constant.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::num::factorization::primes::prime_indicator_sequence; use malachite_base::rounding_modes::RoundingMode; use std::cmp::Ordering; pub fn prime_constant_prec_round_naive(prec: u64, rm: RoundingMode) -> (Float, Ordering) { Float::non_dyadic_from_bits_prec_round(prime_indicator_sequence(), prec, rm) } ================================================ FILE: malachite-float/src/test_util/constants/prouhet_thue_morse_constant.rs ================================================ // Copyright © 2026 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 crate::Float; use malachite_base::iterators::thue_morse_sequence; use malachite_base::rounding_modes::RoundingMode; use std::cmp::Ordering; pub fn prouhet_thue_morse_constant_prec_round_naive( prec: u64, rm: RoundingMode, ) -> (Float, Ordering) { Float::non_dyadic_from_bits_prec_round(thue_morse_sequence(), prec, rm) } ================================================ FILE: malachite-float/src/test_util/constants/sqrt_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_sqrt_2_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sqrt = rug::Float::with_val(u32::exact_from(prec), 0); let o = sqrt.assign_round(rug::Float::with_val(1, 2).sqrt_ref(), rm); (sqrt, o) } ================================================ FILE: malachite-float/src/test_util/constants/sqrt_2_over_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_sqrt_2_over_2_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sqrt = rug::Float::with_val(u32::exact_from(prec), 0); let o = sqrt.assign_round(rug::Float::with_val(1, 2).sqrt_ref(), rm); (sqrt >> 1, o) } ================================================ FILE: malachite-float/src/test_util/constants/sqrt_3.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_sqrt_3_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sqrt = rug::Float::with_val(u32::exact_from(prec), 0); let o = sqrt.assign_round(rug::Float::with_val(2, 3).sqrt_ref(), rm); (sqrt, o) } ================================================ FILE: malachite-float/src/test_util/constants/sqrt_3_over_3.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use rug; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering; pub fn rug_sqrt_3_over_3_prec_round(prec: u64, rm: Round) -> (rug::Float, Ordering) { let mut sqrt = rug::Float::with_val(u32::exact_from(prec), 0); let o = sqrt.assign_round(rug::Float::with_val(2, 3).recip_sqrt_ref(), rm); (sqrt, o) } ================================================ FILE: malachite-float/src/test_util/constants/sqrt_pi.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::platform::Limb; use std::cmp::Ordering::{self, *}; pub fn sqrt_pi_prec_round_simple(prec: u64, rm: RoundingMode) -> (Float, Ordering) { let mut working_prec = prec + 10; let mut increment = Limb::WIDTH; loop { let pi_lo = Float::pi_prec_round(working_prec, Floor).0; let mut pi_hi = pi_lo.clone(); pi_hi.increment(); let lo = pi_lo.sqrt_round(Floor).0; let hi = pi_hi.sqrt_round(Ceiling).0; let (sqrt_pi_lo, mut o_lo) = Float::from_float_prec_round(lo, prec, rm); let (sqrt_pi_hi, mut o_hi) = Float::from_float_prec_round(hi, prec, rm); if o_lo == Equal { o_lo = o_hi; } if o_hi == Equal { o_hi = o_lo; } if o_lo == o_hi && sqrt_pi_lo == sqrt_pi_hi { return (sqrt_pi_lo, o_lo); } working_prec += increment; increment = working_prec >> 1; } } ================================================ FILE: malachite-float/src/test_util/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::logic::traits::SignificantBits; // This differs from the `precision` function provided by `PrimitiveFloat`. That function returns // the smallest precision necessary to represent the float, whereas this function returns the // maximum precision of any float in the same binade. If the float is non-finite or zero, 1 is // returned. pub fn alt_precision(x: T) -> u64 { if x.is_finite() && x != T::ZERO { let (mantissa, exponent) = x.raw_mantissa_and_exponent(); if exponent == 0 { mantissa.significant_bits() } else { T::MANTISSA_WIDTH + 1 } } else { 1 } } ================================================ FILE: malachite-float/src/test_util/conversion/mod.rs ================================================ // Copyright © 2026 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 . pub mod from_primitive_float; ================================================ FILE: malachite-float/src/test_util/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::test_util::common::to_hex_string; use itertools::Itertools; pub fn exhaustive_floats_helper_helper_with_limit>( limit: usize, xs: I, out: &[&str], out_hex: &[&str], ) { let xs_hex = xs.clone(); assert_eq!( xs_hex .take(limit) .map(|f| { assert!(f.is_valid()); to_hex_string(&f) }) .collect_vec() .as_slice(), out_hex ); assert_eq!( xs.take(limit) .map(|f| { f.to_string() }) .collect_vec() .as_slice(), out ); } pub fn exhaustive_floats_helper_helper>( xs: I, out: &[&str], out_hex: &[&str], ) { exhaustive_floats_helper_helper_with_limit(50, xs, out, out_hex); } ================================================ FILE: malachite-float/src/test_util/extra_variadic/mod.rs ================================================ // Copyright © 2026 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 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::logic::traits::SignificantBits; use malachite_base::random::Seed; use malachite_base::random_tuples; use malachite_base::tuples::random::next_helper; use std::cmp::max; use std::marker::PhantomData; #[allow(clippy::missing_const_for_fn)] fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { (a.unwrap(), b.unwrap(), c.unwrap()) } #[allow(clippy::missing_const_for_fn)] fn unwrap_quadruple( (a, b, c, d): (Option, Option, Option, Option), ) -> (X, Y, Z, W) { (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap()) } 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] ); 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)), ExhaustiveQuadruplesXXYZ, (X, X, Y, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xxyz, exhaustive_quadruples_xxyz_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]], [Z, K, zs, zs_done, [3, output_type_zs_3]] ); 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_tuples!( (pub(crate)), RandomQuadruples, RandomQuadruplesFromSingle, random_quadruples, random_quadruples_from_single, (I::Item, I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_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)), RandomTriplesXYY, (X, Y, Y), random_triples_xyy, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXXYZ, (X, X, Y, Z), random_quadruples_xxyz, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]], [Y, J, ys, ys_gen, [y_2, y_2]], [Z, K, zs, zs_gen, [z_3, z_3]] ); ================================================ FILE: malachite-float/src/test_util/generators/common.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::test_util::common::rug_round_exact_from_rounding_mode; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::generators::common::It; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::Rational; pub fn float_rm(xs: It) -> It<(rug::Float, Float)> { Box::new(xs.map(|x| (rug::Float::exact_from(&x), x))) } pub fn float_pair_rm(xs: It<(Float, Float)>) -> It<((rug::Float, rug::Float), (Float, Float))> { Box::new(xs.map(|(x, y)| { ( (rug::Float::exact_from(&x), rug::Float::exact_from(&y)), (x, y), ) })) } pub fn float_natural_pair_rm( xs: It<(Float, Natural)>, ) -> It<((rug::Float, rug::Integer), (Float, Natural))> { Box::new(xs.map(|(x, y)| { ( (rug::Float::exact_from(&x), rug::Integer::exact_from(&y)), (x, y), ) })) } pub fn float_integer_pair_rm( xs: It<(Float, Integer)>, ) -> It<((rug::Float, rug::Integer), (Float, Integer))> { Box::new(xs.map(|(x, y)| { ( (rug::Float::exact_from(&x), rug::Integer::exact_from(&y)), (x, y), ) })) } pub fn float_rational_pair_rm( xs: It<(Float, Rational)>, ) -> It<((rug::Float, rug::Rational), (Float, Rational))> { Box::new(xs.map(|(x, y)| { ( (rug::Float::exact_from(&x), rug::Rational::exact_from(&y)), (x, y), ) })) } pub fn float_primitive_int_pair_rm( xs: It<(Float, T)>, ) -> It<((rug::Float, T), (Float, T))> { Box::new(xs.map(|(x, y)| ((rug::Float::exact_from(&x), y), (x, y)))) } pub fn float_primitive_float_pair_rm( xs: It<(Float, T)>, ) -> It<((rug::Float, T), (Float, T))> { Box::new(xs.map(|(x, y)| ((rug::Float::exact_from(&x), y), (x, y)))) } pub fn float_t_rounding_mode_triple_rm( xs: It<(Float, T, RoundingMode)>, ) -> It<((rug::Float, T, rug::float::Round), (Float, T, RoundingMode))> { Box::new(xs.map(|(x, p, rm)| { ( ( rug::Float::exact_from(&x), p.clone(), rug_round_exact_from_rounding_mode(rm), ), (x, p, rm), ) })) } pub fn float_t_u_triple_rm( xs: It<(Float, T, U)>, ) -> It<((rug::Float, T, U), (Float, T, U))> { Box::new(xs.map(|(x, p, q)| { ( (rug::Float::exact_from(&x), p.clone(), q.clone()), (x, p, q), ) })) } pub fn float_t_u_rounding_mode_quadruple_rm( xs: It<(Float, T, U, RoundingMode)>, ) -> It<( (rug::Float, T, U, rug::float::Round), (Float, T, U, RoundingMode), )> { Box::new(xs.map(|(x, p, q, rm)| { ( ( rug::Float::exact_from(&x), p.clone(), q.clone(), rug_round_exact_from_rounding_mode(rm), ), (x, p, q, rm), ) })) } pub fn float_rounding_mode_pair_rm( xs: It<(Float, RoundingMode)>, ) -> It<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Box::new(xs.map(|(x, rm)| { ( ( rug::Float::exact_from(&x), rug_round_exact_from_rounding_mode(rm), ), (x, rm), ) })) } pub fn float_float_rounding_mode_triple_rm( xs: It<(Float, Float, RoundingMode)>, ) -> It<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Box::new(xs.map(|(x, y, rm)| { ( ( rug::Float::exact_from(&x), rug::Float::exact_from(&y), rug_round_exact_from_rounding_mode(rm), ), (x, y, rm), ) })) } pub fn float_float_anything_triple_rm( xs: It<(Float, Float, T)>, ) -> It<((rug::Float, rug::Float, T), (Float, Float, T))> { Box::new(xs.map(|(x, y, z)| { ( ( rug::Float::exact_from(&x), rug::Float::exact_from(&y), z.clone(), ), (x, y, z), ) })) } pub fn float_rational_anything_triple_rm( xs: It<(Float, Rational, T)>, ) -> It<((rug::Float, rug::Rational, T), (Float, Rational, T))> { Box::new(xs.map(|(x, y, z)| { ( ( rug::Float::exact_from(&x), rug::Rational::exact_from(&y), z.clone(), ), (x, y, z), ) })) } pub fn float_rational_rounding_mode_triple_rm( xs: It<(Float, Rational, RoundingMode)>, ) -> It<( (rug::Float, rug::Rational, rug::float::Round), (Float, Rational, RoundingMode), )> { Box::new(xs.map(|(x, y, rm)| { ( ( rug::Float::exact_from(&x), rug::Rational::exact_from(&y), rug_round_exact_from_rounding_mode(rm), ), (x, y, rm), ) })) } pub fn float_float_anything_rounding_mode_quadruple_rm( xs: It<(Float, Float, T, RoundingMode)>, ) -> It<( (rug::Float, rug::Float, T, rug::float::Round), (Float, Float, T, RoundingMode), )> { Box::new(xs.map(|(x, y, z, rm)| { ( ( rug::Float::exact_from(&x), rug::Float::exact_from(&y), z.clone(), rug_round_exact_from_rounding_mode(rm), ), (x, y, z, rm), ) })) } pub fn float_rational_anything_rounding_mode_quadruple_rm( xs: It<(Float, Rational, T, RoundingMode)>, ) -> It<( (rug::Float, rug::Rational, T, rug::float::Round), (Float, Rational, T, RoundingMode), )> { Box::new(xs.map(|(x, y, z, rm)| { ( ( rug::Float::exact_from(&x), rug::Rational::exact_from(&y), z.clone(), rug_round_exact_from_rounding_mode(rm), ), (x, y, z, rm), ) })) } ================================================ FILE: malachite-float/src/test_util/generators/exhaustive.rs ================================================ // Copyright © 2026 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 crate::exhaustive::{ ExhaustivePositiveFiniteFloatsGenerator, ExhaustivePositiveFloatsWithSciExponent, exhaustive_finite_floats, exhaustive_floats, exhaustive_non_negative_finite_floats, exhaustive_nonzero_finite_floats, exhaustive_positive_finite_floats, exhaustive_positive_floats_with_precision, exhaustive_positive_floats_with_sci_exponent, }; use crate::test_util::extra_variadic::{ exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, }; use crate::{Float, significand_bits}; use alloc::vec::IntoIter; use core::cmp::Ordering::*; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::num::arithmetic::traits::{IsPowerOf2, Reciprocal, Square}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::num::exhaustive::{ exhaustive_positive_primitive_ints, exhaustive_primitive_floats, exhaustive_signeds, exhaustive_unsigneds, primitive_int_increasing_inclusive_range, }; use malachite_base::num::iterators::{BitDistributorSequence, bit_distributor_sequence}; use malachite_base::num::logic::traits::{NotAssign, SignificantBits}; use malachite_base::orderings::exhaustive::exhaustive_orderings; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::{It, reshape_2_1_to_3, reshape_3_1_to_4}; use malachite_base::test_util::generators::exhaustive_pairs_big_tiny; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, exhaustive_dependent_pairs, }; use malachite_base::tuples::exhaustive::{ exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_triples, exhaustive_triples_custom_output, exhaustive_triples_xyy, lex_pairs, }; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_naturals; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::exhaustive::{exhaustive_non_negative_rationals, exhaustive_rationals}; use std::cmp::{Ordering, max}; use std::iter::Chain; use std::mem::swap; // -- Float -- pub fn exhaustive_float_gen() -> It { Box::new(exhaustive_floats()) } pub fn exhaustive_float_gen_var_1() -> It { Box::new(exhaustive_positive_finite_floats()) } pub fn exhaustive_float_gen_var_2() -> It { Box::new(exhaustive_floats().filter(|f| !f.is_nan())) } pub fn exhaustive_float_gen_var_3() -> It { Box::new(exhaustive_nonzero_finite_floats()) } pub fn exhaustive_float_gen_var_4() -> It { Box::new(exhaustive_finite_floats()) } pub fn exhaustive_float_gen_var_5() -> It { Box::new(exhaustive_non_negative_finite_floats()) } pub fn exhaustive_float_gen_var_6() -> It { Box::new(exhaustive_floats_with_precision_inclusive_range( 1, Limb::WIDTH - 1, )) } pub fn exhaustive_float_gen_var_7() -> It { Box::new(exhaustive_positive_floats_with_precision(Limb::WIDTH)) } pub fn exhaustive_float_gen_var_8() -> It { Box::new(exhaustive_floats_with_precision_inclusive_range( Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, )) } pub fn exhaustive_float_gen_var_9() -> It { Box::new(exhaustive_positive_floats_with_precision(Limb::WIDTH << 1)) } pub fn exhaustive_float_gen_var_10() -> It { Box::new(exhaustive_floats_with_precision_inclusive_range( (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, )) } pub fn exhaustive_float_gen_var_11() -> It { Box::new(exhaustive_floats_with_precision_inclusive_range( (Limb::WIDTH << 1) + 1, u64::MAX, )) } pub fn exhaustive_float_gen_var_12() -> It { Box::new(exhaustive_extreme_floats()) } pub fn exhaustive_float_gen_var_13() -> It { Box::new(exhaustive_extreme_nonzero_finite_floats()) } pub fn exhaustive_float_gen_var_14() -> It { Box::new(exhaustive_extreme_floats().filter(|f| !f.is_nan())) } pub fn exhaustive_float_gen_var_15() -> It { Box::new(exhaustive_floats().filter(|x| *x > 0u32)) } #[derive(Clone, Debug)] pub struct ExhaustiveExtremeExponents { counter: bool, i: i32, end_counter: u8, } impl Iterator for ExhaustiveExtremeExponents { type Item = i32; fn next(&mut self) -> Option { if self.i == 2 { return match self.end_counter { 0 => { self.end_counter = 1; Some(-2) } 1 => { self.end_counter = 2; Some(-1) } 2 => { self.end_counter = 3; Some(0) } _ => None, }; } Some(if self.counter { self.counter = false; self.i - 2 } else { self.counter = true; self.i -= 1; -self.i - 1 }) } } pub const fn exhaustive_extreme_exponents() -> ExhaustiveExtremeExponents { ExhaustiveExtremeExponents { counter: true, i: Float::MAX_EXPONENT + 1, end_counter: 0, } } #[derive(Clone, Debug)] struct ExhaustiveMixedExtremeExponents { first: bool, counter: u8, low: i32, high: i32, end_counter: u8, } impl Iterator for ExhaustiveMixedExtremeExponents { type Item = i32; fn next(&mut self) -> Option { if self.low == self.high { return match self.end_counter { 0 => { self.end_counter = 1; Some(-self.high) } 1 => { self.end_counter = 2; Some(-self.high - 1) } _ => None, }; } Some(if self.first { self.first = false; 0 } else { match self.counter { 0 => { self.counter = 1; self.low } 1 => { self.counter = 2; self.low += 1; -self.low + 1 } 2 => { self.counter = 3; self.high - 1 } 3 => { self.counter = 0; self.high -= 1; -self.high - 2 } _ => unreachable!(), } }) } } const fn exhaustive_mixed_extreme_exponents() -> ExhaustiveMixedExtremeExponents { ExhaustiveMixedExtremeExponents { first: true, counter: 0, low: 1, high: Float::MAX_EXPONENT, end_counter: 0, } } #[inline] fn exhaustive_extreme_positive_finite_floats_helper() -> ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveExtremeExponents, ExhaustivePositiveFloatsWithSciExponent, > { exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_extreme_exponents(), ExhaustivePositiveFiniteFloatsGenerator, ) } #[derive(Clone, Debug)] struct ExhaustiveExtremePositiveFiniteFloats( ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveExtremeExponents, ExhaustivePositiveFloatsWithSciExponent, >, ); impl Iterator for ExhaustiveExtremePositiveFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } #[inline] fn exhaustive_extreme_positive_finite_floats() -> ExhaustiveExtremePositiveFiniteFloats { ExhaustiveExtremePositiveFiniteFloats(exhaustive_extreme_positive_finite_floats_helper()) } #[derive(Clone, Debug)] struct ExhaustiveExtremeNonzeroFiniteFloats { toggle: bool, xs: ExhaustiveExtremePositiveFiniteFloats, x: Float, } impl Iterator for ExhaustiveExtremeNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.toggle.not_assign(); Some(if self.toggle { self.x = self.xs.next().unwrap(); self.x.clone() } else { let mut out = Float::NAN; swap(&mut out, &mut self.x); -out }) } } #[inline] fn exhaustive_extreme_nonzero_finite_floats() -> ExhaustiveExtremeNonzeroFiniteFloats { ExhaustiveExtremeNonzeroFiniteFloats { toggle: false, xs: exhaustive_extreme_positive_finite_floats(), x: Float::NAN, } } type ExhaustiveExtremeFloats = Chain, ExhaustiveExtremeNonzeroFiniteFloats>; #[inline] fn exhaustive_extreme_floats() -> ExhaustiveExtremeFloats { alloc::vec![ Float::NAN, Float::INFINITY, Float::NEGATIVE_INFINITY, Float::ZERO, Float::NEGATIVE_ZERO ] .into_iter() .chain(exhaustive_extreme_nonzero_finite_floats()) } #[inline] fn exhaustive_mixed_extreme_positive_finite_floats_helper() -> ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveMixedExtremeExponents, ExhaustivePositiveFloatsWithSciExponent, > { exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_mixed_extreme_exponents(), ExhaustivePositiveFiniteFloatsGenerator, ) } #[derive(Clone, Debug)] struct ExhaustiveMixedExtremePositiveFiniteFloats( ExhaustiveDependentPairs< i32, Float, BitDistributorSequence, ExhaustivePositiveFiniteFloatsGenerator, ExhaustiveMixedExtremeExponents, ExhaustivePositiveFloatsWithSciExponent, >, ); impl Iterator for ExhaustiveMixedExtremePositiveFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } #[inline] fn exhaustive_mixed_extreme_positive_finite_floats() -> ExhaustiveMixedExtremePositiveFiniteFloats { ExhaustiveMixedExtremePositiveFiniteFloats( exhaustive_mixed_extreme_positive_finite_floats_helper(), ) } #[derive(Clone, Debug)] struct ExhaustiveMixedExtremeNonzeroFiniteFloats { toggle: bool, xs: ExhaustiveMixedExtremePositiveFiniteFloats, x: Float, } impl Iterator for ExhaustiveMixedExtremeNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { self.toggle.not_assign(); Some(if self.toggle { self.x = self.xs.next().unwrap(); self.x.clone() } else { let mut out = Float::NAN; swap(&mut out, &mut self.x); -out }) } } #[inline] fn exhaustive_mixed_extreme_nonzero_finite_floats() -> ExhaustiveMixedExtremeNonzeroFiniteFloats { ExhaustiveMixedExtremeNonzeroFiniteFloats { toggle: false, xs: exhaustive_mixed_extreme_positive_finite_floats(), x: Float::NAN, } } type ExhaustiveMixedExtremeFloats = Chain, ExhaustiveMixedExtremeNonzeroFiniteFloats>; #[inline] fn exhaustive_mixed_extreme_floats() -> ExhaustiveMixedExtremeFloats { alloc::vec![ Float::NAN, Float::INFINITY, Float::NEGATIVE_INFINITY, Float::ZERO, Float::NEGATIVE_ZERO ] .into_iter() .chain(exhaustive_mixed_extreme_nonzero_finite_floats()) } struct FloatWithPrecisionRangeGenerator; impl ExhaustiveDependentPairsYsGenerator>> for FloatWithPrecisionRangeGenerator { #[inline] fn get_ys(&self, &prec: &u64) -> Box> { Box::new(exhaustive_positive_floats_with_precision(prec)) } } fn exhaustive_floats_with_precision_inclusive_range(prec_lo: u64, prec_hi: u64) -> It { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(prec_lo, prec_hi), FloatWithPrecisionRangeGenerator, ) .map(|p| p.1), ) } struct FloatPairWithPrecisionRangeGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, (Float, Float), Box>, > for FloatPairWithPrecisionRangeGenerator { #[inline] fn get_ys(&self, &prec: &u64) -> Box> { Box::new(exhaustive_pairs_from_single( exhaustive_positive_floats_with_precision(prec), )) } } fn exhaustive_float_pairs_with_precision_inclusive_range( prec_lo: u64, prec_hi: u64, ) -> It<(Float, Float)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(prec_lo, prec_hi), FloatPairWithPrecisionRangeGenerator, ) .map(|p| p.1), ) } struct FloatPairWithPrecisionRangesGenerator; impl ExhaustiveDependentPairsYsGenerator< (u64, u64), (Float, Float), Box>, > for FloatPairWithPrecisionRangesGenerator { #[inline] fn get_ys(&self, &precs: &(u64, u64)) -> Box> { Box::new(exhaustive_pairs( exhaustive_positive_floats_with_precision(precs.0), exhaustive_positive_floats_with_precision(precs.1), )) } } fn exhaustive_float_pairs_with_precisions(precisions: It<(u64, u64)>) -> It<(Float, Float)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), precisions, FloatPairWithPrecisionRangesGenerator, ) .map(|p| p.1), ) } // -- (Float, Float) -- pub fn exhaustive_float_pair_gen() -> It<(Float, Float)> { Box::new(exhaustive_pairs_from_single(exhaustive_floats())) } pub fn exhaustive_float_pair_gen_var_1() -> It<(Float, Float)> { Box::new(exhaustive_pairs_from_single(exhaustive_finite_floats())) } pub fn exhaustive_float_pair_gen_var_2() -> It<(Float, Float)> { exhaustive_float_pairs_with_precision_inclusive_range(1, Limb::WIDTH - 1) } pub fn exhaustive_float_pair_gen_var_3() -> It<(Float, Float)> { Box::new(exhaustive_pairs_from_single( exhaustive_positive_floats_with_precision(Limb::WIDTH), )) } pub fn exhaustive_float_pair_gen_var_4() -> It<(Float, Float)> { exhaustive_float_pairs_with_precision_inclusive_range(Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1) } pub fn exhaustive_float_pair_gen_var_5() -> It<(Float, Float)> { Box::new(exhaustive_pairs_from_single( exhaustive_positive_floats_with_precision(Limb::WIDTH << 1), )) } pub fn exhaustive_float_pair_gen_var_6() -> It<(Float, Float)> { exhaustive_float_pairs_with_precision_inclusive_range( (Limb::WIDTH << 1) + 1, (Limb::WIDTH * 3) - 1, ) } pub fn exhaustive_float_pair_gen_var_7() -> It<(Float, Float)> { exhaustive_float_pairs_with_precision_inclusive_range(Limb::WIDTH * 3, u64::MAX) } pub fn exhaustive_float_pair_gen_var_8() -> It<(Float, Float)> { exhaustive_float_pairs_with_precisions(Box::new( exhaustive_pairs( exhaustive_positive_primitive_ints(), primitive_int_increasing_inclusive_range(1, Limb::WIDTH), ) .filter(|&(x, y)| x != y), )) } pub fn exhaustive_float_pair_gen_var_9() -> It<(Float, Float)> { exhaustive_float_pairs_with_precisions(Box::new( exhaustive_pairs( exhaustive_positive_primitive_ints(), primitive_int_increasing_inclusive_range(Limb::WIDTH + 1, u64::MAX), ) .filter(|&(x, y)| x != y), )) } pub fn exhaustive_float_pair_gen_var_10() -> It<(Float, Float)> { Box::new(exhaustive_pairs_from_single( exhaustive_mixed_extreme_floats(), )) } // -- (Float, Float, Float) -- pub fn exhaustive_float_triple_gen() -> It<(Float, Float, Float)> { Box::new(exhaustive_triples_from_single(exhaustive_floats())) } // -- (Float, Float, Integer) -- pub fn exhaustive_float_float_integer_triple_gen() -> It<(Float, Float, Integer)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_integers(), )) } // -- (Float, Float, Natural) -- pub fn exhaustive_float_float_natural_triple_gen() -> It<(Float, Float, Natural)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_naturals(), )) } // -- (Float, Float, PrimitiveFloat) -- pub fn exhaustive_float_float_primitive_float_triple_gen() -> It<(Float, Float, T)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_primitive_floats(), )) } // -- (Float, Float, PrimitiveSigned) -- pub fn exhaustive_float_float_signed_triple_gen() -> It<(Float, Float, T)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_signeds(), )) } // -- (Float, Float, PrimitiveUnsigned) -- pub fn exhaustive_float_float_unsigned_triple_gen() -> It<(Float, Float, T)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_float_unsigned_triple_gen_var_1() -> It<(Float, Float, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_float_float_unsigned_triple_gen_var_2() -> It<(Float, Float, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (Float, Float, PrimitiveUnsigned, RoundingMode) -- pub(crate) fn add_prec_round_valid( x: &Float, y: &Float, prec: u64, rm: RoundingMode, extreme: bool, ) -> bool { if rm != Exact { true } else if extreme { x.add_prec_round_ref_ref(y, prec, Floor).1 == Equal } else if let (Ok(rx), Ok(ry)) = (Rational::try_from(x), Rational::try_from(y)) { let sum = Float::exact_from(rx + ry); if let Some(min_prec) = sum.get_min_prec() { prec >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_1() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, false)), ) } pub(crate) fn sub_prec_round_valid( x: &Float, y: &Float, prec: u64, rm: RoundingMode, extreme: bool, ) -> bool { if rm != Exact { return true; } if extreme { x.sub_prec_round_ref_ref(y, prec, Floor).1 == Equal } else if let (Ok(rx), Ok(ry)) = (Rational::try_from(x), Rational::try_from(y)) { let diff = Float::exact_from(rx - ry); if let Some(min_prec) = diff.get_min_prec() { prec >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_2() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, false)), ) } pub(crate) fn mul_prec_round_valid( x: &Float, y: &Float, prec: u64, rm: RoundingMode, extreme: bool, ) -> bool { if rm != Exact { true } else if extreme { x.mul_prec_round_ref_ref(y, prec, Floor).1 == Equal } else if let (Ok(rx), Ok(ry)) = (Rational::try_from(x), Rational::try_from(y)) { let product = Float::exact_from(rx * ry); if let Some(min_prec) = product.get_min_prec() { prec >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_3() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, false)), ) } pub(crate) fn div_prec_round_valid( x: &Float, y: &Float, prec: u64, rm: RoundingMode, extreme: bool, ) -> bool { if rm != Exact || *y == 0u32 { true } else if extreme { x.div_prec_round_ref_ref(y, prec, Floor).1 == Equal } else if let (Ok(rx), Ok(ry)) = (Rational::try_from(x), Rational::try_from(y)) { if let Ok(quotient) = Float::try_from(rx / ry) { if let Some(min_prec) = quotient.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_5() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_6() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_7() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_8() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn agm_prec_round_valid(x: &Float, y: &Float, prec: u64, rm: RoundingMode) -> bool { rm != Exact || !x.is_normal() || !y.is_normal() || *x < 0u32 || *y < 0u32 || x == y && Float::from_float_prec_round_ref(x, prec, Floor).1 == Equal } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_9() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_10() -> It<(Float, Float, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_mixed_extreme_floats(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Float, Rational) -- pub fn exhaustive_float_float_rational_triple_gen() -> It<(Float, Float, Rational)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_rationals(), )) } // -- (Float, Float, RoundingMode) -- pub(crate) fn add_round_valid(x: &Float, y: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact { true } else if extreme { x.add_round_ref_ref(y, Floor).1 == Equal } else if let (Some(x_prec), Some(y_prec)) = (x.get_prec(), y.get_prec()) { let sum = Float::exact_from(Rational::exact_from(x) + Rational::exact_from(y)); if let Some(min_prec) = sum.get_min_prec() { max(x_prec, y_prec) >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_1() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub(crate) fn sub_round_valid(x: &Float, y: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact { true } else if extreme { x.sub_round_ref_ref(y, Floor).1 == Equal } else if let (Some(x_prec), Some(y_prec)) = (x.get_prec(), y.get_prec()) { let diff = Float::exact_from(Rational::exact_from(x) - Rational::exact_from(y)); if let Some(min_prec) = diff.get_min_prec() { max(x_prec, y_prec) >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_2() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_3() -> It<(Float, Float, RoundingMode)> { Box::new(exhaustive_triples_xxy( exhaustive_floats(), exhaustive_rounding_modes().filter(|&rm| rm != Exact), )) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_4() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_5() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_3(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_6() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_4(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_7() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_5(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_8() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_6(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_9() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_7(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_10() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_11() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_3(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_12() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_4(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_13() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_5(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_14() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_6(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_15() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_7(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub(crate) fn mul_round_valid(x: &Float, y: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact { true } else if extreme { x.mul_round_ref_ref(y, Floor).1 == Equal } else if let (Some(x_prec), Some(y_prec)) = (x.get_prec(), y.get_prec()) { let product = Float::exact_from(Rational::exact_from(x) * Rational::exact_from(y)); if let Some(min_prec) = product.get_min_prec() { max(x_prec, y_prec) >= min_prec } else { true } } else { true } } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_16() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_17() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_18() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_3(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_19() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_4(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_20() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_5(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_21() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_6(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_22() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_7(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub(crate) fn div_round_valid(x: &Float, y: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact || *y == 0u32 { true } else if extreme { x.div_round_ref_ref(y, Floor).1 == Equal } else if let (Some(x_prec), Some(y_prec)) = (x.get_prec(), y.get_prec()) { if let Ok(quotient) = Float::try_from(Rational::exact_from(x) / Rational::exact_from(y)) { if let Some(min_prec) = quotient.get_min_prec() { max(x_prec, y_prec) >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_23() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_24() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_2(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_25() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_3(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_26() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_4(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_27() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_8(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_28() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_float_pair_gen_var_9(), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_29() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_mixed_extreme_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, true)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_30() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_mixed_extreme_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, true)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_31() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_mixed_extreme_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, true)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_32() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_mixed_extreme_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, true)), ) } pub(crate) fn agm_round_valid(x: &Float, y: &Float, rm: RoundingMode) -> bool { rm != Exact || !x.is_normal() || !y.is_normal() || *x < 0u32 || *y < 0u32 || x == y } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_33() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_float_rounding_mode_triple_gen_var_34() -> It<(Float, Float, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_mixed_extreme_floats()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } // -- (Float, Integer) -- pub fn exhaustive_float_integer_pair_gen() -> It<(Float, Integer)> { Box::new(exhaustive_pairs(exhaustive_floats(), exhaustive_integers())) } pub fn exhaustive_float_integer_pair_gen_var_1() -> It<(Float, Integer)> { Box::new(exhaustive_pairs( exhaustive_finite_floats(), exhaustive_integers(), )) } pub fn exhaustive_float_integer_pair_gen_var_2() -> It<(Float, Integer)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_integers(), )) } // -- (Float, Integer, Integer) -- pub fn exhaustive_float_integer_integer_triple_gen() -> It<(Float, Integer, Integer)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_integers(), )) } // -- (Float, Natural) -- pub fn exhaustive_float_natural_pair_gen() -> It<(Float, Natural)> { Box::new(exhaustive_pairs(exhaustive_floats(), exhaustive_naturals())) } pub fn exhaustive_float_natural_pair_gen_var_1() -> It<(Float, Natural)> { Box::new(exhaustive_pairs( exhaustive_finite_floats(), exhaustive_naturals(), )) } pub fn exhaustive_float_natural_pair_gen_var_2() -> It<(Float, Natural)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_naturals(), )) } // -- (Float, Natural, Natural) -- pub fn exhaustive_float_natural_natural_triple_gen() -> It<(Float, Natural, Natural)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_naturals(), )) } // -- (Float, Ordering) -- pub fn exhaustive_float_ordering_pair_gen() -> It<(Float, Ordering)> { Box::new(exhaustive_pairs( exhaustive_floats(), exhaustive_orderings(), )) } pub fn exhaustive_float_ordering_pair_gen_var_1() -> It<(Float, Ordering)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_orderings(), )) } // -- (Float, PrimitiveFloat) -- pub fn exhaustive_float_primitive_float_pair_gen() -> It<(Float, T)> { Box::new(exhaustive_pairs( exhaustive_floats(), exhaustive_primitive_floats(), )) } pub fn exhaustive_float_primitive_float_pair_gen_var_1() -> It<(Float, T)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_primitive_floats(), )) } // -- (Float, PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_float_primitive_float_primitive_float_triple_gen() -> It<(Float, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_primitive_floats(), )) } // -- (Float, PrimitiveSigned) -- pub fn exhaustive_float_signed_pair_gen() -> It<(Float, T)> { Box::new(exhaustive_pairs(exhaustive_floats(), exhaustive_signeds())) } pub fn exhaustive_float_signed_pair_gen_var_1() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_floats_with_sci_exponent(0), exhaustive_signeds(), )) } pub fn exhaustive_float_signed_pair_gen_var_2() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_floats(), exhaustive_signeds(), )) } pub fn exhaustive_float_signed_pair_gen_var_3() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_signeds(), )) } pub fn exhaustive_float_signed_pair_gen_var_4() -> It<(Float, T)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_signeds(), )) } // -- (Float, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_float_signed_signed_triple_gen() -> It<(Float, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_signeds(), )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_float_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(Float, T, U)> { Box::new(exhaustive_triples( exhaustive_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_float_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(Float, T, U)> { Box::new(exhaustive_triples( exhaustive_extreme_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_1() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shl_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_2() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_extreme_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shl_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_3() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shr_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_4() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_extreme_floats(), exhaustive_signeds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shr_prec_round_valid(x, bits, prec, rm)), )) } // -- (Float, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_1() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_signeds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_2() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_extreme_floats(), exhaustive_signeds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_3() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_signeds()), exhaustive_rounding_modes().filter(|&rm| rm != Exact), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_4() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_signeds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_5() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_extreme_floats(), exhaustive_signeds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_signed_rounding_mode_triple_gen_var_6() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_signeds()), exhaustive_rounding_modes().filter(|&rm| rm != Exact), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } // -- (Float, PrimitiveUnsigned) -- pub fn exhaustive_float_unsigned_pair_gen() -> It<(Float, T)> { Box::new(exhaustive_pairs( exhaustive_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_1() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_floats(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_2() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_3() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_4() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_5() -> It<(Float, T)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_6() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_floats().filter(|x| *x > 0u32), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_float_unsigned_pair_gen_var_7() -> It<(Float, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_finite_floats(), exhaustive_positive_primitive_ints(), )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_float_unsigned_unsigned_triple_gen() -> It<(Float, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_unsigneds(), )) } pub fn exhaustive_float_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Float, T, U)> { Box::new(exhaustive_triples( exhaustive_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_float_unsigned_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Float, T, U)> { Box::new(exhaustive_triples( exhaustive_extreme_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1< T: PrimitiveUnsigned, >() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shl_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2< T: PrimitiveUnsigned, >() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_extreme_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shl_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3< T: PrimitiveUnsigned, >() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shr_prec_round_valid(x, bits, prec, rm)), )) } pub fn exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4< T: PrimitiveUnsigned, >() -> It<(Float, T, u64, RoundingMode)> { reshape_3_1_to_4(Box::new( lex_pairs( exhaustive_triples( exhaustive_extreme_floats(), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits, prec), rm)| shr_prec_round_valid(x, bits, prec, rm)), )) } // -- (Float, PrimitiveUnsigned, RoundingMode) -- pub fn set_prec_round_valid(x: &Float, p: u64, rm: RoundingMode) -> bool { rm != Exact || !x.is_finite() || x.is_zero() || x.get_prec().unwrap() <= p || { let significand = x.significand_ref().unwrap(); significand_bits(significand) - significand.trailing_zeros().unwrap() <= p } } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_1() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| set_prec_round_valid(x, p, rm)), )) } pub fn square_prec_round_valid(x: &Float, prec: u64, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact { true } else if extreme { x.square_prec_round_ref(prec, Floor).1 == Equal } else if let Ok(rx) = Rational::try_from(x) { let square = Float::exact_from(rx.square()); if let Some(min_prec) = square.get_min_prec() { prec >= min_prec } else { true } } else { true } } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_2() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| square_prec_round_valid(x, p, rm, false)), )) } pub fn reciprocal_prec_round_valid(x: &Float, prec: u64, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact || *x == 0 { true } else if extreme { x.reciprocal_prec_round_ref(prec, Floor).1 == Equal } else if let Ok(rx) = Rational::try_from(x) { if let Ok(reciprocal) = Float::try_from(rx.reciprocal()) { if let Some(min_prec) = reciprocal.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_3() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| reciprocal_prec_round_valid(x, p, rm, false)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_4() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| set_prec_round_valid(x, p, rm)), )) } pub fn shl_round_valid(x: &Float, bits: T, rm: RoundingMode) -> bool { rm != Exact || !x.is_finite() || x.is_zero() || { let exponent = x.get_exponent().unwrap(); if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_add(bits) { return (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent); } false } } pub fn shl_prec_round_valid( x: &Float, bits: T, prec: u64, rm: RoundingMode, ) -> bool { rm != Exact || !x.is_normal() || x.shl_prec_round_ref(bits, prec, Floor).1 == Equal } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_5() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_6() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_extreme_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_7() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes().filter(|&rm| rm != Exact), ) .filter(|&((ref x, bits), rm)| shl_round_valid(x, bits, rm)), )) } pub fn shr_round_valid(x: &Float, bits: T, rm: RoundingMode) -> bool { rm != Exact || !x.is_finite() || x.is_zero() || { let exponent = x.get_exponent().unwrap(); if let Ok(bits) = bits.try_into() && let Some(new_exponent) = exponent.checked_sub(bits) { return (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent); } false } } pub fn shr_prec_round_valid( x: &Float, bits: T, prec: u64, rm: RoundingMode, ) -> bool { rm != Exact || !x.is_normal() || x.shr_prec_round_ref(bits, prec, Floor).1 == Equal } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_8() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_9() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_extreme_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes(), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_10() -> It<(Float, T, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_unsigneds()), exhaustive_rounding_modes().filter(|&rm| rm != Exact), ) .filter(|&((ref x, bits), rm)| shr_round_valid(x, bits, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_11() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| square_prec_round_valid(x, p, rm, true)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_12() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| reciprocal_prec_round_valid(x, p, rm, true)), )) } pub fn sqrt_prec_round_valid(x: &Float, prec: u64, rm: RoundingMode) -> bool { rm != Exact || x.sqrt_prec_round_ref(prec, Floor).1 == Equal } pub fn reciprocal_sqrt_prec_round_valid(x: &Float, prec: u64, rm: RoundingMode) -> bool { rm != Exact || x.reciprocal_sqrt_prec_round_ref(prec, Floor).1 == Equal } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_13() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| sqrt_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_14() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| sqrt_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_15() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_16() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_17() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_floats().filter(|x| *x > 0u32), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ))) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_18() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_finite_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ))) } pub fn ln_prec_round_valid(x: &Float, _prec: u64, rm: RoundingMode) -> bool { rm != Exact || *x <= 0u32 || *x == 1u32 } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_19() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_floats(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| ln_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_float_unsigned_rounding_mode_triple_gen_var_20() -> It<(Float, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_extreme_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref x, p), rm)| ln_prec_round_valid(x, p, rm)), )) } // -- (Float, Rational) -- pub fn exhaustive_float_rational_pair_gen() -> It<(Float, Rational)> { Box::new(exhaustive_pairs( exhaustive_floats(), exhaustive_rationals(), )) } pub fn exhaustive_float_rational_pair_gen_var_1() -> It<(Float, Rational)> { Box::new(exhaustive_pairs( exhaustive_finite_floats(), exhaustive_rationals(), )) } pub fn exhaustive_float_rational_pair_gen_var_2() -> It<(Float, Rational)> { Box::new(exhaustive_pairs( exhaustive_extreme_floats(), exhaustive_rationals(), )) } // -- (Float, Rational, PrimitiveUnsigned) -- pub fn exhaustive_float_rational_unsigned_triple_gen_var_1() -> It<(Float, Rational, T)> { Box::new(exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_float_rational_unsigned_triple_gen_var_2() -> It<(Float, Rational, T)> { Box::new(exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- pub(crate) fn add_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { if rm != Exact { return true; } if let Ok(rx) = Rational::try_from(x) { if let Ok(sum) = Float::try_from(rx + y) { if let Some(min_prec) = sum.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_1() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub(crate) fn sub_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { if rm != Exact { return true; } if let Ok(rx) = Rational::try_from(x) { if let Ok(diff) = Float::try_from(rx - y) { if let Some(min_prec) = diff.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_2() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub(crate) fn mul_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { if rm != Exact { return true; } if let Ok(rx) = Rational::try_from(x) { if let Ok(product) = Float::try_from(rx * y) { if let Some(min_prec) = product.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_3() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub(crate) fn div_rational_prec_round_valid( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { if rm != Exact || *y == 0u32 { return true; } if let Ok(rx) = Rational::try_from(x) { if let Ok(quotient) = Float::try_from(rx / y) { if let Some(min_prec) = quotient.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub(crate) fn rational_div_float_prec_round_valid( x: &Float, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { if rm != Exact || *x == 0u32 { return true; } if let Ok(rx) = Rational::try_from(x) { if let Ok(quotient) = Float::try_from(y / rx) { if let Some(min_prec) = quotient.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_6() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_7() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_8() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_9() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_10() -> It<(Float, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_custom_output( exhaustive_extreme_floats(), exhaustive_rationals(), exhaustive_positive_primitive_ints(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Rational, Rational) -- pub fn exhaustive_float_rational_rational_triple_gen() -> It<(Float, Rational, Rational)> { Box::new(exhaustive_triples_xyy( exhaustive_floats(), exhaustive_rationals(), )) } // -- (Float, Rational, RoundingMode) -- pub(crate) fn add_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { true } else if let Some(x_prec) = x.get_prec() { if let Ok(sum) = Float::try_from(Rational::exact_from(x) + y) { if let Some(min_prec) = sum.get_min_prec() { x_prec >= min_prec } else { true } } else { false } } else { // y must be representable by precision-1 float y.is_power_of_2() } } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_1() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub(crate) fn sub_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { true } else if let Some(x_prec) = x.get_prec() { if let Ok(diff) = Float::try_from(Rational::exact_from(x) - y) { if let Some(min_prec) = diff.get_min_prec() { x_prec >= min_prec } else { true } } else { false } } else { // y must be representable by precision-1 float y.is_power_of_2() } } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_2() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_3() -> It<(Float, Rational, RoundingMode)> { Box::new(exhaustive_triples( exhaustive_floats(), exhaustive_rationals(), exhaustive_rounding_modes().filter(|&rm| rm != Exact), )) } pub(crate) fn mul_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact { true } else if let Some(x_prec) = x.get_prec() { if let Ok(product) = Float::try_from(Rational::exact_from(x) * y) { if let Some(min_prec) = product.get_min_prec() { x_prec >= min_prec } else { true } } else { false } } else { // y must be representable by precision-1 float y.is_power_of_2() } } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_4() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub(crate) fn div_rational_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact || *y == 0 { true } else if let Some(x_prec) = x.get_prec() { if let Ok(quotient) = Float::try_from(Rational::exact_from(x) / y) { if let Some(min_prec) = quotient.get_min_prec() { x_prec >= min_prec } else { true } } else { false } } else { // y must be representable by precision-1 float y.is_power_of_2() } } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_5() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub(crate) fn rational_div_float_round_valid(x: &Float, y: &Rational, rm: RoundingMode) -> bool { if rm != Exact || *x == 0u32 { true } else if let Some(prec) = x.get_prec() { if let Ok(quotient) = Float::try_from(y / Rational::exact_from(x)) { if let Some(min_prec) = quotient.get_min_prec() { prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_6() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_7() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_extreme_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_8() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_extreme_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_9() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_extreme_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_10() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_extreme_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub fn exhaustive_float_rational_rounding_mode_triple_gen_var_11() -> It<(Float, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_extreme_floats(), exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } // -- (Float, RoundingMode) -- pub fn exhaustive_float_rounding_mode_pair_gen() -> It<(Float, RoundingMode)> { Box::new(lex_pairs(exhaustive_floats(), exhaustive_rounding_modes())) } pub(crate) fn natural_rounding_from_float_valid(f: &Float, rm: RoundingMode) -> bool { match rm { Down | Ceiling | Nearest => f.is_finite() || *f == Float::NEGATIVE_INFINITY, Up | Floor => f.is_finite() && (f.is_sign_positive() || f.is_negative_zero()), Exact => Natural::convertible_from(f), } } pub fn exhaustive_float_rounding_mode_pair_gen_var_1() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| natural_rounding_from_float_valid(f, *rm)), ) } pub(crate) fn integer_rounding_from_float_valid(f: &Float, rm: RoundingMode) -> bool { if rm == Exact { Integer::convertible_from(f) } else { f.is_finite() } } pub fn exhaustive_float_rounding_mode_pair_gen_var_2() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| integer_rounding_from_float_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_3() -> It<(Float, RoundingMode)> { Box::new(lex_pairs( exhaustive_nonzero_finite_floats(), exhaustive_rounding_modes(), )) } #[allow(clippy::type_repetition_in_bounds)] pub(crate) fn unsigned_rounding_from_float_valid( f: &Float, rm: RoundingMode, ) -> bool where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { match rm { Floor => f.is_sign_positive() || f.is_negative_zero(), Ceiling => *f <= T::MAX, Down | Nearest => !f.is_nan(), Up => (f.is_sign_positive() || f.is_negative_zero()) && *f <= T::MAX, Exact => T::convertible_from(f), } } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_4() -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub(crate) fn signed_rounding_from_float_valid( f: &Float, rm: RoundingMode, ) -> bool where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { match rm { Floor => *f >= T::MIN, Ceiling => *f <= T::MAX, Down | Nearest => !f.is_nan(), Up => *f >= T::MIN && *f <= T::MAX, Exact => T::convertible_from(f), } } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_5() -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_6() -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub(crate) fn square_round_valid(x: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact { true } else if extreme { x.square_round_ref(Floor).1 == Equal } else if let Some(x_prec) = x.get_prec() { let square = Float::exact_from(Rational::exact_from(x).square()); if let Some(min_prec) = square.get_min_prec() { x_prec >= min_prec } else { true } } else { true } } pub fn exhaustive_float_rounding_mode_pair_gen_var_7() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_8() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range(1, Limb::WIDTH - 1), exhaustive_rounding_modes(), ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_9() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_positive_floats_with_precision(Limb::WIDTH), exhaustive_rounding_modes(), ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_10() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range( Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ), exhaustive_rounding_modes(), ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_11() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_positive_floats_with_precision(Limb::WIDTH << 1), exhaustive_rounding_modes(), ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_12() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range( (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ), exhaustive_rounding_modes(), ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub(crate) fn reciprocal_round_valid(x: &Float, rm: RoundingMode, extreme: bool) -> bool { if rm != Exact || *x == 0 { true } else if extreme { x.reciprocal_round_ref(Floor).1 == Equal } else if let Some(x_prec) = x.get_prec() { if let Ok(reciprocal) = Float::try_from(Rational::exact_from(x).reciprocal()) { if let Some(min_prec) = reciprocal.get_min_prec() { x_prec >= min_prec } else { true } } else { false } } else { true } } pub fn exhaustive_float_rounding_mode_pair_gen_var_13() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_14() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range(1, Limb::WIDTH - 1), exhaustive_rounding_modes(), ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_15() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_positive_floats_with_precision(Limb::WIDTH), exhaustive_rounding_modes(), ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_16() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range( Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ), exhaustive_rounding_modes(), ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_17() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range(Limb::WIDTH + 1, u64::MAX), exhaustive_rounding_modes(), ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_18() -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_19() -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn exhaustive_float_rounding_mode_pair_gen_var_20() -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_21() -> It<(Float, RoundingMode)> { Box::new(lex_pairs( exhaustive_extreme_floats(), exhaustive_rounding_modes(), )) } pub fn exhaustive_float_rounding_mode_pair_gen_var_22() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| square_round_valid(f, *rm, true)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_23() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, true)), ) } pub(crate) fn sqrt_round_valid(x: &Float, rm: RoundingMode) -> bool { rm != Exact || x.sqrt_round_ref(Floor).1 == Equal } pub fn exhaustive_float_rounding_mode_pair_gen_var_24() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_25() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range(1, Limb::WIDTH - 1), exhaustive_rounding_modes(), ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_26() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_positive_floats_with_precision(Limb::WIDTH), exhaustive_rounding_modes(), ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_27() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range( Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ), exhaustive_rounding_modes(), ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_28() -> It<(Float, RoundingMode)> { Box::new( lex_pairs( exhaustive_floats_with_precision_inclusive_range((Limb::WIDTH << 1) + 1, u64::MAX), exhaustive_rounding_modes(), ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_29() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub(crate) fn reciprocal_sqrt_round_valid(x: &Float, rm: RoundingMode) -> bool { rm != Exact || x.reciprocal_sqrt_round_ref(Floor).1 == Equal } pub fn exhaustive_float_rounding_mode_pair_gen_var_30() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_31() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_32() -> It<(Float, RoundingMode)> { Box::new(lex_pairs( exhaustive_floats().filter(|x| *x > 0u32), exhaustive_rounding_modes(), )) } pub fn exhaustive_float_rounding_mode_pair_gen_var_33() -> It<(Float, RoundingMode)> { Box::new(lex_pairs( exhaustive_finite_floats(), exhaustive_rounding_modes(), )) } pub(crate) fn ln_round_valid(x: &Float, rm: RoundingMode) -> bool { rm != Exact || *x <= 0u32 || *x == 1u32 } pub fn exhaustive_float_rounding_mode_pair_gen_var_34() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } pub fn exhaustive_float_rounding_mode_pair_gen_var_35() -> It<(Float, RoundingMode)> { Box::new( lex_pairs(exhaustive_extreme_floats(), exhaustive_rounding_modes()) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. pub fn exhaustive_integer_unsigned_rounding_mode_triple_gen_var_3() -> It<(Integer, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_integers(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), )) } pub fn exhaustive_integer_unsigned_rounding_mode_triple_gen_var_4() -> It<(Integer, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_integers(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes().filter(|rm| *rm != Exact), ))) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- // var 1 is in malachite-nz. pub fn exhaustive_natural_unsigned_rounding_mode_triple_gen_var_2() -> It<(Natural, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), )) } pub fn exhaustive_natural_unsigned_rounding_mode_triple_gen_var_3() -> It<(Natural, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes().filter(|&rm| rm != Exact), ))) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn from_primitive_float_prec_round_valid( x: T, p: u64, rm: RoundingMode, ) -> bool where Float: From, { set_prec_round_valid(&Float::from(x), p, rm) } pub fn exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_3() -> It<(T, u64, RoundingMode)> where Float: From, { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_primitive_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((x, p), rm)| from_primitive_float_prec_round_valid(x, p, rm)), )) } pub fn exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_4() -> It<(T, u64, RoundingMode)> where Float: From, { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_primitive_floats(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes().filter(|rm| *rm != Exact), ))) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_3() -> It<(T, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_signeds::(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), )) } pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_4() -> It<(T, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_signeds::(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes().filter(|rm| *rm != Exact), ))) } pub fn exhaustive_signed_unsigned_rounding_mode_triple_gen_var_5() -> It<(i64, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_signeds(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((pow, _), rm)| { rm != Exact || (Float::MIN_EXPONENT..=Float::MAX_EXPONENT) .contains(&i32::saturating_from(pow).saturating_add(1)) }), )) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 5 are in malachite-base. pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_6() -> It<(T, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), )) } pub fn exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_7() -> It<(T, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny( exhaustive_unsigneds::(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes().filter(|rm| *rm != Exact), ))) } // -- (Rational, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_1() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), )) } pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_2() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes().filter(|rm| *rm != Exact), ))) } pub fn sqrt_rational_prec_round_valid(x: &Rational, prec: u64, rm: RoundingMode) -> bool { rm != Exact || Float::sqrt_rational_prec_round_ref(x, prec, Floor).1 == Equal } pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_3() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| sqrt_rational_prec_round_valid(n, prec, rm)), )) } pub fn reciprocal_sqrt_rational_prec_round_valid( x: &Rational, prec: u64, rm: RoundingMode, ) -> bool { rm != Exact || Float::reciprocal_sqrt_rational_prec_round_ref(x, prec, Floor).1 == Equal } pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_4() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| reciprocal_sqrt_rational_prec_round_valid(n, prec, rm)), )) } pub fn agm_rational_prec_round_valid( x: &Rational, y: &Rational, prec: u64, rm: RoundingMode, ) -> bool { rm != Exact || *x < 0u32 || *y < 0u32 || x == y && Float::from_rational_prec_round_ref(x, prec, Floor).1 == Equal } pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_5() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny( exhaustive_non_negative_rationals(), exhaustive_positive_primitive_ints(), ), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), )) } pub fn ln_rational_prec_round_valid(x: &Rational, _prec: u64, rm: RoundingMode) -> bool { rm != Exact || *x <= 0 || *x == 1u32 } pub fn exhaustive_rational_unsigned_rounding_mode_triple_gen_var_6() -> It<(Rational, u64, RoundingMode)> { reshape_2_1_to_3(Box::new( lex_pairs( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_positive_primitive_ints()), exhaustive_rounding_modes(), ) .filter(|&((ref n, prec), rm)| ln_rational_prec_round_valid(n, prec, rm)), )) } // -- (Rational, Rational, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() -> It<(Rational, Rational, u64, RoundingMode)> { Box::new( reshape_3_1_to_4(Box::new(lex_pairs( exhaustive_triples_xxy_custom_output( exhaustive_rationals(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ), exhaustive_rounding_modes(), ))) .filter(|(x, y, prec, rm)| agm_rational_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Rational, RoundingMode) -- // vars 1 through 5 are in malachite-q. pub fn exhaustive_rational_rounding_mode_pair_gen_var_6() -> It<(Rational, RoundingMode)> { Box::new( lex_pairs(exhaustive_rationals(), exhaustive_rounding_modes()).filter(|&(ref n, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= 1 }), ) } ================================================ FILE: malachite-float/src/test_util/generators/mod.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::test_util::generators::common::{ float_float_anything_rounding_mode_quadruple_rm, float_float_anything_triple_rm, float_float_rounding_mode_triple_rm, float_integer_pair_rm, float_natural_pair_rm, float_pair_rm, float_primitive_float_pair_rm, float_primitive_int_pair_rm, float_rational_anything_rounding_mode_quadruple_rm, float_rational_anything_triple_rm, float_rational_pair_rm, float_rational_rounding_mode_triple_rm, float_rm, float_rounding_mode_pair_rm, float_t_rounding_mode_triple_rm, float_t_u_rounding_mode_quadruple_rm, float_t_u_triple_rm, }; use crate::test_util::generators::exhaustive::*; use crate::test_util::generators::random::*; use crate::test_util::generators::special_random::*; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::generators::common::Generator; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::Rational; use std::cmp::Ordering; // -- Float -- pub fn float_gen() -> Generator { Generator::new( &exhaustive_float_gen, &random_float_gen, &special_random_float_gen, ) } pub fn float_gen_rm() -> Generator<(rug::Float, Float)> { Generator::new( &|| float_rm(exhaustive_float_gen()), &|config| float_rm(random_float_gen(config)), &|config| float_rm(special_random_float_gen(config)), ) } // All positive finite floats (not including positive zero). pub fn float_gen_var_1() -> Generator { Generator::new( &exhaustive_float_gen_var_1, &random_float_gen_var_1, &special_random_float_gen_var_1, ) } // All floats except NaN. pub fn float_gen_var_2() -> Generator { Generator::new( &exhaustive_float_gen_var_2, &random_float_gen_var_2, &special_random_float_gen_var_2, ) } pub fn float_gen_var_2_rm() -> Generator<(rug::Float, Float)> { Generator::new( &|| float_rm(exhaustive_float_gen_var_2()), &|config| float_rm(random_float_gen_var_2(config)), &|config| float_rm(special_random_float_gen_var_2(config)), ) } // All nonzero finite floats. pub fn float_gen_var_3() -> Generator { Generator::new( &exhaustive_float_gen_var_3, &random_float_gen_var_3, &special_random_float_gen_var_3, ) } // All finite floats. pub fn float_gen_var_4() -> Generator { Generator::new( &exhaustive_float_gen_var_4, &random_float_gen_var_4, &special_random_float_gen_var_4, ) } // All non-negative finite floats. pub fn float_gen_var_5() -> Generator { Generator::new( &exhaustive_float_gen_var_5, &random_float_gen_var_5, &special_random_float_gen_var_5, ) } // All floats with a precision less than `Limb::WIDTH`. pub fn float_gen_var_6() -> Generator { Generator::new( &exhaustive_float_gen_var_6, &random_float_gen_var_6, &special_random_float_gen_var_6, ) } // All floats with precision `Limb::WIDTH`. pub fn float_gen_var_7() -> Generator { Generator::new( &exhaustive_float_gen_var_7, &random_float_gen_var_7, &special_random_float_gen_var_7, ) } // All floats with a precision greater than `Limb::WIDTH` and less than `Limb::WIDTH` * 2. pub fn float_gen_var_8() -> Generator { Generator::new( &exhaustive_float_gen_var_8, &random_float_gen_var_8, &special_random_float_gen_var_8, ) } // All floats with precision `Limb::WIDTH` * 2. pub fn float_gen_var_9() -> Generator { Generator::new( &exhaustive_float_gen_var_9, &random_float_gen_var_9, &special_random_float_gen_var_9, ) } // All floats with a precision greater than `Limb::WIDTH` * 2 and less than `Limb::WIDTH` * 3. pub fn float_gen_var_10() -> Generator { Generator::new( &exhaustive_float_gen_var_10, &random_float_gen_var_10, &special_random_float_gen_var_10, ) } // All floats with a precision greater than `Limb::WIDTH` * 2. pub fn float_gen_var_11() -> Generator { Generator::new( &exhaustive_float_gen_var_11, &random_float_gen_var_11, &special_random_float_gen_var_11, ) } // Extreme floats. pub fn float_gen_var_12() -> Generator { Generator::new( &exhaustive_float_gen_var_12, &random_float_gen_var_12, &special_random_float_gen_var_12, ) } // Extreme nonzero finite floats. pub fn float_gen_var_13() -> Generator { Generator::new( &exhaustive_float_gen_var_13, &random_float_gen_var_13, &special_random_float_gen_var_13, ) } // All extreme floats except NaN. pub fn float_gen_var_14() -> Generator { Generator::new( &exhaustive_float_gen_var_14, &random_float_gen_var_14, &special_random_float_gen_var_14, ) } // All positive `Float`s. pub fn float_gen_var_15() -> Generator { Generator::new( &exhaustive_float_gen_var_15, &random_float_gen_var_15, &special_random_float_gen_var_15, ) } // -- (Float, Float) -- pub fn float_pair_gen() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen, &random_float_pair_gen, &special_random_float_pair_gen, ) } pub fn float_pair_gen_rm() -> Generator<((rug::Float, rug::Float), (Float, Float))> { Generator::new( &|| float_pair_rm(exhaustive_float_pair_gen()), &|config| float_pair_rm(random_float_pair_gen(config)), &|config| float_pair_rm(special_random_float_pair_gen(config)), ) } // All pairs of finite floats. pub fn float_pair_gen_var_1() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_1, &random_float_pair_gen_var_1, &special_random_float_pair_gen_var_1, ) } // All pairs of positive floats with the same precision, which is greater than zero and less than // `Limb::WIDTH`. pub fn float_pair_gen_var_2() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_2, &random_float_pair_gen_var_2, &special_random_float_pair_gen_var_2, ) } // All pairs of positive floats with the same precision, which is `Limb::WIDTH`. pub fn float_pair_gen_var_3() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_3, &random_float_pair_gen_var_3, &special_random_float_pair_gen_var_3, ) } // All pairs of positive floats with the same precision, which is greater than `Limb::WIDTH` and // less than twice `Limb::WIDTH`. pub fn float_pair_gen_var_4() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_4, &random_float_pair_gen_var_4, &special_random_float_pair_gen_var_4, ) } // All pairs of positive floats with the same precision, which is twice `Limb::WIDTH`. pub fn float_pair_gen_var_5() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_5, &random_float_pair_gen_var_5, &special_random_float_pair_gen_var_5, ) } // All pairs of positive floats with the same precision, which is greater than twice `Limb::WIDTH` // and less than three times `Limb::WIDTH`. pub fn float_pair_gen_var_6() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_6, &random_float_pair_gen_var_6, &special_random_float_pair_gen_var_6, ) } // All pairs of positive floats with the same precision, which is greater than or equal to three // times `Limb::WIDTH`. pub fn float_pair_gen_var_7() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_7, &random_float_pair_gen_var_7, &special_random_float_pair_gen_var_7, ) } // All pairs of positive floats with different precisions, such that the precision of the second // float is less than or equal to `Limb::WIDTH`. pub fn float_pair_gen_var_8() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_8, &random_float_pair_gen_var_8, &special_random_float_pair_gen_var_8, ) } // All pairs of positive floats with different precisions, such that the precision of the second // float is greater than `Limb::WIDTH`. pub fn float_pair_gen_var_9() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_9, &random_float_pair_gen_var_9, &special_random_float_pair_gen_var_9, ) } // All pairs of floats, some of which are extreme. pub fn float_pair_gen_var_10() -> Generator<(Float, Float)> { Generator::new( &exhaustive_float_pair_gen_var_10, &random_float_pair_gen_var_10, &special_random_float_pair_gen, ) } // -- (Float, Float, Float) -- pub fn float_triple_gen() -> Generator<(Float, Float, Float)> { Generator::new( &exhaustive_float_triple_gen, &random_float_triple_gen, &special_random_float_triple_gen, ) } // -- (Float, Float, Integer) -- pub fn float_float_integer_triple_gen() -> Generator<(Float, Float, Integer)> { Generator::new( &exhaustive_float_float_integer_triple_gen, &random_float_float_integer_triple_gen, &special_random_float_float_integer_triple_gen, ) } // -- (Float, Float, Natural) -- pub fn float_float_natural_triple_gen() -> Generator<(Float, Float, Natural)> { Generator::new( &exhaustive_float_float_natural_triple_gen, &random_float_float_natural_triple_gen, &special_random_float_float_natural_triple_gen, ) } // -- (Float, Float, PrimitiveFloat) -- pub fn float_float_primitive_float_triple_gen() -> Generator<(Float, Float, T)> { Generator::new( &exhaustive_float_float_primitive_float_triple_gen, &random_float_float_primitive_float_triple_gen, &special_random_float_float_primitive_float_triple_gen, ) } // -- (Float, Float, PrimitiveSigned) -- pub fn float_float_signed_triple_gen() -> Generator<(Float, Float, T)> { Generator::new( &exhaustive_float_float_signed_triple_gen, &random_float_float_primitive_int_triple_gen, &special_random_float_float_signed_triple_gen, ) } // -- (Float, Float, PrimitiveUnsigned) -- pub fn float_float_unsigned_triple_gen() -> Generator<(Float, Float, T)> { Generator::new( &exhaustive_float_float_unsigned_triple_gen, &random_float_float_primitive_int_triple_gen, &special_random_float_float_unsigned_triple_gen, ) } // All triples of `(Float, Float, T)`, where `T` is unsigned, small, and positive. pub fn float_float_unsigned_triple_gen_var_1() -> Generator<(Float, Float, T)> { Generator::new( &exhaustive_float_float_unsigned_triple_gen_var_1, &random_float_float_unsigned_triple_gen_var_1, &special_random_float_float_unsigned_triple_gen_var_1, ) } pub fn float_float_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Float, rug::Float, T), (Float, Float, T))> { Generator::new( &|| float_float_anything_triple_rm(exhaustive_float_float_unsigned_triple_gen_var_1()), &|config| { float_float_anything_triple_rm(random_float_float_unsigned_triple_gen_var_1(config)) }, &|config| { float_float_anything_triple_rm(special_random_float_float_unsigned_triple_gen_var_1( config, )) }, ) } // All triples of `(Float, Float, T)`, where the `Float`s may be extreme and the `T` is unsigned, // small, and positive. pub fn float_float_unsigned_triple_gen_var_2() -> Generator<(Float, Float, T)> { Generator::new( &exhaustive_float_float_unsigned_triple_gen_var_2, &random_float_float_unsigned_triple_gen_var_2, &special_random_float_float_unsigned_triple_gen_var_2, ) } // -- (Float, Float, PrimitiveUnsigned, RoundingMode) -- // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::add_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_1() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_1, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_1, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_1, ) } pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( (rug::Float, rug::Float, u64, rug::float::Round), (Float, Float, u64, RoundingMode), )> { Generator::new( &|| { float_float_anything_rounding_mode_quadruple_rm( exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_1(), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( random_float_float_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::sub_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_2() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_2, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_2, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_2, ) } pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_2_rm() -> Generator<( (rug::Float, rug::Float, u64, rug::float::Round), (Float, Float, u64, RoundingMode), )> { Generator::new( &|| { float_float_anything_rounding_mode_quadruple_rm( exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_2(), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( random_float_float_unsigned_rounding_mode_quadruple_gen_var_2(config), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_2(config), ) }, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::mul_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_3() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_3, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_3, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_3, ) } pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( (rug::Float, rug::Float, u64, rug::float::Round), (Float, Float, u64, RoundingMode), )> { Generator::new( &|| { float_float_anything_rounding_mode_quadruple_rm( exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_3(), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( random_float_float_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::div_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_4() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_4, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_4, ) } pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_4_rm() -> Generator<( (rug::Float, rug::Float, u64, rug::float::Round), (Float, Float, u64, RoundingMode), )> { Generator::new( &|| { float_float_anything_rounding_mode_quadruple_rm( exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_4(), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( random_float_float_unsigned_rounding_mode_quadruple_gen_var_4(config), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_4(config), ) }, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::add_prec_round`, where // the `Float`s may be extreme. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_5() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_5, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_5, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_5, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::sub_prec_round`, where // the `Float`s may be extreme. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_6() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_6, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_6, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_6, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::mul_prec_round`, where // the `Float`s may be extreme. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_7() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_7, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_7, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_7, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::div_prec_round`, where // the `Float`s may be extreme. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_8() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_8, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_8, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_8, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::agm_prec_round`. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_9() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_9, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_9, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_9, ) } pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_9_rm() -> Generator<( (rug::Float, rug::Float, u64, rug::float::Round), (Float, Float, u64, RoundingMode), )> { Generator::new( &|| { float_float_anything_rounding_mode_quadruple_rm( exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_9(), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( random_float_float_unsigned_rounding_mode_quadruple_gen_var_9(config), ) }, &|config| { float_float_anything_rounding_mode_quadruple_rm( special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_9(config), ) }, ) } // All `(Float, Float, u64, RoundingMode)` that are valid inputs to `Float::agm_prec_round`, where // the `Float`s may be extreme. pub fn float_float_unsigned_rounding_mode_quadruple_gen_var_10() -> Generator<(Float, Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_float_unsigned_rounding_mode_quadruple_gen_var_10, &random_float_float_unsigned_rounding_mode_quadruple_gen_var_10, &special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_10, ) } // -- (Float, Float, Rational) -- pub fn float_float_rational_triple_gen() -> Generator<(Float, Float, Rational)> { Generator::new( &exhaustive_float_float_rational_triple_gen, &random_float_float_rational_triple_gen, &special_random_float_float_rational_triple_gen, ) } // -- (Float, Float, RoundingMode) -- // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`. pub fn float_float_rounding_mode_triple_gen_var_1() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_1, &random_float_float_rounding_mode_triple_gen_var_1, &special_random_float_float_rounding_mode_triple_gen_var_1, ) } pub fn float_float_rounding_mode_triple_gen_var_1_rm() -> Generator<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Generator::new( &|| { float_float_rounding_mode_triple_rm( exhaustive_float_float_rounding_mode_triple_gen_var_3(), ) }, &|config| { float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_3( config, )) }, &|config| { float_float_rounding_mode_triple_rm( special_random_float_float_rounding_mode_triple_gen_var_3(config), ) }, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`. pub fn float_float_rounding_mode_triple_gen_var_2() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_2, &random_float_float_rounding_mode_triple_gen_var_2, &special_random_float_float_rounding_mode_triple_gen_var_2, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round` or // `Float::sub_round`, excluding those with Exact. pub fn float_float_rounding_mode_triple_gen_var_3_rm() -> Generator<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Generator::new( &|| { float_float_rounding_mode_triple_rm( exhaustive_float_float_rounding_mode_triple_gen_var_3(), ) }, &|config| { float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_3( config, )) }, &|config| { float_float_rounding_mode_triple_rm( special_random_float_float_rounding_mode_triple_gen_var_3(config), ) }, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is greater than zero and less than `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_4() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_4, &random_float_float_rounding_mode_triple_gen_var_4, &special_random_float_float_rounding_mode_triple_gen_var_4, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_5() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_5, &random_float_float_rounding_mode_triple_gen_var_5, &special_random_float_float_rounding_mode_triple_gen_var_5, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is greater than `Limb::WIDTH` and less than twice // `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_6() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_6, &random_float_float_rounding_mode_triple_gen_var_6, &special_random_float_float_rounding_mode_triple_gen_var_6, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is twice `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_7() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_7, &random_float_float_rounding_mode_triple_gen_var_7, &special_random_float_float_rounding_mode_triple_gen_var_7, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is greater than twice `Limb::WIDTH` and less than three // times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_8() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_8, &random_float_float_rounding_mode_triple_gen_var_8, &special_random_float_float_rounding_mode_triple_gen_var_8, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, where the // `Float`s have the same precision, which is greater than or equal to three times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_9() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_9, &random_float_float_rounding_mode_triple_gen_var_9, &special_random_float_float_rounding_mode_triple_gen_var_9, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is greater than zero and less than `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_10() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_10, &random_float_float_rounding_mode_triple_gen_var_10, &special_random_float_float_rounding_mode_triple_gen_var_10, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_11() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_11, &random_float_float_rounding_mode_triple_gen_var_11, &special_random_float_float_rounding_mode_triple_gen_var_11, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is greater than `Limb::WIDTH` and less than twice // `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_12() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_12, &random_float_float_rounding_mode_triple_gen_var_12, &special_random_float_float_rounding_mode_triple_gen_var_12, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is twice `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_13() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_13, &random_float_float_rounding_mode_triple_gen_var_13, &special_random_float_float_rounding_mode_triple_gen_var_13, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is greater than twice `Limb::WIDTH` and less than three // times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_14() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_14, &random_float_float_rounding_mode_triple_gen_var_14, &special_random_float_float_rounding_mode_triple_gen_var_14, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, where the // `Float`s have the same precision, which is greater than or equal to three times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_15() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_15, &random_float_float_rounding_mode_triple_gen_var_15, &special_random_float_float_rounding_mode_triple_gen_var_15, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`. pub fn float_float_rounding_mode_triple_gen_var_16() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_16, &random_float_float_rounding_mode_triple_gen_var_16, &special_random_float_float_rounding_mode_triple_gen_var_16, ) } pub fn float_float_rounding_mode_triple_gen_var_16_rm() -> Generator<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Generator::new( &|| { float_float_rounding_mode_triple_rm( exhaustive_float_float_rounding_mode_triple_gen_var_16(), ) }, &|config| { float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_16( config, )) }, &|config| { float_float_rounding_mode_triple_rm( special_random_float_float_rounding_mode_triple_gen_var_16(config), ) }, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is greater than zero and less than `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_17() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_17, &random_float_float_rounding_mode_triple_gen_var_17, &special_random_float_float_rounding_mode_triple_gen_var_17, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_18() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_18, &random_float_float_rounding_mode_triple_gen_var_18, &special_random_float_float_rounding_mode_triple_gen_var_18, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is greater than `Limb::WIDTH` and less than twice // `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_19() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_19, &random_float_float_rounding_mode_triple_gen_var_19, &special_random_float_float_rounding_mode_triple_gen_var_19, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is twice `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_20() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_20, &random_float_float_rounding_mode_triple_gen_var_20, &special_random_float_float_rounding_mode_triple_gen_var_20, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is greater than twice `Limb::WIDTH` and less than three // times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_21() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_21, &random_float_float_rounding_mode_triple_gen_var_21, &special_random_float_float_rounding_mode_triple_gen_var_21, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, where the // `Float`s have the same precision, which is greater than or equal to three times `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_22() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_22, &random_float_float_rounding_mode_triple_gen_var_22, &special_random_float_float_rounding_mode_triple_gen_var_22, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`. pub fn float_float_rounding_mode_triple_gen_var_23() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_23, &random_float_float_rounding_mode_triple_gen_var_23, &special_random_float_float_rounding_mode_triple_gen_var_23, ) } pub fn float_float_rounding_mode_triple_gen_var_23_rm() -> Generator<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Generator::new( &|| { float_float_rounding_mode_triple_rm( exhaustive_float_float_rounding_mode_triple_gen_var_23(), ) }, &|config| { float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_23( config, )) }, &|config| { float_float_rounding_mode_triple_rm( special_random_float_float_rounding_mode_triple_gen_var_23(config), ) }, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s have the same precision, which is greater than zero and less than `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_24() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_24, &random_float_float_rounding_mode_triple_gen_var_24, &special_random_float_float_rounding_mode_triple_gen_var_24, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s have the same precision, which is `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_25() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_25, &random_float_float_rounding_mode_triple_gen_var_25, &special_random_float_float_rounding_mode_triple_gen_var_25, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s have the same precision, which is greater than `Limb::WIDTH` and less than twice // `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_26() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_26, &random_float_float_rounding_mode_triple_gen_var_26, &special_random_float_float_rounding_mode_triple_gen_var_26, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s have different precisions and that the precision of the second float is less than or // equal to `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_27() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_27, &random_float_float_rounding_mode_triple_gen_var_27, &special_random_float_float_rounding_mode_triple_gen_var_27, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s have different precisions and that the precision of the second float is greater than // `Limb::WIDTH`. pub fn float_float_rounding_mode_triple_gen_var_28() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_28, &random_float_float_rounding_mode_triple_gen_var_28, &special_random_float_float_rounding_mode_triple_gen_var_28, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::add_round`, and the `Float`s // may be extreme. pub fn float_float_rounding_mode_triple_gen_var_29() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_29, &random_float_float_rounding_mode_triple_gen_var_29, &special_random_float_float_rounding_mode_triple_gen_var_29, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::sub_round`, and the `Float`s // may be extreme. pub fn float_float_rounding_mode_triple_gen_var_30() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_30, &random_float_float_rounding_mode_triple_gen_var_30, &special_random_float_float_rounding_mode_triple_gen_var_30, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::mul_round`, and the `Float`s // may be extreme. pub fn float_float_rounding_mode_triple_gen_var_31() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_31, &random_float_float_rounding_mode_triple_gen_var_31, &special_random_float_float_rounding_mode_triple_gen_var_31, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::div_round`, where the // `Float`s may be extreme. pub fn float_float_rounding_mode_triple_gen_var_32() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_32, &random_float_float_rounding_mode_triple_gen_var_32, &special_random_float_float_rounding_mode_triple_gen_var_32, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::agm_round`. pub fn float_float_rounding_mode_triple_gen_var_33() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_33, &random_float_float_rounding_mode_triple_gen_var_33, &special_random_float_float_rounding_mode_triple_gen_var_33, ) } pub fn float_float_rounding_mode_triple_gen_var_33_rm() -> Generator<( (rug::Float, rug::Float, rug::float::Round), (Float, Float, RoundingMode), )> { Generator::new( &|| { float_float_rounding_mode_triple_rm( exhaustive_float_float_rounding_mode_triple_gen_var_33(), ) }, &|config| { float_float_rounding_mode_triple_rm(random_float_float_rounding_mode_triple_gen_var_33( config, )) }, &|config| { float_float_rounding_mode_triple_rm( special_random_float_float_rounding_mode_triple_gen_var_33(config), ) }, ) } // All `(Float, Float, RoundingMode)` that are valid inputs to `Float::agm_round`, where the // `Float`s may be extreme. pub fn float_float_rounding_mode_triple_gen_var_34() -> Generator<(Float, Float, RoundingMode)> { Generator::new( &exhaustive_float_float_rounding_mode_triple_gen_var_34, &random_float_float_rounding_mode_triple_gen_var_34, &special_random_float_float_rounding_mode_triple_gen_var_34, ) } // -- (Float, Integer) -- pub fn float_integer_pair_gen() -> Generator<(Float, Integer)> { Generator::new( &exhaustive_float_integer_pair_gen, &random_float_integer_pair_gen, &special_random_float_integer_pair_gen, ) } pub fn float_integer_pair_gen_rm() -> Generator<((rug::Float, rug::Integer), (Float, Integer))> { Generator::new( &|| float_integer_pair_rm(exhaustive_float_integer_pair_gen()), &|config| float_integer_pair_rm(random_float_integer_pair_gen(config)), &|config| float_integer_pair_rm(special_random_float_integer_pair_gen(config)), ) } // All pairs of finite Floats and Integers. pub fn float_integer_pair_gen_var_1() -> Generator<(Float, Integer)> { Generator::new( &exhaustive_float_integer_pair_gen_var_1, &random_float_integer_pair_gen_var_1, &special_random_float_integer_pair_gen_var_1, ) } // All pairs of Floats and Integers, where the Float is extreme. pub fn float_integer_pair_gen_var_2() -> Generator<(Float, Integer)> { Generator::new( &exhaustive_float_integer_pair_gen_var_2, &random_float_integer_pair_gen_var_2, &special_random_float_integer_pair_gen_var_2, ) } // -- (Float, Integer, Integer) -- pub fn float_integer_integer_triple_gen() -> Generator<(Float, Integer, Integer)> { Generator::new( &exhaustive_float_integer_integer_triple_gen, &random_float_integer_integer_triple_gen, &special_random_float_integer_integer_triple_gen, ) } // -- (Float, Natural) -- pub fn float_natural_pair_gen() -> Generator<(Float, Natural)> { Generator::new( &exhaustive_float_natural_pair_gen, &random_float_natural_pair_gen, &special_random_float_natural_pair_gen, ) } pub fn float_natural_pair_gen_rm() -> Generator<((rug::Float, rug::Integer), (Float, Natural))> { Generator::new( &|| float_natural_pair_rm(exhaustive_float_natural_pair_gen()), &|config| float_natural_pair_rm(random_float_natural_pair_gen(config)), &|config| float_natural_pair_rm(special_random_float_natural_pair_gen(config)), ) } // All pairs of finite Floats and Naturals. pub fn float_natural_pair_gen_var_1() -> Generator<(Float, Natural)> { Generator::new( &exhaustive_float_natural_pair_gen_var_1, &random_float_natural_pair_gen_var_1, &special_random_float_natural_pair_gen_var_1, ) } // All pairs of Floats and Naturals, where the Float is extreme. pub fn float_natural_pair_gen_var_2() -> Generator<(Float, Natural)> { Generator::new( &exhaustive_float_natural_pair_gen_var_2, &random_float_natural_pair_gen_var_2, &special_random_float_natural_pair_gen_var_2, ) } // -- (Float, Natural, Natural) -- pub fn float_natural_natural_triple_gen() -> Generator<(Float, Natural, Natural)> { Generator::new( &exhaustive_float_natural_natural_triple_gen, &random_float_natural_natural_triple_gen, &special_random_float_natural_natural_triple_gen, ) } // -- (Float, Ordering) -- pub fn float_ordering_pair_gen() -> Generator<(Float, Ordering)> { Generator::new( &exhaustive_float_ordering_pair_gen, &random_float_ordering_pair_gen, &special_random_float_ordering_pair_gen, ) } // All `(Float, Ordering)` where the `Float` is extreme. pub fn float_ordering_pair_gen_var_1() -> Generator<(Float, Ordering)> { Generator::new( &exhaustive_float_ordering_pair_gen_var_1, &random_float_ordering_pair_gen_var_1, &special_random_float_ordering_pair_gen_var_1, ) } // -- (Float, PrimitiveFloat) -- pub fn float_primitive_float_pair_gen() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_primitive_float_pair_gen, &random_float_primitive_float_pair_gen, &special_random_float_primitive_float_pair_gen, ) } pub fn float_primitive_float_pair_gen_rm() -> Generator<((rug::Float, T), (Float, T))> { Generator::new( &|| float_primitive_float_pair_rm(exhaustive_float_primitive_float_pair_gen()), &|config| float_primitive_float_pair_rm(random_float_primitive_float_pair_gen(config)), &|config| { float_primitive_float_pair_rm(special_random_float_primitive_float_pair_gen(config)) }, ) } // All `(Float, T)` where the Float is extreme and `T` is a primitive float. pub fn float_primitive_float_pair_gen_var_1() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_primitive_float_pair_gen_var_1, &random_float_primitive_float_pair_gen_var_1, &special_random_float_primitive_float_pair_gen_var_1, ) } // -- (Float, PrimitiveFloat, PrimitiveFloat) -- pub fn float_primitive_float_primitive_float_triple_gen() -> Generator<(Float, T, T)> { Generator::new( &exhaustive_float_primitive_float_primitive_float_triple_gen, &random_float_primitive_float_primitive_float_triple_gen, &special_random_float_primitive_float_primitive_float_triple_gen, ) } // -- (Float, PrimitiveSigned) -- pub fn float_signed_pair_gen() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_signed_pair_gen, &random_float_signed_pair_gen, &special_random_float_signed_pair_gen, ) } pub fn float_signed_pair_gen_rm() -> Generator<((rug::Float, T), (Float, T))> { Generator::new( &|| float_primitive_int_pair_rm(exhaustive_float_signed_pair_gen()), &|config| float_primitive_int_pair_rm(random_float_signed_pair_gen(config)), &|config| float_primitive_int_pair_rm(special_random_float_signed_pair_gen(config)), ) } // All `(Float, T)` where `T` is signed and small and the `Float` is in the range [1.0, 2.0). pub fn float_signed_pair_gen_var_1() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_signed_pair_gen_var_1, &random_float_signed_pair_gen_var_1, &special_random_float_signed_pair_gen_var_1, ) } // All `(Float, T)` where `T` is small and signed. pub fn float_signed_pair_gen_var_2() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_signed_pair_gen_var_2, &random_float_signed_pair_gen_var_2, &special_random_float_signed_pair_gen_var_2, ) } pub fn float_signed_pair_gen_var_2_rm() -> Generator<((rug::Float, T), (Float, T))> { Generator::new( &|| float_primitive_int_pair_rm(exhaustive_float_signed_pair_gen_var_2()), &|config| float_primitive_int_pair_rm(random_float_signed_pair_gen_var_2(config)), &|config| float_primitive_int_pair_rm(special_random_float_signed_pair_gen_var_2(config)), ) } // All `(Float, T)` where the Float is extreme and `T` is small and signed. pub fn float_signed_pair_gen_var_3() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_signed_pair_gen_var_3, &random_float_signed_pair_gen_var_3, &special_random_float_signed_pair_gen_var_3, ) } // All `(Float, T)` where the Float is extreme and `T` is signed. pub fn float_signed_pair_gen_var_4() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_signed_pair_gen_var_4, &random_float_signed_pair_gen_var_4, &special_random_float_signed_pair_gen_var_4, ) } // -- (Float, PrimitiveSigned, PrimitiveSigned) -- pub fn float_signed_signed_triple_gen() -> Generator<(Float, T, T)> { Generator::new( &exhaustive_float_signed_signed_triple_gen, &random_float_primitive_int_primitive_int_triple_gen, &special_random_float_signed_signed_triple_gen, ) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned) -- // All `(Float, T, U)` where `T` is signed, `U` is unsigned, and the `U` is positive. pub fn float_signed_unsigned_triple_gen_var_1() -> Generator<(Float, T, U)> { Generator::new( &exhaustive_float_signed_unsigned_triple_gen_var_1, &random_float_signed_unsigned_triple_gen_var_1, &special_random_float_signed_unsigned_triple_gen_var_1, ) } pub fn float_signed_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Float, T, U), (Float, T, U))> { Generator::new( &|| float_t_u_triple_rm(exhaustive_float_signed_unsigned_triple_gen_var_1()), &|config| float_t_u_triple_rm(random_float_signed_unsigned_triple_gen_var_1(config)), &|config| { float_t_u_triple_rm(special_random_float_signed_unsigned_triple_gen_var_1( config, )) }, ) } // All `(Float, T, U)` where the `Float` is extreme, `T` is signed, `U` is unsigned, and the `U` is // positive. pub fn float_signed_unsigned_triple_gen_var_2() -> Generator<(Float, T, U)> { Generator::new( &exhaustive_float_signed_unsigned_triple_gen_var_2, &random_float_signed_unsigned_triple_gen_var_2, &special_random_float_signed_unsigned_triple_gen_var_2, ) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- // All `(Float, T, u64, RoundingMode)` where `T` is signed and the quadruple is a valid input to // `Float::shl_prec_round`. pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_1() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_1, &random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1, &special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1, ) } pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( (rug::Float, T, u64, rug::float::Round), (Float, T, u64, RoundingMode), )> { Generator::new( &|| { float_t_u_rounding_mode_quadruple_rm( exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_1(), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, ) } // All `(Float, T, u64, RoundingMode)` where `T` is signed, the `Float` is extreme, and the // quadruple is a valid input to `Float::shl_prec_round`. pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_2() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_2, &random_float_signed_unsigned_rounding_mode_quadruple_gen_var_2, &special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_2, ) } // All `(Float, T, u64, RoundingMode)` where `T` is signed and the quadruple is a valid input to // `Float::shr_prec_round`. pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_3() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_3, &random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3, &special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3, ) } pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( (rug::Float, T, u64, rug::float::Round), (Float, T, u64, RoundingMode), )> { Generator::new( &|| { float_t_u_rounding_mode_quadruple_rm( exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_3(), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, ) } // All `(Float, T, u64, RoundingMode)` where `T` is signed, the `Float` is extreme, and the // quadruple is a valid input to `Float::shr_prec_round`. pub fn float_signed_unsigned_rounding_mode_quadruple_gen_var_4() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_signed_unsigned_rounding_mode_quadruple_gen_var_4, &random_float_signed_unsigned_rounding_mode_quadruple_gen_var_4, &special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_4, ) } // -- (Float, PrimitiveSigned, RoundingMode) -- // All `(Float, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Float::shl_round`. pub fn float_signed_rounding_mode_triple_gen_var_1() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_1, &random_float_signed_rounding_mode_triple_gen_var_1, &special_random_float_signed_rounding_mode_triple_gen_var_1, ) } // All `(Float, T, RoundingMode)` where `T` is signed, the `Float` is extreme, and the triple is a // valid input to `Float::shl_round`. pub fn float_signed_rounding_mode_triple_gen_var_2() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_2, &random_float_signed_rounding_mode_triple_gen_var_2, &special_random_float_signed_rounding_mode_triple_gen_var_2, ) } // All `(Float, T, RoundingMode)` where `T` is signed, the triple is a valid input to // `Float::shl_round`, and the `RoundingMode` is not `Exact`. pub fn float_signed_rounding_mode_triple_gen_var_3() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_3, &random_float_signed_rounding_mode_triple_gen_var_3, &special_random_float_signed_rounding_mode_triple_gen_var_3, ) } pub fn float_signed_rounding_mode_triple_gen_var_3_rm() -> Generator<( (rug::Float, i32, rug::float::Round), (Float, i32, RoundingMode), )> { Generator::new( &|| { let ts = exhaustive_float_signed_rounding_mode_triple_gen_var_3(); float_t_rounding_mode_triple_rm(ts) }, &|config| { float_t_rounding_mode_triple_rm(random_float_signed_rounding_mode_triple_gen_var_3( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_signed_rounding_mode_triple_gen_var_3(config), ) }, ) } // All `(Float, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Float::shr_round`. pub fn float_signed_rounding_mode_triple_gen_var_4() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_4, &random_float_signed_rounding_mode_triple_gen_var_4, &special_random_float_signed_rounding_mode_triple_gen_var_4, ) } // All `(Float, T, RoundingMode)` where `T` is signed, the `Float` is extreme, and the triple is a // valid input to `Float::shr_round`. pub fn float_signed_rounding_mode_triple_gen_var_5() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_5, &random_float_signed_rounding_mode_triple_gen_var_5, &special_random_float_signed_rounding_mode_triple_gen_var_5, ) } // All `(Float, T, RoundingMode)` where `T` is signed, the triple is a valid input to // `Float::shr_round`, and the `RoundingMode` is not `Exact`. pub fn float_signed_rounding_mode_triple_gen_var_6() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_signed_rounding_mode_triple_gen_var_6, &random_float_signed_rounding_mode_triple_gen_var_6, &special_random_float_signed_rounding_mode_triple_gen_var_6, ) } pub fn float_signed_rounding_mode_triple_gen_var_6_rm() -> Generator<( (rug::Float, i32, rug::float::Round), (Float, i32, RoundingMode), )> { Generator::new( &|| { let ts = exhaustive_float_signed_rounding_mode_triple_gen_var_6(); float_t_rounding_mode_triple_rm(ts) }, &|config| { float_t_rounding_mode_triple_rm(random_float_signed_rounding_mode_triple_gen_var_6( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_signed_rounding_mode_triple_gen_var_6(config), ) }, ) } // -- (Float, PrimitiveUnsigned) -- pub fn float_unsigned_pair_gen() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen, &random_float_unsigned_pair_gen, &special_random_float_unsigned_pair_gen, ) } type GT = Generator<((rug::Float, T), (Float, T))>; pub fn float_unsigned_pair_gen_rm() -> GT { Generator::new( &|| float_primitive_int_pair_rm(exhaustive_float_unsigned_pair_gen()), &|config| float_primitive_int_pair_rm(random_float_unsigned_pair_gen(config)), &|config| float_primitive_int_pair_rm(special_random_float_unsigned_pair_gen(config)), ) } // All `(Float, T)` where `T` is unsigned, small, and positive. pub fn float_unsigned_pair_gen_var_1() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_1, &random_float_unsigned_pair_gen_var_1, &special_random_float_unsigned_pair_gen_var_1, ) } pub fn float_unsigned_pair_gen_var_1_rm() -> Generator<((rug::Float, T), (Float, T))> { Generator::new( &|| float_primitive_int_pair_rm(exhaustive_float_unsigned_pair_gen_var_1()), &|config| float_primitive_int_pair_rm(random_float_unsigned_pair_gen_var_1(config)), &|config| float_primitive_int_pair_rm(special_random_float_unsigned_pair_gen_var_1(config)), ) } // All `(Float, T)` where `T` is small and unsigned. pub fn float_unsigned_pair_gen_var_2() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_2, &random_float_unsigned_pair_gen_var_2, &special_random_float_unsigned_pair_gen_var_2, ) } pub fn float_unsigned_pair_gen_var_2_rm() -> Generator<((rug::Float, T), (Float, T))> { Generator::new( &|| float_primitive_int_pair_rm(exhaustive_float_unsigned_pair_gen_var_2()), &|config| float_primitive_int_pair_rm(random_float_unsigned_pair_gen_var_2(config)), &|config| float_primitive_int_pair_rm(special_random_float_unsigned_pair_gen_var_2(config)), ) } // All `(Float, T)` where the Float is extreme and `T` is small and unsigned. pub fn float_unsigned_pair_gen_var_3() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_3, &random_float_unsigned_pair_gen_var_3, &special_random_float_unsigned_pair_gen_var_3, ) } // All `(Float, T)` where the `Float` is extreme and the `T` is unsigned, small, and positive. pub fn float_unsigned_pair_gen_var_4() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_4, &random_float_unsigned_pair_gen_var_4, &special_random_float_unsigned_pair_gen_var_4, ) } // All `(Float, T)` where the Float is extreme and `T` is unsigned. pub fn float_unsigned_pair_gen_var_5() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_5, &random_float_unsigned_pair_gen_var_5, &special_random_float_unsigned_pair_gen_var_5, ) } // All `(Float, T)` where the `Float` is positive and the `T` is unsigned, small, and positive. pub fn float_unsigned_pair_gen_var_6() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_6, &random_float_unsigned_pair_gen_var_6, &special_random_float_unsigned_pair_gen_var_6, ) } // All `(Float, T)` where the `Float` is finite and the `T` is unsigned, small, and positive. pub fn float_unsigned_pair_gen_var_7() -> Generator<(Float, T)> { Generator::new( &exhaustive_float_unsigned_pair_gen_var_7, &random_float_unsigned_pair_gen_var_7, &special_random_float_unsigned_pair_gen_var_7, ) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn float_unsigned_unsigned_triple_gen() -> Generator<(Float, T, T)> { Generator::new( &exhaustive_float_unsigned_unsigned_triple_gen, &random_float_primitive_int_primitive_int_triple_gen, &special_random_float_unsigned_unsigned_triple_gen, ) } // All `(Float, T, U)` where `T` and `U` are unsigned and the `U` is positive and small. pub fn float_unsigned_unsigned_triple_gen_var_1() -> Generator<(Float, T, U)> { Generator::new( &exhaustive_float_unsigned_unsigned_triple_gen_var_1, &random_float_unsigned_unsigned_triple_gen_var_1, &special_random_float_unsigned_unsigned_triple_gen_var_1, ) } pub fn float_unsigned_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Float, T, u64), (Float, T, u64))> { Generator::new( &|| float_t_u_triple_rm(exhaustive_float_unsigned_unsigned_triple_gen_var_1()), &|config| float_t_u_triple_rm(random_float_unsigned_unsigned_triple_gen_var_1(config)), &|config| { float_t_u_triple_rm(special_random_float_unsigned_unsigned_triple_gen_var_1( config, )) }, ) } // All `(Float, T, U)` where the `Float` is extreme, the `T` and `U` are unsigned, and the `U` is // positive and small. pub fn float_unsigned_unsigned_triple_gen_var_2() -> Generator<(Float, T, U)> { Generator::new( &exhaustive_float_unsigned_unsigned_triple_gen_var_2, &random_float_unsigned_unsigned_triple_gen_var_2, &special_random_float_unsigned_unsigned_triple_gen_var_2, ) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // All `(Float, T, u64, RoundingMode)` where `T` is unsigned and the quadruple is a valid input to // `Float::shl_prec_round`. pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1, &random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1, &special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1, ) } pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( (rug::Float, T, u64, rug::float::Round), (Float, T, u64, RoundingMode), )> { Generator::new( &|| { float_t_u_rounding_mode_quadruple_rm( exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1(), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, ) } // All `(Float, T, u64, RoundingMode)` where `T` is unsigned, the `Float` is extreme, and the // quadruple is a valid input to `Float::shl_prec_round`. pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2, &random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2, &special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2, ) } // All `(Float, T, u64, RoundingMode)` where `T` is unsigned and the quadruple is a valid input to // `Float::shr_prec_round`. pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3, &random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3, &special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3, ) } pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( (rug::Float, T, u64, rug::float::Round), (Float, T, u64, RoundingMode), )> { Generator::new( &|| { float_t_u_rounding_mode_quadruple_rm( exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3(), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, &|config| { float_t_u_rounding_mode_quadruple_rm( special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, ) } // All `(Float, T, u64, RoundingMode)` where `T` is unsigned, the `Float` is extreme, and the // quadruple is a valid input to `Float::shr_prec_round`. pub fn float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4() -> Generator<(Float, T, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4, &random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4, &special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4, ) } // -- (Float, PrimitiveUnsigned, RoundingMode) -- // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.set_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_1, &random_float_unsigned_rounding_mode_triple_gen_var_1, &special_random_float_unsigned_rounding_mode_triple_gen_var_1, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_1_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_1(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_1( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_1(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.square_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_2, &random_float_unsigned_rounding_mode_triple_gen_var_2, &special_random_float_unsigned_rounding_mode_triple_gen_var_2, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_2_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_2(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_2( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_2(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.reciprocal_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_3, &random_float_unsigned_rounding_mode_triple_gen_var_3, &special_random_float_unsigned_rounding_mode_triple_gen_var_3, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_3_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_3(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_3( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_3(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.set_prec_round`, and the // `Float`s are extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_4() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_4, &random_float_unsigned_rounding_mode_triple_gen_var_4, &special_random_float_unsigned_rounding_mode_triple_gen_var_4, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `Float::shl_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_5() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_5, &random_float_unsigned_rounding_mode_triple_gen_var_5, &special_random_float_unsigned_rounding_mode_triple_gen_var_5, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned, the `Float` is extreme, and the triple is a // valid input to `Float::shl_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_6() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_6, &random_float_unsigned_rounding_mode_triple_gen_var_6, &special_random_float_unsigned_rounding_mode_triple_gen_var_6, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned, the triple is a valid input to // `Float::shl_round`, and the `RoundingMode` is not `Exact`. pub fn float_unsigned_rounding_mode_triple_gen_var_7() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_7, &random_float_unsigned_rounding_mode_triple_gen_var_7, &special_random_float_unsigned_rounding_mode_triple_gen_var_7, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_7_rm() -> Generator<( (rug::Float, u32, rug::float::Round), (Float, u32, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_7(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_7( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_7(config), ) }, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `Float::shr_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_8() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_8, &random_float_unsigned_rounding_mode_triple_gen_var_8, &special_random_float_unsigned_rounding_mode_triple_gen_var_8, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned, the `Float` is extreme, and the triple is a // valid input to `Float::shr_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_9() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_9, &random_float_unsigned_rounding_mode_triple_gen_var_9, &special_random_float_unsigned_rounding_mode_triple_gen_var_9, ) } // All `(Float, T, RoundingMode)` where `T` is unsigned, the triple is a valid input to // `Float::shr_round`, and the `RoundingMode` is not `Exact`. pub fn float_unsigned_rounding_mode_triple_gen_var_10() -> Generator<(Float, T, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_10, &random_float_unsigned_rounding_mode_triple_gen_var_10, &special_random_float_unsigned_rounding_mode_triple_gen_var_10, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_10_rm() -> Generator<( (rug::Float, u32, rug::float::Round), (Float, u32, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_10(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_10( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_10(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.square_prec_round`, where the // `Float` is extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_11() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_11, &random_float_unsigned_rounding_mode_triple_gen_var_11, &special_random_float_unsigned_rounding_mode_triple_gen_var_11, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.reciprocal_prec_round`, where // the `Float` is extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_12() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_12, &random_float_unsigned_rounding_mode_triple_gen_var_12, &special_random_float_unsigned_rounding_mode_triple_gen_var_12, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.sqrt_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_13() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_13, &random_float_unsigned_rounding_mode_triple_gen_var_13, &special_random_float_unsigned_rounding_mode_triple_gen_var_13, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_13_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_13(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_13( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_13(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.sqrt_prec_round`, where the // `Float` is extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_14() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_14, &random_float_unsigned_rounding_mode_triple_gen_var_14, &special_random_float_unsigned_rounding_mode_triple_gen_var_14, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.reciprocal_sqrt_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_15() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_15, &random_float_unsigned_rounding_mode_triple_gen_var_15, &special_random_float_unsigned_rounding_mode_triple_gen_var_15, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_15_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_15(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_15( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_15(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.reciprocal_sqrt_prec_round`, // where the `Float` is extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_16() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_16, &random_float_unsigned_rounding_mode_triple_gen_var_16, &special_random_float_unsigned_rounding_mode_triple_gen_var_16, ) } // All `(Float, u64, RoundingMode)` where the `u64` is positive and the `Float` is positive. pub fn float_unsigned_rounding_mode_triple_gen_var_17() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_17, &random_float_unsigned_rounding_mode_triple_gen_var_17, &special_random_float_unsigned_rounding_mode_triple_gen_var_17, ) } // All `(Float, u64, RoundingMode)` where the `u64` is positive and the `Float` is finite. pub fn float_unsigned_rounding_mode_triple_gen_var_18() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_18, &random_float_unsigned_rounding_mode_triple_gen_var_18, &special_random_float_unsigned_rounding_mode_triple_gen_var_18, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.ln_prec_round`. pub fn float_unsigned_rounding_mode_triple_gen_var_19() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_19, &random_float_unsigned_rounding_mode_triple_gen_var_19, &special_random_float_unsigned_rounding_mode_triple_gen_var_19, ) } pub fn float_unsigned_rounding_mode_triple_gen_var_19_rm() -> Generator<( (rug::Float, u64, rug::float::Round), (Float, u64, RoundingMode), )> { Generator::new( &|| { float_t_rounding_mode_triple_rm( exhaustive_float_unsigned_rounding_mode_triple_gen_var_19(), ) }, &|config| { float_t_rounding_mode_triple_rm(random_float_unsigned_rounding_mode_triple_gen_var_19( config, )) }, &|config| { float_t_rounding_mode_triple_rm( special_random_float_unsigned_rounding_mode_triple_gen_var_19(config), ) }, ) } // All `(Float, u64, RoundingMode)` that are valid inputs to `Float.ln_prec_round`, where the // `Float` is extreme. pub fn float_unsigned_rounding_mode_triple_gen_var_20() -> Generator<(Float, u64, RoundingMode)> { Generator::new( &exhaustive_float_unsigned_rounding_mode_triple_gen_var_20, &random_float_unsigned_rounding_mode_triple_gen_var_20, &special_random_float_unsigned_rounding_mode_triple_gen_var_20, ) } // -- (Float, Rational) -- pub fn float_rational_pair_gen() -> Generator<(Float, Rational)> { Generator::new( &exhaustive_float_rational_pair_gen, &random_float_rational_pair_gen, &special_random_float_rational_pair_gen, ) } pub fn float_rational_pair_gen_rm() -> Generator<((rug::Float, rug::Rational), (Float, Rational))> { Generator::new( &|| float_rational_pair_rm(exhaustive_float_rational_pair_gen()), &|config| float_rational_pair_rm(random_float_rational_pair_gen(config)), &|config| float_rational_pair_rm(special_random_float_rational_pair_gen(config)), ) } // All pairs of finite Floats and Rationals. pub fn float_rational_pair_gen_var_1() -> Generator<(Float, Rational)> { Generator::new( &exhaustive_float_rational_pair_gen_var_1, &random_float_rational_pair_gen_var_1, &special_random_float_rational_pair_gen_var_1, ) } // All pairs of Floats and Rationals where the Float is extreme. pub fn float_rational_pair_gen_var_2() -> Generator<(Float, Rational)> { Generator::new( &exhaustive_float_rational_pair_gen_var_2, &random_float_rational_pair_gen_var_2, &special_random_float_rational_pair_gen_var_2, ) } // -- (Float, Rational, PrimitiveUnsigned) -- // All `(Float, Rational, T)` where `T` is unsigned, small, and positive. pub fn float_rational_unsigned_triple_gen_var_1() -> Generator<(Float, Rational, T)> { Generator::new( &exhaustive_float_rational_unsigned_triple_gen_var_1, &random_float_rational_unsigned_triple_gen_var_1, &special_random_float_rational_unsigned_triple_gen_var_1, ) } pub fn float_rational_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Float, rug::Rational, T), (Float, Rational, T))> { Generator::new( &|| { let ef = exhaustive_float_rational_unsigned_triple_gen_var_1(); float_rational_anything_triple_rm(ef) }, &|config| { float_rational_anything_triple_rm(random_float_rational_unsigned_triple_gen_var_1( config, )) }, &|config| { float_rational_anything_triple_rm( special_random_float_rational_unsigned_triple_gen_var_1(config), ) }, ) } // All `(Float, Rational, T)` where the `Float` is extreme and the `T` is unsigned, small, and // positive. pub fn float_rational_unsigned_triple_gen_var_2() -> Generator<(Float, Rational, T)> { Generator::new( &exhaustive_float_rational_unsigned_triple_gen_var_2, &random_float_rational_unsigned_triple_gen_var_2, &special_random_float_rational_unsigned_triple_gen_var_2, ) } // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::add_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_1() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_1, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1, ) } pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_1_rm() -> Generator<( (rug::Float, rug::Rational, u64, rug::float::Round), (Float, Rational, u64, RoundingMode), )> { Generator::new( &|| { float_rational_anything_rounding_mode_quadruple_rm( exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1(config), ) }, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::sub_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_2() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_2, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2, ) } pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_2_rm() -> Generator<( (rug::Float, rug::Rational, u64, rug::float::Round), (Float, Rational, u64, RoundingMode), )> { Generator::new( &|| { float_rational_anything_rounding_mode_quadruple_rm( exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(config), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2(config), ) }, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::mul_rational_prec_round`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_3() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_3, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3, ) } pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_3_rm() -> Generator<( (rug::Float, rug::Rational, u64, rug::float::Round), (Float, Rational, u64, RoundingMode), )> { Generator::new( &|| { float_rational_anything_rounding_mode_quadruple_rm( exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3(config), ) }, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::div_prec_round_rational`. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_4() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4, ) } pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_4_rm() -> Generator<( (rug::Float, rug::Rational, u64, rug::float::Round), (Float, Rational, u64, RoundingMode), )> { Generator::new( &|| { float_rational_anything_rounding_mode_quadruple_rm( exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(config), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4(config), ) }, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::rational_div_float_prec_round` (with the first two arguments reversed). pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_5() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5, ) } pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_5_rm() -> Generator<( (rug::Float, rug::Rational, u64, rug::float::Round), (Float, Rational, u64, RoundingMode), )> { Generator::new( &|| { float_rational_anything_rounding_mode_quadruple_rm( exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(config), ) }, &|config| { float_rational_anything_rounding_mode_quadruple_rm( special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5(config), ) }, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::add_rational_prec_round`, where the `Float` is extreme. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_6() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_6, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_6, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_6, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::sub_rational_prec_round`, where the `Float` is extreme. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_7() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_7, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_7, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_7, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::mul_rational_prec_round`, where the `Float` is extreme. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_8() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_8, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_8, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_8, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::div_rational_prec_round`, where the `Float` is extreme. pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_9() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_9, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_9, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_9, ) } // All `(Float, Rational, u64, RoundingMode)` that are valid inputs to // `Float::rational_div_float_prec_round`, where the `Float` is extreme (with the first two // arguments reversed). pub fn float_rational_unsigned_rounding_mode_quadruple_gen_var_10() -> Generator<(Float, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_float_rational_unsigned_rounding_mode_quadruple_gen_var_10, &random_float_rational_unsigned_rounding_mode_quadruple_gen_var_10, &special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_10, ) } // -- (Float, Rational, Rational) -- pub fn float_rational_rational_triple_gen() -> Generator<(Float, Rational, Rational)> { Generator::new( &exhaustive_float_rational_rational_triple_gen, &random_float_rational_rational_triple_gen, &special_random_float_rational_rational_triple_gen, ) } // -- (Float, Rational, RoundingMode) -- // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::add_round_rational`. pub fn float_rational_rounding_mode_triple_gen_var_1() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_1, &random_float_rational_rounding_mode_triple_gen_var_1, &special_random_float_rational_rounding_mode_triple_gen_var_1, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::sub_round_rational`. pub fn float_rational_rounding_mode_triple_gen_var_2() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_2, &random_float_rational_rounding_mode_triple_gen_var_2, &special_random_float_rational_rounding_mode_triple_gen_var_2, ) } // All `(Float, Rational, RoundingMode)`, excluding those with `Exact`. pub fn float_rational_rounding_mode_triple_gen_var_3_rm() -> Generator<( (rug::Float, rug::Rational, rug::float::Round), (Float, Rational, RoundingMode), )> { Generator::new( &|| { float_rational_rounding_mode_triple_rm( exhaustive_float_rational_rounding_mode_triple_gen_var_3(), ) }, &|config| { float_rational_rounding_mode_triple_rm( random_float_rational_rounding_mode_triple_gen_var_3(config), ) }, &|config| { float_rational_rounding_mode_triple_rm( special_random_float_rational_rounding_mode_triple_gen_var_3(config), ) }, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::mul_round_rational`. pub fn float_rational_rounding_mode_triple_gen_var_4() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_4, &random_float_rational_rounding_mode_triple_gen_var_4, &special_random_float_rational_rounding_mode_triple_gen_var_4, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::div_round_rational`. pub fn float_rational_rounding_mode_triple_gen_var_5() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_5, &random_float_rational_rounding_mode_triple_gen_var_5, &special_random_float_rational_rounding_mode_triple_gen_var_5, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::rational_div_float_round` // (with the first two arguments reversed). pub fn float_rational_rounding_mode_triple_gen_var_6() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_6, &random_float_rational_rounding_mode_triple_gen_var_6, &special_random_float_rational_rounding_mode_triple_gen_var_6, ) } pub fn float_rational_rounding_mode_triple_gen_var_6_rm() -> Generator<( (rug::Float, rug::Rational, rug::float::Round), (Float, Rational, RoundingMode), )> { Generator::new( &|| { float_rational_rounding_mode_triple_rm( exhaustive_float_rational_rounding_mode_triple_gen_var_6(), ) }, &|config| { float_rational_rounding_mode_triple_rm( random_float_rational_rounding_mode_triple_gen_var_6(config), ) }, &|config| { float_rational_rounding_mode_triple_rm( special_random_float_rational_rounding_mode_triple_gen_var_6(config), ) }, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::add_round_rational`, where // the `Float` is extreme. pub fn float_rational_rounding_mode_triple_gen_var_7() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_7, &random_float_rational_rounding_mode_triple_gen_var_7, &special_random_float_rational_rounding_mode_triple_gen_var_7, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::sub_round_rational`, where // the `Float` is extreme. pub fn float_rational_rounding_mode_triple_gen_var_8() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_8, &random_float_rational_rounding_mode_triple_gen_var_8, &special_random_float_rational_rounding_mode_triple_gen_var_8, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::mul_round_rational`, where // the `Float` is extreme. pub fn float_rational_rounding_mode_triple_gen_var_9() -> Generator<(Float, Rational, RoundingMode)> { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_9, &random_float_rational_rounding_mode_triple_gen_var_9, &special_random_float_rational_rounding_mode_triple_gen_var_9, ) } type FRR = Generator<(Float, Rational, RoundingMode)>; // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::div_round_rational`, where // the `Float` is extreme. pub fn float_rational_rounding_mode_triple_gen_var_10() -> FRR { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_10, &random_float_rational_rounding_mode_triple_gen_var_10, &special_random_float_rational_rounding_mode_triple_gen_var_10, ) } // All `(Float, Rational, RoundingMode)` that are valid inputs to `Float::rational_div_float_round`, // where the `Float` is extreme (with the first two arguments reversed). pub fn float_rational_rounding_mode_triple_gen_var_11() -> FRR { Generator::new( &exhaustive_float_rational_rounding_mode_triple_gen_var_11, &random_float_rational_rounding_mode_triple_gen_var_11, &special_random_float_rational_rounding_mode_triple_gen_var_11, ) } // -- (Float, RoundingMode) -- pub fn float_rounding_mode_pair_gen() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen, &random_float_rounding_mode_pair_gen, &special_random_float_rounding_mode_pair_gen, ) } // All `(Float, RoundingMode)` that are valid inputs to `Natural::rounding_from`. pub fn float_rounding_mode_pair_gen_var_1() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_1, &random_float_rounding_mode_pair_gen_var_1, &special_random_float_rounding_mode_pair_gen_var_1, ) } // All `(Float, RoundingMode)` that are valid inputs to `Integer::rounding_from`. pub fn float_rounding_mode_pair_gen_var_2() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_2, &random_float_rounding_mode_pair_gen_var_2, &special_random_float_rounding_mode_pair_gen_var_2, ) } // All `(Float, RoundingMode)` where the float is finite and nonzero. pub fn float_rounding_mode_pair_gen_var_3() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_3, &random_float_rounding_mode_pair_gen_var_3, &special_random_float_rounding_mode_pair_gen_var_3, ) } // All `(Float, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is unsigned. type GT2 = Generator<(Float, RoundingMode)>; #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_4() -> GT2 where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_4::, &random_float_rounding_mode_pair_gen_var_4::, &special_random_float_rounding_mode_pair_gen_var_4::, ) } // All `(Float, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is signed. #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_5() -> Generator<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_5::, &random_float_rounding_mode_pair_gen_var_5::, &special_random_float_rounding_mode_pair_gen_var_5::, ) } // All `(T, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is a primitive // float. #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_6() -> Generator<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_6::, &random_float_rounding_mode_pair_gen_var_6::, &special_random_float_rounding_mode_pair_gen_var_6::, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`. pub fn float_rounding_mode_pair_gen_var_7() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_7, &random_float_rounding_mode_pair_gen_var_7, &special_random_float_rounding_mode_pair_gen_var_7, ) } pub fn float_rounding_mode_pair_gen_var_7_rm() -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Generator::new( &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_7()), &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_7(config)), &|config| { float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_7(config)) }, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` has a // precision less than `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_8() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_8, &random_float_rounding_mode_pair_gen_var_8, &special_random_float_rounding_mode_pair_gen_var_8, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` has // precision `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_9() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_9, &random_float_rounding_mode_pair_gen_var_9, &special_random_float_rounding_mode_pair_gen_var_9, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` has a // precision greater than `Limb::WIDTH` and less than `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_10() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_10, &random_float_rounding_mode_pair_gen_var_10, &special_random_float_rounding_mode_pair_gen_var_10, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` has // precision `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_11() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_11, &random_float_rounding_mode_pair_gen_var_11, &special_random_float_rounding_mode_pair_gen_var_11, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` has a // precision greater than `Limb::WIDTH` * 2 and less than `Limb::WIDTH` * 3. pub fn float_rounding_mode_pair_gen_var_12() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_12, &random_float_rounding_mode_pair_gen_var_12, &special_random_float_rounding_mode_pair_gen_var_12, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`. pub fn float_rounding_mode_pair_gen_var_13() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_13, &random_float_rounding_mode_pair_gen_var_13, &special_random_float_rounding_mode_pair_gen_var_13, ) } pub fn float_rounding_mode_pair_gen_var_13_rm() -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Generator::new( &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_13()), &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_13(config)), &|config| { float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_13(config)) }, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a // precision less than `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_14() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_14, &random_float_rounding_mode_pair_gen_var_14, &special_random_float_rounding_mode_pair_gen_var_14, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has // precision `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_15() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_15, &random_float_rounding_mode_pair_gen_var_15, &special_random_float_rounding_mode_pair_gen_var_15, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a // precision greater than `Limb::WIDTH` and less than `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_16() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_16, &random_float_rounding_mode_pair_gen_var_16, &special_random_float_rounding_mode_pair_gen_var_16, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` has a // precision greater than `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_17() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_17, &random_float_rounding_mode_pair_gen_var_17, &special_random_float_rounding_mode_pair_gen_var_17, ) } // All `(Float, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is unsigned // and the `Float` is extreme. #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_18() -> GT2 where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_18::, &random_float_rounding_mode_pair_gen_var_18::, &special_random_float_rounding_mode_pair_gen_var_18::, ) } // All `(Float, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is signed and // the `Float` is extreme. #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_19() -> Generator<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_19::, &random_float_rounding_mode_pair_gen_var_19::, &special_random_float_rounding_mode_pair_gen_var_19::, ) } // All `(T, RoundingMode)` that are valid inputs to `T::rounding_from`, where `T` is a primitive // float and the `Float` is extreme. #[allow(clippy::type_repetition_in_bounds)] pub fn float_rounding_mode_pair_gen_var_20() -> Generator<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_20::, &random_float_rounding_mode_pair_gen_var_20::, &special_random_float_rounding_mode_pair_gen_var_20::, ) } // All `(T, RoundingMode)` where the `Float` is extreme. pub fn float_rounding_mode_pair_gen_var_21() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_21, &random_float_rounding_mode_pair_gen_var_21, &special_random_float_rounding_mode_pair_gen_var_21, ) } // All `(Float, RoundingMode)` that are valid inputs to `square_round`, where the `Float` is // extreme. pub fn float_rounding_mode_pair_gen_var_22() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_22, &random_float_rounding_mode_pair_gen_var_22, &special_random_float_rounding_mode_pair_gen_var_22, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_round`, where the `Float` is // extreme. pub fn float_rounding_mode_pair_gen_var_23() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_23, &random_float_rounding_mode_pair_gen_var_23, &special_random_float_rounding_mode_pair_gen_var_23, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`. pub fn float_rounding_mode_pair_gen_var_24() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_24, &random_float_rounding_mode_pair_gen_var_24, &special_random_float_rounding_mode_pair_gen_var_24, ) } pub fn float_rounding_mode_pair_gen_var_24_rm() -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Generator::new( &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_24()), &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_24(config)), &|config| { float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_24(config)) }, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`, where the `Float` has a // precision less than `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_25() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_25, &random_float_rounding_mode_pair_gen_var_25, &special_random_float_rounding_mode_pair_gen_var_25, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`, where the `Float` has // precision `Limb::WIDTH`. pub fn float_rounding_mode_pair_gen_var_26() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_26, &random_float_rounding_mode_pair_gen_var_26, &special_random_float_rounding_mode_pair_gen_var_26, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`, where the `Float` has a // precision greater than `Limb::WIDTH` and less than `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_27() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_27, &random_float_rounding_mode_pair_gen_var_27, &special_random_float_rounding_mode_pair_gen_var_27, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`, where the `Float` has a // precision greater than `Limb::WIDTH` * 2. pub fn float_rounding_mode_pair_gen_var_28() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_28, &random_float_rounding_mode_pair_gen_var_28, &special_random_float_rounding_mode_pair_gen_var_28, ) } // All `(Float, RoundingMode)` that are valid inputs to `sqrt_round`, where the `Float` is extreme. pub fn float_rounding_mode_pair_gen_var_29() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_29, &random_float_rounding_mode_pair_gen_var_29, &special_random_float_rounding_mode_pair_gen_var_29, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_sqrt_round`. pub fn float_rounding_mode_pair_gen_var_30() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_30, &random_float_rounding_mode_pair_gen_var_30, &special_random_float_rounding_mode_pair_gen_var_30, ) } pub fn float_rounding_mode_pair_gen_var_30_rm() -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Generator::new( &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_30()), &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_30(config)), &|config| { float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_30(config)) }, ) } // All `(Float, RoundingMode)` that are valid inputs to `reciprocal_sqrt_round`, where the `Float` // is extreme. pub fn float_rounding_mode_pair_gen_var_31() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_31, &random_float_rounding_mode_pair_gen_var_31, &special_random_float_rounding_mode_pair_gen_var_31, ) } // All `(Float, RoundingMode)` where the `Float` is positive. pub fn float_rounding_mode_pair_gen_var_32() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_32, &random_float_rounding_mode_pair_gen_var_32, &special_random_float_rounding_mode_pair_gen_var_32, ) } // All `(Float, RoundingMode)` where the `Float` is finite. pub fn float_rounding_mode_pair_gen_var_33() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_33, &random_float_rounding_mode_pair_gen_var_33, &special_random_float_rounding_mode_pair_gen_var_33, ) } // All `(Float, RoundingMode)` that are valid inputs to `ln_round`. pub fn float_rounding_mode_pair_gen_var_34() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_34, &random_float_rounding_mode_pair_gen_var_34, &special_random_float_rounding_mode_pair_gen_var_34, ) } pub fn float_rounding_mode_pair_gen_var_34_rm() -> Generator<((rug::Float, rug::float::Round), (Float, RoundingMode))> { Generator::new( &|| float_rounding_mode_pair_rm(exhaustive_float_rounding_mode_pair_gen_var_34()), &|config| float_rounding_mode_pair_rm(random_float_rounding_mode_pair_gen_var_34(config)), &|config| { float_rounding_mode_pair_rm(special_random_float_rounding_mode_pair_gen_var_34(config)) }, ) } // All `(Float, RoundingMode)` that are valid inputs to `ln_round`, where the `Float` is extreme. pub fn float_rounding_mode_pair_gen_var_35() -> Generator<(Float, RoundingMode)> { Generator::new( &exhaustive_float_rounding_mode_pair_gen_var_35, &random_float_rounding_mode_pair_gen_var_35, &special_random_float_rounding_mode_pair_gen_var_35, ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 and 2 are in malachite-nz. // All `(Integer, u64, RoundingMode)` that are valid inputs to `Float::from_integer_prec_round`. pub fn integer_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(Integer, u64, RoundingMode)> { Generator::new( &exhaustive_integer_unsigned_rounding_mode_triple_gen_var_3, &random_integer_unsigned_rounding_mode_triple_gen_var_3, &special_random_integer_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(Integer, u64, RoundingMode)` that are valid inputs to `Float::from_integer_prec_round`, // excluding those with `Exact`. pub fn integer_unsigned_rounding_mode_triple_gen_var_4() -> Generator<(Integer, u64, RoundingMode)> { Generator::new( &exhaustive_integer_unsigned_rounding_mode_triple_gen_var_4, &random_integer_unsigned_rounding_mode_triple_gen_var_4, &special_random_integer_unsigned_rounding_mode_triple_gen_var_4, ) } // var 5 is in malachite-nz. // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. // All `(T, u64, RoundingMode)` that are valid inputs to `from_primitive_float_prec_round`. pub fn primitive_float_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(T, u64, RoundingMode)> where Float: From, { Generator::new( &exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_3, &random_primitive_float_unsigned_rounding_mode_triple_gen_var_3, &special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(T, u64, RoundingMode)` that are valid inputs to `from_primitive_float_prec_round`, except // for those including `Exact`. pub fn primitive_float_unsigned_rounding_mode_triple_gen_var_4() -> Generator<(T, u64, RoundingMode)> where Float: From, { Generator::new( &exhaustive_primitive_float_unsigned_rounding_mode_triple_gen_var_4, &random_primitive_float_unsigned_rounding_mode_triple_gen_var_4, &special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_4, ) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- // var 1 is in malachite-nz // All `(Natural, u64, RoundingMode)` that are valid inputs to `Float::from_natural_prec_round`. pub fn natural_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(Natural, u64, RoundingMode)> { Generator::new( &exhaustive_natural_unsigned_rounding_mode_triple_gen_var_2, &random_natural_unsigned_rounding_mode_triple_gen_var_2, &special_random_natural_unsigned_rounding_mode_triple_gen_var_2, ) } // All `(Natural, u64, RoundingMode)` that are valid inputs to `Float::from_natural_prec_round`, // excluding those with `Exact`. pub fn natural_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(Natural, u64, RoundingMode)> { Generator::new( &exhaustive_natural_unsigned_rounding_mode_triple_gen_var_3, &random_natural_unsigned_rounding_mode_triple_gen_var_3, &special_random_natural_unsigned_rounding_mode_triple_gen_var_3, ) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. // All `(T, u64, RoundingMode)` that are valid inputs to `Float::from_signed_prec_round`. pub fn signed_unsigned_rounding_mode_triple_gen_var_3() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_3, &random_signed_unsigned_rounding_mode_triple_gen_var_1, &special_random_signed_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(T, u64, RoundingMode)` that are valid inputs to `Float::from_signed_prec_round`, excluding // those with `Exact`. pub fn signed_unsigned_rounding_mode_triple_gen_var_4() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_4, &random_signed_unsigned_rounding_mode_triple_gen_var_2, &special_random_signed_unsigned_rounding_mode_triple_gen_var_4, ) } // All `(i64, u64, RoundingMode)` that are valid inputs to `Float::power_of_2_prec_round`, where the // `u64` is small. pub fn signed_unsigned_rounding_mode_triple_gen_var_5() -> Generator<(i64, u64, RoundingMode)> { Generator::new_no_special( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_5, &random_signed_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(i64, u64, RoundingMode)` that are valid inputs to `Float::power_of_2_prec_round`. pub fn signed_unsigned_rounding_mode_triple_gen_var_6() -> Generator<(i64, u64, RoundingMode)> { Generator::new( &exhaustive_signed_unsigned_rounding_mode_triple_gen_var_5, &random_signed_unsigned_rounding_mode_triple_gen_var_4, &special_random_signed_unsigned_rounding_mode_triple_gen_var_5, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 4 are in malachite-base. // All `(T, u64, RoundingMode)` that are valid inputs to `Float::from_unsigned_prec_round` pub fn unsigned_unsigned_rounding_mode_triple_gen_var_5() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_6, &random_unsigned_unsigned_rounding_mode_triple_gen_var_3, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_5, ) } // All `(T, u64, RoundingMode)` that are valid inputs to `Float::from_unsigned_prec_round`, // excluding those with `Exact`. pub fn unsigned_unsigned_rounding_mode_triple_gen_var_6() -> Generator<(T, u64, RoundingMode)> { Generator::new( &exhaustive_unsigned_unsigned_rounding_mode_triple_gen_var_7, &random_unsigned_unsigned_rounding_mode_triple_gen_var_4, &special_random_unsigned_unsigned_rounding_mode_triple_gen_var_6, ) } // -- (Rational, PrimitiveUnsigned, RoundingMode) -- // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::from_rational_prec_round`. type GT3 = Generator<(Rational, u64, RoundingMode)>; pub fn rational_unsigned_rounding_mode_triple_gen_var_1() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_1, &random_rational_unsigned_rounding_mode_triple_gen_var_1, &special_random_rational_unsigned_rounding_mode_triple_gen_var_2, ) } // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::from_rational_prec_round`, // excluding those with `Exact`. pub fn rational_unsigned_rounding_mode_triple_gen_var_2() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_2, &random_rational_unsigned_rounding_mode_triple_gen_var_2, &special_random_rational_unsigned_rounding_mode_triple_gen_var_3, ) } // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::sqrt_rational_prec_round`. pub fn rational_unsigned_rounding_mode_triple_gen_var_3() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_3, &random_rational_unsigned_rounding_mode_triple_gen_var_3, &special_random_rational_unsigned_rounding_mode_triple_gen_var_4, ) } // All `(Rational, u64, RoundingMode)` that are valid inputs to // `Float::reciprocal_sqrt_rational_prec_round`. pub fn rational_unsigned_rounding_mode_triple_gen_var_4() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_4, &random_rational_unsigned_rounding_mode_triple_gen_var_4, &special_random_rational_unsigned_rounding_mode_triple_gen_var_5, ) } // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::from_rational_prec_round`, // and the `Rational` is non-negative. pub fn rational_unsigned_rounding_mode_triple_gen_var_5() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_5, &random_rational_unsigned_rounding_mode_triple_gen_var_5, &special_random_rational_unsigned_rounding_mode_triple_gen_var_6, ) } // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::ln_rational_prec_round`. pub fn rational_unsigned_rounding_mode_triple_gen_var_6() -> GT3 { Generator::new( &exhaustive_rational_unsigned_rounding_mode_triple_gen_var_6, &random_rational_unsigned_rounding_mode_triple_gen_var_6, &special_random_rational_unsigned_rounding_mode_triple_gen_var_7, ) } // -- (Rational, Rational, PrimitiveUnsigned, RoundingMode) -- // All `(Rational, Rational, u64, RoundingMode)` that are valid inputs to // `Float::agm_rational_prec_round`. pub fn rational_rational_unsigned_rounding_mode_quadruple_gen_var_1() -> Generator<(Rational, Rational, u64, RoundingMode)> { Generator::new( &exhaustive_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1, &random_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1, &special_random_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1, ) } // -- (Rational, RoundingMode) -- // vars 1 through 5 are in malachite-q. // All `(Rational, u64, RoundingMode)` that are valid inputs to `Float::from_rational_prec_round`, // with precision fixed at 1. pub fn rational_rounding_mode_pair_gen_var_6() -> Generator<(Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_6, &random_rational_rounding_mode_pair_gen_var_6, &special_random_rational_rounding_mode_pair_gen_var_6, ) } pub mod common; pub mod exhaustive; pub mod random; pub mod special_random; ================================================ FILE: malachite-float/src/test_util/generators/random.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use crate::random::{ RandomPositiveFiniteFloats, random_finite_floats, random_floats, random_non_negative_finite_floats, random_nonzero_finite_floats, random_positive_finite_floats, random_positive_floats_with_precision, }; use crate::test_util::extra_variadic::{ random_quadruples, random_quadruples_xxyz, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::exhaustive::{ add_prec_round_valid, add_rational_prec_round_valid, add_rational_round_valid, add_round_valid, agm_prec_round_valid, agm_rational_prec_round_valid, agm_round_valid, div_prec_round_valid, div_rational_prec_round_valid, div_rational_round_valid, div_round_valid, from_primitive_float_prec_round_valid, integer_rounding_from_float_valid, ln_prec_round_valid, ln_rational_prec_round_valid, ln_round_valid, mul_prec_round_valid, mul_rational_prec_round_valid, mul_rational_round_valid, mul_round_valid, natural_rounding_from_float_valid, rational_div_float_prec_round_valid, rational_div_float_round_valid, reciprocal_prec_round_valid, reciprocal_round_valid, reciprocal_sqrt_prec_round_valid, reciprocal_sqrt_rational_prec_round_valid, reciprocal_sqrt_round_valid, set_prec_round_valid, shl_prec_round_valid, shl_round_valid, shr_prec_round_valid, shr_round_valid, signed_rounding_from_float_valid, sqrt_prec_round_valid, sqrt_rational_prec_round_valid, sqrt_round_valid, square_prec_round_valid, square_round_valid, sub_prec_round_valid, sub_rational_prec_round_valid, sub_rational_round_valid, sub_round_valid, unsigned_rounding_from_float_valid, }; use malachite_base::bools::random::{ RandomBools, WeightedRandomBools, random_bools, weighted_random_bools, }; use malachite_base::iterators::{WithSpecialValues, with_special_values}; use malachite_base::num::arithmetic::traits::{IsPowerOf2, NegModPowerOf2}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_natural_signeds, geometric_random_positive_unsigneds, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use malachite_base::num::random::{ RandomUnsignedInclusiveRange, random_primitive_ints, random_unsigned_inclusive_range, special_random_primitive_floats, }; use malachite_base::orderings::random::random_orderings; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{GenConfig, It, reshape_2_1_to_3}; use malachite_base::tuples::random::{random_pairs, random_pairs_from_single}; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ RandomNaturals, UniformRandomNaturalRange, random_naturals, random_positive_naturals, }; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::random::{random_non_negative_rationals, random_rationals}; use std::cmp::Ordering; use std::collections::HashMap; // -- Float -- pub fn random_float_gen(config: &GenConfig) -> It { Box::new(random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn random_float_gen_var_1(config: &GenConfig) -> It { Box::new(random_positive_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn random_float_gen_var_2(config: &GenConfig) -> It { Box::new( random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|f| !f.is_nan()), ) } pub fn random_float_gen_var_3(config: &GenConfig) -> It { Box::new(random_nonzero_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn random_float_gen_var_4(config: &GenConfig) -> It { Box::new(random_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn random_float_gen_var_5(config: &GenConfig) -> It { Box::new(random_non_negative_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn random_float_gen_var_6(config: &GenConfig) -> It { random_floats_with_precision_inclusive_range(EXAMPLE_SEED, config, 1, Limb::WIDTH - 1) } pub fn random_float_gen_var_7(config: &GenConfig) -> It { Box::new(random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, )) } pub fn random_float_gen_var_8(config: &GenConfig) -> It { random_floats_with_precision_inclusive_range( EXAMPLE_SEED, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) } pub fn random_float_gen_var_9(config: &GenConfig) -> It { Box::new(random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, )) } pub fn random_float_gen_var_10(config: &GenConfig) -> It { random_floats_with_precision_inclusive_range( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) } pub fn random_float_gen_var_11(config: &GenConfig) -> It { random_floats_with_precision_inclusive_range_to_infinity( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, ) } #[derive(Clone, Debug)] pub(crate) struct RandomExtremePositiveFiniteFloats> { pub(crate) exponents: GeometricRandomNaturalValues, pub(crate) exponent_modes: RandomBools, pub(crate) xs: I, } impl> Iterator for RandomExtremePositiveFiniteFloats { type Item = Float; fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); let precision = x.significant_bits(); assert_ne!(precision, 0); let exponent_offset = self.exponents.next().unwrap(); let exp = if self.exponent_modes.next().unwrap() { Float::MAX_EXPONENT - exponent_offset } else { Float::MIN_EXPONENT + exponent_offset }; Some(Float(Finite { sign: true, exponent: exp, precision, significand: x << precision.neg_mod_power_of_2(Limb::LOG_WIDTH), })) } } fn random_extreme_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomExtremePositiveFiniteFloats>> { RandomExtremePositiveFiniteFloats { exponents: geometric_random_natural_signeds( seed.fork("exponents"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), exponent_modes: random_bools(seed.fork("exponent_modes")), xs: random_positive_naturals( seed.fork("significands"), mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct RandomExtremeNonNegativeFiniteFloats> { pub(crate) bs: WeightedRandomBools, pub(crate) xs: RandomExtremePositiveFiniteFloats, } impl> Iterator for RandomExtremeNonNegativeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { if self.bs.next().unwrap() { Some(Float::ZERO) } else { self.xs.next() } } } #[inline] fn random_extreme_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomExtremeNonNegativeFiniteFloats>> { RandomExtremeNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: random_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct RandomExtremeNonzeroFiniteFloats> { pub(crate) bs: RandomBools, pub(crate) xs: RandomExtremePositiveFiniteFloats, } impl> Iterator for RandomExtremeNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } #[inline] fn random_extreme_nonzero_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomExtremeNonzeroFiniteFloats>> { RandomExtremeNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct RandomExtremeFiniteFloats> { pub(crate) bs: RandomBools, pub(crate) xs: RandomExtremeNonNegativeFiniteFloats, } impl> Iterator for RandomExtremeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } #[inline] fn random_extreme_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomExtremeFiniteFloats>> { RandomExtremeFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_extreme_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } #[inline] fn random_extreme_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues>>> { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { random_extreme_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } pub fn random_float_gen_var_12(config: &GenConfig) -> It { Box::new(random_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn random_float_gen_var_13(config: &GenConfig) -> It { Box::new(random_extreme_nonzero_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn random_float_gen_var_14(config: &GenConfig) -> It { Box::new( random_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|f| !f.is_nan()), ) } pub fn random_float_gen_var_15(config: &GenConfig) -> It { Box::new( random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32), ) } #[derive(Clone, Debug)] pub(crate) struct RandomMixedExtremePositiveFiniteFloats> { pub(crate) exponents: GeometricRandomNaturalValues, pub(crate) exponent_modes: RandomUnsignedInclusiveRange, pub(crate) xs: I, } impl> Iterator for RandomMixedExtremePositiveFiniteFloats { type Item = Float; fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); let precision = x.significant_bits(); assert_ne!(precision, 0); let exponent_offset = self.exponents.next().unwrap(); let exp = match self.exponent_modes.next().unwrap() { 0 => exponent_offset, 1 => -exponent_offset, 2 => Float::MAX_EXPONENT - exponent_offset, 3 => Float::MIN_EXPONENT + exponent_offset, _ => unreachable!(), }; Some(Float(Finite { sign: true, exponent: exp, precision, significand: x << precision.neg_mod_power_of_2(Limb::LOG_WIDTH), })) } } fn random_mixed_extreme_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomMixedExtremePositiveFiniteFloats>> { RandomMixedExtremePositiveFiniteFloats { exponents: geometric_random_natural_signeds( seed.fork("exponents"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), exponent_modes: random_unsigned_inclusive_range(seed.fork("exponent_modes"), 0, 3), xs: random_positive_naturals( seed.fork("significands"), mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct RandomMixedExtremeNonNegativeFiniteFloats> { pub(crate) bs: WeightedRandomBools, pub(crate) xs: RandomMixedExtremePositiveFiniteFloats, } impl> Iterator for RandomMixedExtremeNonNegativeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { if self.bs.next().unwrap() { Some(Float::ZERO) } else { self.xs.next() } } } #[inline] fn random_mixed_extreme_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomMixedExtremeNonNegativeFiniteFloats>> { RandomMixedExtremeNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: random_mixed_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct _RandomMixedExtremeNonzeroFiniteFloats> { pub(crate) bs: RandomBools, pub(crate) xs: RandomMixedExtremePositiveFiniteFloats, } impl> Iterator for _RandomMixedExtremeNonzeroFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } #[inline] fn _random_mixed_extreme_nonzero_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> _RandomMixedExtremeNonzeroFiniteFloats>> { _RandomMixedExtremeNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_mixed_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[derive(Clone, Debug)] pub(crate) struct RandomMixedExtremeFiniteFloats> { pub(crate) bs: RandomBools, pub(crate) xs: RandomMixedExtremeNonNegativeFiniteFloats, } impl> Iterator for RandomMixedExtremeFiniteFloats { type Item = Float; #[inline] fn next(&mut self) -> Option { let x = self.xs.next().unwrap(); Some(if self.bs.next().unwrap() { x } else { -x }) } } #[inline] fn random_mixed_extreme_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomMixedExtremeFiniteFloats>> { RandomMixedExtremeFiniteFloats { bs: random_bools(seed.fork("bs")), xs: random_mixed_extreme_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } #[inline] fn random_mixed_extreme_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues< RandomMixedExtremeFiniteFloats>>, > { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { random_mixed_extreme_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } struct RandomFloatsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for RandomFloatsWithPrecisionUniformInclusiveRange { type Item = Float; fn next(&mut self) -> Option { let prec = self.precisions.next().unwrap(); let xs = self .floats .entry(prec) .or_insert(random_positive_floats_with_precision( self.seed.fork(&prec.to_string()), self.mean_exponent_n, self.mean_exponent_d, prec, )); Some(xs.next().unwrap()) } } fn random_floats_with_precision_inclusive_range( seed: Seed, config: &GenConfig, prec_lo: u64, prec_hi: u64, ) -> It { Box::new(RandomFloatsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), precisions: Box::new(random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, prec_hi, )), floats: HashMap::new(), }) } fn random_floats_with_precision_inclusive_range_to_infinity( seed: Seed, config: &GenConfig, prec_lo: u64, ) -> It { let mean_precision = Rational::from_unsigneds( config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 64), ) + Rational::from(prec_lo); let (n, d) = mean_precision.into_numerator_and_denominator(); Box::new(RandomFloatsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), precisions: Box::new(geometric_random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, u64::MAX, u64::exact_from(&n), u64::exact_from(&d), )), floats: HashMap::new(), }) } struct RandomFloatPairsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for RandomFloatPairsWithPrecisionUniformInclusiveRange { type Item = (Float, Float); fn next(&mut self) -> Option<(Float, Float)> { let prec = self.precisions.next().unwrap(); let xs = self .floats .entry(prec) .or_insert(random_positive_floats_with_precision( self.seed.fork(&prec.to_string()), self.mean_exponent_n, self.mean_exponent_d, prec, )); Some((xs.next().unwrap(), xs.next().unwrap())) } } struct RandomFloatPairsWithPrecisions { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for RandomFloatPairsWithPrecisions { type Item = (Float, Float); fn next(&mut self) -> Option<(Float, Float)> { let precs = self.precisions.next().unwrap(); let xs = self .floats .entry(precs.0) .or_insert(random_positive_floats_with_precision( self.seed.fork(&precs.0.to_string()), self.mean_exponent_n, self.mean_exponent_d, precs.0, )); let x = xs.next().unwrap(); let ys = self .floats .entry(precs.1) .or_insert(random_positive_floats_with_precision( self.seed.fork(&precs.1.to_string()), self.mean_exponent_n, self.mean_exponent_d, precs.1, )); let y = ys.next().unwrap(); Some((x, y)) } } fn random_float_pairs_with_precision_inclusive_range( seed: Seed, config: &GenConfig, prec_lo: u64, prec_hi: u64, ) -> It<(Float, Float)> { Box::new(RandomFloatPairsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), precisions: Box::new(random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, prec_hi, )), floats: HashMap::new(), }) } fn random_float_pairs_with_precision_inclusive_range_to_infinity( seed: Seed, config: &GenConfig, prec_lo: u64, ) -> It<(Float, Float)> { let mean_precision = Rational::from_unsigneds( config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 64), ) + Rational::from(prec_lo); let (n, d) = mean_precision.into_numerator_and_denominator(); Box::new(RandomFloatPairsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), precisions: Box::new(geometric_random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, u64::MAX, u64::exact_from(&n), u64::exact_from(&d), )), floats: HashMap::new(), }) } fn random_float_pairs_with_precisions( seed: Seed, config: &GenConfig, precisions: It<(u64, u64)>, ) -> It<(Float, Float)> { Box::new(RandomFloatPairsWithPrecisions { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), precisions, floats: HashMap::new(), }) } // -- (Float, Float) -- pub fn random_float_pair_gen(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single(random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } pub fn random_float_pair_gen_var_1(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single(random_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } pub fn random_float_pair_gen_var_2(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precision_inclusive_range(EXAMPLE_SEED, config, 1, Limb::WIDTH - 1) } pub fn random_float_pair_gen_var_3(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single( random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, ), )) } pub fn random_float_pair_gen_var_4(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precision_inclusive_range( EXAMPLE_SEED, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) } pub fn random_float_pair_gen_var_5(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single( random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, ), )) } pub fn random_float_pair_gen_var_6(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precision_inclusive_range( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) } pub fn random_float_pair_gen_var_7(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precision_inclusive_range_to_infinity( EXAMPLE_SEED, config, Limb::WIDTH * 3, ) } pub fn random_float_pair_gen_var_8(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precisions( EXAMPLE_SEED.fork("abc"), config, Box::new(random_pairs( EXAMPLE_SEED.fork("precisions"), &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, Limb::WIDTH, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, )), ) } pub fn random_float_pair_gen_var_9(config: &GenConfig) -> It<(Float, Float)> { random_float_pairs_with_precisions( EXAMPLE_SEED.fork("abc"), config, Box::new(random_pairs( EXAMPLE_SEED.fork("precisions"), &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|p: u64| p + Limb::WIDTH) }, )), ) } pub fn random_float_pair_gen_var_10(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single(random_mixed_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } // -- (Float, Float, Float) -- pub fn random_float_triple_gen(config: &GenConfig) -> It<(Float, Float, Float)> { Box::new(random_triples_from_single(random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } // -- (Float, Float, Integer) -- pub fn random_float_float_integer_triple_gen(config: &GenConfig) -> It<(Float, Float, Integer)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Float, Natural) -- pub fn random_float_float_natural_triple_gen(config: &GenConfig) -> It<(Float, Float, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Float, PrimitiveFloat) -- pub fn random_float_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, )) } // -- (Float, Float, PrimitiveInt) -- pub fn random_float_float_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| random_primitive_ints(seed), )) } // -- (Float, Float, PrimitiveUnsigned) -- pub fn random_float_float_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_float_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, Float, PrimitiveUnsigned, RoundingMode) -- pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_8( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_9( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_float_unsigned_rounding_mode_quadruple_gen_var_10( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Float, Rational) -- pub fn random_float_float_rational_triple_gen(config: &GenConfig) -> It<(Float, Float, Rational)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Float, RoundingMode) -- pub fn random_float_float_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } pub fn random_float_float_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_12( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_13( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_14( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_15( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_16( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_17( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_18( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_19( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_20( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_21( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_22( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_23( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_24( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_25( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_26( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_27( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precisions( seed.fork("abc"), config, Box::new(random_pairs( seed.fork("precisions"), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, 1, Limb::WIDTH, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, )), ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_28( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_float_pairs_with_precisions( seed.fork("abc"), config, Box::new(random_pairs( seed.fork("precisions"), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|p: u64| p + Limb::WIDTH) }, )), ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn random_float_float_rounding_mode_triple_gen_var_29( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, true)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_30( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, true)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_31( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, true)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_32( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, true)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_33( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } pub fn random_float_float_rounding_mode_triple_gen_var_34( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } // -- (Float, Integer) -- pub fn random_float_integer_pair_gen(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_integer_pair_gen_var_1(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_integer_pair_gen_var_2(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Integer, Integer) -- pub fn random_float_integer_integer_triple_gen( config: &GenConfig, ) -> It<(Float, Integer, Integer)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Natural) -- pub fn random_float_natural_pair_gen(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_natural_pair_gen_var_1(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_natural_pair_gen_var_2(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Natural, Natural) -- pub fn random_float_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Float, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Ordering) -- pub fn random_float_ordering_pair_gen(config: &GenConfig) -> It<(Float, Ordering)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_orderings, )) } pub fn random_float_ordering_pair_gen_var_1(config: &GenConfig) -> It<(Float, Ordering)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_orderings, )) } // -- (Float, PrimitiveFloat) -- pub fn random_float_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, )) } pub fn random_float_primitive_float_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, )) } // -- (Float, PrimitiveFloat, PrimitiveFloat) -- pub fn random_float_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Float, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, )) } // -- (Float, PrimitiveInt, PrimitiveInt) -- pub fn random_float_primitive_int_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Float, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| random_primitive_ints(seed), )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_float_signed_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_signed_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_float_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveSigned) -- pub fn random_float_signed_pair_gen(config: &GenConfig) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_ints, )) } // TODO use ranges pub fn random_float_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|mut x| { if let Float(Finite { exponent, .. }) = &mut x { *exponent = 1; } x }) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_ints, )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_signed_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_signed_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } // -- (Float, PrimitiveSigned, RoundingMode) -- pub fn random_float_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_signed_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_signed_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn random_float_signed_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn random_float_signed_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } // -- (Float, PrimitiveUnsigned) -- pub fn random_float_unsigned_pair_gen(config: &GenConfig) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_ints, )) } pub fn random_float_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_ints, )) } pub fn random_float_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- pub fn random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } pub fn random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } // -- (Float, PrimitiveUnsigned, RoundingMode) -- pub fn random_float_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| set_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| square_prec_round_valid(x, p, rm, false)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm, false)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| set_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| square_prec_round_valid(x, p, rm, true)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_12( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm, true)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_13( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| sqrt_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_14( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| sqrt_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_15( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_16( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_17( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_18( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_19( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| ln_prec_round_valid(x, p, rm)), ) } pub fn random_float_unsigned_rounding_mode_triple_gen_var_20( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| ln_prec_round_valid(x, p, rm)), ) } // -- (Float, Rational) -- pub fn random_float_rational_pair_gen(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_rational_pair_gen_var_1(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_float_rational_pair_gen_var_2(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Rational, PrimitiveUnsigned) -- pub fn random_float_rational_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_float_rational_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_8( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_9( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn random_float_rational_unsigned_rounding_mode_quadruple_gen_var_10( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Rational, Rational) -- pub fn random_float_rational_rational_triple_gen( config: &GenConfig, ) -> It<(Float, Rational, Rational)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Rational, RoundingMode) -- pub fn random_float_rational_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } pub fn random_float_rational_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub fn random_float_rational_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } // -- (Float, RoundingMode) -- pub fn random_float_rounding_mode_pair_gen(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn random_float_rounding_mode_pair_gen_var_1(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| natural_rounding_from_float_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_2(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| integer_rounding_from_float_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_3(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_nonzero_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &random_rounding_modes, )) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_5( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_6( config: &GenConfig, ) -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub fn random_float_rounding_mode_pair_gen_var_7(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_8(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_floats_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1), &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_9(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_10(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_11(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH << 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_12(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_13(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_14(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_floats_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1), &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_15(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_16(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn random_float_rounding_mode_pair_gen_var_17(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH + 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_18( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_19( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_float_rounding_mode_pair_gen_var_20( config: &GenConfig, ) -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub fn random_float_rounding_mode_pair_gen_var_21(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn random_float_rounding_mode_pair_gen_var_22(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, true)), ) } pub fn random_float_rounding_mode_pair_gen_var_23(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, true)), ) } pub fn random_float_rounding_mode_pair_gen_var_24(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_25(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| random_floats_with_precision_inclusive_range(seed, config, 1, Limb::WIDTH - 1), &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_26(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_27(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_28(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats_with_precision_inclusive_range_to_infinity( seed, config, (Limb::WIDTH << 1) + 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_29(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_30(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_31(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_32(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &random_rounding_modes, )) } pub fn random_float_rounding_mode_pair_gen_var_33(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn random_float_rounding_mode_pair_gen_var_34(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } pub fn random_float_rounding_mode_pair_gen_var_35(config: &GenConfig) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. pub fn random_integer_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), ) } pub fn random_integer_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- // var 1 is in malachite-nz pub fn random_natural_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), ) } pub fn random_natural_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Natural, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn random_primitive_float_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> where Float: From, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, p, rm)| from_primitive_float_prec_round_valid(x, p, rm)), ) } pub fn random_primitive_float_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> where Float: From, { Box::new(random_triples( EXAMPLE_SEED, &|seed| { special_random_primitive_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn random_signed_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), ) } pub fn random_signed_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } pub fn random_signed_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(i64, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(pow, _, rm)| { rm != Exact || (Float::MIN_EXPONENT..=Float::MAX_EXPONENT) .contains(&i32::saturating_from(pow).saturating_add(1)) }), ) } pub fn random_signed_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(i64, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(pow, _, rm)| { rm != Exact || (Float::MIN_EXPONENT..=Float::MAX_EXPONENT) .contains(&i32::saturating_from(pow).saturating_add(1)) }), ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn random_unsigned_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), ) } pub fn random_unsigned_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_ints::, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (Rational, PrimitiveUnsigned, RoundingMode) -- // var 1 is in malachite-nz pub fn random_rational_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), ) } pub fn random_rational_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } pub fn random_rational_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| sqrt_rational_prec_round_valid(n, prec, rm)), ) } pub fn random_rational_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| reciprocal_sqrt_rational_prec_round_valid(n, prec, rm)), ) } pub fn random_rational_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_non_negative_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), ) } pub fn random_rational_unsigned_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| ln_rational_prec_round_valid(n, prec, rm)), ) } // -- (Rational, Rational, PrimitiveUnsigned, RoundingMode) -- pub fn random_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_rational_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Rational, RoundingMode) -- // vars 1 through 5 are in malachite-q. pub fn random_rational_rounding_mode_pair_gen_var_6( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= 1 }), ) } ================================================ FILE: malachite-float/src/test_util/generators/special_random.rs ================================================ // Copyright © 2026 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 crate::Float; use crate::InnerFloat::Finite; use crate::random::{ RandomPositiveFiniteFloats, striped_random_finite_floats, striped_random_floats, striped_random_non_negative_finite_floats, striped_random_nonzero_finite_floats, striped_random_positive_finite_floats, striped_random_positive_floats_with_precision, }; use crate::test_util::extra_variadic::{ random_quadruples, random_quadruples_xxyz, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::exhaustive::{ add_prec_round_valid, add_rational_prec_round_valid, add_rational_round_valid, add_round_valid, agm_prec_round_valid, agm_rational_prec_round_valid, agm_round_valid, div_prec_round_valid, div_rational_prec_round_valid, div_rational_round_valid, div_round_valid, from_primitive_float_prec_round_valid, integer_rounding_from_float_valid, ln_prec_round_valid, ln_rational_prec_round_valid, ln_round_valid, mul_prec_round_valid, mul_rational_prec_round_valid, mul_rational_round_valid, mul_round_valid, natural_rounding_from_float_valid, rational_div_float_prec_round_valid, rational_div_float_round_valid, reciprocal_prec_round_valid, reciprocal_round_valid, reciprocal_sqrt_prec_round_valid, reciprocal_sqrt_rational_prec_round_valid, reciprocal_sqrt_round_valid, set_prec_round_valid, shl_prec_round_valid, shl_round_valid, shr_prec_round_valid, shr_round_valid, signed_rounding_from_float_valid, sqrt_prec_round_valid, sqrt_rational_prec_round_valid, sqrt_round_valid, square_prec_round_valid, square_round_valid, sub_prec_round_valid, sub_rational_prec_round_valid, sub_rational_round_valid, sub_round_valid, unsigned_rounding_from_float_valid, }; use crate::test_util::generators::random::{ RandomExtremeFiniteFloats, RandomExtremeNonNegativeFiniteFloats, RandomExtremeNonzeroFiniteFloats, RandomExtremePositiveFiniteFloats, RandomMixedExtremeFiniteFloats, RandomMixedExtremeNonNegativeFiniteFloats, RandomMixedExtremePositiveFiniteFloats, }; use malachite_base::bools::random::{random_bools, weighted_random_bools}; use malachite_base::iterators::{WithSpecialValues, with_special_values}; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_natural_signeds, geometric_random_positive_unsigneds, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use malachite_base::num::random::striped::{striped_random_signeds, striped_random_unsigneds}; use malachite_base::num::random::{random_primitive_floats, random_unsigned_inclusive_range}; use malachite_base::orderings::random::random_orderings; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{GenConfig, It, reshape_2_1_to_3}; use malachite_base::tuples::random::{random_pairs, random_pairs_from_single}; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ StripedRandomNaturalInclusiveRange, StripedRandomNaturals, striped_random_naturals, striped_random_positive_naturals, }; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::random::{striped_random_non_negative_rationals, striped_random_rationals}; use std::cmp::Ordering; use std::collections::HashMap; // -- Float -- pub fn special_random_float_gen(config: &GenConfig) -> It { Box::new(striped_random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn special_random_float_gen_var_1(config: &GenConfig) -> It { Box::new(striped_random_positive_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn special_random_float_gen_var_2(config: &GenConfig) -> It { Box::new( striped_random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|f| !f.is_nan()), ) } pub fn special_random_float_gen_var_3(config: &GenConfig) -> It { Box::new(striped_random_nonzero_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn special_random_float_gen_var_4(config: &GenConfig) -> It { Box::new(striped_random_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn special_random_float_gen_var_5(config: &GenConfig) -> It { Box::new(striped_random_non_negative_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } pub fn special_random_float_gen_var_6(config: &GenConfig) -> It { striped_random_floats_with_precision_inclusive_range(EXAMPLE_SEED, config, 1, Limb::WIDTH - 1) } pub fn special_random_float_gen_var_7(config: &GenConfig) -> It { Box::new(striped_random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, )) } pub fn special_random_float_gen_var_8(config: &GenConfig) -> It { striped_random_floats_with_precision_inclusive_range( EXAMPLE_SEED, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) } pub fn special_random_float_gen_var_9(config: &GenConfig) -> It { Box::new(striped_random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, )) } pub fn special_random_float_gen_var_10(config: &GenConfig) -> It { striped_random_floats_with_precision_inclusive_range( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) } pub fn special_random_float_gen_var_11(config: &GenConfig) -> It { striped_random_floats_with_precision_inclusive_range_to_infinity( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, ) } fn striped_random_extreme_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomExtremePositiveFiniteFloats>> { RandomExtremePositiveFiniteFloats { exponents: geometric_random_natural_signeds( seed.fork("exponents"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), exponent_modes: random_bools(seed.fork("exponent_modes")), xs: striped_random_positive_naturals( seed.fork("significands"), mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[inline] fn striped_random_extreme_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomExtremeNonNegativeFiniteFloats>> { RandomExtremeNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: striped_random_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[inline] fn striped_random_extreme_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomExtremeFiniteFloats>> { RandomExtremeFiniteFloats { bs: random_bools(seed.fork("bs")), xs: striped_random_extreme_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } #[inline] fn striped_random_extreme_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues< RandomExtremeFiniteFloats>>, > { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { striped_random_extreme_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } pub fn special_random_float_gen_var_12(config: &GenConfig) -> It { Box::new(striped_random_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), )) } #[inline] fn striped_random_extreme_nonzero_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomExtremeNonzeroFiniteFloats>> { RandomExtremeNonzeroFiniteFloats { bs: random_bools(seed.fork("bs")), xs: striped_random_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } pub fn special_random_float_gen_var_13(config: &GenConfig) -> It { Box::new(striped_random_extreme_nonzero_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), )) } pub fn special_random_float_gen_var_14(config: &GenConfig) -> It { Box::new( striped_random_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|f| !f.is_nan()), ) } pub fn special_random_float_gen_var_15(config: &GenConfig) -> It { Box::new( striped_random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32), ) } type GRNV = GeometricRandomNaturalValues; fn striped_random_mixed_extreme_positive_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, ) -> RandomMixedExtremePositiveFiniteFloats> { RandomMixedExtremePositiveFiniteFloats { exponents: geometric_random_natural_signeds( seed.fork("exponents"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, ), exponent_modes: random_unsigned_inclusive_range(seed.fork("exponent_modes"), 0, 3), xs: striped_random_positive_naturals( seed.fork("significands"), mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[inline] fn striped_random_mixed_extreme_non_negative_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomMixedExtremeNonNegativeFiniteFloats< StripedRandomNaturals>, > { RandomMixedExtremeNonNegativeFiniteFloats { bs: weighted_random_bools(seed.fork("bs"), zero_p_numerator, zero_p_denominator), xs: striped_random_mixed_extreme_positive_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), } } #[inline] fn striped_random_mixed_extreme_finite_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, ) -> RandomMixedExtremeFiniteFloats>> { RandomMixedExtremeFiniteFloats { bs: random_bools(seed.fork("bs")), xs: striped_random_mixed_extreme_non_negative_finite_floats( seed.fork("xs"), mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), } } #[inline] fn striped_random_mixed_extreme_floats( seed: Seed, mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, ) -> WithSpecialValues< RandomMixedExtremeFiniteFloats>>, > { with_special_values( seed, vec![Float::INFINITY, Float::NEGATIVE_INFINITY, Float::NAN], mean_special_p_numerator, mean_special_p_denominator, &|seed_2| { striped_random_mixed_extreme_finite_floats( seed_2, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ) }, ) } struct StripedRandomFloatsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, mean_stripe_n: u64, mean_stripe_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for StripedRandomFloatsWithPrecisionUniformInclusiveRange { type Item = Float; fn next(&mut self) -> Option { let prec = self.precisions.next().unwrap(); let xs = self .floats .entry(prec) .or_insert(striped_random_positive_floats_with_precision( self.seed.fork(&prec.to_string()), self.mean_exponent_n, self.mean_exponent_d, self.mean_stripe_n, self.mean_stripe_d, prec, )); Some(xs.next().unwrap()) } } fn striped_random_floats_with_precision_inclusive_range( seed: Seed, config: &GenConfig, prec_lo: u64, prec_hi: u64, ) -> It { Box::new(StripedRandomFloatsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), mean_stripe_n: config.get_or("mean_stripe_n", 64), mean_stripe_d: config.get_or("mean_stripe_d", 1), precisions: Box::new(random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, prec_hi, )), floats: HashMap::new(), }) } fn striped_random_floats_with_precision_inclusive_range_to_infinity( seed: Seed, config: &GenConfig, prec_lo: u64, ) -> It { let mean_precision = Rational::from_unsigneds( config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 64), ) + Rational::from(prec_lo); let (n, d) = mean_precision.into_numerator_and_denominator(); Box::new(StripedRandomFloatsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), mean_stripe_n: config.get_or("mean_stripe_n", 64), mean_stripe_d: config.get_or("mean_stripe_d", 1), precisions: Box::new(geometric_random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, u64::MAX, u64::exact_from(&n), u64::exact_from(&d), )), floats: HashMap::new(), }) } struct StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, mean_stripe_n: u64, mean_stripe_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { type Item = (Float, Float); fn next(&mut self) -> Option<(Float, Float)> { let prec = self.precisions.next().unwrap(); let xs = self .floats .entry(prec) .or_insert(striped_random_positive_floats_with_precision( self.seed.fork(&prec.to_string()), self.mean_exponent_n, self.mean_exponent_d, self.mean_stripe_n, self.mean_stripe_d, prec, )); Some((xs.next().unwrap(), xs.next().unwrap())) } } struct StripedRandomFloatPairsWithPrecisions { seed: Seed, mean_exponent_n: u64, mean_exponent_d: u64, mean_stripe_n: u64, mean_stripe_d: u64, precisions: Box>, floats: HashMap>, } impl Iterator for StripedRandomFloatPairsWithPrecisions { type Item = (Float, Float); fn next(&mut self) -> Option<(Float, Float)> { let precs = self.precisions.next().unwrap(); let xs = self.floats .entry(precs.0) .or_insert(striped_random_positive_floats_with_precision( self.seed.fork(&precs.0.to_string()), self.mean_exponent_n, self.mean_exponent_d, self.mean_stripe_n, self.mean_stripe_d, precs.0, )); let x = xs.next().unwrap(); let ys = self.floats .entry(precs.1) .or_insert(striped_random_positive_floats_with_precision( self.seed.fork(&precs.1.to_string()), self.mean_exponent_n, self.mean_exponent_d, self.mean_stripe_n, self.mean_stripe_d, precs.1, )); let y = ys.next().unwrap(); Some((x, y)) } } fn striped_random_float_pairs_with_precision_inclusive_range( seed: Seed, config: &GenConfig, prec_lo: u64, prec_hi: u64, ) -> It<(Float, Float)> { Box::new(StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), mean_stripe_n: config.get_or("mean_stripe_n", 64), mean_stripe_d: config.get_or("mean_stripe_d", 1), precisions: Box::new(random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, prec_hi, )), floats: HashMap::new(), }) } fn striped_random_float_pairs_with_precision_inclusive_range_to_infinity( seed: Seed, config: &GenConfig, prec_lo: u64, ) -> It<(Float, Float)> { let mean_precision = Rational::from_unsigneds( config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 64), ) + Rational::from(prec_lo); let (n, d) = mean_precision.into_numerator_and_denominator(); Box::new(StripedRandomFloatPairsWithPrecisionUniformInclusiveRange { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), mean_stripe_n: config.get_or("mean_stripe_n", 64), mean_stripe_d: config.get_or("mean_stripe_d", 1), precisions: Box::new(geometric_random_unsigned_inclusive_range( seed.fork("precisions"), prec_lo, u64::MAX, u64::exact_from(&n), u64::exact_from(&d), )), floats: HashMap::new(), }) } fn striped_random_float_pairs_with_precisions( seed: Seed, config: &GenConfig, precisions: It<(u64, u64)>, ) -> It<(Float, Float)> { Box::new(StripedRandomFloatPairsWithPrecisions { seed: seed.fork("floats"), mean_exponent_n: config.get_or("mean_exponent_n", 64), mean_exponent_d: config.get_or("mean_exponent_d", 1), mean_stripe_n: config.get_or("mean_stripe_n", 64), mean_stripe_d: config.get_or("mean_stripe_d", 1), precisions, floats: HashMap::new(), }) } // -- (Float, Float) -- pub fn special_random_float_pair_gen(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single(striped_random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } pub fn special_random_float_pair_gen_var_1(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single(striped_random_finite_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } pub fn special_random_float_pair_gen_var_2(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precision_inclusive_range( EXAMPLE_SEED, config, 1, Limb::WIDTH - 1, ) } pub fn special_random_float_pair_gen_var_3(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single( striped_random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, ), )) } pub fn special_random_float_pair_gen_var_4(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precision_inclusive_range( EXAMPLE_SEED, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) } pub fn special_random_float_pair_gen_var_5(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single( striped_random_positive_floats_with_precision( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, ), )) } pub fn special_random_float_pair_gen_var_6(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precision_inclusive_range( EXAMPLE_SEED, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) } pub fn special_random_float_pair_gen_var_7(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precision_inclusive_range_to_infinity( EXAMPLE_SEED, config, Limb::WIDTH * 3, ) } pub fn special_random_float_pair_gen_var_8(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precisions( EXAMPLE_SEED, config, Box::new(random_pairs( EXAMPLE_SEED.fork("precisions"), &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, Limb::WIDTH, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, )), ) } pub fn special_random_float_pair_gen_var_9(config: &GenConfig) -> It<(Float, Float)> { striped_random_float_pairs_with_precisions( EXAMPLE_SEED, config, Box::new(random_pairs( EXAMPLE_SEED.fork("precisions"), &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|p: u64| p + Limb::WIDTH) }, )), ) } pub fn special_random_float_pair_gen_var_10(config: &GenConfig) -> It<(Float, Float)> { Box::new(random_pairs_from_single( striped_random_mixed_extreme_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ), )) } // -- (Float, Float, Float) -- pub fn special_random_float_triple_gen(config: &GenConfig) -> It<(Float, Float, Float)> { Box::new(random_triples_from_single(striped_random_floats( EXAMPLE_SEED, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ))) } // -- (Float, Float, Integer) -- pub fn special_random_float_float_integer_triple_gen( config: &GenConfig, ) -> It<(Float, Float, Integer)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Float, Natural) -- pub fn special_random_float_float_natural_triple_gen( config: &GenConfig, ) -> It<(Float, Float, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_float_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_floats, )) } // -- (Float, Float, PrimitiveSigned) -- pub fn special_random_float_float_signed_triple_gen( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Float, Float, PrimitiveUnsigned) -- pub fn special_random_float_float_unsigned_triple_gen( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_float_float_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_float_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, Float, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, false)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_8( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_prec_round_valid(x, y, *prec, *rm, true)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_9( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_float_unsigned_rounding_mode_quadruple_gen_var_10( config: &GenConfig, ) -> It<(Float, Float, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Float, Rational) -- pub fn special_random_float_float_rational_triple_gen( config: &GenConfig, ) -> It<(Float, Float, Rational)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Float, RoundingMode) -- pub fn special_random_float_float_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, false)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, false)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| add_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_12( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_13( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_14( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_15( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| sub_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_16( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, false)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_17( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_18( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_19( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_20( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_21( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_22( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH * 3, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| mul_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_23( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, false)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_24( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_25( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs_from_single(striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, )) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_26( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_27( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precisions( seed, config, Box::new(random_pairs( seed.fork("precisions"), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed_2| { geometric_random_unsigned_inclusive_range( seed_2, 1, Limb::WIDTH, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, )), ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_28( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { reshape_2_1_to_3(Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_float_pairs_with_precisions( seed, config, Box::new(random_pairs( seed.fork("precisions"), &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|p: u64| p + Limb::WIDTH) }, )), ) }, &random_rounding_modes, ) .filter(|((x, y), rm)| div_round_valid(x, y, *rm, false)), )) } pub fn special_random_float_float_rounding_mode_triple_gen_var_29( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_round_valid(x, y, *rm, true)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_30( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_round_valid(x, y, *rm, true)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_31( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_round_valid(x, y, *rm, true)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_32( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_round_valid(x, y, *rm, true)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_33( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } pub fn special_random_float_float_rounding_mode_triple_gen_var_34( config: &GenConfig, ) -> It<(Float, Float, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_mixed_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| agm_round_valid(x, y, *rm)), ) } // -- (Float, Integer) -- pub fn special_random_float_integer_pair_gen(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_integer_pair_gen_var_1(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_integer_pair_gen_var_2(config: &GenConfig) -> It<(Float, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Integer, Integer) -- pub fn special_random_float_integer_integer_triple_gen( config: &GenConfig, ) -> It<(Float, Integer, Integer)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Natural) -- pub fn special_random_float_natural_pair_gen(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_natural_pair_gen_var_1(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_natural_pair_gen_var_2(config: &GenConfig) -> It<(Float, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Natural, Natural) -- pub fn special_random_float_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Float, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Ordering) -- pub fn special_random_float_ordering_pair_gen(config: &GenConfig) -> It<(Float, Ordering)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_orderings, )) } pub fn special_random_float_ordering_pair_gen_var_1(config: &GenConfig) -> It<(Float, Ordering)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_orderings, )) } // -- (Float, PrimitiveFloat) -- pub fn special_random_float_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_floats, )) } pub fn special_random_float_primitive_float_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_floats, )) } // -- (Float, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_float_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Float, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_primitive_floats, )) } // -- (Float, PrimitiveSigned) -- pub fn special_random_float_signed_pair_gen( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // TODO use ranges pub fn special_random_float_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) .map(|mut x| { if let Float(Finite { exponent, .. }) = &mut x { *exponent = 1; } x }) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Float, PrimitiveSigned, PrimitiveSigned) -- pub fn special_random_float_signed_signed_triple_gen( config: &GenConfig, ) -> It<(Float, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_float_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_1< T: PrimitiveSigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_2< T: PrimitiveSigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_3< T: PrimitiveSigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_signed_unsigned_rounding_mode_quadruple_gen_var_4< T: PrimitiveSigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } // -- (Float, PrimitiveSigned, RoundingMode) -- pub fn special_random_float_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_signed_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_signed_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn special_random_float_signed_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn special_random_float_signed_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } // -- (Float, PrimitiveUnsigned) -- pub fn special_random_float_unsigned_pair_gen( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Float, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_float_unsigned_unsigned_triple_gen( config: &GenConfig, ) -> It<(Float, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_float_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_unsigned_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shl_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } pub fn special_random_float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Float, T, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, prec, rm)| shr_prec_round_valid(x, bits, prec, rm)), ) } // -- (Float, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| set_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| square_prec_round_valid(x, p, rm, false)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm, false)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| set_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shl_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, T, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), ) .filter(|&(ref x, bits, rm)| shr_round_valid(x, bits, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| square_prec_round_valid(x, p, rm, true)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_12( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_prec_round_valid(x, p, rm, true)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_13( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| sqrt_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_14( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| sqrt_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_15( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_16( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| reciprocal_sqrt_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_17( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_18( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_19( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| ln_prec_round_valid(x, p, rm)), ) } pub fn special_random_float_unsigned_rounding_mode_triple_gen_var_20( config: &GenConfig, ) -> It<(Float, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref x, p, rm)| ln_prec_round_valid(x, p, rm)), ) } // -- (Float, Rational) -- pub fn special_random_float_rational_pair_gen(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_rational_pair_gen_var_1(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_float_rational_pair_gen_var_2(config: &GenConfig) -> It<(Float, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Rational, PrimitiveUnsigned) -- pub fn special_random_float_rational_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_float_rational_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Float, Rational, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| add_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| sub_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_8( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| mul_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_9( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| div_rational_prec_round_valid(x, y, *prec, *rm)), ) } pub fn special_random_float_rational_unsigned_rounding_mode_quadruple_gen_var_10( config: &GenConfig, ) -> It<(Float, Rational, u64, RoundingMode)> { Box::new( random_quadruples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| rational_div_float_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Float, Rational, Rational) -- pub fn special_random_float_rational_rational_triple_gen( config: &GenConfig, ) -> It<(Float, Rational, Rational)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Float, Rational, RoundingMode) -- pub fn special_random_float_rational_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| add_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_8( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| sub_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_9( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| mul_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_10( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| div_rational_round_valid(x, y, *rm)), ) } pub fn special_random_float_rational_rounding_mode_triple_gen_var_11( config: &GenConfig, ) -> It<(Float, Rational, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, rm)| rational_div_float_round_valid(x, y, *rm)), ) } // -- (Float, RoundingMode) -- pub fn special_random_float_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn special_random_float_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| natural_rounding_from_float_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| integer_rounding_from_float_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_3( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), ) }, &random_rounding_modes, )) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_5( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_6( config: &GenConfig, ) -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_7( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_8( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_9( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_10( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_11( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH << 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_12( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, (Limb::WIDTH << 1) + 1, Limb::WIDTH * 3 - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_13( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_14( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_15( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_16( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_17( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range_to_infinity( seed, config, Limb::WIDTH + 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, false)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_18( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| unsigned_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_19( config: &GenConfig, ) -> It<(Float, RoundingMode)> where Float: PartialOrd, for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| signed_rounding_from_float_valid::(f, *rm)), ) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_float_rounding_mode_pair_gen_var_20( config: &GenConfig, ) -> It<(Float, RoundingMode)> where for<'a> T: ConvertibleFrom<&'a Float>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| *rm != Exact || T::convertible_from(f)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_21( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn special_random_float_rounding_mode_pair_gen_var_22( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| square_round_valid(f, *rm, true)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_23( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_round_valid(f, *rm, true)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_24( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_25( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, 1, Limb::WIDTH - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_26( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_floats_with_precision( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_27( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range( seed, config, Limb::WIDTH + 1, (Limb::WIDTH << 1) - 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_28( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats_with_precision_inclusive_range_to_infinity( seed, config, (Limb::WIDTH << 1) + 1, ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_29( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_30( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_31( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| reciprocal_sqrt_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_32( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) .filter(|x| *x > 0u32) }, &random_rounding_modes, )) } pub fn special_random_float_rounding_mode_pair_gen_var_33( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_finite_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, )) } pub fn special_random_float_rounding_mode_pair_gen_var_34( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } pub fn special_random_float_rounding_mode_pair_gen_var_35( config: &GenConfig, ) -> It<(Float, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_extreme_floats( seed, config.get_or("mean_exponent_n", 64), config.get_or("mean_exponent_d", 1), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_precision_n", 64), config.get_or("mean_precision_d", 1), config.get_or("mean_zero_p_n", 1), config.get_or("mean_zero_p_d", 64), ) }, &random_rounding_modes, ) .filter(|(f, rm)| ln_round_valid(f, *rm)), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-nz. pub fn special_random_integer_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), ) } pub fn special_random_integer_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- // var 1 is in malachite-nz pub fn special_random_natural_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == 0u32 || n.significant_bits() - n.trailing_zeros().unwrap() <= prec }), ) } pub fn special_random_natural_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Natural, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|&rm| rm != Exact), )) } // -- (PrimitiveFloat, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> where Float: From, { Box::new( random_triples( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(x, p, rm)| from_primitive_float_prec_round_valid(x, p, rm)), ) } pub fn special_random_primitive_float_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> where Float: From, { Box::new(random_triples( EXAMPLE_SEED, &random_primitive_floats, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (PrimitiveSigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 2 are in malachite-base. pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), ) } pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } pub fn special_random_signed_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(i64, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|&(pow, _, rm)| { rm != Exact || (Float::MIN_EXPONENT..=Float::MAX_EXPONENT) .contains(&i32::saturating_from(pow).saturating_add(1)) }), ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned, RoundingMode) -- // vars 1 through 4 are in malachite-base. pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || *n == T::ZERO || n.significant_bits() - n.trailing_zeros() <= prec }), ) } pub fn special_random_unsigned_unsigned_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(T, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } // -- (Rational, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), ) } pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_3( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| random_rounding_modes(seed).filter(|rm| *rm != Exact), )) } pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_4( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| sqrt_rational_prec_round_valid(n, prec, rm)), ) } pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| reciprocal_sqrt_rational_prec_round_valid(n, prec, rm)), ) } pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_6( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_non_negative_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= prec }), ) } pub fn special_random_rational_unsigned_rounding_mode_triple_gen_var_7( config: &GenConfig, ) -> It<(Rational, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, prec, rm)| ln_rational_prec_round_valid(n, prec, rm)), ) } // -- (Rational, Rational, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_rational_rational_unsigned_rounding_mode_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, u64, RoundingMode)> { Box::new( random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, y, prec, rm)| agm_rational_prec_round_valid(x, y, *prec, *rm)), ) } // -- (Rational, RoundingMode) -- // vars 1 through 5 are in malachite-q. pub fn special_random_rational_rounding_mode_pair_gen_var_6( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| { rm != Exact || n.denominator_ref().is_power_of_2() && n.numerator_ref().significant_bits() <= 1 }), ) } ================================================ FILE: malachite-float/src/test_util/mod.rs ================================================ // Copyright © 2026 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 . pub mod arithmetic; pub mod bench; pub mod common; pub mod comparison; pub mod constants; pub mod conversion; pub mod exhaustive; pub mod extra_variadic; pub mod generators; pub mod random; ================================================ FILE: malachite-float/src/test_util/random/mod.rs ================================================ // Copyright © 2026 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 crate::itertools::Itertools; use crate::{ComparableFloat, ComparableFloatRef, Float}; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{MomentStats, moment_stats}; pub fn random_floats_helper_helper>( xs: I, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_median_hex: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { let comparable_xs = xs.clone().map(ComparableFloat); let raw_actual_values = xs.clone().take(20).collect_vec(); let actual_values = raw_actual_values .iter() .map(Float::to_string) .take(20) .collect_vec(); let actual_values_hex = raw_actual_values .iter() .map(|x| format!("{:#x}", ComparableFloatRef(x))) .take(20) .collect_vec(); let actual_values = actual_values.iter().map(String::as_str).collect_vec(); let actual_values_hex = actual_values_hex.iter().map(String::as_str).collect_vec(); for x in xs.clone().take(1000000) { assert!(x.is_valid()); } let raw_common_values = common_values_map(1000000, 10, comparable_xs.clone()) .into_iter() .collect_vec(); let actual_common_values = raw_common_values .iter() .map(|(x, freq)| (x.0.to_string(), *freq)) .collect_vec(); let actual_common_values = actual_common_values .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let actual_common_values_hex = raw_common_values .iter() .map(|(x, freq)| (format!("{x:#x}"), *freq)) .collect_vec(); let actual_common_values_hex = actual_common_values_hex .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let (median_lo, median_hi) = median(comparable_xs.take(1000000)); let (median_lo_hex, median_hi_hex) = ( format!("{median_lo:#x}"), median_hi.as_ref().map(|x| format!("{x:#x}")), ); let (median_lo, median_hi) = ( median_lo.0.to_string(), median_hi.map(|x| Float::to_string(&x.0)), ); let actual_sample_median = (median_lo.as_str(), median_hi.as_deref()); let actual_sample_median_hex = (median_lo_hex.as_str(), median_hi_hex.as_deref()); let actual_sample_moment_stats = moment_stats(xs.take(1000000).map(|x| f64::rounding_from(&x, Nearest).0)); assert_eq!( ( actual_values.as_slice(), actual_values_hex.as_slice(), actual_common_values.as_slice(), actual_common_values_hex.as_slice(), actual_sample_median, actual_sample_median_hex, actual_sample_moment_stats ), ( expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_sample_median, expected_sample_median_hex, expected_sample_moment_stats ) ); } // TODO remove once we have fast to_string pub fn random_floats_helper_helper_no_common_values>( xs: I, expected_values: &[&str], expected_values_hex: &[&str], expected_sample_median: (&str, Option<&str>), expected_sample_median_hex: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { let comparable_xs = xs.clone().map(ComparableFloat); let raw_actual_values = xs.clone().take(20).collect_vec(); let actual_values = raw_actual_values .iter() .map(Float::to_string) .take(20) .collect_vec(); let actual_values_hex = raw_actual_values .iter() .map(|x| format!("{:#x}", ComparableFloatRef(x))) .take(20) .collect_vec(); let actual_values = actual_values.iter().map(String::as_str).collect_vec(); let actual_values_hex = actual_values_hex.iter().map(String::as_str).collect_vec(); for x in xs.clone().take(1000000) { assert!(x.is_valid()); } let (median_lo, median_hi) = median(comparable_xs.take(1000000)); let (median_lo_hex, median_hi_hex) = ( format!("{median_lo:#x}"), median_hi.as_ref().map(|x| format!("{x:#x}")), ); let (median_lo, median_hi) = ( median_lo.0.to_string(), median_hi.map(|x| Float::to_string(&x.0)), ); let actual_sample_median = (median_lo.as_str(), median_hi.as_deref()); let actual_sample_median_hex = (median_lo_hex.as_str(), median_hi_hex.as_deref()); let actual_sample_moment_stats = moment_stats(xs.take(1000000).map(|x| f64::rounding_from(&x, Nearest).0)); assert_eq!( ( actual_values.as_slice(), actual_values_hex.as_slice(), actual_sample_median, actual_sample_median_hex, actual_sample_moment_stats ), ( expected_values, expected_values_hex, expected_sample_median, expected_sample_median_hex, expected_sample_moment_stats ) ); } ================================================ FILE: malachite-float/tests/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::primitive_float_gen; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{float_gen, float_gen_var_4, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; #[test] fn test_abs_negative_zero() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let abs = x.clone().abs_negative_zero(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); assert_eq!(to_hex_string(&abs), out_hex); let abs_alt = x.abs_negative_zero_ref(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); let mut abs_alt = x; abs_alt.abs_negative_zero_assign(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "-Infinity", "-Infinity"); test("0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0"); test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("2.0", "0x2.0#1", "2.0", "0x2.0#1"); test("0.5", "0x0.8#1", "0.5", "0x0.8#1"); test( "0.33333333333333331", "0x0.55555555555554#53", "0.33333333333333331", "0x0.55555555555554#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3.1415926535897931", "0x3.243f6a8885a30#53", ); test("-1.0", "-0x1.0#1", "-1.0", "-0x1.0#1"); test("-2.0", "-0x2.0#1", "-2.0", "-0x2.0#1"); test("-0.5", "-0x0.8#1", "-0.5", "-0x0.8#1"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-0.33333333333333331", "-0x0.55555555555554#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); } #[allow(clippy::needless_pass_by_value)] fn abs_negative_zero_properties_helper(x: Float) { let abs = x.clone().abs_negative_zero(); assert!(abs.is_valid()); let abs_alt = x.abs_negative_zero_ref(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); let mut abs_alt = x.clone(); abs_alt.abs_negative_zero_assign(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); if x.is_negative_zero() { assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&Float::ZERO)); } else { assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&x)); } assert_eq!( ComparableFloat(abs.abs_negative_zero_ref()), ComparableFloat(abs) ); } #[test] fn abs_negative_zero_properties() { float_gen().test_properties(|x| { abs_negative_zero_properties_helper(x); }); float_gen_var_12().test_properties(|x| { abs_negative_zero_properties_helper(x); }); } #[test] fn test_abs() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let abs = x.clone().abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); assert_eq!(to_hex_string(&abs), out_hex); let abs_alt = (&x).abs(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); let mut abs_alt = x.clone(); abs_alt.abs_assign(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); assert_eq!( ComparableFloat(Float::from(&rug::Float::exact_from(&x).abs())), ComparableFloat(abs) ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "Infinity", "Infinity"); test("0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0"); test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("2.0", "0x2.0#1", "2.0", "0x2.0#1"); test("0.5", "0x0.8#1", "0.5", "0x0.8#1"); test( "0.33333333333333331", "0x0.55555555555554#53", "0.33333333333333331", "0x0.55555555555554#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3.1415926535897931", "0x3.243f6a8885a30#53", ); test("-1.0", "-0x1.0#1", "1.0", "0x1.0#1"); test("-2.0", "-0x2.0#1", "2.0", "0x2.0#1"); test("-0.5", "-0x0.8#1", "0.5", "0x0.8#1"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0.33333333333333331", "0x0.55555555555554#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3.1415926535897931", "0x3.243f6a8885a30#53", ); } fn abs_properties_helper(x: Float) { let abs = x.clone().abs(); assert!(abs.is_valid()); let abs_alt = (&x).abs(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); let mut abs_alt = x.clone(); abs_alt.abs_assign(); assert!(abs_alt.is_valid()); assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&abs_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::exact_from(&x).abs())), ComparableFloatRef(&abs) ); if x.is_sign_negative() { assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&-&x)); } else { assert_eq!(ComparableFloatRef(&abs), ComparableFloatRef(&x)); } assert_eq!(ComparableFloatRef(&(&abs).abs()), ComparableFloatRef(&abs)); assert_eq!(ComparableFloat((-x).abs()), ComparableFloat(abs)); } #[test] fn abs_properties() { float_gen().test_properties(|x| { abs_properties_helper(x); }); float_gen_var_12().test_properties(|x| { abs_properties_helper(x); }); float_gen_var_4().test_properties(|x| { assert_eq!( Rational::exact_from((&x).abs()), Rational::exact_from(x).abs() ); }); primitive_float_gen::().test_properties(|x| { assert_eq!( ComparableFloat(Float::from(x.abs())), ComparableFloat(Float::from(x).abs()) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{NegAssign, PowerOf2}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::emulate_float_float_to_float_fn; use malachite_float::test_util::arithmetic::add::{ add_prec_round_naive, add_rational_prec_round_naive, rug_add, rug_add_prec, rug_add_prec_round, rug_add_rational, rug_add_rational_prec, rug_add_rational_prec_round, rug_add_rational_round, rug_add_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_1, float_float_rounding_mode_triple_gen_var_4, float_float_rounding_mode_triple_gen_var_5, float_float_rounding_mode_triple_gen_var_6, float_float_rounding_mode_triple_gen_var_7, float_float_rounding_mode_triple_gen_var_8, float_float_rounding_mode_triple_gen_var_9, float_float_rounding_mode_triple_gen_var_29, float_float_unsigned_rounding_mode_quadruple_gen_var_1, float_float_unsigned_rounding_mode_quadruple_gen_var_5, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_2, float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, float_pair_gen_var_5, float_pair_gen_var_6, float_pair_gen_var_7, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_1, float_rational_rounding_mode_triple_gen_var_8, float_rational_unsigned_rounding_mode_quadruple_gen_var_1, float_rational_unsigned_rounding_mode_quadruple_gen_var_7, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_2, float_rounding_mode_pair_gen, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::cmp::{ Ordering::{self, *}, max, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_add() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let sum = x.clone() + y.clone(); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_add( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef(&sum) ); let sum_alt = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test( "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test( "Infinity", "Infinity", "0.0", "0x0.0", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", "Infinity", "Infinity", ); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "0.0", "0x0.0", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "-0.0", "-0x0.0", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("-0.0", "-0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", "-0.0", "-0x0.0", "123.0", "0x7b.0#7"); test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "123.0", "0x7b.0#7", "123.0", "0x7b.0#7"); test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "123.0", "0x7b.0#7"); // - in add_float_significands_same_prec_lt_w // - x_exp < y_exp in add_float_significands_same_prec_lt_w // - exp_diff < shift in add_float_significands_same_prec_lt_w // - exp_diff < shift && !overflow in add_float_significands_same_prec_lt_w // - (round_bit != 0 || sticky_bit == 0) && rm == Nearest in // add_float_significands_same_prec_lt_w // - round_bit != 0 && (sticky_bit != 0 || (sum & shift_bit) != 0) in // add_float_significands_same_prec_lt_w // - rm == Nearest && sum == 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "4.0", "0x4.0#1"); // - in add_float_significands_same_prec_general // - out_bits > exp_diff in add_float_significands_same_prec_general // - overlap <= ys_len in add_float_significands_same_prec_general // - shift2 != 0 in add_float_significands_same_prec_general // - out_len - k <= overlap in add_float_significands_same_prec_general // - out_len <= xs_len second time in add_float_significands_same_prec_general // - !y in add_float_significands_same_prec_general // - round_bit == Uninitialized && shift != 0 in add_float_significands_same_prec_general // - shift > 1 in add_float_significands_same_prec_general // - x == 0 second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits != True in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff <= out_bits in // add_float_significands_same_prec_general // - exp_diff_rem != 0 || yi != 0 second time in add_float_significands_same_prec_general // - exp_diff_rem != 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized seventh time in add_float_significands_same_prec_general // - yi == 0 second time in add_float_significands_same_prec_general // - in add_float_significands_same_prec_general_round // - following_bits == False && round_bit == False in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "3.0", "0x3.0#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "3.0", "0x3.0#2"); // round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "3.0", "0x3.0#2"); test("1.0", "0x1.000#10", "2.0", "0x2.00#10", "3.0", "0x3.00#10"); // - exp_diff < shift && overflow in add_float_significands_same_prec_lt_w // - round_bit == 0 || (sticky_bit == 0 && (sum & shift_bit) == 0) // - in add_float_significands_same_prec_lt_w test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "4.555806215962888", "0x4.8e4950f0795fc#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1.727379091216698", "-0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "1.727379091216698", "0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-4.555806215962888", "-0x4.8e4950f0795fc#53", ); // - x_exp > y_exp in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "0.0002", "0x0.001#1", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "-1.0", "-0x1.0#1", "0.0", "0x0.0"); // - x_exp == y_exp in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "2.0", "0x2.0#1"); // - rm == Nearest && sum != 0 in add_float_significands_same_prec_lt_w test("1.0", "0x1.0#3", "1.8", "0x1.c#3", "3.0", "0x3.0#3"); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_lt_w test( "7.7e14", "0x2.bcE+12#8", "1.237e-9", "0x5.50E-8#8", "7.7e14", "0x2.bcE+12#8", ); // - shift <= exp_diff < Limb::WIDTH in add_float_significands_same_prec_lt_w // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.852193494e22", "0x3.ec137baE+18#29", "241425944.0", "0xe63de18.0#29", "1.852193494e22", "0x3.ec137baE+18#29", ); // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.999999999999993", "0x1.fffffffffffe#48", "5.96046447753906e-8", "0x1.000000000000E-6#48", "2.00000005960464", "0x2.000001000000#48", ); // - in add_float_significands_same_prec_w // - x_exp == y_exp in add_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", ); // - x_exp < y_exp in add_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_w // - !overflow in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", "3.0", "0x3.0000000000000000#64", ); // - x_exp > y_exp in add_float_significands_same_prec_w test( "2.0", "0x2.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "3.0", "0x3.0000000000000000#64", ); // - (round_bit != 0) || (sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_w // - round_bit == 0 || (sticky_bit == 0 && (sum & 1) == 0) in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", "2.0", "0x2.0000000000000000#64", ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) in add_float_significands_same_prec_w // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and !overflow in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000003", "0x1.0000000000000006#64", "2.0000000000000000004", "0x2.0000000000000008#64", ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", ); // - overflow in add_float_significands_same_prec_w test( "0.00022185253582909293959", "0x0.000e8a1162cbb1a4265#64", "0.000029745661521717034001", "0x0.0001f30ca4b8117ff0a0#64", "0.0002515981973508099736", "0x0.00107d1e0783c324170#64", ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and overflow in // add_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", "128.0", "0x80.00000000000000#64", ); // - in add_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in add_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", ); // - x_exp < y_exp in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", "3.0", "0x3.0000000000000000#65", ); // - x_exp > y_exp in add_float_significands_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "3.0", "0x3.0000000000000000#65", ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (sum_0 != 0 || sum_1 != 0) in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", "2.0", "0x2.0000000000000000#65", ); // - rm == Nearest && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", "2.0000000000000000002", "0x2.0000000000000004#65", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", ); // - exp_diff >= Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", "372369974082165972922376.05178046858", "0x4eda377c7f0d747ff008.0d417c1b20#116", ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_w_lt_2w test( "18.492649216180435830000529", "0x12.7e1e424fe51f1bb914c0#85", "56.637589789906471403844847", "0x38.a339159fe96c1722fdfe#85", "75.130239006086907233845378", "0x4b.215757efce8b32dc12c0#85", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", "256.0", "0x100.0000000000000000000000000#107", ); // - rm == Nearest && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "0.0000610351562499999999996", "0x0.0003ffffffffffffffff8#67", "17179869183.9999389648", "0x3ffffffff.fffc00000#67", "17179869184.0", "0x400000000.00000000#67", ); // - in add_float_significands_same_prec_2w // - x_exp == y_exp in add_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", ); // - x_exp < y_exp in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", "3.0", "0x3.00000000000000000000000000000000#128", ); // - x_exp > y_exp in add_float_significands_same_prec_2w test( "2.0", "0x2.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", "3.0", "0x3.00000000000000000000000000000000#128", ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_2w // - rm == Nearest in add_float_significands_same_prec_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (sum_0 & 1) == 0)) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "2.0", "0x2.00000000000000000000000000000000#128", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (sum_0 & 1) != 0) in // add_float_significands_same_prec_2w // - rm == Nearest && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", "2.00000000000000000000000000000000000002", "0x2.00000000000000000000000000000008#128", ); // - exp_diff >= TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff > TWICE_WIDTH in add_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", "4354249796990942.35435357606921728525736", "0xf782ac869b7de.5ab6ea7c701c9acb1b1#128", ); // - exp_diff == TWICE_WIDTH in add_float_significands_same_prec_2w test( "15732412727332569995335732833027757624.44", "0xbd5f3d586bc01069a1d94f5ab5a1638.7#128", "0.0373708302820085888760745841639896128921", "0x0.0991227de2b63edc67164401ce8ebdb04#128", "15732412727332569995335732833027757624.5", "0xbd5f3d586bc01069a1d94f5ab5a1638.8#128", ); // - Limb::WIDTH == exp_diff in add_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", "148.054913367700296555095560478615943812", "0x94.0e0ecd6e62d0a98ad7d520e1456fe0#128", ); // - exp_diff < TWICE_WIDTH && overflow in add_float_significands_same_prec_2w test( "990.890284854484258981204316304960898664", "0x3de.e3e9b54e224e900a8701c94cea27bc#128", "111.972242543885876168914754084523121772", "0x6f.f8e4e329c509f04b7f9497ec8ce6438#128", "1102.862527398370135150119070389484020437", "0x44e.dcce9877e758805606966139770e00#128", ); // - rm == Nearest && overflow in add_float_significands_same_prec_2w test( "1152920954851033088.0", "0xfffff8000000000.00000000000000000#128", "549755813887.999999999999999999999999998", "0x7fffffffff.ffffffffffffffffffffff8#128", "1152921504606846976.0", "0x1000000000000000.00000000000000000#128", ); // - in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - x_exp > y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "3.0", "0x3.00000000000000000000000000000000#129", ); // - x_exp < y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "2.0", "0x2.00000000000000000000000000000000#129", "3.0", "0x3.00000000000000000000000000000000#129", ); // - x_exp == y_exp in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", "2.0", "0x2.00000000000000000000000000000000#129", ); // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 < exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", ); // - exp_diff >= Limb::WIDTH * 3 in add_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", "978.49328809934495391839923652526678587611222", "0x3d2.7e4820fe314caadcbba75ebc3b0b3d718f#146", ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_2w_lt_3w test( "4499918.46219262840948309077470961400786337", "0x44a9ce.7652418f789422bc22220831e2030#137", "64560208.0262619516023687759351781439347886", "0x3d91c50.06b91a6f42e5205070f82f89eefa#137", "69060126.488454580011851866709887757942652", "0x41dc61e.7d0b5bfebb79430c931a37bbd0fc#137", ); // - exp_diff == Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", "563971925627753843356041629019151473019479982637.25", "0x62c960337e963a378ba6626ea422d8a633b5022d.40#165", ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", "4262448175090788889679.91469733230924119", "0xe71159efd3a67e744f.ea299ab801b2d60#130", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "1180591620717411303423.999999999999999999999999997", "0x3fffffffffffffffff.ffffffffffffffffffffff#158", "5.68434188616351954822429632036496545806324230121e-14", "0x1.000000000fffffffffffe0000000000000000038E-11#158", "1180591620717411303424.00000000000005684341886163", "0x400000000000000000.00000000001000000000fe#158", ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum == 0 test( "4503599627370495.9999999999999999999999999996", "0xfffffffffffff.ffffffffffffffffffffffe#143", "3.3087224509824797385046520537834728287650668e-24", "0x4.00000003ffff0000000000000000fffffffE-20#143", "4503599627370496.000000000000000000000003309", "0x10000000000000.00000000000000000004000#143", ); // - in add_float_significands_same_prec_ge_3w // - exp_diff == 0 in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && round_bit == 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", ); // - x_exp < y_exp in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec in add_float_significands_same_prec_ge_3w // - in add_significands_rsh_to_out // - exp_diff < Limb::WIDTH in add_significands_rsh_to_out // - 0 < exp_diff < prec && shift == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && limb == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - x_exp > y_exp in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - 0 < exp_diff < prec && shift != 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "2.0", "0x2.000000000000000000000000000000000000000000000000#193", "3.0", "0x3.000000000000000000000000000000000000000000000000#193", ); // - exp_diff == 0 && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && sticky_bit == 0 && out[0] & // shift_bit == 0 test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "3.0", "0x3.000000000000000000000000000000000000000000000000#192", ); // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 in // add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "2.0000000000000000000000000000000000000000000000000000000013", "0x2.000000000000000000000000000000000000000000000008#192", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "3.0000000000000000000000000000000000000000000000000000000013", "0x3.000000000000000000000000000000000000000000000008#192", ); // - exp_diff >= Limb::WIDTH in add_significands_rsh_to_out // - exp_diff >= Limb::WIDTH && r != 0 in add_significands_rsh_to_out test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", "3.5123473778825578959041500899351426183100429740785046308614e-27", "0x1.1646de419a6dbd3471970441a59a8d2474f195e0f288088aa8E-22#198", ); // - exp_diff >= prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Nearest || rm == Floor // || rm == Down) test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", ); // - 0 < exp_diff < prec && limb != 0 in add_float_significands_same_prec_ge_3w test( "8.699772042374378140693728074838279708562673799416097107796", "0x8.b32442b4a730454d66b1b2bdf7a2863d417e6ff22d7f6c58#193", "7.5897463681962395437740598844462353563682906392115908083148", "0x7.96f99e34566e7be1960d023e431dc5e0a7ad24ad691a1ac4#193", "16.289518410570617684467787959284515064930964438627687916112", "0x10.4a1de0e8fd9ec12efcbeb4fc3ac04c1de92b949f9699872#193", ); // - exp_diff >= Limb::WIDTH && r == 0 in add_significands_rsh_to_out test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", "1476808010161862576835936576709144.797568704117653151104618", "0x48cff00a780a50d34bb694ada218.cc2d766c7f9881c2afc48#192", ); // - exp_diff == prec in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && power && !carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power in add_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", "1174582238252884689829665592721065057.76655867827770290150729", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d8#194", ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && carry in add_float_significands_same_prec_ge_3w test( "4.336808689942017736029811203479766845699938816177735095446e-19", "0x7.fffffffffffffffffffffffffffffffe0000000000000000E-16#192", "5192296858534827628530496329220095.999999999999999999566319", "0xffffffffffffffffffffffffffff.fffffffffffffff80000#192", "5192296858534827628530496329220096.0", "0x10000000000000000000000000000.00000000000000000000#192", ); // - exp_diff == prec && rm == Nearest && power && carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power && carry in // add_float_significands_same_prec_ge_3w test( "158456325028528675187087900671.99999999999999999999999999997", "0x1ffffffffffffffffffffffff.fffffffffffffffffffffffe#192", "2.5243548967072377773175314089049159349542605923488736152645e-29", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-24#192", "158456325028528675187087900672.0", "0x2000000000000000000000000.000000000000000000000000#192", ); // - exp_diff == prec && rm == Nearest && power in add_float_significands_same_prec_ge_3w test( "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", "2.6469779601696885595885078146238811314105987548828125e-23", "0x2.000000000000000000000000000000000000000000000000E-19#192", "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", ); // - shift2 == 0 in add_float_significands_same_prec_general // - y in add_float_significands_same_prec_general // - shift != 0 in add_float_significands_same_prec_general // - x == 0 first time in add_float_significands_same_prec_general // - shift == 0 || following_bits != Uninitialized in add_float_significands_same_prec_general // - round_bit != Uninitialized || shift == 0 in add_float_significands_same_prec_general // - exp_diff_rem == 0 && yi == 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized sixth time in add_float_significands_same_prec_general test("1.0", "0x1.0#1", "1.0", "0x1.0#2", "2.0", "0x2.0#2"); // - following_bits != False || round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit == 0 in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "2.0", "0x2.0#2"); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && carry in // add_float_significands_same_prec_general_round test("2.0", "0x2.0#1", "1.5", "0x1.8#2", "4.0", "0x4.0#2"); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_general_round test("1.0", "0x1.0#1", "1.8", "0x1.c#3", "3.0", "0x3.0#3"); // - x != 0 && x != mask second time in add_float_significands_same_prec_general // - rm == Nearest && following_bits != False && round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits != False && round_bit != False && !carry in // add_float_significands_same_prec_general_round test("1.5", "0x1.8#2", "4.0", "0x4.0#1", "6.0", "0x6.0#2"); // - rm == Nearest && following_bits != False && round_bit == False in // add_float_significands_same_prec_general_round test("4.0", "0x4.0#1", "1.2", "0x1.4#3", "5.0", "0x5.0#3"); // - x != 0 && x != mask first time in add_float_significands_same_prec_general // - shift != 0 && following_bits == Uninitialized in add_float_significands_same_prec_general test("1.2", "0x1.4#3", "3.0", "0x3.0#2", "4.0", "0x4.0#3"); // - rm == Nearest && following_bits != False && round_bit != False && carry in // add_float_significands_same_prec_general_round test("1.8", "0x1.c#3", "6.0", "0x6.0#2", "8.0", "0x8.0#3"); // - out_bits <= exp_diff in add_float_significands_same_prec_general // - out_len <= xs_len first time in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff > out_bits in // add_float_significands_same_prec_general // - round_bit != Uninitialized fifth time in add_float_significands_same_prec_general test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", "9.75459983374e122", "0x1.79c17f063aE+102#40", ); // - out_len > xs_len first time in add_float_significands_same_prec_general test( "2.8577648979177105962332201291018926848163080599637e-19", "0x5.458a93bffa7b1c05bdd1c0552b60196746d9083cE-16#162", "3.569720699507868e50", "0xf.4400d3acf388E+41#51", "3.5697206995078675404584127554321345196383736430592e50", "0xf.4400d3acf3880000000000000000000000000000E+41#162", ); // - overlap > ys_len in add_float_significands_same_prec_general // - out_len - k > overlap in add_float_significands_same_prec_general // - difw <= 0 || difw <= ys_len in add_float_significands_same_prec_general // - round_bit != Uninitialized fourth time in add_float_significands_same_prec_general test( "29780282551.762684458936866363165", "0x6ef0b0cb7.c33f49e84d21bb6040#104", "0.00003945598947538", "0x0.000295f62f36adb#46", "29780282551.762723914926341743141", "0x6ef0b0cb7.c341dfde7c58691040#104", ); // - out_len > xs_len second time in add_float_significands_same_prec_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", "0.00374222829424688982311482391965285", "0x0.00f5402c235119eafa12eb9821602#107", ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general test( "5.19192095203e-15", "0x1.761e097c5E-12#37", "7.4e4", "0x1.2E+4#5", "73728.0", "0x12000.00000#37", ); // - shift <= 1 in add_float_significands_same_prec_general test( "15135.895602865542606017656527713819177465060416097749360065", "0x3b1f.e5463ab9b599ce49b83c7988b324dc93ce50b2ed51a18#191", "3.581529624499970047886732225242180736649e-8", "0x9.9d355ad2b99a587727da095fa3226bf0E-7#130", "15135.895602901357902262656228192686499717482223464235884113", "0x3b1f.e5463b5388ef7b7551e200fb30c5728e007771ed51a18#191", ); // - round_bit == Uninitialized fourth time in add_float_significands_same_prec_general // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "8.63643735016344467819174862798332593462e-6", "0x0.000090e5374a001358c6606f968bf3813ad9#128", "1.84904e-8", "0x4.f6a6E-7#18", "8.65492771851100147411665059026359937212e-6", "0x0.00009134a1aa001358c6606f968bf3813ad9#128", ); // - round_bit == Uninitialized fifth time in add_float_significands_same_prec_general test( "2.389545997e25", "0x1.3c40f7bE+21#29", "0.078263259824284000402", "0x0.14090f9d6c745bc06#64", "2.389545996756557709e25", "0x1.3c40f7b000000000E+21#64", ); // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", "5.7505517053731436845e-7", "0x9.a5d7d8bbfd3d47dE-6#64", ); // - x != 0 && x == mask second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits == True in add_float_significands_same_prec_general test( "1.081090215247020702e-18", "0x1.3f14ddfe22c0634E-15#59", "6.3799657596147e-8", "0x1.12047722d26cE-6#47", "6.37996575972280156e-8", "0x1.12047722e65d4dcE-6#59", ); // - shift == 0 in add_float_significands_same_prec_general test( "4.3055451539258443718732375731462554408177909736937057433067e-16", "0x1.f06543668e6018c20c17efed72ff6d3d65a4c5dc9db475b0E-13#192", "1.6388436e-15", "0x7.61754E-13#21", "2.0693980969049410047184094732421002104686218250305033868307e-15", "0x9.51da83668e6018c20c17efed72ff6d3d65a4c5dc9db475bE-13#192", ); // - yi != 0 second time in add_float_significands_same_prec_general test( "2.24181435676546e-16", "0x1.0276ae5de1e8E-13#47", "7.6430700039878539638425372386462404393e-36", "0xa.28cd4cb186f5925ddb0d1ecb9681103E-30#128", "2.24181435676546206911083333246297446029e-16", "0x1.0276ae5de1e80000a28cd4cb186f5926E-13#128", ); // - x != 0 && x == mask first time in add_float_significands_same_prec_general test( "2.1474796e9", "0x7.ffff00E+7#24", "8191.9998788833609", "0x1fff.fff80fffff0#54", "2147487743.9998789", "0x80000fff.fff810#54", ); test( "too_big", "0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", "Infinity", "Infinity", ); test( "too_big", "0x4.0E+268435455#1", "1.0", "0x1.0#1", "too_big", "0x4.0E+268435455#1", ); test( "too_small", "0x1.0E-268435456#1", "too_small", "0x1.0E-268435456#1", "too_small", "0x2.0E-268435456#1", ); test( "too_small", "0x1.8E-268435456#2", "-too_small", "-0x1.0E-268435456#1", "0.0", "0x0.0", ); test( "too_small", "0x1.4E-268435456#3", "-too_small", "-0x1.0E-268435456#1", "0.0", "0x0.0", ); test( "1.262113616894785778907e-31", "0x2.8f53ace354a6b7284E-26#68", "-1.26e-31", "-0x2.90E-26#7", "-1.296426623240940697535e-34", "-0xa.c531cab5948d7c00E-29#68", ); test( "too_small", "0x2.8f5E-268435454#14", "-too_small", "-0x2.900E-268435454#14", "-too_small", "-0x1.0000E-268435456#14", ); test( "-too_small", "-0x2.8f5E-268435454#14", "too_small", "0x2.900E-268435454#14", "too_small", "0x1.0000E-268435456#14", ); test( "-too_big", "-0x4.0E+268435455#1", "-too_big", "-0x4.0E+268435455#1", "-Infinity", "-Infinity", ); test( "-too_big", "-0x4.0E+268435455#1", "-1.0", "-0x1.0#1", "-too_big", "-0x4.0E+268435455#1", ); } #[test] fn test_add_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_prec(y.clone(), prec); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_assign(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_assign_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "-0.0", "-0x0.0", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-2.0", "-0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "2.0", "0x2.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 1, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, "0.0", "0x0.0", Equal, ); // - xs_len > out_len in add_float_significands_same_prec_general // - following_bits != False || difw > 0 in add_float_significands_same_prec_general // - difw <= ys_len in add_float_significands_same_prec_general // - exp_diff_rem != 0 || yi != 0 first time in add_float_significands_same_prec_general // - yi >= 0 && yi == ys_len in add_float_significands_same_prec_general // - following_bits != Uninitialized first time in add_float_significands_same_prec_general // - exp_diff_rem != 0 first time in add_float_significands_same_prec_general // - yi >= 0 second time in add_float_significands_same_prec_general // - yi >= 0 third time in add_float_significands_same_prec_general // - x >= y in add_float_significands_same_prec_general // - following_bits != False || x == 0 in add_float_significands_same_prec_general // - following_bits != False && x != Limb::MAX second time in // add_float_significands_same_prec_general test( "1.73414747294406e-17", "0x1.3fe4cc8cf520E-14#48", "5095194424.1679374580403939884785489", "0x12fb27f38.2afdf3020e8eaac84a7ec#116", 62, "5095194424.167937458", "0x12fb27f38.2afdf300#62", Less, ); // - yi < 0 || yi != ys_len in add_float_significands_same_prec_general // - yi < 0 third time in add_float_significands_same_prec_general test( "102490490.309858195", "0x61be17a.4f52dde#54", "140024642456267714260687682888.7395345704093208802906032076327334", "0x1c471ab65a12bae8410f87d48.bd52233a2b6095a9fa45bd79bbfc#209", 126, "140024642456267714260790173379.049392765", "0x1c471ab65a12bae8417145ec3.0ca50118#126", Less, ); // - following_bits != 0 && following_bits != Limb::MAX in // add_float_significands_same_prec_general // - x != Limb::MAX first time in add_float_significands_same_prec_general test( "3.6587e-6", "0x0.00003d62#14", "2.26998937985590408943624715555e46", "0x3.f9e6004fa97f534f98cad274E+38#96", 61, "2.269989379855904089e46", "0x3.f9e6004fa97f534E+38#61", Less, ); // - following_bits == Uninitialized first time in add_float_significands_same_prec_general // - exp_diff_rem != 0 in add_float_significands_same_prec_general // - yi < 0 first time in add_float_significands_same_prec_general // - x >= y or not other conditions in add_float_significands_same_prec_general // - round_bit == Limb::MAX second time in add_float_significands_same_prec_general // - following_bits != False && x != Limb::MAX first time in // add_float_significands_same_prec_general test( "6058.05208272591415306446968882359605946955168456454", "0x17aa.0d554b247ce1b6ab28ba39c8d5992a74c7ac91a#169", "0.000144566892208323", "0x0.0009796e12f9784#47", 64, "6058.0522272928063612", "0x17aa.0d5ec4928fdb2#64", Less, ); // - following_bits == True in add_float_significands_same_prec_general // - round_bit == Uninitialized first time in add_float_significands_same_prec_general // - x != Limb::MAX second time in add_float_significands_same_prec_general test( "3.6596517369110659089355442395654891585e48", "0x2.810875a0ca3206afd8c6cf841941830E+40#123", "1545.699550397407201099813420288295", "0x609.b315bc1ec48a143a74bd53048#109", 64, "3.6596517369110659089e48", "0x2.810875a0ca3206b0E+40#64", Greater, ); // - yi >= 0 first time in add_float_significands_same_prec_general test( "2.80915429604669102593383052436808885401854724410738829e-11", "0x1.ee310ffa09a06a6361f52c2cd8a9569a780b775dc213E-9#177", "519241072363118296470.333928838103121952666621563036", "0x1c25eadc41d4907d96.557c5c3ed81cab65dab0cf920#166", 64, "5.1924107236311829648e20", "0x1.c25eadc41d4907daE+17#64", Greater, ); // - round_bit != Uninitialized second time in add_float_significands_same_prec_general test( "559935046210054011882951826578284118061013900.5853448", "0x191bbd3588c78488c2f4d122814d5fb34edb8c.95d928#170", "3.027932e11", "0x4.67fe2E+9#22", 63, "5.599350462100540119e44", "0x1.91bbd3588c78488cE+37#63", Less, ); // - following_bits == False && difw <= 0 in add_float_significands_same_prec_general test( "7184368264698708563285024670194469326968686224.86386349506591", "0x1422880c600dc4fd90a02f1814859aafd658690.dd2628738430#198", "1.0296060328202e-24", "0x1.3ea5cb49bdaE-20#44", 61, "7.184368264698708565e45", "0x1.422880c600dc4feE+38#61", Greater, ); // - following_bits == False && x != 0 in add_float_significands_same_prec_general test( "19710666.821984898059985706849", "0x12cc2ca.d26d9a2ef9396c5108#94", "7.0e4", "0x1.0E+4#2", 61, "19776202.82198489807", "0x12dc2ca.d26d9a2f0#61", Greater, ); // - round_bit != Uninitialized first time in add_float_significands_same_prec_general test( "2.3370796820961060045359802932823709e39", "0x6.de392c9978b4267553b428865de8E+32#112", "1.187719715482312494e-58", "0xb.edbf4827e1e28aaE-49#64", 63, "2.3370796820961060044e39", "0x6.de392c9978b4267E+32#63", Less, ); // - difw > ys_len in add_float_significands_same_prec_general // - difw > ys_len || goto_c_read in add_float_significands_same_prec_general // - following_bits != Uninitialized second time in add_float_significands_same_prec_general // - following_bits == False second time in add_float_significands_same_prec_general // - xs[xi] != 0 in add_float_significands_same_prec_general test( "1248577957.9617995883835430866672787859939813175787209064549678049868", "0x4a6bc9a5.f6387f7169e05140ece8db047baba25ac8c576b8fed10fa4#221", "1.65314121012e-6", "0x0.00001bbc2ffb9e#36", 126, "1248577957.96180124152475320394882420796", "0x4a6bc9a5.f6389b2d99dbef40ece8db04#126", Less, ); // - x < y in add_float_significands_same_prec_general // - following_bits == False first time in add_float_significands_same_prec_general // - round_bit != False or not other condition in add_float_significands_same_prec_general test( "1.85445e-25", "0x3.9648E-21#15", "1.2975739042614492272769355049909712560463719657882671587557999636387971206e-6", "0x0.000015c509987b7b0dbb1bf2aae59a4afde515d3ec2c3af539738e362659e1f1b0#243", 62, "1.2975739042614492276e-6", "0x0.000015c509987b7b0dbb8#62", Greater, ); // - following_bits == Uninitialized second time in add_float_significands_same_prec_general // - round_bit == Uninitialized third time in add_float_significands_same_prec_general // - following_bits != False second time in add_float_significands_same_prec_general test( "1.3111820218254081035114504135472568116036464005e-6", "0x0.000015ff7be10e865ada82cd25acef5baa9c89c25f4#152", "2.51465891601e-20", "0x7.6c05c64a8E-17#38", 128, "1.311182021825433250100610518712675662596e-6", "0x0.000015ff7be10e86d19adf31cdacef5baa9c8#128", Less, ); // - following_bits == False || x == Limb::MAX second time in // add_float_significands_same_prec_general // - !goto_c_read in add_float_significands_same_prec_general // - following_bits != False || yi < 0 in add_float_significands_same_prec_general test( "7.9999999999995452526491135358810425", "0x7.ffffffffff800000000000000000#114", "0.0039062797764", "0x0.0100007fe38#34", 49, "8.00390627977595", "0x8.0100007fe300#49", Equal, ); // - following_bits != False first time in add_float_significands_same_prec_general test( "2.89901505570589585435e-11", "0x1.fe0007ffc00000000E-9#67", "134217728.00000381469725", "0x8000000.00003ffffffc#74", 51, "134217728.0000038", "0x8000000.000040#51", Less, ); // - yi < 0 second time in add_float_significands_same_prec_general; // - goto_c_read in add_float_significands_same_prec_general test( "4.4474794e-47", "0x4.0ffff0E-39#25", "7.523135146670945963453530822847271532226579417449854573285752516755e-37", "0xf.fffc000001fffffffffffffffffffffffffffc03fffffffc001ffeE-31#219", 57, "7.52313514711569391e-37", "0xf.fffc000411fff0E-31#57", Greater, ); // - round_bit == False and other condition in add_float_significands_same_prec_general test( "1048575.9999999999999999965", "0xfffff.ffffffffffffffc0#81", "1.1102230204892534781399170051165479471979625e-16", "0x7.ffffff800000003ffe000001fffffffc0000E-14#145", 48, "1048576.0", "0x100000.0000000#48", Less, ); // - x == Limb::MAX first time in add_float_significands_same_prec_general // - xi != 0 in add_float_significands_same_prec_general test( "3.810971975326539e-6", "0x0.00003ff00000000004#52", "4.90398573077084434674671048688098938757996518e55", "0x1.ffffffffffffffffffffffffffffffffffffeE+46#148", 21, "4.903986e55", "0x2.00000E+46#21", Greater, ); // - xs[xi] == 0 in add_float_significands_same_prec_general test( "135.998", "0x87.ff8#19", "8796093087743.998046875", "0x8000000ffff.ff80000000000000000000000000000#168", 114, "8796093087879.99609375", "0x80000010087.ff0000000000000000#114", Equal, ); // - following_bits == False && yi >= 0 in add_float_significands_same_prec_general // - exp_diff_rem != 0 && y_prec << (Limb::WIDTH - exp_diff_rem) != 0 in // add_float_significands_same_prec_general test( "4610525002867933183.9999999999998", "0x3ffbe00fffffffff.ffffffffffc#104", "2.27373688992450493e-13", "0x4.000003ffc00000E-11#58", 47, "4.61052500286793e18", "0x3.ffbe01000000E+15#47", Less, ); // - exp_diff_rem == 0 first time in add_float_significands_same_prec_general test( "199484.9246647061832808582", "0x30b3c.ecb6d380d2988d78#79", "9.2945767606483e-15", "0x2.9dbeadc4568E-12#45", 63, "199484.92466470618328", "0x30b3c.ecb6d380d298#63", Less, ); // - exp_diff_rem == 0 || y_prec << (Limb::WIDTH - exp_diff_rem) == 0 in // add_float_significands_same_prec_general // - difw <= ys_len && !goto_c_read in add_float_significands_same_prec_general test( "128.000244140566792339087", "0x80.000fffffc00000000#75", "7.5", "0x7.800000000000000000000#87", 60, "135.5002441405667923", "0x87.800fffffc0000#60", Equal, ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general // - yi != 0 first time in add_float_significands_same_prec_general test( "127.9999999999999997744859485366053840029607161188794193511", "0x7f.ffffffffffffefc000007fffffffffff0000000001e000#190", "64.0000000000000000000000000000000000000000000000410536659471", "0x40.000000000000000000000000000000000000003c000000008#200", 90, "191.9999999999999997744859485", "0xbf.ffffffffffffefc000008#90", Greater, ); // - following_bits == False || x == Limb::MAX first time in // add_float_significands_same_prec_general test( "1927941831.98168915743", "0x72ea0ec7.fb4ffb0a0#65", "10702647.0", "0xa34f37.0#24", 63, "1938644478.9816891574", "0x738d5dfe.fb4ffb0a#63", Equal, ); // - round_bit == Uninitialized sixth time in add_float_significands_same_prec_general test( "8.69134330408049e-16", "0x3.ea0b2d4be674E-13#48", "15492.756587362761273446", "0x3c84.c1afb59ba066160#71", 128, "15492.75658736276127431557748582959734014", "0x3c84.c1afb59ba06654a0b2d4be6740000#128", Equal, ); // - ys[yi] != 0 in add_float_significands_same_prec_general test( "2.384181243542116135358810424804687500000000000000000024885983948e-7", "0x3.ffff8000000000000000000000000000000000000003ffc00000E-6#210", "1.5", "0x1.8000000000000000000#75", 55, "1.50000023841812435", "0x1.800003ffff8000#55", Less, ); // - x == Limb::MAX second time in add_float_significands_same_prec_general test( "98079714615416886934934209737619787751599303785390800896.0002441405", "0x3fffffffffffffffffffffffffffffffffffff800000000.000fffff8#219", "5.8207660907e-11", "0x3.fffffffe0E-9#35", 63, "9.807971461541688693e55", "0x4.000000000000000E+46#63", Greater, ); // - xi == 0 in add_float_significands_same_prec_general test( "2.996272864212510369e-95", "0x3.fffffff00000000E-79#60", "1.49012180372665170580148696899414062499e-8", "0x4.0000fffffffffffffffffffffffffff8E-7#128", 27, "1.4901218e-8", "0x4.000100E-7#27", Greater, ); // - x < y and other conditions in add_float_significands_same_prec_general test( "0.00024414062499999999999999979805160826342", "0x0.000ffffffffffffffffffff00000000000#124", "1.32348897761965396e-23", "0xf.ffffff80000008E-20#57", 63, "0.000244140625", "0x0.0010000000000000000#63", Less, ); // - ys[yi] == 0 in add_float_significands_same_prec_general test( "0.99951171875", "0x0.ffe00000000000000000000#92", "0.017578124999996447286321199499070644378662109375", "0x0.047fffffffff00000000000000000000000000000000000000000000#217", 48, "1.01708984375", "0x1.046000000000#48", Greater, ); // - yi == 0 first time in add_float_significands_same_prec_general test( "67108864.000000000000000000027105054312137610850186320021748542784370058", "0x4000000.00000000000000007ffffffffffffffffffffffffffffff800000#236", "3.63797880709171295166015625e-12", "0x4.000000000000000000000E-10#86", 103, "67108864.0000000000036379788342", "0x4000000.0000000004000000800#103", Greater, ); test( "3.91923414751995775967065104797896464447978457860112833061347e-17", "0x2.d2f8998a5fa796b9de129923cf4d51e04f27e6b6a368fadb0E-14#197", "2.75164948336014612968759798085025748008e-17", "0x1.fb96f911d37dd9fe4933cbeee25d7ddeE-14#128", 8, "6.68e-17", "0x4.d0E-14#8", Greater, ); test( "-too_small", "-0x2.50888E-268435456#19", "too_small", "0x3.10E-268435456#10", 1, "too_small", "0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x3.10E-268435456#10", "too_small", "0x2.50888E-268435456#19", 1, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn add_prec_fail() { assert_panic!(Float::NAN.add_prec(Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.add_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.add_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.add_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_add_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_round(y.clone(), rm); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_round_assign(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_round_assign_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); // Note different behavior for Floor test( "0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); // - (round_bit != 0 || sticky_bit == 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "2.0", "0x2.0#1", Less, ); // - (round_bit != 0 || sticky_bit == 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_lt_w // - (rm == Ceiling || rm == Up) && sum == 0 in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); // - (rm == Ceiling || rm == Up) && sum != 0 in add_float_significands_same_prec_lt_w test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Exact, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Exact, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); // Note different behavior for Floor test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp == y_exp in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "2.0", "0x2.0#1", Equal, ); // - rm == Nearest && sum != 0 in add_float_significands_same_prec_lt_w test( "1.0", "0x1.0#3", "1.8", "0x1.c#3", Nearest, "3.0", "0x3.0#3", Greater, ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_lt_w test( "7.7e14", "0x2.bcE+12#8", "1.237e-9", "0x5.50E-8#8", Nearest, "7.7e14", "0x2.bcE+12#8", Less, ); // - shift <= exp_diff < Limb::WIDTH in add_float_significands_same_prec_lt_w // - shift <= exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_lt_w test( "1.852193494e22", "0x3.ec137baE+18#29", "241425944.0", "0xe63de18.0#29", Nearest, "1.852193494e22", "0x3.ec137baE+18#29", Less, ); test( "1.999999999999993", "0x1.fffffffffffe#48", "5.96046447753906e-8", "0x1.000000000000E-6#48", Nearest, "2.00000005960464", "0x2.000001000000#48", Greater, ); // - in add_float_significands_same_prec_w // - x_exp == y_exp in add_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "2.0", "0x2.0000000000000000#64", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_w // - !overflow in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", Nearest, "3.0", "0x3.0000000000000000#64", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_w test( "2.0", "0x2.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "3.0", "0x3.0000000000000000#64", Equal, ); // - (round_bit != 0) || (sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_w // - round_bit == 0 || (sticky_bit == 0 && (sum & 1) == 0) in add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "2.0", "0x2.0000000000000000#64", Less, ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) in add_float_significands_same_prec_w // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and !overflow in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000003", "0x1.0000000000000006#64", Nearest, "2.0000000000000000004", "0x2.0000000000000008#64", Greater, ); // - exp_diff >= Limb::WIDTH in add_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", Nearest, "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", Less, ); // - overflow in add_float_significands_same_prec_w test( "0.00022185253582909293959", "0x0.000e8a1162cbb1a4265#64", "0.000029745661521717034001", "0x0.0001f30ca4b8117ff0a0#64", Nearest, "0.0002515981973508099736", "0x0.00107d1e0783c324170#64", Greater, ); // - round_bit != 0 && (sticky_bit != 0 || (sum & 1) != 0) and overflow in // add_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", Nearest, "128.0", "0x80.00000000000000#64", Greater, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_w // - (round_bit != 0) || (sticky_bit != 0) && (rm == Floor || rm == Down) && sum != 0 in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Down, "2.0", "0x2.0000000000000000#64", Less, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_w // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum != 0 in // add_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Up, "2.0000000000000000002", "0x2.0000000000000004#64", Greater, ); // - (round_bit != 0) || (sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum == 0 in // add_float_significands_same_prec_w test( "536870911.99999999997", "0x1fffffff.ffffffffe#64", "1.00974195868289511071e-28", "0x7.ffffffffffffffe0E-24#64", Up, "536870912.0", "0x20000000.000000000#64", Greater, ); // - in add_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in add_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "2.0", "0x2.0000000000000000#65", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", Nearest, "3.0", "0x3.0000000000000000#65", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "3.0", "0x3.0000000000000000#65", Equal, ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in add_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (sum_0 != 0 || sum_1 != 0) in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "2.0", "0x2.0000000000000000#65", Less, ); // - rm == Nearest && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", Nearest, "2.0000000000000000002", "0x2.0000000000000004#65", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", Nearest, "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Less, ); // - exp_diff >= Limb::WIDTH * 2 in add_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", Nearest, "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", Less, ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", Nearest, "372369974082165972922376.05178046858", "0x4eda377c7f0d747ff008.0d417c1b20#116", Less, ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_w_lt_2w test( "18.492649216180435830000529", "0x12.7e1e424fe51f1bb914c0#85", "56.637589789906471403844847", "0x38.a339159fe96c1722fdfe#85", Nearest, "75.130239006086907233845378", "0x4b.215757efce8b32dc12c0#85", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_w_lt_2w test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", Nearest, "256.0", "0x100.0000000000000000000000000#107", Less, ); // - rm == Nearest && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "0.0000610351562499999999996", "0x0.0003ffffffffffffffff8#67", "17179869183.9999389648", "0x3ffffffff.fffc00000#67", Nearest, "17179869184.0", "0x400000000.00000000#67", Greater, ); // - rm == Floor || rm == Down in add_float_significands_same_prec_gt_w_lt_2w // - (rm == Floor || rm == Down) && (sum_0 != 0 || sum_1 != 0) in // add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Floor, "2.0", "0x2.0000000000000000#65", Less, ); // - rm == Ceiling || rm == Up in add_float_significands_same_prec_gt_w_lt_2w // - rm == Ceiling || rm == Up && sum_1 != 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Ceiling, "2.0000000000000000001", "0x2.0000000000000002#65", Greater, ); // - rm == Ceiling || rm == Up && sum_1 == 0 in add_float_significands_same_prec_gt_w_lt_2w test( "1.9999999999999999999999998", "0x1.ffffffffffffffffffffc#83", "2.4074118565121938372272894e-35", "0x1.fffff8000000007fffff8E-29#83", Ceiling, "2.0", "0x2.000000000000000000000#83", Greater, ); // - in add_float_significands_same_prec_2w // - x_exp == y_exp in add_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "2.0", "0x2.00000000000000000000000000000000#128", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_2w // - exp_diff < TWICE_WIDTH && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", Nearest, "3.0", "0x3.00000000000000000000000000000000#128", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_2w test( "2.0", "0x2.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "3.0", "0x3.00000000000000000000000000000000#128", Equal, ); // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_2w // - rm == Nearest in add_float_significands_same_prec_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (sum_0 & 1) == 0)) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Nearest, "2.0", "0x2.00000000000000000000000000000000#128", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (sum_0 & 1) != 0) in // add_float_significands_same_prec_2w // - rm == Nearest && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", Nearest, "2.00000000000000000000000000000000000002", "0x2.00000000000000000000000000000008#128", Greater, ); // - exp_diff >= TWICE_WIDTH in add_float_significands_same_prec_2w // - exp_diff > TWICE_WIDTH in add_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", Nearest, "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", Less, ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in add_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", Nearest, "4354249796990942.35435357606921728525736", "0xf782ac869b7de.5ab6ea7c701c9acb1b1#128", Less, ); // - exp_diff == TWICE_WIDTH in add_float_significands_same_prec_2w test( "15732412727332569995335732833027757624.44", "0xbd5f3d586bc01069a1d94f5ab5a1638.7#128", "0.0373708302820085888760745841639896128921", "0x0.0991227de2b63edc67164401ce8ebdb04#128", Nearest, "15732412727332569995335732833027757624.5", "0xbd5f3d586bc01069a1d94f5ab5a1638.8#128", Greater, ); // - Limb::WIDTH == exp_diff in add_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", Nearest, "148.054913367700296555095560478615943812", "0x94.0e0ecd6e62d0a98ad7d520e1456fe0#128", Greater, ); // - exp_diff < TWICE_WIDTH && overflow in add_float_significands_same_prec_2w test( "990.890284854484258981204316304960898664", "0x3de.e3e9b54e224e900a8701c94cea27bc#128", "111.972242543885876168914754084523121772", "0x6f.f8e4e329c509f04b7f9497ec8ce6438#128", Nearest, "1102.862527398370135150119070389484020437", "0x44e.dcce9877e758805606966139770e00#128", Greater, ); // - rm == Nearest && overflow in add_float_significands_same_prec_2w test( "1152920954851033088.0", "0xfffff8000000000.00000000000000000#128", "549755813887.999999999999999999999999998", "0x7fffffffff.ffffffffffffffffffffff8#128", Nearest, "1152921504606846976.0", "0x1000000000000000.00000000000000000#128", Greater, ); // - rm == Floor || m == Down in add_float_significands_same_prec_2w // - (rm == Floor || m == Down) && (sum_0 != 0 || sum_1 != 0) in // add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Floor, "2.0", "0x2.00000000000000000000000000000000#128", Less, ); // - rm == Ceiling || m == Up in add_float_significands_same_prec_2w // - (rm == Ceiling || m == Up) && !overflow in add_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Ceiling, "2.00000000000000000000000000000000000001", "0x2.00000000000000000000000000000004#128", Greater, ); // - (rm == Ceiling || m == Up) && overflow in add_float_significands_same_prec_2w test( "69631.9999999850988390281969486491823076", "0x10fff.ffffffc000000ffffffff80007fc#128", "1.255420347077336152767157884641533283217e58", "0x1.fffffffffffffffffffffffffffffffeE+48#128", Ceiling, "1.25542034707733615276715788464153328322e58", "0x2.00000000000000000000000000000000E+48#128", Greater, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum_2 != 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Up, "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", Greater, ); test( "9903517953099800764370386944.0000000000291038304566", "0x1fffff800000000000000000.000000001fffffffff8#166", "1.68499666669691498716668845382709804457445989930032e66", "0x1.0000000000000000000001fff80000000000000000E+55#166", Up, "1.68499666669691498716668845382709804458436341725346e66", "0x1.0000000000000000000001fff8000001fffff80008E+55#166", Greater, ); // - in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && !overflow in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit != 0 || sticky_bit != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && (round_bit == 0 || (sticky_bit == 0 // && (sum_0 & shift_bit) == 0)) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w // - x_exp > y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "3.0", "0x3.00000000000000000000000000000000#129", Less, ); // - x_exp < y_exp in add_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "2.0", "0x2.00000000000000000000000000000000#129", Nearest, "3.0", "0x3.00000000000000000000000000000000#129", Less, ); // - x_exp == y_exp in add_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "2.0", "0x2.00000000000000000000000000000000#129", Equal, ); // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) in add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum != 0 in add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Nearest, "2.000000000000000000000000000000000000012", "0x2.00000000000000000000000000000004#129", Greater, ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 < exp_diff < Limb::WIDTH * 3 in // add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Nearest, "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Less, ); // - exp_diff >= Limb::WIDTH * 3 in add_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", Nearest, "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", Less, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && !overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", Nearest, "978.49328809934495391839923652526678587611222", "0x3d2.7e4820fe314caadcbba75ebc3b0b3d718f#146", Less, ); // - exp_diff < Limb::WIDTH && overflow in add_float_significands_same_prec_gt_2w_lt_3w test( "4499918.46219262840948309077470961400786337", "0x44a9ce.7652418f789422bc22220831e2030#137", "64560208.0262619516023687759351781439347886", "0x3d91c50.06b91a6f42e5205070f82f89eefa#137", Nearest, "69060126.488454580011851866709887757942652", "0x41dc61e.7d0b5bfebb79430c931a37bbd0fc#137", Less, ); // - exp_diff == Limb::WIDTH * 2 in add_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", Nearest, "563971925627753843356041629019151473019479982637.25", "0x62c960337e963a378ba6626ea422d8a633b5022d.40#165", Less, ); // - exp_diff == Limb::WIDTH in add_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", Nearest, "4262448175090788889679.91469733230924119", "0xe71159efd3a67e744f.ea299ab801b2d60#130", Less, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w test( "1180591620717411303423.999999999999999999999999997", "0x3fffffffffffffffff.ffffffffffffffffffffff#158", "5.68434188616351954822429632036496545806324230121e-14", "0x1.000000000fffffffffffe0000000000000000038E-11#158", Nearest, "1180591620717411303424.00000000000005684341886163", "0x400000000000000000.00000000001000000000fe#158", Less, ); // - Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 && overflow in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && rm == Nearest && round_bit != 0 && (sticky_bit != 0 // || (sum_0 & shift_bit) != 0) && sum == 0 test( "4503599627370495.9999999999999999999999999996", "0xfffffffffffff.ffffffffffffffffffffffe#143", "3.3087224509824797385046520537834728287650668e-24", "0x4.00000003ffff0000000000000000fffffffE-20#143", Nearest, "4503599627370496.000000000000000000000003309", "0x10000000000000.00000000000000000004000#143", Greater, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Floor || rm == Down) in // add_float_significands_same_prec_gt_2w_lt_3w // - (round_bit != 0 || sticky_bit != 0) && (rm == Floor || rm == Down) && sum != 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Down, "2.0", "0x2.00000000000000000000000000000000#129", Less, ); // - (round_bit != 0 || sticky_bit != 0) && (rm == Ceiling || rm == Up) && sum_2 == 0 in // add_float_significands_same_prec_gt_2w_lt_3w test( "18014398509481983.9999999999999999999999999999999998", "0x3fffffffffffff.ffffffffffffffffffffffffffff#166", "9.6296497219361792652798897129246365926905082410768e-35", "0x7.ffffffffffffffffffffffffffffffffffffffffeE-29#166", Up, "18014398509481984.0", "0x40000000000000.0000000000000000000000000000#166", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) in // add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && round_bit == 0 && sticky_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Up, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - in add_float_significands_same_prec_ge_3w // - exp_diff == 0 in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && round_bit == 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Equal, ); // - x_exp < y_exp in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec in add_float_significands_same_prec_ge_3w // - in add_significands_rsh_to_out // - exp_diff < Limb::WIDTH in add_significands_rsh_to_out // - 0 < exp_diff < prec && shift == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && limb == 0 in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - x_exp > y_exp in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - 0 < exp_diff < prec && shift != 0 in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "2.0", "0x2.000000000000000000000000000000000000000000000000#193", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#193", Equal, ); // - exp_diff == 0 && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit == 0 in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Less, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && sticky_bit == 0 && out[0] & // shift_bit == 0 in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Less, ); // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 in // add_float_significands_same_prec_ge_3w // - exp_diff == 0 && rm == Nearest && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", Nearest, "2.0000000000000000000000000000000000000000000000000000000013", "0x2.000000000000000000000000000000000000000000000008#192", Greater, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", Nearest, "3.0000000000000000000000000000000000000000000000000000000013", "0x3.000000000000000000000000000000000000000000000008#192", Greater, ); // - exp_diff >= Limb::WIDTH in add_significands_rsh_to_out // - exp_diff >= Limb::WIDTH && r != 0 in add_significands_rsh_to_out test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", Nearest, "3.5123473778825578959041500899351426183100429740785046308614e-27", "0x1.1646de419a6dbd3471970441a59a8d2474f195e0f288088aa8E-22#198", Greater, ); // - exp_diff >= prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Nearest || rm == Floor // || rm == Down) test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", Nearest, "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", Less, ); // - 0 < exp_diff < prec && limb != 0 in add_float_significands_same_prec_ge_3w test( "8.699772042374378140693728074838279708562673799416097107796", "0x8.b32442b4a730454d66b1b2bdf7a2863d417e6ff22d7f6c58#193", "7.5897463681962395437740598844462353563682906392115908083148", "0x7.96f99e34566e7be1960d023e431dc5e0a7ad24ad691a1ac4#193", Nearest, "16.289518410570617684467787959284515064930964438627687916112", "0x10.4a1de0e8fd9ec12efcbeb4fc3ac04c1de92b949f9699872#193", Greater, ); // - exp_diff >= Limb::WIDTH && r == 0 in add_significands_rsh_to_out test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", Nearest, "1476808010161862576835936576709144.797568704117653151104618", "0x48cff00a780a50d34bb694ada218.cc2d766c7f9881c2afc48#192", Less, ); // - exp_diff == prec in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest in add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && power && !carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power in add_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", Nearest, "1174582238252884689829665592721065057.76655867827770290150729", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d8#194", Greater, ); // - 0 < exp_diff < prec && rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & // shift_bit != 0) && carry in add_float_significands_same_prec_ge_3w test( "4.336808689942017736029811203479766845699938816177735095446e-19", "0x7.fffffffffffffffffffffffffffffffe0000000000000000E-16#192", "5192296858534827628530496329220095.999999999999999999566319", "0xffffffffffffffffffffffffffff.fffffffffffffff80000#192", Nearest, "5192296858534827628530496329220096.0", "0x10000000000000000000000000000.00000000000000000000#192", Greater, ); // - exp_diff == prec && rm == Nearest && power && carry in // add_float_significands_same_prec_ge_3w // - exp_diff == prec && rm == Nearest && !power && carry in // add_float_significands_same_prec_ge_3w test( "158456325028528675187087900671.99999999999999999999999999997", "0x1ffffffffffffffffffffffff.fffffffffffffffffffffffe#192", "2.5243548967072377773175314089049159349542605923488736152645e-29", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-24#192", Nearest, "158456325028528675187087900672.0", "0x2000000000000000000000000.000000000000000000000000#192", Greater, ); // - exp_diff == prec && rm == Nearest && power in add_float_significands_same_prec_ge_3w test( "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", "2.6469779601696885595885078146238811314105987548828125e-23", "0x2.000000000000000000000000000000000000000000000000E-19#192", Nearest, "332306998926888516295359133097394175.99999997019767761230469", "0x3ffffffff0007fffffffffffffffff.ffffff8000000000000#192", Less, ); // - 0 < exp_diff < prec && (rm == Floor || rm == Down || rm == Exact) in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Down, "3.0", "0x3.000000000000000000000000000000000000000000000000#192", Equal, ); // - exp_diff == 0 && (rm == Floor || rm == Down) in add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Down, "2.0", "0x2.000000000000000000000000000000000000000000000000#192", Less, ); // - exp_diff == 0 && (rm == Ceiling || rm == Up) in add_float_significands_same_prec_ge_3w // - exp_diff == 0 && (rm == Ceiling || rm == Up) && !carry in // add_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Up, "2.0000000000000000000000000000000000000000000000000000000006", "0x2.000000000000000000000000000000000000000000000004#192", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // in add_float_significands_same_prec_ge_3w // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // && !carry in add_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Up, "3.0000000000000000000000000000000000000000000000000000000006", "0x3.000000000000000000000000000000000000000000000004#192", Greater, ); // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) && // !carry test( "6823.472967851766873629348006893003460678376513514025568927", "0x1aa7.79146bcf65e9c10b73dc31b712bdbba94db27f42827ee#192", "3.4171243258195824440860481554099490634319461554553884152664e-68", "0xe.bd75c60b3fb1b2daadd125b174611af23cd95ed37b18fd3E-57#192", Up, "6823.472967851766873629348006893003460678376513514025568928", "0x1aa7.79146bcf65e9c10b73dc31b712bdbba94db27f42827f0#192", Greater, ); // - exp_diff == prec && (rm == Ceiling || rm == Up) in add_float_significands_same_prec_ge_3w // - exp_diff == prec && (rm == Ceiling || rm == Up) && !carry in // add_float_significands_same_prec_ge_3w test( "1.1549982013361157285883413763473468330143594437077681839568e-64", "0xc.29de762f7d1efb4e2c76c8e4086645c726cd7efd160d9b2E-54#192", "7.183764682683218761534928278745259569270911336851315880289e-7", "0xc.0d6747ace11077b45ef60fe0663937937659be6facba820E-6#192", Up, "7.183764682683218761534928278745259569270911336851315880291e-7", "0xc.0d6747ace11077b45ef60fe0663937937659be6facba821E-6#192", Greater, ); // - exp_diff == prec && (rm == Floor || rm == Down) in add_float_significands_same_prec_ge_3w test( "1.633185017652497317802829911277029120405335932425346213043e-62", "0x6.b7f1cf4acb21f3fca0c966202fee44bb9bb293511aa1d780E-52#192", "0.00010303969992625256008619861293450462215178250710705317873879", "0x0.0006c0b8243103d1ef7ab2f1e9a66ec9ee623a5e72e237199db8#192", Floor, "0.00010303969992625256008619861293450462215178250710705317873879", "0x0.0006c0b8243103d1ef7ab2f1e9a66ec9ee623a5e72e237199db8#192", Less, ); // - exp_diff > prec in add_float_significands_same_prec_ge_3w && (rm == Ceiling || rm == Up) && // carry test( "2.3509707655716138708899159999241985031053943929132983433321e-38", "0x7.fffc0007ffffffff0000000007ffffffffffffffffffffffE-32#195", "2.15679573337205118357336120696157045389097155380324579848825e68", "0x7.ffffffffffffffffffffffffffffffffffffffffffffffffE+56#195", Up, "2.1567957333720511835733612069615704538909715538032457984883e68", "0x8.000000000000000000000000000000000000000000000000E+56#195", Greater, ); // - 0 < exp_diff < prec && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) // && carry in add_float_significands_same_prec_ge_3w test( "8388607.9999999995343387126922607421875", "0x7fffff.fffffffe00000000000000000000000000000000000#192", "4.6566128730773925781249999999999999999999999999999999999993e-10", "0x1.fffffffffffffffffffffffffffffffffffffffffffffffeE-8#192", Up, "8388608.0", "0x800000.000000000000000000000000000000000000000000#192", Greater, ); // - exp_diff == prec && (rm == Ceiling || rm == Up) && carry in // add_float_significands_same_prec_ge_3w test( "511.9999999999999999999999999999999999999999999999999999999", "0x1ff.fffffffffffffffffffffffffffffffffffffffffffffe#192", "8.156630584998155601789981346010670828251902552640272418926e-56", "0x1.ffffffffffffff00001ffffffffffffff80003f003000000E-46#192", Up, "512.0", "0x200.0000000000000000000000000000000000000000000000#192", Greater, ); // - rm == Floor || rm == Down in add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less, ); // - rm == Ceiling || rm == Up in add_float_significands_same_prec_general_round // - (rm == Ceiling || rm == Up) && !carry in add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Up, "3.0", "0x3.0#2", Greater, ); // - (rm == Ceiling || rm == Up) && carry in add_float_significands_same_prec_general_round test( "2.0", "0x2.0#1", "1.5", "0x1.8#2", Up, "4.0", "0x4.0#2", Greater, ); // - shift2 == 0 in add_float_significands_same_prec_general // - y in add_float_significands_same_prec_general // - shift != 0 in add_float_significands_same_prec_general // - x == 0 first time in add_float_significands_same_prec_general // - shift == 0 || following_bits != Uninitialized in add_float_significands_same_prec_general // - round_bit != Uninitialized || shift == 0 in add_float_significands_same_prec_general // - exp_diff_rem == 0 && yi == 0 second time in add_float_significands_same_prec_general // - round_bit != Uninitialized sixth time in add_float_significands_same_prec_general test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Nearest, "2.0", "0x2.0#2", Equal, ); // - following_bits != False || round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False in add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit == 0 in // add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "2.0", "0x2.0#2", Less, ); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && carry in // add_float_significands_same_prec_general_round test( "2.0", "0x2.0#1", "1.5", "0x1.8#2", Nearest, "4.0", "0x4.0#2", Greater, ); // - rm == Nearest && following_bits == False && out[0] & shift_bit != 0 && !carry in // add_float_significands_same_prec_general_round test( "1.0", "0x1.0#1", "1.8", "0x1.c#3", Nearest, "3.0", "0x3.0#3", Greater, ); // - x != 0 && x != mask second time in add_float_significands_same_prec_general // - rm == Nearest && following_bits != False && round_bit != False in // add_float_significands_same_prec_general_round // - rm == Nearest && following_bits != False && round_bit != False && !carry in // add_float_significands_same_prec_general_round test( "1.5", "0x1.8#2", "4.0", "0x4.0#1", Nearest, "6.0", "0x6.0#2", Greater, ); // - rm == Nearest && following_bits != False && round_bit == False in // add_float_significands_same_prec_general_round test( "4.0", "0x4.0#1", "1.2", "0x1.4#3", Nearest, "5.0", "0x5.0#3", Less, ); // - x != 0 && x != mask first time in add_float_significands_same_prec_general // - shift != 0 && following_bits == Uninitialized in add_float_significands_same_prec_general test( "1.2", "0x1.4#3", "3.0", "0x3.0#2", Nearest, "4.0", "0x4.0#3", Less, ); // - rm == Nearest && following_bits != False && round_bit != False && carry in // add_float_significands_same_prec_general_round test( "1.8", "0x1.c#3", "6.0", "0x6.0#2", Nearest, "8.0", "0x8.0#3", Greater, ); // - out_bits <= exp_diff in add_float_significands_same_prec_general // - out_len <= xs_len first time in add_float_significands_same_prec_general // - difw > 0 && difw > ys_len && exp_diff > out_bits in // add_float_significands_same_prec_general // - round_bit != Uninitialized fifth time in add_float_significands_same_prec_general test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", Nearest, "9.75459983374e122", "0x1.79c17f063aE+102#40", Less, ); // - out_len > xs_len first time in add_float_significands_same_prec_general test( "2.8577648979177105962332201291018926848163080599637e-19", "0x5.458a93bffa7b1c05bdd1c0552b60196746d9083cE-16#162", "3.569720699507868e50", "0xf.4400d3acf388E+41#51", Nearest, "3.5697206995078675404584127554321345196383736430592e50", "0xf.4400d3acf3880000000000000000000000000000E+41#162", Less, ); // - overlap > ys_len in add_float_significands_same_prec_general // - out_len - k > overlap in add_float_significands_same_prec_general // - difw <= 0 || difw <= ys_len in add_float_significands_same_prec_general // - round_bit != Uninitialized fourth time in add_float_significands_same_prec_general test( "29780282551.762684458936866363165", "0x6ef0b0cb7.c33f49e84d21bb6040#104", "0.00003945598947538", "0x0.000295f62f36adb#46", Nearest, "29780282551.762723914926341743141", "0x6ef0b0cb7.c341dfde7c58691040#104", Equal, ); // - out_len > xs_len second time in add_float_significands_same_prec_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", Nearest, "0.00374222829424688982311482391965285", "0x0.00f5402c235119eafa12eb9821602#107", Greater, ); // - exp_diff_rem == 0 second time in add_float_significands_same_prec_general test( "5.19192095203e-15", "0x1.761e097c5E-12#37", "7.4e4", "0x1.2E+4#5", Nearest, "73728.0", "0x12000.00000#37", Less, ); // - shift <= 1 in add_float_significands_same_prec_general test( "15135.895602865542606017656527713819177465060416097749360065", "0x3b1f.e5463ab9b599ce49b83c7988b324dc93ce50b2ed51a18#191", "3.581529624499970047886732225242180736649e-8", "0x9.9d355ad2b99a587727da095fa3226bf0E-7#130", Nearest, "15135.895602901357902262656228192686499717482223464235884113", "0x3b1f.e5463b5388ef7b7551e200fb30c5728e007771ed51a18#191", Equal, ); // - round_bit == Uninitialized fourth time in add_float_significands_same_prec_general // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "8.63643735016344467819174862798332593462e-6", "0x0.000090e5374a001358c6606f968bf3813ad9#128", "1.84904e-8", "0x4.f6a6E-7#18", Nearest, "8.65492771851100147411665059026359937212e-6", "0x0.00009134a1aa001358c6606f968bf3813ad9#128", Equal, ); // - round_bit == Uninitialized fifth time in add_float_significands_same_prec_general test( "2.389545997e25", "0x1.3c40f7bE+21#29", "0.078263259824284000402", "0x0.14090f9d6c745bc06#64", Nearest, "2.389545996756557709e25", "0x1.3c40f7b000000000E+21#64", Less, ); // - round_bit == Uninitialized seventh time in add_float_significands_same_prec_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", Nearest, "5.7505517053731436845e-7", "0x9.a5d7d8bbfd3d47dE-6#64", Equal, ); // - x != 0 && x == mask second time in add_float_significands_same_prec_general // - xs_len <= out_len && following_bits == True in add_float_significands_same_prec_general test( "1.081090215247020702e-18", "0x1.3f14ddfe22c0634E-15#59", "6.3799657596147e-8", "0x1.12047722d26cE-6#47", Nearest, "6.37996575972280156e-8", "0x1.12047722e65d4dcE-6#59", Less, ); // - shift == 0 in add_float_significands_same_prec_general test( "4.3055451539258443718732375731462554408177909736937057433067e-16", "0x1.f06543668e6018c20c17efed72ff6d3d65a4c5dc9db475b0E-13#192", "1.6388436e-15", "0x7.61754E-13#21", Nearest, "2.0693980969049410047184094732421002104686218250305033868307e-15", "0x9.51da83668e6018c20c17efed72ff6d3d65a4c5dc9db475bE-13#192", Equal, ); // - yi != 0 second time in add_float_significands_same_prec_general test( "2.24181435676546e-16", "0x1.0276ae5de1e8E-13#47", "7.6430700039878539638425372386462404393e-36", "0xa.28cd4cb186f5925ddb0d1ecb9681103E-30#128", Nearest, "2.24181435676546206911083333246297446029e-16", "0x1.0276ae5de1e80000a28cd4cb186f5926E-13#128", Greater, ); // - x != 0 && x == mask first time in add_float_significands_same_prec_general test( "2.1474796e9", "0x7.ffff00E+7#24", "8191.9998788833609", "0x1fff.fff80fffff0#54", Nearest, "2147487743.9998789", "0x80000fff.fff810#54", Greater, ); test( "-too_small", "-0x2.50888E-268435456#19", "too_small", "0x3.10E-268435456#10", Down, "0.0", "0x0.0", Less, ); test( "too_big", "0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", Down, "too_big", "0x4.0E+268435455#1", Less, ); test( "-too_big", "-0x4.0E+268435455#1", "-too_big", "-0x4.0E+268435455#1", Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); } #[test] fn add_round_fail() { assert_panic!(Float::one_prec(1).add_round(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_val_ref(&Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_ref_val(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).add_round_ref_ref(&Float::two_prec(1), Exact)); assert_panic!(parse_hex_string("0x1.0#1").add_round(parse_hex_string("0x0.001#1"), Exact)); assert_panic!( parse_hex_string("0x1.0#1").add_round_val_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_val(parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .add_round(parse_hex_string("0x1.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .add_round_val_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .add_round_ref_val(parse_hex_string("0x1.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .add_round_ref_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .add_round(parse_hex_string("0x1.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .add_round_val_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .add_round_ref_val(parse_hex_string("0x1.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .add_round_ref_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_val_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_ref_val( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").add_round_ref_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_val_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_ref_val( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").add_round_ref_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192").add_round( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_val_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_ref_val( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .add_round_ref_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!(parse_hex_string("0x1.0#1").add_round(parse_hex_string("0x1.8#2"), Exact)); assert_panic!( parse_hex_string("0x1.0#1").add_round_val_ref(&parse_hex_string("0x1.8#2"), Exact) ); assert_panic!({ parse_hex_string("0x1.0#1").add_round_ref_val(parse_hex_string("0x1.8#2"), Exact) }); assert_panic!( parse_hex_string("0x1.0#1").add_round_ref_ref(&parse_hex_string("0x1.8#2"), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.add_round_assign(Float::two_prec(1), Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_round_assign_ref(&Float::two_prec(1), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign(parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign_ref(&parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.add_round_assign(parse_hex_string("0x1.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.add_round_assign_ref(&parse_hex_string("0x1.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.add_round_assign(parse_hex_string("0x1.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.add_round_assign_ref(&parse_hex_string("0x1.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.add_round_assign( parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.add_round_assign_ref( &parse_hex_string("0x1.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.add_round_assign( parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.add_round_assign_ref( &parse_hex_string("0x1.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.add_round_assign( parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.add_round_assign_ref( &parse_hex_string("0x1.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign(parse_hex_string("0x1.8#2"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.add_round_assign_ref(&parse_hex_string("0x1.8#2"), Exact) }); } #[test] fn test_add_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (sum, o) = x.clone().add_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); assert_eq!(o, o_out); let (sum_alt, o_alt) = x.clone().add_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_round_assign(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_prec_round_assign_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o_out); let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); // Note different behavior for Floor test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Floor, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Ceiling, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Down, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Up, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Nearest, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, Exact, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Exact, "0.0", "0x0.0", Equal, ); // - exp_diff_rem == 0 && yi == 0 first time in add_float_significands_same_prec_general test( "0.000487804412841796875000000000000000000000000000000000000000291703841149741293879771765\ 542", "0x0.001ff8000000000000000000000000000000000000000000007800000000001fffffffffffe#288", "0.000488281249999997", "0x0.001fffffffffffc#47", 53, Ceiling, "0.0009760856628417935", "0x0.003ff7ffffffffc2#53", Greater, ); test( "0.000488281249999997", "0x0.001fffffffffffc#47", "0.000487804412841796875000000000000000000000000000000000000000291703841149741293879771765\ 542", "0x0.001ff8000000000000000000000000000000000000000000007800000000001fffffffffffe#288", 53, Ceiling, "0.0009760856628417935", "0x0.003ff7ffffffffc2#53", Greater, ); // - round_bit != Uninitialized third time in add_float_significands_same_prec_general test( "54004143877011445683.03364332940006328475124657021", "0x2ed7542badc5a97b3.089cd9678077bdca8dabe52c#160", "8.0", "0x8.0#1", 127, Up, "54004143877011445691.033643329400063285", "0x2ed7542badc5a97bb.089cd9678077bdd0#127", Greater, ); test( "-1.948077668464e-10", "-0xd.63182fa960E-9#41", "too_big", "0x7.c300ddfc112a6cf2a0bb36cf8E+268435455#100", 3, Up, "Infinity", "Infinity", Greater, ); test( "1.948077668464e-10", "0xd.63182fa960E-9#41", "-too_big", "-0x7.c300ddfc112a6cf2a0bb36cf8E+268435455#100", 3, Up, "-Infinity", "-Infinity", Less, ); test( "too_small", "0x1.08E-268435456#6", "-too_small", "-0x1.0E-268435456#1", 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x1.08E-268435456#6", "too_small", "0x1.0E-268435456#1", 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn add_prec_round_fail() { assert_panic!(Float::one_prec(1).add_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).add_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(Float::one_prec(1).add_prec_round(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_val_ref(&Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_ref_val(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).add_prec_round_ref_ref(&Float::two_prec(1), 1, Exact)); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign(Float::two_prec(1), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_prec_round_assign_ref(&Float::two_prec(1), 1, Exact) }); } #[test] fn test_add_rational() { let test = |s, s_hex, t, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let sum = x.clone() + y.clone(); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = y.clone() + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = y.clone() + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &y + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let sum_alt = &y + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); let mut sum_alt = x.clone(); sum_alt += &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_add_rational( &rug::Float::exact_from(&x), &rug::Rational::from(&y) ))), ComparableFloatRef(&sum) ); let sum_alt = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); }; test("NaN", "NaN", "123", "NaN", "NaN"); test("Infinity", "Infinity", "123", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "123", "-Infinity", "-Infinity"); test("0.0", "0x0.0", "0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "123", "1.0e2", "0x8.0E+1#1"); test("-0.0", "-0x0.0", "123", "1.0e2", "0x8.0E+1#1"); test("0.0", "0x0.0", "1/3", "0.2", "0x0.4#1"); test("-0.0", "-0x0.0", "1/3", "0.2", "0x0.4#1"); test("123.0", "0x7b.0#7", "0", "123.0", "0x7b.0#7"); // - same sign in float_rational_sum_exponent_range test("1.0", "0x1.0#1", "2", "4.0", "0x4.0#1"); test("1.0", "0x1.0#2", "2", "3.0", "0x3.0#2"); test("1.0", "0x1.000#10", "2", "3.0", "0x3.00#10"); test("1.0", "0x1.000#10", "1/3", "1.334", "0x1.558#10"); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", "3.4749259869231266", "0x3.7994bfdddaf86#53", ); // - different signs and log_x_abs.abs_diff(log_y_abs) > 1 in float_rational_sum_exponent_range test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", "2.8082593202564596", "0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", "-2.8082593202564596", "-0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", "-3.4749259869231266", "-0x3.7994bfdddaf86#53", ); test("1.0", "0x1.0#1", "1/50000", "1.0", "0x1.0#1"); // - signs different and x.eq_abs(&y) in add_rational_prec_round test("1.0", "0x1.0#1", "-1", "0.0", "0x0.0"); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", "1.832e180", "0x7.10E+149#10", ); test("1.0", "0x1.0#1", "0", "1.0", "0x1.0#1"); // - o == Equal in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1", "2.0", "0x2.0#1"); // - o != Equal in add_rational_prec_round_assign_helper // - t != 0 in add_rational_prec_round_assign_helper // - small Natural in float_can_round // - err0 > prec && err > prec in float_can_round // - s != Limb::WIDTH first time in float_can_round // - n == 0 in float_can_round // - float_can_round in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1/3", "1.0", "0x1.0#1"); // - large Natural in float_can_round // - n != 0 && tmp != 0 && tmp != mask in float_can_round test( "269104312292334.303", "0xf4bfbaf113ee.4d8#57", "517543599148951977/6042448266342026218192", "269104312292334.303", "0xf4bfbaf113ee.4d8#57", ); // - s == Limb::WIDTH first time in float_can_round test( "1.1595752615776271305e-33", "0x6.055703bef650178E-28#63", "-2457795567751474853961645492284796573970712506001349310379799846240055987994196472114730\ 61298054082441720799/23", "-1.0686067685875977626e106", "-0x1.2a31c100f5e98110E+88#63", ); // - !float_can_round in add_rational_prec_round_assign_helper // - n != 0 && tmp == 0 in float_can_round // - n <= 0 first time in float_can_round // - s != Limb::WIDTH second time in float_can_round // - n > 0 first time in float_can_round // - x == 0 in float_can_round // - x != 0 in float_can_round test( "5.82156e33", "0x1.1f066E+28#20", "8238723/1413731881599214931", "5.82156e33", "0x1.1f066E+28#20", ); // - n != 0 && tmp != 0 && tmp == mask in float_can_round // - n <= 0 second time in float_can_round // - s != Limb::WIDTH third time in float_can_round test( "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", "-3183521742267703581572109801877979/35801077870645726", "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", ); // - s == Limb::WIDTH second time in float_can_round // - n > 0 second time in float_can_round // - x == Limb::MAX in float_can_round test( "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", "-808694/11557016618486698036897716112870533564271922504817764249868611771", "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", ); // - x != Limb::MAX in float_can_round test( "4.9046e10", "0xb.6b5eE+8#19", "-182971083215/47776579472461276067598384651239241670113870043", "4.9046e10", "0xb.6b5eE+8#19", ); // - s == Limb::WIDTH third time in float_can_round test( "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", "-3161/286335616056113777", "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", ); // - err0 <= prec || err <= prec in float_can_round // - different signs and log_x_abs.abs_diff(log_y_abs) <= 1 in float_rational_sum_exponent_range // - different signs and log_x_abs.abs_diff(log_y_abs) == 1 in float_rational_sum_exponent_range test( "5.96046446e-8", "0xf.ffffffE-7#28", "-255/4261412864", "-2.34664179e-10", "-0x1.0204182E-8#28", ); // - t == 0 in add_rational_prec_round_assign_helper // - different signs and log_x_abs == log_y_abs in float_rational_sum_exponent_range test( "64.0", "0x40.00000#24", "-215679573337202053366254388918461596342975394375083745820919489101824/336999333319768176\ 9435117813341997219028918889483691361889027096575", "-3.7241676e-9", "-0xf.fec40E-8#24", ); } #[test] fn test_add_rational_prec() { let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (sum, o) = x.clone().add_rational_prec(y.clone(), prec); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let (sum_alt, o_alt) = x.clone().add_rational_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_assign(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_assign_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (rug_sum, rug_o) = rug_add_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("-0.0", "-0x0.0", "123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("0.0", "0x0.0", "1/3", 1, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, "0.2", "0x0.4#1", Less); test("123.0", "0x7b.0#7", "0", 1, "1.0e2", "0x8.0E+1#1", Greater); test("1.0", "0x1.0#1", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.000#10", "2", 2, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "1/3", 100, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, "-3.477", "-0x3.7a#10", Less, ); test("1.0", "0x1.0#1", "1/50000", 10, "1.0", "0x1.000#10", Less); test("1.0", "0x1.0#1", "-1", 10, "0.0", "0x0.0", Equal); test( "4.547473508864641189582899002890190173e-13", "0x8.00000000000000003ffff000000000E-11#123", "-4194304/9223372019742015487", 3, "-8.0e-22", "-0x4.0E-18#3", Less, ); } #[test] fn add_rational_prec_fail() { assert_panic!(Float::NAN.add_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_val_ref(&Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_ref_val(Rational::ZERO, 0)); assert_panic!(Float::NAN.add_rational_prec_ref_ref(&Rational::ZERO, 0)); assert_panic!({ let mut x = Float::NAN; x.add_rational_prec_assign(Rational::ZERO, 0) }); assert_panic!({ let mut x = Float::NAN; x.add_rational_prec_assign_ref(&Rational::ZERO, 0) }); } #[test] fn test_add_rational_round() { let test_helper = |s, s_hex, y: Rational, rm, out: &str, out_hex: &str, o_out, extreme: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (sum, o) = x.clone().add_rational_round(y.clone(), rm); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); if !extreme { let (sum_alt, o_alt) = x.clone().add_rational_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_round_assign(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_round_assign_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); }; let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { test_helper( s, s_hex, Rational::from_str(t).unwrap(), rm, out, out_hex, o_out, false, ); }; test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "123", Down, "6.0e1", "0x4.0E+1#1", Less); test("0.0", "0x0.0", "123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "0.0", "0x0.0", "123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "-0.0", "-0x0.0", "123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "123", Down, "6.0e1", "0x4.0E+1#1", Less); test("-0.0", "-0x0.0", "123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "-0.0", "-0x0.0", "123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("123.0", "0x7b.0#7", "0", Floor, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Down, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "0", Up, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Nearest, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Exact, "123.0", "0x7b.0#7", Equal); test("0.0", "0x0.0", "1/3", Floor, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", Nearest, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", Nearest, "0.2", "0x0.4#1", Less); test("1.0", "0x1.0#1", "2", Floor, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", Ceiling, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", Up, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", Nearest, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "2", Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "2", Exact, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "2", Floor, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Ceiling, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Down, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Up, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Nearest, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "2", Exact, "3.0", "0x3.00#10", Equal); test( "1.0", "0x1.000#10", "1/3", Floor, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Ceiling, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Down, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Up, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Nearest, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Floor, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Ceiling, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Down, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Up, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Nearest, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Floor, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Ceiling, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Down, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Up, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Nearest, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Floor, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Ceiling, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Down, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Up, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Nearest, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Floor, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Ceiling, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Down, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Up, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Nearest, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test("1.0", "0x1.0#1", "1/50000", Floor, "1.0", "0x1.0#1", Less); test( "1.0", "0x1.0#1", "1/50000", Ceiling, "2.0", "0x2.0#1", Greater, ); test("1.0", "0x1.0#1", "1/50000", Down, "1.0", "0x1.0#1", Less); test("1.0", "0x1.0#1", "1/50000", Up, "2.0", "0x2.0#1", Greater); test("1.0", "0x1.0#1", "1/50000", Nearest, "1.0", "0x1.0#1", Less); test("1.0", "0x1.0#1", "-1", Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", Exact, "0.0", "0x0.0", Equal); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Floor, "1.83e180", "0x7.0eE+149#10", Less, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Ceiling, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Down, "1.83e180", "0x7.0eE+149#10", Less, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Up, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Nearest, "1.832e180", "0x7.10E+149#10", Greater, ); test( "1.832e180", "0x7.10E+149#10", "-1/8388607", Nearest, "1.832e180", "0x7.10E+149#10", Greater, ); test("1.0", "0x1.0#1", "0", Nearest, "1.0", "0x1.0#1", Equal); // - o == Equal in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1", Nearest, "2.0", "0x2.0#1", Equal); // - o != Equal in add_rational_prec_round_assign_helper // - t != 0 in add_rational_prec_round_assign_helper // - small Natural in float_can_round // - err0 > prec && err > prec in float_can_round // - s != Limb::WIDTH first time in float_can_round // - n == 0 in float_can_round // - float_can_round in add_rational_prec_round_assign_helper test("1.0", "0x1.0#1", "1/3", Nearest, "1.0", "0x1.0#1", Less); // - large Natural in float_can_round // - n != 0 && tmp != 0 && tmp != mask in float_can_round test( "269104312292334.303", "0xf4bfbaf113ee.4d8#57", "517543599148951977/6042448266342026218192", Nearest, "269104312292334.303", "0xf4bfbaf113ee.4d8#57", Less, ); // - s == Limb::WIDTH first time in float_can_round test( "1.1595752615776271305e-33", "0x6.055703bef650178E-28#63", "-2457795567751474853961645492284796573970712506001349310379799846240055987994196472114730\ 61298054082441720799/23", Nearest, "-1.0686067685875977626e106", "-0x1.2a31c100f5e98110E+88#63", Less, ); // - !float_can_round in add_rational_prec_round_assign_helper // - n != 0 && tmp == 0 in float_can_round // - n <= 0 first time in float_can_round // - s != Limb::WIDTH second time in float_can_round // - n > 0 first time in float_can_round // - x == 0 in float_can_round // - x != 0 in float_can_round test( "5.82156e33", "0x1.1f066E+28#20", "8238723/1413731881599214931", Nearest, "5.82156e33", "0x1.1f066E+28#20", Less, ); // - n != 0 && tmp != 0 && tmp == mask in float_can_round // - n <= 0 second time in float_can_round // - s != Limb::WIDTH third time in float_can_round test( "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", "-3183521742267703581572109801877979/35801077870645726", Nearest, "1.04226364758062811487679885e63", "0x2.889a2dba3978ccd56c826E+52#85", Greater, ); // - s == Limb::WIDTH second time in float_can_round // - n > 0 second time in float_can_round // - x == Limb::MAX in float_can_round test( "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", "-808694/11557016618486698036897716112870533564271922504817764249868611771", Nearest, "5.3586423373910357e63", "0xd.06b0f9ea88b7aE+52#55", Greater, ); // - x != Limb::MAX in float_can_round test( "4.9046e10", "0xb.6b5eE+8#19", "-182971083215/47776579472461276067598384651239241670113870043", Nearest, "4.9046e10", "0xb.6b5eE+8#19", Greater, ); // - s == Limb::WIDTH third time in float_can_round test( "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", "-3161/286335616056113777", Nearest, "2.515940926449112e24", "0x2.14c56e507323d0E+20#55", Greater, ); // - err0 <= prec || err <= prec in float_can_round test( "5.96046446e-8", "0xf.ffffffE-7#28", "-255/4261412864", Nearest, "-2.34664179e-10", "-0x1.0204182E-8#28", Less, ); // - t == 0 in add_rational_prec_round_assign_helper test( "64.0", "0x40.00000#24", "-215679573337202053366254388918461596342975394375083745820919489101824/336999333319768176\ 9435117813341997219028918889483691361889027096575", Nearest, "-3.7241676e-9", "-0xf.fec40E-8#24", Greater, ); // - max_exponent > i64::from(Float::MAX_EXPONENT) - 2 in add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Nearest, "Infinity", "Infinity", Greater, true, ); test_helper( "-too_big", "-0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Nearest, "-Infinity", "-Infinity", Less, true, ); // - min_exponent >= Float::MAX_EXPONENT in add_rational_prec_round // - both signs positive in float_rational_sum_sign // - float_rational_sum_sign(x, &y) && (rm == Ceiling || rm == Up || rm == Nearest) in // add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Nearest, "Infinity", "Infinity", Greater, true, ); // - float_rational_sum_sign(x, &y) && (rm == Floor || rm == Down) in add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Down, "too_big", "0x4.0E+268435455#1", Less, true, ); // - !float_rational_sum_sign(x, &y) && (rm == Ceiling || rm == Down) in add_rational_prec_round test_helper( "-too_big", "-0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Down, "-too_big", "-0x4.0E+268435455#1", Greater, true, ); // - signs different and x.lt_abs(y) in float_rational_sum_sign test_helper( "-too_big", "-0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT) + 1), Nearest, "Infinity", "Infinity", Greater, true, ); // - both signs negative in float_rational_sum_sign // - !float_rational_sum_sign(x, &y) && (rm == Floor || rm == Up || rm == Nearest) in // add_rational_prec_round test_helper( "-too_big", "-0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Nearest, "-Infinity", "-Infinity", Less, true, ); test_helper( "-1.0", "-0x1.0#1", Rational::ONE + Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Nearest, "0.0", "0x0.0", Less, true, ); test_helper( "1.0", "0x1.0#1", Rational::NEGATIVE_ONE - Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Nearest, "-0.0", "-0x0.0", Greater, true, ); } #[test] fn add_rational_round_fail() { assert_panic!(Float::one_prec(1).add_rational_round(Rational::from_unsigneds(1u32, 3), Exact)); assert_panic!( Float::one_prec(1).add_rational_round_val_ref(&Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).add_rational_round_ref_val(Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).add_rational_round_ref_ref(&Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_round_assign(Rational::from_unsigneds(1u32, 3), Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_round_assign_ref(&Rational::from_unsigneds(1u32, 3), Exact) }); } #[test] fn test_add_rational_prec_round() { let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (sum, o) = x.clone().add_rational_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); assert_eq!(o, o_out); assert_eq!(sum.to_string(), out); assert_eq!(to_hex_string(&sum), out_hex); let (sum_alt, o_alt) = x.clone().add_rational_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_round_assign(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let mut sum_alt = x.clone(); let o_alt = sum_alt.add_rational_prec_round_assign_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&sum_alt)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "123", 1, Down, "6.0e1", "0x4.0E+1#1", Less); test("0.0", "0x0.0", "123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test( "0.0", "0x0.0", "123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", 1, Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "-0.0", "-0x0.0", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test("-0.0", "-0x0.0", "1/3", 1, Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "123.0", "0x7b.0#7", "0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("1.0", "0x1.0#1", "2", 1, Floor, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", 1, Ceiling, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 1, Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "2", 1, Up, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 1, Nearest, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "2", 2, Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "2", 2, Exact, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "1/3", 100, Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "1/3", 100, Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "1/3", 100, Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "1/3", 100, Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "1/3", 100, Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Floor, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Down, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Up, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Nearest, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Floor, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Down, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Up, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Floor, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Down, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Up, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Nearest, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Floor, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Down, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Up, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "-3.477", "-0x3.7a#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Floor, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Ceiling, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "1/50000", 10, Down, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "1/50000", 10, Up, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "1/50000", 10, Nearest, "1.0", "0x1.000#10", Less, ); test("1.0", "0x1.0#1", "-1", 10, Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "-1", 10, Exact, "0.0", "0x0.0", Equal); } #[test] fn add_rational_prec_round_fail() { assert_panic!(Float::one_prec(1).add_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_val_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_ref_val( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).add_rational_prec_round_ref_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.add_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn add_prec_round_properties_helper( x: Float, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (sum, o) = x.clone().add_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_prec_round_ref_ref(&x, y.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( sum.sub_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); } if !extreme { let r_sum = if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } let (sum_alt, o_alt) = y.add_prec_round_ref_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.sub_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).sub_prec_round_val_ref(&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).add_prec_round(-&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn add_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_1().test_properties(|(x, y, prec, rm)| { add_prec_round_properties_helper(x, y, prec, rm, false); }); float_float_unsigned_rounding_mode_quadruple_gen_var_5().test_properties(|(x, y, prec, rm)| { add_prec_round_properties_helper(x, y, prec, rm, true); }); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (sum, o) = x.add_prec_round_ref_val(Float::NAN, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_prec_round_val_ref(&x, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_prec_round_ref_val(Float::INFINITY, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_prec_round_ref_val(Float::ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::ZERO.add_prec_round_val_ref(&x, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } if rm != Floor || !x.is_positive_zero() { let (sum, o) = x.add_prec_round_ref_val(Float::NEGATIVE_ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_prec_round_val_ref(&x, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); } fn add_prec_properties_helper(x: Float, y: Float, prec: u64, extreme: bool) { let (sum, o) = x.clone().add_prec(y.clone(), prec); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } let (rug_sum, rug_o) = rug_add_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_prec_ref_ref(&x, y.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( sum.sub_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); } if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } if !extreme { let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } } let (sum_alt, o_alt) = y.add_prec_ref_ref(&x, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.sub_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let (mut sum_alt, mut o_alt) = (-&x).sub_prec_val_ref(&y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-x).add_prec(-y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum.abs_negative_zero()) ); assert_eq!(o_alt, o); } } #[test] fn add_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { add_prec_properties_helper(x, y, prec, false); }); float_float_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { add_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (sum, o) = x.add_prec_ref_val(Float::NAN, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_prec_val_ref(&x, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_prec_ref_val(Float::INFINITY, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_prec_ref_val(Float::NEGATIVE_INFINITY, prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_prec_ref_val(Float::ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::ZERO.add_prec_val_ref(&x, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } let (sum, o) = x.add_prec_ref_val(Float::NEGATIVE_ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_prec_val_ref(&x, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn add_round_properties_helper(x: Float, y: Float, rm: RoundingMode, extreme: bool) { let (sum, o) = x.clone().add_round(y.clone(), rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); let o_alt = x_alt.add_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } let (sum_alt, o_alt) = x.add_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() { assert_eq!(sum.sub_round_ref_ref(&x, Exact).0, y); assert_eq!(sum.sub_round_ref_ref(&y, Exact).0, x); } if !extreme { let r_sum = if sum.is_finite() { if x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( sum.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); } let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } Some(r_sum) } else { assert_eq!(o, Equal); None }; match (r_sum.is_some() && *r_sum.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = y.add_round_ref_ref(&x, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.sub_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (mut sum_alt, mut o_alt) = (-&x).sub_round_val_ref(&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); let (mut sum_alt, mut o_alt) = (-&x).add_round(-&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_round_ref_ref(&y, Exact)); } } #[test] fn add_round_properties() { float_float_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_29().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, true); }); float_float_rounding_mode_triple_gen_var_4().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_5().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_6().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_7().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_8().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_9().test_properties(|(x, y, rm)| { add_round_properties_helper(x, y, rm, false); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (sum, o) = x.add_round_ref_val(Float::NAN, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); let (sum, o) = Float::NAN.add_round_val_ref(&x, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!( x.add_round_ref_val(Float::INFINITY, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::INFINITY.add_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); } if x != Float::INFINITY { assert_eq!( x.add_round_ref_val(Float::NEGATIVE_INFINITY, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (sum, o) = x.add_round_ref_val(Float::ZERO, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); let (sum, o) = Float::ZERO.add_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); } if rm != Floor || !x.is_positive_zero() { let (sum, o) = x.add_round_ref_val(Float::NEGATIVE_ZERO, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); let (sum, o) = Float::NEGATIVE_ZERO.add_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&sum), ComparableFloatRef(&x)); assert_eq!(o, Equal); } }); } #[allow(clippy::type_repetition_in_bounds)] fn add_properties_helper_1() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { let sum_1 = x + y; let sum_2 = emulate_float_float_to_float_fn(Float::add_prec, x, y); assert_eq!(NiceFloat(sum_1), NiceFloat(sum_2)); }); } #[allow(clippy::needless_pass_by_value)] fn add_properties_helper_2(x: Float, y: Float, extreme: bool) { let sum = x.clone() + y.clone(); assert!(sum.is_valid()); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); if !extreme { let sum_alt = add_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); } let sum_alt = x .add_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x .add_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o) = x.add_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if o == Equal && sum.is_finite() { assert_eq!(&sum - &x, y); assert_eq!(&sum - &y, x); } if sum.is_finite() && x.is_normal() && y.is_normal() && sum.is_normal() { assert_eq!( sum.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); if !extreme { let r_sum = Rational::exact_from(&x) + Rational::exact_from(&y); if sum < r_sum { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if sum > r_sum { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } } let rug_sum = rug_add(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); let sum_alt = &y + &x; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x - -&y; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let sum_alt = (-(-&x - &y)).abs_negative_zero(); assert_eq!( ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum.abs_negative_zero_ref()) ); let sum_alt = (-(-&x + -&y)).abs_negative_zero(); assert_eq!( ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum.abs_negative_zero()) ); } // example of associativity failure: 0x1.0#1 0x2.0#1 -0x1.0#1 } #[test] fn add_properties() { float_pair_gen().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_10().test_properties(|(x, y)| { add_properties_helper_2(x, y, true); }); float_pair_gen_var_2().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_3().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_4().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_5().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_6().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); float_pair_gen_var_7().test_properties(|(x, y)| { add_properties_helper_2(x, y, false); }); apply_fn_to_primitive_floats!(add_properties_helper_1); float_gen().test_properties(|x| { assert!((&x + Float::NAN).is_nan()); assert!((Float::NAN + &x).is_nan()); if !x.is_nan() { if x != Float::NEGATIVE_INFINITY { assert_eq!(&x + Float::INFINITY, Float::INFINITY); assert_eq!(Float::INFINITY + &x, Float::INFINITY); } if x != Float::INFINITY { assert_eq!(&x + Float::NEGATIVE_INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::NEGATIVE_INFINITY + &x, Float::NEGATIVE_INFINITY); } } if !x.is_negative_zero() { assert_eq!( ComparableFloatRef(&(&x + Float::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Float::ZERO + &x)), ComparableFloatRef(&x) ); } assert_eq!( ComparableFloatRef(&(&x + Float::NEGATIVE_ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Float::NEGATIVE_ZERO + &x)), ComparableFloatRef(&x) ); assert_eq!(ComparableFloat(&x + &x), ComparableFloat(x << 1u32)); }); } #[allow(clippy::needless_pass_by_value)] fn add_rational_prec_round_properties_helper( x: Float, y: Rational, prec: u64, rm: RoundingMode, extreme: bool, ) { let (sum, o) = x.clone().add_rational_prec_round(y.clone(), prec, rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_prec_round_val_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } if !extreme { let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } match (r_sum >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (sum_alt, o_alt) = x.sub_rational_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).sub_rational_prec_round_val_ref(&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-&x).add_rational_prec_round(-&y, prec, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_rational_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_rational_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn add_rational_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_1().test_properties( |(x, y, prec, rm)| { add_rational_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_rational_unsigned_rounding_mode_quadruple_gen_var_7().test_properties_with_limit( 20, |(x, y, prec, rm)| { add_rational_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_prec_round_ref_val(Rational::ZERO, prec, rm); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (sum, o) = Float::NAN.add_rational_prec_round_val_ref(&x, prec, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_prec_round_val_ref(&x, prec, rm); let (sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_prec_round_val_ref(&x, prec, rm); let (mut sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } fn add_rational_prec_properties_helper(x: Float, y: Rational, prec: u64, extreme: bool) { let (sum, o) = x.clone().add_rational_prec(y.clone(), prec); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_prec_val_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_val(y.clone(), prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (sum_alt, o_alt) = x.add_rational_prec_ref_ref(&y, prec); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } let (rug_sum, rug_o) = rug_add_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); if o == Equal && sum.is_finite() { assert_eq!( ComparableFloat( sum.sub_rational_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if sum.is_finite() { if sum.is_normal() { assert_eq!(sum.get_prec(), Some(prec)); } if !extreme { let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } } let (sum_alt, o_alt) = x.sub_rational_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let (mut sum_alt, mut o_alt) = (-&x).sub_rational_prec_val_ref(&y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let (mut sum_alt, mut o_alt) = (-x).add_rational_prec(-y, prec); sum_alt.neg_assign(); sum_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } } #[test] fn add_rational_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { add_rational_prec_properties_helper(x, y, prec, false); }); float_rational_unsigned_triple_gen_var_2().test_properties_with_limit(20, |(x, y, prec)| { add_rational_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_prec_ref_val(Rational::ZERO, prec); let mut sum_alt = x.clone(); let o_alt = sum_alt.set_prec(prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (sum, o) = Float::NAN.add_rational_prec_val_ref(&x, prec); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_prec_val_ref(&x, prec); let (sum_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_prec_val_ref(&x, prec); let (mut sum_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn add_rational_round_properties_helper(x: Float, y: Rational, rm: RoundingMode, extreme: bool) { let (sum, o) = x.clone().add_rational_round(y.clone(), rm); assert!(sum.is_valid()); let (sum_alt, o_alt) = x.clone().add_rational_round_val_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_rational_round_ref_val(y.clone(), rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o_alt) = x.add_rational_round_ref_ref(&y, rm); assert!(sum_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.add_rational_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if !extreme { let (sum_alt, o_alt) = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); } let (sum_alt, o_alt) = x.add_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); assert_eq!(o_alt, o); if o == Equal && sum.is_finite() && sum != 0 { assert_eq!(sum.sub_rational_round_ref_ref(&y, Exact).0, x); // TODO additional test } if sum.is_finite() { if x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); } if !extreme { let r_sum = Rational::exact_from(&x) + &y; assert_eq!(sum.partial_cmp(&r_sum), Some(o)); if o == Less { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if o == Greater { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } match (r_sum >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sum, rug_o) = rug_add_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum) ); assert_eq!(rug_o, o); } let (sum_alt, o_alt) = x.sub_rational_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (mut sum_alt, mut o_alt) = (-&x).sub_rational_round_val_ref(&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero()), ComparableFloat(sum.abs_negative_zero_ref()) ); let (mut sum_alt, mut o_alt) = (-&x).add_rational_round(-&y, -rm); sum_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(sum_alt.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.add_rational_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sum.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.add_rational_round_ref_ref(&y, Exact)); } } #[test] fn add_rational_round_properties() { float_rational_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { add_rational_round_properties_helper(x, y, rm, false); }); float_rational_rounding_mode_triple_gen_var_8().test_properties_with_limit(20, |(x, y, rm)| { add_rational_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { if !x.is_negative_zero() { let (sum, o) = x.add_rational_round_ref_val(Rational::ZERO, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(x)); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (sum, o) = Float::NAN.add_rational_round_val_ref(&x, rm); assert!(sum.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.add_rational_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.add_rational_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (sum, o) = Float::ZERO.add_rational_round_val_ref(&x, rm); let (sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, 1, rm); assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); let (sum, o) = Float::NEGATIVE_ZERO.add_rational_round_val_ref(&x, rm); let (mut sum_alt, o_alt) = Float::from_rational_prec_round_ref(&x, 1, rm); if x == 0u32 { sum_alt.neg_assign(); } assert_eq!(ComparableFloat(sum), ComparableFloat(sum_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn add_rational_properties_helper(x: Float, y: Rational, extreme: bool) { let sum = x.clone() + y.clone(); assert!(sum.is_valid()); let sum_alt = x.clone() + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + y.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &x + &y; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = y.clone() + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = y.clone() + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &y + x.clone(); assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = &y + &x; assert!(sum_alt.is_valid()); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); let mut x_alt = x.clone(); x_alt += &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sum)); if !extreme { let sum_alt = add_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); } let sum_alt = x .add_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = x.add_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let (sum_alt, o) = x.add_rational_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if o == Equal && sum.is_finite() && sum != 0 { assert_eq!(&sum - &y, x); // TODO additional test } if sum.is_finite() && x.is_normal() && sum.is_normal() { assert_eq!(sum.get_prec(), Some(x.get_prec().unwrap())); if !extreme { let r_sum = Rational::exact_from(&x) + &y; if sum < r_sum { let mut next = sum.clone(); next.increment(); assert!(next > r_sum); } else if sum > r_sum { let mut next = sum.clone(); next.decrement(); assert!(next < r_sum); } } } let rug_sum = rug_add_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sum)), ComparableFloatRef(&sum), ); let sum_alt = &x - -&y; assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let sum_alt = (-(-&x - &y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); let sum_alt = (-(-&x + -&y)).abs_negative_zero(); assert_eq!(ComparableFloatRef(&sum_alt), ComparableFloatRef(&sum)); } } #[test] fn add_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { add_rational_properties_helper(x, y, false); }); float_rational_pair_gen_var_2().test_properties_with_limit(20, |(x, y)| { add_rational_properties_helper(x, y, true); }); float_gen().test_properties(|x| { assert_eq!( ComparableFloatRef(&(&x + Rational::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Rational::ZERO + &x)), ComparableFloatRef(&x) ); }); rational_gen().test_properties(|x| { assert!((&x + Float::NAN).is_nan()); assert!((Float::NAN + &x).is_nan()); assert_eq!(&x + Float::INFINITY, Float::INFINITY); assert_eq!(Float::INFINITY + &x, Float::INFINITY); assert_eq!(&x + Float::NEGATIVE_INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::NEGATIVE_INFINITY + &x, Float::NEGATIVE_INFINITY); let sum_alt = Float::from_rational_prec_ref(&x, 1).0; assert_eq!( ComparableFloat(&x + Float::ZERO), ComparableFloat(sum_alt.clone()) ); assert_eq!( ComparableFloat(Float::ZERO + &x), ComparableFloat(sum_alt.clone()) ); assert_eq!( ComparableFloat((&x + Float::NEGATIVE_ZERO).abs_negative_zero()), ComparableFloat(sum_alt.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat((Float::NEGATIVE_ZERO + &x).abs_negative_zero()), ComparableFloat(sum_alt.abs_negative_zero()) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/agm.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Agm, AgmAssign, PowerOf2, Square}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, OneHalf, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::arithmetic::agm::{primitive_float_agm, primitive_float_agm_rational}; use malachite_float::test_util::arithmetic::agm::{ agm_prec_round_extended, rug_agm, rug_agm_prec, rug_agm_prec_round, rug_agm_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_33, float_float_rounding_mode_triple_gen_var_34, float_float_unsigned_rounding_mode_quadruple_gen_var_9, float_float_unsigned_rounding_mode_quadruple_gen_var_10, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_2, float_gen, float_gen_var_4, float_gen_var_15, float_pair_gen, float_pair_gen_var_10, float_rounding_mode_pair_gen, float_rounding_mode_pair_gen_var_32, float_rounding_mode_pair_gen_var_33, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_6, float_unsigned_pair_gen_var_7, float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_17, float_unsigned_rounding_mode_triple_gen_var_18, rational_rational_unsigned_rounding_mode_quadruple_gen_var_1, rational_unsigned_rounding_mode_triple_gen_var_5, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_pair_gen, rational_rational_unsigned_triple_gen_var_2, rational_unsigned_pair_gen_var_8, }; use std::cmp::Ordering::{self, *}; use std::cmp::max; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_agm() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let agm = x.clone().agm(y.clone()); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); let agm_alt = x.clone().agm(&y); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); let agm_alt = (&x).agm(y.clone()); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); let agm_alt = (&x).agm(&y); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); let mut agm_alt = x.clone(); agm_alt.agm_assign(y.clone()); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); let mut agm_alt = x.clone(); agm_alt.agm_assign(&y); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef(&agm), ); let prec = max(x.significant_bits(), y.significant_bits()); let agm_alt = agm_prec_round_extended(x, y, prec, Nearest).0; assert_eq!(ComparableFloat(agm_alt), ComparableFloat(agm)); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test( "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test("Infinity", "Infinity", "0.0", "0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "-0.0", "-0x0.0", "NaN", "NaN"); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test("-Infinity", "-Infinity", "0.0", "0x0.0", "NaN", "NaN"); test("-Infinity", "-Infinity", "-0.0", "-0x0.0", "NaN", "NaN"); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test("0.0", "0x0.0", "Infinity", "Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "-Infinity", "-Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test("-0.0", "-0x0.0", "Infinity", "Infinity", "NaN", "NaN"); test("-0.0", "-0x0.0", "-Infinity", "-Infinity", "NaN", "NaN"); test("-0.0", "-0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", "Infinity", "Infinity", ); test("123.0", "0x7b.0#7", "-Infinity", "-Infinity", "NaN", "NaN"); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "0.0", "0x0.0"); test("123.0", "0x7b.0#7", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-123.0", "-0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test("-123.0", "-0x7b.0#7", "Infinity", "Infinity", "NaN", "NaN"); test( "-123.0", "-0x7b.0#7", "-Infinity", "-Infinity", "NaN", "NaN", ); test("-123.0", "-0x7b.0#7", "0.0", "0x0.0", "0.0", "0x0.0"); test("-123.0", "-0x7b.0#7", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", ); test("-Infinity", "-Infinity", "123.0", "0x7b.0#7", "NaN", "NaN"); test("0.0", "0x0.0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "1.5", "0x1.8#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "1.5", "0x1.8#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "1.5", "0x1.8#2"); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", "1.457", "0x1.750#10", ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", "13.45817148172561542076681315698", "0xd.754ab9e9f8ac5a0692360241#100", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "2.1920339783176708", "0x2.31292388985d0#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "NaN", "NaN", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "NaN", "NaN", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "NaN", "NaN", ); test( "too_big", "0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", ); test( "too_big", "0x4.0E+268435455#1", "1.0", "0x1.0#1", "too_big", "0x2.0E+268435448#1", ); test( "too_small", "0x1.0E-268435456#1", "too_small", "0x1.0E-268435456#1", "too_small", "0x1.0E-268435456#1", ); test( "too_small", "0x1.0E-268435456#1", "1.0", "0x1.0#1", "2.0e-9", "0x8.0E-8#1", ); test( "too_big", "0x4.0E+268435455#1", "too_small", "0x1.0E-268435456#1", "too_big", "0x1.0E+268435448#1", ); test( "too_small", "0x7.184a0f216320E-268435451#48", "1.0e-7", "0x2.0E-6#2", "2.51596539536877e-16", "0x1.2212310c5964E-13#48", ); } #[test] fn test_agm_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (agm, o) = x.clone().agm_prec(y.clone(), prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, o_out); let (agm_alt, o_alt) = x.clone().agm_prec_val_ref(&y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_prec_ref_val(y.clone(), prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_prec_ref_ref(&y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_prec_assign(y.clone(), prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_prec_assign_ref(&y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (rug_agm, rug_o) = rug_agm_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm) ); assert_eq!(rug_o, o); let (agm_alt, o_alt) = agm_prec_round_extended(x, y, prec, Nearest); assert_eq!(ComparableFloat(agm_alt), ComparableFloat(agm)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 2, "1.5", "0x1.8#2", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 2, "1.5", "0x1.8#2", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 2, "1.5", "0x1.8#2", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 2, "1.5", "0x1.8#2", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 2, "1.5", "0x1.8#2", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, "1.457", "0x1.750#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "2.0", "0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "2.191", "0x2.31#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 1, "0.1", "0x0.2#1", Less, ); test( "1.0", "0x1.0#1", "0.0002", "0x0.001#1", 20, "0.16187", "0x0.297050#20", Less, ); // - in agm_prec_round_ref_ref_normal // - *a >= 0u32 && *b >= 0u32 in agm_prec_round_ref_ref_normal // - a == b in agm_prec_round_ref_ref_normal test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal, ); // - *a < 0u32 || *b < 0u32 in agm_prec_round_ref_ref_normal test("1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); // - a < b in agm_prec_round_ref_ref_normal // - !u_overflow && !u_underflow && !v_overflow && !v_underflow in agm_prec_round_ref_ref_normal // - cmp != Equal in agm_prec_round_ref_ref_normal // - eq <= p / 4 in agm_prec_round_ref_ref_normal // - !uf.is_infinite() in agm_prec_round_ref_ref_normal // - eq > p / 4 in agm_prec_round_ref_ref_normal // - !underflow in agm_prec_round_ref_ref_normal // - terminate Ziv in agm_prec_round_ref_ref_normal test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "1.0", "0x1.0#1", Less, ); // - a > b in agm_prec_round_ref_ref_normal test( "2.0", "0x2.0#1", "1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Less, ); // - don't terminate Ziv in agm_prec_round_ref_ref_normal test( "3.0379e20", "0x1.0780E+17#14", "6.0e1", "0x4.0E+1#3", 14, "1.075e19", "0x9.530E+15#14", Less, ); // - uf.is_infinite() in agm_prec_round_ref_ref_normal test( "1.0", "0x1.0#1", "too_big", "0x4.0E+268435455#1", 1, "too_big", "0x2.0E+268435448#1", Less, ); // - u_overflow || u_underflow || v_overflow || v_underflow in agm_prec_round_ref_ref_normal // - u_overflow || v_overflow in agm_prec_round_ref_ref_normal // - e1 + e2 > Float::MAX_EXPONENT in agm_prec_round_ref_ref_normal test( "2.0", "0x2.0#1", "too_big", "0x4.0E+268435455#1", 1, "too_big", "0x2.0E+268435448#1", Less, ); // - !u_overflow && !v_overflow in agm_prec_round_ref_ref_normal test( "0.5", "0x0.8#1", "too_small", "0x1.0E-268435456#1", 1, "9.0e-10", "0x4.0E-8#1", Less, ); // - underflow in agm_prec_round_ref_ref_normal test( "too_small", "0x1.0E-268435456#1", "too_small", "0x1.8E-268435456#2", 2, "too_small", "0x1.0E-268435456#2", Less, ); // - e1 + e2 <= Float::MAX_EXPONENT in agm_prec_round_ref_ref_normal test( "too_big", "0x7.ffffffe3ffffffffeE+268435455#70", "too_small", "0x1.fffffffc1ffffffffffff1ffffe0000000000003ffffffffc00000000000000000000001fffffffffffff\ ffffffffffff800000000E-268435442#424", 7, "too_big", "0x2.48E+268435448#7", Greater, ); } #[test] fn agm_prec_fail() { assert_panic!(Float::NAN.agm_prec(Float::NAN, 0)); assert_panic!(Float::NAN.agm_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.agm_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.agm_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.agm_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.agm_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_agm_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (agm, o) = x.clone().agm_round(y.clone(), rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, o_out); let (agm_alt, o_alt) = x.clone().agm_round_val_ref(&y, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_round_ref_val(y.clone(), rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_round_ref_ref(&y, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_round_assign(y.clone(), rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_round_assign_ref(&y, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_agm, rug_o) = rug_agm_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm), ); assert_eq!(rug_o, o); } let prec = max(x.significant_bits(), y.significant_bits()); let (agm_alt, o_alt) = agm_prec_round_extended(x, y, prec, rm); assert_eq!(ComparableFloat(agm_alt), ComparableFloat(agm)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "1.0", "0x1.0#2", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "2.1920339783176708", "0x2.31292388985d0#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "2.1920339783176712", "0x2.31292388985d2#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "2.1920339783176708", "0x2.31292388985d0#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "2.1920339783176712", "0x2.31292388985d2#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "2.1920339783176708", "0x2.31292388985d0#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal, ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", Floor, "13.45817148172561542076681315696", "0xd.754ab9e9f8ac5a0692360240#100", Less, ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", Ceiling, "13.45817148172561542076681315698", "0xd.754ab9e9f8ac5a0692360241#100", Greater, ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", Down, "13.45817148172561542076681315696", "0xd.754ab9e9f8ac5a0692360240#100", Less, ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", Up, "13.45817148172561542076681315698", "0xd.754ab9e9f8ac5a0692360241#100", Greater, ); test( "24.0", "0x18.000000000000000000000000#100", "6.0", "0x6.0000000000000000000000000#100", Nearest, "13.45817148172561542076681315698", "0xd.754ab9e9f8ac5a0692360241#100", Greater, ); } #[test] fn agm_round_fail() { assert_panic!(Float::one_prec(1).agm_round(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).agm_round_val_ref(&Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).agm_round_ref_val(Float::two_prec(1), Exact)); assert_panic!(Float::one_prec(1).agm_round_ref_ref(&Float::two_prec(1), Exact)); } #[test] fn test_agm_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (agm, o) = x.clone().agm_prec_round(y.clone(), prec, rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, o_out); let (agm_alt, o_alt) = x.clone().agm_prec_round_val_ref(&y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_prec_round_ref_val(y.clone(), prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let (agm_alt, o_alt) = x.agm_prec_round_ref_ref(&y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_prec_round_assign(y.clone(), prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); let mut agm_alt = x.clone(); let o_alt = agm_alt.agm_prec_round_assign_ref(&y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&agm_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_agm, rug_o) = rug_agm_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm) ); assert_eq!(rug_o, o); } let (agm_alt, o_alt) = agm_prec_round_extended(x, y, prec, rm); assert_eq!(ComparableFloat(agm_alt), ComparableFloat(agm)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Floor, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Ceiling, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Down, "1.455", "0x1.748#10", Less, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Up, "1.457", "0x1.750#10", Greater, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Nearest, "1.457", "0x1.750#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "2.191", "0x2.31#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "2.195", "0x2.32#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "2.191", "0x2.31#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "2.195", "0x2.32#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "2.191", "0x2.31#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Floor, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Ceiling, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Down, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Up, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Nearest, "NaN", "NaN", Equal, ); test( "1.0", "0x1.0#1", "-1.0", "-0x1.0#1", 10, Exact, "NaN", "NaN", Equal, ); } #[test] fn agm_prec_round_fail() { assert_panic!(Float::one_prec(1).agm_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).agm_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).agm_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).agm_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.agm_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.agm_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(Float::one_prec(1).agm_prec_round(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).agm_prec_round_val_ref(&Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).agm_prec_round_ref_val(Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).agm_prec_round_ref_ref(&Float::two_prec(1), 1, Exact)); assert_panic!({ let mut x = Float::one_prec(1); x.agm_prec_round_assign(Float::two_prec(1), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.agm_prec_round_assign_ref(&Float::two_prec(1), 1, Exact) }); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_agm() { fn test(x: T, y: T, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { assert_eq!(NiceFloat(primitive_float_agm(x, y)), NiceFloat(out)); } test::(f32::NAN, f32::NAN, f32::NAN); test::(f32::NAN, f32::INFINITY, f32::NAN); test::(f32::NAN, f32::NEGATIVE_INFINITY, f32::NAN); test::(f32::NAN, 0.0, f32::NAN); test::(f32::NAN, -0.0, f32::NAN); test::(f32::INFINITY, f32::NAN, f32::NAN); test::(f32::INFINITY, f32::INFINITY, f32::INFINITY); test::(f32::INFINITY, f32::NEGATIVE_INFINITY, f32::NAN); test::(f32::INFINITY, 0.0, f32::NAN); test::(f32::INFINITY, -0.0, f32::NAN); test::(f32::NEGATIVE_INFINITY, f32::NAN, f32::NAN); test::(f32::NEGATIVE_INFINITY, f32::INFINITY, f32::NAN); test::(f32::NEGATIVE_INFINITY, f32::NEGATIVE_INFINITY, f32::NAN); test::(f32::NEGATIVE_INFINITY, 0.0, f32::NAN); test::(f32::NEGATIVE_INFINITY, -0.0, f32::NAN); test::(0.0, f32::NAN, f32::NAN); test::(0.0, f32::INFINITY, f32::NAN); test::(0.0, f32::NEGATIVE_INFINITY, f32::NAN); test::(0.0, 0.0, 0.0); test::(0.0, -0.0, 0.0); test::(-0.0, f32::NAN, f32::NAN); test::(-0.0, f32::INFINITY, f32::NAN); test::(-0.0, f32::NEGATIVE_INFINITY, f32::NAN); test::(-0.0, 0.0, 0.0); test::(-0.0, -0.0, 0.0); test::(123.0, f32::NAN, f32::NAN); test::(123.0, f32::INFINITY, f32::INFINITY); test::(123.0, f32::NEGATIVE_INFINITY, f32::NAN); test::(123.0, 0.0, 0.0); test::(123.0, -0.0, 0.0); test::(-123.0, f32::NAN, f32::NAN); test::(-123.0, f32::INFINITY, f32::NAN); test::(-123.0, f32::NEGATIVE_INFINITY, f32::NAN); test::(-123.0, 0.0, 0.0); test::(-123.0, -0.0, 0.0); test::(f32::NAN, 123.0, f32::NAN); test::(f32::INFINITY, 123.0, f32::INFINITY); test::(f32::NEGATIVE_INFINITY, 123.0, f32::NAN); test::(0.0, 123.0, 0.0); test::(-0.0, 123.0, 0.0); test::(1.0, 2.0, 1.456791); test::(24.0, 6.0, 13.458172); test::(f64::NAN, f64::NAN, f64::NAN); test::(f64::NAN, f64::INFINITY, f64::NAN); test::(f64::NAN, f64::NEGATIVE_INFINITY, f64::NAN); test::(f64::NAN, 0.0, f64::NAN); test::(f64::NAN, -0.0, f64::NAN); test::(f64::INFINITY, f64::NAN, f64::NAN); test::(f64::INFINITY, f64::INFINITY, f64::INFINITY); test::(f64::INFINITY, f64::NEGATIVE_INFINITY, f64::NAN); test::(f64::INFINITY, 0.0, f64::NAN); test::(f64::INFINITY, -0.0, f64::NAN); test::(f64::NEGATIVE_INFINITY, f64::NAN, f64::NAN); test::(f64::NEGATIVE_INFINITY, f64::INFINITY, f64::NAN); test::(f64::NEGATIVE_INFINITY, f64::NEGATIVE_INFINITY, f64::NAN); test::(f64::NEGATIVE_INFINITY, 0.0, f64::NAN); test::(f64::NEGATIVE_INFINITY, -0.0, f64::NAN); test::(0.0, f64::NAN, f64::NAN); test::(0.0, f64::INFINITY, f64::NAN); test::(0.0, f64::NEGATIVE_INFINITY, f64::NAN); test::(0.0, 0.0, 0.0); test::(0.0, -0.0, 0.0); test::(-0.0, f64::NAN, f64::NAN); test::(-0.0, f64::INFINITY, f64::NAN); test::(-0.0, f64::NEGATIVE_INFINITY, f64::NAN); test::(-0.0, 0.0, 0.0); test::(-0.0, -0.0, 0.0); test::(123.0, f64::NAN, f64::NAN); test::(123.0, f64::INFINITY, f64::INFINITY); test::(123.0, f64::NEGATIVE_INFINITY, f64::NAN); test::(123.0, 0.0, 0.0); test::(123.0, -0.0, 0.0); test::(-123.0, f64::NAN, f64::NAN); test::(-123.0, f64::INFINITY, f64::NAN); test::(-123.0, f64::NEGATIVE_INFINITY, f64::NAN); test::(-123.0, 0.0, 0.0); test::(-123.0, -0.0, 0.0); test::(f64::NAN, 123.0, f64::NAN); test::(f64::INFINITY, 123.0, f64::INFINITY); test::(f64::NEGATIVE_INFINITY, 123.0, f64::NAN); test::(0.0, 123.0, 0.0); test::(-0.0, 123.0, 0.0); test::(1.0, 2.0, 1.4567910310469068); test::(24.0, 6.0, 13.458171481725616); } #[test] fn test_agm_rational_prec() { let test = |s, t, prec, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let (agm, o) = Float::agm_rational_prec(u.clone(), v.clone(), prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_val_ref(u.clone(), &v, prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_ref_val(&u, v.clone(), prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_ref_ref(&u, &v, prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); }; // - in agm_rational_prec_round // - x == 0 || y == 0 in agm_rational_prec_round test("0", "0", 1, "0.0", "0x0.0", Equal); test("0", "0", 10, "0.0", "0x0.0", Equal); test("0", "0", 100, "0.0", "0x0.0", Equal); test("0", "22/7", 1, "0.0", "0x0.0", Equal); test("0", "22/7", 10, "0.0", "0x0.0", Equal); test("0", "22/7", 100, "0.0", "0x0.0", Equal); test("-1", "22/7", 1, "NaN", "NaN", Equal); test("-1", "22/7", 10, "NaN", "NaN", Equal); test("-1", "22/7", 100, "NaN", "NaN", Equal); test("22/7", "-1", 1, "NaN", "NaN", Equal); test("22/7", "-1", 10, "NaN", "NaN", Equal); test("22/7", "-1", 100, "NaN", "NaN", Equal); test("22/7", "22/7", 1, "4.0", "0x4.0#1", Greater); test("22/7", "22/7", 10, "3.145", "0x3.25#10", Greater); test( "22/7", "22/7", 100, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test("1", "2", 1, "1.0", "0x1.0#1", Less); test("1", "2", 10, "1.457", "0x1.750#10", Greater); test( "1", "2", 100, "1.456791031046906869186432383265", "0x1.74f041cb73dca72066c53853e#100", Less, ); test("1", "4/3", 1, "1.0", "0x1.0#1", Less); test("1", "4/3", 10, "1.16", "0x1.290#10", Less); test( "1", "4/3", 100, "1.160675892119856802207320983052", "0x1.29220e25e91091bea1ecae6de#100", Less, ); test("4/3", "2", 1, "2.0", "0x2.0#1", Greater); test("4/3", "2", 10, "1.65", "0x1.a68#10", Greater); test( "4/3", "2", 100, "1.649786957490869641737773069062", "0x1.a6587023ca668d7d15d42a6a8#100", Greater, ); test("4/3", "22/7", 1, "2.0", "0x2.0#1", Less); test("4/3", "22/7", 10, "2.141", "0x2.24#10", Less); test( "4/3", "22/7", 100, "2.141515087948159535688532991751", "0x2.243a5532a0bea4119018af58c#100", Greater, ); // - x < 0 || y < 0 in agm_rational_prec_round // - x >= 0 && y >= 0 in agm_rational_prec_round // - x == y in agm_rational_prec_round test("1", "1", 1, "1.0", "0x1.0#1", Equal); // - x != y in agm_rational_prec_round // - no overflow or underflow in agm_rational_prec_round // - in agm_rational_helper // - x_o == Equal && y_o == Equal in agm_rational_helper test("1", "1/2", 1, "0.5", "0x0.8#1", Less); // - x_o != Equal || y_o != Equal in agm_rational_helper // - x_o == Equal in agm_rational_helper // - y_o != Equal in agm_rational_helper // - o_lo != Equal in agm_rational_helper // - o_hi != Equal in agm_rational_helper // - o_lo == o_hi && agm_lo == agm_hi in agm_rational_helper test("1", "1/3", 1, "0.5", "0x0.8#1", Less); // - x_o != Equal in agm_rational_helper // - y_o == Equal in agm_rational_helper test("1/3", "1", 1, "0.5", "0x0.8#1", Less); // - o_lo != o_hi || agm_lo != agm_hi in agm_rational_helper test( "558514310918953/444252178279", "81626687/1727294", 36, "422.994593993", "0x1a6.fe9db64#36", Greater, ); // - o_lo == Equal in agm_rational_helper test("1/2", "5000001/10000000", 1, "0.5", "0x0.8#1", Less); // - o_hi == Equal in agm_rational_helper test("1/2", "4999999/10000000", 1, "0.5", "0x0.8#1", Greater); let test_big = |u: Rational, v: Rational, prec, out, out_hex, out_o| { let (agm, o) = Float::agm_rational_prec(u.clone(), v.clone(), prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_val_ref(u.clone(), &v, prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_ref_val(&u, v.clone(), prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_ref_ref(&u, &v, prec); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); }; let max_exp = i64::from(Float::MAX_EXPONENT); let min_exp = i64::from(Float::MIN_EXPONENT); // - just overflow in agm_rational_prec_round test_big( Rational::power_of_2(max_exp), Rational::power_of_2(max_exp + 1), 1, "Infinity", "Infinity", Greater, ); // - just underflow in agm_rational_prec_round test_big( Rational::power_of_2(min_exp - 4), Rational::power_of_2(min_exp - 3), 1, "0.0", "0x0.0", Less, ); // - just underflow (borderline) in agm_rational_prec_round test_big( Rational::power_of_2(min_exp - 3), Rational::power_of_2(min_exp - 2), 1, "0.0", "0x0.0", Less, ); // - partial overflow or underflow in agm_rational_prec_round // - in agm_rational_helper_extended // - x_o == Equal && y_o == Equal in agm_rational_helper_extended test_big( Rational::power_of_2(min_exp - 4), Rational::power_of_2(max_exp + 1), 1, "too_big", "0x4.0E+268435448#1", Less, ); // - x_o != Equal || y_o != Equal in agm_rational_helper_extended // - x_o == Equal in agm_rational_helper_extended // - y_o != Equal in agm_rational_helper_extended // - o_lo != Equal in agm_rational_helper_extended // - o_hi != Equal in agm_rational_helper_extended // - o_lo == o_hi && agm_lo == agm_hi in agm_rational_helper_extended test_big( Rational::ONE, Rational::power_of_2(max_exp + 1) * Rational::from_unsigneds(4u8, 3), 1, "too_big", "0x1.0E+268435449#1", Greater, ); // - x_o != Equal in agm_rational_helper_extended // - y_o == Equal in agm_rational_helper_extended test_big( Rational::power_of_2(max_exp + 1) * Rational::from_unsigneds(4u8, 3), Rational::ONE, 1, "too_big", "0x1.0E+268435449#1", Greater, ); // - o_lo != o_hi || agm_lo != agm_hi in agm_rational_helper_extended test_big( Rational::from_unsigneds(558514310918953u64, 444252178279) << (max_exp - 6), Rational::from_unsigneds(81626687u32, 1727294) << (max_exp - 6), 36, "Infinity", "Infinity", Greater, ); // - no overflow or underflow (borderline) in agm_rational_prec_round // - o_lo == Equal in agm_rational_helper_extended test_big( Rational::ONE_HALF << max_exp, Rational::from_unsigneds(5000001u32, 10000000) << max_exp, 1, "too_big", "0x4.0E+268435455#1", Less, ); } #[test] fn agm_ratonal_prec_fail() { assert_panic!(Float::agm_rational_prec(Rational::ONE, Rational::ONE, 0)); assert_panic!(Float::agm_rational_prec_val_ref( Rational::ONE, &Rational::ONE, 0 )); assert_panic!(Float::agm_rational_prec_ref_val( &Rational::ONE, Rational::ONE, 0 )); assert_panic!(Float::agm_rational_prec_ref_ref( &Rational::ONE, &Rational::ONE, 0 )); } #[test] fn test_agm_rational_prec_round() { let test = |s, t, prec, rm, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let (agm, o) = Float::agm_rational_prec_round(u.clone(), v.clone(), prec, rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_round_val_ref(u.clone(), &v, prec, rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_round_ref_val(&u, v.clone(), prec, rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); let (agm, o) = Float::agm_rational_prec_round_ref_ref(&u, &v, prec, rm); assert!(agm.is_valid()); assert_eq!(agm.to_string(), out); assert_eq!(to_hex_string(&agm), out_hex); assert_eq!(o, out_o); }; test("0", "0", 1, Floor, "0.0", "0x0.0", Equal); test("0", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", "0", 1, Down, "0.0", "0x0.0", Equal); test("0", "0", 1, Up, "0.0", "0x0.0", Equal); test("0", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("0", "0", 1, Exact, "0.0", "0x0.0", Equal); test("0", "0", 10, Floor, "0.0", "0x0.0", Equal); test("0", "0", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", "0", 10, Down, "0.0", "0x0.0", Equal); test("0", "0", 10, Up, "0.0", "0x0.0", Equal); test("0", "0", 10, Nearest, "0.0", "0x0.0", Equal); test("0", "0", 10, Exact, "0.0", "0x0.0", Equal); test("0", "0", 100, Floor, "0.0", "0x0.0", Equal); test("0", "0", 100, Ceiling, "0.0", "0x0.0", Equal); test("0", "0", 100, Down, "0.0", "0x0.0", Equal); test("0", "0", 100, Up, "0.0", "0x0.0", Equal); test("0", "0", 100, Nearest, "0.0", "0x0.0", Equal); test("0", "0", 100, Exact, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Floor, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Down, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Up, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Nearest, "0.0", "0x0.0", Equal); test("0", "22/7", 1, Exact, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Floor, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Down, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Up, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Nearest, "0.0", "0x0.0", Equal); test("0", "22/7", 10, Exact, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Floor, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Ceiling, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Down, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Up, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Nearest, "0.0", "0x0.0", Equal); test("0", "22/7", 100, Exact, "0.0", "0x0.0", Equal); test("-1", "22/7", 1, Floor, "NaN", "NaN", Equal); test("-1", "22/7", 1, Ceiling, "NaN", "NaN", Equal); test("-1", "22/7", 1, Down, "NaN", "NaN", Equal); test("-1", "22/7", 1, Up, "NaN", "NaN", Equal); test("-1", "22/7", 1, Nearest, "NaN", "NaN", Equal); test("-1", "22/7", 1, Exact, "NaN", "NaN", Equal); test("-1", "22/7", 10, Floor, "NaN", "NaN", Equal); test("-1", "22/7", 10, Ceiling, "NaN", "NaN", Equal); test("-1", "22/7", 10, Down, "NaN", "NaN", Equal); test("-1", "22/7", 10, Up, "NaN", "NaN", Equal); test("-1", "22/7", 10, Nearest, "NaN", "NaN", Equal); test("-1", "22/7", 10, Exact, "NaN", "NaN", Equal); test("-1", "22/7", 100, Floor, "NaN", "NaN", Equal); test("-1", "22/7", 100, Ceiling, "NaN", "NaN", Equal); test("-1", "22/7", 100, Down, "NaN", "NaN", Equal); test("-1", "22/7", 100, Up, "NaN", "NaN", Equal); test("-1", "22/7", 100, Nearest, "NaN", "NaN", Equal); test("-1", "22/7", 100, Exact, "NaN", "NaN", Equal); test("22/7", "-1", 1, Floor, "NaN", "NaN", Equal); test("22/7", "-1", 1, Ceiling, "NaN", "NaN", Equal); test("22/7", "-1", 1, Down, "NaN", "NaN", Equal); test("22/7", "-1", 1, Up, "NaN", "NaN", Equal); test("22/7", "-1", 1, Nearest, "NaN", "NaN", Equal); test("22/7", "-1", 1, Exact, "NaN", "NaN", Equal); test("22/7", "-1", 10, Floor, "NaN", "NaN", Equal); test("22/7", "-1", 10, Ceiling, "NaN", "NaN", Equal); test("22/7", "-1", 10, Down, "NaN", "NaN", Equal); test("22/7", "-1", 10, Up, "NaN", "NaN", Equal); test("22/7", "-1", 10, Nearest, "NaN", "NaN", Equal); test("22/7", "-1", 10, Exact, "NaN", "NaN", Equal); test("22/7", "-1", 100, Floor, "NaN", "NaN", Equal); test("22/7", "-1", 100, Ceiling, "NaN", "NaN", Equal); test("22/7", "-1", 100, Down, "NaN", "NaN", Equal); test("22/7", "-1", 100, Up, "NaN", "NaN", Equal); test("22/7", "-1", 100, Nearest, "NaN", "NaN", Equal); test("22/7", "-1", 100, Exact, "NaN", "NaN", Equal); test("22/7", "22/7", 1, Floor, "2.0", "0x2.0#1", Less); test("22/7", "22/7", 1, Ceiling, "4.0", "0x4.0#1", Greater); test("22/7", "22/7", 1, Down, "2.0", "0x2.0#1", Less); test("22/7", "22/7", 1, Up, "4.0", "0x4.0#1", Greater); test("22/7", "22/7", 1, Nearest, "4.0", "0x4.0#1", Greater); test("22/7", "22/7", 10, Floor, "3.141", "0x3.24#10", Less); test("22/7", "22/7", 10, Ceiling, "3.145", "0x3.25#10", Greater); test("22/7", "22/7", 10, Down, "3.141", "0x3.24#10", Less); test("22/7", "22/7", 10, Up, "3.145", "0x3.25#10", Greater); test("22/7", "22/7", 10, Nearest, "3.145", "0x3.25#10", Greater); test( "22/7", "22/7", 100, Floor, "3.142857142857142857142857142855", "0x3.2492492492492492492492490#100", Less, ); test( "22/7", "22/7", 100, Ceiling, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test( "22/7", "22/7", 100, Down, "3.142857142857142857142857142855", "0x3.2492492492492492492492490#100", Less, ); test( "22/7", "22/7", 100, Up, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test( "22/7", "22/7", 100, Nearest, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test("1", "2", 1, Floor, "1.0", "0x1.0#1", Less); test("1", "2", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("1", "2", 1, Down, "1.0", "0x1.0#1", Less); test("1", "2", 1, Up, "2.0", "0x2.0#1", Greater); test("1", "2", 1, Nearest, "1.0", "0x1.0#1", Less); test("1", "2", 10, Floor, "1.455", "0x1.748#10", Less); test("1", "2", 10, Ceiling, "1.457", "0x1.750#10", Greater); test("1", "2", 10, Down, "1.455", "0x1.748#10", Less); test("1", "2", 10, Up, "1.457", "0x1.750#10", Greater); test("1", "2", 10, Nearest, "1.457", "0x1.750#10", Greater); test( "1", "2", 100, Floor, "1.456791031046906869186432383265", "0x1.74f041cb73dca72066c53853e#100", Less, ); test( "1", "2", 100, Ceiling, "1.456791031046906869186432383266", "0x1.74f041cb73dca72066c538540#100", Greater, ); test( "1", "2", 100, Down, "1.456791031046906869186432383265", "0x1.74f041cb73dca72066c53853e#100", Less, ); test( "1", "2", 100, Up, "1.456791031046906869186432383266", "0x1.74f041cb73dca72066c538540#100", Greater, ); test( "1", "2", 100, Nearest, "1.456791031046906869186432383265", "0x1.74f041cb73dca72066c53853e#100", Less, ); test("1", "4/3", 1, Floor, "1.0", "0x1.0#1", Less); test("1", "4/3", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("1", "4/3", 1, Down, "1.0", "0x1.0#1", Less); test("1", "4/3", 1, Up, "2.0", "0x2.0#1", Greater); test("1", "4/3", 1, Nearest, "1.0", "0x1.0#1", Less); test("1", "4/3", 10, Floor, "1.16", "0x1.290#10", Less); test("1", "4/3", 10, Ceiling, "1.162", "0x1.298#10", Greater); test("1", "4/3", 10, Down, "1.16", "0x1.290#10", Less); test("1", "4/3", 10, Up, "1.162", "0x1.298#10", Greater); test("1", "4/3", 10, Nearest, "1.16", "0x1.290#10", Less); test( "1", "4/3", 100, Floor, "1.160675892119856802207320983052", "0x1.29220e25e91091bea1ecae6de#100", Less, ); test( "1", "4/3", 100, Ceiling, "1.160675892119856802207320983053", "0x1.29220e25e91091bea1ecae6e0#100", Greater, ); test( "1", "4/3", 100, Down, "1.160675892119856802207320983052", "0x1.29220e25e91091bea1ecae6de#100", Less, ); test( "1", "4/3", 100, Up, "1.160675892119856802207320983053", "0x1.29220e25e91091bea1ecae6e0#100", Greater, ); test( "1", "4/3", 100, Nearest, "1.160675892119856802207320983052", "0x1.29220e25e91091bea1ecae6de#100", Less, ); test("4/3", "2", 1, Floor, "1.0", "0x1.0#1", Less); test("4/3", "2", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("4/3", "2", 1, Down, "1.0", "0x1.0#1", Less); test("4/3", "2", 1, Up, "2.0", "0x2.0#1", Greater); test("4/3", "2", 1, Nearest, "2.0", "0x2.0#1", Greater); test("4/3", "2", 10, Floor, "1.648", "0x1.a60#10", Less); test("4/3", "2", 10, Ceiling, "1.65", "0x1.a68#10", Greater); test("4/3", "2", 10, Down, "1.648", "0x1.a60#10", Less); test("4/3", "2", 10, Up, "1.65", "0x1.a68#10", Greater); test("4/3", "2", 10, Nearest, "1.65", "0x1.a68#10", Greater); test( "4/3", "2", 100, Floor, "1.64978695749086964173777306906", "0x1.a6587023ca668d7d15d42a6a6#100", Less, ); test( "4/3", "2", 100, Ceiling, "1.649786957490869641737773069062", "0x1.a6587023ca668d7d15d42a6a8#100", Greater, ); test( "4/3", "2", 100, Down, "1.64978695749086964173777306906", "0x1.a6587023ca668d7d15d42a6a6#100", Less, ); test( "4/3", "2", 100, Up, "1.649786957490869641737773069062", "0x1.a6587023ca668d7d15d42a6a8#100", Greater, ); test( "4/3", "2", 100, Nearest, "1.649786957490869641737773069062", "0x1.a6587023ca668d7d15d42a6a8#100", Greater, ); test("4/3", "22/7", 1, Floor, "2.0", "0x2.0#1", Less); test("4/3", "22/7", 1, Ceiling, "4.0", "0x4.0#1", Greater); test("4/3", "22/7", 1, Down, "2.0", "0x2.0#1", Less); test("4/3", "22/7", 1, Up, "4.0", "0x4.0#1", Greater); test("4/3", "22/7", 1, Nearest, "2.0", "0x2.0#1", Less); test("4/3", "22/7", 10, Floor, "2.141", "0x2.24#10", Less); test("4/3", "22/7", 10, Ceiling, "2.145", "0x2.25#10", Greater); test("4/3", "22/7", 10, Down, "2.141", "0x2.24#10", Less); test("4/3", "22/7", 10, Up, "2.145", "0x2.25#10", Greater); test("4/3", "22/7", 10, Nearest, "2.141", "0x2.24#10", Less); test( "4/3", "22/7", 100, Floor, "2.141515087948159535688532991747", "0x2.243a5532a0bea4119018af588#100", Less, ); test( "4/3", "22/7", 100, Ceiling, "2.141515087948159535688532991751", "0x2.243a5532a0bea4119018af58c#100", Greater, ); test( "4/3", "22/7", 100, Down, "2.141515087948159535688532991747", "0x2.243a5532a0bea4119018af588#100", Less, ); test( "4/3", "22/7", 100, Up, "2.141515087948159535688532991751", "0x2.243a5532a0bea4119018af58c#100", Greater, ); test( "4/3", "22/7", 100, Nearest, "2.141515087948159535688532991751", "0x2.243a5532a0bea4119018af58c#100", Greater, ); } #[test] fn agm_ratonal_prec_round_fail() { assert_panic!(Float::agm_rational_prec_round( Rational::ONE, Rational::ONE, 0, Floor )); assert_panic!(Float::agm_rational_prec_round_val_ref( Rational::ONE, &Rational::ONE, 0, Floor )); assert_panic!(Float::agm_rational_prec_round_ref_val( &Rational::ONE, Rational::ONE, 0, Floor )); assert_panic!(Float::agm_rational_prec_round_ref_ref( &Rational::ONE, &Rational::ONE, 0, Floor )); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_agm_rational() { fn test(s: &str, t: &str, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); assert_eq!( NiceFloat(primitive_float_agm_rational(&u, &v)), NiceFloat(out) ); } test::("0", "0", 0.0); test::("123", "0", 0.0); test::("-123", "0", 0.0); test::("0", "123", 0.0); test::("0", "-123", 0.0); test::("-1", "-2", f32::NAN); test::("1", "2", 1.456791); test::("24", "6", 13.458172); test::("-1", "22/7", f32::NAN); test::("22/7", "-1", f32::NAN); test::("22/7", "22/7", 3.142857); test::("1", "2", 1.456791); test::("1", "4/3", 1.1606759); test::("4/3", "2", 1.649787); test::("4/3", "22/7", 2.141515); test::("0", "0", 0.0); test::("123", "0", 0.0); test::("-123", "0", 0.0); test::("0", "123", 0.0); test::("0", "-123", 0.0); test::("-1", "-2", f64::NAN); test::("1", "2", 1.4567910310469068); test::("24", "6", 13.458171481725616); test::("-1", "22/7", f64::NAN); test::("22/7", "-1", f64::NAN); test::("22/7", "22/7", 3.142857142857143); test::("1", "2", 1.4567910310469068); test::("1", "4/3", 1.1606758921198568); test::("4/3", "2", 1.6497869574908697); test::("4/3", "22/7", 2.1415150879481595); } #[allow(clippy::needless_pass_by_value)] fn agm_prec_round_properties_helper( x: Float, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (agm, o) = x.clone().agm_prec_round(y.clone(), prec, rm); assert!(agm.is_valid()); let (agm_alt, o_alt) = x.clone().agm_prec_round_val_ref(&y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = x.agm_prec_round_ref_val(y.clone(), prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = x.agm_prec_round_ref_ref(&y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.agm_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.agm_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_agm, rug_o) = rug_agm_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm) ); assert_eq!(rug_o, o); } if !extreme { let (agm_alt, o_alt) = agm_prec_round_extended(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } if agm.is_normal() && agm > 0u32 { let (min, max) = if x <= y { (&x, &y) } else { (&y, &x) }; if o != Greater { assert!(agm <= *max); } if o != Less { assert!(agm >= *min); } if !extreme { assert_eq!(agm.get_prec(), Some(prec)); let rx = Rational::exact_from(&x); let ry = Rational::exact_from(&y); if o != Greater { let arith = (&rx + &ry) >> 1u32; assert!(agm <= arith); } if o != Less { let geom_squared = rx * ry; assert!(Rational::exact_from(&agm).square() >= geom_squared); } } } else { assert_eq!(o, Equal); } let (agm_alt, o_alt) = y.agm_prec_round_ref_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.agm_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(agm.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.agm_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn agm_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_9().test_properties(|(x, y, prec, rm)| { agm_prec_round_properties_helper(x, y, prec, rm, false); }); float_float_unsigned_rounding_mode_quadruple_gen_var_10().test_properties( |(x, y, prec, rm)| { agm_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_sign_negative() { let (agm, o) = x.agm_prec_round_ref_ref(&x, prec, rm); let (agm_alt, o_alt) = Float::from_float_prec_round_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } let (agm, o) = x.agm_prec_round_ref_val(Float::NAN, prec, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NAN.agm_prec_round_val_ref(&x, prec, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = x.agm_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_INFINITY.agm_prec_round_val_ref(&x, prec, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); }); float_unsigned_rounding_mode_triple_gen_var_17().test_properties(|(x, prec, rm)| { let (agm, o) = x.agm_prec_round_ref_val(Float::INFINITY, prec, rm); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); let (agm, o) = Float::INFINITY.agm_prec_round_val_ref(&x, prec, rm); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); }); float_unsigned_rounding_mode_triple_gen_var_18().test_properties(|(x, prec, rm)| { let (agm, o) = x.agm_prec_round_ref_val(Float::ZERO, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::ZERO.agm_prec_round_val_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = x.agm_prec_round_ref_val(Float::NEGATIVE_ZERO, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_ZERO.agm_prec_round_val_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn agm_prec_properties_helper(x: Float, y: Float, prec: u64, extreme: bool) { let (agm, o) = x.clone().agm_prec(y.clone(), prec); assert!(agm.is_valid()); let (agm_alt, o_alt) = x.clone().agm_prec_val_ref(&y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = x.agm_prec_ref_val(y.clone(), prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = x.agm_prec_ref_ref(&y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.agm_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.agm_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (rug_agm, rug_o) = rug_agm_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm) ); assert_eq!(rug_o, o); if !extreme { let (agm_alt, o_alt) = agm_prec_round_extended(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } if agm.is_normal() && agm > 0u32 { let (min, max) = if x <= y { (&x, &y) } else { (&y, &x) }; if o != Greater { assert!(agm <= *max); } if o != Less { assert!(agm >= *min); } assert_eq!(agm.get_prec(), Some(prec)); if !extreme { let rx = Rational::exact_from(&x); let ry = Rational::exact_from(&y); if o != Greater { let arith = (&rx + &ry) >> 1u32; assert!(agm <= arith); } if o != Less { let geom_squared = rx * ry; assert!(Rational::exact_from(&agm).square() >= geom_squared); } } } else { assert_eq!(o, Equal); } let (agm_alt, o_alt) = x.agm_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = y.agm_prec_ref_ref(&x, prec); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } #[test] fn agm_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { agm_prec_properties_helper(x, y, prec, false); }); float_float_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { agm_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_sign_negative() { let (agm, o) = x.agm_prec_ref_ref(&x, prec); let (agm_alt, o_alt) = Float::from_float_prec_ref(&x, prec); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } let (agm, o) = x.agm_prec_ref_val(Float::NAN, prec); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NAN.agm_prec_val_ref(&x, prec); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = x.agm_prec_ref_val(Float::NEGATIVE_INFINITY, prec); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_INFINITY.agm_prec_val_ref(&x, prec); assert!(agm.is_nan()); assert_eq!(o, Equal); }); float_unsigned_pair_gen_var_6().test_properties(|(x, prec)| { let (agm, o) = x.agm_prec_ref_val(Float::INFINITY, prec); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); let (agm, o) = Float::INFINITY.agm_prec_val_ref(&x, prec); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); }); float_unsigned_pair_gen_var_7().test_properties(|(x, prec)| { let (agm, o) = x.agm_prec_ref_val(Float::ZERO, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::ZERO.agm_prec_val_ref(&x, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = x.agm_prec_ref_val(Float::NEGATIVE_ZERO, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_ZERO.agm_prec_val_ref(&x, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn agm_round_properties_helper(x: Float, y: Float, rm: RoundingMode, extreme: bool) { let (agm, o) = x.clone().agm_round(y.clone(), rm); assert!(agm.is_valid()); let (agm_alt, o_alt) = x.clone().agm_round_val_ref(&y, rm); assert!(agm_alt.is_valid()); assert_eq!(o_alt, o); let (agm_alt, o_alt) = x.agm_round_ref_val(y.clone(), rm); assert!(agm_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let (agm_alt, o_alt) = x.agm_round_ref_ref(&y, rm); assert!(agm_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let mut x_alt = x.clone(); let o_alt = x_alt.agm_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.agm_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if agm.is_normal() && agm > 0u32 { let (min_xy, max_xy) = if x <= y { (&x, &y) } else { (&y, &x) }; if o != Greater { assert!(agm <= *max_xy); } if o != Less { assert!(agm >= *min_xy); } if !extreme { assert_eq!( agm.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); let rx = Rational::exact_from(&x); let ry = Rational::exact_from(&y); if o != Greater { let arith = (&rx + &ry) >> 1u32; assert!(agm <= arith); } if o != Less { let geom_squared = rx * ry; assert!(Rational::exact_from(&agm).square() >= geom_squared); } } } else { assert_eq!(o, Equal); } let (agm_alt, o_alt) = x.agm_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_agm, rug_o) = rug_agm_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm) ); assert_eq!(rug_o, o); } if !extreme { let prec = max(x.significant_bits(), y.significant_bits()); let (agm_alt, o_alt) = agm_prec_round_extended(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); } if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } let (agm_alt, o_alt) = y.agm_round_ref_ref(&x, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.agm_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(agm.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.agm_round_ref_ref(&y, Exact)); } } #[test] fn agm_round_properties() { float_float_rounding_mode_triple_gen_var_33().test_properties(|(x, y, rm)| { agm_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_34().test_properties(|(x, y, rm)| { agm_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { if !x.is_sign_negative() { let (agm, o) = x.agm_round_ref_ref(&x, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&x)); assert_eq!(o, Equal); } let (agm, o) = x.agm_round_ref_val(Float::NAN, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NAN.agm_round_val_ref(&x, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = x.agm_round_ref_val(Float::NEGATIVE_INFINITY, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_INFINITY.agm_round_val_ref(&x, rm); assert!(agm.is_nan()); assert_eq!(o, Equal); }); float_rounding_mode_pair_gen_var_32().test_properties(|(x, rm)| { let (agm, o) = x.agm_round_ref_val(Float::INFINITY, rm); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); let (agm, o) = Float::INFINITY.agm_round_val_ref(&x, rm); assert_eq!(agm, Float::INFINITY); assert_eq!(o, Equal); }); float_rounding_mode_pair_gen_var_33().test_properties(|(x, rm)| { let (agm, o) = x.agm_round_ref_val(Float::ZERO, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::ZERO.agm_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = x.agm_round_ref_val(Float::NEGATIVE_ZERO, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::NEGATIVE_ZERO.agm_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn agm_properties_helper(x: Float, y: Float, extreme: bool) { let agm = x.clone().agm(y.clone()); assert!(agm.is_valid()); let agm_alt = x.clone().agm(&y); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let agm_alt = (&x).agm(y.clone()); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let agm_alt = (&x).agm(&y); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let mut x_alt = x.clone(); x_alt.agm_assign(y.clone()); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); let mut x_alt = x.clone(); x_alt.agm_assign(&y); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&agm)); let agm_alt = x .agm_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let agm_alt = x .agm_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let agm_alt = x.agm_round_ref_ref(&y, Nearest).0; assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); let rug_agm = rug_agm(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_agm)), ComparableFloatRef(&agm), ); if !extreme { let prec = max(x.significant_bits(), y.significant_bits()); let agm_alt = agm_prec_round_extended(x.clone(), y.clone(), prec, Nearest).0; assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); } if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } let agm_alt = y.agm(x); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); } #[test] fn agm_properties() { float_pair_gen().test_properties(|(x, y)| { agm_properties_helper(x, y, false); }); float_pair_gen_var_10().test_properties(|(x, y)| { agm_properties_helper(x, y, true); }); float_gen().test_properties(|x| { if !x.is_sign_negative() { assert_eq!(ComparableFloatRef(&(&x).agm(&x)), ComparableFloatRef(&x)); } let agm = (&x).agm(Float::NAN); assert!(agm.is_nan()); let agm = Float::NAN.agm(&x); assert!(agm.is_nan()); let agm = (&x).agm(Float::NEGATIVE_INFINITY); assert!(agm.is_nan()); let agm = Float::NEGATIVE_INFINITY.agm(&x); assert!(agm.is_nan()); }); float_gen_var_15().test_properties(|x| { let agm = (&x).agm(Float::INFINITY); assert_eq!(agm, Float::INFINITY); let agm = Float::INFINITY.agm(&x); assert_eq!(agm, Float::INFINITY); }); float_gen_var_4().test_properties(|x| { let agm = (&x).agm(Float::ZERO); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); let agm = Float::ZERO.agm(&x); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); let agm = (&x).agm(Float::NEGATIVE_ZERO); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); let agm = Float::NEGATIVE_ZERO.agm(&x); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); }); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_agm_properties_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { primitive_float_agm(x, y); }); } #[test] fn primitive_float_agm_properties() { apply_fn_to_primitive_floats!(primitive_float_agm_properties_helper); } #[test] fn agm_rational_prec_round_properties() { rational_rational_unsigned_rounding_mode_quadruple_gen_var_1().test_properties( |(x, y, prec, rm)| { let (agm, o) = Float::agm_rational_prec_round(x.clone(), y.clone(), prec, rm); assert!(agm.is_valid()); let (agm_alt, o_alt) = Float::agm_rational_prec_round_val_ref(x.clone(), &y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = Float::agm_rational_prec_round_ref_val(&x, y.clone(), prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = Float::agm_rational_prec_round_ref_ref(&x, &y, prec, rm); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } if agm.is_normal() && agm > 0u32 { let (min, max) = if x <= y { (&x, &y) } else { (&y, &x) }; if o != Greater { assert!(agm <= *max); } if o != Less { assert!(agm >= *min); } assert_eq!(agm.get_prec(), Some(prec)); if o != Greater { let arith = (&x + &y) >> 1u32; assert!(agm <= arith); } if o != Less { let geom_squared = &x * &y; assert!(Rational::exact_from(&agm).square() >= geom_squared); } } else { assert_eq!(o, Equal); } let (agm_alt, o_alt) = Float::agm_rational_prec_round_ref_ref(&y, &x, prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::agm_rational_prec_round_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(agm.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::agm_rational_prec_round_ref_ref(&x, &y, prec, Exact)); } }, ); rational_unsigned_rounding_mode_triple_gen_var_5().test_properties(|(x, prec, rm)| { let (agm, o) = Float::agm_rational_prec_round_ref_ref(&x, &x, prec, rm); let (agm_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm, o) = Float::agm_rational_prec_round_ref_val(&x, Rational::ZERO, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::agm_rational_prec_round_val_ref(Rational::ZERO, &x, prec, rm); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); }); } #[test] fn agm_rational_prec_properties() { rational_rational_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { let (agm, o) = Float::agm_rational_prec(x.clone(), y.clone(), prec); assert!(agm.is_valid()); let (agm_alt, o_alt) = Float::agm_rational_prec_val_ref(x.clone(), &y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = Float::agm_rational_prec_ref_val(&x, y.clone(), prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm_alt, o_alt) = Float::agm_rational_prec_ref_ref(&x, &y, prec); assert!(agm_alt.is_valid()); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); if x < 0u32 && y != 0u32 || y < 0u32 && x != 0u32 { assert!(agm.is_nan()); } if agm.is_normal() && agm > 0u32 { let (min, max) = if x <= y { (&x, &y) } else { (&y, &x) }; if o != Greater { assert!(agm <= *max); } if o != Less { assert!(agm >= *min); } assert_eq!(agm.get_prec(), Some(prec)); if o != Greater { let arith = (&x + &y) >> 1u32; assert!(agm <= arith); } if o != Less { let geom_squared = &x * &y; assert!(Rational::exact_from(&agm).square() >= geom_squared); } } else { assert_eq!(o, Equal); } let (agm_alt, o_alt) = Float::agm_rational_prec_ref_ref(&y, &x, prec); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); }); rational_unsigned_pair_gen_var_8().test_properties(|(x, prec)| { let (agm, o) = Float::agm_rational_prec_ref_ref(&x, &x, prec); let (agm_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); assert_eq!(ComparableFloatRef(&agm_alt), ComparableFloatRef(&agm)); assert_eq!(o_alt, o); let (agm, o) = Float::agm_rational_prec_ref_val(&x, Rational::ZERO, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); let (agm, o) = Float::agm_rational_prec_val_ref(Rational::ZERO, &x, prec); assert_eq!(ComparableFloatRef(&agm), ComparableFloatRef(&Float::ZERO)); assert_eq!(o, Equal); }); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_agm_rational_properties_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { rational_pair_gen().test_properties(|(x, y)| { primitive_float_agm_rational::(&x, &y); }); } #[test] fn primitive_float_agm_rational_properties() { apply_fn_to_primitive_floats!(primitive_float_agm_rational_properties_helper); } ================================================ FILE: malachite-float/tests/arithmetic/div.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use core::cmp::max; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::arithmetic::div::{ div_rational_prec_round_direct, div_rational_prec_round_direct_ref_ref, div_rational_prec_round_direct_ref_val, div_rational_prec_round_direct_val_ref, div_rational_prec_round_naive, div_rational_prec_round_naive_ref_ref, div_rational_prec_round_naive_ref_val, div_rational_prec_round_naive_val_ref, rational_div_float_prec_round_direct, rational_div_float_prec_round_direct_ref_ref, rational_div_float_prec_round_direct_ref_val, rational_div_float_prec_round_direct_val_ref, rational_div_float_prec_round_naive, rational_div_float_prec_round_naive_ref_ref, rational_div_float_prec_round_naive_ref_val, rational_div_float_prec_round_naive_val_ref, }; use malachite_float::emulate_float_float_to_float_fn; use malachite_float::test_util::arithmetic::div::{ div_prec_round_naive, rug_div, rug_div_prec, rug_div_prec_round, rug_div_rational, rug_div_rational_prec, rug_div_rational_prec_round, rug_div_rational_round, rug_div_round, rug_rational_div_float_prec, rug_rational_div_float_prec_round, rug_rational_div_float_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_23, float_float_rounding_mode_triple_gen_var_24, float_float_rounding_mode_triple_gen_var_25, float_float_rounding_mode_triple_gen_var_26, float_float_rounding_mode_triple_gen_var_27, float_float_rounding_mode_triple_gen_var_28, float_float_rounding_mode_triple_gen_var_32, float_float_unsigned_rounding_mode_quadruple_gen_var_4, float_float_unsigned_rounding_mode_quadruple_gen_var_8, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_2, float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, float_pair_gen_var_8, float_pair_gen_var_9, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_5, float_rational_rounding_mode_triple_gen_var_6, float_rational_rounding_mode_triple_gen_var_10, float_rational_rounding_mode_triple_gen_var_11, float_rational_unsigned_rounding_mode_quadruple_gen_var_4, float_rational_unsigned_rounding_mode_quadruple_gen_var_5, float_rational_unsigned_rounding_mode_quadruple_gen_var_9, float_rational_unsigned_rounding_mode_quadruple_gen_var_10, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_2, float_rounding_mode_pair_gen, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_div() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let mut quotient_alt = x.clone(); quotient_alt /= y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let mut quotient_alt = x.clone(); quotient_alt /= &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_div( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef("ient), ); let quotient_alt = div_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("NaN", "NaN", "1.0", "0x1.0#1", "NaN", "NaN"); test("NaN", "NaN", "-1.0", "-0x1.0#1", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity", "NaN", "NaN"); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test( "Infinity", "Infinity", "0.0", "0x0.0", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", "-Infinity", "-Infinity", ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", "-Infinity", "-Infinity", ); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", "Infinity", "Infinity", ); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test("0.0", "0x0.0", "Infinity", "Infinity", "0.0", "0x0.0"); test("0.0", "0x0.0", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "0.0", "0x0.0", "NaN", "NaN"); test("0.0", "0x0.0", "-0.0", "-0x0.0", "NaN", "NaN"); test("0.0", "0x0.0", "1.0", "0x1.0#1", "0.0", "0x0.0"); test("0.0", "0x0.0", "-1.0", "-0x1.0#1", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test("-0.0", "-0x0.0", "Infinity", "Infinity", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-Infinity", "-Infinity", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0", "NaN", "NaN"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "NaN", "NaN"); test("-0.0", "-0x0.0", "1.0", "0x1.0#1", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-1.0", "-0x1.0#1", "0.0", "0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test("123.0", "0x7b.0#7", "Infinity", "Infinity", "0.0", "0x0.0"); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", "-0.0", "-0x0.0", ); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "Infinity", "Infinity"); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", "-Infinity", "-Infinity", ); test("123.0", "0x7b.0#7", "1.0", "0x1.0#1", "123.0", "0x7b.0#7"); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", "-123.0", "-0x7b.0#7", ); test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "-0.0", "-0x0.0"); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", "0.0082", "0x0.0218#7", ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", "-0.0082", "-0x0.0218#7", ); test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "0.5", "0x0.8#1"); test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "0.5", "0x0.8#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "0.5", "0x0.8#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "0.5", "0x0.8#2"); test("1.0", "0x1.000#10", "2.0", "0x2.00#10", "0.5", "0x0.800#10"); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "0.45015815807855308", "0x0.733d90a6f99888#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-0.45015815807855308", "-0x0.733d90a6f99888#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "-0.45015815807855308", "-0x0.733d90a6f99888#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0.45015815807855308", "0x0.733d90a6f99888#53", ); // - in div_float_significands_same_prec_lt_w // - increment_exp in div_float_significands_same_prec_lt_w // - (q0 + 2) & (mask >> 1) <= 2 in div_float_significands_same_prec_lt_w // - h == 0 && l < y in div_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "1.0", "0x1.0#1"); // - !increment_exp in div_float_significands_same_prec_lt_w // - (q0 + 2) & (mask >> 1) > 2 in div_float_significands_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_lt_w // - rm == Nearest in div_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (quotient & shift_bit) != 0) in // div_float_significands_same_prec_lt_w test("1.0", "0x1.0#2", "1.5", "0x1.8#2", "0.8", "0x0.c#2"); // - h != 0 || l >= y in div_float_significands_same_prec_lt_w test("1.5", "0x1.8#2", "1.0", "0x1.0#2", "1.5", "0x1.8#2"); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & shift_bit) == 0)) in // div_float_significands_same_prec_lt_w test("1.0", "0x1.0#3", "1.2", "0x1.4#3", "0.8", "0x0.c#3"); // - in div_float_significands_same_prec_w // - increment_exp in div_float_significands_same_prec_w // - hi == 0 && lo < y in div_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", ); // - !increment_exp in div_float_significands_same_prec_w // - round_bit == 0 in div_float_significands_same_prec_w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_w // - rm == Nearest in div_float_significands_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & 1) == 0)) in // div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", "0.99999999999999999989", "0x0.fffffffffffffffe#64", ); // - hi != 0 || lo >= y in div_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", ); // - rm == Nearest || round_bit != 0 && (sticky_bit != 0 || (quotient & 1) != 0) in // div_float_significands_same_prec_w test( "1.0000000000000000002", "0x1.0000000000000004#64", "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000001", "0x1.0000000000000002#64", ); // - round_bit != 0 in div_float_significands_same_prec_w test( "3.1790543009742223972e-11", "0x2.2f43e0add6ebd01cE-9#64", "7770090901.6225594673", "0x1cf222d95.9f600ea8#64", "4.0913991113158902183e-21", "0x1.35232b1b3b9aeabeE-17#64", ); // - in div_float_significands_same_prec_gt_w_lt_2w // - increment_exp in div_float_significands_same_prec_gt_w_lt_2w // - in div_float_2_approx // - y_1 != Limb::MAX in div_float_2_approx // - r_1 == 0 in div_float_2_approx // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in div_float_significands_same_prec_gt_w_lt_2w // - s_2 == 0 && s_1 <= y_1 && (s_1 != y_1 || s_0 < y_0) in // div_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", ); // - !increment_exp in div_float_significands_same_prec_gt_w_lt_2w // - s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) in // div_float_significands_same_prec_gt_w_lt_2w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in div_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in // div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", "0.99999999999999999995", "0x0.ffffffffffffffff0#65", ); // - r_1 != 0 in div_float_2_approx test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000011", "0x1.0000000000000002#65", "0.99999999999999999989", "0x0.fffffffffffffffe0#65", ); // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", "0.99999999999999999984", "0x0.fffffffffffffffd0#65", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in div_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000005", "0x1.0000000000000001#65", ); // - y_1 == Limb::MAX in div_float_2_approx test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", "2.06795153233048966839153112178982e-25", "0x4.00000007e000fffffff1000000E-21#107", ); // - in div_float_significands_long_by_short // - diff >= 0 in div_float_significands_long_by_short // - in limbs_div_limb_to_out_mod_with_fraction // - d.get_highest_bit() in limbs_div_limb_to_out_mod_with_fraction // - sticky_bit != 0 || diff >= 0 || i >= abs_diff in div_float_significands_long_by_short // - tmp[ys_len] == 0 in div_float_significands_long_by_short // - tmp[ys_len] == 0 && shift != 0 in div_float_significands_long_by_short // - round_bit != 0 || sticky_bit != 0 in div_float_significands_long_by_short // - rm == Nearest in div_float_significands_long_by_short // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (ys[0] & shift_bit) != 0) in // div_float_significands_long_by_short // - rm == Nearest && !overflow in div_float_significands_long_by_short test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "0.8", "0x0.c#2"); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (ys[0] & shift_bit) == 0)) in // div_float_significands_long_by_short test("1.0", "0x1.0#1", "1.2", "0x1.4#3", "0.8", "0x0.c#3"); // - tmp[ys_len] != 0 in div_float_significands_long_by_short // - tmp[ys_len] != 0 && shift != 0 in div_float_significands_long_by_short test("1.5", "0x1.8#2", "1.2", "0x1.4#3", "1.2", "0x1.4#3"); // - round_bit == 0 && sticky_bit == 0 in div_float_significands_long_by_short test("1.5", "0x1.8#2", "1.5", "0x1.8#3", "1.0", "0x1.0#3"); // - tmp[ys_len] == 0 && shift == 0 in div_float_significands_long_by_short // - c >= u - c in div_float_significands_long_by_short test( "1539239.2465826685826", "0x177ca7.3f200ab152a#64", "0.00009", "0x0.0006#3", "16812597210.673628039", "0x3ea1bdfda.ac72e31c#64", ); // - c < u - c in div_float_significands_long_by_short // - round_bit == 0 in div_float_significands_long_by_short test( "1.7088961703394199635e-73", "0x4.d4baa70e83509ad8E-61#64", "1.7359472818744e-34", "0xe.6bf39991dcE-29#42", "9.844170892645193631e-40", "0x5.5c13c13c6d059800E-33#64", ); // - tmp[ys_len] != 0 && shift == 0 in div_float_significands_long_by_short test( "4.874956728709606165589080471392071684004548689044982493122e-71", "0x5.6220e3ededa8be921ace72bbb95a16164a2f0abd57c49f18E-59#192", "1.5092483e-10", "0xa.5f190E-9#22", "3.230056172437141772802006354545046772521759341614858124236e-61", "0x8.4e07636cdfc96e412c1de0a522f40a5f092091c1a3aa159E-51#192", ); test( "6.88621557179233820703925296804982406452e-28", "0x3.68ee78c4dbb67961d201a40495749728E-23#127", "0.1418399214207466117788070203268", "0x0.244f9effc4f1edfd85dfab3008#99", "4.85492060543760755133907256608679730501e-27", "0x1.80a57d020f8b7083401eec627a6787ccE-22#127", ); // - in div_float_significands_general // - up[u_size - 1] == vp[vsize - 1] in div_float_significands_general // - k == 0 || l == 0 in div_float_significands_general // - up[k] == vp[l] && l != 0 in div_float_significands_general // - q0size < MPFR_DIV_THRESHOLD || vsize < MPFR_DIV_THRESHOLD in div_float_significands_general // - rm != Nearest || shift != 0 second time in div_float_significands_general // - qqsize > u_size in div_float_significands_general // - qqsize > u_size && !extra_bit in div_float_significands_general // - vsize >= qsize in div_float_significands_general // - in limbs_div_helper // - ds_len == 2 in limbs_div_helper // - qsize == q0size in div_float_significands_general // - vsize <= qsize in div_float_significands_general // - rm == Nearest second time in div_float_significands_general // - !goto_truncate_check_qh && !goto_sub_1_ulp && !goto_sub_1_ulp && !goto_sub_2_ulp in // div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) in div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit == 0 in // div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000005", "0x1.0000000000000001#65", "0.99999999999999999995", "0x0.ffffffffffffffff0#65", ); // - up[u_size - 1] != vp[vsize - 1] in div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000011", "0x1.0000000000000002#65", "0.99999999999999999989", "0x0.fffffffffffffffe0#65", ); // - qqsize > u_size && extra_bit in div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 in // div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && !carry // first time in div_float_significands_general test( "1.5", "0x1.8#2", "1.00000000000000000005", "0x1.0000000000000001#65", "1.49999999999999999995", "0x1.7fffffffffffffff#65", ); // - ds_len > 1 in limbs_div_helper test( "12077.327578390390934514", "0x2f2d.53dc2d699afa78b8#75", "4.90332775049862782951473377323022738896770775e-11", "0x3.5e9a4013acb1890afeca956568e5bffe30edE-9#146", "246308796656764.923124719743308898445103382544", "0xe0043c546c7c.ec51e6d16d3ab81c76ba65494#146", ); // - vsize < qsize in div_float_significands_general test( "1917511442.613985761391508315964935868035476119276770671", "0x724ae712.9d2e2bbd62dd31f140b2b9b664635f251b18c0#180", "3.352896739388742667241376e25", "0x1.bbc08f6e851e14a094c4E+21#79", "5.718969570663133425280005234972069245666491961744252885e-17", "0x4.1ef6b3c1725013efb2a8179983b542a97b0131f39a938E-14#180", ); // - rm == Nearest && shift == 0 second time in div_float_significands_general // - qsize != q0size in div_float_significands_general test( "1.490328e-27", "0x7.61370E-23#20", "2.89262335038499315783322011549431655756e-75", "0x1.4ef161f7b7fc2c6cb4464f827b58b972E-62#128", "5.15216656741446303242577558053691246166e47", "0x5.a3f1d299f6f20544fbba161403f075f8E+39#128", ); // - rm == Floor || rm == Down || (round_bit == 0 && sticky == 0) in // div_float_significands_general test( "2.38418579101562499999949513e-7", "0x3.fffffffffffffffffc0000E-6#87", "2113929216.0", "0x7e000000.000000000#66", "1.12784561231761934265233937e-16", "0x8.208208208208208200000E-14#87", ); // - k != 0 && l != 0 in div_float_significands_general // - up[k] != vp[l] first time in div_float_significands_general // - up[k] != vp[l] second time in div_float_significands_general test( "65535.99999999999999994", "0xffff.fffffffffffffc#70", "22835963083295358096932575511189670382427701248.00000000000000022202", "0x3fffffffffffffffffffffffff8000007000000.0000000000000fff8#219", "2.869859254937225361249367321235116718339077564583058127288930659162e-42", "0x3.fffffffffffffffff000000007fffff8ffffffffffe000001c00008E-35#219", ); // - up[k] == vp[l] first time in div_float_significands_general test( "1.91561942608236107295e53", "0x2.0000000000000000E+44#66", "43556142965880123323311949751266331066368.000061035156249999998", "0x8000000000000000000000000000000000.0003fffffffffffff8#205", "4398046511103.99999999999999999999999999999999383702417796084544", "0x3ffffffffff.ffffffffffffffffffffffffffe00000000000004#205", ); // - up[k] == vp[l] && l == 0 second time in div_float_significands_general test( "255.99999999813735485076904", "0xff.fffffff800000000000#82", "1.35525271559701978119405335351978053e-20", "0x3.ffffffffe0000000000000000000E-17#114", "18889465931478580854784.0", "0x4000000000000000000.0000000000#114", ); // - q0size >= MPFR_DIV_THRESHOLD && vsize >= MPFR_DIV_THRESHOLD in // div_float_significands_general // - u_size < n << 1 in div_float_significands_general // - vsize < n in div_float_significands_general // - in limbs_float_div_high // - len >= MPFR_DIVHIGH_TAB.len() in limbs_float_div_high // - k != 0 in limbs_float_div_high // - q_high != 0 in limbs_float_div_high // - carry == 0 in limbs_float_div_high // - carry != 0 in limbs_float_div_high // - len < MPFR_DIVHIGH_TAB.len() in limbs_float_div_high // - k == 0 in limbs_float_div_high // - len > 2 in limbs_float_div_high // - qh == 1 in div_float_significands_general // - in round_helper_2 // - err0 > 0 in round_helper_2 // - err0 > prec && prec < err in round_helper_2 // - s != Limb::WIDTH in round_helper_2 // - n != 0 && tmp != 0 && tmp != mask in round_helper_2 // - round_helper_2 in div_float_significands_general // - rm == Nearest first time in div_float_significands_general // - rm == Nearest && shift != 0 first time in div_float_significands_general // - rm == Nearest && round_bit == 0 in div_float_significands_general test( "914122363545.7300954288539961362078521335512160921125366724096502748846903936195389924148\ 154757063704910629280973433563521737016298541257057972452261335506117124831272191707877190\ 2119190824963185068512647039440777212199983388696", "0xd4d5f05299.bae788b5e312f78f55ac79e4ca82e12494296afdb40ba21e0c21a4b3915ba2e217c389f8c9fd\ 22042f5ed70da20cfb9f1ee797b1433e077a2d34b1ae5781f975eebbcb21a32ee0c5afa5e59f8f382fe0c754a4\ a3fb57fa4d668#754", "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ 9912721166210129145585", "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ 02af09995fd6ced97b00#1859", "9.161757985214429764992710266551647359057325985892606639113002591596898046569993924851132\ 469009506849046579846739625666450546615840413944516736833310444241924771226669449467280905\ 847180462085951493210441487438964221396785151298524525494386941673630175499486324164244756\ 513337189186243674611400515366863669226025015162200893355049656715514081022497216123358900\ 204159965608607573130556648229035236124949246847315199932950877590362471534070708393335471\ 028355306786566135185894674384218244976402468322690432705335567965983855642753641740432604\ 3437409476409135277542e-112", "0x8.d032a1c09c5a822250facc4d03dcbdde26d4f5fe102c1e08a4f87e413b615d798e202484a718a7e4ee277\ 3677de7769fc7d817e371393d771d3460b42f92e9ba23196df3ebdff7cdda4294aecfb6c43776a893a979bdc8c\ cac166e11d435edd52a1481ecb355a6595fcd794f14478ca886b31b8422e8bc9fdcdbc2261e6c6dfdfea3875fd\ d48e82b6f89b37437a8064efc36e3671100bf00cb530951d17bbaefe545249991b357ff0fbc5a593a69916e391\ e844f20336e8635a395cbda774a8ed440b65ccac5a4a48827068b6780bdeecccb424ecbcea085547d055a670dd\ a2ce7fd1bc8ccfff3fcE-93#1859", ); // - q_high == 0 in limbs_float_div_high test( "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ 62431384255329048179650372924700507846477189871631671161154559755984562472291", "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", "1.150400792350488243006374252439239370084430198894097883408930056885079539097149903334801\ 351771948494649335504249165228317854781872084884358035626531528587565616792440130659246789\ 547068913471358728267587391921067763401960740658485999234360708658257354709138940743401019\ 478517400580149085993404074744575447821383623813098520973947955049547026992303475579228215\ 436224676800479021561310494945776720018368502752527214637080415175177143606297950367602304\ 149567232708944245857383841379350871799797376084773487408407355299732079377175164962925047\ 553551234005632068337070468847266947004802579875459884664958168707856865409967591741263680\ 896819771668163339399940221050773763868745744855354003266260565352234279551485173590767169\ 460117377689246074482291141675360319952860733464727767370984256722737643645180588444886771\ 648355387388454942423178644791668457452750839522592156007162798991977390140623536578544490\ 057707937271642210929120388296125663413585185722459999909564986042307052548228205977082023\ 238981495642981332360042089388607651948288196055583153394379775735995327224157713864077477\ 321557707540034099204193983589868016082915953745995091314702115380175700364741814725184464\ 602065018950641261052531311066491931955988616475785792821351515116629573461861957542243077\ 532642867446492701937719979200426618485741197144774966492676324343483017759514367363624027\ 675809506514516688590348320872084123672477458766804242125009602995249222201904595636534318\ 096670348004414769559053243712710972449074750435098780379781902955436286126620063025099547\ 80435463720060716005725004637793753168276780047800093479230422676842555945701e-42", "0x1.9a7a0a4405b5655db3032989d155cf7a58151a06aacabc4789fac720edfb0e835fe88bc9af3cc179149fe\ 616753cd76b4c7d9c17f2f47389f4e0007572679dad2a5316ede08c14af0283577f171d41d795d4ff13631def2\ 630089c6f215d7b5b8948c52ff97a4a1d9f1eb6d67b60e55478c40ffd2a7cd9684f43637e46ce3ce3e33085654\ 9165c4a377c6ab1dbb9c9b40ece8c47d94ddd1318dd2e5e57388b2e8ef80705d97c3db61d805c43cf7ff7a9a1e\ 41ded3ff033e68dc751b34ffd9cf2eae50cb7e7875b9d8f24116927cd9f609a65c71e840166cf535bbf110404d\ bc493350b17705c0e23a9091d61f544117f70c6c6387dfb9a1dcc2f513cfbebc4cdd4b7d94c9fc57ceebebe3a2\ e7d85b9b488b5571ef7b7c8621b770d99c67f9a19252ec5f9be4b129c7755b4a8585b97ea68e60e390c0b5c2b2\ 7b5fc3a47825c136e3b2517a6a7490ae84cf61659a9b819bfe59d45f7254dd48e028c7b694a9b9b427e60358fd\ 52afbeed855580a61e351d523d4ffaabfc7ca00e9a5b40128e9fd8b2998c189e95abc1857ff9ddf1dac904a2de\ dfce45cbc4f1ffac50c26ec7e1135aa9ca96f6d3ac8cb3a6620a3aecb003d246eade4cf0e6394df920dfba899f\ 44ed41072e121f0402f19fc4c43c348467a07566df372a7b1af45354f2b4c7f94d52f355813e84c1a95202029c\ 0056a974e856e7c42fd6463561d1b5e02ed6a7e0ea0ca50887bd1047f4abd068ea61e2095abdad6a0cbaf91846\ a340717aa624d6c6ba02f5d3e835ff06c742f1343479ec9a9b184eaca8e7c8be7eaf4fa322afc13f046a4a2e5f\ 4e84c723c68079991a080ac6939780e172640d568c2bc3452c14317358ee8d27a18af7c9bf2de8bea3e5b8b113\ d8e61b810d6103e805c2a8f85b9b88f8c9129b924ba95521aa83a066991bea980c8be16f1df53E-35#5329", ); // - qh != 1 in div_float_significands_general test( "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ 3791636230633361526548302742414616516594455084620537903358416e-16", "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ 3a2e81ad38c5d7f45687a8E-13#2587", "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ 61698637621752755004821872e-17", "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ d817f0420227841d34052ed2bd52e148923f8E-15#1571", "43.78305573046740119713641861874642911154821650761595780287653003720809501996262685108891\ 851641972710141298162279987632328545443442081070773994511258975201978303856309243168868354\ 195798884971190979692045031917290903217918542303368118161338247041052975773351929884789101\ 115569142934332750399827875003719838494787907290778719530315375971295186399328856671813524\ 401338950750393532748258170809380674066918530153006391759208813425198252649570832466781508\ 205219467712658427254330831981130973959961174357861904110964877950640959685965415405374479\ 749995867814629083616329619361738872731212580413192190669870683344353586783786957328312637\ 080558281918488071596583884466679323108552730394571978915258990045025562636051246193761815\ 9037942507064891051161378037771712070204599081778501997567779", "0x2b.c87657214d897953f5e5edbb169c290285fbd11622c9cf401ba99ad9f03da7ffc778df1db0d888d67c18\ 379efc8b4b36ed8cbb67da04b5b4cfdabc5f751b0a6fc68b1e3a2a16a62c4160ce4d10e00ae47020ca5d3867a7\ 2213145fe6456480971ef0cb9716c6136384fe41721979e86d1ea1bdc104f2967865add528a1367b01cc449a48\ 5786a74209d8e4c5e216fa7ae2dc897fd4926b55eacde3321f7c41bf2875c24933c8eecc7a8a26f738fd6d666b\ 678ec93b48bab7b34c5392d3ca76949dab6958fa5caaf70927d3e8b40d050bb607bc1b4fe656506e1b3e468e87\ 8b257c21e926286697a97538d3230475cd54415b8154351e72363b4b7509061108fc6ac5db47219368f3ca4011\ 5309edd7318a116c2b62a34277bfdc8a1faf656b14b6a046087cfc5dd238cd94fe91967fb6dfc52f8afa5699df\ e2970ca40fb03c71d7d668#2587", ); // - n != 0 && tmp == 0 in round_helper_2 // - s != Limb::WIDTH first time in round_helper_2 test( "0.029226865494398284939675773661541675546326681033634876986774906885711036844605915426240\ 340310096249605517533494947862661721742262334681480455706389428160732541825851560446846541\ 984468705310228771603694136853587701004882713625816107989162498255925332620064155091399923\ 221735997586925448254801064429910518067322424203818026901404115120552071966804127784634236\ 948421057038304255272147630765439482924461011451862112889343084859504616664030668233890526\ 750016895266382189553251377266295422223247821668554701473442441938933867323625955488726630\ 366895993417469747854898337776376811834753617592182604418498468334055402941851068346511528\ 636460609896950078921029074658151972716364203699936241491820871671807186599907001653993018\ 871354678119954470481273332266267481346670395677171242596948926022697465301700258863974068\ 74909984356479995046141060221761701111762543380195142151878885588292130260647185", "0x0.077b696f76893b930df354ab0e34b0df1508ee4503f673e22fa3b41867c5e4ffbc43b589d4cb4a00c472e\ 4046ccc9dd4a2b88b59dde14b46da030dc5a0f825fc1d9ff0213e8b046b1cd79785dd554b78e98759eae454c23\ 4fddf6ee7ae174bfc7c1ed096e905b41ce6b18511a9bfc9cfbc43c536393410fe83a634f402b0f18a446a3af90\ 9a4079394959da6918bd9094c5b587839c67f902f1f107259257f4ae96549552e41dbe7dbaddda5b9d8fa2b2bd\ d01ba920c27d6ff6e44bd8f0ef230d60508f693680e1d769f920949bd35768a7ff10fa62210e3caf84f93cdccb\ a5238b5e4be804a1422da22abe509c758d0cf44f202896613342ffd0fa93939f0c9bcd4de899fb72b286773da8\ fe9cbfbd51894ec97176996bf2b6a61ac27a5f524cd408e8bca09d7cefc329a98f17616d4b48652d0a3f14cc49\ a9bbe75a69ae9167aaa9d1951d446e95bb89c1760a549ff81f7b1d8ee454047a7d3c3e244dc499d97b256eca33\ 3d43933df1e0a046136e10#2940", "13755175900776476.03444104347769161034491994978466673515315430911280875941467408228432201\ 072744723926732268661761372710838010056791678637659254162102142124198282086034764229922487\ 783612307113854432839997318024745178344073274492535681224805316900558167281372795857375154\ 556654904332875058382920111153919687941523340022403648029377155100560618075774147398400587\ 446623619383420263487024723715538921428293815054071349051549046244877203394687286110159347\ 188168590858399073350484327515115795260226962105536078430163098017753828590552884767518140\ 1985404905771271934", "0x30de427563881c.08d120d36075efcee88657ce81cdcaedf45cd89aeca352b6e32212d20771ea31a54387b4\ 8b1eb8738ae1d31c6213ddc44bdc809d5f5b278e3449ebd13c9ab8d89ec9f0a2d87e7233cbd5128caca14e0c42\ 61e5c9ed6444b50d0cce082673e3c80b1a7102c8fc7520036bc3c6900dbcff7cecdf27ac4022bd4095736dba93\ f47ec8ed66154c32a8eb07e14079a264e1e3370aebbfeacf3a1bbfe7aa657d9911acc70d626a35a29d86c84029\ f97428f7cd8a3965838abf5dba9a9943b07c0ad2541156ef8e2aca1afd50c7dc55f986c835b95647701f744563\ d15716174f2ac444#1845", "2.124790384741531086324618396766014790807036315098759090708607153306148130187657728807205\ 824808003798574987452867827342282934278081982848900135498971286785256137258700150407383617\ 040883394430575593960834148265479663570529896251340120502267014474793716347382140126837773\ 997589830815187190064041312015350810806968062929485379465521677249527992330225473850965169\ 559943150658138282772411679190301632849325467452565481282203194749783450341076382685241552\ 308193411477432500590221491760317417660435511777399629140824293491122934845121250984106958\ 267596015361360781611025519421253206751640221273565905944385402975185311734694681019948131\ 664198303801199498616289444621169851399879692298796098215712787193626312888177618196672010\ 550069281366814417353104090880010484400040465312380510548737422916103805415326232623198929\ 338433641210905412883566788706510371353536321443505713555119784985687877546815e-18", "0x2.73209f5170c5b9aaeb5a7e9e79e1dba6ba9eb57b8701701f4d2be387a03993b7e53f907a48a9029ff962b\ 4eb20e6ade6771889642b19b1985ec76b2b24fb517b27eb86681dab6bc7d5a5a203545d850396986ce5c6f9542\ 50b478a0dd27222c6c45900f2d06dad9d7f78a79b9978e3ce203479c5dce6dde3affc40e370565c038007c8bc1\ ef1fdf0f6398b88721063c52e5eb2c4b5ba1f10d93710d5abe8aab35f5bc5cdf7031f7765dd4f9d4065b1b5b86\ 4ccd6665b73715bdfe783fae157cdc8a78e9d053cae011d4dddf28499ac3809e290ca0a221e38d2a6dd8d01980\ c64da2f6836e0815e2ae3feb8a0d765808afcbdf6df10cf661eaf6c064ec8023cad01912101fb7e8b732b555b4\ a053a203ab5ec17c24af5694ed7db4f67c3c76a7f360512bc9a2018d2860111211238048d21af3d79aa0904474\ 22c0d9c9883b2f3769a5fe3faeaf8bab1409329c376b70c7b54fe1393115359c5a7ff43560bc0e2548a02ffb68\ 184585e5023a6fb507d0E-15#2940", ); // - rm == Nearest && round_bit != 0 in div_float_significands_general // - rm == Nearest && round_bit != 0 && !carry in div_float_significands_general test( "767950667289861979450190915916317600206727962344150969868.8721759327117422801652737665276\ 756590281054535919141164571740727630029753345081284383462360338144272865435150624843971065\ 632159910277471560574746205336214689461444841220676837587640834824669960199738043592424986\ 826697488691269778053087892841924823231361961899657984958299046295741089107389167540777341\ 1137893901502419455", "0x1f51c7714fd0115fee394111538cd8cc2697edb4db72ae0c.df46ec035af05536a25a7e2694997099b2577e\ a12f12bb82f781cda7cd6a148cc07ab56a0bac9e90b8590cb04b95fcb27209c3c8704cb6940c7fb857c1688d50\ 6042d2fb6c58e0600ed4d86a5af398f029ebf3521880629fcd23f2bfd5f9447e8dee8310647fde5e5f5e2a0a18\ 7cdc4e8c046be95417ea73f5d4a1962ebecd092b613af810#1250", "51.02908107282950125513822733633990251324880237789609831750259919822628384179764854139813\ 664310170076349095466129599769105832710389521373306698912599298264052853550294941822816681\ 854313580668986120583821047373123379751687690065811623363578923931243167028825931454472450\ 957582633858214796963862561877157489833071159740156527107422181977546544800568916528954101\ 973657910504690951238460938847030239913388867386095316629182004723248011669496406544341717\ 280330814897033602543594303927085904297027340275835376721330553519116838042737905906942433\ 571685773257005175176741271374980135164819404821829229591371965448368260666618720681201228\ 891015077648242337901859343084853665103006650868094946302847691177013349096688713595881758\ 621480481903927608236275982505035171940737146501502983532266096788435188627685343250723400\ 305856753098249087347464717300786991295322157886984156263306019163631926110778355478267431\ 730519001037411438399866507817311259465545754442998333101310788661554118860610086857525556\ 649462275011688416941329847092728287810185063940836755796270353054485056127471728114260616\ 408519706805571508639638485588089026599284155688404740772260862102363921554760355678529807\ 545078380365647104062842403550988330511500383389703046031841433893387481098301402534069795\ 658730174573583314000979689827444189825731612831252242895060479770394162281620141901978731\ 360879005964038152579829187416621515149774573766217606037565254139422563209723838864340747\ 448492223949482531030183865551640816462517599780266133382572731428229045787209942986614817\ 192016158247860998226332096129248802519217902568127470669978186812858044800325333178140023\ 387809105983555698845635663825858578549915679237164757880235025950739307212793316009945989\ 415835829851915334677834156538103555704104713171341701847682567317855121655570126973890951\ 3929068030854124664713500553256", "0x33.0771db70bc3cc1bbfd03fee9ecfaaa1f99d76266a08107a7c922f5787496298c9bd6b5bfa13889bc0bb1\ 0f2e280f2673b20cb2191b3f747978b1483ed5890a8f1e9b4ef8665dff89aeff7e04820fcb58e76837b70b36b4\ 946ecf9ebe8fba5e510503f922f8e39500946e3ba0fd0a28c3a881101047c77426f1160e2835ecd5cdfc3c85d7\ 78adf772e0b5f5d5913cda27866ff4a68981bb0b247705d4a7a13e0cf5df9064561c207ad89d6bd10ed4faf445\ ceca3d7f86bbdcd652aaf5c547a0071a203dca41ee8ec829aff439308e3dd8d470556949fb583c7ed1bd6c7854\ bb629c27db1c0caa83e77e13d983d022e1865331aa5f67de9bca45976769e471933efa23a7d5fe8e03b8eed13a\ 3920db5d0f4052f811bcd1955c217ad35a8b75478eb3f2e077ecc810af955e23d57d0b957bf2104261c9f16ba6\ a16f119f6d83e2b35b1a28b6fc7a029bcec426c495328cba2082e252a65c7267a9a83365475cc6b4672f77d481\ 40ec81e987a366445896d2ae795891105da2f608b56dca4a3e4166c6a0338423e51de87dcbfe3717817893141c\ 8b61f1377d82379374f5ad121cb9e04cf51776a20bc8b0ccaa51862efa4f51d52333818ee4877c039261bcd8dc\ 152db0a6119f3724603b4aaf9994eaf197d5adbcb723d1dc6ebdd8d2cfd37952c4128f3b79556ea134b7193dcf\ afdc170fa41bf528ba4deac3f3d79d4407db9fd076aaca428efe74dbbc1bc7fad8b57ab1a693330f49aab1ddcc\ f26bdc853360568f201c8fea22c816ae67afff2668debe399f951e72144cfa93dea4f18d1ee734ed2bf350fed9\ d126c9b660f6b27ba5e13f15a8be20837e071c52d7588c0a856a969903419e91d47e7011235886759942c1c0e1\ 896e1621b2d23df869694531248722482999c8600632a5ab2279907e29cb3c38994bfbe299cb368a72ef45ecaa\ b9646b4f1e2f37f24aa954535b1ba220c8e91dfb8f81e56dc45ec4cb3181511fa5b1854096fb3f03f2aa052eb1\ 5111548f398b2a0ffeecd95498fef2bd7f25126507f63bd3803c3a9d1aff24563f7f0baf024307e9c75#6074", "15049274867282653916783425765897232338286237097021544510.63055696334657926692700975852105\ 429908991325181901560777184807721684871576977542689434849596891044659963521044055457283641\ 367304991334226236960366994118987961185804836414630696056584495778598754606288486597978327\ 332370268104018122071463105903604569912790301532188931593783003198530412792016208481406460\ 177569545284296438034561831086095957417103960718034276692579871391678752019863068680376188\ 441084892942908419595289335759422879108451807263984856494740183999962091220506257869533189\ 151879060260534882539324732360323776701789524149049182180697710000483323367419829770508959\ 886298233038628402259126153349007515813222501560286947664943532169644098519601985837510236\ 220345218089637472842801890223279059211522040546360301667071765816467200381174390649332596\ 068474921226001156721359127966627401319343668619013146928630922944213877247277873392955093\ 504639915667110210542526572018725370251615388653789028473354868425502960351888594917293217\ 742712292964655900915998259809033409553076012583762301750508167459913039705278696038307105\ 198133823120123667996810391703122691279674638629684591634520584549627376733588876153831722\ 199369165407756045645488517825617351416613370266999295351664343537186993481753740631996768\ 537474147168714208012012313452364629821090786481898210882140832386720226088895885830143936\ 713915428453413001094302216345205004980013281182978168058085052927135299009881922560519790\ 174395754146412113876346433499785448301225654969985504964945207336686282652994022882395571\ 250336046288750244045997533647713495015654011612857222465008362940468446125031495141758501\ 398188163302138089732641998828146315905675208381266922364102647252983963785718802006725178\ 667871858412814374481149992996719213942377608145948042933317201168269095689729130915320304\ 63030844892155532105060912300876", "0x9d1f2bb817353ba61ad13135f94f65b1b52180f58a183e.a16c2e5fd6b05e4155475ec873e35d0f193a9765\ ef45957a4681138fd789135172e7be4efd1b67c60d22430a10832c82a4dc4a53156de6d8638ce6ffe089ebf880\ f2e1c68c90b576b5dc0b99085865ed663bd642b7743ff5500d4c6d3e2cf4977af36122c98fc49e81ee87b80d89\ 3fe81fa07bdc5986b40bdb0bf7e6bfde432dcedd2063308cf685bfee2b964ff62d434434a9518683156e532f30\ 11f2ac8f98a75178cd412e00f2261a83f952b6a94bb97c280cb51f16f85891ddd7fe6ad8030e20422da11497e5\ efe8d88db4f96479fd0b16f3703dca8946d944979a3454bb8155d8dbdd3a765584148771967d02f798d157b6a1\ 59e10461bc83d8ec9e55b557614c35d75b391c0c9d04aefe96cab5078bd3a13d5618ca219640c68919f1fefea9\ a3d1e47a3fcbc8c19de2210708fd96fed608648d183fd4c1177d803a49f7d276f940aeef6feaffded75f8e03ce\ 33df996eeb67ac6c0bec62d821bfce22d9a30baa6f7f4963eb4eaa91707ba1b12fd6f3e04f75cfea4dc39c6488\ d72e86c36ba981115f42300b97a7caa427023f16c4f66213cf0c18f04cb6aa66e4830cc7040b3103e27c2e800a\ 0bce21b653566628a5bb8b0becb80b441801f31aa100fb4539cf7e4d6d68815a666c11c6cf4ac97878c551c043\ 3750e9ab6fdeb65765ae3ece107302baf12b3086988bf4d0b37206bde4041cc7c4fa79d38170719e92c052187e\ e810ed1b2b425c081512c7ee6ea722c413215229ebaecc207fb1126644e66dea7e0139682e90f91c71b579cd86\ b91211305fe40770c3176e35b783732c2d74c8aa1a09da66c4f34dfa1f9fd35662c5c3d1f82eeb37498b121357\ e73ed7eea79adeab91001b3c63b1f75aa82793cd1a2b39e1bb09ecf5c6522ccc46652d831abe3ad1f9bc301df5\ 2c646068fd97c0402a29caa4ea3f4de8e5fb8a4d537d45d685f87d05d95f7ba40fbb6a919e93b44fb78b9c80ea\ 6c0a75b4dff2f73844bf4f7172907d8165f606a47821da925eda50af0ce44be22fa2b36d56e1d1698a8#6074", ); // - s == Limb::WIDTH in round_helper_2 // - n == 0 first time in round_helper_2 test( "2.169542166817986625468879014599175406350620737442480370882139687492174119453066131804433\ 632496405940270655469169364935548092764516132338564210201385531365409396738163453793191332\ 174443470862749001312126324808896288354477512722829484994475343567852816045883088813362218\ 109536965926916816038009290804934132950340684582117875938116310656669280480683072639988319\ 858148103369026349100099758130382359401952836454392007054797540845974323496094771400665868\ 125503436816661354237720713751777833086011158065863046075212704099660843597053397398549954\ 8348685976904925033580113969653312280822082757679509546197165e-14", "0x6.1b51e41e16de577dd7b5a3a6222357b305d4e7313b1d47721ebe3d4275ef95b0d98ad997627ec7acc76f5\ d426b7c5a9333cbc0dec080499093952901e541880379e2fdf874d1d931d1243e2b2ab072c0772ce94734ae65d\ ff7afda628d44635b3fba75efa9bd2c10d8bdcb3a61a8b6a7697f598758d80bd808f17f8351b1761850fd75cc1\ 9f86409ac25dd27dd0ce7c26478dae9d50aff0210dc4fa18674fd87aa017255dabd141e1289a7e734e21577610\ bf92b6ce4fe21881cc5209081e0536f0aeb1dcf6e288feeed183095b510c09e50c432ef280e742528c0c4dd6d2\ 5e65c8b6d19c28914472a930aae1ad7fac96f6442134ee95f3bd8E-12#1993", "301180.0045246172416425721655892719573457356766058630317841133942315022590404351104810586\ 213517139802439747677458029756555586634849124296886483237621871644459126081050822492233083\ 707945595254133438910359944302659214080172068073620764660184379004827633051943726032292014\ 225559234820452819113849827971319776547835482966443724022128469656550054145203573809984759\ 336239968661049955088445384576034864711412948863817402256055440443111246220943775270251981\ 245519547063921282094595332683031347213016637666849460902039610984880445147686118036204784\ 051476863264255027838976527798504452504598268980029728768388473210371246534136227460265249\ 86471927", "0x4987c.0128867b146bf9c05b0bb90d2c480c2b610c9c19a0a03f58f0d0aefa84d41a94dbc0c1206d80eab12\ 18d0f5e72e0b72a6f063fe0f604b1eedcc3760c7f60b2aa6e35735292ea939fa59fc7da94b3e86d7bbba5f8ef6\ 8136a9a4c5d98df58e4ad215fee20274cd18a324d8b66b0119d3cf93efacf51659a9814222c8f9b53fe6356392\ e2b27f1ee07621f888214936f129248d805ae614b37cae5b83f51b2be167dc62ef96c1322204921369dc6c7475\ c195aa735676f467be6a45d895b6b08fba56a7919ac216a6dc76cf9f5c3184a2ffa7b1bc3d8760c250d651afca\ 18aa90ff70ee4532482978816617fb02f0de87b2abd54886d1c7c16d62550d5fd8a4abb55b0c4ebb8c#2111", "7.203473451839519375659920800256968930150281137907207966420457324091308743561158996788387\ 290694159461823269997598092194316979651412090098764718003237064733792291895103263169730962\ 123418174759909091404064508319172962888992299461557410206033700688023479037478761668781891\ 761303156472454780198812373188616203221872171676002219543916314587725944225532571475160352\ 707938049990541748698746656039607206067984173221685967465441429896808706646646536972493098\ 282122681082474772608417991249668805473092287771115239878542545454824251859441724816281902\ 754574769925885897122660854445163455617440019293712118274988718965330199709067927675503187\ 81705947e-20", "0x1.542ca6851865ac89e311ac1608cac34c9fe637305345b739b624981a50028d6f60e7fd803167413e1285b\ 796e7a5ed37e1cb19125606ca9d15a697c9c497b14455aae6477ad96ffa4f216a14878a9802e8350d104f0b9d8\ cd86ff511d7efbd74d40104b107a9d7f33d0e8894d3b157e46b7fd4e6386f823e75ae0efa9be33aac3e252d7d2\ 411f8e2afd3773f3914778d26a6b76f5569fd822db5a66db515e3cdd6699301b71cbdb73f07c24fb20d0c66059\ fe1f236a4656c3f508e25958bdef5ca863d7950c5740d7849b46bde7e1a38b797265dedd7d4dfdaee7bcb69dce\ 887bddd7a7bbd45a6561cfad8cd840e7d95599a81bb274cc02a161439f7280459a15c9865ad5b658ed8E-16\ #2111", ); // - n != 0 && tmp != 0 && tmp == mask in round_helper_2 // - s != Limb::WIDTH second time in round_helper_2 test( "7.967842945782984973942186035477141750978306951371418866981413625233901049016799636923049\ 043510064598367854094347269064974737243308027061881036076018766384961823690368428913274793\ 537e-19", "0xe.b2b51b3ba9b3fa4c3c91f60bbe2f30efe9403d1c1ed1fa2688711592167dc11f579d747f20609a0e8704a\ 660072ec620d514ab31d0845381f10e96f76ac41c97c2a7b53849757dc846fdeE-16#599", "4.290314881292277334232122993869736164625712811477787127079554140127474408529492187148865\ 860241941174878594521708166855716060386064937593774872957730026516247807479269506509835640\ 014575725456051856772978910171974972671741113731811243859146099959299700690748160884209812\ 639693266282036645473254451466381125403186024743001502094065938286200460441378264282871237\ 445194601993083290951436490295842815606015494575193282638997440331311694865085507331318327\ 437042408938144577985735854973264189023250983346696190654635795462654945584732891184659237\ 746883228154089313101793763347136552004708447204474905674167880735273390965084667673056531\ 378593414825374458582134295243495148718875340371312206621884585775967428131940924035968587\ 526069447315202760539547246403295371510536211424729007907823710381420209210303664575050843\ 559776729235120592670693730372232402604761499044741741752247404544150954858075273585139895\ 643242778698674255451287458469387850297372316908957826221759549123594364155475346755476293\ 552962991845182999537688763267208310118481794778770137863789646906639637779481228371710954\ 980900001879766864929946144490423459237336070803276511200399191948305713293997532907864745\ 24489311444825214442690999e-14", "0xc.137f67f6b60895b6164f36c36d5b134858a21d493d7d49584a1811d76bd92f10b6d0aa0bea20843896e0f\ d0d2e93957b024a1b5e7101d0f679c3dcc134107c20f0664acbfdf6bafac9013ae41ce018c62b6cf36043f13a8\ 1c35291946c79569662de17adff4ec759b1ccbe440675ef95167b0d5a5481ea6e7a6b998233e094436c8eeaefb\ e21fa0f9c24aad8d11f378034d73a5daec0111cef1b0b8426dd5df78555318d44c992e40ad5fa98171908c4019\ 636becfe749a93747c965c11e84b68df48e887e933449d42c1ec5c2d6a7658e91f6d68333ddfde5719ca117d72\ dadec43975eb0b6b6a076c4ada32d70b0e93250cf5e8836b11ad6a8b13a4a957de6221168782640f2313ca3716\ 3e4da0decaee000e5824d53c71d0a36a55295f8ad1c7a86eb35eab709891d1a6ac96a10448e0e307c7d6742d8d\ 0617a3e21978394d0393bc9be8e32ff2d87e85ae44c3a76ac79752bcca4927ca5dc6dcfc4db10793dc0cfc2161\ 24fdf30070db19fd8a89982adf45a408e08499b77cf25011c54cf9270bf491a2186e1a5fad26087812cc3c2446\ ca7e5457d75f66fe9e736ad07c6b1fe4b20eaf1f073d454f371f659f7402d24e6666c8e212ddccf50c22209ca5\ 7651a266ecba0559cacf587691f7f7df3389d9968023d71b412cc20516c9b1d00f1392474c6683bd0fd6c6dc7a\ 705d88E-12#3966", "0.000018571697337476093645597974800042221391343383471511758884717235995391699590980821846\ 925772010524277797520625056343676345716562878283777572676679678398279369283853673423775272\ 117775978501001731220831012727542639628984101788862199591237806493805996059161201835253203\ 204357442043212398495525692960904672132359565047969002327766123188917268873022220728326927\ 266813579456518458545345939557868848624450974456390610446369728959726525392113471132021539\ 038960803550352390128253151270734177749632737865390247648212171456318006032507634424453843\ 795159031314496937836591202252458892414236797451738560115150573320872948069964155298984838\ 456270978739037104719669912968807593222214861520588395175617611807975267322946381339673265\ 479787948188151606275111200784895864164305724683464061829109671306661764726602634895903888\ 287506327660181397735839535481997625450956961420572462126703944263526095290954835871182404\ 868513321447417245068813964246287015709186652991049553947407472630595976266674750290084010\ 397575525528176465754260767775733418629588880876176812207672741703984898153224615968196909\ 775917982890995046346113085550279268258183711136206964350043642244181512435164664671221839\ 6370838653686792137638621224928", "0x0.00013794d52b8b1e96ced9de16a585696e655c080cbd5da8030eef302763f4138b28d7261786b8ff50bc6\ 9d0a5f06f20dad7ee2a65fae9caeeaee187ea820eae6fd4c8a673a92def1c9a165c1aeec8807ddb464eac6f550\ 6dbe6d6e3a21a035c4472d414f4887b05775ede2ad98b9b380b663c0929394c811648792ef20f0756b6bad50de\ 099fda3dd792ae5616df8837945c3cb4cd833fb9bf0db07243887c0a8fedba7030c428024be8572bca9398f563\ b2a661574fd7faf130ac3d404dbe94b7e0ca06f440962616e1879d4f15895a10229f04969c26dbb9a1b733f734\ fd2be1c88c7b20af178cd1d3fa116fba33a435b040155b5f5f28f0668b798810c2acb1faf0581e46cc71e9b07f\ c9e4ebcd8a96a7d7d318d649e4468baa2ce2cdf9b1adf74f6a6b8b95a3eed5991934327ddfeb243e80db0c230e\ d593df31dce1201e64430a27d39e6760dcf2086c1cb86bfb4e9211f18940b72d1a492a5b9109c0fdf4f5fa9fce\ 9e0ec199756ee5f8e69ba7ded6b7507facbc46df62adaa4546b3113a80e7ea40bab782194bfd006099f6a79bb8\ 19aad950497cae351fdc370756b86b3188e5c2cf71ed56fdb3683c9cc38facff80b0f2076d0f3b3a8605ca24d2\ c8b6301601e23b50ea0940f7ba05f92ddd4a644cca6e420d6bfcd06caab9c695ba67b857bc57e1000b5935d0a8\ 79821217280#3966", ); // - rm == Nearest && shift == 0 first time in div_float_significands_general test( "3.494003589335061592114850452482839587826456952956376068177291318828682713177358264760784\ 874304744009907216335963217912223351596098015455390432300579562836209635380394751634810606\ 195414389573610568068623776330707730813932586805062287543490729241818555718410383777926489\ 343323917900958772688451527795643412381235039158654803215405274640835172391547486080681691\ 827169629800140882523056966137099117587677259077996268577162491409610597231997851472454718\ 312803304389117924206548413988545367622912505139619073824279361037770537659001099972259551\ 367613373821227769095845567435994753397767332318253172120529133505790353120177308303588487\ 770407205738279213609665027613843515660027068482463985188375646552261141849026408186728824\ 80307838589616979262426550353243006148083216398932181e-12", "0x3.d7797e014d587584d7875beed50257a2555726437bf03fdebac1110cae2c4b64f09f9a338bf2ca8b1fcf5\ e0128d7f387a40893706e25c04e65fdd316e3fc348d2478632d632bae209325b6c681dde52405cd7f8d9707d7f\ 5d6de0abb73e130c41c21c4537ce41381fc43788187dab4fa280fa46503f1890d663ca441f49a6a7e2b712e710\ 4c826535fdf1c8ae0282d162e3d128a982e44f67c6104624863e7f3c2c60833df521e5bab88feddd4843e4b50b\ 81ba442bc612787ad38f640412f6cff81df9793590dfa6a0debdd7f2f6de7a089fc50d597d700dbeeecfc9d795\ ceb9a69d05db5c520717ddd7e73fabaea4e2cb06b1e1874b8b541dfca2083cb277e4d1bbefa48c0a427afea0a5\ 87cd5085c2ba28c1cad42a97be72844e851abf698ac844915e9f5ac4af406a2c354aa055f3c0994b7932d1bdb7\ b4999768f776148E-10#2560", "8.388557903692744678886673027706512178020882171440574341138664910770681048759242342335520\ 689291884051853125391850946672822384185374426629671262437149651332606541726962233658521936\ 440197380293004778812876511148916284206096731251130678261803308370362817534297504354768207\ 175302739282372189357904919163400327254111204148827422042723518774290057028465296755126014\ 371014512774422430414368313070504306047237723842986944935010614200247398223867859750512432\ 528263508555538801970472032683504663202558316239308702078808690323956381650112536926354687\ 819619269837340011822483859668579241157516055938780563664184620140501025776680716962470155\ 2e-35", "0x6.f80c88bef08546fc8a21f0f2152ee0612eebad2635acbe0d49ce7179b387d0719cd657923976ec2796026\ 5e330a5e71c0cd8417c2cf919556130f9b353cdf2435349f846c895ede372648bccd9c217f1bb7c3e4197c1806\ c4744c8a05ddf4f67946a4972f056d84028e7023d956a95b2ff067c093002267f7015fecb9ca5ed8f58dde48d7\ 4510e965bfa6478370f4e71e5a240dabdd9a4d6e000d4af93eea8510c6c4e095290bce062925fd9a7245caff37\ 8b7be01d3b94b56154cbeb98c26f78338a98e416fa9acc3bd12c4953b058efdcdbe56335f952208a15166babaa\ 698da808f96df97655d3f5cdb4768e6370755a01515d4ad54f625432fc742e9121b7cce4fdb08E-29#2088", "41652017300815899948547.94831484736938823572318695739742204735159366375620848030675947597\ 937407214848121136435440017047965685656179645007771422864559798518659544278806178160023554\ 020245599674536568425190916908552958650848910192845046055088066614557330847090320384899468\ 575304634050066348271499359839369427201019441174516439045175255034723132436872248790761539\ 506937527488424041602486298663492699846695028977559705152038731125314966620233281505474337\ 677248672173837029868825260085661764008715204976773612281854954844288452423998027475082981\ 779489389492756600188312999400831430516184077432877044587246391185262444911853744883006186\ 684049728461939709785134255700251964580618924591175050653894151676243677123400686218961075\ 24208104943935667403367286485079704207117845193523456", "0x8d1f5db9d3f145a7603.f2c4c307c343da5b63ef331aa97f5e951921921a937336258bc4ab65fdf9d715d36\ ef6755e61dd29859283e35c618271ec076a196c3ddb06ce536bafe52ad10a521ebfdcda2a3839fce6eadd33d87\ eba1d25c5eacfa66f0af4f1ce568be4792717319611eb807fe7fc0d855f2cf1b099f908a269208b3ee36d33e71\ 3912e0557515bf16566f8cc4c8c45fd6bb2ced1b3d3f27c9b272c6e5dfaacdd66335f658951d70cd7b3190aac8\ b90d7e564b5c0ac68a04f4681a552c50de11c466e3ac1230d426fdc851e7d5705e73d7ad30a82c2febb82c46b4\ 93762b8d7c80e514c1fe29a64d4189fc176b72bb816f1223676b93d38dc33a2fd578eaf5fa512468b21e723d6c\ d5595dac5bfd84c94e4826fc5b9aff74dec22c3cb43d7970a1359eb2642295a920a70da20a166db400602f0f4f\ 2aee9255f2251c#2560", ); // - !round_helper_2 in div_float_significands_general test( "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ 1249731874464215297923136674027554116062077582682832144200801849365234375", "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000038180485e-31", "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000001ffffffeE-26#2567", "10141204801825835211973625643007.99999999999999999999999999999999999999999999859870153567\ 518292907627041671008386871973805812348422824293171611020891731413939851336181163787841796\ 874999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999018341217", "0x7fffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffe0000002#2567", ); } #[test] fn test_div_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = x.clone().div_prec(y.clone(), prec); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); assert_eq!(o, o_out); let (quotient_alt, o_alt) = x.clone().div_prec_val_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_prec_ref_val(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_prec_ref_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_prec_assign(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_prec_assign_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient), ); assert_eq!(o_alt, o); let (rug_quotient, rug_o) = rug_div_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", "1.0", "0x1.0#1", 1, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, "-0.0", "-0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, "0.0", "0x0.0", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, "-1.0e2", "-0x8.0E+1#1", Less, ); test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, "0.00813", "0x0.0215#10", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, "-0.008", "-0x0.02#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, "-0.00813", "-0x0.0215#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, "0.5", "0x0.800#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "0.5", "0x0.8#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.4502", "0x0.734#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.4502", "-0x0.734#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "-0.5", "-0x0.8#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "-0.4502", "-0x0.734#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "0.5", "0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "0.4502", "0x0.734#10", Greater, ); // - rm == Nearest && overflow in div_float_significands_long_by_short test( "5.8208294e-27", "0x1.cd2c72E-22#24", "5.322295e17", "0x7.62dbe8E+14#24", 3, "1.1e-44", "0x4.0E-37#3", Greater, ); // - diff < 0 in div_float_significands_long_by_short // - sticky_bit == 0 && diff < 0 && i < abs_diff in div_float_significands_long_by_short // - xs[i] != 0 first time in div_float_significands_long_by_short test( "2.4914040842493675536005152793625253098043524808533216867315977e-8", "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", "0.38945825655685", "0x0.63b3894b11a0#45", 74, "6.3971017234954763411416e-8", "0x1.12c0e0961c12c850368E-6#74", Less, ); // - xs[i] == 0 first time in div_float_significands_long_by_short test( "5.94670436124321717863912904768573447358", "0x5.f25b378e852b0522e85279dd6e9b5e20#129", "5.93e6", "0x5.a8E+5#9", 5, "1.0e-6", "0x0.000011#5", Greater, ); // - qqsize <= u_size in div_float_significands_general // - qqsize <= u_size && !extra_bit in div_float_significands_general // - ds_len == 1 in limbs_div_helper // - vsize > qsize in div_float_significands_general // - inex != 0 in div_float_significands_general // - rm == Nearest third time in div_float_significands_general // - sticky_3 <= 1 in div_float_significands_general // - qh == 0 in div_float_significands_general first time // - !qh2 first time in div_float_significands_general // - cmp_s_r != Equal in div_float_significands_general // - cmp_s_r <= Equal first time in div_float_significands_general test( "4.171457951045116318706366624151444947334895358793933e-7", "0x6.ffa0a6f6450242ee750c35f12c7b17a438109694bfE-6#171", "6.7041531299542248604361e-9", "0x1.ccb4b589b3974d3c8a8E-7#75", 63, "62.2219968754442595", "0x3e.38d4c987d8e7580#63", Greater, ); // - cmp_s_r > Equal first time in div_float_significands_general // - !qh2 second time in div_float_significands_general // - low_u == 0 second time in div_float_significands_general // - cmp_s_r != Equal || low_u == 0 in div_float_significands_general // - cmp_s_r <= Equal second time in div_float_significands_general // - sticky_3 != 1 && round_bit == 0 in div_float_significands_general // - cmp_s_r != Equal || shift != 0 in div_float_significands_general // - rm == Nearest || ((rm == Ceiling || rm == Up) && inex != 0) in // div_float_significands_general // - goto_truncate_check_qh || goto_sub_1_ulp || goto_sub_1_ulp || goto_sub_2_ulp in // div_float_significands_general // - !goto_sub_2_ulp in div_float_significands_general // - !goto_sub_2_ulp && !goto_sub_1_ulp in div_float_significands_general // - qh == 0 in div_float_significands_general second time test( "3.7563361266e88", "0x4.b87f4dfa0E+73#36", "6.769173652614128677797571270436826716e-13", "0xb.e8909656207637d3379c02628519c4E-11#123", 63, "5.549179736559369991e100", "0x6.57b76abe8193e56E+83#63", Greater, ); // - sticky_3 > 1 in div_float_significands_general test( "6.4231308808e37", "0x3.05280069E+31#34", "737445296117739183341894639.41419934820825930816963962148939959402654898", "0x262001d9b6493f3dffcfbef.6a08f7ee9438af0b7e2168670bbe153c76748#236", 61, "87099760682.70268959", "0x14478ce02a.b3e377#61", Greater, ); // - cmp_s_r > Equal second time in div_float_significands_general // - rm == Nearest fourth time in div_float_significands_general // - rm == Nearest fourth time && shift == 1 in div_float_significands_general // - rm == Nearest fourth time && shift == 1 && round_bit == 0 in div_float_significands_general // - goto_sub_2_ulp in div_float_significands_general // - goto_sub_2_ulp || goto_sub_1_ulp in div_float_significands_general test( "6.4231308808e37", "0x3.05280069E+31#34", "737445296117739183341894639.41419934820825930816963962148939959402654898", "0x262001d9b6493f3dffcfbef.6a08f7ee9438af0b7e2168670bbe153c76748#236", 63, "87099760682.70268956", "0x14478ce02a.b3e3768#63", Less, ); // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && carry // first time in div_float_significands_general test( "0.00002882366272258", "0x0.0001e394b0518e#40", "4.407913996892399269446698943482826e-28", "0x2.2ec4fccc4a5e21c3fa6da2c36120E-23#113", 1, "8.0e22", "0x1.0E+19#1", Greater, ); // - qqsize <= u_size && extra_bit in div_float_significands_general test( "13863336.632654341786855779405528442674244", "0xd389a8.a1f5a28ba59ea1aca395f84bcc2#131", "88.32972592752556369746097031876493672699524930031683012093294198918", "0x58.5468eb1b5d957d68d5c161060f2abd3d11568e57fb44ace5b9530c#222", 49, "156949.8431822285", "0x26515.d7daca60#49", Greater, ); // - sticky_3 != 1 && round_bit != 0 in div_float_significands_general test( "2.60106", "0x2.99df#18", "1.12640651293023472114636230356467597616119208733434416176044102440877312604351521285e-35", "0xe.f8f67659254f23c6296e8bd68107bb0d6543b0d65b1f5b85639b43d42fafe22d0850E-30#273", 62, "2.309165412400307267e35", "0x2.c7910820f8e1a98E+29#62", Less, ); // - sticky_3 == 1 in div_float_significands_general test( "5.3925833329420346441e-59", "0x5.6a7cd168af6b5224E-49#65", "7.055235440683529923035882801220195059780252442336634700998228376328e-29", "0x5.96f8c4a5671f264deaaafa2151d5a576774640994697357cb67388aE-24#222", 126, "7.6433782802570609426763368452677453109e-31", "0xf.80ab3d3f6f9720a3e3d6bc0dd473a20E-26#126", Greater, ); // - low_u != 0 second time in div_float_significands_general // - l >= k in div_float_significands_general // - cy == 0 first time in div_float_significands_general // - in sub_helper // - len != 0 in sub_helper // - !extra in sub_helper test( "7.326919700506453074257659445909468362437490080995085670582700901565e-8", "0x1.3ab0558546a1bb0ffb3951411ea17cd193a72ecfb10c90503c09df8E-6#220", "6.204773818244710788233721e40", "0xb.65787b1d85852bbdaff0E+33#81", 62, "1.1808520205784374405e-48", "0x1.b9cf274b9b9758d8E-40#62", Greater, ); // - extra in sub_helper test( "8175446.9642736466252057884969624115178724187752436027351898906495229305213", "0x7cbf56.f6daa340a6612207973c17246d0fbeab7366f17c873b36e8a7c5e130#244", "2.2364028106870166695e31", "0x1.1a461277f5c6a045E+26#65", 62, "3.655623631488002044e-25", "0x7.122d595c6ad6278E-21#62", Greater, ); // - rm == Nearest fourth time && shift != 1 in div_float_significands_general test( "1.274876025e31", "0xa.0e9775E+25#28", "7.104011072486714881105976022274735719942619445087760266603169705559e-82", "0x5.6412fa517e8e5c9e2826903dbe9c6b4f020acbf4d07a5f83b6e4008E-68#222", 126, "1.79458620199896394199805694868744557485e112", "0x1.dd946a676df629632baf4759d5af1090E+93#126", Greater, ); // - l < k in div_float_significands_general // - cy == 0 second time in div_float_significands_general test( "1312304952.868834018993672867833994901273914152677", "0x4e382f38.de6be8013ae5b9256e2e3d80a6484417#159", "805222139786632223922.788562923013680863", "0x2ba6b3b5e2de25dcb2.c9df427d2e92a42#130", 61, "1.629742760446910473e-12", "0x1.cabb579ba24a1c8E-10#61", Greater, ); // - qh != 0 in div_float_significands_general first time // - qh != 0 in div_float_significands_general second time test( "4.77e-7", "0x8.00E-6#9", "7.27595761418342590332031250000000280259692864963414184745916657983226252757951518e-12", "0x8.000000000000000000000000000fffffffffffffffffffffffffffffffc00000000E-10#272", 12, "6.554e4", "0x1.000E+4#12", Greater, ); // - cmp_s_r == Equal in div_float_significands_general // - u_size < qqsize in div_float_significands_general // - !slice_test_zero in div_float_significands_general test( "7.37e19", "0x3.ffE+16#10", "5192296858534827628530496329220096.00001525877451", "0x10000000000000000000000000000.0000fffff000#160", 19, "1.419698e-14", "0x3.ff000E-12#19", Greater, ); // - cy != 0 first time in div_float_significands_general test( "68094456598293603327533905548505297620013066911.08376291606058693773517767794501897994582\ 258970805389024907002851553537297142201729190070813276436614829387252399053496817432401142\ 072590738640749961499805778301047693438889653237932045230908598957544293121509337746443019\ 818113697275492083034559948210251757918035033203320082922052180871824896122583688257790633\ 347767288424884057738898369318200284711885269916578380577251435556820233836251778387280672\ 557877138589743092466532437097578789439010809222705729003762084164876928991111619216295374\ 407477624059748769343096515734766384609704158183422827373811211581562563854555563208285030\ 789640954030131590715773225619459109078415421551825383051156907165239504581969296580217917\ 201401107075438836986951972027346920300296173028752019760961905082742144822764332949493643\ 236343403045805151576437841818592689216294090992083144539119316847195395330209116021520674\ 687172083129681053947608634984318972146599189025048336884553676307718881472973047561666876\ 170703037518590793048762200560314576630872589716790447601932356569152269838665699058277016\ 66840662018065630567707390037462589298017636098402605937122", "0xbed7606a24f1082b01518fdb3fb83b7bd6aaa9f.15717c89190a577b04eeec86844b1c5da7ec1d515c98354\ 34d7eaf573076ade2dd2a181b60b144c489be5eadf10a8fa23688bb3d5dc411a80de60bf15d00f4e2bb3d1dd9a\ 05d37673fc56cf152b3e89f3955fd67353655a855872202dd9bb5939503124c7c8c1c2e93073284ac47ffc59ea\ a0e2d8533a243325fc33e1795ea157a7a42aac695237acf96951da79f695a7ba51387281685f9dafc3987d0cd5\ f393a28b74f7077fac3ca1d127e47df74353b51a5191ef44d9d17d76e82b13992c6d3cb5330e49f88047554a32\ 6085af468cf06e8d9d64da3bef6a9dcd50d9c3d50c03f20851ad827d200fd778bb6ffade66b04462f28dd87893\ 32e49807a56a3d251a3123c64131caa8c495f18271f1511c3ebb467c8e07f5a65ce58538f1b5a0a5cffb750f2d\ 2aadcba0995b2bc3d8ec2c295ded7fa6a05959ac7560ab0a8d43761ff672a2823d42f9a3274e5d9f621920a078\ 13bf0f700cfd42309086f1a2a594e81d2cc56780a2d2146487d5c84e4a45ea287d5082ebbc00d963dfc85328fe\ fe6406f3583a1d25b20043620066c12999c2438ae661a9ce3a7577bc39adbb7d9c6b2b95f70ab93d453deab5ba\ 879c49217ce044fb8c99aafeab2a3c2d7b81d1420f50f3124#3778", "5089003.986901636664002211687103226682676013278365930635943365557217778575140755071304051\ 262677914765136974076241170290188547560394627827342683941547868265780205495768503547504471\ 809839828485098007901365847412395780099805986364986150288103155890838726927248245864748917\ 545776909957932766621125809519317578017645670025405880924769796697930801127403727804288556\ 494641308619101409216398256844236435992132716137153671232504127486179270643290623882858426\ 225419756589684747143027545016939069261808018044193898155688966291933573563069322732013621\ 2807285459308838582521108293701", "0x4da6eb.fca595edd73c4fe606a4af64c155ce5a5a06c66381dac0cd6a8b987a7c57162437fab8f807ce8aab\ ccbcb3f448d402e4caa52f0641d93df28bfaf5e58a6f16f39adc87b5a1dd5398bb2bbcc7d994a0201b397c4a74\ f97fca0b917ba0bd07b9ce9d25bb5feb2db2ede12841338d892fca759aafb7971202ee42d8f016c781218a37c3\ bc2cd12d5917a00cf157abd9f8e9ca4f5b16b4359dfe287ef904d8db4c7df271a3b90126ef56586929a4a65813\ f3467787c4829222d7fb9cf2e133be397a765f905e56ae783ac80f559db68cd58a90a22f1ab1af1d4dcd872ca6\ 981a9ecca8670be84795798bfc4#1890", 63, "1.3380704116868237389e40", "0x2.75285dfa208ffd00E+33#63", Greater, ); // - cy != 0 second time in div_float_significands_general test( "5491.549122096322909336636529538856618128292880125595066488677776051102905046366315843918\ 913993420423080685689765224843845532100106275652902608353545283642619588636389226823484210\ 861629061239611056329749023362152227886065897973662117489519345928983306276603012226918628\ 850786900692391091591113247385622873420889775685843449415444179626888676565806730164439066\ 916153918074448979830160313236976037323911844599167437480714277238521850834771260598243342\ 817521177189023", "0x1573.8c93440537c5819a8b2239f718e330a799971b8d83971158cdd2e59617a3347f7b4fb69cbaf9e5ff87\ 522a9c5cda06c869912d81fca8e9ef0dbe259efb7b9b0a54a58449a185302363331ad127c4e9256f242984dbc8\ bcbea4216ff87b05bc4790144521cef5ba2b27261d31a7b650ec83e23fe89b1b2f569c96581f78da0e0d4554f3\ 0f2ed4731ea3d9bfda8cb2254fa514c04681a9298a927fc2abb2b920ac830f6d5ceb4ccb7f627c3b8895ff1804\ 8c7517748878fce7a0839b14beb12#1536", "1.509673347429890062512836190652173917347254081193788057095565296339169922295435269039375\ 472698941288863827397739888112708775552600102260052264376059462711206952889795049703596839\ 232956098476826545419162632064629313103364676417718336633177039699753340705596727615974068\ 628610723831801827765947524025118267152138672831243078933782856373566584766564765627600767\ 096322262179300330204832084508935397859168676086969433875110241760537834330483926543135245\ 217039771663537327658657093592229424143926522163858843150047672118222822507365351980019570\ 622407757023485804508837072933740850465658604e-7", "0x2.88665707e5f5634041c4267ef6487dd6141defd41a214073fe6520a7bdcf0c026eeac8a1a76a6f7c7e2c0\ 73cf8d31cab2cfe226fc73bc3a686dc489877a18a6e4ecfc6970268300003802d27bf6e18d0623eb7b117d7342\ 0a73839c03f41c3d09bb282d8dedfe2fb5675ee89cf010503f7f0b26eede0bb1c37b08c5a55d42499a3d9a9175\ c05b5b8d873a476906f4a54340f4892951e2c8ef3a29f769e86cfab6965b4f110f218061a287f47ff1b3c217cc\ df00c65594ce0048e5bac7ab91da9e0ecbd44b6c0440d575c7f294899ff21e307008ade7d2fba1c820083431d2\ 3a0f94cf78f5937afde262a9f2aa86d36c391c0E-6#1935", 189, "36375744007.4390200041449619204768129898564194090547870908", "0x87829ce07.70639d7017a741d4c383ed19081084c4464eff0#189", Less, ); // - qh2 first time in div_float_significands_general // - qh2 second time in div_float_significands_general test( "17592186044415.99999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999", "0xfffffffffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe#619", "511.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999858969189385560189369588899908301051658131815921691396545986807150339147015462\ 016914098983479659782731543057846003175884332840513803623318182318832820724717407320371823\ 6294395745915856", "0x1ff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000#1539", 26, "3.4359738e10", "0x8.000000E+8#26", Greater, ); // - u_size >= qqsize in div_float_significands_general // - in cmp_helper // - xs_len >= ys_len in cmp_helper // - cmp == Equal && ys_len != 0 in cmp_helper // - extra first time in cmp_helper // - xs[k + ys_len] == bb in cmp_helper // - xs[k + ys_len] < bb in cmp_helper // - cmp != Equal || k == 0 in cmp_helper first time // - cmp != Equal || bb == 0 in cmp_helper test( "5070602400912917605986812821504.000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000072282982868771681166004491412846722101397844122267684138688870467552820474559090102317\ 447234871538375909335604136421707865093288809202542467085297095776399695369977155046440218\ 72699461509694558652328992590065121835881232", "0x40000000000000000000000000.000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffe#2230", "0.031250000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000519145120156837503\ 646385401176147001734918579024397648372858359187739423120395387040659114766108267370765089\ 588804048262656404437892026790384389944710053355139410493357036837062723311890087295336535\ 224886414974037589635945157614552911737025968561447428534517548726620712055254368601400677\ 671297010734467257376219342434577391120913670811726006378408285341591896262197466018812208\ 707818364202903001714252499366447760377357676976645014748597726032434627346717442135450023\ 055574853304203092750885653943947474937587714924946440549453028916954237373614371956358356\ 475429001114655812373726770920126725739237754419551706215855979284224297710219012046069209\ 939692719820661068941772746188111229015697420074924121315943073728508778962547216389153434\ 262911373438798885794691058258008791084816770299900324276184865853804713586768050489411191\ 664317769877562965352444256815704956578248231483831995594631665817366125592817899193355951\ 118530268969738737015352029171836561799730662727849622621896971327136981718066405555588128\ 499837506069085441884105298697942808825809875065414280125486286978200226472477679074148608\ 959361116404570999151605839083899731368423273690135641440237909114194036012915602847402345\ 640200131464172673937558930023395763819989040966673763510370208058366269042896065620543694\ 889060883071378600260819500918049255496885447711748266825241404608194240474286320016971013\ 505365433166482975272851975538460641506474893740018353758689194264153921667729046743564069\ 253579744", "0x0.0800000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01fffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000#6892", 36, "1.62259276829e32", "0x8.00000000E+26#36", Less, ); // - xs_len < ys_len in cmp_helper // - cmp == Equal && xs_len != 0 in cmp_helper // - extra second time in cmp_helper // - xs[xs_len] == bb in cmp_helper // - xs[xs_len] < bb in cmp_helper // - cmp != Equal || k == 0 in cmp_helper second time // - cmp != Equal || !extra || ys[0] & 1 == 0 in cmp_helper test( "0.000488281249999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999963663982709420587425167733195\ 304372898231735836009052811521034277852253692510619649191102380354831309742044158555819900\ 182303288606739679841769892362177959648480394191365684359543454337339931688383011417980993\ 719495486975941054744491093403718104080315380258293738327998799327152912644577698156976186\ 55095367486514165923991079335821758615173478", "0x0.001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000000000000000000000#2815", "2.168404344971008868014905601739883422851562499999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999997e-19", "0x3.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffcE-16#1232", 36, "2.2517998137e15", "0x8.00000000E+12#36", Less, ); // - !extra first time in cmp_helper // - xs[k + ys_len] > bb in cmp_helper test( "187072209578355573530071658587684226515959365500928.0000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000001101803207893244326789943155\ 018460305099242595345476423646015479873854823483513049621916060417380926502108264599637960\ 009028188448912132272078404411433183433802785019851743390002334059444086579631362687278982\ 092055516132867633211303823870165864587972287857634502648284831738260191440051776077031899\ 598142362977237015956245760229588121897813474421614887403259665611637741356303541231148645\ 802831472359942877820272387728004709359817918832294062785037876007514227493405888433177689\ 680714430224698456312336396309714864041562196381794611694655680402546092635353483367808913\ 752362293005799560093641139943406727218702402175348117018858577588516940143086501070121082\ 790860175377027", "0x800000000000000000000000000000000000000000.00000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000003ffffffff80000000000000000000000000000000000000000001fffffffffffffffffffffffffffff\ 0000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000\ 000000000000000000000000000#3331", "4.814824860968089632639944856462318296345254120538470488099846988916397094726562500000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000043039187809582461740\ 237762479156173200033015160616639237674924575702164607097773158539128576763982320696088303\ 832038609517565761168327844792993520257347193172468143718482303439757405926333196250133060\ 288550223275967750822594171887174682861815132430042665799184768861200315909562005634908495\ 040482237984846081838841677107482858326355102804446586581213177924458440804958481615550624\ 777545362515887646344379566287174797564232997148384542907314841464505589746930096972150685\ 525970118605412491959870803444763295822500525548365368442918966063445202883350639365511116\ 639832781262353439062659724470167290957426899576854017375938862005470860735521697212635101\ 685662094078329428036605435693999242602513069760981920534839908438815346198461935722540210\ 326793005024577932413554325700374174982252819095920682430496242093539639719648496398673988\ 294181130946788869550483877630340388986962249045975498873325109426508397715202174256327738\ 115206226749346851411911082798138490772273613411588181424713572149102614119711767787285638\ 524703608044386935250150211880470005994669065127142264588906081548898113686963839840837625\ 878160925150811347647212869111896217042292003837889935947741223166647027572900535517651639\ 207495691251723099461646574220946216274869671971300965751857652439720077434006455131311793\ 590683604336422775710475248004038566299454724867611543407224462775327725726271022150051488\ 962306463251821198471593641698105320214416610382784775624895123451428368367748899615073448\ 540841180568439251922577807930504713787460146305777655304325240206357947725816143068424676\ 946204398859120790721921646336338115096532038905903264996890888572731012019093458139272007\ 836293712752099827742569952571629995231554586253215504385643489009213919397283063609836863\ 267686636840153036916740518806971074030344720455273318700117606897827915624482324081001558\ 580105852766963764590581776038099624170109326877344468594726954445140050830134037782433855\ 587285682701452954803937838579540908490074176523981670683042482665018271091095010951223690\ 5278182153271165591237853e-35", "0x4.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000007ffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000000\ 0000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00E-29#7548", 94, "3.8853377844514581418389238136e84", "0x2.00000000000000000000000E+70#94", Greater, ); // - cmp != Equal || ys_len == 0 in cmp_helper // - cmp == Equal && k != 0 in cmp_helper first time // - xs[k] > bb in cmp_helper test( "536870912.0", "0x20000000.000000000000000000#100", "618970019642690137449562112.000000000000000000000000413590306276513837413283570606", "0x20000000000000000000000.000000000000000000007fffffffffffffff800000000#267", 7, "8.7e-19", "0x1.00E-15#7", Greater, ); // - xs[k] == bb in cmp_helper test( "5.82076609134674072265625e-11", "0x4.0000000000000000000000000000000000000000000000000000000000E-9#234", "8192.000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000073621518290228626754368\ 661771449651176491350325096363488672030344706104289026372412636851722245811280577862962401\ 765246827402220719444460351741455902885984901380506690583579618039994586998414375011572379\ 779182346403549244684325279848137048396135313055840892271543868080199241336353523751067084\ 487605126715192128136637640780333317069117147264850291384068338053712809423009097565764707\ 945202720557662560964127631897773337487421543251587594809897712933202207298421785498016072\ 254449856519027840276532392122510707729637176938094908140620695527942817590009777550509094\ 454152645378859315289504747645957548190040101946887130819745338279179159631457317778420898\ 470611527072781043747280163229876864141766629003055536247648501825111792890761407396390374\ 874897179718966769929553634685717455680003107614184209129041106624130501684449541327017766\ 6757753582718", "0x2000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffe00000000000000000000000000000000000000000fffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc\ #3924", 15, "7.1054e-15", "0x2.0000E-12#15", Greater, ); // - !extra second time in cmp_helper // - xs[xs_len] > bb in cmp_helper test( "8388608.000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000684828866957428698438476408479242192022929376940887598\ 259032840130007525904001877047531991911904326913906546098688715629243382676607047027876451\ 719639473400356638537379034111884955325977768684942789942877048547849906527713086446752791\ 858723447410673711365769970369878574737183686864932741554880327679842509372652502021311890\ 709142794655721430723387345276067736929449744072002738257252158918229576617779883525921585\ 596123442220897772976221689427398725884900122239984724340651124172908938910231534143853336\ 754402", "0x800000.00000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000000000000007ffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000\ 0000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000#4496", "274877906944.0000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000060373564297453652118256309302784011108922184796264095\ 964856067554168050454843683714804467407509910692607381159281320687596446281451430072818608\ 057863867144256826337394425373143511933737397669081937627812007424941677129312470503091170\ 911733627368176008701133101413396404615425187244748480697366133742242352202719895177017100\ 690953740117147446309724130962650836546766701719441996132950568128342147049715911045228743\ 620410093793320012089795191308289370965558751489023393660780664527210525039278006479120686\ 667916583520393051061889574321018782852304715910223159623785353107527307680073164159574897\ 425049765870945886337964515155856670447604028696651128918360721209741264488097948768144159\ 7005421420614212549", "0x4000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ #3940", 17, "0.0000305176", "0x0.00020000#17", Greater, ); // - rm == Nearest fourth time && shift == 1 && round_bit != 0 in div_float_significands_general test( "21778071482940061661655974875633165533184.00000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000038725919148493182\ 728180306332863518475702191920487908654877629413444163480976859648626822342770145969080575\ 425075544675393708363989923503155223180506533504920024360652705227860649920024820627696586\ 039669982633650149716545149281467950945053120039758890080803998602993819265261127978876161\ 185060505268781766584528622179744118464786493161582046377347178114187510333531866422621209\ 846804228328353733454965094209076361330420294172109758000406375110313580574114285388890693\ 305920075040658551907160730659163031529176823334039346417685325080367605674100555171634617\ 234928876787779313622179077907389499960227122096343446066535190397344011264079006874008414\ 382439268898793195608363864632580908988059168802931770976116933654316402639901396184475943\ 729788724295947748963417392515678664943418616270097079670860835720917411673092090040881885\ 21564006805419921875", "0x4000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000#3999", "10384593794440907712397259839635455.99999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999993016492510700454214505644339937412396352916507799605382898196356288572513\ 255335843325740991172311658773153798524263030870893776870186113616631478977505034859608131\ 351745273180872140851736147478994985324507666557307045519001087646931454316452554197971038\ 325854489646439254746059314551440312981763083969256523175727926415817004690047870256478545\ 703194379897622730743058132509274625798800775561678711877861189187434830350273902228109246\ 439341677189967895547076747086150572427772646706738189826894090172821355170927596420947406\ 00086516265683600055", "0x20000003fffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc#2748", 63, "2097151.9843750001164", "0x1fffff.fc000000800#63", Greater, ); // - cmp == Equal && k != 0 in cmp_helper second time // - extra third time in cmp_helper // - bb == 0 in cmp_helper // - bb != 0 in cmp_helper test( "8191.999999999999999999999999999999605569547389494097294135717358606885163396782445488497\ 614860534667968750000000000000000000000000000000000000000000000000000000009104419837890877\ 372181354144852214156953700603760262322108787027839695294275046757", "0x1fff.fffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffff#809", "1.13686837721616029739379882812499995e-13", "0x1.ffffffffffffffffffffffffffff8E-11#114", 12, "7.206e16", "0x1.000E+14#12", Less, ); // - !extra third time in cmp_helper test( "1220323748666959369108273.2342529296875", "0x10269e20a74472df07b31.3bf8000000000000000000000000000#203", "7627023429168496056926.707714", "0x19d7636772071e31a5e.b52cc#93", 3, "1.6e2", "0xa.0E+1#3", Equal, ); // - inex == 0 in div_float_significands_general test( "37825066419214082102958195114240.0", "0x1dd6b619c4a053851a451b28100.0#108", "35597.514868846018999", "0x8b0d.83ce71d761800#66", 41, "1.0625760410123e27", "0x3.6ef13a9ad6E+22#41", Equal, ); // - slice_test_zero in div_float_significands_general test( "1.7093142438003562047006422345280738002737985244107760125e-18", "0x1.f88021f87c2effbffdfffffe1004000fbfdfffc00080000E-15#187", "5.216412786622324189132254660659649298902e-23", "0x3.f1003ffffffffffffc0000001fffffff8E-19#131", 76, "32768.0019530653953552246", "0x8000.007fff000000000#76", Equal, ); // - vsize >= n in div_float_significands_general test( "16383.875", "0x3fff.e000000000000000000#88", "73786413344884785152.0", "0x3fffe000000000000.000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000#2354", 1573, "2.220446049250313080847263336181640625e-16", "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000E-13#1573", Equal, ); // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 in // div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 && q0p[0] // & Limb::power_of_2(shift) == 0 in div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky == 0 && inex < // 0 in div_float_significands_general test( "3.552659469104e-15", "0xf.fff00007f8E-13#41", "4.84676140167789653245e-27", "0x1.80000000000000000E-22#67", 39, "732996567124.0", "0xaaaa000054.0#39", Less, ); // - xs[k] < bb in cmp_helper test( "9444732965739290427392.000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000000000007", "0x2000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000004#832", "2.646977960169688559588507814623881131410598754882812500000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000556268464626800345772558179333101016054803995115582957638331854221801108\ 703479548963570789753127755141009073606571985185530635329448182789571845492934678567064361\ 332708567592792632774560421640775880919059592137166530735473758036612778924544586718232305\ 427824501619198614662740023702411729616701208397136180761162254530729075026989491906995358\ 575857015870579521868248894534215532446934638248802017349968861414212348741850124926530061\ 137882705366115789406521732304520719972162648696165229524120554795461372143924212631388636\ 174362506256920084558049677121644286500487074477020716131861235836886832672281595198230113\ 567709366546419530594295018834136800596699897605463746431155006086897664830884143672193812\ 44610974066e-23", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000\ 000000000000000000000000E-19#3316", 166, "356811923176489970264571492362373784095686656.0", "0x10000000000000000000000000000000000000.00000#166", Less, ); // - u_size >= n << 1 in div_float_significands_general test( "128577.8764868580029756801212656877698983158936282661425976800226962111142207941648763580\ 988345531602067112079580015968145327129866382559301038263207994838658330066205433266994831\ 467312285027812918907079178962008936026981323406687199299541735562087171599287887802035024\ 906243692028775515058236407279458918988174303955662670989299201833922393455224960273024665\ 835516171507144476172664636956597658975023887814926279578799575403427330090956378386637388\ 135713599495925645995132841117427501966959959182813336108896940311309853198603275957130349\ 180224933883131003754623341245570205903946496613695364321801198058339260724701640865654036\ 186860644657991116300768604961954024465425961935896721280763534922807739569795086883210509\ 579889273277174558334960325483739866345331038726073720427318649387253214131422147544043776\ 436460480773469181215055043763336182793567894315442629932401507848298532722652018799777250\ 015693272603467557015010371191540543654044197350381607085047315086344620959308640376127551\ 931466260812673044275557327198781497102634261681647151335962486321030934060949982367829468\ 020749656366004839444427964357828448988474386543697497400049219456871357814121030924016175\ 400479172517413298974822423000259842805397057515980600295281540360693708678122362364971796\ 779616611372222055466670808323170951832437930119313259384578003290031387708344288805368337\ 588807333974140623099430569336560667666750522945572113803323880761652974693642791189155133\ 946965374070768843306018991682723627881006841722563064115628027286093354777874808024620535\ 656673153645820545300742916103648617900434641706211663820400676448026510940215813847245690\ 787061247080030343563700831660998005203777247693478841377389920284883123241874488805072645\ 154615488002533716177437262647168075186850895612670638062910190731729666226316215350837312\ 425251155930035494177805868591779327099854491269372890119982152035832492671125032181675364\ 3983068068", "0x1f641.e06171567f1fa1ce238d5b2d095d742087c3ea45ea9119d15b04ad4fd22debcddfe61686f85e93d4b\ 77b8c6117bfe0d897686b10fb2562ff6e4d3b597d38561e37784dd68d9eefbce8d53e8394cca9a3e2dc4566d1c\ 9dc04bea4f3078e8da6ef5461f25f3bde96a287773d9c8276b6c9374c221c96a70582c7441d2e07612a8c3dd03\ e35a43d31a9e2671a63722177907b421a95e476796ca49409bffcc43124eb7f620ccf522ed0e21b1b97a662a4a\ 5b35525007c94fe7415d10ce2fc897c6fb779527f47ad96624541900afc16557a726046c3df3e463a8d759e7c7\ feef0e9670534db9d04b9d9ffe0466a19dfc275afe386b4af62dae0d9ed645db8afc44566a1737f4ce512e8a0d\ 04938ce2572f4040cf0d01959d07f5d5df2d20e13e12234e2e5c841a48fd2fd2bb90b8def7c213d1e639884238\ 3071b76c2f1dc091971382e76e3ca531afb15c870664c6e2640615bd8879fac86f33c0ebf5aab3d0d4b010c955\ 1bef7718a83f66989073d65be312959c7c9937aaabe885475695d9dd1902651a5cd5f2d9ce22a6048f450b946f\ 042d4f9a2d15ed6a44d25272dce6b428476ab4a30c7d0300bbdf8a8cbae64493c2f3d0ea96dbe0adc923d55fff\ 656cc9d6b580f8d0add486b744493d4f9b350e37ff03e161abf2c2fd4893f126eff0a9b7b4f139f5368f126fc3\ 52362625255424e59ab7a735c2af91f74edfe3d37697ce869643481c7dc622fd11f6214d54709f5388c25fb8e8\ 690a34e8f4636c8a0ca5813927775ec20ea47fd7f0224e27ed9ebff6f101134d49ff8c6dd63ba49afa639a248b\ 3f88841d75b76333f69d13436dc569ecefd0683730d63b9249361dc821d6ec48b599171f73d07d2d356ab1b0dc\ 9dcc7bcd835d04ecb8ed41b2352145ab7136bd22c3c41e6a588a6760c1a914f23552091fad57262a23ad399e35\ 51b0b228b6dfc03c6869855611a71ea2a1b5016273f7eed2871f29979b0d9ba2abb1b7e380f0cf87a751babe1e\ 3d654913b9404d39fa3600a7242059cfcb69ccc95cab565fb53487bda573040c9a25205b93635c890bf9a60959\ 13cffc5cdc250bd50af4696d0d8d39574875a1cdc764ff65ab0#6302", "0.007532733962226776718609740913688407060156761888422741155537371074310369441516668932842\ 179178987568947783738784004214845903753330652661093496965654876471036972958909346642328584\ 201643545013628367738833205156107907841411376234839693950678432472453643018318413087069746\ 828356026984992515666155286293579263416799907808093203442758385289281722930232963476563039\ 602580878024432965067810300259817455445278112730792320635207665972350444684469938601305178\ 752078424498914971701426156771409553942152089734535539717798744531200340412177539019002862\ 118652155125909377605665570522313722924827432454878041302391573666440354096007833415288205\ 656765947802568962289596330168089725205490246098452538786079372905549372857234270190725855\ 849112728556822692019699490095850190529727602819872838218231626101062980913313718469209544\ 852538752806279742668871810873531954763147922731900653003567552388163440686646259900626789\ 714304577755153280330851920000826258260164717299978188447909834297914804211039024170906197\ 475297083472857820673298493173502925728185522784910585353556804550521456290001513633298659\ 714500938359772146658459237683211430724499182734233300374504698265281053478589566729317858\ 790913972324776555314345736769665107752609864227197733165374999429056802940957299499067099\ 921050502361595526540479399993958945176147715155608250079631789775409187220084344594176902\ 12274124444296788210426683668353271294913726417315879718977231613999863580847401836166", "0x0.01edaa4e04695976df280a5d8036e4043050607d25086f92fec3527973e673e50d6fe26cc2a98d36ffdcf\ 64e7201043923f5dc51bce0937d27378352c24808ded1b4b5b3a72dc7bc6709f34a90a426ef3ea922afac190c2\ 8474a8ca4b8fe2f5cbcaee63764658133bf4ee8c398d367693260118ca7e11a3cf7c60021ea9a5c44e5fd2b55c\ 5399c4d2af416fb8495ab953e2fe7f8c37c09d378b6b7ef179c89219865c2e112567c3d0e9ef3604c1cd29671a\ 220859d38f610b87914bda4727d5eb49b9b7067ccd5b9c9ef57e7e59956f66be8e839ab87e7420a7b6d992b60d\ f12bfa9df09e2ca91b91841d01a991c5a473b0d0e55e6f4fda6266333923fec6358fbe2a3c3c1e0005c483a9eb\ a2f70261785a9d095677b794e195f2ebc2ed814ff87150cc3b9449451981dac2554d3c18cf95ed5a563a7acd99\ 5db1f27732d6f2451a3dab2f423f4b7723b8da4c3f303120fc532ea95736220939e15f80b7fd846c650cb099d8\ a0ace134a39fe85ec810d523e13c25e0b719d1cd0977db7ff0a86625a3cb74ff315e7dc83f55296c934dc15f2d\ 4b725cbaa31d95ba6f92d9bc74295829174293ceeb74daf101051b9c789701110c3a4116a550a47c228b82da67\ 245a50e2f1d015ed256175a549250731cf4a90e7f114a6469e323d37552553f60f164d64a8a921b998c466ae6c\ 631027958fb2f7fa98987fb56bdf12919d0fd1695c202c6d66beaf0d9868a53b16e283f1c970a6c9c90790af72\ 75b90192f86671e698defb34b13fbcaaee1cdfc4beec69c2c46072b7a53ab26c823b403098b7657e3ca970d43d\ 9954f49e9d5b94039a66b09f4#4752", 1662, "17069217.78090363703967642537830172830995997926929566889372077304847867142361027601405442\ 286459362568854752643069912976321422774071641269497000825786673743566716666986122201673566\ 954005548156596610807551133418147862857497307376377531996417888282239877181408646433952455\ 449832546174770944921797138738845637802606582911913934926484494169960897434718640487978822\ 397032739913032542773985132071836123040945096104343234766846881246804903855742298793870626\ 77027180448793731547987433698769543012728726607028778", "0x10474a1.c7e94cfe69b17ceb496b55c7673d812006e20b007a03948c3a4b4cfa0e6dbd76b73772e1f6a52b9\ 30ce94a60672db80391db2eb227cad27128df746aae7c1ddb5368fdf97185927d712711fe190297ac2c169017f\ ac401dc6bb041c5fa94ba4452b5b1c6a3d3f8d6d83892439b9e9525639739ce0fdfe4663acc923263563286994\ f78a08edfcad551d9695555741c5301f15857227aeb725ecb09ed40468e21e6e6fe4f0f94b9e338a39e9665362\ acb0922dc06bca5074ed2c965471e97402ed8367fe149485e0bb52e243f78#1662", Less, ); // - rm == Nearest && round_bit != 0 && carry in div_float_significands_general test( "2.454546732648863276547885977493137821487607756249724782555774558593552627360857928230048\ 942018665976138591785782565939256583959305212359451403757412054481726126552732229930964269\ 470905492198653519153594970703124999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 995761114627674791277020932519574469505017610728137410250159407014720169738824650046673749\ 059339474479527195633303962573451642912661719349979993453218111358455268175773121496346851\ 580476856645369527796626919786850732045813122714395701160155300736782415936562761674226693\ 028929972451809327089060718204876263534635026488050357020524924317959135992439056643999723\ 656960561739673936265216544476386688997222734833105296938067057205929214479610015975275932\ 718619380628277147130611593861916399934357066581330096178050556305086195135562253719174061\ 496425118601354010153670564319137109364713055282273218494183562236985834389291157056469689\ 9828846337814e-91", "0x7.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000E-76#4517", "0.015625000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000771048757510508716764719334683019132168263108153512725551350734409293871565\ 903519457201213361797567020084883497703807999422859208123581192925346248118136084792628172\ 988363113468168413497993606331107182531734570308778128025953654408272649725745457159283262\ 0134958821588759455527143", "0x0.0400000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff\ fffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000#3655", 2337, "1.570909908895272496990647025595608205752068963999823860835695717499873681510949074067231\ 322891946224728698742900842201124213733955335910048898404743714868304720993748627155817132\ 46137951500713825225830078125e-89", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000E-74#2337", Greater, ); // - x_exp < Float::MIN_EXPONENT // - x_exp < Float::MIN_EXPONENT special // - x_exp < Float::MIN_EXPONENT special && sign test( "too_small", "0x1.0E-268435456#1", "1.5", "0x1.8#2", 2, "too_small", "0x1.0E-268435456#2", Greater, ); // - x_exp < Float::MIN_EXPONENT special && !sign test( "too_small", "0x1.0E-268435456#1", "-1.5", "-0x1.8#2", 2, "-too_small", "-0x1.0E-268435456#2", Less, ); // - x_exp < Float::MIN_EXPONENT not special // - x_exp < Float::MIN_EXPONENT not special && sign && rm == Floor | Down | Nearest test( "too_small", "0x1.0E-268435456#1", "3.0", "0x3.0#2", 2, "0.0", "0x0.0", Less, ); // - x_exp < Float::MIN_EXPONENT not special && !sign && rm == Ceiling | Down | Nearest test( "too_small", "0x1.0E-268435456#1", "-3.0", "-0x3.0#2", 2, "-0.0", "-0x0.0", Greater, ); // - exp_diff + 2 < Float::MIN_EXPONENT // - exp_diff + 2 < Float::MIN_EXPONENT && sign && rm == Floor | Down | Nearest test( "too_small", "0x1.0E-268435456#1", "too_big", "0x6.0E+268435455#2", 2, "0.0", "0x0.0", Less, ); // - exp_diff + 2 < Float::MIN_EXPONENT && !sign && rm == Ceiling | Down | Nearest test( "too_small", "0x1.0E-268435456#1", "-too_big", "-0x6.0E+268435455#2", 2, "-0.0", "-0x0.0", Greater, ); // - x_exp > Float::MAX_EXPONENT // - x_exp > Float::MAX_EXPONENT // - x_exp > Float::MAX_EXPONENT && sign && rm == Ceiling | Up | Nearest test( "too_big", "0x6.0E+268435455#2", "0.8", "0x0.c#2", 2, "Infinity", "Infinity", Greater, ); // - x_exp > Float::MAX_EXPONENT && !sign && rm == Floor | Up | Nearest test( "too_big", "0x6.0E+268435455#2", "-0.8", "-0x0.c#2", 2, "-Infinity", "-Infinity", Less, ); // - exp_diff > Float::MAX_EXPONENT // - exp_diff > Float::MAX_EXPONENT && sign && Ceiling | Up | Nearest test( "too_big", "0x6.0E+268435455#2", "too_small", "0x1.8E-268435456#2", 2, "Infinity", "Infinity", Greater, ); // - exp_diff > Float::MAX_EXPONENT && !sign && Ceiling | Up | Nearest test( "too_big", "0x6.0E+268435455#2", "-too_small", "-0x1.8E-268435456#2", 2, "-Infinity", "-Infinity", Less, ); } #[test] fn div_prec_fail() { assert_panic!(Float::NAN.div_prec(Float::NAN, 0)); assert_panic!(Float::NAN.div_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.div_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.div_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.div_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.div_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_div_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = x.clone().div_round(y.clone(), rm); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); assert_eq!(o, o_out); let (quotient_alt, o_alt) = x.clone().div_round_val_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_round_ref_val(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_round_ref_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_round_assign(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_round_assign_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } let (quotient_alt, o_alt) = div_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "1.0", "0x1.0#1", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "0.0", "0x0.0", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Exact, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Floor, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Ceiling, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Down, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Up, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Nearest, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Exact, "-123.0", "-0x7b.0#7", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Floor, "0.0081", "0x0.0210#7", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Ceiling, "0.0082", "0x0.0218#7", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Down, "0.0081", "0x0.0210#7", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Up, "0.0082", "0x0.0218#7", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Nearest, "0.0082", "0x0.0218#7", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Floor, "-0.0082", "-0x0.0218#7", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Ceiling, "-0.0081", "-0x0.0210#7", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Down, "-0.0081", "-0x0.0210#7", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Up, "-0.0082", "-0x0.0218#7", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Nearest, "-0.0082", "-0x0.0218#7", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Exact, "0.5", "0x0.8#1", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "0.45015815807855303", "0x0.733d90a6f99884#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "0.45015815807855303", "0x0.733d90a6f99884#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-0.45015815807855303", "-0x0.733d90a6f99884#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-0.45015815807855303", "-0x0.733d90a6f99884#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "-0.45015815807855303", "-0x0.733d90a6f99884#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "-0.45015815807855303", "-0x0.733d90a6f99884#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "-0.45015815807855308", "-0x0.733d90a6f99888#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "0.45015815807855303", "0x0.733d90a6f99884#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "0.45015815807855303", "0x0.733d90a6f99884#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "0.45015815807855308", "0x0.733d90a6f99888#53", Greater, ); // - rm == Floor || rm == Down in div_float_significands_same_prec_lt_w test( "1.0", "0x1.0#2", "1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less, ); // - rm == Ceiling || rm == Up in div_float_significands_same_prec_lt_w test( "1.0", "0x1.0#2", "1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater, ); // - rm == Floor || rm == Down in div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Down, "0.99999999999999999989", "0x0.fffffffffffffffe#64", Less, ); // - rm == Ceiling || rm == Up in div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Up, "0.99999999999999999995", "0x0.ffffffffffffffff#64", Greater, ); // - rm == Floor || rm == Down in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Down, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - rm == Ceiling || rm == Up in div_float_significands_same_prec_gt_w_lt_2w // - (rm == Ceiling || rm == Up) && !overflow in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Up, "0.99999999999999999997", "0x0.ffffffffffffffff8#65", Greater, ); // - rm == Floor || rm == Down in div_float_significands_long_by_short test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less, ); // - rm == Ceiling || rm == Up in div_float_significands_long_by_short // - (rm == Ceiling || rm == Up) && !overflow in div_float_significands_long_by_short test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater, ); // - rm == Floor || rm == Down || inex == 0 second time in div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000005", "0x1.0000000000000001#65", Down, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - (rm == Ceiling || rm == Up) && inex != 0 second time in div_float_significands_general // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) in // div_float_significands_general // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) && !carry in // div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000005", "0x1.0000000000000001#65", Up, "0.99999999999999999997", "0x0.ffffffffffffffff8#65", Greater, ); // - rm == Down || rm == Floor first time in div_float_significands_general test( "9601551840755394477782155306615.400809036690567306698564563582349725588158197630704697078\ 013417362910194409963799900311565761064675199511838067316509390850104862662213505749078521\ 770377437536581181743514602025941917984526635269955727174740188131870994016855234632753317\ 016792561638598147688756431699678956508985348347746587700412259161976828470219450879730366\ 977549362693268375201952814531271011740413280015272635082852480719566333921902104982178638\ 916033220231617933208782646056491566119203568817027316959068412927057431189073591651262563\ 044927867605702941287180061603188567390575475013505450984801866920347023147022407388362970\ 59088991236828388853335477454316615451511519", "0x7930498878f5aafc3b8512a677.669b6bc886f9e61b8a5f2697dc5a3b5a2b2256b53dad0634eac355f6a0a5\ 1716868ade4d034f6702fb8253c1f989a028a5714d4d362b3553fc85427910a52d3d77e4f39bbc7914d902c799\ e58ce8c619156cf04fd16baabf3b0abeb8808eb23612b9dac1cebfc00ede036daaa891cfe4e827cb450c1dc08a\ 8127d7ab7af3ad2ad37537634deffc4816e65732919e1337bdf6abce20a753777e12957b9282ddb2d803496313\ dc5a1048926798d52bfa132da701a4550ee67ff9951f347ffc2fcd57993813839688be78495c10ef533661a217\ c12a2f3327e0d96f3ee8d9b98f05db022bcbe3a69ce3b5009d3946e0ab02a8f9c18127f132344e97387cb60c19\ 2f6949d3c05183b19bc196#2230", "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ 756123234", "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ 9df7961eaa91080cf7a#6892", Down, "173018210334417056237548035723683.1345550599384516271435235732043979258142510481520742047\ 130035554740186809762152344382670192648388101752940643314971638619112864154957540114182619\ 545209429070531797326950151630683621502942030447090067022672243119213825092070120260014287\ 650642444490245716249659346973699250580875272571662195525373996192885786789722040970217252\ 777370731438163261287964967884564981241085126934825161618449785175399006215884116607844104\ 145207013638867416463540845880013358109313225877568519816660562362871960260263575794026214\ 064890992255005169417359526730610750695374229149780488537259076167061214467019669082171678\ 943457474819859479858903499033921570632357132665267027905891468527976638032942305102942045\ 515459276591245938425195867555877301085883501327362346064575111830484879274114432829480494\ 563831995727699779881566675298660138793679903428981563834668966551589617302484043712626362\ 382798953692078892165133138064987411558895534104001531006894289080282050149571295909335181\ 515141217224946465992765152346329894825749923118373449366824218493894112781616587290370204\ 333887308955509161095001732854868950761797166686537700534752075294673973732109977084605381\ 070618564835872903186336652176818456094869891043565959999476502149984797401333397104760957\ 841309659194208245402430373249330458021584229695150780497429392832862209911691278370023807\ 694413776673373810444117733945944078894301474904905817592608430260686560983085185519158848\ 721775216278449134110149155717067705547304860141801798990958269542345867084594152084822858\ 297268178452913654780535118518042943385992804181256593442747503443497424231886204147202265\ 781726406780662404185957882728275703416562894011247737570346607390736902934407385727937750\ 626919779463789669366072755563597481186609564844136728714713287282513301914775072382866982\ 311110548050622515213045989841457194255484993918942830103968812317468779964982010673379443\ 545157108484730053634532297455783144465121662023533540802524486197805471362616441499282252\ 085672354541543506489067224840744574429825390924134914919433088957785876098287919516428588\ 72328203", "0x887cbfd350e72440510425951a3.2272334df26c980a06fd6f49c2120e08d01cbf40066a05dc52d2507fc8b\ a1f7ad8adcfa81f54c2d43be83c3e9e1b2ae573ad5d2402f63f8286058a24ae0b84f54fb38a3e8763f3f65332c\ 7370e069a38ad39fac27c8792cedd37255b83172e20e4dad5cd71f1373de167311ac9c40b97f28dc1deb8f917a\ 4865473383f409e6cb0a10648e46d7a7b4e3635e29b5f290c2b02e89657217e160a8ead0781ee8d369a3f6e0e3\ 373a660b0b7d660faa1b7d91b4cf5cd42a8bdff468e78bef9c7ea60bb9ae18146e44c1a152917815a88c662a0e\ 8a69d92af1497fcb3af33505d54a549fda939b9762346d0a3acec60a952593d9b87d971a913e1a736e06692ed4\ d0790ed0c9756fec1894ac0a4801a0f3ab65d90696cae94d0193ab36015ac78e049348dcf1a40ba53488aff432\ 71652cc4085e19eb0dee362c9c49aeb3ae6922f6bc840455cda7693538989a16dcbcd4771ea096b89b7b6ec780\ e4860380764f3f7268711f226e1c48f3f0ae8068a5d25f97b077ce5d6fb11aa921f2c3ba7cf501ff5bc4456ff0\ a7d490f2e7130fd865897809259d125e6c3a3766e4a746daaf401e8c0be059068b0514c0324881a6f2ed930ee7\ 2bad1215cb6436b3338bf75f190705e69ea7c9c4ebae6e62a0dce4ed74cbdd87135c82ac73fd0bb545e0f0950d\ b386f309d2a674b58f9f446549a4ed3ae9a0de62e5e714f93368cb01396ec887f428e0d0df92bd1216c295f4e4\ 0268e7f8acb642c1e0df9c960e503d5774a53e0042cc13863d67afe7b2e6a631449876b9b307dfb8d3d8d23331\ a7f27c4e21b77c1e3fa05115cd74fc8ddf363caf1d632bde07c5905d7b004ae049a1eb0b8862b102bab6364457\ f072e4eda8795c7bb923327eb1948231771fd0cb4ee5dc7380738f0b1c42d79fbd02c6e1825eadf29ecc297410\ bb9dcb7b2dbfdbf605008a87de17f15bcdae1b2fb9bc31db5d05410224a6ce36fad367262fff7a125c662ed7c8\ cd2e30f4106d2b7a2ab98d4736946788f9fe057e0b0b1a6f1eb99ca9d05ba0091da8bcf3c05efa1e034913764a\ 6c0b52c6582c32ce658ca123e9d830d284a0b63dd2e432788616609ae6da4643f7d599c452e4c8b57689f717d1\ 07559c9efcba9e48001571c49a50a5b8bd100a652034b8f6bca1fe99f6e5537912ce6892e13dd1ccae7d8f4f91\ cb7902ec4aa0749ea#6892", Less, ); // - rm == Up || rm == Ceiling first time in div_float_significands_general // - rm == Up || rm == Ceiling && !carry in div_float_significands_general test( "9601551840755394477782155306615.400809036690567306698564563582349725588158197630704697078\ 013417362910194409963799900311565761064675199511838067316509390850104862662213505749078521\ 770377437536581181743514602025941917984526635269955727174740188131870994016855234632753317\ 016792561638598147688756431699678956508985348347746587700412259161976828470219450879730366\ 977549362693268375201952814531271011740413280015272635082852480719566333921902104982178638\ 916033220231617933208782646056491566119203568817027316959068412927057431189073591651262563\ 044927867605702941287180061603188567390575475013505450984801866920347023147022407388362970\ 59088991236828388853335477454316615451511519", "0x7930498878f5aafc3b8512a677.669b6bc886f9e61b8a5f2697dc5a3b5a2b2256b53dad0634eac355f6a0a5\ 1716868ade4d034f6702fb8253c1f989a028a5714d4d362b3553fc85427910a52d3d77e4f39bbc7914d902c799\ e58ce8c619156cf04fd16baabf3b0abeb8808eb23612b9dac1cebfc00ede036daaa891cfe4e827cb450c1dc08a\ 8127d7ab7af3ad2ad37537634deffc4816e65732919e1337bdf6abce20a753777e12957b9282ddb2d803496313\ dc5a1048926798d52bfa132da701a4550ee67ff9951f347ffc2fcd57993813839688be78495c10ef533661a217\ c12a2f3327e0d96f3ee8d9b98f05db022bcbe3a69ce3b5009d3946e0ab02a8f9c18127f132344e97387cb60c19\ 2f6949d3c05183b19bc196#2230", "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ 756123234", "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ 9df7961eaa91080cf7a#6892", Up, "173018210334417056237548035723683.1345550599384516271435235732043979258142510481520742047\ 130035554740186809762152344382670192648388101752940643314971638619112864154957540114182619\ 545209429070531797326950151630683621502942030447090067022672243119213825092070120260014287\ 650642444490245716249659346973699250580875272571662195525373996192885786789722040970217252\ 777370731438163261287964967884564981241085126934825161618449785175399006215884116607844104\ 145207013638867416463540845880013358109313225877568519816660562362871960260263575794026214\ 064890992255005169417359526730610750695374229149780488537259076167061214467019669082171678\ 943457474819859479858903499033921570632357132665267027905891468527976638032942305102942045\ 515459276591245938425195867555877301085883501327362346064575111830484879274114432829480494\ 563831995727699779881566675298660138793679903428981563834668966551589617302484043712626362\ 382798953692078892165133138064987411558895534104001531006894289080282050149571295909335181\ 515141217224946465992765152346329894825749923118373449366824218493894112781616587290370204\ 333887308955509161095001732854868950761797166686537700534752075294673973732109977084605381\ 070618564835872903186336652176818456094869891043565959999476502149984797401333397104760957\ 841309659194208245402430373249330458021584229695150780497429392832862209911691278370023807\ 694413776673373810444117733945944078894301474904905817592608430260686560983085185519158848\ 721775216278449134110149155717067705547304860141801798990958269542345867084594152084822858\ 297268178452913654780535118518042943385992804181256593442747503443497424231886204147202265\ 781726406780662404185957882728275703416562894011247737570346607390736902934407385727937750\ 626919779463789669366072755563597481186609564844136728714713287282513301914775072382866982\ 311110548050622515213045989841457194255484993918942830103968812317468779964982010673379443\ 545157108484730053634532297455783144465121662023533540802524486197805471362616441499282252\ 085672354541543506489067224840744574429825390924134914919433088957785876098287919516428588\ 7232821", "0x887cbfd350e72440510425951a3.2272334df26c980a06fd6f49c2120e08d01cbf40066a05dc52d2507fc8b\ a1f7ad8adcfa81f54c2d43be83c3e9e1b2ae573ad5d2402f63f8286058a24ae0b84f54fb38a3e8763f3f65332c\ 7370e069a38ad39fac27c8792cedd37255b83172e20e4dad5cd71f1373de167311ac9c40b97f28dc1deb8f917a\ 4865473383f409e6cb0a10648e46d7a7b4e3635e29b5f290c2b02e89657217e160a8ead0781ee8d369a3f6e0e3\ 373a660b0b7d660faa1b7d91b4cf5cd42a8bdff468e78bef9c7ea60bb9ae18146e44c1a152917815a88c662a0e\ 8a69d92af1497fcb3af33505d54a549fda939b9762346d0a3acec60a952593d9b87d971a913e1a736e06692ed4\ d0790ed0c9756fec1894ac0a4801a0f3ab65d90696cae94d0193ab36015ac78e049348dcf1a40ba53488aff432\ 71652cc4085e19eb0dee362c9c49aeb3ae6922f6bc840455cda7693538989a16dcbcd4771ea096b89b7b6ec780\ e4860380764f3f7268711f226e1c48f3f0ae8068a5d25f97b077ce5d6fb11aa921f2c3ba7cf501ff5bc4456ff0\ a7d490f2e7130fd865897809259d125e6c3a3766e4a746daaf401e8c0be059068b0514c0324881a6f2ed930ee7\ 2bad1215cb6436b3338bf75f190705e69ea7c9c4ebae6e62a0dce4ed74cbdd87135c82ac73fd0bb545e0f0950d\ b386f309d2a674b58f9f446549a4ed3ae9a0de62e5e714f93368cb01396ec887f428e0d0df92bd1216c295f4e4\ 0268e7f8acb642c1e0df9c960e503d5774a53e0042cc13863d67afe7b2e6a631449876b9b307dfb8d3d8d23331\ a7f27c4e21b77c1e3fa05115cd74fc8ddf363caf1d632bde07c5905d7b004ae049a1eb0b8862b102bab6364457\ f072e4eda8795c7bb923327eb1948231771fd0cb4ee5dc7380738f0b1c42d79fbd02c6e1825eadf29ecc297410\ bb9dcb7b2dbfdbf605008a87de17f15bcdae1b2fb9bc31db5d05410224a6ce36fad367262fff7a125c662ed7c8\ cd2e30f4106d2b7a2ab98d4736946788f9fe057e0b0b1a6f1eb99ca9d05ba0091da8bcf3c05efa1e034913764a\ 6c0b52c6582c32ce658ca123e9d830d284a0b63dd2e432788616609ae6da4643f7d599c452e4c8b57689f717d1\ 07559c9efcba9e48001571c49a50a5b8bd100a652034b8f6bca1fe99f6e5537912ce6892e13dd1ccae7d8f4f91\ cb7902ec4aa0749eb#6892", Greater, ); // - in div_float_significands_same_prec_lt_w // - increment_exp in div_float_significands_same_prec_lt_w // - (q0 + 2) & (mask >> 1) <= 2 in div_float_significands_same_prec_lt_w // - h == 0 && l < y in div_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal, ); // - !increment_exp in div_float_significands_same_prec_lt_w // - (q0 + 2) & (mask >> 1) > 2 in div_float_significands_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_lt_w // - rm == Nearest in div_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (quotient & shift_bit) != 0) in // div_float_significands_same_prec_lt_w test( "1.0", "0x1.0#2", "1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater, ); // - h != 0 || l >= y in div_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.0", "0x1.0#2", Nearest, "1.5", "0x1.8#2", Equal, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & shift_bit) == 0)) in // div_float_significands_same_prec_lt_w test( "1.0", "0x1.0#3", "1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less, ); // - in div_float_significands_same_prec_w // - increment_exp in div_float_significands_same_prec_w // - hi == 0 && lo < y in div_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "1.0", "0x1.0000000000000000#64", Equal, ); // - !increment_exp in div_float_significands_same_prec_w // - round_bit == 0 in div_float_significands_same_prec_w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_w // - rm == Nearest in div_float_significands_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (quotient & 1) == 0)) in // div_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "0.99999999999999999989", "0x0.fffffffffffffffe#64", Less, ); // - hi != 0 || lo >= y in div_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0", "0x1.0000000000000000#64", Nearest, "1.0000000000000000001", "0x1.0000000000000002#64", Equal, ); // - rm == Nearest || round_bit != 0 && (sticky_bit != 0 || (quotient & 1) != 0) in // div_float_significands_same_prec_w test( "1.0000000000000000002", "0x1.0000000000000004#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "1.0000000000000000001", "0x1.0000000000000002#64", Greater, ); // - round_bit != 0 in div_float_significands_same_prec_w test( "3.1790543009742223972e-11", "0x2.2f43e0add6ebd01cE-9#64", "7770090901.6225594673", "0x1cf222d95.9f600ea8#64", Nearest, "4.0913991113158902183e-21", "0x1.35232b1b3b9aeabeE-17#64", Greater, ); // - in div_float_significands_same_prec_gt_w_lt_2w // - increment_exp in div_float_significands_same_prec_gt_w_lt_2w // - in div_float_2_approx // - y_1 != Limb::MAX in div_float_2_approx // - r_1 == 0 in div_float_2_approx // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in div_float_significands_same_prec_gt_w_lt_2w // - s_2 == 0 && s_1 <= y_1 && (s_1 != y_1 || s_0 < y_0) in // div_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "1.0", "0x1.0000000000000000#65", Equal, ); // - !increment_exp in div_float_significands_same_prec_gt_w_lt_2w // - s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) in // div_float_significands_same_prec_gt_w_lt_2w // - round_bit != 0 || sticky_bit != 0 in div_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in div_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in // div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - r_1 != 0 in div_float_2_approx test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "0.99999999999999999989", "0x0.fffffffffffffffe0#65", Less, ); // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in div_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000016", "0x1.0000000000000003#65", Nearest, "0.99999999999999999984", "0x0.fffffffffffffffd0#65", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in div_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "1.00000000000000000005", "0x1.0000000000000001#65", Greater, ); // - y_1 == Limb::MAX in div_float_2_approx test( "5.29395592276605355108231857701752e-23", "0x4.00000007e000fffffff0000000E-19#107", "255.999999999999999999999947060441", "0xff.ffffffffffffffffffc000000#107", Nearest, "2.06795153233048966839153112178982e-25", "0x4.00000007e000fffffff1000000E-21#107", Less, ); // - in div_float_significands_long_by_short // - diff >= 0 in div_float_significands_long_by_short // - in limbs_div_limb_to_out_mod_with_fraction // - d.get_highest_bit() in limbs_div_limb_to_out_mod_with_fraction // - sticky_bit != 0 || diff >= 0 || i >= abs_diff in div_float_significands_long_by_short // - tmp[ys_len] == 0 in div_float_significands_long_by_short // - tmp[ys_len] == 0 && shift != 0 in div_float_significands_long_by_short // - round_bit != 0 || sticky_bit != 0 in div_float_significands_long_by_short // - rm == Nearest in div_float_significands_long_by_short // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (ys[0] & shift_bit) != 0) in // div_float_significands_long_by_short // - rm == Nearest && !overflow in div_float_significands_long_by_short test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (ys[0] & shift_bit) == 0)) in // div_float_significands_long_by_short test( "1.0", "0x1.0#1", "1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less, ); // - tmp[ys_len] != 0 in div_float_significands_long_by_short // - tmp[ys_len] != 0 && shift != 0 in div_float_significands_long_by_short test( "1.5", "0x1.8#2", "1.2", "0x1.4#3", Nearest, "1.2", "0x1.4#3", Greater, ); // - round_bit == 0 && sticky_bit == 0 in div_float_significands_long_by_short test( "1.5", "0x1.8#2", "1.5", "0x1.8#3", Nearest, "1.0", "0x1.0#3", Equal, ); // - tmp[ys_len] == 0 && shift == 0 in div_float_significands_long_by_short // - c >= u - c in div_float_significands_long_by_short test( "1539239.2465826685826", "0x177ca7.3f200ab152a#64", "0.00009", "0x0.0006#3", Nearest, "16812597210.673628039", "0x3ea1bdfda.ac72e31c#64", Greater, ); // - c < u - c in div_float_significands_long_by_short // - round_bit == 0 in div_float_significands_long_by_short test( "1.7088961703394199635e-73", "0x4.d4baa70e83509ad8E-61#64", "1.7359472818744e-34", "0xe.6bf39991dcE-29#42", Nearest, "9.844170892645193631e-40", "0x5.5c13c13c6d059800E-33#64", Less, ); // - tmp[ys_len] != 0 && shift == 0 in div_float_significands_long_by_short test( "4.874956728709606165589080471392071684004548689044982493122e-71", "0x5.6220e3ededa8be921ace72bbb95a16164a2f0abd57c49f18E-59#192", "1.5092483e-10", "0xa.5f190E-9#22", Nearest, "3.230056172437141772802006354545046772521759341614858124236e-61", "0x8.4e07636cdfc96e412c1de0a522f40a5f092091c1a3aa159E-51#192", Less, ); test( "6.88621557179233820703925296804982406452e-28", "0x3.68ee78c4dbb67961d201a40495749728E-23#127", "0.1418399214207466117788070203268", "0x0.244f9effc4f1edfd85dfab3008#99", Nearest, "4.85492060543760755133907256608679730501e-27", "0x1.80a57d020f8b7083401eec627a6787ccE-22#127", Greater, ); // - in div_float_significands_general // - up[u_size - 1] == vp[vsize - 1] in div_float_significands_general // - k == 0 || l == 0 in div_float_significands_general // - up[k] == vp[l] && l != 0 in div_float_significands_general // - q0size < MPFR_DIV_THRESHOLD || vsize < MPFR_DIV_THRESHOLD in div_float_significands_general // - rm != Nearest || shift != 0 second time in div_float_significands_general // - qqsize > u_size in div_float_significands_general // - qqsize > u_size && !extra_bit in div_float_significands_general // - vsize >= qsize in div_float_significands_general // - in limbs_div_helper // - ds_len == 2 in limbs_div_helper // - qsize == q0size in div_float_significands_general // - vsize <= qsize in div_float_significands_general // - rm == Nearest second time in div_float_significands_general // - !goto_truncate_check_qh && !goto_sub_1_ulp && !goto_sub_1_ulp && !goto_sub_2_ulp in // div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) in div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit == 0 in // div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - up[u_size - 1] != vp[vsize - 1] in div_float_significands_general test( "1.0", "0x1.0#1", "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "0.99999999999999999989", "0x0.fffffffffffffffe0#65", Less, ); // - qqsize > u_size && extra_bit in div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 in // div_float_significands_general // - rm == Nearest && (round_bit != 0 || sticky != 0) && round_bit != 0 && sticky != 0 && !carry // first time in div_float_significands_general test( "1.5", "0x1.8#2", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "1.49999999999999999995", "0x1.7fffffffffffffff#65", Greater, ); // - ds_len > 1 in limbs_div_helper test( "12077.327578390390934514", "0x2f2d.53dc2d699afa78b8#75", "4.90332775049862782951473377323022738896770775e-11", "0x3.5e9a4013acb1890afeca956568e5bffe30edE-9#146", Nearest, "246308796656764.923124719743308898445103382544", "0xe0043c546c7c.ec51e6d16d3ab81c76ba65494#146", Less, ); // - vsize < qsize in div_float_significands_general test( "1917511442.613985761391508315964935868035476119276770671", "0x724ae712.9d2e2bbd62dd31f140b2b9b664635f251b18c0#180", "3.352896739388742667241376e25", "0x1.bbc08f6e851e14a094c4E+21#79", Nearest, "5.718969570663133425280005234972069245666491961744252885e-17", "0x4.1ef6b3c1725013efb2a8179983b542a97b0131f39a938E-14#180", Greater, ); // - rm == Nearest && shift == 0 second time in div_float_significands_general // - qsize != q0size in div_float_significands_general test( "1.490328e-27", "0x7.61370E-23#20", "2.89262335038499315783322011549431655756e-75", "0x1.4ef161f7b7fc2c6cb4464f827b58b972E-62#128", Nearest, "5.15216656741446303242577558053691246166e47", "0x5.a3f1d299f6f20544fbba161403f075f8E+39#128", Less, ); // - rm == Floor || rm == Down || (round_bit == 0 && sticky == 0) in // div_float_significands_general test( "2.38418579101562499999949513e-7", "0x3.fffffffffffffffffc0000E-6#87", "2113929216.0", "0x7e000000.000000000#66", Nearest, "1.12784561231761934265233937e-16", "0x8.208208208208208200000E-14#87", Equal, ); // - k != 0 && l != 0 in div_float_significands_general // - up[k] != vp[l] first time in div_float_significands_general // - up[k] != vp[l] second time in div_float_significands_general test( "65535.99999999999999994", "0xffff.fffffffffffffc#70", "22835963083295358096932575511189670382427701248.00000000000000022202", "0x3fffffffffffffffffffffffff8000007000000.0000000000000fff8#219", Nearest, "2.869859254937225361249367321235116718339077564583058127288930659162e-42", "0x3.fffffffffffffffff000000007fffff8ffffffffffe000001c00008E-35#219", Greater, ); // - up[k] == vp[l] first time in div_float_significands_general test( "1.91561942608236107295e53", "0x2.0000000000000000E+44#66", "43556142965880123323311949751266331066368.000061035156249999998", "0x8000000000000000000000000000000000.0003fffffffffffff8#205", Nearest, "4398046511103.99999999999999999999999999999999383702417796084544", "0x3ffffffffff.ffffffffffffffffffffffffffe00000000000004#205", Less, ); // - up[k] == vp[l] && l == 0 second time in div_float_significands_general test( "255.99999999813735485076904", "0xff.fffffff800000000000#82", "1.35525271559701978119405335351978053e-20", "0x3.ffffffffe0000000000000000000E-17#114", Nearest, "18889465931478580854784.0", "0x4000000000000000000.0000000000#114", Equal, ); // - q0size >= MPFR_DIV_THRESHOLD && vsize >= MPFR_DIV_THRESHOLD in // div_float_significands_general // - u_size < n << 1 in div_float_significands_general // - vsize < n in div_float_significands_general // - in limbs_float_div_high // - len >= MPFR_DIVHIGH_TAB.len() in limbs_float_div_high // - k != 0 in limbs_float_div_high // - q_high != 0 in limbs_float_div_high // - carry == 0 in limbs_float_div_high // - carry != 0 in limbs_float_div_high // - len < MPFR_DIVHIGH_TAB.len() in limbs_float_div_high // - k == 0 in limbs_float_div_high // - len > 2 in limbs_float_div_high // - qh == 1 in div_float_significands_general // - in round_helper_2 // - err0 > 0 in round_helper_2 // - err0 > prec && prec < err in round_helper_2 // - s != Limb::WIDTH in round_helper_2 // - n != 0 && tmp != 0 && tmp != mask in round_helper_2 // - round_helper_2 in div_float_significands_general // - rm == Nearest first time in div_float_significands_general // - rm == Nearest && shift != 0 first time in div_float_significands_general // - rm == Nearest && round_bit == 0 in div_float_significands_general test( "914122363545.7300954288539961362078521335512160921125366724096502748846903936195389924148\ 154757063704910629280973433563521737016298541257057972452261335506117124831272191707877190\ 2119190824963185068512647039440777212199983388696", "0xd4d5f05299.bae788b5e312f78f55ac79e4ca82e12494296afdb40ba21e0c21a4b3915ba2e217c389f8c9fd\ 22042f5ed70da20cfb9f1ee797b1433e077a2d34b1ae5781f975eebbcb21a32ee0c5afa5e59f8f382fe0c754a4\ a3fb57fa4d668#754", "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ 9912721166210129145585", "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ 02af09995fd6ced97b00#1859", Nearest, "9.161757985214429764992710266551647359057325985892606639113002591596898046569993924851132\ 469009506849046579846739625666450546615840413944516736833310444241924771226669449467280905\ 847180462085951493210441487438964221396785151298524525494386941673630175499486324164244756\ 513337189186243674611400515366863669226025015162200893355049656715514081022497216123358900\ 204159965608607573130556648229035236124949246847315199932950877590362471534070708393335471\ 028355306786566135185894674384218244976402468322690432705335567965983855642753641740432604\ 3437409476409135277542e-112", "0x8.d032a1c09c5a822250facc4d03dcbdde26d4f5fe102c1e08a4f87e413b615d798e202484a718a7e4ee277\ 3677de7769fc7d817e371393d771d3460b42f92e9ba23196df3ebdff7cdda4294aecfb6c43776a893a979bdc8c\ cac166e11d435edd52a1481ecb355a6595fcd794f14478ca886b31b8422e8bc9fdcdbc2261e6c6dfdfea3875fd\ d48e82b6f89b37437a8064efc36e3671100bf00cb530951d17bbaefe545249991b357ff0fbc5a593a69916e391\ e844f20336e8635a395cbda774a8ed440b65ccac5a4a48827068b6780bdeecccb424ecbcea085547d055a670dd\ a2ce7fd1bc8ccfff3fcE-93#1859", Less, ); // - q_high == 0 in limbs_float_div_high test( "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ 62431384255329048179650372924700507846477189871631671161154559755984562472291", "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", Nearest, "1.150400792350488243006374252439239370084430198894097883408930056885079539097149903334801\ 351771948494649335504249165228317854781872084884358035626531528587565616792440130659246789\ 547068913471358728267587391921067763401960740658485999234360708658257354709138940743401019\ 478517400580149085993404074744575447821383623813098520973947955049547026992303475579228215\ 436224676800479021561310494945776720018368502752527214637080415175177143606297950367602304\ 149567232708944245857383841379350871799797376084773487408407355299732079377175164962925047\ 553551234005632068337070468847266947004802579875459884664958168707856865409967591741263680\ 896819771668163339399940221050773763868745744855354003266260565352234279551485173590767169\ 460117377689246074482291141675360319952860733464727767370984256722737643645180588444886771\ 648355387388454942423178644791668457452750839522592156007162798991977390140623536578544490\ 057707937271642210929120388296125663413585185722459999909564986042307052548228205977082023\ 238981495642981332360042089388607651948288196055583153394379775735995327224157713864077477\ 321557707540034099204193983589868016082915953745995091314702115380175700364741814725184464\ 602065018950641261052531311066491931955988616475785792821351515116629573461861957542243077\ 532642867446492701937719979200426618485741197144774966492676324343483017759514367363624027\ 675809506514516688590348320872084123672477458766804242125009602995249222201904595636534318\ 096670348004414769559053243712710972449074750435098780379781902955436286126620063025099547\ 80435463720060716005725004637793753168276780047800093479230422676842555945701e-42", "0x1.9a7a0a4405b5655db3032989d155cf7a58151a06aacabc4789fac720edfb0e835fe88bc9af3cc179149fe\ 616753cd76b4c7d9c17f2f47389f4e0007572679dad2a5316ede08c14af0283577f171d41d795d4ff13631def2\ 630089c6f215d7b5b8948c52ff97a4a1d9f1eb6d67b60e55478c40ffd2a7cd9684f43637e46ce3ce3e33085654\ 9165c4a377c6ab1dbb9c9b40ece8c47d94ddd1318dd2e5e57388b2e8ef80705d97c3db61d805c43cf7ff7a9a1e\ 41ded3ff033e68dc751b34ffd9cf2eae50cb7e7875b9d8f24116927cd9f609a65c71e840166cf535bbf110404d\ bc493350b17705c0e23a9091d61f544117f70c6c6387dfb9a1dcc2f513cfbebc4cdd4b7d94c9fc57ceebebe3a2\ e7d85b9b488b5571ef7b7c8621b770d99c67f9a19252ec5f9be4b129c7755b4a8585b97ea68e60e390c0b5c2b2\ 7b5fc3a47825c136e3b2517a6a7490ae84cf61659a9b819bfe59d45f7254dd48e028c7b694a9b9b427e60358fd\ 52afbeed855580a61e351d523d4ffaabfc7ca00e9a5b40128e9fd8b2998c189e95abc1857ff9ddf1dac904a2de\ dfce45cbc4f1ffac50c26ec7e1135aa9ca96f6d3ac8cb3a6620a3aecb003d246eade4cf0e6394df920dfba899f\ 44ed41072e121f0402f19fc4c43c348467a07566df372a7b1af45354f2b4c7f94d52f355813e84c1a95202029c\ 0056a974e856e7c42fd6463561d1b5e02ed6a7e0ea0ca50887bd1047f4abd068ea61e2095abdad6a0cbaf91846\ a340717aa624d6c6ba02f5d3e835ff06c742f1343479ec9a9b184eaca8e7c8be7eaf4fa322afc13f046a4a2e5f\ 4e84c723c68079991a080ac6939780e172640d568c2bc3452c14317358ee8d27a18af7c9bf2de8bea3e5b8b113\ d8e61b810d6103e805c2a8f85b9b88f8c9129b924ba95521aa83a066991bea980c8be16f1df53E-35#5329", Less, ); // - qh != 1 in div_float_significands_general test( "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ 3791636230633361526548302742414616516594455084620537903358416e-16", "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ 3a2e81ad38c5d7f45687a8E-13#2587", "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ 61698637621752755004821872e-17", "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ d817f0420227841d34052ed2bd52e148923f8E-15#1571", Nearest, "43.78305573046740119713641861874642911154821650761595780287653003720809501996262685108891\ 851641972710141298162279987632328545443442081070773994511258975201978303856309243168868354\ 195798884971190979692045031917290903217918542303368118161338247041052975773351929884789101\ 115569142934332750399827875003719838494787907290778719530315375971295186399328856671813524\ 401338950750393532748258170809380674066918530153006391759208813425198252649570832466781508\ 205219467712658427254330831981130973959961174357861904110964877950640959685965415405374479\ 749995867814629083616329619361738872731212580413192190669870683344353586783786957328312637\ 080558281918488071596583884466679323108552730394571978915258990045025562636051246193761815\ 9037942507064891051161378037771712070204599081778501997567779", "0x2b.c87657214d897953f5e5edbb169c290285fbd11622c9cf401ba99ad9f03da7ffc778df1db0d888d67c18\ 379efc8b4b36ed8cbb67da04b5b4cfdabc5f751b0a6fc68b1e3a2a16a62c4160ce4d10e00ae47020ca5d3867a7\ 2213145fe6456480971ef0cb9716c6136384fe41721979e86d1ea1bdc104f2967865add528a1367b01cc449a48\ 5786a74209d8e4c5e216fa7ae2dc897fd4926b55eacde3321f7c41bf2875c24933c8eecc7a8a26f738fd6d666b\ 678ec93b48bab7b34c5392d3ca76949dab6958fa5caaf70927d3e8b40d050bb607bc1b4fe656506e1b3e468e87\ 8b257c21e926286697a97538d3230475cd54415b8154351e72363b4b7509061108fc6ac5db47219368f3ca4011\ 5309edd7318a116c2b62a34277bfdc8a1faf656b14b6a046087cfc5dd238cd94fe91967fb6dfc52f8afa5699df\ e2970ca40fb03c71d7d668#2587", Greater, ); // - n != 0 && tmp == 0 in round_helper_2 // - s != Limb::WIDTH first time in round_helper_2 test( "0.029226865494398284939675773661541675546326681033634876986774906885711036844605915426240\ 340310096249605517533494947862661721742262334681480455706389428160732541825851560446846541\ 984468705310228771603694136853587701004882713625816107989162498255925332620064155091399923\ 221735997586925448254801064429910518067322424203818026901404115120552071966804127784634236\ 948421057038304255272147630765439482924461011451862112889343084859504616664030668233890526\ 750016895266382189553251377266295422223247821668554701473442441938933867323625955488726630\ 366895993417469747854898337776376811834753617592182604418498468334055402941851068346511528\ 636460609896950078921029074658151972716364203699936241491820871671807186599907001653993018\ 871354678119954470481273332266267481346670395677171242596948926022697465301700258863974068\ 74909984356479995046141060221761701111762543380195142151878885588292130260647185", "0x0.077b696f76893b930df354ab0e34b0df1508ee4503f673e22fa3b41867c5e4ffbc43b589d4cb4a00c472e\ 4046ccc9dd4a2b88b59dde14b46da030dc5a0f825fc1d9ff0213e8b046b1cd79785dd554b78e98759eae454c23\ 4fddf6ee7ae174bfc7c1ed096e905b41ce6b18511a9bfc9cfbc43c536393410fe83a634f402b0f18a446a3af90\ 9a4079394959da6918bd9094c5b587839c67f902f1f107259257f4ae96549552e41dbe7dbaddda5b9d8fa2b2bd\ d01ba920c27d6ff6e44bd8f0ef230d60508f693680e1d769f920949bd35768a7ff10fa62210e3caf84f93cdccb\ a5238b5e4be804a1422da22abe509c758d0cf44f202896613342ffd0fa93939f0c9bcd4de899fb72b286773da8\ fe9cbfbd51894ec97176996bf2b6a61ac27a5f524cd408e8bca09d7cefc329a98f17616d4b48652d0a3f14cc49\ a9bbe75a69ae9167aaa9d1951d446e95bb89c1760a549ff81f7b1d8ee454047a7d3c3e244dc499d97b256eca33\ 3d43933df1e0a046136e10#2940", "13755175900776476.03444104347769161034491994978466673515315430911280875941467408228432201\ 072744723926732268661761372710838010056791678637659254162102142124198282086034764229922487\ 783612307113854432839997318024745178344073274492535681224805316900558167281372795857375154\ 556654904332875058382920111153919687941523340022403648029377155100560618075774147398400587\ 446623619383420263487024723715538921428293815054071349051549046244877203394687286110159347\ 188168590858399073350484327515115795260226962105536078430163098017753828590552884767518140\ 1985404905771271934", "0x30de427563881c.08d120d36075efcee88657ce81cdcaedf45cd89aeca352b6e32212d20771ea31a54387b4\ 8b1eb8738ae1d31c6213ddc44bdc809d5f5b278e3449ebd13c9ab8d89ec9f0a2d87e7233cbd5128caca14e0c42\ 61e5c9ed6444b50d0cce082673e3c80b1a7102c8fc7520036bc3c6900dbcff7cecdf27ac4022bd4095736dba93\ f47ec8ed66154c32a8eb07e14079a264e1e3370aebbfeacf3a1bbfe7aa657d9911acc70d626a35a29d86c84029\ f97428f7cd8a3965838abf5dba9a9943b07c0ad2541156ef8e2aca1afd50c7dc55f986c835b95647701f744563\ d15716174f2ac444#1845", Nearest, "2.124790384741531086324618396766014790807036315098759090708607153306148130187657728807205\ 824808003798574987452867827342282934278081982848900135498971286785256137258700150407383617\ 040883394430575593960834148265479663570529896251340120502267014474793716347382140126837773\ 997589830815187190064041312015350810806968062929485379465521677249527992330225473850965169\ 559943150658138282772411679190301632849325467452565481282203194749783450341076382685241552\ 308193411477432500590221491760317417660435511777399629140824293491122934845121250984106958\ 267596015361360781611025519421253206751640221273565905944385402975185311734694681019948131\ 664198303801199498616289444621169851399879692298796098215712787193626312888177618196672010\ 550069281366814417353104090880010484400040465312380510548737422916103805415326232623198929\ 338433641210905412883566788706510371353536321443505713555119784985687877546815e-18", "0x2.73209f5170c5b9aaeb5a7e9e79e1dba6ba9eb57b8701701f4d2be387a03993b7e53f907a48a9029ff962b\ 4eb20e6ade6771889642b19b1985ec76b2b24fb517b27eb86681dab6bc7d5a5a203545d850396986ce5c6f9542\ 50b478a0dd27222c6c45900f2d06dad9d7f78a79b9978e3ce203479c5dce6dde3affc40e370565c038007c8bc1\ ef1fdf0f6398b88721063c52e5eb2c4b5ba1f10d93710d5abe8aab35f5bc5cdf7031f7765dd4f9d4065b1b5b86\ 4ccd6665b73715bdfe783fae157cdc8a78e9d053cae011d4dddf28499ac3809e290ca0a221e38d2a6dd8d01980\ c64da2f6836e0815e2ae3feb8a0d765808afcbdf6df10cf661eaf6c064ec8023cad01912101fb7e8b732b555b4\ a053a203ab5ec17c24af5694ed7db4f67c3c76a7f360512bc9a2018d2860111211238048d21af3d79aa0904474\ 22c0d9c9883b2f3769a5fe3faeaf8bab1409329c376b70c7b54fe1393115359c5a7ff43560bc0e2548a02ffb68\ 184585e5023a6fb507d0E-15#2940", Less, ); // - rm == Nearest && round_bit != 0 in div_float_significands_general // - rm == Nearest && round_bit != 0 && !carry in div_float_significands_general test( "767950667289861979450190915916317600206727962344150969868.8721759327117422801652737665276\ 756590281054535919141164571740727630029753345081284383462360338144272865435150624843971065\ 632159910277471560574746205336214689461444841220676837587640834824669960199738043592424986\ 826697488691269778053087892841924823231361961899657984958299046295741089107389167540777341\ 1137893901502419455", "0x1f51c7714fd0115fee394111538cd8cc2697edb4db72ae0c.df46ec035af05536a25a7e2694997099b2577e\ a12f12bb82f781cda7cd6a148cc07ab56a0bac9e90b8590cb04b95fcb27209c3c8704cb6940c7fb857c1688d50\ 6042d2fb6c58e0600ed4d86a5af398f029ebf3521880629fcd23f2bfd5f9447e8dee8310647fde5e5f5e2a0a18\ 7cdc4e8c046be95417ea73f5d4a1962ebecd092b613af810#1250", "51.02908107282950125513822733633990251324880237789609831750259919822628384179764854139813\ 664310170076349095466129599769105832710389521373306698912599298264052853550294941822816681\ 854313580668986120583821047373123379751687690065811623363578923931243167028825931454472450\ 957582633858214796963862561877157489833071159740156527107422181977546544800568916528954101\ 973657910504690951238460938847030239913388867386095316629182004723248011669496406544341717\ 280330814897033602543594303927085904297027340275835376721330553519116838042737905906942433\ 571685773257005175176741271374980135164819404821829229591371965448368260666618720681201228\ 891015077648242337901859343084853665103006650868094946302847691177013349096688713595881758\ 621480481903927608236275982505035171940737146501502983532266096788435188627685343250723400\ 305856753098249087347464717300786991295322157886984156263306019163631926110778355478267431\ 730519001037411438399866507817311259465545754442998333101310788661554118860610086857525556\ 649462275011688416941329847092728287810185063940836755796270353054485056127471728114260616\ 408519706805571508639638485588089026599284155688404740772260862102363921554760355678529807\ 545078380365647104062842403550988330511500383389703046031841433893387481098301402534069795\ 658730174573583314000979689827444189825731612831252242895060479770394162281620141901978731\ 360879005964038152579829187416621515149774573766217606037565254139422563209723838864340747\ 448492223949482531030183865551640816462517599780266133382572731428229045787209942986614817\ 192016158247860998226332096129248802519217902568127470669978186812858044800325333178140023\ 387809105983555698845635663825858578549915679237164757880235025950739307212793316009945989\ 415835829851915334677834156538103555704104713171341701847682567317855121655570126973890951\ 3929068030854124664713500553256", "0x33.0771db70bc3cc1bbfd03fee9ecfaaa1f99d76266a08107a7c922f5787496298c9bd6b5bfa13889bc0bb1\ 0f2e280f2673b20cb2191b3f747978b1483ed5890a8f1e9b4ef8665dff89aeff7e04820fcb58e76837b70b36b4\ 946ecf9ebe8fba5e510503f922f8e39500946e3ba0fd0a28c3a881101047c77426f1160e2835ecd5cdfc3c85d7\ 78adf772e0b5f5d5913cda27866ff4a68981bb0b247705d4a7a13e0cf5df9064561c207ad89d6bd10ed4faf445\ ceca3d7f86bbdcd652aaf5c547a0071a203dca41ee8ec829aff439308e3dd8d470556949fb583c7ed1bd6c7854\ bb629c27db1c0caa83e77e13d983d022e1865331aa5f67de9bca45976769e471933efa23a7d5fe8e03b8eed13a\ 3920db5d0f4052f811bcd1955c217ad35a8b75478eb3f2e077ecc810af955e23d57d0b957bf2104261c9f16ba6\ a16f119f6d83e2b35b1a28b6fc7a029bcec426c495328cba2082e252a65c7267a9a83365475cc6b4672f77d481\ 40ec81e987a366445896d2ae795891105da2f608b56dca4a3e4166c6a0338423e51de87dcbfe3717817893141c\ 8b61f1377d82379374f5ad121cb9e04cf51776a20bc8b0ccaa51862efa4f51d52333818ee4877c039261bcd8dc\ 152db0a6119f3724603b4aaf9994eaf197d5adbcb723d1dc6ebdd8d2cfd37952c4128f3b79556ea134b7193dcf\ afdc170fa41bf528ba4deac3f3d79d4407db9fd076aaca428efe74dbbc1bc7fad8b57ab1a693330f49aab1ddcc\ f26bdc853360568f201c8fea22c816ae67afff2668debe399f951e72144cfa93dea4f18d1ee734ed2bf350fed9\ d126c9b660f6b27ba5e13f15a8be20837e071c52d7588c0a856a969903419e91d47e7011235886759942c1c0e1\ 896e1621b2d23df869694531248722482999c8600632a5ab2279907e29cb3c38994bfbe299cb368a72ef45ecaa\ b9646b4f1e2f37f24aa954535b1ba220c8e91dfb8f81e56dc45ec4cb3181511fa5b1854096fb3f03f2aa052eb1\ 5111548f398b2a0ffeecd95498fef2bd7f25126507f63bd3803c3a9d1aff24563f7f0baf024307e9c75#6074", Nearest, "15049274867282653916783425765897232338286237097021544510.63055696334657926692700975852105\ 429908991325181901560777184807721684871576977542689434849596891044659963521044055457283641\ 367304991334226236960366994118987961185804836414630696056584495778598754606288486597978327\ 332370268104018122071463105903604569912790301532188931593783003198530412792016208481406460\ 177569545284296438034561831086095957417103960718034276692579871391678752019863068680376188\ 441084892942908419595289335759422879108451807263984856494740183999962091220506257869533189\ 151879060260534882539324732360323776701789524149049182180697710000483323367419829770508959\ 886298233038628402259126153349007515813222501560286947664943532169644098519601985837510236\ 220345218089637472842801890223279059211522040546360301667071765816467200381174390649332596\ 068474921226001156721359127966627401319343668619013146928630922944213877247277873392955093\ 504639915667110210542526572018725370251615388653789028473354868425502960351888594917293217\ 742712292964655900915998259809033409553076012583762301750508167459913039705278696038307105\ 198133823120123667996810391703122691279674638629684591634520584549627376733588876153831722\ 199369165407756045645488517825617351416613370266999295351664343537186993481753740631996768\ 537474147168714208012012313452364629821090786481898210882140832386720226088895885830143936\ 713915428453413001094302216345205004980013281182978168058085052927135299009881922560519790\ 174395754146412113876346433499785448301225654969985504964945207336686282652994022882395571\ 250336046288750244045997533647713495015654011612857222465008362940468446125031495141758501\ 398188163302138089732641998828146315905675208381266922364102647252983963785718802006725178\ 667871858412814374481149992996719213942377608145948042933317201168269095689729130915320304\ 63030844892155532105060912300876", "0x9d1f2bb817353ba61ad13135f94f65b1b52180f58a183e.a16c2e5fd6b05e4155475ec873e35d0f193a9765\ ef45957a4681138fd789135172e7be4efd1b67c60d22430a10832c82a4dc4a53156de6d8638ce6ffe089ebf880\ f2e1c68c90b576b5dc0b99085865ed663bd642b7743ff5500d4c6d3e2cf4977af36122c98fc49e81ee87b80d89\ 3fe81fa07bdc5986b40bdb0bf7e6bfde432dcedd2063308cf685bfee2b964ff62d434434a9518683156e532f30\ 11f2ac8f98a75178cd412e00f2261a83f952b6a94bb97c280cb51f16f85891ddd7fe6ad8030e20422da11497e5\ efe8d88db4f96479fd0b16f3703dca8946d944979a3454bb8155d8dbdd3a765584148771967d02f798d157b6a1\ 59e10461bc83d8ec9e55b557614c35d75b391c0c9d04aefe96cab5078bd3a13d5618ca219640c68919f1fefea9\ a3d1e47a3fcbc8c19de2210708fd96fed608648d183fd4c1177d803a49f7d276f940aeef6feaffded75f8e03ce\ 33df996eeb67ac6c0bec62d821bfce22d9a30baa6f7f4963eb4eaa91707ba1b12fd6f3e04f75cfea4dc39c6488\ d72e86c36ba981115f42300b97a7caa427023f16c4f66213cf0c18f04cb6aa66e4830cc7040b3103e27c2e800a\ 0bce21b653566628a5bb8b0becb80b441801f31aa100fb4539cf7e4d6d68815a666c11c6cf4ac97878c551c043\ 3750e9ab6fdeb65765ae3ece107302baf12b3086988bf4d0b37206bde4041cc7c4fa79d38170719e92c052187e\ e810ed1b2b425c081512c7ee6ea722c413215229ebaecc207fb1126644e66dea7e0139682e90f91c71b579cd86\ b91211305fe40770c3176e35b783732c2d74c8aa1a09da66c4f34dfa1f9fd35662c5c3d1f82eeb37498b121357\ e73ed7eea79adeab91001b3c63b1f75aa82793cd1a2b39e1bb09ecf5c6522ccc46652d831abe3ad1f9bc301df5\ 2c646068fd97c0402a29caa4ea3f4de8e5fb8a4d537d45d685f87d05d95f7ba40fbb6a919e93b44fb78b9c80ea\ 6c0a75b4dff2f73844bf4f7172907d8165f606a47821da925eda50af0ce44be22fa2b36d56e1d1698a8#6074", Greater, ); // - s == Limb::WIDTH in round_helper_2 // - n == 0 first time in round_helper_2 test( "2.169542166817986625468879014599175406350620737442480370882139687492174119453066131804433\ 632496405940270655469169364935548092764516132338564210201385531365409396738163453793191332\ 174443470862749001312126324808896288354477512722829484994475343567852816045883088813362218\ 109536965926916816038009290804934132950340684582117875938116310656669280480683072639988319\ 858148103369026349100099758130382359401952836454392007054797540845974323496094771400665868\ 125503436816661354237720713751777833086011158065863046075212704099660843597053397398549954\ 8348685976904925033580113969653312280822082757679509546197165e-14", "0x6.1b51e41e16de577dd7b5a3a6222357b305d4e7313b1d47721ebe3d4275ef95b0d98ad997627ec7acc76f5\ d426b7c5a9333cbc0dec080499093952901e541880379e2fdf874d1d931d1243e2b2ab072c0772ce94734ae65d\ ff7afda628d44635b3fba75efa9bd2c10d8bdcb3a61a8b6a7697f598758d80bd808f17f8351b1761850fd75cc1\ 9f86409ac25dd27dd0ce7c26478dae9d50aff0210dc4fa18674fd87aa017255dabd141e1289a7e734e21577610\ bf92b6ce4fe21881cc5209081e0536f0aeb1dcf6e288feeed183095b510c09e50c432ef280e742528c0c4dd6d2\ 5e65c8b6d19c28914472a930aae1ad7fac96f6442134ee95f3bd8E-12#1993", "301180.0045246172416425721655892719573457356766058630317841133942315022590404351104810586\ 213517139802439747677458029756555586634849124296886483237621871644459126081050822492233083\ 707945595254133438910359944302659214080172068073620764660184379004827633051943726032292014\ 225559234820452819113849827971319776547835482966443724022128469656550054145203573809984759\ 336239968661049955088445384576034864711412948863817402256055440443111246220943775270251981\ 245519547063921282094595332683031347213016637666849460902039610984880445147686118036204784\ 051476863264255027838976527798504452504598268980029728768388473210371246534136227460265249\ 86471927", "0x4987c.0128867b146bf9c05b0bb90d2c480c2b610c9c19a0a03f58f0d0aefa84d41a94dbc0c1206d80eab12\ 18d0f5e72e0b72a6f063fe0f604b1eedcc3760c7f60b2aa6e35735292ea939fa59fc7da94b3e86d7bbba5f8ef6\ 8136a9a4c5d98df58e4ad215fee20274cd18a324d8b66b0119d3cf93efacf51659a9814222c8f9b53fe6356392\ e2b27f1ee07621f888214936f129248d805ae614b37cae5b83f51b2be167dc62ef96c1322204921369dc6c7475\ c195aa735676f467be6a45d895b6b08fba56a7919ac216a6dc76cf9f5c3184a2ffa7b1bc3d8760c250d651afca\ 18aa90ff70ee4532482978816617fb02f0de87b2abd54886d1c7c16d62550d5fd8a4abb55b0c4ebb8c#2111", Nearest, "7.203473451839519375659920800256968930150281137907207966420457324091308743561158996788387\ 290694159461823269997598092194316979651412090098764718003237064733792291895103263169730962\ 123418174759909091404064508319172962888992299461557410206033700688023479037478761668781891\ 761303156472454780198812373188616203221872171676002219543916314587725944225532571475160352\ 707938049990541748698746656039607206067984173221685967465441429896808706646646536972493098\ 282122681082474772608417991249668805473092287771115239878542545454824251859441724816281902\ 754574769925885897122660854445163455617440019293712118274988718965330199709067927675503187\ 81705947e-20", "0x1.542ca6851865ac89e311ac1608cac34c9fe637305345b739b624981a50028d6f60e7fd803167413e1285b\ 796e7a5ed37e1cb19125606ca9d15a697c9c497b14455aae6477ad96ffa4f216a14878a9802e8350d104f0b9d8\ cd86ff511d7efbd74d40104b107a9d7f33d0e8894d3b157e46b7fd4e6386f823e75ae0efa9be33aac3e252d7d2\ 411f8e2afd3773f3914778d26a6b76f5569fd822db5a66db515e3cdd6699301b71cbdb73f07c24fb20d0c66059\ fe1f236a4656c3f508e25958bdef5ca863d7950c5740d7849b46bde7e1a38b797265dedd7d4dfdaee7bcb69dce\ 887bddd7a7bbd45a6561cfad8cd840e7d95599a81bb274cc02a161439f7280459a15c9865ad5b658ed8E-16\ #2111", Less, ); // - n != 0 && tmp != 0 && tmp == mask in round_helper_2 // - s != Limb::WIDTH second time in round_helper_2 test( "7.967842945782984973942186035477141750978306951371418866981413625233901049016799636923049\ 043510064598367854094347269064974737243308027061881036076018766384961823690368428913274793\ 537e-19", "0xe.b2b51b3ba9b3fa4c3c91f60bbe2f30efe9403d1c1ed1fa2688711592167dc11f579d747f20609a0e8704a\ 660072ec620d514ab31d0845381f10e96f76ac41c97c2a7b53849757dc846fdeE-16#599", "4.290314881292277334232122993869736164625712811477787127079554140127474408529492187148865\ 860241941174878594521708166855716060386064937593774872957730026516247807479269506509835640\ 014575725456051856772978910171974972671741113731811243859146099959299700690748160884209812\ 639693266282036645473254451466381125403186024743001502094065938286200460441378264282871237\ 445194601993083290951436490295842815606015494575193282638997440331311694865085507331318327\ 437042408938144577985735854973264189023250983346696190654635795462654945584732891184659237\ 746883228154089313101793763347136552004708447204474905674167880735273390965084667673056531\ 378593414825374458582134295243495148718875340371312206621884585775967428131940924035968587\ 526069447315202760539547246403295371510536211424729007907823710381420209210303664575050843\ 559776729235120592670693730372232402604761499044741741752247404544150954858075273585139895\ 643242778698674255451287458469387850297372316908957826221759549123594364155475346755476293\ 552962991845182999537688763267208310118481794778770137863789646906639637779481228371710954\ 980900001879766864929946144490423459237336070803276511200399191948305713293997532907864745\ 24489311444825214442690999e-14", "0xc.137f67f6b60895b6164f36c36d5b134858a21d493d7d49584a1811d76bd92f10b6d0aa0bea20843896e0f\ d0d2e93957b024a1b5e7101d0f679c3dcc134107c20f0664acbfdf6bafac9013ae41ce018c62b6cf36043f13a8\ 1c35291946c79569662de17adff4ec759b1ccbe440675ef95167b0d5a5481ea6e7a6b998233e094436c8eeaefb\ e21fa0f9c24aad8d11f378034d73a5daec0111cef1b0b8426dd5df78555318d44c992e40ad5fa98171908c4019\ 636becfe749a93747c965c11e84b68df48e887e933449d42c1ec5c2d6a7658e91f6d68333ddfde5719ca117d72\ dadec43975eb0b6b6a076c4ada32d70b0e93250cf5e8836b11ad6a8b13a4a957de6221168782640f2313ca3716\ 3e4da0decaee000e5824d53c71d0a36a55295f8ad1c7a86eb35eab709891d1a6ac96a10448e0e307c7d6742d8d\ 0617a3e21978394d0393bc9be8e32ff2d87e85ae44c3a76ac79752bcca4927ca5dc6dcfc4db10793dc0cfc2161\ 24fdf30070db19fd8a89982adf45a408e08499b77cf25011c54cf9270bf491a2186e1a5fad26087812cc3c2446\ ca7e5457d75f66fe9e736ad07c6b1fe4b20eaf1f073d454f371f659f7402d24e6666c8e212ddccf50c22209ca5\ 7651a266ecba0559cacf587691f7f7df3389d9968023d71b412cc20516c9b1d00f1392474c6683bd0fd6c6dc7a\ 705d88E-12#3966", Nearest, "0.000018571697337476093645597974800042221391343383471511758884717235995391699590980821846\ 925772010524277797520625056343676345716562878283777572676679678398279369283853673423775272\ 117775978501001731220831012727542639628984101788862199591237806493805996059161201835253203\ 204357442043212398495525692960904672132359565047969002327766123188917268873022220728326927\ 266813579456518458545345939557868848624450974456390610446369728959726525392113471132021539\ 038960803550352390128253151270734177749632737865390247648212171456318006032507634424453843\ 795159031314496937836591202252458892414236797451738560115150573320872948069964155298984838\ 456270978739037104719669912968807593222214861520588395175617611807975267322946381339673265\ 479787948188151606275111200784895864164305724683464061829109671306661764726602634895903888\ 287506327660181397735839535481997625450956961420572462126703944263526095290954835871182404\ 868513321447417245068813964246287015709186652991049553947407472630595976266674750290084010\ 397575525528176465754260767775733418629588880876176812207672741703984898153224615968196909\ 775917982890995046346113085550279268258183711136206964350043642244181512435164664671221839\ 6370838653686792137638621224928", "0x0.00013794d52b8b1e96ced9de16a585696e655c080cbd5da8030eef302763f4138b28d7261786b8ff50bc6\ 9d0a5f06f20dad7ee2a65fae9caeeaee187ea820eae6fd4c8a673a92def1c9a165c1aeec8807ddb464eac6f550\ 6dbe6d6e3a21a035c4472d414f4887b05775ede2ad98b9b380b663c0929394c811648792ef20f0756b6bad50de\ 099fda3dd792ae5616df8837945c3cb4cd833fb9bf0db07243887c0a8fedba7030c428024be8572bca9398f563\ b2a661574fd7faf130ac3d404dbe94b7e0ca06f440962616e1879d4f15895a10229f04969c26dbb9a1b733f734\ fd2be1c88c7b20af178cd1d3fa116fba33a435b040155b5f5f28f0668b798810c2acb1faf0581e46cc71e9b07f\ c9e4ebcd8a96a7d7d318d649e4468baa2ce2cdf9b1adf74f6a6b8b95a3eed5991934327ddfeb243e80db0c230e\ d593df31dce1201e64430a27d39e6760dcf2086c1cb86bfb4e9211f18940b72d1a492a5b9109c0fdf4f5fa9fce\ 9e0ec199756ee5f8e69ba7ded6b7507facbc46df62adaa4546b3113a80e7ea40bab782194bfd006099f6a79bb8\ 19aad950497cae351fdc370756b86b3188e5c2cf71ed56fdb3683c9cc38facff80b0f2076d0f3b3a8605ca24d2\ c8b6301601e23b50ea0940f7ba05f92ddd4a644cca6e420d6bfcd06caab9c695ba67b857bc57e1000b5935d0a8\ 79821217280#3966", Less, ); // - rm == Nearest && shift == 0 first time in div_float_significands_general test( "3.494003589335061592114850452482839587826456952956376068177291318828682713177358264760784\ 874304744009907216335963217912223351596098015455390432300579562836209635380394751634810606\ 195414389573610568068623776330707730813932586805062287543490729241818555718410383777926489\ 343323917900958772688451527795643412381235039158654803215405274640835172391547486080681691\ 827169629800140882523056966137099117587677259077996268577162491409610597231997851472454718\ 312803304389117924206548413988545367622912505139619073824279361037770537659001099972259551\ 367613373821227769095845567435994753397767332318253172120529133505790353120177308303588487\ 770407205738279213609665027613843515660027068482463985188375646552261141849026408186728824\ 80307838589616979262426550353243006148083216398932181e-12", "0x3.d7797e014d587584d7875beed50257a2555726437bf03fdebac1110cae2c4b64f09f9a338bf2ca8b1fcf5\ e0128d7f387a40893706e25c04e65fdd316e3fc348d2478632d632bae209325b6c681dde52405cd7f8d9707d7f\ 5d6de0abb73e130c41c21c4537ce41381fc43788187dab4fa280fa46503f1890d663ca441f49a6a7e2b712e710\ 4c826535fdf1c8ae0282d162e3d128a982e44f67c6104624863e7f3c2c60833df521e5bab88feddd4843e4b50b\ 81ba442bc612787ad38f640412f6cff81df9793590dfa6a0debdd7f2f6de7a089fc50d597d700dbeeecfc9d795\ ceb9a69d05db5c520717ddd7e73fabaea4e2cb06b1e1874b8b541dfca2083cb277e4d1bbefa48c0a427afea0a5\ 87cd5085c2ba28c1cad42a97be72844e851abf698ac844915e9f5ac4af406a2c354aa055f3c0994b7932d1bdb7\ b4999768f776148E-10#2560", "8.388557903692744678886673027706512178020882171440574341138664910770681048759242342335520\ 689291884051853125391850946672822384185374426629671262437149651332606541726962233658521936\ 440197380293004778812876511148916284206096731251130678261803308370362817534297504354768207\ 175302739282372189357904919163400327254111204148827422042723518774290057028465296755126014\ 371014512774422430414368313070504306047237723842986944935010614200247398223867859750512432\ 528263508555538801970472032683504663202558316239308702078808690323956381650112536926354687\ 819619269837340011822483859668579241157516055938780563664184620140501025776680716962470155\ 2e-35", "0x6.f80c88bef08546fc8a21f0f2152ee0612eebad2635acbe0d49ce7179b387d0719cd657923976ec2796026\ 5e330a5e71c0cd8417c2cf919556130f9b353cdf2435349f846c895ede372648bccd9c217f1bb7c3e4197c1806\ c4744c8a05ddf4f67946a4972f056d84028e7023d956a95b2ff067c093002267f7015fecb9ca5ed8f58dde48d7\ 4510e965bfa6478370f4e71e5a240dabdd9a4d6e000d4af93eea8510c6c4e095290bce062925fd9a7245caff37\ 8b7be01d3b94b56154cbeb98c26f78338a98e416fa9acc3bd12c4953b058efdcdbe56335f952208a15166babaa\ 698da808f96df97655d3f5cdb4768e6370755a01515d4ad54f625432fc742e9121b7cce4fdb08E-29#2088", Nearest, "41652017300815899948547.94831484736938823572318695739742204735159366375620848030675947597\ 937407214848121136435440017047965685656179645007771422864559798518659544278806178160023554\ 020245599674536568425190916908552958650848910192845046055088066614557330847090320384899468\ 575304634050066348271499359839369427201019441174516439045175255034723132436872248790761539\ 506937527488424041602486298663492699846695028977559705152038731125314966620233281505474337\ 677248672173837029868825260085661764008715204976773612281854954844288452423998027475082981\ 779489389492756600188312999400831430516184077432877044587246391185262444911853744883006186\ 684049728461939709785134255700251964580618924591175050653894151676243677123400686218961075\ 24208104943935667403367286485079704207117845193523456", "0x8d1f5db9d3f145a7603.f2c4c307c343da5b63ef331aa97f5e951921921a937336258bc4ab65fdf9d715d36\ ef6755e61dd29859283e35c618271ec076a196c3ddb06ce536bafe52ad10a521ebfdcda2a3839fce6eadd33d87\ eba1d25c5eacfa66f0af4f1ce568be4792717319611eb807fe7fc0d855f2cf1b099f908a269208b3ee36d33e71\ 3912e0557515bf16566f8cc4c8c45fd6bb2ced1b3d3f27c9b272c6e5dfaacdd66335f658951d70cd7b3190aac8\ b90d7e564b5c0ac68a04f4681a552c50de11c466e3ac1230d426fdc851e7d5705e73d7ad30a82c2febb82c46b4\ 93762b8d7c80e514c1fe29a64d4189fc176b72bb816f1223676b93d38dc33a2fd578eaf5fa512468b21e723d6c\ d5595dac5bfd84c94e4826fc5b9aff74dec22c3cb43d7970a1359eb2642295a920a70da20a166db400602f0f4f\ 2aee9255f2251c#2560", Greater, ); // - !round_helper_2 in div_float_significands_general test( "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ 1249731874464215297923136674027554116062077582682832144200801849365234375", "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000038180485e-31", "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000001ffffffeE-26#2567", Nearest, "10141204801825835211973625643007.99999999999999999999999999999999999999999999859870153567\ 518292907627041671008386871973805812348422824293171611020891731413939851336181163787841796\ 874999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999999999018341217", "0x7fffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffe0000002#2567", Less, ); // - x_exp < Float::MIN_EXPONENT not special && sign && rm == Ceiling | Up test( "too_small", "0x1.0E-268435456#1", "3.0", "0x3.0#2", Ceiling, "too_small", "0x1.0E-268435456#2", Greater, ); // - x_exp < Float::MIN_EXPONENT not special && !sign && rm == Floor | Up test( "too_small", "0x1.0E-268435456#1", "-3.0", "-0x3.0#2", Floor, "-too_small", "-0x1.0E-268435456#2", Less, ); // - exp_diff + 2 < Float::MIN_EXPONENT && sign && rm == Ceiling | Up test( "too_small", "0x1.0E-268435456#1", "too_big", "0x6.0E+268435455#2", Ceiling, "too_small", "0x1.0E-268435456#2", Greater, ); // - exp_diff + 2 < Float::MIN_EXPONENT && !sign && rm == Floor | Up test( "too_small", "0x1.0E-268435456#1", "-too_big", "-0x6.0E+268435455#2", Floor, "-too_small", "-0x1.0E-268435456#2", Less, ); // - x_exp > Float::MAX_EXPONENT && sign && rm == Floor | Down test( "too_big", "0x6.0E+268435455#2", "0.8", "0x0.c#2", Floor, "too_big", "0x6.0E+268435455#2", Less, ); // - x_exp > Float::MAX_EXPONENT && !sign && rm == Ceiling | Down test( "too_big", "0x6.0E+268435455#2", "-0.8", "-0x0.c#2", Ceiling, "-too_big", "-0x6.0E+268435455#2", Greater, ); // - exp_diff > Float::MAX_EXPONENT && sign && Floor | Down test( "too_big", "0x6.0E+268435455#2", "too_small", "0x1.8E-268435456#2", Floor, "too_big", "0x6.0E+268435455#2", Less, ); // - exp_diff > Float::MAX_EXPONENT && !sign && Floor | Down test( "too_big", "0x6.0E+268435455#2", "-too_small", "-0x1.8E-268435456#2", Ceiling, "-too_big", "-0x6.0E+268435455#2", Greater, ); } #[test] fn div_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::ONE.div_round(THREE, Exact)); assert_panic!(Float::ONE.div_round_val_ref(&THREE, Exact)); assert_panic!(Float::ONE.div_round_ref_val(THREE, Exact)); assert_panic!(Float::ONE.div_round_ref_ref(&THREE, Exact)); assert_panic!({ let mut x = Float::ONE; x.div_round_assign(THREE, Exact) }); assert_panic!({ let mut x = Float::ONE; x.div_round_assign_ref(&THREE, Exact) }); } #[test] fn test_div_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = x.clone().div_prec_round(y.clone(), prec, rm); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); assert_eq!(o, o_out); let (quotient_alt, o_alt) = x.clone().div_prec_round_val_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_prec_round_ref_val(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_prec_round_assign(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_prec_round_assign_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o_out); let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "1.0", "0x1.0#1", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Floor, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Down, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Up, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, Exact, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Floor, "0.00812", "0x0.0214#10", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Ceiling, "0.00813", "0x0.0215#10", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Down, "0.00812", "0x0.0214#10", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Up, "0.00813", "0x0.0215#10", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Nearest, "0.00813", "0x0.0215#10", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Floor, "-0.02", "-0x0.04#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Ceiling, "-0.008", "-0x0.02#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Down, "-0.008", "-0x0.02#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Up, "-0.02", "-0x0.04#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Nearest, "-0.008", "-0x0.02#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Floor, "-0.00813", "-0x0.0215#10", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Ceiling, "-0.00812", "-0x0.0214#10", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Down, "-0.00812", "-0x0.0214#10", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Up, "-0.00813", "-0x0.0215#10", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Nearest, "-0.00813", "-0x0.0215#10", Less, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Exact, "0.5", "0x0.8#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Floor, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Ceiling, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Down, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Up, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Nearest, "0.5", "0x0.800#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Exact, "0.5", "0x0.800#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "0.2", "0x0.4#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "0.5", "0x0.8#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "0.4497", "0x0.732#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "0.4502", "0x0.734#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "0.4497", "0x0.732#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "0.4502", "0x0.734#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "0.4502", "0x0.734#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-0.2", "-0x0.4#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-0.2", "-0x0.4#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-0.4502", "-0x0.734#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-0.4497", "-0x0.732#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-0.4497", "-0x0.732#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-0.4502", "-0x0.734#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-0.4502", "-0x0.734#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-0.2", "-0x0.4#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-0.2", "-0x0.4#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-0.5", "-0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-0.5", "-0x0.8#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "-0.4502", "-0x0.734#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "-0.4497", "-0x0.732#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "-0.4497", "-0x0.732#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "-0.4502", "-0x0.734#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "-0.4502", "-0x0.734#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "0.2", "0x0.4#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "0.5", "0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "0.4497", "0x0.732#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "0.4502", "0x0.734#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "0.4497", "0x0.732#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "0.4502", "0x0.734#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "0.4502", "0x0.734#10", Greater, ); // - (rm == Ceiling || rm == Up) && overflow in div_float_significands_long_by_short test( "2.493205886061172926", "0x2.7e42bdaed3d31b2#61", "7.459893537e20", "0x2.870ae94cE+17#33", 5, Ceiling, "3.4e-21", "0x1.0E-17#5", Greater, ); // - rm != Nearest third time in div_float_significands_genera test( "3.7563361266e88", "0x4.b87f4dfa0E+73#36", "6.769173652614128677797571270436826716e-13", "0xb.e8909656207637d3379c02628519c4E-11#123", 63, Ceiling, "5.549179736559369991e100", "0x6.57b76abe8193e56E+83#63", Greater, ); // - (rm == Up || rm == Ceiling) && (round_bit != 0 || sticky != 0) && carry in // div_float_significands_general test( "4.70916604581e-30", "0x5.f8363584bE-25#39", "341290809831481093.63402342431195212374059", "0x4bc822eed1c5f05.a24f5bf051591756f951#139", 1, Ceiling, "2.0e-47", "0x2.0E-39#1", Greater, ); // - rm != Nearest && ((rm != Ceiling && rm != Up) || inex == 0) && (inex == 0 || rm != Exact) // in div_float_significands_general // - goto_sub_1_ulp in div_float_significands_general test( "6265419941341407687.894108147333", "0x56f33e3db44da9c7.e4e44583e2#102", "28506201793260972591.2041505871822190859316631273737217979877602592305648246097", "0x18b9a5f7fa6ec6a2f.3443367f6825dd51709bc60beed373653861dd1a1c6c0422#256", 63, Floor, "0.2197914680735399977", "0x0.384440ef50d090080#63", Less, ); // - rm == Floor || rm == Down fourth time in div_float_significands_general // - (rm == Floor || rm == Down) fourth time && shift != 0 in div_float_significands_general test( "1.274876025e31", "0xa.0e9775E+25#28", "7.104011072486714881105976022274735719942619445087760266603169705559e-82", "0x5.6412fa517e8e5c9e2826903dbe9c6b4f020acbf4d07a5f83b6e4008E-68#222", 126, Floor, "1.79458620199896394199805694868744557483e112", "0x1.dd946a676df629632baf4759d5af1088E+93#126", Less, ); // - rm == Ceiling || rm == Up fourth time in div_float_significands_general // - (rm == Ceiling || rm == Up) fourth time && shift != 0 in div_float_significands_general test( "1.766000056026770292793619415e30", "0x1.64a410213aff5d6e713e280E+25#90", "3.8777897715163284337835091275987988e-9", "0x1.0a7acc91ecf72f35cdef4a25d008eE-7#116", 63, Ceiling, "4.554140786585790019e38", "0x1.569d8fa574bc1b5cE+32#63", Greater, ); // - (rm == Floor || rm == Down) fourth time && shift == 0 in div_float_significands_general test( "2.6837e8", "0xf.ffE+6#12", "33554432.0156249999999999", "0x2000000.03fffffffffff8#79", 64, Floor, "7.9980468712756191975", "0x7.ff7ffff001000018#64", Less, ); // - (rm == Ceiling || rm == Up) fourth time && shift == 0 in div_float_significands_general test( "0.00341799855229", "0x0.00e0007ffff8#37", "9444877080927366283263.8", "0x20001ffffffffffffff.c#76", 64, Ceiling, "3.6188915144233536057e-25", "0x6.fffd0002bffd4008E-21#64", Greater, ); // - cmp_s_r == Equal && shift == 0 in div_float_significands_general test( "6699743.0549682103909956055738813882394392365647386167825", "0x663adf.0e126589f2efed5e335a996cf4ea2b00000000000#186", "2.7716996157956048532084742e-18", "0x3.320fb3ad0fa6bc833b14E-15#82", 64, Exact, "2.4171966604126677691e24", "0x1.ffdc7e57cc8990bcE+20#64", Equal, ); // - (32-bit) len == 0 in sub_helper test( "30600.896887617100679", "0x7788.e59a6d47a2818#64", "2502994226528294594711254131620329726924950421806.930251136099954006921970343593452748426\ 707752157088293012113325450782206798004004382505336607707515733277073230960543511755657896\ 564954610313805343294199781328288665758818764110630501992193446364134574345717105834955361\ 7609386520869921223421139170307521302744186647065523683732731123797753054753663", "0x1b66e24958fe115307da9ef9c4f815e31129d412e.ee24f03e9dbbd6cdaa800176f4f7a592b62d2ecb1428c\ 19779d86494af5a809600728d36c503347da5f0182f00935e63a628c673a55a1e67334c368efde2d7a0fccbc62\ 0edc630bdd9fafc83b3088a3186480eefe67a7c19b91b866c079c0716d7b844259f598eeb31d6c0baf035c6bc4\ 6b11b5efad4f3ae582c7740#1151", 32, Ceiling, "1.2225716132e-44", "0x4.5cbe7760E-37#32", Greater, ); // - rm == Up || rm == Ceiling && carry in div_float_significands_general test( "2.454546732648863276547885977493137821487607756249724782555774558593552627360857928230048\ 942018665976138591785782565939256583959305212359451403757412054481726126552732229930964269\ 470905492198653519153594970703124999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 995761114627674791277020932519574469505017610728137410250159407014720169738824650046673749\ 059339474479527195633303962573451642912661719349979993453218111358455268175773121496346851\ 580476856645369527796626919786850732045813122714395701160155300736782415936562761674226693\ 028929972451809327089060718204876263534635026488050357020524924317959135992439056643999723\ 656960561739673936265216544476386688997222734833105296938067057205929214479610015975275932\ 718619380628277147130611593861916399934357066581330096178050556305086195135562253719174061\ 496425118601354010153670564319137109364713055282273218494183562236985834389291157056469689\ 9828846337814e-91", "0x7.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000E-76#4517", "0.015625000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000771048757510508716764719334683019132168263108153512725551350734409293871565\ 903519457201213361797567020084883497703807999422859208123581192925346248118136084792628172\ 988363113468168413497993606331107182531734570308778128025953654408272649725745457159283262\ 0134958821588759455527143", "0x0.0400000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffff\ fffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000#3655", 2337, Ceiling, "1.570909908895272496990647025595608205752068963999823860835695717499873681510949074067231\ 322891946224728698742900842201124213733955335910048898404743714868304720993748627155817132\ 46137951500713825225830078125e-89", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000E-74#2337", Greater, ); } #[test] fn div_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).div_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).div_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).div_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).div_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.div_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.div_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(Float::ONE.div_prec_round(THREE, 1, Exact)); assert_panic!(Float::ONE.div_prec_round_val_ref(&THREE, 1, Exact)); assert_panic!(Float::ONE.div_prec_round_ref_val(THREE, 1, Exact)); assert_panic!(Float::ONE.div_prec_round_ref_ref(&THREE, 1, Exact)); assert_panic!({ let mut x = Float::ONE; x.div_prec_round_assign(THREE, 1, Exact) }); assert_panic!({ let mut x = Float::ONE; x.div_prec_round_assign_ref(&THREE, 1, Exact) }); } #[test] fn test_div_rational() { let test = |s, s_hex, t, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let mut quotient_alt = x.clone(); quotient_alt /= y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let mut quotient_alt = x.clone(); quotient_alt /= &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_div_rational( &rug::Float::exact_from(&x), &rug::Rational::from(&y) ))), ComparableFloatRef("ient) ); let quotient_alt = div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if x.is_normal() { let quotient_alt = div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } }; test("NaN", "NaN", "123", "NaN", "NaN"); test("Infinity", "Infinity", "123", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "123", "-Infinity", "-Infinity"); test("NaN", "NaN", "0", "NaN", "NaN"); test("Infinity", "Infinity", "0", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "0", "-Infinity", "-Infinity"); test("0.0", "0x0.0", "0", "NaN", "NaN"); test("-0.0", "-0x0.0", "0", "NaN", "NaN"); test("0.0", "0x0.0", "123", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "123", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "-123", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-123", "0.0", "0x0.0"); test("0.0", "0x0.0", "1/3", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "1/3", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "1", "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", "0", "Infinity", "Infinity"); test("-123.0", "-0x7b.0#7", "0", "-Infinity", "-Infinity"); test("1.0", "0x1.0#1", "2", "0.5", "0x0.8#1"); test("1.0", "0x1.0#2", "2", "0.5", "0x0.8#2"); test("1.0", "0x1.000#10", "2", "0.5", "0x0.800#10"); test("1.0", "0x1.000#10", "3/2", "0.667", "0x0.aac#10"); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", "0.666666666666666666666666666667", "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", ); test("3.0", "0x3.0#2", "2", "1.5", "0x1.8#2"); test("3.0", "0x3.00#10", "2", "1.5", "0x1.800#10"); test("3.0", "0x3.00#10", "3/2", "2.0", "0x2.00#10"); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", "2.0", "0x2.0000000000000000000000000#100", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", "2.0943951023931953", "0x2.182a4705ae6ca#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", "-2.0943951023931953", "-0x2.182a4705ae6ca#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", "-2.0943951023931953", "-0x2.182a4705ae6ca#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", "2.0943951023931953", "0x2.182a4705ae6ca#53", ); // n and d both powers of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "1", "too_big", "0x4.0E+268435455#1", ); // - only n a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "2/3", "Infinity", "Infinity", ); // - only d a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "3", "too_big", "0x1.0E+268435455#1", ); // - neither n nor d a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "5/3", "too_big", "0x2.0E+268435455#1", ); } #[test] fn test_div_rational_prec() { let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (quotient, o) = x.clone().div_rational_prec(y.clone(), prec); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = x.clone().div_rational_prec_val_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_ref_val(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_ref_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_prec_assign(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_prec_assign_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } let (rug_quotient, rug_o) = rug_div_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "0", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", "123", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", "1", 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", "1", 10, "123.0", "0x7b.0#10", Equal); test("123.0", "0x7b.0#7", "0", 1, "Infinity", "Infinity", Equal); test( "-123.0", "-0x7b.0#7", "0", 1, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 10, "-Infinity", "-Infinity", Equal, ); test("1.0", "0x1.0#1", "2", 1, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 10, "0.5", "0x0.800#10", Equal); test("1.0", "0x1.000#10", "3/2", 1, "0.5", "0x0.8#1", Less); test( "1.0", "0x1.000#10", "3/2", 10, "0.667", "0x0.aac#10", Greater, ); test("3.0", "0x3.0#2", "2", 1, "2.0", "0x2.0#1", Greater); test("3.0", "0x3.0#2", "2", 10, "1.5", "0x1.800#10", Equal); test("3.0", "0x3.00#10", "3/2", 1, "2.0", "0x2.0#1", Equal); test("3.0", "0x3.00#10", "3/2", 10, "2.0", "0x2.00#10", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, "2.0", "0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, "2.094", "0x2.18#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, "-2.0", "-0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, "-2.0", "-0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, "2.0", "0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, "2.094", "0x2.18#10", Less, ); } #[test] fn div_rational_prec_fail() { assert_panic!(Float::NAN.div_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::NAN.div_rational_prec_val_ref(&Rational::ZERO, 0)); assert_panic!(Float::NAN.div_rational_prec_ref_val(Rational::ZERO, 0)); assert_panic!(Float::NAN.div_rational_prec_ref_ref(&Rational::ZERO, 0)); assert_panic!({ let mut x = Float::NAN; x.div_rational_prec_assign(Rational::ZERO, 0) }); assert_panic!({ let mut x = Float::NAN; x.div_rational_prec_assign_ref(&Rational::ZERO, 0) }); } #[test] fn test_div_rational_round() { let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (quotient, o) = x.clone().div_rational_round(y.clone(), rm); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = x.clone().div_rational_round_val_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_round_ref_val(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_round_ref_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_round_assign(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_round_assign_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); } let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } }; test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Exact, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Exact, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", "123", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Floor, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Ceiling, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Down, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Up, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Nearest, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Exact, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Exact, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Exact, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", "1", Floor, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "1", Ceiling, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "1", Down, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "1", Up, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "1", Nearest, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "1", Exact, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", Down, "Infinity", "Infinity", Equal, ); test("123.0", "0x7b.0#7", "0", Up, "Infinity", "Infinity", Equal); test( "123.0", "0x7b.0#7", "0", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", Exact, "Infinity", "Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Down, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Up, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", Exact, "-Infinity", "-Infinity", Equal, ); test("1.0", "0x1.0#1", "2", Floor, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", Ceiling, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", Down, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", Up, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", Nearest, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", Exact, "0.5", "0x0.8#1", Equal); test( "1.0", "0x1.000#10", "3/2", Floor, "0.666", "0x0.aa8#10", Less, ); test( "1.0", "0x1.000#10", "3/2", Ceiling, "0.667", "0x0.aac#10", Greater, ); test( "1.0", "0x1.000#10", "3/2", Down, "0.666", "0x0.aa8#10", Less, ); test( "1.0", "0x1.000#10", "3/2", Up, "0.667", "0x0.aac#10", Greater, ); test( "1.0", "0x1.000#10", "3/2", Nearest, "0.667", "0x0.aac#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", Floor, "0.666666666666666666666666666666", "0x0.aaaaaaaaaaaaaaaaaaaaaaaaa#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", Ceiling, "0.666666666666666666666666666667", "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", Down, "0.666666666666666666666666666666", "0x0.aaaaaaaaaaaaaaaaaaaaaaaaa#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", Up, "0.666666666666666666666666666667", "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "3/2", Nearest, "0.666666666666666666666666666667", "0x0.aaaaaaaaaaaaaaaaaaaaaaaab#100", Greater, ); test("3.0", "0x3.0#2", "2", Floor, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.0#2", "2", Ceiling, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.0#2", "2", Down, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.0#2", "2", Up, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.0#2", "2", Nearest, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.0#2", "2", Exact, "1.5", "0x1.8#2", Equal); test("3.0", "0x3.00#10", "3/2", Floor, "2.0", "0x2.00#10", Equal); test( "3.0", "0x3.00#10", "3/2", Ceiling, "2.0", "0x2.00#10", Equal, ); test("3.0", "0x3.00#10", "3/2", Down, "2.0", "0x2.00#10", Equal); test("3.0", "0x3.00#10", "3/2", Up, "2.0", "0x2.00#10", Equal); test( "3.0", "0x3.00#10", "3/2", Nearest, "2.0", "0x2.00#10", Equal, ); test("3.0", "0x3.00#10", "3/2", Exact, "2.0", "0x2.00#10", Equal); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Floor, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Ceiling, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Down, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Up, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Nearest, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", Exact, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", Floor, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", Ceiling, "2.0943951023931957", "0x2.182a4705ae6cc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", Down, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", Up, "2.0943951023931957", "0x2.182a4705ae6cc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", Nearest, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", Floor, "-2.0943951023931957", "-0x2.182a4705ae6cc#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", Ceiling, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", Down, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", Up, "-2.0943951023931957", "-0x2.182a4705ae6cc#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", Nearest, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", Floor, "-2.0943951023931957", "-0x2.182a4705ae6cc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", Ceiling, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", Down, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", Up, "-2.0943951023931957", "-0x2.182a4705ae6cc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", Nearest, "-2.0943951023931953", "-0x2.182a4705ae6ca#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", Floor, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", Ceiling, "2.0943951023931957", "0x2.182a4705ae6cc#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", Down, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", Up, "2.0943951023931957", "0x2.182a4705ae6cc#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", Nearest, "2.0943951023931953", "0x2.182a4705ae6ca#53", Less, ); } #[test] fn div_rational_round_fail() { const THREE: Rational = Rational::const_from_unsigned(3); assert_panic!(Float::ONE.div_rational_round(THREE, Exact)); assert_panic!(Float::ONE.div_rational_round_val_ref(&THREE, Exact)); assert_panic!(Float::ONE.div_rational_round_ref_val(THREE, Exact)); assert_panic!(Float::ONE.div_rational_round_ref_ref(&THREE, Exact)); assert_panic!({ let mut x = Float::ONE; x.div_rational_round_assign(THREE, Exact) }); assert_panic!({ let mut x = Float::ONE; x.div_rational_round_assign_ref(&THREE, Exact) }); } #[test] fn test_div_rational_prec_round() { let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (quotient, o) = x.clone().div_rational_prec_round(y.clone(), prec, rm); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = x.clone().div_rational_prec_round_val_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_prec_round_assign(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.div_rational_prec_round_assign_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Exact, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "0", 1, Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", "123", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Floor, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Down, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Up, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Nearest, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Exact, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Exact, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Exact, "-0.0", "-0x0.0", Equal); test( "123.0", "0x7b.0#7", "1", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("1.0", "0x1.0#1", "2", 1, Floor, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 1, Ceiling, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 1, Down, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 1, Up, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 1, Nearest, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 1, Exact, "0.5", "0x0.8#1", Equal); test("1.0", "0x1.0#1", "2", 10, Floor, "0.5", "0x0.800#10", Equal); test( "1.0", "0x1.0#1", "2", 10, Ceiling, "0.5", "0x0.800#10", Equal, ); test("1.0", "0x1.0#1", "2", 10, Down, "0.5", "0x0.800#10", Equal); test("1.0", "0x1.0#1", "2", 10, Up, "0.5", "0x0.800#10", Equal); test( "1.0", "0x1.0#1", "2", 10, Nearest, "0.5", "0x0.800#10", Equal, ); test("1.0", "0x1.0#1", "2", 10, Exact, "0.5", "0x0.800#10", Equal); test("1.0", "0x1.000#10", "3/2", 1, Floor, "0.5", "0x0.8#1", Less); test( "1.0", "0x1.000#10", "3/2", 1, Ceiling, "1.0", "0x1.0#1", Greater, ); test("1.0", "0x1.000#10", "3/2", 1, Down, "0.5", "0x0.8#1", Less); test("1.0", "0x1.000#10", "3/2", 1, Up, "1.0", "0x1.0#1", Greater); test( "1.0", "0x1.000#10", "3/2", 1, Nearest, "0.5", "0x0.8#1", Less, ); test( "1.0", "0x1.000#10", "3/2", 10, Floor, "0.666", "0x0.aa8#10", Less, ); test( "1.0", "0x1.000#10", "3/2", 10, Ceiling, "0.667", "0x0.aac#10", Greater, ); test( "1.0", "0x1.000#10", "3/2", 10, Down, "0.666", "0x0.aa8#10", Less, ); test( "1.0", "0x1.000#10", "3/2", 10, Up, "0.667", "0x0.aac#10", Greater, ); test( "1.0", "0x1.000#10", "3/2", 10, Nearest, "0.667", "0x0.aac#10", Greater, ); test("3.0", "0x3.0#2", "2", 1, Floor, "1.0", "0x1.0#1", Less); test("3.0", "0x3.0#2", "2", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("3.0", "0x3.0#2", "2", 1, Down, "1.0", "0x1.0#1", Less); test("3.0", "0x3.0#2", "2", 1, Up, "2.0", "0x2.0#1", Greater); test("3.0", "0x3.0#2", "2", 1, Nearest, "2.0", "0x2.0#1", Greater); test("3.0", "0x3.00#10", "3/2", 1, Floor, "2.0", "0x2.0#1", Equal); test( "3.0", "0x3.00#10", "3/2", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test("3.0", "0x3.00#10", "3/2", 1, Down, "2.0", "0x2.0#1", Equal); test("3.0", "0x3.00#10", "3/2", 1, Up, "2.0", "0x2.0#1", Equal); test( "3.0", "0x3.00#10", "3/2", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test("3.0", "0x3.00#10", "3/2", 1, Exact, "2.0", "0x2.0#1", Equal); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "3/2", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 1, Nearest, "2.0", "0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, Floor, "2.094", "0x2.18#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, Ceiling, "2.098", "0x2.19#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, Down, "2.094", "0x2.18#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, Up, "2.098", "0x2.19#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3/2", 10, Nearest, "2.094", "0x2.18#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, Floor, "-4.0", "-0x4.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, Ceiling, "-2.0", "-0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, Down, "-2.0", "-0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, Up, "-4.0", "-0x4.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 1, Nearest, "-2.0", "-0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, Floor, "-2.098", "-0x2.19#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, Ceiling, "-2.094", "-0x2.18#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, Down, "-2.094", "-0x2.18#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, Up, "-2.098", "-0x2.19#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3/2", 10, Nearest, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, Floor, "-4.0", "-0x4.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, Ceiling, "-2.0", "-0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, Down, "-2.0", "-0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, Up, "-4.0", "-0x4.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 1, Nearest, "-2.0", "-0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, Floor, "-2.098", "-0x2.19#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, Ceiling, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, Down, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, Up, "-2.098", "-0x2.19#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3/2", 10, Nearest, "-2.094", "-0x2.18#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 1, Nearest, "2.0", "0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, Floor, "2.094", "0x2.18#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, Ceiling, "2.098", "0x2.19#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, Down, "2.094", "0x2.18#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, Up, "2.098", "0x2.19#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3/2", 10, Nearest, "2.094", "0x2.18#10", Less, ); } #[test] fn div_rational_prec_round_fail() { assert_panic!(Float::one_prec(1).div_rational_prec_round(Rational::ONE, 0, Exact)); assert_panic!(Float::one_prec(1).div_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).div_rational_prec_round_val_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).div_rational_prec_round_ref_val( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).div_rational_prec_round_ref_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!({ let mut x = Float::one_prec(1); x.div_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.div_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) }); } #[test] fn test_rational_div_float() { let test = |s, t, t_hex, out: &str, out_hex: &str| { let x = Rational::from_str(s).unwrap(); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); // TODO add rug comparison once https://gitlab.com/tspiteri/rug/-/issues/85 is resolved let quotient_alt = rational_div_float_prec_round_naive( x.clone(), y.clone(), y.significant_bits(), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if y.is_normal() { let quotient_alt = rational_div_float_prec_round_direct( x.clone(), y.clone(), y.significant_bits(), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } }; test("123", "NaN", "NaN", "NaN", "NaN"); test("123", "Infinity", "Infinity", "0.0", "0x0.0"); test("123", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); test("0", "NaN", "NaN", "NaN", "NaN"); test("0", "Infinity", "Infinity", "0.0", "0x0.0"); test("0", "-Infinity", "-Infinity", "-0.0", "-0x0.0"); test("0", "0.0", "0x0.0", "NaN", "NaN"); test("0", "-0.0", "-0x0.0", "NaN", "NaN"); test("123", "0.0", "0x0.0", "Infinity", "Infinity"); test("123", "-0.0", "-0x0.0", "-Infinity", "-Infinity"); test("-123", "0.0", "0x0.0", "-Infinity", "-Infinity"); test("-123", "-0.0", "-0x0.0", "Infinity", "Infinity"); test("1/3", "0.0", "0x0.0", "Infinity", "Infinity"); test("1/3", "-0.0", "-0x0.0", "-Infinity", "-Infinity"); test("-1/3", "0.0", "0x0.0", "-Infinity", "-Infinity"); test("-1/3", "-0.0", "-0x0.0", "Infinity", "Infinity"); test("1", "123.0", "0x7b.0#7", "0.0082", "0x0.0218#7"); test("0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); test("0", "-123.0", "-0x7b.0#7", "-0.0", "-0x0.0"); test("2", "1.0", "0x1.0#1", "2.0", "0x2.0#1"); test("2", "1.0", "0x1.0#2", "2.0", "0x2.0#2"); test("2", "1.0", "0x1.000#10", "2.0", "0x2.00#10"); test("3/2", "1.0", "0x1.000#10", "1.5", "0x1.800#10"); test("2", "3.0", "0x3.0#2", "0.8", "0x0.c#2"); test("2", "3.0", "0x3.00#10", "0.667", "0x0.aac#10"); test("3/2", "3.0", "0x3.00#10", "0.5", "0x0.800#10"); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", "0.47746482927568601", "0x0.7a3b2292bab310#53", ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-0.47746482927568601", "-0x0.7a3b2292bab310#53", ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", "-0.47746482927568601", "-0x0.7a3b2292bab310#53", ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0.47746482927568601", "0x0.7a3b2292bab310#53", ); test( "1/2", "too_big", "0x4.0E+268435455#1", "too_small", "0x2.0E-268435456#1", ); // - n and d both powers of 2 in mul_rational_prec_round_assign_direct test( "1", "too_big", "0x4.0E+268435455#1", "too_small", "0x4.0E-268435456#1", ); // - only n a power of 2 in mul_rational_prec_round_assign_direct test( "1/3", "too_big", "0x4.0E+268435455#1", "too_small", "0x1.0E-268435456#1", ); // - only d a power of 2 in mul_rational_prec_round_assign_direct test( "3/2", "too_big", "0x4.0E+268435455#1", "too_small", "0x8.0E-268435456#1", ); // - neither n nor d a power of 2 in mul_rational_prec_round_assign_direct test( "3/5", "too_big", "0x4.0E+268435455#1", "too_small", "0x2.0E-268435456#1", ); } #[test] fn test_rational_div_float_prec() { let test = |s, t, t_hex, prec, out: &str, out_hex: &str, o_out| { let x = Rational::from_str(s).unwrap(); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = Float::rational_div_float_prec(x.clone(), y.clone(), prec); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = Float::rational_div_float_prec_val_ref(x.clone(), &y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_val(&x, y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (rug_quotient, rug_o) = rug_rational_div_float_prec( &rug::Rational::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); }; test("123", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("123", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); test("123", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); test("0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("0", "Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); test("0", "-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); test("0", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("123", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); test("123", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); test("-123", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal); test("-123", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal); test("1/3", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); test("1/3", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); test("-1/3", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal); test("-1/3", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal); test("1", "123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less); test( "1", "123.0", "0x7b.0#7", 10, "0.00813", "0x0.0215#10", Greater, ); test("0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", 1, "-0.0", "-0x0.0", Equal); test("2", "1.0", "0x1.0#1", 1, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 10, "2.0", "0x2.00#10", Equal); test("3/2", "1.0", "0x1.000#10", 1, "2.0", "0x2.0#1", Greater); test("3/2", "1.0", "0x1.000#10", 10, "1.5", "0x1.800#10", Equal); test("2", "3.0", "0x3.0#2", 1, "0.5", "0x0.8#1", Less); test("2", "3.0", "0x3.0#2", 10, "0.667", "0x0.aac#10", Greater); test("3/2", "3.0", "0x3.00#10", 1, "0.5", "0x0.8#1", Equal); test("3/2", "3.0", "0x3.00#10", 10, "0.5", "0x0.800#10", Equal); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "0.5", "0x0.8#1", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.4775", "0x0.7a4#10", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.4775", "-0x0.7a4#10", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "-0.5", "-0x0.8#1", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "-0.4775", "-0x0.7a4#10", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "0.5", "0x0.8#1", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "0.4775", "0x0.7a4#10", Greater, ); } #[test] fn rational_div_float_prec_fail() { assert_panic!(Float::rational_div_float_prec( Rational::ZERO, Float::NAN, 0 )); assert_panic!(Float::rational_div_float_prec_val_ref( Rational::ZERO, &Float::NAN, 0 )); assert_panic!(Float::rational_div_float_prec_ref_val( &Rational::ZERO, Float::NAN, 0 )); assert_panic!(Float::rational_div_float_prec_ref_ref( &Rational::ZERO, &Float::NAN, 0 )); } #[test] fn test_rational_div_float_round() { let test = |s, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = Rational::from_str(s).unwrap(); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = Float::rational_div_float_round(x.clone(), y.clone(), rm); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = Float::rational_div_float_round_val_ref(x.clone(), &y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_val(&x, y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_ref(&x, &y, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive(x.clone(), y.clone(), y.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if y.is_normal() { let (quotient_alt, o_alt) = rational_div_float_prec_round_direct( x.clone(), y.clone(), y.significant_bits(), rm, ); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_rational_div_float_round( &rug::Rational::exact_from(&x), &rug::Float::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); } }; test("123", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("123", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("123", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("123", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("123", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test("123", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); test( "123", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal, ); test("123", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); test("123", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); test( "123", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal, ); test("123", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); test( "123", "-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal, ); test("123", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); test( "123", "-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal, ); test("0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test("0", "Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); test( "0", "-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal, ); test("0", "-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal); test("0", "-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); test( "0", "-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal, ); test("0", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test("123", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); test( "123", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test("123", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); test("123", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); test( "123", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test("123", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); test( "123", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test("123", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); test( "123", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test("-123", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal); test( "-123", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test("-123", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal); test( "-123", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test("1/3", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); test( "1/3", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test("1/3", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); test("1/3", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); test( "1/3", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test("1/3", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); test( "1/3", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test("1/3", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); test( "1/3", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test("-1/3", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal); test( "-1/3", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test("-1/3", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal); test( "-1/3", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "1", "123.0", "0x7b.0#7", Floor, "0.0081", "0x0.0210#7", Less, ); test( "1", "123.0", "0x7b.0#7", Ceiling, "0.0082", "0x0.0218#7", Greater, ); test("1", "123.0", "0x7b.0#7", Down, "0.0081", "0x0.0210#7", Less); test( "1", "123.0", "0x7b.0#7", Up, "0.0082", "0x0.0218#7", Greater, ); test( "1", "123.0", "0x7b.0#7", Nearest, "0.0082", "0x0.0218#7", Greater, ); test("0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Floor, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Ceiling, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Down, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Up, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Nearest, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", Exact, "-0.0", "-0x0.0", Equal); test("2", "1.0", "0x1.0#1", Floor, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", Ceiling, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", Down, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", Up, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", Nearest, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", Exact, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#2", Floor, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.0#2", Ceiling, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.0#2", Down, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.0#2", Up, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.0#2", Nearest, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.0#2", Exact, "2.0", "0x2.0#2", Equal); test("2", "1.0", "0x1.000#10", Floor, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.000#10", Ceiling, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.000#10", Down, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.000#10", Up, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.000#10", Nearest, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.000#10", Exact, "2.0", "0x2.00#10", Equal); test( "3/2", "1.0", "0x1.000#10", Floor, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", Ceiling, "1.5", "0x1.800#10", Equal, ); test("3/2", "1.0", "0x1.000#10", Down, "1.5", "0x1.800#10", Equal); test("3/2", "1.0", "0x1.000#10", Up, "1.5", "0x1.800#10", Equal); test( "3/2", "1.0", "0x1.000#10", Nearest, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", Exact, "1.5", "0x1.800#10", Equal, ); test("2", "3.0", "0x3.0#2", Floor, "0.5", "0x0.8#2", Less); test("2", "3.0", "0x3.0#2", Ceiling, "0.8", "0x0.c#2", Greater); test("2", "3.0", "0x3.0#2", Down, "0.5", "0x0.8#2", Less); test("2", "3.0", "0x3.0#2", Up, "0.8", "0x0.c#2", Greater); test("2", "3.0", "0x3.0#2", Nearest, "0.8", "0x0.c#2", Greater); test("2", "3.0", "0x3.00#10", Floor, "0.666", "0x0.aa8#10", Less); test( "2", "3.0", "0x3.00#10", Ceiling, "0.667", "0x0.aac#10", Greater, ); test("2", "3.0", "0x3.00#10", Down, "0.666", "0x0.aa8#10", Less); test("2", "3.0", "0x3.00#10", Up, "0.667", "0x0.aac#10", Greater); test( "2", "3.0", "0x3.00#10", Nearest, "0.667", "0x0.aac#10", Greater, ); test("3/2", "3.0", "0x3.00#10", Floor, "0.5", "0x0.800#10", Equal); test( "3/2", "3.0", "0x3.00#10", Ceiling, "0.5", "0x0.800#10", Equal, ); test("3/2", "3.0", "0x3.00#10", Down, "0.5", "0x0.800#10", Equal); test("3/2", "3.0", "0x3.00#10", Up, "0.5", "0x0.800#10", Equal); test( "3/2", "3.0", "0x3.00#10", Nearest, "0.5", "0x0.800#10", Equal, ); test("3/2", "3.0", "0x3.00#10", Exact, "0.5", "0x0.800#10", Equal); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "0.47746482927568606", "0x0.7a3b2292bab314#53", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "0.47746482927568606", "0x0.7a3b2292bab314#53", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-0.47746482927568606", "-0x0.7a3b2292bab314#53", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-0.47746482927568606", "-0x0.7a3b2292bab314#53", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-0.47746482927568606", "-0x0.7a3b2292bab314#53", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "-0.47746482927568606", "-0x0.7a3b2292bab314#53", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "-0.47746482927568601", "-0x0.7a3b2292bab310#53", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "0.47746482927568606", "0x0.7a3b2292bab314#53", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "0.47746482927568606", "0x0.7a3b2292bab314#53", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "0.47746482927568601", "0x0.7a3b2292bab310#53", Less, ); } #[test] fn rational_div_float_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::rational_div_float_round(Rational::ONE, THREE, Exact)); assert_panic!(Float::rational_div_float_round_val_ref( Rational::ONE, &THREE, Exact )); assert_panic!(Float::rational_div_float_round_ref_val( &Rational::ONE, THREE, Exact )); assert_panic!(Float::rational_div_float_round_ref_ref( &Rational::ONE, &THREE, Exact )); } #[test] fn test_rational_div_float_prec_round() { let test = |s, t, t_hex, prec, rm, out: &str, out_hex: &str, o_out| { let x = Rational::from_str(s).unwrap(); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (quotient, o) = Float::rational_div_float_prec_round(x.clone(), y.clone(), prec, rm); assert!(quotient.is_valid()); assert_eq!(o, o_out); assert_eq!(quotient.to_string(), out); assert_eq!(to_hex_string("ient), out_hex); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_val_ref(x.clone(), &y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_val(&x, y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient), ComparableFloatRef("ient_alt) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if y.is_normal() { let (quotient_alt, o_alt) = rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_rational_div_float_prec_round( &rug::Rational::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient) ); assert_eq!(rug_o, o); } }; test("123", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("123", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("123", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("123", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("123", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("123", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "123", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal, ); test( "123", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "123", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal, ); test("123", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); test( "123", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "123", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "123", "-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, ); test("0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test("0", "Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal); test( "0", "Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal, ); test("0", "Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal); test("0", "Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); test( "0", "Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal, ); test("0", "Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal); test( "0", "-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0", "-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal, ); test("0", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal); test("0", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal); test("0", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "123", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test("123", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); test( "123", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-123", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-123", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "1/3", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "1/3", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "1/3", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test("1/3", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); test( "1/3", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "1/3", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "1/3", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-1/3", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "1", "123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less, ); test( "1", "123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater, ); test("1", "123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less); test("1", "123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater); test( "1", "123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less, ); test( "1", "123.0", "0x7b.0#7", 10, Floor, "0.00812", "0x0.0214#10", Less, ); test( "1", "123.0", "0x7b.0#7", 10, Ceiling, "0.00813", "0x0.0215#10", Greater, ); test( "1", "123.0", "0x7b.0#7", 10, Down, "0.00812", "0x0.0214#10", Less, ); test( "1", "123.0", "0x7b.0#7", 10, Up, "0.00813", "0x0.0215#10", Greater, ); test( "1", "123.0", "0x7b.0#7", 10, Nearest, "0.00813", "0x0.0215#10", Greater, ); test("0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal); test("0", "123.0", "0x7b.0#7", 1, Exact, "0.0", "0x0.0", Equal); test( "0", "-123.0", "-0x7b.0#7", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0", "-123.0", "-0x7b.0#7", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test("0", "-123.0", "-0x7b.0#7", 1, Down, "-0.0", "-0x0.0", Equal); test("0", "-123.0", "-0x7b.0#7", 1, Up, "-0.0", "-0x0.0", Equal); test( "0", "-123.0", "-0x7b.0#7", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0", "-123.0", "-0x7b.0#7", 1, Exact, "-0.0", "-0x0.0", Equal, ); test("2", "1.0", "0x1.0#1", 1, Floor, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 1, Ceiling, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 1, Down, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 1, Up, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 1, Nearest, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 1, Exact, "2.0", "0x2.0#1", Equal); test("2", "1.0", "0x1.0#1", 10, Floor, "2.0", "0x2.00#10", Equal); test( "2", "1.0", "0x1.0#1", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test("2", "1.0", "0x1.0#1", 10, Down, "2.0", "0x2.00#10", Equal); test("2", "1.0", "0x1.0#1", 10, Up, "2.0", "0x2.00#10", Equal); test( "2", "1.0", "0x1.0#1", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test("2", "1.0", "0x1.0#1", 10, Exact, "2.0", "0x2.00#10", Equal); test("3/2", "1.0", "0x1.000#10", 1, Floor, "1.0", "0x1.0#1", Less); test( "3/2", "1.0", "0x1.000#10", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test("3/2", "1.0", "0x1.000#10", 1, Down, "1.0", "0x1.0#1", Less); test("3/2", "1.0", "0x1.000#10", 1, Up, "2.0", "0x2.0#1", Greater); test( "3/2", "1.0", "0x1.000#10", 1, Nearest, "2.0", "0x2.0#1", Greater, ); test( "3/2", "1.0", "0x1.000#10", 10, Floor, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", 10, Ceiling, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", 10, Down, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", 10, Up, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", 10, Nearest, "1.5", "0x1.800#10", Equal, ); test( "3/2", "1.0", "0x1.000#10", 10, Exact, "1.5", "0x1.800#10", Equal, ); test("2", "3.0", "0x3.0#2", 1, Floor, "0.5", "0x0.8#1", Less); test("2", "3.0", "0x3.0#2", 1, Ceiling, "1.0", "0x1.0#1", Greater); test("2", "3.0", "0x3.0#2", 1, Down, "0.5", "0x0.8#1", Less); test("2", "3.0", "0x3.0#2", 1, Up, "1.0", "0x1.0#1", Greater); test("2", "3.0", "0x3.0#2", 1, Nearest, "0.5", "0x0.8#1", Less); test( "2", "3.0", "0x3.0#2", 10, Floor, "0.666", "0x0.aa8#10", Less, ); test( "2", "3.0", "0x3.0#2", 10, Ceiling, "0.667", "0x0.aac#10", Greater, ); test("2", "3.0", "0x3.0#2", 10, Down, "0.666", "0x0.aa8#10", Less); test( "2", "3.0", "0x3.0#2", 10, Up, "0.667", "0x0.aac#10", Greater, ); test( "2", "3.0", "0x3.0#2", 10, Nearest, "0.667", "0x0.aac#10", Greater, ); test("3/2", "3.0", "0x3.00#10", 1, Floor, "0.5", "0x0.8#1", Equal); test( "3/2", "3.0", "0x3.00#10", 1, Ceiling, "0.5", "0x0.8#1", Equal, ); test("3/2", "3.0", "0x3.00#10", 1, Down, "0.5", "0x0.8#1", Equal); test("3/2", "3.0", "0x3.00#10", 1, Up, "0.5", "0x0.8#1", Equal); test( "3/2", "3.0", "0x3.00#10", 1, Nearest, "0.5", "0x0.8#1", Equal, ); test("3/2", "3.0", "0x3.00#10", 1, Exact, "0.5", "0x0.8#1", Equal); test( "3/2", "3.0", "0x3.00#10", 10, Floor, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.0", "0x3.00#10", 10, Ceiling, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.0", "0x3.00#10", 10, Down, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.0", "0x3.00#10", 10, Up, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.0", "0x3.00#10", 10, Nearest, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.0", "0x3.00#10", 10, Exact, "0.5", "0x0.800#10", Equal, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "0.2", "0x0.4#1", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "0.5", "0x0.8#1", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "0.4771", "0x0.7a2#10", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "0.4775", "0x0.7a4#10", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "0.4771", "0x0.7a2#10", Less, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "0.4775", "0x0.7a4#10", Greater, ); test( "3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "0.4775", "0x0.7a4#10", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-0.2", "-0x0.4#1", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-0.2", "-0x0.4#1", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-0.4775", "-0x0.7a4#10", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-0.4771", "-0x0.7a2#10", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-0.4771", "-0x0.7a2#10", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-0.4775", "-0x0.7a4#10", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-0.4775", "-0x0.7a4#10", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-0.2", "-0x0.4#1", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-0.2", "-0x0.4#1", Greater, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-0.5", "-0x0.8#1", Less, ); test( "3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-0.5", "-0x0.8#1", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "-0.4775", "-0x0.7a4#10", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "-0.4771", "-0x0.7a2#10", Greater, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "-0.4771", "-0x0.7a2#10", Greater, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "-0.4775", "-0x0.7a4#10", Less, ); test( "-3/2", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "-0.4775", "-0x0.7a4#10", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "0.2", "0x0.4#1", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "0.5", "0x0.8#1", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "0.4771", "0x0.7a2#10", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "0.4775", "0x0.7a4#10", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "0.4771", "0x0.7a2#10", Less, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "0.4775", "0x0.7a4#10", Greater, ); test( "-3/2", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "0.4775", "0x0.7a4#10", Greater, ); } #[test] fn rational_div_float_prec_round_fail() { assert_panic!(Float::rational_div_float_prec_round( Rational::ONE, Float::one_prec(1), 0, Floor )); assert_panic!(Float::rational_div_float_prec_round( Rational::ONE, Float::from(3), 1, Exact )); assert_panic!(Float::rational_div_float_prec_round_val_ref( Rational::ONE, &Float::from(3), 1, Exact )); assert_panic!(Float::rational_div_float_prec_round_ref_val( &Rational::ONE, Float::from(3), 1, Exact )); assert_panic!(Float::rational_div_float_prec_round_ref_ref( &Rational::ONE, &Float::from(3), 1, Exact )); } #[allow(clippy::needless_pass_by_value)] fn div_prec_round_properties_helper( x: Float, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (quotient, o) = x.clone().div_prec_round(y.clone(), prec, rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_prec_round_val_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_prec_round_ref_val(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!( ComparableFloatRef( "ient .mul_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 ), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef( &x.div_prec_round_ref_ref("ient, y.significant_bits(), Exact) .0 ), ComparableFloatRef(&y) ); } if quotient.is_finite() && y.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut quotient_alt, mut o_alt) = x.div_prec_round_ref_val(-&y, prec, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = (-&x).div_prec_round_val_ref(&y, prec, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = (-&x).div_prec_round(-&y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.div_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.div_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn div_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties(|(x, y, prec, rm)| { div_prec_round_properties_helper(x, y, prec, rm, false); }); float_float_unsigned_rounding_mode_quadruple_gen_var_8().test_properties(|(x, y, prec, rm)| { div_prec_round_properties_helper(x, y, prec, rm, true); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties_with_config( &config, |(x, y, prec, rm)| { div_prec_round_properties_helper(x, y, prec, rm, false); }, ); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_small_n", 2048); float_float_unsigned_rounding_mode_quadruple_gen_var_4().test_properties_with_config( &config, |(x, y, prec, rm)| { div_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (quotient, o) = x.div_prec_round_ref_val(Float::NAN, prec, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); let (quotient, o) = Float::NAN.div_prec_round_val_ref(&x, prec, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x.is_finite() { assert_eq!( x.div_prec_round_ref_val(Float::INFINITY, prec, rm), ( if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::INFINITY.div_prec_round_val_ref(&x, prec, rm), ( if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.div_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), ( if x.is_sign_positive() { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_prec_round_val_ref(&x, prec, rm), ( if x.is_sign_positive() { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x != 0 { assert_eq!( x.div_prec_round_ref_val(Float::ZERO, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::ZERO.div_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( x.div_prec_round_ref_val(Float::ZERO, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_ZERO.div_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); } } if !x.is_negative_zero() { let (quotient, o) = x.div_prec_round_ref_val(Float::ONE, prec, rm); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); assert_eq!(o, o_alt); if rm != Exact { let (quotient, o) = Float::ONE.div_prec_round_val_ref(&x, prec, rm); let (quotient_alt, o_alt) = x.clone().reciprocal_prec_round(prec, rm); assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); assert_eq!(o, o_alt); } } }); } fn div_prec_properties_helper(x: Float, y: Float, prec: u64, extreme: bool) { let (quotient, o) = x.clone().div_prec(y.clone(), prec); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_prec_val_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_prec_ref_val(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_prec_ref_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!( ComparableFloatRef("ient.mul_prec_ref_ref(&y, x.significant_bits()).0), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&x.div_prec_ref_ref("ient, y.significant_bits()).0), ComparableFloatRef(&y) ); } let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if quotient.is_finite() && y.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let (mut quotient_alt, mut o_alt) = x.div_prec_ref_val(-&y, prec); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient), ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = (-&x).div_prec_val_ref(&y, prec); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = (-x).div_prec(-y, prec); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } } #[test] fn div_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { div_prec_properties_helper(x, y, prec, false); }); float_float_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { div_prec_properties_helper(x, y, prec, true); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { div_prec_properties_helper(x, y, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_small_n", 2048); float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { div_prec_properties_helper(x, y, prec, false); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (quotient, o) = x.div_prec_ref_val(Float::NAN, prec); assert!(quotient.is_nan()); assert_eq!(o, Equal); let (quotient, o) = Float::NAN.div_prec_val_ref(&x, prec); assert!(quotient.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x.is_finite() { assert_eq!( x.div_prec_ref_val(Float::INFINITY, prec), ( if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::INFINITY.div_prec_val_ref(&x, prec), ( if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.div_prec_ref_val(Float::NEGATIVE_INFINITY, prec), ( if x.is_sign_positive() { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_prec_val_ref(&x, prec), ( if x.is_sign_positive() { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x != 0 { assert_eq!( x.div_prec_ref_val(Float::ZERO, prec), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::ZERO.div_prec_val_ref(&x, prec), ( if x > 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( x.div_prec_ref_val(Float::NEGATIVE_ZERO, prec), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_ZERO.div_prec_val_ref(&x, prec), ( if x > 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); } } if !x.is_negative_zero() { let (quotient, o) = x.div_prec_ref_val(Float::ONE, prec); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.set_prec(prec); assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); assert_eq!(o, o_alt); } }); } #[allow(clippy::needless_pass_by_value)] fn div_round_properties_helper(x: Float, y: Float, rm: RoundingMode, extreme: bool) { let (quotient, o) = x.clone().div_round(y.clone(), rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_round_val_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = x.div_round_ref_val(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = x.div_round_ref_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let mut x_alt = x.clone(); let o_alt = x_alt.div_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } let (quotient_alt, o_alt) = x.div_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!(quotient.mul_round_ref_ref(&y, Exact).0, x); assert_eq!(x.div_round_ref_ref("ient, Exact).0, y); } if quotient.is_finite() && y.is_finite() { if x.is_normal() && y.is_normal() && quotient.is_normal() { assert_eq!( quotient.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); } if !extreme { let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } let (mut quotient_alt, mut o_alt) = x.div_round_ref_val(-&y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); let (mut quotient_alt, mut o_alt) = (-&x).div_round_val_ref(&y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); let (quotient_alt, o_alt) = (-&x).div_round(-&y, rm); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.div_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.div_round_ref_ref(&y, Exact)); } } #[test] fn div_round_properties() { float_float_rounding_mode_triple_gen_var_23().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_32().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, true); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_float_rounding_mode_triple_gen_var_23().test_properties_with_config( &config, |(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }, ); float_float_rounding_mode_triple_gen_var_24().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_25().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_26().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_27().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_28().test_properties(|(x, y, rm)| { div_round_properties_helper(x, y, rm, false); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (quotient, o) = x.div_round_ref_val(Float::NAN, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); let (quotient, o) = Float::NAN.div_round_val_ref(&x, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x.is_finite() { assert_eq!( x.div_round_ref_val(Float::INFINITY, rm), ( if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::INFINITY.div_round_val_ref(&x, rm), ( if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.div_round_ref_val(Float::NEGATIVE_INFINITY, rm), ( if x.is_sign_positive() { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_round_val_ref(&x, rm), ( if x.is_sign_positive() { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x != 0 { assert_eq!( x.div_round_ref_val(Float::ZERO, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::ZERO.div_round_val_ref(&x, rm), ( if x > 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( x.div_round_ref_val(Float::NEGATIVE_ZERO, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_ZERO.div_round_val_ref(&x, rm), ( if x > 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); } } if !x.is_negative_zero() { let (quotient, o) = x.div_round_ref_val(Float::ONE, rm); assert_eq!(ComparableFloatRef("ient), ComparableFloatRef(&x)); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn div_properties_helper_1(x: Float, y: Float, extreme: bool) { let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let mut x_alt = x.clone(); x_alt /= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); let mut x_alt = x.clone(); x_alt /= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); if !extreme { let quotient_alt = div_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } let quotient_alt = x .div_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = x .div_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o) = x.div_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!("ient * &y, x); assert_eq!(&x / "ient, y); } if quotient.is_finite() && x.is_normal() && y.is_normal() && quotient.is_normal() { assert_eq!( quotient.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); if !extreme { let r_quotient = Rational::exact_from(&x) / Rational::exact_from(&y); if quotient < r_quotient { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if quotient > r_quotient { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } let rug_quotient = rug_div(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { assert_eq!( ComparableFloatRef(&-(&x / -&y)), ComparableFloatRef("ient) ); assert_eq!( ComparableFloatRef(&-(-&x / &y)), ComparableFloatRef("ient) ); assert_eq!( ComparableFloatRef(&(-&x / -&y)), ComparableFloatRef("ient) ); } } #[allow(clippy::type_repetition_in_bounds)] fn div_properties_helper_2() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { let quotient_1 = x / y; let quotient_2 = emulate_float_float_to_float_fn(Float::div_prec, x, y); assert_eq!(NiceFloat(quotient_1), NiceFloat(quotient_2)); }); } #[test] fn div_properties() { float_pair_gen().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_10().test_properties(|(x, y)| { div_properties_helper_1(x, y, true); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_pair_gen().test_properties_with_config(&config, |(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_2().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_3().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_4().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_8().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); float_pair_gen_var_9().test_properties(|(x, y)| { div_properties_helper_1(x, y, false); }); apply_fn_to_primitive_floats!(div_properties_helper_2); float_gen().test_properties(|x| { assert!((&x / Float::NAN).is_nan()); assert!((Float::NAN / &x).is_nan()); if !x.is_nan() { if x.is_finite() { assert_eq!( &x / Float::INFINITY, if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO } ); assert_eq!( Float::INFINITY / &x, if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( &x / Float::NEGATIVE_INFINITY, if x.is_sign_positive() { Float::NEGATIVE_ZERO } else { Float::ZERO } ); assert_eq!( Float::NEGATIVE_INFINITY / &x, if x.is_sign_positive() { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); } if x != 0 { assert_eq!( &x / Float::ZERO, if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( Float::ZERO / &x, if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO } ); assert_eq!( &x / Float::NEGATIVE_ZERO, if x.is_sign_positive() { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); assert_eq!( Float::NEGATIVE_ZERO / &x, if x.is_sign_positive() { Float::NEGATIVE_ZERO } else { Float::ZERO } ); } assert_eq!(&x / Float::ONE, x); } }); } #[allow(clippy::needless_pass_by_value)] fn div_rational_prec_round_properties_helper( x: Float, y: Rational, prec: u64, rm: RoundingMode, extreme: bool, ) { let (quotient, o) = x.clone().div_rational_prec_round(y.clone(), prec, rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_rational_prec_round_val_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = div_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!( ComparableFloatRef( "ient .mul_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 ), ComparableFloatRef(&x) ); // TODO additional test } if quotient.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = Rational::exact_from(&x) / &y; assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut quotient_alt, mut o_alt) = x.div_rational_prec_round_ref_val(-&y, prec, -rm); if y != 0 { quotient_alt.neg_assign(); } o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()), ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = (-&x).div_rational_prec_round_val_ref(&y, prec, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if quotient != 0u32 && y != 0 { let (quotient_alt, o_alt) = (-&x).div_rational_prec_round(-&y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.div_rational_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.div_rational_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn div_rational_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_4().test_properties( |(x, y, prec, rm)| { div_rational_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_rational_unsigned_rounding_mode_quadruple_gen_var_9().test_properties( |(x, y, prec, rm)| { div_rational_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_negative_zero() { let (quotient, o) = x.div_rational_prec_round_ref_val(Rational::ONE, prec, rm); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); assert_eq!(o, o_alt); } if !x.is_nan() && x != 0 { assert_eq!( x.div_rational_prec_round_ref_val(Rational::ZERO, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (quotient, o) = Float::NAN.div_rational_prec_round_val_ref(&x, prec, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.div_rational_prec_round_val_ref(&x, prec, rm), ( if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_rational_prec_round_val_ref(&x, prec, rm), ( if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); if x != 0 { let (quotient, o) = Float::ZERO.div_rational_prec_round_val_ref(&x, prec, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); let (quotient, o) = Float::NEGATIVE_ZERO.div_rational_prec_round_val_ref(&x, prec, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }) ); assert_eq!(o, Equal); } }); } fn div_rational_prec_properties_helper(x: Float, y: Rational, prec: u64, extreme: bool) { let (quotient, o) = x.clone().div_rational_prec(y.clone(), prec); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_rational_prec_val_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_ref_val(y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = x.div_rational_prec_ref_ref(&y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } let (rug_quotient, rug_o) = rug_div_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!( ComparableFloatRef( "ient .mul_rational_prec_ref_ref(&y, x.significant_bits()) .0 ), ComparableFloatRef(&x) ); // TODO additional test } let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if quotient.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = Rational::exact_from(&x) / &y; assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } if x != 0u32 && y != 0u32 { let (mut quotient_alt, mut o_alt) = x.div_rational_prec_ref_val(-&y, prec); quotient_alt.neg_assign(); quotient_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = (-&x).div_rational_prec_val_ref(&y, prec); quotient_alt.neg_assign(); quotient_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = (-x).div_rational_prec(-y, prec); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } } #[test] fn div_rational_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { div_rational_prec_properties_helper(x, y, prec, false); }); float_rational_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { div_rational_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_negative_zero() { let (quotient, o) = x.div_rational_prec_ref_val(Rational::ONE, prec); let mut quotient_alt = x.clone(); let o_alt = quotient_alt.set_prec(prec); assert_eq!(ComparableFloat(quotient), ComparableFloat(quotient_alt)); assert_eq!(o, o_alt); } if x.is_finite() && x != 0 { let (quotient, o) = x.div_rational_prec_ref_val(Rational::ZERO, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }) ); assert_eq!(o, Equal); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (quotient, o) = Float::NAN.div_rational_prec_val_ref(&x, prec); assert!(quotient.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::INFINITY.div_rational_prec_val_ref(&x, prec), ( if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_rational_prec_val_ref(&x, prec), ( if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x != 0 { let (quotient, o) = Float::ZERO.div_rational_prec_val_ref(&x, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); let (quotient, o) = Float::NEGATIVE_ZERO.div_rational_prec_val_ref(&x, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }) ); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn div_rational_round_properties_helper(x: Float, y: Rational, rm: RoundingMode, extreme: bool) { let (quotient, o) = x.clone().div_rational_round(y.clone(), rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = x.clone().div_rational_round_val_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = x.div_rational_round_ref_val(y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = x.div_rational_round_ref_ref(&y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.div_rational_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if x.is_normal() { let (quotient_alt, o_alt) = div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } let (quotient_alt, o_alt) = x.div_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!(quotient.mul_rational_round_ref_ref(&y, Exact).0, x); // TODO additional test } if quotient.is_finite() { if x.is_normal() && quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(x.get_prec().unwrap())); } if !extreme { let r_quotient = Rational::exact_from(&x) / &y; assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_quotient, rug_o) = rug_div_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); assert_eq!(rug_o, o); } if y != 0 { let (mut quotient_alt, mut o_alt) = x.div_rational_round_ref_val(-&y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); } let (mut quotient_alt, mut o_alt) = (-&x).div_rational_round_val_ref(&y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); if x != 0 && y != 0 { let (quotient_alt, o_alt) = (-&x).div_rational_round(-&y, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient), ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.div_rational_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.div_rational_round_ref_ref(&y, Exact)); } } #[test] fn div_rational_round_properties() { float_rational_rounding_mode_triple_gen_var_5().test_properties(|(x, y, rm)| { div_rational_round_properties_helper(x, y, rm, false); }); float_rational_rounding_mode_triple_gen_var_10().test_properties(|(x, y, rm)| { div_rational_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (quotient, o) = x.div_rational_round_ref_val(Rational::ONE, rm); assert_eq!(ComparableFloatRef("ient), ComparableFloatRef(&x)); assert_eq!(o, Equal); if x.is_finite() && x != 0 { let (quotient, o) = x.div_rational_round_ref_val(Rational::ZERO, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }) ); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (quotient, o) = Float::NAN.div_rational_round_val_ref(&x, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::INFINITY.div_rational_round_val_ref(&x, rm), ( if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.div_rational_round_val_ref(&x, rm), ( if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } }); } fn div_rational_properties_helper(x: Float, y: Rational, extreme: bool) { let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let mut x_alt = x.clone(); x_alt /= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); let mut x_alt = x.clone(); x_alt /= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef("ient)); if !extreme { let quotient_alt = div_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } if x.is_normal() { let quotient_alt = div_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } let quotient_alt = x .div_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = x.div_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o) = x.div_rational_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if o == Equal && quotient.is_finite() && quotient != 0 { assert_eq!("ient * &y, x); // TODO additional test } if quotient.is_finite() && x.is_normal() && quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(x.get_prec().unwrap())); if !extreme { let r_quotient = Rational::exact_from(&x) / &y; if quotient < r_quotient { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if quotient > r_quotient { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } let rug_quotient = rug_div_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_quotient)), ComparableFloatRef("ient), ); if quotient != 0u32 { assert_eq!( ComparableFloatRef(&-(-&x / &y)), ComparableFloatRef("ient) ); if y != 0 { assert_eq!( ComparableFloatRef(&-(&x / -&y)), ComparableFloatRef("ient) ); assert_eq!( ComparableFloatRef(&(-x / -y)), ComparableFloatRef("ient) ); } } } #[test] fn div_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { div_rational_properties_helper(x, y, false); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { div_rational_properties_helper(x, y, true); }); float_gen().test_properties(|x| { assert_eq!( ComparableFloatRef(&(&x / Rational::ONE)), ComparableFloatRef(&x) ); if x.is_finite() && x != 0 { assert_eq!( ComparableFloat(&x / Rational::ZERO), ComparableFloat(if x.is_sign_positive() { Float::INFINITY } else { Float::NEGATIVE_INFINITY }), ); } }); rational_gen().test_properties(|x| { assert!((&x / Float::NAN).is_nan()); assert_eq!( &x / Float::INFINITY, if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO } ); assert_eq!( &x / Float::NEGATIVE_INFINITY, if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO } ); if x != 0 { assert_eq!( &x / Float::ZERO, if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( &x / Float::NEGATIVE_ZERO, if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); } }); } #[allow(clippy::needless_pass_by_value)] fn rational_div_float_prec_round_properties_helper( x: Rational, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (quotient, o) = Float::rational_div_float_prec_round(x.clone(), y.clone(), prec, rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_val_ref(x.clone(), &y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_val(&x, y.clone(), prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if y.is_normal() { let (quotient_alt, o_alt) = rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = rational_div_float_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } // TODO add rug comparison once https://gitlab.com/tspiteri/rug/-/issues/85 is resolved if quotient.is_finite() && y.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = &x / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut quotient_alt, mut o_alt) = Float::rational_div_float_prec_round_ref_val(&x, -&y, prec, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()), ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = Float::rational_div_float_prec_round_val_ref(-&x, &y, prec, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if quotient != 0u32 && y != 0u32 { let (quotient_alt, o_alt) = Float::rational_div_float_prec_round(-&x, -&y, prec, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::rational_div_float_prec_round_ref_ref( &x, &y, prec, Exact )); } } #[test] fn rational_div_float_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_5().test_properties( |(y, x, prec, rm)| { rational_div_float_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_rational_unsigned_rounding_mode_quadruple_gen_var_10().test_properties( |(y, x, prec, rm)| { rational_div_float_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_nan() && x != 0 { assert_eq!( Float::rational_div_float_prec_round_val_ref(Rational::ZERO, &x, prec, rm), ( if x > 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (quotient, o) = Float::rational_div_float_prec_round_ref_val(&x, Float::NAN, prec, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::rational_div_float_prec_round_ref_val(&x, Float::INFINITY, prec, rm), ( if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::rational_div_float_prec_round_ref_val(&x, Float::NEGATIVE_INFINITY, prec, rm), ( if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); if x != 0 { let (quotient, o) = Float::rational_div_float_prec_round_ref_val(&x, Float::ZERO, prec, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }) ); assert_eq!(o, Equal); let (quotient, o) = Float::rational_div_float_prec_round_ref_val(&x, Float::NEGATIVE_ZERO, prec, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }) ); assert_eq!(o, Equal); } }); } fn rational_div_float_prec_properties_helper(x: Rational, y: Float, prec: u64, extreme: bool) { let (quotient, o) = Float::rational_div_float_prec(x.clone(), y.clone(), prec); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = Float::rational_div_float_prec_val_ref(x.clone(), &y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_val(&x, y.clone(), prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec_ref_ref(&x, &y, prec); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if !extreme { let (quotient_alt, o_alt) = rational_div_float_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if y.is_normal() { let (quotient_alt, o_alt) = rational_div_float_prec_round_direct(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } // TODO add rug comparison once https://gitlab.com/tspiteri/rug/-/issues/85 is resolved let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_ref(&x, &y, prec, Nearest); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if quotient.is_finite() && y.is_finite() { if quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(prec)); } if !extreme { let r_quotient = &x / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } if x != 0u32 && y != 0u32 { let (mut quotient_alt, mut o_alt) = Float::rational_div_float_prec_ref_val(&x, -&y, prec); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (mut quotient_alt, mut o_alt) = Float::rational_div_float_prec_val_ref(-&x, &y, prec); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); let (quotient_alt, o_alt) = Float::rational_div_float_prec(-x, -y, prec); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } } #[test] fn rational_div_float_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(y, x, prec)| { rational_div_float_prec_properties_helper(x, y, prec, false); }); float_rational_unsigned_triple_gen_var_2().test_properties(|(y, x, prec)| { rational_div_float_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if x.is_finite() && x != 0 { let (quotient, o) = Float::rational_div_float_prec_val_ref(Rational::ZERO, &x, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (quotient, o) = Float::rational_div_float_prec_ref_val(&x, Float::NAN, prec); assert!(quotient.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::rational_div_float_prec_ref_val(&x, Float::INFINITY, prec), ( if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::rational_div_float_prec_ref_val(&x, Float::NEGATIVE_INFINITY, prec), ( if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); } if x != 0 { let (quotient, o) = Float::rational_div_float_prec_ref_val(&x, Float::ZERO, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }) ); assert_eq!(o, Equal); let (quotient, o) = Float::rational_div_float_prec_ref_val(&x, Float::NEGATIVE_ZERO, prec); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }) ); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn rational_div_float_round_properties_helper( x: Rational, y: Float, rm: RoundingMode, extreme: bool, ) { let (quotient, o) = Float::rational_div_float_round(x.clone(), y.clone(), rm); assert!(quotient.is_valid()); let (quotient_alt, o_alt) = Float::rational_div_float_round_val_ref(x.clone(), &y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_val(&x, y.clone(), rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let (quotient_alt, o_alt) = Float::rational_div_float_round_ref_ref(&x, &y, rm); assert!(quotient_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if !extreme { let (quotient_alt, o_alt) = rational_div_float_prec_round_naive(x.clone(), y.clone(), y.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } if y.is_normal() { let (quotient_alt, o_alt) = rational_div_float_prec_round_direct(x.clone(), y.clone(), y.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); } // TODO add rug comparison once https://gitlab.com/tspiteri/rug/-/issues/85 is resolved let (quotient_alt, o_alt) = Float::rational_div_float_prec_round_ref_ref(&x, &y, y.significant_bits(), rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); assert_eq!(o_alt, o); if quotient.is_finite() && y.is_finite() { if y.is_normal() && quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(y.get_prec().unwrap())); } if !extreme { let r_quotient = &x / Rational::exact_from(&y); assert_eq!(quotient.partial_cmp(&r_quotient), Some(o)); if o == Less { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if o == Greater { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } match (r_quotient >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if y != 0 { let (mut quotient_alt, mut o_alt) = Float::rational_div_float_round_ref_val(&x, -&y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); } let (mut quotient_alt, mut o_alt) = Float::rational_div_float_round_val_ref(-&x, &y, -rm); quotient_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(quotient_alt.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); if x != 0 && y != 0 { let (quotient_alt, o_alt) = Float::rational_div_float_round(-&x, -&y, rm); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient), ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::rational_div_float_round_ref_ref(&x, &y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(quotient.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::rational_div_float_round_ref_ref(&x, &y, Exact)); } } #[test] fn rational_div_float_round_properties() { float_rational_rounding_mode_triple_gen_var_6().test_properties(|(y, x, rm)| { rational_div_float_round_properties_helper(x, y, rm, false); }); float_rational_rounding_mode_triple_gen_var_11().test_properties(|(y, x, rm)| { rational_div_float_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { if x.is_finite() && x != 0 { let (quotient, o) = Float::rational_div_float_round_val_ref(Rational::ZERO, &x, rm); assert_eq!( ComparableFloat(quotient), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (quotient, o) = Float::rational_div_float_round_ref_val(&x, Float::NAN, rm); assert!(quotient.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::rational_div_float_round_ref_val(&x, Float::INFINITY, rm), ( if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }, Equal ) ); assert_eq!( Float::rational_div_float_round_ref_val(&x, Float::NEGATIVE_INFINITY, rm), ( if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }, Equal ) ); } }); } fn rational_div_float_properties_helper(x: Rational, y: Float, extreme: bool) { let quotient = x.clone() / y.clone(); assert!(quotient.is_valid()); let quotient_alt = x.clone() / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / y.clone(); assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = &x / &y; assert!(quotient_alt.is_valid()); assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if !extreme { let quotient_alt = rational_div_float_prec_round_naive( x.clone(), y.clone(), y.significant_bits(), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } if y.is_normal() { let quotient_alt = rational_div_float_prec_round_direct( x.clone(), y.clone(), y.significant_bits(), Nearest, ) .0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); } let quotient_alt = Float::rational_div_float_prec_round_ref_ref(&x, &y, y.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = Float::rational_div_float_prec_ref_ref(&x, &y, y.significant_bits()).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); let quotient_alt = Float::rational_div_float_round_ref_ref(&x, &y, Nearest).0; assert_eq!( ComparableFloatRef("ient_alt), ComparableFloatRef("ient) ); if quotient.is_finite() && y.is_normal() && quotient.is_normal() { assert_eq!(quotient.get_prec(), Some(y.get_prec().unwrap())); if !extreme { let r_quotient = &x / Rational::exact_from(&y); if quotient < r_quotient { let mut next = quotient.clone(); next.increment(); assert!(next > r_quotient); } else if quotient > r_quotient { let mut next = quotient.clone(); next.decrement(); assert!(next < r_quotient); } } } // TODO add rug comparison once https://gitlab.com/tspiteri/rug/-/issues/85 is resolved if quotient != 0u32 { assert_eq!( ComparableFloatRef(&-(-&x / &y)), ComparableFloatRef("ient) ); if y != 0 { assert_eq!( ComparableFloatRef(&-(&x / -&y)), ComparableFloatRef("ient) ); assert_eq!( ComparableFloatRef(&(-x / -y)), ComparableFloatRef("ient) ); } } } #[test] fn rational_div_float_properties() { float_rational_pair_gen().test_properties(|(y, x)| { rational_div_float_properties_helper(x, y, false); }); float_rational_pair_gen_var_2().test_properties(|(y, x)| { rational_div_float_properties_helper(x, y, true); }); float_gen().test_properties(|x| { if x.is_finite() && x != 0 { assert_eq!( ComparableFloat(Rational::ZERO / &x), ComparableFloat(if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }), ); assert_eq!( ComparableFloat(Rational::ZERO / &x), ComparableFloat(if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); } }); rational_gen().test_properties(|x| { assert!((Float::NAN / &x).is_nan()); assert_eq!( Float::INFINITY / &x, if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( Float::NEGATIVE_INFINITY / &x, if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); if x != 0 { assert_eq!( Float::ZERO / &x, if x > 0 { Float::ZERO } else { Float::NEGATIVE_ZERO } ); assert_eq!( Float::NEGATIVE_ZERO / &x, if x > 0 { Float::NEGATIVE_ZERO } else { Float::ZERO } ); } let quotient_alt = Float::from_rational_prec_ref(&x, 1).0; assert_eq!( ComparableFloat(&x / Float::ONE), ComparableFloat(quotient_alt.clone()) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::primitive_float_gen; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{float_gen, float_gen_var_4, float_gen_var_12}; use malachite_q::Rational; #[test] fn test_is_power_of_2() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_power_of_2(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", true); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", true); test("too_small", "0x1.0E-268435456#1", true); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_power_of_2_properties_helper(x: Float) { let is_power_of_2 = x.is_power_of_2(); if is_power_of_2 { assert!(x > 0u32); } } #[test] fn is_power_of_2_properties() { float_gen().test_properties(|x| { is_power_of_2_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_power_of_2_properties_helper(x); }); float_gen_var_4().test_properties(|x| { assert_eq!(x.is_power_of_2(), Rational::exact_from(x).is_power_of_2()); }); primitive_float_gen::().test_properties(|x| { assert_eq!(x.is_power_of_2(), Float::from(x).is_power_of_2()); }); } ================================================ FILE: malachite-float/tests/arithmetic/ln.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use core::{f32, f64}; use malachite_base::num::arithmetic::traits::{Ln, LnAssign, PowerOf2, Reciprocal}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::arithmetic::ln::{primitive_float_ln, primitive_float_ln_rational}; use malachite_float::test_util::arithmetic::ln::{ ln_prec_round_extended, rug_ln, rug_ln_prec, rug_ln_prec_round, rug_ln_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_rounding_mode_pair_gen_var_34, float_rounding_mode_pair_gen_var_35, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_19, float_unsigned_rounding_mode_triple_gen_var_20, rational_unsigned_rounding_mode_triple_gen_var_6, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_ln() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let ln = x.clone().ln(); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); let ln_alt = (&x).ln(); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); let mut ln_alt = x.clone(); ln_alt.ln_assign(); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!( ComparableFloatRef(&ln), ComparableFloatRef( &ln_prec_round_extended(x.clone(), x.get_prec().unwrap_or(1), Nearest).0 ) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln(&rug::Float::exact_from(&x)))), ComparableFloatRef(&ln) ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "-Infinity", "-Infinity"); test("-0.0", "-0x0.0", "-Infinity", "-Infinity"); test("1.0", "0x1.0#1", "0.0", "0x0.0"); test("-1.0", "-0x1.0#1", "NaN", "NaN"); test("1.0", "0x1.0000000000000000000000000#100", "0.0", "0x0.0"); test("-1.0", "-0x1.0000000000000000000000000#100", "NaN", "NaN"); test("123.0", "0x7b.0#7", "4.81", "0x4.d#7"); test("-123.0", "-0x7b.0#7", "NaN", "NaN"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1.1447298858494002", "0x1.250d048e7a1bd#53", ); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "NaN", "NaN"); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", "1.577721810442023610823457130564e-30", "0x1.ffffffffffffffffffffffffeE-25#100", ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", "-1.577721810442023610823457130566e-30", "-0x2.0000000000000000000000000E-25#99", ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", "1.0", "0x1.0000000000000#53", ); } #[test] fn test_ln_prec() { let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (ln, o) = x.clone().ln_prec(prec); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, o_out); let (ln_alt, o_alt) = x.ln_prec_ref(prec); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let mut ln_alt = x.clone(); let o_alt = ln_alt.ln_prec_assign(prec); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), prec, Nearest); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let (rug_ln, rug_o) = rug_ln_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "Infinity", "Infinity", Equal); test("-Infinity", "-Infinity", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); // - in ln_prec_round_normal // - *x == 1u32 in ln_prec_round_normal test("1.0", "0x1.0#1", 1, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, "0.0", "0x0.0", Equal); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, "0.0", "0x0.0", Equal, ); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", 1, "4.0", "0x4.0#1", Less); test("123.0", "0x7b.0#7", 10, "4.81", "0x4.d0#10", Greater); test("-123.0", "-0x7b.0#7", 1, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "1.145", "0x1.250#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, "2.0e-30", "0x2.0E-25#1", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, "1.578e-30", "0x2.00E-25#10", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, "-2.0e-30", "-0x2.0E-25#1", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, "-1.578e-30", "-0x2.00E-25#10", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, "1.0", "0x1.0#1", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, "1.0", "0x1.000#10", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1000, "0.999999999999999946817622933941086294801645535631167330140966894773031833945843167502391\ 658696177866134372942956876650105751129080333063719848201745765425041221713102525849084801\ 372391581210765049471829553635989842946539858533293656242339571977421630183546441129939950\ 3482873700231381735818901075103963", "0x0.fffffffffffffc2af5533763665751db2b3c952fde86afe1810bb66ea1494e989573a8be58f802b1c430a\ 02dc8ffc80b2e393a359078dce063403a2113f8777bb9d11195ac4058bd5552c15bae9bd34651b64dd0f9acde5\ 926173f1391023dd0bccba5e4cc09fab80c32b730f5bd7df655766e551cbd2672a9afa3df95#1000", Greater, ); // - *x != 1u32 in ln_prec_round_normal // - tmp1.is_normal() && tmp2.is_normal() in ln_prec_round_normal // - !float_can_round in ln_prec_round_normal // - float_can_round in ln_prec_round_normal test("2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Less); // - !tmp1.is_normal() && !tmp2.is_normal() in ln_prec_round_normal test( "0.999998", "0x0.ffffe#19", 5, "-1.9e-6", "-0x0.000020#5", Greater, ); } #[test] fn ln_prec_fail() { assert_panic!(Float::NAN.ln_prec(0)); assert_panic!(Float::NAN.ln_prec_ref(0)); assert_panic!({ let mut x = Float::NAN; x.ln_prec_assign(0) }); } #[test] fn test_ln_round() { let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (ln, o) = x.clone().ln_round(rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, o_out); let (ln_alt, o_alt) = x.ln_round_ref(rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let mut ln_alt = x.clone(); let o_alt = ln_alt.ln_round_assign(rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), x.get_prec().unwrap_or(1), rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_ln, rug_o) = rug_ln_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal); test("-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal); test("1.0", "0x1.0#1", Floor, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Exact, "0.0", "0x0.0", Equal); test("-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", Floor, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Exact, "0.0", "0x0.0", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", Floor, "4.75", "0x4.c#7", Less); test("123.0", "0x7b.0#7", Ceiling, "4.81", "0x4.d#7", Greater); test("123.0", "0x7b.0#7", Down, "4.75", "0x4.c#7", Less); test("123.0", "0x7b.0#7", Up, "4.81", "0x4.d#7", Greater); test("123.0", "0x7b.0#7", Nearest, "4.81", "0x4.d#7", Greater); test("-123.0", "-0x7b.0#7", Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "1.1447298858493999", "0x1.250d048e7a1bc#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "1.1447298858494002", "0x1.250d048e7a1bd#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "1.1447298858493999", "0x1.250d048e7a1bc#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "1.1447298858494002", "0x1.250d048e7a1bd#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "1.1447298858494002", "0x1.250d048e7a1bd#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "NaN", "NaN", Equal, ); test( "too_big", "0x4.0E+268435455#1", Nearest, "5.0e8", "0x2.0E+7#1", Less, ); test( "too_big", "0x6.0E+268435455#2", Nearest, "8.0e8", "0x3.0E+7#2", Greater, ); test( "too_small", "0x1.0E-268435456#1", Nearest, "-5.0e8", "-0x2.0E+7#1", Greater, ); test( "too_small", "0x1.0E-268435456#2", Nearest, "-8.0e8", "-0x3.0E+7#2", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", Floor, "1.577721810442023610823457130564e-30", "0x1.ffffffffffffffffffffffffeE-25#100", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", Ceiling, "1.577721810442023610823457130566e-30", "0x2.0000000000000000000000000E-25#100", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", Down, "1.577721810442023610823457130564e-30", "0x1.ffffffffffffffffffffffffeE-25#100", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", Up, "1.577721810442023610823457130566e-30", "0x2.0000000000000000000000000E-25#100", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", Nearest, "1.577721810442023610823457130564e-30", "0x1.ffffffffffffffffffffffffeE-25#100", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", Floor, "-1.577721810442023610823457130571e-30", "-0x2.0000000000000000000000008E-25#99", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", Ceiling, "-1.577721810442023610823457130566e-30", "-0x2.0000000000000000000000000E-25#99", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", Down, "-1.577721810442023610823457130566e-30", "-0x2.0000000000000000000000000E-25#99", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", Up, "-1.577721810442023610823457130571e-30", "-0x2.0000000000000000000000008E-25#99", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", Nearest, "-1.577721810442023610823457130566e-30", "-0x2.0000000000000000000000000E-25#99", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", Floor, "0.9999999999999999", "0x0.fffffffffffff8#53", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", Ceiling, "1.0", "0x1.0000000000000#53", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", Down, "0.9999999999999999", "0x0.fffffffffffff8#53", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", Up, "1.0", "0x1.0000000000000#53", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", Nearest, "1.0", "0x1.0000000000000#53", Greater, ); } #[test] fn ln_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.ln_round(Exact)); assert_panic!(THREE.ln_round_ref(Exact)); assert_panic!({ let mut x = THREE; x.ln_round_assign(Exact); }); } #[test] fn test_ln_prec_round() { let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (ln, o) = x.clone().ln_prec_round(prec, rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, o_out); let (ln_alt, o_alt) = x.ln_prec_round_ref(prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let mut ln_alt = x.clone(); let o_alt = ln_alt.ln_prec_round_assign(prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_ln, rug_o) = rug_ln_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test("-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal); test("0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal); test( "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal); test( "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal); test("1.0", "0x1.0#1", 1, Floor, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Floor, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 10, Exact, "0.0", "0x0.0", Equal); test("-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, Floor, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Exact, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Floor, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Exact, "0.0", "0x0.0", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Exact, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", 1, Floor, "4.0", "0x4.0#1", Less); test("123.0", "0x7b.0#7", 1, Ceiling, "8.0", "0x8.0#1", Greater); test("123.0", "0x7b.0#7", 1, Down, "4.0", "0x4.0#1", Less); test("123.0", "0x7b.0#7", 1, Up, "8.0", "0x8.0#1", Greater); test("123.0", "0x7b.0#7", 1, Nearest, "4.0", "0x4.0#1", Less); test("123.0", "0x7b.0#7", 10, Floor, "4.805", "0x4.ce#10", Less); test( "123.0", "0x7b.0#7", 10, Ceiling, "4.81", "0x4.d0#10", Greater, ); test("123.0", "0x7b.0#7", 10, Down, "4.805", "0x4.ce#10", Less); test("123.0", "0x7b.0#7", 10, Up, "4.81", "0x4.d0#10", Greater); test( "123.0", "0x7b.0#7", 10, Nearest, "4.81", "0x4.d0#10", Greater, ); test("-123.0", "-0x7b.0#7", 1, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "1.145", "0x1.250#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "1.146", "0x1.258#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "1.145", "0x1.250#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "1.146", "0x1.258#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "1.145", "0x1.250#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, Floor, "8.0e-31", "0x1.0E-25#1", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, Floor, "1.576e-30", "0x1.ff8E-25#10", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, Ceiling, "2.0e-30", "0x2.0E-25#1", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, Ceiling, "1.578e-30", "0x2.00E-25#10", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, Down, "8.0e-31", "0x1.0E-25#1", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, Down, "1.576e-30", "0x1.ff8E-25#10", Less, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, Up, "2.0e-30", "0x2.0E-25#1", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, Up, "1.578e-30", "0x2.00E-25#10", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 1, Nearest, "2.0e-30", "0x2.0E-25#1", Greater, ); test( "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", 10, Nearest, "1.578e-30", "0x2.00E-25#10", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, Floor, "-3.0e-30", "-0x4.0E-25#1", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, Floor, "-1.581e-30", "-0x2.01E-25#10", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, Ceiling, "-2.0e-30", "-0x2.0E-25#1", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, Ceiling, "-1.578e-30", "-0x2.00E-25#10", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, Down, "-2.0e-30", "-0x2.0E-25#1", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, Down, "-1.578e-30", "-0x2.00E-25#10", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, Up, "-3.0e-30", "-0x4.0E-25#1", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, Up, "-1.581e-30", "-0x2.01E-25#10", Less, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 1, Nearest, "-2.0e-30", "-0x2.0E-25#1", Greater, ); test( "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", 10, Nearest, "-1.578e-30", "-0x2.00E-25#10", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, Floor, "0.5", "0x0.8#1", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, Floor, "0.999", "0x0.ffc#10", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, Ceiling, "1.0", "0x1.0#1", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, Ceiling, "1.0", "0x1.000#10", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, Down, "0.5", "0x0.8#1", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, Down, "0.999", "0x0.ffc#10", Less, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, Up, "1.0", "0x1.0#1", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, Up, "1.0", "0x1.000#10", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 1, Nearest, "1.0", "0x1.0#1", Greater, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", 10, Nearest, "1.0", "0x1.000#10", Greater, ); } #[test] fn ln_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).ln_prec_round(0, Floor)); assert_panic!(Float::one_prec(1).ln_prec_round_ref(0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.ln_prec_round_assign(0, Floor) }); assert_panic!(THREE.ln_prec_round(1, Exact)); assert_panic!(THREE.ln_prec_round_ref(1, Exact)); assert_panic!({ let mut x = THREE; x.ln_prec_round_assign(1, Exact) }); } #[test] fn test_ln_rational_prec() { let test = |s, prec, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (ln, o) = Float::ln_rational_prec(u.clone(), prec); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); let (ln, o) = Float::ln_rational_prec_ref(&u, prec); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); }; test("0", 1, "-Infinity", "-Infinity", Equal); test("0", 10, "-Infinity", "-Infinity", Equal); test("0", 100, "-Infinity", "-Infinity", Equal); test("1", 1, "0.0", "0x0.0", Equal); test("1", 10, "0.0", "0x0.0", Equal); test("1", 100, "0.0", "0x0.0", Equal); test("1/2", 1, "-0.5", "-0x0.8#1", Greater); test("1/2", 10, "-0.693", "-0x0.b18#10", Less); test( "1/2", 100, "-0.693147180559945309417232121458", "-0x0.b17217f7d1cf79abc9e3b3980#100", Greater, ); test("1/3", 1, "-1.0", "-0x1.0#1", Greater); test("1/3", 10, "-1.098", "-0x1.190#10", Greater); test( "1/3", 100, "-1.098612288668109691395245236922", "-0x1.193ea7aad030a976a4198d550#100", Greater, ); test("22/7", 1, "1.0", "0x1.0#1", Less); test("22/7", 10, "1.145", "0x1.250#10", Less); test( "22/7", 100, "1.14513230430300254837382295598", "0x1.2527640493137b5c5ee7165de#100", Greater, ); let test_big = |u: Rational, prec, out, out_hex, out_o| { let (ln, o) = Float::ln_rational_prec(u.clone(), prec); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); let (ln, o) = Float::ln_rational_prec_ref(&u, prec); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); }; test_big( Rational::power_of_2(1000i64), 10, "693.0", "0x2b5.0#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, "-693.0", "-0x2b5.0#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "-7.44e8", "-0x2.c6E+7#10", Less, ); } #[test] fn ln_rational_prec_fail() { assert_panic!(Float::ln_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::ln_rational_prec(Rational::ONE, 0)); assert_panic!(Float::ln_rational_prec(Rational::NEGATIVE_ONE, 0)); } #[test] fn ln_rational_prec_ref_fail() { assert_panic!(Float::ln_rational_prec_ref(&Rational::ZERO, 0)); assert_panic!(Float::ln_rational_prec_ref(&Rational::ONE, 0)); assert_panic!(Float::ln_rational_prec_ref(&Rational::NEGATIVE_ONE, 0)); } #[test] fn test_ln_rational_prec_round_xxx() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (ln, o) = Float::ln_rational_prec_round(u.clone(), prec, rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); let (ln, o) = Float::ln_rational_prec_round_ref(&u, prec, rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); }; test("0", 1, Floor, "-Infinity", "-Infinity", Equal); test("0", 1, Ceiling, "-Infinity", "-Infinity", Equal); test("0", 1, Down, "-Infinity", "-Infinity", Equal); test("0", 1, Up, "-Infinity", "-Infinity", Equal); test("0", 1, Nearest, "-Infinity", "-Infinity", Equal); test("0", 1, Exact, "-Infinity", "-Infinity", Equal); test("0", 10, Floor, "-Infinity", "-Infinity", Equal); test("0", 10, Ceiling, "-Infinity", "-Infinity", Equal); test("0", 10, Down, "-Infinity", "-Infinity", Equal); test("0", 10, Up, "-Infinity", "-Infinity", Equal); test("0", 10, Nearest, "-Infinity", "-Infinity", Equal); test("0", 10, Exact, "-Infinity", "-Infinity", Equal); test("0", 100, Floor, "-Infinity", "-Infinity", Equal); test("0", 100, Ceiling, "-Infinity", "-Infinity", Equal); test("0", 100, Down, "-Infinity", "-Infinity", Equal); test("0", 100, Up, "-Infinity", "-Infinity", Equal); test("0", 100, Nearest, "-Infinity", "-Infinity", Equal); test("0", 100, Exact, "-Infinity", "-Infinity", Equal); test("1", 1, Floor, "0.0", "0x0.0", Equal); test("1", 1, Ceiling, "0.0", "0x0.0", Equal); test("1", 1, Down, "0.0", "0x0.0", Equal); test("1", 1, Up, "0.0", "0x0.0", Equal); test("1", 1, Nearest, "0.0", "0x0.0", Equal); test("1", 1, Exact, "0.0", "0x0.0", Equal); test("1", 10, Floor, "0.0", "0x0.0", Equal); test("1", 10, Ceiling, "0.0", "0x0.0", Equal); test("1", 10, Down, "0.0", "0x0.0", Equal); test("1", 10, Up, "0.0", "0x0.0", Equal); test("1", 10, Nearest, "0.0", "0x0.0", Equal); test("1", 10, Exact, "0.0", "0x0.0", Equal); test("1", 100, Floor, "0.0", "0x0.0", Equal); test("1", 100, Ceiling, "0.0", "0x0.0", Equal); test("1", 100, Down, "0.0", "0x0.0", Equal); test("1", 100, Up, "0.0", "0x0.0", Equal); test("1", 100, Nearest, "0.0", "0x0.0", Equal); test("1", 100, Exact, "0.0", "0x0.0", Equal); test("1/2", 1, Floor, "-1.0", "-0x1.0#1", Less); test("1/2", 1, Ceiling, "-0.5", "-0x0.8#1", Greater); test("1/2", 1, Down, "-0.5", "-0x0.8#1", Greater); test("1/2", 1, Up, "-1.0", "-0x1.0#1", Less); test("1/2", 1, Nearest, "-0.5", "-0x0.8#1", Greater); test("1/2", 10, Floor, "-0.693", "-0x0.b18#10", Less); test("1/2", 10, Ceiling, "-0.692", "-0x0.b14#10", Greater); test("1/2", 10, Down, "-0.692", "-0x0.b14#10", Greater); test("1/2", 10, Up, "-0.693", "-0x0.b18#10", Less); test("1/2", 10, Nearest, "-0.693", "-0x0.b18#10", Less); test( "1/2", 100, Floor, "-0.693147180559945309417232121459", "-0x0.b17217f7d1cf79abc9e3b3981#100", Less, ); test( "1/2", 100, Ceiling, "-0.693147180559945309417232121458", "-0x0.b17217f7d1cf79abc9e3b3980#100", Greater, ); test( "1/2", 100, Down, "-0.693147180559945309417232121458", "-0x0.b17217f7d1cf79abc9e3b3980#100", Greater, ); test( "1/2", 100, Up, "-0.693147180559945309417232121459", "-0x0.b17217f7d1cf79abc9e3b3981#100", Less, ); test( "1/2", 100, Nearest, "-0.693147180559945309417232121458", "-0x0.b17217f7d1cf79abc9e3b3980#100", Greater, ); test("1/3", 1, Floor, "-2.0", "-0x2.0#1", Less); test("1/3", 1, Ceiling, "-1.0", "-0x1.0#1", Greater); test("1/3", 1, Down, "-1.0", "-0x1.0#1", Greater); test("1/3", 1, Up, "-2.0", "-0x2.0#1", Less); test("1/3", 1, Nearest, "-1.0", "-0x1.0#1", Greater); test("1/3", 10, Floor, "-1.1", "-0x1.198#10", Less); test("1/3", 10, Ceiling, "-1.098", "-0x1.190#10", Greater); test("1/3", 10, Down, "-1.098", "-0x1.190#10", Greater); test("1/3", 10, Up, "-1.1", "-0x1.198#10", Less); test("1/3", 10, Nearest, "-1.098", "-0x1.190#10", Greater); test( "1/3", 100, Floor, "-1.098612288668109691395245236924", "-0x1.193ea7aad030a976a4198d552#100", Less, ); test( "1/3", 100, Ceiling, "-1.098612288668109691395245236922", "-0x1.193ea7aad030a976a4198d550#100", Greater, ); test( "1/3", 100, Down, "-1.098612288668109691395245236922", "-0x1.193ea7aad030a976a4198d550#100", Greater, ); test( "1/3", 100, Up, "-1.098612288668109691395245236924", "-0x1.193ea7aad030a976a4198d552#100", Less, ); test( "1/3", 100, Nearest, "-1.098612288668109691395245236922", "-0x1.193ea7aad030a976a4198d550#100", Greater, ); test("22/7", 1, Floor, "1.0", "0x1.0#1", Less); test("22/7", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("22/7", 1, Down, "1.0", "0x1.0#1", Less); test("22/7", 1, Up, "2.0", "0x2.0#1", Greater); test("22/7", 1, Nearest, "1.0", "0x1.0#1", Less); test("22/7", 10, Floor, "1.145", "0x1.250#10", Less); test("22/7", 10, Ceiling, "1.146", "0x1.258#10", Greater); test("22/7", 10, Down, "1.145", "0x1.250#10", Less); test("22/7", 10, Up, "1.146", "0x1.258#10", Greater); test("22/7", 10, Nearest, "1.145", "0x1.250#10", Less); test( "22/7", 100, Floor, "1.145132304303002548373822955979", "0x1.2527640493137b5c5ee7165dc#100", Less, ); test( "22/7", 100, Ceiling, "1.14513230430300254837382295598", "0x1.2527640493137b5c5ee7165de#100", Greater, ); test( "22/7", 100, Down, "1.145132304303002548373822955979", "0x1.2527640493137b5c5ee7165dc#100", Less, ); test( "22/7", 100, Up, "1.14513230430300254837382295598", "0x1.2527640493137b5c5ee7165de#100", Greater, ); test( "22/7", 100, Nearest, "1.14513230430300254837382295598", "0x1.2527640493137b5c5ee7165de#100", Greater, ); test("-1", 1, Floor, "NaN", "NaN", Equal); test("-1", 1, Ceiling, "NaN", "NaN", Equal); test("-1", 1, Down, "NaN", "NaN", Equal); test("-1", 1, Up, "NaN", "NaN", Equal); test("-1", 1, Nearest, "NaN", "NaN", Equal); test("-1", 1, Exact, "NaN", "NaN", Equal); test("-1", 10, Floor, "NaN", "NaN", Equal); test("-1", 10, Ceiling, "NaN", "NaN", Equal); test("-1", 10, Down, "NaN", "NaN", Equal); test("-1", 10, Up, "NaN", "NaN", Equal); test("-1", 10, Nearest, "NaN", "NaN", Equal); test("-1", 10, Exact, "NaN", "NaN", Equal); test("-1", 100, Floor, "NaN", "NaN", Equal); test("-1", 100, Ceiling, "NaN", "NaN", Equal); test("-1", 100, Down, "NaN", "NaN", Equal); test("-1", 100, Up, "NaN", "NaN", Equal); test("-1", 100, Nearest, "NaN", "NaN", Equal); test("-1", 100, Exact, "NaN", "NaN", Equal); test("-1/2", 1, Floor, "NaN", "NaN", Equal); test("-1/2", 1, Ceiling, "NaN", "NaN", Equal); test("-1/2", 1, Down, "NaN", "NaN", Equal); test("-1/2", 1, Up, "NaN", "NaN", Equal); test("-1/2", 1, Nearest, "NaN", "NaN", Equal); test("-1/2", 1, Exact, "NaN", "NaN", Equal); test("-1/2", 10, Floor, "NaN", "NaN", Equal); test("-1/2", 10, Ceiling, "NaN", "NaN", Equal); test("-1/2", 10, Down, "NaN", "NaN", Equal); test("-1/2", 10, Up, "NaN", "NaN", Equal); test("-1/2", 10, Nearest, "NaN", "NaN", Equal); test("-1/2", 10, Exact, "NaN", "NaN", Equal); test("-1/2", 100, Floor, "NaN", "NaN", Equal); test("-1/2", 100, Ceiling, "NaN", "NaN", Equal); test("-1/2", 100, Down, "NaN", "NaN", Equal); test("-1/2", 100, Up, "NaN", "NaN", Equal); test("-1/2", 100, Nearest, "NaN", "NaN", Equal); test("-1/2", 100, Exact, "NaN", "NaN", Equal); test("-1/3", 1, Floor, "NaN", "NaN", Equal); test("-1/3", 1, Ceiling, "NaN", "NaN", Equal); test("-1/3", 1, Down, "NaN", "NaN", Equal); test("-1/3", 1, Up, "NaN", "NaN", Equal); test("-1/3", 1, Nearest, "NaN", "NaN", Equal); test("-1/3", 10, Floor, "NaN", "NaN", Equal); test("-1/3", 10, Ceiling, "NaN", "NaN", Equal); test("-1/3", 10, Down, "NaN", "NaN", Equal); test("-1/3", 10, Up, "NaN", "NaN", Equal); test("-1/3", 10, Nearest, "NaN", "NaN", Equal); test("-1/3", 100, Floor, "NaN", "NaN", Equal); test("-1/3", 100, Ceiling, "NaN", "NaN", Equal); test("-1/3", 100, Down, "NaN", "NaN", Equal); test("-1/3", 100, Up, "NaN", "NaN", Equal); test("-1/3", 100, Nearest, "NaN", "NaN", Equal); test("-22/7", 1, Floor, "NaN", "NaN", Equal); test("-22/7", 1, Ceiling, "NaN", "NaN", Equal); test("-22/7", 1, Down, "NaN", "NaN", Equal); test("-22/7", 1, Up, "NaN", "NaN", Equal); test("-22/7", 1, Nearest, "NaN", "NaN", Equal); test("-22/7", 10, Floor, "NaN", "NaN", Equal); test("-22/7", 10, Ceiling, "NaN", "NaN", Equal); test("-22/7", 10, Down, "NaN", "NaN", Equal); test("-22/7", 10, Up, "NaN", "NaN", Equal); test("-22/7", 10, Nearest, "NaN", "NaN", Equal); test("-22/7", 100, Floor, "NaN", "NaN", Equal); test("-22/7", 100, Ceiling, "NaN", "NaN", Equal); test("-22/7", 100, Down, "NaN", "NaN", Equal); test("-22/7", 100, Up, "NaN", "NaN", Equal); test("-22/7", 100, Nearest, "NaN", "NaN", Equal); let test_big = |u: Rational, prec, rm, out, out_hex, out_o| { let (ln, o) = Float::ln_rational_prec_round(u.clone(), prec, rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); let (ln, o) = Float::ln_rational_prec_round_ref(&u, prec, rm); assert!(ln.is_valid()); assert_eq!(ln.to_string(), out); assert_eq!(to_hex_string(&ln), out_hex); assert_eq!(o, out_o); }; test_big( Rational::power_of_2(1000i64), 10, Floor, "693.0", "0x2b5.0#10", Less, ); test_big( Rational::power_of_2(1000i64), 10, Ceiling, "694.0", "0x2b6.0#10", Greater, ); test_big( Rational::power_of_2(1000i64), 10, Down, "693.0", "0x2b5.0#10", Less, ); test_big( Rational::power_of_2(1000i64), 10, Up, "694.0", "0x2b6.0#10", Greater, ); test_big( Rational::power_of_2(1000i64), 10, Nearest, "693.0", "0x2b5.0#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Floor, "7.43e8", "0x2.c5E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Ceiling, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Down, "7.43e8", "0x2.c5E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Up, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Nearest, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Floor, "7.43e8", "0x2.c5E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Down, "7.43e8", "0x2.c5E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Up, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Nearest, "7.44e8", "0x2.c6E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Floor, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Ceiling, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Down, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Up, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Nearest, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Floor, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Ceiling, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Down, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Up, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Nearest, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Floor, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Ceiling, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Down, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Up, "1.0e9", "0x4.0E+7#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Nearest, "5.0e8", "0x2.0E+7#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, Floor, "-694.0", "-0x2b6.0#10", Less, ); test_big( Rational::power_of_2(-1000i64), 10, Ceiling, "-693.0", "-0x2b5.0#10", Greater, ); test_big( Rational::power_of_2(-1000i64), 10, Down, "-693.0", "-0x2b5.0#10", Greater, ); test_big( Rational::power_of_2(-1000i64), 10, Up, "-694.0", "-0x2b6.0#10", Less, ); test_big( Rational::power_of_2(-1000i64), 10, Nearest, "-693.0", "-0x2b5.0#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "-7.43e8", "-0x2.c5E+7#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "-7.44e8", "-0x2.c6E+7#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "-7.44e8", "-0x2.c6E+7#10", Less, ); } #[test] fn ln_rational_prec_round_fail() { assert_panic!(Float::ln_rational_prec_round(Rational::ZERO, 0, Floor)); assert_panic!(Float::ln_rational_prec_round(Rational::ONE, 0, Floor)); assert_panic!(Float::ln_rational_prec_round( Rational::from(123u32), 1, Exact )); assert_panic!(Float::ln_rational_prec_round( Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::ln_rational_prec_round( Rational::NEGATIVE_ONE, 0, Floor )); } #[test] fn ln_rational_prec_round_ref_fail() { assert_panic!(Float::ln_rational_prec_round_ref(&Rational::ZERO, 0, Floor)); assert_panic!(Float::ln_rational_prec_round_ref(&Rational::ONE, 0, Floor)); assert_panic!(Float::ln_rational_prec_round_ref( &Rational::from(123u32), 1, Exact )); assert_panic!(Float::ln_rational_prec_round_ref( &Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::ln_rational_prec_round_ref( &Rational::NEGATIVE_ONE, 0, Floor )); } #[allow(clippy::needless_pass_by_value)] fn ln_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode) { let (ln, o) = x.clone().ln_prec_round(prec, rm); assert!(ln.is_valid()); let (ln_alt, o_alt) = x.ln_prec_round_ref(prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.ln_prec_round_assign(prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_ln, rug_o) = rug_ln_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); } if x >= 0u32 && x.is_finite() { assert!(ln < x); } if ln.is_normal() { assert_eq!(ln.get_prec(), Some(prec)); if x > 1u32 && o > Less { assert!(ln > 0u32); } else if x < 1u32 && o < Greater { assert!(ln < 0u32); } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.ln_prec_round_ref(prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(ln.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.ln_prec_round_ref(prec, Exact)); } } #[test] fn ln_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_19().test_properties(|(x, prec, rm)| { ln_prec_round_properties_helper(x, prec, rm); }); float_unsigned_rounding_mode_triple_gen_var_20().test_properties(|(x, prec, rm)| { ln_prec_round_properties_helper(x, prec, rm); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { let (ln, o) = Float::NAN.ln_prec_round(prec, rm); assert!(ln.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.ln_prec_round(prec, rm), (Float::INFINITY, Equal) ); let (s, o) = Float::NEGATIVE_INFINITY.ln_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); assert_eq!( Float::ZERO.ln_prec_round(prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_ZERO.ln_prec_round(prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!(Float::ONE.ln_prec_round(prec, rm), (Float::ZERO, Equal)); let (s, o) = Float::NEGATIVE_ONE.ln_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn ln_prec_properties_helper(x: Float, prec: u64) { let (ln, o) = x.clone().ln_prec(prec); assert!(ln.is_valid()); let (ln_alt, o_alt) = x.ln_prec_ref(prec); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.ln_prec_assign(prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), prec, Nearest); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o); let (rug_ln, rug_o) = rug_ln_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); let (ln_alt, o_alt) = x.ln_prec_round_ref(prec, Nearest); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); if x >= 0u32 && x.is_finite() { assert!(ln < x); } if ln.is_normal() { assert_eq!(ln.get_prec(), Some(prec)); if x > 1u32 && o > Less { assert!(ln > 0u32); } else if x < 1u32 && o < Greater { assert!(ln < 0u32); } } } #[test] fn ln_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { ln_prec_properties_helper(x, prec); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { ln_prec_properties_helper(x, prec); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { ln_prec_properties_helper(x, prec); }); unsigned_gen_var_11().test_properties(|prec| { let (ln, o) = Float::NAN.ln_prec(prec); assert!(ln.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::ZERO.ln_prec(prec), (Float::NEGATIVE_INFINITY, Equal)); assert_eq!( Float::NEGATIVE_ZERO.ln_prec(prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!(Float::INFINITY.ln_prec(prec), (Float::INFINITY, Equal)); let (ln, o) = Float::NEGATIVE_INFINITY.ln_prec(prec); assert_eq!(ComparableFloat(ln), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); assert_eq!(Float::ONE.ln_prec(prec), (Float::ZERO, Equal)); let (ln, o) = Float::NEGATIVE_ONE.ln_prec(prec); assert_eq!(ComparableFloat(ln), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn ln_round_properties_helper(x: Float, rm: RoundingMode) { let (ln, o) = x.clone().ln_round(rm); assert!(ln.is_valid()); let (ln_alt, o_alt) = x.ln_round_ref(rm); assert!(ln_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); let mut x_alt = x.clone(); let o_alt = x_alt.ln_round_assign(rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let (ln_alt, o_alt) = x.ln_prec_round_ref(x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); if x >= 0u32 && x.is_finite() { assert!(ln < x); } if ln.is_normal() { assert_eq!(ln.get_prec(), Some(x.get_prec().unwrap())); if x > 1u32 && o > Less { assert!(ln > 0u32); } else if x < 1u32 && o < Greater { assert!(ln < 0u32); } } let (ln_alt, o_alt) = ln_prec_round_extended(x.clone(), x.get_prec().unwrap_or(1), rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln), ComparableFloatRef(&ln_alt)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_ln, rug_o) = rug_ln_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); assert_eq!(rug_o, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.ln_round_ref(rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(ln.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.ln_round_ref(Exact)); } } #[test] fn ln_round_properties() { float_rounding_mode_pair_gen_var_34().test_properties(|(x, rm)| { ln_round_properties_helper(x, rm); }); float_rounding_mode_pair_gen_var_35().test_properties(|(x, rm)| { ln_round_properties_helper(x, rm); }); rounding_mode_gen().test_properties(|rm| { let (ln, o) = Float::NAN.ln_round(rm); assert!(ln.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::ZERO.ln_round(rm), (Float::NEGATIVE_INFINITY, Equal)); assert_eq!( Float::NEGATIVE_ZERO.ln_round(rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!(Float::INFINITY.ln_round(rm), (Float::INFINITY, Equal)); let (ln, o) = Float::NEGATIVE_INFINITY.ln_round(rm); assert_eq!(ComparableFloat(ln), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); assert_eq!(Float::ONE.ln_round(rm), (Float::ZERO, Equal)); let (ln, o) = Float::NEGATIVE_ONE.ln_round(rm); assert_eq!(ComparableFloat(ln), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn ln_properties_helper(x: Float) { let ln = x.clone().ln(); assert!(ln.is_valid()); let ln_alt = (&x).ln(); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); let mut x_alt = x.clone(); x_alt.ln_assign(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&ln)); let ln_alt = x.ln_prec_round_ref(x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); let ln_alt = x.ln_prec_ref(x.significant_bits()).0; assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); let ln_alt = x.ln_round_ref(Nearest).0; assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); if x >= 0u32 && x.is_finite() { assert!(ln < x); } let ln_alt = ln_prec_round_extended(x.clone(), x.get_prec().unwrap_or(1), Nearest).0; assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); let rug_ln = rug_ln(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln)), ComparableFloatRef(&ln), ); } #[test] fn ln_properties() { float_gen().test_properties(|x| { ln_properties_helper(x); }); float_gen_var_12().test_properties(|x| { ln_properties_helper(x); }); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_ln() { fn test(x: T, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { assert_eq!(NiceFloat(primitive_float_ln(x)), NiceFloat(out)); } test::(f32::NAN, f32::NAN); test::(f32::INFINITY, f32::INFINITY); test::(f32::NEGATIVE_INFINITY, f32::NAN); test::(0.0, f32::NEGATIVE_INFINITY); test::(-0.0, f32::NEGATIVE_INFINITY); test::(1.0, 0.0); test::(-1.0, f32::NAN); test::(0.5, -std::f32::consts::LN_2); test::(-0.5, f32::NAN); test::(2.0, std::f32::consts::LN_2); test::(-2.0, f32::NAN); test::(core::f32::consts::PI, 1.14473); test::(-core::f32::consts::PI, f32::NAN); test::(core::f32::consts::E, 0.99999994); test::(-core::f32::consts::E, f32::NAN); test::(f64::NAN, f64::NAN); test::(f64::INFINITY, f64::INFINITY); test::(f64::NEGATIVE_INFINITY, f64::NAN); test::(0.0, f64::NEGATIVE_INFINITY); test::(-0.0, f64::NEGATIVE_INFINITY); test::(1.0, 0.0); test::(-1.0, f64::NAN); test::(0.5, -std::f64::consts::LN_2); test::(-0.5, f64::NAN); test::(2.0, std::f64::consts::LN_2); test::(-2.0, f64::NAN); test::(core::f64::consts::PI, 1.1447298858494002); test::(-core::f64::consts::PI, f64::NAN); test::(core::f64::consts::E, 1.0); test::(-core::f64::consts::E, f64::NAN); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_ln_properties_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { primitive_float_ln(x); }); } #[test] fn primitive_float_ln_properties() { apply_fn_to_primitive_floats!(primitive_float_ln_properties_helper); } #[allow(clippy::needless_pass_by_value)] fn ln_rational_prec_round_properties_helper(x: Rational, prec: u64, rm: RoundingMode) { let (ln, o) = Float::ln_rational_prec_round(x.clone(), prec, rm); assert!(ln.is_valid()); let (ln_alt, o_alt) = Float::ln_rational_prec_round_ref(&x, prec, rm); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); if x != 0u32 { let (ln_alt, o_alt) = Float::ln_rational_prec_round((&x).reciprocal(), prec, -rm); assert!(ln_alt.is_valid()); assert_eq!( ComparableFloatRef(&(-ln_alt).abs_negative_zero()), ComparableFloatRef(&ln.abs_negative_zero_ref()) ); assert_eq!(o_alt.reverse(), o); } if x >= 0u32 { assert!(ln < x); } if ln.is_normal() { assert_eq!(ln.get_prec(), Some(prec)); if x > 1u32 && o > Less { assert!(ln > 0u32); } else if x < 1u32 && o < Greater { assert!(ln < 0u32); } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::ln_rational_prec_round_ref(&x, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(ln.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::ln_rational_prec_round_ref(&x, prec, Exact)); } } #[test] fn ln_rational_prec_round_properties() { rational_unsigned_rounding_mode_triple_gen_var_6().test_properties(|(x, prec, rm)| { ln_rational_prec_round_properties_helper(x, prec, rm); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { assert_eq!( Float::ln_rational_prec_round(Rational::ZERO, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::ln_rational_prec_round(Rational::ONE, prec, rm), (Float::ZERO, Equal) ); let (s, o) = Float::ln_rational_prec_round(Rational::NEGATIVE_ONE, prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn ln_rational_prec_properties_helper(x: Rational, prec: u64) { let (ln, o) = Float::ln_rational_prec(x.clone(), prec); assert!(ln.is_valid()); let (ln_alt, o_alt) = Float::ln_rational_prec_ref(&x, prec); assert!(ln_alt.is_valid()); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); let (ln_alt, o_alt) = Float::ln_rational_prec_round_ref(&x, prec, Nearest); assert_eq!(ComparableFloatRef(&ln_alt), ComparableFloatRef(&ln)); assert_eq!(o_alt, o); if x != 0u32 { let (ln_alt, o_alt) = Float::ln_rational_prec((&x).reciprocal(), prec); assert!(ln_alt.is_valid()); assert_eq!( ComparableFloatRef(&(-ln_alt).abs_negative_zero()), ComparableFloatRef(&ln.abs_negative_zero_ref()) ); assert_eq!(o_alt.reverse(), o); } if x >= 0u32 { assert!(ln < x); } if ln.is_normal() { assert_eq!(ln.get_prec(), Some(prec)); if x > 1u32 && o > Less { assert!(ln > 0u32); } else if x < 1u32 && o < Greater { assert!(ln < 0u32); } } } #[test] fn ln_rational_prec_properties() { rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { ln_rational_prec_properties_helper(x, prec); }); unsigned_gen_var_11().test_properties(|prec| { assert_eq!( Float::ln_rational_prec(Rational::ZERO, prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::ln_rational_prec(Rational::ONE, prec), (Float::ZERO, Equal) ); let (ln, o) = Float::ln_rational_prec(Rational::NEGATIVE_ONE, prec); assert_eq!(ComparableFloat(ln), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_ln_rational() { fn test(s: &str, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { let u = Rational::from_str(s).unwrap(); assert_eq!(NiceFloat(primitive_float_ln_rational(&u)), NiceFloat(out)); } test::("0", f32::NEGATIVE_INFINITY); test::("1", 0.0); test::("1/2", -std::f32::consts::LN_2); test::("1/3", -1.0986123); test::("22/7", 1.1451323); test::("1000000", 13.815511); test::("1/1000000", -13.815511); test::("-1", f32::NAN); test::("-1/2", f32::NAN); test::("-1/3", f32::NAN); test::("-22/7", f32::NAN); test::("0", f64::NEGATIVE_INFINITY); test::("1", 0.0); test::("1/2", -std::f64::consts::LN_2); test::("1/3", -1.0986122886681098); test::("22/7", 1.1451323043030026); test::("1000000", 13.815510557964274); test::("1/1000000", -13.815510557964274); test::("-1", f64::NAN); test::("-1/2", f64::NAN); test::("-1/3", f64::NAN); test::("-22/7", f64::NAN); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_ln_rational_properties_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { rational_gen().test_properties(|x| { let y = primitive_float_ln_rational::(&x); if x != 0u32 { assert_eq!( NiceFloat(primitive_float_ln_rational(&x.reciprocal()).abs_negative_zero()), NiceFloat((-y).abs_negative_zero()) ); } }); } #[test] fn primitive_float_ln_rational_properties() { apply_fn_to_primitive_floats!(primitive_float_ln_rational_properties_helper); } ================================================ FILE: malachite-float/tests/arithmetic/mul.rs ================================================ // Copyright © 2026 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 core::cmp::{ Ordering::{self, *}, max, }; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::arithmetic::mul::{ mul_rational_prec_round_direct, mul_rational_prec_round_direct_ref_ref, mul_rational_prec_round_direct_ref_val, mul_rational_prec_round_direct_val_ref, mul_rational_prec_round_naive, mul_rational_prec_round_naive_ref_ref, mul_rational_prec_round_naive_ref_val, mul_rational_prec_round_naive_val_ref, }; use malachite_float::emulate_float_float_to_float_fn; use malachite_float::test_util::arithmetic::mul::{ mul_prec_round_naive, rug_mul, rug_mul_prec, rug_mul_prec_round, rug_mul_rational, rug_mul_rational_prec, rug_mul_rational_prec_round, rug_mul_rational_round, rug_mul_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_16, float_float_rounding_mode_triple_gen_var_17, float_float_rounding_mode_triple_gen_var_18, float_float_rounding_mode_triple_gen_var_19, float_float_rounding_mode_triple_gen_var_20, float_float_rounding_mode_triple_gen_var_21, float_float_rounding_mode_triple_gen_var_22, float_float_rounding_mode_triple_gen_var_31, float_float_unsigned_rounding_mode_quadruple_gen_var_3, float_float_unsigned_rounding_mode_quadruple_gen_var_7, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_2, float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, float_pair_gen_var_5, float_pair_gen_var_6, float_pair_gen_var_7, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_4, float_rational_rounding_mode_triple_gen_var_9, float_rational_unsigned_rounding_mode_quadruple_gen_var_3, float_rational_unsigned_rounding_mode_quadruple_gen_var_8, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_2, float_rounding_mode_pair_gen, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mul() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let product = x.clone() * y.clone(); assert!(product.is_valid()); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); let product_alt = x.clone() * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &x * y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &x * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let mut product_alt = x.clone(); product_alt *= y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let mut product_alt = x.clone(); product_alt *= &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_mul( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef(&product) ); let product_alt = mul_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("NaN", "NaN", "1.0", "0x1.0#1", "NaN", "NaN"); test("NaN", "NaN", "-1.0", "-0x1.0#1", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test( "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("Infinity", "Infinity", "0.0", "0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "-0.0", "-0x0.0", "NaN", "NaN"); test( "Infinity", "Infinity", "1.0", "0x1.0#1", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", "-Infinity", "-Infinity", ); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "Infinity", "Infinity", ); test("-Infinity", "-Infinity", "0.0", "0x0.0", "NaN", "NaN"); test("-Infinity", "-Infinity", "-0.0", "-0x0.0", "NaN", "NaN"); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", "Infinity", "Infinity", ); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test("0.0", "0x0.0", "Infinity", "Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "-Infinity", "-Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "-0.0", "-0x0.0", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "1.0", "0x1.0#1", "0.0", "0x0.0"); test("0.0", "0x0.0", "-1.0", "-0x1.0#1", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test("-0.0", "-0x0.0", "Infinity", "Infinity", "NaN", "NaN"); test("-0.0", "-0x0.0", "-Infinity", "-Infinity", "NaN", "NaN"); test("-0.0", "-0x0.0", "0.0", "0x0.0", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "1.0", "0x1.0#1", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-1.0", "-0x1.0#1", "0.0", "0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", "Infinity", "Infinity", ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", "-Infinity", "-Infinity", ); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "0.0", "0x0.0"); test("123.0", "0x7b.0#7", "-0.0", "-0x0.0", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "1.0", "0x1.0#1", "123.0", "0x7b.0#7"); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", "-123.0", "-0x7b.0#7", ); test("NaN", "NaN", "123.0", "0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "123.0", "0x7b.0#7", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "123.0", "0x7b.0#7", "-0.0", "-0x0.0"); test("1.0", "0x1.0#1", "123.0", "0x7b.0#7", "123.0", "0x7b.0#7"); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", "-123.0", "-0x7b.0#7", ); test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "2.0", "0x2.0#1"); test("1.0", "0x1.0#1", "2.0", "0x2.0#2", "2.0", "0x2.0#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "2.0", "0x2.0#2"); test("1.0", "0x1.0#2", "2.0", "0x2.0#2", "2.0", "0x2.0#2"); test("1.0", "0x1.000#10", "2.0", "0x2.00#10", "2.0", "0x2.00#10"); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "4.442882938158366", "0x4.7160c6b758b90#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-4.442882938158366", "-0x4.7160c6b758b90#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "-4.442882938158366", "-0x4.7160c6b758b90#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "4.442882938158366", "0x4.7160c6b758b90#53", ); // - in mul_float_significands_same_prec_lt_w // - decrement_exp in mul_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "1.0", "0x1.0#1"); // - !decrement_exp in mul_float_significands_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_lt_w // - rm == Nearest in mul_float_significands_same_prec_lt_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (product & shift_bit) == 0)) in // mul_float_significands_same_prec_lt_w test("1.5", "0x1.8#2", "1.5", "0x1.8#2", "2.0", "0x2.0#2"); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (product & shift_bit) != 0) && // product.overflowing_add_assign(shift_bit) in mul_float_significands_same_prec_lt_w test("1.2", "0x1.4#3", "1.5", "0x1.8#3", "2.0", "0x2.0#3"); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (product & shift_bit) != 0) && // !product.overflowing_add_assign(shift_bit) in mul_float_significands_same_prec_lt_w test("1.2", "0x1.4#4", "1.4", "0x1.6#4", "1.8", "0x1.c#4"); // - in mul_float_significands_same_prec_w // - decrement_exp in mul_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_w // - rm == Nearest in mul_float_significands_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in // mul_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000002", "0x1.0000000000000004#64", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.even()) && // !product.overflowing_add_assign(1) in mul_float_significands_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", "7.8519772600462495573e-34", "0x4.13b4f0d218450fb0E-28#64", "2.569913924134929736e-70", "0x1.c610823e5a4c0774E-58#64", ); // - !decrement_exp in mul_float_significands_same_prec_w test( "3116635254961129.0696", "0xb1290314433e9.11d#64", "7.092177112370390978e-10", "0x3.0bcb09ebbb50e418E-8#64", "2210372.9222841977617", "0x21ba44.ec1ad133010#64", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.even()) && // product.overflowing_add_assign(1) in mul_float_significands_same_prec_w test( "1.9999999999999999998", "0x1.fffffffffffffffc#64", "2.0000000000000000002", "0x2.0000000000000004#64", "4.0", "0x4.0000000000000000#64", ); // - in mul_float_significands_same_prec_gt_w_lt_2w // - l.wrapping_add(2) & (mask >> 2) <= 2 in mul_float_significands_same_prec_gt_w_lt_2w // - decrement_exp in mul_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in mul_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in // mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000011", "0x1.0000000000000002#65", ); // - l.wrapping_add(2) & (mask >> 2) > 2 in mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000022", "0x1.0000000000000004#65", ); // - !decrement_exp in mul_float_significands_same_prec_gt_w_lt_2w test( "0.0001507756106295330606262754053", "0x0.0009e19851127b95dcf03f0cdc#91", "3458.565842843038054059107814", "0xd82.90db1399862ba513faf8#91", "0.5214673768571047372764465276", "0x0.857ee2d1883c6e783c18b1e#91", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in mul_float_significands_same_prec_gt_w_lt_2w test( "119368.6474438890389479272222539538", "0x1d248.a5bee1f96ad66a5061314f7#109", "1.573235366444334767515689608501749e-6", "0x0.00001a64fe94215b4ea1a015983c92bc#109", "0.1877949778033513768632732912065661", "0x0.301354e804b87d40aa80cfe1472a#109", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && overflow // in mul_float_significands_same_prec_gt_w_lt_2w test( "295147905179352825855.999999999999999997", "0xfffffffffffffffff.ffffffffffffffc#127", "0.000244140625000000000000000000000000000003", "0x0.00100000000000000000000000000000004#127", "72057594037927936.0", "0x100000000000000.000000000000000000#127", ); // - in mul_float_significands_same_prec_gt_2w_lt_3w // - a0.wrapping_add(4) & (mask >> 2) <= 4 in mul_float_significands_same_prec_gt_2w_lt_3w // - decrement_exp in mul_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && z_0 & shift_bit == 0)) in // mul_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", ); // - a0.wrapping_add(4) & (mask >> 2) > 4 in mul_float_significands_same_prec_gt_2w_lt_3w // - !decrement_exp in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in // mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow // in mul_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", "0.00497732823382322348141815797577421539704054126", "0x0.014631b5fc58aeb12d61fe8ebe2fa3511f34a8b#149", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && overflow in // mul_float_significands_same_prec_gt_2w_lt_3w test( "1.9999999999999999999999999999999999999993", "0x1.ffffffffffffffffffffffffffffffffc#132", "2.0000000000000000000000000000000000000007", "0x2.000000000000000000000000000000004#132", "4.0", "0x4.000000000000000000000000000000000#132", ); test("1.5", "0x1.8#2", "1.2", "0x1.4#3", "2.0", "0x2.0#3"); // - in mul_float_significands_general // - xs_len <= 2 in mul_float_significands_general // - xs_len == 1 in mul_float_significands_general // - b1 == 0 first time in mul_float_significands_general // - !goto_full_multiply second time in mul_float_significands_general // - in round_helper_raw // - !increment_exp in mul_float_significands_general test("1.0", "0x1.0#1", "1.0", "0x1.0#2", "1.0", "0x1.0#2"); // - xs_hi[0] & ulp != 0 in round_helper_raw // - increment in round_helper_raw // - increment_exp in mul_float_significands_general test("1.5", "0x1.8#2", "1.2", "0x1.4#3", "2.0", "0x2.0#3"); // - b1 != 0 first time in mul_float_significands_general // - xs_hi[0] & ulp == 0 in round_helper_raw test("1.5", "0x1.8#2", "1.5", "0x1.8#3", "2.0", "0x2.0#3"); // - !increment in round_helper_raw test("1.5", "0x1.8#2", "1.1", "0x1.2#4", "1.8", "0x1.c#4"); // - xs_len != 1 && ys_len == 1 in mul_float_significands_general test( "21729783659306408649613509.686", "0x11f975eebbcb21a32ee0c5.af8#95", "4.140691354e21", "0xe.077a2d0E+17#30", "8.9976327319036285762104654629e46", "0xf.c2ad952d9bedaa8c340fb5cE+38#95", ); // - xs_len <= 2 || ys_len <= MPFR_MUL_THRESHOLD in mul_float_significands_general // - goto_full_multiply second time in mul_float_significands_general // - b1 != 0 third time in mul_float_significands_general test( "3.29008365861415556134836580980448399733562188e-9", "0xe.217c389f8c9fd22042f5ed70da20cfb9f1ecE-8#146", "3719044561792922503530448846362960.3599330496921301151502834994", "0xb75cf116bc625ef1eab58f3c9950.5c2492852d5fb6817443c180#205", "12235967738412737409453496.5112769496822945381768578702376539566", "0xa1f1123e59edd22860db8.82e30bd21587183f065c6eea9383ac0#205", ); // - b1 == 0 third time in mul_float_significands_general test( "0.152", "0x0.27#6", "0.000677250271462116637219538246676594845637468375", "0x0.002c625fc46315b1256e735851ab2413f0230460#149", "0.0001031748460430568314514140297671374960150830727", "0x0.0006c2fc96eb184dfcb3d3927471127f099555aa8#149", ); // - xs_len != 1 && ys_len != 1 in mul_float_significands_general test( "3.600675849075089170455453502457566", "0x3.99c5e47746483e1e72f35153c9e#109", "7.042716356117671710991084962952371e-31", "0xe.48c9931f0a6ce474caf85ca810deE-26#116", "2.5358538695359015660810037702729442e-30", "0x3.36ee7f4e42c0edeaa7100c9586414E-25#116", ); // - xs_len > 2 && ys_len > MPFR_MUL_THRESHOLD in mul_float_significands_general // - (xs[0] != 0 || xs[1] != 0) && (ys[0] != 0 || ys[1] != 0) in mul_float_significands_general // - out_prec > p - 5 in mul_float_significands_general // - out_prec > p - 5 + Limb::WIDTH || xs_len <= threshold + 1 in mul_float_significands_general // - in limbs_float_mul_high_same_length // - n >= MPFR_MULHIGH_TAB.len() in limbs_float_mul_high_same_length // - n <= MUL_FFT_THRESHOLD in limbs_float_mul_high_same_length // - n < MPFR_MULHIGH_TAB.len() in limbs_float_mul_high_same_length // - MPFR_MULHIGH_TAB[n] != -1 in limbs_float_mul_high_same_length // - k == Some(0) in limbs_float_mul_high_same_length // - in limbs_float_mul_high_same_length_basecase // - b1 != 0 second time in mul_float_significands_general // - !limbs_float_can_round in mul_float_significands_general // - goto_full_multiply first time in mul_float_significands_general test( "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ 62431384255329048179650372924700507846477189871631671161154559755984562472291", "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", "11691360406839692866118328.82160678934697449148561930623262244451953109076390937578282165\ 187539508530274103471810974014544850101997980642382746362536485174905201106566021759334671\ 038084134174395853704847978726074297598470143399522515598459659231845311084194915852728366\ 056422715218301245062324603756166217017490819881851715545101168897106488715462344820352976\ 259754023729090781152750099501504576567751861133292449402560554539891918302651799386455549\ 657664547443484522197757542024159371062990161647359586646799536699319711548827677391665966\ 287279197599493918294842951008826029536226825832854955685587903267919852682540903329229694\ 700736024127943619726831445160555949561747552032983921128094877425217970278847326632273418\ 407484077549236662570769286015075277220777908237436835596208190640803687131540850535115913\ 655954830695789298058473415611731503722972733488269283706021704532728574584684669676341549\ 292252804245357342748316615826715707101522402518116062329441651970107805707342168691626509\ 305758570985170639749549248022366152944291484173783280217974452532323709041672239778485037\ 294723948248639908579195768663906666012983129167763644004221520737884980923091163080707988\ 588422464078838824212171802847408608047867571127753377657964788586031325255106000694013614\ 527340915821283801356153178149699147203162830520911097467745909302616153231682263893483275\ 019567006794361076438485306321832725119559578113910632379303074353609691782388847871383450\ 484766163524999863199330839928739926251980847649975020069602105177714848358628397385350021\ 24095735959378409981273751636624594837614456921497122960535259532723503477033", "0x9abbdeae92a7cc75062b8.d254d2926ab47ec2646ac6102bc7f2c66e4adda59ec8c5ced87c449f85121ac94\ 7e79dc78b7313a18f2ce5e38db71d51c990df401764ed1949bc25e2614a9bdb3027efa1acf4ea0e322dfad232e\ cbd31249cc1917bbdffcead4f455598e97f24397ef8bff64f45dfd672a81269c27e03d6cb02da64c33a0af7326\ eb8e21ca7d9003144c8f62cd449d48953249142d7f5afd8112b58223fc36214a7e8c4b9a026eb8ba0dc0dca681\ f9d3c37cf62540e73333f8e07151b6353a7d9d6ad54f935a33c049acbf7c6e4e80629250c603ad3a070a43d3f9\ 70a8c5d99edacc2b229a04d8bb9f8b71acb7611d4e6c4a3e4330466403e5422746189403976a41698df939ffc0\ 32b31da3e6493f1393fd89226bf6b4eadf296725de20aac599c96edd2a445c9d689fee07ae5e94997f00659560\ 27632aa2cbfceba0ad1dcfeb7fb56c3a038718044af027a05c55e79d87a581fe5887ab1630360a4ddf22f18f4d\ 250a5385c3b6ee351d8d368543ed65e80461de207d9d924e8595b146d24defa8dbd01358a44fdf639ae28a852e\ 7675001a1c34c22013db15e7527ad9b7064b49c21ba11b7ed42ac9a570c006de5a092e84450d553767a5e2bb57\ f588dd1a63559f4b5bf0f0b1eda574f319b65c5c97023caf2862a4487c403143538931bdaba7e1fd57d1d07dc4\ 613f75769c70427af74a7af461be5b0126125aa40920e4e9b44a9e28616dc9ca7b77624028a0ed40aaed08486d\ 90086f51f501e47b6f5e0f7391a8320f07d62774d2c29f3abfc9f71514e3bc471ff2041ede5c0fb4ad39572ab8\ 6909d5a368ef66086eed3f37dad57f14ec6362b1b9567a687e771330ec416265c437c3e6d3c3136aedfe753577\ 319aed775fdefcbe6ff046d9f93acca0d253617b9b98b73f7e7fc043ad2e5f9ae06754e4df0f8#5329", ); // - out_prec <= p - 5 + Limb::WIDTH && xs_len > threshold + 1 in mul_float_significands_general // - xs_len > len in mul_float_significands_general // - k < len << 1 in mul_float_significands_general // - b1 == 0 second time in mul_float_significands_general // - !goto_full_multiply first time in mul_float_significands_general test( "0.000505125560873134723723784766950092518997332731967301291698755707702902596942317437852\ 941942371960388246351631317879977557751125153730732708319124734660713981958784935850223006\ 317900579689594830566320680544405297096706330277372404179805722699177498153458710988448597\ 667865038489642478166853872591228283694673924060010690084057961646317421857676637869623134\ 589158734829608080525671151880734425152367375882305121472858495571639962287931732234443489\ 588015865732596365983920824372468289009819493599234552103162449485200505569599322042323513\ 171853918367347759762125056867136354464299283595190704290061720089955391730926571989543650\ 123824756", "0x0.00211a99c3aab8ff53e9907564934b7d8b29ea0189ec9cd3d1a74407e1344b68fcd1809f4234bfef08c0c\ 3f89af1fe509093292b5b157eded4009179fedceae065ab0dd9d53b35a4ce7f1d190711e92618f7d0b216ce0bd\ 09e9c6f6625bcc6003ad38389decfb93a34f29b624c9c3c24dd825a59d15423602847fb2fe248d2b631514d4ed\ f610fd7088faa3f59c46a406f42343787142069c527e5b0aa730ef1f4054d887515ccd31c4f04063d57d8645a7\ b70fd198011231617f8b64344b5d43eb951d0a8ebfe39606336b443b19074cd641a63b4656b6e71133e47c099e\ 1fed7bc661252f72ee2c68b5cf9db6ee0645b455fb007e9d294c3a5e091df7f92b6268fff2e65b109ec#2100", "1.594827021209513894575272853189101796908969657496052553026904808146944132849277331696165\ 366066982899056554189139962942976395082328192559670863685439930018276703216617917370998670\ 143663891402542565265723410284904517798491873969116076521737839809230852429183992755715781\ 991743918659448701680599805386273131215689278489918563344703836788128584757613316503273812\ 347176374414975252562793531554358724296424942636927017522952046066543039832692600611375088\ 044395866209370211970587133626417624012062511750942538348241762511210915523305672594074841\ 5529943020302456665999104875220004206872624343740835605816652e-79", "0x4.ba3e1591f6a0ae18e8a750107efc0ca278b3954588d15a3695387227774da4319070b249d295916c24713\ 070f060a0df67ad5c2e8cc350d13189bcbf73f9af1e33fe42bf44fe99164bf802f7a5f41fe2d28377f1932b019\ a00373f4400d62f20693ce9fbe239afbc3c804face7c59fb40fe03be617f14dd6880b31ff429280aafe8ea5d94\ c3349efe67683ab81b8b5f4d00925073051d872bde743109c8e7c79da2c5fff9f489b12c271aa83405fe1d99c2\ 9f846c6b1c71dec233f13240569b3015559ed53bda719283585ed3f94bdeaea4d8438fe90e633bb97ee755eb88\ 113450187e9b05d8e6040fa53e6a10b6dcc2f01463a3937f5a90E-66#1988", "8.055878935840864338761112052964131694842078144914087985110265043132694138227764882097467\ 485603629304908508159498533271385147841989466565220242546894501115782558008761861379571521\ 691942027516784202151149343065118307142127390742346695428089929852244559471690807529077258\ 667004534037323942848543095527661248910413746226405479291587579546107337446543923963731652\ 263604834014601264189816875633028978567676911887046995279630281027980542407933148412976200\ 257662826354908783390381610432026516882234795071151533161797811544609495678329417798803859\ 814384620434259660366163853727351148214688205975873187006097686502581917099916584703699137\ 7927e-83", "0x9.c7fc20220e43b5ac1717bf3fc467495e7a66c020cb393887e4bf4a3ad3eb4f20763507aea5b673c5aff25\ 8525ec5ac9bbc9f5c976983bce6231282e951654f346e3e5f7779ecdeae718176d55b03e21297ae13b32728a38\ 30c19eb847a199cde2fd0f3aa2330282fc433000c5f99b14022cd881da6b7caa98d3563644c4710ec876c4b61c\ b15fdd4cc7d712644bad3a66e844700eafebabf02dead4fd71d95a14ef9c6a12db9092cf7b4723f45cb086b401\ 8123e185be43126baa17ab68fd32a0834023652a003d24211dd87066d2d5b1f0f1993c0dd9756329316927dd98\ 425ba5d470abc9065c6ff724d0e16c68152314d36e37d235fe078572e42d94540fe4418a9440633E-69#2100", ); // - MPFR_MULHIGH_TAB[n] == -1 in limbs_float_mul_high_same_length // - k.is_none() in limbs_float_mul_high_same_length test( "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ 3791636230633361526548302742414616516594455084620537903358416e-16", "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ 3a2e81ad38c5d7f45687a8E-13#2587", "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ 61698637621752755004821872e-17", "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ d817f0420227841d34052ed2bd52e148923f8E-15#1571", "5.713957232680308157039243396854396365207579750474509016836068310655183904589399398864949\ 369194427543435776465300666190725186454505340683874976519507548279996486761744005041118935\ 948747589743699350970808906395296086217435990867715483224265504817855574934867156151545781\ 106814865537845359234760816964504042844539777879186641559132734209465852287196566458935778\ 830300266229578325422723437672411534085537936547389438107265754858071594639985760821104661\ 940648845072022419465943642338099526948876829384943161258695569354371632958134560717841147\ 840574265292252548747529841143166165808068071464187327019844718180901133673499079508336221\ 530763161764985656092293178070670798408664087435197003752408586649867017671653317949434498\ 7804832149608135310831412140057788625216612318872425368846162e-33", "0x1.dab26e4414e016457a3b64d6dc588a9f2a4cbec7acd1a5b9033e00168a27a1ac3f669e39332cdbace29d9\ b5d727df53a041f44f1389d6fda544d07799d35a62fbf327a55fca19ed803e80954753bfb12dcfda81be99eda5\ 2d7a382f6dd0ac26ab4b55fa3587bc812156b0ddb289357e7300ea3dafa43cee4f98c4068d3ffbeceea4a01ecc\ 74a09b85289f4c37000efab1e07926e01496cf6855b4a1f08915fff56a1737ff1d109fb6f3011fb249b88db85f\ 52980590101cbaa0e8af5872ded15ef0f39ec69d2d19d45c2972793e60bbb6eee9b673f24b3318973256a8e9bc\ 90d40f033e145dc56a6caa7e542a2701c0a41519fd0ef8d97ed0cef3e4296de50e877edeae80c0dd91f9082539\ 71e8998ef2a91d865baa5aa565e308789af81b128e8d0e832f5368e689962335ca7077ad875ea20eae1f2fc375\ a972b8e7b8e285bbe3bdb0E-27#2587", ); // - xs_len <= len in mul_float_significands_general // - limbs_float_can_round in mul_float_significands_general test( "2791656999165.493196894581080462482671477586959884065253358835066410305633620155930725019\ 490863414181814174955842522364865024774379310519058136940369290858518517313460149216061827\ 231421960818181308820010416988884966114071973567666857448623899431042502611223036510238920\ 700493077403107131238955287441775846760482666068674778697270732066126184067657756561516984\ 251159820991198761865419427067747698722303345927460124328666182849055120607788400162794652\ 0878157328543259919881", "0x289fbb948fd.7e4226d4b6e97c4ccb64c2a072193f46e582b56e431d1d873706fd936c5e3328fd5b164ebe6\ f6c3319057366a2de168eaef87f67644a657027f176fb9d5deaa62912e24d9b1eebf67a642c7ebc91e95eba928\ d2c47f45ab981a3053c2a055e2a36102f8c4b2c72f24edbf87122ddff42408c1c95b6eccee7c0a49a25e2fe2fd\ 67a0dfc9d33ccad11d273f88f3e5a176da6b5989e6fc247727a58af5ef0f3a863e35d59edceb1ed0401bb2ce98\ 77227cdff6442212230b17fb43a061516c#1558", "2418611879271263.303076595070873673412348926925363768438166046534014463089969421888804109\ 398849144724043021994927400943502019398552005514731676646297869532250197280910814394530400\ 370821284006890204265425587260634300563572770382580394115150082129924900080499709146475799\ 383767996765000283568589472197582158015457869515972738606414178902063354061536898088295371\ 641586286472920893106777705320869713042818435525510767840203306234890813618032983465299395\ 730347727963352100742341245602143", "0x897b6f5e9db5f.4d966d80032f1615c15b6d17e02b100d2d97b52de1b561199b3dbeda9276bc25c5519d480\ c2c20f52155b94074ad9db0bd7a97dae0337b738b6709c5fdd1bbcf1492bef975c393313e477790485d0a4ed0f\ 8790d9d469d65c29122cd019f7ff423e0f74c0585cac3aa85ceee8cbd256a201e23dd78f6dc402aa36b5a053ea\ c1a3b2c435ae84ee9942bec1d88e41507bee030c35cd3f18b2f7a5c9193976d7418a633e08ca4923be03a2dc93\ 6ed64c6ff04ace32f44aa72f58bf488b9bf31c4c03f#1596", "6751934781032429031553446805.854936199324254228337806577049209187291041079391491758652444\ 360751832908394550062618692018471995917689775126406303977393164343146088816585483538887454\ 027840163444916716206473736192766508247978473183426254779355642987433462433675113794019449\ 629515518752711445976665575431349720824019816455254142652806744349728110370084378693365847\ 376950483953541149499814845310185214082773221620162084856311318860928357827312318714828967\ 076794760533141841485387490188815", "0x15d111cde75ec690f0fb3395.dadd194843a336fd8b04fc1edf686f76aa52a00d00db09b133bcedaa832e64\ e3cbe80e635c5bb60e81bb4cb3839dc581a1f683d480b6757136ace3d394264c5f969b75cb4d985b4b2b1096d2\ a53a6d6570c7f7c917bed4f2a9c8f7bcdea046337457665b27e5e01bdbce6f20c6d5bc9e463f055cca9b0c53a2\ f1f5b6d7211ac001a5fa99daf3378815db2c7bc77c6d6b76f815ae464fdc70ae82752dbe2b5683cc1ebc18275d\ 4685cbd35d58b70dbda84d2297ff9a12d20f2283678e#1596", ); // - out_prec <= p - 5 in mul_float_significands_general test( "7.449979045041702122541548973189889723858373710052883535770432677692650998750696470703091\ 744255868088920360332810996981821635561095981209970543165990341865465399250649125818133550\ 345620227288485003961432095280508748897878683743133302349812547742789930883805941444651209\ 784236601329970891014476723035066837590220224883282604585022340111695027909185310636007609\ 680407882966239499164648695501638941698641158401193435378725738878261400237405551514713128\ 836982995938875007304023367379668047357772772649359285993284186179803252277e-21", "0x2.32e78d682285335802e277865ca4c9a80daafb30e4f67daedb2f466845a2fba5d9b1c96b068c42999ae0b\ 463fb94e578b359027630c01a995d88a74b72186c316ec30a8b4238fb27273b57cc5e72fa518fa14032e99af11\ e1d5ccfc1217be504bf8dae0d1ec7e885fc95b51f444d68ed47eb588644910e4196d65104707dcd1c488a22e9c\ 1ef05ce85b3823fd6aa2bb7ad7d14fa1da7a628e1ba344d98ad7e95bf7e01883afc84273614fb8387e4035b2d9\ ad867bc2be83eaabaa44df896348f52d4972bc5e8cf58f1cfd421cc30920d9f5504a043149274f5E-17#1738", "4.689598630661113758052361654518074651900718126313070505518580809308545656249466966444734\ 190644625007707301196274229099309347916384836732990153197811248723616418486524781737017155\ 222220872736570797023388780311017887508289881051954626904239986311860650999175535050592519\ 124458883175586921775053060798371665433755864916689805023189965297596140362143269558535567\ 196585839368205277548820051354051306095222442551993791324926248616628216018709202221063695\ 130497558241752004759655263919857509980778615592531001107310020150056419e-20", "0xd.d75c4c85ded4dada979685c90590eb9f191595aa1862df62f276fa75d5d790d2c00d187fe126b806534fd\ 0379dfcf600aeee23bbe00ed5955cc2e11b7de967da0c347d3ca03714f55b714dbe2c9ad31dbd7b6fb9a639fa4\ da6cec918f3fc77bbca5ded28446186fe8b4224339c0722fed5f69b2d07571b12f4cce6fece51fc63ab46ea7fe\ 5c1f350ed6aab2c76a1e817bf652a9c77a95e3e3c107ed65e9ace86dfec217fb9dcbba544e3d84b0f3cac6c221\ 176c57f1db9bc306f22db85308dab755243a502d385e1b0a31f2f8c2d53c98729cfe52f82289cE-17#1730", "3.493741152808155821061780436862260285420312736969910829282351541785101293399126489805777\ 980187532032743650816868281893520821921299562434265222876601442289649987508199259232837158\ 559068445030886433472805552651673239073165198885867344396236299229232184802565958836951408\ 637905144866851014091996571320623346167534428281388860566996500707311335172658622534949254\ 838518529528764394710349462443386828046760610922770501616700810546292498376696602122491857\ 8540047731481736443609736067164917894729323015869507020379275317039780244947e-40", "0x1.e6f4d9986216e186a3b15da557e0677276dd590e3d92a71ff89974ad2abac1a1e2e3dc761157b14cfef04\ 285b10c4bf2f72117bbdbdfd5ead95a5ed69f62f69682442a59a3f3c8a5a7b41238f0a029b2d53c54a08053451\ 35f5fc0a67464283bade3997992eea966997d442d69987820628966dfcaa6d25ca0be2df6ed92e5fa5201002da\ 70c6447c3a8a64ebd34fc04156c8dbd224d772ba1059982a5aa333d301a708dc568330bdead12245127d520b32\ b4e7d9ae221552ab3d3f5f2f139c90118fe830b6adc84392948585b40267beb9fd60cce93fbed140E-33#1738", ); // - xs[0] == 0 && xs[1] == 0 || ys[0] == 0 && ys[1] == 0 in mul_float_significands_general // - xs[xs_offset] == 0 in mul_float_significands_general // - ys[ys_offset] == 0 in mul_float_significands_general test( "4.44089209850062616169452667236328125e-16", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000E-13#2587", "6.938893903907228377647697925567627621275394370123920756842177449687616281576087749649243\ 449560881562252974476503855378704420289043275360540974361356347799301147460937500000000000\ 428087763478203718701697872488500162623204828539850902982930587576291943616315378569169353\ 840957917417166522314320167278698048638040260019989045715363127222769643922793712163996851\ 225018060026136483495536368092685586468682354268058778363979622204058653592623442621394947\ 3239996744456973724770155e-18", "0x8.0000000000000000000000000003fff000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fe00000000000000000000000000000000000E-15#1571", "3.081487911019577364889564708135884006379343333980678546187704758135879626468817238227001\ 919863959483626636205013163029555487554952753086708205626001498966504653625325671484347367\ 558282010814620352468694740583510310926487120637351903244174605756585424927747220355720149\ 705262186320261062950329818867477826244378862350354462458385252797818784708103173459291235\ 769538479528034217611825504020777438216019896385615152551542382665798426796321259955655479\ 300773291504754679549289638268112862439028560817297535629039872109954348969232817790940901\ 772925125639499661447304917621775611916484032847611462965461660088172016929375670794716891\ 215288121297398166137896866022540415673603027116093396582728756514564426357106145459651571\ 0636500728956428014332817951864653686798458732591874037159276e-33", "0x1.00000000000000000000000000007ffe00000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000E-27#2587", ); // - xs[xs_offset] != 0 in mul_float_significands_general test( "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ 1249731874464215297923136674027554116062077582682832144200801849365234375", "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000038180485e-31", "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000001ffffffeE-26#2567", "1.577721810442023610823457130565572459346412870218046009540557861328124999999781992456191\ 582683140605249728137786969774247203293102032637435297463867968227730622206111553159326620\ 257748727154917100482837417166916131758491078680030585867783733868391940878208953914079279\ 677271330675596139325733702207799069583415985107421875000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000001527219401e-30", "0x1.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000007ffffff8E-25#2567", ); // - ys[ys_offset] != 0 in mul_float_significands_general test( "3.552713678800500929355621337890625000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000185653473271011701515143789632334288014147578747413968011889263434165\ 454031003144878632958696545103828379944287431463737771314691776232764018029744516848435369\ 906941507005331339097431189921414095915636548343770290467007831930064077297413615608072068\ 77626957251331627162116234578193867366731943186452308784033031e-15", "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffE-12#1693", "131071.9999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999931137299504668061215619580033350122879947175743013377219720120678876536\ 628643562946337394277177628286886258713868752206334184193331360816755408598724051586961746\ 685495576886231160425736851019484652776925452038003143395027472798288565900387988918967170\ 024140096215282631707814129061246845336549291242702672707242154281040996134116689237194330\ 449329247059466983779402165943011772702916829761392820351107526820413839207822952585392346\ 328868866364548445701244431290159307431187837005854773744122693182105660536394809595147776\ 165023610906858577556273686957594781817444085841499342583068122729709267291", "0x1ffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffc0000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000#2930", "4.656612873077392578125000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000243339720485780457409929267946893197985903514415810436152543495368429\ 343907516442055321546973277589582124346598388556070043505489984826143425305512049232107258\ 133592644143603087675038065556842214758248268059151846952539521827810268928481776834311731\ 044052486308720793745225556140061733844701779522496735016181906708106564202059526039890815\ 919178696765989061598664073635409369732679923290228161362302668920197866351570235145652815\ 456445767888399222146130209012884306181795683184194476165898983356347814975458163826496169\ 408195862006279548822773547655683272930717806964759394377376260006554734212838956379338694\ 525902352837865322055484704841599472083306918235788680977972181745262154636e-10", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffdffffffffffffffffffffff\ fffffffffffffffffff80000000000000000000000000000000008000000000000000000000000000000000000\ 000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffdfffffffffffc0000000000000000004000000000000000000000000000000000000000000000000000000\ 00080000000000000E-8#2930", ); test( "12962368.00910437392826314193446550944389165836262015621514962112057577196019471161937054\ 243429475140935082492484312458697139062031326336320065697050792374770657213779646419924892\ 886900897092216274606911219143642483069838857046000551685989850622347518286427108428594195\ 826642547794926862213089792293539194572777838215978068770604450325322408918968488729618206\ 83239161602000658143319869428", "0xc5ca40.0254aa0c45bef8b7e5bdc2c8d0bc3f4ef77512b0c665764acef9797020852473fed6cf5aef7ab76f\ af4e7ccca7674b7b9a7d4e3adf7dbd2f9c51a93c8b500f9c6e799811cc9793ad3189530f5202900aed04c32d98\ 72075f4a8efb28f1e3d9e2065d70be0df4f07d46d4f2f48b95a6fcd718d2f233dbbaff41296fe46efd00783168\ f9da607a651780d29e9357c1d8e9abdd149e2d7ed04e74488fff360#1283", "24678125950611051118469790273997953293778953666881566874553684447233373952852192.03220118\ 824573657786267791510531425783997288827451260529832388036858875235909753308200751110173525\ 014519161498781309811156911488470099945303550175018037705473098495478288721507648423524330\ 255884870759432606723320831807670552582364423881930823507999308667398128596287742877235432\ 154091338959855861235089997932459245142831892", "0xd51fdc4e02742b528c90f8a31146dcba3e1273bfdd1198ff1ec486c97e52f8c0e0.083e564a6864272a5d52\ 74cbdf67db38b72e576e7cfe8be5418f583cf4173a82939f37d7b6b399cada03434a24aef04a65323c333b33cf\ 622583787d8ec1f247c4f691c3a7862628783f4322923b6bb9434902754e348fb74eb6364e294832597785e445\ 1994ee48803ea5771d85e7f226166cdd1853477f296076996b97965596455eb50129#1336", "319886950346849155967554337687681180827634107405044558954903133134156000777816460853971.0\ 571286460940042331570995057120143779176892645683546163312322051333969186064059757999062545\ 749424646225780605680908775358827191384406475576071818545005626321659954666901446716884049\ 318512517659256499382137861718683137930417158199590725586222075459373218000006096544204046\ 600400863088080659996213042623116710817104536", "0xa4a9e4f5c54093e3388df17b55e5724251f90cd6c231443e4bc0d5770919a2c1878982d3.0e9ffba2a37526\ 7ffbc880a862170226c003dcfce47863efaa79493245f971642ca10409a10ad584de1597974f309b61313528bd\ 1512f14b2397a5630d41d067d57d9b327d751eacb350f8e13428d4508849e4464775e72f3b4fb63d6bef2d97b6\ f0118aa022becb98c8c88fdcb280078abcbe4c3b8423dc1dfc91e6b09ea9115cd0cd#1336", ); test( "0.853553390593273762200422181052424519642417968844237018294169934497683119615526759712596\ 883581910393183753461557728074256231209013962684303161030374274983957853305666481876398188\ 949987625288195515142867527389992901492568633649215503682129354660222299652388082307621077\ 178580362709940650906998812851997421813349136582952207410155153814588098763686437571939990\ 432458893805084382964252838593650852124711790096724992674751203757636006947579113561955767\ 12323422965539514461577789916717825325390464224680930882212731621531237", "0x0.da827999fcef32422cbec4d9baa55f4f8eb7b05d449dd426768bd642c199cc8aa57e41821d5c5161d458f\ f37ee41ed9c87ba542f21ce3da53c02439b1efd13b469101743a1578fa72982ce3008de19bde558de488b4422c\ 523055e3917be2719e36ad451c5dbf4ee659531a198f9e426fa978907c1b72c1775525044c8206525409ca55b6\ c7e877efa69d01675e49f0621326d5e6a945b28dc679a0db7c11b6380826e00ff191a9799952f4fbded0f5ffb5\ 0df1fe5110983ef503120fbd540e160fe5eef517bee198c41c51757faf9d96927a53b1fd65c#1719", "0.853553390593273762200422181052424519642417968844237018294169934497683119615526759712596\ 883581910393183753461557728074256231209013962684303161030374274983957853305666481876398188\ 949987625288195515142867527389992901492568633649215503682129354660222299652388082307621077\ 178580362709940650906998812851997421813349136582952207410155153814588098763686437571939990\ 432458893805084382964252838593650852124711790096724992674751203757636006947579113561955767\ 12323422965539514461577789916717825325390464224680930882212731621531237", "0x0.da827999fcef32422cbec4d9baa55f4f8eb7b05d449dd426768bd642c199cc8aa57e41821d5c5161d458f\ f37ee41ed9c87ba542f21ce3da53c02439b1efd13b469101743a1578fa72982ce3008de19bde558de488b4422c\ 523055e3917be2719e36ad451c5dbf4ee659531a198f9e426fa978907c1b72c1775525044c8206525409ca55b6\ c7e877efa69d01675e49f0621326d5e6a945b28dc679a0db7c11b6380826e00ff191a9799952f4fbded0f5ffb5\ 0df1fe5110983ef503120fbd540e160fe5eef517bee198c41c51757faf9d96927a53b1fd65c#1719", "0.728553390593273762200422181052424519642417968844237018294169934497683119615526759712596\ 883581910393183753461557728074256231209013962684303161030374274983957853305666481876398188\ 949987625288195515142867527389992901492568633649215503682129354660222299652388082307621077\ 178580362709940650906998812851997421813349136582952207410155153814588098763686437571939990\ 432458893805084382964252838593650852124711790096724992674751203757636006947579113561955767\ 12323422965539514461577789916717825325390464224680930882212731621531237", "0x0.ba827999fcef32422cbec4d9baa55f4f8eb7b05d449dd426768bd642c199cc8aa57e41821d5c5161d458f\ f37ee41ed9c87ba542f21ce3da53c02439b1efd13b469101743a1578fa72982ce3008de19bde558de488b4422c\ 523055e3917be2719e36ad451c5dbf4ee659531a198f9e426fa978907c1b72c1775525044c8206525409ca55b6\ c7e877efa69d01675e49f0621326d5e6a945b28dc679a0db7c11b6380826e00ff191a9799952f4fbded0f5ffb5\ 0df1fe5110983ef503120fbd540e160fe5eef517bee198c41c51757faf9d96927a53b1fd65c#1719", ); } #[test] fn test_mul_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (product, o) = x.clone().mul_prec(y.clone(), prec); assert!(product.is_valid()); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); assert_eq!(o, o_out); let (product_alt, o_alt) = x.clone().mul_prec_val_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_prec_ref_val(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_prec_ref_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_prec_assign(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_prec_assign_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = mul_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product), ); assert_eq!(o_alt, o); let (rug_product, rug_o) = rug_mul_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "1.0", "0x1.0#1", 1, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, "-0.0", "-0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, "0.0", "0x0.0", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 10, "123.0", "0x7b.0#10", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 10, "-123.0", "-0x7b.0#10", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, "123.0", "0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, "-123.0", "-0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, "2.0", "0x2.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "4.445", "0x4.72#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-4.0", "-0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "4.0", "0x4.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "4.445", "0x4.72#10", Greater, ); test( "1.4134592e-8", "0x3.cb5260E-7#24", "3.7164162e-37", "0x7.e768d0E-31#24", 2, "6.0e-45", "0x2.0E-37#2", Greater, ); test( "1.5", "0x1.8#2", "1.5", "0x1.8#2", 3, "2.0", "0x2.0#3", Less, ); test( "-6.5933e-41", "-0x5.be5cE-34#17", "too_small", "0x1.abfd74a88E-268435431#34", 68, "-0.0", "-0x0.0", Greater, ); } #[test] fn mul_prec_fail() { assert_panic!(Float::NAN.mul_prec(Float::NAN, 0)); assert_panic!(Float::NAN.mul_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.mul_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.mul_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.mul_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.mul_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_mul_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (product, o) = x.clone().mul_round(y.clone(), rm); assert!(product.is_valid()); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); assert_eq!(o, o_out); let (product_alt, o_alt) = x.clone().mul_round_val_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_round_ref_val(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_round_ref_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_round_assign(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_round_assign_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } let (product_alt, o_alt) = mul_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "1.0", "0x1.0#1", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", Exact, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Floor, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Ceiling, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Down, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Up, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Nearest, "-123.0", "-0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", Exact, "-123.0", "-0x7b.0#7", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "123.0", "0x7b.0#7", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123.0", "0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "123.0", "0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", Exact, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Floor, "-123.0", "-0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Ceiling, "-123.0", "-0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Down, "-123.0", "-0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Up, "-123.0", "-0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Nearest, "-123.0", "-0x7b.0#7", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", Exact, "-123.0", "-0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Floor, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Ceiling, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Down, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Up, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Nearest, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", Exact, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Floor, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Ceiling, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Down, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Up, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Nearest, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Exact, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Floor, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Ceiling, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Down, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Up, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Nearest, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", Exact, "2.0", "0x2.0#2", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", Exact, "2.0", "0x2.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "4.442882938158367", "0x4.7160c6b758b94#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "4.442882938158367", "0x4.7160c6b758b94#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-4.442882938158367", "-0x4.7160c6b758b94#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-4.442882938158367", "-0x4.7160c6b758b94#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-4.442882938158367", "-0x4.7160c6b758b94#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "-4.442882938158367", "-0x4.7160c6b758b94#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "-4.442882938158366", "-0x4.7160c6b758b90#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "4.442882938158367", "0x4.7160c6b758b94#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "4.442882938158367", "0x4.7160c6b758b94#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "4.442882938158366", "0x4.7160c6b758b90#53", Less, ); // - rm == Floor || rm == Down in mul_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less, ); // - rm == Ceiling || rm == Up in mul_float_significands_same_prec_lt_w // - (rm == Ceiling || rm == Up) && !product.overflowing_add_assign(shift_bit) in // mul_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.5", "0x1.8#2", Up, "3.0", "0x3.0#2", Greater, ); // - (rm == Ceiling || rm == Up) && product.overflowing_add_assign(shift_bit) in // mul_float_significands_same_prec_lt_w test( "1.2", "0x1.4#3", "1.5", "0x1.8#3", Up, "2.0", "0x2.0#3", Greater, ); // - rm == Floor || rm == Down in mul_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000001", "0x1.0000000000000002#64", Down, "1.0000000000000000002", "0x1.0000000000000004#64", Less, ); // - rm == Ceiling || rm == Up in mul_float_significands_same_prec_w // - (rm == Ceiling || rm == Up) && !product.overflowing_add_assign(1) in // mul_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000001", "0x1.0000000000000002#64", Up, "1.0000000000000000003", "0x1.0000000000000006#64", Greater, ); // - (rm == Ceiling || rm == Up) && product.overflowing_add_assign(1) in // mul_float_significands_same_prec_w test( "1.9999999999999999998", "0x1.fffffffffffffffc#64", "2.0000000000000000002", "0x2.0000000000000004#64", Up, "4.0", "0x4.0000000000000000#64", Greater, ); // - rm == Floor || rm == Down in mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000005", "0x1.0000000000000001#65", Down, "1.00000000000000000011", "0x1.0000000000000002#65", Less, ); // - rm == Ceiling || rm == Up in mul_float_significands_same_prec_gt_w_lt_2w // - (rm == Ceiling || rm == Up) && !overflow in mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000005", "0x1.0000000000000001#65", Up, "1.00000000000000000016", "0x1.0000000000000003#65", Greater, ); // - (rm == Ceiling || rm == Up) && overflow in mul_float_significands_same_prec_gt_w_lt_2w test( "295147905179352825855.999999999999999997", "0xfffffffffffffffff.ffffffffffffffc#127", "0.000244140625000000000000000000000000000003", "0x0.00100000000000000000000000000000004#127", Up, "72057594037927936.0", "0x100000000000000.000000000000000000#127", Greater, ); // - rm == Floor || rm == Down in mul_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Down, "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", Less, ); // - rm == Ceiling || rm == Up in mul_float_significands_same_prec_gt_2w_lt_3w // - (rm == Ceiling || rm == Up) && z_2 != 0 in mul_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Up, "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Greater, ); // - (rm == Ceiling || rm == Up) && z_2 == 0 in mul_float_significands_same_prec_gt_2w_lt_3w test( "1.9999999999999999999999999999999999999993", "0x1.ffffffffffffffffffffffffffffffffc#132", "2.0000000000000000000000000000000000000007", "0x2.000000000000000000000000000000004#132", Up, "4.0", "0x4.000000000000000000000000000000000#132", Greater, ); // - in mul_float_significands_same_prec_lt_w // - decrement_exp in mul_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal, ); // - !decrement_exp in mul_float_significands_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_lt_w // - rm == Nearest in mul_float_significands_same_prec_lt_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (product & shift_bit) == 0)) in // mul_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.5", "0x1.8#2", Nearest, "2.0", "0x2.0#2", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (product & shift_bit) != 0) && // product.overflowing_add_assign(shift_bit) in mul_float_significands_same_prec_lt_w test( "1.2", "0x1.4#3", "1.5", "0x1.8#3", Nearest, "2.0", "0x2.0#3", Greater, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (product & shift_bit) != 0) && // !product.overflowing_add_assign(shift_bit) in mul_float_significands_same_prec_lt_w test( "1.2", "0x1.4#4", "1.4", "0x1.6#4", Nearest, "1.8", "0x1.c#4", Greater, ); // - in mul_float_significands_same_prec_w // - decrement_exp in mul_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "1.0", "0x1.0000000000000000#64", Equal, ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_w // - rm == Nearest in mul_float_significands_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in // mul_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "1.0000000000000000002", "0x1.0000000000000004#64", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.even()) && // !product.overflowing_add_assign(1) in mul_float_significands_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", "7.8519772600462495573e-34", "0x4.13b4f0d218450fb0E-28#64", Nearest, "2.569913924134929736e-70", "0x1.c610823e5a4c0774E-58#64", Greater, ); // - !decrement_exp in mul_float_significands_same_prec_w test( "3116635254961129.0696", "0xb1290314433e9.11d#64", "7.092177112370390978e-10", "0x3.0bcb09ebbb50e418E-8#64", Nearest, "2210372.9222841977617", "0x21ba44.ec1ad133010#64", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.even()) && // product.overflowing_add_assign(1) in mul_float_significands_same_prec_w test( "1.9999999999999999998", "0x1.fffffffffffffffc#64", "2.0000000000000000002", "0x2.0000000000000004#64", Nearest, "4.0", "0x4.0000000000000000#64", Greater, ); // - in mul_float_significands_same_prec_gt_w_lt_2w // - l.wrapping_add(2) & (mask >> 2) <= 2 in mul_float_significands_same_prec_gt_w_lt_2w // - decrement_exp in mul_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "1.0", "0x1.0000000000000000#65", Equal, ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in mul_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0)) in // mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "1.00000000000000000011", "0x1.0000000000000002#65", Less, ); // - l.wrapping_add(2) & (mask >> 2) > 2 in mul_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "1.00000000000000000022", "0x1.0000000000000004#65", Less, ); // - !decrement_exp in mul_float_significands_same_prec_gt_w_lt_2w test( "0.0001507756106295330606262754053", "0x0.0009e19851127b95dcf03f0cdc#91", "3458.565842843038054059107814", "0xd82.90db1399862ba513faf8#91", Nearest, "0.5214673768571047372764465276", "0x0.857ee2d1883c6e783c18b1e#91", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in mul_float_significands_same_prec_gt_w_lt_2w test( "119368.6474438890389479272222539538", "0x1d248.a5bee1f96ad66a5061314f7#109", "1.573235366444334767515689608501749e-6", "0x0.00001a64fe94215b4ea1a015983c92bc#109", Nearest, "0.1877949778033513768632732912065661", "0x0.301354e804b87d40aa80cfe1472a#109", Greater, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && overflow // in mul_float_significands_same_prec_gt_w_lt_2w test( "295147905179352825855.999999999999999997", "0xfffffffffffffffff.ffffffffffffffc#127", "0.000244140625000000000000000000000000000003", "0x0.00100000000000000000000000000000004#127", Nearest, "72057594037927936.0", "0x100000000000000.000000000000000000#127", Greater, ); // - in mul_float_significands_same_prec_gt_2w_lt_3w // - a0.wrapping_add(4) & (mask >> 2) <= 4 in mul_float_significands_same_prec_gt_2w_lt_3w // - decrement_exp in mul_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in mul_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "1.0", "0x1.00000000000000000000000000000000#129", Equal, ); // - round_bit != 0 || sticky_bit != 0 in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && z_0 & shift_bit == 0)) in // mul_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", Less, ); // - a0.wrapping_add(4) & (mask >> 2) > 4 in mul_float_significands_same_prec_gt_2w_lt_3w // - !decrement_exp in mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in // mul_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow // in mul_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Nearest, "0.00497732823382322348141815797577421539704054126", "0x0.014631b5fc58aeb12d61fe8ebe2fa3511f34a8b#149", Greater, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && overflow in // mul_float_significands_same_prec_gt_2w_lt_3w test( "1.9999999999999999999999999999999999999993", "0x1.ffffffffffffffffffffffffffffffffc#132", "2.0000000000000000000000000000000000000007", "0x2.000000000000000000000000000000004#132", Nearest, "4.0", "0x4.000000000000000000000000000000000#132", Greater, ); test( "1.5", "0x1.8#2", "1.2", "0x1.4#3", Nearest, "2.0", "0x2.0#3", Greater, ); // - in mul_float_significands_general // - xs_len <= 2 in mul_float_significands_general // - xs_len == 1 in mul_float_significands_general // - b1 == 0 first time in mul_float_significands_general // - !goto_full_multiply second time in mul_float_significands_general // - in round_helper_raw // - !increment_exp in mul_float_significands_general test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Nearest, "1.0", "0x1.0#2", Equal, ); // - xs_hi[0] & ulp != 0 in round_helper_raw // - increment in round_helper_raw // - increment_exp in mul_float_significands_general test( "1.5", "0x1.8#2", "1.2", "0x1.4#3", Nearest, "2.0", "0x2.0#3", Greater, ); // - b1 != 0 first time in mul_float_significands_general // - xs_hi[0] & ulp == 0 in round_helper_raw test( "1.5", "0x1.8#2", "1.5", "0x1.8#3", Nearest, "2.0", "0x2.0#3", Less, ); // - !increment in round_helper_raw test( "1.5", "0x1.8#2", "1.1", "0x1.2#4", Nearest, "1.8", "0x1.c#4", Greater, ); // - xs_len != 1 && ys_len == 1 in mul_float_significands_general test( "21729783659306408649613509.686", "0x11f975eebbcb21a32ee0c5.af8#95", "4.140691354e21", "0xe.077a2d0E+17#30", Nearest, "8.9976327319036285762104654629e46", "0xf.c2ad952d9bedaa8c340fb5cE+38#95", Less, ); // - xs_len <= 2 || ys_len <= MPFR_MUL_THRESHOLD in mul_float_significands_general // - goto_full_multiply second time in mul_float_significands_general // - b1 != 0 third time in mul_float_significands_general test( "3.29008365861415556134836580980448399733562188e-9", "0xe.217c389f8c9fd22042f5ed70da20cfb9f1ecE-8#146", "3719044561792922503530448846362960.3599330496921301151502834994", "0xb75cf116bc625ef1eab58f3c9950.5c2492852d5fb6817443c180#205", Nearest, "12235967738412737409453496.5112769496822945381768578702376539566", "0xa1f1123e59edd22860db8.82e30bd21587183f065c6eea9383ac0#205", Less, ); // - b1 == 0 third time in mul_float_significands_general test( "0.152", "0x0.27#6", "0.000677250271462116637219538246676594845637468375", "0x0.002c625fc46315b1256e735851ab2413f0230460#149", Nearest, "0.0001031748460430568314514140297671374960150830727", "0x0.0006c2fc96eb184dfcb3d3927471127f099555aa8#149", Less, ); // - xs_len != 1 && ys_len != 1 in mul_float_significands_general test( "3.600675849075089170455453502457566", "0x3.99c5e47746483e1e72f35153c9e#109", "7.042716356117671710991084962952371e-31", "0xe.48c9931f0a6ce474caf85ca810deE-26#116", Nearest, "2.5358538695359015660810037702729442e-30", "0x3.36ee7f4e42c0edeaa7100c9586414E-25#116", Less, ); // - xs_len > 2 && ys_len > MPFR_MUL_THRESHOLD in mul_float_significands_general // - (xs[0] != 0 || xs[1] != 0) && (ys[0] != 0 || ys[1] != 0) in mul_float_significands_general // - out_prec > p - 5 in mul_float_significands_general // - out_prec > p - 5 + Limb::WIDTH || xs_len <= threshold + 1 in mul_float_significands_general // - in limbs_float_mul_high_same_length // - n >= MPFR_MULHIGH_TAB.len() in limbs_float_mul_high_same_length // - n <= MUL_FFT_THRESHOLD in limbs_float_mul_high_same_length // - n < MPFR_MULHIGH_TAB.len() in limbs_float_mul_high_same_length // - MPFR_MULHIGH_TAB[n] != -1 in limbs_float_mul_high_same_length // - k == Some(0) in limbs_float_mul_high_same_length // - in limbs_float_mul_high_same_length_basecase // - b1 != 0 second time in mul_float_significands_general // - !limbs_float_can_round in mul_float_significands_general // - goto_full_multiply first time in mul_float_significands_general test( "3.667390117738159207950705349477719105571949429980976394812181671883945054829509256768693\ 428777428660656941387302685172371854480204626447190818847235223777196475037450938977825246\ 002439873468885558547110470430228085143851019175355894923610792842932340338852051239754427\ 095026930245556704615627992643819617817074019244527799280182728405175259498139200084973400\ 185025632529817381341736837108765891093445296142846875524815723636775475593320258020981988\ 641285509338653295726597545939874976233498010217572353942629414771256828458910867296816672\ 522543163090158525097032013393556880192772591230747507060825723928635133507431423165786715\ 278150157159772706487785219042905040143153742214007713387626849311191420055238664770362170\ 343983987545766271318010394410223132309343859005046365250499465556871672911799580499791909\ 295656508202340485571517780009270726548788594036564495463224892161734462687808109262481368\ 096969794376769660230615691331025217443348007977074560288273633401967130359649250852147512\ 141074330343117535301250887203664127461249846867757356639750473042390297739319749311431157\ 14372183907772936544329974943881256368038028229439176970805917055179180439477409e-9", "0xf.c0568c485e0b826908a56a1e9eed605a795d47bbb3b22b86ff364a5aa967860d79fa907ffa4b598c74ca2\ 768fd610cc65e72d1328231f74c2896a372707f3fffd4713cd781c36ddc8c429a53c9de0a260ab39221aa6723f\ 639d4f0a18f42a39ce148ec18caa8292a2404e421cb5af96a525988ace64d3b66492e8b29b9f1982af075eac7f\ a4c4f560684706f9c92a1babe3a7cedd233045842df3c534b90481e818908a787ba694e61d3bd3d93a45651240\ a1926f3b818e8c51165d9c7c186dd99b0afededda17332acec6e4419ca2c498ecac62e9670b8cc359ac4ce5abb\ e6a858a9ad732af4717655c73ab36f06357d16912bd759fba2c774b33607e2ee49fbf3328842b34b1649846034\ e601a686e91c2040c578ab8676f4c413bc62718b75fe591900b6f10a6ee20a73c59ab3be30fb9a154c1a50b4b5\ d60d7a76de24b93f804302eb4d625df61cf824be4c93189bd500d72fe88443b2e506a11e3b57403b447b8602ef\ 45e256c2e9cbfbc69697901d340ae418d96a38e3f87b38c8ee8b168c15df448ce29060725fff6438c91fd406bf\ 6cf95e07431942e379a50250441c4ed69a634f4e155cb67d47b7b4b285388f957b3809dcfb73606173ca9a64c8\ 9b5ee06f42fc1ee8c752cf947957f346aac01a1e21759f8267f58d36b22e7bd14E-8#3843", "3187923845432148642442057154569059.126715487792372839803386914179538752693826970283207166\ 811288798839227319311871148502823407877176659352907588186871022894787193533982873662011253\ 290757573915501169313819926148549862448642272469031186766746849160076154409190019980289710\ 170792165652792217117270925812431819493193080694795589891807146039351866024622601910524654\ 975993653145125921373829181052606711648254654081125875153947355721451359688668050452670532\ 460418624462017975144128989503732730892234660879379487543472739334395798501406522301770530\ 084261662015482020833397653047706275744771695945820139179975325296925632712346348118093097\ 953095934511815810581175318735500116787412839224213098543182657584610954902591533740060963\ 289805212670558460977431314581393471573332429725647583364688986461335610003995668212280028\ 807977055980202986273442266172236653427698776974320204115552560417196660880213932819325142\ 548937684752935846670101028764484218237392844524558383599287530029421881169570993841163993\ 843829902198804691520255195056203676272889080365643704609455722537324606271987166289767672\ 190663805227886932691226996255254535007618551610966568052639325048438160780381909128343538\ 211967934803057176881479842550254050201767779261994751352264395465646274141983125281497566\ 020553366225193569060382295548356106219949376044134821789228041804290511458952966410365196\ 222090758059421770693182158103609003570428820956594490269060711518240230638460085565864341\ 256289190220580928350048868798606128912317218138793827337661513849296003850300428079774414\ 62431384255329048179650372924700507846477189871631671161154559755984562472291", "0x9d2d417f3ca9f32fea99c6482363.20706d1bf7058f4c6275f668a177cd076adccb2fda12b6ed78a3b56bb5\ 9dfb518b8b3c05c40c48fd5544dac5cf4c4b5097a348e21623af642ca54df95b1dc69591e2bdc1e3f296461a0e\ 73545f0b1a728f095b34af1c14dc3ff040878852b81a047198ec51c9f7dcfffac0ad33017fdb2f0c43edcff12d\ ef18336029b6f47a305e278cb4eda766445530f250be179818a2d241b5afebc21b194dbd62400042f887100725\ 62fb877debcff302fcc5b1162c1450e14478eb4e96906a31d6843172390e3cd69b3c0f474a72a62036579c22fe\ 1d1ad35fc2be49e475a1be85f30bec6d387e595070d17b17f5b5a6f400fde641d92abee13055777fe7f6b647fc\ 7850f8002fadb99332ceffb5439a87b2ac7f223b73750c6b42112fffe8b992da6c3fbc5274503b1bba48602753\ 174ba7260f73f3fa02c00fc495aad0f85c84c966f0a98fa7d85cca68b07d58e6292617f3b67fd0aafc0dc0c457\ 806b811f2698bea27de70e9ea3de0e898978b9670aa90750e88ac855daaf830c9dedb5d22968f2b01302edc889\ ce03e2af4ec2e339258ace8efa81eeb76b273039929d7289eadfb0bae898fd0257e0f1db349eba610dfb56e3d3\ 1520f08012e02d96edfbf9a1a05ad01f682c49e1cf1e0f2b1131943ffe95afd8c6454deffe4bfdbf15fe656e18\ 13690a6dbdca197ec4c2b29ac61a6ca074a2866ff9f55184ed344bb45b2e44eca9945a21cd78ccdd427dff1dab\ 1d449dccc0aa07e37c89bb61c7fc94ce0edd5fb60b7e2d8034decb7a0e2bba4c1159236fd7f800450c1516e64c\ bb2206f385ee11aba1c6993b2d50b2437bc23cc47f6b85d72fdd7348a5e321b5c960e8e23830fc93c4393938b8\ 98c2f16e8452c9e81ce5aa01460fb108dca1e371c53a1e72ad6ad0cb80bd5bf0ace476ab08fe8#5329", Nearest, "11691360406839692866118328.82160678934697449148561930623262244451953109076390937578282165\ 187539508530274103471810974014544850101997980642382746362536485174905201106566021759334671\ 038084134174395853704847978726074297598470143399522515598459659231845311084194915852728366\ 056422715218301245062324603756166217017490819881851715545101168897106488715462344820352976\ 259754023729090781152750099501504576567751861133292449402560554539891918302651799386455549\ 657664547443484522197757542024159371062990161647359586646799536699319711548827677391665966\ 287279197599493918294842951008826029536226825832854955685587903267919852682540903329229694\ 700736024127943619726831445160555949561747552032983921128094877425217970278847326632273418\ 407484077549236662570769286015075277220777908237436835596208190640803687131540850535115913\ 655954830695789298058473415611731503722972733488269283706021704532728574584684669676341549\ 292252804245357342748316615826715707101522402518116062329441651970107805707342168691626509\ 305758570985170639749549248022366152944291484173783280217974452532323709041672239778485037\ 294723948248639908579195768663906666012983129167763644004221520737884980923091163080707988\ 588422464078838824212171802847408608047867571127753377657964788586031325255106000694013614\ 527340915821283801356153178149699147203162830520911097467745909302616153231682263893483275\ 019567006794361076438485306321832725119559578113910632379303074353609691782388847871383450\ 484766163524999863199330839928739926251980847649975020069602105177714848358628397385350021\ 24095735959378409981273751636624594837614456921497122960535259532723503477033", "0x9abbdeae92a7cc75062b8.d254d2926ab47ec2646ac6102bc7f2c66e4adda59ec8c5ced87c449f85121ac94\ 7e79dc78b7313a18f2ce5e38db71d51c990df401764ed1949bc25e2614a9bdb3027efa1acf4ea0e322dfad232e\ cbd31249cc1917bbdffcead4f455598e97f24397ef8bff64f45dfd672a81269c27e03d6cb02da64c33a0af7326\ eb8e21ca7d9003144c8f62cd449d48953249142d7f5afd8112b58223fc36214a7e8c4b9a026eb8ba0dc0dca681\ f9d3c37cf62540e73333f8e07151b6353a7d9d6ad54f935a33c049acbf7c6e4e80629250c603ad3a070a43d3f9\ 70a8c5d99edacc2b229a04d8bb9f8b71acb7611d4e6c4a3e4330466403e5422746189403976a41698df939ffc0\ 32b31da3e6493f1393fd89226bf6b4eadf296725de20aac599c96edd2a445c9d689fee07ae5e94997f00659560\ 27632aa2cbfceba0ad1dcfeb7fb56c3a038718044af027a05c55e79d87a581fe5887ab1630360a4ddf22f18f4d\ 250a5385c3b6ee351d8d368543ed65e80461de207d9d924e8595b146d24defa8dbd01358a44fdf639ae28a852e\ 7675001a1c34c22013db15e7527ad9b7064b49c21ba11b7ed42ac9a570c006de5a092e84450d553767a5e2bb57\ f588dd1a63559f4b5bf0f0b1eda574f319b65c5c97023caf2862a4487c403143538931bdaba7e1fd57d1d07dc4\ 613f75769c70427af74a7af461be5b0126125aa40920e4e9b44a9e28616dc9ca7b77624028a0ed40aaed08486d\ 90086f51f501e47b6f5e0f7391a8320f07d62774d2c29f3abfc9f71514e3bc471ff2041ede5c0fb4ad39572ab8\ 6909d5a368ef66086eed3f37dad57f14ec6362b1b9567a687e771330ec416265c437c3e6d3c3136aedfe753577\ 319aed775fdefcbe6ff046d9f93acca0d253617b9b98b73f7e7fc043ad2e5f9ae06754e4df0f8#5329", Greater, ); // - out_prec <= p - 5 + Limb::WIDTH && xs_len > threshold + 1 in mul_float_significands_general // - xs_len > len in mul_float_significands_general // - k < len << 1 in mul_float_significands_general // - b1 == 0 second time in mul_float_significands_general // - !goto_full_multiply first time in mul_float_significands_general test( "0.000505125560873134723723784766950092518997332731967301291698755707702902596942317437852\ 941942371960388246351631317879977557751125153730732708319124734660713981958784935850223006\ 317900579689594830566320680544405297096706330277372404179805722699177498153458710988448597\ 667865038489642478166853872591228283694673924060010690084057961646317421857676637869623134\ 589158734829608080525671151880734425152367375882305121472858495571639962287931732234443489\ 588015865732596365983920824372468289009819493599234552103162449485200505569599322042323513\ 171853918367347759762125056867136354464299283595190704290061720089955391730926571989543650\ 123824756", "0x0.00211a99c3aab8ff53e9907564934b7d8b29ea0189ec9cd3d1a74407e1344b68fcd1809f4234bfef08c0c\ 3f89af1fe509093292b5b157eded4009179fedceae065ab0dd9d53b35a4ce7f1d190711e92618f7d0b216ce0bd\ 09e9c6f6625bcc6003ad38389decfb93a34f29b624c9c3c24dd825a59d15423602847fb2fe248d2b631514d4ed\ f610fd7088faa3f59c46a406f42343787142069c527e5b0aa730ef1f4054d887515ccd31c4f04063d57d8645a7\ b70fd198011231617f8b64344b5d43eb951d0a8ebfe39606336b443b19074cd641a63b4656b6e71133e47c099e\ 1fed7bc661252f72ee2c68b5cf9db6ee0645b455fb007e9d294c3a5e091df7f92b6268fff2e65b109ec#2100", "1.594827021209513894575272853189101796908969657496052553026904808146944132849277331696165\ 366066982899056554189139962942976395082328192559670863685439930018276703216617917370998670\ 143663891402542565265723410284904517798491873969116076521737839809230852429183992755715781\ 991743918659448701680599805386273131215689278489918563344703836788128584757613316503273812\ 347176374414975252562793531554358724296424942636927017522952046066543039832692600611375088\ 044395866209370211970587133626417624012062511750942538348241762511210915523305672594074841\ 5529943020302456665999104875220004206872624343740835605816652e-79", "0x4.ba3e1591f6a0ae18e8a750107efc0ca278b3954588d15a3695387227774da4319070b249d295916c24713\ 070f060a0df67ad5c2e8cc350d13189bcbf73f9af1e33fe42bf44fe99164bf802f7a5f41fe2d28377f1932b019\ a00373f4400d62f20693ce9fbe239afbc3c804face7c59fb40fe03be617f14dd6880b31ff429280aafe8ea5d94\ c3349efe67683ab81b8b5f4d00925073051d872bde743109c8e7c79da2c5fff9f489b12c271aa83405fe1d99c2\ 9f846c6b1c71dec233f13240569b3015559ed53bda719283585ed3f94bdeaea4d8438fe90e633bb97ee755eb88\ 113450187e9b05d8e6040fa53e6a10b6dcc2f01463a3937f5a90E-66#1988", Nearest, "8.055878935840864338761112052964131694842078144914087985110265043132694138227764882097467\ 485603629304908508159498533271385147841989466565220242546894501115782558008761861379571521\ 691942027516784202151149343065118307142127390742346695428089929852244559471690807529077258\ 667004534037323942848543095527661248910413746226405479291587579546107337446543923963731652\ 263604834014601264189816875633028978567676911887046995279630281027980542407933148412976200\ 257662826354908783390381610432026516882234795071151533161797811544609495678329417798803859\ 814384620434259660366163853727351148214688205975873187006097686502581917099916584703699137\ 7927e-83", "0x9.c7fc20220e43b5ac1717bf3fc467495e7a66c020cb393887e4bf4a3ad3eb4f20763507aea5b673c5aff25\ 8525ec5ac9bbc9f5c976983bce6231282e951654f346e3e5f7779ecdeae718176d55b03e21297ae13b32728a38\ 30c19eb847a199cde2fd0f3aa2330282fc433000c5f99b14022cd881da6b7caa98d3563644c4710ec876c4b61c\ b15fdd4cc7d712644bad3a66e844700eafebabf02dead4fd71d95a14ef9c6a12db9092cf7b4723f45cb086b401\ 8123e185be43126baa17ab68fd32a0834023652a003d24211dd87066d2d5b1f0f1993c0dd9756329316927dd98\ 425ba5d470abc9065c6ff724d0e16c68152314d36e37d235fe078572e42d94540fe4418a9440633E-69#2100", Greater, ); // - MPFR_MULHIGH_TAB[n] == -1 in limbs_float_mul_high_same_length // - k.is_none() in limbs_float_mul_high_same_length test( "5.001744775175450910666028825162941035057223155811961434576858983758571141018459147239961\ 203150588371507863692097065128597336587126035820647361489875366021800666979434518756504925\ 080057234368614339602900137940067888065298554658519361482160014564328827389146902718969285\ 655774560873251528749737416878097111467317878479458938947793439179987668446365650646689222\ 368834166803110702160567896615568919058064520266761717855703906871630752776256537972706691\ 492064397304429453321564568279795029252524047182880248127317544801138445700458013706547493\ 607273723210196209139384085476634511414334117395068648152693457778920460359930382343697178\ 078573995749595631668772420417704996567074590195305455833132484492282116574194971013126880\ 3791636230633361526548302742414616516594455084620537903358416e-16", "0x2.40a97302ee75111e17146bc65c8925811ce517da511093e155a5f8d319eaddbeb4108f1636a175bfa8c49\ 995045d6820b2f007a269091d024c939d8b02f4910a81e4eb38a836a327a5c12207dbd4d7a81228e55fec96493\ eb7d51704a03ee77c5caca6616fdc0b6cbe90c676923de6ef8bf3f132b9e5e0dcbae8db3a41502b6d35629f01c\ 0834af3506639efdaa9dba6adf35a24b53b04e032ba7f9821a7155eb04aa7d235436bb878e13e2f265b7a183bd\ 7830bf484c2c6b19e1df88120105ab6ceb5f940ee7e82d4a6da4e67b7532f20750db350a532138117c02fd3f63\ 1e917747a8217c0e647adfae38491beacae6be9197fecb6a639604eba9f3e2a0e1250124f9d994d6ae0f8077c0\ ad1f961f00f0513cb1b3b92f03fd2e19ce799415d8c26352d23ab730bff342c3d10823b5d476e3a74e5e3a1265\ 3a2e81ad38c5d7f45687a8E-13#2587", "1.142392802815468388118014752111991104436260746248041498551240097570984474280784266879307\ 592064853042631818930172030116326290909317377878988867978348974337550025356060840134215623\ 183687852648862683292152461337367387727519703906836027722282460995072637442171724001503892\ 471336699233392710738717656085295397789876649817787754823752786376233371866685422498954888\ 388883747226256845650864591251580129661172288008506642506027201072159168710566406994425528\ 61698637621752755004821872e-17", "0xd.2bbf98dfde60cfd72ff373085dca4697e7a8a2b1b6d379d3c49be918a519d5508c59f210662104e5d0b4b\ bb4e9f09afcccb3c1655f91f2a86657e3f1315aa4e7c857d68f4d7b989d2a2f5d56a205e85ef7d6d2e9325e0fe\ eded2158374d99d513a6d203143a26cfd251731f49e63a0e342dec62e52287bd673124d763a94038f4529cffd3\ 3599c97c0e19c589ce5603d9c26a084d360b9e7decaa7dda44ce1c27bb7c21adcb23b90d069b0a9b53b9d66094\ d817f0420227841d34052ed2bd52e148923f8E-15#1571", Nearest, "5.713957232680308157039243396854396365207579750474509016836068310655183904589399398864949\ 369194427543435776465300666190725186454505340683874976519507548279996486761744005041118935\ 948747589743699350970808906395296086217435990867715483224265504817855574934867156151545781\ 106814865537845359234760816964504042844539777879186641559132734209465852287196566458935778\ 830300266229578325422723437672411534085537936547389438107265754858071594639985760821104661\ 940648845072022419465943642338099526948876829384943161258695569354371632958134560717841147\ 840574265292252548747529841143166165808068071464187327019844718180901133673499079508336221\ 530763161764985656092293178070670798408664087435197003752408586649867017671653317949434498\ 7804832149608135310831412140057788625216612318872425368846162e-33", "0x1.dab26e4414e016457a3b64d6dc588a9f2a4cbec7acd1a5b9033e00168a27a1ac3f669e39332cdbace29d9\ b5d727df53a041f44f1389d6fda544d07799d35a62fbf327a55fca19ed803e80954753bfb12dcfda81be99eda5\ 2d7a382f6dd0ac26ab4b55fa3587bc812156b0ddb289357e7300ea3dafa43cee4f98c4068d3ffbeceea4a01ecc\ 74a09b85289f4c37000efab1e07926e01496cf6855b4a1f08915fff56a1737ff1d109fb6f3011fb249b88db85f\ 52980590101cbaa0e8af5872ded15ef0f39ec69d2d19d45c2972793e60bbb6eee9b673f24b3318973256a8e9bc\ 90d40f033e145dc56a6caa7e542a2701c0a41519fd0ef8d97ed0cef3e4296de50e877edeae80c0dd91f9082539\ 71e8998ef2a91d865baa5aa565e308789af81b128e8d0e832f5368e689962335ca7077ad875ea20eae1f2fc375\ a972b8e7b8e285bbe3bdb0E-27#2587", Less, ); // - xs_len <= len in mul_float_significands_general // - limbs_float_can_round in mul_float_significands_general test( "2791656999165.493196894581080462482671477586959884065253358835066410305633620155930725019\ 490863414181814174955842522364865024774379310519058136940369290858518517313460149216061827\ 231421960818181308820010416988884966114071973567666857448623899431042502611223036510238920\ 700493077403107131238955287441775846760482666068674778697270732066126184067657756561516984\ 251159820991198761865419427067747698722303345927460124328666182849055120607788400162794652\ 0878157328543259919881", "0x289fbb948fd.7e4226d4b6e97c4ccb64c2a072193f46e582b56e431d1d873706fd936c5e3328fd5b164ebe6\ f6c3319057366a2de168eaef87f67644a657027f176fb9d5deaa62912e24d9b1eebf67a642c7ebc91e95eba928\ d2c47f45ab981a3053c2a055e2a36102f8c4b2c72f24edbf87122ddff42408c1c95b6eccee7c0a49a25e2fe2fd\ 67a0dfc9d33ccad11d273f88f3e5a176da6b5989e6fc247727a58af5ef0f3a863e35d59edceb1ed0401bb2ce98\ 77227cdff6442212230b17fb43a061516c#1558", "2418611879271263.303076595070873673412348926925363768438166046534014463089969421888804109\ 398849144724043021994927400943502019398552005514731676646297869532250197280910814394530400\ 370821284006890204265425587260634300563572770382580394115150082129924900080499709146475799\ 383767996765000283568589472197582158015457869515972738606414178902063354061536898088295371\ 641586286472920893106777705320869713042818435525510767840203306234890813618032983465299395\ 730347727963352100742341245602143", "0x897b6f5e9db5f.4d966d80032f1615c15b6d17e02b100d2d97b52de1b561199b3dbeda9276bc25c5519d480\ c2c20f52155b94074ad9db0bd7a97dae0337b738b6709c5fdd1bbcf1492bef975c393313e477790485d0a4ed0f\ 8790d9d469d65c29122cd019f7ff423e0f74c0585cac3aa85ceee8cbd256a201e23dd78f6dc402aa36b5a053ea\ c1a3b2c435ae84ee9942bec1d88e41507bee030c35cd3f18b2f7a5c9193976d7418a633e08ca4923be03a2dc93\ 6ed64c6ff04ace32f44aa72f58bf488b9bf31c4c03f#1596", Nearest, "6751934781032429031553446805.854936199324254228337806577049209187291041079391491758652444\ 360751832908394550062618692018471995917689775126406303977393164343146088816585483538887454\ 027840163444916716206473736192766508247978473183426254779355642987433462433675113794019449\ 629515518752711445976665575431349720824019816455254142652806744349728110370084378693365847\ 376950483953541149499814845310185214082773221620162084856311318860928357827312318714828967\ 076794760533141841485387490188815", "0x15d111cde75ec690f0fb3395.dadd194843a336fd8b04fc1edf686f76aa52a00d00db09b133bcedaa832e64\ e3cbe80e635c5bb60e81bb4cb3839dc581a1f683d480b6757136ace3d394264c5f969b75cb4d985b4b2b1096d2\ a53a6d6570c7f7c917bed4f2a9c8f7bcdea046337457665b27e5e01bdbce6f20c6d5bc9e463f055cca9b0c53a2\ f1f5b6d7211ac001a5fa99daf3378815db2c7bc77c6d6b76f815ae464fdc70ae82752dbe2b5683cc1ebc18275d\ 4685cbd35d58b70dbda84d2297ff9a12d20f2283678e#1596", Greater, ); // - out_prec <= p - 5 in mul_float_significands_general test( "7.449979045041702122541548973189889723858373710052883535770432677692650998750696470703091\ 744255868088920360332810996981821635561095981209970543165990341865465399250649125818133550\ 345620227288485003961432095280508748897878683743133302349812547742789930883805941444651209\ 784236601329970891014476723035066837590220224883282604585022340111695027909185310636007609\ 680407882966239499164648695501638941698641158401193435378725738878261400237405551514713128\ 836982995938875007304023367379668047357772772649359285993284186179803252277e-21", "0x2.32e78d682285335802e277865ca4c9a80daafb30e4f67daedb2f466845a2fba5d9b1c96b068c42999ae0b\ 463fb94e578b359027630c01a995d88a74b72186c316ec30a8b4238fb27273b57cc5e72fa518fa14032e99af11\ e1d5ccfc1217be504bf8dae0d1ec7e885fc95b51f444d68ed47eb588644910e4196d65104707dcd1c488a22e9c\ 1ef05ce85b3823fd6aa2bb7ad7d14fa1da7a628e1ba344d98ad7e95bf7e01883afc84273614fb8387e4035b2d9\ ad867bc2be83eaabaa44df896348f52d4972bc5e8cf58f1cfd421cc30920d9f5504a043149274f5E-17#1738", "4.689598630661113758052361654518074651900718126313070505518580809308545656249466966444734\ 190644625007707301196274229099309347916384836732990153197811248723616418486524781737017155\ 222220872736570797023388780311017887508289881051954626904239986311860650999175535050592519\ 124458883175586921775053060798371665433755864916689805023189965297596140362143269558535567\ 196585839368205277548820051354051306095222442551993791324926248616628216018709202221063695\ 130497558241752004759655263919857509980778615592531001107310020150056419e-20", "0xd.d75c4c85ded4dada979685c90590eb9f191595aa1862df62f276fa75d5d790d2c00d187fe126b806534fd\ 0379dfcf600aeee23bbe00ed5955cc2e11b7de967da0c347d3ca03714f55b714dbe2c9ad31dbd7b6fb9a639fa4\ da6cec918f3fc77bbca5ded28446186fe8b4224339c0722fed5f69b2d07571b12f4cce6fece51fc63ab46ea7fe\ 5c1f350ed6aab2c76a1e817bf652a9c77a95e3e3c107ed65e9ace86dfec217fb9dcbba544e3d84b0f3cac6c221\ 176c57f1db9bc306f22db85308dab755243a502d385e1b0a31f2f8c2d53c98729cfe52f82289cE-17#1730", Nearest, "3.493741152808155821061780436862260285420312736969910829282351541785101293399126489805777\ 980187532032743650816868281893520821921299562434265222876601442289649987508199259232837158\ 559068445030886433472805552651673239073165198885867344396236299229232184802565958836951408\ 637905144866851014091996571320623346167534428281388860566996500707311335172658622534949254\ 838518529528764394710349462443386828046760610922770501616700810546292498376696602122491857\ 8540047731481736443609736067164917894729323015869507020379275317039780244947e-40", "0x1.e6f4d9986216e186a3b15da557e0677276dd590e3d92a71ff89974ad2abac1a1e2e3dc761157b14cfef04\ 285b10c4bf2f72117bbdbdfd5ead95a5ed69f62f69682442a59a3f3c8a5a7b41238f0a029b2d53c54a08053451\ 35f5fc0a67464283bade3997992eea966997d442d69987820628966dfcaa6d25ca0be2df6ed92e5fa5201002da\ 70c6447c3a8a64ebd34fc04156c8dbd224d772ba1059982a5aa333d301a708dc568330bdead12245127d520b32\ b4e7d9ae221552ab3d3f5f2f139c90118fe830b6adc84392948585b40267beb9fd60cce93fbed140E-33#1738", Greater, ); // - xs[0] == 0 && xs[1] == 0 || ys[0] == 0 && ys[1] == 0 in mul_float_significands_general // - xs[xs_offset] == 0 in mul_float_significands_general // - ys[ys_offset] == 0 in mul_float_significands_general test( "4.44089209850062616169452667236328125e-16", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000E-13#2587", "6.938893903907228377647697925567627621275394370123920756842177449687616281576087749649243\ 449560881562252974476503855378704420289043275360540974361356347799301147460937500000000000\ 428087763478203718701697872488500162623204828539850902982930587576291943616315378569169353\ 840957917417166522314320167278698048638040260019989045715363127222769643922793712163996851\ 225018060026136483495536368092685586468682354268058778363979622204058653592623442621394947\ 3239996744456973724770155e-18", "0x8.0000000000000000000000000003fff000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fe00000000000000000000000000000000000E-15#1571", Nearest, "3.081487911019577364889564708135884006379343333980678546187704758135879626468817238227001\ 919863959483626636205013163029555487554952753086708205626001498966504653625325671484347367\ 558282010814620352468694740583510310926487120637351903244174605756585424927747220355720149\ 705262186320261062950329818867477826244378862350354462458385252797818784708103173459291235\ 769538479528034217611825504020777438216019896385615152551542382665798426796321259955655479\ 300773291504754679549289638268112862439028560817297535629039872109954348969232817790940901\ 772925125639499661447304917621775611916484032847611462965461660088172016929375670794716891\ 215288121297398166137896866022540415673603027116093396582728756514564426357106145459651571\ 0636500728956428014332817951864653686798458732591874037159276e-33", "0x1.00000000000000000000000000007ffe00000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000E-27#2587", Equal, ); // - xs[xs_offset] != 0 in mul_float_significands_general test( "3.999999999999999999999999999999999999999999999999999999999999999999999999999447285212473\ 955543975273480780774427448575976676077991358482977909210124597604668289823519777773553500\ 1249731874464215297923136674027554116062077582682832144200801849365234375", "0x3.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000000000000000#2090", "3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000038180485e-31", "0x8.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000001ffffffeE-26#2567", Nearest, "1.577721810442023610823457130565572459346412870218046009540557861328124999999781992456191\ 582683140605249728137786969774247203293102032637435297463867968227730622206111553159326620\ 257748727154917100482837417166916131758491078680030585867783733868391940878208953914079279\ 677271330675596139325733702207799069583415985107421875000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000001527219401e-30", "0x1.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000007ffffff8E-25#2567", Greater, ); // - ys[ys_offset] != 0 in mul_float_significands_general test( "3.552713678800500929355621337890625000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000185653473271011701515143789632334288014147578747413968011889263434165\ 454031003144878632958696545103828379944287431463737771314691776232764018029744516848435369\ 906941507005331339097431189921414095915636548343770290467007831930064077297413615608072068\ 77626957251331627162116234578193867366731943186452308784033031e-15", "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffE-12#1693", "131071.9999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999931137299504668061215619580033350122879947175743013377219720120678876536\ 628643562946337394277177628286886258713868752206334184193331360816755408598724051586961746\ 685495576886231160425736851019484652776925452038003143395027472798288565900387988918967170\ 024140096215282631707814129061246845336549291242702672707242154281040996134116689237194330\ 449329247059466983779402165943011772702916829761392820351107526820413839207822952585392346\ 328868866364548445701244431290159307431187837005854773744122693182105660536394809595147776\ 165023610906858577556273686957594781817444085841499342583068122729709267291", "0x1ffff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffc0000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000#2930", Nearest, "4.656612873077392578125000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000243339720485780457409929267946893197985903514415810436152543495368429\ 343907516442055321546973277589582124346598388556070043505489984826143425305512049232107258\ 133592644143603087675038065556842214758248268059151846952539521827810268928481776834311731\ 044052486308720793745225556140061733844701779522496735016181906708106564202059526039890815\ 919178696765989061598664073635409369732679923290228161362302668920197866351570235145652815\ 456445767888399222146130209012884306181795683184194476165898983356347814975458163826496169\ 408195862006279548822773547655683272930717806964759394377376260006554734212838956379338694\ 525902352837865322055484704841599472083306918235788680977972181745262154636e-10", "0x2.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000\ 00000000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffdffffffffffffffffffffff\ fffffffffffffffffff80000000000000000000000000000000008000000000000000000000000000000000000\ 000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffdfffffffffffc0000000000000000004000000000000000000000000000000000000000000000000000000\ 00080000000000000E-8#2930", Greater, ); test( "12962368.00910437392826314193446550944389165836262015621514962112057577196019471161937054\ 243429475140935082492484312458697139062031326336320065697050792374770657213779646419924892\ 886900897092216274606911219143642483069838857046000551685989850622347518286427108428594195\ 826642547794926862213089792293539194572777838215978068770604450325322408918968488729618206\ 83239161602000658143319869428", "0xc5ca40.0254aa0c45bef8b7e5bdc2c8d0bc3f4ef77512b0c665764acef9797020852473fed6cf5aef7ab76f\ af4e7ccca7674b7b9a7d4e3adf7dbd2f9c51a93c8b500f9c6e799811cc9793ad3189530f5202900aed04c32d98\ 72075f4a8efb28f1e3d9e2065d70be0df4f07d46d4f2f48b95a6fcd718d2f233dbbaff41296fe46efd00783168\ f9da607a651780d29e9357c1d8e9abdd149e2d7ed04e74488fff360#1283", "24678125950611051118469790273997953293778953666881566874553684447233373952852192.03220118\ 824573657786267791510531425783997288827451260529832388036858875235909753308200751110173525\ 014519161498781309811156911488470099945303550175018037705473098495478288721507648423524330\ 255884870759432606723320831807670552582364423881930823507999308667398128596287742877235432\ 154091338959855861235089997932459245142831892", "0xd51fdc4e02742b528c90f8a31146dcba3e1273bfdd1198ff1ec486c97e52f8c0e0.083e564a6864272a5d52\ 74cbdf67db38b72e576e7cfe8be5418f583cf4173a82939f37d7b6b399cada03434a24aef04a65323c333b33cf\ 622583787d8ec1f247c4f691c3a7862628783f4322923b6bb9434902754e348fb74eb6364e294832597785e445\ 1994ee48803ea5771d85e7f226166cdd1853477f296076996b97965596455eb50129#1336", Nearest, "319886950346849155967554337687681180827634107405044558954903133134156000777816460853971.0\ 571286460940042331570995057120143779176892645683546163312322051333969186064059757999062545\ 749424646225780605680908775358827191384406475576071818545005626321659954666901446716884049\ 318512517659256499382137861718683137930417158199590725586222075459373218000006096544204046\ 600400863088080659996213042623116710817104536", "0xa4a9e4f5c54093e3388df17b55e5724251f90cd6c231443e4bc0d5770919a2c1878982d3.0e9ffba2a37526\ 7ffbc880a862170226c003dcfce47863efaa79493245f971642ca10409a10ad584de1597974f309b61313528bd\ 1512f14b2397a5630d41d067d57d9b327d751eacb350f8e13428d4508849e4464775e72f3b4fb63d6bef2d97b6\ f0118aa022becb98c8c88fdcb280078abcbe4c3b8423dc1dfc91e6b09ea9115cd0cd#1336", Greater, ); // - exp_sum - 1 > Float::MAX_EXPONENT // - exp_sum - 1 > Float::MAX_EXPONENT && sign && rm == Floor | Down test( "2.0", "0x2.0#1", "too_big", "0x4.0E+268435455#1", Down, "too_big", "0x4.0E+268435455#1", Less, ); // - exp_sum - 1 > Float::MAX_EXPONENT && sign && rm == Ceiling | Up | Nearest test( "2.0", "0x2.0#1", "too_big", "0x4.0E+268435455#1", Up, "Infinity", "Infinity", Greater, ); // - exp_sum - 1 > Float::MAX_EXPONENT && !sign && rm == Ceiling | Down test( "2.0", "0x2.0#1", "-too_big", "-0x4.0E+268435455#1", Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); // - exp_sum - 1 > Float::MAX_EXPONENT && !sign && rm == Floor | Up | Nearest test( "2.0", "0x2.0#1", "-too_big", "-0x4.0E+268435455#1", Up, "-Infinity", "-Infinity", Less, ); // - exp > Float::MAX_EXPONENT // - exp > Float::MAX_EXPONENT && sign && rm == Floor | Down test( "1.5", "0x1.8#2", "too_big", "0x6.0E+268435455#2", Down, "too_big", "0x6.0E+268435455#2", Less, ); // - exp > Float::MAX_EXPONENT && sign && rm == Ceiling | Up | Nearest test( "1.5", "0x1.8#2", "too_big", "0x6.0E+268435455#2", Up, "Infinity", "Infinity", Greater, ); // - exp > Float::MAX_EXPONENT && !sign && rm == Ceiling | Down test( "1.5", "0x1.8#2", "-too_big", "-0x6.0E+268435455#2", Down, "-too_big", "-0x6.0E+268435455#2", Greater, ); // - exp > Float::MAX_EXPONENT && !sign && rm == Floor | Up | Nearest test( "1.5", "0x1.8#2", "-too_big", "-0x6.0E+268435455#2", Up, "-Infinity", "-Infinity", Less, ); // - exp < Float::MIN_EXPONENT // - exp < Float::MIN_EXPONENT not special // - exp < Float::MIN_EXPONENT && sign && rm == Floor | Down | Nearest test( "0.5", "0x0.8#1", "too_small", "0x1.0E-268435456#1", Down, "0.0", "0x0.0", Less, ); // - exp < Float::MIN_EXPONENT && sign && rm == Ceiling | Up test( "0.5", "0x0.8#1", "too_small", "0x1.0E-268435456#1", Up, "too_small", "0x1.0E-268435456#1", Greater, ); // - exp < Float::MIN_EXPONENT && !sign && rm == Ceiling | Down | Nearest test( "0.5", "0x0.8#1", "-too_small", "-0x1.0E-268435456#1", Down, "-0.0", "-0x0.0", Greater, ); // - exp < Float::MIN_EXPONENT && !sign && rm == Floor | Up test( "0.5", "0x0.8#1", "-too_small", "-0x1.0E-268435456#1", Up, "-too_small", "-0x1.0E-268435456#1", Less, ); // - exp < Float::MIN_EXPONENT special // - exp < Float::MIN_EXPONENT special and sign test( "0.8", "0x0.c#2", "too_small", "0x1.0E-268435456#1", Nearest, "too_small", "0x1.0E-268435456#2", Greater, ); // - exp < Float::MIN_EXPONENT special and !sign test( "0.8", "0x0.c#2", "-too_small", "-0x1.0E-268435456#1", Nearest, "-too_small", "-0x1.0E-268435456#2", Less, ); // - exp_sum < Float::MIN_EXPONENT - 1 // - exp_sum < Float::MIN_EXPONENT - 1 && sign && rm == Floor | Down | Nearest test( "0.1", "0x0.2#1", "too_small", "0x1.0E-268435456#1", Down, "0.0", "0x0.0", Less, ); // - exp_sum < Float::MIN_EXPONENT - 1 && sign && rm == Ceiling | Up test( "0.1", "0x0.2#1", "too_small", "0x1.0E-268435456#1", Up, "too_small", "0x1.0E-268435456#1", Greater, ); // - exp_sum < Float::MIN_EXPONENT - 1 && !sign && rm == Ceiling | Down | Nearest test( "0.1", "0x0.2#1", "-too_small", "-0x1.0E-268435456#1", Down, "-0.0", "-0x0.0", Greater, ); // - exp_sum < Float::MIN_EXPONENT - 1 && !sign && rm == Floor | Up test( "0.1", "0x0.2#1", "-too_small", "-0x1.0E-268435456#1", Up, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn mul_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.mul_round(THREE, Exact)); assert_panic!(THREE.mul_round_val_ref(&THREE, Exact)); assert_panic!(THREE.mul_round_ref_val(THREE, Exact)); assert_panic!(THREE.mul_round_ref_ref(&THREE, Exact)); assert_panic!({ let mut x = THREE; x.mul_round_assign(THREE, Exact) }); assert_panic!({ let mut x = THREE; x.mul_round_assign_ref(&THREE, Exact) }); } #[test] fn test_mul_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (product, o) = x.clone().mul_prec_round(y.clone(), prec, rm); assert!(product.is_valid()); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); assert_eq!(o, o_out); let (product_alt, o_alt) = x.clone().mul_prec_round_val_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_prec_round_ref_val(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = x.mul_prec_round_ref_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_prec_round_assign(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let mut product_alt = x.clone(); let o_alt = product_alt.mul_prec_round_assign_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o_out); let (product_alt, o_alt) = mul_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "1.0", "0x1.0#1", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "1.0", "0x1.0#1", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "1.0", "0x1.0#1", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "1.0", "0x1.0#1", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "Infinity", "Infinity", "-1.0", "-0x1.0#1", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "1.0", "0x1.0#1", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-1.0", "-0x1.0#1", 1, Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "1.0", "0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "1.0", "0x1.0#1", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Floor, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-1.0", "-0x1.0#1", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1.0", "0x1.0#1", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-1.0", "-0x1.0#1", 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "123.0", "0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123.0", "0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123.0", "0x7b.0#7", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "123.0", "0x7b.0#7", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "123.0", "0x7b.0#7", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Floor, "123.0", "0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Down, "123.0", "0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Up, "123.0", "0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "123.0", "0x7b.0#7", 10, Exact, "123.0", "0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test( "-1.0", "-0x1.0#1", "123.0", "0x7b.0#7", 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 1, Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 1, Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#1", "2.0", "0x2.0#2", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 1, Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 1, Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.0#2", "2.0", "0x2.0#2", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Floor, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Down, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Up, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 1, Exact, "2.0", "0x2.0#1", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Down, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Up, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2.0", "0x2.00#10", 10, Exact, "2.0", "0x2.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "8.0", "0x8.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "8.0", "0x8.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "4.44", "0x4.70#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "4.445", "0x4.72#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "4.44", "0x4.70#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "4.445", "0x4.72#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "4.445", "0x4.72#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-8.0", "-0x8.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-4.0", "-0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-4.0", "-0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-8.0", "-0x8.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-4.0", "-0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-4.445", "-0x4.72#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-4.44", "-0x4.70#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-4.44", "-0x4.70#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-4.445", "-0x4.72#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "-8.0", "-0x8.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "-8.0", "-0x8.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "-4.44", "-0x4.70#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "-4.44", "-0x4.70#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "-4.445", "-0x4.72#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "4.0", "0x4.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "8.0", "0x8.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "4.0", "0x4.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "8.0", "0x8.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "4.0", "0x4.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "4.44", "0x4.70#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "4.445", "0x4.72#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "4.44", "0x4.70#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "4.445", "0x4.72#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "4.445", "0x4.72#10", Greater, ); } #[test] fn mul_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).mul_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).mul_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).mul_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).mul_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.mul_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.mul_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(THREE.mul_prec_round(THREE, 1, Exact)); assert_panic!(THREE.mul_prec_round_val_ref(&THREE, 1, Exact)); assert_panic!(THREE.mul_prec_round_ref_val(THREE, 1, Exact)); assert_panic!(THREE.mul_prec_round_ref_ref(&THREE, 1, Exact)); assert_panic!({ let mut x = THREE; x.mul_prec_round_assign(THREE, 1, Exact) }); assert_panic!({ let mut x = THREE; x.mul_prec_round_assign_ref(&THREE, 1, Exact) }); } #[test] fn test_mul_rational() { let test = |s, s_hex, t, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let product = x.clone() * y.clone(); assert!(product.is_valid()); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); let product_alt = x.clone() * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &x * y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &x * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = y.clone() * x.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = y.clone() * &x; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &y * x.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let product_alt = &y * &x; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let mut product_alt = x.clone(); product_alt *= y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); let mut product_alt = x.clone(); product_alt *= &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_mul_rational( &rug::Float::exact_from(&x), &rug::Rational::from(&y) ))), ComparableFloatRef(&product) ); let product_alt = mul_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); if x.is_normal() { let product_alt = mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); } }; test("NaN", "NaN", "123", "NaN", "NaN"); test("Infinity", "Infinity", "123", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "123", "-Infinity", "-Infinity"); test("NaN", "NaN", "0", "NaN", "NaN"); test("Infinity", "Infinity", "0", "NaN", "NaN"); test("-Infinity", "-Infinity", "0", "NaN", "NaN"); test("0.0", "0x0.0", "0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "123", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "123", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "-123", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "-123", "0.0", "0x0.0"); test("0.0", "0x0.0", "1/3", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "1/3", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "1", "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", "0", "0.0", "0x0.0"); test("-123.0", "-0x7b.0#7", "0", "-0.0", "-0x0.0"); test("1.0", "0x1.0#1", "2", "2.0", "0x2.0#1"); test("1.0", "0x1.0#2", "2", "2.0", "0x2.0#2"); test("1.0", "0x1.000#10", "2", "2.0", "0x2.00#10"); test("1.0", "0x1.000#10", "1/3", "0.3335", "0x0.556#10"); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", ); test("3.0", "0x3.0#2", "2", "6.0", "0x6.0#2"); test("3.0", "0x3.00#10", "2", "6.0", "0x6.00#10"); test("3.0", "0x3.00#10", "1/3", "1.0", "0x1.000#10"); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", "1.0", "0x1.0000000000000000000000000#100", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", "1.0471975511965976", "0x1.0c152382d7365#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", "-1.0471975511965976", "-0x1.0c152382d7365#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", "-1.0471975511965976", "-0x1.0c152382d7365#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", "1.0471975511965976", "0x1.0c152382d7365#53", ); // n and d both powers of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "1", "too_big", "0x4.0E+268435455#1", ); // - only n a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "1/3", "too_big", "0x1.0E+268435455#1", ); // - only d a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "3/2", "Infinity", "Infinity", ); // - neither n nor d a power of 2 in mul_rational_prec_round_assign_direct test( "too_big", "0x4.0E+268435455#1", "3/5", "too_big", "0x2.0E+268435455#1", ); } #[test] fn test_mul_rational_prec() { let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (product, o) = x.clone().mul_rational_prec(y.clone(), prec); assert!(product.is_valid()); assert_eq!(o, o_out); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); let (product_alt, o_alt) = x.clone().mul_rational_prec_val_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_ref_val(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_ref_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_prec_assign(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_prec_assign_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } let (rug_product, rug_o) = rug_mul_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "123", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", "1", 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", "0", 1, "0.0", "0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", 1, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "2", 1, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 10, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.0#2", "2", 1, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 10, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", 1, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.000#10", "2", 10, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "1/3", 1, "0.2", "0x0.4#1", Less); test( "1.0", "0x1.000#10", "1/3", 10, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, "0.2", "0x0.4#1", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, "0.3335", "0x0.556#10", Greater, ); test("3.0", "0x3.0#2", "2", 1, "8.0", "0x8.0#1", Greater); test("3.0", "0x3.0#2", "2", 10, "6.0", "0x6.00#10", Equal); test("3.0", "0x3.00#10", "2", 1, "8.0", "0x8.0#1", Greater); test("3.0", "0x3.00#10", "2", 10, "6.0", "0x6.00#10", Equal); test("3.0", "0x3.00#10", "1/3", 1, "1.0", "0x1.0#1", Equal); test("3.0", "0x3.00#10", "1/3", 10, "1.0", "0x1.000#10", Equal); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, "1.0", "0x1.000#10", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, "1.047", "0x1.0c0#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, "-1.0", "-0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, "-1.0", "-0x1.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, "1.0", "0x1.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, "1.047", "0x1.0c0#10", Less, ); } #[test] fn mul_rational_prec_fail() { assert_panic!(Float::NAN.mul_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::NAN.mul_rational_prec_val_ref(&Rational::ZERO, 0)); assert_panic!(Float::NAN.mul_rational_prec_ref_val(Rational::ZERO, 0)); assert_panic!(Float::NAN.mul_rational_prec_ref_ref(&Rational::ZERO, 0)); assert_panic!({ let mut x = Float::NAN; x.mul_rational_prec_assign(Rational::ZERO, 0) }); assert_panic!({ let mut x = Float::NAN; x.mul_rational_prec_assign_ref(&Rational::ZERO, 0) }); } #[test] fn test_mul_rational_round() { let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (product, o) = x.clone().mul_rational_round(y.clone(), rm); assert!(product.is_valid()); assert_eq!(o, o_out); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); let (product_alt, o_alt) = x.clone().mul_rational_round_val_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_round_ref_val(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_round_ref_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_round_assign(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_round_assign_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product) ); assert_eq!(rug_o, o); } let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } }; test("NaN", "NaN", "123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", Exact, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Floor, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Ceiling, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Down, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Up, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Nearest, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", Exact, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Floor, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Ceiling, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Down, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Up, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Nearest, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Exact, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", Exact, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", Exact, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", "1", Floor, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "1", Ceiling, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "1", Down, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "1", Up, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "1", Nearest, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "1", Exact, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "0", Floor, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", Ceiling, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", Down, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", Up, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", Nearest, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", Exact, "0.0", "0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Floor, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Ceiling, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Down, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Up, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Nearest, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", Exact, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "2", Floor, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", Ceiling, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", Down, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", Up, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", Nearest, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", Exact, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", Floor, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.0#2", "2", Ceiling, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.0#2", "2", Down, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.0#2", "2", Up, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.0#2", "2", Nearest, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.0#2", "2", Exact, "2.0", "0x2.0#2", Equal); test("1.0", "0x1.000#10", "2", Floor, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", Ceiling, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", Down, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", Up, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", Nearest, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", Exact, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.000#10", "1/3", Floor, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Ceiling, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Down, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.000#10", "1/3", Up, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", Nearest, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Floor, "0.3333333333333333333333333333331", "0x0.55555555555555555555555550#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Ceiling, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Down, "0.3333333333333333333333333333331", "0x0.55555555555555555555555550#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Up, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", Nearest, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Floor, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Ceiling, "1.0471975511965979", "0x1.0c152382d7366#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Down, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Up, "1.0471975511965979", "0x1.0c152382d7366#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Nearest, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Floor, "-1.0471975511965979", "-0x1.0c152382d7366#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Ceiling, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Down, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Up, "-1.0471975511965979", "-0x1.0c152382d7366#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Nearest, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Floor, "-1.0471975511965979", "-0x1.0c152382d7366#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Ceiling, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Down, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Up, "-1.0471975511965979", "-0x1.0c152382d7366#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Nearest, "-1.0471975511965976", "-0x1.0c152382d7365#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Floor, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Ceiling, "1.0471975511965979", "0x1.0c152382d7366#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Down, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Up, "1.0471975511965979", "0x1.0c152382d7366#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Nearest, "1.0471975511965976", "0x1.0c152382d7365#53", Less, ); } #[test] fn mul_rational_round_fail() { const THREE_F: Float = Float::const_from_unsigned(3); const THREE_Q: Rational = Rational::const_from_unsigned(3); assert_panic!(THREE_F.mul_rational_round(THREE_Q, Exact)); assert_panic!(THREE_F.mul_rational_round_val_ref(&THREE_Q, Exact)); assert_panic!(THREE_F.mul_rational_round_ref_val(THREE_Q, Exact)); assert_panic!(THREE_F.mul_rational_round_ref_ref(&THREE_Q, Exact)); assert_panic!({ let mut x = THREE_F; x.mul_rational_round_assign(THREE_Q, Exact) }); assert_panic!({ let mut x = THREE_F; x.mul_rational_round_assign_ref(&THREE_Q, Exact) }); } #[test] fn test_mul_rational_prec_round() { let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (product, o) = x.clone().mul_rational_prec_round(y.clone(), prec, rm); assert!(product.is_valid()); assert_eq!(o, o_out); assert_eq!(product.to_string(), out); assert_eq!(to_hex_string(&product), out_hex); let (product_alt, o_alt) = x.clone().mul_rational_prec_round_val_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_prec_round_assign(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let mut product_alt = x.clone(); let o_alt = product_alt.mul_rational_prec_round_assign_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product), ComparableFloatRef(&product_alt) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "123", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "123", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "123", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "123", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("NaN", "NaN", "0", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0", 1, Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Floor, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Ceiling, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Down, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Up, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Nearest, "NaN", "NaN", Equal); test("Infinity", "Infinity", "0", 1, Exact, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", 1, Floor, "NaN", "NaN", Equal); test( "-Infinity", "-Infinity", "0", 1, Ceiling, "NaN", "NaN", Equal, ); test("-Infinity", "-Infinity", "0", 1, Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", "0", 1, Up, "NaN", "NaN", Equal); test( "-Infinity", "-Infinity", "0", 1, Nearest, "NaN", "NaN", Equal, ); test("-Infinity", "-Infinity", "0", 1, Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", "0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "123", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "123", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Floor, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Down, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Up, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Nearest, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, Exact, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "-123", 1, Exact, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "1/3", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "1/3", 1, Exact, "-0.0", "-0x0.0", Equal); test( "123.0", "0x7b.0#7", "1", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "1", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "1", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("123.0", "0x7b.0#7", "0", 1, Floor, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", 1, Down, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", 1, Up, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("123.0", "0x7b.0#7", "0", 1, Exact, "0.0", "0x0.0", Equal); test( "-123.0", "-0x7b.0#7", "0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test("-123.0", "-0x7b.0#7", "0", 1, Down, "-0.0", "-0x0.0", Equal); test("-123.0", "-0x7b.0#7", "0", 1, Up, "-0.0", "-0x0.0", Equal); test( "-123.0", "-0x7b.0#7", "0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-123.0", "-0x7b.0#7", "0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test("1.0", "0x1.0#1", "2", 1, Floor, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 1, Ceiling, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 1, Down, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 1, Up, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 1, Nearest, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 1, Exact, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#1", "2", 10, Floor, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.0#1", "2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.0#1", "2", 10, Down, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.0#1", "2", 10, Up, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.0#1", "2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.0#1", "2", 10, Exact, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.0#2", "2", 1, Floor, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 1, Ceiling, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 1, Down, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 1, Up, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 1, Nearest, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 1, Exact, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.0#2", "2", 10, Floor, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.0#2", "2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.0#2", "2", 10, Down, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.0#2", "2", 10, Up, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.0#2", "2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.0#2", "2", 10, Exact, "2.0", "0x2.00#10", Equal); test("1.0", "0x1.000#10", "2", 1, Floor, "2.0", "0x2.0#1", Equal); test( "1.0", "0x1.000#10", "2", 1, Ceiling, "2.0", "0x2.0#1", Equal, ); test("1.0", "0x1.000#10", "2", 1, Down, "2.0", "0x2.0#1", Equal); test("1.0", "0x1.000#10", "2", 1, Up, "2.0", "0x2.0#1", Equal); test( "1.0", "0x1.000#10", "2", 1, Nearest, "2.0", "0x2.0#1", Equal, ); test("1.0", "0x1.000#10", "2", 1, Exact, "2.0", "0x2.0#1", Equal); test( "1.0", "0x1.000#10", "2", 10, Floor, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2", 10, Ceiling, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2", 10, Down, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.000#10", "2", 10, Up, "2.0", "0x2.00#10", Equal); test( "1.0", "0x1.000#10", "2", 10, Nearest, "2.0", "0x2.00#10", Equal, ); test( "1.0", "0x1.000#10", "2", 10, Exact, "2.0", "0x2.00#10", Equal, ); test("1.0", "0x1.000#10", "1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "1.0", "0x1.000#10", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test("1.0", "0x1.000#10", "1/3", 1, Down, "0.2", "0x0.4#1", Less); test("1.0", "0x1.000#10", "1/3", 1, Up, "0.5", "0x0.8#1", Greater); test( "1.0", "0x1.000#10", "1/3", 1, Nearest, "0.2", "0x0.4#1", Less, ); test( "1.0", "0x1.000#10", "1/3", 10, Floor, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.000#10", "1/3", 10, Ceiling, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", 10, Down, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.000#10", "1/3", 10, Up, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.000#10", "1/3", 10, Nearest, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, Down, "0.2", "0x0.4#1", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 1, Nearest, "0.2", "0x0.4#1", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, Floor, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, Ceiling, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, Down, "0.333", "0x0.554#10", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, Up, "0.3335", "0x0.556#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "1/3", 10, Nearest, "0.3335", "0x0.556#10", Greater, ); test("3.0", "0x3.0#2", "2", 1, Floor, "4.0", "0x4.0#1", Less); test("3.0", "0x3.0#2", "2", 1, Ceiling, "8.0", "0x8.0#1", Greater); test("3.0", "0x3.0#2", "2", 1, Down, "4.0", "0x4.0#1", Less); test("3.0", "0x3.0#2", "2", 1, Up, "8.0", "0x8.0#1", Greater); test("3.0", "0x3.0#2", "2", 1, Nearest, "8.0", "0x8.0#1", Greater); test("3.0", "0x3.0#2", "2", 10, Floor, "6.0", "0x6.00#10", Equal); test( "3.0", "0x3.0#2", "2", 10, Ceiling, "6.0", "0x6.00#10", Equal, ); test("3.0", "0x3.0#2", "2", 10, Down, "6.0", "0x6.00#10", Equal); test("3.0", "0x3.0#2", "2", 10, Up, "6.0", "0x6.00#10", Equal); test( "3.0", "0x3.0#2", "2", 10, Nearest, "6.0", "0x6.00#10", Equal, ); test("3.0", "0x3.0#2", "2", 10, Exact, "6.0", "0x6.00#10", Equal); test("3.0", "0x3.00#10", "2", 1, Floor, "4.0", "0x4.0#1", Less); test( "3.0", "0x3.00#10", "2", 1, Ceiling, "8.0", "0x8.0#1", Greater, ); test("3.0", "0x3.00#10", "2", 1, Down, "4.0", "0x4.0#1", Less); test("3.0", "0x3.00#10", "2", 1, Up, "8.0", "0x8.0#1", Greater); test( "3.0", "0x3.00#10", "2", 1, Nearest, "8.0", "0x8.0#1", Greater, ); test( "3.0", "0x3.00#10", "2", 10, Floor, "6.0", "0x6.00#10", Equal, ); test( "3.0", "0x3.00#10", "2", 10, Ceiling, "6.0", "0x6.00#10", Equal, ); test("3.0", "0x3.00#10", "2", 10, Down, "6.0", "0x6.00#10", Equal); test("3.0", "0x3.00#10", "2", 10, Up, "6.0", "0x6.00#10", Equal); test( "3.0", "0x3.00#10", "2", 10, Nearest, "6.0", "0x6.00#10", Equal, ); test( "3.0", "0x3.00#10", "2", 10, Exact, "6.0", "0x6.00#10", Equal, ); test("3.0", "0x3.00#10", "1/3", 1, Floor, "1.0", "0x1.0#1", Equal); test( "3.0", "0x3.00#10", "1/3", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test("3.0", "0x3.00#10", "1/3", 1, Down, "1.0", "0x1.0#1", Equal); test("3.0", "0x3.00#10", "1/3", 1, Up, "1.0", "0x1.0#1", Equal); test( "3.0", "0x3.00#10", "1/3", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test("3.0", "0x3.00#10", "1/3", 1, Exact, "1.0", "0x1.0#1", Equal); test( "3.0", "0x3.00#10", "1/3", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.00#10", "1/3", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.00#10", "1/3", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.00#10", "1/3", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.00#10", "1/3", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.00#10", "1/3", 10, Exact, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Floor, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Down, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Up, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 1, Exact, "1.0", "0x1.0#1", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "3.0", "0x3.0000000000000000000000000#100", "1/3", 10, Exact, "1.0", "0x1.000#10", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, Down, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Floor, "1.047", "0x1.0c0#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "1.049", "0x1.0c8#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Down, "1.047", "0x1.0c0#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Up, "1.049", "0x1.0c8#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Nearest, "1.047", "0x1.0c0#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, Floor, "-2.0", "-0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, Ceiling, "-1.0", "-0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, Down, "-1.0", "-0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, Up, "-2.0", "-0x2.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 1, Nearest, "-1.0", "-0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Floor, "-1.049", "-0x1.0c8#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "-1.047", "-0x1.0c0#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Down, "-1.047", "-0x1.0c0#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Up, "-1.049", "-0x1.0c8#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, Floor, "-2.0", "-0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, Ceiling, "-1.0", "-0x1.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, Down, "-1.0", "-0x1.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, Up, "-2.0", "-0x2.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 1, Nearest, "-1.0", "-0x1.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Floor, "-1.049", "-0x1.0c8#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Down, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Up, "-1.049", "-0x1.0c8#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Nearest, "-1.047", "-0x1.0c0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, Down, "1.0", "0x1.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Floor, "1.047", "0x1.0c0#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "1.049", "0x1.0c8#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Down, "1.047", "0x1.0c0#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Up, "1.049", "0x1.0c8#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "1.047", "0x1.0c0#10", Less, ); } #[test] fn mul_rational_prec_round_fail() { assert_panic!(Float::one_prec(1).mul_rational_prec_round(Rational::ONE, 0, Exact)); assert_panic!(Float::one_prec(1).mul_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).mul_rational_prec_round_val_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).mul_rational_prec_round_ref_val( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).mul_rational_prec_round_ref_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!({ let mut x = Float::one_prec(1); x.mul_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.mul_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn mul_prec_round_properties_helper( x: Float, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (product, o) = x.clone().mul_prec_round(y.clone(), prec, rm); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_prec_round_val_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_prec_round_ref_val(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_prec_round_ref_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } if o == Equal && product.is_finite() && product != 0 { assert_eq!( ComparableFloatRef( &product .div_prec_round_ref_ref(&x, y.significant_bits(), Exact) .0 ), ComparableFloatRef(&y) ); assert_eq!( ComparableFloatRef( &product .div_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 ), ComparableFloatRef(&x) ); } if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); } if !extreme { let r_product = Rational::exact_from(&x) * Rational::exact_from(&y); assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } match (r_product >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (product_alt, o_alt) = y.mul_prec_round_ref_ref(&x, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (mut product_alt, mut o_alt) = x.mul_prec_round_ref_val(-&y, prec, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut product_alt, mut o_alt) = (-&x).mul_prec_round_val_ref(&y, prec, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = (-&x).mul_prec_round(-&y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.mul_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.mul_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn mul_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_3().test_properties(|(x, y, prec, rm)| { mul_prec_round_properties_helper(x, y, prec, rm, false); }); float_float_unsigned_rounding_mode_quadruple_gen_var_7().test_properties(|(x, y, prec, rm)| { mul_prec_round_properties_helper(x, y, prec, rm, true); }); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (product, o) = x.mul_prec_round_ref_val(Float::NAN, prec, rm); assert!(product.is_nan()); assert_eq!(o, Equal); let (product, o) = Float::NAN.mul_prec_round_val_ref(&x, prec, rm); assert!(product.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != 0 { assert_eq!( x.mul_prec_round_ref_val(Float::INFINITY, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::INFINITY.mul_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.mul_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x.is_finite() { assert_eq!( x.mul_prec_round_ref_val(Float::ZERO, prec, rm), (Float::ZERO, Equal) ); assert_eq!( Float::ZERO.mul_prec_round_val_ref(&x, prec, rm), (Float::ZERO, Equal) ); assert_eq!( x.mul_prec_round_ref_val(Float::NEGATIVE_ZERO, prec, rm), (Float::ZERO, Equal) ); assert_eq!( Float::NEGATIVE_ZERO.mul_prec_round_val_ref(&x, prec, rm), (Float::ZERO, Equal) ); } } if !x.is_negative_zero() { let (product, o) = x.mul_prec_round_ref_val(Float::ONE, prec, rm); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); let (product, o) = Float::ONE.mul_prec_round_val_ref(&x, prec, rm); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); } }); } fn mul_prec_properties_helper(x: Float, y: Float, prec: u64, extreme: bool) { let (product, o) = x.clone().mul_prec(y.clone(), prec); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_prec_val_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_prec_ref_val(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_prec_ref_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } let (rug_product, rug_o) = rug_mul_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); if o == Equal && product.is_finite() && product != 0 { assert_eq!( ComparableFloatRef(&product.div_prec_ref_ref(&x, y.significant_bits()).0), ComparableFloatRef(&y) ); assert_eq!( ComparableFloatRef(&product.div_prec_ref_ref(&y, x.significant_bits()).0), ComparableFloatRef(&x) ); } let (product_alt, o_alt) = x.mul_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); } if !extreme { let r_product = Rational::exact_from(&x) * Rational::exact_from(&y); assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } } } let (product_alt, o_alt) = y.mul_prec_ref_ref(&x, prec); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let (mut product_alt, mut o_alt) = x.mul_prec_ref_val(-&y, prec); product_alt.neg_assign(); product_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut product_alt, mut o_alt) = (-&x).mul_prec_val_ref(&y, prec); product_alt.neg_assign(); product_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = (-x).mul_prec(-y, prec); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } } #[test] fn mul_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { mul_prec_properties_helper(x, y, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { mul_prec_properties_helper(x, y, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("small_n", 16 << Limb::LOG_WIDTH); float_float_unsigned_triple_gen_var_1().test_properties_with_config(&config, |(x, y, prec)| { mul_prec_properties_helper(x, y, prec, false); }); float_float_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { mul_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (product, o) = x.mul_prec_ref_val(Float::NAN, prec); assert!(product.is_nan()); assert_eq!(o, Equal); let (product, o) = Float::NAN.mul_prec_val_ref(&x, prec); assert!(product.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != 0 { assert_eq!( x.mul_prec_ref_val(Float::INFINITY, prec), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::INFINITY.mul_prec_val_ref(&x, prec), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.mul_prec_ref_val(Float::NEGATIVE_INFINITY, prec), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_prec_val_ref(&x, prec), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x.is_finite() { assert_eq!(x.mul_prec_ref_val(Float::ZERO, prec), (Float::ZERO, Equal)); assert_eq!(Float::ZERO.mul_prec_val_ref(&x, prec), (Float::ZERO, Equal)); assert_eq!( x.mul_prec_ref_val(Float::NEGATIVE_ZERO, prec), (Float::ZERO, Equal) ); assert_eq!( Float::NEGATIVE_ZERO.mul_prec_val_ref(&x, prec), (Float::ZERO, Equal) ); } } if !x.is_negative_zero() { let (product, o) = x.mul_prec_ref_val(Float::ONE, prec); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec(prec); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); let (product, o) = Float::ONE.mul_prec_val_ref(&x, prec); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec(prec); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); } }); } #[allow(clippy::needless_pass_by_value)] fn mul_round_properties_helper(x: Float, y: Float, rm: RoundingMode, extreme: bool) { let (product, o) = x.clone().mul_round(y.clone(), rm); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_round_val_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o_alt) = x.mul_round_ref_val(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o_alt) = x.mul_round_ref_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let mut x_alt = x.clone(); let o_alt = x_alt.mul_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if o == Equal && product.is_finite() && product != 0 { assert_eq!(product.div_round_ref_ref(&x, Exact).0, y); assert_eq!(product.div_round_ref_ref(&y, Exact).0, x); } if product.is_finite() { if x.is_normal() && y.is_normal() && product.is_normal() { assert_eq!( product.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); } if !extreme { let r_product = Rational::exact_from(&x) * Rational::exact_from(&y); assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } match (r_product >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } let (product_alt, o_alt) = y.mul_round_ref_ref(&x, rm); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (mut product_alt, mut o_alt) = x.mul_round_ref_val(-&y, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); let (mut product_alt, mut o_alt) = (-&x).mul_round_val_ref(&y, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); let (product_alt, o_alt) = (-&x).mul_round(-&y, rm); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.mul_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.mul_round_ref_ref(&y, Exact)); } } #[test] fn mul_round_properties() { float_float_rounding_mode_triple_gen_var_16().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_17().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_18().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_19().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_20().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_21().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_22().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_31().test_properties(|(x, y, rm)| { mul_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (product, o) = x.mul_round_ref_val(Float::NAN, rm); assert!(product.is_nan()); assert_eq!(o, Equal); let (product, o) = Float::NAN.mul_round_val_ref(&x, rm); assert!(product.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != 0 { assert_eq!( x.mul_round_ref_val(Float::INFINITY, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::INFINITY.mul_round_val_ref(&x, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( x.mul_round_ref_val(Float::NEGATIVE_INFINITY, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_round_val_ref(&x, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } if x.is_finite() { assert_eq!(x.mul_round_ref_val(Float::ZERO, rm), (Float::ZERO, Equal)); assert_eq!(Float::ZERO.mul_round_val_ref(&x, rm), (Float::ZERO, Equal)); assert_eq!( x.mul_round_ref_val(Float::NEGATIVE_ZERO, rm), (Float::ZERO, Equal) ); assert_eq!( Float::NEGATIVE_ZERO.mul_round_val_ref(&x, rm), (Float::ZERO, Equal) ); } } if !x.is_negative_zero() { let (product, o) = x.mul_round_ref_val(Float::ONE, rm); assert_eq!(ComparableFloatRef(&product), ComparableFloatRef(&x)); assert_eq!(o, Equal); let (product, o) = Float::ONE.mul_round_val_ref(&x, rm); assert_eq!(ComparableFloatRef(&product), ComparableFloatRef(&x)); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn mul_properties_helper_1(x: Float, y: Float, extreme: bool) { let product = x.clone() * y.clone(); assert!(product.is_valid()); let product_alt = x.clone() * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &x * y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &x * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let mut x_alt = x.clone(); x_alt *= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); let mut x_alt = x.clone(); x_alt *= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); if !extreme { let product_alt = mul_prec_round_naive( x.clone(), y.clone(), max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); } let product_alt = x .mul_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = x .mul_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o) = x.mul_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); if o == Equal && product.is_finite() && product != 0 { assert_eq!(&product / &x, y); assert_eq!(&product / &y, x); } if product.is_finite() && x.is_normal() && y.is_normal() && product.is_normal() { assert_eq!( product.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); if !extreme { let r_product = Rational::exact_from(&x) * Rational::exact_from(&y); if product < r_product { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if product > r_product { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } } } let rug_product = rug_mul(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); let product_alt = &y * &x; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { assert_eq!(ComparableFloatRef(&(&y * &x)), ComparableFloatRef(&product)); assert_eq!( ComparableFloatRef(&-(&x * -&y)), ComparableFloatRef(&product) ); assert_eq!( ComparableFloatRef(&-(-&x * &y)), ComparableFloatRef(&product) ); assert_eq!( ComparableFloatRef(&(-&x * -&y)), ComparableFloatRef(&product) ); } } #[allow(clippy::type_repetition_in_bounds)] fn mul_properties_helper_2() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { let product_1 = x * y; let product_2 = emulate_float_float_to_float_fn(Float::mul_prec, x, y); assert_eq!(NiceFloat(product_1), NiceFloat(product_2)); }); } #[test] fn mul_properties() { float_pair_gen().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_pair_gen().test_properties_with_config(&config, |(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_2().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_3().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_4().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_5().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_6().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_7().test_properties(|(x, y)| { mul_properties_helper_1(x, y, false); }); float_pair_gen_var_10().test_properties(|(x, y)| { mul_properties_helper_1(x, y, true); }); apply_fn_to_primitive_floats!(mul_properties_helper_2); float_gen().test_properties(|x| { assert!((&x * Float::NAN).is_nan()); assert!((Float::NAN * &x).is_nan()); if !x.is_nan() { if x != 0 { assert_eq!( &x * Float::INFINITY, if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( Float::INFINITY * &x, if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( &x * Float::NEGATIVE_INFINITY, if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); assert_eq!( Float::NEGATIVE_INFINITY * &x, if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); } if x.is_finite() { assert_eq!(&x * Float::ZERO, Float::ZERO); assert_eq!(Float::ZERO * &x, Float::ZERO); assert_eq!(&x * Float::NEGATIVE_ZERO, Float::ZERO); assert_eq!(Float::NEGATIVE_ZERO * &x, Float::ZERO); } assert_eq!(&x * Float::ONE, x); assert_eq!(Float::ONE * &x, x); } }); } #[allow(clippy::needless_pass_by_value)] fn mul_rational_prec_round_properties_helper( x: Float, y: Rational, prec: u64, rm: RoundingMode, extreme: bool, ) { let (product, o) = x.clone().mul_rational_prec_round(y.clone(), prec, rm); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_rational_prec_round_val_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, prec, rm); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_naive_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_val_ref(x.clone(), &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_val(&x, y.clone(), prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = mul_rational_prec_round_direct_ref_ref(&x, &y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } if o == Equal && product.is_finite() && product != 0 { assert_eq!( ComparableFloatRef( &product .div_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 ), ComparableFloatRef(&x) ); // TODO additional test } if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); } if !extreme { let r_product = Rational::exact_from(&x) * &y; assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } match (r_product >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut product_alt, mut o_alt) = x.mul_rational_prec_round_ref_val(-&y, prec, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut product_alt, mut o_alt) = (-&x).mul_rational_prec_round_val_ref(&y, prec, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(product_alt.abs_negative_zero()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if product != 0u32 { let (product_alt, o_alt) = (-&x).mul_rational_prec_round(-&y, prec, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.mul_rational_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.mul_rational_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn mul_rational_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_3().test_properties( |(x, y, prec, rm)| { mul_rational_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_rational_unsigned_rounding_mode_quadruple_gen_var_8().test_properties( |(x, y, prec, rm)| { mul_rational_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_negative_zero() { let (product, o) = x.mul_rational_prec_round_ref_val(Rational::ONE, prec, rm); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (product, o) = Float::NAN.mul_rational_prec_round_val_ref(&x, prec, rm); assert!(product.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::INFINITY.mul_rational_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_rational_prec_round_val_ref(&x, prec, rm), ( if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } let (product, o) = Float::ZERO.mul_rational_prec_round_val_ref(&x, prec, rm); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); let (product, o) = Float::NEGATIVE_ZERO.mul_rational_prec_round_val_ref(&x, prec, rm); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }) ); assert_eq!(o, Equal); }); } fn mul_rational_prec_properties_helper(x: Float, y: Rational, prec: u64, extreme: bool) { let (product, o) = x.clone().mul_rational_prec(y.clone(), prec); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_rational_prec_val_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_ref_val(y.clone(), prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = x.mul_rational_prec_ref_ref(&y, prec); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } let (rug_product, rug_o) = rug_mul_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); if o == Equal && product.is_finite() && product != 0 { assert_eq!( ComparableFloatRef( &product .div_rational_prec_ref_ref(&y, x.significant_bits()) .0 ), ComparableFloatRef(&x) ); // TODO additional test } let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if product.is_finite() { if product.is_normal() { assert_eq!(product.get_prec(), Some(prec)); } if !extreme { let r_product = Rational::exact_from(&x) * &y; assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } } } if x != 0u32 && y != 0u32 { let (mut product_alt, mut o_alt) = x.mul_rational_prec_ref_val(-&y, prec); product_alt.neg_assign(); product_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut product_alt, mut o_alt) = (-&x).mul_rational_prec_val_ref(&y, prec); product_alt.neg_assign(); product_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (product_alt, o_alt) = (-x).mul_rational_prec(-y, prec); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } } #[test] fn mul_rational_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { mul_rational_prec_properties_helper(x, y, prec, false); }); float_rational_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { mul_rational_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_negative_zero() { let (product, o) = x.mul_rational_prec_ref_val(Rational::ONE, prec); let mut product_alt = x.clone(); let o_alt = product_alt.set_prec(prec); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); } if x.is_finite() && !x.is_negative_zero() { let (product, o) = x.mul_rational_prec_ref_val(Rational::ZERO, prec); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (product, o) = Float::NAN.mul_rational_prec_val_ref(&x, prec); assert!(product.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::INFINITY.mul_rational_prec_val_ref(&x, prec), ( if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_rational_prec_val_ref(&x, prec), ( if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } let (product, o) = Float::ONE.mul_rational_prec_val_ref(&x, prec); let (product_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); let (product, o) = Float::ZERO.mul_rational_prec_val_ref(&x, prec); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); let (product, o) = Float::NEGATIVE_ZERO.mul_rational_prec_val_ref(&x, prec); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::NEGATIVE_ZERO } else { Float::ZERO }) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn mul_rational_round_properties_helper(x: Float, y: Rational, rm: RoundingMode, extreme: bool) { let (product, o) = x.clone().mul_rational_round(y.clone(), rm); assert!(product.is_valid()); let (product_alt, o_alt) = x.clone().mul_rational_round_val_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o_alt) = x.mul_rational_round_ref_val(y.clone(), rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o_alt) = x.mul_rational_round_ref_ref(&y, rm); assert!(product_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.mul_rational_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); assert_eq!(o_alt, o); if !extreme { let (product_alt, o_alt) = mul_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } if x.is_normal() { let (product_alt, o_alt) = mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); } let (product_alt, o_alt) = x.mul_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); assert_eq!(o_alt, o); if o == Equal && product.is_finite() && product != 0 { assert_eq!(product.div_rational_round_ref_ref(&y, Exact).0, x); // TODO additional test } if product.is_finite() { if x.is_normal() && product.is_normal() { assert_eq!(product.get_prec(), Some(x.get_prec().unwrap())); } if !extreme { let r_product = Rational::exact_from(&x) * &y; assert_eq!(product.partial_cmp(&r_product), Some(o)); if o == Less { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if o == Greater { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } match (r_product >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_product, rug_o) = rug_mul_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); assert_eq!(rug_o, o); } let (mut product_alt, mut o_alt) = x.mul_rational_round_ref_val(-&y, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(product_alt.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); let (mut product_alt, mut o_alt) = (-&x).mul_rational_round_val_ref(&y, -rm); product_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(product_alt.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); if x != 0 && y != 0 { let (product_alt, o_alt) = (-&x).mul_rational_round(-&y, rm); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product), ); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.mul_rational_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(product.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.mul_rational_round_ref_ref(&y, Exact)); } } #[test] fn mul_rational_round_properties() { float_rational_rounding_mode_triple_gen_var_4().test_properties(|(x, y, rm)| { mul_rational_round_properties_helper(x, y, rm, false); }); float_rational_rounding_mode_triple_gen_var_9().test_properties(|(x, y, rm)| { mul_rational_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (product, o) = x.mul_rational_round_ref_val(Rational::ONE, rm); assert_eq!(ComparableFloatRef(&product), ComparableFloatRef(&x)); assert_eq!(o, Equal); if x.is_finite() && !x.is_negative_zero() { let (product, o) = x.mul_rational_round_ref_val(Rational::ZERO, rm); assert_eq!( ComparableFloat(product), ComparableFloat(if x >= 0 { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (product, o) = Float::NAN.mul_rational_round_val_ref(&x, rm); assert!(product.is_nan()); assert_eq!(o, Equal); if x != 0 { assert_eq!( Float::INFINITY.mul_rational_round_val_ref(&x, rm), ( if x >= 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY }, Equal ) ); assert_eq!( Float::NEGATIVE_INFINITY.mul_rational_round_val_ref(&x, rm), ( if x >= 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY }, Equal ) ); } let (product, o) = Float::ONE.mul_rational_round_val_ref(&x, rm); let (product_alt, o_alt) = Float::from_rational_prec_round_ref(&x, 1, rm); assert_eq!(ComparableFloat(product), ComparableFloat(product_alt)); assert_eq!(o, o_alt); }); } fn mul_rational_properties_helper(x: Float, y: Rational, extreme: bool) { let product = x.clone() * y.clone(); assert!(product.is_valid()); let product_alt = x.clone() * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &x * y.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &x * &y; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = y.clone() * x.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = y.clone() * &x; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &y * x.clone(); assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = &y * &x; assert!(product_alt.is_valid()); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let mut x_alt = x.clone(); x_alt *= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); let mut x_alt = x.clone(); x_alt *= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&product)); if !extreme { let product_alt = mul_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); } if x.is_normal() { let product_alt = mul_rational_prec_round_direct(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); } let product_alt = x .mul_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let product_alt = x.mul_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); let (product_alt, o) = x.mul_rational_round_ref_ref(&y, Nearest); assert_eq!( ComparableFloatRef(&product_alt), ComparableFloatRef(&product) ); if o == Equal && product.is_finite() && product != 0 { assert_eq!(&product / &y, x); // TODO additional test } if product.is_finite() && x.is_normal() && product.is_normal() { assert_eq!(product.get_prec(), Some(x.get_prec().unwrap())); if !extreme { let r_product = Rational::exact_from(&x) * &y; if product < r_product { let mut next = product.clone(); next.increment(); assert!(next > r_product); } else if product > r_product { let mut next = product.clone(); next.decrement(); assert!(next < r_product); } } } let rug_product = rug_mul_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_product)), ComparableFloatRef(&product), ); if product != 0u32 { assert_eq!( ComparableFloatRef(&-(-&x * &y)), ComparableFloatRef(&product) ); assert_eq!( ComparableFloatRef(&-(&x * -&y)), ComparableFloatRef(&product) ); assert_eq!(ComparableFloatRef(&(-x * -y)), ComparableFloatRef(&product)); } } #[test] fn mul_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { mul_rational_properties_helper(x, y, false); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { mul_rational_properties_helper(x, y, true); }); float_gen().test_properties(|x| { assert_eq!( ComparableFloatRef(&(&x * Rational::ONE)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&(Rational::ONE * &x)), ComparableFloatRef(&x) ); if x.is_finite() { assert_eq!( ComparableFloat(&x * Rational::ZERO), ComparableFloat(if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }), ); assert_eq!( ComparableFloat(Rational::ZERO * &x), ComparableFloat(if x.is_sign_positive() { Float::ZERO } else { Float::NEGATIVE_ZERO }) ); } }); rational_gen().test_properties(|x| { assert!((&x * Float::NAN).is_nan()); assert!((Float::NAN * &x).is_nan()); if x != 0 { assert_eq!( &x * Float::INFINITY, if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( Float::INFINITY * &x, if x > 0 { Float::INFINITY } else { Float::NEGATIVE_INFINITY } ); assert_eq!( &x * Float::NEGATIVE_INFINITY, if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); assert_eq!( Float::NEGATIVE_INFINITY * &x, if x > 0 { Float::NEGATIVE_INFINITY } else { Float::INFINITY } ); } let product_alt = Float::from_rational_prec_ref(&x, 1).0; assert_eq!( ComparableFloat(&x * Float::ONE), ComparableFloat(product_alt.clone()) ); assert_eq!( ComparableFloat(Float::ONE * &x), ComparableFloat(product_alt.clone()) ); assert_eq!( ComparableFloat((&x * Float::ZERO).abs_negative_zero()), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat((Float::ZERO * &x).abs_negative_zero()), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat((&x * Float::NEGATIVE_ZERO).abs_negative_zero()), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat((Float::NEGATIVE_ZERO * &x).abs_negative_zero()), ComparableFloat(Float::ZERO) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::primitive_float_gen; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{float_gen, float_gen_var_4, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; #[test] fn test_neg() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let neg = -x.clone(); assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); assert_eq!(to_hex_string(&neg), out_hex); let neg_alt = -&x; assert!(neg_alt.is_valid()); assert_eq!(ComparableFloatRef(&neg), ComparableFloatRef(&neg_alt)); let mut neg_alt = x.clone(); neg_alt.neg_assign(); assert!(neg_alt.is_valid()); assert_eq!(ComparableFloatRef(&neg), ComparableFloatRef(&neg_alt)); assert_eq!( ComparableFloat(Float::from(&-rug::Float::exact_from(&x))), ComparableFloat(neg) ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", "Infinity", "Infinity"); test("0.0", "0x0.0", "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0"); test("1.0", "0x1.0#1", "-1.0", "-0x1.0#1"); test("2.0", "0x2.0#1", "-2.0", "-0x2.0#1"); test("0.5", "0x0.8#1", "-0.5", "-0x0.8#1"); test( "0.33333333333333331", "0x0.55555555555554#53", "-0.33333333333333331", "-0x0.55555555555554#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "too_big", "0x4.0E+268435455#1", "-too_big", "-0x4.0E+268435455#1", ); test( "too_small", "0x1.0E-268435456#1", "-too_small", "-0x1.0E-268435456#1", ); test("-1.0", "-0x1.0#1", "1.0", "0x1.0#1"); test("-2.0", "-0x2.0#1", "2.0", "0x2.0#1"); test("-0.5", "-0x0.8#1", "0.5", "0x0.8#1"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0.33333333333333331", "0x0.55555555555554#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "-too_big", "-0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", ); test( "-too_small", "-0x1.0E-268435456#1", "too_small", "0x1.0E-268435456#1", ); } fn neg_properties_helper(x: Float) { let neg = -x.clone(); assert!(neg.is_valid()); let neg_alt = -&x; assert!(neg_alt.is_valid()); assert_eq!(ComparableFloatRef(&neg), ComparableFloatRef(&neg_alt)); let mut neg_alt = x.clone(); neg_alt.neg_assign(); assert!(neg_alt.is_valid()); assert_eq!(ComparableFloatRef(&neg), ComparableFloatRef(&neg_alt)); assert_eq!( ComparableFloatRef(&-Float::from(&rug::Float::exact_from(&x))), ComparableFloatRef(&neg) ); assert_eq!( ComparableFloatRef(&neg) == ComparableFloatRef(&x), x.is_nan() ); assert_eq!(ComparableFloat(-neg), ComparableFloat(x)); } #[test] fn neg_properties() { float_gen().test_properties(|x| { neg_properties_helper(x); }); float_gen_var_12().test_properties(|x| { neg_properties_helper(x); }); float_gen_var_4().test_properties(|x| { assert_eq!(Rational::exact_from(-&x), -Rational::exact_from(x)); }); primitive_float_gen::().test_properties(|x| { assert_eq!( ComparableFloat(Float::from(-x)), ComparableFloat(-Float::from(x)) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2}; use malachite_base::num::basic::traits::Infinity; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, signed_unsigned_pair_gen_var_19, signed_unsigned_pair_gen_var_20, unsigned_gen, unsigned_gen_var_5, }; use malachite_float::test_util::arithmetic::power_of_2::{ power_of_2_i64_naive, power_of_2_prec_naive, power_of_2_prec_round_naive, power_of_2_u64_naive, }; use malachite_float::test_util::arithmetic::shl_round::rug_shl_prec_round_signed; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::{ signed_unsigned_rounding_mode_triple_gen_var_5, signed_unsigned_rounding_mode_triple_gen_var_6, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_power_of_2_prec_round() { let test = |i: i64, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, o_out| { let (p, o) = Float::power_of_2_prec_round(i, prec, rm); assert!(p.is_valid()); assert_eq!(o, o_out); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); let (p_alt, o_alt) = power_of_2_prec_round_naive(i, prec, rm); assert_eq!(p_alt.to_string(), out); assert_eq!(to_hex_string(&p_alt), out_hex); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_p, o) = rug_shl_prec_round_signed( &rug::Float::with_val(1, 1), i32::exact_from(i), prec, rm, ); let p = Float::exact_from(&rug_p); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); assert_eq!(o, o_out); } }; test(0, 1, Floor, "1.0", "0x1.0#1", Equal); test(0, 1, Ceiling, "1.0", "0x1.0#1", Equal); test(0, 1, Down, "1.0", "0x1.0#1", Equal); test(0, 1, Up, "1.0", "0x1.0#1", Equal); test(0, 1, Nearest, "1.0", "0x1.0#1", Equal); test(0, 1, Exact, "1.0", "0x1.0#1", Equal); test( 0, 100, Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( 0, 100, Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( 0, 100, Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( 0, 100, Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( 0, 100, Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( 0, 100, Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test(1, 1, Floor, "2.0", "0x2.0#1", Equal); test(1, 1, Ceiling, "2.0", "0x2.0#1", Equal); test(1, 1, Down, "2.0", "0x2.0#1", Equal); test(1, 1, Up, "2.0", "0x2.0#1", Equal); test(1, 1, Nearest, "2.0", "0x2.0#1", Equal); test(1, 1, Exact, "2.0", "0x2.0#1", Equal); test( 1, 100, Floor, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( 1, 100, Ceiling, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( 1, 100, Down, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( 1, 100, Up, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( 1, 100, Nearest, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test( 1, 100, Exact, "2.0", "0x2.0000000000000000000000000#100", Equal, ); test(100, 1, Floor, "1.0e30", "0x1.0E+25#1", Equal); test(100, 1, Ceiling, "1.0e30", "0x1.0E+25#1", Equal); test(100, 1, Down, "1.0e30", "0x1.0E+25#1", Equal); test(100, 1, Up, "1.0e30", "0x1.0E+25#1", Equal); test(100, 1, Nearest, "1.0e30", "0x1.0E+25#1", Equal); test(100, 1, Exact, "1.0e30", "0x1.0E+25#1", Equal); test( 100, 100, Floor, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test( 100, 100, Ceiling, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test( 100, 100, Down, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test( 100, 100, Up, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test( 100, 100, Nearest, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test( 100, 100, Exact, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test(1073741822, 1, Floor, "too_big", "0x4.0E+268435455#1", Equal); test( 1073741822, 1, Ceiling, "too_big", "0x4.0E+268435455#1", Equal, ); test(1073741822, 1, Down, "too_big", "0x4.0E+268435455#1", Equal); test(1073741822, 1, Up, "too_big", "0x4.0E+268435455#1", Equal); test( 1073741822, 1, Nearest, "too_big", "0x4.0E+268435455#1", Equal, ); test(1073741822, 1, Exact, "too_big", "0x4.0E+268435455#1", Equal); test( 1073741822, 100, Floor, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test( 1073741822, 100, Ceiling, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test( 1073741822, 100, Down, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test( 1073741822, 100, Up, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test( 1073741822, 100, Nearest, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test( 1073741822, 100, Exact, "too_big", "0x4.0000000000000000000000000E+268435455#100", Equal, ); test(1073741823, 1, Floor, "too_big", "0x4.0E+268435455#1", Less); test(1073741823, 1, Ceiling, "Infinity", "Infinity", Greater); test(1073741823, 1, Down, "too_big", "0x4.0E+268435455#1", Less); test(1073741823, 1, Up, "Infinity", "Infinity", Greater); test(1073741823, 1, Nearest, "Infinity", "Infinity", Greater); test( 1073741823, 100, Floor, "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", Less, ); test(1073741823, 100, Ceiling, "Infinity", "Infinity", Greater); test( 1073741823, 100, Down, "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", Less, ); test(1073741823, 100, Up, "Infinity", "Infinity", Greater); test(1073741823, 100, Nearest, "Infinity", "Infinity", Greater); test(-1, 1, Floor, "0.5", "0x0.8#1", Equal); test(-1, 1, Ceiling, "0.5", "0x0.8#1", Equal); test(-1, 1, Down, "0.5", "0x0.8#1", Equal); test(-1, 1, Up, "0.5", "0x0.8#1", Equal); test(-1, 1, Nearest, "0.5", "0x0.8#1", Equal); test(-1, 1, Exact, "0.5", "0x0.8#1", Equal); test( -1, 100, Floor, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( -1, 100, Ceiling, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( -1, 100, Down, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( -1, 100, Up, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( -1, 100, Nearest, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( -1, 100, Exact, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test(-100, 1, Floor, "8.0e-31", "0x1.0E-25#1", Equal); test(-100, 1, Ceiling, "8.0e-31", "0x1.0E-25#1", Equal); test(-100, 1, Down, "8.0e-31", "0x1.0E-25#1", Equal); test(-100, 1, Up, "8.0e-31", "0x1.0E-25#1", Equal); test(-100, 1, Nearest, "8.0e-31", "0x1.0E-25#1", Equal); test(-100, 1, Exact, "8.0e-31", "0x1.0E-25#1", Equal); test( -1073741824, 1, Floor, "too_small", "0x1.0E-268435456#1", Equal, ); test( -1073741824, 1, Ceiling, "too_small", "0x1.0E-268435456#1", Equal, ); test( -1073741824, 1, Down, "too_small", "0x1.0E-268435456#1", Equal, ); test(-1073741824, 1, Up, "too_small", "0x1.0E-268435456#1", Equal); test( -1073741824, 1, Nearest, "too_small", "0x1.0E-268435456#1", Equal, ); test( -1073741824, 1, Exact, "too_small", "0x1.0E-268435456#1", Equal, ); test( -1073741824, 100, Floor, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test( -1073741824, 100, Ceiling, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test( -1073741824, 100, Down, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test( -1073741824, 100, Up, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test( -1073741824, 100, Nearest, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test( -1073741824, 100, Exact, "too_small", "0x1.0000000000000000000000000E-268435456#100", Equal, ); test(-1073741825, 1, Floor, "0.0", "0x0.0", Less); test( -1073741825, 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test(-1073741825, 1, Down, "0.0", "0x0.0", Less); test( -1073741825, 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test(-1073741825, 1, Nearest, "0.0", "0x0.0", Less); test(-1073741825, 100, Floor, "0.0", "0x0.0", Less); test( -1073741825, 100, Ceiling, "too_small", "0x1.0000000000000000000000000E-268435456#100", Greater, ); test(-1073741825, 100, Down, "0.0", "0x0.0", Less); test( -1073741825, 100, Up, "too_small", "0x1.0000000000000000000000000E-268435456#100", Greater, ); test(-1073741825, 100, Nearest, "0.0", "0x0.0", Less); } #[test] fn power_of_2_prec_round_fail() { assert_panic!(Float::power_of_2_prec_round(0, 0, Floor)); assert_panic!(Float::power_of_2_prec_round(1073741823, 1, Exact)); assert_panic!(Float::power_of_2_prec_round(1073741823, 100, Exact)); assert_panic!(Float::power_of_2_prec_round(-1073741825, 1, Exact)); assert_panic!(Float::power_of_2_prec_round(-1073741825, 100, Exact)); } fn power_of_2_prec_round_properties_helper(i: i64, prec: u64, rm: RoundingMode) { let (p, o) = Float::power_of_2_prec_round(i, prec, rm); assert!(p.is_valid()); assert!(p.is_finite() || p == Float::INFINITY || p.is_positive_zero()); assert!(p >= 0u32); if p.is_normal() { assert_eq!(p.get_prec(), Some(prec)); } else { assert_eq!(o, if p > 0 { Greater } else { Less }); } if i.lt_abs(&1_000_000_000) { let (p_alt, o_alt) = power_of_2_prec_round_naive(i, prec, rm); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); assert_eq!(o_alt, o); } if rm == Exact { assert_eq!(o, Equal); } else { let rm = rug_round_try_from_rounding_mode(rm).unwrap(); if i32::convertible_from(i) { let (rug_p, rug_o) = rug_shl_prec_round_signed( &rug::Float::with_val(1, 1), i32::exact_from(i), prec, rm, ); assert_eq!( ComparableFloat(Float::exact_from(&rug_p)), ComparableFloat(p) ); assert_eq!(rug_o, o); } } } #[test] fn power_of_2_prec_round_properties() { signed_unsigned_rounding_mode_triple_gen_var_5().test_properties(|(i, prec, rm)| { power_of_2_prec_round_properties_helper(i, prec, rm); }); signed_unsigned_rounding_mode_triple_gen_var_6().test_properties(|(i, prec, rm)| { power_of_2_prec_round_properties_helper(i, prec, rm); }); } #[test] fn test_power_of_2_prec() { let test = |i: i64, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let (p, o) = Float::power_of_2_prec(i, prec); assert!(p.is_valid()); assert_eq!(o, o_out); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); let (p_alt, o_alt) = power_of_2_prec_naive(i, prec); assert_eq!(p_alt.to_string(), out); assert_eq!(to_hex_string(&p_alt), out_hex); assert_eq!(o_alt, o_out); let rug_p = rug::Float::with_val(u32::exact_from(prec), 1) << i32::exact_from(i); let p = Float::exact_from(&rug_p); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); }; test(0, 1, "1.0", "0x1.0#1", Equal); test(0, 100, "1.0", "0x1.0000000000000000000000000#100", Equal); test(1, 1, "2.0", "0x2.0#1", Equal); test(1, 100, "2.0", "0x2.0000000000000000000000000#100", Equal); test(100, 1, "1.0e30", "0x1.0E+25#1", Equal); test( 100, 100, "1267650600228229401496703205376.0", "0x10000000000000000000000000.0#100", Equal, ); test(1073741822, 1, "too_big", "0x4.0E+268435455#1", Equal); test(1073741823, 1, "Infinity", "Infinity", Greater); test(-1, 1, "0.5", "0x0.8#1", Equal); test(-1, 100, "0.5", "0x0.8000000000000000000000000#100", Equal); test(-100, 1, "8.0e-31", "0x1.0E-25#1", Equal); test( -100, 100, "7.88860905221011805411728565283e-31", "0x1.0000000000000000000000000E-25#100", Equal, ); test(-1073741824, 1, "too_small", "0x1.0E-268435456#1", Equal); test(-1073741825, 1, "0.0", "0x0.0", Less); } #[test] #[should_panic] fn power_of_2_prec_fail() { Float::power_of_2_prec(0, 0); } fn power_of_2_prec_properties_helper(i: i64, prec: u64) { let (p, o) = Float::power_of_2_prec(i, prec); assert!(p.is_valid()); assert!(p.is_finite() || p == Float::INFINITY || p.is_positive_zero()); assert!(p >= 0u32); assert_eq!(Float::power_of_2(i), p); let (p_alt, o_alt) = Float::power_of_2_prec_round(i, prec, Nearest); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); assert_eq!(o, o_alt); if p.is_normal() { assert_eq!(o, Equal); assert_eq!(p.get_prec(), Some(prec)); assert!(p.is_power_of_2()); } else { assert_eq!(o, if p > 0 { Greater } else { Less }); } if i.lt_abs(&1_000_000_000) { let (p_alt, o_alt) = power_of_2_prec_naive(i, prec); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); assert_eq!(o_alt, o); } if o == Equal { for rm in exhaustive_rounding_modes() { let (p_alt, o_alt) = Float::power_of_2_prec_round(i, prec, rm); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); assert_eq!(o_alt, Equal); } } if let Ok(i) = i32::try_from(i) { let rug_p = rug::Float::with_val(u32::exact_from(prec), 1) << i; assert_eq!( ComparableFloatRef(&Float::from(&rug_p)), ComparableFloatRef(&p) ); } } #[test] fn power_of_2_prec_properties() { signed_unsigned_pair_gen_var_19::().test_properties(|(i, prec)| { power_of_2_prec_properties_helper(i, prec); }); signed_unsigned_pair_gen_var_20::().test_properties(|(i, prec)| { power_of_2_prec_properties_helper(i, prec); }); } #[test] fn test_power_of_2() { let test = |i: i64, out: &str, out_hex: &str| { let p = Float::power_of_2(i); assert!(p.is_valid()); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); let p_alt = power_of_2_i64_naive(i); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); let rug_p = rug::Float::with_val(1, 1) << i32::exact_from(i); let p = Float::exact_from(&rug_p); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); }; test(0, "1.0", "0x1.0#1"); test(1, "2.0", "0x2.0#1"); test(2, "4.0", "0x4.0#1"); test(3, "8.0", "0x8.0#1"); test(1073741822, "too_big", "0x4.0E+268435455#1"); test(1073741823, "Infinity", "Infinity"); test(-1, "0.5", "0x0.8#1"); test(-2, "0.2", "0x0.4#1"); test(-3, "0.1", "0x0.2#1"); test(-100, "8.0e-31", "0x1.0E-25#1"); test(-1073741824, "too_small", "0x1.0E-268435456#1"); test(-1073741825, "0.0", "0x0.0"); let test = |u: u64, out: &str, out_hex: &str| { let p = Float::power_of_2(u); assert!(p.is_valid()); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); let p_alt = power_of_2_u64_naive(u); assert_eq!(p_alt.to_string(), out); assert_eq!(to_hex_string(&p_alt), out_hex); let rug_p = rug::Float::with_val(1, 1) << u32::exact_from(u); let p = Float::exact_from(&rug_p); assert_eq!(p.to_string(), out); assert_eq!(to_hex_string(&p), out_hex); }; test(0, "1.0", "0x1.0#1"); test(1, "2.0", "0x2.0#1"); test(2, "4.0", "0x4.0#1"); test(3, "8.0", "0x8.0#1"); test(100, "1.0e30", "0x1.0E+25#1"); test(1073741822, "too_big", "0x4.0E+268435455#1"); test(1073741823, "Infinity", "Infinity"); } fn power_of_2_properties_signed_helper(i: i64) { let p = Float::power_of_2(i); assert!(p.is_valid()); assert!(p.is_finite() || p == Float::INFINITY || p.is_positive_zero()); assert!(p >= 0u32); if p.is_normal() { assert!(p.is_power_of_2()); assert_eq!(p.get_prec(), Some(1)); } assert_eq!( ComparableFloatRef(&Float::power_of_2_prec(i, 1).0), ComparableFloatRef(&p) ); if i >= 0 { assert_eq!( ComparableFloatRef(&Float::power_of_2(i.unsigned_abs())), ComparableFloatRef(&p) ); } if i.lt_abs(&1_000_000_000) { let p_alt = power_of_2_i64_naive(i); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); } if let Ok(i) = u32::try_from(i) { let rug_p = rug::Float::with_val(1, 1) << i; assert_eq!( ComparableFloatRef(&Float::from(&rug_p)), ComparableFloatRef(&p) ); } } fn power_of_2_properties_unsigned_helper(u: u64) { let p = Float::power_of_2(u); assert!(p.is_valid()); assert!(p.is_finite() || p == Float::INFINITY || p.is_positive_zero()); assert!(p >= 0u32); if p.is_normal() { assert!(p.is_power_of_2()); assert_eq!(p.get_prec(), Some(1)); } if u < 1_000_000_000 { let p_alt = power_of_2_u64_naive(u); assert_eq!(ComparableFloatRef(&p_alt), ComparableFloatRef(&p)); } if let Ok(u) = u32::try_from(u) { let rug_p = rug::Float::with_val(1, 1) << u; assert_eq!( ComparableFloatRef(&Float::from(&rug_p)), ComparableFloatRef(&p) ); } } #[test] fn power_of_2_properties() { signed_gen_var_5().test_properties(|i| { power_of_2_properties_signed_helper(i); }); signed_gen().test_properties(|i| { power_of_2_properties_signed_helper(i); }); unsigned_gen_var_5().test_properties(|u| { power_of_2_properties_unsigned_helper(u); }); unsigned_gen().test_properties(|u| { power_of_2_properties_unsigned_helper(u); }); } ================================================ FILE: malachite-float/tests/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{NegAssign, Reciprocal, ReciprocalAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::emulate_float_to_float_fn; use malachite_float::test_util::arithmetic::reciprocal::{ reciprocal_prec_round_naive_1, reciprocal_prec_round_naive_2, rug_reciprocal, rug_reciprocal_prec, rug_reciprocal_prec_round, rug_reciprocal_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_6, float_gen_var_7, float_gen_var_8, float_gen_var_11, float_gen_var_12, float_rounding_mode_pair_gen_var_13, float_rounding_mode_pair_gen_var_14, float_rounding_mode_pair_gen_var_15, float_rounding_mode_pair_gen_var_16, float_rounding_mode_pair_gen_var_17, float_rounding_mode_pair_gen_var_23, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_3, float_unsigned_rounding_mode_triple_gen_var_12, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use std::panic::catch_unwind; #[test] fn test_reciprocal() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let reciprocal = x.clone().reciprocal(); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); assert_eq!(to_hex_string(&reciprocal), out_hex); let reciprocal_alt = (&x).reciprocal(); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); let mut reciprocal_alt = x.clone(); reciprocal_alt.reciprocal_assign(); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); let reciprocal_alt = reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); let reciprocal_alt = reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), Nearest).0; assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); let rug_reciprocal = rug_reciprocal(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "0.0", "0x0.0"); test("-Infinity", "-Infinity", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "Infinity", "Infinity"); test("-0.0", "-0x0.0", "-Infinity", "-Infinity"); test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("-1.0", "-0x1.0#1", "-1.0", "-0x1.0#1"); test( "1.0", "0x1.0000000000000000000000000#100", "1.0", "0x1.0000000000000000000000000#100", ); test( "-1.0", "-0x1.0000000000000000000000000#100", "-1.0", "-0x1.0000000000000000000000000#100", ); test("123.0", "0x7b.0#7", "0.0082", "0x0.0218#7"); test("-123.0", "-0x7b.0#7", "-0.0082", "-0x0.0218#7"); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0.7071067811865475", "0x0.b504f333f9de60#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-0.7071067811865475", "-0x0.b504f333f9de60#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0.31830988618379069", "0x0.517cc1b727220c#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-0.31830988618379069", "-0x0.517cc1b727220c#53", ); // - x.is_power_of_2() in reciprocal_prec_round // - !x.is_power_of_2() in reciprocal_prec_round // - in reciprocal_float_significand_same_prec_lt_w // - x != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_lt_w // - (q + 2) & (mask >> 1) > 2 in reciprocal_float_significand_same_prec_lt_w; // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_lt_w // - rm == Nearest in reciprocal_float_significand_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 && reciprocal & shift_bit != 0) in // reciprocal_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", "0.8", "0x0.c#2"); // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0) in // reciprocal_float_significand_same_prec_lt_w test("1.2", "0x1.4#3", "0.8", "0x0.c#3"); // - (q + 2) & (mask >> 1) <= 2 in reciprocal_float_significand_same_prec_lt_w // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_lt_w // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_lt_w test( "3615091.606162289805", "0x372973.9b2d73aac8#61", "2.7661816322867136e-7", "0x4.a410e30d72ea318E-6#61", ); // - in reciprocal_float_significand_same_prec_w // - x != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_w // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_w // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_w // - !round_bit in reciprocal_float_significand_same_prec_w // - round_bit || sticky_bit != 0 in reciprocal_float_significand_same_prec_w // - rm == Exact in reciprocal_float_significand_same_prec_w // - rm == Exact && (!round_bit || sticky_bit == 0 && reciprocal.even()) in // reciprocal_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "0.99999999999999999989", "0x0.fffffffffffffffe#64", ); // - round_bit in reciprocal_float_significand_same_prec_w // - rm == Exact && round_bit && (sticky_bit != 0 || reciprocal.even() in // reciprocal_float_significand_same_prec_w test( "0.113243462684988497952", "0x0.1cfd8608b7c32de2a#64", "8.830531814288645436", "0x8.d49dbba4a843592#64", ); // - in reciprocal_float_significand_same_prec_gt_w_lt_2w // - x_0 != 0 || x_1 != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_gt_w_lt_2w // - in reciprocal_float_2_approx // - x_1 != Limb::MAX in reciprocal_float_2_approx // - yy == 0 in reciprocal_float_2_approx // - r_0 != 0 || yy == 0 in reciprocal_float_2_approx // - carry in reciprocal_float_2_approx // - r_1 == 0 in reciprocal_float_2_approx // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in // reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_1 != 0 || s_0 != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 in // reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_1 < x_1 || s_1 == x_1 && s_0 < x_0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest in reciprocal_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "0.99999999999999999995", "0x0.ffffffffffffffff0#65", ); // - r_1 != 0 in reciprocal_float_2_approx // - s_1 >= x_1 && (s_1 != x_1 || s_0 >= x_0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "0.99999999999999999989", "0x0.fffffffffffffffe0#65", ); // - yy != 0 in reciprocal_float_2_approx test( "1.00000000000000000003", "0x1.00000000000000008#66", "0.99999999999999999997", "0x0.ffffffffffffffff8#66", ); // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000016", "0x1.0000000000000003#65", "0.99999999999999999984", "0x0.fffffffffffffffd0#65", ); // - rm != Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !carry in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "6.9434396726939059937558762e-29", "0x5.804bfffff864a7e6a3c7cE-24#85", ); // - s_2 <= 0 && s_1 <= x_1 && (s_1 != x_1 || s_0 < x_0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.1066650957130428898050817125418740852e-35", "0xe.b5c943322fb9cafab82fc881e3c1f4E-30#123", "90361574054676697026138186100092211.86", "0x11672b68e1cda153b96db5b555ad33.dc#123", ); // - x_1 == Limb::MAX in reciprocal_float_2_approx test( "4.9517601571415210995e27", "0xf.fffffffffffffff8E+22#65", "2.019483917365790222e-28", "0x1.0000000000000001E-23#65", ); // - !carry in reciprocal_float_2_approx test( "1.809457589959748038781206513903043742e-25", "0x3.800000000000000000000000000000E-21#121", "5526518032524019084371090.285714285714", "0x492492492492492492492.4924924924#121", ); // - s_1 == 0 && s_0 == 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w test( "4095.75", "0xfff.c00000000000000000000000000#120", "0.0002441555270707440639687480925349447598", "0x0.001000400100040010004001000400100#120", ); // - in reciprocal_float_significand_general // - extra_bit in reciprocal_float_significand_general // - qs_len < MPFR_DIV_THRESHOLD || ds_len < MPFR_DIV_THRESHOLD in // reciprocal_float_significand_general // - rm != Nearest || shift != 0 in reciprocal_float_significand_general // - ds_len >= qs_2_len in reciprocal_float_significand_general // - qs_2_len == qs_len in reciprocal_float_significand_general // - sticky_bit != 0 || sticky_3 != 0 in reciprocal_float_significand_general // - ds_len <= qs_2_len in reciprocal_float_significand_general // - ds_len <= qs_2_len && rm == Nearest in reciprocal_float_significand_general // - cleanup == None in reciprocal_float_significand_general // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) in // reciprocal_float_significand_general // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit == 0 // in reciprocal_float_significand_general test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "0.999999999999999999999999999999999999997", "0x0.ffffffffffffffffffffffffffffffff0#129", ); // - !extra_bit in reciprocal_float_significand_general test( "3.8524937267946719191140399538619613749184e-10", "0x1.a7960ee660129a7bc6beccda5d8bb012f0E-8#135", "2595721293.573692163399156109109436743137", "0x9ab7904d.92dd7d57c55752828aeb2a056a#135", ); // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit != 0 // && sticky_bit == 0 in reciprocal_float_significand_general test( "59494692712728004820788608585666.4829798", "0x2eeedb85c9cdc503a8e25ed4fc2.7ba490#129", "1.680822195062896543011322450000404260061e-32", "0x5.745f58c91536fd9586859912d6b99220E-27#129", ); // - rm == Nearest && shift == 0 in reciprocal_float_significand_general // - ds_len < qs_2_len in reciprocal_float_significand_general // - qs_2_len != qs_len in reciprocal_float_significand_general test( "2.652265028059746721807174554033221706564e-11", "0x1.d29765de1f777af51db92558a3d9f542E-9#128", "37703622730.7776167463689706185944181549", "0x8c74fa04a.c711e41e7a061938aeb7ca7#128", ); // - qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD in // reciprocal_float_significand_general // - ds_len < n in reciprocal_float_significand_general // - !q_high first time in reciprocal_float_significand_general test( "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ 9912721166210129145585", "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ 02af09995fd6ced97b00#1859", "1.002246345847779005201453959044909523251487705121768272318254782834562788571992915761065\ 827618366102604676901058851697875789517863827988808181377939460972322574747531876040609995\ 972589309563651666694269954573404860608746408716939006674422401722850836821062009150256011\ 720454011696660779666788543360159960577274185817743487975811370456064842946971427355525804\ 257690941749159301402957505054859414089331855848531064209977516186532202351442372831975270\ 870077932986581025601789533966442159881772178301189187013534424007199259091978932352502557\ 2202453587766889671779e-123", "0xa.99c4846d5eeedd01292b3ecbfdcde3e23e86f2c0de91a7853e3f16d01225356463802a0309555fe6a982a\ b689ccb12d932eab55b6ffd61c4fdd7cd737afd36bd5acda69948c10851f5fd1a254537be41d4c013aa43aaa09\ 93fccd821acb36881a3a14540999fa35a76a34b052ec4c6e62c85b8890330ad74145c3af385378890639293f97\ 87eeb51c942fb1b0480f7e5dcadd2da6f8bbf05ac6e562e773bff36faf231658530929fef9e7c5b84843c5674a\ 883eede0deef889addd0d20f57f1eaeb61dfb8dd23ed0ba6dfc00929192924d8b397f3d5d4913b580d5176e47b\ 5900b7857bdc095ca14E-103#1859", ); // - r_0 == 0 && yy != 0 in reciprocal_float_2_approx test( "206158430208.00000000558794", "0x3000000000.000000180000#83", "4.850638409455617268748732e-12", "0x5.5555555555555552aaabE-10#83", ); } #[test] fn test_reciprocal_prec() { let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal, o) = x.clone().reciprocal_prec(prec); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); assert_eq!(to_hex_string(&reciprocal), out_hex); assert_eq!(o, o_out); let (reciprocal_alt, o_alt) = x.reciprocal_prec_ref(prec); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_alt = x.clone(); let o_alt = reciprocal_alt.reciprocal_prec_assign(prec); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let (rug_reciprocal, rug_o) = rug_reciprocal_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal); test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 10, "-1.0", "-0x1.000#10", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, "-1.0", "-0x1.0#1", Equal, ); test("123.0", "0x7b.0#7", 1, "0.008", "0x0.02#1", Less); test("123.0", "0x7b.0#7", 10, "0.00813", "0x0.0215#10", Greater); test("-123.0", "-0x7b.0#7", 1, "-0.008", "-0x0.02#1", Greater); test("-123.0", "-0x7b.0#7", 10, "-0.00813", "-0x0.0215#10", Less); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, "0.5", "0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, "0.707", "0x0.b50#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, "-0.5", "-0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, "-0.707", "-0x0.b50#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "0.2", "0x0.4#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.3184", "0x0.518#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-0.2", "-0x0.4#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.3184", "-0x0.518#10", Less, ); // - in reciprocal_float_significand_short // - in limbs_reciprocal_limb_to_out_mod_with_fraction // - fraction_len != 0 in limbs_reciprocal_limb_to_out_mod_with_fraction // - out_last == 0 in reciprocal_float_significand_short // - out_last == 0 && shift != 0 in reciprocal_float_significand_short // - round_bit == 0 && sticky_bit != 0 in reciprocal_float_significand_short // - rm == Nearest in reciprocal_float_significand_short // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && out[0] & shift_bit == 0) in // reciprocal_float_significand_short test("1.5", "0x1.8#2", 1, "0.5", "0x0.8#1", Less); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || out[0] & shift_bit != 0) in // reciprocal_float_significand_short test("1.5", "0x1.8#2", 4, "0.7", "0x0.b#4", Greater); // - ds_len > qs_2_len in reciprocal_float_significand_general // - inex != Equal in reciprocal_float_significand_general // - ds_len > qs_2_len && rm == Nearest in reciprocal_float_significand_general // - sticky_3 > 1 in reciprocal_float_significand_general test( "0.000199046277632504184666664672269768242929310652018203552191617720205649", "0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225", 26, "5023.9573", "0x139f.f510#26", Less, ); // - out_last == 0 && shift == 0 in reciprocal_float_significand_short // - out_last == 0 && shift == 0 && c >= y - c test( "1.4904942e-19", "0x2.bfddbE-16#22", 64, "6709184284559176977.0", "0x5d1bcf8f5dc87511.0#64", Greater, ); // - sticky_3 <= 1 in reciprocal_float_significand_general // - !q_high second time in reciprocal_float_significand_general // - !q_high_2 in reciprocal_float_significand_general // - cmp_s_r != Equal in reciprocal_float_significand_general // - cmp_s_r <= Equal first time in reciprocal_float_significand_general test( "13104.5238818416080254535", "0x3330.861d1ed0acba8a3a#77", 61, "0.00007630952555137529844", "0x0.00050042eaa75fe3e40#61", Less, ); // - cmp_s_r > Equal first time in reciprocal_float_significand_general // - cmp_s_r > Equal && !q_high_2 in reciprocal_float_significand_general // - cmp_s_r <= Equal second time in reciprocal_float_significand_general // - sticky_3 != 1 && round_bit != 0 in reciprocal_float_significand_general test( "4047252243163522937320069504914937843.384444039", "0x30b78f117589e437888c5573227d7f3.626aecb#150", 126, "2.47081214591743090926825573642415225879e-37", "0x5.413cf35bf8a6be7eed9713c3529cac4E-31#126", Less, ); // - out_last == 0 && shift == 0 && c < y - c in reciprocal_float_significand_short test( "0.252", "0x0.408#8", 64, "3.9689922480620155039", "0x3.f80fe03f80fe03f8#64", Less, ); // - sticky_3 != 1 && round_bit == 0 in reciprocal_float_significand_general // - cmp_s_r != Equal || shift != 0 in reciprocal_float_significand_general // - rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) in // reciprocal_float_significand_general // - cleanup == TruncateCheckQHigh in reciprocal_float_significand_general // - !q_high third time in reciprocal_float_significand_general test( "13486082141.77132281557478202754", "0x323d5485d.c575697b8d65625d0#99", 60, "7.41505197349076425e-11", "0x5.187840c7b7df518E-9#60", Greater, ); // - sticky_3 == 1 in reciprocal_float_significand_general test( "1.22280082196367917099634553e-19", "0x2.41738c7082eda42f40f3f0E-16#87", 62, "8177946743559704448.0", "0x717de73c11f04f80.0#62", Less, ); // - cmp_s_r > Equal second time in reciprocal_float_significand_general // - cmp_s_r > Equal && rm == Nearest in reciprocal_float_significand_general // - cmp_s_r > Equal && rm == Nearest && shift == 1 in reciprocal_float_significand_general // - cmp_s_r > Equal && rm == Nearest && shift == 1 && round_bit == 0 in // reciprocal_float_significand_general // - cleanup == Sub2Ulp in reciprocal_float_significand_general test( "18686733767405.50192797818236099916512095073138146049740456616", "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", 63, "5.351389988464750895e-14", "0xf.1015372ed29c6daE-12#63", Less, ); // - cmp_s_r > Equal && rm == Nearest && shift == 1 && round_bit != 0 in // reciprocal_float_significand_general test( "5.1485428388978050057923204436e-7", "0x8.a348459137c894fe7ce2ce4E-6#94", 63, "1942297.1339480570737", "0x1da319.224a6b7c7e8#63", Greater, ); // - q_high second time in reciprocal_float_significand_general // - q_high third time in reciprocal_float_significand_general test( "77371252455336267181195267.98438", "0x4000000000000000000003.fc00#101", 21, "1.29247e-26", "0x4.00000E-22#21", Greater, ); // - cmp_s_r > Equal && rm == Nearest && shift != 1 in reciprocal_float_significand_general test( "2658455991647202407967140029027844095.999984793", "0x2000000003fffdfffffffffff7fffff.ffff00e#150", 126, "3.76158192252184441821673862447332945247e-37", "0x7.ffffffff000080001fffe0020400060E-31#126", Greater, ); // - cmp_s_r == Equal in reciprocal_float_significand_general // - !slice_test_zero(sp_lo) in reciprocal_float_significand_general test( "1.00000000000000000000000000000000000000000000035028", "0x1.00000000000000000000000000000000000001fff#165", 9, "1.0", "0x1.00#9", Greater, ); // - ds_len >= n in reciprocal_float_significand_general test( "0.055494458197186880675630915676192867532090892470422627386324587939238035948781984969197\ 293549419550977162311955781124943110956302191334821801709357381779895051695270613703928454\ 324596584327643817343816609304133584205767499993731432854297161698269943482406592768874444\ 537959922587924718339566077249075342435855861361805700477320039260219431275491192763683820\ 335274971653357747385666948482136785955293678142161982025522843889154198503897563042426395\ 128128925013857602497675148024154470366154782845358820106881972937537492453282371069714224\ 342987087633028783648188309716648625167308459669051113846104707695985727291553732092985376\ 828259777127224883258056131830095048084139109366273880047266946456087245977725112865710579\ 525111935320391211042996099454878241904334424644681645423208503968089041208566140555448097\ 852910157786980160921009881876094041863058139126904649967001982231878732430835123816538920\ 677999964668461960985136485079991108378659476109039768366016053541284627738754596865400997\ 112674267336505852768050602674774522669073467755292625683686148376948941511306559626232154\ 752250188007464931234370449669484827725942224651581822979291904312419637250173763557353262\ 213949126273235198961215664565140295983002285722717251104994492638175694612259962414559660\ 670986455111669460799863783422503680534332809871688740315758114042751185650495859242221856\ 676315059490112305738127164937772981750053994564437960009449100953381044642977719710987666\ 446442147625231494914221140350124646594870978197268779196749153799654193158076220975432784\ 285250458268961487489605062990550609833462756239703423977438296502233632161406744847227123\ 129345837972247611423244017961911382138681216321381679915794615975763676728759826413970576\ 860022980739678182223426387634227578298610034617798500806276338343012622846552838812662393\ 624312342667652111927682534015047744310614980669350777266223429538479188836406048087315918\ 309894499222120214872928367335411152843249721184424372084873571670196566303743654124450236\ 183156500319414376380635601282651645722305689309629762280330704861001884908133936528480642\ 756123234", "0x0.0e34e28310efa672de91bbf3447b991e67d8318cdf0c4058e4c9c730c71dc5b4bf675e849e3ac19fa3e70\ d9cbfb926620de7c9c66fc396364a70516bd66e253f5b318c8f82fabc4da09cab178fa55b2cd32603f085d4149\ a70fb07eb0959a5a78a00603aae495e7a094d9ee04b63747d7a023fb4369e5bf83efc20d6dfe31bafee72256df\ 1e39a8949cb554b519bb7b532f0ffb97b7fe5238cb68f0cfca74556fd7588422c7b383f4183a4193de48c69bae\ 7faf54820ec3c71871cbb288daf37266ee4f1fd3e40e483ed25f601b87f9c4a92b8cec5ec0e8d7edbd4234fba3\ 1a0a463a29b8f32d02f0d1f55195b2ec33db71548c7ccaf7e3a658ee71d308649653be586268e028c9f15d7788\ cbbd9d825fadf58d6f13183242c54015f254a271b4c89cfc1d82fc8c6182b0d0c620d53cf81728d495822994c6\ 63bb058d661f74be0ae8c8c10381afa72bc89a2a01da15a5f6d117b31e04e34a6e11e0aa8ad521b7a6117ce813\ b8e9326335c30e14052e4aa58c9062245ce2b058e7ca1221aa19af3c21653dac76aa59bb843a7a0ad8c6e22992\ 639766e47bfcc7de81f7a5a43e5faba0bd029002632b5d26d5a4303d9bbf4cf2664d57e50df98491d49ceb0f2f\ a1db2579ec23c459066023beebebd800fc879d76d59a3d6d2949650b07ef7b31e752ca051f4f107c7ff4af3f56\ 43eb287784ebcbcbefaa6a9496458e1b5afa0a74a27a47545d2f9091189f54f315a8bc904dedd3248f8cfbf32b\ 19df9037d47bd021b075b70aaa2087c30b755c65f93508e4564f2d998430e8f68565d451de80e317a96c18493e\ 662aa4f6ed98647d9051d9c993accc85820fe55a06d956025618ac1fbd020af906edd248ee088ee34f3ec8fc99\ 1e9392efafd1acd495d65fe834644d939ef5fa91d984969c79257afb98f8d94a3551a1a4b533c182b0d198d8a9\ 53e030b1532cd0e54117934099dd0b0027cd6058fb4190686ba78ded239aca8ac146e13f4c88052537903cb587\ 95eae03289ef10a0dee81bb143567c686a600364a57829437fc75160f8660a0ac48daacd98471fb2c0c490cd90\ 2cea0ea9aa3a814462dd78ab7d573f356b8c0ee7ac1f0c13819e3aeb5b2c8ea9f3a386bf90e5898fb38867db59\ a9e8ae436df1ececb24a9e478c52dd17ad020f761aca8761acb63eb70ac73687a85f5fc45a10ab7873104f3489\ 9df7961eaa91080cf7a#6892", 2006, "18.01981733827778674260325184800154550178488687484021553354418910902303106544992907597073\ 029189149288233180017138039419588169269797921955767649134253967949783482048904124978427680\ 356665076989426379081885511868423028921432842040598017121872298172949413285212017353511719\ 635837927429422415155120291649700552853758008370658383590920718577880818445566446372050296\ 508733341553853089827665379953621398768316388977766832203115700511569639084749508682625973\ 200934933860726967306493882349632958444320046459537281159643562613023877018494385007867594\ 9194217635032456311998703209522721567033904823795308705191538464412", "0x12.0512bfc3cbff370e13079bf70f24c8fc14fb1154aa0638c41252b425cfb276f04379cf0908b1732ae3ca\ 5d5ce2ef398eca257c87dfb650e9648bf8397dd443e42a5fd3663c3d58b9b6cd2a1ebf3c9246c45a1f6086158e\ a1e93d0f78945b71e8bdf265700c826de9776e648ce900159a0f4f2716ec326e2b8289920112637767e8fee268\ 3363b8e4c4bf07c685c226e6b97d260fdc2910d7e8a10fada9bda175aeb73def046bae399c664bfe3cfb3f7e73\ 136427cf5ca96cad226976adc2a9a0117dd38cbd0aaf5edbdb6a9e925126c38670a8946bc5ee1840200876c486\ de477d9c4b50e410143b115c27f9ba57c1176894c9d33effdbbd50928#2006", Less, ); // - q_high first time in reciprocal_float_significand_general // - !round_helper_2 in reciprocal_float_significand_general test( "3.725290298461914062500000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000011016237598729697344643067035553076048795855845749823769296583726265856513\ 808851994012395922156678620494270052333942368952051919368238891272218333e-9", "0x1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeE-7#3520", 1969, "268435456.0", "0x10000000.000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000000000000000000000000#1969", Greater, ); } #[test] fn reciprocal_prec_fail() { assert_panic!(Float::NAN.reciprocal_prec(0)); assert_panic!(Float::NAN.reciprocal_prec_ref(0)); assert_panic!({ let mut x = Float::NAN; x.reciprocal_prec_assign(0) }); } #[test] fn test_reciprocal_round() { let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal, o) = x.clone().reciprocal_round(rm); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); assert_eq!(to_hex_string(&reciprocal), out_hex); assert_eq!(o, o_out); let (reciprocal_alt, o_alt) = x.reciprocal_round_ref(rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_alt = x.clone(); let o_alt = reciprocal_alt.reciprocal_round_assign(rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal, rug_o) = rug_reciprocal_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", Floor, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", Ceiling, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", Down, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", Up, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", Nearest, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal); test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Floor, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Ceiling, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Down, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Up, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Nearest, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Exact, "-1.0", "-0x1.0#1", Equal); test( "1.0", "0x1.0000000000000000000000000#100", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Floor, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Ceiling, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Down, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Up, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Nearest, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Exact, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test("123.0", "0x7b.0#7", Floor, "0.0081", "0x0.0210#7", Less); test( "123.0", "0x7b.0#7", Ceiling, "0.0082", "0x0.0218#7", Greater, ); test("123.0", "0x7b.0#7", Down, "0.0081", "0x0.0210#7", Less); test("123.0", "0x7b.0#7", Up, "0.0082", "0x0.0218#7", Greater); test( "123.0", "0x7b.0#7", Nearest, "0.0082", "0x0.0218#7", Greater, ); test("-123.0", "-0x7b.0#7", Floor, "-0.0082", "-0x0.0218#7", Less); test( "-123.0", "-0x7b.0#7", Ceiling, "-0.0081", "-0x0.0210#7", Greater, ); test( "-123.0", "-0x7b.0#7", Down, "-0.0081", "-0x0.0210#7", Greater, ); test("-123.0", "-0x7b.0#7", Up, "-0.0082", "-0x0.0218#7", Less); test( "-123.0", "-0x7b.0#7", Nearest, "-0.0082", "-0x0.0218#7", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Floor, "0.7071067811865475", "0x0.b504f333f9de60#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Ceiling, "0.7071067811865476", "0x0.b504f333f9de68#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Down, "0.7071067811865475", "0x0.b504f333f9de60#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Up, "0.7071067811865476", "0x0.b504f333f9de68#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Nearest, "0.7071067811865475", "0x0.b504f333f9de60#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Floor, "-0.7071067811865476", "-0x0.b504f333f9de68#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Ceiling, "-0.7071067811865475", "-0x0.b504f333f9de60#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Down, "-0.7071067811865475", "-0x0.b504f333f9de60#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Up, "-0.7071067811865476", "-0x0.b504f333f9de68#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Nearest, "-0.7071067811865475", "-0x0.b504f333f9de60#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "0.31830988618379064", "0x0.517cc1b7272208#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "0.31830988618379069", "0x0.517cc1b727220c#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "0.31830988618379064", "0x0.517cc1b7272208#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "0.31830988618379069", "0x0.517cc1b727220c#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "0.31830988618379069", "0x0.517cc1b727220c#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "-0.31830988618379069", "-0x0.517cc1b727220c#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "-0.31830988618379064", "-0x0.517cc1b7272208#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "-0.31830988618379064", "-0x0.517cc1b7272208#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "-0.31830988618379069", "-0x0.517cc1b727220c#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "-0.31830988618379069", "-0x0.517cc1b727220c#53", Less, ); // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Down, "0.5", "0x0.8#2", Less); // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Up, "0.8", "0x0.c#2", Greater); // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Down, "0.99999999999999999989", "0x0.fffffffffffffffe#64", Less, ); // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Up, "0.99999999999999999995", "0x0.ffffffffffffffff#64", Greater, ); // - rm == Floor || rm == Down in reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Down, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - rm == Ceiling || rm == Up in reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Up, "0.99999999999999999997", "0x0.ffffffffffffffff8#65", Greater, ); // - ds_len <= qs_2_len && rm == Ceiling || rm == Up && inex != Equal in // reciprocal_float_significand_general // - cleanup == None && (rm == Ceiling || rm == Up) && (round_bit != 0 || sticky_bit != 0) in // reciprocal_float_significand_general test( "2.4914040842493675536005152793625253098043524808533216867315977e-8", "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", Up, "40138009.17811728321982547739205337771132288200540084196230409", "0x2647519.2d9918224811b1eb5289a86e1aa22ec284493440dbd2#202", Greater, ); // - ds_len <= qs_2_len && rm == Floor || rm == Down || (rm != Nearest && inex == Equal) in // reciprocal_float_significand_general // - cleanup == None && (rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0) in // reciprocal_float_significand_general test( "2.4914040842493675536005152793625253098043524808533216867315977e-8", "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", Down, "40138009.17811728321982547739205337771132288200540084196230408", "0x2647519.2d9918224811b1eb5289a86e1aa22ec284493440dbd1#202", Less, ); // - x.is_power_of_2() in reciprocal_prec_round // - !x.is_power_of_2() in reciprocal_prec_round // - in reciprocal_float_significand_same_prec_lt_w // - x != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_lt_w // - (q + 2) & (mask >> 1) > 2 in reciprocal_float_significand_same_prec_lt_w; // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_lt_w // - rm == Nearest in reciprocal_float_significand_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 && reciprocal & shift_bit != 0) in // reciprocal_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Nearest, "0.8", "0x0.c#2", Greater); // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0) in // reciprocal_float_significand_same_prec_lt_w test("1.2", "0x1.4#3", Nearest, "0.8", "0x0.c#3", Less); // - (q + 2) & (mask >> 1) <= 2 in reciprocal_float_significand_same_prec_lt_w // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_lt_w // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_lt_w test( "3615091.606162289805", "0x372973.9b2d73aac8#61", Nearest, "2.7661816322867136e-7", "0x4.a410e30d72ea318E-6#61", Less, ); // - in reciprocal_float_significand_same_prec_w // - x != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_w // - hi == 0 && lo < x first time in reciprocal_float_significand_same_prec_w // - hi == 0 && lo < x second time in reciprocal_float_significand_same_prec_w // - !round_bit in reciprocal_float_significand_same_prec_w // - round_bit || sticky_bit != 0 in reciprocal_float_significand_same_prec_w // - rm == Exact in reciprocal_float_significand_same_prec_w // - rm == Exact && (!round_bit || sticky_bit == 0 && reciprocal.even()) in // reciprocal_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "0.99999999999999999989", "0x0.fffffffffffffffe#64", Less, ); // - round_bit in reciprocal_float_significand_same_prec_w // - rm == Exact && round_bit && (sticky_bit != 0 || reciprocal.even() in // reciprocal_float_significand_same_prec_w test( "0.113243462684988497952", "0x0.1cfd8608b7c32de2a#64", Nearest, "8.830531814288645436", "0x8.d49dbba4a843592#64", Greater, ); // - in reciprocal_float_significand_same_prec_gt_w_lt_2w // - x_0 != 0 || x_1 != LIMB_HIGH_BIT in reciprocal_float_significand_same_prec_gt_w_lt_2w // - in reciprocal_float_2_approx // - x_1 != Limb::MAX in reciprocal_float_2_approx // - yy == 0 in reciprocal_float_2_approx // - r_0 != 0 || yy == 0 in reciprocal_float_2_approx // - carry in reciprocal_float_2_approx // - r_1 == 0 in reciprocal_float_2_approx // - (q_0.wrapping_add(21)) & (mask >> 1) <= 21 in // reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_1 != 0 || s_0 != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 in // reciprocal_float_significand_same_prec_gt_w_lt_2w // - s_1 < x_1 || s_1 == x_1 && s_0 < x_0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - round_bit != 0 || sticky_bit != 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest in reciprocal_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "0.99999999999999999995", "0x0.ffffffffffffffff0#65", Less, ); // - r_1 != 0 in reciprocal_float_2_approx // - s_1 >= x_1 && (s_1 != x_1 || s_0 >= x_0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "0.99999999999999999989", "0x0.fffffffffffffffe0#65", Less, ); // - yy != 0 in reciprocal_float_2_approx test( "1.00000000000000000003", "0x1.00000000000000008#66", Nearest, "0.99999999999999999997", "0x0.ffffffffffffffff8#66", Less, ); // - (q_0.wrapping_add(21)) & (mask >> 1) > 21 in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000016", "0x1.0000000000000003#65", Nearest, "0.99999999999999999984", "0x0.fffffffffffffffd0#65", Less, ); // - rm != Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !carry in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Nearest, "6.9434396726939059937558762e-29", "0x5.804bfffff864a7e6a3c7cE-24#85", Greater, ); // - s_2 <= 0 && s_1 <= x_1 && (s_1 != x_1 || s_0 < x_0) in // reciprocal_float_significand_same_prec_gt_w_lt_2w test( "1.1066650957130428898050817125418740852e-35", "0xe.b5c943322fb9cafab82fc881e3c1f4E-30#123", Nearest, "90361574054676697026138186100092211.86", "0x11672b68e1cda153b96db5b555ad33.dc#123", Greater, ); // - x_1 == Limb::MAX in reciprocal_float_2_approx test( "4.9517601571415210995e27", "0xf.fffffffffffffff8E+22#65", Nearest, "2.019483917365790222e-28", "0x1.0000000000000001E-23#65", Greater, ); // - !carry in reciprocal_float_2_approx test( "1.809457589959748038781206513903043742e-25", "0x3.800000000000000000000000000000E-21#121", Nearest, "5526518032524019084371090.285714285714", "0x492492492492492492492.4924924924#121", Less, ); // - s_1 == 0 && s_0 == 0 in reciprocal_float_significand_same_prec_gt_w_lt_2w test( "4095.75", "0xfff.c00000000000000000000000000#120", Nearest, "0.0002441555270707440639687480925349447598", "0x0.001000400100040010004001000400100#120", Less, ); // - in reciprocal_float_significand_general // - extra_bit in reciprocal_float_significand_general // - qs_len < MPFR_DIV_THRESHOLD || ds_len < MPFR_DIV_THRESHOLD in // reciprocal_float_significand_general // - rm != Nearest || shift != 0 in reciprocal_float_significand_general // - ds_len >= qs_2_len in reciprocal_float_significand_general // - qs_2_len == qs_len in reciprocal_float_significand_general // - sticky_bit != 0 || sticky_3 != 0 in reciprocal_float_significand_general // - ds_len <= qs_2_len in reciprocal_float_significand_general // - ds_len <= qs_2_len && rm == Nearest in reciprocal_float_significand_general // - cleanup == None in reciprocal_float_significand_general // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) in // reciprocal_float_significand_general // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit == 0 // in reciprocal_float_significand_general test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "0.999999999999999999999999999999999999997", "0x0.ffffffffffffffffffffffffffffffff0#129", Less, ); // - !extra_bit in reciprocal_float_significand_general test( "3.8524937267946719191140399538619613749184e-10", "0x1.a7960ee660129a7bc6beccda5d8bb012f0E-8#135", Nearest, "2595721293.573692163399156109109436743137", "0x9ab7904d.92dd7d57c55752828aeb2a056a#135", Less, ); // - cleanup == None && rm == Nearest && (round_bit != 0 || sticky_bit != 0) && round_bit != 0 // && sticky_bit == 0 in reciprocal_float_significand_general test( "59494692712728004820788608585666.4829798", "0x2eeedb85c9cdc503a8e25ed4fc2.7ba490#129", Nearest, "1.680822195062896543011322450000404260061e-32", "0x5.745f58c91536fd9586859912d6b99220E-27#129", Greater, ); // - rm == Nearest && shift == 0 in reciprocal_float_significand_general // - ds_len < qs_2_len in reciprocal_float_significand_general // - qs_2_len != qs_len in reciprocal_float_significand_general test( "2.652265028059746721807174554033221706564e-11", "0x1.d29765de1f777af51db92558a3d9f542E-9#128", Nearest, "37703622730.7776167463689706185944181549", "0x8c74fa04a.c711e41e7a061938aeb7ca7#128", Greater, ); // - qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD in // reciprocal_float_significand_general // - ds_len < n in reciprocal_float_significand_general // - !q_high first time in reciprocal_float_significand_general test( "99775868891207693182758620905617766484977359141657322302733467080906379945858675686059451\ 2527853476231275058799551652072546.7114971760702609364731573674336745185834760605451122614\ 680178551142556046183482705875960001033145321970465204907865385015751310573750415565593472\ 515573584122133946534420508845514863685042630834456885627933663697385547769664847990486584\ 336882273751721721644989648370590667737234950547668737865047573751482757356022197920174371\ 088074314780588737501583713833755004374512024407585163195094394292034507503368814534990168\ 9912721166210129145585", "0x1826427338bc8ee8c907c3ce5e6a2a793f6ba67df6e738f22dc8aee7eb1838ddc4290e49186e61bdbedb847\ d19c5d8c4bf88c62.b624adce6b0a3564827e04608c1aec0c8b10390491e15df75402c1788241935e791ebd5f4\ 25d73042c03e3bad5f0d11257d8bcdab6c8bae677785865be19fa4f42690ddb02174b09bb2c1c9ce6cf3dc2d80\ 9f0b0b79c42ae70f14ec682ac3850e91ee3b6ef02555e18758417024bf2e8801a759e710b3ac91f28b15277ff4\ f6380b7ba380aa56c032ce8db2107bfd99a9c789098467f2b27a7b3e1bb6a9e7804ef8a26a3baea51e9a8da4d5\ 02af09995fd6ced97b00#1859", Nearest, "1.002246345847779005201453959044909523251487705121768272318254782834562788571992915761065\ 827618366102604676901058851697875789517863827988808181377939460972322574747531876040609995\ 972589309563651666694269954573404860608746408716939006674422401722850836821062009150256011\ 720454011696660779666788543360159960577274185817743487975811370456064842946971427355525804\ 257690941749159301402957505054859414089331855848531064209977516186532202351442372831975270\ 870077932986581025601789533966442159881772178301189187013534424007199259091978932352502557\ 2202453587766889671779e-123", "0xa.99c4846d5eeedd01292b3ecbfdcde3e23e86f2c0de91a7853e3f16d01225356463802a0309555fe6a982a\ b689ccb12d932eab55b6ffd61c4fdd7cd737afd36bd5acda69948c10851f5fd1a254537be41d4c013aa43aaa09\ 93fccd821acb36881a3a14540999fa35a76a34b052ec4c6e62c85b8890330ad74145c3af385378890639293f97\ 87eeb51c942fb1b0480f7e5dcadd2da6f8bbf05ac6e562e773bff36faf231658530929fef9e7c5b84843c5674a\ 883eede0deef889addd0d20f57f1eaeb61dfb8dd23ed0ba6dfc00929192924d8b397f3d5d4913b580d5176e47b\ 5900b7857bdc095ca14E-103#1859", Greater, ); // - r_0 == 0 && yy != 0 in reciprocal_float_2_approx test( "206158430208.00000000558794", "0x3000000000.000000180000#83", Nearest, "4.850638409455617268748732e-12", "0x5.5555555555555552aaabE-10#83", Greater, ); } #[test] fn reciprocal_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.reciprocal_round(Exact)); assert_panic!(THREE.reciprocal_round_ref(Exact)); assert_panic!({ let mut x = THREE; x.reciprocal_round_assign(Exact); }); } #[test] fn test_reciprocal_prec_round() { let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal, o) = x.clone().reciprocal_prec_round(prec, rm); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); assert_eq!(to_hex_string(&reciprocal), out_hex); assert_eq!(o, o_out); let (reciprocal_alt, o_alt) = x.reciprocal_prec_round_ref(prec, rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_alt = x.clone(); let o_alt = reciprocal_alt.reciprocal_prec_round_assign(prec, rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal), ComparableFloatRef(&reciprocal_alt) ); assert_eq!(o_alt, o_out); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal, rug_o) = rug_reciprocal_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", 1, Floor, "-0.0", "-0x0.0", Equal); test( "-Infinity", "-Infinity", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test("-Infinity", "-Infinity", 1, Down, "-0.0", "-0x0.0", Equal); test("-Infinity", "-Infinity", 1, Up, "-0.0", "-0x0.0", Equal); test( "-Infinity", "-Infinity", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test("-Infinity", "-Infinity", 1, Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal); test( "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal); test("-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal); test( "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal); test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Floor, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Down, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Up, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Nearest, "-1.0", "-0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Exact, "-1.0", "-0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Floor, "-1.0", "-0x1.000#10", Equal); test( "-1.0", "-0x1.0#1", 10, Ceiling, "-1.0", "-0x1.000#10", Equal, ); test("-1.0", "-0x1.0#1", 10, Down, "-1.0", "-0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Up, "-1.0", "-0x1.000#10", Equal); test( "-1.0", "-0x1.0#1", 10, Nearest, "-1.0", "-0x1.000#10", Equal, ); test("-1.0", "-0x1.0#1", 10, Exact, "-1.0", "-0x1.000#10", Equal); test("123.0", "0x7b.0#7", 1, Floor, "0.008", "0x0.02#1", Less); test("123.0", "0x7b.0#7", 1, Ceiling, "0.02", "0x0.04#1", Greater); test("123.0", "0x7b.0#7", 1, Down, "0.008", "0x0.02#1", Less); test("123.0", "0x7b.0#7", 1, Up, "0.02", "0x0.04#1", Greater); test("123.0", "0x7b.0#7", 1, Nearest, "0.008", "0x0.02#1", Less); test("-123.0", "-0x7b.0#7", 1, Floor, "-0.02", "-0x0.04#1", Less); test( "-123.0", "-0x7b.0#7", 1, Ceiling, "-0.008", "-0x0.02#1", Greater, ); test( "-123.0", "-0x7b.0#7", 1, Down, "-0.008", "-0x0.02#1", Greater, ); test("-123.0", "-0x7b.0#7", 1, Up, "-0.02", "-0x0.04#1", Less); test( "-123.0", "-0x7b.0#7", 1, Nearest, "-0.008", "-0x0.02#1", Greater, ); test( "123.0", "0x7b.0#7", 10, Floor, "0.00812", "0x0.0214#10", Less, ); test( "123.0", "0x7b.0#7", 10, Ceiling, "0.00813", "0x0.0215#10", Greater, ); test( "123.0", "0x7b.0#7", 10, Down, "0.00812", "0x0.0214#10", Less, ); test( "123.0", "0x7b.0#7", 10, Up, "0.00813", "0x0.0215#10", Greater, ); test( "123.0", "0x7b.0#7", 10, Nearest, "0.00813", "0x0.0215#10", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Floor, "-0.00813", "-0x0.0215#10", Less, ); test( "-123.0", "-0x7b.0#7", 10, Ceiling, "-0.00812", "-0x0.0214#10", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Down, "-0.00812", "-0x0.0214#10", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Up, "-0.00813", "-0x0.0215#10", Less, ); test( "-123.0", "-0x7b.0#7", 10, Nearest, "-0.00813", "-0x0.0215#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Floor, "0.5", "0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Ceiling, "1.0", "0x1.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Down, "0.5", "0x0.8#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Up, "1.0", "0x1.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Nearest, "0.5", "0x0.8#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Floor, "-1.0", "-0x1.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Ceiling, "-0.5", "-0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Down, "-0.5", "-0x0.8#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Up, "-1.0", "-0x1.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Nearest, "-0.5", "-0x0.8#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Floor, "0.707", "0x0.b50#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Ceiling, "0.708", "0x0.b54#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Down, "0.707", "0x0.b50#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Up, "0.708", "0x0.b54#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Nearest, "0.707", "0x0.b50#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Floor, "-0.708", "-0x0.b54#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Ceiling, "-0.707", "-0x0.b50#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Down, "-0.707", "-0x0.b50#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Up, "-0.708", "-0x0.b54#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Nearest, "-0.707", "-0x0.b50#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "0.2", "0x0.4#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "0.2", "0x0.4#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "0.5", "0x0.8#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "0.2", "0x0.4#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "-0.5", "-0x0.8#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "-0.2", "-0x0.4#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "-0.2", "-0x0.4#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "-0.5", "-0x0.8#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "-0.2", "-0x0.4#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "0.3179", "0x0.516#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "0.3184", "0x0.518#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "0.3179", "0x0.516#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "0.3184", "0x0.518#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "0.3184", "0x0.518#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-0.3184", "-0x0.518#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-0.3179", "-0x0.516#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-0.3179", "-0x0.516#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-0.3184", "-0x0.518#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-0.3184", "-0x0.518#10", Less, ); // - rm == Floor || rm == Down in reciprocal_float_significand_short test("1.5", "0x1.8#2", 1, Down, "0.5", "0x0.8#1", Less); // - rm == Ceiling || rm == Up in reciprocal_float_significand_short test("1.5", "0x1.8#2", 1, Up, "1.0", "0x1.0#1", Greater); // - ds_len > qs_2_len && rm != Nearest in reciprocal_float_significand_general test( "2.4914040842493675536005152793625253098043524808533216867315977e-8", "0x6.b014710df6d8d0fb1901206ed24e1e002b4411ac77d2348fd2E-7#202", 15, Up, "4.0139e7", "0x2.6478E+6#15", Greater, ); // - rm != Nearest && (rm != Ceiling && rm != Up || inex == Equal) && (rm != Exact || inex != // Equal) in reciprocal_float_significand_general // - cleanup == Sub1Ulp in reciprocal_float_significand_general test( "1164607425.036820041559", "0x456a7fc1.096d09ca55#71", 64, Down, "8.586584444697183348e-10", "0x3.b01add9bdcc8ca28E-8#64", Less, ); // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) in reciprocal_float_significand_general // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) && shift != 0 in // reciprocal_float_significand_general test( "18686733767405.50192797818236099916512095073138146049740456616", "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", 63, Up, "5.3513899884647508956e-14", "0xf.1015372ed29c6dcE-12#63", Greater, ); // - cmp_s_r > Equal && (rm == Floor || rm == Down) in reciprocal_float_significand_general // - cmp_s_r > Equal && (rm == Floor || rm == Down) && shift != 0 in // reciprocal_float_significand_general test( "18686733767405.50192797818236099916512095073138146049740456616", "0x10fed820d2ed.807e5a1b3d9ab71287cc373ef7f3521609fa72f#201", 63, Down, "5.351389988464750895e-14", "0xf.1015372ed29c6daE-12#63", Less, ); // - cmp_s_r > Equal && (rm == Ceiling || rm == Up) && shift == 0 in // reciprocal_float_significand_general test( "1.063382396643406948814112e37", "0x8.000000007ffffffffff8E+30#81", 64, Up, "9.4039548064414545111e-38", "0x1.ffffffffe0000002E-31#64", Greater, ); // - cmp_s_r > Equal && (rm == Floor || rm == Down) && shift == 0 in // reciprocal_float_significand_general test( "1.063382396643406948814112e37", "0x8.000000007ffffffffff8E+30#81", 64, Down, "9.4039548064414545106e-38", "0x1.ffffffffe0000000E-31#64", Less, ); // - exp > Self::MAX_EXPONENT in reciprocal // - exp > Self::MAX_EXPONENT && sign && Ceiling | Up | Nearest in reciprocal test( "too_small", "0x1.8E-268435456#2", 2, Nearest, "Infinity", "Infinity", Greater, ); // exp > Self::MAX_EXPONENT && sign && Floor | Down in reciprocal test( "too_small", "0x1.8E-268435456#2", 2, Floor, "too_big", "0x6.0E+268435455#2", Less, ); // - exp > Self::MAX_EXPONENT && !sign && Floor | Up | Nearest test( "-too_small", "-0x1.8E-268435456#2", 2, Nearest, "-Infinity", "-Infinity", Less, ); // - exp > Self::MAX_EXPONENT && !sign && Ceiling | Down in reciprocal test( "-too_small", "-0x1.8E-268435456#2", 2, Ceiling, "-too_big", "-0x6.0E+268435455#2", Greater, ); test( "too_big", "0x4.0E+268435455#1", 1, Floor, "too_small", "0x4.0E-268435456#1", Equal, ); test( "too_big", "0x6.0E+268435455#2", 2, Floor, "too_small", "0x2.0E-268435456#2", Less, ); test( "too_big", "0x7.0E+268435455#3", 3, Floor, "too_small", "0x2.0E-268435456#3", Less, ); test( "too_big", "0x7.ffffE+268435455#19", 19, Floor, "too_small", "0x2.00000E-268435456#19", Less, ); } #[test] fn reciprocal_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).reciprocal_prec_round(0, Floor)); assert_panic!(Float::one_prec(1).reciprocal_prec_round_ref(0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.reciprocal_prec_round_assign(0, Floor) }); assert_panic!(THREE.reciprocal_prec_round(1, Exact)); assert_panic!(THREE.reciprocal_prec_round_ref(1, Exact)); assert_panic!({ let mut x = THREE; x.reciprocal_prec_round_assign(1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode, extreme: bool) { let (reciprocal, o) = x.clone().reciprocal_prec_round(prec, rm); assert!(reciprocal.is_valid()); let (reciprocal_alt, o_alt) = x.reciprocal_prec_round_ref(prec, rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_prec_round_assign(prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); assert_eq!(o_alt, o); if !extreme { let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); } let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal, rug_o) = rug_reciprocal_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); } if o == Equal && reciprocal.is_finite() && reciprocal != 0 { assert_eq!( ComparableFloatRef( &reciprocal .reciprocal_prec_round_ref(x.significant_bits(), Exact) .0 ), ComparableFloatRef(&x) ); } let (reciprocal_alt, o_alt) = Float::ONE.div_prec_round(x.clone(), prec, rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if reciprocal.is_finite() && x.is_finite() { if reciprocal.is_normal() { assert_eq!(reciprocal.get_prec(), Some(prec)); } if !extreme { let r_reciprocal = Rational::exact_from(&x).reciprocal(); assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); if o == Less { let mut next = reciprocal.clone(); next.increment(); assert!(next > r_reciprocal); } else if o == Greater { let mut next = reciprocal.clone(); next.decrement(); assert!(next < r_reciprocal); } match (r_reciprocal >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_prec_round(prec, -rm); reciprocal_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(reciprocal_alt.abs_negative_zero()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.reciprocal_prec_round_ref(prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.reciprocal_prec_round_ref(prec, Exact)); } } #[test] fn reciprocal_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_3().test_properties(|(x, prec, rm)| { reciprocal_prec_round_properties_helper(x, prec, rm, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_rounding_mode_triple_gen_var_3().test_properties_with_config( &config, |(x, prec, rm)| { reciprocal_prec_round_properties_helper(x, prec, rm, false); }, ); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_small_n", 2048); float_unsigned_rounding_mode_triple_gen_var_3().test_properties_with_config( &config, |(x, prec, rm)| { reciprocal_prec_round_properties_helper(x, prec, rm, false); }, ); float_unsigned_rounding_mode_triple_gen_var_12().test_properties(|(x, prec, rm)| { reciprocal_prec_round_properties_helper(x, prec, rm, true); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { let (reciprocal, o) = Float::NAN.reciprocal_prec_round(prec, rm); assert!(reciprocal.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.reciprocal_prec_round(prec, rm), (Float::ZERO, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.reciprocal_prec_round(prec, rm), (Float::NEGATIVE_ZERO, Equal) ); assert_eq!( Float::ZERO.reciprocal_prec_round(prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_ZERO.reciprocal_prec_round(prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::ONE.reciprocal_prec_round(prec, rm), (Float::one_prec(prec), Equal) ); assert_eq!( Float::NEGATIVE_ONE.reciprocal_prec_round(prec, rm), (Float::negative_one_prec(prec), Equal) ); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_prec_properties_helper(x: Float, prec: u64, extreme: bool) { let (reciprocal, o) = x.clone().reciprocal_prec(prec); assert!(reciprocal.is_valid()); let (reciprocal_alt, o_alt) = x.reciprocal_prec_ref(prec); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_prec_assign(prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); assert_eq!(o_alt, o); if !extreme { let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); } let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), prec, Nearest); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let (rug_reciprocal, rug_o) = rug_reciprocal_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); let (reciprocal_alt, o_alt) = Float::ONE.div_prec(x.clone(), prec); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if reciprocal.is_finite() && x.is_finite() { if reciprocal.is_normal() { assert_eq!(reciprocal.get_prec(), Some(prec)); } if !extreme { let r_reciprocal = Rational::exact_from(&x).reciprocal(); assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); if o == Less { let mut next = reciprocal.clone(); next.increment(); assert!(next > r_reciprocal); } else if o == Greater { let mut next = reciprocal.clone(); next.decrement(); assert!(next < r_reciprocal); } } } let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_prec(prec); reciprocal_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(reciprocal_alt.abs_negative_zero()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); } #[test] fn reciprocal_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { reciprocal_prec_properties_helper(x, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { reciprocal_prec_properties_helper(x, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_small_n", 2048); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { reciprocal_prec_properties_helper(x, prec, false); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { reciprocal_prec_properties_helper(x, prec, true); }); unsigned_gen_var_11().test_properties(|prec| { let (reciprocal, o) = Float::NAN.reciprocal_prec(prec); assert!(reciprocal.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.reciprocal_prec(prec), (Float::ZERO, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.reciprocal_prec(prec), (Float::NEGATIVE_ZERO, Equal) ); assert_eq!(Float::ZERO.reciprocal_prec(prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_ZERO.reciprocal_prec(prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::ONE.reciprocal_prec(prec), (Float::one_prec(prec), Equal) ); assert_eq!( Float::NEGATIVE_ONE.reciprocal_prec(prec), (Float::negative_one_prec(prec), Equal) ); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_round_properties_helper(x: Float, rm: RoundingMode, extreme: bool) { let (reciprocal, o) = x.clone().reciprocal_round(rm); assert!(reciprocal.is_valid()); let (reciprocal_alt, o_alt) = x.reciprocal_round_ref(rm); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_round_assign(rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); assert_eq!(o_alt, o); if !extreme { let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); } let (reciprocal_alt, o_alt) = reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal, rug_o) = rug_reciprocal_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!(rug_o, o); } let (reciprocal_alt, o_alt) = Float::ONE.div_round(x.clone(), rm); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); assert_eq!(o_alt, o); if reciprocal.is_finite() && x.is_finite() { if reciprocal.is_normal() { assert_eq!(reciprocal.get_prec(), Some(x.significant_bits())); } if !extreme { let r_reciprocal = Rational::exact_from(&x).reciprocal(); assert_eq!(reciprocal.partial_cmp(&r_reciprocal), Some(o)); if o == Less { let mut next = reciprocal.clone(); next.increment(); assert!(next > r_reciprocal); } else if o == Greater { let mut next = reciprocal.clone(); next.decrement(); assert!(next < r_reciprocal); } match (r_reciprocal >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (mut reciprocal_alt, mut o_alt) = (-&x).reciprocal_round(-rm); reciprocal_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(reciprocal_alt.abs_negative_zero()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.reciprocal_round_ref(rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.reciprocal_round_ref(Exact)); } } #[test] fn reciprocal_round_properties() { float_rounding_mode_pair_gen_var_13().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_rounding_mode_pair_gen_var_13().test_properties_with_config(&config, |(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_14().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_15().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_16().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_17().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_23().test_properties(|(x, rm)| { reciprocal_round_properties_helper(x, rm, true); }); rounding_mode_gen().test_properties(|rm| { let (reciprocal, o) = Float::NAN.reciprocal_round(rm); assert!(reciprocal.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.reciprocal_round(rm), (Float::ZERO, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.reciprocal_round(rm), (Float::NEGATIVE_ZERO, Equal) ); assert_eq!(Float::ZERO.reciprocal_round(rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_ZERO.reciprocal_round(rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!(Float::ONE.reciprocal_round(rm), (Float::ONE, Equal)); assert_eq!( Float::NEGATIVE_ONE.reciprocal_round(rm), (Float::NEGATIVE_ONE, Equal) ); }); } #[allow(clippy::type_repetition_in_bounds)] fn reciprocal_properties_helper_2() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { let reciprocal_1 = x.reciprocal(); let reciprocal_2 = emulate_float_to_float_fn(Float::reciprocal_prec, x); assert_eq!(NiceFloat(reciprocal_1), NiceFloat(reciprocal_2)); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_properties_helper_1(x: Float, extreme: bool) { let reciprocal = x.clone().reciprocal(); assert!(reciprocal.is_valid()); let reciprocal_alt = (&x).reciprocal(); assert!(reciprocal_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_alt), ComparableFloatRef(&reciprocal) ); let mut x_alt = x.clone(); x_alt.reciprocal_assign(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal)); if !extreme { assert_eq!( ComparableFloatRef( &reciprocal_prec_round_naive_1(x.clone(), x.significant_bits(), Nearest).0 ), ComparableFloatRef(&reciprocal) ); } assert_eq!( ComparableFloatRef( &reciprocal_prec_round_naive_2(x.clone(), x.significant_bits(), Nearest).0 ), ComparableFloatRef(&reciprocal) ); let rug_reciprocal = rug_reciprocal(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal)), ComparableFloatRef(&reciprocal), ); assert_eq!( ComparableFloatRef(&(Float::ONE / x.clone())), ComparableFloatRef(&reciprocal) ); if reciprocal.is_finite() && x.is_finite() { if reciprocal.is_normal() { assert_eq!(reciprocal.get_prec(), Some(x.significant_bits())); } if !extreme { let r_reciprocal = Rational::exact_from(&x).reciprocal(); if reciprocal < r_reciprocal { let mut next = reciprocal.clone(); next.increment(); assert!(next > r_reciprocal); } else if reciprocal > r_reciprocal { let mut next = reciprocal.clone(); next.decrement(); assert!(next < r_reciprocal); } } } let mut reciprocal_alt = (-&x).reciprocal(); reciprocal_alt.neg_assign(); assert_eq!( ComparableFloat(reciprocal_alt.abs_negative_zero()), ComparableFloat(reciprocal.abs_negative_zero_ref()) ); } #[test] fn reciprocal_properties() { float_gen().test_properties(|x| { reciprocal_properties_helper_1(x, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_gen().test_properties_with_config(&config, |x| { reciprocal_properties_helper_1(x, false); }); float_gen_var_6().test_properties(|x| { reciprocal_properties_helper_1(x, false); }); float_gen_var_7().test_properties(|x| { reciprocal_properties_helper_1(x, false); }); float_gen_var_8().test_properties(|x| { reciprocal_properties_helper_1(x, false); }); float_gen_var_11().test_properties(|x| { reciprocal_properties_helper_1(x, false); }); float_gen_var_12().test_properties(|x| { reciprocal_properties_helper_1(x, true); }); apply_fn_to_primitive_floats!(reciprocal_properties_helper_2); } ================================================ FILE: malachite-float/tests/arithmetic/reciprocal_sqrt.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use core::{f32, f64}; use malachite_base::num::arithmetic::traits::{ PowerOf2, Reciprocal, ReciprocalSqrt, ReciprocalSqrtAssign, Square, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::arithmetic::reciprocal_sqrt::{ primitive_float_reciprocal_sqrt, primitive_float_reciprocal_sqrt_rational, }; use malachite_float::test_util::arithmetic::reciprocal_sqrt::{ reciprocal_sqrt_rational_prec_round_generic, reciprocal_sqrt_rational_prec_round_simple, rug_reciprocal_sqrt, rug_reciprocal_sqrt_prec, rug_reciprocal_sqrt_prec_round, rug_reciprocal_sqrt_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_rounding_mode_pair_gen_var_30, float_rounding_mode_pair_gen_var_31, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_15, float_unsigned_rounding_mode_triple_gen_var_16, rational_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen_var_1, rational_pair_gen_var_8, rational_unsigned_pair_gen_var_7, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_reciprocal_sqrt() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let reciprocal_sqrt = x.clone().reciprocal_sqrt(); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); let reciprocal_sqrt_alt = (&x).reciprocal_sqrt(); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); let mut reciprocal_sqrt_alt = x.clone(); reciprocal_sqrt_alt.reciprocal_sqrt_assign(); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt(&rug::Float::exact_from( &x )))), ComparableFloatRef(&reciprocal_sqrt) ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "0.0", "0x0.0"); test("-Infinity", "-Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "Infinity", "Infinity"); test("-0.0", "-0x0.0", "Infinity", "Infinity"); // - working_prec < limb_to_bit_count(rn) in limbs_reciprocal_sqrt // - in limbs_reciprocal_sqrt // - an <= n in limbs_reciprocal_sqrt // - p > 11 in limbs_reciprocal_sqrt // - ahn <= an in limbs_reciprocal_sqrt // - p == 11 in limbs_reciprocal_sqrt // - h << 1 <= Limb::WIDTH in limbs_reciprocal_sqrt // - rn == 1 in limbs_reciprocal_sqrt // - neg == 0 first time in limbs_reciprocal_sqrt // - tn == 1 in limbs_reciprocal_sqrt // - !a_s in limbs_reciprocal_sqrt // - pl != 0 in limbs_reciprocal_sqrt // - neg == 0 second time in limbs_reciprocal_sqrt // - neg == 0 && ln == 0 in limbs_reciprocal_sqrt // - cy != 0 in limbs_reciprocal_sqrt // - h << 1 > Limb::WIDTH && xn == 1 in limbs_reciprocal_sqrt // - rn != 1 in limbs_reciprocal_sqrt // - tn != 1 in limbs_reciprocal_sqrt // - pl == 0 in limbs_reciprocal_sqrt // - can't round in limbs_reciprocal_sqrt // - s == 0 && x.is_power_of_2() in limbs_reciprocal_sqrt test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("-1.0", "-0x1.0#1", "NaN", "NaN"); test( "1.0", "0x1.0000000000000000000000000#100", "1.0", "0x1.0000000000000000000000000#100", ); test("-1.0", "-0x1.0000000000000000000000000#100", "NaN", "NaN"); test("123.0", "0x7b.0#7", "0.09", "0x0.170#7"); test("-123.0", "-0x7b.0#7", "NaN", "NaN"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0.5641895835477563", "0x0.906eba8214db68#53", ); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "NaN", "NaN"); } #[test] fn test_reciprocal_sqrt_prec() { let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_prec(prec); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, o_out); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_prec_ref(prec); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_sqrt_alt = x.clone(); let o_alt = reciprocal_sqrt_alt.reciprocal_sqrt_prec_assign(prec); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal); test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, "1.0", "0x1.000#10", Equal, ); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", 1, "0.06", "0x0.1#1", Less); test("123.0", "0x7b.0#7", 10, "0.0902", "0x0.1718#10", Greater); test("-123.0", "-0x7b.0#7", 1, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "0.5", "0x0.8#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.564", "0x0.908#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); // - a_s in limbs_reciprocal_sqrt // - cy == 0 in limbs_reciprocal_sqrt // - neg != 0 first time in limbs_reciprocal_sqrt // - neg != 0 second time in limbs_reciprocal_sqrt // - neg != 0 && ln == 0 in limbs_reciprocal_sqrt // - can round in limbs_reciprocal_sqrt test("2.0", "0x2.0#1", 1, "0.5", "0x0.8#1", Less); // - neg == 0 && ln != 0 in limbs_reciprocal_sqrt // - h << 1 > Limb::WIDTH && xn != 1 in limbs_reciprocal_sqrt // - rn < xn << 1 in limbs_reciprocal_sqrt test( "21729783659306408649613509.686", "0x11f975eebbcb21a32ee0c5.af8#95", 95, "2.14522227948652325458263602314e-13", "0x3.c61f4a318617d94043119898E-11#95", Less, ); // - working_prec >= limb_to_bit_count(rn) in limbs_reciprocal_sqrt // - neg != 0 && ln != 0 in limbs_reciprocal_sqrt test( "513.233925441497129966680656795646506", "0x201.3be289a8eeba947a6a3693540ab#118", 118, "0.0441410156743607347324939524894430093", "0x0.0b4cd35abbcd63a67e82b6f5189c42c#118", Less, ); // - rn >= xn << 1 in limbs_reciprocal_sqrt test( "531607.999405753398566100250398911805595276409254333486007034444758646220477451", "0x81c97.ffd90e3247f501afdb3e5781d0c650b8de694094110713b5a698d3d38550#257", 257, "0.00137152663593666837873986552665405007986703190176786715506823381645265890475571", "0x0.0059e2660c04516f28e8c959120460810dbcbbd967b4a8d1f95cf325678e624d8b8#257", Less, ); // - s != 0 || !x.is_power_of_2() in limbs_reciprocal_sqrt // - ahn > an in limbs_reciprocal_sqrt test( "2.97703041169639178e-21", "0xe.0f0249448dd1dE-18#56", 56, "18327716753.4591751", "0x4446ac391.758c80#56", Less, ); // - an > n in limbs_reciprocal_sqrt test( "0.000199046277632504184666664672269768242929310652018203552191617720205649", "0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225", 26, "70.879879", "0x46.e13fc#26", Less, ); } #[test] fn reciprocal_sqrt_prec_fail() { assert_panic!(Float::NAN.reciprocal_sqrt_prec(0)); assert_panic!(Float::NAN.reciprocal_sqrt_prec_ref(0)); assert_panic!({ let mut x = Float::NAN; x.reciprocal_sqrt_prec_assign(0) }); } #[test] fn test_reciprocal_sqrt_round() { let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_round(rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, o_out); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_round_ref(rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_sqrt_alt = x.clone(); let o_alt = reciprocal_sqrt_alt.reciprocal_sqrt_round_assign(rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", Floor, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Ceiling, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Down, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Up, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Nearest, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", Exact, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Down, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Up, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal); test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", Floor, "0.09", "0x0.170#7", Less); test("123.0", "0x7b.0#7", Ceiling, "0.091", "0x0.174#7", Greater); test("123.0", "0x7b.0#7", Down, "0.09", "0x0.170#7", Less); test("123.0", "0x7b.0#7", Up, "0.091", "0x0.174#7", Greater); test("123.0", "0x7b.0#7", Nearest, "0.09", "0x0.170#7", Less); test("-123.0", "-0x7b.0#7", Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "0.5641895835477563", "0x0.906eba8214db68#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "0.5641895835477564", "0x0.906eba8214db70#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "0.5641895835477563", "0x0.906eba8214db68#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "0.5641895835477564", "0x0.906eba8214db70#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "0.5641895835477563", "0x0.906eba8214db68#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "NaN", "NaN", Equal, ); } #[test] fn reciprocal_sqrt_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.reciprocal_sqrt_round(Exact)); assert_panic!(THREE.reciprocal_sqrt_round_ref(Exact)); assert_panic!({ let mut x = THREE; x.reciprocal_sqrt_round_assign(Exact); }); } #[test] fn test_reciprocal_sqrt_prec_round() { let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_prec_round(prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, o_out); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_prec_round_ref(prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); let mut reciprocal_sqrt_alt = x.clone(); let o_alt = reciprocal_sqrt_alt.reciprocal_sqrt_prec_round_assign(prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt), ComparableFloatRef(&reciprocal_sqrt_alt) ); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, Floor, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Ceiling, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Down, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Up, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Nearest, "0.0", "0x0.0", Equal); test("Infinity", "Infinity", 1, Exact, "0.0", "0x0.0", Equal); test("-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal); test("-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal); test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, Floor, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Down, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Up, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Exact, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Exact, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Exact, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", 1, Floor, "0.06", "0x0.1#1", Less); test("123.0", "0x7b.0#7", 1, Ceiling, "0.1", "0x0.2#1", Greater); test("123.0", "0x7b.0#7", 1, Down, "0.06", "0x0.1#1", Less); test("123.0", "0x7b.0#7", 1, Up, "0.1", "0x0.2#1", Greater); test("123.0", "0x7b.0#7", 1, Nearest, "0.06", "0x0.1#1", Less); test( "123.0", "0x7b.0#7", 10, Floor, "0.0901", "0x0.1710#10", Less, ); test( "123.0", "0x7b.0#7", 10, Ceiling, "0.0902", "0x0.1718#10", Greater, ); test("123.0", "0x7b.0#7", 10, Down, "0.0901", "0x0.1710#10", Less); test( "123.0", "0x7b.0#7", 10, Up, "0.0902", "0x0.1718#10", Greater, ); test( "123.0", "0x7b.0#7", 10, Nearest, "0.0902", "0x0.1718#10", Greater, ); test("-123.0", "-0x7b.0#7", 1, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "0.5", "0x0.8#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "1.0", "0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "0.5", "0x0.8#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "1.0", "0x1.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "0.5", "0x0.8#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "0.563", "0x0.904#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "0.564", "0x0.908#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "0.563", "0x0.904#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "0.564", "0x0.908#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "0.564", "0x0.908#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_reciprocal_sqrt() { fn test(x: T, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { assert_eq!( NiceFloat(primitive_float_reciprocal_sqrt(x)), NiceFloat(out) ); } test::(f32::NAN, f32::NAN); test::(f32::INFINITY, 0.0); test::(f32::NEGATIVE_INFINITY, f32::NAN); test::(0.0, f32::INFINITY); test::(-0.0, f32::INFINITY); test::(1.0, 1.0); test::(-1.0, f32::NAN); test::(0.5, core::f32::consts::SQRT_2); test::(-0.5, f32::NAN); test::(2.0, core::f32::consts::FRAC_1_SQRT_2); test::(-2.0, f32::NAN); test::(core::f32::consts::PI, 0.56418955); test::(-core::f32::consts::PI, f32::NAN); test::(f64::NAN, f64::NAN); test::(f64::INFINITY, 0.0); test::(f64::NEGATIVE_INFINITY, f64::NAN); test::(0.0, f64::INFINITY); test::(-0.0, f64::INFINITY); test::(1.0, 1.0); test::(-1.0, f64::NAN); test::(0.5, core::f64::consts::SQRT_2); test::(-0.5, f64::NAN); test::(2.0, core::f64::consts::FRAC_1_SQRT_2); test::(-2.0, f64::NAN); test::(core::f64::consts::PI, 0.5641895835477563); test::(-core::f64::consts::PI, f64::NAN); } #[test] fn test_reciprocal_sqrt_rational_prec() { let test = |s, prec, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec(u.clone(), prec); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_ref(&u, prec); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_generic(&u, prec, Nearest); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_simple(&u, prec, Nearest); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, u), Less => { assert!(square > u); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < u); } } Greater => { assert!(square < u); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > u); } } } } }; test("0", 1, "Infinity", "Infinity", Equal); test("0", 10, "Infinity", "Infinity", Equal); test("0", 100, "Infinity", "Infinity", Equal); test("1", 1, "1.0", "0x1.0#1", Equal); test("1", 10, "1.0", "0x1.000#10", Equal); test("1", 100, "1.0", "0x1.0000000000000000000000000#100", Equal); test("1/2", 1, "1.0", "0x1.0#1", Less); test("1/2", 10, "1.414", "0x1.6a0#10", Less); test( "1/2", 100, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test("1/3", 1, "2.0", "0x2.0#1", Greater); test("1/3", 10, "1.732", "0x1.bb8#10", Greater); test( "1/3", 100, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test("22/7", 1, "0.5", "0x0.8#1", Less); test("22/7", 10, "0.564", "0x0.908#10", Greater); test( "22/7", 100, "0.5640760748177662089151473616116", "0x0.90674a25cc60febbd6cc7515c#100", Greater, ); let test_big = |u: Rational, prec, out, out_hex, out_o| { let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec(u.clone(), prec); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_ref(&u, prec); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_generic(&u, prec, Nearest); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_simple(&u, prec, Nearest); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, u), Less => { assert!(square > u); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < u); } } Greater => { assert!(square < u); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0 { assert!(Rational::exact_from(&previous).square().reciprocal() > u); } } } } }; test_big( Rational::power_of_2(1000i64), 10, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(-1000i64), 10, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, "too_big", "0x1.6a0E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_big", "0x1.6a0E+134217728#10", Greater, ); } #[test] fn reciprocal_sqrt_rational_prec_fail() { assert_panic!(Float::reciprocal_sqrt_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::reciprocal_sqrt_rational_prec(Rational::ONE, 0)); assert_panic!(Float::reciprocal_sqrt_rational_prec( Rational::NEGATIVE_ONE, 0 )); } #[test] fn reciprocal_sqrt_rational_prec_ref_fail() { assert_panic!(Float::reciprocal_sqrt_rational_prec_ref(&Rational::ZERO, 0)); assert_panic!(Float::reciprocal_sqrt_rational_prec_ref(&Rational::ONE, 0)); assert_panic!(Float::reciprocal_sqrt_rational_prec_ref( &Rational::NEGATIVE_ONE, 0 )); } #[test] fn test_reciprocal_sqrt_rational_prec_round() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_round(u.clone(), prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_round_ref(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_generic(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_simple(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, u), Less => { assert!(square > u); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < u); } } Greater => { assert!(square < u); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > u); } } } } }; test("0", 1, Floor, "Infinity", "Infinity", Equal); test("0", 1, Ceiling, "Infinity", "Infinity", Equal); test("0", 1, Down, "Infinity", "Infinity", Equal); test("0", 1, Up, "Infinity", "Infinity", Equal); test("0", 1, Nearest, "Infinity", "Infinity", Equal); test("0", 1, Exact, "Infinity", "Infinity", Equal); test("0", 10, Floor, "Infinity", "Infinity", Equal); test("0", 10, Ceiling, "Infinity", "Infinity", Equal); test("0", 10, Down, "Infinity", "Infinity", Equal); test("0", 10, Up, "Infinity", "Infinity", Equal); test("0", 10, Nearest, "Infinity", "Infinity", Equal); test("0", 10, Exact, "Infinity", "Infinity", Equal); test("0", 100, Floor, "Infinity", "Infinity", Equal); test("0", 100, Ceiling, "Infinity", "Infinity", Equal); test("0", 100, Down, "Infinity", "Infinity", Equal); test("0", 100, Up, "Infinity", "Infinity", Equal); test("0", 100, Nearest, "Infinity", "Infinity", Equal); test("0", 100, Exact, "Infinity", "Infinity", Equal); test("1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1", 1, Down, "1.0", "0x1.0#1", Equal); test("1", 1, Up, "1.0", "0x1.0#1", Equal); test("1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1", 10, Down, "1.0", "0x1.000#10", Equal); test("1", 10, Up, "1.0", "0x1.000#10", Equal); test("1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1", 10, Exact, "1.0", "0x1.000#10", Equal); test( "1", 100, Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test("1/2", 1, Floor, "1.0", "0x1.0#1", Less); test("1/2", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("1/2", 1, Down, "1.0", "0x1.0#1", Less); test("1/2", 1, Up, "2.0", "0x2.0#1", Greater); test("1/2", 1, Nearest, "1.0", "0x1.0#1", Less); test("1/2", 10, Floor, "1.414", "0x1.6a0#10", Less); test("1/2", 10, Ceiling, "1.416", "0x1.6a8#10", Greater); test("1/2", 10, Down, "1.414", "0x1.6a0#10", Less); test("1/2", 10, Up, "1.416", "0x1.6a8#10", Greater); test("1/2", 10, Nearest, "1.414", "0x1.6a0#10", Less); test( "1/2", 100, Floor, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test( "1/2", 100, Ceiling, "1.414213562373095048801688724211", "0x1.6a09e667f3bcc908b2fb13670#100", Greater, ); test( "1/2", 100, Down, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test( "1/2", 100, Up, "1.414213562373095048801688724211", "0x1.6a09e667f3bcc908b2fb13670#100", Greater, ); test( "1/2", 100, Nearest, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test("1/3", 1, Floor, "1.0", "0x1.0#1", Less); test("1/3", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("1/3", 1, Down, "1.0", "0x1.0#1", Less); test("1/3", 1, Up, "2.0", "0x2.0#1", Greater); test("1/3", 1, Nearest, "2.0", "0x2.0#1", Greater); test("1/3", 10, Floor, "1.73", "0x1.bb0#10", Less); test("1/3", 10, Ceiling, "1.732", "0x1.bb8#10", Greater); test("1/3", 10, Down, "1.73", "0x1.bb0#10", Less); test("1/3", 10, Up, "1.732", "0x1.bb8#10", Greater); test("1/3", 10, Nearest, "1.732", "0x1.bb8#10", Greater); test( "1/3", 100, Floor, "1.732050807568877293527446341505", "0x1.bb67ae8584caa73b25742d706#100", Less, ); test( "1/3", 100, Ceiling, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test( "1/3", 100, Down, "1.732050807568877293527446341505", "0x1.bb67ae8584caa73b25742d706#100", Less, ); test( "1/3", 100, Up, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test( "1/3", 100, Nearest, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test("22/7", 1, Floor, "0.5", "0x0.8#1", Less); test("22/7", 1, Ceiling, "1.0", "0x1.0#1", Greater); test("22/7", 1, Down, "0.5", "0x0.8#1", Less); test("22/7", 1, Up, "1.0", "0x1.0#1", Greater); test("22/7", 1, Nearest, "0.5", "0x0.8#1", Less); test("22/7", 10, Floor, "0.563", "0x0.904#10", Less); test("22/7", 10, Ceiling, "0.564", "0x0.908#10", Greater); test("22/7", 10, Down, "0.563", "0x0.904#10", Less); test("22/7", 10, Up, "0.564", "0x0.908#10", Greater); test("22/7", 10, Nearest, "0.564", "0x0.908#10", Greater); test( "22/7", 100, Floor, "0.564076074817766208915147361611", "0x0.90674a25cc60febbd6cc7515b#100", Less, ); test( "22/7", 100, Ceiling, "0.5640760748177662089151473616116", "0x0.90674a25cc60febbd6cc7515c#100", Greater, ); test( "22/7", 100, Down, "0.564076074817766208915147361611", "0x0.90674a25cc60febbd6cc7515b#100", Less, ); test( "22/7", 100, Up, "0.5640760748177662089151473616116", "0x0.90674a25cc60febbd6cc7515c#100", Greater, ); test( "22/7", 100, Nearest, "0.5640760748177662089151473616116", "0x0.90674a25cc60febbd6cc7515c#100", Greater, ); test("-1", 1, Floor, "NaN", "NaN", Equal); test("-1", 1, Ceiling, "NaN", "NaN", Equal); test("-1", 1, Down, "NaN", "NaN", Equal); test("-1", 1, Up, "NaN", "NaN", Equal); test("-1", 1, Nearest, "NaN", "NaN", Equal); test("-1", 1, Exact, "NaN", "NaN", Equal); test("-1", 10, Floor, "NaN", "NaN", Equal); test("-1", 10, Ceiling, "NaN", "NaN", Equal); test("-1", 10, Down, "NaN", "NaN", Equal); test("-1", 10, Up, "NaN", "NaN", Equal); test("-1", 10, Nearest, "NaN", "NaN", Equal); test("-1", 10, Exact, "NaN", "NaN", Equal); test("-1", 100, Floor, "NaN", "NaN", Equal); test("-1", 100, Ceiling, "NaN", "NaN", Equal); test("-1", 100, Down, "NaN", "NaN", Equal); test("-1", 100, Up, "NaN", "NaN", Equal); test("-1", 100, Nearest, "NaN", "NaN", Equal); test("-1", 100, Exact, "NaN", "NaN", Equal); test("-1/2", 1, Floor, "NaN", "NaN", Equal); test("-1/2", 1, Ceiling, "NaN", "NaN", Equal); test("-1/2", 1, Down, "NaN", "NaN", Equal); test("-1/2", 1, Up, "NaN", "NaN", Equal); test("-1/2", 1, Nearest, "NaN", "NaN", Equal); test("-1/2", 1, Exact, "NaN", "NaN", Equal); test("-1/2", 10, Floor, "NaN", "NaN", Equal); test("-1/2", 10, Ceiling, "NaN", "NaN", Equal); test("-1/2", 10, Down, "NaN", "NaN", Equal); test("-1/2", 10, Up, "NaN", "NaN", Equal); test("-1/2", 10, Nearest, "NaN", "NaN", Equal); test("-1/2", 10, Exact, "NaN", "NaN", Equal); test("-1/2", 100, Floor, "NaN", "NaN", Equal); test("-1/2", 100, Ceiling, "NaN", "NaN", Equal); test("-1/2", 100, Down, "NaN", "NaN", Equal); test("-1/2", 100, Up, "NaN", "NaN", Equal); test("-1/2", 100, Nearest, "NaN", "NaN", Equal); test("-1/2", 100, Exact, "NaN", "NaN", Equal); test("-1/3", 1, Floor, "NaN", "NaN", Equal); test("-1/3", 1, Ceiling, "NaN", "NaN", Equal); test("-1/3", 1, Down, "NaN", "NaN", Equal); test("-1/3", 1, Up, "NaN", "NaN", Equal); test("-1/3", 1, Nearest, "NaN", "NaN", Equal); test("-1/3", 10, Floor, "NaN", "NaN", Equal); test("-1/3", 10, Ceiling, "NaN", "NaN", Equal); test("-1/3", 10, Down, "NaN", "NaN", Equal); test("-1/3", 10, Up, "NaN", "NaN", Equal); test("-1/3", 10, Nearest, "NaN", "NaN", Equal); test("-1/3", 100, Floor, "NaN", "NaN", Equal); test("-1/3", 100, Ceiling, "NaN", "NaN", Equal); test("-1/3", 100, Down, "NaN", "NaN", Equal); test("-1/3", 100, Up, "NaN", "NaN", Equal); test("-1/3", 100, Nearest, "NaN", "NaN", Equal); test("-22/7", 1, Floor, "NaN", "NaN", Equal); test("-22/7", 1, Ceiling, "NaN", "NaN", Equal); test("-22/7", 1, Down, "NaN", "NaN", Equal); test("-22/7", 1, Up, "NaN", "NaN", Equal); test("-22/7", 1, Nearest, "NaN", "NaN", Equal); test("-22/7", 10, Floor, "NaN", "NaN", Equal); test("-22/7", 10, Ceiling, "NaN", "NaN", Equal); test("-22/7", 10, Down, "NaN", "NaN", Equal); test("-22/7", 10, Up, "NaN", "NaN", Equal); test("-22/7", 10, Nearest, "NaN", "NaN", Equal); test("-22/7", 100, Floor, "NaN", "NaN", Equal); test("-22/7", 100, Ceiling, "NaN", "NaN", Equal); test("-22/7", 100, Down, "NaN", "NaN", Equal); test("-22/7", 100, Up, "NaN", "NaN", Equal); test("-22/7", 100, Nearest, "NaN", "NaN", Equal); let test_big = |u: Rational, prec, rm, out, out_hex, out_o| { let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_round(u.clone(), prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_round_ref(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_generic(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); let (reciprocal_sqrt, o) = reciprocal_sqrt_rational_prec_round_simple(&u, prec, rm); assert!(reciprocal_sqrt.is_valid()); assert_eq!(reciprocal_sqrt.to_string(), out); assert_eq!(to_hex_string(&reciprocal_sqrt), out_hex); assert_eq!(o, out_o); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, u), Less => { assert!(square > u); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < u); } } Greater => { assert!(square < u); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > u); } } } } }; test_big( Rational::power_of_2(1000i64), 10, Floor, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Ceiling, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Down, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Up, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Nearest, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Exact, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Floor, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Ceiling, "too_small", "0x1.6a8E-134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Down, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Up, "too_small", "0x1.6a8E-134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Nearest, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Floor, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Down, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Up, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Nearest, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Exact, "too_small", "0x2.00E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Floor, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Ceiling, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Down, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Up, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Nearest, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Floor, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Ceiling, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Down, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Up, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Nearest, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Floor, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Ceiling, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Down, "too_small", "0x1.0E-134217728#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Up, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Nearest, "too_small", "0x2.0E-134217728#1", Greater, ); test_big( Rational::power_of_2(-1000i64), 10, Floor, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Ceiling, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Down, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Up, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Nearest, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Exact, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Floor, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Ceiling, "too_big", "0xb.54E+134217727#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Down, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Up, "too_big", "0xb.54E+134217727#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Nearest, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Floor, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Ceiling, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Down, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Up, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Nearest, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Exact, "too_big", "0x1.000E+134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Floor, "too_big", "0x1.6a0E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Ceiling, "too_big", "0x1.6a8E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Down, "too_big", "0x1.6a0E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Up, "too_big", "0x1.6a8E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Floor, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Ceiling, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Down, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Up, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "too_big", "0x1.698E+134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_big", "0x1.6a0E+134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_big", "0x1.6a0E+134217728#10", Greater, ); } #[test] fn reciprocal_sqrt_rational_prec_round_fail() { assert_panic!(Float::reciprocal_sqrt_rational_prec_round( Rational::ZERO, 0, Floor )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round( Rational::ONE, 0, Floor )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round( Rational::from(123u32), 1, Exact )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round( Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round( Rational::NEGATIVE_ONE, 0, Floor )); } #[test] fn reciprocal_sqrt_rational_prec_round_ref_fail() { assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &Rational::ZERO, 0, Floor )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &Rational::ONE, 0, Floor )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &Rational::from(123u32), 1, Exact )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &Rational::NEGATIVE_ONE, 0, Floor )); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_reciprocal_sqrt_rational() { fn test(s: &str, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { let u = Rational::from_str(s).unwrap(); let reciprocal_sqrt = primitive_float_reciprocal_sqrt_rational::(&u); assert_eq!(NiceFloat(reciprocal_sqrt), NiceFloat(out)); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(reciprocal_sqrt).square().reciprocal(); match square.cmp(&u) { Less => { let mut next = reciprocal_sqrt; next = next.next_lower(); assert!(Rational::exact_from(next).square().reciprocal() > u); } Greater => { let mut previous = reciprocal_sqrt; previous = previous.next_higher(); assert!(Rational::exact_from(previous).square().reciprocal() < u); } _ => {} } } } test::("0", f32::INFINITY); test::("1", 1.0); test::("1/2", f32::consts::SQRT_2); test::("1/3", 1.7320508); test::("22/7", 0.56407607); test::("1/225", 15.0); test::("-1", f32::NAN); test::("-1/2", f32::NAN); test::("-1/3", f32::NAN); test::("-22/7", f32::NAN); test::("0", f64::INFINITY); test::("1", 1.0); test::("1/2", f64::consts::SQRT_2); test::("1/3", 1.7320508075688772); test::("22/7", 0.5640760748177662); test::("1/225", 15.0); test::("-1", f64::NAN); test::("-1/2", f64::NAN); test::("-1/3", f64::NAN); test::("-22/7", f64::NAN); #[allow(clippy::needless_pass_by_value)] fn test_big(u: Rational, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { let reciprocal_sqrt = primitive_float_reciprocal_sqrt_rational::(&u); assert_eq!(NiceFloat(reciprocal_sqrt), NiceFloat(out)); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(reciprocal_sqrt).square().reciprocal(); match square.cmp(&u) { Less => { let mut next = reciprocal_sqrt; next = next.next_lower(); assert!(Rational::exact_from(next).square().reciprocal() > u); } Greater => { let mut previous = reciprocal_sqrt; previous = previous.next_higher(); assert!(Rational::exact_from(previous).square().reciprocal() < u); } _ => {} } } } test_big::(Rational::power_of_2(1000i64), 0.0); test_big::(Rational::power_of_2(-1000i64), f32::INFINITY); test_big::(Rational::power_of_2(-290i64), f32::INFINITY); test_big::(Rational::power_of_2(-200i64), 1.2676506e30); test_big::(Rational::power_of_2(10000i64), 0.0); test_big::(Rational::power_of_2(1000i64), 3.054936363499605e-151); test_big::(Rational::power_of_2(-10000i64), f64::INFINITY); test_big::(Rational::power_of_2(-2100i64), f64::INFINITY); test_big::(Rational::power_of_2(-1000i64), 3.273390607896142e150); } #[test] fn reciprocal_sqrt_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).reciprocal_sqrt_prec_round(0, Floor)); assert_panic!(Float::one_prec(1).reciprocal_sqrt_prec_round_ref(0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.reciprocal_sqrt_prec_round_assign(0, Floor) }); assert_panic!(THREE.reciprocal_sqrt_prec_round(1, Exact)); assert_panic!(THREE.reciprocal_sqrt_prec_round_ref(1, Exact)); assert_panic!({ let mut x = THREE; x.reciprocal_sqrt_prec_round_assign(1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_sqrt_prec_round_properties_helper( x: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_prec_round(prec, rm); assert!(reciprocal_sqrt.is_valid()); let (reciprocal_sqrt_alt, o_alt) = x.clone().reciprocal_sqrt_prec_round_ref(prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_sqrt_prec_round_assign(prec, rm); assert!(x_alt.is_valid()); assert_eq!( ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); } if x >= 0u32 && !x.is_negative_zero() { assert!(reciprocal_sqrt.is_sign_positive()); } if reciprocal_sqrt.is_normal() { assert_eq!(reciprocal_sqrt.get_prec(), Some(prec)); if x > 1u32 && o < Greater { assert!(reciprocal_sqrt < x); } else if x < 1u32 && o > Less { assert!(reciprocal_sqrt > x); } } if !extreme && x.is_normal() && reciprocal_sqrt.is_normal() { let reciprocal_square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(reciprocal_square, x), Less => { assert!(reciprocal_square > x); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < x); } } Greater => { assert!(reciprocal_square < x); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > x); } } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.reciprocal_sqrt_prec_round_ref(prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(reciprocal_sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.reciprocal_sqrt_prec_round_ref(prec, Exact)); } } #[test] fn reciprocal_sqrt_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_15().test_properties(|(x, prec, rm)| { reciprocal_sqrt_prec_round_properties_helper(x, prec, rm, false); }); float_unsigned_rounding_mode_triple_gen_var_16().test_properties(|(x, prec, rm)| { reciprocal_sqrt_prec_round_properties_helper(x, prec, rm, true); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { let (product, o) = Float::NAN.reciprocal_sqrt_prec_round(prec, rm); assert!(product.is_nan()); assert_eq!(o, Equal); let (s, o) = Float::INFINITY.reciprocal_sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (s, o) = Float::NEGATIVE_INFINITY.reciprocal_sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); let (s, o) = Float::ZERO.reciprocal_sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::INFINITY)); assert_eq!(o, Equal); let (s, o) = Float::NEGATIVE_ZERO.reciprocal_sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::INFINITY)); assert_eq!(o, Equal); assert_eq!( Float::ONE.reciprocal_sqrt_prec_round(prec, rm), (Float::one_prec(prec), Equal) ); let (s, o) = Float::NEGATIVE_ONE.reciprocal_sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_sqrt_prec_properties_helper(x: Float, prec: u64, extreme: bool) { let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_prec(prec); assert!(reciprocal_sqrt.is_valid()); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_prec_ref(prec); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_sqrt_prec_assign(prec); assert!(x_alt.is_valid()); assert_eq!( ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_prec_round_ref(prec, Nearest); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); if x >= 0u32 && !x.is_negative_zero() { assert!(reciprocal_sqrt.is_sign_positive()); } if reciprocal_sqrt.is_normal() { assert_eq!(reciprocal_sqrt.get_prec(), Some(prec)); if x > 1u32 && o < Greater { assert!(reciprocal_sqrt < x); } else if x < 1u32 && o > Less { assert!(reciprocal_sqrt > x); } } if !extreme && x.is_normal() && reciprocal_sqrt.is_normal() { let reciprocal_square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(reciprocal_square, x), Less => { assert!(reciprocal_square > x); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < x); } } Greater => { assert!(reciprocal_square < x); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0 { assert!(Rational::exact_from(&previous).square().reciprocal() > x); } } } } } #[test] fn reciprocal_sqrt_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { reciprocal_sqrt_prec_properties_helper(x, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { reciprocal_sqrt_prec_properties_helper(x, prec, false); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { reciprocal_sqrt_prec_properties_helper(x, prec, true); }); unsigned_gen_var_11().test_properties(|prec| { let (reciprocal_sqrt, o) = Float::NAN.reciprocal_sqrt_prec(prec); assert!(reciprocal_sqrt.is_nan()); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::ZERO.reciprocal_sqrt_prec(prec); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::INFINITY) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::NEGATIVE_ZERO.reciprocal_sqrt_prec(prec); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::INFINITY) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::INFINITY.reciprocal_sqrt_prec(prec); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::ZERO) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::NEGATIVE_INFINITY.reciprocal_sqrt_prec(prec); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::NAN) ); assert_eq!(o, Equal); assert_eq!( Float::ONE.reciprocal_sqrt_prec(prec), (Float::one_prec(prec), Equal) ); let (reciprocal_sqrt, o) = Float::NEGATIVE_ONE.reciprocal_sqrt_prec(prec); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::NAN) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_sqrt_round_properties_helper(x: Float, rm: RoundingMode, extreme: bool) { let (reciprocal_sqrt, o) = x.clone().reciprocal_sqrt_round(rm); assert!(reciprocal_sqrt.is_valid()); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_round_ref(rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); let mut x_alt = x.clone(); let o_alt = x_alt.reciprocal_sqrt_round_assign(rm); assert!(x_alt.is_valid()); assert_eq!( ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); let (reciprocal_sqrt_alt, o_alt) = x.reciprocal_sqrt_prec_round_ref(x.significant_bits(), rm); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o_alt, o); if x >= 0u32 && !x.is_negative_zero() { assert!(reciprocal_sqrt.is_sign_positive()); } if reciprocal_sqrt.is_normal() { assert_eq!(reciprocal_sqrt.get_prec(), Some(x.get_prec().unwrap())); if x > 1u32 && o < Greater { assert!(reciprocal_sqrt < x); } else if x < 1u32 && o > Less { assert!(reciprocal_sqrt > x); } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_reciprocal_sqrt, rug_o) = rug_reciprocal_sqrt_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); assert_eq!(rug_o, o); } if !extreme && x.is_normal() && reciprocal_sqrt.is_normal() { let reciprocal_square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(reciprocal_square, x), Less => { assert!(reciprocal_square > x); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < x); } } Greater => { assert!(reciprocal_square < x); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > x); } } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.reciprocal_sqrt_round_ref(rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(reciprocal_sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.reciprocal_sqrt_round_ref(Exact)); } } #[test] fn reciprocal_sqrt_round_properties() { float_rounding_mode_pair_gen_var_30().test_properties(|(x, rm)| { reciprocal_sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_31().test_properties(|(x, rm)| { reciprocal_sqrt_round_properties_helper(x, rm, true); }); rounding_mode_gen().test_properties(|rm| { let (reciprocal_sqrt, o) = Float::NAN.reciprocal_sqrt_round(rm); assert!(reciprocal_sqrt.is_nan()); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::ZERO.reciprocal_sqrt_round(rm); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::INFINITY) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::NEGATIVE_ZERO.reciprocal_sqrt_round(rm); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::INFINITY) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::INFINITY.reciprocal_sqrt_round(rm); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::ZERO) ); assert_eq!(o, Equal); let (reciprocal_sqrt, o) = Float::NEGATIVE_INFINITY.reciprocal_sqrt_round(rm); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::NAN) ); assert_eq!(o, Equal); assert_eq!(Float::ONE.reciprocal_sqrt_round(rm), (Float::ONE, Equal)); let (reciprocal_sqrt, o) = Float::NEGATIVE_ONE.reciprocal_sqrt_round(rm); assert_eq!( ComparableFloat(reciprocal_sqrt), ComparableFloat(Float::NAN) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn reciprocal_sqrt_properties_helper(x: Float, extreme: bool) { let reciprocal_sqrt = x.clone().reciprocal_sqrt(); assert!(reciprocal_sqrt.is_valid()); let reciprocal_sqrt_alt = (&x).reciprocal_sqrt(); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); let mut x_alt = x.clone(); x_alt.reciprocal_sqrt_assign(); assert!(x_alt.is_valid()); assert_eq!( ComparableFloatRef(&x_alt), ComparableFloatRef(&reciprocal_sqrt) ); let reciprocal_sqrt_alt = x .reciprocal_sqrt_prec_round_ref(x.significant_bits(), Nearest) .0; assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); let reciprocal_sqrt_alt = x.reciprocal_sqrt_prec_ref(x.significant_bits()).0; assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); let reciprocal_sqrt_alt = x.reciprocal_sqrt_round_ref(Nearest).0; assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); if x >= 0u32 && !x.is_negative_zero() { assert!(reciprocal_sqrt.is_sign_positive()); } if x.is_normal() && reciprocal_sqrt.is_normal() { assert_eq!(reciprocal_sqrt.get_prec(), Some(x.get_prec().unwrap())); } if !extreme && x.is_normal() && reciprocal_sqrt.is_normal() { assert_eq!(reciprocal_sqrt.get_prec(), Some(x.get_prec().unwrap())); let reciprocal_square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); if reciprocal_square < x { let mut next = reciprocal_sqrt.clone(); next.decrement(); assert!(Rational::exact_from(&next).square().reciprocal() > x); } else if reciprocal_square > x { let mut previous = reciprocal_sqrt.clone(); previous.increment(); assert!(Rational::exact_from(&previous).square().reciprocal() < x); } } let rug_reciprocal_sqrt = rug_reciprocal_sqrt(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_reciprocal_sqrt)), ComparableFloatRef(&reciprocal_sqrt), ); } #[test] fn reciprocal_sqrt_properties() { float_gen().test_properties(|x| { reciprocal_sqrt_properties_helper(x, false); }); float_gen_var_12().test_properties(|x| { reciprocal_sqrt_properties_helper(x, true); }); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_reciprocal_sqrt_properties_helper() where Float: From + PartialOrd, Rational: ExactFrom + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { let reciprocal_sqrt = primitive_float_reciprocal_sqrt(x); if x.is_normal() && reciprocal_sqrt.is_normal() { let reciprocal_square = Rational::exact_from(reciprocal_sqrt).square().reciprocal(); if reciprocal_square < x { let next = reciprocal_sqrt.next_lower(); assert!(Rational::exact_from(next).square().reciprocal() > x); } else if reciprocal_square > x { let previous = reciprocal_sqrt.next_higher(); assert!(Rational::exact_from(previous).square().reciprocal() < x); } } }); } #[test] fn primitive_float_reciprocal_sqrt_properties() { apply_fn_to_primitive_floats!(primitive_float_reciprocal_sqrt_properties_helper); } #[test] fn reciprocal_sqrt_rational_prec_properties() { rational_unsigned_pair_gen_var_7().test_properties(|(x, prec)| { let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec(x.clone(), prec); assert!(reciprocal_sqrt.is_valid()); let (reciprocal_sqrt_alt, o_alt) = Float::reciprocal_sqrt_rational_prec_ref(&x, prec); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); let (reciprocal_sqrt_alt, o_alt) = Float::reciprocal_sqrt_rational_prec_round_ref(&x, prec, Nearest); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); let (reciprocal_sqrt_alt, o_alt) = reciprocal_sqrt_rational_prec_round_generic(&x, prec, Nearest); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); let (reciprocal_sqrt_alt, o_alt) = reciprocal_sqrt_rational_prec_round_simple(&x, prec, Nearest); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); if !reciprocal_sqrt.is_nan() { assert_eq!( reciprocal_sqrt.get_prec(), if x == 0u32 { None } else { Some(prec) } ); } if x >= 0u32 { assert!(reciprocal_sqrt.is_sign_positive()); } if reciprocal_sqrt.is_normal() { if x > 1u32 && o < Greater { assert!(reciprocal_sqrt < x); } else if x < 1u32 && o > Less { assert!(reciprocal_sqrt > x); } let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, x), Less => { assert!(square > x); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0u32 { assert!(Rational::exact_from(&next).square().reciprocal() < x); } } Greater => { assert!(square < x); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0 { assert!(Rational::exact_from(&previous).square().reciprocal() > x); } } } } }); } #[test] fn reciprocal_sqrt_rational_prec_round_properties() { rational_unsigned_rounding_mode_triple_gen_var_4().test_properties(|(x, prec, rm)| { let (reciprocal_sqrt, o) = Float::reciprocal_sqrt_rational_prec_round(x.clone(), prec, rm); assert!(reciprocal_sqrt.is_valid()); let (reciprocal_sqrt_alt, o_alt) = Float::reciprocal_sqrt_rational_prec_round_ref(&x, prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); if !reciprocal_sqrt.is_nan() { match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } let (reciprocal_sqrt_alt, o_alt) = reciprocal_sqrt_rational_prec_round_generic(&x, prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); let (reciprocal_sqrt_alt, o_alt) = reciprocal_sqrt_rational_prec_round_simple(&x, prec, rm); assert!(reciprocal_sqrt_alt.is_valid()); assert_eq!( ComparableFloatRef(&reciprocal_sqrt_alt), ComparableFloatRef(&reciprocal_sqrt) ); assert_eq!(o, o_alt); if !reciprocal_sqrt.is_nan() { assert_eq!( reciprocal_sqrt.get_prec(), if x == 0u32 { None } else { Some(prec) } ); } if x >= 0u32 { assert!(reciprocal_sqrt.is_sign_positive()); } if reciprocal_sqrt.is_normal() { if x > 1u32 && o < Greater { assert!(reciprocal_sqrt < x); } else if x < 1u32 && o > Less { assert!(reciprocal_sqrt > x); } } if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(&reciprocal_sqrt).square().reciprocal(); match o { Equal => assert_eq!(square, x), Less => { assert!(square > x); let mut next = reciprocal_sqrt.clone(); next.increment(); if next != 0 { assert!(Rational::exact_from(&next).square().reciprocal() < x); } } Greater => { assert!(square < x); let mut previous = reciprocal_sqrt.clone(); previous.decrement(); if previous != 0u32 { assert!(Rational::exact_from(&previous).square().reciprocal() > x); } } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::reciprocal_sqrt_rational_prec_round_ref(&x, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(reciprocal_sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::reciprocal_sqrt_rational_prec_round_ref( &x, prec, Exact )); } }); // reciprocal_sqrt(3/5) is one of the simplest cases that doesn't reduce to sqrt or // reciprocal_sqrt of a Float const X: Rational = Rational::const_from_unsigneds(3, 5); test_constant( |prec, rm| Float::reciprocal_sqrt_rational_prec_round(X, prec, rm), 10000, ); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_reciprocal_sqrt_rational_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { rational_gen_var_1().test_properties(|x| { let reciprocal_sqrt = primitive_float_reciprocal_sqrt_rational::(&x); if reciprocal_sqrt.is_normal() { let square = Rational::exact_from(reciprocal_sqrt).square().reciprocal(); match square.cmp(&x) { Less => { assert!( Rational::exact_from(reciprocal_sqrt.next_higher()) .square() .reciprocal() < x ); } Greater => { assert!( Rational::exact_from(reciprocal_sqrt.next_lower()) .square() .reciprocal() > x ); } _ => {} } } }); rational_pair_gen_var_8().test_properties(|(x, y)| { let reciprocal_sqrt_x = NiceFloat(primitive_float_reciprocal_sqrt_rational::(&x)); let reciprocal_sqrt_y = NiceFloat(primitive_float_reciprocal_sqrt_rational::(&y)); if !reciprocal_sqrt_x.0.is_nan() && !reciprocal_sqrt_y.0.is_nan() { match x.partial_cmp(&y).unwrap() { Equal => assert_eq!(reciprocal_sqrt_x, reciprocal_sqrt_y), Less => assert!(reciprocal_sqrt_x >= reciprocal_sqrt_y), Greater => assert!(reciprocal_sqrt_x <= reciprocal_sqrt_y), } } }); } #[test] fn primitive_float_reciprocal_sqrt_rational_properties() { apply_fn_to_primitive_floats!(primitive_float_reciprocal_sqrt_rational_helper); } ================================================ FILE: malachite-float/tests/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2, ShlRound, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, unsigned_gen, unsigned_gen_var_5, }; use malachite_float::test_util::arithmetic::shl::shl_naive; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{ float_gen, float_signed_pair_gen_var_2, float_signed_pair_gen_var_3, float_unsigned_pair_gen_var_2, float_unsigned_pair_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use malachite_q::Rational; use std::ops::{Shl, ShlAssign, Shr}; fn test_shl_unsigned_helper(f: F) where Float: ShlAssign + Shl, Rational: Shl, for<'a> &'a Float: Shl, { let test = |s, s_hex, v: u64, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); n <<= v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = x.clone() << v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = &x << v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = shl_naive(x.clone(), v); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); f(x, v, n); }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); let test_extreme = |s, s_hex, v: i32, out: &str, out_hex: &str| { let v = u64::exact_from(v); if T::convertible_from(v) { test(s, s_hex, v, out, out_hex); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, "too_big", "0x4.0E+268435455#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, "Infinity", "Infinity", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, "-too_big", "-0x4.0E+268435455#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, "-Infinity", "-Infinity", ); } #[test] fn test_shl_unsigned() { test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|x, v, shifted| { let mut n = rug::Float::exact_from(&x); n <<= v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); let n = rug::Float::exact_from(&x) << v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); }); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); } fn test_shl_signed_helper(f: F) where Float: ShlAssign + Shl, Rational: Shl, for<'a> &'a Float: Shl, { let test = |s, s_hex, v: i64, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); n <<= v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = x.clone() << v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = &x << v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = shl_naive(x.clone(), v); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); f(x, v, n); }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("NaN", "NaN", -10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7"); test("123.0", "0x7b.0#7", -1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", -10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", -100, "9.7e-29", "0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", -1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", -10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", -100, "-9.7e-29", "-0x7.bE-24#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); let test_extreme = |s, s_hex, v: i32, out: &str, out_hex: &str| { let v = i64::from(v); if T::convertible_from(v) { test(s, s_hex, v, out, out_hex); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, "too_big", "0x4.0E+268435455#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, "Infinity", "Infinity", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, "-too_big", "-0x4.0E+268435455#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, "-Infinity", "-Infinity", ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, "too_small", "0x2.0E-268435456#1", ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, "too_small", "0x1.0E-268435456#1", ); test_extreme("1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, "0.0", "0x0.0"); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, "too_small", "0x1.0E-268435456#2", ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, "-too_small", "-0x2.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, "-too_small", "-0x1.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, "-0.0", "-0x0.0", ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, "-too_small", "-0x1.0E-268435456#2", ); } #[test] fn test_shl_signed() { test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|x, v, shifted| { let mut n = rug::Float::exact_from(&x); n <<= v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); let n = rug::Float::exact_from(&x) << v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); }); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); } fn shl_properties_helper_unsigned_helper(n: Float, u: T) where for<'a> &'a Integer: Shl, Float: Shl + ShlRound + ShlAssign + Shr, Rational: Shl, for<'a> &'a Float: Shl, u64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); mut_n <<= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << u; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone() << u; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shl_round(u, Nearest).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shl_prec(u, n.get_prec().unwrap_or(1)).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let shifted_alt = shl_naive(n.clone(), u); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { assert!((&n << u).ge_abs(&n)); } assert_eq!(ComparableFloat(-&n << u), ComparableFloat(-(&n << u))); if shifted.is_normal() { assert_eq!(ComparableFloatRef(&(&n << u >> u)), ComparableFloatRef(&n)); assert_eq!( ComparableFloat(&n << u), ComparableFloat(n * Float::power_of_2(u64::exact_from(u))) ); } } fn shl_properties_helper_unsigned() where for<'a> &'a Integer: Shl, Float: Shl + ShlRound + ShlAssign + Shr, Rational: Shl, for<'a> &'a Float: Shl, u64: TryFrom, i128: TryFrom, { float_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { shl_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_3::().test_properties(|(n, u)| { shl_properties_helper_unsigned_helper(n, u); }); float_gen().test_properties(|n| { assert_eq!(ComparableFloat(&n << T::ZERO), ComparableFloat(n)); }); unsigned_gen::().test_properties(|u| { assert!((Float::NAN << u).is_nan()); assert_eq!(Float::INFINITY << u, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY << u, Float::NEGATIVE_INFINITY); assert_eq!( ComparableFloat(Float::ZERO << u), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat(Float::NEGATIVE_ZERO << u), ComparableFloat(Float::NEGATIVE_ZERO) ); }); unsigned_gen_var_5::().test_properties(|u| { assert!((Float::ONE << u).is_power_of_2()); }); integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { assert_eq!(&n << u, Float::exact_from(n) << u); }); } #[allow(clippy::needless_pass_by_value)] fn shl_properties_helper_signed_helper(n: Float, i: T) where for<'a> &'a Integer: Shl, Float: Shl + ShlRound + ShlAssign + Shr, Rational: Shl, for<'a> &'a Float: Shl + Shl<::Output, Output = Float> + Shr + Shr<::Output, Output = Float>, i64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); mut_n <<= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << i; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone() << i; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shl_round(i, Nearest).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shl_prec(i, n.get_prec().unwrap_or(1)).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let shifted_alt = shl_naive(n.clone(), i); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if i >= T::ZERO { assert_eq!( ComparableFloatRef(&(&n << i.unsigned_abs())), ComparableFloatRef(&shifted) ); } else if i != T::MIN { assert_eq!( ComparableFloatRef(&(&n >> i.unsigned_abs())), ComparableFloatRef(&shifted) ); } assert_eq!(ComparableFloat(-&n << i), ComparableFloat(-(&n << i))); if let Some(neg_i) = i.checked_neg() { assert_eq!(ComparableFloat(&n << neg_i), ComparableFloat(&n >> i)); } if shifted.is_normal() { if shifted.get_exponent() != Some(Float::MIN_EXPONENT) { assert_eq!(ComparableFloatRef(&(&n << i >> i)), ComparableFloatRef(&n)); } assert_eq!( ComparableFloat(shifted), ComparableFloat(n * Float::power_of_2(i64::exact_from(i))) ); } } fn shl_properties_helper_signed() where for<'a> &'a Integer: Shl, Float: Shl + ShlRound + ShlAssign + Shr, Rational: Shl, for<'a> &'a Float: Shl + Shl<::Output, Output = Float> + Shr + Shr<::Output, Output = Float>, i64: TryFrom, i128: TryFrom, { float_signed_pair_gen_var_2::().test_properties(|(n, i)| { shl_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_3::().test_properties(|(n, i)| { shl_properties_helper_signed_helper(n, i); }); float_gen().test_properties(|n| { assert_eq!(ComparableFloat(&n << T::ZERO), ComparableFloat(n)); }); signed_gen::().test_properties(|i| { assert!((Float::NAN << i).is_nan()); assert_eq!(Float::INFINITY << i, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY << i, Float::NEGATIVE_INFINITY); assert_eq!( ComparableFloat(Float::ZERO << i), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat(Float::NEGATIVE_ZERO << i), ComparableFloat(Float::NEGATIVE_ZERO) ); }); signed_gen_var_5::().test_properties(|i| { assert!((Float::ONE << i).is_power_of_2()); }); } #[test] fn shl_properties() { apply_fn_to_unsigneds!(shl_properties_helper_unsigned); apply_fn_to_signeds!(shl_properties_helper_signed); float_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let shifted = &n << u; let mut rug_n = rug::Float::exact_from(&n); rug_n <<= u; assert_eq!( ComparableFloatRef(&Float::from(&rug_n)), ComparableFloatRef(&shifted) ); assert_eq!( ComparableFloat(Float::from(&(rug::Float::exact_from(&n) << u))), ComparableFloat(shifted) ); }); float_signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = &n << i; let mut rug_n = rug::Float::exact_from(&n); rug_n <<= i; assert_eq!( ComparableFloatRef(&Float::from(&rug_n)), ComparableFloatRef(&shifted) ); assert_eq!( ComparableFloat(Float::from(&(rug::Float::exact_from(&n) << i))), ComparableFloat(shifted) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ IsPowerOf2, PowerOf2, ShlRound, ShlRoundAssign, ShrRound, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_rounding_mode_pair_gen_var_5, signed_unsigned_pair_gen_var_19, signed_unsigned_pair_gen_var_20, signed_unsigned_rounding_mode_triple_gen_var_7, signed_unsigned_rounding_mode_triple_gen_var_8, unsigned_pair_gen_var_18, unsigned_rounding_mode_pair_gen, unsigned_rounding_mode_pair_gen_var_5, unsigned_unsigned_rounding_mode_triple_gen_var_7, }; use malachite_float::test_util::arithmetic::shl_round::{ rug_shl_prec_round_signed, rug_shl_prec_round_unsigned, rug_shl_prec_signed, rug_shl_prec_unsigned, rug_shl_round_signed, rug_shl_round_unsigned, shl_prec_naive, shl_prec_round_naive, shl_round_naive, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_rounding_mode_pair_gen, float_signed_rounding_mode_triple_gen_var_1, float_signed_rounding_mode_triple_gen_var_2, float_signed_unsigned_rounding_mode_quadruple_gen_var_1, float_signed_unsigned_rounding_mode_quadruple_gen_var_2, float_signed_unsigned_triple_gen_var_1, float_signed_unsigned_triple_gen_var_2, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_5, float_unsigned_rounding_mode_triple_gen_var_6, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2, float_unsigned_unsigned_triple_gen_var_1, float_unsigned_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_unsigned_rounding_mode_triple_gen_var_5; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; use std::ops::Shl; use std::panic::catch_unwind; fn test_shl_prec_round_unsigned_helper< T: PrimitiveUnsigned, F: Fn(Float, T, u64, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShlRoundAssign + ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { let test_r = |s, s_hex, v: u64, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_prec_round_assign(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_prec_round(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shl_prec_round_ref(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_prec_round_naive(x.clone(), v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, rm, n, out_o); }; let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { test_r(s, s_hex, v, prec, rm, out, out_hex, Equal); } }; test("NaN", "NaN", 0, 1, "NaN", "NaN"); test("NaN", "NaN", 0, 10, "NaN", "NaN"); test("NaN", "NaN", 10, 1, "NaN", "NaN"); test("NaN", "NaN", 10, 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0"); test_r( "123.0", "0x7b.0#7", 0, 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test_r( "123.0", "0x7b.0#7", 0, 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_r( "123.0", "0x7b.0#7", 0, 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 10, Floor, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Down, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal); test_r( "123.0", "0x7b.0#7", 0, 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Exact, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 1, Floor, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", 10, 1, Ceiling, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 1, Down, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", 10, 1, Up, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 1, Nearest, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 10, Floor, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Ceiling, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Down, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Up, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Nearest, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Exact, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Floor, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Ceiling, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Down, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Up, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Nearest, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Floor, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Ceiling, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Down, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Up, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Nearest, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Exact, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); // - overflow in shl_prec_round // - overflow && sign && rm == Floor | Down in shl_prec_round test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); // - overflow && sign && rm == Up | Ceiling | Nearest in shl_prec_round test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Ceiling, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Up, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Nearest, "Infinity", "Infinity", Greater, ); // - overflow && !sign && rm == Up | Floor | Nearest in shl_prec_round test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Floor, "-Infinity", "-Infinity", Less, ); // - overflow && !sign && rm == Ceiling | Down in shl_prec_round test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Up, "-Infinity", "-Infinity", Less, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Nearest, "-Infinity", "-Infinity", Less, ); } #[test] fn test_shl_prec_round_unsigned() { test_shl_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_unsigned_helper::(|x, v, prec, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shl_prec_round_unsigned(&rug::Float::exact_from(&x), v, prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shl_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); } fn test_shl_prec_round_signed_helper< T: PrimitiveSigned, F: Fn(Float, T, u64, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShlRoundAssign + ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { let test_r = |s, s_hex, v: i64, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_prec_round_assign(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_prec_round(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shl_prec_round_ref(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_prec_round_naive(x.clone(), v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, rm, n, out_o); }; let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { test_r(s, s_hex, v, prec, rm, out, out_hex, Equal); } }; test("NaN", "NaN", 0, 1, "NaN", "NaN"); test("NaN", "NaN", 0, 10, "NaN", "NaN"); test("NaN", "NaN", 10, 1, "NaN", "NaN"); test("NaN", "NaN", 10, 10, "NaN", "NaN"); test("NaN", "NaN", -10, 1, "NaN", "NaN"); test("NaN", "NaN", -10, 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0"); test_r( "123.0", "0x7b.0#7", 0, 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test_r( "123.0", "0x7b.0#7", 0, 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_r( "123.0", "0x7b.0#7", 0, 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 10, Floor, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Down, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal); test_r( "123.0", "0x7b.0#7", 0, 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Exact, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 1, Floor, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", 10, 1, Ceiling, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 1, Down, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", 10, 1, Up, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 1, Nearest, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 10, Floor, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Ceiling, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Down, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Up, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Nearest, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Exact, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r("123.0", "0x7b.0#7", -10, 1, Floor, "0.06", "0x0.1#1", Less); test_r( "123.0", "0x7b.0#7", -10, 1, Ceiling, "0.1", "0x0.2#1", Greater, ); test_r("123.0", "0x7b.0#7", -10, 1, Down, "0.06", "0x0.1#1", Less); test_r("123.0", "0x7b.0#7", -10, 1, Up, "0.1", "0x0.2#1", Greater); test_r( "123.0", "0x7b.0#7", -10, 1, Nearest, "0.1", "0x0.2#1", Greater, ); test_r( "123.0", "0x7b.0#7", -10, 10, Floor, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Ceiling, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Down, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Up, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Nearest, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Exact, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Floor, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Ceiling, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Down, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Up, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Nearest, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Floor, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Ceiling, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Down, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Up, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Nearest, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Exact, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Floor, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Ceiling, "-0.06", "-0x0.1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Down, "-0.06", "-0x0.1#1", Greater, ); test_r("-123.0", "-0x7b.0#7", -10, 1, Up, "-0.1", "-0x0.2#1", Less); test_r( "-123.0", "-0x7b.0#7", -10, 1, Nearest, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Floor, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Ceiling, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Down, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Up, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Nearest, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Exact, "-0.1201", "-0x0.1ec0#10", Equal, ); // - overflow in shl_prec_round // - overflow && sign && rm == Floor | Down in shl_prec_round test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); // - overflow && sign && rm == Up | Ceiling | Nearest in shl_prec_round test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Ceiling, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Up, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", 1, 1, Nearest, "Infinity", "Infinity", Greater, ); // - overflow && !sign && rm == Up | Floor | Nearest in shl_prec_round test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Floor, "-Infinity", "-Infinity", Less, ); // - overflow && !sign && rm == Ceiling | Down in shl_prec_round test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Up, "-Infinity", "-Infinity", Less, ); test_r( "-too_big", "-0x4.0E+268435455#1", 1, 1, Nearest, "-Infinity", "-Infinity", Less, ); // - underflow in shl_prec_round // - underflow && sign && rm == Floor | Down | Nearest in shl_prec_round test_r( "too_small", "0x1.0E-268435456#1", -1, 1, Floor, "0.0", "0x0.0", Less, ); // - underflow && sign && rm == Up | Ceiling in shl_prec_round test_r( "too_small", "0x1.0E-268435456#1", -1, 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", -1, 1, Down, "0.0", "0x0.0", Less, ); test_r( "too_small", "0x1.0E-268435456#1", -1, 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", -1, 1, Nearest, "0.0", "0x0.0", Less, ); // - underflow && !sign && rm == Up | Floor in shl_prec_round test_r( "-too_small", "-0x1.0E-268435456#1", -1, 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); // - underflow && !sign && rm == Ceiling | Down | Nearest in shl_prec_round test_r( "-too_small", "-0x1.0E-268435456#1", -1, 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", -1, 1, Down, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", -1, 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", -1, 1, Nearest, "-0.0", "-0x0.0", Greater, ); // - underflow half-up in shl_prec_round // - underflow half-up && sign in shl_prec_round test_r( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", -7, 66, Nearest, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); // - underflow half-up && !sign in shl_prec_round test_r( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", -7, 66, Nearest, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shl_prec_round_signed() { test_shl_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_signed_helper::(|x, v, prec, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shl_prec_round_signed(&rug::Float::exact_from(&x), v, prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shl_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shl_prec_round_signed_helper::(|_, _, _, _, _, _| {}); } #[test] fn shl_prec_round_fail() { assert_panic!(Float::ONE.shl_prec_round(Float::MAX_EXPONENT, 1, Exact)); assert_panic!(Float::ONE.shl_prec_round(Float::MIN_EXPONENT - 2, 1, Exact)); assert_panic!(Float::NEGATIVE_ONE.shl_prec_round(Float::MAX_EXPONENT, 1, Exact)); assert_panic!(Float::NEGATIVE_ONE.shl_prec_round(Float::MIN_EXPONENT - 2, 1, Exact)); } fn test_shl_prec_unsigned_helper(f: F) where Rational: Shl, { let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_prec_assign(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_prec(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shl_prec_ref(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_prec_naive(x.clone(), v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, n, out_o); }; test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal); test("123.0", "0x7b.0#7", 10, 1, "1.0e5", "0x2.0E+4#1", Greater); test( "123.0", "0x7b.0#7", 10, 10, "1.26e5", "0x1.ec0E+4#10", Equal, ); test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less); test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal); test("-123.0", "-0x7b.0#7", 10, 1, "-1.0e5", "-0x2.0E+4#1", Less); test( "-123.0", "-0x7b.0#7", 10, 10, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test( "too_big", "0x4.0E+268435455#1", 1, 1, "Infinity", "Infinity", Greater, ); test( "-too_big", "-0x4.0E+268435455#1", 1, 1, "-Infinity", "-Infinity", Less, ); } #[test] fn test_shl_prec_unsigned() { test_shl_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shl_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shl_prec_unsigned_helper::(|x, v, prec, shifted, o_out| { let (n, o) = rug_shl_prec_unsigned(&rug::Float::exact_from(&x), v, prec); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); }); test_shl_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shl_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shl_prec_unsigned_helper::(|_, _, _, _, _| {}); } fn test_shl_prec_signed_helper(f: F) where Rational: Shl, { let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_prec_assign(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_prec(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shl_prec_ref(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_prec_naive(x.clone(), v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, n, out_o); }; test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal); test("NaN", "NaN", -10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", -10, 10, "NaN", "NaN", Equal); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", -10, 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", -10, 10, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", -10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", -10, 10, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal); test("123.0", "0x7b.0#7", 10, 1, "1.0e5", "0x2.0E+4#1", Greater); test( "123.0", "0x7b.0#7", 10, 10, "1.26e5", "0x1.ec0E+4#10", Equal, ); test("123.0", "0x7b.0#7", -10, 1, "0.1", "0x0.2#1", Greater); test("123.0", "0x7b.0#7", -10, 10, "0.1201", "0x0.1ec0#10", Equal); test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less); test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal); test("-123.0", "-0x7b.0#7", 10, 1, "-1.0e5", "-0x2.0E+4#1", Less); test( "-123.0", "-0x7b.0#7", 10, 10, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test("-123.0", "-0x7b.0#7", -10, 1, "-0.1", "-0x0.2#1", Less); test( "-123.0", "-0x7b.0#7", -10, 10, "-0.1201", "-0x0.1ec0#10", Equal, ); test( "too_big", "0x4.0E+268435455#1", 1, 1, "Infinity", "Infinity", Greater, ); test( "-too_big", "-0x4.0E+268435455#1", 1, 1, "-Infinity", "-Infinity", Less, ); test( "too_small", "0x1.0E-268435456#1", -1, 1, "0.0", "0x0.0", Less, ); test( "-too_small", "-0x1.0E-268435456#1", -1, 1, "-0.0", "-0x0.0", Greater, ); // - underflow half-up in shl_prec_round // - underflow half-up && sign in shl_prec_round test( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", -7, 66, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); // - underflow half-up && !sign in shl_prec_round test( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", -7, 66, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shl_prec_signed() { test_shl_prec_signed_helper::(|_, _, _, _, _| {}); test_shl_prec_signed_helper::(|_, _, _, _, _| {}); test_shl_prec_signed_helper::(|x, v, prec, shifted, o_out| { let (n, o) = rug_shl_prec_signed(&rug::Float::exact_from(&x), v, prec); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); }); test_shl_prec_signed_helper::(|_, _, _, _, _| {}); test_shl_prec_signed_helper::(|_, _, _, _, _| {}); test_shl_prec_signed_helper::(|_, _, _, _, _| {}); } fn test_shl_round_unsigned_helper< T: PrimitiveUnsigned, F: Fn(Float, T, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShlRoundAssign + ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { let test = |s, s_hex, v: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = x.clone().shl_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = (&x).shl_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = shl_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, Equal); f(x, v, rm, n, Equal); } }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); let test_extreme = |s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let v = u64::exact_from(v); if T::convertible_from(v) { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = (&x).shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, rm, n, out_o); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Floor, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Ceiling, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Down, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Up, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Nearest, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Exact, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Ceiling, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Up, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Nearest, "Infinity", "Infinity", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Floor, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Down, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Up, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Nearest, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Exact, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Floor, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Up, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Nearest, "-Infinity", "-Infinity", Less, ); } #[test] fn test_shl_round_unsigned() { test_shl_round_unsigned_helper::(|_, _, _, _, _| {}); test_shl_round_unsigned_helper::(|_, _, _, _, _| {}); test_shl_round_unsigned_helper::(|x, v, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shl_round_unsigned(&rug::Float::exact_from(&x), v, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shl_round_unsigned_helper::(|_, _, _, _, _| {}); test_shl_round_unsigned_helper::(|_, _, _, _, _| {}); test_shl_round_unsigned_helper::(|_, _, _, _, _| {}); } fn test_shl_round_signed_helper< T: PrimitiveSigned, F: Fn(Float, T, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShlRoundAssign + ShlRound, Rational: Shl, for<'a> &'a Float: ShlRound, { let test = |s, s_hex, v: i64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = x.clone().shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = (&x).shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = shl_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, Equal); f(x, v, rm, n, Equal); } }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("NaN", "NaN", -10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", 10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", 100, "1.56e32", "0x7.bE+26#7"); test("123.0", "0x7b.0#7", -1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", -10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", -100, "9.7e-29", "0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", 10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", 100, "-1.56e32", "-0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", -1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", -10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", -100, "-9.7e-29", "-0x7.bE-24#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); let test_extreme = |s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let v = i64::from(v); if T::convertible_from(v) { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shl_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = (&x).shl_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shl_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, rm, n, out_o); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Floor, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Ceiling, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Down, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Up, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Nearest, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, Exact, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Ceiling, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Up, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, Nearest, "Infinity", "Infinity", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Floor, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Down, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Up, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Nearest, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, Exact, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Floor, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Up, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, Nearest, "-Infinity", "-Infinity", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Floor, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Ceiling, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Down, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Up, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Nearest, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 1, Exact, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT - 2, Nearest, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, Ceiling, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, Up, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MIN_EXPONENT - 2, Nearest, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Floor, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Ceiling, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Down, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Up, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 1, Exact, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT - 2, Nearest, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, Floor, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, Up, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MIN_EXPONENT - 2, Nearest, "-too_small", "-0x1.0E-268435456#2", Less, ); } #[test] fn shl_round_fail() { assert_panic!(Float::ONE.shl_round(Float::MAX_EXPONENT, Exact)); assert_panic!(Float::ONE.shl_round(Float::MIN_EXPONENT - 2, Exact)); assert_panic!(Float::NEGATIVE_ONE.shl_round(Float::MAX_EXPONENT, Exact)); assert_panic!(Float::NEGATIVE_ONE.shl_round(Float::MIN_EXPONENT - 2, Exact)); } #[test] fn test_shl_round_signed() { test_shl_round_signed_helper::(|_, _, _, _, _| {}); test_shl_round_signed_helper::(|_, _, _, _, _| {}); test_shl_round_signed_helper::(|x, v, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shl_round_signed(&rug::Float::exact_from(&x), v, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shl_round_signed_helper::(|_, _, _, _, _| {}); test_shl_round_signed_helper::(|_, _, _, _, _| {}); test_shl_round_signed_helper::(|_, _, _, _, _| {}); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_properties_helper_unsigned_helper(n: Float, u: T, prec: u64) where i128: TryFrom, u64: TryFrom, Rational: Shl, { let mut mut_n = n.clone(); let o = mut_n.shl_prec_assign(u, prec); assert!(mut_n.is_valid()); let shifted = mut_n; if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shl_prec_ref(u, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_prec(u, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_prec_naive(n.clone(), u, prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted), ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } let (shifted_2, o_2) = (-&n).shl_prec(u, prec); let (shifted_2_alt, o_2_alt) = n.shl_prec_ref(u, prec); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_prec(Float::power_of_2(u64::exact_from(u)), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_prec_properties_helper_unsigned() where i128: TryFrom, u64: TryFrom, Rational: Shl, { float_unsigned_unsigned_triple_gen_var_1::().test_properties(|(n, u, prec)| { shl_prec_properties_helper_unsigned_helper(n, u, prec); }); float_unsigned_unsigned_triple_gen_var_2::().test_properties(|(n, u, prec)| { shl_prec_properties_helper_unsigned_helper(n, u, prec); }); float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| { let (shifted, o) = n.shl_prec_ref(T::ZERO, prec); let (shifted_alt, o_alt) = Float::from_float_prec(n, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); unsigned_pair_gen_var_18::().test_properties(|(u, prec)| { let (shifted, o) = Float::NAN.shl_prec(u, prec); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shl_prec(u, prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shl_prec(u, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_prec(u, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec(u, prec); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_properties_helper_signed_helper(n: Float, i: T, prec: u64) where i128: TryFrom, i64: TryFrom, Rational: Shl, ::Output: PrimitiveUnsigned, { let mut mut_n = n.clone(); let o = mut_n.shl_prec_assign(i, prec); assert!(mut_n.is_valid()); let shifted = mut_n; if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shl_prec_ref(i, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_prec(i, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_prec_naive(n.clone(), i, prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } if i >= T::ZERO { let (shifted_alt, o_alt) = n.shl_prec_ref(i.unsigned_abs(), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = n.shr_prec_ref(i.unsigned_abs(), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shl_prec(i, prec); let (shifted_2_alt, o_2_alt) = n.shl_prec_ref(i, prec); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_prec(Float::power_of_2(i64::exact_from(i)), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_prec_properties_helper_signed() where i128: TryFrom, i64: TryFrom, Rational: Shl, ::Output: PrimitiveUnsigned, { float_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, prec)| { shl_prec_properties_helper_signed_helper(n, i, prec); }); float_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, prec)| { shl_prec_properties_helper_signed_helper(n, i, prec); }); float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| { let (shifted, o) = n.shl_prec_ref(T::ZERO, prec); let (shifted_alt, o_alt) = Float::from_float_prec(n, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); signed_unsigned_pair_gen_var_19::().test_properties(|(i, prec)| { let (shifted, o) = Float::NAN.shl_prec(i, prec); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shl_prec(i, prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shl_prec(i, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_prec(i, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec(i, prec); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_unsigned_pair_gen_var_20::().test_properties(|(i, prec)| { let (shifted, o) = Float::ONE.shl_prec(i, prec); if shifted.is_normal() { assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_rug_unsigned_helper(n: Float, u: u32, prec: u64) { let (shifted, o) = n.shl_prec_ref(u, prec); let (rug_shifted, rug_o) = rug_shl_prec_unsigned(&rug::Float::exact_from(&n), u, prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_rug_signed_helper(n: Float, i: i32, prec: u64) { let (shifted, o) = n.shl_prec_ref(i, prec); let (rug_shifted, rug_o) = rug_shl_prec_signed(&rug::Float::exact_from(&n), i, prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } #[test] fn shl_prec_properties() { apply_fn_to_unsigneds!(shl_prec_properties_helper_unsigned); apply_fn_to_signeds!(shl_prec_properties_helper_signed); float_unsigned_unsigned_triple_gen_var_1::() .test_properties(|(n, u, prec)| shl_prec_rug_unsigned_helper(n, u, prec)); float_unsigned_unsigned_triple_gen_var_2::() .test_properties(|(n, u, prec)| shl_prec_rug_unsigned_helper(n, u, prec)); float_signed_unsigned_triple_gen_var_1::() .test_properties(|(n, i, prec)| shl_prec_rug_signed_helper(n, i, prec)); float_signed_unsigned_triple_gen_var_2::() .test_properties(|(n, i, prec)| shl_prec_rug_signed_helper(n, i, prec)); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_round_properties_helper_unsigned_helper( n: Float, u: T, prec: u64, rm: RoundingMode, ) where i128: TryFrom, u64: TryFrom, Rational: Shl, { let mut mut_n = n.clone(); let o = mut_n.shl_prec_round_assign(u, prec, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_prec_round(u, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_prec_round_naive(n.clone(), u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted), ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } let (shifted_2, o_2) = (-&n).shl_prec_round(u, prec, rm); let (shifted_2_alt, o_2_alt) = n.shl_prec_round_ref(u, prec, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_prec_round(Float::power_of_2(u64::exact_from(u)), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_prec_round_properties_helper_unsigned() where i128: TryFrom, u64: TryFrom, Rational: Shl, { float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::().test_properties( |(n, u, prec, rm)| { shl_prec_round_properties_helper_unsigned_helper(n, u, prec, rm); }, ); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::().test_properties( |(n, u, prec, rm)| { shl_prec_round_properties_helper_unsigned_helper(n, u, prec, rm); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| { let (shifted, o) = n.shl_prec_round_ref(T::ZERO, prec, rm); let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); unsigned_unsigned_rounding_mode_triple_gen_var_7::().test_properties(|(u, prec, rm)| { let (shifted, o) = Float::NAN.shl_prec_round(u, prec, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.shl_prec_round(u, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.shl_prec_round(u, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_prec_round(u, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec_round(u, prec, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_round_properties_helper_signed_helper( n: Float, i: T, prec: u64, rm: RoundingMode, ) where i128: TryFrom, i64: TryFrom, Rational: Shl, ::Output: PrimitiveUnsigned, { let mut mut_n = n.clone(); let o = mut_n.shl_prec_round_assign(i, prec, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_prec_round(i, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_prec_round_naive(n.clone(), i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } if i >= T::ZERO { let (shifted_alt, o_alt) = n.shl_prec_round_ref(i.unsigned_abs(), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = n.shr_prec_round_ref(i.unsigned_abs(), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shl_prec_round(i, prec, rm); let (shifted_2_alt, o_2_alt) = n.shl_prec_round_ref(i, prec, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_prec_round(Float::power_of_2(i64::exact_from(i)), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_prec_round_properties_helper_signed() where i128: TryFrom, i64: TryFrom, Rational: Shl, ::Output: PrimitiveUnsigned, { float_signed_unsigned_rounding_mode_quadruple_gen_var_1::().test_properties( |(n, i, prec, rm)| { shl_prec_round_properties_helper_signed_helper(n, i, prec, rm); }, ); float_signed_unsigned_rounding_mode_quadruple_gen_var_2::().test_properties( |(n, i, prec, rm)| { shl_prec_round_properties_helper_signed_helper(n, i, prec, rm); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| { let (shifted, o) = n.shl_prec_round_ref(T::ZERO, prec, rm); let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); signed_unsigned_rounding_mode_triple_gen_var_7::().test_properties(|(i, prec, rm)| { let (shifted, o) = Float::NAN.shl_prec_round(i, prec, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.shl_prec_round(i, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.shl_prec_round(i, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_prec_round(i, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_prec_round(i, prec, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_unsigned_rounding_mode_triple_gen_var_8::().test_properties(|(i, prec, rm)| { let (shifted, o) = Float::ONE.shl_prec_round(i, prec, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shl_prec_round_rug_unsigned_helper(n: Float, u: u32, prec: u64, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = n.shl_prec_round_ref(u, prec, rm); let (rug_shifted, rug_o) = rug_shl_prec_round_unsigned(&rug::Float::exact_from(&n), u, prec, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[allow(clippy::needless_pass_by_value)] fn shl_prec_round_rug_signed_helper(n: Float, i: i32, prec: u64, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = n.shl_prec_round_ref(i, prec, rm); let (rug_shifted, rug_o) = rug_shl_prec_round_signed(&rug::Float::exact_from(&n), i, prec, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[test] fn shl_prec_round_properties() { apply_fn_to_unsigneds!(shl_prec_round_properties_helper_unsigned); apply_fn_to_signeds!(shl_prec_round_properties_helper_signed); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_1::() .test_properties(|(n, u, prec, rm)| shl_prec_round_rug_unsigned_helper(n, u, prec, rm)); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_2::() .test_properties(|(n, u, prec, rm)| shl_prec_round_rug_unsigned_helper(n, u, prec, rm)); float_signed_unsigned_rounding_mode_quadruple_gen_var_1::() .test_properties(|(n, i, prec, rm)| shl_prec_round_rug_signed_helper(n, i, prec, rm)); float_signed_unsigned_rounding_mode_quadruple_gen_var_2::() .test_properties(|(n, i, prec, rm)| shl_prec_round_rug_signed_helper(n, i, prec, rm)); } #[allow(clippy::needless_pass_by_value)] fn shl_round_properties_helper_unsigned_helper( n: Float, u: T, rm: RoundingMode, ) where for<'a> &'a Integer: Shl, Float: ShlRound + ShlRoundAssign + ShrRound, Rational: Shl, for<'a> &'a Float: ShlRound, u64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); let o = mut_n.shl_round_assign(u, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = (&n).shl_round(u, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = (&n).shl_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.shl_prec_round_ref(u, n.get_prec().unwrap_or(1), rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_round_naive(n.clone(), u, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { assert!((&n).shl_round(u, rm).0.ge_abs(&n)); } let (shifted_2, o_2) = (-&n).shl_round(u, rm); let (shifted_2_alt, o_2_alt) = (&n).shl_round(u, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_round(Float::power_of_2(u64::exact_from(u)), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_round_properties_helper_unsigned() where for<'a> &'a Integer: Shl, Float: ShlRound + ShrRound + ShlRoundAssign, Rational: Shl, for<'a> &'a Float: ShlRound, u64: TryFrom, i128: TryFrom, { float_unsigned_rounding_mode_triple_gen_var_5::().test_properties(|(n, u, rm)| { shl_round_properties_helper_unsigned_helper(n, u, rm); }); float_unsigned_rounding_mode_triple_gen_var_6::().test_properties(|(n, u, rm)| { shl_round_properties_helper_unsigned_helper(n, u, rm); }); float_rounding_mode_pair_gen().test_properties(|(n, rm)| { let (shifted, o) = (&n).shl_round(T::ZERO, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(n)); assert_eq!(o, Equal); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { let (shifted, o) = Float::NAN.shl_round(u, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shl_round(u, rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shl_round(u, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_round(u, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_round(u, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); unsigned_rounding_mode_pair_gen_var_5::().test_properties(|(u, rm)| { let (shifted, o) = Float::ONE.shl_round(u, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); integer_unsigned_rounding_mode_triple_gen_var_5::().test_properties(|(n, u, rm)| { let (shifted, o) = Float::exact_from(&n).shl_round(u, rm); assert_eq!(&n << u, shifted); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shl_round_properties_helper_signed_helper(n: Float, i: T, rm: RoundingMode) where for<'a> &'a Integer: Shl, Float: ShlRound + ShlRoundAssign + ShrRound, Rational: Shl, for<'a> &'a Float: ShlRound + ShlRound<::Output, Output = Float> + ShrRound<::Output, Output = Float> + ShrRound, i64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); let o = mut_n.shl_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = (&n).shl_round(i, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = (&n).shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.shl_prec_round_ref(i, n.get_prec().unwrap_or(1), rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shl_round_naive(n.clone(), i, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { if i >= T::ZERO { assert!((&n).shl_round(i, rm).0.ge_abs(&n)); } else { assert!((&n).shl_round(i, rm).0.le_abs(&n)); } } if i >= T::ZERO { let (shifted_alt, o_alt) = (&n).shl_round(i.unsigned_abs(), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = (&n).shr_round(i.unsigned_abs(), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shl_round(i, rm); let (shifted_2_alt, o_2_alt) = (&n).shl_round(i, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.mul_round(Float::power_of_2(i64::exact_from(i)), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shl_round_properties_helper_signed() where for<'a> &'a Integer: Shl, Float: ShlRound + ShlRoundAssign + ShrRound, Rational: Shl, for<'a> &'a Float: ShlRound + ShlRound<::Output, Output = Float> + ShrRound<::Output, Output = Float> + ShrRound, i64: TryFrom, i128: TryFrom, { float_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { shl_round_properties_helper_signed_helper(n, i, rm); }); float_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { shl_round_properties_helper_signed_helper(n, i, rm); }); float_rounding_mode_pair_gen().test_properties(|(n, rm)| { let (shifted, o) = (&n).shl_round(T::ZERO, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(n)); assert_eq!(o, Equal); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { let (shifted, o) = Float::NAN.shl_round(i, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shl_round(i, rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shl_round(i, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shl_round(i, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shl_round(i, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_rounding_mode_pair_gen_var_5::().test_properties(|(i, rm)| { let (shifted, o) = Float::ONE.shl_round(i, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shl_round_rug_unsigned_helper(n: Float, u: u32, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = (&n).shl_round(u, rm); let (rug_shifted, rug_o) = rug_shl_round_unsigned(&rug::Float::exact_from(&n), u, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[allow(clippy::needless_pass_by_value)] fn shl_round_rug_signed_helper(n: Float, i: i32, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = (&n).shl_round(i, rm); let (rug_shifted, rug_o) = rug_shl_round_signed(&rug::Float::exact_from(&n), i, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[test] fn shl_round_properties() { apply_fn_to_unsigneds!(shl_round_properties_helper_unsigned); apply_fn_to_signeds!(shl_round_properties_helper_signed); float_unsigned_rounding_mode_triple_gen_var_5::() .test_properties(|(n, u, rm)| shl_round_rug_unsigned_helper(n, u, rm)); float_unsigned_rounding_mode_triple_gen_var_6::() .test_properties(|(n, u, rm)| shl_round_rug_unsigned_helper(n, u, rm)); float_signed_rounding_mode_triple_gen_var_1::() .test_properties(|(n, i, rm)| shl_round_rug_signed_helper(n, i, rm)); float_signed_rounding_mode_triple_gen_var_2::() .test_properties(|(n, i, rm)| shl_round_rug_signed_helper(n, i, rm)); } ================================================ FILE: malachite-float/tests/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2, ShrRound, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, unsigned_gen, unsigned_gen_var_5, }; use malachite_float::test_util::arithmetic::shr::shr_naive; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{ float_gen, float_signed_pair_gen_var_2, float_signed_pair_gen_var_3, float_unsigned_pair_gen_var_2, float_unsigned_pair_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_q::Rational; use std::ops::{Shl, Shr, ShrAssign}; fn test_shr_unsigned_helper(f: F) where Float: ShrAssign + Shr, Rational: Shr, for<'a> &'a Float: Shr, { let test = |s, s_hex, v: u64, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); n >>= v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = x.clone() >> v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = &x >> v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = shr_naive(x.clone(), v); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); f(x, v, n); }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", 10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", 100, "9.7e-29", "0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", 10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", 100, "-9.7e-29", "-0x7.bE-24#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); let test_extreme = |s, s_hex, v: i32, out: &str, out_hex: &str| { let v = u64::exact_from(v); if T::convertible_from(v) { test(s, s_hex, v, out, out_hex); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, "too_small", "0x4.0E-268435456#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, "too_small", "0x2.0E-268435456#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, "too_small", "0x1.0E-268435456#1", ); test_extreme("1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, "0.0", "0x0.0"); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, "too_small", "0x1.0E-268435456#2", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, "-too_small", "-0x4.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, "-too_small", "-0x2.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, "-too_small", "-0x1.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, "-0.0", "-0x0.0", ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, "-too_small", "-0x1.0E-268435456#2", ); } #[test] fn test_shr_unsigned() { test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|x, v, shifted| { let mut n = rug::Float::exact_from(&x); n >>= v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); let n = rug::Float::exact_from(&x) >> v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); }); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); } fn test_shr_signed_helper(f: F) where Float: ShrAssign + Shr, Rational: Shr, for<'a> &'a Float: Shr, { let test = |s, s_hex, v: i64, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); n >>= v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = x.clone() >> v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = &x >> v; assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); let n = shr_naive(x.clone(), v); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); f(x, v, n); }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("NaN", "NaN", -10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", 10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", 100, "9.7e-29", "0x7.bE-24#7"); test("123.0", "0x7b.0#7", -1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", -10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", -100, "1.56e32", "0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", 10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", 100, "-9.7e-29", "-0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", -1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", -10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", -100, "-1.56e32", "-0x7.bE+26#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); let test_extreme = |s, s_hex, v: i32, out: &str, out_hex: &str| { let v = i64::exact_from(v); if T::convertible_from(v) { test(s, s_hex, v, out, out_hex); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT - 1, "too_small", "0x4.0E-268435456#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT, "too_small", "0x2.0E-268435456#1", ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, "too_small", "0x1.0E-268435456#1", ); test_extreme("1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, "0.0", "0x0.0"); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, "too_small", "0x1.0E-268435456#2", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT - 1, "-too_small", "-0x4.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT, "-too_small", "-0x2.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, "-too_small", "-0x1.0E-268435456#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, "-0.0", "-0x0.0", ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, "Infinity", "Infinity", ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, "too_big", "0x4.0E+268435455#1", ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, "-Infinity", "-Infinity", ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, "-too_big", "-0x4.0E+268435455#1", ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, "-too_small", "-0x1.0E-268435456#2", ); } #[test] fn test_shr_signed() { test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|x, v, shifted| { let mut n = rug::Float::exact_from(&x); n >>= v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); let n = rug::Float::exact_from(&x) >> v; assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); }); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); } #[allow(clippy::needless_pass_by_value)] fn shr_properties_helper_unsigned_helper(n: Float, u: T) where for<'a> &'a Integer: Shr, Float: Shl + ShrRound + Shr + ShrAssign, Rational: Shr, for<'a> &'a Float: Shr, i64: TryFrom, u64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); mut_n >>= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> u; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone() >> u; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shr_round(u, Nearest).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shr_prec(u, n.get_prec().unwrap_or(1)).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_sub(i128::exact_from(u)) .lt_abs(&1_000_000) { let shifted_alt = shr_naive(n.clone(), u); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { assert!((&n >> u).le_abs(&n)); } assert_eq!(ComparableFloat(-&n >> u), ComparableFloat(-(&n >> u))); if shifted.is_normal() { if shifted.get_exponent() != Some(Float::MIN_EXPONENT) { assert_eq!(ComparableFloatRef(&(&n >> u << u)), ComparableFloatRef(&n)); } assert_eq!( ComparableFloatRef(&shifted), ComparableFloatRef( &(&n * Float::power_of_2(i64::exact_from(u).checked_neg().unwrap())) ) ); assert_eq!( ComparableFloat(shifted), ComparableFloat(n / Float::power_of_2(u64::exact_from(u))) ); } } fn shr_properties_helper_unsigned() where for<'a> &'a Integer: Shr, Float: Shl + ShrRound + Shr + ShrAssign, Rational: Shr, for<'a> &'a Float: Shr, i64: TryFrom, u64: TryFrom, i128: TryFrom, { float_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { shr_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_3::().test_properties(|(n, u)| { shr_properties_helper_unsigned_helper(n, u); }); float_gen().test_properties(|n| { assert_eq!(ComparableFloat(&n >> T::ZERO), ComparableFloat(n)); }); unsigned_gen::().test_properties(|u| { assert!((Float::NAN >> u).is_nan()); assert_eq!(Float::INFINITY >> u, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY >> u, Float::NEGATIVE_INFINITY); assert_eq!( ComparableFloat(Float::ZERO >> u), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat(Float::NEGATIVE_ZERO >> u), ComparableFloat(Float::NEGATIVE_ZERO) ); }); unsigned_gen_var_5::().test_properties(|u| { assert!((Float::ONE >> u).is_power_of_2()); }); } #[allow(clippy::needless_pass_by_value)] fn shr_properties_helper_signed_helper(n: Float, i: T) where for<'a> &'a Integer: Shr, Float: Shl + ShrRound + ShrAssign + Shr, Rational: Shr, for<'a> &'a Float: Shl + Shr + Shr<::Output, Output = Float> + Shl<::Output, Output = Float>, i64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); mut_n >>= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> i; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone() >> i; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shr_round(i, Nearest).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); let shifted_alt = n.clone().shr_prec(i, n.get_prec().unwrap_or(1)).0; assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_sub(i128::exact_from(i)) .lt_abs(&1_000_000) { let shifted_alt = shr_naive(n.clone(), i); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if i >= T::ZERO { assert_eq!( ComparableFloatRef(&(&n >> i.unsigned_abs())), ComparableFloatRef(&shifted) ); } else if i != T::MIN { assert_eq!( ComparableFloatRef(&(&n << i.unsigned_abs())), ComparableFloatRef(&shifted) ); } assert_eq!(ComparableFloat(-&n >> i), ComparableFloat(-(&n >> i))); if let Some(neg_i) = i.checked_neg() { assert_eq!(ComparableFloat(&n >> neg_i), ComparableFloat(&n << i)); } if shifted.is_normal() { if shifted.get_exponent() != Some(Float::MIN_EXPONENT) { assert_eq!(ComparableFloatRef(&(&n >> i << i)), ComparableFloatRef(&n)); } assert_eq!( ComparableFloat(&n >> i), ComparableFloat(&n * Float::power_of_2(i64::exact_from(i).checked_neg().unwrap())) ); assert_eq!( ComparableFloat(&n >> i), ComparableFloat(n / Float::power_of_2(i64::exact_from(i))) ); } } fn shr_properties_helper_signed() where for<'a> &'a Integer: Shr, Float: Shl + ShrRound + ShrAssign + Shr, Rational: Shr, for<'a> &'a Float: Shl + Shr + Shr<::Output, Output = Float> + Shl<::Output, Output = Float>, i64: TryFrom, i128: TryFrom, { float_signed_pair_gen_var_2::().test_properties(|(n, i)| { shr_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_3::().test_properties(|(n, i)| { shr_properties_helper_signed_helper(n, i); }); float_gen().test_properties(|n| { assert_eq!(ComparableFloat(&n >> T::ZERO), ComparableFloat(n)); }); signed_gen::().test_properties(|i| { assert!((Float::NAN >> i).is_nan()); assert_eq!(Float::INFINITY >> i, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY >> i, Float::NEGATIVE_INFINITY); assert_eq!( ComparableFloat(Float::ZERO >> i), ComparableFloat(Float::ZERO) ); assert_eq!( ComparableFloat(Float::NEGATIVE_ZERO >> i), ComparableFloat(Float::NEGATIVE_ZERO) ); }); signed_gen_var_5::().test_properties(|i| { assert!((Float::ONE >> i).is_power_of_2()); }); } #[test] fn shr_properties() { apply_fn_to_unsigneds!(shr_properties_helper_unsigned); apply_fn_to_signeds!(shr_properties_helper_signed); float_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let shifted = &n >> u; let mut rug_n = rug::Float::exact_from(&n); rug_n >>= u; assert_eq!( ComparableFloatRef(&Float::from(&rug_n)), ComparableFloatRef(&shifted) ); assert_eq!( ComparableFloat(Float::from(&(rug::Float::exact_from(&n) >> u))), ComparableFloat(shifted) ); }); float_signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = &n >> i; let mut rug_n = rug::Float::exact_from(&n); rug_n >>= i; assert_eq!( ComparableFloatRef(&Float::from(&rug_n)), ComparableFloatRef(&shifted) ); assert_eq!( ComparableFloat(Float::from(&(rug::Float::exact_from(&n) >> i))), ComparableFloat(shifted) ); }); } ================================================ FILE: malachite-float/tests/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ IsPowerOf2, PowerOf2, ShlRound, ShrRound, ShrRoundAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_rounding_mode_pair_gen_var_5, signed_unsigned_pair_gen_var_19, signed_unsigned_pair_gen_var_20, signed_unsigned_rounding_mode_triple_gen_var_7, signed_unsigned_rounding_mode_triple_gen_var_8, unsigned_pair_gen_var_18, unsigned_rounding_mode_pair_gen, unsigned_rounding_mode_pair_gen_var_5, unsigned_unsigned_rounding_mode_triple_gen_var_7, }; use malachite_float::test_util::arithmetic::shr_round::{ rug_shr_prec_round_signed, rug_shr_prec_round_unsigned, rug_shr_prec_signed, rug_shr_prec_unsigned, rug_shr_round_signed, rug_shr_round_unsigned, shr_prec_naive, shr_prec_round_naive, shr_round_naive, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_rounding_mode_pair_gen, float_signed_rounding_mode_triple_gen_var_4, float_signed_rounding_mode_triple_gen_var_5, float_signed_unsigned_rounding_mode_quadruple_gen_var_3, float_signed_unsigned_rounding_mode_quadruple_gen_var_4, float_signed_unsigned_triple_gen_var_1, float_signed_unsigned_triple_gen_var_2, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_8, float_unsigned_rounding_mode_triple_gen_var_9, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3, float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4, float_unsigned_unsigned_triple_gen_var_1, float_unsigned_unsigned_triple_gen_var_2, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; use std::ops::Shr; use std::panic::catch_unwind; fn test_shr_prec_round_unsigned_helper< T: PrimitiveUnsigned, F: Fn(Float, T, u64, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShrRoundAssign + ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { let test_r = |s, s_hex, v: u64, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_prec_round_assign(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_prec_round(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shr_prec_round_ref(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_prec_round_naive(x.clone(), v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, rm, n, out_o); }; let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { test_r(s, s_hex, v, prec, rm, out, out_hex, Equal); } }; test("NaN", "NaN", 0, 1, "NaN", "NaN"); test("NaN", "NaN", 0, 10, "NaN", "NaN"); test("NaN", "NaN", 10, 1, "NaN", "NaN"); test("NaN", "NaN", 10, 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0"); test_r( "123.0", "0x7b.0#7", 0, 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test_r( "123.0", "0x7b.0#7", 0, 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_r( "123.0", "0x7b.0#7", 0, 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 10, Floor, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Down, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal); test_r( "123.0", "0x7b.0#7", 0, 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Exact, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 10, 1, Floor, "0.06", "0x0.1#1", Less); test_r( "123.0", "0x7b.0#7", 10, 1, Ceiling, "0.1", "0x0.2#1", Greater, ); test_r("123.0", "0x7b.0#7", 10, 1, Down, "0.06", "0x0.1#1", Less); test_r("123.0", "0x7b.0#7", 10, 1, Up, "0.1", "0x0.2#1", Greater); test_r( "123.0", "0x7b.0#7", 10, 1, Nearest, "0.1", "0x0.2#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 10, Floor, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Ceiling, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Down, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Up, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Nearest, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Exact, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Floor, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Ceiling, "-0.06", "-0x0.1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Down, "-0.06", "-0x0.1#1", Greater, ); test_r("-123.0", "-0x7b.0#7", 10, 1, Up, "-0.1", "-0x0.2#1", Less); test_r( "-123.0", "-0x7b.0#7", 10, 1, Nearest, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Floor, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Ceiling, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Down, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Up, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Nearest, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Exact, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Floor, "0.0", "0x0.0", Less, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Down, "0.0", "0x0.0", Less, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Nearest, "0.0", "0x0.0", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Down, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Nearest, "-0.0", "-0x0.0", Greater, ); test_r( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, Nearest, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); test_r( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, Nearest, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shr_prec_round_unsigned() { test_shr_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_unsigned_helper::(|x, v, prec, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shr_prec_round_unsigned(&rug::Float::exact_from(&x), v, prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shr_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_unsigned_helper::(|_, _, _, _, _, _| {}); } fn test_shr_prec_round_signed_helper< T: PrimitiveSigned, F: Fn(Float, T, u64, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShrRoundAssign + ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { let test_r = |s, s_hex, v: i64, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_prec_round_assign(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_prec_round(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shr_prec_round_ref(v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_prec_round_naive(x.clone(), v, prec, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, rm, n, out_o); }; let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { test_r(s, s_hex, v, prec, rm, out, out_hex, Equal); } }; test("NaN", "NaN", 0, 1, "NaN", "NaN"); test("NaN", "NaN", 0, 10, "NaN", "NaN"); test("NaN", "NaN", 10, 1, "NaN", "NaN"); test("NaN", "NaN", 10, 10, "NaN", "NaN"); test("NaN", "NaN", -10, 1, "NaN", "NaN"); test("NaN", "NaN", -10, 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, 1, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, 1, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0"); test_r( "123.0", "0x7b.0#7", 0, 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test_r( "123.0", "0x7b.0#7", 0, 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test_r("123.0", "0x7b.0#7", 0, 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_r( "123.0", "0x7b.0#7", 0, 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test_r( "123.0", "0x7b.0#7", 0, 10, Floor, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Ceiling, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Down, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 0, 10, Up, "123.0", "0x7b.0#10", Equal); test_r( "123.0", "0x7b.0#7", 0, 10, Nearest, "123.0", "0x7b.0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 0, 10, Exact, "123.0", "0x7b.0#10", Equal, ); test_r("123.0", "0x7b.0#7", 10, 1, Floor, "0.06", "0x0.1#1", Less); test_r( "123.0", "0x7b.0#7", 10, 1, Ceiling, "0.1", "0x0.2#1", Greater, ); test_r("123.0", "0x7b.0#7", 10, 1, Down, "0.06", "0x0.1#1", Less); test_r("123.0", "0x7b.0#7", 10, 1, Up, "0.1", "0x0.2#1", Greater); test_r( "123.0", "0x7b.0#7", 10, 1, Nearest, "0.1", "0x0.2#1", Greater, ); test_r( "123.0", "0x7b.0#7", 10, 10, Floor, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Ceiling, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Down, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Up, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Nearest, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", 10, 10, Exact, "0.1201", "0x0.1ec0#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 1, Floor, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", -10, 1, Ceiling, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", -10, 1, Down, "7.0e4", "0x1.0E+4#1", Less, ); test_r( "123.0", "0x7b.0#7", -10, 1, Up, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", -10, 1, Nearest, "1.0e5", "0x2.0E+4#1", Greater, ); test_r( "123.0", "0x7b.0#7", -10, 10, Floor, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Ceiling, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Down, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Up, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Nearest, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "123.0", "0x7b.0#7", -10, 10, Exact, "1.26e5", "0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Up, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Floor, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Ceiling, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Down, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Up, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Nearest, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 0, 10, Exact, "-123.0", "-0x7b.0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Floor, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Ceiling, "-0.06", "-0x0.1#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", 10, 1, Down, "-0.06", "-0x0.1#1", Greater, ); test_r("-123.0", "-0x7b.0#7", 10, 1, Up, "-0.1", "-0x0.2#1", Less); test_r( "-123.0", "-0x7b.0#7", 10, 1, Nearest, "-0.1", "-0x0.2#1", Less, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Floor, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Ceiling, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Down, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Up, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Nearest, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", 10, 10, Exact, "-0.1201", "-0x0.1ec0#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Floor, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Ceiling, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Down, "-7.0e4", "-0x1.0E+4#1", Greater, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Up, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", -10, 1, Nearest, "-1.0e5", "-0x2.0E+4#1", Less, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Floor, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Ceiling, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Down, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Up, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Nearest, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "-123.0", "-0x7b.0#7", -10, 10, Exact, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test_r( "too_big", "0x4.0E+268435455#1", -1, 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_r( "too_big", "0x4.0E+268435455#1", -1, 1, Ceiling, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", -1, 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_r( "too_big", "0x4.0E+268435455#1", -1, 1, Up, "Infinity", "Infinity", Greater, ); test_r( "too_big", "0x4.0E+268435455#1", -1, 1, Nearest, "Infinity", "Infinity", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", -1, 1, Floor, "-Infinity", "-Infinity", Less, ); test_r( "-too_big", "-0x4.0E+268435455#1", -1, 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", -1, 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_r( "-too_big", "-0x4.0E+268435455#1", -1, 1, Up, "-Infinity", "-Infinity", Less, ); test_r( "-too_big", "-0x4.0E+268435455#1", -1, 1, Nearest, "-Infinity", "-Infinity", Less, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Floor, "0.0", "0x0.0", Less, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Down, "0.0", "0x0.0", Less, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_r( "too_small", "0x1.0E-268435456#1", 1, 1, Nearest, "0.0", "0x0.0", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Down, "-0.0", "-0x0.0", Greater, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_r( "-too_small", "-0x1.0E-268435456#1", 1, 1, Nearest, "-0.0", "-0x0.0", Greater, ); test_r( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, Nearest, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); test_r( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, Nearest, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shr_prec_round_signed() { test_shr_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_signed_helper::(|x, v, prec, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shr_prec_round_signed(&rug::Float::exact_from(&x), v, prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shr_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_signed_helper::(|_, _, _, _, _, _| {}); test_shr_prec_round_signed_helper::(|_, _, _, _, _, _| {}); } #[test] fn shr_prec_round_fail() { assert_panic!(Float::ONE.shr_prec_round(Float::MIN_EXPONENT, 1, Exact)); assert_panic!(Float::ONE.shr_prec_round(Float::MAX_EXPONENT + 2, 1, Exact)); assert_panic!(Float::NEGATIVE_ONE.shr_prec_round(Float::MIN_EXPONENT, 1, Exact)); assert_panic!(Float::NEGATIVE_ONE.shr_prec_round(Float::MAX_EXPONENT + 2, 1, Exact)); } fn test_shr_prec_unsigned_helper(f: F) where Rational: Shr, { let test = |s, s_hex, v: u64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_prec_assign(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_prec(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shr_prec_ref(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_prec_naive(x.clone(), v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, n, out_o); }; test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal); test("123.0", "0x7b.0#7", 10, 1, "0.1", "0x0.2#1", Greater); test("123.0", "0x7b.0#7", 10, 10, "0.1201", "0x0.1ec0#10", Equal); test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less); test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal); test("-123.0", "-0x7b.0#7", 10, 1, "-0.1", "-0x0.2#1", Less); test( "-123.0", "-0x7b.0#7", 10, 10, "-0.1201", "-0x0.1ec0#10", Equal, ); test( "too_small", "0x1.0E-268435456#1", 1, 1, "0.0", "0x0.0", Less, ); test( "-too_small", "-0x1.0E-268435456#1", 1, 1, "-0.0", "-0x0.0", Greater, ); test( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); test( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shr_prec_unsigned() { test_shr_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shr_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shr_prec_unsigned_helper::(|x, v, prec, shifted, o_out| { let (n, o) = rug_shr_prec_unsigned(&rug::Float::exact_from(&x), v, prec); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); }); test_shr_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shr_prec_unsigned_helper::(|_, _, _, _, _| {}); test_shr_prec_unsigned_helper::(|_, _, _, _, _| {}); } fn test_shr_prec_signed_helper(f: F) where Rational: Shr, { let test = |s, s_hex, v: i64, prec: u64, out: &str, out_hex: &str, out_o: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_prec_assign(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_prec(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.shr_prec_ref(v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_prec_naive(x.clone(), v, prec); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, prec, n, out_o); }; test("NaN", "NaN", 0, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 0, 10, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", 10, 10, "NaN", "NaN", Equal); test("NaN", "NaN", -10, 1, "NaN", "NaN", Equal); test("NaN", "NaN", -10, 10, "NaN", "NaN", Equal); test("Infinity", "Infinity", 0, 1, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 0, 10, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", 10, 1, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 10, 10, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", -10, 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", -10, 10, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 0, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 10, 10, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", -10, 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", -10, 10, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 10, 10, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", -10, 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", -10, 10, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 10, 10, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", -10, 1, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", -10, 10, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", 0, 1, "1.0e2", "0x8.0E+1#1", Greater); test("123.0", "0x7b.0#7", 0, 10, "123.0", "0x7b.0#10", Equal); test("123.0", "0x7b.0#7", 10, 1, "0.1", "0x0.2#1", Greater); test("123.0", "0x7b.0#7", 10, 10, "0.1201", "0x0.1ec0#10", Equal); test("123.0", "0x7b.0#7", -10, 1, "1.0e5", "0x2.0E+4#1", Greater); test( "123.0", "0x7b.0#7", -10, 10, "1.26e5", "0x1.ec0E+4#10", Equal, ); test("-123.0", "-0x7b.0#7", 0, 1, "-1.0e2", "-0x8.0E+1#1", Less); test("-123.0", "-0x7b.0#7", 0, 10, "-123.0", "-0x7b.0#10", Equal); test("-123.0", "-0x7b.0#7", 10, 1, "-0.1", "-0x0.2#1", Less); test( "-123.0", "-0x7b.0#7", 10, 10, "-0.1201", "-0x0.1ec0#10", Equal, ); test("-123.0", "-0x7b.0#7", -10, 1, "-1.0e5", "-0x2.0E+4#1", Less); test( "-123.0", "-0x7b.0#7", -10, 10, "-1.26e5", "-0x1.ec0E+4#10", Equal, ); test( "too_big", "0x4.0E+268435455#1", -1, 1, "Infinity", "Infinity", Greater, ); test( "-too_big", "-0x4.0E+268435455#1", -1, 1, "-Infinity", "-Infinity", Less, ); test( "too_small", "0x1.0E-268435456#1", 1, 1, "0.0", "0x0.0", Less, ); test( "-too_small", "-0x1.0E-268435456#1", 1, 1, "-0.0", "-0x0.0", Greater, ); test( "too_small", "0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, "too_small", "0x1.00000000000000000E-268435456#66", Greater, ); test( "-too_small", "-0x4.df81e47e11c9aa6dE-268435455#67", 7, 66, "-too_small", "-0x1.00000000000000000E-268435456#66", Less, ); } #[test] fn test_shr_prec_signed() { test_shr_prec_signed_helper::(|_, _, _, _, _| {}); test_shr_prec_signed_helper::(|_, _, _, _, _| {}); test_shr_prec_signed_helper::(|x, v, prec, shifted, o_out| { let (n, o) = rug_shr_prec_signed(&rug::Float::exact_from(&x), v, prec); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); }); test_shr_prec_signed_helper::(|_, _, _, _, _| {}); test_shr_prec_signed_helper::(|_, _, _, _, _| {}); test_shr_prec_signed_helper::(|_, _, _, _, _| {}); } fn test_shr_round_unsigned_helper< T: PrimitiveUnsigned, F: Fn(Float, T, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShrRoundAssign + ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { let test = |s, s_hex, v: u64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = x.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = (&x).shr_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = shr_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, Equal); f(x, v, rm, n, Equal); } }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", 10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", 100, "9.7e-29", "0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", 10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", 100, "-9.7e-29", "-0x7.bE-24#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); let test_extreme = |s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let v = u64::exact_from(v); if T::convertible_from(v) { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = (&x).shr_round(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, rm, n, out_o); } }; test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Floor, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Ceiling, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Down, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Up, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Nearest, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Exact, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Nearest, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Ceiling, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Up, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Nearest, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Floor, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Ceiling, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Down, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Up, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Exact, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Nearest, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Floor, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Up, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Nearest, "-too_small", "-0x1.0E-268435456#2", Less, ); } #[test] fn test_shr_round_unsigned() { test_shr_round_unsigned_helper::(|_, _, _, _, _| {}); test_shr_round_unsigned_helper::(|_, _, _, _, _| {}); test_shr_round_unsigned_helper::(|x, v, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shr_round_unsigned(&rug::Float::exact_from(&x), v, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shr_round_unsigned_helper::(|_, _, _, _, _| {}); test_shr_round_unsigned_helper::(|_, _, _, _, _| {}); test_shr_round_unsigned_helper::(|_, _, _, _, _| {}); } fn test_shr_round_signed_helper< T: PrimitiveSigned, F: Fn(Float, T, RoundingMode, Float, Ordering), >( f: F, ) where Float: ShrRoundAssign + ShrRound, Rational: Shr, for<'a> &'a Float: ShrRound, { let test = |s, s_hex, v: i64, out: &str, out_hex: &str| { for rm in exhaustive_rounding_modes() { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = x.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = (&x).shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, Equal); let (n, o) = shr_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, Equal); f(x, v, rm, n, Equal); } }; test("NaN", "NaN", 0, "NaN", "NaN"); test("NaN", "NaN", 10, "NaN", "NaN"); test("NaN", "NaN", -10, "NaN", "NaN"); test("Infinity", "Infinity", 0, "Infinity", "Infinity"); test("Infinity", "Infinity", 10, "Infinity", "Infinity"); test("Infinity", "Infinity", -10, "Infinity", "Infinity"); test("-Infinity", "-Infinity", 0, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", 10, "-Infinity", "-Infinity"); test("-Infinity", "-Infinity", -10, "-Infinity", "-Infinity"); test("0.0", "0x0.0", 10, "0.0", "0x0.0"); test("0.0", "0x0.0", -10, "0.0", "0x0.0"); test("-0.0", "-0x0.0", 10, "-0.0", "-0x0.0"); test("-0.0", "-0x0.0", -10, "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", 0, "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", 1, "61.5", "0x3d.8#7"); test("123.0", "0x7b.0#7", 10, "0.12", "0x0.1ec#7"); test("123.0", "0x7b.0#7", 100, "9.7e-29", "0x7.bE-24#7"); test("123.0", "0x7b.0#7", -1, "246.0", "0xf6.0#7"); test("123.0", "0x7b.0#7", -10, "1.26e5", "0x1.ecE+4#7"); test("123.0", "0x7b.0#7", -100, "1.56e32", "0x7.bE+26#7"); test("-123.0", "-0x7b.0#7", 0, "-123.0", "-0x7b.0#7"); test("-123.0", "-0x7b.0#7", 1, "-61.5", "-0x3d.8#7"); test("-123.0", "-0x7b.0#7", 10, "-0.12", "-0x0.1ec#7"); test("-123.0", "-0x7b.0#7", 100, "-9.7e-29", "-0x7.bE-24#7"); test("-123.0", "-0x7b.0#7", -1, "-246.0", "-0xf6.0#7"); test("-123.0", "-0x7b.0#7", -10, "-1.26e5", "-0x1.ecE+4#7"); test("-123.0", "-0x7b.0#7", -100, "-1.56e32", "-0x7.bE+26#7"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, "3.1415926535897931", "0x3.243f6a8885a30#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "1.5707963267948966", "0x1.921fb54442d18#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "0.0030679615757712823", "0x0.00c90fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "2.4782796245465248e-30", "0x3.243f6a8885a30E-25#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, "6.283185307179586", "0x6.487ed5110b460#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -10, "3216.9908772759482", "0xc90.fdaa22168c0#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, "3.9824418129956972e30", "0x3.243f6a8885a30E+25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, "-3.1415926535897931", "-0x3.243f6a8885a30#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "-1.5707963267948966", "-0x1.921fb54442d18#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-0.0030679615757712823", "-0x0.00c90fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-2.4782796245465248e-30", "-0x3.243f6a8885a30E-25#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, "-6.283185307179586", "-0x6.487ed5110b460#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -10, "-3216.9908772759482", "-0xc90.fdaa22168c0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, "-3.9824418129956972e30", "-0x3.243f6a8885a30E+25#53", ); let test_extreme = |s, s_hex, v: i32, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering| { let v = i64::from(v); if T::convertible_from(v) { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let v = T::exact_from(v); let mut n = x.clone(); let o = n.shr_round_assign(v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = x.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = (&x).shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, out_o); let (n, o) = shr_round_naive(x.clone(), v, rm); assert_eq!(n.to_string(), out); assert_eq!(to_hex_string(&n), out_hex); assert_eq!(o, out_o); f(x, v, rm, n, out_o); } }; test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Floor, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Ceiling, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Down, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Up, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Nearest, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT + 1, Exact, "too_big", "0x4.0E+268435455#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, Ceiling, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, Up, "Infinity", "Infinity", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MIN_EXPONENT, Nearest, "Infinity", "Infinity", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Ceiling, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Up, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "1.5", "0x1.8#2", Float::MAX_EXPONENT + 2, Nearest, "too_small", "0x1.0E-268435456#2", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Floor, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Down, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Up, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Nearest, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT + 1, Exact, "-too_big", "-0x4.0E+268435455#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, Floor, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, Up, "-Infinity", "-Infinity", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MIN_EXPONENT, Nearest, "-Infinity", "-Infinity", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Floor, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Ceiling, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Down, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Up, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Nearest, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 1, Exact, "too_small", "0x1.0E-268435456#1", Equal, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Floor, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Down, "0.0", "0x0.0", Less, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_extreme( "1.0", "0x1.0#1", Float::MAX_EXPONENT + 2, Nearest, "0.0", "0x0.0", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Floor, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Ceiling, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Down, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Up, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 1, Exact, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_extreme( "-1.0", "-0x1.0#1", Float::MAX_EXPONENT + 2, Nearest, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Floor, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Ceiling, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Down, "-0.0", "-0x0.0", Greater, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Up, "-too_small", "-0x1.0E-268435456#2", Less, ); test_extreme( "-1.5", "-0x1.8#2", Float::MAX_EXPONENT + 2, Nearest, "-too_small", "-0x1.0E-268435456#2", Less, ); } #[test] fn shr_round_fail() { assert_panic!(Float::ONE.shr_round(Float::MIN_EXPONENT, Exact)); assert_panic!(Float::ONE.shr_round(Float::MAX_EXPONENT + 2, Exact)); assert_panic!(Float::NEGATIVE_ONE.shr_round(Float::MIN_EXPONENT, Exact)); assert_panic!(Float::NEGATIVE_ONE.shr_round(Float::MAX_EXPONENT + 2, Exact)); } #[test] fn test_shr_round_signed() { test_shr_round_signed_helper::(|_, _, _, _, _| {}); test_shr_round_signed_helper::(|_, _, _, _, _| {}); test_shr_round_signed_helper::(|x, v, rm, shifted, o_out| { if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (n, o) = rug_shr_round_signed(&rug::Float::exact_from(&x), v, rm); assert_eq!( ComparableFloatRef(&Float::from(&n)), ComparableFloatRef(&shifted) ); assert_eq!(o, o_out); } }); test_shr_round_signed_helper::(|_, _, _, _, _| {}); test_shr_round_signed_helper::(|_, _, _, _, _| {}); test_shr_round_signed_helper::(|_, _, _, _, _| {}); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_properties_helper_unsigned_helper(n: Float, u: T, prec: u64) where i128: TryFrom, u64: TryFrom, Rational: Shr, { let mut mut_n = n.clone(); let o = mut_n.shr_prec_assign(u, prec); assert!(mut_n.is_valid()); let shifted = mut_n; if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shr_prec_round_ref(u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shr_prec_ref(u, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_prec(u, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_prec_naive(n.clone(), u, prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted), ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } let (shifted_2, o_2) = (-&n).shr_prec(u, prec); let (shifted_2_alt, o_2_alt) = n.shr_prec_ref(u, prec); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.div_prec(Float::power_of_2(u64::exact_from(u)), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shr_prec_properties_helper_unsigned() where i128: TryFrom, u64: TryFrom, Rational: Shr, { float_unsigned_unsigned_triple_gen_var_1::().test_properties(|(n, u, prec)| { shr_prec_properties_helper_unsigned_helper(n, u, prec); }); float_unsigned_unsigned_triple_gen_var_2::().test_properties(|(n, u, prec)| { shr_prec_properties_helper_unsigned_helper(n, u, prec); }); float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| { let (shifted, o) = n.shr_prec_ref(T::ZERO, prec); let (shifted_alt, o_alt) = Float::from_float_prec(n, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); unsigned_pair_gen_var_18::().test_properties(|(u, prec)| { let (shifted, o) = Float::NAN.shr_prec(u, prec); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shr_prec(u, prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shr_prec(u, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_prec(u, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_prec(u, prec); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_properties_helper_signed_helper(n: Float, i: T, prec: u64) where i128: TryFrom, i64: TryFrom, Rational: Shr, ::Output: PrimitiveUnsigned, { let mut mut_n = n.clone(); let o = mut_n.shr_prec_assign(i, prec); assert!(mut_n.is_valid()); let shifted = mut_n; if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shr_prec_round_ref(i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shr_prec_ref(i, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_prec(i, prec); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_prec_naive(n.clone(), i, prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } if i >= T::ZERO { let (shifted_alt, o_alt) = n.shr_prec_ref(i.unsigned_abs(), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = n.shl_prec_ref(i.unsigned_abs(), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shr_prec(i, prec); let (shifted_2_alt, o_2_alt) = n.shr_prec_ref(i, prec); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.div_prec(Float::power_of_2(i64::exact_from(i)), prec); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shr_prec_properties_helper_signed() where i128: TryFrom, i64: TryFrom, Rational: Shr, ::Output: PrimitiveUnsigned, { float_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, prec)| { shr_prec_properties_helper_signed_helper(n, i, prec); }); float_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, prec)| { shr_prec_properties_helper_signed_helper(n, i, prec); }); float_unsigned_pair_gen_var_1().test_properties(|(n, prec)| { let (shifted, o) = n.shr_prec_ref(T::ZERO, prec); let (shifted_alt, o_alt) = Float::from_float_prec(n, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); signed_unsigned_pair_gen_var_19::().test_properties(|(i, prec)| { let (shifted, o) = Float::NAN.shr_prec(i, prec); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shr_prec(i, prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shr_prec(i, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_prec(i, prec); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_prec(i, prec); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_unsigned_pair_gen_var_20::().test_properties(|(i, prec)| { let (shifted, o) = Float::ONE.shr_prec(i, prec); if shifted.is_normal() { assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); } }); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_rug_unsigned_helper(n: Float, u: u32, prec: u64) { let (shifted, o) = n.shr_prec_ref(u, prec); let (rug_shifted, rug_o) = rug_shr_prec_unsigned(&rug::Float::exact_from(&n), u, prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_rug_signed_helper(n: Float, i: i32, prec: u64) { let (shifted, o) = n.shr_prec_ref(i, prec); let (rug_shifted, rug_o) = rug_shr_prec_signed(&rug::Float::exact_from(&n), i, prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } #[test] fn shr_prec_properties() { apply_fn_to_unsigneds!(shr_prec_properties_helper_unsigned); apply_fn_to_signeds!(shr_prec_properties_helper_signed); float_unsigned_unsigned_triple_gen_var_1::() .test_properties(|(n, u, prec)| shr_prec_rug_unsigned_helper(n, u, prec)); float_unsigned_unsigned_triple_gen_var_2::() .test_properties(|(n, u, prec)| shr_prec_rug_unsigned_helper(n, u, prec)); float_signed_unsigned_triple_gen_var_1::() .test_properties(|(n, i, prec)| shr_prec_rug_signed_helper(n, i, prec)); float_signed_unsigned_triple_gen_var_2::() .test_properties(|(n, i, prec)| shr_prec_rug_signed_helper(n, i, prec)); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_round_properties_helper_unsigned_helper( n: Float, u: T, prec: u64, rm: RoundingMode, ) where i128: TryFrom, u64: TryFrom, Rational: Shr, { let mut mut_n = n.clone(); let o = mut_n.shr_prec_round_assign(u, prec, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shr_prec_round_ref(u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shr_prec_round_ref(u, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_prec_round(u, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_prec_round_naive(n.clone(), u, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted), ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } let (shifted_2, o_2) = (-&n).shr_prec_round(u, prec, rm); let (shifted_2_alt, o_2_alt) = n.shr_prec_round_ref(u, prec, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.div_prec_round(Float::power_of_2(u64::exact_from(u)), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shr_prec_round_properties_helper_unsigned() where i128: TryFrom, u64: TryFrom, Rational: Shr, { float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::().test_properties( |(n, u, prec, rm)| { shr_prec_round_properties_helper_unsigned_helper(n, u, prec, rm); }, ); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4::().test_properties( |(n, u, prec, rm)| { shr_prec_round_properties_helper_unsigned_helper(n, u, prec, rm); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| { let (shifted, o) = n.shr_prec_round_ref(T::ZERO, prec, rm); let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); unsigned_unsigned_rounding_mode_triple_gen_var_7::().test_properties(|(u, prec, rm)| { let (shifted, o) = Float::NAN.shr_prec_round(u, prec, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.shr_prec_round(u, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.shr_prec_round(u, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_prec_round(u, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_prec_round(u, prec, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_round_properties_helper_signed_helper( n: Float, i: T, prec: u64, rm: RoundingMode, ) where i128: TryFrom, i64: TryFrom, Rational: Shr, ::Output: PrimitiveUnsigned, { let mut mut_n = n.clone(); let o = mut_n.shr_prec_round_assign(i, prec, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = n.shr_prec_round_ref(i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = n.shr_prec_round_ref(i, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_prec_round(i, prec, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_add(i128::exact_from(i)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_prec_round_naive(n.clone(), i, prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(shifted.get_prec(), Some(prec)); } if i >= T::ZERO { let (shifted_alt, o_alt) = n.shr_prec_round_ref(i.unsigned_abs(), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = n.shl_prec_round_ref(i.unsigned_abs(), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shr_prec_round(i, prec, rm); let (shifted_2_alt, o_2_alt) = n.shr_prec_round_ref(i, prec, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { let (shifted_alt, o_alt) = n.div_prec_round(Float::power_of_2(i64::exact_from(i)), prec, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } } fn shr_prec_round_properties_helper_signed() where i128: TryFrom, i64: TryFrom, Rational: Shr, ::Output: PrimitiveUnsigned, { float_signed_unsigned_rounding_mode_quadruple_gen_var_3::().test_properties( |(n, i, prec, rm)| { shr_prec_round_properties_helper_signed_helper(n, i, prec, rm); }, ); float_signed_unsigned_rounding_mode_quadruple_gen_var_4::().test_properties( |(n, i, prec, rm)| { shr_prec_round_properties_helper_signed_helper(n, i, prec, rm); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, prec, rm)| { let (shifted, o) = n.shr_prec_round_ref(T::ZERO, prec, rm); let (shifted_alt, o_alt) = Float::from_float_prec_round(n, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(shifted_alt)); assert_eq!(o, o_alt); }); signed_unsigned_rounding_mode_triple_gen_var_7::().test_properties(|(i, prec, rm)| { let (shifted, o) = Float::NAN.shr_prec_round(i, prec, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.shr_prec_round(i, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.shr_prec_round(i, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_prec_round(i, prec, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_prec_round(i, prec, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_unsigned_rounding_mode_triple_gen_var_8::().test_properties(|(i, prec, rm)| { let (shifted, o) = Float::ONE.shr_prec_round(i, prec, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shr_prec_round_rug_unsigned_helper(n: Float, u: u32, prec: u64, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = n.shr_prec_round_ref(u, prec, rm); let (rug_shifted, rug_o) = rug_shr_prec_round_unsigned(&rug::Float::exact_from(&n), u, prec, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[allow(clippy::needless_pass_by_value)] fn shr_prec_round_rug_signed_helper(n: Float, i: i32, prec: u64, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = n.shr_prec_round_ref(i, prec, rm); let (rug_shifted, rug_o) = rug_shr_prec_round_signed(&rug::Float::exact_from(&n), i, prec, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[test] fn shr_prec_round_properties() { apply_fn_to_unsigneds!(shr_prec_round_properties_helper_unsigned); apply_fn_to_signeds!(shr_prec_round_properties_helper_signed); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_3::() .test_properties(|(n, u, prec, rm)| shr_prec_round_rug_unsigned_helper(n, u, prec, rm)); float_unsigned_unsigned_rounding_mode_quadruple_gen_var_4::() .test_properties(|(n, u, prec, rm)| shr_prec_round_rug_unsigned_helper(n, u, prec, rm)); float_signed_unsigned_rounding_mode_quadruple_gen_var_3::() .test_properties(|(n, i, prec, rm)| shr_prec_round_rug_signed_helper(n, i, prec, rm)); float_signed_unsigned_rounding_mode_quadruple_gen_var_4::() .test_properties(|(n, i, prec, rm)| shr_prec_round_rug_signed_helper(n, i, prec, rm)); } #[allow(clippy::needless_pass_by_value)] fn shr_round_properties_helper_unsigned_helper( n: Float, u: T, rm: RoundingMode, ) where for<'a> &'a Integer: Shr, Float: ShrRound + ShrRoundAssign + ShlRound, Rational: Shr, for<'a> &'a Float: ShrRound + Shr, u64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(u, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = (&n).shr_round(u, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = (&n).shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.shr_prec_round_ref(u, n.get_prec().unwrap_or(1), rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_sub(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_round_naive(n.clone(), u, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if i128::from(n.get_exponent().unwrap_or(1)) .wrapping_sub(i128::exact_from(u)) .lt_abs(&1_000_000) { let (shifted_alt, o_alt) = shr_round_naive(n.clone(), u, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { assert!((&n).shr_round(u, rm).0.le_abs(&n)); } let (shifted_2, o_2) = (-&n).shr_round(u, rm); let (shifted_2_alt, o_2_alt) = (&n).shr_round(u, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { assert_eq!( ComparableFloat(&n >> u), ComparableFloat(n / Float::power_of_2(u64::exact_from(u))) ); } } fn shr_round_properties_helper_unsigned() where for<'a> &'a Integer: Shr, Float: ShrRound + ShlRound + ShrRoundAssign, Rational: Shr, for<'a> &'a Float: ShrRound + Shr, u64: TryFrom, i128: TryFrom, { float_unsigned_rounding_mode_triple_gen_var_8::().test_properties(|(n, u, rm)| { shr_round_properties_helper_unsigned_helper(n, u, rm); }); float_unsigned_rounding_mode_triple_gen_var_9::().test_properties(|(n, u, rm)| { shr_round_properties_helper_unsigned_helper(n, u, rm); }); float_rounding_mode_pair_gen().test_properties(|(n, rm)| { let (shifted, o) = (&n).shr_round(T::ZERO, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(n)); assert_eq!(o, Equal); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { let (shifted, o) = Float::NAN.shr_round(u, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shr_round(u, rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shr_round(u, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_round(u, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_round(u, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); unsigned_rounding_mode_pair_gen_var_5::().test_properties(|(u, rm)| { let (shifted, o) = Float::ONE.shr_round(u, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shr_round_properties_helper_signed_helper(n: Float, i: T, rm: RoundingMode) where for<'a> &'a Integer: Shr, Float: ShrRound + ShrRoundAssign + ShlRound, for<'a> &'a Float: ShrRound + Shr + ShrRound<::Output, Output = Float> + ShlRound<::Output, Output = Float> + ShlRound, u64: TryFrom, i64: TryFrom, i128: TryFrom, { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if o == Equal { for rm in exhaustive_rounding_modes() { let (shifted_alt, o_alt) = (&n).shr_round(i, rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, Equal); } } let (shifted_alt, o_alt) = (&n).shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.shr_prec_round_ref(i, n.get_prec().unwrap_or(1), rm); assert!(shifted_alt.is_valid()); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); if shifted.is_normal() { assert_eq!(n.get_prec(), shifted.get_prec()); } if !n.is_nan() { if i >= T::ZERO { assert!((&n).shr_round(i, rm).0.le_abs(&n)); } else { assert!((&n).shr_round(i, rm).0.ge_abs(&n)); } } if i >= T::ZERO { let (shifted_alt, o_alt) = (&n).shr_round(i.unsigned_abs(), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); } else if i != T::MIN { let (shifted_alt, o_alt) = (&n).shl_round(i.unsigned_abs(), rm); assert_eq!( ComparableFloatRef(&shifted_alt), ComparableFloatRef(&shifted) ); assert_eq!(o_alt, o); }; let (shifted_2, o_2) = (-&n).shr_round(i, rm); let (shifted_2_alt, o_2_alt) = (&n).shr_round(i, -rm); assert_eq!(ComparableFloat(-shifted_2_alt), ComparableFloat(shifted_2)); assert_eq!(o_2_alt.reverse(), o_2); if shifted.is_normal() { assert_eq!( ComparableFloat(&n >> i), ComparableFloat(n / Float::power_of_2(i64::exact_from(i))) ); } } fn shr_round_properties_helper_signed() where for<'a> &'a Integer: Shr, Float: ShrRound + ShrRoundAssign + ShlRound, for<'a> &'a Float: ShrRound + Shr + ShrRound<::Output, Output = Float> + ShlRound<::Output, Output = Float> + ShlRound, i64: TryFrom, u64: TryFrom, i128: TryFrom, { float_signed_rounding_mode_triple_gen_var_4::().test_properties(|(n, i, rm)| { shr_round_properties_helper_signed_helper(n, i, rm); }); float_signed_rounding_mode_triple_gen_var_5::().test_properties(|(n, i, rm)| { shr_round_properties_helper_signed_helper(n, i, rm); }); float_rounding_mode_pair_gen().test_properties(|(n, rm)| { let (shifted, o) = (&n).shr_round(T::ZERO, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(n)); assert_eq!(o, Equal); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { let (shifted, o) = Float::NAN.shr_round(i, rm); assert!(shifted.is_nan()); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.shr_round(i, rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.shr_round(i, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (shifted, o) = Float::ZERO.shr_round(i, rm); assert_eq!(ComparableFloat(shifted), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (shifted, o) = Float::NEGATIVE_ZERO.shr_round(i, rm); assert_eq!( ComparableFloat(shifted), ComparableFloat(Float::NEGATIVE_ZERO) ); assert_eq!(o, Equal); }); signed_rounding_mode_pair_gen_var_5::().test_properties(|(i, rm)| { let (shifted, o) = Float::ONE.shr_round(i, rm); assert!(shifted.is_power_of_2()); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn shr_round_rug_unsigned_helper(n: Float, u: u32, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = (&n).shr_round(u, rm); let (rug_shifted, rug_o) = rug_shr_round_unsigned(&rug::Float::exact_from(&n), u, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[allow(clippy::needless_pass_by_value)] fn shr_round_rug_signed_helper(n: Float, i: i32, rm: RoundingMode) { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { let (shifted, o) = (&n).shr_round(i, rm); let (rug_shifted, rug_o) = rug_shr_round_signed(&rug::Float::exact_from(&n), i, rug_rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_shifted)), ComparableFloatRef(&shifted) ); assert_eq!(o, rug_o); } } #[test] fn shr_round_properties() { apply_fn_to_unsigneds!(shr_round_properties_helper_unsigned); apply_fn_to_signeds!(shr_round_properties_helper_signed); float_unsigned_rounding_mode_triple_gen_var_8::() .test_properties(|(n, u, rm)| shr_round_rug_unsigned_helper(n, u, rm)); float_unsigned_rounding_mode_triple_gen_var_9::() .test_properties(|(n, u, rm)| shr_round_rug_unsigned_helper(n, u, rm)); float_signed_rounding_mode_triple_gen_var_4::() .test_properties(|(n, i, rm)| shr_round_rug_signed_helper(n, i, rm)); float_signed_rounding_mode_triple_gen_var_5::() .test_properties(|(n, i, rm)| shr_round_rug_signed_helper(n, i, rm)); } ================================================ FILE: malachite-float/tests/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::traits::NaN; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::primitive_float_gen_var_11; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{float_gen_var_2, float_gen_var_3, float_gen_var_14}; use malachite_q::Rational; use std::cmp::Ordering::*; #[test] fn test_sign() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.sign(), out); }; test("Infinity", "Infinity", Greater); test("-Infinity", "-Infinity", Less); test("0.0", "0x0.0", Greater); test("-0.0", "-0x0.0", Less); test("1.0", "0x1.0#1", Greater); test("2.0", "0x2.0#1", Greater); test("0.5", "0x0.8#1", Greater); test("0.33333333333333331", "0x0.55555555555554#53", Greater); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", Greater); test("3.1415926535897931", "0x3.243f6a8885a30#53", Greater); test("too_big", "0x4.0E+268435455#1", Greater); test("too_small", "0x1.0E-268435456#1", Greater); test("-1.0", "-0x1.0#1", Less); test("-2.0", "-0x2.0#1", Less); test("-0.5", "-0x0.8#1", Less); test("-0.33333333333333331", "-0x0.55555555555554#53", Less); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Less); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", Less); test("-too_big", "-0x4.0E+268435455#1", Less); test("-too_small", "-0x1.0E-268435456#1", Less); } #[test] #[should_panic] fn sign_fail() { Float::NAN.sign(); } fn sign_properties_helper(x: Float) { let sign = x.sign(); assert_ne!(sign, Equal); assert_eq!(if x.is_sign_positive() { Greater } else { Less }, sign); assert_eq!((-x).sign(), sign.reverse()); } #[test] fn sign_properties() { float_gen_var_2().test_properties(|x| { sign_properties_helper(x); }); float_gen_var_14().test_properties(|x| { sign_properties_helper(x); }); float_gen_var_3().test_properties(|x| { assert_eq!(x.sign(), Rational::exact_from(x).sign()); }); primitive_float_gen_var_11::().test_properties(|x| { assert_eq!(x.sign(), Float::from(x).sign()); }); } ================================================ FILE: malachite-float/tests/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use core::{f32, f64}; use malachite_base::num::arithmetic::traits::{PowerOf2, Sqrt, SqrtAssign, Square}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::arithmetic::sqrt::primitive_float_sqrt_rational; use malachite_float::emulate_float_to_float_fn; use malachite_float::test_util::arithmetic::sqrt::{ rug_sqrt, rug_sqrt_prec, rug_sqrt_prec_round, rug_sqrt_round, sqrt_rational_prec_round_generic, sqrt_rational_prec_round_simple, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_6, float_gen_var_7, float_gen_var_8, float_gen_var_11, float_gen_var_12, float_rounding_mode_pair_gen_var_24, float_rounding_mode_pair_gen_var_25, float_rounding_mode_pair_gen_var_26, float_rounding_mode_pair_gen_var_27, float_rounding_mode_pair_gen_var_28, float_rounding_mode_pair_gen_var_29, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_13, float_unsigned_rounding_mode_triple_gen_var_14, rational_unsigned_rounding_mode_triple_gen_var_3, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_pair_gen, rational_unsigned_pair_gen_var_3, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_sqrt() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let sqrt = x.clone().sqrt(); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); let sqrt_alt = (&x).sqrt(); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); let mut sqrt_alt = x.clone(); sqrt_alt.sqrt_assign(); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt(&rug::Float::exact_from(&x)))), ComparableFloatRef(&sqrt) ); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "NaN", "NaN"); test("0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "-0.0", "-0x0.0"); // - in sqrt_float_significand_ref // - in sqrt_float_significand_ref_helper // - in sqrt_float_significand_same_prec_ref // - 1 limb in sqrt_float_significand_same_prec_ref // - in sqrt_float_significand_same_prec_lt_w // - exp_u.odd() in sqrt_float_significand_same_prec_lt_w // - in limb_sqrt_approx // - in half_limb_sqrt_approx // - z <= 2 * (LIMIT - 1) in limb_sqrt_approx // - z > y + y in limb_sqrt_approx // - r0.wrapping_add(7) & (mask >> 1) <= 7 in sqrt_float_significand_same_prec_lt_w // - rb == 0 || (rb == 1 && sb <= r0.wrapping_mul(2)) in sqrt_float_significand_same_prec_lt_w // - sb == 0 in sqrt_float_significand_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("-1.0", "-0x1.0#1", "NaN", "NaN"); test( "1.0", "0x1.0000000000000000000000000#100", "1.0", "0x1.0000000000000000000000000#100", ); test("-1.0", "-0x1.0000000000000000000000000#100", "NaN", "NaN"); test("123.0", "0x7b.0#7", "11.1", "0xb.2#7"); test("-123.0", "-0x7b.0#7", "NaN", "NaN"); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1.7724538509055159", "0x1.c5bf891b4ef6a#53", ); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "NaN", "NaN"); test( "245015989.087862987938504839548125246171", "0xe9aa5b5.167e3053b9874c7a7e9ad42ec#126", "15652.9865868422371154837031363385510498", "0x3d24.fc90f48e1283b9ddd9ddcd80c651#126", ); test( "8207.999969482421875000000208449716311754706238513360135037", "0x200f.fffe00000000000000fc000ffffffffe7fffffffe0000#191", "90.59801305482599751936121493336015116751576530601123201492", "0x5a.991762310f07e6c407b327fcf04aa587cf47462012c4a5#191", ); test( "255.99998475609754677861929270691580954", "0xff.ffff003ff00000000003ffffffffc#122", "15.999999523628041245261756402527546248", "0xf.fffff801ff7e00ff9f10dd9f7ca998#122", ); test( "0.9175812291850011518031983506835431746", "0x0.eae69a7ac5e74e0580d8afa7065e9b0#121", "0.9579046033843877252229074148114839997", "0x0.f5393c70394ab5224b7b609430e0038#121", ); } #[test] fn test_sqrt_prec() { let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (sqrt, o) = x.clone().sqrt_prec(prec); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, o_out); let (sqrt_alt, o_alt) = x.sqrt_prec_ref(prec); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); let mut sqrt_alt = x.clone(); let o_alt = sqrt_alt.sqrt_prec_assign(prec); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); let (rug_sqrt, rug_o) = rug_sqrt_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "Infinity", "Infinity", Equal); test("-Infinity", "-Infinity", 1, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, "1.0", "0x1.000#10", Equal, ); test("-1.0", "-0x1.0#1", 1, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", 1, "8.0", "0x8.0#1", Less); test("123.0", "0x7b.0#7", 10, "11.09", "0xb.18#10", Greater); test("-123.0", "-0x7b.0#7", 1, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "1.771", "0x1.c58#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "NaN", "NaN", Equal, ); test( "0.004", "0x0.01#1", 159, "0.0625", "0x0.10000000000000000000000000000000000000000#159", Equal, ); test( "3.977856078879580383473276114029204544685854243426e189", "0x3.9238e0e804fbb07c90c48c1a3f2717fe767aa541E+157#162", 162, "6.307024717630001791804921737602144987170364743623e94", "0x7.8f1c619832e271db7d7c00000000000000000000E+78#162", Equal, ); // - rm == Nearest && sticky1 == (1 << (sh - 1)) && !sqrt_inexact && sticky0 == 0 in // sqrt_float_significands_general // - in even_rule // - sh < Limb::WIDTH in even_rule // - rp[0] & (1 << sh) != 0 in even_rule // - inexact != Less in even_rule test("2.2", "0x2.4#4", 1, "2.0", "0x2.0#1", Greater); // - rp[0] & (1 << sh) == 0 in even_rule // - inexact == Less in even_rule test("1.56", "0x1.9#5", 2, "1.0", "0x1.0#2", Less); // - u_size > rrsize in sqrt_float_significands_general // - u_size > rrsize && !odd_exp in sqrt_float_significands_general // - sticky0 == 0 && l != 0 in sqrt_float_significands_general test( "0.000199046277632504184666664672269768242929310652018203552191617720205649", "0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225", 26, "0.0141083761", "0x0.039c9b46#26", Less, ); // - u_size <= rrsize && odd_exp && k == 0 in sqrt_float_significands_general test( "330.3297903358337046735382484655688", "0x14a.546d23b2f14f71a1f4c12ddaa88#115", 45, "18.17497703811", "0x12.2ccb4b903c#45", Greater, ); // - u_size > rrsize && odd_exp in sqrt_float_significands_general test( "4.377225292368646512419693467837359069662104001145e-12", "0x4.d01452b8a6a69b159aa9fe42a13c8852969ebbf2E-10#163", 31, "2.092181946e-6", "0x0.00002319da608#31", Greater, ); // - sticky0 != 0 || l == 0 in sqrt_float_significands_general test( "1.05073202367937779245019344912798895329031793654792205944648e-92", "0x5.7ab7ff36bcc0024c64f4507f522e91df687d9649e2e60984E-77#195", 53, "1.0250522053434049e-46", "0x9.5cfc196264d98E-39#53", Greater, ); } #[test] fn sqrt_prec_fail() { assert_panic!(Float::NAN.sqrt_prec(0)); assert_panic!(Float::NAN.sqrt_prec_ref(0)); assert_panic!({ let mut x = Float::NAN; x.sqrt_prec_assign(0) }); } #[test] fn test_sqrt_round() { let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (sqrt, o) = x.clone().sqrt_round(rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, o_out); let (sqrt_alt, o_alt) = x.sqrt_round_ref(rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); let mut sqrt_alt = x.clone(); let o_alt = sqrt_alt.sqrt_round_assign(rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt, rug_o) = rug_sqrt_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal); test("-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", Exact, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", Floor, "11.0", "0xb.0#7", Less); test("123.0", "0x7b.0#7", Ceiling, "11.1", "0xb.2#7", Greater); test("123.0", "0x7b.0#7", Down, "11.0", "0xb.0#7", Less); test("123.0", "0x7b.0#7", Up, "11.1", "0xb.2#7", Greater); test("123.0", "0x7b.0#7", Nearest, "11.1", "0xb.2#7", Greater); test("-123.0", "-0x7b.0#7", Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "1.7724538509055159", "0x1.c5bf891b4ef6a#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "1.7724538509055161", "0x1.c5bf891b4ef6b#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "1.7724538509055159", "0x1.c5bf891b4ef6a#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "1.7724538509055161", "0x1.c5bf891b4ef6b#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "1.7724538509055159", "0x1.c5bf891b4ef6a#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "NaN", "NaN", Equal, ); // - exp_u.even() in sqrt_float_significand_same_prec_lt_w // - z <= y + y in limb_sqrt_approx // - r0.wrapping_add(7) & (mask >> 1) > 7 in sqrt_float_significand_same_prec_lt_w // - sb != 0 in sqrt_float_significand_same_prec_lt_w // - rm == Nearest in sqrt_float_significand_same_prec_lt_w // - rm == Nearest && rb == 0 in sqrt_float_significand_same_prec_lt_w test("2.0", "0x2.0#1", Nearest, "1.0", "0x1.0#1", Less); // - rm == Nearest && rb != 0 in sqrt_float_significand_same_prec_lt_w // - rm == Nearest && rb != 0 && r0 != 0 in sqrt_float_significand_same_prec_lt_w test("2.0", "0x2.0#2", Nearest, "1.5", "0x1.8#2", Greater); // - z > 2 * (LIMIT - 1) in limb_sqrt_approx test("3.5", "0x3.8#3", Nearest, "1.8", "0x1.c#3", Less); // - !(rb == 0 || (rb == 1 && sb <= r0.wrapping_mul(2))) in // sqrt_float_significand_same_prec_lt_w test( "8.56684288039927757e26", "0x2.c4a1f44fb4eb72cE+22#60", Nearest, "29269169582342.57382", "0x1a9ec274b106.92e6#60", Greater, ); // - in sqrt_float_significand_same_prec_w // - exp_u.odd() in sqrt_float_significand_same_prec_w // - rb == 0 || (rb == 1 && sb <= r0.wrapping_mul(2)) in sqrt_float_significand_same_prec_w // - sb == 0 in sqrt_float_significand_same_prec_w test( "1.0", "0x1.0000000000000000#64", Nearest, "1.0", "0x1.0000000000000000#64", Equal, ); // - exp_u.even() in sqrt_float_significand_same_prec_w // - !(rb == 0 || (rb == 1 && sb <= r0.wrapping_mul(2))) in sqrt_float_significand_same_prec_w // - sb != 0 in sqrt_float_significand_same_prec_w // - rm == Nearest in sqrt_float_significand_same_prec_w // - rm == Nearest && rb == 0 in sqrt_float_significand_same_prec_w test( "2.0", "0x2.0000000000000000#64", Nearest, "1.4142135623730950488", "0x1.6a09e667f3bcc908#64", Less, ); // - rm == Nearest && rb != 0 in sqrt_float_significand_same_prec_w // - rm == Nearest && rb != 0 && r0 != 0 in sqrt_float_significand_same_prec_w test( "1.0000000000000000002", "0x1.0000000000000004#64", Nearest, "1.0000000000000000001", "0x1.0000000000000002#64", Greater, ); // - 2 limbs, prec != 2*w in sqrt_float_significand_same_prec_ref // - in sqrt_float_significand_same_prec_gt_w_lt_2w // - exp_u.odd() in sqrt_float_significand_same_prec_gt_w_lt_2w // - in limbs_2_sqrt_approx // - in limb_sqrt // - in limb_inverse_sqrt_approx // - !r.get_highest_bit() in limb_sqrt // - h < 16 in limb_sqrt // - h < 8 in limb_sqrt // - h < 4 in limb_sqrt // - h <= 1 && ((h != 1) || (l <= r.wrapping_mul(2))) in limb_sqrt // - h == 0 in limbs_2_sqrt_approx // - r0.wrapping_add(26) & (mask >> 1) <= 30 in sqrt_float_significand_same_prec_gt_w_lt_2w // - SignedLimb::wrapping_from(t2) >= 0 in sqrt_float_significand_same_prec_gt_w_lt_2w // - t2 <= 1 && (t2 != 1 || t1 <= h) && (t2 != 1 || t1 != h || t0 <= l) in // sqrt_float_significand_same_prec_gt_w_lt_2w // - sb == 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", Nearest, "1.0", "0x1.0000000000000000#65", Equal, ); // - exp_u.even() in sqrt_float_significand_same_prec_gt_w_lt_2w // - r.get_highest_bit() in limb_sqrt // - h >= 4 in limb_sqrt // - h > 1 || ((h == 1) && (l > r.wrapping_mul(2))) in limb_sqrt // - r0.wrapping_add(26) & (mask >> 1) > 30 in sqrt_float_significand_same_prec_gt_w_lt_2w // - sb != 0 in sqrt_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest in sqrt_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && rb != 0 in sqrt_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && rb != 0 && r1 != 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", Nearest, "1.41421356237309504882", "0x1.6a09e667f3bcc909#65", Greater, ); // - t2 > 1 || (t2 == 1 && t1 > h) || (t2 == 1 && t1 == h && t0 > l) in // sqrt_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && rb == 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "1.0", "0x1.0000000000000000#65", Less, ); // - h != 0 in limbs_2_sqrt_approx test( "2.00000000000000000125", "0x2.0000000000000017#66", Nearest, "1.41421356237309504925", "0x1.6a09e667f3bcc9110#66", Greater, ); // - h >= 8 in limb_sqrt test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Nearest, "120008682170084.730095556159", "0x6d25b2dee6e4.bae78ad8a8#85", Greater, ); // - h >= 16 in limb_sqrt test( "14.8543972813270696412821", "0xe.dab9c7bd1750bad37350#83", Nearest, "3.8541402778475862892890363", "0x3.daa8efef8d3e9881bc6d0#83", Less, ); // - default case in sqrt_float_significand_same_prec_ref // - in sqrt_float_significands_general // - sh != 0 || rm != Nearest in sqrt_float_significands_general // - u_size <= rrsize in sqrt_float_significands_general // - u_size <= rrsize || !odd_exp in sqrt_float_significands_general // - sticky0 in sqrt_float_significands_general // - rm == Nearest in sqrt_float_significands_general // - rm == Nearest && sh < Limb::WIDTH in sqrt_float_significands_general // - rm == Nearest && sticky1 & (1 << (sh - 1)) == 0 in sqrt_float_significands_general // - in truncate // - sh != Limb::WIDTH in truncate test( "531607.999405753398566100250398911805595276409254333486007034444758646220477451", "0x81c97.ffd90e3247f501afdb3e5781d0c650b8de694094110713b5a698d3d38550#257", Nearest, "729.11453106199536130370773365901724384208766502803825392984301547488034915749", "0x2d9.1d51e85da56f057ec9027291169bc84fb3262e9f7b56ad4fbded5d5fb28234#257", Less, ); // - u_size <= rrsize && odd_exp in sqrt_float_significands_general // - u_size <= rrsize && odd_exp && k != 0 in sqrt_float_significands_general test( "8669478862124781.0453122498906357696603256", "0x1eccd857f6f6ed.0b999567637220ce5162#133", Nearest, "93110036.31255215575055410689733347856975", "0x58cbf14.50036b073e308b45123fad288c8#133", Less, ); // - rm == Nearest && sticky1 & (1 << (sh - 1)) != 0 in sqrt_float_significands_general // - rm == Nearest && sticky1 == (1 << (sh - 1)) && !sqrt_inexact && sticky0 != 0 in // sqrt_float_significands_general // - in add_one // - sh != Limb::WIDTH in add_one // - !carry in add_one test( "4.342868714761498751021923028996829056762200989107722850118926783525941596406956471866296\ 2992498076143086829355664e-20", "0xc.d160fab1cc524c2fe76cffa155f81b8188af00d7023e4d317d44fbce1d3d47bc1d1312f172ce15520ea1d\ 11590abE-17#372", Nearest, "2.083955065437232202468518924164364631048457537561905126352513612727408728510770037672930\ 6989930075738883830052488e-10", "0xe.5221ecf52b8695b0ee215b5d4b92348fce150af3190e08806ac4bb447fc0e236659b5b02162fde717b9e2\ 56afe2eE-9#372", Greater, ); // - sh == 0 && rm == Nearest in sqrt_float_significands_general // - rm == Nearest && sh >= Limb::WIDTH in sqrt_float_significands_general // - rm == Nearest && sticky1.get_highest_bit() in sqrt_float_significands_general // - rm == Nearest && sticky1 == LIMB_HIGH_BIT && !sqrt_inexact && sticky0 != 0 in // sqrt_float_significands_general // - sh == Limb::WIDTH in add_one test( "2.652265028059746721807174554033221706564e-11", "0x1.d29765de1f777af51db92558a3d9f542E-9#128", Nearest, "5.15001459032860092518337573994143253147e-6", "0x0.0000566724ecdf4dd7e9fadaf1a94e15741b0#128", Greater, ); // - rm == Nearest && !sticky1.get_highest_bit() in sqrt_float_significands_general // - sh == Limb::WIDTH in truncate test( "4.131497698938604195099390193257480907988376605341754029892e72", "0x2.569dc44aae4efd9bf163a72fcf66facef9729212ebaf3d4cE+60#192", Nearest, "2032608594623815959008545804304448692.2928683624055859234906", "0x18777574b6d7a0f8c80efa20bdefcb4.4af96bc690a8425010#192", Less, ); // - !sticky0 in sqrt_float_significands_general test( "3.9231885846166754773973683895047915100639721527900216e56", "0x1.00000000000000000000000000000000000000000000E+47#176", Nearest, "19807040628566084398385987584.0", "0x400000000000000000000000.000000000000000000000#176", Equal, ); test( "too_big", "0x4.0E+268435455#1", Nearest, "too_big", "0x8.0E+134217727#1", Equal, ); test( "too_big", "0x6.0E+268435455#2", Nearest, "too_big", "0x8.0E+134217727#2", Less, ); test( "too_small", "0x1.0E-268435456#1", Nearest, "too_small", "0x1.0E-134217728#1", Equal, ); test( "too_small", "0x1.0E-268435456#2", Nearest, "too_small", "0x1.0E-134217728#2", Equal, ); // - rm == Floor | Down in sqrt_float_significand_same_prec_lt_w test("2.0", "0x2.0#1", Down, "1.0", "0x1.0#1", Less); // - rm == Ceiling | Up in sqrt_float_significand_same_prec_lt_w // - rm == Ceiling | Up && r0 == 0 in sqrt_float_significand_same_prec_lt_w test("2.0", "0x2.0#1", Up, "2.0", "0x2.0#1", Greater); // - rm == Ceiling | Up && r0 != 0 in sqrt_float_significand_same_prec_lt_w test("2.0", "0x2.0#2", Up, "1.5", "0x1.8#2", Greater); // - rm == Floor | Down in sqrt_float_significand_same_prec_w test( "2.0", "0x2.0000000000000000#64", Down, "1.4142135623730950488", "0x1.6a09e667f3bcc908#64", Less, ); // - rm == Ceiling | Up in sqrt_float_significand_same_prec_w // - r0 != 0 in sqrt_float_significand_same_prec_w test( "2.0", "0x2.0000000000000000#64", Up, "1.4142135623730950489", "0x1.6a09e667f3bcc90a#64", Greater, ); // - r0 == 0 in sqrt_float_significand_same_prec_w test( "67108863.999999999996", "0x3ffffff.fffffffffc#64", Up, "8192.0", "0x2000.0000000000000#64", Greater, ); // - rm == Floor | Down in sqrt_float_significand_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", Down, "1.41421356237309504876", "0x1.6a09e667f3bcc908#65", Less, ); // - rm == Ceiling | Up in sqrt_float_significand_same_prec_gt_w_lt_2w // - rm == Ceiling | Up && r1 != 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "2.0", "0x2.0000000000000000#65", Up, "1.41421356237309504882", "0x1.6a09e667f3bcc909#65", Greater, ); // - rm == Ceiling | Up && r1 == 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "7.00649232162408535461864791e-46", "0x3.fffffffffffffffffffffeE-38#89", Up, "2.646977960169688559588507815e-23", "0x2.0000000000000000000000E-19#89", Greater, ); // - rm == Floor | Down in sqrt_float_significands_general test( "2.0", "0x2.00000000000000000000000000000000#129", Down, "1.414213562373095048801688724209698078569", "0x1.6a09e667f3bcc908b2fb1366ea957d3e#129", Less, ); // - rm == Ceiling | Up in sqrt_float_significands_general test( "2.0", "0x2.00000000000000000000000000000000#129", Up, "1.414213562373095048801688724209698078572", "0x1.6a09e667f3bcc908b2fb1366ea957d3f#129", Greater, ); // - carry in add_one test( "0.999999999999999999999999999999999999999", "0x0.ffffffffffffffffffffffffffffffff8#129", Up, "1.0", "0x1.00000000000000000000000000000000#129", Greater, ); // - SignedLimb::wrapping_from(t2) < 0 in sqrt_float_significand_same_prec_gt_w_lt_2w test( "3.1370587247788594938889277427222882863e58", "0x4.ff643687dfbb20bf81d2ef780dca280E+48#124", Nearest, "177117439140781941633284688407.1796741", "0x23c4c1c9f13433f0d1315ca17.2dff1f4#124", Less, ); } #[test] fn sqrt_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.sqrt_round(Exact)); assert_panic!(THREE.sqrt_round_ref(Exact)); assert_panic!({ let mut x = THREE; x.sqrt_round_assign(Exact); }); } #[test] fn test_sqrt_prec_round() { let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (sqrt, o) = x.clone().sqrt_prec_round(prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, o_out); let (sqrt_alt, o_alt) = x.sqrt_prec_round_ref(prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); let mut sqrt_alt = x.clone(); let o_alt = sqrt_alt.sqrt_prec_round_assign(prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt), ComparableFloatRef(&sqrt_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt, rug_o) = rug_sqrt_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test("-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal); test("-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal); test("0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 1, Exact, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Floor, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Ceiling, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Down, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Up, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Nearest, "NaN", "NaN", Equal); test("-1.0", "-0x1.0#1", 10, Exact, "NaN", "NaN", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, Floor, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Down, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Up, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Exact, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Exact, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Exact, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Floor, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Down, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Up, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Nearest, "NaN", "NaN", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Exact, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", 1, Floor, "8.0", "0x8.0#1", Less); test( "123.0", "0x7b.0#7", 1, Ceiling, "2.0e1", "0x1.0E+1#1", Greater, ); test("123.0", "0x7b.0#7", 1, Down, "8.0", "0x8.0#1", Less); test("123.0", "0x7b.0#7", 1, Up, "2.0e1", "0x1.0E+1#1", Greater); test("123.0", "0x7b.0#7", 1, Nearest, "8.0", "0x8.0#1", Less); test("123.0", "0x7b.0#7", 10, Floor, "11.08", "0xb.14#10", Less); test( "123.0", "0x7b.0#7", 10, Ceiling, "11.09", "0xb.18#10", Greater, ); test("123.0", "0x7b.0#7", 10, Down, "11.08", "0xb.14#10", Less); test("123.0", "0x7b.0#7", 10, Up, "11.09", "0xb.18#10", Greater); test( "123.0", "0x7b.0#7", 10, Nearest, "11.09", "0xb.18#10", Greater, ); test("-123.0", "-0x7b.0#7", 1, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Floor, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Ceiling, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Down, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Up, "NaN", "NaN", Equal); test("-123.0", "-0x7b.0#7", 10, Nearest, "NaN", "NaN", Equal); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "1.0", "0x1.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "2.0", "0x2.0#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "1.771", "0x1.c58#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "1.773", "0x1.c60#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "1.771", "0x1.c58#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "1.773", "0x1.c60#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "1.771", "0x1.c58#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "NaN", "NaN", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "NaN", "NaN", Equal, ); } #[test] fn sqrt_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).sqrt_prec_round(0, Floor)); assert_panic!(Float::one_prec(1).sqrt_prec_round_ref(0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.sqrt_prec_round_assign(0, Floor) }); assert_panic!(THREE.sqrt_prec_round(1, Exact)); assert_panic!(THREE.sqrt_prec_round_ref(1, Exact)); assert_panic!({ let mut x = THREE; x.sqrt_prec_round_assign(1, Exact) }); } #[test] fn test_sqrt_rational_prec() { let test = |s, prec, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (sqrt, o) = Float::sqrt_rational_prec(u.clone(), prec); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = Float::sqrt_rational_prec_ref(&u, prec); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_generic(&u, prec, Nearest); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_simple(&u, prec, Nearest); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); if sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < u); } } } }; test("0", 1, "0.0", "0x0.0", Equal); test("0", 10, "0.0", "0x0.0", Equal); test("0", 100, "0.0", "0x0.0", Equal); test("1", 1, "1.0", "0x1.0#1", Equal); test("1", 10, "1.0", "0x1.000#10", Equal); test("1", 100, "1.0", "0x1.0000000000000000000000000#100", Equal); test("1/2", 1, "0.5", "0x0.8#1", Less); test("1/2", 10, "0.707", "0x0.b50#10", Less); test( "1/2", 100, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test("1/3", 1, "0.5", "0x0.8#1", Less); test("1/3", 10, "0.577", "0x0.93c#10", Less); test( "1/3", 100, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test("22/7", 1, "2.0", "0x2.0#1", Greater); test("22/7", 10, "1.773", "0x1.c60#10", Greater); test( "22/7", 100, "1.772810520855836656590463136493", "0x1.c5d6e909149e8e4e59f04b68e#100", Greater, ); let test_big = |u: Rational, prec, out, out_hex, out_o| { let (sqrt, o) = Float::sqrt_rational_prec(u.clone(), prec); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = Float::sqrt_rational_prec_ref(&u, prec); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_generic(&u, prec, Nearest); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_simple(&u, prec, Nearest); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); if sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < u); } } } }; test_big( Rational::power_of_2(1000i64), 10, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_small", "0xb.50E-134217729#10", Less, ); } #[test] fn sqrt_rational_prec_fail() { assert_panic!(Float::sqrt_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::sqrt_rational_prec(Rational::ONE, 0)); assert_panic!(Float::sqrt_rational_prec(Rational::NEGATIVE_ONE, 0)); } #[test] fn sqrt_rational_prec_ref_fail() { assert_panic!(Float::sqrt_rational_prec_ref(&Rational::ZERO, 0)); assert_panic!(Float::sqrt_rational_prec_ref(&Rational::ONE, 0)); assert_panic!(Float::sqrt_rational_prec_ref(&Rational::NEGATIVE_ONE, 0)); } #[test] fn test_sqrt_rational_prec_round() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (sqrt, o) = Float::sqrt_rational_prec_round(u.clone(), prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = Float::sqrt_rational_prec_round_ref(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_generic(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_simple(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); if sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < u); } } } }; test("0", 1, Floor, "0.0", "0x0.0", Equal); test("0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", 1, Down, "0.0", "0x0.0", Equal); test("0", 1, Up, "0.0", "0x0.0", Equal); test("0", 1, Nearest, "0.0", "0x0.0", Equal); test("0", 1, Exact, "0.0", "0x0.0", Equal); test("0", 10, Floor, "0.0", "0x0.0", Equal); test("0", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", 10, Down, "0.0", "0x0.0", Equal); test("0", 10, Up, "0.0", "0x0.0", Equal); test("0", 10, Nearest, "0.0", "0x0.0", Equal); test("0", 10, Exact, "0.0", "0x0.0", Equal); test("0", 100, Floor, "0.0", "0x0.0", Equal); test("0", 100, Ceiling, "0.0", "0x0.0", Equal); test("0", 100, Down, "0.0", "0x0.0", Equal); test("0", 100, Up, "0.0", "0x0.0", Equal); test("0", 100, Nearest, "0.0", "0x0.0", Equal); test("0", 100, Exact, "0.0", "0x0.0", Equal); test("1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1", 1, Down, "1.0", "0x1.0#1", Equal); test("1", 1, Up, "1.0", "0x1.0#1", Equal); test("1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1", 10, Down, "1.0", "0x1.000#10", Equal); test("1", 10, Up, "1.0", "0x1.000#10", Equal); test("1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1", 10, Exact, "1.0", "0x1.000#10", Equal); test( "1", 100, Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test("1/2", 1, Floor, "0.5", "0x0.8#1", Less); test("1/2", 1, Ceiling, "1.0", "0x1.0#1", Greater); test("1/2", 1, Down, "0.5", "0x0.8#1", Less); test("1/2", 1, Up, "1.0", "0x1.0#1", Greater); test("1/2", 1, Nearest, "0.5", "0x0.8#1", Less); test("1/2", 10, Floor, "0.707", "0x0.b50#10", Less); test("1/2", 10, Ceiling, "0.708", "0x0.b54#10", Greater); test("1/2", 10, Down, "0.707", "0x0.b50#10", Less); test("1/2", 10, Up, "0.708", "0x0.b54#10", Greater); test("1/2", 10, Nearest, "0.707", "0x0.b50#10", Less); test( "1/2", 100, Floor, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test( "1/2", 100, Ceiling, "0.7071067811865475244008443621054", "0x0.b504f333f9de6484597d89b38#100", Greater, ); test( "1/2", 100, Down, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test( "1/2", 100, Up, "0.7071067811865475244008443621054", "0x0.b504f333f9de6484597d89b38#100", Greater, ); test( "1/2", 100, Nearest, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test("1/3", 1, Floor, "0.5", "0x0.8#1", Less); test("1/3", 1, Ceiling, "1.0", "0x1.0#1", Greater); test("1/3", 1, Down, "0.5", "0x0.8#1", Less); test("1/3", 1, Up, "1.0", "0x1.0#1", Greater); test("1/3", 1, Nearest, "0.5", "0x0.8#1", Less); test("1/3", 10, Floor, "0.577", "0x0.93c#10", Less); test("1/3", 10, Ceiling, "0.578", "0x0.940#10", Greater); test("1/3", 10, Down, "0.577", "0x0.93c#10", Less); test("1/3", 10, Up, "0.578", "0x0.940#10", Greater); test("1/3", 10, Nearest, "0.577", "0x0.93c#10", Less); test( "1/3", 100, Floor, "0.577350269189625764509148780501", "0x0.93cd3a2c8198e2690c7c0f257#100", Less, ); test( "1/3", 100, Ceiling, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test( "1/3", 100, Down, "0.577350269189625764509148780501", "0x0.93cd3a2c8198e2690c7c0f257#100", Less, ); test( "1/3", 100, Up, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test( "1/3", 100, Nearest, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test("22/7", 1, Floor, "1.0", "0x1.0#1", Less); test("22/7", 1, Ceiling, "2.0", "0x2.0#1", Greater); test("22/7", 1, Down, "1.0", "0x1.0#1", Less); test("22/7", 1, Up, "2.0", "0x2.0#1", Greater); test("22/7", 1, Nearest, "2.0", "0x2.0#1", Greater); test("22/7", 10, Floor, "1.771", "0x1.c58#10", Less); test("22/7", 10, Ceiling, "1.773", "0x1.c60#10", Greater); test("22/7", 10, Down, "1.771", "0x1.c58#10", Less); test("22/7", 10, Up, "1.773", "0x1.c60#10", Greater); test("22/7", 10, Nearest, "1.773", "0x1.c60#10", Greater); test( "22/7", 100, Floor, "1.772810520855836656590463136491", "0x1.c5d6e909149e8e4e59f04b68c#100", Less, ); test( "22/7", 100, Ceiling, "1.772810520855836656590463136493", "0x1.c5d6e909149e8e4e59f04b68e#100", Greater, ); test( "22/7", 100, Down, "1.772810520855836656590463136491", "0x1.c5d6e909149e8e4e59f04b68c#100", Less, ); test( "22/7", 100, Up, "1.772810520855836656590463136493", "0x1.c5d6e909149e8e4e59f04b68e#100", Greater, ); test( "22/7", 100, Nearest, "1.772810520855836656590463136493", "0x1.c5d6e909149e8e4e59f04b68e#100", Greater, ); test("-1", 1, Floor, "NaN", "NaN", Equal); test("-1", 1, Ceiling, "NaN", "NaN", Equal); test("-1", 1, Down, "NaN", "NaN", Equal); test("-1", 1, Up, "NaN", "NaN", Equal); test("-1", 1, Nearest, "NaN", "NaN", Equal); test("-1", 1, Exact, "NaN", "NaN", Equal); test("-1", 10, Floor, "NaN", "NaN", Equal); test("-1", 10, Ceiling, "NaN", "NaN", Equal); test("-1", 10, Down, "NaN", "NaN", Equal); test("-1", 10, Up, "NaN", "NaN", Equal); test("-1", 10, Nearest, "NaN", "NaN", Equal); test("-1", 10, Exact, "NaN", "NaN", Equal); test("-1", 100, Floor, "NaN", "NaN", Equal); test("-1", 100, Ceiling, "NaN", "NaN", Equal); test("-1", 100, Down, "NaN", "NaN", Equal); test("-1", 100, Up, "NaN", "NaN", Equal); test("-1", 100, Nearest, "NaN", "NaN", Equal); test("-1", 100, Exact, "NaN", "NaN", Equal); test("-1/2", 1, Floor, "NaN", "NaN", Equal); test("-1/2", 1, Ceiling, "NaN", "NaN", Equal); test("-1/2", 1, Down, "NaN", "NaN", Equal); test("-1/2", 1, Up, "NaN", "NaN", Equal); test("-1/2", 1, Nearest, "NaN", "NaN", Equal); test("-1/2", 1, Exact, "NaN", "NaN", Equal); test("-1/2", 10, Floor, "NaN", "NaN", Equal); test("-1/2", 10, Ceiling, "NaN", "NaN", Equal); test("-1/2", 10, Down, "NaN", "NaN", Equal); test("-1/2", 10, Up, "NaN", "NaN", Equal); test("-1/2", 10, Nearest, "NaN", "NaN", Equal); test("-1/2", 10, Exact, "NaN", "NaN", Equal); test("-1/2", 100, Floor, "NaN", "NaN", Equal); test("-1/2", 100, Ceiling, "NaN", "NaN", Equal); test("-1/2", 100, Down, "NaN", "NaN", Equal); test("-1/2", 100, Up, "NaN", "NaN", Equal); test("-1/2", 100, Nearest, "NaN", "NaN", Equal); test("-1/2", 100, Exact, "NaN", "NaN", Equal); test("-1/3", 1, Floor, "NaN", "NaN", Equal); test("-1/3", 1, Ceiling, "NaN", "NaN", Equal); test("-1/3", 1, Down, "NaN", "NaN", Equal); test("-1/3", 1, Up, "NaN", "NaN", Equal); test("-1/3", 1, Nearest, "NaN", "NaN", Equal); test("-1/3", 10, Floor, "NaN", "NaN", Equal); test("-1/3", 10, Ceiling, "NaN", "NaN", Equal); test("-1/3", 10, Down, "NaN", "NaN", Equal); test("-1/3", 10, Up, "NaN", "NaN", Equal); test("-1/3", 10, Nearest, "NaN", "NaN", Equal); test("-1/3", 100, Floor, "NaN", "NaN", Equal); test("-1/3", 100, Ceiling, "NaN", "NaN", Equal); test("-1/3", 100, Down, "NaN", "NaN", Equal); test("-1/3", 100, Up, "NaN", "NaN", Equal); test("-1/3", 100, Nearest, "NaN", "NaN", Equal); test("-22/7", 1, Floor, "NaN", "NaN", Equal); test("-22/7", 1, Ceiling, "NaN", "NaN", Equal); test("-22/7", 1, Down, "NaN", "NaN", Equal); test("-22/7", 1, Up, "NaN", "NaN", Equal); test("-22/7", 1, Nearest, "NaN", "NaN", Equal); test("-22/7", 10, Floor, "NaN", "NaN", Equal); test("-22/7", 10, Ceiling, "NaN", "NaN", Equal); test("-22/7", 10, Down, "NaN", "NaN", Equal); test("-22/7", 10, Up, "NaN", "NaN", Equal); test("-22/7", 10, Nearest, "NaN", "NaN", Equal); test("-22/7", 100, Floor, "NaN", "NaN", Equal); test("-22/7", 100, Ceiling, "NaN", "NaN", Equal); test("-22/7", 100, Down, "NaN", "NaN", Equal); test("-22/7", 100, Up, "NaN", "NaN", Equal); test("-22/7", 100, Nearest, "NaN", "NaN", Equal); let test_big = |u: Rational, prec, rm, out, out_hex, out_o| { let (sqrt, o) = Float::sqrt_rational_prec_round(u.clone(), prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = Float::sqrt_rational_prec_round_ref(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_generic(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); let (sqrt, o) = sqrt_rational_prec_round_simple(&u, prec, rm); assert!(sqrt.is_valid()); assert_eq!(sqrt.to_string(), out); assert_eq!(to_hex_string(&sqrt), out_hex); assert_eq!(o, out_o); if sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < u); } } } }; test_big( Rational::power_of_2(1000i64), 10, Floor, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Ceiling, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Down, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Up, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Nearest, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Exact, "3.273e150", "0x1.000E+125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Floor, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Ceiling, "too_big", "0xb.54E+134217727#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Down, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Up, "too_big", "0xb.54E+134217727#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Nearest, "too_big", "0xb.50E+134217727#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Floor, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Down, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Up, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Nearest, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Exact, "too_big", "0x8.00E+134217727#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Floor, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Ceiling, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Down, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Up, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Nearest, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Floor, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Ceiling, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Down, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Up, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Nearest, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Floor, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Ceiling, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Down, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Up, "too_big", "0x1.0E+134217728#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Nearest, "too_big", "0x8.0E+134217727#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, Floor, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Ceiling, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Down, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Up, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Nearest, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Exact, "3.055e-151", "0x1.000E-125#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Floor, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Ceiling, "too_small", "0x1.6a8E-134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Down, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Up, "too_small", "0x1.6a8E-134217728#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Nearest, "too_small", "0x1.6a0E-134217728#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Floor, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Ceiling, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Down, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Up, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Nearest, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Exact, "too_small", "0x1.000E-134217728#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "too_small", "0xb.50E-134217729#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_small", "0xb.54E-134217729#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_small", "0xb.50E-134217729#10", Less, ); } #[test] fn sqrt_rational_prec_round_fail() { assert_panic!(Float::sqrt_rational_prec_round(Rational::ZERO, 0, Floor)); assert_panic!(Float::sqrt_rational_prec_round(Rational::ONE, 0, Floor)); assert_panic!(Float::sqrt_rational_prec_round( Rational::from(123u32), 1, Exact )); assert_panic!(Float::sqrt_rational_prec_round( Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::sqrt_rational_prec_round( Rational::NEGATIVE_ONE, 0, Floor )); } #[test] fn sqrt_rational_prec_round_ref_fail() { assert_panic!(Float::sqrt_rational_prec_round_ref( &Rational::ZERO, 0, Floor )); assert_panic!(Float::sqrt_rational_prec_round_ref( &Rational::ONE, 0, Floor )); assert_panic!(Float::sqrt_rational_prec_round_ref( &Rational::from(123u32), 1, Exact )); assert_panic!(Float::sqrt_rational_prec_round_ref( &Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::sqrt_rational_prec_round_ref( &Rational::NEGATIVE_ONE, 0, Floor )); } #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_primitive_float_sqrt_rational() { fn test(s: &str, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { let u = Rational::from_str(s).unwrap(); let sqrt = primitive_float_sqrt_rational::(&u); assert_eq!(NiceFloat(sqrt), NiceFloat(out)); if sqrt.is_normal() { let square = Rational::exact_from(sqrt).square(); match square.cmp(&u) { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt; next = next.next_higher(); assert!(Rational::exact_from(next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt; previous = previous.next_lower(); assert!(Rational::exact_from(previous).square() < u); } } } } test::("0", 0.0); test::("1", 1.0); test::("1/2", 0.70710677); test::("1/3", 0.57735026); test::("22/7", 1.7728106); test::("225", 15.0); test::("-1", f32::NAN); test::("-1/2", f32::NAN); test::("-1/3", f32::NAN); test::("-22/7", f32::NAN); test::("0", 0.0); test::("1", 1.0); test::("1/2", f64::consts::FRAC_1_SQRT_2); test::("1/3", 0.5773502691896257); test::("22/7", 1.7728105208558367); test::("225", 15.0); test::("-1", f64::NAN); test::("-1/2", f64::NAN); test::("-1/3", f64::NAN); test::("-22/7", f64::NAN); #[allow(clippy::needless_pass_by_value)] fn test_big(u: Rational, out: T) where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { let sqrt = primitive_float_sqrt_rational::(&u); assert_eq!(NiceFloat(sqrt), NiceFloat(out)); if sqrt.is_normal() { let square = Rational::exact_from(sqrt).square(); match square.cmp(&u) { Equal => assert_eq!(square, u), Less => { assert!(square < u); let mut next = sqrt; next = next.next_higher(); assert!(Rational::exact_from(next).square() > u); } Greater => { assert!(square > u); let mut previous = sqrt; previous = previous.next_lower(); assert!(Rational::exact_from(previous).square() < u); } } } } test_big::(Rational::power_of_2(1000i64), f32::INFINITY); test_big::(Rational::power_of_2(-1000i64), 0.0); test_big::(Rational::power_of_2(-290i64), 2.2e-44); test_big::(Rational::power_of_2(-200i64), 7.888609e-31); test_big::(Rational::power_of_2(10000i64), f64::INFINITY); test_big::(Rational::power_of_2(1000i64), 3.273390607896142e150); test_big::(Rational::power_of_2(-10000i64), 0.0); test_big::(Rational::power_of_2(-2100i64), 8.289046e-317); test_big::(Rational::power_of_2(-1000i64), 3.054936363499605e-151); } #[allow(clippy::needless_pass_by_value)] fn sqrt_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode, extreme: bool) { let (sqrt, o) = x.clone().sqrt_prec_round(prec, rm); assert!(sqrt.is_valid()); let (sqrt_alt, o_alt) = x.clone().sqrt_prec_round_ref(prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sqrt_prec_round_assign(prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt, rug_o) = rug_sqrt_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); } if x >= 0u32 && !x.is_negative_zero() { assert!(sqrt.is_sign_positive()); } if sqrt.is_normal() { assert_eq!(sqrt.get_prec(), Some(prec)); if x > 1u32 && o < Greater { assert!(sqrt < x); } else if x < 1u32 && o > Less { assert!(sqrt > x); } } if !extreme && x.is_normal() && sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, x), Less => { assert!(square < x); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } Greater => { assert!(square > x); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.sqrt_prec_round_ref(prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sqrt_prec_round_ref(prec, Exact)); } } #[test] fn sqrt_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_13().test_properties(|(x, prec, rm)| { sqrt_prec_round_properties_helper(x, prec, rm, false); }); float_unsigned_rounding_mode_triple_gen_var_14().test_properties(|(x, prec, rm)| { sqrt_prec_round_properties_helper(x, prec, rm, true); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { let (sqrt, o) = Float::NAN.sqrt_prec_round(prec, rm); assert!(sqrt.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.sqrt_prec_round(prec, rm), (Float::INFINITY, Equal) ); let (s, o) = Float::NEGATIVE_INFINITY.sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); let (s, o) = Float::ZERO.sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (s, o) = Float::NEGATIVE_ZERO.sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NEGATIVE_ZERO)); assert_eq!(o, Equal); assert_eq!( Float::ONE.sqrt_prec_round(prec, rm), (Float::one_prec(prec), Equal) ); let (s, o) = Float::NEGATIVE_ONE.sqrt_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn sqrt_prec_properties_helper(x: Float, prec: u64, extreme: bool) { let (sqrt, o) = x.clone().sqrt_prec(prec); assert!(sqrt.is_valid()); let (sqrt_alt, o_alt) = x.sqrt_prec_ref(prec); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sqrt_prec_assign(prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); let (rug_sqrt, rug_o) = rug_sqrt_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); let (sqrt_alt, o_alt) = x.sqrt_prec_round_ref(prec, Nearest); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); if x >= 0u32 && !x.is_negative_zero() { assert!(sqrt.is_sign_positive()); } if sqrt.is_normal() { assert_eq!(sqrt.get_prec(), Some(prec)); if x > 1u32 && o < Greater { assert!(sqrt < x); } else if x < 1u32 && o > Less { assert!(sqrt > x); } } if !extreme && x.is_normal() && sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, x), Less => { assert!(square < x); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } Greater => { assert!(square > x); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } } } #[test] fn sqrt_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { sqrt_prec_properties_helper(x, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { sqrt_prec_properties_helper(x, prec, false); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { sqrt_prec_properties_helper(x, prec, true); }); unsigned_gen_var_11().test_properties(|prec| { let (sqrt, o) = Float::NAN.sqrt_prec(prec); assert!(sqrt.is_nan()); assert_eq!(o, Equal); let (sqrt, o) = Float::ZERO.sqrt_prec(prec); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (sqrt, o) = Float::NEGATIVE_ZERO.sqrt_prec(prec); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NEGATIVE_ZERO)); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.sqrt_prec(prec), (Float::INFINITY, Equal)); let (sqrt, o) = Float::NEGATIVE_INFINITY.sqrt_prec(prec); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); assert_eq!(Float::ONE.sqrt_prec(prec), (Float::one_prec(prec), Equal)); let (sqrt, o) = Float::NEGATIVE_ONE.sqrt_prec(prec); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn sqrt_round_properties_helper(x: Float, rm: RoundingMode, extreme: bool) { let (sqrt, o) = x.clone().sqrt_round(rm); assert!(sqrt.is_valid()); let (sqrt_alt, o_alt) = x.sqrt_round_ref(rm); assert!(sqrt_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); let mut x_alt = x.clone(); let o_alt = x_alt.sqrt_round_assign(rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); let (sqrt_alt, o_alt) = x.sqrt_prec_round_ref(x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o_alt, o); if x >= 0u32 && !x.is_negative_zero() { assert!(sqrt.is_sign_positive()); } if sqrt.is_normal() { assert_eq!(sqrt.get_prec(), Some(x.get_prec().unwrap())); if x > 1u32 && o < Greater { assert!(sqrt < x); } else if x < 1u32 && o > Less { assert!(sqrt > x); } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt, rug_o) = rug_sqrt_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); assert_eq!(rug_o, o); } if !extreme && x.is_normal() && sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, x), Less => { assert!(square < x); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } Greater => { assert!(square > x); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = x.sqrt_round_ref(rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sqrt_round_ref(Exact)); } } #[test] fn sqrt_round_properties() { float_rounding_mode_pair_gen_var_24().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_25().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_26().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_27().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_28().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_29().test_properties(|(x, rm)| { sqrt_round_properties_helper(x, rm, true); }); rounding_mode_gen().test_properties(|rm| { let (sqrt, o) = Float::NAN.sqrt_round(rm); assert!(sqrt.is_nan()); assert_eq!(o, Equal); let (sqrt, o) = Float::ZERO.sqrt_round(rm); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (sqrt, o) = Float::NEGATIVE_ZERO.sqrt_round(rm); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NEGATIVE_ZERO)); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.sqrt_round(rm), (Float::INFINITY, Equal)); let (sqrt, o) = Float::NEGATIVE_INFINITY.sqrt_round(rm); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); assert_eq!(Float::ONE.sqrt_round(rm), (Float::ONE, Equal)); let (sqrt, o) = Float::NEGATIVE_ONE.sqrt_round(rm); assert_eq!(ComparableFloat(sqrt), ComparableFloat(Float::NAN)); assert_eq!(o, Equal); }); } #[allow(clippy::needless_pass_by_value)] fn sqrt_properties_helper_1(x: Float, extreme: bool) { let sqrt = x.clone().sqrt(); assert!(sqrt.is_valid()); let sqrt_alt = (&x).sqrt(); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); let mut x_alt = x.clone(); x_alt.sqrt_assign(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&sqrt)); let sqrt_alt = x.sqrt_prec_round_ref(x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); let sqrt_alt = x.sqrt_prec_ref(x.significant_bits()).0; assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); let sqrt_alt = x.sqrt_round_ref(Nearest).0; assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); if x >= 0u32 && !x.is_negative_zero() { assert!(sqrt.is_sign_positive()); } if !extreme && x.is_normal() && sqrt.is_normal() { assert_eq!(sqrt.get_prec(), Some(x.get_prec().unwrap())); let square = Rational::exact_from(&sqrt).square(); if square < x { let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } else if square > x { let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } let rug_sqrt = rug_sqrt(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt)), ComparableFloatRef(&sqrt), ); } #[allow(clippy::type_repetition_in_bounds)] fn sqrt_properties_helper_2() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { let sqrt_1 = x.sqrt(); let sqrt_2 = emulate_float_to_float_fn(Float::sqrt_prec, x); assert_eq!(NiceFloat(sqrt_1), NiceFloat(sqrt_2)); }); } #[test] fn sqrt_properties() { float_gen().test_properties(|x| { sqrt_properties_helper_1(x, false); }); float_gen_var_6().test_properties(|x| { sqrt_properties_helper_1(x, false); }); float_gen_var_7().test_properties(|x| { sqrt_properties_helper_1(x, false); }); float_gen_var_8().test_properties(|x| { sqrt_properties_helper_1(x, false); }); float_gen_var_11().test_properties(|x| { sqrt_properties_helper_1(x, false); }); float_gen_var_12().test_properties(|x| { sqrt_properties_helper_1(x, true); }); apply_fn_to_primitive_floats!(sqrt_properties_helper_2); } #[test] fn sqrt_rational_prec_properties() { rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (sqrt, o) = Float::sqrt_rational_prec(x.clone(), prec); assert!(sqrt.is_valid()); let (sqrt_alt, o_alt) = Float::sqrt_rational_prec_ref(&x, prec); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); let (sqrt_alt, o_alt) = Float::sqrt_rational_prec_round_ref(&x, prec, Nearest); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); let (sqrt_alt, o_alt) = sqrt_rational_prec_round_generic(&x, prec, Nearest); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); let (sqrt_alt, o_alt) = sqrt_rational_prec_round_simple(&x, prec, Nearest); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); if !sqrt.is_nan() { assert_eq!(sqrt.get_prec(), if x == 0u32 { None } else { Some(prec) }); } if x >= 0u32 { assert!(sqrt.is_sign_positive()); } if sqrt.is_normal() { if x > 1u32 && o < Greater { assert!(sqrt < x); } else if x < 1u32 && o > Less { assert!(sqrt > x); } let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, x), Less => { assert!(square < x); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } Greater => { assert!(square > x); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } } }); } #[test] fn sqrt_rational_prec_round_properties() { rational_unsigned_rounding_mode_triple_gen_var_3().test_properties(|(x, prec, rm)| { let (sqrt, o) = Float::sqrt_rational_prec_round(x.clone(), prec, rm); assert!(sqrt.is_valid()); let (sqrt_alt, o_alt) = Float::sqrt_rational_prec_round_ref(&x, prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); if !sqrt.is_nan() { match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } let (sqrt_alt, o_alt) = sqrt_rational_prec_round_generic(&x, prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); let (sqrt_alt, o_alt) = sqrt_rational_prec_round_simple(&x, prec, rm); assert!(sqrt_alt.is_valid()); assert_eq!(ComparableFloatRef(&sqrt_alt), ComparableFloatRef(&sqrt)); assert_eq!(o, o_alt); if !sqrt.is_nan() { assert_eq!(sqrt.get_prec(), if x == 0u32 { None } else { Some(prec) }); } if x >= 0u32 { assert!(sqrt.is_sign_positive()); } if sqrt.is_normal() { if x > 1u32 && o < Greater { assert!(sqrt < x); } else if x < 1u32 && o > Less { assert!(sqrt > x); } } if sqrt.is_normal() { let square = Rational::exact_from(&sqrt).square(); match o { Equal => assert_eq!(square, x), Less => { assert!(square < x); let mut next = sqrt.clone(); next.increment(); assert!(Rational::exact_from(&next).square() > x); } Greater => { assert!(square > x); let mut previous = sqrt.clone(); previous.decrement(); assert!(Rational::exact_from(&previous).square() < x); } } } if o == Equal { for rm in exhaustive_rounding_modes() { let (s, oo) = Float::sqrt_rational_prec_round_ref(&x, prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(sqrt.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(Float::sqrt_rational_prec_round_ref(&x, prec, Exact)); } }); // sqrt(3/5) is one of the simplest cases that doesn't reduce to sqrt or reciprocal_sqrt of a // Float const X: Rational = Rational::const_from_unsigneds(3, 5); test_constant( |prec, rm| Float::sqrt_rational_prec_round(X, prec, rm), 10000, ); } #[allow(clippy::type_repetition_in_bounds)] fn primitive_float_sqrt_rational_helper() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, Rational: ExactFrom, { rational_gen().test_properties(|x| { let sqrt = primitive_float_sqrt_rational::(&x); if sqrt.is_normal() { let square = Rational::exact_from(sqrt).square(); match square.cmp(&x) { Less => { assert!(Rational::exact_from(sqrt.next_higher()).square() > x); } Greater => { assert!(Rational::exact_from(sqrt.next_lower()).square() < x); } _ => {} } } }); rational_pair_gen().test_properties(|(x, y)| { let sqrt_x = NiceFloat(primitive_float_sqrt_rational::(&x)); let sqrt_y = NiceFloat(primitive_float_sqrt_rational::(&y)); if !sqrt_x.0.is_nan() && !sqrt_y.0.is_nan() { match x.partial_cmp(&y).unwrap() { Equal => assert_eq!(sqrt_x, sqrt_y), Less => assert!(sqrt_x <= sqrt_y), Greater => assert!(sqrt_x >= sqrt_y), } } }); } #[test] fn primitive_float_sqrt_rational_properties() { apply_fn_to_primitive_floats!(primitive_float_sqrt_rational_helper); } ================================================ FILE: malachite-float/tests/arithmetic/square.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{Square, SquareAssign}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ primitive_float_gen, rounding_mode_gen, unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_3, }; use malachite_float::emulate_float_to_float_fn; use malachite_float::test_util::arithmetic::square::{ rug_square, rug_square_prec, rug_square_prec_round, rug_square_round, square_prec_round_naive, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_6, float_gen_var_7, float_gen_var_8, float_gen_var_9, float_gen_var_10, float_gen_var_12, float_rounding_mode_pair_gen_var_7, float_rounding_mode_pair_gen_var_8, float_rounding_mode_pair_gen_var_9, float_rounding_mode_pair_gen_var_10, float_rounding_mode_pair_gen_var_11, float_rounding_mode_pair_gen_var_12, float_rounding_mode_pair_gen_var_22, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_2, float_unsigned_rounding_mode_triple_gen_var_11, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::platform::Limb; use malachite_q::Rational; use std::panic::catch_unwind; #[test] fn test_square() { let test = |s, s_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let square = x.clone().square(); assert!(square.is_valid()); assert_eq!(square.to_string(), out); assert_eq!(to_hex_string(&square), out_hex); let square_alt = (&x).square(); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); let mut square_alt = x.clone(); square_alt.square_assign(); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_square(&rug::Float::exact_from(&x)))), ComparableFloatRef(&square) ); let square_alt = square_prec_round_naive(x.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); }; test("NaN", "NaN", "NaN", "NaN"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "Infinity", "Infinity"); test("0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0"); test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); test("-1.0", "-0x1.0#1", "1.0", "0x1.0#1"); test( "1.0", "0x1.0000000000000000000000000#100", "1.0", "0x1.0000000000000000000000000#100", ); test( "-1.0", "-0x1.0000000000000000000000000#100", "1.0", "0x1.0000000000000000000000000#100", ); test("123.0", "0x7b.0#7", "1.51e4", "0x3.b0E+3#7"); test("-123.0", "-0x7b.0#7", "1.51e4", "0x3.b0E+3#7"); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "2.0000000000000004", "0x2.0000000000002#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "2.0000000000000004", "0x2.0000000000002#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "9.869604401089358", "0x9.de9e64df22ef0#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "9.869604401089358", "0x9.de9e64df22ef0#53", ); // - in square_float_significand_same_prec_lt_w // - decrement_exp in square_float_significand_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1"); // - !decrement_exp in square_float_significand_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_lt_w // - rm == Nearest in square_float_significand_same_prec_lt_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && square & shift_bit == 0)) in // square_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", "2.0", "0x2.0#2"); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && // !overflow in square_float_significand_same_prec_lt_w test("1.6", "0x1.a#4", "2.8", "0x2.c#4"); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && overflow // in square_float_significand_same_prec_lt_w test("1.414", "0x1.6a#8", "2.0", "0x2.00#8"); // - in square_float_significand_same_prec_w // - decrement_exp in square_float_significand_same_prec_w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_w // - rm == Nearest in square_float_significand_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in // square_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0000000000000000002", "0x1.0000000000000004#64", ); // - !decrement_exp in square_float_significand_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.odd()) && !overflow in // square_float_significand_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", "1.0712210262617041571e-73", "0x3.073e45e79ac604c4E-61#64", ); test( "1.9999999999999999999", "0x1.fffffffffffffffe#64", "3.9999999999999999996", "0x3.fffffffffffffff8#64", ); test( "1.9999999999999999998", "0x1.fffffffffffffffc#64", "3.9999999999999999991", "0x3.fffffffffffffff0#64", ); test( "1.4142135623730950488", "0x1.6a09e667f3bcc908#64", "1.9999999999999999999", "0x1.fffffffffffffffe#64", ); test( "1.4142135623730950489", "0x1.6a09e667f3bcc90a#64", "2.0000000000000000002", "0x2.0000000000000004#64", ); // - in square_float_significand_same_prec_gt_w_lt_2w // - lo.wrapping_add(2) & (mask >> 2) <= 2 in square_float_significand_same_prec_gt_w_lt_2w // - decrement_exp in square_float_significand_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest in square_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && (z_0 & shift_bit) == 0) in // square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.00000000000000000011", "0x1.0000000000000002#65", ); // - lo.wrapping_add(2) & (mask >> 2) > 2 in square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", "1.00000000000000000022", "0x1.0000000000000004#65", ); // - !decrement_exp in square_float_significand_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "2.0742001767277848782373298e56", "0x8.7590e74562e8c0aeed1d0E+46#85", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in square_float_significand_same_prec_gt_w_lt_2w test( "119368.6474438890389479272222539538", "0x1d248.a5bee1f96ad66a5061314f7#109", "14248873992.58347719172623084795998", "0x3514c9008.955ec2e06d13cb2d862#109", ); // - in square_float_significand_same_prec_gt_2w_lt_3w // - a0.wrapping_add(4) & (mask >> 2) <= 4 in square_float_significand_same_prec_gt_2w_lt_3w // - decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest in square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in // square_float_significand_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", ); // - a0.wrapping_add(4) & (mask >> 2) > 4 in square_float_significand_same_prec_gt_2w_lt_3w // - !decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "4.09688648907491713333499964381160220254051958e-58", "0x2.9258227caed7c4000630a1192a20211680c74E-48#149", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in // square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow // in square_float_significand_same_prec_gt_2w_lt_3w test( "4.9709672065181108960570410290811793724062284431352e-48", "0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165", "2.47105149682784709830100902225310999174453232836862e-95", "0x3.4c805dfa0982f9705aa6bbd6840b755493beef234E-79#165", ); test( "0.853553390593273762200422181052424519642417968844237018294169934497683119615526759712596\ 883581910393183753461557728074256231209013962684303161030374274983957853305666481876398188\ 949987625288195515142867527389992901492568633649215503682129354660222299652388082307621077\ 178580362709940650906998812851997421813349136582952207410155153814588098763686437571939990\ 432458893805084382964252838593650852124711790096724992674751203757636006947579113561955767\ 12323422965539514461577789916717825325390464224680930882212731621531237", "0x0.da827999fcef32422cbec4d9baa55f4f8eb7b05d449dd426768bd642c199cc8aa57e41821d5c5161d458f\ f37ee41ed9c87ba542f21ce3da53c02439b1efd13b469101743a1578fa72982ce3008de19bde558de488b4422c\ 523055e3917be2719e36ad451c5dbf4ee659531a198f9e426fa978907c1b72c1775525044c8206525409ca55b6\ c7e877efa69d01675e49f0621326d5e6a945b28dc679a0db7c11b6380826e00ff191a9799952f4fbded0f5ffb5\ 0df1fe5110983ef503120fbd540e160fe5eef517bee198c41c51757faf9d96927a53b1fd65c#1719", "0.728553390593273762200422181052424519642417968844237018294169934497683119615526759712596\ 883581910393183753461557728074256231209013962684303161030374274983957853305666481876398188\ 949987625288195515142867527389992901492568633649215503682129354660222299652388082307621077\ 178580362709940650906998812851997421813349136582952207410155153814588098763686437571939990\ 432458893805084382964252838593650852124711790096724992674751203757636006947579113561955767\ 12323422965539514461577789916717825325390464224680930882212731621531237", "0x0.ba827999fcef32422cbec4d9baa55f4f8eb7b05d449dd426768bd642c199cc8aa57e41821d5c5161d458f\ f37ee41ed9c87ba542f21ce3da53c02439b1efd13b469101743a1578fa72982ce3008de19bde558de488b4422c\ 523055e3917be2719e36ad451c5dbf4ee659531a198f9e426fa978907c1b72c1775525044c8206525409ca55b6\ c7e877efa69d01675e49f0621326d5e6a945b28dc679a0db7c11b6380826e00ff191a9799952f4fbded0f5ffb5\ 0df1fe5110983ef503120fbd540e160fe5eef517bee198c41c51757faf9d96927a53b1fd65c#1719", ); } #[test] fn test_square_prec() { let test = |s, s_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (square, o) = x.clone().square_prec(prec); assert!(square.is_valid()); assert_eq!(square.to_string(), out); assert_eq!(to_hex_string(&square), out_hex); assert_eq!(o, o_out); let (square_alt, o_alt) = x.square_prec_ref(prec); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); let mut square_alt = x.clone(); let o_alt = square_alt.square_prec_assign(prec); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", 1, "Infinity", "Infinity", Equal); test("-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal); test("0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 10, "1.0", "0x1.000#10", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, "1.0", "0x1.000#10", Equal, ); test("123.0", "0x7b.0#7", 1, "2.0e4", "0x4.0E+3#1", Greater); test("123.0", "0x7b.0#7", 10, "1.514e4", "0x3.b2E+3#10", Greater); test("-123.0", "-0x7b.0#7", 1, "2.0e4", "0x4.0E+3#1", Greater); test( "-123.0", "-0x7b.0#7", 10, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, "2.0", "0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, "2.0", "0x2.00#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, "2.0", "0x2.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, "2.0", "0x2.00#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "8.0", "0x8.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "9.88", "0x9.e0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "8.0", "0x8.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "9.88", "0x9.e0#10", Greater, ); // - in square_float_significands_general // - xs_len <= 2 in square_float_significands_general // - xs_len == 1 in square_float_significands_general // - !b1 first time in square_float_significands_general // - !goto_full_square second time in square_float_significands_general // - !increment_exp in square_float_significands_general test("1.0", "0x1.0#1", 2, "1.0", "0x1.0#2", Equal); // - b1 first time in square_float_significands_general test("1.5", "0x1.8#2", 1, "2.0", "0x2.0#1", Less); // - increment_exp in square_float_significands_general test("1.2", "0x1.4#3", 1, "2.0", "0x2.0#1", Greater); // - xs_len < 2 <= MPFR_SQR_THRESHOLD in square_float_significands_general // - goto_full_square second time in square_float_significands_general // - b1 third time in square_float_significands_general test( "0.000199046277632504184666664672269768242929310652018203552191617720205649", "0x0.000d0b7140b8f3aea60aad60c1dc3b2ee0d83e2eba33dcfb6f874df52d78#225", 26, "3.9619421e-8", "0xa.a2a038E-7#26", Less, ); // - xs_len == 2 in square_float_significands_general test( "330.3297903358337046735382484655688", "0x14a.546d23b2f14f71a1f4c12ddaa88#115", 45, "109117.770383317", "0x1aa3d.c537d75#45", Greater, ); // - !b1 third time in square_float_significands_general test( "88.32972592752556369746097031876493672699524930031683012093294198918", "0x58.5468eb1b5d957d68d5c161060f2abd3d11568e57fb44ace5b9530c#222", 41, "7802.140482433", "0x1e7a.23f6a82#41", Greater, ); // - xs_len > MPFR_SQR_THRESHOLD in square_float_significands_general // - xs[0] != 0 || xs[1] != 0 in square_float_significands_general // - out_prec <= p - 5 in square_float_significands_general // - !goto_full_square first time in square_float_significands_general // - in limbs_float_square_high // - k.is_none() in limbs_float_square_high // - b1 second time in square_float_significands_general // - can_round in square_float_significands_general test( "396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\ 869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\ 021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\ 355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\ 532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\ 840293409397442", "0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\ 89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\ 63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\ 91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\ c35bf6b0a8d1d636bb2afad1ab82c0#1539", 41, "157086.3684222", "0x2659e.5e50ea#41", Greater, ); // - !b1 second time in square_float_significands_general test( "0.289565969492664694638578202456729810638628879666435586140728331245058747654800231361781\ 733367215018660480916949243715433401890725345322341436886642908102373347900363371546861032\ 804628537167569586473086484745604528149555432827776527274466086199528238950727774219761110\ 278394595668030807862161516149163941956835588098749888947102946654461061159884953097421811\ 149735301912628233431116932895412543378996752139902311082164451547359831823770756258588441\ 392364079976282812844068282256919410425900496233045740740436555471195699615728406687884353\ 411870520651275282496307876556394549674324563102261561135259821040813150131202195032317605\ 601108576080171231347456850423368707704016287732147225807113778613580546356726188558446009\ 37667532705200099920676965417288103441", "0x0.4a20fed1016a521a64864d01138a193df1e23f2f35edd21912c8d7ea345216c5ec7c59aca3d2ce1378dd1\ 89d7419984353ecef1dc303caddc54cc6cf871a7d44df07922bfe75b3e27fa2ac58a45a2700c2b9d233b14afbe\ c4aeeed4683073d061d99c2f92084cbae1d1bf26f8fb2323910d590864daa5f4b534e0509ff60a7238357ab7ff\ 36bcc0024c64f4507f522e91df687d9649e2e609840feea945bd53cec1fec45c7ccee6ad51aacd8c59427836f6\ 871c316bc3ba008d00a81638ec6c5630fafa1ebe3c492a94c04c96f772e57d74f808872161bf166402ea4e9dd0\ 42397a51a2e1ffd33b8865cca279beaaf61c288bdc67dceb9e84f124abd1c1016bfc1d67e916ef24dc5a541f8c\ e0888c25325a3955899b701e5035429c76e90b7de02973eaa08674d6315156df3c4afdd962afc0b2fb855c12c7\ cb#2507", 41, "0.08384845068821", "0x0.1577179186b#41", Less, ); // - k == Some(0) in limbs_float_square_high // - in limbs_float_square_high_basecase test( "2.534905093269173913399961419051078001207362536676304036217117050023406987769089211085345\ 845282321276763762108762278121117963061716139888836603176571082592497694546991532956806762\ 060078393566599448512584861538013806584451166069797239642908909634341260487656925769615819\ 575456879212968568058838065343005029399246396366977778814769813140337173953816940118229696\ 975910769633258534685767958638383299293048391708530965415961893726949253541358150164947850\ 354131943712963257075685505691799739914956071583726713409225265256065457404089250831362505\ 964054898560581202320837085103659819920563909237065863856674551755094031141043600118470396\ 110548066038755307598657006758419658655479386061317383935495778887020750969220495044500181\ 502836698351684979845272389537925642124685759621079734656489541651071700522564930994999675\ 548215393164945318735677787876975365012973524228071379171196099071790619084107585184183873\ 649229987470512431316532998401599147457982188040992886626796443210441148620644905909977484\ 092106548023293796713001951271606863906640116960398160889963208431853184379130926702446309\ 16665296291511e-18", "0x2.ec2c037afc439f03a036777b3b49c929652bc0198062ee846d167a89e9a1b649beaab8e3935d29165383b\ 8032ab14cd30954f6e10277bf2adbaa3dc7f4af85aa6a3dfe37f0afee4bafa862c5d97d6b0ad6fe3a473f086a0\ d78eaa4db0710879d93d26ada2de74e4133838c88fda61bf559b836a376e2ece72417c51fff1870b23e21aa228\ c6b132e5b2dea393b782ddc27593a878aec5ddd0254c2fe5515f3036b02fc8ab225f7433c0e931717894c1f581\ 86927d1a1d3ae8a8d5a52d6ffd5bb9a6f1d8c55f9c54d16411a5a7a6bf1616d3eaf4692379eb81ba2b11179269\ 987c75a403cd7845851b66bf9758892745e79ac67a6a8feb7dcdcb16690d8fae58f96bc20e8495bdee03ef7ad7\ d1821419ec1bfe2bb5b49cbfcab0f7a3523939693c97830d3c6e027badb91529d6076972fcea0ace6d83b34f64\ 0da99faaa4862efc02a02d3a5066111bfc08e28a6b55ff9e7c245b0232f0a85e97a68fa69e8d218bce6abe990a\ 2e0b503cf831ad5df31caba8915c38bad1cc785b9e99b3bb855801ec29ad43668762f37f228f77bf7a8590649f\ 937d5dc5039a46479d0dac0be7aa72929e8868980b3f76831bf434c15ba83ba74394414959b1c8bc010f735a6c\ 14c8b93afc80E-15#3627", 423, "6.425743831881999297033060889967219634391598848272085805147756300415778053639020164208035\ 3509860715112301888671841760135704785647e-36", "0x8.8a913be7e47dfd7ad8403512f1a0ee8d3fad7395038c39eb4039b4703fdcd0314b45e761b67375d18eb58\ ced237cd5fd6c79c02dcE-30#423", Less, ); // - xs[0] == 0 && xs[1] == 0 in square_float_significands_general test( "511.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999858969189385560189369588899908301051658131815921691396545986807150339147015462\ 016914098983479659782731543057846003175884332840513803623318182318832820724717407320371823\ 6294395745915856", "0x1ff.fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000#1539", 45, "262144.0", "0x40000.0000000#45", Greater, ); // - !can_round in square_float_significands_general test( "5070602400912917605986812821504.000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000072282982868771681166004491412846722101397844122267684138688870467552820474559090102317\ 447234871538375909335604136421707865093288809202542467085297095776399695369977155046440218\ 72699461509694558652328992590065121835881232", "0x40000000000000000000000000.000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffe#2230", 75, "2.5711008708143844408671e61", "0x1.0000000000000000000E+51#75", Less, ); // - k != None && k != Some(0) && len <= SQR_FFT_THRESHOLD in limbs_float_square_high test( "396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\ 869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\ 021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\ 355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\ 532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\ 840293409397442", "0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\ 89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\ 63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\ 91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\ c35bf6b0a8d1d636bb2afad1ab82c0#1539", 1000, "157086.3684220939290392835990654860444953123468682922432646919273797192952403374080185049\ 441414358725029167080302705853255170809678818388441806686518494713508728113056316939955366\ 580321349638671885788642336442940811575310873763709312578497006621517503935000405848895060\ 9190911436529068384755172193385643", "0x2659e.5e50e90c8c8f731b6ec42e31ac581c6d5c6e7051268a54ce30dbe17faafc9ad4523be4827db001d48\ 8a322a36c3d610868daa74b44da3bd6945b467643769f500a263ca6634a2786c8e089cd305b177ffba7d9cf923\ 74c0483fa9a736b452c7e65bfe13f1fbababe9090e56a0abfa7e4982915fe0dff247e8378e8#1000", Greater, ); // - out_prec > p - 5 in square_float_significands_general // - out_prec > p - 5 + Limb::WIDTH || xs_len <= MPFR_SQR_THRESHOLD + 1 in // square_float_significands_general // - goto_full_square first time in square_float_significands_general test( "396.3412272551190567593891335756570564001425784787446073953740531440207891605323131867948\ 869355406520857599475406495997289490143735096829625551391579153111055037678989978858579586\ 021105696471344997604889396207883425571313379937012790014662248134632025438319010426957144\ 355546486040271820495868974546882981476343977667254209899704548500299738343700283443799494\ 532151589935402512791651191411866655264587358069356924819557816073395721436815590916015139\ 840293409397442", "0x18c.575aab5d3d7d931fe7b1df9a17c5180eb11799ddcdb0b514b818c68be091c380b4f49e26c6357fc5521\ 89c83f7fb1af51d3ad56a7621351488217dec257419292d332960be3dcbdbf0989c56e4cc82fcee123ce6c00b8\ 63f9e45062bf3fbae296936b2ab5e3779905657246488ffaf88040c9e3456d8e0dcb25c0b55feba5452509320e\ 91f9be5ce584d555f8c77c79aeec4f5bb5aff76c235d04d87f5adafe9a729dccc5692f11d14f4aeeec72b2dc3e\ c35bf6b0a8d1d636bb2afad1ab82c0#1539", 5000, "157086.3684220939290392835990654860444953123468682922432646919273797192952403374080185049\ 441414358725029167080302705853255170809678818388441806686518494713508728113056316939955366\ 580321349638671885788642336442940811575310873763709312578497006621517503935000405848895060\ 919091143652906838475517219338564216871512733323414114900025582889108770319888495423472591\ 622217081406162593383439817010743870950284355953948594596501930134914144626602460886577742\ 699397445023366416628676609358289067494944516044161793867980863078877928160882497479870173\ 995550846564918220947311792283316244784987871826325087158139795457567671300755416634197565\ 825272103067497350477832613308006740370014538444363794113999101665422314265225122590389544\ 388555686073293478850435707082986891289816937189501867266947100104879700862539689861260203\ 303222356049565246944094013202651746222554947384760413370539804854333289940364855469937239\ 014120251649267431651939212811005766277308077834857972931251756411522886575455852040387255\ 586633599190053514685721006798676467868675709844997689304699851005119605477859913661835009\ 980047325267722717984269099465289430789912767924820742466247451598658072993390431860927262\ 510441796888642732252820490424273307195428579227975601954580861122408746440602416210603394\ 010320119854126656872002234654813295901729990426282838623889803078731960696692381273900064\ 363258066357675869791572233715232583553618635258761844046010323346239050118033120274686587\ 47626978436794438933236478602171106153180118157402691906229607357337", "0x2659e.5e50e90c8c8f731b6ec42e31ac581c6d5c6e7051268a54ce30dbe17faafc9ad4523be4827db001d48\ 8a322a36c3d610868daa74b44da3bd6945b467643769f500a263ca6634a2786c8e089cd305b177ffba7d9cf923\ 74c0483fa9a736b452c7e65bfe13f1fbababe9090e56a0abfa7e4982915fe0dff247e8378e637c71563f40ac88\ bff59ccb63d55f07b40f44324086d33c752ca2a398f8021f9ab7e61160ce80b0eb4d350cfcb2745c0ffb94a7ea\ c2a42031e1d67c39dabea5ed0ed1839b3cb19c95afad38ff4d85fe726701b1400759bff428fc5d441579646a9a\ edbda6e96c39642ea5102dcc1744e2f22bc2669606b02248465eda50f7ab00888fe70cd5b94c6886478a9d89d4\ 721fd315aae640835a05a2ac14cf927011012c9a0b12526c935c3b86e035f9369aa246b7f864ac313401679f2d\ 585686dd60ca3610690fc6e131d703a07afa9f50e1c62593876e5dfcd53a06dfc5c84a2d7c8129428f50ff8669\ 462d4cbbacfe9e72bf3cd17875fb28dd45607447a1bdd656f47900000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ #5000", Equal, ); // - out_prec <= p - 5 + Limb::WIDTH && xs_len > MPFR_SQR_THRESHOLD + 1 in // square_float_significands_general // - xs_len <= len in square_float_significands_general // - k < twice_len in square_float_significands_general test( "70459532516206275717738.24583571192785940804485220379113093012216854237552273164629839052\ 295542459627091867686732592292054910255896821543632944963319945361030770270423888774548519\ 352455933682416235026529894320254192088358055829902767990508592251676851896653974385735963\ 818455173075208105139936148350808080166279329650970874228499292765775926866402018763767601\ 932631118142152227916465948527446827475834919059052275938611139784416871828297279794775881\ 754156488112402263366312959738244152841157181731104967167515387928211427131697792191239671\ 200062974233522321766736844717284659803787329075216256925936831334895804054605134987158729\ 635284806758566129642530508638215601547746106827192539740893000302521313674983124372016914\ 389464631779788838617640381788549537988633853246170604449289457144019599904363663940307935\ 010893280729695200089400652615175194820160750890242280186267733830422108880046398617008039\ 346196610860314292217862221940568925947020858793049858538542201667012791629444317697230994\ 497432161328637397726885087365856366871387393212442806903408576734184446519785519751530501\ 203958503763892329891980999384336300765212927244594343049091702158556853491733512332595607\ 980340866258213963813028256778277899307861580399445091884912999955742998432553541817046928\ 089178846440489676733765036119262237349966327782496860922729317780078565098542288671006633\ 263750319390117261972206095532634412489779996284041680459224965604552001326514848875913522\ 75401658328725688546699002488305760364795486416541", "0xeeb9e70f8e3103fea6a.3eef16d6eb45c3a998fb982ebe639fc8759b70c44fe5810571a8155bfb031e4bc24\ 7dda5a8581f5ab0434d47c9eb35f6a9fb469e23b989044db9aefcec6a8d1de5bf14332cc4bb1bc75c32a4e36cc\ f907a5658e025a6f217cb147f7a8ce671eee07c655ecbe2598eb280ca4d26207f6c1e55ed67b66c69d289c56d3\ 4f2d2b25f411c0b9e4696d67a2ebe0b5716309bb26e24a3cc52943382e8956c46f600932e74aed277d50d0b801\ d8cdf51e8d20373cc3c14623e93446643f969b662cd3d7da7f3f840246325c873da49be886e93a9f2b9debb19d\ 6b28dc9e7e168f16ac806d56ffbeb1836aff27be850217d6311ab97d9742412187d3ecde0f7d4a0c89c6b46c37\ 610de9e5d478f868be38875f5c45f683618305161b4a1e6811cc1c53c2798dddbe1daba42c542637900cae7fe8\ 7cb8178a8825ae05ae6c791d728ab540947bc63fcb32f5af0d89b211e00aa940c8ccb7aa1ff76a1590b970f2c4\ 010fddbeb773600a0bd98bc005244e5ce6bf94d6ff4be6c4ddaffe2d3f89ae99eb2b79591c994977331c5caa40\ d57d28f6fa0bd1458390ffd906d84e849964bf2c3afb5fa3e251d60fb42251182bc006f0da82dd32c5877d3183\ b771fa955b64fe611c8a57edf9070898139a48e93a9f7cf1bc280142a0c900175e97125e4dba6cd579985765eb\ ea2bf0ecfb3754e8373897fd5f3fbdd8a04c429f1eb274d27b90c5ba4cdc5221ee37d3885cc6b8a0745a21d803\ 9a0571a0a77248c1a21338919b63ada2c014b8d1864ad65dc80551ded9cd5e048f7a262866d51e252ee527629b\ 0628f7561340ddc20398c57d6f3159cec6f4979a02c5610d3743e31aa8993d652c6ea0#4942", 5000, "4964545722402329471538520890548020778505727316.714928212970963455240096184214428743957383\ 329922752233199764049780878042702316184608300084915002665385500366536453418018453492928341\ 017054541630873437214644149654854522755654366831843415669733075028381314388954345055868246\ 000218989221937469258574896624097067887464348708304868331849053151758619452575265628276389\ 682599022898309226512794404632814475266579950972366209872195059885305874209009896969746959\ 550374594439111632193759127250892146888326838744623554050318490109344201586718804154701606\ 966010758459087950191998865560033257935278780535428646473292047088396527777426223171234483\ 188009004262125992356660280897524089496628310376755558332111429032108512629018171093951768\ 666071288536225840334502196980458876275123956423686107784807652541652782835788006847858977\ 993995691507283189780038044528425354524130033815262491772309833202212299992561581175232232\ 053665702559586771762340461465421956694347639348699503880840804336286789065206696824702252\ 001401065405887247144705146834255039213991488108844897575368853688286293567906566377054487\ 855713514655373784168449710429759002204390811345191073301339247358231849563161226052987665\ 594985477181835691490984499872892234197121121888658800164578709448237427211277623000068159\ 736988165669283234595563391379976241167126662466254710156731663896405093320111508971147717\ 596133787650005180714732054756611220213766696881623761124569357842183971615077248468826825\ 78028047188611500722085706480035062367867718429318751607371955873121", "0xde9e30a0b16bb9d3b1d41b9ca941523105ed54.b705890db2b0d9f3e32b9f103e1b83c7f9edba5c1f4e2af3\ adeb66de82892d7410e07fd6532bc0baf1535d9dfdf455d02d7b3cdcd6b683dd9909ef54c1c3138d14f10d53ef\ a61999322d530e26efcb69e290c671098fb49bb695602d0e25cb7d993dc249014fc873b17a61bb8c9a878cb42e\ f205fa6138dbfc05bd5c65440690ca6b0054108cab3099860992a8d16ad6797a10fba9af26f477b820e5a0499c\ bf71480aff1edfd22ad78810350210eae0cec2b5d0248df96b630be8372423d110cdd49422b85db636542c44ca\ d9c82a307aaeb2d1795d93184dd19dc0e3bd6c9cdc631fe51a88f0a178def01f6ae41386a6563a14613e79ab7d\ b81b5373a481694455cc8778c037bd3a3c6e2b7a0f448025095104d91359860535455349496f70c9ca535c3e69\ 8563c5e868485868fb51e33f09ed11186e72d4c6b2ce9f4b7629a78b907f198ac6cdde2f6642df2b1c9737ce1a\ 48ac426a8d401ef2aa8acbd3185bfd87dc282064adc7145f4dc07a12d6b35f38fb04eb2c4da98e45b7287d9982\ 2aea6ee0f4d2b8771272e2f4e9d0afb433896b20f842155ae13c2df308b254065539842f8cb05363f97ef29bbb\ 6b1fd5ac471efcf6cd026fe29de50b9a08d5e4610e95cba281a1006f876c351b4b8c381caf1f9f849a3ad17f6b\ fed7e727b78c97f11622da2ae8fd3c5759f030ea2800bd1d267f019d2292f18d7360d036e88707bbd93901fda7\ c8fa8cfeeb7aca62069cec0809ae3add2dfdbffa773246c8ae9749ac6c8b0cced5911da8050ea0171f866099b7\ 44d3739341181361c2df7c3d9320134683888ed78e4d80fc191958b201777943c0cac9c3c082a01b24d3#5000", Less, ); } #[test] fn square_prec_fail() { assert_panic!(Float::NAN.square_prec(0)); assert_panic!(Float::NAN.square_prec_ref(0)); assert_panic!({ let mut x = Float::NAN; x.square_prec_assign(0) }); } #[test] fn test_square_round() { let test = |s, s_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (square, o) = x.clone().square_round(rm); assert!(square.is_valid()); assert_eq!(square.to_string(), out); assert_eq!(to_hex_string(&square), out_hex); assert_eq!(o, o_out); let (square_alt, o_alt) = x.square_round_ref(rm); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); let mut square_alt = x.clone(); let o_alt = square_alt.square_round_assign(rm); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); } let (square_alt, o_alt) = square_prec_round_naive(x.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); }; test("NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", Exact, "NaN", "NaN", Equal); test("Infinity", "Infinity", Floor, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Down, "Infinity", "Infinity", Equal); test("Infinity", "Infinity", Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", Nearest, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", Exact, "Infinity", "Infinity", Equal); test( "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test("-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal); test( "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Floor, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Ceiling, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Down, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Up, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", Exact, "1.0", "0x1.0#1", Equal); test( "1.0", "0x1.0000000000000000000000000#100", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test("123.0", "0x7b.0#7", Floor, "1.51e4", "0x3.b0E+3#7", Less); test( "123.0", "0x7b.0#7", Ceiling, "1.52e4", "0x3.b8E+3#7", Greater, ); test("123.0", "0x7b.0#7", Down, "1.51e4", "0x3.b0E+3#7", Less); test("123.0", "0x7b.0#7", Up, "1.52e4", "0x3.b8E+3#7", Greater); test("123.0", "0x7b.0#7", Nearest, "1.51e4", "0x3.b0E+3#7", Less); test("-123.0", "-0x7b.0#7", Floor, "1.51e4", "0x3.b0E+3#7", Less); test( "-123.0", "-0x7b.0#7", Ceiling, "1.52e4", "0x3.b8E+3#7", Greater, ); test("-123.0", "-0x7b.0#7", Down, "1.51e4", "0x3.b0E+3#7", Less); test("-123.0", "-0x7b.0#7", Up, "1.52e4", "0x3.b8E+3#7", Greater); test( "-123.0", "-0x7b.0#7", Nearest, "1.51e4", "0x3.b0E+3#7", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Floor, "2.0", "0x2.0000000000000#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Ceiling, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Down, "2.0", "0x2.0000000000000#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Up, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Nearest, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Floor, "2.0", "0x2.0000000000000#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Ceiling, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Down, "2.0", "0x2.0000000000000#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Up, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Nearest, "2.0000000000000004", "0x2.0000000000002#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "9.869604401089356", "0x9.de9e64df22ee8#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "9.869604401089356", "0x9.de9e64df22ee8#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "9.869604401089356", "0x9.de9e64df22ee8#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "9.869604401089356", "0x9.de9e64df22ee8#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "9.869604401089358", "0x9.de9e64df22ef0#53", Greater, ); // - rm == Floor || rm == Down in square_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Down, "2.0", "0x2.0#2", Less); // - rm == Ceiling || rm == Up in square_float_significand_same_prec_lt_w // - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Up, "3.0", "0x3.0#2", Greater); // - (rm == Ceiling || rm == Up) && overflow in square_float_significand_same_prec_lt_w test("1.4", "0x1.6#4", Up, "2.0", "0x2.0#4", Greater); // - rm == Floor || rm == Down in square_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Down, "1.0000000000000000002", "0x1.0000000000000004#64", Less, ); // - rm == Ceiling || rm == Up in square_float_significand_same_prec_w // - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Up, "1.0000000000000000003", "0x1.0000000000000006#64", Greater, ); // - rm == Floor || rm == Down in square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Down, "1.00000000000000000011", "0x1.0000000000000002#65", Less, ); // - rm == Ceiling || rm == Up in square_float_significand_same_prec_gt_w_lt_2w // - (rm == Ceiling || rm == Up) && !overflow in square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Up, "1.00000000000000000016", "0x1.0000000000000003#65", Greater, ); // - rm == Floor || rm == Down in square_float_significand_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Down, "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", Less, ); // - rm == Ceiling || rm == Up in square_float_significand_same_prec_gt_2w_lt_3w // - (rm == Floor || rm == Down) && !overflow in square_float_significand_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Up, "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", Greater, ); // - in square_float_significand_same_prec_lt_w // - decrement_exp in square_float_significand_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_lt_w test("1.0", "0x1.0#1", Nearest, "1.0", "0x1.0#1", Equal); // - !decrement_exp in square_float_significand_same_prec_lt_w // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_lt_w // - rm == Nearest in square_float_significand_same_prec_lt_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && square & shift_bit == 0)) in // square_float_significand_same_prec_lt_w test("1.5", "0x1.8#2", Nearest, "2.0", "0x2.0#2", Less); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && // !overflow in square_float_significand_same_prec_lt_w test("1.6", "0x1.a#4", Nearest, "2.8", "0x2.c#4", Greater); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || square & shift_bit != 0) && overflow // in square_float_significand_same_prec_lt_w test("1.414", "0x1.6a#8", Nearest, "2.0", "0x2.00#8", Greater); // - in square_float_significand_same_prec_w // - decrement_exp in square_float_significand_same_prec_w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_w test( "1.0", "0x1.0000000000000000#64", Nearest, "1.0", "0x1.0000000000000000#64", Equal, ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_w // - rm == Nearest in square_float_significand_same_prec_w // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && product.even())) in // square_float_significand_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "1.0000000000000000002", "0x1.0000000000000004#64", Less, ); // - !decrement_exp in square_float_significand_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || product.odd()) && !overflow in // square_float_significand_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", Nearest, "1.0712210262617041571e-73", "0x3.073e45e79ac604c4E-61#64", Greater, ); test( "1.9999999999999999999", "0x1.fffffffffffffffe#64", Nearest, "3.9999999999999999996", "0x3.fffffffffffffff8#64", Less, ); test( "1.9999999999999999998", "0x1.fffffffffffffffc#64", Nearest, "3.9999999999999999991", "0x3.fffffffffffffff0#64", Less, ); test( "1.4142135623730950488", "0x1.6a09e667f3bcc908#64", Nearest, "1.9999999999999999999", "0x1.fffffffffffffffe#64", Less, ); test( "1.4142135623730950489", "0x1.6a09e667f3bcc90a#64", Nearest, "2.0000000000000000002", "0x2.0000000000000004#64", Greater, ); // - in square_float_significand_same_prec_gt_w_lt_2w // - lo.wrapping_add(2) & (mask >> 2) <= 2 in square_float_significand_same_prec_gt_w_lt_2w // - decrement_exp in square_float_significand_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", Nearest, "1.0", "0x1.0000000000000000#65", Equal, ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest in square_float_significand_same_prec_gt_w_lt_2w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && (z_0 & shift_bit) == 0) in // square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "1.00000000000000000011", "0x1.0000000000000002#65", Less, ); // - lo.wrapping_add(2) & (mask >> 2) > 2 in square_float_significand_same_prec_gt_w_lt_2w test( "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "1.00000000000000000022", "0x1.0000000000000004#65", Less, ); // - !decrement_exp in square_float_significand_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Nearest, "2.0742001767277848782373298e56", "0x8.7590e74562e8c0aeed1d0E+46#85", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (z_0 & shift_bit) != 0) && !overflow // in square_float_significand_same_prec_gt_w_lt_2w test( "119368.6474438890389479272222539538", "0x1d248.a5bee1f96ad66a5061314f7#109", Nearest, "14248873992.58347719172623084795998", "0x3514c9008.955ec2e06d13cb2d862#109", Greater, ); // - in square_float_significand_same_prec_gt_2w_lt_3w // - a0.wrapping_add(4) & (mask >> 2) <= 4 in square_float_significand_same_prec_gt_2w_lt_3w // - decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in square_float_significand_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "1.0", "0x1.00000000000000000000000000000000#129", Equal, ); // - round_bit != 0 || sticky_bit != 0 in square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest in square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest && (round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0) in // square_float_significand_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", Less, ); // - a0.wrapping_add(4) & (mask >> 2) > 4 in square_float_significand_same_prec_gt_2w_lt_3w // - !decrement_exp in square_float_significand_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", Nearest, "4.09688648907491713333499964381160220254051958e-58", "0x2.9258227caed7c4000630a1192a20211680c74E-48#149", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) in // square_float_significand_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || z_0 & shift_bit != 0) && !overflow // in square_float_significand_same_prec_gt_2w_lt_3w test( "4.9709672065181108960570410290811793724062284431352e-48", "0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165", Nearest, "2.47105149682784709830100902225310999174453232836862e-95", "0x3.4c805dfa0982f9705aa6bbd6840b755493beef234E-79#165", Greater, ); // - twice_exp - 1 > Float::MAX_EXPONENT // - twice_exp - 1 > Float::MAX_EXPONENT && rm == Floor | Down test( "too_big", "0x4.0E+268435455#1", Down, "too_big", "0x4.0E+268435455#1", Less, ); // - twice_exp - 1 > Float::MAX_EXPONENT && rm == Ceiling | Up | Nearest test( "too_big", "0x4.0E+268435455#1", Up, "Infinity", "Infinity", Greater, ); // - exp > Float::MAX_EXPONENT // - exp > Float::MAX_EXPONENT && rm == Floor | Down test( "too_big", "0xc.0E+134217727#2", Down, "too_big", "0x6.0E+268435455#2", Less, ); // - exp > Float::MAX_EXPONENT && rm == Ceiling | Up | Nearest test( "too_big", "0xc.0E+134217727#2", Up, "Infinity", "Infinity", Greater, ); // - twice_exp < Float::MIN_EXPONENT - 1 // - twice_exp < Float::MIN_EXPONENT - 1 && rm == Floor | Down | Nearest test( "too_small", "0x1.0E-268435456#1", Down, "0.0", "0x0.0", Less, ); // - twice_exp < Float::MIN_EXPONENT - 1 && rm == Ceiling | Up test( "too_small", "0x1.0E-268435456#1", Up, "too_small", "0x1.0E-268435456#1", Greater, ); // - exp < Float::MIN_EXPONENT // - exp < Float::MIN_EXPONENT no special // - exp < Float::MIN_EXPONENT no special && rm == Floor | Down | Nearest test( "too_small", "0x8.0E-134217729#1", Down, "0.0", "0x0.0", Less, ); // - exp < Float::MIN_EXPONENT no special && rm == Ceiling | Up test( "too_small", "0x8.0E-134217729#1", Up, "too_small", "0x1.0E-268435456#1", Greater, ); // - exp < Float::MIN_EXPONENT special test( "too_small", "0xc.0E-134217729#2", Nearest, "too_small", "0x1.0E-268435456#2", Greater, ); } #[test] fn square_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(THREE.square_round(Exact)); assert_panic!(THREE.square_round_ref(Exact)); assert_panic!({ let mut x = THREE; x.square_round_assign(Exact); }); } #[test] fn test_square_prec_round() { let test = |s, s_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (square, o) = x.clone().square_prec_round(prec, rm); assert!(square.is_valid()); assert_eq!(square.to_string(), out); assert_eq!(to_hex_string(&square), out_hex); assert_eq!(o, o_out); let (square_alt, o_alt) = x.square_prec_round_ref(prec, rm); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); let mut square_alt = x.clone(); let o_alt = square_alt.square_prec_round_assign(prec, rm); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square), ComparableFloatRef(&square_alt)); assert_eq!(o_alt, o_out); let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test("Infinity", "Infinity", 1, Up, "Infinity", "Infinity", Equal); test( "Infinity", "Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test("0.0", "0x0.0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1.0", "0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1.0", "0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 1, Floor, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Down, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Up, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 1, Exact, "1.0", "0x1.0#1", Equal); test("-1.0", "-0x1.0#1", 10, Floor, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Down, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Up, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("-1.0", "-0x1.0#1", 10, Exact, "1.0", "0x1.000#10", Equal); test( "1.0", "0x1.0000000000000000000000000#100", 1, Floor, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Down, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Up, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 1, Exact, "1.0", "0x1.0#1", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "1.0", "0x1.0000000000000000000000000#100", 10, Exact, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Floor, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Ceiling, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Down, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Up, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Nearest, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 1, Exact, "1.0", "0x1.0#1", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Floor, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Ceiling, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Down, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Up, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Nearest, "1.0", "0x1.000#10", Equal, ); test( "-1.0", "-0x1.0000000000000000000000000#100", 10, Exact, "1.0", "0x1.000#10", Equal, ); test("123.0", "0x7b.0#7", 1, Floor, "8.0e3", "0x2.0E+3#1", Less); test( "123.0", "0x7b.0#7", 1, Ceiling, "2.0e4", "0x4.0E+3#1", Greater, ); test("123.0", "0x7b.0#7", 1, Down, "8.0e3", "0x2.0E+3#1", Less); test("123.0", "0x7b.0#7", 1, Up, "2.0e4", "0x4.0E+3#1", Greater); test( "123.0", "0x7b.0#7", 1, Nearest, "2.0e4", "0x4.0E+3#1", Greater, ); test( "123.0", "0x7b.0#7", 10, Floor, "1.512e4", "0x3.b1E+3#10", Less, ); test( "123.0", "0x7b.0#7", 10, Ceiling, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "123.0", "0x7b.0#7", 10, Down, "1.512e4", "0x3.b1E+3#10", Less, ); test( "123.0", "0x7b.0#7", 10, Up, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "123.0", "0x7b.0#7", 10, Nearest, "1.514e4", "0x3.b2E+3#10", Greater, ); test("-123.0", "-0x7b.0#7", 1, Floor, "8.0e3", "0x2.0E+3#1", Less); test( "-123.0", "-0x7b.0#7", 1, Ceiling, "2.0e4", "0x4.0E+3#1", Greater, ); test("-123.0", "-0x7b.0#7", 1, Down, "8.0e3", "0x2.0E+3#1", Less); test("-123.0", "-0x7b.0#7", 1, Up, "2.0e4", "0x4.0E+3#1", Greater); test( "-123.0", "-0x7b.0#7", 1, Nearest, "2.0e4", "0x4.0E+3#1", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Floor, "1.512e4", "0x3.b1E+3#10", Less, ); test( "-123.0", "-0x7b.0#7", 10, Ceiling, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Down, "1.512e4", "0x3.b1E+3#10", Less, ); test( "-123.0", "-0x7b.0#7", 10, Up, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "-123.0", "-0x7b.0#7", 10, Nearest, "1.514e4", "0x3.b2E+3#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Nearest, "2.0", "0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Floor, "2.0", "0x2.00#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Ceiling, "2.004", "0x2.01#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Down, "2.0", "0x2.00#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Up, "2.004", "0x2.01#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, Nearest, "2.0", "0x2.00#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Down, "2.0", "0x2.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Nearest, "2.0", "0x2.0#1", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Floor, "2.0", "0x2.00#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Ceiling, "2.004", "0x2.01#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Down, "2.0", "0x2.00#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Up, "2.004", "0x2.01#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, Nearest, "2.0", "0x2.00#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Floor, "8.0", "0x8.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Ceiling, "2.0e1", "0x1.0E+1#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Down, "8.0", "0x8.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Up, "2.0e1", "0x1.0E+1#1", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Nearest, "8.0", "0x8.0#1", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "9.86", "0x9.dc#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "9.88", "0x9.e0#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "9.86", "0x9.dc#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "9.88", "0x9.e0#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "9.88", "0x9.e0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Floor, "8.0", "0x8.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Ceiling, "2.0e1", "0x1.0E+1#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Down, "8.0", "0x8.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Up, "2.0e1", "0x1.0E+1#1", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Nearest, "8.0", "0x8.0#1", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "9.86", "0x9.dc#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "9.88", "0x9.e0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "9.86", "0x9.dc#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "9.88", "0x9.e0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "9.88", "0x9.e0#10", Greater, ); } #[test] fn square_prec_round_fail() { const THREE: Float = Float::const_from_unsigned(3); assert_panic!(Float::one_prec(1).square_prec_round(0, Floor)); assert_panic!(Float::one_prec(1).square_prec_round_ref(0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.square_prec_round_assign(0, Floor) }); assert_panic!(THREE.square_prec_round(1, Exact)); assert_panic!(THREE.square_prec_round_ref(1, Exact)); assert_panic!({ let mut x = THREE; x.square_prec_round_assign(1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn square_prec_round_properties_helper(x: Float, prec: u64, rm: RoundingMode, extreme: bool) { let (square, o) = x.clone().square_prec_round(prec, rm); assert!(square.is_valid()); let (square_alt, o_alt) = x.clone().square_prec_round_ref(prec, rm); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.square_prec_round_assign(prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if !extreme { let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_square, rug_o) = rug_square_prec_round(&rug::Float::exact_from(&x), prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); } if !x.is_nan() { assert!(square.is_sign_positive()); } if square.is_finite() { if square.is_normal() { assert_eq!(square.get_prec(), Some(prec)); } if !extreme { let r_square = Rational::exact_from(&x).square(); assert_eq!(square.partial_cmp(&r_square), Some(o)); if o == Less { let mut next = square.clone(); next.increment(); assert!(next > r_square); } else if o == Greater { let mut next = square.clone(); next.decrement(); assert!(next < r_square); } match (r_square >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (square_alt, o_alt) = (-&x).square_prec_round(prec, rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if o == Equal { if square.is_finite() { assert!(square.sqrt_prec_round_ref(prec, Exact).0.eq_abs(&x)); } for rm in exhaustive_rounding_modes() { let (s, oo) = x.square_prec_round_ref(prec, rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(square.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.square_prec_round_ref(prec, Exact)); } } #[test] fn square_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_2().test_properties(|(x, prec, rm)| { square_prec_round_properties_helper(x, prec, rm, false); }); float_unsigned_rounding_mode_triple_gen_var_11().test_properties(|(x, prec, rm)| { square_prec_round_properties_helper(x, prec, rm, true); }); unsigned_rounding_mode_pair_gen_var_3().test_properties(|(prec, rm)| { let (product, o) = Float::NAN.square_prec_round(prec, rm); assert!(product.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.square_prec_round(prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.square_prec_round(prec, rm), (Float::INFINITY, Equal) ); let (s, o) = Float::ZERO.square_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (s, o) = Float::NEGATIVE_ZERO.square_prec_round(prec, rm); assert_eq!(ComparableFloat(s), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); assert_eq!( Float::ONE.square_prec_round(prec, rm), (Float::one_prec(prec), Equal) ); assert_eq!( Float::NEGATIVE_ONE.square_prec_round(prec, rm), (Float::one_prec(prec), Equal) ); }); } #[allow(clippy::needless_pass_by_value)] fn square_prec_properties_helper(x: Float, prec: u64, extreme: bool) { let (square, o) = x.clone().square_prec(prec); assert!(square.is_valid()); let (square_alt, o_alt) = x.square_prec_ref(prec); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.square_prec_assign(prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if !extreme { let (square_alt, o_alt) = square_prec_round_naive(x.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); } let (rug_square, rug_o) = rug_square_prec(&rug::Float::exact_from(&x), prec); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); let (square_alt, o_alt) = x.square_prec_round_ref(prec, Nearest); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if !x.is_nan() { assert!(square.is_sign_positive()); } if square.is_finite() { if square.is_normal() { assert_eq!(square.get_prec(), Some(prec)); } if !extreme { let r_square = Rational::exact_from(&x).square(); assert_eq!(square.partial_cmp(&r_square), Some(o)); if o == Less { let mut next = square.clone(); next.increment(); assert!(next > r_square); } else if o == Greater { let mut next = square.clone(); next.decrement(); assert!(next < r_square); } } } let (square_alt, o_alt) = (-&x).square_prec(prec); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if o == Equal && square.is_finite() { assert!( square .sqrt_prec_round(x.get_prec().unwrap_or(1), Exact) .0 .eq_abs(&x) ); } } #[test] fn square_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { square_prec_properties_helper(x, prec, false); }); let mut config = GenConfig::new(); config.insert("mean_precision_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); float_unsigned_pair_gen_var_1().test_properties_with_config(&config, |(x, prec)| { square_prec_properties_helper(x, prec, false); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { square_prec_properties_helper(x, prec, true); }); unsigned_gen_var_11().test_properties(|prec| { let (square, o) = Float::NAN.square_prec(prec); assert!(square.is_nan()); assert_eq!(o, Equal); let (square, o) = Float::ZERO.square_prec(prec); assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (square, o) = Float::NEGATIVE_ZERO.square_prec(prec); assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.square_prec(prec), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.square_prec(prec), (Float::INFINITY, Equal) ); assert_eq!(Float::ONE.square_prec(prec), (Float::one_prec(prec), Equal)); assert_eq!( Float::NEGATIVE_ONE.square_prec(prec), (Float::one_prec(prec), Equal) ); }); } #[allow(clippy::needless_pass_by_value)] fn square_round_properties_helper(x: Float, rm: RoundingMode, extreme: bool) { let (square, o) = x.clone().square_round(rm); assert!(square.is_valid()); let (square_alt, o_alt) = x.square_round_ref(rm); assert!(square_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); let mut x_alt = x.clone(); let o_alt = x_alt.square_round_assign(rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if !extreme { let (square_alt, o_alt) = square_prec_round_naive(x.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); } let (square_alt, o_alt) = x.square_prec_round_ref(x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); assert_eq!(o_alt, o); if !x.is_nan() { assert!(square.is_sign_positive()); } if square.is_finite() { if x.is_normal() && square.is_normal() { assert_eq!(square.get_prec(), Some(x.get_prec().unwrap())); } if !extreme { let r_square = Rational::exact_from(&x).square(); assert_eq!(square.partial_cmp(&r_square), Some(o)); if o == Less { let mut next = square.clone(); next.increment(); assert!(next > r_square); } else if o == Greater { let mut next = square.clone(); next.decrement(); assert!(next < r_square); } match (r_square >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_square, rug_o) = rug_square_round(&rug::Float::exact_from(&x), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(rug_o, o); } let (square_alt, o_alt) = (-&x).square_round(rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); if o == Equal { if square.is_finite() { assert!(square.sqrt_round_ref(Exact).0.eq_abs(&x)); } for rm in exhaustive_rounding_modes() { let (s, oo) = x.square_round_ref(rm); assert_eq!( ComparableFloat(s.abs_negative_zero_ref()), ComparableFloat(square.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.square_round_ref(Exact)); } } #[test] fn square_round_properties() { float_rounding_mode_pair_gen_var_7().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_8().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_9().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_10().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_11().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_12().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_22().test_properties(|(x, rm)| { square_round_properties_helper(x, rm, true); }); rounding_mode_gen().test_properties(|rm| { let (square, o) = Float::NAN.square_round(rm); assert!(square.is_nan()); assert_eq!(o, Equal); let (square, o) = Float::ZERO.square_round(rm); assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); let (square, o) = Float::NEGATIVE_ZERO.square_round(rm); assert_eq!(ComparableFloat(square), ComparableFloat(Float::ZERO)); assert_eq!(o, Equal); assert_eq!(Float::INFINITY.square_round(rm), (Float::INFINITY, Equal)); assert_eq!( Float::NEGATIVE_INFINITY.square_round(rm), (Float::INFINITY, Equal) ); assert_eq!(Float::ONE.square_round(rm), (Float::ONE, Equal)); assert_eq!(Float::NEGATIVE_ONE.square_round(rm), (Float::ONE, Equal)); }); } fn square_properties_helper_1(x: Float, extreme: bool) { let square = x.clone().square(); assert!(square.is_valid()); let square_alt = (&x).square(); assert!(square_alt.is_valid()); assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); let mut x_alt = x.clone(); x_alt.square_assign(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&square)); if !extreme { let square_alt = square_prec_round_naive(x.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); } let square_alt = x.square_prec_round_ref(x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); let square_alt = x.square_prec_ref(x.significant_bits()).0; assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); let square_alt = x.square_round_ref(Nearest).0; assert_eq!(ComparableFloatRef(&square_alt), ComparableFloatRef(&square)); if !x.is_nan() { assert!(square.is_sign_positive()); } if square.is_finite() && x.is_normal() && square.is_normal() { assert_eq!(square.get_prec(), Some(x.get_prec().unwrap())); if !extreme { let r_square = Rational::exact_from(&x).square(); if square < r_square { let mut next = square.clone(); next.increment(); assert!(next > r_square); } else if square > r_square { let mut next = square.clone(); next.decrement(); assert!(next < r_square); } } } let rug_square = rug_square(&rug::Float::exact_from(&x)); assert_eq!( ComparableFloatRef(&Float::from(&rug_square)), ComparableFloatRef(&square), ); assert_eq!(ComparableFloat((-x).square()), ComparableFloat(square)); } #[allow(clippy::type_repetition_in_bounds)] fn square_properties_helper_2() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { let square_1 = x.square(); let square_2 = emulate_float_to_float_fn(Float::square_prec, x); assert_eq!(NiceFloat(square_1), NiceFloat(square_2)); }); } #[test] fn square_properties() { float_gen().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_6().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_7().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_8().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_9().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_10().test_properties(|x| { square_properties_helper_1(x, false); }); float_gen_var_12().test_properties(|x| { square_properties_helper_1(x, true); }); apply_fn_to_primitive_floats!(square_properties_helper_2); } ================================================ FILE: malachite-float/tests/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{NegAssign, PowerOf2}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero, }; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::emulate_float_float_to_float_fn; use malachite_float::test_util::arithmetic::add::add_prec_round_naive; use malachite_float::test_util::arithmetic::sub::sub_rational_prec_round_naive; use malachite_float::test_util::arithmetic::sub::{ rug_sub, rug_sub_prec, rug_sub_prec_round, rug_sub_rational, rug_sub_rational_prec, rug_sub_rational_prec_round, rug_sub_rational_round, rug_sub_round, }; use malachite_float::test_util::common::{ parse_hex_string, rug_round_try_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_float_rounding_mode_triple_gen_var_2, float_float_rounding_mode_triple_gen_var_10, float_float_rounding_mode_triple_gen_var_11, float_float_rounding_mode_triple_gen_var_12, float_float_rounding_mode_triple_gen_var_13, float_float_rounding_mode_triple_gen_var_14, float_float_rounding_mode_triple_gen_var_15, float_float_rounding_mode_triple_gen_var_30, float_float_unsigned_rounding_mode_quadruple_gen_var_2, float_float_unsigned_rounding_mode_quadruple_gen_var_6, float_float_unsigned_triple_gen_var_1, float_float_unsigned_triple_gen_var_2, float_gen, float_pair_gen, float_pair_gen_var_2, float_pair_gen_var_3, float_pair_gen_var_4, float_pair_gen_var_5, float_pair_gen_var_6, float_pair_gen_var_7, float_pair_gen_var_10, float_rational_pair_gen, float_rational_pair_gen_var_2, float_rational_rounding_mode_triple_gen_var_2, float_rational_rounding_mode_triple_gen_var_8, float_rational_unsigned_rounding_mode_quadruple_gen_var_2, float_rational_unsigned_rounding_mode_quadruple_gen_var_7, float_rational_unsigned_triple_gen_var_1, float_rational_unsigned_triple_gen_var_2, float_rounding_mode_pair_gen, float_unsigned_pair_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_1, rational_rounding_mode_pair_gen_var_6, rational_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::cmp::{ Ordering::{self, *}, max, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_sub() { let test = |s, s_hex, t, t_hex, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let diff = x.clone() - y.clone(); assert!(diff.is_valid()); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); let diff_alt = x.clone() - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let diff_alt = &x - y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let diff_alt = &x - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let mut diff_alt = x.clone(); diff_alt -= y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let mut diff_alt = x.clone(); diff_alt -= &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sub( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y) ))), ComparableFloatRef(&diff) ); let diff_alt = add_prec_round_naive( x.clone(), -&y, max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); }; test("NaN", "NaN", "NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "Infinity", "Infinity", "NaN", "NaN"); test("NaN", "NaN", "-Infinity", "-Infinity", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0", "NaN", "NaN"); test("NaN", "NaN", "-0.0", "-0x0.0", "NaN", "NaN"); test("Infinity", "Infinity", "NaN", "NaN", "NaN", "NaN"); test( "Infinity", "Infinity", "-Infinity", "-Infinity", "Infinity", "Infinity", ); test("Infinity", "Infinity", "Infinity", "Infinity", "NaN", "NaN"); test( "Infinity", "Infinity", "-0.0", "-0x0.0", "Infinity", "Infinity", ); test( "Infinity", "Infinity", "0.0", "0x0.0", "Infinity", "Infinity", ); test("-Infinity", "-Infinity", "NaN", "NaN", "NaN", "NaN"); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", "NaN", "NaN", ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", "-Infinity", "-Infinity", ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "0.0", "0x0.0", "-Infinity", "-Infinity", "Infinity", "Infinity", ); test( "0.0", "0x0.0", "Infinity", "Infinity", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "0.0", "0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "NaN", "NaN", "NaN", "NaN"); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", "Infinity", "Infinity", ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", "-Infinity", "-Infinity", ); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0.0", "0x0.0", "-0.0", "-0x0.0"); test("123.0", "0x7b.0#7", "NaN", "NaN", "NaN", "NaN"); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", "Infinity", "Infinity", ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", "-Infinity", "-Infinity", ); test("123.0", "0x7b.0#7", "-0.0", "-0x0.0", "123.0", "0x7b.0#7"); test("123.0", "0x7b.0#7", "0.0", "0x0.0", "123.0", "0x7b.0#7"); test("NaN", "NaN", "-123.0", "-0x7b.0#7", "NaN", "NaN"); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", "Infinity", "Infinity", ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", "-Infinity", "-Infinity", ); test("0.0", "0x0.0", "-123.0", "-0x7b.0#7", "123.0", "0x7b.0#7"); test("-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", "123.0", "0x7b.0#7"); test("1.0", "0x1.0#1", "-2.0", "-0x2.0#1", "4.0", "0x4.0#1"); test("1.0", "0x1.0#1", "-2.0", "-0x2.0#2", "3.0", "0x3.0#2"); test("1.0", "0x1.0#2", "-2.0", "-0x2.0#1", "3.0", "0x3.0#2"); test("1.0", "0x1.0#2", "-2.0", "-0x2.0#2", "3.0", "0x3.0#2"); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", "3.0", "0x3.00#10", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "4.555806215962888", "0x4.8e4950f0795fc#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "-1.727379091216698", "-0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1.727379091216698", "0x1.ba35842091e63#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", "-4.555806215962888", "-0x4.8e4950f0795fc#53", ); test("1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", "1.0", "0x1.0#1"); // - in sub_float_significands_same_prec_lt_w // - x_exp == y_exp in sub_float_significands_same_prec_lt_w // - x == y in sub_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "1.0", "0x1.0#1", "0.0", "0x0.0"); // - x_exp < y_exp in sub_float_significands_same_prec_lt_w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_lt_w // - leading_zeros != 0 in sub_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "2.0", "0x2.0#1", "-1.0", "-0x1.0#1"); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_lt_w // - neg in sub_float_significands_same_prec_lt_w // - rm == Nearest in sub_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & shift_bit) != 0) in // sub_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && sticky_bit != 0 && diff == 0 in // sub_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "4.0", "0x4.0#1", "-4.0", "-0x4.0#1"); // - !neg in sub_float_significands_same_prec_lt_w test("1.0", "0x1.0#1", "0.2", "0x0.4#1", "1.0", "0x1.0#1"); // - x < y in sub_float_significands_same_prec_lt_w test("1.0", "0x1.0#2", "1.5", "0x1.8#2", "-0.5", "-0x0.8#2"); // - x > y in sub_float_significands_same_prec_lt_w test("1.5", "0x1.8#2", "1.0", "0x1.0#2", "0.5", "0x0.8#2"); // - leading_zeros == 0 in sub_float_significands_same_prec_lt_w test("1.5", "0x1.8#2", "0.5", "0x0.8#2", "1.0", "0x1.0#2"); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff & shift_bit) == 0)) in // sub_float_significands_same_prec_lt_w test("2.0", "0x2.0#2", "0.8", "0x0.c#2", "1.0", "0x1.0#2"); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & shift_bit) != 0) && diff != // 0 in sub_float_significands_same_prec_lt_w test("1.5", "0x1.8#2", "0.1", "0x0.2#2", "1.5", "0x1.8#2"); // - exp_diff >= Limb::WIDTH in sub_float_significands_same_prec_lt_w // - x <= LIMB_HIGH_BIT in sub_float_significands_same_prec_lt_w test( "1.0e9", "0x4.0E+7#1", "6.0e-11", "0x4.0E-9#1", "1.0e9", "0x4.0E+7#1", ); // - x > LIMB_HIGH_BIT in sub_float_significands_same_prec_lt_w test( "9.2047171e-27", "0x2.d945d78E-22#27", "1.43189635e33", "0x4.69912aE+27#27", "-1.43189635e33", "-0x4.69912aE+27#27", ); // - in sub_float_significands_same_prec_w // - x_exp == y_exp in sub_float_significands_same_prec_w // - x_exp == y_exp && a0 == 0 in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", "0.0", "0x0.0", ); // - x_exp != y_exp in sub_float_significands_same_prec_w // - x_exp < y_exp in sub_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_w // - a0 != 0 in sub_float_significands_same_prec_w // - leading_zeros != 0 in sub_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", "-1.0", "-0x1.0000000000000000#64", ); // - a0 > x in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", "-1.084202172485504434e-19", "-0x2.0000000000000000E-16#64", ); // - a0 <= x in sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0", "0x1.0000000000000000#64", "1.084202172485504434e-19", "0x2.0000000000000000E-16#64", ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_w // - neg in sub_float_significands_same_prec_w // - rm == Nearest in sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) in // sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) && // !diff.overflowing_add_assign(1) in sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "4.0", "0x4.0000000000000000#64", "-3.0", "-0x3.0000000000000000#64", ); // - !neg in sub_float_significands_same_prec_w test( "4.0", "0x4.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", "3.0", "0x3.0000000000000000#64", ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff & 1) == 0)) in // sub_float_significands_same_prec_w test( "1.0000000000000000003", "0x1.0000000000000006#64", "4.0", "0x4.0000000000000000#64", "-2.9999999999999999996", "-0x2.fffffffffffffff8#64", ); // - leading_zeros == 0 in sub_float_significands_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", "7.8519772600462495573e-34", "0x4.13b4f0d218450fb0E-28#64", "-7.848704308738543156e-34", "-0x4.13459164c75d56b8E-28#64", ); // - exp_diff >= Limb::WIDTH in sub_float_significands_same_prec_w // - x > LIMB_HIGH_BIT in sub_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", ); // - x <= LIMB_HIGH_BIT in sub_float_significands_same_prec_w // - exp_diff != Limb::WIDTH || y <= LIMB_HIGH_BIT in sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) && // diff.overflowing_add_assign(1) in sub_float_significands_same_prec_w test( "8355840.0624923708378", "0x7f8000.0fff8000ff8#64", "2.3384026197294446691e49", "0x1.0000000000000000E+41#64", "-2.3384026197294446691e49", "-0x1.0000000000000000E+41#64", ); // - x_exp != y_exp && a0 == 0 in sub_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", "-3.4694469519536141888e-18", "-0x4.0000000000000000E-15#64", ); // - exp_diff == Limb::WIDTH && y > LIMB_HIGH_BIT in sub_float_significands_same_prec_w test( "4.656578456163629198e-10", "0x1.ffff07fffffffffeE-8#64", "4294967296.0", "0x100000000.00000000#64", "-4294967295.9999999995", "-0xffffffff.fffffffe#64", ); // - in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - a1 == 0 && a0 == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", "0.0", "0x0.0", ); // - x_exp != y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp < y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp != y_exp && a1 != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp != y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", "-1.0", "-0x1.0000000000000000#65", ); // - (a1 != 0 || a0 != 0) && a1 >= x_1 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp && a1 == 0 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", "-5.42101086242752217e-20", "-0x1.0000000000000000E-16#65", ); // - (a1 != 0 || a0 != 0) && a1 < x_1 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.0", "0x1.0000000000000000#65", "5.42101086242752217e-20", "0x1.0000000000000000E-16#65", ); // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.00000000000000000#66", "1.00000000000000000003", "0x1.00000000000000008#66", "-2.710505431213761085e-20", "-0x8.0000000000000000E-17#66", ); // - x_exp == y_exp && a1 != 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000011", "0x1.0000000000000002#65", "-1.084202172485504434e-19", "-0x2.0000000000000000E-16#65", ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - neg in sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // !overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "4.0", "0x4.0000000000000000#65", "-3.0", "-0x3.0000000000000000#65", ); // - !neg in sub_float_significands_same_prec_gt_w_lt_2w test( "4.0", "0x4.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", "3.0", "0x3.0000000000000000#65", ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0)) in // sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000016", "0x1.0000000000000003#65", "4.0", "0x4.0000000000000000#65", "-2.9999999999999999998", "-0x2.fffffffffffffffc#65", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && a1 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", ); // - x_exp != y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "0.0001507756106295330606262754053", "0x0.0009e19851127b95dcf03f0cdc#91", "3458.565842843038054059107814", "0xd82.90db1399862ba513faf8#91", "-3458.565692067427424526047188", "-0xd82.90d132013519297e1e08#91", ); // - exp_diff >= Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - exp_diff >= Limb::WIDTH * 2 && a1 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", "-372369974082165972883205.481495834785", "-0x4eda377c7f0d747f5705.7b434f9f90#116", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && a1 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "9.9035203142830421991929938e27", "0x2.000000000000000000000E+23#85", "16.0", "0x10.00000000000000000000#85", "9.9035203142830421991929938e27", "0x2.000000000000000000000E+23#85", ); // - exp_diff >= Limb::WIDTH * 2 && a1 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "5.3455294200288159103345444e-51", "0x1.ffffffffc000000000000E-42#83", "8.0", "0x8.00000000000000000000#83", "-8.0", "-0x8.00000000000000000000#83", ); // - x_exp != y_exp && a1 == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "4.00000000000000000000084702", "0x4.000000000000000003fffc#89", "3.999999999999999999999999994", "0x3.fffffffffffffffffffffe#89", "8.47026484905764768539612568e-22", "0x3.fffe000000000000000000E-18#89", ); // - in sub_float_significands_same_prec_2w // - x_exp == y_exp in sub_float_significands_same_prec_2w // - a1 == 0 && a0 == 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", "0.0", "0x0.0", ); // - x_exp != y_exp in sub_float_significands_same_prec_2w // - x_exp < y_exp in sub_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_2w // - a1 != 0 second time in sub_float_significands_same_prec_2w // - a1 != 0 third time in sub_float_significands_same_prec_2w // - x_exp != y_exp && leading_zeros != 0 in sub_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", "-1.0", "-0x1.00000000000000000000000000000000#128", ); // - (a1 != 0 || a0 != 0) && a1 >= x_1 in sub_float_significands_same_prec_2w // - a1 == 0 first time in sub_float_significands_same_prec_2w // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "-5.87747175411143753984368268611122838909e-39", "-0x2.00000000000000000000000000000000E-32#128", ); // - (a1 != 0 || a0 != 0) && a1 < x_1 in sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "1.0", "0x1.00000000000000000000000000000000#128", "5.87747175411143753984368268611122838909e-39", "0x2.00000000000000000000000000000000E-32#128", ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_2w // - neg in sub_float_significands_same_prec_2w // - rm == Nearest in sub_float_significands_same_prec_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & 1) != 0) && !overflow in // sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "4.0", "0x4.00000000000000000000000000000000#128", "-3.0", "-0x3.00000000000000000000000000000000#128", ); // - !neg in sub_float_significands_same_prec_2w test( "4.0", "0x4.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "3.0", "0x3.00000000000000000000000000000000#128", ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff_0 & 1) == 0)) in // sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", "4.0", "0x4.00000000000000000000000000000000#128", "-2.99999999999999999999999999999999999998", "-0x2.fffffffffffffffffffffffffffffff8#128", ); // - x_exp != y_exp && leading_zeros == 0 in sub_float_significands_same_prec_2w test( "1.91698663575347889601435178329077738407e-37", "0x4.13b4f0d218450fb6f5f6d50e7b8f6eb0E-31#128", "8.0669110092962644724944820639408319804e-34", "0x4.3046c1d7c0f5b6be39df2b03f3e49a70E-28#128", "-8.06499402266051099359846771215754120301e-34", "-0x4.30058688b3d4326d3e6fcb96a2fce178E-28#128", ); // - exp_diff >= Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - x_1 > LIMB_HIGH_BIT || x_0 > 0 in sub_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - a1 >= LIMB_HIGH_BIT in sub_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", "4354249796990942.35435357446273837760591", "0xf782ac869b7de.5ab6ea7589c4fdd5d8d#128", ); // - a1 != 0 first time in sub_float_significands_same_prec_2w test( "852777855057.113455599443829872557360137", "0xc68d856851.1d0b6d1928c98779f28bdd#128", "869223500084.503694559376384046083491558", "0xca61c20934.80f2206bb1d7d5cad69caa#128", "-16445645027.39023895993255417352613142066", "-0x3d43ca0e3.63e6b352890e4e50e410cd00#128", ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", "-148.054913367700296533946811280266669483", "-0x94.0e0ecd6e62d0a804b7b02b85098c9c#128", ); // - x_1 <= LIMB_HIGH_BIT && x_0 <= 0 in sub_float_significands_same_prec_2w // - exp_diff != TWICE_WIDTH || tst in sub_float_significands_same_prec_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & 1) != 0) && overflow in // sub_float_significands_same_prec_2w test( "3.83123885216472214589586756787577295905e53", "0x4.00000000000000000000000000000000E+44#128", "9.09494703466994132423639742106012939545e-13", "0x1.00000008000000000000007fffffff80E-10#128", "3.83123885216472214589586756787577295905e53", "0x4.00000000000000000000000000000000E+44#128", ); // - a1 < LIMB_HIGH_BIT in sub_float_significands_same_prec_2w test( "0.000473141670219947088192358501321236008969", "0x0.001f01fffffe001ffe000000000003ffff0#128", "144115188075855872.000000000007275846592", "0x200000000000000.0000000007fff80000#128", "-144115188075855871.9995268583370558995037", "-0x1ffffffffffffff.ffe0fe000801f7e002#128", ); // - a1 == 0 second time in sub_float_significands_same_prec_2w test( "1.192092895507812500000000000000000918348e-7", "0x2.0000000000000000000000000007fffcE-6#128", "1.19209289550781249999999999999999632658e-7", "0x1.ffffffffffffffffffffffffffe00000E-6#128", "4.5917678014072389539175224798764807294e-40", "0x2.7fffc000000000000000000000000000E-33#128", ); // - exp_diff == TWICE_WIDTH && !tst in sub_float_significands_same_prec_2w test( "1024.0", "0x400.000000000000000000000000000000#128", "5.97151130219911582898625687582100437209e-36", "0x7.f00000001fffffffffffffffe0000000E-30#128", "1023.999999999999999999999999999999999994", "0x3ff.fffffffffffffffffffffffffffff8#128", ); // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_2w test( "0.249999999999999999999999999974756451033", "0x0.3ffffffffffffffffffffffe000000000#128", "0.2499999999999999999864474728691747435412", "0x0.3fffffffffffffffc0000001ffffffffc#128", "1.35525271055817074916830884337875729072e-20", "0x3.ffffffc0000000040000000000000000E-17#128", ); // - a1 == 0 third time in sub_float_significands_same_prec_2w test( "8.0", "0x8.0000000000000000000000000000000#128", "7.99999999999999999999999999999999999998", "0x7.fffffffffffffffffffffffffffffff8#128", "2.35098870164457501593747307444449135564e-38", "0x8.0000000000000000000000000000000E-32#128", ); // - in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp in sub_float_significands_same_prec_gt_2w_lt_3w // - a2 == 0 && a1 == 0 && a0 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", "0.0", "0x0.0", ); // - x_exp != y_exp in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && sticky_bit == 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && a2 != 0 first time in // sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && leading_zeros != 0 in // sub_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "2.0", "0x2.00000000000000000000000000000000#129", "-1.0", "-0x1.00000000000000000000000000000000#129", ); // - x_exp >= y_exp in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", ); // - (a2 != 0 || a1 != 0 || a0 != 0) && a2 >= x_2 in // sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && a2 == 0 first time in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && a2 == 0 second time in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "-2.93873587705571876992184134305561419455e-39", "-0x1.00000000000000000000000000000000E-32#129", ); // - (a2 != 0 || a1 != 0 || a0 != 0) && a2 < x_2 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.0", "0x1.00000000000000000000000000000000#129", "2.93873587705571876992184134305561419455e-39", "0x1.00000000000000000000000000000000E-32#129", ); // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.000000000000000000000000000000000#130", "1.000000000000000000000000000000000000001", "0x1.000000000000000000000000000000008#130", "-1.469367938527859384960920671527807097273e-39", "-0x8.00000000000000000000000000000000E-33#130", ); // - x_exp == y_exp && a2 != 0 second time in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", "-5.87747175411143753984368268611122838909e-39", "-0x2.00000000000000000000000000000000E-32#129", ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - neg in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) in // sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // overflow in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && diff_1 // == 0 && diff_0 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && diff_2 != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "4.0", "0x4.00000000000000000000000000000000#129", "-3.0", "-0x3.00000000000000000000000000000000#129", ); // - !neg in sub_float_significands_same_prec_gt_2w_lt_3w test( "4.0", "0x4.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "3.0", "0x3.00000000000000000000000000000000#129", ); // - rm == Nearest && round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0) in // sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", "4.0", "0x4.00000000000000000000000000000000#129", "-2.999999999999999999999999999999999999988", "-0x2.fffffffffffffffffffffffffffffffc#129", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // (diff_1 != 0 || diff_0 != 0) in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.000000000000000000000000000000000000006", "0x2.00000000000000000000000000000002#129", "0.500000000000000000000000000000000000001", "0x0.800000000000000000000000000000008#129", "1.500000000000000000000000000000000000006", "0x1.80000000000000000000000000000002#129", ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // !overflow in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.000000000000000000000000000000000000003", "0x2.00000000000000000000000000000001#130", "0.5000000000000000000000000000000000000007", "0x0.800000000000000000000000000000004#130", "1.500000000000000000000000000000000000003", "0x1.800000000000000000000000000000010#130", ); // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - TWICE_WIDTH < exp_diff < THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", "-245906107849378561117126906.9059035528266331265", "-0xcb68a4d1611415054400fa.e7e94b94b8791630#149", ); // - exp_diff >= THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff >= THRICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", ); // - exp_diff < Limb::WIDTH && leading_zeros == 0 in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.9709672065181108960570410290811793724062284431352e-48", "0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165", "5.2183974782595301717751266872943662193587933931613e-47", "0x4.c4457ca8b3429511981a96eb0c2de4fdb8c43bea4E-39#165", "-4.7213007576077190821694225843862482821181705488478e-47", "-0x4.5007bb94c9e5f3ee2ee4463bdaea865173035443cE-39#165", ); // - exp_diff < Limb::WIDTH && sticky_bit != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "8.264811372870109665580646414654919646529224699888394e-20", "0x1.864b7049feb3dcfe49ea910db778157cbe9c2021b44E-16#171", "0.0007337187065343299500100945131574173571435306249470578", "0x0.003015c1d959ec54ab97dc58b77c22566586c06119b810#171", "-0.0007337187065343298673619807844563207013370664783978612", "-0x0.003015c1d959ec53254c6c0eb8c845581b9c2f53623ff8#171", ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH && sticky_bit != 0 in // sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", "-978.49328809934495391839837951452201374861917", "-0x3d2.7e4820fe314caadcb79b4ec1aad85458e9#146", ); // - Limb::WIDTH < exp_diff < TWICE_WIDTH && sticky_bit == 0 in // sub_float_significands_same_prec_gt_2w_lt_3w test( "0.4575080253178526499352273198671695352442", "0x0.751f3ef665d0ca4dfa2d089979c4e9600#130", "184366716174337778394.1535133791267987587", "0x9fe9a278b38ab22da.274ca71ed919c918#130", "-184366716174337778393.6960053538089461089", "-0x9fe9a278b38ab22d9.b22d68287348fecc#130", ); // - x_exp == y_exp && a2 != 0 first time in sub_float_significands_same_prec_gt_2w_lt_3w test( "229.1456159244630209666077998586332154002628588961962846344", "0xe5.254715d158717849f7198986a38cb415eeea3464b1df38#189", "175.1335582002789888688278442018847623084238889142385801004", "0xaf.2230dec64f958583522e37252cf610378914f3127d0bb0#189", "54.01205772418403209777995565674845309183896998195770453405", "0x36.0316370b08dbf2c6a4eb52617696a3de65d5415234d388#189", ); // - exp_diff == TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", "563971925627753843356041629019151473016877231793.59", "0x62c960337e963a378ba6626ea422d8a598922eb1.98#165", ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", "-4262448175090788889226.053679181660481592", "-0xe71159efd3a67e728a.0dbdeb39b533210#130", ); // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && diff_2 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "0.0001220703125", "0x0.0008000000000000000000000000000000000000#145", "8.2855746158774225568154012162196749515653053e-50", "0x1.f0000fc000000000000003fffffffffffffcE-41#145", "0.0001220703125", "0x0.0008000000000000000000000000000000000000#145", ); // - Limb::WIDTH < exp_diff < TWICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "0.0156250000000000000000000000252435487789932816416198", "0x0.040000000000000000000001ffffffc00000000003f#167", "2.11758236813575084767080625169910490512847748461541e-22", "0xf.ffffffffffffffffffffffffffffffffff0000000E-19#167", "0.0156249999999999999997882417884299736942262010164499", "0x0.03ffffffffffffffff000001ffffffc00000000003f0#167", ); // - exp_diff >= THRICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "1.028440348325753776346855739098344065614209916020987e62", "0x4.000000000000000000000000000000000000000000E+51#168", "0.00781238079073842683897073489057921223679527623088422", "0x0.01fffe000007e000000038000007fffffffffe000000#168", "1.028440348325753776346855739098344065614209916020987e62", "0x4.000000000000000000000000000000000000000000E+51#168", ); // - exp_diff < Limb::WIDTH && a2 == 0 first time in // sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && a2 != 0 second time in // sub_float_significands_same_prec_gt_2w_lt_3w test( "32767.9999999999999999999999999999999999999999996", "0x7fff.fffffffffffffffffffffffffffffffffff8#156", "32768.0000000000000000069388939039072268369037424", "0x8000.000000000000007ffffffffffff80000000#156", "-6.93889390390722683690374277451135137549581608853e-18", "-0x7.ffffffffffff800000008000000000000000000E-15#156", ); // - exp_diff < Limb::WIDTH && a2 == 0 second time in // sub_float_significands_same_prec_gt_2w_lt_3w test( "137438953471.99999999999999999999999999999", "0x1fffffffff.ffffffffffffffffffffffff#133", "137438953472.0", "0x2000000000.000000000000000000000000#133", "-1.2621774483536188886587657044524579674771e-29", "-0x1.000000000000000000000000000000000E-24#133", ); // - in sub_float_significands_same_prec_ge_3w // - x_exp == y_exp in sub_float_significands_same_prec_ge_3w // - k < 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "0.0", "0x0.0", ); // - x_exp > y_exp in sub_float_significands_same_prec_ge_3w // - exp_diff == 1 in sub_float_significands_same_prec_ge_3w // - !goto_sub_d1_no_lose && !goto_sub_d1_lose in sub_float_significands_same_prec_ge_3w // - limb < LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - exp_diff == 0 in sub_float_significands_same_prec_ge_3w // - goto_exact_normalize in sub_float_significands_same_prec_ge_3w // - limb != 0 in sub_float_significands_same_prec_ge_3w // - exp_diff == 0 && limb != 0 && leading_zeros == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", ); // - k >= 0 && xs[k] < ys[k] in sub_float_significands_same_prec_ge_3w // - !goto_exact_normalize in sub_float_significands_same_prec_ge_3w // - limb == 0 in sub_float_significands_same_prec_ge_3w // - out[usize::exact_from(k)] != 0 in sub_float_significands_same_prec_ge_3w // - limb == 0 && leading_zeros != 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "-3.186183822264904554057760795535423611182209110385237572148e-58", "-0x2.000000000000000000000000000000000000000000000000E-48#192", ); // - k >= 0 && xs[k] >= ys[k] in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "3.186183822264904554057760795535423611182209110385237572148e-58", "0x2.000000000000000000000000000000000000000000000000E-48#192", ); // - exp_diff == 0 && limb != 0 && leading_zeros != 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "0.9999999999999999999999999999999999999999999999999999999997", "0x0.fffffffffffffffffffffffffffffffffffffffffffffffe#192", ); // - 2 <= exp_diff < prec in sub_float_significands_same_prec_ge_3w // - dm != 0 && m == 0 in sub_float_significands_same_prec_ge_3w // - sx != 0 in sub_float_significands_same_prec_ge_3w // - !out[n - 1].get_highest_bit() in sub_float_significands_same_prec_ge_3w // - round_bit == 0 in sub_float_significands_same_prec_ge_3w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "0.5", "0x0.800000000000000000000000000000000000000000000000#192", "1.5", "0x1.800000000000000000000000000000000000000000000000#192", ); // - limb == 0 && leading_zeros == 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "1.0000000000000000000000000000000000000000000000000000000002", "0x1.000000000000000000000000000000000000000000000001#193", "-1.5930919111324522770288803977677118055911045551926187860739e-58", "-0x1.000000000000000000000000000000000000000000000000E-48#193", ); // - sx == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#193", "0.5", "0x0.8000000000000000000000000000000000000000000000000#193", "1.5", "0x1.800000000000000000000000000000000000000000000000#193", ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_ge_3w // - out_power_of_2 || round_bit == 0 in sub_float_significands_same_prec_ge_3w // - rm == Nearest in sub_float_significands_same_prec_ge_3w // - rm == Nearest && !out_power_of_2 first time in sub_float_significands_same_prec_ge_3w // - rm == Nearest && (round_bit == 0 || (round_bit != 0 && sticky_bit == 0 && (out[0] & // shift_bit == 0 || prec == 1))) in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "-3.0", "-0x3.000000000000000000000000000000000000000000000000#192", ); // - out[usize::exact_from(k)] == 0 in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000002", "0x1.000000000000000000000000000000000000000000000001#193", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#193", "-1.5930919111324522770288803977677118055911045551926187860739e-58", "-0x1.000000000000000000000000000000000000000000000000E-48#193", ); // - round_bit != 0 in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000006", "0x1.000000000000000000000000000000000000000000000004#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "-2.9999999999999999999999999999999999999999999999999999999994", "-0x2.fffffffffffffffffffffffffffffffffffffffffffffffc#192", ); // - rm == Nearest && round_bit != 0 && (round_bit == 0 || sticky_bit != 0 || (out[0] & // shift_bit != 0 && prec == 1)) in sub_float_significands_same_prec_ge_3w // - rm == Nearest && !out_power_of_2 second time in sub_float_significands_same_prec_ge_3w test( "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "-2.9999999999999999999999999999999999999999999999999999999987", "-0x2.fffffffffffffffffffffffffffffffffffffffffffffff8#192", ); // - sticky_bit_2 == 0 && k > 0 third time in sub_float_significands_same_prec_ge_3w test( "0.5", "0x0.8000000000000000000000000000000000000000000000000#193", "4.0", "0x4.000000000000000000000000000000000000000000000000#193", "-3.5", "-0x3.800000000000000000000000000000000000000000000000#193", ); // - sticky_bit_2 != 0 || k <= 0 third time in sub_float_significands_same_prec_ge_3w test( "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "0.5000000000000000000000000000000000000000000000000000000002", "0x0.800000000000000000000000000000000000000000000001#192", "3.5", "0x3.800000000000000000000000000000000000000000000000#192", ); // - dm != 0 && m != 0 in sub_float_significands_same_prec_ge_3w // - out[n - 1].get_highest_bit() in sub_float_significands_same_prec_ge_3w test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", "-3.51234737788255789588958894759637493376138490511114928693281e-27", "-0x1.1646de419a6dbd345c4f0be661b66dbec20356d34b05340208E-22#198", ); // - exp_diff >= prec in sub_float_significands_same_prec_ge_3w // - exp_diff > prec in sub_float_significands_same_prec_ge_3w // - exp_diff != prec + 1 in sub_float_significands_same_prec_ge_3w test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", ); // - dm == 0 in sub_float_significands_same_prec_ge_3w test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", "-1476808010161862576835936576709144.7975558190129516579963983", "-0x48cff00a780a50d34bb694ada218.cc2c9e3f6526bd5f9c868#192", ); // - exp_diff == prec + 1 in sub_float_significands_same_prec_ge_3w // - sticky_bit_2 != 0 || k <= 0 second time in sub_float_significands_same_prec_ge_3w test( "29249291732025621624535078208.59212499364958152526111994335", "0x5e827271f9e9d261e7cb5540.979580eade814aae28ae9d3c8#192", "1.7056859397843570965021420438616279890690624515282312011749e-30", "0x2.2986d80d04731f28b49380410e3f4711dc2cc5f113c594a0E-25#192", "29249291732025621624535078208.59212499364958152526111994335", "0x5e827271f9e9d261e7cb5540.979580eade814aae28ae9d3c8#192", ); // - limb > LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - y0 != 0 in sub_float_significands_same_prec_ge_3w test( "1958139908729.1847354007541959640287427302874567071533816044", "0x1c7ea3bd279.2f4ad1b8a7190307771c7e5767590237208b90#192", "688604646855.2266320591592881661509057171162297144871538944", "0xa054090dc7.3a048f025074a63da83a500a235d2b8fd9766d#192", "1269535261873.9581033415949077978778370131712269926662277102", "0x1279632c4b1.f54642b656a45cc9cee22e4d43fbd6a7471524#192", ); // - y0 == 0 in sub_float_significands_same_prec_ge_3w test( "2473299914875391681216.10395653853096422269749051583697615", "0x8613ee70797f97a2c0.1a9ce54d32239153edab6ff15dad1c0#193", "7716446651886500012256.87778108230244207876352217543002925", "0x1a24f3592677b2760e0.e0b642d189564d3b4c797ad9c9cde8#193", "-5243146737011108331040.7738245437714778560660316595930531", "-0x11c3b4721edfb8fbe20.c6195d845732bbe75ece0ae86c20cc#193", ); // - exp_diff == prec in sub_float_significands_same_prec_ge_3w // - sticky_bit_2 != 0 || k <= 0 first time in sub_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", "-1174582238252884689829665592721065057.76655867827770290150718", "-0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d0#194", ); // - rm == Nearest && out_power_of_2 first time in sub_float_significands_same_prec_ge_3w test( "22300745198530623141535718272648361505980416.0", "0x1000000000000000000000000000000000000.000000000000#192", "8.470329472543003387009805160583577341645369940072346001613e-22", "0x3.ffffffffffffffe000000003ff0000003ffffffc00000000E-18#192", "22300745198530623141535718272648361505980416.0", "0x1000000000000000000000000000000000000.000000000000#192", ); // - sticky_bit_2 == 0 && k > 0 second time in sub_float_significands_same_prec_ge_3w test( "1.6849966666969146159452711670928107852024276704905067469395e66", "0xf.ffffffffffff01fffff00000000000000000000000000000E+54#193", "33554432.00000000000000044408920985006261616945266723632812", "0x2000000.0000000000001ffffffffffffffffffffffffffffe#193", "1.6849966666969146159452711670928107852024276704905067469395e66", "0xf.ffffffffffff01fffff00000000000000000000000000000E+54#193", ); // - limb == LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - l >= 0 first time in sub_float_significands_same_prec_ge_3w // - xs[l] != yl_shifted in sub_float_significands_same_prec_ge_3w // - l >= 0 && xs[l] <= yl_shifted in sub_float_significands_same_prec_ge_3w // - goto_sub_d1_no_lose || goto_sub_d1_lose in sub_float_significands_same_prec_ge_3w test( "2047.9999999999999999999999999999747564510329303127198868805", "0x7ff.fffffffffffffffffffffffe00000000003c000003fffc#193", "4095.99999999999999988897769753748434595763683319091796875", "0xfff.fffffffffffff800000000000000000000000000000000#193", "-2047.9999999999999998889776975375095895066039028781980818695", "-0x7ff.fffffffffffff80000000001ffffffffffc3fffffc0004#193", ); // - sticky_bit_2 == 0 && k > 0 first time in sub_float_significands_same_prec_ge_3w test( "0.0002442598197376355528831482438462803411504065058668775410457", "0x0.001001fff000000000000003ffff00000001fffffff07fffffe#192", "5.834076822994820350447560050418866475553361427251759468222e-62", "0x1.8000000000000000000000000000000000001c00007ffffeE-51#192", "0.00024425981973763555288314824384628034115040650586687754104564", "0x0.001001fff000000000000003ffff00000001fffffff07fffffc#192", ); // - l >= 0 && xs[l] > yl_shifted in sub_float_significands_same_prec_ge_3w test( "127.99999999999999999999998841947063540272586186468301133273", "0x7f.fffffffffffffffffff1fffff00007ffffffffffffffff8#192", "255.99999999999999999999999979320484686174308128214782699291", "0xff.ffffffffffffffffffffc00000000000000000000000ff#192", "-128.0000000000000000000000113737342114590172194174648156602", "-0x80.0000000000000000000dc0000ffff80000000000000100#192", ); // - out_power_of_2 && round_bit != 0 in sub_float_significands_same_prec_ge_3w test( "81129638414606681695789005144064.0", "0x400000000000000000000000000.0000000000000000000000#193", "6.46392625738094777466974989455420015132331189664152496326e-27", "0x2.001ffffffffe0000001fffff000000ffffff80000000000eE-22#193", "81129638414606681695789005144063.999999999999999999999999994", "0x3ffffffffffffffffffffffffff.fffffffffffffffffffffe#193", ); // - rm == Nearest && out_power_of_2 second time in sub_float_significands_same_prec_ge_3w test( "9.5367431640625e-7", "0x0.00001000000000000000000000000000000000000000000000000#192", "7.596455102175746880546879414772134233793171691679642324806e-65", "0x8.00000ffffffffffe000000000000000000000000001ffffE-54#192", "9.536743164062499999999999999999999999999999999999999999998e-7", "0xf.fffffffffffffffffffffffffffffffffffffffffffffffE-6#192", ); // - xs[l] == yl_shifted in sub_float_significands_same_prec_ge_3w test( "1180591620717411303423.9999999999999999999999999999999999998", "0x3fffffffffffffffff.ffffffffffffffffffffffffffffffc#192", "2361183241434822606847.9999999999999999930619531290400259223", "0x7fffffffffffffffff.ffffffffffffff8003ffffffffffff8#192", "-1180591620717411303423.9999999999999999930619531290400259225", "-0x3fffffffffffffffff.ffffffffffffff8003ffffffffffffc#192", ); // - l < 0 first time in sub_float_significands_same_prec_ge_3w // - l < 0 second time in sub_float_significands_same_prec_ge_3w // - yl_shifted != 0 in sub_float_significands_same_prec_ge_3w test( "32767.999999999999999999999999999999999999999999999999999995", "0x7fff.ffffffffffffffffffffffffffffffffffffffffffff8#192", "65535.99999999999999999999999999999999999999999999999999999", "0xffff.ffffffffffffffffffffffffffffffffffffffffffff#192", "-32767.999999999999999999999999999999999999999999999999999995", "-0x7fff.ffffffffffffffffffffffffffffffffffffffffffff8#192", ); // - yl_shifted == 0 in sub_float_significands_same_prec_ge_3w test( "34359738367.999999999999999999999999999999999999999999999989", "0x7ffffffff.fffffffffffffffffffffffffffffffffffffff0#192", "68719476735.99999999999999999999999999999999999999999999999", "0xfffffffff.fffffffffffffffffffffffffffffffffffffff#192", "-34359738368.0", "-0x800000000.000000000000000000000000000000000000000#192", ); test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "-0.5", "-0x0.8#2"); test("0.5", "0x0.8#1", "3.0", "0x3.0#2", "-2.0", "-0x2.0#2"); test("0.2", "0x0.4#1", "4.0", "0x4.0#2", "-4.0", "-0x4.0#2"); test( "0.00374222828352849", "0x0.00f5402c178824#46", "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222827281009532032311766811006", "0x0.00f5402c0bbf2e1505ed1467de9fe#107", ); test( "2589062031404.0", "0x25ad01f682c.0#43", "4351572166934988.581719655389852344796925751245753159273257621838622031922945531041952618\ 810238932316", "0xf75bb593981cc.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", "-4348983104903584.58171965538985234479692575124575315927325762183862203192294553104195261\ 8810238932316", "-0xf7360891a19a0.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", ); // - in sub_float_significands_general // - in exponent_shift_compare // - sdiff_exp >= 0 in exponent_shift_compare // - diff_exp == 0 first time in exponent_shift_compare // - xi >= 0 && yi >= 0 && xs[xi] == ys[yi] in exponent_shift_compare // - xi < 0 in exponent_shift_compare // - xi < 0 && yi < 0 in exponent_shift_compare // - sign == Equal in sub_float_significands_general test("1.0", "0x1.0#1", "1.0", "0x1.0#2", "0.0", "0x0.0"); // - diff_exp != 0 first time in exponent_shift_compare // - diff_exp < Limb::WIDTH in exponent_shift_compare // - diff_exp != 0 second time in exponent_shift_compare // - (yi < 0 && lasty == 0) || high_dif != 0 || dif != 1 in exponent_shift_compare // - high_dif == 0 in exponent_shift_compare // - dif.is_power_of_2() in exponent_shift_compare // - yi < 0 && lasty == 0 in exponent_shift_compare // - sign != Equal in sub_float_significands_general // - sign != Less in sub_float_significands_general // - !neg in sub_float_significands_general // - max(out_prec, x_prec) + 2 > exp_diff in sub_float_significands_general // - shift_x != 0 in sub_float_significands_general // - shift_y == 0 in sub_float_significands_general // - cancel >= exp_diff in sub_float_significands_general // - out_len + cancel1 <= xs_len in sub_float_significands_general // - out_len + cancel2 > 0 in sub_float_significands_general // - cancel2 >= 0 in sub_float_significands_general // - out_len + cancel2 <= ys_len in sub_float_significands_general // - rm == Nearest in sub_float_significands_general // - rm == Nearest && carry <= Limb::power_of_2(sh - 1) && (0 >= carry || carry >= // Limb::power_of_2(sh - 1)) in sub_float_significands_general // - !goto_truncate in sub_float_significands_general // - ixs_len <= 0 && iys_len <= 0 in sub_float_significands_general // - !goto_truncate && !goto_end_of_sub second time in sub_float_significands_general // - rm != Nearest || cmp_low == 0 in sub_float_significands_general // - !goto_end_of_sub in sub_float_significands_general // - out[out_len - 1] >> (Limb::WIDTH - 1) != 0 in sub_float_significands_general // - cancel != 0 in sub_float_significands_general test("2.0", "0x2.0#1", "1.0", "0x1.0#2", "1.0", "0x1.0#2"); // - sdiff_exp < 0 in exponent_shift_compare // - sign == Less in sub_float_significands_general // - neg in sub_float_significands_general test("1.0", "0x1.0#2", "2.0", "0x2.0#1", "-1.0", "-0x1.0#2"); // - xi < 0 || yi < 0 || xs[xi] != ys[yi] in exponent_shift_compare // - xi >= 0 in exponent_shift_compare // - yi >= 0 second time in exponent_shift_compare // - xs[xi] < ys[yi] in exponent_shift_compare // - diff_exp == 0 second time in exponent_shift_compare // - shift_y != 0 in sub_float_significands_general test("1.0", "0x1.0#1", "1.5", "0x1.8#2", "-0.5", "-0x0.8#2"); // - xs[xi] >= ys[yi] in exponent_shift_compare test("1.5", "0x1.8#2", "1.0", "0x1.0#1", "0.5", "0x0.8#2"); // - shift_x == 0 in sub_float_significands_general // - cancel < exp_diff in sub_float_significands_general // - ixs_len > 0 || iys_len > 0 in sub_float_significands_general // - ixs_len <= 0 in sub_float_significands_general // - iys_len condition in sub_float_significands_general // - cmp_low == 0 first time in sub_float_significands_general // - rm == Nearest && (sh != 0 || k != 0) in sub_float_significands_general // - cmp_low == 0 second time in sub_float_significands_general // - !goto_truncate && !goto_end_of_sub first time in sub_float_significands_general // - cancel == 0 in sub_float_significands_general test("0.5", "0x0.8#1", "1.5", "0x1.8#2", "-1.0", "-0x1.0#2"); // - !dif.is_power_of_2() in exponent_shift_compare test("0.5", "0x0.8#1", "2.0", "0x2.0#2", "-1.5", "-0x1.8#2"); // - cmp_low != 0 first time in sub_float_significands_general // - cmp_low > 0 in sub_float_significands_general // - cmp_low > 0 && rm == Nearest in sub_float_significands_general // - cmp_low > 0 && rm == Nearest && xx == yy in sub_float_significands_general // - rm == Nearest && cmp_low != 0 in sub_float_significands_general // - (out[0] >> sh) & 1 == 0 in sub_float_significands_general test("0.5", "0x0.8#1", "3.0", "0x3.0#2", "-2.0", "-0x2.0#2"); // - (out[0] >> sh) & 1 != 0 in sub_float_significands_general // - cmp_low >= 0 in sub_float_significands_general // - cmp_low >= 0 && !carry in sub_float_significands_general test("4.0", "0x4.0#1", "1.2", "0x1.4#3", "3.0", "0x3.0#3"); // - cmp_low >= 0 && carry in sub_float_significands_general test("4.0", "0x4.0#1", "0.5", "0x0.8#2", "4.0", "0x4.0#2"); // - rm == Nearest && carry > Limb::power_of_2(sh - 1) in sub_float_significands_general // - goto_truncate in sub_float_significands_general test("3.0", "0x3.0#2", "0.2", "0x0.4#1", "3.0", "0x3.0#2"); // - rm == Nearest && carry <= Limb::power_of_2(sh - 1) && 0 < carry && carry < // Limb::power_of_2(sh - 1) in sub_float_significands_general test("4.0", "0x4.0#1", "0.8", "0x0.c#2", "3.0", "0x3.0#2"); // - max(out_prec, x_prec) + 2 <= exp_diff in sub_float_significands_general // - in round_helper // - dest_prec >= x_prec in round_helper // - !increment_exp in sub_float_significands_general // - inexact == 0 && rm != Down && rm != Floor in sub_float_significands_general test("0.2", "0x0.4#1", "4.0", "0x4.0#2", "-4.0", "-0x4.0#2"); // - diff_exp >= Limb::WIDTH in exponent_shift_compare first time test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", "-9.75459983374e122", "-0x1.79c17f063aE+102#40", ); // - cancel2 < 0 in sub_float_significands_general // - out_len - neg_cancel2 <= ys_len in sub_float_significands_general test( "3.29008365861415556134836580980448399733562188e-9", "0xe.217c389f8c9fd22042f5ed70da20cfb9f1ecE-8#146", "3719044561792922503530448846362960.3599330496921301151502834994", "0xb75cf116bc625ef1eab58f3c9950.5c2492852d5fb6817443c180#205", "-3719044561792922503530448846362960.359933046402046456536127938", "-0xb75cf116bc625ef1eab58f3c9950.5c2492770be37de1e7a3ef60#205", ); // - out_len + cancel1 > xs_len in sub_float_significands_general // - cancel1 < xs_len in sub_float_significands_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", "-0.00374222827281009532032311766811006", "-0x0.00f5402c0bbf2e1505ed1467de9fe#107", ); // - out_len + cancel2 > ys_len in sub_float_significands_general test( "2589062031404.0", "0x25ad01f682c.0#43", "4351572166934988.581719655389852344796925751245753159273257621838622031922945531041952618\ 810238932316", "0xf75bb593981cc.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", "-4348983104903584.58171965538985234479692575124575315927325762183862203192294553104195261\ 8810238932316", "-0xf7360891a19a0.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", ); // - yi >= 0 && lasty != 0 in exponent_shift_compare // - xi < 0 fourth time in exponent_shift_compare // - lasty == 0 in exponent_shift_compare // - yi < 0 || ys[yi] != 0 in exponent_shift_compare // - yi >= 0 fourth time in exponent_shift_compare test( "0.002", "0x0.008#2", "1.107886492190627864290739752375593855464628579e-38", "0x3.c51af197224960473945f6944424f855697e2E-32#149", "0.001953124999999999999999999999999999988921135078", "0x0.007ffffffffffffffffffffffffffffc3ae50e68#149", ); // - cmp_low > 0 && rm == Nearest && xx < yy in sub_float_significands_general // - goto_truncate || goto_end_of_sub first time in sub_float_significands_general // - goto_truncate || goto_end_of_sub second time in sub_float_significands_general test( "1.521287e-9", "0x6.88ac4E-8#21", "6.842391932190563625e-20", "0x1.431f7157e61b20d0E-16#62", "1.5212870962270854807e-9", "0x6.88ac3ffebce08eaE-8#62", ); // - out_len - neg_cancel2 > ys_len in sub_float_significands_general test( "0.00678514868524062", "0x0.01bcabe7b39c71#49", "492541199943575879969.43922949854802247248767794847124160758", "0x1ab361dbc0e97d4121.7071582bb3c5bd22b8f59cfc93c72a98#194", "-492541199943575879969.43244434986278185350564935536210679008", "-0x1ab361dbc0e97d4121.6eb4ac4400294c22b8f59cfc93c72a98#194", ); // - rm == Nearest && sh == 0 && k == 0 in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 && yy < half in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 && cmp_low <= 0 in sub_float_significands_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", "5.7505514701952590309e-7", "0x9.a5d7d21d5a9d47dE-6#64", ); // - rm == Nearest && cmp_low < 0 in sub_float_significands_general // - rm == Nearest && cmp_low < 0 && yy < half in sub_float_significands_general // - cmp_low < 0 in sub_float_significands_general first time // - cmp_low < 0 && rm == Nearest in sub_float_significands_general // - rm == Nearest && (xx > yy || sh > 0 || cmp_low == -1) in sub_float_significands_general test( "8319983682.218895978935307677994592087137128849954503237724", "0x1efe8e042.3809911ec0c7f99b114d2930720001b00aa46846#192", "1.88392800575e35", "0x2.4487b7174E+29#37", "-188392800574747474298435817696599997.78110402106469232200542", "-0x24487b7173fffffffffffe10171fbd.c7f66ee13f380664eec#192", ); // - rm == Nearest && cmp_low < 0 && yy >= half in sub_float_significands_general // - rm == Nearest && xx < yy && sh <= 0 && cmp_low != -1 in sub_float_significands_general // - goto_end_of_sub in sub_float_significands_general test( "2.36288970224581301467472547462526069521e-27", "0xb.b3518c72d51185c09977eb6e009c2c0E-23#128", "3.413020751e-12", "0x3.c0ae105E-10#30", "-3.413020751029435178256669624768773569e-12", "-0x3.c0ae104fffff44cae738d2aee7a3f668E-10#128", ); // - xi >= 0 fourth time in exponent_shift_compare // - diff_exp >= Limb::WIDTH in exponent_shift_compare second time // - xs[xi] == yy in exponent_shift_compare test( "1125899906842624.0", "0x4000000000000.000000000000#98", "1.166815364554e-61", "0x2.ffffffff80E-51#39", "1125899906842624.0", "0x4000000000000.000000000000#98", ); // - 0 < diff_exp < Limb::WIDTH && yi >= 0 in exponent_shift_compare // - xs[xi] != yy in exponent_shift_compare test( "9671406556917033397649408.0", "0x800000000000000000000.0000#99", "65536.015624999999999999946", "0x10000.03ffffffffffffff00#87", "9671406556917033397583871.98438", "0x7fffffffffffffffeffff.fc00#99", ); // - diff_exp == 0 && yi >= 0 in exponent_shift_compare test( "1.3877787807814456370485565165946e-17", "0xf.ffffffffffffe007ffffffff8E-15#101", "128.0000000000000000000000000008077935669463159990585083341", "0x80.00000000000000000000003ffffffffffffe0000000000#190", "-127.9999999999999999861222121929933371964607508331127668586", "-0x7f.ffffffffffffff00000000400001ff7ffffe0008000000#190", ); // - rm == Nearest && xx == yy && sh <= 0 && cmp_low != -1 in sub_float_significands_general // - cmp_low < 0 in sub_float_significands_general second time test( "2.220581574517834801066783605693002897371795957735742517101e-16", "0x1.0003fffffe00000000007ffffffffffffffffffffff000feE-13#192", "8.881784e-16", "0x4.00000E-13#21", "-6.661202622483417522322269739033559602628204042264257482898e-16", "-0x2.fffc000001ffffffffff80000000000000000000000fff00E-13#192", ); // - diff_exp < Limb::WIDTH && yi < 0 in exponent_shift_compare test( "-1.8e-12", "-0x1.fcE-10#7", "-524288.0000000000017621525", "-0x80000.0000000001f00078#81", "524287.9999999999999573739", "0x7ffff.fffffffffff40078#81", ); // - (yi >= 0 || lasty != 0) && high_dif == 0 && dif == 1 in exponent_shift_compare // - xi >= 0 third time in exponent_shift_compare // - yi >= 0 && diff_exp != 0 in exponent_shift_compare // - high_dif != 0 in exponent_shift_compare // - dif == 0 in exponent_shift_compare test( "3.99999999999999999957", "0x3.fffffffffffffff80#67", "4.0", "0x4.00000000000000000#68", "-4.33680868994201773603e-19", "-0x8.0000000000000000E-16#68", ); // - xi < 0 third time in exponent_shift_compare // - cancel1 >= xs_len in sub_float_significands_general test( "6.77626357803440271254657930615627554e-21", "0x1.ffffffffffffffffffffc01fff800E-17#117", "7.0e-21", "0x2.0E-17#4", "-6.99280860154738521672154778865541105e-46", "-0x3.fe000800000000000000000000000E-38#117", ); // - yi >= 0 && diff_exp == 0 in exponent_shift_compare // - dif != 0 in exponent_shift_compare test( "1.45519152351431153846750277125465800054371356958e-11", "0x1.00000001ffffffffffffffffffffffffffffffcE-9#155", "1.455191523514311538467502771254658000526607875496523229114700566610230516799191954282190\ 364e-11", "0x1.00000001fffffffffffffffffffffffc0000000000000000000000000000fffffffffff87f8E-9#301", "1.710569408086637569000134230861426729009957349416545362986887684243433631257558931055548\ 3967e-49", "0x3.ffffffbfffffffffffffffffffff00000000000780800000000000000000000000000000000E-41#301", ); // - xs[xi] == 0 in exponent_shift_compare // - xi < 0 second time in exponent_shift_compare test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", "0.0", "0x0.0", ); // - xi >= 0 second time in exponent_shift_compare test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", "0.0", "0x0.0", ); test( "too_big", "0x4.0E+268435455#1", "-too_big", "-0x4.0E+268435455#1", "Infinity", "Infinity", ); test( "too_big", "0x4.0E+268435455#1", "-1.0", "-0x1.0#1", "too_big", "0x4.0E+268435455#1", ); test( "too_small", "0x1.0E-268435456#1", "-too_small", "-0x1.0E-268435456#1", "too_small", "0x2.0E-268435456#1", ); test( "too_small", "0x1.8E-268435456#2", "too_small", "0x1.0E-268435456#1", "0.0", "0x0.0", ); test( "too_small", "0x1.4E-268435456#3", "too_small", "0x1.0E-268435456#1", "0.0", "0x0.0", ); test( "1.262113616894785778907e-31", "0x2.8f53ace354a6b7284E-26#68", "1.26e-31", "0x2.90E-26#7", "-1.296426623240940697535e-34", "-0xa.c531cab5948d7c00E-29#68", ); test( "too_small", "0x2.8f5E-268435454#14", "too_small", "0x2.900E-268435454#14", "-too_small", "-0x1.0000E-268435456#14", ); test( "-too_small", "-0x2.8f5E-268435454#14", "-too_small", "-0x2.900E-268435454#14", "too_small", "0x1.0000E-268435456#14", ); test( "-too_big", "-0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", "-Infinity", "-Infinity", ); test( "-too_big", "-0x4.0E+268435455#1", "1.0", "0x1.0#1", "-too_big", "-0x4.0E+268435455#1", ); } #[test] fn test_sub_prec() { let test = |s, s_hex, t, t_hex, prec: u64, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (diff, o) = x.clone().sub_prec(y.clone(), prec); assert!(diff.is_valid()); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); assert_eq!(o, o_out); let (diff_alt, o_alt) = x.clone().sub_prec_val_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_prec_ref_val(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_prec_ref_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_prec_assign(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_prec_assign_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (rug_diff, rug_o) = rug_sub_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test("NaN", "NaN", "Infinity", "Infinity", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, "NaN", "NaN", Equal); test("Infinity", "Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, "-Infinity", "-Infinity", Equal, ); test("-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0.0", "0x0.0", 1, "-0.0", "-0x0.0", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", 1, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test("NaN", "NaN", "-123.0", "-0x7b.0#7", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 2, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "4.0", "0x4.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "-2.0", "-0x2.0#1", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, "2.0", "0x2.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 1, "-4.0", "-0x4.0#1", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, "1.000244", "0x1.00100#20", Equal, ); test("1.0", "0x1.0#1", "1.0", "0x1.0#1", 1, "0.0", "0x0.0", Equal); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, "0.0", "0x0.0", Equal, ); test( "0.5", "0x0.8#1", "4.0", "0x4.0#1", 2, "-4.0", "-0x4.0#2", Less, ); test( "8.829e30", "0x6.f70E+25#13", "0.05475", "0x0.0e04#10", 36, "8.8289883602e30", "0x6.f70000000E+25#36", Greater, ); test( "1.6390041924e12", "0x1.7d9c433e8E+10#34", "1.8272611248130303984e40", "0x3.5b2c8ea9f3a386bE+33#62", 40, "-1.827261124813e40", "-0x3.5b2c8ea9f4E+33#40", Less, ); test( "5.96031697199505378e-9", "0x1.9997014b4948928E-7#60", "0.000014", "0x0.0000f#4", 3, "-0.000013", "-0x0.0000e#3", Greater, ); test( "8.7741695e-21", "0x2.96f51f0E-17#27", "1.86647e10", "0x4.5880E+8#16", 11, "-1.866e10", "-0x4.58E+8#11", Greater, ); // - dest_prec < x_prec in round_helper // - sh != 0 in round_helper // - sh != 0 && (rm == Nearest || rb == 0) in round_helper // - sh != 0 && (rm == Nearest || rb == 0) && (n == 0 || sb != 0) in round_helper // - rm == Nearest in round_helper // - rm == Nearest && rb != 0 && sb != 0 in round_helper // - !increment second time in round_helper // - inexact != 0 && inexact != MPFR_EVEN_INEX in sub_float_significands_general test( "1.6390041924e12", "0x1.7d9c433e8E+10#34", "1.8272611248130303984e40", "0x3.5b2c8ea9f3a386bE+33#62", 40, "-1.827261124813e40", "-0x3.5b2c8ea9f4E+33#40", Less, ); // - rm == Nearest && rb == 0 in round_helper test( "13104.5238818416080254535", "0x3330.861d1ed0acba8a3a#77", "2.854e-35", "0x2.5fE-29#10", 17, "13104.5", "0x3330.8#17", Less, ); // - out_len + cancel2 <= 0 in sub_float_significands_general test( "1.73414747294406e-17", "0x1.3fe4cc8cf520E-14#48", "5095194424.1679374580403939884785489", "0x12fb27f38.2afdf3020e8eaac84a7ec#116", 62, "-5095194424.167937458", "-0x12fb27f38.2afdf300#62", Greater, ); // - rm == Nearest && rb != 0 && sb == 0 in round_helper // - xs[o] & ulp != 0 in round_helper // - increment first time in round_helper // - increment_exp in sub_float_significands_general // - inexact != 0 || rm == Down || rm == Floor && (inexact == 0 || inexact == MPFR_EVEN_INEX) in // sub_float_significands_general // - !out[out_len - 1].get_highest_bit() in sub_float_significands_general test( "5.96031697199505378e-9", "0x1.9997014b4948928E-7#60", "0.000014", "0x0.0000f#4", 3, "-0.000013", "-0x0.0000e#3", Greater, ); // - xs[o] & ulp == 0 in round_helper test( "8.7741695e-21", "0x2.96f51f0E-17#27", "1.86647e10", "0x4.5880E+8#16", 11, "-1.866e10", "-0x4.58E+8#11", Greater, ); // - !increment first time in round_helper // - out[out_len - 1].get_highest_bit() in sub_float_significands_general test( "1.3482e25", "0xb.27E+20#12", "1.12202588817e-11", "0xc.5638dc08E-10#36", 11, "1.348e25", "0xb.26E+20#11", Less, ); // - increment second time in round_helper test( "4.53892e18", "0x3.efd8E+15#16", "3412.3125291", "0xd54.5001e8#33", 1, "5.0e18", "0x4.0E+15#1", Greater, ); // - ixs_len > 0 in sub_float_significands_general test( "6058.05208272591415306446968882359605946955168456454", "0x17aa.0d554b247ce1b6ab28ba39c8d5992a74c7ac91a#169", "0.000144566892208323", "0x0.0009796e12f9784#47", 64, "6058.0519381590219448", "0x17aa.0d4bd1b669e84#64", Greater, ); // - sh == 0 in round_helper // - sh == 0 && (rm == Nearest || rb == 0) in round_helper // - sh == 0 && (rm == Nearest || rb == 0) && (n == 0 || sb != 0) in round_helper test( "3.6596517369110659089355442395654891585e48", "0x2.810875a0ca3206afd8c6cf841941830E+40#123", "1545.699550397407201099813420288295", "0x609.b315bc1ec48a143a74bd53048#109", 64, "3.6596517369110659089e48", "0x2.810875a0ca3206b0E+40#64", Greater, ); // - rm == Nearest && cmp_low >= 0 && cmp_low > 0 in sub_float_significands_general // - cmp_low > 0 && rm == Nearest && xx > yy in sub_float_significands_general // - cmp_low == 2 && rm == Nearest && xx > yy in sub_float_significands_general // - cmp_low == 2 && rm == Nearest && xx > yy && !carry in sub_float_significands_general test( "2.80915429604669102593383052436808885401854724410738829e-11", "0x1.ee310ffa09a06a6361f52c2cd8a9569a780b775dc213E-9#177", "519241072363118296470.333928838103121952666621563036", "0x1c25eadc41d4907d96.557c5c3ed81cab65dab0cf920#166", 64, "-5.1924107236311829648e20", "-0x1.c25eadc41d4907daE+17#64", Less, ); // - cmp_low > 0 && cmp_low != 2 && rm == Nearest && xx > yy in sub_float_significands_general test( "559935046210054011882951826578284118061013900.5853448", "0x191bbd3588c78488c2f4d122814d5fb34edb8c.95d928#170", "3.027932e11", "0x4.67fe2E+9#22", 63, "5.599350462100540119e44", "0x1.91bbd3588c78488cE+37#63", Less, ); // - sh != 0 && (rm == Nearest || rb == 0) && n != 0 && sb == 0 in round_helper test( "7184368264698708563285024670194469326968686224.86386349506591", "0x1422880c600dc4fd90a02f1814859aafd658690.dd2628738430#198", "1.0296060328202e-24", "0x1.3ea5cb49bdaE-20#44", 61, "7.184368264698708565e45", "0x1.422880c600dc4feE+38#61", Greater, ); // - not iys_len condition in sub_float_significands_general test( "0.005406335446698931371156460215539762984788400068", "0x0.01624f41ef4d9361bd396d1b5ff5c84cbeacdc10#153", "268934084586659427574577798723115132232.14094768348", "0xca52d21696ccb42e28dd0ff5c50ba548.241525bafe#167", 62, "-2.689340845866594276e38", "-0xc.a52d21696ccb430E+31#62", Less, ); // - out[out_len - 1] >> (Limb::WIDTH - 1) == 0 in sub_float_significands_general test( "64.0", "0x40.000000000000000000000000#101", "3.388131587461699328349286349380665493965593642335603946234186645761911188725141218987660\ 374e-21", "0xf.fffff007f8000000007ffc00ffff00007fffffffffffffff80003ffff800001fffffffff80E-18#298", 32, "64.0", "0x40.0000000#32", Greater, ); // - xi < 0 && yi >= 0 in exponent_shift_compare // - yi < 0 second time in exponent_shift_compare // - xs[xi] != 0 in exponent_shift_compare test( "8.0", "0x8.00#10", "8.000000000000000000001799531422609112", "0x8.0000000000000000087f8000000000#121", 146, "-1.79953142260911170668274960959820418793242425e-21", "-0x8.7f8000000000000000000000000000000000E-18#146", Equal, ); // - yi >= 0 && ys[yi] == 0 in exponent_shift_compare // - yi < 0 fourth time in exponent_shift_compare test( "65536.0", "0x10000.0000000000000000000#90", "1.0e5", "0x2.0E+4#2", 146, "-65536.0", "-0x10000.000000000000000000000000000000000#146", Equal, ); // - rm == Nearest && cmp_low >= 0 && yy >= half in sub_float_significands_general test( "3004622760.998488672936478517", "0xb316e7a8.ff9cf423b0491b4#90", "1355498858579258.8596", "0x4d0d1abf5853a.dc0ec#70", 64, "-1355495853956497.8611", "-0x4d0d0f8de9d91.dc70#64", Greater, ); // - cmp_low == 2 && rm == Nearest && xx > yy && carry in sub_float_significands_general test( "2596143477507256672744148570210303.750244140624999888977803416602752745179193772357882662\ 973853959140044204", "0x7ffff000000000000000001fffff.c00ffffffffff800007ffffffffffffffe000001ffffffff80000001ff\ fc#349", "4.2351647e-22", "0x1.ffffffcE-18#27", 18, "2.59615e33", "0x8.0000E+27#18", Greater, ); // - lasty != 0 in exponent_shift_compare test( "6.2230152778611417071440640537801242403342227837862e-61", "0xf.ffffffffffffffffffffffffffffff1ffff3fffeE-51#163", "6.0e-61", "0x1.0E-50#4", 11, "-2.56e-98", "-0xe.00E-82#11", Greater, ); // - sh == 0 && (rm == Nearest || rb == 0) && n != 0 && sb == 0 in round_helper test( "1.56676e-64", "0x1.07ff8E-53#18", "127.906249999999999993061106096092771622352302164", "0x7f.e7ffffffffffff8000000000000000000001ff8#160", 64, "-127.906249999999999993", "-0x7f.e7ffffffffffff8#64", Greater, ); // - yi < 0 third time in exponent_shift_compare test( "6.9e-18", "0x8.0E-15#6", "6.9388939039072283773e-18", "0x7.fffffffffffffff8E-15#64", 86, "3.7615819226313200254999569e-37", "0x8.000000000000000000000E-31#86", Equal, ); test( "-too_small", "-0x2.50888E-268435456#19", "-too_small", "-0x3.10E-268435456#10", 1, "too_small", "0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x3.10E-268435456#10", "-too_small", "-0x2.50888E-268435456#19", 1, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn sub_prec_fail() { assert_panic!(Float::NAN.sub_prec(Float::NAN, 0)); assert_panic!(Float::NAN.sub_prec_val_ref(&Float::NAN, 0)); assert_panic!(Float::NAN.sub_prec_ref_val(Float::NAN, 0)); assert_panic!(Float::NAN.sub_prec_ref_ref(&Float::NAN, 0)); assert_panic!({ let mut x = Float::NAN; x.sub_prec_assign(Float::NAN, 0) }); assert_panic!({ let mut x = Float::NAN; x.sub_prec_assign_ref(&Float::NAN, 0) }); } #[test] fn test_sub_round() { let test = |s, s_hex, t, t_hex, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (diff, o) = x.clone().sub_round(y.clone(), rm); assert!(diff.is_valid()); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); assert_eq!(o, o_out); let (diff_alt, o_alt) = x.clone().sub_round_val_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_round_ref_val(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_round_ref_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_round_assign(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_round_assign_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); } let (diff_alt, o_alt) = add_prec_round_naive( x.clone(), -&y, max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); }; test("NaN", "NaN", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", Exact, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); // Note different behavior for Floor test( "0.0", "0x0.0", "0.0", "0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0.0", "0x0.0", Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Floor, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Up, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Nearest, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", Exact, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Ceiling, "NaN", "NaN", Equal, ); test("123.0", "0x7b.0#7", "NaN", "NaN", Down, "NaN", "NaN", Equal); test("123.0", "0x7b.0#7", "NaN", "NaN", Up, "NaN", "NaN", Equal); test( "123.0", "0x7b.0#7", "NaN", "NaN", Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Floor, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Down, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Up, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", Exact, "123.0", "0x7b.0#7", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", Down, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-123.0", "-0x7b.0#7", Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Floor, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Ceiling, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Down, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Up, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Nearest, "123.0", "0x7b.0#7", Equal, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", Exact, "123.0", "0x7b.0#7", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", Floor, "3.0", "0x3.0#2", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "4.555806215962889", "0x4.8e4950f079600#53", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "4.555806215962888", "0x4.8e4950f0795fc#53", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Nearest, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Exact, "-1.727379091216698", "-0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Floor, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Ceiling, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Down, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Up, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Nearest, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", Exact, "1.727379091216698", "0x1.ba35842091e63#53", Equal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Ceiling, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Down, "-4.555806215962888", "-0x4.8e4950f0795fc#53", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Up, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", Floor, "-4.555806215962889", "-0x4.8e4950f079600#53", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); // Note different behavior for Floor test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Exact, "0.0", "0x0.0", Equal, ); test( "0.5", "0x0.8#1", "2.0", "0x2.0#1", Down, "-1.0", "-0x1.0#1", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", Nearest, "1.0", "0x1.0#1", Less, ); // - in sub_float_significands_same_prec_lt_w // - x_exp == y_exp in sub_float_significands_same_prec_lt_w // - x == y in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp < y_exp in sub_float_significands_same_prec_lt_w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_lt_w // - leading_zeros != 0 in sub_float_significands_same_prec_lt_w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "2.0", "0x2.0#1", Nearest, "-1.0", "-0x1.0#1", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_lt_w // - neg in sub_float_significands_same_prec_lt_w // - rm == Nearest in sub_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & shift_bit) != 0) in // sub_float_significands_same_prec_lt_w // - rm == Nearest && round_bit != 0 && sticky_bit != 0 && diff == 0 in // sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "4.0", "0x4.0#1", Nearest, "-4.0", "-0x4.0#1", Less, ); // - !neg in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "0.2", "0x0.4#1", Nearest, "1.0", "0x1.0#1", Greater, ); // - x < y in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#2", "1.5", "0x1.8#2", Nearest, "-0.5", "-0x0.8#2", Equal, ); // - x > y in sub_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "1.0", "0x1.0#2", Nearest, "0.5", "0x0.8#2", Equal, ); // - leading_zeros == 0 in sub_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "0.5", "0x0.8#2", Nearest, "1.0", "0x1.0#2", Equal, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff & shift_bit) == 0)) in // sub_float_significands_same_prec_lt_w test( "2.0", "0x2.0#2", "0.8", "0x0.c#2", Nearest, "1.0", "0x1.0#2", Less, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & shift_bit) != 0) && diff != // 0 in sub_float_significands_same_prec_lt_w test( "1.5", "0x1.8#2", "0.1", "0x0.2#2", Nearest, "1.5", "0x1.8#2", Greater, ); // - exp_diff >= Limb::WIDTH in sub_float_significands_same_prec_lt_w // - x <= LIMB_HIGH_BIT in sub_float_significands_same_prec_lt_w test( "1.0e9", "0x4.0E+7#1", "6.0e-11", "0x4.0E-9#1", Nearest, "1.0e9", "0x4.0E+7#1", Greater, ); // - x > LIMB_HIGH_BIT in sub_float_significands_same_prec_lt_w test( "9.2047171e-27", "0x2.d945d78E-22#27", "1.43189635e33", "0x4.69912aE+27#27", Nearest, "-1.43189635e33", "-0x4.69912aE+27#27", Less, ); // - rm == Floor || rm == Down in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "0.2", "0x0.4#1", Down, "0.5", "0x0.8#1", Less, ); // - rm == Ceiling || rm == Up in sub_float_significands_same_prec_lt_w // - (rm == Ceiling || rm == Up) && diff == 0 in sub_float_significands_same_prec_lt_w test( "1.0", "0x1.0#1", "0.2", "0x0.4#1", Up, "1.0", "0x1.0#1", Greater, ); // - (rm == Ceiling || rm == Up) && diff != 0 in sub_float_significands_same_prec_lt_w test( "2.0", "0x2.0#2", "0.8", "0x0.c#2", Up, "1.5", "0x1.8#2", Greater, ); // - in sub_float_significands_same_prec_w // - x_exp == y_exp in sub_float_significands_same_prec_w // - x_exp == y_exp && a0 == 0 in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0", "0x1.0000000000000000#64", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp != y_exp in sub_float_significands_same_prec_w // - x_exp < y_exp in sub_float_significands_same_prec_w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_w // - a0 != 0 in sub_float_significands_same_prec_w // - leading_zeros != 0 in sub_float_significands_same_prec_w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "2.0", "0x2.0000000000000000#64", Nearest, "-1.0", "-0x1.0000000000000000#64", Equal, ); // - a0 > x in sub_float_significands_same_prec_w test( "1.0", "0x1.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "-1.084202172485504434e-19", "-0x2.0000000000000000E-16#64", Equal, ); // - a0 <= x in sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "1.0", "0x1.0000000000000000#64", Nearest, "1.084202172485504434e-19", "0x2.0000000000000000E-16#64", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_w // - neg in sub_float_significands_same_prec_w // - rm == Nearest in sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) in // sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) && // !diff.overflowing_add_assign(1) in sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "4.0", "0x4.0000000000000000#64", Nearest, "-3.0", "-0x3.0000000000000000#64", Less, ); // - !neg in sub_float_significands_same_prec_w test( "4.0", "0x4.0000000000000000#64", "1.0000000000000000001", "0x1.0000000000000002#64", Nearest, "3.0", "0x3.0000000000000000#64", Greater, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff & 1) == 0)) in // sub_float_significands_same_prec_w test( "1.0000000000000000003", "0x1.0000000000000006#64", "4.0", "0x4.0000000000000000#64", Nearest, "-2.9999999999999999996", "-0x2.fffffffffffffff8#64", Greater, ); // - leading_zeros == 0 in sub_float_significands_same_prec_w test( "3.2729513077064011786e-37", "0x6.f5f6d50e7b8f6eb0E-31#64", "7.8519772600462495573e-34", "0x4.13b4f0d218450fb0E-28#64", Nearest, "-7.848704308738543156e-34", "-0x4.13459164c75d56b8E-28#64", Greater, ); // - exp_diff >= Limb::WIDTH in sub_float_significands_same_prec_w // - x > LIMB_HIGH_BIT in sub_float_significands_same_prec_w test( "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", "2.9347251290514630352e-45", "0x1.0c11b075f03d6daeE-37#64", Nearest, "5.9376349676904431794e-6", "0x0.0000639df2b03f3e49a70#64", Greater, ); // - x <= LIMB_HIGH_BIT in sub_float_significands_same_prec_w // - exp_diff != Limb::WIDTH || y <= LIMB_HIGH_BIT in sub_float_significands_same_prec_w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff & 1) != 0) && // diff.overflowing_add_assign(1) in sub_float_significands_same_prec_w test( "8355840.0624923708378", "0x7f8000.0fff8000ff8#64", "2.3384026197294446691e49", "0x1.0000000000000000E+41#64", Nearest, "-2.3384026197294446691e49", "-0x1.0000000000000000E+41#64", Less, ); // - x_exp != y_exp && a0 == 0 in sub_float_significands_same_prec_w test( "63.999999999999999997", "0x3f.ffffffffffffffc#64", "64.0", "0x40.000000000000000#64", Nearest, "-3.4694469519536141888e-18", "-0x4.0000000000000000E-15#64", Equal, ); // - exp_diff == Limb::WIDTH && y > LIMB_HIGH_BIT in sub_float_significands_same_prec_w test( "4.656578456163629198e-10", "0x1.ffff07fffffffffeE-8#64", "4294967296.0", "0x100000000.00000000#64", Nearest, "-4294967295.9999999995", "-0xffffffff.fffffffe#64", Greater, ); // - rm == Floor || rm == Down in sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "4.0", "0x4.0000000000000000#64", Down, "-2.9999999999999999998", "-0x2.fffffffffffffffc#64", Greater, ); // - rm == Ceiling || rm == Up in sub_float_significands_same_prec_w // - (rm == Ceiling || rm == Up) && !diff.overflowing_add_assign(1) in // sub_float_significands_same_prec_w test( "1.0000000000000000001", "0x1.0000000000000002#64", "4.0", "0x4.0000000000000000#64", Up, "-3.0", "-0x3.0000000000000000#64", Less, ); // - (rm == Ceiling || rm == Up) && diff.overflowing_add_assign(1) in // sub_float_significands_same_prec_w test( "7.737125245533626718e25", "0x4.0000000000000000E+21#64", "3.4410713482205469792e-21", "0x1.03fffffffffc0000E-17#64", Up, "7.737125245533626718e25", "0x4.0000000000000000E+21#64", Greater, ); // - in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - a1 == 0 && a0 == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.0", "0x1.0000000000000000#65", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp != y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp < y_exp in sub_float_significands_same_prec_gt_w_lt_2w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp != y_exp && a1 != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp != y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "2.0", "0x2.0000000000000000#65", Nearest, "-1.0", "-0x1.0000000000000000#65", Equal, ); // - (a1 != 0 || a0 != 0) && a1 >= x_1 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp && a1 == 0 in sub_float_significands_same_prec_gt_w_lt_2w // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "-5.42101086242752217e-20", "-0x1.0000000000000000E-16#65", Equal, ); // - (a1 != 0 || a0 != 0) && a1 < x_1 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "1.0", "0x1.0000000000000000#65", Nearest, "5.42101086242752217e-20", "0x1.0000000000000000E-16#65", Equal, ); // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.00000000000000000#66", "1.00000000000000000003", "0x1.00000000000000008#66", Nearest, "-2.710505431213761085e-20", "-0x8.0000000000000000E-17#66", Equal, ); // - x_exp == y_exp && a1 != 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "1.0", "0x1.0000000000000000#65", "1.00000000000000000011", "0x1.0000000000000002#65", Nearest, "-1.084202172485504434e-19", "-0x2.0000000000000000E-16#65", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_gt_w_lt_2w // - neg in sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest in sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // !overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "4.0", "0x4.0000000000000000#65", Nearest, "-3.0", "-0x3.0000000000000000#65", Less, ); // - !neg in sub_float_significands_same_prec_gt_w_lt_2w test( "4.0", "0x4.0000000000000000#65", "1.00000000000000000005", "0x1.0000000000000001#65", Nearest, "3.0", "0x3.0000000000000000#65", Greater, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0)) in // sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000016", "0x1.0000000000000003#65", "4.0", "0x4.0000000000000000#65", Nearest, "-2.9999999999999999998", "-0x2.fffffffffffffffc#65", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && a1 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", "18.63123034252626794758647", "0x12.a1984fcd64a8ae228eef#85", Nearest, "1.44020837962004126031156726e28", "0x2.e891fdf020840728c0894E+23#85", Greater, ); // - x_exp != y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "0.0001507756106295330606262754053", "0x0.0009e19851127b95dcf03f0cdc#91", "3458.565842843038054059107814", "0xd82.90db1399862ba513faf8#91", Nearest, "-3458.565692067427424526047188", "-0xd82.90d132013519297e1e08#91", Less, ); // - exp_diff >= Limb::WIDTH * 2 in sub_float_significands_same_prec_gt_w_lt_2w // - exp_diff >= Limb::WIDTH * 2 && a1 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", "1.14823551075108882469e-96", "0x2.73dea72af3fe6314E-80#65", Nearest, "4.8545822922649671226e27", "0xf.af9dc963a0709f78E+22#65", Greater, ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_gt_w_lt_2w test( "19585.2851423168986928116147584507795", "0x4c81.48ff163dc91a0d4bd90309b0f8#116", "372369974082165972902790.766638151683", "0x4eda377c7f0d747fa386.c44265dd58#116", Nearest, "-372369974082165972883205.481495834785", "-0x4eda377c7f0d747f5705.7b434f9f90#116", Less, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 && a1 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "9.9035203142830421991929938e27", "0x2.000000000000000000000E+23#85", "16.0", "0x10.00000000000000000000#85", Nearest, "9.9035203142830421991929938e27", "0x2.000000000000000000000E+23#85", Greater, ); // - exp_diff >= Limb::WIDTH * 2 && a1 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_w_lt_2w test( "5.3455294200288159103345444e-51", "0x1.ffffffffc000000000000E-42#83", "8.0", "0x8.00000000000000000000#83", Nearest, "-8.0", "-0x8.00000000000000000000#83", Less, ); // - x_exp != y_exp && a1 == 0 in sub_float_significands_same_prec_gt_w_lt_2w test( "4.00000000000000000000084702", "0x4.000000000000000003fffc#89", "3.999999999999999999999999994", "0x3.fffffffffffffffffffffe#89", Nearest, "8.47026484905764768539612568e-22", "0x3.fffe000000000000000000E-18#89", Equal, ); // - rm == Floor || rm == Down in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "4.0", "0x4.0000000000000000#65", Down, "-2.9999999999999999999", "-0x2.fffffffffffffffe#65", Greater, ); // - rm == Ceiling || rm == Up in sub_float_significands_same_prec_gt_w_lt_2w // - (rm == Ceiling || rm == Up) && !overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "1.00000000000000000005", "0x1.0000000000000001#65", "4.0", "0x4.0000000000000000#65", Up, "-3.0", "-0x3.0000000000000000#65", Less, ); // - (rm == Ceiling || rm == Up) && overflow in sub_float_significands_same_prec_gt_w_lt_2w test( "1.5986723171183083380727715984266450731e-36", "0x2.1fffffffffff00000000000000ffff8E-30#123", "2475880078570760549798248448.0", "0x80000000000000000000000.00000000#123", Up, "-2475880078570760549798248448.0", "-0x80000000000000000000000.00000000#123", Less, ); // - in sub_float_significands_same_prec_2w // - x_exp == y_exp in sub_float_significands_same_prec_2w // - a1 == 0 && a0 == 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp != y_exp in sub_float_significands_same_prec_2w // - x_exp < y_exp in sub_float_significands_same_prec_2w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_2w // - a1 != 0 second time in sub_float_significands_same_prec_2w // - a1 != 0 third time in sub_float_significands_same_prec_2w // - x_exp != y_exp && leading_zeros != 0 in sub_float_significands_same_prec_2w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "2.0", "0x2.00000000000000000000000000000000#128", Nearest, "-1.0", "-0x1.00000000000000000000000000000000#128", Equal, ); // - (a1 != 0 || a0 != 0) && a1 >= x_1 in sub_float_significands_same_prec_2w // - a1 == 0 first time in sub_float_significands_same_prec_2w // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_2w test( "1.0", "0x1.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Nearest, "-5.87747175411143753984368268611122838909e-39", "-0x2.00000000000000000000000000000000E-32#128", Equal, ); // - (a1 != 0 || a0 != 0) && a1 < x_1 in sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "1.0", "0x1.00000000000000000000000000000000#128", Nearest, "5.87747175411143753984368268611122838909e-39", "0x2.00000000000000000000000000000000E-32#128", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_2w // - neg in sub_float_significands_same_prec_2w // - rm == Nearest in sub_float_significands_same_prec_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & 1) != 0) && !overflow in // sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "4.0", "0x4.00000000000000000000000000000000#128", Nearest, "-3.0", "-0x3.00000000000000000000000000000000#128", Less, ); // - !neg in sub_float_significands_same_prec_2w test( "4.0", "0x4.00000000000000000000000000000000#128", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", Nearest, "3.0", "0x3.00000000000000000000000000000000#128", Greater, ); // - rm == Nearest && (round_bit == 0 || (sticky_bit == 0 && (diff_0 & 1) == 0)) in // sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000018", "0x1.00000000000000000000000000000006#128", "4.0", "0x4.00000000000000000000000000000000#128", Nearest, "-2.99999999999999999999999999999999999998", "-0x2.fffffffffffffffffffffffffffffff8#128", Greater, ); // - x_exp != y_exp && leading_zeros == 0 in sub_float_significands_same_prec_2w test( "1.91698663575347889601435178329077738407e-37", "0x4.13b4f0d218450fb6f5f6d50e7b8f6eb0E-31#128", "8.0669110092962644724944820639408319804e-34", "0x4.3046c1d7c0f5b6be39df2b03f3e49a70E-28#128", Nearest, "-8.06499402266051099359846771215754120301e-34", "-0x4.30058688b3d4326d3e6fcb96a2fce178E-28#128", Greater, ); // - exp_diff >= Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - x_1 > LIMB_HIGH_BIT || x_0 > 0 in sub_float_significands_same_prec_2w test( "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", "5.07801249136957145270807726205511855421e-45", "0x1.cfd8608b7c32de2bbcfecf8bcf8a2d00E-37#128", Nearest, "5.80991149045382428948889299639419733262e-6", "0x0.00006179613d776a1c835894818a219f488e8#128", Greater, ); // - Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - Limb::WIDTH < exp_diff < Limb::WIDTH * 2 in sub_float_significands_same_prec_2w // - a1 >= LIMB_HIGH_BIT in sub_float_significands_same_prec_2w test( "4354249796990942.35435357526597783143164", "0xf782ac869b7de.5ab6ea78fcf0cc5079f#128", "8.03239453825726512240307053405256016022e-10", "0x3.732bce7aa121827a284545a25f32dc68E-8#128", Nearest, "4354249796990942.35435357446273837760591", "0xf782ac869b7de.5ab6ea7589c4fdd5d8d#128", Greater, ); // - a1 != 0 first time in sub_float_significands_same_prec_2w test( "852777855057.113455599443829872557360137", "0xc68d856851.1d0b6d1928c98779f28bdd#128", "869223500084.503694559376384046083491558", "0xca61c20934.80f2206bb1d7d5cad69caa#128", Nearest, "-16445645027.39023895993255417352613142066", "-0x3d43ca0e3.63e6b352890e4e50e410cd00#128", Equal, ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_2w test( "1.057437459917463716438672572710788562701e-17", "0xc.310127aae1df1a1cb12f60c4d339d76E-15#128", "148.0549133677002965445211858794413066474", "0x94.0e0ecd6e62d0a8c7c7c2a633277e3e#128", Nearest, "-148.054913367700296533946811280266669483", "-0x94.0e0ecd6e62d0a804b7b02b85098c9c#128", Greater, ); // - x_1 <= LIMB_HIGH_BIT && x_0 <= 0 in sub_float_significands_same_prec_2w // - exp_diff != TWICE_WIDTH || tst in sub_float_significands_same_prec_2w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & 1) != 0) && overflow in // sub_float_significands_same_prec_2w test( "3.83123885216472214589586756787577295905e53", "0x4.00000000000000000000000000000000E+44#128", "9.09494703466994132423639742106012939545e-13", "0x1.00000008000000000000007fffffff80E-10#128", Nearest, "3.83123885216472214589586756787577295905e53", "0x4.00000000000000000000000000000000E+44#128", Greater, ); // - a1 < LIMB_HIGH_BIT in sub_float_significands_same_prec_2w test( "0.000473141670219947088192358501321236008969", "0x0.001f01fffffe001ffe000000000003ffff0#128", "144115188075855872.000000000007275846592", "0x200000000000000.0000000007fff80000#128", Nearest, "-144115188075855871.9995268583370558995037", "-0x1ffffffffffffff.ffe0fe000801f7e002#128", Less, ); // - a1 == 0 second time in sub_float_significands_same_prec_2w test( "1.192092895507812500000000000000000918348e-7", "0x2.0000000000000000000000000007fffcE-6#128", "1.19209289550781249999999999999999632658e-7", "0x1.ffffffffffffffffffffffffffe00000E-6#128", Nearest, "4.5917678014072389539175224798764807294e-40", "0x2.7fffc000000000000000000000000000E-33#128", Equal, ); // - exp_diff == TWICE_WIDTH && !tst in sub_float_significands_same_prec_2w test( "1024.0", "0x400.000000000000000000000000000000#128", "5.97151130219911582898625687582100437209e-36", "0x7.f00000001fffffffffffffffe0000000E-30#128", Nearest, "1023.999999999999999999999999999999999994", "0x3ff.fffffffffffffffffffffffffffff8#128", Less, ); // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_2w test( "0.249999999999999999999999999974756451033", "0x0.3ffffffffffffffffffffffe000000000#128", "0.2499999999999999999864474728691747435412", "0x0.3fffffffffffffffc0000001ffffffffc#128", Nearest, "1.35525271055817074916830884337875729072e-20", "0x3.ffffffc0000000040000000000000000E-17#128", Equal, ); // - a1 == 0 third time in sub_float_significands_same_prec_2w test( "8.0", "0x8.0000000000000000000000000000000#128", "7.99999999999999999999999999999999999998", "0x7.fffffffffffffffffffffffffffffff8#128", Nearest, "2.35098870164457501593747307444449135564e-38", "0x8.0000000000000000000000000000000E-32#128", Equal, ); // - rm == Floor || rm == Down in sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "4.0", "0x4.00000000000000000000000000000000#128", Down, "-2.99999999999999999999999999999999999999", "-0x2.fffffffffffffffffffffffffffffffc#128", Greater, ); // - rm == Ceiling || rm == Up in sub_float_significands_same_prec_2w // - (rm == Ceiling || rm == Up) && !overflow in sub_float_significands_same_prec_2w test( "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#128", "4.0", "0x4.00000000000000000000000000000000#128", Up, "-3.0", "-0x3.00000000000000000000000000000000#128", Less, ); // - (rm == Ceiling || rm == Up) && overflow in sub_float_significands_same_prec_2w test( "77371252455336267181195264.0", "0x4000000000000000000000.00000000000#128", "4.93038066207960562897601098365736701192e-32", "0x1.00000003e00000000001ff000000001eE-26#128", Up, "77371252455336267181195264.0", "0x4000000000000000000000.00000000000#128", Greater, ); // - rm == Floor || rm == Down in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "4.0", "0x4.00000000000000000000000000000000#129", Down, "-2.999999999999999999999999999999999999994", "-0x2.fffffffffffffffffffffffffffffffe#129", Greater, ); // - rm == Ceiling || rm == Up in sub_float_significands_same_prec_gt_2w_lt_3w // - (rm == Ceiling || rm == Up) && overflow in sub_float_significands_same_prec_gt_2w_lt_3w // - (rm == Ceiling || rm == Up) && diff_1 == 0 && diff_0 == 0 in // sub_float_significands_same_prec_gt_2w_lt_3w // - (rm == Ceiling || rm == Up) && diff_2 != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "4.0", "0x4.00000000000000000000000000000000#129", Up, "-3.0", "-0x3.00000000000000000000000000000000#129", Less, ); // - (rm == Ceiling || rm == Up) && !overflow in sub_float_significands_same_prec_gt_2w_lt_3w // - (rm == Ceiling || rm == Up) && (diff_1 != 0 || diff_0 != 0) in // sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", "4.0", "0x4.00000000000000000000000000000000#129", Up, "-2.999999999999999999999999999999999999994", "-0x2.fffffffffffffffffffffffffffffffe#129", Less, ); // - (rm == Ceiling || rm == Up) && diff_2 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "3.982729777831130692572200994412995874342180298e-59", "0x3.ffffffffffffffffffffffff800000000000000E-49#155", "9.31322574615478515625e-10", "0x4.00000000000000000000000000000000000000E-8#155", Floor, "-9.31322574615478515625e-10", "-0x4.00000000000000000000000000000000000000E-8#155", Less, ); // - in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp in sub_float_significands_same_prec_gt_2w_lt_3w // - a2 == 0 && a1 == 0 && a0 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp != y_exp in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && sticky_bit == 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && a2 != 0 first time in // sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && leading_zeros != 0 in // sub_float_significands_same_prec_gt_2w_lt_3w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "2.0", "0x2.00000000000000000000000000000000#129", Nearest, "-1.0", "-0x1.00000000000000000000000000000000#129", Equal, ); // - x_exp >= y_exp in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.0", "0x2.00000000000000000000000000000000#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "1.0", "0x1.00000000000000000000000000000000#129", Equal, ); // - (a2 != 0 || a1 != 0 || a0 != 0) && a2 >= x_2 in // sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && a2 == 0 first time in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && a2 == 0 second time in sub_float_significands_same_prec_gt_2w_lt_3w // - x_exp == y_exp && leading_zeros == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "-2.93873587705571876992184134305561419455e-39", "-0x1.00000000000000000000000000000000E-32#129", Equal, ); // - (a2 != 0 || a1 != 0 || a0 != 0) && a2 < x_2 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "1.0", "0x1.00000000000000000000000000000000#129", Nearest, "2.93873587705571876992184134305561419455e-39", "0x1.00000000000000000000000000000000E-32#129", Equal, ); // - x_exp == y_exp && leading_zeros != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.000000000000000000000000000000000#130", "1.000000000000000000000000000000000000001", "0x1.000000000000000000000000000000008#130", Nearest, "-1.469367938527859384960920671527807097273e-39", "-0x8.00000000000000000000000000000000E-33#130", Equal, ); // - x_exp == y_exp && a2 != 0 second time in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.0", "0x1.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000006", "0x1.00000000000000000000000000000002#129", Nearest, "-5.87747175411143753984368268611122838909e-39", "-0x2.00000000000000000000000000000000E-32#129", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - neg in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) in // sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // overflow in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && diff_1 // == 0 && diff_0 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && diff_2 != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", "4.0", "0x4.00000000000000000000000000000000#129", Nearest, "-3.0", "-0x3.00000000000000000000000000000000#129", Less, ); // - !neg in sub_float_significands_same_prec_gt_2w_lt_3w test( "4.0", "0x4.00000000000000000000000000000000#129", "1.000000000000000000000000000000000000003", "0x1.00000000000000000000000000000001#129", Nearest, "3.0", "0x3.00000000000000000000000000000000#129", Greater, ); // - rm == Nearest && round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0) in // sub_float_significands_same_prec_gt_2w_lt_3w test( "1.000000000000000000000000000000000000009", "0x1.00000000000000000000000000000003#129", "4.0", "0x4.00000000000000000000000000000000#129", Nearest, "-2.999999999999999999999999999999999999988", "-0x2.fffffffffffffffffffffffffffffffc#129", Greater, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // (diff_1 != 0 || diff_0 != 0) in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.000000000000000000000000000000000000006", "0x2.00000000000000000000000000000002#129", "0.500000000000000000000000000000000000001", "0x0.800000000000000000000000000000008#129", Nearest, "1.500000000000000000000000000000000000006", "0x1.80000000000000000000000000000002#129", Greater, ); // - rm == Nearest && round_bit != 0 && (sticky_bit != 0 || (diff_0 & shift_bit) != 0) && // !overflow in sub_float_significands_same_prec_gt_2w_lt_3w test( "2.000000000000000000000000000000000000003", "0x2.00000000000000000000000000000001#130", "0.5000000000000000000000000000000000000007", "0x0.800000000000000000000000000000004#130", Nearest, "1.500000000000000000000000000000000000003", "0x1.800000000000000000000000000000010#130", Greater, ); // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - TWICE_WIDTH < exp_diff < THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "2.024076700393272432111968987625898501371897741e-29", "0x1.9a88122864b9c4b577e4b655958954f82345dE-24#149", "245906107849378561117126906.9059035528266331265", "0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Nearest, "-245906107849378561117126906.9059035528266331265", "-0xcb68a4d1611415054400fa.e7e94b94b8791630#149", Less, ); // - exp_diff >= THRICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff >= THRICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", "6.8892360159362421595728818935378487832685754059e-50", "0x1.9c693c182df3035eef00d41638bbdd942f4d498E-41#155", Nearest, "4.397610888919711045634814958598336677777534377e47", "0x4.d0791b9428a6b4fc52e44e537ab5a0f269ad60E+39#155", Greater, ); // - exp_diff < Limb::WIDTH && leading_zeros == 0 in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.9709672065181108960570410290811793724062284431352e-48", "0x7.43dc113e95ca123693650af31435eac45c0e7a680E-40#165", "5.2183974782595301717751266872943662193587933931613e-47", "0x4.c4457ca8b3429511981a96eb0c2de4fdb8c43bea4E-39#165", Nearest, "-4.7213007576077190821694225843862482821181705488478e-47", "-0x4.5007bb94c9e5f3ee2ee4463bdaea865173035443cE-39#165", Equal, ); // - exp_diff < Limb::WIDTH && sticky_bit != 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "8.264811372870109665580646414654919646529224699888394e-20", "0x1.864b7049feb3dcfe49ea910db778157cbe9c2021b44E-16#171", "0.0007337187065343299500100945131574173571435306249470578", "0x0.003015c1d959ec54ab97dc58b77c22566586c06119b810#171", Nearest, "-0.0007337187065343298673619807844563207013370664783978612", "-0x0.003015c1d959ec53254c6c0eb8c845581b9c2f53623ff8#171", Greater, ); // - Limb::WIDTH <= exp_diff < TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH && sticky_bit != 0 in // sub_float_significands_same_prec_gt_2w_lt_3w // - Limb::WIDTH < exp_diff < TWICE_WIDTH && a2 >= LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "4.2850537238606374652351877988811796373898773e-22", "0x2.0607fd4819748c532aad3528693c1e3c1966E-18#146", "978.49328809934495391839880801989439981236569", "0x3d2.7e4820fe314caadcb9a156bef2f1c8e53c#146", Nearest, "-978.49328809934495391839837951452201374861917", "-0x3d2.7e4820fe314caadcb79b4ec1aad85458e9#146", Less, ); // - Limb::WIDTH < exp_diff < TWICE_WIDTH && sticky_bit == 0 in // sub_float_significands_same_prec_gt_2w_lt_3w test( "0.4575080253178526499352273198671695352442", "0x0.751f3ef665d0ca4dfa2d089979c4e9600#130", "184366716174337778394.1535133791267987587", "0x9fe9a278b38ab22da.274ca71ed919c918#130", Nearest, "-184366716174337778393.6960053538089461089", "-0x9fe9a278b38ab22d9.b22d68287348fecc#130", Less, ); // - x_exp == y_exp && a2 != 0 first time in sub_float_significands_same_prec_gt_2w_lt_3w test( "229.1456159244630209666077998586332154002628588961962846344", "0xe5.254715d158717849f7198986a38cb415eeea3464b1df38#189", "175.1335582002789888688278442018847623084238889142385801004", "0xaf.2230dec64f958583522e37252cf610378914f3127d0bb0#189", Nearest, "54.01205772418403209777995565674845309183896998195770453405", "0x36.0316370b08dbf2c6a4eb52617696a3de65d5415234d388#189", Equal, ); // - exp_diff == TWICE_WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w test( "563971925627753843356041629019151473018178607215.42", "0x62c960337e963a378ba6626ea422d8a5e623986f.6c#165", "1301375421.83361702516620516356439489325145225661938", "0x4d9169bd.d567ece47a47ef60371d48c969ba8765d4#165", Nearest, "563971925627753843356041629019151473016877231793.59", "0x62c960337e963a378ba6626ea422d8a598922eb1.98#165", Greater, ); // - exp_diff == Limb::WIDTH in sub_float_significands_same_prec_gt_2w_lt_3w test( "226.9305090753243797994707628568605406194", "0xe2.ee35d7bf263fda8c632644ad7c49d98#130", "4262448175090788889452.984188256984861391", "0xe71159efd3a67e736c.fbf3c2f8db72fb8#130", Nearest, "-4262448175090788889226.053679181660481592", "-0xe71159efd3a67e728a.0dbdeb39b533210#130", Less, ); // - TWICE_WIDTH <= exp_diff < THRICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w // - rm == Nearest && diff_2 == 0 in sub_float_significands_same_prec_gt_2w_lt_3w test( "0.0001220703125", "0x0.0008000000000000000000000000000000000000#145", "8.2855746158774225568154012162196749515653053e-50", "0x1.f0000fc000000000000003fffffffffffffcE-41#145", Nearest, "0.0001220703125", "0x0.0008000000000000000000000000000000000000#145", Greater, ); // - Limb::WIDTH < exp_diff < TWICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "0.0156250000000000000000000000252435487789932816416198", "0x0.040000000000000000000001ffffffc00000000003f#167", "2.11758236813575084767080625169910490512847748461541e-22", "0xf.ffffffffffffffffffffffffffffffffff0000000E-19#167", Nearest, "0.0156249999999999999997882417884299736942262010164499", "0x0.03ffffffffffffffff000001ffffffc00000000003f0#167", Less, ); // - exp_diff >= THRICE_WIDTH && a2 < LIMB_HIGH_BIT in // sub_float_significands_same_prec_gt_2w_lt_3w test( "1.028440348325753776346855739098344065614209916020987e62", "0x4.000000000000000000000000000000000000000000E+51#168", "0.00781238079073842683897073489057921223679527623088422", "0x0.01fffe000007e000000038000007fffffffffe000000#168", Nearest, "1.028440348325753776346855739098344065614209916020987e62", "0x4.000000000000000000000000000000000000000000E+51#168", Greater, ); // - exp_diff < Limb::WIDTH && a2 == 0 first time in // sub_float_significands_same_prec_gt_2w_lt_3w // - exp_diff < Limb::WIDTH && a2 != 0 second time in // sub_float_significands_same_prec_gt_2w_lt_3w test( "32767.9999999999999999999999999999999999999999996", "0x7fff.fffffffffffffffffffffffffffffffffff8#156", "32768.0000000000000000069388939039072268369037424", "0x8000.000000000000007ffffffffffff80000000#156", Nearest, "-6.93889390390722683690374277451135137549581608853e-18", "-0x7.ffffffffffff800000008000000000000000000E-15#156", Equal, ); // - exp_diff < Limb::WIDTH && a2 == 0 second time in // sub_float_significands_same_prec_gt_2w_lt_3w test( "137438953471.99999999999999999999999999999", "0x1fffffffff.ffffffffffffffffffffffff#133", "137438953472.0", "0x2000000000.000000000000000000000000#133", Nearest, "-1.2621774483536188886587657044524579674771e-29", "-0x1.000000000000000000000000000000000E-24#133", Equal, ); // - in sub_float_significands_same_prec_ge_3w // - x_exp == y_exp in sub_float_significands_same_prec_ge_3w // - k < 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "0.0", "0x0.0", Equal, ); // - x_exp > y_exp in sub_float_significands_same_prec_ge_3w // - exp_diff == 1 in sub_float_significands_same_prec_ge_3w // - !goto_sub_d1_no_lose && !goto_sub_d1_lose in sub_float_significands_same_prec_ge_3w // - limb < LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - exp_diff == 0 in sub_float_significands_same_prec_ge_3w // - goto_exact_normalize in sub_float_significands_same_prec_ge_3w // - limb != 0 in sub_float_significands_same_prec_ge_3w // - exp_diff == 0 && limb != 0 && leading_zeros == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Equal, ); // - k >= 0 && xs[k] < ys[k] in sub_float_significands_same_prec_ge_3w // - !goto_exact_normalize in sub_float_significands_same_prec_ge_3w // - limb == 0 in sub_float_significands_same_prec_ge_3w // - out[usize::exact_from(k)] != 0 in sub_float_significands_same_prec_ge_3w // - limb == 0 && leading_zeros != 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "-3.186183822264904554057760795535423611182209110385237572148e-58", "-0x2.000000000000000000000000000000000000000000000000E-48#192", Equal, ); // - k >= 0 && xs[k] >= ys[k] in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "1.0", "0x1.000000000000000000000000000000000000000000000000#192", Nearest, "3.186183822264904554057760795535423611182209110385237572148e-58", "0x2.000000000000000000000000000000000000000000000000E-48#192", Equal, ); // - exp_diff == 0 && limb != 0 && leading_zeros != 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Nearest, "0.9999999999999999999999999999999999999999999999999999999997", "0x0.fffffffffffffffffffffffffffffffffffffffffffffffe#192", Equal, ); // - 2 <= exp_diff < prec in sub_float_significands_same_prec_ge_3w // - dm != 0 && m == 0 in sub_float_significands_same_prec_ge_3w // - sx != 0 in sub_float_significands_same_prec_ge_3w // - !out[n - 1].get_highest_bit() in sub_float_significands_same_prec_ge_3w // - round_bit == 0 in sub_float_significands_same_prec_ge_3w // - round_bit == 0 && sticky_bit == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#192", "0.5", "0x0.800000000000000000000000000000000000000000000000#192", Nearest, "1.5", "0x1.800000000000000000000000000000000000000000000000#192", Equal, ); // - limb == 0 && leading_zeros == 0 in sub_float_significands_same_prec_ge_3w test( "1.0", "0x1.000000000000000000000000000000000000000000000000#193", "1.0000000000000000000000000000000000000000000000000000000002", "0x1.000000000000000000000000000000000000000000000001#193", Nearest, "-1.5930919111324522770288803977677118055911045551926187860739e-58", "-0x1.000000000000000000000000000000000000000000000000E-48#193", Equal, ); // - sx == 0 in sub_float_significands_same_prec_ge_3w test( "2.0", "0x2.000000000000000000000000000000000000000000000000#193", "0.5", "0x0.8000000000000000000000000000000000000000000000000#193", Nearest, "1.5", "0x1.800000000000000000000000000000000000000000000000#193", Equal, ); // - round_bit != 0 || sticky_bit != 0 in sub_float_significands_same_prec_ge_3w // - out_power_of_2 || round_bit == 0 in sub_float_significands_same_prec_ge_3w // - rm == Nearest in sub_float_significands_same_prec_ge_3w // - rm == Nearest && !out_power_of_2 first time in sub_float_significands_same_prec_ge_3w // - rm == Nearest && (round_bit == 0 || (round_bit != 0 && sticky_bit == 0 && (out[0] & // shift_bit == 0 || prec == 1))) in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", Nearest, "-3.0", "-0x3.000000000000000000000000000000000000000000000000#192", Less, ); // - out[usize::exact_from(k)] == 0 in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000002", "0x1.000000000000000000000000000000000000000000000001#193", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#193", Nearest, "-1.5930919111324522770288803977677118055911045551926187860739e-58", "-0x1.000000000000000000000000000000000000000000000000E-48#193", Equal, ); // - round_bit != 0 in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000006", "0x1.000000000000000000000000000000000000000000000004#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", Nearest, "-2.9999999999999999999999999999999999999999999999999999999994", "-0x2.fffffffffffffffffffffffffffffffffffffffffffffffc#192", Equal, ); // - rm == Nearest && round_bit != 0 && (round_bit == 0 || sticky_bit != 0 || (out[0] & // shift_bit != 0 && prec == 1)) in sub_float_significands_same_prec_ge_3w // - rm == Nearest && !out_power_of_2 second time in sub_float_significands_same_prec_ge_3w test( "1.000000000000000000000000000000000000000000000000000000001", "0x1.000000000000000000000000000000000000000000000006#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", Nearest, "-2.9999999999999999999999999999999999999999999999999999999987", "-0x2.fffffffffffffffffffffffffffffffffffffffffffffff8#192", Greater, ); // - sticky_bit_2 == 0 && k > 0 third time in sub_float_significands_same_prec_ge_3w test( "0.5", "0x0.8000000000000000000000000000000000000000000000000#193", "4.0", "0x4.000000000000000000000000000000000000000000000000#193", Nearest, "-3.5", "-0x3.800000000000000000000000000000000000000000000000#193", Equal, ); // - sticky_bit_2 != 0 || k <= 0 third time in sub_float_significands_same_prec_ge_3w test( "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "0.5000000000000000000000000000000000000000000000000000000002", "0x0.800000000000000000000000000000000000000000000001#192", Nearest, "3.5", "0x3.800000000000000000000000000000000000000000000000#192", Greater, ); // - dm != 0 && m != 0 in sub_float_significands_same_prec_ge_3w // - out[n - 1].get_highest_bit() in sub_float_significands_same_prec_ge_3w test( "7.28057116938384227432903448367767196428679514765398378973101e-48", "0xa.a3fc2da1f20fb2d9771f86d3c16a444cd62d5d139e3935f24E-40#198", "3.5123473778825578958968695187657587760357139395948269588971e-27", "0x1.1646de419a6dbd3466f3081403a87d719b7a765a1ec69e4658E-22#198", Nearest, "-3.51234737788255789588958894759637493376138490511114928693281e-27", "-0x1.1646de419a6dbd345c4f0be661b66dbec20356d34b05340208E-22#198", Greater, ); // - exp_diff >= prec in sub_float_significands_same_prec_ge_3w // - exp_diff > prec in sub_float_significands_same_prec_ge_3w // - exp_diff != prec + 1 in sub_float_significands_same_prec_ge_3w test( "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", "0.023991386767031193042066748710708351501952890752924613005724", "0x0.06244cad8cd272134e34b325815ad281733f2c06231a0ee744#193", Nearest, "4.1322282880219162156901559575161649173615955518072607291207e86", "0xd.4b575f05941ee41ef3ef9a37068d9d453f22eb3bf80bd1b0E+71#193", Greater, ); // - dm == 0 in sub_float_significands_same_prec_ge_3w test( "6.442552350746554109885349691592991892989624685631192235549e-6", "0x0.00006c168d38e231899f0fc85d1888549d5177bdceaee72e15060#192", "1476808010161862576835936576709144.7975622615653024045505082", "0x48cff00a780a50d34bb694ada218.cc2d0a55f25f9f9126258#192", Nearest, "-1476808010161862576835936576709144.7975558190129516579963983", "-0x48cff00a780a50d34bb694ada218.cc2c9e3f6526bd5f9c868#192", Less, ); // - exp_diff == prec + 1 in sub_float_significands_same_prec_ge_3w // - sticky_bit_2 != 0 || k <= 0 second time in sub_float_significands_same_prec_ge_3w test( "29249291732025621624535078208.59212499364958152526111994335", "0x5e827271f9e9d261e7cb5540.979580eade814aae28ae9d3c8#192", "1.7056859397843570965021420438616279890690624515282312011749e-30", "0x2.2986d80d04731f28b49380410e3f4711dc2cc5f113c594a0E-25#192", Nearest, "29249291732025621624535078208.59212499364958152526111994335", "0x5e827271f9e9d261e7cb5540.979580eade814aae28ae9d3c8#192", Greater, ); // - limb > LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - y0 != 0 in sub_float_significands_same_prec_ge_3w test( "1958139908729.1847354007541959640287427302874567071533816044", "0x1c7ea3bd279.2f4ad1b8a7190307771c7e5767590237208b90#192", "688604646855.2266320591592881661509057171162297144871538944", "0xa054090dc7.3a048f025074a63da83a500a235d2b8fd9766d#192", Nearest, "1269535261873.9581033415949077978778370131712269926662277102", "0x1279632c4b1.f54642b656a45cc9cee22e4d43fbd6a7471524#192", Greater, ); // - y0 == 0 in sub_float_significands_same_prec_ge_3w test( "2473299914875391681216.10395653853096422269749051583697615", "0x8613ee70797f97a2c0.1a9ce54d32239153edab6ff15dad1c0#193", "7716446651886500012256.87778108230244207876352217543002925", "0x1a24f3592677b2760e0.e0b642d189564d3b4c797ad9c9cde8#193", Nearest, "-5243146737011108331040.7738245437714778560660316595930531", "-0x11c3b4721edfb8fbe20.c6195d845732bbe75ece0ae86c20cc#193", Equal, ); // - exp_diff == prec in sub_float_significands_same_prec_ge_3w // - sticky_bit_2 != 0 || k <= 0 first time in sub_float_significands_same_prec_ge_3w test( "4.0635838402455207229400698207668893925379768151364313942222e-23", "0x3.1202ecf10ff40b477337957dede18bd7b746884ec977474eE-19#194", "1174582238252884689829665592721065057.76655867827770290150723", "0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d4#194", Nearest, "-1174582238252884689829665592721065057.76655867827770290150718", "-0xe237601fa3ed6d89b0ae33e924c461.c43d3085aaefab6b5d0#194", Greater, ); // - rm == Nearest && out_power_of_2 first time in sub_float_significands_same_prec_ge_3w test( "22300745198530623141535718272648361505980416.0", "0x1000000000000000000000000000000000000.000000000000#192", "8.470329472543003387009805160583577341645369940072346001613e-22", "0x3.ffffffffffffffe000000003ff0000003ffffffc00000000E-18#192", Nearest, "22300745198530623141535718272648361505980416.0", "0x1000000000000000000000000000000000000.000000000000#192", Greater, ); // - sticky_bit_2 == 0 && k > 0 second time in sub_float_significands_same_prec_ge_3w test( "1.6849966666969146159452711670928107852024276704905067469395e66", "0xf.ffffffffffff01fffff00000000000000000000000000000E+54#193", "33554432.00000000000000044408920985006261616945266723632812", "0x2000000.0000000000001ffffffffffffffffffffffffffffe#193", Nearest, "1.6849966666969146159452711670928107852024276704905067469395e66", "0xf.ffffffffffff01fffff00000000000000000000000000000E+54#193", Greater, ); // - limb == LIMB_HIGH_BIT in sub_float_significands_same_prec_ge_3w // - l >= 0 first time in sub_float_significands_same_prec_ge_3w // - xs[l] != yl_shifted in sub_float_significands_same_prec_ge_3w // - l >= 0 && xs[l] <= yl_shifted in sub_float_significands_same_prec_ge_3w // - goto_sub_d1_no_lose || goto_sub_d1_lose in sub_float_significands_same_prec_ge_3w test( "2047.9999999999999999999999999999747564510329303127198868805", "0x7ff.fffffffffffffffffffffffe00000000003c000003fffc#193", "4095.99999999999999988897769753748434595763683319091796875", "0xfff.fffffffffffff800000000000000000000000000000000#193", Nearest, "-2047.9999999999999998889776975375095895066039028781980818695", "-0x7ff.fffffffffffff80000000001ffffffffffc3fffffc0004#193", Equal, ); // - sticky_bit_2 == 0 && k > 0 first time in sub_float_significands_same_prec_ge_3w test( "0.0002442598197376355528831482438462803411504065058668775410457", "0x0.001001fff000000000000003ffff00000001fffffff07fffffe#192", "5.834076822994820350447560050418866475553361427251759468222e-62", "0x1.8000000000000000000000000000000000001c00007ffffeE-51#192", Nearest, "0.00024425981973763555288314824384628034115040650586687754104564", "0x0.001001fff000000000000003ffff00000001fffffff07fffffc#192", Less, ); // - l >= 0 && xs[l] > yl_shifted in sub_float_significands_same_prec_ge_3w test( "127.99999999999999999999998841947063540272586186468301133273", "0x7f.fffffffffffffffffff1fffff00007ffffffffffffffff8#192", "255.99999999999999999999999979320484686174308128214782699291", "0xff.ffffffffffffffffffffc00000000000000000000000ff#192", Nearest, "-128.0000000000000000000000113737342114590172194174648156602", "-0x80.0000000000000000000dc0000ffff80000000000000100#192", Less, ); // - out_power_of_2 && round_bit != 0 in sub_float_significands_same_prec_ge_3w test( "81129638414606681695789005144064.0", "0x400000000000000000000000000.0000000000000000000000#193", "6.46392625738094777466974989455420015132331189664152496326e-27", "0x2.001ffffffffe0000001fffff000000ffffff80000000000eE-22#193", Nearest, "81129638414606681695789005144063.999999999999999999999999994", "0x3ffffffffffffffffffffffffff.fffffffffffffffffffffe#193", Greater, ); // - rm == Nearest && out_power_of_2 second time in sub_float_significands_same_prec_ge_3w test( "9.5367431640625e-7", "0x0.00001000000000000000000000000000000000000000000000000#192", "7.596455102175746880546879414772134233793171691679642324806e-65", "0x8.00000ffffffffffe000000000000000000000000001ffffE-54#192", Nearest, "9.536743164062499999999999999999999999999999999999999999998e-7", "0xf.fffffffffffffffffffffffffffffffffffffffffffffffE-6#192", Less, ); // - xs[l] == yl_shifted in sub_float_significands_same_prec_ge_3w test( "1180591620717411303423.9999999999999999999999999999999999998", "0x3fffffffffffffffff.ffffffffffffffffffffffffffffffc#192", "2361183241434822606847.9999999999999999930619531290400259223", "0x7fffffffffffffffff.ffffffffffffff8003ffffffffffff8#192", Nearest, "-1180591620717411303423.9999999999999999930619531290400259225", "-0x3fffffffffffffffff.ffffffffffffff8003ffffffffffffc#192", Equal, ); // - l < 0 first time in sub_float_significands_same_prec_ge_3w // - l < 0 second time in sub_float_significands_same_prec_ge_3w // - yl_shifted != 0 in sub_float_significands_same_prec_ge_3w test( "32767.999999999999999999999999999999999999999999999999999995", "0x7fff.ffffffffffffffffffffffffffffffffffffffffffff8#192", "65535.99999999999999999999999999999999999999999999999999999", "0xffff.ffffffffffffffffffffffffffffffffffffffffffff#192", Nearest, "-32767.999999999999999999999999999999999999999999999999999995", "-0x7fff.ffffffffffffffffffffffffffffffffffffffffffff8#192", Equal, ); // - yl_shifted == 0 in sub_float_significands_same_prec_ge_3w test( "34359738367.999999999999999999999999999999999999999999999989", "0x7ffffffff.fffffffffffffffffffffffffffffffffffffff0#192", "68719476735.99999999999999999999999999999999999999999999999", "0xfffffffff.fffffffffffffffffffffffffffffffffffffff#192", Nearest, "-34359738368.0", "-0x800000000.000000000000000000000000000000000000000#192", Equal, ); // - neg in sub_float_significands_same_prec_ge_3w // - rm == Down || rm == Floor in sub_float_significands_same_prec_ge_3w // - (rm == Down || rm == Floor) && !out_power_of_2 in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", Down, "-2.9999999999999999999999999999999999999999999999999999999994", "-0x2.fffffffffffffffffffffffffffffffffffffffffffffffc#192", Greater, ); // - !neg in sub_float_significands_same_prec_ge_3w test( "4.0", "0x4.000000000000000000000000000000000000000000000000#192", "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", Down, "2.9999999999999999999999999999999999999999999999999999999994", "0x2.fffffffffffffffffffffffffffffffffffffffffffffffc#192", Less, ); // - rm == Up || rm == Ceiling in sub_float_significands_same_prec_ge_3w test( "1.0000000000000000000000000000000000000000000000000000000003", "0x1.000000000000000000000000000000000000000000000002#192", "4.0", "0x4.000000000000000000000000000000000000000000000000#192", Up, "-3.0", "-0x3.000000000000000000000000000000000000000000000000#192", Less, ); // - (rm == Down || rm == Floor) && out_power_of_2 in sub_float_significands_same_prec_ge_3w test( "5.392603845001725202291044579550746038551121674218581060912e-33", "0x1.c0000000fffffffffffffffffffffffffffffffffffffffeE-27#192", "1329227995784915872903807060280344576.0", "0x1000000000000000000000000000000.000000000000000000#192", Ceiling, "-1329227995784915872903807060280344575.9999999999999999999998", "-0xffffffffffffffffffffffffffffff.ffffffffffffffffff#192", Greater, ); test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "-0.5", "-0x0.8#2", Equal, ); test( "0.5", "0x0.8#1", "3.0", "0x3.0#2", Nearest, "-2.0", "-0x2.0#2", Greater, ); test( "0.2", "0x0.4#1", "4.0", "0x4.0#2", Nearest, "-4.0", "-0x4.0#2", Less, ); test( "0.00374222828352849", "0x0.00f5402c178824#46", "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", Nearest, "0.00374222827281009532032311766811006", "0x0.00f5402c0bbf2e1505ed1467de9fe#107", Less, ); test( "2589062031404.0", "0x25ad01f682c.0#43", "4351572166934988.581719655389852344796925751245753159273257621838622031922945531041952618\ 810238932316", "0xf75bb593981cc.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", Nearest, "-4348983104903584.58171965538985234479692575124575315927325762183862203192294553104195261\ 8810238932316", "-0xf7360891a19a0.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", Equal, ); // - in sub_float_significands_general // - in exponent_shift_compare // - sdiff_exp >= 0 in exponent_shift_compare // - diff_exp == 0 first time in exponent_shift_compare // - xi >= 0 && yi >= 0 && xs[xi] == ys[yi] in exponent_shift_compare // - xi < 0 in exponent_shift_compare // - xi < 0 && yi < 0 in exponent_shift_compare // - sign == Equal in sub_float_significands_general test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Nearest, "0.0", "0x0.0", Equal, ); // - diff_exp != 0 first time in exponent_shift_compare // - diff_exp < Limb::WIDTH in exponent_shift_compare // - diff_exp != 0 second time in exponent_shift_compare // - (yi < 0 && lasty == 0) || high_dif != 0 || dif != 1 in exponent_shift_compare // - high_dif == 0 in exponent_shift_compare // - dif.is_power_of_2() in exponent_shift_compare // - yi < 0 && lasty == 0 in exponent_shift_compare // - sign != Equal in sub_float_significands_general // - sign != Less in sub_float_significands_general // - !neg in sub_float_significands_general // - max(out_prec, x_prec) + 2 > exp_diff in sub_float_significands_general // - shift_x != 0 in sub_float_significands_general // - shift_y == 0 in sub_float_significands_general // - cancel >= exp_diff in sub_float_significands_general // - out_len + cancel1 <= xs_len in sub_float_significands_general // - out_len + cancel2 > 0 in sub_float_significands_general // - cancel2 >= 0 in sub_float_significands_general // - out_len + cancel2 <= ys_len in sub_float_significands_general // - rm == Nearest in sub_float_significands_general // - rm == Nearest && carry <= Limb::power_of_2(sh - 1) && (0 >= carry || carry >= // Limb::power_of_2(sh - 1)) in sub_float_significands_general // - !goto_truncate in sub_float_significands_general // - ixs_len <= 0 && iys_len <= 0 in sub_float_significands_general // - !goto_truncate && !goto_end_of_sub second time in sub_float_significands_general // - rm != Nearest || cmp_low == 0 in sub_float_significands_general // - !goto_end_of_sub in sub_float_significands_general // - out[out_len - 1] >> (Limb::WIDTH - 1) != 0 in sub_float_significands_general // - cancel != 0 in sub_float_significands_general test( "2.0", "0x2.0#1", "1.0", "0x1.0#2", Nearest, "1.0", "0x1.0#2", Equal, ); // - sdiff_exp < 0 in exponent_shift_compare // - sign == Less in sub_float_significands_general // - neg in sub_float_significands_general test( "1.0", "0x1.0#2", "2.0", "0x2.0#1", Nearest, "-1.0", "-0x1.0#2", Equal, ); // - xi < 0 || yi < 0 || xs[xi] != ys[yi] in exponent_shift_compare // - xi >= 0 in exponent_shift_compare // - yi >= 0 second time in exponent_shift_compare // - xs[xi] < ys[yi] in exponent_shift_compare // - diff_exp == 0 second time in exponent_shift_compare // - shift_y != 0 in sub_float_significands_general test( "1.0", "0x1.0#1", "1.5", "0x1.8#2", Nearest, "-0.5", "-0x0.8#2", Equal, ); // - xs[xi] >= ys[yi] in exponent_shift_compare test( "1.5", "0x1.8#2", "1.0", "0x1.0#1", Nearest, "0.5", "0x0.8#2", Equal, ); // - shift_x == 0 in sub_float_significands_general // - cancel < exp_diff in sub_float_significands_general // - ixs_len > 0 || iys_len > 0 in sub_float_significands_general // - ixs_len <= 0 in sub_float_significands_general // - iys_len condition in sub_float_significands_general // - cmp_low == 0 first time in sub_float_significands_general // - rm == Nearest && (sh != 0 || k != 0) in sub_float_significands_general // - cmp_low == 0 second time in sub_float_significands_general // - !goto_truncate && !goto_end_of_sub first time in sub_float_significands_general // - cancel == 0 in sub_float_significands_general test( "0.5", "0x0.8#1", "1.5", "0x1.8#2", Nearest, "-1.0", "-0x1.0#2", Equal, ); // - !dif.is_power_of_2() in exponent_shift_compare test( "0.5", "0x0.8#1", "2.0", "0x2.0#2", Nearest, "-1.5", "-0x1.8#2", Equal, ); // - cmp_low != 0 first time in sub_float_significands_general // - cmp_low > 0 in sub_float_significands_general // - cmp_low > 0 && rm == Nearest in sub_float_significands_general // - cmp_low > 0 && rm == Nearest && xx == yy in sub_float_significands_general // - rm == Nearest && cmp_low != 0 in sub_float_significands_general // - (out[0] >> sh) & 1 == 0 in sub_float_significands_general test( "0.5", "0x0.8#1", "3.0", "0x3.0#2", Nearest, "-2.0", "-0x2.0#2", Greater, ); // - (out[0] >> sh) & 1 != 0 in sub_float_significands_general // - cmp_low >= 0 in sub_float_significands_general // - cmp_low >= 0 && !carry in sub_float_significands_general test( "4.0", "0x4.0#1", "1.2", "0x1.4#3", Nearest, "3.0", "0x3.0#3", Greater, ); // - cmp_low >= 0 && carry in sub_float_significands_general test( "4.0", "0x4.0#1", "0.5", "0x0.8#2", Nearest, "4.0", "0x4.0#2", Greater, ); // - rm == Nearest && carry > Limb::power_of_2(sh - 1) in sub_float_significands_general // - goto_truncate in sub_float_significands_general test( "3.0", "0x3.0#2", "0.2", "0x0.4#1", Nearest, "3.0", "0x3.0#2", Greater, ); // - rm == Nearest && carry <= Limb::power_of_2(sh - 1) && 0 < carry && carry < // Limb::power_of_2(sh - 1) in sub_float_significands_general test( "4.0", "0x4.0#1", "0.8", "0x0.c#2", Nearest, "3.0", "0x3.0#2", Less, ); // - max(out_prec, x_prec) + 2 <= exp_diff in sub_float_significands_general // - in round_helper // - dest_prec >= x_prec in round_helper // - !increment_exp in sub_float_significands_general // - inexact == 0 && rm != Down && rm != Floor in sub_float_significands_general test( "0.2", "0x0.4#1", "4.0", "0x4.0#2", Nearest, "-4.0", "-0x4.0#2", Less, ); // - diff_exp >= Limb::WIDTH in exponent_shift_compare first time test( "8.82188e11", "0xc.d668E+9#18", "9.75459983374e122", "0x1.79c17f063aE+102#40", Nearest, "-9.75459983374e122", "-0x1.79c17f063aE+102#40", Less, ); // - cancel2 < 0 in sub_float_significands_general // - out_len - neg_cancel2 <= ys_len in sub_float_significands_general test( "3.29008365861415556134836580980448399733562188e-9", "0xe.217c389f8c9fd22042f5ed70da20cfb9f1ecE-8#146", "3719044561792922503530448846362960.3599330496921301151502834994", "0xb75cf116bc625ef1eab58f3c9950.5c2492852d5fb6817443c180#205", Nearest, "-3719044561792922503530448846362960.359933046402046456536127938", "-0xb75cf116bc625ef1eab58f3c9950.5c2492770be37de1e7a3ef60#205", Less, ); // - out_len + cancel1 > xs_len in sub_float_significands_general // - cancel1 < xs_len in sub_float_significands_general test( "1.07183972513958531257713938927815e-11", "0xb.c8f5eafa12eb9821601f1dd6aeE-10#107", "0.00374222828352849", "0x0.00f5402c178824#46", Nearest, "-0.00374222827281009532032311766811006", "-0x0.00f5402c0bbf2e1505ed1467de9fe#107", Greater, ); // - out_len + cancel2 > ys_len in sub_float_significands_general test( "2589062031404.0", "0x25ad01f682c.0#43", "4351572166934988.581719655389852344796925751245753159273257621838622031922945531041952618\ 810238932316", "0xf75bb593981cc.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", Nearest, "-4348983104903584.58171965538985234479692575124575315927325762183862203192294553104195261\ 8810238932316", "-0xf7360891a19a0.94eb944f56fd85d744c7e812bf078ed9a4f5d3086fdab71e98a907840097016cb76fdc\ #330", Equal, ); // - yi >= 0 && lasty != 0 in exponent_shift_compare // - xi < 0 fourth time in exponent_shift_compare // - lasty == 0 in exponent_shift_compare // - yi < 0 || ys[yi] != 0 in exponent_shift_compare // - yi >= 0 fourth time in exponent_shift_compare test( "0.002", "0x0.008#2", "1.107886492190627864290739752375593855464628579e-38", "0x3.c51af197224960473945f6944424f855697e2E-32#149", Nearest, "0.001953124999999999999999999999999999988921135078", "0x0.007ffffffffffffffffffffffffffffc3ae50e68#149", Less, ); // - cmp_low > 0 && rm == Nearest && xx < yy in sub_float_significands_general // - goto_truncate || goto_end_of_sub first time in sub_float_significands_general // - goto_truncate || goto_end_of_sub second time in sub_float_significands_general test( "1.521287e-9", "0x6.88ac4E-8#21", "6.842391932190563625e-20", "0x1.431f7157e61b20d0E-16#62", Nearest, "1.5212870962270854807e-9", "0x6.88ac3ffebce08eaE-8#62", Less, ); // - out_len - neg_cancel2 > ys_len in sub_float_significands_general test( "0.00678514868524062", "0x0.01bcabe7b39c71#49", "492541199943575879969.43922949854802247248767794847124160758", "0x1ab361dbc0e97d4121.7071582bb3c5bd22b8f59cfc93c72a98#194", Nearest, "-492541199943575879969.43244434986278185350564935536210679008", "-0x1ab361dbc0e97d4121.6eb4ac4400294c22b8f59cfc93c72a98#194", Equal, ); // - rm == Nearest && sh == 0 && k == 0 in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 && yy < half in sub_float_significands_general // - rm == Nearest && cmp_low >= 0 && cmp_low <= 0 in sub_float_significands_general test( "5.7505515877842013577e-7", "0x9.a5d7d56cabed47dE-6#64", "1.1758894e-14", "0x3.4f515E-12#22", Nearest, "5.7505514701952590309e-7", "0x9.a5d7d21d5a9d47dE-6#64", Equal, ); // - rm == Nearest && cmp_low < 0 in sub_float_significands_general // - rm == Nearest && cmp_low < 0 && yy < half in sub_float_significands_general // - cmp_low < 0 in sub_float_significands_general first time // - cmp_low < 0 && rm == Nearest in sub_float_significands_general // - rm == Nearest && (xx > yy || sh > 0 || cmp_low == -1) in sub_float_significands_general test( "8319983682.218895978935307677994592087137128849954503237724", "0x1efe8e042.3809911ec0c7f99b114d2930720001b00aa46846#192", "1.88392800575e35", "0x2.4487b7174E+29#37", Nearest, "-188392800574747474298435817696599997.78110402106469232200542", "-0x24487b7173fffffffffffe10171fbd.c7f66ee13f380664eec#192", Less, ); // - rm == Nearest && cmp_low < 0 && yy >= half in sub_float_significands_general // - rm == Nearest && xx < yy && sh <= 0 && cmp_low != -1 in sub_float_significands_general // - goto_end_of_sub in sub_float_significands_general test( "2.36288970224581301467472547462526069521e-27", "0xb.b3518c72d51185c09977eb6e009c2c0E-23#128", "3.413020751e-12", "0x3.c0ae105E-10#30", Nearest, "-3.413020751029435178256669624768773569e-12", "-0x3.c0ae104fffff44cae738d2aee7a3f668E-10#128", Greater, ); // - xi >= 0 fourth time in exponent_shift_compare // - diff_exp >= Limb::WIDTH in exponent_shift_compare second time // - xs[xi] == yy in exponent_shift_compare test( "1125899906842624.0", "0x4000000000000.000000000000#98", "1.166815364554e-61", "0x2.ffffffff80E-51#39", Nearest, "1125899906842624.0", "0x4000000000000.000000000000#98", Greater, ); // - 0 < diff_exp < Limb::WIDTH && yi >= 0 in exponent_shift_compare // - xs[xi] != yy in exponent_shift_compare test( "9671406556917033397649408.0", "0x800000000000000000000.0000#99", "65536.015624999999999999946", "0x10000.03ffffffffffffff00#87", Nearest, "9671406556917033397583871.98438", "0x7fffffffffffffffeffff.fc00#99", Less, ); // - diff_exp == 0 && yi >= 0 in exponent_shift_compare test( "1.3877787807814456370485565165946e-17", "0xf.ffffffffffffe007ffffffff8E-15#101", "128.0000000000000000000000000008077935669463159990585083341", "0x80.00000000000000000000003ffffffffffffe0000000000#190", Nearest, "-127.9999999999999999861222121929933371964607508331127668586", "-0x7f.ffffffffffffff00000000400001ff7ffffe0008000000#190", Equal, ); // - rm == Nearest && xx == yy && sh <= 0 && cmp_low != -1 in sub_float_significands_general // - cmp_low < 0 in sub_float_significands_general second time test( "2.220581574517834801066783605693002897371795957735742517101e-16", "0x1.0003fffffe00000000007ffffffffffffffffffffff000feE-13#192", "8.881784e-16", "0x4.00000E-13#21", Nearest, "-6.661202622483417522322269739033559602628204042264257482898e-16", "-0x2.fffc000001ffffffffff80000000000000000000000fff00E-13#192", Greater, ); // - diff_exp < Limb::WIDTH && yi < 0 in exponent_shift_compare test( "-1.8e-12", "-0x1.fcE-10#7", "-524288.0000000000017621525", "-0x80000.0000000001f00078#81", Nearest, "524287.9999999999999573739", "0x7ffff.fffffffffff40078#81", Equal, ); // - (yi >= 0 || lasty != 0) && high_dif == 0 && dif == 1 in exponent_shift_compare // - xi >= 0 third time in exponent_shift_compare // - yi >= 0 && diff_exp != 0 in exponent_shift_compare // - high_dif != 0 in exponent_shift_compare // - dif == 0 in exponent_shift_compare test( "3.99999999999999999957", "0x3.fffffffffffffff80#67", "4.0", "0x4.00000000000000000#68", Nearest, "-4.33680868994201773603e-19", "-0x8.0000000000000000E-16#68", Equal, ); // - xi < 0 third time in exponent_shift_compare // - cancel1 >= xs_len in sub_float_significands_general test( "6.77626357803440271254657930615627554e-21", "0x1.ffffffffffffffffffffc01fff800E-17#117", "7.0e-21", "0x2.0E-17#4", Nearest, "-6.99280860154738521672154778865541105e-46", "-0x3.fe000800000000000000000000000E-38#117", Equal, ); // - yi >= 0 && diff_exp == 0 in exponent_shift_compare // - dif != 0 in exponent_shift_compare test( "1.45519152351431153846750277125465800054371356958e-11", "0x1.00000001ffffffffffffffffffffffffffffffcE-9#155", "1.455191523514311538467502771254658000526607875496523229114700566610230516799191954282190\ 364e-11", "0x1.00000001fffffffffffffffffffffffc0000000000000000000000000000fffffffffff87f8E-9#301", Nearest, "1.710569408086637569000134230861426729009957349416545362986887684243433631257558931055548\ 3967e-49", "0x3.ffffffbfffffffffffffffffffff00000000000780800000000000000000000000000000000E-41#301", Equal, ); // - xs[xi] == 0 in exponent_shift_compare // - xi < 0 second time in exponent_shift_compare test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Nearest, "0.0", "0x0.0", Equal, ); // - xi >= 0 second time in exponent_shift_compare test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Nearest, "0.0", "0x0.0", Equal, ); // - rm != Nearest in sub_float_significands_general // - rm != Nearest && carry == 0 in sub_float_significands_general test( "2.0", "0x2.0#1", "1.0", "0x1.0#2", Down, "1.0", "0x1.0#2", Equal, ); // - rm != Nearest && carry != 0 in sub_float_significands_general // - rm == Floor || rm == Down in sub_float_significands_general test( "0.5", "0x0.8#1", "3.0", "0x3.0#2", Down, "-2.0", "-0x2.0#2", Greater, ); // - rm == Ceiling || rm == Up in sub_float_significands_general // - (rm == Ceiling || rm == Up) && !carry in sub_float_significands_general test( "0.5", "0x0.8#1", "3.0", "0x3.0#2", Up, "-3.0", "-0x3.0#2", Less, ); // - (rm == Ceiling || rm == Up) && carry in sub_float_significands_general test( "4.0", "0x4.0#1", "0.5", "0x0.8#2", Up, "4.0", "0x4.0#2", Greater, ); // - cmp_low < 0 && (rm == Floor || rm == Down) in sub_float_significands_general test( "0.1952943266615587806218370459", "0x0.31fecf1a1b1180be748fe5b8#91", "5.04217616231508488430478600129900999076e-13", "0x8.decb552f6cf9a70a64d0c0d7a367802E-11#127", Down, "0.195294326661054563005605537435615043117", "0x0.31fecf1a1a8394092199161d8f59b2f38#127", Less, ); // - cmp_low < 0 && (rm == Ceiling || rm == Up) in sub_float_significands_general test( "1.1718977744e31", "0x9.3ea0f304E+25#34", "1910333504687680.9305", "0x6c9702df30e40.ee38#64", Ceiling, "1.171897774363652748e31", "0x9.3ea0f303ffff937E+25#64", Greater, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#2", Exact, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Floor, "-0.0", "-0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Ceiling, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Down, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Up, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Nearest, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000E-7#69", Exact, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Floor, "-0.0", "-0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Ceiling, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Down, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Up, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Nearest, "0.0", "0x0.0", Equal, ); test( "7.0e-9", "0x2.0E-7#2", "7.450580596923828125e-9", "0x2.00000000000000000000000000000000000000000000000000E-7#200", Exact, "0.0", "0x0.0", Equal, ); test( "-too_small", "-0x2.50888E-268435456#19", "-too_small", "-0x3.10E-268435456#10", Down, "0.0", "0x0.0", Less, ); test( "too_big", "0x4.0E+268435455#1", "-too_big", "-0x4.0E+268435455#1", Down, "too_big", "0x4.0E+268435455#1", Less, ); test( "-too_big", "-0x4.0E+268435455#1", "too_big", "0x4.0E+268435455#1", Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); } #[test] fn sub_round_fail() { assert_panic!(Float::one_prec(1).sub_round(Float::from_unsigned_prec(4u8, 1).0, Exact)); assert_panic!({ Float::one_prec(1).sub_round_val_ref(&Float::from_unsigned_prec(4u8, 1).0, Exact) }); assert_panic!(Float::one_prec(1).sub_round_ref_val(Float::from_unsigned_prec(4u8, 1).0, Exact)); assert_panic!({ Float::one_prec(1).sub_round_ref_ref(&Float::from_unsigned_prec(4u8, 1).0, Exact) }); assert_panic!(parse_hex_string("0x1.0#1").sub_round(parse_hex_string("0x0.001#1"), Exact)); assert_panic!( parse_hex_string("0x1.0#1").sub_round_val_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").sub_round_ref_val(parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0#1").sub_round_ref_ref(&parse_hex_string("0x0.001#1"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .sub_round(parse_hex_string("0x2.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .sub_round_val_ref(&parse_hex_string("0x2.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .sub_round_ref_val(parse_hex_string("0x2.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#64") .sub_round_ref_ref(&parse_hex_string("0x2.0000000000000002#64"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .sub_round(parse_hex_string("0x2.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .sub_round_val_ref(&parse_hex_string("0x2.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .sub_round_ref_val(parse_hex_string("0x2.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.0000000000000000#65") .sub_round_ref_ref(&parse_hex_string("0x2.0000000000000001#65"), Exact) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").sub_round( parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").sub_round_val_ref( &parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").sub_round_ref_val( parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#128").sub_round_ref_ref( &parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").sub_round( parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").sub_round_val_ref( &parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").sub_round_ref_val( parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.00000000000000000000000000000000#129").sub_round_ref_ref( &parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192").sub_round( parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .sub_round_val_ref( &parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .sub_round_ref_val( parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!( parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192") .sub_round_ref_ref( &parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact ) ); assert_panic!(parse_hex_string("0x0.8#1").sub_round(parse_hex_string("0x3.0#2"), Exact)); assert_panic!( parse_hex_string("0x0.8#1").sub_round_val_ref(&parse_hex_string("0x3.0#2"), Exact) ); assert_panic!({ parse_hex_string("0x0.8#1").sub_round_ref_val(parse_hex_string("0x3.0#2"), Exact) }); assert_panic!( parse_hex_string("0x0.8#1").sub_round_ref_ref(&parse_hex_string("0x3.0#2"), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.sub_round_assign(Float::from_unsigned_prec(4u8, 1).0, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.sub_round_assign_ref(&Float::from_unsigned_prec(4u8, 1).0, Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.sub_round_assign(parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0#1"); x.sub_round_assign_ref(&parse_hex_string("0x0.001#1"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.sub_round_assign(parse_hex_string("0x2.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#64"); x.sub_round_assign_ref(&parse_hex_string("0x2.0000000000000002#64"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.sub_round_assign(parse_hex_string("0x2.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.0000000000000000#65"); x.sub_round_assign_ref(&parse_hex_string("0x2.0000000000000001#65"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.sub_round_assign( parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#128"); x.sub_round_assign_ref( &parse_hex_string("0x2.00000000000000000000000000000002#128"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.sub_round_assign( parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.00000000000000000000000000000000#129"); x.sub_round_assign_ref( &parse_hex_string("0x2.00000000000000000000000000000003#129"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.sub_round_assign( parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x1.000000000000000000000000000000000000000000000000#192"); x.sub_round_assign_ref( &parse_hex_string("0x2.000000000000000000000000000000000000000000000002#192"), Exact, ) }); assert_panic!({ let mut x = parse_hex_string("0x0.8#1"); x.sub_round_assign(parse_hex_string("0x3.0#2"), Exact) }); assert_panic!({ let mut x = parse_hex_string("0x0.8#1"); x.sub_round_assign_ref(&parse_hex_string("0x3.0#2"), Exact) }); } #[test] fn test_sub_prec_round() { let test = |s, s_hex, t, t_hex, prec: u64, rm, out: &str, out_hex: &str, o_out: Ordering| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let (diff, o) = x.clone().sub_prec_round(y.clone(), prec, rm); assert!(diff.is_valid()); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); assert_eq!(o, o_out); let (diff_alt, o_alt) = x.clone().sub_prec_round_val_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_prec_round_ref_val(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = x.sub_prec_round_ref_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_prec_round_assign(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_prec_round_assign_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o_out); let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-0.0", "-0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-0.0", "-0x0.0", 1, Exact, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Floor, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Ceiling, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "0.0", "0x0.0", 1, Up, "NaN", "NaN", Equal); test( "NaN", "NaN", "0.0", "0x0.0", 1, Nearest, "NaN", "NaN", Equal, ); test("NaN", "NaN", "0.0", "0x0.0", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "Infinity", "Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-0.0", "-0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "0.0", "0x0.0", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Floor, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Ceiling, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Down, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Up, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Nearest, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "-Infinity", "-Infinity", 1, Exact, "NaN", "NaN", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "Infinity", "Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-0.0", "-0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "0.0", "0x0.0", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("0.0", "0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test("0.0", "0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "Infinity", "Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Floor, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); // Note different behavior for Floor test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test("0.0", "0x0.0", "0.0", "0x0.0", 1, Up, "0.0", "0x0.0", Equal); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "0.0", "0x0.0", "0.0", "0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal); test("-0.0", "-0x0.0", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-0.0", "-0x0.0", "Infinity", "Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); // Note different behavior for Floor test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Ceiling, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Down, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Up, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Nearest, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "-0.0", "-0x0.0", 1, Exact, "0.0", "0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Floor, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Ceiling, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Down, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Up, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Nearest, "-0.0", "-0x0.0", Equal, ); test( "-0.0", "-0x0.0", "0.0", "0x0.0", 1, Exact, "-0.0", "-0x0.0", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Floor, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Ceiling, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Down, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Up, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Nearest, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "NaN", "NaN", 1, Exact, "NaN", "NaN", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Floor, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Down, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Up, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-Infinity", "-Infinity", 1, Exact, "Infinity", "Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "Infinity", "Infinity", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "-0.0", "-0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0.0", "0x0.0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Floor, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Ceiling, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Down, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Up, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Nearest, "NaN", "NaN", Equal, ); test( "NaN", "NaN", "-123.0", "-0x7b.0#7", 1, Exact, "NaN", "NaN", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123.0", "-0x7b.0#7", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123.0", "-0x7b.0#7", 1, Exact, "-Infinity", "-Infinity", Equal, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "-123.0", "-0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123.0", "-0x7b.0#7", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#1", "-2.0", "-0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#1", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.0#2", "-2.0", "-0x2.0#2", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, Floor, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, Down, "2.0", "0x2.0#1", Less, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, Up, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Floor, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Ceiling, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Down, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Up, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Nearest, "3.0", "0x3.00#10", Equal, ); test( "1.0", "0x1.000#10", "-2.0", "-0x2.00#10", 10, Exact, "3.0", "0x3.00#10", Equal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "4.56", "0x4.90#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "4.555", "0x4.8e#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "-1.727", "-0x1.ba0#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "-1.729", "-0x1.ba8#10", Less, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "-1.727", "-0x1.ba0#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "1.729", "0x1.ba8#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "1.727", "0x1.ba0#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "-4.555", "-0x4.8e#10", Greater, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "-4.56", "-0x4.90#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "-4.555", "-0x4.8e#10", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, Floor, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, Ceiling, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, Down, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, Up, "2.0", "0x2.0#1", Greater, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 1, Nearest, "1.0", "0x1.0#1", Less, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Floor, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Ceiling, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Down, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Up, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Nearest, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "-0.0002", "-0x0.001#1", 20, Exact, "1.000244", "0x1.00100#20", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Floor, "-0.0", "-0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Ceiling, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Down, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Up, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Nearest, "0.0", "0x0.0", Equal, ); test( "1.0", "0x1.0#1", "1.0", "0x1.0#1", 10, Exact, "0.0", "0x0.0", Equal, ); // - rm != Nearest in round_helper // - (rm == Up || rm == Ceiling) && sb | rb != 0 in round_helper // - !increment third time in round_helper test( "13104.5238818416080254535", "0x3330.861d1ed0acba8a3a#77", "2.854e-35", "0x2.5fE-29#10", 17, Ceiling, "13104.6", "0x3330.a#17", Greater, ); // - sh != 0 && (rm != Nearest && rb != 0) in round_helper // - rm == Down || rm == Floor in round_helper test( "2.8979948183270175762296398212780973e-12", "0x3.2fb688bd98f0271a53708f0554568E-10#115", "8.270488650862e23", "0xa.f2268a8074E+19#42", 2, Down, "-6.0e23", "-0x8.0E+19#2", Greater, ); // - (rm == Up || rm == Ceiling) && sb | rb == 0 in round_helper test( "1.503764257662314e22", "0x3.2f31367a9800E+18#48", "7.3839e-20", "0x1.5cb2E-16#17", 39, Ceiling, "1.503764257662e22", "0x3.2f31367a98E+18#39", Greater, ); // - increment third time in round_helper test( "4.70916604581e-30", "0x5.f8363584bE-25#39", "341290809831481093.63402342431195212374059", "0x4bc822eed1c5f05.a24f5bf051591756f951#139", 1, Floor, "-6.0e17", "-0x8.0E+14#1", Less, ); // - cmp_low > 0 && (rm == Floor || rm == Down) in sub_float_significands_general test( "559935046210054011882951826578284118061013900.5853448", "0x191bbd3588c78488c2f4d122814d5fb34edb8c.95d928#170", "3.027932e11", "0x4.67fe2E+9#22", 63, Down, "5.599350462100540119e44", "0x1.91bbd3588c78488cE+37#63", Less, ); // - cmp_low > 0 && (rm == Ceiling || rm == Up) in sub_float_significands_general // - cmp_low > 0 && (rm == Ceiling || rm == Up) && !carry in sub_float_significands_general test( "1.3111820218254081035114504135472568116036464005e-6", "0x0.000015ff7be10e865ada82cd25acef5baa9c89c25f4#152", "2.51465891601e-20", "0x7.6c05c64a8E-17#38", 128, Ceiling, "1.311182021825382956922290308381837960614e-6", "0x0.000015ff7be10e85e41a26687dacef5baa9ca#128", Greater, ); // - cmp_low > 0 && (rm == Ceiling || rm == Up) && carry in sub_float_significands_general test( "1.19e-7", "0x2.0E-6#6", "2722258925226302905881161717745111269376.0000001187", "0x7ffffff800000000000003fe7c0000000.000001fe0#164", 28, Up, "-2.72225894e39", "-0x8.000000E+32#28", Less, ); test( "-1.948077668464e-10", "-0xd.63182fa960E-9#41", "-too_big", "-0x7.c300ddfc112a6cf2a0bb36cf8E+268435455#100", 3, Up, "Infinity", "Infinity", Greater, ); test( "1.948077668464e-10", "0xd.63182fa960E-9#41", "too_big", "0x7.c300ddfc112a6cf2a0bb36cf8E+268435455#100", 3, Up, "-Infinity", "-Infinity", Less, ); test( "too_small", "0x1.08E-268435456#6", "too_small", "0x1.0E-268435456#1", 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x1.08E-268435456#6", "-too_small", "-0x1.0E-268435456#1", 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn sub_prec_round_fail() { assert_panic!(Float::one_prec(1).sub_prec_round(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).sub_prec_round_val_ref(&Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).sub_prec_round_ref_val(Float::two_prec(1), 0, Floor)); assert_panic!(Float::one_prec(1).sub_prec_round_ref_ref(&Float::two_prec(1), 0, Floor)); assert_panic!({ let mut x = Float::one_prec(1); x.sub_prec_round_assign(Float::two_prec(1), 0, Floor) }); assert_panic!({ let mut x = Float::one_prec(1); x.sub_prec_round_assign_ref(&Float::two_prec(1), 0, Floor) }); assert_panic!(Float::one_prec(1).sub_prec_round(-Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).sub_prec_round_val_ref(&-Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).sub_prec_round_ref_val(-Float::two_prec(1), 1, Exact)); assert_panic!(Float::one_prec(1).sub_prec_round_ref_ref(&-Float::two_prec(1), 1, Exact)); assert_panic!({ let mut x = Float::one_prec(1); x.sub_prec_round_assign(-Float::two_prec(1), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.sub_prec_round_assign_ref(&-Float::two_prec(1), 1, Exact) }); } #[test] fn test_sub_rational() { let test = |s, s_hex, t, out: &str, out_hex: &str| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let diff = x.clone() - y.clone(); assert!(diff.is_valid()); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); let diff_alt = x.clone() - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let diff_alt = &x - y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let diff_alt = &x - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let diff_alt = y.clone() - x.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloat(-&diff), ComparableFloat(diff_alt)); let diff_alt = y.clone() - &x; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloat(-&diff), ComparableFloat(diff_alt)); let diff_alt = &y - x.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloat(-&diff), ComparableFloat(diff_alt)); let diff_alt = &y - &x; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloat(-&diff), ComparableFloat(diff_alt)); let mut diff_alt = x.clone(); diff_alt -= y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); let mut diff_alt = x.clone(); diff_alt -= &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!( ComparableFloatRef(&Float::from(&rug_sub_rational( &rug::Float::exact_from(&x), &rug::Rational::from(&y) ))), ComparableFloatRef(&diff) ); let diff_alt = sub_rational_prec_round_naive(x.clone(), y, x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); }; test("NaN", "NaN", "-123", "NaN", "NaN"); test("Infinity", "Infinity", "-123", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "-123", "-Infinity", "-Infinity"); test("0.0", "0x0.0", "0", "0.0", "0x0.0"); test("-0.0", "-0x0.0", "0", "-0.0", "-0x0.0"); test("0.0", "0x0.0", "-123", "1.0e2", "0x8.0E+1#1"); test("-0.0", "-0x0.0", "-123", "1.0e2", "0x8.0E+1#1"); test("0.0", "0x0.0", "-1/3", "0.2", "0x0.4#1"); test("-0.0", "-0x0.0", "-1/3", "0.2", "0x0.4#1"); test("123.0", "0x7b.0#7", "0", "123.0", "0x7b.0#7"); // - different signs in float_rational_diff_exponent_range test("1.0", "0x1.0#1", "-2", "4.0", "0x4.0#1"); test("1.0", "0x1.0#2", "-2", "3.0", "0x3.0#2"); test("1.0", "0x1.000#10", "-2", "3.0", "0x3.00#10"); test("1.0", "0x1.000#10", "-1/3", "1.334", "0x1.558#10"); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", "3.4749259869231266", "0x3.7994bfdddaf86#53", ); // - same sign and log_x_abs.abs_diff(log_y_abs) > 1 in float_rational_diff_exponent_range test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", "2.8082593202564596", "0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", "-2.8082593202564596", "-0x2.ceea1533304da#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", "-3.4749259869231266", "-0x3.7994bfdddaf86#53", ); test("1.0", "0x1.0#1", "-1/50000", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "1", "0.0", "0x0.0"); // - same sign and log_x_abs.abs_diff(log_y_abs) <= 1 in float_rational_diff_exponent_range // - same sign and log_x_abs.abs_diff(log_y_abs) == 1 in float_rational_diff_exponent_range test("2.0", "0x2.0#1", "1", "1.0", "0x1.0#1"); // - same sign and log_x_abs == log_y_abs in float_rational_diff_exponent_range test("1.0", "0x1.0#1", "3/2", "-0.5", "-0x0.8#1"); test("2.0", "0x2.0#1", "1", "1.0", "0x1.0#1"); test("1.0", "0x1.0#1", "3/2", "-0.5", "-0x0.8#1"); } #[test] fn test_sub_rational_prec() { let test = |s, s_hex, t, prec, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (diff, o) = x.clone().sub_rational_prec(y.clone(), prec); assert!(diff.is_valid()); assert_eq!(o, o_out); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); let (diff_alt, o_alt) = x.clone().sub_rational_prec_val_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_ref_val(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_ref_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_prec_assign(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_prec_assign_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (rug_diff, rug_o) = rug_sub_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); }; test("NaN", "NaN", "-123", 1, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "-123", 1, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("-0.0", "-0x0.0", "-123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("0.0", "0x0.0", "-1/3", 1, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", 1, "0.2", "0x0.4#1", Less); test("123.0", "0x7b.0#7", "0", 1, "1.0e2", "0x8.0E+1#1", Greater); test("1.0", "0x1.0#1", "-2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "-2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "-2", 2, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "-2", 1, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.000#10", "-2", 2, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "-1/3", 100, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, "-3.477", "-0x3.7a#10", Less, ); test("1.0", "0x1.0#1", "-1/50000", 10, "1.0", "0x1.000#10", Less); test("1.0", "0x1.0#1", "1", 10, "0.0", "0x0.0", Equal); } #[test] fn sub_rational_prec_fail() { assert_panic!(Float::NAN.sub_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::NAN.sub_rational_prec_val_ref(&Rational::ZERO, 0)); assert_panic!(Float::NAN.sub_rational_prec_ref_val(Rational::ZERO, 0)); assert_panic!(Float::NAN.sub_rational_prec_ref_ref(&Rational::ZERO, 0)); assert_panic!({ let mut x = Float::NAN; x.sub_rational_prec_assign(Rational::ZERO, 0) }); assert_panic!({ let mut x = Float::NAN; x.sub_rational_prec_assign_ref(&Rational::ZERO, 0) }); } #[test] fn test_sub_rational_round() { let test_helper = |s, s_hex, y: Rational, rm, out: &str, out_hex: &str, o_out, extreme: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (diff, o) = x.clone().sub_rational_round(y.clone(), rm); assert!(diff.is_valid()); assert_eq!(o, o_out); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); if !extreme { let (diff_alt, o_alt) = x.clone().sub_rational_round_val_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_round_ref_val(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_round_ref_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_round_assign(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_round_assign_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); } let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y, x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); }; let test = |s, s_hex, t, rm, out: &str, out_hex: &str, o_out| { test_helper( s, s_hex, Rational::from_str(t).unwrap(), rm, out, out_hex, o_out, false, ); }; test("NaN", "NaN", "-123", Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "-123", Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", Exact, "-0.0", "-0x0.0", Equal); test("0.0", "0x0.0", "-123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "-123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "-123", Down, "6.0e1", "0x4.0E+1#1", Less); test("0.0", "0x0.0", "-123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "0.0", "0x0.0", "-123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "-123", Floor, "6.0e1", "0x4.0E+1#1", Less); test( "-0.0", "-0x0.0", "-123", Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("-0.0", "-0x0.0", "-123", Down, "6.0e1", "0x4.0E+1#1", Less); test("-0.0", "-0x0.0", "-123", Up, "1.0e2", "0x8.0E+1#1", Greater); test( "-0.0", "-0x0.0", "-123", Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("123.0", "0x7b.0#7", "0", Floor, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Ceiling, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Down, "123.0", "0x7b.0#7", Equal); test("123.0", "0x7b.0#7", "0", Up, "123.0", "0x7b.0#7", Equal); test( "123.0", "0x7b.0#7", "0", Nearest, "123.0", "0x7b.0#7", Equal, ); test("123.0", "0x7b.0#7", "0", Exact, "123.0", "0x7b.0#7", Equal); test("0.0", "0x0.0", "-1/3", Floor, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "-1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "-1/3", Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "-1/3", Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "-1/3", Nearest, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", Ceiling, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "-1/3", Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "-1/3", Nearest, "0.2", "0x0.4#1", Less); test("1.0", "0x1.0#1", "-2", Floor, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "-2", Ceiling, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "-2", Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "-2", Up, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#1", "-2", Nearest, "4.0", "0x4.0#1", Greater); test("1.0", "0x1.0#2", "-2", Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#2", "-2", Exact, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.000#10", "-2", Floor, "3.0", "0x3.00#10", Equal); test( "1.0", "0x1.000#10", "-2", Ceiling, "3.0", "0x3.00#10", Equal, ); test("1.0", "0x1.000#10", "-2", Down, "3.0", "0x3.00#10", Equal); test("1.0", "0x1.000#10", "-2", Up, "3.0", "0x3.00#10", Equal); test( "1.0", "0x1.000#10", "-2", Nearest, "3.0", "0x3.00#10", Equal, ); test("1.0", "0x1.000#10", "-2", Exact, "3.0", "0x3.00#10", Equal); test( "1.0", "0x1.000#10", "-1/3", Floor, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "-1/3", Ceiling, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "-1/3", Down, "1.332", "0x1.550#10", Less, ); test( "1.0", "0x1.000#10", "-1/3", Up, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.000#10", "-1/3", Nearest, "1.334", "0x1.558#10", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.0000000000000000000000000#100", "-1/3", Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Floor, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Ceiling, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Down, "3.4749259869231262", "0x3.7994bfdddaf84#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Up, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Nearest, "3.4749259869231266", "0x3.7994bfdddaf86#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Floor, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Ceiling, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Down, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Up, "2.8082593202564601", "0x2.ceea1533304dc#53", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Nearest, "2.8082593202564596", "0x2.ceea1533304da#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Floor, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Ceiling, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Down, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Up, "-2.8082593202564601", "-0x2.ceea1533304dc#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Nearest, "-2.8082593202564596", "-0x2.ceea1533304da#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Floor, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Ceiling, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Down, "-3.4749259869231262", "-0x3.7994bfdddaf84#53", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Up, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Nearest, "-3.4749259869231266", "-0x3.7994bfdddaf86#53", Less, ); test("1.0", "0x1.0#1", "-1/50000", Floor, "1.0", "0x1.0#1", Less); test( "1.0", "0x1.0#1", "-1/50000", Ceiling, "2.0", "0x2.0#1", Greater, ); test("1.0", "0x1.0#1", "-1/50000", Down, "1.0", "0x1.0#1", Less); test("1.0", "0x1.0#1", "-1/50000", Up, "2.0", "0x2.0#1", Greater); test( "1.0", "0x1.0#1", "-1/50000", Nearest, "1.0", "0x1.0#1", Less, ); test("1.0", "0x1.0#1", "1", Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "1", Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", Exact, "0.0", "0x0.0", Equal); // - max_exponent > i64::from(Float::MAX_EXPONENT) - 2 in add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Nearest, "Infinity", "Infinity", Greater, true, ); test_helper( "-too_big", "-0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Nearest, "-Infinity", "-Infinity", Less, true, ); // - min_exponent >= Float::MAX_EXPONENT in add_rational_prec_round // - both signs positive in float_rational_sum_sign // - float_rational_sum_sign(x, &y) && (rm == Ceiling || rm == Up || rm == Nearest) in // add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Nearest, "Infinity", "Infinity", Greater, true, ); // - float_rational_sum_sign(x, &y) && (rm == Floor || rm == Down) in add_rational_prec_round test_helper( "too_big", "0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Down, "too_big", "0x4.0E+268435455#1", Less, true, ); // - !float_rational_sum_sign(x, &y) && (rm == Ceiling || rm == Down) in add_rational_prec_round test_helper( "-too_big", "-0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Down, "-too_big", "-0x4.0E+268435455#1", Greater, true, ); // - signs different and x.lt_abs(y) in float_rational_sum_sign test_helper( "-too_big", "-0x4.0E+268435455#1", -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) + 1), Nearest, "Infinity", "Infinity", Greater, true, ); // - both signs negative in float_rational_sum_sign // - !float_rational_sum_sign(x, &y) && (rm == Floor || rm == Up || rm == Nearest) in // add_rational_prec_round test_helper( "-too_big", "-0x4.0E+268435455#1", Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Nearest, "-Infinity", "-Infinity", Less, true, ); test_helper( "-1.0", "-0x1.0#1", Rational::NEGATIVE_ONE - Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Nearest, "0.0", "0x0.0", Less, true, ); test_helper( "1.0", "0x1.0#1", Rational::ONE + Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Nearest, "-0.0", "-0x0.0", Greater, true, ); } #[test] fn sub_rational_round_fail() { assert_panic!(Float::one_prec(1).sub_rational_round(-Rational::from_unsigneds(1u32, 3), Exact)); assert_panic!( Float::one_prec(1).sub_rational_round_val_ref(&-Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).sub_rational_round_ref_val(-Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!( Float::one_prec(1).sub_rational_round_ref_ref(&-Rational::from_unsigneds(1u32, 3), Exact) ); assert_panic!({ let mut x = Float::one_prec(1); x.sub_rational_round_assign(-Rational::from_unsigneds(1u32, 3), Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.sub_rational_round_assign_ref(&-Rational::from_unsigneds(1u32, 3), Exact) }); } #[test] fn test_sub_rational_prec_round() { let test = |s, s_hex, t, prec, rm, out: &str, out_hex: &str, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = Rational::from_str(t).unwrap(); let (diff, o) = x.clone().sub_rational_prec_round(y.clone(), prec, rm); assert!(diff.is_valid()); assert_eq!(o, o_out); assert_eq!(diff.to_string(), out); assert_eq!(to_hex_string(&diff), out_hex); let (diff_alt, o_alt) = x.clone().sub_rational_prec_round_val_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_prec_round_assign(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let mut diff_alt = x.clone(); let o_alt = diff_alt.sub_rational_prec_round_assign_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); } }; test("NaN", "NaN", "-123", 1, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Ceiling, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Down, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Up, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Nearest, "NaN", "NaN", Equal); test("NaN", "NaN", "-123", 1, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", "-123", 1, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", 1, Ceiling, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", 1, Down, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", 1, Up, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", 1, Nearest, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", "-123", 1, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Down, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Up, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Nearest, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", "-123", 1, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", "0", 1, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Down, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Up, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Nearest, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", "0", 1, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Ceiling, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Down, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Up, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Nearest, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", "0", 1, Exact, "-0.0", "-0x0.0", Equal); test( "0.0", "0x0.0", "-123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "0.0", "0x0.0", "-123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "-123", 1, Down, "6.0e1", "0x4.0E+1#1", Less); test( "0.0", "0x0.0", "-123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "0.0", "0x0.0", "-123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "-123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "-0.0", "-0x0.0", "-123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "-0.0", "-0x0.0", "-123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("0.0", "0x0.0", "-1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "0.0", "0x0.0", "-1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test("0.0", "0x0.0", "-1/3", 1, Down, "0.2", "0x0.4#1", Less); test("0.0", "0x0.0", "-1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("0.0", "0x0.0", "-1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "-0.0", "-0x0.0", "-1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater, ); test("-0.0", "-0x0.0", "-1/3", 1, Down, "0.2", "0x0.4#1", Less); test("-0.0", "-0x0.0", "-1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("-0.0", "-0x0.0", "-1/3", 1, Floor, "0.2", "0x0.4#1", Less); test( "123.0", "0x7b.0#7", "0", 1, Floor, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Down, "6.0e1", "0x4.0E+1#1", Less, ); test( "123.0", "0x7b.0#7", "0", 1, Up, "1.0e2", "0x8.0E+1#1", Greater, ); test( "123.0", "0x7b.0#7", "0", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater, ); test("1.0", "0x1.0#1", "-2", 1, Floor, "2.0", "0x2.0#1", Less); test( "1.0", "0x1.0#1", "-2", 1, Ceiling, "4.0", "0x4.0#1", Greater, ); test("1.0", "0x1.0#1", "-2", 1, Down, "2.0", "0x2.0#1", Less); test("1.0", "0x1.0#1", "-2", 1, Up, "4.0", "0x4.0#1", Greater); test( "1.0", "0x1.0#1", "-2", 1, Nearest, "4.0", "0x4.0#1", Greater, ); test("1.0", "0x1.0#1", "-2", 2, Floor, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "-2", 2, Ceiling, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "-2", 2, Down, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "-2", 2, Up, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "-2", 2, Nearest, "3.0", "0x3.0#2", Equal); test("1.0", "0x1.0#1", "-2", 2, Exact, "3.0", "0x3.0#2", Equal); test( "1.0", "0x1.000#10", "-1/3", 100, Floor, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "-1/3", 100, Ceiling, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "-1/3", 100, Down, "1.333333333333333333333333333332", "0x1.5555555555555555555555554#100", Less, ); test( "1.0", "0x1.000#10", "-1/3", 100, Up, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "1.0", "0x1.000#10", "-1/3", 100, Nearest, "1.333333333333333333333333333334", "0x1.5555555555555555555555556#100", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Floor, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Down, "3.473", "0x3.79#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Up, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "3.477", "0x3.7a#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Floor, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Down, "2.805", "0x2.ce#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Up, "2.809", "0x2.cf#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", 10, Nearest, "2.809", "0x2.cf#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Floor, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Ceiling, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Down, "-2.805", "-0x2.ce#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Up, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", 10, Nearest, "-2.809", "-0x2.cf#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Floor, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Ceiling, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Down, "-3.473", "-0x3.79#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Up, "-3.477", "-0x3.7a#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", 10, Nearest, "-3.477", "-0x3.7a#10", Less, ); test( "1.0", "0x1.0#1", "-1/50000", 10, Floor, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "-1/50000", 10, Ceiling, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "-1/50000", 10, Down, "1.0", "0x1.000#10", Less, ); test( "1.0", "0x1.0#1", "-1/50000", 10, Up, "1.002", "0x1.008#10", Greater, ); test( "1.0", "0x1.0#1", "-1/50000", 10, Nearest, "1.0", "0x1.000#10", Less, ); test("1.0", "0x1.0#1", "1", 10, Floor, "-0.0", "-0x0.0", Equal); test("1.0", "0x1.0#1", "1", 10, Ceiling, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", 10, Down, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", 10, Up, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", 10, Nearest, "0.0", "0x0.0", Equal); test("1.0", "0x1.0#1", "1", 10, Exact, "0.0", "0x0.0", Equal); } #[test] fn sub_rational_prec_round_fail() { assert_panic!(Float::one_prec(1).sub_rational_prec_round( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).sub_rational_prec_round_val_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).sub_rational_prec_round_ref_val( Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!(Float::one_prec(1).sub_rational_prec_round_ref_ref( &Rational::from_unsigneds(5u32, 8), 1, Exact )); assert_panic!({ let mut x = Float::one_prec(1); x.sub_rational_prec_round_assign(Rational::from_unsigneds(5u32, 8), 1, Exact) }); assert_panic!({ let mut x = Float::one_prec(1); x.sub_rational_prec_round_assign_ref(&Rational::from_unsigneds(5u32, 8), 1, Exact) }); } #[allow(clippy::needless_pass_by_value)] fn sub_prec_round_properties_helper( x: Float, y: Float, prec: u64, rm: RoundingMode, extreme: bool, ) { let (diff, o) = x.clone().sub_prec_round(y.clone(), prec, rm); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_prec_round_val_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_prec_round_ref_val(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_prec_round_ref_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_prec_round( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); } if o == Equal && diff.is_finite() { assert_eq!( ComparableFloat( diff.add_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( x.sub_prec_round_ref_ref(&diff, y.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); } if !extreme { let r_diff = if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); } let r_diff = Rational::exact_from(&x) - Rational::exact_from(&y); assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } Some(r_diff) } else { assert_eq!(o, Equal); None }; match (r_diff.is_some() && *r_diff.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } let (mut diff_alt, mut o_alt) = y.sub_prec_round_ref_ref(&x, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.add_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-&x).add_prec_round_val_ref(&y, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-&x).sub_prec_round(-&y, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (d, oo) = x.sub_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(d.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sub_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn sub_prec_round_properties() { float_float_unsigned_rounding_mode_quadruple_gen_var_2().test_properties(|(x, y, prec, rm)| { sub_prec_round_properties_helper(x, y, prec, rm, false); }); float_float_unsigned_rounding_mode_quadruple_gen_var_6().test_properties(|(x, y, prec, rm)| { sub_prec_round_properties_helper(x, y, prec, rm, true); }); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (diff, o) = x.sub_prec_round_ref_val(Float::NAN, prec, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); let (diff, o) = Float::NAN.sub_prec_round_val_ref(&x, prec, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::INFINITY { assert_eq!( x.sub_prec_round_ref_val(Float::INFINITY, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::INFINITY.sub_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); } if x != Float::NEGATIVE_INFINITY { assert_eq!( x.sub_prec_round_ref_val(Float::NEGATIVE_INFINITY, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (diff, o) = x.sub_prec_round_ref_val(Float::ZERO, prec, rm); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec_round(prec, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::ZERO.sub_prec_round_val_ref(&x, prec, rm); let mut diff_alt = -&x; let o_alt = diff_alt.set_prec_round(prec, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); } if rm != Floor || !x.is_positive_zero() { let (diff, o) = x.sub_prec_round_ref_val(Float::NEGATIVE_ZERO, prec, rm); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec_round(prec, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::NEGATIVE_ZERO.sub_prec_round_val_ref(&x, prec, rm); let mut diff_alt = -&x; let o_alt = diff_alt.set_prec_round(prec, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); } }); } fn sub_prec_properties_helper(x: Float, y: Float, prec: u64, extreme: bool) { let (diff, o) = x.clone().sub_prec(y.clone(), prec); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_prec_val_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_prec_ref_val(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_prec_ref_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = add_prec_round_naive(x.clone(), -&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } let (rug_diff, rug_o) = rug_sub_prec( &rug::Float::exact_from(&x), &rug::Float::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); if o == Equal && diff.is_finite() { assert_eq!( ComparableFloat( diff.add_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat( x.sub_prec_ref_ref(&diff, y.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(y.abs_negative_zero_ref()) ); } let (diff_alt, o_alt) = x.sub_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); } if !extreme { let r_diff = Rational::exact_from(&x) - Rational::exact_from(&y); assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } } } let (mut diff_alt, mut o_alt) = y.sub_prec_ref_ref(&x, prec); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.add_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || (x.is_sign_positive() && y.is_sign_positive()) { let (mut diff_alt, mut o_alt) = (-&x).add_prec_val_ref(&y, prec); diff_alt.neg_assign(); diff_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-x).sub_prec(-y, prec); diff_alt.neg_assign(); diff_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff.abs_negative_zero()) ); assert_eq!(o_alt, o); } } #[test] fn sub_prec_properties() { float_float_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { sub_prec_properties_helper(x, y, prec, false); }); float_float_unsigned_triple_gen_var_2().test_properties(|(x, y, prec)| { sub_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { let (diff, o) = x.sub_prec_ref_val(Float::NAN, prec); assert!(diff.is_nan()); assert_eq!(o, Equal); let (diff, o) = Float::NAN.sub_prec_val_ref(&x, prec); assert!(diff.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::INFINITY { assert_eq!( x.sub_prec_ref_val(Float::INFINITY, prec), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::INFINITY.sub_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); } if x != Float::NEGATIVE_INFINITY { assert_eq!( x.sub_prec_ref_val(Float::NEGATIVE_INFINITY, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (diff, o) = x.sub_prec_ref_val(Float::ZERO, prec); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec(prec); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); let (diff, o) = Float::ZERO.sub_prec_val_ref(&x, prec); let mut diff_alt = -&x; let o_alt = diff_alt.set_prec(prec); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); } let (diff, o) = x.sub_prec_ref_val(Float::NEGATIVE_ZERO, prec); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec(prec); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::NEGATIVE_ZERO.sub_prec_val_ref(&x, prec); let mut diff_alt = -x; let o_alt = diff_alt.set_prec(prec); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn sub_round_properties_helper(x: Float, y: Float, rm: RoundingMode, extreme: bool) { let (diff, o) = x.clone().sub_round(y.clone(), rm); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_round_val_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o_alt) = x.sub_round_ref_val(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o_alt) = x.sub_round_ref_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); let o_alt = x_alt.sub_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = add_prec_round_naive( x.clone(), -&y, max(x.significant_bits(), y.significant_bits()), rm, ); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } let (diff_alt, o_alt) = x.sub_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if o == Equal && diff.is_finite() { assert_eq!(diff.add_round_ref_ref(&y, Exact).0, x); assert_eq!(x.sub_round_ref_ref(&diff, Exact).0, y); } if !extreme { let r_diff = if diff.is_finite() { if x.is_normal() && y.is_normal() && diff.is_normal() { assert_eq!( diff.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); } let r_diff = Rational::exact_from(&x) - Rational::exact_from(&y); assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } Some(r_diff) } else { assert_eq!(o, Equal); None }; match (r_diff.is_some() && *r_diff.as_ref().unwrap() >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_round(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y), rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); assert_eq!(rug_o, o); } let (mut diff_alt, mut o_alt) = y.sub_round_ref_ref(&x, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloatRef(&diff_alt.abs_negative_zero()), ComparableFloatRef(&diff.abs_negative_zero_ref()) ); let (diff_alt, o_alt) = x.add_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (mut diff_alt, mut o_alt) = (-&x).add_round_val_ref(&y, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); let (mut diff_alt, mut o_alt) = (-&x).sub_round(-&y, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (d, oo) = x.sub_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(d.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sub_round_ref_ref(&y, Exact)); } } #[test] fn sub_round_properties() { float_float_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_30().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, true); }); float_float_rounding_mode_triple_gen_var_10().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_11().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_12().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_13().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_14().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_float_rounding_mode_triple_gen_var_15().test_properties(|(x, y, rm)| { sub_round_properties_helper(x, y, rm, false); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { let (diff, o) = x.sub_round_ref_val(Float::NAN, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); let (diff, o) = Float::NAN.sub_round_val_ref(&x, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); if !x.is_nan() { if x != Float::INFINITY { assert_eq!( x.sub_round_ref_val(Float::INFINITY, rm), (Float::NEGATIVE_INFINITY, Equal) ); assert_eq!( Float::INFINITY.sub_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); } if x != Float::NEGATIVE_INFINITY { assert_eq!( x.sub_round_ref_val(Float::NEGATIVE_INFINITY, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); } } if !x.is_negative_zero() { let (diff, o) = x.sub_round_ref_val(Float::ZERO, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero_ref()), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!(o, Equal); let (diff, o) = Float::ZERO.sub_round_val_ref(&x, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat((-&x).abs_negative_zero()) ); assert_eq!(o, Equal); } if rm != Floor || !x.is_positive_zero() { let (diff, o) = x.sub_round_ref_val(Float::NEGATIVE_ZERO, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero_ref()), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!(o, Equal); let (diff, o) = Float::NEGATIVE_ZERO.sub_round_val_ref(&x, rm); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat((-&x).abs_negative_zero()) ); assert_eq!(o, Equal); } }); } #[allow(clippy::type_repetition_in_bounds)] fn sub_properties_helper_1() where Float: From + PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>, { primitive_float_pair_gen::().test_properties(|(x, y)| { let diff_1 = x - y; let diff_2 = emulate_float_float_to_float_fn(Float::sub_prec, x, y); assert_eq!(NiceFloat(diff_1), NiceFloat(diff_2)); }); } #[allow(clippy::needless_pass_by_value)] fn sub_properties_helper_2(x: Float, y: Float, extreme: bool) { let diff = x.clone() - y.clone(); assert!(diff.is_valid()); let diff_alt = x.clone() - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = &x - y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = &x - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); x_alt -= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); x_alt -= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); if !extreme { let diff_alt = add_prec_round_naive( x.clone(), -&y, max(x.significant_bits(), y.significant_bits()), Nearest, ) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); } let diff_alt = x .sub_prec_round_ref_ref(&y, max(x.significant_bits(), y.significant_bits()), Nearest) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = x .sub_prec_ref_ref(&y, max(x.significant_bits(), y.significant_bits())) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o) = x.sub_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); if o == Equal && diff.is_finite() { assert_eq!(&diff + &y, x); assert_eq!(&x - &diff, y); } if diff.is_finite() && x.is_normal() && y.is_normal() && diff.is_normal() { assert_eq!( diff.get_prec(), Some(max(x.get_prec().unwrap(), y.get_prec().unwrap())) ); if !extreme { let r_diff = Rational::exact_from(&x) - Rational::exact_from(&y); if diff < r_diff { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if diff > r_diff { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } } } let rug_diff = rug_sub(&rug::Float::exact_from(&x), &rug::Float::exact_from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); let diff_alt = -(&y - &x); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); let diff_alt = &x + -&y; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = -(-&x + &y); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); let diff_alt = -(-&x - -&y); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero()) ); } #[test] fn sub_properties() { float_pair_gen().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_10().test_properties(|(x, y)| { sub_properties_helper_2(x, y, true); }); float_pair_gen_var_2().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_3().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_4().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_5().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_6().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); float_pair_gen_var_7().test_properties(|(x, y)| { sub_properties_helper_2(x, y, false); }); apply_fn_to_primitive_floats!(sub_properties_helper_1); float_gen().test_properties(|x| { assert!((&x - Float::NAN).is_nan()); assert!((Float::NAN - &x).is_nan()); if !x.is_nan() { if x != Float::INFINITY { assert_eq!(&x - Float::INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::INFINITY - &x, Float::INFINITY); } if x != Float::NEGATIVE_INFINITY { assert_eq!(&x - Float::NEGATIVE_INFINITY, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY - &x, Float::NEGATIVE_INFINITY); } } assert_eq!( ComparableFloatRef(&(&x - Float::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloat((-(Float::ZERO - &x)).abs_negative_zero()), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat((&x - Float::NEGATIVE_ZERO).abs_negative_zero()), ComparableFloat(x.abs_negative_zero_ref()) ); assert_eq!( ComparableFloatRef(&-(Float::NEGATIVE_ZERO - &x)), ComparableFloatRef(&x) ); }); } #[allow(clippy::needless_pass_by_value)] fn sub_rational_prec_round_properties_helper( x: Float, y: Rational, prec: u64, rm: RoundingMode, extreme: bool, ) { let (diff, o) = x.clone().sub_rational_prec_round(y.clone(), prec, rm); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_rational_prec_round_val_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_val(y.clone(), prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_ref(&y, prec, rm); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_prec_round_assign(y.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_prec_round_assign_ref(&y, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y.clone(), prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_prec_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); } if o == Equal && diff.is_finite() { assert_eq!( ComparableFloat( diff.add_rational_prec_round_ref_ref(&y, x.significant_bits(), Exact) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); } if !extreme { let r_diff = Rational::exact_from(&x) - &y; assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } match (r_diff >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } let (diff_alt, o_alt) = x.add_rational_prec_round_ref_val(-&y, prec, rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-&x).add_rational_prec_round_val_ref(&y, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-&x).sub_rational_prec_round(-&y, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); if o == Equal { for rm in exhaustive_rounding_modes() { let (d, oo) = x.sub_rational_prec_round_ref_ref(&y, prec, rm); assert_eq!( ComparableFloat(d.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sub_rational_prec_round_ref_ref(&y, prec, Exact)); } } #[test] fn sub_rational_prec_round_properties() { float_rational_unsigned_rounding_mode_quadruple_gen_var_2().test_properties( |(x, y, prec, rm)| { sub_rational_prec_round_properties_helper(x, y, prec, rm, false); }, ); float_rational_unsigned_rounding_mode_quadruple_gen_var_7().test_properties_with_limit( 20, |(x, y, prec, rm)| { sub_rational_prec_round_properties_helper(x, y, prec, rm, true); }, ); float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { if !x.is_negative_zero() { let (diff, o) = x.sub_rational_prec_round_ref_val(Rational::ZERO, prec, rm); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec_round(prec, rm); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (diff, o) = Float::NAN.sub_rational_prec_round_val_ref(&x, prec, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.sub_rational_prec_round_val_ref(&x, prec, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_rational_prec_round_val_ref(&x, prec, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (diff, o) = Float::ZERO.sub_rational_prec_round_val_ref(&x, prec, rm); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_round_ref(&x, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::NEGATIVE_ZERO.sub_rational_prec_round_val_ref(&x, prec, rm); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_round_ref(&x, prec, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); }); } fn sub_rational_prec_properties_helper(x: Float, y: Rational, prec: u64, extreme: bool) { let (diff, o) = x.clone().sub_rational_prec(y.clone(), prec); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_rational_prec_val_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_ref_val(y.clone(), prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (diff_alt, o_alt) = x.sub_rational_prec_ref_ref(&y, prec); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_prec_assign(y.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_prec_assign_ref(&y, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y.clone(), prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } let (rug_diff, rug_o) = rug_sub_rational_prec( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), prec, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); if o == Equal && diff.is_finite() { assert_eq!( ComparableFloat( diff.add_rational_prec_ref_ref(&y, x.significant_bits()) .0 .abs_negative_zero() ), ComparableFloat(x.abs_negative_zero_ref()) ); // TODO additional test } let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_ref(&y, prec, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if diff.is_finite() { if diff.is_normal() { assert_eq!(diff.get_prec(), Some(prec)); } if !extreme { let r_diff = Rational::exact_from(&x) - &y; assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } } } let (diff_alt, o_alt) = x.add_rational_prec_ref_val(-&y, prec); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let (mut diff_alt, mut o_alt) = (-&x).add_rational_prec_val_ref(&y, prec); diff_alt.neg_assign(); diff_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let (mut diff_alt, mut o_alt) = (-x).sub_rational_prec(-y, prec); diff_alt.neg_assign(); diff_alt.abs_negative_zero_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } } #[test] fn sub_rational_prec_properties() { float_rational_unsigned_triple_gen_var_1().test_properties(|(x, y, prec)| { sub_rational_prec_properties_helper(x, y, prec, false); }); float_rational_unsigned_triple_gen_var_2().test_properties_with_limit(20, |(x, y, prec)| { sub_rational_prec_properties_helper(x, y, prec, true); }); float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { if !x.is_negative_zero() { let (diff, o) = x.sub_rational_prec_ref_val(Rational::ZERO, prec); let mut diff_alt = x.clone(); let o_alt = diff_alt.set_prec(prec); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (diff, o) = Float::NAN.sub_rational_prec_val_ref(&x, prec); assert!(diff.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.sub_rational_prec_val_ref(&x, prec), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_rational_prec_val_ref(&x, prec), (Float::NEGATIVE_INFINITY, Equal) ); let (diff, o) = Float::ZERO.sub_rational_prec_val_ref(&x, prec); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_ref(&x, prec); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::NEGATIVE_ZERO.sub_rational_prec_val_ref(&x, prec); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_ref(&x, prec); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloat(diff), ComparableFloat(diff_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn sub_rational_round_properties_helper(x: Float, y: Rational, rm: RoundingMode, extreme: bool) { let (diff, o) = x.clone().sub_rational_round(y.clone(), rm); assert!(diff.is_valid()); let (diff_alt, o_alt) = x.clone().sub_rational_round_val_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o_alt) = x.sub_rational_round_ref_val(y.clone(), rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o_alt) = x.sub_rational_round_ref_ref(&y, rm); assert!(diff_alt.is_valid()); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_round_assign(y.clone(), rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); let mut x_alt = x.clone(); let o_alt = x_alt.sub_rational_round_assign_ref(&y, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if !extreme { let (diff_alt, o_alt) = sub_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); } let (diff_alt, o_alt) = x.sub_rational_prec_round_ref_ref(&y, x.significant_bits(), rm); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); assert_eq!(o_alt, o); if o == Equal && diff.is_finite() && diff != 0 { assert_eq!(diff.add_rational_round_ref_ref(&y, Exact).0, x); // TODO additional test } if diff.is_finite() { if x.is_normal() && diff.is_normal() { assert_eq!(diff.get_prec(), Some(x.get_prec().unwrap())); } if !extreme { let r_diff = Rational::exact_from(&x) - &y; assert_eq!(diff.partial_cmp(&r_diff), Some(o)); if o == Less { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if o == Greater { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } match (r_diff >= 0u32, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_diff, rug_o) = rug_sub_rational_round( &rug::Float::exact_from(&x), &rug::Rational::exact_from(&y), rm, ); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff) ); assert_eq!(rug_o, o); } let (diff_alt, o_alt) = x.add_rational_round_ref_val(-&y, rm); assert_eq!(o_alt, o); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (mut diff_alt, mut o_alt) = (-&x).add_rational_round_val_ref(&y, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); let (mut diff_alt, mut o_alt) = (-&x).sub_rational_round(-&y, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(o_alt, o); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); if o == Equal { for rm in exhaustive_rounding_modes() { let (d, oo) = x.sub_rational_round_ref_ref(&y, rm); assert_eq!( ComparableFloat(d.abs_negative_zero_ref()), ComparableFloat(diff.abs_negative_zero_ref()) ); assert_eq!(oo, Equal); } } else { assert_panic!(x.sub_rational_round_ref_ref(&y, Exact)); } } #[test] fn sub_rational_round_properties() { float_rational_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { sub_rational_round_properties_helper(x, y, rm, false); }); float_rational_rounding_mode_triple_gen_var_8().test_properties_with_limit(20, |(x, y, rm)| { sub_rational_round_properties_helper(x, y, rm, true); }); float_rounding_mode_pair_gen().test_properties(|(x, rm)| { if !x.is_negative_zero() { let (diff, o) = x.sub_rational_round_ref_val(Rational::ZERO, rm); assert_eq!(ComparableFloat(diff), ComparableFloat(x)); assert_eq!(o, Equal); } }); rational_rounding_mode_pair_gen_var_6().test_properties(|(x, rm)| { let (diff, o) = Float::NAN.sub_rational_round_val_ref(&x, rm); assert!(diff.is_nan()); assert_eq!(o, Equal); assert_eq!( Float::INFINITY.sub_rational_round_val_ref(&x, rm), (Float::INFINITY, Equal) ); assert_eq!( Float::NEGATIVE_INFINITY.sub_rational_round_val_ref(&x, rm), (Float::NEGATIVE_INFINITY, Equal) ); let (diff, o) = Float::ZERO.sub_rational_round_val_ref(&x, rm); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_round_ref(&x, 1, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!( ComparableFloat(diff.abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero()) ); assert_eq!(o, o_alt); let (diff, o) = Float::NEGATIVE_ZERO.sub_rational_round_val_ref(&x, rm); let (mut diff_alt, mut o_alt) = Float::from_rational_prec_round_ref(&x, 1, -rm); diff_alt.neg_assign(); o_alt = o_alt.reverse(); assert_eq!(ComparableFloatRef(&diff), ComparableFloatRef(&diff_alt)); assert_eq!(o, o_alt); }); } #[allow(clippy::needless_pass_by_value)] fn sub_rational_properties_helper(x: Float, y: Rational, extreme: bool) { let diff = x.clone() - y.clone(); assert!(diff.is_valid()); let diff_alt = x.clone() - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = &x - y.clone(); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = &x - &y; assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = -(y.clone() - x.clone()); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = -(y.clone() - &x); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = -(&y - x.clone()); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = -(&y - &x); assert!(diff_alt.is_valid()); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); x_alt -= y.clone(); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); let mut x_alt = x.clone(); x_alt -= &y; assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&diff)); if !extreme { let diff_alt = sub_rational_prec_round_naive(x.clone(), y.clone(), x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); } let diff_alt = x .sub_rational_prec_round_ref_ref(&y, x.significant_bits(), Nearest) .0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let diff_alt = x.sub_rational_prec_ref_ref(&y, x.significant_bits()).0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); let (diff_alt, o) = x.sub_rational_round_ref_ref(&y, Nearest); assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); if o == Equal && diff.is_finite() && diff != 0 { assert_eq!(&diff + &y, x); // TODO additional test } if diff.is_finite() && x.is_normal() && diff.is_normal() { assert_eq!(diff.get_prec(), Some(x.get_prec().unwrap())); if !extreme { let r_diff = Rational::exact_from(&x) - &y; if diff < r_diff { let mut next = diff.clone(); next.increment(); assert!(next > r_diff); } else if diff > r_diff { let mut next = diff.clone(); next.decrement(); assert!(next < r_diff); } } } let rug_diff = rug_sub_rational(&rug::Float::exact_from(&x), &rug::Rational::from(&y)); assert_eq!( ComparableFloatRef(&Float::from(&rug_diff)), ComparableFloatRef(&diff), ); let diff_alt = &x + -&y; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); if (x != 0u32 && y != 0u32) || x.is_sign_positive() { let diff_alt = -(-&x + &y); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); let diff_alt = -(-&x - -&y); assert_eq!( ComparableFloat(diff_alt.abs_negative_zero()), ComparableFloat(diff.abs_negative_zero_ref()) ); } let diff_alt = sub_rational_prec_round_naive(x.clone(), y, x.significant_bits(), Nearest).0; assert_eq!(ComparableFloatRef(&diff_alt), ComparableFloatRef(&diff)); } #[test] fn sub_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { sub_rational_properties_helper(x, y, false); }); float_rational_pair_gen_var_2().test_properties_with_limit(20, |(x, y)| { sub_rational_properties_helper(x, y, true); }); float_gen().test_properties(|x| { assert_eq!( ComparableFloatRef(&(&x - Rational::ZERO)), ComparableFloatRef(&x) ); assert_eq!( ComparableFloatRef(&-(Rational::ZERO - &x)), ComparableFloatRef(&x) ); }); rational_gen().test_properties(|x| { assert!((&x - Float::NAN).is_nan()); assert!((Float::NAN - &x).is_nan()); assert_eq!(&x - Float::INFINITY, Float::NEGATIVE_INFINITY); assert_eq!(Float::INFINITY - &x, Float::INFINITY); assert_eq!(&x - Float::NEGATIVE_INFINITY, Float::INFINITY); assert_eq!(Float::NEGATIVE_INFINITY - &x, Float::NEGATIVE_INFINITY); let diff_alt = Float::from_rational_prec_ref(&x, 1).0; assert_eq!( ComparableFloat((&x - Float::ZERO).abs_negative_zero()), ComparableFloat(diff_alt.abs_negative_zero_ref()) ); assert_eq!( ComparableFloat((Float::ZERO - &x).abs_negative_zero()), ComparableFloat((-&diff_alt).abs_negative_zero()) ); assert_eq!( ComparableFloat(&x - Float::NEGATIVE_ZERO), ComparableFloat(diff_alt.clone()) ); assert_eq!( ComparableFloat(Float::NEGATIVE_ZERO - &x), ComparableFloat(-diff_alt) ); }); } ================================================ FILE: malachite-float/tests/basic/classification.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::primitive_float_gen; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; use malachite_float::{ComparableFloatRef, Float}; use std::num::FpCategory; #[test] fn test_is_nan() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_nan(), out); assert_eq!(rug::Float::exact_from(&x).is_nan(), out); }; test("NaN", "NaN", true); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_nan_properties_helper(x: Float) { let is_nan = x.is_nan(); assert_eq!( is_nan, ComparableFloatRef(&x) == ComparableFloatRef(&Float::NAN) ); assert_eq!(is_nan, x.classify() == FpCategory::Nan); assert_eq!(is_nan, !x.is_finite() && !x.is_infinite()); assert_eq!(is_nan, rug::Float::exact_from(&x).is_nan()); } #[test] fn is_nan_properties() { float_gen().test_properties(|x| { is_nan_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_nan_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!(Float::from(x).is_nan(), x.is_nan()); }); } #[test] fn test_is_finite() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_finite(), out); assert_eq!(rug::Float::exact_from(&x).is_finite(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", true); test("0.33333333333333331", "0x0.55555555555554#53", true); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", true); test("3.1415926535897931", "0x3.243f6a8885a30#53", true); test("too_big", "0x4.0E+268435455#1", true); test("too_small", "0x1.0E-268435456#1", true); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", true); test("-0.33333333333333331", "-0x0.55555555555554#53", true); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", true); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", true); test("-too_big", "-0x4.0E+268435455#1", true); test("-too_small", "-0x1.0E-268435456#1", true); } #[allow(clippy::needless_pass_by_value)] fn is_finite_properties_helper(x: Float) { let is_finite = x.is_finite(); assert_eq!(is_finite, !x.is_nan() && !x.is_infinite()); assert_eq!( is_finite, x > Float::NEGATIVE_INFINITY && x < Float::INFINITY ); assert_eq!(is_finite, rug::Float::exact_from(&x).is_finite()); } #[test] fn is_finite_properties() { float_gen().test_properties(|x| { is_finite_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_finite_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!(Float::from(x).is_finite(), x.is_finite()); }); } #[test] fn test_is_infinite() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_infinite(), out); assert_eq!(rug::Float::exact_from(&x).is_infinite(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", true); test("-Infinity", "-Infinity", true); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_infinite_properties_helper(x: Float) { let is_infinite = x.is_infinite(); assert_eq!(x.classify() == FpCategory::Infinite, is_infinite); assert_eq!(is_infinite, !x.is_nan() && !x.is_finite()); assert_eq!( is_infinite, x == Float::NEGATIVE_INFINITY || x == Float::INFINITY ); assert_eq!(is_infinite, rug::Float::exact_from(&x).is_infinite()); } #[test] fn is_infinite_properties() { float_gen().test_properties(|x| { is_infinite_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_infinite_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!(Float::from(x).is_infinite(), x.is_infinite()); }); } #[test] fn test_is_positive_zero() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_positive_zero(), out); let fx = rug::Float::exact_from(&x); assert_eq!(fx.is_zero() && fx.is_sign_positive(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_positive_zero_properties_helper(x: Float) { let is_positive_zero = x.is_positive_zero(); assert_eq!( is_positive_zero, ComparableFloatRef(&x) == ComparableFloatRef(&Float::ZERO) ); assert_eq!(is_positive_zero, x == Float::ZERO && x.is_sign_positive()); let fx = rug::Float::exact_from(&x); assert_eq!(is_positive_zero, fx.is_zero() && fx.is_sign_positive()); } #[test] fn is_positive_zero_properties() { float_gen().test_properties(|x| { is_positive_zero_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_positive_zero_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!( Float::from(x).is_positive_zero(), x == 0.0 && x.is_sign_positive() ); }); } #[test] fn test_is_negative_zero() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_negative_zero(), out); let fx = rug::Float::exact_from(&x); assert_eq!(fx.is_zero() && fx.is_sign_negative(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_negative_zero_properties_helper(x: Float) { let is_negative_zero = x.is_negative_zero(); assert_eq!( is_negative_zero, ComparableFloatRef(&x) == ComparableFloatRef(&Float::NEGATIVE_ZERO) ); assert_eq!(is_negative_zero, x == Float::ZERO && x.is_sign_negative()); let fx = rug::Float::exact_from(&x); assert_eq!(is_negative_zero, fx.is_zero() && fx.is_sign_negative()); } #[test] fn is_negative_zero_properties() { float_gen().test_properties(|x| { is_negative_zero_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_negative_zero_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!( Float::from(x).is_negative_zero(), x == 0.0 && x.is_sign_negative() ); }); } #[test] fn test_is_zero() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_zero(), out); assert_eq!(rug::Float::exact_from(&x).is_zero(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_zero_properties_helper(x: Float) { let is_zero = x.is_zero(); assert_eq!(is_zero, x == Float::ZERO); assert_eq!(is_zero, x.classify() == FpCategory::Zero); assert_eq!(is_zero, rug::Float::exact_from(&x).is_zero()); } #[test] fn is_zero_properties() { float_gen().test_properties(|x| { is_zero_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_zero_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!(Float::from(x).is_zero(), x == 0.0); }); } #[test] fn test_is_normal() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_normal(), out); assert_eq!(rug::Float::exact_from(&x).is_normal(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", true); test("0.33333333333333331", "0x0.55555555555554#53", true); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", true); test("3.1415926535897931", "0x3.243f6a8885a30#53", true); test("too_big", "0x4.0E+268435455#1", true); test("too_small", "0x1.0E-268435456#1", true); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", true); test("-0.33333333333333331", "-0x0.55555555555554#53", true); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", true); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", true); test("-too_big", "-0x4.0E+268435455#1", true); test("-too_small", "-0x1.0E-268435456#1", true); } #[allow(clippy::needless_pass_by_value)] fn is_normal_properties_helper(x: Float) { let is_normal = x.is_normal(); assert_eq!(is_normal, x.is_finite() && !x.is_zero()); assert_eq!(is_normal, x.classify() == FpCategory::Normal); assert_eq!(is_normal, rug::Float::exact_from(&x).is_normal()); } #[test] fn is_normal_properties() { float_gen().test_properties(|x| { is_normal_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_normal_properties_helper(x); }); } #[test] fn test_is_sign_positive() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_sign_positive(), out); let fx = rug::Float::exact_from(&x); assert_eq!(!fx.is_nan() && fx.is_sign_positive(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", true); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", true); test("0.33333333333333331", "0x0.55555555555554#53", true); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", true); test("3.1415926535897931", "0x3.243f6a8885a30#53", true); test("too_big", "0x4.0E+268435455#1", true); test("too_small", "0x1.0E-268435456#1", true); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", false); test("-too_big", "-0x4.0E+268435455#1", false); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_sign_positive_properties_helper(x: Float) { let is_sign_positive = x.is_sign_positive(); assert_eq!(is_sign_positive, x.is_positive_zero() || x > Float::ZERO); assert_eq!(is_sign_positive, !x.is_nan() && !x.is_sign_negative()); let fx = rug::Float::exact_from(&x); assert_eq!(is_sign_positive, !fx.is_nan() && fx.is_sign_positive()); } #[test] fn is_sign_positive_properties() { float_gen().test_properties(|x| { is_sign_positive_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_sign_positive_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!( Float::from(x).is_sign_positive(), !x.is_nan() && x.is_sign_positive() ); }); } #[test] fn test_is_sign_negative() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_sign_negative(), out); let fx = rug::Float::exact_from(&x); assert_eq!(!fx.is_nan() && fx.is_sign_negative(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", true); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", false); test("2.0", "0x2.0#1", false); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", false); test("too_big", "0x4.0E+268435455#1", false); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", true); test("-0.33333333333333331", "-0x0.55555555555554#53", true); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", true); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", true); test("-too_big", "-0x4.0E+268435455#1", true); test("-too_small", "-0x1.0E-268435456#1", true); } #[allow(clippy::needless_pass_by_value)] fn is_sign_negative_properties_helper(x: Float) { let is_sign_negative = x.is_sign_negative(); assert_eq!(is_sign_negative, x.is_negative_zero() || x < Float::ZERO); assert_eq!(is_sign_negative, !x.is_nan() && !x.is_sign_positive()); let fx = rug::Float::exact_from(&x); assert_eq!(is_sign_negative, !fx.is_nan() && fx.is_sign_negative()); } #[test] fn is_sign_negative_properties() { float_gen().test_properties(|x| { is_sign_negative_properties_helper(x); }); float_gen_var_12().test_properties(|x| { is_sign_negative_properties_helper(x); }); primitive_float_gen::().test_properties(|x| { assert_eq!( Float::from(x).is_sign_negative(), !x.is_nan() && x.is_sign_negative() ); }); } #[test] fn test_classify() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.classify(), out); assert_eq!(rug::Float::exact_from(&x).classify(), out); }; test("NaN", "NaN", FpCategory::Nan); test("Infinity", "Infinity", FpCategory::Infinite); test("-Infinity", "-Infinity", FpCategory::Infinite); test("0.0", "0x0.0", FpCategory::Zero); test("-0.0", "-0x0.0", FpCategory::Zero); test("1.0", "0x1.0#1", FpCategory::Normal); test("2.0", "0x2.0#1", FpCategory::Normal); test("0.5", "0x0.8#1", FpCategory::Normal); test( "0.33333333333333331", "0x0.55555555555554#53", FpCategory::Normal, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", FpCategory::Normal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", FpCategory::Normal, ); test("too_big", "0x4.0E+268435455#1", FpCategory::Normal); test("too_small", "0x1.0E-268435456#1", FpCategory::Normal); test("-1.0", "-0x1.0#1", FpCategory::Normal); test("-2.0", "-0x2.0#1", FpCategory::Normal); test("-0.5", "-0x0.8#1", FpCategory::Normal); test( "-0.33333333333333331", "-0x0.55555555555554#53", FpCategory::Normal, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", FpCategory::Normal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", FpCategory::Normal, ); test("-too_big", "-0x4.0E+268435455#1", FpCategory::Normal); test("-too_small", "-0x1.0E-268435456#1", FpCategory::Normal); } #[allow(clippy::needless_pass_by_value)] fn classify_properties_helper(x: Float) { assert_eq!(x.classify(), rug::Float::exact_from(&x).classify()); } #[test] fn classify_properties() { float_gen().test_properties(|x| { classify_properties_helper(x); }); float_gen_var_12().test_properties(|x| { classify_properties_helper(x); }); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_to_non_nan() { let test = |s, s_hex, out: Option<&str>, out_hex: Option<&str>| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let actual_out = x.to_non_nan(); assert!(actual_out.as_ref().is_none_or(Float::is_valid)); let actual_out_alt = x.into_non_nan(); assert!(actual_out_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(actual_out_alt, actual_out); let s = actual_out.as_ref().map(|x| x.to_string()); assert_eq!(s.as_deref(), out); let s = actual_out.map(|x| to_hex_string(&x)); assert_eq!(s.as_deref(), out_hex); }; test("NaN", "NaN", None, None); test("Infinity", "Infinity", Some("Infinity"), Some("Infinity")); test( "-Infinity", "-Infinity", Some("-Infinity"), Some("-Infinity"), ); test("0.0", "0x0.0", Some("0.0"), Some("0x0.0")); test("-0.0", "-0x0.0", Some("-0.0"), Some("-0x0.0")); test("1.0", "0x1.0#1", Some("1.0"), Some("0x1.0#1")); test("2.0", "0x2.0#1", Some("2.0"), Some("0x2.0#1")); test("0.5", "0x0.8#1", Some("0.5"), Some("0x0.8#1")); test( "0.33333333333333331", "0x0.55555555555554#53", Some("0.33333333333333331"), Some("0x0.55555555555554#53"), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Some("1.4142135623730951"), Some("0x1.6a09e667f3bcd#53"), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Some("3.1415926535897931"), Some("0x3.243f6a8885a30#53"), ); test( "too_big", "0x4.0E+268435455#1", Some("too_big"), Some("0x4.0E+268435455#1"), ); test( "too_small", "0x1.0E-268435456#1", Some("too_small"), Some("0x1.0E-268435456#1"), ); test("-1.0", "-0x1.0#1", Some("-1.0"), Some("-0x1.0#1")); test("-2.0", "-0x2.0#1", Some("-2.0"), Some("-0x2.0#1")); test("-0.5", "-0x0.8#1", Some("-0.5"), Some("-0x0.8#1")); test( "-0.33333333333333331", "-0x0.55555555555554#53", Some("-0.33333333333333331"), Some("-0x0.55555555555554#53"), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some("-1.4142135623730951"), Some("-0x1.6a09e667f3bcd#53"), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Some("-3.1415926535897931"), Some("-0x3.243f6a8885a30#53"), ); test( "-too_big", "-0x4.0E+268435455#1", Some("-too_big"), Some("-0x4.0E+268435455#1"), ); test( "-too_small", "-0x1.0E-268435456#1", Some("-too_small"), Some("-0x1.0E-268435456#1"), ); } fn to_non_nan_properties_helper(x: Float) { let nn = x.to_non_nan(); if let Some(nn) = nn { assert!(nn.is_valid()); let nn_alt = x.clone().into_non_nan().unwrap(); assert!(nn_alt.is_valid()); assert_eq!(ComparableFloatRef(&nn), ComparableFloatRef(&nn_alt)); assert_eq!(ComparableFloatRef(&nn), ComparableFloatRef(&x)); assert!(!nn.is_nan()); } else { assert!(x.is_nan()); assert!(x.into_non_nan().is_none()); } } #[test] fn to_non_nan_properties() { float_gen().test_properties(|x| { to_non_nan_properties_helper(x); }); float_gen_var_12().test_properties(|x| { to_non_nan_properties_helper(x); }); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_to_finite() { let test = |s, s_hex, out: Option<&str>, out_hex: Option<&str>| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let actual_out = x.to_finite(); assert!(actual_out.as_ref().is_none_or(Float::is_valid)); let actual_out_alt = x.into_finite(); assert!(actual_out_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(actual_out_alt, actual_out); let s = actual_out.as_ref().map(|x| x.to_string()); assert_eq!(s.as_deref(), out); let s = actual_out.map(|x| to_hex_string(&x)); assert_eq!(s.as_deref(), out_hex); }; test("NaN", "NaN", None, None); test("Infinity", "Infinity", None, None); test("-Infinity", "-Infinity", None, None); test("0.0", "0x0.0", Some("0.0"), Some("0x0.0")); test("-0.0", "-0x0.0", Some("-0.0"), Some("-0x0.0")); test("1.0", "0x1.0#1", Some("1.0"), Some("0x1.0#1")); test("2.0", "0x2.0#1", Some("2.0"), Some("0x2.0#1")); test("0.5", "0x0.8#1", Some("0.5"), Some("0x0.8#1")); test( "0.33333333333333331", "0x0.55555555555554#53", Some("0.33333333333333331"), Some("0x0.55555555555554#53"), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Some("1.4142135623730951"), Some("0x1.6a09e667f3bcd#53"), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Some("3.1415926535897931"), Some("0x3.243f6a8885a30#53"), ); test( "too_big", "0x4.0E+268435455#1", Some("too_big"), Some("0x4.0E+268435455#1"), ); test( "too_small", "0x1.0E-268435456#1", Some("too_small"), Some("0x1.0E-268435456#1"), ); test("-1.0", "-0x1.0#1", Some("-1.0"), Some("-0x1.0#1")); test("-2.0", "-0x2.0#1", Some("-2.0"), Some("-0x2.0#1")); test("-0.5", "-0x0.8#1", Some("-0.5"), Some("-0x0.8#1")); test( "-0.33333333333333331", "-0x0.55555555555554#53", Some("-0.33333333333333331"), Some("-0x0.55555555555554#53"), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some("-1.4142135623730951"), Some("-0x1.6a09e667f3bcd#53"), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Some("-3.1415926535897931"), Some("-0x3.243f6a8885a30#53"), ); test( "-too_big", "-0x4.0E+268435455#1", Some("-too_big"), Some("-0x4.0E+268435455#1"), ); test( "-too_small", "-0x1.0E-268435456#1", Some("-too_small"), Some("-0x1.0E-268435456#1"), ); } fn to_finite_properties_helper(x: Float) { let f = x.to_finite(); if let Some(f) = f { assert!(f.is_valid()); let f_alt = x.clone().into_non_nan().unwrap(); assert!(f_alt.is_valid()); assert_eq!(ComparableFloatRef(&f), ComparableFloatRef(&f_alt)); assert_eq!(ComparableFloatRef(&f), ComparableFloatRef(&x)); assert!(f.is_finite()); } else { assert!(!x.is_finite()); assert!(x.into_finite().is_none()); } } #[test] fn to_finite_properties() { float_gen().test_properties(|x| { to_finite_properties_helper(x); }); float_gen_var_12().test_properties(|x| { to_finite_properties_helper(x); }); } ================================================ FILE: malachite-float/tests/basic/complexity.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; #[test] fn test_complexity() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.complexity(), out); }; test("NaN", "NaN", 1); test("Infinity", "Infinity", 1); test("-Infinity", "-Infinity", 1); test("0.0", "0x0.0", 1); test("-0.0", "-0x0.0", 1); test("1.0", "0x1.0#1", 1); test("2.0", "0x2.0#1", 1); test("0.5", "0x0.8#1", 1); test("0.33333333333333331", "0x0.55555555555554#53", 53); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 53); test("3.1415926535897931", "0x3.243f6a8885a30#53", 53); test("3.0e120", "0x1.0E+100#1", 400); test("4.0e-121", "0x1.0E-100#1", 400); test("too_big", "0x4.0E+268435455#1", 1073741822); test("too_small", "0x1.0E-268435456#1", 1073741824); test("-1.0", "-0x1.0#1", 1); test("-2.0", "-0x2.0#1", 1); test("-0.5", "-0x0.8#1", 1); test("-0.33333333333333331", "-0x0.55555555555554#53", 53); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 53); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 53); test("-3.0e120", "-0x1.0E+100#1", 400); test("-4.0e-121", "-0x1.0E-100#1", 400); test("-too_big", "-0x4.0E+268435455#1", 1073741822); test("-too_small", "-0x1.0E-268435456#1", 1073741824); } #[test] fn test_significant_bits() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.significant_bits(), out); }; test("NaN", "NaN", 1); test("Infinity", "Infinity", 1); test("-Infinity", "-Infinity", 1); test("0.0", "0x0.0", 1); test("-0.0", "-0x0.0", 1); test("1.0", "0x1.0#1", 1); test("2.0", "0x2.0#1", 1); test("0.5", "0x0.8#1", 1); test("0.33333333333333331", "0x0.55555555555554#53", 53); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 53); test("3.1415926535897931", "0x3.243f6a8885a30#53", 53); test("3.0e120", "0x1.0E+100#1", 1); test("4.0e-121", "0x1.0E-100#1", 1); test("too_big", "0x4.0E+268435455#1", 1); test("too_small", "0x1.0E-268435456#1", 1); test("-1.0", "-0x1.0#1", 1); test("-2.0", "-0x2.0#1", 1); test("-0.5", "-0x0.8#1", 1); test("-0.33333333333333331", "-0x0.55555555555554#53", 53); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 53); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 53); test("-3.0e120", "-0x1.0E+100#1", 1); test("-4.0e-121", "-0x1.0E-100#1", 1); test("-too_big", "-0x4.0E+268435455#1", 1); test("-too_small", "-0x1.0E-268435456#1", 1); } fn complexity_properties_helper(x: Float) { let complexity = x.complexity(); assert_ne!(complexity, 0); assert_eq!((-x).complexity(), complexity); } #[test] fn complexity_properties() { float_gen().test_properties(|x| { complexity_properties_helper(x); }); float_gen_var_12().test_properties(|x| { complexity_properties_helper(x); }); } #[allow(clippy::needless_pass_by_value)] fn significant_bits_properties_helper(x: Float) { let bits = x.significant_bits(); assert_ne!(bits, 0); assert_eq!((-&x).significant_bits(), bits); assert!(bits <= x.complexity()); } #[test] fn significant_bits_properties() { float_gen().test_properties(|x| { significant_bits_properties_helper(x); }); float_gen_var_12().test_properties(|x| { significant_bits_properties_helper(x); }); } ================================================ FILE: malachite-float/tests/basic/constants.rs ================================================ // Copyright © 2026 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 crate::malachite_base::num::comparison::traits::EqAbs; use malachite_base::comparison::traits::{Max, Min}; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Two, Zero, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::unsigned_gen_var_11; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use rug::float::Special; #[test] fn test_min() { let min = Float::MIN; assert!(min.is_valid()); assert_eq!(min, f64::NEGATIVE_INFINITY); assert_eq!(min.to_string(), "-Infinity"); assert_eq!( Float::from(&rug::Float::with_val(1, Special::NegInfinity)), min ); } #[test] fn test_max() { let max = Float::MAX; assert!(max.is_valid()); assert_eq!(max, f64::INFINITY); assert_eq!(max.to_string(), "Infinity"); assert_eq!( Float::from(&rug::Float::with_val(1, Special::Infinity)), max ); } #[test] fn test_zero() { let zero = Float::ZERO; assert!(zero.is_valid()); assert_eq!(zero, 0); assert_eq!(zero, 0.0); assert!(zero.is_positive_zero()); assert!(zero.is_zero()); assert_eq!(zero.to_string(), "0.0"); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(1, Special::Zero))), ComparableFloat(zero) ); } #[test] fn test_min_positive_value_prec() { let min_positive = Float::MIN_POSITIVE; assert!(min_positive.is_valid()); assert_eq!(min_positive.to_string(), "too_small"); assert_eq!( format!("{:#x}", ComparableFloatRef(&min_positive)), "0x1.0E-268435456#1" ); assert_eq!(min_positive.get_prec(), Some(1)); assert_eq!( ComparableFloatRef(&Float::from( &(rug::Float::with_val(1, 1.0) << (Float::MIN_EXPONENT - 1)) )), ComparableFloatRef(&min_positive) ); assert_eq!( ComparableFloat(Float::min_positive_value_prec(1)), ComparableFloat(min_positive) ); let test = |p, out, out_hex| { let min_positive = Float::min_positive_value_prec(p); assert!(min_positive.is_valid()); assert_eq!(min_positive.to_string(), out); assert_eq!(to_hex_string(&min_positive), out_hex); assert_eq!( ComparableFloat(Float::from( &(rug::Float::with_val(u32::exact_from(p), 1.0) << (Float::MIN_EXPONENT - 1)) )), ComparableFloat(min_positive) ); }; test(1, "too_small", "0x1.0E-268435456#1"); test(2, "too_small", "0x1.0E-268435456#2"); test(3, "too_small", "0x1.0E-268435456#3"); test(10, "too_small", "0x1.000E-268435456#10"); test( 100, "too_small", "0x1.0000000000000000000000000E-268435456#100", ); } #[test] #[should_panic] fn min_positive_value_prec_fail() { Float::min_positive_value_prec(0); } #[test] fn min_positive_value_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let min = Float::min_positive_value_prec(p); assert!(min.is_valid()); assert_eq!(min.get_prec(), Some(p)); assert!(min.is_power_of_2()); }); } #[test] fn test_abs_is_min_positive_value_properties() { let test = |s, s_hex, out: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.abs_is_min_positive_value(), out); }; test("too_small", "0x1.0E-268435456#1", true); test("too_small", "0x1.0E-268435456#2", true); test("too_small", "0x1.0E-268435456#3", true); test("too_small", "0x1.000E-268435456#10", true); test( "too_small", "0x1.0000000000000000000000000E-268435456#100", true, ); test("-too_small", "-0x1.0E-268435456#1", true); test("-too_small", "-0x1.0E-268435456#2", true); test("-too_small", "-0x1.0E-268435456#3", true); test("-too_small", "-0x1.000E-268435456#10", true); test( "-too_small", "-0x1.0000000000000000000000000E-268435456#100", true, ); test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", false); test("-1.0", "-0x1.0#1", false); test("too_small", "0x1.8E-268435456#2", false); test("too_small", "0x2.0E-268435456#1", false); test("too_small", "0x1.0E-268435455#1", false); test("-too_small", "-0x1.8E-268435456#2", false); test("-too_small", "-0x2.0E-268435456#1", false); test("-too_small", "-0x1.0E-268435455#1", false); } fn abs_is_min_positive_value_properties_helper(x: Float) { let is_min = x.abs_is_min_positive_value(); assert_eq!( is_min, x.is_normal() && x.eq_abs(&Float::min_positive_value_prec(x.get_prec().unwrap())) ); assert_eq!((-x).abs_is_min_positive_value(), is_min); } #[test] fn abs_is_min_positive_value_properties() { float_gen().test_properties(|x| { abs_is_min_positive_value_properties_helper(x); }); float_gen_var_12().test_properties(|x| { abs_is_min_positive_value_properties_helper(x); }); } #[test] fn test_max_finite_value_with_prec() { let test = |p, out, out_hex| { let max_finite = Float::max_finite_value_with_prec(p); assert!(max_finite.is_valid()); assert_eq!(max_finite.to_string(), out); assert_eq!(to_hex_string(&max_finite), out_hex); }; test(1, "too_big", "0x4.0E+268435455#1"); test(2, "too_big", "0x6.0E+268435455#2"); test(3, "too_big", "0x7.0E+268435455#3"); test(10, "too_big", "0x7.feE+268435455#10"); test( 100, "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", ); } #[test] #[should_panic] fn max_finite_value_with_prec_fail() { Float::max_finite_value_with_prec(0); } #[test] fn max_finite_value_with_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let max = Float::max_finite_value_with_prec(p); assert!(max.is_valid()); assert_eq!(max.get_prec(), Some(p)); assert!(max > 0u32); }); } #[test] fn test_abs_is_max_finite_value_with_prec() { let test = |s, s_hex, out: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.abs_is_max_finite_value_with_prec(), out); }; test("too_big", "0x4.0E+268435455#1", true); test("too_big", "0x6.0E+268435455#2", true); test("too_big", "0x7.0E+268435455#3", true); test("too_big", "0x7.feE+268435455#10", true); test( "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", true, ); test("-too_big", "-0x4.0E+268435455#1", true); test("-too_big", "-0x6.0E+268435455#2", true); test("-too_big", "-0x7.0E+268435455#3", true); test("-too_big", "-0x7.feE+268435455#10", true); test( "-too_big", "-0x7.ffffffffffffffffffffffff8E+268435455#100", true, ); test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", false); test("-0.0", "-0x0.0", false); test("1.0", "0x1.0#1", false); test("-1.0", "-0x1.0#1", false); test("too_big", "0x2.0E+268435455#1", false); test("too_big", "0x4.0E+268435455#2", false); test("too_big", "0x4.0E+268435454#2", false); test("-too_big", "-0x2.0E+268435455#1", false); test("-too_big", "-0x4.0E+268435455#2", false); test("-too_big", "-0x4.0E+268435454#2", false); } fn abs_is_max_finite_value_with_prec_properties_helper(x: Float) { let is_max = x.abs_is_max_finite_value_with_prec(); assert_eq!( is_max, x.is_normal() && x.eq_abs(&Float::max_finite_value_with_prec(x.get_prec().unwrap())) ); assert_eq!((-x).abs_is_max_finite_value_with_prec(), is_max); } #[test] fn abs_is_max_finite_value_with_prec_properties() { float_gen().test_properties(|x| { abs_is_max_finite_value_with_prec_properties_helper(x); }); float_gen_var_12().test_properties(|x| { abs_is_max_finite_value_with_prec_properties_helper(x); }); } #[test] fn test_one_prec() { let one = Float::ONE; assert!(one.is_valid()); assert_eq!(one, 1); assert_eq!(one, 1.0); assert_eq!(one.to_string(), "1.0"); assert_eq!(one.get_prec(), Some(1)); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(1, 1.0))), ComparableFloatRef(&one) ); assert_eq!(ComparableFloat(Float::one_prec(1)), ComparableFloat(one)); let test = |p, out, out_hex| { let one = Float::one_prec(p); assert!(one.is_valid()); assert_eq!(one.to_string(), out); assert_eq!(to_hex_string(&one), out_hex); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(u32::exact_from(p), 1.0))), ComparableFloat(one) ); }; test(1, "1.0", "0x1.0#1"); test(2, "1.0", "0x1.0#2"); test(3, "1.0", "0x1.0#3"); test(10, "1.0", "0x1.000#10"); test(100, "1.0", "0x1.0000000000000000000000000#100"); } #[test] #[should_panic] fn one_prec_fail() { Float::one_prec(0); } #[test] fn one_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let one = Float::one_prec(p); assert!(one.is_valid()); assert_eq!(one, 1); assert_eq!(one, 1.0); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(u32::exact_from(p), 1.0))), ComparableFloatRef(&one) ); assert_eq!(one.get_prec(), Some(p)); }); } #[test] fn test_two_prec() { let two = Float::TWO; assert!(two.is_valid()); assert_eq!(two, 2); assert_eq!(two, 2.0); assert_eq!(two.to_string(), "2.0"); assert_eq!(two.get_prec(), Some(1)); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(1, 2.0))), ComparableFloatRef(&two) ); assert_eq!(ComparableFloat(Float::two_prec(1)), ComparableFloat(two)); let test = |p, out, out_hex| { let two = Float::two_prec(p); assert!(two.is_valid()); assert_eq!(two.to_string(), out); assert_eq!(to_hex_string(&two), out_hex); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(u32::exact_from(p), 2.0))), ComparableFloat(two) ); }; test(1, "2.0", "0x2.0#1"); test(2, "2.0", "0x2.0#2"); test(3, "2.0", "0x2.0#3"); test(10, "2.0", "0x2.00#10"); test(100, "2.0", "0x2.0000000000000000000000000#100"); } #[test] #[should_panic] fn two_prec_fail() { Float::two_prec(0); } #[test] fn two_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let two = Float::two_prec(p); assert!(two.is_valid()); assert_eq!(two, 2); assert_eq!(two, 2.0); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(u32::exact_from(p), 2.0))), ComparableFloatRef(&two) ); assert_eq!(two.get_prec(), Some(p)); }); } #[test] fn test_negative_one_prec() { let negative_one = Float::NEGATIVE_ONE; assert!(negative_one.is_valid()); assert_eq!(negative_one, -1); assert_eq!(negative_one, -1.0); assert_eq!(negative_one.to_string(), "-1.0"); assert_eq!(negative_one.get_prec(), Some(1)); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(1, -1.0))), ComparableFloatRef(&negative_one) ); assert_eq!( ComparableFloat(Float::negative_one_prec(1)), ComparableFloat(negative_one) ); let test = |p, out, out_hex| { let negative_one = Float::negative_one_prec(p); assert!(negative_one.is_valid()); assert_eq!(negative_one.to_string(), out); assert_eq!(to_hex_string(&negative_one), out_hex); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(u32::exact_from(p), -1.0))), ComparableFloat(negative_one) ); }; test(1, "-1.0", "-0x1.0#1"); test(2, "-1.0", "-0x1.0#2"); test(3, "-1.0", "-0x1.0#3"); test(10, "-1.0", "-0x1.000#10"); test(100, "-1.0", "-0x1.0000000000000000000000000#100"); } #[test] #[should_panic] fn negative_one_prec_fail() { Float::negative_one_prec(0); } #[test] fn negative_one_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let negative_one = Float::negative_one_prec(p); assert!(negative_one.is_valid()); assert_eq!(negative_one, -1); assert_eq!(negative_one, -1.0); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val( u32::exact_from(p), -1.0 ))), ComparableFloatRef(&negative_one) ); assert_eq!(negative_one.get_prec(), Some(p)); }); } #[test] fn test_one_half_prec() { let one_half = Float::ONE_HALF; assert!(one_half.is_valid()); assert_eq!(one_half, 0.5); assert_eq!(one_half.to_string(), "0.5"); assert_eq!(one_half.get_prec(), Some(1)); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(1, 0.5))), ComparableFloatRef(&one_half) ); assert_eq!( ComparableFloat(Float::one_half_prec(1)), ComparableFloat(one_half) ); let test = |p, out, out_hex| { let one_half = Float::one_half_prec(p); assert!(one_half.is_valid()); assert_eq!(one_half.to_string(), out); assert_eq!(to_hex_string(&one_half), out_hex); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(u32::exact_from(p), 0.5))), ComparableFloat(one_half) ); }; test(1, "0.5", "0x0.8#1"); test(2, "0.5", "0x0.8#2"); test(3, "0.5", "0x0.8#3"); test(10, "0.5", "0x0.800#10"); test(100, "0.5", "0x0.8000000000000000000000000#100"); } #[test] #[should_panic] fn one_half_prec_fail() { Float::one_half_prec(0); } #[test] fn one_half_prec_properties() { unsigned_gen_var_11().test_properties(|p| { let one_half = Float::one_half_prec(p); assert!(one_half.is_valid()); assert_eq!(one_half, 0.5); assert_eq!( ComparableFloatRef(&Float::from(&rug::Float::with_val(u32::exact_from(p), 0.5))), ComparableFloatRef(&one_half) ); assert_eq!(one_half.get_prec(), Some(p)); }); } #[test] fn test_negative_zero() { let negative_zero = Float::NEGATIVE_ZERO; assert!(negative_zero.is_valid()); assert_eq!(negative_zero, 0); assert!(negative_zero.is_negative_zero()); assert!(negative_zero.is_zero()); assert_eq!(negative_zero.to_string(), "-0.0"); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(1, Special::NegZero))), ComparableFloat(negative_zero) ); } #[test] fn test_nan() { let nan = Float::NAN; assert!(nan.is_valid()); assert!(nan.is_nan()); assert_eq!(nan.to_string(), "NaN"); assert_eq!( ComparableFloat(Float::from(&rug::Float::with_val(1, Special::Nan))), ComparableFloat(nan) ); } #[test] fn test_infinity() { let infinity = Float::INFINITY; assert!(infinity.is_valid()); assert_eq!(infinity, f64::INFINITY); assert_eq!(infinity.to_string(), "Infinity"); assert_eq!( Float::from(&rug::Float::with_val(1, Special::Infinity)), infinity ); } #[test] fn test_negative_infinity() { let negative_infinity = Float::NEGATIVE_INFINITY; assert!(negative_infinity.is_valid()); assert_eq!(negative_infinity, f64::NEGATIVE_INFINITY); assert_eq!(negative_infinity.to_string(), "-Infinity"); assert_eq!( Float::from(&rug::Float::with_val(1, Special::NegInfinity)), negative_infinity ); } #[test] fn test_default() { let d = Float::default(); assert!(d.is_valid()); assert!(d.is_nan()); assert_eq!(d.to_string(), "NaN"); } ================================================ FILE: malachite-float/tests/basic/get_and_set.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::ToDebugString; use malachite_float::test_util::common::{ parse_hex_string, rug_round_exact_from_rounding_mode, to_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_unsigned_pair_gen_var_1, float_unsigned_pair_gen_var_4, float_unsigned_rounding_mode_triple_gen_var_1, float_unsigned_rounding_mode_triple_gen_var_4, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use std::cmp::Ordering::*; #[test] fn test_to_significand() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let significand = x.to_significand(); assert_eq!(x.significand_ref(), significand.as_ref()); assert_eq!(x.clone().into_significand(), significand); if Limb::WIDTH == u64::WIDTH { assert_eq!(significand.to_debug_string(), out); assert_eq!( rug::Float::exact_from(&x) .get_significand() .map(|s| Natural::exact_from(&*s)), significand ); } }; test("NaN", "NaN", "None"); test("Infinity", "Infinity", "None"); test("-Infinity", "-Infinity", "None"); test("0.0", "0x0.0", "None"); test("-0.0", "-0x0.0", "None"); test("1.0", "0x1.0#1", "Some(9223372036854775808)"); test("2.0", "0x2.0#1", "Some(9223372036854775808)"); test("0.5", "0x0.8#1", "Some(9223372036854775808)"); test( "0.33333333333333331", "0x0.55555555555554#53", "Some(12297829382473033728)", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "Some(13043817825332783104)", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "Some(14488038916154245120)", ); test("3.0e120", "0x1.0E+100#1", "Some(9223372036854775808)"); test("4.0e-121", "0x1.0E-100#1", "Some(9223372036854775808)"); test( "2.582249878086908589655919172003011874329705792829223512830659e120", "0x1.00000000000000000000000000000000000000000000000000E+100#200", "Some(57896044618658097711785492504343953926634992332820282019728792003956564819968)", ); test( "3.872591914849318272818030633286351847570219192048790865487763e-121", "0x1.00000000000000000000000000000000000000000000000000E-100#200", "Some(57896044618658097711785492504343953926634992332820282019728792003956564819968)", ); test("too_big", "0x4.0E+268435455#1", "Some(9223372036854775808)"); test( "too_small", "0x1.0E-268435456#1", "Some(9223372036854775808)", ); test("-1.0", "-0x1.0#1", "Some(9223372036854775808)"); test("-2.0", "-0x2.0#1", "Some(9223372036854775808)"); test("-0.5", "-0x0.8#1", "Some(9223372036854775808)"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "Some(12297829382473033728)", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "Some(13043817825332783104)", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "Some(14488038916154245120)", ); test("-3.0e120", "-0x1.0E+100#1", "Some(9223372036854775808)"); test("-4.0e-121", "-0x1.0E-100#1", "Some(9223372036854775808)"); test( "-2.582249878086908589655919172003011874329705792829223512830659e120", "-0x1.00000000000000000000000000000000000000000000000000E+100#200", "Some(57896044618658097711785492504343953926634992332820282019728792003956564819968)", ); test( "-3.872591914849318272818030633286351847570219192048790865487763e-121", "-0x1.00000000000000000000000000000000000000000000000000E-100#200", "Some(57896044618658097711785492504343953926634992332820282019728792003956564819968)", ); test( "-too_big", "-0x4.0E+268435455#1", "Some(9223372036854775808)", ); test( "-too_small", "-0x1.0E-268435456#1", "Some(9223372036854775808)", ); } fn to_significand_properties_helper(x: Float) { let significand = x.to_significand(); assert_eq!(x.significand_ref(), significand.as_ref()); assert_eq!(x.clone().into_significand(), significand); if Limb::WIDTH == u64::WIDTH { assert_eq!( rug::Float::exact_from(&x) .get_significand() .map(|s| Natural::exact_from(&*s)), significand ); } significand.as_ref().map_or_else( || { assert!(!x.is_normal()); }, |significand| { assert_ne!(*significand, 0u32); assert!( significand .significant_bits() .divisible_by_power_of_2(Limb::LOG_WIDTH) ); }, ); assert_eq!((-x).into_significand(), significand); } #[test] fn to_significand_properties() { float_gen().test_properties(|x| { to_significand_properties_helper(x); }); float_gen_var_12().test_properties(|x| { to_significand_properties_helper(x); }); } #[test] fn test_get_exponent() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let exponent = x.get_exponent(); assert_eq!(exponent, out); assert_eq!(rug::Float::exact_from(&x).get_exp(), out); }; test("NaN", "NaN", None); test("Infinity", "Infinity", None); test("-Infinity", "-Infinity", None); test("0.0", "0x0.0", None); test("-0.0", "-0x0.0", None); test("1.0", "0x1.0#1", Some(1)); test("2.0", "0x2.0#1", Some(2)); test("0.5", "0x0.8#1", Some(0)); test("0.33333333333333331", "0x0.55555555555554#53", Some(-1)); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", Some(1)); test("3.1415926535897931", "0x3.243f6a8885a30#53", Some(2)); test("3.0e120", "0x1.0E+100#1", Some(401)); test("4.0e-121", "0x1.0E-100#1", Some(-399)); test( "2.582249878086908589655919172003011874329705792829223512830659e120", "0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(401), ); test( "3.872591914849318272818030633286351847570219192048790865487763e-121", "0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(-399), ); test("too_big", "0x4.0E+268435455#1", Some(1073741823)); test("too_small", "0x1.0E-268435456#1", Some(-1073741823)); test("-1.0", "-0x1.0#1", Some(1)); test("-2.0", "-0x2.0#1", Some(2)); test("-0.5", "-0x0.8#1", Some(0)); test("-0.33333333333333331", "-0x0.55555555555554#53", Some(-1)); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some(1)); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", Some(2)); test("-3.0e120", "-0x1.0E+100#1", Some(401)); test("-4.0e-121", "-0x1.0E-100#1", Some(-399)); test( "-2.582249878086908589655919172003011874329705792829223512830659e120", "-0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(401), ); test( "-3.872591914849318272818030633286351847570219192048790865487763e-121", "-0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(-399), ); test("-too_big", "-0x4.0E+268435455#1", Some(1073741823)); test("-too_small", "-0x1.0E-268435456#1", Some(-1073741823)); } fn get_exponent_properties_helper(x: Float) { let exponent = x.get_exponent(); assert_eq!(rug::Float::exact_from(&x).get_exp(), exponent); if let Some(exponent) = exponent { assert_eq!(x.sci_exponent() + 1, exponent); assert!(exponent <= Float::MAX_EXPONENT); assert!(exponent >= Float::MIN_EXPONENT); } else { assert!(!x.is_normal()); } } #[test] fn get_exponent_properties() { float_gen().test_properties(|x| { get_exponent_properties_helper(x); }); float_gen_var_12().test_properties(|x| { get_exponent_properties_helper(x); }); } #[test] fn test_get_prec() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let exponent = x.get_prec(); assert_eq!(exponent, out); if x.is_normal() { assert_eq!(Some(u64::from(rug::Float::exact_from(&x).prec())), out); } }; test("NaN", "NaN", None); test("Infinity", "Infinity", None); test("-Infinity", "-Infinity", None); test("0.0", "0x0.0", None); test("-0.0", "-0x0.0", None); test("1.0", "0x1.0#1", Some(1)); test("2.0", "0x2.0#1", Some(1)); test("0.5", "0x0.8#1", Some(1)); test("0.33333333333333331", "0x0.55555555555554#53", Some(53)); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", Some(53)); test("3.1415926535897931", "0x3.243f6a8885a30#53", Some(53)); test("3.0e120", "0x1.0E+100#1", Some(1)); test("4.0e-121", "0x1.0E-100#1", Some(1)); test( "2.582249878086908589655919172003011874329705792829223512830659e120", "0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(200), ); test( "3.872591914849318272818030633286351847570219192048790865487763e-121", "0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(200), ); test("too_big", "0x4.0E+268435455#1", Some(1)); test("too_small", "0x1.0E-268435456#1", Some(1)); test("-1.0", "-0x1.0#1", Some(1)); test("-2.0", "-0x2.0#1", Some(1)); test("-0.5", "-0x0.8#1", Some(1)); test("-0.33333333333333331", "-0x0.55555555555554#53", Some(53)); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some(53)); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", Some(53)); test("-3.0e120", "-0x1.0E+100#1", Some(1)); test("-4.0e-121", "-0x1.0E-100#1", Some(1)); test( "-2.582249878086908589655919172003011874329705792829223512830659e120", "-0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(200), ); test( "-3.872591914849318272818030633286351847570219192048790865487763e-121", "-0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(200), ); test("-too_big", "-0x4.0E+268435455#1", Some(1)); test("-too_small", "-0x1.0E-268435456#1", Some(1)); } #[allow(clippy::needless_pass_by_value)] fn get_prec_properties_helper(x: Float) { x.get_prec().map_or_else( || { assert!(!x.is_normal()); }, |precision| { assert_eq!(u64::from(rug::Float::exact_from(&x).prec()), precision); }, ); } #[test] fn get_prec_properties() { float_gen().test_properties(|x| { get_prec_properties_helper(x); }); float_gen_var_12().test_properties(|x| { get_prec_properties_helper(x); }); } #[test] fn test_get_min_prec() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let exponent = x.get_min_prec(); assert_eq!(exponent, out); }; test("NaN", "NaN", None); test("Infinity", "Infinity", None); test("-Infinity", "-Infinity", None); test("0.0", "0x0.0", None); test("-0.0", "-0x0.0", None); test("1.0", "0x1.0#1", Some(1)); test("2.0", "0x2.0#1", Some(1)); test("0.5", "0x0.8#1", Some(1)); test("0.33333333333333331", "0x0.55555555555554#53", Some(53)); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", Some(53)); test("3.1415926535897931", "0x3.243f6a8885a30#53", Some(50)); test("3.0e120", "0x1.0E+100#1", Some(1)); test("4.0e-121", "0x1.0E-100#1", Some(1)); test( "2.582249878086908589655919172003011874329705792829223512830659e120", "0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(1), ); test( "3.872591914849318272818030633286351847570219192048790865487763e-121", "0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(1), ); test("too_big", "0x4.0E+268435455#1", Some(1)); test("too_small", "0x1.0E-268435456#1", Some(1)); test("-1.0", "-0x1.0#1", Some(1)); test("-2.0", "-0x2.0#1", Some(1)); test("-0.5", "-0x0.8#1", Some(1)); test("-0.33333333333333331", "-0x0.55555555555554#53", Some(53)); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some(53)); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", Some(50)); test("-3.0e120", "-0x1.0E+100#1", Some(1)); test("-4.0e-121", "-0x1.0E-100#1", Some(1)); test( "-2.582249878086908589655919172003011874329705792829223512830659e120", "-0x1.00000000000000000000000000000000000000000000000000E+100#200", Some(1), ); test( "-3.872591914849318272818030633286351847570219192048790865487763e-121", "-0x1.00000000000000000000000000000000000000000000000000E-100#200", Some(1), ); test("-too_big", "-0x4.0E+268435455#1", Some(1)); test("-too_small", "-0x1.0E-268435456#1", Some(1)); } #[allow(clippy::needless_pass_by_value)] fn get_min_prec_properties_helper(x: Float) { x.get_min_prec().map_or_else( || { assert!(!x.is_normal()); }, |min_prec| { assert!(min_prec <= x.get_prec().unwrap()); }, ); } #[test] fn get_min_prec_properties() { float_gen().test_properties(|x| { get_min_prec_properties_helper(x); }); float_gen_var_12().test_properties(|x| { get_min_prec_properties_helper(x); }); } #[test] fn test_set_prec_round() { let test = |s, s_hex, prec, rm, out, out_hex, o| { let mut x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let old_x = x.clone(); assert_eq!(x.set_prec_round(prec, rm), o); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); let (x_alt, o_alt) = Float::from_float_prec_round(old_x.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let (x_alt, o_alt) = Float::from_float_prec_round_ref(&old_x, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); if rm != Exact { let mut rug_x = rug::Float::exact_from(&old_x); assert_eq!( rug_x.set_prec_round( u32::exact_from(prec), rug_round_exact_from_rounding_mode(rm) ), o ); assert_eq!(ComparableFloat(x), ComparableFloat(Float::from(&rug_x))); } }; test("NaN", "NaN", 100, Floor, "NaN", "NaN", Equal); test("NaN", "NaN", 100, Exact, "NaN", "NaN", Equal); test( "Infinity", "Infinity", 100, Floor, "Infinity", "Infinity", Equal, ); test( "Infinity", "Infinity", 100, Exact, "Infinity", "Infinity", Equal, ); test( "-Infinity", "-Infinity", 100, Floor, "-Infinity", "-Infinity", Equal, ); test( "-Infinity", "-Infinity", 100, Exact, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 100, Floor, "0.0", "0x0.0", Equal); test("0.0", "0x0.0", 100, Exact, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 100, Floor, "-0.0", "-0x0.0", Equal); test("-0.0", "-0x0.0", 100, Exact, "-0.0", "-0x0.0", Equal); test( "1.0", "0x1.0#1", 100, Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0#1", 100, Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0#1", 100, Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0#1", 100, Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0#1", 100, Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1.0", "0x1.0#1", 100, Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Floor, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Ceiling, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Down, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Up, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Nearest, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Exact, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Floor, "3.141", "0x3.24#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Ceiling, "3.145", "0x3.25#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Down, "3.141", "0x3.24#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Up, "3.145", "0x3.25#10", Greater, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, Nearest, "3.141", "0x3.24#10", Less, ); test( "too_big", "0x6.0E+268435455#2", 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test( "too_big", "0x6.0E+268435455#2", 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test( "too_big", "0x6.0E+268435455#2", 1, Ceiling, "Infinity", "Infinity", Greater, ); test( "too_big", "0x6.0E+268435455#2", 1, Up, "Infinity", "Infinity", Greater, ); // It doesn't really make sense that rounding with `Nearest` could overflow, but this matches // the behavior of MPFR. test( "too_big", "0x6.0E+268435455#2", 1, Nearest, "Infinity", "Infinity", Greater, ); test( "too_small", "0x1.8E-268435456#2", 1, Floor, "too_small", "0x1.0E-268435456#1", Less, ); test( "too_small", "0x1.8E-268435456#2", 1, Down, "too_small", "0x1.0E-268435456#1", Less, ); test( "too_small", "0x1.8E-268435456#2", 1, Ceiling, "too_small", "0x2.0E-268435456#1", Greater, ); test( "too_small", "0x1.8E-268435456#2", 1, Up, "too_small", "0x2.0E-268435456#1", Greater, ); test( "too_small", "0x1.8E-268435456#2", 1, Nearest, "too_small", "0x2.0E-268435456#1", Greater, ); test( "-1.0", "-0x1.0#1", 100, Floor, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0#1", 100, Ceiling, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0#1", 100, Down, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0#1", 100, Up, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0#1", 100, Nearest, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1.0", "-0x1.0#1", 100, Exact, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Floor, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Floor, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Down, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Up, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Nearest, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Exact, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Floor, "-3.145", "-0x3.25#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Ceiling, "-3.141", "-0x3.24#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Down, "-3.141", "-0x3.24#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Up, "-3.145", "-0x3.25#10", Less, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, Nearest, "-3.141", "-0x3.24#10", Greater, ); test( "-too_big", "-0x6.0E+268435455#2", 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test( "-too_big", "-0x6.0E+268435455#2", 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test( "-too_big", "-0x6.0E+268435455#2", 1, Floor, "-Infinity", "-Infinity", Less, ); test( "-too_big", "-0x6.0E+268435455#2", 1, Up, "-Infinity", "-Infinity", Less, ); // It doesn't really make sense that rounding with `Nearest` could overflow, but this matches // the behavior of MPFR. test( "-too_big", "-0x6.0E+268435455#2", 1, Nearest, "-Infinity", "-Infinity", Less, ); test( "-too_small", "-0x1.8E-268435456#2", 1, Ceiling, "-too_small", "-0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x1.8E-268435456#2", 1, Down, "-too_small", "-0x1.0E-268435456#1", Greater, ); test( "-too_small", "-0x1.8E-268435456#2", 1, Floor, "-too_small", "-0x2.0E-268435456#1", Less, ); test( "-too_small", "-0x1.8E-268435456#2", 1, Up, "-too_small", "-0x2.0E-268435456#1", Less, ); test( "-too_small", "-0x1.8E-268435456#2", 1, Nearest, "-too_small", "-0x2.0E-268435456#1", Less, ); } #[test] #[should_panic] fn set_prec_round_fail() { let mut x = Float::from(std::f64::consts::PI); x.set_prec_round(10, Exact); } fn set_prec_round_properties_helper(mut x: Float, prec: u64, rm: RoundingMode) { let old_x = x.clone(); let o = x.set_prec_round(prec, rm); assert!(x.is_valid()); let final_x = x.clone(); if x.is_normal() { assert_eq!(x.get_prec(), Some(prec)); assert_eq!(x.partial_cmp(&old_x), Some(o)); } else { assert!(o != if x > 0 { Less } else { Greater }); } let (x_alt, o_alt) = Float::from_float_prec_round(old_x.clone(), prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let (x_alt, o_alt) = Float::from_float_prec_round_ref(&old_x, prec, rm); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); if rm == Exact { assert_eq!(o, Equal); } else { let mut rug_x = rug::Float::exact_from(&old_x); assert_eq!( rug_x.set_prec_round( u32::exact_from(prec), rug_round_exact_from_rounding_mode(rm) ), o ); assert_eq!( ComparableFloatRef(&x), ComparableFloatRef(&Float::from(&rug_x)) ); } if o == Equal && let Some(old_precision) = old_x.get_prec() { assert_eq!(x.set_prec_round(old_precision, Exact), Equal); assert_eq!(ComparableFloatRef(&x), ComparableFloatRef(&old_x)); } let mut x = -old_x; x.set_prec_round(prec, -rm); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); } #[test] fn set_prec_round_properties() { float_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { set_prec_round_properties_helper(x, prec, rm); }); float_unsigned_rounding_mode_triple_gen_var_4().test_properties(|(x, prec, rm)| { set_prec_round_properties_helper(x, prec, rm); }); } #[test] fn test_set_prec() { let test = |s, s_hex, prec, out, out_hex, o| { let mut x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let old_x = x.clone(); assert_eq!(x.set_prec(prec), o); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); let (x_alt, o_alt) = Float::from_float_prec(old_x.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let (x_alt, o_alt) = Float::from_float_prec_ref(&old_x, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let mut rug_x = rug::Float::exact_from(&old_x); rug_x.set_prec(u32::exact_from(prec)); assert_eq!(ComparableFloat(x), ComparableFloat(Float::from(&rug_x))); }; test("NaN", "NaN", 100, "NaN", "NaN", Equal); test("Infinity", "Infinity", 100, "Infinity", "Infinity", Equal); test( "-Infinity", "-Infinity", 100, "-Infinity", "-Infinity", Equal, ); test("0.0", "0x0.0", 100, "0.0", "0x0.0", Equal); test("-0.0", "-0x0.0", 100, "-0.0", "-0x0.0", Equal); test( "1.0", "0x1.0#1", 100, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test( "0.33333333333333331", "0x0.55555555555554#53", 10, "0.3335", "0x0.556#10", Greater, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 10, "1.414", "0x1.6a0#10", Less, ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 10, "3.141", "0x3.24#10", Less, ); // It doesn't really make sense that rounding with `Nearest` could overflow, but this matches // the behavior of MPFR. test( "too_big", "0x6.0E+268435455#2", 1, "Infinity", "Infinity", Greater, ); test( "too_small", "0x1.8E-268435456#2", 1, "too_small", "0x2.0E-268435456#1", Greater, ); test( "-1.0", "-0x1.0#1", 100, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", 10, "-0.3335", "-0x0.556#10", Less, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 10, "-1.414", "-0x1.6a0#10", Greater, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 10, "-3.141", "-0x3.24#10", Greater, ); // It doesn't really make sense that rounding with `Nearest` could overflow, but this matches // the behavior of MPFR. test( "-too_big", "-0x6.0E+268435455#2", 1, "-Infinity", "-Infinity", Less, ); test( "-too_small", "-0x1.8E-268435456#2", 1, "-too_small", "-0x2.0E-268435456#1", Less, ); } fn set_prec_properties_helper(mut x: Float, prec: u64) { let old_x = x.clone(); let o = x.set_prec(prec); let final_x = x.clone(); assert!(x.is_valid()); if x.is_normal() { assert_eq!(x.get_prec(), Some(prec)); assert_eq!(x.partial_cmp(&old_x), Some(o)); } else { assert!(o != if x > 0 { Less } else { Greater }); } let (x_alt, o_alt) = Float::from_float_prec(old_x.clone(), prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let (x_alt, o_alt) = Float::from_float_prec_ref(&old_x, prec); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let mut rug_x = rug::Float::exact_from(&old_x); rug_x.set_prec(u32::exact_from(prec)); assert_eq!( ComparableFloatRef(&x), ComparableFloatRef(&Float::from(&rug_x)) ); if o == Equal && let Some(old_precision) = old_x.get_prec() { assert_eq!(x.set_prec_round(old_precision, Exact), Equal); assert_eq!(ComparableFloatRef(&x), ComparableFloatRef(&old_x)); } let mut x = -old_x; x.set_prec(prec); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); } #[test] fn set_prec_properties() { float_unsigned_pair_gen_var_1().test_properties(|(x, prec)| { set_prec_properties_helper(x, prec); }); float_unsigned_pair_gen_var_4().test_properties(|(x, prec)| { set_prec_properties_helper(x, prec); }); } ================================================ FILE: malachite-float/tests/basic/named.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_float::Float; #[test] fn test_named() { assert_eq!(Float::NAME, "Float"); } ================================================ FILE: malachite-float/tests/basic/overflow_and_underflow.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::{self, *}; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_ordering_pair_gen, float_ordering_pair_gen_var_1, }; use malachite_float::{Float, test_overflow, test_underflow}; #[test] fn test_test_overflow() { let test = |s, s_hex, o, out: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(test_overflow(&x, o), out); }; test("Infinity", "Infinity", Greater, true); // This input doesn't actually make sense, since Infinity can't be less than the actual value test("Infinity", "Infinity", Less, false); test("-Infinity", "-Infinity", Less, true); // Likewise test("-Infinity", "-Infinity", Greater, false); test("too_big", "0x4.0E+268435455#1", Equal, false); test("too_big", "0x4.0E+268435455#1", Less, true); test("too_big", "0x6.0E+268435455#2", Less, true); test("too_big", "0x7.0E+268435455#3", Less, true); test("too_big", "0x7.feE+268435455#10", Less, true); test( "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", Less, true, ); test("too_big", "0x4.0E+268435454#1", Less, false); test("too_big", "0x6.0E+268435454#2", Less, false); test("too_big", "0x7.0E+268435454#3", Less, false); test("too_big", "0x4.0E+268435455#1", Greater, false); test("too_big", "0x6.0E+268435455#2", Greater, false); test("too_big", "0x7.0E+268435455#3", Greater, false); test("too_big", "0x7.feE+268435455#10", Greater, false); test( "too_big", "0x7.ffffffffffffffffffffffff8E+268435455#100", Greater, false, ); test("-too_big", "-0x4.0E+268435455#1", Equal, false); test("-too_big", "-0x4.0E+268435455#1", Greater, true); test("-too_big", "-0x6.0E+268435455#2", Greater, true); test("-too_big", "-0x7.0E+268435455#3", Greater, true); test("-too_big", "-0x7.feE+268435455#10", Greater, true); test( "-too_big", "-0x7.ffffffffffffffffffffffff8E+268435455#100", Greater, true, ); test("-too_big", "-0x4.0E+268435454#1", Greater, false); test("-too_big", "-0x6.0E+268435454#2", Greater, false); test("-too_big", "-0x7.0E+268435454#3", Greater, false); test("-too_big", "-0x4.0E+268435455#1", Less, false); test("-too_big", "-0x6.0E+268435455#2", Less, false); test("-too_big", "-0x7.0E+268435455#3", Less, false); test("-too_big", "-0x7.feE+268435455#10", Less, false); test( "-too_big", "-0x7.ffffffffffffffffffffffff8E+268435455#100", Less, false, ); test("0.0", "0x0.0", Equal, false); test("-0.0", "-0x0.0", Equal, false); test("1.0", "0x1.0#1", Equal, false); test("-1.0", "-0x1.0#1", Equal, false); } #[allow(clippy::needless_pass_by_value)] fn test_overflow_properties_helper(x: Float, o: Ordering) { let overflow = test_overflow(&x, o); assert_eq!(test_overflow(&-x, o.reverse()), overflow); } #[test] fn test_overflow_properties() { float_ordering_pair_gen().test_properties(|(x, o)| { test_overflow_properties_helper(x, o); }); float_ordering_pair_gen_var_1().test_properties(|(x, o)| { test_overflow_properties_helper(x, o); }); } #[test] fn test_test_underflow() { let test = |s, s_hex, o, out: bool| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(test_underflow(&x, o), out); }; test("0.0", "0x0.0", Less, true); test("0.0", "0x0.0", Greater, true); test("-0.0", "-0x0.0", Less, true); test("-0.0", "-0x0.0", Greater, true); test("too_small", "0x1.0E-268435456#1", Equal, false); test("too_small", "0x1.0E-268435456#1", Greater, true); test("too_small", "0x1.0E-268435456#2", Greater, true); test("too_small", "0x1.0E-268435456#3", Greater, true); test("too_small", "0x1.000E-268435456#10", Greater, true); test( "too_small", "0x1.0000000000000000000000000E-268435456#100", Greater, true, ); test("too_small", "0x1.8E-268435456#2", Greater, false); test("too_small", "0x2.0E-268435456#1", Greater, false); test("too_small", "0x1.0E-268435455#1", Greater, false); test("too_small", "0x1.0E-268435456#1", Less, false); test("too_small", "0x1.0E-268435456#2", Less, false); test("too_small", "0x1.0E-268435456#3", Less, false); test("too_small", "0x1.000E-268435456#10", Less, false); test( "too_small", "0x1.0000000000000000000000000E-268435456#100", Less, false, ); test("-too_small", "-0x1.0E-268435456#1", Equal, false); test("-too_small", "-0x1.0E-268435456#1", Less, true); test("-too_small", "-0x1.0E-268435456#2", Less, true); test("-too_small", "-0x1.0E-268435456#3", Less, true); test("-too_small", "-0x1.000E-268435456#10", Less, true); test( "-too_small", "-0x1.0000000000000000000000000E-268435456#100", Less, true, ); test("-too_small", "-0x1.8E-268435456#2", Less, false); test("-too_small", "-0x2.0E-268435456#1", Less, false); test("-too_small", "-0x1.0E-268435455#1", Less, false); test("-too_small", "-0x1.0E-268435456#1", Greater, false); test("-too_small", "-0x1.0E-268435456#2", Greater, false); test("-too_small", "-0x1.0E-268435456#3", Greater, false); test("-too_small", "-0x1.000E-268435456#10", Greater, false); test( "-too_small", "-0x1.0000000000000000000000000E-268435456#100", Greater, false, ); test("0.0", "0x0.0", Equal, false); test("-0.0", "-0x0.0", Equal, false); test("1.0", "0x1.0#1", Equal, false); test("-1.0", "-0x1.0#1", Equal, false); } #[allow(clippy::needless_pass_by_value)] fn test_underflow_properties_helper(x: Float, o: Ordering) { let underflow = test_underflow(&x, o); assert_eq!(test_underflow(&-x, o.reverse()), underflow); } #[test] fn test_underflow_properties() { float_ordering_pair_gen().test_properties(|(x, o)| { test_underflow_properties_helper(x, o); }); float_ordering_pair_gen_var_1().test_properties(|(x, o)| { test_underflow_properties_helper(x, o); }); } ================================================ FILE: malachite-float/tests/basic/size.rs ================================================ // Copyright © 2026 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 malachite_float::Float; use std::mem::size_of; #[test] fn test_size() { if size_of::() == size_of::() { assert_eq!(size_of::(), 40); } } ================================================ FILE: malachite-float/tests/basic/ulp.rs ================================================ // Copyright © 2026 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 malachite_base::assert_panic; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; use malachite_base::test_util::generators::primitive_float_gen_var_12; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::conversion::from_primitive_float::alt_precision; use malachite_float::test_util::generators::{ float_gen, float_gen_var_3, float_gen_var_12, float_gen_var_13, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::panic::catch_unwind; #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_ulp() { let test = |s, s_hex, out: Option<&str>, out_hex: Option<&str>| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let actual_out = x.ulp(); assert!(actual_out.as_ref().is_none_or(Float::is_valid)); let s = actual_out.as_ref().map(|x| x.to_string()); assert_eq!(s.as_deref(), out); let s = actual_out.map(|x| to_hex_string(&x)); assert_eq!(s.as_deref(), out_hex); }; test("NaN", "NaN", None, None); test("Infinity", "Infinity", None, None); test("-Infinity", "-Infinity", None, None); test("0.0", "0x0.0", None, None); test("-0.0", "-0x0.0", None, None); test("1.0", "0x1.0#1", Some("1.0"), Some("0x1.0#1")); test("2.0", "0x2.0#1", Some("2.0"), Some("0x2.0#1")); test("0.5", "0x0.8#1", Some("0.5"), Some("0x0.8#1")); test( "0.33333333333333331", "0x0.55555555555554#53", Some("6.0e-17"), Some("0x4.0E-14#1"), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", Some("2.0e-16"), Some("0x1.0E-13#1"), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", Some("4.0e-16"), Some("0x2.0E-13#1"), ); test( "too_big", "0x4.0E+268435455#1", Some("too_big"), Some("0x4.0E+268435455#1"), ); test( "too_small", "0x1.0E-268435456#1", Some("too_small"), Some("0x1.0E-268435456#1"), ); test("too_small", "0x1.0E-268435456#2", None, None); test("-1.0", "-0x1.0#1", Some("1.0"), Some("0x1.0#1")); test("-2.0", "-0x2.0#1", Some("2.0"), Some("0x2.0#1")); test("-0.5", "-0x0.8#1", Some("0.5"), Some("0x0.8#1")); test( "-0.33333333333333331", "-0x0.55555555555554#53", Some("6.0e-17"), Some("0x4.0E-14#1"), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", Some("2.0e-16"), Some("0x1.0E-13#1"), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", Some("4.0e-16"), Some("0x2.0E-13#1"), ); test( "-too_big", "-0x4.0E+268435455#1", Some("too_big"), Some("0x4.0E+268435455#1"), ); test( "-too_small", "-0x1.0E-268435456#1", Some("too_small"), Some("0x1.0E-268435456#1"), ); test("-too_small", "-0x1.0E-268435456#2", None, None); } fn ulp_properties_helper(x: Float) { let ulp = x.ulp(); ulp.as_ref().map_or_else( || {}, |ulp| { assert!(ulp.is_valid()); assert!(*ulp > 0); assert!(ulp.is_power_of_2()); }, ); assert_eq!((-x).ulp().map(ComparableFloat), ulp.map(ComparableFloat)); } #[test] fn ulp_properties() { float_gen().test_properties(|x| { ulp_properties_helper(x); }); float_gen_var_12().test_properties(|x| { ulp_properties_helper(x); }); } #[test] fn test_increment() { let test = |s, s_hex, out: &str, out_hex: &str| { let mut x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); x.increment(); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test("1.0", "0x1.0#1", "2.0", "0x2.0#2"); test("2.0", "0x2.0#1", "4.0", "0x4.0#2"); test("0.5", "0x0.8#1", "1.0", "0x1.0#2"); test("1.0", "0x1.0#2", "1.5", "0x1.8#2"); test("2.0", "0x2.0#2", "3.0", "0x3.0#2"); test("0.5", "0x0.8#2", "0.8", "0x0.c#2"); test( "1.0", "0x1.0000000000000000000000000#100", "1.000000000000000000000000000002", "0x1.0000000000000000000000002#100", ); test( "0.33333333333333331", "0x0.55555555555554#53", "0.33333333333333337", "0x0.55555555555558#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730954", "0x1.6a09e667f3bce#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3.1415926535897936", "0x3.243f6a8885a32#53", ); test( "too_big", "0x4.0E+268435455#2", "too_big", "0x6.0E+268435455#2", ); test("too_big", "0x4.0E+268435455#1", "Infinity", "Infinity"); test( "too_small", "0x1.0E-268435456#1", "too_small", "0x2.0E-268435456#2", ); test( "too_small", "0x1.0E-268435456#2", "too_small", "0x1.8E-268435456#2", ); test("-1.0", "-0x1.0#1", "-0.0", "-0x0.0"); test("-2.0", "-0x2.0#1", "-0.0", "-0x0.0"); test("-0.5", "-0x0.8#1", "-0.0", "-0x0.0"); test("-1.0", "-0x1.0#2", "-0.5", "-0x0.8#1"); test("-2.0", "-0x2.0#2", "-1.0", "-0x1.0#1"); test("-0.5", "-0x0.8#2", "-0.2", "-0x0.4#1"); test( "-1.0", "-0x1.0000000000000000000000000#100", "-0.999999999999999999999999999998", "-0x0.ffffffffffffffffffffffffe#99", ); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-0.33333333333333326", "-0x0.55555555555550#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1.4142135623730949", "-0x1.6a09e667f3bcc#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3.1415926535897927", "-0x3.243f6a8885a2e#53", ); test( "-too_big", "-0x4.0E+268435455#2", "-too_big", "-0x2.0E+268435455#1", ); test("-too_big", "-0x4.0E+268435455#1", "-0.0", "-0x0.0"); test("-too_small", "-0x1.0E-268435456#1", "-0.0", "-0x0.0"); test("-too_small", "-0x1.0E-268435456#2", "-0.0", "-0x0.0"); } #[test] fn increment_fail() { assert_panic!({ let mut x = Float::NAN; x.increment(); }); assert_panic!({ let mut x = Float::INFINITY; x.increment(); }); assert_panic!({ let mut x = Float::NEGATIVE_INFINITY; x.increment(); }); assert_panic!({ let mut x = Float::ZERO; x.increment(); }); assert_panic!({ let mut x = Float::NEGATIVE_ZERO; x.increment(); }); } fn increment_properties_helper(mut x: Float, extreme: bool) { let old_x = x.clone(); x.increment(); let final_x = x.clone(); assert!(x.is_valid()); if !extreme { assert_eq!( Rational::exact_from(&old_x) + Rational::exact_from(old_x.ulp().unwrap()), Rational::exact_from(&x) ); } if x.is_normal() { assert_eq!(x.ulp(), old_x.ulp()); assert!(x.get_prec().unwrap().abs_diff(old_x.get_prec().unwrap()) <= 1); x.decrement(); assert_eq!(ComparableFloatRef(&x), ComparableFloatRef(&old_x)); } let mut x = -old_x; x.decrement(); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); } #[test] fn increment_properties() { float_gen_var_3().test_properties(|x| { increment_properties_helper(x, false); }); float_gen_var_13().test_properties(|x| { increment_properties_helper(x, true); }); primitive_float_gen_var_12::().test_properties(|x| { let next_x = x.next_higher(); if next_x.is_finite() && next_x != 0.0 && x.sci_exponent() == next_x.sci_exponent() { let mut big_x = Float::from_primitive_float_prec(x, alt_precision(x)).0; big_x.increment(); assert_eq!( ComparableFloat(big_x), ComparableFloat(Float::from_primitive_float_prec(next_x, alt_precision(next_x)).0) ); } }); } #[test] fn test_decrement() { let test = |s, s_hex, out: &str, out_hex: &str| { let mut x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); x.decrement(); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test("1.0", "0x1.0#1", "0.0", "0x0.0"); test("2.0", "0x2.0#1", "0.0", "0x0.0"); test("0.5", "0x0.8#1", "0.0", "0x0.0"); test("1.0", "0x1.0#2", "0.5", "0x0.8#1"); test("2.0", "0x2.0#2", "1.0", "0x1.0#1"); test("0.5", "0x0.8#2", "0.2", "0x0.4#1"); test( "1.0", "0x1.0000000000000000000000000#100", "0.999999999999999999999999999998", "0x0.ffffffffffffffffffffffffe#99", ); test( "0.33333333333333331", "0x0.55555555555554#53", "0.33333333333333326", "0x0.55555555555550#53", ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730949", "0x1.6a09e667f3bcc#53", ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "3.1415926535897927", "0x3.243f6a8885a2e#53", ); test( "too_big", "0x4.0E+268435455#2", "too_big", "0x2.0E+268435455#1", ); test("too_big", "0x4.0E+268435455#1", "0.0", "0x0.0"); test("too_small", "0x1.0E-268435456#1", "0.0", "0x0.0"); test("too_small", "0x1.0E-268435456#2", "0.0", "0x0.0"); test("-1.0", "-0x1.0#1", "-2.0", "-0x2.0#2"); test("-2.0", "-0x2.0#1", "-4.0", "-0x4.0#2"); test("-0.5", "-0x0.8#1", "-1.0", "-0x1.0#2"); test("-1.0", "-0x1.0#2", "-1.5", "-0x1.8#2"); test("-2.0", "-0x2.0#2", "-3.0", "-0x3.0#2"); test("-0.5", "-0x0.8#2", "-0.8", "-0x0.c#2"); test( "-1.0", "-0x1.0000000000000000000000000#100", "-1.000000000000000000000000000002", "-0x1.0000000000000000000000002#100", ); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-0.33333333333333337", "-0x0.55555555555558#53", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1.4142135623730954", "-0x1.6a09e667f3bce#53", ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-3.1415926535897936", "-0x3.243f6a8885a32#53", ); test( "-too_big", "-0x4.0E+268435455#2", "-too_big", "-0x6.0E+268435455#2", ); test("-too_big", "-0x4.0E+268435455#1", "-Infinity", "-Infinity"); test( "-too_small", "-0x1.0E-268435456#1", "-too_small", "-0x2.0E-268435456#2", ); test( "-too_small", "-0x1.0E-268435456#2", "-too_small", "-0x1.8E-268435456#2", ); } #[test] fn decrement_fail() { assert_panic!({ let mut x = Float::NAN; x.decrement(); }); assert_panic!({ let mut x = Float::INFINITY; x.decrement(); }); assert_panic!({ let mut x = Float::NEGATIVE_INFINITY; x.decrement(); }); assert_panic!({ let mut x = Float::ZERO; x.decrement(); }); assert_panic!({ let mut x = Float::NEGATIVE_ZERO; x.decrement(); }); } fn decrement_properties_helper(mut x: Float, extreme: bool) { let old_x = x.clone(); x.decrement(); let final_x = x.clone(); assert!(x.is_valid()); if !extreme { assert_eq!( Rational::exact_from(&old_x) - Rational::exact_from(old_x.ulp().unwrap()), Rational::exact_from(&x) ); } if x.is_normal() { assert_eq!(x.ulp(), old_x.ulp()); assert!(x.get_prec().unwrap().abs_diff(old_x.get_prec().unwrap()) <= 1); x.increment(); assert_eq!(ComparableFloatRef(&x), ComparableFloatRef(&old_x)); } let mut x = -old_x; x.increment(); assert_eq!(ComparableFloat(x), ComparableFloat(-final_x)); } #[test] fn decrement_properties() { float_gen_var_3().test_properties(|x| { decrement_properties_helper(x, false); }); float_gen_var_13().test_properties(|x| { decrement_properties_helper(x, true); }); primitive_float_gen_var_12::().test_properties(|x| { let next_x = x.next_lower(); if next_x.is_finite() && next_x != 0.0 && x.sci_exponent() == next_x.sci_exponent() { let mut big_x = Float::from_primitive_float_prec(x, alt_precision(x)).0; big_x.decrement(); assert_eq!( ComparableFloat(big_x), ComparableFloat(Float::from_primitive_float_prec(next_x, alt_precision(next_x)).0) ); } }); } ================================================ FILE: malachite-float/tests/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::common::{ORDERED_FLOAT_HEX_STRINGS, parse_hex_string}; use malachite_float::test_util::generators::{ float_gen, float_pair_gen, float_pair_gen_var_1, float_pair_gen_var_10, float_triple_gen, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; const fn encode(oo: Option) -> u8 { match oo { None => 9, Some(Less) => 0, Some(Equal) => 1, Some(Greater) => 2, } } #[rustfmt::skip] const MATRIX: [[u8; 21]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#1 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#2 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#100 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[test] fn test_partial_cmp() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { let y = parse_hex_string(sy); assert_eq!(encode(x.partial_cmp(&y)), e); assert_eq!( encode(rug::Float::exact_from(&x).partial_cmp(&rug::Float::exact_from(&y))), e ); } } } fn partial_cmp_properties_helper(x: Float, y: Float) { let ord = x.partial_cmp(&y); assert_eq!(y.partial_cmp(&x).map(Ordering::reverse), ord); assert_eq!(x == y, x.partial_cmp(&y) == Some(Equal)); assert_eq!((-&y).partial_cmp(&-&x), ord); assert_eq!( rug::Float::exact_from(&x).partial_cmp(&rug::Float::exact_from(&y)), ord ); if (!x.is_zero() || !y.is_zero()) && let Some(ord) = ord && ord != Equal { assert_eq!(ComparableFloat(x).cmp(&ComparableFloat(y)), ord); } } #[test] fn partial_cmp_properties() { float_pair_gen().test_properties(|(x, y)| { partial_cmp_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { partial_cmp_properties_helper(x, y); }); float_gen().test_properties(|x| { if !x.is_nan() { assert_eq!(x.partial_cmp(&x), Some(Equal)); assert!(x <= Float::INFINITY); assert!(x >= Float::NEGATIVE_INFINITY); } }); float_triple_gen().test_properties(|(x, y, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( Float::from(x).partial_cmp(&Float::from(y)), x.partial_cmp(&y) ); }); float_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Some(Rational::exact_from(&x).cmp(&Rational::exact_from(&y))), x.partial_cmp(&y) ); }); } fn read_hex_strings(strings: &[&str]) -> Vec { strings.iter().map(|s| parse_hex_string(s)).collect() } #[test] fn test_comparable_float_cmp() { let xs = read_hex_strings(&ORDERED_FLOAT_HEX_STRINGS); let ys = read_hex_strings(&ORDERED_FLOAT_HEX_STRINGS); for (i, x) in xs.iter().enumerate() { for (j, y) in ys.iter().enumerate() { assert_eq!( i.cmp(&j), ComparableFloat(x.clone()).cmp(&ComparableFloat(y.clone())) ); assert_eq!(i.cmp(&j), ComparableFloatRef(x).cmp(&ComparableFloatRef(y))); } } } #[test] fn comparable_float_cmp_properties() { float_pair_gen().test_properties(|(x, y)| { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); let ord = cx.cmp(&cy); assert_eq!(cy.cmp(&cx).reverse(), ord); assert_eq!(cx == cy, cx.cmp(&cy) == Equal); assert_eq!( ComparableFloat(x.clone()).cmp(&ComparableFloat(y.clone())), ord ); assert_eq!((ComparableFloat(-y)).cmp(&ComparableFloat(-x)), ord); }); float_gen().test_properties(|x| { let cx = ComparableFloatRef(&x); assert_eq!(cx.cmp(&cx), Equal); assert!(cx <= ComparableFloatRef(&Float::INFINITY)); assert!(cx >= ComparableFloatRef(&Float::NEGATIVE_INFINITY)); }); float_triple_gen().test_properties(|(x, y, z)| { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); let cz = ComparableFloatRef(&z); if cx < cy && cy < cz { assert!(cx < cz); } else if cx > cy && cy > cz { assert!(cx > cz); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( ComparableFloat(Float::from(x)).cmp(&ComparableFloat(Float::from(y))), NiceFloat(x).cmp(&NiceFloat(y)) ); }); } ================================================ FILE: malachite-float/tests/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NegativeInfinity}; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::common::{ORDERED_FLOAT_HEX_STRINGS, parse_hex_string}; use malachite_float::test_util::generators::{ float_gen, float_pair_gen, float_pair_gen_var_1, float_pair_gen_var_10, float_triple_gen, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; const fn encode(oo: Option) -> u8 { match oo { None => 9, Some(Less) => 0, Some(Equal) => 1, Some(Greater) => 2, } } #[rustfmt::skip] const MATRIX: [[u8; 21]; 21] = [ [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0], [0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0], [0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 9, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0], [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[test] fn test_partial_cmp_abs() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { let y = parse_hex_string(sy); assert_eq!(encode(x.partial_cmp_abs(&y)), e); assert_eq!( encode(rug::Float::exact_from(&x).cmp_abs(&rug::Float::exact_from(&y))), e ); } } } fn partial_cmp_abs_properties_helper(x: Float, y: Float) { let ord = x.partial_cmp_abs(&y); assert_eq!(y.partial_cmp_abs(&x).map(Ordering::reverse), ord); assert_eq!( (&x).abs() == (&y).abs(), x.partial_cmp_abs(&y) == Some(Equal) ); assert_eq!((-&x).partial_cmp_abs(&y), ord); assert_eq!(x.partial_cmp_abs(&-&y), ord); assert_eq!((-&x).partial_cmp_abs(&-&y), ord); assert_eq!( rug::Float::exact_from(&x).cmp_abs(&rug::Float::exact_from(&y)), ord ); if (!x.is_zero() || !y.is_zero()) && let Some(ord) = ord && ord != Equal { assert_eq!(ComparableFloat(x).cmp_abs(&ComparableFloat(y)), ord); } } #[test] fn partial_cmp_abs_properties() { float_pair_gen().test_properties(|(x, y)| { partial_cmp_abs_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { partial_cmp_abs_properties_helper(x, y); }); float_gen().test_properties(|x| { if !x.is_nan() { assert_eq!(x.partial_cmp_abs(&x), Some(Equal)); assert_eq!(x.partial_cmp_abs(&-&x), Some(Equal)); assert_eq!((-&x).partial_cmp_abs(&x), Some(Equal)); assert_eq!((-&x).partial_cmp_abs(&-&x), Some(Equal)); assert!(x.le_abs(&Float::INFINITY)); assert!(x.le_abs(&Float::NEGATIVE_INFINITY)); } }); float_triple_gen().test_properties(|(x, y, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( Float::from(x).partial_cmp_abs(&Float::from(y)), x.abs().partial_cmp(&y.abs()) ); }); float_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Some(Rational::exact_from(&x).cmp_abs(&Rational::exact_from(&y))), x.partial_cmp_abs(&y) ); }); } #[rustfmt::skip] const MATRIX_2: [[u8; 21]; 21] = [ [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0], [0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0], [0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0], [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0], [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[test] fn test_comparable_float_cmp_abs() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_2.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { assert_ne!(e, 9); let y = parse_hex_string(sy); assert_eq!( encode(Some( ComparableFloat(x.clone()).cmp_abs(&ComparableFloat(y.clone())) )), e ); assert_eq!( encode(Some( ComparableFloatRef(&x).cmp_abs(&ComparableFloatRef(&y)) )), e ); } } } fn comparable_float_cmp_abs_properties_helper(x: Float, y: Float) { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); let ord = cx.cmp_abs(&cy); assert_eq!(cy.cmp_abs(&cx).reverse(), ord); assert_eq!( ComparableFloat((&x).abs()) == ComparableFloat((&y).abs()), cx.cmp_abs(&cy) == Equal ); assert_eq!( ComparableFloat(x.clone()).cmp_abs(&ComparableFloat(y.clone())), ord ); assert_eq!( (ComparableFloatRef(&x)).cmp_abs(&ComparableFloatRef(&-&y)), ord ); assert_eq!( (ComparableFloatRef(&-&x)).cmp_abs(&ComparableFloatRef(&y)), ord ); assert_eq!((ComparableFloat(-x)).cmp_abs(&ComparableFloat(-y)), ord); } #[test] fn comparable_float_cmp_abs_properties() { float_pair_gen().test_properties(|(x, y)| { comparable_float_cmp_abs_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { comparable_float_cmp_abs_properties_helper(x, y); }); float_gen().test_properties(|x| { let cx = ComparableFloatRef(&x); assert_eq!(cx.cmp_abs(&cx), Equal); assert_eq!(cx.cmp_abs(&ComparableFloatRef(&-&x)), Equal); assert_eq!(ComparableFloatRef(&-&x).cmp_abs(&cx), Equal); assert_eq!( ComparableFloatRef(&-&x).cmp_abs(&ComparableFloatRef(&-&x)), Equal ); assert!(cx.le_abs(&ComparableFloatRef(&Float::INFINITY))); assert!(cx.le_abs(&ComparableFloatRef(&Float::NEGATIVE_INFINITY))); }); float_triple_gen().test_properties(|(x, y, z)| { let cx = ComparableFloatRef(&x); let cy = ComparableFloatRef(&y); let cz = ComparableFloatRef(&z); if cx.lt_abs(&cy) && cy.lt_abs(&cz) { assert!(cx.lt_abs(&cz)); } else if cx.gt_abs(&cy) && cy.gt_abs(&cz) { assert!(cx.gt_abs(&cz)); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( ComparableFloat(Float::from(x)).cmp_abs(&ComparableFloat(Float::from(y))), NiceFloat(x.abs()).cmp(&NiceFloat(y.abs())) ); }); } ================================================ FILE: malachite-float/tests/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::NaN; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::common::{ ORDERED_FLOAT_HEX_STRINGS, ORDERED_FLOAT_STRINGS, parse_hex_string, }; use malachite_float::test_util::generators::{ float_gen, float_pair_gen, float_pair_gen_var_1, float_pair_gen_var_10, float_triple_gen, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; #[rustfmt::skip] const MATRIX: [[u8; 21]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[test] fn test_eq() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { let y = parse_hex_string(sy); assert_eq!(u8::from(x == y), e); assert_eq!( u8::from(rug::Float::exact_from(&x) == rug::Float::exact_from(&y)), e ); } } } #[allow(clippy::needless_pass_by_value)] fn eq_properties_helper(x: Float, y: Float) { let e = x == y; assert_eq!(y == x, e); assert_eq!(rug::Float::exact_from(&x) == rug::Float::exact_from(&y), e); } #[allow(clippy::cmp_owned)] #[test] fn eq_properties() { float_pair_gen().test_properties(|(x, y)| { eq_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { eq_properties_helper(x, y); }); float_gen().test_properties(|x| { if !x.is_nan() { assert_eq!(x, x); } assert_ne!(x, Float::NAN); }); float_triple_gen().test_properties(|(x, y, z)| { if x == y && y == z { assert_eq!(x, z); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x) == Float::from(y), x == y); }); float_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x) == Rational::exact_from(&y), x == y); }); } fn read_hex_strings(strings: &[&str]) -> Vec { strings.iter().map(|s| parse_hex_string(s)).collect() } #[test] fn test_comparable_float_eq() { let xs = read_hex_strings(&ORDERED_FLOAT_HEX_STRINGS); let ys = read_hex_strings(&ORDERED_FLOAT_HEX_STRINGS); let xs_2: Vec = xs.iter().map(Float::to_string).collect(); assert_eq!(xs_2, ORDERED_FLOAT_STRINGS); for (i, x) in xs.iter().enumerate() { for (j, y) in ys.iter().enumerate() { assert_eq!( i == j, ComparableFloat(x.clone()) == ComparableFloat(y.clone()) ); assert_eq!(i == j, ComparableFloatRef(x) == ComparableFloatRef(y)); } } } #[allow(clippy::needless_pass_by_value)] fn comparable_float_eq_properties_helper(x: Float, y: Float) { let rx = ComparableFloatRef(&x); let ry = ComparableFloatRef(&y); let e = rx == ry; assert_eq!(ry == rx, e); let x = ComparableFloat(x.clone()); let y = ComparableFloat(y.clone()); assert_eq!(x == y, e); assert_eq!(y == x, e); if e && !x.is_nan() { assert_eq!(x, y); } } #[test] fn comparable_float_eq_properties() { float_pair_gen().test_properties(|(x, y)| { comparable_float_eq_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { comparable_float_eq_properties_helper(x, y); }); float_gen().test_properties(|x| { let x = ComparableFloat(x); assert_eq!(x, x); }); float_triple_gen().test_properties(|(x, y, z)| { let x = ComparableFloat(x); let y = ComparableFloat(y); let z = ComparableFloat(z); if x == y && y == z { assert_eq!(x, z); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( ComparableFloat(Float::from(x)) == ComparableFloat(Float::from(y)), NiceFloat(x) == NiceFloat(y) ); }); } ================================================ FILE: malachite-float/tests/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::NaN; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::primitive_float_pair_gen; use malachite_float::test_util::common::{ORDERED_FLOAT_HEX_STRINGS, parse_hex_string}; use malachite_float::test_util::generators::{ float_gen, float_pair_gen, float_pair_gen_var_1, float_pair_gen_var_10, float_triple_gen, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; #[rustfmt::skip] const MATRIX: [[u8; 21]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[test] fn test_eq_abs() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { let y = parse_hex_string(sy); assert_eq!(u8::from(x.eq_abs(&y)), e); } } } #[allow(clippy::needless_pass_by_value)] fn eq_abs_properties_helper(x: Float, y: Float) { let e = x.eq_abs(&y); assert_eq!((&x).abs() == (&y).abs(), e); assert_eq!(x.ne_abs(&y), !e); assert_eq!(y.eq_abs(&x), e); } #[allow(clippy::cmp_owned)] #[test] fn eq_abs_properties() { float_pair_gen().test_properties(|(x, y)| { eq_abs_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { eq_abs_properties_helper(x, y); }); float_gen().test_properties(|x| { if !x.is_nan() { assert!(x.eq_abs(&x)); } assert!(x.ne_abs(&Float::NAN)); }); float_triple_gen().test_properties(|(x, y, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x).eq_abs(&Float::from(y)), x.eq_abs(&y)); }); float_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Rational::exact_from(&x).eq_abs(&Rational::exact_from(&y)), x.eq_abs(&y) ); }); } #[rustfmt::skip] const ORDERED_FLOAT_MATRIX: [[u8; 21]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[test] fn test_comparable_float_eq_abs() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS .iter() .zip(ORDERED_FLOAT_MATRIX.iter()) { let x = parse_hex_string(sx); for (sy, &e) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(row.iter()) { let y = parse_hex_string(sy); assert_eq!( u8::from(ComparableFloat(x.clone()).eq_abs(&ComparableFloat(y.clone()))), e ); assert_eq!( u8::from(ComparableFloatRef(&x).eq_abs(&ComparableFloatRef(&y))), e ); } } } #[allow(clippy::needless_pass_by_value)] fn comparable_float_eq_abs_properties_helper(x: Float, y: Float) { let rx = ComparableFloatRef(&x); let ry = ComparableFloatRef(&y); let e = rx.eq_abs(&ry); assert_eq!( ComparableFloatRef(&(&x).abs()) == ComparableFloatRef(&(&y).abs()), e ); assert_eq!(rx.ne_abs(&ry), !e); assert_eq!(ry.eq_abs(&rx), e); let x = ComparableFloat(x.clone()); let y = ComparableFloat(y.clone()); assert_eq!( ComparableFloat((&x.0).abs()) == ComparableFloat((&y.0).abs()), e ); assert_eq!(x.eq_abs(&y), e); assert_eq!(x.ne_abs(&y), !e); assert_eq!(y.eq_abs(&x), e); if e && !x.is_nan() { assert!(x.eq_abs(&y)); } } #[test] fn comparable_float_eq_abs_properties() { float_pair_gen().test_properties(|(x, y)| { comparable_float_eq_abs_properties_helper(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { comparable_float_eq_abs_properties_helper(x, y); }); float_gen().test_properties(|x| { let x = ComparableFloat(x); assert!(x.eq_abs(&x)); }); float_triple_gen().test_properties(|(x, y, z)| { let x = ComparableFloat(x); let y = ComparableFloat(y); let z = ComparableFloat(z); if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); primitive_float_pair_gen::().test_properties(|(x, y)| { assert_eq!( ComparableFloat(Float::from(x)).eq_abs(&ComparableFloat(Float::from(y))), NiceFloat(x).eq_abs(&NiceFloat(y)) ); }); } ================================================ FILE: malachite-float/tests/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_var_1, float_integer_pair_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen}; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_eq_abs_integer() { let test = |s, s_hex, t, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Integer::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == (&v).abs(), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", true); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "-1", false); test("Infinity", "Infinity", "-1", false); test("-Infinity", "-Infinity", "-1", false); test("0.0", "0x0.0", "-1", false); test("-0.0", "-0x0.0", "-1", false); test("1.0", "0x1.0#1", "-1", true); test("2.0", "0x2.0#1", "-1", false); test("0.5", "0x0.8#1", "-1", false); test("0.33333333333333331", "0x0.55555555555554#53", "-1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1", false); test("3.0e120", "0x1.0E+100#1", "-1", false); test("4.0e-121", "0x1.0E-100#1", "-1", false); test("-1.0", "-0x1.0#1", "-1", true); test("-2.0", "-0x2.0#1", "-1", false); test("-0.5", "-0x0.8#1", "-1", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", false); test("-3.0e120", "-0x1.0E+100#1", "-1", false); test("-4.0e-121", "-0x1.0E-100#1", "-1", false); test("NaN", "NaN", "-100", false); test("Infinity", "Infinity", "-100", false); test("-Infinity", "-Infinity", "-100", false); test("0.0", "0x0.0", "-100", false); test("-0.0", "-0x0.0", "-100", false); test("1.0", "0x1.0#1", "-100", false); test("2.0", "0x2.0#1", "-100", false); test("0.5", "0x0.8#1", "-100", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-100", false); test("3.0e120", "0x1.0E+100#1", "-100", false); test("4.0e-121", "0x1.0E-100#1", "-100", false); test("-1.0", "-0x1.0#1", "-100", false); test("-2.0", "-0x2.0#1", "-100", false); test("-0.5", "-0x0.8#1", "-100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", false, ); test("-3.0e120", "-0x1.0E+100#1", "-100", false); test("-4.0e-121", "-0x1.0E-100#1", "-100", false); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned)] fn eq_abs_integer_properties_helper(x: Float, y: Integer) { let eq_abs = x.eq_abs(&y); assert_eq!((&x).abs() == (&y).abs(), eq_abs); assert_eq!(x.ne_abs(&y), !eq_abs); assert_eq!(y.eq_abs(&x), eq_abs); assert_eq!(x.eq_abs(&Float::exact_from(&y)), eq_abs); } #[allow(clippy::cmp_owned)] #[test] fn eq_abs_integer_properties() { float_integer_pair_gen().test_properties(|(x, y)| { eq_abs_integer_properties_helper(x, y); }); float_integer_pair_gen_var_2().test_properties(|(x, y)| { eq_abs_integer_properties_helper(x, y); }); integer_gen().test_properties(|x| { assert!(x.ne_abs(&Float::NAN)); assert!(x.ne_abs(&Float::INFINITY)); assert!(x.ne_abs(&Float::NEGATIVE_INFINITY)); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Float::exact_from(&y)), x.eq_abs(&y)); }); float_integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x).eq_abs(&y), x.eq_abs(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_var_1, float_natural_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_eq_abs_natural() { let test = |s, s_hex, t, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Natural::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == v, eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", true); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned)] fn eq_abs_natural_properties_helper(x: Float, y: Natural) { let eq = x.eq_abs(&y); assert_eq!((&x).abs() == y, eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.eq_abs(&Float::exact_from(&y)), eq); } #[allow(clippy::cmp_owned)] #[test] fn eq_abs_natural_properties() { float_natural_pair_gen().test_properties(|(x, y)| { eq_abs_natural_properties_helper(x, y); }); float_natural_pair_gen_var_2().test_properties(|(x, y)| { eq_abs_natural_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert!(x.ne_abs(&Float::NAN)); assert!(x.ne_abs(&Float::INFINITY)); assert!(x.ne_abs(&Float::NEGATIVE_INFINITY)); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Float::exact_from(&y)), x == y); }); float_natural_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x).eq_abs(&y), x.eq_abs(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::{ ORDERED_F32S, ORDERED_F64S, ORDERED_FLOAT_HEX_STRINGS, parse_hex_string, }; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, }; use std::cmp::Ordering::*; #[rustfmt::skip] const MATRIX_F32: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[rustfmt::skip] const MATRIX_F64: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[test] fn test_eq_abs_primitive_float() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F64.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F64S.iter().zip(row.iter()) { assert_eq!(u8::from(x.eq_abs(&y)), e); assert_eq!(u8::from(y.eq_abs(&x)), e); } } for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F32.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F32S.iter().zip(row.iter()) { assert_eq!(u8::from(x.eq_abs(&y)), e); assert_eq!(u8::from(y.eq_abs(&x)), e); } } } #[allow(clippy::needless_pass_by_value)] fn eq_abs_primitive_float_properties_helper_helper + PrimitiveFloat>(n: Float, f: T) where Float: TryFrom + EqAbs + PartialEq + PartialOrdAbs, { let eq = n.eq_abs(&f); assert_eq!((&n).abs() == f.abs(), eq); assert_eq!(n.ne_abs(&f), !eq); assert_eq!(f.eq_abs(&n), eq); assert_eq!(n.partial_cmp_abs(&f) == Some(Equal), eq); if f.is_finite() { assert_eq!(EqAbs::::eq_abs(&n, &Float::exact_from(f)), eq); } } fn eq_abs_primitive_float_properties_helper + PrimitiveFloat>() where Float: TryFrom + EqAbs + PartialEq + PartialOrdAbs, { float_primitive_float_pair_gen::().test_properties(|(n, f)| { eq_abs_primitive_float_properties_helper_helper(n, f); }); float_primitive_float_pair_gen_var_1::().test_properties(|(n, f)| { eq_abs_primitive_float_properties_helper_helper(n, f); }); } #[test] fn eq_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(eq_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, unsigned_gen, unsigned_pair_gen_var_27, }; use malachite_base::{apply_fn_to_signeds, apply_fn_to_unsigneds}; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_var_5, }; #[test] fn test_eq_abs_u32() { let test = |s, s_hex, v: u32, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == v, eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, true); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); } #[test] fn test_eq_abs_u64() { let test = |s, s_hex, v: u64, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == v, eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, true); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); } #[test] fn test_eq_abs_i32() { let test = |s, s_hex, v: i32, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, true); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); test("NaN", "NaN", -1, false); test("Infinity", "Infinity", -1, false); test("-Infinity", "-Infinity", -1, false); test("0.0", "0x0.0", -1, false); test("-0.0", "-0x0.0", -1, false); test("1.0", "0x1.0#1", -1, true); test("2.0", "0x2.0#1", -1, false); test("0.5", "0x0.8#1", -1, false); test("0.33333333333333331", "0x0.55555555555554#53", -1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -1, false); test("3.0e120", "0x1.0E+100#1", -1, false); test("4.0e-121", "0x1.0E-100#1", -1, false); test("-1.0", "-0x1.0#1", -1, true); test("-2.0", "-0x2.0#1", -1, false); test("-0.5", "-0x0.8#1", -1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", -1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, false); test("-3.0e120", "-0x1.0E+100#1", -1, false); test("-4.0e-121", "-0x1.0E-100#1", -1, false); test("NaN", "NaN", -100, false); test("Infinity", "Infinity", -100, false); test("-Infinity", "-Infinity", -100, false); test("0.0", "0x0.0", -100, false); test("-0.0", "-0x0.0", -100, false); test("1.0", "0x1.0#1", -100, false); test("2.0", "0x2.0#1", -100, false); test("0.5", "0x0.8#1", -100, false); test("0.33333333333333331", "0x0.55555555555554#53", -100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -100, false); test("3.0e120", "0x1.0E+100#1", -100, false); test("4.0e-121", "0x1.0E-100#1", -100, false); test("-1.0", "-0x1.0#1", -100, false); test("-2.0", "-0x2.0#1", -100, false); test("-0.5", "-0x0.8#1", -100, false); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, false); test("-3.0e120", "-0x1.0E+100#1", -100, false); test("-4.0e-121", "-0x1.0E-100#1", -100, false); } #[test] fn test_eq_abs_i64() { let test = |s, s_hex, v: i64, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, true); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); test("NaN", "NaN", -1, false); test("Infinity", "Infinity", -1, false); test("-Infinity", "-Infinity", -1, false); test("0.0", "0x0.0", -1, false); test("-0.0", "-0x0.0", -1, false); test("1.0", "0x1.0#1", -1, true); test("2.0", "0x2.0#1", -1, false); test("0.5", "0x0.8#1", -1, false); test("0.33333333333333331", "0x0.55555555555554#53", -1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -1, false); test("3.0e120", "0x1.0E+100#1", -1, false); test("4.0e-121", "0x1.0E-100#1", -1, false); test("-1.0", "-0x1.0#1", -1, true); test("-2.0", "-0x2.0#1", -1, false); test("-0.5", "-0x0.8#1", -1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", -1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, false); test("-3.0e120", "-0x1.0E+100#1", -1, false); test("-4.0e-121", "-0x1.0E-100#1", -1, false); test("NaN", "NaN", -100, false); test("Infinity", "Infinity", -100, false); test("-Infinity", "-Infinity", -100, false); test("0.0", "0x0.0", -100, false); test("-0.0", "-0x0.0", -100, false); test("1.0", "0x1.0#1", -100, false); test("2.0", "0x2.0#1", -100, false); test("0.5", "0x0.8#1", -100, false); test("0.33333333333333331", "0x0.55555555555554#53", -100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -100, false); test("3.0e120", "0x1.0E+100#1", -100, false); test("4.0e-121", "0x1.0E-100#1", -100, false); test("-1.0", "-0x1.0#1", -100, false); test("-2.0", "-0x2.0#1", -100, false); test("-0.5", "-0x0.8#1", -100, false); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, false); test("-3.0e120", "-0x1.0E+100#1", -100, false); test("-4.0e-121", "-0x1.0E-100#1", -100, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned, clippy::op_ref)] fn eq_abs_primitive_int_properties_helper_unsigned_helper + PrimitiveUnsigned>( n: Float, u: T, ) where Float: From + PartialEq + EqAbs, { let eq = n.eq_abs(&u); assert_eq!(EqAbs::::eq_abs(&n, &Float::from(u)), eq); assert_eq!((&n).abs() == u, eq); assert_eq!(n.ne_abs(&u), !eq); assert_eq!(u.eq_abs(&n), eq); assert_eq!(EqAbs::::eq_abs(&Float::from(u), &n), eq); } #[allow(clippy::cmp_owned, clippy::op_ref)] fn eq_abs_primitive_int_properties_helper_unsigned + PrimitiveUnsigned>() where Float: From + PartialEq + EqAbs, { float_unsigned_pair_gen::().test_properties(|(n, u)| { eq_abs_primitive_int_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_5::().test_properties(|(n, u)| { eq_abs_primitive_int_properties_helper_unsigned_helper(n, u); }); unsigned_gen::().test_properties(|x| { assert!(x.ne_abs(&Float::NAN)); assert!(x.ne_abs(&Float::INFINITY)); assert!(x.ne_abs(&Float::NEGATIVE_INFINITY)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Float::from(x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Float::from(y)), x == y); }); } #[allow(clippy::needless_pass_by_value)] fn eq_abs_primitive_int_properties_helper_signed_helper + PrimitiveSigned>( n: Float, i: T, ) where Float: From + PartialEq<::Output> + EqAbs, { let eq = n.eq_abs(&i); assert_eq!(EqAbs::::eq_abs(&n, &Float::from(i)), eq); assert_eq!((&n).abs() == i.unsigned_abs(), eq); assert_eq!(n.ne_abs(&i), !eq); assert_eq!(i.eq_abs(&n), eq); assert_eq!(EqAbs::::eq_abs(&Float::from(i), &n), eq); } fn eq_abs_primitive_int_properties_helper_signed + PrimitiveSigned>() where Float: From + PartialEq<::Output> + EqAbs, { float_signed_pair_gen::().test_properties(|(n, i)| { eq_abs_primitive_int_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_4::().test_properties(|(n, i)| { eq_abs_primitive_int_properties_helper_signed_helper(n, i); }); signed_gen::().test_properties(|x| { assert!(x.ne_abs(&Float::NAN)); assert!(x.ne_abs(&Float::INFINITY)); assert!(x.ne_abs(&Float::NEGATIVE_INFINITY)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Float::from(y)), x.eq_abs(&y)); }); } #[test] fn eq_abs_primitive_int_properties() { apply_fn_to_unsigneds!(eq_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(eq_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-float/tests/comparison/eq_abs_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_var_1, float_rational_pair_gen_var_2, }; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use std::str::FromStr; #[test] fn test_eq_abs_rational() { let test = |s, s_hex, t, eq: bool| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Rational::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!((&u).abs() == (&v).abs(), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!(v.eq_abs(&u), eq); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", true); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "1/2", false); test("Infinity", "Infinity", "1/2", false); test("-Infinity", "-Infinity", "1/2", false); test("0.0", "0x0.0", "1/2", false); test("-0.0", "-0x0.0", "1/2", false); test("1.0", "0x1.0#1", "1/2", false); test("2.0", "0x2.0#1", "1/2", false); test("0.5", "0x0.8#1", "1/2", true); test("0.33333333333333331", "0x0.55555555555554#53", "1/2", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/2", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1/2", false); test("3.0e120", "0x1.0E+100#1", "1/2", false); test("4.0e-121", "0x1.0E-100#1", "1/2", false); test("-1.0", "-0x1.0#1", "1/2", false); test("-2.0", "-0x2.0#1", "1/2", false); test("-0.5", "-0x0.8#1", "1/2", true); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/2", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/2", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/2", false); test("-3.0e120", "-0x1.0E+100#1", "1/2", false); test("-4.0e-121", "-0x1.0E-100#1", "1/2", false); test("NaN", "NaN", "1/3", false); test("Infinity", "Infinity", "1/3", false); test("-Infinity", "-Infinity", "1/3", false); test("0.0", "0x0.0", "1/3", false); test("-0.0", "-0x0.0", "1/3", false); test("1.0", "0x1.0#1", "1/3", false); test("2.0", "0x2.0#1", "1/3", false); test("0.5", "0x0.8#1", "1/3", false); test("0.33333333333333331", "0x0.55555555555554#53", "1/3", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/3", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", false); test("3.0e120", "0x1.0E+100#1", "1/3", false); test("4.0e-121", "0x1.0E-100#1", "1/3", false); test("-1.0", "-0x1.0#1", "1/3", false); test("-2.0", "-0x2.0#1", "1/3", false); test("-0.5", "-0x0.8#1", "1/3", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/3", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/3", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", false); test("-3.0e120", "-0x1.0E+100#1", "1/3", false); test("-4.0e-121", "-0x1.0E-100#1", "1/3", false); test("NaN", "NaN", "22/7", false); test("Infinity", "Infinity", "22/7", false); test("-Infinity", "-Infinity", "22/7", false); test("0.0", "0x0.0", "22/7", false); test("-0.0", "-0x0.0", "22/7", false); test("1.0", "0x1.0#1", "22/7", false); test("2.0", "0x2.0#1", "22/7", false); test("0.5", "0x0.8#1", "22/7", false); test( "0.33333333333333331", "0x0.55555555555554#53", "22/7", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "22/7", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "22/7", false); test("3.0e120", "0x1.0E+100#1", "22/7", false); test("4.0e-121", "0x1.0E-100#1", "22/7", false); test("-1.0", "-0x1.0#1", "22/7", false); test("-2.0", "-0x2.0#1", "22/7", false); test("-0.5", "-0x0.8#1", "22/7", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "22/7", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "22/7", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "22/7", false, ); test("-3.0e120", "-0x1.0E+100#1", "22/7", false); test("-4.0e-121", "-0x1.0E-100#1", "22/7", false); test("NaN", "NaN", "-1", false); test("Infinity", "Infinity", "-1", false); test("-Infinity", "-Infinity", "-1", false); test("0.0", "0x0.0", "-1", false); test("-0.0", "-0x0.0", "-1", false); test("1.0", "0x1.0#1", "-1", true); test("2.0", "0x2.0#1", "-1", false); test("0.5", "0x0.8#1", "-1", false); test("0.33333333333333331", "0x0.55555555555554#53", "-1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1", false); test("3.0e120", "0x1.0E+100#1", "-1", false); test("4.0e-121", "0x1.0E-100#1", "-1", false); test("-1.0", "-0x1.0#1", "-1", true); test("-2.0", "-0x2.0#1", "-1", false); test("-0.5", "-0x0.8#1", "-1", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", false); test("-3.0e120", "-0x1.0E+100#1", "-1", false); test("-4.0e-121", "-0x1.0E-100#1", "-1", false); test("NaN", "NaN", "-100", false); test("Infinity", "Infinity", "-100", false); test("-Infinity", "-Infinity", "-100", false); test("0.0", "0x0.0", "-100", false); test("-0.0", "-0x0.0", "-100", false); test("1.0", "0x1.0#1", "-100", false); test("2.0", "0x2.0#1", "-100", false); test("0.5", "0x0.8#1", "-100", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-100", false); test("3.0e120", "0x1.0E+100#1", "-100", false); test("4.0e-121", "0x1.0E-100#1", "-100", false); test("-1.0", "-0x1.0#1", "-100", false); test("-2.0", "-0x2.0#1", "-100", false); test("-0.5", "-0x0.8#1", "-100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", false, ); test("-3.0e120", "-0x1.0E+100#1", "-100", false); test("-4.0e-121", "-0x1.0E-100#1", "-100", false); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "-1/2", false); test("Infinity", "Infinity", "-1/2", false); test("-Infinity", "-Infinity", "-1/2", false); test("0.0", "0x0.0", "-1/2", false); test("-0.0", "-0x0.0", "-1/2", false); test("1.0", "0x1.0#1", "-1/2", false); test("2.0", "0x2.0#1", "-1/2", false); test("0.5", "0x0.8#1", "-1/2", true); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/2", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/2", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1/2", false); test("3.0e120", "0x1.0E+100#1", "-1/2", false); test("4.0e-121", "0x1.0E-100#1", "-1/2", false); test("-1.0", "-0x1.0#1", "-1/2", false); test("-2.0", "-0x2.0#1", "-1/2", false); test("-0.5", "-0x0.8#1", "-1/2", true); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/2", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/2", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/2", false, ); test("-3.0e120", "-0x1.0E+100#1", "-1/2", false); test("-4.0e-121", "-0x1.0E-100#1", "-1/2", false); test("NaN", "NaN", "-1/3", false); test("Infinity", "Infinity", "-1/3", false); test("-Infinity", "-Infinity", "-1/3", false); test("0.0", "0x0.0", "-1/3", false); test("-0.0", "-0x0.0", "-1/3", false); test("1.0", "0x1.0#1", "-1/3", false); test("2.0", "0x2.0#1", "-1/3", false); test("0.5", "0x0.8#1", "-1/3", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/3", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/3", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", false); test("3.0e120", "0x1.0E+100#1", "-1/3", false); test("4.0e-121", "0x1.0E-100#1", "-1/3", false); test("-1.0", "-0x1.0#1", "-1/3", false); test("-2.0", "-0x2.0#1", "-1/3", false); test("-0.5", "-0x0.8#1", "-1/3", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/3", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/3", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", false, ); test("-3.0e120", "-0x1.0E+100#1", "-1/3", false); test("-4.0e-121", "-0x1.0E-100#1", "-1/3", false); test("NaN", "NaN", "-22/7", false); test("Infinity", "Infinity", "-22/7", false); test("-Infinity", "-Infinity", "-22/7", false); test("0.0", "0x0.0", "-22/7", false); test("-0.0", "-0x0.0", "-22/7", false); test("1.0", "0x1.0#1", "-22/7", false); test("2.0", "0x2.0#1", "-22/7", false); test("0.5", "0x0.8#1", "-22/7", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-22/7", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-22/7", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-22/7", false); test("3.0e120", "0x1.0E+100#1", "-22/7", false); test("4.0e-121", "0x1.0E-100#1", "-22/7", false); test("-1.0", "-0x1.0#1", "-22/7", false); test("-2.0", "-0x2.0#1", "-22/7", false); test("-0.5", "-0x0.8#1", "-22/7", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-22/7", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-22/7", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-22/7", false, ); test("-3.0e120", "-0x1.0E+100#1", "-22/7", false); test("-4.0e-121", "-0x1.0E-100#1", "-22/7", false); } #[allow(clippy::needless_pass_by_value)] fn eq_abs_rational_properties_helper(x: Float, y: Rational) { let eq_abs = x.eq_abs(&y); assert_eq!((&x).abs() == (&y).abs(), eq_abs); assert_eq!(x.ne_abs(&y), !eq_abs); assert_eq!(y.eq_abs(&x), eq_abs); } #[test] fn eq_abs_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { eq_abs_rational_properties_helper(x, y); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { eq_abs_rational_properties_helper(x, y); }); rational_gen().test_properties(|x| { assert!(x.ne_abs(&Float::NAN)); assert!(x.ne_abs(&Float::INFINITY)); assert!(x.ne_abs(&Float::NEGATIVE_INFINITY)); }); float_rational_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x).eq_abs(&y), x.eq_abs(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::hash::hash; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; use malachite_float::{ComparableFloatRef, Float}; #[allow(clippy::needless_pass_by_value)] fn hash_properties_helper(x: Float) { assert_eq!( hash(&ComparableFloatRef(&x)), hash(&ComparableFloatRef(&x.clone())) ); } #[test] fn hash_properties() { float_gen().test_properties(|x| { hash_properties_helper(x); }); float_gen_var_12().test_properties(|x| { hash_properties_helper(x); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_integer_triple_gen, float_integer_integer_triple_gen, float_integer_pair_gen, float_integer_pair_gen_var_1, float_integer_pair_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen}; use malachite_q::Rational; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_integer() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Integer::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&(&v).abs()), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u) .abs() .partial_cmp(&rug::Integer::from(&v).abs()), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Greater)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Greater)); test("-2.0", "-0x2.0#1", "0", Some(Greater)); test("-0.5", "-0x0.8#1", "0", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Greater)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Greater)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Equal)); test("-2.0", "-0x2.0#1", "1", Some(Greater)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Greater)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); test("NaN", "NaN", "-1", None); test("Infinity", "Infinity", "-1", Some(Greater)); test("-Infinity", "-Infinity", "-1", Some(Greater)); test("0.0", "0x0.0", "-1", Some(Less)); test("-0.0", "-0x0.0", "-1", Some(Less)); test("1.0", "0x1.0#1", "-1", Some(Equal)); test("2.0", "0x2.0#1", "-1", Some(Greater)); test("0.5", "0x0.8#1", "-1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1", Some(Less)); test("-1.0", "-0x1.0#1", "-1", Some(Equal)); test("-2.0", "-0x2.0#1", "-1", Some(Greater)); test("-0.5", "-0x0.8#1", "-1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-1", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-1", Some(Less)); test("NaN", "NaN", "-100", None); test("Infinity", "Infinity", "-100", Some(Greater)); test("-Infinity", "-Infinity", "-100", Some(Greater)); test("0.0", "0x0.0", "-100", Some(Less)); test("-0.0", "-0x0.0", "-100", Some(Less)); test("1.0", "0x1.0#1", "-100", Some(Less)); test("2.0", "0x2.0#1", "-100", Some(Less)); test("0.5", "0x0.8#1", "-100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "-100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-100", Some(Less)); test("-1.0", "-0x1.0#1", "-100", Some(Less)); test("-2.0", "-0x2.0#1", "-100", Some(Less)); test("-0.5", "-0x0.8#1", "-100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-100", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-100", Some(Less)); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_integer_properties_helper(x: Float, y: Integer) { let cmp = x.partial_cmp_abs(&y); assert_eq!(x.partial_cmp_abs(&Float::exact_from(&y)), cmp); assert_eq!((&x).abs().partial_cmp(&(&y).abs()), cmp); assert_eq!( rug::Float::exact_from(&x) .abs() .partial_cmp(&rug::Integer::from(&y).abs()), cmp ); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_abs_integer_properties() { float_integer_pair_gen().test_properties(|(x, y)| { partial_cmp_abs_integer_properties_helper(x, y); }); float_integer_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_abs_integer_properties_helper(x, y); }); integer_gen().test_properties(|x| { assert!(x.partial_cmp_abs(&Float::NAN).is_none()); assert!(x.ge_abs(&Float::ZERO)); assert!(x.ge_abs(&Float::NEGATIVE_ZERO)); assert!(x.lt_abs(&Float::INFINITY)); assert!(x.lt_abs(&Float::NEGATIVE_INFINITY)); }); float_float_integer_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); float_integer_integer_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!( Float::exact_from(&x).partial_cmp_abs(&y), x.partial_cmp_abs(&y) ); assert_eq!( x.partial_cmp_abs(&Float::exact_from(&y)), x.partial_cmp_abs(&y) ); }); float_integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Rational::exact_from(&x).partial_cmp_abs(&y), x.partial_cmp_abs(&y) ); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_natural_triple_gen, float_natural_natural_triple_gen, float_natural_pair_gen, float_natural_pair_gen_var_1, float_natural_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use malachite_q::Rational; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_natural() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&v), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u) .abs() .partial_cmp(&rug::Integer::from(&v)), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Greater)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Greater)); test("-2.0", "-0x2.0#1", "0", Some(Greater)); test("-0.5", "-0x0.8#1", "0", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Greater)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Greater)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Equal)); test("-2.0", "-0x2.0#1", "1", Some(Greater)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Greater)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_natural_properties_helper(x: Float, y: Natural) { let cmp = x.partial_cmp_abs(&y); assert_eq!(x.partial_cmp_abs(&Float::exact_from(&y)), cmp); assert_eq!((&x).abs().partial_cmp(&y), cmp); assert_eq!( rug::Float::exact_from(&x) .abs() .partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_abs_natural_properties() { float_natural_pair_gen().test_properties(|(x, y)| { partial_cmp_abs_natural_properties_helper(x, y); }); float_natural_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_abs_natural_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert!(x.partial_cmp_abs(&Float::NAN).is_none()); assert!(x.ge_abs(&Float::ZERO)); assert!(x.ge_abs(&Float::NEGATIVE_ZERO)); assert!(x.lt_abs(&Float::INFINITY)); assert!(x.lt_abs(&Float::NEGATIVE_INFINITY)); }); float_float_natural_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); float_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x < z); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x).partial_cmp_abs(&y), x.partial_cmp(&y)); assert_eq!(x.partial_cmp_abs(&Float::exact_from(&y)), x.partial_cmp(&y)); }); float_natural_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Rational::exact_from(&x).partial_cmp_abs(&y), x.partial_cmp_abs(&y) ); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{primitive_float_gen, primitive_float_gen_var_11}; use malachite_float::Float; use malachite_float::test_util::common::{ ORDERED_F32S, ORDERED_F64S, ORDERED_FLOAT_HEX_STRINGS, parse_hex_string, }; use malachite_float::test_util::generators::{ float_float_primitive_float_triple_gen, float_gen, float_gen_var_2, float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, float_primitive_float_primitive_float_triple_gen, }; use std::cmp::Ordering::{self, *}; const fn encode(oo: Option) -> u8 { match oo { None => 9, Some(Less) => 0, Some(Equal) => 1, Some(Greater) => 2, } } #[rustfmt::skip] const MATRIX_F32: [[u8; 17]; 21] = [ [1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], [0, 0, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 0], [0, 0, 1, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [0, 0, 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 2, 9, 2, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 2, 9, 2, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 0, 0, 0], [0, 0, 1, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [0, 0, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 0], [1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[rustfmt::skip] const MATRIX_F64: [[u8; 17]; 21] = [ [1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], [0, 1, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0], [0, 0, 1, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [0, 0, 0, 1, 2, 2, 2, 2, 9, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 1, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 1, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 1, 2, 2, 2, 2, 9, 2, 2, 2, 2, 1, 0, 0, 0], [0, 0, 1, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [0, 1, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0], [1, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[test] fn test_partial_cmp_abs_primitive_float() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F64.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F64S.iter().zip(row.iter()) { assert_eq!(encode(x.partial_cmp_abs(&y)), e); assert_eq!(encode(y.partial_cmp_abs(&x).map(Ordering::reverse)), e); } } for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F32.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F32S.iter().zip(row.iter()) { assert_eq!(encode(x.partial_cmp_abs(&y)), e); assert_eq!(encode(y.partial_cmp_abs(&x).map(Ordering::reverse)), e); } } } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_primitive_float_properties_helper_helper< T: PartialOrd + PartialOrdAbs + PrimitiveFloat, >( n: Float, u: T, ) where Float: TryFrom + PartialOrd + PartialOrdAbs, { let cmp = n.partial_cmp_abs(&u); assert_eq!((&n).abs().partial_cmp(&u.abs()), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&n), cmp_rev); assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &Float::exact_from(u)), cmp ); } fn partial_cmp_abs_primitive_float_properties_helper< T: PartialOrd + PartialOrdAbs + PrimitiveFloat, >() where Float: TryFrom + PartialOrd + PartialOrdAbs, { float_primitive_float_pair_gen::().test_properties(|(n, u)| { partial_cmp_abs_primitive_float_properties_helper_helper(n, u); }); float_primitive_float_pair_gen_var_1::().test_properties(|(n, u)| { partial_cmp_abs_primitive_float_properties_helper_helper(n, u); }); float_float_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Less)); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Greater) ); } }); float_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(PartialOrdAbs::::lt_abs(&u, &v)); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(PartialOrdAbs::::gt_abs(&u, &v)); } }); float_gen().test_properties(|x| { assert!(!(x.lt_abs(&T::NAN))); assert!(!(x.gt_abs(&T::NAN))); }); float_gen_var_2().test_properties(|x| { assert!(x.le_abs(&T::NEGATIVE_INFINITY)); assert!(x.le_abs(&T::INFINITY)); }); primitive_float_gen::().test_properties(|x| { assert!(!(x.lt_abs(&Float::NAN))); assert!(!(x.gt_abs(&Float::NAN))); }); primitive_float_gen_var_11::().test_properties(|x| { assert!(x.le_abs(&Float::NEGATIVE_INFINITY)); assert!(x.le_abs(&Float::INFINITY)); }); } #[test] fn partial_cmp_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, unsigned_gen, unsigned_pair_gen_var_27, }; use malachite_base::{apply_fn_to_signeds, apply_fn_to_unsigneds}; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_signed_triple_gen, float_float_unsigned_triple_gen, float_signed_pair_gen, float_signed_pair_gen_var_4, float_signed_signed_triple_gen, float_unsigned_pair_gen, float_unsigned_pair_gen_var_5, float_unsigned_unsigned_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; #[test] fn test_partial_cmp_abs_u32() { let test = |s, s_hex, v: u32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&v), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!(rug::Float::exact_from(&u).abs().partial_cmp(&v), out); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Greater)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Greater)); test("-2.0", "-0x2.0#1", 0, Some(Greater)); test("-0.5", "-0x0.8#1", 0, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Greater)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Greater)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Equal)); test("-2.0", "-0x2.0#1", 1, Some(Greater)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Greater)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); } #[test] fn test_partial_cmp_abs_u64() { let test = |s, s_hex, v: u64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&v), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!(rug::Float::exact_from(&u).abs().partial_cmp(&v), out); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Greater)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Greater)); test("-2.0", "-0x2.0#1", 0, Some(Greater)); test("-0.5", "-0x0.8#1", 0, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Greater)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Greater)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Equal)); test("-2.0", "-0x2.0#1", 1, Some(Greater)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Greater)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); } #[test] fn test_partial_cmp_abs_i32() { let test = |s, s_hex, v: i32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&v.unsigned_abs()), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u) .abs() .partial_cmp(&v.unsigned_abs()), out ); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Greater)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Greater)); test("-2.0", "-0x2.0#1", 0, Some(Greater)); test("-0.5", "-0x0.8#1", 0, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Greater)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Greater)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Equal)); test("-2.0", "-0x2.0#1", 1, Some(Greater)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Greater)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); test("NaN", "NaN", -1, None); test("Infinity", "Infinity", -1, Some(Greater)); test("-Infinity", "-Infinity", -1, Some(Greater)); test("0.0", "0x0.0", -1, Some(Less)); test("-0.0", "-0x0.0", -1, Some(Less)); test("1.0", "0x1.0#1", -1, Some(Equal)); test("2.0", "0x2.0#1", -1, Some(Greater)); test("0.5", "0x0.8#1", -1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", -1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -1, Some(Less)); test("-1.0", "-0x1.0#1", -1, Some(Equal)); test("-2.0", "-0x2.0#1", -1, Some(Greater)); test("-0.5", "-0x0.8#1", -1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", -1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", -1, Some(Less)); test("NaN", "NaN", -100, None); test("Infinity", "Infinity", -100, Some(Greater)); test("-Infinity", "-Infinity", -100, Some(Greater)); test("0.0", "0x0.0", -100, Some(Less)); test("-0.0", "-0x0.0", -100, Some(Less)); test("1.0", "0x1.0#1", -100, Some(Less)); test("2.0", "0x2.0#1", -100, Some(Less)); test("0.5", "0x0.8#1", -100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", -100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", -100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -100, Some(Less)); test("-1.0", "-0x1.0#1", -100, Some(Less)); test("-2.0", "-0x2.0#1", -100, Some(Less)); test("-0.5", "-0x0.8#1", -100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", -100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", -100, Some(Less)); } #[test] fn test_partial_cmp_abs_i64() { let test = |s, s_hex, v: i64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&v.unsigned_abs()), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u) .abs() .partial_cmp(&v.unsigned_abs()), out ); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Greater)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Greater)); test("-2.0", "-0x2.0#1", 0, Some(Greater)); test("-0.5", "-0x0.8#1", 0, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Greater)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Greater)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Equal)); test("-2.0", "-0x2.0#1", 1, Some(Greater)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Greater)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); test("NaN", "NaN", -1, None); test("Infinity", "Infinity", -1, Some(Greater)); test("-Infinity", "-Infinity", -1, Some(Greater)); test("0.0", "0x0.0", -1, Some(Less)); test("-0.0", "-0x0.0", -1, Some(Less)); test("1.0", "0x1.0#1", -1, Some(Equal)); test("2.0", "0x2.0#1", -1, Some(Greater)); test("0.5", "0x0.8#1", -1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", -1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -1, Some(Less)); test("-1.0", "-0x1.0#1", -1, Some(Equal)); test("-2.0", "-0x2.0#1", -1, Some(Greater)); test("-0.5", "-0x0.8#1", -1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", -1, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", -1, Some(Less)); test("NaN", "NaN", -100, None); test("Infinity", "Infinity", -100, Some(Greater)); test("-Infinity", "-Infinity", -100, Some(Greater)); test("0.0", "0x0.0", -100, Some(Less)); test("-0.0", "-0x0.0", -100, Some(Less)); test("1.0", "0x1.0#1", -100, Some(Less)); test("2.0", "0x2.0#1", -100, Some(Less)); test("0.5", "0x0.8#1", -100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", -100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", -100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -100, Some(Less)); test("-1.0", "-0x1.0#1", -100, Some(Less)); test("-2.0", "-0x2.0#1", -100, Some(Less)); test("-0.5", "-0x0.8#1", -100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", -100, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", -100, Some(Less)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_primitive_int_properties_helper_unsigned_helper< T: PartialOrdAbs + PrimitiveUnsigned, >( n: Float, u: T, ) where Float: From + PartialOrdAbs + PartialOrd, rug::Float: PartialOrd, { let cmp = n.partial_cmp_abs(&u); assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &Float::from(u)), cmp ); assert_eq!((&n).abs().partial_cmp(&u), cmp); assert_eq!(rug::Float::exact_from(&n).abs().partial_cmp(&u), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&n), cmp_rev); assert_eq!( PartialOrdAbs::::partial_cmp_abs(&Float::from(u), &n), cmp_rev ); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_abs_primitive_int_properties_helper_unsigned< T: PartialOrdAbs + PrimitiveUnsigned, >() where Float: From + PartialOrdAbs + PartialOrd, rug::Float: PartialOrd, { float_unsigned_pair_gen::().test_properties(|(n, u)| { partial_cmp_abs_primitive_int_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_5::().test_properties(|(n, u)| { partial_cmp_abs_primitive_int_properties_helper_unsigned_helper(n, u); }); unsigned_gen::().test_properties(|x| { assert!(x.partial_cmp_abs(&Float::NAN).is_none()); assert!(x.ge_abs(&Float::ZERO)); assert!(x.ge_abs(&Float::NEGATIVE_ZERO)); assert!(x.lt_abs(&Float::INFINITY)); assert!(x.lt_abs(&Float::NEGATIVE_INFINITY)); }); float_float_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Less)); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Greater) ); } }); float_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u < v); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u > v); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Float::from(x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Float::from(y)), Some(x.cmp(&y))); }); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_primitive_int_properties_helper_signed_helper< T: PartialOrdAbs + PrimitiveSigned, >( n: Float, i: T, ) where Float: From + PartialOrdAbs + PartialOrd<::Output>, rug::Float: PartialOrd<::Output>, { let cmp = n.partial_cmp_abs(&i); assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &Float::from(i)), cmp ); assert_eq!((&n).abs().partial_cmp(&i.unsigned_abs()), cmp); assert_eq!( rug::Float::exact_from(&n) .abs() .partial_cmp(&i.unsigned_abs()), cmp ); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp_abs(&n), cmp_rev); assert_eq!( PartialOrdAbs::::partial_cmp_abs(&Float::from(i), &n), cmp_rev ); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_abs_primitive_int_properties_helper_signed< T: PartialOrdAbs + PrimitiveSigned, >() where Float: From + PartialOrdAbs + PartialOrd<::Output>, rug::Float: PartialOrd<::Output>, { float_signed_pair_gen::().test_properties(|(n, i)| { partial_cmp_abs_primitive_int_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_4::().test_properties(|(n, i)| { partial_cmp_abs_primitive_int_properties_helper_signed_helper(n, i); }); signed_gen::().test_properties(|x| { assert!(x.partial_cmp_abs(&Float::NAN).is_none()); assert!(x.ge_abs(&Float::ZERO)); assert!(x.ge_abs(&Float::NEGATIVE_ZERO)); assert!(x.lt_abs(&Float::INFINITY)); assert!(x.lt_abs(&Float::NEGATIVE_INFINITY)); }); float_float_signed_triple_gen::().test_properties(|(n, m, i)| { if n.lt_abs(&i) && i.lt_abs(&m) { assert_eq!(PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Less)); } else if n.gt_abs(&i) && i.gt_abs(&m) { assert_eq!( PartialOrdAbs::::partial_cmp_abs(&n, &m), Some(Greater) ); } }); float_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i.lt_abs(&n) && n.lt_abs(&j) { assert!(i.lt_abs(&j)); } else if i.gt_abs(&n) && n.gt_abs(&j) { assert!(i.gt_abs(&j)); } }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x).partial_cmp_abs(&y), x.partial_cmp_abs(&y)); assert_eq!(x.partial_cmp_abs(&Float::from(y)), x.partial_cmp_abs(&y)); }); } #[test] fn partial_cmp_abs_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_abs_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeZero, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_rational_triple_gen, float_rational_pair_gen, float_rational_pair_gen_var_1, float_rational_pair_gen_var_2, float_rational_rational_triple_gen, }; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_rational() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Rational::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp(&(&v).abs()), out); assert_eq!(v.partial_cmp_abs(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u) .abs() .partial_cmp(&rug::Rational::from(&v).abs()), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Greater)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Greater)); test("-2.0", "-0x2.0#1", "0", Some(Greater)); test("-0.5", "-0x0.8#1", "0", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Greater)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Greater)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Equal)); test("-2.0", "-0x2.0#1", "1", Some(Greater)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Greater)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); test("NaN", "NaN", "1/2", None); test("Infinity", "Infinity", "1/2", Some(Greater)); test("-Infinity", "-Infinity", "1/2", Some(Greater)); test("0.0", "0x0.0", "1/2", Some(Less)); test("-0.0", "-0x0.0", "1/2", Some(Less)); test("1.0", "0x1.0#1", "1/2", Some(Greater)); test("2.0", "0x2.0#1", "1/2", Some(Greater)); test("0.5", "0x0.8#1", "1/2", Some(Equal)); test( "0.33333333333333331", "0x0.55555555555554#53", "1/2", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/2", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/2", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1/2", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1/2", Some(Less)); test("-1.0", "-0x1.0#1", "1/2", Some(Greater)); test("-2.0", "-0x2.0#1", "1/2", Some(Greater)); test("-0.5", "-0x0.8#1", "1/2", Some(Equal)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/2", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/2", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/2", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "1/2", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "1/2", Some(Less)); test("NaN", "NaN", "1/3", None); test("Infinity", "Infinity", "1/3", Some(Greater)); test("-Infinity", "-Infinity", "1/3", Some(Greater)); test("0.0", "0x0.0", "1/3", Some(Less)); test("-0.0", "-0x0.0", "1/3", Some(Less)); test("1.0", "0x1.0#1", "1/3", Some(Greater)); test("2.0", "0x2.0#1", "1/3", Some(Greater)); test("0.5", "0x0.8#1", "1/3", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "1/3", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/3", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1/3", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1/3", Some(Less)); test("-1.0", "-0x1.0#1", "1/3", Some(Greater)); test("-2.0", "-0x2.0#1", "1/3", Some(Greater)); test("-0.5", "-0x0.8#1", "1/3", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/3", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/3", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "1/3", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "1/3", Some(Less)); test("NaN", "NaN", "22/7", None); test("Infinity", "Infinity", "22/7", Some(Greater)); test("-Infinity", "-Infinity", "22/7", Some(Greater)); test("0.0", "0x0.0", "22/7", Some(Less)); test("-0.0", "-0x0.0", "22/7", Some(Less)); test("1.0", "0x1.0#1", "22/7", Some(Less)); test("2.0", "0x2.0#1", "22/7", Some(Less)); test("0.5", "0x0.8#1", "22/7", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "22/7", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "22/7", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "22/7", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "22/7", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "22/7", Some(Less)); test("-1.0", "-0x1.0#1", "22/7", Some(Less)); test("-2.0", "-0x2.0#1", "22/7", Some(Less)); test("-0.5", "-0x0.8#1", "22/7", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "22/7", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "22/7", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "22/7", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "22/7", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "22/7", Some(Less)); test("NaN", "NaN", "-1", None); test("Infinity", "Infinity", "-1", Some(Greater)); test("-Infinity", "-Infinity", "-1", Some(Greater)); test("0.0", "0x0.0", "-1", Some(Less)); test("-0.0", "-0x0.0", "-1", Some(Less)); test("1.0", "0x1.0#1", "-1", Some(Equal)); test("2.0", "0x2.0#1", "-1", Some(Greater)); test("0.5", "0x0.8#1", "-1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1", Some(Less)); test("-1.0", "-0x1.0#1", "-1", Some(Equal)); test("-2.0", "-0x2.0#1", "-1", Some(Greater)); test("-0.5", "-0x0.8#1", "-1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-1", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-1", Some(Less)); test("NaN", "NaN", "-100", None); test("Infinity", "Infinity", "-100", Some(Greater)); test("-Infinity", "-Infinity", "-100", Some(Greater)); test("0.0", "0x0.0", "-100", Some(Less)); test("-0.0", "-0x0.0", "-100", Some(Less)); test("1.0", "0x1.0#1", "-100", Some(Less)); test("2.0", "0x2.0#1", "-100", Some(Less)); test("0.5", "0x0.8#1", "-100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "-100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-100", Some(Less)); test("-1.0", "-0x1.0#1", "-100", Some(Less)); test("-2.0", "-0x2.0#1", "-100", Some(Less)); test("-0.5", "-0x0.8#1", "-100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-100", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-100", Some(Less)); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Greater)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); test("NaN", "NaN", "-1/2", None); test("Infinity", "Infinity", "-1/2", Some(Greater)); test("-Infinity", "-Infinity", "-1/2", Some(Greater)); test("0.0", "0x0.0", "-1/2", Some(Less)); test("-0.0", "-0x0.0", "-1/2", Some(Less)); test("1.0", "0x1.0#1", "-1/2", Some(Greater)); test("2.0", "0x2.0#1", "-1/2", Some(Greater)); test("0.5", "0x0.8#1", "-1/2", Some(Equal)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/2", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/2", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/2", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1/2", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1/2", Some(Less)); test("-1.0", "-0x1.0#1", "-1/2", Some(Greater)); test("-2.0", "-0x2.0#1", "-1/2", Some(Greater)); test("-0.5", "-0x0.8#1", "-1/2", Some(Equal)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/2", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/2", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/2", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-1/2", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-1/2", Some(Less)); test("NaN", "NaN", "-1/3", None); test("Infinity", "Infinity", "-1/3", Some(Greater)); test("-Infinity", "-Infinity", "-1/3", Some(Greater)); test("0.0", "0x0.0", "-1/3", Some(Less)); test("-0.0", "-0x0.0", "-1/3", Some(Less)); test("1.0", "0x1.0#1", "-1/3", Some(Greater)); test("2.0", "0x2.0#1", "-1/3", Some(Greater)); test("0.5", "0x0.8#1", "-1/3", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/3", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/3", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1/3", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1/3", Some(Less)); test("-1.0", "-0x1.0#1", "-1/3", Some(Greater)); test("-2.0", "-0x2.0#1", "-1/3", Some(Greater)); test("-0.5", "-0x0.8#1", "-1/3", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/3", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/3", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-1/3", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-1/3", Some(Less)); test("NaN", "NaN", "-22/7", None); test("Infinity", "Infinity", "-22/7", Some(Greater)); test("-Infinity", "-Infinity", "-22/7", Some(Greater)); test("0.0", "0x0.0", "-22/7", Some(Less)); test("-0.0", "-0x0.0", "-22/7", Some(Less)); test("1.0", "0x1.0#1", "-22/7", Some(Less)); test("2.0", "0x2.0#1", "-22/7", Some(Less)); test("0.5", "0x0.8#1", "-22/7", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "-22/7", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-22/7", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-22/7", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "-22/7", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-22/7", Some(Less)); test("-1.0", "-0x1.0#1", "-22/7", Some(Less)); test("-2.0", "-0x2.0#1", "-22/7", Some(Less)); test("-0.5", "-0x0.8#1", "-22/7", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-22/7", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-22/7", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-22/7", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-22/7", Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", "-22/7", Some(Less)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_abs_rational_properties_helper(x: Float, y: Rational) { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp(&(&y).abs()), cmp); assert_eq!( rug::Float::exact_from(&x) .abs() .partial_cmp(&rug::Rational::from(&y).abs()), cmp ); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_abs_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { partial_cmp_abs_rational_properties_helper(x, y); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_abs_rational_properties_helper(x, y); }); rational_gen().test_properties(|x| { assert!(x.partial_cmp_abs(&Float::NAN).is_none()); assert!(x.ge_abs(&Float::ZERO)); assert!(x.ge_abs(&Float::NEGATIVE_ZERO)); assert!(x.lt_abs(&Float::INFINITY)); assert!(x.lt_abs(&Float::NEGATIVE_INFINITY)); }); float_float_rational_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); float_rational_rational_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); float_rational_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Rational::exact_from(&x).partial_cmp_abs(&y), x.partial_cmp_abs(&y) ); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_integer_triple_gen, float_integer_integer_triple_gen, float_integer_pair_gen, float_integer_pair_gen_var_1, float_integer_pair_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_integer() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Integer::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u).partial_cmp(&rug::Integer::from(&v)), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Less)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Less)); test("-2.0", "-0x2.0#1", "0", Some(Less)); test("-0.5", "-0x0.8#1", "0", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Less)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Less)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Less)); test("-2.0", "-0x2.0#1", "1", Some(Less)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Less)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); test("NaN", "NaN", "-1", None); test("Infinity", "Infinity", "-1", Some(Greater)); test("-Infinity", "-Infinity", "-1", Some(Less)); test("0.0", "0x0.0", "-1", Some(Greater)); test("-0.0", "-0x0.0", "-1", Some(Greater)); test("1.0", "0x1.0#1", "-1", Some(Greater)); test("2.0", "0x2.0#1", "-1", Some(Greater)); test("0.5", "0x0.8#1", "-1", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1", Some(Greater)); test("-1.0", "-0x1.0#1", "-1", Some(Equal)); test("-2.0", "-0x2.0#1", "-1", Some(Less)); test("-0.5", "-0x0.8#1", "-1", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-1", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-1", Some(Greater)); test("NaN", "NaN", "-100", None); test("Infinity", "Infinity", "-100", Some(Greater)); test("-Infinity", "-Infinity", "-100", Some(Less)); test("0.0", "0x0.0", "-100", Some(Greater)); test("-0.0", "-0x0.0", "-100", Some(Greater)); test("1.0", "0x1.0#1", "-100", Some(Greater)); test("2.0", "0x2.0#1", "-100", Some(Greater)); test("0.5", "0x0.8#1", "-100", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-100", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-100", Some(Greater)); test("-1.0", "-0x1.0#1", "-100", Some(Greater)); test("-2.0", "-0x2.0#1", "-100", Some(Greater)); test("-0.5", "-0x0.8#1", "-100", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-100", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-100", Some(Greater)); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Greater)); test("-0.0", "-0x0.0", s, Some(Greater)); test("1.0", "0x1.0#1", s, Some(Greater)); test("2.0", "0x2.0#1", s, Some(Greater)); test("0.5", "0x0.8#1", s, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", s, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", s, Some(Greater)); test("-1.0", "-0x1.0#1", s, Some(Greater)); test("-2.0", "-0x2.0#1", s, Some(Greater)); test("-0.5", "-0x0.8#1", s, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Greater)); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Greater)); test("-0.0", "-0x0.0", s, Some(Greater)); test("1.0", "0x1.0#1", s, Some(Greater)); test("2.0", "0x2.0#1", s, Some(Greater)); test("0.5", "0x0.8#1", s, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", s, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", s, Some(Greater)); test("-1.0", "-0x1.0#1", s, Some(Greater)); test("-2.0", "-0x2.0#1", s, Some(Greater)); test("-0.5", "-0x0.8#1", s, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Greater)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_integer_properties_helper(x: Float, y: Integer) { let cmp = x.partial_cmp(&y); assert_eq!(x.partial_cmp(&Float::exact_from(&y)), cmp); assert_eq!( rug::Float::exact_from(&x).partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_integer_properties() { float_integer_pair_gen().test_properties(|(x, y)| { partial_cmp_integer_properties_helper(x, y); }); float_integer_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_integer_properties_helper(x, y); }); float_float_integer_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); float_integer_integer_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Float::exact_from(&y)), Some(x.cmp(&y))); }); float_integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x).partial_cmp(&y), x.partial_cmp(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_natural_triple_gen, float_natural_natural_triple_gen, float_natural_pair_gen, float_natural_pair_gen_var_1, float_natural_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen; use malachite_q::Rational; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_natural() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u).partial_cmp(&rug::Integer::from(&v)), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Less)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Less)); test("-2.0", "-0x2.0#1", "0", Some(Less)); test("-0.5", "-0x0.8#1", "0", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Less)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Less)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Less)); test("-2.0", "-0x2.0#1", "1", Some(Less)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Less)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_natural_properties_helper(x: Float, y: Natural) { let cmp = x.partial_cmp(&y); assert_eq!(x.partial_cmp(&Float::exact_from(&y)), cmp); assert_eq!( rug::Float::exact_from(&x).partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_natural_properties() { float_natural_pair_gen().test_properties(|(x, y)| { partial_cmp_natural_properties_helper(x, y); }); float_natural_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_natural_properties_helper(x, y); }); float_float_natural_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); float_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Float::exact_from(&y)), Some(x.cmp(&y))); }); float_natural_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x).partial_cmp(&y), x.partial_cmp(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{primitive_float_gen, primitive_float_gen_var_11}; use malachite_float::Float; use malachite_float::test_util::common::{ ORDERED_F32S, ORDERED_F64S, ORDERED_FLOAT_HEX_STRINGS, parse_hex_string, }; use malachite_float::test_util::generators::{ float_float_primitive_float_triple_gen, float_gen, float_gen_var_2, float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, float_primitive_float_primitive_float_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; const fn encode(oo: Option) -> u8 { match oo { None => 9, Some(Less) => 0, Some(Equal) => 1, Some(Greater) => 2, } } #[rustfmt::skip] const MATRIX_F32: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 1, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [2, 2, 2, 2, 2, 1, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#1 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#2 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#100 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[rustfmt::skip] const MATRIX_F64: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 1, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 1, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [2, 2, 2, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [2, 2, 2, 2, 2, 1, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], // NaN [2, 2, 2, 2, 2, 2, 2, 1, 9, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 1, 0, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 1, 0, 0, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#1 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#2 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 1, 0, 0, 0, 0], // 0x1.0#100 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 1, 0, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 1, 0, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 1, 0], [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 1], ]; #[test] fn test_partial_cmp_primitive_float() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F64.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F64S.iter().zip(row.iter()) { assert_eq!(encode(x.partial_cmp(&y)), e); assert_eq!(encode(rug::Float::exact_from(&x).partial_cmp(&y)), e); assert_eq!(encode(y.partial_cmp(&x).map(Ordering::reverse)), e); assert_eq!( encode( y.partial_cmp(&rug::Float::exact_from(&x)) .map(Ordering::reverse) ), e ); } } for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F32.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F32S.iter().zip(row.iter()) { assert_eq!(encode(x.partial_cmp(&y)), e); assert_eq!(encode(rug::Float::exact_from(&x).partial_cmp(&y)), e); assert_eq!(encode(y.partial_cmp(&x).map(Ordering::reverse)), e); assert_eq!( encode( y.partial_cmp(&rug::Float::exact_from(&x)) .map(Ordering::reverse) ), e ); } } } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_primitive_float_properties_helper_helper< T: PartialOrd + PartialOrd + PrimitiveFloat, >( n: Float, u: T, ) where Float: TryFrom + PartialOrd, rug::Float: PartialOrd, { let cmp = n.partial_cmp(&u); assert_eq!(rug::Float::exact_from(&n).partial_cmp(&u), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Float::exact_from(&n)), cmp_rev); assert_eq!( PartialOrd::::partial_cmp(&n, &Float::exact_from(u)), cmp ); } #[allow(clippy::neg_cmp_op_on_partial_ord)] fn partial_cmp_primitive_float_properties_helper< T: PartialOrd + PartialOrd + PrimitiveFloat, >() where Float: TryFrom + PartialOrd, rug::Float: PartialOrd, { float_primitive_float_pair_gen::().test_properties(|(n, u)| { partial_cmp_primitive_float_properties_helper_helper(n, u); }); float_primitive_float_pair_gen_var_1::().test_properties(|(n, u)| { partial_cmp_primitive_float_properties_helper_helper(n, u); }); float_float_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Less)); } else if n > u && u > m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Greater)); } }); float_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); float_gen().test_properties(|x| { assert!(!(x < T::NAN)); assert!(!(x > T::NAN)); }); float_gen_var_2().test_properties(|x| { assert!(x >= T::NEGATIVE_INFINITY); assert!(x <= T::INFINITY); }); primitive_float_gen::().test_properties(|x| { assert!(!(x < Float::NAN)); assert!(!(x > Float::NAN)); }); primitive_float_gen_var_11::().test_properties(|x| { assert!(x >= Float::NEGATIVE_INFINITY); assert!(x <= Float::INFINITY); }); } #[test] fn partial_cmp_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_base::{apply_fn_to_signeds, apply_fn_to_unsigneds}; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_float_signed_triple_gen, float_float_unsigned_triple_gen, float_signed_pair_gen, float_signed_pair_gen_var_4, float_signed_signed_triple_gen, float_unsigned_pair_gen, float_unsigned_pair_gen_var_5, float_unsigned_unsigned_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; #[test] fn test_partial_cmp_u32() { let test = |s, s_hex, v: u32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Float::exact_from(&u).partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Less)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Less)); test("-2.0", "-0x2.0#1", 0, Some(Less)); test("-0.5", "-0x0.8#1", 0, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Less)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Less)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Less)); test("-2.0", "-0x2.0#1", 1, Some(Less)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Less)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); } #[test] fn test_partial_cmp_u64() { let test = |s, s_hex, v: u64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Float::exact_from(&u).partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Less)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Less)); test("-2.0", "-0x2.0#1", 0, Some(Less)); test("-0.5", "-0x0.8#1", 0, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Less)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Less)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Less)); test("-2.0", "-0x2.0#1", 1, Some(Less)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Less)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); } #[test] fn test_partial_cmp_i32() { let test = |s, s_hex, v: i32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Float::exact_from(&u).partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Less)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Less)); test("-2.0", "-0x2.0#1", 0, Some(Less)); test("-0.5", "-0x0.8#1", 0, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Less)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Less)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Less)); test("-2.0", "-0x2.0#1", 1, Some(Less)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Less)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); test("NaN", "NaN", -1, None); test("Infinity", "Infinity", -1, Some(Greater)); test("-Infinity", "-Infinity", -1, Some(Less)); test("0.0", "0x0.0", -1, Some(Greater)); test("-0.0", "-0x0.0", -1, Some(Greater)); test("1.0", "0x1.0#1", -1, Some(Greater)); test("2.0", "0x2.0#1", -1, Some(Greater)); test("0.5", "0x0.8#1", -1, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", -1, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -1, Some(Greater)); test("-1.0", "-0x1.0#1", -1, Some(Equal)); test("-2.0", "-0x2.0#1", -1, Some(Less)); test("-0.5", "-0x0.8#1", -1, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -1, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", -1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", -1, Some(Greater)); test("NaN", "NaN", -100, None); test("Infinity", "Infinity", -100, Some(Greater)); test("-Infinity", "-Infinity", -100, Some(Less)); test("0.0", "0x0.0", -100, Some(Greater)); test("-0.0", "-0x0.0", -100, Some(Greater)); test("1.0", "0x1.0#1", -100, Some(Greater)); test("2.0", "0x2.0#1", -100, Some(Greater)); test("0.5", "0x0.8#1", -100, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", -100, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -100, Some(Greater)); test("-1.0", "-0x1.0#1", -100, Some(Greater)); test("-2.0", "-0x2.0#1", -100, Some(Greater)); test("-0.5", "-0x0.8#1", -100, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", -100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", -100, Some(Greater)); } #[test] fn test_partial_cmp_i64() { let test = |s, s_hex, v: i64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Float::exact_from(&u).partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("NaN", "NaN", 0, None); test("Infinity", "Infinity", 0, Some(Greater)); test("-Infinity", "-Infinity", 0, Some(Less)); test("0.0", "0x0.0", 0, Some(Equal)); test("-0.0", "-0x0.0", 0, Some(Equal)); test("1.0", "0x1.0#1", 0, Some(Greater)); test("2.0", "0x2.0#1", 0, Some(Greater)); test("0.5", "0x0.8#1", 0, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", 0, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 0, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 0, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 0, Some(Greater)); test("-1.0", "-0x1.0#1", 0, Some(Less)); test("-2.0", "-0x2.0#1", 0, Some(Less)); test("-0.5", "-0x0.8#1", 0, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 0, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 0, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 0, Some(Less)); test("NaN", "NaN", 1, None); test("Infinity", "Infinity", 1, Some(Greater)); test("-Infinity", "-Infinity", 1, Some(Less)); test("0.0", "0x0.0", 1, Some(Less)); test("-0.0", "-0x0.0", 1, Some(Less)); test("1.0", "0x1.0#1", 1, Some(Equal)); test("2.0", "0x2.0#1", 1, Some(Greater)); test("0.5", "0x0.8#1", 1, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 1, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", 1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 1, Some(Less)); test("-1.0", "-0x1.0#1", 1, Some(Less)); test("-2.0", "-0x2.0#1", 1, Some(Less)); test("-0.5", "-0x0.8#1", 1, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 1, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 1, Some(Less)); test("NaN", "NaN", 100, None); test("Infinity", "Infinity", 100, Some(Greater)); test("-Infinity", "-Infinity", 100, Some(Less)); test("0.0", "0x0.0", 100, Some(Less)); test("-0.0", "-0x0.0", 100, Some(Less)); test("1.0", "0x1.0#1", 100, Some(Less)); test("2.0", "0x2.0#1", 100, Some(Less)); test("0.5", "0x0.8#1", 100, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", 100, Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", 100, Some(Less), ); test("3.0e120", "0x1.0E+100#1", 100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", 100, Some(Less)); test("-1.0", "-0x1.0#1", 100, Some(Less)); test("-2.0", "-0x2.0#1", 100, Some(Less)); test("-0.5", "-0x0.8#1", 100, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", 100, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", 100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", 100, Some(Less)); test("NaN", "NaN", -1, None); test("Infinity", "Infinity", -1, Some(Greater)); test("-Infinity", "-Infinity", -1, Some(Less)); test("0.0", "0x0.0", -1, Some(Greater)); test("-0.0", "-0x0.0", -1, Some(Greater)); test("1.0", "0x1.0#1", -1, Some(Greater)); test("2.0", "0x2.0#1", -1, Some(Greater)); test("0.5", "0x0.8#1", -1, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", -1, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -1, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -1, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -1, Some(Greater)); test("-1.0", "-0x1.0#1", -1, Some(Equal)); test("-2.0", "-0x2.0#1", -1, Some(Less)); test("-0.5", "-0x0.8#1", -1, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -1, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", -1, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", -1, Some(Greater)); test("NaN", "NaN", -100, None); test("Infinity", "Infinity", -100, Some(Greater)); test("-Infinity", "-Infinity", -100, Some(Less)); test("0.0", "0x0.0", -100, Some(Greater)); test("-0.0", "-0x0.0", -100, Some(Greater)); test("1.0", "0x1.0#1", -100, Some(Greater)); test("2.0", "0x2.0#1", -100, Some(Greater)); test("0.5", "0x0.8#1", -100, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", -100, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", -100, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", -100, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", -100, Some(Greater)); test("-1.0", "-0x1.0#1", -100, Some(Greater)); test("-2.0", "-0x2.0#1", -100, Some(Greater)); test("-0.5", "-0x0.8#1", -100, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", -100, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", -100, Some(Greater)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_primitive_int_properties_helper_unsigned_helper< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >( n: Float, u: T, ) where Float: From + PartialOrd, rug::Float: PartialOrd, { let cmp = n.partial_cmp(&u); assert_eq!(rug::Float::exact_from(&n).partial_cmp(&u), cmp); assert_eq!(PartialOrd::::partial_cmp(&n, &Float::from(u)), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Float::exact_from(&n)), cmp_rev); assert_eq!( PartialOrd::::partial_cmp(&Float::from(u), &n), cmp_rev ); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_unsigned< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >() where Float: From + PartialOrd, rug::Float: PartialOrd, { float_unsigned_pair_gen::().test_properties(|(n, u)| { partial_cmp_primitive_int_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_5::().test_properties(|(n, u)| { partial_cmp_primitive_int_properties_helper_unsigned_helper(n, u); }); float_float_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Less)); } else if n > u && u > m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Greater)); } }); float_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Float::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Float::from(y)), Some(x.cmp(&y))); }); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_primitive_int_properties_helper_signed_helper< T: PartialOrd + PartialOrd + PrimitiveSigned, >( n: Float, i: T, ) where Float: From + PartialOrd, rug::Float: PartialOrd, { let cmp = n.partial_cmp(&i); assert_eq!(rug::Float::exact_from(&n).partial_cmp(&i), cmp); assert_eq!(PartialOrd::::partial_cmp(&n, &Float::from(i)), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp(&n), cmp_rev); assert_eq!(i.partial_cmp(&rug::Float::exact_from(&n)), cmp_rev); assert_eq!( PartialOrd::::partial_cmp(&Float::from(i), &n), cmp_rev ); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_signed< T: PartialOrd + PartialOrd + PrimitiveSigned, >() where Float: From + PartialOrd, rug::Float: PartialOrd, { float_signed_pair_gen::().test_properties(|(n, i)| { partial_cmp_primitive_int_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_4::().test_properties(|(n, i)| { partial_cmp_primitive_int_properties_helper_signed_helper(n, i); }); float_float_signed_triple_gen::().test_properties(|(n, m, i)| { if n < i && i < m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Less)); } else if n > i && i > m { assert_eq!(PartialOrd::::partial_cmp(&n, &m), Some(Greater)); } }); float_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i < n && n < j { assert!(i < j); } else if i > n && n > j { assert!(i > j); } }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Float::from(y)), Some(x.cmp(&y))); }); } #[test] fn partial_cmp_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-float/tests/comparison/partial_cmp_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::comparison::partial_cmp_rational::float_partial_cmp_rational_alt; use malachite_float::test_util::generators::{ float_float_rational_triple_gen, float_rational_pair_gen, float_rational_pair_gen_var_1, float_rational_pair_gen_var_2, float_rational_rational_triple_gen, }; use malachite_q::Rational; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_rational() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Rational::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); assert_eq!( rug::Float::exact_from(&u).partial_cmp(&rug::Rational::from(&v)), out ); }; test("NaN", "NaN", "0", None); test("Infinity", "Infinity", "0", Some(Greater)); test("-Infinity", "-Infinity", "0", Some(Less)); test("0.0", "0x0.0", "0", Some(Equal)); test("-0.0", "-0x0.0", "0", Some(Equal)); test("1.0", "0x1.0#1", "0", Some(Greater)); test("2.0", "0x2.0#1", "0", Some(Greater)); test("0.5", "0x0.8#1", "0", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "0", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "0", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "0", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "0", Some(Greater)); test("-1.0", "-0x1.0#1", "0", Some(Less)); test("-2.0", "-0x2.0#1", "0", Some(Less)); test("-0.5", "-0x0.8#1", "0", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "0", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "0", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "0", Some(Less)); test("NaN", "NaN", "1", None); test("Infinity", "Infinity", "1", Some(Greater)); test("-Infinity", "-Infinity", "1", Some(Less)); test("0.0", "0x0.0", "1", Some(Less)); test("-0.0", "-0x0.0", "1", Some(Less)); test("1.0", "0x1.0#1", "1", Some(Equal)); test("2.0", "0x2.0#1", "1", Some(Greater)); test("0.5", "0x0.8#1", "1", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "1", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1", Some(Less)); test("-1.0", "-0x1.0#1", "1", Some(Less)); test("-2.0", "-0x2.0#1", "1", Some(Less)); test("-0.5", "-0x0.8#1", "1", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "1", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "1", Some(Less)); test("NaN", "NaN", "100", None); test("Infinity", "Infinity", "100", Some(Greater)); test("-Infinity", "-Infinity", "100", Some(Less)); test("0.0", "0x0.0", "100", Some(Less)); test("-0.0", "-0x0.0", "100", Some(Less)); test("1.0", "0x1.0#1", "100", Some(Less)); test("2.0", "0x2.0#1", "100", Some(Less)); test("0.5", "0x0.8#1", "100", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "100", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "100", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "100", Some(Less)); test("-1.0", "-0x1.0#1", "100", Some(Less)); test("-2.0", "-0x2.0#1", "100", Some(Less)); test("-0.5", "-0x0.8#1", "100", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "100", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "100", Some(Less)); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Equal)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Less)); test("-0.0", "-0x0.0", s, Some(Less)); test("1.0", "0x1.0#1", s, Some(Less)); test("2.0", "0x2.0#1", s, Some(Less)); test("0.5", "0x0.8#1", s, Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Less), ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Less)); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Less)); test("3.0e120", "0x1.0E+100#1", s, Some(Less)); test("4.0e-121", "0x1.0E-100#1", s, Some(Less)); test("-1.0", "-0x1.0#1", s, Some(Less)); test("-2.0", "-0x2.0#1", s, Some(Less)); test("-0.5", "-0x0.8#1", s, Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Less)); test("NaN", "NaN", "1/2", None); test("Infinity", "Infinity", "1/2", Some(Greater)); test("-Infinity", "-Infinity", "1/2", Some(Less)); test("0.0", "0x0.0", "1/2", Some(Less)); test("-0.0", "-0x0.0", "1/2", Some(Less)); test("1.0", "0x1.0#1", "1/2", Some(Greater)); test("2.0", "0x2.0#1", "1/2", Some(Greater)); test("0.5", "0x0.8#1", "1/2", Some(Equal)); test( "0.33333333333333331", "0x0.55555555555554#53", "1/2", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/2", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/2", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1/2", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1/2", Some(Less)); test("-1.0", "-0x1.0#1", "1/2", Some(Less)); test("-2.0", "-0x2.0#1", "1/2", Some(Less)); test("-0.5", "-0x0.8#1", "1/2", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/2", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/2", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/2", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "1/2", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "1/2", Some(Less)); test("NaN", "NaN", "1/3", None); test("Infinity", "Infinity", "1/3", Some(Greater)); test("-Infinity", "-Infinity", "1/3", Some(Less)); test("0.0", "0x0.0", "1/3", Some(Less)); test("-0.0", "-0x0.0", "1/3", Some(Less)); test("1.0", "0x1.0#1", "1/3", Some(Greater)); test("2.0", "0x2.0#1", "1/3", Some(Greater)); test("0.5", "0x0.8#1", "1/3", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "1/3", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/3", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "1/3", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "1/3", Some(Less)); test("-1.0", "-0x1.0#1", "1/3", Some(Less)); test("-2.0", "-0x2.0#1", "1/3", Some(Less)); test("-0.5", "-0x0.8#1", "1/3", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/3", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/3", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "1/3", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "1/3", Some(Less)); test("NaN", "NaN", "22/7", None); test("Infinity", "Infinity", "22/7", Some(Greater)); test("-Infinity", "-Infinity", "22/7", Some(Less)); test("0.0", "0x0.0", "22/7", Some(Less)); test("-0.0", "-0x0.0", "22/7", Some(Less)); test("1.0", "0x1.0#1", "22/7", Some(Less)); test("2.0", "0x2.0#1", "22/7", Some(Less)); test("0.5", "0x0.8#1", "22/7", Some(Less)); test( "0.33333333333333331", "0x0.55555555555554#53", "22/7", Some(Less), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "22/7", Some(Less), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "22/7", Some(Less), ); test("3.0e120", "0x1.0E+100#1", "22/7", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "22/7", Some(Less)); test("-1.0", "-0x1.0#1", "22/7", Some(Less)); test("-2.0", "-0x2.0#1", "22/7", Some(Less)); test("-0.5", "-0x0.8#1", "22/7", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "22/7", Some(Less), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "22/7", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "22/7", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "22/7", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "22/7", Some(Less)); test("NaN", "NaN", "-1", None); test("Infinity", "Infinity", "-1", Some(Greater)); test("-Infinity", "-Infinity", "-1", Some(Less)); test("0.0", "0x0.0", "-1", Some(Greater)); test("-0.0", "-0x0.0", "-1", Some(Greater)); test("1.0", "0x1.0#1", "-1", Some(Greater)); test("2.0", "0x2.0#1", "-1", Some(Greater)); test("0.5", "0x0.8#1", "-1", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1", Some(Greater)); test("-1.0", "-0x1.0#1", "-1", Some(Equal)); test("-2.0", "-0x2.0#1", "-1", Some(Less)); test("-0.5", "-0x0.8#1", "-1", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-1", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-1", Some(Greater)); test("NaN", "NaN", "-100", None); test("Infinity", "Infinity", "-100", Some(Greater)); test("-Infinity", "-Infinity", "-100", Some(Less)); test("0.0", "0x0.0", "-100", Some(Greater)); test("-0.0", "-0x0.0", "-100", Some(Greater)); test("1.0", "0x1.0#1", "-100", Some(Greater)); test("2.0", "0x2.0#1", "-100", Some(Greater)); test("0.5", "0x0.8#1", "-100", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-100", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-100", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-100", Some(Greater)); test("-1.0", "-0x1.0#1", "-100", Some(Greater)); test("-2.0", "-0x2.0#1", "-100", Some(Greater)); test("-0.5", "-0x0.8#1", "-100", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-100", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-100", Some(Greater)); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Greater)); test("-0.0", "-0x0.0", s, Some(Greater)); test("1.0", "0x1.0#1", s, Some(Greater)); test("2.0", "0x2.0#1", s, Some(Greater)); test("0.5", "0x0.8#1", s, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", s, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", s, Some(Greater)); test("-1.0", "-0x1.0#1", s, Some(Greater)); test("-2.0", "-0x2.0#1", s, Some(Greater)); test("-0.5", "-0x0.8#1", s, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Equal)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Greater)); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, None); test("Infinity", "Infinity", s, Some(Greater)); test("-Infinity", "-Infinity", s, Some(Less)); test("0.0", "0x0.0", s, Some(Greater)); test("-0.0", "-0x0.0", s, Some(Greater)); test("1.0", "0x1.0#1", s, Some(Greater)); test("2.0", "0x2.0#1", s, Some(Greater)); test("0.5", "0x0.8#1", s, Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", s, Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", s, Some(Greater), ); test("3.0e120", "0x1.0E+100#1", s, Some(Greater)); test("4.0e-121", "0x1.0E-100#1", s, Some(Greater)); test("-1.0", "-0x1.0#1", s, Some(Greater)); test("-2.0", "-0x2.0#1", s, Some(Greater)); test("-0.5", "-0x0.8#1", s, Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", s, Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", s, Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", s, Some(Greater)); test("-4.0e-121", "-0x1.0E-100#1", s, Some(Greater)); test("NaN", "NaN", "-1/2", None); test("Infinity", "Infinity", "-1/2", Some(Greater)); test("-Infinity", "-Infinity", "-1/2", Some(Less)); test("0.0", "0x0.0", "-1/2", Some(Greater)); test("-0.0", "-0x0.0", "-1/2", Some(Greater)); test("1.0", "0x1.0#1", "-1/2", Some(Greater)); test("2.0", "0x2.0#1", "-1/2", Some(Greater)); test("0.5", "0x0.8#1", "-1/2", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/2", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/2", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/2", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1/2", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1/2", Some(Greater)); test("-1.0", "-0x1.0#1", "-1/2", Some(Less)); test("-2.0", "-0x2.0#1", "-1/2", Some(Less)); test("-0.5", "-0x0.8#1", "-1/2", Some(Equal)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/2", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/2", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/2", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-1/2", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-1/2", Some(Greater)); test("NaN", "NaN", "-1/3", None); test("Infinity", "Infinity", "-1/3", Some(Greater)); test("-Infinity", "-Infinity", "-1/3", Some(Less)); test("0.0", "0x0.0", "-1/3", Some(Greater)); test("-0.0", "-0x0.0", "-1/3", Some(Greater)); test("1.0", "0x1.0#1", "-1/3", Some(Greater)); test("2.0", "0x2.0#1", "-1/3", Some(Greater)); test("0.5", "0x0.8#1", "-1/3", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/3", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/3", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-1/3", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-1/3", Some(Greater)); test("-1.0", "-0x1.0#1", "-1/3", Some(Less)); test("-2.0", "-0x2.0#1", "-1/3", Some(Less)); test("-0.5", "-0x0.8#1", "-1/3", Some(Less)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/3", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/3", Some(Less), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", Some(Less), ); test("-3.0e120", "-0x1.0E+100#1", "-1/3", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-1/3", Some(Greater)); test("NaN", "NaN", "-22/7", None); test("Infinity", "Infinity", "-22/7", Some(Greater)); test("-Infinity", "-Infinity", "-22/7", Some(Less)); test("0.0", "0x0.0", "-22/7", Some(Greater)); test("-0.0", "-0x0.0", "-22/7", Some(Greater)); test("1.0", "0x1.0#1", "-22/7", Some(Greater)); test("2.0", "0x2.0#1", "-22/7", Some(Greater)); test("0.5", "0x0.8#1", "-22/7", Some(Greater)); test( "0.33333333333333331", "0x0.55555555555554#53", "-22/7", Some(Greater), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "-22/7", Some(Greater), ); test( "3.1415926535897931", "0x3.243f6a8885a30#53", "-22/7", Some(Greater), ); test("3.0e120", "0x1.0E+100#1", "-22/7", Some(Greater)); test("4.0e-121", "0x1.0E-100#1", "-22/7", Some(Greater)); test("-1.0", "-0x1.0#1", "-22/7", Some(Greater)); test("-2.0", "-0x2.0#1", "-22/7", Some(Greater)); test("-0.5", "-0x0.8#1", "-22/7", Some(Greater)); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-22/7", Some(Greater), ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-22/7", Some(Greater), ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-22/7", Some(Greater), ); test("-3.0e120", "-0x1.0E+100#1", "-22/7", Some(Less)); test("-4.0e-121", "-0x1.0E-100#1", "-22/7", Some(Greater)); } #[allow(clippy::needless_pass_by_value)] fn partial_cmp_rational_properties_helper(x: Float, y: Rational) { let cmp = x.partial_cmp(&y); assert_eq!( rug::Float::exact_from(&x).partial_cmp(&rug::Rational::from(&y)), cmp ); assert_eq!(float_partial_cmp_rational_alt(&x, &y), cmp); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); } #[test] fn partial_cmp_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { partial_cmp_rational_properties_helper(x, y); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { partial_cmp_rational_properties_helper(x, y); }); float_float_rational_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); float_rational_rational_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); float_rational_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Some(Rational::exact_from(&x).cmp(&y)), x.partial_cmp(&y)); }); } ================================================ FILE: malachite-float/tests/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_integer_pair_gen, float_integer_pair_gen_var_1, float_integer_pair_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen}; use malachite_q::Rational; use rug; use std::str::FromStr; #[test] fn test_partial_eq_integer() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Integer::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!(rug::Float::exact_from(&u) == rug::Integer::from(&v), out); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", false); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "-1", false); test("Infinity", "Infinity", "-1", false); test("-Infinity", "-Infinity", "-1", false); test("0.0", "0x0.0", "-1", false); test("-0.0", "-0x0.0", "-1", false); test("1.0", "0x1.0#1", "-1", false); test("2.0", "0x2.0#1", "-1", false); test("0.5", "0x0.8#1", "-1", false); test("0.33333333333333331", "0x0.55555555555554#53", "-1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1", false); test("3.0e120", "0x1.0E+100#1", "-1", false); test("4.0e-121", "0x1.0E-100#1", "-1", false); test("-1.0", "-0x1.0#1", "-1", true); test("-2.0", "-0x2.0#1", "-1", false); test("-0.5", "-0x0.8#1", "-1", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", false); test("-3.0e120", "-0x1.0E+100#1", "-1", false); test("-4.0e-121", "-0x1.0E-100#1", "-1", false); test("NaN", "NaN", "-100", false); test("Infinity", "Infinity", "-100", false); test("-Infinity", "-Infinity", "-100", false); test("0.0", "0x0.0", "-100", false); test("-0.0", "-0x0.0", "-100", false); test("1.0", "0x1.0#1", "-100", false); test("2.0", "0x2.0#1", "-100", false); test("0.5", "0x0.8#1", "-100", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-100", false); test("3.0e120", "0x1.0E+100#1", "-100", false); test("4.0e-121", "0x1.0E-100#1", "-100", false); test("-1.0", "-0x1.0#1", "-100", false); test("-2.0", "-0x2.0#1", "-100", false); test("-0.5", "-0x0.8#1", "-100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", false, ); test("-3.0e120", "-0x1.0E+100#1", "-100", false); test("-4.0e-121", "-0x1.0E-100#1", "-100", false); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned)] fn partial_eq_integer_properties_helper(x: Float, y: Integer) { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(x == Float::exact_from(&y), eq); assert_eq!(rug::Float::exact_from(&x) == rug::Integer::from(&y), eq); } #[allow(clippy::cmp_owned)] #[test] fn partial_eq_integer_properties() { float_integer_pair_gen().test_properties(|(x, y)| { partial_eq_integer_properties_helper(x, y); }); float_integer_pair_gen_var_2().test_properties(|(x, y)| { partial_eq_integer_properties_helper(x, y); }); integer_gen().test_properties(|x| { assert_ne!(x, Float::NAN); assert_ne!(x, Float::INFINITY); assert_ne!(x, Float::NEGATIVE_INFINITY); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x) == y, x == y); assert_eq!(x == Float::exact_from(&y), x == y); }); float_integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x) == y, x == y); }); } ================================================ FILE: malachite-float/tests/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_natural_pair_gen, float_natural_pair_gen_var_1, float_natural_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use malachite_q::Rational; use rug; use std::str::FromStr; #[test] fn test_partial_eq_natural() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Natural::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!(rug::Float::exact_from(&u) == rug::Integer::from(&v), out); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", false); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned)] fn partial_eq_natural_properties_helper(x: Float, y: Natural) { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(x == Float::exact_from(&y), eq); assert_eq!(rug::Float::exact_from(&x) == rug::Integer::from(&y), eq); } #[allow(clippy::cmp_owned)] #[test] fn partial_eq_natural_properties() { float_natural_pair_gen().test_properties(|(x, y)| { partial_eq_natural_properties_helper(x, y); }); float_natural_pair_gen_var_2().test_properties(|(x, y)| { partial_eq_natural_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert_ne!(x, Float::NAN); assert_ne!(x, Float::INFINITY); assert_ne!(x, Float::NEGATIVE_INFINITY); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Float::exact_from(&x) == y, x == y); assert_eq!(x == Float::exact_from(&y), x == y); }); float_natural_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x) == y, x == y); }); } ================================================ FILE: malachite-float/tests/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::{ ORDERED_F32S, ORDERED_F64S, ORDERED_FLOAT_HEX_STRINGS, parse_hex_string, }; use malachite_float::test_util::generators::{ float_primitive_float_pair_gen, float_primitive_float_pair_gen_var_1, }; use rug; use std::cmp::Ordering::*; #[rustfmt::skip] const MATRIX_F32: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[rustfmt::skip] const MATRIX_F64: [[u8; 17]; 21] = [ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#100 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#2 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // -0x1.0#1 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // -0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // NaN [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], // 0.0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], // 0x1.0#100 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]; #[test] fn test_partial_eq_primitive_float() { for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F64.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F64S.iter().zip(row.iter()) { assert_eq!(u8::from(x == y), e); assert_eq!(u8::from(rug::Float::exact_from(&x) == y), e); assert_eq!(u8::from(y == x), e); assert_eq!(u8::from(y == rug::Float::exact_from(&x)), e); } } for (sx, row) in ORDERED_FLOAT_HEX_STRINGS.iter().zip(MATRIX_F32.iter()) { let x = parse_hex_string(sx); for (&y, &e) in ORDERED_F32S.iter().zip(row.iter()) { assert_eq!(u8::from(x == y), e); assert_eq!(u8::from(rug::Float::exact_from(&x) == y), e); assert_eq!(u8::from(y == x), e); assert_eq!(u8::from(y == rug::Float::exact_from(&x)), e); } } } #[allow(clippy::needless_pass_by_value)] fn partial_eq_primitive_float_properties_helper_helper< T: PartialEq + PartialEq + PrimitiveFloat, >( n: Float, f: T, ) where Float: TryFrom + PartialEq + PartialOrd, rug::Float: PartialEq, { let eq = n == f; assert_eq!(f == n, eq); let rn = rug::Float::exact_from(&n); assert_eq!(rn == f, eq); assert_eq!(f == rn, eq); assert_eq!(n.partial_cmp(&f) == Some(Equal), eq); if f.is_finite() { assert_eq!(PartialEq::::eq(&n, &Float::exact_from(f)), eq); } } fn partial_eq_primitive_float_properties_helper< T: PartialEq + PartialEq + PrimitiveFloat, >() where Float: TryFrom + PartialEq + PartialOrd, rug::Float: PartialEq, { float_primitive_float_pair_gen::().test_properties(|(n, f)| { partial_eq_primitive_float_properties_helper_helper(n, f); }); float_primitive_float_pair_gen_var_1::().test_properties(|(n, f)| { partial_eq_primitive_float_properties_helper_helper(n, f); }); } #[test] fn partial_eq_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_eq_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen, unsigned_gen, unsigned_pair_gen_var_27, }; use malachite_base::{apply_fn_to_signeds, apply_fn_to_unsigneds}; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_signed_pair_gen, float_signed_pair_gen_var_4, float_unsigned_pair_gen, float_unsigned_pair_gen_var_5, }; use rug; #[test] fn test_partial_eq_u32() { let test = |s, s_hex, v: u32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let ru = rug::Float::exact_from(&u); assert_eq!(u == v, out); assert_eq!(ru == v, out); assert_eq!(v == u, out); assert_eq!(v == ru, out); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, false); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); } #[test] fn test_partial_eq_u64() { let test = |s, s_hex, v: u64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let ru = rug::Float::exact_from(&u); assert_eq!(u == v, out); assert_eq!(ru == v, out); assert_eq!(v == u, out); assert_eq!(v == ru, out); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, false); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); } #[test] fn test_partial_eq_i32() { let test = |s, s_hex, v: i32, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let ru = rug::Float::exact_from(&u); assert_eq!(u == v, out); assert_eq!(ru == v, out); assert_eq!(v == u, out); assert_eq!(v == ru, out); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, false); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); test("NaN", "NaN", -1, false); test("Infinity", "Infinity", -1, false); test("-Infinity", "-Infinity", -1, false); test("0.0", "0x0.0", -1, false); test("-0.0", "-0x0.0", -1, false); test("1.0", "0x1.0#1", -1, false); test("2.0", "0x2.0#1", -1, false); test("0.5", "0x0.8#1", -1, false); test("0.33333333333333331", "0x0.55555555555554#53", -1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -1, false); test("3.0e120", "0x1.0E+100#1", -1, false); test("4.0e-121", "0x1.0E-100#1", -1, false); test("-1.0", "-0x1.0#1", -1, true); test("-2.0", "-0x2.0#1", -1, false); test("-0.5", "-0x0.8#1", -1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", -1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, false); test("-3.0e120", "-0x1.0E+100#1", -1, false); test("-4.0e-121", "-0x1.0E-100#1", -1, false); test("NaN", "NaN", -100, false); test("Infinity", "Infinity", -100, false); test("-Infinity", "-Infinity", -100, false); test("0.0", "0x0.0", -100, false); test("-0.0", "-0x0.0", -100, false); test("1.0", "0x1.0#1", -100, false); test("2.0", "0x2.0#1", -100, false); test("0.5", "0x0.8#1", -100, false); test("0.33333333333333331", "0x0.55555555555554#53", -100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -100, false); test("3.0e120", "0x1.0E+100#1", -100, false); test("4.0e-121", "0x1.0E-100#1", -100, false); test("-1.0", "-0x1.0#1", -100, false); test("-2.0", "-0x2.0#1", -100, false); test("-0.5", "-0x0.8#1", -100, false); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, false); test("-3.0e120", "-0x1.0E+100#1", -100, false); test("-4.0e-121", "-0x1.0E-100#1", -100, false); } #[test] fn test_partial_eq_i64() { let test = |s, s_hex, v: i64, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let ru = rug::Float::exact_from(&u); assert_eq!(u == v, out); assert_eq!(ru == v, out); assert_eq!(v == u, out); assert_eq!(v == ru, out); }; test("NaN", "NaN", 0, false); test("Infinity", "Infinity", 0, false); test("-Infinity", "-Infinity", 0, false); test("0.0", "0x0.0", 0, true); test("-0.0", "-0x0.0", 0, true); test("1.0", "0x1.0#1", 0, false); test("2.0", "0x2.0#1", 0, false); test("0.5", "0x0.8#1", 0, false); test("0.33333333333333331", "0x0.55555555555554#53", 0, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 0, false); test("3.0e120", "0x1.0E+100#1", 0, false); test("4.0e-121", "0x1.0E-100#1", 0, false); test("-1.0", "-0x1.0#1", 0, false); test("-2.0", "-0x2.0#1", 0, false); test("-0.5", "-0x0.8#1", 0, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 0, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 0, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 0, false); test("-3.0e120", "-0x1.0E+100#1", 0, false); test("-4.0e-121", "-0x1.0E-100#1", 0, false); test("NaN", "NaN", 1, false); test("Infinity", "Infinity", 1, false); test("-Infinity", "-Infinity", 1, false); test("0.0", "0x0.0", 1, false); test("-0.0", "-0x0.0", 1, false); test("1.0", "0x1.0#1", 1, true); test("2.0", "0x2.0#1", 1, false); test("0.5", "0x0.8#1", 1, false); test("0.33333333333333331", "0x0.55555555555554#53", 1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 1, false); test("3.0e120", "0x1.0E+100#1", 1, false); test("4.0e-121", "0x1.0E-100#1", 1, false); test("-1.0", "-0x1.0#1", 1, false); test("-2.0", "-0x2.0#1", 1, false); test("-0.5", "-0x0.8#1", 1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 1, false); test("-3.0e120", "-0x1.0E+100#1", 1, false); test("-4.0e-121", "-0x1.0E-100#1", 1, false); test("NaN", "NaN", 100, false); test("Infinity", "Infinity", 100, false); test("-Infinity", "-Infinity", 100, false); test("0.0", "0x0.0", 100, false); test("-0.0", "-0x0.0", 100, false); test("1.0", "0x1.0#1", 100, false); test("2.0", "0x2.0#1", 100, false); test("0.5", "0x0.8#1", 100, false); test("0.33333333333333331", "0x0.55555555555554#53", 100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", 100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", 100, false); test("3.0e120", "0x1.0E+100#1", 100, false); test("4.0e-121", "0x1.0E-100#1", 100, false); test("-1.0", "-0x1.0#1", 100, false); test("-2.0", "-0x2.0#1", 100, false); test("-0.5", "-0x0.8#1", 100, false); test("-0.33333333333333331", "-0x0.55555555555554#53", 100, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", 100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", 100, false); test("-3.0e120", "-0x1.0E+100#1", 100, false); test("-4.0e-121", "-0x1.0E-100#1", 100, false); test("NaN", "NaN", -1, false); test("Infinity", "Infinity", -1, false); test("-Infinity", "-Infinity", -1, false); test("0.0", "0x0.0", -1, false); test("-0.0", "-0x0.0", -1, false); test("1.0", "0x1.0#1", -1, false); test("2.0", "0x2.0#1", -1, false); test("0.5", "0x0.8#1", -1, false); test("0.33333333333333331", "0x0.55555555555554#53", -1, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -1, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -1, false); test("3.0e120", "0x1.0E+100#1", -1, false); test("4.0e-121", "0x1.0E-100#1", -1, false); test("-1.0", "-0x1.0#1", -1, true); test("-2.0", "-0x2.0#1", -1, false); test("-0.5", "-0x0.8#1", -1, false); test("-0.33333333333333331", "-0x0.55555555555554#53", -1, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -1, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -1, false); test("-3.0e120", "-0x1.0E+100#1", -1, false); test("-4.0e-121", "-0x1.0E-100#1", -1, false); test("NaN", "NaN", -100, false); test("Infinity", "Infinity", -100, false); test("-Infinity", "-Infinity", -100, false); test("0.0", "0x0.0", -100, false); test("-0.0", "-0x0.0", -100, false); test("1.0", "0x1.0#1", -100, false); test("2.0", "0x2.0#1", -100, false); test("0.5", "0x0.8#1", -100, false); test("0.33333333333333331", "0x0.55555555555554#53", -100, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", -100, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", -100, false); test("3.0e120", "0x1.0E+100#1", -100, false); test("4.0e-121", "0x1.0E-100#1", -100, false); test("-1.0", "-0x1.0#1", -100, false); test("-2.0", "-0x2.0#1", -100, false); test("-0.5", "-0x0.8#1", -100, false); test( "-0.33333333333333331", "-0x0.55555555555554#53", -100, false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", -100, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", -100, false); test("-3.0e120", "-0x1.0E+100#1", -100, false); test("-4.0e-121", "-0x1.0E-100#1", -100, false); } #[allow(clippy::needless_pass_by_value, clippy::cmp_owned, clippy::op_ref)] fn partial_eq_primitive_int_properties_helper_unsigned_helper< T: PartialEq + PartialEq + PrimitiveUnsigned, >( n: Float, u: T, ) where Float: From + PartialEq, rug::Float: PartialEq, { let eq = n == u; assert_eq!(rug::Float::exact_from(&n) == u, eq); assert_eq!(&n == &Float::from(u), eq); assert_eq!(u == n, eq); assert_eq!(u == rug::Float::exact_from(&n), eq); assert_eq!(&Float::from(u) == &n, eq); } #[allow(clippy::cmp_owned, clippy::op_ref)] fn partial_eq_primitive_int_properties_helper_unsigned< T: PartialEq + PartialEq + PrimitiveUnsigned, >() where Float: From + PartialEq, rug::Float: PartialEq, { float_unsigned_pair_gen::().test_properties(|(n, u)| { partial_eq_primitive_int_properties_helper_unsigned_helper(n, u); }); float_unsigned_pair_gen_var_5::().test_properties(|(n, u)| { partial_eq_primitive_int_properties_helper_unsigned_helper(n, u); }); unsigned_gen::().test_properties(|x| { assert_ne!(x, Float::NAN); assert_ne!(x, Float::INFINITY); assert_ne!(x, Float::NEGATIVE_INFINITY); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Float::from(x) == y, x == y); assert_eq!(x == Float::from(y), x == y); }); } #[allow(clippy::needless_pass_by_value, clippy::op_ref)] fn partial_eq_primitive_int_properties_helper_signed_helper< T: PartialEq + PartialEq + PrimitiveSigned, >( n: Float, i: T, ) where Float: From + PartialEq, rug::Float: PartialEq, { let eq = n == i; assert_eq!(rug::Float::exact_from(&n) == i, eq); assert_eq!(&n == &Float::from(i), eq); assert_eq!(i == n, eq); assert_eq!(i == rug::Float::exact_from(&n), eq); assert_eq!(&Float::from(i) == &n, eq); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref)] fn partial_eq_primitive_int_properties_helper_signed< T: PartialEq + PartialEq + PrimitiveSigned, >() where Float: From + PartialEq, rug::Float: PartialEq, { float_signed_pair_gen::().test_properties(|(n, i)| { partial_eq_primitive_int_properties_helper_signed_helper(n, i); }); float_signed_pair_gen_var_4::().test_properties(|(n, i)| { partial_eq_primitive_int_properties_helper_signed_helper(n, i); }); signed_gen::().test_properties(|x| { assert_ne!(x, Float::NAN); assert_ne!(x, Float::INFINITY); assert_ne!(x, Float::NEGATIVE_INFINITY); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Float::from(x) == y, x == y); assert_eq!(x == Float::from(y), x == y); }); } #[test] fn partial_eq_primitive_int_properties() { apply_fn_to_unsigneds!(partial_eq_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_eq_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-float/tests/comparison/partial_eq_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_rational_pair_gen, float_rational_pair_gen_var_1, float_rational_pair_gen_var_2, }; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use rug; use std::str::FromStr; #[test] fn test_partial_eq_rational() { let test = |s, s_hex, t, out| { let u = parse_hex_string(s_hex); assert_eq!(u.to_string(), s); let v = Rational::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!(rug::Float::exact_from(&u) == rug::Rational::from(&v), out); }; test("NaN", "NaN", "0", false); test("Infinity", "Infinity", "0", false); test("-Infinity", "-Infinity", "0", false); test("0.0", "0x0.0", "0", true); test("-0.0", "-0x0.0", "0", true); test("1.0", "0x1.0#1", "0", false); test("2.0", "0x2.0#1", "0", false); test("0.5", "0x0.8#1", "0", false); test("0.33333333333333331", "0x0.55555555555554#53", "0", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "0", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "0", false); test("3.0e120", "0x1.0E+100#1", "0", false); test("4.0e-121", "0x1.0E-100#1", "0", false); test("-1.0", "-0x1.0#1", "0", false); test("-2.0", "-0x2.0#1", "0", false); test("-0.5", "-0x0.8#1", "0", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "0", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "0", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "0", false); test("-3.0e120", "-0x1.0E+100#1", "0", false); test("-4.0e-121", "-0x1.0E-100#1", "0", false); test("NaN", "NaN", "1", false); test("Infinity", "Infinity", "1", false); test("-Infinity", "-Infinity", "1", false); test("0.0", "0x0.0", "1", false); test("-0.0", "-0x0.0", "1", false); test("1.0", "0x1.0#1", "1", true); test("2.0", "0x2.0#1", "1", false); test("0.5", "0x0.8#1", "1", false); test("0.33333333333333331", "0x0.55555555555554#53", "1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1", false); test("3.0e120", "0x1.0E+100#1", "1", false); test("4.0e-121", "0x1.0E-100#1", "1", false); test("-1.0", "-0x1.0#1", "1", false); test("-2.0", "-0x2.0#1", "1", false); test("-0.5", "-0x0.8#1", "1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", "1", false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1", false); test("-3.0e120", "-0x1.0E+100#1", "1", false); test("-4.0e-121", "-0x1.0E-100#1", "1", false); test("NaN", "NaN", "100", false); test("Infinity", "Infinity", "100", false); test("-Infinity", "-Infinity", "100", false); test("0.0", "0x0.0", "100", false); test("-0.0", "-0x0.0", "100", false); test("1.0", "0x1.0#1", "100", false); test("2.0", "0x2.0#1", "100", false); test("0.5", "0x0.8#1", "100", false); test("0.33333333333333331", "0x0.55555555555554#53", "100", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "100", false); test("3.0e120", "0x1.0E+100#1", "100", false); test("4.0e-121", "0x1.0E-100#1", "100", false); test("-1.0", "-0x1.0#1", "100", false); test("-2.0", "-0x2.0#1", "100", false); test("-0.5", "-0x0.8#1", "100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "100", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "100", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "100", false); test("-3.0e120", "-0x1.0E+100#1", "100", false); test("-4.0e-121", "-0x1.0E-100#1", "100", false); let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, true); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "2582249878086908589655919172003011874329705792829223512830659356540647622016841194629\ 645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "1/2", false); test("Infinity", "Infinity", "1/2", false); test("-Infinity", "-Infinity", "1/2", false); test("0.0", "0x0.0", "1/2", false); test("-0.0", "-0x0.0", "1/2", false); test("1.0", "0x1.0#1", "1/2", false); test("2.0", "0x2.0#1", "1/2", false); test("0.5", "0x0.8#1", "1/2", true); test("0.33333333333333331", "0x0.55555555555554#53", "1/2", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/2", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1/2", false); test("3.0e120", "0x1.0E+100#1", "1/2", false); test("4.0e-121", "0x1.0E-100#1", "1/2", false); test("-1.0", "-0x1.0#1", "1/2", false); test("-2.0", "-0x2.0#1", "1/2", false); test("-0.5", "-0x0.8#1", "1/2", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/2", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/2", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/2", false); test("-3.0e120", "-0x1.0E+100#1", "1/2", false); test("-4.0e-121", "-0x1.0E-100#1", "1/2", false); test("NaN", "NaN", "1/3", false); test("Infinity", "Infinity", "1/3", false); test("-Infinity", "-Infinity", "1/3", false); test("0.0", "0x0.0", "1/3", false); test("-0.0", "-0x0.0", "1/3", false); test("1.0", "0x1.0#1", "1/3", false); test("2.0", "0x2.0#1", "1/3", false); test("0.5", "0x0.8#1", "1/3", false); test("0.33333333333333331", "0x0.55555555555554#53", "1/3", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1/3", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "1/3", false); test("3.0e120", "0x1.0E+100#1", "1/3", false); test("4.0e-121", "0x1.0E-100#1", "1/3", false); test("-1.0", "-0x1.0#1", "1/3", false); test("-2.0", "-0x2.0#1", "1/3", false); test("-0.5", "-0x0.8#1", "1/3", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1/3", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1/3", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "1/3", false); test("-3.0e120", "-0x1.0E+100#1", "1/3", false); test("-4.0e-121", "-0x1.0E-100#1", "1/3", false); test("NaN", "NaN", "22/7", false); test("Infinity", "Infinity", "22/7", false); test("-Infinity", "-Infinity", "22/7", false); test("0.0", "0x0.0", "22/7", false); test("-0.0", "-0x0.0", "22/7", false); test("1.0", "0x1.0#1", "22/7", false); test("2.0", "0x2.0#1", "22/7", false); test("0.5", "0x0.8#1", "22/7", false); test( "0.33333333333333331", "0x0.55555555555554#53", "22/7", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "22/7", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "22/7", false); test("3.0e120", "0x1.0E+100#1", "22/7", false); test("4.0e-121", "0x1.0E-100#1", "22/7", false); test("-1.0", "-0x1.0#1", "22/7", false); test("-2.0", "-0x2.0#1", "22/7", false); test("-0.5", "-0x0.8#1", "22/7", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "22/7", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "22/7", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "22/7", false, ); test("-3.0e120", "-0x1.0E+100#1", "22/7", false); test("-4.0e-121", "-0x1.0E-100#1", "22/7", false); test("NaN", "NaN", "-1", false); test("Infinity", "Infinity", "-1", false); test("-Infinity", "-Infinity", "-1", false); test("0.0", "0x0.0", "-1", false); test("-0.0", "-0x0.0", "-1", false); test("1.0", "0x1.0#1", "-1", false); test("2.0", "0x2.0#1", "-1", false); test("0.5", "0x0.8#1", "-1", false); test("0.33333333333333331", "0x0.55555555555554#53", "-1", false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1", false); test("3.0e120", "0x1.0E+100#1", "-1", false); test("4.0e-121", "0x1.0E-100#1", "-1", false); test("-1.0", "-0x1.0#1", "-1", true); test("-2.0", "-0x2.0#1", "-1", false); test("-0.5", "-0x0.8#1", "-1", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1", false, ); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1", false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1", false); test("-3.0e120", "-0x1.0E+100#1", "-1", false); test("-4.0e-121", "-0x1.0E-100#1", "-1", false); test("NaN", "NaN", "-100", false); test("Infinity", "Infinity", "-100", false); test("-Infinity", "-Infinity", "-100", false); test("0.0", "0x0.0", "-100", false); test("-0.0", "-0x0.0", "-100", false); test("1.0", "0x1.0#1", "-100", false); test("2.0", "0x2.0#1", "-100", false); test("0.5", "0x0.8#1", "-100", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-100", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-100", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-100", false); test("3.0e120", "0x1.0E+100#1", "-100", false); test("4.0e-121", "0x1.0E-100#1", "-100", false); test("-1.0", "-0x1.0#1", "-100", false); test("-2.0", "-0x2.0#1", "-100", false); test("-0.5", "-0x0.8#1", "-100", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-100", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-100", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-100", false, ); test("-3.0e120", "-0x1.0E+100#1", "-100", false); test("-4.0e-121", "-0x1.0E-100#1", "-100", false); let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493376"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, true); test("-4.0e-121", "-0x1.0E-100#1", s, false); // off by 1 let s = "-258224987808690858965591917200301187432970579282922351283065935654064762201684119462\ 9645353280137831435903171972747493377"; test("NaN", "NaN", s, false); test("Infinity", "Infinity", s, false); test("-Infinity", "-Infinity", s, false); test("0.0", "0x0.0", s, false); test("-0.0", "-0x0.0", s, false); test("1.0", "0x1.0#1", s, false); test("2.0", "0x2.0#1", s, false); test("0.5", "0x0.8#1", s, false); test("0.33333333333333331", "0x0.55555555555554#53", s, false); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", s, false); test("3.1415926535897931", "0x3.243f6a8885a30#53", s, false); test("3.0e120", "0x1.0E+100#1", s, false); test("4.0e-121", "0x1.0E-100#1", s, false); test("-1.0", "-0x1.0#1", s, false); test("-2.0", "-0x2.0#1", s, false); test("-0.5", "-0x0.8#1", s, false); test("-0.33333333333333331", "-0x0.55555555555554#53", s, false); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", s, false); test("-3.1415926535897931", "-0x3.243f6a8885a30#53", s, false); test("-3.0e120", "-0x1.0E+100#1", s, false); test("-4.0e-121", "-0x1.0E-100#1", s, false); test("NaN", "NaN", "-1/2", false); test("Infinity", "Infinity", "-1/2", false); test("-Infinity", "-Infinity", "-1/2", false); test("0.0", "0x0.0", "-1/2", false); test("-0.0", "-0x0.0", "-1/2", false); test("1.0", "0x1.0#1", "-1/2", false); test("2.0", "0x2.0#1", "-1/2", false); test("0.5", "0x0.8#1", "-1/2", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/2", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/2", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1/2", false); test("3.0e120", "0x1.0E+100#1", "-1/2", false); test("4.0e-121", "0x1.0E-100#1", "-1/2", false); test("-1.0", "-0x1.0#1", "-1/2", false); test("-2.0", "-0x2.0#1", "-1/2", false); test("-0.5", "-0x0.8#1", "-1/2", true); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/2", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/2", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/2", false, ); test("-3.0e120", "-0x1.0E+100#1", "-1/2", false); test("-4.0e-121", "-0x1.0E-100#1", "-1/2", false); test("NaN", "NaN", "-1/3", false); test("Infinity", "Infinity", "-1/3", false); test("-Infinity", "-Infinity", "-1/3", false); test("0.0", "0x0.0", "-1/3", false); test("-0.0", "-0x0.0", "-1/3", false); test("1.0", "0x1.0#1", "-1/3", false); test("2.0", "0x2.0#1", "-1/3", false); test("0.5", "0x0.8#1", "-1/3", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-1/3", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-1/3", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-1/3", false); test("3.0e120", "0x1.0E+100#1", "-1/3", false); test("4.0e-121", "0x1.0E-100#1", "-1/3", false); test("-1.0", "-0x1.0#1", "-1/3", false); test("-2.0", "-0x2.0#1", "-1/3", false); test("-0.5", "-0x0.8#1", "-1/3", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-1/3", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-1/3", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-1/3", false, ); test("-3.0e120", "-0x1.0E+100#1", "-1/3", false); test("-4.0e-121", "-0x1.0E-100#1", "-1/3", false); test("NaN", "NaN", "-22/7", false); test("Infinity", "Infinity", "-22/7", false); test("-Infinity", "-Infinity", "-22/7", false); test("0.0", "0x0.0", "-22/7", false); test("-0.0", "-0x0.0", "-22/7", false); test("1.0", "0x1.0#1", "-22/7", false); test("2.0", "0x2.0#1", "-22/7", false); test("0.5", "0x0.8#1", "-22/7", false); test( "0.33333333333333331", "0x0.55555555555554#53", "-22/7", false, ); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", "-22/7", false); test("3.1415926535897931", "0x3.243f6a8885a30#53", "-22/7", false); test("3.0e120", "0x1.0E+100#1", "-22/7", false); test("4.0e-121", "0x1.0E-100#1", "-22/7", false); test("-1.0", "-0x1.0#1", "-22/7", false); test("-2.0", "-0x2.0#1", "-22/7", false); test("-0.5", "-0x0.8#1", "-22/7", false); test( "-0.33333333333333331", "-0x0.55555555555554#53", "-22/7", false, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "-22/7", false, ); test( "-3.1415926535897931", "-0x3.243f6a8885a30#53", "-22/7", false, ); test("-3.0e120", "-0x1.0E+100#1", "-22/7", false); test("-4.0e-121", "-0x1.0E-100#1", "-22/7", false); } #[allow(clippy::needless_pass_by_value)] fn partial_eq_rational_properties_helper(x: Float, y: Rational) { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(rug::Float::exact_from(&x) == rug::Rational::from(&y), eq); } #[test] fn partial_eq_rational_properties() { float_rational_pair_gen().test_properties(|(x, y)| { partial_eq_rational_properties_helper(x, y); }); float_rational_pair_gen_var_2().test_properties(|(x, y)| { partial_eq_rational_properties_helper(x, y); }); rational_gen().test_properties(|x| { assert_ne!(x, Float::NAN); assert_ne!(x, Float::INFINITY); assert_ne!(x, Float::NEGATIVE_INFINITY); }); float_rational_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(&x) == y, x == y); }); } ================================================ FILE: malachite-float/tests/constants/gauss_constant.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::GaussConstant; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_gauss_constant_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::gauss_constant_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_gauss_constant_prec() { test_gauss_constant_prec_helper(1, "1.0", "0x1.0#1", Greater); test_gauss_constant_prec_helper(2, "0.8", "0x0.c#2", Less); test_gauss_constant_prec_helper(3, "0.9", "0x0.e#3", Greater); test_gauss_constant_prec_helper(4, "0.81", "0x0.d#4", Less); test_gauss_constant_prec_helper(5, "0.84", "0x0.d8#5", Greater); test_gauss_constant_prec_helper(6, "0.83", "0x0.d4#6", Less); test_gauss_constant_prec_helper(7, "0.836", "0x0.d6#7", Greater); test_gauss_constant_prec_helper(8, "0.836", "0x0.d6#8", Greater); test_gauss_constant_prec_helper(9, "0.834", "0x0.d58#9", Less); test_gauss_constant_prec_helper(10, "0.835", "0x0.d5c#10", Greater); test_gauss_constant_prec_helper( 100, "0.834626841674073186281429732799", "0x0.d5aa1acd5a9a1f6b126ed4160#100", Less, ); test_gauss_constant_prec_helper( 1000, "0.834626841674073186281429732799046808993993013490347002449827370103681992709526411869691\ 160351275324129067850352412010086724789007634750392659060526742712560320685998973751521461\ 574107190667714762311244616644051871383967845140283869200451381335890758553020498480052804\ 4693164358093689789568906891741207", "0x0.d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c271f049361406e4cdd9089ef0715384d6c72\ c4bdd754b2bc1ecc5c199c686439032cbb16813342ded4cffc19dcab8db34c27b6168ceb88298ed572b191c8f3\ 05743e1f293dfd41f82b0210f65e6163e5434a891261dc7440e2093b1a156a8e05ae8319d30#1000", Greater, ); test_gauss_constant_prec_helper( 10000, "0.834626841674073186281429732799046808993993013490347002449827370103681992709526411869691\ 160351275324129067850352412010086724789007634750392659060526742712560320685998973751521461\ 574107190667714762311244616644051871383967845140283869200451381335890758553020498480052804\ 469316435809368978956890689174120737291094066558175187025477401074678379716526356753331906\ 545452517692961030560054068494662548964218614294720752148653658161076202146037520348775359\ 620856771168292200325359109589899893069833199696977335883739104959085967402918246956874691\ 648574519106727574078611438142761058018432034542615493754610095708911752106842013580331247\ 539219381390232390909523434088742226918438886299422225926335216394780110220990752149069396\ 430836038257717941194870596739642726558350848321693971336950595116238828151547470228642077\ 757753710601888047232489046185253018895970256898180138788048957359293465403946331321583387\ 855328545224934416417651732023496827033747209414764964964606237379439957051908666982548125\ 962465776495889388368485992365411189017490504837785319323332016970056895534269527949656522\ 591691440712533718989871283605282652705310788877986415746880714285132363349955706585164159\ 241908262606339549845864348827078931363082390967437220434580842087307738346482679475197152\ 331746478597653712438272228263231954311739836817821079539242107816783313273533095656482023\ 584565825460564836279530167452398262582723504220166256671818402486313168189187792969542212\ 049101757196085075106858844201730767102408667492711144920904088412131757268261002709591485\ 892572769623193922808548994645936128594734522557112869973628301289234178756660025395220971\ 552551454810467511328914938148018407394784903305080042952463744828221428366721013966075942\ 176793399501825273207819753276434605496999824553994689519587067068339386727318342025784480\ 812767824268457965573220366984271657187184409113540094514027074844640093106297080444683824\ 377405875474810493604461011348533762134305687849293031921110040424810842901352348537310269\ 206343713905334007912336241882284201504403580321299174976797884816704896804726358250985559\ 799985988186958064670880371662368698113531302487616884846859115258187407737403728723368707\ 323846651707183803490851996303220801277270427901677230978957397647160240115820018502810895\ 154331934225555668095902625013638806356733750900152886422306611378111421987550050293430845\ 245916855621247493144225520107062263328132881734912860608708345845489197324468978356848814\ 153016313843435670624732166396406812362503527093774812335463520844348918966133198354326738\ 496326752080510329079510994322418056607631925724340293558660223517800973234536235348928246\ 383901175664232107529211451027625980008171999768528451504191728443523334216985440123487511\ 813092014431776472273139813296105395494814393977203673426345745101500312996611664855878256\ 912980607401095185355559714095036916705107898036880918260750972195965805299757075605874207\ 106344998902706621017515778393586780555045138364087216847932503796899969299231484446771505\ 66063511739512880228167240763662857429382489", "0x0.d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c271f049361406e4cdd9089ef0715384d6c72\ c4bdd754b2bc1ecc5c199c686439032cbb16813342ded4cffc19dcab8db34c27b6168ceb88298ed572b191c8f3\ 05743e1f293dfd41f82b0210f65e6163e5434a891261dc7440e2093b1a156a8e05ae8319d2ff97641b5a7fd78f\ 7cf6dc96868e4130d819e5f2ca3a94c6112e9b5a5801bfe4a11e5a42582d5081ac41fa9b728b4ac35e244d5a85\ 69a511aa70984b50c4070684a6ac159bdc9325d1fde1271f02527cc064b69ec913f415531392712d3fb1c34ed3\ c075bef86d6a059f7a22834767ad03e455760919f51006e91df313136656ef23512f1e105bfa2eb5f06fef2837\ 36474330c7c0bac59657d9963f201efba238eaa0c933f0989864323803599e6dc26aef9c7fa5f268f531f503b3\ af964f171b4980fb0cb845df9f68e7393d3471de7195e248e795b9225a0b176c4deecd2390e150a7ca76c1f3dd\ f86cce329f30053a570d269f38de7c3d7475abb273c84dbbbc9e2469b486e86b3f792f8c039bb07b126676c07b\ 33332595fc7d9f877476f088f075265ed7f675bbcc8e6d8ada2f52abb307a3ebc73a2639ecf3287b4c2a68c18e\ 03b158d2ddfabb3f14826dc5a16e5b0d15b6dc83d22f25505ed5a58a81e4fb874d6fa23df6989cd319003989f0\ 8e14d201f949eff049dcb40d2e4ee6a09a9cb8a8ed98c3cf66f7aadd8ab1107e0777170849e24b32d5342ba17d\ e3db8816045423a00fd6feebadc650d05a47f26ef7b184793feab8a0f72fda537794ec1db7ba60bae81a34044d\ f64da299718b09ab02787b15c0cc87c047594f33d4955d2fa6b272582fedc6252a9c2143e9b5c510a52bd37d1b\ 8b03a88f3f3981ee8fb77b336a301bcf19ad8bffac5815954340690f235ebc2f763fd7beff9bee4393243bd467\ 8ba486780982c6ddb3e52a1a7c220d85f80cd263b3c39039c67d2105008bfc82b656b0a569fef2af16435a097a\ 066864fa7f39d24e36a9e4ee1e48fb7520d941e1c3d998a423d7323624de96e0862f19531652e4a4c7fd843112\ 48118ebe1f71610abf8bd41e859c8fd1087afdb24745cb6cd03af58f79904a9b1aa2e2dc5571c564cc3276b76f\ a2003f5fc9e83956ab4c37848e2537ea2bbb81600b49441a0246fa5972e98b073069cc693abad679c6e5af259b\ 9a3418f9a2c0eb07f4bee61de65e0c4cac92dc7e814e9e710fef4117be6ceae26e295b32403823e99471d39256\ 22751aa788ff76be3ade62a196e546ab1f24bb973e914cc5b9fdf6baa5b5ae0ec5513fb76772007bacb0b1d514\ f9045622b309cf750c162aaf417ff93536fc9a21c95909021f3f92c404825a0615e27cc5b5c309636ee7d0ade9\ e7974b4a7c5dbb74ac75f2adc6929afe15b9891b7d9217c366f601132c9e5e7f7a2d05a80035e9cebc097affd5\ 0a7e73a3fc24a15efc02146f08b666cb29b7855e06e9bff03beaf3d27b2d8c1986ee6b77d51078df5b8194951c\ 2f9cc61e37de23b068699ee0af89a23c09235b52b15c7003c8a4ebb021a6e1e30411487ce16815548f919f2288\ 209aca02dad50dae05cf6669f49c173ec9e988c850db3ab92226478c1a6349300af076f75432e01bcebf00fc94\ e171e049a257068125002014c8ec94daab6f5fc58d480f3ea11937610c5c72e1ba18d8440d6c4f583cb3453b9d\ 9f5effe308d79101081796211c92bf38dcd19353835166bb09cc2bd541798f16eaa8df0183d#10000", Greater, ); let gauss_constant_f32 = Float::gauss_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(gauss_constant_f32.to_string(), "0.83462685"); assert_eq!(to_hex_string(&gauss_constant_f32), "0x0.d5aa1b#24"); assert_eq!(gauss_constant_f32, f32::GAUSS_CONSTANT); let gauss_constant_f64 = Float::gauss_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(gauss_constant_f64.to_string(), "0.8346268416740732"); assert_eq!(to_hex_string(&gauss_constant_f64), "0x0.d5aa1acd5a9a20#53"); assert_eq!(gauss_constant_f64, f64::GAUSS_CONSTANT); } #[test] #[should_panic] fn gauss_constant_prec_fail_1() { Float::gauss_constant_prec(0); } fn test_gauss_constant_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::gauss_constant_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_gauss_constant_prec_round() { test_gauss_constant_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_gauss_constant_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_gauss_constant_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_gauss_constant_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_gauss_constant_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Greater); test_gauss_constant_prec_round_helper(2, Floor, "0.8", "0x0.c#2", Less); test_gauss_constant_prec_round_helper(2, Ceiling, "1.0", "0x1.0#2", Greater); test_gauss_constant_prec_round_helper(2, Down, "0.8", "0x0.c#2", Less); test_gauss_constant_prec_round_helper(2, Up, "1.0", "0x1.0#2", Greater); test_gauss_constant_prec_round_helper(2, Nearest, "0.8", "0x0.c#2", Less); test_gauss_constant_prec_round_helper(3, Floor, "0.8", "0x0.c#3", Less); test_gauss_constant_prec_round_helper(3, Ceiling, "0.9", "0x0.e#3", Greater); test_gauss_constant_prec_round_helper(3, Down, "0.8", "0x0.c#3", Less); test_gauss_constant_prec_round_helper(3, Up, "0.9", "0x0.e#3", Greater); test_gauss_constant_prec_round_helper(3, Nearest, "0.9", "0x0.e#3", Greater); test_gauss_constant_prec_round_helper(4, Floor, "0.81", "0x0.d#4", Less); test_gauss_constant_prec_round_helper(4, Ceiling, "0.88", "0x0.e#4", Greater); test_gauss_constant_prec_round_helper(4, Down, "0.81", "0x0.d#4", Less); test_gauss_constant_prec_round_helper(4, Up, "0.88", "0x0.e#4", Greater); test_gauss_constant_prec_round_helper(4, Nearest, "0.81", "0x0.d#4", Less); test_gauss_constant_prec_round_helper(5, Floor, "0.81", "0x0.d0#5", Less); test_gauss_constant_prec_round_helper(5, Ceiling, "0.84", "0x0.d8#5", Greater); test_gauss_constant_prec_round_helper(5, Down, "0.81", "0x0.d0#5", Less); test_gauss_constant_prec_round_helper(5, Up, "0.84", "0x0.d8#5", Greater); test_gauss_constant_prec_round_helper(5, Nearest, "0.84", "0x0.d8#5", Greater); test_gauss_constant_prec_round_helper(6, Floor, "0.83", "0x0.d4#6", Less); test_gauss_constant_prec_round_helper(6, Ceiling, "0.84", "0x0.d8#6", Greater); test_gauss_constant_prec_round_helper(6, Down, "0.83", "0x0.d4#6", Less); test_gauss_constant_prec_round_helper(6, Up, "0.84", "0x0.d8#6", Greater); test_gauss_constant_prec_round_helper(6, Nearest, "0.83", "0x0.d4#6", Less); test_gauss_constant_prec_round_helper(7, Floor, "0.83", "0x0.d4#7", Less); test_gauss_constant_prec_round_helper(7, Ceiling, "0.836", "0x0.d6#7", Greater); test_gauss_constant_prec_round_helper(7, Down, "0.83", "0x0.d4#7", Less); test_gauss_constant_prec_round_helper(7, Up, "0.836", "0x0.d6#7", Greater); test_gauss_constant_prec_round_helper(7, Nearest, "0.836", "0x0.d6#7", Greater); test_gauss_constant_prec_round_helper(8, Floor, "0.832", "0x0.d5#8", Less); test_gauss_constant_prec_round_helper(8, Ceiling, "0.836", "0x0.d6#8", Greater); test_gauss_constant_prec_round_helper(8, Down, "0.832", "0x0.d5#8", Less); test_gauss_constant_prec_round_helper(8, Up, "0.836", "0x0.d6#8", Greater); test_gauss_constant_prec_round_helper(8, Nearest, "0.836", "0x0.d6#8", Greater); test_gauss_constant_prec_round_helper(9, Floor, "0.834", "0x0.d58#9", Less); test_gauss_constant_prec_round_helper(9, Ceiling, "0.836", "0x0.d60#9", Greater); test_gauss_constant_prec_round_helper(9, Down, "0.834", "0x0.d58#9", Less); test_gauss_constant_prec_round_helper(9, Up, "0.836", "0x0.d60#9", Greater); test_gauss_constant_prec_round_helper(9, Nearest, "0.834", "0x0.d58#9", Less); test_gauss_constant_prec_round_helper(10, Floor, "0.834", "0x0.d58#10", Less); test_gauss_constant_prec_round_helper(10, Ceiling, "0.835", "0x0.d5c#10", Greater); test_gauss_constant_prec_round_helper(10, Down, "0.834", "0x0.d58#10", Less); test_gauss_constant_prec_round_helper(10, Up, "0.835", "0x0.d5c#10", Greater); test_gauss_constant_prec_round_helper(10, Nearest, "0.835", "0x0.d5c#10", Greater); test_gauss_constant_prec_round_helper( 100, Floor, "0.834626841674073186281429732799", "0x0.d5aa1acd5a9a1f6b126ed4160#100", Less, ); test_gauss_constant_prec_round_helper( 100, Ceiling, "0.8346268416740731862814297328", "0x0.d5aa1acd5a9a1f6b126ed4161#100", Greater, ); test_gauss_constant_prec_round_helper( 100, Down, "0.834626841674073186281429732799", "0x0.d5aa1acd5a9a1f6b126ed4160#100", Less, ); test_gauss_constant_prec_round_helper( 100, Up, "0.8346268416740731862814297328", "0x0.d5aa1acd5a9a1f6b126ed4161#100", Greater, ); test_gauss_constant_prec_round_helper( 100, Nearest, "0.834626841674073186281429732799", "0x0.d5aa1acd5a9a1f6b126ed4160#100", Less, ); } #[test] #[should_panic] fn gauss_constant_prec_round_fail_1() { Float::gauss_constant_prec_round(0, Floor); } #[test] #[should_panic] fn gauss_constant_prec_round_fail_2() { Float::gauss_constant_prec_round(1, Exact); } #[test] #[should_panic] fn gauss_constant_prec_round_fail_3() { Float::gauss_constant_prec_round(1000, Exact); } #[test] fn gauss_constant_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (gauss_constant, o) = Float::gauss_constant_prec(prec); assert!(gauss_constant.is_valid()); assert_eq!(gauss_constant.get_prec(), Some(prec)); assert_eq!( gauss_constant.get_exponent(), Some(if prec == 1 { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (gauss_constant_alt, o_alt) = Float::gauss_constant_prec_round(prec, Ceiling); let mut next_upper = gauss_constant.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(gauss_constant_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !gauss_constant.is_power_of_2() { let (gauss_constant_alt, o_alt) = Float::gauss_constant_prec_round(prec, Floor); let mut next_lower = gauss_constant.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(gauss_constant_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (gauss_constant_alt, o_alt) = Float::gauss_constant_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&gauss_constant_alt), ComparableFloatRef(&gauss_constant) ); assert_eq!(o_alt, o); }); } #[test] fn gauss_constant_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (gauss_constant, o) = Float::gauss_constant_prec_round(prec, rm); assert!(gauss_constant.is_valid()); assert_eq!(gauss_constant.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 1, _ => 0, }; assert_eq!(gauss_constant.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (gauss_constant_alt, o_alt) = Float::gauss_constant_prec_round(prec, Ceiling); let mut next_upper = gauss_constant.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(gauss_constant_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !gauss_constant.is_power_of_2() { let (gauss_constant_alt, o_alt) = Float::gauss_constant_prec_round(prec, Floor); let mut next_lower = gauss_constant.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(gauss_constant_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::gauss_constant_prec_round(prec, Exact)); }); test_constant(Float::gauss_constant_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/lemniscate_constant.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::LemniscateConstant; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::lemniscate_constant::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_lemniscate_constant_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::lemniscate_constant_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = lemniscate_constant_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_lemniscate_constant_prec() { test_lemniscate_constant_prec_helper(1, "2.0", "0x2.0#1", Less); test_lemniscate_constant_prec_helper(2, "3.0", "0x3.0#2", Greater); test_lemniscate_constant_prec_helper(3, "2.5", "0x2.8#3", Less); test_lemniscate_constant_prec_helper(4, "2.5", "0x2.8#4", Less); test_lemniscate_constant_prec_helper(5, "2.6", "0x2.a#5", Greater); test_lemniscate_constant_prec_helper(6, "2.62", "0x2.a#6", Greater); test_lemniscate_constant_prec_helper(7, "2.62", "0x2.a0#7", Greater); test_lemniscate_constant_prec_helper(8, "2.62", "0x2.a0#8", Greater); test_lemniscate_constant_prec_helper(9, "2.625", "0x2.a0#9", Greater); test_lemniscate_constant_prec_helper(10, "2.621", "0x2.9f#10", Less); test_lemniscate_constant_prec_helper( 100, "2.62205755429211981046483958989", "0x2.9f3f29f3ea160dcf30eed7580#100", Less, ); test_lemniscate_constant_prec_helper( 1000, "2.622057554292119810464839589891119413682754951431623162816821703800790587070414250230295\ 532961429093446135752671783218055608956901393935694701119434775235840422641497164906951936\ 899979932146072383121390810206221897429600856554539772305369549710288888325526487021329012\ 0975408331285685117297522292142966", "0x2.9f3f29f3ea160dcf30eed75811b3c2f6d7172e48e43735af6b46c7af912d10e70017b44f6b10c20e6755e\ 81d92714d02ce28c9bbc0133ee370554ff5165f91aae132697ee64025bd01da354b8da35c1ca7832784a9965a0\ c14398dc6fb92c5154e84157fa74aec0c44dfda20393fe782139b91b083fc85b1441ac82ad0#1000", Less, ); test_lemniscate_constant_prec_helper( 10000, "2.622057554292119810464839589891119413682754951431623162816821703800790587070414250230295\ 532961429093446135752671783218055608956901393935694701119434775235840422641497164906951936\ 899979932146072383121390810206221897429600856554539772305369549710288888325526487021329012\ 097540833128568511729752229214296692430513968456455539432881415381331735108409226312132476\ 667633414509988603429421479224714487963907872564189521811027252516629964333384660679333635\ 093139808526237739409142626489848034804572541477046175421256342129955863129980224054609012\ 091499139897885645312480971101149665075060542093841723886900040274785389625483030580303946\ 324783219558325522973037191341918983592199914229536672569106861130938134980725552913015093\ 730332611087045814240765781886530766932476940761626721636249549480066760961388122322476925\ 591018705775743614648912879832686662030731373313562107612636379245785801781364105361306093\ 563472025022592312041202668270457723044608378953311357002940577442011806826257962983642671\ 092116198597298460755620828986569905715850585969733482498916979139661512076092673544847646\ 574626457769227556279085403488486299631791644074183032890572244174725314174445875123605657\ 139575363059725889282920861276365948025081705994780553810740323485381958708594579092174018\ 668477776969917734589963845805236673259560797055893212070139745771343010329460928029259114\ 281387388493544876912962400450451515749437725842216728515086072450581997727624380905274299\ 795351792018910957399605991273238903791116648437850911342937302632750071201301892980462180\ 428765649352238455214584305436298513850108631443435366399087818335289725057991586901139218\ 731261235482234682842959686621093089202655982151707327457126997244722591053622446697155585\ 523244205556551378985416014007281696154803764953004010586969769798728528544268595900874210\ 615976672889856196920646383327838417979669834893047455706005883206470466312323973364023277\ 796282492416941692491715034784541889387264509022763917623129944975660994166520078299733003\ 514497680346375538989464128500976201473352363956758954456057294389704660492210734900562422\ 060698049424698227273322272545152596399605261093570054581266506375784426587891009902248739\ 074851475335571668858945648604938903484149255083213830273958314785697922542663980952768924\ 339176421212403458061264319698865734211695958669092740058571756733772940260843870335168806\ 554093029896061847165969615210879733103894090573687904026615017392722182113253614379462748\ 410822722172415291174195706198674247582236389438854755351468899984473586928701255109272056\ 897315524697141375285481897383672357481534008060452330772039824202794480385098376136184356\ 879523471104690616561399028704017447178011844138034863898042145300962033247526574931328554\ 943387329065193422836581434847505032876745487649716644131511122812960672857587623568606457\ 132192794260190549677753958426178724331815736858905292945584979487114184373394133441249801\ 511678382932856516301228572505799118357873322849053225342038152978949939297661715113526220\ 8853282485258038240456468938147672657060189", "0x2.9f3f29f3ea160dcf30eed75811b3c2f6d7172e48e43735af6b46c7af912d10e70017b44f6b10c20e6755e\ 81d92714d02ce28c9bbc0133ee370554ff5165f91aae132697ee64025bd01da354b8da35c1ca7832784a9965a0\ c14398dc6fb92c5154e84157fa74aec0c44dfda20393fe782139b91b083fc85b1441ac82ad11541d32c7d05a72\ 3a95453cb09b15964d9b9e2bc05b3b7d29877c9a4b44216c4a2dda21dc33dd433090e44a06c3c1f481e075fd94\ 21ecc82d065fe31873cf84d0a6f66b94a68ca0edf58ab7118c279921d8f0b918ce81b4b6f957b508ec630ae014\ 066fb52b9825f76ccb6bc78c38c4492c0220c805403b6d28ebc28cff3c6b354eed64d86b282b6c5045ee4a48d2\ 39d222d69aa29ebba7e23d6ca59093bf052e76d6da8e7567ecbf817d2c1225ec79a3ca30176f7278fe02993af2\ 4f6729cf38a835f6546826d4845bb03bd57075dcb0902f9a09225354aa620358678e3510c30ed57970038d983e\ b399d694188f2bd2a3cdd0195478f25df26f7f6d941552566f3efbb6f49cd4a9ffe631175ae021fa25809ab898\ 26df98a555338ac2029fc9ee45c5099d7284ef412f878425791628a818f7c826883b3ad7198d30c5f83a7738d7\ 1de0a3310c7cc5e889941fc475a5d9145798b2ecc4c57c6ab448267648a64942b2ae1b4a2b8f2735acdc0e72e6\ 826ee5b166c4c05d874f61c2a55ce9d1ebafc1c0375a43b0df0189b326566e625334856a6d43bc6256ac22f546\ 6d302d1d2242310bf0118124c9cb1bcc69be3a951b4f9f86c419494311bfc1fb0f2d6dd5768703d859fcfe1b4d\ 6b959e9ee6767cf7a152f34269e166cf850fc2d0278f0ba25bf64ed7cfe799d7a324cf238084d10ec8dc667d8f\ 92403b94640db67e3c63473f683fe6a3881b3997069fe1ad958a5433e7720102a273512d2b28d4a46699a3cb1f\ 42532f37658965357b95e149d90c83c02453c15517ecbb80c88df5b1a8e0ee86c0d4d082758058cb2664c62dae\ f9ed89bd69c0d6f66381e3f93d7474e266a2bf1dc97c19464cbbd0793bd74674dc03e28a2ab5e1d50da6fc8b09\ 76730ce30603718f3072e1081edfb2dbe178162099ea48bf81c3341f1421f77008833a0b30ad6cdad21d2beb60\ e79f8c891d70c88d7fcf6dfca38032e48280e8d3f40c5a0ab27dc76c32113d090c4686e0c5af335ee8e02bf167\ 565f64587b00b6eeb163f782ee0f30a13c6386b94732d3d795261b00f328f20061e7dd29e5ba1649815e8b86f8\ 749cf82d7ae468a30fc75a44213e70e017de72b2f73bd8698855f4d0d0806980ddd6d3a2d5257165fd1f73ea29\ d2c6b232528aa4f54a711deccfbe0a41aad688b4c077d9d7bce4d8d4bf0a22d61a55d4f97f147c6f45f5d03023\ 4fd8ba98f9dec471598ea5fa3f0f35ef0e006bcbfa54050e6e4ca5d8734c24cda360ea64146d27c81d0e05d61d\ 577cf76b8b4ed519262488699e7a5a0838dbc88c3be2fc7c488d855b0f9ccfe111091777beb081c1ea5ee0853b\ 3ae2d4ea046a292e33e9ab99d3734355a7bb39462571a408ad450e83de0ee52fdb5aa8d38706117b2c87b03ab5\ 868eff0e9c6c3ab4afce9ddca3db9b0c66305ca71fd6a7842fdb2dc86990eb4bc0b7fde91f503e8788a772ab33\ 41473c80c1503eeca8c1534d984be33f86f904239944078141f06fe1dee3e1eaae3cb2f1984df30e54f0dc6c3c\ ac27892c1ee783c1d26589418270060cdb2077a890b369215342641df45d1210b1cc551b780#10000", Greater, ); let lemniscate_constant_f32 = Float::lemniscate_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(lemniscate_constant_f32.to_string(), "2.6220574"); assert_eq!(to_hex_string(&lemniscate_constant_f32), "0x2.9f3f28#24"); assert_eq!(lemniscate_constant_f32, f32::LEMNISCATE_CONSTANT); let lemniscate_constant_f64 = Float::lemniscate_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(lemniscate_constant_f64.to_string(), "2.6220575542921196"); assert_eq!( to_hex_string(&lemniscate_constant_f64), "0x2.9f3f29f3ea160#53" ); assert_eq!(lemniscate_constant_f64, f64::LEMNISCATE_CONSTANT); } #[test] #[should_panic] fn lemniscate_constant_prec_fail_1() { Float::lemniscate_constant_prec(0); } fn test_lemniscate_constant_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::lemniscate_constant_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = lemniscate_constant_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_lemniscate_constant_prec_round() { test_lemniscate_constant_prec_round_helper(1, Floor, "2.0", "0x2.0#1", Less); test_lemniscate_constant_prec_round_helper(1, Ceiling, "4.0", "0x4.0#1", Greater); test_lemniscate_constant_prec_round_helper(1, Down, "2.0", "0x2.0#1", Less); test_lemniscate_constant_prec_round_helper(1, Up, "4.0", "0x4.0#1", Greater); test_lemniscate_constant_prec_round_helper(1, Nearest, "2.0", "0x2.0#1", Less); test_lemniscate_constant_prec_round_helper(2, Floor, "2.0", "0x2.0#2", Less); test_lemniscate_constant_prec_round_helper(2, Ceiling, "3.0", "0x3.0#2", Greater); test_lemniscate_constant_prec_round_helper(2, Down, "2.0", "0x2.0#2", Less); test_lemniscate_constant_prec_round_helper(2, Up, "3.0", "0x3.0#2", Greater); test_lemniscate_constant_prec_round_helper(2, Nearest, "3.0", "0x3.0#2", Greater); test_lemniscate_constant_prec_round_helper(3, Floor, "2.5", "0x2.8#3", Less); test_lemniscate_constant_prec_round_helper(3, Ceiling, "3.0", "0x3.0#3", Greater); test_lemniscate_constant_prec_round_helper(3, Down, "2.5", "0x2.8#3", Less); test_lemniscate_constant_prec_round_helper(3, Up, "3.0", "0x3.0#3", Greater); test_lemniscate_constant_prec_round_helper(3, Nearest, "2.5", "0x2.8#3", Less); test_lemniscate_constant_prec_round_helper(4, Floor, "2.5", "0x2.8#4", Less); test_lemniscate_constant_prec_round_helper(4, Ceiling, "2.8", "0x2.c#4", Greater); test_lemniscate_constant_prec_round_helper(4, Down, "2.5", "0x2.8#4", Less); test_lemniscate_constant_prec_round_helper(4, Up, "2.8", "0x2.c#4", Greater); test_lemniscate_constant_prec_round_helper(4, Nearest, "2.5", "0x2.8#4", Less); test_lemniscate_constant_prec_round_helper(5, Floor, "2.5", "0x2.8#5", Less); test_lemniscate_constant_prec_round_helper(5, Ceiling, "2.6", "0x2.a#5", Greater); test_lemniscate_constant_prec_round_helper(5, Down, "2.5", "0x2.8#5", Less); test_lemniscate_constant_prec_round_helper(5, Up, "2.6", "0x2.a#5", Greater); test_lemniscate_constant_prec_round_helper(5, Nearest, "2.6", "0x2.a#5", Greater); test_lemniscate_constant_prec_round_helper(6, Floor, "2.56", "0x2.9#6", Less); test_lemniscate_constant_prec_round_helper(6, Ceiling, "2.62", "0x2.a#6", Greater); test_lemniscate_constant_prec_round_helper(6, Down, "2.56", "0x2.9#6", Less); test_lemniscate_constant_prec_round_helper(6, Up, "2.62", "0x2.a#6", Greater); test_lemniscate_constant_prec_round_helper(6, Nearest, "2.62", "0x2.a#6", Greater); test_lemniscate_constant_prec_round_helper(7, Floor, "2.59", "0x2.98#7", Less); test_lemniscate_constant_prec_round_helper(7, Ceiling, "2.62", "0x2.a0#7", Greater); test_lemniscate_constant_prec_round_helper(7, Down, "2.59", "0x2.98#7", Less); test_lemniscate_constant_prec_round_helper(7, Up, "2.62", "0x2.a0#7", Greater); test_lemniscate_constant_prec_round_helper(7, Nearest, "2.62", "0x2.a0#7", Greater); test_lemniscate_constant_prec_round_helper(8, Floor, "2.61", "0x2.9c#8", Less); test_lemniscate_constant_prec_round_helper(8, Ceiling, "2.62", "0x2.a0#8", Greater); test_lemniscate_constant_prec_round_helper(8, Down, "2.61", "0x2.9c#8", Less); test_lemniscate_constant_prec_round_helper(8, Up, "2.62", "0x2.a0#8", Greater); test_lemniscate_constant_prec_round_helper(8, Nearest, "2.62", "0x2.a0#8", Greater); test_lemniscate_constant_prec_round_helper(9, Floor, "2.617", "0x2.9e#9", Less); test_lemniscate_constant_prec_round_helper(9, Ceiling, "2.625", "0x2.a0#9", Greater); test_lemniscate_constant_prec_round_helper(9, Down, "2.617", "0x2.9e#9", Less); test_lemniscate_constant_prec_round_helper(9, Up, "2.625", "0x2.a0#9", Greater); test_lemniscate_constant_prec_round_helper(9, Nearest, "2.625", "0x2.a0#9", Greater); test_lemniscate_constant_prec_round_helper(10, Floor, "2.621", "0x2.9f#10", Less); test_lemniscate_constant_prec_round_helper(10, Ceiling, "2.625", "0x2.a0#10", Greater); test_lemniscate_constant_prec_round_helper(10, Down, "2.621", "0x2.9f#10", Less); test_lemniscate_constant_prec_round_helper(10, Up, "2.625", "0x2.a0#10", Greater); test_lemniscate_constant_prec_round_helper(10, Nearest, "2.621", "0x2.9f#10", Less); test_lemniscate_constant_prec_round_helper( 100, Floor, "2.62205755429211981046483958989", "0x2.9f3f29f3ea160dcf30eed7580#100", Less, ); test_lemniscate_constant_prec_round_helper( 100, Ceiling, "2.622057554292119810464839589893", "0x2.9f3f29f3ea160dcf30eed7584#100", Greater, ); test_lemniscate_constant_prec_round_helper( 100, Down, "2.62205755429211981046483958989", "0x2.9f3f29f3ea160dcf30eed7580#100", Less, ); test_lemniscate_constant_prec_round_helper( 100, Up, "2.622057554292119810464839589893", "0x2.9f3f29f3ea160dcf30eed7584#100", Greater, ); test_lemniscate_constant_prec_round_helper( 100, Nearest, "2.62205755429211981046483958989", "0x2.9f3f29f3ea160dcf30eed7580#100", Less, ); } #[test] #[should_panic] fn lemniscate_constant_prec_round_fail_1() { Float::lemniscate_constant_prec_round(0, Floor); } #[test] #[should_panic] fn lemniscate_constant_prec_round_fail_2() { Float::lemniscate_constant_prec_round(1, Exact); } #[test] #[should_panic] fn lemniscate_constant_prec_round_fail_3() { Float::lemniscate_constant_prec_round(1000, Exact); } #[test] fn lemniscate_constant_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (lemniscate_constant, o) = Float::lemniscate_constant_prec(prec); assert!(lemniscate_constant.is_valid()); assert_eq!(lemniscate_constant.get_prec(), Some(prec)); assert_eq!(lemniscate_constant.get_exponent(), Some(2)); assert_ne!(o, Equal); if o == Less { let (lemniscate_constant_alt, o_alt) = Float::lemniscate_constant_prec_round(prec, Ceiling); let mut next_upper = lemniscate_constant.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(lemniscate_constant_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !lemniscate_constant.is_power_of_2() { let (lemniscate_constant_alt, o_alt) = Float::lemniscate_constant_prec_round(prec, Floor); let mut next_lower = lemniscate_constant.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(lemniscate_constant_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (lemniscate_constant_alt, o_alt) = Float::lemniscate_constant_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&lemniscate_constant_alt), ComparableFloatRef(&lemniscate_constant) ); assert_eq!(o_alt, o); let (lemniscate_constant_alt, o_alt) = lemniscate_constant_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&lemniscate_constant_alt), ComparableFloatRef(&lemniscate_constant) ); assert_eq!(o_alt, o); }); } #[test] fn lemniscate_constant_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (lemniscate_constant, o) = Float::lemniscate_constant_prec_round(prec, rm); assert!(lemniscate_constant.is_valid()); assert_eq!(lemniscate_constant.get_prec(), Some(prec)); assert_eq!( lemniscate_constant.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 3 } else { 2 }) ); assert_ne!(o, Equal); if o == Less { let (lemniscate_constant_alt, o_alt) = Float::lemniscate_constant_prec_round(prec, Ceiling); let mut next_upper = lemniscate_constant.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(lemniscate_constant_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !lemniscate_constant.is_power_of_2() { let (lemniscate_constant_alt, o_alt) = Float::lemniscate_constant_prec_round(prec, Floor); let mut next_lower = lemniscate_constant.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(lemniscate_constant_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (lemniscate_constant_alt, o_alt) = lemniscate_constant_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&lemniscate_constant_alt), ComparableFloatRef(&lemniscate_constant) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::lemniscate_constant_prec_round(prec, Exact)); }); test_constant(Float::lemniscate_constant_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/ln_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::{Ln2, Two}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::ln_2::rug_ln_2_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_ln_2_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::ln_2_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = Float::ln_prec(Float::TWO, prec); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); let (rug_x, rug_o) = rug_ln_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_ln_2_prec() { // - in ln_2_prec_round // - in sum // - n2 != n1 + 1 in sum // - n2 == n1 + 1 in sum // - n1 == 0 in sum // - n1 != 0 in sum // - !need_p first time in sum // - v == 0 first time in sum // - can't round in ln_2_prec_round // - need_p first time in sum // - v != 0 first time in sum // - w < v first time in sum // - need_p second time in sum // - w < v second time in sum // - v != 0 second time in sum // - need_p third time in sum // - w >= v first time in sum // - v == 0 second time in sum // - w >= v second time in sum // - !need_p second time in sum // - !need_p third time in sum // - can round in ln_2_prec_round test_ln_2_prec_helper(1, "0.5", "0x0.8#1", Less); test_ln_2_prec_helper(2, "0.8", "0x0.c#2", Greater); test_ln_2_prec_helper(3, "0.8", "0x0.c#3", Greater); test_ln_2_prec_helper(4, "0.7", "0x0.b#4", Less); test_ln_2_prec_helper(5, "0.69", "0x0.b0#5", Less); test_ln_2_prec_helper(6, "0.69", "0x0.b0#6", Less); test_ln_2_prec_helper(7, "0.695", "0x0.b2#7", Greater); test_ln_2_prec_helper(8, "0.691", "0x0.b1#8", Less); test_ln_2_prec_helper(9, "0.693", "0x0.b18#9", Greater); test_ln_2_prec_helper(10, "0.693", "0x0.b18#10", Greater); test_ln_2_prec_helper( 100, "0.693147180559945309417232121458", "0x0.b17217f7d1cf79abc9e3b3980#100", Less, ); test_ln_2_prec_helper( 1000, "0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863\ 326996418687542001481020570685733685520235758130557032670751635075961930727570828371435190\ 307038623891673471123350115364497955239120475172681574932065155524734139525882950453007095\ 3263666426541042391578149520437404", "0x0.b17217f7d1cf79abc9e3b39803f2f6af40f343267298b62d8a0d175b8baafa2be7b876206debac9855955\ 2fb4afa1b10ed2eae35c138214427573b291169b8253e96ca16224ae8c51acbda11317c387eb9ea9bc3b136603\ b256fa0ec7657f74b72ce87b19d6548caf5dfa6bd38303248655fa1872f20e3a2da2d97c50f#1000", Less, ); test_ln_2_prec_helper( 10000, "0.693147180559945309417232121458176568075500134360255254120680009493393621969694715605863\ 326996418687542001481020570685733685520235758130557032670751635075961930727570828371435190\ 307038623891673471123350115364497955239120475172681574932065155524734139525882950453007095\ 326366642654104239157814952043740430385500801944170641671518644712839968171784546957026271\ 631064546150257207402481637773389638550695260668341137273873722928956493547025762652098859\ 693201965058554764703306793654432547632744951250406069438147104689946506220167720424524529\ 612687946546193165174681392672504103802546259656869144192871608293803172714367782654877566\ 485085674077648451464439940461422603193096735402574446070308096085047486638523138181676751\ 438667476647890881437141985494231519973548803751658612753529166100071053558249879414729509\ 293113897155998205654392871700072180857610252368892132449713893203784393530887748259701715\ 591070882368362758984258918535302436342143670611892367891923723146723217205340164925687274\ 778234453534764811494186423867767744060695626573796008670762571991847340226514628379048830\ 620330611446300737194890027436439650025809365194430411911506080948793067865158870900605203\ 468429736193841289652556539686022194122924207574321757489097706752687115817051137009158942\ 665478595964890653058460258668382940022833005382074005677053046787001841624044188332327983\ 863490015631218895606505531512721993983320307514084260914790012651682434438935724727882054\ 862715527418772430024897945401961872339808608316648114909306675193393128904316413706813977\ 764981769748689038877899912965036192707108892641052309247839173735012298424204995689359922\ 066022046549415106139187885744245577510206837030866619480896412186807790208181588580001688\ 115973056186676199187395200766719214592236720602539595436541655311295175989940056000366513\ 567569051245926825743946483168332624901803824240824231452306140963805700702551387702681785\ 163069025513703234053802145019015374029509942262995779647427138157363801729873940704242179\ 972266962979939312706935747240493386530879758721699645129446491883771156701678598804981838\ 896784134938314014073166472765327635919233511233389338709513209059272185471328975470797891\ 384445466676192702885533423429899321803769154973340267546758873236778342916191810430116091\ 695265547859732891763545556742863877463987101912431754255888301206779210280341206879759143\ 081283307230300883494705792496591005860012341561757413272465943068435465211135021544341539\ 955381856522750221424566440006276183303206472725721975152908278568421320795988638967277119\ 552218819046603957009774706512619505278932296088931405625433442552392062030343941777357945\ 592125901992559114844024239012554259003129537051922061506434583787873002035414421785758013\ 236451660709914383145004985896688577222148652882169418127048860758972203216663128378329156\ 763074987298574638928269373509840778049395004933998762647550703162216139034845299424917248\ 373406136622638349368111684167056925214751383930638455371862687797328895558871634429756244\ 75539236636948887782389017498102735655240503", "0x0.b17217f7d1cf79abc9e3b39803f2f6af40f343267298b62d8a0d175b8baafa2be7b876206debac9855955\ 2fb4afa1b10ed2eae35c138214427573b291169b8253e96ca16224ae8c51acbda11317c387eb9ea9bc3b136603\ b256fa0ec7657f74b72ce87b19d6548caf5dfa6bd38303248655fa1872f20e3a2da2d97c50f3fd5c607f4ca11f\ b5bfb90610d30f88fe551a2ee569d6dfc1efa157d2e23de1400b39617460775db8990e5c943e732b479cd33ccc\ c4e659393514c4c1a1e0bd1d6095d25669b333564a3376a9c7f8a5e148e82074db6015cfe7aa30c480a5417350\ d2c955d5179b1e17b9dae313cdb6c606cb1078f735d1b2db31b5f50b5185064c18b4d162db3b365853d7598a19\ 51ae273ee5570b6c68f96983496d4e6d330af889b44a02554731cdc8ea17293d1228a4ef98d6f5177fbcf07552\ 68a5c1f9538b98261affd446b1ca3cf5e9222b88c66d3c5422183edc99421090bbb16faf3d949f236e02b20cee\ 886b905c128d53d0bd2f9621363196af503020060e49908391a0c57339ba2beba7d052ac5b61cc4e9207cef2f0\ ce2d7373958d7622658901e646a95184460dc4e7487156e0c292413d5e361c1696dd24aaebd473826fda0c238b\ 90ab111bbbd67c724972cd18bfbbd9d426c472096e76115c05f6f7cebac9f45aececb72f19c38339d8f6826250\ dea891ef07afff3a892374e175eb4afc8daadd885db6ab03a49bd0dc0b1b31d8a0e23fac5e5767df95884e0642\ 5a41526fac51c3ea8449fe8f70edd062b1a63a6c4c60c52ab33161e238438897a39ce78b63c9f364f5b8aef22e\ c2fee6e0850eca42d06fb0c75df5497e00c554b03d7d2874a000ca8f58d94f0341cbe2ec92156c9f949db4a931\ 6f281501e53daec3f64f1b783154c60320e2ff79333ce3573facc5fdcf11785903155bbd90f023b220224fcd84\ 71bf4f445f0a88a14f0cd976ea354bb20cdb5ccb3db239288d586554e2a0e8a6fe51a8cfaa72ef2ad8a43dc421\ 2b210b779dfe49d7307cc846532e4b9694edad162af053b1751f3a3d091f65665815412b5e8c202461069ac14b\ 958784934b8d6cce1daa50537011aa4fb42b9a3def41bda1f85ef6fdbf2f2d89d2a4b1835278fd9405789f4568\ 12b552879a6168695c12963b0ff01eaab73e5b5c1585318e7624f14a51a4a026b6808292057fd99b66dc085a98\ ac8d8caf9eeeea98a2400cac95f260fd10036f9f91096ac3195220a1a356b2a73b7eaadaf6d605871ef7afb80b\ c423433562e94b12dfab414451579df59eae0517070624012a82962c59cab347f8304d889659e5a9139db14efc\ c30852be3e8fc99f14d1d822dd6e2f76797e30219c8aa9ce8848a886eb3c87b7295988012e8314186edbaf8685\ 6ccd3c3b6ee94e62f110a6783d2aae89ccc3b76fc435a0ce134c2838fd571ec6c1366a992cbb9ac407ddb6c13a\ 4b8d1ecf7567eb0971cc90b5518569f144e67ebe9b42698fea79d89d5c5ed40ac5e3701d7d7725377cf0656907\ fb9b1b16ea8911afbf1ae5a66203d62fd1e7093435b9c277736a70fa8601cf6868a055b2238677a2bfbbd843bf\ a1873f0c446b01b2ae0e98e0e1527a900b1af5e75f87c7cd17af804d933d6f7e1b9e1903d71c7bba0281137609\ 0dd617335dfdd424f2b661cd85063034e341b06e211977b075a8b7808df43bd8eef1fd9678cc0b5e9f60a3eb81\ 747f87e5709468d78ebd2da0116e6b65aeb3be77ee236fdc33bc8e7df1ffc2e2288f8ca9aee#10000", Less, ); let ln_2_f32 = Float::ln_2_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(ln_2_f32.to_string(), "0.69314718"); assert_eq!(to_hex_string(&ln_2_f32), "0x0.b17218#24"); assert_eq!(ln_2_f32, f32::LN_2); let ln_2_f64 = Float::ln_2_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(ln_2_f64.to_string(), "0.6931471805599453"); assert_eq!(to_hex_string(&ln_2_f64), "0x0.b17217f7d1cf78#53"); assert_eq!(ln_2_f64, f64::LN_2); } #[test] #[should_panic] fn ln_2_prec_fail_1() { Float::ln_2_prec(0); } fn test_ln_2_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::ln_2_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = Float::ln_prec_round(Float::TWO, prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_ln_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_ln_2_prec_round() { test_ln_2_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_ln_2_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_ln_2_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_ln_2_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_ln_2_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_ln_2_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_ln_2_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_ln_2_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_ln_2_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_ln_2_prec_round_helper(2, Nearest, "0.8", "0x0.c#2", Greater); test_ln_2_prec_round_helper(3, Floor, "0.6", "0x0.a#3", Less); test_ln_2_prec_round_helper(3, Ceiling, "0.8", "0x0.c#3", Greater); test_ln_2_prec_round_helper(3, Down, "0.6", "0x0.a#3", Less); test_ln_2_prec_round_helper(3, Up, "0.8", "0x0.c#3", Greater); test_ln_2_prec_round_helper(3, Nearest, "0.8", "0x0.c#3", Greater); test_ln_2_prec_round_helper(4, Floor, "0.7", "0x0.b#4", Less); test_ln_2_prec_round_helper(4, Ceiling, "0.75", "0x0.c#4", Greater); test_ln_2_prec_round_helper(4, Down, "0.7", "0x0.b#4", Less); test_ln_2_prec_round_helper(4, Up, "0.75", "0x0.c#4", Greater); test_ln_2_prec_round_helper(4, Nearest, "0.7", "0x0.b#4", Less); test_ln_2_prec_round_helper(5, Floor, "0.69", "0x0.b0#5", Less); test_ln_2_prec_round_helper(5, Ceiling, "0.72", "0x0.b8#5", Greater); test_ln_2_prec_round_helper(5, Down, "0.69", "0x0.b0#5", Less); test_ln_2_prec_round_helper(5, Up, "0.72", "0x0.b8#5", Greater); test_ln_2_prec_round_helper(5, Nearest, "0.69", "0x0.b0#5", Less); test_ln_2_prec_round_helper(6, Floor, "0.69", "0x0.b0#6", Less); test_ln_2_prec_round_helper(6, Ceiling, "0.7", "0x0.b4#6", Greater); test_ln_2_prec_round_helper(6, Down, "0.69", "0x0.b0#6", Less); test_ln_2_prec_round_helper(6, Up, "0.7", "0x0.b4#6", Greater); test_ln_2_prec_round_helper(6, Nearest, "0.69", "0x0.b0#6", Less); test_ln_2_prec_round_helper(7, Floor, "0.69", "0x0.b0#7", Less); test_ln_2_prec_round_helper(7, Ceiling, "0.695", "0x0.b2#7", Greater); test_ln_2_prec_round_helper(7, Down, "0.69", "0x0.b0#7", Less); test_ln_2_prec_round_helper(7, Up, "0.695", "0x0.b2#7", Greater); test_ln_2_prec_round_helper(7, Nearest, "0.695", "0x0.b2#7", Greater); test_ln_2_prec_round_helper(8, Floor, "0.691", "0x0.b1#8", Less); test_ln_2_prec_round_helper(8, Ceiling, "0.695", "0x0.b2#8", Greater); test_ln_2_prec_round_helper(8, Down, "0.691", "0x0.b1#8", Less); test_ln_2_prec_round_helper(8, Up, "0.695", "0x0.b2#8", Greater); test_ln_2_prec_round_helper(8, Nearest, "0.691", "0x0.b1#8", Less); test_ln_2_prec_round_helper(9, Floor, "0.691", "0x0.b10#9", Less); test_ln_2_prec_round_helper(9, Ceiling, "0.693", "0x0.b18#9", Greater); test_ln_2_prec_round_helper(9, Down, "0.691", "0x0.b10#9", Less); test_ln_2_prec_round_helper(9, Up, "0.693", "0x0.b18#9", Greater); test_ln_2_prec_round_helper(9, Nearest, "0.693", "0x0.b18#9", Greater); test_ln_2_prec_round_helper(10, Floor, "0.692", "0x0.b14#10", Less); test_ln_2_prec_round_helper(10, Ceiling, "0.693", "0x0.b18#10", Greater); test_ln_2_prec_round_helper(10, Down, "0.692", "0x0.b14#10", Less); test_ln_2_prec_round_helper(10, Up, "0.693", "0x0.b18#10", Greater); test_ln_2_prec_round_helper(10, Nearest, "0.693", "0x0.b18#10", Greater); test_ln_2_prec_round_helper( 100, Floor, "0.693147180559945309417232121458", "0x0.b17217f7d1cf79abc9e3b3980#100", Less, ); test_ln_2_prec_round_helper( 100, Ceiling, "0.693147180559945309417232121459", "0x0.b17217f7d1cf79abc9e3b3981#100", Greater, ); test_ln_2_prec_round_helper( 100, Down, "0.693147180559945309417232121458", "0x0.b17217f7d1cf79abc9e3b3980#100", Less, ); test_ln_2_prec_round_helper( 100, Up, "0.693147180559945309417232121459", "0x0.b17217f7d1cf79abc9e3b3981#100", Greater, ); test_ln_2_prec_round_helper( 100, Nearest, "0.693147180559945309417232121458", "0x0.b17217f7d1cf79abc9e3b3980#100", Less, ); } #[test] #[should_panic] fn ln_2_prec_round_fail_1() { Float::ln_2_prec_round(0, Floor); } #[test] #[should_panic] fn ln_2_prec_round_fail_2() { Float::ln_2_prec_round(1, Exact); } #[test] #[should_panic] fn ln_2_prec_round_fail_3() { Float::ln_2_prec_round(1000, Exact); } #[test] fn ln_2_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (ln_2, o) = Float::ln_2_prec(prec); assert!(ln_2.is_valid()); assert_eq!(ln_2.get_prec(), Some(prec)); assert_eq!(ln_2.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (ln_2_alt, o_alt) = Float::ln_2_prec_round(prec, Ceiling); let mut next_upper = ln_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(ln_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !ln_2.is_power_of_2() { let (ln_2_alt, o_alt) = Float::ln_2_prec_round(prec, Floor); let mut next_lower = ln_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(ln_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (ln_2_alt, o_alt) = Float::ln_2_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&ln_2_alt), ComparableFloatRef(&ln_2)); assert_eq!(o_alt, o); let (ln_2_alt, o_alt) = Float::ln_prec(Float::TWO, prec); assert_eq!(ComparableFloatRef(&ln_2_alt), ComparableFloatRef(&ln_2)); assert_eq!(o_alt, o); let (rug_ln_2, rug_o) = rug_ln_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln_2)), ComparableFloatRef(&ln_2) ); assert_eq!(rug_o, o); }); } #[test] fn ln_2_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (ln_2, o) = Float::ln_2_prec_round(prec, rm); assert!(ln_2.is_valid()); assert_eq!(ln_2.get_prec(), Some(prec)); assert_eq!( ln_2.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (ln_2_alt, o_alt) = Float::ln_2_prec_round(prec, Ceiling); let mut next_upper = ln_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(ln_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !ln_2.is_power_of_2() { let (ln_2_alt, o_alt) = Float::ln_2_prec_round(prec, Floor); let mut next_lower = ln_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(ln_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (ln_2_alt, o_alt) = Float::ln_prec_round(Float::TWO, prec, rm); assert_eq!(ComparableFloatRef(&ln_2_alt), ComparableFloatRef(&ln_2)); assert_eq!(o_alt, o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_ln_2, rug_o) = rug_ln_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_ln_2)), ComparableFloatRef(&ln_2) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::ln_2_prec_round(prec, Exact)); }); test_constant(Float::ln_2_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/log_2_e.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Log2E; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::log_2_e::log_2_e_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_log_2_e_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::log_2_e_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = log_2_e_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_log_2_e_prec() { test_log_2_e_prec_helper(1, "1.0", "0x1.0#1", Less); test_log_2_e_prec_helper(2, "1.5", "0x1.8#2", Greater); test_log_2_e_prec_helper(3, "1.5", "0x1.8#3", Greater); test_log_2_e_prec_helper(4, "1.5", "0x1.8#4", Greater); test_log_2_e_prec_helper(5, "1.44", "0x1.7#5", Less); test_log_2_e_prec_helper(6, "1.44", "0x1.70#6", Less); test_log_2_e_prec_helper(7, "1.44", "0x1.70#7", Less); test_log_2_e_prec_helper(8, "1.445", "0x1.72#8", Greater); test_log_2_e_prec_helper(9, "1.441", "0x1.71#9", Less); test_log_2_e_prec_helper(10, "1.443", "0x1.718#10", Greater); test_log_2_e_prec_helper( 100, "1.442695040888963407359924681003", "0x1.71547652b82fe1777d0ffda0e#100", Greater, ); test_log_2_e_prec_helper( 1000, "1.442695040888963407359924681001892137426645954152985934135449406931109219181185079885526\ 622893506344496997518309652544255593101687168359642720662158223479336274537369884718493630\ 701387663532015533894318916664837643128615424047478422289497904795091530351338588054968865\ 8930969963680361105110756308441454", "0x1.71547652b82fe1777d0ffda0d23a7d11d6aef551bad2b4b1164a2cd9a342648fbc3887eeaa2ed9ac49b25\ eeb82d7c167d52173cc1895213f897f5e06a7be73665fc529264c2fb3ab643687aaf3ab440c16bd777e75050a8\ d1a39e8af56c64a7833352906deb692ce4f199e108cf392819cfc406b19abb71ec25e11f75c#1000", Less, ); test_log_2_e_prec_helper( 10000, "1.442695040888963407359924681001892137426645954152985934135449406931109219181185079885526\ 622893506344496997518309652544255593101687168359642720662158223479336274537369884718493630\ 701387663532015533894318916664837643128615424047478422289497904795091530351338588054968865\ 893096996368036110511075630844145427215828344941891933908577715790044171280246848341374522\ 695182369011239094034459968539906113421722886278029158010630061976762445652605995073753240\ 625655815475938178305239725510724813077156267545807578171330193573006168761937372982675897\ 415623817983567103443489750680705518088486561386832917732182934913968431059345402202518636\ 934526269215095597191002219679224321433424494179071455118499385921221675365311300774632767\ 206461233741108211913794433398480579310912877609670200375758998158851806126788099760956252\ 507841024847056900768768058461327865474782027808659462060910749015324819969730579015272324\ 787298740981254100033448687573822364716494544753706716759589942809981826783490131666633534\ 803678986944688709116660497353729258607212948697354540708098306748938341237186314008359796\ 188659758687452533054689212976641570420621259246313692421680590877408335813928666541584971\ 162587069556578588747699631296952500459372627389026805669355128729433837219131116650881001\ 587862655915637954055905677822368140030968843934808622848184791345633141193023840264097274\ 843644962195449224465222047176358607479658556660534098286098574027883743312688563354434306\ 978701896435826139118100252599020766184432984883184723915912701390457047735764831010211928\ 297085328960931680353919649869573264393791490308485470616433789856348238900004564261855622\ 496930913960312520223767376074153862116245551165086436799129389371225572752855358505388627\ 546928167550407303918984389641052039899021078907741074670715487187445927826480325745329406\ 836552544103465737320315138225129361437624142202250714370369730734609414850108603189323604\ 113311115744937702491468814553609722861672425272088889061517451052531559178316247029430178\ 095934252371975125612329569505926858901075573121447832714438655839592620356007499708416567\ 681679268721978983048302281782977385152293797381195278398266923467818982723138352442777865\ 647623134859901194028780732484171511058619349202546881837818357300094700147502951964817837\ 874039354216278848238941974695520862627419471357392597226651239427201166462692938707284017\ 956993398889202501277913459329094676020415764879790841607401359157889710773691716288172692\ 755182517960232474350173532606863738793763572044458313264353526509290061748888247033974920\ 459020557724020364994277699238470527177685203357040125910731736639056137520453197778773562\ 797180625921321743667984249874334562328228971247257945609197595215055835184523639531383497\ 657376260166981167685146145560638695562162638896323160272971094995069592801744350030798593\ 924157506631512149867563008065061831442109254227561277967430907171276820183902280303065724\ 252294800267075913436729080697447776799229453917140856561043148672020633912643384787632773\ 495535569020831968308365499869958364273149", "0x1.71547652b82fe1777d0ffda0d23a7d11d6aef551bad2b4b1164a2cd9a342648fbc3887eeaa2ed9ac49b25\ eeb82d7c167d52173cc1895213f897f5e06a7be73665fc529264c2fb3ab643687aaf3ab440c16bd777e75050a8\ d1a39e8af56c64a7833352906deb692ce4f199e108cf392819cfc406b19abb71ec25e11f75c6142e64ca16da20\ b1d74a12c719098b4040cbe82351bd8bd422427231f9ee25bd0c470fe2464b892824c120f2d07db43448b6bdd3\ 58165f1a2b3d8675f9ee1d8d19ce22ece1d8e1cf2ed95025c73a0b608ecb0ac9cb843a1c53b021698c0eba2176\ 77f7d0b9c4b6e004ca5169aedd5b0fbf79220755e0827ae421af38c350dbfd200f5437ad88854a185bbc4bbb5f\ 9231797de27c1982e15c6f87a30b468c39b2a586e51fb9211a51bfd1e1075e545eff26d6bfc0b51b3db80dbcb2\ 4254977733864dadcb616d749e415eb60cbda42f3df5d4a527d762fb97efdb287e16c60c8e5cbd7fc5b97445f4\ a50a628f826ca66964b903cfa5da099460790c09071c1e23caa41ed00d87cd3ea10639d896b14ff19af35259c5\ 375f02f650e4e4154a0f0ad4150c9f23c2ac41a153c154c13420555a1dd2359b43d861faa27020f89240cce172\ 8bc41b06c19c811d57a442f32964754bf5393c68fce7c1143becd02ebdb9d9d6cd6ce0772765a409b32d4e2ff5\ e479ea9cf606f388b14bf1040fd7ac3c572fa96799afa88d9b908ee33cc144dd7b3a9034befd1786dffd1b374c\ 3ab057c78308382a2ecb4a8ae9ebfe2400db7e42eb1afaf630de1ee8d85808160092d7bfb276e839390f2cc6dd\ 801dd8d0791db4a9e602c37179d4d793f85e6b7de417c9d92c6cded0dec3a15568bd8c41b35d16b262f9c9b86f\ 8efb146d75817a5a20dd9f20c8b36649fc6713eb9a596b7b63c90b82f4efacb3afa37dbda4bd2259ec05bf0464\ c73c98129349a177c1beac7023630d669ff199f5bb7b898c5f42057260d95232260b815e608b14add28858c21b\ afcb7061a345db80ebbd88c1a8cd7d558c3e49fde7e67e61b47752cc51aa59a7a8909a7888a2a53158b35e487f\ 9ccf8914ce12c742a93e9cb6d7360a5e4fb2e4acdd70f3a7c5afb7233d9547378dbd9a0f8eee80c01446b265c0\ 30bbd0bba9aa245c1a351aa40c8e9a6c1a2f9259df8d78033b8e5b1fbb46c6ff0514ca6f17c72498ff937dc7ef\ 1270ea59b36d4b6f41f6d327e363e04463279e5a893d88566e171b92c0af10b9eb3015a189e17eb81288143e5c\ ea089a45ca8b5c69aeb433e4dc420589191a767f85e5aa15108ac58de430f24ddc986f1a18377639dcc819b7fe\ b92041aeb238c812adf284474f81d729d962149f69e3aa2000a51acde13f7d8c097cdde28b92b7323ee95f66b3\ c11bb8a14c27dad07685f8ebe4195220ef186f13536485dd4d3f6d1a01a7f5dc63145fb5688742fa36da1ef616\ c00760f0ca4ea16514fed4ceb9a0b1afafe73aaa7a69727855effa8662bb16794ee125dc16c57b422bf1ab01bf\ 576392dd8813dc17771e2e4956c8bf568126613e4814945f3583b02acc36249d1db915aecab476582cf6dc8646\ 02ba37849ddb40cc61052fdd5001e3ecd7ac0e1d9d011d01f5392aaaf33b9d2a91f01e5ded9a6ec3f5b1e01e45\ e96fb5653006d8a86b8986eb4bfc9b73352350d82bbde9d247cbd4b56ca2d8fd78c0244b2003418eef32ffec82\ a35b9c7c64ed6f67a012528ad9fcd8c71017143f043b22cace3bfa4730f9c22bc761a40f5ea#10000", Less, ); let log_2_e_f32 = Float::log_2_e_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(log_2_e_f32.to_string(), "1.442695"); assert_eq!(to_hex_string(&log_2_e_f32), "0x1.715476#24"); assert_eq!(log_2_e_f32, f32::LOG_2_E); let log_2_e_f64 = Float::log_2_e_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(log_2_e_f64.to_string(), "1.4426950408889634"); assert_eq!(to_hex_string(&log_2_e_f64), "0x1.71547652b82fe#53"); assert_eq!(log_2_e_f64, f64::LOG_2_E); } #[test] #[should_panic] fn log_2_e_prec_fail_1() { Float::log_2_e_prec(0); } fn test_log_2_e_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::log_2_e_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = log_2_e_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_log_2_e_prec_round() { test_log_2_e_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_log_2_e_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_log_2_e_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_log_2_e_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_log_2_e_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Less); test_log_2_e_prec_round_helper(2, Floor, "1.0", "0x1.0#2", Less); test_log_2_e_prec_round_helper(2, Ceiling, "1.5", "0x1.8#2", Greater); test_log_2_e_prec_round_helper(2, Down, "1.0", "0x1.0#2", Less); test_log_2_e_prec_round_helper(2, Up, "1.5", "0x1.8#2", Greater); test_log_2_e_prec_round_helper(2, Nearest, "1.5", "0x1.8#2", Greater); test_log_2_e_prec_round_helper(3, Floor, "1.2", "0x1.4#3", Less); test_log_2_e_prec_round_helper(3, Ceiling, "1.5", "0x1.8#3", Greater); test_log_2_e_prec_round_helper(3, Down, "1.2", "0x1.4#3", Less); test_log_2_e_prec_round_helper(3, Up, "1.5", "0x1.8#3", Greater); test_log_2_e_prec_round_helper(3, Nearest, "1.5", "0x1.8#3", Greater); test_log_2_e_prec_round_helper(4, Floor, "1.4", "0x1.6#4", Less); test_log_2_e_prec_round_helper(4, Ceiling, "1.5", "0x1.8#4", Greater); test_log_2_e_prec_round_helper(4, Down, "1.4", "0x1.6#4", Less); test_log_2_e_prec_round_helper(4, Up, "1.5", "0x1.8#4", Greater); test_log_2_e_prec_round_helper(4, Nearest, "1.5", "0x1.8#4", Greater); test_log_2_e_prec_round_helper(5, Floor, "1.44", "0x1.7#5", Less); test_log_2_e_prec_round_helper(5, Ceiling, "1.5", "0x1.8#5", Greater); test_log_2_e_prec_round_helper(5, Down, "1.44", "0x1.7#5", Less); test_log_2_e_prec_round_helper(5, Up, "1.5", "0x1.8#5", Greater); test_log_2_e_prec_round_helper(5, Nearest, "1.44", "0x1.7#5", Less); test_log_2_e_prec_round_helper(6, Floor, "1.44", "0x1.70#6", Less); test_log_2_e_prec_round_helper(6, Ceiling, "1.47", "0x1.78#6", Greater); test_log_2_e_prec_round_helper(6, Down, "1.44", "0x1.70#6", Less); test_log_2_e_prec_round_helper(6, Up, "1.47", "0x1.78#6", Greater); test_log_2_e_prec_round_helper(6, Nearest, "1.44", "0x1.70#6", Less); test_log_2_e_prec_round_helper(7, Floor, "1.44", "0x1.70#7", Less); test_log_2_e_prec_round_helper(7, Ceiling, "1.45", "0x1.74#7", Greater); test_log_2_e_prec_round_helper(7, Down, "1.44", "0x1.70#7", Less); test_log_2_e_prec_round_helper(7, Up, "1.45", "0x1.74#7", Greater); test_log_2_e_prec_round_helper(7, Nearest, "1.44", "0x1.70#7", Less); test_log_2_e_prec_round_helper(8, Floor, "1.44", "0x1.70#8", Less); test_log_2_e_prec_round_helper(8, Ceiling, "1.445", "0x1.72#8", Greater); test_log_2_e_prec_round_helper(8, Down, "1.44", "0x1.70#8", Less); test_log_2_e_prec_round_helper(8, Up, "1.445", "0x1.72#8", Greater); test_log_2_e_prec_round_helper(8, Nearest, "1.445", "0x1.72#8", Greater); test_log_2_e_prec_round_helper(9, Floor, "1.441", "0x1.71#9", Less); test_log_2_e_prec_round_helper(9, Ceiling, "1.445", "0x1.72#9", Greater); test_log_2_e_prec_round_helper(9, Down, "1.441", "0x1.71#9", Less); test_log_2_e_prec_round_helper(9, Up, "1.445", "0x1.72#9", Greater); test_log_2_e_prec_round_helper(9, Nearest, "1.441", "0x1.71#9", Less); test_log_2_e_prec_round_helper(10, Floor, "1.441", "0x1.710#10", Less); test_log_2_e_prec_round_helper(10, Ceiling, "1.443", "0x1.718#10", Greater); test_log_2_e_prec_round_helper(10, Down, "1.441", "0x1.710#10", Less); test_log_2_e_prec_round_helper(10, Up, "1.443", "0x1.718#10", Greater); test_log_2_e_prec_round_helper(10, Nearest, "1.443", "0x1.718#10", Greater); test_log_2_e_prec_round_helper( 100, Floor, "1.442695040888963407359924681001", "0x1.71547652b82fe1777d0ffda0c#100", Less, ); test_log_2_e_prec_round_helper( 100, Ceiling, "1.442695040888963407359924681003", "0x1.71547652b82fe1777d0ffda0e#100", Greater, ); test_log_2_e_prec_round_helper( 100, Down, "1.442695040888963407359924681001", "0x1.71547652b82fe1777d0ffda0c#100", Less, ); test_log_2_e_prec_round_helper( 100, Up, "1.442695040888963407359924681003", "0x1.71547652b82fe1777d0ffda0e#100", Greater, ); test_log_2_e_prec_round_helper( 100, Nearest, "1.442695040888963407359924681003", "0x1.71547652b82fe1777d0ffda0e#100", Greater, ); } #[test] #[should_panic] fn log_2_e_prec_round_fail_1() { Float::log_2_e_prec_round(0, Floor); } #[test] #[should_panic] fn log_2_e_prec_round_fail_2() { Float::log_2_e_prec_round(1, Exact); } #[test] #[should_panic] fn log_2_e_prec_round_fail_3() { Float::log_2_e_prec_round(1000, Exact); } #[test] fn log_2_e_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (log_2_e, o) = Float::log_2_e_prec(prec); assert!(log_2_e.is_valid()); assert_eq!(log_2_e.get_prec(), Some(prec)); assert_eq!(log_2_e.get_exponent(), Some(1)); assert_ne!(o, Equal); if o == Less { let (log_2_e_alt, o_alt) = Float::log_2_e_prec_round(prec, Ceiling); let mut next_upper = log_2_e.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(log_2_e_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !log_2_e.is_power_of_2() { let (log_2_e_alt, o_alt) = Float::log_2_e_prec_round(prec, Floor); let mut next_lower = log_2_e.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(log_2_e_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (log_2_e_alt, o_alt) = Float::log_2_e_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&log_2_e_alt), ComparableFloatRef(&log_2_e) ); assert_eq!(o_alt, o); let (log_2_e_alt, o_alt) = log_2_e_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&log_2_e_alt), ComparableFloatRef(&log_2_e) ); assert_eq!(o_alt, o); }); } #[test] fn log_2_e_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (log_2_e, o) = Float::log_2_e_prec_round(prec, rm); assert!(log_2_e.is_valid()); assert_eq!(log_2_e.get_prec(), Some(prec)); assert_eq!( log_2_e.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 2 } else { 1 }) ); assert_ne!(o, Equal); if o == Less { let (log_2_e_alt, o_alt) = Float::log_2_e_prec_round(prec, Ceiling); let mut next_upper = log_2_e.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(log_2_e_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !log_2_e.is_power_of_2() { let (log_2_e_alt, o_alt) = Float::log_2_e_prec_round(prec, Floor); let mut next_lower = log_2_e.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(log_2_e_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (log_2_e_alt, o_alt) = log_2_e_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&log_2_e_alt), ComparableFloatRef(&log_2_e) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::log_2_e_prec_round(prec, Exact)); }); test_constant(Float::log_2_e_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/one_over_pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::OneOverPi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::one_over_pi::one_over_pi_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_one_over_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::one_over_pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_pi_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_pi_prec() { test_one_over_pi_prec_helper(1, "0.2", "0x0.4#1", Less); test_one_over_pi_prec_helper(2, "0.4", "0x0.6#2", Greater); test_one_over_pi_prec_helper(3, "0.3", "0x0.5#3", Less); test_one_over_pi_prec_helper(4, "0.31", "0x0.50#4", Less); test_one_over_pi_prec_helper(5, "0.31", "0x0.50#5", Less); test_one_over_pi_prec_helper(6, "0.32", "0x0.52#6", Greater); test_one_over_pi_prec_helper(7, "0.316", "0x0.51#7", Less); test_one_over_pi_prec_helper(8, "0.318", "0x0.518#8", Greater); test_one_over_pi_prec_helper(9, "0.318", "0x0.518#9", Greater); test_one_over_pi_prec_helper(10, "0.3184", "0x0.518#10", Greater); test_one_over_pi_prec_helper( 100, "0.3183098861837906715377675267449", "0x0.517cc1b727220a94fe13abe8f8#100", Less, ); test_one_over_pi_prec_helper( 1000, "0.318309886183790671537767526745028724068919291480912897495334688117793595268453070180227\ 605532506171912145685453515916073785823692229157305755934821463399678458479933874818155146\ 155492793850615377434785792434795323386724780483447258023664760228445399511431880923780173\ 80534791224097882187387568817105745", "0x0.517cc1b727220a94fe13abe8fa9a6ee06db14acc9e21c820ff28b1d5ef5de2b0db92371d2126e97003249\ 77504e8c90e7f0ef58e5894d39f74411afa975da24274ce38135a2fbf209cc8eb1cc1a99cfa4e422fc5defc941\ d8ffc4bffef02cc07f79788c5ad05368fb69b3f6793e584dba7a31fb34f2ff516ba93dd63f60#1000", Greater, ); test_one_over_pi_prec_helper( 10000, "0.318309886183790671537767526745028724068919291480912897495334688117793595268453070180227\ 605532506171912145685453515916073785823692229157305755934821463399678458479933874818155146\ 155492793850615377434785792434795323386724780483447258023664760228445399511431880923780173\ 805347912240978821873875688171057446199892886800497344695478919221796646193566149812333972\ 925609398897304375763149573133928482077991748278697219967736198399924885751170342357716862\ 235037534321093095073976019478920729518667536118604988993270610654313551006440649555632794\ 332045893496239196331681212033606071996267823974997665573308870559510140032481355128777699\ 142621760244398752295362755529475781266136092915956963522624854628139921550049000595519714\ 178113805593570263050420032635492041849623212481122912406292968178496918382870423150815112\ 401743053213604434318281514949165445195492570799750310658781627963544818716509594146657438\ 081399951815315415698694078717965617434685128073379023325091411886655262537300052245435942\ 306422519900877335890075251121672634233905195162564498832466686290212247073757126227273384\ 334284139493920258501156672106239217189019679113437419909493020863247631035161678885959941\ 999010508775132258891766613692101570583030282080978597701277632155239398614682077999157383\ 781196187475544123750864454378602732510522477560775077762213628135308681656557053866853599\ 112141580772120705477992490251991498552594047188191168602329659282371155424811508898914043\ 579539584818980654589540433299207130636307088007681379749435383177526381933013928809553941\ 375367313556209559590900706791516603763677375875532249629906119931160438167197502070254258\ 086463160997439373755518931326924420684088817109957007585477388587073238755658574718756869\ 406460474291675847114237272683858920366364583928330017566158662706995581994917298580534901\ 219787378189176610067406107610946246431618863953520645662628379619499644876670348713979695\ 002079001367760079573447199216048005478021749909709575847136522279897806537994854166992229\ 841657807553569486071009136912167342958616913446654070970785112404173678648199124423506636\ 788041941587141549930997617372132721937323934074949084205662438503692449669982322299133112\ 075939352279862565992155216555980201566072004676545975817080477523114890861852023820108675\ 996778093098424965903214145706010454420472035046626346359518622100656310218747827279290611\ 585214360167235909753449291960947954584896218401874251573836665791772567980871737333279513\ 468902819007274654383486227761327661451846055194690121096425556074130675566064341975469933\ 136981600653977013483582929367016563233706628672321461990299706239639467516888419683311908\ 304501286788625728880767767123017595432900341294135037549121183217433715715878452469512663\ 422265997311883193781439701377488460115038395411380076436785124406774847072513616708313034\ 594217623443591873665129770374999497417106233196612202784289089203229769055405022822140497\ 043479490207733472807745720199349786347123624142348095779873777311384615697004611411428812\ 72772640473704021482011497184562231443936007", "0x0.517cc1b727220a94fe13abe8fa9a6ee06db14acc9e21c820ff28b1d5ef5de2b0db92371d2126e97003249\ 77504e8c90e7f0ef58e5894d39f74411afa975da24274ce38135a2fbf209cc8eb1cc1a99cfa4e422fc5defc941\ d8ffc4bffef02cc07f79788c5ad05368fb69b3f6793e584dba7a31fb34f2ff516ba93dd63f5f2f8bd9e839cfbc\ 529497535fdafd88fc6ae842b0198237e3db5d5f867de104d7a1b0ed4f1c8b0af730d8432ccc2af8a50342046f\ fec4026b9939883030aab6539d464b0713de04635a3e20ce1b3e6ee74049541ace23b45cb0e536ed7a268ab8c8\ 29f52ff83829fbf19f419616f27cc193edde19e9377b58f2f7c4f9d0f9ae5793f8ec3f890c83e3e12357d376ab\ b9698219d8ae30a5ace8ce1e16256a0a6962e8006233ec316b8f1cd634d803119be695a4bd3da6aaa9bfb1f6b8\ c0851fe3b26954eb255ebb87c3e31abd83d738a8bab24e06ceb1d9c4253e591923bc56b11aa2d5c8f800d8578e\ fe70cff98cfb50f3330abcca3fdd66c3fbf5bb29144f419305ff366e277849b366a1faeebef0b6f1dac494def1\ 4116974431426ac711965630b718465bef028600bd38ef9adf00c1a099731094180a441adc77abfd856f9748f2\ 1a52469b3886c6ed5212fd76730b55214055a4ce9f953033fbbae41e151c41e30bc39c52d4657deebb7b1d316e\ 5dffa77c0c6b3e09322e52a9b6ce569541446b0e13be4890a13024da309622ce22262e448d926f98b8056a1ea7\ 2a494886afefe5f00664a0f7767387a9f09c078f661f3d9947c63ca02c99f38e0d9849779a285ce09443d9055c\ fda9761492397993db6aa864853b90ff3b5cb6598a50b3cf13ca0c4effa4bca744273714b98ccb5f6c41b2faf8\ 77eddda4d24365233a13938992ec6dc0acf84f2de1298c69cba7b8e0298008606b40425ac77164855238173ba1\ 26b5ed33efbb92437778b4fd34a477b48da28a9e8f9056799cc103f25fab431d92f9f6e81aea03fc4c294a92ae\ 0321b886c369924193aa62dea38a7372a22e08485b4fa956ab30a4e8393a8022eed9dda62bb750bfcc3beb5a4d\ d138e94b4cb5666632a0a56b5714844ecc42839165f52024a03bbb8187993fe005438f524e1331ef03241eecbc\ b9fd1feca21c64306ef2098ce9cc946386ef3db8b9def84159b8ad0402e49c02d4908886c7407d7c03625ffed8\ 7c81c3b0c2c8ad2b15de5b0dcc4e3dea00802796913baa4fb5b75dd916dd50a05179344bb41b2199d848d4a075\ 51d28e1518ed776d789132e26e136ce3d16cbab60419f81fb7804c62015cc98b683da1c8a90062de1ec62497aa\ 5d6e352e527669bd39b54f34a4955b4216eef318cf7c63b2945b41bedfe55d0d7188aefd0d7006d7d863326b25\ b82f6983294dfab2b9d7fa3dcfcb579df3aefc994184055fb46330ae58203117d0ef26cd2599ec78dab84e69b7\ 4a127525f09da91998d55785432a7d2e0e9079f85e6bc2dbb7c918245bdb90bc4a9d3637137378075f7ac254dd\ bed625d335567e7bb0e816896f8d8e0ccc63bd6e1ed2443502efbfa406317f8564d766ede2e1fb6ef680fe3c85\ b6d951d12d1cd578049a9d6822bdb5a1694bf4025d383ed07553b50acbd95090b16dbee7ef2fd7f6dc4fedf44b\ 63b727e548338401f0ab742ffc3fe839f1419b3b0c30c15755ea6d7f3d9b736c79cb3caaddf98a46bc20b6f982\ 196e39ab092e73864dc65987eb65fd10052723602d06ead23b790e90931422e5ca4b0b8702b0#10000", Less, ); let one_over_pi_f32 = Float::one_over_pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(one_over_pi_f32.to_string(), "0.31830987"); assert_eq!(to_hex_string(&one_over_pi_f32), "0x0.517cc18#24"); assert_eq!(one_over_pi_f32, f32::ONE_OVER_PI); let one_over_pi_f64 = Float::one_over_pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(one_over_pi_f64.to_string(), "0.31830988618379069"); assert_eq!(to_hex_string(&one_over_pi_f64), "0x0.517cc1b727220c#53"); assert_eq!(one_over_pi_f64, f64::ONE_OVER_PI); } #[test] #[should_panic] fn one_over_pi_prec_fail_1() { Float::one_over_pi_prec(0); } fn test_one_over_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::one_over_pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_pi_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_pi_prec_round() { test_one_over_pi_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); test_one_over_pi_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); test_one_over_pi_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); test_one_over_pi_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); test_one_over_pi_prec_round_helper(1, Nearest, "0.2", "0x0.4#1", Less); test_one_over_pi_prec_round_helper(2, Floor, "0.2", "0x0.4#2", Less); test_one_over_pi_prec_round_helper(2, Ceiling, "0.4", "0x0.6#2", Greater); test_one_over_pi_prec_round_helper(2, Down, "0.2", "0x0.4#2", Less); test_one_over_pi_prec_round_helper(2, Up, "0.4", "0x0.6#2", Greater); test_one_over_pi_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Greater); test_one_over_pi_prec_round_helper(3, Floor, "0.3", "0x0.5#3", Less); test_one_over_pi_prec_round_helper(3, Ceiling, "0.38", "0x0.6#3", Greater); test_one_over_pi_prec_round_helper(3, Down, "0.3", "0x0.5#3", Less); test_one_over_pi_prec_round_helper(3, Up, "0.38", "0x0.6#3", Greater); test_one_over_pi_prec_round_helper(3, Nearest, "0.3", "0x0.5#3", Less); test_one_over_pi_prec_round_helper(4, Floor, "0.31", "0x0.50#4", Less); test_one_over_pi_prec_round_helper(4, Ceiling, "0.34", "0x0.58#4", Greater); test_one_over_pi_prec_round_helper(4, Down, "0.31", "0x0.50#4", Less); test_one_over_pi_prec_round_helper(4, Up, "0.34", "0x0.58#4", Greater); test_one_over_pi_prec_round_helper(4, Nearest, "0.31", "0x0.50#4", Less); test_one_over_pi_prec_round_helper(5, Floor, "0.31", "0x0.50#5", Less); test_one_over_pi_prec_round_helper(5, Ceiling, "0.33", "0x0.54#5", Greater); test_one_over_pi_prec_round_helper(5, Down, "0.31", "0x0.50#5", Less); test_one_over_pi_prec_round_helper(5, Up, "0.33", "0x0.54#5", Greater); test_one_over_pi_prec_round_helper(5, Nearest, "0.31", "0x0.50#5", Less); test_one_over_pi_prec_round_helper(6, Floor, "0.31", "0x0.50#6", Less); test_one_over_pi_prec_round_helper(6, Ceiling, "0.32", "0x0.52#6", Greater); test_one_over_pi_prec_round_helper(6, Down, "0.31", "0x0.50#6", Less); test_one_over_pi_prec_round_helper(6, Up, "0.32", "0x0.52#6", Greater); test_one_over_pi_prec_round_helper(6, Nearest, "0.32", "0x0.52#6", Greater); test_one_over_pi_prec_round_helper(7, Floor, "0.316", "0x0.51#7", Less); test_one_over_pi_prec_round_helper(7, Ceiling, "0.32", "0x0.52#7", Greater); test_one_over_pi_prec_round_helper(7, Down, "0.316", "0x0.51#7", Less); test_one_over_pi_prec_round_helper(7, Up, "0.32", "0x0.52#7", Greater); test_one_over_pi_prec_round_helper(7, Nearest, "0.316", "0x0.51#7", Less); test_one_over_pi_prec_round_helper(8, Floor, "0.316", "0x0.510#8", Less); test_one_over_pi_prec_round_helper(8, Ceiling, "0.318", "0x0.518#8", Greater); test_one_over_pi_prec_round_helper(8, Down, "0.316", "0x0.510#8", Less); test_one_over_pi_prec_round_helper(8, Up, "0.318", "0x0.518#8", Greater); test_one_over_pi_prec_round_helper(8, Nearest, "0.318", "0x0.518#8", Greater); test_one_over_pi_prec_round_helper(9, Floor, "0.317", "0x0.514#9", Less); test_one_over_pi_prec_round_helper(9, Ceiling, "0.318", "0x0.518#9", Greater); test_one_over_pi_prec_round_helper(9, Down, "0.317", "0x0.514#9", Less); test_one_over_pi_prec_round_helper(9, Up, "0.318", "0x0.518#9", Greater); test_one_over_pi_prec_round_helper(9, Nearest, "0.318", "0x0.518#9", Greater); test_one_over_pi_prec_round_helper(10, Floor, "0.3179", "0x0.516#10", Less); test_one_over_pi_prec_round_helper(10, Ceiling, "0.3184", "0x0.518#10", Greater); test_one_over_pi_prec_round_helper(10, Down, "0.3179", "0x0.516#10", Less); test_one_over_pi_prec_round_helper(10, Up, "0.3184", "0x0.518#10", Greater); test_one_over_pi_prec_round_helper(10, Nearest, "0.3184", "0x0.518#10", Greater); test_one_over_pi_prec_round_helper( 100, Floor, "0.3183098861837906715377675267449", "0x0.517cc1b727220a94fe13abe8f8#100", Less, ); test_one_over_pi_prec_round_helper( 100, Ceiling, "0.3183098861837906715377675267453", "0x0.517cc1b727220a94fe13abe900#100", Greater, ); test_one_over_pi_prec_round_helper( 100, Down, "0.3183098861837906715377675267449", "0x0.517cc1b727220a94fe13abe8f8#100", Less, ); test_one_over_pi_prec_round_helper( 100, Up, "0.3183098861837906715377675267453", "0x0.517cc1b727220a94fe13abe900#100", Greater, ); test_one_over_pi_prec_round_helper( 100, Nearest, "0.3183098861837906715377675267449", "0x0.517cc1b727220a94fe13abe8f8#100", Less, ); } #[test] #[should_panic] fn one_over_pi_prec_round_fail_1() { Float::one_over_pi_prec_round(0, Floor); } #[test] #[should_panic] fn one_over_pi_prec_round_fail_2() { Float::one_over_pi_prec_round(1, Exact); } #[test] #[should_panic] fn one_over_pi_prec_round_fail_3() { Float::one_over_pi_prec_round(1000, Exact); } #[test] fn one_over_pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (one_over_pi, o) = Float::one_over_pi_prec(prec); assert!(one_over_pi.is_valid()); assert_eq!(one_over_pi.get_prec(), Some(prec)); assert_eq!(one_over_pi.get_exponent(), Some(-1)); assert_ne!(o, Equal); if o == Less { let (one_over_pi_alt, o_alt) = Float::one_over_pi_prec_round(prec, Ceiling); let mut next_upper = one_over_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_pi.is_power_of_2() { let (one_over_pi_alt, o_alt) = Float::one_over_pi_prec_round(prec, Floor); let mut next_lower = one_over_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_pi_alt, o_alt) = Float::one_over_pi_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_pi_alt), ComparableFloatRef(&one_over_pi) ); assert_eq!(o_alt, o); let (one_over_pi_alt, o_alt) = one_over_pi_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_pi_alt), ComparableFloatRef(&one_over_pi) ); assert_eq!(o_alt, o); }); } #[test] fn one_over_pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (one_over_pi, o) = Float::one_over_pi_prec_round(prec, rm); assert!(one_over_pi.is_valid()); assert_eq!(one_over_pi.get_prec(), Some(prec)); assert_eq!( one_over_pi.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 0 } else { -1 }) ); assert_ne!(o, Equal); if o == Less { let (one_over_pi_alt, o_alt) = Float::one_over_pi_prec_round(prec, Ceiling); let mut next_upper = one_over_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_pi.is_power_of_2() { let (one_over_pi_alt, o_alt) = Float::one_over_pi_prec_round(prec, Floor); let mut next_lower = one_over_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_pi_alt, o_alt) = one_over_pi_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&one_over_pi_alt), ComparableFloatRef(&one_over_pi) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::one_over_pi_prec_round(prec, Exact)); }); test_constant(Float::one_over_pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/one_over_sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::OneOverSqrtPi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::one_over_sqrt_pi::one_over_sqrt_pi_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_one_over_sqrt_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::one_over_sqrt_pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_sqrt_pi_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_sqrt_pi_prec() { test_one_over_sqrt_pi_prec_helper(1, "0.5", "0x0.8#1", Less); test_one_over_sqrt_pi_prec_helper(2, "0.5", "0x0.8#2", Less); test_one_over_sqrt_pi_prec_helper(3, "0.6", "0x0.a#3", Greater); test_one_over_sqrt_pi_prec_helper(4, "0.56", "0x0.9#4", Less); test_one_over_sqrt_pi_prec_helper(5, "0.56", "0x0.90#5", Less); test_one_over_sqrt_pi_prec_helper(6, "0.56", "0x0.90#6", Less); test_one_over_sqrt_pi_prec_helper(7, "0.56", "0x0.90#7", Less); test_one_over_sqrt_pi_prec_helper(8, "0.562", "0x0.90#8", Less); test_one_over_sqrt_pi_prec_helper(9, "0.564", "0x0.908#9", Greater); test_one_over_sqrt_pi_prec_helper(10, "0.564", "0x0.908#10", Greater); test_one_over_sqrt_pi_prec_helper( 100, "0.564189583547756286948079451561", "0x0.906eba8214db688d71d48a7f7#100", Greater, ); test_one_over_sqrt_pi_prec_helper( 1000, "0.564189583547756286948079451560772585844050629328998856844085721710642468441493414486743\ 660202107363443028347906361707351689931494826162866365489520017768993292837637059598439760\ 352464350217972571211580245772820220554508527173216622208463308111399512763454486023068237\ 6909187451587466158513010663983578", "0x0.906eba8214db688d71d48a7f6bfec3441409a0ebac3e751739a15830cce620b0c0759cf859270f1140c03\ 6096cc79aebbd1f4eee48e1ca7874f76f877ffec25152561dcc244dc65e9c22f47f7b7fb57c9522f2f93e16b2a\ 3d27a3282dada7316eb9feb2436f2f272ac2c88bbba81b1c750754b409e94d32d18d3e91add#1000", Greater, ); test_one_over_sqrt_pi_prec_helper( 10000, "0.564189583547756286948079451560772585844050629328998856844085721710642468441493414486743\ 660202107363443028347906361707351689931494826162866365489520017768993292837637059598439760\ 352464350217972571211580245772820220554508527173216622208463308111399512763454486023068237\ 690918745158746615851301066398357771999377334160357798876166744076233039380216350601643621\ 696235050458312531946879456656288325815521624434548865703189877430881778182948389475108500\ 918458534221631782589335251833012024622562223724947270033897431264299659426350428304490363\ 315803937695985608159337829220557382923788231579233105761964777468253090171561808059522229\ 617632465359040085344294862502894739216418119274309774225569878795779049874819136937239692\ 072860633424767969948609588763043633726455878751543080934419738483288491379175361895663509\ 241348925308830394965405841057254148274823475174742009396988341677714885589167833739498591\ 581650137685988686204396412907286928963807377326731118428678802115524866218971908896807531\ 495120147455271759129815272122063234346757415260256184982277894986952530166949696856638623\ 092204424861433131061101739704316554435364616300266810889304772054130274832143365864710291\ 854949083838769247696374058754103158473317076216953144890497317398112138525262894966581881\ 072472305017305600073055507380269070239209325129365185654408027303045608558893318652586305\ 258834720981091615225551340163448096077340629067652092477744457915659936286913810650697399\ 221160635018381201634827945255588045897195279903092298856115545628197444322318409489548225\ 698923189346820367003206229210032439562925718525419045578836831335596305728880148673271426\ 404156118265947052921488282109621556115877884575869370769316568975733036330605808042677655\ 428887246839586538128191754446004116925982320701014879775987396655241201231020855972580774\ 163232436519687057937186995686641316370707460164674562326647852763293612556036730458147509\ 675836925881775102516171791588543511319449779511302064465744235464169847898040837501074701\ 352751880478226229284695968227276043713529635662439179198513462262203022255831394816897442\ 156283042895891974583056032928037616331070074684468077543352388043093250182093443276971756\ 604585358146189293483000847521883563156134850300525631317511502402815253573480281037755873\ 096872058049839116785448367821638308739616614732338613368580643691303623270229201209584205\ 184540016221297602224920502091385620779268452045138092065191048228713446511588759776466334\ 955164279752771529006304592626662132102474121626192672652575831748945391640021506027583121\ 434323762213688659265886677223270051307283677840267588527026126262046233048278337730934597\ 251048975207110619022526431266585290657052824558964508055413035731525022451056993474245131\ 940271984820050179010512183653933500150867883341285338203943259891864588601821281032378193\ 761352726418609752619573339217755306901824708807431947047706039526585252022757276732244053\ 528355676567827486661805285681843895340144818064306646936344654007472918717723921069499452\ 62293257821840527730356884864031512332566992", "0x0.906eba8214db688d71d48a7f6bfec3441409a0ebac3e751739a15830cce620b0c0759cf859270f1140c03\ 6096cc79aebbd1f4eee48e1ca7874f76f877ffec25152561dcc244dc65e9c22f47f7b7fb57c9522f2f93e16b2a\ 3d27a3282dada7316eb9feb2436f2f272ac2c88bbba81b1c750754b409e94d32d18d3e91adcff6c039ad39cf86\ 6dd09628cd2681847e759247bb68d0db3217d6928d2c52986a1ef82fd6bde19d4863cd81de6bb94f13db14d3ac\ 25186f4f23712538d461ea97b001e73157a8e5fd0894dfd79bea110cd0c886c16e0cc2d71f2331782fe3af6af3\ 8d95ebaf4bdcaf407f127fcee21139e560f41988fba498490a2f046bd5d928060833f81efeffc9b1f476e77a5c\ 560d16d31aff355b18658c49dfffbf2b24ebd85570ea4e3551e6045d0a36dcb1e46fe9121958e5e0085a461d2e\ 69efd1284fb5f445a03e882c983dc91ec8ffd8edb30c57e8ad4952dd036641d7d5223048f5567aa5a9178ca2e8\ c8f26d66d0899c3cba579d1a1fbe71b4cabf7ee1c212c2987e7c81ba09dd83fd1b82dc9a5d640a2bb4106903a0\ 5532629934b6622adbce3256ae672fffa96cd508a764ff883a76e3184d13014db85491972cf555280d50565251\ 3b94139e1397635d9a38584adbe3a3d177cf1e310732f87b24661689d25a18170cbd38f4766de0088c2c050e08\ d1a0e3c9a6988eb9f9a25c2e839623d90f4226b5c965b39c56a5777a8a4e07a5f76e5dac5d468d209c0346efe2\ 57ef980d1deaf815ccd5e0661a456ebeaf04e66aad8ed6462a7117e127986462672d4372a902f7db4341aeac82\ 533af16409add2cb38cfdd50cdd3c49336dbd8d5a6d9b58e5a095a6af709feef8bb46de1a3e9536a629b5d6487\ ffff1ab63baf70322c7216ba26b50b76a8d62074f1019a114b1ebbd2a2fc5ad771751d9be11eda7a826a3dcc36\ 516aa1d5bf8ac7936a37a25d41c716753bba34924d7fb957eb8baad78e7560fd3d6864629b76a7959212a2c2c1\ 9e83efb12a9f58ffffe0e879efbb8a0c0567130c689128e7f54f353052ff8436c6696bd07a1748582a5756e413\ 401db988220bc7b3b589f914a6cbdccf698c70552afd06a795b55b0ce2bb849e6704291c36f27aa171cee7eae5\ a646b9b49e5a8fe668b1fbe87c2a9c3a09bebd4e81c43620dbd1a3d4418f0d6ea7c30ea4749dbded9a534c38ea\ 7457b0a410276136368d0aa59998f7ef31f091494d36e75bbc31316a0b4a715d23ed230545370985cc1222f507\ 22da00753753538227128b1aa8de13ca2840e9a229209879f8f4687e0510d2dad16e5431258280d050039bf530\ 2194770c6354c1c43f61d1192f579f9440ca53f792c8bbffc33132f201844b7e8dafbab89aeda56c8b23b471de\ 02baaebbae4a33608e0d4e6ce9c02fe99164d5ffaa134ff9246ae00f4cc6d6560cad52a48ba21174a58bbaf3ac\ 19e64f7c8282a70460a445d41d2fc237829e680bb1795b47a64cbc7620d29fc77362dc8769613f41fd347815e5\ 28b411c31003911777199ab2f233e757e919885780c6ec05d414c0c5c164f4b12e388f4383cfe534a6ede9fddf\ b68089f73397e212e0df99ff496d43a9f35abb5e03f8b7a9c0d6b0afe2ec113c6918476e1f63429f60e3910430\ 7aeaf0e9c06c51f49e31cafa107a56947bed2ac19415640ce6db45372d33b0f0d5c87c6bc4c0e0fd0a81da36fd\ bc11afa300997175943be0fe51f3d0b221b9d99cb1aa10f1c4761e8be0cf7920bfa3b689d53#10000", Less, ); let one_over_sqrt_pi_f32 = Float::one_over_sqrt_pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(one_over_sqrt_pi_f32.to_string(), "0.56418961"); assert_eq!(to_hex_string(&one_over_sqrt_pi_f32), "0x0.906ebb#24"); assert_eq!(one_over_sqrt_pi_f32, f32::ONE_OVER_SQRT_PI); let one_over_sqrt_pi_f64 = Float::one_over_sqrt_pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(one_over_sqrt_pi_f64.to_string(), "0.5641895835477563"); assert_eq!( to_hex_string(&one_over_sqrt_pi_f64), "0x0.906eba8214db68#53" ); assert_eq!(one_over_sqrt_pi_f64, f64::ONE_OVER_SQRT_PI); } #[test] #[should_panic] fn one_over_sqrt_pi_prec_fail_1() { Float::one_over_sqrt_pi_prec(0); } fn test_one_over_sqrt_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::one_over_sqrt_pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_sqrt_pi_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_sqrt_pi_prec_round() { test_one_over_sqrt_pi_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_one_over_sqrt_pi_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_one_over_sqrt_pi_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_one_over_sqrt_pi_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_one_over_sqrt_pi_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_one_over_sqrt_pi_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_one_over_sqrt_pi_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_one_over_sqrt_pi_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_one_over_sqrt_pi_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_one_over_sqrt_pi_prec_round_helper(2, Nearest, "0.5", "0x0.8#2", Less); test_one_over_sqrt_pi_prec_round_helper(3, Floor, "0.5", "0x0.8#3", Less); test_one_over_sqrt_pi_prec_round_helper(3, Ceiling, "0.6", "0x0.a#3", Greater); test_one_over_sqrt_pi_prec_round_helper(3, Down, "0.5", "0x0.8#3", Less); test_one_over_sqrt_pi_prec_round_helper(3, Up, "0.6", "0x0.a#3", Greater); test_one_over_sqrt_pi_prec_round_helper(3, Nearest, "0.6", "0x0.a#3", Greater); test_one_over_sqrt_pi_prec_round_helper(4, Floor, "0.56", "0x0.9#4", Less); test_one_over_sqrt_pi_prec_round_helper(4, Ceiling, "0.62", "0x0.a#4", Greater); test_one_over_sqrt_pi_prec_round_helper(4, Down, "0.56", "0x0.9#4", Less); test_one_over_sqrt_pi_prec_round_helper(4, Up, "0.62", "0x0.a#4", Greater); test_one_over_sqrt_pi_prec_round_helper(4, Nearest, "0.56", "0x0.9#4", Less); test_one_over_sqrt_pi_prec_round_helper(5, Floor, "0.56", "0x0.90#5", Less); test_one_over_sqrt_pi_prec_round_helper(5, Ceiling, "0.59", "0x0.98#5", Greater); test_one_over_sqrt_pi_prec_round_helper(5, Down, "0.56", "0x0.90#5", Less); test_one_over_sqrt_pi_prec_round_helper(5, Up, "0.59", "0x0.98#5", Greater); test_one_over_sqrt_pi_prec_round_helper(5, Nearest, "0.56", "0x0.90#5", Less); test_one_over_sqrt_pi_prec_round_helper(6, Floor, "0.56", "0x0.90#6", Less); test_one_over_sqrt_pi_prec_round_helper(6, Ceiling, "0.58", "0x0.94#6", Greater); test_one_over_sqrt_pi_prec_round_helper(6, Down, "0.56", "0x0.90#6", Less); test_one_over_sqrt_pi_prec_round_helper(6, Up, "0.58", "0x0.94#6", Greater); test_one_over_sqrt_pi_prec_round_helper(6, Nearest, "0.56", "0x0.90#6", Less); test_one_over_sqrt_pi_prec_round_helper(7, Floor, "0.56", "0x0.90#7", Less); test_one_over_sqrt_pi_prec_round_helper(7, Ceiling, "0.57", "0x0.92#7", Greater); test_one_over_sqrt_pi_prec_round_helper(7, Down, "0.56", "0x0.90#7", Less); test_one_over_sqrt_pi_prec_round_helper(7, Up, "0.57", "0x0.92#7", Greater); test_one_over_sqrt_pi_prec_round_helper(7, Nearest, "0.56", "0x0.90#7", Less); test_one_over_sqrt_pi_prec_round_helper(8, Floor, "0.562", "0x0.90#8", Less); test_one_over_sqrt_pi_prec_round_helper(8, Ceiling, "0.566", "0x0.91#8", Greater); test_one_over_sqrt_pi_prec_round_helper(8, Down, "0.562", "0x0.90#8", Less); test_one_over_sqrt_pi_prec_round_helper(8, Up, "0.566", "0x0.91#8", Greater); test_one_over_sqrt_pi_prec_round_helper(8, Nearest, "0.562", "0x0.90#8", Less); test_one_over_sqrt_pi_prec_round_helper(9, Floor, "0.562", "0x0.900#9", Less); test_one_over_sqrt_pi_prec_round_helper(9, Ceiling, "0.564", "0x0.908#9", Greater); test_one_over_sqrt_pi_prec_round_helper(9, Down, "0.562", "0x0.900#9", Less); test_one_over_sqrt_pi_prec_round_helper(9, Up, "0.564", "0x0.908#9", Greater); test_one_over_sqrt_pi_prec_round_helper(9, Nearest, "0.564", "0x0.908#9", Greater); test_one_over_sqrt_pi_prec_round_helper(10, Floor, "0.563", "0x0.904#10", Less); test_one_over_sqrt_pi_prec_round_helper(10, Ceiling, "0.564", "0x0.908#10", Greater); test_one_over_sqrt_pi_prec_round_helper(10, Down, "0.563", "0x0.904#10", Less); test_one_over_sqrt_pi_prec_round_helper(10, Up, "0.564", "0x0.908#10", Greater); test_one_over_sqrt_pi_prec_round_helper(10, Nearest, "0.564", "0x0.908#10", Greater); test_one_over_sqrt_pi_prec_round_helper( 100, Floor, "0.56418958354775628694807945156", "0x0.906eba8214db688d71d48a7f6#100", Less, ); test_one_over_sqrt_pi_prec_round_helper( 100, Ceiling, "0.564189583547756286948079451561", "0x0.906eba8214db688d71d48a7f7#100", Greater, ); test_one_over_sqrt_pi_prec_round_helper( 100, Down, "0.56418958354775628694807945156", "0x0.906eba8214db688d71d48a7f6#100", Less, ); test_one_over_sqrt_pi_prec_round_helper( 100, Up, "0.564189583547756286948079451561", "0x0.906eba8214db688d71d48a7f7#100", Greater, ); test_one_over_sqrt_pi_prec_round_helper( 100, Nearest, "0.564189583547756286948079451561", "0x0.906eba8214db688d71d48a7f7#100", Greater, ); } #[test] #[should_panic] fn one_over_sqrt_pi_prec_round_fail_1() { Float::one_over_sqrt_pi_prec_round(0, Floor); } #[test] #[should_panic] fn one_over_sqrt_pi_prec_round_fail_2() { Float::one_over_sqrt_pi_prec_round(1, Exact); } #[test] #[should_panic] fn one_over_sqrt_pi_prec_round_fail_3() { Float::one_over_sqrt_pi_prec_round(1000, Exact); } #[test] fn one_over_sqrt_pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec(prec); assert!(one_over_sqrt_pi.is_valid()); assert_eq!(one_over_sqrt_pi.get_prec(), Some(prec)); assert_eq!(one_over_sqrt_pi.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (one_over_sqrt_pi_alt, o_alt) = Float::one_over_sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = one_over_sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_sqrt_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_sqrt_pi.is_power_of_2() { let (one_over_sqrt_pi_alt, o_alt) = Float::one_over_sqrt_pi_prec_round(prec, Floor); let mut next_lower = one_over_sqrt_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_sqrt_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_sqrt_pi_alt, o_alt) = Float::one_over_sqrt_pi_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_sqrt_pi_alt), ComparableFloatRef(&one_over_sqrt_pi) ); assert_eq!(o_alt, o); let (one_over_sqrt_pi_alt, o_alt) = one_over_sqrt_pi_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_sqrt_pi_alt), ComparableFloatRef(&one_over_sqrt_pi) ); assert_eq!(o_alt, o); }); } #[test] fn one_over_sqrt_pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (one_over_sqrt_pi, o) = Float::one_over_sqrt_pi_prec_round(prec, rm); assert!(one_over_sqrt_pi.is_valid()); assert_eq!(one_over_sqrt_pi.get_prec(), Some(prec)); assert_eq!( one_over_sqrt_pi.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (one_over_sqrt_pi_alt, o_alt) = Float::one_over_sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = one_over_sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_sqrt_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_sqrt_pi.is_power_of_2() { let (one_over_sqrt_pi_alt, o_alt) = Float::one_over_sqrt_pi_prec_round(prec, Floor); let mut next_lower = one_over_sqrt_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_sqrt_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_sqrt_pi_alt, o_alt) = one_over_sqrt_pi_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&one_over_sqrt_pi_alt), ComparableFloatRef(&one_over_sqrt_pi) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::one_over_sqrt_pi_prec_round(prec, Exact)); }); test_constant(Float::one_over_sqrt_pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/one_over_sqrt_tau.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::OneOverSqrtTau; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::one_over_sqrt_tau::one_over_sqrt_tau_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_one_over_sqrt_tau_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::one_over_sqrt_tau_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_sqrt_tau_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_sqrt_tau_prec() { test_one_over_sqrt_tau_prec_helper(1, "0.5", "0x0.8#1", Greater); test_one_over_sqrt_tau_prec_helper(2, "0.4", "0x0.6#2", Less); test_one_over_sqrt_tau_prec_helper(3, "0.38", "0x0.6#3", Less); test_one_over_sqrt_tau_prec_helper(4, "0.41", "0x0.68#4", Greater); test_one_over_sqrt_tau_prec_helper(5, "0.41", "0x0.68#5", Greater); test_one_over_sqrt_tau_prec_helper(6, "0.4", "0x0.66#6", Less); test_one_over_sqrt_tau_prec_helper(7, "0.398", "0x0.66#7", Less); test_one_over_sqrt_tau_prec_helper(8, "0.398", "0x0.660#8", Less); test_one_over_sqrt_tau_prec_helper(9, "0.399", "0x0.664#9", Greater); test_one_over_sqrt_tau_prec_helper(10, "0.3989", "0x0.662#10", Less); test_one_over_sqrt_tau_prec_helper( 100, "0.3989422804014326779399460599344", "0x0.662114cf50d942343f2cf14030#100", Greater, ); test_one_over_sqrt_tau_prec_helper( 1000, "0.398942280401432677939946059934381868475858631164934657665925829670657925899301838501252\ 333907306936430302558862635182685510991954555837242996212730625507706345270582720499317564\ 516345807530597253642732083669593478271702999186419063456032808933388606704653652796716869\ 34195477117721206532537536913347877", "0x0.662114cf50d942343f2cf1402eae38bfd3829f30512706d8c0471b4802639d2e9df8ac55447d3db723f5d\ 3abb374e88deb14277970be1513278e993445f08cff98282e1fd947ce4b4ecdbd6e65c23395cacb544de69eea3\ 2c276937b1bc567691c1cec4882c77aacefe1f6708329ab3fc8d2ab2435ee45c9150c426bbb8#1000", Greater, ); test_one_over_sqrt_tau_prec_helper( 10000, "0.398942280401432677939946059934381868475858631164934657665925829670657925899301838501252\ 333907306936430302558862635182685510991954555837242996212730625507706345270582720499317564\ 516345807530597253642732083669593478271702999186419063456032808933388606704653652796716869\ 341954771177212065325375369133478750560424055704884258180482317903772804997176338575363992\ 839140318693283694771754858239775054447927761155070412703969672485047337603814813923901300\ 564676023356305570085700726641100015721563953577823123410952609069269089244567245554672105\ 743928915256735109303850680783183519806551964687438189980165959781887721458861617459900501\ 712960940366313293846201865045309966814316491432421060417455294539282219688799792718106125\ 413701644536367652874648406122597740302757632013709422194511725465470758442141422502838061\ 868594135257554774549801530578349147613022007422892027821093302633276582742943413612643384\ 980057963587894437275171155013545859889393745518894340738320491519829619307071761750803329\ 086547364282269194590675379988171293765563498747919820220506439472756588960162518241653865\ 682958549834199174484028901472961826557349795720893467152719051181680313262827229623899368\ 921510110599838914400198674472347351963204746387291915197608912260762509601476407511767145\ 433601016214971648007948262922613392149108721308143700798328558749768734347897980278300510\ 262826071460132831874309251391448950500864351371232094749134907629411222727979591421075299\ 673747197316387505002135776055200631744235271327518724616860849157649748825471682030207497\ 062098265106007658380606023541897775864990099263845899892122682397288552012228221816314178\ 308158121229466255828963270625452661691131034742094301703313846663457879729080007652468485\ 334179957678287388085633885615200206213603246796710415477475796066423508536474271747792912\ 434828025073907614687889180477807434263307378988209019313548164988087811605658554801862326\ 665697388456830642702724077905143312033897044455936044032662126236766581278672374404901166\ 564541339777091280689982201428151967506588958639140595771858450705515561437105861118338079\ 716914044380378761129991061804988776438561675358245271277544532102159485888359954032827725\ 246069745445363049745582651877816164759265756297881307521577254233707200857137834531266312\ 782357208128645404040264033722898206313179116571251682514874032991214269126845955003622262\ 315257794830645021004783385421309666323873108778765242160746712375568508761910339254792109\ 211573641128195708927088639062119252851547796326120921969626873693129996429236958310270565\ 733834386378238052071363813152698866481153604716886972531676903101376207010580993776843055\ 041892765565102116589831129651509557052479656507203268313538993083521906924099338259623407\ 406961415103750340216958051666093814503142437034516561361464323353515610162799624281647911\ 127783108359666320819610363671588870086956238204933545154454220560124064024272600360105966\ 644223437056162524970715123219160940261473588761105521231222473362842356480453287247436537\ 04133401719034564232591496298172511220088055", "0x0.662114cf50d942343f2cf1402eae38bfd3829f30512706d8c0471b4802639d2e9df8ac55447d3db723f5d\ 3abb374e88deb14277970be1513278e993445f08cff98282e1fd947ce4b4ecdbd6e65c23395cacb544de69eea3\ 2c276937b1bc567691c1cec4882c77aacefe1f6708329ab3fc8d2ab2435ee45c9150c426bbb49487e480d8928e\ 623122d2369599582a3983769e7329865c92193ed298857cb81ab87659565e91e51487afe60871d04a18e432e6\ bff594c697ed53f9d0aaf01aa890d8b742ca9e5ec8b5ea95546cad1961020feb8ed1ea218282c79079f714f4a0\ bfda67f0e5ab81ec651ef4167fcf0e311b0d6b17578cbb5c65b311eb9071956748defa26992503a86e8300c9f5\ 082467be471e1dec4e7e1e9180296a90caadaed32e1972f7d51f05d9bcb5a7fe9f37a2d620cd24a3f28575328d\ 854f7a09661928fa57a78ad7d45d31fdb6377ddd63a6b7ce9fcd58c0ea0d7d36a37179fa5dd9215dde6682b2d8\ 6a8158f30670945f1eede2fd6ca404d7795a848aa442b3106116c7e9a212cdf14506bbc1ac9ab8d9b98bfd767b\ d58e4a529fcb015285a0779f53c3be9533137bac5c5f90226a7534c7a819995ffae2499426d04682ef71cbbb0b\ 0e3261ce51b1494f21861a1750090850f2ae343d0a6e302b563eac32d234a07be481f2e2f16df62fb78e9e342d\ 6d3029d2c37a03cbaae2fdc23728ea3136432daed576883b9fe332b136f979cb9de719361019e6e62aa7893d43\ 6a8e51246e9378a70b92afcc9323b414f4de095326a8ef23d71049f3e05b326ad299d22fc0bc8b809450180fef\ 478554821b4ee6e0357f88b14350f4e77386b505ad7c8fa32a5b42163de45cf7b41ad63c4aed86175ef1028a0d\ 932b739351783a42c771c6967ea9212f2c8e86616639d9705a45299031b722cafe8f6042a968f1e5aee9c73c6b\ a50c6af3a2598b0e128dbf85be2f3a60df9fb6f48a8ee7162d7013b3c1ca232deae1b39f0d797180f7a6a752a6\ 83690e26925c1b164a07f4ac2cb0c0ad0145ef80be80744063f6bc1ef94fc58e85283f61fa89f784b8d0679fc2\ 3f82e80dc04e91054d8cb75f64dbcee3db4759684165e5c21e0a98b9e88456e5c5444a353a73991f4fef88ee23\ 9e8cb2fc7152d3bdb119b8edb56206b31171a7eb12fac6cfba71c9341ef50a6863b38ab43747cfd41e062104bc\ 48549100e7b85f76b1989f0f72ef87e9cb989045f8500dfc329819b44464fa01750b5c8911a7b4776be2e27016\ 1f2ac11cea7136bce9f185370fc22fb213c3cbc9eca4d85875674085728a8d475b0cb557c00062f22e0de84560\ 33321dd367fc84751878bb1ebf079740abebbc8adce82e6ed570f9bb90f741f47f1ce9619b5f354c15a51894ea\ e8f37251e6f6c2f24f191e380b3cf8f9550968d0b3628248974046f1ed6013aee5bb2817edf5276d43f1c894dd\ 4f87a770f11619efb6f33d62f037de3612014ab96d3ba744922006bd15b4c0e248bfc854e1f4666a12ee7d5bf3\ 765d35191b53037aa8e989ca2868ff144c1bc7b6867eea49a234b963f36812f0119d5b379e2db3e5f1cbf7cbe9\ 8f92866e1120d3ba1ae76dfaa31dd7cfc7b651b490b8a434b8def7a99cb6c880eac6e66bf16ad72ef5492adcb4\ 3ca05e0bab3fae213ca98d72f11460f81ef2366721c30053b2f769cb43c96a42504e21e504c86f85c4916dba52\ de2edd93889cfd32b8ac6a59cb54912ec0c01f3dd79eaaea0699c78d5e8b7f1b5234617b1d10#10000", Less, ); let one_over_sqrt_tau_f32 = Float::one_over_sqrt_tau_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(one_over_sqrt_tau_f32.to_string(), "0.39894229"); assert_eq!(to_hex_string(&one_over_sqrt_tau_f32), "0x0.6621150#24"); assert_eq!(one_over_sqrt_tau_f32, f32::ONE_OVER_SQRT_TAU); let one_over_sqrt_tau_f64 = Float::one_over_sqrt_tau_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(one_over_sqrt_tau_f64.to_string(), "0.3989422804014327"); assert_eq!( to_hex_string(&one_over_sqrt_tau_f64), "0x0.662114cf50d944#53" ); assert_eq!(one_over_sqrt_tau_f64, f64::ONE_OVER_SQRT_TAU); } #[test] #[should_panic] fn one_over_sqrt_tau_prec_fail_1() { Float::one_over_sqrt_tau_prec(0); } fn test_one_over_sqrt_tau_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::one_over_sqrt_tau_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = one_over_sqrt_tau_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_one_over_sqrt_tau_prec_round() { test_one_over_sqrt_tau_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); test_one_over_sqrt_tau_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); test_one_over_sqrt_tau_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); test_one_over_sqrt_tau_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); test_one_over_sqrt_tau_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); test_one_over_sqrt_tau_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); test_one_over_sqrt_tau_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); test_one_over_sqrt_tau_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); test_one_over_sqrt_tau_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); test_one_over_sqrt_tau_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); test_one_over_sqrt_tau_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); test_one_over_sqrt_tau_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); test_one_over_sqrt_tau_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); test_one_over_sqrt_tau_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); test_one_over_sqrt_tau_prec_round_helper(3, Nearest, "0.38", "0x0.6#3", Less); test_one_over_sqrt_tau_prec_round_helper(4, Floor, "0.38", "0x0.60#4", Less); test_one_over_sqrt_tau_prec_round_helper(4, Ceiling, "0.41", "0x0.68#4", Greater); test_one_over_sqrt_tau_prec_round_helper(4, Down, "0.38", "0x0.60#4", Less); test_one_over_sqrt_tau_prec_round_helper(4, Up, "0.41", "0x0.68#4", Greater); test_one_over_sqrt_tau_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Greater); test_one_over_sqrt_tau_prec_round_helper(5, Floor, "0.39", "0x0.64#5", Less); test_one_over_sqrt_tau_prec_round_helper(5, Ceiling, "0.41", "0x0.68#5", Greater); test_one_over_sqrt_tau_prec_round_helper(5, Down, "0.39", "0x0.64#5", Less); test_one_over_sqrt_tau_prec_round_helper(5, Up, "0.41", "0x0.68#5", Greater); test_one_over_sqrt_tau_prec_round_helper(5, Nearest, "0.41", "0x0.68#5", Greater); test_one_over_sqrt_tau_prec_round_helper(6, Floor, "0.4", "0x0.66#6", Less); test_one_over_sqrt_tau_prec_round_helper(6, Ceiling, "0.406", "0x0.68#6", Greater); test_one_over_sqrt_tau_prec_round_helper(6, Down, "0.4", "0x0.66#6", Less); test_one_over_sqrt_tau_prec_round_helper(6, Up, "0.406", "0x0.68#6", Greater); test_one_over_sqrt_tau_prec_round_helper(6, Nearest, "0.4", "0x0.66#6", Less); test_one_over_sqrt_tau_prec_round_helper(7, Floor, "0.398", "0x0.66#7", Less); test_one_over_sqrt_tau_prec_round_helper(7, Ceiling, "0.402", "0x0.67#7", Greater); test_one_over_sqrt_tau_prec_round_helper(7, Down, "0.398", "0x0.66#7", Less); test_one_over_sqrt_tau_prec_round_helper(7, Up, "0.402", "0x0.67#7", Greater); test_one_over_sqrt_tau_prec_round_helper(7, Nearest, "0.398", "0x0.66#7", Less); test_one_over_sqrt_tau_prec_round_helper(8, Floor, "0.398", "0x0.660#8", Less); test_one_over_sqrt_tau_prec_round_helper(8, Ceiling, "0.4", "0x0.668#8", Greater); test_one_over_sqrt_tau_prec_round_helper(8, Down, "0.398", "0x0.660#8", Less); test_one_over_sqrt_tau_prec_round_helper(8, Up, "0.4", "0x0.668#8", Greater); test_one_over_sqrt_tau_prec_round_helper(8, Nearest, "0.398", "0x0.660#8", Less); test_one_over_sqrt_tau_prec_round_helper(9, Floor, "0.398", "0x0.660#9", Less); test_one_over_sqrt_tau_prec_round_helper(9, Ceiling, "0.399", "0x0.664#9", Greater); test_one_over_sqrt_tau_prec_round_helper(9, Down, "0.398", "0x0.660#9", Less); test_one_over_sqrt_tau_prec_round_helper(9, Up, "0.399", "0x0.664#9", Greater); test_one_over_sqrt_tau_prec_round_helper(9, Nearest, "0.399", "0x0.664#9", Greater); test_one_over_sqrt_tau_prec_round_helper(10, Floor, "0.3989", "0x0.662#10", Less); test_one_over_sqrt_tau_prec_round_helper(10, Ceiling, "0.3994", "0x0.664#10", Greater); test_one_over_sqrt_tau_prec_round_helper(10, Down, "0.3989", "0x0.662#10", Less); test_one_over_sqrt_tau_prec_round_helper(10, Up, "0.3994", "0x0.664#10", Greater); test_one_over_sqrt_tau_prec_round_helper(10, Nearest, "0.3989", "0x0.662#10", Less); test_one_over_sqrt_tau_prec_round_helper( 100, Floor, "0.3989422804014326779399460599341", "0x0.662114cf50d942343f2cf14028#100", Less, ); test_one_over_sqrt_tau_prec_round_helper( 100, Ceiling, "0.3989422804014326779399460599344", "0x0.662114cf50d942343f2cf14030#100", Greater, ); test_one_over_sqrt_tau_prec_round_helper( 100, Down, "0.3989422804014326779399460599341", "0x0.662114cf50d942343f2cf14028#100", Less, ); test_one_over_sqrt_tau_prec_round_helper( 100, Up, "0.3989422804014326779399460599344", "0x0.662114cf50d942343f2cf14030#100", Greater, ); test_one_over_sqrt_tau_prec_round_helper( 100, Nearest, "0.3989422804014326779399460599344", "0x0.662114cf50d942343f2cf14030#100", Greater, ); } #[test] #[should_panic] fn one_over_sqrt_tau_prec_round_fail_1() { Float::one_over_sqrt_tau_prec_round(0, Floor); } #[test] #[should_panic] fn one_over_sqrt_tau_prec_round_fail_2() { Float::one_over_sqrt_tau_prec_round(1, Exact); } #[test] #[should_panic] fn one_over_sqrt_tau_prec_round_fail_3() { Float::one_over_sqrt_tau_prec_round(1000, Exact); } #[test] fn one_over_sqrt_tau_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec(prec); assert!(one_over_sqrt_tau.is_valid()); assert_eq!(one_over_sqrt_tau.get_prec(), Some(prec)); assert_eq!( one_over_sqrt_tau.get_exponent(), Some(if prec == 1 { 0 } else { -1 }) ); assert_ne!(o, Equal); if o == Less { let (one_over_sqrt_tau_alt, o_alt) = Float::one_over_sqrt_tau_prec_round(prec, Ceiling); let mut next_upper = one_over_sqrt_tau.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_sqrt_tau_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_sqrt_tau.is_power_of_2() { let (one_over_sqrt_tau_alt, o_alt) = Float::one_over_sqrt_tau_prec_round(prec, Floor); let mut next_lower = one_over_sqrt_tau.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_sqrt_tau_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_sqrt_tau_alt, o_alt) = Float::one_over_sqrt_tau_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_sqrt_tau_alt), ComparableFloatRef(&one_over_sqrt_tau) ); assert_eq!(o_alt, o); let (one_over_sqrt_tau_alt, o_alt) = one_over_sqrt_tau_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&one_over_sqrt_tau_alt), ComparableFloatRef(&one_over_sqrt_tau) ); assert_eq!(o_alt, o); }); } #[test] fn one_over_sqrt_tau_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (one_over_sqrt_tau, o) = Float::one_over_sqrt_tau_prec_round(prec, rm); assert!(one_over_sqrt_tau.is_valid()); assert_eq!(one_over_sqrt_tau.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 0, _ => -1, }; assert_eq!(one_over_sqrt_tau.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (one_over_sqrt_tau_alt, o_alt) = Float::one_over_sqrt_tau_prec_round(prec, Ceiling); let mut next_upper = one_over_sqrt_tau.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(one_over_sqrt_tau_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !one_over_sqrt_tau.is_power_of_2() { let (one_over_sqrt_tau_alt, o_alt) = Float::one_over_sqrt_tau_prec_round(prec, Floor); let mut next_lower = one_over_sqrt_tau.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(one_over_sqrt_tau_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (one_over_sqrt_tau_alt, o_alt) = one_over_sqrt_tau_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&one_over_sqrt_tau_alt), ComparableFloatRef(&one_over_sqrt_tau) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::one_over_sqrt_tau_prec_round(prec, Exact)); }); test_constant(Float::one_over_sqrt_tau_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/phi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Phi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_phi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::phi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_phi_prec() { test_phi_prec_helper(1, "2.0", "0x2.0#1", Greater); test_phi_prec_helper(2, "1.5", "0x1.8#2", Less); test_phi_prec_helper(3, "1.5", "0x1.8#3", Less); test_phi_prec_helper(4, "1.6", "0x1.a#4", Greater); test_phi_prec_helper(5, "1.62", "0x1.a#5", Greater); test_phi_prec_helper(6, "1.62", "0x1.a0#6", Greater); test_phi_prec_helper(7, "1.62", "0x1.a0#7", Greater); test_phi_prec_helper(8, "1.617", "0x1.9e#8", Less); test_phi_prec_helper(9, "1.617", "0x1.9e#9", Less); test_phi_prec_helper(10, "1.617", "0x1.9e0#10", Less); test_phi_prec_helper( 100, "1.618033988749894848204586834366", "0x1.9e3779b97f4a7c15f39cc0606#100", Greater, ); test_phi_prec_helper( 1000, "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207\ 204189391137484754088075386891752126633862223536931793180060766726354433389086595939582905\ 638322661319928290267880675208766892501711696207032221043216269548626296313614438149758701\ 2203408058879544547492461856953648", "0x1.9e3779b97f4a7c15f39cc0605cedc8341082276bf3a27251f86c6a11d0c18e952767f0b153d27b7f03470\ 45b5bf1827f01886f0928403002c1d64ba40f335e36f06ad7ae9717877e85839d6effbd7dc664d325d1c537168\ 2cadd0cccfdffbbe1626e33b8d04b4331bbf73c790d94f79d471c4ab3ed3d82a5fec507705e#1000", Less, ); test_phi_prec_helper( 10000, "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207\ 204189391137484754088075386891752126633862223536931793180060766726354433389086595939582905\ 638322661319928290267880675208766892501711696207032221043216269548626296313614438149758701\ 220340805887954454749246185695364864449241044320771344947049565846788509874339442212544877\ 066478091588460749988712400765217057517978834166256249407589069704000281210427621771117778\ 053153171410117046665991466979873176135600670874807101317952368942752194843530567830022878\ 569978297783478458782289110976250030269615617002504643382437764861028383126833037242926752\ 631165339247316711121158818638513316203840052221657912866752946549068113171599343235973494\ 985090409476213222981017261070596116456299098162905552085247903524060201727997471753427775\ 927786256194320827505131218156285512224809394712341451702237358057727861600868838295230459\ 264787801788992199027077690389532196819861514378031499741106926088674296226757560523172777\ 520353613936210767389376455606060592165894667595519004005559089502295309423124823552122124\ 154440064703405657347976639723949499465845788730396230903750339938562102423690251386804145\ 779956981224457471780341731264532204163972321340444494873023154176768937521030687378803441\ 700939544096279558986787232095124268935573097045095956844017555198819218020640529055189349\ 475926007348522821010881946445442223188913192946896220023014437702699230078030852611807545\ 192887705021096842493627135925187607778846658361502389134933331223105339232136243192637289\ 106705033992822652635562090297986424727597725655086154875435748264718141451270006023890162\ 077732244994353088999095016803281121943204819643876758633147985719113978153978074761507722\ 117508269458639320456520989698555678141069683728840587461033781054443909436835835813811311\ 689938555769754841491445341509129540700501947754861630754226417293946803673198058618339183\ 285991303960720144559504497792120761247856459161608370594987860069701894098864007644361709\ 334172709191433650137157660114803814306262380514321173481510055901345610118007905063814215\ 270930858809287570345050780814545881990633612982798141174533927312080928972792221329806429\ 468782427487401745055406778757083237310975915117762978443284747908176518097787268416117632\ 503861211291436834376702350371116330725869883258710336322238109809012110198991768414917512\ 331340152733843837234500934786049792945991582201258104598230925528721241370436149102054718\ 554961180876426576511060545881475604431784798584539731286301625448761148520217064404111660\ 766950597757832570395110878230827106478939021115691039276838453863333215658296597731034360\ 323225457436372041244064088826737584339536795931232213437320995749889469956564736007295999\ 839128810319742631251797141432012311279551894778172691415891177991956481255800184550656329\ 528598591000908621802977563789259991649946428193022293552346674759326951654214021091363018\ 194722707890122087287361707348649998156255472811373479871656952748900814438405327483781378\ 2466917444229634914708157007352545707089773", "0x1.9e3779b97f4a7c15f39cc0605cedc8341082276bf3a27251f86c6a11d0c18e952767f0b153d27b7f03470\ 45b5bf1827f01886f0928403002c1d64ba40f335e36f06ad7ae9717877e85839d6effbd7dc664d325d1c537168\ 2cadd0cccfdffbbe1626e33b8d04b4331bbf73c790d94f79d471c4ab3ed3d82a5fec507705e4ae6e5e73a9b91f\ 3aa4db287ae44f332e923a73cb91648e428e975a3781eb01b49d8674fa1508419e0eaa4038b352d9bad30f4485\ b71a8ef64452a0dd40dc8cb8f9a2d4c514f1b229dcaa222ac268e9666e4a866769145f5f5880a9d0acd3b9e8c6\ 82f4f810320abeb94034e70f21608c061ab1c1caef1ebdcefbc72134ecf06ed82bfb7d8eb1a41901d65f5c8cab\ 2accbc32eab1fbe8284f2b44ba2e834c5893a39ea7865443f489c37f8742acd895afd87b467d22a40d098f30dd\ 2cafdeb3abb3a13507b46b3d757fc04001906e1767d40c3a3792a26eeef2ab5bd6685b915b5629400faa684ecb\ a752dddcb5d18576d77b652ac0d999973686604128f0cd42743596deb2d42c789d64b92658610b5b95c719adeb\ 8ce287326344e31d59a59963220b1a4c42771d454ec78f12393bfb4ac54188e59113d7c35441f15aa34a114070\ 35f006fc3ad70fc0d6331c6d479f484bf39cbfbd95e664e39bebdc5b09d9d5b8f8905d9805c8199457d444a909\ 316cc58d38b3a25c714be8d422964e9724c033b6748acbc2e05caaf737c95622e6483fa0707999afc482995170\ 1c6ed5f27ce231770965541f5f28797f2fecbd984d3435ce547c88c38466e2865235683d4447e4b32757903058\ ca11a903f3baa3864932b80a7d02d61b50c1ff281d5dd2947da4624bbc7c7b94962717aed284395c42f253c17f\ 492f401bb6c17a95c3296b424db05afa8e7ad2561aca1f4fd6e0eb57f831e40227fbacd467ff8b7f84370aef71\ 1857634d0cf4189002dde8787576c631f0b9a173c16b80e7d941c128a540c91d33a1daf0f0222986e3c7661b2a\ 7b374dc06d8396659e0fde9b7b41dc1bbb0f42988d4d2525906bdf64a6ea5b159f2adf7c883ce8c4808a9b46eb\ 960f74192010862bd1c306500c6795a0a29df4a34d42b1a418a9fbcabd51e1887aa0f8ebdf4452d6efb8d2948d\ 8878256e2c6c33dc8ca89d68e06aeabd56bca17dea2358e443b567201dbe25e06a7451a736b14cfe3af4385221\ 86524dad69f054b61cdbf1ba9a54f46ff7a2a1e5090e0a26dbe7766ebf40475a2f166ab6b1791b0ee0b48d863c\ 08f809967ac68a158a6b4eefe4fae8eb1d32cfa6a4573468c137401262ab7893a30cb015245b76fa16cf89db93\ 647bb74e2581ae8823d14c0343efb790b35764216428d6e9856dd074ee6f411ee1b5dd2a670cce122bf868be81\ 8525e08f5b8b3d940252b853b7248a83aa561610f17a35fc83e542a94fcb71694c229ef98f50746a08c3fcd875\ ca4b94d390bba41e657f21892b6ee0ef705034accc46fc4e1af7e9a90ff984fc20bd9596a3da5beca81a0ac599\ 947c1f5eebf18b16c96a12face93501968c59c16f7cd92e8a58d472335d816bbb85e1caa23ed2a61cc0cdbbb37\ 00b8bb3f9669fc3590347bc63f4c5dcb9b2a8c174acbadbdef7dd61aa4dff59fb3adca34b37fd54fcdbdeb6824\ 16a89edc65754aadaa3d5d5f329b92a98a8f08c8d6b6197dec9b63286673d2123a78adb6e162b938081682e154\ 56856ea498bee3ac11a03804078c8426b1eeba9afe94a602b0aca31dcc753b038d74573c896#10000", Greater, ); let phi_f32 = Float::phi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(phi_f32.to_string(), "1.618034"); assert_eq!(to_hex_string(&phi_f32), "0x1.9e377a#24"); assert_eq!(phi_f32, f32::PHI); let phi_f64 = Float::phi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(phi_f64.to_string(), "1.6180339887498949"); assert_eq!(to_hex_string(&phi_f64), "0x1.9e3779b97f4a8#53"); assert_eq!(phi_f64, f64::PHI); } #[test] #[should_panic] fn phi_prec_fail_1() { Float::phi_prec(0); } fn test_phi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::phi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_phi_prec_round() { test_phi_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_phi_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_phi_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_phi_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_phi_prec_round_helper(1, Nearest, "2.0", "0x2.0#1", Greater); test_phi_prec_round_helper(2, Floor, "1.5", "0x1.8#2", Less); test_phi_prec_round_helper(2, Ceiling, "2.0", "0x2.0#2", Greater); test_phi_prec_round_helper(2, Down, "1.5", "0x1.8#2", Less); test_phi_prec_round_helper(2, Up, "2.0", "0x2.0#2", Greater); test_phi_prec_round_helper(2, Nearest, "1.5", "0x1.8#2", Less); test_phi_prec_round_helper(3, Floor, "1.5", "0x1.8#3", Less); test_phi_prec_round_helper(3, Ceiling, "1.8", "0x1.c#3", Greater); test_phi_prec_round_helper(3, Down, "1.5", "0x1.8#3", Less); test_phi_prec_round_helper(3, Up, "1.8", "0x1.c#3", Greater); test_phi_prec_round_helper(3, Nearest, "1.5", "0x1.8#3", Less); test_phi_prec_round_helper(4, Floor, "1.5", "0x1.8#4", Less); test_phi_prec_round_helper(4, Ceiling, "1.6", "0x1.a#4", Greater); test_phi_prec_round_helper(4, Down, "1.5", "0x1.8#4", Less); test_phi_prec_round_helper(4, Up, "1.6", "0x1.a#4", Greater); test_phi_prec_round_helper(4, Nearest, "1.6", "0x1.a#4", Greater); test_phi_prec_round_helper(5, Floor, "1.56", "0x1.9#5", Less); test_phi_prec_round_helper(5, Ceiling, "1.62", "0x1.a#5", Greater); test_phi_prec_round_helper(5, Down, "1.56", "0x1.9#5", Less); test_phi_prec_round_helper(5, Up, "1.62", "0x1.a#5", Greater); test_phi_prec_round_helper(5, Nearest, "1.62", "0x1.a#5", Greater); test_phi_prec_round_helper(6, Floor, "1.59", "0x1.98#6", Less); test_phi_prec_round_helper(6, Ceiling, "1.62", "0x1.a0#6", Greater); test_phi_prec_round_helper(6, Down, "1.59", "0x1.98#6", Less); test_phi_prec_round_helper(6, Up, "1.62", "0x1.a0#6", Greater); test_phi_prec_round_helper(6, Nearest, "1.62", "0x1.a0#6", Greater); test_phi_prec_round_helper(7, Floor, "1.61", "0x1.9c#7", Less); test_phi_prec_round_helper(7, Ceiling, "1.62", "0x1.a0#7", Greater); test_phi_prec_round_helper(7, Down, "1.61", "0x1.9c#7", Less); test_phi_prec_round_helper(7, Up, "1.62", "0x1.a0#7", Greater); test_phi_prec_round_helper(7, Nearest, "1.62", "0x1.a0#7", Greater); test_phi_prec_round_helper(8, Floor, "1.617", "0x1.9e#8", Less); test_phi_prec_round_helper(8, Ceiling, "1.625", "0x1.a0#8", Greater); test_phi_prec_round_helper(8, Down, "1.617", "0x1.9e#8", Less); test_phi_prec_round_helper(8, Up, "1.625", "0x1.a0#8", Greater); test_phi_prec_round_helper(8, Nearest, "1.617", "0x1.9e#8", Less); test_phi_prec_round_helper(9, Floor, "1.617", "0x1.9e#9", Less); test_phi_prec_round_helper(9, Ceiling, "1.621", "0x1.9f#9", Greater); test_phi_prec_round_helper(9, Down, "1.617", "0x1.9e#9", Less); test_phi_prec_round_helper(9, Up, "1.621", "0x1.9f#9", Greater); test_phi_prec_round_helper(9, Nearest, "1.617", "0x1.9e#9", Less); test_phi_prec_round_helper(10, Floor, "1.617", "0x1.9e0#10", Less); test_phi_prec_round_helper(10, Ceiling, "1.619", "0x1.9e8#10", Greater); test_phi_prec_round_helper(10, Down, "1.617", "0x1.9e0#10", Less); test_phi_prec_round_helper(10, Up, "1.619", "0x1.9e8#10", Greater); test_phi_prec_round_helper(10, Nearest, "1.617", "0x1.9e0#10", Less); test_phi_prec_round_helper( 100, Floor, "1.618033988749894848204586834364", "0x1.9e3779b97f4a7c15f39cc0604#100", Less, ); test_phi_prec_round_helper( 100, Ceiling, "1.618033988749894848204586834366", "0x1.9e3779b97f4a7c15f39cc0606#100", Greater, ); test_phi_prec_round_helper( 100, Down, "1.618033988749894848204586834364", "0x1.9e3779b97f4a7c15f39cc0604#100", Less, ); test_phi_prec_round_helper( 100, Up, "1.618033988749894848204586834366", "0x1.9e3779b97f4a7c15f39cc0606#100", Greater, ); test_phi_prec_round_helper( 100, Nearest, "1.618033988749894848204586834366", "0x1.9e3779b97f4a7c15f39cc0606#100", Greater, ); } #[test] #[should_panic] fn phi_prec_round_fail_1() { Float::phi_prec_round(0, Floor); } #[test] #[should_panic] fn phi_prec_round_fail_2() { Float::phi_prec_round(1, Exact); } #[test] #[should_panic] fn phi_prec_round_fail_3() { Float::phi_prec_round(1000, Exact); } #[test] fn phi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (phi, o) = Float::phi_prec(prec); assert!(phi.is_valid()); assert_eq!(phi.get_prec(), Some(prec)); assert_eq!(phi.get_exponent(), Some(if prec == 1 { 2 } else { 1 })); assert_ne!(o, Equal); if o == Less { let (phi_alt, o_alt) = Float::phi_prec_round(prec, Ceiling); let mut next_upper = phi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(phi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !phi.is_power_of_2() { let (phi_alt, o_alt) = Float::phi_prec_round(prec, Floor); let mut next_lower = phi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(phi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (phi_alt, o_alt) = Float::phi_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&phi_alt), ComparableFloatRef(&phi)); assert_eq!(o_alt, o); }); } #[test] fn phi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (phi, o) = Float::phi_prec_round(prec, rm); assert!(phi.is_valid()); assert_eq!(phi.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 2, _ => 1, }; assert_eq!(phi.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (phi_alt, o_alt) = Float::phi_prec_round(prec, Ceiling); let mut next_upper = phi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(phi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !phi.is_power_of_2() { let (phi_alt, o_alt) = Float::phi_prec_round(prec, Floor); let mut next_lower = phi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(phi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::phi_prec_round(prec, Exact)); }); test_constant(Float::phi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Pi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::pi::rug_pi_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (rug_x, rug_o) = rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } fn test_pi_prec_helper_big(prec: u64) { let (x, o) = Float::pi_prec(prec); assert!(x.is_valid()); let (rug_x, rug_o) = rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_pi_prec() { test_pi_prec_helper(1, "4.0", "0x4.0#1", Greater); test_pi_prec_helper(2, "3.0", "0x3.0#2", Less); test_pi_prec_helper(3, "3.0", "0x3.0#3", Less); test_pi_prec_helper(4, "3.2", "0x3.4#4", Greater); test_pi_prec_helper(5, "3.1", "0x3.2#5", Less); test_pi_prec_helper(6, "3.12", "0x3.2#6", Less); test_pi_prec_helper(7, "3.16", "0x3.28#7", Greater); test_pi_prec_helper(8, "3.14", "0x3.24#8", Less); test_pi_prec_helper(9, "3.14", "0x3.24#9", Less); test_pi_prec_helper(10, "3.141", "0x3.24#10", Less); test_pi_prec_helper( 100, "3.141592653589793238462643383279", "0x3.243f6a8885a308d313198a2e0#100", Less, ); test_pi_prec_helper( 1000, "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034\ 825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105\ 559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348\ 6104543266482133936072602491412736", "0x3.243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be546\ 6cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5ac2ffd72dbd01adfb\ 7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc16636920d870#1000", Less, ); test_pi_prec_helper( 10000, "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034\ 825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105\ 559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348\ 610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590\ 360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118\ 548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224\ 737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771\ 342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021\ 960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459\ 455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147\ 303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195\ 909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413\ 891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319\ 255060400927701671139009848824012858361603563707660104710181942955596198946767837449448255\ 379774726847104047534646208046684259069491293313677028989152104752162056966024058038150193\ 511253382430035587640247496473263914199272604269922796782354781636009341721641219924586315\ 030286182974555706749838505494588586926995690927210797509302955321165344987202755960236480\ 665499119881834797753566369807426542527862551818417574672890977772793800081647060016145249\ 192173217214772350141441973568548161361157352552133475741849468438523323907394143334547762\ 416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784\ 383827967976681454100953883786360950680064225125205117392984896084128488626945604241965285\ 022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832\ 645995813390478027590099465764078951269468398352595709825822620522489407726719478268482601\ 476990902640136394437455305068203496252451749399651431429809190659250937221696461515709858\ 387410597885959772975498930161753928468138268683868942774155991855925245953959431049972524\ 680845987273644695848653836736222626099124608051243884390451244136549762780797715691435997\ 700129616089441694868555848406353422072225828488648158456028506016842739452267467678895252\ 138522549954666727823986456596116354886230577456498035593634568174324112515076069479451096\ 596094025228879710893145669136867228748940560101503308617928680920874760917824938589009714\ 909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234\ 364542858444795265867821051141354735739523113427166102135969536231442952484937187110145765\ 403590279934403742007310578539062198387447808478489683321445713868751943506430218453191048\ 481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814\ 675142691239748940907186494231961567945208", "0x3.243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be546\ 6cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5ac2ffd72dbd01adfb\ 7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc16636920d871574e69a458fea3f\ 4933d7e0d95748f728eb658718bcd5882154aee7b54a41dc25a59b59c30d5392af26013c5d1b023286085f0ca4\ 17918b8db38ef8e79dcb0603a180e6c9e0e8bb01e8a3ed71577c1bd314b2778af2fda55605c60e65525f3aa55a\ b945748986263e8144055ca396a2aab10b6b4cc5c341141e8cea15486af7c72e993b3ee1411636fbc2a2ba9c55\ d741831f6ce5c3e169b87931eafd6ba336c24cf5c7a325381289586773b8f48986b4bb9afc4bfe81b662821936\ 1d809ccfb21a991487cac605dec8032ef845d5de98575b1dc262302eb651b8823893e81d396acc50f6d6ff383f\ 442392e0b4482a484200469c8f04a9e1f9b5e21c66842f6e96c9a670c9c61abd388f06a51a0d2d8542f68960fa\ 728ab5133a36eef0b6c137a3be4ba3bf0507efb2a98a1f1651d39af017666ca593e82430e888cee8619456f9fb\ 47d84a5c33b8b5ebee06f75d885c12073401a449f56c16aa64ed3aa62363f77061bfedf72429b023d37d0d724d\ 00a1248db0fead349f1c09b075372c980991b7b25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a\ 94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5eb\ d09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c\ 6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd2387605\ 3317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbc\ a58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf\ 2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a\ 0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b\ 3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc\ 43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e8\ 9a0d6411bd3ae1e7e4900250e2d2071b35e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c1438\ 9d95a537f207d5ba202e5b9c5832603766295cfa911c819684e734a41b3472dca7b14a94a1b5100529a532915d\ 60f573fbc9bc6e42b60a47681e6740008ba6fb5571be91ff296ec6b2a0dd915b6636521e7b9f9b6ff34052ec58\ 5566453b02d5da99f8fa108ba47996e85076a4b7a70e9b5b32944db75092ec4192623ad6ea6b049a7df7d9cee6\ 0b88fedb266ecaa8c71699a17ff5664526cc2b19ee1193602a575094c29a0591340e4183a3e3f54989a5b429d6\ 56b8fe4d699f73fd6a1d29c07efe830f54d2d38e6f0255dc14cdd20868470eb266382e9c6021ecc5e09686b3f3\ ebaefc93c9718146b6a70a1687f358452a0e286b79c5305aa5007373e07841c7fdeae5c8e7c#10000", Less, ); test_pi_prec_helper_big(1000000); let pi_f32 = Float::pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_f32.to_string(), "3.1415927"); assert_eq!(to_hex_string(&pi_f32), "0x3.243f6c#24"); assert_eq!(pi_f32, f32::PI); let pi_f64 = Float::pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_f64.to_string(), "3.1415926535897931"); assert_eq!(to_hex_string(&pi_f64), "0x3.243f6a8885a30#53"); assert_eq!(pi_f64, f64::PI); } #[test] #[should_panic] fn pi_prec_fail_1() { Float::pi_prec(0); } fn test_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_pi_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_pi_prec_round() { test_pi_prec_round_helper(1, Floor, "2.0", "0x2.0#1", Less); test_pi_prec_round_helper(1, Ceiling, "4.0", "0x4.0#1", Greater); test_pi_prec_round_helper(1, Down, "2.0", "0x2.0#1", Less); test_pi_prec_round_helper(1, Up, "4.0", "0x4.0#1", Greater); test_pi_prec_round_helper(1, Nearest, "4.0", "0x4.0#1", Greater); test_pi_prec_round_helper(2, Floor, "3.0", "0x3.0#2", Less); test_pi_prec_round_helper(2, Ceiling, "4.0", "0x4.0#2", Greater); test_pi_prec_round_helper(2, Down, "3.0", "0x3.0#2", Less); test_pi_prec_round_helper(2, Up, "4.0", "0x4.0#2", Greater); test_pi_prec_round_helper(2, Nearest, "3.0", "0x3.0#2", Less); test_pi_prec_round_helper(3, Floor, "3.0", "0x3.0#3", Less); test_pi_prec_round_helper(3, Ceiling, "3.5", "0x3.8#3", Greater); test_pi_prec_round_helper(3, Down, "3.0", "0x3.0#3", Less); test_pi_prec_round_helper(3, Up, "3.5", "0x3.8#3", Greater); test_pi_prec_round_helper(3, Nearest, "3.0", "0x3.0#3", Less); test_pi_prec_round_helper(4, Floor, "3.0", "0x3.0#4", Less); test_pi_prec_round_helper(4, Ceiling, "3.2", "0x3.4#4", Greater); test_pi_prec_round_helper(4, Down, "3.0", "0x3.0#4", Less); test_pi_prec_round_helper(4, Up, "3.2", "0x3.4#4", Greater); test_pi_prec_round_helper(4, Nearest, "3.2", "0x3.4#4", Greater); test_pi_prec_round_helper(5, Floor, "3.1", "0x3.2#5", Less); test_pi_prec_round_helper(5, Ceiling, "3.2", "0x3.4#5", Greater); test_pi_prec_round_helper(5, Down, "3.1", "0x3.2#5", Less); test_pi_prec_round_helper(5, Up, "3.2", "0x3.4#5", Greater); test_pi_prec_round_helper(5, Nearest, "3.1", "0x3.2#5", Less); test_pi_prec_round_helper(6, Floor, "3.12", "0x3.2#6", Less); test_pi_prec_round_helper(6, Ceiling, "3.19", "0x3.3#6", Greater); test_pi_prec_round_helper(6, Down, "3.12", "0x3.2#6", Less); test_pi_prec_round_helper(6, Up, "3.19", "0x3.3#6", Greater); test_pi_prec_round_helper(6, Nearest, "3.12", "0x3.2#6", Less); test_pi_prec_round_helper(7, Floor, "3.12", "0x3.20#7", Less); test_pi_prec_round_helper(7, Ceiling, "3.16", "0x3.28#7", Greater); test_pi_prec_round_helper(7, Down, "3.12", "0x3.20#7", Less); test_pi_prec_round_helper(7, Up, "3.16", "0x3.28#7", Greater); test_pi_prec_round_helper(7, Nearest, "3.16", "0x3.28#7", Greater); test_pi_prec_round_helper(8, Floor, "3.14", "0x3.24#8", Less); test_pi_prec_round_helper(8, Ceiling, "3.16", "0x3.28#8", Greater); test_pi_prec_round_helper(8, Down, "3.14", "0x3.24#8", Less); test_pi_prec_round_helper(8, Up, "3.16", "0x3.28#8", Greater); test_pi_prec_round_helper(8, Nearest, "3.14", "0x3.24#8", Less); test_pi_prec_round_helper(9, Floor, "3.14", "0x3.24#9", Less); test_pi_prec_round_helper(9, Ceiling, "3.15", "0x3.26#9", Greater); test_pi_prec_round_helper(9, Down, "3.14", "0x3.24#9", Less); test_pi_prec_round_helper(9, Up, "3.15", "0x3.26#9", Greater); test_pi_prec_round_helper(9, Nearest, "3.14", "0x3.24#9", Less); test_pi_prec_round_helper(10, Floor, "3.141", "0x3.24#10", Less); test_pi_prec_round_helper(10, Ceiling, "3.145", "0x3.25#10", Greater); test_pi_prec_round_helper(10, Down, "3.141", "0x3.24#10", Less); test_pi_prec_round_helper(10, Up, "3.145", "0x3.25#10", Greater); test_pi_prec_round_helper(10, Nearest, "3.141", "0x3.24#10", Less); test_pi_prec_round_helper( 100, Floor, "3.141592653589793238462643383279", "0x3.243f6a8885a308d313198a2e0#100", Less, ); test_pi_prec_round_helper( 100, Ceiling, "3.141592653589793238462643383282", "0x3.243f6a8885a308d313198a2e4#100", Greater, ); test_pi_prec_round_helper( 100, Down, "3.141592653589793238462643383279", "0x3.243f6a8885a308d313198a2e0#100", Less, ); test_pi_prec_round_helper( 100, Up, "3.141592653589793238462643383282", "0x3.243f6a8885a308d313198a2e4#100", Greater, ); test_pi_prec_round_helper( 100, Nearest, "3.141592653589793238462643383279", "0x3.243f6a8885a308d313198a2e0#100", Less, ); } #[test] #[should_panic] fn pi_prec_round_fail_1() { Float::pi_prec_round(0, Floor); } #[test] #[should_panic] fn pi_prec_round_fail_2() { Float::pi_prec_round(1, Exact); } #[test] #[should_panic] fn pi_prec_round_fail_3() { Float::pi_prec_round(1000, Exact); } #[test] fn pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi, o) = Float::pi_prec(prec); assert!(pi.is_valid()); assert_eq!(pi.get_prec(), Some(prec)); assert_eq!(pi.get_exponent(), Some(if prec == 1 { 3 } else { 2 })); assert_ne!(o, Equal); if o == Less { let (pi_alt, o_alt) = Float::pi_prec_round(prec, Ceiling); let mut next_upper = pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi.is_power_of_2() { let (pi_alt, o_alt) = Float::pi_prec_round(prec, Floor); let mut next_lower = pi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_alt, o_alt) = Float::pi_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&pi_alt), ComparableFloatRef(&pi)); assert_eq!(o_alt, o); let (rug_pi, rug_o) = rug_pi_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_pi)), ComparableFloatRef(&pi) ); assert_eq!(rug_o, o); }); } #[test] fn pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi, o) = Float::pi_prec_round(prec, rm); assert!(pi.is_valid()); assert_eq!(pi.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 3, _ => 2, }; assert_eq!(pi.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (pi_alt, o_alt) = Float::pi_prec_round(prec, Ceiling); let mut next_upper = pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi.is_power_of_2() { let (pi_alt, o_alt) = Float::pi_prec_round(prec, Floor); let mut next_lower = pi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_pi, rug_o) = rug_pi_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_pi)), ComparableFloatRef(&pi) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_prec_round(prec, Exact)); }); test_constant(Float::pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi_over_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PiOver2; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_over_2_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_over_2_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_2_prec() { test_pi_over_2_prec_helper(1, "2.0", "0x2.0#1", Greater); test_pi_over_2_prec_helper(2, "1.5", "0x1.8#2", Less); test_pi_over_2_prec_helper(3, "1.5", "0x1.8#3", Less); test_pi_over_2_prec_helper(4, "1.6", "0x1.a#4", Greater); test_pi_over_2_prec_helper(5, "1.56", "0x1.9#5", Less); test_pi_over_2_prec_helper(6, "1.56", "0x1.90#6", Less); test_pi_over_2_prec_helper(7, "1.58", "0x1.94#7", Greater); test_pi_over_2_prec_helper(8, "1.57", "0x1.92#8", Less); test_pi_over_2_prec_helper(9, "1.57", "0x1.92#9", Less); test_pi_over_2_prec_helper(10, "1.57", "0x1.920#10", Less); test_pi_over_2_prec_helper( 100, "1.57079632679489661923132169164", "0x1.921fb54442d18469898cc5170#100", Less, ); test_pi_over_2_prec_helper( 1000, "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017\ 412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552\ 779822311474477465190982214405487832966723064237824116893391582635600954572824283461730174\ 3052271633241066968036301245706368", "0x1.921fb54442d18469898cc51701b839a252049c1114cf98e804177d4c76273644a29410f31c6809bbdf2a3\ 3679a748636605614dbe4be286e9fc26adadaa3848bc90b6aecc4bcfd8de89885d34c6fdad617feb96de80d6fd\ bdc70d7f6b5133f4b5d3e4822f8963fcc9250cca3d9c8b67b8400f97142c77e0b31b4906c38#1000", Less, ); test_pi_over_2_prec_helper( 10000, "1.570796326794896619231321691639751442098584699687552910487472296153908203143104499314017\ 412671058533991074043256641153323546922304775291115862679704064240558725142051350969260552\ 779822311474477465190982214405487832966723064237824116893391582635600954572824283461730174\ 305227163324106696803630124570636862293503303157794087440760460481414627045857682183946295\ 180005665265274410233260692073475970755804716528635182879795976546093058690966305896552559\ 274037231189981374783675942876362445613969091505974564916836681220328321543010697473197612\ 368595351089930471851385269608588146588376192337409233834702566000284063572631780413892885\ 671378894804586818589360734220450612476715073274792685525396139844629461771009978056064510\ 980432017209079906814887385654980259353605674999999186489024975529865866408048159297512229\ 727673454151321261154126672342517630965594085505001568919376443293766604190710308588834573\ 651799126745214377734365579781431941176893796875978890928890266085613403306500963938305597\ 954608210099469047628600532742931639432968076690913984115150976017650926484497886811299706\ 945624860887641739565757787428621227075347975414766558430863927944537549190877318732469659\ 627530200463850835569504924412006429180801781853830052355090971477798099473383918724724127\ 689887363423552023767323104023342129534745646656838514494576052376081028483012029019075096\ 755626691215017793820123748236631957099636302134961398391177390818004670860820609962293157\ 515143091487277853374919252747294293463497845463605398754651477660582672493601377980118240\ 332749559940917398876783184903713271263931275909208787336445488886396900040823530008072624\ 596086608607386175070720986784274080680578676276066737870924734219261661953697071667273881\ 208431259491784742781049609611092136275127128443835895247300826733402494313616395893042892\ 191913983988340727050476941893180475340032112562602558696492448042064244313472802120982642\ 511105330593153372139311019597472523561856893480478182185958643733882328786981206945432916\ 322997906695239013795049732882039475634734199176297854912911310261244703863359739134241300\ 738495451320068197218727652534101748126225874699825715714904595329625468610848230757854929\ 193705298942979886487749465080876964234069134341934471387077995927962622976979715524986262\ 340422993636822347924326918368111313049562304025621942195225622068274881390398857845717998\ 850064808044720847434277924203176711036112914244324079228014253008421369726133733839447626\ 069261274977333363911993228298058177443115288728249017796817284087162056257538034739725548\ 298047012614439855446572834568433614374470280050751654308964340460437380458912469294504857\ 454837992630682774890946564892410841499474361329402428782007135238777566189820725761873117\ 182271429222397632933910525570677367869761556713583051067984768115721476242468593555072882\ 701795139967201871003655289269531099193723904239244841660722856934375971753215109226595524\ 240502685307340337459639095598969976030709831714377220321872561859096089999195507959780907\ 337571345619874470453593247115980783972604", "0x1.921fb54442d18469898cc51701b839a252049c1114cf98e804177d4c76273644a29410f31c6809bbdf2a3\ 3679a748636605614dbe4be286e9fc26adadaa3848bc90b6aecc4bcfd8de89885d34c6fdad617feb96de80d6fd\ bdc70d7f6b5133f4b5d3e4822f8963fcc9250cca3d9c8b67b8400f97142c77e0b31b4906c38aba734d22c7f51f\ a499ebf06caba47b9475b2c38c5e6ac410aa5773daa520ee12d2cdace186a9c95793009e2e8d811943042f8652\ 0bc8c5c6d9c77c73cee58301d0c07364f0745d80f451f6b8abbe0de98a593bc5797ed2ab02e30732a92f9d52ad\ 5ca2ba44c3131f40a202ae51cb51555885b5a662e1a08a0f46750aa4357be3974c9d9f70a08b1b7de1515d4e2a\ eba0c18fb672e1f0b4dc3c98f57eb5d19b61267ae3d1929c0944ac33b9dc7a44c35a5dcd7e25ff40db31410c9b\ 0ec04e67d90d4c8a43e56302ef6401977c22eaef4c2bad8ee13118175b28dc411c49f40e9cb566287b6b7f9c1f\ a211c9705a2415242100234e478254f0fcdaf10e334217b74b64d33864e30d5e9c4783528d0696c2a17b44b07d\ 39455a899d1b77785b609bd1df25d1df8283f7d954c50f8b28e9cd780bb33652c9f412187444677430ca2b7cfd\ a3ec252e19dc5af5f7037baec42e09039a00d224fab60b5532769d5311b1fbb830dff6fb9214d811e9be86b926\ 80509246d87f569a4f8e04d83a9b964c04c8dbd92ea3cec7b746f7bf1ff280d5b3ca61dcbb6705e8260035d60d\ 4a7db204fb0622f2e4f610cb51231b47db7d79f3629da899cd9759da97637b6fe288fcd984a966640a2a257af5\ e84df71e8026f19a57eb30794038c9725d9e065d42ba2e43a07e905af9cdce9fdedaabce05e8d3019056b50806\ 32016393cb3cf92ff7d8fd1e64752f4fc6d99117c1e3a8b6ffeb0b58a97a80f645682a955991edafd7e91c3b02\ 998bda41f006fc14f2e2bdde537c6500d43ab176f8bb4edeaa1547b143f7fe1d63399634627aab9b4ad93d85de\ 52c6470ffd1aedc7808d0087d1ecc7e90c1dc257e5ab616e8e9adcd29f23cdb7c22b2e94724de25fdcbc870eef\ 96d5265bf19b17d89a0e77263747790656d1b3ba600e83f4f7f15f88fda4aeded26d74848cc7556c738b5c9ead\ 0684768e857e392f0471e2d97c73aca5bc7fb717df90915b244445c094806f80e27d6af503447e18e68e7f8c8d\ 9d460d69797910c5f070bbbf53a96ff45810fd0f2d06607dab7ba740c5679eb6744f14cda5427f07e89f05bbe6\ 21dc0e956d46c8b2fd133404abb82c9e6398a108d0a3bf3569032bbdafd4363aa217afdce9ae7f5e6d7863d9f4\ 4d06b208de9d70f3f24801287169038d9af1134005dabdc705792321b4df804dc8f2ab1c88eacefd3553c60a1c\ 4ecad29bf903eadd10172dce2c19301bb314ae7d488e40cb42739a520d9a396e53d8a54a50da880294d29948ae\ b07ab9fde4de37215b0523b40f33a00045d37daab8df48ff94b76359506ec8adb31b290f3dcfcdb7f9a029762c\ 2ab3229d816aed4cfc7d0845d23ccb74283b525bd3874dad994a26dba8497620c9311d6b7535824d3efbece773\ 05c47f6d93376554638b4cd0bffab3229366158cf708c9b0152ba84a614d02c89a0720c1d1f1faa4c4d2da14eb\ 2b5c7f26b4cfb9feb50e94e03f7f4187aa6969c737812aee0a66e90434238759331c174e3010f662f04b4359f9\ f5d77e49e4b8c0a35b53850b43f9ac2295071435bce2982d528039b9f03c20e3fef572e473e#10000", Less, ); let pi_over_2_f32 = Float::pi_over_2_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_over_2_f32.to_string(), "1.5707964"); assert_eq!(to_hex_string(&pi_over_2_f32), "0x1.921fb6#24"); assert_eq!(pi_over_2_f32, f32::PI_OVER_2); let pi_over_2_f64 = Float::pi_over_2_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_over_2_f64.to_string(), "1.5707963267948966"); assert_eq!(to_hex_string(&pi_over_2_f64), "0x1.921fb54442d18#53"); assert_eq!(pi_over_2_f64, f64::PI_OVER_2); } #[test] #[should_panic] fn pi_over_2_prec_fail_1() { Float::pi_over_2_prec(0); } fn test_pi_over_2_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_over_2_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_2_prec_round() { test_pi_over_2_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_pi_over_2_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_pi_over_2_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_pi_over_2_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_pi_over_2_prec_round_helper(1, Nearest, "2.0", "0x2.0#1", Greater); test_pi_over_2_prec_round_helper(2, Floor, "1.5", "0x1.8#2", Less); test_pi_over_2_prec_round_helper(2, Ceiling, "2.0", "0x2.0#2", Greater); test_pi_over_2_prec_round_helper(2, Down, "1.5", "0x1.8#2", Less); test_pi_over_2_prec_round_helper(2, Up, "2.0", "0x2.0#2", Greater); test_pi_over_2_prec_round_helper(2, Nearest, "1.5", "0x1.8#2", Less); test_pi_over_2_prec_round_helper(3, Floor, "1.5", "0x1.8#3", Less); test_pi_over_2_prec_round_helper(3, Ceiling, "1.8", "0x1.c#3", Greater); test_pi_over_2_prec_round_helper(3, Down, "1.5", "0x1.8#3", Less); test_pi_over_2_prec_round_helper(3, Up, "1.8", "0x1.c#3", Greater); test_pi_over_2_prec_round_helper(3, Nearest, "1.5", "0x1.8#3", Less); test_pi_over_2_prec_round_helper(4, Floor, "1.5", "0x1.8#4", Less); test_pi_over_2_prec_round_helper(4, Ceiling, "1.6", "0x1.a#4", Greater); test_pi_over_2_prec_round_helper(4, Down, "1.5", "0x1.8#4", Less); test_pi_over_2_prec_round_helper(4, Up, "1.6", "0x1.a#4", Greater); test_pi_over_2_prec_round_helper(4, Nearest, "1.6", "0x1.a#4", Greater); test_pi_over_2_prec_round_helper(5, Floor, "1.56", "0x1.9#5", Less); test_pi_over_2_prec_round_helper(5, Ceiling, "1.62", "0x1.a#5", Greater); test_pi_over_2_prec_round_helper(5, Down, "1.56", "0x1.9#5", Less); test_pi_over_2_prec_round_helper(5, Up, "1.62", "0x1.a#5", Greater); test_pi_over_2_prec_round_helper(5, Nearest, "1.56", "0x1.9#5", Less); test_pi_over_2_prec_round_helper(6, Floor, "1.56", "0x1.90#6", Less); test_pi_over_2_prec_round_helper(6, Ceiling, "1.59", "0x1.98#6", Greater); test_pi_over_2_prec_round_helper(6, Down, "1.56", "0x1.90#6", Less); test_pi_over_2_prec_round_helper(6, Up, "1.59", "0x1.98#6", Greater); test_pi_over_2_prec_round_helper(6, Nearest, "1.56", "0x1.90#6", Less); test_pi_over_2_prec_round_helper(7, Floor, "1.56", "0x1.90#7", Less); test_pi_over_2_prec_round_helper(7, Ceiling, "1.58", "0x1.94#7", Greater); test_pi_over_2_prec_round_helper(7, Down, "1.56", "0x1.90#7", Less); test_pi_over_2_prec_round_helper(7, Up, "1.58", "0x1.94#7", Greater); test_pi_over_2_prec_round_helper(7, Nearest, "1.58", "0x1.94#7", Greater); test_pi_over_2_prec_round_helper(8, Floor, "1.57", "0x1.92#8", Less); test_pi_over_2_prec_round_helper(8, Ceiling, "1.58", "0x1.94#8", Greater); test_pi_over_2_prec_round_helper(8, Down, "1.57", "0x1.92#8", Less); test_pi_over_2_prec_round_helper(8, Up, "1.58", "0x1.94#8", Greater); test_pi_over_2_prec_round_helper(8, Nearest, "1.57", "0x1.92#8", Less); test_pi_over_2_prec_round_helper(9, Floor, "1.57", "0x1.92#9", Less); test_pi_over_2_prec_round_helper(9, Ceiling, "1.574", "0x1.93#9", Greater); test_pi_over_2_prec_round_helper(9, Down, "1.57", "0x1.92#9", Less); test_pi_over_2_prec_round_helper(9, Up, "1.574", "0x1.93#9", Greater); test_pi_over_2_prec_round_helper(9, Nearest, "1.57", "0x1.92#9", Less); test_pi_over_2_prec_round_helper(10, Floor, "1.57", "0x1.920#10", Less); test_pi_over_2_prec_round_helper(10, Ceiling, "1.572", "0x1.928#10", Greater); test_pi_over_2_prec_round_helper(10, Down, "1.57", "0x1.920#10", Less); test_pi_over_2_prec_round_helper(10, Up, "1.572", "0x1.928#10", Greater); test_pi_over_2_prec_round_helper(10, Nearest, "1.57", "0x1.920#10", Less); test_pi_over_2_prec_round_helper( 100, Floor, "1.57079632679489661923132169164", "0x1.921fb54442d18469898cc5170#100", Less, ); test_pi_over_2_prec_round_helper( 100, Ceiling, "1.570796326794896619231321691641", "0x1.921fb54442d18469898cc5172#100", Greater, ); test_pi_over_2_prec_round_helper( 100, Down, "1.57079632679489661923132169164", "0x1.921fb54442d18469898cc5170#100", Less, ); test_pi_over_2_prec_round_helper( 100, Up, "1.570796326794896619231321691641", "0x1.921fb54442d18469898cc5172#100", Greater, ); test_pi_over_2_prec_round_helper( 100, Nearest, "1.57079632679489661923132169164", "0x1.921fb54442d18469898cc5170#100", Less, ); } #[test] #[should_panic] fn pi_over_2_prec_round_fail_1() { Float::pi_over_2_prec_round(0, Floor); } #[test] #[should_panic] fn pi_over_2_prec_round_fail_2() { Float::pi_over_2_prec_round(1, Exact); } #[test] #[should_panic] fn pi_over_2_prec_round_fail_3() { Float::pi_over_2_prec_round(1000, Exact); } #[test] fn pi_over_2_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi_over_2, o) = Float::pi_over_2_prec(prec); assert!(pi_over_2.is_valid()); assert_eq!(pi_over_2.get_prec(), Some(prec)); assert_eq!( pi_over_2.get_exponent(), Some(if prec == 1 { 2 } else { 1 }) ); assert_ne!(o, Equal); if o == Less { let (pi_over_2_alt, o_alt) = Float::pi_over_2_prec_round(prec, Ceiling); let mut next_upper = pi_over_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_2.is_power_of_2() { let (pi_over_2_alt, o_alt) = Float::pi_over_2_prec_round(prec, Floor); let mut next_lower = pi_over_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_2_alt, o_alt) = Float::pi_over_2_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_2_alt), ComparableFloatRef(&pi_over_2) ); assert_eq!(o_alt, o); }); } #[test] fn pi_over_2_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi_over_2, o) = Float::pi_over_2_prec_round(prec, rm); assert!(pi_over_2.is_valid()); assert_eq!(pi_over_2.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 2, _ => 1, }; assert_eq!(pi_over_2.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (pi_over_2_alt, o_alt) = Float::pi_over_2_prec_round(prec, Ceiling); let mut next_upper = pi_over_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_2.is_power_of_2() { let (pi_over_2_alt, o_alt) = Float::pi_over_2_prec_round(prec, Floor); let mut next_lower = pi_over_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_over_2_prec_round(prec, Exact)); }); test_constant(Float::pi_over_2_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi_over_3.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PiOver3; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::pi_over_3::pi_over_3_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_over_3_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_over_3_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = pi_over_3_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_pi_over_3_prec() { test_pi_over_3_prec_helper(1, "1.0", "0x1.0#1", Less); test_pi_over_3_prec_helper(2, "1.0", "0x1.0#2", Less); test_pi_over_3_prec_helper(3, "1.0", "0x1.0#3", Less); test_pi_over_3_prec_helper(4, "1.0", "0x1.0#4", Less); test_pi_over_3_prec_helper(5, "1.06", "0x1.1#5", Greater); test_pi_over_3_prec_helper(6, "1.06", "0x1.10#6", Greater); test_pi_over_3_prec_helper(7, "1.05", "0x1.0c#7", Less); test_pi_over_3_prec_helper(8, "1.047", "0x1.0c#8", Less); test_pi_over_3_prec_helper(9, "1.047", "0x1.0c#9", Less); test_pi_over_3_prec_helper(10, "1.047", "0x1.0c0#10", Less); test_pi_over_3_prec_helper( 100, "1.047197551196597746154214461094", "0x1.0c152382d73658465bb32e0f6#100", Greater, ); test_pi_over_3_prec_helper( 1000, "1.047197551196597746154214461093167628065723133125035273658314864102605468762069666209344\ 941780705689327382695504427435549031281536516860743908453136042827039150094700900646173701\ 853214874316318310127321476270325221977815376158549411262261055090400636381882855641153449\ 5368181088827377978690867497137579", "0x1.0c152382d73658465bb32e0f567ad116e158680b6335109aad64fe32f96f7983170d60a212f0067d3f717\ 79a66f85979958eb892987ec59f152c473c91c2585d30b247488328a90945bb03e232f53c8ebaa9d0f3f008f53\ d3da08ff9ce0cd4dce8d4301750642a88618b3317e685cefd02ab50f62c84feb221230af2d0#1000", Less, ); test_pi_over_3_prec_helper( 10000, "1.047197551196597746154214461093167628065723133125035273658314864102605468762069666209344\ 941780705689327382695504427435549031281536516860743908453136042827039150094700900646173701\ 853214874316318310127321476270325221977815376158549411262261055090400636381882855641153449\ 536818108882737797869086749713757908195668868771862724960506973654276418030571788122630863\ 453337110176849606822173794715650647170536477685756788586530651030728705793977537264368372\ 849358154126654249855783961917574963742646061003983043277891120813552214362007131648798408\ 245730234059953647900923513072392097725584128224939489223135044000189375715087853609261923\ 780919263203057879059573822813633741651143382183195123683597426563086307847339985370709673\ 986954678139386604543258257103320172902403783333332790992683317019910577605365439531674819\ 818448969434214174102751114895011753977062723670001045946250962195844402793806872392556382\ 434532751163476251822910386520954627451262531250652593952593510723742268871000642625537065\ 303072140066312698419067021828621092955312051127275989410100650678433950989665257874199804\ 630416573925094493043838524952414151383565316943177705620575951963025032793918212488313106\ 418353466975900557046336616274670952787201187902553368236727314318532066315589279149816085\ 126591575615701349178215402682228086356497097771225676329717368250720685655341352679383397\ 837084460810011862546749165491087971399757534756640932260784927212003113907213739974862105\ 010095394324851902249946168498196195642331896975736932503100985107055114995734251986745493\ 555166373293944932584522123269142180842620850606139191557630325924264600027215686672048416\ 397391072404924116713813991189516053787052450850711158580616489479507774635798047778182587\ 472287506327856495187366406407394757516751418962557263498200551155601662875744263928695261\ 461275989325560484700317961262120316893354741708401705797661632028042829542315201413988428\ 340736887062102248092874013064981682374571262320318788123972429155921552524654137963621944\ 215331937796826009196699821921359650423156132784198569941940873507496469242239826089494200\ 492330300880045464812485101689401165417483916466550477143269730219750312407232153838569952\ 795803532628653257658499643387251309489379422894622980924718663951975081984653143683324174\ 893615329091214898616217945578740875366374869350414628130150414712183254260265905230478665\ 900043205363147231622851949468784474024075276162882719485342835338947579817422489226298417\ 379507516651555575941328818865372118295410192485499345197878189391441370838358689826483698\ 865364675076293236964381889712289076249646853367167769539309560306958253639274979529669904\ 969891995087121849927297709928273894332982907552934952521338090159185044126547150507915411\ 454847619481598421955940350380451578579841037809055367378656512077147650828312395703381921\ 801196759978134580669103526179687399462482602826163227773815237956250647835476739484397016\ 160335123538226891639759397065979984020473221142918146881248374572730726666130338639853938\ 2250475637465829803023954980773205226484027", "0x1.0c152382d73658465bb32e0f567ad116e158680b6335109aad64fe32f96f7983170d60a212f0067d3f717\ 79a66f85979958eb892987ec59f152c473c91c2585d30b247488328a90945bb03e232f53c8ebaa9d0f3f008f53\ d3da08ff9ce0cd4dce8d4301750642a88618b3317e685cefd02ab50f62c84feb221230af2d0726f788c1daa36a\ 6dbbf2a048726da7b84e772d083ef1d80b1c3a4d3c6e15f40c8c891debaf1bdb8fb755bec9b3ab662cad750436\ b285d92f3bda52f7df43acabe0804cedf5a2e900a2e14f25c7d409465c3b7d2e50ff371cac975a21c61fbe371e\ 3dc1d1832cb76a2b16ac7436878b8e3b03ce6eec966b06b4d9a35c6d78fd4264ddbe6a4b15b21253eb8b938971\ f26b2bb5244c96a07892d310a3a9ce8bbceb6efc97e10c68062dc8227be851832ce6e933a96eaa2b3ccb80b312\ 09d5899a90b3885c2d4397574a42abba52c1f1f4dd7273b49620baba3cc5e82b68314d5f132399705247aa6815\ 16b6864ae6c2b8c2c0aac2342fac38a0a891f60977816524dcede22598975e3f12da578c5e046481c0fcd875a8\ d0d8e70668bcfa503ceb128bea19369501ad4fe638835fb21b4688fab277798c86a2b6baf82d9a4d75dc1cfdfe\ 6d4818c96692e74ea4acfd1f2d74060266ab36c351ceb238cc4f138cb676a7d020954f5261633ab69bd459d0c4\ 558b0c2f3aff8f118a5eade57c67b98803309290c9c289da7a2f4fd4bff7008e77dc413dd244ae9ac40023e408\ dc53cc035204174c98a40b32361767853cfe514cec691b1133ba3be70f97a79fec5b533badc64442b1716e51f9\ 45894f69aac4a1118ff22050d57b30f6e914043e2c7c1ed7c054603ca689346a9491c7deae9b37566039ce0559\ 76ab97b7dcd350caa53b5369984e1f8a84910b652bed1b24aa9cb23b1ba700a42e4571b8e661491fe54612d201\ bbb291814aaf52b8a1ec7e9437a84355e2d1cba4a5d2349471638520d7faa968ecd10ecd96fc7267873b7e593e\ e1d984b55367492fab08ab05369dda9b5d692c3a991ceb9f09bc933714c289252c1cc9b84c33ec3fe87daf5f4a\ 648e1992a1120fe5bc09a4c424da50aee48bcd26eab457f8a54b9505fe6dc9e9e19e4dadb32f8e484d07931473\ 59ada45f03a97b74ada141e652f7c86e7daa7a0fea6060e76d82d92b0daaf50096fe474e022da965ef09aa5db3\ be2eb39ba650b5d94af5d27f8d1b9ff83ab5fe0a1e044053c7a7c4d5d8efbf244d8a0dde6e2c54aff06a03d299\ 6be809b8f38485cca8b778031d2573144265c0b08b17d4ce46021d291fe2ced1c1651fe89bc9aa3ef3a597e6a2\ de0476b09468f5f7f6daab704b9b57b3bca0b78003e7292f58fb6cc1233faade85f71cbdb09c89fe238d2eb168\ 34873712a6029c93600f73dec810cabd220dc9a8db09808781a266e15e66d0f437e5c386e091b001b88c663074\ 75a726a9433ecf6b92036d22b4cd155583e253c725ea30aa6324ece6359f3073ccbcc60a293533cffbc01ba41d\ 71ccc1be564748ddfda8b02e8c2887a2c57ce1928d04de73bb86c4927030f96b30cb68f24e23ac337f529defa2\ 03d854f3b77a438d97b23335d551ccc1b79963b34f5b31200e1d1adc40de01db115a15d68bf6a71883373c0df2\ 1ce854c4788a7bff235f0dead4ff81051c464684cfab71f406ef4602cd6d04e62212ba34200b4eeca0322ce6a6\ a3e4fedbedd0806ce78d035cd7fbc8170e04b823d341bac8e1aad126a02815ed54a3a1eda2a#10000", Greater, ); let pi_over_3_f32 = Float::pi_over_3_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_over_3_f32.to_string(), "1.0471976"); assert_eq!(to_hex_string(&pi_over_3_f32), "0x1.0c1524#24"); assert_eq!(pi_over_3_f32, f32::PI_OVER_3); let pi_over_3_f64 = Float::pi_over_3_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_over_3_f64.to_string(), "1.0471975511965979"); assert_eq!(to_hex_string(&pi_over_3_f64), "0x1.0c152382d7366#53"); assert_eq!(pi_over_3_f64, f64::PI_OVER_3); } #[test] #[should_panic] fn pi_over_3_prec_fail_1() { Float::pi_over_3_prec(0); } fn test_pi_over_3_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_over_3_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = pi_over_3_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_pi_over_3_prec_round() { test_pi_over_3_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_pi_over_3_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_pi_over_3_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_pi_over_3_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_pi_over_3_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Less); test_pi_over_3_prec_round_helper(2, Floor, "1.0", "0x1.0#2", Less); test_pi_over_3_prec_round_helper(2, Ceiling, "1.5", "0x1.8#2", Greater); test_pi_over_3_prec_round_helper(2, Down, "1.0", "0x1.0#2", Less); test_pi_over_3_prec_round_helper(2, Up, "1.5", "0x1.8#2", Greater); test_pi_over_3_prec_round_helper(2, Nearest, "1.0", "0x1.0#2", Less); test_pi_over_3_prec_round_helper(3, Floor, "1.0", "0x1.0#3", Less); test_pi_over_3_prec_round_helper(3, Ceiling, "1.2", "0x1.4#3", Greater); test_pi_over_3_prec_round_helper(3, Down, "1.0", "0x1.0#3", Less); test_pi_over_3_prec_round_helper(3, Up, "1.2", "0x1.4#3", Greater); test_pi_over_3_prec_round_helper(3, Nearest, "1.0", "0x1.0#3", Less); test_pi_over_3_prec_round_helper(4, Floor, "1.0", "0x1.0#4", Less); test_pi_over_3_prec_round_helper(4, Ceiling, "1.1", "0x1.2#4", Greater); test_pi_over_3_prec_round_helper(4, Down, "1.0", "0x1.0#4", Less); test_pi_over_3_prec_round_helper(4, Up, "1.1", "0x1.2#4", Greater); test_pi_over_3_prec_round_helper(4, Nearest, "1.0", "0x1.0#4", Less); test_pi_over_3_prec_round_helper(5, Floor, "1.0", "0x1.0#5", Less); test_pi_over_3_prec_round_helper(5, Ceiling, "1.06", "0x1.1#5", Greater); test_pi_over_3_prec_round_helper(5, Down, "1.0", "0x1.0#5", Less); test_pi_over_3_prec_round_helper(5, Up, "1.06", "0x1.1#5", Greater); test_pi_over_3_prec_round_helper(5, Nearest, "1.06", "0x1.1#5", Greater); test_pi_over_3_prec_round_helper(6, Floor, "1.03", "0x1.08#6", Less); test_pi_over_3_prec_round_helper(6, Ceiling, "1.06", "0x1.10#6", Greater); test_pi_over_3_prec_round_helper(6, Down, "1.03", "0x1.08#6", Less); test_pi_over_3_prec_round_helper(6, Up, "1.06", "0x1.10#6", Greater); test_pi_over_3_prec_round_helper(6, Nearest, "1.06", "0x1.10#6", Greater); test_pi_over_3_prec_round_helper(7, Floor, "1.05", "0x1.0c#7", Less); test_pi_over_3_prec_round_helper(7, Ceiling, "1.06", "0x1.10#7", Greater); test_pi_over_3_prec_round_helper(7, Down, "1.05", "0x1.0c#7", Less); test_pi_over_3_prec_round_helper(7, Up, "1.06", "0x1.10#7", Greater); test_pi_over_3_prec_round_helper(7, Nearest, "1.05", "0x1.0c#7", Less); test_pi_over_3_prec_round_helper(8, Floor, "1.047", "0x1.0c#8", Less); test_pi_over_3_prec_round_helper(8, Ceiling, "1.055", "0x1.0e#8", Greater); test_pi_over_3_prec_round_helper(8, Down, "1.047", "0x1.0c#8", Less); test_pi_over_3_prec_round_helper(8, Up, "1.055", "0x1.0e#8", Greater); test_pi_over_3_prec_round_helper(8, Nearest, "1.047", "0x1.0c#8", Less); test_pi_over_3_prec_round_helper(9, Floor, "1.047", "0x1.0c#9", Less); test_pi_over_3_prec_round_helper(9, Ceiling, "1.051", "0x1.0d#9", Greater); test_pi_over_3_prec_round_helper(9, Down, "1.047", "0x1.0c#9", Less); test_pi_over_3_prec_round_helper(9, Up, "1.051", "0x1.0d#9", Greater); test_pi_over_3_prec_round_helper(9, Nearest, "1.047", "0x1.0c#9", Less); test_pi_over_3_prec_round_helper(10, Floor, "1.047", "0x1.0c0#10", Less); test_pi_over_3_prec_round_helper(10, Ceiling, "1.049", "0x1.0c8#10", Greater); test_pi_over_3_prec_round_helper(10, Down, "1.047", "0x1.0c0#10", Less); test_pi_over_3_prec_round_helper(10, Up, "1.049", "0x1.0c8#10", Greater); test_pi_over_3_prec_round_helper(10, Nearest, "1.047", "0x1.0c0#10", Less); test_pi_over_3_prec_round_helper( 100, Floor, "1.047197551196597746154214461092", "0x1.0c152382d73658465bb32e0f4#100", Less, ); test_pi_over_3_prec_round_helper( 100, Ceiling, "1.047197551196597746154214461094", "0x1.0c152382d73658465bb32e0f6#100", Greater, ); test_pi_over_3_prec_round_helper( 100, Down, "1.047197551196597746154214461092", "0x1.0c152382d73658465bb32e0f4#100", Less, ); test_pi_over_3_prec_round_helper( 100, Up, "1.047197551196597746154214461094", "0x1.0c152382d73658465bb32e0f6#100", Greater, ); test_pi_over_3_prec_round_helper( 100, Nearest, "1.047197551196597746154214461094", "0x1.0c152382d73658465bb32e0f6#100", Greater, ); } #[test] #[should_panic] fn pi_over_3_prec_round_fail_1() { Float::pi_over_3_prec_round(0, Floor); } #[test] #[should_panic] fn pi_over_3_prec_round_fail_2() { Float::pi_over_3_prec_round(1, Exact); } #[test] #[should_panic] fn pi_over_3_prec_round_fail_3() { Float::pi_over_3_prec_round(1000, Exact); } #[test] fn pi_over_3_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi_over_3, o) = Float::pi_over_3_prec(prec); assert!(pi_over_3.is_valid()); assert_eq!(pi_over_3.get_prec(), Some(prec)); assert_eq!(pi_over_3.get_exponent(), Some(1)); assert_ne!(o, Equal); if o == Less { let (pi_over_3_alt, o_alt) = Float::pi_over_3_prec_round(prec, Ceiling); let mut next_upper = pi_over_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_3_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_3.is_power_of_2() { let (pi_over_3_alt, o_alt) = Float::pi_over_3_prec_round(prec, Floor); let mut next_lower = pi_over_3.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_3_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_3_alt, o_alt) = Float::pi_over_3_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_3_alt), ComparableFloatRef(&pi_over_3) ); assert_eq!(o_alt, o); let (pi_over_3_alt, o_alt) = pi_over_3_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_3_alt), ComparableFloatRef(&pi_over_3) ); assert_eq!(o_alt, o); }); } #[test] fn pi_over_3_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi_over_3, o) = Float::pi_over_3_prec_round(prec, rm); assert!(pi_over_3.is_valid()); assert_eq!(pi_over_3.get_prec(), Some(prec)); assert_eq!( pi_over_3.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 2 } else { 1 }) ); assert_ne!(o, Equal); if o == Less { let (pi_over_3_alt, o_alt) = Float::pi_over_3_prec_round(prec, Ceiling); let mut next_upper = pi_over_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_3_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_3.is_power_of_2() { let (pi_over_3_alt, o_alt) = Float::pi_over_3_prec_round(prec, Floor); let mut next_lower = pi_over_3.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_3_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_3_alt, o_alt) = pi_over_3_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&pi_over_3_alt), ComparableFloatRef(&pi_over_3) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_over_3_prec_round(prec, Exact)); }); test_constant(Float::pi_over_3_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi_over_4.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PiOver4; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_over_4_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_over_4_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_4_prec() { test_pi_over_4_prec_helper(1, "1.0", "0x1.0#1", Greater); test_pi_over_4_prec_helper(2, "0.8", "0x0.c#2", Less); test_pi_over_4_prec_helper(3, "0.8", "0x0.c#3", Less); test_pi_over_4_prec_helper(4, "0.81", "0x0.d#4", Greater); test_pi_over_4_prec_helper(5, "0.78", "0x0.c8#5", Less); test_pi_over_4_prec_helper(6, "0.78", "0x0.c8#6", Less); test_pi_over_4_prec_helper(7, "0.79", "0x0.ca#7", Greater); test_pi_over_4_prec_helper(8, "0.785", "0x0.c9#8", Less); test_pi_over_4_prec_helper(9, "0.785", "0x0.c90#9", Less); test_pi_over_4_prec_helper(10, "0.785", "0x0.c90#10", Less); test_pi_over_4_prec_helper( 100, "0.78539816339744830961566084582", "0x0.c90fdaa22168c234c4c6628b8#100", Less, ); test_pi_over_4_prec_helper( 1000, "0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008\ 706335529266995537021628320576661773461152387645557931339852032120279362571025675484630276\ 389911155737238732595491107202743916483361532118912058446695791317800477286412141730865087\ 1526135816620533484018150622853184", "0x0.c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef951\ 9b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7e\ dee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c#1000", Less, ); test_pi_over_4_prec_helper( 10000, "0.785398163397448309615660845819875721049292349843776455243736148076954101571552249657008\ 706335529266995537021628320576661773461152387645557931339852032120279362571025675484630276\ 389911155737238732595491107202743916483361532118912058446695791317800477286412141730865087\ 152613581662053348401815062285318431146751651578897043720380230240707313522928841091973147\ 590002832632637205116630346036737985377902358264317591439897988273046529345483152948276279\ 637018615594990687391837971438181222806984545752987282458418340610164160771505348736598806\ 184297675544965235925692634804294073294188096168704616917351283000142031786315890206946442\ 835689447402293409294680367110225306238357536637396342762698069922314730885504989028032255\ 490216008604539953407443692827490129676802837499999593244512487764932933204024079648756114\ 863836727075660630577063336171258815482797042752500784459688221646883302095355154294417286\ 825899563372607188867182789890715970588446898437989445464445133042806701653250481969152798\ 977304105049734523814300266371465819716484038345456992057575488008825463242248943405649853\ 472812430443820869782878893714310613537673987707383279215431963972268774595438659366234829\ 813765100231925417784752462206003214590400890926915026177545485738899049736691959362362063\ 844943681711776011883661552011671064767372823328419257247288026188040514241506014509537548\ 377813345607508896910061874118315978549818151067480699195588695409002335430410304981146578\ 757571545743638926687459626373647146731748922731802699377325738830291336246800688990059120\ 166374779970458699438391592451856635631965637954604393668222744443198450020411765004036312\ 298043304303693087535360493392137040340289338138033368935462367109630830976848535833636940\ 604215629745892371390524804805546068137563564221917947623650413366701247156808197946521446\ 095956991994170363525238470946590237670016056281301279348246224021032122156736401060491321\ 255552665296576686069655509798736261780928446740239091092979321866941164393490603472716458\ 161498953347619506897524866441019737817367099588148927456455655130622351931679869567120650\ 369247725660034098609363826267050874063112937349912857857452297664812734305424115378927464\ 596852649471489943243874732540438482117034567170967235693538997963981311488489857762493131\ 170211496818411173962163459184055656524781152012810971097612811034137440695199428922858999\ 425032404022360423717138962101588355518056457122162039614007126504210684863066866919723813\ 034630637488666681955996614149029088721557644364124508898408642043581028128769017369862774\ 149023506307219927723286417284216807187235140025375827154482170230218690229456234647252428\ 727418996315341387445473282446205420749737180664701214391003567619388783094910362880936558\ 591135714611198816466955262785338683934880778356791525533992384057860738121234296777536441\ 350897569983600935501827644634765549596861952119622420830361428467187985876607554613297762\ 120251342653670168729819547799484988015354915857188610160936280929548044999597753979890453\ 66878567280993723522679662355799039198630201", "0x0.c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef951\ 9b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7e\ dee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8f\ d24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c329\ 05e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956\ ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea715\ 75d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d\ 87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0f\ d108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e\ 9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7e\ d1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93\ 402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06\ a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7a\ f426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a8403\ 1900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d81\ 4cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef\ 29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777\ cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f56\ 83423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646\ cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf3\ 10ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa\ 268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e\ 2765694dfc81f56e880b96e7160c980dd98a573ea4472065a139cd2906cd1cb729ec52a5286d44014a694ca457\ 583d5cfef26f1b90ad8291da0799d00022e9bed55c6fa47fca5bb1aca8376456d98d94879ee7e6dbfcd014bb16\ 1559914ec0b576a67e3e8422e91e65ba141da92de9c3a6d6cca5136dd424bb1064988eb5ba9ac1269f7df673b9\ 82e23fb6c99bb2aa31c5a6685ffd599149b30ac67b8464d80a95d42530a681644d039060e8f8fd5262696d0a75\ 95ae3f935a67dcff5a874a701fbfa0c3d534b4e39bc09577053374821a11c3ac998e0ba718087b317825a1acfc\ faebbf24f25c6051ada9c285a1fcd6114a838a1ade714c16a9401cdcf81e1071ff7ab97239f#10000", Less, ); let pi_over_4_f32 = Float::pi_over_4_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_over_4_f32.to_string(), "0.78539819"); assert_eq!(to_hex_string(&pi_over_4_f32), "0x0.c90fdb#24"); assert_eq!(pi_over_4_f32, f32::PI_OVER_4); let pi_over_4_f64 = Float::pi_over_4_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_over_4_f64.to_string(), "0.7853981633974483"); assert_eq!(to_hex_string(&pi_over_4_f64), "0x0.c90fdaa22168c0#53"); assert_eq!(pi_over_4_f64, f64::PI_OVER_4); } #[test] #[should_panic] fn pi_over_4_prec_fail_1() { Float::pi_over_4_prec(0); } fn test_pi_over_4_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_over_4_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_4_prec_round() { test_pi_over_4_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_pi_over_4_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_pi_over_4_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_pi_over_4_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_pi_over_4_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Greater); test_pi_over_4_prec_round_helper(2, Floor, "0.8", "0x0.c#2", Less); test_pi_over_4_prec_round_helper(2, Ceiling, "1.0", "0x1.0#2", Greater); test_pi_over_4_prec_round_helper(2, Down, "0.8", "0x0.c#2", Less); test_pi_over_4_prec_round_helper(2, Up, "1.0", "0x1.0#2", Greater); test_pi_over_4_prec_round_helper(2, Nearest, "0.8", "0x0.c#2", Less); test_pi_over_4_prec_round_helper(3, Floor, "0.8", "0x0.c#3", Less); test_pi_over_4_prec_round_helper(3, Ceiling, "0.9", "0x0.e#3", Greater); test_pi_over_4_prec_round_helper(3, Down, "0.8", "0x0.c#3", Less); test_pi_over_4_prec_round_helper(3, Up, "0.9", "0x0.e#3", Greater); test_pi_over_4_prec_round_helper(3, Nearest, "0.8", "0x0.c#3", Less); test_pi_over_4_prec_round_helper(4, Floor, "0.75", "0x0.c#4", Less); test_pi_over_4_prec_round_helper(4, Ceiling, "0.81", "0x0.d#4", Greater); test_pi_over_4_prec_round_helper(4, Down, "0.75", "0x0.c#4", Less); test_pi_over_4_prec_round_helper(4, Up, "0.81", "0x0.d#4", Greater); test_pi_over_4_prec_round_helper(4, Nearest, "0.81", "0x0.d#4", Greater); test_pi_over_4_prec_round_helper(5, Floor, "0.78", "0x0.c8#5", Less); test_pi_over_4_prec_round_helper(5, Ceiling, "0.81", "0x0.d0#5", Greater); test_pi_over_4_prec_round_helper(5, Down, "0.78", "0x0.c8#5", Less); test_pi_over_4_prec_round_helper(5, Up, "0.81", "0x0.d0#5", Greater); test_pi_over_4_prec_round_helper(5, Nearest, "0.78", "0x0.c8#5", Less); test_pi_over_4_prec_round_helper(6, Floor, "0.78", "0x0.c8#6", Less); test_pi_over_4_prec_round_helper(6, Ceiling, "0.8", "0x0.cc#6", Greater); test_pi_over_4_prec_round_helper(6, Down, "0.78", "0x0.c8#6", Less); test_pi_over_4_prec_round_helper(6, Up, "0.8", "0x0.cc#6", Greater); test_pi_over_4_prec_round_helper(6, Nearest, "0.78", "0x0.c8#6", Less); test_pi_over_4_prec_round_helper(7, Floor, "0.78", "0x0.c8#7", Less); test_pi_over_4_prec_round_helper(7, Ceiling, "0.79", "0x0.ca#7", Greater); test_pi_over_4_prec_round_helper(7, Down, "0.78", "0x0.c8#7", Less); test_pi_over_4_prec_round_helper(7, Up, "0.79", "0x0.ca#7", Greater); test_pi_over_4_prec_round_helper(7, Nearest, "0.79", "0x0.ca#7", Greater); test_pi_over_4_prec_round_helper(8, Floor, "0.785", "0x0.c9#8", Less); test_pi_over_4_prec_round_helper(8, Ceiling, "0.789", "0x0.ca#8", Greater); test_pi_over_4_prec_round_helper(8, Down, "0.785", "0x0.c9#8", Less); test_pi_over_4_prec_round_helper(8, Up, "0.789", "0x0.ca#8", Greater); test_pi_over_4_prec_round_helper(8, Nearest, "0.785", "0x0.c9#8", Less); test_pi_over_4_prec_round_helper(9, Floor, "0.785", "0x0.c90#9", Less); test_pi_over_4_prec_round_helper(9, Ceiling, "0.787", "0x0.c98#9", Greater); test_pi_over_4_prec_round_helper(9, Down, "0.785", "0x0.c90#9", Less); test_pi_over_4_prec_round_helper(9, Up, "0.787", "0x0.c98#9", Greater); test_pi_over_4_prec_round_helper(9, Nearest, "0.785", "0x0.c90#9", Less); test_pi_over_4_prec_round_helper(10, Floor, "0.785", "0x0.c90#10", Less); test_pi_over_4_prec_round_helper(10, Ceiling, "0.786", "0x0.c94#10", Greater); test_pi_over_4_prec_round_helper(10, Down, "0.785", "0x0.c90#10", Less); test_pi_over_4_prec_round_helper(10, Up, "0.786", "0x0.c94#10", Greater); test_pi_over_4_prec_round_helper(10, Nearest, "0.785", "0x0.c90#10", Less); test_pi_over_4_prec_round_helper( 100, Floor, "0.78539816339744830961566084582", "0x0.c90fdaa22168c234c4c6628b8#100", Less, ); test_pi_over_4_prec_round_helper( 100, Ceiling, "0.7853981633974483096156608458206", "0x0.c90fdaa22168c234c4c6628b9#100", Greater, ); test_pi_over_4_prec_round_helper( 100, Down, "0.78539816339744830961566084582", "0x0.c90fdaa22168c234c4c6628b8#100", Less, ); test_pi_over_4_prec_round_helper( 100, Up, "0.7853981633974483096156608458206", "0x0.c90fdaa22168c234c4c6628b9#100", Greater, ); test_pi_over_4_prec_round_helper( 100, Nearest, "0.78539816339744830961566084582", "0x0.c90fdaa22168c234c4c6628b8#100", Less, ); } #[test] #[should_panic] fn pi_over_4_prec_round_fail_1() { Float::pi_over_4_prec_round(0, Floor); } #[test] #[should_panic] fn pi_over_4_prec_round_fail_2() { Float::pi_over_4_prec_round(1, Exact); } #[test] #[should_panic] fn pi_over_4_prec_round_fail_3() { Float::pi_over_4_prec_round(1000, Exact); } #[test] fn pi_over_4_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi_over_4, o) = Float::pi_over_4_prec(prec); assert!(pi_over_4.is_valid()); assert_eq!(pi_over_4.get_prec(), Some(prec)); assert_eq!( pi_over_4.get_exponent(), Some(if prec == 1 { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (pi_over_4_alt, o_alt) = Float::pi_over_4_prec_round(prec, Ceiling); let mut next_upper = pi_over_4.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_4_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_4.is_power_of_2() { let (pi_over_4_alt, o_alt) = Float::pi_over_4_prec_round(prec, Floor); let mut next_lower = pi_over_4.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_4_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_4_alt, o_alt) = Float::pi_over_4_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_4_alt), ComparableFloatRef(&pi_over_4) ); assert_eq!(o_alt, o); }); } #[test] fn pi_over_4_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi_over_4, o) = Float::pi_over_4_prec_round(prec, rm); assert!(pi_over_4.is_valid()); assert_eq!(pi_over_4.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 1, _ => 0, }; assert_eq!(pi_over_4.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (pi_over_4_alt, o_alt) = Float::pi_over_4_prec_round(prec, Ceiling); let mut next_upper = pi_over_4.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_4_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_4.is_power_of_2() { let (pi_over_4_alt, o_alt) = Float::pi_over_4_prec_round(prec, Floor); let mut next_lower = pi_over_4.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_4_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_over_4_prec_round(prec, Exact)); }); test_constant(Float::pi_over_4_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi_over_6.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PiOver6; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_over_6_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_over_6_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_6_prec() { test_pi_over_6_prec_helper(1, "0.5", "0x0.8#1", Less); test_pi_over_6_prec_helper(2, "0.5", "0x0.8#2", Less); test_pi_over_6_prec_helper(3, "0.5", "0x0.8#3", Less); test_pi_over_6_prec_helper(4, "0.5", "0x0.8#4", Less); test_pi_over_6_prec_helper(5, "0.53", "0x0.88#5", Greater); test_pi_over_6_prec_helper(6, "0.53", "0x0.88#6", Greater); test_pi_over_6_prec_helper(7, "0.523", "0x0.86#7", Less); test_pi_over_6_prec_helper(8, "0.523", "0x0.86#8", Less); test_pi_over_6_prec_helper(9, "0.523", "0x0.860#9", Less); test_pi_over_6_prec_helper(10, "0.523", "0x0.860#10", Less); test_pi_over_6_prec_helper( 100, "0.523598775598298873077107230547", "0x0.860a91c16b9b2c232dd99707b#100", Greater, ); test_pi_over_6_prec_helper( 1000, "0.523598775598298873077107230546583814032861566562517636829157432051302734381034833104672\ 470890352844663691347752213717774515640768258430371954226568021413519575047350450323086850\ 926607437158159155063660738135162610988907688079274705631130527545200318190941427820576724\ 7684090544413688989345433748568789", "0x0.860a91c16b9b2c232dd99707ab3d688b70ac3405b19a884d56b27f197cb7bcc18b86b0510978033e9fb8b\ bcd337c2cbccac75c494c3f62cf8a96239e48e12c2e985923a441945484a2dd81f1197a9e475d54e879f8047a9\ e9ed047fce7066a6e746a180ba832154430c5998bf342e77e8155a87b16427f591091857968#1000", Less, ); test_pi_over_6_prec_helper( 10000, "0.523598775598298873077107230546583814032861566562517636829157432051302734381034833104672\ 470890352844663691347752213717774515640768258430371954226568021413519575047350450323086850\ 926607437158159155063660738135162610988907688079274705631130527545200318190941427820576724\ 768409054441368898934543374856878954097834434385931362480253486827138209015285894061315431\ 726668555088424803411086897357825323585268238842878394293265325515364352896988768632184186\ 424679077063327124927891980958787481871323030501991521638945560406776107181003565824399204\ 122865117029976823950461756536196048862792064112469744611567522000094687857543926804630961\ 890459631601528939529786911406816870825571691091597561841798713281543153923669992685354836\ 993477339069693302271629128551660086451201891666666395496341658509955288802682719765837409\ 909224484717107087051375557447505876988531361835000522973125481097922201396903436196278191\ 217266375581738125911455193260477313725631265625326296976296755361871134435500321312768532\ 651536070033156349209533510914310546477656025563637994705050325339216975494832628937099902\ 315208286962547246521919262476207075691782658471588852810287975981512516396959106244156553\ 209176733487950278523168308137335476393600593951276684118363657159266033157794639574908042\ 563295787807850674589107701341114043178248548885612838164858684125360342827670676339691698\ 918542230405005931273374582745543985699878767378320466130392463606001556953606869987431052\ 505047697162425951124973084249098097821165948487868466251550492553527557497867125993372746\ 777583186646972466292261061634571090421310425303069595778815162962132300013607843336024208\ 198695536202462058356906995594758026893526225425355579290308244739753887317899023889091293\ 736143753163928247593683203203697378758375709481278631749100275577800831437872131964347630\ 730637994662780242350158980631060158446677370854200852898830816014021414771157600706994214\ 170368443531051124046437006532490841187285631160159394061986214577960776262327068981810972\ 107665968898413004598349910960679825211578066392099284970970436753748234621119913044747100\ 246165150440022732406242550844700582708741958233275238571634865109875156203616076919284976\ 397901766314326628829249821693625654744689711447311490462359331975987540992326571841662087\ 446807664545607449308108972789370437683187434675207314065075207356091627130132952615239332\ 950021602681573615811425974734392237012037638081441359742671417669473789908711244613149208\ 689753758325777787970664409432686059147705096242749672598939094695720685419179344913241849\ 432682337538146618482190944856144538124823426683583884769654780153479126819637489764834952\ 484945997543560924963648854964136947166491453776467476260669045079592522063273575253957705\ 727423809740799210977970175190225789289920518904527683689328256038573825414156197851690960\ 900598379989067290334551763089843699731241301413081613886907618978125323917738369742198508\ 080167561769113445819879698532989992010236610571459073440624187286365363333065169319926969\ 11252378187329149015119774903866026132420136", "0x0.860a91c16b9b2c232dd99707ab3d688b70ac3405b19a884d56b27f197cb7bcc18b86b0510978033e9fb8b\ bcd337c2cbccac75c494c3f62cf8a96239e48e12c2e985923a441945484a2dd81f1197a9e475d54e879f8047a9\ e9ed047fce7066a6e746a180ba832154430c5998bf342e77e8155a87b16427f5910918579683937bc460ed51b5\ 36ddf950243936d3dc273b96841f78ec058e1d269e370afa0646448ef5d78dedc7dbaadf64d9d5b31656ba821b\ 5942ec979ded297befa1d655f0402676fad174805170a792e3ea04a32e1dbe97287f9b8e564bad10e30fdf1b8f\ 1ee0e8c1965bb5158b563a1b43c5c71d81e737764b35835a6cd1ae36bc7ea1326edf35258ad90929f5c5c9c4b8\ f93595da92264b503c49698851d4e745de75b77e4bf086340316e4113df428c196737499d4b755159e65c05989\ 04eac4cd4859c42e16a1cbaba52155dd2960f8fa6eb939da4b105d5d1e62f415b418a6af8991ccb82923d5340a\ 8b5b432573615c616055611a17d61c505448fb04bbc0b2926e76f112cc4baf1f896d2bc62f023240e07e6c3ad4\ 686c7383345e7d281e758945f50c9b4a80d6a7f31c41afd90da3447d593bbcc643515b5d7c16cd26baee0e7eff\ 36a40c64b34973a752567e8f96ba030133559b61a8e7591c662789c65b3b53e8104aa7a930b19d5b4dea2ce862\ 2ac586179d7fc788c52f56f2be33dcc40198494864e144ed3d17a7ea5ffb80473bee209ee922574d620011f204\ 6e29e601a9020ba64c5205991b0bb3c29e7f28a676348d8899dd1df387cbd3cff62da99dd6e3222158b8b728fc\ a2c4a7b4d5625088c7f910286abd987b748a021f163e0f6be02a301e53449a354a48e3ef574d9bab301ce702ac\ bb55cbdbee69a865529da9b4cc270fc5424885b295f68d92554e591d8dd380521722b8dc7330a48ff2a3096900\ ddd948c0a557a95c50f63f4a1bd421aaf168e5d252e91a4a38b1c2906bfd54b476688766cb7e3933c39dbf2c9f\ 70ecc25aa9b3a497d58455829b4eed4daeb4961d4c8e75cf84de499b8a614492960e64dc2619f61ff43ed7afa5\ 32470cc9508907f2de04d262126d28577245e693755a2bfc52a5ca82ff36e4f4f0cf26d6d997c7242683c98a39\ acd6d22f81d4bdba56d0a0f3297be4373ed53d07f5303073b6c16c9586d57a804b7f23a70116d4b2f784d52ed9\ df1759cdd3285aeca57ae93fc68dcffc1d5aff050f022029e3d3e26aec77df9226c506ef37162a57f83501e94c\ b5f404dc79c242e6545bbc018e92b98a2132e058458bea6723010e948ff16768e0b28ff44de4d51f79d2cbf351\ 6f023b584a347afbfb6d55b825cdabd9de505bc001f39497ac7db660919fd56f42fb8e5ed84e44ff11c69758b4\ 1a439b8953014e49b007b9ef6408655e9106e4d46d84c043c0d13370af33687a1bf2e1c37048d800dc4633183a\ 3ad39354a19f67b5c901b6915a668aaac1f129e392f51855319276731acf9839e65e6305149a99e7fde00dd20e\ b8e660df2b23a46efed45817461443d162be70c946826f39ddc3624938187cb59865b4792711d619bfa94ef7d1\ 01ec2a79dbbd21c6cbd9199aeaa8e660dbccb1d9a7ad9890070e8d6e206f00ed88ad0aeb45fb538c419b9e06f9\ 0e742a623c453dff91af86f56a7fc0828e23234267d5b8fa0377a30166b6827311095d1a1005a7765019167353\ 51f27f6df6e8403673c681ae6bfde40b87025c11e9a0dd6470d5689350140af6aa51d0f6d15#10000", Greater, ); let pi_over_6_f32 = Float::pi_over_6_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_over_6_f32.to_string(), "0.52359879"); assert_eq!(to_hex_string(&pi_over_6_f32), "0x0.860a92#24"); assert_eq!(pi_over_6_f32, f32::PI_OVER_6); let pi_over_6_f64 = Float::pi_over_6_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_over_6_f64.to_string(), "0.5235987755982989"); assert_eq!(to_hex_string(&pi_over_6_f64), "0x0.860a91c16b9b30#53"); assert_eq!(pi_over_6_f64, f64::PI_OVER_6); } #[test] #[should_panic] fn pi_over_6_prec_fail_1() { Float::pi_over_6_prec(0); } fn test_pi_over_6_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_over_6_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_6_prec_round() { test_pi_over_6_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_pi_over_6_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_pi_over_6_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_pi_over_6_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_pi_over_6_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_pi_over_6_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_pi_over_6_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_pi_over_6_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_pi_over_6_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_pi_over_6_prec_round_helper(2, Nearest, "0.5", "0x0.8#2", Less); test_pi_over_6_prec_round_helper(3, Floor, "0.5", "0x0.8#3", Less); test_pi_over_6_prec_round_helper(3, Ceiling, "0.6", "0x0.a#3", Greater); test_pi_over_6_prec_round_helper(3, Down, "0.5", "0x0.8#3", Less); test_pi_over_6_prec_round_helper(3, Up, "0.6", "0x0.a#3", Greater); test_pi_over_6_prec_round_helper(3, Nearest, "0.5", "0x0.8#3", Less); test_pi_over_6_prec_round_helper(4, Floor, "0.5", "0x0.8#4", Less); test_pi_over_6_prec_round_helper(4, Ceiling, "0.56", "0x0.9#4", Greater); test_pi_over_6_prec_round_helper(4, Down, "0.5", "0x0.8#4", Less); test_pi_over_6_prec_round_helper(4, Up, "0.56", "0x0.9#4", Greater); test_pi_over_6_prec_round_helper(4, Nearest, "0.5", "0x0.8#4", Less); test_pi_over_6_prec_round_helper(5, Floor, "0.5", "0x0.80#5", Less); test_pi_over_6_prec_round_helper(5, Ceiling, "0.53", "0x0.88#5", Greater); test_pi_over_6_prec_round_helper(5, Down, "0.5", "0x0.80#5", Less); test_pi_over_6_prec_round_helper(5, Up, "0.53", "0x0.88#5", Greater); test_pi_over_6_prec_round_helper(5, Nearest, "0.53", "0x0.88#5", Greater); test_pi_over_6_prec_round_helper(6, Floor, "0.52", "0x0.84#6", Less); test_pi_over_6_prec_round_helper(6, Ceiling, "0.53", "0x0.88#6", Greater); test_pi_over_6_prec_round_helper(6, Down, "0.52", "0x0.84#6", Less); test_pi_over_6_prec_round_helper(6, Up, "0.53", "0x0.88#6", Greater); test_pi_over_6_prec_round_helper(6, Nearest, "0.53", "0x0.88#6", Greater); test_pi_over_6_prec_round_helper(7, Floor, "0.523", "0x0.86#7", Less); test_pi_over_6_prec_round_helper(7, Ceiling, "0.53", "0x0.88#7", Greater); test_pi_over_6_prec_round_helper(7, Down, "0.523", "0x0.86#7", Less); test_pi_over_6_prec_round_helper(7, Up, "0.53", "0x0.88#7", Greater); test_pi_over_6_prec_round_helper(7, Nearest, "0.523", "0x0.86#7", Less); test_pi_over_6_prec_round_helper(8, Floor, "0.523", "0x0.86#8", Less); test_pi_over_6_prec_round_helper(8, Ceiling, "0.527", "0x0.87#8", Greater); test_pi_over_6_prec_round_helper(8, Down, "0.523", "0x0.86#8", Less); test_pi_over_6_prec_round_helper(8, Up, "0.527", "0x0.87#8", Greater); test_pi_over_6_prec_round_helper(8, Nearest, "0.523", "0x0.86#8", Less); test_pi_over_6_prec_round_helper(9, Floor, "0.523", "0x0.860#9", Less); test_pi_over_6_prec_round_helper(9, Ceiling, "0.525", "0x0.868#9", Greater); test_pi_over_6_prec_round_helper(9, Down, "0.523", "0x0.860#9", Less); test_pi_over_6_prec_round_helper(9, Up, "0.525", "0x0.868#9", Greater); test_pi_over_6_prec_round_helper(9, Nearest, "0.523", "0x0.860#9", Less); test_pi_over_6_prec_round_helper(10, Floor, "0.523", "0x0.860#10", Less); test_pi_over_6_prec_round_helper(10, Ceiling, "0.524", "0x0.864#10", Greater); test_pi_over_6_prec_round_helper(10, Down, "0.523", "0x0.860#10", Less); test_pi_over_6_prec_round_helper(10, Up, "0.524", "0x0.864#10", Greater); test_pi_over_6_prec_round_helper(10, Nearest, "0.523", "0x0.860#10", Less); test_pi_over_6_prec_round_helper( 100, Floor, "0.523598775598298873077107230546", "0x0.860a91c16b9b2c232dd99707a#100", Less, ); test_pi_over_6_prec_round_helper( 100, Ceiling, "0.523598775598298873077107230547", "0x0.860a91c16b9b2c232dd99707b#100", Greater, ); test_pi_over_6_prec_round_helper( 100, Down, "0.523598775598298873077107230546", "0x0.860a91c16b9b2c232dd99707a#100", Less, ); test_pi_over_6_prec_round_helper( 100, Up, "0.523598775598298873077107230547", "0x0.860a91c16b9b2c232dd99707b#100", Greater, ); test_pi_over_6_prec_round_helper( 100, Nearest, "0.523598775598298873077107230547", "0x0.860a91c16b9b2c232dd99707b#100", Greater, ); } #[test] #[should_panic] fn pi_over_6_prec_round_fail_1() { Float::pi_over_6_prec_round(0, Floor); } #[test] #[should_panic] fn pi_over_6_prec_round_fail_2() { Float::pi_over_6_prec_round(1, Exact); } #[test] #[should_panic] fn pi_over_6_prec_round_fail_3() { Float::pi_over_6_prec_round(1000, Exact); } #[test] fn pi_over_6_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi_over_6, o) = Float::pi_over_6_prec(prec); assert!(pi_over_6.is_valid()); assert_eq!(pi_over_6.get_prec(), Some(prec)); assert_eq!(pi_over_6.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (pi_over_6_alt, o_alt) = Float::pi_over_6_prec_round(prec, Ceiling); let mut next_upper = pi_over_6.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_6_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_6.is_power_of_2() { let (pi_over_6_alt, o_alt) = Float::pi_over_6_prec_round(prec, Floor); let mut next_lower = pi_over_6.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_6_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_6_alt, o_alt) = Float::pi_over_6_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_6_alt), ComparableFloatRef(&pi_over_6) ); assert_eq!(o_alt, o); }); } #[test] fn pi_over_6_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi_over_6, o) = Float::pi_over_6_prec_round(prec, rm); assert!(pi_over_6.is_valid()); assert_eq!(pi_over_6.get_prec(), Some(prec)); assert_eq!( pi_over_6.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (pi_over_6_alt, o_alt) = Float::pi_over_6_prec_round(prec, Ceiling); let mut next_upper = pi_over_6.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_6_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_6.is_power_of_2() { let (pi_over_6_alt, o_alt) = Float::pi_over_6_prec_round(prec, Floor); let mut next_lower = pi_over_6.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_6_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_over_6_prec_round(prec, Exact)); }); test_constant(Float::pi_over_6_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/pi_over_8.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PiOver8; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_pi_over_8_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::pi_over_8_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_8_prec() { test_pi_over_8_prec_helper(1, "0.5", "0x0.8#1", Greater); test_pi_over_8_prec_helper(2, "0.4", "0x0.6#2", Less); test_pi_over_8_prec_helper(3, "0.38", "0x0.6#3", Less); test_pi_over_8_prec_helper(4, "0.41", "0x0.68#4", Greater); test_pi_over_8_prec_helper(5, "0.39", "0x0.64#5", Less); test_pi_over_8_prec_helper(6, "0.39", "0x0.64#6", Less); test_pi_over_8_prec_helper(7, "0.395", "0x0.65#7", Greater); test_pi_over_8_prec_helper(8, "0.393", "0x0.648#8", Less); test_pi_over_8_prec_helper(9, "0.393", "0x0.648#9", Less); test_pi_over_8_prec_helper(10, "0.3926", "0x0.648#10", Less); test_pi_over_8_prec_helper( 100, "0.3926990816987241548078304229099", "0x0.6487ed5110b4611a62633145c0#100", Less, ); test_pi_over_8_prec_helper( 1000, "0.392699081698724154807830422909937860524646174921888227621868074038477050785776124828504\ 353167764633497768510814160288330886730576193822778965669926016060139681285512837742315138\ 194955577868619366297745553601371958241680766059456029223347895658900238643206070865432543\ 5763067908310266742009075311426592", "0x0.6487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8\ cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf\ 6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e0#1000", Less, ); test_pi_over_8_prec_helper( 10000, "0.392699081698724154807830422909937860524646174921888227621868074038477050785776124828504\ 353167764633497768510814160288330886730576193822778965669926016060139681285512837742315138\ 194955577868619366297745553601371958241680766059456029223347895658900238643206070865432543\ 576306790831026674200907531142659215573375825789448521860190115120353656761464420545986573\ 795001416316318602558315173018368992688951179132158795719948994136523264672741576474138139\ 818509307797495343695918985719090611403492272876493641229209170305082080385752674368299403\ 092148837772482617962846317402147036647094048084352308458675641500071015893157945103473221\ 417844723701146704647340183555112653119178768318698171381349034961157365442752494514016127\ 745108004302269976703721846413745064838401418749999796622256243882466466602012039824378057\ 431918363537830315288531668085629407741398521376250392229844110823441651047677577147208643\ 412949781686303594433591394945357985294223449218994722732222566521403350826625240984576399\ 488652052524867261907150133185732909858242019172728496028787744004412731621124471702824926\ 736406215221910434891439446857155306768836993853691639607715981986134387297719329683117414\ 906882550115962708892376231103001607295200445463457513088772742869449524868345979681181031\ 922471840855888005941830776005835532383686411664209628623644013094020257120753007254768774\ 188906672803754448455030937059157989274909075533740349597794347704501167715205152490573289\ 378785772871819463343729813186823573365874461365901349688662869415145668123400344495029560\ 083187389985229349719195796225928317815982818977302196834111372221599225010205882502018156\ 149021652151846543767680246696068520170144669069016684467731183554815415488424267916818470\ 302107814872946185695262402402773034068781782110958973811825206683350623578404098973260723\ 047978495997085181762619235473295118835008028140650639674123112010516061078368200530245660\ 627776332648288343034827754899368130890464223370119545546489660933470582196745301736358229\ 080749476673809753448762433220509868908683549794074463728227827565311175965839934783560325\ 184623862830017049304681913133525437031556468674956428928726148832406367152712057689463732\ 298426324735744971621937366270219241058517283585483617846769498981990655744244928881246565\ 585105748409205586981081729592027828262390576006405485548806405517068720347599714461429499\ 712516202011180211858569481050794177759028228561081019807003563252105342431533433459861906\ 517315318744333340977998307074514544360778822182062254449204321021790514064384508684931387\ 074511753153609963861643208642108403593617570012687913577241085115109345114728117323626214\ 363709498157670693722736641223102710374868590332350607195501783809694391547455181440468279\ 295567857305599408233477631392669341967440389178395762766996192028930369060617148388768220\ 675448784991800467750913822317382774798430976059811210415180714233593992938303777306648881\ 060125671326835084364909773899742494007677457928594305080468140464774022499798876989945226\ 834392836404968617613398311778995195993151", "0x0.6487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8\ cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf\ 6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47\ e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be194\ 82f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab\ 5728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538a\ bae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326\ c3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707\ e884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f\ 4e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f\ 68fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49\ a0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d7583\ 529f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd\ 7a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad4201\ 8c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0\ a662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f6177\ 94b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bb\ e5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab\ 41a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe323\ 6751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef9\ 887703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d\ 1341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f18287\ 13b2b4a6fe40fab74405cb738b064c06ecc52b9f52239032d09ce69483668e5b94f629529436a200a534a6522b\ ac1eae7f79378dc856c148ed03cce8001174df6aae37d23fe52dd8d6541bb22b6cc6ca43cf73f36dfe680a5d8b\ 0aacc8a7605abb533f1f4211748f32dd0a0ed496f4e1d36b665289b6ea125d88324c475add4d60934fbefb39dc\ c1711fdb64cdd95518e2d3342ffeacc8a4d985633dc2326c054aea12985340b22681c830747c7ea93134b6853a\ cad71fc9ad33ee7fad43a5380fdfd061ea9a5a71cde04abb8299ba410d08e1d64cc705d38c043d98bc12d0d67e\ 7d75df92792e3028d6d4e142d0fe6b08a541c50d6f38a60b54a00e6e7c0f0838ffbd5cb91cf8#10000", Less, ); let pi_over_8_f32 = Float::pi_over_8_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pi_over_8_f32.to_string(), "0.39269909"); assert_eq!(to_hex_string(&pi_over_8_f32), "0x0.6487ed8#24"); assert_eq!(pi_over_8_f32, f32::PI_OVER_8); let pi_over_8_f64 = Float::pi_over_8_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pi_over_8_f64.to_string(), "0.39269908169872414"); assert_eq!(to_hex_string(&pi_over_8_f64), "0x0.6487ed5110b460#53"); assert_eq!(pi_over_8_f64, f64::PI_OVER_8); } #[test] #[should_panic] fn pi_over_8_prec_fail_1() { Float::pi_over_8_prec(0); } fn test_pi_over_8_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::pi_over_8_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_pi_over_8_prec_round() { test_pi_over_8_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); test_pi_over_8_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); test_pi_over_8_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); test_pi_over_8_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); test_pi_over_8_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); test_pi_over_8_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); test_pi_over_8_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); test_pi_over_8_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); test_pi_over_8_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); test_pi_over_8_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); test_pi_over_8_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); test_pi_over_8_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); test_pi_over_8_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); test_pi_over_8_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); test_pi_over_8_prec_round_helper(3, Nearest, "0.38", "0x0.6#3", Less); test_pi_over_8_prec_round_helper(4, Floor, "0.38", "0x0.60#4", Less); test_pi_over_8_prec_round_helper(4, Ceiling, "0.41", "0x0.68#4", Greater); test_pi_over_8_prec_round_helper(4, Down, "0.38", "0x0.60#4", Less); test_pi_over_8_prec_round_helper(4, Up, "0.41", "0x0.68#4", Greater); test_pi_over_8_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Greater); test_pi_over_8_prec_round_helper(5, Floor, "0.39", "0x0.64#5", Less); test_pi_over_8_prec_round_helper(5, Ceiling, "0.41", "0x0.68#5", Greater); test_pi_over_8_prec_round_helper(5, Down, "0.39", "0x0.64#5", Less); test_pi_over_8_prec_round_helper(5, Up, "0.41", "0x0.68#5", Greater); test_pi_over_8_prec_round_helper(5, Nearest, "0.39", "0x0.64#5", Less); test_pi_over_8_prec_round_helper(6, Floor, "0.39", "0x0.64#6", Less); test_pi_over_8_prec_round_helper(6, Ceiling, "0.4", "0x0.66#6", Greater); test_pi_over_8_prec_round_helper(6, Down, "0.39", "0x0.64#6", Less); test_pi_over_8_prec_round_helper(6, Up, "0.4", "0x0.66#6", Greater); test_pi_over_8_prec_round_helper(6, Nearest, "0.39", "0x0.64#6", Less); test_pi_over_8_prec_round_helper(7, Floor, "0.391", "0x0.64#7", Less); test_pi_over_8_prec_round_helper(7, Ceiling, "0.395", "0x0.65#7", Greater); test_pi_over_8_prec_round_helper(7, Down, "0.391", "0x0.64#7", Less); test_pi_over_8_prec_round_helper(7, Up, "0.395", "0x0.65#7", Greater); test_pi_over_8_prec_round_helper(7, Nearest, "0.395", "0x0.65#7", Greater); test_pi_over_8_prec_round_helper(8, Floor, "0.393", "0x0.648#8", Less); test_pi_over_8_prec_round_helper(8, Ceiling, "0.395", "0x0.650#8", Greater); test_pi_over_8_prec_round_helper(8, Down, "0.393", "0x0.648#8", Less); test_pi_over_8_prec_round_helper(8, Up, "0.395", "0x0.650#8", Greater); test_pi_over_8_prec_round_helper(8, Nearest, "0.393", "0x0.648#8", Less); test_pi_over_8_prec_round_helper(9, Floor, "0.393", "0x0.648#9", Less); test_pi_over_8_prec_round_helper(9, Ceiling, "0.394", "0x0.64c#9", Greater); test_pi_over_8_prec_round_helper(9, Down, "0.393", "0x0.648#9", Less); test_pi_over_8_prec_round_helper(9, Up, "0.394", "0x0.64c#9", Greater); test_pi_over_8_prec_round_helper(9, Nearest, "0.393", "0x0.648#9", Less); test_pi_over_8_prec_round_helper(10, Floor, "0.3926", "0x0.648#10", Less); test_pi_over_8_prec_round_helper(10, Ceiling, "0.3931", "0x0.64a#10", Greater); test_pi_over_8_prec_round_helper(10, Down, "0.3926", "0x0.648#10", Less); test_pi_over_8_prec_round_helper(10, Up, "0.3931", "0x0.64a#10", Greater); test_pi_over_8_prec_round_helper(10, Nearest, "0.3926", "0x0.648#10", Less); test_pi_over_8_prec_round_helper( 100, Floor, "0.3926990816987241548078304229099", "0x0.6487ed5110b4611a62633145c0#100", Less, ); test_pi_over_8_prec_round_helper( 100, Ceiling, "0.3926990816987241548078304229103", "0x0.6487ed5110b4611a62633145c8#100", Greater, ); test_pi_over_8_prec_round_helper( 100, Down, "0.3926990816987241548078304229099", "0x0.6487ed5110b4611a62633145c0#100", Less, ); test_pi_over_8_prec_round_helper( 100, Up, "0.3926990816987241548078304229103", "0x0.6487ed5110b4611a62633145c8#100", Greater, ); test_pi_over_8_prec_round_helper( 100, Nearest, "0.3926990816987241548078304229099", "0x0.6487ed5110b4611a62633145c0#100", Less, ); } #[test] #[should_panic] fn pi_over_8_prec_round_fail_1() { Float::pi_over_8_prec_round(0, Floor); } #[test] #[should_panic] fn pi_over_8_prec_round_fail_2() { Float::pi_over_8_prec_round(1, Exact); } #[test] #[should_panic] fn pi_over_8_prec_round_fail_3() { Float::pi_over_8_prec_round(1000, Exact); } #[test] fn pi_over_8_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pi_over_8, o) = Float::pi_over_8_prec(prec); assert!(pi_over_8.is_valid()); assert_eq!(pi_over_8.get_prec(), Some(prec)); assert_eq!( pi_over_8.get_exponent(), Some(if prec == 1 { 0 } else { -1 }) ); assert_ne!(o, Equal); if o == Less { let (pi_over_8_alt, o_alt) = Float::pi_over_8_prec_round(prec, Ceiling); let mut next_upper = pi_over_8.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_8_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_8.is_power_of_2() { let (pi_over_8_alt, o_alt) = Float::pi_over_8_prec_round(prec, Floor); let mut next_lower = pi_over_8.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_8_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pi_over_8_alt, o_alt) = Float::pi_over_8_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&pi_over_8_alt), ComparableFloatRef(&pi_over_8) ); assert_eq!(o_alt, o); }); } #[test] fn pi_over_8_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pi_over_8, o) = Float::pi_over_8_prec_round(prec, rm); assert!(pi_over_8.is_valid()); assert_eq!(pi_over_8.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 0, _ => -1, }; assert_eq!(pi_over_8.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (pi_over_8_alt, o_alt) = Float::pi_over_8_prec_round(prec, Ceiling); let mut next_upper = pi_over_8.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pi_over_8_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pi_over_8.is_power_of_2() { let (pi_over_8_alt, o_alt) = Float::pi_over_8_prec_round(prec, Floor); let mut next_lower = pi_over_8.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pi_over_8_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::pi_over_8_prec_round(prec, Exact)); }); test_constant(Float::pi_over_8_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/prime_constant.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::PrimeConstant; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::prime_constant::prime_constant_prec_round_naive; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_prime_constant_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::prime_constant_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = prime_constant_prec_round_naive(prec, Nearest); assert_eq!(x, x_alt); assert_eq!(o, o_alt); } #[test] pub fn test_prime_constant_prec() { test_prime_constant_prec_helper(1, "0.5", "0x0.8#1", Greater); test_prime_constant_prec_helper(2, "0.4", "0x0.6#2", Less); test_prime_constant_prec_helper(3, "0.44", "0x0.7#3", Greater); test_prime_constant_prec_helper(4, "0.41", "0x0.68#4", Less); test_prime_constant_prec_helper(5, "0.42", "0x0.6c#5", Greater); test_prime_constant_prec_helper(6, "0.414", "0x0.6a#6", Less); test_prime_constant_prec_helper(7, "0.414", "0x0.6a#7", Less); test_prime_constant_prec_helper(8, "0.414", "0x0.6a0#8", Less); test_prime_constant_prec_helper(9, "0.415", "0x0.6a4#9", Greater); test_prime_constant_prec_helper(10, "0.4146", "0x0.6a2#10", Less); test_prime_constant_prec_helper( 100, "0.4146825098511116602481096221542", "0x0.6a28a20a08a208282282208088#100", Less, ); test_prime_constant_prec_helper( 1000, "0.414682509851111660248109622154307708365774238137916977868245414488640960619357334196290\ 048428475777939616159352082985957835749978453022009904120814650033958993701974119186285615\ 579237191637251488161071073428432480218016979856815134246794749243902778820311537783180662\ 98787003544718107300315282293658657", "0x0.6a28a20a08a20828228220808a28800220a00a08220828028a00200228828020820a08a00800228800208\ 028820208220808808028028220808a20020220220800a00008200820a08020828208a00200a20828008820200\ 808020208220208808800200800a00a28020008a20008a200002202008088208002208202080#1000", Less, ); test_prime_constant_prec_helper( 10000, "0.414682509851111660248109622154307708365774238137916977868245414488640960619357334196290\ 048428475777939616159352082985957835749978453022009904120814650033958993701974119186285615\ 579237191637251488161071073428432480218016979856815134246794749243902778820311537783180662\ 987870035447181073003152822936586571701195884345760580684835877525498698320011540191930758\ 099002319261468413919152574118369129168574279239129804341592424543430422903399908325112045\ 668292742611194732667211553722399175647987527658878910703815406904018048152558727250330913\ 032734465178315959501124916374515488312368223411699732976990859213965904304781712473399850\ 022855936162301792842610279636663239004692389139831027778036326093312778898964673169309518\ 310306063152926347489776338241054180226337674492907279938068989754912015273280509376794011\ 427472704319064395781618400649434291302477306540023894812147846692492936635719588061120657\ 051390501956020214967100891969377486235872143778145145772057385386205343716378192432613513\ 172804602223001006685864520195545148953810709046574934296166432665763774833905637940402631\ 576801946504697746229836623924610157737793410864303438788766145163542908821015516523230106\ 797290246886870760828326453371632716614992987127399459741555239537031562083871442168565303\ 189912375257157779026541835903342269582971374263275545243196592115378128694441070207946879\ 764496037081508369373832295654819400087481268863376301792472431388415929294658211923608901\ 402710138982797422281950231204740825160556996531760010125162932087538066645067994257503747\ 988951392973626720366328982170505846234832544143958403519197518756622565009818379834626553\ 617954708446358169530464486348037793106750286422766029143787907491013162528697477255180525\ 301688970187379440498919433856401585513390951795192326204312092377569597171283867789460769\ 396842845072133229690180683640002570495073917768933999215761139873608859874089589096776461\ 995923745390535138086006656259166023212941879359754829079532092146864715376576674216923592\ 356284657954731472882379615899071977783469111502062539802490350514979367013733212811256787\ 651076562739406500368100788692192060657019146542871834536027154909579465624259941136769107\ 561003973746479133595976239940200240349439391177366640902400434482715348474352654705232334\ 865757263289528822462280034190931946143020430007789481367871305250457767936834157491630698\ 107741376398506062111121345698764997552559136414698454192672485636202709453131509266585281\ 706706580881014762163488645479634465001692797445197175229384471918672226624328100132469141\ 109007889697011845498155181004138530396370327432831414575546500251524843825045622130807383\ 973351694821712447724540951485939349474765305310454105446321469155906341381357010374677903\ 488746578301462245594571327626904723478958729803396726212447661231362593184418074810567100\ 150303566417543158729492869454556673124380354806665894633517169712578312518114309438722159\ 398158466744490582994391095649028975452941714271570359608073520730264326067239780059666358\ 3765668592857275961081596601034186349684386", "0x0.6a28a20a08a20828228220808a28800220a00a08220828028a00200228828020820a08a00800228800208\ 028820208220808808028028220808a20020220220800a00008200820a08020828208a00200a20828008820200\ 808020208220208808800200800a00a28020008a20008a20000220200808820800220820208008828028200a00\ a08000228820808208000028020200820808008820a08008020000a20a08a20028200000000820808000200800\ 228820228200200a28820020020200208820220220008828828200800008228000008a00800a00808208200008\ 228008020020200020008228a00800820800028000a00000820208a20208028020008020800a28020028000a08\ a00808000200000220808000a20200028808208800a00000828220800208a08820020820008820020208800000\ 200008020220a08000020028000808800800200a20208228820228200a00808800200800a08a00020008820208\ 800020200820808020020008820a00000028020220008808008200220800008028000800000228008220020808\ 808000028a00200000028208220a00220028028000a00020800008000808a28000020200208028828200a00200\ a00800208820208200020028800208808020208200000828020008820000a00800228020008808000220a20a00\ 220000200000800a20828200000a08000820028200200028820008a00008000008020a00a00a00828028020808\ 000000200a00808200800020800800a00008220820000a00800208a20000028008200020208200008000a20a08\ 200820020020000a08800020200000228828008800200000008020800800208020028820208028800208220a00\ a00020020200008820028208200000020800220200808008000228800000800828000820800200800220000000\ 820820208a00208a08000020a20000a20028220000008208808020000000200028228a00800208808020800008\ a08000000220200820808200220a08828028000820000220020008000000820000220000808220800208200a00\ 800808028020200200800000a20208808000200820a08020028020820808200828208200808000008200000a00\ 008808020000000808000228020a08800020200200008000828008200a00a08020008800000a00028028020000\ 228808000820a00200020220800000028028220820208800820200220008008020000020800828000020200008\ 020800228200808220800000020008028008028000a00008000008000208000800020a00008828020200820808\ 828028008820a00220008000220800008808220220008220008008a00000008800000820800800800208a20000\ 820020208800a00200000008000a08000020008200800828808020820000020008220200200008028028820000\ 208800228800208008000008020808028000000220a00220008200000000800808200a20000200808000a00800\ 228008200020808808820208200208820808000220000220028020a00800a20000208000000208808020020a00\ 000028228000800a08020200000200208000208800208800808200220800820028000800008a00800020220008\ a08000020800208200828028a00000a20820020800200800820220000000020008008220a00208008000a00808\ 000028008220800028008220020208008820020a00200220008200020a008080002080000000#10000", Less, ); let pc_f32 = Float::prime_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(pc_f32.to_string(), "0.41468251"); assert_eq!(to_hex_string(&pc_f32), "0x0.6a28a20#24"); assert_eq!(pc_f32, f32::PRIME_CONSTANT); let pc_f64 = Float::prime_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(pc_f64.to_string(), "0.41468250985111166"); assert_eq!(to_hex_string(&pc_f64), "0x0.6a28a20a08a208#53"); assert_eq!(pc_f64, f64::PRIME_CONSTANT); } #[test] #[should_panic] fn prime_constant_prec_fail_1() { Float::prime_constant_prec(0); } fn test_prime_constant_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::prime_constant_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = prime_constant_prec_round_naive(prec, rm); assert_eq!(x, x_alt); assert_eq!(o, o_alt); } #[test] pub fn test_prime_constant_prec_round() { test_prime_constant_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); test_prime_constant_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); test_prime_constant_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); test_prime_constant_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); test_prime_constant_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); test_prime_constant_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); test_prime_constant_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); test_prime_constant_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); test_prime_constant_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); test_prime_constant_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); test_prime_constant_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); test_prime_constant_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); test_prime_constant_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); test_prime_constant_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); test_prime_constant_prec_round_helper(3, Nearest, "0.44", "0x0.7#3", Greater); test_prime_constant_prec_round_helper(4, Floor, "0.41", "0x0.68#4", Less); test_prime_constant_prec_round_helper(4, Ceiling, "0.44", "0x0.70#4", Greater); test_prime_constant_prec_round_helper(4, Down, "0.41", "0x0.68#4", Less); test_prime_constant_prec_round_helper(4, Up, "0.44", "0x0.70#4", Greater); test_prime_constant_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Less); test_prime_constant_prec_round_helper(5, Floor, "0.41", "0x0.68#5", Less); test_prime_constant_prec_round_helper(5, Ceiling, "0.42", "0x0.6c#5", Greater); test_prime_constant_prec_round_helper(5, Down, "0.41", "0x0.68#5", Less); test_prime_constant_prec_round_helper(5, Up, "0.42", "0x0.6c#5", Greater); test_prime_constant_prec_round_helper(5, Nearest, "0.42", "0x0.6c#5", Greater); test_prime_constant_prec_round_helper(6, Floor, "0.414", "0x0.6a#6", Less); test_prime_constant_prec_round_helper(6, Ceiling, "0.42", "0x0.6c#6", Greater); test_prime_constant_prec_round_helper(6, Down, "0.414", "0x0.6a#6", Less); test_prime_constant_prec_round_helper(6, Up, "0.42", "0x0.6c#6", Greater); test_prime_constant_prec_round_helper(6, Nearest, "0.414", "0x0.6a#6", Less); test_prime_constant_prec_round_helper(7, Floor, "0.414", "0x0.6a#7", Less); test_prime_constant_prec_round_helper(7, Ceiling, "0.418", "0x0.6b#7", Greater); test_prime_constant_prec_round_helper(7, Down, "0.414", "0x0.6a#7", Less); test_prime_constant_prec_round_helper(7, Up, "0.418", "0x0.6b#7", Greater); test_prime_constant_prec_round_helper(7, Nearest, "0.414", "0x0.6a#7", Less); test_prime_constant_prec_round_helper(8, Floor, "0.414", "0x0.6a0#8", Less); test_prime_constant_prec_round_helper(8, Ceiling, "0.416", "0x0.6a8#8", Greater); test_prime_constant_prec_round_helper(8, Down, "0.414", "0x0.6a0#8", Less); test_prime_constant_prec_round_helper(8, Up, "0.416", "0x0.6a8#8", Greater); test_prime_constant_prec_round_helper(8, Nearest, "0.414", "0x0.6a0#8", Less); test_prime_constant_prec_round_helper(9, Floor, "0.414", "0x0.6a0#9", Less); test_prime_constant_prec_round_helper(9, Ceiling, "0.415", "0x0.6a4#9", Greater); test_prime_constant_prec_round_helper(9, Down, "0.414", "0x0.6a0#9", Less); test_prime_constant_prec_round_helper(9, Up, "0.415", "0x0.6a4#9", Greater); test_prime_constant_prec_round_helper(9, Nearest, "0.415", "0x0.6a4#9", Greater); test_prime_constant_prec_round_helper(10, Floor, "0.4146", "0x0.6a2#10", Less); test_prime_constant_prec_round_helper(10, Ceiling, "0.415", "0x0.6a4#10", Greater); test_prime_constant_prec_round_helper(10, Down, "0.4146", "0x0.6a2#10", Less); test_prime_constant_prec_round_helper(10, Up, "0.415", "0x0.6a4#10", Greater); test_prime_constant_prec_round_helper(10, Nearest, "0.4146", "0x0.6a2#10", Less); test_prime_constant_prec_round_helper( 100, Floor, "0.4146825098511116602481096221542", "0x0.6a28a20a08a208282282208088#100", Less, ); test_prime_constant_prec_round_helper( 100, Ceiling, "0.4146825098511116602481096221546", "0x0.6a28a20a08a208282282208090#100", Greater, ); test_prime_constant_prec_round_helper( 100, Down, "0.4146825098511116602481096221542", "0x0.6a28a20a08a208282282208088#100", Less, ); test_prime_constant_prec_round_helper( 100, Up, "0.4146825098511116602481096221546", "0x0.6a28a20a08a208282282208090#100", Greater, ); test_prime_constant_prec_round_helper( 100, Nearest, "0.4146825098511116602481096221542", "0x0.6a28a20a08a208282282208088#100", Less, ); } #[test] #[should_panic] fn prime_constant_prec_round_fail_1() { Float::prime_constant_prec_round(0, Floor); } #[test] #[should_panic] fn prime_constant_prec_round_fail_2() { Float::prime_constant_prec_round(1, Exact); } #[test] #[should_panic] fn prime_constant_prec_round_fail_3() { Float::prime_constant_prec_round(1000, Exact); } #[test] fn prime_constant_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (pc, o) = Float::prime_constant_prec(prec); assert!(pc.is_valid()); assert_eq!(pc.get_prec(), Some(prec)); assert_ne!(o, Equal); assert_eq!(pc.get_exponent(), Some(if prec == 1 { 0 } else { -1 })); if o == Less { let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Ceiling); let mut next_upper = pc.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pc.is_power_of_2() { let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Floor); let mut next_lower = pc.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&pc_alt), ComparableFloatRef(&pc)); assert_eq!(o_alt, o); let (pc_alt, o_alt) = prime_constant_prec_round_naive(prec, Nearest); assert_eq!(pc, pc_alt); assert_eq!(o, o_alt); }); } #[test] fn prime_constant_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (pc, o) = Float::prime_constant_prec_round(prec, rm); assert!(pc.is_valid()); assert_eq!(pc.get_prec(), Some(prec)); assert_ne!(o, Equal); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 0, _ => -1, }; assert_eq!(pc.get_exponent(), Some(expected_exponent)); if o == Less { let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Ceiling); let mut next_upper = pc.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !pc.is_power_of_2() { let (pc_alt, o_alt) = Float::prime_constant_prec_round(prec, Floor); let mut next_lower = pc.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(pc_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (pc_alt, o_alt) = prime_constant_prec_round_naive(prec, rm); assert_eq!(pc, pc_alt); assert_eq!(o, o_alt); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::prime_constant_prec_round(prec, Exact)); }); test_constant(Float::prime_constant_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/prouhet_thue_morse_constant.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::ProuhetThueMorseConstant; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::prouhet_thue_morse_constant::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_prouhet_thue_morse_constant_prec_helper( prec: u64, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::prouhet_thue_morse_constant_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = prouhet_thue_morse_constant_prec_round_naive(prec, Nearest); assert_eq!(x, x_alt); assert_eq!(o, o_alt); } #[test] pub fn test_prouhet_thue_morse_constant_prec() { test_prouhet_thue_morse_constant_prec_helper(1, "0.5", "0x0.8#1", Greater); test_prouhet_thue_morse_constant_prec_helper(2, "0.4", "0x0.6#2", Less); test_prouhet_thue_morse_constant_prec_helper(3, "0.44", "0x0.7#3", Greater); test_prouhet_thue_morse_constant_prec_helper(4, "0.41", "0x0.68#4", Less); test_prouhet_thue_morse_constant_prec_helper(5, "0.41", "0x0.68#5", Less); test_prouhet_thue_morse_constant_prec_helper(6, "0.414", "0x0.6a#6", Greater); test_prouhet_thue_morse_constant_prec_helper(7, "0.414", "0x0.6a#7", Greater); test_prouhet_thue_morse_constant_prec_helper(8, "0.412", "0x0.698#8", Less); test_prouhet_thue_morse_constant_prec_helper(9, "0.412", "0x0.698#9", Less); test_prouhet_thue_morse_constant_prec_helper(10, "0.4126", "0x0.69a#10", Greater); test_prouhet_thue_morse_constant_prec_helper( 100, "0.4124540336401075977833613682584", "0x0.69969669966969969669699668#100", Less, ); test_prouhet_thue_morse_constant_prec_helper( 1000, "0.412454033640107597783361368258455283089478374455769557573379415348793592365782588963804\ 540486212133396256366446538137487421617125193606520130996812525914093898811685058241405148\ 794923736837717681632072372543961648455116929274915967121308797839015745939416763942926546\ 99576354558364476401478446511510844", "0x0.6996966996696996966969966996966996696996699696696996966996696996966969966996966969969\ 669966969966996966996696996966969966996966996696996699696696996966996696996699696699669699\ 6966969966996966969969669966969969669699669969669966969966996966969969669968#1000", Greater, ); test_prouhet_thue_morse_constant_prec_helper( 10000, "0.412454033640107597783361368258455283089478374455769557573379415348793592365782588963804\ 540486212133396256366446538137487421617125193606520130996812525914093898811685058241405148\ 794923736837717681632072372543961648455116929274915967121308797839015745939416763942926546\ 995763545583644764014784465115108432988880527862797583778966429806153625600892794767509570\ 613156170981916634767556262265886591706560103745429025080980592282684200382286637025552138\ 072551019786013560720441271576469980054213089589582092326366528534417259882166080658990995\ 454185078647844640598822656110795985657599962216385510031350572070562361426971255128326932\ 200511472227565707730468866881043116266791929041303471097804134296620336523301148618999636\ 607737503684384287533124783775524067880628087063676089104069872257951121771322589484343969\ 687095887155500338806472758969301236596955913500219809107121878986270983191365987288252181\ 126158494661750104956413082261728325258668242137155812289887905859814150448158087621806081\ 262788059473203194858059514889641770915367577963421317521615653898873066742051436896862845\ 559388487896091534788479920439498978693239273118810516671742331317074845718885491752000298\ 494549886494536473002915644233647450149747441404205378363056251376268024177778124482615212\ 986239829412055649329758982540912039441942593759895057769683431420175890362746422845117500\ 028864842247279148167611365866356168475145086817445555637346709003759617604542400457827717\ 878660619366846815483941374378957060770110880180541318234323659237369552401312033505621806\ 489384014183232923162046501177883641270956312786606124433156307628120044554491098561964906\ 941642998546962635980094725095337754362574897392106593547505034744530716373746139055913844\ 730509118321844885047459136295028893709649115890738042446256488167921608092525231651808551\ 275515631923236859178416003062357823567287388396791613593690713019818632422297617615418611\ 504665052818584325511618352200787725967763734519804573074925771880268729695759436794061431\ 099083941098658903463402394219222397121260948820568428682987584463231060168451271023138827\ 618185738550975032215601211268731359671002623792857579075515885840571314634970190214029027\ 767535211043320712596064063934151016649744328535127842648397490736292971851028934173894800\ 896326950620264219873205858953858503888863733655930190565936770347310031381812711297640523\ 854923089574146136921130192885320184597064184712813990427490161972158454924359809839110934\ 222905109312597374946863138945391555541320741472882457682612774489682755147712902066198766\ 365305692386197821993411562093365185277357462610197541359244519518547852573339123003451159\ 324066183679763125504488718106276971066142222729525177728792136200206791458838091045048890\ 889263477842031146946636054226135511708407225571080034132437244605493617364337010772961383\ 884632019459005730120007550129264229222419321684701101892904472852138411474750231020219380\ 490568164815194679503954588116034274794607988054271917142826665676154809041554888257037645\ 08626387325662901457682774568054766955037516", "0x0.6996966996696996966969966996966996696996699696696996966996696996966969966996966969969\ 669966969966996966996696996966969966996966996696996699696696996966996696996699696699669699\ 696696996699696696996966996696996966969966996966996696996699696696996966996696996966969966\ 996966969969669966969966996966996696996966969966996966969969669966969969669699669969669966\ 969966996966969969669966969966996966996696996966969966996966996696996699696696996966996696\ 996966969966996966969969669966969966996966996696996966969966996966996696996699696696996966\ 996696996699696699669699696696996699696696996966996696996966969966996966996696996699696696\ 996966996696996699696699669699696696996699696699669699669969669699696699669699696696996699\ 696696996966996696996699696699669699696696996699696696996966996696996966969966996966996696\ 996699696696996966996696996966969966996966969969669966969966996966996696996966969966996966\ 996696996699696696996966996696996699696699669699696696996699696696996966996696996966969966\ 996966996696996699696696996966996696996966969966996966969969669966969966996966996696996966\ 969966996966969969669966969969669699669969669966969966996966969969669966969966996966996696\ 996966969966996966996696996699696696996966996696996966969966996966969969669966969966996966\ 996696996966969966996966969969669966969969669699669969669966969966996966969969669966969969\ 669699669969669699696699669699669969669966969969669699669969669966969966996966969969669966\ 969966996966996696996966969966996966969969669966969969669699669969669966969966996966969969\ 669966969966996966996696996966969966996966996696996699696696996966996696996966969966996966\ 969969669966969966996966996696996966969966996966996696996699696696996966996696996699696699\ 669699696696996699696696996966996696996966969966996966996696996699696696996966996696996966\ 969966996966969969669966969966996966996696996966969966996966969969669966969969669699669969\ 669966969966996966969969669966969966996966996696996966969966996966996696996699696696996966\ 996696996966969966996966969969669966969966996966996696996966969966996966996696996699696696\ 996966996696996699696699669699696696996699696696996966996696996966969966996966996696996699\ 696696996966996696996699696699669699696696996699696699669699669969669699696699669699696696\ 996699696696996966996696996699696699669699696696996699696696996966996696996966969966996966\ 996696996699696696996966996696996966969966996966969969669966969966996966996696996966969966\ 9969669966969966996966969969669966969966996966996696996966969966996966969968#10000", Less, ); let ptmc_f32 = Float::prouhet_thue_morse_constant_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(ptmc_f32.to_string(), "0.41245404"); assert_eq!(to_hex_string(&ptmc_f32), "0x0.6996968#24"); assert_eq!(ptmc_f32, f32::PROUHET_THUE_MORSE_CONSTANT); let ptmc_f64 = Float::prouhet_thue_morse_constant_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(ptmc_f64.to_string(), "0.41245403364010758"); assert_eq!(to_hex_string(&ptmc_f64), "0x0.69969669966968#53"); assert_eq!(ptmc_f64, f64::PROUHET_THUE_MORSE_CONSTANT); } #[test] #[should_panic] fn prouhet_thue_morse_constant_prec_fail_1() { Float::prouhet_thue_morse_constant_prec(0); } fn test_prouhet_thue_morse_constant_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::prouhet_thue_morse_constant_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = prouhet_thue_morse_constant_prec_round_naive(prec, rm); assert_eq!(x, x_alt); assert_eq!(o, o_alt); } #[test] pub fn test_prouhet_thue_morse_constant_prec_round() { test_prouhet_thue_morse_constant_prec_round_helper(1, Floor, "0.2", "0x0.4#1", Less); test_prouhet_thue_morse_constant_prec_round_helper(1, Ceiling, "0.5", "0x0.8#1", Greater); test_prouhet_thue_morse_constant_prec_round_helper(1, Down, "0.2", "0x0.4#1", Less); test_prouhet_thue_morse_constant_prec_round_helper(1, Up, "0.5", "0x0.8#1", Greater); test_prouhet_thue_morse_constant_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Greater); test_prouhet_thue_morse_constant_prec_round_helper(2, Floor, "0.4", "0x0.6#2", Less); test_prouhet_thue_morse_constant_prec_round_helper(2, Ceiling, "0.5", "0x0.8#2", Greater); test_prouhet_thue_morse_constant_prec_round_helper(2, Down, "0.4", "0x0.6#2", Less); test_prouhet_thue_morse_constant_prec_round_helper(2, Up, "0.5", "0x0.8#2", Greater); test_prouhet_thue_morse_constant_prec_round_helper(2, Nearest, "0.4", "0x0.6#2", Less); test_prouhet_thue_morse_constant_prec_round_helper(3, Floor, "0.38", "0x0.6#3", Less); test_prouhet_thue_morse_constant_prec_round_helper(3, Ceiling, "0.44", "0x0.7#3", Greater); test_prouhet_thue_morse_constant_prec_round_helper(3, Down, "0.38", "0x0.6#3", Less); test_prouhet_thue_morse_constant_prec_round_helper(3, Up, "0.44", "0x0.7#3", Greater); test_prouhet_thue_morse_constant_prec_round_helper(3, Nearest, "0.44", "0x0.7#3", Greater); test_prouhet_thue_morse_constant_prec_round_helper(4, Floor, "0.41", "0x0.68#4", Less); test_prouhet_thue_morse_constant_prec_round_helper(4, Ceiling, "0.44", "0x0.70#4", Greater); test_prouhet_thue_morse_constant_prec_round_helper(4, Down, "0.41", "0x0.68#4", Less); test_prouhet_thue_morse_constant_prec_round_helper(4, Up, "0.44", "0x0.70#4", Greater); test_prouhet_thue_morse_constant_prec_round_helper(4, Nearest, "0.41", "0x0.68#4", Less); test_prouhet_thue_morse_constant_prec_round_helper(5, Floor, "0.41", "0x0.68#5", Less); test_prouhet_thue_morse_constant_prec_round_helper(5, Ceiling, "0.42", "0x0.6c#5", Greater); test_prouhet_thue_morse_constant_prec_round_helper(5, Down, "0.41", "0x0.68#5", Less); test_prouhet_thue_morse_constant_prec_round_helper(5, Up, "0.42", "0x0.6c#5", Greater); test_prouhet_thue_morse_constant_prec_round_helper(5, Nearest, "0.41", "0x0.68#5", Less); test_prouhet_thue_morse_constant_prec_round_helper(6, Floor, "0.406", "0x0.68#6", Less); test_prouhet_thue_morse_constant_prec_round_helper(6, Ceiling, "0.414", "0x0.6a#6", Greater); test_prouhet_thue_morse_constant_prec_round_helper(6, Down, "0.406", "0x0.68#6", Less); test_prouhet_thue_morse_constant_prec_round_helper(6, Up, "0.414", "0x0.6a#6", Greater); test_prouhet_thue_morse_constant_prec_round_helper(6, Nearest, "0.414", "0x0.6a#6", Greater); test_prouhet_thue_morse_constant_prec_round_helper(7, Floor, "0.41", "0x0.69#7", Less); test_prouhet_thue_morse_constant_prec_round_helper(7, Ceiling, "0.414", "0x0.6a#7", Greater); test_prouhet_thue_morse_constant_prec_round_helper(7, Down, "0.41", "0x0.69#7", Less); test_prouhet_thue_morse_constant_prec_round_helper(7, Up, "0.414", "0x0.6a#7", Greater); test_prouhet_thue_morse_constant_prec_round_helper(7, Nearest, "0.414", "0x0.6a#7", Greater); test_prouhet_thue_morse_constant_prec_round_helper(8, Floor, "0.412", "0x0.698#8", Less); test_prouhet_thue_morse_constant_prec_round_helper(8, Ceiling, "0.414", "0x0.6a0#8", Greater); test_prouhet_thue_morse_constant_prec_round_helper(8, Down, "0.412", "0x0.698#8", Less); test_prouhet_thue_morse_constant_prec_round_helper(8, Up, "0.414", "0x0.6a0#8", Greater); test_prouhet_thue_morse_constant_prec_round_helper(8, Nearest, "0.412", "0x0.698#8", Less); test_prouhet_thue_morse_constant_prec_round_helper(9, Floor, "0.412", "0x0.698#9", Less); test_prouhet_thue_morse_constant_prec_round_helper(9, Ceiling, "0.413", "0x0.69c#9", Greater); test_prouhet_thue_morse_constant_prec_round_helper(9, Down, "0.412", "0x0.698#9", Less); test_prouhet_thue_morse_constant_prec_round_helper(9, Up, "0.413", "0x0.69c#9", Greater); test_prouhet_thue_morse_constant_prec_round_helper(9, Nearest, "0.412", "0x0.698#9", Less); test_prouhet_thue_morse_constant_prec_round_helper(10, Floor, "0.4121", "0x0.698#10", Less); test_prouhet_thue_morse_constant_prec_round_helper( 10, Ceiling, "0.4126", "0x0.69a#10", Greater, ); test_prouhet_thue_morse_constant_prec_round_helper(10, Down, "0.4121", "0x0.698#10", Less); test_prouhet_thue_morse_constant_prec_round_helper(10, Up, "0.4126", "0x0.69a#10", Greater); test_prouhet_thue_morse_constant_prec_round_helper( 10, Nearest, "0.4126", "0x0.69a#10", Greater, ); test_prouhet_thue_morse_constant_prec_round_helper( 100, Floor, "0.4124540336401075977833613682584", "0x0.69969669966969969669699668#100", Less, ); test_prouhet_thue_morse_constant_prec_round_helper( 100, Ceiling, "0.4124540336401075977833613682588", "0x0.69969669966969969669699670#100", Greater, ); test_prouhet_thue_morse_constant_prec_round_helper( 100, Down, "0.4124540336401075977833613682584", "0x0.69969669966969969669699668#100", Less, ); test_prouhet_thue_morse_constant_prec_round_helper( 100, Up, "0.4124540336401075977833613682588", "0x0.69969669966969969669699670#100", Greater, ); test_prouhet_thue_morse_constant_prec_round_helper( 100, Nearest, "0.4124540336401075977833613682584", "0x0.69969669966969969669699668#100", Less, ); } #[test] #[should_panic] fn prouhet_thue_morse_constant_prec_round_fail_1() { Float::prouhet_thue_morse_constant_prec_round(0, Floor); } #[test] #[should_panic] fn prouhet_thue_morse_constant_prec_round_fail_2() { Float::prouhet_thue_morse_constant_prec_round(1, Exact); } #[test] #[should_panic] fn prouhet_thue_morse_constant_prec_round_fail_3() { Float::prouhet_thue_morse_constant_prec_round(1000, Exact); } #[test] fn prouhet_thue_morse_constant_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (ptmc, o) = Float::prouhet_thue_morse_constant_prec(prec); assert!(ptmc.is_valid()); assert_eq!(ptmc.get_prec(), Some(prec)); assert_eq!(ptmc.get_exponent(), Some(if prec == 1 { 0 } else { -1 })); assert_ne!(o, Equal); if o == Less { let (ptmc_alt, o_alt) = Float::prouhet_thue_morse_constant_prec_round(prec, Ceiling); let mut next_upper = ptmc.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(ptmc_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !ptmc.is_power_of_2() { let (ptmc_alt, o_alt) = Float::prouhet_thue_morse_constant_prec_round(prec, Floor); let mut next_lower = ptmc.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(ptmc_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (ptmc_alt, o_alt) = Float::prouhet_thue_morse_constant_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&ptmc_alt), ComparableFloatRef(&ptmc)); assert_eq!(o_alt, o); let (ptmc_alt, o_alt) = prouhet_thue_morse_constant_prec_round_naive(prec, Nearest); assert_eq!(ptmc, ptmc_alt); assert_eq!(o, o_alt); }); } #[test] fn prouhet_thue_morse_constant_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (ptmc, o) = Float::prouhet_thue_morse_constant_prec_round(prec, rm); assert!(ptmc.is_valid()); assert_eq!(ptmc.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 0, _ => -1, }; assert_eq!(ptmc.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (ptmc_alt, o_alt) = Float::prouhet_thue_morse_constant_prec_round(prec, Ceiling); let mut next_upper = ptmc.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(ptmc_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !ptmc.is_power_of_2() { let (ptmc_alt, o_alt) = Float::prouhet_thue_morse_constant_prec_round(prec, Floor); let mut next_lower = ptmc.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(ptmc_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (ptmc_alt, o_alt) = prouhet_thue_morse_constant_prec_round_naive(prec, rm); assert_eq!(ptmc, ptmc_alt); assert_eq!(o, o_alt); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::prouhet_thue_morse_constant_prec_round(prec, Exact)); }); test_constant(Float::prouhet_thue_morse_constant_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/sqrt_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Sqrt2; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::sqrt_2::rug_sqrt_2_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_sqrt_2_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::sqrt_2_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (rug_x, rug_o) = rug_sqrt_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_sqrt_2_prec() { test_sqrt_2_prec_helper(1, "1.0", "0x1.0#1", Less); test_sqrt_2_prec_helper(2, "1.5", "0x1.8#2", Greater); test_sqrt_2_prec_helper(3, "1.5", "0x1.8#3", Greater); test_sqrt_2_prec_helper(4, "1.4", "0x1.6#4", Less); test_sqrt_2_prec_helper(5, "1.44", "0x1.7#5", Greater); test_sqrt_2_prec_helper(6, "1.41", "0x1.68#6", Less); test_sqrt_2_prec_helper(7, "1.42", "0x1.6c#7", Greater); test_sqrt_2_prec_helper(8, "1.414", "0x1.6a#8", Less); test_sqrt_2_prec_helper(9, "1.414", "0x1.6a#9", Less); test_sqrt_2_prec_helper(10, "1.414", "0x1.6a0#10", Less); test_sqrt_2_prec_helper( 100, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test_sqrt_2_prec_helper( 1000, "1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387\ 534327641572735013846230912297024924836055850737212644121497099935831413222665927505592755\ 799950501152782060571470109559971605970274534596862014728517418640889198609552329230484308\ 7143214508397626036279952514079896", "0x1.6a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a95f90608757145875163f\ cdfb907b6721ee950bc8738f694f0090e6c7bf44ed1a4405d0e855e3e9ca60b38c0237866f7956379222d108b1\ 48c1578e45ef89c678dab5147176fd3b99654c68663e7909bea5e241f06dcb05dd549411320#1000", Less, ); test_sqrt_2_prec_helper( 10000, "1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387\ 534327641572735013846230912297024924836055850737212644121497099935831413222665927505592755\ 799950501152782060571470109559971605970274534596862014728517418640889198609552329230484308\ 714321450839762603627995251407989687253396546331808829640620615258352395054745750287759961\ 729835575220337531857011354374603408498847160386899970699004815030544027790316454247823068\ 492936918621580578463111596668713013015618568987237235288509264861249497715421833420428568\ 606014682472077143585487415565706967765372022648544701585880162075847492265722600208558446\ 652145839889394437092659180031138824646815708263010059485870400318648034219489727829064104\ 507263688131373985525611732204024509122770022694112757362728049573810896750401836986836845\ 072579936472906076299694138047565482372899718032680247442062926912485905218100445984215059\ 112024944134172853147810580360337107730918286931471017111168391658172688941975871658215212\ 822951848847208969463386289156288276595263514054226765323969461751129160240871551013515045\ 538128756005263146801712740265396947024030051749531886292563138518816347800156936917688185\ 237868405228783762938921430065586956868596459515550164472450983689603688732311438941557665\ 104088391429233811320605243362948531704991577175622854974143899918802176243096520656421182\ 731672625753959471725593463723863226148274262220867115583959992652117625269891754098815934\ 864008345708518147223181420407042650905653233339843645786579679651926729239987536661721598\ 257886026336361782749599421940377775368142621773879919455139723127406689832998989538672882\ 285637869774966251996658352577619893932284534473569479496295216889148549253890475582883452\ 609652409654288939453864662574492755638196441031697983306185201937938494005715633372054806\ 854057586799967012137223947582142630658513221740883238294728761739364746783743196000159218\ 880734785761725221186749042497736692920731109636972160893370866115673458533483329525467585\ 164471075784860246360083444911481858765555428645512331421992631133251797060843655970435285\ 641008791850076036100915946567067688360557174007675690509613671940132493560524018599910506\ 210816359772643138060546701029356997104242510578174953105725593498445112692278034491350663\ 756874776028316282960553242242695753452902883876844642917328277088831808702533985233812274\ 999081237189254072647536785030482159180188616710897286922920119759988070381854333253646021\ 108229927929307287178079988809917674177410898306080032631181642798823117154363869661702999\ 934161614878686018045505553986913115186010386375325004558186044804075024119518430567453368\ 361367459737442398855328517930896037389891517319587413442881784212502191695187559344438739\ 618931454999990610758704909026088351763622474975785885836803745793115733980209998662218694\ 992259591327642361941059210032802614987456659968887406795616739185957288864247346358588686\ 449682238600698335264279905628316561391394255764906206518602164726303336297507569787060660\ 6856498160092718709292153132368281356988938", "0x1.6a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a95f90608757145875163f\ cdfb907b6721ee950bc8738f694f0090e6c7bf44ed1a4405d0e855e3e9ca60b38c0237866f7956379222d108b1\ 48c1578e45ef89c678dab5147176fd3b99654c68663e7909bea5e241f06dcb05dd5494113208194950272956db\ 1fa1dfbe9a74059d7927c1884c9b579aa516ca3719e6836df046d8e0209b803fc646a5e6654bd3ef7b43d7fed4\ 37c7f9444260fbd40c483ef55038583f97bbd45efb8663107145d5febe765a49e94ec7f597105fbfc2e1fa763e\ f01f3599c82f2fe500b848cf0bd252ae046bf9f1ef7947d46769af8c14bcc67c7c290be76929b0578c10b584fb\ 487c924f5b71f82dcd2903609dee8912983d4eaad0eea321f7489f46a7e9030be20fb7694efb58c9984cdd70a1\ da9045c3d133a068423d6e38303d901ba9da3476684796c5cd5972dc0ff3540c3412942d6406101ef6fc6de911\ 4a2b4f248c689c600bb40a8b56b041fd5de6e0dd0c66d4831fe7fff5757e4710980cdbd5c268485da5e91b3e2f\ 205b72725b971d60a1f888f08a0a6e100ccedc2ce5bd98aee71e42e268d37a6072f220234613ffc22453439ea9\ 7a999b6c9e3ce71f94d6092ace120ab8e550e0d5511688631778cf60350d02fe85f29ec8be5c72b807af5771b8\ 25b30a0e78376a91c08c6a7f0f8f323b36281d225689c0b5a82047db989f63a8a64e8519bc0d0c1e22280484d9\ 4f4f9bb3d4b31d489d75231b5c633c480c96be549bf5d96678b4d2c4dda867bd8e48029fea8c8173567c2ba3d3\ ce9dfe0bd1b4dd771178057b695b7eaf1b05c22c8d5feebd077fec96db8f778fc1c2bbbce1b49ebf5af4460882\ 958add01ca7f1b6bc0b7ec1bc6e0a6edbc67f85b274e0861b3a137571b16549873d211c6aae69d801e579445bc\ 60a3e0a4fd8968eb794bdc702d6945da94b04a440cabc94387c3d26fd0f3be8af6305a53a177288aca13fb406c\ 982915d83ba0d3558d81dd1159e9643eaa27eb7757a2052975b6f4a889e3d092bb1c685480dc2e99947b372ded\ a05e2192f95b1b926512b404c33181d64a359a89b6f8864f3d575319359aa386257a93a57a5977547fa0f606cc\ 32eea84ef7103d2d2d57b6c153a5f37c2c77fe2928d321b29470eae4158b3cedc64ade1e431a138bb7be7305b4\ 6f7fe0bc754ff3ec042bdc85b325996522a87b8643e3d17870f8c25b5978060d55b82fd4ed3f3e15892b5b5236\ 182cb2831f44ca27ad1a66fd56fdc29a7c7a93e4279aa12d460a0d49495b6be4dc73ddf96ee80a9dfc22d8d385\ ea2ecc801d740c1990c7bf28458480527bb8ba8109d2770c3ffde121a7be434f83d0aabfbde531f74bafdbc2da\ fbece02e65bb77b8fbb8cdb4ad8e4b9ef01e2c90f8069d23ecfb0c8e2e27d647daa43762a64b9c7d745344fdb5\ 16fc56fa1eae6a95874fb501f69b17b66b81dfba11ed52415d7ee3e53f9585946bb2081617805996805bb4f9da\ 796f633c9d13f6c172c3afe3401a32e99dd6a247e279600a3f5c09991a6554a35000ffe090abfbc2d8a4a88145\ 9ed127a54ccecb63cf6373a711c9cf91566c397b28278a7f0bb8bbc4516ddcab0f6e9557448f93eeb80f69f34b\ 525c760f3380ef9edb8aceefa8db3c7ce26e42aa5984d4db95612ec528a245fcf43db3757f0a0a1fc24fe218f4\ b630720904044b232f38c4032f1c3ab8971dd4f7966dd97614bae8d797a0848b1d5cfdb137e#10000", Greater, ); let sqrt_2_f32 = Float::sqrt_2_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(sqrt_2_f32.to_string(), "1.4142135"); assert_eq!(to_hex_string(&sqrt_2_f32), "0x1.6a09e6#24"); assert_eq!(sqrt_2_f32, f32::SQRT_2); let sqrt_2_f64 = Float::sqrt_2_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(sqrt_2_f64.to_string(), "1.4142135623730951"); assert_eq!(to_hex_string(&sqrt_2_f64), "0x1.6a09e667f3bcd#53"); assert_eq!(sqrt_2_f64, f64::SQRT_2); } #[test] #[should_panic] fn sqrt_2_prec_fail_1() { Float::sqrt_2_prec(0); } fn test_sqrt_2_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::sqrt_2_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_sqrt_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_sqrt_2_prec_round() { test_sqrt_2_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_sqrt_2_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_sqrt_2_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_sqrt_2_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_sqrt_2_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Less); test_sqrt_2_prec_round_helper(2, Floor, "1.0", "0x1.0#2", Less); test_sqrt_2_prec_round_helper(2, Ceiling, "1.5", "0x1.8#2", Greater); test_sqrt_2_prec_round_helper(2, Down, "1.0", "0x1.0#2", Less); test_sqrt_2_prec_round_helper(2, Up, "1.5", "0x1.8#2", Greater); test_sqrt_2_prec_round_helper(2, Nearest, "1.5", "0x1.8#2", Greater); test_sqrt_2_prec_round_helper(3, Floor, "1.2", "0x1.4#3", Less); test_sqrt_2_prec_round_helper(3, Ceiling, "1.5", "0x1.8#3", Greater); test_sqrt_2_prec_round_helper(3, Down, "1.2", "0x1.4#3", Less); test_sqrt_2_prec_round_helper(3, Up, "1.5", "0x1.8#3", Greater); test_sqrt_2_prec_round_helper(3, Nearest, "1.5", "0x1.8#3", Greater); test_sqrt_2_prec_round_helper(4, Floor, "1.4", "0x1.6#4", Less); test_sqrt_2_prec_round_helper(4, Ceiling, "1.5", "0x1.8#4", Greater); test_sqrt_2_prec_round_helper(4, Down, "1.4", "0x1.6#4", Less); test_sqrt_2_prec_round_helper(4, Up, "1.5", "0x1.8#4", Greater); test_sqrt_2_prec_round_helper(4, Nearest, "1.4", "0x1.6#4", Less); test_sqrt_2_prec_round_helper(5, Floor, "1.38", "0x1.6#5", Less); test_sqrt_2_prec_round_helper(5, Ceiling, "1.44", "0x1.7#5", Greater); test_sqrt_2_prec_round_helper(5, Down, "1.38", "0x1.6#5", Less); test_sqrt_2_prec_round_helper(5, Up, "1.44", "0x1.7#5", Greater); test_sqrt_2_prec_round_helper(5, Nearest, "1.44", "0x1.7#5", Greater); test_sqrt_2_prec_round_helper(6, Floor, "1.41", "0x1.68#6", Less); test_sqrt_2_prec_round_helper(6, Ceiling, "1.44", "0x1.70#6", Greater); test_sqrt_2_prec_round_helper(6, Down, "1.41", "0x1.68#6", Less); test_sqrt_2_prec_round_helper(6, Up, "1.44", "0x1.70#6", Greater); test_sqrt_2_prec_round_helper(6, Nearest, "1.41", "0x1.68#6", Less); test_sqrt_2_prec_round_helper(7, Floor, "1.41", "0x1.68#7", Less); test_sqrt_2_prec_round_helper(7, Ceiling, "1.42", "0x1.6c#7", Greater); test_sqrt_2_prec_round_helper(7, Down, "1.41", "0x1.68#7", Less); test_sqrt_2_prec_round_helper(7, Up, "1.42", "0x1.6c#7", Greater); test_sqrt_2_prec_round_helper(7, Nearest, "1.42", "0x1.6c#7", Greater); test_sqrt_2_prec_round_helper(8, Floor, "1.414", "0x1.6a#8", Less); test_sqrt_2_prec_round_helper(8, Ceiling, "1.42", "0x1.6c#8", Greater); test_sqrt_2_prec_round_helper(8, Down, "1.414", "0x1.6a#8", Less); test_sqrt_2_prec_round_helper(8, Up, "1.42", "0x1.6c#8", Greater); test_sqrt_2_prec_round_helper(8, Nearest, "1.414", "0x1.6a#8", Less); test_sqrt_2_prec_round_helper(9, Floor, "1.414", "0x1.6a#9", Less); test_sqrt_2_prec_round_helper(9, Ceiling, "1.418", "0x1.6b#9", Greater); test_sqrt_2_prec_round_helper(9, Down, "1.414", "0x1.6a#9", Less); test_sqrt_2_prec_round_helper(9, Up, "1.418", "0x1.6b#9", Greater); test_sqrt_2_prec_round_helper(9, Nearest, "1.414", "0x1.6a#9", Less); test_sqrt_2_prec_round_helper(10, Floor, "1.414", "0x1.6a0#10", Less); test_sqrt_2_prec_round_helper(10, Ceiling, "1.416", "0x1.6a8#10", Greater); test_sqrt_2_prec_round_helper(10, Down, "1.414", "0x1.6a0#10", Less); test_sqrt_2_prec_round_helper(10, Up, "1.416", "0x1.6a8#10", Greater); test_sqrt_2_prec_round_helper(10, Nearest, "1.414", "0x1.6a0#10", Less); test_sqrt_2_prec_round_helper( 100, Floor, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test_sqrt_2_prec_round_helper( 100, Ceiling, "1.414213562373095048801688724211", "0x1.6a09e667f3bcc908b2fb13670#100", Greater, ); test_sqrt_2_prec_round_helper( 100, Down, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); test_sqrt_2_prec_round_helper( 100, Up, "1.414213562373095048801688724211", "0x1.6a09e667f3bcc908b2fb13670#100", Greater, ); test_sqrt_2_prec_round_helper( 100, Nearest, "1.414213562373095048801688724209", "0x1.6a09e667f3bcc908b2fb1366e#100", Less, ); } #[test] #[should_panic] fn sqrt_2_prec_round_fail_1() { Float::sqrt_2_prec_round(0, Floor); } #[test] #[should_panic] fn sqrt_2_prec_round_fail_2() { Float::sqrt_2_prec_round(1, Exact); } #[test] #[should_panic] fn sqrt_2_prec_round_fail_3() { Float::sqrt_2_prec_round(1000, Exact); } #[test] fn sqrt_2_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (sqrt_2, o) = Float::sqrt_2_prec(prec); assert!(sqrt_2.is_valid()); assert_eq!(sqrt_2.get_prec(), Some(prec)); assert_eq!(sqrt_2.get_exponent(), Some(1)); assert_ne!(o, Equal); if o == Less { let (sqrt_2_alt, o_alt) = Float::sqrt_2_prec_round(prec, Ceiling); let mut next_upper = sqrt_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_2.is_power_of_2() { let (sqrt_2_alt, o_alt) = Float::sqrt_2_prec_round(prec, Floor); let mut next_lower = sqrt_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (sqrt_2_alt, o_alt) = Float::sqrt_2_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&sqrt_2_alt), ComparableFloatRef(&sqrt_2)); assert_eq!(o_alt, o); let (rug_sqrt_2, rug_o) = rug_sqrt_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_2)), ComparableFloatRef(&sqrt_2) ); assert_eq!(rug_o, o); }); } #[test] fn sqrt_2_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (sqrt_2, o) = Float::sqrt_2_prec_round(prec, rm); assert!(sqrt_2.is_valid()); assert_eq!(sqrt_2.get_prec(), Some(prec)); assert_eq!( sqrt_2.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 2 } else { 1 }) ); assert_ne!(o, Equal); if o == Less { let (sqrt_2_alt, o_alt) = Float::sqrt_2_prec_round(prec, Ceiling); let mut next_upper = sqrt_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_2_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_2.is_power_of_2() { let (sqrt_2_alt, o_alt) = Float::sqrt_2_prec_round(prec, Floor); let mut next_lower = sqrt_2.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_2_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt_2, rug_o) = rug_sqrt_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_2)), ComparableFloatRef(&sqrt_2) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::sqrt_2_prec_round(prec, Exact)); }); test_constant(Float::sqrt_2_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/sqrt_2_over_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Sqrt2Over2; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::sqrt_2_over_2::rug_sqrt_2_over_2_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_sqrt_2_over_2_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::sqrt_2_over_2_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (rug_x, rug_o) = rug_sqrt_2_over_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_sqrt_2_over_2_prec() { test_sqrt_2_over_2_prec_helper(1, "0.5", "0x0.8#1", Less); test_sqrt_2_over_2_prec_helper(2, "0.8", "0x0.c#2", Greater); test_sqrt_2_over_2_prec_helper(3, "0.8", "0x0.c#3", Greater); test_sqrt_2_over_2_prec_helper(4, "0.7", "0x0.b#4", Less); test_sqrt_2_over_2_prec_helper(5, "0.72", "0x0.b8#5", Greater); test_sqrt_2_over_2_prec_helper(6, "0.7", "0x0.b4#6", Less); test_sqrt_2_over_2_prec_helper(7, "0.71", "0x0.b6#7", Greater); test_sqrt_2_over_2_prec_helper(8, "0.707", "0x0.b5#8", Less); test_sqrt_2_over_2_prec_helper(9, "0.707", "0x0.b50#9", Less); test_sqrt_2_over_2_prec_helper(10, "0.707", "0x0.b50#10", Less); test_sqrt_2_over_2_prec_helper( 100, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test_sqrt_2_over_2_prec_helper( 1000, "0.707106781186547524400844362104849039284835937688474036588339868995366239231053519425193\ 767163820786367506923115456148512462418027925368606322060748549967915706611332963752796377\ 899975250576391030285735054779985802985137267298431007364258709320444599304776164615242154\ 3571607254198813018139976257039948", "0x0.b504f333f9de6484597d89b3754abe9f1d6f60ba893ba84ced17ac85833399154afc83043ab8a2c3a8b1f\ e6fdc83db390f74a85e439c7b4a780487363dfa2768d2202e8742af1f4e53059c6011bc337bcab1bc911688458\ a460abc722f7c4e33c6d5a8a38bb7e9dccb2a634331f3c84df52f120f836e582eeaa4a08990#1000", Less, ); test_sqrt_2_over_2_prec_helper( 10000, "0.707106781186547524400844362104849039284835937688474036588339868995366239231053519425193\ 767163820786367506923115456148512462418027925368606322060748549967915706611332963752796377\ 899975250576391030285735054779985802985137267298431007364258709320444599304776164615242154\ 357160725419881301813997625703994843626698273165904414820310307629176197527372875143879980\ 864917787610168765928505677187301704249423580193449985349502407515272013895158227123911534\ 246468459310790289231555798334356506507809284493618617644254632430624748857710916710214284\ 303007341236038571792743707782853483882686011324272350792940081037923746132861300104279223\ 326072919944697218546329590015569412323407854131505029742935200159324017109744863914532052\ 253631844065686992762805866102012254561385011347056378681364024786905448375200918493418422\ 536289968236453038149847069023782741186449859016340123721031463456242952609050222992107529\ 556012472067086426573905290180168553865459143465735508555584195829086344470987935829107606\ 411475924423604484731693144578144138297631757027113382661984730875564580120435775506757522\ 769064378002631573400856370132698473512015025874765943146281569259408173900078468458844092\ 618934202614391881469460715032793478434298229757775082236225491844801844366155719470778832\ 552044195714616905660302621681474265852495788587811427487071949959401088121548260328210591\ 365836312876979735862796731861931613074137131110433557791979996326058812634945877049407967\ 432004172854259073611590710203521325452826616669921822893289839825963364619993768330860799\ 128943013168180891374799710970188887684071310886939959727569861563703344916499494769336441\ 142818934887483125998329176288809946966142267236784739748147608444574274626945237791441726\ 304826204827144469726932331287246377819098220515848991653092600968969247002857816686027403\ 427028793399983506068611973791071315329256610870441619147364380869682373391871598000079609\ 440367392880862610593374521248868346460365554818486080446685433057836729266741664762733792\ 582235537892430123180041722455740929382777714322756165710996315566625898530421827985217642\ 820504395925038018050457973283533844180278587003837845254806835970066246780262009299955253\ 105408179886321569030273350514678498552121255289087476552862796749222556346139017245675331\ 878437388014158141480276621121347876726451441938422321458664138544415904351266992616906137\ 499540618594627036323768392515241079590094308355448643461460059879994035190927166626823010\ 554114963964653643589039994404958837088705449153040016315590821399411558577181934830851499\ 967080807439343009022752776993456557593005193187662502279093022402037512059759215283726684\ 180683729868721199427664258965448018694945758659793706721440892106251095847593779672219369\ 809465727499995305379352454513044175881811237487892942918401872896557866990104999331109347\ 496129795663821180970529605016401307493728329984443703397808369592978644432123673179294343\ 224841119300349167632139952814158280695697127882453103259301082363151668148753784893530330\ 34282490800463593546460765661841406784944688", "0x0.b504f333f9de6484597d89b3754abe9f1d6f60ba893ba84ced17ac85833399154afc83043ab8a2c3a8b1f\ e6fdc83db390f74a85e439c7b4a780487363dfa2768d2202e8742af1f4e53059c6011bc337bcab1bc911688458\ a460abc722f7c4e33c6d5a8a38bb7e9dccb2a634331f3c84df52f120f836e582eeaa4a0899040ca4a81394ab6d\ 8fd0efdf4d3a02cebc93e0c4264dabcd528b651b8cf341b6f8236c70104dc01fe32352f332a5e9f7bda1ebff6a\ 1be3fca221307dea06241f7aa81c2c1fcbddea2f7dc3318838a2eaff5f3b2d24f4a763facb882fdfe170fd3b1f\ 780f9acce41797f2805c246785e929570235fcf8f7bca3ea33b4d7c60a5e633e3e1485f3b494d82bc6085ac27d\ a43e4927adb8fc16e69481b04ef744894c1ea75568775190fba44fa353f48185f107dbb4a77dac64cc266eb850\ ed4822e1e899d034211eb71c181ec80dd4ed1a3b3423cb62e6acb96e07f9aa061a094a16b203080f7b7e36f488\ a515a79246344e3005da0545ab5820feaef3706e86336a418ff3fffababf23884c066deae134242ed2f48d9f17\ 902db9392dcb8eb050fc44784505370806676e1672decc57738f21713469bd3039791011a309ffe11229a1cf54\ bd4ccdb64f1e738fca6b04956709055c72a8706aa88b44318bbc67b01a86817f42f94f645f2e395c03d7abb8dc\ 12d985073c1bb548e046353f87c7991d9b140e912b44e05ad41023edcc4fb1d45327428cde06860f111402426c\ a7a7cdd9ea598ea44eba918dae319e24064b5f2a4dfaecb33c5a69626ed433dec724014ff54640b9ab3e15d1e9\ e74eff05e8da6ebb88bc02bdb4adbf578d82e11646aff75e83bff64b6dc7bbc7e0e15dde70da4f5fad7a230441\ 4ac56e80e53f8db5e05bf60de3705376de33fc2d93a70430d9d09bab8d8b2a4c39e908e355734ec00f2bca22de\ 3051f0527ec4b475bca5ee3816b4a2ed4a5825220655e4a1c3e1e937e879df457b182d29d0bb94456509fda036\ 4c148aec1dd069aac6c0ee88acf4b21f5513f5bbabd10294badb7a5444f1e8495d8e342a406e174cca3d9b96f6\ d02f10c97cad8dc932895a026198c0eb251acd44db7c43279eaba98c9acd51c312bd49d2bd2cbbaa3fd07b0366\ 197754277b881e9696abdb60a9d2f9be163bff14946990d94a3875720ac59e76e3256f0f218d09c5dbdf3982da\ 37bff05e3aa7f9f60215ee42d992ccb291543dc321f1e8bc387c612dacbc0306aadc17ea769f9f0ac495ada91b\ 0c1659418fa26513d68d337eab7ee14d3e3d49f213cd5096a30506a4a4adb5f26e39eefcb774054efe116c69c2\ f51766400eba060cc863df9422c240293ddc5d4084e93b861ffef090d3df21a7c1e8555fdef298fba5d7ede16d\ 7df6701732ddbbdc7ddc66da56c725cf780f16487c034e91f67d86471713eb23ed521bb15325ce3eba29a27eda\ 8b7e2b7d0f57354ac3a7da80fb4d8bdb35c0efdd08f6a920aebf71f29fcac2ca35d9040b0bc02ccb402dda7ced\ 3cb7b19e4e89fb60b961d7f1a00d1974ceeb5123f13cb0051fae04cc8d32aa51a8007ff04855fde16c525440a2\ cf6893d2a66765b1e7b1b9d388e4e7c8ab361cbd9413c53f85dc5de228b6ee5587b74aaba247c9f75c07b4f9a5\ a92e3b0799c077cf6dc56777d46d9e3e713721552cc26a6dcab09762945122fe7a1ed9babf85050fe127f10c7a\ 5b18390482022591979c6201978e1d5c4b8eea7bcb36ecbb0a5d746bcbd042458eae7ed89bf#10000", Greater, ); let sqrt_2_over_2_f32 = Float::sqrt_2_over_2_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(sqrt_2_over_2_f32.to_string(), "0.70710677"); assert_eq!(to_hex_string(&sqrt_2_over_2_f32), "0x0.b504f3#24"); assert_eq!(sqrt_2_over_2_f32, f32::SQRT_2_OVER_2); let sqrt_2_over_2_f64 = Float::sqrt_2_over_2_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(sqrt_2_over_2_f64.to_string(), "0.7071067811865476"); assert_eq!(to_hex_string(&sqrt_2_over_2_f64), "0x0.b504f333f9de68#53"); assert_eq!(sqrt_2_over_2_f64, f64::SQRT_2_OVER_2); } #[test] #[should_panic] fn sqrt_2_over_2_prec_fail_1() { Float::sqrt_2_over_2_prec(0); } fn test_sqrt_2_over_2_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::sqrt_2_over_2_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_sqrt_2_over_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_sqrt_2_over_2_prec_round() { test_sqrt_2_over_2_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_sqrt_2_over_2_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_sqrt_2_over_2_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_sqrt_2_over_2_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_sqrt_2_over_2_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_sqrt_2_over_2_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_sqrt_2_over_2_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_sqrt_2_over_2_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_sqrt_2_over_2_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_sqrt_2_over_2_prec_round_helper(2, Nearest, "0.8", "0x0.c#2", Greater); test_sqrt_2_over_2_prec_round_helper(3, Floor, "0.6", "0x0.a#3", Less); test_sqrt_2_over_2_prec_round_helper(3, Ceiling, "0.8", "0x0.c#3", Greater); test_sqrt_2_over_2_prec_round_helper(3, Down, "0.6", "0x0.a#3", Less); test_sqrt_2_over_2_prec_round_helper(3, Up, "0.8", "0x0.c#3", Greater); test_sqrt_2_over_2_prec_round_helper(3, Nearest, "0.8", "0x0.c#3", Greater); test_sqrt_2_over_2_prec_round_helper(4, Floor, "0.7", "0x0.b#4", Less); test_sqrt_2_over_2_prec_round_helper(4, Ceiling, "0.75", "0x0.c#4", Greater); test_sqrt_2_over_2_prec_round_helper(4, Down, "0.7", "0x0.b#4", Less); test_sqrt_2_over_2_prec_round_helper(4, Up, "0.75", "0x0.c#4", Greater); test_sqrt_2_over_2_prec_round_helper(4, Nearest, "0.7", "0x0.b#4", Less); test_sqrt_2_over_2_prec_round_helper(5, Floor, "0.69", "0x0.b0#5", Less); test_sqrt_2_over_2_prec_round_helper(5, Ceiling, "0.72", "0x0.b8#5", Greater); test_sqrt_2_over_2_prec_round_helper(5, Down, "0.69", "0x0.b0#5", Less); test_sqrt_2_over_2_prec_round_helper(5, Up, "0.72", "0x0.b8#5", Greater); test_sqrt_2_over_2_prec_round_helper(5, Nearest, "0.72", "0x0.b8#5", Greater); test_sqrt_2_over_2_prec_round_helper(6, Floor, "0.7", "0x0.b4#6", Less); test_sqrt_2_over_2_prec_round_helper(6, Ceiling, "0.72", "0x0.b8#6", Greater); test_sqrt_2_over_2_prec_round_helper(6, Down, "0.7", "0x0.b4#6", Less); test_sqrt_2_over_2_prec_round_helper(6, Up, "0.72", "0x0.b8#6", Greater); test_sqrt_2_over_2_prec_round_helper(6, Nearest, "0.7", "0x0.b4#6", Less); test_sqrt_2_over_2_prec_round_helper(7, Floor, "0.703", "0x0.b4#7", Less); test_sqrt_2_over_2_prec_round_helper(7, Ceiling, "0.71", "0x0.b6#7", Greater); test_sqrt_2_over_2_prec_round_helper(7, Down, "0.703", "0x0.b4#7", Less); test_sqrt_2_over_2_prec_round_helper(7, Up, "0.71", "0x0.b6#7", Greater); test_sqrt_2_over_2_prec_round_helper(7, Nearest, "0.71", "0x0.b6#7", Greater); test_sqrt_2_over_2_prec_round_helper(8, Floor, "0.707", "0x0.b5#8", Less); test_sqrt_2_over_2_prec_round_helper(8, Ceiling, "0.711", "0x0.b6#8", Greater); test_sqrt_2_over_2_prec_round_helper(8, Down, "0.707", "0x0.b5#8", Less); test_sqrt_2_over_2_prec_round_helper(8, Up, "0.711", "0x0.b6#8", Greater); test_sqrt_2_over_2_prec_round_helper(8, Nearest, "0.707", "0x0.b5#8", Less); test_sqrt_2_over_2_prec_round_helper(9, Floor, "0.707", "0x0.b50#9", Less); test_sqrt_2_over_2_prec_round_helper(9, Ceiling, "0.709", "0x0.b58#9", Greater); test_sqrt_2_over_2_prec_round_helper(9, Down, "0.707", "0x0.b50#9", Less); test_sqrt_2_over_2_prec_round_helper(9, Up, "0.709", "0x0.b58#9", Greater); test_sqrt_2_over_2_prec_round_helper(9, Nearest, "0.707", "0x0.b50#9", Less); test_sqrt_2_over_2_prec_round_helper(10, Floor, "0.707", "0x0.b50#10", Less); test_sqrt_2_over_2_prec_round_helper(10, Ceiling, "0.708", "0x0.b54#10", Greater); test_sqrt_2_over_2_prec_round_helper(10, Down, "0.707", "0x0.b50#10", Less); test_sqrt_2_over_2_prec_round_helper(10, Up, "0.708", "0x0.b54#10", Greater); test_sqrt_2_over_2_prec_round_helper(10, Nearest, "0.707", "0x0.b50#10", Less); test_sqrt_2_over_2_prec_round_helper( 100, Floor, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test_sqrt_2_over_2_prec_round_helper( 100, Ceiling, "0.7071067811865475244008443621054", "0x0.b504f333f9de6484597d89b38#100", Greater, ); test_sqrt_2_over_2_prec_round_helper( 100, Down, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); test_sqrt_2_over_2_prec_round_helper( 100, Up, "0.7071067811865475244008443621054", "0x0.b504f333f9de6484597d89b38#100", Greater, ); test_sqrt_2_over_2_prec_round_helper( 100, Nearest, "0.7071067811865475244008443621046", "0x0.b504f333f9de6484597d89b37#100", Less, ); } #[test] #[should_panic] fn sqrt_2_over_2_prec_round_fail_1() { Float::sqrt_2_over_2_prec_round(0, Floor); } #[test] #[should_panic] fn sqrt_2_over_2_prec_round_fail_2() { Float::sqrt_2_over_2_prec_round(1, Exact); } #[test] #[should_panic] fn sqrt_2_over_2_prec_round_fail_3() { Float::sqrt_2_over_2_prec_round(1000, Exact); } #[test] fn sqrt_2_over_2_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec(prec); assert!(sqrt_2_over_2.is_valid()); assert_eq!(sqrt_2_over_2.get_prec(), Some(prec)); assert_eq!(sqrt_2_over_2.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (sqrt_2_over_2_alt, o_alt) = Float::sqrt_2_over_2_prec_round(prec, Ceiling); let mut next_upper = sqrt_2_over_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(sqrt_2_over_2_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !sqrt_2_over_2.is_power_of_2() { let (sqrt_2_over_2_alt, o_alt) = Float::sqrt_2_over_2_prec_round(prec, Floor); let mut next_lower = sqrt_2_over_2.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(sqrt_2_over_2_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (sqrt_2_over_2_alt, o_alt) = Float::sqrt_2_over_2_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&sqrt_2_over_2_alt), ComparableFloatRef(&sqrt_2_over_2) ); assert_eq!(o_alt, o); let (rug_sqrt_2_over_2, rug_o) = rug_sqrt_2_over_2_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_2_over_2)), ComparableFloatRef(&sqrt_2_over_2) ); assert_eq!(rug_o, o); }); } #[test] fn sqrt_2_over_2_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (sqrt_2_over_2, o) = Float::sqrt_2_over_2_prec_round(prec, rm); assert!(sqrt_2_over_2.is_valid()); assert_eq!(sqrt_2_over_2.get_prec(), Some(prec)); assert_eq!( sqrt_2_over_2.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (sqrt_2_over_2_alt, o_alt) = Float::sqrt_2_over_2_prec_round(prec, Ceiling); let mut next_upper = sqrt_2_over_2.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(sqrt_2_over_2_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !sqrt_2_over_2.is_power_of_2() { let (sqrt_2_over_2_alt, o_alt) = Float::sqrt_2_over_2_prec_round(prec, Floor); let mut next_lower = sqrt_2_over_2.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(sqrt_2_over_2_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt_2_over_2, rug_o) = rug_sqrt_2_over_2_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_2_over_2)), ComparableFloatRef(&sqrt_2_over_2) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::sqrt_2_over_2_prec_round(prec, Exact)); }); test_constant(Float::sqrt_2_over_2_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/sqrt_3.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Sqrt3; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::sqrt_3::rug_sqrt_3_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_sqrt_3_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::sqrt_3_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (rug_x, rug_o) = rug_sqrt_3_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_sqrt_3_prec() { test_sqrt_3_prec_helper(1, "2.0", "0x2.0#1", Greater); test_sqrt_3_prec_helper(2, "1.5", "0x1.8#2", Less); test_sqrt_3_prec_helper(3, "1.8", "0x1.c#3", Greater); test_sqrt_3_prec_helper(4, "1.8", "0x1.c#4", Greater); test_sqrt_3_prec_helper(5, "1.75", "0x1.c#5", Greater); test_sqrt_3_prec_helper(6, "1.72", "0x1.b8#6", Less); test_sqrt_3_prec_helper(7, "1.73", "0x1.bc#7", Greater); test_sqrt_3_prec_helper(8, "1.734", "0x1.bc#8", Greater); test_sqrt_3_prec_helper(9, "1.73", "0x1.bb#9", Less); test_sqrt_3_prec_helper(10, "1.732", "0x1.bb8#10", Greater); test_sqrt_3_prec_helper( 100, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test_sqrt_3_prec_helper( 1000, "1.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146\ 186757248575675626141415406703029969945094998952478811655512094373648528093231902305582067\ 974820101084674923265015312343266903322886650672254668921837971227047131660367861588019049\ 9865373798593894676503475065760508", "0x1.bb67ae8584caa73b25742d7078b83b8925d834cc53da4798c720a6486e45a6e2490bcfd95ef15dbda9930\ aae12228f87cc4cf24da3a1ec68d0cd33a01ad9a383b9e122e6138c3ae6de5ede3bd42db7301b6bf553af7b09f\ d6ebef33a9a9fe57729426f30e5892ab572816ccefc5899355f7f11c3e24f3768a5c7cb90d6#1000", Greater, ); test_sqrt_3_prec_helper( 10000, "1.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146\ 186757248575675626141415406703029969945094998952478811655512094373648528093231902305582067\ 974820101084674923265015312343266903322886650672254668921837971227047131660367861588019049\ 986537379859389467650347506576050756618348129606100947602187190325083145829523959832997789\ 824508288714463832917347224163984587855397667958063818353666110843173780894378316102088305\ 524901670023520711144288695990956365797087168498072899493296484283020786408603988738697537\ 582317317831395992983007838702877053913369563312103707264019249106768231199288375641141422\ 016742752102372994270831059898459475987664288897796147837958390228854852903576033852808064\ 381972344661059689722872865264153822664698420021195484155278441181286534507035191650016689\ 294415480846071277143999762926834629577438361895110127148638746976545982451788550975379013\ 880664961911962222957110555242923723192197738262561631468842032853716682938649611917049738\ 836395495938145757671853373633125910899655424624834787197605235997769192323570220305302840\ 385915414971072429559206706202509520175963185872766359975283663431080150665853710647328538\ 625922260582220510403680270297504798728079461658100417052681940019095733462175943893670249\ 320422691034369812463720111185261084268910299720311202100063507176374582405203847555197279\ 933797614906107894985544223326004018851303631561144886847281589288163245187265066645384877\ 599162576642872111240842068016763517100102943180715515190961642460907039408129216903517492\ 961364004139670431041253632327030922577327960292376597745537095469115742140424230781992327\ 617401906424512454877516862696105333694216213605394604245654140128533007813633449856736406\ 703977342229811961042925534501601405940479547154534548407271737656262366549166640233006013\ 265744070107836858468452313160467754480500402240639911970362218602920238867150711017169400\ 296868759663500040895316214233425227956834067013470185902028360716762147743493449563595808\ 082130442586469468522610908263353008756612603460672195404055984128912975994810000772057440\ 230047673258800091514371489475444879157191294659083570873961515537797640262068370848046072\ 969382719585689759759626104159152657577790782334980567840022901532052138935373775536566427\ 046826874289963441395743666073744445583086477893212985302148197395341478170516614952551763\ 291993699565744522639112519093541386989366817430938226424736926202072990967831154131946484\ 377915459915923928287714695149274026409213645654041644581490201945749419305269002613972646\ 081065071439603206077510594187798284793986195249964165213139715293599421897416647075187235\ 788629466108560170428869605798394052906407430811833388677881562635867156008396760245349229\ 943938867059754315442943430957258470988215463111260766774067864571578060647447499750354544\ 559313286549189849336572747626297414738235686914837831363361283627903824840163806671607179\ 848728555842931349226093240565957553651136754644387834283313466644554180390821898983294626\ 3450161711220169296194601693206210330397449", "0x1.bb67ae8584caa73b25742d7078b83b8925d834cc53da4798c720a6486e45a6e2490bcfd95ef15dbda9930\ aae12228f87cc4cf24da3a1ec68d0cd33a01ad9a383b9e122e6138c3ae6de5ede3bd42db7301b6bf553af7b09f\ d6ebef33a9a9fe57729426f30e5892ab572816ccefc5899355f7f11c3e24f3768a5c7cb90d55302505df014c70\ adb1ec1baf58f084433c0d56696a039d962d8434194aab164d642f76e2c8f7dbed64b39dad2f9f7726c6930c49\ d48ffcdc21114a6c36b2ab7018af65c10f806a8fcf4188ef377d2d5b5fd1942e6fd41f9d23b667813df420b68d\ 313b387ae00d7a1ddd40aa69bb5352d3522529a7269af1ace62c8325ced0d18c24635d661cfb468be1b096fe67\ 7a78756ff46b5506d202bbab5e3351351776080e751e7a6ed2ecbd5cab0343f677bc2f4d3020b12c5a3dd54170\ 514f1d910c64a786d9f4fdde306dfce0de8466b0c0b1097801348a9497aca75bdd1b2cb8a042330fb4a53f02fb\ e02b0bd65b382e53877c9b3b518f837f09b9ea3eada4de774744c667ee778a7de2100ef3847573d88bf593779a\ f61a446d5cf76c39e9b5e3a8e82eadb3bab8bbed573c82332c9b692ad88926393687c4cfd268bf8c11f4f39490\ 3816010414c231d5ab4e954cca351a0b97b9c1dfc9c263bc18fe1b0899efae7dc41d63fa0d29a5e5d541f52617\ ab4671cded759436e30da234491b192dc6d190fe6b15e72e0a142ca532c3971e0e57a50d517325b52415ccf1e4\ feb9efba3bf091f9c3ffb3a9b243bb001a5fa8c9c9272115c5b9f6cf09325ecc659bb47a3b2dbf660c7bfd4046\ 81a5c00c10bc4c7978e5255fc1aa1230c7768f631ccba5fe87314527436fc1e1851ffcf0709060141b5e7c80d2\ f80c57e3f4f1242645dc47a2e85bcbe4b8d7a8185e7000f7655499a681467d71000bd05244d47947991e01d822\ 3c817c45780617c2a1fed7f14f334615af5cd378b298c36afe497ed4e6d74b8f87312cc7d9c03b1b260ae50eae\ 83b121f59686686a44115094562752ce8e7eef2baf5383aaf67c4b9cc3e12d6edf2424fab1e11fdea7d433bca4\ 4d5022ed471d20ae60d74b953c30bbc0a8ca668f86c230ff4b42e14ee60fa2752e462642cebb5c383da047309e\ fec6fff1c9ab3b796ef8d1b446f6b7b87453acf3c77dcdab7d5eb310fb8b07a014e9c03e0f1e0fcdd841bc45e2\ 186afe58e091e66d9d713952fbf2cef88598adf4ce26f02044d52ef69dca5124d91adc008a9375da7ec5b47953\ 0ff2146c81ab095fe0a995a418ed5eef9ab0b044f06369d3e37b1b97baf10ee167701aa2bdcde28e3b3ab1924e\ 9f93affd5e402c83fbc35c9c1ebe0b497b1eb1fb1333d19373e5b7327b1da58ef99c201deee108a885f9d569d3\ 7843e775a3b7a6ebe41c3b08f740482934519c3d82cabd6bc17498ad9d484526b2af59e948b13fc009a7ae97d7\ ed1dd29de6c5cbeff0deb3f702f4b105873857f2fa74515cca70f8453dafb5bd7104a15ad9259826c47c17ac69\ a50cb6280457aa7ae6a4dcf359618816b665a5949609815ffb3b9a5ca3db6941ab0faba197ed8870640a0714bc\ c395db140d3ab37df75a5c13af7fe4d8b784d8594a59a664cb01ecb6910be6712b1f42d802886f52cd61fc24a8\ 13d04b79a53bf7bd7c5a328606a507d61c98e40551ed0923be10c7927cfc334b9a72486dfcdf217395cf771132\ 201a0c1814249a0edd7771933fa5a194818792f12eb0aed7c164b6a95c3786ff646361d752e#10000", Greater, ); let sqrt_3_f32 = Float::sqrt_3_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(sqrt_3_f32.to_string(), "1.7320508"); assert_eq!(to_hex_string(&sqrt_3_f32), "0x1.bb67ae#24"); assert_eq!(sqrt_3_f32, f32::SQRT_3); let sqrt_3_f64 = Float::sqrt_3_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(sqrt_3_f64.to_string(), "1.7320508075688772"); assert_eq!(to_hex_string(&sqrt_3_f64), "0x1.bb67ae8584caa#53"); assert_eq!(sqrt_3_f64, f64::SQRT_3); } #[test] #[should_panic] fn sqrt_3_prec_fail_1() { Float::sqrt_3_prec(0); } fn test_sqrt_3_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::sqrt_3_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_sqrt_3_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_sqrt_3_prec_round() { test_sqrt_3_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_sqrt_3_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_sqrt_3_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_sqrt_3_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_sqrt_3_prec_round_helper(1, Nearest, "2.0", "0x2.0#1", Greater); test_sqrt_3_prec_round_helper(2, Floor, "1.5", "0x1.8#2", Less); test_sqrt_3_prec_round_helper(2, Ceiling, "2.0", "0x2.0#2", Greater); test_sqrt_3_prec_round_helper(2, Down, "1.5", "0x1.8#2", Less); test_sqrt_3_prec_round_helper(2, Up, "2.0", "0x2.0#2", Greater); test_sqrt_3_prec_round_helper(2, Nearest, "1.5", "0x1.8#2", Less); test_sqrt_3_prec_round_helper(3, Floor, "1.5", "0x1.8#3", Less); test_sqrt_3_prec_round_helper(3, Ceiling, "1.8", "0x1.c#3", Greater); test_sqrt_3_prec_round_helper(3, Down, "1.5", "0x1.8#3", Less); test_sqrt_3_prec_round_helper(3, Up, "1.8", "0x1.c#3", Greater); test_sqrt_3_prec_round_helper(3, Nearest, "1.8", "0x1.c#3", Greater); test_sqrt_3_prec_round_helper(4, Floor, "1.6", "0x1.a#4", Less); test_sqrt_3_prec_round_helper(4, Ceiling, "1.8", "0x1.c#4", Greater); test_sqrt_3_prec_round_helper(4, Down, "1.6", "0x1.a#4", Less); test_sqrt_3_prec_round_helper(4, Up, "1.8", "0x1.c#4", Greater); test_sqrt_3_prec_round_helper(4, Nearest, "1.8", "0x1.c#4", Greater); test_sqrt_3_prec_round_helper(5, Floor, "1.7", "0x1.b#5", Less); test_sqrt_3_prec_round_helper(5, Ceiling, "1.75", "0x1.c#5", Greater); test_sqrt_3_prec_round_helper(5, Down, "1.7", "0x1.b#5", Less); test_sqrt_3_prec_round_helper(5, Up, "1.75", "0x1.c#5", Greater); test_sqrt_3_prec_round_helper(5, Nearest, "1.75", "0x1.c#5", Greater); test_sqrt_3_prec_round_helper(6, Floor, "1.72", "0x1.b8#6", Less); test_sqrt_3_prec_round_helper(6, Ceiling, "1.75", "0x1.c0#6", Greater); test_sqrt_3_prec_round_helper(6, Down, "1.72", "0x1.b8#6", Less); test_sqrt_3_prec_round_helper(6, Up, "1.75", "0x1.c0#6", Greater); test_sqrt_3_prec_round_helper(6, Nearest, "1.72", "0x1.b8#6", Less); test_sqrt_3_prec_round_helper(7, Floor, "1.72", "0x1.b8#7", Less); test_sqrt_3_prec_round_helper(7, Ceiling, "1.73", "0x1.bc#7", Greater); test_sqrt_3_prec_round_helper(7, Down, "1.72", "0x1.b8#7", Less); test_sqrt_3_prec_round_helper(7, Up, "1.73", "0x1.bc#7", Greater); test_sqrt_3_prec_round_helper(7, Nearest, "1.73", "0x1.bc#7", Greater); test_sqrt_3_prec_round_helper(8, Floor, "1.727", "0x1.ba#8", Less); test_sqrt_3_prec_round_helper(8, Ceiling, "1.734", "0x1.bc#8", Greater); test_sqrt_3_prec_round_helper(8, Down, "1.727", "0x1.ba#8", Less); test_sqrt_3_prec_round_helper(8, Up, "1.734", "0x1.bc#8", Greater); test_sqrt_3_prec_round_helper(8, Nearest, "1.734", "0x1.bc#8", Greater); test_sqrt_3_prec_round_helper(9, Floor, "1.73", "0x1.bb#9", Less); test_sqrt_3_prec_round_helper(9, Ceiling, "1.734", "0x1.bc#9", Greater); test_sqrt_3_prec_round_helper(9, Down, "1.73", "0x1.bb#9", Less); test_sqrt_3_prec_round_helper(9, Up, "1.734", "0x1.bc#9", Greater); test_sqrt_3_prec_round_helper(9, Nearest, "1.73", "0x1.bb#9", Less); test_sqrt_3_prec_round_helper(10, Floor, "1.73", "0x1.bb0#10", Less); test_sqrt_3_prec_round_helper(10, Ceiling, "1.732", "0x1.bb8#10", Greater); test_sqrt_3_prec_round_helper(10, Down, "1.73", "0x1.bb0#10", Less); test_sqrt_3_prec_round_helper(10, Up, "1.732", "0x1.bb8#10", Greater); test_sqrt_3_prec_round_helper(10, Nearest, "1.732", "0x1.bb8#10", Greater); test_sqrt_3_prec_round_helper( 100, Floor, "1.732050807568877293527446341505", "0x1.bb67ae8584caa73b25742d706#100", Less, ); test_sqrt_3_prec_round_helper( 100, Ceiling, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test_sqrt_3_prec_round_helper( 100, Down, "1.732050807568877293527446341505", "0x1.bb67ae8584caa73b25742d706#100", Less, ); test_sqrt_3_prec_round_helper( 100, Up, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); test_sqrt_3_prec_round_helper( 100, Nearest, "1.732050807568877293527446341506", "0x1.bb67ae8584caa73b25742d708#100", Greater, ); } #[test] #[should_panic] fn sqrt_3_prec_round_fail_1() { Float::sqrt_3_prec_round(0, Floor); } #[test] #[should_panic] fn sqrt_3_prec_round_fail_2() { Float::sqrt_3_prec_round(1, Exact); } #[test] #[should_panic] fn sqrt_3_prec_round_fail_3() { Float::sqrt_3_prec_round(1000, Exact); } #[test] fn sqrt_3_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (sqrt_3, o) = Float::sqrt_3_prec(prec); assert!(sqrt_3.is_valid()); assert_eq!(sqrt_3.get_prec(), Some(prec)); assert_eq!(sqrt_3.get_exponent(), Some(if prec == 1 { 2 } else { 1 })); assert_ne!(o, Equal); if o == Less { let (sqrt_3_alt, o_alt) = Float::sqrt_3_prec_round(prec, Ceiling); let mut next_upper = sqrt_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_3_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_3.is_power_of_2() { let (sqrt_3_alt, o_alt) = Float::sqrt_3_prec_round(prec, Floor); let mut next_lower = sqrt_3.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_3_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (sqrt_3_alt, o_alt) = Float::sqrt_3_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&sqrt_3_alt), ComparableFloatRef(&sqrt_3)); assert_eq!(o_alt, o); let (rug_sqrt_3, rug_o) = rug_sqrt_3_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_3)), ComparableFloatRef(&sqrt_3) ); assert_eq!(rug_o, o); }); } #[test] fn sqrt_3_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (sqrt_3, o) = Float::sqrt_3_prec_round(prec, rm); assert!(sqrt_3.is_valid()); assert_eq!(sqrt_3.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 2, _ => 1, }; assert_eq!(sqrt_3.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (sqrt_3_alt, o_alt) = Float::sqrt_3_prec_round(prec, Ceiling); let mut next_upper = sqrt_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_3_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_3.is_power_of_2() { let (sqrt_3_alt, o_alt) = Float::sqrt_3_prec_round(prec, Floor); let mut next_lower = sqrt_3.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_3_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt_3, rug_o) = rug_sqrt_3_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_3)), ComparableFloatRef(&sqrt_3) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::sqrt_3_prec_round(prec, Exact)); }); test_constant(Float::sqrt_3_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/sqrt_3_over_3.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Sqrt3Over3; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{ rug_round_try_from_rounding_mode, test_constant, to_hex_string, }; use malachite_float::test_util::constants::sqrt_3_over_3::rug_sqrt_3_over_3_prec_round; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_sqrt_3_over_3_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::sqrt_3_over_3_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (rug_x, rug_o) = rug_sqrt_3_over_3_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } #[test] pub fn test_sqrt_3_over_3_prec() { test_sqrt_3_over_3_prec_helper(1, "0.5", "0x0.8#1", Less); test_sqrt_3_over_3_prec_helper(2, "0.5", "0x0.8#2", Less); test_sqrt_3_over_3_prec_helper(3, "0.6", "0x0.a#3", Greater); test_sqrt_3_over_3_prec_helper(4, "0.56", "0x0.9#4", Less); test_sqrt_3_over_3_prec_helper(5, "0.56", "0x0.90#5", Less); test_sqrt_3_over_3_prec_helper(6, "0.58", "0x0.94#6", Greater); test_sqrt_3_over_3_prec_helper(7, "0.58", "0x0.94#7", Greater); test_sqrt_3_over_3_prec_helper(8, "0.578", "0x0.94#8", Greater); test_sqrt_3_over_3_prec_helper(9, "0.578", "0x0.940#9", Greater); test_sqrt_3_over_3_prec_helper(10, "0.577", "0x0.93c#10", Less); test_sqrt_3_over_3_prec_helper( 100, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test_sqrt_3_over_3_prec_helper( 1000, "0.577350269189625764509148780501957455647601751270126876018602326483977672302933345693715\ 395585749525225208713805135567676656648364999650826270551837364791216176031077300768527355\ 991606700361558307755005104114422301107628883557418222973945990409015710553455953862673016\ 6621791266197964892167825021920169", "0x0.93cd3a2c8198e2690c7c0f257d92be830c9d66eec69e17dd97b58cc2cf6c8cf61859454874fb1f3f38865\ 8e4b0b62fd7eec450c48be0a422f044668ab39de12be8a060f75bd968f79f74f4be9c0f3d100923fc713a7e58a\ 9cf94fbbe338aa1d2631625104c830e3c7b80799a541d88671fd505ebf61a67cd8c97ee859c#1000", Less, ); test_sqrt_3_over_3_prec_helper( 10000, "0.577350269189625764509148780501957455647601751270126876018602326483977672302933345693715\ 395585749525225208713805135567676656648364999650826270551837364791216176031077300768527355\ 991606700361558307755005104114422301107628883557418222973945990409015710553455953862673016\ 662179126619796489216782502192016918872782709868700315867395730108361048609841319944332596\ 608169429571487944305782408054661529285132555986021272784555370281057926964792772034029435\ 174967223341173570381429565330318788599029056166024299831098828094340262136201329579565845\ 860772439277131997661002612900959017971123187770701235754673083035589410399762791880380474\ 005580917367457664756943686632819825329221429632598715945986130076284950967858677950936021\ 460657448220353229907624288421384607554899473340398494718426147060428844835678397216672229\ 764805160282023759047999920975611543192479453965036709049546248992181994150596183658459671\ 293554987303987407652370185080974574397399246087520543822947344284572227646216537305683246\ 278798498646048585890617791211041970299885141541611595732535078665923064107856740101767613\ 461971804990357476519735568734169840058654395290922119991761221143693383555284570215776179\ 541974086860740170134560090099168266242693153886033472350893980006365244487391981297890083\ 106807563678123270821240037061753694756303433240103734033354502392124860801734615851732426\ 644599204968702631661848074442001339617101210520381628949093863096054415062421688881794959\ 199720858880957370413614022672254505700034314393571838396987214153635679802709738967839164\ 320454668046556810347084544109010307525775986764125532581845698489705247380141410260664109\ 205800635474837484959172287565368444564738737868464868081884713376177669271211149952245468\ 901325780743270653680975178167200468646826515718178182802423912552087455516388880077668671\ 088581356702612286156150771053489251493500134080213303990120739534306746289050237005723133\ 432289586554500013631772071411141742652278022337823395300676120238920715914497816521198602\ 694043480862156489507536969421117669585537534486890731801351994709637658664936666924019146\ 743349224419600030504790496491814959719063764886361190291320505179265880087356123616015357\ 656460906528563253253208701386384219192596927444993522613340967177350712978457925178855475\ 682275624763321147131914555357914815194362159297737661767382732465113826056838871650850587\ 763997899855248174213037506364513795663122272476979408808245642067357663655943718043982161\ 459305153305307976095904898383091342136404548551347214860496733981916473101756334204657548\ 693688357146534402025836864729266094931328731749988055071046571764533140632472215691729078\ 596209822036186723476289868599464684302135810270611129559293854211955718669465586748449743\ 314646289019918105147647810319086156996071821037086922258022621523859353549149166583451514\ 853104428849729949778857582542099138246078562304945943787787094542634608280054602223869059\ 949576185280977116408697746855319184550378918214795944761104488881518060130273966327764875\ 44833872370733897653982005644020701101324831", "0x0.93cd3a2c8198e2690c7c0f257d92be830c9d66eec69e17dd97b58cc2cf6c8cf61859454874fb1f3f38865\ 8e4b0b62fd7eec450c48be0a422f044668ab39de12be8a060f75bd968f79f74f4be9c0f3d100923fc713a7e58a\ 9cf94fbbe338aa1d2631625104c830e3c7b80799a541d88671fd505ebf61a67cd8c97ee859c7100c574a55c425\ 8f3b4eb3e51da5816bbeaf1ccdce013487648166b318e3b219cc0fd24b98529ea476e689e4653527b79786596d\ f1855449605b18cebce639255d8fcc95afd578da9a6b2da5127f0f1e7545dc0f7a9c0a89b692228069fc0ae784\ 65be6828f559d35f49c038cde91bc64670b70de26233a5e44cb9810c9a459b2eb6cbc9ccb453c22ea0903254cd\ 28d2d1cffc23c7024600e9391f66706707d202af7c5f7e24f0f99474390116a77d3eba6f100ae5b97369f1c07a\ c5c509db04218d2cf351a9f4bacf544af4d6cce59590587d55bc2e3187e437c949b3b992e01611053c371500fe\ a00e594773bd64c6827ede691b2fd67fade8a36a39e19f7d17c19777fa27d8d4a0b004fbd6d1d1482ea73127de\ 5208c179c9a7cebdf891f68da2ba39e69392e94f1d142b666433cdb8f2d86213122d419a9b783fd95b51a686da\ bd5cab015c40bb47391a31c4436708ae87e895f54340cbe95daa0902ddfa8f7f415f215359b88ca1f1c0a70cb2\ 8e6cd099f9d1dc124baf36116db3b30f4245daff79074d0f58b1643710ebdd0a04c7e1af1b2661e70c074450a1\ aa3dfa93695030a896aa913890c13e555e1fe2ededb7b5b1ec9352450310ca4421de917e13b9ea77597ea9c017\ 808c95595ae96ed3284c61ca95e35b6597d22fcbb443e1ff8265c1b7c12540a081b554502585755c091f7ed59b\ a8041d4bfc50616217496d364d73eea192f28d5d74d00052771c3337806cd47b0003f01b6c46d317ddb4ab480b\ 69807ec1d2acb29635ff9d506fbbc2073a74467d90dd9678ff6dd4f1a247c3da8265b997f34013b3b758f704e4\ d69060a7322ccd78c15b1adc1cb7c644da2a4fb93a712be3a77ec3deebf5b9cf9fb6b6fe3b4b0a9f8d46bbe98c\ 19c560f9c25f0ae4caf26e8714103e958d98ccda8240baffc3c0f5c4f75a8b7c64c20cc0ef93c968148ac2658a\ 54ecfffb433913d324fd9b3c17a79292d17139a697d499e3d474e65afe83ad355c4deabf5a5f5a99f2c094174b\ 5d78ff72f585f779df25bdc653fb9a52d732e4a6ef62500ac19c64fcdf4370619db39eaad8dbd1f37f973c2871\ 0550b179808e58754ae331e15da474fa88e59016facbcdf14bd3b3dd3e505a4b227ab38b9499f62f691390861a\ 35313aa9ca15642bfe9674340a3f59187e5f90a906669b3126a1e7bb7e5f372fa8896009fa4b02e2d753472346\ 7d6bf7d1e13d37a3f6b413ada7c0180dbc1b341480ee3f23eb26dd8f346d6c623b8fc8a3183b15400337e4dd47\ f9b49b89f79743faa59f9152565190572d12c7fba8d17074437afd6c69e53c947b018b1e4861dd62417eb28ecd\ e1aee762ac1d38d3a236f4511dcb2d5ce77737318758807553be88c98bf3cdc08e5a8e8b32a482d02158ad06e9\ 96874906af139129fd1e1eb13a7ff6f2e7d6f2c86e1de2219900a43cdb03f77b0e5fc0f2ab82cfc64475feb6e2\ b1456e7de1bea7e9d41e10d7578c57f209884c01c5f9adb694b0428629a9666e88d0c2cf544a607bdc9a7d05bb\ 6008aeb2b16188af9f27d0866a8c8b318082865064e58f9d4076e78dc967d7aa76cbcb47c65#10000", Greater, ); let sqrt_3_over_3_f32 = Float::sqrt_3_over_3_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(sqrt_3_over_3_f32.to_string(), "0.57735026"); assert_eq!(to_hex_string(&sqrt_3_over_3_f32), "0x0.93cd3a#24"); assert_eq!(sqrt_3_over_3_f32, f32::SQRT_3_OVER_3); let sqrt_3_over_3_f64 = Float::sqrt_3_over_3_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(sqrt_3_over_3_f64.to_string(), "0.5773502691896257"); assert_eq!(to_hex_string(&sqrt_3_over_3_f64), "0x0.93cd3a2c8198e0#53"); assert_eq!(sqrt_3_over_3_f64, f64::SQRT_3_OVER_3); } #[test] #[should_panic] fn sqrt_3_over_3_prec_fail_1() { Float::sqrt_3_over_3_prec(0); } fn test_sqrt_3_over_3_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::sqrt_3_over_3_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug_sqrt_3_over_3_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_x)), ComparableFloatRef(&x) ); assert_eq!(rug_o, o); } } #[test] pub fn test_sqrt_3_over_3_prec_round() { test_sqrt_3_over_3_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_sqrt_3_over_3_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_sqrt_3_over_3_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_sqrt_3_over_3_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_sqrt_3_over_3_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_sqrt_3_over_3_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_sqrt_3_over_3_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_sqrt_3_over_3_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_sqrt_3_over_3_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_sqrt_3_over_3_prec_round_helper(2, Nearest, "0.5", "0x0.8#2", Less); test_sqrt_3_over_3_prec_round_helper(3, Floor, "0.5", "0x0.8#3", Less); test_sqrt_3_over_3_prec_round_helper(3, Ceiling, "0.6", "0x0.a#3", Greater); test_sqrt_3_over_3_prec_round_helper(3, Down, "0.5", "0x0.8#3", Less); test_sqrt_3_over_3_prec_round_helper(3, Up, "0.6", "0x0.a#3", Greater); test_sqrt_3_over_3_prec_round_helper(3, Nearest, "0.6", "0x0.a#3", Greater); test_sqrt_3_over_3_prec_round_helper(4, Floor, "0.56", "0x0.9#4", Less); test_sqrt_3_over_3_prec_round_helper(4, Ceiling, "0.62", "0x0.a#4", Greater); test_sqrt_3_over_3_prec_round_helper(4, Down, "0.56", "0x0.9#4", Less); test_sqrt_3_over_3_prec_round_helper(4, Up, "0.62", "0x0.a#4", Greater); test_sqrt_3_over_3_prec_round_helper(4, Nearest, "0.56", "0x0.9#4", Less); test_sqrt_3_over_3_prec_round_helper(5, Floor, "0.56", "0x0.90#5", Less); test_sqrt_3_over_3_prec_round_helper(5, Ceiling, "0.59", "0x0.98#5", Greater); test_sqrt_3_over_3_prec_round_helper(5, Down, "0.56", "0x0.90#5", Less); test_sqrt_3_over_3_prec_round_helper(5, Up, "0.59", "0x0.98#5", Greater); test_sqrt_3_over_3_prec_round_helper(5, Nearest, "0.56", "0x0.90#5", Less); test_sqrt_3_over_3_prec_round_helper(6, Floor, "0.56", "0x0.90#6", Less); test_sqrt_3_over_3_prec_round_helper(6, Ceiling, "0.58", "0x0.94#6", Greater); test_sqrt_3_over_3_prec_round_helper(6, Down, "0.56", "0x0.90#6", Less); test_sqrt_3_over_3_prec_round_helper(6, Up, "0.58", "0x0.94#6", Greater); test_sqrt_3_over_3_prec_round_helper(6, Nearest, "0.58", "0x0.94#6", Greater); test_sqrt_3_over_3_prec_round_helper(7, Floor, "0.57", "0x0.92#7", Less); test_sqrt_3_over_3_prec_round_helper(7, Ceiling, "0.58", "0x0.94#7", Greater); test_sqrt_3_over_3_prec_round_helper(7, Down, "0.57", "0x0.92#7", Less); test_sqrt_3_over_3_prec_round_helper(7, Up, "0.58", "0x0.94#7", Greater); test_sqrt_3_over_3_prec_round_helper(7, Nearest, "0.58", "0x0.94#7", Greater); test_sqrt_3_over_3_prec_round_helper(8, Floor, "0.574", "0x0.93#8", Less); test_sqrt_3_over_3_prec_round_helper(8, Ceiling, "0.578", "0x0.94#8", Greater); test_sqrt_3_over_3_prec_round_helper(8, Down, "0.574", "0x0.93#8", Less); test_sqrt_3_over_3_prec_round_helper(8, Up, "0.578", "0x0.94#8", Greater); test_sqrt_3_over_3_prec_round_helper(8, Nearest, "0.578", "0x0.94#8", Greater); test_sqrt_3_over_3_prec_round_helper(9, Floor, "0.576", "0x0.938#9", Less); test_sqrt_3_over_3_prec_round_helper(9, Ceiling, "0.578", "0x0.940#9", Greater); test_sqrt_3_over_3_prec_round_helper(9, Down, "0.576", "0x0.938#9", Less); test_sqrt_3_over_3_prec_round_helper(9, Up, "0.578", "0x0.940#9", Greater); test_sqrt_3_over_3_prec_round_helper(9, Nearest, "0.578", "0x0.940#9", Greater); test_sqrt_3_over_3_prec_round_helper(10, Floor, "0.577", "0x0.93c#10", Less); test_sqrt_3_over_3_prec_round_helper(10, Ceiling, "0.578", "0x0.940#10", Greater); test_sqrt_3_over_3_prec_round_helper(10, Down, "0.577", "0x0.93c#10", Less); test_sqrt_3_over_3_prec_round_helper(10, Up, "0.578", "0x0.940#10", Greater); test_sqrt_3_over_3_prec_round_helper(10, Nearest, "0.577", "0x0.93c#10", Less); test_sqrt_3_over_3_prec_round_helper( 100, Floor, "0.577350269189625764509148780501", "0x0.93cd3a2c8198e2690c7c0f257#100", Less, ); test_sqrt_3_over_3_prec_round_helper( 100, Ceiling, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test_sqrt_3_over_3_prec_round_helper( 100, Down, "0.577350269189625764509148780501", "0x0.93cd3a2c8198e2690c7c0f257#100", Less, ); test_sqrt_3_over_3_prec_round_helper( 100, Up, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); test_sqrt_3_over_3_prec_round_helper( 100, Nearest, "0.577350269189625764509148780502", "0x0.93cd3a2c8198e2690c7c0f258#100", Greater, ); } #[test] #[should_panic] fn sqrt_3_over_3_prec_round_fail_1() { Float::sqrt_3_over_3_prec_round(0, Floor); } #[test] #[should_panic] fn sqrt_3_over_3_prec_round_fail_2() { Float::sqrt_3_over_3_prec_round(1, Exact); } #[test] #[should_panic] fn sqrt_3_over_3_prec_round_fail_3() { Float::sqrt_3_over_3_prec_round(1000, Exact); } #[test] fn sqrt_3_over_3_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec(prec); assert!(sqrt_3_over_3.is_valid()); assert_eq!(sqrt_3_over_3.get_prec(), Some(prec)); assert_eq!(sqrt_3_over_3.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (sqrt_3_over_3_alt, o_alt) = Float::sqrt_3_over_3_prec_round(prec, Ceiling); let mut next_upper = sqrt_3_over_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(sqrt_3_over_3_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !sqrt_3_over_3.is_power_of_2() { let (sqrt_3_over_3_alt, o_alt) = Float::sqrt_3_over_3_prec_round(prec, Floor); let mut next_lower = sqrt_3_over_3.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(sqrt_3_over_3_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (sqrt_3_over_3_alt, o_alt) = Float::sqrt_3_over_3_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&sqrt_3_over_3_alt), ComparableFloatRef(&sqrt_3_over_3) ); assert_eq!(o_alt, o); let (rug_sqrt_3_over_3, rug_o) = rug_sqrt_3_over_3_prec_round(prec, rug_round_try_from_rounding_mode(Nearest).unwrap()); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_3_over_3)), ComparableFloatRef(&sqrt_3_over_3) ); assert_eq!(rug_o, o); }); } #[test] fn sqrt_3_over_3_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (sqrt_3_over_3, o) = Float::sqrt_3_over_3_prec_round(prec, rm); assert!(sqrt_3_over_3.is_valid()); assert_eq!(sqrt_3_over_3.get_prec(), Some(prec)); assert_eq!( sqrt_3_over_3.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (sqrt_3_over_3_alt, o_alt) = Float::sqrt_3_over_3_prec_round(prec, Ceiling); let mut next_upper = sqrt_3_over_3.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(sqrt_3_over_3_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !sqrt_3_over_3.is_power_of_2() { let (sqrt_3_over_3_alt, o_alt) = Float::sqrt_3_over_3_prec_round(prec, Floor); let mut next_lower = sqrt_3_over_3.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(sqrt_3_over_3_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_sqrt_3_over_3, rug_o) = rug_sqrt_3_over_3_prec_round(prec, rm); assert_eq!( ComparableFloatRef(&Float::from(&rug_sqrt_3_over_3)), ComparableFloatRef(&sqrt_3_over_3) ); assert_eq!(rug_o, o); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::sqrt_3_over_3_prec_round(prec, Exact)); }); test_constant(Float::sqrt_3_over_3_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::SqrtPi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::test_util::constants::sqrt_pi::sqrt_pi_prec_round_simple; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_sqrt_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::sqrt_pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = sqrt_pi_prec_round_simple(prec, Nearest); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_sqrt_pi_prec() { test_sqrt_pi_prec_helper(1, "2.0", "0x2.0#1", Greater); test_sqrt_pi_prec_helper(2, "2.0", "0x2.0#2", Greater); test_sqrt_pi_prec_helper(3, "1.8", "0x1.c#3", Less); test_sqrt_pi_prec_helper(4, "1.8", "0x1.c#4", Less); test_sqrt_pi_prec_helper(5, "1.75", "0x1.c#5", Less); test_sqrt_pi_prec_helper(6, "1.78", "0x1.c8#6", Greater); test_sqrt_pi_prec_helper(7, "1.77", "0x1.c4#7", Less); test_sqrt_pi_prec_helper(8, "1.773", "0x1.c6#8", Greater); test_sqrt_pi_prec_helper(9, "1.773", "0x1.c6#9", Greater); test_sqrt_pi_prec_helper(10, "1.771", "0x1.c58#10", Less); test_sqrt_pi_prec_helper( 100, "1.772453850905516027298167483341", "0x1.c5bf891b4ef6aa79c3b0520d6#100", Greater, ); test_sqrt_pi_prec_helper( 1000, "1.772453850905516027298167483341145182797549456122387128213807789852911284591032181374950\ 656738544665416226823624282570666236152865724422602525093709602787068462037698653105122849\ 925173028950826228932095379267962800174639015351479720516700190185234018585446974494912640\ 3139217755259062164054193325009063", "0x1.c5bf891b4ef6aa79c3b0520d5db9383fe3921546f63b252dca100bd3ea14746ed76ffd6f941f1dbacd8e7\ 6141e0c77476c521446ddc35851524490c34a42174dcbafdf109d1b3acfb553ade465bea6c5032aa8a111a626e\ 2c702f124d16fb3a90b8b1717835c4e1ec9c08f40a3db6d8123741ca788a38e7a619ffb5bae#1000", Less, ); test_sqrt_pi_prec_helper( 10000, "1.772453850905516027298167483341145182797549456122387128213807789852911284591032181374950\ 656738544665416226823624282570666236152865724422602525093709602787068462037698653105122849\ 925173028950826228932095379267962800174639015351479720516700190185234018585446974494912640\ 313921775525906216405419332500906398407613733477475153433667989789365851836408795451165161\ 738760059067393431791332809854846248184902054654852195613251561647467515042738761056107996\ 127107210060372044483672365296613708094323498831668424213845709609120420427785778068694766\ 570005218305685125413396636944654181510716693883321942929357062268865224420542149948049920\ 756486398874838505930640218214029285811233064978945203621149078962287389403245978198513134\ 871266512506293260044656382109675026812496930595420461560761952217391525070207792758099054\ 332900662223067614469661248188743069978835205061464443854185307973574257179185635959749959\ 952263849242203889103966406447293972841345043002140564233433039261756134176336320017037654\ 163476320669276541812835762490326904508485320134192435989730871193799482938730111262561658\ 818884785977875963761363218634246546641333954355703201522654193952186030497310513829498439\ 659165614245955421226615102478536098095510395600789402188099613382854025016800745802729119\ 366425192820510001936350073914643295493433951928853735459200563766502880540575532123189009\ 126322819150914980836695624483100852221923973646324842863261145766932425371577377894414090\ 544573595351225626391080239236909732127905807617134603914574791879794124850218445145811341\ 888880413220955332184646709727491028565262707845453262227848800982385836300754950954764062\ 377083388357225436621567481327668384244972420874516161833205077991480184666814236693651902\ 845463857614827857037774388376297479982737705431583682410998683228503805526355369722293133\ 805264428410372312043967004307612454138311792278275363715598398376884537027842985707090511\ 223840536779013385414585316208073043138069739987436693166013817079272056041954882858063093\ 111636297047867814026963272962701226135985897754505289483113016684001532074851982402463337\ 555851713568019341228975980719568740250571502141783792543643030365928211250925880618903117\ 074543127903953553660682611001188965742048727593919976995538352115086696255596441370503829\ 244953590310636234530564717116216858725458687440029611757921723190554057198681727588419089\ 649657906696515601728351482903856551169807210795330916130843598524389465440682165500327537\ 996023866503798886481521186579995857186563775113315974753596043413776645119143460134292508\ 116324806409073773212629335747472967679341271602966512080989809057799660305102181625557978\ 907487076211076238026267854297015027109153504985351492390832484280828987595575678848892608\ 420885521269510357370208661259115541320440373560864338837123962064293902378666311632616788\ 841922798194995240394245784220443030420430420710969273392946085104969289739161855607837870\ 336428902342932718872968029721581659426129728366395905041130374745743509749058016326916537\ 5769098109748562537785034287994219223771859", "0x1.c5bf891b4ef6aa79c3b0520d5db9383fe3921546f63b252dca100bd3ea14746ed76ffd6f941f1dbacd8e7\ 6141e0c77476c521446ddc35851524490c34a42174dcbafdf109d1b3acfb553ade465bea6c5032aa8a111a626e\ 2c702f124d16fb3a90b8b1717835c4e1ec9c08f40a3db6d8123741ca788a38e7a619ffb5baebf7b166df28b5d2\ ce89be636c040bb4096804fd2cd93812fbb09908b40ae5eede4891596c00af6afa05395faf6c86dc08b42b2eb0\ dfb3a4876c1b058529354f2d429308d212dfcafadc0b046f3bc362555d119aaf416e879d013f2c8f4a2d55dab8\ c4a398e161c9a5ba77ff284c3fdf892bf0f36805c5b0f813e47b36432ae9abfb8c2df6620a343b71239bd6f0ff\ 6e4525e14f2fd52776201d3e8ef4114462465d2552a8f30a26da0b28395985eaf57168b0fc66f7c6a5b8866f58\ 404028f9bf801f152865bb9b5adc90f6db648f9cfb609ca9193da29454c09450a4c8efbec6b5aeb4f075432e78\ 235da1447372389183627d449bafefcf9fd8a7267a98772baffa71b8d310c9d4f58bfd3d7299db12456357ddd5\ 2d6a9c56cf29d0303cbc0bf54a3ba39a725c78e8f19a0e59bfa4c7f915be3ff44c6c5d7b325585276abd43e221\ ca9aafdd05c54a3fed2de03ba9b2606683f2870665e21a663c1387b4e02b4b90cc94033cc9775f2372e04174f5\ 19c42b9f65ec003149951eab1053ac0b7b77d251a898259637e3f17aea75bf15a08060348c31a61bd0b7e27e7c\ 68c614857ab238b36c1c64718de50ddc4293720630dbd5452b0d542e3f897e6bde585711e016e030e5dec6161b\ a79dff01f061ca3b961fc02e77db5d73f2ef6d47c471d57f97a9a134cce64b48479d0628117f4350aff9d0d8ac\ b474bdea6af441f7ade16dd2b1d90e128a91425fbef3609a23ee55c413660fee0224e4ff76fd23e43f11038c51\ fef6ab1c0b9c2a50c5e15f92f5c998d5fac7d979367efd2277ccb66a735d3480c02f6dbdff7ac4e13dc41ec140\ 1b7424ad067f21c1f72464177ce2d902a6d60868b14aeed4385e55c94e0264549528cff2d94ecb0f9ea6febc17\ 8e7c440d9f1fa1e2c8bce21f2aa74067c08073707df38ff04fb731fe11753c63e5178fb6e0856db51bf8ae3f46\ f3db7248a242f320803db8570f9ba75cea2e97d479ecfa6c84a3d9fe177eb2610ead682efed92bc297e843d696\ f9797852fe0da2230c230757c48bf6172d2a8f6c94af315ffd09d9fc3fbe5f9146b2da2de051f6b0914fe89a2e\ 142e02ab85f76391911ff1eaaa0fe03cea3f7ccb93a1581dec1650dd6b1a1ff53eca03f427bf879f02ec73b2c0\ cc2109c261083c4810c681d4fcdc970239432382a9cae18656ca343b831e1e720d4b4121472f039ac06c3dd3a6\ ee46f70e2e929ca487dda488e4f4f80a00ad9bf6f7aaed026102f31a2d2f858c91ec18d5d8948940b306095746\ 8b4536d01bd00313ddf4685220b51c9b72856b906526488af9b2aaf0850915918a621fe23a63fb2594cf359db7\ 0377bb3a408a210dc230fa803135e46c1f2914f43ad8275f98dde221a0c93c23905fd6ae77eb55dc2c017d7e3b\ 84c564107577e6bd0f9817cc73db32a279d38fe586e954296ace2e7901a15b8974ec1b87c419d75684f61076cb\ f653eae047e7f31c0c50e27f992c19f3059f632baa5aae158021bb870bbc9162f579d3ca45d2208e000d91a4fb\ a0750031b19a4ab6e88733c2a86de645b7bf87676bcfa4347b1b40ad01adaba2967096f969e#10000", Greater, ); let sqrt_pi_f32 = Float::sqrt_pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(sqrt_pi_f32.to_string(), "1.7724539"); assert_eq!(to_hex_string(&sqrt_pi_f32), "0x1.c5bf8a#24"); assert_eq!(sqrt_pi_f32, f32::SQRT_PI); let sqrt_pi_f64 = Float::sqrt_pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(sqrt_pi_f64.to_string(), "1.7724538509055161"); assert_eq!(to_hex_string(&sqrt_pi_f64), "0x1.c5bf891b4ef6b#53"); assert_eq!(sqrt_pi_f64, f64::SQRT_PI); } #[test] #[should_panic] fn sqrt_pi_prec_fail_1() { Float::sqrt_pi_prec(0); } fn test_sqrt_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::sqrt_pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x_alt, o_alt) = sqrt_pi_prec_round_simple(prec, rm); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); assert_eq!(o_alt, o); } #[test] pub fn test_sqrt_pi_prec_round() { test_sqrt_pi_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_sqrt_pi_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_sqrt_pi_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_sqrt_pi_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_sqrt_pi_prec_round_helper(1, Nearest, "2.0", "0x2.0#1", Greater); test_sqrt_pi_prec_round_helper(2, Floor, "1.5", "0x1.8#2", Less); test_sqrt_pi_prec_round_helper(2, Ceiling, "2.0", "0x2.0#2", Greater); test_sqrt_pi_prec_round_helper(2, Down, "1.5", "0x1.8#2", Less); test_sqrt_pi_prec_round_helper(2, Up, "2.0", "0x2.0#2", Greater); test_sqrt_pi_prec_round_helper(2, Nearest, "2.0", "0x2.0#2", Greater); test_sqrt_pi_prec_round_helper(3, Floor, "1.8", "0x1.c#3", Less); test_sqrt_pi_prec_round_helper(3, Ceiling, "2.0", "0x2.0#3", Greater); test_sqrt_pi_prec_round_helper(3, Down, "1.8", "0x1.c#3", Less); test_sqrt_pi_prec_round_helper(3, Up, "2.0", "0x2.0#3", Greater); test_sqrt_pi_prec_round_helper(3, Nearest, "1.8", "0x1.c#3", Less); test_sqrt_pi_prec_round_helper(4, Floor, "1.8", "0x1.c#4", Less); test_sqrt_pi_prec_round_helper(4, Ceiling, "1.9", "0x1.e#4", Greater); test_sqrt_pi_prec_round_helper(4, Down, "1.8", "0x1.c#4", Less); test_sqrt_pi_prec_round_helper(4, Up, "1.9", "0x1.e#4", Greater); test_sqrt_pi_prec_round_helper(4, Nearest, "1.8", "0x1.c#4", Less); test_sqrt_pi_prec_round_helper(5, Floor, "1.75", "0x1.c#5", Less); test_sqrt_pi_prec_round_helper(5, Ceiling, "1.81", "0x1.d#5", Greater); test_sqrt_pi_prec_round_helper(5, Down, "1.75", "0x1.c#5", Less); test_sqrt_pi_prec_round_helper(5, Up, "1.81", "0x1.d#5", Greater); test_sqrt_pi_prec_round_helper(5, Nearest, "1.75", "0x1.c#5", Less); test_sqrt_pi_prec_round_helper(6, Floor, "1.75", "0x1.c0#6", Less); test_sqrt_pi_prec_round_helper(6, Ceiling, "1.78", "0x1.c8#6", Greater); test_sqrt_pi_prec_round_helper(6, Down, "1.75", "0x1.c0#6", Less); test_sqrt_pi_prec_round_helper(6, Up, "1.78", "0x1.c8#6", Greater); test_sqrt_pi_prec_round_helper(6, Nearest, "1.78", "0x1.c8#6", Greater); test_sqrt_pi_prec_round_helper(7, Floor, "1.77", "0x1.c4#7", Less); test_sqrt_pi_prec_round_helper(7, Ceiling, "1.78", "0x1.c8#7", Greater); test_sqrt_pi_prec_round_helper(7, Down, "1.77", "0x1.c4#7", Less); test_sqrt_pi_prec_round_helper(7, Up, "1.78", "0x1.c8#7", Greater); test_sqrt_pi_prec_round_helper(7, Nearest, "1.77", "0x1.c4#7", Less); test_sqrt_pi_prec_round_helper(8, Floor, "1.766", "0x1.c4#8", Less); test_sqrt_pi_prec_round_helper(8, Ceiling, "1.773", "0x1.c6#8", Greater); test_sqrt_pi_prec_round_helper(8, Down, "1.766", "0x1.c4#8", Less); test_sqrt_pi_prec_round_helper(8, Up, "1.773", "0x1.c6#8", Greater); test_sqrt_pi_prec_round_helper(8, Nearest, "1.773", "0x1.c6#8", Greater); test_sqrt_pi_prec_round_helper(9, Floor, "1.77", "0x1.c5#9", Less); test_sqrt_pi_prec_round_helper(9, Ceiling, "1.773", "0x1.c6#9", Greater); test_sqrt_pi_prec_round_helper(9, Down, "1.77", "0x1.c5#9", Less); test_sqrt_pi_prec_round_helper(9, Up, "1.773", "0x1.c6#9", Greater); test_sqrt_pi_prec_round_helper(9, Nearest, "1.773", "0x1.c6#9", Greater); test_sqrt_pi_prec_round_helper(10, Floor, "1.771", "0x1.c58#10", Less); test_sqrt_pi_prec_round_helper(10, Ceiling, "1.773", "0x1.c60#10", Greater); test_sqrt_pi_prec_round_helper(10, Down, "1.771", "0x1.c58#10", Less); test_sqrt_pi_prec_round_helper(10, Up, "1.773", "0x1.c60#10", Greater); test_sqrt_pi_prec_round_helper(10, Nearest, "1.771", "0x1.c58#10", Less); test_sqrt_pi_prec_round_helper( 100, Floor, "1.77245385090551602729816748334", "0x1.c5bf891b4ef6aa79c3b0520d4#100", Less, ); test_sqrt_pi_prec_round_helper( 100, Ceiling, "1.772453850905516027298167483341", "0x1.c5bf891b4ef6aa79c3b0520d6#100", Greater, ); test_sqrt_pi_prec_round_helper( 100, Down, "1.77245385090551602729816748334", "0x1.c5bf891b4ef6aa79c3b0520d4#100", Less, ); test_sqrt_pi_prec_round_helper( 100, Up, "1.772453850905516027298167483341", "0x1.c5bf891b4ef6aa79c3b0520d6#100", Greater, ); test_sqrt_pi_prec_round_helper( 100, Nearest, "1.772453850905516027298167483341", "0x1.c5bf891b4ef6aa79c3b0520d6#100", Greater, ); } #[test] #[should_panic] fn sqrt_pi_prec_round_fail_1() { Float::sqrt_pi_prec_round(0, Floor); } #[test] #[should_panic] fn sqrt_pi_prec_round_fail_2() { Float::sqrt_pi_prec_round(1, Exact); } #[test] #[should_panic] fn sqrt_pi_prec_round_fail_3() { Float::sqrt_pi_prec_round(1000, Exact); } #[test] fn sqrt_pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (sqrt_pi, o) = Float::sqrt_pi_prec(prec); assert!(sqrt_pi.is_valid()); assert_eq!(sqrt_pi.get_prec(), Some(prec)); assert_eq!(sqrt_pi.get_exponent(), Some(if prec <= 2 { 2 } else { 1 })); assert_ne!(o, Equal); if o == Less { let (sqrt_pi_alt, o_alt) = Float::sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_pi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_pi.is_power_of_2() { let (sqrt_pi_alt, o_alt) = Float::sqrt_pi_prec_round(prec, Floor); let mut next_lower = sqrt_pi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_pi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (sqrt_pi_alt, o_alt) = Float::sqrt_pi_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&sqrt_pi_alt), ComparableFloatRef(&sqrt_pi) ); assert_eq!(o_alt, o); let (sqrt_pi_alt, o_alt) = sqrt_pi_prec_round_simple(prec, Nearest); assert_eq!( ComparableFloatRef(&sqrt_pi_alt), ComparableFloatRef(&sqrt_pi) ); assert_eq!(o_alt, o); }); } #[test] fn sqrt_pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (sqrt_pi, o) = Float::sqrt_pi_prec_round(prec, rm); assert!(sqrt_pi.is_valid()); assert_eq!(sqrt_pi.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1 | 2, Ceiling | Up | Nearest) | (3, Ceiling | Up) => 2, _ => 1, }; assert_eq!(sqrt_pi.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (sqrt_pi_alt, o_alt) = Float::sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(sqrt_pi_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !sqrt_pi.is_power_of_2() { let (sqrt_pi_alt, o_alt) = Float::sqrt_pi_prec_round(prec, Floor); let mut next_lower = sqrt_pi.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(sqrt_pi_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (sqrt_pi_alt, o_alt) = sqrt_pi_prec_round_simple(prec, rm); assert_eq!( ComparableFloatRef(&sqrt_pi_alt), ComparableFloatRef(&sqrt_pi) ); assert_eq!(o_alt, o); }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::sqrt_pi_prec_round(prec, Exact)); }); test_constant(Float::sqrt_pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/tau.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::Tau; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_tau_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::tau_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_tau_prec() { test_tau_prec_helper(1, "8.0", "0x8.0#1", Greater); test_tau_prec_helper(2, "6.0", "0x6.0#2", Less); test_tau_prec_helper(3, "6.0", "0x6.0#3", Less); test_tau_prec_helper(4, "6.5", "0x6.8#4", Greater); test_tau_prec_helper(5, "6.2", "0x6.4#5", Less); test_tau_prec_helper(6, "6.2", "0x6.4#6", Less); test_tau_prec_helper(7, "6.3", "0x6.5#7", Greater); test_tau_prec_helper(8, "6.28", "0x6.48#8", Less); test_tau_prec_helper(9, "6.28", "0x6.48#9", Less); test_tau_prec_helper(10, "6.28", "0x6.48#10", Less); test_tau_prec_helper( 100, "6.283185307179586476925286766559", "0x6.487ed5110b4611a62633145c0#100", Less, ); test_tau_prec_helper( 1000, "6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069\ 650684234135964296173026564613294187689219101164463450718816256962234900568205403877042211\ 119289245897909860763928857621951331866892256951296467573566330542403818291297133846920697\ 220908653296426787214520498282547", "0x6.487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8c\ d9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6\ f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e0#1000", Less, ); test_tau_prec_helper( 10000, "6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069\ 650684234135964296173026564613294187689219101164463450718816256962234900568205403877042211\ 119289245897909860763928857621951331866892256951296467573566330542403818291297133846920697\ 220908653296426787214520498282547449174013212631176349763041841925658508183430728735785180\ 720022661061097640933042768293903883023218866114540731519183906184372234763865223586210237\ 096148924759925499134703771505449782455876366023898259667346724881313286172042789892790449\ 474381404359721887405541078434352586353504769349636935338810264001136254290527121655571542\ 685515579218347274357442936881802449906860293099170742101584559378517847084039912224258043\ 921728068836319627259549542619921037414422699999996745956099902119463465632192637190048918\ 910693816605285044616506689370070523862376342020006275677505773175066416762841234355338294\ 607196506980857510937462319125727764707575187503915563715561064342453613226003855753222391\ 818432840397876190514402130971726557731872306763655936460603904070603705937991547245198827\ 782499443550566958263031149714484908301391901659066233723455711778150196763509274929878638\ 510120801855403342278019697648025716723207127415320209420363885911192397893535674898896510\ 759549453694208095069292416093368518138982586627354057978304209504324113932048116076300387\ 022506764860071175280494992946527828398545208539845593564709563272018683443282439849172630\ 060572365949111413499677010989177173853991381854421595018605910642330689974405511920472961\ 330998239763669595507132739614853085055725103636835149345781955545587600163294120032290498\ 384346434429544700282883947137096322722314705104266951483698936877046647814788286669095524\ 833725037967138971124198438444368545100508513775343580989203306933609977254465583572171568\ 767655935953362908201907767572721901360128450250410234785969792168256977253891208483930570\ 044421322372613488557244078389890094247427573921912728743834574935529315147924827781731665\ 291991626780956055180198931528157902538936796705191419651645241044978815453438956536965202\ 953981805280272788874910610136406992504903498799302862859618381318501874443392923031419716\ 774821195771919545950997860323507856936276537367737885548311983711850491907918862099945049\ 361691974547289391697307673472445252198249216102487768780902488273099525561595431382871995\ 400259232178883389737111696812706844144451656977296316912057012033685478904534935357790504\ 277045099909333455647972913192232709772461154912996071187269136348648225030152138958902193\ 192188050457759421786291338273734457497881120203006617235857361841749521835649877178019429\ 819351970522731099563786259569643365997897445317609715128028540955110264759282903047492468\ 729085716889590531735642102282709471479046226854332204271939072462885904969874374220291530\ 807180559868807484014621157078124396774895616956979366642891427737503887012860436906382096\ 962010741229361349838556382395879904122839326857508881287490247436384359996782031839123629\ 3502853824794978818143729884639231358904161", "0x6.487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8c\ d9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6\ f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e\ 9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be1948\ 2f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5\ 728ae9130c4c7d02880ab9472d45556216d6998b8682283d19d42a90d5ef8e5d32767dc2822c6df785457538ab\ ae83063ed9cb87c2d370f263d5fad7466d8499eb8f464a702512b0cee771e9130d697735f897fd036cc504326c\ 3b01399f643532290f958c0bbd90065df08babbd30aeb63b84c4605d6ca371047127d03a72d598a1edadfe707e\ 884725c16890549084008d391e0953c3f36bc438cd085edd2d934ce1938c357a711e0d4a341a5b0a85ed12c1f4\ e5156a26746ddde16d826f477c97477e0a0fdf6553143e2ca3a735e02eccd94b27d04861d1119dd0c328adf3f6\ 8fb094b867716bd7dc0deebb10b8240e68034893ead82d54c9da754c46c7eee0c37fdbee48536047a6fa1ae49a\ 0142491b61fd5a693e381360ea6e593013236f64ba8f3b1edd1bdefc7fca0356cf298772ed9c17a09800d75835\ 29f6c813ec188bcb93d8432d448c6d1f6df5e7cd8a76a267365d676a5d8dedbf8a23f36612a5999028a895ebd7\ a137dc7a009bc6695facc1e500e325c9767819750ae8b90e81fa416be7373a7f7b6aaf3817a34c06415ad42018\ c8058e4f2cf3e4bfdf63f47991d4bd3f1b66445f078ea2dbffac2d62a5ea03d915a0aa556647b6bf5fa470ec0a\ 662f6907c01bf053cb8af7794df1940350eac5dbe2ed3b7aa8551ec50fdff8758ce658d189eaae6d2b64f61779\ 4b191c3ff46bb71e0234021f47b31fa43077095f96ad85ba3a6b734a7c8f36df08acba51c937897f72f21c3bbe\ 5b54996fc66c5f626839dc98dd1de4195b46cee9803a0fd3dfc57e23f692bb7b49b5d212331d55b1ce2d727ab4\ 1a11da3a15f8e4bc11c78b65f1ceb296f1fedc5f7e42456c911117025201be0389f5abd40d11f8639a39fe3236\ 751835a5e5e44317c1c2eefd4ea5bfd16043f43cb41981f6adee9d03159e7ad9d13c53369509fc1fa27c16ef98\ 87703a55b51b22cbf44cd012aee0b2798e628423428efcd5a40caef6bf50d8ea885ebf73a6b9fd79b5e18f67d1\ 341ac8237a75c3cfc92004a1c5a40e366bc44d00176af71c15e48c86d37e013723caac7223ab3bf4d54f182871\ 3b2b4a6fe40fab74405cb738b064c06ecc52b9f52239032d09ce69483668e5b94f629529436a200a534a6522ba\ c1eae7f79378dc856c148ed03cce8001174df6aae37d23fe52dd8d6541bb22b6cc6ca43cf73f36dfe680a5d8b0\ aacc8a7605abb533f1f4211748f32dd0a0ed496f4e1d36b665289b6ea125d88324c475add4d60934fbefb39dcc\ 1711fdb64cdd95518e2d3342ffeacc8a4d985633dc2326c054aea12985340b22681c830747c7ea93134b6853ac\ ad71fc9ad33ee7fad43a5380fdfd061ea9a5a71cde04abb8299ba410d08e1d64cc705d38c043d98bc12d0d67e7\ d75df92792e3028d6d4e142d0fe6b08a541c50d6f38a60b54a00e6e7c0f0838ffbd5cb91cf8#10000", Less, ); let tau_f32 = Float::tau_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(tau_f32.to_string(), "6.2831855"); assert_eq!(to_hex_string(&tau_f32), "0x6.487ed8#24"); assert_eq!(tau_f32, f32::TAU); let tau_f64 = Float::tau_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(tau_f64.to_string(), "6.283185307179586"); assert_eq!(to_hex_string(&tau_f64), "0x6.487ed5110b460#53"); assert_eq!(tau_f64, f64::TAU); } #[test] #[should_panic] fn tau_prec_fail_1() { Float::tau_prec(0); } fn test_tau_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::tau_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_tau_prec_round() { test_tau_prec_round_helper(1, Floor, "4.0", "0x4.0#1", Less); test_tau_prec_round_helper(1, Ceiling, "8.0", "0x8.0#1", Greater); test_tau_prec_round_helper(1, Down, "4.0", "0x4.0#1", Less); test_tau_prec_round_helper(1, Up, "8.0", "0x8.0#1", Greater); test_tau_prec_round_helper(1, Nearest, "8.0", "0x8.0#1", Greater); test_tau_prec_round_helper(2, Floor, "6.0", "0x6.0#2", Less); test_tau_prec_round_helper(2, Ceiling, "8.0", "0x8.0#2", Greater); test_tau_prec_round_helper(2, Down, "6.0", "0x6.0#2", Less); test_tau_prec_round_helper(2, Up, "8.0", "0x8.0#2", Greater); test_tau_prec_round_helper(2, Nearest, "6.0", "0x6.0#2", Less); test_tau_prec_round_helper(3, Floor, "6.0", "0x6.0#3", Less); test_tau_prec_round_helper(3, Ceiling, "7.0", "0x7.0#3", Greater); test_tau_prec_round_helper(3, Down, "6.0", "0x6.0#3", Less); test_tau_prec_round_helper(3, Up, "7.0", "0x7.0#3", Greater); test_tau_prec_round_helper(3, Nearest, "6.0", "0x6.0#3", Less); test_tau_prec_round_helper(4, Floor, "6.0", "0x6.0#4", Less); test_tau_prec_round_helper(4, Ceiling, "6.5", "0x6.8#4", Greater); test_tau_prec_round_helper(4, Down, "6.0", "0x6.0#4", Less); test_tau_prec_round_helper(4, Up, "6.5", "0x6.8#4", Greater); test_tau_prec_round_helper(4, Nearest, "6.5", "0x6.8#4", Greater); test_tau_prec_round_helper(5, Floor, "6.2", "0x6.4#5", Less); test_tau_prec_round_helper(5, Ceiling, "6.5", "0x6.8#5", Greater); test_tau_prec_round_helper(5, Down, "6.2", "0x6.4#5", Less); test_tau_prec_round_helper(5, Up, "6.5", "0x6.8#5", Greater); test_tau_prec_round_helper(5, Nearest, "6.2", "0x6.4#5", Less); test_tau_prec_round_helper(6, Floor, "6.2", "0x6.4#6", Less); test_tau_prec_round_helper(6, Ceiling, "6.4", "0x6.6#6", Greater); test_tau_prec_round_helper(6, Down, "6.2", "0x6.4#6", Less); test_tau_prec_round_helper(6, Up, "6.4", "0x6.6#6", Greater); test_tau_prec_round_helper(6, Nearest, "6.2", "0x6.4#6", Less); test_tau_prec_round_helper(7, Floor, "6.25", "0x6.4#7", Less); test_tau_prec_round_helper(7, Ceiling, "6.3", "0x6.5#7", Greater); test_tau_prec_round_helper(7, Down, "6.25", "0x6.4#7", Less); test_tau_prec_round_helper(7, Up, "6.3", "0x6.5#7", Greater); test_tau_prec_round_helper(7, Nearest, "6.3", "0x6.5#7", Greater); test_tau_prec_round_helper(8, Floor, "6.28", "0x6.48#8", Less); test_tau_prec_round_helper(8, Ceiling, "6.31", "0x6.50#8", Greater); test_tau_prec_round_helper(8, Down, "6.28", "0x6.48#8", Less); test_tau_prec_round_helper(8, Up, "6.31", "0x6.50#8", Greater); test_tau_prec_round_helper(8, Nearest, "6.28", "0x6.48#8", Less); test_tau_prec_round_helper(9, Floor, "6.28", "0x6.48#9", Less); test_tau_prec_round_helper(9, Ceiling, "6.3", "0x6.4c#9", Greater); test_tau_prec_round_helper(9, Down, "6.28", "0x6.48#9", Less); test_tau_prec_round_helper(9, Up, "6.3", "0x6.4c#9", Greater); test_tau_prec_round_helper(9, Nearest, "6.28", "0x6.48#9", Less); test_tau_prec_round_helper(10, Floor, "6.28", "0x6.48#10", Less); test_tau_prec_round_helper(10, Ceiling, "6.29", "0x6.4a#10", Greater); test_tau_prec_round_helper(10, Down, "6.28", "0x6.48#10", Less); test_tau_prec_round_helper(10, Up, "6.29", "0x6.4a#10", Greater); test_tau_prec_round_helper(10, Nearest, "6.28", "0x6.48#10", Less); test_tau_prec_round_helper( 100, Floor, "6.283185307179586476925286766559", "0x6.487ed5110b4611a62633145c0#100", Less, ); test_tau_prec_round_helper( 100, Ceiling, "6.283185307179586476925286766565", "0x6.487ed5110b4611a62633145c8#100", Greater, ); test_tau_prec_round_helper( 100, Down, "6.283185307179586476925286766559", "0x6.487ed5110b4611a62633145c0#100", Less, ); test_tau_prec_round_helper( 100, Up, "6.283185307179586476925286766565", "0x6.487ed5110b4611a62633145c8#100", Greater, ); test_tau_prec_round_helper( 100, Nearest, "6.283185307179586476925286766559", "0x6.487ed5110b4611a62633145c0#100", Less, ); } #[test] #[should_panic] fn tau_prec_round_fail_1() { Float::tau_prec_round(0, Floor); } #[test] #[should_panic] fn tau_prec_round_fail_2() { Float::tau_prec_round(1, Exact); } #[test] #[should_panic] fn tau_prec_round_fail_3() { Float::tau_prec_round(1000, Exact); } #[test] fn tau_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (tau, o) = Float::tau_prec(prec); assert!(tau.is_valid()); assert_eq!(tau.get_prec(), Some(prec)); assert_eq!(tau.get_exponent(), Some(if prec == 1 { 4 } else { 3 })); assert_ne!(o, Equal); if o == Less { let (tau_alt, o_alt) = Float::tau_prec_round(prec, Ceiling); let mut next_upper = tau.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(tau_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !tau.is_power_of_2() { let (tau_alt, o_alt) = Float::tau_prec_round(prec, Floor); let mut next_lower = tau.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(tau_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } let (tau_alt, o_alt) = Float::tau_prec_round(prec, Nearest); assert_eq!(ComparableFloatRef(&tau_alt), ComparableFloatRef(&tau)); assert_eq!(o_alt, o); }); } #[test] fn tau_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (tau, o) = Float::tau_prec_round(prec, rm); assert!(tau.is_valid()); assert_eq!(tau.get_prec(), Some(prec)); let expected_exponent = match (prec, rm) { (1, Ceiling | Up | Nearest) | (2, Ceiling | Up) => 4, _ => 3, }; assert_eq!(tau.get_exponent(), Some(expected_exponent)); assert_ne!(o, Equal); if o == Less { let (tau_alt, o_alt) = Float::tau_prec_round(prec, Ceiling); let mut next_upper = tau.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!(ComparableFloat(tau_alt), ComparableFloat(next_upper)); assert_eq!(o_alt, Greater); } } else if !tau.is_power_of_2() { let (tau_alt, o_alt) = Float::tau_prec_round(prec, Floor); let mut next_lower = tau.clone(); next_lower.decrement(); assert_eq!(ComparableFloat(tau_alt), ComparableFloat(next_lower)); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::tau_prec_round(prec, Exact)); }); test_constant(Float::tau_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/two_over_pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::TwoOverPi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_two_over_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::two_over_pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_two_over_pi_prec() { test_two_over_pi_prec_helper(1, "0.5", "0x0.8#1", Less); test_two_over_pi_prec_helper(2, "0.8", "0x0.c#2", Greater); test_two_over_pi_prec_helper(3, "0.6", "0x0.a#3", Less); test_two_over_pi_prec_helper(4, "0.62", "0x0.a#4", Less); test_two_over_pi_prec_helper(5, "0.62", "0x0.a0#5", Less); test_two_over_pi_prec_helper(6, "0.64", "0x0.a4#6", Greater); test_two_over_pi_prec_helper(7, "0.63", "0x0.a2#7", Less); test_two_over_pi_prec_helper(8, "0.637", "0x0.a3#8", Greater); test_two_over_pi_prec_helper(9, "0.637", "0x0.a30#9", Greater); test_two_over_pi_prec_helper(10, "0.637", "0x0.a30#10", Greater); test_two_over_pi_prec_helper( 100, "0.63661977236758134307553505349", "0x0.a2f9836e4e441529fc2757d1f#100", Less, ); test_two_over_pi_prec_helper( 1000, "0.636619772367581343075535053490057448137838582961825794990669376235587190536906140360455\ 211065012343824291370907031832147571647384458314611511869642926799356916959867749636310292\ 310985587701230754869571584869590646773449560966894516047329520456890799022863761847560347\ 6106958244819576437477513763421149", "0x0.a2f9836e4e441529fc2757d1f534ddc0db6295993c439041fe5163abdebbc561b7246e3a424dd2e006492\ eea09d1921cfe1deb1cb129a73ee88235f52ebb4484e99c7026b45f7e413991d639835339f49c845f8bbdf9283\ b1ff897ffde05980fef2f118b5a0a6d1f6d367ecf27cb09b74f463f669e5fea2d7527bac7ec#1000", Greater, ); test_two_over_pi_prec_helper( 10000, "0.636619772367581343075535053490057448137838582961825794990669376235587190536906140360455\ 211065012343824291370907031832147571647384458314611511869642926799356916959867749636310292\ 310985587701230754869571584869590646773449560966894516047329520456890799022863761847560347\ 610695824481957643747751376342114892399785773600994689390957838443593292387132299624667945\ 851218797794608751526299146267856964155983496557394439935472396799849771502340684715433724\ 470075068642186190147952038957841459037335072237209977986541221308627102012881299111265588\ 664091786992478392663362424067212143992535647949995331146617741119020280064962710257555398\ 285243520488797504590725511058951562532272185831913927045249709256279843100098001191039428\ 356227611187140526100840065270984083699246424962245824812585936356993836765740846301630224\ 803486106427208868636563029898330890390985141599500621317563255927089637433019188293314876\ 162799903630630831397388157435931234869370256146758046650182823773310525074600104490871884\ 612845039801754671780150502243345268467810390325128997664933372580424494147514252454546768\ 668568278987840517002313344212478434378039358226874839818986041726495262070323357771919883\ 998021017550264517783533227384203141166060564161957195402555264310478797229364155998314767\ 562392374951088247501728908757205465021044955121550155524427256270617363313114107733707198\ 224283161544241410955984980503982997105188094376382337204659318564742310849623017797828087\ 159079169637961309179080866598414261272614176015362759498870766355052763866027857619107882\ 750734627112419119181801413583033207527354751751064499259812239862320876334395004140508516\ 172926321994878747511037862653848841368177634219914015170954777174146477511317149437513738\ 812920948583351694228474545367717840732729167856660035132317325413991163989834597161069802\ 439574756378353220134812215221892492863237727907041291325256759238999289753340697427959390\ 004158002735520159146894398432096010956043499819419151694273044559795613075989708333984459\ 683315615107138972142018273824334685917233826893308141941570224808347357296398248847013273\ 576083883174283099861995234744265443874647868149898168411324877007384899339964644598266224\ 151878704559725131984310433111960403132144009353091951634160955046229781723704047640217351\ 993556186196849931806428291412020908840944070093252692719037244201312620437495654558581223\ 170428720334471819506898583921895909169792436803748503147673331583545135961743474666559026\ 937805638014549308766972455522655322903692110389380242192851112148261351132128683950939866\ 273963201307954026967165858734033126467413257344642923980599412479278935033776839366623816\ 609002573577251457761535534246035190865800682588270075098242366434867431431756904939025326\ 844531994623766387562879402754976920230076790822760152873570248813549694145027233416626069\ 188435246887183747330259540749998994834212466393224405568578178406459538110810045644280994\ 086958980415466945615491440398699572694247248284696191559747554622769231394009222822857625\ 45545280947408042964022994369124462887872014", "0x0.a2f9836e4e441529fc2757d1f534ddc0db6295993c439041fe5163abdebbc561b7246e3a424dd2e006492\ eea09d1921cfe1deb1cb129a73ee88235f52ebb4484e99c7026b45f7e413991d639835339f49c845f8bbdf9283\ b1ff897ffde05980fef2f118b5a0a6d1f6d367ecf27cb09b74f463f669e5fea2d7527bac7ebe5f17b3d0739f78\ a5292ea6bfb5fb11f8d5d0856033046fc7b6babf0cfbc209af4361da9e391615ee61b086599855f14a068408df\ fd8804d73273106061556ca73a8c960e27bc08c6b47c419c367cddce8092a8359c4768b961ca6ddaf44d157190\ 53ea5ff07053f7e33e832c2de4f98327dbbc33d26ef6b1e5ef89f3a1f35caf27f1d87f121907c7c246afa6ed57\ 72d30433b15c614b59d19c3c2c4ad414d2c5d000c467d862d71e39ac69b0062337cd2b497a7b4d55537f63ed71\ 810a3fc764d2a9d64abd770f87c6357b07ae715175649c0d9d63b3884a7cb2324778ad623545ab91f001b0af1d\ fce19ff319f6a1e6661579947fbacd87f7eb7652289e83260bfe6cdc4ef09366cd43f5dd7de16de3b58929bde2\ 822d2e886284d58e232cac616e308cb7de050c017a71df35be01834132e6212830148835b8ef57fb0adf2e91e4\ 34a48d36710d8ddaa425faece616aa4280ab499d3f2a6067f775c83c2a3883c6178738a5a8cafbdd76f63a62dc\ bbff4ef818d67c12645ca5536d9cad2a8288d61c277c9121426049b4612c459c444c5c891b24df31700ad43d4e\ 5492910d5fdfcbe00cc941eeece70f53e1380f1ecc3e7b328f8c79405933e71c1b3092ef3450b9c12887b20ab9\ fb52ec292472f327b6d550c90a7721fe76b96cb314a1679e2794189dff49794e884e6e29731996bed88365f5f0\ efdbbb49a486ca467427271325d8db8159f09e5bc25318d3974f71c0530010c0d68084b58ee2c90aa4702e7742\ 4d6bda67df772486eef169fa6948ef691b45153d1f20acf3398207e4bf56863b25f3edd035d407f8985295255c\ 0643710d86d324832754c5bd4714e6e5445c1090b69f52ad566149d072750045ddb3bb4c576ea17f9877d6b49b\ a271d296996acccc65414ad6ae29089d98850722cbea4049407777030f327fc00a871ea49c2663de06483dd979\ 73fa3fd94438c860dde41319d39928c70dde7b7173bdf082b3715a0805c93805a921110d8e80faf806c4bffdb0\ f903876185915a562bbcb61b989c7bd401004f2d2277549f6b6ebbb22dbaa140a2f2689768364333b091a940ea\ a3a51c2a31daeedaf12265c4dc26d9c7a2d9756c0833f03f6f0098c402b99316d07b43915200c5bc3d8c492f54\ badc6a5ca4ecd37a736a9e69492ab6842ddde6319ef8c76528b6837dbfcaba1ae3115dfa1ae00dafb0c664d64b\ 705ed306529bf56573aff47b9f96af3be75df93283080abf68c6615cb040622fa1de4d9a4b33d8f1b5709cd36e\ 9424ea4be13b523331aaaf0a8654fa5c1d20f3f0bcd785b76f923048b7b72178953a6c6e26e6f00ebef584a9bb\ 7dac4ba66aacfcf761d02d12df1b1c1998c77adc3da4886a05df7f480c62ff0ac9aecddbc5c3f6dded01fc790b\ 6db2a3a25a39aaf009353ad0457b6b42d297e804ba707da0eaa76a1597b2a12162db7dcfde5fafedb89fdbe896\ c76e4fca90670803e156e85ff87fd073e2833676186182aeabd4dafe7b36e6d8f3967955bbf3148d78416df304\ 32dc7356125ce70c9b8cb30fd6cbfa200a4e46c05a0dd5a476f21d21262845cb9496170e056#10000", Less, ); let two_over_pi_f32 = Float::two_over_pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(two_over_pi_f32.to_string(), "0.63661975"); assert_eq!(to_hex_string(&two_over_pi_f32), "0x0.a2f983#24"); assert_eq!(two_over_pi_f32, f32::TWO_OVER_PI); let two_over_pi_f64 = Float::two_over_pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(two_over_pi_f64.to_string(), "0.6366197723675814"); assert_eq!(to_hex_string(&two_over_pi_f64), "0x0.a2f9836e4e4418#53"); assert_eq!(two_over_pi_f64, f64::TWO_OVER_PI); } #[test] #[should_panic] fn two_over_pi_prec_fail_1() { Float::two_over_pi_prec(0); } fn test_two_over_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::two_over_pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_two_over_pi_prec_round() { test_two_over_pi_prec_round_helper(1, Floor, "0.5", "0x0.8#1", Less); test_two_over_pi_prec_round_helper(1, Ceiling, "1.0", "0x1.0#1", Greater); test_two_over_pi_prec_round_helper(1, Down, "0.5", "0x0.8#1", Less); test_two_over_pi_prec_round_helper(1, Up, "1.0", "0x1.0#1", Greater); test_two_over_pi_prec_round_helper(1, Nearest, "0.5", "0x0.8#1", Less); test_two_over_pi_prec_round_helper(2, Floor, "0.5", "0x0.8#2", Less); test_two_over_pi_prec_round_helper(2, Ceiling, "0.8", "0x0.c#2", Greater); test_two_over_pi_prec_round_helper(2, Down, "0.5", "0x0.8#2", Less); test_two_over_pi_prec_round_helper(2, Up, "0.8", "0x0.c#2", Greater); test_two_over_pi_prec_round_helper(2, Nearest, "0.8", "0x0.c#2", Greater); test_two_over_pi_prec_round_helper(3, Floor, "0.6", "0x0.a#3", Less); test_two_over_pi_prec_round_helper(3, Ceiling, "0.8", "0x0.c#3", Greater); test_two_over_pi_prec_round_helper(3, Down, "0.6", "0x0.a#3", Less); test_two_over_pi_prec_round_helper(3, Up, "0.8", "0x0.c#3", Greater); test_two_over_pi_prec_round_helper(3, Nearest, "0.6", "0x0.a#3", Less); test_two_over_pi_prec_round_helper(4, Floor, "0.62", "0x0.a#4", Less); test_two_over_pi_prec_round_helper(4, Ceiling, "0.7", "0x0.b#4", Greater); test_two_over_pi_prec_round_helper(4, Down, "0.62", "0x0.a#4", Less); test_two_over_pi_prec_round_helper(4, Up, "0.7", "0x0.b#4", Greater); test_two_over_pi_prec_round_helper(4, Nearest, "0.62", "0x0.a#4", Less); test_two_over_pi_prec_round_helper(5, Floor, "0.62", "0x0.a0#5", Less); test_two_over_pi_prec_round_helper(5, Ceiling, "0.66", "0x0.a8#5", Greater); test_two_over_pi_prec_round_helper(5, Down, "0.62", "0x0.a0#5", Less); test_two_over_pi_prec_round_helper(5, Up, "0.66", "0x0.a8#5", Greater); test_two_over_pi_prec_round_helper(5, Nearest, "0.62", "0x0.a0#5", Less); test_two_over_pi_prec_round_helper(6, Floor, "0.62", "0x0.a0#6", Less); test_two_over_pi_prec_round_helper(6, Ceiling, "0.64", "0x0.a4#6", Greater); test_two_over_pi_prec_round_helper(6, Down, "0.62", "0x0.a0#6", Less); test_two_over_pi_prec_round_helper(6, Up, "0.64", "0x0.a4#6", Greater); test_two_over_pi_prec_round_helper(6, Nearest, "0.64", "0x0.a4#6", Greater); test_two_over_pi_prec_round_helper(7, Floor, "0.63", "0x0.a2#7", Less); test_two_over_pi_prec_round_helper(7, Ceiling, "0.64", "0x0.a4#7", Greater); test_two_over_pi_prec_round_helper(7, Down, "0.63", "0x0.a2#7", Less); test_two_over_pi_prec_round_helper(7, Up, "0.64", "0x0.a4#7", Greater); test_two_over_pi_prec_round_helper(7, Nearest, "0.63", "0x0.a2#7", Less); test_two_over_pi_prec_round_helper(8, Floor, "0.633", "0x0.a2#8", Less); test_two_over_pi_prec_round_helper(8, Ceiling, "0.637", "0x0.a3#8", Greater); test_two_over_pi_prec_round_helper(8, Down, "0.633", "0x0.a2#8", Less); test_two_over_pi_prec_round_helper(8, Up, "0.637", "0x0.a3#8", Greater); test_two_over_pi_prec_round_helper(8, Nearest, "0.637", "0x0.a3#8", Greater); test_two_over_pi_prec_round_helper(9, Floor, "0.635", "0x0.a28#9", Less); test_two_over_pi_prec_round_helper(9, Ceiling, "0.637", "0x0.a30#9", Greater); test_two_over_pi_prec_round_helper(9, Down, "0.635", "0x0.a28#9", Less); test_two_over_pi_prec_round_helper(9, Up, "0.637", "0x0.a30#9", Greater); test_two_over_pi_prec_round_helper(9, Nearest, "0.637", "0x0.a30#9", Greater); test_two_over_pi_prec_round_helper(10, Floor, "0.636", "0x0.a2c#10", Less); test_two_over_pi_prec_round_helper(10, Ceiling, "0.637", "0x0.a30#10", Greater); test_two_over_pi_prec_round_helper(10, Down, "0.636", "0x0.a2c#10", Less); test_two_over_pi_prec_round_helper(10, Up, "0.637", "0x0.a30#10", Greater); test_two_over_pi_prec_round_helper(10, Nearest, "0.637", "0x0.a30#10", Greater); test_two_over_pi_prec_round_helper( 100, Floor, "0.63661977236758134307553505349", "0x0.a2f9836e4e441529fc2757d1f#100", Less, ); test_two_over_pi_prec_round_helper( 100, Ceiling, "0.6366197723675813430755350534906", "0x0.a2f9836e4e441529fc2757d20#100", Greater, ); test_two_over_pi_prec_round_helper( 100, Down, "0.63661977236758134307553505349", "0x0.a2f9836e4e441529fc2757d1f#100", Less, ); test_two_over_pi_prec_round_helper( 100, Up, "0.6366197723675813430755350534906", "0x0.a2f9836e4e441529fc2757d20#100", Greater, ); test_two_over_pi_prec_round_helper( 100, Nearest, "0.63661977236758134307553505349", "0x0.a2f9836e4e441529fc2757d1f#100", Less, ); } #[test] #[should_panic] fn two_over_pi_prec_round_fail_1() { Float::two_over_pi_prec_round(0, Floor); } #[test] #[should_panic] fn two_over_pi_prec_round_fail_2() { Float::two_over_pi_prec_round(1, Exact); } #[test] #[should_panic] fn two_over_pi_prec_round_fail_3() { Float::two_over_pi_prec_round(1000, Exact); } #[test] fn two_over_pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (two_over_pi, o) = Float::two_over_pi_prec(prec); assert!(two_over_pi.is_valid()); assert_eq!(two_over_pi.get_prec(), Some(prec)); assert_eq!(two_over_pi.get_exponent(), Some(0)); assert_ne!(o, Equal); if o == Less { let (two_over_pi_alt, o_alt) = Float::two_over_pi_prec_round(prec, Ceiling); let mut next_upper = two_over_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(two_over_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !two_over_pi.is_power_of_2() { let (two_over_pi_alt, o_alt) = Float::two_over_pi_prec_round(prec, Floor); let mut next_lower = two_over_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(two_over_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (two_over_pi_alt, o_alt) = Float::two_over_pi_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&two_over_pi_alt), ComparableFloatRef(&two_over_pi) ); assert_eq!(o_alt, o); }); } #[test] fn two_over_pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (two_over_pi, o) = Float::two_over_pi_prec_round(prec, rm); assert!(two_over_pi.is_valid()); assert_eq!(two_over_pi.get_prec(), Some(prec)); assert_eq!( two_over_pi.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 1 } else { 0 }) ); assert_ne!(o, Equal); if o == Less { let (two_over_pi_alt, o_alt) = Float::two_over_pi_prec_round(prec, Ceiling); let mut next_upper = two_over_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(two_over_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !two_over_pi.is_power_of_2() { let (two_over_pi_alt, o_alt) = Float::two_over_pi_prec_round(prec, Floor); let mut next_lower = two_over_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(two_over_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::two_over_pi_prec_round(prec, Exact)); }); test_constant(Float::two_over_pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/constants/two_over_sqrt_pi.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::traits::TwoOverSqrtPi; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_rounding_mode_pair_gen_var_4, }; use malachite_float::test_util::common::{test_constant, to_hex_string}; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; fn test_two_over_sqrt_pi_prec_helper(prec: u64, out: &str, out_hex: &str, out_o: Ordering) { let (x, o) = Float::two_over_sqrt_pi_prec(prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_two_over_sqrt_pi_prec() { test_two_over_sqrt_pi_prec_helper(1, "1.0", "0x1.0#1", Less); test_two_over_sqrt_pi_prec_helper(2, "1.0", "0x1.0#2", Less); test_two_over_sqrt_pi_prec_helper(3, "1.2", "0x1.4#3", Greater); test_two_over_sqrt_pi_prec_helper(4, "1.1", "0x1.2#4", Less); test_two_over_sqrt_pi_prec_helper(5, "1.12", "0x1.2#5", Less); test_two_over_sqrt_pi_prec_helper(6, "1.12", "0x1.20#6", Less); test_two_over_sqrt_pi_prec_helper(7, "1.12", "0x1.20#7", Less); test_two_over_sqrt_pi_prec_helper(8, "1.125", "0x1.20#8", Less); test_two_over_sqrt_pi_prec_helper(9, "1.129", "0x1.21#9", Greater); test_two_over_sqrt_pi_prec_helper(10, "1.129", "0x1.210#10", Greater); test_two_over_sqrt_pi_prec_helper( 100, "1.128379167095512573896158903122", "0x1.20dd750429b6d11ae3a914fee#100", Greater, ); test_two_over_sqrt_pi_prec_helper( 1000, "1.128379167095512573896158903121545171688101258657997713688171443421284936882986828973487\ 320404214726886056695812723414703379862989652325732730979040035537986585675274119196879520\ 704928700435945142423160491545640441109017054346433244416926616222799025526908972046136475\ 3818374903174932317026021327967155", "0x1.20dd750429b6d11ae3a914fed7fd8688281341d7587cea2e7342b06199cc416180eb39f0b24e1e2281806\ c12d98f35d77a3e9ddc91c394f0e9eedf0efffd84a2a4ac3b98489b8cbd3845e8fef6ff6af92a45e5f27c2d654\ 7a4f46505b5b4e62dd73fd6486de5e4e5585911777503638ea0ea96813d29a65a31a7d235ba#1000", Greater, ); test_two_over_sqrt_pi_prec_helper( 10000, "1.128379167095512573896158903121545171688101258657997713688171443421284936882986828973487\ 320404214726886056695812723414703379862989652325732730979040035537986585675274119196879520\ 704928700435945142423160491545640441109017054346433244416926616222799025526908972046136475\ 381837490317493231702602132796715543998754668320715597752333488152466078760432701203287243\ 392470100916625063893758913312576651631043248869097731406379754861763556365896778950217001\ 836917068443263565178670503666024049245124447449894540067794862528599318852700856608980726\ 631607875391971216318675658441114765847576463158466211523929554936506180343123616119044459\ 235264930718080170688589725005789478432836238548619548451139757591558099749638273874479384\ 145721266849535939897219177526087267452911757503086161868839476966576982758350723791327018\ 482697850617660789930811682114508296549646950349484018793976683355429771178335667478997183\ 163300275371977372408792825814573857927614754653462236857357604231049732437943817793615062\ 990240294910543518259630544244126468693514830520512369964555789973905060333899393713277246\ 184408849722866262122203479408633108870729232600533621778609544108260549664286731729420583\ 709898167677538495392748117508206316946634152433906289780994634796224277050525789933163762\ 144944610034611200146111014760538140478418650258730371308816054606091217117786637305172610\ 517669441962183230451102680326896192154681258135304184955488915831319872573827621301394798\ 442321270036762403269655890511176091794390559806184597712231091256394888644636818979096451\ 397846378693640734006412458420064879125851437050838091157673662671192611457760297346542852\ 808312236531894105842976564219243112231755769151738741538633137951466072661211616085355310\ 857774493679173076256383508892008233851964641402029759551974793310482402462041711945161548\ 326464873039374115874373991373282632741414920329349124653295705526587225112073460916295019\ 351673851763550205032343583177087022638899559022604128931488470928339695796081675002149402\ 705503760956452458569391936454552087427059271324878358397026924524406044511662789633794884\ 312566085791783949166112065856075232662140149368936155086704776086186500364186886553943513\ 209170716292378586966001695043767126312269700601051262635023004805630507146960562075511746\ 193744116099678233570896735643276617479233229464677226737161287382607246540458402419168410\ 369080032442595204449841004182771241558536904090276184130382096457426893023177519552932669\ 910328559505543058012609185253324264204948243252385345305151663497890783280043012055166242\ 868647524427377318531773354446540102614567355680535177054052252524092466096556675461869194\ 502097950414221238045052862533170581314105649117929016110826071463050044902113986948490263\ 880543969640100358021024367307867000301735766682570676407886519783729177203642562064756387\ 522705452837219505239146678435510613803649417614863894095412079053170504045514553464488107\ 056711353135654973323610571363687790680289636128613293872689308014945837435447842138998905\ 2458651564368105546071376972806302466513398", "0x1.20dd750429b6d11ae3a914fed7fd8688281341d7587cea2e7342b06199cc416180eb39f0b24e1e2281806\ c12d98f35d77a3e9ddc91c394f0e9eedf0efffd84a2a4ac3b98489b8cbd3845e8fef6ff6af92a45e5f27c2d654\ 7a4f46505b5b4e62dd73fd6486de5e4e5585911777503638ea0ea96813d29a65a31a7d235b9fed80735a739f0c\ dba12c519a4d0308fceb248f76d1a1b6642fad251a58a530d43df05fad7bc33a90c79b03bcd7729e27b629a758\ 4a30de9e46e24a71a8c3d52f6003ce62af51cbfa1129bfaf37d42219a1910d82dc1985ae3e4662f05fc75ed5e7\ 1b2bd75e97b95e80fe24ff9dc42273cac1e83311f7493092145e08d7abb2500c1067f03dfdff9363e8edcef4b8\ ac1a2da635fe6ab630cb1893bfff7e5649d7b0aae1d49c6aa3cc08ba146db963c8dfd22432b1cbc010b48c3a5c\ d3dfa2509f6be88b407d1059307b923d91ffb1db6618afd15a92a5ba06cc83afaa446091eaacf54b522f1945d1\ 91e4dacda113387974af3a343f7ce369957efdc384258530fcf9037413bb07fa3705b934bac814576820d20740\ aa64c532696cc455b79c64ad5cce5fff52d9aa114ec9ff1074edc6309a26029b70a9232e59eaaa501aa0aca4a2\ 7728273c272ec6bb3470b095b7c747a2ef9e3c620e65f0f648cc2d13a4b4302e197a71e8ecdbc01118580a1c11\ a341c7934d311d73f344b85d072c47b21e844d6b92cb6738ad4aeef5149c0f4beedcbb58ba8d1a4138068ddfc4\ afdf301a3bd5f02b99abc0cc348add7d5e09ccd55b1dac8c54e22fc24f30c8c4ce5a86e55205efb686835d5904\ a675e2c8135ba596719fbaa19ba789266db7b1ab4db36b1cb412b4d5ee13fddf1768dbc347d2a6d4c536bac90f\ fffe356c775ee06458e42d744d6a16ed51ac40e9e2033422963d77a545f8b5aee2ea3b37c23db4f504d47b986c\ a2d543ab7f158f26d46f44ba838e2cea777469249aff72afd71755af1ceac1fa7ad0c8c536ed4f2b2425458583\ 3d07df62553eb1ffffc1d0f3df7714180ace2618d12251cfea9e6a60a5ff086d8cd2d7a0f42e90b054aeadc826\ 803b731044178f676b13f2294d97b99ed318e0aa55fa0d4f2b6ab619c577093cce0852386de4f542e39dcfd5cb\ 4c8d73693cb51fccd163f7d0f8553874137d7a9d03886c41b7a347a8831e1add4f861d48e93b7bdb34a69871d4\ e8af6148204ec26c6d1a154b3331efde63e122929a6dceb7786262d41694e2ba47da460a8a6e130b982445ea0e\ 45b400ea6ea6a7044e25163551bc27945081d344524130f3f1e8d0fc0a21a5b5a2dca8624b0501a0a00737ea60\ 4328ee18c6a983887ec3a2325eaf3f288194a7ef259177ff866265e4030896fd1b5f757135db4ad9164768e3bc\ 05755d775c9466c11c1a9cd9d3805fd322c9abff54269ff248d5c01e998dacac195aa549174422e94b1775e758\ 33cc9ef905054e08c1488ba83a5f846f053cd01762f2b68f4c9978ec41a53f8ee6c5b90ed2c27e83fa68f02bca\ 516823862007222eee333565e467ceafd23310af018dd80ba829818b82c9e9625c711e87079fca694ddbd3fbbf\ 6d0113ee672fc425c1bf33fe92da8753e6b576bc07f16f5381ad615fc5d82278d2308edc3ec6853ec1c7220860\ f5d5e1d380d8a3e93c6395f420f4ad28f7da5583282ac819cdb68a6e5a6761e1ab90f8d78981c1fa1503b46dfb\ 78235f460132e2eb2877c1fca3e7a1644373b339635421e388ec3d17c19ef2417f476d13aa6#10000", Less, ); let two_over_sqrt_pi_f32 = Float::two_over_sqrt_pi_prec(u64::from(f32::MANTISSA_DIGITS)).0; assert_eq!(two_over_sqrt_pi_f32.to_string(), "1.1283792"); assert_eq!(to_hex_string(&two_over_sqrt_pi_f32), "0x1.20dd76#24"); assert_eq!(two_over_sqrt_pi_f32, f32::TWO_OVER_SQRT_PI); let two_over_sqrt_pi_f64 = Float::two_over_sqrt_pi_prec(u64::from(f64::MANTISSA_DIGITS)).0; assert_eq!(two_over_sqrt_pi_f64.to_string(), "1.1283791670955126"); assert_eq!(to_hex_string(&two_over_sqrt_pi_f64), "0x1.20dd750429b6d#53"); assert_eq!(two_over_sqrt_pi_f64, f64::TWO_OVER_SQRT_PI); } #[test] #[should_panic] fn two_over_sqrt_pi_prec_fail_1() { Float::two_over_sqrt_pi_prec(0); } fn test_two_over_sqrt_pi_prec_round_helper( prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) { let (x, o) = Float::two_over_sqrt_pi_prec_round(prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } #[test] pub fn test_two_over_sqrt_pi_prec_round() { test_two_over_sqrt_pi_prec_round_helper(1, Floor, "1.0", "0x1.0#1", Less); test_two_over_sqrt_pi_prec_round_helper(1, Ceiling, "2.0", "0x2.0#1", Greater); test_two_over_sqrt_pi_prec_round_helper(1, Down, "1.0", "0x1.0#1", Less); test_two_over_sqrt_pi_prec_round_helper(1, Up, "2.0", "0x2.0#1", Greater); test_two_over_sqrt_pi_prec_round_helper(1, Nearest, "1.0", "0x1.0#1", Less); test_two_over_sqrt_pi_prec_round_helper(2, Floor, "1.0", "0x1.0#2", Less); test_two_over_sqrt_pi_prec_round_helper(2, Ceiling, "1.5", "0x1.8#2", Greater); test_two_over_sqrt_pi_prec_round_helper(2, Down, "1.0", "0x1.0#2", Less); test_two_over_sqrt_pi_prec_round_helper(2, Up, "1.5", "0x1.8#2", Greater); test_two_over_sqrt_pi_prec_round_helper(2, Nearest, "1.0", "0x1.0#2", Less); test_two_over_sqrt_pi_prec_round_helper(3, Floor, "1.0", "0x1.0#3", Less); test_two_over_sqrt_pi_prec_round_helper(3, Ceiling, "1.2", "0x1.4#3", Greater); test_two_over_sqrt_pi_prec_round_helper(3, Down, "1.0", "0x1.0#3", Less); test_two_over_sqrt_pi_prec_round_helper(3, Up, "1.2", "0x1.4#3", Greater); test_two_over_sqrt_pi_prec_round_helper(3, Nearest, "1.2", "0x1.4#3", Greater); test_two_over_sqrt_pi_prec_round_helper(4, Floor, "1.1", "0x1.2#4", Less); test_two_over_sqrt_pi_prec_round_helper(4, Ceiling, "1.2", "0x1.4#4", Greater); test_two_over_sqrt_pi_prec_round_helper(4, Down, "1.1", "0x1.2#4", Less); test_two_over_sqrt_pi_prec_round_helper(4, Up, "1.2", "0x1.4#4", Greater); test_two_over_sqrt_pi_prec_round_helper(4, Nearest, "1.1", "0x1.2#4", Less); test_two_over_sqrt_pi_prec_round_helper(5, Floor, "1.12", "0x1.2#5", Less); test_two_over_sqrt_pi_prec_round_helper(5, Ceiling, "1.19", "0x1.3#5", Greater); test_two_over_sqrt_pi_prec_round_helper(5, Down, "1.12", "0x1.2#5", Less); test_two_over_sqrt_pi_prec_round_helper(5, Up, "1.19", "0x1.3#5", Greater); test_two_over_sqrt_pi_prec_round_helper(5, Nearest, "1.12", "0x1.2#5", Less); test_two_over_sqrt_pi_prec_round_helper(6, Floor, "1.12", "0x1.20#6", Less); test_two_over_sqrt_pi_prec_round_helper(6, Ceiling, "1.16", "0x1.28#6", Greater); test_two_over_sqrt_pi_prec_round_helper(6, Down, "1.12", "0x1.20#6", Less); test_two_over_sqrt_pi_prec_round_helper(6, Up, "1.16", "0x1.28#6", Greater); test_two_over_sqrt_pi_prec_round_helper(6, Nearest, "1.12", "0x1.20#6", Less); test_two_over_sqrt_pi_prec_round_helper(7, Floor, "1.12", "0x1.20#7", Less); test_two_over_sqrt_pi_prec_round_helper(7, Ceiling, "1.14", "0x1.24#7", Greater); test_two_over_sqrt_pi_prec_round_helper(7, Down, "1.12", "0x1.20#7", Less); test_two_over_sqrt_pi_prec_round_helper(7, Up, "1.14", "0x1.24#7", Greater); test_two_over_sqrt_pi_prec_round_helper(7, Nearest, "1.12", "0x1.20#7", Less); test_two_over_sqrt_pi_prec_round_helper(8, Floor, "1.125", "0x1.20#8", Less); test_two_over_sqrt_pi_prec_round_helper(8, Ceiling, "1.13", "0x1.22#8", Greater); test_two_over_sqrt_pi_prec_round_helper(8, Down, "1.125", "0x1.20#8", Less); test_two_over_sqrt_pi_prec_round_helper(8, Up, "1.13", "0x1.22#8", Greater); test_two_over_sqrt_pi_prec_round_helper(8, Nearest, "1.125", "0x1.20#8", Less); test_two_over_sqrt_pi_prec_round_helper(9, Floor, "1.125", "0x1.20#9", Less); test_two_over_sqrt_pi_prec_round_helper(9, Ceiling, "1.129", "0x1.21#9", Greater); test_two_over_sqrt_pi_prec_round_helper(9, Down, "1.125", "0x1.20#9", Less); test_two_over_sqrt_pi_prec_round_helper(9, Up, "1.129", "0x1.21#9", Greater); test_two_over_sqrt_pi_prec_round_helper(9, Nearest, "1.129", "0x1.21#9", Greater); test_two_over_sqrt_pi_prec_round_helper(10, Floor, "1.127", "0x1.208#10", Less); test_two_over_sqrt_pi_prec_round_helper(10, Ceiling, "1.129", "0x1.210#10", Greater); test_two_over_sqrt_pi_prec_round_helper(10, Down, "1.127", "0x1.208#10", Less); test_two_over_sqrt_pi_prec_round_helper(10, Up, "1.129", "0x1.210#10", Greater); test_two_over_sqrt_pi_prec_round_helper(10, Nearest, "1.129", "0x1.210#10", Greater); test_two_over_sqrt_pi_prec_round_helper( 100, Floor, "1.12837916709551257389615890312", "0x1.20dd750429b6d11ae3a914fec#100", Less, ); test_two_over_sqrt_pi_prec_round_helper( 100, Ceiling, "1.128379167095512573896158903122", "0x1.20dd750429b6d11ae3a914fee#100", Greater, ); test_two_over_sqrt_pi_prec_round_helper( 100, Down, "1.12837916709551257389615890312", "0x1.20dd750429b6d11ae3a914fec#100", Less, ); test_two_over_sqrt_pi_prec_round_helper( 100, Up, "1.128379167095512573896158903122", "0x1.20dd750429b6d11ae3a914fee#100", Greater, ); test_two_over_sqrt_pi_prec_round_helper( 100, Nearest, "1.128379167095512573896158903122", "0x1.20dd750429b6d11ae3a914fee#100", Greater, ); } #[test] #[should_panic] fn two_over_sqrt_pi_prec_round_fail_1() { Float::two_over_sqrt_pi_prec_round(0, Floor); } #[test] #[should_panic] fn two_over_sqrt_pi_prec_round_fail_2() { Float::two_over_sqrt_pi_prec_round(1, Exact); } #[test] #[should_panic] fn two_over_sqrt_pi_prec_round_fail_3() { Float::two_over_sqrt_pi_prec_round(1000, Exact); } #[test] fn two_over_sqrt_pi_prec_properties() { unsigned_gen_var_11().test_properties(|prec| { let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec(prec); assert!(two_over_sqrt_pi.is_valid()); assert_eq!(two_over_sqrt_pi.get_prec(), Some(prec)); assert_eq!(two_over_sqrt_pi.get_exponent(), Some(1)); assert_ne!(o, Equal); if o == Less { let (two_over_sqrt_pi_alt, o_alt) = Float::two_over_sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = two_over_sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(two_over_sqrt_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !two_over_sqrt_pi.is_power_of_2() { let (two_over_sqrt_pi_alt, o_alt) = Float::two_over_sqrt_pi_prec_round(prec, Floor); let mut next_lower = two_over_sqrt_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(two_over_sqrt_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } let (two_over_sqrt_pi_alt, o_alt) = Float::two_over_sqrt_pi_prec_round(prec, Nearest); assert_eq!( ComparableFloatRef(&two_over_sqrt_pi_alt), ComparableFloatRef(&two_over_sqrt_pi) ); assert_eq!(o_alt, o); }); } #[test] fn two_over_sqrt_pi_prec_round_properties() { unsigned_rounding_mode_pair_gen_var_4().test_properties(|(prec, rm)| { let (two_over_sqrt_pi, o) = Float::two_over_sqrt_pi_prec_round(prec, rm); assert!(two_over_sqrt_pi.is_valid()); assert_eq!(two_over_sqrt_pi.get_prec(), Some(prec)); assert_eq!( two_over_sqrt_pi.get_exponent(), Some(if prec == 1 && (rm == Ceiling || rm == Up) { 2 } else { 1 }) ); assert_ne!(o, Equal); if o == Less { let (two_over_sqrt_pi_alt, o_alt) = Float::two_over_sqrt_pi_prec_round(prec, Ceiling); let mut next_upper = two_over_sqrt_pi.clone(); next_upper.increment(); if !next_upper.is_power_of_2() { assert_eq!( ComparableFloat(two_over_sqrt_pi_alt), ComparableFloat(next_upper) ); assert_eq!(o_alt, Greater); } } else if !two_over_sqrt_pi.is_power_of_2() { let (two_over_sqrt_pi_alt, o_alt) = Float::two_over_sqrt_pi_prec_round(prec, Floor); let mut next_lower = two_over_sqrt_pi.clone(); next_lower.decrement(); assert_eq!( ComparableFloat(two_over_sqrt_pi_alt), ComparableFloat(next_lower) ); assert_eq!(o_alt, Less); } }); unsigned_gen_var_11().test_properties(|prec| { assert_panic!(Float::two_over_sqrt_pi_prec_round(prec, Exact)); }); test_constant(Float::two_over_sqrt_pi_prec_round, 10000); } ================================================ FILE: malachite-float/tests/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_gen, float_gen_var_12, float_pair_gen, float_pair_gen_var_10, }; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::test_util::generators::integer_pair_gen; use rug; #[test] #[allow(clippy::redundant_clone)] fn test_clone() { let test = |s, s_hex| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let x_alt = x.clone(); assert!(x.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); let r_x = rug::Float::exact_from(&x).clone(); assert_eq!(ComparableFloat(Float::from(&r_x)), ComparableFloat(x)); }; test("NaN", "NaN"); test("Infinity", "Infinity"); test("-Infinity", "-Infinity"); test("0.0", "0x0.0"); test("-0.0", "-0x0.0"); test("1.0", "0x1.0#1"); test("2.0", "0x2.0#1"); test("0.5", "0x0.8#1"); test("0.33333333333333331", "0x0.55555555555554#53"); test("1.4142135623730951", "0x1.6a09e667f3bcd#53"); test("3.1415926535897931", "0x3.243f6a8885a30#53"); test("-1.0", "-0x1.0#1"); test("-2.0", "-0x2.0#1"); test("-0.5", "-0x0.8#1"); test("-0.33333333333333331", "-0x0.55555555555554#53"); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53"); test("-3.1415926535897931", "-0x3.243f6a8885a30#53"); } #[test] fn test_clone_from() { let test = |s, s_hex, t, t_hex| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let y = parse_hex_string(t_hex); assert_eq!(y.to_string(), t); let mut x_alt = x.clone(); x_alt.clone_from(&y); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&y)); let mut rug_x = rug::Float::exact_from(&x); let rug_y = rug::Float::exact_from(&y); rug_x.clone_from(&rug_y); assert_eq!( ComparableFloat(Float::from(&rug_x)), ComparableFloat(Float::from(&rug_y)) ); }; test("NaN", "NaN", "NaN", "NaN"); test("NaN", "NaN", "0.0", "0x0.0"); test("NaN", "NaN", "Infinity", "Infinity"); test("NaN", "NaN", "-Infinity", "-Infinity"); test("NaN", "NaN", "0.33333333333333331", "0x0.55555555555554#53"); test("0.0", "0x0.0", "NaN", "NaN"); test("0.0", "0x0.0", "0.0", "0x0.0"); test("0.0", "0x0.0", "Infinity", "Infinity"); test("0.0", "0x0.0", "-Infinity", "-Infinity"); test( "0.0", "0x0.0", "0.33333333333333331", "0x0.55555555555554#53", ); test("Infinity", "Infinity", "NaN", "NaN"); test("Infinity", "Infinity", "0.0", "0x0.0"); test("Infinity", "Infinity", "Infinity", "Infinity"); test("Infinity", "Infinity", "-Infinity", "-Infinity"); test( "Infinity", "Infinity", "0.33333333333333331", "0x0.55555555555554#53", ); test("-Infinity", "-Infinity", "NaN", "NaN"); test("-Infinity", "-Infinity", "0.0", "0x0.0"); test("-Infinity", "-Infinity", "Infinity", "Infinity"); test("-Infinity", "-Infinity", "-Infinity", "-Infinity"); test( "-Infinity", "-Infinity", "0.33333333333333331", "0x0.55555555555554#53", ); test("0.33333333333333331", "0x0.55555555555554#53", "NaN", "NaN"); test( "0.33333333333333331", "0x0.55555555555554#53", "0.0", "0x0.0", ); test( "0.33333333333333331", "0x0.55555555555554#53", "Infinity", "Infinity", ); test( "0.33333333333333331", "0x0.55555555555554#53", "-Infinity", "-Infinity", ); test( "0.33333333333333331", "0x0.55555555555554#53", "0.33333333333333331", "0x0.55555555555554#53", ); } fn clone_and_clone_from_properties_helper_1(x: Float) { let mut_x = x.clone(); assert!(mut_x.is_valid()); assert_eq!(ComparableFloatRef(&mut_x), ComparableFloatRef(&x)); assert_eq!( ComparableFloat(Float::from(&rug::Float::exact_from(&x).clone())), ComparableFloat(x) ); } #[allow(clippy::needless_pass_by_value)] fn clone_and_clone_from_properties_helper_2(x: Float, y: Float) { let mut mut_x = x.clone(); mut_x.clone_from(&y); assert!(mut_x.is_valid()); assert_eq!(ComparableFloatRef(&mut_x), ComparableFloatRef(&y)); let mut rug_x = rug::Float::exact_from(&x); rug_x.clone_from(&rug::Float::exact_from(&y)); assert_eq!(ComparableFloat(Float::from(&rug_x)), ComparableFloat(y)); } #[allow(clippy::redundant_clone)] #[test] fn clone_and_clone_from_properties() { float_gen().test_properties(|x| { clone_and_clone_from_properties_helper_1(x); }); float_gen_var_12().test_properties(|x| { clone_and_clone_from_properties_helper_1(x); }); float_pair_gen().test_properties(|(x, y)| { clone_and_clone_from_properties_helper_2(x, y); }); float_pair_gen_var_10().test_properties(|(x, y)| { clone_and_clone_from_properties_helper_2(x, y); }); integer_pair_gen().test_properties(|(i, j)| { let x = Float::exact_from(&i); let y = Float::exact_from(&j); let mut mut_i = i.clone(); let mut mut_x = x.clone(); mut_i.clone_from(&j); mut_x.clone_from(&y); assert_eq!(mut_x, mut_i); }); } ================================================ FILE: malachite-float/tests/conversion/from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_gen, integer_unsigned_pair_gen_var_6}; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_from_integer_prec() { let test = |s, prec, out, out_hex, out_o| { let u = Integer::from_str(s).unwrap(); let (x, o) = Float::from_integer_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_integer_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test("0", 1, "0.0", "0x0.0", Equal); test("0", 10, "0.0", "0x0.0", Equal); test("0", 20, "0.0", "0x0.0", Equal); test("1", 1, "1.0", "0x1.0#1", Equal); test("1", 10, "1.0", "0x1.000#10", Equal); test("1", 20, "1.0", "0x1.00000#20", Equal); test("123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("123", 10, "123.0", "0x7b.0#10", Equal); test("123", 20, "123.0", "0x7b.0000#20", Equal); test("1000000000000", 1, "1.0e12", "0x1.0E+10#1", Greater); test("1000000000000", 10, "9.997e11", "0xe.8cE+9#10", Less); test("1000000000000", 20, "9.999997e11", "0xe.8d4aE+9#20", Less); test("-1", 1, "-1.0", "-0x1.0#1", Equal); test("-1", 10, "-1.0", "-0x1.000#10", Equal); test("-1", 20, "-1.0", "-0x1.00000#20", Equal); test("-123", 1, "-1.0e2", "-0x8.0E+1#1", Less); test("-123", 10, "-123.0", "-0x7b.0#10", Equal); test("-123", 20, "-123.0", "-0x7b.0000#20", Equal); test("-1000000000000", 1, "-1.0e12", "-0x1.0E+10#1", Less); test("-1000000000000", 10, "-9.997e11", "-0xe.8cE+9#10", Greater); test( "-1000000000000", 20, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); let test_big = |u: Integer, prec, out, out_hex, out_o| { let (x, o) = Float::from_integer_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_integer_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test_big( Integer::power_of_2(1000), 10, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, "too_big", "0x4.0E+268435455#1", Less, ); test_big( -Integer::power_of_2(1000), 10, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, "-too_big", "-0x4.0E+268435455#1", Greater, ); } #[test] fn from_integer_prec_fail() { assert_panic!(Float::from_integer_prec(Integer::ZERO, 0)); assert_panic!(Float::from_integer_prec(Integer::ONE, 0)); assert_panic!(Float::from_integer_prec(Integer::NEGATIVE_ONE, 0)); } #[test] fn from_integer_prec_ref_fail() { assert_panic!(Float::from_integer_prec_ref(&Integer::ZERO, 0)); assert_panic!(Float::from_integer_prec_ref(&Integer::ONE, 0)); assert_panic!(Float::from_integer_prec_ref(&Integer::NEGATIVE_ONE, 0)); } #[test] fn test_from_integer_prec_round() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Integer::from_str(s).unwrap(); let (x, o) = Float::from_integer_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_integer_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(rug_o, out_o); } }; test("0", 1, Floor, "0.0", "0x0.0", Equal); test("0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", 1, Down, "0.0", "0x0.0", Equal); test("0", 1, Up, "0.0", "0x0.0", Equal); test("0", 1, Nearest, "0.0", "0x0.0", Equal); test("0", 1, Exact, "0.0", "0x0.0", Equal); test("0", 10, Floor, "0.0", "0x0.0", Equal); test("0", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", 10, Down, "0.0", "0x0.0", Equal); test("0", 10, Up, "0.0", "0x0.0", Equal); test("0", 10, Nearest, "0.0", "0x0.0", Equal); test("0", 10, Exact, "0.0", "0x0.0", Equal); test("0", 20, Floor, "0.0", "0x0.0", Equal); test("0", 20, Ceiling, "0.0", "0x0.0", Equal); test("0", 20, Down, "0.0", "0x0.0", Equal); test("0", 20, Up, "0.0", "0x0.0", Equal); test("0", 20, Nearest, "0.0", "0x0.0", Equal); test("0", 20, Exact, "0.0", "0x0.0", Equal); test("1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1", 1, Down, "1.0", "0x1.0#1", Equal); test("1", 1, Up, "1.0", "0x1.0#1", Equal); test("1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1", 10, Down, "1.0", "0x1.000#10", Equal); test("1", 10, Up, "1.0", "0x1.000#10", Equal); test("1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1", 10, Exact, "1.0", "0x1.000#10", Equal); test("1", 20, Floor, "1.0", "0x1.00000#20", Equal); test("1", 20, Ceiling, "1.0", "0x1.00000#20", Equal); test("1", 20, Down, "1.0", "0x1.00000#20", Equal); test("1", 20, Up, "1.0", "0x1.00000#20", Equal); test("1", 20, Nearest, "1.0", "0x1.00000#20", Equal); test("1", 20, Exact, "1.0", "0x1.00000#20", Equal); test("123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test("123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater); test("123", 1, Down, "6.0e1", "0x4.0E+1#1", Less); test("123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test("123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater); test("123", 10, Floor, "123.0", "0x7b.0#10", Equal); test("123", 10, Ceiling, "123.0", "0x7b.0#10", Equal); test("123", 10, Down, "123.0", "0x7b.0#10", Equal); test("123", 10, Up, "123.0", "0x7b.0#10", Equal); test("123", 10, Nearest, "123.0", "0x7b.0#10", Equal); test("123", 10, Exact, "123.0", "0x7b.0#10", Equal); test("123", 20, Floor, "123.0", "0x7b.0000#20", Equal); test("123", 20, Ceiling, "123.0", "0x7b.0000#20", Equal); test("123", 20, Down, "123.0", "0x7b.0000#20", Equal); test("123", 20, Up, "123.0", "0x7b.0000#20", Equal); test("123", 20, Nearest, "123.0", "0x7b.0000#20", Equal); test("123", 20, Exact, "123.0", "0x7b.0000#20", Equal); test("1000000000000", 1, Floor, "5.0e11", "0x8.0E+9#1", Less); test( "1000000000000", 1, Ceiling, "1.0e12", "0x1.0E+10#1", Greater, ); test("1000000000000", 1, Down, "5.0e11", "0x8.0E+9#1", Less); test("1000000000000", 1, Up, "1.0e12", "0x1.0E+10#1", Greater); test( "1000000000000", 1, Nearest, "1.0e12", "0x1.0E+10#1", Greater, ); test("1000000000000", 10, Floor, "9.997e11", "0xe.8cE+9#10", Less); test( "1000000000000", 10, Ceiling, "1.001e12", "0xe.90E+9#10", Greater, ); test("1000000000000", 10, Down, "9.997e11", "0xe.8cE+9#10", Less); test("1000000000000", 10, Up, "1.001e12", "0xe.90E+9#10", Greater); test( "1000000000000", 10, Nearest, "9.997e11", "0xe.8cE+9#10", Less, ); test( "1000000000000", 20, Floor, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test( "1000000000000", 20, Ceiling, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test( "1000000000000", 20, Down, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test( "1000000000000", 20, Up, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test( "1000000000000", 20, Nearest, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test("-1", 1, Floor, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Down, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Up, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Nearest, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Exact, "-1.0", "-0x1.0#1", Equal); test("-1", 10, Floor, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Ceiling, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Down, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Up, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Nearest, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Exact, "-1.0", "-0x1.000#10", Equal); test("-1", 20, Floor, "-1.0", "-0x1.00000#20", Equal); test("-1", 20, Ceiling, "-1.0", "-0x1.00000#20", Equal); test("-1", 20, Down, "-1.0", "-0x1.00000#20", Equal); test("-1", 20, Up, "-1.0", "-0x1.00000#20", Equal); test("-1", 20, Nearest, "-1.0", "-0x1.00000#20", Equal); test("-1", 20, Exact, "-1.0", "-0x1.00000#20", Equal); test("-123", 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less); test("-123", 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater); test("-123", 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater); test("-123", 1, Up, "-1.0e2", "-0x8.0E+1#1", Less); test("-123", 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less); test("-123", 10, Floor, "-123.0", "-0x7b.0#10", Equal); test("-123", 10, Ceiling, "-123.0", "-0x7b.0#10", Equal); test("-123", 10, Down, "-123.0", "-0x7b.0#10", Equal); test("-123", 10, Up, "-123.0", "-0x7b.0#10", Equal); test("-123", 10, Nearest, "-123.0", "-0x7b.0#10", Equal); test("-123", 10, Exact, "-123.0", "-0x7b.0#10", Equal); test("-123", 20, Floor, "-123.0", "-0x7b.0000#20", Equal); test("-123", 20, Ceiling, "-123.0", "-0x7b.0000#20", Equal); test("-123", 20, Down, "-123.0", "-0x7b.0000#20", Equal); test("-123", 20, Up, "-123.0", "-0x7b.0000#20", Equal); test("-123", 20, Nearest, "-123.0", "-0x7b.0000#20", Equal); test("-123", 20, Exact, "-123.0", "-0x7b.0000#20", Equal); test("-1000000000000", 1, Floor, "-1.0e12", "-0x1.0E+10#1", Less); test( "-1000000000000", 1, Ceiling, "-5.0e11", "-0x8.0E+9#1", Greater, ); test("-1000000000000", 1, Down, "-5.0e11", "-0x8.0E+9#1", Greater); test("-1000000000000", 1, Up, "-1.0e12", "-0x1.0E+10#1", Less); test( "-1000000000000", 1, Nearest, "-1.0e12", "-0x1.0E+10#1", Less, ); test( "-1000000000000", 10, Floor, "-1.001e12", "-0xe.90E+9#10", Less, ); test( "-1000000000000", 10, Ceiling, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test( "-1000000000000", 10, Down, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test("-1000000000000", 10, Up, "-1.001e12", "-0xe.90E+9#10", Less); test( "-1000000000000", 10, Nearest, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test( "-1000000000000", 20, Floor, "-1.000001e12", "-0xe.8d4bE+9#20", Less, ); test( "-1000000000000", 20, Ceiling, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); test( "-1000000000000", 20, Down, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); test( "-1000000000000", 20, Up, "-1.000001e12", "-0xe.8d4bE+9#20", Less, ); test( "-1000000000000", 20, Nearest, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); let test_big = |u: Integer, prec, rm, out, out_hex, out_o| { let (x, o) = Float::from_integer_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_integer_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } }; test_big( Integer::power_of_2(1000), 10, Floor, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(1000), 10, Ceiling, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(1000), 10, Down, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(1000), 10, Up, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(1000), 10, Nearest, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(1000), 10, Exact, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Floor, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Down, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Up, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Nearest, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Floor, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Down, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Up, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Nearest, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Exact, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Nearest, "too_big", "0x4.0E+268435455#1", Less, ); test_big( -Integer::power_of_2(1000), 10, Floor, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(1000), 10, Ceiling, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(1000), 10, Down, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(1000), 10, Up, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(1000), 10, Nearest, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(1000), 10, Exact, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Ceiling, "-too_big", "-0x7.feE+268435455#10", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Down, "-too_big", "-0x7.feE+268435455#10", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Up, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Floor, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Down, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Up, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Nearest, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Exact, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), 1, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), 1, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), 1, Nearest, "-too_big", "-0x4.0E+268435455#1", Greater, ); } #[test] fn from_integer_prec_round_fail() { assert_panic!(Float::from_integer_prec_round(Integer::ZERO, 0, Floor)); assert_panic!(Float::from_integer_prec_round(Integer::ONE, 0, Floor)); assert_panic!(Float::from_integer_prec_round( Integer::from(123u32), 1, Exact )); assert_panic!(Float::from_integer_prec_round( Integer::NEGATIVE_ONE, 0, Floor )); assert_panic!(Float::from_integer_prec_round( Integer::from(-123), 1, Exact )); } #[test] fn from_integer_prec_round_ref_fail() { assert_panic!(Float::from_integer_prec_round_ref(&Integer::ZERO, 0, Floor)); assert_panic!(Float::from_integer_prec_round_ref(&Integer::ONE, 0, Floor)); assert_panic!(Float::from_integer_prec_round_ref( &Integer::from(123u32), 1, Exact )); assert_panic!(Float::from_integer_prec_round_ref( &Integer::NEGATIVE_ONE, 0, Floor )); assert_panic!(Float::from_integer_prec_round_ref( &Integer::from(-123), 1, Exact )); } #[allow(clippy::needless_borrow)] #[test] fn test_try_from_integer() { let test = |s, out, out_hex| { let x = Integer::from_str(s).unwrap(); let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test("0", Ok("0.0"), Ok("0x0.0")); test("1", Ok("1.0"), Ok("0x1.0#1")); test("123", Ok("123.0"), Ok("0x7b.0#7")); test("1000000000000", Ok("1.0e12"), Ok("0xe.8d4a51E+9#28")); test("-1", Ok("-1.0"), Ok("-0x1.0#1")); test("-123", Ok("-123.0"), Ok("-0x7b.0#7")); test("-1000000000000", Ok("-1.0e12"), Ok("-0xe.8d4a51E+9#28")); let test_big = |x: Integer, out, out_hex| { let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test_big(Integer::power_of_2(1000), Ok("1.0e301"), Ok("0x1.0E+250#1")); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), Ok("too_big"), Ok("0x4.0E+268435455#1"), ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), Ok("too_big"), Ok("0x6.0E+268435455#2"), ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), Ok("too_big"), Ok("0x6.008E+268435455#12"), ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), Ok("too_big"), Ok("0x5.ff8E+268435455#12"), ); test_big( -Integer::power_of_2(1000), Ok("-1.0e301"), Ok("-0x1.0E+250#1"), ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), Ok("-too_big"), Ok("-0x4.0E+268435455#1"), ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), Ok("-too_big"), Ok("-0x6.0E+268435455#2"), ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), Ok("-too_big"), Ok("-0x6.008E+268435455#12"), ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), Ok("-too_big"), Ok("-0x5.ff8E+268435455#12"), ); } #[test] fn test_convertible_from_integer() { let test = |s, out| { let x = Integer::from_str(s).unwrap(); assert_eq!(Float::convertible_from(&x), out); }; test("0", true); test("1", true); test("123", true); test("-1", true); test("-123", true); let test_big = |x: Integer, out| { assert_eq!(Float::convertible_from(&x), out); }; test_big(Integer::power_of_2(1000), true); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), false, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)) - Integer::ONE, true, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), true, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), true, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), true, ); test_big( Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), true, ); test_big(-Integer::power_of_2(1000), true); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), false, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT)) + Integer::ONE, true, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), true, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Integer::from(3u8), true, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3073u16), true, ); test_big( -Integer::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Integer::from(3071u16), true, ); } #[test] fn from_integer_prec_properties() { integer_unsigned_pair_gen_var_6().test_properties(|(n, prec)| { let (float_n, o) = Float::from_integer_prec(n.clone(), prec); assert!(float_n.is_valid()); let (float_n_alt, o_alt) = Float::from_integer_prec_ref(&n, prec); assert!(float_n_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o, o_alt); assert_eq!(float_n.partial_cmp(&n), Some(o)); let rug_n = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&n)); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); assert_eq!( float_n.get_prec(), if n == 0u32 { None } else { Some(prec) } ); }); } #[test] fn from_integer_prec_round_properties() { integer_unsigned_rounding_mode_triple_gen_var_3().test_properties(|(n, prec, rm)| { let (float_n, o) = Float::from_integer_prec_round(n.clone(), prec, rm); assert!(float_n.is_valid()); let (float_n_alt, o_alt) = Float::from_integer_prec_round_ref(&n, prec, rm); assert!(float_n_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o, o_alt); assert_eq!(float_n.partial_cmp(&n), Some(o)); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_n, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&n), rm); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); assert_eq!(rug_o, o); } assert_eq!( float_n.get_prec(), if n == 0u32 { None } else { Some(prec) } ); }); integer_unsigned_pair_gen_var_6().test_properties(|(n, prec)| { let floor = Float::from_integer_prec_round_ref(&n, prec, Floor); let r_floor = Rational::exact_from(&floor.0); assert!(r_floor <= n); if r_floor != 0u32 { assert!(r_floor + Rational::exact_from(floor.0.ulp().unwrap()) > n); } let (floor_n_alt, o_alt) = Float::from_integer_prec_round_ref(&n, prec, if n >= 0 { Down } else { Up }); assert_eq!( ComparableFloatRef(&floor_n_alt), ComparableFloatRef(&floor.0) ); assert_eq!(o_alt, floor.1); let ceiling = Float::from_integer_prec_round_ref(&n, prec, Ceiling); let r_ceiling = Rational::exact_from(&ceiling.0); assert!(r_ceiling >= n); if r_ceiling != 0u32 { assert!(r_ceiling - Rational::exact_from(ceiling.0.ulp().unwrap()) < n); } let (ceiling_n_alt, o_alt) = Float::from_integer_prec_round_ref(&n, prec, if n >= 0 { Up } else { Down }); assert_eq!( ComparableFloatRef(&ceiling_n_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(o_alt, ceiling.1); let nearest = Float::from_integer_prec_round_ref(&n, prec, Nearest); let r_nearest = Rational::exact_from(&nearest.0); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); if r_nearest != 0u32 { assert!( (r_nearest - Rational::from(&n)) .le_abs(&(Rational::exact_from(nearest.0.ulp().unwrap()) >> 1)) ); } }); } #[test] fn float_try_from_integer_properties() { integer_gen().test_properties(|x| { let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); assert_eq!( Float::try_from(x.clone()).map(ComparableFloat), of.clone().map(ComparableFloat) ); if let Ok(f) = of { assert_eq!(-x, -f); } }); } #[test] fn float_convertible_from_integer_properties() { integer_gen().test_properties(|x| { assert_eq!(Float::convertible_from(&x), Float::try_from(&x).is_ok()); }); } ================================================ FILE: malachite-float/tests/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_7}; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_from_natural_prec() { let test = |s, prec, out, out_hex, out_o| { let u = Natural::from_str(s).unwrap(); let (x, o) = Float::from_natural_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_natural_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test("0", 1, "0.0", "0x0.0", Equal); test("0", 10, "0.0", "0x0.0", Equal); test("0", 20, "0.0", "0x0.0", Equal); test("1", 1, "1.0", "0x1.0#1", Equal); test("1", 10, "1.0", "0x1.000#10", Equal); test("1", 20, "1.0", "0x1.00000#20", Equal); test("123", 1, "1.0e2", "0x8.0E+1#1", Greater); test("123", 10, "123.0", "0x7b.0#10", Equal); test("123", 20, "123.0", "0x7b.0000#20", Equal); test("1000000000000", 1, "1.0e12", "0x1.0E+10#1", Greater); test("1000000000000", 10, "9.997e11", "0xe.8cE+9#10", Less); test("1000000000000", 20, "9.999997e11", "0xe.8d4aE+9#20", Less); test( "289905948138435080392", 64, "2.8990594813843508038e20", "0xf.b740d3d8283d70cE+16#64", Less, ); let test_big = |u: Natural, prec, out, out_hex, out_o| { let (x, o) = Float::from_natural_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_natural_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); }; test_big( Natural::power_of_2(1000), 10, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, "too_big", "0x4.0E+268435455#1", Less, ); } #[test] fn from_natural_prec_fail() { assert_panic!(Float::from_natural_prec(Natural::ZERO, 0)); assert_panic!(Float::from_natural_prec(Natural::ONE, 0)); } #[test] fn from_natural_prec_ref_fail() { assert_panic!(Float::from_natural_prec_ref(&Natural::ZERO, 0)); assert_panic!(Float::from_natural_prec_ref(&Natural::ONE, 0)); } #[test] fn test_from_natural_prec_round() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Natural::from_str(s).unwrap(); let (x, o) = Float::from_natural_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_natural_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(rug_o, out_o); } }; test("0", 1, Floor, "0.0", "0x0.0", Equal); test("0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", 1, Down, "0.0", "0x0.0", Equal); test("0", 1, Up, "0.0", "0x0.0", Equal); test("0", 1, Nearest, "0.0", "0x0.0", Equal); test("0", 1, Exact, "0.0", "0x0.0", Equal); test("0", 10, Floor, "0.0", "0x0.0", Equal); test("0", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", 10, Down, "0.0", "0x0.0", Equal); test("0", 10, Up, "0.0", "0x0.0", Equal); test("0", 10, Nearest, "0.0", "0x0.0", Equal); test("0", 10, Exact, "0.0", "0x0.0", Equal); test("0", 20, Floor, "0.0", "0x0.0", Equal); test("0", 20, Ceiling, "0.0", "0x0.0", Equal); test("0", 20, Down, "0.0", "0x0.0", Equal); test("0", 20, Up, "0.0", "0x0.0", Equal); test("0", 20, Nearest, "0.0", "0x0.0", Equal); test("0", 20, Exact, "0.0", "0x0.0", Equal); test("1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1", 1, Down, "1.0", "0x1.0#1", Equal); test("1", 1, Up, "1.0", "0x1.0#1", Equal); test("1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1", 10, Down, "1.0", "0x1.000#10", Equal); test("1", 10, Up, "1.0", "0x1.000#10", Equal); test("1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1", 10, Exact, "1.0", "0x1.000#10", Equal); test("1", 20, Floor, "1.0", "0x1.00000#20", Equal); test("1", 20, Ceiling, "1.0", "0x1.00000#20", Equal); test("1", 20, Down, "1.0", "0x1.00000#20", Equal); test("1", 20, Up, "1.0", "0x1.00000#20", Equal); test("1", 20, Nearest, "1.0", "0x1.00000#20", Equal); test("1", 20, Exact, "1.0", "0x1.00000#20", Equal); test("123", 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test("123", 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater); test("123", 1, Down, "6.0e1", "0x4.0E+1#1", Less); test("123", 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test("123", 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater); test("123", 10, Floor, "123.0", "0x7b.0#10", Equal); test("123", 10, Ceiling, "123.0", "0x7b.0#10", Equal); test("123", 10, Down, "123.0", "0x7b.0#10", Equal); test("123", 10, Up, "123.0", "0x7b.0#10", Equal); test("123", 10, Nearest, "123.0", "0x7b.0#10", Equal); test("123", 10, Exact, "123.0", "0x7b.0#10", Equal); test("123", 20, Floor, "123.0", "0x7b.0000#20", Equal); test("123", 20, Ceiling, "123.0", "0x7b.0000#20", Equal); test("123", 20, Down, "123.0", "0x7b.0000#20", Equal); test("123", 20, Up, "123.0", "0x7b.0000#20", Equal); test("123", 20, Nearest, "123.0", "0x7b.0000#20", Equal); test("123", 20, Exact, "123.0", "0x7b.0000#20", Equal); test("1000000000000", 1, Floor, "5.0e11", "0x8.0E+9#1", Less); test( "1000000000000", 1, Ceiling, "1.0e12", "0x1.0E+10#1", Greater, ); test("1000000000000", 1, Down, "5.0e11", "0x8.0E+9#1", Less); test("1000000000000", 1, Up, "1.0e12", "0x1.0E+10#1", Greater); test( "1000000000000", 1, Nearest, "1.0e12", "0x1.0E+10#1", Greater, ); test("1000000000000", 10, Floor, "9.997e11", "0xe.8cE+9#10", Less); test( "1000000000000", 10, Ceiling, "1.001e12", "0xe.90E+9#10", Greater, ); test("1000000000000", 10, Down, "9.997e11", "0xe.8cE+9#10", Less); test("1000000000000", 10, Up, "1.001e12", "0xe.90E+9#10", Greater); test( "1000000000000", 10, Nearest, "9.997e11", "0xe.8cE+9#10", Less, ); test( "1000000000000", 20, Floor, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test( "1000000000000", 20, Ceiling, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test( "1000000000000", 20, Down, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test( "1000000000000", 20, Up, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test( "1000000000000", 20, Nearest, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test( "20928269765806917927943182622889", 64, Nearest, "2.0928269765806917929e31", "0x1.0826e3012a87296eE+26#64", Greater, ); // - in from_natural_prec_round // - x == 0 in from_natural_prec_round test("0", 1, Down, "0.0", "0x0.0", Equal); // - x != 0 in from_natural_prec_round // - bits <= prec in from_natural_prec_round test("1", 1, Down, "1.0", "0x1.0#1", Equal); // - bits > prec in from_natural_prec_round // - needed_bits == 0 in from_natural_prec_round // - mask_width < Limb::WIDTH in from_natural_prec_round // - rm == Floor || rm == Down in from_natural_prec_round // - (rm == Floor || rm == Down) && !inexact in from_natural_prec_round test("2", 1, Down, "2.0", "0x2.0#1", Equal); // - rm == Ceiling || rm == Up in from_natural_prec_round // - (rm == Ceiling || rm == Up) && !inexact in from_natural_prec_round test("2", 1, Up, "2.0", "0x2.0#1", Equal); // - rm == Nearest in from_natural_prec_round // - rm == Nearest && (!half_bit || !inexact_after_half && !x.get_bit(bits - prec) && !inexact // in from_natural_prec_round test("2", 1, Nearest, "2.0", "0x2.0#1", Equal); // - rm == Exact in from_natural_prec_round test("2", 1, Exact, "2.0", "0x2.0#1", Equal); // - (rm == Floor || rm == Down) && inexact in from_natural_prec_round test("3", 1, Down, "2.0", "0x2.0#1", Less); // - (rm == Ceiling || rm == Up) && inexact in from_natural_prec_round // - (rm == Ceiling || rm == Up) && significand.limb_count() > original_limb_count in // from_natural_prec_round test("3", 1, Up, "4.0", "0x4.0#1", Greater); // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) in // from_natural_prec_round // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) && // significand.limb_count() > original_limb_count in from_natural_prec_round test("3", 1, Nearest, "4.0", "0x4.0#1", Greater); // - rm == Nearest && (!half_bit || !inexact_after_half && !x.get_bit(bits - prec) && inexact in // from_natural_prec_round test("5", 1, Nearest, "4.0", "0x4.0#1", Less); // - (rm == Ceiling || rm == Up) && significand.limb_count() <= original_limb_count in // from_natural_prec_round test("5", 2, Up, "6.0", "0x6.0#2", Greater); // - rm == Nearest && half_bit && (inexact_after_half || x.get_bit(bits - prec)) && // significand.limb_count() <= original_limb_count in from_natural_prec_round test("11", 2, Nearest, "1.0e1", "0xc.0#2", Greater); // - needed_bits != 0 in from_natural_prec_round // - mask_width >= Limb::WIDTH in from_natural_prec_round test( "10524811972430560515843", 15, Floor, "1.05244e22", "0x2.3a88E+18#15", Less, ); let test_big = |u: Natural, prec, rm, out, out_hex, out_o| { let (x, o) = Float::from_natural_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_natural_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } }; test_big( Natural::power_of_2(1000), 10, Floor, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(1000), 10, Ceiling, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(1000), 10, Down, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(1000), 10, Up, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(1000), 10, Nearest, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(1000), 10, Exact, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Floor, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Down, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Up, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), 10, Nearest, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Floor, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Down, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Up, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Nearest, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), 10, Exact, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), 1, Nearest, "too_big", "0x4.0E+268435455#1", Less, ); } #[test] fn from_natural_prec_round_fail() { assert_panic!(Float::from_natural_prec_round(Natural::ZERO, 0, Floor)); assert_panic!(Float::from_natural_prec_round(Natural::ONE, 0, Floor)); assert_panic!(Float::from_natural_prec_round( Natural::from(123u32), 1, Exact )); } #[test] fn from_natural_prec_round_ref_fail() { assert_panic!(Float::from_natural_prec_round_ref(&Natural::ZERO, 0, Floor)); assert_panic!(Float::from_natural_prec_round_ref(&Natural::ONE, 0, Floor)); assert_panic!(Float::from_natural_prec_round_ref( &Natural::from(123u32), 1, Exact )); } #[allow(clippy::needless_borrow)] #[test] fn test_try_from_natural() { let test = |s, out, out_hex| { let x = Natural::from_str(s).unwrap(); let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test("0", Ok("0.0"), Ok("0x0.0")); test("1", Ok("1.0"), Ok("0x1.0#1")); test("123", Ok("123.0"), Ok("0x7b.0#7")); test("1000000000000", Ok("1.0e12"), Ok("0xe.8d4a51E+9#28")); let test_big = |x: Natural, out, out_hex| { let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test_big(Natural::power_of_2(1000), Ok("1.0e301"), Ok("0x1.0E+250#1")); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), Ok("too_big"), Ok("0x4.0E+268435455#1"), ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), Ok("too_big"), Ok("0x6.0E+268435455#2"), ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), Ok("too_big"), Ok("0x6.008E+268435455#12"), ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), Ok("too_big"), Ok("0x5.ff8E+268435455#12"), ); } #[test] fn test_convertible_from_natural() { let test = |s, out| { let x = Natural::from_str(s).unwrap(); assert_eq!(Float::convertible_from(&x), out); }; test("0", true); test("1", true); test("123", true); let test_big = |x: Natural, out| { assert_eq!(Float::convertible_from(&x), out); }; test_big(Natural::power_of_2(1000), true); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)), false, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT)) - Natural::ONE, true, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 1), true, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 2) * Natural::from(3u8), true, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3073u16), true, ); test_big( Natural::power_of_2(u64::exact_from(Float::MAX_EXPONENT) - 12) * Natural::from(3071u16), true, ); } #[test] fn from_natural_prec_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(n, prec)| { let (float_n, o) = Float::from_natural_prec(n.clone(), prec); assert!(float_n.is_valid()); let (float_n_alt, o_alt) = Float::from_natural_prec_ref(&n, prec); assert!(float_n_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o, o_alt); assert_eq!(float_n.partial_cmp(&n), Some(o)); let rug_n = rug::Float::with_val(u32::exact_from(prec), rug::Integer::from(&n)); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); let (float_n_alt, o_alt) = Float::from_integer_prec(Integer::from(&n), prec); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == 0u32 { None } else { Some(prec) } ); }); } #[test] fn from_natural_prec_round_properties() { natural_unsigned_rounding_mode_triple_gen_var_2().test_properties(|(n, prec, rm)| { let (float_n, o) = Float::from_natural_prec_round(n.clone(), prec, rm); assert!(float_n.is_valid()); let (float_n_alt, o_alt) = Float::from_natural_prec_round_ref(&n, prec, rm); assert!(float_n_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o, o_alt); assert_eq!(float_n.partial_cmp(&n), Some(o)); match rm { Floor | Down => { assert_ne!(o, Greater); } Ceiling | Up => { assert_ne!(o, Less); } Exact => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_n, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Integer::from(&n), rm); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); assert_eq!(rug_o, o); } let (float_n_alt, o_alt) = Float::from_integer_prec_round(Integer::from(&n), prec, rm); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == 0u32 { None } else { Some(prec) } ); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, prec)| { let floor = Float::from_natural_prec_round_ref(&n, prec, Floor); let r_floor = Rational::exact_from(&floor.0); assert!(r_floor <= n); if r_floor != 0u32 { assert!(r_floor + Rational::exact_from(floor.0.ulp().unwrap()) > n); } let (floor_alt, floor_o_alt) = Float::from_natural_prec_round_ref(&n, prec, Down); assert_eq!(ComparableFloatRef(&floor_alt), ComparableFloatRef(&floor.0)); assert_eq!(floor_o_alt, floor.1); let ceiling = Float::from_natural_prec_round_ref(&n, prec, Ceiling); let r_ceiling = Rational::exact_from(&ceiling.0); assert!(r_ceiling >= n); if r_ceiling != 0u32 { assert!(r_ceiling - Rational::exact_from(ceiling.0.ulp().unwrap()) < n); } let (ceiling_alt, ceiling_o_alt) = Float::from_natural_prec_round_ref(&n, prec, Up); assert_eq!( ComparableFloatRef(&ceiling_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(ceiling_o_alt, ceiling.1); let nearest = Float::from_natural_prec_round_ref(&n, prec, Nearest); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); let r_nearest = Rational::exact_from(&nearest.0); if r_nearest != 0u32 { assert!( (r_nearest - Rational::from(&n)) .le_abs(&(Rational::exact_from(nearest.0.ulp().unwrap()) >> 1)) ); } }); } #[test] fn float_try_from_natural_properties() { natural_gen().test_properties(|x| { let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); assert_eq!( Float::try_from(x.clone()).map(ComparableFloat), of.clone().map(ComparableFloat) ); if let Ok(f) = of { assert_eq!(-x, -f); } }); } #[test] fn float_convertible_from_natural_properties() { natural_gen().test_properties(|x| { assert_eq!(Float::convertible_from(&x), Float::try_from(&x).is_ok()); }); } ================================================ FILE: malachite-float/tests/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{ NegativeInfinity, NegativeOne, NegativeZero, One, OneHalf, Two, Zero, }; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::{SignificantBits, TrailingZeros}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_unsigned_pair_gen_var_4, }; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::primitive_float_unsigned_rounding_mode_triple_gen_var_3; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_q::Rational; use rug::Assign; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::{ Ordering::{self, *}, max, }; use std::panic::catch_unwind; #[test] fn test_from_primitive_float() { fn test_helper(u: T, out: &str, out_hex: &str) where Float: From, rug::Float: Assign, { let x = Float::from(u); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); let prec = if !u.is_finite() || u == T::ZERO { 1 } else { let n = u.integer_mantissa(); u32::exact_from(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }; let rug_x = rug::Float::with_val(prec, u); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } test_helper(f32::NAN, "NaN", "NaN"); test_helper(f32::INFINITY, "Infinity", "Infinity"); test_helper(f32::NEGATIVE_INFINITY, "-Infinity", "-Infinity"); test_helper(f32::ZERO, "0.0", "0x0.0"); test_helper(f32::NEGATIVE_ZERO, "-0.0", "-0x0.0"); test_helper(f32::ONE, "1.0", "0x1.0#1"); test_helper(f32::TWO, "2.0", "0x2.0#1"); test_helper(f32::ONE_HALF, "0.5", "0x0.8#1"); test_helper(1.0f32 / 3.0, "0.33333334", "0x0.5555558#24"); test_helper(std::f32::consts::SQRT_2, "1.4142135", "0x1.6a09e6#24"); test_helper(std::f32::consts::PI, "3.1415927", "0x3.243f6c#24"); test_helper(f32::MIN_POSITIVE_SUBNORMAL, "1.0e-45", "0x8.0E-38#1"); test_helper(f32::MAX_SUBNORMAL, "1.1754942e-38", "0x3.fffff8E-32#23"); test_helper(f32::MIN_POSITIVE_NORMAL, "1.0e-38", "0x4.0E-32#1"); test_helper(f32::MAX_FINITE, "3.4028235e38", "0xf.fffffE+31#24"); test_helper(f32::NEGATIVE_ONE, "-1.0", "-0x1.0#1"); test_helper(-f32::TWO, "-2.0", "-0x2.0#1"); test_helper(-f32::ONE_HALF, "-0.5", "-0x0.8#1"); test_helper(-1.0f32 / 3.0, "-0.33333334", "-0x0.5555558#24"); test_helper(-std::f32::consts::SQRT_2, "-1.4142135", "-0x1.6a09e6#24"); test_helper(-std::f32::consts::PI, "-3.1415927", "-0x3.243f6c#24"); test_helper(-f32::MIN_POSITIVE_SUBNORMAL, "-1.0e-45", "-0x8.0E-38#1"); test_helper(-f32::MAX_SUBNORMAL, "-1.1754942e-38", "-0x3.fffff8E-32#23"); test_helper(-f32::MIN_POSITIVE_NORMAL, "-1.0e-38", "-0x4.0E-32#1"); test_helper(-f32::MAX_FINITE, "-3.4028235e38", "-0xf.fffffE+31#24"); test_helper(f64::NAN, "NaN", "NaN"); test_helper(f64::INFINITY, "Infinity", "Infinity"); test_helper(f64::NEGATIVE_INFINITY, "-Infinity", "-Infinity"); test_helper(f64::ZERO, "0.0", "0x0.0"); test_helper(f64::NEGATIVE_ZERO, "-0.0", "-0x0.0"); test_helper(f64::ONE, "1.0", "0x1.0#1"); test_helper(f64::TWO, "2.0", "0x2.0#1"); test_helper(f64::ONE_HALF, "0.5", "0x0.8#1"); test_helper(1.0f64 / 3.0, "0.33333333333333331", "0x0.55555555555554#53"); test_helper( std::f64::consts::SQRT_2, "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test_helper( std::f64::consts::PI, "3.141592653589793", "0x3.243f6a8885a3#50", ); test_helper(f64::MIN_POSITIVE_SUBNORMAL, "5.0e-324", "0x4.0E-269#1"); test_helper( f64::MAX_SUBNORMAL, "2.2250738585072009e-308", "0x3.ffffffffffffcE-256#52", ); test_helper(f64::MIN_POSITIVE_NORMAL, "2.0e-308", "0x4.0E-256#1"); test_helper( f64::MAX_FINITE, "1.7976931348623157e308", "0xf.ffffffffffff8E+255#53", ); test_helper(f64::NEGATIVE_ONE, "-1.0", "-0x1.0#1"); test_helper(-f64::TWO, "-2.0", "-0x2.0#1"); test_helper(-f64::ONE_HALF, "-0.5", "-0x0.8#1"); test_helper( -1.0f64 / 3.0, "-0.33333333333333331", "-0x0.55555555555554#53", ); test_helper( -std::f64::consts::SQRT_2, "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", ); test_helper( -std::f64::consts::PI, "-3.141592653589793", "-0x3.243f6a8885a3#50", ); test_helper(-f64::MIN_POSITIVE_SUBNORMAL, "-5.0e-324", "-0x4.0E-269#1"); test_helper( -f64::MAX_SUBNORMAL, "-2.2250738585072009e-308", "-0x3.ffffffffffffcE-256#52", ); test_helper(-f64::MIN_POSITIVE_NORMAL, "-2.0e-308", "-0x4.0E-256#1"); test_helper( -f64::MAX_FINITE, "-1.7976931348623157e308", "-0xf.ffffffffffff8E+255#53", ); } #[test] fn test_from_primitive_float_prec() { fn test_helper(u: T, prec: u64, out: &str, out_hex: &str, out_o: Ordering) where Float: From, rug::Float: Assign, { let (x, o) = Float::from_primitive_float_prec(u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(max(1, u32::exact_from(prec)), u); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } test_helper(f32::NAN, 1, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, "NaN", "NaN", Equal); test_helper(f32::NAN, 100, "NaN", "NaN", Equal); test_helper(f32::INFINITY, 1, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 100, "Infinity", "Infinity", Equal); test_helper(f32::NEGATIVE_INFINITY, 1, "-Infinity", "-Infinity", Equal); test_helper(f32::NEGATIVE_INFINITY, 10, "-Infinity", "-Infinity", Equal); test_helper(f32::NEGATIVE_INFINITY, 100, "-Infinity", "-Infinity", Equal); test_helper(f32::ZERO, 1, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 100, "0.0", "0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 100, "-0.0", "-0x0.0", Equal); test_helper(f32::ONE, 1, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 10, "1.0", "0x1.000#10", Equal); test_helper( f32::ONE, 100, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test_helper(1.0f32 / 3.0, 1, "0.2", "0x0.4#1", Less); test_helper(1.0f32 / 3.0, 10, "0.3335", "0x0.556#10", Greater); test_helper( 1.0f32 / 3.0, 100, "0.3333333432674407958984375", "0x0.55555580000000000000000000#100", Equal, ); test_helper(std::f32::consts::PI, 1, "4.0", "0x4.0#1", Greater); test_helper(std::f32::consts::PI, 10, "3.141", "0x3.24#10", Less); test_helper( std::f32::consts::PI, 100, "3.1415927410125732421875", "0x3.243f6c0000000000000000000#100", Equal, ); test_helper( f32::MIN_POSITIVE_SUBNORMAL, 1, "1.0e-45", "0x8.0E-38#1", Equal, ); test_helper( f32::MIN_POSITIVE_SUBNORMAL, 10, "1.401e-45", "0x8.00E-38#10", Equal, ); test_helper( f32::MIN_POSITIVE_SUBNORMAL, 100, "1.40129846432481707092372958329e-45", "0x8.000000000000000000000000E-38#100", Equal, ); test_helper(f32::NEGATIVE_ONE, 1, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 10, "-1.0", "-0x1.000#10", Equal); test_helper( f32::NEGATIVE_ONE, 100, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test_helper(-1.0f32 / 3.0, 1, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f32 / 3.0, 10, "-0.3335", "-0x0.556#10", Less); test_helper( -1.0f32 / 3.0, 100, "-0.3333333432674407958984375", "-0x0.55555580000000000000000000#100", Equal, ); test_helper(-std::f32::consts::PI, 1, "-4.0", "-0x4.0#1", Less); test_helper(-std::f32::consts::PI, 10, "-3.141", "-0x3.24#10", Greater); test_helper( -std::f32::consts::PI, 100, "-3.1415927410125732421875", "-0x3.243f6c0000000000000000000#100", Equal, ); test_helper( -f32::MIN_POSITIVE_SUBNORMAL, 1, "-1.0e-45", "-0x8.0E-38#1", Equal, ); test_helper( -f32::MIN_POSITIVE_SUBNORMAL, 10, "-1.401e-45", "-0x8.00E-38#10", Equal, ); test_helper( -f32::MIN_POSITIVE_SUBNORMAL, 100, "-1.40129846432481707092372958329e-45", "-0x8.000000000000000000000000E-38#100", Equal, ); test_helper(f64::NAN, 1, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, "NaN", "NaN", Equal); test_helper(f64::NAN, 100, "NaN", "NaN", Equal); test_helper(f64::INFINITY, 1, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 100, "Infinity", "Infinity", Equal); test_helper(f64::NEGATIVE_INFINITY, 1, "-Infinity", "-Infinity", Equal); test_helper(f64::NEGATIVE_INFINITY, 10, "-Infinity", "-Infinity", Equal); test_helper(f64::NEGATIVE_INFINITY, 100, "-Infinity", "-Infinity", Equal); test_helper(f64::ZERO, 1, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 100, "0.0", "0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 100, "-0.0", "-0x0.0", Equal); test_helper(f64::ONE, 1, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 10, "1.0", "0x1.000#10", Equal); test_helper( f64::ONE, 100, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test_helper(1.0f64 / 3.0, 1, "0.2", "0x0.4#1", Less); test_helper(1.0f64 / 3.0, 10, "0.3335", "0x0.556#10", Greater); test_helper( 1.0f64 / 3.0, 100, "0.3333333333333333148296162562474", "0x0.55555555555554000000000000#100", Equal, ); test_helper(std::f64::consts::PI, 1, "4.0", "0x4.0#1", Greater); test_helper(std::f64::consts::PI, 10, "3.141", "0x3.24#10", Less); test_helper( std::f64::consts::PI, 100, "3.141592653589793115997963468544", "0x3.243f6a8885a30000000000000#100", Equal, ); test_helper( f64::MIN_POSITIVE_SUBNORMAL, 1, "5.0e-324", "0x4.0E-269#1", Equal, ); test_helper( f64::MIN_POSITIVE_SUBNORMAL, 10, "4.94e-324", "0x4.00E-269#10", Equal, ); test_helper( f64::MIN_POSITIVE_SUBNORMAL, 100, "4.94065645841246544176568792868e-324", "0x4.0000000000000000000000000E-269#100", Equal, ); test_helper(f64::NEGATIVE_ONE, 1, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 10, "-1.0", "-0x1.000#10", Equal); test_helper( f64::NEGATIVE_ONE, 100, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test_helper(-1.0f64 / 3.0, 1, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f64 / 3.0, 10, "-0.3335", "-0x0.556#10", Less); test_helper( -1.0f64 / 3.0, 100, "-0.3333333333333333148296162562474", "-0x0.55555555555554000000000000#100", Equal, ); test_helper(-std::f64::consts::PI, 1, "-4.0", "-0x4.0#1", Less); test_helper(-std::f64::consts::PI, 10, "-3.141", "-0x3.24#10", Greater); test_helper( -std::f64::consts::PI, 100, "-3.141592653589793115997963468544", "-0x3.243f6a8885a30000000000000#100", Equal, ); test_helper( -f64::MIN_POSITIVE_SUBNORMAL, 1, "-5.0e-324", "-0x4.0E-269#1", Equal, ); test_helper( -f64::MIN_POSITIVE_SUBNORMAL, 10, "-4.94e-324", "-0x4.00E-269#10", Equal, ); test_helper( -f64::MIN_POSITIVE_SUBNORMAL, 100, "-4.94065645841246544176568792868e-324", "-0x4.0000000000000000000000000E-269#100", Equal, ); } fn from_primitive_float_prec_fail_helper() where Float: From, { assert_panic!(Float::from_primitive_float_prec(T::NAN, 0)); assert_panic!(Float::from_primitive_float_prec(T::INFINITY, 0)); assert_panic!(Float::from_primitive_float_prec(T::NEGATIVE_INFINITY, 0)); assert_panic!(Float::from_primitive_float_prec(T::ZERO, 0)); assert_panic!(Float::from_primitive_float_prec(T::NEGATIVE_ZERO, 0)); assert_panic!(Float::from_primitive_float_prec(T::ONE, 0)); assert_panic!(Float::from_primitive_float_prec(T::NEGATIVE_ONE, 0)); } #[test] fn from_primitive_float_prec_fail() { apply_fn_to_primitive_floats!(from_primitive_float_prec_fail_helper); } #[test] fn test_from_primitive_float_prec_round() { fn test_helper( u: T, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) where rug::Float: AssignRound, { let (x, o) = Float::from_primitive_float_prec_round(u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(max(1, u32::exact_from(prec)), u, rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(rug_o, out_o); } } test_helper(f32::NAN, 1, Floor, "NaN", "NaN", Equal); test_helper(f32::NAN, 1, Ceiling, "NaN", "NaN", Equal); test_helper(f32::NAN, 1, Down, "NaN", "NaN", Equal); test_helper(f32::NAN, 1, Up, "NaN", "NaN", Equal); test_helper(f32::NAN, 1, Nearest, "NaN", "NaN", Equal); test_helper(f32::NAN, 1, Exact, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Floor, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Ceiling, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Down, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Up, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Nearest, "NaN", "NaN", Equal); test_helper(f32::NAN, 10, Exact, "NaN", "NaN", Equal); test_helper(f32::INFINITY, 1, Floor, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 1, Ceiling, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 1, Down, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 1, Up, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 1, Nearest, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 1, Exact, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Floor, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Ceiling, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Down, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Up, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Nearest, "Infinity", "Infinity", Equal); test_helper(f32::INFINITY, 10, Exact, "Infinity", "Infinity", Equal); test_helper( f32::NEGATIVE_INFINITY, 1, Floor, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 1, Down, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 1, Up, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 1, Nearest, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 1, Exact, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Floor, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Ceiling, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Down, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Up, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Nearest, "-Infinity", "-Infinity", Equal, ); test_helper( f32::NEGATIVE_INFINITY, 10, Exact, "-Infinity", "-Infinity", Equal, ); test_helper(f32::ZERO, 1, Floor, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 1, Ceiling, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 1, Down, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 1, Up, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 1, Nearest, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 1, Exact, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Floor, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Ceiling, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Down, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Up, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Nearest, "0.0", "0x0.0", Equal); test_helper(f32::ZERO, 10, Exact, "0.0", "0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Floor, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Ceiling, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Down, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Up, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Nearest, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 1, Exact, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Floor, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Ceiling, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Down, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Up, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Nearest, "-0.0", "-0x0.0", Equal); test_helper(f32::NEGATIVE_ZERO, 10, Exact, "-0.0", "-0x0.0", Equal); test_helper(f32::ONE, 1, Floor, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 1, Ceiling, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 1, Down, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 1, Up, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 1, Nearest, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 1, Exact, "1.0", "0x1.0#1", Equal); test_helper(f32::ONE, 10, Floor, "1.0", "0x1.000#10", Equal); test_helper(f32::ONE, 10, Ceiling, "1.0", "0x1.000#10", Equal); test_helper(f32::ONE, 10, Down, "1.0", "0x1.000#10", Equal); test_helper(f32::ONE, 10, Up, "1.0", "0x1.000#10", Equal); test_helper(f32::ONE, 10, Nearest, "1.0", "0x1.000#10", Equal); test_helper(f32::ONE, 10, Exact, "1.0", "0x1.000#10", Equal); test_helper(1.0f32 / 3.0, 1, Floor, "0.2", "0x0.4#1", Less); test_helper(1.0f32 / 3.0, 1, Ceiling, "0.5", "0x0.8#1", Greater); test_helper(1.0f32 / 3.0, 1, Down, "0.2", "0x0.4#1", Less); test_helper(1.0f32 / 3.0, 1, Up, "0.5", "0x0.8#1", Greater); test_helper(1.0f32 / 3.0, 1, Nearest, "0.2", "0x0.4#1", Less); test_helper(1.0f32 / 3.0, 10, Floor, "0.333", "0x0.554#10", Less); test_helper(1.0f32 / 3.0, 10, Ceiling, "0.3335", "0x0.556#10", Greater); test_helper(1.0f32 / 3.0, 10, Down, "0.333", "0x0.554#10", Less); test_helper(1.0f32 / 3.0, 10, Up, "0.3335", "0x0.556#10", Greater); test_helper(1.0f32 / 3.0, 10, Nearest, "0.3335", "0x0.556#10", Greater); test_helper(std::f32::consts::PI, 1, Floor, "2.0", "0x2.0#1", Less); test_helper(std::f32::consts::PI, 1, Ceiling, "4.0", "0x4.0#1", Greater); test_helper(std::f32::consts::PI, 1, Down, "2.0", "0x2.0#1", Less); test_helper(std::f32::consts::PI, 1, Up, "4.0", "0x4.0#1", Greater); test_helper(std::f32::consts::PI, 1, Nearest, "4.0", "0x4.0#1", Greater); test_helper(std::f32::consts::PI, 10, Floor, "3.141", "0x3.24#10", Less); test_helper( std::f32::consts::PI, 10, Ceiling, "3.145", "0x3.25#10", Greater, ); test_helper(std::f32::consts::PI, 10, Down, "3.141", "0x3.24#10", Less); test_helper(std::f32::consts::PI, 10, Up, "3.145", "0x3.25#10", Greater); test_helper( std::f32::consts::PI, 10, Nearest, "3.141", "0x3.24#10", Less, ); test_helper(f32::MAX_FINITE, 1, Floor, "2.0e38", "0x8.0E+31#1", Less); test_helper( f32::MAX_FINITE, 1, Ceiling, "3.0e38", "0x1.0E+32#1", Greater, ); test_helper(f32::MAX_FINITE, 1, Down, "2.0e38", "0x8.0E+31#1", Less); test_helper(f32::MAX_FINITE, 1, Up, "3.0e38", "0x1.0E+32#1", Greater); test_helper( f32::MAX_FINITE, 1, Nearest, "3.0e38", "0x1.0E+32#1", Greater, ); test_helper(f32::MAX_FINITE, 10, Floor, "3.4e38", "0xf.fcE+31#10", Less); test_helper( f32::MAX_FINITE, 10, Ceiling, "3.403e38", "0x1.000E+32#10", Greater, ); test_helper(f32::MAX_FINITE, 10, Down, "3.4e38", "0xf.fcE+31#10", Less); test_helper( f32::MAX_FINITE, 10, Up, "3.403e38", "0x1.000E+32#10", Greater, ); test_helper( f32::MAX_FINITE, 10, Nearest, "3.403e38", "0x1.000E+32#10", Greater, ); test_helper(f32::NEGATIVE_ONE, 1, Floor, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 1, Down, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 1, Up, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 1, Nearest, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 1, Exact, "-1.0", "-0x1.0#1", Equal); test_helper(f32::NEGATIVE_ONE, 10, Floor, "-1.0", "-0x1.000#10", Equal); test_helper(f32::NEGATIVE_ONE, 10, Ceiling, "-1.0", "-0x1.000#10", Equal); test_helper(f32::NEGATIVE_ONE, 10, Down, "-1.0", "-0x1.000#10", Equal); test_helper(f32::NEGATIVE_ONE, 10, Up, "-1.0", "-0x1.000#10", Equal); test_helper(f32::NEGATIVE_ONE, 10, Nearest, "-1.0", "-0x1.000#10", Equal); test_helper(f32::NEGATIVE_ONE, 10, Exact, "-1.0", "-0x1.000#10", Equal); test_helper(-1.0f32 / 3.0, 1, Floor, "-0.5", "-0x0.8#1", Less); test_helper(-1.0f32 / 3.0, 1, Ceiling, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f32 / 3.0, 1, Down, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f32 / 3.0, 1, Up, "-0.5", "-0x0.8#1", Less); test_helper(-1.0f32 / 3.0, 1, Nearest, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f32 / 3.0, 10, Floor, "-0.3335", "-0x0.556#10", Less); test_helper(-1.0f32 / 3.0, 10, Ceiling, "-0.333", "-0x0.554#10", Greater); test_helper(-1.0f32 / 3.0, 10, Down, "-0.333", "-0x0.554#10", Greater); test_helper(-1.0f32 / 3.0, 10, Up, "-0.3335", "-0x0.556#10", Less); test_helper(-1.0f32 / 3.0, 10, Nearest, "-0.3335", "-0x0.556#10", Less); test_helper(-std::f32::consts::PI, 1, Floor, "-4.0", "-0x4.0#1", Less); test_helper( -std::f32::consts::PI, 1, Ceiling, "-2.0", "-0x2.0#1", Greater, ); test_helper(-std::f32::consts::PI, 1, Down, "-2.0", "-0x2.0#1", Greater); test_helper(-std::f32::consts::PI, 1, Up, "-4.0", "-0x4.0#1", Less); test_helper(-std::f32::consts::PI, 1, Nearest, "-4.0", "-0x4.0#1", Less); test_helper( -std::f32::consts::PI, 10, Floor, "-3.145", "-0x3.25#10", Less, ); test_helper( -std::f32::consts::PI, 10, Ceiling, "-3.141", "-0x3.24#10", Greater, ); test_helper( -std::f32::consts::PI, 10, Down, "-3.141", "-0x3.24#10", Greater, ); test_helper(-std::f32::consts::PI, 10, Up, "-3.145", "-0x3.25#10", Less); test_helper( -std::f32::consts::PI, 10, Nearest, "-3.141", "-0x3.24#10", Greater, ); test_helper(-f32::MAX_FINITE, 1, Floor, "-3.0e38", "-0x1.0E+32#1", Less); test_helper( -f32::MAX_FINITE, 1, Ceiling, "-2.0e38", "-0x8.0E+31#1", Greater, ); test_helper( -f32::MAX_FINITE, 1, Down, "-2.0e38", "-0x8.0E+31#1", Greater, ); test_helper(-f32::MAX_FINITE, 1, Up, "-3.0e38", "-0x1.0E+32#1", Less); test_helper( -f32::MAX_FINITE, 1, Nearest, "-3.0e38", "-0x1.0E+32#1", Less, ); test_helper( -f32::MAX_FINITE, 10, Floor, "-3.403e38", "-0x1.000E+32#10", Less, ); test_helper( -f32::MAX_FINITE, 10, Ceiling, "-3.4e38", "-0xf.fcE+31#10", Greater, ); test_helper( -f32::MAX_FINITE, 10, Down, "-3.4e38", "-0xf.fcE+31#10", Greater, ); test_helper( -f32::MAX_FINITE, 10, Up, "-3.403e38", "-0x1.000E+32#10", Less, ); test_helper( -f32::MAX_FINITE, 10, Nearest, "-3.403e38", "-0x1.000E+32#10", Less, ); test_helper(f64::NAN, 1, Floor, "NaN", "NaN", Equal); test_helper(f64::NAN, 1, Ceiling, "NaN", "NaN", Equal); test_helper(f64::NAN, 1, Down, "NaN", "NaN", Equal); test_helper(f64::NAN, 1, Up, "NaN", "NaN", Equal); test_helper(f64::NAN, 1, Nearest, "NaN", "NaN", Equal); test_helper(f64::NAN, 1, Exact, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Floor, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Ceiling, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Down, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Up, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Nearest, "NaN", "NaN", Equal); test_helper(f64::NAN, 10, Exact, "NaN", "NaN", Equal); test_helper(f64::INFINITY, 1, Floor, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 1, Ceiling, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 1, Down, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 1, Up, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 1, Nearest, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 1, Exact, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Floor, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Ceiling, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Down, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Up, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Nearest, "Infinity", "Infinity", Equal); test_helper(f64::INFINITY, 10, Exact, "Infinity", "Infinity", Equal); test_helper( f64::NEGATIVE_INFINITY, 1, Floor, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 1, Ceiling, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 1, Down, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 1, Up, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 1, Nearest, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 1, Exact, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Floor, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Ceiling, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Down, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Up, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Nearest, "-Infinity", "-Infinity", Equal, ); test_helper( f64::NEGATIVE_INFINITY, 10, Exact, "-Infinity", "-Infinity", Equal, ); test_helper(f64::ZERO, 1, Floor, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 1, Ceiling, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 1, Down, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 1, Up, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 1, Nearest, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 1, Exact, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Floor, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Ceiling, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Down, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Up, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Nearest, "0.0", "0x0.0", Equal); test_helper(f64::ZERO, 10, Exact, "0.0", "0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Floor, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Ceiling, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Down, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Up, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Nearest, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 1, Exact, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Floor, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Ceiling, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Down, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Up, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Nearest, "-0.0", "-0x0.0", Equal); test_helper(f64::NEGATIVE_ZERO, 10, Exact, "-0.0", "-0x0.0", Equal); test_helper(f64::ONE, 1, Floor, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 1, Ceiling, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 1, Down, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 1, Up, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 1, Nearest, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 1, Exact, "1.0", "0x1.0#1", Equal); test_helper(f64::ONE, 10, Floor, "1.0", "0x1.000#10", Equal); test_helper(f64::ONE, 10, Ceiling, "1.0", "0x1.000#10", Equal); test_helper(f64::ONE, 10, Down, "1.0", "0x1.000#10", Equal); test_helper(f64::ONE, 10, Up, "1.0", "0x1.000#10", Equal); test_helper(f64::ONE, 10, Nearest, "1.0", "0x1.000#10", Equal); test_helper(f64::ONE, 10, Exact, "1.0", "0x1.000#10", Equal); test_helper(1.0f64 / 3.0, 1, Floor, "0.2", "0x0.4#1", Less); test_helper(1.0f64 / 3.0, 1, Ceiling, "0.5", "0x0.8#1", Greater); test_helper(1.0f64 / 3.0, 1, Down, "0.2", "0x0.4#1", Less); test_helper(1.0f64 / 3.0, 1, Up, "0.5", "0x0.8#1", Greater); test_helper(1.0f64 / 3.0, 1, Nearest, "0.2", "0x0.4#1", Less); test_helper(1.0f64 / 3.0, 10, Floor, "0.333", "0x0.554#10", Less); test_helper(1.0f64 / 3.0, 10, Ceiling, "0.3335", "0x0.556#10", Greater); test_helper(1.0f64 / 3.0, 10, Down, "0.333", "0x0.554#10", Less); test_helper(1.0f64 / 3.0, 10, Up, "0.3335", "0x0.556#10", Greater); test_helper(1.0f64 / 3.0, 10, Nearest, "0.3335", "0x0.556#10", Greater); test_helper(std::f64::consts::PI, 1, Floor, "2.0", "0x2.0#1", Less); test_helper(std::f64::consts::PI, 1, Ceiling, "4.0", "0x4.0#1", Greater); test_helper(std::f64::consts::PI, 1, Down, "2.0", "0x2.0#1", Less); test_helper(std::f64::consts::PI, 1, Up, "4.0", "0x4.0#1", Greater); test_helper(std::f64::consts::PI, 1, Nearest, "4.0", "0x4.0#1", Greater); test_helper(std::f64::consts::PI, 10, Floor, "3.141", "0x3.24#10", Less); test_helper( std::f64::consts::PI, 10, Ceiling, "3.145", "0x3.25#10", Greater, ); test_helper(std::f64::consts::PI, 10, Down, "3.141", "0x3.24#10", Less); test_helper(std::f64::consts::PI, 10, Up, "3.145", "0x3.25#10", Greater); test_helper( std::f64::consts::PI, 10, Nearest, "3.141", "0x3.24#10", Less, ); test_helper(f64::MAX_FINITE, 1, Floor, "9.0e307", "0x8.0E+255#1", Less); test_helper( f64::MAX_FINITE, 1, Ceiling, "2.0e308", "0x1.0E+256#1", Greater, ); test_helper(f64::MAX_FINITE, 1, Down, "9.0e307", "0x8.0E+255#1", Less); test_helper(f64::MAX_FINITE, 1, Up, "2.0e308", "0x1.0E+256#1", Greater); test_helper( f64::MAX_FINITE, 1, Nearest, "2.0e308", "0x1.0E+256#1", Greater, ); test_helper( f64::MAX_FINITE, 10, Floor, "1.796e308", "0xf.fcE+255#10", Less, ); test_helper( f64::MAX_FINITE, 10, Ceiling, "1.798e308", "0x1.000E+256#10", Greater, ); test_helper( f64::MAX_FINITE, 10, Down, "1.796e308", "0xf.fcE+255#10", Less, ); test_helper( f64::MAX_FINITE, 10, Up, "1.798e308", "0x1.000E+256#10", Greater, ); test_helper( f64::MAX_FINITE, 10, Nearest, "1.798e308", "0x1.000E+256#10", Greater, ); test_helper(f64::NEGATIVE_ONE, 1, Floor, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 1, Down, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 1, Up, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 1, Nearest, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 1, Exact, "-1.0", "-0x1.0#1", Equal); test_helper(f64::NEGATIVE_ONE, 10, Floor, "-1.0", "-0x1.000#10", Equal); test_helper(f64::NEGATIVE_ONE, 10, Ceiling, "-1.0", "-0x1.000#10", Equal); test_helper(f64::NEGATIVE_ONE, 10, Down, "-1.0", "-0x1.000#10", Equal); test_helper(f64::NEGATIVE_ONE, 10, Up, "-1.0", "-0x1.000#10", Equal); test_helper(f64::NEGATIVE_ONE, 10, Nearest, "-1.0", "-0x1.000#10", Equal); test_helper(f64::NEGATIVE_ONE, 10, Exact, "-1.0", "-0x1.000#10", Equal); test_helper(-1.0f64 / 3.0, 1, Floor, "-0.5", "-0x0.8#1", Less); test_helper(-1.0f64 / 3.0, 1, Ceiling, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f64 / 3.0, 1, Down, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f64 / 3.0, 1, Up, "-0.5", "-0x0.8#1", Less); test_helper(-1.0f64 / 3.0, 1, Nearest, "-0.2", "-0x0.4#1", Greater); test_helper(-1.0f64 / 3.0, 10, Floor, "-0.3335", "-0x0.556#10", Less); test_helper(-1.0f64 / 3.0, 10, Ceiling, "-0.333", "-0x0.554#10", Greater); test_helper(-1.0f64 / 3.0, 10, Down, "-0.333", "-0x0.554#10", Greater); test_helper(-1.0f64 / 3.0, 10, Up, "-0.3335", "-0x0.556#10", Less); test_helper(-1.0f64 / 3.0, 10, Nearest, "-0.3335", "-0x0.556#10", Less); test_helper(-std::f64::consts::PI, 1, Floor, "-4.0", "-0x4.0#1", Less); test_helper( -std::f64::consts::PI, 1, Ceiling, "-2.0", "-0x2.0#1", Greater, ); test_helper(-std::f64::consts::PI, 1, Down, "-2.0", "-0x2.0#1", Greater); test_helper(-std::f64::consts::PI, 1, Up, "-4.0", "-0x4.0#1", Less); test_helper(-std::f64::consts::PI, 1, Nearest, "-4.0", "-0x4.0#1", Less); test_helper( -std::f64::consts::PI, 10, Floor, "-3.145", "-0x3.25#10", Less, ); test_helper( -std::f64::consts::PI, 10, Ceiling, "-3.141", "-0x3.24#10", Greater, ); test_helper( -std::f64::consts::PI, 10, Down, "-3.141", "-0x3.24#10", Greater, ); test_helper(-std::f64::consts::PI, 10, Up, "-3.145", "-0x3.25#10", Less); test_helper( -std::f64::consts::PI, 10, Nearest, "-3.141", "-0x3.24#10", Greater, ); test_helper( -f64::MAX_FINITE, 1, Floor, "-2.0e308", "-0x1.0E+256#1", Less, ); test_helper( -f64::MAX_FINITE, 1, Ceiling, "-9.0e307", "-0x8.0E+255#1", Greater, ); test_helper( -f64::MAX_FINITE, 1, Down, "-9.0e307", "-0x8.0E+255#1", Greater, ); test_helper(-f64::MAX_FINITE, 1, Up, "-2.0e308", "-0x1.0E+256#1", Less); test_helper( -f64::MAX_FINITE, 1, Nearest, "-2.0e308", "-0x1.0E+256#1", Less, ); test_helper( -f64::MAX_FINITE, 10, Floor, "-1.798e308", "-0x1.000E+256#10", Less, ); test_helper( -f64::MAX_FINITE, 10, Ceiling, "-1.796e308", "-0xf.fcE+255#10", Greater, ); test_helper( -f64::MAX_FINITE, 10, Down, "-1.796e308", "-0xf.fcE+255#10", Greater, ); test_helper( -f64::MAX_FINITE, 10, Up, "-1.798e308", "-0x1.000E+256#10", Less, ); test_helper( -f64::MAX_FINITE, 10, Nearest, "-1.798e308", "-0x1.000E+256#10", Less, ); } fn from_primitive_float_prec_round_fail_helper() where Float: From, { assert_panic!(Float::from_primitive_float_prec_round(T::NAN, 0, Floor)); assert_panic!(Float::from_primitive_float_prec_round( T::INFINITY, 0, Floor )); assert_panic!(Float::from_primitive_float_prec_round( T::NEGATIVE_INFINITY, 0, Floor )); assert_panic!(Float::from_primitive_float_prec_round(T::ZERO, 0, Floor)); assert_panic!(Float::from_primitive_float_prec_round( T::NEGATIVE_ZERO, 0, Floor )); assert_panic!(Float::from_primitive_float_prec_round(T::ONE, 0, Floor)); assert_panic!(Float::from_primitive_float_prec_round( T::NEGATIVE_ONE, 0, Floor )); assert_panic!(Float::from_primitive_float_prec_round( T::from(1.0f32) / T::from(3.0f32), 1, Exact )); assert_panic!(Float::from_primitive_float_prec_round( T::from(-1.0f32) / T::from(3.0f32), 1, Exact )); } #[test] fn from_primitive_float_prec_round_fail() { apply_fn_to_primitive_floats!(from_primitive_float_prec_round_fail_helper); } fn from_primitive_float_prec_properties_helper() where Float: PartialOrd, Rational: TryFrom, rug::Float: Assign, { primitive_float_unsigned_pair_gen_var_4::().test_properties(|(x, prec)| { let (float_x, o) = Float::from_primitive_float_prec(x, prec); assert!(float_x.is_valid()); assert_eq!( float_x.partial_cmp(&x), if x.is_nan() { None } else { Some(o) } ); let rug_x = rug::Float::with_val(u32::exact_from(prec), x); assert_eq!( ComparableFloatRef(&float_x), ComparableFloatRef(&Float::from(&rug_x)) ); if let Ok(r_x) = Rational::try_from(x) { let (float_x_alt, o_alt) = Float::from_rational_prec(r_x, prec); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); } assert_eq!( float_x.get_prec(), if x.is_finite() && x != T::ZERO { Some(prec) } else { None } ); let (float_x_alt, o_alt) = Float::from_primitive_float_prec(x, prec); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o_alt, o); let (float_x_alt, o_alt) = Float::from_primitive_float_prec_round(x, prec, Nearest); assert_eq!(ComparableFloat(float_x_alt), ComparableFloat(float_x)); assert_eq!(o_alt, o); }); } #[test] fn from_primitive_float_prec_properties() { apply_fn_to_primitive_floats!(from_primitive_float_prec_properties_helper); } fn from_primitive_float_prec_round_properties_helper() where Float: From + PartialOrd, Rational: PartialOrd + TryFrom, rug::Float: AssignRound, { primitive_float_unsigned_rounding_mode_triple_gen_var_3::().test_properties( |(x, prec, rm)| { let (float_x, o) = Float::from_primitive_float_prec_round(x, prec, rm); assert!(float_x.is_valid()); assert_eq!( float_x.partial_cmp(&x), if x.is_nan() { None } else { Some(o) } ); match (x >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), x, rm); let float_x_alt: Float = From::from(&rug_x); assert_eq!( ComparableFloatRef(&float_x), ComparableFloatRef(&float_x_alt) ); assert_eq!(rug_o, o); } if let Ok(r_x) = Rational::try_from(x) { let (float_x_alt, o_alt) = Float::from_rational_prec_round(r_x, prec, rm); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x.abs_negative_zero_ref()) ); assert_eq!(o_alt, o); } assert_eq!( float_x.get_prec(), if x.is_finite() && x != T::ZERO { Some(prec) } else { None } ); }, ); primitive_float_unsigned_pair_gen_var_4::().test_properties(|(x, prec)| { let floor = Float::from_primitive_float_prec_round(x, prec, Floor); if x.is_nan() { assert!(floor.0.is_nan()); } else { let or_floor: Result = TryFrom::try_from(&floor.0); if let Ok(r_floor) = or_floor { assert!(r_floor <= x); if r_floor != T::ZERO { let rulp: Rational = ExactFrom::exact_from(floor.0.ulp().unwrap()); assert!(r_floor + rulp > x); } let (floor_x_alt, o_alt) = Float::from_primitive_float_prec_round( x, prec, if x >= T::ZERO { Down } else { Up }, ); assert_eq!( ComparableFloatRef(&floor_x_alt), ComparableFloatRef(&floor.0) ); assert_eq!(o_alt, floor.1); } } let ceiling = Float::from_primitive_float_prec_round(x, prec, Ceiling); if x.is_nan() { assert!(ceiling.0.is_nan()); } else { let or_ceiling: Result = TryFrom::try_from(&ceiling.0); if let Ok(r_ceiling) = or_ceiling { assert!(r_ceiling >= x); if r_ceiling != T::ZERO { let rulp: Rational = ExactFrom::exact_from(ceiling.0.ulp().unwrap()); assert!(r_ceiling - rulp < x); } let (ceiling_x_alt, o_alt) = Float::from_primitive_float_prec_round( x, prec, if x >= T::ZERO { Up } else { Down }, ); assert_eq!( ComparableFloatRef(&ceiling_x_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(o_alt, ceiling.1); } } let nearest = Float::from_primitive_float_prec_round(x, prec, Nearest); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); let or_nearest: Result = TryFrom::try_from(&nearest.0); if let Ok(r_nearest) = or_nearest && r_nearest != T::ZERO { let rulp: Rational = ExactFrom::exact_from(nearest.0.ulp().unwrap()); assert!((r_nearest - Rational::exact_from(x)).le_abs(&(rulp >> 1))); } }); } #[test] fn from_primitive_float_prec_round_properties() { apply_fn_to_primitive_floats!(from_primitive_float_prec_round_properties_helper); } #[allow(clippy::type_repetition_in_bounds)] fn from_primitive_float_properties_helper() where Float: From, rug::Float: Assign, for<'a> T: ExactFrom<&'a Float>, { primitive_float_gen::().test_properties(|x| { let float_x = Float::from(x); assert!(float_x.is_valid()); let expected_prec = if !x.is_finite() || x == T::ZERO { None } else { let n = x.integer_mantissa(); Some(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }; let rug_x = rug::Float::with_val(expected_prec.map_or(1, u32::exact_from), x); assert_eq!( ComparableFloatRef(&float_x), ComparableFloatRef(&From::<&rug::Float>::from(&rug_x)) ); assert_eq!(float_x.get_prec(), expected_prec); assert_eq!(NiceFloat(T::exact_from(&float_x)), NiceFloat(x)); let (f, o) = Float::from_primitive_float_prec(x, expected_prec.unwrap_or(1)); assert_eq!(ComparableFloat(f), ComparableFloat(float_x)); assert_eq!(o, Equal); }); } #[test] fn from_primitive_float_properties() { apply_fn_to_primitive_floats!(from_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, signed_pair_gen_var_2, signed_unsigned_pair_gen_var_20, unsigned_gen, unsigned_pair_gen_var_32, unsigned_signed_pair_gen_var_1, }; use malachite_float::test_util::common::{rug_round_try_from_rounding_mode, to_hex_string}; use malachite_float::test_util::generators::*; use malachite_float::{ComparableFloat, ComparableFloatRef, Float}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_q::Rational; use rug::Assign; use rug::float::Round; use rug::ops::AssignRound; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[test] fn test_from_primitive_int() { fn test_helper(u: T, out: &str, out_hex: &str) where Float: From, rug::Float: Assign, Limb: WrappingFrom, SignedLimb: WrappingFrom, { let x = Float::from(u); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); let rug_x = rug::Float::with_val( if u == T::ZERO { 1 } else { u32::exact_from(u.significant_bits() - TrailingZeros::trailing_zeros(u)) }, u, ); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); if T::NAME == Limb::NAME { let x_alt = Float::const_from_unsigned(Limb::wrapping_from(u)); assert!(x_alt.is_valid()); assert_eq!(ComparableFloatRef(&x_alt), ComparableFloatRef(&x)); } if T::NAME == SignedLimb::NAME { let x_alt = Float::const_from_signed(SignedLimb::wrapping_from(u)); assert!(x_alt.is_valid()); assert_eq!(ComparableFloat(x_alt), ComparableFloat(x)); } } fn test_helper_ui() where Float: From, rug::Float: Assign, Limb: WrappingFrom, SignedLimb: WrappingFrom, { test_helper(T::ZERO, "0.0", "0x0.0"); test_helper(T::ONE, "1.0", "0x1.0#1"); test_helper(T::exact_from(123u8), "123.0", "0x7b.0#7"); } apply_fn_to_primitive_ints!(test_helper_ui); test_helper(1000000000000u64, "1.0e12", "0xe.8d4a51E+9#28"); fn test_helper_i() where Float: From, rug::Float: Assign, Limb: WrappingFrom, SignedLimb: WrappingFrom, { test_helper(T::NEGATIVE_ONE, "-1.0", "-0x1.0#1"); test_helper(T::from(-123i8), "-123.0", "-0x7b.0#7"); } apply_fn_to_signeds!(test_helper_i); test_helper(-1000000000000i64, "-1.0e12", "-0xe.8d4a51E+9#28"); } #[test] fn test_from_primitive_int_prec() { fn test_helper_u( u: T, prec: u64, out: &str, out_hex: &str, out_o: Ordering, ) where Natural: From, rug::Float: Assign, { let (x, o) = Float::from_unsigned_prec(u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), u); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } fn test_helper_u2() where Natural: From, rug::Float: Assign, { test_helper_u(T::ZERO, 1, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, "0.0", "0x0.0", Equal); test_helper_u(T::ONE, 1, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 10, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 20, "1.0", "0x1.00000#20", Equal); test_helper_u(T::from(123u8), 1, "1.0e2", "0x8.0E+1#1", Greater); test_helper_u(T::from(123u8), 10, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 20, "123.0", "0x7b.0000#20", Equal); } apply_fn_to_unsigneds!(test_helper_u2); test_helper_u(1000000000000u64, 1, "1.0e12", "0x1.0E+10#1", Greater); test_helper_u(1000000000000u64, 10, "9.997e11", "0xe.8cE+9#10", Less); test_helper_u(1000000000000u64, 20, "9.999997e11", "0xe.8d4aE+9#20", Less); fn test_helper_i(u: T, prec: u64, out: &str, out_hex: &str, out_o: Ordering) where Integer: From, rug::Float: Assign, { let (x, o) = Float::from_signed_prec(u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), u); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } fn test_helper_i2() where Integer: From, rug::Float: Assign, { test_helper_i(T::ZERO, 1, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, "0.0", "0x0.0", Equal); test_helper_i(T::ONE, 1, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 10, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 20, "1.0", "0x1.00000#20", Equal); test_helper_i(T::from(123i8), 1, "1.0e2", "0x8.0E+1#1", Greater); test_helper_i(T::from(123i8), 10, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 20, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 1, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 10, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 20, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::from(-123i8), 1, "-1.0e2", "-0x8.0E+1#1", Less); test_helper_i(T::from(-123i8), 10, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 20, "-123.0", "-0x7b.0000#20", Equal); } apply_fn_to_signeds!(test_helper_i2); test_helper_i(1000000000000i64, 1, "1.0e12", "0x1.0E+10#1", Greater); test_helper_i(1000000000000i64, 10, "9.997e11", "0xe.8cE+9#10", Less); test_helper_i(1000000000000i64, 20, "9.999997e11", "0xe.8d4aE+9#20", Less); test_helper_i(-1000000000000i64, 1, "-1.0e12", "-0x1.0E+10#1", Less); test_helper_i(-1000000000000i64, 10, "-9.997e11", "-0xe.8cE+9#10", Greater); test_helper_i( -1000000000000i64, 20, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); } fn from_unsigned_prec_fail_helper() where Natural: From, { assert_panic!(Float::from_unsigned_prec(T::ZERO, 0)); assert_panic!(Float::from_unsigned_prec(T::ONE, 0)); } fn from_signed_prec_fail_helper() where Integer: From, { assert_panic!(Float::from_signed_prec(T::ZERO, 0)); assert_panic!(Float::from_signed_prec(T::ONE, 0)); assert_panic!(Float::from_signed_prec(T::NEGATIVE_ONE, 0)); } #[test] fn from_primitive_int_prec_fail() { apply_fn_to_unsigneds!(from_unsigned_prec_fail_helper); apply_fn_to_signeds!(from_signed_prec_fail_helper); } #[test] fn test_from_primitive_int_prec_round() { fn test_helper_u( u: T, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) where Natural: From, rug::Float: AssignRound, { let (x, o) = Float::from_unsigned_prec_round(u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), u, rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(rug_o, out_o); } } fn test_helper_u2() where Natural: From, rug::Float: AssignRound, { test_helper_u(T::ZERO, 1, Floor, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 1, Ceiling, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 1, Down, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 1, Up, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 1, Nearest, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 1, Exact, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Floor, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Ceiling, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Down, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Up, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Nearest, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 10, Exact, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Floor, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Ceiling, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Down, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Up, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Nearest, "0.0", "0x0.0", Equal); test_helper_u(T::ZERO, 20, Exact, "0.0", "0x0.0", Equal); test_helper_u(T::ONE, 1, Floor, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 1, Ceiling, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 1, Down, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 1, Up, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 1, Nearest, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 1, Exact, "1.0", "0x1.0#1", Equal); test_helper_u(T::ONE, 10, Floor, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 10, Ceiling, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 10, Down, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 10, Up, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 10, Nearest, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 10, Exact, "1.0", "0x1.000#10", Equal); test_helper_u(T::ONE, 20, Floor, "1.0", "0x1.00000#20", Equal); test_helper_u(T::ONE, 20, Ceiling, "1.0", "0x1.00000#20", Equal); test_helper_u(T::ONE, 20, Down, "1.0", "0x1.00000#20", Equal); test_helper_u(T::ONE, 20, Up, "1.0", "0x1.00000#20", Equal); test_helper_u(T::ONE, 20, Nearest, "1.0", "0x1.00000#20", Equal); test_helper_u(T::ONE, 20, Exact, "1.0", "0x1.00000#20", Equal); test_helper_u(T::from(123u8), 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test_helper_u(T::from(123u8), 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater); test_helper_u(T::from(123u8), 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_helper_u(T::from(123u8), 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test_helper_u(T::from(123u8), 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater); test_helper_u(T::from(123u8), 10, Floor, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 10, Ceiling, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 10, Down, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 10, Up, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 10, Nearest, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 10, Exact, "123.0", "0x7b.0#10", Equal); test_helper_u(T::from(123u8), 20, Floor, "123.0", "0x7b.0000#20", Equal); test_helper_u(T::from(123u8), 20, Ceiling, "123.0", "0x7b.0000#20", Equal); test_helper_u(T::from(123u8), 20, Down, "123.0", "0x7b.0000#20", Equal); test_helper_u(T::from(123u8), 20, Up, "123.0", "0x7b.0000#20", Equal); test_helper_u(T::from(123u8), 20, Nearest, "123.0", "0x7b.0000#20", Equal); test_helper_u(T::from(123u8), 20, Exact, "123.0", "0x7b.0000#20", Equal); } apply_fn_to_unsigneds!(test_helper_u2); test_helper_u(1000000000000u64, 1, Floor, "5.0e11", "0x8.0E+9#1", Less); test_helper_u( 1000000000000u64, 1, Ceiling, "1.0e12", "0x1.0E+10#1", Greater, ); test_helper_u(1000000000000u64, 1, Down, "5.0e11", "0x8.0E+9#1", Less); test_helper_u(1000000000000u64, 1, Up, "1.0e12", "0x1.0E+10#1", Greater); test_helper_u( 1000000000000u64, 1, Nearest, "1.0e12", "0x1.0E+10#1", Greater, ); test_helper_u( 1000000000000u64, 10, Floor, "9.997e11", "0xe.8cE+9#10", Less, ); test_helper_u( 1000000000000u64, 10, Ceiling, "1.001e12", "0xe.90E+9#10", Greater, ); test_helper_u(1000000000000u64, 10, Down, "9.997e11", "0xe.8cE+9#10", Less); test_helper_u( 1000000000000u64, 10, Up, "1.001e12", "0xe.90E+9#10", Greater, ); test_helper_u( 1000000000000u64, 10, Nearest, "9.997e11", "0xe.8cE+9#10", Less, ); test_helper_u( 1000000000000u64, 20, Floor, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test_helper_u( 1000000000000u64, 20, Ceiling, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test_helper_u( 1000000000000u64, 20, Down, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test_helper_u( 1000000000000u64, 20, Up, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test_helper_u( 1000000000000u64, 20, Nearest, "9.999997e11", "0xe.8d4aE+9#20", Less, ); fn test_helper_i( u: T, prec: u64, rm: RoundingMode, out: &str, out_hex: &str, out_o: Ordering, ) where Integer: From, rug::Float: AssignRound, { let (x, o) = Float::from_signed_prec_round(u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), u, rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(rug_o, out_o); } } fn test_helper_i2() where Integer: From, rug::Float: AssignRound, { test_helper_i(T::ZERO, 1, Floor, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 1, Ceiling, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 1, Down, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 1, Up, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 1, Nearest, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 1, Exact, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Floor, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Ceiling, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Down, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Up, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Nearest, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 10, Exact, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Floor, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Ceiling, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Down, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Up, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Nearest, "0.0", "0x0.0", Equal); test_helper_i(T::ZERO, 20, Exact, "0.0", "0x0.0", Equal); test_helper_i(T::ONE, 1, Floor, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 1, Ceiling, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 1, Down, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 1, Up, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 1, Nearest, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 1, Exact, "1.0", "0x1.0#1", Equal); test_helper_i(T::ONE, 10, Floor, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 10, Ceiling, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 10, Down, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 10, Up, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 10, Nearest, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 10, Exact, "1.0", "0x1.000#10", Equal); test_helper_i(T::ONE, 20, Floor, "1.0", "0x1.00000#20", Equal); test_helper_i(T::ONE, 20, Ceiling, "1.0", "0x1.00000#20", Equal); test_helper_i(T::ONE, 20, Down, "1.0", "0x1.00000#20", Equal); test_helper_i(T::ONE, 20, Up, "1.0", "0x1.00000#20", Equal); test_helper_i(T::ONE, 20, Nearest, "1.0", "0x1.00000#20", Equal); test_helper_i(T::ONE, 20, Exact, "1.0", "0x1.00000#20", Equal); test_helper_i(T::from(123i8), 1, Floor, "6.0e1", "0x4.0E+1#1", Less); test_helper_i(T::from(123i8), 1, Ceiling, "1.0e2", "0x8.0E+1#1", Greater); test_helper_i(T::from(123i8), 1, Down, "6.0e1", "0x4.0E+1#1", Less); test_helper_i(T::from(123i8), 1, Up, "1.0e2", "0x8.0E+1#1", Greater); test_helper_i(T::from(123i8), 1, Nearest, "1.0e2", "0x8.0E+1#1", Greater); test_helper_i(T::from(123i8), 10, Floor, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 10, Ceiling, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 10, Down, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 10, Up, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 10, Nearest, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 10, Exact, "123.0", "0x7b.0#10", Equal); test_helper_i(T::from(123i8), 20, Floor, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::from(123i8), 20, Ceiling, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::from(123i8), 20, Down, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::from(123i8), 20, Up, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::from(123i8), 20, Nearest, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::from(123i8), 20, Exact, "123.0", "0x7b.0000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Floor, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Down, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Up, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Nearest, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 1, Exact, "-1.0", "-0x1.0#1", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Floor, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Ceiling, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Down, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Up, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Nearest, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 10, Exact, "-1.0", "-0x1.000#10", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Floor, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Ceiling, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Down, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Up, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Nearest, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::NEGATIVE_ONE, 20, Exact, "-1.0", "-0x1.00000#20", Equal); test_helper_i(T::from(-123i8), 1, Floor, "-1.0e2", "-0x8.0E+1#1", Less); test_helper_i( T::from(-123i8), 1, Ceiling, "-6.0e1", "-0x4.0E+1#1", Greater, ); test_helper_i(T::from(-123i8), 1, Down, "-6.0e1", "-0x4.0E+1#1", Greater); test_helper_i(T::from(-123i8), 1, Up, "-1.0e2", "-0x8.0E+1#1", Less); test_helper_i(T::from(-123i8), 1, Nearest, "-1.0e2", "-0x8.0E+1#1", Less); test_helper_i(T::from(-123i8), 10, Floor, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 10, Ceiling, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 10, Down, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 10, Up, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 10, Nearest, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 10, Exact, "-123.0", "-0x7b.0#10", Equal); test_helper_i(T::from(-123i8), 20, Floor, "-123.0", "-0x7b.0000#20", Equal); test_helper_i( T::from(-123i8), 20, Ceiling, "-123.0", "-0x7b.0000#20", Equal, ); test_helper_i(T::from(-123i8), 20, Down, "-123.0", "-0x7b.0000#20", Equal); test_helper_i(T::from(-123i8), 20, Up, "-123.0", "-0x7b.0000#20", Equal); test_helper_i( T::from(-123i8), 20, Nearest, "-123.0", "-0x7b.0000#20", Equal, ); test_helper_i(T::from(-123i8), 20, Exact, "-123.0", "-0x7b.0000#20", Equal); } apply_fn_to_signeds!(test_helper_i2); test_helper_i(1000000000000i64, 1, Floor, "5.0e11", "0x8.0E+9#1", Less); test_helper_i( 1000000000000i64, 1, Ceiling, "1.0e12", "0x1.0E+10#1", Greater, ); test_helper_i(1000000000000i64, 1, Down, "5.0e11", "0x8.0E+9#1", Less); test_helper_i(1000000000000i64, 1, Up, "1.0e12", "0x1.0E+10#1", Greater); test_helper_i( 1000000000000i64, 1, Nearest, "1.0e12", "0x1.0E+10#1", Greater, ); test_helper_i( 1000000000000i64, 10, Floor, "9.997e11", "0xe.8cE+9#10", Less, ); test_helper_i( 1000000000000i64, 10, Ceiling, "1.001e12", "0xe.90E+9#10", Greater, ); test_helper_i(1000000000000i64, 10, Down, "9.997e11", "0xe.8cE+9#10", Less); test_helper_i( 1000000000000i64, 10, Up, "1.001e12", "0xe.90E+9#10", Greater, ); test_helper_i( 1000000000000i64, 10, Nearest, "9.997e11", "0xe.8cE+9#10", Less, ); test_helper_i( 1000000000000i64, 20, Floor, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test_helper_i( 1000000000000i64, 20, Ceiling, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test_helper_i( 1000000000000i64, 20, Down, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test_helper_i( 1000000000000i64, 20, Up, "1.000001e12", "0xe.8d4bE+9#20", Greater, ); test_helper_i( 1000000000000i64, 20, Nearest, "9.999997e11", "0xe.8d4aE+9#20", Less, ); test_helper_i(-1000000000000i64, 1, Floor, "-1.0e12", "-0x1.0E+10#1", Less); test_helper_i( -1000000000000i64, 1, Ceiling, "-5.0e11", "-0x8.0E+9#1", Greater, ); test_helper_i( -1000000000000i64, 1, Down, "-5.0e11", "-0x8.0E+9#1", Greater, ); test_helper_i(-1000000000000i64, 1, Up, "-1.0e12", "-0x1.0E+10#1", Less); test_helper_i( -1000000000000i64, 1, Nearest, "-1.0e12", "-0x1.0E+10#1", Less, ); test_helper_i( -1000000000000i64, 10, Floor, "-1.001e12", "-0xe.90E+9#10", Less, ); test_helper_i( -1000000000000i64, 10, Ceiling, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test_helper_i( -1000000000000i64, 10, Down, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test_helper_i( -1000000000000i64, 10, Up, "-1.001e12", "-0xe.90E+9#10", Less, ); test_helper_i( -1000000000000i64, 10, Nearest, "-9.997e11", "-0xe.8cE+9#10", Greater, ); test_helper_i( -1000000000000i64, 20, Floor, "-1.000001e12", "-0xe.8d4bE+9#20", Less, ); test_helper_i( -1000000000000i64, 20, Ceiling, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); test_helper_i( -1000000000000i64, 20, Down, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); test_helper_i( -1000000000000i64, 20, Up, "-1.000001e12", "-0xe.8d4bE+9#20", Less, ); test_helper_i( -1000000000000i64, 20, Nearest, "-9.999997e11", "-0xe.8d4aE+9#20", Greater, ); } fn from_unsigned_prec_round_fail_helper() where Natural: From, { assert_panic!(Float::from_unsigned_prec_round(T::ZERO, 0, Floor)); assert_panic!(Float::from_unsigned_prec_round(T::ONE, 0, Floor)); assert_panic!(Float::from_unsigned_prec_round(T::from(123u8), 1, Exact)); } fn from_signed_prec_round_fail_helper() where Integer: From, { assert_panic!(Float::from_signed_prec_round(T::ZERO, 0, Floor)); assert_panic!(Float::from_signed_prec_round(T::ONE, 0, Floor)); assert_panic!(Float::from_signed_prec_round(T::from(123i8), 1, Exact)); assert_panic!(Float::from_signed_prec_round(T::NEGATIVE_ONE, 0, Floor)); assert_panic!(Float::from_signed_prec_round(T::from(-123i8), 1, Exact)); } #[test] fn from_primitive_int_prec_round_fail() { apply_fn_to_unsigneds!(from_unsigned_prec_round_fail_helper); apply_fn_to_signeds!(from_signed_prec_round_fail_helper); } #[test] fn test_const_from_unsigned_times_power_of_2() { fn test_helper(u: Limb, pow: i32, out: &str, out_hex: &str) { let x = Float::const_from_unsigned_times_power_of_2(u, pow); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } test_helper(0, 0, "0.0", "0x0.0"); test_helper(0, 10, "0.0", "0x0.0"); test_helper(0, -10, "0.0", "0x0.0"); test_helper(1, 0, "1.0", "0x1.0#1"); test_helper(1, 10, "1.0e3", "0x4.0E+2#1"); test_helper(1, -10, "0.001", "0x0.004#1"); test_helper(1, 1073741822, "too_big", "0x4.0E+268435455#1"); test_helper(1, -1073741824, "too_small", "0x1.0E-268435456#1"); #[cfg(not(feature = "32_bit_limbs"))] { test_helper( 884279719003555, -48, "3.141592653589793", "0x3.243f6a8885a3#50", ); } } #[test] fn const_from_unsigned_times_power_of_2_fail() { assert_panic!(Float::const_from_unsigned_times_power_of_2(1, 1073741823)); assert_panic!(Float::const_from_unsigned_times_power_of_2(1, -1073741825)); } #[test] fn test_const_from_signed_times_power_of_2() { fn test_helper(u: SignedLimb, pow: i32, out: &str, out_hex: &str) { let x = Float::const_from_signed_times_power_of_2(u, pow); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); } test_helper(0, 0, "0.0", "0x0.0"); test_helper(0, 10, "0.0", "0x0.0"); test_helper(0, -10, "0.0", "0x0.0"); test_helper(1, 0, "1.0", "0x1.0#1"); test_helper(1, 10, "1.0e3", "0x4.0E+2#1"); test_helper(1, -10, "0.001", "0x0.004#1"); test_helper(-1, 0, "-1.0", "-0x1.0#1"); test_helper(-1, 10, "-1.0e3", "-0x4.0E+2#1"); test_helper(-1, -10, "-0.001", "-0x0.004#1"); test_helper(1, 1073741822, "too_big", "0x4.0E+268435455#1"); test_helper(1, -1073741824, "too_small", "0x1.0E-268435456#1"); #[cfg(not(feature = "32_bit_limbs"))] { test_helper( 884279719003555, -48, "3.141592653589793", "0x3.243f6a8885a3#50", ); test_helper( -884279719003555, -48, "-3.141592653589793", "-0x3.243f6a8885a3#50", ); } } #[test] fn const_from_signed_times_power_of_2_fail() { assert_panic!(Float::const_from_signed_times_power_of_2(1, 1073741823)); assert_panic!(Float::const_from_signed_times_power_of_2(1, -1073741825)); } #[allow(clippy::type_repetition_in_bounds)] fn from_primitive_int_properties_helper_unsigned() where Float: From, rug::Float: Assign, Natural: From + PartialEq, for<'a> T: ExactFrom<&'a Float>, Limb: WrappingFrom, { unsigned_gen::().test_properties(|n| { let float_n = Float::from(n); assert!(float_n.is_valid()); if T::WIDTH == Limb::WIDTH { let n_alt = Float::const_from_unsigned(Limb::wrapping_from(n)); assert!(n_alt.is_valid()); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); let n_alt = Float::const_from_unsigned_times_power_of_2(Limb::wrapping_from(n), 0); assert!(n_alt.is_valid()); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); } let expected_prec = if n == T::ZERO { None } else { Some(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }; let rug_n = rug::Float::with_val(expected_prec.map_or(1, u32::exact_from), n); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&From::<&rug::Float>::from(&rug_n)) ); let n_alt: Float = ExactFrom::exact_from(Natural::exact_from(n)); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); assert_eq!(float_n.get_prec(), expected_prec); assert_eq!(T::exact_from(&float_n), n); let (f, o) = Float::from_unsigned_prec(n, expected_prec.unwrap_or(1)); assert_eq!(ComparableFloat(f), ComparableFloat(float_n)); assert_eq!(o, Equal); }); } #[allow(clippy::type_repetition_in_bounds)] fn from_primitive_int_properties_helper_signed() where Float: From, rug::Float: Assign, Integer: From + PartialEq, for<'a> T: ExactFrom<&'a Float>, SignedLimb: WrappingFrom, { signed_gen::().test_properties(|n| { let float_n = Float::from(n); assert!(float_n.is_valid()); if T::WIDTH == SignedLimb::WIDTH { let n_alt = Float::const_from_signed(SignedLimb::wrapping_from(n)); assert!(n_alt.is_valid()); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); let n_alt = Float::const_from_signed_times_power_of_2(SignedLimb::wrapping_from(n), 0); assert!(n_alt.is_valid()); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); } let expected_prec = if n == T::ZERO { None } else { Some(n.significant_bits() - TrailingZeros::trailing_zeros(n)) }; let rug_n = rug::Float::with_val(expected_prec.map_or(1, u32::exact_from), n); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&From::<&rug::Float>::from(&rug_n)) ); let n_alt: Float = ExactFrom::exact_from(Integer::from(n)); assert_eq!(ComparableFloatRef(&n_alt), ComparableFloatRef(&float_n)); assert_eq!(float_n.get_prec(), expected_prec); assert_eq!(T::exact_from(&float_n), n); let (f, o) = Float::from_signed_prec(n, expected_prec.unwrap_or(1)); assert_eq!(ComparableFloat(f), ComparableFloat(float_n)); assert_eq!(o, Equal); }); } #[test] fn from_primitive_int_properties() { apply_fn_to_unsigneds!(from_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(from_primitive_int_properties_helper_signed); } fn from_primitive_int_prec_properties_helper_unsigned() where Natural: From, Float: PartialOrd, rug::Float: Assign, { unsigned_pair_gen_var_32::().test_properties(|(n, prec)| { let (float_n, o) = Float::from_unsigned_prec(n, prec); assert!(float_n.is_valid()); assert_eq!(float_n.partial_cmp(&n), Some(o)); let rug_n = rug::Float::with_val(u32::exact_from(prec), n); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); let (float_n_alt, o_alt) = Float::from_natural_prec(Natural::from(n), prec); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == T::ZERO { None } else { Some(prec) } ); }); } fn from_primitive_int_prec_properties_helper_signed() where Integer: From, Float: PartialOrd, rug::Float: Assign, { signed_unsigned_pair_gen_var_20::().test_properties(|(n, prec)| { let (float_n, o) = Float::from_signed_prec(n, prec); assert!(float_n.is_valid()); assert_eq!(float_n.partial_cmp(&n), Some(o)); let rug_n = rug::Float::with_val(u32::exact_from(prec), n); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); let (float_n_alt, o_alt) = Float::from_integer_prec(Integer::from(n), prec); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == T::ZERO { None } else { Some(prec) } ); }); } #[test] fn from_primitive_int_prec_properties() { apply_fn_to_unsigneds!(from_primitive_int_prec_properties_helper_unsigned); apply_fn_to_signeds!(from_primitive_int_prec_properties_helper_signed); } fn from_primitive_int_prec_round_properties_helper_unsigned() where Natural: From, Float: PartialOrd, Rational: From + PartialOrd, rug::Float: AssignRound, { unsigned_unsigned_rounding_mode_triple_gen_var_5::().test_properties(|(n, prec, rm)| { let (float_n, o) = Float::from_unsigned_prec_round(n, prec, rm); assert!(float_n.is_valid()); assert_eq!(float_n.partial_cmp(&n), Some(o)); match rm { Floor | Down => { assert_ne!(o, Greater); } Ceiling | Up => { assert_ne!(o, Less); } Exact => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_n, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), n, rm); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); assert_eq!(rug_o, o); } let (float_n_alt, o_alt) = Float::from_natural_prec_round(Natural::from(n), prec, rm); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == T::ZERO { None } else { Some(prec) } ); }); unsigned_pair_gen_var_32::().test_properties(|(n, prec)| { let floor = Float::from_unsigned_prec_round(n, prec, Floor); let r_floor = Rational::exact_from(&floor.0); assert!(r_floor <= n); if r_floor != T::ZERO { assert!(r_floor + Rational::exact_from(floor.0.ulp().unwrap()) > n); } let (floor_alt, floor_o_alt) = Float::from_unsigned_prec_round(n, prec, Down); assert_eq!(ComparableFloatRef(&floor_alt), ComparableFloatRef(&floor.0)); assert_eq!(floor_o_alt, floor.1); let ceiling = Float::from_unsigned_prec_round(n, prec, Ceiling); let r_ceiling = Rational::exact_from(&ceiling.0); assert!(r_ceiling >= n); if r_ceiling != T::ZERO { assert!(r_ceiling - Rational::exact_from(ceiling.0.ulp().unwrap()) < n); } let (ceiling_alt, ceiling_o_alt) = Float::from_unsigned_prec_round(n, prec, Up); assert_eq!( ComparableFloatRef(&ceiling_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(ceiling_o_alt, ceiling.1); let nearest = Float::from_unsigned_prec_round(n, prec, Nearest); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); let r_nearest = Rational::exact_from(&nearest.0); if r_nearest != T::ZERO { assert!( (r_nearest - Rational::from(n)) .le_abs(&(Rational::exact_from(nearest.0.ulp().unwrap()) >> 1)) ); } }); } fn from_primitive_int_prec_round_properties_helper_signed() where Integer: From, Float: PartialOrd, Rational: From + PartialOrd, rug::Float: AssignRound, { signed_unsigned_rounding_mode_triple_gen_var_3::().test_properties(|(n, prec, rm)| { let (float_n, o) = Float::from_signed_prec_round(n, prec, rm); assert!(float_n.is_valid()); assert_eq!(float_n.partial_cmp(&n), Some(o)); match (n >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_n, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), n, rm); assert_eq!( ComparableFloatRef(&float_n), ComparableFloatRef(&Float::from(&rug_n)) ); assert_eq!(rug_o, o); } let (float_n_alt, o_alt) = Float::from_integer_prec_round(Integer::from(n), prec, rm); assert_eq!( ComparableFloatRef(&float_n_alt), ComparableFloatRef(&float_n) ); assert_eq!(o_alt, o); assert_eq!( float_n.get_prec(), if n == T::ZERO { None } else { Some(prec) } ); }); signed_unsigned_pair_gen_var_20::().test_properties(|(n, prec)| { let floor = Float::from_signed_prec_round(n, prec, Floor); let r_floor = Rational::exact_from(&floor.0); assert!(r_floor <= n); if r_floor != T::ZERO { assert!(r_floor + Rational::exact_from(floor.0.ulp().unwrap()) > n); } let (floor_n_alt, o_alt) = Float::from_signed_prec_round(n, prec, if n >= T::ZERO { Down } else { Up }); assert_eq!( ComparableFloatRef(&floor_n_alt), ComparableFloatRef(&floor.0) ); assert_eq!(o_alt, floor.1); let ceiling = Float::from_signed_prec_round(n, prec, Ceiling); let r_ceiling = Rational::exact_from(&ceiling.0); assert!(r_ceiling >= n); if r_ceiling != T::ZERO { assert!(r_ceiling - Rational::exact_from(ceiling.0.ulp().unwrap()) < n); } let (ceiling_n_alt, o_alt) = Float::from_signed_prec_round(n, prec, if n >= T::ZERO { Up } else { Down }); assert_eq!( ComparableFloatRef(&ceiling_n_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(o_alt, ceiling.1); let nearest = Float::from_signed_prec_round(n, prec, Nearest); let r_nearest = Rational::exact_from(&nearest.0); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); if r_nearest != T::ZERO { assert!( (r_nearest - Rational::from(n)) .le_abs(&(Rational::exact_from(nearest.0.ulp().unwrap()) >> 1)) ); } }); } #[test] fn from_primitive_int_prec_round_properties() { apply_fn_to_unsigneds!(from_primitive_int_prec_round_properties_helper_unsigned); apply_fn_to_signeds!(from_primitive_int_prec_round_properties_helper_signed); } #[test] fn const_from_unsigned_times_power_of_2_properties() { unsigned_signed_pair_gen_var_1().test_properties(|(n, pow)| { let float_n = Float::const_from_unsigned_times_power_of_2(n, pow); assert!(float_n.is_valid()); assert!(float_n >= 0); assert_eq!( ComparableFloat(float_n), ComparableFloat(Float::from(n) << pow) ); }); signed_gen_var_5().test_properties(|pow| { assert_eq!( ComparableFloat(Float::const_from_unsigned_times_power_of_2(1, pow)), ComparableFloat(Float::power_of_2(i64::from(pow))) ); }); } #[test] fn const_from_signed_times_power_of_2_properties() { signed_pair_gen_var_2().test_properties(|(n, pow)| { let float_n = Float::const_from_signed_times_power_of_2(n, pow); assert!(float_n.is_valid()); assert_eq!(float_n >= 0, n >= 0); assert_eq!( ComparableFloat(float_n), ComparableFloat(Float::from(n) << pow) ); }); signed_gen_var_5().test_properties(|pow| { assert_eq!( ComparableFloat(Float::const_from_signed_times_power_of_2(1, pow)), ComparableFloat(Float::power_of_2(i64::from(pow))) ); }); } ================================================ FILE: malachite-float/tests/conversion/from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::*; use malachite_float::conversion::from_rational::{ from_rational_prec_round_direct, from_rational_prec_round_ref_direct, from_rational_prec_round_ref_using_div, from_rational_prec_round_using_div, }; use malachite_float::test_util::common::rug_round_try_from_rounding_mode; use malachite_float::test_util::common::to_hex_string; use malachite_float::test_util::generators::rational_unsigned_rounding_mode_triple_gen_var_1; use malachite_float::{ComparableFloat, ComparableFloatRef, Float, emulate_rational_to_float_fn}; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; use malachite_q::test_util::generators::{rational_gen, rational_unsigned_pair_gen_var_3}; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] #[allow(clippy::type_repetition_in_bounds)] fn test_from_rational_prec() { fn float_helper(x: &Rational) where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float> + RoundingFrom<&'a Rational>, Rational: TryFrom, { let xf = emulate_rational_to_float_fn::(Float::from_rational_prec_ref, x); assert_eq!(NiceFloat(xf), NiceFloat(T::rounding_from(x, Nearest).0)); } let test = |s, prec, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (x, o) = Float::from_rational_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_rational_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_direct(u.clone(), prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_direct(&u, prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Rational::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); float_helper::(&u); float_helper::(&u); }; test("0", 1, "0.0", "0x0.0", Equal); test("0", 10, "0.0", "0x0.0", Equal); test("0", 100, "0.0", "0x0.0", Equal); test("1", 1, "1.0", "0x1.0#1", Equal); test("1", 10, "1.0", "0x1.000#10", Equal); test("1", 100, "1.0", "0x1.0000000000000000000000000#100", Equal); test("1/2", 1, "0.5", "0x0.8#1", Equal); test("1/2", 10, "0.5", "0x0.800#10", Equal); test( "1/2", 100, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test("1/3", 1, "0.2", "0x0.4#1", Less); test("1/3", 10, "0.3335", "0x0.556#10", Greater); test( "1/3", 100, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test("22/7", 1, "4.0", "0x4.0#1", Greater); test("22/7", 10, "3.145", "0x3.25#10", Greater); test( "22/7", 100, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); let test_big = |u: Rational, prec, out, out_hex, out_o| { let (x, o) = Float::from_rational_prec(u.clone(), prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_rational_prec_ref(&u, prec); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_direct(u.clone(), prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_direct(&u, prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, Nearest); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Rational::from(&u)); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); float_helper::(&u); float_helper::(&u); }; test_big( Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), 10, "1.401e-45", "0x8.00E-38#10", Equal, ); test_big( Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL) >> 1, 10, "7.01e-46", "0x4.00E-38#10", Equal, ); test_big( (Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL) >> 1) + Rational::power_of_2(-1000i64), 10, "7.01e-46", "0x4.00E-38#10", Less, ); test_big( (Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL) >> 1) - Rational::power_of_2(-1000i64), 10, "7.01e-46", "0x4.00E-38#10", Greater, ); test_big( Rational::exact_from(f64::MIN_POSITIVE_SUBNORMAL), 10, "4.94e-324", "0x4.00E-269#10", Equal, ); test_big( Rational::exact_from(f64::MIN_POSITIVE_SUBNORMAL) >> 1, 10, "2.47e-324", "0x2.00E-269#10", Equal, ); test_big( (Rational::exact_from(f64::MIN_POSITIVE_SUBNORMAL) >> 1) + Rational::power_of_2(-2000i64), 10, "2.47e-324", "0x2.00E-269#10", Less, ); test_big( (Rational::exact_from(f64::MIN_POSITIVE_SUBNORMAL) >> 1) - Rational::power_of_2(-2000i64), 10, "2.47e-324", "0x2.00E-269#10", Greater, ); test_big( Rational::power_of_2(1000i64), 10, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(-1000i64), 1, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( -Rational::power_of_2(1000i64), 10, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(-1000i64), 10, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(-1000i64), 1, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn from_rational_prec_fail() { assert_panic!(Float::from_rational_prec(Rational::ZERO, 0)); assert_panic!(Float::from_rational_prec(Rational::ONE, 0)); assert_panic!(Float::from_rational_prec(Rational::NEGATIVE_ONE, 0)); } #[test] fn from_rational_prec_ref_fail() { assert_panic!(Float::from_rational_prec_ref(&Rational::ZERO, 0)); assert_panic!(Float::from_rational_prec_ref(&Rational::ONE, 0)); assert_panic!(Float::from_rational_prec_ref(&Rational::NEGATIVE_ONE, 0)); } #[test] fn test_from_rational_prec_round() { let test = |s, prec, rm, out, out_hex, out_o| { let u = Rational::from_str(s).unwrap(); let (x, o) = Float::from_rational_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_rational_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_direct(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_direct(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Rational::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } }; test("0", 1, Floor, "0.0", "0x0.0", Equal); test("0", 1, Ceiling, "0.0", "0x0.0", Equal); test("0", 1, Down, "0.0", "0x0.0", Equal); test("0", 1, Up, "0.0", "0x0.0", Equal); test("0", 1, Nearest, "0.0", "0x0.0", Equal); test("0", 1, Exact, "0.0", "0x0.0", Equal); test("0", 10, Floor, "0.0", "0x0.0", Equal); test("0", 10, Ceiling, "0.0", "0x0.0", Equal); test("0", 10, Down, "0.0", "0x0.0", Equal); test("0", 10, Up, "0.0", "0x0.0", Equal); test("0", 10, Nearest, "0.0", "0x0.0", Equal); test("0", 10, Exact, "0.0", "0x0.0", Equal); test("0", 100, Floor, "0.0", "0x0.0", Equal); test("0", 100, Ceiling, "0.0", "0x0.0", Equal); test("0", 100, Down, "0.0", "0x0.0", Equal); test("0", 100, Up, "0.0", "0x0.0", Equal); test("0", 100, Nearest, "0.0", "0x0.0", Equal); test("0", 100, Exact, "0.0", "0x0.0", Equal); test("1", 1, Floor, "1.0", "0x1.0#1", Equal); test("1", 1, Ceiling, "1.0", "0x1.0#1", Equal); test("1", 1, Down, "1.0", "0x1.0#1", Equal); test("1", 1, Up, "1.0", "0x1.0#1", Equal); test("1", 1, Nearest, "1.0", "0x1.0#1", Equal); test("1", 1, Exact, "1.0", "0x1.0#1", Equal); test("1", 10, Floor, "1.0", "0x1.000#10", Equal); test("1", 10, Ceiling, "1.0", "0x1.000#10", Equal); test("1", 10, Down, "1.0", "0x1.000#10", Equal); test("1", 10, Up, "1.0", "0x1.000#10", Equal); test("1", 10, Nearest, "1.0", "0x1.000#10", Equal); test("1", 10, Exact, "1.0", "0x1.000#10", Equal); test( "1", 100, Floor, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Ceiling, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Down, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Up, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Nearest, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test( "1", 100, Exact, "1.0", "0x1.0000000000000000000000000#100", Equal, ); test("1/2", 1, Floor, "0.5", "0x0.8#1", Equal); test("1/2", 1, Ceiling, "0.5", "0x0.8#1", Equal); test("1/2", 1, Down, "0.5", "0x0.8#1", Equal); test("1/2", 1, Up, "0.5", "0x0.8#1", Equal); test("1/2", 1, Nearest, "0.5", "0x0.8#1", Equal); test("1/2", 1, Exact, "0.5", "0x0.8#1", Equal); test("1/2", 10, Floor, "0.5", "0x0.800#10", Equal); test("1/2", 10, Ceiling, "0.5", "0x0.800#10", Equal); test("1/2", 10, Down, "0.5", "0x0.800#10", Equal); test("1/2", 10, Up, "0.5", "0x0.800#10", Equal); test("1/2", 10, Nearest, "0.5", "0x0.800#10", Equal); test("1/2", 10, Exact, "0.5", "0x0.800#10", Equal); test( "1/2", 100, Floor, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( "1/2", 100, Ceiling, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( "1/2", 100, Down, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( "1/2", 100, Up, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( "1/2", 100, Nearest, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test( "1/2", 100, Exact, "0.5", "0x0.8000000000000000000000000#100", Equal, ); test("1/3", 1, Floor, "0.2", "0x0.4#1", Less); test("1/3", 1, Ceiling, "0.5", "0x0.8#1", Greater); test("1/3", 1, Down, "0.2", "0x0.4#1", Less); test("1/3", 1, Up, "0.5", "0x0.8#1", Greater); test("1/3", 1, Nearest, "0.2", "0x0.4#1", Less); test("1/3", 10, Floor, "0.333", "0x0.554#10", Less); test("1/3", 10, Ceiling, "0.3335", "0x0.556#10", Greater); test("1/3", 10, Down, "0.333", "0x0.554#10", Less); test("1/3", 10, Up, "0.3335", "0x0.556#10", Greater); test("1/3", 10, Nearest, "0.3335", "0x0.556#10", Greater); test( "1/3", 100, Floor, "0.3333333333333333333333333333331", "0x0.55555555555555555555555550#100", Less, ); test( "1/3", 100, Ceiling, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test( "1/3", 100, Down, "0.3333333333333333333333333333331", "0x0.55555555555555555555555550#100", Less, ); test( "1/3", 100, Up, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test( "1/3", 100, Nearest, "0.3333333333333333333333333333335", "0x0.55555555555555555555555558#100", Greater, ); test("22/7", 1, Floor, "2.0", "0x2.0#1", Less); test("22/7", 1, Ceiling, "4.0", "0x4.0#1", Greater); test("22/7", 1, Down, "2.0", "0x2.0#1", Less); test("22/7", 1, Up, "4.0", "0x4.0#1", Greater); test("22/7", 1, Nearest, "4.0", "0x4.0#1", Greater); test("22/7", 10, Floor, "3.141", "0x3.24#10", Less); test("22/7", 10, Ceiling, "3.145", "0x3.25#10", Greater); test("22/7", 10, Down, "3.141", "0x3.24#10", Less); test("22/7", 10, Up, "3.145", "0x3.25#10", Greater); test("22/7", 10, Nearest, "3.145", "0x3.25#10", Greater); test( "22/7", 100, Floor, "3.142857142857142857142857142855", "0x3.2492492492492492492492490#100", Less, ); test( "22/7", 100, Ceiling, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test( "22/7", 100, Down, "3.142857142857142857142857142855", "0x3.2492492492492492492492490#100", Less, ); test( "22/7", 100, Up, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test( "22/7", 100, Nearest, "3.142857142857142857142857142858", "0x3.2492492492492492492492494#100", Greater, ); test("-1", 1, Floor, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Ceiling, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Down, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Up, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Nearest, "-1.0", "-0x1.0#1", Equal); test("-1", 1, Exact, "-1.0", "-0x1.0#1", Equal); test("-1", 10, Floor, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Ceiling, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Down, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Up, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Nearest, "-1.0", "-0x1.000#10", Equal); test("-1", 10, Exact, "-1.0", "-0x1.000#10", Equal); test( "-1", 100, Floor, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1", 100, Ceiling, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1", 100, Down, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1", 100, Up, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1", 100, Nearest, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test( "-1", 100, Exact, "-1.0", "-0x1.0000000000000000000000000#100", Equal, ); test("-1/2", 1, Floor, "-0.5", "-0x0.8#1", Equal); test("-1/2", 1, Ceiling, "-0.5", "-0x0.8#1", Equal); test("-1/2", 1, Down, "-0.5", "-0x0.8#1", Equal); test("-1/2", 1, Up, "-0.5", "-0x0.8#1", Equal); test("-1/2", 1, Nearest, "-0.5", "-0x0.8#1", Equal); test("-1/2", 1, Exact, "-0.5", "-0x0.8#1", Equal); test("-1/2", 10, Floor, "-0.5", "-0x0.800#10", Equal); test("-1/2", 10, Ceiling, "-0.5", "-0x0.800#10", Equal); test("-1/2", 10, Down, "-0.5", "-0x0.800#10", Equal); test("-1/2", 10, Up, "-0.5", "-0x0.800#10", Equal); test("-1/2", 10, Nearest, "-0.5", "-0x0.800#10", Equal); test("-1/2", 10, Exact, "-0.5", "-0x0.800#10", Equal); test( "-1/2", 100, Floor, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test( "-1/2", 100, Ceiling, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test( "-1/2", 100, Down, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test( "-1/2", 100, Up, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test( "-1/2", 100, Nearest, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test( "-1/2", 100, Exact, "-0.5", "-0x0.8000000000000000000000000#100", Equal, ); test("-1/3", 1, Floor, "-0.5", "-0x0.8#1", Less); test("-1/3", 1, Ceiling, "-0.2", "-0x0.4#1", Greater); test("-1/3", 1, Down, "-0.2", "-0x0.4#1", Greater); test("-1/3", 1, Up, "-0.5", "-0x0.8#1", Less); test("-1/3", 1, Nearest, "-0.2", "-0x0.4#1", Greater); test("-1/3", 10, Floor, "-0.3335", "-0x0.556#10", Less); test("-1/3", 10, Ceiling, "-0.333", "-0x0.554#10", Greater); test("-1/3", 10, Down, "-0.333", "-0x0.554#10", Greater); test("-1/3", 10, Up, "-0.3335", "-0x0.556#10", Less); test("-1/3", 10, Nearest, "-0.3335", "-0x0.556#10", Less); test( "-1/3", 100, Floor, "-0.3333333333333333333333333333335", "-0x0.55555555555555555555555558#100", Less, ); test( "-1/3", 100, Ceiling, "-0.3333333333333333333333333333331", "-0x0.55555555555555555555555550#100", Greater, ); test( "-1/3", 100, Down, "-0.3333333333333333333333333333331", "-0x0.55555555555555555555555550#100", Greater, ); test( "-1/3", 100, Up, "-0.3333333333333333333333333333335", "-0x0.55555555555555555555555558#100", Less, ); test( "-1/3", 100, Nearest, "-0.3333333333333333333333333333335", "-0x0.55555555555555555555555558#100", Less, ); test("-22/7", 1, Floor, "-4.0", "-0x4.0#1", Less); test("-22/7", 1, Ceiling, "-2.0", "-0x2.0#1", Greater); test("-22/7", 1, Down, "-2.0", "-0x2.0#1", Greater); test("-22/7", 1, Up, "-4.0", "-0x4.0#1", Less); test("-22/7", 1, Nearest, "-4.0", "-0x4.0#1", Less); test("-22/7", 10, Floor, "-3.145", "-0x3.25#10", Less); test("-22/7", 10, Ceiling, "-3.141", "-0x3.24#10", Greater); test("-22/7", 10, Down, "-3.141", "-0x3.24#10", Greater); test("-22/7", 10, Up, "-3.145", "-0x3.25#10", Less); test("-22/7", 10, Nearest, "-3.145", "-0x3.25#10", Less); test( "-22/7", 100, Floor, "-3.142857142857142857142857142858", "-0x3.2492492492492492492492494#100", Less, ); test( "-22/7", 100, Ceiling, "-3.142857142857142857142857142855", "-0x3.2492492492492492492492490#100", Greater, ); test( "-22/7", 100, Down, "-3.142857142857142857142857142855", "-0x3.2492492492492492492492490#100", Greater, ); test( "-22/7", 100, Up, "-3.142857142857142857142857142858", "-0x3.2492492492492492492492494#100", Less, ); test( "-22/7", 100, Nearest, "-3.142857142857142857142857142858", "-0x3.2492492492492492492492494#100", Less, ); let test_big = |u: Rational, prec, rm, out, out_hex, out_o| { let (x, o) = Float::from_rational_prec_round(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = Float::from_rational_prec_round_ref(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_direct(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_using_div(u.clone(), prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_direct(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); let (x, o) = from_rational_prec_round_ref_using_div(&u, prec, rm); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Rational::from(&u), rm); let x = Float::exact_from(&rug_x); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); assert_eq!(o, out_o); } }; test_big( Rational::power_of_2(1000i64), 10, Floor, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Ceiling, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Down, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Up, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Nearest, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(1000i64), 10, Exact, "1.072e301", "0x1.000E+250#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Floor, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Down, "too_big", "0x7.feE+268435455#10", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Up, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Nearest, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Floor, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Down, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Up, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Nearest, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Exact, "too_big", "0x4.00E+268435455#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Nearest, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Floor, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Ceiling, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Down, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Up, "Infinity", "Infinity", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Nearest, "too_big", "0x4.0E+268435455#1", Less, ); test_big( Rational::power_of_2(-1000i64), 10, Floor, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Ceiling, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Down, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Up, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Nearest, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(-1000i64), 10, Exact, "9.33e-302", "0x1.000E-250#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Floor, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Ceiling, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Down, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Up, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Nearest, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Exact, "too_small", "0x2.00E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Floor, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Down, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Up, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Nearest, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Exact, "too_small", "0x1.000E-268435456#10", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Nearest, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Nearest, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "too_small", "0x1.000E-268435456#10", Greater, ); test_big( Rational::power_of_2(-1000i64), 1, Floor, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(-1000i64), 1, Ceiling, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(-1000i64), 1, Down, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(-1000i64), 1, Up, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(-1000i64), 1, Nearest, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(-1000i64), 1, Exact, "9.0e-302", "0x1.0E-250#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Floor, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Ceiling, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Down, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Up, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Nearest, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Exact, "too_small", "0x2.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Floor, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Down, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Up, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Nearest, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Exact, "too_small", "0x1.0E-268435456#1", Equal, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Nearest, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Nearest, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Nearest, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Nearest, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Nearest, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Floor, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Ceiling, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Down, "0.0", "0x0.0", Less, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Up, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Nearest, "too_small", "0x1.0E-268435456#1", Greater, ); test_big( -Rational::power_of_2(1000i64), 10, Floor, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(1000i64), 10, Ceiling, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(1000i64), 10, Down, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(1000i64), 10, Up, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(1000i64), 10, Nearest, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(1000i64), 10, Exact, "-1.072e301", "-0x1.000E+250#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Ceiling, "-too_big", "-0x7.feE+268435455#10", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Down, "-too_big", "-0x7.feE+268435455#10", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Up, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), 10, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Floor, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Ceiling, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Down, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Up, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Nearest, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), 10, Exact, "-too_big", "-0x4.00E+268435455#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), 1, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), 1, Nearest, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Floor, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Ceiling, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Down, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Up, "-Infinity", "-Infinity", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), 1, Nearest, "-too_big", "-0x4.0E+268435455#1", Greater, ); test_big( -Rational::power_of_2(-1000i64), 10, Floor, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(-1000i64), 10, Ceiling, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(-1000i64), 10, Down, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(-1000i64), 10, Up, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(-1000i64), 10, Nearest, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(-1000i64), 10, Exact, "-9.33e-302", "-0x1.000E-250#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Floor, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Ceiling, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Down, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Up, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Nearest, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 10, Exact, "-too_small", "-0x2.00E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Ceiling, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Down, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Up, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 10, Exact, "-too_small", "-0x1.000E-268435456#10", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 10, Nearest, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Floor, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Up, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 10, Nearest, "-too_small", "-0x1.000E-268435456#10", Less, ); test_big( -Rational::power_of_2(-1000i64), 1, Floor, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(-1000i64), 1, Ceiling, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(-1000i64), 1, Down, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(-1000i64), 1, Up, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(-1000i64), 1, Nearest, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(-1000i64), 1, Exact, "-9.0e-302", "-0x1.0E-250#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Floor, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Ceiling, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Down, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Up, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Nearest, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), 1, Exact, "-too_small", "-0x2.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Ceiling, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Down, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Up, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), 1, Exact, "-too_small", "-0x1.0E-268435456#1", Equal, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), 1, Nearest, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Floor, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Ceiling, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Down, "-0.0", "-0x0.0", Greater, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Up, "-too_small", "-0x1.0E-268435456#1", Less, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), 1, Nearest, "-too_small", "-0x1.0E-268435456#1", Less, ); } #[test] fn from_rational_prec_round_fail() { assert_panic!(Float::from_rational_prec_round(Rational::ZERO, 0, Floor)); assert_panic!(Float::from_rational_prec_round(Rational::ONE, 0, Floor)); assert_panic!(Float::from_rational_prec_round( Rational::from(123u32), 1, Exact )); assert_panic!(Float::from_rational_prec_round( Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::from_rational_prec_round( Rational::NEGATIVE_ONE, 0, Floor )); assert_panic!(Float::from_rational_prec_round( Rational::from(-123), 1, Exact )); assert_panic!(Float::from_rational_prec_round( Rational::from_signeds(-1i8, 3), 100, Exact )); } #[test] fn from_rational_prec_round_ref_fail() { assert_panic!(Float::from_rational_prec_round_ref( &Rational::ZERO, 0, Floor )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::ONE, 0, Floor )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::from(123u32), 1, Exact )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::from_unsigneds(1u8, 3), 100, Exact )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::NEGATIVE_ONE, 0, Floor )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::from(-123), 1, Exact )); assert_panic!(Float::from_rational_prec_round_ref( &Rational::from_signeds(-1i8, 3), 100, Exact )); } #[allow(clippy::needless_borrow)] #[test] fn test_try_from_rational() { let test = |s, out, out_hex| { let x = Rational::from_str(s).unwrap(); let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test("0", Ok("0.0"), Ok("0x0.0")); test("1", Ok("1.0"), Ok("0x1.0#1")); test("1/2", Ok("0.5"), Ok("0x0.8#1")); test("117/256", Ok("0.457"), Ok("0x0.75#7")); test( "6369051672525773/4503599627370496", Ok("1.4142135623730951"), Ok("0x1.6a09e667f3bcd#53"), ); test( "884279719003555/281474976710656", Ok("3.141592653589793"), Ok("0x3.243f6a8885a3#50"), ); test( "6121026514868073/2251799813685248", Ok("2.7182818284590451"), Ok("0x2.b7e151628aed2#53"), ); test("-1", Ok("-1.0"), Ok("-0x1.0#1")); test("-1/2", Ok("-0.5"), Ok("-0x0.8#1")); test("-117/256", Ok("-0.457"), Ok("-0x0.75#7")); test( "-6369051672525773/4503599627370496", Ok("-1.4142135623730951"), Ok("-0x1.6a09e667f3bcd#53"), ); test( "-884279719003555/281474976710656", Ok("-3.141592653589793"), Ok("-0x3.243f6a8885a3#50"), ); test( "-6121026514868073/2251799813685248", Ok("-2.7182818284590451"), Ok("-0x2.b7e151628aed2#53"), ); test( "1/3", Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test( "22/7", Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test( "-1/3", Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test( "-22/7", Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); let test_big = |x: Rational, out, out_hex| { let of = Float::try_from(x.clone()); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); let ofs = of.as_ref().map(ToString::to_string); assert_eq!(ofs.as_ref().map(String::as_str), out); let ofs = of.map(|f| to_hex_string(&f)); assert_eq!(ofs.as_ref().map(String::as_str), out_hex); }; test_big( Rational::power_of_2(1000i64), Ok("1.0e301"), Ok("0x1.0E+250#1"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Ok("too_big"), Ok("0x4.0E+268435455#1"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), Ok("too_big"), Ok("0x6.0E+268435455#2"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3073u16, 2048), Ok("too_big"), Ok("0x6.008E+268435455#12"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3071u16, 2048), Ok("too_big"), Ok("0x5.ff8E+268435455#12"), ); test_big( Rational::power_of_2(-1000i64), Ok("9.0e-302"), Ok("0x1.0E-250#1"), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), Ok("too_small"), Ok("0x2.0E-268435456#1"), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), Ok("too_small"), Ok("0x1.0E-268435456#1"), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( Rational::power_of_2(1000i64), Ok("1.0e301"), Ok("0x1.0E+250#1"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Ok("too_big"), Ok("0x4.0E+268435455#1"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), Ok("too_big"), Ok("0x6.0E+268435455#2"), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( -Rational::power_of_2(-1000i64), Ok("-9.0e-302"), Ok("-0x1.0E-250#1"), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), Ok("-too_small"), Ok("-0x2.0E-268435456#1"), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), Ok("-too_small"), Ok("-0x1.0E-268435456#1"), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), Err(&&FloatConversionError::Underflow), Err(&&FloatConversionError::Underflow), ); test_big( -Rational::power_of_2(1000i64), Ok("-1.0e301"), Ok("-0x1.0E+250#1"), ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), Err(&&FloatConversionError::Overflow), Err(&&FloatConversionError::Overflow), ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), Ok("-too_big"), Ok("-0x4.0E+268435455#1"), ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), Ok("-too_big"), Ok("-0x6.0E+268435455#2"), ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), Err(&&FloatConversionError::Inexact), Err(&&FloatConversionError::Inexact), ); } #[test] fn test_convertible_from_rational() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); assert_eq!(Float::convertible_from(&x), out); }; test("0", true); test("1", true); test("1/2", true); test("117/256", true); test("6369051672525773/4503599627370496", true); test("884279719003555/281474976710656", true); test("6121026514868073/2251799813685248", true); test("-1", true); test("-1/2", true); test("-117/256", true); test("-6369051672525773/4503599627370496", true); test("-884279719003555/281474976710656", true); test("-6121026514868073/2251799813685248", true); test("1/3", false); test("22/7", false); test("-1/3", false); test("-22/7", false); let test_big = |x: Rational, out| { assert_eq!(Float::convertible_from(&x), out); }; test_big(Rational::power_of_2(1000i64), true); test_big(Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), false); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), true, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), true, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), false, ); test_big( Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), false, ); test_big(Rational::power_of_2(-1000i64), true); test_big(Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), true); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), true, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), false, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), false, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), false, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), false, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), false, ); test_big( Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), false, ); test_big(-Rational::power_of_2(1000i64), true); test_big(-Rational::power_of_2(i64::from(Float::MAX_EXPONENT)), false); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1), true, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(3u8, 2), true, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(300u16, 199), false, ); test_big( -Rational::power_of_2(i64::from(Float::MAX_EXPONENT) - 1) * Rational::from_unsigneds(299u16, 200), false, ); test_big(-Rational::power_of_2(-1000i64), true); test_big(-Rational::power_of_2(i64::from(Float::MIN_EXPONENT)), true); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 1), true, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2), false, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), false, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), false, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1024u16, 1023), false, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1001u16, 1000), false, ); test_big( -Rational::power_of_2(i64::from(Float::MIN_EXPONENT) - 2) * Rational::from_unsigneds(1025u16, 1024), false, ); } #[allow(clippy::type_repetition_in_bounds)] fn from_rational_prec_properties_helper() where Float: PartialOrd, for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float> + RoundingFrom<&'a Rational>, Rational: TryFrom, { rational_gen().test_properties(|x| { let xf = emulate_rational_to_float_fn::(Float::from_rational_prec_ref, &x); assert_eq!(NiceFloat(xf), NiceFloat(T::rounding_from(&x, Nearest).0)); }); } #[test] fn from_rational_prec_properties() { rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let (float_x, o) = Float::from_rational_prec(x.clone(), prec); assert!(float_x.is_valid()); let (float_x_alt, o_alt) = Float::from_rational_prec_ref(&x, prec); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); assert_eq!(float_x.partial_cmp(&x), Some(o)); let (float_x_alt, o_alt) = from_rational_prec_round_direct(x.clone(), prec, Nearest); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_using_div(x.clone(), prec, Nearest); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_ref_direct(&x, prec, Nearest); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_ref_using_div(&x, prec, Nearest); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let rug_x = rug::Float::with_val(u32::exact_from(prec), rug::Rational::from(&x)); assert_eq!( ComparableFloatRef(&float_x), ComparableFloatRef(&Float::from(&rug_x)) ); assert_eq!(x == 0u32, float_x == 0u32); assert_eq!( float_x.get_prec(), if x == 0u32 { None } else { Some(prec) } ); if x != 0u32 { assert!( (Rational::exact_from(&float_x) - &x) .le_abs(&(Rational::exact_from(float_x.ulp().unwrap()) >> 1)) ); } }); apply_fn_to_primitive_floats!(from_rational_prec_properties_helper); } #[test] fn from_rational_prec_round_properties() { rational_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(x, prec, rm)| { let (float_x, o) = Float::from_rational_prec_round(x.clone(), prec, rm); assert!(float_x.is_valid()); let (float_x_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, rm); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); assert_eq!(float_x.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } let (float_x_alt, o_alt) = from_rational_prec_round_direct(x.clone(), prec, rm); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_using_div(x.clone(), prec, rm); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_ref_direct(&x, prec, rm); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); let (float_x_alt, o_alt) = from_rational_prec_round_ref_using_div(&x, prec, rm); assert!(float_x_alt.is_valid()); assert_eq!( ComparableFloatRef(&float_x_alt), ComparableFloatRef(&float_x) ); assert_eq!(o, o_alt); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rug_x, rug_o) = rug::Float::with_val_round(u32::exact_from(prec), rug::Rational::from(&x), rm); assert_eq!( ComparableFloatRef(&float_x), ComparableFloatRef(&Float::from(&rug_x)) ); assert_eq!(rug_o, o); } assert_eq!(x == 0u32, float_x == 0u32); assert_eq!( float_x.get_prec(), if x == 0u32 { None } else { Some(prec) } ); if x != 0u32 { assert!( (Rational::exact_from(&float_x) - &x) .le_abs(&Rational::exact_from(float_x.ulp().unwrap())) ); } }); rational_unsigned_pair_gen_var_3().test_properties(|(x, prec)| { let floor = Float::from_rational_prec_round_ref(&x, prec, Floor); let r_floor = Rational::exact_from(&floor.0); assert!(r_floor <= x); if r_floor != 0u32 { assert!(r_floor + Rational::exact_from(floor.0.ulp().unwrap()) > x); } let (floor_x_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, if x >= 0 { Down } else { Up }); assert_eq!( ComparableFloatRef(&floor_x_alt), ComparableFloatRef(&floor.0) ); assert_eq!(o_alt, floor.1); let ceiling = Float::from_rational_prec_round_ref(&x, prec, Ceiling); let r_ceiling = Rational::exact_from(&ceiling.0); assert!(r_ceiling >= x); if r_ceiling != 0u32 { assert!(r_ceiling - Rational::exact_from(ceiling.0.ulp().unwrap()) < x); } let (ceiling_x_alt, o_alt) = Float::from_rational_prec_round_ref(&x, prec, if x >= 0 { Up } else { Down }); assert_eq!( ComparableFloatRef(&ceiling_x_alt), ComparableFloatRef(&ceiling.0) ); assert_eq!(o_alt, ceiling.1); let nearest = Float::from_rational_prec_round_ref(&x, prec, Nearest); let r_nearest = Rational::exact_from(&nearest.0); assert!( ComparableFloatRef(&nearest.0) == ComparableFloatRef(&floor.0) && nearest.1 == floor.1 || ComparableFloatRef(&nearest.0) == ComparableFloatRef(&ceiling.0) && nearest.1 == ceiling.1 ); if r_nearest != 0u32 { assert!((r_nearest - x).le_abs(&(Rational::exact_from(nearest.0.ulp().unwrap()) >> 1))); } }); } #[test] fn float_try_from_rational_properties() { rational_gen().test_properties(|x| { let of = Float::try_from(&x); assert!(of.as_ref().map_or(true, Float::is_valid)); assert_eq!( Float::try_from(x.clone()).map(ComparableFloat), of.clone().map(ComparableFloat) ); if let Ok(f) = of { assert_eq!(-x, -f); } }); } #[test] fn float_convertible_from_rational_properties() { rational_gen().test_properties(|x| { assert_eq!(Float::convertible_from(&x), Float::try_from(&x).is_ok()); }); integer_gen().test_properties(|n| { assert!(Float::convertible_from(&Rational::from(n))); }); } ================================================ FILE: malachite-float/tests/conversion/integer_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, Floor, Parity}; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, One, OneHalf}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_float::Float; use malachite_float::test_util::common::{parse_hex_string, rug_round_try_from_rounding_mode}; use malachite_float::test_util::generators::{ float_gen, float_gen_var_4, float_rounding_mode_pair_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use std::cmp::Ordering::*; use std::panic::catch_unwind; #[test] fn test_try_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = Integer::try_from(x.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Integer::try_from(&x); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("NaN", "NaN", "Err(FloatInfiniteOrNan)"); test("Infinity", "Infinity", "Err(FloatInfiniteOrNan)"); test("-Infinity", "-Infinity", "Err(FloatInfiniteOrNan)"); test("0.0", "0x0.0", "Ok(0)"); test("-0.0", "-0x0.0", "Ok(0)"); test("1.0", "0x1.0#1", "Ok(1)"); test("2.0", "0x2.0#1", "Ok(2)"); test("0.5", "0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test( "0.33333333333333331", "0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test("123.0", "0x7b.0#7", "Ok(123)"); test("1000000000000.0", "0xe8d4a51000.0#40", "Ok(1000000000000)"); test("-1.0", "-0x1.0#1", "Ok(-1)"); test("-2.0", "-0x2.0#1", "Ok(-2)"); test("-0.5", "-0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test("-123.0", "-0x7b.0#7", "Ok(-123)"); test( "-1000000000000.0", "-0xe8d4a51000.0#40", "Ok(-1000000000000)", ); } #[test] fn test_convertible_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(Integer::convertible_from(&x), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("123.0", "0x7b.0#7", true); test("1000000000000.0", "0xe8d4a51000.0#40", true); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-123.0", "-0x7b.0#7", true); test("-1000000000000.0", "-0xe8d4a51000.0#40", true); } #[test] fn test_rounding_from_float() { let test = |s, s_hex, rm, out, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (n, o) = Integer::rounding_from(x.clone(), rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); let (n, o) = Integer::rounding_from(&x, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rn, ro) = rug::Float::exact_from(&x).to_integer_round(rm).unwrap(); assert_eq!(Integer::from(&rn), n); assert_eq!(ro, o); } }; test("0.0", "0x0.0", Floor, "0", Equal); test("0.0", "0x0.0", Ceiling, "0", Equal); test("0.0", "0x0.0", Down, "0", Equal); test("0.0", "0x0.0", Up, "0", Equal); test("0.0", "0x0.0", Nearest, "0", Equal); test("0.0", "0x0.0", Exact, "0", Equal); test("-0.0", "-0x0.0", Floor, "0", Equal); test("-0.0", "-0x0.0", Ceiling, "0", Equal); test("-0.0", "-0x0.0", Down, "0", Equal); test("-0.0", "-0x0.0", Up, "0", Equal); test("-0.0", "-0x0.0", Nearest, "0", Equal); test("-0.0", "-0x0.0", Exact, "0", Equal); test("1.0", "0x1.0#1", Floor, "1", Equal); test("1.0", "0x1.0#1", Ceiling, "1", Equal); test("1.0", "0x1.0#1", Down, "1", Equal); test("1.0", "0x1.0#1", Up, "1", Equal); test("1.0", "0x1.0#1", Nearest, "1", Equal); test("1.0", "0x1.0#1", Exact, "1", Equal); test("2.0", "0x2.0#1", Floor, "2", Equal); test("2.0", "0x2.0#1", Ceiling, "2", Equal); test("2.0", "0x2.0#1", Down, "2", Equal); test("2.0", "0x2.0#1", Up, "2", Equal); test("2.0", "0x2.0#1", Nearest, "2", Equal); test("2.0", "0x2.0#1", Exact, "2", Equal); test("0.5", "0x0.8#1", Floor, "0", Less); test("0.5", "0x0.8#1", Ceiling, "1", Greater); test("0.5", "0x0.8#1", Down, "0", Less); test("0.5", "0x0.8#1", Up, "1", Greater); test("0.5", "0x0.8#1", Nearest, "0", Less); test( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0", Less, ); test( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "1", Greater, ); test( "0.33333333333333331", "0x0.55555555555554#53", Down, "0", Less, ); test( "0.33333333333333331", "0x0.55555555555554#53", Up, "1", Greater, ); test( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Floor, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Ceiling, "1", Greater, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Down, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Up, "1", Greater, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Nearest, "1", Greater, ); test("1.5", "0x1.8#2", Floor, "1", Less); test("1.5", "0x1.8#2", Ceiling, "2", Greater); test("1.5", "0x1.8#2", Down, "1", Less); test("1.5", "0x1.8#2", Up, "2", Greater); test("1.5", "0x1.8#2", Nearest, "2", Greater); test("2.5", "0x2.8#3", Floor, "2", Less); test("2.5", "0x2.8#3", Ceiling, "3", Greater); test("2.5", "0x2.8#3", Down, "2", Less); test("2.5", "0x2.8#3", Up, "3", Greater); test("2.5", "0x2.8#3", Nearest, "2", Less); test("123.0", "0x7b.0#7", Floor, "123", Equal); test("123.0", "0x7b.0#7", Ceiling, "123", Equal); test("123.0", "0x7b.0#7", Down, "123", Equal); test("123.0", "0x7b.0#7", Up, "123", Equal); test("123.0", "0x7b.0#7", Nearest, "123", Equal); test("123.0", "0x7b.0#7", Exact, "123", Equal); test("-1.0", "-0x1.0#1", Floor, "-1", Equal); test("-1.0", "-0x1.0#1", Ceiling, "-1", Equal); test("-1.0", "-0x1.0#1", Down, "-1", Equal); test("-1.0", "-0x1.0#1", Up, "-1", Equal); test("-1.0", "-0x1.0#1", Nearest, "-1", Equal); test("-1.0", "-0x1.0#1", Exact, "-1", Equal); test("-2.0", "-0x2.0#1", Floor, "-2", Equal); test("-2.0", "-0x2.0#1", Ceiling, "-2", Equal); test("-2.0", "-0x2.0#1", Down, "-2", Equal); test("-2.0", "-0x2.0#1", Up, "-2", Equal); test("-2.0", "-0x2.0#1", Nearest, "-2", Equal); test("-2.0", "-0x2.0#1", Exact, "-2", Equal); test("-0.5", "-0x0.8#1", Floor, "-1", Less); test("-0.5", "-0x0.8#1", Ceiling, "0", Greater); test("-0.5", "-0x0.8#1", Down, "0", Greater); test("-0.5", "-0x0.8#1", Up, "-1", Less); test("-0.5", "-0x0.8#1", Nearest, "0", Greater); test( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "-1", Less, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "0", Greater, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "0", Greater, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "-1", Less, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Floor, "-1", Less, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Ceiling, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Down, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Up, "-1", Less, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Nearest, "-1", Less, ); test("-1.5", "-0x1.8#2", Floor, "-2", Less); test("-1.5", "-0x1.8#2", Ceiling, "-1", Greater); test("-1.5", "-0x1.8#2", Down, "-1", Greater); test("-1.5", "-0x1.8#2", Up, "-2", Less); test("-1.5", "-0x1.8#2", Nearest, "-2", Less); test("-2.5", "-0x2.8#3", Floor, "-3", Less); test("-2.5", "-0x2.8#3", Ceiling, "-2", Greater); test("-2.5", "-0x2.8#3", Down, "-2", Greater); test("-2.5", "-0x2.8#3", Up, "-3", Less); test("-2.5", "-0x2.8#3", Nearest, "-2", Greater); test("-123.0", "-0x7b.0#7", Floor, "-123", Equal); test("-123.0", "-0x7b.0#7", Ceiling, "-123", Equal); test("-123.0", "-0x7b.0#7", Down, "-123", Equal); test("-123.0", "-0x7b.0#7", Up, "-123", Equal); test("-123.0", "-0x7b.0#7", Nearest, "-123", Equal); test("-123.0", "-0x7b.0#7", Exact, "-123", Equal); } #[test] fn integer_rounding_from_float_fail() { assert_panic!(Integer::rounding_from(Float::NAN, Floor)); assert_panic!(Integer::rounding_from(Float::NAN, Ceiling)); assert_panic!(Integer::rounding_from(Float::NAN, Down)); assert_panic!(Integer::rounding_from(Float::NAN, Up)); assert_panic!(Integer::rounding_from(Float::NAN, Nearest)); assert_panic!(Integer::rounding_from(Float::NAN, Exact)); assert_panic!(Integer::rounding_from(Float::INFINITY, Floor)); assert_panic!(Integer::rounding_from(Float::INFINITY, Ceiling)); assert_panic!(Integer::rounding_from(Float::INFINITY, Down)); assert_panic!(Integer::rounding_from(Float::INFINITY, Up)); assert_panic!(Integer::rounding_from(Float::INFINITY, Nearest)); assert_panic!(Integer::rounding_from(Float::INFINITY, Exact)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Floor)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Ceiling)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Down)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Up)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Nearest)); assert_panic!(Integer::rounding_from(Float::NEGATIVE_INFINITY, Exact)); assert_panic!(Integer::rounding_from(Float::from(3u8) >> 1, Exact)); assert_panic!(Integer::rounding_from(Float::from(-3i8) >> 1, Exact)); } #[test] fn integer_rounding_from_float_ref_fail() { assert_panic!(Integer::rounding_from(&Float::NAN, Floor)); assert_panic!(Integer::rounding_from(&Float::NAN, Ceiling)); assert_panic!(Integer::rounding_from(&Float::NAN, Down)); assert_panic!(Integer::rounding_from(&Float::NAN, Up)); assert_panic!(Integer::rounding_from(&Float::NAN, Nearest)); assert_panic!(Integer::rounding_from(&Float::NAN, Exact)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Floor)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Ceiling)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Down)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Up)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Nearest)); assert_panic!(Integer::rounding_from(&Float::INFINITY, Exact)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Floor)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Ceiling)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Down)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Up)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Nearest)); assert_panic!(Integer::rounding_from(&Float::NEGATIVE_INFINITY, Exact)); assert_panic!(Integer::rounding_from(&(Float::from(3u8) >> 1), Exact)); assert_panic!(Integer::rounding_from(&(Float::from(-3i8) >> 1), Exact)); } #[test] fn try_from_float_properties() { float_gen().test_properties(|x| { let integer_x = Integer::try_from(x.clone()); assert!(integer_x.as_ref().map_or(true, Integer::is_valid)); let integer_x_alt = Integer::try_from(&x); assert!(integer_x_alt.as_ref().map_or(true, Integer::is_valid)); assert_eq!(integer_x, integer_x_alt); assert_eq!(integer_x.is_ok(), Integer::convertible_from(&x)); if let Ok(n) = integer_x { assert_eq!(Integer::exact_from(&x), n); assert_eq!(n, x); assert_eq!(Float::exact_from(&n), x); assert_eq!(Float::exact_from(n), x); } }); } #[test] fn convertible_from_float_properties() { float_gen().test_properties(|x| { Integer::convertible_from(&x); }); } #[test] fn rounding_from_float_properties() { float_rounding_mode_pair_gen_var_2().test_properties(|(x, rm)| { let no = Integer::rounding_from(&x, rm); assert_eq!(Integer::rounding_from(x.clone(), rm), no); let (n, o) = no; assert!((Rational::from(&n) - Rational::exact_from(&x)).lt_abs(&1)); assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if let Ok(rm) = rug_round_try_from_rounding_mode(rm) { let (rn, ro) = rug::Float::exact_from(&x).to_integer_round(rm).unwrap(); assert_eq!(Integer::from(&rn), n); assert_eq!(ro, o); } }); float_gen_var_4().test_properties(|x| { let floor = Integer::rounding_from(&x, Floor); assert_eq!(floor.0, Rational::exact_from(&x).floor()); assert!(floor.0 <= x); assert!(&floor.0 + Integer::ONE > x); assert_eq!( Integer::rounding_from(&x, if x >= 0 { Down } else { Up }), floor ); let ceiling = Integer::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, Rational::exact_from(&x).ceiling()); assert!(ceiling.0 >= x); assert!(&ceiling.0 - Integer::ONE < x); assert_eq!( Integer::rounding_from(&x, if x >= 0 { Up } else { Down }), ceiling ); let nearest = Integer::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); assert!((Rational::from(nearest.0) - Rational::exact_from(x)).le_abs(&Rational::ONE_HALF)); }); integer_gen().test_properties(|n| { let x = Float::exact_from(&n); let no = (n, Equal); assert_eq!(Integer::rounding_from(&x, Floor), no); assert_eq!(Integer::rounding_from(&x, Down), no); assert_eq!(Integer::rounding_from(&x, Ceiling), no); assert_eq!(Integer::rounding_from(&x, Up), no); assert_eq!(Integer::rounding_from(&x, Nearest), no); assert_eq!(Integer::rounding_from(&x, Exact), no); let x = Float::exact_from((no.0 << 1) | Integer::ONE) >> 1; assert!(Integer::rounding_from(x, Nearest).0.even()); }); } ================================================ FILE: malachite-float/tests/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{float_gen, float_gen_var_12}; use malachite_q::Rational; #[test] fn test_is_integer() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(x.is_integer(), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("123.0", "0x7b.0#7", true); test("1000000000000.0", "0xe8d4a51000.0#40", true); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", false); test("3.141592653589793", "0x3.243f6a8885a3#50", false); test("2.7182818284590451", "0x2.b7e151628aed2#53", false); test("too_big", "0x4.0E+268435455#1", true); test("too_small", "0x1.0E-268435456#1", false); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-123.0", "-0x7b.0#7", true); test("-1000000000000.0", "-0xe8d4a51000.0#40", true); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", false); test("-3.141592653589793", "-0x3.243f6a8885a3#50", false); test("-2.7182818284590451", "-0x2.b7e151628aed2#53", false); test("-too_big", "-0x4.0E+268435455#1", true); test("-too_small", "-0x1.0E-268435456#1", false); } #[allow(clippy::needless_pass_by_value)] fn is_integer_properties_helper(x: Float, extreme: bool) { assert_eq!(x.is_integer(), (-&x).is_integer()); if !extreme && let Ok(q) = Rational::try_from(&x) { assert_eq!(q.is_integer(), x.is_integer()); } } #[test] fn is_integer_properties() { float_gen().test_properties(|x| is_integer_properties_helper(x, false)); float_gen_var_12().test_properties(|x| is_integer_properties_helper(x, true)); } ================================================ FILE: malachite-float/tests/conversion/mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, DivisibleByPowerOf2, Parity}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero, }; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ ExactFrom, IntegerMantissaAndExponent, RawMantissaAndExponent, SciMantissaAndExponent, }; use malachite_base::num::float::NiceFloat; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ primitive_float_gen_var_12, primitive_float_signed_pair_gen_var_3, }; use malachite_float::test_util::common::{parse_hex_string, to_hex_string}; use malachite_float::test_util::generators::{ float_gen_var_3, float_gen_var_13, float_rounding_mode_pair_gen, float_rounding_mode_pair_gen_var_21, float_signed_pair_gen_var_1, }; use malachite_float::{ComparableFloatRef, Float}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_signed_pair_gen_var_2, natural_signed_pair_gen_var_4, }; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_sci_mantissa_and_exponent_round() { fn test(s: &str, s_hex: &str, rm: RoundingMode, out: &str) { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let meo: Option<(T, i32, Ordering)> = x.sci_mantissa_and_exponent_round(rm); if let Some((m, e, o)) = meo { assert_eq!(format!("Some({}, {}, {:?})", NiceFloat(m), e, o), out); } else { assert_eq!("None", out); } } test::("NaN", "NaN", Floor, "None"); test::("NaN", "NaN", Ceiling, "None"); test::("NaN", "NaN", Down, "None"); test::("NaN", "NaN", Up, "None"); test::("NaN", "NaN", Nearest, "None"); test::("NaN", "NaN", Exact, "None"); test::("Infinity", "Infinity", Floor, "None"); test::("Infinity", "Infinity", Ceiling, "None"); test::("Infinity", "Infinity", Down, "None"); test::("Infinity", "Infinity", Up, "None"); test::("Infinity", "Infinity", Nearest, "None"); test::("Infinity", "Infinity", Exact, "None"); test::("-Infinity", "-Infinity", Floor, "None"); test::("-Infinity", "-Infinity", Ceiling, "None"); test::("-Infinity", "-Infinity", Down, "None"); test::("-Infinity", "-Infinity", Up, "None"); test::("-Infinity", "-Infinity", Nearest, "None"); test::("-Infinity", "-Infinity", Exact, "None"); test::("0.0", "0x0.0", Floor, "None"); test::("0.0", "0x0.0", Ceiling, "None"); test::("0.0", "0x0.0", Down, "None"); test::("0.0", "0x0.0", Up, "None"); test::("0.0", "0x0.0", Nearest, "None"); test::("0.0", "0x0.0", Exact, "None"); test::("-0.0", "-0x0.0", Floor, "None"); test::("-0.0", "-0x0.0", Ceiling, "None"); test::("-0.0", "-0x0.0", Down, "None"); test::("-0.0", "-0x0.0", Up, "None"); test::("-0.0", "-0x0.0", Nearest, "None"); test::("-0.0", "-0x0.0", Exact, "None"); test::("1.0", "0x1.0#1", Floor, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Ceiling, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Down, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Up, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Nearest, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Exact, "Some(1.0, 0, Equal)"); test::("123.0", "0x7b.0#7", Floor, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Ceiling, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Down, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Up, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Nearest, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Exact, "Some(1.921875, 6, Equal)"); test::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "Some(1.3333333, -2, Less)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "Some(1.3333334, -2, Greater)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Down, "Some(1.3333333, -2, Less)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Up, "Some(1.3333334, -2, Greater)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "Some(1.3333334, -2, Greater)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Exact, "None", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Floor, "Some(1.5707963, 1, Less)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Ceiling, "Some(1.5707964, 1, Greater)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Down, "Some(1.5707963, 1, Less)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Up, "Some(1.5707964, 1, Greater)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Nearest, "Some(1.5707964, 1, Greater)", ); test::("3.141592653589793", "0x3.243f6a8885a3#50", Exact, "None"); test::( "1000000000000.0", "0xe8d4a51000.0#40", Floor, "Some(1.8189894, 39, Less)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Ceiling, "Some(1.8189895, 39, Greater)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Down, "Some(1.8189894, 39, Less)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Up, "Some(1.8189895, 39, Greater)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Nearest, "Some(1.8189894, 39, Less)", ); test::("1000000000000.0", "0xe8d4a51000.0#40", Exact, "None"); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Floor, "Some(1.6543611, 79, Less)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Ceiling, "Some(1.6543612, 79, Greater)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Down, "Some(1.6543611, 79, Less)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Up, "Some(1.6543612, 79, Greater)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Nearest, "Some(1.6543612, 79, Greater)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Exact, "None", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Floor, "Some(1.9999999, -1, Less)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Ceiling, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Down, "Some(1.9999999, -1, Less)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Up, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Nearest, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Exact, "None", ); test::( "too_big", "0x4.0E+268435455#1", Floor, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Ceiling, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Down, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Up, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Nearest, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Exact, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.000001E+268435455#27", Floor, "Some(1.0, 1073741822, Less)", ); test::( "too_big", "0x4.000001E+268435455#27", Ceiling, "Some(1.0000001, 1073741822, Greater)", ); test::( "too_big", "0x4.000001E+268435455#27", Down, "Some(1.0, 1073741822, Less)", ); test::( "too_big", "0x4.000001E+268435455#27", Up, "Some(1.0000001, 1073741822, Greater)", ); test::( "too_big", "0x4.000001E+268435455#27", Nearest, "Some(1.0, 1073741822, Less)", ); test::("too_big", "0x4.000001E+268435455#27", Exact, "None"); test::( "too_small", "0x1.0E-268435456#1", Floor, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Ceiling, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Down, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Up, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Nearest, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Exact, "Some(1.0, -1073741824, Equal)", ); test::("-1.0", "-0x1.0#1", Floor, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Ceiling, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Down, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Up, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Nearest, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Exact, "Some(1.0, 0, Equal)"); test::("-123.0", "-0x7b.0#7", Floor, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Ceiling, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Down, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Up, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Nearest, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Exact, "Some(1.921875, 6, Equal)"); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "Some(1.3333333, -2, Less)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "Some(1.3333334, -2, Greater)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "Some(1.3333333, -2, Less)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "Some(1.3333334, -2, Greater)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "Some(1.3333334, -2, Greater)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Exact, "None", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Floor, "Some(1.5707963, 1, Less)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Ceiling, "Some(1.5707964, 1, Greater)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Down, "Some(1.5707963, 1, Less)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Up, "Some(1.5707964, 1, Greater)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Nearest, "Some(1.5707964, 1, Greater)", ); test::("-3.141592653589793", "-0x3.243f6a8885a3#50", Exact, "None"); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Floor, "Some(1.8189894, 39, Less)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Ceiling, "Some(1.8189895, 39, Greater)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Down, "Some(1.8189894, 39, Less)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Up, "Some(1.8189895, 39, Greater)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Nearest, "Some(1.8189894, 39, Less)", ); test::("-1000000000000.0", "-0xe8d4a51000.0#40", Exact, "None"); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Floor, "Some(1.6543611, 79, Less)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Ceiling, "Some(1.6543612, 79, Greater)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Down, "Some(1.6543611, 79, Less)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Up, "Some(1.6543612, 79, Greater)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Nearest, "Some(1.6543612, 79, Greater)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Exact, "None", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Floor, "Some(1.9999999, -1, Less)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Ceiling, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Down, "Some(1.9999999, -1, Less)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Up, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Nearest, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Exact, "None", ); test::( "-too_big", "-0x4.0E+268435455#1", Floor, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Ceiling, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Down, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Up, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Nearest, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Exact, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.000001E+268435455#27", Floor, "Some(1.0, 1073741822, Less)", ); test::( "-too_big", "-0x4.000001E+268435455#27", Ceiling, "Some(1.0000001, 1073741822, Greater)", ); test::( "-too_big", "-0x4.000001E+268435455#27", Down, "Some(1.0, 1073741822, Less)", ); test::( "-too_big", "-0x4.000001E+268435455#27", Up, "Some(1.0000001, 1073741822, Greater)", ); test::( "-too_big", "-0x4.000001E+268435455#27", Nearest, "Some(1.0, 1073741822, Less)", ); test::("-too_big", "-0x4.000001E+268435455#27", Exact, "None"); test::( "-too_small", "-0x1.0E-268435456#1", Floor, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Ceiling, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Down, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Up, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Nearest, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Exact, "Some(1.0, -1073741824, Equal)", ); test::("NaN", "NaN", Floor, "None"); test::("NaN", "NaN", Ceiling, "None"); test::("NaN", "NaN", Down, "None"); test::("NaN", "NaN", Up, "None"); test::("NaN", "NaN", Nearest, "None"); test::("NaN", "NaN", Exact, "None"); test::("Infinity", "Infinity", Floor, "None"); test::("Infinity", "Infinity", Ceiling, "None"); test::("Infinity", "Infinity", Down, "None"); test::("Infinity", "Infinity", Up, "None"); test::("Infinity", "Infinity", Nearest, "None"); test::("Infinity", "Infinity", Exact, "None"); test::("-Infinity", "-Infinity", Floor, "None"); test::("-Infinity", "-Infinity", Ceiling, "None"); test::("-Infinity", "-Infinity", Down, "None"); test::("-Infinity", "-Infinity", Up, "None"); test::("-Infinity", "-Infinity", Nearest, "None"); test::("-Infinity", "-Infinity", Exact, "None"); test::("0.0", "0x0.0", Floor, "None"); test::("0.0", "0x0.0", Ceiling, "None"); test::("0.0", "0x0.0", Down, "None"); test::("0.0", "0x0.0", Up, "None"); test::("0.0", "0x0.0", Nearest, "None"); test::("0.0", "0x0.0", Exact, "None"); test::("-0.0", "-0x0.0", Floor, "None"); test::("-0.0", "-0x0.0", Ceiling, "None"); test::("-0.0", "-0x0.0", Down, "None"); test::("-0.0", "-0x0.0", Up, "None"); test::("-0.0", "-0x0.0", Nearest, "None"); test::("-0.0", "-0x0.0", Exact, "None"); test::("1.0", "0x1.0#1", Floor, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Ceiling, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Down, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Up, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Nearest, "Some(1.0, 0, Equal)"); test::("1.0", "0x1.0#1", Exact, "Some(1.0, 0, Equal)"); test::("123.0", "0x7b.0#7", Floor, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Ceiling, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Down, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Up, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Nearest, "Some(1.921875, 6, Equal)"); test::("123.0", "0x7b.0#7", Exact, "Some(1.921875, 6, Equal)"); test::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "Some(1.3333333333333333, -2, Equal)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "Some(1.3333333333333333, -2, Equal)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Down, "Some(1.3333333333333333, -2, Equal)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Up, "Some(1.3333333333333333, -2, Equal)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "Some(1.3333333333333333, -2, Equal)", ); test::( "0.33333333333333331", "0x0.55555555555554#53", Exact, "Some(1.3333333333333333, -2, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Floor, "Some(1.5707963267948966, 1, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Ceiling, "Some(1.5707963267948966, 1, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Down, "Some(1.5707963267948966, 1, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Up, "Some(1.5707963267948966, 1, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Nearest, "Some(1.5707963267948966, 1, Equal)", ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", Exact, "Some(1.5707963267948966, 1, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Floor, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Ceiling, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Down, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Up, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Nearest, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000.0", "0xe8d4a51000.0#40", Exact, "Some(1.8189894035458565, 39, Equal)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Floor, "Some(1.6543612251060553, 79, Less)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Ceiling, "Some(1.6543612251060555, 79, Greater)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Down, "Some(1.6543612251060553, 79, Less)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Up, "Some(1.6543612251060555, 79, Greater)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Nearest, "Some(1.6543612251060553, 79, Less)", ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", Exact, "None", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Floor, "Some(1.9999999999999998, -1, Less)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Ceiling, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Down, "Some(1.9999999999999998, -1, Less)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Up, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Nearest, "Some(1.0, 0, Greater)", ); test::( "0.999999999999999999999999", "0x0.ffffffffffffffffffff#80", Exact, "None", ); test::( "too_big", "0x4.0E+268435455#1", Floor, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Ceiling, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Down, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Up, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Nearest, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0E+268435455#1", Exact, "Some(1.0, 1073741822, Equal)", ); test::( "too_big", "0x4.0000000000001E+268435455#55", Floor, "Some(1.0, 1073741822, Less)", ); test::( "too_big", "0x4.0000000000001E+268435455#55", Ceiling, "Some(1.0000000000000002, 1073741822, Greater)", ); test::( "too_big", "0x4.0000000000001E+268435455#55", Down, "Some(1.0, 1073741822, Less)", ); test::( "too_big", "0x4.0000000000001E+268435455#55", Up, "Some(1.0000000000000002, 1073741822, Greater)", ); test::( "too_big", "0x4.0000000000001E+268435455#55", Nearest, "Some(1.0, 1073741822, Less)", ); test::("too_big", "0x4.0000000000001E+268435455#55", Exact, "None"); test::( "too_small", "0x1.0E-268435456#1", Floor, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Ceiling, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Down, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Up, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Nearest, "Some(1.0, -1073741824, Equal)", ); test::( "too_small", "0x1.0E-268435456#1", Exact, "Some(1.0, -1073741824, Equal)", ); test::("-1.0", "-0x1.0#1", Floor, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Ceiling, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Down, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Up, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Nearest, "Some(1.0, 0, Equal)"); test::("-1.0", "-0x1.0#1", Exact, "Some(1.0, 0, Equal)"); test::("-123.0", "-0x7b.0#7", Floor, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Ceiling, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Down, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Up, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Nearest, "Some(1.921875, 6, Equal)"); test::("-123.0", "-0x7b.0#7", Exact, "Some(1.921875, 6, Equal)"); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "Some(1.3333333333333333, -2, Equal)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "Some(1.3333333333333333, -2, Equal)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "Some(1.3333333333333333, -2, Equal)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "Some(1.3333333333333333, -2, Equal)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "Some(1.3333333333333333, -2, Equal)", ); test::( "-0.33333333333333331", "-0x0.55555555555554#53", Exact, "Some(1.3333333333333333, -2, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Floor, "Some(1.5707963267948966, 1, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Ceiling, "Some(1.5707963267948966, 1, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Down, "Some(1.5707963267948966, 1, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Up, "Some(1.5707963267948966, 1, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Nearest, "Some(1.5707963267948966, 1, Equal)", ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", Exact, "Some(1.5707963267948966, 1, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Floor, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Ceiling, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Down, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Up, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Nearest, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", Exact, "Some(1.8189894035458565, 39, Equal)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Floor, "Some(1.6543612251060553, 79, Less)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Ceiling, "Some(1.6543612251060555, 79, Greater)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Down, "Some(1.6543612251060553, 79, Less)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Up, "Some(1.6543612251060555, 79, Greater)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Nearest, "Some(1.6543612251060553, 79, Less)", ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", Exact, "None", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Floor, "Some(1.9999999999999998, -1, Less)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Ceiling, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Down, "Some(1.9999999999999998, -1, Less)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Up, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Nearest, "Some(1.0, 0, Greater)", ); test::( "-0.999999999999999999999999", "-0x0.ffffffffffffffffffff#80", Exact, "None", ); test::( "-too_big", "-0x4.0E+268435455#1", Floor, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Ceiling, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Down, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Up, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Nearest, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0E+268435455#1", Exact, "Some(1.0, 1073741822, Equal)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Floor, "Some(1.0, 1073741822, Less)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Ceiling, "Some(1.0000000000000002, 1073741822, Greater)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Down, "Some(1.0, 1073741822, Less)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Up, "Some(1.0000000000000002, 1073741822, Greater)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Nearest, "Some(1.0, 1073741822, Less)", ); test::( "-too_big", "-0x4.0000000000001E+268435455#55", Exact, "None", ); test::( "-too_small", "-0x1.0E-268435456#1", Floor, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Ceiling, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Down, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Up, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Nearest, "Some(1.0, -1073741824, Equal)", ); test::( "-too_small", "-0x1.0E-268435456#1", Exact, "Some(1.0, -1073741824, Equal)", ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_raw_mantissa_and_exponent() { let test = |s, s_hex, m_out, e_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (m, e) = x.clone().raw_mantissa_and_exponent(); assert_eq!(m.to_string(), m_out); assert_eq!(e, e_out); let (m_alt, e_alt) = (&x).raw_mantissa_and_exponent(); assert_eq!(m_alt, m); assert_eq!(e_alt, e); assert_eq!(x.clone().raw_mantissa(), m); assert_eq!((&x).raw_mantissa(), m); assert_eq!(x.clone().raw_exponent(), e); assert_eq!((&x).raw_exponent(), e); }; test("1.0", "0x1.0#1", "9223372036854775808", 1); test("2.0", "0x2.0#1", "9223372036854775808", 2); test("0.5", "0x0.8#1", "9223372036854775808", 0); test( "0.33333333333333331", "0x0.55555555555554#53", "12297829382473033728", -1, ); test("123.0", "0x7b.0#7", "17726168133330272256", 7); test( "1000000000000.0", "0xe8d4a51000.0#40", "16777216000000000000", 40, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "13043817825332783104", 1, ); test( "3.141592653589793", "0x3.243f6a8885a3#50", "14488038916154245120", 2, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", "12535862302449813504", 2, ); test( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", "281474976710656000000000000000000000000", 80, ); test( "too_big", "0x4.0E+268435455#1", "9223372036854775808", 1073741823, ); test( "too_small", "0x1.0E-268435456#1", "9223372036854775808", -1073741823, ); test("-1.0", "-0x1.0#1", "9223372036854775808", 1); test("-2.0", "-0x2.0#1", "9223372036854775808", 2); test("-0.5", "-0x0.8#1", "9223372036854775808", 0); test( "-0.33333333333333331", "-0x0.55555555555554#53", "12297829382473033728", -1, ); test("-123.0", "-0x7b.0#7", "17726168133330272256", 7); test( "-1000000000000.0", "-0xe8d4a51000.0#40", "16777216000000000000", 40, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "13043817825332783104", 1, ); test( "-3.141592653589793", "-0x3.243f6a8885a3#50", "14488038916154245120", 2, ); test( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "12535862302449813504", 2, ); test( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", "281474976710656000000000000000000000000", 80, ); test( "-too_big", "-0x4.0E+268435455#1", "9223372036854775808", 1073741823, ); test( "-too_small", "-0x1.0E-268435456#1", "9223372036854775808", -1073741823, ); } #[test] fn raw_mantissa_and_exponent_fail() { assert_panic!(Float::NAN.raw_mantissa_and_exponent()); assert_panic!(Float::INFINITY.raw_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.raw_mantissa_and_exponent()); assert_panic!(Float::ZERO.raw_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_ZERO.raw_mantissa_and_exponent()); assert_panic!(Float::NAN.raw_mantissa()); assert_panic!(Float::INFINITY.raw_mantissa()); assert_panic!(Float::NEGATIVE_INFINITY.raw_mantissa()); assert_panic!(Float::ZERO.raw_mantissa()); assert_panic!(Float::NEGATIVE_ZERO.raw_mantissa()); assert_panic!(Float::NAN.raw_exponent()); assert_panic!(Float::INFINITY.raw_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.raw_exponent()); assert_panic!(Float::ZERO.raw_exponent()); assert_panic!(Float::NEGATIVE_ZERO.raw_exponent()); } #[test] fn raw_mantissa_and_exponent_ref_fail() { assert_panic!((&Float::NAN).raw_mantissa_and_exponent()); assert_panic!((&Float::INFINITY).raw_mantissa_and_exponent()); assert_panic!((&Float::NEGATIVE_INFINITY).raw_mantissa_and_exponent()); assert_panic!((&Float::ZERO).raw_mantissa_and_exponent()); assert_panic!((&Float::NEGATIVE_ZERO).raw_mantissa_and_exponent()); assert_panic!((&Float::NAN).raw_mantissa()); assert_panic!((&Float::INFINITY).raw_mantissa()); assert_panic!((&Float::NEGATIVE_INFINITY).raw_mantissa()); assert_panic!((&Float::ZERO).raw_mantissa()); assert_panic!((&Float::NEGATIVE_ZERO).raw_mantissa()); assert_panic!((&Float::NAN).raw_exponent()); assert_panic!((&Float::INFINITY).raw_exponent()); assert_panic!((&Float::NEGATIVE_INFINITY).raw_exponent()); assert_panic!((&Float::ZERO).raw_exponent()); assert_panic!((&Float::NEGATIVE_ZERO).raw_exponent()); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_from_raw_mantissa_and_exponent() { let test = |m, e, out, out_hex| { let m = Natural::from_str(m).unwrap(); let x = Float::from_raw_mantissa_and_exponent(m.clone(), e); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(to_hex_string(&x), out_hex); let x_alt = <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent(m, e); assert!(x_alt.is_valid()); assert_eq!(x_alt, x); }; test("9223372036854775808", 1, "1.0", "0x1.0#1"); test( "9223372036854775809", 1, "1.0000000000000000001", "0x1.0000000000000002#64", ); test( "18446744073709551615", 1, "1.9999999999999999999", "0x1.fffffffffffffffe#64", ); test( "170141183460469231731687303715884105728", 1, "1.0", "0x1.0000000000000000#65", ); test("9223372036854775808", 2, "2.0", "0x2.0#1"); test("9223372036854775808", 0, "0.5", "0x0.8#1"); test( "12297829382473033728", -1, "0.33333333333333331", "0x0.55555555555554#53", ); test("17726168133330272256", 7, "123.0", "0x7b.0#7"); test("16777216000000000000", 40, "1.0e12", "0xe.8d4a51E+9#28"); test( "13043817825332783104", 1, "1.4142135623730951", "0x1.6a09e667f3bcd#53", ); test( "14488038916154245120", 2, "3.141592653589793", "0x3.243f6a8885a3#50", ); test( "12535862302449813504", 2, "2.7182818284590451", "0x2.b7e151628aed2#53", ); test( "281474976710656000000000000000000000000", 80, "1.0e24", "0xd.3c21bcecceda1000E+19#65", ); test( "9223372036854775808", 1073741823, "too_big", "0x4.0E+268435455#1", ); test( "9223372036854775808", -1073741823, "too_small", "0x1.0E-268435456#1", ); } #[test] fn from_raw_mantissa_and_exponent_float_fail() { assert_panic!(Float::from_raw_mantissa_and_exponent(Natural::ZERO, 0)); assert_panic!(Float::from_raw_mantissa_and_exponent(Natural::ONE, 0)); assert_panic!(Float::from_raw_mantissa_and_exponent( Natural::from_str("9223372036854775808").unwrap(), 1073741824 )); assert_panic!(Float::from_raw_mantissa_and_exponent( Natural::from_str("9223372036854775808").unwrap(), -1073741824 )); assert_panic!( <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( Natural::ZERO, 0 ) ); assert_panic!( <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( Natural::ONE, 0 ) ); assert_panic!( <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( Natural::from_str("9223372036854775808").unwrap(), 1073741824 ) ); assert_panic!( <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( Natural::from_str("9223372036854775808").unwrap(), -1073741824 ) ); } #[test] fn test_integer_mantissa_and_exponent() { let test = |s, s_hex, m_out, e_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (m, e) = x.clone().integer_mantissa_and_exponent(); assert_eq!(m.to_string(), m_out); assert_eq!(e, e_out); let (m_alt, e_alt) = (&x).integer_mantissa_and_exponent(); assert_eq!(m_alt, m); assert_eq!(e_alt, e); assert_eq!(x.clone().integer_mantissa(), m); assert_eq!((&x).integer_mantissa(), m); assert_eq!(x.clone().integer_exponent(), e); assert_eq!((&x).integer_exponent(), e); }; test("1.0", "0x1.0#1", "1", 0); test("2.0", "0x2.0#1", "1", 1); test("0.5", "0x0.8#1", "1", -1); test( "0.33333333333333331", "0x0.55555555555554#53", "6004799503160661", -54, ); test("123.0", "0x7b.0#7", "123", 0); test("1000000000000.0", "0xe8d4a51000.0#40", "244140625", 12); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "6369051672525773", -52, ); test( "3.141592653589793", "0x3.243f6a8885a3#50", "884279719003555", -48, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", "6121026514868073", -51, ); test( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", "59604644775390625", 24, ); test("too_big", "0x4.0E+268435455#1", "1", 1073741822); test("too_small", "0x1.0E-268435456#1", "1", -1073741824); test( "too_small", "0x1.0000001E-268435456#29", "268435457", -1073741852, ); test("-1.0", "-0x1.0#1", "1", 0); test("-2.0", "-0x2.0#1", "1", 1); test("-0.5", "-0x0.8#1", "1", -1); test( "-0.33333333333333331", "-0x0.55555555555554#53", "6004799503160661", -54, ); test("-123.0", "-0x7b.0#7", "123", 0); test("-1000000000000.0", "-0xe8d4a51000.0#40", "244140625", 12); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "6369051672525773", -52, ); test( "-3.141592653589793", "-0x3.243f6a8885a3#50", "884279719003555", -48, ); test( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "6121026514868073", -51, ); test( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", "59604644775390625", 24, ); test("-too_big", "-0x4.0E+268435455#1", "1", 1073741822); test("-too_small", "-0x1.0E-268435456#1", "1", -1073741824); test( "-too_small", "-0x1.0000001E-268435456#29", "268435457", -1073741852, ); } #[test] fn integer_mantissa_and_exponent_fail() { assert_panic!(Float::NAN.integer_mantissa_and_exponent()); assert_panic!(Float::INFINITY.integer_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.integer_mantissa_and_exponent()); assert_panic!(Float::ZERO.integer_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_ZERO.integer_mantissa_and_exponent()); assert_panic!(Float::NAN.integer_mantissa()); assert_panic!(Float::INFINITY.integer_mantissa()); assert_panic!(Float::NEGATIVE_INFINITY.integer_mantissa()); assert_panic!(Float::ZERO.integer_mantissa()); assert_panic!(Float::NEGATIVE_ZERO.integer_mantissa()); assert_panic!(Float::NAN.integer_exponent()); assert_panic!(Float::INFINITY.integer_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.integer_exponent()); assert_panic!(Float::ZERO.integer_exponent()); assert_panic!(Float::NEGATIVE_ZERO.integer_exponent()); } #[test] fn integer_mantissa_and_exponent_ref_fail() { assert_panic!((&Float::NAN).integer_mantissa_and_exponent()); assert_panic!((&Float::INFINITY).integer_mantissa_and_exponent()); assert_panic!((&Float::NEGATIVE_INFINITY).integer_mantissa_and_exponent()); assert_panic!((&Float::ZERO).integer_mantissa_and_exponent()); assert_panic!((&Float::NEGATIVE_ZERO).integer_mantissa_and_exponent()); assert_panic!((&Float::NAN).integer_mantissa()); assert_panic!((&Float::INFINITY).integer_mantissa()); assert_panic!((&Float::NEGATIVE_INFINITY).integer_mantissa()); assert_panic!((&Float::ZERO).integer_mantissa()); assert_panic!((&Float::NEGATIVE_ZERO).integer_mantissa()); assert_panic!((&Float::NAN).integer_exponent()); assert_panic!((&Float::INFINITY).integer_exponent()); assert_panic!((&Float::NEGATIVE_INFINITY).integer_exponent()); assert_panic!((&Float::ZERO).integer_exponent()); assert_panic!((&Float::NEGATIVE_ZERO).integer_exponent()); } #[test] fn test_from_integer_mantissa_and_exponent() { let test = |m, e, out, out_hex| { let m = Natural::from_str(m).unwrap(); let ox = Float::from_integer_mantissa_and_exponent(m.clone(), e); assert!(ox.as_ref().is_none_or(Float::is_valid)); let os = ox.as_ref().map(ToString::to_string); assert_eq!(os.as_deref(), out); let os = ox.as_ref().map(to_hex_string); assert_eq!(os.as_deref(), out_hex); let ox_alt = <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( m, e, ); assert!(ox_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(ox_alt, ox); }; test("0", 0, Some("0.0"), Some("0x0.0")); test("0", 10, Some("0.0"), Some("0x0.0")); test("0", -10, Some("0.0"), Some("0x0.0")); test("1", 0, Some("1.0"), Some("0x1.0#1")); test("1", 1, Some("2.0"), Some("0x2.0#1")); test("1", -1, Some("0.5"), Some("0x0.8#1")); test("2", -1, Some("1.0"), Some("0x1.0#1")); test("2", 0, Some("2.0"), Some("0x2.0#1")); test("2", -2, Some("0.5"), Some("0x0.8#1")); test( "6004799503160661", -54, Some("0.33333333333333331"), Some("0x0.55555555555554#53"), ); test("123", 0, Some("123.0"), Some("0x7b.0#7")); test("244140625", 12, Some("1.0e12"), Some("0xe.8d4a51E+9#28")); test( "6369051672525773", -52, Some("1.4142135623730951"), Some("0x1.6a09e667f3bcd#53"), ); test( "884279719003555", -48, Some("3.141592653589793"), Some("0x3.243f6a8885a3#50"), ); test( "6121026514868073", -51, Some("2.7182818284590451"), Some("0x2.b7e151628aed2#53"), ); test( "59604644775390625", 24, Some("1.0e24"), Some("0xd.3c21bcecceda1E+19#56"), ); test("1", 1073741822, Some("too_big"), Some("0x4.0E+268435455#1")); test( "1", -1073741824, Some("too_small"), Some("0x1.0E-268435456#1"), ); test( "268435457", -1073741852, Some("too_small"), Some("0x1.0000001E-268435456#29"), ); test("1", 1073741823, None, None); test("1", -1073741852, None, None); } #[test] fn test_sci_mantissa_and_exponent_float() { let test = |s, s_hex, m_out, m_out_hex, e_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (m, e) = x.clone().sci_mantissa_and_exponent(); assert!(m.is_valid()); assert_eq!(m.to_string(), m_out); assert_eq!(to_hex_string(&m), m_out_hex); assert_eq!(e, e_out); let (m_alt, e_alt): (Float, i32) = (&x).sci_mantissa_and_exponent(); assert!(m_alt.is_valid()); assert_eq!(ComparableFloatRef(&m_alt), ComparableFloatRef(&m)); assert_eq!(e_alt, e); let mantissa_alt: Float = x.clone().sci_mantissa(); assert!(mantissa_alt.is_valid()); assert_eq!(ComparableFloatRef(&mantissa_alt), ComparableFloatRef(&m)); let mantissa_alt: Float = (&x).sci_mantissa(); assert!(mantissa_alt.is_valid()); assert_eq!(ComparableFloatRef(&mantissa_alt), ComparableFloatRef(&m)); assert_eq!(x.clone().sci_exponent(), e); assert_eq!( <&Float as SciMantissaAndExponent>::sci_exponent(&x), e ); }; test("1.0", "0x1.0#1", "1.0", "0x1.0#1", 0); test("2.0", "0x2.0#1", "1.0", "0x1.0#1", 1); test("0.5", "0x0.8#1", "1.0", "0x1.0#1", -1); test( "0.33333333333333331", "0x0.55555555555554#53", "1.3333333333333333", "0x1.5555555555555#53", -2, ); test("123.0", "0x7b.0#7", "1.92", "0x1.ec#7", 6); test( "1000000000000.0", "0xe8d4a51000.0#40", "1.818989403546", "0x1.d1a94a2000#40", 39, ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, ); test( "3.141592653589793", "0x3.243f6a8885a3#50", "1.570796326794897", "0x1.921fb54442d18#50", 1, ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", "1.3591409142295225", "0x1.5bf0a8b145769#53", 1, ); test( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", "1.654361225106055349742817", "0x1.a784379d99db42000000#80", 79, ); test( "too_big", "0x4.0E+268435455#1", "1.0", "0x1.0#1", 1073741822, ); test( "too_small", "0x1.0E-268435456#1", "1.0", "0x1.0#1", -1073741824, ); test("-1.0", "-0x1.0#1", "1.0", "0x1.0#1", 0); test("-2.0", "-0x2.0#1", "1.0", "0x1.0#1", 1); test("-0.5", "-0x0.8#1", "1.0", "0x1.0#1", -1); test( "-0.33333333333333331", "-0x0.55555555555554#53", "1.3333333333333333", "0x1.5555555555555#53", -2, ); test("-123.0", "-0x7b.0#7", "1.92", "0x1.ec#7", 6); test( "-1000000000000.0", "-0xe8d4a51000.0#40", "1.818989403546", "0x1.d1a94a2000#40", 39, ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, ); test( "-3.141592653589793", "-0x3.243f6a8885a3#50", "1.570796326794897", "0x1.921fb54442d18#50", 1, ); test( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "1.3591409142295225", "0x1.5bf0a8b145769#53", 1, ); test( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", "1.654361225106055349742817", "0x1.a784379d99db42000000#80", 79, ); test( "-too_big", "-0x4.0E+268435455#1", "1.0", "0x1.0#1", 1073741822, ); test( "-too_small", "-0x1.0E-268435456#1", "1.0", "0x1.0#1", -1073741824, ); } #[test] fn sci_mantissa_and_exponent_float_fail() { assert_panic!(Float::NAN.sci_mantissa_and_exponent()); assert_panic!(Float::INFINITY.sci_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.sci_mantissa_and_exponent()); assert_panic!(Float::ZERO.sci_mantissa_and_exponent()); assert_panic!(Float::NEGATIVE_ZERO.sci_mantissa_and_exponent()); assert_panic!(Float::NAN.sci_mantissa()); assert_panic!(Float::INFINITY.sci_mantissa()); assert_panic!(Float::NEGATIVE_INFINITY.sci_mantissa()); assert_panic!(Float::ZERO.sci_mantissa()); assert_panic!(Float::NEGATIVE_ZERO.sci_mantissa()); assert_panic!(Float::NAN.sci_exponent()); assert_panic!(Float::INFINITY.sci_exponent()); assert_panic!(Float::NEGATIVE_INFINITY.sci_exponent()); assert_panic!(Float::ZERO.sci_exponent()); assert_panic!(Float::NEGATIVE_ZERO.sci_exponent()); } #[test] fn sci_mantissa_and_exponent_float_ref_fail() { assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&Float::NAN) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent( &Float::INFINITY ) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent( &Float::NEGATIVE_INFINITY ) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&Float::ZERO) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent( &Float::NEGATIVE_ZERO ) ); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa(&Float::NAN)); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa(&Float::INFINITY)); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa(&Float::NEGATIVE_INFINITY) ); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa(&Float::ZERO)); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa(&Float::NEGATIVE_ZERO) ); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent(&Float::NAN)); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent(&Float::INFINITY)); assert_panic!( <&Float as SciMantissaAndExponent>::sci_exponent(&Float::NEGATIVE_INFINITY) ); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent(&Float::ZERO)); assert_panic!( <&Float as SciMantissaAndExponent>::sci_exponent(&Float::NEGATIVE_ZERO) ); } #[test] fn test_from_sci_mantissa_and_exponent_float() { let test = |ms, ms_hex, e, out, out_hex| { let m = parse_hex_string(ms_hex); assert_eq!(m.to_string(), ms); let ox = Float::from_sci_mantissa_and_exponent(m.clone(), e); assert!(ox.as_ref().is_none_or(Float::is_valid)); let os = ox.as_ref().map(ToString::to_string); assert_eq!(os.as_deref(), out); let os = ox.as_ref().map(to_hex_string); assert_eq!(os.as_deref(), out_hex); let ox_alt = <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e); assert!(ox_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(ox_alt, ox); }; test("1.0", "0x1.0#1", 0, Some("1.0"), Some("0x1.0#1")); test("1.0", "0x1.0#1", 1, Some("2.0"), Some("0x2.0#1")); test("1.0", "0x1.0#1", -1, Some("0.5"), Some("0x0.8#1")); test( "1.3333333333333333", "0x1.5555555555555#53", -2, Some("0.33333333333333331"), Some("0x0.55555555555554#53"), ); test("1.92", "0x1.ec#7", 6, Some("123.0"), Some("0x7b.0#7")); test( "1.818989403546", "0x1.d1a94a2000#40", 39, Some("1000000000000.0"), Some("0xe8d4a51000.0#40"), ); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", 0, Some("1.4142135623730951"), Some("0x1.6a09e667f3bcd#53"), ); test( "1.570796326794897", "0x1.921fb54442d18#50", 1, Some("3.141592653589793"), Some("0x3.243f6a8885a3#50"), ); test( "1.3591409142295225", "0x1.5bf0a8b145769#53", 1, Some("2.7182818284590451"), Some("0x2.b7e151628aed2#53"), ); test( "1.654361225106055349742817", "0x1.a784379d99db42000000#80", 79, Some("1000000000000000000000000.0"), Some("0xd3c21bcecceda1000000.0#80"), ); test( "1.0", "0x1.0#1", 1073741822, Some("too_big"), Some("0x4.0E+268435455#1"), ); test( "1.0", "0x1.0#1", -1073741824, Some("too_small"), Some("0x1.0E-268435456#1"), ); test("1.0", "0x1.0#1", 1073741823, None, None); test("1.0", "0x1.0#1", -1073741825, None, None); test("-1.0", "-0x1.0#1", 0, None, None); test("2.0", "0x2.0#1", 0, None, None); test("0.5", "0x0.8#1", 0, None, None); } #[test] fn from_sci_mantissa_and_exponent_float_fail() { assert_panic!(Float::from_sci_mantissa_and_exponent(Float::NAN, 0)); assert_panic!(Float::from_sci_mantissa_and_exponent(Float::INFINITY, 0)); assert_panic!(Float::from_sci_mantissa_and_exponent( Float::NEGATIVE_INFINITY, 0 )); assert_panic!(Float::from_sci_mantissa_and_exponent(Float::ZERO, 0)); assert_panic!(Float::from_sci_mantissa_and_exponent( Float::NEGATIVE_ZERO, 0 )); } #[test] fn test_sci_mantissa_and_exponent_primitive_float() { fn test(s: &str, s_hex: &str, m_out: &str, e_out: i32) where for<'a> &'a Float: SciMantissaAndExponent, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (m, e): (T, i32) = (&x).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(m).to_string(), m_out); assert_eq!(e, e_out); assert_eq!(NiceFloat((&x).sci_mantissa()), NiceFloat(m)); assert_eq!( <&Float as SciMantissaAndExponent>::sci_exponent(&x), e ); } test::("1.0", "0x1.0#1", "1.0", 0); test::("2.0", "0x2.0#1", "1.0", 1); test::("0.5", "0x0.8#1", "1.0", -1); test::( "0.33333333333333331", "0x0.55555555555554#53", "1.3333334", -2, ); test::("123.0", "0x7b.0#7", "1.921875", 6); test::("1000000000000.0", "0xe8d4a51000.0#40", "1.8189894", 39); test::("1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135", 0); test::("3.141592653589793", "0x3.243f6a8885a3#50", "1.5707964", 1); test::("2.7182818284590451", "0x2.b7e151628aed2#53", "1.3591409", 1); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", "1.6543612", 79, ); test::("too_big", "0x4.0E+268435455#1", "1.0", 1073741822); test::("too_small", "0x1.0E-268435456#1", "1.0", -1073741824); test::("-1.0", "-0x1.0#1", "1.0", 0); test::("-2.0", "-0x2.0#1", "1.0", 1); test::("-0.5", "-0x0.8#1", "1.0", -1); test::( "-0.33333333333333331", "-0x0.55555555555554#53", "1.3333334", -2, ); test::("-123.0", "-0x7b.0#7", "1.921875", 6); test::("-1000000000000.0", "-0xe8d4a51000.0#40", "1.8189894", 39); test::( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1.4142135", 0, ); test::("-3.141592653589793", "-0x3.243f6a8885a3#50", "1.5707964", 1); test::( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "1.3591409", 1, ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", "1.6543612", 79, ); test::("1.0", "0x1.0#1", "1.0", 0); test::("2.0", "0x2.0#1", "1.0", 1); test::("0.5", "0x0.8#1", "1.0", -1); test::( "0.33333333333333331", "0x0.55555555555554#53", "1.3333333333333333", -2, ); test::("123.0", "0x7b.0#7", "1.921875", 6); test::( "1000000000000.0", "0xe8d4a51000.0#40", "1.8189894035458565", 39, ); test::( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "1.4142135623730951", 0, ); test::( "3.141592653589793", "0x3.243f6a8885a3#50", "1.5707963267948966", 1, ); test::( "2.7182818284590451", "0x2.b7e151628aed2#53", "1.3591409142295225", 1, ); test::( "1000000000000000000000000.0", "0xd3c21bcecceda1000000.0#80", "1.6543612251060553", 79, ); test::("-1.0", "-0x1.0#1", "1.0", 0); test::("-2.0", "-0x2.0#1", "1.0", 1); test::("-0.5", "-0x0.8#1", "1.0", -1); test::( "-0.33333333333333331", "-0x0.55555555555554#53", "1.3333333333333333", -2, ); test::("-123.0", "-0x7b.0#7", "1.921875", 6); test::( "-1000000000000.0", "-0xe8d4a51000.0#40", "1.8189894035458565", 39, ); test::( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "1.4142135623730951", 0, ); test::( "-3.141592653589793", "-0x3.243f6a8885a3#50", "1.5707963267948966", 1, ); test::( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "1.3591409142295225", 1, ); test::( "-1000000000000000000000000.0", "-0xd3c21bcecceda1000000.0#80", "1.6543612251060553", 79, ); test::("-too_big", "-0x4.0E+268435455#1", "1.0", 1073741822); test::("-too_small", "-0x1.0E-268435456#1", "1.0", -1073741824); } fn sci_mantissa_and_exponent_primitive_float_fail_helper() where for<'a> &'a Float: SciMantissaAndExponent, { assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&Float::NAN) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&Float::INFINITY) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent( &Float::NEGATIVE_INFINITY ) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent(&Float::ZERO) ); assert_panic!( <&Float as SciMantissaAndExponent>::sci_mantissa_and_exponent( &Float::NEGATIVE_ZERO ) ); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa( &Float::NAN )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa( &Float::INFINITY )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa( &Float::NEGATIVE_INFINITY )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa( &Float::ZERO )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_mantissa( &Float::NEGATIVE_ZERO )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent( &Float::NAN )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent( &Float::INFINITY )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent( &Float::NEGATIVE_INFINITY )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent( &Float::ZERO )); assert_panic!(<&Float as SciMantissaAndExponent>::sci_exponent( &Float::NEGATIVE_ZERO )); } #[test] fn sci_mantissa_and_exponent_primitive_float_fail() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_primitive_float_fail_helper); } #[test] fn test_from_sci_mantissa_and_exponent_primitive_float() { fn test(m: T, e: i32, out: Option<&str>, out_hex: Option<&str>) where for<'a> &'a Float: SciMantissaAndExponent, { let ox = <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e); assert!(ox.as_ref().is_none_or(Float::is_valid)); let os = ox.as_ref().map(ToString::to_string); assert_eq!(os.as_deref(), out); let os = ox.as_ref().map(to_hex_string); assert_eq!(os.as_deref(), out_hex); } test::(1.0, 0, Some("1.0"), Some("0x1.0#1")); test::(1.0, 1, Some("2.0"), Some("0x2.0#1")); test::(1.0, -1, Some("0.5"), Some("0x0.8#1")); test::(1.3333334, -2, Some("0.33333334"), Some("0x0.5555558#24")); test::(1.921875, 6, Some("123.0"), Some("0x7b.0#7")); test::(1.8189894, 39, Some("1.0e12"), Some("0xe.8d4a5E+9#24")); test::( std::f32::consts::SQRT_2, 0, Some("1.4142135"), Some("0x1.6a09e6#24"), ); test::(1.5707964, 1, Some("3.1415927"), Some("0x3.243f6c#24")); test::(1.3591409, 1, Some("2.718282"), Some("0x2.b7e15#22")); test::(1.6543612, 79, Some("1.0e24"), Some("0xd.3c21cE+19#22")); test(1.0, 1073741822, Some("too_big"), Some("0x4.0E+268435455#1")); test(1.0, 1073741823, None, None); test( 1.0, -1073741824, Some("too_small"), Some("0x1.0E-268435456#1"), ); test(1.0, -1073741825, None, None); test::(-1.0, 0, None, None); test::(2.0, 0, None, None); test::(0.5, 0, None, None); test::(1.0, 0, Some("1.0"), Some("0x1.0#1")); test::(1.0, 1, Some("2.0"), Some("0x2.0#1")); test::(1.0, -1, Some("0.5"), Some("0x0.8#1")); test::( 1.3333333333333333, -2, Some("0.33333333333333331"), Some("0x0.55555555555554#53"), ); test::(1.921875, 6, Some("123.0"), Some("0x7b.0#7")); test::( 1.8189894035458565, 39, Some("1.0e12"), Some("0xe.8d4a51E+9#28"), ); test::( std::f64::consts::SQRT_2, 0, Some("1.4142135623730951"), Some("0x1.6a09e667f3bcd#53"), ); test::( std::f64::consts::FRAC_PI_2, 1, Some("3.141592653589793"), Some("0x3.243f6a8885a3#50"), ); test::( 1.3591409142295225, 1, Some("2.7182818284590451"), Some("0x2.b7e151628aed2#53"), ); test::( 1.6543612251060553, 79, Some("1.0e24"), Some("0xd.3c21bceccedaE+19#51"), ); test::(-1.0, 0, None, None); test::(2.0, 0, None, None); test::(0.5, 0, None, None); } fn from_sci_mantissa_and_exponent_primitive_float_fail_helper() where for<'a> &'a Float: SciMantissaAndExponent, { assert_panic!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(T::NAN, 0) ); assert_panic!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(T::INFINITY, 0) ); assert_panic!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( T::NEGATIVE_INFINITY, 0 ) ); assert_panic!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(T::ZERO, 0) ); assert_panic!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( T::NEGATIVE_ZERO, 0 ) ); } #[test] fn from_sci_mantissa_and_exponent_primitive_float_fail() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_primitive_float_fail_helper); } fn raw_mantissa_and_exponent_properties_helper(x: Float) { let (mantissa, exponent) = x.clone().raw_mantissa_and_exponent(); let (mantissa_alt, exponent_alt) = (&x).raw_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); let (mantissa_alt, exponent_alt) = (-&x).raw_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); assert_eq!(x.clone().raw_mantissa(), mantissa); assert_eq!((&x).raw_mantissa(), mantissa); assert_eq!(x.clone().raw_exponent(), exponent); assert_eq!((&x).raw_exponent(), exponent); assert_eq!(x.to_significand().unwrap(), mantissa); assert_eq!(x.get_exponent().unwrap(), exponent); assert_eq!( Float::from_raw_mantissa_and_exponent(mantissa.clone(), exponent), (&x).abs() ); assert_eq!( <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( mantissa.clone(), exponent ), x.abs() ); let bits = mantissa.significant_bits(); assert_ne!(bits, 0); assert!(bits.divisible_by_power_of_2(Limb::LOG_WIDTH)); assert!(exponent <= Float::MAX_EXPONENT); assert!(exponent >= Float::MIN_EXPONENT); } #[test] fn raw_mantissa_and_exponent_properties() { float_gen_var_3().test_properties(|x| { raw_mantissa_and_exponent_properties_helper(x); }); float_gen_var_13().test_properties(|x| { raw_mantissa_and_exponent_properties_helper(x); }); } #[test] fn from_raw_mantissa_and_exponent_properties() { natural_signed_pair_gen_var_4::().test_properties(|(mantissa, exponent)| { let x = Float::from_raw_mantissa_and_exponent(mantissa.clone(), exponent); assert!(x.is_valid()); assert!(x.is_finite()); assert!(x > 0u32); assert_eq!((&x).raw_mantissa(), mantissa); assert_eq!((&x).raw_exponent(), exponent); let x_alt = <&Float as RawMantissaAndExponent<_, _, _>>::from_raw_mantissa_and_exponent( mantissa, exponent, ); assert!(x_alt.is_valid()); assert_eq!(x_alt, x); }); } fn integer_mantissa_and_exponent_properties_helper() where Float: From, { primitive_float_gen_var_12::().test_properties(|x| { let (mantissa, exponent) = x.integer_mantissa_and_exponent(); let (mantissa_alt, exponent_alt) = Float::from(x).integer_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); }); } fn integer_mantissa_and_exponent_properties_helper_2(x: Float) { let (mantissa, exponent) = x.clone().integer_mantissa_and_exponent(); let (mantissa_alt, exponent_alt) = (&x).integer_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); let (mantissa_alt, exponent_alt) = (-&x).integer_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); assert_eq!(x.clone().integer_mantissa(), mantissa); assert_eq!((&x).integer_mantissa(), mantissa); assert_eq!(x.clone().integer_exponent(), exponent); assert_eq!((&x).integer_exponent(), exponent); assert_eq!( Float::from_integer_mantissa_and_exponent(mantissa.clone(), exponent), Some(x.clone().abs()) ); assert_eq!( <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( mantissa.clone(), exponent ), Some(x.abs()) ); assert!(mantissa.odd()); assert!(exponent < i64::from(Float::MAX_EXPONENT)); } #[test] fn integer_mantissa_and_exponent_properties() { float_gen_var_3().test_properties(|x| { integer_mantissa_and_exponent_properties_helper_2(x); }); float_gen_var_13().test_properties(|x| { integer_mantissa_and_exponent_properties_helper_2(x); }); apply_fn_to_primitive_floats!(integer_mantissa_and_exponent_properties_helper); } #[test] fn from_integer_mantissa_and_exponent_properties() { natural_signed_pair_gen_var_2::().test_properties(|(mantissa, exponent)| { let ox = Float::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); if let Some(x) = ox.as_ref() { assert!(x.is_valid()); assert!(x.is_finite()); assert!(*x >= 0u32); if mantissa.odd() { assert_eq!(x.integer_mantissa(), mantissa); assert_eq!(x.integer_exponent(), exponent); } } let ox_alt = <&Float as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( mantissa, exponent, ); assert!(ox_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(ox_alt, ox); }); } fn sci_mantissa_and_exponent_round_properties_helper_helper( x: Float, rm: RoundingMode, extreme: bool, ) where Rational: TryFrom, { let meo = x.sci_mantissa_and_exponent_round::(rm); assert_eq!((-&x).sci_mantissa_and_exponent_round(rm), meo); if let Some((mantissa, exponent, o)) = meo { assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); assert!(x.is_valid()); // Although the maximum sci-exponent for a Float is Float::MAX_EXPONENT, this function may // return an exponent that is larger by 1, due to rounding. assert!(exponent <= Float::MAX_EXPONENT); assert!(exponent >= Float::MIN_EXPONENT - 1); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } if !extreme { let x_alt = Rational::exact_from(mantissa) << exponent; assert_eq!(x_alt.partial_cmp_abs(&x), Some(o)); if rm == Exact { assert_eq!(x_alt.partial_cmp_abs(&x), Some(Equal)); } let r_x: Rational = ExactFrom::exact_from(x); assert_eq!( r_x.sci_mantissa_and_exponent_round(rm).unwrap(), (mantissa, i64::from(exponent), o) ); } } else { assert!(!x.is_finite() || x == 0u32 || rm == Exact); } } fn sci_mantissa_and_exponent_round_properties_helper() where Rational: TryFrom, { float_rounding_mode_pair_gen().test_properties(|(x, rm)| { sci_mantissa_and_exponent_round_properties_helper_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_21().test_properties(|(x, rm)| { sci_mantissa_and_exponent_round_properties_helper_helper(x, rm, true); }); float_gen_var_3().test_properties(|n| { let (floor_mantissa, floor_exponent, floor_o) = n.sci_mantissa_and_exponent_round::(Floor).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round::(Down).unwrap(), (floor_mantissa, floor_exponent, floor_o) ); let (ceiling_mantissa, ceiling_exponent, ceiling_o) = n.sci_mantissa_and_exponent_round::(Ceiling).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round::(Up).unwrap(), (ceiling_mantissa, ceiling_exponent, ceiling_o) ); let (nearest_mantissa, nearest_exponent, nearest_o) = n.sci_mantissa_and_exponent_round::(Nearest).unwrap(); if let Some((mantissa, exponent, o)) = n.sci_mantissa_and_exponent_round::(Exact) { assert_eq!(o, Equal); assert_eq!(floor_mantissa, mantissa); assert_eq!(ceiling_mantissa, mantissa); assert_eq!(nearest_mantissa, mantissa); assert_eq!(floor_exponent, exponent); assert_eq!(ceiling_exponent, exponent); assert_eq!(nearest_exponent, exponent); } else { assert_eq!(floor_o, Less); assert_eq!(ceiling_o, Greater); assert_ne!( (floor_mantissa, floor_exponent), (ceiling_mantissa, ceiling_exponent) ); assert!( (nearest_mantissa, nearest_exponent, nearest_o) == (floor_mantissa, floor_exponent, floor_o) || (nearest_mantissa, nearest_exponent, nearest_o) == (ceiling_mantissa, ceiling_exponent, ceiling_o) ); if ceiling_mantissa == T::ONE { assert_eq!(floor_mantissa, T::TWO.next_lower()); assert_eq!(floor_exponent, ceiling_exponent - 1); } else { assert_eq!(floor_mantissa, ceiling_mantissa.next_lower()); assert_eq!(floor_exponent, ceiling_exponent); } } }); } #[test] fn sci_mantissa_and_exponent_round_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_round_properties_helper); } fn sci_mantissa_and_exponent_float_properties_helper(x: Float) { let (mantissa, exponent): (Float, i32) = x.clone().sci_mantissa_and_exponent(); assert!(mantissa.is_valid()); let (mantissa_alt, exponent_alt): (Float, i32) = (&x).sci_mantissa_and_exponent(); assert!(mantissa_alt.is_valid()); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); let (mantissa_alt, exponent_alt): (Float, i32) = (-&x).sci_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); let mantissa_alt: Float = (&x).sci_mantissa(); assert!(mantissa_alt.is_valid()); assert_eq!(mantissa_alt, mantissa); let mantissa_alt: Float = x.clone().sci_mantissa(); assert!(mantissa_alt.is_valid()); assert_eq!(mantissa_alt, mantissa); assert_eq!( >::sci_exponent(x.clone()), exponent ); assert_eq!( <&Float as SciMantissaAndExponent>::sci_exponent(&x), exponent ); assert_eq!( Float::from_sci_mantissa_and_exponent(mantissa.clone(), exponent), Some(x.clone().abs()) ); assert_eq!( <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa.clone(), exponent ), Some(x.abs()) ); assert!(mantissa >= 1u32); assert!(mantissa < 2u32); assert!(exponent < Float::MAX_EXPONENT); assert!(exponent >= Float::MIN_EXPONENT - 1); } #[test] fn sci_mantissa_and_exponent_float_properties() { float_gen_var_3().test_properties(|x| { sci_mantissa_and_exponent_float_properties_helper(x); }); float_gen_var_13().test_properties(|x| { sci_mantissa_and_exponent_float_properties_helper(x); }); } #[test] fn from_sci_mantissa_and_exponent_float_properties() { float_signed_pair_gen_var_1::().test_properties(|(mantissa, exponent)| { let ox = Float::from_sci_mantissa_and_exponent(mantissa.clone(), exponent); if let Some(x) = ox.as_ref() { assert!(x.is_valid()); assert!(x.is_finite()); assert!(*x > 0u32); assert_eq!( <&Float as SciMantissaAndExponent>::sci_mantissa(x), mantissa ); assert_eq!( <&Float as SciMantissaAndExponent>::sci_exponent(x), exponent ); } let ox_alt = <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, exponent, ); assert!(ox_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(ox_alt, ox); }); } fn sci_mantissa_and_exponent_primitive_float_properties_helper_helper( x: Float, extreme: bool, ) where for<'a> &'a Float: SciMantissaAndExponent, Float: From, { let (mantissa, exponent): (T, i32) = (&x).sci_mantissa_and_exponent(); assert_eq!( <&Float as SciMantissaAndExponent>::sci_mantissa(&x), mantissa ); assert_eq!( <&Float as SciMantissaAndExponent>::sci_exponent(&x), exponent ); let (mantissa_alt, exponent_alt): (T, i32) = (&-&x).sci_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(exponent_alt, exponent); if !extreme { let x_alt = <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, exponent, ) .unwrap(); assert!( Rational::exact_from(x) - Rational::exact_from(&x_alt) <= Rational::exact_from(x_alt.ulp().unwrap()) >> 1u32 ); } assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); } fn sci_mantissa_and_exponent_primitive_float_properties_helper() where for<'a> &'a Float: SciMantissaAndExponent, Float: From, { float_gen_var_3().test_properties(|x| { sci_mantissa_and_exponent_primitive_float_properties_helper_helper(x, false); }); float_gen_var_13().test_properties(|x| { sci_mantissa_and_exponent_primitive_float_properties_helper_helper(x, true); }); primitive_float_gen_var_12::().test_properties(|x| { let (mantissa, exponent) = x.sci_mantissa_and_exponent(); let (mantissa_alt, exponent_alt): (T, i32) = (&Float::from(x)).sci_mantissa_and_exponent(); assert_eq!(mantissa_alt, mantissa); assert_eq!(i64::from(exponent_alt), exponent); }); } #[test] fn sci_mantissa_and_exponent_primitive_float_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_primitive_float_properties_helper); } fn from_sci_mantissa_and_exponent_primitive_float_properties_helper() where for<'a> &'a Float: SciMantissaAndExponent, Float: From, { primitive_float_signed_pair_gen_var_3::().test_properties(|(mantissa, exponent)| { let ox = <&Float as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, i32::exact_from(exponent), ); if let Some(x) = ox.as_ref() { assert!(x.is_valid()); assert!(x.is_finite()); assert!(*x > 0u32); assert_eq!( <&Float as SciMantissaAndExponent>::sci_mantissa(x), mantissa ); assert_eq!( i64::from(<&Float as SciMantissaAndExponent>::sci_exponent(x)), exponent ); } let ox_alt = Float::from_sci_mantissa_and_exponent(Float::from(mantissa), i32::exact_from(exponent)); assert!(ox_alt.as_ref().is_none_or(Float::is_valid)); assert_eq!(ox_alt, ox); }); } #[test] fn from_sci_mantissa_and_exponent_primitive_float_properties() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_primitive_float_properties_helper); } ================================================ FILE: malachite-float/tests/conversion/natural_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, Floor, Parity}; use malachite_base::num::basic::traits::{ Infinity, NaN, NegativeInfinity, NegativeOne, One, OneHalf, }; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_gen, float_gen_var_5, float_rounding_mode_pair_gen_var_1, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use malachite_q::Rational; use std::cmp::Ordering::*; use std::panic::catch_unwind; #[test] fn test_try_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = Natural::try_from(x.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Natural::try_from(&x); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("NaN", "NaN", "Err(FloatInfiniteOrNan)"); test("Infinity", "Infinity", "Err(FloatInfiniteOrNan)"); test("-Infinity", "-Infinity", "Err(FloatInfiniteOrNan)"); test("0.0", "0x0.0", "Ok(0)"); test("-0.0", "-0x0.0", "Ok(0)"); test("1.0", "0x1.0#1", "Ok(1)"); test("2.0", "0x2.0#1", "Ok(2)"); test("0.5", "0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test( "0.33333333333333331", "0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test("123.0", "0x7b.0#7", "Ok(123)"); test("1000000000000.0", "0xe8d4a51000.0#40", "Ok(1000000000000)"); test("-1.0", "-0x1.0#1", "Err(FloatNegative)"); test("-2.0", "-0x2.0#1", "Err(FloatNegative)"); test("-0.5", "-0x0.8#1", "Err(FloatNegative)"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "Err(FloatNegative)", ); test("-123.0", "-0x7b.0#7", "Err(FloatNegative)"); test( "-1000000000000.0", "-0xe8d4a51000.0#40", "Err(FloatNegative)", ); } #[test] fn test_convertible_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(Natural::convertible_from(&x), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", false); test("0.33333333333333331", "0x0.55555555555554#53", false); test("123.0", "0x7b.0#7", true); test("1000000000000.0", "0xe8d4a51000.0#40", true); test("-1.0", "-0x1.0#1", false); test("-2.0", "-0x2.0#1", false); test("-0.5", "-0x0.8#1", false); test("-0.33333333333333331", "-0x0.55555555555554#53", false); test("-123.0", "-0x7b.0#7", false); test("-1000000000000.0", "-0xe8d4a51000.0#40", false); } #[test] fn test_rounding_from_float() { let test = |s, s_hex, rm, out, o_out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (n, o) = Natural::rounding_from(x.clone(), rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); let (n, o) = Natural::rounding_from(&x, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); }; test("-Infinity", "-Infinity", Ceiling, "0", Greater); test("-Infinity", "-Infinity", Down, "0", Greater); test("-Infinity", "-Infinity", Nearest, "0", Greater); test("0.0", "0x0.0", Floor, "0", Equal); test("0.0", "0x0.0", Ceiling, "0", Equal); test("0.0", "0x0.0", Down, "0", Equal); test("0.0", "0x0.0", Up, "0", Equal); test("0.0", "0x0.0", Nearest, "0", Equal); test("0.0", "0x0.0", Exact, "0", Equal); test("-0.0", "-0x0.0", Floor, "0", Equal); test("-0.0", "-0x0.0", Ceiling, "0", Equal); test("-0.0", "-0x0.0", Down, "0", Equal); test("-0.0", "-0x0.0", Up, "0", Equal); test("-0.0", "-0x0.0", Nearest, "0", Equal); test("-0.0", "-0x0.0", Exact, "0", Equal); test("1.0", "0x1.0#1", Floor, "1", Equal); test("1.0", "0x1.0#1", Ceiling, "1", Equal); test("1.0", "0x1.0#1", Down, "1", Equal); test("1.0", "0x1.0#1", Up, "1", Equal); test("1.0", "0x1.0#1", Nearest, "1", Equal); test("1.0", "0x1.0#1", Exact, "1", Equal); test("2.0", "0x2.0#1", Floor, "2", Equal); test("2.0", "0x2.0#1", Ceiling, "2", Equal); test("2.0", "0x2.0#1", Down, "2", Equal); test("2.0", "0x2.0#1", Up, "2", Equal); test("2.0", "0x2.0#1", Nearest, "2", Equal); test("2.0", "0x2.0#1", Exact, "2", Equal); test("0.5", "0x0.8#1", Floor, "0", Less); test("0.5", "0x0.8#1", Ceiling, "1", Greater); test("0.5", "0x0.8#1", Down, "0", Less); test("0.5", "0x0.8#1", Up, "1", Greater); test("0.5", "0x0.8#1", Nearest, "0", Less); test( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0", Less, ); test( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "1", Greater, ); test( "0.33333333333333331", "0x0.55555555555554#53", Down, "0", Less, ); test( "0.33333333333333331", "0x0.55555555555554#53", Up, "1", Greater, ); test( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Floor, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Ceiling, "1", Greater, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Down, "0", Less, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Up, "1", Greater, ); test( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Nearest, "1", Greater, ); test("1.5", "0x1.8#2", Floor, "1", Less); test("1.5", "0x1.8#2", Ceiling, "2", Greater); test("1.5", "0x1.8#2", Down, "1", Less); test("1.5", "0x1.8#2", Up, "2", Greater); test("1.5", "0x1.8#2", Nearest, "2", Greater); test("2.5", "0x2.8#3", Floor, "2", Less); test("2.5", "0x2.8#3", Ceiling, "3", Greater); test("2.5", "0x2.8#3", Down, "2", Less); test("2.5", "0x2.8#3", Up, "3", Greater); test("2.5", "0x2.8#3", Nearest, "2", Less); test("123.0", "0x7b.0#7", Floor, "123", Equal); test("123.0", "0x7b.0#7", Ceiling, "123", Equal); test("123.0", "0x7b.0#7", Down, "123", Equal); test("123.0", "0x7b.0#7", Up, "123", Equal); test("123.0", "0x7b.0#7", Nearest, "123", Equal); test("123.0", "0x7b.0#7", Exact, "123", Equal); test("-1.0", "-0x1.0#1", Ceiling, "0", Greater); test("-1.0", "-0x1.0#1", Down, "0", Greater); test("-1.0", "-0x1.0#1", Nearest, "0", Greater); test("-2.0", "-0x2.0#1", Ceiling, "0", Greater); test("-2.0", "-0x2.0#1", Down, "0", Greater); test("-2.0", "-0x2.0#1", Nearest, "0", Greater); test("-0.5", "-0x0.8#1", Ceiling, "0", Greater); test("-0.5", "-0x0.8#1", Down, "0", Greater); test("-0.5", "-0x0.8#1", Nearest, "0", Greater); test( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "0", Greater, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "0", Greater, ); test( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Ceiling, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Down, "0", Greater, ); test( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Nearest, "0", Greater, ); test("-1.5", "-0x1.8#2", Ceiling, "0", Greater); test("-1.5", "-0x1.8#2", Down, "0", Greater); test("-1.5", "-0x1.8#2", Nearest, "0", Greater); test("-2.5", "-0x2.8#3", Ceiling, "0", Greater); test("-2.5", "-0x2.8#3", Down, "0", Greater); test("-2.5", "-0x2.8#3", Nearest, "0", Greater); test("-123.0", "-0x7b.0#7", Ceiling, "0", Greater); test("-123.0", "-0x7b.0#7", Down, "0", Greater); test("-123.0", "-0x7b.0#7", Nearest, "0", Greater); } #[test] fn natural_rounding_from_float_fail() { assert_panic!(Natural::rounding_from(Float::NAN, Floor)); assert_panic!(Natural::rounding_from(Float::NAN, Ceiling)); assert_panic!(Natural::rounding_from(Float::NAN, Down)); assert_panic!(Natural::rounding_from(Float::NAN, Up)); assert_panic!(Natural::rounding_from(Float::NAN, Nearest)); assert_panic!(Natural::rounding_from(Float::NAN, Exact)); assert_panic!(Natural::rounding_from(Float::INFINITY, Floor)); assert_panic!(Natural::rounding_from(Float::INFINITY, Ceiling)); assert_panic!(Natural::rounding_from(Float::INFINITY, Down)); assert_panic!(Natural::rounding_from(Float::INFINITY, Up)); assert_panic!(Natural::rounding_from(Float::INFINITY, Nearest)); assert_panic!(Natural::rounding_from(Float::INFINITY, Exact)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_INFINITY, Floor)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_INFINITY, Up)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_INFINITY, Exact)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_ONE, Floor)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_ONE, Up)); assert_panic!(Natural::rounding_from(Float::NEGATIVE_ONE, Exact)); assert_panic!(Natural::rounding_from(Float::from(3u8) >> 1, Exact)); } #[test] fn natural_rounding_from_float_ref_fail() { assert_panic!(Natural::rounding_from(&Float::NAN, Floor)); assert_panic!(Natural::rounding_from(&Float::NAN, Ceiling)); assert_panic!(Natural::rounding_from(&Float::NAN, Down)); assert_panic!(Natural::rounding_from(&Float::NAN, Up)); assert_panic!(Natural::rounding_from(&Float::NAN, Nearest)); assert_panic!(Natural::rounding_from(&Float::NAN, Exact)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Floor)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Ceiling)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Down)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Up)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Nearest)); assert_panic!(Natural::rounding_from(&Float::INFINITY, Exact)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_INFINITY, Floor)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_INFINITY, Up)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_INFINITY, Exact)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_ONE, Floor)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_ONE, Up)); assert_panic!(Natural::rounding_from(&Float::NEGATIVE_ONE, Exact)); assert_panic!(Natural::rounding_from(&(Float::from(3u8) >> 1), Exact)); } #[test] fn try_from_float_properties() { float_gen().test_properties(|x| { let natural_x = Natural::try_from(x.clone()); assert!(natural_x.as_ref().map_or(true, Natural::is_valid)); let natural_x_alt = Natural::try_from(&x); assert!(natural_x_alt.as_ref().map_or(true, Natural::is_valid)); assert_eq!(natural_x, natural_x_alt); assert_eq!(natural_x.is_ok(), Natural::convertible_from(&x)); if let Ok(n) = natural_x { assert_eq!(Natural::exact_from(&x), n); assert_eq!(n, x); assert_eq!(Float::exact_from(&n), x); assert_eq!(Float::exact_from(n), x); } }); } #[test] fn convertible_from_float_properties() { float_gen().test_properties(|x| { Natural::convertible_from(&x); }); } #[test] fn rounding_from_float_properties() { float_rounding_mode_pair_gen_var_1().test_properties(|(x, rm)| { let no = Natural::rounding_from(&x, rm); assert_eq!(Natural::rounding_from(x.clone(), rm), no); let (n, o) = no; if x >= 0 { assert_eq!(Integer::rounding_from(&x, rm), (Integer::from(&n), o)); assert!((Rational::from(&n) - Rational::exact_from(&x)).lt_abs(&1)); } assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); float_gen_var_5().test_properties(|x| { let floor = Natural::rounding_from(&x, Floor); assert_eq!(floor.0, Rational::exact_from(&x).floor()); assert!(floor.0 <= x); assert!(&floor.0 + Natural::ONE > x); assert_eq!(Natural::rounding_from(&x, Down), floor); let ceiling = Natural::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, Rational::exact_from(&x).ceiling()); assert!(ceiling.0 >= x); if x > 0 { assert!(&ceiling.0 - Natural::ONE < x); } assert_eq!(Natural::rounding_from(&x, Up), ceiling); let nearest = Natural::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); assert!((Rational::from(nearest.0) - Rational::exact_from(x)).le_abs(&Rational::ONE_HALF)); }); natural_gen().test_properties(|n| { let x = Float::exact_from(&n); let no = (n, Equal); assert_eq!(Natural::rounding_from(&x, Floor), no); assert_eq!(Natural::rounding_from(&x, Down), no); assert_eq!(Natural::rounding_from(&x, Ceiling), no); assert_eq!(Natural::rounding_from(&x, Up), no); assert_eq!(Natural::rounding_from(&x, Nearest), no); assert_eq!(Natural::rounding_from(&x, Exact), no); let x = Float::exact_from((no.0 << 1) | Natural::ONE) >> 1; assert!(Natural::rounding_from(x, Nearest).0.even()); }); } ================================================ FILE: malachite-float/tests/conversion/primitive_float_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::primitive_float_gen; use malachite_float::Float; use malachite_float::conversion::primitive_float_from_float::FloatFromFloatError; use malachite_float::test_util::common::{parse_hex_string, rug_round_try_from_rounding_mode}; use malachite_float::test_util::generators::{ float_gen, float_gen_var_4, float_gen_var_12, float_rounding_mode_pair_gen_var_6, float_rounding_mode_pair_gen_var_20, }; use malachite_nz::integer::Integer; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[allow(clippy::type_repetition_in_bounds)] #[test] fn test_try_from_float() { fn test_helper>( s: &str, s_hex: &str, out: &str, ) where for<'a> T: TryFrom<&'a Float, Error = FloatFromFloatError>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = match T::try_from(x.clone()) { Ok(n) => format!("Ok({})", NiceFloat(n)), e => e.to_debug_string(), }; assert_eq!(on, out); let on = match T::try_from(&x) { Ok(n) => format!("Ok({})", NiceFloat(n)), e => e.to_debug_string(), }; assert_eq!(on, out); } fn test_helper_2>() where for<'a> T: TryFrom<&'a Float, Error = FloatFromFloatError>, { test_helper::("NaN", "NaN", "Ok(NaN)"); test_helper::("Infinity", "Infinity", "Ok(Infinity)"); test_helper::("-Infinity", "-Infinity", "Ok(-Infinity)"); test_helper::("0.0", "0x0.0", "Ok(0.0)"); test_helper::("-0.0", "-0x0.0", "Ok(-0.0)"); test_helper::("1.0", "0x1.0#1", "Ok(1.0)"); test_helper::("2.0", "0x2.0#1", "Ok(2.0)"); test_helper::("0.5", "0x0.8#1", "Ok(0.5)"); test_helper::("123.0", "0x7b.0#7", "Ok(123.0)"); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", "Err(Inexact)", ); test_helper::("2.0e2408", "0x1.0E+2000#1", "Err(Overflow)"); test_helper::("6.0e-2409", "0x1.0E-2000#1", "Err(Underflow)"); test_helper::("too_big", "0x4.0E+268435455#1", "Err(Overflow)"); test_helper::("too_small", "0x1.0E-268435456#1", "Err(Underflow)"); test_helper::("-1.0", "-0x1.0#1", "Ok(-1.0)"); test_helper::("-2.0", "-0x2.0#1", "Ok(-2.0)"); test_helper::("-0.5", "-0x0.8#1", "Ok(-0.5)"); test_helper::("-123.0", "-0x7b.0#7", "Ok(-123.0)"); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", "Err(Inexact)", ); test_helper::("-2.0e2408", "-0x1.0E+2000#1", "Err(Overflow)"); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", "Err(Underflow)"); test_helper::("-too_big", "-0x4.0E+268435455#1", "Err(Overflow)"); test_helper::("-too_small", "-0x1.0E-268435456#1", "Err(Underflow)"); } apply_fn_to_primitive_floats!(test_helper_2); test_helper::("0.33333334", "0x0.5555558#24", "Ok(0.33333334)"); test_helper::("0.33333334", "0x0.5555558#24", "Ok(0.3333333432674408)"); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", "Err(Inexact)", ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", "Ok(0.3333333333333333)", ); test_helper::("7.0e240", "0x1.0E+200#1", "Err(Overflow)"); test_helper::("7.0e240", "0x1.0E+200#1", "Ok(6.668014432879854e240)"); test_helper::("1.0e-241", "0x1.0E-200#1", "Err(Underflow)"); test_helper::("1.0e-241", "0x1.0E-200#1", "Ok(1.499696813895631e-241)"); test_helper::("-0.33333334", "-0x0.5555558#24", "Ok(-0.33333334)"); test_helper::("-0.33333334", "-0x0.5555558#24", "Ok(-0.3333333432674408)"); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", "Err(Inexact)", ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", "Ok(-0.3333333333333333)", ); test_helper::("-7.0e240", "-0x1.0E+200#1", "Err(Overflow)"); test_helper::("-7.0e240", "-0x1.0E+200#1", "Ok(-6.668014432879854e240)"); test_helper::("-1.0e-241", "-0x1.0E-200#1", "Err(Underflow)"); test_helper::("-1.0e-241", "-0x1.0E-200#1", "Ok(-1.499696813895631e-241)"); } #[test] fn test_convertible_from_float() { #[allow(clippy::type_repetition_in_bounds)] fn test_helper(s: &str, s_hex: &str, out: bool) where for<'a> T: ConvertibleFrom<&'a Float>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(T::convertible_from(&x), out); } #[allow(clippy::type_repetition_in_bounds)] fn test_helper_2() where for<'a> T: ConvertibleFrom<&'a Float>, { test_helper::("NaN", "NaN", true); test_helper::("Infinity", "Infinity", true); test_helper::("-Infinity", "-Infinity", true); test_helper::("0.0", "0x0.0", true); test_helper::("-0.0", "-0x0.0", true); test_helper::("1.0", "0x1.0#1", true); test_helper::("2.0", "0x2.0#1", true); test_helper::("0.5", "0x0.8#1", true); test_helper::("0.33333334", "0x0.5555558#24", true); test_helper::("123.0", "0x7b.0#7", true); test_helper::("0.333333333333333332", "0x0.555555555555554#57", false); test_helper::("2.0e2408", "0x1.0E+2000#1", false); test_helper::("6.0e-2409", "0x1.0E-2000#1", false); test_helper::("too_big", "0x4.0E+268435455#1", false); test_helper::("too_small", "0x1.0E-268435456#1", false); test_helper::("-1.0", "-0x1.0#1", true); test_helper::("-2.0", "-0x2.0#1", true); test_helper::("-0.5", "-0x0.8#1", true); test_helper::("-0.33333334", "-0x0.5555558#24", true); test_helper::("-123.0", "-0x7b.0#7", true); test_helper::("-0.333333333333333332", "-0x0.555555555555554#57", false); test_helper::("-2.0e2408", "-0x1.0E+2000#1", false); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", false); test_helper::("-too_big", "-0x4.0E+268435455#1", false); test_helper::("-too_small", "-0x1.0E-268435456#1", false); } apply_fn_to_primitive_floats!(test_helper_2); test_helper::("0.33333333333333331", "0x0.55555555555554#53", false); test_helper::("0.33333333333333331", "0x0.55555555555554#53", true); test_helper::("7.0e240", "0x1.0E+200#1", false); test_helper::("7.0e240", "0x1.0E+200#1", true); test_helper::("1.0e-241", "0x1.0E-200#1", false); test_helper::("1.0e-241", "0x1.0E-200#1", true); test_helper::("-0.33333333333333331", "-0x0.55555555555554#53", false); test_helper::("-0.33333333333333331", "-0x0.55555555555554#53", true); test_helper::("-7.0e240", "-0x1.0E+200#1", false); test_helper::("-7.0e240", "-0x1.0E+200#1", true); test_helper::("-1.0e-241", "-0x1.0E-200#1", false); test_helper::("-1.0e-241", "-0x1.0E-200#1", true); } #[test] fn test_rounding_from_float() { #[allow(clippy::type_repetition_in_bounds)] fn test_helper>( s: &str, s_hex: &str, rm: RoundingMode, out: &str, o_out: Ordering, ) where for<'a> T: RoundingFrom<&'a Float>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (n, o) = T::rounding_from(x.clone(), rm); assert_eq!(NiceFloat(n).to_string(), out); assert_eq!(o, o_out); let (n, o) = T::rounding_from(&x, rm); assert_eq!(NiceFloat(n).to_string(), out); assert_eq!(o, o_out); } #[allow(clippy::type_repetition_in_bounds)] fn test_helper_2>() where for<'a> T: RoundingFrom<&'a Float>, { test_helper::("NaN", "NaN", Floor, "NaN", Equal); test_helper::("NaN", "NaN", Ceiling, "NaN", Equal); test_helper::("NaN", "NaN", Down, "NaN", Equal); test_helper::("NaN", "NaN", Up, "NaN", Equal); test_helper::("NaN", "NaN", Nearest, "NaN", Equal); test_helper::("NaN", "NaN", Exact, "NaN", Equal); test_helper::("Infinity", "Infinity", Floor, "Infinity", Equal); test_helper::("Infinity", "Infinity", Ceiling, "Infinity", Equal); test_helper::("Infinity", "Infinity", Down, "Infinity", Equal); test_helper::("Infinity", "Infinity", Up, "Infinity", Equal); test_helper::("Infinity", "Infinity", Nearest, "Infinity", Equal); test_helper::("Infinity", "Infinity", Exact, "Infinity", Equal); test_helper::("-Infinity", "-Infinity", Floor, "-Infinity", Equal); test_helper::("-Infinity", "-Infinity", Ceiling, "-Infinity", Equal); test_helper::("-Infinity", "-Infinity", Down, "-Infinity", Equal); test_helper::("-Infinity", "-Infinity", Up, "-Infinity", Equal); test_helper::("-Infinity", "-Infinity", Nearest, "-Infinity", Equal); test_helper::("-Infinity", "-Infinity", Exact, "-Infinity", Equal); test_helper::("0.0", "0x0.0", Floor, "0.0", Equal); test_helper::("0.0", "0x0.0", Ceiling, "0.0", Equal); test_helper::("0.0", "0x0.0", Down, "0.0", Equal); test_helper::("0.0", "0x0.0", Up, "0.0", Equal); test_helper::("0.0", "0x0.0", Nearest, "0.0", Equal); test_helper::("0.0", "0x0.0", Exact, "0.0", Equal); test_helper::("-0.0", "-0x0.0", Floor, "-0.0", Equal); test_helper::("-0.0", "-0x0.0", Ceiling, "-0.0", Equal); test_helper::("-0.0", "-0x0.0", Down, "-0.0", Equal); test_helper::("-0.0", "-0x0.0", Up, "-0.0", Equal); test_helper::("-0.0", "-0x0.0", Nearest, "-0.0", Equal); test_helper::("-0.0", "-0x0.0", Exact, "-0.0", Equal); test_helper::("1.0", "0x1.0#1", Floor, "1.0", Equal); test_helper::("1.0", "0x1.0#1", Ceiling, "1.0", Equal); test_helper::("1.0", "0x1.0#1", Down, "1.0", Equal); test_helper::("1.0", "0x1.0#1", Up, "1.0", Equal); test_helper::("1.0", "0x1.0#1", Nearest, "1.0", Equal); test_helper::("1.0", "0x1.0#1", Exact, "1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Floor, "-1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Ceiling, "-1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Down, "-1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Up, "-1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Nearest, "-1.0", Equal); test_helper::("-1.0", "-0x1.0#1", Exact, "-1.0", Equal); } apply_fn_to_primitive_floats!(test_helper_2); test_helper::("0.33333334", "0x0.5555558#24", Floor, "0.33333334", Equal); test_helper::("0.33333334", "0x0.5555558#24", Ceiling, "0.33333334", Equal); test_helper::("0.33333334", "0x0.5555558#24", Down, "0.33333334", Equal); test_helper::("0.33333334", "0x0.5555558#24", Up, "0.33333334", Equal); test_helper::("0.33333334", "0x0.5555558#24", Nearest, "0.33333334", Equal); test_helper::("0.33333334", "0x0.5555558#24", Exact, "0.33333334", Equal); test_helper::( "0.33333334", "0x0.5555558#24", Floor, "0.3333333432674408", Equal, ); test_helper::( "0.33333334", "0x0.5555558#24", Ceiling, "0.3333333432674408", Equal, ); test_helper::( "0.33333334", "0x0.5555558#24", Down, "0.3333333432674408", Equal, ); test_helper::( "0.33333334", "0x0.5555558#24", Up, "0.3333333432674408", Equal, ); test_helper::( "0.33333334", "0x0.5555558#24", Nearest, "0.3333333432674408", Equal, ); test_helper::( "0.33333334", "0x0.5555558#24", Exact, "0.3333333432674408", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0.3333333", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "0.33333334", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Down, "0.3333333", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Up, "0.33333334", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0.33333334", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0.3333333333333333", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "0.3333333333333333", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Down, "0.3333333333333333", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Up, "0.3333333333333333", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0.3333333333333333", Equal, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Exact, "0.3333333333333333", Equal, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Floor, "0.3333333", Less, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Ceiling, "0.33333334", Greater, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Down, "0.3333333", Less, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Up, "0.33333334", Greater, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Nearest, "0.33333334", Greater, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Floor, "0.3333333333333333", Less, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Ceiling, "0.33333333333333337", Greater, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Down, "0.3333333333333333", Less, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Up, "0.33333333333333337", Greater, ); test_helper::( "0.333333333333333332", "0x0.555555555555554#57", Nearest, "0.3333333333333333", Less, ); test_helper::("7.0e240", "0x1.0E+200#1", Floor, "3.4028235e38", Less); test_helper::("7.0e240", "0x1.0E+200#1", Ceiling, "Infinity", Greater); test_helper::("7.0e240", "0x1.0E+200#1", Down, "3.4028235e38", Less); test_helper::("7.0e240", "0x1.0E+200#1", Up, "Infinity", Greater); test_helper::("7.0e240", "0x1.0E+200#1", Nearest, "Infinity", Greater); test_helper::( "7.0e240", "0x1.0E+200#1", Floor, "6.668014432879854e240", Equal, ); test_helper::( "7.0e240", "0x1.0E+200#1", Ceiling, "6.668014432879854e240", Equal, ); test_helper::( "7.0e240", "0x1.0E+200#1", Down, "6.668014432879854e240", Equal, ); test_helper::( "7.0e240", "0x1.0E+200#1", Up, "6.668014432879854e240", Equal, ); test_helper::( "7.0e240", "0x1.0E+200#1", Nearest, "6.668014432879854e240", Equal, ); test_helper::( "7.0e240", "0x1.0E+200#1", Exact, "6.668014432879854e240", Equal, ); test_helper::("2.0e2408", "0x1.0E+2000#1", Floor, "3.4028235e38", Less); test_helper::("2.0e2408", "0x1.0E+2000#1", Ceiling, "Infinity", Greater); test_helper::("2.0e2408", "0x1.0E+2000#1", Down, "3.4028235e38", Less); test_helper::("2.0e2408", "0x1.0E+2000#1", Up, "Infinity", Greater); test_helper::("2.0e2408", "0x1.0E+2000#1", Nearest, "Infinity", Greater); test_helper::( "2.0e2408", "0x1.0E+2000#1", Floor, "1.7976931348623157e308", Less, ); test_helper::("2.0e2408", "0x1.0E+2000#1", Ceiling, "Infinity", Greater); test_helper::( "2.0e2408", "0x1.0E+2000#1", Down, "1.7976931348623157e308", Less, ); test_helper::("2.0e2408", "0x1.0E+2000#1", Up, "Infinity", Greater); test_helper::("2.0e2408", "0x1.0E+2000#1", Nearest, "Infinity", Greater); test_helper::("1.0e-241", "0x1.0E-200#1", Floor, "0.0", Less); test_helper::("1.0e-241", "0x1.0E-200#1", Ceiling, "1.0e-45", Greater); test_helper::("1.0e-241", "0x1.0E-200#1", Down, "0.0", Less); test_helper::("1.0e-241", "0x1.0E-200#1", Up, "1.0e-45", Greater); test_helper::("1.0e-241", "0x1.0E-200#1", Nearest, "0.0", Less); test_helper::( "1.0e-241", "0x1.0E-200#1", Floor, "1.499696813895631e-241", Equal, ); test_helper::( "1.0e-241", "0x1.0E-200#1", Ceiling, "1.499696813895631e-241", Equal, ); test_helper::( "1.0e-241", "0x1.0E-200#1", Down, "1.499696813895631e-241", Equal, ); test_helper::( "1.0e-241", "0x1.0E-200#1", Up, "1.499696813895631e-241", Equal, ); test_helper::( "1.0e-241", "0x1.0E-200#1", Nearest, "1.499696813895631e-241", Equal, ); test_helper::( "1.0e-241", "0x1.0E-200#1", Exact, "1.499696813895631e-241", Equal, ); test_helper::("6.0e-2409", "0x1.0E-2000#1", Floor, "0.0", Less); test_helper::("6.0e-2409", "0x1.0E-2000#1", Ceiling, "1.0e-45", Greater); test_helper::("6.0e-2409", "0x1.0E-2000#1", Down, "0.0", Less); test_helper::("6.0e-2409", "0x1.0E-2000#1", Up, "1.0e-45", Greater); test_helper::("6.0e-2409", "0x1.0E-2000#1", Nearest, "0.0", Less); test_helper::("6.0e-2409", "0x1.0E-2000#1", Floor, "0.0", Less); test_helper::("6.0e-2409", "0x1.0E-2000#1", Ceiling, "5.0e-324", Greater); test_helper::("6.0e-2409", "0x1.0E-2000#1", Down, "0.0", Less); test_helper::("6.0e-2409", "0x1.0E-2000#1", Up, "5.0e-324", Greater); test_helper::("6.0e-2409", "0x1.0E-2000#1", Nearest, "0.0", Less); test_helper::("too_big", "0x4.0E+268435455#1", Floor, "3.4028235e38", Less); test_helper::( "too_big", "0x4.0E+268435455#1", Ceiling, "Infinity", Greater, ); test_helper::("too_big", "0x4.0E+268435455#1", Down, "3.4028235e38", Less); test_helper::("too_big", "0x4.0E+268435455#1", Up, "Infinity", Greater); test_helper::( "too_big", "0x4.0E+268435455#1", Nearest, "Infinity", Greater, ); test_helper::( "too_big", "0x4.0E+268435455#1", Floor, "1.7976931348623157e308", Less, ); test_helper::( "too_big", "0x4.0E+268435455#1", Ceiling, "Infinity", Greater, ); test_helper::( "too_big", "0x4.0E+268435455#1", Down, "1.7976931348623157e308", Less, ); test_helper::("too_big", "0x4.0E+268435455#1", Up, "Infinity", Greater); test_helper::( "too_big", "0x4.0E+268435455#1", Nearest, "Infinity", Greater, ); test_helper::("too_small", "0x1.0E-268435456#1", Floor, "0.0", Less); test_helper::( "too_small", "0x1.0E-268435456#1", Ceiling, "1.0e-45", Greater, ); test_helper::("too_small", "0x1.0E-268435456#1", Down, "0.0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Up, "1.0e-45", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Nearest, "0.0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Floor, "0.0", Less); test_helper::( "too_small", "0x1.0E-268435456#1", Ceiling, "5.0e-324", Greater, ); test_helper::("too_small", "0x1.0E-268435456#1", Down, "0.0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Up, "5.0e-324", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Nearest, "0.0", Less); test_helper::( "-0.33333334", "-0x0.5555558#24", Floor, "-0.33333334", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Ceiling, "-0.33333334", Equal, ); test_helper::("-0.33333334", "-0x0.5555558#24", Down, "-0.33333334", Equal); test_helper::("-0.33333334", "-0x0.5555558#24", Up, "-0.33333334", Equal); test_helper::( "-0.33333334", "-0x0.5555558#24", Nearest, "-0.33333334", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Exact, "-0.33333334", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Floor, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Ceiling, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Down, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Up, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Nearest, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333334", "-0x0.5555558#24", Exact, "-0.3333333432674408", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "-0.33333334", Less, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "-0.3333333", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "-0.3333333", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "-0.33333334", Less, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "-0.33333334", Less, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "-0.3333333333333333", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "-0.3333333333333333", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "-0.3333333333333333", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "-0.3333333333333333", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "-0.3333333333333333", Equal, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Exact, "-0.3333333333333333", Equal, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Floor, "-0.33333334", Less, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Ceiling, "-0.3333333", Greater, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Down, "-0.3333333", Greater, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Up, "-0.33333334", Less, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Nearest, "-0.33333334", Less, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Floor, "-0.33333333333333337", Less, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Ceiling, "-0.3333333333333333", Greater, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Down, "-0.3333333333333333", Greater, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Up, "-0.33333333333333337", Less, ); test_helper::( "-0.333333333333333332", "-0x0.555555555555554#57", Nearest, "-0.3333333333333333", Greater, ); test_helper::("-7.0e240", "-0x1.0E+200#1", Floor, "-Infinity", Less); test_helper::( "-7.0e240", "-0x1.0E+200#1", Ceiling, "-3.4028235e38", Greater, ); test_helper::("-7.0e240", "-0x1.0E+200#1", Down, "-3.4028235e38", Greater); test_helper::("-7.0e240", "-0x1.0E+200#1", Up, "-Infinity", Less); test_helper::("-7.0e240", "-0x1.0E+200#1", Nearest, "-Infinity", Less); test_helper::( "-7.0e240", "-0x1.0E+200#1", Floor, "-6.668014432879854e240", Equal, ); test_helper::( "-7.0e240", "-0x1.0E+200#1", Ceiling, "-6.668014432879854e240", Equal, ); test_helper::( "-7.0e240", "-0x1.0E+200#1", Down, "-6.668014432879854e240", Equal, ); test_helper::( "-7.0e240", "-0x1.0E+200#1", Up, "-6.668014432879854e240", Equal, ); test_helper::( "-7.0e240", "-0x1.0E+200#1", Nearest, "-6.668014432879854e240", Equal, ); test_helper::( "-7.0e240", "-0x1.0E+200#1", Exact, "-6.668014432879854e240", Equal, ); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Floor, "-Infinity", Less); test_helper::( "-2.0e2408", "-0x1.0E+2000#1", Ceiling, "-3.4028235e38", Greater, ); test_helper::( "-2.0e2408", "-0x1.0E+2000#1", Down, "-3.4028235e38", Greater, ); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Up, "-Infinity", Less); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Nearest, "-Infinity", Less); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Floor, "-Infinity", Less); test_helper::( "-2.0e2408", "-0x1.0E+2000#1", Ceiling, "-1.7976931348623157e308", Greater, ); test_helper::( "-2.0e2408", "-0x1.0E+2000#1", Down, "-1.7976931348623157e308", Greater, ); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Up, "-Infinity", Less); test_helper::("-2.0e2408", "-0x1.0E+2000#1", Nearest, "-Infinity", Less); test_helper::("-1.0e-241", "-0x1.0E-200#1", Floor, "-1.0e-45", Less); test_helper::("-1.0e-241", "-0x1.0E-200#1", Ceiling, "-0.0", Greater); test_helper::("-1.0e-241", "-0x1.0E-200#1", Down, "-0.0", Greater); test_helper::("-1.0e-241", "-0x1.0E-200#1", Up, "-1.0e-45", Less); test_helper::("-1.0e-241", "-0x1.0E-200#1", Nearest, "-0.0", Greater); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Floor, "-1.499696813895631e-241", Equal, ); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Ceiling, "-1.499696813895631e-241", Equal, ); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Down, "-1.499696813895631e-241", Equal, ); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Up, "-1.499696813895631e-241", Equal, ); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Nearest, "-1.499696813895631e-241", Equal, ); test_helper::( "-1.0e-241", "-0x1.0E-200#1", Exact, "-1.499696813895631e-241", Equal, ); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Floor, "-1.0e-45", Less); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Ceiling, "-0.0", Greater); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Down, "-0.0", Greater); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Up, "-1.0e-45", Less); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Nearest, "-0.0", Greater); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Floor, "-5.0e-324", Less); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Ceiling, "-0.0", Greater); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Down, "-0.0", Greater); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Up, "-5.0e-324", Less); test_helper::("-6.0e-2409", "-0x1.0E-2000#1", Nearest, "-0.0", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Floor, "-Infinity", Less); test_helper::( "-too_big", "-0x4.0E+268435455#1", Ceiling, "-3.4028235e38", Greater, ); test_helper::( "-too_big", "-0x4.0E+268435455#1", Down, "-3.4028235e38", Greater, ); test_helper::("-too_big", "-0x4.0E+268435455#1", Up, "-Infinity", Less); test_helper::( "-too_big", "-0x4.0E+268435455#1", Nearest, "-Infinity", Less, ); test_helper::("-too_big", "-0x4.0E+268435455#1", Floor, "-Infinity", Less); test_helper::( "-too_big", "-0x4.0E+268435455#1", Ceiling, "-1.7976931348623157e308", Greater, ); test_helper::( "-too_big", "-0x4.0E+268435455#1", Down, "-1.7976931348623157e308", Greater, ); test_helper::("-too_big", "-0x4.0E+268435455#1", Up, "-Infinity", Less); test_helper::( "-too_big", "-0x4.0E+268435455#1", Nearest, "-Infinity", Less, ); test_helper::("-too_small", "-0x1.0E-268435456#1", Floor, "-1.0e-45", Less); test_helper::( "-too_small", "-0x1.0E-268435456#1", Ceiling, "-0.0", Greater, ); test_helper::("-too_small", "-0x1.0E-268435456#1", Down, "-0.0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Up, "-1.0e-45", Less); test_helper::( "-too_small", "-0x1.0E-268435456#1", Nearest, "-0.0", Greater, ); test_helper::( "-too_small", "-0x1.0E-268435456#1", Floor, "-5.0e-324", Less, ); test_helper::( "-too_small", "-0x1.0E-268435456#1", Ceiling, "-0.0", Greater, ); test_helper::("-too_small", "-0x1.0E-268435456#1", Down, "-0.0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Up, "-5.0e-324", Less); test_helper::( "-too_small", "-0x1.0E-268435456#1", Nearest, "-0.0", Greater, ); } fn rounding_from_float_fail_helper>() { assert_panic!(T::rounding_from( Float::from_rational_prec(Rational::from_unsigneds(1u8, 3), 100).0, Exact )); assert_panic!(T::rounding_from( Float::exact_from(Rational::power_of_2(10000i64)), Exact )); assert_panic!(T::rounding_from( Float::exact_from(Rational::power_of_2(-10000i64)), Exact )); assert_panic!(T::rounding_from( Float::from_rational_prec(Rational::from_signeds(-1, 3), 100).0, Exact )); assert_panic!(T::rounding_from( Float::exact_from(-Rational::power_of_2(10000i64)), Exact )); assert_panic!(T::rounding_from( Float::exact_from(-Rational::power_of_2(-10000i64)), Exact )); } #[test] fn rounding_from_float_fail() { apply_fn_to_primitive_floats!(rounding_from_float_fail_helper); } #[allow( clippy::type_repetition_in_bounds, clippy::op_ref, clippy::needless_pass_by_value )] fn try_from_float_properties_helper_helper< T: PrimitiveFloat + PartialEq + TryFrom, >( x: Float, ) where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = FloatFromFloatError>, Float: From + PartialEq, { let t_x = T::try_from(x.clone()); let t_x_alt = T::try_from(&x); assert_eq!(t_x.map(NiceFloat), t_x_alt.map(NiceFloat)); assert_eq!(t_x.is_ok(), T::convertible_from(&x)); if let Ok(n) = t_x { assert_eq!(NiceFloat(T::exact_from(&x)), NiceFloat(n)); assert!(n.is_nan() && x.is_nan() || n == x); let n_alt = Float::from(n); assert!(n_alt.is_nan() && x.is_nan() || &n_alt == &x); } } #[allow(clippy::type_repetition_in_bounds, clippy::op_ref)] fn try_from_float_properties_helper< T: PrimitiveFloat + PartialEq + TryFrom, >() where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = FloatFromFloatError>, Float: From + PartialEq, { float_gen().test_properties(|x| { try_from_float_properties_helper_helper(x); }); float_gen_var_12().test_properties(|x| { try_from_float_properties_helper_helper(x); }); } #[test] fn try_from_float_properties() { apply_fn_to_primitive_floats!(try_from_float_properties_helper); } #[allow(clippy::needless_pass_by_value)] fn convertible_from_float_properties_helper_helper(x: Float) where for<'a> T: ConvertibleFrom<&'a Float>, { T::convertible_from(&x); } fn convertible_from_float_properties_helper() where for<'a> T: ConvertibleFrom<&'a Float>, { float_gen().test_properties(|x| { convertible_from_float_properties_helper_helper::(x); }); float_gen_var_12().test_properties(|x| { convertible_from_float_properties_helper_helper::(x); }); } #[test] fn convertible_from_float_properties() { apply_fn_to_primitive_floats!(convertible_from_float_properties_helper); } const fn wrap_nice_float(p: (T, Ordering)) -> (NiceFloat, Ordering) { (NiceFloat(p.0), p.1) } #[allow(clippy::type_repetition_in_bounds, clippy::needless_pass_by_value)] fn rounding_from_float_properties_helper_helper< T: PrimitiveFloat + RoundingFrom + PartialOrd, >( x: Float, rm: RoundingMode, extreme: bool, ) where for<'a> T: ConvertibleFrom<&'a Float> + PartialOrd + RoundingFrom<&'a Float>, Float: From + PartialOrd, Rational: TryFrom, { let no = T::rounding_from(&x, rm); let no_alt = T::rounding_from(x.clone(), rm); assert_eq!(NiceFloat(no_alt.0), NiceFloat(no.0)); assert_eq!(no_alt.1, no.1); let (n, o) = no; if !extreme && n > -T::MAX_FINITE && n < T::MAX_FINITE && n != T::ZERO { let r_x: Rational = ExactFrom::<&Float>::exact_from(&x); assert!((Rational::exact_from(n) - r_x).lt_abs(&Float::from(n).ulp().unwrap())); } assert_eq!(n.partial_cmp(&x), if x.is_nan() { None } else { Some(o) }); match (x >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } #[allow(clippy::type_repetition_in_bounds)] fn rounding_from_float_properties_helper< T: PrimitiveFloat + RoundingFrom + PartialOrd, >() where for<'a> T: ConvertibleFrom<&'a Float> + PartialOrd + RoundingFrom<&'a Float>, Float: From + PartialOrd, Rational: TryFrom, { float_rounding_mode_pair_gen_var_6::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_20::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_helper(x, rm, true); }); float_gen_var_4().test_properties(|x| { let floor = T::rounding_from(&x, Floor); assert!(floor.0 <= x); assert_eq!( T::rounding_from(&x, if x >= T::ZERO { Down } else { Up }), floor ); let ceiling = T::rounding_from(&x, Ceiling); assert!(ceiling.0 >= x); assert_eq!( T::rounding_from(&x, if x >= T::ZERO { Up } else { Down }), ceiling ); let nearest = T::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); if nearest.0 > -T::MAX_FINITE && nearest.0 < T::MAX_FINITE && nearest.0 != T::ZERO { let r_x: Rational = ExactFrom::<&Float>::exact_from(&x); let rulp: Rational = ExactFrom::exact_from(Float::from(nearest.0).ulp().unwrap()); assert!((Rational::exact_from(nearest.0) - r_x).le_abs(&(rulp >> 1u32))); } }); primitive_float_gen::().test_properties(|n| { let x = Float::from(n); let no = (NiceFloat(n), Equal); assert_eq!(wrap_nice_float(T::rounding_from(&x, Floor)), no); assert_eq!(wrap_nice_float(T::rounding_from(&x, Down)), no); assert_eq!(wrap_nice_float(T::rounding_from(&x, Ceiling)), no); assert_eq!(wrap_nice_float(T::rounding_from(&x, Up)), no); assert_eq!(wrap_nice_float(T::rounding_from(&x, Nearest)), no); assert_eq!(wrap_nice_float(T::rounding_from(&x, Exact)), no); }); } #[allow(clippy::manual_range_contains)] #[test] fn rounding_from_float_properties() { apply_fn_to_primitive_floats!(rounding_from_float_properties_helper); float_rounding_mode_pair_gen_var_6::().test_properties(|(x, rm)| { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { assert_eq!( NiceFloat(f32::rounding_from(&x, rm).0), NiceFloat(rug::Float::exact_from(&x).to_f32_round(rug_rm)), ); } }); float_rounding_mode_pair_gen_var_6::().test_properties(|(x, rm)| { if let Ok(rug_rm) = rug_round_try_from_rounding_mode(rm) { assert_eq!( NiceFloat(f64::rounding_from(&x, rm).0), NiceFloat(rug::Float::exact_from(&x).to_f64_round(rug_rm)), ); } }); } ================================================ FILE: malachite-float/tests/conversion/primitive_int_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, Floor}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, NegativeOne, OneHalf}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError}; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_float::Float; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::{ float_gen, float_gen_var_4, float_gen_var_5, float_gen_var_12, float_rounding_mode_pair_gen_var_4, float_rounding_mode_pair_gen_var_5, float_rounding_mode_pair_gen_var_18, float_rounding_mode_pair_gen_var_19, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::Rational; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; #[allow(clippy::type_repetition_in_bounds)] #[test] fn test_try_from_float() { fn test_helper_u>( s: &str, s_hex: &str, out: &str, ) where for<'a> T: TryFrom<&'a Float, Error = UnsignedFromFloatError>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = T::try_from(x.clone()); assert_eq!(on.to_debug_string(), out); let on = T::try_from(&x); assert_eq!(on.to_debug_string(), out); } fn test_helper_u2>() where for<'a> T: TryFrom<&'a Float, Error = UnsignedFromFloatError>, { test_helper_u::("NaN", "NaN", "Err(FloatInfiniteOrNan)"); test_helper_u::("Infinity", "Infinity", "Err(FloatInfiniteOrNan)"); test_helper_u::("-Infinity", "-Infinity", "Err(FloatInfiniteOrNan)"); test_helper_u::("0.0", "0x0.0", "Ok(0)"); test_helper_u::("-0.0", "-0x0.0", "Ok(0)"); test_helper_u::("1.0", "0x1.0#1", "Ok(1)"); test_helper_u::("2.0", "0x2.0#1", "Ok(2)"); test_helper_u::("0.5", "0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test_helper_u::( "0.33333333333333331", "0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_u::("123.0", "0x7b.0#7", "Ok(123)"); test_helper_u::( "too_big", "0x4.0E+268435455#1", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_u::( "too_small", "0x1.0E-268435456#1", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_u::("-1.0", "-0x1.0#1", "Err(FloatNegative)"); test_helper_u::("-2.0", "-0x2.0#1", "Err(FloatNegative)"); test_helper_u::("-0.5", "-0x0.8#1", "Err(FloatNegative)"); test_helper_u::( "-0.33333333333333331", "-0x0.55555555555554#53", "Err(FloatNegative)", ); test_helper_u::("-123.0", "-0x7b.0#7", "Err(FloatNegative)"); test_helper_u::( "-1000000000000.0", "-0xe8d4a51000.0#40", "Err(FloatNegative)", ); test_helper_u::("-too_big", "-0x4.0E+268435455#1", "Err(FloatNegative)"); test_helper_u::("-too_small", "-0x1.0E-268435456#1", "Err(FloatNegative)"); } apply_fn_to_unsigneds!(test_helper_u2); test_helper_u::("1000000000000.0", "0xe8d4a51000.0#40", "Ok(1000000000000)"); fn test_helper_i>( s: &str, s_hex: &str, out: &str, ) where for<'a> T: TryFrom<&'a Float, Error = SignedFromFloatError>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = T::try_from(x.clone()); assert_eq!(on.to_debug_string(), out); let on = T::try_from(&x); assert_eq!(on.to_debug_string(), out); } fn test_helper_i2>() where for<'a> T: TryFrom<&'a Float, Error = SignedFromFloatError>, { test_helper_i::("NaN", "NaN", "Err(FloatInfiniteOrNan)"); test_helper_i::("Infinity", "Infinity", "Err(FloatInfiniteOrNan)"); test_helper_i::("-Infinity", "-Infinity", "Err(FloatInfiniteOrNan)"); test_helper_i::("0.0", "0x0.0", "Ok(0)"); test_helper_i::("-0.0", "-0x0.0", "Ok(0)"); test_helper_i::("1.0", "0x1.0#1", "Ok(1)"); test_helper_i::("2.0", "0x2.0#1", "Ok(2)"); test_helper_i::("0.5", "0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test_helper_i::( "0.33333333333333331", "0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_i::("123.0", "0x7b.0#7", "Ok(123)"); test_helper_i::( "too_big", "0x4.0E+268435455#1", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_i::( "too_small", "0x1.0E-268435456#1", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_i::("-1.0", "-0x1.0#1", "Ok(-1)"); test_helper_i::("-2.0", "-0x2.0#1", "Ok(-2)"); test_helper_i::("-0.5", "-0x0.8#1", "Err(FloatNonIntegerOrOutOfRange)"); test_helper_i::( "-0.33333333333333331", "-0x0.55555555555554#53", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_i::("-123.0", "-0x7b.0#7", "Ok(-123)"); test_helper_i::( "-too_big", "-0x4.0E+268435455#1", "Err(FloatNonIntegerOrOutOfRange)", ); test_helper_i::( "-too_small", "-0x1.0E-268435456#1", "Err(FloatNonIntegerOrOutOfRange)", ); } apply_fn_to_signeds!(test_helper_i2); test_helper_i::("1000000000000.0", "0xe8d4a51000.0#40", "Ok(1000000000000)"); test_helper_i::( "-1000000000000.0", "-0xe8d4a51000.0#40", "Ok(-1000000000000)", ); } #[test] fn test_convertible_from_float() { #[allow(clippy::type_repetition_in_bounds)] fn test_helper(s: &str, s_hex: &str, out: bool) where for<'a> T: ConvertibleFrom<&'a Float>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(T::convertible_from(&x), out); } #[allow(clippy::type_repetition_in_bounds)] fn test_helper_u() where for<'a> T: ConvertibleFrom<&'a Float>, { test_helper::("NaN", "NaN", false); test_helper::("Infinity", "Infinity", false); test_helper::("-Infinity", "-Infinity", false); test_helper::("0.0", "0x0.0", true); test_helper::("-0.0", "-0x0.0", true); test_helper::("1.0", "0x1.0#1", true); test_helper::("2.0", "0x2.0#1", true); test_helper::("0.5", "0x0.8#1", false); test_helper::("0.33333333333333331", "0x0.55555555555554#53", false); test_helper::("123.0", "0x7b.0#7", true); test_helper::("too_big", "0x4.0E+268435455#1", false); test_helper::("too_small", "0x1.0E-268435456#1", false); test_helper::("-1.0", "-0x1.0#1", false); test_helper::("-2.0", "-0x2.0#1", false); test_helper::("-0.5", "-0x0.8#1", false); test_helper::("-0.33333333333333331", "-0x0.55555555555554#53", false); test_helper::("-123.0", "-0x7b.0#7", false); test_helper::("-1000000000000.0", "-0xe8d4a51000.0#40", false); test_helper::("-too_big", "-0x4.0E+268435455#1", false); test_helper::("-too_small", "-0x1.0E-268435456#1", false); } apply_fn_to_unsigneds!(test_helper_u); test_helper::("1000000000000.0", "0xe8d4a51000.0#40", true); #[allow(clippy::type_repetition_in_bounds)] fn test_helper_i() where for<'a> T: ConvertibleFrom<&'a Float>, { test_helper::("NaN", "NaN", false); test_helper::("Infinity", "Infinity", false); test_helper::("-Infinity", "-Infinity", false); test_helper::("0.0", "0x0.0", true); test_helper::("-0.0", "-0x0.0", true); test_helper::("1.0", "0x1.0#1", true); test_helper::("2.0", "0x2.0#1", true); test_helper::("0.5", "0x0.8#1", false); test_helper::("0.33333333333333331", "0x0.55555555555554#53", false); test_helper::("123.0", "0x7b.0#7", true); test_helper::("too_big", "0x4.0E+268435455#1", false); test_helper::("too_small", "0x1.0E-268435456#1", false); test_helper::("-1.0", "-0x1.0#1", true); test_helper::("-2.0", "-0x2.0#1", true); test_helper::("-0.5", "-0x0.8#1", false); test_helper::("-0.33333333333333331", "-0x0.55555555555554#53", false); test_helper::("-123.0", "-0x7b.0#7", true); test_helper::("-too_big", "-0x4.0E+268435455#1", false); test_helper::("-too_small", "-0x1.0E-268435456#1", false); } apply_fn_to_signeds!(test_helper_i); test_helper::("1000000000000.0", "0xe8d4a51000.0#40", true); test_helper::("-1000000000000.0", "-0xe8d4a51000.0#40", true); } #[test] fn test_rounding_from_float() { #[allow(clippy::type_repetition_in_bounds)] fn test_helper>( s: &str, s_hex: &str, rm: RoundingMode, out: &str, o_out: Ordering, ) where for<'a> T: RoundingFrom<&'a Float>, { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let (n, o) = T::rounding_from(x.clone(), rm); assert_eq!(n.to_string(), out); assert_eq!(o, o_out); let (n, o) = T::rounding_from(&x, rm); assert_eq!(n.to_string(), out); assert_eq!(o, o_out); } #[allow(clippy::type_repetition_in_bounds)] fn test_helper_u>() where for<'a> T: RoundingFrom<&'a Float>, { test_helper::("-Infinity", "-Infinity", Ceiling, "0", Greater); test_helper::("-Infinity", "-Infinity", Down, "0", Greater); test_helper::("-Infinity", "-Infinity", Nearest, "0", Greater); test_helper::("0.0", "0x0.0", Floor, "0", Equal); test_helper::("0.0", "0x0.0", Ceiling, "0", Equal); test_helper::("0.0", "0x0.0", Down, "0", Equal); test_helper::("0.0", "0x0.0", Up, "0", Equal); test_helper::("0.0", "0x0.0", Nearest, "0", Equal); test_helper::("0.0", "0x0.0", Exact, "0", Equal); test_helper::("-0.0", "-0x0.0", Floor, "0", Equal); test_helper::("-0.0", "-0x0.0", Ceiling, "0", Equal); test_helper::("-0.0", "-0x0.0", Down, "0", Equal); test_helper::("-0.0", "-0x0.0", Up, "0", Equal); test_helper::("-0.0", "-0x0.0", Nearest, "0", Equal); test_helper::("-0.0", "-0x0.0", Exact, "0", Equal); test_helper::("1.0", "0x1.0#1", Floor, "1", Equal); test_helper::("1.0", "0x1.0#1", Ceiling, "1", Equal); test_helper::("1.0", "0x1.0#1", Down, "1", Equal); test_helper::("1.0", "0x1.0#1", Up, "1", Equal); test_helper::("1.0", "0x1.0#1", Nearest, "1", Equal); test_helper::("1.0", "0x1.0#1", Exact, "1", Equal); test_helper::("2.0", "0x2.0#1", Floor, "2", Equal); test_helper::("2.0", "0x2.0#1", Ceiling, "2", Equal); test_helper::("2.0", "0x2.0#1", Down, "2", Equal); test_helper::("2.0", "0x2.0#1", Up, "2", Equal); test_helper::("2.0", "0x2.0#1", Nearest, "2", Equal); test_helper::("2.0", "0x2.0#1", Exact, "2", Equal); test_helper::("0.5", "0x0.8#1", Floor, "0", Less); test_helper::("0.5", "0x0.8#1", Ceiling, "1", Greater); test_helper::("0.5", "0x0.8#1", Down, "0", Less); test_helper::("0.5", "0x0.8#1", Up, "1", Greater); test_helper::("0.5", "0x0.8#1", Nearest, "0", Less); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "1", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Down, "0", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Up, "1", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Floor, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Ceiling, "1", Greater, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Down, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Up, "1", Greater, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Nearest, "1", Greater, ); test_helper::("1.5", "0x1.8#2", Floor, "1", Less); test_helper::("1.5", "0x1.8#2", Ceiling, "2", Greater); test_helper::("1.5", "0x1.8#2", Down, "1", Less); test_helper::("1.5", "0x1.8#2", Up, "2", Greater); test_helper::("1.5", "0x1.8#2", Nearest, "2", Greater); test_helper::("2.5", "0x2.8#3", Floor, "2", Less); test_helper::("2.5", "0x2.8#3", Ceiling, "3", Greater); test_helper::("2.5", "0x2.8#3", Down, "2", Less); test_helper::("2.5", "0x2.8#3", Up, "3", Greater); test_helper::("2.5", "0x2.8#3", Nearest, "2", Less); test_helper::("123.0", "0x7b.0#7", Floor, "123", Equal); test_helper::("123.0", "0x7b.0#7", Ceiling, "123", Equal); test_helper::("123.0", "0x7b.0#7", Down, "123", Equal); test_helper::("123.0", "0x7b.0#7", Up, "123", Equal); test_helper::("123.0", "0x7b.0#7", Nearest, "123", Equal); test_helper::("123.0", "0x7b.0#7", Exact, "123", Equal); test_helper::("too_small", "0x1.0E-268435456#1", Floor, "0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Ceiling, "1", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Down, "0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Up, "1", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Nearest, "0", Less); test_helper::("-1.0", "-0x1.0#1", Ceiling, "0", Greater); test_helper::("-1.0", "-0x1.0#1", Down, "0", Greater); test_helper::("-1.0", "-0x1.0#1", Nearest, "0", Greater); test_helper::("-2.0", "-0x2.0#1", Ceiling, "0", Greater); test_helper::("-2.0", "-0x2.0#1", Down, "0", Greater); test_helper::("-2.0", "-0x2.0#1", Nearest, "0", Greater); test_helper::("-0.5", "-0x0.8#1", Ceiling, "0", Greater); test_helper::("-0.5", "-0x0.8#1", Down, "0", Greater); test_helper::("-0.5", "-0x0.8#1", Nearest, "0", Greater); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "0", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "0", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Ceiling, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Down, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Nearest, "0", Greater, ); test_helper::("-1.5", "-0x1.8#2", Ceiling, "0", Greater); test_helper::("-1.5", "-0x1.8#2", Down, "0", Greater); test_helper::("-1.5", "-0x1.8#2", Nearest, "0", Greater); test_helper::("-2.5", "-0x2.8#3", Ceiling, "0", Greater); test_helper::("-2.5", "-0x2.8#3", Down, "0", Greater); test_helper::("-2.5", "-0x2.8#3", Nearest, "0", Greater); test_helper::("-123.0", "-0x7b.0#7", Ceiling, "0", Greater); test_helper::("-123.0", "-0x7b.0#7", Down, "0", Greater); test_helper::("-123.0", "-0x7b.0#7", Nearest, "0", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Ceiling, "0", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Down, "0", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Nearest, "0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Ceiling, "0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Down, "0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Nearest, "0", Greater); } apply_fn_to_unsigneds!(test_helper_u); test_helper::("too_big", "0x4.0E+268435455#1", Floor, "255", Less); test_helper::("too_big", "0x4.0E+268435455#1", Down, "255", Less); test_helper::("too_big", "0x4.0E+268435455#1", Nearest, "255", Less); #[allow(clippy::type_repetition_in_bounds)] fn test_helper_i>() where for<'a> T: RoundingFrom<&'a Float>, { test_helper::("0.0", "0x0.0", Floor, "0", Equal); test_helper::("0.0", "0x0.0", Ceiling, "0", Equal); test_helper::("0.0", "0x0.0", Down, "0", Equal); test_helper::("0.0", "0x0.0", Up, "0", Equal); test_helper::("0.0", "0x0.0", Nearest, "0", Equal); test_helper::("0.0", "0x0.0", Exact, "0", Equal); test_helper::("-0.0", "-0x0.0", Floor, "0", Equal); test_helper::("-0.0", "-0x0.0", Ceiling, "0", Equal); test_helper::("-0.0", "-0x0.0", Down, "0", Equal); test_helper::("-0.0", "-0x0.0", Up, "0", Equal); test_helper::("-0.0", "-0x0.0", Nearest, "0", Equal); test_helper::("-0.0", "-0x0.0", Exact, "0", Equal); test_helper::("1.0", "0x1.0#1", Floor, "1", Equal); test_helper::("1.0", "0x1.0#1", Ceiling, "1", Equal); test_helper::("1.0", "0x1.0#1", Down, "1", Equal); test_helper::("1.0", "0x1.0#1", Up, "1", Equal); test_helper::("1.0", "0x1.0#1", Nearest, "1", Equal); test_helper::("1.0", "0x1.0#1", Exact, "1", Equal); test_helper::("2.0", "0x2.0#1", Floor, "2", Equal); test_helper::("2.0", "0x2.0#1", Ceiling, "2", Equal); test_helper::("2.0", "0x2.0#1", Down, "2", Equal); test_helper::("2.0", "0x2.0#1", Up, "2", Equal); test_helper::("2.0", "0x2.0#1", Nearest, "2", Equal); test_helper::("2.0", "0x2.0#1", Exact, "2", Equal); test_helper::("0.5", "0x0.8#1", Floor, "0", Less); test_helper::("0.5", "0x0.8#1", Ceiling, "1", Greater); test_helper::("0.5", "0x0.8#1", Down, "0", Less); test_helper::("0.5", "0x0.8#1", Up, "1", Greater); test_helper::("0.5", "0x0.8#1", Nearest, "0", Less); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Floor, "0", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Ceiling, "1", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Down, "0", Less, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Up, "1", Greater, ); test_helper::( "0.33333333333333331", "0x0.55555555555554#53", Nearest, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Floor, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Ceiling, "1", Greater, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Down, "0", Less, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Up, "1", Greater, ); test_helper::( "0.6666666666666666", "0x0.aaaaaaaaaaaaa8#53", Nearest, "1", Greater, ); test_helper::("1.5", "0x1.8#2", Floor, "1", Less); test_helper::("1.5", "0x1.8#2", Ceiling, "2", Greater); test_helper::("1.5", "0x1.8#2", Down, "1", Less); test_helper::("1.5", "0x1.8#2", Up, "2", Greater); test_helper::("1.5", "0x1.8#2", Nearest, "2", Greater); test_helper::("2.5", "0x2.8#3", Floor, "2", Less); test_helper::("2.5", "0x2.8#3", Ceiling, "3", Greater); test_helper::("2.5", "0x2.8#3", Down, "2", Less); test_helper::("2.5", "0x2.8#3", Up, "3", Greater); test_helper::("2.5", "0x2.8#3", Nearest, "2", Less); test_helper::("123.0", "0x7b.0#7", Floor, "123", Equal); test_helper::("123.0", "0x7b.0#7", Ceiling, "123", Equal); test_helper::("123.0", "0x7b.0#7", Down, "123", Equal); test_helper::("123.0", "0x7b.0#7", Up, "123", Equal); test_helper::("123.0", "0x7b.0#7", Nearest, "123", Equal); test_helper::("123.0", "0x7b.0#7", Exact, "123", Equal); test_helper::("too_small", "0x1.0E-268435456#1", Floor, "0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Ceiling, "1", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Down, "0", Less); test_helper::("too_small", "0x1.0E-268435456#1", Up, "1", Greater); test_helper::("too_small", "0x1.0E-268435456#1", Nearest, "0", Less); test_helper::("-1.0", "-0x1.0#1", Floor, "-1", Equal); test_helper::("-1.0", "-0x1.0#1", Ceiling, "-1", Equal); test_helper::("-1.0", "-0x1.0#1", Down, "-1", Equal); test_helper::("-1.0", "-0x1.0#1", Up, "-1", Equal); test_helper::("-1.0", "-0x1.0#1", Nearest, "-1", Equal); test_helper::("-1.0", "-0x1.0#1", Exact, "-1", Equal); test_helper::("-2.0", "-0x2.0#1", Floor, "-2", Equal); test_helper::("-2.0", "-0x2.0#1", Ceiling, "-2", Equal); test_helper::("-2.0", "-0x2.0#1", Down, "-2", Equal); test_helper::("-2.0", "-0x2.0#1", Up, "-2", Equal); test_helper::("-2.0", "-0x2.0#1", Nearest, "-2", Equal); test_helper::("-2.0", "-0x2.0#1", Exact, "-2", Equal); test_helper::("-0.5", "-0x0.8#1", Floor, "-1", Less); test_helper::("-0.5", "-0x0.8#1", Ceiling, "0", Greater); test_helper::("-0.5", "-0x0.8#1", Down, "0", Greater); test_helper::("-0.5", "-0x0.8#1", Up, "-1", Less); test_helper::("-0.5", "-0x0.8#1", Nearest, "0", Greater); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Floor, "-1", Less, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Ceiling, "0", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Down, "0", Greater, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Up, "-1", Less, ); test_helper::( "-0.33333333333333331", "-0x0.55555555555554#53", Nearest, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Floor, "-1", Less, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Ceiling, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Down, "0", Greater, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Up, "-1", Less, ); test_helper::( "-0.6666666666666666", "-0x0.aaaaaaaaaaaaa8#53", Nearest, "-1", Less, ); test_helper::("-1.5", "-0x1.8#2", Floor, "-2", Less); test_helper::("-1.5", "-0x1.8#2", Ceiling, "-1", Greater); test_helper::("-1.5", "-0x1.8#2", Down, "-1", Greater); test_helper::("-1.5", "-0x1.8#2", Up, "-2", Less); test_helper::("-1.5", "-0x1.8#2", Nearest, "-2", Less); test_helper::("-2.5", "-0x2.8#3", Floor, "-3", Less); test_helper::("-2.5", "-0x2.8#3", Ceiling, "-2", Greater); test_helper::("-2.5", "-0x2.8#3", Down, "-2", Greater); test_helper::("-2.5", "-0x2.8#3", Up, "-3", Less); test_helper::("-2.5", "-0x2.8#3", Nearest, "-2", Greater); test_helper::("-123.0", "-0x7b.0#7", Floor, "-123", Equal); test_helper::("-123.0", "-0x7b.0#7", Ceiling, "-123", Equal); test_helper::("-123.0", "-0x7b.0#7", Down, "-123", Equal); test_helper::("-123.0", "-0x7b.0#7", Up, "-123", Equal); test_helper::("-123.0", "-0x7b.0#7", Nearest, "-123", Equal); test_helper::("-123.0", "-0x7b.0#7", Exact, "-123", Equal); test_helper::("-too_small", "-0x1.0E-268435456#1", Floor, "-1", Less); test_helper::("-too_small", "-0x1.0E-268435456#1", Ceiling, "0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Down, "0", Greater); test_helper::("-too_small", "-0x1.0E-268435456#1", Up, "-1", Less); test_helper::("-too_small", "-0x1.0E-268435456#1", Nearest, "0", Greater); } apply_fn_to_signeds!(test_helper_i); test_helper::("too_big", "0x4.0E+268435455#1", Floor, "127", Less); test_helper::("too_big", "0x4.0E+268435455#1", Down, "127", Less); test_helper::("too_big", "0x4.0E+268435455#1", Nearest, "127", Less); test_helper::("-too_big", "-0x4.0E+268435455#1", Ceiling, "-128", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Down, "-128", Greater); test_helper::("-too_big", "-0x4.0E+268435455#1", Nearest, "-128", Greater); } fn unsigned_rounding_from_float_fail_helper>() { assert_panic!(T::rounding_from(Float::NAN, Floor)); assert_panic!(T::rounding_from(Float::NAN, Ceiling)); assert_panic!(T::rounding_from(Float::NAN, Down)); assert_panic!(T::rounding_from(Float::NAN, Up)); assert_panic!(T::rounding_from(Float::NAN, Nearest)); assert_panic!(T::rounding_from(Float::NAN, Exact)); assert_panic!(T::rounding_from(Float::INFINITY, Ceiling)); assert_panic!(T::rounding_from(Float::INFINITY, Up)); assert_panic!(T::rounding_from(Float::INFINITY, Exact)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Floor)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Up)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Exact)); assert_panic!(T::rounding_from(Float::NEGATIVE_ONE, Floor)); assert_panic!(T::rounding_from(Float::NEGATIVE_ONE, Up)); assert_panic!(T::rounding_from(Float::NEGATIVE_ONE, Exact)); assert_panic!(T::rounding_from(Float::from(3u8) >> 1, Exact)); } fn signed_rounding_from_float_fail_helper>() { assert_panic!(T::rounding_from(Float::NAN, Floor)); assert_panic!(T::rounding_from(Float::NAN, Ceiling)); assert_panic!(T::rounding_from(Float::NAN, Down)); assert_panic!(T::rounding_from(Float::NAN, Up)); assert_panic!(T::rounding_from(Float::NAN, Nearest)); assert_panic!(T::rounding_from(Float::NAN, Exact)); assert_panic!(T::rounding_from(Float::INFINITY, Ceiling)); assert_panic!(T::rounding_from(Float::INFINITY, Up)); assert_panic!(T::rounding_from(Float::INFINITY, Exact)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Floor)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Up)); assert_panic!(T::rounding_from(Float::NEGATIVE_INFINITY, Exact)); assert_panic!(T::rounding_from(Float::from(3u8) >> 1, Exact)); assert_panic!(T::rounding_from(Float::from(-3i8) >> 1, Exact)); } #[test] fn rounding_from_float_fail() { apply_fn_to_unsigneds!(unsigned_rounding_from_float_fail_helper); apply_fn_to_signeds!(signed_rounding_from_float_fail_helper); } #[allow(clippy::type_repetition_in_bounds)] fn unsigned_rounding_from_float_ref_fail_helper() where for<'a> T: RoundingFrom<&'a Float>, { assert_panic!(T::rounding_from(&Float::NAN, Floor)); assert_panic!(T::rounding_from(&Float::NAN, Ceiling)); assert_panic!(T::rounding_from(&Float::NAN, Down)); assert_panic!(T::rounding_from(&Float::NAN, Up)); assert_panic!(T::rounding_from(&Float::NAN, Nearest)); assert_panic!(T::rounding_from(&Float::NAN, Exact)); assert_panic!(T::rounding_from(&Float::INFINITY, Ceiling)); assert_panic!(T::rounding_from(&Float::INFINITY, Up)); assert_panic!(T::rounding_from(&Float::INFINITY, Exact)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Floor)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Up)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Exact)); assert_panic!(T::rounding_from(&Float::NEGATIVE_ONE, Floor)); assert_panic!(T::rounding_from(&Float::NEGATIVE_ONE, Up)); assert_panic!(T::rounding_from(&Float::NEGATIVE_ONE, Exact)); assert_panic!(T::rounding_from(&(Float::from(3u8) >> 1), Exact)); } #[allow(clippy::type_repetition_in_bounds)] fn signed_rounding_from_float_ref_fail_helper() where for<'a> T: RoundingFrom<&'a Float>, { assert_panic!(T::rounding_from(&Float::NAN, Floor)); assert_panic!(T::rounding_from(&Float::NAN, Ceiling)); assert_panic!(T::rounding_from(&Float::NAN, Down)); assert_panic!(T::rounding_from(&Float::NAN, Up)); assert_panic!(T::rounding_from(&Float::NAN, Nearest)); assert_panic!(T::rounding_from(&Float::NAN, Exact)); assert_panic!(T::rounding_from(&Float::INFINITY, Ceiling)); assert_panic!(T::rounding_from(&Float::INFINITY, Up)); assert_panic!(T::rounding_from(&Float::INFINITY, Exact)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Floor)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Up)); assert_panic!(T::rounding_from(&Float::NEGATIVE_INFINITY, Exact)); assert_panic!(T::rounding_from(&(Float::from(3u8) >> 1), Exact)); assert_panic!(T::rounding_from(&(Float::from(-3i8) >> 1), Exact)); } #[test] fn rounding_from_float_ref_fail() { apply_fn_to_unsigneds!(unsigned_rounding_from_float_ref_fail_helper); apply_fn_to_signeds!(signed_rounding_from_float_ref_fail_helper); } #[allow(clippy::needless_pass_by_value, clippy::type_repetition_in_bounds)] fn try_from_float_properties_helper_unsigned_helper< T: PrimitiveUnsigned + PartialEq + TryFrom, >( x: Float, ) where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = UnsignedFromFloatError>, Float: From + PartialEq, { let t_x = T::try_from(x.clone()); let t_x_alt = T::try_from(&x); assert_eq!(t_x, t_x_alt); assert_eq!(t_x.is_ok(), T::convertible_from(&x)); if let Ok(n) = t_x { assert_eq!(T::exact_from(&x), n); assert_eq!(n, x); assert_eq!(&Float::from(n), &x); } } #[allow(clippy::type_repetition_in_bounds)] fn try_from_float_properties_helper_unsigned< T: PrimitiveUnsigned + PartialEq + TryFrom, >() where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = UnsignedFromFloatError>, Float: From + PartialEq, { float_gen().test_properties(|x| { try_from_float_properties_helper_unsigned_helper(x); }); float_gen_var_12().test_properties(|x| { try_from_float_properties_helper_unsigned_helper(x); }); } #[allow(clippy::needless_pass_by_value, clippy::type_repetition_in_bounds)] fn try_from_float_properties_helper_signed_helper< T: PrimitiveSigned + PartialEq + TryFrom, >( x: Float, ) where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = SignedFromFloatError>, Float: From + PartialEq, { let t_x = T::try_from(x.clone()); let t_x_alt = T::try_from(&x); assert_eq!(t_x, t_x_alt); assert_eq!(t_x.is_ok(), T::convertible_from(&x)); if let Ok(n) = t_x { assert_eq!(T::exact_from(&x), n); assert_eq!(n, x); assert_eq!(&Float::from(n), &x); } } #[allow(clippy::type_repetition_in_bounds)] fn try_from_float_properties_helper_signed< T: PrimitiveSigned + PartialEq + TryFrom, >() where for<'a> T: ConvertibleFrom<&'a Float> + TryFrom<&'a Float, Error = SignedFromFloatError>, Float: From + PartialEq, { float_gen().test_properties(|x| { try_from_float_properties_helper_signed_helper(x); }); float_gen_var_12().test_properties(|x| { try_from_float_properties_helper_signed_helper(x); }); } #[test] fn try_from_float_properties() { apply_fn_to_unsigneds!(try_from_float_properties_helper_unsigned); apply_fn_to_signeds!(try_from_float_properties_helper_signed); } #[allow(clippy::needless_pass_by_value)] fn convertible_from_float_properties_helper_helper(x: Float) where for<'a> T: ConvertibleFrom<&'a Float>, { T::convertible_from(&x); } fn convertible_from_float_properties_helper() where for<'a> T: ConvertibleFrom<&'a Float>, { float_gen().test_properties(|x| { convertible_from_float_properties_helper_helper::(x); }); float_gen_var_12().test_properties(|x| { convertible_from_float_properties_helper_helper::(x); }); } #[test] fn convertible_from_float_properties() { apply_fn_to_primitive_ints!(convertible_from_float_properties_helper); } #[allow(clippy::needless_pass_by_value)] fn rounding_from_float_properties_helper_unsigned_helper< T: PrimitiveUnsigned + PartialOrd + PartialOrd + RoundingFrom, >( x: Float, rm: RoundingMode, extreme: bool, ) where Float: From + PartialOrd, Natural: From, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, for<'a> Rational: From, { let no = T::rounding_from(&x, rm); assert_eq!(T::rounding_from(x.clone(), rm), no); let (n, o) = no; if !extreme && x >= T::ZERO && x <= T::MAX { assert!((Rational::from(n) - Rational::exact_from(&x)).lt_abs(&1)); } assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } fn rounding_from_float_properties_helper_unsigned< T: PrimitiveUnsigned + PartialOrd + PartialOrd + RoundingFrom, >() where Float: From + PartialOrd, Natural: From, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, for<'a> Rational: From, { float_rounding_mode_pair_gen_var_4::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_unsigned_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_18::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_unsigned_helper(x, rm, true); }); float_gen_var_5().test_properties(|x| { let floor = T::rounding_from(&x, Floor); if x <= T::MAX { assert_eq!(floor.0, Rational::exact_from(&x).floor()); } assert!(floor.0 <= x); if floor.0 != T::MAX { assert!(floor.0 + T::ONE > x); } assert_eq!(T::rounding_from(&x, Down), floor); let nearest = T::rounding_from(&x, Nearest); if x <= T::MAX { let ceiling = T::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, Rational::exact_from(&x).ceiling()); assert!(ceiling.0 >= x); if x > T::ZERO { assert!(ceiling.0 - T::ONE < x); } assert_eq!(T::rounding_from(&x, Up), ceiling); assert!(nearest == floor || nearest == ceiling); assert!( (Rational::from(nearest.0) - Rational::exact_from(x)).le_abs(&Rational::ONE_HALF) ); } else { assert!(nearest == (T::MAX, Less)); } }); unsigned_gen::().test_properties(|n| { let x = Float::from(n); let no = (n, Equal); assert_eq!(T::rounding_from(&x, Floor), no); assert_eq!(T::rounding_from(&x, Down), no); assert_eq!(T::rounding_from(&x, Ceiling), no); assert_eq!(T::rounding_from(&x, Up), no); assert_eq!(T::rounding_from(&x, Nearest), no); assert_eq!(T::rounding_from(&x, Exact), no); let x = Float::from((no.0 << 1) | T::ONE) >> 1; assert!(T::rounding_from(x, Nearest).0.even()); }); } #[allow(clippy::needless_pass_by_value)] fn rounding_from_float_properties_helper_signed_helper< T: PrimitiveSigned + RoundingFrom + PartialOrd + PartialOrd, >( x: Float, rm: RoundingMode, extreme: bool, ) where Float: From + PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, Integer: From + PartialEq, Rational: From, { let no = T::rounding_from(&x, rm); assert_eq!(T::rounding_from(x.clone(), rm), no); let (n, o) = no; if !extreme && x >= T::MIN && x <= T::MAX { assert!((Rational::from(n) - Rational::exact_from(&x)).lt_abs(&1)); } assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } } fn rounding_from_float_properties_helper_signed< T: PrimitiveSigned + RoundingFrom + PartialOrd + PartialOrd, >() where Float: From + PartialOrd, for<'a> T: ConvertibleFrom<&'a Float> + RoundingFrom<&'a Float>, Integer: From + PartialEq, Rational: From, { float_rounding_mode_pair_gen_var_5::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_signed_helper(x, rm, false); }); float_rounding_mode_pair_gen_var_19::().test_properties(|(x, rm)| { rounding_from_float_properties_helper_signed_helper(x, rm, true); }); float_gen_var_4().test_properties(|x| { let mut o_floor = None; if x >= T::MIN { let floor = T::rounding_from(&x, Floor); assert!(floor.0 <= x); if x <= T::MAX { assert_eq!(floor.0, Rational::exact_from(&x).floor()); } if floor.0 != T::MAX { assert!(floor.0 + T::ONE > x); } assert_eq!( T::rounding_from(&x, if x >= T::ZERO { Down } else { Up }), floor ); o_floor = Some(floor); } let mut o_ceiling = None; if x <= T::MAX { let ceiling = T::rounding_from(&x, Ceiling); assert!(ceiling.0 >= x); if x >= T::MIN { assert_eq!(ceiling.0, Rational::exact_from(&x).ceiling()); } if ceiling.0 != T::MIN { assert!(ceiling.0 - T::ONE < x); } assert_eq!( T::rounding_from(&x, if x >= T::ZERO { Up } else { Down }), ceiling ); o_ceiling = Some(ceiling); } let nearest = T::rounding_from(&x, Nearest); if let Some(floor) = o_floor && let Some(ceiling) = o_ceiling { assert!(nearest == floor || nearest == ceiling); } if x >= T::MIN && x <= T::MAX { assert!( (Rational::from(nearest.0) - Rational::exact_from(x)).le_abs(&Rational::ONE_HALF) ); } }); signed_gen::().test_properties(|n| { let x = Float::from(n); let no = (n, Equal); assert_eq!(T::rounding_from(&x, Floor), no); assert_eq!(T::rounding_from(&x, Down), no); assert_eq!(T::rounding_from(&x, Ceiling), no); assert_eq!(T::rounding_from(&x, Up), no); assert_eq!(T::rounding_from(&x, Nearest), no); assert_eq!(T::rounding_from(&x, Exact), no); let x = Float::from((no.0 << 1) | T::ONE) >> 1; assert!(T::rounding_from(x, Nearest).0.even()); }); } #[test] fn rounding_from_float_properties() { apply_fn_to_unsigneds!(rounding_from_float_properties_helper_unsigned); apply_fn_to_signeds!(rounding_from_float_properties_helper_signed); } ================================================ FILE: malachite-float/tests/conversion/rational_from_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::strings::ToDebugString; use malachite_float::Float; use malachite_float::conversion::rational_from_float::RationalFromFloatError; use malachite_float::test_util::common::parse_hex_string; use malachite_float::test_util::generators::float_gen; use malachite_q::Rational; #[test] fn test_try_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); let on = Rational::try_from(x.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Rational::try_from(&x); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("NaN", "NaN", "Err(RationalFromFloatError)"); test("Infinity", "Infinity", "Err(RationalFromFloatError)"); test("-Infinity", "-Infinity", "Err(RationalFromFloatError)"); test("0.0", "0x0.0", "Ok(0)"); test("-0.0", "-0x0.0", "Ok(0)"); test("1.0", "0x1.0#1", "Ok(1)"); test("2.0", "0x2.0#1", "Ok(2)"); test("0.5", "0x0.8#1", "Ok(1/2)"); test( "0.33333333333333331", "0x0.55555555555554#53", "Ok(6004799503160661/18014398509481984)", ); test("123.0", "0x7b.0#7", "Ok(123)"); test("1000000000000.0", "0xe8d4a51000.0#40", "Ok(1000000000000)"); test( "1.4142135623730951", "0x1.6a09e667f3bcd#53", "Ok(6369051672525773/4503599627370496)", ); test( "3.141592653589793", "0x3.243f6a8885a3#50", "Ok(884279719003555/281474976710656)", ); test( "2.7182818284590451", "0x2.b7e151628aed2#53", "Ok(6121026514868073/2251799813685248)", ); test("-1.0", "-0x1.0#1", "Ok(-1)"); test("-2.0", "-0x2.0#1", "Ok(-2)"); test("-0.5", "-0x0.8#1", "Ok(-1/2)"); test( "-0.33333333333333331", "-0x0.55555555555554#53", "Ok(-6004799503160661/18014398509481984)", ); test("-123.0", "-0x7b.0#7", "Ok(-123)"); test( "-1000000000000.0", "-0xe8d4a51000.0#40", "Ok(-1000000000000)", ); test( "-1.4142135623730951", "-0x1.6a09e667f3bcd#53", "Ok(-6369051672525773/4503599627370496)", ); test( "-3.141592653589793", "-0x3.243f6a8885a3#50", "Ok(-884279719003555/281474976710656)", ); test( "-2.7182818284590451", "-0x2.b7e151628aed2#53", "Ok(-6121026514868073/2251799813685248)", ); } #[test] fn test_convertible_from_float() { let test = |s, s_hex, out| { let x = parse_hex_string(s_hex); assert_eq!(x.to_string(), s); assert_eq!(Rational::convertible_from(&x), out); }; test("NaN", "NaN", false); test("Infinity", "Infinity", false); test("-Infinity", "-Infinity", false); test("0.0", "0x0.0", true); test("-0.0", "-0x0.0", true); test("1.0", "0x1.0#1", true); test("2.0", "0x2.0#1", true); test("0.5", "0x0.8#1", true); test("0.33333333333333331", "0x0.55555555555554#53", true); test("123.0", "0x7b.0#7", true); test("1000000000000.0", "0xe8d4a51000.0#40", true); test("1.4142135623730951", "0x1.6a09e667f3bcd#53", true); test("3.141592653589793", "0x3.243f6a8885a3#50", true); test("2.7182818284590451", "0x2.b7e151628aed2#53", true); test("-1.0", "-0x1.0#1", true); test("-2.0", "-0x2.0#1", true); test("-0.5", "-0x0.8#1", true); test("-0.33333333333333331", "-0x0.55555555555554#53", true); test("-123.0", "-0x7b.0#7", true); test("-1000000000000.0", "-0xe8d4a51000.0#40", true); test("-1.4142135623730951", "-0x1.6a09e667f3bcd#53", true); test("-3.141592653589793", "-0x3.243f6a8885a3#50", true); test("-2.7182818284590451", "-0x2.b7e151628aed2#53", true); } #[test] fn try_from_float_properties() { float_gen().test_properties(|x| { let rational_x = Rational::try_from(x.clone()); assert!(rational_x.as_ref().map_or(true, Rational::is_valid)); let rational_x_alt = Rational::try_from(&x); assert!(rational_x_alt.as_ref().map_or(true, Rational::is_valid)); assert_eq!(rational_x, rational_x_alt); assert_eq!( rug::Rational::try_from(rug::Float::exact_from(&x)) .map(|q| Rational::from(&q)) .map_err(|_| RationalFromFloatError), rational_x ); assert_eq!(rational_x.is_ok(), Rational::convertible_from(&x)); if let Ok(n) = rational_x { assert_eq!(Rational::exact_from(&x), n); assert_eq!(n, x); assert_eq!(Float::exact_from(&n), x); assert_eq!(Float::exact_from(n.clone()), x); assert!(n.denominator_ref().is_power_of_2()); } }); } #[test] fn convertible_from_float_properties() { float_gen().test_properties(|x| { assert_eq!(Rational::convertible_from(&x), x.is_finite()); }); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_finite_floats(), &[ "0.0", "-0.0", "1.0", "-1.0", "2.0", "-2.0", "1.0", "-1.0", "2.0", "-2.0", "0.5", "-0.5", "4.0", "-4.0", "0.5", "-0.5", "4.0", "-4.0", "1.5", "-1.5", "3.0", "-3.0", "1.0", "-1.0", "2.0", "-2.0", "0.8", "-0.8", "6.0", "-6.0", "0.5", "-0.5", "4.0", "-4.0", "0.2", "-0.2", "8.0", "-8.0", "0.2", "-0.2", "8.0", "-8.0", "0.1", "-0.1", "2.0e1", "-2.0e1", "0.1", "-0.1", "16.0", "-16.0", "0.4", "-0.4", "1.0e1", "-1.0e1", "0.25", "-0.25", "8.0", "-8.0", "0.19", "-0.19", "24.0", "-24.0", "0.1", "-0.1", "16.0", "-16.0", "1.2", "-1.2", "2.5", "-2.5", "1.5", "-1.5", "3.0", "-3.0", "0.6", "-0.6", "5.0", "-5.0", "0.8", "-0.8", "6.0", "-6.0", "1.8", "-1.8", "3.5", "-3.5", "1.0", "-1.0", "2.0", "-2.0", "0.9", "-0.9", "7.0", "-7.0", "0.5", "-0.5", "4.0", "-4.0", "0.3", "-0.3", ], &[ "0x0.0", "-0x0.0", "0x1.0#1", "-0x1.0#1", "0x2.0#1", "-0x2.0#1", "0x1.0#2", "-0x1.0#2", "0x2.0#2", "-0x2.0#2", "0x0.8#1", "-0x0.8#1", "0x4.0#1", "-0x4.0#1", "0x0.8#2", "-0x0.8#2", "0x4.0#2", "-0x4.0#2", "0x1.8#2", "-0x1.8#2", "0x3.0#2", "-0x3.0#2", "0x1.0#3", "-0x1.0#3", "0x2.0#3", "-0x2.0#3", "0x0.c#2", "-0x0.c#2", "0x6.0#2", "-0x6.0#2", "0x0.8#3", "-0x0.8#3", "0x4.0#3", "-0x4.0#3", "0x0.4#1", "-0x0.4#1", "0x8.0#1", "-0x8.0#1", "0x0.4#2", "-0x0.4#2", "0x8.0#2", "-0x8.0#2", "0x0.2#1", "-0x0.2#1", "0x1.0E+1#1", "-0x1.0E+1#1", "0x0.2#2", "-0x0.2#2", "0x10.0#2", "-0x10.0#2", "0x0.6#2", "-0x0.6#2", "0xc.0#2", "-0xc.0#2", "0x0.4#3", "-0x0.4#3", "0x8.0#3", "-0x8.0#3", "0x0.3#2", "-0x0.3#2", "0x18.0#2", "-0x18.0#2", "0x0.20#3", "-0x0.20#3", "0x10.0#3", "-0x10.0#3", "0x1.4#3", "-0x1.4#3", "0x2.8#3", "-0x2.8#3", "0x1.8#3", "-0x1.8#3", "0x3.0#3", "-0x3.0#3", "0x0.a#3", "-0x0.a#3", "0x5.0#3", "-0x5.0#3", "0x0.c#3", "-0x0.c#3", "0x6.0#3", "-0x6.0#3", "0x1.c#3", "-0x1.c#3", "0x3.8#3", "-0x3.8#3", "0x1.0#4", "-0x1.0#4", "0x2.0#4", "-0x2.0#4", "0x0.e#3", "-0x0.e#3", "0x7.0#3", "-0x7.0#3", "0x0.8#4", "-0x0.8#4", "0x4.0#4", "-0x4.0#4", "0x0.5#3", "-0x0.5#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_floats(), &[ "NaN", "Infinity", "-Infinity", "0.0", "-0.0", "1.0", "-1.0", "2.0", "-2.0", "1.0", "-1.0", "2.0", "-2.0", "0.5", "-0.5", "4.0", "-4.0", "0.5", "-0.5", "4.0", "-4.0", "1.5", "-1.5", "3.0", "-3.0", "1.0", "-1.0", "2.0", "-2.0", "0.8", "-0.8", "6.0", "-6.0", "0.5", "-0.5", "4.0", "-4.0", "0.2", "-0.2", "8.0", "-8.0", "0.2", "-0.2", "8.0", "-8.0", "0.1", "-0.1", "2.0e1", "-2.0e1", "0.1", "-0.1", "16.0", "-16.0", "0.4", "-0.4", "1.0e1", "-1.0e1", "0.25", "-0.25", "8.0", "-8.0", "0.19", "-0.19", "24.0", "-24.0", "0.1", "-0.1", "16.0", "-16.0", "1.2", "-1.2", "2.5", "-2.5", "1.5", "-1.5", "3.0", "-3.0", "0.6", "-0.6", "5.0", "-5.0", "0.8", "-0.8", "6.0", "-6.0", "1.8", "-1.8", "3.5", "-3.5", "1.0", "-1.0", "2.0", "-2.0", "0.9", "-0.9", "7.0", "-7.0", "0.5", "-0.5", "4.0", ], &[ "NaN", "Infinity", "-Infinity", "0x0.0", "-0x0.0", "0x1.0#1", "-0x1.0#1", "0x2.0#1", "-0x2.0#1", "0x1.0#2", "-0x1.0#2", "0x2.0#2", "-0x2.0#2", "0x0.8#1", "-0x0.8#1", "0x4.0#1", "-0x4.0#1", "0x0.8#2", "-0x0.8#2", "0x4.0#2", "-0x4.0#2", "0x1.8#2", "-0x1.8#2", "0x3.0#2", "-0x3.0#2", "0x1.0#3", "-0x1.0#3", "0x2.0#3", "-0x2.0#3", "0x0.c#2", "-0x0.c#2", "0x6.0#2", "-0x6.0#2", "0x0.8#3", "-0x0.8#3", "0x4.0#3", "-0x4.0#3", "0x0.4#1", "-0x0.4#1", "0x8.0#1", "-0x8.0#1", "0x0.4#2", "-0x0.4#2", "0x8.0#2", "-0x8.0#2", "0x0.2#1", "-0x0.2#1", "0x1.0E+1#1", "-0x1.0E+1#1", "0x0.2#2", "-0x0.2#2", "0x10.0#2", "-0x10.0#2", "0x0.6#2", "-0x0.6#2", "0xc.0#2", "-0xc.0#2", "0x0.4#3", "-0x0.4#3", "0x8.0#3", "-0x8.0#3", "0x0.3#2", "-0x0.3#2", "0x18.0#2", "-0x18.0#2", "0x0.20#3", "-0x0.20#3", "0x10.0#3", "-0x10.0#3", "0x1.4#3", "-0x1.4#3", "0x2.8#3", "-0x2.8#3", "0x1.8#3", "-0x1.8#3", "0x3.0#3", "-0x3.0#3", "0x0.a#3", "-0x0.a#3", "0x5.0#3", "-0x5.0#3", "0x0.c#3", "-0x0.c#3", "0x6.0#3", "-0x6.0#3", "0x1.c#3", "-0x1.c#3", "0x3.8#3", "-0x3.8#3", "0x1.0#4", "-0x1.0#4", "0x2.0#4", "-0x2.0#4", "0x0.e#3", "-0x0.e#3", "0x7.0#3", "-0x7.0#3", "0x0.8#4", "-0x0.8#4", "0x4.0#4", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_floats_with_precision.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_floats_with_precision; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; use std::panic::catch_unwind; fn exhaustive_floats_with_precision_helper(precision: u64, out: &[&str], out_hex: &[&str]) { exhaustive_floats_helper_helper_with_limit( 20, exhaustive_floats_with_precision(precision), out, out_hex, ); } #[test] fn test_exhaustive_floats_with_precision() { exhaustive_floats_with_precision_helper( 1, &[ "1.0", "-1.0", "2.0", "-2.0", "0.5", "-0.5", "0.2", "-0.2", "4.0", "-4.0", "8.0", "-8.0", "0.1", "-0.1", "3.0e1", "-3.0e1", "2.0e1", "-2.0e1", "0.06", "-0.06", ], &[ "0x1.0#1", "-0x1.0#1", "0x2.0#1", "-0x2.0#1", "0x0.8#1", "-0x0.8#1", "0x0.4#1", "-0x0.4#1", "0x4.0#1", "-0x4.0#1", "0x8.0#1", "-0x8.0#1", "0x0.2#1", "-0x0.2#1", "0x2.0E+1#1", "-0x2.0E+1#1", "0x1.0E+1#1", "-0x1.0E+1#1", "0x0.1#1", "-0x0.1#1", ], ); exhaustive_floats_with_precision_helper( 2, &[ "1.0", "-1.0", "2.0", "-2.0", "1.5", "-1.5", "0.5", "-0.5", "3.0", "-3.0", "0.8", "-0.8", "4.0", "-4.0", "0.1", "-0.1", "6.0", "-6.0", "0.2", "-0.2", ], &[ "0x1.0#2", "-0x1.0#2", "0x2.0#2", "-0x2.0#2", "0x1.8#2", "-0x1.8#2", "0x0.8#2", "-0x0.8#2", "0x3.0#2", "-0x3.0#2", "0x0.c#2", "-0x0.c#2", "0x4.0#2", "-0x4.0#2", "0x0.2#2", "-0x0.2#2", "0x6.0#2", "-0x6.0#2", "0x0.4#2", "-0x0.4#2", ], ); exhaustive_floats_with_precision_helper( 10, &[ "1.0", "-1.0", "2.0", "-2.0", "1.002", "-1.002", "0.5", "-0.5", "1.004", "-1.004", "2.004", "-2.004", "1.006", "-1.006", "4.0", "-4.0", "1.008", "-1.008", "2.008", "-2.008", ], &[ "0x1.000#10", "-0x1.000#10", "0x2.00#10", "-0x2.00#10", "0x1.008#10", "-0x1.008#10", "0x0.800#10", "-0x0.800#10", "0x1.010#10", "-0x1.010#10", "0x2.01#10", "-0x2.01#10", "0x1.018#10", "-0x1.018#10", "0x4.00#10", "-0x4.00#10", "0x1.020#10", "-0x1.020#10", "0x2.02#10", "-0x2.02#10", ], ); exhaustive_floats_with_precision_helper( 100, &[ "1.0", "-1.0", "2.0", "-2.0", "1.000000000000000000000000000002", "-1.000000000000000000000000000002", "0.5", "-0.5", "1.000000000000000000000000000003", "-1.000000000000000000000000000003", "2.000000000000000000000000000003", "-2.000000000000000000000000000003", "1.000000000000000000000000000005", "-1.000000000000000000000000000005", "4.0", "-4.0", "1.000000000000000000000000000006", "-1.000000000000000000000000000006", "2.000000000000000000000000000006", "-2.000000000000000000000000000006", ], &[ "0x1.0000000000000000000000000#100", "-0x1.0000000000000000000000000#100", "0x2.0000000000000000000000000#100", "-0x2.0000000000000000000000000#100", "0x1.0000000000000000000000002#100", "-0x1.0000000000000000000000002#100", "0x0.8000000000000000000000000#100", "-0x0.8000000000000000000000000#100", "0x1.0000000000000000000000004#100", "-0x1.0000000000000000000000004#100", "0x2.0000000000000000000000004#100", "-0x2.0000000000000000000000004#100", "0x1.0000000000000000000000006#100", "-0x1.0000000000000000000000006#100", "0x4.0000000000000000000000000#100", "-0x4.0000000000000000000000000#100", "0x1.0000000000000000000000008#100", "-0x1.0000000000000000000000008#100", "0x2.0000000000000000000000008#100", "-0x2.0000000000000000000000008#100", ], ); } #[test] fn exhaustive_floats_with_precision_fail() { assert_panic!(exhaustive_floats_with_precision(0)); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_negative_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_negative_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_negative_finite_floats(), &[ "-1.0", "-2.0", "-1.0", "-2.0", "-0.5", "-4.0", "-0.5", "-4.0", "-1.5", "-3.0", "-1.0", "-2.0", "-0.8", "-6.0", "-0.5", "-4.0", "-0.2", "-8.0", "-0.2", "-8.0", "-0.1", "-2.0e1", "-0.1", "-16.0", "-0.4", "-1.0e1", "-0.25", "-8.0", "-0.19", "-24.0", "-0.1", "-16.0", "-1.2", "-2.5", "-1.5", "-3.0", "-0.6", "-5.0", "-0.8", "-6.0", "-1.8", "-3.5", "-1.0", "-2.0", "-0.9", "-7.0", "-0.5", "-4.0", "-0.3", "-10.0", "-0.38", "-12.0", "-0.16", "-20.0", "-0.19", "-24.0", "-0.44", "-14.0", "-0.25", "-8.0", "-0.22", "-28.0", "-0.12", "-16.0", "-0.06", "-3.0e1", "-0.06", "-3.0e1", "-0.03", "-6.0e1", "-0.03", "-6.0e1", "-0.09", "-5.0e1", "-0.06", "-3.0e1", "-0.05", "-96.0", "-0.03", "-6.0e1", "-0.02", "-1.0e2", "-0.016", "-1.0e2", "-0.008", "-3.0e2", "-0.008", "-3.0e2", "-0.023", "-2.0e2", "-0.016", "-1.3e2", "-0.01", "-4.0e2", "-0.008", "-2.6e2", "-0.08", "-4.0e1", "-0.09", "-5.0e1", ], &[ "-0x1.0#1", "-0x2.0#1", "-0x1.0#2", "-0x2.0#2", "-0x0.8#1", "-0x4.0#1", "-0x0.8#2", "-0x4.0#2", "-0x1.8#2", "-0x3.0#2", "-0x1.0#3", "-0x2.0#3", "-0x0.c#2", "-0x6.0#2", "-0x0.8#3", "-0x4.0#3", "-0x0.4#1", "-0x8.0#1", "-0x0.4#2", "-0x8.0#2", "-0x0.2#1", "-0x1.0E+1#1", "-0x0.2#2", "-0x10.0#2", "-0x0.6#2", "-0xc.0#2", "-0x0.4#3", "-0x8.0#3", "-0x0.3#2", "-0x18.0#2", "-0x0.20#3", "-0x10.0#3", "-0x1.4#3", "-0x2.8#3", "-0x1.8#3", "-0x3.0#3", "-0x0.a#3", "-0x5.0#3", "-0x0.c#3", "-0x6.0#3", "-0x1.c#3", "-0x3.8#3", "-0x1.0#4", "-0x2.0#4", "-0x0.e#3", "-0x7.0#3", "-0x0.8#4", "-0x4.0#4", "-0x0.5#3", "-0xa.0#3", "-0x0.6#3", "-0xc.0#3", "-0x0.28#3", "-0x14.0#3", "-0x0.30#3", "-0x18.0#3", "-0x0.7#3", "-0xe.0#3", "-0x0.40#4", "-0x8.0#4", "-0x0.38#3", "-0x1c.0#3", "-0x0.20#4", "-0x10.0#4", "-0x0.1#1", "-0x2.0E+1#1", "-0x0.10#2", "-0x2.0E+1#2", "-0x0.08#1", "-0x4.0E+1#1", "-0x0.08#2", "-0x4.0E+1#2", "-0x0.18#2", "-0x3.0E+1#2", "-0x0.10#3", "-0x20.0#3", "-0x0.0c#2", "-0x6.0E+1#2", "-0x0.08#3", "-0x4.0E+1#3", "-0x0.04#1", "-0x8.0E+1#1", "-0x0.04#2", "-0x8.0E+1#2", "-0x0.02#1", "-0x1.0E+2#1", "-0x0.02#2", "-0x1.0E+2#2", "-0x0.06#2", "-0xc.0E+1#2", "-0x0.04#3", "-0x8.0E+1#3", "-0x0.03#2", "-0x1.8E+2#2", "-0x0.020#3", "-0x1.0E+2#3", "-0x0.14#3", "-0x28.0#3", "-0x0.18#3", "-0x30.0#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_non_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_non_negative_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_non_negative_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_non_negative_finite_floats(), &[ "0.0", "1.0", "2.0", "1.0", "2.0", "0.5", "4.0", "0.5", "4.0", "1.5", "3.0", "1.0", "2.0", "0.8", "6.0", "0.5", "4.0", "0.2", "8.0", "0.2", "8.0", "0.1", "2.0e1", "0.1", "16.0", "0.4", "1.0e1", "0.25", "8.0", "0.19", "24.0", "0.1", "16.0", "1.2", "2.5", "1.5", "3.0", "0.6", "5.0", "0.8", "6.0", "1.8", "3.5", "1.0", "2.0", "0.9", "7.0", "0.5", "4.0", "0.3", "10.0", "0.38", "12.0", "0.16", "20.0", "0.19", "24.0", "0.44", "14.0", "0.25", "8.0", "0.22", "28.0", "0.12", "16.0", "0.06", "3.0e1", "0.06", "3.0e1", "0.03", "6.0e1", "0.03", "6.0e1", "0.09", "5.0e1", "0.06", "3.0e1", "0.05", "96.0", "0.03", "6.0e1", "0.02", "1.0e2", "0.016", "1.0e2", "0.008", "3.0e2", "0.008", "3.0e2", "0.023", "2.0e2", "0.016", "1.3e2", "0.01", "4.0e2", "0.008", "2.6e2", "0.08", "4.0e1", "0.09", ], &[ "0x0.0", "0x1.0#1", "0x2.0#1", "0x1.0#2", "0x2.0#2", "0x0.8#1", "0x4.0#1", "0x0.8#2", "0x4.0#2", "0x1.8#2", "0x3.0#2", "0x1.0#3", "0x2.0#3", "0x0.c#2", "0x6.0#2", "0x0.8#3", "0x4.0#3", "0x0.4#1", "0x8.0#1", "0x0.4#2", "0x8.0#2", "0x0.2#1", "0x1.0E+1#1", "0x0.2#2", "0x10.0#2", "0x0.6#2", "0xc.0#2", "0x0.4#3", "0x8.0#3", "0x0.3#2", "0x18.0#2", "0x0.20#3", "0x10.0#3", "0x1.4#3", "0x2.8#3", "0x1.8#3", "0x3.0#3", "0x0.a#3", "0x5.0#3", "0x0.c#3", "0x6.0#3", "0x1.c#3", "0x3.8#3", "0x1.0#4", "0x2.0#4", "0x0.e#3", "0x7.0#3", "0x0.8#4", "0x4.0#4", "0x0.5#3", "0xa.0#3", "0x0.6#3", "0xc.0#3", "0x0.28#3", "0x14.0#3", "0x0.30#3", "0x18.0#3", "0x0.7#3", "0xe.0#3", "0x0.40#4", "0x8.0#4", "0x0.38#3", "0x1c.0#3", "0x0.20#4", "0x10.0#4", "0x0.1#1", "0x2.0E+1#1", "0x0.10#2", "0x2.0E+1#2", "0x0.08#1", "0x4.0E+1#1", "0x0.08#2", "0x4.0E+1#2", "0x0.18#2", "0x3.0E+1#2", "0x0.10#3", "0x20.0#3", "0x0.0c#2", "0x6.0E+1#2", "0x0.08#3", "0x4.0E+1#3", "0x0.04#1", "0x8.0E+1#1", "0x0.04#2", "0x8.0E+1#2", "0x0.02#1", "0x1.0E+2#1", "0x0.02#2", "0x1.0E+2#2", "0x0.06#2", "0xc.0E+1#2", "0x0.04#3", "0x8.0E+1#3", "0x0.03#2", "0x1.8E+2#2", "0x0.020#3", "0x1.0E+2#3", "0x0.14#3", "0x28.0#3", "0x0.18#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_non_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_non_positive_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_non_positive_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_non_positive_finite_floats(), &[ "-0.0", "-1.0", "-2.0", "-1.0", "-2.0", "-0.5", "-4.0", "-0.5", "-4.0", "-1.5", "-3.0", "-1.0", "-2.0", "-0.8", "-6.0", "-0.5", "-4.0", "-0.2", "-8.0", "-0.2", "-8.0", "-0.1", "-2.0e1", "-0.1", "-16.0", "-0.4", "-1.0e1", "-0.25", "-8.0", "-0.19", "-24.0", "-0.1", "-16.0", "-1.2", "-2.5", "-1.5", "-3.0", "-0.6", "-5.0", "-0.8", "-6.0", "-1.8", "-3.5", "-1.0", "-2.0", "-0.9", "-7.0", "-0.5", "-4.0", "-0.3", "-10.0", "-0.38", "-12.0", "-0.16", "-20.0", "-0.19", "-24.0", "-0.44", "-14.0", "-0.25", "-8.0", "-0.22", "-28.0", "-0.12", "-16.0", "-0.06", "-3.0e1", "-0.06", "-3.0e1", "-0.03", "-6.0e1", "-0.03", "-6.0e1", "-0.09", "-5.0e1", "-0.06", "-3.0e1", "-0.05", "-96.0", "-0.03", "-6.0e1", "-0.02", "-1.0e2", "-0.016", "-1.0e2", "-0.008", "-3.0e2", "-0.008", "-3.0e2", "-0.023", "-2.0e2", "-0.016", "-1.3e2", "-0.01", "-4.0e2", "-0.008", "-2.6e2", "-0.08", "-4.0e1", "-0.09", ], &[ "-0x0.0", "-0x1.0#1", "-0x2.0#1", "-0x1.0#2", "-0x2.0#2", "-0x0.8#1", "-0x4.0#1", "-0x0.8#2", "-0x4.0#2", "-0x1.8#2", "-0x3.0#2", "-0x1.0#3", "-0x2.0#3", "-0x0.c#2", "-0x6.0#2", "-0x0.8#3", "-0x4.0#3", "-0x0.4#1", "-0x8.0#1", "-0x0.4#2", "-0x8.0#2", "-0x0.2#1", "-0x1.0E+1#1", "-0x0.2#2", "-0x10.0#2", "-0x0.6#2", "-0xc.0#2", "-0x0.4#3", "-0x8.0#3", "-0x0.3#2", "-0x18.0#2", "-0x0.20#3", "-0x10.0#3", "-0x1.4#3", "-0x2.8#3", "-0x1.8#3", "-0x3.0#3", "-0x0.a#3", "-0x5.0#3", "-0x0.c#3", "-0x6.0#3", "-0x1.c#3", "-0x3.8#3", "-0x1.0#4", "-0x2.0#4", "-0x0.e#3", "-0x7.0#3", "-0x0.8#4", "-0x4.0#4", "-0x0.5#3", "-0xa.0#3", "-0x0.6#3", "-0xc.0#3", "-0x0.28#3", "-0x14.0#3", "-0x0.30#3", "-0x18.0#3", "-0x0.7#3", "-0xe.0#3", "-0x0.40#4", "-0x8.0#4", "-0x0.38#3", "-0x1c.0#3", "-0x0.20#4", "-0x10.0#4", "-0x0.1#1", "-0x2.0E+1#1", "-0x0.10#2", "-0x2.0E+1#2", "-0x0.08#1", "-0x4.0E+1#1", "-0x0.08#2", "-0x4.0E+1#2", "-0x0.18#2", "-0x3.0E+1#2", "-0x0.10#3", "-0x20.0#3", "-0x0.0c#2", "-0x6.0E+1#2", "-0x0.08#3", "-0x4.0E+1#3", "-0x0.04#1", "-0x8.0E+1#1", "-0x0.04#2", "-0x8.0E+1#2", "-0x0.02#1", "-0x1.0E+2#1", "-0x0.02#2", "-0x1.0E+2#2", "-0x0.06#2", "-0xc.0E+1#2", "-0x0.04#3", "-0x8.0E+1#3", "-0x0.03#2", "-0x1.8E+2#2", "-0x0.020#3", "-0x1.0E+2#3", "-0x0.14#3", "-0x28.0#3", "-0x0.18#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_nonzero_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_nonzero_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_nonzero_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_nonzero_finite_floats(), &[ "1.0", "-1.0", "2.0", "-2.0", "1.0", "-1.0", "2.0", "-2.0", "0.5", "-0.5", "4.0", "-4.0", "0.5", "-0.5", "4.0", "-4.0", "1.5", "-1.5", "3.0", "-3.0", "1.0", "-1.0", "2.0", "-2.0", "0.8", "-0.8", "6.0", "-6.0", "0.5", "-0.5", "4.0", "-4.0", "0.2", "-0.2", "8.0", "-8.0", "0.2", "-0.2", "8.0", "-8.0", "0.1", "-0.1", "2.0e1", "-2.0e1", "0.1", "-0.1", "16.0", "-16.0", "0.4", "-0.4", "1.0e1", "-1.0e1", "0.25", "-0.25", "8.0", "-8.0", "0.19", "-0.19", "24.0", "-24.0", "0.1", "-0.1", "16.0", "-16.0", "1.2", "-1.2", "2.5", "-2.5", "1.5", "-1.5", "3.0", "-3.0", "0.6", "-0.6", "5.0", "-5.0", "0.8", "-0.8", "6.0", "-6.0", "1.8", "-1.8", "3.5", "-3.5", "1.0", "-1.0", "2.0", "-2.0", "0.9", "-0.9", "7.0", "-7.0", "0.5", "-0.5", "4.0", "-4.0", "0.3", "-0.3", "10.0", "-10.0", ], &[ "0x1.0#1", "-0x1.0#1", "0x2.0#1", "-0x2.0#1", "0x1.0#2", "-0x1.0#2", "0x2.0#2", "-0x2.0#2", "0x0.8#1", "-0x0.8#1", "0x4.0#1", "-0x4.0#1", "0x0.8#2", "-0x0.8#2", "0x4.0#2", "-0x4.0#2", "0x1.8#2", "-0x1.8#2", "0x3.0#2", "-0x3.0#2", "0x1.0#3", "-0x1.0#3", "0x2.0#3", "-0x2.0#3", "0x0.c#2", "-0x0.c#2", "0x6.0#2", "-0x6.0#2", "0x0.8#3", "-0x0.8#3", "0x4.0#3", "-0x4.0#3", "0x0.4#1", "-0x0.4#1", "0x8.0#1", "-0x8.0#1", "0x0.4#2", "-0x0.4#2", "0x8.0#2", "-0x8.0#2", "0x0.2#1", "-0x0.2#1", "0x1.0E+1#1", "-0x1.0E+1#1", "0x0.2#2", "-0x0.2#2", "0x10.0#2", "-0x10.0#2", "0x0.6#2", "-0x0.6#2", "0xc.0#2", "-0xc.0#2", "0x0.4#3", "-0x0.4#3", "0x8.0#3", "-0x8.0#3", "0x0.3#2", "-0x0.3#2", "0x18.0#2", "-0x18.0#2", "0x0.20#3", "-0x0.20#3", "0x10.0#3", "-0x10.0#3", "0x1.4#3", "-0x1.4#3", "0x2.8#3", "-0x2.8#3", "0x1.8#3", "-0x1.8#3", "0x3.0#3", "-0x3.0#3", "0x0.a#3", "-0x0.a#3", "0x5.0#3", "-0x5.0#3", "0x0.c#3", "-0x0.c#3", "0x6.0#3", "-0x6.0#3", "0x1.c#3", "-0x1.c#3", "0x3.8#3", "-0x3.8#3", "0x1.0#4", "-0x1.0#4", "0x2.0#4", "-0x2.0#4", "0x0.e#3", "-0x0.e#3", "0x7.0#3", "-0x7.0#3", "0x0.8#4", "-0x0.8#4", "0x4.0#4", "-0x4.0#4", "0x0.5#3", "-0x0.5#3", "0xa.0#3", "-0xa.0#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_positive_finite_floats; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; #[test] fn test_exhaustive_positive_finite_floats() { exhaustive_floats_helper_helper_with_limit( 100, exhaustive_positive_finite_floats(), &[ "1.0", "2.0", "1.0", "2.0", "0.5", "4.0", "0.5", "4.0", "1.5", "3.0", "1.0", "2.0", "0.8", "6.0", "0.5", "4.0", "0.2", "8.0", "0.2", "8.0", "0.1", "2.0e1", "0.1", "16.0", "0.4", "1.0e1", "0.25", "8.0", "0.19", "24.0", "0.1", "16.0", "1.2", "2.5", "1.5", "3.0", "0.6", "5.0", "0.8", "6.0", "1.8", "3.5", "1.0", "2.0", "0.9", "7.0", "0.5", "4.0", "0.3", "10.0", "0.38", "12.0", "0.16", "20.0", "0.19", "24.0", "0.44", "14.0", "0.25", "8.0", "0.22", "28.0", "0.12", "16.0", "0.06", "3.0e1", "0.06", "3.0e1", "0.03", "6.0e1", "0.03", "6.0e1", "0.09", "5.0e1", "0.06", "3.0e1", "0.05", "96.0", "0.03", "6.0e1", "0.02", "1.0e2", "0.016", "1.0e2", "0.008", "3.0e2", "0.008", "3.0e2", "0.023", "2.0e2", "0.016", "1.3e2", "0.01", "4.0e2", "0.008", "2.6e2", "0.08", "4.0e1", "0.09", "5.0e1", ], &[ "0x1.0#1", "0x2.0#1", "0x1.0#2", "0x2.0#2", "0x0.8#1", "0x4.0#1", "0x0.8#2", "0x4.0#2", "0x1.8#2", "0x3.0#2", "0x1.0#3", "0x2.0#3", "0x0.c#2", "0x6.0#2", "0x0.8#3", "0x4.0#3", "0x0.4#1", "0x8.0#1", "0x0.4#2", "0x8.0#2", "0x0.2#1", "0x1.0E+1#1", "0x0.2#2", "0x10.0#2", "0x0.6#2", "0xc.0#2", "0x0.4#3", "0x8.0#3", "0x0.3#2", "0x18.0#2", "0x0.20#3", "0x10.0#3", "0x1.4#3", "0x2.8#3", "0x1.8#3", "0x3.0#3", "0x0.a#3", "0x5.0#3", "0x0.c#3", "0x6.0#3", "0x1.c#3", "0x3.8#3", "0x1.0#4", "0x2.0#4", "0x0.e#3", "0x7.0#3", "0x0.8#4", "0x4.0#4", "0x0.5#3", "0xa.0#3", "0x0.6#3", "0xc.0#3", "0x0.28#3", "0x14.0#3", "0x0.30#3", "0x18.0#3", "0x0.7#3", "0xe.0#3", "0x0.40#4", "0x8.0#4", "0x0.38#3", "0x1c.0#3", "0x0.20#4", "0x10.0#4", "0x0.1#1", "0x2.0E+1#1", "0x0.10#2", "0x2.0E+1#2", "0x0.08#1", "0x4.0E+1#1", "0x0.08#2", "0x4.0E+1#2", "0x0.18#2", "0x3.0E+1#2", "0x0.10#3", "0x20.0#3", "0x0.0c#2", "0x6.0E+1#2", "0x0.08#3", "0x4.0E+1#3", "0x0.04#1", "0x8.0E+1#1", "0x0.04#2", "0x8.0E+1#2", "0x0.02#1", "0x1.0E+2#1", "0x0.02#2", "0x1.0E+2#2", "0x0.06#2", "0xc.0E+1#2", "0x0.04#3", "0x8.0E+1#3", "0x0.03#2", "0x1.8E+2#2", "0x0.020#3", "0x1.0E+2#3", "0x0.14#3", "0x28.0#3", "0x0.18#3", "0x30.0#3", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_positive_floats_with_precision.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_positive_floats_with_precision; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; use std::panic::catch_unwind; fn exhaustive_positive_floats_with_precision_helper( precision: u64, out: &[&str], out_hex: &[&str], ) { exhaustive_floats_helper_helper_with_limit( 20, exhaustive_positive_floats_with_precision(precision), out, out_hex, ); } #[test] fn test_exhaustive_positive_floats_with_precision() { exhaustive_positive_floats_with_precision_helper( 1, &[ "1.0", "2.0", "0.5", "0.2", "4.0", "8.0", "0.1", "3.0e1", "2.0e1", "0.06", "0.03", "0.02", "6.0e1", "1.0e2", "0.008", "0.002", "3.0e2", "0.004", "5.0e2", "1.0e3", ], &[ "0x1.0#1", "0x2.0#1", "0x0.8#1", "0x0.4#1", "0x4.0#1", "0x8.0#1", "0x0.2#1", "0x2.0E+1#1", "0x1.0E+1#1", "0x0.1#1", "0x0.08#1", "0x0.04#1", "0x4.0E+1#1", "0x8.0E+1#1", "0x0.02#1", "0x0.008#1", "0x1.0E+2#1", "0x0.01#1", "0x2.0E+2#1", "0x4.0E+2#1", ], ); exhaustive_positive_floats_with_precision_helper( 2, &[ "1.0", "2.0", "1.5", "0.5", "3.0", "0.8", "4.0", "0.1", "6.0", "0.2", "0.4", "0.19", "8.0", "16.0", "1.0e1", "0.03", "24.0", "0.06", "0.09", "0.05", ], &[ "0x1.0#2", "0x2.0#2", "0x1.8#2", "0x0.8#2", "0x3.0#2", "0x0.c#2", "0x4.0#2", "0x0.2#2", "0x6.0#2", "0x0.4#2", "0x0.6#2", "0x0.3#2", "0x8.0#2", "0x10.0#2", "0xc.0#2", "0x0.08#2", "0x18.0#2", "0x0.10#2", "0x0.18#2", "0x0.0c#2", ], ); exhaustive_positive_floats_with_precision_helper( 10, &[ "1.0", "2.0", "1.002", "0.5", "1.004", "2.004", "1.006", "4.0", "1.008", "2.008", "1.01", "0.501", "1.012", "2.012", "1.014", "0.25", "1.016", "2.016", "1.018", "0.502", ], &[ "0x1.000#10", "0x2.00#10", "0x1.008#10", "0x0.800#10", "0x1.010#10", "0x2.01#10", "0x1.018#10", "0x4.00#10", "0x1.020#10", "0x2.02#10", "0x1.028#10", "0x0.804#10", "0x1.030#10", "0x2.03#10", "0x1.038#10", "0x0.400#10", "0x1.040#10", "0x2.04#10", "0x1.048#10", "0x0.808#10", ], ); exhaustive_positive_floats_with_precision_helper( 100, &[ "1.0", "2.0", "1.000000000000000000000000000002", "0.5", "1.000000000000000000000000000003", "2.000000000000000000000000000003", "1.000000000000000000000000000005", "4.0", "1.000000000000000000000000000006", "2.000000000000000000000000000006", "1.000000000000000000000000000008", "0.500000000000000000000000000001", "1.000000000000000000000000000009", "2.000000000000000000000000000009", "1.000000000000000000000000000011", "0.25", "1.000000000000000000000000000013", "2.000000000000000000000000000013", "1.000000000000000000000000000014", "0.5000000000000000000000000000016", ], &[ "0x1.0000000000000000000000000#100", "0x2.0000000000000000000000000#100", "0x1.0000000000000000000000002#100", "0x0.8000000000000000000000000#100", "0x1.0000000000000000000000004#100", "0x2.0000000000000000000000004#100", "0x1.0000000000000000000000006#100", "0x4.0000000000000000000000000#100", "0x1.0000000000000000000000008#100", "0x2.0000000000000000000000008#100", "0x1.000000000000000000000000a#100", "0x0.8000000000000000000000001#100", "0x1.000000000000000000000000c#100", "0x2.000000000000000000000000c#100", "0x1.000000000000000000000000e#100", "0x0.40000000000000000000000000#100", "0x1.0000000000000000000000010#100", "0x2.0000000000000000000000010#100", "0x1.0000000000000000000000012#100", "0x0.8000000000000000000000002#100", ], ); } #[test] fn exhaustive_positive_floats_with_precision_fail() { assert_panic!(exhaustive_positive_floats_with_precision(0)); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_positive_floats_with_sci_exponent.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_positive_floats_with_sci_exponent; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; fn exhaustive_positive_floats_with_sci_exponent_helper( sci_exponent: i32, out: &[&str], out_hex: &[&str], ) { exhaustive_floats_helper_helper_with_limit( 20, exhaustive_positive_floats_with_sci_exponent(sci_exponent), out, out_hex, ); } #[test] fn test_exhaustive_positive_floats_with_sci_exponent() { exhaustive_positive_floats_with_sci_exponent_helper( 0, &[ "1.0", "1.0", "1.5", "1.0", "1.2", "1.5", "1.8", "1.0", "1.1", "1.2", "1.4", "1.5", "1.6", "1.8", "1.9", "1.0", "1.06", "1.12", "1.19", "1.25", ], &[ "0x1.0#1", "0x1.0#2", "0x1.8#2", "0x1.0#3", "0x1.4#3", "0x1.8#3", "0x1.c#3", "0x1.0#4", "0x1.2#4", "0x1.4#4", "0x1.6#4", "0x1.8#4", "0x1.a#4", "0x1.c#4", "0x1.e#4", "0x1.0#5", "0x1.1#5", "0x1.2#5", "0x1.3#5", "0x1.4#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( 1, &[ "2.0", "2.0", "3.0", "2.0", "2.5", "3.0", "3.5", "2.0", "2.2", "2.5", "2.8", "3.0", "3.2", "3.5", "3.8", "2.0", "2.1", "2.2", "2.4", "2.5", ], &[ "0x2.0#1", "0x2.0#2", "0x3.0#2", "0x2.0#3", "0x2.8#3", "0x3.0#3", "0x3.8#3", "0x2.0#4", "0x2.4#4", "0x2.8#4", "0x2.c#4", "0x3.0#4", "0x3.4#4", "0x3.8#4", "0x3.c#4", "0x2.0#5", "0x2.2#5", "0x2.4#5", "0x2.6#5", "0x2.8#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( 2, &[ "4.0", "4.0", "6.0", "4.0", "5.0", "6.0", "7.0", "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5", "4.0", "4.2", "4.5", "4.8", "5.0", ], &[ "0x4.0#1", "0x4.0#2", "0x6.0#2", "0x4.0#3", "0x5.0#3", "0x6.0#3", "0x7.0#3", "0x4.0#4", "0x4.8#4", "0x5.0#4", "0x5.8#4", "0x6.0#4", "0x6.8#4", "0x7.0#4", "0x7.8#4", "0x4.0#5", "0x4.4#5", "0x4.8#5", "0x4.c#5", "0x5.0#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( 10, &[ "1.0e3", "1.0e3", "1.5e3", "1.0e3", "1.3e3", "1.5e3", "1.8e3", "1.0e3", "1.2e3", "1.3e3", "1.4e3", "1.5e3", "1.7e3", "1.8e3", "1.9e3", "1.0e3", "1.1e3", "1.15e3", "1.22e3", "1.28e3", ], &[ "0x4.0E+2#1", "0x4.0E+2#2", "0x6.0E+2#2", "0x4.0E+2#3", "0x5.0E+2#3", "0x6.0E+2#3", "0x7.0E+2#3", "0x4.0E+2#4", "0x4.8E+2#4", "0x5.0E+2#4", "0x5.8E+2#4", "0x6.0E+2#4", "0x6.8E+2#4", "0x7.0E+2#4", "0x7.8E+2#4", "0x4.0E+2#5", "0x4.4E+2#5", "0x4.8E+2#5", "0x4.cE+2#5", "0x5.0E+2#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( -1, &[ "0.5", "0.5", "0.8", "0.5", "0.6", "0.8", "0.9", "0.5", "0.56", "0.62", "0.7", "0.75", "0.81", "0.88", "0.94", "0.5", "0.53", "0.56", "0.59", "0.62", ], &[ "0x0.8#1", "0x0.8#2", "0x0.c#2", "0x0.8#3", "0x0.a#3", "0x0.c#3", "0x0.e#3", "0x0.8#4", "0x0.9#4", "0x0.a#4", "0x0.b#4", "0x0.c#4", "0x0.d#4", "0x0.e#4", "0x0.f#4", "0x0.80#5", "0x0.88#5", "0x0.90#5", "0x0.98#5", "0x0.a0#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( -2, &[ "0.2", "0.2", "0.4", "0.25", "0.3", "0.38", "0.44", "0.25", "0.28", "0.31", "0.34", "0.38", "0.41", "0.44", "0.47", "0.25", "0.27", "0.28", "0.3", "0.31", ], &[ "0x0.4#1", "0x0.4#2", "0x0.6#2", "0x0.4#3", "0x0.5#3", "0x0.6#3", "0x0.7#3", "0x0.40#4", "0x0.48#4", "0x0.50#4", "0x0.58#4", "0x0.60#4", "0x0.68#4", "0x0.70#4", "0x0.78#4", "0x0.40#5", "0x0.44#5", "0x0.48#5", "0x0.4c#5", "0x0.50#5", ], ); exhaustive_positive_floats_with_sci_exponent_helper( -10, &[ "0.001", "0.00098", "0.0015", "0.00098", "0.0012", "0.0015", "0.0017", "0.00098", "0.0011", "0.0012", "0.0013", "0.0015", "0.0016", "0.0017", "0.0018", "0.00098", "0.001", "0.0011", "0.00116", "0.00122", ], &[ "0x0.004#1", "0x0.004#2", "0x0.006#2", "0x0.004#3", "0x0.005#3", "0x0.006#3", "0x0.007#3", "0x0.0040#4", "0x0.0048#4", "0x0.0050#4", "0x0.0058#4", "0x0.0060#4", "0x0.0068#4", "0x0.0070#4", "0x0.0078#4", "0x0.0040#5", "0x0.0044#5", "0x0.0048#5", "0x0.004c#5", "0x0.0050#5", ], ); } ================================================ FILE: malachite-float/tests/exhaustive/exhaustive_positive_floats_with_sci_exponent_and_precision.rs ================================================ // Copyright © 2026 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 malachite_float::exhaustive::exhaustive_positive_floats_with_sci_exponent_and_precision; use malachite_float::test_util::exhaustive::exhaustive_floats_helper_helper_with_limit; use std::panic::catch_unwind; fn exhaustive_positive_floats_with_sci_exponent_and_precision_helper( sci_exponent: i32, prec: u64, out: &[&str], out_hex: &[&str], ) { exhaustive_floats_helper_helper_with_limit( 20, exhaustive_positive_floats_with_sci_exponent_and_precision(sci_exponent, prec), out, out_hex, ); } #[test] fn test_exhaustive_positive_floats_with_sci_exponent_and_precision() { exhaustive_positive_floats_with_sci_exponent_and_precision_helper(0, 1, &["1.0"], &["0x1.0#1"]); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 0, 2, &["1.0", "1.5"], &["0x1.0#2", "0x1.8#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 0, 3, &["1.0", "1.2", "1.5", "1.8"], &["0x1.0#3", "0x1.4#3", "0x1.8#3", "0x1.c#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 0, 4, &["1.0", "1.1", "1.2", "1.4", "1.5", "1.6", "1.8", "1.9"], &["0x1.0#4", "0x1.2#4", "0x1.4#4", "0x1.6#4", "0x1.8#4", "0x1.a#4", "0x1.c#4", "0x1.e#4"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 0, 5, &[ "1.0", "1.06", "1.12", "1.19", "1.25", "1.3", "1.38", "1.44", "1.5", "1.56", "1.62", "1.7", "1.75", "1.81", "1.88", "1.94", ], &[ "0x1.0#5", "0x1.1#5", "0x1.2#5", "0x1.3#5", "0x1.4#5", "0x1.5#5", "0x1.6#5", "0x1.7#5", "0x1.8#5", "0x1.9#5", "0x1.a#5", "0x1.b#5", "0x1.c#5", "0x1.d#5", "0x1.e#5", "0x1.f#5", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper(1, 1, &["2.0"], &["0x2.0#1"]); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 1, 2, &["2.0", "3.0"], &["0x2.0#2", "0x3.0#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 1, 3, &["2.0", "2.5", "3.0", "3.5"], &["0x2.0#3", "0x2.8#3", "0x3.0#3", "0x3.8#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 1, 4, &["2.0", "2.2", "2.5", "2.8", "3.0", "3.2", "3.5", "3.8"], &["0x2.0#4", "0x2.4#4", "0x2.8#4", "0x2.c#4", "0x3.0#4", "0x3.4#4", "0x3.8#4", "0x3.c#4"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 1, 5, &[ "2.0", "2.1", "2.2", "2.4", "2.5", "2.6", "2.8", "2.9", "3.0", "3.1", "3.2", "3.4", "3.5", "3.6", "3.8", "3.9", ], &[ "0x2.0#5", "0x2.2#5", "0x2.4#5", "0x2.6#5", "0x2.8#5", "0x2.a#5", "0x2.c#5", "0x2.e#5", "0x3.0#5", "0x3.2#5", "0x3.4#5", "0x3.6#5", "0x3.8#5", "0x3.a#5", "0x3.c#5", "0x3.e#5", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 4, 1, &["2.0e1"], &["0x1.0E+1#1"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 4, 2, &["16.0", "24.0"], &["0x10.0#2", "0x18.0#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 4, 3, &["16.0", "20.0", "24.0", "28.0"], &["0x10.0#3", "0x14.0#3", "0x18.0#3", "0x1c.0#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 4, 4, &["16.0", "18.0", "20.0", "22.0", "24.0", "26.0", "28.0", "30.0"], &[ "0x10.0#4", "0x12.0#4", "0x14.0#4", "0x16.0#4", "0x18.0#4", "0x1a.0#4", "0x1c.0#4", "0x1e.0#4", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 4, 5, &[ "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0", "25.0", "26.0", "27.0", "28.0", "29.0", "30.0", "31.0", ], &[ "0x10.0#5", "0x11.0#5", "0x12.0#5", "0x13.0#5", "0x14.0#5", "0x15.0#5", "0x16.0#5", "0x17.0#5", "0x18.0#5", "0x19.0#5", "0x1a.0#5", "0x1b.0#5", "0x1c.0#5", "0x1d.0#5", "0x1e.0#5", "0x1f.0#5", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 1, &["1.0e30"], &["0x1.0E+25#1"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 2, &["1.0e30", "2.0e30"], &["0x1.0E+25#2", "0x1.8E+25#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 3, &["1.3e30", "1.6e30", "1.9e30", "2.2e30"], &["0x1.0E+25#3", "0x1.4E+25#3", "0x1.8E+25#3", "0x1.cE+25#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 4, &["1.3e30", "1.4e30", "1.6e30", "1.7e30", "1.9e30", "2.1e30", "2.2e30", "2.4e30"], &[ "0x1.0E+25#4", "0x1.2E+25#4", "0x1.4E+25#4", "0x1.6E+25#4", "0x1.8E+25#4", "0x1.aE+25#4", "0x1.cE+25#4", "0x1.eE+25#4", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 5, &[ "1.27e30", "1.35e30", "1.4e30", "1.5e30", "1.6e30", "1.66e30", "1.74e30", "1.8e30", "1.9e30", "2.0e30", "2.06e30", "2.14e30", "2.2e30", "2.3e30", "2.4e30", "2.46e30", ], &[ "0x1.0E+25#5", "0x1.1E+25#5", "0x1.2E+25#5", "0x1.3E+25#5", "0x1.4E+25#5", "0x1.5E+25#5", "0x1.6E+25#5", "0x1.7E+25#5", "0x1.8E+25#5", "0x1.9E+25#5", "0x1.aE+25#5", "0x1.bE+25#5", "0x1.cE+25#5", "0x1.dE+25#5", "0x1.eE+25#5", "0x1.fE+25#5", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( 100, 30, &[ "1.2676506e30", "1.267650603e30", "1.267650605e30", "1.267650607e30", "1.26765061e30", "1.267650612e30", "1.267650614e30", "1.267650617e30", "1.267650619e30", "1.267650621e30", "1.267650624e30", "1.267650626e30", "1.267650629e30", "1.267650631e30", "1.267650633e30", "1.267650636e30", "1.267650638e30", "1.26765064e30", "1.267650643e30", "1.267650645e30", ], &[ "0x1.00000000E+25#30", "0x1.00000008E+25#30", "0x1.00000010E+25#30", "0x1.00000018E+25#30", "0x1.00000020E+25#30", "0x1.00000028E+25#30", "0x1.00000030E+25#30", "0x1.00000038E+25#30", "0x1.00000040E+25#30", "0x1.00000048E+25#30", "0x1.00000050E+25#30", "0x1.00000058E+25#30", "0x1.00000060E+25#30", "0x1.00000068E+25#30", "0x1.00000070E+25#30", "0x1.00000078E+25#30", "0x1.00000080E+25#30", "0x1.00000088E+25#30", "0x1.00000090E+25#30", "0x1.00000098E+25#30", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -1, 1, &["0.5"], &["0x0.8#1"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -1, 2, &["0.5", "0.8"], &["0x0.8#2", "0x0.c#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -1, 3, &["0.5", "0.6", "0.8", "0.9"], &["0x0.8#3", "0x0.a#3", "0x0.c#3", "0x0.e#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -1, 4, &["0.5", "0.56", "0.62", "0.7", "0.75", "0.81", "0.88", "0.94"], &["0x0.8#4", "0x0.9#4", "0x0.a#4", "0x0.b#4", "0x0.c#4", "0x0.d#4", "0x0.e#4", "0x0.f#4"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -1, 5, &[ "0.5", "0.53", "0.56", "0.59", "0.62", "0.66", "0.69", "0.72", "0.75", "0.78", "0.81", "0.84", "0.88", "0.91", "0.94", "0.97", ], &[ "0x0.80#5", "0x0.88#5", "0x0.90#5", "0x0.98#5", "0x0.a0#5", "0x0.a8#5", "0x0.b0#5", "0x0.b8#5", "0x0.c0#5", "0x0.c8#5", "0x0.d0#5", "0x0.d8#5", "0x0.e0#5", "0x0.e8#5", "0x0.f0#5", "0x0.f8#5", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -10, 1, &["0.001"], &["0x0.004#1"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -10, 2, &["0.00098", "0.0015"], &["0x0.004#2", "0x0.006#2"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -10, 3, &["0.00098", "0.0012", "0.0015", "0.0017"], &["0x0.004#3", "0x0.005#3", "0x0.006#3", "0x0.007#3"], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -10, 4, &["0.00098", "0.0011", "0.0012", "0.0013", "0.0015", "0.0016", "0.0017", "0.0018"], &[ "0x0.0040#4", "0x0.0048#4", "0x0.0050#4", "0x0.0058#4", "0x0.0060#4", "0x0.0068#4", "0x0.0070#4", "0x0.0078#4", ], ); exhaustive_positive_floats_with_sci_exponent_and_precision_helper( -10, 5, &[ "0.00098", "0.001", "0.0011", "0.00116", "0.00122", "0.00128", "0.00134", "0.0014", "0.00146", "0.00153", "0.00159", "0.00165", "0.0017", "0.00177", "0.00183", "0.0019", ], &[ "0x0.0040#5", "0x0.0044#5", "0x0.0048#5", "0x0.004c#5", "0x0.0050#5", "0x0.0054#5", "0x0.0058#5", "0x0.005c#5", "0x0.0060#5", "0x0.0064#5", "0x0.0068#5", "0x0.006c#5", "0x0.0070#5", "0x0.0074#5", "0x0.0078#5", "0x0.007c#5", ], ); } #[test] fn exhaustive_positive_floats_with_sci_exponent_and_precision_fail() { assert_panic!(exhaustive_positive_floats_with_sci_exponent_and_precision( 1, 0 )); } ================================================ FILE: malachite-float/tests/lib.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::bool_assert_comparison, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::excessive_precision, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::float_cmp, clippy::type_complexity, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::option_if_let_else, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::borrow_as_ptr, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns )] #[macro_use] extern crate malachite_base; pub mod arithmetic { pub mod abs; pub mod add; pub mod agm; pub mod div; pub mod is_power_of_2; pub mod ln; pub mod mul; pub mod neg; pub mod power_of_2; pub mod reciprocal; pub mod reciprocal_sqrt; pub mod shl; pub mod shl_round; pub mod shr; pub mod shr_round; pub mod sign; pub mod sqrt; pub mod square; pub mod sub; } pub mod basic { pub mod classification; pub mod complexity; pub mod constants; pub mod get_and_set; pub mod named; pub mod overflow_and_underflow; pub mod size; pub mod ulp; } pub mod comparison { pub mod cmp; pub mod cmp_abs; pub mod eq; pub mod eq_abs; pub mod eq_abs_integer; pub mod eq_abs_natural; pub mod eq_abs_primitive_float; pub mod eq_abs_primitive_int; pub mod eq_abs_rational; pub mod hash; pub mod partial_cmp_abs_integer; pub mod partial_cmp_abs_natural; pub mod partial_cmp_abs_primitive_float; pub mod partial_cmp_abs_primitive_int; pub mod partial_cmp_abs_rational; pub mod partial_cmp_integer; pub mod partial_cmp_natural; pub mod partial_cmp_primitive_float; pub mod partial_cmp_primitive_int; pub mod partial_cmp_rational; pub mod partial_eq_integer; pub mod partial_eq_natural; pub mod partial_eq_primitive_float; pub mod partial_eq_primitive_int; pub mod partial_eq_rational; } pub mod constants { pub mod gauss_constant; pub mod lemniscate_constant; pub mod ln_2; pub mod log_2_e; pub mod one_over_pi; pub mod one_over_sqrt_pi; pub mod one_over_sqrt_tau; pub mod phi; pub mod pi; pub mod pi_over_2; pub mod pi_over_3; pub mod pi_over_4; pub mod pi_over_6; pub mod pi_over_8; pub mod prime_constant; pub mod prouhet_thue_morse_constant; pub mod sqrt_2; pub mod sqrt_2_over_2; pub mod sqrt_3; pub mod sqrt_3_over_3; pub mod sqrt_pi; pub mod tau; pub mod two_over_pi; pub mod two_over_sqrt_pi; } pub mod conversion { pub mod clone; pub mod from_integer; pub mod from_natural; pub mod from_primitive_float; pub mod from_primitive_int; pub mod from_rational; pub mod integer_from_float; pub mod is_integer; pub mod mantissa_and_exponent; pub mod natural_from_float; pub mod primitive_float_from_float; pub mod primitive_int_from_float; pub mod rational_from_float; } pub mod exhaustive { pub mod exhaustive_finite_floats; pub mod exhaustive_floats; pub mod exhaustive_negative_finite_floats; pub mod exhaustive_non_negative_finite_floats; pub mod exhaustive_non_positive_finite_floats; pub mod exhaustive_nonzero_finite_floats; pub mod exhaustive_positive_finite_floats; pub mod exhaustive_positive_floats_with_sci_exponent; pub mod exhaustive_positive_floats_with_sci_exponent_and_precision; } pub mod random { pub mod random_finite_floats; pub mod random_floats; pub mod random_negative_finite_floats; pub mod random_non_negative_finite_floats; pub mod random_non_positive_finite_floats; pub mod random_nonzero_finite_floats; pub mod random_positive_finite_floats; pub mod striped_random_negative_finite_floats; pub mod striped_random_non_negative_finite_floats; pub mod striped_random_non_positive_finite_floats; pub mod striped_random_nonzero_finite_floats; pub mod striped_random_positive_finite_floats; } ================================================ FILE: malachite-float/tests/random/random_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_finite_floats() { // mean |sci_exponent| 1, mean precision 2, special probability 1/10 let values = &[ "-3.0", "-1.0", "-2.0", "1.12", "-1.0", "1.5", "-2.0", "-0.3", "-1.0", "0.8", "0.0", "0.338", "-1.2", "-0.59", "8.0", "-6.0", "-3.0", "-0.2", "-0.8", "-0.5", ]; let values_hex = &[ "-0x3.0#3", "-0x1.0#3", "-0x2.0#2", "0x1.2#5", "-0x1.0#2", "0x1.8#3", "-0x2.0#1", "-0x0.5#3", "-0x1.0#1", "0x0.c#2", "0x0.0", "0x0.568#9", "-0x1.4#3", "-0x0.98#5", "0x8.0#1", "-0x6.0#2", "-0x3.0#2", "-0x0.4#1", "-0x0.c#2", "-0x0.8#2", ]; let common_values = &[ ("1.0", 75012), ("-1.0", 74560), ("0.0", 49991), ("-0.0", 49908), ("0.5", 37822), ("2.0", 37501), ("-0.5", 37342), ("-2.0", 37246), ("-0.2", 18908), ("-1.0", 18873), ]; let common_values_hex = &[ ("0x1.0#1", 75012), ("-0x1.0#1", 74560), ("0x0.0", 49991), ("-0x0.0", 49908), ("0x0.8#1", 37822), ("0x2.0#1", 37501), ("-0x0.8#1", 37342), ("-0x2.0#1", 37246), ("-0x0.4#1", 18908), ("-0x1.0#2", 18873), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.7164152871702301), standard_deviation: NiceFloat(1678.2398853586644), skewness: NiceFloat(-81.29182513358477), excess_kurtosis: NiceFloat(334895.7379317797), }; random_finite_floats_helper( 1, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, special probability 1/10 let values = &[ "-2.55291108846570214097387565888051871482698844535", "-1.42916620847224432", "-2.8", "1.627895434494957473077687019296248257966273", "-1.7636659376", "1.0673947", "-2.56646360702751047", "-0.26139226673975317791585341", "-1.1299945035408183423314884117645901537", "0.85631649", "0.0", "0.38895408170042664025227", "-1.12207115063093089756992765", "-0.934062407041679788538190170179503", "11.30718", "-5.0", "-3.2134957439331342", "-0.35078847666770333344764253961", "-0.8696", "-0.61703047474", ]; let values_hex = &[ "-0x2.8d8b94c28e52f82d1e50104590476568ffae14e#158", "-0x1.6dddd62defc582#57", "-0x2.c#5", "0x1.a0bdc15476ab627f1b98bc51ab2497603df6#145", "-0x1.c37f9c630#34", "0x1.1140c8#22", "-0x2.9103c24a8eaeb4#57", "-0x0.42ea9a8513159b517a2ee8#84", "-0x1.214751dd5e1921c008153fce88b687c#123", "0x0.db378ec#26", "0x0.0", "0x0.63927ea48c8e2dfcdd8#75", "-0x1.1f400e0fbeb4413f6af44#85", "-0x0.ef1eb6c2aac41a798ac240288da#107", "0xb.4ea38#21", "-0x5.0#4", "-0x3.36a7a836072b20#55", "-0x0.59cd460b19f84a9b4a9886c4#94", "-0x0.dea0#13", "-0x0.9df5b58da#36", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("1.0", 2360), ("-1.0", 2302), ("2.0", 1209), ("-1.0", 1197), ("-0.5", 1177), ("1.0", 1168), ("0.5", 1158), ("-2.0", 1158), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("0x1.0#1", 2360), ("-0x1.0#1", 2302), ("0x2.0#1", 1209), ("-0x1.0#2", 1197), ("-0x0.8#1", 1177), ("0x1.0#2", 1168), ("0x0.8#1", 1158), ("-0x2.0#1", 1158), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.6054865970994369), standard_deviation: NiceFloat(1644.9473368833571), skewness: NiceFloat(-6.939646339338025), excess_kurtosis: NiceFloat(322737.3533747247), }; random_finite_floats_helper( 1, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, special probability 1/10 let values = &[ "-5.0e13", "-2.2e-16", "-0.5", "3.0e8", "-9.5e-7", "0.38", "-1.0e-11", "-7.0e-17", "-3.0e10", "1.7e-13", "0.0", "3.99e20", "-1.6e-29", "-4.7e28", "1.0e-8", "-2.5e-21", "-1.0e10", "-1.0e43", "-0.19", "-0.1", ]; let values_hex = &[ "-0x3.0E+11#3", "-0x1.0E-13#3", "-0x0.8#2", "0x1.2E+7#5", "-0x0.000010#2", "0x0.6#3", "-0x1.0E-9#1", "-0x5.0E-14#3", "-0x8.0E+8#1", "0x3.0E-11#2", "0x0.0", "0x1.5aE+17#9", "-0x1.4E-24#3", "-0x9.8E+23#5", "0x4.0E-7#1", "-0xc.0E-18#2", "-0x3.0E+8#2", "-0x8.0E+35#1", "-0x0.3#2", "-0x0.2#2", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("1.0", 1791), ("0.5", 1788), ("-1.0", 1782), ("-4.0", 1778), ("-0.5", 1727), ("2.0", 1695), ("4.0", 1690), ("2.0e1", 1689), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("0x1.0#1", 1791), ("0x0.8#1", 1788), ("-0x1.0#1", 1782), ("-0x4.0#1", 1778), ("-0x0.8#1", 1727), ("0x2.0#1", 1695), ("0x4.0#1", 1690), ("0x1.0E+1#1", 1689), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.7899297879002272e243), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_finite_floats_helper( 64, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, special probability 1/10 let values = &[ "-44911286823141.1855899032680253942982725544577883", "-3.17338646132424422e-16", "-0.69", "436984853.27897203898621663845006920021638213", "-1.6819629074e-6", "0.2668487", "-1.86734804230764746e-11", "-5.8040742598686895873572801e-17", "-38826315498.940567851125400956255170888", "1.94703828e-13", "0.0", "459195929699359096631.38", "-1.41625290177455750344133296e-29", "-74004048183563132066750152744.5532", "2.106127e-8", "-2.1e-21", "-13801859126.0280018", "-1.5645688873494313277150105805e43", "-0.21741", "-0.154257618684", ]; let values_hex = &[ "-0x28d8b94c28e5.2f82d1e50104590476568ffae14e#158", "-0x1.6dddd62defc582E-13#57", "-0x0.b0#5", "0x1a0bdc15.476ab627f1b98bc51ab2497603df6#145", "-0x0.00001c37f9c630#34", "0x0.445032#22", "-0x1.4881e12547575aE-9#57", "-0x4.2ea9a8513159b517a2ee8E-14#84", "-0x90a3a8eea.f0c90e0040a9fe7445b43e#123", "0x3.6cde3bE-11#26", "0x0.0", "0x18e49fa923238b7f37.60#75", "-0x1.1f400e0fbeb4413f6af44E-24#85", "-0xef1eb6c2aac41a798ac24028.8da#107", "0x5.a751cE-7#21", "-0xa.0E-18#4", "-0x336a7a836.072b20#55", "-0xb.39a8c1633f0953695310d88E+35#94", "-0x0.37a8#13", "-0x0.277d6d6368#36", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("-2.0e1", 77), ("2.0", 66), ("-2.0", 61), ("-8.0", 61), ("-3.0e1", 59), ("-0.2", 58), ("0.5", 57), ("4.0e3", 57), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("-0x1.0E+1#1", 77), ("0x2.0#1", 66), ("-0x2.0#1", 61), ("-0x8.0#1", 61), ("-0x2.0E+1#1", 59), ("-0x0.4#1", 58), ("0x0.8#1", 57), ("0x1.0E+3#1", 57), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.2330178132397616e243), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_finite_floats_helper( 64, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_finite_floats_fail_1() { random_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn random_finite_floats_fail_2() { random_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn random_finite_floats_fail_3() { random_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn random_finite_floats_fail_4() { random_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn random_finite_floats_fail_5() { random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn random_finite_floats_fail_6() { random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1); } ================================================ FILE: malachite-float/tests/random/random_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_floats() { // mean |sci_exponent| 1, mean precision 2, zero probability 1/10 let values = &[ "1.0", "0.2", "0.0", "NaN", "-0.2", "-1.0", "-1.0", "-1.5", "2.0", "0.2", "-1.0", "-0.2", "-2.0", "Infinity", "-0.5", "-1.0", "-0.4", "NaN", "0.5", "-0.0", ]; let values_hex = &[ "0x1.0#1", "0x0.4#1", "0x0.0", "NaN", "-0x0.4#1", "-0x1.0#2", "-0x1.0#1", "-0x1.8#2", "0x2.0#1", "0x0.4#1", "-0x1.0#3", "-0x0.4#2", "-0x2.0#1", "Infinity", "-0x0.8#1", "-0x1.0#2", "-0x0.6#2", "NaN", "0x0.8#1", "-0x0.0", ]; let common_values = &[ ("-1.0", 67626), ("1.0", 67293), ("0.0", 45033), ("-0.0", 44760), ("-2.0", 33918), ("2.0", 33760), ("0.5", 33658), ("Infinity", 33640), ("-0.5", 33629), ("NaN", 33393), ]; let common_values_hex = &[ ("-0x1.0#1", 67626), ("0x1.0#1", 67293), ("0x0.0", 45033), ("-0x0.0", 44760), ("-0x2.0#1", 33918), ("0x2.0#1", 33760), ("0x0.8#1", 33658), ("Infinity", 33640), ("-0x0.8#1", 33629), ("NaN", 33393), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_floats_helper( 1, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, zero probability 1/10 let values = &[ "1.60469", "0.3689021918822", "0.0", "NaN", "-0.28085087121796634898241172643", "-1.753651001", "-1.76635021435647835233096910201935186533898089", "-1.43252385721349903405196303338780402302813416810241256872117258", "2.0", "0.250602502656981020491543289450999271", "-1.8960717298288877935", "-0.25858", "-2.6358228847359354842130018065396119276102632191023", "Infinity", "-0.9541023510530255", "-1.5", "-0.464323", "NaN", "0.725643469742899", "-0.0", ]; let values_hex = &[ "0x1.9acd0#18", "0x0.5e705fc18e8#40", "0x0.0", "NaN", "-0x0.47e5d7baef2c868cbb8316be#95", "-0x1.c0ef45a0#30", "-0x1.c42f8713f193fa44085ebdae1b4419f73e3d8#146", "-0x1.6eb9e22d78c4bde3d56b1e7932a0b849250a5abf6d02e887830#205", "0x2.00#7", "0x0.40277c51351dd7528f4d46d26a8156#118", "-0x1.e564f4f67c376d50#62", "-0x0.4232#14", "-0x2.a2c549dffd3d8e02dee8e02a95b00cb3a36c841e#162", "Infinity", "-0x0.f4400d3acf388#51", "-0x1.8#2", "-0x0.76dde0#20", "NaN", "0x0.b9c3c53b1a0a#48", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("1.0", 2133), ("-1.0", 2122), ("-2.0", 1103), ("0.5", 1094), ("1.5", 1091), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x1.0#1", 2133), ("-0x1.0#1", 2122), ("-0x2.0#1", 1103), ("0x0.8#1", 1094), ("0x1.8#2", 1091), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_floats_helper( 1, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, zero probability 1/10 let values = &[ "5.0e11", "7.0e122", "0.0", "NaN", "-2.0e25", "-2.0e21", "-2.0e-9", "-4.0e33", "4.0e-9", "5.0e2", "-4.0e-16", "-7.0e-18", "-2.0e-19", "Infinity", "-2.0e50", "-1.0e12", "-3.0e-28", "NaN", "0.02", "-0.0", ]; let values_hex = &[ "0x8.0E+9#1", "0x1.0E+102#1", "0x0.0", "NaN", "-0x1.0E+21#1", "-0x8.0E+17#2", "-0x8.0E-8#1", "-0xc.0E+27#2", "0x1.0E-7#1", "0x2.0E+2#1", "-0x2.0E-13#3", "-0x8.0E-15#2", "-0x4.0E-16#1", "Infinity", "-0x8.0E+41#1", "-0x1.0E+10#2", "-0x1.8E-23#2", "NaN", "0x0.04#1", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0.5", 1583), ("-1.0", 1560), ("2.0", 1542), ("-2.0", 1523), ("1.0", 1518), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x0.8#1", 1583), ("-0x1.0#1", 1560), ("0x2.0#1", 1542), ("-0x2.0#1", 1523), ("0x1.0#1", 1518), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_floats_helper( 64, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, zero probability 1/10 let values = &[ "8.82188e11", "9.75459983374e122", "0.0", "NaN", "-21729783659306408649613509.686", "-4.140691354e21", "-3.29008365861415556134836580980448399733562188e-9", "-3719044561792922503530448846362960.3599330496921301151502834994", "3.73e-9", "513.233925441497129966680656795646506", "-8.420249963187521806e-16", "-7.177e-18", "-2.8577648979177105962332201291018926848163080599637e-19", "Infinity", "-3.569720699507868e50", "-1.6e12", "-3.750772e-28", "NaN", "0.0226763584294656", "-0.0", ]; let values_hex = &[ "0xc.d668E+9#18", "0x1.79c17f063aE+102#40", "0x0.0", "NaN", "-0x11f975eebbcb21a32ee0c5.af8#95", "-0xe.077a2d0E+17#30", "-0xe.217c389f8c9fd22042f5ed70da20cfb9f1ecE-8#146", "-0xb75cf116bc625ef1eab58f3c9950.5c2492852d5fb6817443c180#205", "0x1.00E-7#7", "0x201.3be289a8eeba947a6a3693540ab#118", "-0x3.cac9e9ecf86edaaE-13#62", "-0x8.464E-15#14", "-0x5.458a93bffa7b1c05bdd1c0552b60196746d9083cE-16#162", "Infinity", "-0xf.4400d3acf388E+41#51", "-0x1.8E+10#2", "-0x1.db778E-23#20", "NaN", "0x0.05ce1e29d8d050#48", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0.00003", 60), ("-0.5", 57), ("-6.0e1", 56), ("-5.0e2", 55), ("8.0", 54), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x0.0002#1", 60), ("-0x0.8#1", 57), ("-0x4.0E+1#1", 56), ("-0x2.0E+2#1", 55), ("0x8.0#1", 54), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_floats_helper( 64, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_floats_fail_1() { random_floats(EXAMPLE_SEED, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn random_floats_fail_2() { random_floats(EXAMPLE_SEED, 0, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn random_floats_fail_3() { random_floats(EXAMPLE_SEED, 1, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn random_floats_fail_4() { random_floats(EXAMPLE_SEED, 1, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn random_floats_fail_5() { random_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn random_floats_fail_6() { random_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1); } ================================================ FILE: malachite-float/tests/random/random_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_negative_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_negative_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_negative_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_negative_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "-1.5", "-1.0", "-2.0", "-1.0", "-1.0", "-2.0", "-2.0", "-1.2", "-2.0", "-1.0", "-2.0", "-2.0", "-4.0", "-1.0", "-1.8", "-2.5", "-0.1", "-1.0", "-0.2", "-1.2", ]; let values_hex = &[ "-0x1.8#2", "-0x1.0#1", "-0x2.0#2", "-0x1.0#2", "-0x1.0#1", "-0x2.0#1", "-0x2.0#1", "-0x1.4#3", "-0x2.0#1", "-0x1.0#1", "-0x2.0#1", "-0x2.0#1", "-0x4.0#1", "-0x1.0#1", "-0x1.c#3", "-0x2.8#4", "-0x0.2#1", "-0x1.0#1", "-0x0.4#1", "-0x1.4#3", ]; let common_values = &[ ("-1.0", 166114), ("-0.5", 83464), ("-2.0", 83434), ("-1.5", 42025), ("-0.2", 41531), ("-1.0", 41506), ("-4.0", 41483), ("-3.0", 21005), ("-2.0", 20892), ("-0.1", 20888), ]; let common_values_hex = &[ ("-0x1.0#1", 166114), ("-0x0.8#1", 83464), ("-0x2.0#1", 83434), ("-0x1.8#2", 42025), ("-0x0.4#1", 41531), ("-0x1.0#2", 41506), ("-0x4.0#1", 41483), ("-0x3.0#2", 21005), ("-0x2.0#2", 20892), ("-0x0.2#1", 20888), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.292847587427611), standard_deviation: NiceFloat(416.97010060005687), skewness: NiceFloat(-334.72226371600976), excess_kurtosis: NiceFloat(139648.08254659182), }; random_negative_finite_floats_helper( 1, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "-1.8", "-1.3850071337780625300836", "-3.21176241813", "-1.981013494834061409257349", "-1.665272", "-3.0477509378551710980549069671536911164880571509", "-3.86646429082638580413691355062141611967080168780483321308586", "-1.1383718", "-3.005438259332186398250782844", "-1.31402772840010613", "-2.2954821356993", "-3.341070237", "-6.42834377982969296", "-1.055708800484474", "-1.09154149257425903017951075071293557661092806", "-2.750421277483313", "-0.2219335998", "-1.1563594283786540769774526007723931560664", "-0.39596234107597", "-1.3496675", ]; let values_hex = &[ "-0x1.c#3", "-0x1.628fd3d84db091d430#71", "-0x3.36360fd46#38", "-0x1.fb23b34d3f38af725038#79", "-0x1.aa4f4#19", "-0x3.0c3967cc70f8444c90df6c12283a15fa4637da#153", "-0x3.ddd09a90404c02ee3c715fa17bf84c143354d47adb8aff3c0#195", "-0x1.236c56#24", "-0x3.016466d9fa99ac91c2dfb4#89", "-0x1.50641f07840015#57", "-0x2.4ba4b79d6178#48", "-0x3.57506108#31", "-0x6.6da7f01dd04530#57", "-0x1.0e42ee942e22#48", "-0x1.176f4364d55e3feb51571e25ef39e528b86a#145", "-0x2.c01b9bdd036c4#54", "-0x0.38d0a3f10#31", "-0x1.28072be74ebd242348b5852a9e4a3c62e#132", "-0x0.655dc9b95e7#43", "-0x1.5983d0#24", ]; let common_values = &[ ("-1.0", 5069), ("-1.0", 2626), ("-0.5", 2623), ("-2.0", 2623), ("-1.5", 2488), ("-2.0", 1309), ("-0.2", 1301), ("-4.0", 1299), ("-1.2", 1293), ("-0.8", 1283), ]; let common_values_hex = &[ ("-0x1.0#1", 5069), ("-0x1.0#2", 2626), ("-0x0.8#1", 2623), ("-0x2.0#1", 2623), ("-0x1.8#2", 2488), ("-0x2.0#2", 1309), ("-0x0.4#1", 1301), ("-0x4.0#1", 1299), ("-0x1.4#3", 1293), ("-0x0.c#2", 1283), ]; let sample_median = ( "-1.492048772960956", Some("-1.492046225515012964994532213857812720544842101177086840260174"), ); let sample_median_hex = ( "-0x1.7df6e88be77c#49", Some("-0x1.7df6bdceb50c76e2fdee90d7296fa9b4a2cc3ae315ce8cf010#199"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-9.138627718915657), standard_deviation: NiceFloat(468.606797626186), skewness: NiceFloat(-309.74563573271297), excess_kurtosis: NiceFloat(127224.11304735676), }; random_negative_finite_floats_helper( 1, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "-3.0e-37", "-8.0e-34", "-4.0e-6", "-3.0e-45", "-2.0e15", "-5.0e-10", "-2.0e4", "-0.08", "-0.0001", "-1.0e14", "-2.0e34", "-9.0e-13", "-0.0001", "-9.0e9", "-2.3e33", "-0.16", "-0.00003", "-5.0e18", "-0.06", "-7.0e8", ]; let values_hex = &[ "-0x6.0E-31#2", "-0x4.0E-28#1", "-0x0.00004#2", "-0x1.0E-37#2", "-0x8.0E+12#1", "-0x2.0E-8#1", "-0x4.0E+3#1", "-0x0.14#3", "-0x0.0008#1", "-0x8.0E+11#1", "-0x4.0E+28#1", "-0x1.0E-10#1", "-0x0.0008#1", "-0x2.0E+8#1", "-0x7.0E+27#3", "-0x0.28#4", "-0x0.0002#1", "-0x4.0E+15#1", "-0x0.1#1", "-0x2.8E+7#3", ]; let common_values = &[ ("-1.0", 3831), ("-0.2", 3830), ("-0.5", 3826), ("-2.0", 3753), ("-4.0", 3716), ("-8.0", 3653), ("-0.1", 3639), ("-0.06", 3637), ("-3.0e1", 3632), ("-2.0e1", 3617), ]; let common_values_hex = &[ ("-0x1.0#1", 3831), ("-0x0.4#1", 3830), ("-0x0.8#1", 3826), ("-0x2.0#1", 3753), ("-0x4.0#1", 3716), ("-0x8.0#1", 3653), ("-0x0.2#1", 3639), ("-0x0.1#1", 3637), ("-0x2.0E+1#1", 3632), ("-0x1.0E+1#1", 3617), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.9680504915704222e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_finite_floats_helper( 64, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "-3.3e-37", "-1.066970684853243558372e-33", "-6.12595065713e-6", "-5.55198233623541837705276e-45", "-3.74986e15", "-7.096098125575043023691761696603361322749539164e-10", "-31674.0754704497525074895958066906408523432074264971936815994", "-0.07114824", "-0.0001834373937580680174713612576", "-184932962124288.041", "-2.38376493640286e34", "-1.519342839e-12", "-0.000196177483515310454", "-9068469544.36041", "-1416901865713435510498832543218638.47378814837", "-0.17190132984270706", "-0.00005418300776", "-5332766608130525448.821004944540229640534", "-0.09899058526899", "-7.2459725e8", ]; let values_hex = &[ "-0x7.0E-31#3", "-0x5.8a3f4f6136c24750cE-28#71", "-0x0.000066c6c1fa8c#38", "-0x1.fb23b34d3f38af725038E-37#79", "-0xd.527aE+12#19", "-0x3.0c3967cc70f8444c90df6c12283a15fa4637daE-8#153", "-0x7bba.13520809805dc78e2bf42f7f0982866a9a8f5b715fe78#195", "-0x0.1236c56#24", "-0x0.000c05919b67ea66b2470b7ed0#89", "-0xa8320f83c200.0a8#57", "-0x4.97496f3ac2f0E+28#48", "-0x1.aba83084E-10#31", "-0x0.000cdb4fe03ba08a60#57", "-0x21c85dd28.5c44#48", "-0x45dbd0d935578ffad455c7897bce.794a2e1a8#145", "-0x0.2c01b9bdd036c4#54", "-0x0.00038d0a3f10#31", "-0x4a01caf9d3af4908.d22d614aa7928f18b8#132", "-0x0.1957726e579c#43", "-0x2.b307a0E+7#24", ]; let common_values = &[ ("-2.0", 130), ("-2.0e1", 129), ("-0.2", 122), ("-3.0e1", 117), ("-0.004", 116), ("-1.0e5", 114), ("-0.02", 112), ("-0.00002", 112), ("-0.1", 109), ("-8.0", 108), ]; let common_values_hex = &[ ("-0x2.0#1", 130), ("-0x1.0E+1#1", 129), ("-0x0.4#1", 122), ("-0x2.0E+1#1", 117), ("-0x0.01#1", 116), ("-0x2.0E+4#1", 114), ("-0x0.04#1", 112), ("-0x0.0001#1", 112), ("-0x0.2#1", 109), ("-0x8.0#1", 108), ]; let sample_median = ( "-1.4527665236460671657422963814630798553398772791", Some("-1.45263"), ); let sample_median_hex = ( "-0x1.73e881c3c8916f41f0bcfa9b4958a2e850b2da0#154", Some("-0x1.73df8#18"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.9911135832684696e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_finite_floats_helper( 64, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_negative_finite_floats_fail_1() { random_negative_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1); } #[test] #[should_panic] fn random_negative_finite_floats_fail_2() { random_negative_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1); } #[test] #[should_panic] fn random_negative_finite_floats_fail_3() { random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0); } #[test] #[should_panic] fn random_negative_finite_floats_fail_4() { random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1); } ================================================ FILE: malachite-float/tests/random/random_non_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_non_negative_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_non_negative_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_non_negative_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_non_negative_finite_floats() { // mean |sci_exponent| 1, mean precision 2, zero probability 1/10 let values = &[ "8.0", "1.0", "0.8", "0.0", "4.0", "2.0", "1.0", "2.0", "0.8", "0.9536", "2.0", "3.0e1", "0.5", "0.0", "1.0", "2.0", "0.5", "0.0", "1.5", "0.1", ]; let values_hex = &[ "0x8.0#1", "0x1.0#1", "0x0.c#2", "0x0.0", "0x4.0#1", "0x2.0#3", "0x1.0#1", "0x2.0#1", "0x0.c#2", "0x0.f42#12", "0x2.0#1", "0x2.0E+1#1", "0x0.8#1", "0x0.0", "0x1.0#1", "0x2.0#2", "0x0.8#1", "0x0.0", "0x1.8#2", "0x0.2#1", ]; let common_values = &[ ("1.0", 149586), ("0.0", 100224), ("2.0", 74929), ("0.5", 74827), ("1.0", 37902), ("4.0", 37612), ("0.2", 37602), ("1.5", 37600), ("0.5", 18934), ("0.8", 18834), ]; let common_values_hex = &[ ("0x1.0#1", 149586), ("0x0.0", 100224), ("0x2.0#1", 74929), ("0x0.8#1", 74827), ("0x1.0#2", 37902), ("0x4.0#1", 37612), ("0x0.4#1", 37602), ("0x1.8#2", 37600), ("0x0.8#2", 18934), ("0x0.c#2", 18834), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.693371936934735), standard_deviation: NiceFloat(1671.7840625385452), skewness: NiceFloat(718.2460436055444), excess_kurtosis: NiceFloat(578520.0792964109), }; random_non_negative_finite_floats_helper( 1, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, zero probability 1/10 let values = &[ "8.288616155488807101232282300740634937242230275473095947256061292584667312127693953525219\ 033439102", "1.0", "0.6651592248", "0.0", "4.2345242873846765390825841", "2.38320785690539951782446111823006788535", "1.036853813", "2.4027026671793265640566992824", "0.52666405862440172", "0.5366", "3.42175", "61.701080114490962438", "0.8336708437", "0.0", "1.0", "2.5", "0.658027364385", "0.0", "1.246", "0.14", ]; let values_hex = &[ "0x8.49e2bf94ebf30cb80717aab089ffe81a4240bd550c84a499a4753e306f26fd3913222c258d89033b#324", "0x1.0#1", "0x0.aa47dffd#32", "0x0.0", "0x4.3c09c8a06f55060972e84#86", "0x2.6219e8fcfa9bb9ef41add9535f62860#125", "0x1.096f406#28", "0x2.671785a18c13ffbbe8b27f4#93", "0x0.86d374abc53b0a#55", "0x0.896#12", "0x3.6bf8#16", "0x3d.b379fc839d57b1c#65", "0x0.d56b73d18#33", "0x0.0", "0x1.0#2", "0x2.8#4", "0x0.a8747b39e8#37", "0x0.0", "0x1.3f#9", "0x0.24#4", ]; let common_values = &[ ("0.0", 100224), ("1.0", 4643), ("2.0", 2373), ("0.5", 2353), ("1.5", 2327), ("1.0", 2294), ("0.5", 1219), ("4.0", 1204), ("2.0", 1195), ("0.8", 1191), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x1.0#1", 4643), ("0x2.0#1", 2373), ("0x0.8#1", 2353), ("0x1.8#2", 2327), ("0x1.0#2", 2294), ("0x0.8#2", 1219), ("0x4.0#1", 1204), ("0x2.0#2", 1195), ("0x0.c#2", 1191), ]; let sample_median = ( "1.31267178118571998379", Some("1.31268190290298901432879852014280461789620659172002407"), ); let sample_median_hex = ( "0x1.500b42029321dc7ec#67", Some("0x1.500bebd304f66efb8d7a481eef659ad171581e14dea8#175"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(10.510498034617717), standard_deviation: NiceFloat(1688.742389206287), skewness: NiceFloat(594.3533044311691), excess_kurtosis: NiceFloat(387838.0226770939), }; random_non_negative_finite_floats_helper( 1, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, zero probability 1/10 let values = &[ "1.0e9", "2.0e-6", "24.0", "0.0", "5.0e-7", "0.06", "8.0e22", "7.0e19", "0.05", "6.4e7", "2.0e38", "7.0e-9", "2.0e15", "0.0", "3.0e11", "1.0e-8", "6.0e14", "0.0", "0.05", "2.0e-34", ]; let values_hex = &[ "0x4.0E+7#1", "0x0.00002#1", "0x18.0#2", "0x0.0", "0x8.0E-6#1", "0x0.10#3", "0x1.0E+19#1", "0x4.0E+16#1", "0x0.0c#2", "0x3.d08E+6#12", "0x8.0E+31#1", "0x2.0E-7#1", "0x8.0E+12#1", "0x0.0", "0x4.0E+9#1", "0x4.0E-7#2", "0x2.0E+12#1", "0x0.0", "0x0.0c#2", "0x1.0E-28#1", ]; let common_values = &[ ("0.0", 100224), ("1.0", 3531), ("2.0", 3503), ("4.0", 3399), ("0.5", 3381), ("0.1", 3375), ("0.2", 3369), ("0.06", 3330), ("8.0", 3283), ("2.0e1", 3250), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x1.0#1", 3531), ("0x2.0#1", 3503), ("0x4.0#1", 3399), ("0x0.8#1", 3381), ("0x0.2#1", 3375), ("0x0.4#1", 3369), ("0x0.1#1", 3330), ("0x8.0#1", 3283), ("0x1.0E+1#1", 3250), ]; let sample_median = ("0.006", Some("0.0059")); let sample_median_hex = ("0x0.018#3", Some("0x0.018#4")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.237414368630999e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_negative_finite_floats_helper( 64, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, zero probability 1/10 let values = &[ "1112479228.653802418557662930660020738554074733226813063166716380919457294269645928321492\ 4893705523", "2.0e-6", "21.285095192", "0.0", "5.0479463188465553988010694e-7", "0.074475245528293734932014409944689621417", "7.83424591e22", "88644082373352750967.8179473", "0.032916503664025107", "3.601e7", "2.91091e38", "1.43659021971959067597e-8", "3.7545197012e15", "0.0", "3.0e11", "1.9e-8", "7.4087294826e14", "0.0", "0.0389", "2.2e-34", ]; let values_hex = &[ "0x424f15fc.a75f9865c038bd55844fff40d21205eaa8642524cd23a9f1837937e9c89911612c6c4819d8#324", "0x0.00002#1", "0x15.48fbffa#32", "0x0.0", "0x8.78139140deaa0c12e5d08E-6#86", "0x0.1310cf47e7d4ddcf7a0d6eca9afb1430#125", "0x1.096f406E+19#28", "0x4ce2f0b431827ff77.d164fe8#93", "0x0.086d374abc53b0a#55", "0x2.258E+6#12", "0xd.afeE+31#16", "0x3.db379fc839d57b1cE-7#65", "0xd.56b73d18E+12#33", "0x0.0", "0x4.0E+9#2", "0x5.0E-7#4", "0x2.a1d1ece7aE+12#37", "0x0.0", "0x0.09f8#9", "0x1.2E-28#4", ]; let common_values = &[ ("0.0", 100224), ("8.0", 129), ("4.0", 120), ("2.0", 107), ("0.06", 107), ("1.0e3", 106), ("3.0e1", 105), ("4.0e3", 104), ("0.5", 102), ("1.0e2", 102), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x8.0#1", 129), ("0x4.0#1", 120), ("0x2.0#1", 107), ("0x0.1#1", 107), ("0x4.0E+2#1", 106), ("0x2.0E+1#1", 105), ("0x1.0E+3#1", 104), ("0x0.8#1", 102), ("0x8.0E+1#1", 102), ]; let sample_median = ("0.007447481", Some("0.0074479832945")); let sample_median_hex = ("0x0.01e8140#21", Some("0x0.01e81c6cabc#35")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.6946902524964283e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_negative_finite_floats_helper( 64, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_1() { random_non_negative_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_2() { random_non_negative_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_3() { random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_4() { random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_5() { random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn random_non_negative_finite_floats_fail_6() { random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1); } ================================================ FILE: malachite-float/tests/random/random_non_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_non_positive_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_non_positive_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_non_positive_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_non_positive_finite_floats() { // mean |sci_exponent| 1, mean precision 2, zero probability 1/10 let values = &[ "-8.0", "-1.0", "-0.8", "-0.0", "-4.0", "-2.0", "-1.0", "-2.0", "-0.8", "-0.9536", "-2.0", "-3.0e1", "-0.5", "-0.0", "-1.0", "-2.0", "-0.5", "-0.0", "-1.5", "-0.1", ]; let values_hex = &[ "-0x8.0#1", "-0x1.0#1", "-0x0.c#2", "-0x0.0", "-0x4.0#1", "-0x2.0#3", "-0x1.0#1", "-0x2.0#1", "-0x0.c#2", "-0x0.f42#12", "-0x2.0#1", "-0x2.0E+1#1", "-0x0.8#1", "-0x0.0", "-0x1.0#1", "-0x2.0#2", "-0x0.8#1", "-0x0.0", "-0x1.8#2", "-0x0.2#1", ]; let common_values = &[ ("-1.0", 149586), ("-0.0", 100224), ("-2.0", 74929), ("-0.5", 74827), ("-1.0", 37902), ("-4.0", 37612), ("-0.2", 37602), ("-1.5", 37600), ("-0.5", 18934), ("-0.8", 18834), ]; let common_values_hex = &[ ("-0x1.0#1", 149586), ("-0x0.0", 100224), ("-0x2.0#1", 74929), ("-0x0.8#1", 74827), ("-0x1.0#2", 37902), ("-0x4.0#1", 37612), ("-0x0.4#1", 37602), ("-0x1.8#2", 37600), ("-0x0.8#2", 18934), ("-0x0.c#2", 18834), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.693371936934735), standard_deviation: NiceFloat(1671.7840625385452), skewness: NiceFloat(-718.2460436055444), excess_kurtosis: NiceFloat(578520.0792964109), }; random_non_positive_finite_floats_helper( 1, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, zero probability 1/10 let values = &[ "-8.28861615548880710123228230074063493724223027547309594725606129258466731212769395352521\ 9033439102", "-1.0", "-0.6651592248", "-0.0", "-4.2345242873846765390825841", "-2.38320785690539951782446111823006788535", "-1.036853813", "-2.4027026671793265640566992824", "-0.52666405862440172", "-0.5366", "-3.42175", "-61.701080114490962438", "-0.8336708437", "-0.0", "-1.0", "-2.5", "-0.658027364385", "-0.0", "-1.246", "-0.14", ]; let values_hex = &[ "-0x8.49e2bf94ebf30cb80717aab089ffe81a4240bd550c84a499a4753e306f26fd3913222c258d89033b\ #324", "-0x1.0#1", "-0x0.aa47dffd#32", "-0x0.0", "-0x4.3c09c8a06f55060972e84#86", "-0x2.6219e8fcfa9bb9ef41add9535f62860#125", "-0x1.096f406#28", "-0x2.671785a18c13ffbbe8b27f4#93", "-0x0.86d374abc53b0a#55", "-0x0.896#12", "-0x3.6bf8#16", "-0x3d.b379fc839d57b1c#65", "-0x0.d56b73d18#33", "-0x0.0", "-0x1.0#2", "-0x2.8#4", "-0x0.a8747b39e8#37", "-0x0.0", "-0x1.3f#9", "-0x0.24#4", ]; let common_values = &[ ("-0.0", 100224), ("-1.0", 4643), ("-2.0", 2373), ("-0.5", 2353), ("-1.5", 2327), ("-1.0", 2294), ("-0.5", 1219), ("-4.0", 1204), ("-2.0", 1195), ("-0.8", 1191), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x1.0#1", 4643), ("-0x2.0#1", 2373), ("-0x0.8#1", 2353), ("-0x1.8#2", 2327), ("-0x1.0#2", 2294), ("-0x0.8#2", 1219), ("-0x4.0#1", 1204), ("-0x2.0#2", 1195), ("-0x0.c#2", 1191), ]; let sample_median = ( "-1.31268190290298901432879852014280461789620659172002407", Some("-1.31267178118571998379"), ); let sample_median_hex = ( "-0x1.500bebd304f66efb8d7a481eef659ad171581e14dea8#175", Some("-0x1.500b42029321dc7ec#67"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-10.510498034617717), standard_deviation: NiceFloat(1688.742389206287), skewness: NiceFloat(-594.3533044311691), excess_kurtosis: NiceFloat(387838.0226770939), }; random_non_positive_finite_floats_helper( 1, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, zero probability 1/10 let values = &[ "-1.0e9", "-2.0e-6", "-24.0", "-0.0", "-5.0e-7", "-0.06", "-8.0e22", "-7.0e19", "-0.05", "-6.4e7", "-2.0e38", "-7.0e-9", "-2.0e15", "-0.0", "-3.0e11", "-1.0e-8", "-6.0e14", "-0.0", "-0.05", "-2.0e-34", ]; let values_hex = &[ "-0x4.0E+7#1", "-0x0.00002#1", "-0x18.0#2", "-0x0.0", "-0x8.0E-6#1", "-0x0.10#3", "-0x1.0E+19#1", "-0x4.0E+16#1", "-0x0.0c#2", "-0x3.d08E+6#12", "-0x8.0E+31#1", "-0x2.0E-7#1", "-0x8.0E+12#1", "-0x0.0", "-0x4.0E+9#1", "-0x4.0E-7#2", "-0x2.0E+12#1", "-0x0.0", "-0x0.0c#2", "-0x1.0E-28#1", ]; let common_values = &[ ("-0.0", 100224), ("-1.0", 3531), ("-2.0", 3503), ("-4.0", 3399), ("-0.5", 3381), ("-0.1", 3375), ("-0.2", 3369), ("-0.06", 3330), ("-8.0", 3283), ("-2.0e1", 3250), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x1.0#1", 3531), ("-0x2.0#1", 3503), ("-0x4.0#1", 3399), ("-0x0.8#1", 3381), ("-0x0.2#1", 3375), ("-0x0.4#1", 3369), ("-0x0.1#1", 3330), ("-0x8.0#1", 3283), ("-0x1.0E+1#1", 3250), ]; let sample_median = ("-0.0059", Some("-0.006")); let sample_median_hex = ("-0x0.018#4", Some("-0x0.018#3")); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.237414368630999e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_positive_finite_floats_helper( 64, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, zero probability 1/10 let values = &[ "-1112479228.65380241855766293066002073855407473322681306316671638091945729426964592832149\ 24893705523", "-2.0e-6", "-21.285095192", "-0.0", "-5.0479463188465553988010694e-7", "-0.074475245528293734932014409944689621417", "-7.83424591e22", "-88644082373352750967.8179473", "-0.032916503664025107", "-3.601e7", "-2.91091e38", "-1.43659021971959067597e-8", "-3.7545197012e15", "-0.0", "-3.0e11", "-1.9e-8", "-7.4087294826e14", "-0.0", "-0.0389", "-2.2e-34", ]; let values_hex = &[ "-0x424f15fc.a75f9865c038bd55844fff40d21205eaa8642524cd23a9f1837937e9c89911612c6c4819d8\ #324", "-0x0.00002#1", "-0x15.48fbffa#32", "-0x0.0", "-0x8.78139140deaa0c12e5d08E-6#86", "-0x0.1310cf47e7d4ddcf7a0d6eca9afb1430#125", "-0x1.096f406E+19#28", "-0x4ce2f0b431827ff77.d164fe8#93", "-0x0.086d374abc53b0a#55", "-0x2.258E+6#12", "-0xd.afeE+31#16", "-0x3.db379fc839d57b1cE-7#65", "-0xd.56b73d18E+12#33", "-0x0.0", "-0x4.0E+9#2", "-0x5.0E-7#4", "-0x2.a1d1ece7aE+12#37", "-0x0.0", "-0x0.09f8#9", "-0x1.2E-28#4", ]; let common_values = &[ ("-0.0", 100224), ("-8.0", 129), ("-4.0", 120), ("-2.0", 107), ("-0.06", 107), ("-1.0e3", 106), ("-3.0e1", 105), ("-4.0e3", 104), ("-0.5", 102), ("-1.0e2", 102), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x8.0#1", 129), ("-0x4.0#1", 120), ("-0x2.0#1", 107), ("-0x0.1#1", 107), ("-0x4.0E+2#1", 106), ("-0x2.0E+1#1", 105), ("-0x1.0E+3#1", 104), ("-0x0.8#1", 102), ("-0x8.0E+1#1", 102), ]; let sample_median = ("-0.0074479832945", Some("-0.007447481")); let sample_median_hex = ("-0x0.01e81c6cabc#35", Some("-0x0.01e8140#21")); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.6946902524964283e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_positive_finite_floats_helper( 64, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_1() { random_non_positive_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_2() { random_non_positive_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_3() { random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_4() { random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_5() { random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn random_non_positive_finite_floats_fail_6() { random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1); } ================================================ FILE: malachite-float/tests/random/random_nonzero_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_nonzero_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_nonzero_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_nonzero_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_nonzero_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "-8.0", "-1.0", "-0.8", "4.0", "-2.0", "1.0", "-2.0", "-0.8", "-0.9536", "2.0", "3.0e1", "0.5", "-1.0", "-2.0", "0.5", "-1.5", "-0.1", "-1.0", "-0.047", "-1.0", ]; let values_hex = &[ "-0x8.0#1", "-0x1.0#1", "-0x0.c#2", "0x4.0#1", "-0x2.0#3", "0x1.0#1", "-0x2.0#1", "-0x0.c#2", "-0x0.f42#12", "0x2.0#1", "0x2.0E+1#1", "0x0.8#1", "-0x1.0#1", "-0x2.0#2", "0x0.8#1", "-0x1.8#2", "-0x0.2#1", "-0x1.0#1", "-0x0.0c#3", "-0x1.0#3", ]; let common_values = &[ ("1.0", 83167), ("-1.0", 83060), ("2.0", 41731), ("-2.0", 41688), ("0.5", 41643), ("-0.5", 41534), ("-4.0", 21185), ("1.0", 21166), ("0.2", 21077), ("-1.0", 20914), ]; let common_values_hex = &[ ("0x1.0#1", 83167), ("-0x1.0#1", 83060), ("0x2.0#1", 41731), ("-0x2.0#1", 41688), ("0x0.8#1", 41643), ("-0x0.8#1", 41534), ("-0x4.0#1", 21185), ("0x1.0#2", 21166), ("0x0.4#1", 21077), ("-0x1.0#2", 20914), ]; let sample_median = ("0.002", None); let sample_median_hex = ("0x0.008#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.137441392805658), standard_deviation: NiceFloat(1753.4002861490633), skewness: NiceFloat(-540.308156545252), excess_kurtosis: NiceFloat(486100.3517515351), }; random_nonzero_finite_floats_helper( 1, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "-8.28861615548880710123228230074063493724223027547309594725606129258466731212769395352521\ 9033439102", "-1.0", "-0.6651592248", "4.2345242873846765390825841", "-2.38320785690539951782446111823006788535", "1.036853813", "-2.4027026671793265640566992824", "-0.52666405862440172", "-0.5366", "3.42175", "61.701080114490962438", "0.8336708437", "-1.0", "-2.5", "0.658027364385", "-1.246", "-0.14", "-1.245722352956368383395858819", "-0.03962809021", "-1.0011", ]; let values_hex = &[ "-0x8.49e2bf94ebf30cb80717aab089ffe81a4240bd550c84a499a4753e306f26fd3913222c258d89033b\ #324", "-0x1.0#1", "-0x0.aa47dffd#32", "0x4.3c09c8a06f55060972e84#86", "-0x2.6219e8fcfa9bb9ef41add9535f62860#125", "0x1.096f406#28", "-0x2.671785a18c13ffbbe8b27f4#93", "-0x0.86d374abc53b0a#55", "-0x0.896#12", "0x3.6bf8#16", "0x3d.b379fc839d57b1c#65", "0x0.d56b73d18#33", "-0x1.0#2", "-0x2.8#4", "0x0.a8747b39e8#37", "-0x1.3f#9", "-0x0.24#4", "-0x1.3ee7a8fdd801625ca3c1028#90", "-0x0.0a2511077#32", "-0x1.0048#14", ]; let common_values = &[ ("-1.0", 2594), ("1.0", 2582), ("2.0", 1322), ("0.5", 1316), ("-2.0", 1310), ("-1.5", 1295), ("1.5", 1288), ("1.0", 1286), ("-0.5", 1282), ("-1.0", 1256), ]; let common_values_hex = &[ ("-0x1.0#1", 2594), ("0x1.0#1", 2582), ("0x2.0#1", 1322), ("0x0.8#1", 1316), ("-0x2.0#1", 1310), ("-0x1.8#2", 1295), ("0x1.8#2", 1288), ("0x1.0#2", 1286), ("-0x0.8#1", 1282), ("-0x1.0#2", 1256), ]; let sample_median = ( "0.0027890310577504986877", Some("0.0027891362634973129863915401"), ); let sample_median_hex = ( "0x0.00b6c82d2e399e2de0#63", Some("0x0.00b6c9f1092ac094b9e5264#84"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.6942588764777254), standard_deviation: NiceFloat(1892.6524949864393), skewness: NiceFloat(-231.427091034788), excess_kurtosis: NiceFloat(286498.2528287583), }; random_nonzero_finite_floats_helper( 1, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "-1.0e9", "-2.0e-6", "-24.0", "5.0e-7", "-0.06", "8.0e22", "-7.0e19", "-0.05", "-6.4e7", "2.0e38", "7.0e-9", "2.0e15", "-3.0e11", "-1.0e-8", "6.0e14", "-0.05", "-2.0e-34", "-6.0e14", "-3.8e30", "-1.6e57", ]; let values_hex = &[ "-0x4.0E+7#1", "-0x0.00002#1", "-0x18.0#2", "0x8.0E-6#1", "-0x0.10#3", "0x1.0E+19#1", "-0x4.0E+16#1", "-0x0.0c#2", "-0x3.d08E+6#12", "0x8.0E+31#1", "0x2.0E-7#1", "0x8.0E+12#1", "-0x4.0E+9#1", "-0x4.0E-7#2", "0x2.0E+12#1", "-0x0.0c#2", "-0x1.0E-28#1", "-0x2.0E+12#1", "-0x3.0E+25#3", "-0x4.0E+47#3", ]; let common_values = &[ ("1.0", 2018), ("-2.0", 2004), ("-1.0", 1938), ("4.0", 1933), ("0.5", 1901), ("0.1", 1900), ("-0.2", 1883), ("-4.0", 1875), ("0.2", 1874), ("2.0", 1873), ]; let common_values_hex = &[ ("0x1.0#1", 2018), ("-0x2.0#1", 2004), ("-0x1.0#1", 1938), ("0x4.0#1", 1933), ("0x0.8#1", 1901), ("0x0.2#1", 1900), ("-0x0.4#1", 1883), ("-0x4.0#1", 1875), ("0x0.4#1", 1874), ("0x2.0#1", 1873), ]; let sample_median = ("1.0e-122", Some("1.0e-122")); let sample_median_hex = ("0x8.0E-102#2", Some("0x8.0E-102#3")); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.2374143686309846e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_finite_floats_helper( 64, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "-1112479228.65380241855766293066002073855407473322681306316671638091945729426964592832149\ 24893705523", "-2.0e-6", "-21.285095192", "5.0479463188465553988010694e-7", "-0.074475245528293734932014409944689621417", "7.83424591e22", "-88644082373352750967.8179473", "-0.032916503664025107", "-3.601e7", "2.91091e38", "1.43659021971959067597e-8", "3.7545197012e15", "-3.0e11", "-1.9e-8", "7.4087294826e14", "-0.0389", "-2.2e-34", "-701279340572674.768452138179", "-3.215012629e30", "-1.571e57", ]; let values_hex = &[ "-0x424f15fc.a75f9865c038bd55844fff40d21205eaa8642524cd23a9f1837937e9c89911612c6c4819d8\ #324", "-0x0.00002#1", "-0x15.48fbffa#32", "0x8.78139140deaa0c12e5d08E-6#86", "-0x0.1310cf47e7d4ddcf7a0d6eca9afb1430#125", "0x1.096f406E+19#28", "-0x4ce2f0b431827ff77.d164fe8#93", "-0x0.086d374abc53b0a#55", "-0x2.258E+6#12", "0xd.afeE+31#16", "0x3.db379fc839d57b1cE-7#65", "0xd.56b73d18E+12#33", "-0x4.0E+9#2", "-0x5.0E-7#4", "0x2.a1d1ece7aE+12#37", "-0x0.09f8#9", "-0x1.2E-28#4", "-0x27dcf51fbb002.c4b9478205#90", "-0x2.894441dcE+25#32", "-0x4.012E+47#14", ]; let common_values = &[ ("-8.0", 73), ("1.0e3", 70), ("4.0", 69), ("2.0", 68), ("8.0", 68), ("-1.0e2", 67), ("-0.02", 65), ("-0.5", 64), ("2.0e1", 64), ("-4.0", 62), ]; let common_values_hex = &[ ("-0x8.0#1", 73), ("0x4.0E+2#1", 70), ("0x4.0#1", 69), ("0x2.0#1", 68), ("0x8.0#1", 68), ("-0x8.0E+1#1", 67), ("-0x0.04#1", 65), ("-0x0.8#1", 64), ("0x1.0E+1#1", 64), ("-0x4.0#1", 62), ]; let sample_median = ( "2.22082266973856198260258239259022e-122", Some("2.35472681582314e-122"), ); let sample_median_hex = ( "0xe.ae4e347efb6723ba8a9c199b48E-102#105", Some("0xf.90e97334e78E-102#45"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.6946902524964396e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_finite_floats_helper( 64, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_nonzero_finite_floats_fail_1() { random_nonzero_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1); } #[test] #[should_panic] fn random_nonzero_finite_floats_fail_2() { random_nonzero_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1); } #[test] #[should_panic] fn random_nonzero_finite_floats_fail_3() { random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0); } #[test] #[should_panic] fn random_nonzero_finite_floats_fail_4() { random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1); } ================================================ FILE: malachite-float/tests/random/random_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_positive_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn random_positive_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_positive_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_random_positive_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "1.5", "1.0", "2.0", "1.0", "1.0", "2.0", "2.0", "1.2", "2.0", "1.0", "2.0", "2.0", "4.0", "1.0", "1.8", "2.5", "0.1", "1.0", "0.2", "1.2", ]; let values_hex = &[ "0x1.8#2", "0x1.0#1", "0x2.0#2", "0x1.0#2", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x1.4#3", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x4.0#1", "0x1.0#1", "0x1.c#3", "0x2.8#4", "0x0.2#1", "0x1.0#1", "0x0.4#1", "0x1.4#3", ]; let common_values = &[ ("1.0", 166114), ("0.5", 83464), ("2.0", 83434), ("1.5", 42025), ("0.2", 41531), ("1.0", 41506), ("4.0", 41483), ("3.0", 21005), ("2.0", 20892), ("0.1", 20888), ]; let common_values_hex = &[ ("0x1.0#1", 166114), ("0x0.8#1", 83464), ("0x2.0#1", 83434), ("0x1.8#2", 42025), ("0x0.4#1", 41531), ("0x1.0#2", 41506), ("0x4.0#1", 41483), ("0x3.0#2", 21005), ("0x2.0#2", 20892), ("0x0.2#1", 20888), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.292847587427611), standard_deviation: NiceFloat(416.97010060005687), skewness: NiceFloat(334.72226371600976), excess_kurtosis: NiceFloat(139648.08254659182), }; random_positive_finite_floats_helper( 1, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "1.8", "1.3850071337780625300836", "3.21176241813", "1.981013494834061409257349", "1.665272", "3.0477509378551710980549069671536911164880571509", "3.86646429082638580413691355062141611967080168780483321308586", "1.1383718", "3.005438259332186398250782844", "1.31402772840010613", "2.2954821356993", "3.341070237", "6.42834377982969296", "1.055708800484474", "1.09154149257425903017951075071293557661092806", "2.750421277483313", "0.2219335998", "1.1563594283786540769774526007723931560664", "0.39596234107597", "1.3496675", ]; let values_hex = &[ "0x1.c#3", "0x1.628fd3d84db091d430#71", "0x3.36360fd46#38", "0x1.fb23b34d3f38af725038#79", "0x1.aa4f4#19", "0x3.0c3967cc70f8444c90df6c12283a15fa4637da#153", "0x3.ddd09a90404c02ee3c715fa17bf84c143354d47adb8aff3c0#195", "0x1.236c56#24", "0x3.016466d9fa99ac91c2dfb4#89", "0x1.50641f07840015#57", "0x2.4ba4b79d6178#48", "0x3.57506108#31", "0x6.6da7f01dd04530#57", "0x1.0e42ee942e22#48", "0x1.176f4364d55e3feb51571e25ef39e528b86a#145", "0x2.c01b9bdd036c4#54", "0x0.38d0a3f10#31", "0x1.28072be74ebd242348b5852a9e4a3c62e#132", "0x0.655dc9b95e7#43", "0x1.5983d0#24", ]; let common_values = &[ ("1.0", 5069), ("1.0", 2626), ("0.5", 2623), ("2.0", 2623), ("1.5", 2488), ("2.0", 1309), ("0.2", 1301), ("4.0", 1299), ("1.2", 1293), ("0.8", 1283), ]; let common_values_hex = &[ ("0x1.0#1", 5069), ("0x1.0#2", 2626), ("0x0.8#1", 2623), ("0x2.0#1", 2623), ("0x1.8#2", 2488), ("0x2.0#2", 1309), ("0x0.4#1", 1301), ("0x4.0#1", 1299), ("0x1.4#3", 1293), ("0x0.c#2", 1283), ]; let sample_median = ( "1.492046225515012964994532213857812720544842101177086840260174", Some("1.492048772960956"), ); let sample_median_hex = ( "0x1.7df6bdceb50c76e2fdee90d7296fa9b4a2cc3ae315ce8cf010#199", Some("0x1.7df6e88be77c#49"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(9.138627718915657), standard_deviation: NiceFloat(468.606797626186), skewness: NiceFloat(309.74563573271297), excess_kurtosis: NiceFloat(127224.11304735676), }; random_positive_finite_floats_helper( 1, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "3.0e-37", "8.0e-34", "4.0e-6", "3.0e-45", "2.0e15", "5.0e-10", "2.0e4", "0.08", "0.0001", "1.0e14", "2.0e34", "9.0e-13", "0.0001", "9.0e9", "2.3e33", "0.16", "0.00003", "5.0e18", "0.06", "7.0e8", ]; let values_hex = &[ "0x6.0E-31#2", "0x4.0E-28#1", "0x0.00004#2", "0x1.0E-37#2", "0x8.0E+12#1", "0x2.0E-8#1", "0x4.0E+3#1", "0x0.14#3", "0x0.0008#1", "0x8.0E+11#1", "0x4.0E+28#1", "0x1.0E-10#1", "0x0.0008#1", "0x2.0E+8#1", "0x7.0E+27#3", "0x0.28#4", "0x0.0002#1", "0x4.0E+15#1", "0x0.1#1", "0x2.8E+7#3", ]; let common_values = &[ ("1.0", 3831), ("0.2", 3830), ("0.5", 3826), ("2.0", 3753), ("4.0", 3716), ("8.0", 3653), ("0.1", 3639), ("0.06", 3637), ("3.0e1", 3632), ("2.0e1", 3617), ]; let common_values_hex = &[ ("0x1.0#1", 3831), ("0x0.4#1", 3830), ("0x0.8#1", 3826), ("0x2.0#1", 3753), ("0x4.0#1", 3716), ("0x8.0#1", 3653), ("0x0.2#1", 3639), ("0x0.1#1", 3637), ("0x2.0E+1#1", 3632), ("0x1.0E+1#1", 3617), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.9680504915704222e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_finite_floats_helper( 64, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "3.3e-37", "1.066970684853243558372e-33", "6.12595065713e-6", "5.55198233623541837705276e-45", "3.74986e15", "7.096098125575043023691761696603361322749539164e-10", "31674.0754704497525074895958066906408523432074264971936815994", "0.07114824", "0.0001834373937580680174713612576", "184932962124288.041", "2.38376493640286e34", "1.519342839e-12", "0.000196177483515310454", "9068469544.36041", "1416901865713435510498832543218638.47378814837", "0.17190132984270706", "0.00005418300776", "5332766608130525448.821004944540229640534", "0.09899058526899", "7.2459725e8", ]; let values_hex = &[ "0x7.0E-31#3", "0x5.8a3f4f6136c24750cE-28#71", "0x0.000066c6c1fa8c#38", "0x1.fb23b34d3f38af725038E-37#79", "0xd.527aE+12#19", "0x3.0c3967cc70f8444c90df6c12283a15fa4637daE-8#153", "0x7bba.13520809805dc78e2bf42f7f0982866a9a8f5b715fe78#195", "0x0.1236c56#24", "0x0.000c05919b67ea66b2470b7ed0#89", "0xa8320f83c200.0a8#57", "0x4.97496f3ac2f0E+28#48", "0x1.aba83084E-10#31", "0x0.000cdb4fe03ba08a60#57", "0x21c85dd28.5c44#48", "0x45dbd0d935578ffad455c7897bce.794a2e1a8#145", "0x0.2c01b9bdd036c4#54", "0x0.00038d0a3f10#31", "0x4a01caf9d3af4908.d22d614aa7928f18b8#132", "0x0.1957726e579c#43", "0x2.b307a0E+7#24", ]; let common_values = &[ ("2.0", 130), ("2.0e1", 129), ("0.2", 122), ("3.0e1", 117), ("0.004", 116), ("1.0e5", 114), ("0.02", 112), ("0.00002", 112), ("0.1", 109), ("8.0", 108), ]; let common_values_hex = &[ ("0x2.0#1", 130), ("0x1.0E+1#1", 129), ("0x0.4#1", 122), ("0x2.0E+1#1", 117), ("0x0.01#1", 116), ("0x2.0E+4#1", 114), ("0x0.04#1", 112), ("0x0.0001#1", 112), ("0x0.2#1", 109), ("0x8.0#1", 108), ]; let sample_median = ( "1.45263", Some("1.4527665236460671657422963814630798553398772791"), ); let sample_median_hex = ( "0x1.73df8#18", Some("0x1.73e881c3c8916f41f0bcfa9b4958a2e850b2da0#154"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(1.9911135832684696e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_finite_floats_helper( 64, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_positive_finite_floats_fail_1() { random_positive_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1); } #[test] #[should_panic] fn random_positive_finite_floats_fail_2() { random_positive_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1); } #[test] #[should_panic] fn random_positive_finite_floats_fail_3() { random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0); } #[test] #[should_panic] fn random_positive_finite_floats_fail_4() { random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 1); } ================================================ FILE: malachite-float/tests/random/random_positive_floats_with_precision.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::random_positive_floats_with_precision; use malachite_float::test_util::random::{ random_floats_helper_helper, random_floats_helper_helper_no_common_values, }; fn random_positive_floats_with_precision_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, precision: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( random_positive_floats_with_precision( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, precision, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } fn random_positive_floats_with_precision_helper_no_common_values( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, precision: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper_no_common_values( random_positive_floats_with_precision( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, precision, ), expected_values, expected_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } #[test] fn test_random_positive_floats_with_precision() { // mean |sci_exponent| 1, precision 1 let values = &[ "1.0", "1.0", "2.0", "1.0", "1.0", "2.0", "2.0", "1.0", "2.0", "1.0", "2.0", "2.0", "4.0", "1.0", "1.0", "2.0", "0.1", "1.0", "0.2", "1.0", ]; let values_hex = &[ "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x4.0#1", "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x0.2#1", "0x1.0#1", "0x0.4#1", "0x1.0#1", ]; let common_values = &[ ("1.0", 333085), ("2.0", 167041), ("0.5", 166671), ("0.2", 83200), ("4.0", 83177), ("8.0", 41643), ("0.1", 41551), ("0.06", 20981), ("2.0e1", 20919), ("3.0e1", 10411), ]; let common_values_hex = &[ ("0x1.0#1", 333085), ("0x2.0#1", 167041), ("0x0.8#1", 166671), ("0x0.4#1", 83200), ("0x4.0#1", 83177), ("0x8.0#1", 41643), ("0x0.2#1", 41551), ("0x0.1#1", 20981), ("0x1.0E+1#1", 20919), ("0x2.0E+1#1", 10411), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(6.111051015726221), standard_deviation: NiceFloat(305.2547556508084), skewness: NiceFloat(297.86495510456103), excess_kurtosis: NiceFloat(112470.88988361698), }; random_positive_floats_with_precision_helper( 1, 1, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, precision 10 let values = &[ "1.918", "1.98", "3.305", "1.42", "1.557", "3.023", "2.5", "1.541", "3.621", "1.834", "3.102", "2.617", "7.15", "1.43", "1.943", "3.727", "0.2124", "1.869", "0.272", "1.172", ]; let values_hex = &[ "0x1.eb0#10", "0x1.fb0#10", "0x3.4e#10", "0x1.6b8#10", "0x1.8e8#10", "0x3.06#10", "0x2.80#10", "0x1.8a8#10", "0x3.9f#10", "0x1.d58#10", "0x3.1a#10", "0x2.9e#10", "0x7.26#10", "0x1.6e0#10", "0x1.f18#10", "0x3.ba#10", "0x0.366#10", "0x1.de8#10", "0x0.45a#10", "0x1.2c0#10", ]; let common_values = &[ ("1.381", 721), ("1.869", 717), ("1.084", 711), ("1.033", 710), ("1.635", 707), ("1.059", 706), ("1.469", 706), ("1.252", 705), ("1.205", 702), ("1.047", 700), ]; let common_values_hex = &[ ("0x1.618#10", 721), ("0x1.de8#10", 717), ("0x1.158#10", 711), ("0x1.088#10", 710), ("0x1.a28#10", 707), ("0x1.0f0#10", 706), ("0x1.780#10", 706), ("0x1.408#10", 705), ("0x1.348#10", 702), ("0x1.0c0#10", 700), ]; let sample_median = ("1.5", None); let sample_median_hex = ("0x1.800#10", None); let sample_moment_stats = MomentStats { mean: NiceFloat(9.056696785111221), standard_deviation: NiceFloat(431.29029073720193), skewness: NiceFloat(278.5706756279952), excess_kurtosis: NiceFloat(97797.38656215608), }; random_positive_floats_with_precision_helper( 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, precision 64 let values = &[ "1.740199402817679648", "1.0192449215156261222", "3.1130307619404870736", "1.0471449172912252423", "1.3840640877665362527", "3.0460668755070546289", "3.476526206271118552", "1.8118954029598159672", "3.728977157780790176", "1.9336753518355031441", "2.157307006970948965", "3.4498871850383974534", "6.9412040614053056114", "1.7943152699644272746", "1.2440394513671251233", "2.6137809712053548931", "0.2398662564271449353", "1.6629773022545155586", "0.25533214025794003077", "1.900690880541109083", ]; let values_hex = &[ "0x1.bd7db5439ee3dbac#64", "0x1.04ed3c34861143ec#64", "0x3.1cef9581f9f24d38#64", "0x1.0c11b075f03d6dae#64", "0x1.62520628867d223a#64", "0x3.0bcb09ebbb50e418#64", "0x3.79fd9f179f145a00#64", "0x1.cfd8608b7c32de2a#64", "0x3.ba9e3f3c33141e7c#64", "0x1.ef05590d36fbcb56#64", "0x2.284545a25f32dc68#64", "0x3.732bce7aa1218278#64", "0x6.f0f2bfd699213c98#64", "0x1.cb583edb35eb99b8#64", "0x1.3e795e968e3acfc6#64", "0x2.9d20bfee3bef16e8#64", "0x0.3d67dffec4bedc598#64", "0x1.a9b8e1672c674f7a#64", "0x0.415d727806899f168#64", "0x1.e693ad73bac0ecb0#64", ]; let sample_median = ("1.5021401700224458548", Some("1.5021411966182242309")); let sample_median_hex = ("0x1.808c42184118ca86#64", Some("0x1.808c5351731799cc#64")); let sample_moment_stats = MomentStats { mean: NiceFloat(9.06512816951906), standard_deviation: NiceFloat(439.97218971420835), skewness: NiceFloat(280.6616264514779), excess_kurtosis: NiceFloat(99433.37467826756), }; random_positive_floats_with_precision_helper_no_common_values( 1, 1, 64, values, values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 1 let values = &[ "2.0e-37", "8.0e-34", "4.0e-6", "3.0e-45", "2.0e15", "5.0e-10", "2.0e4", "0.06", "0.0001", "1.0e14", "2.0e34", "9.0e-13", "0.0001", "9.0e9", "1.0e33", "0.1", "0.00003", "5.0e18", "0.06", "5.0e8", ]; let values_hex = &[ "0x4.0E-31#1", "0x4.0E-28#1", "0x0.00004#1", "0x1.0E-37#1", "0x8.0E+12#1", "0x2.0E-8#1", "0x4.0E+3#1", "0x0.1#1", "0x0.0008#1", "0x8.0E+11#1", "0x4.0E+28#1", "0x1.0E-10#1", "0x0.0008#1", "0x2.0E+8#1", "0x4.0E+27#1", "0x0.2#1", "0x0.0002#1", "0x4.0E+15#1", "0x0.1#1", "0x2.0E+7#1", ]; let common_values = &[ ("1.0", 7698), ("0.2", 7624), ("0.5", 7597), ("2.0", 7563), ("4.0", 7402), ("8.0", 7362), ("0.06", 7323), ("0.1", 7239), ("3.0e1", 7225), ("2.0e1", 7161), ]; let common_values_hex = &[ ("0x1.0#1", 7698), ("0x0.4#1", 7624), ("0x0.8#1", 7597), ("0x2.0#1", 7563), ("0x4.0#1", 7402), ("0x8.0#1", 7362), ("0x0.1#1", 7323), ("0x0.2#1", 7239), ("0x2.0E+1#1", 7225), ("0x1.0E+1#1", 7161), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.9680504915704222e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_floats_with_precision_helper( 64, 1, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 10 let values = &[ "3.607e-37", "1.526e-33", "6.303e-6", "3.979e-45", "3.505e15", "7.04e-10", "2.048e4", "0.0963", "0.000221", "2.581e14", "3.221e34", "1.19e-12", "0.0002182", "1.228e10", "2.523e33", "0.2329", "0.00005186", "8.62e18", "0.068", "6.29e8", ]; let values_hex = &[ "0x7.acE-31#10", "0x7.ecE-28#10", "0x0.000069c#10", "0x1.6b8E-37#10", "0xc.74E+12#10", "0x3.06E-8#10", "0x5.00E+3#10", "0x0.18a8#10", "0x0.000e7c#10", "0xe.acE+11#10", "0x6.34E+28#10", "0x1.4f0E-10#10", "0x0.000e4c#10", "0x2.dcE+8#10", "0x7.c6E+27#10", "0x0.3ba#10", "0x0.000366#10", "0x7.7aE+15#10", "0x0.1168#10", "0x2.58E+7#10", ]; let common_values = &[ ("0.001066", 31), ("1.35", 29), ("0.814", 29), ("1.688", 29), ("0.4429", 29), ("0.569", 28), ("2.883", 28), ("496.0", 28), ("0.02191", 28), ("0.02954", 28), ]; let common_values_hex = &[ ("0x0.0045e#10", 31), ("0x1.598#10", 29), ("0x0.d08#10", 29), ("0x1.b00#10", 29), ("0x0.716#10", 29), ("0x0.91c#10", 28), ("0x2.e2#10", 28), ("0x1f0.0#10", 28), ("0x0.059c#10", 28), ("0x0.0790#10", 28), ]; let sample_median = ("1.471", None); let sample_median_hex = ("0x1.788#10", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.163487411254837e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_floats_with_precision_helper( 64, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 64 let values = &[ "3.2729513077064011786e-37", "7.8519772600462495573e-34", "5.9376349676904431794e-6", "2.9347251290514630352e-45", "3116635254961129.0696", "7.092177112370390978e-10", "28479.702681773003178", "0.113243462684988497952", "0.00022759870347783143164", "272140612311933.89714", "2.2402756790380859597e34", "1.5688270582533720942e-12", "0.00021182873722550371128", "15413050806.4212524556", "1.6148555338067285629e33", "0.16336131070033468082", "0.000058561097760533431471", "7669129173769245662.5", "0.063833035064485007692", "1020425646.4661882869", ]; let values_hex = &[ "0x6.f5f6d50e7b8f6eb0E-31#64", "0x4.13b4f0d218450fb0E-28#64", "0x0.0000639df2b03f3e49a70#64", "0x1.0c11b075f03d6daeE-37#64", "0xb1290314433e9.11d#64", "0x3.0bcb09ebbb50e418E-8#64", "0x6f3f.b3e2f3e28b400#64", "0x0.1cfd8608b7c32de2a#64", "0x0.000eea78fcf0cc5079f#64", "0xf782ac869b7d.e5ab#64", "0x4.508a8b44be65b8d0E+28#64", "0x1.b995e73d5090c13cE-10#64", "0x0.000de1e57fad3242793#64", "0x396b07db6.6bd73370#64", "0x4.f9e57a5a38eb3f18E+27#64", "0x0.29d20bfee3bef16e8#64", "0x0.0003d67dffec4bedc598#64", "0x6a6e3859cb19d3de.8#64", "0x0.10575c9e01a267c5a#64", "0x3cd275ae.77581d960#64", ]; let sample_median = ("1.4744048330756642118", Some("1.4745500033376170913")); let sample_median_hex = ("0x1.7972985b1fd33b34#64", Some("0x1.797c1be8a6d97f72#64")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.1785863803225345e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_floats_with_precision_helper_no_common_values( 64, 1, 64, values, values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn random_positive_floats_with_precision_fail_1() { random_positive_floats_with_precision(EXAMPLE_SEED, 1, 0, 2); } #[test] #[should_panic] fn random_positive_floats_with_precision_fail_2() { random_positive_floats_with_precision(EXAMPLE_SEED, 0, 1, 2); } #[test] #[should_panic] fn random_positive_floats_with_precision_fail_3() { random_positive_floats_with_precision(EXAMPLE_SEED, 1, 1, 0); } ================================================ FILE: malachite-float/tests/random/striped_random_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_zero_p_numerator: u64, mean_zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, mean_zero_p_numerator, mean_zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } #[test] fn test_striped_random_finite_floats() { // mean |sci_exponent| 1, mean precision 2, special probability 1/10 let values = &[ "-3.0", "-1.2", "-2.0", "1.12", "-1.5", "1.0", "-2.0", "-0.25", "-1.0", "0.8", "0.0", "0.262", "-1.2", "-0.59", "8.0", "-6.0", "-2.0", "-0.2", "-0.5", "-0.5", ]; let values_hex = &[ "-0x3.0#3", "-0x1.4#3", "-0x2.0#2", "0x1.2#5", "-0x1.8#2", "0x1.0#3", "-0x2.0#1", "-0x0.4#3", "-0x1.0#1", "0x0.c#2", "0x0.0", "0x0.430#9", "-0x1.4#3", "-0x0.98#5", "0x8.0#1", "-0x6.0#2", "-0x2.0#2", "-0x0.4#1", "-0x0.8#2", "-0x0.8#2", ]; let common_values = &[ ("1.0", 75012), ("-1.0", 74560), ("0.0", 49991), ("-0.0", 49908), ("0.5", 37822), ("2.0", 37501), ("-0.5", 37342), ("-2.0", 37246), ("1.5", 18939), ("-0.2", 18908), ]; let common_values_hex = &[ ("0x1.0#1", 75012), ("-0x1.0#1", 74560), ("0x0.0", 49991), ("-0x0.0", 49908), ("0x0.8#1", 37822), ("0x2.0#1", 37501), ("-0x0.8#1", 37342), ("-0x2.0#1", 37246), ("0x1.8#2", 18939), ("-0x0.4#1", 18908), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.15755047615569168), standard_deviation: NiceFloat(1365.3366507063222), skewness: NiceFloat(296.763954633545), excess_kurtosis: NiceFloat(413698.88164587686), }; striped_random_finite_floats_helper( 1, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, special probability 1/10 let values = &[ "-2.00000000000727595760740716232528665608530686987", "-1.99999999999999999", "-2.0", "1.99999955296516418457031249999999999999990816", "-1.992248535", "1.75", "-2.0", "-0.49999999953433871269226074", "-1.9843754917383193414615082757658364469", "0.99999999", "0.0", "0.25000005867354957271587", "-1.99999999906867742711924491", "-0.500000119209289544709704599191368", "15.999985", "-7.5", "-3.9999999999999432", "-0.49999999999999999998644747284", "-0.5", "-0.53118896484", ]; let values_hex = &[ "-0x2.0000000007ffffffe00000000003dfffffffff0#158", "-0x1.ffffffffffffff#57", "-0x2.0#5", "0x1.fffff87ffffffffffffffffffffffffff800#145", "-0x1.fe03ffff8#34", "0x1.c00000#22", "-0x2.00000000000000#57", "-0x0.7ffffffe00000000000000#84", "-0x1.fc00083ffffffc000003f0000007ffc#123", "0x0.ffffffc#26", "0x0.0", "0x0.400000fc003fffe0000#75", "-0x1.fffffffc0000001ffffff#85", "-0x0.800001ffffffff8fffefffffffe#107", "0xf.ffff0#21", "-0x7.8#4", "-0x3.fffffffffff000#55", "-0x0.7fffffffffffffffc0000000#94", "-0x0.8000#13", "-0x0.87fc00000#36", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("1.0", 2360), ("-1.0", 2302), ("-1.0", 1217), ("2.0", 1209), ("1.0", 1193), ("-0.5", 1177), ("0.5", 1158), ("-2.0", 1158), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("0x1.0#1", 2360), ("-0x1.0#1", 2302), ("-0x1.0#2", 1217), ("0x2.0#1", 1209), ("0x1.0#2", 1193), ("-0x0.8#1", 1177), ("0x0.8#1", 1158), ("-0x2.0#1", 1158), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.10376383630935192), standard_deviation: NiceFloat(1990.1410792105194), skewness: NiceFloat(339.3581426358755), excess_kurtosis: NiceFloat(463204.1189100673), }; striped_random_finite_floats_helper( 1, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, special probability 1/10 let values = &[ "-5.0e13", "-2.8e-16", "-0.5", "3.0e8", "-1.4e-6", "0.25", "-1.0e-11", "-6.0e-17", "-3.0e10", "1.7e-13", "0.0", "3.09e20", "-1.6e-29", "-4.7e28", "1.0e-8", "-2.5e-21", "-9.0e9", "-1.0e43", "-0.1", "-0.1", ]; let values_hex = &[ "-0x3.0E+11#3", "-0x1.4E-13#3", "-0x0.8#2", "0x1.2E+7#5", "-0x0.000018#2", "0x0.4#3", "-0x1.0E-9#1", "-0x4.0E-14#3", "-0x8.0E+8#1", "0x3.0E-11#2", "0x0.0", "0x1.0cE+17#9", "-0x1.4E-24#3", "-0x9.8E+23#5", "0x4.0E-7#1", "-0xc.0E-18#2", "-0x2.0E+8#2", "-0x8.0E+35#1", "-0x0.2#2", "-0x0.2#2", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("1.0", 1791), ("0.5", 1788), ("-1.0", 1782), ("-4.0", 1778), ("-0.5", 1727), ("2.0", 1695), ("4.0", 1690), ("2.0e1", 1689), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("0x1.0#1", 1791), ("0x0.8#1", 1788), ("-0x1.0#1", 1782), ("-0x4.0#1", 1778), ("-0x0.8#1", 1727), ("0x2.0#1", 1695), ("0x4.0#1", 1690), ("0x1.0E+1#1", 1689), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.789929787900277e243), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_finite_floats_helper( 64, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, special probability 1/10 let values = &[ "-35184372088959.9999998807907104492318790106824386", "-4.44089209850062613e-16", "-0.5", "536870791.99999999999999999999999999999997535", "-1.8999562598e-6", "0.4375", "-1.45519152283668518e-11", "-1.11022302359118077473234707e-16", "-68182622719.99999809265147909798093515", "2.27373672e-13", "0.0", "295147974448853809152.0", "-2.5243548955317434286847727e-29", "-39614090701865134055025016831.9995", "2.980229e-8", "-3.2e-21", "-17179869183.9997559", "-2.2300745198530623140931255363e43", "-0.125", "-0.132797241211", ]; let values_hex = &[ "-0x20000000007f.fffffe00000000003dfffffffff0#158", "-0x1.ffffffffffffffE-13#57", "-0x0.80#5", "0x1fffff87.ffffffffffffffffffffffffff800#145", "-0x0.00001fe03ffff8#34", "0x0.700000#22", "-0x1.00000000000000E-9#57", "-0x7.ffffffe00000000000000E-14#84", "-0xfe00041ff.ffffe000001f8000003ffe#123", "0x3.ffffffE-11#26", "0x0.0", "0x1000003f000ffff800.00#75", "-0x1.fffffffc0000001ffffffE-24#85", "-0x800001ffffffff8fffefffff.ffe#107", "0x7.ffff8E-7#21", "-0xf.0E-18#4", "-0x3ffffffff.fff000#55", "-0xf.fffffffffffffff80000000E+35#94", "-0x0.2000#13", "-0x0.21ff000000#36", ]; let common_values = &[ ("0.0", 49991), ("-0.0", 49908), ("-2.0e1", 77), ("2.0", 66), ("-2.0", 61), ("-8.0", 61), ("-3.0e1", 59), ("-0.2", 58), ("0.5", 57), ("4.0e3", 57), ]; let common_values_hex = &[ ("0x0.0", 49991), ("-0x0.0", 49908), ("-0x1.0E+1#1", 77), ("0x2.0#1", 66), ("-0x2.0#1", 61), ("-0x8.0#1", 61), ("-0x2.0E+1#1", 59), ("-0x0.4#1", 58), ("0x0.8#1", 57), ("0x1.0E+3#1", 57), ]; let sample_median = ("0.0", None); let sample_median_hex = ("0x0.0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.7908037774743073e243), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_finite_floats_helper( 64, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_finite_floats_fail_1() { striped_random_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_2() { striped_random_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_3() { striped_random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_4() { striped_random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_5() { striped_random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_6() { striped_random_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_finite_floats_fail_7() { striped_random_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 1, 0); } ================================================ FILE: malachite-float/tests/random/striped_random_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, mean_special_p_numerator: u64, mean_special_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, mean_special_p_numerator, mean_special_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } #[test] fn test_striped_random_floats() { // mean |sci_exponent| 1, mean precision 2, special probability 1/10 let values = &[ "1.0", "0.2", "0.0", "NaN", "-0.2", "-1.0", "-1.0", "-1.5", "2.0", "0.2", "-1.0", "-0.2", "-2.0", "Infinity", "-0.5", "-1.5", "-0.2", "NaN", "0.5", "-0.0", ]; let values_hex = &[ "0x1.0#1", "0x0.4#1", "0x0.0", "NaN", "-0x0.4#1", "-0x1.0#2", "-0x1.0#1", "-0x1.8#2", "0x2.0#1", "0x0.4#1", "-0x1.0#3", "-0x0.4#2", "-0x2.0#1", "Infinity", "-0x0.8#1", "-0x1.8#2", "-0x0.4#2", "NaN", "0x0.8#1", "-0x0.0", ]; let common_values = &[ ("-1.0", 67626), ("1.0", 67293), ("0.0", 45033), ("-0.0", 44760), ("-2.0", 33918), ("2.0", 33760), ("0.5", 33658), ("Infinity", 33640), ("-0.5", 33629), ("NaN", 33393), ]; let common_values_hex = &[ ("-0x1.0#1", 67626), ("0x1.0#1", 67293), ("0x0.0", 45033), ("-0x0.0", 44760), ("-0x2.0#1", 33918), ("0x2.0#1", 33760), ("0x0.8#1", 33658), ("Infinity", 33640), ("-0x0.8#1", 33629), ("NaN", 33393), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_floats_helper( 1, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64, special probability 1/10 let values = &[ "1.99999", "0.4999999850988", "0.0", "NaN", "-0.25000000005820766091346740721", "-1.0", "-1.99999999999999999999978989612421431724891016", "-1.0000000000145519117589199127777235073172084570819473318104658", "3.97", "0.250057220575342853408074206771059911", "-1.0000305175708774606", "-0.49988", "-2.999969497323036190378209298059007584907370931259", "Infinity", "-0.9999999999999996", "-1.5", "-0.25", "NaN", "0.531249999999943", "-0.0", ]; let values_hex = &[ "0x1.ffff8#18", "0x0.7fffffc0000#40", "0x0.0", "NaN", "-0x0.400000003fffffffffffffff#95", "-0x1.00000000#30", "-0x1.ffffffffffffffffff01fffffc0001ffffff8#146", "-0x1.000000000fffffc0000003ffffffffffffffffffffff80003ff#205", "0x3.f8#7", "0x0.4003c0007ff0000000003dfffffffe#118", "-0x1.0001fffff807ffc0#62", "-0x0.7ff8#14", "-0x2.fffe003fffffffc000000000ffffff000001ffff#162", "Infinity", "-0x0.ffffffffffffe#51", "-0x1.8#2", "-0x0.400000#20", "NaN", "0x0.87fffffffff0#48", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("1.0", 2133), ("-1.0", 2122), ("-2.0", 1103), ("0.5", 1094), ("2.0", 1075), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x1.0#1", 2133), ("-0x1.0#1", 2122), ("-0x2.0#1", 1103), ("0x0.8#1", 1094), ("0x2.0#1", 1075), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_floats_helper( 1, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2, special probability 1/10 let values = &[ "5.0e11", "7.0e122", "0.0", "NaN", "-2.0e25", "-2.0e21", "-2.0e-9", "-4.0e33", "4.0e-9", "5.0e2", "-4.0e-16", "-7.0e-18", "-2.0e-19", "Infinity", "-2.0e50", "-1.6e12", "-2.0e-28", "NaN", "0.02", "-0.0", ]; let values_hex = &[ "0x8.0E+9#1", "0x1.0E+102#1", "0x0.0", "NaN", "-0x1.0E+21#1", "-0x8.0E+17#2", "-0x8.0E-8#1", "-0xc.0E+27#2", "0x1.0E-7#1", "0x2.0E+2#1", "-0x2.0E-13#3", "-0x8.0E-15#2", "-0x4.0E-16#1", "Infinity", "-0x8.0E+41#1", "-0x1.8E+10#2", "-0x1.0E-23#2", "NaN", "0x0.04#1", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0.5", 1583), ("-1.0", 1560), ("2.0", 1542), ("-2.0", 1523), ("1.0", 1518), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x0.8#1", 1583), ("-0x1.0#1", 1560), ("0x2.0#1", 1542), ("-0x2.0#1", 1523), ("0x1.0#1", 1518), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_floats_helper( 64, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64, special probability 1/10 let values = &[ "1.099507e12", "1.322111898178e123", "0.0", "NaN", "-19342813118337666422669311.999", "-2.361183241e21", "-3.72529029846191406249960865103493317449262395e-9", "-2596148429305192737121006105133055.9999999999999999999864475761", "7.4e-9", "512.117187738302163779735975467130698", "-4.441027623740001309e-16", "-1.38744e-17", "-3.252573446387882516080103398476707881754715262554e-19", "Infinity", "-3.74144419156711e50", "-1.6e12", "-2.019484e-28", "NaN", "0.0166015624999982", "-0.0", ]; let values_hex = &[ "0xf.fffcE+9#18", "0x1.ffffff0000E+102#40", "0x0.0", "NaN", "-0x100000000fffffffffffff.ffc#95", "-0x8.0000000E+17#30", "-0xf.fffffffffffffffff80fffffe0000ffffffcE-8#146", "-0x8000000007ffffe0000001ffffff.ffffffffffffffffc0001ff8#205", "0x1.fcE-7#7", "0x200.1e0003ff8000000001effffffff#118", "-0x2.0003fffff00fff8E-13#62", "-0xf.ff0E-15#14", "-0x5.fffc007fffffff8000000001fffffe000003fffeE-16#162", "Infinity", "-0xf.fffffffffffeE+41#51", "-0x1.8E+10#2", "-0x1.00000E-23#20", "NaN", "0x0.043fffffffff80#48", "-0x0.0", ]; let common_values = &[ ("0.0", 45033), ("-0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0.00003", 60), ("-0.5", 57), ("-6.0e1", 56), ("-5.0e2", 55), ("8.0", 54), ]; let common_values_hex = &[ ("0x0.0", 45033), ("-0x0.0", 44760), ("Infinity", 33640), ("NaN", 33393), ("-Infinity", 33191), ("0x0.0002#1", 60), ("-0x0.8#1", 57), ("-0x4.0E+1#1", 56), ("-0x2.0E+2#1", 55), ("0x8.0#1", 54), ]; let sample_median = ("NaN", None); let sample_median_hex = ("NaN", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_floats_helper( 64, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_floats_fail_1() { striped_random_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_2() { striped_random_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_3() { striped_random_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_4() { striped_random_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_5() { striped_random_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_6() { striped_random_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_floats_fail_7() { striped_random_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 1, 0); } ================================================ FILE: malachite-float/tests/random/striped_random_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_negative_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_negative_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_negative_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_striped_random_negative_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "-1.5", "-1.0", "-2.0", "-1.0", "-1.0", "-2.0", "-2.0", "-1.8", "-2.0", "-1.0", "-2.0", "-2.0", "-4.0", "-1.0", "-1.0", "-2.0", "-0.1", "-1.0", "-0.2", "-1.0", ]; let values_hex = &[ "-0x1.8#2", "-0x1.0#1", "-0x2.0#2", "-0x1.0#2", "-0x1.0#1", "-0x2.0#1", "-0x2.0#1", "-0x1.c#3", "-0x2.0#1", "-0x1.0#1", "-0x2.0#1", "-0x2.0#1", "-0x4.0#1", "-0x1.0#1", "-0x1.0#3", "-0x2.0#4", "-0x0.2#1", "-0x1.0#1", "-0x0.4#1", "-0x1.0#3", ]; let common_values = &[ ("-1.0", 166114), ("-0.5", 83464), ("-2.0", 83434), ("-1.0", 42010), ("-0.2", 41531), ("-1.5", 41521), ("-4.0", 41483), ("-3.0", 21125), ("-0.1", 20888), ("-8.0", 20800), ]; let common_values_hex = &[ ("-0x1.0#1", 166114), ("-0x0.8#1", 83464), ("-0x2.0#1", 83434), ("-0x1.0#2", 42010), ("-0x0.4#1", 41531), ("-0x1.8#2", 41521), ("-0x4.0#1", 41483), ("-0x3.0#2", 21125), ("-0x0.2#1", 20888), ("-0x8.0#1", 20800), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.102812885245132), standard_deviation: NiceFloat(351.5541728670195), skewness: NiceFloat(-274.1565025440714), excess_kurtosis: NiceFloat(92676.98806519402), }; striped_random_negative_finite_floats_helper( 1, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "-1.8", "-1.999992251396406572893", "-2.0", "-1.000007629394303879793997", "-1.0", "-3.9999999999999999861222122955831198138315944982", "-2.00048828124999999999322373803755273042776921295151896098423", "-1.0000609", "-3.98439049720059301762375898", "-1.9921875", "-3.99609375186263", "-3.9921875", "-4.0", "-1.998046875", "-1.0000000894069671630893256317890172009801151", "-3.9999997615814209", "-0.2499990481", "-1.0000000000000000034694465383634065199217", "-0.49999999998545", "-1.9852905", ]; let values_hex = &[ "-0x1.c#3", "-0x1.ffff7e00003ffffffc#71", "-0x2.000000000#38", "-0x1.00007fffffc0003ffff8#79", "-0x1.00000#19", "-0x3.ffffffffffffff0000001fffffffffff8007fe#153", "-0x2.001fffffffffffffe000007fffffff0000000000000001ff8#195", "-0x1.0003fe#24", "-0x3.fc0103fff83fffffffff00#89", "-0x1.fe000000000000#57", "-0x3.ff000007fffc#48", "-0x3.fe000000#31", "-0x4.00000000000000#57", "-0x1.ff8000000000#48", "-0x1.00000180000000000fffffffffffff800000#145", "-0x3.fffffc0000000#54", "-0x0.3ffff0078#31", "-0x1.000000000000003fffff800001ffffff8#132", "-0x0.7ffffffff00#43", "-0x1.fc3c00#24", ]; let common_values = &[ ("-1.0", 5069), ("-0.5", 2623), ("-2.0", 2623), ("-1.0", 2567), ("-1.5", 2547), ("-1.8", 2419), ("-1.0", 2408), ("-1.9", 2381), ("-1.0", 2336), ("-1.0", 2240), ]; let common_values_hex = &[ ("-0x1.0#1", 5069), ("-0x0.8#1", 2623), ("-0x2.0#1", 2623), ("-0x1.0#2", 2567), ("-0x1.8#2", 2547), ("-0x1.c#3", 2419), ("-0x1.0#3", 2408), ("-0x1.e#4", 2381), ("-0x1.0#4", 2336), ("-0x1.00#6", 2240), ]; let sample_median = ("-1.4999997616", Some("-1.4999997616")); let sample_median_hex = ("-0x1.7ffffc00#33", Some("-0x1.7ffffc00#32")); let sample_moment_stats = MomentStats { mean: NiceFloat(-9.303344556597335), standard_deviation: NiceFloat(516.4696271945669), skewness: NiceFloat(-332.951705809113), excess_kurtosis: NiceFloat(144341.98602578667), }; striped_random_negative_finite_floats_helper( 1, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "-3.0e-37", "-8.0e-34", "-4.0e-6", "-3.0e-45", "-2.0e15", "-5.0e-10", "-2.0e4", "-0.11", "-0.0001", "-1.0e14", "-2.0e34", "-9.0e-13", "-0.0001", "-9.0e9", "-1.3e33", "-0.12", "-0.00003", "-5.0e18", "-0.06", "-5.0e8", ]; let values_hex = &[ "-0x6.0E-31#2", "-0x4.0E-28#1", "-0x0.00004#2", "-0x1.0E-37#2", "-0x8.0E+12#1", "-0x2.0E-8#1", "-0x4.0E+3#1", "-0x0.1c#3", "-0x0.0008#1", "-0x8.0E+11#1", "-0x4.0E+28#1", "-0x1.0E-10#1", "-0x0.0008#1", "-0x2.0E+8#1", "-0x4.0E+27#3", "-0x0.20#4", "-0x0.0002#1", "-0x4.0E+15#1", "-0x0.1#1", "-0x2.0E+7#3", ]; let common_values = &[ ("-1.0", 3831), ("-0.2", 3830), ("-0.5", 3826), ("-2.0", 3753), ("-4.0", 3716), ("-8.0", 3653), ("-0.1", 3639), ("-0.06", 3637), ("-3.0e1", 3632), ("-2.0e1", 3617), ]; let common_values_hex = &[ ("-0x1.0#1", 3831), ("-0x0.4#1", 3830), ("-0x0.8#1", 3826), ("-0x2.0#1", 3753), ("-0x4.0#1", 3716), ("-0x8.0#1", 3653), ("-0x0.2#1", 3639), ("-0x0.1#1", 3637), ("-0x2.0E+1#1", 3632), ("-0x1.0E+1#1", 3617), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.952075737355551e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_finite_floats_helper( 64, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "-3.3e-37", "-1.5407379862027135753234e-33", "-3.81469726562e-6", "-2.80261831076667765237162e-45", "-2.2518e15", "-9.3132257461547851239382575628885994987366592936e-10", "-16387.9999999999999999444888620036319676642853924988433283828", "-0.062503807", "-0.000243187896557653382423325133", "-280375465082880.0", "-4.1497810068414e34", "-1.81543669e-12", "-0.0001220703125", "-17163091968.0", "-1298074330690585590141422900609023.99951171875", "-0.24999998509883881", "-0.00006103492385", "-4611686018427387919.999998092651821934844", "-0.12499999999636", "-1.06584474e9", ]; let values_hex = &[ "-0x7.0E-31#3", "-0x7.fffdf80000fffffffE-28#71", "-0x0.00004000000000#38", "-0x1.00007fffffc0003ffff8E-37#79", "-0x8.0000E+12#19", "-0x3.ffffffffffffff0000001fffffffffff8007feE-8#153", "-0x4003.fffffffffffffc00000fffffffe0000000000000003ff#195", "-0x0.10003fe#24", "-0x0.000ff0040fffe0fffffffffc00#89", "-0xff0000000000.000#57", "-0x7.fe00000ffff8E+28#48", "-0x1.ff000000E-10#31", "-0x0.000800000000000000#57", "-0x3ff000000.0000#48", "-0x400000600000000003ffffffffff.ffe000000#145", "-0x0.3fffffc0000000#54", "-0x0.0003ffff0078#31", "-0x400000000000000f.ffffe000007fffffe0#132", "-0x0.1ffffffffc00#43", "-0x3.f87800E+7#24", ]; let common_values = &[ ("-2.0", 130), ("-2.0e1", 129), ("-0.2", 122), ("-3.0e1", 117), ("-0.004", 116), ("-1.0e5", 114), ("-0.02", 112), ("-0.00002", 112), ("-0.1", 109), ("-8.0", 108), ]; let common_values_hex = &[ ("-0x2.0#1", 130), ("-0x1.0E+1#1", 129), ("-0x0.4#1", 122), ("-0x2.0E+1#1", 117), ("-0x0.01#1", 116), ("-0x2.0E+4#1", 114), ("-0x0.04#1", 112), ("-0x0.0001#1", 112), ("-0x0.2#1", 109), ("-0x8.0#1", 108), ]; let sample_median = ("-1.1249998807907122255", Some("-1.12499988079071")); let sample_median_hex = ("-0x1.1ffffe0000007ffe#64", Some("-0x1.1ffffe000000#49")); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.8054101301847865e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_finite_floats_helper( 64, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_1() { striped_random_negative_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_2() { striped_random_negative_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_3() { striped_random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_4() { striped_random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_5() { striped_random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1); } #[test] #[should_panic] fn striped_random_negative_finite_floats_fail_6() { striped_random_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1); } ================================================ FILE: malachite-float/tests/random/striped_random_non_negative_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_non_negative_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_non_negative_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_non_negative_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_striped_random_non_negative_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "8.0", "1.0", "0.8", "0.0", "4.0", "3.5", "1.0", "2.0", "0.5", "0.5", "2.0", "3.0e1", "0.5", "0.0", "1.0", "3.0", "0.5", "0.0", "1.0", "0.1", ]; let values_hex = &[ "0x8.0#1", "0x1.0#1", "0x0.c#2", "0x0.0", "0x4.0#1", "0x3.8#3", "0x1.0#1", "0x2.0#1", "0x0.8#2", "0x0.800#12", "0x2.0#1", "0x2.0E+1#1", "0x0.8#1", "0x0.0", "0x1.0#1", "0x3.0#2", "0x0.8#1", "0x0.0", "0x1.0#2", "0x0.2#1", ]; let common_values = &[ ("1.0", 149586), ("0.0", 100224), ("2.0", 74929), ("0.5", 74827), ("1.0", 38123), ("4.0", 37612), ("0.2", 37602), ("1.5", 37379), ("0.5", 18928), ("0.8", 18840), ]; let common_values_hex = &[ ("0x1.0#1", 149586), ("0x0.0", 100224), ("0x2.0#1", 74929), ("0x0.8#1", 74827), ("0x1.0#2", 38123), ("0x4.0#1", 37612), ("0x0.4#1", 37602), ("0x1.8#2", 37379), ("0x0.8#2", 18928), ("0x0.c#2", 18840), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.756520872349506), standard_deviation: NiceFloat(1567.2504048767603), skewness: NiceFloat(588.0046776041995), excess_kurtosis: NiceFloat(368204.8297165849), }; striped_random_non_negative_finite_floats_helper( 1, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "15.99996948242187500002710174558968740475801788817904844007080242775028492173761449748527\ 50344620578", "1.0", "0.9999961855", "0.0", "7.9999923707218827326204245", "3.99902343750000005551115123125625546225", "1.999999963", "3.9687500000000568434188608076", "0.99999999999999645", "0.5", "3.5", "63.9375", "0.5019531249", "0.0", "1.5", "3.8", "0.5", "0.0", "1.0", "0.23", ]; let values_hex = &[ "0xf.fffe0000000000007ffc0000000007ffffff8003fe00000000000003fff0003ffffffff8ff000000#324", "0x1.0#1", "0x0.ffffc001#32", "0x0.0", "0x7.ffff80007fff9f80000fe#86", "0x3.ffc00000000003ffffffffffe01fffe#125", "0x1.ffffff6#28", "0x3.f8000000000fffffffffffe#93", "0x0.ffffffffffff00#55", "0x0.800#12", "0x3.8000#16", "0x3f.f00000000000000#65", "0x0.807fffff8#33", "0x0.0", "0x1.8#2", "0x3.c#4", "0x0.8000000000#37", "0x0.0", "0x1.00#9", "0x0.3c#4", ]; let common_values = &[ ("0.0", 100224), ("1.0", 4643), ("2.0", 2373), ("0.5", 2353), ("1.5", 2346), ("1.0", 2275), ("1.0", 2183), ("1.8", 2131), ("1.0", 2125), ("1.9", 2082), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x1.0#1", 4643), ("0x2.0#1", 2373), ("0x0.8#1", 2353), ("0x1.8#2", 2346), ("0x1.0#2", 2275), ("0x1.0#3", 2183), ("0x1.c#3", 2131), ("0x1.0#4", 2125), ("0x1.e#4", 2082), ]; let sample_median = ( "1.000007629394531249993647252693644355720408559059500172572", Some("1.000007629394531249997"), ); let sample_median_hex = ( "0x1.00007fffffffffffe1fffff000000000000000000000000#189", Some("0x1.00007ffffffffffff#69"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(11.589283909473794), standard_deviation: NiceFloat(2398.6644729176514), skewness: NiceFloat(671.6561608456597), excess_kurtosis: NiceFloat(499631.39656685427), }; striped_random_non_negative_finite_floats_helper( 1, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "1.0e9", "2.0e-6", "24.0", "0.0", "5.0e-7", "0.11", "8.0e22", "7.0e19", "0.03", "3.355e7", "2.0e38", "7.0e-9", "2.0e15", "0.0", "3.0e11", "2.0e-8", "6.0e14", "0.0", "0.03", "2.0e-34", ]; let values_hex = &[ "0x4.0E+7#1", "0x0.00002#1", "0x18.0#2", "0x0.0", "0x8.0E-6#1", "0x0.1c#3", "0x1.0E+19#1", "0x4.0E+16#1", "0x0.08#2", "0x2.000E+6#12", "0x8.0E+31#1", "0x2.0E-7#1", "0x8.0E+12#1", "0x0.0", "0x4.0E+9#1", "0x6.0E-7#2", "0x2.0E+12#1", "0x0.0", "0x0.08#2", "0x1.0E-28#1", ]; let common_values = &[ ("0.0", 100224), ("1.0", 3531), ("2.0", 3503), ("4.0", 3399), ("0.5", 3381), ("0.1", 3375), ("0.2", 3369), ("0.06", 3330), ("8.0", 3283), ("2.0e1", 3250), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x1.0#1", 3531), ("0x2.0#1", 3503), ("0x4.0#1", 3399), ("0x0.8#1", 3381), ("0x0.2#1", 3375), ("0x0.4#1", 3369), ("0x0.1#1", 3330), ("0x8.0#1", 3283), ("0x1.0E+1#1", 3250), ]; let sample_median = ("0.007", None); let sample_median_hex = ("0x0.01c#3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.2374143686309695e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_negative_finite_floats_helper( 64, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "2147479552.000000000003637534717881863696837550734749938828247260989527393548280429992335\ 3285806191", "2.0e-6", "31.999877937", "0.0", "9.5367340692542585523371988e-7", "0.124969482421875001734723475976757983195", "1.511157246e23", "146421031085071663103.99999999", "0.062499999999999778", "3.355e7", "2.97747e38", "1.48866092786192893982e-8", "2.2605959062e15", "0.0", "4.0e11", "2.8e-8", "5.6294995342e14", "0.0", "0.0312", "3.6e-34", ]; let values_hex = &[ "0x7ffff000.0000000003ffe0000000003ffffffc001ff00000000000001fff8001ffffffffc7f8000000\ #324", "0x0.00002#1", "0x1f.fff8002#32", "0x0.0", "0xf.ffff0000ffff3f00001fcE-6#86", "0x0.1ffe00000000001fffffffffff00ffff#125", "0x1.ffffff6E+19#28", "0x7f0000000001fffff.ffffffc#93", "0x0.0ffffffffffff00#55", "0x2.000E+6#12", "0xe.000E+31#16", "0x3.ff00000000000000E-7#65", "0x8.07fffff8E+12#33", "0x0.0", "0x6.0E+9#2", "0x7.8E-7#4", "0x2.000000000E+12#37", "0x0.0", "0x0.0800#9", "0x1.eE-28#4", ]; let common_values = &[ ("0.0", 100224), ("8.0", 129), ("4.0", 120), ("2.0", 107), ("0.06", 107), ("1.0e3", 106), ("3.0e1", 105), ("4.0e3", 104), ("0.5", 102), ("1.0e2", 102), ]; let common_values_hex = &[ ("0x0.0", 100224), ("0x8.0#1", 129), ("0x4.0#1", 120), ("0x2.0#1", 107), ("0x0.1#1", 107), ("0x4.0E+2#1", 106), ("0x2.0E+1#1", 105), ("0x1.0E+3#1", 104), ("0x0.8#1", 102), ("0x8.0E+1#1", 102), ]; let sample_median = ( "0.007812499999971581759", Some("0.007812499999971581759170316330143455009"), ); let sample_median_hex = ( "0x0.01fffffffff8003ffc#63", Some("0x0.01fffffffff8003ffc00f800000000ff#121"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(2.238472715881828e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_negative_finite_floats_helper( 64, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_1() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_2() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_3() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_4() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_5() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_6() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_7() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_non_negative_finite_floats_fail_8() { striped_random_non_negative_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 1, 0); } ================================================ FILE: malachite-float/tests/random/striped_random_non_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_non_positive_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_non_positive_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, zero_p_numerator: u64, zero_p_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_non_positive_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, zero_p_numerator, zero_p_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_striped_random_non_positive_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "-8.0", "-1.0", "-0.8", "-0.0", "-4.0", "-3.5", "-1.0", "-2.0", "-0.5", "-0.5", "-2.0", "-3.0e1", "-0.5", "-0.0", "-1.0", "-3.0", "-0.5", "-0.0", "-1.0", "-0.1", ]; let values_hex = &[ "-0x8.0#1", "-0x1.0#1", "-0x0.c#2", "-0x0.0", "-0x4.0#1", "-0x3.8#3", "-0x1.0#1", "-0x2.0#1", "-0x0.8#2", "-0x0.800#12", "-0x2.0#1", "-0x2.0E+1#1", "-0x0.8#1", "-0x0.0", "-0x1.0#1", "-0x3.0#2", "-0x0.8#1", "-0x0.0", "-0x1.0#2", "-0x0.2#1", ]; let common_values = &[ ("-1.0", 149586), ("-0.0", 100224), ("-2.0", 74929), ("-0.5", 74827), ("-1.0", 38123), ("-4.0", 37612), ("-0.2", 37602), ("-1.5", 37379), ("-0.5", 18928), ("-0.8", 18840), ]; let common_values_hex = &[ ("-0x1.0#1", 149586), ("-0x0.0", 100224), ("-0x2.0#1", 74929), ("-0x0.8#1", 74827), ("-0x1.0#2", 38123), ("-0x4.0#1", 37612), ("-0x0.4#1", 37602), ("-0x1.8#2", 37379), ("-0x0.8#2", 18928), ("-0x0.c#2", 18840), ]; let sample_median = ("-1.0", None); let sample_median_hex = ("-0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.756520872349506), standard_deviation: NiceFloat(1567.2504048767603), skewness: NiceFloat(-588.0046776041995), excess_kurtosis: NiceFloat(368204.8297165849), }; striped_random_non_positive_finite_floats_helper( 1, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "-15.9999694824218750000271017455896874047580178881790484400708024277502849217376144974852\ 750344620578", "-1.0", "-0.9999961855", "-0.0", "-7.9999923707218827326204245", "-3.99902343750000005551115123125625546225", "-1.999999963", "-3.9687500000000568434188608076", "-0.99999999999999645", "-0.5", "-3.5", "-63.9375", "-0.5019531249", "-0.0", "-1.5", "-3.8", "-0.5", "-0.0", "-1.0", "-0.23", ]; let values_hex = &[ "-0xf.fffe0000000000007ffc0000000007ffffff8003fe00000000000003fff0003ffffffff8ff000000\ #324", "-0x1.0#1", "-0x0.ffffc001#32", "-0x0.0", "-0x7.ffff80007fff9f80000fe#86", "-0x3.ffc00000000003ffffffffffe01fffe#125", "-0x1.ffffff6#28", "-0x3.f8000000000fffffffffffe#93", "-0x0.ffffffffffff00#55", "-0x0.800#12", "-0x3.8000#16", "-0x3f.f00000000000000#65", "-0x0.807fffff8#33", "-0x0.0", "-0x1.8#2", "-0x3.c#4", "-0x0.8000000000#37", "-0x0.0", "-0x1.00#9", "-0x0.3c#4", ]; let common_values = &[ ("-0.0", 100224), ("-1.0", 4643), ("-2.0", 2373), ("-0.5", 2353), ("-1.5", 2346), ("-1.0", 2275), ("-1.0", 2183), ("-1.8", 2131), ("-1.0", 2125), ("-1.9", 2082), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x1.0#1", 4643), ("-0x2.0#1", 2373), ("-0x0.8#1", 2353), ("-0x1.8#2", 2346), ("-0x1.0#2", 2275), ("-0x1.0#3", 2183), ("-0x1.c#3", 2131), ("-0x1.0#4", 2125), ("-0x1.e#4", 2082), ]; let sample_median = ( "-1.000007629394531249997", Some("-1.000007629394531249993647252693644355720408559059500172572"), ); let sample_median_hex = ( "-0x1.00007ffffffffffff#69", Some("-0x1.00007fffffffffffe1fffff000000000000000000000000#189"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-11.589283909473794), standard_deviation: NiceFloat(2398.6644729176514), skewness: NiceFloat(-671.6561608456597), excess_kurtosis: NiceFloat(499631.39656685427), }; striped_random_non_positive_finite_floats_helper( 1, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "-1.0e9", "-2.0e-6", "-24.0", "-0.0", "-5.0e-7", "-0.11", "-8.0e22", "-7.0e19", "-0.03", "-3.355e7", "-2.0e38", "-7.0e-9", "-2.0e15", "-0.0", "-3.0e11", "-2.0e-8", "-6.0e14", "-0.0", "-0.03", "-2.0e-34", ]; let values_hex = &[ "-0x4.0E+7#1", "-0x0.00002#1", "-0x18.0#2", "-0x0.0", "-0x8.0E-6#1", "-0x0.1c#3", "-0x1.0E+19#1", "-0x4.0E+16#1", "-0x0.08#2", "-0x2.000E+6#12", "-0x8.0E+31#1", "-0x2.0E-7#1", "-0x8.0E+12#1", "-0x0.0", "-0x4.0E+9#1", "-0x6.0E-7#2", "-0x2.0E+12#1", "-0x0.0", "-0x0.08#2", "-0x1.0E-28#1", ]; let common_values = &[ ("-0.0", 100224), ("-1.0", 3531), ("-2.0", 3503), ("-4.0", 3399), ("-0.5", 3381), ("-0.1", 3375), ("-0.2", 3369), ("-0.06", 3330), ("-8.0", 3283), ("-2.0e1", 3250), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x1.0#1", 3531), ("-0x2.0#1", 3503), ("-0x4.0#1", 3399), ("-0x0.8#1", 3381), ("-0x0.2#1", 3375), ("-0x0.4#1", 3369), ("-0x0.1#1", 3330), ("-0x8.0#1", 3283), ("-0x1.0E+1#1", 3250), ]; let sample_median = ("-0.007", None); let sample_median_hex = ("-0x0.01c#3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.2374143686309695e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_positive_finite_floats_helper( 64, 1, 8, 1, 2, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "-2147479552.00000000000363753471788186369683755073474993882824726098952739354828042999233\ 53285806191", "-2.0e-6", "-31.999877937", "-0.0", "-9.5367340692542585523371988e-7", "-0.124969482421875001734723475976757983195", "-1.511157246e23", "-146421031085071663103.99999999", "-0.062499999999999778", "-3.355e7", "-2.97747e38", "-1.48866092786192893982e-8", "-2.2605959062e15", "-0.0", "-4.0e11", "-2.8e-8", "-5.6294995342e14", "-0.0", "-0.0312", "-3.6e-34", ]; let values_hex = &[ "-0x7ffff000.0000000003ffe0000000003ffffffc001ff00000000000001fff8001ffffffffc7f8000000\ #324", "-0x0.00002#1", "-0x1f.fff8002#32", "-0x0.0", "-0xf.ffff0000ffff3f00001fcE-6#86", "-0x0.1ffe00000000001fffffffffff00ffff#125", "-0x1.ffffff6E+19#28", "-0x7f0000000001fffff.ffffffc#93", "-0x0.0ffffffffffff00#55", "-0x2.000E+6#12", "-0xe.000E+31#16", "-0x3.ff00000000000000E-7#65", "-0x8.07fffff8E+12#33", "-0x0.0", "-0x6.0E+9#2", "-0x7.8E-7#4", "-0x2.000000000E+12#37", "-0x0.0", "-0x0.0800#9", "-0x1.eE-28#4", ]; let common_values = &[ ("-0.0", 100224), ("-8.0", 129), ("-4.0", 120), ("-2.0", 107), ("-0.06", 107), ("-1.0e3", 106), ("-3.0e1", 105), ("-4.0e3", 104), ("-0.5", 102), ("-1.0e2", 102), ]; let common_values_hex = &[ ("-0x0.0", 100224), ("-0x8.0#1", 129), ("-0x4.0#1", 120), ("-0x2.0#1", 107), ("-0x0.1#1", 107), ("-0x4.0E+2#1", 106), ("-0x2.0E+1#1", 105), ("-0x1.0E+3#1", 104), ("-0x0.8#1", 102), ("-0x8.0E+1#1", 102), ]; let sample_median = ( "-0.007812499999971581759170316330143455009", Some("-0.007812499999971581759"), ); let sample_median_hex = ( "-0x0.01fffffffff8003ffc00f800000000ff#121", Some("-0x0.01fffffffff8003ffc#63"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.238472715881828e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_positive_finite_floats_helper( 64, 1, 32, 1, 64, 1, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_1() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_2() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_3() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_4() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_5() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_6() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1, 1, 10); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_7() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_non_positive_finite_floats_fail_8() { striped_random_non_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 2, 1, 1, 0); } ================================================ FILE: malachite-float/tests/random/striped_random_nonzero_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_nonzero_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_nonzero_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_nonzero_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_striped_random_nonzero_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "-8.0", "-1.0", "-0.8", "4.0", "-3.5", "1.0", "-2.0", "-0.5", "-0.5", "2.0", "3.0e1", "0.5", "-1.0", "-3.0", "0.5", "-1.0", "-0.1", "-1.0", "-0.055", "-1.8", ]; let values_hex = &[ "-0x8.0#1", "-0x1.0#1", "-0x0.c#2", "0x4.0#1", "-0x3.8#3", "0x1.0#1", "-0x2.0#1", "-0x0.8#2", "-0x0.800#12", "0x2.0#1", "0x2.0E+1#1", "0x0.8#1", "-0x1.0#1", "-0x3.0#2", "0x0.8#1", "-0x1.0#2", "-0x0.2#1", "-0x1.0#1", "-0x0.0e#3", "-0x1.c#3", ]; let common_values = &[ ("1.0", 83167), ("-1.0", 83060), ("2.0", 41731), ("-2.0", 41688), ("0.5", 41643), ("-0.5", 41534), ("1.0", 21186), ("-4.0", 21185), ("-1.0", 21101), ("0.2", 21077), ]; let common_values_hex = &[ ("0x1.0#1", 83167), ("-0x1.0#1", 83060), ("0x2.0#1", 41731), ("-0x2.0#1", 41688), ("0x0.8#1", 41643), ("-0x0.8#1", 41534), ("0x1.0#2", 21186), ("-0x4.0#1", 21185), ("-0x1.0#2", 21101), ("0x0.4#1", 21077), ]; let sample_median = ("0.002", None); let sample_median_hex = ("0x0.008#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.1181422910011878), standard_deviation: NiceFloat(1654.3094882610405), skewness: NiceFloat(-398.68071157281685), excess_kurtosis: NiceFloat(306701.41416153224), }; striped_random_nonzero_finite_floats_helper( 1, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "-15.9999694824218750000271017455896874047580178881790484400708024277502849217376144974852\ 750344620578", "-1.0", "-0.9999961855", "7.9999923707218827326204245", "-3.99902343750000005551115123125625546225", "1.999999963", "-3.9687500000000568434188608076", "-0.99999999999999645", "-0.5", "3.5", "63.9375", "0.5019531249", "-1.5", "-3.8", "0.5", "-1.0", "-0.23", "-1.624816894531249999999999173", "-0.06225609778", "-1.9999", ]; let values_hex = &[ "-0xf.fffe0000000000007ffc0000000007ffffff8003fe00000000000003fff0003ffffffff8ff000000\ #324", "-0x1.0#1", "-0x0.ffffc001#32", "0x7.ffff80007fff9f80000fe#86", "-0x3.ffc00000000003ffffffffffe01fffe#125", "0x1.ffffff6#28", "-0x3.f8000000000fffffffffffe#93", "-0x0.ffffffffffff00#55", "-0x0.800#12", "0x3.8000#16", "0x3f.f00000000000000#65", "0x0.807fffff8#33", "-0x1.8#2", "-0x3.c#4", "0x0.8000000000#37", "-0x1.00#9", "-0x0.3c#4", "-0x1.9ff3ffffffffffffffff000#90", "-0x0.0ff003fff#32", "-0x1.fff8#14", ]; let common_values = &[ ("-1.0", 2594), ("1.0", 2582), ("2.0", 1322), ("0.5", 1316), ("-2.0", 1310), ("-1.5", 1300), ("1.0", 1293), ("-0.5", 1282), ("1.5", 1281), ("-1.0", 1251), ]; let common_values_hex = &[ ("-0x1.0#1", 2594), ("0x1.0#1", 2582), ("0x2.0#1", 1322), ("0x0.8#1", 1316), ("-0x2.0#1", 1310), ("-0x1.8#2", 1300), ("0x1.0#2", 1293), ("-0x0.8#1", 1282), ("0x1.8#2", 1281), ("-0x1.0#2", 1251), ]; let sample_median = ( "0.0019826889", Some("0.00198341719988093245774507522583003"), ); let sample_median_hex = ( "0x0.0081f0000#26", Some("0x0.0081fc3801ffffffffffffffffffc#106"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.535338105008931), standard_deviation: NiceFloat(2619.656937757806), skewness: NiceFloat(-395.5135549279457), excess_kurtosis: NiceFloat(376873.9371275132), }; striped_random_nonzero_finite_floats_helper( 1, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "-1.0e9", "-2.0e-6", "-24.0", "5.0e-7", "-0.11", "8.0e22", "-7.0e19", "-0.03", "-3.355e7", "2.0e38", "7.0e-9", "2.0e15", "-3.0e11", "-2.0e-8", "6.0e14", "-0.03", "-2.0e-34", "-6.0e14", "-4.4e30", "-2.7e57", ]; let values_hex = &[ "-0x4.0E+7#1", "-0x0.00002#1", "-0x18.0#2", "0x8.0E-6#1", "-0x0.1c#3", "0x1.0E+19#1", "-0x4.0E+16#1", "-0x0.08#2", "-0x2.000E+6#12", "0x8.0E+31#1", "0x2.0E-7#1", "0x8.0E+12#1", "-0x4.0E+9#1", "-0x6.0E-7#2", "0x2.0E+12#1", "-0x0.08#2", "-0x1.0E-28#1", "-0x2.0E+12#1", "-0x3.8E+25#3", "-0x7.0E+47#3", ]; let common_values = &[ ("1.0", 2018), ("-2.0", 2004), ("-1.0", 1938), ("4.0", 1933), ("0.5", 1901), ("0.1", 1900), ("-0.2", 1883), ("-4.0", 1875), ("0.2", 1874), ("2.0", 1873), ]; let common_values_hex = &[ ("0x1.0#1", 2018), ("-0x2.0#1", 2004), ("-0x1.0#1", 1938), ("0x4.0#1", 1933), ("0x0.8#1", 1901), ("0x0.2#1", 1900), ("-0x0.4#1", 1883), ("-0x4.0#1", 1875), ("0x0.4#1", 1874), ("0x2.0#1", 1873), ]; let sample_median = ("1.0e-122", None); let sample_median_hex = ("0x8.0E-102#2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.237414368630952e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_finite_floats_helper( 64, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "-2147479552.00000000000363753471788186369683755073474993882824726098952739354828042999233\ 53285806191", "-2.0e-6", "-31.999877937", "9.5367340692542585523371988e-7", "-0.124969482421875001734723475976757983195", "1.511157246e23", "-146421031085071663103.99999999", "-0.062499999999999778", "-3.355e7", "2.97747e38", "1.48866092786192893982e-8", "2.2605959062e15", "-4.0e11", "-2.8e-8", "5.6294995342e14", "-0.0312", "-3.6e-34", "-914690595094527.999999999534", "-5.050814702e30", "-3.1384e57", ]; let values_hex = &[ "-0x7ffff000.0000000003ffe0000000003ffffffc001ff00000000000001fff8001ffffffffc7f8000000\ #324", "-0x0.00002#1", "-0x1f.fff8002#32", "0xf.ffff0000ffff3f00001fcE-6#86", "-0x0.1ffe00000000001fffffffffff00ffff#125", "0x1.ffffff6E+19#28", "-0x7f0000000001fffff.ffffffc#93", "-0x0.0ffffffffffff00#55", "-0x2.000E+6#12", "0xe.000E+31#16", "0x3.ff00000000000000E-7#65", "0x8.07fffff8E+12#33", "-0x6.0E+9#2", "-0x7.8E-7#4", "0x2.000000000E+12#37", "-0x0.0800#9", "-0x1.eE-28#4", "-0x33fe7ffffffff.fffffffe00#90", "-0x3.fc00fffcE+25#32", "-0x7.ffeE+47#14", ]; let common_values = &[ ("-8.0", 73), ("1.0e3", 70), ("4.0", 69), ("2.0", 68), ("8.0", 68), ("-1.0e2", 67), ("-0.02", 65), ("-0.5", 64), ("2.0e1", 64), ("-4.0", 62), ]; let common_values_hex = &[ ("-0x8.0#1", 73), ("0x4.0E+2#1", 70), ("0x4.0#1", 69), ("0x2.0#1", 68), ("0x8.0#1", 68), ("-0x8.0E+1#1", 67), ("-0x0.04#1", 65), ("-0x0.8#1", 64), ("0x1.0E+1#1", 64), ("-0x4.0#1", 62), ]; let sample_median = ( "1.21019420636902759627106091036435e-122", Some("1.81527747811658e-122"), ); let sample_median_hex = ( "0x8.0003fffffffc00000000000000E-102#105", Some("0xc.000001fff00E-102#45"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.2384727158818326e242), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_finite_floats_helper( 64, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_1() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_2() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_3() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_4() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_5() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1); } #[test] #[should_panic] fn striped_random_nonzero_finite_floats_fail_6() { striped_random_nonzero_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1); } ================================================ FILE: malachite-float/tests/random/striped_random_positive_finite_floats.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_positive_finite_floats; use malachite_float::test_util::random::random_floats_helper_helper; fn striped_random_positive_finite_floats_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_precision_numerator: u64, mean_precision_denominator: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_positive_finite_floats( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, mean_precision_numerator, mean_precision_denominator, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ); } #[test] fn test_striped_random_positive_finite_floats() { // mean |sci_exponent| 1, mean precision 2 let values = &[ "1.5", "1.0", "2.0", "1.0", "1.0", "2.0", "2.0", "1.8", "2.0", "1.0", "2.0", "2.0", "4.0", "1.0", "1.0", "2.0", "0.1", "1.0", "0.2", "1.0", ]; let values_hex = &[ "0x1.8#2", "0x1.0#1", "0x2.0#2", "0x1.0#2", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x1.c#3", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x4.0#1", "0x1.0#1", "0x1.0#3", "0x2.0#4", "0x0.2#1", "0x1.0#1", "0x0.4#1", "0x1.0#3", ]; let common_values = &[ ("1.0", 166114), ("0.5", 83464), ("2.0", 83434), ("1.0", 42010), ("0.2", 41531), ("1.5", 41521), ("4.0", 41483), ("3.0", 21125), ("0.1", 20888), ("8.0", 20800), ]; let common_values_hex = &[ ("0x1.0#1", 166114), ("0x0.8#1", 83464), ("0x2.0#1", 83434), ("0x1.0#2", 42010), ("0x0.4#1", 41531), ("0x1.8#2", 41521), ("0x4.0#1", 41483), ("0x3.0#2", 21125), ("0x0.2#1", 20888), ("0x8.0#1", 20800), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.102812885245132), standard_deviation: NiceFloat(351.5541728670195), skewness: NiceFloat(274.1565025440714), excess_kurtosis: NiceFloat(92676.98806519402), }; striped_random_positive_finite_floats_helper( 1, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, mean precision 64 let values = &[ "1.8", "1.999992251396406572893", "2.0", "1.000007629394303879793997", "1.0", "3.9999999999999999861222122955831198138315944982", "2.00048828124999999999322373803755273042776921295151896098423", "1.0000609", "3.98439049720059301762375898", "1.9921875", "3.99609375186263", "3.9921875", "4.0", "1.998046875", "1.0000000894069671630893256317890172009801151", "3.9999997615814209", "0.2499990481", "1.0000000000000000034694465383634065199217", "0.49999999998545", "1.9852905", ]; let values_hex = &[ "0x1.c#3", "0x1.ffff7e00003ffffffc#71", "0x2.000000000#38", "0x1.00007fffffc0003ffff8#79", "0x1.00000#19", "0x3.ffffffffffffff0000001fffffffffff8007fe#153", "0x2.001fffffffffffffe000007fffffff0000000000000001ff8#195", "0x1.0003fe#24", "0x3.fc0103fff83fffffffff00#89", "0x1.fe000000000000#57", "0x3.ff000007fffc#48", "0x3.fe000000#31", "0x4.00000000000000#57", "0x1.ff8000000000#48", "0x1.00000180000000000fffffffffffff800000#145", "0x3.fffffc0000000#54", "0x0.3ffff0078#31", "0x1.000000000000003fffff800001ffffff8#132", "0x0.7ffffffff00#43", "0x1.fc3c00#24", ]; let common_values = &[ ("1.0", 5069), ("0.5", 2623), ("2.0", 2623), ("1.0", 2567), ("1.5", 2547), ("1.8", 2419), ("1.0", 2408), ("1.9", 2381), ("1.0", 2336), ("1.0", 2240), ]; let common_values_hex = &[ ("0x1.0#1", 5069), ("0x0.8#1", 2623), ("0x2.0#1", 2623), ("0x1.0#2", 2567), ("0x1.8#2", 2547), ("0x1.c#3", 2419), ("0x1.0#3", 2408), ("0x1.e#4", 2381), ("0x1.0#4", 2336), ("0x1.00#6", 2240), ]; let sample_median = ("1.4999997616", Some("1.4999997616")); let sample_median_hex = ("0x1.7ffffc00#32", Some("0x1.7ffffc00#33")); let sample_moment_stats = MomentStats { mean: NiceFloat(9.303344556597335), standard_deviation: NiceFloat(516.4696271945669), skewness: NiceFloat(332.951705809113), excess_kurtosis: NiceFloat(144341.98602578667), }; striped_random_positive_finite_floats_helper( 1, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 2 let values = &[ "3.0e-37", "8.0e-34", "4.0e-6", "3.0e-45", "2.0e15", "5.0e-10", "2.0e4", "0.11", "0.0001", "1.0e14", "2.0e34", "9.0e-13", "0.0001", "9.0e9", "1.3e33", "0.12", "0.00003", "5.0e18", "0.06", "5.0e8", ]; let values_hex = &[ "0x6.0E-31#2", "0x4.0E-28#1", "0x0.00004#2", "0x1.0E-37#2", "0x8.0E+12#1", "0x2.0E-8#1", "0x4.0E+3#1", "0x0.1c#3", "0x0.0008#1", "0x8.0E+11#1", "0x4.0E+28#1", "0x1.0E-10#1", "0x0.0008#1", "0x2.0E+8#1", "0x4.0E+27#3", "0x0.20#4", "0x0.0002#1", "0x4.0E+15#1", "0x0.1#1", "0x2.0E+7#3", ]; let common_values = &[ ("1.0", 3831), ("0.2", 3830), ("0.5", 3826), ("2.0", 3753), ("4.0", 3716), ("8.0", 3653), ("0.1", 3639), ("0.06", 3637), ("3.0e1", 3632), ("2.0e1", 3617), ]; let common_values_hex = &[ ("0x1.0#1", 3831), ("0x0.4#1", 3830), ("0x0.8#1", 3826), ("0x2.0#1", 3753), ("0x4.0#1", 3716), ("0x8.0#1", 3653), ("0x0.2#1", 3639), ("0x0.1#1", 3637), ("0x2.0E+1#1", 3632), ("0x1.0E+1#1", 3617), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.952075737355551e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_finite_floats_helper( 64, 1, 8, 1, 2, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, mean precision 64 let values = &[ "3.3e-37", "1.5407379862027135753234e-33", "3.81469726562e-6", "2.80261831076667765237162e-45", "2.2518e15", "9.3132257461547851239382575628885994987366592936e-10", "16387.9999999999999999444888620036319676642853924988433283828", "0.062503807", "0.000243187896557653382423325133", "280375465082880.0", "4.1497810068414e34", "1.81543669e-12", "0.0001220703125", "17163091968.0", "1298074330690585590141422900609023.99951171875", "0.24999998509883881", "0.00006103492385", "4611686018427387919.999998092651821934844", "0.12499999999636", "1.06584474e9", ]; let values_hex = &[ "0x7.0E-31#3", "0x7.fffdf80000fffffffE-28#71", "0x0.00004000000000#38", "0x1.00007fffffc0003ffff8E-37#79", "0x8.0000E+12#19", "0x3.ffffffffffffff0000001fffffffffff8007feE-8#153", "0x4003.fffffffffffffc00000fffffffe0000000000000003ff#195", "0x0.10003fe#24", "0x0.000ff0040fffe0fffffffffc00#89", "0xff0000000000.000#57", "0x7.fe00000ffff8E+28#48", "0x1.ff000000E-10#31", "0x0.000800000000000000#57", "0x3ff000000.0000#48", "0x400000600000000003ffffffffff.ffe000000#145", "0x0.3fffffc0000000#54", "0x0.0003ffff0078#31", "0x400000000000000f.ffffe000007fffffe0#132", "0x0.1ffffffffc00#43", "0x3.f87800E+7#24", ]; let common_values = &[ ("2.0", 130), ("2.0e1", 129), ("0.2", 122), ("3.0e1", 117), ("0.004", 116), ("1.0e5", 114), ("0.02", 112), ("0.00002", 112), ("0.1", 109), ("8.0", 108), ]; let common_values_hex = &[ ("0x2.0#1", 130), ("0x1.0E+1#1", 129), ("0x0.4#1", 122), ("0x2.0E+1#1", 117), ("0x0.01#1", 116), ("0x2.0E+4#1", 114), ("0x0.04#1", 112), ("0x0.0001#1", 112), ("0x0.2#1", 109), ("0x8.0#1", 108), ]; let sample_median = ("1.12499988079071", Some("1.1249998807907122255")); let sample_median_hex = ("0x1.1ffffe000000#49", Some("0x1.1ffffe0000007ffe#64")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.8054101301847865e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_finite_floats_helper( 64, 1, 32, 1, 64, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_1() { striped_random_positive_finite_floats(EXAMPLE_SEED, 1, 0, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_2() { striped_random_positive_finite_floats(EXAMPLE_SEED, 0, 1, 2, 1, 2, 1); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_3() { striped_random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 0); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_4() { striped_random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 1, 1, 1); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_5() { striped_random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 2, 3, 2, 1); } #[test] #[should_panic] fn striped_random_positive_finite_floats_fail_6() { striped_random_positive_finite_floats(EXAMPLE_SEED, 1, 1, 1, 0, 2, 1); } ================================================ FILE: malachite-float/tests/random/striped_random_positive_floats_with_precision.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_float::random::striped_random_positive_floats_with_precision; use malachite_float::test_util::random::{ random_floats_helper_helper, random_floats_helper_helper_no_common_values, }; fn striped_random_positive_floats_with_precision_helper( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, prec: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_common_values: &[(&str, usize)], expected_common_values_hex: &[(&str, usize)], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper( striped_random_positive_floats_with_precision( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, prec, ), expected_values, expected_values_hex, expected_common_values, expected_common_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } fn striped_random_positive_floats_with_precision_helper_no_common_values( mean_sci_exponent_abs_numerator: u64, mean_sci_exponent_abs_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, prec: u64, expected_values: &[&str], expected_values_hex: &[&str], expected_median: (&str, Option<&str>), expected_median_hex: (&str, Option<&str>), expected_moment_stats: MomentStats, ) { random_floats_helper_helper_no_common_values( striped_random_positive_floats_with_precision( EXAMPLE_SEED, mean_sci_exponent_abs_numerator, mean_sci_exponent_abs_denominator, mean_stripe_numerator, mean_stripe_denominator, prec, ), expected_values, expected_values_hex, expected_median, expected_median_hex, expected_moment_stats, ) } #[test] fn test_striped_random_positive_floats_with_precision() { // mean |sci_exponent| 1, precision 1 let values = &[ "1.0", "1.0", "2.0", "1.0", "1.0", "2.0", "2.0", "1.0", "2.0", "1.0", "2.0", "2.0", "4.0", "1.0", "1.0", "2.0", "0.1", "1.0", "0.2", "1.0", ]; let values_hex = &[ "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x1.0#1", "0x2.0#1", "0x2.0#1", "0x4.0#1", "0x1.0#1", "0x1.0#1", "0x2.0#1", "0x0.2#1", "0x1.0#1", "0x0.4#1", "0x1.0#1", ]; let common_values = &[ ("1.0", 333085), ("2.0", 167041), ("0.5", 166671), ("0.2", 83200), ("4.0", 83177), ("8.0", 41643), ("0.1", 41551), ("0.06", 20981), ("2.0e1", 20919), ("3.0e1", 10411), ]; let common_values_hex = &[ ("0x1.0#1", 333085), ("0x2.0#1", 167041), ("0x0.8#1", 166671), ("0x0.4#1", 83200), ("0x4.0#1", 83177), ("0x8.0#1", 41643), ("0x0.2#1", 41551), ("0x0.1#1", 20981), ("0x1.0E+1#1", 20919), ("0x2.0E+1#1", 10411), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(6.111051015726221), standard_deviation: NiceFloat(305.2547556508084), skewness: NiceFloat(297.86495510456103), excess_kurtosis: NiceFloat(112470.88988361698), }; striped_random_positive_floats_with_precision_helper( 1, 1, 8, 1, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, precision 10 let values = &[ "1.998", "1.0", "3.996", "1.123", "1.0", "3.996", "2.0", "1.971", "3.996", "1.998", "3.996", "3.996", "7.99", "1.0", "1.998", "2.0", "0.2498", "1.998", "0.2505", "1.0", ]; let values_hex = &[ "0x1.ff8#10", "0x1.000#10", "0x3.ff#10", "0x1.1f8#10", "0x1.000#10", "0x3.ff#10", "0x2.00#10", "0x1.f88#10", "0x3.ff#10", "0x1.ff8#10", "0x3.ff#10", "0x3.ff#10", "0x7.fe#10", "0x1.000#10", "0x1.ff8#10", "0x2.00#10", "0x0.3ff#10", "0x1.ff8#10", "0x0.402#10", "0x1.000#10", ]; let common_values = &[ ("1.998", 129180), ("1.0", 129087), ("2.0", 64918), ("0.999", 64782), ("3.996", 64781), ("0.5", 64602), ("7.99", 32474), ("0.4995", 32422), ("4.0", 32040), ("0.25", 32029), ]; let common_values_hex = &[ ("0x1.ff8#10", 129180), ("0x1.000#10", 129087), ("0x2.00#10", 64918), ("0x0.ffc#10", 64782), ("0x3.ff#10", 64781), ("0x0.800#10", 64602), ("0x7.fe#10", 32474), ("0x0.7fe#10", 32422), ("0x4.00#10", 32040), ("0x0.400#10", 32029), ]; let sample_median = ("1.5", None); let sample_median_hex = ("0x1.800#10", None); let sample_moment_stats = MomentStats { mean: NiceFloat(9.349869877794564), standard_deviation: NiceFloat(520.151410587591), skewness: NiceFloat(337.57543940728004), excess_kurtosis: NiceFloat(145252.3259106671), }; striped_random_positive_floats_with_precision_helper( 1, 1, 32, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 1, precision 64 let values = &[ "1.9999999925494194034", "1.2499999999999999999", "3.9999999925494194031", "1.0000000000018189893", "1.0000610351562482236", "3.9999389648437526645", "2.0", "1.9843750001164152663", "3.8750004768369308294", "1.9999923706636728582", "3.9999999999999431566", "3.9960937504656541819", "7.9999999999998863132", "1.0000305175781248889", "1.9999999999990905053", "2.0000000001164153216", "0.24999999906869163623", "1.9990539550781179222", "0.25", "1.0000000000001136799", ]; let values_hex = &[ "0x1.ffffffe000000006#64", "0x1.3ffffffffffffffe#64", "0x3.ffffffe000000000#64", "0x1.0000000001fffffe#64", "0x1.0003ffffffff8000#64", "0x3.fffc00000000c000#64", "0x2.0000000000000000#64", "0x1.fc0000007ffffc00#64", "0x3.e00007ffffc00000#64", "0x1.ffff80003fff0000#64", "0x3.fffffffffff00000#64", "0x3.ff000001fffe0000#64", "0x7.ffffffffffe00000#64", "0x1.0001fffffffff7fe#64", "0x1.ffffffffff000000#64", "0x2.000000007ffffffc#64", "0x0.3ffffffc0003ffffc#64", "0x1.ffc1fffffffe01fe#64", "0x0.40000000000000000#64", "0x1.00000000001fff80#64", ]; let sample_median = ("1.5", None); let sample_median_hex = ("0x1.8000000000000000#64", None); let sample_moment_stats = MomentStats { mean: NiceFloat(9.337530231284171), standard_deviation: NiceFloat(520.317614819243), skewness: NiceFloat(340.99301578218797), excess_kurtosis: NiceFloat(147660.4928189293), }; striped_random_positive_floats_with_precision_helper_no_common_values( 1, 1, 32, 1, 64, values, values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 1 let values = &[ "2.0e-37", "8.0e-34", "4.0e-6", "3.0e-45", "2.0e15", "5.0e-10", "2.0e4", "0.06", "0.0001", "1.0e14", "2.0e34", "9.0e-13", "0.0001", "9.0e9", "1.0e33", "0.1", "0.00003", "5.0e18", "0.06", "5.0e8", ]; let values_hex = &[ "0x4.0E-31#1", "0x4.0E-28#1", "0x0.00004#1", "0x1.0E-37#1", "0x8.0E+12#1", "0x2.0E-8#1", "0x4.0E+3#1", "0x0.1#1", "0x0.0008#1", "0x8.0E+11#1", "0x4.0E+28#1", "0x1.0E-10#1", "0x0.0008#1", "0x2.0E+8#1", "0x4.0E+27#1", "0x0.2#1", "0x0.0002#1", "0x4.0E+15#1", "0x0.1#1", "0x2.0E+7#1", ]; let common_values = &[ ("1.0", 7698), ("0.2", 7624), ("0.5", 7597), ("2.0", 7563), ("4.0", 7402), ("8.0", 7362), ("0.06", 7323), ("0.1", 7239), ("3.0e1", 7225), ("2.0e1", 7161), ]; let common_values_hex = &[ ("0x1.0#1", 7698), ("0x0.4#1", 7624), ("0x0.8#1", 7597), ("0x2.0#1", 7563), ("0x4.0#1", 7402), ("0x8.0#1", 7362), ("0x0.1#1", 7323), ("0x0.2#1", 7239), ("0x2.0E+1#1", 7225), ("0x1.0E+1#1", 7161), ]; let sample_median = ("1.0", None); let sample_median_hex = ("0x1.0#1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.9680504915704222e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_floats_with_precision_helper( 64, 1, 8, 1, 1, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 64 let values = &[ "3.758e-37", "7.7e-34", "7.62e-6", "3.147e-45", "2.252e15", "9.304e-10", "1.638e4", "0.1232", "0.0002439", "2.812e14", "4.15e34", "1.817e-12", "0.0002439", "8.59e9", "2.594e33", "0.125", "0.00006098", "9.214e18", "0.0626", "5.37e8", ]; let values_hex = &[ "0x7.feE-31#10", "0x4.00E-28#10", "0x0.00007fe#10", "0x1.1f8E-37#10", "0x8.00E+12#10", "0x3.ffE-8#10", "0x4.00E+3#10", "0x0.1f88#10", "0x0.000ffc#10", "0xf.fcE+11#10", "0x7.feE+28#10", "0x1.ff8E-10#10", "0x0.000ffc#10", "0x2.00E+8#10", "0x7.feE+27#10", "0x0.200#10", "0x0.0003ff#10", "0x7.feE+15#10", "0x0.1008#10", "0x2.00E+7#10", ]; let common_values = &[ ("1.0", 3037), ("1.998", 2989), ("3.996", 2983), ("0.5", 2957), ("0.25", 2940), ("0.4995", 2931), ("0.999", 2926), ("2.0", 2913), ("15.98", 2904), ("7.99", 2887), ]; let common_values_hex = &[ ("0x1.000#10", 3037), ("0x1.ff8#10", 2989), ("0x3.ff#10", 2983), ("0x0.800#10", 2957), ("0x0.400#10", 2940), ("0x0.7fe#10", 2931), ("0x0.ffc#10", 2926), ("0x2.00#10", 2913), ("0xf.fc#10", 2904), ("0x7.fe#10", 2887), ]; let sample_median = ("1.127", Some("1.188")); let sample_median_hex = ("0x1.208#10", Some("0x1.300#10")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.932257134524397e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_floats_with_precision_helper( 64, 1, 32, 1, 10, values, values_hex, common_values, common_values_hex, sample_median, sample_median_hex, sample_moment_stats, ); // mean |sci_exponent| 64, precision 64 let values = &[ "3.7615819086183353829e-37", "9.6296497219361792644e-34", "7.6293945170391452848e-6", "2.8025969286547320357e-45", "2251937252638716.0", "9.3130836376076393401e-10", "16384.0", "0.124023437507275954145", "0.00023651125957256657895", "281473902977023.5", "4.1538374868278030732e34", "1.817213046918211231e-12", "0.00024414062499999653055", "8590196735.999999045", "2.5961484292662332226e33", "0.1250000000072759576", "0.000061035156022629794", "9219009174715727999.5", "0.0625", "536870912.00006103143", ]; let values_hex = &[ "0x7.ffffff8000000018E-31#64", "0x4.fffffffffffffff8E-28#64", "0x0.00007ffffffc000000000#64", "0x1.0000000001fffffeE-37#64", "0x8001ffffffffc.000#64", "0x3.fffc00000000c000E-8#64", "0x4000.0000000000000#64", "0x0.1fc0000007ffffc00#64", "0x0.000f80001fffff00000#64", "0xffffc0001fff.8000#64", "0x7.ffffffffffe00000E+28#64", "0x1.ff800000ffff0000E-10#64", "0x0.000fffffffffffc0000#64", "0x20003ffff.ffffeffc#64", "0x7.fffffffffc000000E+27#64", "0x0.2000000007ffffffc#64", "0x0.0003ffffffc0003ffffc#64", "0x7ff07fffffff807f.8#64", "0x0.10000000000000000#64", "0x20000000.0003fff00#64", ]; let sample_median = ("1.2490234375", Some("1.2490234449505805968")); let sample_median_hex = ("0x1.3fc0000000000000#64", Some("0x1.3fc0001ffffffffe#64")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.9361009831408444e255), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_floats_with_precision_helper_no_common_values( 64, 1, 32, 1, 64, values, values_hex, sample_median, sample_median_hex, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_positive_floats_with_precision_fail_1() { striped_random_positive_floats_with_precision(EXAMPLE_SEED, 1, 0, 2, 1, 2); } #[test] #[should_panic] fn striped_random_positive_floats_with_precision_fail_2() { striped_random_positive_floats_with_precision(EXAMPLE_SEED, 0, 1, 2, 1, 2); } #[test] #[should_panic] fn striped_random_positive_floats_with_precision_fail_3() { striped_random_positive_floats_with_precision(EXAMPLE_SEED, 1, 1, 2, 1, 0); } #[test] #[should_panic] fn striped_random_positive_floats_with_precision_fail_4() { striped_random_positive_floats_with_precision(EXAMPLE_SEED, 1, 1, 2, 3, 2); } #[test] #[should_panic] fn striped_random_positive_floats_with_precision_fail_5() { striped_random_positive_floats_with_precision(EXAMPLE_SEED, 1, 1, 1, 0, 2); } ================================================ FILE: malachite-nz/.gitignore ================================================ target *.bk .idea* *.iml ================================================ FILE: malachite-nz/Cargo.toml ================================================ [package] name = "malachite-nz" version = "0.9.1" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true description = "The bignum types Natural and Integer, with efficient algorithms partially derived from GMP and FLINT." readme = "README.md" homepage = "https://malachite.rs/" repository = "https://github.com/mhogrefe/malachite" license = "LGPL-3.0-only" keywords = ["mathematics", "math", "numerics", "bignum"] categories = ["mathematics"] [lib] name = "malachite_nz" path = "src/lib.rs" [[bin]] name = "malachite_nz_main" path = "src/bin.rs" [dependencies] itertools = { version = "0.14.0", default-features = false, features = ["use_alloc"] } libm = { version = "0.2.16", default-features = false } malachite-base = { version = "0.9.1", default-features = false, path = "../malachite-base" } serde = { version = "1.0.228", optional = true, default-features = false, features = ["alloc", "derive"] } wide = { version = "1.1.1" } indoc = { version = "2.0.7", optional = true} pyo3 = { version = "0.27.2", optional = true } serde_json = { version = "1.0.149", optional = true } num = { version = "0.4.3", optional = true, features = ["serde"] } rug = { version = "1.28.1", default-features = false, optional = true, features = ["integer", "serde"] } embed-doc-image = { version = "0.1.4", optional = true } [dev-dependencies] malachite-nz = { path = ".", features = ["test_build"] } [build-dependencies] pyo3-build-config = { version = "0.27.2", features = ["resolve-config"], optional = true } [features] default = ["std"] std = ["malachite-base/std"] 32_bit_limbs = [] random = ["malachite-base/random"] enable_pyo3 = ["pyo3", "pyo3-build-config"] enable_serde = ["serde"] test_build = ["malachite-base/test_build", "random", "serde", "serde_json", "num", "rug", "pyo3", "pyo3-build-config", "indoc"] bin_build = ["test_build"] float_helpers = [] doc-images = ["embed-doc-image"] [package.metadata.docs.rs] # docs.rs uses a nightly compiler, so by instructing it to use our `doc-images` feature we # ensure that it will render any images that we may have in inner attribute documentation. features = ["doc-images", "random"] rustdoc-args = [ "--html-in-header", "katex-header.html" ] ================================================ FILE: malachite-nz/README.md ================================================ - [crates.io](https://crates.io/crates/malachite-nz) - [docs.rs](https://docs.rs/malachite-nz/latest/malachite_nz/) Rather than using this crate directly, use the [`malachite`](https://crates.io/crates/malachite) meta-crate. It re-exports all of this crate's public members. In `malachite-nz`'s doctests you will frequently see import paths beginning with `malachite_nz::`. When using the `malachite` crate, replace this part of the paths with `malachite::`. The import paths of the `Natural` and `Integer` types are shortened further, to `malachite::Natural` and `malachite::Integer`. # malachite-nz This crate defines [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s (non-negative integers) and [`Integer`](https://docs.rs/malachite-nz/latest/malachite_nz/integer/struct.Integer.html)s. Unlike primitive integers ([`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html), [`i32`](https://doc.rust-lang.org/nightly/std/primitive.i32.html), and so on), these may be arbitrarily large. The name of this crate refers to the mathematical symbols for natural numbers and integers, ℕ and ℤ. - There are many functions defined on [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s and [`Integer`](https://docs.rs/malachite-nz/latest/malachite_nz/integer/struct.Integer.html)s. These include - All the ones you'd expect, like addition, subtraction, multiplication, and integer division; - Implementations of [`DivRound`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.DivRound.html), which provides division that rounds according to a specified [`RoundingMode`](https://docs.rs/malachite-base/latest/malachite_base/rounding_modes/enum.RoundingMode.html); - Various mathematical functions, like implementations of [`FloorSqrt`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.FloorSqrt.html) and [`Gcd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.Gcd.html); - Modular arithmetic functions, like implementations of [`ModAdd`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModAdd.html) and [`ModPow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPow.html), and of traits for arithmetic modulo a power of 2, like [`ModPowerOf2Add`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPowerOf2Add.html) and [`ModPowerOf2Pow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPowerOf2Pow.html); - Various functions for logic and bit manipulation, like [`BitAnd`](https://doc.rust-lang.org/nightly/core/ops/trait.BitAnd.html) and [`BitAccess`](https://docs.rs/malachite-base/latest/malachite_base/num/logic/traits/trait.BitAccess.html). - The implementations of these functions use high-performance algorithms that work efficiently for large numbers. For example, multiplication uses the naive quadratic algorithm, or one of 13 variants of [Toom-Cook multiplication](https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication), or [Schönhage-Strassen (FFT) multiplication](https://en.wikipedia.org/wiki/Schonhage-Strassen_algorithm), depending on the input size. - Small numbers are also handled efficiently. Any [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) smaller than 264 does not use any allocated memory, and working with such numbers is almost as fast as working with primitive integers. As a result, Malachite does not provide implementations for _e.g._ adding a [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) to a [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html), since the [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html) can be converted to a [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) very cheaply. - Malachite handles memory intelligently. Consider the problem of adding a 1000-bit [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) and a 500-bit [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html). If we only have references to the [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s, then we must allocate new memory for the result, and this is what the `&Natural + &Natural` implementation does. However, if we can take the first (larger) [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) by value, then we do not need to allocate any memory (except in the unlikely case of a carry): we can reuse the memory of the first [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) to store the result, and this is what the `Natural + &Natural` implementation does. On the other hand, if we can only take the second (smaller) [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) by value, then we only have 500 bits of memory available, which is not enough to store the sum. In this case, the [`Vec`](https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html) containing the smaller [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)'s data can be extended to hold 1000 bits, in hopes that this will be more efficient than allocating 1000 bits in a completely new [`Vec`](https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html). Finally, if both [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s are taken by value, then the `Natural + Natural` implementation chooses to reuse the memory of the larger one. Now consider what happens when evaluating the expression `&x + &y + &z`, where each [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html) has _n_ bits. Malachite must allocate about _n_ bits for the result, but what about the intermediate sum `&x + &y`? Does Malachite need to allocate another _n_ bits for that, for a total of 2 _n_ bits? No! Malachite first allocates _n_ bits for `&x + &y`, but then that partial sum is taken by _value_ using the `Natural + &Natural` implementation described above; so those _n_ bits are reused for the final sum. # Limbs Large [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s and [`Integer`](https://docs.rs/malachite-nz/latest/malachite_nz/integer/struct.Integer.html)s store their data as [`Vec`](https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html)s of some primitive type. The elements of these [`Vec`](https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html)s are called "limbs" in GMP terminology, since they're large digits. By default, the type of a `Limb` is [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html), but you can set it to [`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html) using the `32_bit_limbs` feature. # Demos and benchmarks This crate comes with a `bin` target that can be used for running demos and benchmarks. - Almost all of the public functions in this crate have an associated demo. Running a demo shows you a function's behavior on a large number of inputs. For example, to demo the [`mod_pow`](https://docs.rs/malachite-base/latest/malachite_base/num/arithmetic/traits/trait.ModPow.html#tymethod.mod_pow) function on [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s, you can use the following command: ```text cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_natural_mod_pow ``` This command uses the `exhaustive` mode, which generates every possible input, generally starting with the simplest input and progressing to more complex ones. Another mode is `random`. The `-l` flag specifies how many inputs should be generated. - You can use a similar command to run benchmarks. The following command benchmarks various GCD algorithms for [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html)s: ```text cargo run --features bin_build --release -- -l 1000000 -m random -b \ benchmark_natural_gcd_algorithms -o gcd-bench.gp ``` or GCD implementations of other libraries: ```text cargo run --features bin_build --release -- -l 1000000 -m random -b \ benchmark_natural_gcd_library_comparison -o gcd-bench.gp ``` This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like so: ```text gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg ``` The list of available demos and benchmarks is not documented anywhere; you must find them by browsing through [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-nz/src/bin_util/demo_and_bench). # Features - `32_bit_limbs`: Sets the type of `Limb` to [`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html) instead of the default, [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html). - `random`: This feature provides some functions for randomly generating values. It is off by default to avoid pulling in some extra dependencies. - `enable_serde`: Enables serialization and deserialization using [serde](`https://serde.rs/`). - `test_build`: A large proportion of the code in this crate is only used for testing. For a typical user, building this code would result in an unnecessarily long compilation time and an unnecessarily large binary. Some of it is also used for testing [`malachite-q`](https://crates.io/crates/malachite-q), so it can't just be confined to the `tests` directory. My solution is to only build this code when the `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`. However, doctests don't require it, since they only test the public interface. Enabling this feature also enables `random`. - `bin_build`: This feature is used to build the code for demos and benchmarks, which also takes a long time to build. Enabling this feature also enables `test_build` and `random`. Malachite is developed by Mikhail Hogrefe. Thanks to b4D8, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, shekohex, and skycloudd for additional contributions. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: malachite-nz/build.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // PyO3 integration contributed by Antonio Mamić. // // 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 . fn main() { #[cfg(feature = "enable_pyo3")] pyo3_build_config::use_pyo3_cfgs(); } ================================================ FILE: malachite-nz/extra-tests.py ================================================ import subprocess def substitute_constant(const_prefix, input_filename, output_filename, value): prefix = f'{const_prefix}: usize = ' with open(input_filename, 'r') as in_f: with open(output_filename, 'w') as out_f: for line in in_f.readlines(): line = line.rstrip() if line.startswith(prefix): original_value = line[len(prefix):-1] out_f.write(prefix + value + ';\n') else: out_f.write(line + '\n') def substitute_hgcd_reduce_threshold(input_filename, output_filename, value): substitute_constant('const HGCD_REDUCE_THRESHOLD', input_filename, output_filename, value) path = 'src/natural/arithmetic/gcd/half_gcd.rs' assert subprocess.call('cp ' + path + ' backup.rs', shell = True) == 0 substitute_hgcd_reduce_threshold('backup.rs', 'temp.rs', '200') assert subprocess.call('mv temp.rs ' + path, shell = True) == 0 assert subprocess.call('cargo test --test lib --features 32_bit_limbs --features serde --features test_build -- test_limbs_gcd_reduced', shell = True) == 0 assert subprocess.call('cargo test --test lib --features serde --features test_build -- test_limbs_gcd_reduced', shell = True) == 0 assert subprocess.call('mv backup.rs ' + path, shell = True) == 0 ================================================ FILE: malachite-nz/images/natural-mem-layout.asy ================================================ defaultpen(fontsize(14pt)); size(400,400); real height = 10; real tag_width = 35; real small_width = 26; real text_offset = 17.5; real text_offset_2 = 49; real text_offset_3 = 104; real col_2 = 90; string small_label = "{\tt Natural::Small}"; string large_label = "{\tt Natural::Large}"; filldraw(box((-5,5),(121,-85)),rgb(150.0/255,150.0/255,150.0/255)); filldraw(box((col_2,-height),(col_2+small_width,-2*height)),lightblue); label("{\tt 0xa8dc8417 }", (text_offset_3,-3*height/2)); filldraw(box((col_2,-2*height),(col_2+small_width,-3*height)),lightblue); label("{\tt 0x000009af }", (text_offset_3,-5*height/2)); filldraw(box((col_2,-4*height),(col_2+small_width,-5*height)),lightblue); label("{\tt 0xd2d335fb }", (text_offset_3,-9*height/2)); filldraw(box((col_2,-5*height),(col_2+small_width,-6*height)),lightblue); label("{\tt 0xce285713 }", (text_offset_3,-11*height/2)); filldraw(box((col_2,-6*height),(col_2+small_width,-7*height)),lightblue); label("{\tt 0x005dd267 }", (text_offset_3,-13*height/2)); draw((tag_width+small_width,-13*height/2) -- (70,-13*height/2)); draw((70,-13*height/2) -- (70,-3*height/2)); draw((70,-3*height/2) -- (col_2,-3*height/2), arrow=Arrow); draw((tag_width+small_width,-15*height/2) -- (80,-15*height/2)); draw((80,-15*height/2) -- (80,-9*height/2)); draw((80,-9*height/2) -- (col_2,-9*height/2), arrow=Arrow); filldraw(box((0,0),(tag_width,-height)),mediumgray); label(small_label, (text_offset,-height/2)); filldraw(box((tag_width,0),(tag_width+small_width,-height)),lightblue); label("{\tt 0x00000002 }", (text_offset_2,-height/2)); filldraw(box((0,-height),(tag_width,-2*height)),mediumgray); label(small_label, (text_offset,-3*height/2)); filldraw(box((tag_width,-height),(tag_width+small_width,-2*height)),lightblue); label("{\tt 0x00000003 }", (text_offset_2,-3*height/2)); filldraw(box((0,-2*height),(tag_width,-3*height)),mediumgray); label(small_label, (text_offset,-5*height/2)); filldraw(box((tag_width,-2*height),(tag_width+small_width,-3*height)),lightblue); label("{\tt 0x00000007 }", (text_offset_2,-5*height/2)); filldraw(box((0,-3*height),(tag_width,-4*height)),mediumgray); label(small_label, (text_offset,-7*height/2)); filldraw(box((tag_width,-3*height),(tag_width+small_width,-4*height)),lightblue); label("{\tt 0x0000002b }", (text_offset_2,-7*height/2)); filldraw(box((0,-4*height),(tag_width,-5*height)),mediumgray); label(small_label, (text_offset,-9*height/2)); filldraw(box((tag_width,-4*height),(tag_width+small_width,-5*height)),lightblue); label("{\tt 0x0000070f }", (text_offset_2,-9*height/2)); filldraw(box((0,-5*height),(tag_width,-6*height)),mediumgray); label(small_label, (text_offset,-11*height/2)); filldraw(box((tag_width,-5*height),(tag_width+small_width,-6*height)),lightblue); label("{\tt 0x0031cbd3 }", (text_offset_2,-11*height/2)); filldraw(box((0,-6*height),(tag_width,-7*height)),mediumgray); label(large_label, (text_offset,-13*height/2)); filldraw(box((tag_width,-6*height),(tag_width+small_width,-7*height)),mediumgray); label("{\tt Vec }", (text_offset_2,-13*height/2)); filldraw(box((0,-7*height),(tag_width,-8*height)),mediumgray); label(large_label, (text_offset,-15*height/2)); filldraw(box((tag_width,-7*height),(tag_width+small_width,-8*height)),mediumgray); label("{\tt Vec }", (text_offset_2,-15*height/2)); ================================================ FILE: malachite-nz/katex-header.html ================================================ ================================================ FILE: malachite-nz/rustfmt.toml ================================================ max_width = 100 array_width = 100 ================================================ FILE: malachite-nz/src/bin.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #[cfg(feature = "bin_build")] extern crate itertools; #[cfg(feature = "bin_build")] #[macro_use] extern crate malachite_base; #[cfg(feature = "bin_build")] extern crate malachite_nz; #[cfg(feature = "bin_build")] extern crate num; #[cfg(feature = "bin_build")] extern crate rug; #[cfg(feature = "bin_build")] extern crate serde; #[cfg(feature = "bin_build")] extern crate serde_json; #[cfg(feature = "bin_build")] use crate::bin_util::demo_and_bench::register; #[cfg(feature = "bin_build")] use crate::bin_util::generate::digits_data::generate_string_data; #[cfg(feature = "bin_build")] use crate::bin_util::generate::factorial_data::generate_factorial_data; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::Runner; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::cmd::read_command_line_arguments; // Examples: // // ``` // cargo run --release --features bin_build -- -l 100000 -m special_random -d // demo_natural_from_unsigned_u128 -c "mean_run_length_n 4 mean_run_length_d 1" // // cargo run --release --features bin_build -- -l 100000 -m random -b // benchmark_limbs_to_digits_small_base_algorithms // // cargo run --features bin_build -- -g digits_data // ``` #[cfg(feature = "bin_build")] fn main() { let args = read_command_line_arguments("malachite-nz test utils"); let mut runner = Runner::new(); register(&mut runner); if let Some(demo_key) = args.demo_key { runner.run_demo(&demo_key, args.generation_mode, &args.config, args.limit); } else if let Some(bench_key) = args.bench_key { runner.run_bench( &bench_key, args.generation_mode, &args.config, args.limit, &args.out, ); } else { let codegen_key = args.codegen_key.unwrap(); match codegen_key.as_str() { "digits_data" => generate_string_data(), "factorial_data" => generate_factorial_data(), _ => panic!("Invalid codegen key: {codegen_key}"), } } } #[cfg(not(feature = "bin_build"))] const fn main() {} #[cfg(feature = "bin_build")] pub mod bin_util { pub mod demo_and_bench; pub mod generate; } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign, UnsignedAbs}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, triple_1_integer_bit_bucketer, triple_3_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_nrm, integer_integer_natural_triple_gen, }; use num::Signed; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_abs); register_demo!(runner, demo_integer_abs_ref); register_demo!(runner, demo_integer_abs_assign); register_demo!(runner, demo_integer_unsigned_abs); register_demo!(runner, demo_integer_unsigned_abs_ref); register_demo!(runner, demo_integer_unsigned_abs_ref_out); register_demo!(runner, demo_integer_mutate_unsigned_abs); register_bench!(runner, benchmark_integer_abs_library_comparison); register_bench!(runner, benchmark_integer_abs_evaluation_strategy); register_bench!(runner, benchmark_integer_abs_assign); register_bench!(runner, benchmark_integer_unsigned_abs_evaluation_strategy); register_bench!(runner, benchmark_integer_mutate_unsigned_abs); } fn demo_integer_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("|{}| = {}", n.clone(), n.abs()); } } fn demo_integer_abs_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("|&{}| = {}", n, (&n).abs()); } } fn demo_integer_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in integer_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_assign(); println!("n := {n_old}; n.abs_assign(); n = {n}"); } } fn demo_integer_unsigned_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("unsigned_abs({}) = {}", n.clone(), n.unsigned_abs()); } } fn demo_integer_unsigned_abs_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("unsigned_abs(&{}) = {}", n, (&n).unsigned_abs()); } } fn demo_integer_unsigned_abs_ref_out(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{}.unsigned_abs_ref() = {}", n, n.unsigned_abs_ref()); } } fn demo_integer_mutate_unsigned_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, out, new_abs) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let old_n = n.clone(); let old_out = out.clone(); let old_new_abs = new_abs.clone(); let actual_out = n.mutate_unsigned_abs(|x| { *x = new_abs; out }); println!( "n := {old_n}; \ n.mutate_unsigned_abs(|x| {{ *x = {old_new_abs}; {old_out} }}) = {actual_out}; \ n = {n}", ); } } fn benchmark_integer_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.abs()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.abs())), ("num", &mut |(n, _, _)| no_out!(n.abs())), ("rug", &mut |(_, n, _)| no_out!(n.abs().cmp0())), ], ); } fn benchmark_integer_abs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.abs()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.abs()", &mut |n| no_out!(n.abs())), ("(&Integer).abs()", &mut |n| no_out!((&n).abs())), ], ); } fn benchmark_integer_abs_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.abs_assign()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.abs_assign())], ); } fn benchmark_integer_unsigned_abs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.unsigned_abs()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.unsigned_abs()", &mut |n| no_out!(n.unsigned_abs())), ("(&Integer).unsigned_abs()", &mut |n| { no_out!((&n).unsigned_abs()); }), ("Integer.unsigned_abs_ref()", &mut |n| { no_out!(n.unsigned_abs_ref()); }), ], ); } fn benchmark_integer_mutate_unsigned_abs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mutate_unsigned_abs(FnOnce(&mut Natural) -> T)", BenchmarkType::Single, integer_integer_natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, out, new_abs)| { no_out!(n.mutate_unsigned_abs(|x| { *x = new_abs; out })); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AbsDiff, AbsDiffAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_integer_max_bit_bucketer; use malachite_nz::test_util::generators::integer_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_abs_diff); register_demo!(runner, demo_integer_abs_diff_val_ref); register_demo!(runner, demo_integer_abs_diff_ref_val); register_demo!(runner, demo_integer_abs_diff_ref_ref); register_demo!(runner, demo_integer_abs_diff_assign); register_demo!(runner, demo_integer_abs_diff_assign_ref); register_bench!( runner, benchmark_integer_abs_diff_assign_evaluation_strategy ); register_bench!(runner, benchmark_integer_abs_diff_evaluation_strategy); } fn demo_integer_abs_diff(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("|{} - {}| = {:?}", x_old, y_old, x.abs_diff(y)); } } fn demo_integer_abs_diff_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("|{} - &{}| = {:?}", x_old, y, x.abs_diff(&y)); } } fn demo_integer_abs_diff_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("|&{} - {}| = {:?}", x, y_old, (&x).abs_diff(y)); } } fn demo_integer_abs_diff_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("|&{} - &{}| = {:?}", x, y, (&x).abs_diff(&y)); } } fn demo_integer_abs_diff_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.abs_diff_assign(y); println!("x := {x_old}; x.abs_diff_assign({y_old}); x = {x}"); } } fn demo_integer_abs_diff_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.abs_diff_assign(&y); println!("x := {x_old}; x.abs_diff_assign(&{y}); x = {x}"); } } fn benchmark_integer_abs_diff_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.abs_diff_assign(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer.abs_diff_assign(Integer)", &mut |(mut x, y)| { x.abs_diff_assign(y); }), ("Integer.abs_diff_assign(&Integer)", &mut |(mut x, y)| { x.abs_diff_assign(&y); }), ], ); } fn benchmark_integer_abs_diff_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.abs_diff(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer.abs_diff(Integer)", &mut |(x, y)| { no_out!(x.abs_diff(y)); }), ("Integer.abs_diff(&Integer)", &mut |(x, y)| { no_out!(x.abs_diff(&y)); }), ("&Integer.abs_diff(Integer)", &mut |(x, y)| { no_out!((&x).abs_diff(y)); }), ("&Integer.abs_diff(&Integer)", &mut |(x, y)| { no_out!((&x).abs_diff(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, triple_3_vec_integer_sum_bits_bucketer, vec_integer_sum_bits_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen, integer_pair_gen_nrm, integer_pair_gen_rm, integer_vec_gen, integer_vec_gen_nrm, }; use malachite_nz::test_util::integer::arithmetic::add::integer_sum_alt; use num::BigInt; use std::iter::Sum; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_add); register_demo!(runner, demo_integer_add_val_ref); register_demo!(runner, demo_integer_add_ref_val); register_demo!(runner, demo_integer_add_ref_ref); register_demo!(runner, demo_integer_add_assign); register_demo!(runner, demo_integer_add_assign_ref); register_demo!(runner, demo_integer_sum); register_demo!(runner, demo_integer_ref_sum); register_bench!(runner, benchmark_integer_add_library_comparison); register_bench!(runner, benchmark_integer_add_evaluation_strategy); register_bench!(runner, benchmark_integer_add_assign_library_comparison); register_bench!(runner, benchmark_integer_add_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_sum_algorithms); register_bench!(runner, benchmark_integer_sum_library_comparison); register_bench!(runner, benchmark_integer_sum_evaluation_strategy); } fn demo_integer_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_integer_add_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_integer_add_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_integer_add_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_integer_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_integer_add_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_integer_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in integer_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs.clone(), Integer::sum(xs.into_iter())); } } fn demo_integer_ref_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in integer_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs, Integer::sum(xs.iter())); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_add_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer + Integer", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x + y)), ("num", &mut |((x, y), _, _)| no_out!(x + y)), ("rug", &mut |(_, (x, y), _)| no_out!(x + y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer + Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer + Integer", &mut |(x, y)| no_out!(x + y)), ("Integer + &Integer", &mut |(x, y)| no_out!(x + &y)), ("&Integer + Integer", &mut |(x, y)| no_out!(&x + y)), ("&Integer + &Integer", &mut |(x, y)| no_out!(&x + &y)), ], ); } fn benchmark_integer_add_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer += Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x += y), ("rug", &mut |((mut x, y), _)| x += y)], ); } fn benchmark_integer_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer += Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer += Integer", &mut |(mut x, y)| no_out!(x += y)), ("Integer += &Integer", &mut |(mut x, y)| no_out!(x += &y)), ], ); } fn benchmark_integer_sum_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::sum(Iterator)", BenchmarkType::LibraryComparison, integer_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_integer_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Integer::sum(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigInt::sum(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Integer::sum(xs.iter())); }), ], ); } fn benchmark_integer_sum_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::sum(Iterator)", BenchmarkType::Algorithms, integer_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_integer_sum_bits_bucketer(), &mut [ ("default", &mut |xs| no_out!(Integer::sum(xs.into_iter()))), ("alt", &mut |xs| no_out!(integer_sum_alt(xs.into_iter()))), ], ); } fn benchmark_integer_sum_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::sum(Iterator)", BenchmarkType::EvaluationStrategy, integer_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_integer_sum_bits_bucketer(), &mut [ ("Integer::sum(Iterator)", &mut |xs| { no_out!(Integer::sum(xs.into_iter())); }), ("Integer::sum(Iterator)", &mut |xs| { no_out!(Integer::sum(xs.iter())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_integer_max_bit_bucketer; use malachite_nz::test_util::generators::integer_triple_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_add_mul); register_demo!(runner, demo_integer_add_mul_val_val_ref); register_demo!(runner, demo_integer_add_mul_val_ref_val); register_demo!(runner, demo_integer_add_mul_val_ref_ref); register_demo!(runner, demo_integer_add_mul_ref_ref_ref); register_demo!(runner, demo_integer_add_mul_assign); register_demo!(runner, demo_integer_add_mul_assign_val_ref); register_demo!(runner, demo_integer_add_mul_assign_ref_val); register_demo!(runner, demo_integer_add_mul_assign_ref_ref); register_bench!(runner, benchmark_integer_add_mul_evaluation_strategy); register_bench!(runner, benchmark_integer_add_mul_algorithms); register_bench!(runner, benchmark_integer_add_mul_val_val_ref_algorithms); register_bench!(runner, benchmark_integer_add_mul_val_ref_val_algorithms); register_bench!(runner, benchmark_integer_add_mul_val_ref_ref_algorithms); register_bench!(runner, benchmark_integer_add_mul_ref_ref_ref_algorithms); register_bench!(runner, benchmark_integer_add_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_add_mul_assign_algorithms); register_bench!(runner, benchmark_integer_add_mul_assign_val_ref_algorithms); register_bench!(runner, benchmark_integer_add_mul_assign_ref_val_algorithms); register_bench!(runner, benchmark_integer_add_mul_assign_ref_ref_algorithms); } fn demo_integer_add_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); println!( "{}.add_mul({}, {}) = {}", x_old, y_old, z_old, x.add_mul(y, z) ); } } fn demo_integer_add_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.add_mul({}, &({})) = {}", x_old, y_old, z, x.add_mul(y, &z) ); } } fn demo_integer_add_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); println!( "{}.add_mul(&({}), {}) = {}", x_old, y, z_old, x.add_mul(&y, z) ); } } fn demo_integer_add_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.add_mul(&({}), &({})) = {}", x_old, y, z, x.add_mul(&y, &z) ); } } fn demo_integer_add_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { println!( "(&{}).add_mul(&({}), &({})) = {}", x, y, z, (&x).add_mul(&y, &z) ); } } fn demo_integer_add_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); x.add_mul_assign(y, z); println!("x := {x_old}; x.add_mul_assign({y_old}, {z_old}); x = {x}"); } } fn demo_integer_add_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.add_mul_assign(y, &z); println!("x := {x_old}; x.add_mul_assign({y_old}, &({z})); x = {x}"); } } fn demo_integer_add_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); x.add_mul_assign(&y, z); println!("x := {x_old}; x.add_mul_assign(&({y}), {z_old}); x = {x}"); } } fn demo_integer_add_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.add_mul_assign(&y, &z); println!("x := {x_old}; x.add_mul_assign(&({y}), &({z})); x = {x}"); } } fn benchmark_integer_add_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.add_mul(Integer, Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(b, c)); }), ("Integer.add_mul(Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(b, &c)); }), ("Integer.add_mul(&Integer, Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, c)); }), ("Integer.add_mul(&Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, &c)); }), ( "(&Integer).add_mul(&Integer, &Integer)", &mut |(a, b, c)| no_out!((&a).add_mul(&b, &c)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.add_mul(Integer, Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(b, c)); }), ("Integer + Integer * Integer", &mut |(a, b, c)| { no_out!(a + b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.add_mul(Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(b, &c)); }), ("Integer + Integer * &Integer", &mut |(a, b, c)| { no_out!(a + b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(&Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.add_mul(&Integer, Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, c)); }), ("Integer + &Integer * Integer", &mut |(a, b, c)| { no_out!(a + &b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.add_mul(&Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, &c)); }), ("Integer + Integer * Integer", &mut |(a, b, c)| { no_out!(a + &b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_add_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "(&Integer).add_mul(&Integer, &Integer)", &mut |(a, b, c)| no_out!((&a).add_mul(&b, &c)), ), ("&Integer + Integer * Integer", &mut |(a, b, c)| { no_out!(&a + &b * &c); }), ], ); } fn benchmark_integer_add_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul_assign(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.add_mul_assign(Integer, Integer)", &mut |(mut a, b, c)| a.add_mul_assign(b, c), ), ( "Integer.add_mul_assign(Integer, &Integer)", &mut |(mut a, b, c)| a.add_mul_assign(b, &c), ), ( "Integer.add_mul_assign(&Integer, Integer)", &mut |(mut a, b, c)| a.add_mul_assign(&b, c), ), ( "Integer.add_mul_assign(&Integer, &Integer)", &mut |(mut a, b, c)| a.add_mul_assign(&b, &c), ), ], ); } fn benchmark_integer_add_mul_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul_assign(Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.add_mul_assign(Integer, Integer)", &mut |(mut a, b, c)| a.add_mul_assign(b, c), ), ("Integer += Integer * Integer", &mut |(mut a, b, c)| { a += b * c; }), ], ); } fn benchmark_integer_add_mul_assign_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul_assign(Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.add_mul_assign(Integer, &Integer)", &mut |(mut a, b, c)| a.add_mul_assign(b, &c), ), ("Integer += Integer * &Integer", &mut |(mut a, b, c)| { a += b * &c; }), ], ); } fn benchmark_integer_add_mul_assign_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul_assign(&Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.add_mul_assign(&Integer, Integer)", &mut |(mut a, b, c)| a.add_mul_assign(&b, c), ), ("Integer += &Integer * Integer", &mut |(mut a, b, c)| { a += &b * c; }), ], ); } fn benchmark_integer_add_mul_assign_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.add_mul_assign(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.add_mul_assign(&Integer, &Integer)", &mut |(mut a, b, c)| a.add_mul_assign(&b, &c), ), ("Integer += &Integer * &Integer", &mut |(mut a, b, c)| { a += &b * &c; }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::BinomialCoefficient; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen_var_7, integer_pair_gen_var_7_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_binomial_coefficient); register_demo!(runner, demo_integer_binomial_coefficient_ref); register_bench!( runner, benchmark_integer_binomial_coefficient_evaluation_strategy ); register_bench!( runner, benchmark_integer_binomial_coefficient_library_comparison ); } fn demo_integer_binomial_coefficient(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in integer_pair_gen_var_7().get(gm, config).take(limit) { let n_orig = n.clone(); let k_orig = k.clone(); println!( "C({}, {}) = {}", n_orig, k_orig, Integer::binomial_coefficient(n, k) ); } } fn demo_integer_binomial_coefficient_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in integer_pair_gen_var_7().get(gm, config).take(limit) { println!( "C({}, {}) = {}", n, k, Integer::binomial_coefficient(&n, &k) ); } } fn benchmark_integer_binomial_coefficient_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.binomial_coefficient(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ( "Integer.binomial_coefficient(Integer, Integer)", &mut |(n, k)| no_out!(Integer::binomial_coefficient(n, k)), ), ( "Integer.binomial_coefficient(&Integer, &Integer)", &mut |(n, k)| no_out!(Integer::binomial_coefficient(&n, &k)), ), ], ); } #[allow(unused_must_use)] fn benchmark_integer_binomial_coefficient_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.binomial_coefficient(Integer, Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_7_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (n, k))| { no_out!(Integer::binomial_coefficient(n, k)); }), ("rug", &mut |((n, k), _)| no_out!(n.binomial(k))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedDiv, DivRem}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen, integer_pair_gen_nm, integer_pair_gen_var_1, integer_pair_gen_var_1_nrm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_div); register_demo!(runner, demo_integer_div_val_ref); register_demo!(runner, demo_integer_div_ref_val); register_demo!(runner, demo_integer_div_ref_ref); register_demo!(runner, demo_integer_div_assign); register_demo!(runner, demo_integer_div_assign_ref); register_demo!(runner, demo_integer_checked_div); register_demo!(runner, demo_integer_checked_div_val_ref); register_demo!(runner, demo_integer_checked_div_ref_val); register_demo!(runner, demo_integer_checked_div_ref_ref); register_bench!(runner, benchmark_integer_div_library_comparison); register_bench!(runner, benchmark_integer_div_algorithms); register_bench!(runner, benchmark_integer_div_evaluation_strategy); register_bench!(runner, benchmark_integer_div_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_checked_div_library_comparison); register_bench!(runner, benchmark_integer_checked_div_evaluation_strategy); } fn demo_integer_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_integer_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_integer_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_integer_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_integer_div_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x /= y.clone(); println!("x := {x_old}; x /= {y}; x = {x}"); } } fn demo_integer_div_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!("x := {x_old}; x /= &{y}; x = {x}"); } } fn demo_integer_checked_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).checked_div({}) = {:?}", x_old, y_old, x.checked_div(y) ); } } fn demo_integer_checked_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).checked_div(&{}) = {:?}", x_old, y, x.checked_div(&y)); } } fn demo_integer_checked_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).checked_div({}) = {:?}", x, y_old, (&x).checked_div(y) ); } } fn demo_integer_checked_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("(&{}).checked_div(&{}) = {:?}", x, y, (&x).checked_div(&y)); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer / Integer", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x / y)), ("num", &mut |((x, y), _, _)| no_out!(x / y)), ("rug", &mut |(_, (x, y), _)| no_out!(x / y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_div_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer / Integer", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x / y)), ("using div_rem", &mut |(x, y)| no_out!(x.div_rem(y).0)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer / Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer / Integer", &mut |(x, y)| no_out!(x / y)), ("Integer / &Integer", &mut |(x, y)| no_out!(x / &y)), ("&Integer / Integer", &mut |(x, y)| no_out!(&x / y)), ("&Integer / &Integer", &mut |(x, y)| no_out!(&x / &y)), ], ); } fn benchmark_integer_div_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer /= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer /= Integer", &mut |(mut x, y)| no_out!(x /= y)), ("Integer /= &Integer", &mut |(mut x, y)| no_out!(x /= &y)), ], ); } fn benchmark_integer_checked_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_div(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_nm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.checked_div(&y))), ("num", &mut |((x, y), _)| no_out!(x.checked_div(&y))), ], ); } fn benchmark_integer_checked_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_div(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.checked_div(Integer)", &mut |(x, y)| { no_out!(x.checked_div(y)); }), ("Integer.checked_div(&Integer)", &mut |(x, y)| { no_out!(x.checked_div(&y)); }), ("(&Integer).checked_div(Integer)", &mut |(x, y)| { no_out!((&x).checked_div(y)); }), ("(&Integer).checked_div(&Integer)", &mut |(x, y)| { no_out!((&x).checked_div(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen_var_2, integer_pair_gen_var_2_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_div_exact); register_demo!(runner, demo_integer_div_exact_val_ref); register_demo!(runner, demo_integer_div_exact_ref_val); register_demo!(runner, demo_integer_div_exact_ref_ref); register_demo!(runner, demo_integer_div_exact_assign); register_demo!(runner, demo_integer_div_exact_assign_ref); register_bench!(runner, benchmark_integer_div_exact_library_comparison); register_bench!(runner, benchmark_integer_div_exact_algorithms); register_bench!(runner, benchmark_integer_div_exact_evaluation_strategy); register_bench!(runner, benchmark_integer_div_exact_assign_algorithms); register_bench!( runner, benchmark_integer_div_exact_assign_evaluation_strategy ); } fn demo_integer_div_exact(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_exact({}) = {}", x_old, y_old, x.div_exact(y)); } } fn demo_integer_div_exact_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_exact(&{}) = {}", x_old, y, x.div_exact(&y)); } } fn demo_integer_div_exact_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_exact({}) = {}", x, y_old, (&x).div_exact(y)); } } fn demo_integer_div_exact_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { println!("(&{}).div_exact(&{}) = {}", x, y, (&x).div_exact(&y)); } } fn demo_integer_div_exact_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); x.div_exact_assign(y.clone()); println!("x := {x_old}; x.div_exact_assign({y}); x = {x}"); } } fn demo_integer_div_exact_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); x.div_exact_assign(&y); println!("x := {x_old}; x.div_exact_assign(&{y}); x = {x}"); } } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_div_exact_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_exact(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_2_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("num", &mut |((x, y), _, _)| no_out!(x / y)), ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_exact(y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_exact(&y))), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_div_exact_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_exact(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("ordinary division", &mut |(x, y)| no_out!(x / y)), ("exact division", &mut |(x, y)| no_out!(x.div_exact(y))), ], ); } fn benchmark_integer_div_exact_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_exact(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_exact(Integer)", &mut |(x, y)| { no_out!(x.div_exact(y)); }), ("Integer.div_exact(&Integer)", &mut |(x, y)| { no_out!(x.div_exact(&y)); }), ("(&Integer).div_exact(Integer)", &mut |(x, y)| { no_out!((&x).div_exact(y)); }), ("(&Integer).div_exact(&Integer)", &mut |(x, y)| { no_out!((&x).div_exact(&y)); }), ], ); } fn benchmark_integer_div_exact_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_exact_assign(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("ordinary division", &mut |(mut x, y)| x /= y), ("exact division", &mut |(mut x, y)| x.div_exact_assign(y)), ], ); } fn benchmark_integer_div_exact_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_exact_assign(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_exact_assign(Integer)", &mut |(mut x, y)| { x.div_exact_assign(y); }), ("Integer.div_exact_assign(&Integer)", &mut |(mut x, y)| { x.div_exact_assign(&y); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivAssignMod, CeilingDivMod, CeilingMod, DivAssignMod, DivAssignRem, DivMod, DivRem, DivRound, Mod, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen_var_1, integer_pair_gen_var_1_nrm, integer_pair_gen_var_1_rm, }; use num::Integer as NumInteger; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_div_mod); register_demo!(runner, demo_integer_div_mod_val_ref); register_demo!(runner, demo_integer_div_mod_ref_val); register_demo!(runner, demo_integer_div_mod_ref_ref); register_demo!(runner, demo_integer_div_assign_mod); register_demo!(runner, demo_integer_div_assign_mod_ref); register_demo!(runner, demo_integer_div_rem); register_demo!(runner, demo_integer_div_rem_val_ref); register_demo!(runner, demo_integer_div_rem_ref_val); register_demo!(runner, demo_integer_div_rem_ref_ref); register_demo!(runner, demo_integer_div_assign_rem); register_demo!(runner, demo_integer_div_assign_rem_ref); register_demo!(runner, demo_integer_ceiling_div_mod); register_demo!(runner, demo_integer_ceiling_div_mod_val_ref); register_demo!(runner, demo_integer_ceiling_div_mod_ref_val); register_demo!(runner, demo_integer_ceiling_div_mod_ref_ref); register_demo!(runner, demo_integer_ceiling_div_assign_mod); register_demo!(runner, demo_integer_ceiling_div_assign_mod_ref); register_bench!(runner, benchmark_integer_div_mod_library_comparison); register_bench!(runner, benchmark_integer_div_mod_algorithms); register_bench!(runner, benchmark_integer_div_mod_evaluation_strategy); register_bench!(runner, benchmark_integer_div_assign_mod_evaluation_strategy); register_bench!(runner, benchmark_integer_div_rem_library_comparison); register_bench!(runner, benchmark_integer_div_rem_algorithms); register_bench!(runner, benchmark_integer_div_rem_evaluation_strategy); register_bench!(runner, benchmark_integer_div_assign_rem_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_div_mod_library_comparison); register_bench!(runner, benchmark_integer_ceiling_div_mod_algorithms); register_bench!( runner, benchmark_integer_ceiling_div_mod_evaluation_strategy ); register_bench!( runner, benchmark_integer_ceiling_div_assign_mod_evaluation_strategy ); } fn demo_integer_div_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_mod({}) = {:?}", x_old, y_old, x.div_mod(y)); } } fn demo_integer_div_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_mod(&{}) = {:?}", x_old, y, x.div_mod(&y)); } } fn demo_integer_div_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_mod({}) = {:?}", x, y_old, (&x).div_mod(y)); } } fn demo_integer_div_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).div_mod(&{}) = {:?}", x, y, (&x).div_mod(&y)); } } fn demo_integer_div_assign_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.div_assign_mod(y); println!("x := {x_old}; x.div_assign_mod({y_old}) = {remainder}; x = {x}"); } } fn demo_integer_div_assign_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.div_assign_mod(&y); println!("x := {x_old}; x.div_assign_mod(&{y}) = {remainder}; x = {x}"); } } fn demo_integer_div_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_rem({}) = {:?}", x_old, y_old, x.div_rem(y)); } } fn demo_integer_div_rem_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_rem(&{}) = {:?}", x_old, y, x.div_rem(&y)); } } fn demo_integer_div_rem_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_rem({}) = {:?}", x, y_old, (&x).div_rem(y)); } } fn demo_integer_div_rem_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).div_rem(&{}) = {:?}", x, y, (&x).div_rem(&y)); } } fn demo_integer_div_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.div_assign_rem(y); println!("x := {x_old}; x.div_assign_rem({y_old}) = {remainder}; x = {x}"); } } fn demo_integer_div_assign_rem_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.div_assign_rem(&y); println!("x := {x_old}; x.div_assign_rem(&{y}) = {remainder}; x = {x}"); } } fn demo_integer_ceiling_div_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.ceiling_div_mod({}) = {:?}", x_old, y_old, x.ceiling_div_mod(y) ); } } fn demo_integer_ceiling_div_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.ceiling_div_mod(&{}) = {:?}", x_old, y, x.ceiling_div_mod(&y) ); } } fn demo_integer_ceiling_div_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).ceiling_div_mod({}) = {:?}", x, y_old, (&x).ceiling_div_mod(y) ); } } fn demo_integer_ceiling_div_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!( "(&{}).ceiling_div_mod(&{}) = {:?}", x, y, (&x).ceiling_div_mod(&y) ); } } fn demo_integer_ceiling_div_assign_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.ceiling_div_assign_mod(y); println!("x := {x_old}; x.ceiling_div_assign_mod({y_old}) = {remainder}; x = {x}"); } } fn demo_integer_ceiling_div_assign_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.ceiling_div_assign_mod(&y); println!("x := {x_old}; x.ceiling_div_assign_mod(&{y}) = {remainder}; x = {x}"); } } fn benchmark_integer_div_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_mod(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_mod(y))), ("num", &mut |((x, y), _, _)| no_out!(x.div_mod_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_rem_floor(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_div_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_mod(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.div_mod(y))), ("using div_round and mod_op", &mut |(x, y)| { no_out!(((&x).div_round(&y, Floor), x.mod_op(y))); }), ], ); } fn benchmark_integer_div_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_mod(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_mod(Integer)", &mut |(x, y)| { no_out!(x.div_mod(y)); }), ("Integer.div_mod(&Integer)", &mut |(x, y)| { no_out!(x.div_mod(&y)); }), ("(&Integer).div_mod(Integer)", &mut |(x, y)| { no_out!((&x).div_mod(y)); }), ("(&Integer).div_mod(&Integer)", &mut |(x, y)| { no_out!((&x).div_mod(&y)); }), ], ); } fn benchmark_integer_div_assign_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_assign_mod(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_assign_mod(Integer)", &mut |(mut x, y)| { no_out!(x.div_assign_mod(y)); }), ("Integer.div_assign_mod(&Integer)", &mut |(mut x, y)| { no_out!(x.div_assign_mod(&y)); }), ], ); } fn benchmark_integer_div_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_rem(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_rem(y))), ("num", &mut |((x, y), _, _)| no_out!(x.div_rem(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_rem(y))), ], ); } #[allow(clippy::no_effect)] fn benchmark_integer_div_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_rem(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.div_rem(y))), ("using / and %", &mut |(x, y)| no_out!((&x / &y, x % y))), ], ); } fn benchmark_integer_div_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_rem(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_rem(Integer)", &mut |(x, y)| { no_out!(x.div_rem(y)); }), ("Integer.div_rem(&Integer)", &mut |(x, y)| { no_out!(x.div_rem(&y)); }), ("(&Integer).div_rem(Integer)", &mut |(x, y)| { no_out!((&x).div_rem(y)); }), ("(&Integer).div_rem(&Integer)", &mut |(x, y)| { no_out!((&x).div_rem(&y)); }), ], ); } fn benchmark_integer_div_assign_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_assign_rem(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.div_assign_rem(Integer)", &mut |(mut x, y)| { no_out!(x.div_assign_rem(y)); }), ("Integer.div_assign_rem(&Integer)", &mut |(mut x, y)| { no_out!(x.div_assign_rem(&y)); }), ], ); } fn benchmark_integer_ceiling_div_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_div_mod(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.ceiling_div_mod(y)); }), ("rug", &mut |((x, y), _)| no_out!(x.div_rem_ceil(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_ceiling_div_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_div_mod(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.ceiling_div_mod(y))), ("using div_round and ceiling_mod", &mut |(x, y)| { ((&x).div_round(&y, Ceiling), x.ceiling_mod(y)); }), ], ); } fn benchmark_integer_ceiling_div_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_div_mod(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_div_mod(Integer)", &mut |(x, y)| { no_out!(x.ceiling_div_mod(y)); }), ("Integer.ceiling_div_mod(&Integer)", &mut |(x, y)| { no_out!(x.ceiling_div_mod(&y)); }), ("(&Integer).ceiling_div_mod(Integer)", &mut |(x, y)| { no_out!((&x).ceiling_div_mod(y)); }), ("(&Integer).ceiling_div_mod(&Integer)", &mut |(x, y)| { no_out!((&x).ceiling_div_mod(&y)); }), ], ); } fn benchmark_integer_ceiling_div_assign_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_div_assign_mod(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ( "Integer.ceiling_div_assign_mod(Integer)", &mut |(mut x, y)| no_out!(x.ceiling_div_assign_mod(y)), ), ( "Integer.ceiling_div_assign_mod(&Integer)", &mut |(mut x, y)| no_out!(x.ceiling_div_assign_mod(&y)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingDivMod, DivRound, DivRoundAssign}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, triple_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_integer_rounding_mode_triple_gen_var_1, integer_pair_gen_var_1, integer_pair_gen_var_1_nrm, integer_pair_gen_var_1_rm, }; use num::Integer as NumInteger; use rug::ops::DivRounding; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_div_round); register_demo!(runner, demo_integer_div_round_val_ref); register_demo!(runner, demo_integer_div_round_ref_val); register_demo!(runner, demo_integer_div_round_ref_ref); register_demo!(runner, demo_integer_div_round_assign); register_demo!(runner, demo_integer_div_round_assign_ref); register_bench!(runner, benchmark_integer_div_round_down_library_comparison); register_bench!(runner, benchmark_integer_div_round_floor_library_comparison); register_bench!( runner, benchmark_integer_div_round_ceiling_library_comparison ); register_bench!(runner, benchmark_integer_div_round_ceiling_algorithms); register_bench!(runner, benchmark_integer_div_round_evaluation_strategy); register_bench!( runner, benchmark_integer_div_round_assign_evaluation_strategy ); } fn demo_integer_div_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.div_round({}, {}) = {:?}", x_old, y_old, rm, x.div_round(y, rm) ); } } fn demo_integer_div_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{}.div_round(&{}, {}) = {:?}", x_old, y, rm, x.div_round(&y, rm) ); } } fn demo_integer_div_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_round({}, {}) = {:?}", x, y_old, rm, (&x).div_round(y, rm) ); } } fn demo_integer_div_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).div_round(&{}, {}) = {:?}", x, y, rm, (&x).div_round(&y, rm) ); } } fn demo_integer_div_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_round_assign(y, rm); println!("x := {x_old}; x.div_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_integer_div_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in integer_integer_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_round_assign(&y, rm); println!("x := {x_old}; x.div_round_assign(&{y}, {rm}) = {o:?}; x = {x}"); } } fn benchmark_integer_div_round_down_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round(Integer, Down)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.div_round(y, Down)); }), ("rug", &mut |((x, y), _)| no_out!(x.div_trunc(y))), ], ); } fn benchmark_integer_div_round_floor_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round(Integer, Floor)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.div_round(y, Floor)); }), ("num", &mut |((x, y), _, _)| no_out!(x.div_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_floor(y))), ], ); } fn benchmark_integer_div_round_ceiling_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round(Integer, Ceiling)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.div_round(y, Ceiling)); }), ("rug", &mut |((x, y), _)| no_out!(x.div_ceil(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_div_round_ceiling_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round(Integer, Ceiling)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.div_round(y, Ceiling))), ("using ceiling_div_mod", &mut |(x, y)| { no_out!(x.ceiling_div_mod(y).0); }), ], ); } fn benchmark_integer_div_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round(Integer, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_integer_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [ ( "Integer.div_round(Integer, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round(y, rm)), ), ( "Integer.div_round(&Integer, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round(&y, rm)), ), ( "(&Integer).div_round(Integer, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).div_round(y, rm)), ), ( "(&Integer).div_round(&Integer, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).div_round(&y, rm)), ), ], ); } fn benchmark_integer_div_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.div_round_assign(Integer, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_integer_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [ ( "Integer.div_round_assign(Integer, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign(y, rm)), ), ( "Integer.div_round_assign(&Integer, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign(&y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_nrm}; use malachite_nz::test_util::integer::arithmetic::divisible_by::num_divisible_by; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_divisible_by); register_demo!(runner, demo_integer_divisible_by_val_ref); register_demo!(runner, demo_integer_divisible_by_ref_val); register_demo!(runner, demo_integer_divisible_by_ref_ref); register_bench!(runner, benchmark_integer_divisible_by_library_comparison); register_bench!(runner, benchmark_integer_divisible_by_algorithms); register_bench!(runner, benchmark_integer_divisible_by_evaluation_strategy); } fn demo_integer_divisible_by(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); if x.divisible_by(y) { println!("{x_old} is divisible by {y_old}"); } else { println!("{x_old} is not divisible by {y_old}"); } } } fn demo_integer_divisible_by_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); if x.divisible_by(&y) { println!("{x_old} is divisible by {y}"); } else { println!("{x_old} is not divisible by {y}"); } } } fn demo_integer_divisible_by_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); if (&x).divisible_by(y) { println!("{x} is divisible by {y_old}"); } else { println!("{x} is not divisible by {y_old}"); } } } fn demo_integer_divisible_by_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if (&x).divisible_by(&y) { println!("{x} is divisible by {y}"); } else { println!("{x} is not divisible by {y}"); } } } fn benchmark_integer_divisible_by_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.divisible_by(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.divisible_by(y)); }), ("num", &mut |((x, y), _, _)| { no_out!(num_divisible_by(&x, &y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x.is_divisible(&y))), ], ); } #[allow(clippy::no_effect, clippy::short_circuit_statement, unused_must_use)] fn benchmark_integer_divisible_by_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.divisible_by(Integer)", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.divisible_by(y))), ("using %", &mut |(x, y)| { no_out!(x == 0 || y != 0 && x % y == 0); }), ], ); } fn benchmark_integer_divisible_by_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.divisible_by(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.divisible_by(Integer)", &mut |(x, y)| { no_out!(x.divisible_by(y)); }), ("Integer.divisible_by(&Integer)", &mut |(x, y)| { no_out!(x.divisible_by(&y)); }), ("(&Integer).divisible_by(Integer)", &mut |(x, y)| { no_out!((&x).divisible_by(y)); }), ("(&Integer).divisible_by(&Integer)", &mut |(x, y)| { no_out!((&x).divisible_by(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_divisible_by_power_of_2); register_bench!( runner, benchmark_integer_divisible_by_power_of_2_library_comparison ); register_bench!(runner, benchmark_integer_divisible_by_power_of_2_algorithms); } fn demo_integer_divisible_by_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { if n.divisible_by_power_of_2(pow) { println!("{n} is divisible by 2^{pow}"); } else { println!("{n} is not divisible by 2^{pow}"); } } } fn benchmark_integer_divisible_by_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.divisible_by_power_of_2(u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (n, pow))| { no_out!(n.divisible_by_power_of_2(pow)); }), ("rug", &mut |((n, pow), _)| { n.is_divisible_2pow(u32::exact_from(pow)); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_divisible_by_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.divisible_by_power_of_2(u64)", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.divisible_by_power_of_2(u64)", &mut |(n, pow)| { no_out!(n.divisible_by_power_of_2(pow)); }), ( "Integer.trailing_zeros().map_or(true, |z| z >= u64)", &mut |(n, pow)| no_out!(n.trailing_zeros().is_none_or(|z| z >= pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, EqMod, UnsignedAbs}; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_triple_gen_var_36, unsigned_vec_unsigned_unsigned_triple_gen_var_5, unsigned_vec_unsigned_unsigned_triple_gen_var_7, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::integer::arithmetic::eq_mod::{ limbs_eq_neg_limb_mod_limb, limbs_pos_eq_neg_limb_mod, limbs_pos_eq_neg_limb_mod_ref, limbs_pos_eq_neg_mod, limbs_pos_eq_neg_mod_limb, limbs_pos_eq_neg_mod_ref, limbs_pos_limb_eq_neg_limb_mod, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_triple_1_2_integer_max_bit_bucketer, triple_1_2_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_integer_natural_triple_gen, integer_integer_natural_triple_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_eq_neg_limb_mod_limb); register_demo!(runner, demo_limbs_pos_limb_eq_neg_limb_mod); register_demo!(runner, demo_limbs_pos_eq_neg_limb_mod); register_demo!(runner, demo_limbs_pos_eq_neg_limb_mod_ref); register_demo!(runner, demo_limbs_pos_eq_neg_mod_limb); register_demo!(runner, demo_limbs_pos_eq_neg_mod); register_demo!(runner, demo_limbs_pos_eq_neg_mod_ref); register_demo!(runner, demo_integer_eq_mod); register_demo!(runner, demo_integer_eq_mod_val_val_ref); register_demo!(runner, demo_integer_eq_mod_val_ref_val); register_demo!(runner, demo_integer_eq_mod_val_ref_ref); register_demo!(runner, demo_integer_eq_mod_ref_val_val); register_demo!(runner, demo_integer_eq_mod_ref_val_ref); register_demo!(runner, demo_integer_eq_mod_ref_ref_val); register_demo!(runner, demo_integer_eq_mod_ref_ref_ref); register_bench!(runner, benchmark_limbs_eq_neg_limb_mod_limb); register_bench!(runner, benchmark_limbs_pos_limb_eq_neg_limb_mod); register_bench!( runner, benchmark_limbs_pos_eq_neg_limb_mod_evaluation_strategy ); register_bench!(runner, benchmark_limbs_pos_eq_neg_mod_limb); register_bench!(runner, benchmark_limbs_pos_eq_neg_mod_evaluation_strategy); register_bench!(runner, benchmark_integer_eq_mod_evaluation_strategy); register_bench!(runner, benchmark_integer_eq_mod_library_comparison); register_bench!(runner, benchmark_integer_eq_mod_algorithms); } fn demo_limbs_eq_neg_limb_mod_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y, m) in unsigned_vec_unsigned_unsigned_triple_gen_var_7() .get(gm, config) .take(limit) { println!( "limbs_eq_neg_limb_mod_limb({:?}, {}, {}) = {}", xs, y, m, limbs_eq_neg_limb_mod_limb(&xs, y, m) ); } } fn demo_limbs_pos_limb_eq_neg_limb_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (m, x, y) in unsigned_vec_unsigned_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { println!( "limbs_pos_limb_eq_neg_limb_mod({}, {}, {:?}) = {}", x, y, m, limbs_pos_limb_eq_neg_limb_mod(x, y, &m) ); } } fn demo_limbs_pos_eq_neg_limb_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut m, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_m = m.clone(); println!( "limbs_pos_eq_neg_limb_mod({:?}, {}, {:?}) = {}", xs, y, old_m, limbs_pos_eq_neg_limb_mod(&xs, y, &mut m) ); } } fn demo_limbs_pos_eq_neg_limb_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, m, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "limbs_pos_eq_neg_limb_mod_ref({:?}, {}, {:?}) = {}", xs, y, m, limbs_pos_eq_neg_limb_mod_ref(&xs, y, &m) ); } } fn demo_limbs_pos_eq_neg_mod_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, m) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "limbs_pos_eq_neg_mod_limb({:?}, {:?}, {}) = {}", xs, ys, m, limbs_pos_eq_neg_mod_limb(&xs, &ys, m) ); } } fn demo_limbs_pos_eq_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, mut m) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { let old_m = m.clone(); println!( "limbs_pos_eq_neg_mod({:?}, {:?}, {:?}) = {}", xs, ys, old_m, limbs_pos_eq_neg_mod(&xs, &ys, &mut m) ); } } fn demo_limbs_pos_eq_neg_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, m) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { println!( "limbs_pos_eq_neg_mod_ref({:?}, {:?}, {:?}) = {}", xs, ys, m, limbs_pos_eq_neg_mod_ref(&xs, &ys, &m) ); } } fn demo_integer_eq_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); if x.eq_mod(y, m) { println!("{x_old} is equal to {y_old} mod {m_old}"); } else { println!("{x_old} is not equal to {y_old} mod {m_old}"); } } } fn demo_integer_eq_mod_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); if x.eq_mod(y, &m) { println!("{x_old} is equal to {y_old} mod &{m}"); } else { println!("{x_old} is not equal to {y_old} mod &{m}"); } } } fn demo_integer_eq_mod_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let x_old = x.clone(); let m_old = m.clone(); if x.eq_mod(&y, m) { println!("{x_old} is equal to &{y} mod {m_old}"); } else { println!("{x_old} is not equal to &{y} mod {m_old}"); } } } fn demo_integer_eq_mod_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let x_old = x.clone(); if x.eq_mod(&y, &m) { println!("{x_old} is equal to &{y} mod &{m}"); } else { println!("{x_old} is not equal to &{y} mod &{m}"); } } } fn demo_integer_eq_mod_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let y_old = y.clone(); let m_old = m.clone(); if (&x).eq_mod(y, m) { println!("&{x} is equal to {y_old} mod {m_old}"); } else { println!("&{x} is not equal to {y_old} mod {m_old}"); } } } fn demo_integer_eq_mod_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let y_old = y.clone(); if (&x).eq_mod(y, &m) { println!("&{x} is equal to {y_old} mod &{m}"); } else { println!("&{x} is not equal to {y_old} mod &{m}"); } } } fn demo_integer_eq_mod_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { let m_old = m.clone(); if (&x).eq_mod(&y, m) { println!("&{x} is equal to &{y} mod {m_old}"); } else { println!("&{x} is not equal to &{y} mod {m_old}"); } } } fn demo_integer_eq_mod_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in integer_integer_natural_triple_gen() .get(gm, config) .take(limit) { if (&x).eq_mod(&y, &m) { println!("&{x} is equal to &{y} mod &{m}"); } else { println!("&{x} is not equal to &{y} mod &{m}"); } } } fn benchmark_limbs_eq_neg_limb_mod_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_neg_limb_mod_limb(&mut [Limb], Limb, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("limbs_eq_neg_limb_mod_limb", &mut |(xs, y, m)| { no_out!(limbs_eq_neg_limb_mod_limb(&xs, y, m)); })], ); } fn benchmark_limbs_pos_limb_eq_neg_limb_mod( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_limb_eq_neg_limb_mod(Limb, Limb, &[Limb])", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("m"), &mut [("limbs_pos_limb_eq_neg_limb_mod", &mut |(m, x, y)| { no_out!(limbs_pos_limb_eq_neg_limb_mod(x, y, &m)); })], ); } fn benchmark_limbs_pos_eq_neg_limb_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_limb(&[Limb], Limb, &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("limbs_pos_eq_neg_limb_mod", &mut |(xs, mut m, y)| { no_out!(limbs_pos_eq_neg_limb_mod(&xs, y, &mut m)); }), ("limbs_pos_eq_neg_limb_mod_ref", &mut |(xs, m, y)| { no_out!(limbs_pos_eq_neg_limb_mod_ref(&xs, y, &m)); }), ], ); } fn benchmark_limbs_pos_eq_neg_mod_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_eq_neg_mod_limb(&[Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("limbs_pos_eq_neg_mod_limb", &mut |(xs, ys, m)| { no_out!(limbs_pos_eq_neg_mod_limb(&xs, &ys, m)); })], ); } fn benchmark_limbs_pos_eq_neg_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_limb(&[Limb], &[Limb], &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_triple_gen_var_36().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [ ("limbs_pos_eq_neg_mod", &mut |(ref xs, ref y, ref mut m)| { no_out!(limbs_pos_eq_neg_mod(xs, y, m)); }), ("limbs_pos_eq_neg_mod_ref", &mut |(ref xs, ref y, ref m)| { no_out!(limbs_pos_eq_neg_mod_ref(xs, y, m)); }), ], ); } fn benchmark_integer_eq_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_mod(Integer, Natural)", BenchmarkType::EvaluationStrategy, integer_integer_natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer.eq_mod(Integer, Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, m)); }), ("Integer.eq_mod(Integer, &Integer)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, &m)); }), ("Integer.eq_mod(&Integer, Integer)", &mut |(x, y, m)| { no_out!(x.eq_mod(&y, m)); }), ("Integer.eq_mod(&Integer, &Integer)", &mut |(x, y, m)| { no_out!(x.eq_mod(&y, &m)); }), ("(&Integer).eq_mod(Integer, Natural)", &mut |(x, y, m)| { no_out!((&x).eq_mod(y, m)); }), ("(&Integer).eq_mod(Integer, &Integer)", &mut |(x, y, m)| { no_out!((&x).eq_mod(y, &m)); }), ("(&Integer).eq_mod(&Integer, Integer)", &mut |(x, y, m)| { no_out!((&x).eq_mod(&y, m)); }), ("(&Integer).eq_mod(&Integer, &Integer)", &mut |(x, y, m)| { no_out!((&x).eq_mod(&y, &m)); }), ], ); } fn benchmark_integer_eq_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_mod(Integer, Natural)", BenchmarkType::LibraryComparison, integer_integer_natural_triple_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, m))| no_out!(x.eq_mod(y, m))), ("rug", &mut |((x, y, m), _)| no_out!(x.is_congruent(&y, &m))), ], ); } #[allow(clippy::short_circuit_statement, unused_must_use)] fn benchmark_integer_eq_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_mod(Integer, Natural)", BenchmarkType::Algorithms, integer_integer_natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer.eq_mod(Integer, Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, m)); }), ( "Integer == Integer || Integer != 0 && Integer % Natural == Integer % Natural", &mut |(x, y, m)| { no_out!(x == y || m != 0 && x.unsigned_abs() % &m == y.unsigned_abs() % m); }, ), ( "(Integer - Integer).divisible_by(Natural)", &mut |(x, y, m)| no_out!((x - y).divisible_by(Integer::from(m))), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::EqModPowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_unsigned_triple_gen_var_8, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::arithmetic::eq_mod_power_of_2::{ limbs_eq_mod_power_of_2_neg_limb, limbs_eq_mod_power_of_2_neg_pos, }; use malachite_nz::test_util::bench::bucketers::pair_2_triple_1_2_integer_max_bit_bucketer; use malachite_nz::test_util::generators::{ integer_integer_unsigned_triple_gen_var_1, integer_integer_unsigned_triple_gen_var_1_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_eq_mod_power_of_2_neg_limb); register_demo!(runner, demo_limbs_eq_mod_power_of_2_neg_pos); register_demo!(runner, demo_integer_eq_mod_power_of_2); register_bench!(runner, benchmark_limbs_eq_mod_power_of_2_neg_limb); register_bench!(runner, benchmark_limbs_eq_mod_power_of_2_neg_pos); register_bench!( runner, benchmark_integer_eq_mod_power_of_2_library_comparison ); } fn demo_limbs_eq_mod_power_of_2_neg_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_8() .get(gm, config) .take(limit) { println!( "limbs_eq_mod_power_of_2_neg_limb({:?}, {}, {}) = {:?}", xs, y, pow, limbs_eq_mod_power_of_2_neg_limb(&xs, y, pow) ); } } fn demo_limbs_eq_mod_power_of_2_neg_pos(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9() .get(gm, config) .take(limit) { println!( "limbs_eq_mod_power_of_2_neg_pos({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_eq_mod_power_of_2_neg_pos(&xs, &ys, pow) ); } } fn demo_integer_eq_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in integer_integer_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { if x.eq_mod_power_of_2(&y, pow) { println!("{x} is equal to {y} mod 2^{pow}"); } else { println!("{x} is not equal to {y} mod 2^{pow}"); } } } fn benchmark_limbs_eq_mod_power_of_2_neg_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_power_of_2_neg_limb(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_8().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y, pow)| { no_out!(limbs_eq_mod_power_of_2_neg_limb(&xs, y, pow)); })], ); } fn benchmark_limbs_eq_mod_power_of_2_neg_pos( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_power_of_2_neg_pos(&[Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref ys, pow)| { no_out!(limbs_eq_mod_power_of_2_neg_pos(xs, ys, pow)); })], ); } fn benchmark_integer_eq_mod_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_mod_power_of_2(&Integer, u64)", BenchmarkType::LibraryComparison, integer_integer_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (ref n, ref u, pow))| { no_out!(n.eq_mod_power_of_2(u, pow)); }), ("rug", &mut |((ref n, ref u, pow), _)| { no_out!(n.is_congruent_2pow(u, u32::exact_from(pow))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ExtendedGcd; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_integer_max_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_nrm}; use num::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_extended_gcd); register_demo!(runner, demo_integer_extended_gcd_val_ref); register_demo!(runner, demo_integer_extended_gcd_ref_val); register_demo!(runner, demo_integer_extended_gcd_ref_ref); register_bench!(runner, benchmark_integer_extended_gcd_library_comparison); register_bench!(runner, benchmark_integer_extended_gcd_evaluation_strategy); } fn demo_integer_extended_gcd(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).extended_gcd({}) = {:?}", x_old, y_old, x.extended_gcd(y) ); } } fn demo_integer_extended_gcd_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "({}).extended_gcd(&{}) = {:?}", x_old, y, x.extended_gcd(&y) ); } } fn demo_integer_extended_gcd_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).extended_gcd({}) = {:?}", x, y_old, (&x).extended_gcd(y) ); } } fn demo_integer_extended_gcd_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!( "(&{}).extended_gcd(&{}) = {:?}", x, y, (&x).extended_gcd(&y) ); } } fn benchmark_integer_extended_gcd_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.extended_gcd(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.extended_gcd(y)); }), ("num", &mut |((x, y), _, _)| no_out!(x.extended_gcd(&y))), ("rug", &mut |(_, (x, y), _)| { no_out!(x.extended_gcd(y, rug::Integer::new())); }), ], ); } fn benchmark_integer_extended_gcd_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.extended_gcd(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer.extended_gcd(Integer)", &mut |(x, y)| { no_out!(x.extended_gcd(y)); }), ("Integer.extended_gcd(&Integer)", &mut |(x, y)| { no_out!(x.extended_gcd(&y)); }), ("&Integer.extended_gcd(Integer)", &mut |(x, y)| { no_out!((&x).extended_gcd(y)); }), ("&Integer.extended_gcd(&Integer)", &mut |(x, y)| { no_out!((&x).extended_gcd(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{JacobiSymbol, KroneckerSymbol}; use malachite_base::test_util::bench::bucketers::quadruple_1_3_vec_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::large_type_gen_var_27; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::arithmetic::kronecker_symbol::limbs_kronecker_symbol; use malachite_nz::test_util::bench::bucketers::{ pair_2_integer_bit_bucketer, pair_2_pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen, integer_pair_gen_rm, integer_pair_gen_var_4, integer_pair_gen_var_4_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_kronecker_symbol); register_demo!(runner, demo_integer_jacobi_symbol); register_demo!(runner, demo_integer_jacobi_symbol_val_ref); register_demo!(runner, demo_integer_jacobi_symbol_ref_val); register_demo!(runner, demo_integer_jacobi_symbol_ref_ref); register_demo!(runner, demo_integer_kronecker_symbol); register_demo!(runner, demo_integer_kronecker_symbol_val_ref); register_demo!(runner, demo_integer_kronecker_symbol_ref_val); register_demo!(runner, demo_integer_kronecker_symbol_ref_ref); register_bench!(runner, benchmark_limbs_kronecker_symbol); register_bench!(runner, benchmark_integer_jacobi_symbol_library_comparison); register_bench!(runner, benchmark_integer_jacobi_symbol_evaluation_strategy); register_bench!( runner, benchmark_integer_kronecker_symbol_library_comparison ); register_bench!( runner, benchmark_integer_kronecker_symbol_evaluation_strategy ); } fn demo_limbs_kronecker_symbol(gm: GenMode, config: &GenConfig, limit: usize) { for (x_sign, xs, y_sign, ys) in large_type_gen_var_27().get(gm, config).take(limit) { println!( "limbs_kronecker_symbol({}, {:?}, {}, {:?}) = {}", x_sign, xs, y_sign, ys, limbs_kronecker_symbol(x_sign, &xs, y_sign, &ys) ); } } fn demo_integer_jacobi_symbol(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen_var_4().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!( "({}).jacobi_symbol({}) = {}", n_old, m_old, n.jacobi_symbol(m) ); } } fn demo_integer_jacobi_symbol_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen_var_4().get(gm, config).take(limit) { let n_old = n.clone(); println!("({}).jacobi_symbol({}) = {}", n_old, m, n.jacobi_symbol(&m)); } } fn demo_integer_jacobi_symbol_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen_var_4().get(gm, config).take(limit) { let m_old = m.clone(); println!( "({}).jacobi_symbol({}) = {}", n, m_old, (&n).jacobi_symbol(m) ); } } fn demo_integer_jacobi_symbol_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen_var_4().get(gm, config).take(limit) { println!("({}).jacobi_symbol({}) = {}", n, m, (&n).jacobi_symbol(&m)); } } fn demo_integer_kronecker_symbol(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!( "({}).kronecker_symbol({}) = {}", n_old, m_old, n.kronecker_symbol(m) ); } } fn demo_integer_kronecker_symbol_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen().get(gm, config).take(limit) { let n_old = n.clone(); println!( "({}).kronecker_symbol({}) = {}", n_old, m, n.kronecker_symbol(&m) ); } } fn demo_integer_kronecker_symbol_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen().get(gm, config).take(limit) { let m_old = m.clone(); println!( "({}).kronecker_symbol({}) = {}", n, m_old, (&n).kronecker_symbol(m) ); } } fn demo_integer_kronecker_symbol_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in integer_pair_gen().get(gm, config).take(limit) { println!( "({}).kronecker_symbol({}) = {}", n, m, (&n).kronecker_symbol(&m) ); } } fn benchmark_limbs_kronecker_symbol( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_kronecker_symbol(bool, &[Limb], bool, &[Limb])", BenchmarkType::Single, large_type_gen_var_27().get(gm, config), gm.name(), limit, file_name, &quadruple_1_3_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(x_sign, xs, y_sign, ys)| { no_out!(limbs_kronecker_symbol(x_sign, &xs, y_sign, &ys)); })], ); } fn benchmark_integer_jacobi_symbol_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.jacobi_symbol(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_4_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.jacobi_symbol(y))), ("rug", &mut |((x, y), _)| no_out!(x.jacobi(&y))), ], ); } fn benchmark_integer_jacobi_symbol_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.jacobi_symbol(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("m"), &mut [ ("Integer.jacobi_symbol(Integer)", &mut |(n, m)| { no_out!(n.jacobi_symbol(m)); }), ("Integer.jacobi_symbol(&Integer)", &mut |(n, m)| { no_out!(n.jacobi_symbol(&m)); }), ("(&Integer).jacobi_symbol(Integer)", &mut |(n, m)| { no_out!((&n).jacobi_symbol(m)); }), ("(&Integer).jacobi_symbol(&Integer)", &mut |(n, m)| { no_out!((&n).jacobi_symbol(&m)); }), ], ); } fn benchmark_integer_kronecker_symbol_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.kronecker_symbol(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.kronecker_symbol(y)); }), ("rug", &mut |((x, y), _)| no_out!(x.kronecker(&y))), ], ); } fn benchmark_integer_kronecker_symbol_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.kronecker_symbol(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("m"), &mut [ ("Integer.kronecker_symbol(Integer)", &mut |(n, m)| { no_out!(n.kronecker_symbol(m)); }), ("Integer.kronecker_symbol(&Integer)", &mut |(n, m)| { no_out!(n.kronecker_symbol(&m)); }), ("(&Integer).kronecker_symbol(Integer)", &mut |(n, m)| { no_out!((&n).kronecker_symbol(m)); }), ("(&Integer).kronecker_symbol(&Integer)", &mut |(n, m)| { no_out!((&n).kronecker_symbol(&m)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs::register(runner); abs_diff::register(runner); add::register(runner); add_mul::register(runner); binomial_coefficient::register(runner); div::register(runner); div_exact::register(runner); div_mod::register(runner); div_round::register(runner); divisible_by::register(runner); divisible_by_power_of_2::register(runner); eq_mod::register(runner); eq_mod_power_of_2::register(runner); extended_gcd::register(runner); kronecker_symbol::register(runner); mod_op::register(runner); mod_power_of_2::register(runner); mul::register(runner); neg::register(runner); parity::register(runner); pow::register(runner); power_of_2::register(runner); root::register(runner); round_to_multiple::register(runner); round_to_multiple_of_power_of_2::register(runner); shl::register(runner); shl_round::register(runner); shr::register(runner); shr_round::register(runner); sign::register(runner); sqrt::register(runner); square::register(runner); sub::register(runner); sub_mul::register(runner); } mod abs; mod abs_diff; mod add; mod add_mul; mod binomial_coefficient; mod div; mod div_exact; mod div_mod; mod div_round; mod divisible_by; mod divisible_by_power_of_2; mod eq_mod; mod eq_mod_power_of_2; mod extended_gcd; mod kronecker_symbol; mod mod_op; mod mod_power_of_2; mod mul; mod neg; mod parity; mod pow; mod power_of_2; mod root; mod round_to_multiple; mod round_to_multiple_of_power_of_2; mod shl; mod shl_round; mod shr; mod shr_round; mod sign; mod sqrt; mod square; mod sub; mod sub_mul; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivMod, CeilingMod, CeilingModAssign, DivMod, DivRem, Mod, ModAssign, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen_var_1, integer_pair_gen_var_1_nrm, integer_pair_gen_var_1_rm, }; use num::Integer as NumInteger; use rug::ops::RemRounding; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_mod); register_demo!(runner, demo_integer_mod_val_ref); register_demo!(runner, demo_integer_mod_ref_val); register_demo!(runner, demo_integer_mod_ref_ref); register_demo!(runner, demo_integer_mod_assign); register_demo!(runner, demo_integer_mod_assign_ref); register_demo!(runner, demo_integer_rem); register_demo!(runner, demo_integer_rem_val_ref); register_demo!(runner, demo_integer_rem_ref_val); register_demo!(runner, demo_integer_rem_ref_ref); register_demo!(runner, demo_integer_rem_assign); register_demo!(runner, demo_integer_rem_assign_ref); register_demo!(runner, demo_integer_ceiling_mod); register_demo!(runner, demo_integer_ceiling_mod_val_ref); register_demo!(runner, demo_integer_ceiling_mod_ref_val); register_demo!(runner, demo_integer_ceiling_mod_ref_ref); register_demo!(runner, demo_integer_ceiling_mod_assign); register_demo!(runner, demo_integer_ceiling_mod_assign_ref); register_bench!(runner, benchmark_integer_mod_library_comparison); register_bench!(runner, benchmark_integer_mod_algorithms); register_bench!(runner, benchmark_integer_mod_evaluation_strategy); register_bench!(runner, benchmark_integer_mod_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_rem_library_comparison); register_bench!(runner, benchmark_integer_rem_algorithms); register_bench!(runner, benchmark_integer_rem_evaluation_strategy); register_bench!(runner, benchmark_integer_rem_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_mod_library_comparison); register_bench!(runner, benchmark_integer_ceiling_mod_algorithms); register_bench!(runner, benchmark_integer_ceiling_mod_evaluation_strategy); register_bench!( runner, benchmark_integer_ceiling_mod_assign_evaluation_strategy ); } fn demo_integer_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.mod_op({}) = {}", x_old, y_old, x.mod_op(y)); } } fn demo_integer_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.mod_op(&{}) = {}", x_old, y, x.mod_op(&y)); } } fn demo_integer_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).mod_op({}) = {:?}", x, y_old, (&x).mod_op(y)); } } fn demo_integer_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).mod_op(&{}) = {:?}", x, y, (&x).mod_op(&y)); } } fn demo_integer_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_assign(y); println!("x := {x_old}; x.mod_assign({y_old}); x = {x}"); } } fn demo_integer_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_assign(&y); println!("x := {x_old}; x.mod_assign(&{y}); x = {x}"); } } fn demo_integer_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} % {} = {:?}", x_old, y_old, x % y); } } fn demo_integer_rem_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} % &{} = {:?}", x_old, y, x % &y); } } fn demo_integer_rem_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} % {} = {:?}", x, y_old, &x % y); } } fn demo_integer_rem_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("&{} % &{} = {:?}", x, y, &x % &y); } } fn demo_integer_rem_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x %= y; println!("x := {x_old}; x %= {y_old}; x = {x}"); } } fn demo_integer_rem_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x %= &y; println!("x := {x_old}; x %= &{y}; x = {x}"); } } fn demo_integer_ceiling_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.ceiling_mod({}) = {}", x_old, y_old, x.ceiling_mod(y)); } } fn demo_integer_ceiling_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.ceiling_mod(&{}) = {}", x_old, y, x.ceiling_mod(&y)); } } fn demo_integer_ceiling_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).ceiling_mod({}) = {}", x, y_old, (&x).ceiling_mod(y)); } } fn demo_integer_ceiling_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).ceiling_mod(&{}) = {}", x, y, (&x).ceiling_mod(&y)); } } fn demo_integer_ceiling_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.ceiling_mod_assign(y); println!("x := {x_old}; x.ceiling_mod_assign({y_old}); x = {x}"); } } fn demo_integer_ceiling_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.ceiling_mod_assign(&y); println!("x := {x_old}; x.ceiling_mod_assign(&{y}); x = {x}"); } } fn benchmark_integer_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_op(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.mod_op(y))), ("num", &mut |((x, y), _, _)| no_out!(x.mod_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.rem_floor(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_op(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.mod_op(y))), ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y).1)), ], ); } fn benchmark_integer_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_op(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.mod_op(Integer)", &mut |(x, y)| { no_out!(x.mod_op(y)); }), ("Integer.mod_op(&Integer)", &mut |(x, y)| { no_out!(x.mod_op(&y)); }), ("(&Integer).mod_op(Integer)", &mut |(x, y)| { no_out!((&x).mod_op(y)); }), ("(&Integer).mod_op(&Integer)", &mut |(x, y)| { no_out!((&x).mod_op(&y)); }), ], ); } fn benchmark_integer_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_assign(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.mod_assign(Integer)", &mut |(mut x, y)| { no_out!(x.mod_assign(y)); }), ("Integer.mod_assign(&Integer)", &mut |(mut x, y)| { no_out!(x.mod_assign(&y)); }), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x % y)), ("num", &mut |((x, y), _, _)| no_out!(x % y)), ("rug", &mut |(_, (x, y), _)| no_out!(x % y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x % y)), ("using div_rem", &mut |(x, y)| no_out!(x.div_rem(y).1)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer % Integer", &mut |(x, y)| no_out!(x % y)), ("Integer % &Integer", &mut |(x, y)| no_out!(x % &y)), ("&Integer % Integer", &mut |(x, y)| no_out!(&x % y)), ("&Integer % &Integer", &mut |(x, y)| no_out!(&x % &y)), ], ); } fn benchmark_integer_rem_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem_assign(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer %= Integer", &mut |(mut x, y)| x %= y), ("Integer %= &Integer", &mut |(mut x, y)| x %= &y), ], ); } fn benchmark_integer_ceiling_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod(Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.ceiling_mod(y))), ("rug", &mut |((x, y), _)| no_out!(x.rem_ceil(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_ceiling_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod(Integer)", BenchmarkType::Algorithms, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.ceiling_mod(y))), ("using ceiling_div_mod", &mut |(x, y)| { no_out!(x.ceiling_div_mod(y).1); }), ], ); } fn benchmark_integer_ceiling_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_mod(Integer)", &mut |(x, y)| { no_out!(x.ceiling_mod(y)); }), ("Integer.ceiling_mod(&Integer)", &mut |(x, y)| { no_out!(x.ceiling_mod(&y)); }), ("(&Integer).ceiling_mod(Integer)", &mut |(x, y)| { no_out!((&x).ceiling_mod(y)); }), ("(&Integer).ceiling_mod(&Integer)", &mut |(x, y)| { no_out!((&x).ceiling_mod(&y)); }), ], ); } fn benchmark_integer_ceiling_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod_assign(Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_mod_assign(Integer)", &mut |(mut x, y)| { no_out!(x.ceiling_mod_assign(y)); }), ("Integer.ceiling_mod_assign(&Integer)", &mut |(mut x, y)| { no_out!(x.ceiling_mod_assign(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingModPowerOf2, CeilingModPowerOf2Assign, ModPowerOf2, ModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign, }; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_mod_power_of_2_assign); register_demo!(runner, demo_integer_mod_power_of_2); register_demo!(runner, demo_integer_mod_power_of_2_ref); register_demo!(runner, demo_integer_rem_power_of_2_assign); register_demo!(runner, demo_integer_rem_power_of_2); register_demo!(runner, demo_integer_rem_power_of_2_ref); register_demo!(runner, demo_integer_ceiling_mod_power_of_2_assign); register_demo!(runner, demo_integer_ceiling_mod_power_of_2); register_demo!(runner, demo_integer_ceiling_mod_power_of_2_ref); register_bench!(runner, benchmark_integer_mod_power_of_2_assign); register_bench!(runner, benchmark_integer_mod_power_of_2_evaluation_strategy); register_bench!(runner, benchmark_integer_rem_power_of_2_assign); register_bench!(runner, benchmark_integer_rem_power_of_2_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_mod_power_of_2_assign); register_bench!( runner, benchmark_integer_ceiling_mod_power_of_2_evaluation_strategy ); } fn demo_integer_mod_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_assign(u); println!("x := {n_old}; x.mod_power_of_2_assign({u}); x = {n}"); } } fn demo_integer_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.mod_power_of_2({}) = {}", n_old, u, n.mod_power_of_2(u)); } } fn demo_integer_mod_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).mod_power_of_2({}) = {}", n, u, (&n).mod_power_of_2(u) ); } } fn demo_integer_rem_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.rem_power_of_2_assign(u); println!("x := {n_old}; x.rem_power_of_2_assign({u}); x = {n}"); } } fn demo_integer_rem_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.rem_power_of_2({}) = {}", n_old, u, n.rem_power_of_2(u)); } } fn demo_integer_rem_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).rem_power_of_2({}) = {}", n, u, (&n).rem_power_of_2(u) ); } } fn demo_integer_ceiling_mod_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.ceiling_mod_power_of_2_assign(u); println!("x := {n_old}; x.ceiling_mod_power_of_2_assign({u}); x = {n}"); } } fn demo_integer_ceiling_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.ceiling_mod_power_of_2({}) = {}", n_old, u, n.ceiling_mod_power_of_2(u) ); } } fn demo_integer_ceiling_mod_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).ceiling_mod_power_of_2({}) = {}", n, u, (&n).ceiling_mod_power_of_2(u) ); } } fn benchmark_integer_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_power_of_2_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, u)| n.mod_power_of_2_assign(u))], ); } fn benchmark_integer_mod_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.mod_power_of_2(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [ ("Integer.mod_power_of_2(u64)", &mut |(n, u)| { no_out!(n.mod_power_of_2(u)); }), ("(&Integer).mod_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).mod_power_of_2(u)); }), ], ); } fn benchmark_integer_rem_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem_power_of_2_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, u)| n.rem_power_of_2_assign(u))], ); } fn benchmark_integer_rem_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.rem_power_of_2(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [ ("Integer.rem_power_of_2(u64)", &mut |(n, u)| { no_out!(n.rem_power_of_2(u)); }), ("(&Integer).rem_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).rem_power_of_2(u)); }), ], ); } fn benchmark_integer_ceiling_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod_power_of_2_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, u)| { n.ceiling_mod_power_of_2_assign(u); })], ); } fn benchmark_integer_ceiling_mod_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_mod_power_of_2(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [ ("Integer.ceiling_mod_power_of_2(u64)", &mut |(n, u)| { no_out!(n.ceiling_mod_power_of_2(u)); }), ("(&Integer).ceiling_mod_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).ceiling_mod_power_of_2(u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, triple_3_vec_integer_sum_bits_bucketer, vec_integer_sum_bits_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen, integer_pair_gen_nrm, integer_pair_gen_rm, integer_vec_gen, integer_vec_gen_nrm, }; use malachite_nz::test_util::integer::arithmetic::mul::integer_product_naive; use num::BigInt; use std::iter::Product; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_mul); register_demo!(runner, demo_integer_mul_val_ref); register_demo!(runner, demo_integer_mul_ref_val); register_demo!(runner, demo_integer_mul_ref_ref); register_demo!(runner, demo_integer_mul_assign); register_demo!(runner, demo_integer_mul_assign_ref); register_demo!(runner, demo_integer_product); register_demo!(runner, demo_integer_ref_product); register_bench!(runner, benchmark_integer_mul_library_comparison); register_bench!(runner, benchmark_integer_mul_evaluation_strategy); register_bench!(runner, benchmark_integer_mul_assign_library_comparison); register_bench!(runner, benchmark_integer_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_product_algorithms); register_bench!(runner, benchmark_integer_product_library_comparison); register_bench!(runner, benchmark_integer_product_evaluation_strategy); } fn demo_integer_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_integer_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_integer_mul_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_integer_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_integer_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x *= {y}; x = {x}"); } } fn demo_integer_mul_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x *= &{y}; x = {x}"); } } fn demo_integer_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in integer_vec_gen().get(gm, config).take(limit) { println!( "product({:?}) = {}", xs.clone(), Integer::product(xs.into_iter()) ); } } fn demo_integer_ref_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in integer_vec_gen().get(gm, config).take(limit) { println!("product({:?}) = {}", xs, Integer::product(xs.iter())); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_mul_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer * Integer", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x * y)), ("num", &mut |((x, y), _, _)| no_out!(x * y)), ("rug", &mut |(_, (x, y), _)| no_out!(x * y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer * Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer * Integer", &mut |(x, y)| no_out!(x * y)), ("Integer * &Integer", &mut |(x, y)| no_out!(x * &y)), ("&Integer * Integer", &mut |(x, y)| no_out!(&x * y)), ("&Integer * &Integer", &mut |(x, y)| no_out!(&x * &y)), ], ); } fn benchmark_integer_mul_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer *= Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x *= y), ("rug", &mut |((mut x, y), _)| x *= y)], ); } fn benchmark_integer_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer *= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer *= Integer", &mut |(mut x, y)| no_out!(x *= y)), ("Integer *= &Integer", &mut |(mut x, y)| no_out!(x *= &y)), ], ); } fn benchmark_integer_product_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::product(Iterator)", BenchmarkType::LibraryComparison, integer_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_integer_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Integer::product(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigInt::product(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Integer::product(xs.iter())); }), ], ); } fn benchmark_integer_product_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::product(Iterator)", BenchmarkType::Algorithms, integer_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_integer_sum_bits_bucketer(), &mut [ ("default", &mut |xs| { no_out!(Integer::product(xs.into_iter())); }), ("naive", &mut |xs| { no_out!(integer_product_naive(xs.into_iter())); }), ], ); } fn benchmark_integer_product_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::product(Iterator)", BenchmarkType::EvaluationStrategy, integer_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_integer_sum_bits_bucketer(), &mut [ ("Integer::product(Iterator)", &mut |xs| { no_out!(Integer::product(xs.into_iter())); }), ("Integer::product(Iterator)", &mut |xs| { no_out!(Integer::product(xs.iter())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, triple_3_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_gen, integer_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_neg); register_demo!(runner, demo_integer_neg_ref); register_demo!(runner, demo_integer_neg_assign); register_bench!(runner, benchmark_integer_neg_library_comparison); register_bench!(runner, benchmark_integer_neg_evaluation_strategy); register_bench!(runner, benchmark_integer_neg_assign); } fn demo_integer_neg(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("-{} = {}", n.clone(), -n); } } fn demo_integer_neg_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("-(&{}) = {}", n.clone(), -n); } } fn demo_integer_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in integer_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.neg_assign(); println!("n := {n_old}; n.neg_assign(); n = {n}"); } } #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn benchmark_integer_neg_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Integer", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(-x)), ("num", &mut |(x, _, _)| no_out!(-x)), ("rug", &mut |(_, x, _)| no_out!(-x)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_integer_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Integer", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("-Integer", &mut |x| no_out!(-x)), ("-&Integer", &mut |x| no_out!(-&x))], ); } fn benchmark_integer_neg_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "-Integer", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.neg_assign())], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_even); register_demo!(runner, demo_integer_odd); register_bench!(runner, benchmark_integer_even); register_bench!(runner, benchmark_integer_odd); } fn demo_integer_even(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { if n.even() { println!("{n} is even"); } else { println!("{n} is not even"); } } } fn demo_integer_odd(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { if n.even() { println!("{n} is odd"); } else { println!("{n} is not odd"); } } } fn benchmark_integer_even(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.even()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.even()))], ); } fn benchmark_integer_odd(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.odd()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.odd()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Pow, PowAssign}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::pair_1_bits_times_pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_pair_1_integer_bits_times_pair_2_bucketer; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_nrm, }; use rug::ops::Pow as RugPow; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_pow_assign); register_demo!(runner, demo_integer_pow); register_demo!(runner, demo_integer_pow_ref); register_bench!(runner, benchmark_integer_pow_assign); register_bench!(runner, benchmark_integer_pow_library_comparison); register_bench!(runner, benchmark_integer_pow_evaluation_strategy); } fn demo_integer_pow_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, pow) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.pow_assign(pow); println!("x := {n_old}; x.pow_assign({pow}); x = {n}"); } } fn demo_integer_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("({}).pow({}) = {}", n_old, pow, n.pow(pow)); } } fn demo_integer_pow_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!("(&{}).pow({}) = {}", n, pow, (&n).pow(pow)); } } fn benchmark_integer_pow_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.pow_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_bits_times_pair_2_bucketer("n", "pow"), &mut [("Malachite", &mut |(mut x, exp)| x.pow_assign(exp))], ); } fn benchmark_integer_pow_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.pow_assign(u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bits_times_pair_2_bucketer("n", "pow"), &mut [ ("Malachite", &mut |(_, _, (x, exp))| no_out!(x.pow(exp))), ("num", &mut |((x, exp), _, _)| { no_out!(x.pow(u32::exact_from(exp))); }), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.pow(u32::exact_from(exp))); }), ], ); } fn benchmark_integer_pow_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.pow(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_bits_times_pair_2_bucketer("n", "pow"), &mut [ ("Integer.pow(u64)", &mut |(x, exp)| no_out!(x.pow(exp))), ("(&Integer).pow(u64)", &mut |(x, exp)| { no_out!((&x).pow(exp)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_power_of_2); register_bench!(runner, benchmark_integer_power_of_2); } fn demo_integer_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for pow in unsigned_gen_var_5().get(gm, config).take(limit) { println!("2^{} = {}", pow, Integer::power_of_2(pow)); } } fn benchmark_integer_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer::power_of_2(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |pow| no_out!(Integer::power_of_2(pow)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CheckedRoot, FloorRoot, FloorRootAssign, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_1_integer_bit_bucketer, triple_3_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_nrm, integer_unsigned_pair_gen_var_3, integer_unsigned_pair_gen_var_3_nrm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_floor_cbrt); register_demo!(runner, demo_integer_floor_cbrt_ref); register_demo!(runner, demo_integer_floor_cbrt_assign); register_demo!(runner, demo_integer_ceiling_cbrt); register_demo!(runner, demo_integer_ceiling_cbrt_ref); register_demo!(runner, demo_integer_ceiling_cbrt_assign); register_demo!(runner, demo_integer_checked_cbrt); register_demo!(runner, demo_integer_checked_cbrt_ref); register_demo!(runner, demo_integer_floor_root); register_demo!(runner, demo_integer_floor_root_ref); register_demo!(runner, demo_integer_floor_root_assign); register_demo!(runner, demo_integer_ceiling_root); register_demo!(runner, demo_integer_ceiling_root_ref); register_demo!(runner, demo_integer_ceiling_root_assign); register_demo!(runner, demo_integer_checked_root); register_demo!(runner, demo_integer_checked_root_ref); register_bench!(runner, benchmark_integer_floor_cbrt_evaluation_strategy); register_bench!(runner, benchmark_integer_floor_cbrt_library_comparison); register_bench!(runner, benchmark_integer_floor_cbrt_assign); register_bench!(runner, benchmark_integer_ceiling_cbrt_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_cbrt_assign); register_bench!(runner, benchmark_integer_checked_cbrt_evaluation_strategy); register_bench!(runner, benchmark_integer_floor_root_evaluation_strategy); register_bench!(runner, benchmark_integer_floor_root_library_comparison); register_bench!(runner, benchmark_integer_floor_root_assign); register_bench!(runner, benchmark_integer_ceiling_root_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_root_assign); register_bench!(runner, benchmark_integer_checked_root_evaluation_strategy); } fn demo_integer_floor_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("({}).floor_root(3) = {}", x, x.clone().floor_root(3)); } } fn demo_integer_floor_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("(&{}).floor_root(3) = {}", x, (&x).floor_root(3)); } } fn demo_integer_floor_cbrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in integer_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.floor_root_assign(3); println!("x := {old_x}; x.floor_root_assign(3); x = {x}"); } } fn demo_integer_ceiling_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("({}).ceiling_root(3) = {}", x, x.clone().ceiling_root(3)); } } fn demo_integer_ceiling_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("(&{}).ceiling_root(3) = {}", x, (&x).ceiling_root(3)); } } fn demo_integer_ceiling_cbrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in integer_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.ceiling_root_assign(3); println!("x := {old_x}; x.ceiling_root_assign(3); x = {x}"); } } fn demo_integer_checked_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("({}).checked_root(3) = {:?}", x, x.clone().checked_root(3)); } } fn demo_integer_checked_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("(&{}).checked_root(3) = {:?}", x, (&x).checked_root(3)); } } fn demo_integer_floor_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "({}).floor_root({}) = {}", x, exp, x.clone().floor_root(exp) ); } } fn demo_integer_floor_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!("(&{}).floor_root({}) = {}", x, exp, (&x).floor_root(exp)); } } fn demo_integer_floor_root_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let old_x = x.clone(); x.floor_root_assign(exp); println!("x := {old_x}; x.floor_root_assign(); x = {x}"); } } fn demo_integer_ceiling_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "({}).ceiling_root({}) = {}", x, exp, x.clone().ceiling_root(exp) ); } } fn demo_integer_ceiling_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "(&{}).ceiling_root({}) = {}", x, exp, (&x).ceiling_root(exp) ); } } fn demo_integer_ceiling_root_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { let old_x = x.clone(); x.ceiling_root_assign(exp); println!("x := {old_x}; x.ceiling_root_assign({exp}); x = {x}"); } } fn demo_integer_checked_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "({}).checked_root({}) = {:?}", x, exp, x.clone().checked_root(exp) ); } } fn demo_integer_checked_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in integer_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "(&{}).checked_root({}) = {:?}", x, exp, (&x).checked_root(exp) ); } } fn benchmark_integer_floor_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root(3)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.floor_root(3)", &mut |x| no_out!(x.floor_root(3))), ("(&Integer).floor_root(3)", &mut |x| { no_out!((&x).floor_root(3)); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_floor_cbrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("num", &mut |(x, _, _)| { no_out!(x.nth_root(u32::exact_from(3))); }), ("rug", &mut |(_, x, _)| no_out!(x.root(u32::exact_from(3)))), ("Malachite", &mut |(_, _, x)| no_out!(x.floor_root(3))), ], ); } fn benchmark_integer_floor_cbrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root_assign(3)", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.floor_root_assign(3))], ); } fn benchmark_integer_ceiling_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_root(3)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_root(3)", &mut |x| { no_out!(x.ceiling_root(3)); }), ("(&Integer).ceiling_root(3)", &mut |x| { no_out!((&x).ceiling_root(3)); }), ], ); } fn benchmark_integer_ceiling_cbrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_root_assign(3)", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.ceiling_root_assign(3))], ); } fn benchmark_integer_checked_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_root(3)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.checked_root(3)", &mut |x| { no_out!(x.checked_root(3)); }), ("(&Integer).checked_root(3)", &mut |x| { no_out!((&x).checked_root(3)); }), ], ); } fn benchmark_integer_floor_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.floor_root(u64)", &mut |(x, exp)| { no_out!(x.floor_root(exp)); }), ("(&Integer).floor_root(u64)", &mut |(x, exp)| { no_out!((&x).floor_root(exp)); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_floor_root_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root()", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_3_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("num", &mut |((x, exp), _, _)| { no_out!(x.nth_root(u32::exact_from(exp))); }), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.root(u32::exact_from(exp))); }), ("Malachite", &mut |(_, _, (x, exp))| { no_out!(x.floor_root(exp)); }), ], ); } fn benchmark_integer_floor_root_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_root_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, exp)| x.floor_root_assign(exp))], ); } fn benchmark_integer_ceiling_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_root(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_root(u64)", &mut |(x, exp)| { no_out!(x.ceiling_root(exp)); }), ("(&Integer).ceiling_root(u64)", &mut |(x, exp)| { no_out!((&x).ceiling_root(exp)); }), ], ); } fn benchmark_integer_ceiling_root_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_root_assign(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, exp)| x.ceiling_root_assign(exp))], ); } fn benchmark_integer_checked_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_root(u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.checked_root(u64)", &mut |(x, exp)| { no_out!(x.checked_root(exp)); }), ("(&Integer).checked_root(u64)", &mut |(x, exp)| { no_out!((&x).checked_root(exp)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_integer_rounding_mode_triple_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_round_to_multiple_assign); register_demo!(runner, demo_integer_round_to_multiple_assign_ref); register_demo!(runner, demo_integer_round_to_multiple); register_demo!(runner, demo_integer_round_to_multiple_val_ref); register_demo!(runner, demo_integer_round_to_multiple_ref_val); register_demo!(runner, demo_integer_round_to_multiple_ref_ref); register_bench!( runner, benchmark_integer_round_to_multiple_assign_evaluation_strategy ); register_bench!( runner, benchmark_integer_round_to_multiple_evaluation_strategy ); } fn demo_integer_round_to_multiple_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.round_to_multiple_assign(y, rm); println!("x := {x_old}; x.round_to_multiple_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_integer_round_to_multiple_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.round_to_multiple_assign(&y, rm); println!("x := {x_old}; x.round_to_multiple_assign(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_integer_round_to_multiple(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).round_to_multiple({}, {}) = {:?}", x_old, y_old, rm, x.round_to_multiple(y, rm) ); } } fn demo_integer_round_to_multiple_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).round_to_multiple(&{}, {}) = {:?}", x_old, y, rm, x.round_to_multiple(&y, rm) ); } } fn demo_integer_round_to_multiple_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).round_to_multiple({}, {}) = {:?}", x, y_old, rm, (&x).round_to_multiple(y, rm) ); } } fn demo_integer_round_to_multiple_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in integer_integer_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple(&{}, {}) = {:?}", x, y, rm, (&x).round_to_multiple(&y, rm) ); } } fn benchmark_integer_round_to_multiple_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.round_to_multiple_assign(Integer, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_integer_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [ ( "Integer.round_to_multiple_assign(Integer, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(y, rm)), ), ( "Integer.round_to_multiple_assign(&Integer, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(&y, rm)), ), ], ); } fn benchmark_integer_round_to_multiple_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.round_to_multiple(Integer, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_integer_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [ ( "Integer.round_to_multiple(Integer, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(y, rm)), ), ( "Integer.round_to_multiple(&Integer, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(&y, rm)), ), ( "(&Integer).round_to_multiple(Integer, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(y, rm)), ), ( "(&Integer).round_to_multiple(&Integer, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(&y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, ShrRound, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::triple_1_2_integer_bit_u64_max_bucketer; use malachite_nz::test_util::generators::integer_unsigned_rounding_mode_triple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_round_to_multiple_of_power_of_2_assign); register_demo!(runner, demo_integer_round_to_multiple_of_power_of_2); register_demo!(runner, demo_integer_round_to_multiple_of_power_of_2_ref); register_bench!( runner, benchmark_integer_round_to_multiple_of_power_of_2_assign ); register_bench!( runner, benchmark_integer_round_to_multiple_of_power_of_2_algorithms ); register_bench!( runner, benchmark_integer_round_to_multiple_of_power_of_2_evaluation_strategy ); } fn demo_integer_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow, rm) in integer_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.round_to_multiple_of_power_of_2_assign(pow, rm); println!( "x := {n_old}; x.round_to_multiple_of_power_of_2_assign({pow}, {rm}) = {o:?}; x = {n}" ); } } fn demo_integer_round_to_multiple_of_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow, rm) in integer_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "({}).round_to_multiple_of_power_of_2({}, {}) = {:?}", n_old, pow, rm, n.round_to_multiple_of_power_of_2(pow, rm) ); } } fn demo_integer_round_to_multiple_of_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow, rm) in integer_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple_of_power_of_2({}, {}) = {:?}", n, pow, rm, (&n).round_to_multiple_of_power_of_2(pow, rm) ); } } fn benchmark_integer_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.round_to_multiple_of_power_of_2_assign(u64, RoundingMode)", BenchmarkType::Single, integer_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_bit_u64_max_bucketer("n", "pow"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2_assign(y, rm)); })], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_round_to_multiple_of_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::Algorithms, integer_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_bit_u64_max_bucketer("n", "pow"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2(y, rm)); }), ("using shr_round", &mut |(x, y, rm)| { no_out!(x.shr_round(y, rm).0 << y); }), ("using round_to_multiple", &mut |(x, y, rm)| { no_out!(x.round_to_multiple(Integer::power_of_2(y), rm)); }), ], ); } fn benchmark_integer_round_to_multiple_of_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, integer_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_integer_bit_u64_max_bucketer("n", "pow"), &mut [ ( "Integer.round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple_of_power_of_2(y, rm)), ), ( "(&Integer).round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple_of_power_of_2(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_signed_pair_gen_var_1, integer_signed_pair_gen_var_1_rm, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_rm, }; use std::ops::{Shl, ShlAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_shl_assign_unsigned); register_signed_demos!(runner, demo_integer_shl_assign_signed); register_unsigned_demos!(runner, demo_integer_shl_unsigned); register_signed_demos!(runner, demo_integer_shl_signed); register_unsigned_demos!(runner, demo_integer_shl_unsigned_ref); register_signed_demos!(runner, demo_integer_shl_signed_ref); register_unsigned_benches!(runner, benchmark_integer_shl_assign_unsigned); register_signed_benches!(runner, benchmark_integer_shl_assign_signed); register_unsigned_benches!(runner, benchmark_integer_shl_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_integer_shl_signed_evaluation_strategy); register_bench!(runner, benchmark_integer_shl_assign_u32_library_comparison); register_bench!(runner, benchmark_integer_shl_u32_library_comparison); register_bench!(runner, benchmark_integer_shl_assign_i32_library_comparison); register_bench!(runner, benchmark_integer_shl_i32_library_comparison); } fn demo_integer_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ShlAssign, { for (mut n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= u; println!("x := {n_old}; x <<= {u}; x = {n}"); } } fn demo_integer_shl_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ShlAssign, { for (mut n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= i; println!("x := {n_old}; x <<= {i}; x = {n}"); } } fn demo_integer_shl_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: Shl, { for (n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, u, n << u); } } fn demo_integer_shl_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: Shl, { for (n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, i, n << i); } } fn demo_integer_shl_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Integer: Shl, { for (n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, u, &n << u); } } fn demo_integer_shl_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Integer: Shl, { for (n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, i, &n << i); } } fn benchmark_integer_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShlAssign, { run_benchmark( &format!("Integer <<= {}", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n <<= u)], ); } fn benchmark_integer_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShlAssign, { run_benchmark( &format!("Integer <<= {}", T::NAME), BenchmarkType::Single, integer_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n <<= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: Shl, for<'a> &'a Integer: Shl, { run_benchmark( &format!("Integer << {}", T::NAME), BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [ (&format!("Integer << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Integer << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: Shl, for<'a> &'a Integer: Shl, { run_benchmark( &format!("Integer << {}", T::NAME), BenchmarkType::EvaluationStrategy, integer_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [ (&format!("Integer << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Integer << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } fn benchmark_integer_shl_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer <<= u32", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_shl_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer << u32", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } fn benchmark_integer_shl_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer <<= i32", BenchmarkType::LibraryComparison, integer_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_shl_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer << i32", BenchmarkType::LibraryComparison, integer_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShlRound, ShlRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::triple_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_signed_rounding_mode_triple_gen_var_1; use std::ops::Shr; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_integer_shl_round_assign); register_signed_demos!(runner, demo_integer_shl_round); register_signed_demos!(runner, demo_integer_shl_round_ref); register_signed_benches!(runner, benchmark_integer_shl_round_assign); register_signed_benches!(runner, benchmark_integer_shl_round_evaluation_strategy); } fn demo_integer_shl_round_assign(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ShlRoundAssign + Shr, { for (mut n, i, rm) in integer_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(i, rm); println!("x := {n_old}; x.shl_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_integer_shl_round(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ShlRound + Shr, { for (n, i, rm) in integer_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, i, rm, n.shl_round(i, rm) ); } } fn demo_integer_shl_round_ref(gm: GenMode, config: &GenConfig, limit: usize) where Integer: Shr, for<'a> &'a Integer: ShlRound, { for (n, i, rm) in integer_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).shl_round({}, {}) = {:?}", n, i, rm, (&n).shl_round(i, rm) ); } } fn benchmark_integer_shl_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShlRoundAssign + Shr, { run_benchmark( &format!("Integer.shl_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, integer_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shl_round_assign(y, rm)); })], ); } fn benchmark_integer_shl_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShlRound + Shr, for<'a> &'a Integer: ShlRound, { run_benchmark( &format!("Integer.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, integer_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [ ( &format!("Integer.shl_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shl_round(y, rm)), ), ( &format!("(&Integer).shl_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shl_round(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_1_integer_bit_bucketer, pair_2_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_signed_pair_gen_var_1, integer_signed_pair_gen_var_1_rm, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_rm, }; use std::ops::{Shr, ShrAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_shr_assign_unsigned); register_signed_demos!(runner, demo_integer_shr_assign_signed); register_unsigned_demos!(runner, demo_integer_shr_unsigned); register_signed_demos!(runner, demo_integer_shr_signed); register_unsigned_demos!(runner, demo_integer_shr_unsigned_ref); register_signed_demos!(runner, demo_integer_shr_signed_ref); register_unsigned_benches!(runner, benchmark_integer_shr_assign_unsigned); register_signed_benches!(runner, benchmark_integer_shr_assign_signed); register_unsigned_benches!(runner, benchmark_integer_shr_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_integer_shr_signed_evaluation_strategy); register_bench!(runner, benchmark_integer_shr_assign_u32_library_comparison); register_bench!(runner, benchmark_integer_shr_u32_library_comparison); register_bench!(runner, benchmark_integer_shr_assign_i32_library_comparison); register_bench!(runner, benchmark_integer_shr_i32_library_comparison); } fn demo_integer_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ShrAssign, { for (mut n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!("x := {n_old}; x >>= {u}; x = {n}"); } } fn demo_integer_shr_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ShrAssign, { for (mut n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= i; println!("x := {n_old}; x >>= {i}; x = {n}"); } } fn demo_integer_shr_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: Shr, { for (n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_integer_shr_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: Shr, { for (n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, i, n >> i); } } fn demo_integer_shr_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Integer: Shr, { for (n, u) in integer_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, u, &n >> u); } } fn demo_integer_shr_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Integer: Shr, { for (n, i) in integer_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, i, &n >> i); } } fn benchmark_integer_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrAssign, { run_benchmark( &format!("Integer >>= {}", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n >>= u)], ); } fn benchmark_integer_shr_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrAssign, { run_benchmark( &format!("Integer >>= {}", T::NAME), BenchmarkType::Single, integer_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n >>= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_shr_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: Shr, for<'a> &'a Integer: Shr, { run_benchmark( &format!("Integer >> {}", T::NAME), BenchmarkType::EvaluationStrategy, integer_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [ (&format!("Integer >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Integer >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_shr_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: Shr, for<'a> &'a Integer: Shr, { run_benchmark( &format!("Integer >> {}", T::NAME), BenchmarkType::EvaluationStrategy, integer_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [ (&format!("Integer >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Integer >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } fn benchmark_integer_shr_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer >>= u32", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_shr_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer >> u32", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } fn benchmark_integer_shr_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer >>= i32", BenchmarkType::LibraryComparison, integer_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_shr_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer >> i32", BenchmarkType::LibraryComparison, integer_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::triple_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{ integer_signed_rounding_mode_triple_gen_var_2, integer_unsigned_rounding_mode_triple_gen_var_2, }; use std::ops::Shl; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_shr_round_assign_unsigned); register_signed_demos!(runner, demo_integer_shr_round_assign_signed); register_unsigned_demos!(runner, demo_integer_shr_round_unsigned); register_signed_demos!(runner, demo_integer_shr_round_signed); register_unsigned_demos!(runner, demo_integer_shr_round_ref_unsigned); register_signed_demos!(runner, demo_integer_shr_round_ref_signed); register_unsigned_benches!(runner, benchmark_integer_shr_round_assign_unsigned); register_signed_benches!(runner, benchmark_integer_shr_round_assign_signed); register_unsigned_benches!( runner, benchmark_integer_shr_round_evaluation_strategy_unsigned ); register_signed_benches!( runner, benchmark_integer_shr_round_evaluation_strategy_signed ); } fn demo_integer_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ShrRoundAssign + Shl, { for (mut n, u, rm) in integer_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(u, rm); println!("x := {n_old}; x.shr_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_integer_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ShrRoundAssign + Shl, { for (mut n, i, rm) in integer_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(i, rm); println!("x := {n_old}; x.shr_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_integer_shr_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ShrRound + Shl, { for (n, u, rm) in integer_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, u, rm, n.shr_round(u, rm) ); } } fn demo_integer_shr_round_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ShrRound + Shl, { for (n, i, rm) in integer_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, i, rm, n.shr_round(i, rm) ); } } fn demo_integer_shr_round_ref_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: Shl, for<'a> &'a Integer: ShrRound, { for (n, u, rm) in integer_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, u, rm, (&n).shr_round(u, rm) ); } } fn demo_integer_shr_round_ref_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: Shl, for<'a> &'a Integer: ShrRound, { for (n, i, rm) in integer_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, i, rm, (&n).shr_round(i, rm) ); } } fn benchmark_integer_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrRoundAssign + Shl, { run_benchmark( &format!("Integer.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, integer_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shr_round_assign(y, rm)); })], ); } fn benchmark_integer_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrRoundAssign + Shl, { run_benchmark( &format!("Integer.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, integer_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shr_round_assign(y, rm)); })], ); } fn benchmark_integer_shr_round_evaluation_strategy_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrRound + Shl, for<'a> &'a Integer: ShrRound, { run_benchmark( &format!("Integer.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, integer_unsigned_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [ ( &format!("Integer.shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shr_round(y, rm)), ), ( &format!("(&Integer).shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shr_round(y, rm)), ), ], ); } fn benchmark_integer_shr_round_evaluation_strategy_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ShrRound + Shl, for<'a> &'a Integer: ShrRound, { run_benchmark( &format!("Integer.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, integer_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("n"), &mut [ ( &format!("Integer.shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shr_round(y, rm)), ), ( &format!("(&Integer).shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shr_round(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_gen, integer_gen_nrm}; use malachite_nz::test_util::integer::arithmetic::sign::num_sign; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_sign); register_bench!(runner, benchmark_integer_sign_library_comparison); } fn demo_integer_sign(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { match n.sign() { Less => println!("{n} is negative"), Equal => println!("{n} is zero"), Greater => println!("{n} is positive"), } } } fn benchmark_integer_sign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sign()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.sign())), ("num", &mut |(n, _, _)| no_out!(num_sign(&n))), ("rug", &mut |(_, n, _)| no_out!(n.cmp0())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingSqrt, CeilingSqrtAssign, CheckedSqrt, FloorSqrt, FloorSqrtAssign, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, triple_3_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_gen_var_4, integer_gen_var_4_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_floor_sqrt); register_demo!(runner, demo_integer_floor_sqrt_ref); register_demo!(runner, demo_integer_floor_sqrt_assign); register_demo!(runner, demo_integer_ceiling_sqrt); register_demo!(runner, demo_integer_ceiling_sqrt_ref); register_demo!(runner, demo_integer_ceiling_sqrt_assign); register_demo!(runner, demo_integer_checked_sqrt); register_demo!(runner, demo_integer_checked_sqrt_ref); register_bench!(runner, benchmark_integer_floor_sqrt_evaluation_strategy); register_bench!(runner, benchmark_integer_floor_sqrt_library_comparison); register_bench!(runner, benchmark_integer_floor_sqrt_assign); register_bench!(runner, benchmark_integer_ceiling_sqrt_evaluation_strategy); register_bench!(runner, benchmark_integer_ceiling_sqrt_assign); register_bench!(runner, benchmark_integer_checked_sqrt_evaluation_strategy); } fn demo_integer_floor_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("{}.floor_sqrt() = {}", x, x.clone().floor_sqrt()); } } fn demo_integer_floor_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("(&{}).floor_sqrt() = {}", x, (&x).floor_sqrt()); } } fn demo_integer_floor_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in integer_gen_var_4().get(gm, config).take(limit) { let old_x = x.clone(); x.floor_sqrt_assign(); println!("x := {old_x}; x.floor_sqrt_assign(); x = {x}"); } } fn demo_integer_ceiling_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("{}.ceiling_sqrt() = {}", x, x.clone().ceiling_sqrt()); } } fn demo_integer_ceiling_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("(&{}).ceiling_sqrt() = {}", x, (&x).ceiling_sqrt()); } } fn demo_integer_ceiling_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in integer_gen_var_4().get(gm, config).take(limit) { let old_x = x.clone(); x.ceiling_sqrt_assign(); println!("x := {old_x}; x.ceiling_sqrt_assign(); x = {x}"); } } fn demo_integer_checked_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("{}.checked_sqrt() = {:?}", x, x.clone().checked_sqrt()); } } fn demo_integer_checked_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen_var_4().get(gm, config).take(limit) { println!("(&{}).checked_sqrt() = {:?}", x, (&x).checked_sqrt()); } } fn benchmark_integer_floor_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_sqrt()", BenchmarkType::EvaluationStrategy, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.floor_sqrt()", &mut |x| no_out!(x.floor_sqrt())), ("(&Integer).floor_sqrt()", &mut |x| { no_out!((&x).floor_sqrt()); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_floor_sqrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_sqrt()", BenchmarkType::LibraryComparison, integer_gen_var_4_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("num", &mut |(x, _, _)| no_out!(x.sqrt())), ("rug", &mut |(_, x, _)| no_out!(x.sqrt())), ("Malachite", &mut |(_, _, x)| no_out!(x.floor_sqrt())), ], ); } fn benchmark_integer_floor_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.floor_sqrt_assign()", BenchmarkType::Single, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.floor_sqrt_assign())], ); } fn benchmark_integer_ceiling_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_sqrt()", BenchmarkType::EvaluationStrategy, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.ceiling_sqrt()", &mut |x| no_out!(x.ceiling_sqrt())), ("(&Integer).ceiling_sqrt()", &mut |x| { no_out!((&x).ceiling_sqrt()); }), ], ); } fn benchmark_integer_ceiling_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ceiling_sqrt_assign()", BenchmarkType::Single, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.ceiling_sqrt_assign())], ); } fn benchmark_integer_checked_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_sqrt()", BenchmarkType::EvaluationStrategy, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("Integer.checked_sqrt()", &mut |x| no_out!(x.checked_sqrt())), ("(&Integer).checked_sqrt()", &mut |x| { no_out!((&x).checked_sqrt()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Square, SquareAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_square_assign); register_demo!(runner, demo_integer_square); register_demo!(runner, demo_integer_square_ref); register_bench!(runner, benchmark_integer_square_assign); register_bench!(runner, benchmark_integer_square_algorithms); register_bench!(runner, benchmark_integer_square_evaluation_strategy); } fn demo_integer_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in integer_gen().get(gm, config).take(limit) { let old_n = n.clone(); n.square_assign(); println!("n := {n}; n.square_assign(); n = {old_n}"); } } fn demo_integer_square(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("({}) ^ 2 = {}", n.clone(), n.square()); } } fn demo_integer_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("&{} ^ 2 = {}", n, (&n).square()); } } fn benchmark_integer_square_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.square_assign()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |mut n| n.square_assign())], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.square()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("standard", &mut |ref n| no_out!(n.square())), ("using *", &mut |ref n| no_out!(n * n)), ], ); } fn benchmark_integer_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.square()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Integer.square()", &mut |n| no_out!(n.square())), ("(&Integer).square()", &mut |n| no_out!((&n).square())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen, integer_pair_gen_nrm, integer_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_sub_assign); register_demo!(runner, demo_integer_sub_assign_ref); register_demo!(runner, demo_integer_sub); register_demo!(runner, demo_integer_sub_val_ref); register_demo!(runner, demo_integer_sub_ref_val); register_demo!(runner, demo_integer_sub_ref_ref); register_bench!(runner, benchmark_integer_sub_assign_library_comparison); register_bench!(runner, benchmark_integer_sub_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_sub_library_comparison); register_bench!(runner, benchmark_integer_sub_evaluation_strategy); } fn demo_integer_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x -= y.clone(); println!("x := {x_old}; x -= {y}; x = {x}"); } } fn demo_integer_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x -= &y; println!("x := {x_old}; x -= &{y}; x = {x}"); } } fn demo_integer_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_integer_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_integer_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_integer_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn benchmark_integer_sub_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer -= Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x -= y), ("rug", &mut |((mut x, y), _)| x -= y)], ); } fn benchmark_integer_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer -= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer -= Integer", &mut |(mut x, y)| no_out!(x -= y)), ("Integer -= &Integer", &mut |(mut x, y)| no_out!(x -= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_sub_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer - Integer", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x - y)), ("num", &mut |((x, y), _, _)| no_out!(x - y)), ("rug", &mut |(_, (x, y), _)| no_out!(x - y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer - Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer - Integer", &mut |(x, y)| no_out!(x - y)), ("Integer - &Integer", &mut |(x, y)| no_out!(x - &y)), ("&Integer - Integer", &mut |(x, y)| no_out!(&x - y)), ("&Integer - &Integer", &mut |(x, y)| no_out!(&x - &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{SubMul, SubMulAssign}; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_vec_max_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_triple_gen_var_39, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::arithmetic::sub_mul::{ limbs_overflowing_sub_mul, limbs_overflowing_sub_mul_in_place_left, limbs_overflowing_sub_mul_limb, limbs_overflowing_sub_mul_limb_in_place_either, limbs_overflowing_sub_mul_limb_in_place_left, limbs_overflowing_sub_mul_limb_in_place_right, }; use malachite_nz::test_util::bench::bucketers::triple_integer_max_bit_bucketer; use malachite_nz::test_util::generators::integer_triple_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_overflowing_sub_mul_limb); register_demo!(runner, demo_limbs_overflowing_sub_mul_limb_in_place_left); register_demo!(runner, demo_limbs_overflowing_sub_mul_limb_in_place_right); register_demo!(runner, demo_limbs_overflowing_sub_mul_limb_in_place_either); register_demo!(runner, demo_limbs_overflowing_sub_mul); register_demo!(runner, demo_limbs_overflowing_sub_mul_in_place_left); register_demo!(runner, demo_integer_sub_mul); register_demo!(runner, demo_integer_sub_mul_val_val_ref); register_demo!(runner, demo_integer_sub_mul_val_ref_val); register_demo!(runner, demo_integer_sub_mul_val_ref_ref); register_demo!(runner, demo_integer_sub_mul_ref_ref_ref); register_demo!(runner, demo_integer_sub_mul_assign); register_demo!(runner, demo_integer_sub_mul_assign_val_ref); register_demo!(runner, demo_integer_sub_mul_assign_ref_val); register_demo!(runner, demo_integer_sub_mul_assign_ref_ref); register_bench!(runner, benchmark_limbs_overflowing_sub_mul_limb); register_bench!( runner, benchmark_limbs_overflowing_sub_mul_limb_in_place_left ); register_bench!( runner, benchmark_limbs_overflowing_sub_mul_limb_in_place_right ); register_bench!( runner, benchmark_limbs_overflowing_sub_mul_limb_in_place_either ); register_bench!(runner, benchmark_limbs_overflowing_sub_mul); register_bench!(runner, benchmark_limbs_overflowing_sub_mul_in_place_left); register_bench!(runner, benchmark_integer_sub_mul_evaluation_strategy); register_bench!(runner, benchmark_integer_sub_mul_algorithms); register_bench!(runner, benchmark_integer_sub_mul_val_val_ref_algorithms); register_bench!(runner, benchmark_integer_sub_mul_val_ref_val_algorithms); register_bench!(runner, benchmark_integer_sub_mul_val_ref_ref_algorithms); register_bench!(runner, benchmark_integer_sub_mul_ref_ref_ref_algorithms); register_bench!(runner, benchmark_integer_sub_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_sub_mul_assign_algorithms); register_bench!(runner, benchmark_integer_sub_mul_assign_val_ref_algorithms); register_bench!(runner, benchmark_integer_sub_mul_assign_ref_val_algorithms); register_bench!(runner, benchmark_integer_sub_mul_assign_ref_ref_algorithms); } fn demo_limbs_overflowing_sub_mul_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { println!( "limbs_overflowing_sub_mul_limb({:?}, {:?}, {}) = {:?}", a, b, c, limbs_overflowing_sub_mul_limb(&a, &b, c), ); } } fn demo_limbs_overflowing_sub_mul_limb_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut a, b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let a_old = a.clone(); let borrow = limbs_overflowing_sub_mul_limb_in_place_left(&mut a, &b, c); println!( "a := {a_old:?}; \ limbs_overflowing_sub_mul_limb_in_place_left(&mut a, {b:?}, {c}) = {borrow}; \ a = {a:?}", ); } } fn demo_limbs_overflowing_sub_mul_limb_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, ) { for (a, mut b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let b_old = b.clone(); let borrow = limbs_overflowing_sub_mul_limb_in_place_right(&a, &mut b, c); println!( "b := {b_old:?}; \ limbs_overflowing_sub_mul_limb_in_place_right({a:?}, &mut b, {c}) = {borrow}; \ b = {b:?}", ); } } fn demo_limbs_overflowing_sub_mul_limb_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut a, mut b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let a_old = a.clone(); let b_old = b.clone(); limbs_overflowing_sub_mul_limb_in_place_either(&mut a, &mut b, c); println!( "a := {a_old:?}; b := {b_old:?}; \ limbs_overflowing_sub_mul_limb_in_place_either(&mut a, &mut b, {c}); \ a = {a:?}; b = {b:?}", ); } } fn demo_limbs_overflowing_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in unsigned_vec_triple_gen_var_39().get(gm, config).take(limit) { println!( "limbs_overflowing_sub_mul({:?}, {:?}, {:?}) = {:?}", a, b, c, limbs_overflowing_sub_mul(&a, &b, &c), ); } } fn demo_limbs_overflowing_sub_mul_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in unsigned_vec_triple_gen_var_39().get(gm, config).take(limit) { let a_old = a.clone(); let sign = limbs_overflowing_sub_mul_in_place_left(&mut a, &b, &c); println!( "a := {a_old:?}; \ limbs_overflowing_sub_mul_in_place_left(&mut a, {b:?}, {c:?}) = {sign}; \ a = {a:?}", ); } } fn demo_integer_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); println!( "{}.sub_mul({}, {}) = {}", x_old, y_old, z_old, x.sub_mul(y, z) ); } } fn demo_integer_sub_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.sub_mul({}, &({})) = {}", x_old, y_old, z, x.sub_mul(y, &z) ); } } fn demo_integer_sub_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); println!( "{}.sub_mul(&({}), {}) = {}", x_old, y, z_old, x.sub_mul(&y, z) ); } } fn demo_integer_sub_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.sub_mul(&({}), &({})) = {}", x_old, y, z, x.sub_mul(&y, &z) ); } } fn demo_integer_sub_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in integer_triple_gen().get(gm, config).take(limit) { println!( "(&{}).sub_mul(&({}), &({})) = {}", x, y, z, (&x).sub_mul(&y, &z) ); } } fn demo_integer_sub_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); x.sub_mul_assign(y, z); println!("x := {x_old}; x.sub_mul_assign({y_old}, {z_old}); x = {x}"); } } fn demo_integer_sub_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.sub_mul_assign(y, &z); println!("x := {x_old}; x.sub_mul_assign({y_old}, &({z})); x = {x}"); } } fn demo_integer_sub_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); x.sub_mul_assign(&y, z); println!("x := {x_old}; x.sub_mul_assign(&({y}), {z_old}); x = {x}"); } } fn demo_integer_sub_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in integer_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.sub_mul_assign(&y, &z); println!("x := {x_old}; x.sub_mul_assign(&({y}), &({z})); x = {x}"); } } fn benchmark_limbs_overflowing_sub_mul_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul_limb(&[Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(a, b, c)| { no_out!(limbs_overflowing_sub_mul_limb(&a, &b, c)); })], ); } fn benchmark_limbs_overflowing_sub_mul_limb_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul_limb_in_place_left(&mut Vec, &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut a, b, c)| { no_out!(limbs_overflowing_sub_mul_limb_in_place_left(&mut a, &b, c)); })], ); } fn benchmark_limbs_overflowing_sub_mul_limb_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul_limb_in_place_right(&[Limb], &mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(a, mut b, c)| { no_out!(limbs_overflowing_sub_mul_limb_in_place_right(&a, &mut b, c)); })], ); } fn benchmark_limbs_overflowing_sub_mul_limb_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul_limb_in_place_either(&mut Vec, &mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut a, mut b, c)| { no_out!(limbs_overflowing_sub_mul_limb_in_place_either( &mut a, &mut b, c )); })], ); } fn benchmark_limbs_overflowing_sub_mul( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul(&[Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_39().get(gm, config), gm.name(), limit, file_name, &triple_vec_max_len_bucketer("xs", "ys", "zs"), &mut [("Malachite", &mut |(a, b, c)| { no_out!(limbs_overflowing_sub_mul(&a, &b, &c)); })], ); } fn benchmark_limbs_overflowing_sub_mul_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_overflowing_sub_mul_in_place_left(&mut Vec, &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_39().get(gm, config), gm.name(), limit, file_name, &triple_vec_max_len_bucketer("xs", "ys", "zs"), &mut [("Malachite", &mut |(mut a, b, c)| { no_out!(limbs_overflowing_sub_mul_in_place_left(&mut a, &b, &c)); })], ); } fn benchmark_integer_sub_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.sub_mul(Integer, Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, c)); }), ("Integer.sub_mul(Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, &c)); }), ("Integer.sub_mul(&Integer, Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, c)); }), ("Integer.sub_mul(&Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, &c)); }), ( "(&Integer).sub_mul(&Integer, &Integer)", &mut |(a, b, c)| no_out!((&a).sub_mul(&b, &c)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.sub_mul(Integer, Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, c)); }), ("Integer - Integer * Integer", &mut |(a, b, c)| { no_out!(a - b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.sub_mul(Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, &c)); }), ("Integer - Integer * &Integer", &mut |(a, b, c)| { no_out!(a - b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(&Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.sub_mul(&Integer, Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, c)); }), ("Integer - &Integer * Integer", &mut |(a, b, c)| { no_out!(a - &b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ("Integer.sub_mul(&Integer, &Integer)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, &c)); }), ("Integer - Integer * Integer", &mut |(a, b, c)| { no_out!(a - &b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_sub_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "(&Integer).sub_mul(&Integer, &Integer)", &mut |(a, b, c)| no_out!((&a).sub_mul(&b, &c)), ), ("&Integer - Integer * Integer", &mut |(a, b, c)| { no_out!(&a - &b * &c); }), ], ); } fn benchmark_integer_sub_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul_assign(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.sub_mul_assign(Integer, Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(b, c), ), ( "Integer.sub_mul_assign(Integer, &Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(b, &c), ), ( "Integer.sub_mul_assign(&Integer, Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, c), ), ( "Integer.sub_mul_assign(&Integer, &Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, &c), ), ], ); } fn benchmark_integer_sub_mul_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul_assign(Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.sub_mul_assign(Integer, Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(b, c), ), ("Integer -= Integer * Integer", &mut |(mut a, b, c)| { a -= b * c; }), ], ); } fn benchmark_integer_sub_mul_assign_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul_assign(Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.sub_mul_assign(Integer, &Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(b, &c), ), ("Integer -= Integer * &Integer", &mut |(mut a, b, c)| { a -= b * &c; }), ], ); } fn benchmark_integer_sub_mul_assign_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul_assign(&Integer, Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.sub_mul_assign(&Integer, Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, c), ), ("Integer -= &Integer * Integer", &mut |(mut a, b, c)| { a -= &b * c; }), ], ); } fn benchmark_integer_sub_mul_assign_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.sub_mul_assign(&Integer, &Integer)", BenchmarkType::Algorithms, integer_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_integer_max_bit_bucketer("x", "y", "z"), &mut [ ( "Integer.sub_mul_assign(&Integer, &Integer)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, &c), ), ("Integer -= &Integer * &Integer", &mut |(mut a, b, c)| { a -= &b * &c; }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/basic/from_sign_and_abs.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_bool_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_from_sign_and_abs); register_demo!(runner, demo_from_sign_and_abs_ref); register_bench!(runner, benchmark_from_sign_and_abs_evaluation_strategy); } fn demo_from_sign_and_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (abs, sign) in natural_bool_pair_gen().get(gm, config).take(limit) { let abs_old = abs.clone(); println!( "Integer::from_sign_and_abs({}, {}) = {}", sign, abs_old, Integer::from_sign_and_abs(sign, abs) ); } } fn demo_from_sign_and_abs_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (abs, sign) in natural_bool_pair_gen().get(gm, config).take(limit) { println!( "Integer::from_sign_and_abs_ref({}, {}) = {}", sign, abs, Integer::from_sign_and_abs_ref(sign, &abs) ); } } fn benchmark_from_sign_and_abs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_sign_and_abs(bool, Natural)", BenchmarkType::EvaluationStrategy, natural_bool_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("abs"), &mut [ ("from_sign_and_abs", &mut |(abs, sign)| { no_out!(Integer::from_sign_and_abs(sign, abs)); }), ("from_sign_and_abs_ref", &mut |(abs, sign)| { no_out!(Integer::from_sign_and_abs_ref(sign, &abs)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/basic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sign_and_abs::register(runner); } mod from_sign_and_abs; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_pair_integer_max_bit_bucketer; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_nrm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_cmp); register_bench!(runner, benchmark_integer_cmp_library_comparison); } fn demo_integer_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { match x.cmp(&y) { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } #[allow(unused_must_use)] fn benchmark_integer_cmp_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp(&Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.cmp(&y))), ("num", &mut |((x, y), _, _)| no_out!(x.cmp(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.cmp(&y))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_cmp_abs); register_demo!(runner, demo_integer_lt_abs); register_demo!(runner, demo_integer_gt_abs); register_demo!(runner, demo_integer_le_abs); register_demo!(runner, demo_integer_ge_abs); register_bench!(runner, benchmark_integer_cmp_abs_library_comparison); register_bench!(runner, benchmark_integer_cmp_abs_algorithms); register_bench!(runner, benchmark_integer_lt_abs); register_bench!(runner, benchmark_integer_gt_abs); register_bench!(runner, benchmark_integer_le_abs); register_bench!(runner, benchmark_integer_ge_abs); } fn demo_integer_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { match x.cmp_abs(&y) { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } fn demo_integer_lt_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x.lt_abs(&y) { println!("|{x}| < |{y}|"); } else { println!("|{x}| ≮ |{y}|"); } } } fn demo_integer_gt_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x.gt_abs(&y) { println!("|{x}| > |{y}|"); } else { println!("|{x}| ≯ |{y}|"); } } } fn demo_integer_le_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x.le_abs(&y) { println!("|{x}| ≤ |{y}|"); } else { println!("|{x}| ≰ |{y}|"); } } } fn demo_integer_ge_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x.ge_abs(&y) { println!("|{x}| ≥ |{y}|"); } else { println!("|{x}| ≱ |{y}|"); } } } #[allow(unused_must_use)] fn benchmark_integer_cmp_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp_abs(&Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.cmp_abs(&y))), ("rug", &mut |((x, y), _)| no_out!(x.cmp_abs(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.cmp_abs(&Integer)", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().cmp(&y.abs()))), ], ); } fn benchmark_integer_lt_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.lt_abs(&Integer)", BenchmarkType::Single, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_integer_gt_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.gt_abs(&Integer)", BenchmarkType::Single, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_integer_le_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.le_abs(&Integer)", BenchmarkType::Single, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_integer_ge_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.ge_abs(&Integer)", BenchmarkType::Single, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_pair_integer_max_bit_bucketer; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_eq); register_bench!(runner, benchmark_integer_eq_library_comparison); } fn demo_integer_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_eq_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer == Integer", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x == y)), ("num", &mut |((x, y), _, _)| no_out!(x == y)), ("rug", &mut |(_, (x, y), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_integer_max_bit_bucketer; use malachite_nz::test_util::generators::integer_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_eq_abs); register_bench!(runner, benchmark_integer_eq_abs_algorithms); } fn demo_integer_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_abs(&Natural)", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_natural_max_bit_bucketer; use malachite_nz::test_util::generators::integer_natural_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_eq_abs_natural); register_demo!(runner, demo_natural_eq_abs_integer); register_bench!(runner, benchmark_integer_eq_abs_natural_algorithms); register_bench!(runner, benchmark_natural_eq_abs_integer_algorithms); } fn demo_integer_eq_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_natural_eq_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y.eq_abs(&x) { println!("|{y}| = |{x}|"); } else { println!("|{y}| ≠ |{x}|"); } } } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_abs(&Natural)", BenchmarkType::Algorithms, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(unused_must_use)] fn benchmark_natural_eq_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_abs(&Integer)", BenchmarkType::Algorithms, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y == x.abs())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_primitive_float_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_integer_eq_abs_primitive_float); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_integer); register_primitive_float_benches!(runner, benchmark_integer_eq_abs_primitive_float_algorithms); register_primitive_float_benches!(runner, benchmark_primitive_float_eq_abs_integer_algorithms); } fn demo_integer_eq_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: EqAbs, { for (n, x) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n.eq_abs(&x) { println!("|{}| = |{}|", n, NiceFloat(x)); } else { println!("|{}| ≠ |{}|", n, NiceFloat(x)); } } } fn demo_primitive_float_eq_abs_integer + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, x) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x.eq_abs(&n) { println!("|{}| = |{}|", NiceFloat(x), n); } else { println!("|{}| ≠ |{}|", NiceFloat(x), n); } } } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: EqAbs + PartialEq, { run_benchmark( &format!("Integer.eq_abs(&{})", T::NAME), BenchmarkType::Algorithms, integer_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(unused_must_use)] fn benchmark_primitive_float_eq_abs_integer_algorithms< T: EqAbs + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y == x.abs())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_signed_pair_gen, integer_unsigned_pair_gen}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_partial_eq_abs_unsigned); register_signed_demos!(runner, demo_integer_partial_eq_abs_signed); register_unsigned_demos!(runner, demo_unsigned_partial_eq_abs_integer); register_signed_demos!(runner, demo_signed_partial_eq_abs_integer); register_unsigned_benches!(runner, benchmark_integer_eq_abs_unsigned_algorithms); register_signed_benches!(runner, benchmark_integer_eq_abs_signed_algorithms); register_unsigned_benches!(runner, benchmark_unsigned_eq_abs_integer_algorithms); register_signed_benches!(runner, benchmark_signed_eq_abs_integer_algorithms); } fn demo_integer_partial_eq_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: EqAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n.eq_abs(&u) { println!("|{n}| = |{u}|"); } else { println!("|{n}| ≠ |{u}|"); } } } fn demo_integer_partial_eq_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: EqAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n.eq_abs(&i) { println!("|{n}| = |{i}|"); } else { println!("|{n}| ≠ |{i}|"); } } } fn demo_unsigned_partial_eq_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u.eq_abs(&n) { println!("|{u}| = |{n}|"); } else { println!("|{u}| ≠ |{n}|"); } } } fn demo_signed_partial_eq_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i.eq_abs(&n) { println!("|{i}| = |{n}|"); } else { println!("|{i}| ≠ |{n}|"); } } } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: EqAbs + PartialEq, { run_benchmark( &format!("Integer.eq_abs({})", T::NAME), BenchmarkType::Algorithms, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: EqAbs + PartialEq<::Output>, { run_benchmark( &format!("Integer.eq_abs({})", T::NAME), BenchmarkType::Algorithms, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs() == y.unsigned_abs()); }), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_eq_abs_integer_algorithms< T: EqAbs + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y == x.abs())), ], ); } #[allow(unused_must_use)] fn benchmark_signed_eq_abs_integer_algorithms + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialEq, { run_benchmark( &format!("{}.eq_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.unsigned_abs() == x.abs()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_gen, integer_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_hash); register_bench!(runner, benchmark_integer_hash_library_comparison); } fn demo_integer_hash(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("hash({}) = {}", n, hash(&n)); } } fn benchmark_integer_hash_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer hash", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(hash(&n))), ("num", &mut |(_, n, _)| no_out!(hash(&n))), ("rug", &mut |(n, _, _)| no_out!(hash(&n))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); cmp_abs::register(runner); eq::register(runner); eq_abs::register(runner); eq_abs_natural::register(runner); eq_abs_primitive_float::register(runner); eq_abs_primitive_int::register(runner); hash::register(runner); partial_cmp_abs_natural::register(runner); partial_cmp_abs_primitive_float::register(runner); partial_cmp_abs_primitive_int::register(runner); partial_cmp_natural::register(runner); partial_cmp_primitive_float::register(runner); partial_cmp_primitive_int::register(runner); partial_eq_natural::register(runner); partial_eq_primitive_float::register(runner); partial_eq_primitive_int::register(runner); } mod cmp; mod cmp_abs; mod eq; mod eq_abs; mod eq_abs_natural; mod eq_abs_primitive_float; mod eq_abs_primitive_int; mod hash; mod partial_cmp_abs_natural; mod partial_cmp_abs_primitive_float; mod partial_cmp_abs_primitive_int; mod partial_cmp_natural; mod partial_cmp_primitive_float; mod partial_cmp_primitive_int; mod partial_eq_natural; mod partial_eq_primitive_float; mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_natural_max_bit_bucketer, pair_2_integer_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_natural_pair_gen, integer_natural_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_partial_cmp_abs_natural); register_demo!(runner, demo_natural_partial_cmp_abs_integer); register_demo!(runner, demo_integer_lt_abs_natural); register_demo!(runner, demo_integer_gt_abs_natural); register_demo!(runner, demo_integer_le_abs_natural); register_demo!(runner, demo_integer_ge_abs_natural); register_demo!(runner, demo_natural_lt_abs_integer); register_demo!(runner, demo_natural_gt_abs_integer); register_demo!(runner, demo_natural_le_abs_integer); register_demo!(runner, demo_natural_ge_abs_integer); register_bench!( runner, benchmark_integer_partial_cmp_abs_natural_library_comparison ); register_bench!(runner, benchmark_integer_partial_cmp_abs_natural_algorithms); register_bench!( runner, benchmark_natural_partial_cmp_abs_integer_library_comparison ); register_bench!(runner, benchmark_natural_partial_cmp_abs_integer_algorithms); register_bench!(runner, benchmark_integer_lt_abs_natural); register_bench!(runner, benchmark_integer_gt_abs_natural); register_bench!(runner, benchmark_integer_le_abs_natural); register_bench!(runner, benchmark_integer_ge_abs_natural); register_bench!(runner, benchmark_natural_lt_abs_integer); register_bench!(runner, benchmark_natural_gt_abs_integer); register_bench!(runner, benchmark_natural_le_abs_integer); register_bench!(runner, benchmark_natural_ge_abs_integer); } fn demo_integer_partial_cmp_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y).unwrap() { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } fn demo_natural_partial_cmp_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { match y.partial_cmp_abs(&x).unwrap() { Less => println!("|{y}| < |{x}|"), Equal => println!("|{y}| = |{x}|"), Greater => println!("|{y}| > |{x}|"), } } } fn demo_integer_lt_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x.lt_abs(&y) { println!("|{x}| < |{y}|"); } else { println!("|{x}| ≮ |{y}|"); } } } fn demo_integer_gt_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x.gt_abs(&y) { println!("|{x}| > |{y}|"); } else { println!("|{x}| ≯ |{y}|"); } } } fn demo_integer_le_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x.le_abs(&y) { println!("|{x}| ≤ |{y}|"); } else { println!("|{x}| ≰ |{y}|"); } } } fn demo_integer_ge_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x.ge_abs(&y) { println!("|{x}| ≥ |{y}|"); } else { println!("|{x}| ≱ |{y}|"); } } } fn demo_natural_lt_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y.lt_abs(&x) { println!("|{y}| < |{x}|"); } else { println!("|{y}| ≮ |{x}|"); } } } fn demo_natural_gt_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y.gt_abs(&x) { println!("|{y}| > |{x}|"); } else { println!("|{y}| ≯ |{x}|"); } } } fn demo_natural_le_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y.le_abs(&x) { println!("|{y}| ≤ |{x}|"); } else { println!("|{y}| ≰ |{x}|"); } } } fn demo_natural_ge_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y.ge_abs(&x) { println!("|{y}| ≥ |{x}|"); } else { println!("|{y}| ≱ |{x}|"); } } } fn benchmark_integer_partial_cmp_abs_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp_abs(&Natural)", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.partial_cmp_abs(&y)); }), ("rug", &mut |((x, y), _)| no_out!(x.cmp_abs(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp_abs(&Natural)", BenchmarkType::Algorithms, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(x.partial_cmp_abs(&y)); }), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y)); }), ], ); } fn benchmark_natural_partial_cmp_abs_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp_abs(&Integer)", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(y.partial_cmp_abs(&x)); }), ("rug", &mut |((x, y), _)| no_out!(y.cmp_abs(&x))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp_abs(&Integer)", BenchmarkType::Algorithms, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(y.partial_cmp_abs(&x)); }), ("using abs", &mut |(x, y)| { no_out!(y.partial_cmp(&x.abs())); }), ], ); } fn benchmark_integer_lt_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.lt_abs(&Natural)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_integer_gt_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.gt_abs(&Natural)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_integer_le_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.le_abs(&Natural)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_integer_ge_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ge_abs(&Natural)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_natural_lt_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.lt_abs(&Integer)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_natural_gt_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gt_abs(&Integer)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_natural_le_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.le_abs(&Integer)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_natural_ge_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ge_abs(&Integer)", BenchmarkType::Single, integer_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &integer_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_primitive_float_pair_gen; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_integer_partial_cmp_abs_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_integer); register_primitive_float_benches!(runner, benchmark_integer_partial_cmp_abs_float_algorithms); register_primitive_float_benches!(runner, benchmark_float_partial_cmp_abs_integer_algorithms); } fn demo_integer_partial_cmp_abs_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialOrdAbs, { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp_abs(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("|{}| < |{}|", n, NiceFloat(f)), Some(Equal) => println!("|{}| = |{}|", n, NiceFloat(f)), Some(Greater) => println!("|{}| > |{}|", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_abs_integer + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp_abs(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("|{}| < |{}|", NiceFloat(f), n), Some(Equal) => println!("|{}| = |{}|", NiceFloat(f), n), Some(Greater) => println!("|{}| > |{}|", NiceFloat(f), n), } } } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Integer.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, integer_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_integer_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.abs().partial_cmp(&x.abs())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_signed_pair_gen, integer_unsigned_pair_gen}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_partial_cmp_abs_unsigned); register_signed_demos!(runner, demo_integer_partial_cmp_abs_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_integer); register_signed_demos!(runner, demo_signed_partial_cmp_abs_integer); register_unsigned_demos!(runner, demo_integer_lt_abs_unsigned); register_signed_demos!(runner, demo_integer_lt_abs_signed); register_unsigned_demos!(runner, demo_integer_gt_abs_unsigned); register_signed_demos!(runner, demo_integer_gt_abs_signed); register_unsigned_demos!(runner, demo_integer_le_abs_unsigned); register_signed_demos!(runner, demo_integer_le_abs_signed); register_unsigned_demos!(runner, demo_integer_ge_abs_unsigned); register_signed_demos!(runner, demo_integer_ge_abs_signed); register_unsigned_demos!(runner, demo_unsigned_lt_abs_integer); register_signed_demos!(runner, demo_signed_lt_abs_integer); register_unsigned_demos!(runner, demo_unsigned_gt_abs_integer); register_signed_demos!(runner, demo_signed_gt_abs_integer); register_unsigned_demos!(runner, demo_unsigned_le_abs_integer); register_signed_demos!(runner, demo_signed_le_abs_integer); register_unsigned_demos!(runner, demo_unsigned_ge_abs_integer); register_signed_demos!(runner, demo_signed_ge_abs_integer); register_unsigned_benches!( runner, benchmark_integer_partial_cmp_abs_unsigned_algorithms ); register_signed_benches!(runner, benchmark_integer_partial_cmp_abs_signed_algorithms); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_abs_integer_algorithms ); register_signed_benches!(runner, benchmark_signed_partial_cmp_abs_integer_algorithms); register_unsigned_benches!(runner, benchmark_integer_lt_abs_unsigned); register_signed_benches!(runner, benchmark_integer_lt_abs_signed); register_unsigned_benches!(runner, benchmark_integer_gt_abs_unsigned); register_signed_benches!(runner, benchmark_integer_gt_abs_signed); register_unsigned_benches!(runner, benchmark_integer_le_abs_unsigned); register_signed_benches!(runner, benchmark_integer_le_abs_signed); register_unsigned_benches!(runner, benchmark_integer_ge_abs_unsigned); register_signed_benches!(runner, benchmark_integer_ge_abs_signed); register_unsigned_benches!(runner, benchmark_unsigned_lt_abs_integer); register_signed_benches!(runner, benchmark_signed_lt_abs_integer); register_unsigned_benches!(runner, benchmark_unsigned_gt_abs_integer); register_signed_benches!(runner, benchmark_signed_gt_abs_integer); register_unsigned_benches!(runner, benchmark_unsigned_le_abs_integer); register_signed_benches!(runner, benchmark_signed_le_abs_integer); register_unsigned_benches!(runner, benchmark_unsigned_ge_abs_integer); register_signed_benches!(runner, benchmark_signed_ge_abs_integer); } fn demo_integer_partial_cmp_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialOrdAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp_abs(&u).unwrap() { Less => println!("|{n}| < |{u}|"), Equal => println!("|{n}| = |{u}|"), Greater => println!("|{n}| > |{u}|"), } } } fn demo_integer_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialOrdAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp_abs(&i).unwrap() { Less => println!("|{n}| < |{i}|"), Equal => println!("|{n}| = |{i}|"), Greater => println!("|{n}| > |{i}|"), } } } fn demo_unsigned_partial_cmp_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { match u.partial_cmp_abs(&n).unwrap() { Less => println!("|{u}| < |{n}|"), Equal => println!("|{u}| = |{n}|"), Greater => println!("|{u}| > |{n}|"), } } } fn demo_signed_partial_cmp_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp_abs(&n).unwrap() { Less => println!("|{i}| < |{n}|"), Equal => println!("|{i}| = |{n}|"), Greater => println!("|{i}| > |{n}|"), } } } fn demo_integer_lt_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n.lt_abs(&u) { println!("|{n}| < |{u}|"); } else { println!("|{n}| ≮ |{u}|"); } } } fn demo_integer_lt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n.lt_abs(&i) { println!("|{n}| < |{i}|"); } else { println!("|{n}| ≮ |{i}|"); } } } fn demo_integer_gt_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n.gt_abs(&u) { println!("|{n}| > |{u}|"); } else { println!("|{n}| ≯ |{u}|"); } } } fn demo_integer_gt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n.gt_abs(&i) { println!("|{n}| > |{i}|"); } else { println!("|{n}| ≯ |{i}|"); } } } fn demo_integer_le_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n.le_abs(&u) { println!("|{n}| ≤ |{u}|"); } else { println!("|{n}| ≰ |{u}|"); } } } fn demo_integer_le_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n.le_abs(&i) { println!("|{n}| ≤ |{i}|"); } else { println!("|{n}| ≰ |{i}|"); } } } fn demo_integer_ge_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n.ge_abs(&u) { println!("|{n}| ≥ |{u}|"); } else { println!("|{n}| ≱ |{u}|"); } } } fn demo_integer_ge_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrdAbs, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n.ge_abs(&i) { println!("|{n}| ≥ |{i}|"); } else { println!("|{n}| ≱ |{i}|"); } } } fn demo_unsigned_lt_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u.lt_abs(&n) { println!("|{u}| < |{n}|"); } else { println!("|{u}| ≮ |{n}|"); } } } fn demo_signed_lt_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i.lt_abs(&n) { println!("|{i}| < |{n}|"); } else { println!("|{i}| ≮ |{n}|"); } } } fn demo_unsigned_gt_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u.gt_abs(&n) { println!("|{u}| > |{n}|"); } else { println!("|{u}| ≯ |{n}|"); } } } fn demo_signed_gt_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i.gt_abs(&n) { println!("|{i}| > |{n}|"); } else { println!("|{i}| ≯ |{n}|"); } } } fn demo_unsigned_le_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u.le_abs(&n) { println!("|{u}| ≤ |{n}|"); } else { println!("|{u}| ≰ |{n}|"); } } } fn demo_signed_le_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i.le_abs(&n) { println!("|{i}| ≤ |{n}|"); } else { println!("|{i}| ≰ |{n}|"); } } } fn demo_unsigned_ge_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u.ge_abs(&n) { println!("|{u}| ≥ |{n}|"); } else { println!("|{u}| ≱ |{n}|"); } } } fn demo_signed_ge_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i.ge_abs(&n) { println!("|{i}| ≥ |{n}|"); } else { println!("|{i}| ≱ |{n}|"); } } } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Integer.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs + PartialOrd<::Output>, { run_benchmark( &format!("Integer.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.unsigned_abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_abs_integer_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.partial_cmp(&x.abs()))), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_abs_integer_algorithms< T: PartialOrdAbs + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialOrd, { run_benchmark( &format!("{}.partial_cmp_abs(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.unsigned_abs().partial_cmp(&x.abs())); }), ], ); } fn benchmark_integer_lt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.lt_abs(&{})", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_integer_lt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.lt_abs(&{})", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_integer_gt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.gt_abs(&{})", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_integer_gt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.gt_abs(&{})", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_integer_le_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.le_abs(&{})", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_integer_le_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.le_abs(&{})", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_integer_ge_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.ge_abs(&{})", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_integer_ge_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrdAbs, { run_benchmark( &format!("Integer.ge_abs(&{})", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_unsigned_lt_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_signed_lt_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_unsigned_gt_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_signed_gt_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_unsigned_le_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_signed_le_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_unsigned_ge_abs_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } fn benchmark_signed_ge_abs_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Integer)", T::NAME), BenchmarkType::Single, integer_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_integer_natural_max_bit_bucketer; use malachite_nz::test_util::generators::{integer_natural_pair_gen, integer_natural_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_partial_cmp_natural); register_demo!(runner, demo_natural_partial_cmp_integer); register_bench!( runner, benchmark_integer_partial_cmp_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_cmp_integer_library_comparison ); } fn demo_integer_partial_cmp_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y).unwrap() { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } fn demo_natural_partial_cmp_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { match y.partial_cmp(&x).unwrap() { Less => println!("{y} < {x}"), Equal => println!("{y} = {x}"), Greater => println!("{y} > {x}"), } } } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp(&Natural)", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp(&Integer)", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_2_pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{ integer_primitive_float_pair_gen, integer_primitive_float_pair_gen_rm, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_integer_partial_cmp_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_integer); register_primitive_float_benches!( runner, benchmark_integer_partial_cmp_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_cmp_integer_library_comparison ); } fn demo_integer_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialOrd, { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("{} < {}", n, NiceFloat(f)), Some(Equal) => println!("{} = {}", n, NiceFloat(f)), Some(Greater) => println!("{} > {}", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_integer + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("{} < {}", NiceFloat(f), n), Some(Equal) => println!("{} = {}", NiceFloat(f), n), Some(Greater) => println!("{} > {}", NiceFloat(f), n), } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Integer.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, integer_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_cmp_integer_library_comparison< T: PartialOrd + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Integer)", T::NAME), BenchmarkType::LibraryComparison, integer_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_signed_pair_gen, integer_signed_pair_gen_rm, integer_unsigned_pair_gen, integer_unsigned_pair_gen_nrm, integer_unsigned_pair_gen_rm, }; use malachite_nz::test_util::integer::comparison::partial_cmp_primitive_int::*; use num::BigInt; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_partial_cmp_unsigned); register_signed_demos!(runner, demo_integer_partial_cmp_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_integer); register_signed_demos!(runner, demo_signed_partial_cmp_integer); register_unsigned_benches!( runner, benchmark_integer_partial_cmp_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_integer_partial_cmp_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_integer_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_cmp_integer_library_comparison ); } fn demo_integer_partial_cmp_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialOrd, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp(&u).unwrap() { Less => println!("{n} < {u}"), Equal => println!("{n} = {u}"), Greater => println!("{n} > {u}"), } } } fn demo_integer_partial_cmp_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialOrd, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp(&i).unwrap() { Less => println!("{n} < {i}"), Equal => println!("{n} = {i}"), Greater => println!("{n} > {i}"), } } } fn demo_unsigned_partial_cmp_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { match u.partial_cmp(&n).unwrap() { Less => println!("{u} < {n}"), Equal => println!("{u} = {n}"), Greater => println!("{u} > {n}"), } } } fn demo_signed_partial_cmp_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp(&n).unwrap() { Less => println!("{i} < {n}"), Equal => println!("{i} = {n}"), Greater => println!("{i} > {n}"), } } } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BigInt: From, Integer: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Integer.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.partial_cmp(&y)); }), ("num", &mut |((x, y), _, _)| { no_out!(num_partial_cmp_primitive(&x, y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Integer.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, integer_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_integer_library_comparison< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Integer)", T::NAME), BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_integer_library_comparison< T: PartialOrd + PartialOrd + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Integer)", T::NAME), BenchmarkType::LibraryComparison, integer_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_integer_natural_max_bit_bucketer; use malachite_nz::test_util::generators::{integer_natural_pair_gen, integer_natural_pair_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_partial_eq_natural); register_demo!(runner, demo_natural_partial_eq_integer); register_bench!( runner, benchmark_integer_partial_eq_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_eq_integer_library_comparison ); } fn demo_integer_partial_eq_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_natural_partial_eq_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_natural_pair_gen().get(gm, config).take(limit) { if y == x { println!("{y} = {x}"); } else { println!("{y} ≠ {x}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_eq_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer == Natural", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_eq_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural == Integer", BenchmarkType::LibraryComparison, integer_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::pair_2_pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{ integer_primitive_float_pair_gen, integer_primitive_float_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_integer_partial_eq_float); register_primitive_float_demos!(runner, demo_float_partial_eq_integer); register_primitive_float_benches!( runner, benchmark_integer_partial_eq_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_eq_integer_library_comparison ); } fn demo_integer_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialEq, { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n == f { println!("{} = {}", n, NiceFloat(f)); } else { println!("{} ≠ {}", n, NiceFloat(f)); } } } fn demo_float_partial_eq_integer + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in integer_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if f == n { println!("{} = {}", NiceFloat(f), n); } else { println!("{} ≠ {}", NiceFloat(f), n); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Integer == {}", T::NAME), BenchmarkType::LibraryComparison, integer_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_eq_integer_library_comparison< T: PartialEq + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Integer", T::NAME), BenchmarkType::LibraryComparison, integer_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_1_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_signed_pair_gen, integer_signed_pair_gen_rm, integer_unsigned_pair_gen, integer_unsigned_pair_gen_nrm, integer_unsigned_pair_gen_rm, }; use malachite_nz::test_util::integer::comparison::partial_eq_primitive_int::*; use num::BigInt; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_partial_eq_unsigned); register_signed_demos!(runner, demo_integer_partial_eq_signed); register_unsigned_demos!(runner, demo_unsigned_partial_eq_integer); register_signed_demos!(runner, demo_signed_partial_eq_integer); register_unsigned_benches!( runner, benchmark_integer_partial_eq_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_integer_partial_eq_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_eq_integer_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_eq_integer_library_comparison ); } fn demo_integer_partial_eq_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: PartialEq, { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if n == u { println!("{n} = {u}"); } else { println!("{n} ≠ {u}"); } } } fn demo_integer_partial_eq_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: PartialEq, { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if n == i { println!("{n} = {i}"); } else { println!("{n} ≠ {i}"); } } } fn demo_unsigned_partial_eq_integer + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in integer_unsigned_pair_gen::().get(gm, config).take(limit) { if u == n { println!("{u} = {n}"); } else { println!("{u} ≠ {n}"); } } } fn demo_signed_partial_eq_integer + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in integer_signed_pair_gen::().get(gm, config).take(limit) { if i == n { println!("{i} = {n}"); } else { println!("{i} ≠ {n}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_eq_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BigInt: From, Integer: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Integer == {}", T::NAME), BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x == y)), ("num", &mut |((x, y), _, _)| { no_out!(num_partial_eq_primitive(&x, y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_eq_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Integer == {}", T::NAME), BenchmarkType::LibraryComparison, integer_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_unsigned_partial_eq_integer_library_comparison< T: PartialEq + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Integer", T::NAME), BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_signed_partial_eq_integer_library_comparison< T: PartialEq + PartialEq + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Integer", T::NAME), BenchmarkType::LibraryComparison, integer_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ triple_3_integer_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_nrm, integer_pair_gen, integer_pair_gen_nrm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_clone); register_demo!(runner, demo_integer_clone_from); register_bench!(runner, benchmark_integer_clone_library_comparison); register_bench!(runner, benchmark_integer_clone_from_library_comparison); } fn demo_integer_clone(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("clone({}) = {}", n, n.clone()); } } fn demo_integer_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } #[allow(clippy::redundant_clone, unused_must_use)] fn benchmark_integer_clone_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.clone()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.clone())), ("num", &mut |(n, _, _)| no_out!(n.clone())), ("rug", &mut |(_, n, _)| no_out!(n.clone())), ], ); } fn benchmark_integer_clone_from_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.clone_from(&Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (mut x, y))| x.clone_from(&y)), ("num", &mut |((mut x, y), _, _)| x.clone_from(&y)), ("rug", &mut |(_, (mut x, y), _)| x.clone_from(&y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/floating_point_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::integer::conversion::primitive_float_from_integer::PrimitiveFloatFromIntegerError; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_1, integer_rounding_mode_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_rounding_from_integer); register_primitive_float_demos!(runner, demo_float_try_from_integer); register_primitive_float_demos!(runner, demo_float_exact_from_integer); register_primitive_float_demos!(runner, demo_float_convertible_from_integer); register_primitive_float_benches!(runner, benchmark_float_rounding_from_integer); register_primitive_float_benches!(runner, benchmark_float_try_from_integer); register_primitive_float_benches!(runner, benchmark_float_exact_from_integer); register_primitive_float_benches!(runner, benchmark_float_convertible_from_integer); } fn demo_float_rounding_from_integer< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat + for<'a> RoundingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in integer_rounding_mode_pair_gen_var_1::() .get(gm, config) .take(limit) { let (x, o) = T::rounding_from(&n, rm); println!( "{}::rounding_from(&{}, {}) = {:?}", T::NAME, n, rm, (NiceFloat(x), o) ); } } fn demo_float_try_from_integer< T: for<'a> TryFrom<&'a Integer, Error = PrimitiveFloatFromIntegerError> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { println!( "{}::try_from(&{}) = {:?}", T::NAME, n.clone(), T::try_from(&n).map(NiceFloat) ); } } fn demo_float_exact_from_integer ExactFrom<&'a Integer> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: TryFrom, { for n in integer_gen_var_1::().get(gm, config).take(limit) { println!( "{}::exact_from(&{}) = {}", T::NAME, n.clone(), NiceFloat(T::exact_from(&n)) ); } } fn demo_float_convertible_from_integer ConvertibleFrom<&'a Integer> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { if T::convertible_from(&n) { println!("{} is convertible to an {}", n, T::NAME); } else { println!("{} is not convertible to an {}", n, T::NAME); } } } fn benchmark_float_rounding_from_integer< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat + for<'a> RoundingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::rounding_from(Integer, RoundingMode)", T::NAME), BenchmarkType::Single, integer_rounding_mode_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(n, rm)| { no_out!(T::rounding_from(&n, rm)); })], ); } fn benchmark_float_try_from_integer TryFrom<&'a Integer> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(Integer)", T::NAME), BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::try_from(&n).ok()))], ); } fn benchmark_float_exact_from_integer ExactFrom<&'a Integer> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: TryFrom, { run_benchmark( &format!("{}::exact_from(Integer)", T::NAME), BenchmarkType::Single, integer_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } fn benchmark_float_convertible_from_integer< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(Integer)", T::NAME), BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(&n)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::bool_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_bool); } fn demo_integer_from_bool(gm: GenMode, config: &GenConfig, limit: usize) { for b in bool_gen().get(gm, config).take(limit) { println!("Integer::from({}) = {}", b, Integer::from(b)); } } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/from_floating_point.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::from::SignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_primitive_float_bucketer, primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_5, primitive_float_rounding_mode_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_integer_rounding_from_float); register_primitive_float_demos!(runner, demo_integer_try_from_float); register_primitive_float_demos!(runner, demo_integer_exact_from_float); register_primitive_float_demos!(runner, demo_integer_convertible_from_float); register_primitive_float_benches!(runner, benchmark_integer_rounding_from_float); register_primitive_float_benches!(runner, benchmark_integer_try_from_float); register_primitive_float_benches!(runner, benchmark_integer_exact_from_float); register_primitive_float_benches!(runner, benchmark_integer_convertible_from_float_algorithms); } fn demo_integer_rounding_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: RoundingFrom, { for (f, rm) in primitive_float_rounding_mode_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "Integer::rounding_from({}, {}) = {:?}", NiceFloat(f), rm, Integer::rounding_from(f, rm) ); } } fn demo_integer_try_from_float(gm: GenMode, config: &GenConfig, limit: usize) where Integer: TryFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { println!( "Integer::try_from({}) = {:?}", NiceFloat(f), Integer::try_from(f) ); } } fn demo_integer_exact_from_float(gm: GenMode, config: &GenConfig, limit: usize) where Integer: ExactFrom, { for f in primitive_float_gen_var_5::().get(gm, config).take(limit) { println!( "Integer::exact_from({}) = {}", NiceFloat(f), Integer::exact_from(f) ); } } fn demo_integer_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: ConvertibleFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { if Integer::convertible_from(f) { println!("{} is convertible to a Integer", NiceFloat(f)); } else { println!("{} is not convertible to a Integer", NiceFloat(f)); } } } fn benchmark_integer_rounding_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: RoundingFrom, { run_benchmark( &format!("Integer::rounding_from({}, RoundingMode)", T::NAME), BenchmarkType::Single, primitive_float_rounding_mode_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("f"), &mut [("Malachite", &mut |(f, rm)| { no_out!(Integer::rounding_from(f, rm)); })], ); } fn benchmark_integer_try_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: TryFrom, { run_benchmark( &format!("Integer::try_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Integer::try_from(f).ok()))], ); } fn benchmark_integer_exact_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: ExactFrom, { run_benchmark( &format!("Integer::exact_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Integer::exact_from(f)))], ); } #[allow(unused_must_use)] fn benchmark_integer_convertible_from_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: TryFrom + ConvertibleFrom, { run_benchmark( &format!("Integer::convertible_from({})", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("standard", &mut |f| no_out!(Integer::convertible_from(f))), ("using try_from", &mut |f| { no_out!(Integer::try_from(f).is_ok()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_natural); register_demo!(runner, demo_integer_from_natural_ref); register_bench!(runner, benchmark_integer_from_natural_evaluation_strategy); } fn demo_integer_from_natural(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!("Integer::from({}) = {}", n_clone, Integer::from(n)); } } fn demo_integer_from_natural_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("Integer::from(&{}) = {}", n, Integer::from(&n)); } } #[allow(unused_must_use)] fn benchmark_integer_from_natural_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from(Natural)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Integer::from(Natural)", &mut |n| no_out!(Integer::from(n))), ("Integer::from(&Natural)", &mut |n| { no_out!(Integer::from(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use num::BigInt; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_integer_from_unsigned); register_signed_demos!(runner, demo_integer_from_signed); register_demo!(runner, demo_integer_const_from_unsigned); register_demo!(runner, demo_integer_const_from_signed); register_unsigned_benches!(runner, benchmark_integer_from_unsigned); register_signed_benches!(runner, benchmark_integer_from_signed); register_bench!(runner, benchmark_integer_from_u32_library_comparison); register_bench!(runner, benchmark_integer_from_u64_library_comparison); register_bench!(runner, benchmark_integer_from_i32_library_comparison); register_bench!(runner, benchmark_integer_from_i64_library_comparison); register_bench!(runner, benchmark_integer_const_from_unsigned); register_bench!(runner, benchmark_integer_const_from_signed); } fn demo_integer_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Integer: From, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("Integer::from({}) = {}", u, Integer::from(u)); } } fn demo_integer_from_signed(gm: GenMode, config: &GenConfig, limit: usize) where Integer: From, { for i in signed_gen::().get(gm, config).take(limit) { println!("Integer::from({}) = {}", i, Integer::from(i)); } } fn demo_integer_const_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen().get(gm, config).take(limit) { println!( "Integer::const_from_unsigned({}) = {}", u, Integer::const_from_unsigned(u) ); } } fn demo_integer_const_from_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen().get(gm, config).take(limit) { println!( "Integer::const_from_signed({}) = {}", i, Integer::const_from_signed(i) ); } } #[allow(unused_must_use)] fn benchmark_integer_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: From, { run_benchmark( &format!("Integer::from({})", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Integer::from(u)))], ); } #[allow(unused_must_use)] fn benchmark_integer_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: From, { run_benchmark( &format!("Integer::from({})", T::NAME), BenchmarkType::Single, signed_gen().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Integer::from(u)))], ); } #[allow(unused_must_use)] fn benchmark_integer_from_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from(u32)", BenchmarkType::LibraryComparison, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(Integer::from(u))), ("num", &mut |u| no_out!(BigInt::from(u))), ("rug", &mut |u| no_out!(rug::Integer::from(u))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_from_u64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from(u64)", BenchmarkType::LibraryComparison, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(Integer::from(u))), ("num", &mut |u| no_out!(BigInt::from(u))), ("rug", &mut |u| no_out!(rug::Integer::from(u))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_from_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from(i32)", BenchmarkType::LibraryComparison, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(Integer::from(i))), ("num", &mut |i| no_out!(BigInt::from(i))), ("rug", &mut |i| no_out!(rug::Integer::from(i))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_from_i64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from(i64)", BenchmarkType::LibraryComparison, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(Integer::from(i))), ("num", &mut |i| no_out!(BigInt::from(i))), ("rug", &mut |i| no_out!(rug::Integer::from(i))), ], ); } fn benchmark_integer_const_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::const_from_unsigned(Limb)", BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| { no_out!(Integer::const_from_unsigned(u)); })], ); } fn benchmark_integer_const_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::const_from_signed(Limb)", BenchmarkType::Single, signed_gen().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| no_out!(Integer::const_from_signed(i)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/from_twos_complement_limbs.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_twos_complement_limbs_asc); register_demo!(runner, demo_integer_from_twos_complement_limbs_desc); register_demo!(runner, demo_integer_from_owned_twos_complement_limbs_asc); register_demo!(runner, demo_integer_from_owned_twos_complement_limbs_desc); register_bench!( runner, benchmark_integer_from_twos_complement_limbs_asc_evaluation_strategy ); register_bench!( runner, benchmark_integer_from_twos_complement_limbs_desc_evaluation_strategy ); } fn demo_integer_from_twos_complement_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_twos_complement_limbs_asc({:?}) = {:?}", xs, Integer::from_twos_complement_limbs_asc(&xs) ); } } fn demo_integer_from_twos_complement_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_twos_complement_limbs_desc({:?}) = {:?}", xs, Integer::from_twos_complement_limbs_desc(&xs) ); } } fn demo_integer_from_owned_twos_complement_limbs_asc( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_owned_twos_complement_limbs_asc({:?}) = {:?}", xs.clone(), Integer::from_owned_twos_complement_limbs_asc(xs) ); } } fn demo_integer_from_owned_twos_complement_limbs_desc( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_owned_twos_complement_limbs_desc({:?}) = {:?}", xs.clone(), Integer::from_owned_twos_complement_limbs_desc(xs) ); } } fn benchmark_integer_from_twos_complement_limbs_asc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_twos_complement_limbs_asc(&[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ( "Integer::from_twos_complement_limbs_asc(&[Limb])", &mut |xs| no_out!(Integer::from_twos_complement_limbs_asc(&xs)), ), ( "Integer::from_owned_twos_complement_limbs_asc(Vec)", &mut |xs| no_out!(Integer::from_owned_twos_complement_limbs_asc(xs)), ), ], ); } fn benchmark_integer_from_twos_complement_limbs_desc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_twos_complement_limbs_desc(&[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ( "Integer::from_twos_complement_limbs_desc(&[Limb])", &mut |xs| no_out!(Integer::from_twos_complement_limbs_desc(&xs)), ), ( "Integer::from_owned_twos_complement_limbs_desc(Vec)", &mut |xs| no_out!(Integer::from_owned_twos_complement_limbs_desc(xs)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_is_integer); register_bench!(runner, benchmark_integer_is_integer); } fn demo_integer_is_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { if n.is_integer() { println!("{n} is an integer"); } else { println!("{n} is not an integer"); } } } fn benchmark_integer_is_integer(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.is_integer()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); floating_point_from_integer::register(runner); from_bool::register(runner); from_floating_point::register(runner); from_natural::register(runner); from_primitive_int::register(runner); from_twos_complement_limbs::register(runner); is_integer::register(runner); natural_from_integer::register(runner); primitive_int_from_integer::register(runner); serde::register(runner); string::register(runner); to_twos_complement_limbs::register(runner); } mod clone; mod floating_point_from_integer; mod from_bool; mod from_floating_point; mod from_natural; mod from_primitive_int; mod from_twos_complement_limbs; mod is_integer; mod natural_from_integer; mod primitive_int_from_integer; mod serde; mod string; mod to_twos_complement_limbs; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/natural_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_gen, integer_gen_var_4}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_try_from_integer); register_demo!(runner, demo_natural_try_from_integer_ref); register_demo!(runner, demo_natural_exact_from_integer); register_demo!(runner, demo_natural_exact_from_integer_ref); register_demo!(runner, demo_natural_saturating_from_integer); register_demo!(runner, demo_natural_saturating_from_integer_ref); register_demo!(runner, demo_natural_convertible_from_integer); register_demo!(runner, demo_natural_convertible_from_integer_ref); register_bench!( runner, benchmark_natural_try_from_integer_evaluation_strategy ); register_bench!( runner, benchmark_natural_exact_from_integer_evaluation_strategy ); register_bench!( runner, benchmark_natural_saturating_from_integer_evaluation_strategy ); register_bench!( runner, benchmark_natural_convertible_from_integer_evaluation_strategy ); register_bench!( runner, benchmark_natural_convertible_from_integer_algorithms ); } fn demo_natural_try_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!( "Natural::try_from({}) = {:?}", n_clone, Natural::try_from(n) ); } } fn demo_natural_try_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("Natural::try_from(&{}) = {:?}", n, Natural::try_from(&n)); } } fn demo_natural_exact_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen_var_4().get(gm, config).take(limit) { let n_clone = n.clone(); println!( "Natural::exact_from({}) = {}", n_clone, Natural::exact_from(n) ); } } fn demo_natural_exact_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen_var_4().get(gm, config).take(limit) { println!("Natural::exact_from(&{}) = {}", n, Natural::exact_from(&n)); } } fn demo_natural_saturating_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!( "Natural::saturating_from({}) = {}", n_clone, Natural::saturating_from(n) ); } } fn demo_natural_saturating_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "Natural::saturating_from(&{}) = {}", n, Natural::saturating_from(&n) ); } } fn demo_natural_convertible_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!( "{} is {}convertible to a Natural", n_clone, if Natural::convertible_from(n) { "" } else { "not " }, ); } } fn demo_natural_convertible_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Natural", n, if Natural::convertible_from(&n) { "" } else { "not " }, ); } } fn benchmark_natural_try_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::try_from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Natural::try_from(Integer)", &mut |n| { no_out!(Natural::try_from(n).ok()); }), ("Natural::try_from(&Integer)", &mut |n| { no_out!(Natural::try_from(&n).ok()); }), ], ); } fn benchmark_natural_exact_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::exact_from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen_var_4().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Natural::exact_from(Integer)", &mut |n| { no_out!(Natural::exact_from(n)); }), ("Natural::exact_from(&Integer)", &mut |n| { no_out!(Natural::exact_from(&n)); }), ], ); } fn benchmark_natural_saturating_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::saturating_from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Natural::saturating_from(Integer)", &mut |n| { no_out!(Natural::saturating_from(n)); }), ("Natural::saturating_from(&Integer)", &mut |n| { no_out!(Natural::saturating_from(&n)); }), ], ); } fn benchmark_natural_convertible_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::convertible_from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Natural::convertible_from(Integer)", &mut |n| { no_out!(Natural::convertible_from(n)); }), ("Natural::convertible_from(&Integer)", &mut |n| { no_out!(Natural::convertible_from(&n)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_convertible_from_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::convertible_from(Integer)", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("standard", &mut |n| no_out!(Natural::convertible_from(n))), ("using try_from", &mut |n| { no_out!(Natural::try_from(n).is_ok()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/primitive_int_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, OverflowingFrom, SaturatingFrom, WrappingFrom, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_2_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_rm, integer_gen_var_5, integer_gen_var_6, }; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_demos!(runner, demo_primitive_int_try_from_integer); register_unsigned_demos!(runner, demo_unsigned_exact_from_integer); register_signed_demos!(runner, demo_signed_exact_from_integer); register_primitive_int_demos!(runner, demo_primitive_int_wrapping_from_integer); register_primitive_int_demos!(runner, demo_primitive_int_saturating_from_integer); register_primitive_int_demos!(runner, demo_primitive_int_overflowing_from_integer); register_primitive_int_demos!(runner, demo_primitive_int_convertible_from_integer); register_primitive_int_benches!(runner, benchmark_primitive_int_try_from_integer_algorithms); register_unsigned_benches!(runner, benchmark_unsigned_exact_from_integer); register_signed_benches!(runner, benchmark_signed_exact_from_integer); register_primitive_int_benches!( runner, benchmark_primitive_int_wrapping_from_integer_algorithms ); register_primitive_int_benches!(runner, benchmark_primitive_int_saturating_from_integer); register_primitive_int_benches!( runner, benchmark_primitive_int_overflowing_from_integer_algorithms ); register_primitive_int_benches!( runner, benchmark_primitive_int_convertible_from_integer_algorithms ); register_bench!(runner, benchmark_u32_try_from_integer_library_comparison); register_bench!( runner, benchmark_u32_wrapping_from_integer_library_comparison ); register_bench!(runner, benchmark_u64_try_from_integer_library_comparison); register_bench!( runner, benchmark_u64_wrapping_from_integer_library_comparison ); register_bench!(runner, benchmark_i32_try_from_integer_library_comparison); register_bench!( runner, benchmark_i32_wrapping_from_integer_library_comparison ); register_bench!(runner, benchmark_i64_try_from_integer_library_comparison); register_bench!( runner, benchmark_i64_wrapping_from_integer_library_comparison ); } fn demo_primitive_int_try_from_integer TryFrom<&'a Integer> + PrimitiveInt>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> >::Error: Debug, { for n in integer_gen().get(gm, config).take(limit) { println!("{}::try_from(&{}) = {:?}", T::NAME, n, T::try_from(&n)); } } fn demo_unsigned_exact_from_integer ExactFrom<&'a Integer> + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: From, { for n in integer_gen_var_5::().get(gm, config).take(limit) { println!("{}::exact_from(&{}) = {}", T::NAME, n, T::exact_from(&n)); } } fn demo_signed_exact_from_integer ExactFrom<&'a Integer> + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Integer: From, { for n in integer_gen_var_6::().get(gm, config).take(limit) { println!("{}::exact_from(&{}) = {}", T::NAME, n, T::exact_from(&n)); } } fn demo_primitive_int_wrapping_from_integer WrappingFrom<&'a Integer>>( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { println!( "{}::wrapping_from(&{}) = {}", T::NAME, n, T::wrapping_from(&n) ); } } fn demo_primitive_int_saturating_from_integer< T: PrimitiveInt + for<'a> SaturatingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { println!( "{}::saturating_from(&{}) = {}", T::NAME, n, T::saturating_from(&n) ); } } fn demo_primitive_int_overflowing_from_integer< T: for<'a> OverflowingFrom<&'a Integer> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { println!( "{}::overflowing_from(&{}) = {:?}", T::NAME, n, T::overflowing_from(&n) ); } } fn demo_primitive_int_convertible_from_integer< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in integer_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", n, if T::convertible_from(&n) { "" } else { "not " }, T::NAME, ); } } fn benchmark_primitive_int_try_from_integer_algorithms< T: for<'a> TryFrom<&'a Integer> + for<'a> OverflowingFrom<&'a Integer> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("standard", &mut |n| no_out!(T::try_from(&n).ok())), ("using overflowing_from", &mut |n| { let (value, overflow) = T::overflowing_from(&n); if overflow { None } else { Some(value) }; }), ], ); } fn benchmark_unsigned_exact_from_integer ExactFrom<&'a Integer> + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: From, { run_benchmark( &format!("{}::exact_from(&Integer)", T::NAME), BenchmarkType::Single, integer_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } fn benchmark_signed_exact_from_integer ExactFrom<&'a Integer> + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: From, { run_benchmark( &format!("{}::exact_from(&Integer)", T::NAME), BenchmarkType::Single, integer_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_primitive_int_wrapping_from_integer_algorithms< T: for<'a> OverflowingFrom<&'a Integer> + PrimitiveInt + for<'a> WrappingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::wrapping_from(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("standard", &mut |n| no_out!(T::wrapping_from(&n))), ("using overflowing_from", &mut |n| { T::overflowing_from(&n).0; }), ], ); } fn benchmark_primitive_int_saturating_from_integer< T: PrimitiveInt + for<'a> SaturatingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::saturating_from(&Integer)", T::NAME), BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(T::saturating_from(&n)))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_primitive_int_overflowing_from_integer_algorithms< T: for<'a> ConvertibleFrom<&'a Integer> + for<'a> OverflowingFrom<&'a Integer> + PrimitiveInt + for<'a> WrappingFrom<&'a Integer>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::overflowing_from(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("standard", &mut |n| no_out!(T::overflowing_from(&n))), ("using wrapping_from and convertible_from", &mut |n| { no_out!((T::wrapping_from(&n), !T::convertible_from(&n))); }), ], ); } #[allow(unused_must_use)] fn benchmark_primitive_int_convertible_from_integer_algorithms< T: for<'a> TryFrom<&'a Integer> + for<'a> ConvertibleFrom<&'a Integer> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(&Integer)", T::NAME), BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("standard", &mut |n| no_out!(T::convertible_from(&n))), ("using try_from", &mut |n| no_out!(T::try_from(&n).is_ok())), ], ); } fn benchmark_u32_try_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32::try_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u32::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_u32())), ], ); } fn benchmark_u32_wrapping_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32::wrapping_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u32::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_u32_wrapping())), ], ); } fn benchmark_u64_try_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64::try_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u64::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_u64())), ], ); } fn benchmark_u64_wrapping_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64::wrapping_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u64::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_u64_wrapping())), ], ); } fn benchmark_i32_try_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i32::try_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i32::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_i32())), ], ); } fn benchmark_i32_wrapping_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i32::wrapping_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i32::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_i32_wrapping())), ], ); } fn benchmark_i64_try_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i64::try_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i64::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_i64())), ], ); } fn benchmark_i64_wrapping_from_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i64::wrapping_from(&Integer)", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i64::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_i64_wrapping())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_9}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::{ integer_deserialize_bucketer, triple_3_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_gen, integer_gen_nrm, string_triple_gen_var_2}; use num::BigInt; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_serialize_json); register_demo!(runner, demo_integer_deserialize_json); register_demo!(runner, demo_integer_deserialize_json_targeted); register_bench!(runner, benchmark_integer_serialize_json_library_comparison); register_bench!(runner, benchmark_integer_deserialize_json); register_bench!( runner, benchmark_integer_deserialize_json_library_comparison ); } fn demo_integer_serialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "serde_json::to_string({}) = {}", n, serde_json::to_string(&n).unwrap() ); } } fn demo_integer_deserialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { let n: Result = serde_json::from_str(&s); println!("serde_json::from_str({s}) = {n:?}"); } } fn demo_integer_deserialize_json_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_9().get(gm, config).take(limit) { let n: Integer = serde_json::from_str(&s).unwrap(); println!("serde_json::from_str({s}) = {n}"); } } fn benchmark_integer_serialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::to_string(&Integer)", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("num", &mut |(x, _, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("rug", &mut |(_, x, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ], ); } fn benchmark_integer_deserialize_json( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| { let _n: Integer = serde_json::from_str(&s).unwrap(); })], ); } fn benchmark_integer_deserialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::LibraryComparison, string_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &integer_deserialize_bucketer(), &mut [ ("Malachite", &mut |(_, _, s)| { let _n: Integer = serde_json::from_str(&s).unwrap(); }), ("num", &mut |(s, _, _)| { let _n: BigInt = serde_json::from_str(&s).unwrap(); }), ("rug", &mut |(_, s, _)| { let _n: rug::Integer = serde_json::from_str(&s).unwrap(); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::FromSciString; use malachite_base::test_util::bench::bucketers::{ pair_1_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_sci_string); register_demo!(runner, demo_integer_from_sci_string_targeted); register_demo!(runner, demo_integer_from_sci_string_with_options); register_demo!(runner, demo_integer_from_sci_string_with_options_targeted); register_bench!(runner, benchmark_integer_from_sci_string); register_bench!(runner, benchmark_integer_from_sci_string_with_options); } fn demo_integer_from_sci_string(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_14().get(gm, config).take(limit) { println!( "Integer::from_sci_string({}) = {:?}", s, Integer::from_sci_string(&s) ); } } fn demo_integer_from_sci_string_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_15().get(gm, config).take(limit) { println!( "Integer::from_sci_string({}) = {:?}", s, Integer::from_sci_string(&s) ); } } fn demo_integer_from_sci_string_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (s, options) in string_from_sci_string_options_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::from_sci_string_with_options({}, {:?}) = {:?}", s, options, Integer::from_sci_string_with_options(&s, options) ); } } fn demo_integer_from_sci_string_with_options_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, options) in string_from_sci_string_options_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Integer::from_sci_string_with_options({}, {:?}) = {:?}", s, options, Integer::from_sci_string_with_options(&s, options) ); } } fn benchmark_integer_from_sci_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_sci_string(&str)", BenchmarkType::Single, string_gen_var_15().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(Integer::from_sci_string(&s)))], ); } fn benchmark_integer_from_sci_string_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_sci_string_with_options(&str, FromSciStringOptions)", BenchmarkType::Single, string_from_sci_string_options_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_string_len_bucketer("s"), &mut [("Malachite", &mut |(s, options)| { no_out!(Integer::from_sci_string_with_options(&s, options)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{FromStringBase, WrappingFrom}; use malachite_base::test_util::bench::bucketers::{ pair_2_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_gen, string_gen_var_4, unsigned_string_pair_gen_var_2, unsigned_string_pair_gen_var_3, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use num::{BigInt, Num}; use std::str::FromStr; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_str); register_demo!(runner, demo_integer_from_str_targeted); register_demo!(runner, demo_integer_from_string_base); register_demo!(runner, demo_integer_from_string_base_targeted); register_bench!(runner, benchmark_integer_from_str_library_comparison); register_bench!( runner, benchmark_integer_from_string_base_library_comparison ); } fn demo_integer_from_string_base(gm: GenMode, config: &GenConfig, limit: usize) { for (base, s) in unsigned_string_pair_gen_var_2().get(gm, config).take(limit) { println!( "Integer::from_string_base({}, {}) = {:?}", base, s, Integer::from_string_base(base, &s) ); } } fn demo_integer_from_string_base_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (base, s) in unsigned_string_pair_gen_var_3().get(gm, config).take(limit) { println!( "Integer::from_string_base({}, {}) = {}", base, s, Integer::from_string_base(base, &s).unwrap() ); } } fn demo_integer_from_str(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!("Integer::from_str({}) = {:?}", s, Integer::from_str(&s)); } } fn demo_integer_from_str_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_4().get(gm, config).take(limit) { println!( "Integer::from_str({}) = {}", s, Integer::from_str(&s).unwrap() ); } } fn benchmark_integer_from_str_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_str(&str)", BenchmarkType::LibraryComparison, string_gen_var_4().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Integer::from_str(&s).unwrap()); }), ("num", &mut |s| no_out!(BigInt::from_str(&s).unwrap())), ("rug", &mut |s| no_out!(rug::Integer::from_str(&s).unwrap())), ], ); } fn benchmark_integer_from_string_base_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_string_base(u64, &str)", BenchmarkType::LibraryComparison, unsigned_string_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_2_string_len_bucketer("s"), &mut [ ("Malachite", &mut |(base, s)| { no_out!(Integer::from_string_base(base, &s).unwrap()); }), ("num", &mut |(base, s)| { no_out!(BigInt::from_str_radix(&s, u32::wrapping_from(base)).unwrap()); }), ("rug", &mut |(base, s)| { no_out!(rug::Integer::from_str_radix(&s, i32::wrapping_from(base)).unwrap()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/string/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sci_string::register(runner); from_string::register(runner); to_sci::register(runner); to_string::register(runner); } mod from_sci_string; mod from_string; mod to_sci; mod to_string; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ToSci; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_to_sci_options_pair_gen, integer_to_sci_options_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_to_sci); register_demo!(runner, demo_integer_fmt_sci_valid); register_demo!(runner, demo_integer_to_sci_with_options); register_bench!(runner, benchmark_integer_to_sci); register_bench!(runner, benchmark_integer_fmt_sci_valid); register_bench!(runner, benchmark_integer_to_sci_with_options); } fn demo_integer_to_sci(gm: GenMode, config: &GenConfig, limit: usize) { for x in integer_gen().get(gm, config).take(limit) { println!("({}).to_sci() = {}", x, x.to_sci()); } } fn demo_integer_fmt_sci_valid(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in integer_to_sci_options_pair_gen() .get(gm, config) .take(limit) { if x.fmt_sci_valid(options) { println!("{x} can be converted to sci using {options:?}"); } else { println!("{x} cannot be converted to sci using {options:?}"); } } } fn demo_integer_to_sci_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in integer_to_sci_options_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "to_sci_with_options({}, {:?}) = {}", x, options, x.to_sci_with_options(options) ); } } fn benchmark_integer_to_sci(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.to_sci()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |x| no_out!(x.to_sci().to_string()))], ); } fn benchmark_integer_fmt_sci_valid(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.fmt_sci_valid(ToSciOptions)", BenchmarkType::Single, integer_to_sci_options_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.fmt_sci_valid(options)); })], ); } fn benchmark_integer_to_sci_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_sci_with_options(ToSciOptions)", BenchmarkType::Single, integer_to_sci_options_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.to_sci_with_options(options).to_string()); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ToStringBase, WrappingFrom}; use malachite_base::strings::{ToBinaryString, ToLowerHexString, ToOctalString, ToUpperHexString}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_1_integer_bit_bucketer, triple_1_integer_bit_bucketer, triple_3_integer_bit_bucketer, triple_3_pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_nrm, integer_unsigned_pair_gen_var_1, integer_unsigned_pair_gen_var_1_nrm, integer_unsigned_pair_gen_var_2, integer_unsigned_unsigned_triple_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_to_string); register_demo!(runner, demo_integer_to_string_with_width); register_demo!(runner, demo_integer_to_binary_string); register_demo!(runner, demo_integer_to_binary_string_with_0b); register_demo!(runner, demo_integer_to_binary_string_with_width); register_demo!(runner, demo_integer_to_binary_string_with_0b_and_width); register_demo!(runner, demo_integer_to_octal_string); register_demo!(runner, demo_integer_to_octal_string_with_0o); register_demo!(runner, demo_integer_to_octal_string_with_width); register_demo!(runner, demo_integer_to_octal_string_with_0o_and_width); register_demo!(runner, demo_integer_to_lower_hex_string); register_demo!(runner, demo_integer_to_lower_hex_string_with_0x); register_demo!(runner, demo_integer_to_lower_hex_string_with_width); register_demo!(runner, demo_integer_to_lower_hex_string_with_0x_and_width); register_demo!(runner, demo_integer_to_upper_hex_string); register_demo!(runner, demo_integer_to_upper_hex_string_with_0x); register_demo!(runner, demo_integer_to_upper_hex_string_with_width); register_demo!(runner, demo_integer_to_upper_hex_string_with_0x_and_width); register_demo!(runner, demo_integer_to_string_base); register_demo!(runner, demo_integer_to_string_base_upper); register_demo!(runner, demo_integer_base_fmt_wrapper_fmt); register_demo!(runner, demo_integer_base_fmt_wrapper_fmt_upper); register_demo!(runner, demo_integer_base_fmt_wrapper_fmt_with_width); register_demo!(runner, demo_integer_base_fmt_wrapper_fmt_upper_with_width); register_bench!(runner, benchmark_integer_to_string_library_comparison); register_bench!(runner, benchmark_integer_to_string_algorithms); register_bench!(runner, benchmark_integer_to_string_with_width); register_bench!( runner, benchmark_integer_to_binary_string_library_comparison ); register_bench!(runner, benchmark_integer_to_binary_string_algorithms); register_bench!(runner, benchmark_integer_to_binary_string_with_width); register_bench!(runner, benchmark_integer_to_octal_string_library_comparison); register_bench!(runner, benchmark_integer_to_octal_string_algorithms); register_bench!(runner, benchmark_integer_to_octal_string_with_width); register_bench!( runner, benchmark_integer_to_lower_hex_string_library_comparison ); register_bench!(runner, benchmark_integer_to_lower_hex_string_algorithms); register_bench!(runner, benchmark_integer_to_lower_hex_string_with_width); register_bench!( runner, benchmark_integer_to_upper_hex_string_library_comparison ); register_bench!(runner, benchmark_integer_to_upper_hex_string_with_width); register_bench!(runner, benchmark_integer_to_string_base_library_comparison); register_bench!(runner, benchmark_integer_to_string_base_algorithms); register_bench!(runner, benchmark_integer_to_string_base_upper_algorithms); register_bench!(runner, benchmark_integer_base_fmt_wrapper_fmt_with_width); register_bench!( runner, benchmark_integer_base_fmt_wrapper_fmt_upper_with_width ); } fn demo_integer_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n}"); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", {}) = {}", width, n, format!("{n:0width$}") ); } } fn demo_integer_to_binary_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:b}"); } } fn demo_integer_to_binary_string_with_0b(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:#b}"); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_binary_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}b}}\", {}) = {}", width, n, format!("{n:0width$b}") ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_binary_string_with_0b_and_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}b}}\", {}) = {}", width, n, format!("{n:#0width$b}") ); } } fn demo_integer_to_octal_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:o}"); } } fn demo_integer_to_octal_string_with_0o(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:#o}"); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_octal_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}o}}\", {}) = {}", width, n, format!("{n:0width$o}") ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_octal_string_with_0o_and_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}o}}\", {}) = {}", width, n, format!("{n:#0width$o}") ); } } fn demo_integer_to_lower_hex_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:x}"); } } fn demo_integer_to_lower_hex_string_with_0x(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:#x}"); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_lower_hex_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}x}}\", {}) = {}", width, n, format!("{n:0width$x}") ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_lower_hex_string_with_0x_and_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}x}}\", {}) = {}", width, n, format!("{n:#0width$x}") ); } } fn demo_integer_to_upper_hex_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:X}"); } } fn demo_integer_to_upper_hex_string_with_0x(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("{n:#X}"); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_upper_hex_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}X}}\", {}) = {}", width, n, format!("{n:0width$X}") ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_to_upper_hex_string_with_0x_and_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, width) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}X}}\", {}) = {}", width, n, format!("{n:#0width$X}") ); } } fn demo_integer_to_string_base(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in integer_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "({}).to_string_base({}) = {}", x, base, x.to_string_base(base) ); } } fn demo_integer_to_string_base_upper(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in integer_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "({}).to_string_base_upper({}) = {}", x, base, x.to_string_base_upper(base) ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_base_fmt_wrapper_fmt(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in integer_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{}", BaseFmtWrapper::new(&x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_base_fmt_wrapper_fmt_upper(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in integer_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{:#}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{:#}", BaseFmtWrapper::new(&x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_base_fmt_wrapper_fmt_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base, width) in integer_unsigned_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:0width$}", BaseFmtWrapper::new(&x, base), width = width) ); } } #[allow(clippy::format_in_format_args)] fn demo_integer_base_fmt_wrapper_fmt_upper_with_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base, width) in integer_unsigned_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:#0width$}", BaseFmtWrapper::new(&x, base), width = width) ); } } fn benchmark_integer_to_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_string()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_string())), ("num", &mut |(x, _, _)| no_out!(x.to_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_string())), ], ); } fn benchmark_integer_to_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_string()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(10))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usize}}\", Integer)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$}")); })], ); } fn benchmark_integer_to_binary_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_binary_string()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_binary_string())), ("num", &mut |(x, _, _)| no_out!(x.to_binary_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_binary_string())), ], ); } fn benchmark_integer_to_binary_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_binary_string()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_binary_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(2))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_binary_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeb}}\", Integer)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$b}")); })], ); } fn benchmark_integer_to_octal_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_octal_string()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_octal_string())), ("num", &mut |(x, _, _)| no_out!(x.to_octal_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_octal_string())), ], ); } fn benchmark_integer_to_octal_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_octal_string()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_octal_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(8))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_octal_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeo}}\", Integer)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$o}")); })], ); } fn benchmark_integer_to_lower_hex_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_lower_hex_string()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(x.to_lower_hex_string()); }), ("num", &mut |(x, _, _)| no_out!(x.to_lower_hex_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_lower_hex_string())), ], ); } fn benchmark_integer_to_lower_hex_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_lower_hex_string()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_lower_hex_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(16))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_lower_hex_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizex}}\", Integer)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$x}")); })], ); } fn benchmark_integer_to_upper_hex_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_upper_hex_string()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(x.to_upper_hex_string()); }), ("num", &mut |(x, _, _)| no_out!(x.to_upper_hex_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_upper_hex_string())), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_upper_hex_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeX}}\", Integer)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$X}")); })], ); } fn benchmark_integer_to_string_base_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_string_base(u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_integer_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, base))| { no_out!(x.to_string_base(base)); }), ("num", &mut |((x, base), _, _)| { no_out!(x.to_str_radix(u32::wrapping_from(base))); }), ("rug", &mut |(_, (x, base), _)| { no_out!(x.to_string_radix(i32::wrapping_from(base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_string_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_string_base(u64)", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{}", BaseFmtWrapper::new(&x, base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_to_string_base_upper_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_string_base_upper(u64)", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base_upper(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{:#}", BaseFmtWrapper::new(&x, base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_base_fmt_wrapper_fmt_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usize}}\", BaseFmtWrapper::new(Integer, u64))", BenchmarkType::Single, integer_unsigned_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:0width$}", BaseFmtWrapper::new(&x, base), width = width )); })], ); } #[allow(unused_must_use)] fn benchmark_integer_base_fmt_wrapper_fmt_upper_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:#0usize}}\", BaseFmtWrapper::new(Integer, u64))", BenchmarkType::Single, integer_unsigned_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:#0width$}", BaseFmtWrapper::new(&x, base), width = width )); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/conversion/to_twos_complement_limbs.rs ================================================ // Copyright © 2026 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::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_vec_gen, unsigned_vec_gen_var_2}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::conversion::to_twos_complement_limbs::{ limbs_maybe_sign_extend_non_negative_in_place, limbs_twos_complement, limbs_twos_complement_and_maybe_sign_extend_negative_in_place, limbs_twos_complement_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_1_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_gen, integer_unsigned_pair_gen_var_2}; use malachite_nz::test_util::integer::conversion::to_twos_complement_limbs::{ limbs_twos_complement_in_place_alt_1, limbs_twos_complement_in_place_alt_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_twos_complement); register_demo!(runner, demo_limbs_maybe_sign_extend_non_negative_in_place); register_demo!(runner, demo_limbs_twos_complement_in_place); register_demo!( runner, demo_limbs_twos_complement_and_maybe_sign_extend_negative_in_place ); register_demo!(runner, demo_integer_to_twos_complement_limbs_asc); register_demo!(runner, demo_integer_to_twos_complement_limbs_desc); register_demo!(runner, demo_integer_into_twos_complement_limbs_asc); register_demo!(runner, demo_integer_into_twos_complement_limbs_desc); register_demo!(runner, demo_integer_twos_complement_limbs); register_demo!(runner, demo_integer_twos_complement_limbs_rev); register_demo!(runner, demo_integer_twos_complement_limbs_get_limb); register_demo!(runner, demo_integer_twos_complement_limb_count); register_bench!(runner, benchmark_limbs_twos_complement); register_bench!( runner, benchmark_limbs_maybe_sign_extend_non_negative_in_place ); register_bench!(runner, benchmark_limbs_twos_complement_in_place_algorithms); register_bench!( runner, benchmark_limbs_twos_complement_and_maybe_sign_extend_negative_in_place ); register_bench!( runner, benchmark_integer_to_twos_complement_limbs_asc_evaluation_strategy ); register_bench!( runner, benchmark_integer_to_twos_complement_limbs_desc_evaluation_strategy ); register_bench!( runner, benchmark_integer_twos_complement_limbs_get_limb_algorithms ); register_bench!(runner, benchmark_integer_twos_complement_limb_count); } fn demo_limbs_twos_complement(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_2().get(gm, config).take(limit) { println!( "limbs_twos_complement({:?}) = {:?}", xs, limbs_twos_complement(&xs) ); } } fn demo_limbs_maybe_sign_extend_non_negative_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { let mut mut_xs = xs.clone(); limbs_maybe_sign_extend_non_negative_in_place(&mut mut_xs); println!( "xs := {xs:?}; limbs_maybe_sign_extend_non_negative_in_place(&mut xs); xs = {mut_xs:?}", ); } } fn demo_limbs_twos_complement_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { let mut mut_xs = xs.clone(); let carry = limbs_twos_complement_in_place(&mut mut_xs); println!( "xs := {xs:?}; limbs_twos_complement_in_place(&mut xs) = {carry}; xs = {mut_xs:?}", ); } } fn demo_limbs_twos_complement_and_maybe_sign_extend_negative_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for xs in unsigned_vec_gen_var_2().get(gm, config).take(limit) { let mut mut_xs = xs.clone(); limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut mut_xs); println!( "xs := {xs:?}; limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut xs); \ xs = {mut_xs:?}", ); } } fn demo_integer_to_twos_complement_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "to_twos_complement_limbs_asc({}) = {:?}", n, n.to_twos_complement_limbs_asc() ); } } fn demo_integer_to_twos_complement_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "to_twos_complement_limbs_desc({}) = {:?}", n, n.to_twos_complement_limbs_desc() ); } } fn demo_integer_into_twos_complement_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "into_twos_complement_limbs_asc({}) = {:?}", n, n.clone().into_twos_complement_limbs_asc() ); } } fn demo_integer_into_twos_complement_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "into_twos_complement_limbs_desc({}) = {:?}", n, n.clone().into_twos_complement_limbs_desc() ); } } fn demo_integer_twos_complement_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "twos_complement_limbs({}) = {:?}", n, n.twos_complement_limbs().collect_vec() ); } } fn demo_integer_twos_complement_limbs_rev(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "twos_complement_limbs({}).rev() = {:?}", n, n.twos_complement_limbs().rev().collect_vec() ); } } fn demo_integer_twos_complement_limbs_get_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (n, i) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "twos_complement_limbs({}).get_limb({}) = {:?}", n, i, n.twos_complement_limbs().get_limb(i) ); } } fn demo_integer_twos_complement_limb_count(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!( "twos_complement_limb_count({}) = {}", n, n.twos_complement_limb_count() ); } } fn benchmark_limbs_twos_complement(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_twos_complement(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_2().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_twos_complement(&xs)))], ); } fn benchmark_limbs_maybe_sign_extend_non_negative_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_maybe_sign_extend_non_negative_in_place(&mut [Limb])", BenchmarkType::Single, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref mut xs| { limbs_maybe_sign_extend_non_negative_in_place(xs); })], ); } fn benchmark_limbs_twos_complement_in_place_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_twos_complement_in_place(&mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_gen_var_2().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref mut xs| { no_out!(limbs_twos_complement_in_place(xs)); }), ("integrated", &mut |ref mut xs| { no_out!(limbs_twos_complement_in_place_alt_1(xs)); }), ("sub 1 and not", &mut |ref mut xs| { no_out!(limbs_twos_complement_in_place_alt_2(xs)); }), ], ); } fn benchmark_limbs_twos_complement_and_maybe_sign_extend_negative_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut [Limb])", BenchmarkType::Single, unsigned_vec_gen_var_2().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref mut xs| { limbs_twos_complement_and_maybe_sign_extend_negative_in_place(xs); })], ); } fn benchmark_integer_to_twos_complement_limbs_asc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_twos_complement_limbs_asc()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Integer.to_twos_complement_limbs_asc()", &mut |n| { no_out!(n.to_twos_complement_limbs_asc()); }), ("Integer.into_twos_complement_limbs_asc()", &mut |n| { no_out!(n.into_twos_complement_limbs_asc()); }), ("Integer.twos_complement_limbs().collect_vec()", &mut |n| { no_out!(n.twos_complement_limbs().collect_vec()); }), ], ); } fn benchmark_integer_to_twos_complement_limbs_desc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_twos_complement_limbs_desc()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Integer.to_twos_complement_limbs_desc()", &mut |n| { no_out!(n.to_twos_complement_limbs_desc()); }), ("Integer.into_twos_complement_limbs_desc()", &mut |n| { no_out!(n.into_twos_complement_limbs_desc()); }), ( "Integer.twos_complement_limbs().rev().collect_vec()", &mut |n| no_out!(n.twos_complement_limbs().collect_vec()), ), ], ); } fn benchmark_integer_twos_complement_limbs_get_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.twos_complement_limbs().get_limb()", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("n"), &mut [ ( "Integer.twos_complement_limbs().get_limb(u)", &mut |(n, u)| no_out!(n.twos_complement_limbs().get_limb(u)), ), ( "Integer.into_twos_complement_limbs_asc()[u]", &mut |(n, u)| { let u = usize::exact_from(u); let non_negative = n >= 0; let limbs = n.into_twos_complement_limbs_asc(); if u >= limbs.len() { if non_negative { 0 } else { Limb::MAX } } else { limbs[u] }; }, ), ], ); } fn benchmark_integer_twos_complement_limb_count( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.twos_complement_limb_count()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |n| { no_out!(n.twos_complement_limb_count()); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/and.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_8, unsigned_vec_pair_gen_var_9, unsigned_vec_triple_gen_var_33, unsigned_vec_triple_gen_var_34, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::and::{ limbs_and_neg_neg, limbs_and_neg_neg_to_out, limbs_and_pos_neg, limbs_and_pos_neg_in_place_left, limbs_and_pos_neg_to_out, limbs_neg_and_limb_neg, limbs_neg_and_limb_neg_to_out, limbs_pos_and_limb_neg, limbs_pos_and_limb_neg_in_place, limbs_pos_and_limb_neg_to_out, limbs_slice_and_neg_neg_in_place_either, limbs_slice_and_neg_neg_in_place_left, limbs_slice_and_pos_neg_in_place_right, limbs_slice_neg_and_limb_neg_in_place, limbs_vec_and_neg_neg_in_place_either, limbs_vec_and_neg_neg_in_place_left, limbs_vec_and_pos_neg_in_place_right, limbs_vec_neg_and_limb_neg_in_place, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_rm}; use malachite_nz::test_util::integer::logic::and::{integer_and_alt_1, integer_and_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_pos_and_limb_neg); register_demo!(runner, demo_limbs_pos_and_limb_neg_to_out); register_demo!(runner, demo_limbs_pos_and_limb_neg_in_place); register_demo!(runner, demo_limbs_neg_and_limb_neg); register_demo!(runner, demo_limbs_neg_and_limb_neg_to_out); register_demo!(runner, demo_limbs_slice_neg_and_limb_neg_in_place); register_demo!(runner, demo_limbs_vec_neg_and_limb_neg_in_place); register_demo!(runner, demo_limbs_and_pos_neg); register_demo!(runner, demo_limbs_and_pos_neg_to_out); register_demo!(runner, demo_limbs_and_pos_neg_in_place_left); register_demo!(runner, demo_limbs_slice_and_pos_neg_in_place_right); register_demo!(runner, demo_limbs_vec_and_pos_neg_in_place_right); register_demo!(runner, demo_limbs_and_neg_neg); register_demo!(runner, demo_limbs_and_neg_neg_to_out); register_demo!(runner, demo_limbs_slice_and_neg_neg_in_place_left); register_demo!(runner, demo_limbs_vec_and_neg_neg_in_place_left); register_demo!(runner, demo_limbs_slice_and_neg_neg_in_place_either); register_demo!(runner, demo_limbs_vec_and_neg_neg_in_place_either); register_demo!(runner, demo_integer_and_assign); register_demo!(runner, demo_integer_and_assign_ref); register_demo!(runner, demo_integer_and); register_demo!(runner, demo_integer_and_val_ref); register_demo!(runner, demo_integer_and_ref_val); register_demo!(runner, demo_integer_and_ref_ref); register_bench!(runner, benchmark_limbs_pos_and_limb_neg); register_bench!(runner, benchmark_limbs_pos_and_limb_neg_to_out); register_bench!(runner, benchmark_limbs_pos_and_limb_neg_in_place); register_bench!(runner, benchmark_limbs_neg_and_limb_neg); register_bench!(runner, benchmark_limbs_neg_and_limb_neg_to_out); register_bench!(runner, benchmark_limbs_slice_neg_and_limb_neg_in_place); register_bench!(runner, benchmark_limbs_vec_neg_and_limb_neg_in_place); register_bench!(runner, benchmark_limbs_and_pos_neg); register_bench!(runner, benchmark_limbs_and_pos_neg_to_out); register_bench!(runner, benchmark_limbs_and_pos_neg_in_place_left); register_bench!(runner, benchmark_limbs_slice_and_pos_neg_in_place_right); register_bench!(runner, benchmark_limbs_vec_and_pos_neg_in_place_right); register_bench!(runner, benchmark_limbs_and_neg_neg); register_bench!(runner, benchmark_limbs_and_neg_neg_to_out); register_bench!(runner, benchmark_limbs_slice_and_neg_neg_in_place_left); register_bench!(runner, benchmark_limbs_vec_and_neg_neg_in_place_left); register_bench!(runner, benchmark_limbs_slice_and_neg_neg_in_place_either); register_bench!(runner, benchmark_limbs_vec_and_neg_neg_in_place_either); register_bench!(runner, benchmark_integer_and_assign_library_comparison); register_bench!(runner, benchmark_integer_and_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_and_library_comparison); register_bench!(runner, benchmark_integer_and_algorithms); register_bench!(runner, benchmark_integer_and_evaluation_strategy); } fn demo_limbs_pos_and_limb_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_pos_and_limb_neg({:?}, {}) = {:?}", xs, y, limbs_pos_and_limb_neg(&xs, y) ); } } fn demo_limbs_pos_and_limb_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_pos_and_limb_neg_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_pos_and_limb_neg_to_out(&mut out, {xs:?}, {y}); out = {out:?}", ); } } fn demo_limbs_pos_and_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_pos_and_limb_neg_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_pos_and_limb_neg_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_neg_and_limb_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_neg_and_limb_neg({:?}, {}) = {:?}", xs, y, limbs_neg_and_limb_neg(&xs, y) ); } } fn demo_limbs_neg_and_limb_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_neg_and_limb_neg_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; limbs_neg_and_limb_neg_to_out(&mut out, {xs:?}, {y}) = {carry}; \ out = {out:?}", ); } } fn demo_limbs_slice_neg_and_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_neg_and_limb_neg_in_place(&mut xs, y); println!( "xs := {xs_old:?}; \ limbs_slice_neg_and_limb_neg_in_place(&mut xs, {y}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_neg_and_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_neg_and_limb_neg_in_place(&mut xs, y); println!( "xs := {xs_old:?}; limbs_vec_neg_and_limb_neg_in_place(&mut xs, {y}); xs = {xs:?}", ); } } fn demo_limbs_and_pos_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_and_pos_neg({:?}, {:?}) = {:?}", xs, ys, limbs_and_pos_neg(&xs, &ys) ); } } fn demo_limbs_and_pos_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_33().get(gm, config).take(limit) { let out_old = out.clone(); limbs_and_pos_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; limbs_and_pos_neg_to_out(&mut out, {xs:?}, {ys:?}); \ out = {out:?}", ); } } fn demo_limbs_and_pos_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_and_pos_neg_in_place_left(&mut xs, &ys); println!("xs := {xs_old:?}; limbs_and_pos_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}"); } } fn demo_limbs_slice_and_pos_neg_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let ys_old = ys.clone(); limbs_vec_and_pos_neg_in_place_right(&xs, &mut ys); println!( "ys := {xs:?}; limbs_vec_and_pos_neg_in_place_right({ys_old:?}, &mut ys); ys = {ys:?}", ); } } fn demo_limbs_vec_and_pos_neg_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let ys_old = ys.clone(); limbs_slice_and_pos_neg_in_place_right(&xs, &mut ys); println!( "ys := {xs:?}; \ limbs_slice_and_pos_neg_in_place_right({ys_old:?}, &mut ys); ys = {ys:?}", ); } } fn demo_limbs_and_neg_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_and_neg_neg({:?}, {:?}) = {:?}", xs, ys, limbs_and_neg_neg(&xs, &ys) ); } } fn demo_limbs_and_neg_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_34().get(gm, config).take(limit) { let out_old = out.clone(); let b = limbs_and_neg_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_and_neg_neg_to_out(&mut out, {xs:?}, {ys:?}) = {b}; out = {out:?}", ); } } fn demo_limbs_slice_and_neg_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_9().get(gm, config).take(limit) { let xs_old = xs.clone(); let b = limbs_slice_and_neg_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_and_neg_neg_in_place_left(&mut xs, {ys:?}) = {b}; xs = {xs:?}", ); } } fn demo_limbs_vec_and_neg_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_and_neg_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_vec_and_neg_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_slice_and_neg_neg_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let p = limbs_slice_and_neg_neg_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_slice_and_neg_neg_in_place_either(&mut xs, &mut ys) = \ {p:?}; xs = {xs:?}; ys = {ys:?}", ); } } fn demo_limbs_vec_and_neg_neg_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let b = limbs_vec_and_neg_neg_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_vec_and_neg_neg_in_place_either(&mut xs, &mut ys) = \ {b}; xs = {xs:?}; ys = {ys:?}", ); } } fn demo_integer_and_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x &= y.clone(); println!("x := {x_old}; x &= {y}; x = {x}"); } } fn demo_integer_and_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x &= &y; println!("x := {x_old}; x &= &{y}; x = {x}"); } } fn demo_integer_and(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} & {} = {}", x_old, y_old, x & y); } } fn demo_integer_and_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} & &{} = {}", x_old, y, x & &y); } } fn demo_integer_and_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} & {} = {}", x, y_old, &x & y); } } fn demo_integer_and_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} & &{} = {}", x, y, &x & &y); } } fn benchmark_limbs_pos_and_limb_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_and_limb_neg(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_pos_and_limb_neg(&xs, y)); })], ); } fn benchmark_limbs_pos_and_limb_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_and_limb_neg_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { limbs_pos_and_limb_neg_to_out(&mut out, &xs, y); })], ); } fn benchmark_limbs_pos_and_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_and_limb_neg_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_pos_and_limb_neg_in_place(&mut xs, y); })], ); } fn benchmark_limbs_neg_and_limb_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_and_limb_neg(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(limbs, limb)| { no_out!(limbs_neg_and_limb_neg(&limbs, limb)); })], ); } fn benchmark_limbs_neg_and_limb_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_and_limb_neg_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_neg_and_limb_neg_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_slice_neg_and_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_neg_and_limb_neg_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_slice_neg_and_limb_neg_in_place(&mut xs, y)); })], ); } fn benchmark_limbs_vec_neg_and_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_neg_and_limb_neg_in_place(&Vec[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_vec_neg_and_limb_neg_in_place(&mut xs, y); })], ); } fn benchmark_limbs_and_pos_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_and_pos_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_and_pos_neg(xs, ys)); })], ); } fn benchmark_limbs_and_pos_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_and_pos_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_33().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut out, ref xs, ref ys)| { limbs_and_pos_neg_to_out(out, xs, ys); })], ); } fn benchmark_limbs_and_pos_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_and_pos_neg_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { limbs_and_pos_neg_in_place_left(xs, ys); })], ); } fn benchmark_limbs_slice_and_pos_neg_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_and_pos_neg_in_place_right(&[Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref mut ys)| { limbs_slice_and_pos_neg_in_place_right(xs, ys); })], ); } fn benchmark_limbs_vec_and_pos_neg_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_and_pos_neg_in_place_right(&[Limb], &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref mut ys)| { limbs_vec_and_pos_neg_in_place_right(xs, ys); })], ); } fn benchmark_limbs_and_neg_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_and_neg_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_and_neg_neg(xs, ys)); })], ); } fn benchmark_limbs_and_neg_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_and_neg_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_34().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut out, ref xs, ref ys)| { no_out!(limbs_and_neg_neg_to_out(out, xs, ys)); })], ); } fn benchmark_limbs_slice_and_neg_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_and_neg_neg_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_9().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { no_out!(limbs_slice_and_neg_neg_in_place_left(xs, ys)); })], ); } fn benchmark_limbs_vec_and_neg_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_and_neg_neg_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { no_out!(limbs_vec_and_neg_neg_in_place_left(xs, ys)); })], ); } fn benchmark_limbs_slice_and_neg_neg_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_and_neg_neg_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys)| { no_out!(limbs_slice_and_neg_neg_in_place_either(xs, ys)); })], ); } fn benchmark_limbs_vec_and_neg_neg_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_and_neg_neg_in_place_either(&mut Vec, &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys)| { no_out!(limbs_vec_and_neg_neg_in_place_either(xs, ys)); })], ); } fn benchmark_integer_and_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer &= Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x &= y), ("rug", &mut |((mut x, y), _)| x &= y)], ); } fn benchmark_integer_and_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer &= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer &= Integer", &mut |(mut x, y)| no_out!(x &= y)), ("Integer &= &Integer", &mut |(mut x, y)| no_out!(x &= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_and_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer &= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x & y)), ("rug", &mut |((x, y), _)| no_out!(x & y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_and_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer & Integer", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x & y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(integer_and_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(integer_and_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_and_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer & Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer & Integer", &mut |(x, y)| no_out!(x & y)), ("Integer & &Integer", &mut |(x, y)| no_out!(x & &y)), ("&Integer & Integer", &mut |(x, y)| no_out!(&x & y)), ("&Integer & &Integer", &mut |(x, y)| no_out!(&x & &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_triple_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::generators::{ integer_unsigned_bool_triple_gen_var_1, integer_unsigned_bool_triple_gen_var_1_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_assign_bit); register_bench!(runner, benchmark_integer_assign_bit_library_comparison); } fn demo_integer_assign_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index, bit) in integer_unsigned_bool_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); n.assign_bit(index, bit); println!("x := {n_old}; x.assign_bit({index}, {bit}); x = {n}"); } } fn benchmark_integer_assign_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.assign_bit(u64, bool)", BenchmarkType::LibraryComparison, integer_unsigned_bool_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, (mut n, index, bit))| { n.assign_bit(index, bit); }), ("rug", &mut |((mut n, index, bit), _)| { no_out!(n.set_bit(u32::exact_from(index), bit)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::quadruple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::large_type_gen_var_4; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_block_access::limbs_neg_assign_bits; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::integer_unsigned_unsigned_natural_quadruple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_neg_assign_bits); register_demo!(runner, demo_integer_assign_bits); register_bench!(runner, benchmark_limbs_neg_assign_bits); register_bench!(runner, benchmark_integer_assign_bits_algorithms); } fn demo_limbs_neg_assign_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, start, end, bits) in large_type_gen_var_4().get(gm, config).take(limit) { let old_xs = xs.clone(); limbs_neg_assign_bits(&mut xs, start, end, &bits); println!( "xs := {old_xs:?}; \ limbs_neg_assign_bits(&mut xs, {start}, {end}, &{bits:?}); limbs = {xs:?}", ); } } fn demo_integer_assign_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, start, end, bits) in integer_unsigned_unsigned_natural_quadruple_gen_var_1() .get(gm, config) .take(limit) { let old_n = n.clone(); n.assign_bits(start, end, &bits); println!("n := {old_n}; n.assign_bits({start}, {end}, &{bits}); n = {n}"); } } fn benchmark_limbs_neg_assign_bits(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_neg_assign_bits(&mut Vec, u64, u64, &[Limb])", BenchmarkType::Single, large_type_gen_var_4().get(gm, config), gm.name(), limit, file_name, &quadruple_3_bucketer("end"), &mut [("limbs_neg_assign_bits", &mut |( ref mut limbs, start, end, ref bits, )| { limbs_neg_assign_bits(limbs, start, end, bits); })], ); } fn benchmark_integer_assign_bits_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.assign_bits(u64, u64, &Natural)", BenchmarkType::Algorithms, integer_unsigned_unsigned_natural_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_3_bucketer("end"), &mut [ ("default", &mut |(mut n, start, end, bits)| { n.assign_bits(start, end, &bits); }), ("naive", &mut |(mut n, start, end, bits)| { assign_bits_naive::(&mut n, start, end, &bits); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/bits.rs ================================================ // Copyright © 2026 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::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_gen, integer_unsigned_pair_gen_var_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_bits); register_demo!(runner, demo_integer_bits_rev); register_demo!(runner, demo_integer_bits_index); register_bench!(runner, benchmark_integer_bits_get_algorithms); } fn demo_integer_bits(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("bits({}) = {:?}", n, n.bits().collect_vec()); } } fn demo_integer_bits_rev(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("bits({}).rev() = {:?}", n, n.bits().rev().collect_vec()); } } fn demo_integer_bits_index(gm: GenMode, config: &GenConfig, limit: usize) { for (n, i) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!("bits({})[{}] = {:?}", n, i, n.bits()[i]); } } #[allow(clippy::unnecessary_operation)] fn benchmark_integer_bits_get_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.bits()[u64]", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("Integer.bits()[u]", &mut |(n, u)| no_out!(n.bits()[u])), ("Integer.to_bits_asc()[u]", &mut |(n, u)| { let bits = n.to_bits_asc(); let u = usize::exact_from(u); if u >= bits.len() { n < 0 } else { bits[u] }; }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/checked_count_ones.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::checked_count_ones::{ integer_checked_count_ones_alt_1, integer_checked_count_ones_alt_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_checked_count_ones); register_bench!(runner, benchmark_integer_checked_count_ones_algorithms); } fn demo_integer_checked_count_ones(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("checked_count_ones({}) = {:?}", n, n.checked_count_ones()); } } fn benchmark_integer_checked_count_ones_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.count_ones()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.checked_count_ones())), ("using bits explicitly", &mut |n| { no_out!(integer_checked_count_ones_alt_1(&n)); }), ("using limbs explicitly", &mut |n| { no_out!(integer_checked_count_ones_alt_2(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/checked_count_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_4; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::checked_count_zeros::limbs_count_zeros_neg; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::checked_count_zeros::{ integer_checked_count_zeros_alt_1, integer_checked_count_zeros_alt_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_count_zeros_neg); register_demo!(runner, demo_integer_checked_count_zeros); register_bench!(runner, benchmark_limbs_count_zeros_neg); register_bench!(runner, benchmark_integer_checked_count_zeros_algorithms); } fn demo_limbs_count_zeros_neg(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_4().get(gm, config).take(limit) { println!( "limbs_count_zeros_neg({:?}) = {}", xs, limbs_count_zeros_neg(&xs) ); } } fn demo_integer_checked_count_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("checked_count_zeros({}) = {:?}", n, n.checked_count_zeros()); } } fn benchmark_limbs_count_zeros_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_count_zeros_neg(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_4().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_count_zeros_neg(&xs)))], ); } fn benchmark_integer_checked_count_zeros_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.count_zeros()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.checked_count_zeros())), ("using bits explicitly", &mut |n| { no_out!(integer_checked_count_zeros_alt_1(&n)); }), ("using limbs explicitly", &mut |n| { no_out!(integer_checked_count_zeros_alt_2(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/checked_hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::CheckedHammingDistance; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_max_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_8, unsigned_vec_unsigned_pair_gen_var_19, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::checked_hamming_distance::{ limbs_hamming_distance_limb_neg, limbs_hamming_distance_neg, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_rm}; use malachite_nz::test_util::integer::logic::checked_hamming_distance::rug_checked_hamming_distance; use malachite_nz::test_util::integer::logic::checked_hamming_distance::{ integer_checked_hamming_distance_alt_1, integer_checked_hamming_distance_alt_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_hamming_distance_limb_neg); register_demo!(runner, demo_limbs_hamming_distance_neg); register_demo!(runner, demo_integer_checked_hamming_distance); register_bench!(runner, benchmark_limbs_hamming_distance_limb_neg); register_bench!(runner, benchmark_limbs_hamming_distance_neg); register_bench!( runner, benchmark_integer_checked_hamming_distance_library_comparison ); register_bench!( runner, benchmark_integer_checked_hamming_distance_algorithms ); } fn demo_limbs_hamming_distance_limb_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_19() .get(gm, config) .take(limit) { println!( "limbs_hamming_distance_limb_neg({:?}, {}) = {}", xs, y, limbs_hamming_distance_limb_neg(&xs, y) ); } } fn demo_limbs_hamming_distance_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_hamming_distance_neg({:?}, {:?}) = {}", xs, ys, limbs_hamming_distance_neg(&xs, &ys) ); } } fn demo_integer_checked_hamming_distance(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!( "checked_hamming_distance({}, {}) = {:?}", x, y, x.checked_hamming_distance(&y) ); } } fn benchmark_limbs_hamming_distance_limb_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_hamming_distance_limb_neg(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_19().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_hamming_distance_limb_neg(&xs, y)); })], ); } fn benchmark_limbs_hamming_distance_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_hamming_distance_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_hamming_distance_neg(xs, ys)); })], ); } fn benchmark_integer_checked_hamming_distance_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_hamming_distance(&Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.checked_hamming_distance(&y)); }), ("rug", &mut |((x, y), _)| { no_out!(rug_checked_hamming_distance(&x, &y)); }), ], ); } fn benchmark_integer_checked_hamming_distance_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.checked_hamming_distance(&Integer)", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(n, other)| { no_out!(n.checked_hamming_distance(&other)); }), ("using bits explicitly", &mut |(n, other)| { no_out!(integer_checked_hamming_distance_alt_1(&n, &other)); }), ("using limbs explicitly", &mut |(n, other)| { no_out!(integer_checked_hamming_distance_alt_2(&n, &other)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_access::{ limbs_slice_clear_bit_neg, limbs_vec_clear_bit_neg, }; use malachite_nz::test_util::bench::bucketers::pair_integer_bit_u64_max_bucketer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use malachite_nz::test_util::generators::unsigned_vec_unsigned_pair_gen_var_21; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_slice_clear_bit_neg); register_demo!(runner, demo_limbs_vec_clear_bit_neg); register_demo!(runner, demo_integer_clear_bit); register_bench!(runner, benchmark_limbs_slice_clear_bit_neg); register_bench!(runner, benchmark_limbs_vec_clear_bit_neg); register_bench!(runner, benchmark_integer_clear_bit); } fn demo_limbs_slice_clear_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_21() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_slice_clear_bit_neg(&mut xs, index); println!("xs := {xs_old:?}; limbs_slice_clear_bit_neg(&mut xs, {index}); xs = {xs:?}"); } } fn demo_limbs_vec_clear_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { let old_xs = xs.clone(); limbs_vec_clear_bit_neg(&mut xs, index); println!("xs := {old_xs:?}; limbs_vec_clear_bit_neg(&mut xs, {index}); xs = {xs:?}"); } } fn demo_integer_clear_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.clear_bit(index); println!("x := {n_old}; x.clear_bit({index}); x = {n}"); } } fn benchmark_limbs_slice_clear_bit_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_clear_bit_neg(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_21().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_slice_clear_bit_neg(&mut xs, index)); })], ); } fn benchmark_limbs_vec_clear_bit_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_clear_bit_neg(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_vec_clear_bit_neg(&mut xs, index)); })], ); } fn benchmark_integer_clear_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.clear_bit(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_integer_bit_u64_max_bucketer("x", "index"), &mut [("Malachite", &mut |(mut n, index)| n.clear_bit(index))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_pair_integer_bit_u64_max_bucketer; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_flip_bit); register_bench!(runner, benchmark_integer_flip_bit_library_comparison); } fn demo_integer_flip_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.flip_bit(index); println!("x := {n_old}; x.flip_bit({index}); x = {n}"); } } fn benchmark_integer_flip_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.flip_bit(u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_bit_u64_max_bucketer("x", "index"), &mut [ ("Malachite", &mut |(_, (mut n, index))| n.flip_bit(index)), ("rug", &mut |((mut n, index), _)| { no_out!(n.toggle_bit(u32::exact_from(index))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/from_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitConvertible; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::bool_vec_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_desc_alt, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::integer::logic::from_bits::{ from_bits_asc_naive, from_bits_desc_naive, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_from_bits_asc); register_demo!(runner, demo_integer_from_bits_desc); register_bench!(runner, benchmark_integer_from_bits_asc_algorithms); register_bench!(runner, benchmark_integer_from_bits_desc_algorithms); } fn demo_integer_from_bits_asc(gm: GenMode, config: &GenConfig, limit: usize) { for bits in bool_vec_gen().get(gm, config).take(limit) { println!( "from_bits_asc({:?}) = {:?}", bits, Integer::from_bits_asc(bits.iter().copied()) ); } } fn demo_integer_from_bits_desc(gm: GenMode, config: &GenConfig, limit: usize) { for bits in bool_vec_gen().get(gm, config).take(limit) { println!( "from_bits_desc({:?}) = {:?}", bits, Integer::from_bits_desc(bits.iter().copied()) ); } } fn benchmark_integer_from_bits_asc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_bits_asc>(I)", BenchmarkType::Algorithms, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |bits| { no_out!(Integer::from_bits_asc(bits.into_iter())); }), ("alt", &mut |bits| { no_out!(from_bits_asc_alt::(bits.into_iter())); }), ("naive", &mut |bits| { no_out!(from_bits_asc_naive(bits.into_iter())); }), ], ); } fn benchmark_integer_from_bits_desc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::from_bits_desc>(I)", BenchmarkType::Algorithms, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |bits| { no_out!(Integer::from_bits_desc(bits.into_iter())); }), ("alt", &mut |bits| { no_out!(from_bits_desc_alt::(bits.into_iter())); }), ("naive", &mut |bits| { no_out!(from_bits_desc_naive(bits.into_iter())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::{pair_2_bucketer, pair_2_pair_2_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_18; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_access::limbs_get_bit_neg; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_2_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_get_bit_neg); register_demo!(runner, demo_integer_get_bit); register_bench!(runner, benchmark_limbs_get_bit_neg); register_bench!(runner, benchmark_integer_get_bit_library_comparison); } fn demo_limbs_get_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, index) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_get_bit_neg({:?}, {}) = {}", xs, index, limbs_get_bit_neg(&xs, index) ); } } fn demo_integer_get_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, index) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!("get_bit({}, {}) = {}", n, index, n.get_bit(index)); } } fn benchmark_limbs_get_bit_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_get_bit_neg(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(xs, index)| { no_out!(limbs_get_bit_neg(&xs, index)); })], ); } fn benchmark_integer_get_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.get_bit(u64)", BenchmarkType::LibraryComparison, integer_unsigned_pair_gen_var_2_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, (n, index))| { no_out!(n.get_bit(index)); }), ("rug", &mut |((n, index), _)| { no_out!(n.get_bit(u32::exact_from(index))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::{triple_1_vec_len_bucketer, triple_3_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_20, unsigned_vec_unsigned_unsigned_triple_gen_var_4, }; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_block_access::{ limbs_neg_limb_get_bits, limbs_slice_neg_get_bits, limbs_vec_neg_get_bits, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::triple_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_unsigned_unsigned_triple_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_neg_limb_get_bits); register_demo!(runner, demo_limbs_slice_neg_get_bits); register_demo!(runner, demo_limbs_vec_neg_get_bits); register_demo!(runner, demo_integer_get_bits); register_bench!(runner, benchmark_limbs_neg_limb_get_bits); register_bench!(runner, benchmark_limbs_neg_get_bits_evaluation_strategy); register_bench!(runner, benchmark_integer_get_bits_evaluation_strategy); register_bench!(runner, benchmark_integer_get_bits_algorithms); } fn demo_limbs_neg_limb_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (x, start, end) in unsigned_triple_gen_var_20().get(gm, config).take(limit) { println!( "limbs_neg_limb_get_bits({}, {}, {}) = {:?}", x, start, end, limbs_neg_limb_get_bits(x, start, end) ); } } fn demo_limbs_slice_neg_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, start, end) in unsigned_vec_unsigned_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "limbs_slice_neg_get_bits({:?}, {}, {}) = {:?}", xs, start, end, limbs_slice_neg_get_bits(&xs, start, end) ); } } fn demo_limbs_vec_neg_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, start, end) in unsigned_vec_unsigned_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let old_xs = xs.clone(); println!( "limbs_vec_neg_get_bits({:?}, {}, {}) = {:?}", old_xs, start, end, limbs_vec_neg_get_bits(xs, start, end) ); } } fn demo_integer_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, start, end) in integer_unsigned_unsigned_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "({}).get_bits({}, {}) = {}", n, start, end, n.get_bits(start, end) ); } } fn benchmark_limbs_neg_limb_get_bits( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_limb_get_bits(Limb, u64, u64)", BenchmarkType::Single, unsigned_triple_gen_var_20().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("end"), &mut [("limbs_neg_limb_get_bits", &mut |(x, start, end)| { no_out!(limbs_neg_limb_get_bits(x, start, end)); })], ); } fn benchmark_limbs_neg_get_bits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_get_bits(&[Limb], u64, u64)", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("limbs_slice_neg_get_bits", &mut |(xs, start, end)| { no_out!(limbs_slice_neg_get_bits(&xs, start, end)); }), ("limbs_vec_neg_get_bits", &mut |(xs, start, end)| { no_out!(limbs_vec_neg_get_bits(xs, start, end)); }), ], ); } fn benchmark_integer_get_bits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.get_bits(u64, u64)", BenchmarkType::EvaluationStrategy, integer_unsigned_unsigned_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [ ("get_bits", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("get_bits_owned", &mut |(n, start, end)| { no_out!(n.get_bits_owned(start, end)); }), ], ); } fn benchmark_integer_get_bits_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.get_bits(u64, u64)", BenchmarkType::Algorithms, integer_unsigned_unsigned_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("naive", &mut |(n, start, end)| { no_out!(get_bits_naive::(&n, start, end)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitScan; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_scan::limbs_index_of_next_false_bit_neg; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use malachite_nz::test_util::integer::logic::index_of_next_false_bit::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_index_of_next_false_bit_neg); register_demo!(runner, demo_integer_index_of_next_false_bit); register_bench!(runner, benchmark_limbs_index_of_next_false_bit_neg); register_bench!(runner, benchmark_integer_index_of_next_false_bit_algorithms); } fn demo_limbs_index_of_next_false_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, u) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_index_of_next_false_bit_neg({:?}, {}) = {:?}", xs, u, limbs_index_of_next_false_bit_neg(&xs, u) ); } } fn demo_integer_index_of_next_false_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "index_of_next_false_bit({}, {}) = {:?}", n, u, n.index_of_next_false_bit(u) ); } } fn benchmark_limbs_index_of_next_false_bit_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_index_of_next_false_bit_neg(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, u)| { no_out!(limbs_index_of_next_false_bit_neg(&xs, u)); })], ); } #[allow(clippy::needless_borrow)] fn benchmark_integer_index_of_next_false_bit_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.index_of_next_false_bit(u64)", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(ref n, u)| { no_out!(n.index_of_next_false_bit(u)); }), ("using bits explicitly", &mut |(ref n, u)| { no_out!(integer_index_of_next_false_bit_alt(&n, u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitScan; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_scan::limbs_index_of_next_true_bit_neg; use malachite_nz::test_util::bench::bucketers::pair_1_integer_bit_bucketer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use malachite_nz::test_util::integer::logic::index_of_next_true_bit::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_index_of_next_true_bit_neg); register_demo!(runner, demo_integer_index_of_next_true_bit); register_bench!(runner, benchmark_limbs_index_of_next_true_bit_neg); register_bench!(runner, benchmark_integer_index_of_next_true_bit_algorithms); } fn demo_limbs_index_of_next_true_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, u) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_index_of_next_true_bit_neg({:?}, {}) = {:?}", xs, u, limbs_index_of_next_true_bit_neg(&xs, u) ); } } fn demo_integer_index_of_next_true_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "index_of_next_true_bit({}, {}) = {:?}", n, u, n.index_of_next_true_bit(u) ); } } fn benchmark_limbs_index_of_next_true_bit_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_index_of_next_true_bit_neg(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, u)| { no_out!(limbs_index_of_next_true_bit_neg(&xs, u)); })], ); } fn benchmark_integer_index_of_next_true_bit_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.index_of_next_true_bit(u64)", BenchmarkType::Algorithms, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_integer_bit_bucketer("x"), &mut [ ("default", &mut |(ref n, u)| { no_out!(n.index_of_next_true_bit(u)); }), ("using bits explicitly", &mut |(ref n, u)| { no_out!(integer_index_of_next_true_bit_alt(n, u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::LowMask; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_low_mask); register_bench!(runner, benchmark_integer_low_mask); } fn demo_integer_low_mask(gm: GenMode, config: &GenConfig, limit: usize) { for bits in unsigned_gen_var_5().get(gm, config).take(limit) { println!("Integer::low_mask({}) = {}", bits, Integer::low_mask(bits)); } } fn benchmark_integer_low_mask(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.low_mask(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |bits| no_out!(Integer::low_mask(bits)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { and::register(runner); assign_bit::register(runner); assign_bits::register(runner); bits::register(runner); checked_count_ones::register(runner); checked_count_zeros::register(runner); checked_hamming_distance::register(runner); clear_bit::register(runner); flip_bit::register(runner); from_bits::register(runner); get_bit::register(runner); get_bits::register(runner); index_of_next_false_bit::register(runner); index_of_next_true_bit::register(runner); low_mask::register(runner); not::register(runner); or::register(runner); set_bit::register(runner); significant_bits::register(runner); to_bits::register(runner); trailing_zeros::register(runner); xor::register(runner); } mod and; mod assign_bit; mod assign_bits; mod bits; mod checked_count_ones; mod checked_count_zeros; mod checked_hamming_distance; mod clear_bit; mod flip_bit; mod from_bits; mod get_bit; mod get_bits; mod index_of_next_false_bit; mod index_of_next_true_bit; mod low_mask; mod not; mod or; mod set_bit; mod significant_bits; mod to_bits; mod trailing_zeros; mod xor; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/not.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::NotAssign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ integer_bit_bucketer, pair_2_integer_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_gen, integer_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_not_assign); register_demo!(runner, demo_integer_not); register_demo!(runner, demo_integer_not_ref); register_bench!(runner, benchmark_integer_not_assign); register_bench!(runner, benchmark_integer_not_library_comparison); register_bench!(runner, benchmark_integer_not_evaluation_strategy); } fn demo_integer_not_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in integer_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.not_assign(); println!("n := {n_old}; n.not_assign(); n = {n}"); } } fn demo_integer_not(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("!({}) = {}", n.clone(), !n); } } fn demo_integer_not_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("!(&{}) = {}", n, !&n); } } fn benchmark_integer_not_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.not_assign()", BenchmarkType::Single, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("Malachite", &mut |mut n| n.not_assign())], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_not_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.not()", BenchmarkType::LibraryComparison, integer_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_integer_bit_bucketer("n"), &mut [("Malachite", &mut |(_, n)| no_out!(!n)), ("rug", &mut |(n, _)| no_out!(!n))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_not_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.not()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [("!Integer", &mut |n| no_out!(!n)), ("!&Integer", &mut |n| no_out!(!&n))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/or.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_2_vec_len_bucketer, triple_3_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_8, unsigned_vec_triple_gen_var_33, unsigned_vec_triple_gen_var_35, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_pair_gen_var_19, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::or::{ limbs_neg_or_limb, limbs_neg_or_limb_in_place, limbs_neg_or_limb_to_out, limbs_neg_or_neg_limb, limbs_or_neg_neg, limbs_or_neg_neg_in_place_either, limbs_or_neg_neg_to_out, limbs_or_pos_neg, limbs_or_pos_neg_in_place_right, limbs_or_pos_neg_to_out, limbs_pos_or_neg_limb, limbs_slice_or_neg_neg_in_place_left, limbs_slice_or_pos_neg_in_place_left, limbs_vec_or_neg_neg_in_place_left, limbs_vec_or_pos_neg_in_place_left, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_rm}; use malachite_nz::test_util::integer::logic::or::{integer_or_alt_1, integer_or_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_neg_or_limb); register_demo!(runner, demo_limbs_neg_or_limb_to_out); register_demo!(runner, demo_limbs_neg_or_limb_in_place); register_demo!(runner, demo_limbs_pos_or_neg_limb); register_demo!(runner, demo_limbs_neg_or_neg_limb); register_demo!(runner, demo_limbs_or_pos_neg); register_demo!(runner, demo_limbs_or_pos_neg_to_out); register_demo!(runner, demo_limbs_slice_or_pos_neg_in_place_left); register_demo!(runner, demo_limbs_vec_or_pos_neg_in_place_left); register_demo!(runner, demo_limbs_or_pos_neg_in_place_right); register_demo!(runner, demo_limbs_or_neg_neg); register_demo!(runner, demo_limbs_or_neg_neg_to_out); register_demo!(runner, demo_limbs_slice_or_neg_neg_in_place_left); register_demo!(runner, demo_limbs_vec_or_neg_neg_in_place_left); register_demo!(runner, demo_limbs_or_neg_neg_in_place_either); register_demo!(runner, demo_integer_or_assign); register_demo!(runner, demo_integer_or_assign_ref); register_demo!(runner, demo_integer_or); register_demo!(runner, demo_integer_or_val_ref); register_demo!(runner, demo_integer_or_ref_val); register_demo!(runner, demo_integer_or_ref_ref); register_bench!(runner, benchmark_limbs_neg_or_limb); register_bench!(runner, benchmark_limbs_neg_or_limb_to_out); register_bench!(runner, benchmark_limbs_neg_or_limb_in_place); register_bench!(runner, benchmark_limbs_pos_or_neg_limb); register_bench!(runner, benchmark_limbs_neg_or_neg_limb); register_bench!(runner, benchmark_limbs_or_pos_neg); register_bench!(runner, benchmark_limbs_or_pos_neg_to_out); register_bench!(runner, benchmark_limbs_slice_or_pos_neg_in_place_left); register_bench!(runner, benchmark_limbs_vec_or_pos_neg_in_place_left); register_bench!(runner, benchmark_limbs_or_pos_neg_in_place_right); register_bench!(runner, benchmark_limbs_or_neg_neg); register_bench!(runner, benchmark_limbs_or_neg_neg_to_out); register_bench!(runner, benchmark_limbs_slice_or_neg_neg_in_place_left); register_bench!(runner, benchmark_limbs_vec_or_neg_neg_in_place_left); register_bench!(runner, benchmark_limbs_or_neg_neg_in_place_either); register_bench!(runner, benchmark_integer_or_assign_library_comparison); register_bench!(runner, benchmark_integer_or_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_or_library_comparison); register_bench!(runner, benchmark_integer_or_algorithms); register_bench!(runner, benchmark_integer_or_evaluation_strategy); } fn demo_limbs_neg_or_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_neg_or_limb({:?}, {}) = {:?}", xs, y, limbs_neg_or_limb(&xs, y) ); } } fn demo_limbs_neg_or_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_neg_or_limb_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; limbs_neg_or_limb_to_out(&mut out, {xs:?}, {y}); out = {out:?}", ); } } fn demo_limbs_neg_or_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_neg_or_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_neg_or_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_pos_or_neg_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_19() .get(gm, config) .take(limit) { println!( "limbs_pos_or_neg_limb({:?}, {}) = {}", xs, y, limbs_pos_or_neg_limb(&xs, y) ); } } fn demo_limbs_neg_or_neg_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_19() .get(gm, config) .take(limit) { println!( "limbs_neg_or_neg_limb({:?}, {}) = {}", xs, y, limbs_neg_or_neg_limb(&xs, y) ); } } fn demo_limbs_or_pos_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_or_pos_neg({:?}, {:?}) = {:?}", xs, ys, limbs_or_pos_neg(&xs, &ys) ); } } fn demo_limbs_or_pos_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, ys, xs) in unsigned_vec_triple_gen_var_33().get(gm, config).take(limit) { let out_old = out.clone(); limbs_or_pos_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; limbs_or_pos_neg_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_slice_or_pos_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let out = limbs_slice_or_pos_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_or_pos_neg_in_place_left(&mut xs, {ys:?}) = {out}; xs = {xs:?}", ); } } fn demo_limbs_vec_or_pos_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_or_pos_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_vec_or_pos_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_or_pos_neg_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let ys_old = ys.clone(); limbs_or_pos_neg_in_place_right(&xs, &mut ys); println!( "ys := {xs:?}; \ limbs_or_pos_neg_in_place_right({ys_old:?}, &mut ys); ys = {ys:?}" ); } } fn demo_limbs_or_neg_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_or_neg_neg({:?}, {:?}) = {:?}", xs, ys, limbs_or_neg_neg(&xs, &ys) ); } } fn demo_limbs_or_neg_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_35().get(gm, config).take(limit) { let out_old = out.clone(); limbs_or_neg_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; limbs_or_neg_neg_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_slice_or_neg_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_slice_or_neg_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_slice_or_neg_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_vec_or_neg_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_or_neg_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_vec_or_neg_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_or_neg_neg_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let b = limbs_or_neg_neg_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_or_neg_neg_in_place_either(&mut xs, &mut ys) = {b}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_integer_or_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x |= y.clone(); println!("x := {x_old}; x |= {y}; x = {x}"); } } fn demo_integer_or_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x |= &y; println!("x := {x_old}; x |= &{y}; x = {x}"); } } fn demo_integer_or(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} | {} = {}", x_old, y_old, x | y); } } fn demo_integer_or_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} | &{} = {}", x_old, y, x | &y); } } fn demo_integer_or_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} | {} = {}", x, y_old, &x | y); } } fn demo_integer_or_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} | &{} = {}", x, y, &x | &y); } } fn benchmark_limbs_neg_or_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_neg_or_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_neg_or_limb(&xs, y)); })], ); } fn benchmark_limbs_neg_or_limb_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_or_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { limbs_neg_or_limb_to_out(&mut out, &xs, y); })], ); } fn benchmark_limbs_neg_or_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_or_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_neg_or_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_pos_or_neg_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_pos_or_neg_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_19().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_pos_or_neg_limb(&xs, y)); })], ); } fn benchmark_limbs_neg_or_neg_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_neg_or_neg_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_19().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_neg_or_neg_limb(&xs, y)); })], ); } fn benchmark_limbs_or_pos_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_pos_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_or_pos_neg(xs, ys)); })], ); } fn benchmark_limbs_or_pos_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_pos_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_33().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, ys, xs)| { limbs_or_pos_neg_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_slice_or_pos_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_or_pos_neg_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { no_out!(limbs_slice_or_pos_neg_in_place_left(xs, ys)); })], ); } fn benchmark_limbs_vec_or_pos_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_or_pos_neg_in_place_left(&Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { limbs_vec_or_pos_neg_in_place_left(xs, ys); })], ); } fn benchmark_limbs_or_pos_neg_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_pos_neg_in_place_right(&[Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref mut ys)| { limbs_or_pos_neg_in_place_right(xs, ys); })], ); } fn benchmark_limbs_or_neg_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_neg_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_or_neg_neg(xs, ys)); })], ); } fn benchmark_limbs_or_neg_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_neg_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_35().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut out, ref xs, ref ys)| { limbs_or_neg_neg_to_out(out, xs, ys); })], ); } fn benchmark_limbs_slice_or_neg_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_or_neg_neg_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { limbs_slice_or_neg_neg_in_place_left(xs, ys); })], ); } fn benchmark_limbs_vec_or_neg_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_or_neg_neg_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { limbs_vec_or_neg_neg_in_place_left(xs, ys); })], ); } fn benchmark_limbs_or_neg_neg_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_neg_neg_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys)| { no_out!(limbs_or_neg_neg_in_place_either(xs, ys)); })], ); } fn benchmark_integer_or_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer |= Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x |= y), ("rug", &mut |((mut x, y), _)| x |= y)], ); } fn benchmark_integer_or_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer |= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer |= Integer", &mut |(mut x, y)| no_out!(x |= y)), ("Integer |= &Integer", &mut |(mut x, y)| no_out!(x |= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_or_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer | Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x | y)), ("rug", &mut |((x, y), _)| no_out!(x | y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_or_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer | Integer", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x | y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(integer_or_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(integer_or_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_or_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer | Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("x", "y"), &mut [ ("Integer | Integer", &mut |(x, y)| no_out!(x | y)), ("Integer | &Integer", &mut |(x, y)| no_out!(x | &y)), ("&Integer | Integer", &mut |(x, y)| no_out!(&x | y)), ("&Integer | &Integer", &mut |(x, y)| no_out!(&x | &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_access::limbs_set_bit_neg; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_set_bit_neg); register_demo!(runner, demo_integer_set_bit); register_bench!(runner, benchmark_limbs_set_bit_neg); register_bench!(runner, benchmark_integer_set_bit); } fn demo_limbs_set_bit_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { let old_xs = xs.clone(); limbs_set_bit_neg(&mut xs, index); println!("xs := {old_xs:?}; limbs_set_bit_neg(&mut xs, {index}); xs = {xs:?}"); } } fn demo_integer_set_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in integer_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { let n_old = n.clone(); n.set_bit(index); println!("x := {n_old}; x.set_bit({index}); x = {n}"); } } fn benchmark_limbs_set_bit_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_set_bit_neg(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_set_bit_neg(&mut xs, index)); })], ); } fn benchmark_integer_set_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Integer.set_bit(u64)", BenchmarkType::Single, integer_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.set_bit(index))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_integer_bit_bucketer; use malachite_nz::test_util::generators::{integer_gen, integer_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_significant_bits); register_bench!( runner, benchmark_integer_significant_bits_library_comparison ); } fn demo_integer_significant_bits(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("significant_bits({}) = {}", n, n.significant_bits()); } } fn benchmark_integer_significant_bits_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.significant_bits()", BenchmarkType::LibraryComparison, integer_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_integer_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.significant_bits())), ("num", &mut |(n, _, _)| no_out!(n.bits())), ("rug", &mut |(_, n, _)| no_out!(n.significant_bits())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/to_bits.rs ================================================ // Copyright © 2026 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::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{bool_vec_gen, bool_vec_gen_var_5}; use malachite_base::test_util::num::logic::bit_convertible::{to_bits_asc_alt, to_bits_desc_alt}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::bit_convertible::{ bits_slice_to_twos_complement_bits_negative, bits_to_twos_complement_bits_non_negative, bits_vec_to_twos_complement_bits_negative, }; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::to_bits::{to_bits_asc_naive, to_bits_desc_naive}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_bits_to_twos_complement_bits_non_negative); register_demo!(runner, demo_bits_slice_to_twos_complement_bits_negative); register_demo!(runner, demo_bits_vec_to_twos_complement_bits_negative); register_demo!(runner, demo_integer_to_bits_asc); register_demo!(runner, demo_integer_to_bits_desc); register_bench!(runner, benchmark_bits_to_twos_complement_bits_non_negative); register_bench!( runner, benchmark_bits_slice_to_twos_complement_bits_negative ); register_bench!(runner, benchmark_bits_vec_to_twos_complement_bits_negative); register_bench!(runner, benchmark_integer_to_bits_asc_evaluation_strategy); register_bench!(runner, benchmark_integer_to_bits_asc_algorithms); register_bench!(runner, benchmark_integer_to_bits_desc_evaluation_strategy); register_bench!(runner, benchmark_integer_to_bits_desc_algorithms); } fn demo_bits_to_twos_complement_bits_non_negative(gm: GenMode, config: &GenConfig, limit: usize) { for mut bits in bool_vec_gen().get(gm, config).take(limit) { let old_bits = bits.clone(); bits_to_twos_complement_bits_non_negative(&mut bits); println!( "bits := {old_bits:?}; \ bits_to_twos_complement_bits_non_negative(&mut bits); bits = {bits:?}", ); } } fn demo_bits_slice_to_twos_complement_bits_negative(gm: GenMode, config: &GenConfig, limit: usize) { for mut bits in bool_vec_gen().get(gm, config).take(limit) { let old_bits = bits.clone(); let carry = bits_slice_to_twos_complement_bits_negative(&mut bits); println!( "bits := {old_bits:?}; \ bits_slice_to_twos_complement_bits_negative(&mut bits) = {carry}; bits = {bits:?}", ); } } fn demo_bits_vec_to_twos_complement_bits_negative(gm: GenMode, config: &GenConfig, limit: usize) { for mut bits in bool_vec_gen_var_5().get(gm, config).take(limit) { let old_bits = bits.clone(); bits_vec_to_twos_complement_bits_negative(&mut bits); println!( "bits := {old_bits:?}; \ bits_vec_to_twos_complement_bits_negative(&mut bits); bits = {bits:?}", ); } } fn demo_integer_to_bits_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("to_bits_asc({}) = {:?}", n, n.to_bits_asc()); } } fn demo_integer_to_bits_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("to_bits_desc({}) = {:?}", n, n.to_bits_desc()); } } fn benchmark_bits_to_twos_complement_bits_non_negative( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "bits_to_twos_complement_bits_non_negative(&mut [bool])", BenchmarkType::Single, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut bits| { bits_to_twos_complement_bits_non_negative(&mut bits); })], ); } fn benchmark_bits_slice_to_twos_complement_bits_negative( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "bits_slice_to_twos_complement_bits_negative(&mut [bool])", BenchmarkType::Single, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut bits| { no_out!(bits_slice_to_twos_complement_bits_negative(&mut bits)); })], ); } fn benchmark_bits_vec_to_twos_complement_bits_negative( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "bits_vec_to_twos_complement_bits_negative(&mut [bool])", BenchmarkType::Single, bool_vec_gen_var_5().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref mut bits| { bits_vec_to_twos_complement_bits_negative(bits); })], ); } fn benchmark_integer_to_bits_asc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_bits_asc()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Integer.to_bits_asc()", &mut |n| no_out!(n.to_bits_asc())), ("Integer.bits().collect_vec()", &mut |n| { no_out!(n.bits().collect_vec()); }), ], ); } fn benchmark_integer_to_bits_asc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_bits_asc()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.to_bits_asc())), ("alt", &mut |n| no_out!(to_bits_asc_alt(&n))), ("naive", &mut |n| no_out!(to_bits_asc_naive(&n))), ], ); } fn benchmark_integer_to_bits_desc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_bits_desc()", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Integer.to_bits_desc()", &mut |n| no_out!(n.to_bits_desc())), ("Integer.bits().rev().collect_vec()", &mut |n| { no_out!(n.bits().rev().collect_vec()); }), ], ); } fn benchmark_integer_to_bits_desc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.to_bits_desc()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.to_bits_desc())), ("alt", &mut |n| no_out!(to_bits_desc_alt(&n))), ("naive", &mut |n| no_out!(to_bits_desc_naive(&n))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::trailing_zeros::integer_trailing_zeros_alt; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_trailing_zeros); register_bench!(runner, benchmark_integer_trailing_zeros_algorithms); } fn demo_integer_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("trailing_zeros({}) = {:?}", n, n.trailing_zeros()); } } fn benchmark_integer_trailing_zeros_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.trailing_zeros()", BenchmarkType::Algorithms, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.trailing_zeros())), ("using bits explicitly", &mut |n| { no_out!(integer_trailing_zeros_alt(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/logic/xor.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_max_len_bucketer, triple_2_3_vec_max_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_8, unsigned_vec_triple_gen_var_34, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::logic::xor::{ limbs_neg_xor_limb, limbs_neg_xor_limb_neg, limbs_neg_xor_limb_neg_in_place, limbs_neg_xor_limb_neg_to_out, limbs_neg_xor_limb_to_out, limbs_pos_xor_limb_neg, limbs_pos_xor_limb_neg_to_out, limbs_slice_neg_xor_limb_in_place, limbs_slice_pos_xor_limb_neg_in_place, limbs_vec_neg_xor_limb_in_place, limbs_vec_pos_xor_limb_neg_in_place, limbs_xor_neg_neg, limbs_xor_neg_neg_in_place_either, limbs_xor_neg_neg_in_place_left, limbs_xor_neg_neg_to_out, limbs_xor_pos_neg, limbs_xor_pos_neg_in_place_either, limbs_xor_pos_neg_in_place_left, limbs_xor_pos_neg_in_place_right, limbs_xor_pos_neg_to_out, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_integer_max_bit_bucketer, pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{integer_pair_gen, integer_pair_gen_rm}; use malachite_nz::test_util::integer::logic::xor::{integer_xor_alt_1, integer_xor_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_neg_xor_limb); register_demo!(runner, demo_limbs_neg_xor_limb_to_out); register_demo!(runner, demo_limbs_slice_neg_xor_limb_in_place); register_demo!(runner, demo_limbs_vec_neg_xor_limb_in_place); register_demo!(runner, demo_limbs_pos_xor_limb_neg); register_demo!(runner, demo_limbs_pos_xor_limb_neg_to_out); register_demo!(runner, demo_limbs_slice_pos_xor_limb_neg_in_place); register_demo!(runner, demo_limbs_vec_pos_xor_limb_neg_in_place); register_demo!(runner, demo_limbs_neg_xor_limb_neg); register_demo!(runner, demo_limbs_neg_xor_limb_neg_to_out); register_demo!(runner, demo_limbs_neg_xor_limb_neg_in_place); register_demo!(runner, demo_limbs_xor_pos_neg); register_demo!(runner, demo_limbs_xor_pos_neg_to_out); register_demo!(runner, demo_limbs_xor_pos_neg_in_place_left); register_demo!(runner, demo_limbs_xor_pos_neg_in_place_right); register_demo!(runner, demo_limbs_xor_pos_neg_in_place_either); register_demo!(runner, demo_limbs_xor_neg_neg); register_demo!(runner, demo_limbs_xor_neg_neg_to_out); register_demo!(runner, demo_limbs_xor_neg_neg_in_place_left); register_demo!(runner, demo_limbs_xor_neg_neg_in_place_either); register_demo!(runner, demo_integer_xor_assign); register_demo!(runner, demo_integer_xor_assign_ref); register_demo!(runner, demo_integer_xor); register_demo!(runner, demo_integer_xor_val_ref); register_demo!(runner, demo_integer_xor_ref_val); register_demo!(runner, demo_integer_xor_ref_ref); register_bench!(runner, benchmark_limbs_neg_xor_limb); register_bench!(runner, benchmark_limbs_neg_xor_limb_to_out); register_bench!(runner, benchmark_limbs_slice_neg_xor_limb_in_place); register_bench!(runner, benchmark_limbs_vec_neg_xor_limb_in_place); register_bench!(runner, benchmark_limbs_pos_xor_limb_neg); register_bench!(runner, benchmark_limbs_pos_xor_limb_neg_to_out); register_bench!(runner, benchmark_limbs_slice_pos_xor_limb_neg_in_place); register_bench!(runner, benchmark_limbs_vec_pos_xor_limb_neg_in_place); register_bench!(runner, benchmark_limbs_neg_xor_limb_neg); register_bench!(runner, benchmark_limbs_neg_xor_limb_neg_to_out); register_bench!(runner, benchmark_limbs_neg_xor_limb_neg_in_place); register_bench!(runner, benchmark_limbs_xor_pos_neg); register_bench!(runner, benchmark_limbs_xor_pos_neg_to_out); register_bench!(runner, benchmark_limbs_xor_pos_neg_in_place_left); register_bench!(runner, benchmark_limbs_xor_pos_neg_in_place_right); register_bench!(runner, benchmark_limbs_xor_pos_neg_in_place_either); register_bench!(runner, benchmark_limbs_xor_neg_neg); register_bench!(runner, benchmark_limbs_xor_neg_neg_to_out); register_bench!(runner, benchmark_limbs_xor_neg_neg_in_place_left); register_bench!(runner, benchmark_limbs_xor_neg_neg_in_place_either); register_bench!(runner, benchmark_integer_xor_assign_library_comparison); register_bench!(runner, benchmark_integer_xor_assign_evaluation_strategy); register_bench!(runner, benchmark_integer_xor_library_comparison); register_bench!(runner, benchmark_integer_xor_algorithms); register_bench!(runner, benchmark_integer_xor_evaluation_strategy); } fn demo_limbs_neg_xor_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_neg_xor_limb({:?}, {}) = {:?}", xs, y, limbs_neg_xor_limb(&xs, y) ); } } fn demo_limbs_neg_xor_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_neg_xor_limb_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_neg_xor_limb_to_out(&mut out, {xs:?}, {y}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_neg_xor_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_neg_xor_limb_in_place(&mut xs, y); println!( "xs := {xs_old:?}; \ limbs_slice_neg_xor_limb_in_place(&mut xs, {y}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_neg_xor_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_neg_xor_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_vec_neg_xor_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_pos_xor_limb_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_pos_xor_limb_neg({:?}, {}) = {:?}", xs, y, limbs_pos_xor_limb_neg(&xs, y) ); } } fn demo_limbs_pos_xor_limb_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_pos_xor_limb_neg_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_pos_xor_limb_neg_to_out(&mut out, {xs:?}, {y}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_pos_xor_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_pos_xor_limb_neg_in_place(&mut xs, y); println!( "xs := {xs_old:?}; \ limbs_slice_pos_xor_limb_neg_in_place(&mut xs, {y}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_pos_xor_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_pos_xor_limb_neg_in_place(&mut xs, y); println!( "xs := {xs_old:?}; limbs_vec_pos_xor_limb_neg_in_place(&mut xs, {y}); xs = {xs:?}", ); } } fn demo_limbs_neg_xor_limb_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_neg_xor_limb_neg({:?}, {}) = {:?}", xs, y, limbs_neg_xor_limb_neg(&xs, y) ); } } fn demo_limbs_neg_xor_limb_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_neg_xor_limb_neg_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_neg_xor_limb_neg_to_out(&mut out, {xs:?}, {y}) = out = {out:?}", ); } } fn demo_limbs_neg_xor_limb_neg_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_neg_xor_limb_neg_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_neg_xor_limb_neg_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_xor_pos_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_xor_pos_neg({:?}, {:?}) = {:?}", xs, ys, limbs_xor_pos_neg(&xs, &ys) ); } } fn demo_limbs_xor_pos_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_34().get(gm, config).take(limit) { let out_old = out.clone(); let carry = limbs_xor_pos_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_xor_pos_neg_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } fn demo_limbs_xor_pos_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_xor_pos_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_xor_pos_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}" ); } } fn demo_limbs_xor_pos_neg_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let ys_old = ys.clone(); limbs_xor_pos_neg_in_place_right(&xs, &mut ys); println!( "ys := {xs:?}; limbs_xor_pos_neg_in_place_right({ys_old:?}, &mut ys); ys = {ys:?}", ); } } fn demo_limbs_xor_pos_neg_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let b = limbs_xor_pos_neg_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_xor_pos_neg_in_place_either(&mut xs, &mut ys) = {b}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_limbs_xor_neg_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { println!( "limbs_xor_neg_neg({:?}, {:?}) = {:?}", xs, ys, limbs_xor_neg_neg(&xs, &ys) ); } } fn demo_limbs_xor_neg_neg_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_34().get(gm, config).take(limit) { let out_old = out.clone(); limbs_xor_neg_neg_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_xor_neg_neg_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_xor_neg_neg_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_xor_neg_neg_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_xor_neg_neg_in_place_left(&mut xs, {ys:?}); xs = {xs:?}" ); } } fn demo_limbs_xor_neg_neg_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_8().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let b = limbs_xor_neg_neg_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_xor_neg_neg_in_place_either(&mut xs, &mut ys) = {b}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_integer_xor_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x ^= y.clone(); println!("x := {x_old}; x ^= {y}; x = {x}"); } } fn demo_integer_xor_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x ^= &y; println!("x := {x_old}; x ^= &{y}; x = {x}"); } } fn demo_integer_xor(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} ^ {} = {}", x_old, y_old, x ^ y); } } fn demo_integer_xor_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} ^ &{} = {}", x_old, y, x ^ &y); } } fn demo_integer_xor_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} ^ {} = {}", x, y_old, &x ^ y); } } fn demo_integer_xor_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in integer_pair_gen().get(gm, config).take(limit) { println!("&{} ^ &{} = {}", x, y, &x ^ &y); } } fn benchmark_limbs_neg_xor_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_neg_xor_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_neg_xor_limb(&xs, y)); })], ); } fn benchmark_limbs_neg_xor_limb_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_xor_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_neg_xor_limb_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_slice_neg_xor_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_slice_xor_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_slice_neg_xor_limb_in_place(&mut xs, y)); })], ); } fn benchmark_limbs_vec_neg_xor_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_vec_xor_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_vec_neg_xor_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_pos_xor_limb_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_xor_limb_neg(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_pos_xor_limb_neg(&xs, y)); })], ); } fn benchmark_limbs_pos_xor_limb_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_pos_xor_limb_neg_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_pos_xor_limb_neg_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_slice_pos_xor_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_pos_xor_limb_neg_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_slice_pos_xor_limb_neg_in_place(&mut xs, y)); })], ); } fn benchmark_limbs_vec_pos_xor_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_pos_xor_limb_neg_in_place(&Vec[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_vec_pos_xor_limb_neg_in_place(&mut xs, y); })], ); } fn benchmark_limbs_neg_xor_limb_neg( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_xor_limb_neg(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_neg_xor_limb_neg(&xs, y)); })], ); } fn benchmark_limbs_neg_xor_limb_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_xor_limb_neg_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_neg_xor_limb_neg_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_neg_xor_limb_neg_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_xor_limb_neg_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_neg_xor_limb_neg_in_place(&mut xs, y); })], ); } fn benchmark_limbs_xor_pos_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_pos_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_xor_pos_neg(xs, ys)); })], ); } fn benchmark_limbs_xor_pos_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_pos_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_34().get(gm, config), gm.name(), limit, file_name, &triple_2_3_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut out, ref xs, ref ys)| { no_out!(limbs_xor_pos_neg_to_out(out, xs, ys)); })], ); } fn benchmark_limbs_xor_pos_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_pos_neg_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { no_out!(limbs_xor_pos_neg_in_place_left(xs, ys)); })], ); } fn benchmark_limbs_xor_pos_neg_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_pos_neg_in_place_right(&[Limb], &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref mut ys)| { no_out!(limbs_xor_pos_neg_in_place_right(xs, ys)); })], ); } fn benchmark_limbs_xor_pos_neg_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_pos_neg_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys)| { no_out!(limbs_xor_pos_neg_in_place_either(xs, ys)); })], ); } fn benchmark_limbs_xor_neg_neg(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_neg_neg(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref ys)| { no_out!(limbs_xor_neg_neg(xs, ys)); })], ); } fn benchmark_limbs_xor_neg_neg_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_neg_neg_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_34().get(gm, config), gm.name(), limit, file_name, &triple_2_3_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut out, ref xs, ref ys)| { limbs_xor_neg_neg_to_out(out, xs, ys); })], ); } fn benchmark_limbs_xor_neg_neg_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_neg_neg_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut xs, ref ys)| { no_out!(limbs_xor_neg_neg_in_place_left(xs, ys)); })], ); } fn benchmark_limbs_xor_neg_neg_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_neg_neg_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys)| { no_out!(limbs_xor_neg_neg_in_place_either(xs, ys)); })], ); } fn benchmark_integer_xor_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer ^= Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("xs", "ys"), &mut [("Malachite", &mut |(_, (mut x, y))| x ^= y), ("rug", &mut |((mut x, y), _)| x ^= y)], ); } fn benchmark_integer_xor_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer ^= Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("xs", "ys"), &mut [ ("Integer ^= Integer", &mut |(mut x, y)| no_out!(x ^= y)), ("Integer ^= &Integer", &mut |(mut x, y)| no_out!(x ^= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_xor_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer ^ Integer", BenchmarkType::LibraryComparison, integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_integer_max_bit_bucketer("xs", "ys"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x ^ y)), ("rug", &mut |((x, y), _)| no_out!(x ^ y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_xor_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer ^ Integer", BenchmarkType::Algorithms, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("xs", "ys"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x ^ y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(integer_xor_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(integer_xor_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_integer_xor_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer ^ Integer", BenchmarkType::EvaluationStrategy, integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("xs", "ys"), &mut [ ("Integer ^ Integer", &mut |(x, y)| no_out!(x ^ y)), ("Integer ^ &Integer", &mut |(x, y)| no_out!(x ^ &y)), ("&Integer ^ Integer", &mut |(x, y)| no_out!(&x ^ y)), ("&Integer ^ &Integer", &mut |(x, y)| no_out!(&x ^ &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/integer/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); basic::register(runner); comparison::register(runner); conversion::register(runner); logic::register(runner); } mod arithmetic; mod basic; mod comparison; mod conversion; mod logic; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; macro_rules! natural_signed_single_arg_demo_with_trait { ($name: ident, $f: ident, $gen: ident, $tr: ident) => { fn $name(gm: GenMode, config: &GenConfig, limit: usize) where Natural: $tr, { for x in $gen::().get(gm, config).take(limit) { println!( concat!("Natural::", stringify!($f), "({}) = {}"), x, Natural::$f(x) ); } } }; } macro_rules! natural_signed_single_arg_bench_with_trait { ($name: ident, $f: ident, $gen: ident, $tr: ident) => { fn $name(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) where Natural: $tr, { run_benchmark( &format!(concat!("Natural::", stringify!($f), "({})"), T::NAME), BenchmarkType::Single, $gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(Natural::$f(x)))], ); } }; } pub(crate) fn register(runner: &mut Runner) { integer::register(runner); natural::register(runner); } mod integer; mod natural; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AbsDiff, AbsDiffAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_abs_diff); register_demo!(runner, demo_natural_abs_diff_val_ref); register_demo!(runner, demo_natural_abs_diff_ref_val); register_demo!(runner, demo_natural_abs_diff_ref_ref); register_demo!(runner, demo_natural_abs_diff_assign); register_demo!(runner, demo_natural_abs_diff_assign_ref); register_bench!( runner, benchmark_natural_abs_diff_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_abs_diff_evaluation_strategy); } fn demo_natural_abs_diff(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("|{} - {}| = {:?}", x_old, y_old, x.abs_diff(y)); } } fn demo_natural_abs_diff_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("|{} - &{}| = {:?}", x_old, y, x.abs_diff(&y)); } } fn demo_natural_abs_diff_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("|&{} - {}| = {:?}", x, y_old, (&x).abs_diff(y)); } } fn demo_natural_abs_diff_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("|&{} - &{}| = {:?}", x, y, (&x).abs_diff(&y)); } } fn demo_natural_abs_diff_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.abs_diff_assign(y); println!("x := {x_old}; x.abs_diff_assign({y_old}); x = {x}"); } } fn demo_natural_abs_diff_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.abs_diff_assign(&y); println!("x := {x_old}; x.abs_diff_assign(&{y}); x = {x}"); } } fn benchmark_natural_abs_diff_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.abs_diff_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.abs_diff_assign(Natural)", &mut |(mut x, y)| { x.abs_diff_assign(y); }), ("Natural.abs_diff_assign(&Natural)", &mut |(mut x, y)| { x.abs_diff_assign(&y); }), ], ); } fn benchmark_natural_abs_diff_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.abs_diff(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.abs_diff(Natural)", &mut |(x, y)| { no_out!(x.abs_diff(y)); }), ("Natural.abs_diff(&Natural)", &mut |(x, y)| { no_out!(x.abs_diff(&y)); }), ("&Natural.abs_diff(Natural)", &mut |(x, y)| { no_out!((&x).abs_diff(y)); }), ("&Natural.abs_diff(&Natural)", &mut |(x, y)| { no_out!((&x).abs_diff(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_max_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_triple_gen_var_40, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::add::{ limbs_add, limbs_add_greater, limbs_add_greater_to_out, limbs_add_limb, limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_to_out, limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_in_place_either, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, limbs_vec_add_in_place_either, limbs_vec_add_in_place_left, limbs_vec_add_limb_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, triple_3_vec_natural_sum_bits_bucketer, vec_natural_sum_bits_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_rm, natural_vec_gen, natural_vec_gen_nrm, }; use malachite_nz::test_util::natural::arithmetic::add::natural_sum_alt; use num::BigUint; use std::iter::Sum; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_add_limb); register_demo!(runner, demo_limbs_add_limb_to_out); register_demo!(runner, demo_limbs_slice_add_limb_in_place); register_demo!(runner, demo_limbs_vec_add_limb_in_place); register_demo!(runner, demo_limbs_add_greater); register_demo!(runner, demo_limbs_add); register_demo!(runner, demo_limbs_add_same_length_to_out); register_demo!(runner, demo_limbs_add_greater_to_out); register_demo!(runner, demo_limbs_add_to_out); register_demo!(runner, demo_limbs_add_to_out_aliased); register_demo!(runner, demo_limbs_slice_add_same_length_in_place_left); register_demo!(runner, demo_limbs_slice_add_greater_in_place_left); register_demo!(runner, demo_limbs_vec_add_in_place_left); register_demo!(runner, demo_limbs_slice_add_in_place_either); register_demo!(runner, demo_limbs_vec_add_in_place_either); register_demo!(runner, demo_natural_add_assign); register_demo!(runner, demo_natural_add_assign_ref); register_demo!(runner, demo_natural_add); register_demo!(runner, demo_natural_add_val_ref); register_demo!(runner, demo_natural_add_ref_val); register_demo!(runner, demo_natural_add_ref_ref); register_demo!(runner, demo_natural_sum); register_demo!(runner, demo_natural_ref_sum); register_bench!(runner, benchmark_limbs_add_limb); register_bench!(runner, benchmark_limbs_add_limb_to_out); register_bench!(runner, benchmark_limbs_slice_add_limb_in_place); register_bench!(runner, benchmark_limbs_vec_add_limb_in_place); register_bench!(runner, benchmark_limbs_add_greater); register_bench!(runner, benchmark_limbs_add); register_bench!(runner, benchmark_limbs_add_same_length_to_out); register_bench!(runner, benchmark_limbs_add_greater_to_out); register_bench!(runner, benchmark_limbs_add_to_out); register_bench!(runner, benchmark_limbs_add_to_out_aliased); register_bench!(runner, benchmark_limbs_slice_add_same_length_in_place_left); register_bench!(runner, benchmark_limbs_slice_add_greater_in_place_left); register_bench!(runner, benchmark_limbs_vec_add_in_place_left); register_bench!(runner, benchmark_limbs_slice_add_in_place_either); register_bench!(runner, benchmark_limbs_vec_add_in_place_either); register_bench!(runner, benchmark_natural_add_assign_library_comparison); register_bench!(runner, benchmark_natural_add_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_add_library_comparison); register_bench!(runner, benchmark_natural_add_evaluation_strategy); register_bench!(runner, benchmark_natural_sum_algorithms); register_bench!(runner, benchmark_natural_sum_library_comparison); register_bench!(runner, benchmark_natural_sum_evaluation_strategy); } fn demo_limbs_add_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { println!( "limbs_add_limb({:?}, {}) = {:?}", xs, y, limbs_add_limb(&xs, y) ); } } fn demo_limbs_add_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_add_limb_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_add_limb_to_out(&mut out, {xs:?}, {y}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_add_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_add_limb_in_place(&mut xs, y); println!( "xs := {xs_old:?}; limbs_slice_add_limb_in_place(&mut xs, {y}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_add_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_add_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_vec_add_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_add_greater(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_1().get(gm, config).take(limit) { println!( "limbs_add_greater({:?}, {:?}) = {:?}", xs, ys, limbs_add_greater(&xs, &ys) ); } } fn demo_limbs_add(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { println!("limbs_add({:?}, {:?}) = {:?}", xs, ys, limbs_add(&xs, &ys)); } } fn demo_limbs_add_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_31().get(gm, config).take(limit) { let out_old = out.clone(); let carry = limbs_add_same_length_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_add_same_length_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } fn demo_limbs_add_greater_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_40().get(gm, config).take(limit) { let out_old = xs.clone(); let carry = limbs_add_greater_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_add_greater_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } fn demo_limbs_add_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_32().get(gm, config).take(limit) { let out_old = out.clone(); let carry = limbs_add_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_add_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } fn demo_limbs_add_to_out_aliased(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, xs_len) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_add_to_out_aliased(&mut xs, xs_len, &ys); println!( "xs := {xs_old:?}; \ limbs_add_to_out_aliased(&mut xs, {xs_len}, {ys:?}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_slice_add_same_length_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_add_same_length_in_place_left::(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_add_same_length_in_place_left(&mut xs, {ys:?}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_slice_add_greater_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_1().get(gm, config).take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_add_greater_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_add_greater_in_place_left(&mut xs, {ys:?}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_add_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_add_in_place_left(&mut xs, &ys); println!("xs := {xs_old:?}; limbs_vec_add_in_place_left(&mut xs, {ys:?}); xs = {xs:?}"); } } fn demo_limbs_slice_add_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let result = limbs_slice_add_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_slice_add_in_place_either(&mut xs, &mut ys) = {result:?}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_limbs_vec_add_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_vec_add_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_vec_add_in_place_either(&mut xs, &mut ys) = {right}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_natural_add_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_natural_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_natural_add_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_natural_add_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_natural_add_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_natural_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in natural_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs.clone(), Natural::sum(xs.into_iter())); } } fn demo_natural_ref_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in natural_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs, Natural::sum(xs.iter())); } } fn benchmark_limbs_add_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_add_limb(&xs, y)))], ); } fn benchmark_limbs_add_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_add_limb_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_slice_add_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_slice_add_limb_in_place(&mut xs, y)); })], ); } fn benchmark_limbs_vec_add_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_limb_in_place(&mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_vec_add_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_add_greater(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_greater(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_add_greater(&xs, &ys)); })], ); } fn benchmark_limbs_add(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_add(&xs, &ys)))], ); } fn benchmark_limbs_add_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_add_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { no_out!(limbs_add_same_length_to_out(&mut out, &xs, &ys)); })], ); } fn benchmark_limbs_add_greater_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_add_greater_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_40().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { no_out!(limbs_add_greater_to_out(&mut out, &xs, &ys)); })], ); } fn benchmark_limbs_add_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_32().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { no_out!(limbs_add_to_out(&mut out, &xs, &ys)); })], ); } fn benchmark_limbs_add_to_out_aliased( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_add_to_out_aliased(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ys"), &mut [("Malachite", &mut |(mut xs, ys, xs_len)| { no_out!(limbs_add_to_out_aliased(&mut xs, xs_len, &ys)); })], ); } fn benchmark_limbs_slice_add_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_same_length_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_slice_add_same_length_in_place_left::( &mut xs, &ys )); })], ); } fn benchmark_limbs_slice_add_greater_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_greater_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_slice_add_greater_in_place_left(&mut xs, &ys)); })], ); } fn benchmark_limbs_vec_add_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_vec_add_in_place_left(&mut xs, &ys)); })], ); } fn benchmark_limbs_slice_add_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { no_out!(limbs_slice_add_in_place_either(&mut xs, &mut ys)); })], ); } fn benchmark_limbs_vec_add_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_in_place_either(&mut Vec, &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { no_out!(limbs_vec_add_in_place_either(&mut xs, &mut ys)); })], ); } fn benchmark_natural_add_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural += Natural", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x += y), ("rug", &mut |((mut x, y), _)| x += y)], ); } fn benchmark_natural_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural += Natural", BenchmarkType::LibraryComparison, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural += Natural", &mut |(mut x, y)| no_out!(x += y)), ("Natural += &Natural", &mut |(mut x, y)| no_out!(x += &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_add_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural + Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x + y)), ("num", &mut |((x, y), _, _)| no_out!(x + y)), ("rug", &mut |(_, (x, y), _)| no_out!(x + y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural + Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural + Natural", &mut |(x, y)| no_out!(x + y)), ("Natural + &Natural", &mut |(x, y)| no_out!(x + &y)), ("&Natural + Natural", &mut |(x, y)| no_out!(&x + y)), ("&Natural + &Natural", &mut |(x, y)| no_out!(&x + &y)), ], ); } fn benchmark_natural_sum_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::sum(Iterator)", BenchmarkType::LibraryComparison, natural_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_natural_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Natural::sum(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigUint::sum(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Integer::sum(xs.iter())); }), ], ); } fn benchmark_natural_sum_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::sum(Iterator)", BenchmarkType::Algorithms, natural_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_natural_sum_bits_bucketer(), &mut [ ("default", &mut |xs| no_out!(Natural::sum(xs.into_iter()))), ("alt", &mut |xs| no_out!(natural_sum_alt(xs.into_iter()))), ], ); } fn benchmark_natural_sum_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::sum(Iterator)", BenchmarkType::EvaluationStrategy, natural_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_natural_sum_bits_bucketer(), &mut [ ("Natural::sum(Iterator)", &mut |xs| { no_out!(Natural::sum(xs.into_iter())); }), ("Natural::sum(Iterator)", &mut |xs| { no_out!(Natural::sum(xs.iter())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign}; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_vec_max_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_triple_gen_var_41, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::add_mul::{ limbs_add_mul, limbs_add_mul_in_place_left, limbs_add_mul_limb, limbs_slice_add_mul_limb_same_length_in_place_left, limbs_slice_add_mul_limb_same_length_in_place_right, limbs_vec_add_mul_limb_in_place_either, limbs_vec_add_mul_limb_in_place_left, limbs_vec_add_mul_limb_in_place_right, }; use malachite_nz::test_util::bench::bucketers::triple_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_add_mul_limb); register_demo!( runner, demo_limbs_slice_add_mul_limb_same_length_in_place_left ); register_demo!( runner, demo_limbs_slice_add_mul_limb_same_length_in_place_right ); register_demo!(runner, demo_limbs_vec_add_mul_limb_in_place_left); register_demo!(runner, demo_limbs_vec_add_mul_limb_in_place_right); register_demo!(runner, demo_limbs_vec_add_mul_limb_in_place_either); register_demo!(runner, demo_limbs_add_mul); register_demo!(runner, demo_limbs_add_mul_in_place_left); register_demo!(runner, demo_natural_add_mul_assign); register_demo!(runner, demo_natural_add_mul_assign_val_ref); register_demo!(runner, demo_natural_add_mul_assign_ref_val); register_demo!(runner, demo_natural_add_mul_assign_ref_ref); register_demo!(runner, demo_natural_add_mul); register_demo!(runner, demo_natural_add_mul_val_val_ref); register_demo!(runner, demo_natural_add_mul_val_ref_val); register_demo!(runner, demo_natural_add_mul_val_ref_ref); register_demo!(runner, demo_natural_add_mul_ref_ref_ref); register_bench!(runner, benchmark_limbs_add_mul_limb); register_bench!( runner, benchmark_limbs_slice_add_mul_limb_same_length_in_place_left ); register_bench!( runner, benchmark_limbs_slice_add_mul_limb_same_length_in_place_right ); register_bench!(runner, benchmark_limbs_vec_add_mul_limb_in_place_left); register_bench!(runner, benchmark_limbs_vec_add_mul_limb_in_place_right); register_bench!(runner, benchmark_limbs_vec_add_mul_limb_in_place_either); register_bench!(runner, benchmark_limbs_add_mul); register_bench!(runner, benchmark_limbs_add_mul_in_place_left); register_bench!(runner, benchmark_natural_add_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_add_mul_assign_algorithms); register_bench!(runner, benchmark_natural_add_mul_assign_val_ref_algorithms); register_bench!(runner, benchmark_natural_add_mul_assign_ref_val_algorithms); register_bench!(runner, benchmark_natural_add_mul_assign_ref_ref_algorithms); register_bench!(runner, benchmark_natural_add_mul_evaluation_stategy); register_bench!(runner, benchmark_natural_add_mul_algorithms); register_bench!(runner, benchmark_natural_add_mul_val_val_ref_algorithms); register_bench!(runner, benchmark_natural_add_mul_val_ref_val_algorithms); register_bench!(runner, benchmark_natural_add_mul_val_ref_ref_algorithms); register_bench!(runner, benchmark_natural_add_mul_ref_ref_ref_algorithms); } fn demo_limbs_add_mul_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { println!( "limbs_add_mul_limb({:?}, {:?}, {}) = {:?}", a, b, c, limbs_add_mul_limb(&a, &b, c), ); } } fn demo_limbs_slice_add_mul_limb_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut a, b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() .get(gm, config) .take(limit) { let a_old = a.clone(); let carry = limbs_slice_add_mul_limb_same_length_in_place_left(&mut a, &b, c); println!( "a := {a_old:?}; \ limbs_slice_add_mul_limb_same_length_in_place_left(&mut a, {b:?}, {c}) = {carry}; \ a = {a:?}", ); } } fn demo_limbs_slice_add_mul_limb_same_length_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, ) { for (a, mut b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() .get(gm, config) .take(limit) { let b_old = b.clone(); let carry = limbs_slice_add_mul_limb_same_length_in_place_right(&a, &mut b, c); println!( "b := {b_old:?}; \ limbs_slice_add_mul_limb_same_length_in_place_right({a:?}, &mut b, {c}) \ = {carry}; b = {b:?}", ); } } fn demo_limbs_vec_add_mul_limb_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let a_old = a.clone(); limbs_vec_add_mul_limb_in_place_left(&mut a, &b, c); println!( "a := {a_old:?}; limbs_vec_add_mul_limb_in_place_left(&mut a, {b:?}, {c}); a = {a:?}", ); } } fn demo_limbs_vec_add_mul_limb_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (a, mut b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let b_old = b.clone(); limbs_vec_add_mul_limb_in_place_right(&a, &mut b, c); println!( "b := {b_old:?}; limbs_vec_add_mul_limb_in_place_right({a:?}, &mut b, {c}); b = {b:?}", ); } } fn demo_limbs_vec_add_mul_limb_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, mut b, c) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { let a_old = a.clone(); let b_old = b.clone(); limbs_vec_add_mul_limb_in_place_either(&mut a, &mut b, c); println!( "a := {a_old:?}; \ b := {b_old:?}; limbs_vec_add_mul_limb_in_place_either(&mut a, &mut b, {c}); \ a = {a:?}; b = {b:?}", ); } } fn demo_limbs_add_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in unsigned_vec_triple_gen_var_41().get(gm, config).take(limit) { println!( "limbs_add_mul({:?}, {:?}, {:?}) = {:?}", a, b, c, limbs_add_mul(&a, &b, &c), ); } } fn demo_limbs_add_mul_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in unsigned_vec_triple_gen_var_41().get(gm, config).take(limit) { let a_old = a.clone(); limbs_add_mul_in_place_left(&mut a, &b, &c); println!("a := {a_old:?}; limbs_add_mul_in_place_left(&mut a, {b:?}, {c:?}); a = {a:?}"); } } fn demo_natural_add_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); let c_old = c.clone(); a.add_mul_assign(b, c); println!("a := {a_old}; x.add_mul_assign({b_old}, {c_old}); x = {a}"); } } fn demo_natural_add_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); a.add_mul_assign(b, &c); println!("a := {a_old}; x.add_mul_assign({b_old}, &{c}); x = {a}"); } } fn demo_natural_add_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let c_old = c.clone(); a.add_mul_assign(&b, c); println!("a := {a_old}; x.add_mul_assign(&{b}, {c_old}); x = {a}"); } } fn demo_natural_add_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); a.add_mul_assign(&b, &c); println!("a := {a_old}; x.add_mul_assign(&{b}, &{c}); x = {a}"); } } fn demo_natural_add_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); let c_old = c.clone(); println!( "{}.add_mul({}, {}) = {}", a_old, b_old, c_old, a.add_mul(b, c) ); } } fn demo_natural_add_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); println!( "{}.add_mul({}, &{}) = {}", a_old, b_old, c, a.add_mul(b, &c) ); } } fn demo_natural_add_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let c_old = c.clone(); println!( "{}.add_mul(&{}, {}) = {}", a_old, b, c_old, a.add_mul(&b, c) ); } } fn demo_natural_add_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); println!("{}.add_mul(&{}, &{}) = {}", a_old, b, c, a.add_mul(&b, &c)); } } fn demo_natural_add_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { println!( "(&{}).add_mul(&{}, &{}) = {}", a, b, c, (&a).add_mul(&b, &c) ); } } fn benchmark_limbs_add_mul_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_mul_limb(&[Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(a, b, c)| { no_out!(limbs_add_mul_limb(&a, &b, c)); })], ); } fn benchmark_limbs_slice_add_mul_limb_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_mul_limb_same_length_in_place_left(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(mut a, b, c)| { no_out!(limbs_slice_add_mul_limb_same_length_in_place_left( &mut a, &b, c )); })], ); } fn benchmark_limbs_slice_add_mul_limb_same_length_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_add_mul_limb_same_length_in_place_left(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(a, mut b, c)| { no_out!(limbs_slice_add_mul_limb_same_length_in_place_right( &a, &mut b, c )); })], ); } fn benchmark_limbs_vec_add_mul_limb_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_mul_limb_in_place_left(&mut Vec, &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(mut a, b, c)| { limbs_vec_add_mul_limb_in_place_left(&mut a, &b, c); })], ); } fn benchmark_limbs_vec_add_mul_limb_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_mul_limb_in_place_left(&mut Vec, &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(a, mut b, c)| { limbs_vec_add_mul_limb_in_place_right(&a, &mut b, c); })], ); } fn benchmark_limbs_vec_add_mul_limb_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_add_mul_limb_in_place_either(&mut Vec, &mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("a", "b"), &mut [("Malachite", &mut |(mut a, b, c)| { limbs_vec_add_mul_limb_in_place_left(&mut a, &b, c); })], ); } fn benchmark_limbs_add_mul(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_add_mul(&[Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_41().get(gm, config), gm.name(), limit, file_name, &triple_vec_max_len_bucketer("a", "b", "c"), &mut [("Malachite", &mut |(a, b, c)| { no_out!(limbs_add_mul(&a, &b, &c)); })], ); } fn benchmark_limbs_add_mul_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_add_mul_in_place_left(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_41().get(gm, config), gm.name(), limit, file_name, &triple_vec_max_len_bucketer("a", "b", "c"), &mut [("Malachite", &mut |(mut a, b, c)| { no_out!(limbs_add_mul_in_place_left(&mut a, &b, &c)); })], ); } fn benchmark_natural_add_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.add_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.add_mul_assign(b, c), ), ( "Natural.add_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.add_mul_assign(b, &c), ), ( "Natural.add_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.add_mul_assign(&b, c), ), ( "Natural.add_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.add_mul_assign(&b, &c), ), ], ); } fn benchmark_natural_add_mul_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.add_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.add_mul_assign(b, c), ), ("Natural += Natural * Natural", &mut |(mut a, b, c)| { a += b * c; }), ], ); } fn benchmark_natural_add_mul_assign_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul_assign(Natural, &Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.add_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.add_mul_assign(b, &c), ), ("Natural += Natural * &Natural", &mut |(mut a, b, c)| { a += b * &c; }), ], ); } fn benchmark_natural_add_mul_assign_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul_assign(&Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.add_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.add_mul_assign(&b, c), ), ("Natural += &Natural * Natural", &mut |(mut a, b, c)| { a += &b * c; }), ], ); } fn benchmark_natural_add_mul_assign_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul_assign(&Natural, &Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.add_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.add_mul_assign(&b, &c), ), ("Natural += &Natural * &Natural", &mut |(mut a, b, c)| { a += &b * &c; }), ], ); } fn benchmark_natural_add_mul_evaluation_stategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.add_mul(Natural, Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(b, c)); }), ("Natural.add_mul(Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(b, &c)); }), ("Natural.add_mul(&Natural, Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, c)); }), ("Natural.add_mul(&Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, &c)); }), ( "(&Natural).add_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).add_mul(&b, &c)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_add_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.add_mul(Natural, Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(b, c)); }), ("Natural + Natural * Natural", &mut |(a, b, c)| { no_out!(a + b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_add_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul(Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.add_mul(Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(b, &c)); }), ("Natural + Natural * &Natural", &mut |(a, b, c)| { no_out!(a + b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_add_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul(&Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.add_mul(&Natural, Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, c)); }), ("Natural + &Natural * Natural", &mut |(a, b, c)| { no_out!(a + &b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_add_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.add_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.add_mul(&Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.add_mul(&b, &c)); }), ("Natural + &Natural * &Natural", &mut |(a, b, c)| { no_out!(a + &b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_add_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).add_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "(&Natural).add_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).add_mul(&b, &c)), ), ("(&Natural) + &Natural * &Natural", &mut |(a, b, c)| { no_out!((&a) + &b * &c); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::BinomialCoefficient; use malachite_base::test_util::bench::bucketers::usize_convertible_pair_max_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_28; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::binomial_coefficient::*; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen_var_15, natural_pair_gen_var_15_rm, unsigned_pair_gen_var_45, unsigned_pair_gen_var_46, unsigned_pair_gen_var_47, unsigned_pair_gen_var_48, unsigned_pair_gen_var_49, }; use malachite_nz::test_util::natural::arithmetic::binomial_coefficient::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_binomial_coefficient_limb_limb_bdiv); register_demo!(runner, demo_limbs_binomial_coefficient_limb_limb_small_k); register_demo!(runner, demo_limbs_binomial_coefficient_limb_limb_basecase); register_demo!( runner, demo_limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer ); register_demo!( runner, demo_limbs_binomial_coefficient_limb_limb_goetgheluck ); register_demo!(runner, demo_binomial_coefficient_limb_limb); register_demo!(runner, demo_natural_binomial_coefficient); register_demo!(runner, demo_natural_binomial_coefficient_ref); register_bench!(runner, benchmark_binomial_coefficient_limb_limb_algorithms); register_bench!( runner, benchmark_natural_binomial_coefficient_evaluation_strategy ); register_bench!(runner, benchmark_natural_binomial_coefficient_algorithms); register_bench!( runner, benchmark_natural_binomial_coefficient_library_comparison ); } fn demo_limbs_binomial_coefficient_limb_limb_bdiv(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in unsigned_pair_gen_var_45().get(gm, config).take(limit) { println!( "limbs_binomial_coefficient_limb_limb_bdiv({}, {}) = {:?}", n, k, limbs_binomial_coefficient_limb_limb_bdiv(n, k), ); } } fn demo_limbs_binomial_coefficient_limb_limb_small_k( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_46().get(gm, config).take(limit) { println!( "limbs_binomial_coefficient_limb_limb_small_k({}, {}) = {:?}", n, k, limbs_binomial_coefficient_limb_limb_small_k(n, k), ); } } fn demo_limbs_binomial_coefficient_limb_limb_basecase( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_47().get(gm, config).take(limit) { println!( "limbs_binomial_coefficient_limb_limb_basecase({}, {}) = {}", n, k, limbs_binomial_coefficient_limb_limb_basecase(n, k), ); } } fn demo_limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_48().get(gm, config).take(limit) { println!( "limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer({}, {}) = {:?}", n, k, limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, k), ); } } fn demo_limbs_binomial_coefficient_limb_limb_goetgheluck( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, k) in unsigned_pair_gen_var_49().get(gm, config).take(limit) { println!( "limbs_binomial_coefficient_limb_limb_goetgheluck({}, {}) = {:?}", n, k, limbs_binomial_coefficient_limb_limb_goetgheluck(n, k), ); } } fn demo_binomial_coefficient_limb_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in unsigned_pair_gen_var_28().get(gm, config).take(limit) { println!( "binomial_coefficient_limb_limb({}, {}) = {}", n, k, binomial_coefficient_limb_limb(n, k), ); } } fn demo_natural_binomial_coefficient(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in natural_pair_gen_var_15().get(gm, config).take(limit) { let n_orig = n.clone(); let k_orig = k.clone(); println!( "C({}, {}) = {}", n_orig, k_orig, Natural::binomial_coefficient(n, k) ); } } fn demo_natural_binomial_coefficient_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, k) in natural_pair_gen_var_15().get(gm, config).take(limit) { println!( "C({}, {}) = {}", n, k, Natural::binomial_coefficient(&n, &k) ); } } fn benchmark_binomial_coefficient_limb_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "binomial_coefficient_limb_limb(Limb, Limb)", BenchmarkType::Algorithms, unsigned_pair_gen_var_28().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_max_bucketer("n", "k"), &mut [ ("default", &mut |(n, k)| { no_out!(binomial_coefficient_limb_limb(n, k)); }), ("naive", &mut |(n, k)| { no_out!(Natural::binomial_coefficient( Natural::from(n), Natural::from(k) )); }), ], ); } fn benchmark_natural_binomial_coefficient_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.binomial_coefficient(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ( "Natural.binomial_coefficient(Natural, Natural)", &mut |(n, k)| no_out!(Natural::binomial_coefficient(n, k)), ), ( "Natural.binomial_coefficient(&Natural, &Natural)", &mut |(n, k)| no_out!(Natural::binomial_coefficient(&n, &k)), ), ], ); } fn benchmark_natural_binomial_coefficient_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.binomial_coefficient(Natural, Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(n, k)| { no_out!(Natural::binomial_coefficient(n, k)); }), ("naive 1", &mut |(n, k)| { no_out!(binomial_coefficient_naive_1(n, k)); }), ("naive 2", &mut |(n, k)| { no_out!(binomial_coefficient_naive_2(n, k)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_binomial_coefficient_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.binomial_coefficient(Natural, Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_15_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (n, k))| { no_out!(Natural::binomial_coefficient(n, k)); }), ("rug", &mut |((n, k), _)| no_out!(n.binomial(k))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/checked_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedSub; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_nrm}; use malachite_nz::test_util::natural::arithmetic::checked_sub::checked_sub; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_checked_sub); register_demo!(runner, demo_natural_checked_sub_val_ref); register_demo!(runner, demo_natural_checked_sub_ref_val); register_demo!(runner, demo_natural_checked_sub_ref_ref); register_bench!(runner, benchmark_natural_checked_sub_library_comparison); register_bench!(runner, benchmark_natural_checked_sub_evaluation_strategy); } fn demo_natural_checked_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.checked_sub({}) = {:?}", x_old, y_old, x.checked_sub(y)); } } fn demo_natural_checked_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.checked_sub(&{}) = {:?}", x_old, y, x.checked_sub(&y)); } } fn demo_natural_checked_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).checked_sub({}) = {:?}", x, y_old, (&x).checked_sub(y) ); } } fn demo_natural_checked_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("(&{}).checked_sub(&{}) = {:?}", x, y, (&x).checked_sub(&y)); } } fn benchmark_natural_checked_sub_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.checked_sub(y))), ("num", &mut |((x, y), _, _)| no_out!(checked_sub(x, y))), ("rug", &mut |(_, (x, y), _)| no_out!(checked_sub(x, y))), ], ); } fn benchmark_natural_checked_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.checked_sub(Natural)", &mut |(x, y)| { no_out!(x.checked_sub(y)); }), ("Natural.checked_sub(&Natural)", &mut |(x, y)| { no_out!(x.checked_sub(&y)); }), ("&Natural.checked_sub(Natural)", &mut |(x, y)| { no_out!((&x).checked_sub(y)); }), ("&Natural.checked_sub(&Natural)", &mut |(x, y)| { no_out!((&x).checked_sub(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedSub, CheckedSubMul}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_checked_sub_mul); register_demo!(runner, demo_natural_checked_sub_mul_val_val_ref); register_demo!(runner, demo_natural_checked_sub_mul_val_ref_val); register_demo!(runner, demo_natural_checked_sub_mul_val_ref_ref); register_demo!(runner, demo_natural_checked_sub_mul_ref_ref_ref); register_bench!( runner, benchmark_natural_checked_sub_mul_evaluation_strategy ); register_bench!(runner, benchmark_natural_checked_sub_mul_algorithms); register_bench!( runner, benchmark_natural_checked_sub_mul_val_val_ref_algorithms ); register_bench!( runner, benchmark_natural_checked_sub_mul_val_ref_val_algorithms ); register_bench!( runner, benchmark_natural_checked_sub_mul_val_ref_ref_algorithms ); register_bench!( runner, benchmark_natural_checked_sub_mul_ref_ref_ref_algorithms ); } fn demo_natural_checked_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); let c_old = c.clone(); println!( "{}.checked_sub_mul({}, {}) = {:?}", a_old, b_old, c_old, a.checked_sub_mul(b, c) ); } } fn demo_natural_checked_sub_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); println!( "{}.checked_sub_mul({}, &{}) = {:?}", a_old, b_old, c, a.checked_sub_mul(b, &c) ); } } fn demo_natural_checked_sub_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); let c_old = c.clone(); println!( "{}.checked_sub_mul(&{}, {}) = {:?}", a_old, b, c_old, a.checked_sub_mul(&b, c) ); } } fn demo_natural_checked_sub_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); println!( "{}.checked_sub_mul(&{}, &{}) = {:?}", a_old, b, c, a.checked_sub_mul(&b, &c) ); } } fn demo_natural_checked_sub_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen().get(gm, config).take(limit) { let a_old = a.clone(); println!( "(&{}).checked_sub_mul(&{}, &{}) = {:?}", a_old, b, c, (&a).checked_sub_mul(&b, &c) ); } } fn benchmark_natural_checked_sub_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub_mul(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.checked_sub_mul(Natural, Natural)", &mut |(a, b, c)| no_out!(a.checked_sub_mul(b, c)), ), ( "Natural.checked_sub_mul(Natural, &Natural)", &mut |(a, b, c)| no_out!(a.checked_sub_mul(b, &c)), ), ( "Natural.checked_sub_mul(&Natural, Natural)", &mut |(a, b, c)| no_out!(a.checked_sub_mul(&b, c)), ), ( "Natural.checked_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!(a.checked_sub_mul(&b, &c)), ), ( "(&Natural).checked_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).checked_sub_mul(&b, &c)), ), ], ); } fn benchmark_natural_checked_sub_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub_mul(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ("Natural.sub_mul(Natural, Natural)", &mut |(a, b, c)| { no_out!(a.checked_sub_mul(b, c)); }), ( "Natural.checked_sub(Natural * Natural)", &mut |(a, b, c)| no_out!(a.checked_sub(b * c)), ), ], ); } fn benchmark_natural_checked_sub_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub_mul(Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ("Natural.sub_mul(Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.checked_sub_mul(b, &c)); }), ( "Natural.checked_sub(Natural * &Natural)", &mut |(a, b, c)| no_out!(a.checked_sub(b * &c)), ), ], ); } fn benchmark_natural_checked_sub_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub_mul(&Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ("Natural.sub_mul(&Natural, Natural)", &mut |(a, b, c)| { no_out!(a.checked_sub_mul(&b, c)); }), ( "Natural.checked_sub(&Natural * Natural)", &mut |(a, b, c)| no_out!(a.checked_sub(&b * c)), ), ], ); } fn benchmark_natural_checked_sub_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ("Natural.sub_mul(&Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.checked_sub_mul(&b, &c)); }), ( "Natural.checked_sub(&Natural * &Natural)", &mut |(a, b, c)| no_out!(a.checked_sub(&b * &c)), ), ], ); } fn benchmark_natural_checked_sub_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).checked_sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "(&Natural).checked_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).checked_sub_mul(&b, &c)), ), ( "(&Natural).checked_sub(&Natural * &Natural)", &mut |(a, b, c)| no_out!((&a).checked_sub(&b * &c)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CoprimeWith, Gcd}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::coprime_with::{ coprime_with_check_2, coprime_with_check_2_3, coprime_with_check_2_3_5, }; use malachite_nz::test_util::bench::bucketers::pair_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_coprime_with); register_demo!(runner, demo_natural_coprime_with_val_ref); register_demo!(runner, demo_natural_coprime_with_ref_val); register_demo!(runner, demo_natural_coprime_with_ref_ref); register_bench!(runner, benchmark_natural_coprime_with_algorithms); register_bench!(runner, benchmark_natural_coprime_with_evaluation_strategy); } fn demo_natural_coprime_with(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); if x.coprime_with(y) { println!("{x_old} is coprime with {y_old}"); } else { println!("{x_old} is not coprime with {y_old}"); } } } fn demo_natural_coprime_with_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); if x.coprime_with(&y) { println!("{x_old} is coprime with {y}"); } else { println!("{x_old} is not coprime with {y}"); } } } fn demo_natural_coprime_with_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); if (&x).coprime_with(y) { println!("{x} is coprime with {y_old}"); } else { println!("{x} is not coprime with {y_old}"); } } } fn demo_natural_coprime_with_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { if (&x).coprime_with(&y) { println!("{x} is coprime with {y}"); } else { println!("{x} is not coprime with {y}"); } } } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_coprime_with_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.coprime_with(Natural)", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.coprime_with(y))), ("no divisibility check", &mut |(x, y)| { no_out!(x.gcd(y) == 1); }), ("check divisibility by 2", &mut |(x, y)| { no_out!(coprime_with_check_2(x, y)); }), ("check divisibility by 2 and 3", &mut |(x, y)| { no_out!(coprime_with_check_2_3(x, y)); }), ("check divisibility by 2, 3, and 5", &mut |(x, y)| { no_out!(coprime_with_check_2_3_5(x, y)); }), ], ); } fn benchmark_natural_coprime_with_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.coprime_with(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.coprime_with(Natural)", &mut |(x, y)| { no_out!(x.coprime_with(y)); }), ("Natural.coprime_with(&Natural)", &mut |(x, y)| { no_out!(x.coprime_with(&y)); }), ("&Natural.coprime_with(Natural)", &mut |(x, y)| { no_out!((&x).coprime_with(y)); }), ("&Natural.coprime_with(&Natural)", &mut |(x, y)| { no_out!((&x).coprime_with(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedDiv, DivMod}; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, quadruple_2_3_diff_vec_len_bucketer, quadruple_2_vec_len_bucketer, quadruple_3_vec_len_bucketer, triple_1_vec_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_11, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::div::{ limbs_div, limbs_div_barrett, limbs_div_barrett_approx, limbs_div_barrett_approx_scratch_len, limbs_div_barrett_scratch_len, limbs_div_divide_and_conquer, limbs_div_divide_and_conquer_approx, limbs_div_divisor_of_limb_max_with_carry_in_place, limbs_div_divisor_of_limb_max_with_carry_to_out, limbs_div_limb, limbs_div_limb_in_place, limbs_div_limb_to_out, limbs_div_schoolbook, limbs_div_schoolbook_approx, limbs_div_to_out, limbs_div_to_out_balanced, limbs_div_to_out_ref_ref, limbs_div_to_out_ref_val, limbs_div_to_out_unbalanced, limbs_div_to_out_val_ref, }; use malachite_nz::natural::arithmetic::div_mod::{ limbs_div_mod, limbs_div_mod_barrett, limbs_div_mod_barrett_scratch_len, limbs_div_mod_divide_and_conquer, limbs_div_mod_schoolbook, limbs_div_mod_to_out, limbs_two_limb_inverse_helper, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ limbs_div_to_out_balancing_bucketer, pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ large_type_gen_var_10, large_type_gen_var_11, large_type_gen_var_12, natural_pair_gen, natural_pair_gen_nm, natural_pair_gen_var_5, natural_pair_gen_var_5_nrm, unsigned_vec_quadruple_gen_var_1, unsigned_vec_triple_gen_var_42, unsigned_vec_triple_gen_var_43, unsigned_vec_triple_gen_var_44, unsigned_vec_triple_gen_var_45, unsigned_vec_unsigned_unsigned_triple_gen_var_9, }; use malachite_nz::test_util::natural::arithmetic::div::{ limbs_div_limb_in_place_alt, limbs_div_limb_to_out_alt, }; use num::CheckedDiv as NumCheckedDiv; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_div_limb); register_demo!(runner, demo_limbs_div_limb_to_out); register_demo!(runner, demo_limbs_div_limb_in_place); register_demo!(runner, demo_limbs_div_divisor_of_limb_max_with_carry_to_out); register_demo!( runner, demo_limbs_div_divisor_of_limb_max_with_carry_in_place ); register_demo!(runner, demo_limbs_div_schoolbook); register_demo!(runner, demo_limbs_div_divide_and_conquer); register_demo!(runner, demo_limbs_div_barrett); register_demo!(runner, demo_limbs_div_schoolbook_approx); register_demo!(runner, demo_limbs_div_divide_and_conquer_approx); register_demo!(runner, demo_limbs_div_barrett_approx); register_demo!(runner, demo_limbs_div); register_demo!(runner, demo_limbs_div_to_out); register_demo!(runner, demo_limbs_div_to_out_val_ref); register_demo!(runner, demo_limbs_div_to_out_ref_val); register_demo!(runner, demo_limbs_div_to_out_ref_ref); register_demo!(runner, demo_natural_div_assign); register_demo!(runner, demo_natural_div_assign_ref); register_demo!(runner, demo_natural_div); register_demo!(runner, demo_natural_div_val_ref); register_demo!(runner, demo_natural_div_ref_val); register_demo!(runner, demo_natural_div_ref_ref); register_demo!(runner, demo_natural_checked_div); register_demo!(runner, demo_natural_checked_div_val_ref); register_demo!(runner, demo_natural_checked_div_ref_val); register_demo!(runner, demo_natural_checked_div_ref_ref); register_bench!(runner, benchmark_limbs_div_limb); register_bench!(runner, benchmark_limbs_div_limb_to_out_algorithms); register_bench!(runner, benchmark_limbs_div_limb_in_place_algorithms); register_bench!( runner, benchmark_limbs_div_divisor_of_limb_max_with_carry_to_out ); register_bench!( runner, benchmark_limbs_div_divisor_of_limb_max_with_carry_in_place ); register_bench!(runner, benchmark_limbs_div_schoolbook_algorithms); register_bench!(runner, benchmark_limbs_div_divide_and_conquer_algorithms); register_bench!(runner, benchmark_limbs_div_barrett_algorithms); register_bench!(runner, benchmark_limbs_div_schoolbook_approx_algorithms); register_bench!( runner, benchmark_limbs_div_divide_and_conquer_approx_algorithms ); register_bench!(runner, benchmark_limbs_div_barrett_approx_algorithms); register_bench!(runner, benchmark_limbs_div_algorithms); register_bench!(runner, benchmark_limbs_div_to_out_balancing_algorithms); register_bench!(runner, benchmark_limbs_div_to_out_evaluation_strategy); register_bench!(runner, benchmark_limbs_div_to_out_ref_ref_algorithms); register_bench!(runner, benchmark_natural_div_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_div_library_comparison); register_bench!(runner, benchmark_natural_div_algorithms); register_bench!(runner, benchmark_natural_div_evaluation_strategy); register_bench!(runner, benchmark_natural_checked_div_library_comparison); register_bench!(runner, benchmark_natural_checked_div_evaluation_strategy); } fn demo_limbs_div_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_div_limb({:?}, {}) = {:?}", xs, y, limbs_div_limb(&xs, y) ); } } fn demo_limbs_div_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_div_limb_to_out(&mut out, &xs, y); println!("out := {out_old:?}; limbs_div_limb_to_out(&mut out, {xs:?}, {y}); out = {out:?}"); } } fn demo_limbs_div_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_div_limb_in_place(&mut xs, y); println!("limbs := {xs_old:?}; limbs_div_limb_in_place(&mut limbs, {y}); limbs = {xs:?}"); } } fn demo_limbs_div_divisor_of_limb_max_with_carry_to_out( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut out, xs, divisor, carry) in large_type_gen_var_10().get(gm, config).take(limit) { let out_old = out.clone(); let carry_out = limbs_div_divisor_of_limb_max_with_carry_to_out::( &mut out, &xs, divisor, carry, ); println!( "out := {out_old:?}; \ limbs_div_divisor_of_limb_max_with_carry_to_out(&mut out, {xs:?}, {divisor}, {carry}) \ = {carry_out}; out = {out:?}", ); } } fn demo_limbs_div_divisor_of_limb_max_with_carry_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, divisor, carry) in unsigned_vec_unsigned_unsigned_triple_gen_var_9() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry_out = limbs_div_divisor_of_limb_max_with_carry_in_place(&mut xs, divisor, carry); println!( "xs := {xs_old:?}; \ limbs_div_divisor_of_limb_max_with_carry_in_place(&mut xs, {divisor}, {carry}) = \ {carry_out}; xs = {xs:?}", ); } } fn demo_limbs_div_schoolbook(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_11().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_schoolbook(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; \ ns := {old_ns:?}; limbs_div_schoolbook(&mut qs, &mut ns, {ds:?}, {inverse}) = \ {highest_q}; qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_div_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds, inverse) in large_type_gen_var_12().get(gm, config).take(limit) { let old_qs = qs.clone(); let highest_q = limbs_div_divide_and_conquer(&mut qs, &ns, &ds, inverse); println!( "qs := {old_qs:?}; \ ns := {ns:?}; limbs_div_divide_and_conquer(&mut qs, &ns, {ds:?}, {inverse}) = \ {highest_q}; qs = {qs:?}", ); } } fn demo_limbs_div_barrett(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_43().get(gm, config).take(limit) { let old_qs = qs.clone(); let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; let highest_q = limbs_div_barrett(&mut qs, &ns, &ds, &mut scratch); println!( "qs := {old_qs:?}; ns := {ns:?}; \ limbs_div_barrett(&mut qs, ns, {ds:?}, &mut scratch) = {highest_q}; qs = {qs:?}", ); } } fn demo_limbs_div_schoolbook_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_11().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_schoolbook_approx(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; ns := {old_ns:?}; \ limbs_div_schoolbook_approx(&mut qs, &mut ns, {ds:?}, {inverse}) = {highest_q}; \ qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_div_divide_and_conquer_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_12().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_divide_and_conquer_approx(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; ns := {old_ns:?}; \ limbs_div_divide_and_conquer_approx(&mut qs, &mut ns, {ds:?}, {inverse}) = \ {highest_q}; qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_div_barrett_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_42().get(gm, config).take(limit) { let old_qs = qs.clone(); let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; let highest_q = limbs_div_barrett_approx(&mut qs, &ns, &ds, &mut scratch); println!( "qs := {old_qs:?}; ns := {ns:?}; \ limbs_div_barrett_approx(&mut qs, ns, {ds:?}, &mut scratch) = {highest_q}; \ qs = {qs:?}", ); } } fn demo_limbs_div(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_11().get(gm, config).take(limit) { println!("limbs_div({:?}, {:?}) = {:?}", ns, ds, limbs_div(&ns, &ds)); } } fn demo_limbs_div_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, mut ds) in unsigned_vec_triple_gen_var_44().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let old_ds = ds.clone(); limbs_div_to_out(&mut qs, &mut ns, &mut ds); println!( "qs := {old_qs:?}; \ ns := {old_ns:?}; ds := {old_ds:?}; limbs_div_to_out(&mut qs, &mut ns, &mut ds); \ qs = {qs:?}", ); } } fn demo_limbs_div_to_out_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds) in unsigned_vec_triple_gen_var_44().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); limbs_div_to_out_val_ref(&mut qs, &mut ns, &ds); println!( "qs := {old_qs:?}; \ ns := {old_ns:?}; limbs_div_to_out_val_ref(&mut qs, &mut ns, {ds:?}); qs = {qs:?}", ); } } fn demo_limbs_div_to_out_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, mut ds) in unsigned_vec_triple_gen_var_44().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ds = ds.clone(); limbs_div_to_out_ref_val(&mut qs, &ns, &mut ds); println!( "qs := {old_qs:?}; \ ds := {old_ds:?}; limbs_div_to_out_ref_val(&mut qs, {ns:?}, &mut ds); qs = {qs:?}", ); } } fn demo_limbs_div_to_out_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_44().get(gm, config).take(limit) { let old_qs = qs.clone(); limbs_div_to_out_ref_ref(&mut qs, &ns, &ds); println!( "qs := {old_qs:?}; limbs_div_to_out_ref_ref(&mut qs, {ns:?}, {ds:?}); qs = {qs:?}", ); } } fn demo_natural_div_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x /= y; println!("x := {x_old}; x /= {y_old}; x = {x}"); } } fn demo_natural_div_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); x /= &y; println!("x := {x_old}; x /= &{y}; x = {x}"); } } fn demo_natural_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_natural_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_natural_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_natural_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_natural_checked_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).checked_div({}) = {:?}", x_old, y_old, x.checked_div(y) ); } } fn demo_natural_checked_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).checked_div(&{}) = {:?}", x_old, y, x.checked_div(&y)); } } fn demo_natural_checked_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).checked_div({}) = {:?}", x, y_old, (&x).checked_div(y) ); } } fn demo_natural_checked_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("(&{}).checked_div(&{}) = {:?}", x, y, (&x).checked_div(&y)); } } fn benchmark_limbs_div_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_div_limb(&xs, y)))], ); } fn benchmark_limbs_div_limb_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut out, xs, y)| { limbs_div_limb_to_out(&mut out, &xs, y); }), ("alt", &mut |(mut out, xs, y)| { limbs_div_limb_to_out_alt(&mut out, &xs, y); }), ], ); } fn benchmark_limbs_div_limb_in_place_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut xs, y)| { limbs_div_limb_in_place(&mut xs, y); }), ("alt", &mut |(mut xs, y)| { limbs_div_limb_in_place_alt(&mut xs, y); }), ], ); } fn benchmark_limbs_div_divisor_of_limb_max_with_carry_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_divisor_of_limb_max_with_carry_to_out(&mut [Limb], &[Limb], Limb, Limb)", BenchmarkType::Single, large_type_gen_var_10().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, divisor, carry)| { no_out!(limbs_div_divisor_of_limb_max_with_carry_to_out::< DoubleLimb, Limb, >(&mut out, &xs, divisor, carry)); })], ); } fn benchmark_limbs_div_divisor_of_limb_max_with_carry_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_divisor_of_limb_max_with_carry_in_place(&mut [Limb], Limb, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, divisor, carry)| { no_out!(limbs_div_divisor_of_limb_max_with_carry_in_place( &mut xs, divisor, carry )); })], ); } fn benchmark_limbs_div_schoolbook_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_schoolbook(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_11().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook div/mod", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ("Schoolbook div", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ], ); } fn benchmark_limbs_div_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook div", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ("divide-and-conquer div/mod", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_div_mod_divide_and_conquer( &mut qs, &mut ns, &ds, inverse )); }), ("divide-and-conquer div", &mut |( mut qs, ns, ds, inverse, )| { no_out!(limbs_div_divide_and_conquer(&mut qs, &ns, &ds, inverse)); }), ], ); } fn benchmark_limbs_div_barrett_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_barrett(&mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("divide-and-conquer div", &mut |( mut qs, ns, ds, inverse, )| { no_out!(limbs_div_divide_and_conquer(&mut qs, &ns, &ds, inverse)); }), ("Barrett div/mod", &mut |(mut qs, ns, ds, _)| { let mut rs = vec![0; ds.len()]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; no_out!(limbs_div_mod_barrett( &mut qs, &mut rs, &ns, &ds, &mut scratch )); }), ("Barrett div", &mut |(mut qs, ns, ds, _)| { let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; no_out!(limbs_div_barrett(&mut qs, &ns, &ds, &mut scratch)); }), ], ); } fn benchmark_limbs_div_schoolbook_approx_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_schoolbook_approx(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_11().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ("Schoolbook approx", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_schoolbook_approx(&mut qs, &mut ns, &ds, inverse)); }), ], ); } fn benchmark_limbs_div_divide_and_conquer_approx_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_divide_and_conquer_approx(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook approx", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_schoolbook_approx(&mut qs, &mut ns, &ds, inverse)); }), ("divide-and-conquer", &mut |(mut qs, ns, ds, inverse)| { no_out!(limbs_div_divide_and_conquer(&mut qs, &ns, &ds, inverse)); }), ("divide-and-conquer approx", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_div_divide_and_conquer_approx( &mut qs, &mut ns, &ds, inverse )); }), ], ); } fn benchmark_limbs_div_barrett_approx_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_barrett_approx(&mut [Limb], &[Limb], &[Limb], &mut Limb)", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("divide-and-conquer approx", &mut |( mut qs, mut ns, ds, _, )| { // recompute inverse to make benchmark fair let inverse = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); no_out!(limbs_div_divide_and_conquer_approx( &mut qs, &mut ns, &ds, inverse )); }), ("Barrett", &mut |(mut qs, ns, ds, _)| { let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; no_out!(limbs_div_barrett(&mut qs, &ns, &ds, &mut scratch)); }), ("Barrett approx", &mut |(mut qs, ns, ds, _)| { let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; no_out!(limbs_div_barrett_approx(&mut qs, &ns, &ds, &mut scratch)); }), ], ); } fn benchmark_limbs_div_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div(&[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("div_mod", &mut |(ns, ds)| no_out!(limbs_div_mod(&ns, &ds))), ("div", &mut |(ns, ds)| no_out!(limbs_div(&ns, &ds))), ], ); } fn benchmark_limbs_div_to_out_balancing_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_to_out(&mut [Limb], &mut [Limb], &mut [Limb]) balancing", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_45().get(gm, config), gm.name(), limit, file_name, &limbs_div_to_out_balancing_bucketer(), &mut [ ("unbalanced", &mut |(mut qs, mut ns, mut ds)| { limbs_div_to_out_unbalanced(&mut qs, &mut ns, &mut ds); }), ("balanced", &mut |(mut qs, ns, ds)| { limbs_div_to_out_balanced(&mut qs, &ns, &ds); }), ], ); } fn benchmark_limbs_div_to_out_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_to_out(&mut [Limb], &mut [Limb], &mut [Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_triple_gen_var_44().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ( "limbs_div_to_out(&mut [Limb], &mut [Limb], &mut [Limb])", &mut |(mut qs, mut ns, mut ds)| limbs_div_to_out(&mut qs, &mut ns, &mut ds), ), ( "limbs_div_to_out_val_ref(&mut [Limb], &mut [Limb], &[Limb])", &mut |(mut qs, mut ns, ds)| limbs_div_to_out_val_ref(&mut qs, &mut ns, &ds), ), ( "limbs_div_to_out_ref_val(&mut [Limb], &[Limb], &mut [Limb])", &mut |(mut qs, ns, mut ds)| limbs_div_to_out_ref_val(&mut qs, &ns, &mut ds), ), ( "limbs_div_to_out_ref_ref(&mut [Limb], &[Limb], &[Limb])", &mut |(mut qs, ns, ds)| limbs_div_to_out_ref_ref(&mut qs, &ns, &ds), ), ], ); } fn benchmark_limbs_div_to_out_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_to_out_ref_ref(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ns"), &mut [ ("div_mod", &mut |(mut qs, mut rs, ns, ds)| { limbs_div_mod_to_out(&mut qs, &mut rs, &ns, &ds); }), ("div", &mut |(mut qs, _, ns, ds)| { limbs_div_to_out_ref_ref(&mut qs, &ns, &ds); }), ], ); } fn benchmark_natural_div_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural /= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural /= Natural", &mut |(mut x, y)| x /= y), ("Natural /= &Natural", &mut |(mut x, y)| x /= &y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural / Natural", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x / y)), ("num", &mut |((x, y), _, _)| no_out!(x / &y)), ("rug", &mut |(_, (x, y), _)| no_out!(x / y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_div_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural / Natural", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("standard", &mut |(x, y)| no_out!(x / y)), ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y).0)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural / Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural / Natural", &mut |(x, y)| no_out!(x / y)), ("Natural / &Natural", &mut |(x, y)| no_out!(x / &y)), ("&Natural / Natural", &mut |(x, y)| no_out!(&x / y)), ("&Natural / &Natural", &mut |(x, y)| no_out!(&x / &y)), ], ); } fn benchmark_natural_checked_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_div(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.checked_div(&y))), ("num", &mut |((x, y), _)| no_out!(x.checked_div(&y))), ], ); } fn benchmark_natural_checked_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_div(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.checked_div(Natural)", &mut |(x, y)| { no_out!(x.checked_div(y)); }), ("Natural.checked_div(&Natural)", &mut |(x, y)| { no_out!(x.checked_div(&y)); }), ("(&Natural).checked_div(Natural)", &mut |(x, y)| { no_out!((&x).checked_div(y)); }), ("(&Natural).checked_div(&Natural)", &mut |(x, y)| { no_out!((&x).checked_div(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign}; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_2_vec_len_bucketer, quadruple_2_vec_len_bucketer, quadruple_3_vec_len_bucketer, triple_2_vec_len_bucketer, unsigned_bit_bucketer, vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_gen_var_22, unsigned_vec_pair_gen_var_12}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::div::{ limbs_div, limbs_div_limb, limbs_div_limb_in_place, limbs_div_limb_to_out, limbs_div_to_out, }; use malachite_nz::natural::arithmetic::div_exact::{ limbs_div_exact, limbs_div_exact_3, limbs_div_exact_3_in_place, limbs_div_exact_3_to_out, limbs_div_exact_limb, limbs_div_exact_limb_in_place, limbs_div_exact_limb_in_place_no_special_3, limbs_div_exact_limb_no_special_3, limbs_div_exact_limb_to_out, limbs_div_exact_limb_to_out_no_special_3, limbs_div_exact_to_out, limbs_div_exact_to_out_ref_ref, limbs_div_exact_to_out_ref_val, limbs_div_exact_to_out_val_ref, limbs_modular_div, limbs_modular_div_barrett, limbs_modular_div_barrett_scratch_len, limbs_modular_div_divide_and_conquer, limbs_modular_div_mod_barrett, limbs_modular_div_mod_barrett_scratch_len, limbs_modular_div_mod_divide_and_conquer, limbs_modular_div_mod_schoolbook, limbs_modular_div_ref, limbs_modular_div_ref_scratch_len, limbs_modular_div_schoolbook, limbs_modular_div_scratch_len, limbs_modular_invert, limbs_modular_invert_limb, limbs_modular_invert_scratch_len, limbs_modular_invert_small, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ large_type_gen_var_13, large_type_gen_var_14, large_type_gen_var_15, large_type_gen_var_16, large_type_gen_var_17, natural_pair_gen_var_6, natural_pair_gen_var_6_nrm, unsigned_vec_gen_var_5, unsigned_vec_pair_gen_var_13, unsigned_vec_pair_gen_var_14, unsigned_vec_quadruple_gen_var_2, unsigned_vec_quadruple_gen_var_3, unsigned_vec_triple_gen_var_46, unsigned_vec_triple_gen_var_47, unsigned_vec_triple_gen_var_48, unsigned_vec_triple_gen_var_49, unsigned_vec_unsigned_pair_gen_var_29, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14, }; use malachite_nz::test_util::natural::arithmetic::div_exact::{ limbs_div_exact_3_in_place_alt, limbs_div_exact_3_to_out_alt, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_modular_invert_limb); register_demo!(runner, demo_limbs_div_exact_limb); register_demo!(runner, demo_limbs_div_exact_limb_to_out); register_demo!(runner, demo_limbs_div_exact_limb_in_place); register_demo!(runner, demo_limbs_div_exact_3); register_demo!(runner, demo_limbs_div_exact_3_to_out); register_demo!(runner, demo_limbs_div_exact_3_in_place); register_demo!(runner, demo_limbs_modular_invert); register_demo!(runner, demo_limbs_modular_div_mod_schoolbook); register_demo!(runner, demo_limbs_modular_div_mod_divide_and_conquer); register_demo!(runner, demo_limbs_modular_div_mod_barrett); register_demo!(runner, demo_limbs_modular_div_schoolbook); register_demo!(runner, demo_limbs_modular_div_divide_and_conquer); register_demo!(runner, demo_limbs_modular_div_barrett); register_demo!(runner, demo_limbs_modular_div); register_demo!(runner, demo_limbs_modular_div_ref); register_demo!(runner, demo_limbs_div_exact); register_demo!(runner, demo_limbs_div_exact_to_out); register_demo!(runner, demo_limbs_div_exact_to_out_val_ref); register_demo!(runner, demo_limbs_div_exact_to_out_ref_val); register_demo!(runner, demo_limbs_div_exact_to_out_ref_ref); register_demo!(runner, demo_natural_div_exact_assign); register_demo!(runner, demo_natural_div_exact_assign_ref); register_demo!(runner, demo_natural_div_exact); register_demo!(runner, demo_natural_div_exact_val_ref); register_demo!(runner, demo_natural_div_exact_ref_val); register_demo!(runner, demo_natural_div_exact_ref_ref); register_bench!(runner, benchmark_limbs_modular_invert_limb); register_bench!(runner, benchmark_limbs_div_exact_limb_algorithms); register_bench!(runner, benchmark_limbs_div_exact_limb_to_out_algorithms); register_bench!(runner, benchmark_limbs_div_exact_limb_in_place_algorithms); register_bench!(runner, benchmark_limbs_div_exact_3_algorithms); register_bench!(runner, benchmark_limbs_div_exact_3_to_out_algorithms); register_bench!(runner, benchmark_limbs_div_exact_3_in_place_algorithms); register_bench!(runner, benchmark_limbs_modular_invert_algorithms); register_bench!(runner, benchmark_limbs_modular_div_mod_schoolbook); register_bench!( runner, benchmark_limbs_modular_div_mod_divide_and_conquer_algorithms ); register_bench!(runner, benchmark_limbs_modular_div_mod_barrett_algorithms); register_bench!(runner, benchmark_limbs_modular_div_schoolbook); register_bench!( runner, benchmark_limbs_modular_div_divide_and_conquer_algorithms ); register_bench!(runner, benchmark_limbs_modular_div_barrett_algorithms); register_bench!(runner, benchmark_limbs_modular_div_evaluation_strategy); register_bench!(runner, benchmark_limbs_div_exact_algorithms); register_bench!(runner, benchmark_limbs_div_exact_to_out_algorithms); register_bench!(runner, benchmark_limbs_div_exact_to_out_evaluation_strategy); register_bench!(runner, benchmark_natural_div_exact_assign_algorithms); register_bench!( runner, benchmark_natural_div_exact_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_div_exact_library_comparison); register_bench!(runner, benchmark_natural_div_exact_algorithms); register_bench!(runner, benchmark_natural_div_exact_evaluation_strategy); } fn demo_limbs_modular_invert_limb(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_22().get(gm, config).take(limit) { println!( "limbs_modular_invert_limb({}) = {}", x, limbs_modular_invert_limb::(x) ); } } fn demo_limbs_div_exact_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_29() .get(gm, config) .take(limit) { println!( "limbs_div_exact_limb({:?}, {}) = {:?}", xs, y, limbs_div_exact_limb(&xs, y) ); } } fn demo_limbs_div_exact_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_div_exact_limb_to_out::(&mut out, &xs, y); println!( "out := {out_old:?}; limbs_exact_div_limb_to_out(&mut out, {xs:?}, {y}); \ out = {out:?}", ); } } fn demo_limbs_div_exact_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_29() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_div_exact_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_div_exact_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_div_exact_3(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_5().get(gm, config).take(limit) { println!("limbs_div_exact_3({:?}) = {:?}", xs, limbs_div_exact_3(&xs)); } } fn demo_limbs_div_exact_3_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_13().get(gm, config).take(limit) { let out_old = out.clone(); limbs_div_exact_3_to_out::(&mut out, &xs); println!("out := {out_old:?}; limbs_exact_div_3_to_out(&mut out, {xs:?}); out = {out:?}"); } } fn demo_limbs_div_exact_3_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen_var_5().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_div_exact_3_in_place(&mut xs); println!("xs := {xs_old:?}; limbs_div_exact_3_in_place(&mut xs); xs = {xs:?}"); } } fn demo_limbs_modular_invert(gm: GenMode, config: &GenConfig, limit: usize) { for (mut is, ds) in unsigned_vec_pair_gen_var_12().get(gm, config).take(limit) { let old_is = is.clone(); let mut scratch = vec![0; limbs_modular_invert_scratch_len(ds.len())]; limbs_modular_invert(&mut is, &ds, &mut scratch); println!( "is := {old_is:?}; limbs_modular_invert(&mut is, {ds:?}, &mut scratch); is = {is:?}, " ); } } fn demo_limbs_modular_div_mod_schoolbook(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_14().get(gm, config).take(limit) { let qs_old = qs.clone(); let ns_old = ns.clone(); let borrow = limbs_modular_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse); println!( "qs := {qs_old:?}; ns := {ns_old:?}; \ limbs_modular_div_mod_schoolbook(&mut qs, &mut ns, {ds:?}, {inverse}) = {borrow}; \ qs = {qs:?}; ns = {ns:?}", ); } } fn demo_limbs_modular_div_mod_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_15().get(gm, config).take(limit) { let qs_old = qs.clone(); let ns_old = ns.clone(); let borrow = limbs_modular_div_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); println!( "qs := {qs_old:?}; ns := {ns_old:?}; \ limbs_modular_div_mod_divide_and_conquer(&mut qs, &mut ns, {ds:?}, {inverse}) = \ {borrow}; qs = {qs:?}; ns = {ns:?}", ); } } fn demo_limbs_modular_div_mod_barrett(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut rs, ns, ds) in unsigned_vec_quadruple_gen_var_2() .get(gm, config) .take(limit) { let qs_old = qs.clone(); let rs_old = rs.clone(); let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let borrow = limbs_modular_div_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); println!( "qs := {qs_old:?}; rs := {rs_old:?}; limbs_modular_div_mod_divide_and_conquer(\ &mut qs, &mut rs, {ns:?}, {ds:?} &mut scratch) = {borrow}; qs = {qs:?}; rs = {rs:?}", ); } } fn demo_limbs_modular_div_schoolbook(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_13().get(gm, config).take(limit) { let qs_old = qs.clone(); let ns_old = ns.clone(); limbs_modular_div_schoolbook(&mut qs, &mut ns, &ds, inverse); println!( "qs := {qs_old:?}; \ ns := {ns_old:?}; limbs_modular_div_schoolbook(&mut qs, &mut ns, {ds:?}, {inverse}); \ qs = {qs:?}", ); } } fn demo_limbs_modular_div_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_16().get(gm, config).take(limit) { let qs_old = qs.clone(); let ns_old = ns.clone(); limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); println!( "qs := {qs_old:?}; ns := {ns_old:?}; \ limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, {ds:?}, {inverse}); \ qs = {qs:?}", ); } } fn demo_limbs_modular_div_barrett(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_46().get(gm, config).take(limit) { let qs_old = qs.clone(); let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut qs, &ns, &ds, &mut scratch); println!( "qs := {qs_old:?}; limbs_modular_div_barrett(&mut qs, {ns:?}, {ds:?} &mut scratch); \ qs = {qs:?}", ); } } fn demo_limbs_modular_div(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds) in unsigned_vec_triple_gen_var_47().get(gm, config).take(limit) { let ns_old = ns.clone(); let qs_old = qs.clone(); let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut qs, &mut ns, &ds, &mut scratch); println!( "qs := {qs_old:?}; limbs_modular_div(&mut qs, {ns_old:?}, {ds:?} &mut scratch); \ qs = {qs:?}", ); } } fn demo_limbs_modular_div_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_47().get(gm, config).take(limit) { let qs_old = qs.clone(); let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut qs, &ns, &ds, &mut scratch); println!( "qs := {qs_old:?}; limbs_modular_div_ref(&mut qs, {ns:?}, {ds:?} &mut scratch); \ qs = {qs:?}", ); } } fn demo_limbs_div_exact(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_14().get(gm, config).take(limit) { println!( "limbs_div_exact({:?}, {:?}) = {:?}", ns, ds, limbs_div_exact(&ns, &ds) ); } } fn demo_limbs_div_exact_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, mut ds) in unsigned_vec_triple_gen_var_48().get(gm, config).take(limit) { let ns_old = ns.clone(); let ds_old = ds.clone(); let qs_old = qs.clone(); limbs_div_exact_to_out(&mut qs, &mut ns, &mut ds); println!( "qs := {qs_old:?}; limbs_div_exact_to_out(&mut qs, {ns_old:?}, {ds_old:?}); \ qs = {qs:?}", ); } } fn demo_limbs_div_exact_to_out_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds) in unsigned_vec_triple_gen_var_48().get(gm, config).take(limit) { let ns_old = ns.clone(); let qs_old = qs.clone(); limbs_div_exact_to_out_val_ref(&mut qs, &mut ns, &ds); println!( "qs := {qs_old:?}; limbs_div_exact_to_out_val_ref(&mut qs, {ns_old:?}, {ds:?}); \ qs = {qs:?}", ); } } fn demo_limbs_div_exact_to_out_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, mut ds) in unsigned_vec_triple_gen_var_48().get(gm, config).take(limit) { let ds_old = ds.clone(); let qs_old = qs.clone(); limbs_div_exact_to_out_ref_val(&mut qs, &ns, &mut ds); println!( "qs := {qs_old:?}; limbs_div_exact_to_out_ref_val(&mut qs, {ns:?}, {ds_old:?}); \ qs = {qs:?}", ); } } fn demo_limbs_div_exact_to_out_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, ns, ds) in unsigned_vec_triple_gen_var_48().get(gm, config).take(limit) { let qs_old = qs.clone(); limbs_div_exact_to_out_ref_ref(&mut qs, &ns, &ds); println!( "qs := {qs_old:?}; limbs_div_exact_to_out_ref_ref(&mut qs, {ns:?}, {ds:?}); \ qs = {qs:?}", ); } } fn demo_natural_div_exact_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.div_exact_assign(y); println!("x := {x_old}; x.div_exact_assign({y_old}); x = {x}"); } } fn demo_natural_div_exact_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { let x_old = x.clone(); x.div_exact_assign(&y); println!("x := {x_old}; x.div_exact_assign(&{y}); x = {x}"); } } fn demo_natural_div_exact(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_exact({}) = {}", x_old, y_old, x.div_exact(y)); } } fn demo_natural_div_exact_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_exact(&{}) = {}", x_old, y, x.div_exact(&y)); } } fn demo_natural_div_exact_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_exact({}) = {}", x, y_old, (&x).div_exact(y)); } } fn demo_natural_div_exact_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_6().get(gm, config).take(limit) { println!("(&{}).div_exact(&{}) = {}", x, y, (&x).div_exact(&y)); } } fn benchmark_limbs_modular_invert_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_invert_limb(Limb)", BenchmarkType::Single, unsigned_gen_var_22().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| { no_out!(limbs_modular_invert_limb::(x)); })], ); } fn benchmark_limbs_div_exact_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_limb(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_29().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("div_exact", &mut |(xs, y)| { no_out!(limbs_div_exact_limb(&xs, y)); }), ("div", &mut |(xs, y)| no_out!(limbs_div_limb(&xs, y))), ], ); } fn benchmark_limbs_div_exact_limb_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("div_exact", &mut |(mut out, xs, y)| { limbs_div_exact_limb_to_out::(&mut out, &xs, y); }), ("div", &mut |(mut out, xs, y)| { limbs_div_limb_to_out(&mut out, &xs, y); }), ], ); } fn benchmark_limbs_div_exact_limb_in_place_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_29().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("div_exact", &mut |(mut xs, y)| { limbs_div_exact_limb_in_place(&mut xs, y); }), ("div", &mut |(mut xs, y)| { limbs_div_limb_in_place(&mut xs, y); }), ], ); } fn benchmark_limbs_div_exact_3_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_3(&[Limb])", BenchmarkType::Algorithms, unsigned_vec_gen_var_5().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("limbs_div_exact_3", &mut |xs| { no_out!(limbs_div_exact_3(&xs)); }), ("limbs_div_exact_limb_no_special_3", &mut |xs| { no_out!(limbs_div_exact_limb_no_special_3(&xs, 3)); }), ], ); } fn benchmark_limbs_div_exact_3_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_limb_to_out(&mut [Limb], 3)", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ( "limbs_div_exact_limb_to_out_no_special_3", &mut |(mut out, xs)| { limbs_div_exact_limb_to_out_no_special_3::(&mut out, &xs, 3); }, ), ("limbs_div_exact_3_to_out", &mut |(mut out, xs)| { limbs_div_exact_3_to_out::(&mut out, &xs); }), ("limbs_div_exact_3_to_out_alt", &mut |(mut out, xs)| { limbs_div_exact_3_to_out_alt(&mut out, &xs); }), ], ); } fn benchmark_limbs_div_exact_3_in_place_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_limb_in_place(&mut [Limb], 3)", BenchmarkType::Algorithms, unsigned_vec_gen_var_5().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ( "limbs_div_exact_limb_in_place_no_special_3", &mut |mut xs| limbs_div_exact_limb_in_place_no_special_3(&mut xs, 3), ), ("limbs_div_exact_3_in_place", &mut |mut xs| { limbs_div_exact_3_in_place(&mut xs); }), ("limbs_div_exact_3_in_place_alt", &mut |mut xs| { limbs_div_exact_3_in_place_alt(&mut xs); }), ], ); } // use large params fn benchmark_limbs_modular_invert_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_invert(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, large_type_gen_var_17().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ds"), &mut [ ("modular invert small", &mut |( mut is, mut scratch, ds, inverse, )| { let n = ds.len(); limbs_modular_invert_small(n, &mut is, &mut scratch[..n], &ds, inverse); }), ("modular invert", &mut |(mut is, mut scratch, ds, _)| { limbs_modular_invert(&mut is, &ds, &mut scratch); }), ], ); } fn benchmark_limbs_modular_div_mod_schoolbook( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_mod_schoolbook(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Single, large_type_gen_var_14().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_modular_div_mod_schoolbook( &mut qs, &mut ns, &ds, inverse )); })], ); } // use large params fn benchmark_limbs_modular_div_mod_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_mod_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_15().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ds"), &mut [ ("schoolbook", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_modular_div_mod_schoolbook( &mut qs, &mut ns, &ds, inverse )); }), ("divide-and-conquer", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_modular_div_mod_divide_and_conquer( &mut qs, &mut ns, &ds, inverse )); }), ], ); } fn benchmark_limbs_modular_div_mod_barrett_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_mod_barrett(&mut [Limb], &mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_quadruple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("ns"), &mut [ ("divide-and-conquer", &mut |(mut qs, _, mut ns, ds)| { let inverse = limbs_modular_invert_limb(ds[0]).wrapping_neg(); no_out!(limbs_modular_div_mod_divide_and_conquer( &mut qs, &mut ns, &ds, inverse )); }), ("Barrett", &mut |(mut qs, mut rs, ns, ds)| { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; no_out!(limbs_modular_div_mod_barrett( &mut qs, &mut rs, &ns, &ds, &mut scratch )); }), ], ); } fn benchmark_limbs_modular_div_schoolbook( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_schoolbook(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Single, large_type_gen_var_13().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(mut qs, mut ns, ds, inverse)| { limbs_modular_div_schoolbook(&mut qs, &mut ns, &ds, inverse); })], ); } // use large params fn benchmark_limbs_modular_div_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_16().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ns"), &mut [ ("schoolbook", &mut |(mut qs, mut ns, ds, inverse)| { limbs_modular_div_schoolbook(&mut qs, &mut ns, &ds, inverse); }), ("divide-and-conquer", &mut |( mut qs, mut ns, ds, inverse, )| { limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); }), ], ); } fn benchmark_limbs_modular_div_barrett_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_46().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ("divide-and-conquer", &mut |(mut qs, mut ns, ds)| { let inverse = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); }), ("Barrett", &mut |(mut qs, ns, ds)| { let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut qs, &ns, &ds, &mut scratch); }), ], ); } // use large params fn benchmark_limbs_modular_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_modular_div(&mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_triple_gen_var_47().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ( "limbs_modular_div(&mut [Limb], &mut [Limb], &[Limb], &mut [Limb])", &mut |(mut qs, mut ns, ds)| { let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut qs, &mut ns, &ds, &mut scratch); }, ), ( "limbs_modular_div_ref(&mut [Limb], &[Limb], &[Limb], &mut [Limb])", &mut |(mut qs, ns, ds)| { let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut qs, &ns, &ds, &mut scratch); }, ), ], ); } fn benchmark_limbs_div_exact_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact(&[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_14().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("div_exact", &mut |(ns, ds)| { no_out!(limbs_div_exact(&ns, &ds)); }), ("div", &mut |(ns, ds)| no_out!(limbs_div(&ns, &ds))), ], ); } fn benchmark_limbs_div_exact_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_to_out(&mut [Limb], &mut [Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_49().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ("div", &mut |(mut qs, mut ns, mut ds)| { limbs_div_to_out(&mut qs, &mut ns, &mut ds); }), ("div exact", &mut |(mut qs, mut ns, mut ds)| { limbs_div_exact_to_out(&mut qs, &mut ns, &mut ds); }), ], ); } fn benchmark_limbs_div_exact_to_out_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_exact_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_triple_gen_var_49().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ( "limbs_div_exact_to_out(&mut [Limb], &mut [Limb], &mut [Limb])", &mut |(mut qs, mut ns, mut ds)| limbs_div_exact_to_out(&mut qs, &mut ns, &mut ds), ), ( "limbs_div_exact_to_out_val_ref(&mut [Limb], &mut [Limb], &[Limb])", &mut |(mut qs, mut ns, ds)| limbs_div_exact_to_out_val_ref(&mut qs, &mut ns, &ds), ), ( "limbs_div_exact_to_out_ref_val(&mut [Limb], &[Limb], &mut [Limb])", &mut |(mut qs, ns, mut ds)| limbs_div_exact_to_out_ref_val(&mut qs, &ns, &mut ds), ), ( "limbs_div_exact_to_out_ref_ref(&mut [Limb], &[Limb], &[Limb])", &mut |(mut qs, ns, ds)| limbs_div_exact_to_out_ref_ref(&mut qs, &ns, &ds), ), ], ); } // use large params fn benchmark_natural_div_exact_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_exact_assign(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("ordinary division", &mut |(mut x, y)| x /= y), ("exact division", &mut |(mut x, y)| x.div_exact_assign(y)), ], ); } // use large params fn benchmark_natural_div_exact_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_exact_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.div_exact_assign(Natural)", &mut |(mut x, y)| { x.div_exact_assign(y); }), ("Natural.div_exact_assign(&Natural)", &mut |(mut x, y)| { x.div_exact_assign(&y); }), ], ); } // use large params #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_div_exact_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_exact(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_6_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("n"), &mut [ ("num", &mut |((x, y), _, _)| no_out!(x / y)), ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_exact(y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_exact(&y))), ], ); } // use large params #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_div_exact_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_exact(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("ordinary division", &mut |(x, y)| no_out!(x / y)), ("exact division", &mut |(x, y)| no_out!(x.div_exact(y))), ], ); } // use large params fn benchmark_natural_div_exact_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_exact(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.div_exact(Natural)", &mut |(x, y)| { no_out!(x.div_exact(y)); }), ("Natural.div_exact(&Natural)", &mut |(x, y)| { no_out!(x.div_exact(&y)); }), ("(&Natural).div_exact(Natural)", &mut |(x, y)| { no_out!((&x).div_exact(y)); }), ("(&Natural).div_exact(&Natural)", &mut |(x, y)| { no_out!((&x).div_exact(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivAssignNegMod, CeilingDivNegMod, DivAssignMod, DivAssignRem, DivMod, DivRem, DivRound, NegMod, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::BitAccess; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, quadruple_2_3_diff_vec_len_bucketer, quadruple_2_vec_len_bucketer, quadruple_3_vec_len_bucketer, quadruple_4_vec_len_bucketer, quintuple_1_vec_len_bucketer, triple_2_3_diff_vec_len_bucketer, triple_2_vec_len_bucketer, unsigned_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_12, unsigned_pair_gen_var_35, unsigned_vec_pair_gen_var_11, unsigned_vec_triple_gen_var_50, unsigned_vec_triple_gen_var_51, unsigned_vec_triple_gen_var_52, unsigned_vec_triple_gen_var_53, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::div_mod::{ limbs_div_barrett_large_product, limbs_div_limb_in_place_mod, limbs_div_limb_mod, limbs_div_limb_to_out_mod, limbs_div_mod, limbs_div_mod_barrett, limbs_div_mod_barrett_helper, limbs_div_mod_barrett_large_helper, limbs_div_mod_barrett_scratch_len, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_divide_and_conquer, limbs_div_mod_extra, limbs_div_mod_extra_in_place, limbs_div_mod_schoolbook, limbs_div_mod_three_limb_by_two_limb, limbs_div_mod_to_out, limbs_invert_approx, limbs_invert_basecase_approx, limbs_invert_limb, limbs_invert_newton_approx, limbs_two_limb_inverse_helper, }; use malachite_nz::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ limbs_div_mod_barrett_helper_bucketer, limbs_div_mod_barrett_product_bucketer, limbs_div_mod_extra_bucketer, pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ large_type_gen_var_11, large_type_gen_var_12, large_type_gen_var_18, large_type_gen_var_19, large_type_gen_var_20, natural_pair_gen_var_5, natural_pair_gen_var_5_nrm, natural_pair_gen_var_5_rm, unsigned_sextuple_gen_var_2, unsigned_vec_quadruple_gen_var_1, unsigned_vec_quadruple_gen_var_4, unsigned_vec_quadruple_gen_var_5, }; use malachite_nz::test_util::natural::arithmetic::div_mod::{ limbs_div_limb_in_place_mod_alt, limbs_div_limb_in_place_mod_naive, limbs_div_limb_to_out_mod_alt, limbs_div_limb_to_out_mod_naive, rug_ceiling_div_neg_mod, }; use num::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_invert_limb); register_demo!(runner, demo_limbs_div_limb_mod); register_demo!(runner, demo_limbs_div_limb_to_out_mod); register_demo!(runner, demo_limbs_div_limb_in_place_mod); register_demo!(runner, demo_limbs_div_mod_extra); register_demo!(runner, demo_limbs_div_mod_extra_in_place); register_demo!(runner, demo_limbs_two_limb_inverse_helper); register_demo!(runner, demo_limbs_div_mod_three_limb_by_two_limb); register_demo!(runner, demo_limbs_div_mod_by_two_limb_normalized); register_demo!(runner, demo_limbs_div_mod_schoolbook); register_demo!(runner, demo_limbs_div_mod_divide_and_conquer); register_demo!(runner, demo_limbs_invert_basecase_approx); register_demo!(runner, demo_limbs_invert_newton_approx); register_demo!(runner, demo_limbs_invert_approx); register_demo!(runner, demo_limbs_div_mod_barrett); register_demo!(runner, demo_limbs_div_mod); register_demo!(runner, demo_limbs_div_mod_to_out); register_demo!(runner, demo_natural_div_assign_mod); register_demo!(runner, demo_natural_div_assign_mod_ref); register_demo!(runner, demo_natural_div_mod); register_demo!(runner, demo_natural_div_mod_val_ref); register_demo!(runner, demo_natural_div_mod_ref_val); register_demo!(runner, demo_natural_div_mod_ref_ref); register_demo!(runner, demo_natural_div_assign_rem); register_demo!(runner, demo_natural_div_assign_rem_ref); register_demo!(runner, demo_natural_div_rem); register_demo!(runner, demo_natural_div_rem_val_ref); register_demo!(runner, demo_natural_div_rem_ref_val); register_demo!(runner, demo_natural_div_rem_ref_ref); register_demo!(runner, demo_natural_ceiling_div_assign_neg_mod); register_demo!(runner, demo_natural_ceiling_div_assign_neg_mod_ref); register_demo!(runner, demo_natural_ceiling_div_neg_mod); register_demo!(runner, demo_natural_ceiling_div_neg_mod_val_ref); register_demo!(runner, demo_natural_ceiling_div_neg_mod_ref_val); register_demo!(runner, demo_natural_ceiling_div_neg_mod_ref_ref); register_bench!(runner, benchmark_limbs_invert_limb); register_bench!(runner, benchmark_limbs_div_limb_mod); register_bench!(runner, benchmark_limbs_div_limb_to_out_mod_algorithms); register_bench!(runner, benchmark_limbs_div_limb_in_place_mod_algorithms); register_bench!(runner, benchmark_limbs_div_mod_extra); register_bench!(runner, benchmark_limbs_div_mod_extra_in_place); register_bench!(runner, benchmark_limbs_div_mod_by_two_limb_normalized); register_bench!(runner, benchmark_limbs_div_mod_schoolbook); register_bench!( runner, benchmark_limbs_div_mod_divide_and_conquer_algorithms ); register_bench!(runner, benchmark_limbs_invert_basecase_approx); register_bench!(runner, benchmark_limbs_invert_newton_approx_algorithms); register_bench!(runner, benchmark_limbs_invert_approx_algorithms); register_bench!(runner, benchmark_limbs_div_mod_barrett); register_bench!( runner, benchmark_limbs_div_mod_divide_and_conquer_to_barrett_algorithms ); register_bench!(runner, benchmark_limbs_div_mod_barrett_product_algorithms); register_bench!(runner, benchmark_limbs_div_mod_barrett_helper_algorithms); register_bench!(runner, benchmark_limbs_div_mod); register_bench!(runner, benchmark_limbs_div_mod_to_out); register_bench!(runner, benchmark_natural_div_assign_mod_evaluation_strategy); register_bench!(runner, benchmark_natural_div_mod_library_comparison); register_bench!(runner, benchmark_natural_div_mod_algorithms); register_bench!(runner, benchmark_natural_div_mod_evaluation_strategy); register_bench!(runner, benchmark_natural_div_assign_rem_evaluation_strategy); register_bench!(runner, benchmark_natural_div_rem_library_comparison); register_bench!(runner, benchmark_natural_div_rem_evaluation_strategy); register_bench!( runner, benchmark_natural_ceiling_div_assign_neg_mod_evaluation_strategy ); register_bench!( runner, benchmark_natural_ceiling_div_neg_mod_library_comparison ); register_bench!(runner, benchmark_natural_ceiling_div_neg_mod_algorithms); register_bench!( runner, benchmark_natural_ceiling_div_neg_mod_evaluation_strategy ); } fn demo_limbs_invert_limb(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_12().get(gm, config).take(limit) { println!( "limbs_invert_limb({}) = {}", x, limbs_invert_limb::(x) ); } } fn demo_limbs_div_limb_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_div_limb_mod({:?}, {}) = {:?}", xs, y, limbs_div_limb_mod(&xs, y) ); } } fn demo_limbs_div_limb_to_out_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13() .get(gm, config) .take(limit) { let out_old = out.clone(); let remainder = limbs_div_limb_to_out_mod(&mut out, &xs, y); println!( "out := {out_old:?}; limbs_div_limb_to_out_mod(&mut out, {xs:?}, {y}) = {remainder}; \ out = {out:?}", ); } } fn demo_limbs_div_limb_in_place_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let remainder = limbs_div_limb_in_place_mod(&mut xs, y); println!( "limbs := {xs_old:?}; limbs_div_limb_in_place_mod(&mut limbs, {y}) = {remainder}; \ limbs = {xs:?}", ); } } fn demo_limbs_div_mod_extra(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, fraction_len, ns, d, d_inv, shift) in large_type_gen_var_19().get(gm, config).take(limit) { let out_old = out.clone(); let remainder = limbs_div_mod_extra(&mut out, fraction_len, &ns, d, d_inv, shift); println!( "out := {out_old:?}; \ limbs_div_mod_extra(&mut out, {fraction_len}, {ns:?}, {d}, {d_inv}, {shift}) = \ {remainder}; out = {out:?}", ); } } fn demo_limbs_div_mod_extra_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut ns, fraction_len, d, d_inv, shift) in large_type_gen_var_18().get(gm, config).take(limit) { let ns_old = ns.clone(); let remainder = limbs_div_mod_extra_in_place(&mut ns, fraction_len, d, d_inv, shift); println!( "ns := {ns_old:?}; \ limbs_div_mod_extra_in_place(&mut ns, {fraction_len}, {d}, {d_inv}, {shift}) = \ {remainder}; ns = {ns:?}", ); } } fn demo_limbs_two_limb_inverse_helper(gm: GenMode, config: &GenConfig, limit: usize) { for (hi, lo) in unsigned_pair_gen_var_35().get(gm, config).take(limit) { println!( "limbs_two_limb_inverse_helper({}, {}) = {}", hi, lo, limbs_two_limb_inverse_helper(hi, lo) ); } } fn demo_limbs_div_mod_three_limb_by_two_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (n2, n1, n0, d1, d0, inverse) in unsigned_sextuple_gen_var_2().get(gm, config).take(limit) { println!( "limbs_div_mod_three_limb_by_two_limb({}, {}, {}, {}, {}, {}) = {:?}", n2, n1, n0, d1, d0, inverse, limbs_div_mod_three_limb_by_two_limb(n2, n1, n0, d1, d0, inverse) ); } } fn demo_limbs_div_mod_by_two_limb_normalized(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds) in unsigned_vec_triple_gen_var_53().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, &ds); println!( "qs := {old_qs:?}; ns := {old_ns:?}; \ limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, {ds:?}) = {highest_q}; \ qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_div_mod_schoolbook(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_11().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; \ ns := {old_ns:?}; \ limbs_div_mod_schoolbook(&mut qs, &mut ns, {ds:?}, {inverse}) = {highest_q}; \ qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_div_mod_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_12().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); let highest_q = limbs_div_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; ns := {old_ns:?}; \ limbs_div_mod_divide_and_conquer(&mut qs, &mut ns, {ds:?}, {inverse}) = {highest_q}; \ qs = {qs:?}, ns = {ns:?}", ); } } fn demo_limbs_invert_basecase_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut is, ds, mut scratch) in unsigned_vec_triple_gen_var_50().get(gm, config).take(limit) { let old_is = is.clone(); let old_scratch = scratch.clone(); let result_definitely_exact = limbs_invert_basecase_approx(&mut is, &ds, &mut scratch); println!( "is := {old_is:?}; scratch := {old_scratch:?}; \ limbs_invert_basecase_approx(&mut is, {ds:?}, &mut scratch) = \ {result_definitely_exact}; \ is = {is:?}, scratch = {scratch:?}", ); } } fn demo_limbs_invert_newton_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut is, ds, mut scratch) in unsigned_vec_triple_gen_var_51().get(gm, config).take(limit) { let old_is = is.clone(); let old_scratch = scratch.clone(); let result_definitely_exact = limbs_invert_newton_approx(&mut is, &ds, &mut scratch); println!( "is := {old_is:?}; scratch := {old_scratch:?}; \ limbs_invert_newton_approx(&mut is, {ds:?}, &mut scratch) = \ {result_definitely_exact}; \ is = {is:?}, scratch = {scratch:?}", ); } } fn demo_limbs_invert_approx(gm: GenMode, config: &GenConfig, limit: usize) { for (mut is, ds, mut scratch) in unsigned_vec_triple_gen_var_50().get(gm, config).take(limit) { let old_is = is.clone(); let old_scratch = scratch.clone(); let result_definitely_exact = limbs_invert_approx(&mut is, &ds, &mut scratch); println!( "is := {old_is:?}; scratch := {old_scratch:?}; \ limbs_invert_approx(&mut is, {ds:?}, &mut scratch) = {result_definitely_exact}; \ is = {is:?}, scratch = {scratch:?}", ); } } fn demo_limbs_div_mod_barrett(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut rs, ns, ds) in unsigned_vec_quadruple_gen_var_5() .get(gm, config) .take(limit) { let old_qs = qs.clone(); let old_rs = rs.clone(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let highest_q = limbs_div_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); println!( "qs := {old_qs:?}; \ rs := {old_rs:?}; \ limbs_div_mod_barrett(&mut qs, &mut ns, {ns:?}, {ds:?}) = {highest_q}; \ qs = {qs:?}, rs = {rs:?}", ); } } fn demo_limbs_div_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_11().get(gm, config).take(limit) { println!( "limbs_div_mod({:?}, {:?}) = {:?}", ns, ds, limbs_div_mod(&ns, &ds) ); } } fn demo_limbs_div_mod_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut rs, ns, ds) in unsigned_vec_quadruple_gen_var_1() .get(gm, config) .take(limit) { let old_qs = qs.clone(); let old_rs = rs.clone(); limbs_div_mod_to_out(&mut qs, &mut rs, &ns, &ds); println!( "qs := {old_qs:?}; \ rs := {old_rs:?}; limbs_div_mod_to_out(&mut qs, &mut ns, {ns:?}, {ds:?}); \ qs = {qs:?}, rs = {rs:?}", ); } } fn demo_natural_div_assign_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.div_assign_mod(y); println!("x := {x_old}; x.div_assign_mod({y_old}) = {remainder}; x = {x}"); } } fn demo_natural_div_assign_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.div_assign_mod(&y); println!("x := {x_old}; x.div_assign_mod(&{y}) = {remainder}; x = {x}"); } } fn demo_natural_div_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_mod({}) = {:?}", x_old, y_old, x.div_mod(y)); } } fn demo_natural_div_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_mod(&{}) = {:?}", x_old, y, x.div_mod(&y)); } } fn demo_natural_div_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_mod({}) = {:?}", x, y_old, (&x).div_mod(y)); } } fn demo_natural_div_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("(&{}).div_mod(&{}) = {:?}", x, y, (&x).div_mod(&y)); } } fn demo_natural_div_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.div_assign_rem(y); println!("x := {x_old}; x.div_assign_rem({y_old}) = {remainder}; x = {x}"); } } fn demo_natural_div_assign_rem_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.div_assign_rem(&y); println!("x := {x_old}; x.div_assign_rem(&{y}) = {remainder}; x = {x}"); } } fn demo_natural_div_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.div_rem({}) = {:?}", x_old, y_old, x.div_rem(y)); } } fn demo_natural_div_rem_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.div_rem(&{}) = {:?}", x_old, y, x.div_rem(&y)); } } fn demo_natural_div_rem_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).div_rem({}) = {:?}", x, y_old, (&x).div_rem(y)); } } fn demo_natural_div_rem_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("(&{}).div_rem(&{}) = {:?}", x, y, (&x).div_rem(&y)); } } fn demo_natural_ceiling_div_assign_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let remainder = x.ceiling_div_assign_neg_mod(y); println!("x := {x_old}; x.ceiling_div_assign_neg_mod({y_old}) = {remainder}; x = {x}"); } } fn demo_natural_ceiling_div_assign_neg_mod_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let remainder = x.ceiling_div_assign_neg_mod(&y); println!("x := {x_old}; x.ceiling_div_assign_neg_mod(&{y}) = {remainder}; x = {x}"); } } fn demo_natural_ceiling_div_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.ceiling_div_neg_mod({}) = {:?}", x_old, y_old, x.ceiling_div_neg_mod(y) ); } } fn demo_natural_ceiling_div_neg_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.ceiling_div_neg_mod(&{}) = {:?}", x_old, y, x.ceiling_div_neg_mod(&y) ); } } fn demo_natural_ceiling_div_neg_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).ceiling_div_neg_mod({}) = {:?}", x, y_old, (&x).ceiling_div_neg_mod(y) ); } } fn demo_natural_ceiling_div_neg_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!( "(&{}).ceiling_div_neg_mod(&{}) = {:?}", x, y, (&x).ceiling_div_neg_mod(&y) ); } } fn benchmark_limbs_invert_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_invert_limb(Limb)", BenchmarkType::Single, unsigned_gen_var_12().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |x| { no_out!(limbs_invert_limb::(x)); })], ); } fn benchmark_limbs_div_limb_mod(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_limb_mod(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_div_limb_mod(&xs, y)); })], ); } fn benchmark_limbs_div_limb_to_out_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_limb_to_out_mod(&mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut out, xs, y)| { no_out!(limbs_div_limb_to_out_mod(&mut out, &xs, y)); }), ("alt", &mut |(mut out, xs, y)| { no_out!(limbs_div_limb_to_out_mod_alt(&mut out, &xs, y)); }), ("naive", &mut |(mut out, xs, y)| { no_out!(limbs_div_limb_to_out_mod_naive(&mut out, &xs, y)); }), ], ); } fn benchmark_limbs_div_limb_in_place_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_limb_in_place_mod(&mut [Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut xs, y)| { no_out!(limbs_div_limb_in_place_mod(&mut xs, y)); }), ("alt", &mut |(mut xs, y)| { no_out!(limbs_div_limb_in_place_mod_alt(&mut xs, y)); }), ("naive", &mut |(mut xs, y)| { no_out!(limbs_div_limb_in_place_mod_naive(&mut xs, y)); }), ], ); } fn benchmark_limbs_div_mod_extra(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_mod_extra(&mut [Limb], usize, &[Limb], Limb, Limb, u64)", BenchmarkType::Single, large_type_gen_var_19().get(gm, config), gm.name(), limit, file_name, &limbs_div_mod_extra_bucketer(), &mut [("Malachite", &mut |( mut out, fraction_len, ns, d, d_inv, shift, )| { no_out!(limbs_div_mod_extra( &mut out, fraction_len, &ns, d, d_inv, shift )); })], ); } fn benchmark_limbs_div_mod_extra_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_extra(&mut [Limb], usize, Limb, Limb, u64)", BenchmarkType::Single, large_type_gen_var_18().get(gm, config), gm.name(), limit, file_name, &quintuple_1_vec_len_bucketer("out"), &mut [("Malachite", &mut |( mut ns, fraction_len, d, d_inv, shift, )| { no_out!(limbs_div_mod_extra_in_place( &mut ns, fraction_len, d, d_inv, shift )); })], ); } fn benchmark_limbs_div_mod_by_two_limb_normalized( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_by_two_limb_normalized(&mut [Limb], &mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_53().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(mut qs, mut ns, ds)| { no_out!(limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, &ds)); })], ); } fn benchmark_limbs_div_mod_schoolbook( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_schoolbook(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Single, large_type_gen_var_11().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse)); })], ); } // use large params fn benchmark_limbs_div_mod_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ("divide-and-conquer", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_div_mod_divide_and_conquer( &mut qs, &mut ns, &ds, inverse )); }), ], ); } fn benchmark_limbs_invert_basecase_approx( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_invert_basecase_approx(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_50().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ds"), &mut [("Malachite", &mut |(mut is, ds, mut scratch)| { no_out!(limbs_invert_basecase_approx(&mut is, &ds, &mut scratch)); })], ); } // use very large params fn benchmark_limbs_invert_newton_approx_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_invert_newton_approx(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_51().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ds"), &mut [ ("basecase", &mut |(mut is, ds, mut scratch)| { no_out!(limbs_invert_basecase_approx(&mut is, &ds, &mut scratch)); }), ("Newton", &mut |(mut is, ds, mut scratch)| { no_out!(limbs_invert_newton_approx(&mut is, &ds, &mut scratch)); }), ], ); } // use very large params fn benchmark_limbs_invert_approx_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_invert_approx(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_50().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ds"), &mut [ ("basecase", &mut |(mut is, ds, mut scratch)| { no_out!(limbs_invert_basecase_approx(&mut is, &ds, &mut scratch)); }), ("default", &mut |(mut is, ds, mut scratch)| { no_out!(limbs_invert_approx(&mut is, &ds, &mut scratch)); }), ], ); } fn benchmark_limbs_div_mod_barrett(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_mod_barrett(&mut [Limb], &mut [Limb], &[Limb], &[Limb], &mut Limb)", BenchmarkType::Single, unsigned_vec_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_4_vec_len_bucketer("ds"), &mut [("Malachite", &mut |(mut qs, mut rs, ns, ds)| { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; no_out!(limbs_div_mod_barrett( &mut qs, &mut rs, &ns, &ds, &mut scratch )); })], ); } // use very large params fn benchmark_limbs_div_mod_divide_and_conquer_to_barrett_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_barrett(&mut [Limb], &mut [Limb], &[Limb], &[Limb], &mut Limb)", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_52::().get(gm, config), gm.name(), limit, file_name, &triple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("divide-and-conquer", &mut |(mut qs, mut ns, mut ds)| { let q_len = ns.len() - ds.len() + 1; ds[q_len - 1].set_bit(Limb::WIDTH - 1); let inverse = limbs_two_limb_inverse_helper(ds[q_len - 1], ds[q_len - 2]); no_out!(limbs_div_mod_divide_and_conquer( &mut qs, &mut ns[..q_len << 1], &ds[..q_len], inverse )); }), ("Barrett", &mut |(mut qs, mut ns, mut ds)| { let d_len = ds.len(); let mut rs = vec![0; d_len]; let q_len = ns.len() - d_len + 1; let q_len_2 = q_len << 1; ds[q_len - 1].set_bit(Limb::WIDTH - 1); limbs_two_limb_inverse_helper(ds[q_len - 1], ds[q_len - 2]); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(q_len_2, q_len)]; limbs_div_mod_barrett(&mut qs, &mut rs, &ns[..q_len_2], &ds[..q_len], &mut scratch); ns[..q_len].copy_from_slice(&rs[..q_len]); }), ], ); } // use large params fn benchmark_limbs_div_mod_barrett_product_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_barrett_large_product(&mut [Limb], &[Limb], &[Limb], &[Limb], usize, usize)", BenchmarkType::Algorithms, large_type_gen_var_20().get(gm, config), gm.name(), limit, file_name, &limbs_div_mod_barrett_product_bucketer(), &mut [ ("limbs_mul_greater_to_out", &mut |( mut scratch, ds, qs, _, _, _, )| { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; no_out!(limbs_mul_greater_to_out( &mut scratch, &ds, &qs, &mut mul_scratch, )); }), ("limbs_div_barrett_large_product", &mut |( mut scratch, ds, qs, rs_hi, scratch_len, i_len, )| { limbs_div_barrett_large_product(&mut scratch, &ds, &qs, &rs_hi, scratch_len, i_len); }), ], ); } fn benchmark_limbs_div_mod_barrett_helper_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_div_mod_barrett_helper(&mut [Limb], &mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_quadruple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &limbs_div_mod_barrett_helper_bucketer(), &mut [ ("limbs_div_mod_barrett_helper", &mut |( mut qs, mut rs, ns, ds, )| { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let q_len = ns.len() - ds.len(); no_out!(limbs_div_mod_barrett_helper( &mut qs[..q_len], &mut rs[..ds.len()], &ns, &ds, &mut scratch )); }), ("limbs_div_mod_barrett_large_helper", &mut |( mut qs, mut rs, ns, ds, )| { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let q_len = ns.len() - ds.len(); no_out!(limbs_div_mod_barrett_large_helper( &mut qs[..q_len], &mut rs[..ds.len()], &ns, &ds, &mut scratch )); }), ], ); } fn benchmark_limbs_div_mod(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_mod(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(ns, ds)| { no_out!(limbs_div_mod(&ns, &ds)); })], ); } fn benchmark_limbs_div_mod_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_div_mod_to_out(&mut [Limb], &mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(mut qs, mut rs, ns, ds)| { limbs_div_mod_to_out(&mut qs, &mut rs, &ns, &ds); })], ); } fn benchmark_natural_div_assign_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_assign_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.div_assign_mod(Natural)", &mut |(mut x, y)| { no_out!(x.div_assign_mod(y)); }), ("Natural.div_mod(&Natural)", &mut |(mut x, y)| { no_out!(x.div_assign_mod(&y)); }), ], ); } fn benchmark_natural_div_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_mod(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_mod(y))), ("num", &mut |((x, y), _, _)| no_out!(x.div_mod_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_rem_floor(y))), ], ); } #[allow(clippy::no_effect)] fn benchmark_natural_div_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_mod(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.div_mod(y))), ("using / and %", &mut |(x, y)| no_out!((&x / &y, x % y))), ], ); } fn benchmark_natural_div_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.div_mod(Natural)", &mut |(x, y)| { no_out!(x.div_mod(y)); }), ("Natural.div_mod(&Natural)", &mut |(x, y)| { no_out!(x.div_mod(&y)); }), ("(&Natural).div_mod(Natural)", &mut |(x, y)| { no_out!((&x).div_mod(y)); }), ("(&Natural).div_mod(&Natural)", &mut |(x, y)| { no_out!((&x).div_mod(&y)); }), ], ); } fn benchmark_natural_div_assign_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_assign_rem(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.div_assign_rem(Natural)", &mut |(mut x, y)| { no_out!(x.div_assign_rem(y)); }), ("Natural.div_assign_rem(&Natural)", &mut |(mut x, y)| { no_out!(x.div_assign_rem(&y)); }), ], ); } fn benchmark_natural_div_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_rem(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.div_rem(y))), ("num", &mut |((x, y), _, _)| no_out!(x.div_rem(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_rem(y))), ], ); } fn benchmark_natural_div_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.div_rem(Natural)", &mut |(x, y)| { no_out!(x.div_rem(y)); }), ("Natural.div_rem(&Natural)", &mut |(x, y)| { no_out!(x.div_rem(&y)); }), ("(&Natural).div_rem(Natural)", &mut |(x, y)| { no_out!((&x).div_rem(y)); }), ("(&Natural).div_rem(&Natural)", &mut |(x, y)| { no_out!((&x).div_rem(&y)); }), ], ); } fn benchmark_natural_ceiling_div_assign_neg_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_div_assign_neg_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ( "Natural.ceiling_div_assign_neg_mod(Natural)", &mut |(mut x, y)| no_out!(x.ceiling_div_assign_neg_mod(y)), ), ( "Natural.ceiling_div_assign_neg_mod(&Natural)", &mut |(mut x, y)| no_out!(x.ceiling_div_assign_neg_mod(&y)), ), ], ); } fn benchmark_natural_ceiling_div_neg_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_div_neg_mod(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.ceiling_div_neg_mod(y)); }), ("rug", &mut |((x, y), _)| { no_out!(rug_ceiling_div_neg_mod(x, y)); }), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_ceiling_div_neg_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_div_neg_mod(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.ceiling_div_neg_mod(y))), ("using div_round and %", &mut |(x, y)| { ((&x).div_round(&y, Ceiling), x.neg_mod(y)); }), ], ); } fn benchmark_natural_ceiling_div_neg_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_div_neg_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.ceiling_div_neg_mod(Natural)", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(y)); }), ("Natural.ceiling_div_neg_mod(&Natural)", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(&y)); }), ("(&Natural).ceiling_div_neg_mod(Natural)", &mut |(x, y)| { no_out!((&x).ceiling_div_neg_mod(y)); }), ("(&Natural).ceiling_div_neg_mod(&Natural)", &mut |(x, y)| { no_out!((&x).ceiling_div_neg_mod(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingDivNegMod, DivRound, DivRoundAssign}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::bucketers::triple_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_rounding_mode_triple_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::div_round::limbs_limb_div_round_limbs; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, triple_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_natural_rounding_mode_triple_gen_var_1, natural_pair_gen_var_5, natural_pair_gen_var_5_nrm, natural_pair_gen_var_5_rm, }; use num::Integer; use rug::ops::DivRounding; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_limb_div_round_limbs); register_demo!(runner, demo_natural_div_round); register_demo!(runner, demo_natural_div_round_val_ref); register_demo!(runner, demo_natural_div_round_ref_val); register_demo!(runner, demo_natural_div_round_ref_ref); register_demo!(runner, demo_natural_div_round_assign); register_demo!(runner, demo_natural_div_round_assign_ref); register_bench!(runner, benchmark_limbs_limb_div_round_limbs); register_bench!(runner, benchmark_natural_div_round_down_library_comparison); register_bench!(runner, benchmark_natural_div_round_floor_library_comparison); register_bench!( runner, benchmark_natural_div_round_ceiling_library_comparison ); register_bench!(runner, benchmark_natural_div_round_ceiling_algorithms); register_bench!( runner, benchmark_natural_div_round_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_div_round_evaluation_strategy); } fn demo_limbs_limb_div_round_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for (ys, x, rm) in unsigned_vec_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "limbs_limb_div_round_limbs({}, {:?}, {}) = {:?}", x, ys, rm, limbs_limb_div_round_limbs(x, &ys, rm) ); } } fn demo_natural_div_round(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.div_round({}, {}) = {:?}", x_old, y_old, rm, x.div_round(y, rm) ); } } fn demo_natural_div_round_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{}.div_round(&{}, {}) = {:?}", x_old, y, rm, x.div_round(&y, rm) ); } } fn demo_natural_div_round_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).div_round({}, {}) = {:?}", x, y_old, rm, (&x).div_round(y, rm) ); } } fn demo_natural_div_round_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).div_round(&{}, {}) = {:?}", x, y, rm, (&x).div_round(&y, rm) ); } } fn demo_natural_div_round_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.div_round_assign(y, rm); println!("x := {x_old}; x.div_round_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_natural_div_round_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in natural_natural_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.div_round_assign(&y, rm); println!("x := {x_old}; x.div_round_assign(&{y}, {rm}) = {o:?}; x = {x}"); } } fn benchmark_limbs_limb_div_round_limbs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_limb_div_round_limbs(Limb, &[Limb], RoundingMode)", BenchmarkType::Single, unsigned_vec_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("ys"), &mut [("Malachite", &mut |(ys, x, rm)| { no_out!(limbs_limb_div_round_limbs(x, &ys, rm)); })], ); } fn benchmark_natural_div_round_down_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round(Natural, Down)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.div_round(y, Down)); }), ("rug", &mut |((x, y), _)| no_out!(x.div_trunc(y))), ], ); } fn benchmark_natural_div_round_floor_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round(Natural, Floor)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.div_round(y, Floor)); }), ("num", &mut |((x, y), _, _)| no_out!(x.div_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.div_floor(y))), ], ); } fn benchmark_natural_div_round_ceiling_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round(Natural, Ceiling)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.div_round(y, Ceiling)); }), ("rug", &mut |((x, y), _)| no_out!(x.div_ceil(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_div_round_ceiling_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round(Natural, Ceiling)", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("standard", &mut |(x, y)| no_out!(x.div_round(y, Ceiling))), ("using ceiling_div_neg_mod", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(y).0); }), ], ); } fn benchmark_natural_div_round_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round_assign(Natural, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_natural_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [ ( "Natural.div_round_assign(Natural, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign(y, rm)), ), ( "Natural.div_round_assign(&Natural, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.div_round_assign(&y, rm)), ), ], ); } fn benchmark_natural_div_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.div_round(Natural, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_natural_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [ ( "Natural.div_round(Natural, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round(y, rm)), ), ( "Natural.div_round(&Natural, RoundingMode)", &mut |(x, y, rm)| no_out!(x.div_round(&y, rm)), ), ( "(&Natural).div_round(Natural, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).div_round(y, rm)), ), ( "(&Natural).div_round(&Natural, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).div_round(&y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::slices::slice_test_zero; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_15, unsigned_vec_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_22, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::divisible_by::{ limbs_divisible_by, limbs_divisible_by_limb, limbs_divisible_by_ref_ref, limbs_divisible_by_ref_val, limbs_divisible_by_val_ref, }; use malachite_nz::natural::arithmetic::mod_op::{limbs_mod, limbs_mod_limb}; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_nrm}; use malachite_nz::test_util::natural::arithmetic::divisible_by::{ combined_limbs_divisible_by_limb, num_divisible_by, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_divisible_by_limb); register_demo!(runner, demo_limbs_divisible_by); register_demo!(runner, demo_limbs_divisible_by_val_ref); register_demo!(runner, demo_limbs_divisible_by_ref_val); register_demo!(runner, demo_limbs_divisible_by_ref_ref); register_demo!(runner, demo_natural_divisible_by); register_demo!(runner, demo_natural_divisible_by_val_ref); register_demo!(runner, demo_natural_divisible_by_ref_val); register_demo!(runner, demo_natural_divisible_by_ref_ref); register_bench!(runner, benchmark_limbs_divisible_by_limb_algorithms); register_bench!(runner, benchmark_limbs_divisible_by_algorithms); register_bench!(runner, benchmark_limbs_divisible_by_evaluation_strategy); register_bench!(runner, benchmark_natural_divisible_by_algorithms); register_bench!(runner, benchmark_natural_divisible_by_evaluation_strategy); register_bench!(runner, benchmark_natural_divisible_by_library_comparison); } fn demo_limbs_divisible_by_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_divisible_by_limb({:?}, {}) = {}", xs, y, limbs_divisible_by_limb(&xs, y) ); } } fn demo_limbs_divisible_by(gm: GenMode, config: &GenConfig, limit: usize) { for (mut ns, mut ds) in unsigned_vec_pair_gen_var_15().get(gm, config).take(limit) { let ns_old = ns.clone(); let ds_old = ds.clone(); println!( "limbs_divisible_by({:?}, {:?}) = {}", ns_old, ds_old, limbs_divisible_by(&mut ns, &mut ds) ); } } fn demo_limbs_divisible_by_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut ns, ds) in unsigned_vec_pair_gen_var_15().get(gm, config).take(limit) { let ns_old = ns.clone(); println!( "limbs_divisible_by_val_ref({:?}, {:?}) = {}", ns_old, ds, limbs_divisible_by_val_ref(&mut ns, &ds) ); } } fn demo_limbs_divisible_by_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, mut ds) in unsigned_vec_pair_gen_var_15().get(gm, config).take(limit) { let ds_old = ds.clone(); println!( "limbs_divisible_by_ref_val({:?}, {:?}) = {}", ns, ds_old, limbs_divisible_by_ref_val(&ns, &mut ds) ); } } fn demo_limbs_divisible_by_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_15().get(gm, config).take(limit) { println!( "limbs_divisible_by_ref_ref({:?}, {:?}) = {}", ns, ds, limbs_divisible_by_ref_ref(&ns, &ds) ); } } fn demo_natural_divisible_by(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); if x.divisible_by(y) { println!("{x_old} is divisible by {y_old}"); } else { println!("{x_old} is not divisible by {y_old}"); } } } fn demo_natural_divisible_by_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); if x.divisible_by(&y) { println!("{x_old} is divisible by {y}"); } else { println!("{x_old} is not divisible by {y}"); } } } fn demo_natural_divisible_by_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); if (&x).divisible_by(y) { println!("{x} is divisible by {y_old}"); } else { println!("{x} is not divisible by {y_old}"); } } } fn demo_natural_divisible_by_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); if (&x).divisible_by(y) { println!("{x} is divisible by {y_old}"); } else { println!("{x} is not divisible by {y_old}"); } } } // use large params #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_limbs_divisible_by_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_divisible_by_limb(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("limbs_divisible_by_limb", &mut |(xs, y)| { no_out!(limbs_divisible_by_limb(&xs, y)); }), ("divisibility using limbs_mod_limb", &mut |(xs, y)| { no_out!(limbs_mod_limb::(&xs, y) == 0); }), ("combined_limbs_divisible_by_limb", &mut |(xs, y)| { no_out!(combined_limbs_divisible_by_limb(&xs, y)); }), ], ); } // use large params fn benchmark_limbs_divisible_by_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_divisible_by(&[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("limbs_divisible_by", &mut |(mut ns, mut ds)| { no_out!(limbs_divisible_by(&mut ns, &mut ds)); }), ("divisibility using limbs_mod", &mut |(ns, ds)| { no_out!(slice_test_zero(&limbs_mod(&ns, &ds))); }), ], ); } // use large params fn benchmark_limbs_divisible_by_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_divisible_by(&[Limb], &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ( "limbs_divisible_by(&mut [Limb], &mut [Limb])", &mut |(mut ns, mut ds)| no_out!(limbs_divisible_by(&mut ns, &mut ds)), ), ( "limbs_divisible_by_val_ref(&mut [Limb], &mut [Limb])", &mut |(mut ns, ds)| no_out!(limbs_divisible_by_val_ref(&mut ns, &ds)), ), ( "limbs_divisible_by_ref_val(&mut [Limb], &mut [Limb])", &mut |(ns, mut ds)| no_out!(limbs_divisible_by_ref_val(&ns, &mut ds)), ), ( "limbs_divisible_by_ref_ref(&mut [Limb], &mut [Limb])", &mut |(ns, ds)| no_out!(limbs_divisible_by_ref_ref(&ns, &ds)), ), ], ); } #[allow(clippy::no_effect, clippy::short_circuit_statement, unused_must_use)] fn benchmark_natural_divisible_by_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.divisible_by(Natural)", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("standard", &mut |(x, y)| no_out!(x.divisible_by(y))), ("using %", &mut |(x, y)| { no_out!(x == 0 || y != 0 && x % y == 0); }), ], ); } fn benchmark_natural_divisible_by_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.divisible_by(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.divisible_by(Natural)", &mut |(x, y)| { no_out!(x.divisible_by(y)); }), ("Natural.divisible_by(&Natural)", &mut |(x, y)| { no_out!(x.divisible_by(&y)); }), ("(&Natural).divisible_by(Natural)", &mut |(x, y)| { no_out!((&x).divisible_by(y)); }), ("(&Natural).divisible_by(&Natural)", &mut |(x, y)| { no_out!((&x).divisible_by(&y)); }), ], ); } fn benchmark_natural_divisible_by_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.divisible_by(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.divisible_by(y)); }), ("num", &mut |((x, y), _, _)| { no_out!(num_divisible_by(&x, &y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x.is_divisible(&y))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_20, unsigned_vec_unsigned_pair_gen_var_22, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_divisible_by_power_of_2); register_demo!(runner, demo_natural_divisible_by_power_of_2); register_bench!(runner, benchmark_limbs_divisible_by_power_of_2); register_bench!( runner, benchmark_natural_divisible_by_power_of_2_library_comparison ); register_bench!(runner, benchmark_natural_divisible_by_power_of_2_algorithms); } fn demo_limbs_divisible_by_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_divisible_by_power_of_2({:?}, {}) = {:?}", xs, pow, limbs_divisible_by_power_of_2(&xs, pow) ); } } fn demo_natural_divisible_by_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { if n.divisible_by_power_of_2(pow) { println!("{n} is divisible by 2^{pow}"); } else { println!("{n} is not divisible by 2^{pow}"); } } } fn benchmark_limbs_divisible_by_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_divisible_by_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_divisible_by_power_of_2(&xs, pow)); })], ); } fn benchmark_natural_divisible_by_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.divisible_by_power_of_2(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (n, pow))| { no_out!(n.divisible_by_power_of_2(pow)); }), ("rug", &mut |((n, pow), _)| { n.is_divisible_2pow(u32::exact_from(pow)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_divisible_by_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.divisible_by_power_of_2(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.divisible_by_power_of_2(u64)", &mut |(n, pow)| { no_out!(n.divisible_by_power_of_2(pow)); }), ( "Natural.trailing_zeros().map_or(true, |z| z >= u64)", &mut |(n, pow)| no_out!(n.trailing_zeros().is_none_or(|z| z >= pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, EqMod, UnsignedAbs}; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_1_bit_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_21, unsigned_vec_triple_gen_var_36, unsigned_vec_unsigned_unsigned_triple_gen_var_7, unsigned_vec_unsigned_unsigned_triple_gen_var_10, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::natural::arithmetic::eq_mod::{ limbs_eq_limb_mod, limbs_eq_limb_mod_limb, limbs_eq_limb_mod_ref_ref, limbs_eq_limb_mod_ref_val, limbs_eq_limb_mod_val_ref, limbs_eq_mod_limb_ref_ref, limbs_eq_mod_limb_ref_val, limbs_eq_mod_limb_val_ref, limbs_eq_mod_ref_ref_ref, limbs_eq_mod_ref_ref_val, limbs_eq_mod_ref_val_ref, limbs_eq_mod_ref_val_val, limbs_limb_mod_exact_odd_limb, limbs_mod_exact_odd_limb, }; use malachite_nz::natural::arithmetic::mod_op::limbs_mod_limb; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ pair_2_triple_1_2_natural_max_bit_bucketer, triple_1_2_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_triple_gen, natural_triple_gen_rm}; use malachite_nz::test_util::natural::arithmetic::eq_mod::{ combined_limbs_eq_limb_mod_limb, limbs_eq_limb_mod_naive_1, limbs_eq_limb_mod_naive_2, limbs_eq_mod_limb_naive_1, limbs_eq_mod_limb_naive_2, limbs_eq_mod_naive_1, limbs_eq_mod_naive_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_limb_mod_exact_odd_limb); register_demo!(runner, demo_limbs_mod_exact_odd_limb); register_demo!(runner, demo_limbs_eq_limb_mod_limb); register_demo!(runner, demo_limbs_eq_limb_mod); register_demo!(runner, demo_limbs_eq_limb_mod_val_ref); register_demo!(runner, demo_limbs_eq_limb_mod_ref_val); register_demo!(runner, demo_limbs_eq_limb_mod_ref_ref); register_demo!(runner, demo_limbs_eq_mod_limb_val_ref); register_demo!(runner, demo_limbs_eq_mod_limb_ref_val); register_demo!(runner, demo_limbs_eq_mod_limb_ref_ref); register_demo!(runner, demo_limbs_eq_mod_ref_val_val); register_demo!(runner, demo_limbs_eq_mod_ref_val_ref); register_demo!(runner, demo_limbs_eq_mod_ref_ref_val); register_demo!(runner, demo_limbs_eq_mod_ref_ref_ref); register_demo!(runner, demo_natural_eq_mod); register_demo!(runner, demo_natural_eq_mod_val_val_ref); register_demo!(runner, demo_natural_eq_mod_val_ref_val); register_demo!(runner, demo_natural_eq_mod_val_ref_ref); register_demo!(runner, demo_natural_eq_mod_ref_val_val); register_demo!(runner, demo_natural_eq_mod_ref_val_ref); register_demo!(runner, demo_natural_eq_mod_ref_ref_val); register_demo!(runner, demo_natural_eq_mod_ref_ref_ref); register_bench!(runner, benchmark_limbs_limb_mod_exact_odd_limb); register_bench!(runner, benchmark_limbs_mod_exact_odd_limb); register_bench!(runner, benchmark_limbs_eq_limb_mod_limb_algorithms); register_bench!(runner, benchmark_limbs_eq_limb_mod_evaluation_strategy); register_bench!(runner, benchmark_limbs_eq_limb_mod_algorithms); register_bench!(runner, benchmark_limbs_eq_mod_limb_evaluation_strategy); register_bench!(runner, benchmark_limbs_eq_mod_limb_algorithms); register_bench!(runner, benchmark_limbs_eq_mod_evaluation_strategy); register_bench!(runner, benchmark_limbs_eq_mod_algorithms); register_bench!(runner, benchmark_natural_eq_mod_evaluation_strategy); register_bench!(runner, benchmark_natural_eq_mod_library_comparison); register_bench!(runner, benchmark_natural_eq_mod_algorithms); } fn demo_limbs_limb_mod_exact_odd_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d, carry) in unsigned_triple_gen_var_21().get(gm, config).take(limit) { println!( "limbs_limb_mod_exact_odd_limb({}, {}, {}) = {}", n, d, carry, limbs_limb_mod_exact_odd_limb(n, d, carry) ); } } fn demo_limbs_mod_exact_odd_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d, carry) in unsigned_vec_unsigned_unsigned_triple_gen_var_10() .get(gm, config) .take(limit) { println!( "limbs_mod_exact_odd_limb({:?}, {}, {}) = {}", ns, d, carry, limbs_mod_exact_odd_limb(&ns, d, carry) ); } } fn demo_limbs_eq_limb_mod_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y, m) in unsigned_vec_unsigned_unsigned_triple_gen_var_7() .get(gm, config) .take(limit) { println!( "limbs_eq_limb_mod_limb({:?}, {}, {}) = {}", xs, y, m, limbs_eq_limb_mod_limb(&xs, y, m) ); } } fn demo_limbs_eq_limb_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ms, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_xs = xs.clone(); let old_ms = ms.clone(); println!( "limbs_eq_limb_mod({:?}, {}, {:?}) = {}", old_xs, y, old_ms, limbs_eq_limb_mod(&mut xs, y, &mut ms) ); } } fn demo_limbs_eq_limb_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ms, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_xs = xs.clone(); println!( "limbs_eq_limb_mod_val_ref({:?}, {}, {:?}) = {}", old_xs, y, ms, limbs_eq_limb_mod_val_ref(&mut xs, y, &ms) ); } } fn demo_limbs_eq_limb_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ms, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_ms = ms.clone(); println!( "limbs_eq_limb_mod_ref_val({:?}, {}, {:?}) = {}", xs, y, old_ms, limbs_eq_limb_mod_ref_val(&xs, y, &mut ms) ); } } fn demo_limbs_eq_limb_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ms, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "limbs_eq_limb_mod_ref_ref({:?}, {}, {:?}) = {}", xs, y, ms, limbs_eq_limb_mod_ref_ref(&xs, y, &ms) ); } } fn demo_limbs_eq_mod_limb_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, m) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_xs = xs.clone(); println!( "limbs_eq_mod_limb_val_ref({:?}, {:?}, {}) = {}", old_xs, ys, m, limbs_eq_mod_limb_val_ref(&mut xs, &ys, m) ); } } fn demo_limbs_eq_mod_limb_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, m) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { let old_ys = ys.clone(); println!( "limbs_eq_mod_limb_ref_val({:?}, {:?}, {}) = {}", xs, old_ys, m, limbs_eq_mod_limb_ref_val(&xs, &mut ys, m) ); } } fn demo_limbs_eq_mod_limb_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, m) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6() .get(gm, config) .take(limit) { println!( "limbs_eq_mod_limb_ref_ref({:?}, {:?}, {}) = {}", xs, ys, m, limbs_eq_mod_limb_ref_ref(&xs, &ys, m) ); } } fn demo_limbs_eq_mod_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, mut ms) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { let old_ys = ys.clone(); let old_ms = ms.clone(); println!( "limbs_eq_mod_ref_val_val({:?}, {:?}, {:?}) = {}", xs, old_ys, old_ms, limbs_eq_mod_ref_val_val(&xs, &mut ys, &mut ms) ); } } fn demo_limbs_eq_mod_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, ms) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { let old_ys = ys.clone(); println!( "limbs_eq_mod_ref_val_ref({:?}, {:?}, {:?}) = {}", xs, old_ys, ms, limbs_eq_mod_ref_val_ref(&xs, &mut ys, &ms) ); } } fn demo_limbs_eq_mod_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, mut ms) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { let old_ms = ms.clone(); println!( "limbs_eq_mod_ref_ref_val({:?}, {:?}, {:?}) = {}", xs, ys, old_ms, limbs_eq_mod_ref_ref_val(&xs, &ys, &mut ms) ); } } fn demo_limbs_eq_mod_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, ms) in unsigned_vec_triple_gen_var_36().get(gm, config).take(limit) { println!( "limbs_eq_mod_ref_ref_ref({:?}, {:?}, {:?}) = {}", xs, ys, ms, limbs_eq_mod_ref_ref_ref(&xs, &ys, &ms) ); } } fn demo_natural_eq_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); if x.eq_mod(y, m) { println!("{x_old} is equal to {y_old} mod {m_old}"); } else { println!("{x_old} is not equal to {y_old} mod {m_old}"); } } } fn demo_natural_eq_mod_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); if x.eq_mod(y, &m) { println!("{x_old} is equal to {y_old} mod &{m}"); } else { println!("{x_old} is not equal to {y_old} mod &{m}"); } } } fn demo_natural_eq_mod_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); if x.eq_mod(&y, m) { println!("{x_old} is equal to &{y} mod {m_old}"); } else { println!("{x_old} is not equal to &{y} mod {m_old}"); } } } fn demo_natural_eq_mod_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); if x.eq_mod(&y, &m) { println!("{x_old} is equal to &{y} mod &{m}"); } else { println!("{x_old} is not equal to &{y} mod &{m}"); } } } fn demo_natural_eq_mod_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let y_old = y.clone(); let m_old = m.clone(); if (&x).eq_mod(y, m) { println!("&{x} is equal to {y_old} mod {m_old}"); } else { println!("&{x} is not equal to {y_old} mod {m_old}"); } } } fn demo_natural_eq_mod_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let y_old = y.clone(); if (&x).eq_mod(y, &m) { println!("&{x} is equal to {y_old} mod &{m}"); } else { println!("&{x} is not equal to {y_old} mod &{m}"); } } } fn demo_natural_eq_mod_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { let m_old = m.clone(); if (&x).eq_mod(&y, m) { println!("&{x} is equal to &{y} mod {m_old}"); } else { println!("&{x} is not equal to &{y} mod {m_old}"); } } } fn demo_natural_eq_mod_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen().get(gm, config).take(limit) { if (&x).eq_mod(&y, &m) { println!("&{x} is equal to &{y} mod &{m}"); } else { println!("&{x} is not equal to &{y} mod &{m}"); } } } fn benchmark_limbs_limb_mod_exact_odd_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_limb_mod_exact_odd_limb(Limb, Limb, Limb)", BenchmarkType::Single, unsigned_triple_gen_var_21().get(gm, config), gm.name(), limit, file_name, &triple_1_bit_bucketer("n"), &mut [("Malachite", &mut |(n, d, carry)| { no_out!(limbs_limb_mod_exact_odd_limb(n, d, carry)); })], ); } fn benchmark_limbs_mod_exact_odd_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_exact_odd_limb(&[Limb], Limb, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_10().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("ns"), &mut [("Malachite", &mut |(ref ns, d, carry)| { no_out!(limbs_mod_exact_odd_limb(ns, d, carry)); })], ); } // use large params #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_limbs_eq_limb_mod_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_limb_mod_limb(&mut [Limb], Limb, Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_unsigned_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("limbs_eq_limb_mod_limb", &mut |(ref xs, y, m)| { no_out!(limbs_eq_limb_mod_limb(xs, y, m)); }), ("limbs_mod_limb", &mut |(ref xs, y, m)| { no_out!(limbs_mod_limb::(xs, m) == y % m); }), ("combined_limbs_eq_limb_mod_limb", &mut |(ref xs, y, m)| { no_out!(combined_limbs_eq_limb_mod_limb(xs, y, m)); }), ], ); } fn benchmark_limbs_eq_limb_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_limb_mod(&[Limb], Limb, &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("limbs_eq_limb_mod", &mut |(ref mut xs, ref mut ms, y)| { no_out!(limbs_eq_limb_mod(xs, y, ms)); }), ("limbs_eq_limb_mod_val_ref", &mut |( ref mut xs, ref mut ms, y, )| { no_out!(limbs_eq_limb_mod_val_ref(xs, y, ms)); }), ("limbs_eq_limb_mod_ref_val", &mut |( ref xs, ref mut ms, y, )| { no_out!(limbs_eq_limb_mod_ref_val(xs, y, ms)); }), ("limbs_eq_limb_mod_ref_ref", &mut |( ref xs, ref mut ms, y, )| { no_out!(limbs_eq_limb_mod_ref_ref(xs, y, ms)); }), ], ); } fn benchmark_limbs_eq_limb_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_limb_mod_ref_ref(&[Limb], Limb, &[Limb])", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(ref xs, ref ms, y)| { no_out!(limbs_eq_limb_mod_ref_ref(xs, y, ms)); }), ("naive 1", &mut |(ref xs, ref ms, y)| { no_out!(limbs_eq_limb_mod_naive_1(xs, y, ms)); }), ("naive 2", &mut |(ref xs, ref ms, y)| { no_out!(limbs_eq_limb_mod_naive_2(xs, y, ms)); }), ], ); } fn benchmark_limbs_eq_mod_limb_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_limb_val_ref(&mut [Limb], &[Limb], Limb)", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [ ("limbs_eq_mod_limb_val_ref", &mut |( ref mut xs, ref ys, ms, )| { no_out!(limbs_eq_mod_limb_val_ref(xs, ys, ms)); }), ("limbs_eq_mod_limb_ref_val", &mut |( ref xs, ref mut ys, ms, )| { no_out!(limbs_eq_mod_limb_ref_val(xs, ys, ms)); }), ("limbs_eq_mod_limb_ref_ref", &mut |(ref xs, ref ys, ms)| { no_out!(limbs_eq_mod_limb_ref_ref(xs, ys, ms)); }), ], ); } fn benchmark_limbs_eq_mod_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_limb_val_ref(&mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [ ("standard", &mut |(ref xs, ref ys, ms)| { no_out!(limbs_eq_mod_limb_ref_ref(xs, ys, ms)); }), ("naive 1", &mut |(ref xs, ref ys, ms)| { no_out!(limbs_eq_mod_limb_naive_1(xs, ys, ms)); }), ("naive 2", &mut |(ref xs, ref ys, ms)| { no_out!(limbs_eq_mod_limb_naive_2(xs, ys, ms)); }), ], ); } fn benchmark_limbs_eq_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_ref_ref_ref(&[Limb], &[Limb], &[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_triple_gen_var_36().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [ ("limbs_eq_mod_ref_val_val", &mut |( ref xs, ref mut ys, ref mut ms, )| { no_out!(limbs_eq_mod_ref_val_val(xs, ys, ms)); }), ("limbs_eq_mod_ref_val_ref", &mut |( ref xs, ref mut ys, ref ms, )| { no_out!(limbs_eq_mod_ref_val_ref(xs, ys, ms)); }), ("limbs_eq_mod_ref_ref_val", &mut |( ref xs, ref ys, ref mut ms, )| { no_out!(limbs_eq_mod_ref_ref_val(xs, ys, ms)); }), ("limbs_eq_mod_ref_ref_ref", &mut |( ref xs, ref ys, ref ms, )| { no_out!(limbs_eq_mod_ref_ref_ref(xs, ys, ms)); }), ], ); } fn benchmark_limbs_eq_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_ref_ref_ref(&[Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_36().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [ ("standard", &mut |(ref xs, ref ys, ref ms)| { no_out!(limbs_eq_mod_ref_ref_ref(xs, ys, ms)); }), ("naive 1", &mut |(ref xs, ref ys, ref ms)| { no_out!(limbs_eq_mod_naive_1(xs, ys, ms)); }), ("naive 2", &mut |(ref xs, ref ys, ref ms)| { no_out!(limbs_eq_mod_naive_2(xs, ys, ms)); }), ], ); } fn benchmark_natural_eq_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_mod(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.eq_mod(Natural, Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, m)); }), ("Natural.eq_mod(Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, &m)); }), ("Natural.eq_mod(&Natural, Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(&y, m)); }), ("Natural.eq_mod(&Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(&y, &m)); }), ("(&Natural).eq_mod(Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).eq_mod(y, m)); }), ("(&Natural).eq_mod(Natural, &Natural)", &mut |(x, y, m)| { no_out!((&x).eq_mod(y, &m)); }), ("(&Natural).eq_mod(&Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).eq_mod(&y, m)); }), ("(&Natural).eq_mod(&Natural, &Natural)", &mut |(x, y, m)| { no_out!((&x).eq_mod(&y, &m)); }), ], ); } fn benchmark_natural_eq_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_mod(Natural, Natural)", BenchmarkType::LibraryComparison, natural_triple_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y, m))| no_out!(x.eq_mod(y, m))), ("rug", &mut |((x, y, m), _)| no_out!(x.is_congruent(&y, &m))), ], ); } #[allow(clippy::no_effect, clippy::short_circuit_statement, unused_must_use)] fn benchmark_natural_eq_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_mod(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.eq_mod(Natural, Natural)", &mut |(x, y, m)| { no_out!(x.eq_mod(y, m)); }), ( "Natural == Natural || Natural != 0 && Natural % Natural == Natural % Natural", &mut |(x, y, m)| no_out!(x == y || m != 0 && x % &m == y % m), ), ( "|Natural - Natural|.divisible_by(Natural)", &mut |(x, y, m)| { no_out!( (Integer::from(x) - Integer::from(y)) .unsigned_abs() .divisible_by(m) ); }, ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{EqModPowerOf2, ModPowerOf2}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{ triple_1_2_vec_max_len_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_unsigned_triple_gen_var_13, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::eq_mod_power_of_2::{ limbs_eq_limb_mod_power_of_2, limbs_eq_mod_power_of_2, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_triple_1_2_natural_max_bit_bucketer, triple_1_2_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_1, natural_natural_unsigned_triple_gen_var_1_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_eq_limb_mod_power_of_2); register_demo!(runner, demo_limbs_eq_mod_power_of_2); register_demo!(runner, demo_natural_eq_mod_power_of_2); register_bench!(runner, benchmark_limbs_eq_limb_mod_power_of_2); register_bench!(runner, benchmark_limbs_eq_mod_power_of_2); register_bench!( runner, benchmark_natural_eq_mod_power_of_2_library_comparison ); register_bench!(runner, benchmark_natural_eq_mod_power_of_2_algorithms); } fn demo_limbs_eq_limb_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_13() .get(gm, config) .take(limit) { println!( "limbs_eq_limb_mod_power_of_2({:?}, {}, {}) = {:?}", xs, y, pow, limbs_eq_limb_mod_power_of_2(&xs, y, pow) ); } } fn demo_limbs_eq_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9() .get(gm, config) .take(limit) { println!( "limbs_eq_mod_power_of_2({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_eq_mod_power_of_2(&xs, &ys, pow) ); } } fn demo_natural_eq_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { if x.eq_mod_power_of_2(&y, pow) { println!("{x} is equal to {y} mod 2^{pow}"); } else { println!("{x} is not equal to {y} mod 2^{pow}"); } } } fn benchmark_limbs_eq_limb_mod_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_limb_mod_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_13().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, y, pow)| { no_out!(limbs_eq_limb_mod_power_of_2(xs, y, pow)); })], ); } fn benchmark_limbs_eq_mod_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_eq_mod_power_of_2(&[Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(ref xs, ref ys, pow)| { no_out!(limbs_eq_mod_power_of_2(xs, ys, pow)); })], ); } fn benchmark_natural_eq_mod_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_mod_power_of_2(&Natural, u64)", BenchmarkType::LibraryComparison, natural_natural_unsigned_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_1_2_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (ref n, ref u, pow))| { no_out!(n.eq_mod_power_of_2(u, pow)); }), ("rug", &mut |((ref n, ref u, pow), _)| { no_out!(n.is_congruent_2pow(u, u32::exact_from(pow))); }), ], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_eq_mod_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_mod_power_of_2(&Natural, u64)", BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_max_bit_bucketer("x", "y"), &mut [ ( "Natural.eq_mod_power_of_2(&Natural, u64)", &mut |(ref x, ref y, pow)| no_out!(x.eq_mod_power_of_2(y, pow)), ), ( "Natural.mod_power_of_2(u64) == Natural.mod_power_of_2(u64)", &mut |(ref x, ref y, pow)| no_out!(x.mod_power_of_2(pow) == y.mod_power_of_2(pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ExtendedGcd; use malachite_base::test_util::bench::bucketers::pair_vec_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_pair_gen_var_11; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::gcd::extended_gcd::limbs_extended_gcd; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_rm}; use malachite_nz::test_util::natural::arithmetic::extended_gcd::{ extended_gcd_binary_natural, extended_gcd_euclidean_natural, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_extended_gcd); register_demo!(runner, demo_natural_extended_gcd); register_demo!(runner, demo_natural_extended_gcd_val_ref); register_demo!(runner, demo_natural_extended_gcd_ref_val); register_demo!(runner, demo_natural_extended_gcd_ref_ref); register_bench!(runner, benchmark_limbs_extended_gcd); register_bench!(runner, benchmark_natural_extended_gcd_algorithms); register_bench!(runner, benchmark_natural_extended_gcd_library_comparison); register_bench!(runner, benchmark_natural_extended_gcd_evaluation_strategy); } fn demo_limbs_extended_gcd(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_11().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let mut gs = vec![0; ys.len()]; let mut ss = vec![0; ys.len() + 1]; let result = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); println!( "limbs_gcd_extended_gcd(&mut gs, &mut ss, {xs_old:?}, {ys_old:?}) = {result:?}; \ gs = {gs:?}, ss = {ss:?}", ); } } fn demo_natural_extended_gcd(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.extended_gcd({}) = {:?}", x_old, y_old, x.extended_gcd(y) ); } } fn demo_natural_extended_gcd_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.extended_gcd(&{}) = {:?}", x_old, y, x.extended_gcd(&y)); } } fn demo_natural_extended_gcd_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).extended_gcd({}) = {:?}", x, y_old, (&x).extended_gcd(y) ); } } fn demo_natural_extended_gcd_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!( "(&{}).extended_gcd(&{}) = {:?}", x, y, (&x).extended_gcd(&y) ); } } fn benchmark_limbs_extended_gcd(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_extended_gcd(&mut [Limb], &mut [Limb], &mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { let mut gs = vec![0; ys.len()]; let mut ss = vec![0; ys.len() + 1]; limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); })], ); } fn benchmark_natural_extended_gcd_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.extended_gcd(Natural)", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.extended_gcd(y))), ("Euclidean", &mut |(x, y)| { no_out!(extended_gcd_euclidean_natural(x, y)); }), ("binary", &mut |(x, y)| { no_out!(extended_gcd_binary_natural(x, y)); }), ], ); } fn benchmark_natural_extended_gcd_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.extended_gcd(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.extended_gcd(y))), ("rug", &mut |((x, y), _)| { no_out!(x.extended_gcd(y, rug::Integer::new())); }), ], ); } fn benchmark_natural_extended_gcd_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.extended_gcd(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.extended_gcd(Natural)", &mut |(x, y)| { no_out!(x.extended_gcd(y)); }), ("Natural.extended_gcd(&Natural)", &mut |(x, y)| { no_out!(x.extended_gcd(&y)); }), ("&Natural.extended_gcd(Natural)", &mut |(x, y)| { no_out!((&x).extended_gcd(y)); }), ("&Natural.extended_gcd(&Natural)", &mut |(x, y)| { no_out!((&x).extended_gcd(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ DoubleFactorial, Factorial, Multifactorial, Subfactorial, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{ pair_1_bucketer, unsigned_direct_bucketer, usize_convertible_pair_ratio_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_gen_var_5, unsigned_pair_gen_var_18}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::factorial::limbs_odd_factorial; use malachite_nz::test_util::generators::unsigned_bool_pair_gen_var_1; use malachite_nz::test_util::natural::arithmetic::factorial::{ double_factorial_naive, factorial_naive, multifactorial_naive, }; use rug::Complete; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_odd_factorial); register_demo!(runner, demo_factorial); register_demo!(runner, demo_double_factorial); register_demo!(runner, demo_multifactorial); register_demo!(runner, demo_subfactorial); register_bench!(runner, benchmark_limbs_odd_factorial); register_bench!(runner, benchmark_factorial_algorithms); register_bench!(runner, benchmark_factorial_library_comparison); register_bench!(runner, benchmark_double_factorial_algorithms); register_bench!(runner, benchmark_double_factorial_library_comparison); register_bench!(runner, benchmark_multifactorial_algorithms); register_bench!(runner, benchmark_multifactorial_library_comparison); register_bench!(runner, benchmark_subfactorial); } fn demo_limbs_odd_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for (n, double) in unsigned_bool_pair_gen_var_1().get(gm, config).take(limit) { println!( "limbs_odd_factorial({:?}, {}) = {:?}", n, double, limbs_odd_factorial(n, double) ); } } fn demo_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!("{}! = {}", n, Natural::factorial(n)); } } fn demo_double_factorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!("{}!! = {}", n, Natural::double_factorial(n)); } } fn demo_multifactorial(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in unsigned_pair_gen_var_18().get(gm, config).take(limit) { if m <= 5 { print!("{n}"); for _ in 0..m { print!("!"); } println!(" = {}", Natural::multifactorial(n, m)); } else { println!("{}[!^{}] = {}", n, m, Natural::multifactorial(n, m)); } } } fn demo_subfactorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!("!{} = {}", n, Natural::subfactorial(n)); } } fn benchmark_limbs_odd_factorial(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_odd_factorial(u64, bool)", BenchmarkType::Single, unsigned_bool_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_bucketer("n"), &mut [("Malachite", &mut |(n, double)| { no_out!(limbs_odd_factorial(n, double)); })], ); } fn benchmark_factorial_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.factorial(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(Natural::factorial(n))), ("naive", &mut |n| no_out!(factorial_naive(n))), ], ); } fn benchmark_factorial_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.factorial(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |n| no_out!(Natural::factorial(n))), ("rug", &mut |n| { no_out!(rug::Integer::factorial(u32::exact_from(n)).complete()); }), ], ); } fn benchmark_double_factorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.double_factorial(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(Natural::double_factorial(n))), ("naive", &mut |n| no_out!(double_factorial_naive(n))), ], ); } fn benchmark_double_factorial_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.double_factorial(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |n| no_out!(Natural::double_factorial(n))), ("rug", &mut |n| { no_out!(rug::Integer::factorial_2(u32::exact_from(n)).complete()); }), ], ); } fn benchmark_multifactorial_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.multifactorial(u64, u64)", BenchmarkType::Algorithms, unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_ratio_bucketer("n", "m"), &mut [ ("default", &mut |(n, m)| { no_out!(Natural::multifactorial(n, m)); }), ("naive", &mut |(n, m)| no_out!(multifactorial_naive(n, m))), ], ); } fn benchmark_multifactorial_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.multifactorial(u64, u64)", BenchmarkType::LibraryComparison, unsigned_pair_gen_var_18().get(gm, config), gm.name(), limit, file_name, &usize_convertible_pair_ratio_bucketer("n", "m"), &mut [ ("Malachite", &mut |(m, n)| { no_out!(Natural::multifactorial(m, n)); }), ("rug", &mut |(m, n)| { no_out!( rug::Integer::factorial_m(u32::exact_from(n), u32::exact_from(m)).complete() ); }), ], ); } fn benchmark_subfactorial(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.subfactorial(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| no_out!(Natural::subfactorial(n)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Gcd, GcdAssign}; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, quadruple_3_vec_len_bucketer, quadruple_max_bit_bucketer, unsigned_direct_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_quadruple_gen_var_11, unsigned_vec_unsigned_pair_gen_var_23, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::gcd::half_gcd::{ HalfGcdMatrix, limbs_gcd_div, limbs_gcd_reduced, limbs_half_gcd_matrix_1_mul_vector, }; use malachite_nz::natural::arithmetic::gcd::limbs_gcd_limb; use malachite_nz::natural::arithmetic::gcd::matrix_2_2::{ limbs_matrix_2_2_mul, limbs_matrix_2_2_mul_small, limbs_matrix_2_2_mul_strassen, limbs_matrix_mul_2_2_scratch_len, }; use malachite_nz::test_util::bench::bucketers::{ limbs_matrix_2_2_mul_bucketer, pair_1_half_gcd_matrix_bucketer, pair_natural_max_bit_bucketer, triple_1_half_gcd_matrix_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ large_type_gen_var_5, large_type_gen_var_6, large_type_gen_var_7, large_type_gen_var_8, natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_var_4, natural_pair_gen_var_4_nrm, unsigned_vec_pair_gen_var_10, }; use malachite_nz::test_util::natural::arithmetic::gcd::{ OwnedHalfGcdMatrix, gcd_binary_nz, gcd_euclidean_nz, limbs_gcd_div_alt, limbs_gcd_div_naive, }; use num::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_gcd_limb); register_demo!(runner, demo_half_gcd_matrix_init); register_demo!(runner, demo_half_gcd_matrix_update_q); register_demo!(runner, demo_half_gcd_matrix_mul_matrix_1); register_demo!(runner, demo_half_gcd_matrix_1_mul_vector); register_demo!(runner, demo_limbs_matrix_2_2_mul); register_demo!(runner, demo_limbs_gcd_div); register_demo!(runner, demo_limbs_gcd_reduced); register_demo!(runner, demo_natural_gcd); register_demo!(runner, demo_natural_gcd_val_ref); register_demo!(runner, demo_natural_gcd_ref_val); register_demo!(runner, demo_natural_gcd_ref_ref); register_demo!(runner, demo_natural_gcd_assign); register_demo!(runner, demo_natural_gcd_assign_ref); register_demo!(runner, demo_natural_gcd_2); register_bench!(runner, benchmark_limbs_gcd_limb); register_bench!(runner, benchmark_half_gcd_matrix_init); register_bench!(runner, benchmark_half_gcd_matrix_update_q); register_bench!(runner, benchmark_half_gcd_matrix_mul_matrix_1); register_bench!(runner, benchmark_half_gcd_matrix_1_mul_vector); register_bench!(runner, benchmark_limbs_matrix_2_2_mul_algorithms); register_bench!(runner, benchmark_limbs_gcd_div_algorithms); register_bench!(runner, benchmark_limbs_gcd_reduced); register_bench!(runner, benchmark_natural_gcd_algorithms); register_bench!(runner, benchmark_natural_gcd_library_comparison); register_bench!(runner, benchmark_natural_gcd_evaluation_strategy); register_bench!(runner, benchmark_natural_gcd_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_gcd_algorithms_2); register_bench!(runner, benchmark_natural_gcd_library_comparison_2); register_bench!(runner, benchmark_natural_gcd_evaluation_strategy_2); } fn demo_limbs_gcd_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_23() .get(gm, config) .take(limit) { println!( "limbs_gcd_limb({:?}, {}) = {}", xs, y, limbs_gcd_limb(&xs, y) ); } } fn demo_half_gcd_matrix_init(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_11().get(gm, config).take(limit) { let scratch_len = HalfGcdMatrix::min_init_scratch(n); println!( "HalfGcdMatrix::init({}, vec![0; {}]) = {:?}", n, scratch_len, OwnedHalfGcdMatrix::init(n, vec![0; scratch_len]) ); } } fn demo_half_gcd_matrix_update_q(gm: GenMode, config: &GenConfig, limit: usize) { for (mut m, qs, column) in large_type_gen_var_5().get(gm, config).take(limit) { let old_m = m.clone(); let mut scratch = vec![0; OwnedHalfGcdMatrix::update_q_scratch_len(&m, qs.len())]; m.update_q(&qs, column, &mut scratch); println!("HalfGcdMatrix::update_q({old_m:?}, {qs:?}, {column}) = {m:?}"); } } fn demo_half_gcd_matrix_mul_matrix_1(gm: GenMode, config: &GenConfig, limit: usize) { for (mut m, m_1) in large_type_gen_var_7().get(gm, config).take(limit) { let old_m = m.clone(); let mut scratch = vec![0; m.n]; m.mul_matrix_1(&m_1, &mut scratch); println!("m := {old_m:?}; m.mul_matrix_1({m_1:?}); m = {m:?}"); } } fn demo_half_gcd_matrix_1_mul_vector(gm: GenMode, config: &GenConfig, limit: usize) { for (m, mut out, xs, mut ys) in large_type_gen_var_6().get(gm, config).take(limit) { let old_out = out.clone(); let old_ys = ys.clone(); let out_len = limbs_half_gcd_matrix_1_mul_vector(&m, &mut out, &xs, &mut ys); println!( "out := {old_out:?}; ys := {old_ys:?}; \ limbs_half_gcd_matrix_1_mul_vector({m:?}, &mut out, {xs:?}, &mut ys) = {out_len}; \ out = {out:?}; ys = {ys:?}", ); } } fn demo_limbs_matrix_2_2_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs00, mut xs01, mut xs10, mut xs11, xs_len, ys00, ys01, ys10, ys11) in large_type_gen_var_8().get(gm, config).take(limit) { let xs00_old = xs00.clone(); let xs01_old = xs01.clone(); let xs10_old = xs10.clone(); let xs11_old = xs11.clone(); let mut scratch = vec![0; limbs_matrix_mul_2_2_scratch_len(xs_len, ys00.len())]; limbs_matrix_2_2_mul( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, &ys00, &ys01, &ys10, &ys11, &mut scratch, ); println!( "(xs00, xs01, xs10, xs11) := {:?}; \ limbs_matrix_2_2_mul(..., {}, {:?}, {:?}, {:?}, {:?}); \ (xs00, xs01, xs10, xs11) = {:?}", (xs00_old, xs01_old, xs10_old, xs11_old), xs_len, ys00, ys01, ys10, ys11, (xs00, xs01, xs10, xs11) ); } } fn demo_limbs_gcd_div(gm: GenMode, config: &GenConfig, limit: usize) { for (n1, n0, d1, d0) in unsigned_quadruple_gen_var_11().get(gm, config).take(limit) { println!( "limbs_gcd_div({}, {}, {}, {}) = {:?}", n1, n0, d1, d0, limbs_gcd_div(n1, n0, d1, d0) ); } } fn demo_limbs_gcd_reduced(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_10().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let mut out = vec![0; xs.len()]; let out_len = limbs_gcd_reduced(&mut out, &mut xs, &mut ys); out.resize(out_len, 0); println!("limbs_gcd_reduced(&mut out, {xs_old:?}, {ys_old:?}); out = {out:?}"); } } fn demo_natural_gcd(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.gcd({}) = {}", x_old, y_old, x.gcd(y)); } } fn demo_natural_gcd_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.gcd(&{}) = {}", x_old, y, x.gcd(&y)); } } fn demo_natural_gcd_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).gcd({}) = {}", x, y_old, (&x).gcd(y)); } } fn demo_natural_gcd_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("(&{}).gcd(&{}) = {}", x, y, (&x).gcd(&y)); } } fn demo_natural_gcd_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.gcd_assign(y.clone()); println!("x := {x_old}; x.gcd_assign({y}); x = {x}"); } } fn demo_natural_gcd_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.gcd_assign(&y); println!("x := {x_old}; x.gcd_assign(&{y}); x = {x}"); } } fn demo_natural_gcd_2(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_4().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.gcd({}) = {}", x_old, y_old, x.gcd(y)); } } fn benchmark_limbs_gcd_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "HalfGcdMatrix::init(usize, Vec)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_23().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_gcd_limb(&xs, y)))], ); } fn benchmark_half_gcd_matrix_init(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_gcd_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_gen_var_11().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |n| { let scratch_len = HalfGcdMatrix::min_init_scratch(n); OwnedHalfGcdMatrix::init(n, vec![0; scratch_len]); })], ); } fn benchmark_half_gcd_matrix_update_q( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "HalfGcdMatrix::update_q(&[Limb], u8, &mut [Limb])", BenchmarkType::Single, large_type_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_half_gcd_matrix_bucketer("m"), &mut [("Malachite", &mut |(mut m, qs, column)| { let mut scratch = vec![0; OwnedHalfGcdMatrix::update_q_scratch_len(&m, qs.len())]; m.update_q(&qs, column, &mut scratch); })], ); } fn benchmark_half_gcd_matrix_mul_matrix_1( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "HalfGcdMatrix::mul_matrix_1(&HalfGcdMatrix1, &mut [Limb])", BenchmarkType::Single, large_type_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_half_gcd_matrix_bucketer("m"), &mut [("Malachite", &mut |(mut m, m_1)| { let mut scratch = vec![0; m.n]; m.mul_matrix_1(&m_1, &mut scratch); })], ); } fn benchmark_half_gcd_matrix_1_mul_vector( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_half_gcd_matrix_1_mul_vector(&HalfGcdMatrix1, &mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Single, large_type_gen_var_6().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(m, mut out, xs, mut ys)| { no_out!(limbs_half_gcd_matrix_1_mul_vector( &m, &mut out, &xs, &mut ys )); })], ); } fn benchmark_limbs_matrix_2_2_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_matrix_2_2_mul", BenchmarkType::Algorithms, large_type_gen_var_8().get(gm, config), gm.name(), limit, file_name, &limbs_matrix_2_2_mul_bucketer(), &mut [ ("default", &mut |( mut xs00, mut xs01, mut xs10, mut xs11, xs_len, ys00, ys01, ys10, ys11, )| { let scratch_len = 3 * (xs_len + ys00.len()) + 5; let mut scratch = vec![0; scratch_len]; limbs_matrix_2_2_mul( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, &ys00, &ys01, &ys10, &ys11, &mut scratch, ); }), ("small", &mut |( mut xs00, mut xs01, mut xs10, mut xs11, xs_len, ys00, ys01, ys10, ys11, )| { let scratch_len = 3 * (xs_len + ys00.len()) + 5; let mut scratch = vec![0; scratch_len]; limbs_matrix_2_2_mul_small( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, &ys00, &ys01, &ys10, &ys11, &mut scratch, ); }), ("Strassen", &mut |( mut xs00, mut xs01, mut xs10, mut xs11, xs_len, ys00, ys01, ys10, ys11, )| { let scratch_len = 3 * (xs_len + ys00.len()) + 5; let mut scratch = vec![0; scratch_len]; limbs_matrix_2_2_mul_strassen( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, &ys00, &ys01, &ys10, &ys11, &mut scratch, ); }), ], ); } fn benchmark_limbs_gcd_div_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_gcd_div(Limb, Limb, Limb, Limb)", BenchmarkType::Algorithms, unsigned_quadruple_gen_var_11().get(gm, config), gm.name(), limit, file_name, &quadruple_max_bit_bucketer("n1", "n0", "d1", "d0"), &mut [ ("default", &mut |(n1, n0, d1, d0)| { no_out!(limbs_gcd_div(n1, n0, d1, d0)); }), ("alt", &mut |(n1, n0, d1, d0)| { no_out!(limbs_gcd_div_alt(n1, n0, d1, d0)); }), ("naive", &mut |(n1, n0, d1, d0)| { no_out!(limbs_gcd_div_naive(n1, n0, d1, d0)); }), ], ); } fn benchmark_limbs_gcd_reduced(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_gcd_reduced(&mut [Limb], &mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_10().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, mut ys)| { let mut out = vec![0; xs.len()]; limbs_gcd_reduced(&mut out, &mut xs, &mut ys); })], ); } fn benchmark_natural_gcd_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.gcd(y))), ("Euclidean", &mut |(x, y)| no_out!(gcd_euclidean_nz(x, y))), ("binary", &mut |(x, y)| no_out!(gcd_binary_nz(x, y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_gcd_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.gcd(y))), ("num", &mut |((x, y), _, _)| no_out!(x.gcd(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.gcd(&y))), ], ); } fn benchmark_natural_gcd_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.gcd(Natural)", &mut |(x, y)| no_out!(x.gcd(y))), ("Natural.gcd(&Natural)", &mut |(x, y)| no_out!(x.gcd(&y))), ("&Natural.gcd(Natural)", &mut |(x, y)| no_out!((&x).gcd(y))), ("&Natural.gcd(&Natural)", &mut |(x, y)| { no_out!((&x).gcd(&y)); }), ], ); } fn benchmark_natural_gcd_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.gcd(y))), ("Euclidean", &mut |(x, y)| no_out!(gcd_euclidean_nz(x, y))), ("binary", &mut |(x, y)| no_out!(gcd_binary_nz(x, y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_gcd_library_comparison_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_4_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.gcd(y))), ("num", &mut |((x, y), _, _)| no_out!(x.gcd(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.gcd(&y))), ], ); } fn benchmark_natural_gcd_evaluation_strategy_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.gcd(Natural)", &mut |(x, y)| no_out!(x.gcd(y))), ("Natural.gcd(&Natural)", &mut |(x, y)| no_out!(x.gcd(&y))), ("&Natural.gcd(Natural)", &mut |(x, y)| no_out!((&x).gcd(y))), ("&Natural.gcd(&Natural)", &mut |(x, y)| { no_out!((&x).gcd(&y)); }), ], ); } fn benchmark_natural_gcd_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gcd_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.gcd(Natural)", &mut |(x, y)| no_out!(x.gcd(y))), ("Natural.gcd(&Natural)", &mut |(x, y)| no_out!(x.gcd(&y))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use malachite_nz::test_util::bench::bucketers::pair_2_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_is_power_of_2); register_demo!(runner, demo_natural_is_power_of_2); register_bench!(runner, benchmark_limbs_is_power_of_2); register_bench!(runner, benchmark_natural_is_power_of_2_library_comparison); } fn demo_limbs_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_is_power_of_2({:?}) = {:?}", xs, limbs_is_power_of_2(&xs) ); } } fn demo_natural_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.is_power_of_2() { println!("{n} is a power of 2"); } else { println!("{n} is not a power of 2"); } } } fn benchmark_limbs_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_is_power_of_2(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_is_power_of_2(&xs)))], ); } fn benchmark_natural_is_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.is_power_of_2()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.is_power_of_2())), ("rug", &mut |(n, _)| no_out!(n.is_power_of_two())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{JacobiSymbol, KroneckerSymbol}; use malachite_base::test_util::bench::bucketers::pair_vec_max_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_pair_gen_var_32; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::kronecker_symbol::{ limbs_jacobi_symbol_init, limbs_jacobi_symbol_same_length, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_natural_bit_bucketer, pair_2_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_rm, natural_pair_gen_var_12, natural_pair_gen_var_12_rm, }; use malachite_nz::test_util::natural::arithmetic::kronecker_symbol::jacobi_symbol_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_jacobi_symbol_same_length); register_demo!(runner, demo_natural_jacobi_symbol); register_demo!(runner, demo_natural_jacobi_symbol_val_ref); register_demo!(runner, demo_natural_jacobi_symbol_ref_val); register_demo!(runner, demo_natural_jacobi_symbol_ref_ref); register_demo!(runner, demo_natural_kronecker_symbol); register_demo!(runner, demo_natural_kronecker_symbol_val_ref); register_demo!(runner, demo_natural_kronecker_symbol_ref_val); register_demo!(runner, demo_natural_kronecker_symbol_ref_ref); register_bench!(runner, benchmark_limbs_jacobi_symbol_same_length); register_bench!(runner, benchmark_natural_jacobi_symbol_library_comparison); register_bench!(runner, benchmark_natural_jacobi_symbol_evaluation_strategy); register_bench!(runner, benchmark_natural_jacobi_symbol_algorithms); register_bench!( runner, benchmark_natural_kronecker_symbol_library_comparison ); register_bench!( runner, benchmark_natural_kronecker_symbol_evaluation_strategy ); } fn demo_limbs_jacobi_symbol_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen_var_32().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let bits = limbs_jacobi_symbol_init(xs[0], ys[0], 0); let s = limbs_jacobi_symbol_same_length(&mut xs, &mut ys, bits); println!("limbs_jacobi_symbol_same_length({xs_old:?}, {ys_old:?}) = {s}"); } } fn demo_natural_jacobi_symbol(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_12().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!( "{}.jacobi_symbol({}) = {}", n_old, m_old, n.jacobi_symbol(m) ); } } fn demo_natural_jacobi_symbol_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_12().get(gm, config).take(limit) { let n_old = n.clone(); println!("{}.jacobi_symbol({}) = {}", n_old, m, n.jacobi_symbol(&m)); } } fn demo_natural_jacobi_symbol_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_12().get(gm, config).take(limit) { let m_old = m.clone(); println!("{}.jacobi_symbol({}) = {}", n, m_old, (&n).jacobi_symbol(m)); } } fn demo_natural_jacobi_symbol_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_12().get(gm, config).take(limit) { println!("{}.jacobi_symbol({}) = {}", n, m, (&n).jacobi_symbol(&m)); } } fn demo_natural_kronecker_symbol(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!( "{}.kronecker_symbol({}) = {}", n_old, m_old, n.kronecker_symbol(m) ); } } fn demo_natural_kronecker_symbol_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen().get(gm, config).take(limit) { let n_old = n.clone(); println!( "{}.kronecker_symbol({}) = {}", n_old, m, n.kronecker_symbol(&m) ); } } fn demo_natural_kronecker_symbol_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen().get(gm, config).take(limit) { let m_old = m.clone(); println!( "{}.kronecker_symbol({}) = {}", n, m_old, (&n).kronecker_symbol(m) ); } } fn demo_natural_kronecker_symbol_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen().get(gm, config).take(limit) { println!( "{}.kronecker_symbol({}) = {}", n, m, (&n).kronecker_symbol(&m) ); } } fn benchmark_limbs_jacobi_symbol_same_length( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_jacobi_symbol_same_length(&mut [Limb], &mut [Limb], u8)", BenchmarkType::Single, unsigned_vec_pair_gen_var_32().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { let bits = limbs_jacobi_symbol_init(xs[0], ys[0], 0); limbs_jacobi_symbol_same_length(&mut xs, &mut ys, bits); })], ); } fn benchmark_natural_jacobi_symbol_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.jacobi_symbol(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_12_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.jacobi_symbol(y))), ("rug", &mut |((x, y), _)| no_out!(x.jacobi(&y))), ], ); } fn benchmark_natural_jacobi_symbol_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.jacobi_symbol(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_12().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.jacobi_symbol(Natural)", &mut |(n, m)| { no_out!(n.jacobi_symbol(m)); }), ("Natural.jacobi_symbol(&Natural)", &mut |(n, m)| { no_out!(n.jacobi_symbol(&m)); }), ("(&Natural).jacobi_symbol(Natural)", &mut |(n, m)| { no_out!((&n).jacobi_symbol(m)); }), ("(&Natural).jacobi_symbol(&Natural)", &mut |(n, m)| { no_out!((&n).jacobi_symbol(&m)); }), ], ); } fn benchmark_natural_jacobi_symbol_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.jacobi_symbol(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_12().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("default", &mut |(n, m)| no_out!(n.jacobi_symbol(m))), ("simple", &mut |(n, m)| no_out!(jacobi_symbol_simple(n, m))), ], ); } fn benchmark_natural_kronecker_symbol_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.kronecker_symbol(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.kronecker_symbol(y)); }), ("rug", &mut |((x, y), _)| no_out!(x.kronecker(&y))), ], ); } fn benchmark_natural_kronecker_symbol_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.kronecker_symbol(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.kronecker_symbol(Natural)", &mut |(n, m)| { no_out!(n.kronecker_symbol(m)); }), ("Natural.kronecker_symbol(&Natural)", &mut |(n, m)| { no_out!(n.kronecker_symbol(&m)); }), ("(&Natural).kronecker_symbol(Natural)", &mut |(n, m)| { no_out!((&n).kronecker_symbol(m)); }), ("(&Natural).kronecker_symbol(&Natural)", &mut |(n, m)| { no_out!((&n).kronecker_symbol(&m)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Lcm, LcmAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_nrm}; use num::Integer; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_lcm); register_demo!(runner, demo_natural_lcm_val_ref); register_demo!(runner, demo_natural_lcm_ref_val); register_demo!(runner, demo_natural_lcm_ref_ref); register_demo!(runner, demo_natural_lcm_assign); register_demo!(runner, demo_natural_lcm_assign_ref); register_bench!(runner, benchmark_natural_lcm_library_comparison); register_bench!(runner, benchmark_natural_lcm_evaluation_strategy); register_bench!(runner, benchmark_natural_lcm_assign_evaluation_strategy); } fn demo_natural_lcm(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.lcm({}) = {}", x_old, y_old, x.lcm(y)); } } fn demo_natural_lcm_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.lcm(&{}) = {}", x_old, y, x.lcm(&y)); } } fn demo_natural_lcm_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).lcm({}) = {}", x, y_old, (&x).lcm(y)); } } fn demo_natural_lcm_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("(&{}).lcm(&{}) = {}", x, y, (&x).lcm(&y)); } } fn demo_natural_lcm_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.lcm_assign(y); println!("x := {x_old}; x.lcm_assign({y_old}); x = {x}"); } } fn demo_natural_lcm_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.lcm_assign(&y); println!("x := {x_old}; x.lcm_assign(&{y}); x = {x}"); } } #[allow(unused_must_use)] fn benchmark_natural_lcm_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.lcm(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.lcm(y))), ("num", &mut |((x, y), _, _)| no_out!(x.lcm(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.lcm(&y))), ], ); } fn benchmark_natural_lcm_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.lcm(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.lcm(Natural)", &mut |(x, y)| no_out!(x.lcm(y))), ("Natural.lcm(&Natural)", &mut |(x, y)| no_out!(x.lcm(&y))), ("&Natural.lcm(Natural)", &mut |(x, y)| no_out!((&x).lcm(y))), ("&Natural.lcm(&Natural)", &mut |(x, y)| { no_out!((&x).lcm(&y)); }), ], ); } fn benchmark_natural_lcm_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.lcm_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.lcm(Natural)", &mut |(x, y)| no_out!(x.lcm(y))), ("Natural.lcm(&Natural)", &mut |(x, y)| no_out!(x.lcm(&y))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingLogBase, CheckedLogBase, FloorLogBase}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{natural_bit_bucketer, natural_bit_ratio_bucketer}; use malachite_nz::test_util::generators::{natural_gen_var_2, natural_pair_gen_var_3}; use malachite_nz::test_util::natural::arithmetic::log_base::{ ceiling_log_base_by_squaring, ceiling_log_base_naive, checked_log_base_by_squaring, checked_log_base_naive, floor_log_base_by_squaring, floor_log_base_naive, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_approx_ln); register_demo!(runner, demo_natural_floor_log_base); register_demo!(runner, demo_natural_ceiling_log_base); register_demo!(runner, demo_natural_checked_log_base); register_bench!(runner, benchmark_approx_ln); register_bench!(runner, benchmark_natural_floor_log_base_algorithms); register_bench!(runner, benchmark_natural_ceiling_log_base_algorithms); register_bench!(runner, benchmark_natural_checked_log_base_algorithms); } fn demo_natural_approx_ln(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("ln({}) ≈ {}", n, NiceFloat(n.approx_ln())); } } fn demo_natural_floor_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in natural_pair_gen_var_3().get(gm, config).take(limit) { println!( "floor_log_base({}, {}) = {}", n, base, n.floor_log_base(&base) ); } } fn demo_natural_ceiling_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in natural_pair_gen_var_3().get(gm, config).take(limit) { println!( "ceiling_log_base({}, {}) = {}", n, base, n.ceiling_log_base(&base) ); } } fn demo_natural_checked_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in natural_pair_gen_var_3().get(gm, config).take(limit) { println!( "checked_log_base({}, {}) = {:?}", n, base, n.checked_log_base(&base) ); } } fn benchmark_approx_ln(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "(&Natural).approx_ln()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("default", &mut |n| no_out!(n.approx_ln()))], ); } fn benchmark_natural_floor_log_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).floor_log_base(&Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("n", "base"), &mut [ ("default", &mut |(n, base)| no_out!(n.floor_log_base(&base))), ("naive", &mut |(n, base)| { no_out!(floor_log_base_naive(&n, &base)); }), ("by squaring", &mut |(n, base)| { no_out!(floor_log_base_by_squaring(&n, &base)); }), ], ); } fn benchmark_natural_ceiling_log_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).ceiling_log_base(&Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("n", "base"), &mut [ ("default", &mut |(n, base)| { no_out!(n.ceiling_log_base(&base)); }), ("naive", &mut |(n, base)| { no_out!(ceiling_log_base_naive(&n, &base)); }), ("by squaring", &mut |(n, base)| { no_out!(ceiling_log_base_by_squaring(&n, &base)); }), ], ); } fn benchmark_natural_checked_log_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).checked_log_base(&Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("n", "base"), &mut [ ("default", &mut |(n, base)| { no_out!(n.checked_log_base(&base)); }), ("naive", &mut |(n, base)| { no_out!(checked_log_base_naive(&n, &base)); }), ("by squaring", &mut |(n, base)| { no_out!(checked_log_base_by_squaring(&n, &base)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingLogBase2, CheckedLogBase2, FloorLogBase2}; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::log_base_2::{ limbs_ceiling_log_base_2, limbs_checked_log_base_2, limbs_floor_log_base_2, }; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_floor_log_base_2); register_demo!(runner, demo_limbs_ceiling_log_base_2); register_demo!(runner, demo_limbs_checked_log_base_2); register_demo!(runner, demo_natural_floor_log_base_2); register_demo!(runner, demo_natural_ceiling_log_base_2); register_demo!(runner, demo_natural_checked_log_base_2); register_bench!(runner, benchmark_limbs_floor_log_base_2); register_bench!(runner, benchmark_limbs_ceiling_log_base_2); register_bench!(runner, benchmark_limbs_checked_log_base_2); register_bench!(runner, benchmark_natural_floor_log_base_2); register_bench!(runner, benchmark_natural_ceiling_log_base_2); register_bench!(runner, benchmark_natural_checked_log_base_2); } fn demo_limbs_floor_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_floor_log_base_2({:?}) = {}", xs, limbs_floor_log_base_2(&xs) ); } } fn demo_limbs_ceiling_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_ceiling_log_base_2({:?}) = {}", xs, limbs_ceiling_log_base_2(&xs) ); } } fn demo_limbs_checked_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_checked_log_base_2({:?}) = {:?}", xs, limbs_checked_log_base_2(&xs) ); } } fn demo_natural_floor_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("floor_log_base_2({}) = {}", n, n.floor_log_base_2()); } } fn demo_natural_ceiling_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("ceiling_log_base_2({}) = {}", n, n.ceiling_log_base_2()); } } fn demo_natural_checked_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("checked_log_base_2({}) = {:?}", n, n.checked_log_base_2()); } } fn benchmark_limbs_floor_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_floor_log_base_2(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref xs| { no_out!(limbs_floor_log_base_2(xs)); })], ); } fn benchmark_limbs_ceiling_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_ceiling_log_base_2(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref xs| { no_out!(limbs_ceiling_log_base_2(xs)); })], ); } fn benchmark_limbs_checked_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_checked_log_base_2(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |ref xs| { no_out!(limbs_checked_log_base_2(xs)); })], ); } fn benchmark_natural_floor_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_log_base_2()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.floor_log_base_2()))], ); } fn benchmark_natural_ceiling_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_log_base_2()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.ceiling_log_base_2()))], ); } fn benchmark_natural_checked_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_log_base_2()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.checked_log_base_2()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBasePowerOf2, CheckedLogBasePowerOf2, FloorLogBasePowerOf2, }; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_13; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::log_base_power_of_2::{ limbs_ceiling_log_base_power_of_2, limbs_checked_log_base_power_of_2, limbs_floor_log_base_power_of_2, }; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_8; use malachite_nz::test_util::natural::arithmetic::log_base_power_of_2::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_floor_log_base_power_of_2); register_demo!(runner, demo_limbs_ceiling_log_base_power_of_2); register_demo!(runner, demo_limbs_checked_log_base_power_of_2); register_demo!(runner, demo_natural_floor_log_base_power_of_2); register_demo!(runner, demo_natural_ceiling_log_base_power_of_2); register_demo!(runner, demo_natural_checked_log_base_power_of_2); register_bench!(runner, benchmark_limbs_floor_log_base_power_of_2); register_bench!(runner, benchmark_limbs_ceiling_log_base_power_of_2); register_bench!(runner, benchmark_limbs_checked_log_base_power_of_2); register_bench!(runner, benchmark_natural_floor_log_base_power_of_2); register_bench!( runner, benchmark_natural_ceiling_log_base_power_of_2_algorithms ); register_bench!(runner, benchmark_natural_checked_log_base_power_of_2); } fn demo_limbs_floor_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_13() .get(gm, config) .take(limit) { println!( "limbs_floor_log_base_power_of_2({:?}, {}) = {}", xs, pow, limbs_floor_log_base_power_of_2(&xs, pow) ); } } fn demo_limbs_ceiling_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_13() .get(gm, config) .take(limit) { println!( "limbs_ceiling_log_base_power_of_2({:?}, {}) = {}", xs, pow, limbs_ceiling_log_base_power_of_2(&xs, pow) ); } } fn demo_limbs_checked_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_13() .get(gm, config) .take(limit) { println!( "limbs_checked_log_base_power_of_2({:?}, {}) = {:?}", xs, pow, limbs_checked_log_base_power_of_2(&xs, pow) ); } } fn demo_natural_floor_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_8() .get(gm, config) .take(limit) { println!( "floor_log_base_power_of_2({}, {}) = {}", n, pow, n.floor_log_base_power_of_2(pow) ); } } fn demo_natural_ceiling_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_8() .get(gm, config) .take(limit) { println!( "ceiling_log_base_power_of_2({}, {}) = {}", n, pow, n.ceiling_log_base_power_of_2(pow) ); } } fn demo_natural_checked_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_8() .get(gm, config) .take(limit) { println!( "checked_log_base_power_of_2({}, {}) = {:?}", n, pow, n.checked_log_base_power_of_2(pow) ); } } fn benchmark_limbs_floor_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_floor_log_base_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, pow)| { no_out!(limbs_floor_log_base_power_of_2(xs, pow)); })], ); } fn benchmark_limbs_ceiling_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_ceiling_log_base_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, pow)| { no_out!(limbs_ceiling_log_base_power_of_2(xs, pow)); })], ); } fn benchmark_limbs_checked_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_checked_log_base_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_13().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, pow)| { no_out!(limbs_checked_log_base_power_of_2(xs, pow)); })], ); } fn benchmark_natural_floor_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_log_base_power_of_2(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.floor_log_base_power_of_2(pow)); })], ); } fn benchmark_natural_ceiling_log_base_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_log_base_power_of_2(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(n, pow)| { no_out!(n.ceiling_log_base_power_of_2(pow)); }), ("naive", &mut |(ref n, pow)| { no_out!(ceiling_log_base_power_of_2_naive_nz(n, pow)); }), ], ); } fn benchmark_natural_checked_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_log_base_power_of_2(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.checked_log_base_power_of_2(pow)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs_diff::register(runner); add::register(runner); add_mul::register(runner); binomial_coefficient::register(runner); checked_sub::register(runner); checked_sub_mul::register(runner); coprime_with::register(runner); div::register(runner); div_exact::register(runner); div_mod::register(runner); div_round::register(runner); divisible_by::register(runner); divisible_by_power_of_2::register(runner); eq_mod::register(runner); eq_mod_power_of_2::register(runner); extended_gcd::register(runner); factorial::register(runner); gcd::register(runner); is_power_of_2::register(runner); kronecker_symbol::register(runner); lcm::register(runner); log_base::register(runner); log_base_2::register(runner); log_base_power_of_2::register(runner); mod_add::register(runner); mod_inverse::register(runner); mod_is_reduced::register(runner); mod_mul::register(runner); mod_neg::register(runner); mod_op::register(runner); mod_pow::register(runner); mod_power_of_2::register(runner); mod_power_of_2_add::register(runner); mod_power_of_2_inverse::register(runner); mod_power_of_2_is_reduced::register(runner); mod_power_of_2_mul::register(runner); mod_power_of_2_neg::register(runner); mod_power_of_2_pow::register(runner); mod_power_of_2_shl::register(runner); mod_power_of_2_shr::register(runner); mod_power_of_2_square::register(runner); mod_power_of_2_sub::register(runner); mod_shl::register(runner); mod_shr::register(runner); mod_square::register(runner); mod_sub::register(runner); mul::register(runner); neg::register(runner); next_power_of_2::register(runner); parity::register(runner); pow::register(runner); power_of_2::register(runner); primorial::register(runner); root::register(runner); round_to_multiple::register(runner); round_to_multiple_of_power_of_2::register(runner); saturating_sub::register(runner); saturating_sub_mul::register(runner); shl::register(runner); shl_round::register(runner); shr::register(runner); shr_round::register(runner); sign::register(runner); sqrt::register(runner); square::register(runner); sub::register(runner); sub_mul::register(runner); } mod abs_diff; mod add; mod add_mul; mod binomial_coefficient; mod checked_sub; mod checked_sub_mul; mod coprime_with; mod div; mod div_exact; mod div_mod; mod div_round; mod divisible_by; mod divisible_by_power_of_2; mod eq_mod; mod eq_mod_power_of_2; mod extended_gcd; mod factorial; mod gcd; mod is_power_of_2; mod kronecker_symbol; mod lcm; mod log_base; mod log_base_2; mod log_base_power_of_2; mod mod_add; mod mod_inverse; mod mod_is_reduced; mod mod_mul; mod mod_neg; mod mod_op; mod mod_pow; mod mod_power_of_2; mod mod_power_of_2_add; mod mod_power_of_2_inverse; mod mod_power_of_2_is_reduced; mod mod_power_of_2_mul; mod mod_power_of_2_neg; mod mod_power_of_2_pow; mod mod_power_of_2_shl; mod mod_power_of_2_shr; mod mod_power_of_2_square; mod mod_power_of_2_sub; mod mod_shl; mod mod_shr; mod mod_square; mod mod_sub; mod mul; mod neg; mod next_power_of_2; mod parity; mod pow; mod power_of_2; mod primorial; mod root; mod round_to_multiple; mod round_to_multiple_of_power_of_2; mod saturating_sub; mod saturating_sub_mul; mod shl; mod shl_round; mod shr; mod shr_round; mod sign; mod sqrt; mod square; mod sub; mod sub_mul; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModAdd, ModAddAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen_var_3; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_add_assign); register_demo!(runner, demo_natural_mod_add_assign_val_ref); register_demo!(runner, demo_natural_mod_add_assign_ref_val); register_demo!(runner, demo_natural_mod_add_assign_ref_ref); register_demo!(runner, demo_natural_mod_add); register_demo!(runner, demo_natural_mod_add_val_val_ref); register_demo!(runner, demo_natural_mod_add_val_ref_val); register_demo!(runner, demo_natural_mod_add_val_ref_ref); register_demo!(runner, demo_natural_mod_add_ref_val_val); register_demo!(runner, demo_natural_mod_add_ref_val_ref); register_demo!(runner, demo_natural_mod_add_ref_ref_val); register_demo!(runner, demo_natural_mod_add_ref_ref_ref); register_bench!(runner, benchmark_natural_mod_add_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_add_algorithms); register_bench!(runner, benchmark_natural_mod_add_evaluation_strategy); } fn demo_natural_mod_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); x.mod_add_assign(y, m); println!("x := {x_old}; x.mod_add_assign({y_old}, {m_old}); x = {x}"); } } fn demo_natural_mod_add_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let m_old = m.clone(); let y_old = y.clone(); x.mod_add_assign(y, &m); println!("x := {x}; x.mod_add_assign({y_old}, &{m_old}); x = {x}"); } } fn demo_natural_mod_add_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); x.mod_add_assign(&y, m); println!("x := {x_old}; x.mod_add_assign(&{y}, {m_old}); x = {x}"); } } fn demo_natural_mod_add_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_add_assign(&y, &m); println!("x := {x_old}; x.mod_add_assign(&{y}, &{m}); x = {x}"); } } fn demo_natural_mod_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); println!("{} + {} ≡ {} mod {}", x_old, y_old, x.mod_add(y, m), m_old); } } fn demo_natural_mod_add_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} ≡ {} mod {}", x_old, y_old, x.mod_add(y, &m), m); } } fn demo_natural_mod_add_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); println!("{} + {} ≡ {} mod {}", x_old, y, x.mod_add(&y, m), m_old); } } fn demo_natural_mod_add_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + {} ≡ {} mod {}", x_old, y, x.mod_add(&y, &m), m); } } fn demo_natural_mod_add_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); let m_old = m.clone(); println!("{} + {} ≡ {} mod {}", x, y_old, (&x).mod_add(y, m), m_old); } } fn demo_natural_mod_add_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); println!("{} + {} ≡ {} mod {}", x, y_old, (&x).mod_add(y, &m), m); } } fn demo_natural_mod_add_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let m_old = m.clone(); println!("{} + {} ≡ {} mod {}", x, y, (&x).mod_add(&y, m), m_old); } } fn demo_natural_mod_add_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { println!("{} + {} ≡ {} mod {}", x, y, (&x).mod_add(&y, &m), m); } } fn benchmark_natural_mod_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_add_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ( "Natural.mod_add_assign(Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_add_assign(y, m)), ), ( "Natural.mod_add_assign(Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_add_assign(y, &m)), ), ( "Natural.mod_add_assign(&Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_add_assign(&y, m)), ), ( "Natural.mod_add_assign(&Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_add_assign(&y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_add_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_add(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| no_out!(x.mod_add(y, m))), ("naive", &mut |(x, y, m)| no_out!((x + y) % m)), ], ); } fn benchmark_natural_mod_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_add(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("Natural.mod_add(Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_add(y, m)); }), ("Natural.mod_add(Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_add(y, &m)); }), ("Natural.mod_add(&Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_add(&y, m)); }), ("Natural.mod_add(&Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_add(&y, &m)); }), ("(&Natural).mod_add(Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_add(y, m)); }), ("(&Natural).mod_add(Natural, &Natural)", &mut |(x, y, m)| { no_out!((&x).mod_add(y, &m)); }), ("(&Natural).mod_add(&Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_add(&y, m)); }), ( "(&Natural).mod_add(&Natural, &Natural)", &mut |(x, y, m)| no_out!((&x).mod_add(&y, &m)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ModInverse; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen_var_11; use malachite_nz::test_util::natural::arithmetic::mod_inverse::mod_inverse_simple; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_inverse); register_demo!(runner, demo_natural_mod_inverse_val_ref); register_demo!(runner, demo_natural_mod_inverse_ref_val); register_demo!(runner, demo_natural_mod_inverse_ref_ref); register_bench!(runner, benchmark_natural_mod_inverse_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_inverse_algorithms); } fn demo_natural_mod_inverse(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_11().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); if let Some(inverse) = n.mod_inverse(m) { println!("{n_old}⁻¹ ≡ {inverse} mod {m_old}"); } else { println!("{n_old} is not invertible mod {m_old}"); } } } fn demo_natural_mod_inverse_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_11().get(gm, config).take(limit) { let n_old = n.clone(); if let Some(inverse) = n.mod_inverse(&m) { println!("{n_old}⁻¹ ≡ {inverse} mod {m}"); } else { println!("{n_old} is not invertible mod {m}"); } } } fn demo_natural_mod_inverse_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_11().get(gm, config).take(limit) { let m_old = m.clone(); if let Some(inverse) = (&n).mod_inverse(m) { println!("{n}⁻¹ ≡ {inverse} mod {m_old}"); } else { println!("{n} is not invertible mod {m_old}"); } } } fn demo_natural_mod_inverse_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_11().get(gm, config).take(limit) { if let Some(inverse) = (&n).mod_inverse(&m) { println!("{n}⁻¹ ≡ {inverse} mod {m}"); } else { println!("{n} is not invertible mod {m}"); } } } fn benchmark_natural_mod_inverse_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_inverse(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_inverse(Natural)", &mut |(n, m)| { no_out!(n.mod_inverse(m)); }), ("Natural.mod_inverse(&Natural)", &mut |(n, m)| { no_out!(n.mod_inverse(&m)); }), ("(&Natural).mod_inverse(Natural)", &mut |(n, m)| { no_out!((&n).mod_inverse(m)); }), ("(&Natural).mod_inverse(&Natural)", &mut |(n, m)| { no_out!((&n).mod_inverse(&m)); }), ], ); } fn benchmark_natural_mod_inverse_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_inverse(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("default", &mut |(n, m)| no_out!(n.mod_inverse(m))), ("simple", &mut |(n, m)| no_out!(mod_inverse_simple(n, m))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ModIsReduced; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen_var_5; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_is_reduced); register_bench!(runner, benchmark_natural_mod_is_reduced); } fn demo_natural_mod_is_reduced(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_5().get(gm, config).take(limit) { if n.mod_is_reduced(&m) { println!("{n} is reduced mod {m}"); } else { println!("{n} is not reduced mod {m}"); } } } fn benchmark_natural_mod_is_reduced( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_is_reduced(&Natural)", BenchmarkType::Single, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(n, m)| no_out!(n.mod_is_reduced(&m)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModMul, ModMulAssign, ModMulPrecomputed}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_pair_gen_var_36; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_mul::{ limbs_mod_mul_two_limbs, limbs_precompute_mod_mul_two_limbs, }; use malachite_nz::test_util::bench::bucketers::{ limb_pair_significant_bits_bucketer, limbs_mod_mul_two_limbs_bucketer, triple_3_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{large_type_gen_var_21, natural_triple_gen_var_3}; use malachite_nz::test_util::natural::arithmetic::mod_mul::{ limbs_mod_mul_two_limbs_naive, limbs_precompute_mod_mul_two_limbs_alt, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_precompute_mod_mul_two_limbs); register_demo!(runner, demo_limbs_mod_mul_two_limbs); register_demo!(runner, demo_natural_mod_mul_assign); register_demo!(runner, demo_natural_mod_mul_assign_val_ref); register_demo!(runner, demo_natural_mod_mul_assign_ref_val); register_demo!(runner, demo_natural_mod_mul_assign_ref_ref); register_demo!(runner, demo_natural_mod_mul); register_demo!(runner, demo_natural_mod_mul_val_val_ref); register_demo!(runner, demo_natural_mod_mul_val_ref_val); register_demo!(runner, demo_natural_mod_mul_val_ref_ref); register_demo!(runner, demo_natural_mod_mul_ref_val_val); register_demo!(runner, demo_natural_mod_mul_ref_val_ref); register_demo!(runner, demo_natural_mod_mul_ref_ref_val); register_demo!(runner, demo_natural_mod_mul_ref_ref_ref); register_bench!( runner, benchmark_limbs_precompute_mod_mul_two_limbs_algorithms ); register_bench!(runner, benchmark_limbs_mod_mul_two_limbs); register_bench!(runner, benchmark_natural_mod_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_mul_algorithms); register_bench!(runner, benchmark_natural_mod_mul_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_mul_precomputed_algorithms); } fn demo_limbs_precompute_mod_mul_two_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for (m_1, m_0) in unsigned_pair_gen_var_36().get(gm, config).take(limit) { println!( "limbs_precompute_mod_mul_two_limbs({}, {}) = {:?}", m_1, m_0, limbs_precompute_mod_mul_two_limbs(m_1, m_0) ); } } fn demo_limbs_mod_mul_two_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for (x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0) in large_type_gen_var_21().get(gm, config).take(limit) { println!( "limbs_mod_mul_two_limbs({}, {}, {}, {}, {}, {}, {}, {}, {}) = {:?}", x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0, limbs_mod_mul_two_limbs(x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0) ); } } fn demo_natural_mod_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); x.mod_mul_assign(y, m); println!("x := {x_old}; x.mod_mul_assign({y_old}, {m_old}); x = {x}"); } } fn demo_natural_mod_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let m_old = m.clone(); let y_old = y.clone(); x.mod_mul_assign(y, &m); println!("x := {x}; x.mod_mul_assign({y_old}, &{m_old}); x = {x}"); } } fn demo_natural_mod_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); x.mod_mul_assign(&y, m); println!("x := {x_old}; x.mod_mul_assign(&{y}, {m_old}); x = {x}"); } } fn demo_natural_mod_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_mul_assign(&y, &m); println!("x := {x_old}; x.mod_mul_assign(&{y}, &{m}); x = {x}"); } } fn demo_natural_mod_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); println!("{} * {} ≡ {} mod {}", x_old, y_old, x.mod_mul(y, m), m_old); } } fn demo_natural_mod_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} ≡ {} mod {}", x_old, y_old, x.mod_mul(y, &m), m); } } fn demo_natural_mod_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); println!("{} * {} ≡ {} mod {}", x_old, y, x.mod_mul(&y, m), m_old); } } fn demo_natural_mod_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * {} ≡ {} mod {}", x_old, y, x.mod_mul(&y, &m), m); } } fn demo_natural_mod_mul_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); let m_old = m.clone(); println!("{} * {} ≡ {} mod {}", x, y_old, (&x).mod_mul(y, m), m_old); } } fn demo_natural_mod_mul_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); println!("{} * {} ≡ {} mod {}", x, y_old, (&x).mod_mul(y, &m), m); } } fn demo_natural_mod_mul_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let m_old = m.clone(); println!("{} * {} ≡ {} mod {}", x, y, (&x).mod_mul(&y, m), m_old); } } fn demo_natural_mod_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { println!("{} * {} ≡ {} mod {}", x, y, (&x).mod_mul(&y, &m), m); } } fn benchmark_limbs_precompute_mod_mul_two_limbs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_precompute_mod_mul_two_limbs(Limb, Limb)", BenchmarkType::Algorithms, unsigned_pair_gen_var_36().get(gm, config), gm.name(), limit, file_name, &limb_pair_significant_bits_bucketer("m"), &mut [ ("default", &mut |(m_1, m_0)| { no_out!(limbs_precompute_mod_mul_two_limbs(m_1, m_0)); }), ("alt", &mut |(m_1, m_0)| { no_out!(limbs_precompute_mod_mul_two_limbs_alt(m_1, m_0)); }), ], ); } fn benchmark_limbs_mod_mul_two_limbs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_mul_two_limbs(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)", BenchmarkType::Single, large_type_gen_var_21().get(gm, config), gm.name(), limit, file_name, &limbs_mod_mul_two_limbs_bucketer(), &mut [ ("default", &mut |( x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0, )| { no_out!(limbs_mod_mul_two_limbs( x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0 )); }), ("naive", &mut |(x_1, x_0, y_1, y_0, m_1, m_0, _, _, _)| { no_out!(limbs_mod_mul_two_limbs_naive(x_1, x_0, y_1, y_0, m_1, m_0)); }), ], ); } fn benchmark_natural_mod_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ( "Natural.mod_mul_assign(Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_mul_assign(y, m)), ), ( "Natural.mod_mul_assign(Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_mul_assign(y, &m)), ), ( "Natural.mod_mul_assign(&Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_mul_assign(&y, m)), ), ( "Natural.mod_mul_assign(&Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_mul_assign(&y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_mul(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| no_out!(x.mod_mul(y, m))), ("naive", &mut |(x, y, m)| no_out!((x * y) % m)), ], ); } fn benchmark_natural_mod_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_mul(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("Natural.mod_mul(Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_mul(y, m)); }), ("Natural.mod_mul(Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_mul(y, &m)); }), ("Natural.mod_mul(&Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_mul(&y, m)); }), ("Natural.mod_mul(&Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_mul(&y, &m)); }), ("(&Natural).mod_mul(Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_mul(y, m)); }), ("(&Natural).mod_mul(Natural, &Natural)", &mut |(x, y, m)| { no_out!((&x).mod_mul(y, &m)); }), ("(&Natural).mod_mul(&Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_mul(&y, m)); }), ( "(&Natural).mod_mul(&Natural, &Natural)", &mut |(x, y, m)| no_out!((&x).mod_mul(&y, &m)), ), ], ); } fn benchmark_natural_mod_mul_precomputed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_mul_precomputed(Natural, Natural, &ModMulData)", BenchmarkType::Algorithms, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| { for _ in 0..10 { (&x).mod_mul(&y, &m); } }), ("precomputed", &mut |(x, y, m)| { let data = ModMulPrecomputed::::precompute_mod_mul_data(&m); for _ in 0..10 { (&x).mod_mul_precomputed(&y, &m, &data); } }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Mod, ModNeg, ModNegAssign}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_2_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen_var_8; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_neg_assign); register_demo!(runner, demo_natural_mod_neg_assign_ref); register_demo!(runner, demo_natural_mod_neg); register_demo!(runner, demo_natural_mod_neg_val_ref); register_demo!(runner, demo_natural_mod_neg_ref_val); register_demo!(runner, demo_natural_mod_neg_ref_ref); register_bench!(runner, benchmark_natural_mod_neg_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_neg_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_neg_algorithms); } fn demo_natural_mod_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); n.mod_neg_assign(m); println!("x := {n_old}; x.mod_neg_assign({m_old}); x = {n}"); } } fn demo_natural_mod_neg_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); n.mod_neg_assign(&m); println!("x := {n_old}; x.mod_neg_assign(&{m}); x = {n}"); } } fn demo_natural_mod_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!("-{} ≡ {} mod {}", n_old, n.mod_neg(m), m_old); } } fn demo_natural_mod_neg_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); println!("-{} ≡ {} mod &{}", n_old, n.mod_neg(&m), m); } } fn demo_natural_mod_neg_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let m_old = m.clone(); println!("&(-{}) ≡ {} mod {}", n, (&n).mod_neg(m), m_old); } } fn demo_natural_mod_neg_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { println!("&(-{}) ≡ {} mod &{}", n, (&n).mod_neg(&m), m); } } fn benchmark_natural_mod_neg_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_neg_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_neg_assign(Natural)", &mut |(mut n, m)| { n.mod_neg_assign(m); }), ("Natural.mod_neg_assign(&Natural)", &mut |(mut n, m)| { n.mod_neg_assign(&m); }), ], ); } fn benchmark_natural_mod_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_neg(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_neg(Natural)", &mut |(n, m)| { no_out!(n.mod_neg(m)); }), ("Natural.mod_neg(&Natural)", &mut |(n, m)| { no_out!(n.mod_neg(&m)); }), ("(&Natural).mod_neg(Natural)", &mut |(n, m)| { no_out!((&n).mod_neg(m)); }), ("(&Natural).mod_neg(&Natural)", &mut |(n, m)| { no_out!((&n).mod_neg(&m)); }), ], ); } fn benchmark_natural_mod_neg_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_neg(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_neg(Natural)", &mut |(n, m)| { no_out!(n.mod_neg(m)); }), ("(-Natural).mod(Natural)", &mut |(n, m)| { no_out!(Natural::exact_from((-n).mod_op(Integer::from(m)))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivMod; use malachite_base::num::arithmetic::traits::{ CeilingDivNegMod, Mod, ModAssign, NegMod, NegModAssign, }; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_1_vec_len_sub_1_bucketer, quadruple_2_3_diff_vec_len_bucketer, quadruple_2_vec_len_bucketer, quadruple_3_vec_len_bucketer, quadruple_4_vec_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_24; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_11, unsigned_vec_pair_gen_var_18, unsigned_vec_triple_gen_var_57, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_pair_gen_var_25, unsigned_vec_unsigned_pair_gen_var_26, unsigned_vec_unsigned_pair_gen_var_27, unsigned_vec_unsigned_pair_gen_var_28, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::div_mod::{ limbs_div_mod_barrett, limbs_div_mod_barrett_scratch_len, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_divide_and_conquer, limbs_div_mod_schoolbook, limbs_div_mod_to_out, }; use malachite_nz::natural::arithmetic::mod_op::{ limbs_mod, limbs_mod_barrett, limbs_mod_by_two_limb_normalized, limbs_mod_divide_and_conquer, limbs_mod_limb, limbs_mod_limb_alt_1, limbs_mod_limb_alt_2, limbs_mod_limb_any_leading_zeros, limbs_mod_limb_any_leading_zeros_1, limbs_mod_limb_any_leading_zeros_2, limbs_mod_limb_at_least_1_leading_zero, limbs_mod_limb_at_least_2_leading_zeros, limbs_mod_limb_small_normalized, limbs_mod_limb_small_normalized_large, limbs_mod_limb_small_small, limbs_mod_limb_small_unnormalized, limbs_mod_limb_small_unnormalized_large, limbs_mod_schoolbook, limbs_mod_three_limb_by_two_limb, limbs_mod_to_out, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ limbs_mod_limb_small_unnormalized_bucketer, pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ large_type_gen_var_11, large_type_gen_var_12, natural_pair_gen_var_5, natural_pair_gen_var_5_nrm, natural_pair_gen_var_5_rm, unsigned_sextuple_gen_var_2, unsigned_vec_quadruple_gen_var_1, unsigned_vec_quadruple_gen_var_5, unsigned_vec_triple_gen_var_56, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17, }; use malachite_nz::test_util::natural::arithmetic::mod_op::{limbs_mod_limb_alt_3, rug_neg_mod}; use num::Integer; use rug::ops::RemRounding; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_limb); register_demo!(runner, demo_limbs_mod_limb_small_normalized); register_demo!(runner, demo_limbs_mod_limb_small_unnormalized); register_demo!(runner, demo_limbs_mod_limb_any_leading_zeros_1); register_demo!(runner, demo_limbs_mod_limb_any_leading_zeros_2); register_demo!(runner, demo_limbs_mod_limb_at_least_1_leading_zero); register_demo!(runner, demo_limbs_mod_limb_at_least_2_leading_zeros); register_demo!(runner, demo_limbs_mod_three_limb_by_two_limb); register_demo!(runner, demo_limbs_mod_by_two_limb_normalized); register_demo!(runner, demo_limbs_mod_schoolbook); register_demo!(runner, demo_limbs_mod_divide_and_conquer); register_demo!(runner, demo_limbs_mod_barrett); register_demo!(runner, demo_limbs_mod); register_demo!(runner, demo_limbs_mod_to_out); register_demo!(runner, demo_natural_mod_assign); register_demo!(runner, demo_natural_mod_assign_ref); register_demo!(runner, demo_natural_mod); register_demo!(runner, demo_natural_mod_val_ref); register_demo!(runner, demo_natural_mod_ref_val); register_demo!(runner, demo_natural_mod_ref_ref); register_demo!(runner, demo_natural_rem_assign); register_demo!(runner, demo_natural_rem_assign_ref); register_demo!(runner, demo_natural_rem); register_demo!(runner, demo_natural_rem_val_ref); register_demo!(runner, demo_natural_rem_ref_val); register_demo!(runner, demo_natural_rem_ref_ref); register_demo!(runner, demo_natural_neg_mod_assign); register_demo!(runner, demo_natural_neg_mod_assign_ref); register_demo!(runner, demo_natural_neg_mod); register_demo!(runner, demo_natural_neg_mod_val_ref); register_demo!(runner, demo_natural_neg_mod_ref_val); register_demo!(runner, demo_natural_neg_mod_ref_ref); register_bench!(runner, benchmark_limbs_mod_limb_algorithms); register_bench!(runner, benchmark_limbs_mod_limb_small_normalized_algorithms); register_bench!( runner, benchmark_limbs_mod_limb_small_unnormalized_algorithms ); register_bench!( runner, benchmark_limbs_mod_limb_any_leading_zeros_from_normalized_algorithms ); register_bench!( runner, benchmark_limbs_mod_limb_any_leading_zeros_from_unnormalized_algorithms ); register_bench!( runner, benchmark_limbs_mod_limb_at_least_1_leading_zero_algorithms ); register_bench!( runner, benchmark_limbs_mod_limb_at_least_2_leading_zeros_algorithms ); register_bench!( runner, benchmark_limbs_mod_by_two_limb_normalized_algorithms ); register_bench!(runner, benchmark_limbs_mod_schoolbook_algorithms); register_bench!(runner, benchmark_limbs_mod_divide_and_conquer_algorithms); register_bench!(runner, benchmark_limbs_mod_barrett_algorithms); register_bench!(runner, benchmark_limbs_mod); register_bench!(runner, benchmark_limbs_mod_to_out_algorithms); register_bench!(runner, benchmark_natural_mod_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_library_comparison); register_bench!(runner, benchmark_natural_mod_algorithms); register_bench!(runner, benchmark_natural_mod_evaluation_strategy); register_bench!(runner, benchmark_natural_rem_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_rem_library_comparison); register_bench!(runner, benchmark_natural_rem_evaluation_strategy); register_bench!(runner, benchmark_natural_neg_mod_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_neg_mod_library_comparison); register_bench!(runner, benchmark_natural_neg_mod_algorithms); register_bench!(runner, benchmark_natural_neg_mod_evaluation_strategy); } fn demo_limbs_mod_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_mod_limb({:?}, {}) = {}", ns, d, limbs_mod_limb::(&ns, d) ); } } fn demo_limbs_mod_limb_small_normalized(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_26() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_small_normalized({:?}, {}) = {}", ns, d, limbs_mod_limb_small_normalized::(&ns, d) ); } } fn demo_limbs_mod_limb_small_unnormalized(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_27() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_small_unnormalized({:?}, {}) = {}", ns, d, limbs_mod_limb_small_unnormalized::(&ns, d) ); } } fn demo_limbs_mod_limb_any_leading_zeros_1(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_any_leading_zeros_1({:?}, {}) = {}", ns, d, limbs_mod_limb_any_leading_zeros_1::(&ns, d) ); } } fn demo_limbs_mod_limb_any_leading_zeros_2(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_22() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_any_leading_zeros_2({:?}, {}) = {}", ns, d, limbs_mod_limb_any_leading_zeros_2::(&ns, d) ); } } fn demo_limbs_mod_limb_at_least_1_leading_zero(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_27() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_at_least_1_leading_zero({:?}, {}) = {}", ns, d, limbs_mod_limb_at_least_1_leading_zero::(&ns, d) ); } } fn demo_limbs_mod_limb_at_least_2_leading_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, d) in unsigned_vec_unsigned_pair_gen_var_28() .get(gm, config) .take(limit) { println!( "limbs_mod_limb_at_least_2_leading_zeros({:?}, {}) = {}", ns, d, limbs_mod_limb_at_least_2_leading_zeros::(&ns, d) ); } } fn demo_limbs_mod_three_limb_by_two_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (n2, n1, n0, d1, d0, inverse) in unsigned_sextuple_gen_var_2().get(gm, config).take(limit) { println!( "limbs_mod_three_limb_by_two_limb({}, {}, {}, {}, {}, {}) = {}", n2, n1, n0, d1, d0, inverse, limbs_mod_three_limb_by_two_limb(n2, n1, n0, d1, d0, inverse) ); } } fn demo_limbs_mod_by_two_limb_normalized(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_18().get(gm, config).take(limit) { println!( "limbs_mod_by_two_limb_normalized({:?}, {:?}) = {:?}", ns, ds, limbs_mod_by_two_limb_normalized(&ns, &ds), ); } } fn demo_limbs_mod_schoolbook(gm: GenMode, config: &GenConfig, limit: usize) { for (mut ns, ds, inverse) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17() .get(gm, config) .take(limit) { let old_ns = ns.clone(); limbs_mod_schoolbook(&mut ns, &ds, inverse); println!("ns := {old_ns:?}; limbs_mod_schoolbook(&mut ns, {ds:?}, {inverse}); ns = {ns:?}"); } } fn demo_limbs_mod_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut ns, ds, inverse) in large_type_gen_var_12().get(gm, config).take(limit) { let old_qs = qs.clone(); let old_ns = ns.clone(); limbs_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); println!( "qs := {old_qs:?}; ns := {old_ns:?}; \ limbs_mod_divide_and_conquer(&mut qs, &mut ns, {ds:?}, {inverse}); ns = {ns:?}", ); } } fn demo_limbs_mod_barrett(gm: GenMode, config: &GenConfig, limit: usize) { for (mut qs, mut rs, ns, ds) in unsigned_vec_quadruple_gen_var_5() .get(gm, config) .take(limit) { let old_qs = qs.clone(); let old_rs = rs.clone(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); println!( "qs := {old_qs:?}; \ rs := {old_rs:?}; limbs_mod_barrett(&mut qs, &mut ns, {ns:?}, {ds:?}); rs = {rs:?}", ); } } fn demo_limbs_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (ns, ds) in unsigned_vec_pair_gen_var_11().get(gm, config).take(limit) { println!("limbs_mod({:?}, {:?}) = {:?}", ns, ds, limbs_mod(&ns, &ds)); } } fn demo_limbs_mod_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut rs, ns, ds) in unsigned_vec_triple_gen_var_57().get(gm, config).take(limit) { let old_rs = rs.clone(); limbs_mod_to_out(&mut rs, &ns, &ds); println!("rs := {old_rs:?}; limbs_mod_to_out(&mut rs, {ns:?}, {ds:?}); rs = {rs:?}"); } } fn demo_natural_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_assign(y); println!("x := {x_old}; x.mod_assign({y_old}); x = {x}"); } } fn demo_natural_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_assign(&y); println!("x := {x_old}; x.mod_assign(&{y}); x = {x}"); } } fn demo_natural_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.mod_op({}) = {}", x_old, y_old, x.mod_op(y)); } } fn demo_natural_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.mod_op(&{}) = {}", x_old, y, x.mod_op(&y)); } } fn demo_natural_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).mod_op({}) = {:?}", x, y_old, (&x).mod_op(y)); } } fn demo_natural_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("(&{}).mod_op(&{}) = {:?}", x, y, (&x).mod_op(&y)); } } fn demo_natural_rem_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x %= y; println!("x := {x_old}; x %= {y_old}; x = {x}"); } } fn demo_natural_rem_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); x %= &y; println!("x := {x_old}; x %= &{y}; x = {x}"); } } fn demo_natural_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} % {} = {:?}", x_old, y_old, x % y); } } fn demo_natural_rem_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} % &{} = {:?}", x_old, y, x % &y); } } fn demo_natural_rem_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} % {} = {:?}", x, y_old, &x % y); } } fn demo_natural_rem_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("&{} % &{} = {:?}", x, y, &x % &y); } } fn demo_natural_neg_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.neg_mod_assign(y); println!("x := {x_old}; x.neg_mod_assign({y_old}); x = {x}"); } } fn demo_natural_neg_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); x.neg_mod_assign(&y); println!("x := {x_old}; x.neg_mod_assign(&{y}); x = {x}"); } } fn demo_natural_neg_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.neg_mod({}) = {}", x_old, y_old, x.neg_mod(y)); } } fn demo_natural_neg_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.neg_mod(&{}) = {}", x_old, y, x.neg_mod(&y)); } } fn demo_natural_neg_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).neg_mod({}) = {}", x, y_old, (&x).neg_mod(y)); } } fn demo_natural_neg_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!("(&{}).neg_mod(&{}) = {}", x, y, (&x).neg_mod(&y)); } } fn benchmark_limbs_mod_limb_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("alt 1", &mut |(ns, d)| { no_out!(limbs_mod_limb_alt_1::(&ns, d)); }), ("alt 2", &mut |(ns, d)| { no_out!(limbs_mod_limb_alt_2::(&ns, d)); }), ("alt 3", &mut |(ns, d)| { no_out!(limbs_mod_limb_alt_3(&ns, d)); }), ("limbs_mod_limb_any_leading_zeros_1", &mut |(ns, d)| { no_out!(limbs_mod_limb_any_leading_zeros_1::( &ns, d )); }), ("limbs_mod_limb_any_leading_zeros_2", &mut |(ns, d)| { no_out!(limbs_mod_limb_any_leading_zeros_2::( &ns, d )); }), ], ); } fn benchmark_limbs_mod_limb_small_normalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_small_normalized(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_26().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_sub_1_bucketer("ns"), &mut [ ("small", &mut |(ns, d)| { let mut len = ns.len(); let mut r = ns[len - 1]; if r >= d { r -= d; } len -= 1; if len == 0 { return; } limbs_mod_limb_small_small::(&ns[..len], d, r); }), ("large", &mut |(ns, d)| { let mut len = ns.len(); let mut r = ns[len - 1]; if r >= d { r -= d; } len -= 1; if len == 0 { return; } limbs_mod_limb_small_normalized_large::(&ns[..len], d, r); }), ], ); } fn benchmark_limbs_mod_limb_small_unnormalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_small_unnormalized(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_27().get(gm, config), gm.name(), limit, file_name, &limbs_mod_limb_small_unnormalized_bucketer(), &mut [ ("small", &mut |(ns, d)| { let mut len = ns.len(); let mut r = ns[len - 1]; if r < d { len -= 1; if len == 0 { return; } } else { r = 0; } limbs_mod_limb_small_small::(&ns[..len], d, r); }), ("large", &mut |(ns, d)| { let mut len = ns.len(); let mut r = ns[len - 1]; if r < d { len -= 1; if len == 0 { return; } } else { r = 0; } limbs_mod_limb_small_unnormalized_large::(&ns[..len], d, r); }), ], ); } fn benchmark_limbs_mod_limb_any_leading_zeros_from_normalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_any_leading_zeros(&[Limb], Limb) from normalized", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_24().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("limbs_mod_limb_small_normalized", &mut |(ns, d)| { no_out!(limbs_mod_limb_small_normalized::(&ns, d)); }), ("limbs_mod_limb_any_leading_zeros", &mut |(ns, d)| { no_out!(limbs_mod_limb_any_leading_zeros::(&ns, d)); }), ], ); } fn benchmark_limbs_mod_limb_any_leading_zeros_from_unnormalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_any_leading_zeros(&[Limb], Limb) from unnormalized", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_25().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("limbs_mod_limb_small_unnormalized", &mut |(ns, d)| { no_out!(limbs_mod_limb_small_unnormalized::( &ns, d )); }), ("limbs_mod_limb_any_leading_zeros", &mut |(ns, d)| { no_out!(limbs_mod_limb_any_leading_zeros::(&ns, d)); }), ], ); } fn benchmark_limbs_mod_limb_at_least_1_leading_zero_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_at_least_1_leading_zero(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_25().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("limbs_mod_limb_any_leading_zeros", &mut |(ns, d)| { no_out!(limbs_mod_limb_any_leading_zeros::(&ns, d)); }), ("limbs_mod_limb_at_least_1_leading_zero", &mut |(ns, d)| { no_out!(limbs_mod_limb_at_least_1_leading_zero::( &ns, d )); }), ], ); } fn benchmark_limbs_mod_limb_at_least_2_leading_zeros_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_limb_at_least_2_leading_zeros(&[Limb], Limb)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_28().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ns"), &mut [ ("Malachite", &mut |(ns, d)| { no_out!(limbs_mod_limb_at_least_1_leading_zero::( &ns, d )); }), ("limbs_mod_limb_at_least_2_leading_zeros", &mut |(ns, d)| { no_out!(limbs_mod_limb_at_least_2_leading_zeros::( &ns, d )); }), ], ); } fn benchmark_limbs_mod_by_two_limb_normalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_by_two_limb_normalized(&[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_56().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("ns"), &mut [ ("using div/mod", &mut |(mut qs, mut ns, ds)| { no_out!(limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, &ds)); }), ("standard", &mut |(_, ns, ds)| { no_out!(limbs_mod_by_two_limb_normalized(&ns, &ds)); }), ], ); } fn benchmark_limbs_mod_schoolbook_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_schoolbook(&mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_11().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("ns"), &mut [ ("using div/mod", &mut |(mut qs, mut ns, ds, inverse)| { no_out!(limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse)); }), ("standard", &mut |(_, mut ns, ds, inverse)| { limbs_mod_schoolbook(&mut ns, &ds, inverse); }), ], ); } // use large params fn benchmark_limbs_mod_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_divide_and_conquer(&mut [Limb], &mut [Limb], &[Limb], Limb)", BenchmarkType::Algorithms, large_type_gen_var_12().get(gm, config), gm.name(), limit, file_name, &quadruple_2_3_diff_vec_len_bucketer("ns", "ds"), &mut [ ("Schoolbook", &mut |(_, mut ns, ds, inverse)| { limbs_mod_schoolbook(&mut ns, &ds, inverse); }), ("divide-and-conquer using div/mod", &mut |( mut qs, mut ns, ds, inverse, )| { no_out!(limbs_div_mod_divide_and_conquer( &mut qs, &mut ns, &ds, inverse )); }), ("divide-and-conquer", &mut |( mut qs, mut ns, ds, inverse, )| { limbs_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); }), ], ); } fn benchmark_limbs_mod_barrett_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_barrett(&mut [Limb], &mut [Limb], &[Limb], &[Limb], &mut Limb)", BenchmarkType::Algorithms, unsigned_vec_quadruple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &quadruple_4_vec_len_bucketer("ds"), &mut [ ("Barrett using div/mod", &mut |(mut qs, mut rs, ns, ds)| { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); }), ("Barrett", &mut |(mut qs, mut rs, ns, ds)| { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); }), ], ); } fn benchmark_limbs_mod(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mod(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("ds"), &mut [("Malachite", &mut |(ns, ds)| no_out!(limbs_mod(&ns, &ds)))], ); } fn benchmark_limbs_mod_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("ns"), &mut [ ("using div/mod", &mut |(qs, mut rs, ns, ds)| { // Allocate again to make benchmark fair let mut qs = vec![0; qs.len()]; limbs_div_mod_to_out(&mut qs, &mut rs, &ns, &ds); }), ("standard", &mut |(_, mut rs, ns, ds)| { limbs_mod_to_out(&mut rs, &ns, &ds); }), ], ); } fn benchmark_natural_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.mod_assign(Natural)", &mut |(mut x, y)| { no_out!(x.mod_assign(y)); }), ("Natural.mod_assign(&Natural)", &mut |(mut x, y)| { no_out!(x.mod_assign(&y)); }), ], ); } fn benchmark_natural_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_op(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.mod_op(y))), ("num", &mut |((x, y), _, _)| no_out!(x.mod_floor(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.rem_floor(y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_op(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("standard", &mut |(x, y)| no_out!(x.mod_op(y))), ("using div_mod", &mut |(x, y)| no_out!(x.div_mod(y).1)), ], ); } fn benchmark_natural_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_op(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.mod_op(Natural)", &mut |(x, y)| { no_out!(x.mod_op(y)); }), ("Natural.mod_op(&Natural)", &mut |(x, y)| { no_out!(x.mod_op(&y)); }), ("(&Natural).mod_op(Natural)", &mut |(x, y)| { no_out!((&x).mod_op(y)); }), ("(&Natural).mod_op(&Natural)", &mut |(x, y)| { no_out!((&x).mod_op(&y)); }), ], ); } fn benchmark_natural_rem_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural %= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural %= Natural", &mut |(mut x, y)| x %= y), ("Natural %= &Natural", &mut |(mut x, y)| x %= &y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural % Natural", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x % y)), ("num", &mut |((x, y), _, _)| no_out!(x % y)), ("rug", &mut |(_, (x, y), _)| no_out!(x % y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural % Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural % Natural", &mut |(x, y)| no_out!(x % y)), ("Natural % &Natural", &mut |(x, y)| no_out!(x % &y)), ("&Natural % Natural", &mut |(x, y)| no_out!(&x % y)), ("&Natural % &Natural", &mut |(x, y)| no_out!(&x % &y)), ], ); } fn benchmark_natural_neg_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.neg_mod_assign(Natural)", &mut |(mut x, y)| { no_out!(x.neg_mod_assign(y)); }), ("Natural.neg_mod_assign(&Natural)", &mut |(mut x, y)| { no_out!(x.neg_mod_assign(&y)); }), ], ); } fn benchmark_natural_neg_mod_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod(Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_var_5_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.neg_mod(y))), ("rug", &mut |((x, y), _)| no_out!(rug_neg_mod(x, y))), ], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_neg_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("standard", &mut |(x, y)| no_out!(x.neg_mod(y))), ("using ceiling_div_neg_mod", &mut |(x, y)| { no_out!(x.ceiling_div_neg_mod(y).1); }), ], ); } fn benchmark_natural_neg_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.neg_mod(Natural)", &mut |(x, y)| { no_out!(x.neg_mod(y)); }), ("Natural.neg_mod(&Natural)", &mut |(x, y)| { no_out!(x.neg_mod(&y)); }), ("(&Natural).neg_mod(Natural)", &mut |(x, y)| { no_out!((&x).neg_mod(y)); }), ("(&Natural).neg_mod(&Natural)", &mut |(x, y)| { no_out!((&x).neg_mod(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPow, ModPowAssign}; use malachite_base::test_util::bench::bucketers::quadruple_4_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::mod_pow::{ limbs_mod_pow, limbs_mod_pow_odd, limbs_mod_pow_odd_scratch_len, }; use malachite_nz::test_util::bench::bucketers::{ triple_1_3_prod_natural_bits_bucketer, triple_3_triple_1_3_prod_natural_bits_bucketer, }; use malachite_nz::test_util::generators::{ natural_triple_gen_var_5, natural_triple_gen_var_5_nrm, unsigned_vec_quadruple_gen_var_6, unsigned_vec_quadruple_gen_var_7, }; use malachite_nz::test_util::natural::arithmetic::mod_pow::simple_binary_mod_pow; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_pow_odd); register_demo!(runner, demo_limbs_mod_pow); register_demo!(runner, demo_natural_mod_pow_assign); register_demo!(runner, demo_natural_mod_pow_assign_val_ref); register_demo!(runner, demo_natural_mod_pow_assign_ref_val); register_demo!(runner, demo_natural_mod_pow_assign_ref_ref); register_demo!(runner, demo_natural_mod_pow); register_demo!(runner, demo_natural_mod_pow_val_val_ref); register_demo!(runner, demo_natural_mod_pow_val_ref_val); register_demo!(runner, demo_natural_mod_pow_val_ref_ref); register_demo!(runner, demo_natural_mod_pow_ref_val_val); register_demo!(runner, demo_natural_mod_pow_ref_val_ref); register_demo!(runner, demo_natural_mod_pow_ref_ref_val); register_demo!(runner, demo_natural_mod_pow_ref_ref_ref); register_bench!(runner, benchmark_limbs_mod_pow_odd); register_bench!(runner, benchmark_limbs_mod_pow); register_bench!(runner, benchmark_natural_mod_pow_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_pow_algorithms); register_bench!(runner, benchmark_natural_mod_pow_library_comparison); register_bench!(runner, benchmark_natural_mod_pow_evaluation_strategy); } fn demo_limbs_mod_pow_odd(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, es, ms) in unsigned_vec_quadruple_gen_var_7() .get(gm, config) .take(limit) { let out_old = out.clone(); let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(ms.len())]; limbs_mod_pow_odd(&mut out, &xs, &es, &ms, &mut scratch); println!( "out := {out_old:?}; \ limbs_mod_pow_odd(&mut out, {xs:?}, {es:?}, {ms:?}, &mut scratch); out = {out:?}", ); } } fn demo_limbs_mod_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, es, ms) in unsigned_vec_quadruple_gen_var_6() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_mod_pow(&mut out, &xs, &es, &ms); println!( "out := {out_old:?}; limbs_mod_pow(&mut out, {xs:?}, {es:?}, {ms:?}); out = {out:?}", ); } } fn demo_natural_mod_pow_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let exp_old = exp.clone(); let m_old = m.clone(); x.mod_pow_assign(exp, m); println!("x := {x_old}; x.mod_pow_assign({exp_old}, {m_old}); x = {x}"); } } fn demo_natural_mod_pow_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let m_old = m.clone(); let exp_old = exp.clone(); x.mod_pow_assign(exp, &m); println!("x := {x}; x.mod_pow_assign({exp_old}, &{m_old}); x = {x}"); } } fn demo_natural_mod_pow_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); x.mod_pow_assign(&exp, m); println!("x := {x_old}; x.mod_pow_assign(&{exp}, {m_old}); x = {x}"); } } fn demo_natural_mod_pow_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_pow_assign(&exp, &m); println!("x := {x_old}; x.mod_pow_assign(&{exp}, &{m}); x = {x}"); } } fn demo_natural_mod_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let exp_old = exp.clone(); let m_old = m.clone(); println!( "{}.pow({}) ≡ {} mod {}", x_old, exp_old, x.mod_pow(exp, m), m_old ); } } fn demo_natural_mod_pow_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let exp_old = exp.clone(); println!( "{}.pow({}) ≡ {} mod {}", x_old, exp_old, x.mod_pow(exp, &m), m ); } } fn demo_natural_mod_pow_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); println!( "{}.pow({}) ≡ {} mod {}", x_old, exp, x.mod_pow(&exp, m), m_old ); } } fn demo_natural_mod_pow_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.pow({}) ≡ {} mod {}", x_old, exp, x.mod_pow(&exp, &m), m); } } fn demo_natural_mod_pow_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let exp_old = exp.clone(); let m_old = m.clone(); println!( "{}.pow({}) ≡ {} mod {}", x, exp_old, (&x).mod_pow(exp, m), m_old ); } } fn demo_natural_mod_pow_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let exp_old = exp.clone(); println!( "{}.pow({}) ≡ {} mod {}", x, exp_old, (&x).mod_pow(exp, &m), m ); } } fn demo_natural_mod_pow_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { let m_old = m.clone(); println!( "{}.pow({}) ≡ {} mod {}", x, exp, (&x).mod_pow(&exp, m), m_old ); } } fn demo_natural_mod_pow_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, m) in natural_triple_gen_var_5().get(gm, config).take(limit) { println!("{}.pow({}) ≡ {} mod {}", x, exp, (&x).mod_pow(&exp, &m), m); } } fn benchmark_limbs_mod_pow_odd(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mod_pow_odd(&mut [Limb], &[Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_quadruple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &quadruple_4_vec_len_bucketer("ms"), &mut [("Malachite", &mut |(mut out, xs, es, ms)| { let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(ms.len())]; limbs_mod_pow_odd(&mut out, &xs, &es, &ms, &mut scratch); })], ); } fn benchmark_limbs_mod_pow(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mod_pow(&mut [Limb], &[Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_quadruple_gen_var_6().get(gm, config), gm.name(), limit, file_name, &quadruple_4_vec_len_bucketer("ms"), &mut [("Malachite", &mut |(mut out, xs, es, ms)| { limbs_mod_pow(&mut out, &xs, &es, &ms); })], ); } fn benchmark_natural_mod_pow_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_pow_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_3_prod_natural_bits_bucketer("exp", "m"), &mut [ ( "Natural.mod_pow_assign(Natural, Natural)", &mut |(mut x, exp, m)| no_out!(x.mod_pow_assign(exp, m)), ), ( "Natural.mod_pow_assign(Natural, &Natural)", &mut |(mut x, exp, m)| no_out!(x.mod_pow_assign(exp, &m)), ), ( "Natural.mod_pow_assign(&Natural, Natural)", &mut |(mut x, exp, m)| no_out!(x.mod_pow_assign(&exp, m)), ), ( "Natural.mod_pow_assign(&Natural, &Natural)", &mut |(mut x, exp, m)| no_out!(x.mod_pow_assign(&exp, &m)), ), ], ); } fn benchmark_natural_mod_pow_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_pow(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_3_prod_natural_bits_bucketer("exp", "m"), &mut [ ("default", &mut |(x, exp, m)| no_out!(x.mod_pow(exp, m))), ("simple binary", &mut |(x, exp, m)| { no_out!(simple_binary_mod_pow(&x, &exp, &m)); }), ], ); } fn benchmark_natural_mod_pow_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_pow(Natural, Natural)", BenchmarkType::LibraryComparison, natural_triple_gen_var_5_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_triple_1_3_prod_natural_bits_bucketer("exp", "m"), &mut [ ("Malachite", &mut |(_, _, (x, exp, m))| { no_out!(x.mod_pow(exp, m)); }), ("num", &mut |((x, exp, m), _, _)| { no_out!(x.modpow(&exp, &m)); }), ("rug", &mut |(_, (x, exp, m), _)| { no_out!(x.pow_mod(&exp, &m).unwrap()); }), ], ); } fn benchmark_natural_mod_pow_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_pow(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_1_3_prod_natural_bits_bucketer("exp", "m"), &mut [ ("Natural.mod_pow(Natural, Natural)", &mut |(x, exp, m)| { no_out!(x.mod_pow(exp, m)); }), ("Natural.mod_pow(Natural, &Natural)", &mut |(x, exp, m)| { no_out!(x.mod_pow(exp, &m)); }), ("Natural.mod_pow(&Natural, Natural)", &mut |(x, exp, m)| { no_out!(x.mod_pow(&exp, m)); }), ("Natural.mod_pow(&Natural, &Natural)", &mut |(x, exp, m)| { no_out!(x.mod_pow(&exp, &m)); }), ("(&Natural).mod_pow(Natural, Natural)", &mut |( x, exp, m, )| { no_out!((&x).mod_pow(exp, m)); }), ( "(&Natural).mod_pow(Natural, &Natural)", &mut |(x, exp, m)| no_out!((&x).mod_pow(exp, &m)), ), ( "(&Natural).mod_pow(&Natural, Natural)", &mut |(x, exp, m)| no_out!((&x).mod_pow(&exp, m)), ), ( "(&Natural).mod_pow(&Natural, &Natural)", &mut |(x, exp, m)| no_out!((&x).mod_pow(&exp, &m)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, NegModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign, }; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::mod_power_of_2::{ limbs_mod_power_of_2, limbs_neg_mod_power_of_2, limbs_neg_mod_power_of_2_in_place, limbs_slice_mod_power_of_2_in_place, limbs_vec_mod_power_of_2_in_place, }; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_power_of_2); register_demo!(runner, demo_limbs_slice_mod_power_of_2_in_place); register_demo!(runner, demo_limbs_vec_mod_power_of_2_in_place); register_demo!(runner, demo_limbs_neg_mod_power_of_2); register_demo!(runner, demo_limbs_neg_mod_power_of_2_in_place); register_demo!(runner, demo_natural_mod_power_of_2_assign); register_demo!(runner, demo_natural_mod_power_of_2); register_demo!(runner, demo_natural_mod_power_of_2_ref); register_demo!(runner, demo_natural_rem_power_of_2_assign); register_demo!(runner, demo_natural_rem_power_of_2); register_demo!(runner, demo_natural_rem_power_of_2_ref); register_demo!(runner, demo_natural_neg_mod_power_of_2_assign); register_demo!(runner, demo_natural_neg_mod_power_of_2); register_demo!(runner, demo_natural_neg_mod_power_of_2_ref); register_bench!(runner, benchmark_limbs_mod_power_of_2); register_bench!(runner, benchmark_limbs_slice_mod_power_of_2_in_place); register_bench!(runner, benchmark_limbs_vec_mod_power_of_2_in_place); register_bench!(runner, benchmark_limbs_neg_mod_power_of_2); register_bench!(runner, benchmark_limbs_neg_mod_power_of_2_in_place); register_bench!(runner, benchmark_natural_mod_power_of_2_assign); register_bench!(runner, benchmark_natural_mod_power_of_2_evaluation_strategy); register_bench!(runner, benchmark_natural_rem_power_of_2_assign); register_bench!(runner, benchmark_natural_rem_power_of_2_evaluation_strategy); register_bench!(runner, benchmark_natural_neg_mod_power_of_2_assign); register_bench!( runner, benchmark_natural_neg_mod_power_of_2_evaluation_strategy ); } fn demo_limbs_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2({:?}, {}) = {:?}", xs, pow, limbs_mod_power_of_2(&xs, pow) ); } } fn demo_limbs_slice_mod_power_of_2_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_slice_mod_power_of_2_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; limbs_slice_mod_power_of_2_in_place(&mut xs, {pow}); xs = {xs:?}", ); } } fn demo_limbs_vec_mod_power_of_2_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_mod_power_of_2_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; limbs_vec_mod_power_of_2_in_place(&mut xs, {pow}); xs = {xs:?}", ); } } fn demo_limbs_neg_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_neg_mod_power_of_2({:?}, {}) = {:?}", xs, pow, limbs_neg_mod_power_of_2(&xs, pow) ); } } fn demo_limbs_neg_mod_power_of_2_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_neg_mod_power_of_2_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; limbs_neg_mod_power_of_2_in_place(&mut xs, {pow}); xs = {xs:?}", ); } } fn demo_natural_mod_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_assign(u); println!("x := {n_old}; x.mod_power_of_2_assign({u}); x = {n}"); } } fn demo_natural_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.mod_power_of_2({}) = {}", n_old, u, n.mod_power_of_2(u)); } } fn demo_natural_mod_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "(&{}).mod_power_of_2({}) = {}", n, u, (&n).mod_power_of_2(u) ); } } fn demo_natural_rem_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.rem_power_of_2_assign(u); println!("x := {n_old}; x.rem_power_of_2_assign({u}); x = {n}"); } } fn demo_natural_rem_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.rem_power_of_2({}) = {}", n_old, u, n.rem_power_of_2(u)); } } fn demo_natural_rem_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "(&{}).rem_power_of_2({}) = {}", n, u, (&n).rem_power_of_2(u) ); } } fn demo_natural_neg_mod_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.neg_mod_power_of_2_assign(u); println!("x := {n_old}; x.neg_mod_power_of_2_assign({u}); x = {n}"); } } fn demo_natural_neg_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.neg_mod_power_of_2({}) = {}", n_old, u, n.neg_mod_power_of_2(u) ); } } fn demo_natural_neg_mod_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "(&{}).neg_mod_power_of_2({}) = {}", n, u, (&n).neg_mod_power_of_2(u) ); } } fn benchmark_limbs_mod_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mod_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_mod_power_of_2(&xs, pow)); })], ); } fn benchmark_limbs_slice_mod_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_mod_power_of_2_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut xs, pow)| { limbs_slice_mod_power_of_2_in_place(&mut xs, pow); })], ); } fn benchmark_limbs_vec_mod_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_mod_power_of_2_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut xs, pow)| { limbs_vec_mod_power_of_2_in_place(&mut xs, pow); })], ); } fn benchmark_limbs_neg_mod_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_mod_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_neg_mod_power_of_2(&xs, pow)); })], ); } fn benchmark_limbs_neg_mod_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_neg_mod_power_of_2(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut xs, pow)| { limbs_neg_mod_power_of_2_in_place(&mut xs, pow); })], ); } fn benchmark_natural_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut n, u)| n.mod_power_of_2_assign(u))], ); } fn benchmark_natural_mod_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2(u64)", &mut |(n, u)| { no_out!(n.mod_power_of_2(u)); }), ("(&Natural).mod_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).mod_power_of_2(u)); }), ], ); } fn benchmark_natural_rem_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.rem_power_of_2_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut n, u)| n.rem_power_of_2_assign(u))], ); } fn benchmark_natural_rem_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.rem_power_of_2(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.rem_power_of_2(u64)", &mut |(n, u)| { no_out!(n.rem_power_of_2(u)); }), ("(&Natural).rem_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).rem_power_of_2(u)); }), ], ); } fn benchmark_natural_neg_mod_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod_power_of_2_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Malachite", &mut |(mut n, u)| { n.neg_mod_power_of_2_assign(u); })], ); } fn benchmark_natural_neg_mod_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.neg_mod_power_of_2(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.neg_mod_power_of_2(u64)", &mut |(n, u)| { no_out!(n.neg_mod_power_of_2(u)); }), ("(&Natural).neg_mod_power_of_2(u64)", &mut |(n, u)| { no_out!((&n).neg_mod_power_of_2(u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModAdd, ModPowerOf2, ModPowerOf2Add, ModPowerOf2AddAssign, PowerOf2, }; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::{triple_1_vec_len_bucketer, triple_3_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_add::{ limbs_mod_power_of_2_add, limbs_mod_power_of_2_add_greater, limbs_mod_power_of_2_add_in_place_either, limbs_mod_power_of_2_add_limb, limbs_slice_mod_power_of_2_add_greater_in_place_left, limbs_slice_mod_power_of_2_add_limb_in_place, limbs_vec_mod_power_of_2_add_in_place_left, limbs_vec_mod_power_of_2_add_limb_in_place, }; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_4, unsigned_vec_unsigned_unsigned_triple_gen_var_14, unsigned_vec_unsigned_unsigned_triple_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_power_of_2_add_limb); register_demo!(runner, demo_limbs_slice_mod_power_of_2_add_limb_in_place); register_demo!(runner, demo_limbs_vec_mod_power_of_2_add_limb_in_place); register_demo!(runner, demo_limbs_mod_power_of_2_add_greater); register_demo!(runner, demo_limbs_mod_power_of_2_add); register_demo!( runner, demo_limbs_slice_mod_power_of_2_add_greater_in_place_left ); register_demo!(runner, demo_limbs_vec_mod_power_of_2_add_in_place_left); register_demo!(runner, demo_limbs_mod_power_of_2_add_in_place_either); register_demo!(runner, demo_natural_mod_power_of_2_add_assign); register_demo!(runner, demo_natural_mod_power_of_2_add_assign_ref); register_demo!(runner, demo_natural_mod_power_of_2_add); register_demo!(runner, demo_natural_mod_power_of_2_add_val_ref); register_demo!(runner, demo_natural_mod_power_of_2_add_ref_val); register_demo!(runner, demo_natural_mod_power_of_2_add_ref_ref); register_bench!(runner, benchmark_limbs_mod_power_of_2_add_limb); register_bench!( runner, benchmark_limbs_slice_mod_power_of_2_add_limb_in_place ); register_bench!(runner, benchmark_limbs_vec_mod_power_of_2_add_limb_in_place); register_bench!(runner, benchmark_limbs_mod_power_of_2_add_greater); register_bench!(runner, benchmark_limbs_mod_power_of_2_add); register_bench!( runner, benchmark_limbs_slice_mod_power_of_2_add_greater_in_place_left ); register_bench!(runner, benchmark_limbs_vec_mod_power_of_2_add_in_place_left); register_bench!(runner, benchmark_limbs_mod_power_of_2_add_in_place_either); register_bench!( runner, benchmark_natural_mod_power_of_2_add_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_add_algorithms); register_bench!( runner, benchmark_natural_mod_power_of_2_add_evaluation_strategy ); } fn demo_limbs_mod_power_of_2_add_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_14() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_add_limb({:?}, {}, {}) = {:?}", xs, y, pow, limbs_mod_power_of_2_add_limb(&xs, y, pow) ); } } fn demo_limbs_slice_mod_power_of_2_add_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, y, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_14() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); println!( "xs := {xs_old:?}; \ limbs_slice_mod_power_of_2_add_limb_in_place(&mut xs, {y}, {pow}) = {carry}; \ xs = {xs:?}", ); } } fn demo_limbs_vec_mod_power_of_2_add_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); println!( "xs := {xs_old:?}; \ limbs_vec_mod_power_of_2_add_limb_in_place(&mut xs, {y}, {pow}); xs = {xs:?}", ); } } fn demo_limbs_mod_power_of_2_add_greater(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19() .get(gm, config) .take(limit) { println!( "limbs_add_greater({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_mod_power_of_2_add_greater(&xs, &ys, pow) ); } } fn demo_limbs_mod_power_of_2_add(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_add({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_mod_power_of_2_add(&xs, &ys, pow) ); } } fn demo_limbs_slice_mod_power_of_2_add_greater_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut xs, &ys, pow); println!( "xs := {xs_old:?}; \ limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut xs, {ys:?}, {pow}) \ = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_mod_power_of_2_add_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_mod_power_of_2_add_in_place_left(&mut xs, &ys, pow); println!( "xs := {xs_old:?}; \ limbs_vec_mod_power_of_2_add_in_place_left(&mut xs, {ys:?}, {pow}); \ xs = {xs:?}", ); } } fn demo_limbs_mod_power_of_2_add_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_mod_power_of_2_add_in_place_either(&mut xs, &mut ys, pow); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_mod_power_of_2_add_in_place_either(&mut xs, &mut ys, \ {pow}) = {right}; xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_mod_power_of_2_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_power_of_2_add_assign(y, pow); println!("x := {x_old}; x.mod_power_of_2_add_assign({y_old}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_add_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mod_power_of_2_add_assign(&y, pow); println!("x := {x_old}; x.mod_power_of_2_add_assign(&{y}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} + {} ≡ {} mod 2^{}", x_old, y_old, x.mod_power_of_2_add(y, pow), pow ); } } fn demo_natural_mod_power_of_2_add_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{} + {} ≡ {} mod 2^{}", x_old, y, x.mod_power_of_2_add(&y, pow), pow ); } } fn demo_natural_mod_power_of_2_add_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "{} + {} ≡ {} mod 2^{}", x, y_old, (&x).mod_power_of_2_add(y, pow), pow ); } } fn demo_natural_mod_power_of_2_add_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "{} + {} ≡ {} mod 2^{}", x, y, (&x).mod_power_of_2_add(&y, pow), pow ); } } fn benchmark_limbs_mod_power_of_2_add_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_add_limb(&[Limb], Limb, u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_14().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y, pow)| { no_out!(limbs_mod_power_of_2_add_limb(&xs, y, pow)); })], ); } fn benchmark_limbs_slice_mod_power_of_2_add_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_mod_power_of_2_add_limb_in_place(&mut [Limb], Limb, u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_14().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y, pow)| { no_out!(limbs_slice_mod_power_of_2_add_limb_in_place( &mut xs, y, pow )); })], ); } fn benchmark_limbs_vec_mod_power_of_2_add_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_mod_power_of_2_add_limb_in_place(&mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_14().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y, pow)| { limbs_vec_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); })], ); } fn benchmark_limbs_mod_power_of_2_add_greater( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_add_greater(&[Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(ref xs, ref ys, pow)| { no_out!(limbs_mod_power_of_2_add_greater(xs, ys, pow)); })], ); } fn benchmark_limbs_mod_power_of_2_add( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_add(&[Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ref xs, ref ys, pow)| { no_out!(limbs_mod_power_of_2_add(xs, ys, pow)); })], ); } fn benchmark_limbs_slice_mod_power_of_2_add_greater_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut [Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys, pow)| { no_out!(limbs_slice_mod_power_of_2_add_greater_in_place_left( &mut xs, &ys, pow )); })], ); } fn benchmark_limbs_vec_mod_power_of_2_add_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_mod_power_of_2_add_in_place_left(&Vec, &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut xs, ys, pow)| { no_out!(limbs_vec_mod_power_of_2_add_in_place_left( &mut xs, &ys, pow )); })], ); } fn benchmark_limbs_mod_power_of_2_add_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_add_in_place_either(&mut [Limb], &mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut xs, mut ys, pow)| { no_out!(limbs_mod_power_of_2_add_in_place_either( &mut xs, &mut ys, pow )); })], ); } fn benchmark_natural_mod_power_of_2_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_add_assign(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_add_assign(Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_add_assign(y, pow)), ), ( "Natural.mod_power_of_2_add_assign(&Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_add_assign(&y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_add_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_add(Natural, u64)", BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_add(y, pow)); }), ("alt", &mut |(x, y, pow)| { let mut sum = x + y; sum.clear_bit(pow); }), ("naive", &mut |(x, y, pow)| { no_out!((x + y).mod_power_of_2(pow)); }), ("using mod_add", &mut |(x, y, pow)| { no_out!(x.mod_add(y, Natural::power_of_2(pow))); }), ], ); } fn benchmark_natural_mod_power_of_2_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_add(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_add(Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_add(y, pow)), ), ( "Natural.mod_power_of_2_add(&Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_add(&y, pow)), ), ( "(&Natural).mod_power_of_2_add(Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_add(y, pow)), ), ( "(&Natural).mod_power_of_2_add(&Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_add(&y, pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModInverse, ModPowerOf2Inverse, PowerOf2}; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_14; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_power_of_2_inverse); register_demo!(runner, demo_natural_mod_power_of_2_inverse_ref); register_bench!( runner, benchmark_natural_mod_power_of_2_inverse_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_inverse_algorithms); } fn demo_natural_mod_power_of_2_inverse(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_14() .get(gm, config) .take(limit) { let n_old = n.clone(); if let Some(inverse) = n.mod_power_of_2_inverse(pow) { println!("{n_old}⁻¹ ≡ {inverse} mod 2^{pow}"); } else { println!("{n_old} is not invertible mod 2^{pow}"); } } } fn demo_natural_mod_power_of_2_inverse_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_14() .get(gm, config) .take(limit) { if let Some(inverse) = (&n).mod_power_of_2_inverse(pow) { println!("{n}⁻¹ ≡ {inverse} mod 2^{pow}"); } else { println!("{n} is not invertible mod 2^{pow}"); } } } fn benchmark_natural_mod_power_of_2_inverse_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_inverse(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_14().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2_inverse(u64)", &mut |(n, pow)| { no_out!(n.mod_power_of_2_inverse(pow)); }), ("(&Natural).mod_power_of_2_inverse(u64)", &mut |(n, pow)| { no_out!((&n).mod_power_of_2_inverse(pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_inverse_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_inverse(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_14().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("default", &mut |(n, pow)| { no_out!(n.mod_power_of_2_inverse(pow)); }), ("simple", &mut |(n, pow)| { no_out!(n.mod_inverse(Natural::power_of_2(pow))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModIsReduced, ModPowerOf2IsReduced, PowerOf2}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_power_of_2_is_reduced); register_bench!( runner, benchmark_natural_mod_power_of_2_is_reduced_algorithms ); } fn demo_natural_mod_power_of_2_is_reduced(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { if n.mod_power_of_2_is_reduced(log_base) { println!("{n} is reduced mod 2^{log_base}"); } else { println!("{n} is not reduced mod 2^{log_base}"); } } } fn benchmark_natural_mod_power_of_2_is_reduced_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_add_limb(&[Limb], Limb, u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, log_base)| { no_out!(n.mod_power_of_2_is_reduced(log_base)); }), ("using mod_is_reduced", &mut |(n, log_base)| { no_out!(n.mod_is_reduced(&Natural::power_of_2(log_base))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModMul, ModPowerOf2, ModPowerOf2Mul, ModPowerOf2MulAssign, PowerOf2, }; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_mul::{ limbs_mod_power_of_2_mul, limbs_mod_power_of_2_mul_ref_ref, limbs_mod_power_of_2_mul_val_ref, }; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_power_of_2_mul); register_demo!(runner, demo_limbs_mod_power_of_2_mul_val_ref); register_demo!(runner, demo_limbs_mod_power_of_2_mul_ref_ref); register_demo!(runner, demo_natural_mod_power_of_2_mul_assign); register_demo!(runner, demo_natural_mod_power_of_2_mul_assign_ref); register_demo!(runner, demo_natural_mod_power_of_2_mul); register_demo!(runner, demo_natural_mod_power_of_2_mul_val_ref); register_demo!(runner, demo_natural_mod_power_of_2_mul_ref_val); register_demo!(runner, demo_natural_mod_power_of_2_mul_ref_ref); register_bench!( runner, benchmark_limbs_mod_power_of_2_mul_evaluation_strategy ); register_bench!( runner, benchmark_natural_mod_power_of_2_mul_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_mul_algorithms); register_bench!( runner, benchmark_natural_mod_power_of_2_mul_evaluation_strategy ); } fn demo_limbs_mod_power_of_2_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); println!( "limbs_mod_power_of_2_mul({:?}, {:?}, {}) = {:?}", xs_old, ys_old, pow, limbs_mod_power_of_2_mul(&mut xs, &mut ys, pow) ); } } fn demo_limbs_mod_power_of_2_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); println!( "limbs_mod_power_of_2_mul({:?}, {:?}, {}) = {:?}", xs_old, ys, pow, limbs_mod_power_of_2_mul_val_ref(&mut xs, &ys, pow) ); } } fn demo_limbs_mod_power_of_2_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_mul_ref_ref({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_mod_power_of_2_mul_ref_ref(&xs, &ys, pow) ); } } fn demo_natural_mod_power_of_2_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_power_of_2_mul_assign(y, pow); println!("x := {x_old}; x.mod_power_of_2_mul_assign({y_old}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_mul_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mod_power_of_2_mul_assign(&y, pow); println!("x := {x_old}; x.mod_power_of_2_mul_assign(&{y}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} * {} ≡ {} mod 2^{}", x_old, y_old, x.mod_power_of_2_mul(y, pow), pow ); } } fn demo_natural_mod_power_of_2_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{} * {} ≡ {} mod 2^{}", x_old, y, x.mod_power_of_2_mul(&y, pow), pow ); } } fn demo_natural_mod_power_of_2_mul_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "{} * {} ≡ {} mod 2^{}", x, y_old, (&x).mod_power_of_2_mul(y, pow), pow ); } } fn demo_natural_mod_power_of_2_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "{} * {} ≡ {} mod 2^{}", x, y, (&x).mod_power_of_2_mul(&y, pow), pow ); } } fn benchmark_limbs_mod_power_of_2_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_mul(&[Limb], &[Limb], u64)", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("limbs_mod_power_of_2_mul", &mut |( ref mut xs, ref mut ys, pow, )| { no_out!(limbs_mod_power_of_2_mul(xs, ys, pow)); }), ("limbs_mod_power_of_2_mul_val_ref", &mut |( ref mut xs, ref ys, pow, )| { no_out!(limbs_mod_power_of_2_mul_val_ref(xs, ys, pow)); }), ("limbs_mod_power_of_2_mul_ref_ref", &mut |( ref xs, ref ys, pow, )| { no_out!(limbs_mod_power_of_2_mul_ref_ref(xs, ys, pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_mul_assign(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_mul_assign(Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_mul_assign(y, pow)), ), ( "Natural.mod_power_of_2_mul_assign(&Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_mul_assign(&y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_mul(Natural, u64)", BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_mul(y, pow)); }), ("naive", &mut |(x, y, pow)| { no_out!((x * y).mod_power_of_2(pow)); }), ("using mod_mul", &mut |(x, y, pow)| { no_out!(x.mod_mul(y, Natural::power_of_2(pow))); }), ], ); } fn benchmark_natural_mod_power_of_2_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_mul(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_mul(Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_mul(y, pow)), ), ( "Natural.mod_power_of_2_mul(&Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_mul(&y, pow)), ), ( "(&Natural).mod_power_of_2_mul(Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_mul(y, pow)), ), ( "(&Natural).mod_power_of_2_mul(&Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_mul(&y, pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModNeg, ModPowerOf2, ModPowerOf2Neg, ModPowerOf2NegAssign, PowerOf2, }; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_11; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_power_of_2_neg_assign); register_demo!(runner, demo_natural_mod_power_of_2_neg); register_demo!(runner, demo_natural_mod_power_of_2_neg_ref); register_bench!(runner, benchmark_natural_mod_power_of_2_neg_assign); register_bench!( runner, benchmark_natural_mod_power_of_2_neg_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_neg_algorithms); } fn demo_natural_mod_power_of_2_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_neg_assign(pow); println!("x := {n_old}; x.mod_power_of_2_neg_assign({pow}); x = {n}"); } } fn demo_natural_mod_power_of_2_neg(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("-{} ≡ {} mod 2^{}", n_old, n.mod_power_of_2_neg(pow), pow); } } fn demo_natural_mod_power_of_2_neg_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "-(&{}) ≡ {} mod 2^{}", n_old, n.mod_power_of_2_neg(pow), pow ); } } fn benchmark_natural_mod_power_of_2_neg_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_neg_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [("Natural.mod_power_of_2_neg_assign(u64)", &mut |( mut n, pow, )| { n.mod_power_of_2_neg_assign(pow); })], ); } fn benchmark_natural_mod_power_of_2_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_neg(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2_neg(u64)", &mut |(n, pow)| { no_out!(n.mod_power_of_2_neg(pow)); }), ("(&Natural).mod_power_of_2_neg(u64)", &mut |(n, pow)| { no_out!((&n).mod_power_of_2_neg(pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_neg_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_neg(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2_neg(u64)", &mut |(n, pow)| { no_out!(n.mod_power_of_2_neg(pow)); }), ("(-Natural).mod_power_of_2(u64)", &mut |(n, pow)| { no_out!((-n).mod_power_of_2(pow)); }), ( "Natural.mod_neg(Natural::power_of_2(u64))", &mut |(n, pow)| no_out!(n.mod_neg(Natural::power_of_2(pow))), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2Pow, ModPowerOf2PowAssign}; use malachite_base::test_util::bench::bucketers::{ pair_product_vec_len_bucketer, triple_1_2_product_vec_len_bucketer, triple_2_bits_times_triple_3_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_pair_gen_var_3; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::mod_power_of_2_pow::{ limbs_mod_power_of_2_pow, limbs_pow_low, }; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_5, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21, }; use malachite_nz::test_util::natural::arithmetic::mod_power_of_2_pow::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_pow_low); register_demo!(runner, demo_limbs_mod_power_of_2_pow); register_demo!(runner, demo_natural_mod_power_of_2_pow_assign); register_demo!(runner, demo_natural_mod_power_of_2_pow_assign_ref); register_demo!(runner, demo_natural_mod_power_of_2_pow); register_demo!(runner, demo_natural_mod_power_of_2_pow_val_ref); register_demo!(runner, demo_natural_mod_power_of_2_pow_ref_val); register_demo!(runner, demo_natural_mod_power_of_2_pow_ref_ref); register_bench!(runner, benchmark_limbs_pow_low); register_bench!(runner, benchmark_limbs_mod_power_of_2_pow); register_bench!( runner, benchmark_natural_mod_power_of_2_pow_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_pow_algorithms); register_bench!( runner, benchmark_natural_mod_power_of_2_pow_evaluation_strategy ); } fn demo_limbs_pow_low(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, es) in unsigned_vec_pair_gen_var_3().get(gm, config).take(limit) { let xs_old = xs.clone(); let mut scratch = vec![0; xs.len()]; limbs_pow_low(&mut xs, &es, &mut scratch); println!("xs := {xs_old:?}; limbs_pow_low(&mut xs, {es:?}, &mut scratch); xs = {xs:?}"); } } fn demo_limbs_mod_power_of_2_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, es, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_mod_power_of_2_pow(&mut xs, &es, pow); println!("xs := {xs_old:?}; limbs_mod_power_of_2_pow(&mut xs, {es:?}, {pow}); xs = {xs:?}"); } } fn demo_natural_mod_power_of_2_pow_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let exp_old = exp.clone(); x.mod_power_of_2_pow_assign(exp, pow); println!("x := {x_old}; x.mod_power_of_2_pow_assign({exp_old}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_pow_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mod_power_of_2_pow_assign(&exp, pow); println!("x := {x_old}; x.mod_power_of_2_pow_assign({exp}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); let exp_old = exp.clone(); println!( "{}.pow({}) ≡ {} mod 2^{}", x_old, exp_old, x.mod_power_of_2_pow(exp, pow), pow ); } } fn demo_natural_mod_power_of_2_pow_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{}.pow({}) ≡ {} mod 2^{}", x_old, exp, x.mod_power_of_2_pow(&exp, pow), pow ); } } fn demo_natural_mod_power_of_2_pow_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { let exp_old = exp.clone(); println!( "{}.pow({}) ≡ {} mod 2^{}", x, exp_old, (&x).mod_power_of_2_pow(exp, pow), pow ); } } fn demo_natural_mod_power_of_2_pow_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp, pow) in natural_natural_unsigned_triple_gen_var_5() .get(gm, config) .take(limit) { println!( "{}.pow({}) ≡ {} mod 2^{}", x, exp, (&x).mod_power_of_2_pow(&exp, pow), pow ); } } fn benchmark_limbs_pow_low(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_pow_low(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_product_vec_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, es)| { let mut scratch = vec![0; xs.len()]; limbs_pow_low(&mut xs, &es, &mut scratch); })], ); } fn benchmark_limbs_mod_power_of_2_pow( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_pow(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21().get(gm, config), gm.name(), limit, file_name, &triple_1_2_product_vec_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, es, pow)| { limbs_mod_power_of_2_pow(&mut xs, &es, pow); })], ); } fn benchmark_natural_mod_power_of_2_pow_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_pow_assign(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_bits_times_triple_3_bucketer("exp", "pow"), &mut [ ( "Natural.mod_power_of_2_pow_assign(Natural, u64)", &mut |(mut x, exp, pow)| no_out!(x.mod_power_of_2_pow_assign(exp, pow)), ), ( "Natural.mod_power_of_2_pow_assign(&Natural, u64)", &mut |(mut x, exp, pow)| no_out!(x.mod_power_of_2_pow_assign(&exp, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_pow_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_pow(Natural, u64)", BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_bits_times_triple_3_bucketer("exp", "pow"), &mut [ ("default", &mut |(x, exp, pow)| { no_out!(x.mod_power_of_2_pow(exp, pow)); }), ("simple binary", &mut |(x, exp, pow)| { no_out!(simple_binary_mod_power_of_2_pow(&x, &exp, pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_pow_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_pow(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_5().get(gm, config), gm.name(), limit, file_name, &triple_2_bits_times_triple_3_bucketer("exp", "pow"), &mut [ ( "Natural.mod_power_of_2_pow(Natural, u64)", &mut |(x, exp, pow)| no_out!(x.mod_power_of_2_pow(exp, pow)), ), ( "Natural.mod_power_of_2_pow(&Natural, u64)", &mut |(x, exp, pow)| no_out!(x.mod_power_of_2_pow(&exp, pow)), ), ( "(&Natural).mod_power_of_2_pow(Natural, u64)", &mut |(x, exp, pow)| no_out!((&x).mod_power_of_2_pow(exp, pow)), ), ( "(&Natural).mod_power_of_2_pow(&Natural, u64)", &mut |(x, exp, pow)| no_out!((&x).mod_power_of_2_pow(&exp, pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2Shl, ModPowerOf2ShlAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_signed_unsigned_triple_gen_var_1, natural_unsigned_unsigned_triple_gen_var_6, }; use std::ops::Shl; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_mod_power_of_2_shl_assign_unsigned); register_unsigned_demos!(runner, demo_natural_mod_power_of_2_shl_unsigned); register_unsigned_demos!(runner, demo_natural_mod_power_of_2_shl_unsigned_ref); register_signed_demos!(runner, demo_natural_mod_power_of_2_shl_assign_signed); register_signed_demos!(runner, demo_natural_mod_power_of_2_shl_signed); register_signed_demos!(runner, demo_natural_mod_power_of_2_shl_signed_ref); register_unsigned_benches!(runner, benchmark_natural_mod_power_of_2_shl_assign_unsigned); register_unsigned_benches!( runner, benchmark_natural_mod_power_of_2_shl_unsigned_evaluation_strategy ); register_unsigned_benches!( runner, benchmark_natural_mod_power_of_2_shl_unsigned_algorithms ); register_signed_benches!(runner, benchmark_natural_mod_power_of_2_shl_assign_signed); register_signed_benches!( runner, benchmark_natural_mod_power_of_2_shl_signed_evaluation_strategy ); register_signed_benches!( runner, benchmark_natural_mod_power_of_2_shl_signed_algorithms ); } fn demo_natural_mod_power_of_2_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2ShlAssign, { for (mut n, u, pow) in natural_unsigned_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_shl_assign(u, pow); println!("x := {n_old}; x.mod_power_of_2_shl_assign({u}, {pow}); x = {n}"); } } fn demo_natural_mod_power_of_2_shl_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2Shl, { for (n, u, pow) in natural_unsigned_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_power_of_2_shl({}, {}) = {}", n_old, u, pow, n.mod_power_of_2_shl(u, pow) ); } } fn demo_natural_mod_power_of_2_shl_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: ModPowerOf2Shl, { for (n, u, pow) in natural_unsigned_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "(&{}).mod_power_of_2_shl({}, {}) = {}", n_old, u, pow, (&n).mod_power_of_2_shl(u, pow) ); } } fn demo_natural_mod_power_of_2_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2ShlAssign, { for (mut n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_shl_assign(i, pow); println!("x := {n_old}; x.mod_power_of_2_shl_assign({i}, {pow}); x = {n}"); } } fn demo_natural_mod_power_of_2_shl_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2Shl, { for (n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_power_of_2_shl({}, {}) = {}", n_old, i, pow, n.mod_power_of_2_shl(i, pow) ); } } fn demo_natural_mod_power_of_2_shl_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: ModPowerOf2Shl, { for (n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "(&{}).mod_power_of_2_shl({}, {}) = {}", n_old, i, pow, (&n).mod_power_of_2_shl(i, pow) ); } } fn benchmark_natural_mod_power_of_2_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2ShlAssign, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::Single, natural_unsigned_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shl_assign(y, pow); })], ); } fn benchmark_natural_mod_power_of_2_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shl, for<'a> &'a Natural: ModPowerOf2Shl, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, natural_unsigned_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( &format!("Natural.mod_power_of_2_shl({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!(x.mod_power_of_2_shl(y, pow)), ), ( &format!("(&Natural).mod_power_of_2_shl({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_shl(y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_shl_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shl + Shl, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::Algorithms, natural_unsigned_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shl(y, pow)); }), ( &format!("(Natural << {}).mod_power_of_2(u64)", T::NAME), &mut |(x, y, pow)| no_out!((x << y).mod_power_of_2(pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2ShlAssign, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::Single, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shl_assign(y, pow); })], ); } fn benchmark_natural_mod_power_of_2_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shl, for<'a> &'a Natural: ModPowerOf2Shl, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( &format!("Natural.mod_power_of_2_shl({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!(x.mod_power_of_2_shl(y, pow)), ), ( &format!("(&Natural).mod_power_of_2_shl({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_shl(y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_shl_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shl + Shl, { run_benchmark( &format!("Natural.mod_power_of_2_shl_assign({}, u64)", T::NAME), BenchmarkType::Algorithms, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shl(y, pow)); }), ( &format!("(Natural << {}).mod_power_of_2(u64)", T::NAME), &mut |(x, y, pow)| no_out!((x << y).mod_power_of_2(pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2Shr, ModPowerOf2ShrAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_signed_unsigned_triple_gen_var_1; use std::ops::Shr; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_natural_mod_power_of_2_shr_assign); register_signed_demos!(runner, demo_natural_mod_power_of_2_shr); register_signed_demos!(runner, demo_natural_mod_power_of_2_shr_ref); register_signed_benches!(runner, benchmark_natural_mod_power_of_2_shr_assign); register_signed_benches!( runner, benchmark_natural_mod_power_of_2_shr_evaluation_strategy ); register_signed_benches!(runner, benchmark_natural_mod_power_of_2_shr_algorithms); } fn demo_natural_mod_power_of_2_shr_assign( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2ShrAssign, { for (mut n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_shr_assign(i, pow); println!("x := {n_old}; x.mod_power_of_2_shr_assign({i}, {pow}); x = {n}"); } } fn demo_natural_mod_power_of_2_shr( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModPowerOf2Shr, { for (n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_power_of_2_shr({}, {}) = {}", n_old, i, pow, n.mod_power_of_2_shr(i, pow) ); } } fn demo_natural_mod_power_of_2_shr_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: ModPowerOf2Shr, { for (n, i, pow) in natural_signed_unsigned_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "(&{}).mod_power_of_2_shr({}, {}) = {}", n_old, i, pow, (&n).mod_power_of_2_shr(i, pow) ); } } fn benchmark_natural_mod_power_of_2_shr_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2ShrAssign, { run_benchmark( &format!("Natural.mod_power_of_2_shr_assign({}, u64)", T::NAME), BenchmarkType::Single, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut x, y, pow)| { x.mod_power_of_2_shr_assign(y, pow); })], ); } fn benchmark_natural_mod_power_of_2_shr_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shr, for<'a> &'a Natural: ModPowerOf2Shr, { run_benchmark( &format!("Natural.mod_power_of_2_shr_assign({}, u64)", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( &format!("Natural.mod_power_of_2_shr({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!(x.mod_power_of_2_shr(y, pow)), ), ( &format!("(&Natural).mod_power_of_2_shr({}, u64)", T::NAME), &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_shr(y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_shr_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModPowerOf2Shr + Shr, { run_benchmark( &format!("Natural.mod_power_of_2_shr_assign({}, u64)", T::NAME), BenchmarkType::Algorithms, natural_signed_unsigned_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_shr(y, pow)); }), ( &format!("(Natural >> {}).mod_power_of_2(u64)", T::NAME), &mut |(x, y, pow)| no_out!((x >> y).mod_power_of_2(pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Mul, ModPowerOf2Square, ModPowerOf2SquareAssign, ModSquare, PowerOf2, Square, }; use malachite_base::test_util::bench::bucketers::{pair_2_bucketer, pair_2_vec_len_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_20, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_square::{ limbs_mod_power_of_2_square, limbs_mod_power_of_2_square_ref, limbs_square_low, limbs_square_low_basecase, limbs_square_low_divide_and_conquer, limbs_square_low_scratch_len, }; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_11, unsigned_vec_pair_gen_var_21, unsigned_vec_unsigned_pair_gen_var_30, }; use malachite_nz::test_util::natural::arithmetic::mod_power_of_2_square::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_square_low_basecase); register_demo!(runner, demo_limbs_square_low_divide_and_conquer); register_demo!(runner, demo_limbs_square_low); register_demo!(runner, demo_limbs_mod_power_of_2_square); register_demo!(runner, demo_limbs_mod_power_of_2_square_ref); register_demo!(runner, demo_natural_mod_power_of_2_square_assign); register_demo!(runner, demo_natural_mod_power_of_2_square); register_demo!(runner, demo_natural_mod_power_of_2_square_ref); register_bench!(runner, benchmark_limbs_square_low_basecase); register_bench!( runner, benchmark_limbs_square_low_divide_and_conquer_algorithms ); register_bench!(runner, benchmark_limbs_square_low); register_bench!( runner, benchmark_limbs_mod_power_of_2_square_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_square_assign); register_bench!( runner, benchmark_natural_mod_power_of_2_square_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_square_algorithms); } fn demo_limbs_square_low_basecase(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_21().get(gm, config).take(limit) { let out_old = out.clone(); limbs_square_low_basecase(&mut out, &xs); println!("out := {out_old:?}; limbs_square_low_basecase(&mut out, {xs:?}); out = {out:?}"); } } fn demo_limbs_square_low_divide_and_conquer(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_20().get(gm, config).take(limit) { let out_old = out.clone(); let mut scratch = vec![0; limbs_square_low_scratch_len(xs.len())]; limbs_square_low_divide_and_conquer(&mut out, &xs, &mut scratch); println!( "out := {out_old:?}; \ limbs_square_low_divide_and_conquer(&mut out, {xs:?}, &mut scratch); \ out = {out:?}", ); } } fn demo_limbs_square_low(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_1().get(gm, config).take(limit) { let out_old = out.clone(); limbs_square_low(&mut out, &xs); println!("out := {out_old:?}; limbs_square_low(&mut out, {xs:?}); out = {out:?}"); } } fn demo_limbs_mod_power_of_2_square(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_30() .get(gm, config) .take(limit) { let xs_old = xs.clone(); println!( "limbs_mod_power_of_2_square({:?}, {}) = {:?}", xs_old, pow, limbs_mod_power_of_2_square(&mut xs, pow) ); } } fn demo_limbs_mod_power_of_2_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_30() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_square_ref({:?}, {}) = {:?}", xs, pow, limbs_mod_power_of_2_square_ref(&xs, pow) ); } } fn demo_natural_mod_power_of_2_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_power_of_2_square_assign(pow); println!("x := {n_old}; x.mod_power_of_2_square_assign({pow}); x = {n}"); } } fn demo_natural_mod_power_of_2_square(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.square() ≡ {} mod 2^{}", n_old, n.mod_power_of_2_square(pow), pow ); } } fn demo_natural_mod_power_of_2_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_11() .get(gm, config) .take(limit) { println!( "(&{}).square() ≡ {} mod 2^{}", n, (&n).mod_power_of_2_square(pow), pow ); } } fn benchmark_limbs_square_low_basecase( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_low_basecase(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_21().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs)| { limbs_square_low_basecase(&mut out, &xs); })], ); } fn benchmark_limbs_square_low_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_low_divide_and_conquer(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs)| { limbs_square_low_basecase_unrestricted(&mut out, &xs); }), ("divide and conquer", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_low_scratch_len(xs.len())]; limbs_square_low_divide_and_conquer(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_limbs_square_low(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_square_low(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs)| { limbs_square_low(&mut out, &xs); })], ); } fn benchmark_limbs_mod_power_of_2_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_square(&[Limb], u64)", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_pair_gen_var_30().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("limbs_mod_power_of_2_square", &mut |(ref mut xs, pow)| { no_out!(limbs_mod_power_of_2_square(xs, pow)); }), ("limbs_mod_power_of_2_square_ref", &mut |( ref mut xs, pow, )| { no_out!(limbs_mod_power_of_2_square_ref(xs, pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_square_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_square_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [( "Natural.mod_power_of_2_square_assign(u64)", &mut |(mut n, pow)| n.mod_power_of_2_square_assign(pow), )], ); } fn benchmark_natural_mod_power_of_2_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_square(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2_square(u64)", &mut |(n, pow)| { no_out!(n.mod_power_of_2_square(pow)); }), ("(&Natural).mod_power_of_2_square(u64)", &mut |(n, pow)| { no_out!((&n).mod_power_of_2_square(pow)); }), ], ); } fn benchmark_natural_mod_power_of_2_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_square(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_11().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("pow"), &mut [ ("Natural.mod_power_of_2_square(u64)", &mut |(n, pow)| { no_out!(n.mod_power_of_2_square(pow)); }), ( "Natural.mod_power_of_2_mul(Natural, u64)", &mut |(n, pow)| no_out!(n.clone().mod_power_of_2_mul(n, pow)), ), ("Natural.square().mod_power_of_2(u64)", &mut |(n, pow)| { no_out!(n.square().mod_power_of_2(pow)); }), ( "Natural.mod_square(Natural::power_of_2(u64))", &mut |(n, pow)| no_out!(n.mod_square(Natural::power_of_2(pow))), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Sub, ModPowerOf2SubAssign, ModSub, PowerOf2, }; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::triple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_sub::{ limbs_mod_power_of_2_limb_sub_limbs, limbs_mod_power_of_2_limb_sub_limbs_in_place, limbs_mod_power_of_2_sub, limbs_mod_power_of_2_sub_in_place_either, limbs_mod_power_of_2_sub_in_place_left, limbs_mod_power_of_2_sub_in_place_right, }; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_4, unsigned_vec_unsigned_unsigned_triple_gen_var_16, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mod_power_of_2_limb_sub_limbs); register_demo!(runner, demo_limbs_mod_power_of_2_limb_sub_limbs_in_place); register_demo!(runner, demo_limbs_mod_power_of_2_sub); register_demo!(runner, demo_limbs_mod_power_of_2_sub_in_place_left); register_demo!(runner, demo_limbs_mod_power_of_2_sub_in_place_right); register_demo!(runner, demo_limbs_mod_power_of_2_sub_in_place_either); register_demo!(runner, demo_natural_mod_power_of_2_sub_assign); register_demo!(runner, demo_natural_mod_power_of_2_sub_assign_ref); register_demo!(runner, demo_natural_mod_power_of_2_sub); register_demo!(runner, demo_natural_mod_power_of_2_sub_val_ref); register_demo!(runner, demo_natural_mod_power_of_2_sub_ref_val); register_demo!(runner, demo_natural_mod_power_of_2_sub_ref_ref); register_bench!(runner, benchmark_limbs_mod_power_of_2_limb_sub_limbs); register_bench!( runner, benchmark_limbs_mod_power_of_2_limb_sub_limbs_in_place ); register_bench!(runner, benchmark_limbs_mod_power_of_2_sub); register_bench!(runner, benchmark_limbs_mod_power_of_2_sub_in_place_left); register_bench!(runner, benchmark_limbs_mod_power_of_2_sub_in_place_right); register_bench!(runner, benchmark_limbs_mod_power_of_2_sub_in_place_either); register_bench!( runner, benchmark_natural_mod_power_of_2_sub_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_power_of_2_sub_algorithms); register_bench!( runner, benchmark_natural_mod_power_of_2_sub_evaluation_strategy ); } fn demo_limbs_mod_power_of_2_limb_sub_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for (ys, x, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_limb_sub_limbs({}, {:?}, {}) = {:?}", x, ys, pow, limbs_mod_power_of_2_limb_sub_limbs(x, &ys, pow) ); } } fn demo_limbs_mod_power_of_2_limb_sub_limbs_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut ys, x, pow) in unsigned_vec_unsigned_unsigned_triple_gen_var_16() .get(gm, config) .take(limit) { let ys_old = ys.clone(); limbs_mod_power_of_2_limb_sub_limbs_in_place(x, &mut ys, pow); println!( "ys := {ys_old:?}; limbs_mod_power_of_2_limb_sub_limbs_in_place({x}, &mut ys, {pow}); \ ys = {ys:?}", ); } } fn demo_limbs_mod_power_of_2_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() .get(gm, config) .take(limit) { println!( "limbs_mod_power_of_2_sub({:?}, {:?}, {}) = {:?}", xs, ys, pow, limbs_mod_power_of_2_sub(&xs, &ys, pow) ); } } fn demo_limbs_mod_power_of_2_sub_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_mod_power_of_2_sub_in_place_left(&mut xs, &ys, pow); println!( "xs := {xs_old:?}; \ limbs_mod_power_of_2_sub_in_place_left(&mut xs, {ys:?}, {pow}); xs = {xs:?}", ); } } fn demo_limbs_mod_power_of_2_sub_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() .get(gm, config) .take(limit) { let ys_old = ys.clone(); limbs_mod_power_of_2_sub_in_place_right(&xs, &mut ys, pow); println!( "ys := {ys_old:?}; \ limbs_mod_power_of_2_sub_in_place_right({xs:?}, &mut ys, {pow}); ys = {ys:?}", ); } } fn demo_limbs_mod_power_of_2_sub_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys, pow) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_mod_power_of_2_sub_in_place_either(&mut xs, &mut ys, pow); println!( "xs := {xs_old:?}; ys := {ys_old:?}; \ limbs_mod_power_of_2_sub_in_place_either(&mut xs, &mut ys, {pow}) = {right}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_mod_power_of_2_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_power_of_2_sub_assign(y, pow); println!("x := {x_old}; x.mod_power_of_2_sub_assign({y_old}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); x.mod_power_of_2_sub_assign(&y, pow); println!("x := {x_old}; x.mod_power_of_2_sub_assign(&{y}, {pow}); x = {x}"); } } fn demo_natural_mod_power_of_2_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{} - {} ≡ {} mod 2^{}", x_old, y_old, x.mod_power_of_2_sub(y, pow), pow ); } } fn demo_natural_mod_power_of_2_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{} - {} ≡ {} mod 2^{}", x_old, y, x.mod_power_of_2_sub(&y, pow), pow ); } } fn demo_natural_mod_power_of_2_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "{} - {} ≡ {} mod 2^{}", x, y_old, (&x).mod_power_of_2_sub(y, pow), pow ); } } fn demo_natural_mod_power_of_2_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, pow) in natural_natural_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "{} - {} ≡ {} mod 2^{}", x, y, (&x).mod_power_of_2_sub(&y, pow), pow ); } } fn benchmark_limbs_mod_power_of_2_limb_sub_limbs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_limb_sub_limbs(Limb, &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_16().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ys, x, pow)| { no_out!(limbs_mod_power_of_2_limb_sub_limbs(x, &ys, pow)); })], ); } fn benchmark_limbs_mod_power_of_2_limb_sub_limbs_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_limb_sub_limbs_in_place(Limb, &mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen_var_16().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(mut ys, x, pow)| { limbs_mod_power_of_2_limb_sub_limbs_in_place(x, &mut ys, pow); })], ); } fn benchmark_limbs_mod_power_of_2_sub( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_sub(&[Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ref xs, ref ys, pow)| { no_out!(limbs_mod_power_of_2_sub(xs, ys, pow)); })], ); } fn benchmark_limbs_mod_power_of_2_sub_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_sub_in_place_left(&mut Vec, &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ref mut xs, ref ys, pow)| { limbs_mod_power_of_2_sub_in_place_left(xs, ys, pow); })], ); } fn benchmark_limbs_mod_power_of_2_sub_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_sub_in_place_right(&[Limb], &mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ref xs, ref mut ys, pow)| { limbs_mod_power_of_2_sub_in_place_right(xs, ys, pow); })], ); } fn benchmark_limbs_mod_power_of_2_sub_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mod_power_of_2_sub_in_place_left(&mut Vec, &mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [("Malachite", &mut |(ref mut xs, ref mut ys, pow)| { no_out!(limbs_mod_power_of_2_sub_in_place_either(xs, ys, pow)); })], ); } fn benchmark_natural_mod_power_of_2_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_sub_assign(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_sub_assign(Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_sub_assign(y, pow)), ), ( "Natural.mod_power_of_2_sub_assign(&Natural, u64)", &mut |(mut x, y, pow)| no_out!(x.mod_power_of_2_sub_assign(&y, pow)), ), ], ); } fn benchmark_natural_mod_power_of_2_sub_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_sub(Natural, u64)", BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ("default", &mut |(x, y, pow)| { no_out!(x.mod_power_of_2_sub(y, pow)); }), ("alt", &mut |(x, y, pow)| { if x >= y { x - y } else { let mut x = x; x.set_bit(pow); x - y }; }), ("naive", &mut |(x, y, pow)| { no_out!((Integer::from(x) - Integer::from(y)).mod_power_of_2(pow)); }), ("using mod_sub", &mut |(x, y, pow)| { no_out!(x.mod_sub(y, Natural::power_of_2(pow))); }), ], ); } fn benchmark_natural_mod_power_of_2_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_power_of_2_sub(Natural, u64)", BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_3_bucketer("pow"), &mut [ ( "Natural.mod_power_of_2_sub(Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_sub(y, pow)), ), ( "Natural.mod_power_of_2_sub(&Natural, u64)", &mut |(x, y, pow)| no_out!(x.mod_power_of_2_sub(&y, pow)), ), ( "(&Natural).mod_power_of_2_sub(Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_sub(y, pow)), ), ( "(&Natural).mod_power_of_2_sub(&Natural, u64)", &mut |(x, y, pow)| no_out!((&x).mod_power_of_2_sub(&y, pow)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModShl, ModShlAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::triple_3_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_natural_signed_triple_gen_var_1, natural_natural_unsigned_triple_gen_var_6, }; use std::ops::Shl; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_mod_shl_assign_unsigned); register_unsigned_demos!(runner, demo_natural_mod_shl_assign_unsigned_ref); register_unsigned_demos!(runner, demo_natural_mod_shl_unsigned); register_unsigned_demos!(runner, demo_natural_mod_shl_unsigned_val_ref); register_unsigned_demos!(runner, demo_natural_mod_shl_unsigned_ref_val); register_unsigned_demos!(runner, demo_natural_mod_shl_unsigned_ref_ref); register_signed_demos!(runner, demo_natural_mod_shl_assign_signed); register_signed_demos!(runner, demo_natural_mod_shl_assign_signed_ref); register_signed_demos!(runner, demo_natural_mod_shl_signed); register_signed_demos!(runner, demo_natural_mod_shl_signed_val_ref); register_signed_demos!(runner, demo_natural_mod_shl_signed_ref_val); register_signed_demos!(runner, demo_natural_mod_shl_signed_ref_ref); register_unsigned_benches!( runner, benchmark_natural_mod_shl_assign_unsigned_evaluation_strategy ); register_unsigned_benches!(runner, benchmark_natural_mod_shl_unsigned_algorithms); register_unsigned_benches!( runner, benchmark_natural_mod_shl_unsigned_evaluation_strategy ); register_signed_benches!( runner, benchmark_natural_mod_shl_assign_signed_evaluation_strategy ); register_signed_benches!(runner, benchmark_natural_mod_shl_signed_algorithms); register_signed_benches!(runner, benchmark_natural_mod_shl_signed_evaluation_strategy); } fn demo_natural_mod_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModShlAssign, { for (mut n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shl_assign(u, m.clone()); println!("x := {n_old}; x.mod_shl_assign({u}, {m}); x = {n}"); } } fn demo_natural_mod_shl_assign_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> Natural: ModShlAssign, { for (mut n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shl_assign(u, &m); println!("x := {n_old}; x.mod_shl_assign({u}, &{m}); x = {n}"); } } fn demo_natural_mod_shl_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModShl, { for (n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_shl({}, {}) = {}", n_old, u, m.clone(), n.mod_shl(u, m) ); } } fn demo_natural_mod_shl_unsigned_val_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> Natural: ModShl, { for (n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.mod_shl({}, &{}) = {}", n_old, u, m, n.mod_shl(u, &m)); } } fn demo_natural_mod_shl_unsigned_ref_val( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: ModShl, { for (n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { println!( "(&{}).mod_shl({}, {}) = {}", n, u, m.clone(), (&n).mod_shl(u, m) ); } } fn demo_natural_mod_shl_unsigned_ref_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a, 'b> &'a Natural: ModShl, { for (n, m, u) in natural_natural_unsigned_triple_gen_var_6::() .get(gm, config) .take(limit) { println!("(&{}).mod_shl({}, &{}) = {}", n, u, m, (&n).mod_shl(u, &m)); } } fn demo_natural_mod_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ModShlAssign, { for (mut n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shl_assign(i, m.clone()); println!("x := {n_old}; x.mod_shl_assign({i}, {m}); x = {n}"); } } fn demo_natural_mod_shl_assign_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> Natural: ModShlAssign, { for (mut n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shl_assign(i, &m); println!("x := {n_old}; x.mod_shl_assign({i}, &{m}); x = {n}"); } } fn demo_natural_mod_shl_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ModShl, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_shl({}, {}) = {}", n_old, i, m.clone(), n.mod_shl(i, m) ); } } fn demo_natural_mod_shl_signed_val_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> Natural: ModShl, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.mod_shl({}, &{}) = {}", n_old, i, m, n.mod_shl(i, &m)); } } fn demo_natural_mod_shl_signed_ref_val( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: ModShl, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).mod_shl({}, {}) = {}", n, i, m.clone(), (&n).mod_shl(i, m) ); } } fn demo_natural_mod_shl_signed_ref_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a, 'b> &'a Natural: ModShl, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { println!("(&{}).mod_shl({}, &{}) = {}", n, i, m, (&n).mod_shl(i, &m)); } } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shl_assign_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShlAssign + ModShlAssign, { run_benchmark( &format!("Natural.mod_shl_assign({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shl_assign({}, Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shl_assign(y, m)), ), ( &format!("Natural.mod_shl_assign({}, &Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shl_assign(y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_shl_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModShl + Shl, { run_benchmark( &format!("Natural.mod_shl({}, Natural)", T::NAME), BenchmarkType::Algorithms, natural_natural_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, m, y)| no_out!(x.mod_shl(y, m))), ("using << and %", &mut |(x, m, y)| no_out!((x << y) % m)), ], ); } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShl + ModShl, for<'a, 'b> &'a Natural: ModShl + ModShl, { run_benchmark( &format!("Natural.mod_shl({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_unsigned_triple_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shl({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shl(y, m)), ), ( &format!("Natural.mod_shl({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shl(y, &m)), ), ( &format!("(&Natural).mod_shl({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shl(y, m)), ), ( &format!("(&Natural).mod_shl({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shl(y, &m)), ), ], ); } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shl_assign_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShlAssign + ModShlAssign, { run_benchmark( &format!("Natural.mod_shl_assign({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shl_assign({}, Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shl_assign(y, m)), ), ( &format!("Natural.mod_shl_assign({}, &Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shl_assign(y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_shl_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModShl + Shl, { run_benchmark( &format!("Natural.mod_shl({}, Natural)", T::NAME), BenchmarkType::Algorithms, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, m, y)| no_out!(x.mod_shl(y, m))), ("using << and %", &mut |(x, m, y)| no_out!((x << y) % m)), ], ); } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShl + ModShl, for<'a, 'b> &'a Natural: ModShl + ModShl, { run_benchmark( &format!("Natural.mod_shl({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shl({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shl(y, m)), ), ( &format!("Natural.mod_shl({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shl(y, &m)), ), ( &format!("(&Natural).mod_shl({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shl(y, m)), ), ( &format!("(&Natural).mod_shl({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shl(y, &m)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModShr, ModShrAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::bucketers::triple_3_bit_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_natural_signed_triple_gen_var_1; use std::ops::Shr; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_natural_mod_shr_assign); register_signed_demos!(runner, demo_natural_mod_shr_assign_ref); register_signed_demos!(runner, demo_natural_mod_shr); register_signed_demos!(runner, demo_natural_mod_shr_val_ref); register_signed_demos!(runner, demo_natural_mod_shr_ref_val); register_signed_demos!(runner, demo_natural_mod_shr_ref_ref); register_signed_benches!(runner, benchmark_natural_mod_shr_assign_evaluation_strategy); register_signed_benches!(runner, benchmark_natural_mod_shr_algorithms); register_signed_benches!(runner, benchmark_natural_mod_shr_evaluation_strategy); } fn demo_natural_mod_shr_assign(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ModShrAssign, { for (mut n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shr_assign(i, m.clone()); println!("x := {n_old}; x.mod_shr_assign({i}, {m}); x = {n}"); } } fn demo_natural_mod_shr_assign_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> Natural: ModShrAssign, { for (mut n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.mod_shr_assign(i, &m); println!("x := {n_old}; x.mod_shr_assign({i}, &{m}); x = {n}"); } } fn demo_natural_mod_shr(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ModShr, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.mod_shr({}, {}) = {}", n_old, i, m.clone(), n.mod_shr(i, m) ); } } fn demo_natural_mod_shr_val_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> Natural: ModShr, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.mod_shr({}, &{}) = {}", n_old, i, m, n.mod_shr(i, &m)); } } fn demo_natural_mod_shr_ref_val(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Natural: ModShr, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).mod_shr({}, {}) = {}", n, i, m.clone(), (&n).mod_shr(i, m) ); } } fn demo_natural_mod_shr_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a, 'b> &'a Natural: ModShr, { for (n, m, i) in natural_natural_signed_triple_gen_var_1::() .get(gm, config) .take(limit) { println!("(&{}).mod_shr({}, &{}) = {}", n, i, m, (&n).mod_shr(i, &m)); } } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shr_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShrAssign + ModShrAssign, { run_benchmark( &format!("Natural.mod_shr_assign({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shr_assign({}, Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shr_assign(y, m)), ), ( &format!("Natural.mod_shr_assign({}, &Natural)", T::NAME), &mut |(mut x, m, y)| no_out!(x.mod_shr_assign(y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_shr_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ModShr + Shr, { run_benchmark( &format!("Natural.mod_shr({}, Natural)", T::NAME), BenchmarkType::Algorithms, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ("default", &mut |(x, m, y)| no_out!(x.mod_shr(y, m))), ("using >> and %", &mut |(x, m, y)| no_out!((x >> y) % m)), ], ); } #[allow(clippy::trait_duplication_in_bounds)] fn benchmark_natural_mod_shr_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> Natural: ModShr + ModShr, for<'a, 'b> &'a Natural: ModShr + ModShr, { run_benchmark( &format!("Natural.mod_shr({}, Natural)", T::NAME), BenchmarkType::EvaluationStrategy, natural_natural_signed_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_bit_bucketer("m"), &mut [ ( &format!("Natural.mod_shr({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shr(y, m)), ), ( &format!("Natural.mod_shr({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!(x.mod_shr(y, &m)), ), ( &format!("(&Natural).mod_shr({}, Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shr(y, m)), ), ( &format!("(&Natural).mod_shr({}, &Natural)", T::NAME), &mut |(x, m, y)| no_out!((&x).mod_shr(y, &m)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModMul, ModSquare, ModSquareAssign, Square}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen_var_8; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_square_assign); register_demo!(runner, demo_natural_mod_square_assign_ref); register_demo!(runner, demo_natural_mod_square); register_demo!(runner, demo_natural_mod_square_val_ref); register_demo!(runner, demo_natural_mod_square_ref_val); register_demo!(runner, demo_natural_mod_square_ref_ref); register_bench!( runner, benchmark_natural_mod_square_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_mod_square_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_square_algorithms); } fn demo_natural_mod_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); n.mod_square_assign(m); println!("x := {n_old}; x.mod_square_assign({m_old}); x = {n}"); } } fn demo_natural_mod_square_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); n.mod_square_assign(&m); println!("x := {n_old}; x.mod_square_assign(&{m}); x = {n}"); } } fn demo_natural_mod_square(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); let m_old = m.clone(); println!("{}.square() ≡ {} mod {}", n_old, n.mod_square(m), m_old); } } fn demo_natural_mod_square_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let n_old = n.clone(); println!("{}.square() ≡ {} mod &{}", n_old, n.mod_square(&m), m); } } fn demo_natural_mod_square_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { let m_old = m.clone(); println!("(&{}).square() ≡ {} mod {}", n, (&n).mod_square(m), m_old); } } fn demo_natural_mod_square_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, m) in natural_pair_gen_var_8().get(gm, config).take(limit) { println!("(&{}).square() ≡ {} mod &{}", n, (&n).mod_square(&m), m); } } fn benchmark_natural_mod_square_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_square_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_square_assign(Natural)", &mut |(mut n, m)| { n.mod_square_assign(m); }), ("Natural.mod_square_assign(&Natural)", &mut |(mut n, m)| { n.mod_square_assign(&m); }), ], ); } fn benchmark_natural_mod_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_square(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_square(Natural)", &mut |(n, m)| { no_out!(n.mod_square(m)); }), ("Natural.mod_square(&Natural)", &mut |(n, m)| { no_out!(n.mod_square(&m)); }), ("(&Natural).mod_square(Natural)", &mut |(n, m)| { no_out!((&n).mod_square(m)); }), ("(&Natural).mod_square(&Natural)", &mut |(n, m)| { no_out!((&n).mod_square(&m)); }), ], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_mod_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_square(Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_8().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("m"), &mut [ ("Natural.mod_square(Natural)", &mut |(n, m)| { no_out!((&n).mod_square(&m)); }), ("Natural.mod_mul(Natural, Natural)", &mut |(n, m)| { no_out!((&n).mod_mul(&n, &m)); }), ("Natural.square() % Natural", &mut |(n, m)| { no_out!((&n).square() % &m); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Mod, ModSub, ModSubAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::test_util::bench::bucketers::triple_3_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen_var_3; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_mod_sub_assign); register_demo!(runner, demo_natural_mod_sub_assign_val_ref); register_demo!(runner, demo_natural_mod_sub_assign_ref_val); register_demo!(runner, demo_natural_mod_sub_assign_ref_ref); register_demo!(runner, demo_natural_mod_sub); register_demo!(runner, demo_natural_mod_sub_val_val_ref); register_demo!(runner, demo_natural_mod_sub_val_ref_val); register_demo!(runner, demo_natural_mod_sub_val_ref_ref); register_demo!(runner, demo_natural_mod_sub_ref_val_val); register_demo!(runner, demo_natural_mod_sub_ref_val_ref); register_demo!(runner, demo_natural_mod_sub_ref_ref_val); register_demo!(runner, demo_natural_mod_sub_ref_ref_ref); register_bench!(runner, benchmark_natural_mod_sub_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_mod_sub_algorithms); register_bench!(runner, benchmark_natural_mod_sub_evaluation_strategy); } fn demo_natural_mod_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); x.mod_sub_assign(y, m); println!("x := {x_old}; x.mod_sub_assign({y_old}, {m_old}); x = {x}"); } } fn demo_natural_mod_sub_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); let y_old = y.clone(); x.mod_sub_assign(y, &m); println!("x := {x_old}; x.mod_sub_assign({y_old}, &{m_old}); x = {x}"); } } fn demo_natural_mod_sub_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); x.mod_sub_assign(&y, m); println!("x := {x_old}; x.mod_sub_assign(&{y}, {m_old}); x = {x}"); } } fn demo_natural_mod_sub_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_sub_assign(&y, &m); println!("x := {x_old}; x.mod_sub_assign(&{y}, &{m}); x = {x}"); } } fn demo_natural_mod_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let m_old = m.clone(); println!("{} - {} ≡ {} mod {}", x_old, y_old, x.mod_sub(y, m), m_old); } } fn demo_natural_mod_sub_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} ≡ {} mod {}", x_old, y_old, x.mod_sub(y, &m), m); } } fn demo_natural_mod_sub_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); let m_old = m.clone(); println!("{} - {} ≡ {} mod {}", x_old, y, x.mod_sub(&y, m), m_old); } } fn demo_natural_mod_sub_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - {} ≡ {} mod {}", x_old, y, x.mod_sub(&y, &m), m); } } fn demo_natural_mod_sub_ref_val_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); let m_old = m.clone(); println!("{} - {} ≡ {} mod {}", x, y_old, (&x).mod_sub(y, m), m_old); } } fn demo_natural_mod_sub_ref_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let y_old = y.clone(); println!("{} - {} ≡ {} mod {}", x, y_old, (&x).mod_sub(y, &m), m); } } fn demo_natural_mod_sub_ref_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { let m_old = m.clone(); println!("{} - {} ≡ {} mod {}", x, y, (&x).mod_sub(&y, m), m_old); } } fn demo_natural_mod_sub_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, m) in natural_triple_gen_var_3().get(gm, config).take(limit) { println!("{} - {} ≡ {} mod {}", x, y, (&x).mod_sub(&y, &m), m); } } fn benchmark_natural_mod_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_sub_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ( "Natural.mod_sub_assign(Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_sub_assign(y, m)), ), ( "Natural.mod_sub_assign(Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_sub_assign(y, &m)), ), ( "Natural.mod_sub_assign(&Natural, Natural)", &mut |(mut x, y, m)| no_out!(x.mod_sub_assign(&y, m)), ), ( "Natural.mod_sub_assign(&Natural, &Natural)", &mut |(mut x, y, m)| no_out!(x.mod_sub_assign(&y, &m)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mod_sub_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_sub(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("default", &mut |(x, y, m)| no_out!(x.mod_sub(y, m))), ("naive", &mut |(x, y, m)| { no_out!((Integer::from(x) - Integer::from(y)).mod_op(Integer::from(m))); }), ], ); } fn benchmark_natural_mod_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.mod_sub(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("m"), &mut [ ("Natural.mod_sub(Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_sub(y, m)); }), ("Natural.mod_sub(Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_sub(y, &m)); }), ("Natural.mod_sub(&Natural, Natural)", &mut |(x, y, m)| { no_out!(x.mod_sub(&y, m)); }), ("Natural.mod_sub(&Natural, &Natural)", &mut |(x, y, m)| { no_out!(x.mod_sub(&y, &m)); }), ("(&Natural).mod_sub(Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_sub(y, m)); }), ("(&Natural).mod_sub(Natural, &Natural)", &mut |(x, y, m)| { no_out!((&x).mod_sub(y, &m)); }), ("(&Natural).mod_sub(&Natural, Natural)", &mut |(x, y, m)| { no_out!((&x).mod_sub(&y, m)); }), ( "(&Natural).mod_sub(&Natural, &Natural)", &mut |(x, y, m)| no_out!((&x).mod_sub(&y, &m)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_sum_vec_len_bucketer, quadruple_2_vec_len_bucketer, triple_1_vec_len_bucketer, triple_2_3_sum_vec_len_bucketer, triple_2_vec_len_bucketer, triple_3_vec_len_bucketer, vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ large_type_gen_var_1, unsigned_pair_gen_var_27, unsigned_vec_gen_var_6, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_2, unsigned_vec_triple_gen_var_1, unsigned_vec_triple_gen_var_2, unsigned_vec_triple_gen_var_3, unsigned_vec_triple_gen_var_24, unsigned_vec_triple_gen_var_25, unsigned_vec_triple_gen_var_26, unsigned_vec_triple_gen_var_27, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_unsigned_triple_gen, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mul::limb::{ limbs_mul_limb, limbs_mul_limb_to_out, limbs_mul_limb_with_carry_to_out, limbs_slice_mul_limb_in_place, limbs_slice_mul_limb_with_carry_in_place, limbs_vec_mul_limb_in_place, }; use malachite_nz::natural::arithmetic::mul::mul_low::{ limbs_mul_low_same_length, limbs_mul_low_same_length_basecase, limbs_mul_low_same_length_basecase_alt, limbs_mul_low_same_length_divide_and_conquer, limbs_mul_low_same_length_divide_and_conquer_scratch_len, limbs_mul_low_same_length_divide_and_conquer_shared_scratch, limbs_mul_low_same_length_large, }; use malachite_nz::natural::arithmetic::mul::product_of_limbs::limbs_product; use malachite_nz::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h, limbs_mul_greater_to_out_toom_6h_input_sizes_valid, limbs_mul_greater_to_out_toom_6h_scratch_len, limbs_mul_greater_to_out_toom_8h, limbs_mul_greater_to_out_toom_8h_input_sizes_valid, limbs_mul_greater_to_out_toom_8h_scratch_len, limbs_mul_greater_to_out_toom_22, limbs_mul_greater_to_out_toom_22_input_sizes_valid, limbs_mul_greater_to_out_toom_22_scratch_len, limbs_mul_greater_to_out_toom_32, limbs_mul_greater_to_out_toom_32_input_sizes_valid, limbs_mul_greater_to_out_toom_32_scratch_len, limbs_mul_greater_to_out_toom_33, limbs_mul_greater_to_out_toom_33_input_sizes_valid, limbs_mul_greater_to_out_toom_33_scratch_len, limbs_mul_greater_to_out_toom_42, limbs_mul_greater_to_out_toom_42_input_sizes_valid, limbs_mul_greater_to_out_toom_42_scratch_len, limbs_mul_greater_to_out_toom_43, limbs_mul_greater_to_out_toom_43_input_sizes_valid, limbs_mul_greater_to_out_toom_43_scratch_len, limbs_mul_greater_to_out_toom_44, limbs_mul_greater_to_out_toom_44_input_sizes_valid, limbs_mul_greater_to_out_toom_44_scratch_len, limbs_mul_greater_to_out_toom_52, limbs_mul_greater_to_out_toom_52_input_sizes_valid, limbs_mul_greater_to_out_toom_52_scratch_len, limbs_mul_greater_to_out_toom_53, limbs_mul_greater_to_out_toom_53_input_sizes_valid, limbs_mul_greater_to_out_toom_53_scratch_len, limbs_mul_greater_to_out_toom_54, limbs_mul_greater_to_out_toom_54_input_sizes_valid, limbs_mul_greater_to_out_toom_54_scratch_len, limbs_mul_greater_to_out_toom_62, limbs_mul_greater_to_out_toom_62_input_sizes_valid, limbs_mul_greater_to_out_toom_62_scratch_len, limbs_mul_greater_to_out_toom_63, limbs_mul_greater_to_out_toom_63_input_sizes_valid, limbs_mul_greater_to_out_toom_63_scratch_len, }; use malachite_nz::natural::arithmetic::mul::{ limbs_mul, limbs_mul_greater, limbs_mul_greater_to_out, limbs_mul_greater_to_out_basecase, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, triple_3_vec_natural_sum_bits_bucketer, vec_natural_sum_bits_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_rm, natural_vec_gen, natural_vec_gen_nrm, unsigned_vec_triple_gen_var_4, unsigned_vec_triple_gen_var_5, unsigned_vec_triple_gen_var_6, unsigned_vec_triple_gen_var_7, unsigned_vec_triple_gen_var_8, unsigned_vec_triple_gen_var_9, unsigned_vec_triple_gen_var_10, unsigned_vec_triple_gen_var_11, unsigned_vec_triple_gen_var_12, unsigned_vec_triple_gen_var_13, unsigned_vec_triple_gen_var_14, unsigned_vec_triple_gen_var_15, unsigned_vec_triple_gen_var_16, unsigned_vec_triple_gen_var_18, unsigned_vec_triple_gen_var_19, unsigned_vec_triple_gen_var_20, unsigned_vec_triple_gen_var_22, unsigned_vec_triple_gen_var_23, unsigned_vec_triple_gen_var_58, }; use malachite_nz::test_util::natural::arithmetic::mul::{ limbs_mul_greater_to_out_basecase_mem_opt, limbs_product_naive, natural_product_naive, }; use num::BigUint; use std::iter::Product; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_mul_limb); register_demo!(runner, demo_limbs_mul_limb_with_carry_to_out); register_demo!(runner, demo_limbs_mul_limb_to_out); register_demo!(runner, demo_limbs_slice_mul_limb_with_carry_in_place); register_demo!(runner, demo_limbs_slice_mul_limb_in_place); register_demo!(runner, demo_limbs_vec_mul_limb_in_place); register_demo!(runner, demo_limbs_mul_greater); register_demo!(runner, demo_limbs_mul); register_demo!(runner, demo_limbs_mul_same_length_to_out); register_demo!(runner, demo_limbs_mul_greater_to_out); register_demo!(runner, demo_limbs_mul_to_out); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_22_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_32_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_33_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_42_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_43_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_44_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_52_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_53_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_54_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_62_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_63_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_6h_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_8h_input_sizes_valid ); register_demo!( runner, demo_limbs_mul_greater_to_out_toom_33_and_toom_44_input_sizes_valid ); register_demo!(runner, demo_limbs_mul_low_same_length_basecase); register_demo!( runner, demo_limbs_mul_low_same_length_divide_and_conquer_shared_scratch ); register_demo!(runner, demo_limbs_mul_low_same_length_divide_and_conquer); register_demo!(runner, demo_limbs_mul_low_same_length); register_demo!(runner, demo_limbs_product); register_demo!(runner, demo_natural_mul); register_demo!(runner, demo_natural_mul_val_ref); register_demo!(runner, demo_natural_mul_ref_val); register_demo!(runner, demo_natural_mul_ref_ref); register_demo!(runner, demo_natural_mul_assign); register_demo!(runner, demo_natural_mul_assign_ref); register_demo!(runner, demo_natural_product); register_demo!(runner, demo_natural_ref_product); register_bench!(runner, benchmark_limbs_mul_limb); register_bench!(runner, benchmark_limbs_mul_limb_with_carry_to_out); register_bench!(runner, benchmark_limbs_mul_limb_to_out); register_bench!(runner, benchmark_limbs_slice_mul_limb_with_carry_in_place); register_bench!(runner, benchmark_limbs_slice_mul_limb_in_place); register_bench!(runner, benchmark_limbs_vec_mul_limb_in_place); register_bench!(runner, benchmark_limbs_mul_greater); register_bench!(runner, benchmark_limbs_mul); register_bench!(runner, benchmark_limbs_mul_same_length_to_out); register_bench!(runner, benchmark_limbs_mul_greater_to_out_algorithms); register_bench!(runner, benchmark_limbs_mul_to_out); register_bench!( runner, benchmark_limbs_mul_greater_to_out_basecase_mem_opt_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_22_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_32_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_33_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_33_same_length_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_42_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_43_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_44_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_44_same_length_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_52_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_53_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_54_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_62_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_63_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_6h_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_6h_same_length_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_8h_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_8h_same_length_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_32_to_43_algorithms ); register_bench!( runner, benchmark_limbs_mul_greater_to_out_toom_42_to_53_algorithms ); register_bench!( runner, benchmark_limbs_mul_low_same_length_basecase_algorithms ); register_bench!( runner, benchmark_limbs_mul_low_same_length_basecase_algorithms_2 ); register_bench!( runner, benchmark_limbs_mul_low_same_length_divide_and_conquer_shared_scratch_algorithms ); register_bench!( runner, benchmark_limbs_mul_low_same_length_divide_and_conquer_algorithms ); register_bench!(runner, benchmark_limbs_mul_low_same_length_large_algorithms); register_bench!(runner, benchmark_limbs_mul_low_same_length_algorithms); register_bench!(runner, benchmark_limbs_product_algorithms); register_bench!(runner, benchmark_natural_mul_library_comparison); register_bench!(runner, benchmark_natural_mul_evaluation_strategy); register_bench!(runner, benchmark_natural_mul_assign_library_comparison); register_bench!(runner, benchmark_natural_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_product_algorithms); register_bench!(runner, benchmark_natural_product_library_comparison); register_bench!(runner, benchmark_natural_product_evaluation_strategy); } fn demo_limbs_mul_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { println!( "limbs_mul_limb({:?}, {}) = {:?}", xs, y, limbs_mul_limb(&xs, y) ); } } fn demo_limbs_mul_limb_with_carry_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y, carry) in large_type_gen_var_1().get(gm, config).take(limit) { let out_old = out.clone(); let carry_out = limbs_mul_limb_with_carry_to_out::(&mut out, &xs, y, carry); println!( "out := {out_old:?}; \ limbs_mul_limb_with_carry_to_out(&mut out, {xs:?}, {y}, {carry}) = {carry_out}; \ out = {out:?}", ); } } fn demo_limbs_mul_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_mul_limb_to_out::(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_mul_limb_to_out(&mut out, {xs:?}, {y}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_mul_limb_with_carry_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y, carry) in unsigned_vec_unsigned_unsigned_triple_gen() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry_out = limbs_slice_mul_limb_with_carry_in_place(&mut xs, y, carry); println!( "xs := {xs_old:?}; \ limbs_slice_mul_limb_with_carry_in_place(&mut xs, {y}, {carry}) = {carry_out}; \ xs = {xs:?}", ); } } fn demo_limbs_slice_mul_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_mul_limb_in_place(&mut xs, y); println!( "xs := {xs_old:?}; \ limbs_slice_mul_limb_in_place(&mut xs, {y}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_mul_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_mul_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_vec_mul_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_mul_greater(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_1().get(gm, config).take(limit) { println!( "limbs_mul_greater({:?}, {:?}) = {:?}", xs, ys, limbs_mul_greater(&xs, &ys) ); } } fn demo_limbs_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_2().get(gm, config).take(limit) { println!("limbs_mul({:?}, {:?}) = {:?}", xs, ys, limbs_mul(&xs, &ys)); } } fn demo_limbs_mul_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_1().get(gm, config).take(limit) { let out_old = out.clone(); let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(&mut out, &xs, &ys, &mut mul_scratch); println!( "out := {out_old:?}; \ limbs_mul_same_length_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_mul_greater_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_2().get(gm, config).take(limit) { let out_old = out.clone(); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs.len(), ys.len())]; let carry = limbs_mul_greater_to_out(&mut out, &xs, &ys, &mut mul_scratch); println!( "out := {out_old:?}; \ limbs_mul_greater_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } fn demo_limbs_mul_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_3().get(gm, config).take(limit) { let out_old = out.clone(); let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs.len(), ys.len())]; let carry = limbs_mul_to_out(&mut out, &xs, &ys, &mut mul_scratch); println!( "out := {out_old:?}; \ limbs_mul_to_out(&mut out, {xs:?}, {ys:?}) = {carry}; out = {out:?}", ); } } macro_rules! mul_valid_helper { ($name: ident, $demo_name: ident) => { fn $demo_name(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in unsigned_pair_gen_var_27().get(gm, config).take(limit) { println!( concat!(stringify!($name), "({}, {}) = {}"), x, y, $name(x, y) ); } } }; } mul_valid_helper!( limbs_mul_greater_to_out_toom_22_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_22_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_32_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_32_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_33_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_33_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_42_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_42_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_43_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_43_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_44_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_44_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_52_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_52_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_53_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_53_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_54_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_54_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_62_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_62_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_63_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_63_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_6h_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_6h_input_sizes_valid ); mul_valid_helper!( limbs_mul_greater_to_out_toom_8h_input_sizes_valid, demo_limbs_mul_greater_to_out_toom_8h_input_sizes_valid ); fn demo_limbs_mul_greater_to_out_toom_33_and_toom_44_input_sizes_valid( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, y) in unsigned_pair_gen_var_27().get(gm, config).take(limit) { println!( "Toom-33 and Toom-44 ({}, {}) = {}", x, y, limbs_mul_greater_to_out_toom_33_input_sizes_valid(x, y) && limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) ); } } fn demo_limbs_mul_low_same_length_basecase(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_24().get(gm, config).take(limit) { let out_old = out.clone(); limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_mul_low_same_length_basecase(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_mul_low_same_length_divide_and_conquer_shared_scratch( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_25().get(gm, config).take(limit) { let out_old = out.clone(); limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_mul_low_same_length_divide_and_conquer_shared_scratch\ (&mut out, {xs:?}, {ys:?}); \ out = {out:?}", ); } } fn demo_limbs_mul_low_same_length_divide_and_conquer( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_26().get(gm, config).take(limit) { let out_old = out.clone(); let mut scratch = vec![0; xs.len() << 1]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &xs, &ys, &mut scratch); println!( "out := {out_old:?}; \ limbs_mul_low_same_length_divide_and_conquer(&mut out, {xs:?}, {ys:?}); \ out = {out:?}", ); } } fn demo_limbs_mul_low_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_1().get(gm, config).take(limit) { let out_old = out.clone(); limbs_mul_low_same_length(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_mul_low_same_length(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_product(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen_var_6().get(gm, config).take(limit) { let xs_old = xs.clone(); let mut out = Vec::new(); let (size, new_out) = limbs_product(&mut out, &mut xs); out = new_out.unwrap(); out.truncate(size); println!("product_of_limbs({xs_old:?}) = {out:?}"); } } fn demo_natural_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_natural_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_natural_mul_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_natural_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_natural_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x *= {y}; x = {x}"); } } fn demo_natural_mul_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x *= &{y}; x = {x}"); } } fn demo_natural_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in natural_vec_gen().get(gm, config).take(limit) { println!( "product({:?}) = {}", xs.clone(), Natural::product(xs.into_iter()) ); } } fn demo_natural_ref_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in natural_vec_gen().get(gm, config).take(limit) { println!("product({:?}) = {}", xs, Natural::product(xs.iter())); } } fn benchmark_limbs_mul_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mul_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_mul_limb(&xs, y)))], ); } fn benchmark_limbs_mul_limb_with_carry_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_limb_with_carry_to_out(&mut [Limb], &[Limb], Limb, Limb)", BenchmarkType::Single, large_type_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y, carry)| { no_out!(limbs_mul_limb_with_carry_to_out::( &mut out, &xs, y, carry )); })], ); } fn benchmark_limbs_mul_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mul_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_mul_limb_to_out::(&mut out, &xs, y)); })], ); } fn benchmark_limbs_slice_mul_limb_with_carry_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_mul_limb_with_carry_in_place(&mut [Limb], Limb, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_unsigned_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y, carry)| { no_out!(limbs_slice_mul_limb_with_carry_in_place(&mut xs, y, carry)); })], ); } fn benchmark_limbs_slice_mul_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_mul_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_slice_mul_limb_in_place(&mut xs, y)); })], ); } fn benchmark_limbs_vec_mul_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_mul_limb_in_place(&mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_vec_mul_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_mul_greater(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mul_greater(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_sum_vec_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_mul_greater(&xs, &ys)); })], ); } fn benchmark_limbs_mul(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mul(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_sum_vec_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_mul(&xs, &ys)))], ); } fn benchmark_limbs_mul_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(&mut out, &xs, &ys, &mut mul_scratch); })], ); } fn benchmark_limbs_mul_greater_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ("full", &mut |(mut out, xs, ys)| { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs.len(), ys.len())]; no_out!(limbs_mul_greater_to_out( &mut out, &xs, &ys, &mut mul_scratch, )); }), ], ); } fn benchmark_limbs_mul_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_mul_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut out, xs, ys)| { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs.len(), ys.len())]; no_out!(limbs_mul_to_out(&mut out, &xs, &ys, &mut mul_scratch)); })], ); } fn benchmark_limbs_mul_greater_to_out_basecase_mem_opt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_basecase_mem_opt(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [ ("limbs_mul_greater_to_out_basecase", &mut |( mut out, xs, ys, )| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ( "limbs_mul_greater_to_out_basecase_mem_opt", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase_mem_opt(&mut out, &xs, &ys); }, ), ], ); } macro_rules! bench_mul_helper { ($bench: ident, $mul: ident, $scratch: ident, $gen: ident, $name: expr) => { fn $bench(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( concat!(stringify!($mul), "(&mut [Limb], &[Limb], &[Limb])"), BenchmarkType::Algorithms, $gen().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys) }), ($name, &mut |(mut out, xs, ys)| { let mut scratch = vec![0; $scratch(xs.len(), ys.len())]; $mul(&mut out, &xs, &ys, &mut scratch) }), ], ); } }; } bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_22_algorithms, limbs_mul_greater_to_out_toom_22, limbs_mul_greater_to_out_toom_22_scratch_len, unsigned_vec_triple_gen_var_4, "Toom22" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_32_algorithms, limbs_mul_greater_to_out_toom_32, limbs_mul_greater_to_out_toom_32_scratch_len, unsigned_vec_triple_gen_var_5, "Toom32" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_33_algorithms, limbs_mul_greater_to_out_toom_33, limbs_mul_greater_to_out_toom_33_scratch_len, unsigned_vec_triple_gen_var_6, "Toom33" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_42_algorithms, limbs_mul_greater_to_out_toom_42, limbs_mul_greater_to_out_toom_42_scratch_len, unsigned_vec_triple_gen_var_7, "Toom42" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_43_algorithms, limbs_mul_greater_to_out_toom_43, limbs_mul_greater_to_out_toom_43_scratch_len, unsigned_vec_triple_gen_var_8, "Toom43" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_44_algorithms, limbs_mul_greater_to_out_toom_44, limbs_mul_greater_to_out_toom_44_scratch_len, unsigned_vec_triple_gen_var_9, "Toom44" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_52_algorithms, limbs_mul_greater_to_out_toom_52, limbs_mul_greater_to_out_toom_52_scratch_len, unsigned_vec_triple_gen_var_10, "Toom52" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_54_algorithms, limbs_mul_greater_to_out_toom_54, limbs_mul_greater_to_out_toom_54_scratch_len, unsigned_vec_triple_gen_var_12, "Toom54" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_62_algorithms, limbs_mul_greater_to_out_toom_62, limbs_mul_greater_to_out_toom_62_scratch_len, unsigned_vec_triple_gen_var_13, "Toom62" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_6h_algorithms, limbs_mul_greater_to_out_toom_6h, limbs_mul_greater_to_out_toom_6h_scratch_len, unsigned_vec_triple_gen_var_15, "Toom6h" ); bench_mul_helper!( benchmark_limbs_mul_greater_to_out_toom_8h_algorithms, limbs_mul_greater_to_out_toom_8h, limbs_mul_greater_to_out_toom_8h_scratch_len, unsigned_vec_triple_gen_var_16, "Toom8h" ); fn benchmark_limbs_mul_greater_to_out_toom_53_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_53(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_11().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ("Toom32", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); }), ("Toom42", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_42(&mut out, &xs, &ys, &mut scratch); }), ("Toom53", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_63_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_63(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_14().get(gm, config), gm.name(), limit, file_name, &triple_2_3_sum_vec_len_bucketer("xs", "ys"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ("Toom42", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_42(&mut out, &xs, &ys, &mut scratch); }), ("Toom63", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_33_same_length_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_33(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_18().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ("Toom22", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_22_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_22(&mut out, &xs, &ys, &mut scratch); }), ("Toom33", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_44_same_length_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_44(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_58().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("Toom33", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); }), ("Toom44", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_6h_same_length_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_6h(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_19().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("Toom33", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); }), ("Toom44", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); }), ("Toom6h", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_8h_same_length_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_greater_to_out_toom_8h(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_20().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("Toom6h", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); }), ("Toom8h", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_32_to_43_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Toom32 to Toom43", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_22().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_len_bucketer("ys"), &mut [ ("Toom32", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); }), ("Toom43", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_greater_to_out_toom_42_to_53_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Toom42 to Toom53", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_23().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_len_bucketer("ys"), &mut [ ("Toom42", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_42(&mut out, &xs, &ys, &mut scratch); }), ("Toom53", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_low_same_length_basecase_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length_basecase(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_24().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); }), ("alt", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_basecase_alt(&mut out, &xs, &ys); }), ], ); } fn benchmark_limbs_mul_low_same_length_basecase_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length_basecase(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("basecase mul", &mut |(mut out, xs, ys)| { limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); }), ("basecase mul low", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); }), ], ); } fn benchmark_limbs_mul_low_same_length_divide_and_conquer_shared_scratch_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length_divide_and_conquer_shared_scratch\ (&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_25().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); }), ("divide-and-conquer", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &xs, &ys); }), ], ); } fn benchmark_limbs_mul_low_same_length_divide_and_conquer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length_divide_and_conquer(&mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_26().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); }), ("divide-and-conquer", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; ys.len() << 1]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_low_same_length_large_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length_large(&mut [Limb], &[Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_27().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("mul low divide-and-conquer", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_low_same_length_divide_and_conquer_scratch_len(xs.len())]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &xs, &ys, &mut scratch); }), ("mul low large", &mut |(mut out, xs, ys)| { let mut scratch = vec![0; limbs_mul_low_same_length_divide_and_conquer_scratch_len(xs.len())]; limbs_mul_low_same_length_large(&mut out, &xs, &ys, &mut scratch); }), ], ); } fn benchmark_limbs_mul_low_same_length_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_mul_low_same_length(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("mul low", &mut |(mut out, xs, ys)| { limbs_mul_low_same_length(&mut out, &xs, &ys); }), ("mul", &mut |(mut out, xs, ys)| { let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(&mut out, &xs, &ys, &mut mul_scratch); }), ], ); } fn benchmark_limbs_product_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_product(&mut [Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_gen_var_6().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |mut xs| { let mut out = Vec::new(); let (size, new_out) = limbs_product(&mut out, &mut xs); out = new_out.unwrap(); out.truncate(size); }), ("naive", &mut |xs| { let mut out = vec![0; xs.len()]; let out_len = limbs_product_naive(&mut out, &xs); out.truncate(out_len); }), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_mul_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural * Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x * y)), ("num", &mut |((x, y), _, _)| no_out!(x * y)), ("rug", &mut |(_, (x, y), _)| no_out!(x * y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural * Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural * Natural", &mut |(x, y)| no_out!(x * y)), ("Natural * &Natural", &mut |(x, y)| no_out!(x * &y)), ("&Natural * Natural", &mut |(x, y)| no_out!(&x * y)), ("&Natural * &Natural", &mut |(x, y)| no_out!(&x * &y)), ], ); } fn benchmark_natural_mul_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural *= Natural", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x *= y), ("rug", &mut |((mut x, y), _)| x *= y)], ); } fn benchmark_natural_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural *= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural *= Natural", &mut |(mut x, y)| no_out!(x *= y)), ("Natural *= &Natural", &mut |(mut x, y)| no_out!(x *= &y)), ], ); } fn benchmark_natural_product_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::product(Iterator)", BenchmarkType::LibraryComparison, natural_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_natural_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Natural::product(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigUint::product(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Integer::product(xs.iter())); }), ], ); } fn benchmark_natural_product_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::product(Iterator)", BenchmarkType::Algorithms, natural_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_natural_sum_bits_bucketer(), &mut [ ("default", &mut |xs| { no_out!(Natural::product(xs.into_iter())); }), ("naive", &mut |xs| { no_out!(natural_product_naive(xs.into_iter())); }), ], ); } fn benchmark_natural_product_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::product(Iterator)", BenchmarkType::EvaluationStrategy, natural_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_natural_sum_bits_bucketer(), &mut [ ("Natural::product(Iterator)", &mut |xs| { no_out!(Natural::product(xs.into_iter())); }), ("Natural::product(Iterator)", &mut |xs| { no_out!(Natural::product(xs.iter())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, triple_3_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_nrm}; use malachite_nz::test_util::natural::arithmetic::neg::neg_num; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_neg); register_demo!(runner, demo_natural_neg_ref); register_bench!(runner, benchmark_natural_neg_library_comparison); register_bench!(runner, benchmark_natural_neg_evaluation_strategy); } fn demo_natural_neg(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("-{} = {}", n.clone(), -n); } } fn demo_natural_neg_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("-(&{}) = {}", n.clone(), -n); } } #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn benchmark_natural_neg_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Natural", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(-x)), ("num", &mut |(x, _, _)| no_out!(neg_num(x))), ("rug", &mut |(_, x, _)| no_out!(-x)), ], ); } #[allow(unused_must_use, clippy::no_effect)] fn benchmark_natural_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Natural", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("-Natural", &mut |x| no_out!(-x)), ("-&Natural", &mut |x| no_out!(-&x))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign}; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::next_power_of_2::{ limbs_next_power_of_2, limbs_slice_next_power_of_2_in_place, limbs_vec_next_power_of_2_in_place, }; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_next_power_of_2); register_demo!(runner, demo_limbs_slice_next_power_of_2_in_place); register_demo!(runner, demo_limbs_vec_next_power_of_2_in_place); register_demo!(runner, demo_natural_next_power_of_2_assign); register_demo!(runner, demo_natural_next_power_of_2); register_demo!(runner, demo_natural_next_power_of_2_ref); register_bench!(runner, benchmark_limbs_next_power_of_2); register_bench!(runner, benchmark_limbs_slice_next_power_of_2_in_place); register_bench!(runner, benchmark_limbs_vec_next_power_of_2_in_place); register_bench!(runner, benchmark_natural_next_power_of_2_assign); register_bench!(runner, benchmark_natural_next_power_of_2_library_comparison); register_bench!( runner, benchmark_natural_next_power_of_2_evaluation_strategy ); } fn demo_limbs_next_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_next_power_of_2({:?}) = {:?}", xs, limbs_next_power_of_2(&xs) ); } } fn demo_limbs_slice_next_power_of_2_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_next_power_of_2_in_place(&mut xs); println!( "xs := {xs_old:?}; \ limbs_slice_next_power_of_2_in_place(&mut xs) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_next_power_of_2_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_next_power_of_2_in_place(&mut xs); println!("xs := {xs_old:?}; limbs_vec_next_power_of_2_in_place(&mut xs); xs = {xs:?}"); } } fn demo_natural_next_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in natural_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.next_power_of_2_assign(); println!("x := {n_old}; x.next_power_of_2_assign(); x = {n}"); } } fn demo_natural_next_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { let n_old = n.clone(); println!("{}.next_power_of_2() = {}", n_old, n.next_power_of_2()); } } fn demo_natural_next_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("(&{}).next_power_of_2() = {}", n, (&n).next_power_of_2()); } } fn benchmark_limbs_next_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_next_power_of_2(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_next_power_of_2(&xs)))], ); } fn benchmark_limbs_slice_next_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_next_power_of_2_in_place(&mut [Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut xs| { no_out!(limbs_slice_next_power_of_2_in_place(&mut xs)); })], ); } fn benchmark_limbs_vec_next_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_next_power_of_2_in_place(&mut Vec)", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut xs| { limbs_vec_next_power_of_2_in_place(&mut xs); })], ); } fn benchmark_natural_next_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.next_power_of_2_assign()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |mut n| n.next_power_of_2_assign())], ); } #[allow(unused_must_use)] fn benchmark_natural_next_power_of_2_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.next_power_of_2()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.next_power_of_2())), ("rug", &mut |(n, _)| no_out!(n.next_power_of_two())), ], ); } fn benchmark_natural_next_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.next_power_of_2()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.next_power_of_2()", &mut |n| { no_out!(n.next_power_of_2()); }), ("(&Natural).next_power_of_2()", &mut |n| { no_out!((&n).next_power_of_2()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_even); register_demo!(runner, demo_natural_odd); register_bench!(runner, benchmark_natural_even); register_bench!(runner, benchmark_natural_odd); } fn demo_natural_even(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.even() { println!("{n} is even"); } else { println!("{n} is not even"); } } } fn demo_natural_odd(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.odd() { println!("{n} is odd"); } else { println!("{n} is not odd"); } } } fn benchmark_natural_even(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.even()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.even()))], ); } fn benchmark_natural_odd(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.odd()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.odd()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Pow, PowAssign}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::{ pair_1_bits_times_pair_2_bucketer, pair_1_vec_len_times_pair_2_bucketer, triple_3_pair_1_bits_times_pair_2_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_31; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::pow::limbs_pow; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_nrm, }; use malachite_nz::test_util::natural::arithmetic::pow::{ natural_pow_naive, natural_pow_simple_binary, }; use num::traits::Pow as NumPow; use rug::ops::Pow as RugPow; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_pow); register_demo!(runner, demo_natural_pow_assign); register_demo!(runner, demo_natural_pow); register_demo!(runner, demo_natural_pow_ref); register_bench!(runner, benchmark_limbs_pow); register_bench!(runner, benchmark_natural_pow_assign); register_bench!(runner, benchmark_natural_pow_algorithms); register_bench!(runner, benchmark_natural_pow_library_comparison); register_bench!(runner, benchmark_natural_pow_evaluation_strategy); } fn demo_limbs_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, exp) in unsigned_vec_unsigned_pair_gen_var_31() .get(gm, config) .take(limit) { println!("limbs_pow({:?}, {}) = {:?}", xs, exp, limbs_pow(&xs, exp)); } } fn demo_natural_pow_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, pow) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.pow_assign(pow); println!("x := {n_old}; x.pow_assign({pow}); x = {n}"); } } fn demo_natural_pow(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{}.pow({}) = {}", n_old, pow, n.pow(pow)); } } fn demo_natural_pow_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!("(&{}).pow({}) = {}", n, pow, (&n).pow(pow)); } } fn benchmark_limbs_pow(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_pow(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_31().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_bucketer("xs", "exp"), &mut [("Malachite", &mut |(ref xs, exp)| { no_out!(limbs_pow(xs, exp)); })], ); } fn benchmark_natural_pow_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.pow_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bits_times_pair_2_bucketer("x", "exp"), &mut [("Malachite", &mut |(mut x, exp)| x.pow_assign(exp))], ); } fn benchmark_natural_pow_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.pow(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bits_times_pair_2_bucketer("x", "exp"), &mut [ ("default", &mut |(x, exp)| no_out!((&x).pow(exp))), ("naive", &mut |(x, exp)| no_out!(natural_pow_naive(&x, exp))), ("simple binary", &mut |(x, exp)| { no_out!(natural_pow_simple_binary(&x, exp)); }), ("alt", &mut |(x, exp)| no_out!(x.pow_ref_alt(exp))), ], ); } fn benchmark_natural_pow_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.pow(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_bits_times_pair_2_bucketer("x", "exp"), &mut [ ("Malachite", &mut |(_, _, (x, exp))| no_out!(x.pow(exp))), ("num", &mut |((x, exp), _, _)| no_out!(x.pow(exp))), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.pow(u32::exact_from(exp))); }), ], ); } fn benchmark_natural_pow_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.pow(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_bits_times_pair_2_bucketer("x", "exp"), &mut [ ("Natural.pow(u64)", &mut |(x, exp)| no_out!(x.pow(exp))), ("(&Natural).pow(u64)", &mut |(x, exp)| { no_out!((&x).pow(exp)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_power_of_2); register_bench!(runner, benchmark_natural_power_of_2); } fn demo_natural_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for pow in unsigned_gen_var_5().get(gm, config).take(limit) { println!("2^{} = {}", pow, Natural::power_of_2(pow)); } } fn benchmark_natural_power_of_2(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.power_of_2(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |pow| no_out!(Natural::power_of_2(pow)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Primorial; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::natural::arithmetic::primorial::{ primorial_naive, product_of_first_n_primes_naive, }; use rug::Complete; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_primorial); register_demo!(runner, demo_product_of_first_n_primes); register_bench!(runner, benchmark_primorial_library_comparison); register_bench!(runner, benchmark_primorial_algorithms); register_bench!(runner, benchmark_product_of_first_n_primes_algorithms); } fn demo_primorial(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!("{}# = {}", n, Natural::primorial(n)); } } fn demo_product_of_first_n_primes(gm: GenMode, config: &GenConfig, limit: usize) { for n in unsigned_gen_var_5().get(gm, config).take(limit) { println!("p_{}# = {}", n, Natural::product_of_first_n_primes(n)); } } fn benchmark_primorial_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.primorial(u64)", BenchmarkType::LibraryComparison, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Malachite", &mut |n| no_out!(Natural::primorial(n))), ("rug", &mut |n| { no_out!(rug::Integer::primorial(u32::exact_from(n)).complete()); }), ], ); } fn benchmark_primorial_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.primorial(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| no_out!(Natural::primorial(n))), ("naive", &mut |n| no_out!(primorial_naive(n))), ], ); } fn benchmark_product_of_first_n_primes_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.product_of_first_n_primes(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("default", &mut |n| { no_out!(Natural::product_of_first_n_primes(n)); }), ("naive", &mut |n| { no_out!(product_of_first_n_primes_naive(n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CheckedRoot, FloorRoot, FloorRootAssign, Pow, RootAssignRem, RootRem, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_14; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::root::{limbs_floor_root, limbs_root_rem}; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, pair_2_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, triple_3_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_nrm, natural_gen_rm, natural_unsigned_pair_gen_var_7, natural_unsigned_pair_gen_var_7_nrm, natural_unsigned_pair_gen_var_7_rm, }; use malachite_nz::test_util::natural::arithmetic::root::{ ceiling_root_binary, checked_root_binary, floor_root_binary, root_rem_binary, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_floor_root); register_demo!(runner, demo_limbs_root_rem); register_demo!(runner, demo_natural_floor_cbrt); register_demo!(runner, demo_natural_floor_cbrt_ref); register_demo!(runner, demo_natural_floor_cbrt_assign); register_demo!(runner, demo_natural_ceiling_cbrt); register_demo!(runner, demo_natural_ceiling_cbrt_ref); register_demo!(runner, demo_natural_ceiling_cbrt_assign); register_demo!(runner, demo_natural_checked_cbrt); register_demo!(runner, demo_natural_checked_cbrt_ref); register_demo!(runner, demo_natural_cbrt_rem); register_demo!(runner, demo_natural_cbrt_rem_ref); register_demo!(runner, demo_natural_cbrt_assign_rem); register_demo!(runner, demo_natural_floor_root); register_demo!(runner, demo_natural_floor_root_ref); register_demo!(runner, demo_natural_floor_root_assign); register_demo!(runner, demo_natural_ceiling_root); register_demo!(runner, demo_natural_ceiling_root_ref); register_demo!(runner, demo_natural_ceiling_root_assign); register_demo!(runner, demo_natural_checked_root); register_demo!(runner, demo_natural_checked_root_ref); register_demo!(runner, demo_natural_root_rem); register_demo!(runner, demo_natural_root_rem_ref); register_demo!(runner, demo_natural_root_assign_rem); register_bench!(runner, benchmark_limbs_floor_root); register_bench!(runner, benchmark_limbs_root_rem); register_bench!(runner, benchmark_natural_floor_cbrt_evaluation_strategy); register_bench!(runner, benchmark_natural_floor_cbrt_algorithms); register_bench!(runner, benchmark_natural_floor_cbrt_library_comparison); register_bench!(runner, benchmark_natural_floor_cbrt_assign); register_bench!(runner, benchmark_natural_ceiling_cbrt_evaluation_strategy); register_bench!(runner, benchmark_natural_ceiling_cbrt_algorithms); register_bench!(runner, benchmark_natural_ceiling_cbrt_assign); register_bench!(runner, benchmark_natural_checked_cbrt_evaluation_strategy); register_bench!(runner, benchmark_natural_checked_cbrt_algorithms); register_bench!(runner, benchmark_natural_cbrt_rem_evaluation_strategy); register_bench!(runner, benchmark_natural_cbrt_rem_algorithms); register_bench!(runner, benchmark_natural_cbrt_rem_library_comparison); register_bench!(runner, benchmark_natural_cbrt_assign_rem); register_bench!(runner, benchmark_natural_floor_root_evaluation_strategy); register_bench!(runner, benchmark_natural_floor_root_algorithms); register_bench!(runner, benchmark_natural_floor_root_library_comparison); register_bench!(runner, benchmark_natural_floor_root_assign); register_bench!(runner, benchmark_natural_ceiling_root_evaluation_strategy); register_bench!(runner, benchmark_natural_ceiling_root_algorithms); register_bench!(runner, benchmark_natural_ceiling_root_assign); register_bench!(runner, benchmark_natural_checked_root_evaluation_strategy); register_bench!(runner, benchmark_natural_checked_root_algorithms); register_bench!(runner, benchmark_natural_root_rem_evaluation_strategy); register_bench!(runner, benchmark_natural_root_rem_algorithms); register_bench!(runner, benchmark_natural_root_rem_library_comparison); register_bench!(runner, benchmark_natural_root_assign_rem); } fn demo_limbs_floor_root(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, exp) in unsigned_vec_unsigned_pair_gen_var_14() .get(gm, config) .take(limit) { println!( "limbs_root({:?}, {}) = {:?}", xs, exp, limbs_floor_root(&xs, exp) ); } } fn demo_limbs_root_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, exp) in unsigned_vec_unsigned_pair_gen_var_14() .get(gm, config) .take(limit) { println!( "limbs_root_rem({:?}, {}) = {:?}", xs, exp, limbs_root_rem(&xs, exp) ); } } fn demo_natural_floor_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.floor_root(3) = {}", x, x.clone().floor_root(3)); } } fn demo_natural_floor_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).floor_root(3) = {}", x, (&x).floor_root(3)); } } fn demo_natural_floor_cbrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.floor_root_assign(3); println!("x := {old_x}; x.floor_root_assign(3); x = {x}"); } } fn demo_natural_ceiling_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.ceiling_root(3) = {}", x, x.clone().ceiling_root(3)); } } fn demo_natural_ceiling_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).ceiling_root(3) = {}", x, (&x).ceiling_root(3)); } } fn demo_natural_ceiling_cbrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.ceiling_root_assign(3); println!("x := {old_x}; x.ceiling_root_assign(3); x = {x}"); } } fn demo_natural_checked_cbrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.checked_root(3) = {:?}", x, x.clone().checked_root(3)); } } fn demo_natural_checked_cbrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).checked_root(3) = {:?}", x, (&x).checked_root(3)); } } fn demo_natural_cbrt_rem(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.root_rem(3) = {:?}", x, x.clone().root_rem(3)); } } fn demo_natural_cbrt_rem_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).root_rem(3) = {:?}", x, (&x).root_rem(3)); } } fn demo_natural_cbrt_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); let rem = x.root_assign_rem(3); println!("x := {old_x}; x.root_assign_rem(3) = {rem}; x = {x}"); } } fn demo_natural_floor_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!("{}.floor_root({}) = {}", x, exp, x.clone().floor_root(exp)); } } fn demo_natural_floor_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!("(&{}).floor_root({}) = {}", x, exp, (&x).floor_root(exp)); } } fn demo_natural_floor_root_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { let old_x = x.clone(); x.floor_root_assign(exp); println!("x := {old_x}; x.floor_root_assign({exp}); x = {x}"); } } fn demo_natural_ceiling_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "{}.ceiling_root({}) = {}", x, exp, x.clone().ceiling_root(exp) ); } } fn demo_natural_ceiling_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "(&{}).ceiling_root({}) = {}", x, exp, (&x).ceiling_root(exp) ); } } fn demo_natural_ceiling_root_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { let old_x = x.clone(); x.ceiling_root_assign(exp); println!("x := {old_x}; x.ceiling_root_assign({exp}); x = {x}"); } } fn demo_natural_checked_root(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "{}.checked_root({}) = {:?}", x, exp, x.clone().checked_root(exp) ); } } fn demo_natural_checked_root_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "(&{}).checked_root({}) = {:?}", x, exp, (&x).checked_root(exp) ); } } fn demo_natural_root_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!("{}.root_rem({}) = {:?}", x, exp, x.clone().root_rem(exp)); } } fn demo_natural_root_rem_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!("(&{}).root_rem({}) = {:?}", x, exp, (&x).root_rem(exp)); } } fn demo_natural_root_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, exp) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { let old_x = x.clone(); let rem = x.root_assign_rem(exp); println!("x := {old_x}; x.root_assign_rem({exp}) = {rem}; x = {x}"); } } fn benchmark_limbs_floor_root(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_floor_root(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_14().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, exp)| { no_out!(limbs_floor_root(&xs, exp)); })], ); } fn benchmark_limbs_root_rem(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_root_rem(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_14().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, exp)| { no_out!(limbs_root_rem(&xs, exp)); })], ); } fn benchmark_natural_floor_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(3)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.floor_root(3)", &mut |x| no_out!(x.floor_root(3))), ("(&Natural).floor_root(3)", &mut |x| { no_out!((&x).floor_root(3)); }), ], ); } fn benchmark_natural_floor_cbrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(3)", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.floor_root(3))), ("binary", &mut |x| no_out!(floor_root_binary(&x, 3))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_floor_cbrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(3)", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("num", &mut |(x, _, _)| no_out!(x.nth_root(3))), ("rug", &mut |(_, x, _)| no_out!(x.root(3))), ("Malachite", &mut |(_, _, x)| no_out!(x.floor_root(3))), ], ); } fn benchmark_natural_floor_cbrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root_assign(3)", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.floor_root_assign(3))], ); } fn benchmark_natural_ceiling_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root(3)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.ceiling_root(3)", &mut |x| { no_out!(x.ceiling_root(3)); }), ("(&Natural).ceiling_root(3)", &mut |x| { no_out!((&x).ceiling_root(3)); }), ], ); } fn benchmark_natural_ceiling_cbrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root(3)", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.ceiling_root(3))), ("binary", &mut |x| no_out!(ceiling_root_binary(&x, 3))), ], ); } fn benchmark_natural_ceiling_cbrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root_assign(3)", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.ceiling_root_assign(3))], ); } fn benchmark_natural_checked_cbrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_root(3)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.checked_root(3)", &mut |x| { no_out!(x.checked_root(3)); }), ("(&Natural).checked_root(3)", &mut |x| { no_out!((&x).checked_root(3)); }), ], ); } fn benchmark_natural_checked_cbrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_root(3)", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.checked_root(3))), ("binary", &mut |x| no_out!(checked_root_binary(&x, 3))), ], ); } fn benchmark_natural_cbrt_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(3)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.root_rem(3)", &mut |x| no_out!(x.root_rem(3))), ("(&Natural).root_rem(3)", &mut |x| no_out!((&x).root_rem(3))), ], ); } #[allow(clippy::no_effect)] fn benchmark_natural_cbrt_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(3)", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.root_rem(3))), ("floor and subtraction", &mut |x| { let root = (&x).floor_root(3); let pow = (&root).pow(3); (root, x - pow); }), ("binary", &mut |x| no_out!(root_rem_binary(&x, 3))), ], ); } fn benchmark_natural_cbrt_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(3)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("x"), &mut [ ("rug", &mut |(x, _)| { no_out!(x.root_rem(rug::Integer::new(), 3)); }), ("Malachite", &mut |(_, x)| no_out!(x.root_rem(3))), ], ); } fn benchmark_natural_cbrt_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_assign_rem(3)", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| no_out!(x.root_assign_rem(3)))], ); } fn benchmark_natural_floor_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.floor_root()", &mut |(x, exp)| { no_out!(x.floor_root(exp)); }), ("(&Natural).floor_root()", &mut |(x, exp)| { no_out!((&x).floor_root(exp)); }), ], ); } fn benchmark_natural_floor_root_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, exp)| no_out!(x.floor_root(exp))), ("binary", &mut |(x, exp)| { no_out!(floor_root_binary(&x, exp)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_floor_root_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_7_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("num", &mut |((x, exp), _, _)| { no_out!(x.nth_root(u32::exact_from(exp))); }), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.root(u32::exact_from(exp))); }), ("Malachite", &mut |(_, _, (x, exp))| { no_out!(x.floor_root(exp)); }), ], ); } fn benchmark_natural_floor_root_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_root_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, exp)| x.floor_root_assign(exp))], ); } fn benchmark_natural_ceiling_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.ceiling_root()", &mut |(x, exp)| { no_out!(x.ceiling_root(exp)); }), ("(&Natural).ceiling_root()", &mut |(x, exp)| { no_out!((&x).ceiling_root(exp)); }), ], ); } fn benchmark_natural_ceiling_root_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, exp)| no_out!(x.ceiling_root(exp))), ("binary", &mut |(x, exp)| { no_out!(ceiling_root_binary(&x, exp)); }), ], ); } fn benchmark_natural_ceiling_root_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_root_assign(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, exp)| x.ceiling_root_assign(exp))], ); } fn benchmark_natural_checked_root_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_root(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.checked_root()", &mut |(x, exp)| { no_out!(x.checked_root(exp)); }), ("(&Natural).checked_root()", &mut |(x, exp)| { no_out!((&x).checked_root(exp)); }), ], ); } fn benchmark_natural_checked_root_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_root(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, exp)| no_out!(x.checked_root(exp))), ("binary", &mut |(x, exp)| { no_out!(checked_root_binary(&x, exp)); }), ], ); } fn benchmark_natural_root_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.root_rem()", &mut |(x, exp)| { no_out!(x.root_rem(exp)); }), ("(&Natural).root_rem()", &mut |(x, exp)| { no_out!((&x).root_rem(exp)); }), ], ); } #[allow(clippy::no_effect)] fn benchmark_natural_root_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, exp)| no_out!(x.root_rem(exp))), ("floor and subtraction", &mut |(x, exp)| { let root = (&x).floor_root(exp); let pow = (&root).pow(exp); (root, x - pow); }), ("binary", &mut |(x, exp)| no_out!(root_rem_binary(&x, exp))), ], ); } fn benchmark_natural_root_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_rem(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_7_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("rug", &mut |((x, exp), _)| { no_out!(x.root_rem(rug::Integer::new(), u32::exact_from(exp))); }), ("Malachite", &mut |(_, (x, exp))| no_out!(x.root_rem(exp))), ], ); } fn benchmark_natural_root_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.root_assign_rem(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(mut x, exp)| { no_out!(x.root_assign_rem(exp)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_natural_rounding_mode_triple_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_round_to_multiple_assign); register_demo!(runner, demo_natural_round_to_multiple_assign_ref); register_demo!(runner, demo_natural_round_to_multiple); register_demo!(runner, demo_natural_round_to_multiple_val_ref); register_demo!(runner, demo_natural_round_to_multiple_ref_val); register_demo!(runner, demo_natural_round_to_multiple_ref_ref); register_bench!( runner, benchmark_natural_round_to_multiple_assign_evaluation_strategy ); register_bench!( runner, benchmark_natural_round_to_multiple_evaluation_strategy ); } fn demo_natural_round_to_multiple_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.round_to_multiple_assign(y, rm); println!("x := {x_old}; x.round_to_multiple_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_natural_round_to_multiple_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.round_to_multiple_assign(&y, rm); println!("x := {x_old}; x.round_to_multiple_assign(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_natural_round_to_multiple(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.round_to_multiple({}, {}) = {:?}", x_old, y_old, rm, x.round_to_multiple(y, rm) ); } } fn demo_natural_round_to_multiple_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "{}.round_to_multiple(&{}, {}) = {:?}", x_old, y, rm, x.round_to_multiple(&y, rm) ); } } fn demo_natural_round_to_multiple_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).round_to_multiple({}, {}) = {:?}", x, y_old, rm, (&x).round_to_multiple(y, rm) ); } } fn demo_natural_round_to_multiple_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in natural_natural_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple(&{}, {}) = {:?}", x, y, rm, (&x).round_to_multiple(&y, rm) ); } } fn benchmark_natural_round_to_multiple_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.round_to_multiple_assign(Natural, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_natural_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [ ( "Natural.round_to_multiple_assign(Natural, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(y, rm)), ), ( "Natural.round_to_multiple_assign(&Natural, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(&y, rm)), ), ], ); } fn benchmark_natural_round_to_multiple_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.round_to_multiple(Natural, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_natural_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [ ( "Natural.round_to_multiple(Natural, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(y, rm)), ), ( "Natural.round_to_multiple(&Natural, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(&y, rm)), ), ( "(&Natural).round_to_multiple(Natural, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(y, rm)), ), ( "(&Natural).round_to_multiple(&Natural, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(&y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, ShrRound, }; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_20, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::round_to_multiple_of_power_of_2::*; use malachite_nz::test_util::bench::bucketers::triple_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_rounding_mode_triple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_round_to_multiple_of_power_of_2_down); register_demo!(runner, demo_limbs_round_to_multiple_of_power_of_2_up); register_demo!(runner, demo_limbs_round_to_multiple_of_power_of_2_nearest); register_demo!(runner, demo_limbs_round_to_multiple_of_power_of_2); register_demo!( runner, demo_limbs_round_to_multiple_of_power_of_2_down_in_place ); register_demo!( runner, demo_limbs_round_to_multiple_of_power_of_2_up_in_place ); register_demo!( runner, demo_limbs_round_to_multiple_of_power_of_2_nearest_in_place ); register_demo!(runner, demo_limbs_round_to_multiple_of_power_of_2_in_place); register_demo!(runner, demo_natural_round_to_multiple_of_power_of_2_assign); register_demo!(runner, demo_natural_round_to_multiple_of_power_of_2); register_demo!(runner, demo_natural_round_to_multiple_of_power_of_2_ref); register_bench!(runner, benchmark_limbs_round_to_multiple_of_power_of_2_down); register_bench!(runner, benchmark_limbs_round_to_multiple_of_power_of_2_up); register_bench!( runner, benchmark_limbs_round_to_multiple_of_power_of_2_nearest ); register_bench!(runner, benchmark_limbs_round_to_multiple_of_power_of_2); register_bench!( runner, benchmark_limbs_round_to_multiple_of_power_of_2_down_in_place ); register_bench!( runner, benchmark_limbs_round_to_multiple_of_power_of_2_up_in_place ); register_bench!( runner, benchmark_limbs_round_to_multiple_of_power_of_2_nearest_in_place ); register_bench!( runner, benchmark_limbs_round_to_multiple_of_power_of_2_in_place ); register_bench!( runner, benchmark_natural_round_to_multiple_of_power_of_2_assign ); register_bench!( runner, benchmark_natural_round_to_multiple_of_power_of_2_algorithms ); register_bench!( runner, benchmark_natural_round_to_multiple_of_power_of_2_evaluation_strategy ); } fn demo_limbs_round_to_multiple_of_power_of_2_down(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_round_to_multiple_of_power_of_2_down({:?}, {}) = {:?}", xs, pow, limbs_round_to_multiple_of_power_of_2_down(&xs, pow) ); } } fn demo_limbs_round_to_multiple_of_power_of_2_up(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_round_to_multiple_of_power_of_2_up({:?}, {}) = {:?}", xs, pow, limbs_round_to_multiple_of_power_of_2_up(&xs, pow) ); } } fn demo_limbs_round_to_multiple_of_power_of_2_nearest( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_round_to_multiple_of_power_of_2_nearest({:?}, {}) = {:?}", xs, pow, limbs_round_to_multiple_of_power_of_2_nearest(&xs, pow) ); } } fn demo_limbs_round_to_multiple_of_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, pow, rm) in unsigned_vec_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "limbs_round_to_multiple_of_power_of_2({:?}, {}, {}) = {:?}", xs, pow, rm, limbs_round_to_multiple_of_power_of_2(&xs, pow, rm) ); } } fn demo_limbs_round_to_multiple_of_power_of_2_down_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let o = limbs_round_to_multiple_of_power_of_2_down_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; \ limbs_round_to_multiple_of_power_of_2_down_in_place(&mut xs, {pow}) = {o:?}; \ xs = {xs:?}", ); } } fn demo_limbs_round_to_multiple_of_power_of_2_up_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let o = limbs_round_to_multiple_of_power_of_2_up_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; \ limbs_round_to_multiple_of_power_of_2_up_in_place(&mut xs, {pow}) = {o:?}; \ xs = {xs:?}", ); } } fn demo_limbs_round_to_multiple_of_power_of_2_nearest_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, pow) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let o = limbs_round_to_multiple_of_power_of_2_nearest_in_place(&mut xs, pow); println!( "xs := {xs_old:?}; \ limbs_round_to_multiple_of_power_of_2_nearest_in_place(&mut xs, {pow}) = {o:?}; \ xs = {xs:?}", ); } } fn demo_limbs_round_to_multiple_of_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, pow, rm) in unsigned_vec_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let oo = limbs_round_to_multiple_of_power_of_2_in_place(&mut xs, pow, rm); println!( "xs := {xs_old:?}; \ limbs_round_to_multiple_of_power_of_2_in_place(&mut xs, {pow}, {rm}) = {oo:?}; \ xs = {xs:?}", ); } } fn demo_natural_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow, rm) in natural_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.round_to_multiple_of_power_of_2_assign(pow, rm); println!( "x := {n_old}; x.round_to_multiple_of_power_of_2_assign({pow}, {rm}) = {o:?}; x = {n}" ); } } fn demo_natural_round_to_multiple_of_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow, rm) in natural_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.round_to_multiple_of_power_of_2({}, {}) = {:?}", n_old, pow, rm, n.round_to_multiple_of_power_of_2(pow, rm) ); } } fn demo_natural_round_to_multiple_of_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow, rm) in natural_unsigned_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple_of_power_of_2({}, {}) = {:?}", n, pow, rm, (&n).round_to_multiple_of_power_of_2(pow, rm) ); } } fn benchmark_limbs_round_to_multiple_of_power_of_2_down( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_down(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_down(&xs, pow)); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_up( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_up(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_up(&xs, pow)); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_nearest( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_nearest(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_nearest(&xs, pow)); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2(&[Limb], u64, RoundingMode)", BenchmarkType::Single, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, pow, rm)| { no_out!(limbs_round_to_multiple_of_power_of_2(&xs, pow, rm)); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_down_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_down_in_place(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_down_in_place( &mut xs, pow )); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_up_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_up_in_place(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_up_in_place( &mut xs, pow )); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_nearest_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_nearest_in_place(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, pow)| { no_out!(limbs_round_to_multiple_of_power_of_2_nearest_in_place( &mut xs, pow )); })], ); } fn benchmark_limbs_round_to_multiple_of_power_of_2_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_round_to_multiple_of_power_of_2_in_place(&mut Vec, u64, RoundingMode)", BenchmarkType::Single, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, pow, rm)| { no_out!(limbs_round_to_multiple_of_power_of_2_in_place( &mut xs, pow, rm )); })], ); } fn benchmark_natural_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.round_to_multiple_of_power_of_2_assign(u64, RoundingMode)", BenchmarkType::Single, natural_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2_assign(y, rm)); })], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_round_to_multiple_of_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::Algorithms, natural_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2(y, rm)); }), ("using shr_round", &mut |(x, y, rm)| { no_out!(x.shr_round(y, rm).0 << y); }), ("using round_to_multiple", &mut |(x, y, rm)| { no_out!(x.round_to_multiple(Natural::power_of_2(y), rm)); }), ], ); } fn benchmark_natural_round_to_multiple_of_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, natural_unsigned_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( "Natural.round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple_of_power_of_2(y, rm)), ), ( "(&Natural).round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple_of_power_of_2(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{SaturatingSub, SaturatingSubAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_saturating_sub); register_demo!(runner, demo_natural_saturating_sub_val_ref); register_demo!(runner, demo_natural_saturating_sub_ref_val); register_demo!(runner, demo_natural_saturating_sub_ref_ref); register_demo!(runner, demo_natural_saturating_sub_assign); register_demo!(runner, demo_natural_saturating_sub_assign_ref); register_bench!( runner, benchmark_natural_saturating_sub_assign_evaluation_strategy ); register_bench!(runner, benchmark_natural_saturating_sub_evaluation_strategy); } fn demo_natural_saturating_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.saturating_sub({}) = {:?}", x_old, y_old, x.saturating_sub(y) ); } } fn demo_natural_saturating_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.saturating_sub(&{}) = {:?}", x_old, y, x.saturating_sub(&y) ); } } fn demo_natural_saturating_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).saturating_sub({}) = {:?}", x, y_old, (&x).saturating_sub(y) ); } } fn demo_natural_saturating_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!( "(&{}).saturating_sub(&{}) = {:?}", x, y, (&x).saturating_sub(&y) ); } } fn demo_natural_saturating_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.saturating_sub_assign(y); println!("x := {x_old}; x.saturating_sub_assign({y_old}); x = {x}"); } } fn demo_natural_saturating_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.saturating_sub_assign(&y); println!("x := {x_old}; x.saturating_sub_assign(&{y}); x = {x}"); } } fn benchmark_natural_saturating_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_assign(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ( "Natural.saturating_sub_assign(Natural)", &mut |(mut x, y)| x.saturating_sub_assign(y), ), ( "Natural.saturating_sub_assign(&Natural)", &mut |(mut x, y)| x.saturating_sub_assign(&y), ), ], ); } fn benchmark_natural_saturating_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub(Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural.saturating_sub(Natural)", &mut |(x, y)| { no_out!(x.saturating_sub(y)); }), ("Natural.saturating_sub(&Natural)", &mut |(x, y)| { no_out!(x.saturating_sub(&y)); }), ("&Natural.saturating_sub(Natural)", &mut |(x, y)| { no_out!((&x).saturating_sub(y)); }), ("&Natural.saturating_sub(&Natural)", &mut |(x, y)| { no_out!((&x).saturating_sub(&y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ SaturatingSub, SaturatingSubAssign, SaturatingSubMul, SaturatingSubMulAssign, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_saturating_sub_mul); register_demo!(runner, demo_natural_saturating_sub_mul_val_val_ref); register_demo!(runner, demo_natural_saturating_sub_mul_val_ref_val); register_demo!(runner, demo_natural_saturating_sub_mul_val_ref_ref); register_demo!(runner, demo_natural_saturating_sub_mul_ref_ref_ref); register_demo!(runner, demo_natural_saturating_sub_mul_assign); register_demo!(runner, demo_natural_saturating_sub_mul_assign_val_ref); register_demo!(runner, demo_natural_saturating_sub_mul_assign_ref_val); register_demo!(runner, demo_natural_saturating_sub_mul_assign_ref_ref); register_bench!( runner, benchmark_natural_saturating_sub_mul_evaluation_strategy ); register_bench!(runner, benchmark_natural_saturating_sub_mul_algorithms); register_bench!( runner, benchmark_natural_saturating_sub_mul_val_val_ref_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_val_ref_val_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_val_ref_ref_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_ref_ref_ref_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_assign_evaluation_strategy ); register_bench!( runner, benchmark_natural_saturating_sub_mul_assign_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_assign_val_ref_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_assign_ref_val_algorithms ); register_bench!( runner, benchmark_natural_saturating_sub_mul_assign_ref_ref_algorithms ); } fn demo_natural_saturating_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); println!( "{}.saturating_sub_mul({}, {}) = {}", x_old, y_old, z_old, x.saturating_sub_mul(y, z) ); } } fn demo_natural_saturating_sub_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "{}.saturating_sub_mul({}, &({})) = {}", x_old, y_old, z, x.saturating_sub_mul(y, &z) ); } } fn demo_natural_saturating_sub_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); println!( "{}.saturating_sub_mul(&({}), {}) = {}", x_old, y, z_old, x.saturating_sub_mul(&y, z) ); } } fn demo_natural_saturating_sub_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!( "{}.saturating_sub_mul(&({}), &({})) = {}", x_old, y, z, x.saturating_sub_mul(&y, &z) ); } } fn demo_natural_saturating_sub_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, z) in natural_triple_gen().get(gm, config).take(limit) { println!( "(&{}).saturating_sub_mul(&({}), &({})) = {}", x, y, z, (&x).saturating_sub_mul(&y, &z) ); } } fn demo_natural_saturating_sub_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); let z_old = z.clone(); x.saturating_sub_mul_assign(y, z); println!("x := {x_old}; x.saturating_sub_mul_assign({y_old}, {z_old}); x = {x}"); } } fn demo_natural_saturating_sub_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.saturating_sub_mul_assign(y, &z); println!("x := {x_old}; x.saturating_sub_mul_assign({y_old}, &({z})); x = {x}"); } } fn demo_natural_saturating_sub_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); let z_old = z.clone(); x.saturating_sub_mul_assign(&y, z); println!("x := {x_old}; x.saturating_sub_mul_assign(&({y}), {z_old}); x = {x}"); } } fn demo_natural_saturating_sub_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, z) in natural_triple_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.saturating_sub_mul_assign(&y, &z); println!("x := {x_old}; x.saturating_sub_mul_assign(&({y}), &({z})); x = {x}"); } } fn benchmark_natural_saturating_sub_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul(Natural, Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(b, c)), ), ( "Natural.saturating_sub_mul(Natural, &Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(b, &c)), ), ( "Natural.saturating_sub_mul(&Natural, Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(&b, c)), ), ( "Natural.saturating_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(&b, &c)), ), ( "(&Natural).saturating_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).saturating_sub_mul(&b, &c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul(Natural, Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(b, c)), ), ( "Natural.saturating_sub(Natural * Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub(b * c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul(Natural, &Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(b, &c)), ), ( "Natural.saturating_sub(Natural * &Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub(b * &c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(&Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul(&Natural, Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(&b, c)), ), ( "Natural.saturating_sub(&Natural * Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub(&b * c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub_mul(&b, &c)), ), ( "Natural.saturating_sub(Natural * Natural)", &mut |(a, b, c)| no_out!(a.saturating_sub(&b * &c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "(&Natural).saturating_sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).saturating_sub_mul(&b, &c)), ), ( "(&Natural).saturating_sub(Natural * Natural)", &mut |(a, b, c)| no_out!((&a).saturating_sub(&b * &c)), ), ], ); } fn benchmark_natural_saturating_sub_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(b, c), ), ( "Natural.saturating_sub_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(b, &c), ), ( "Natural.saturating_sub_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(&b, c), ), ( "Natural.saturating_sub_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(&b, &c), ), ], ); } fn benchmark_natural_saturating_sub_mul_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul_assign(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(b, c), ), ( "Natural.saturating_sub_assign(Natural * Natural)", &mut |(mut a, b, c)| a.saturating_sub_assign(b * c), ), ], ); } fn benchmark_natural_saturating_sub_mul_assign_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul_assign(Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(b, &c), ), ( "Natural.saturating_sub_assign(Natural * &Natural)", &mut |(mut a, b, c)| a.saturating_sub_assign(b * &c), ), ], ); } fn benchmark_natural_saturating_sub_mul_assign_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul_assign(&Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(&b, c), ), ( "Natural.saturating_sub_assign(&Natural * Natural)", &mut |(mut a, b, c)| a.saturating_sub_assign(&b * c), ), ], ); } fn benchmark_natural_saturating_sub_mul_assign_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.saturating_sub_mul_assign(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("x", "y", "z"), &mut [ ( "Natural.saturating_sub_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.saturating_sub_mul_assign(&b, &c), ), ( "Natural.saturating_sub_assign(&Natural * &Natural)", &mut |(mut a, b, c)| a.saturating_sub_assign(&b * &c), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_32, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shl::{ limbs_shl, limbs_shl_to_out, limbs_shl_with_complement_to_out, limbs_slice_shl_in_place, limbs_vec_shl_in_place, }; use malachite_nz::natural::logic::not::limbs_not_in_place; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_signed_pair_gen_var_2, natural_signed_pair_gen_var_2_rm, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_rm, }; use std::ops::{Shl, ShlAssign}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_shl); register_demo!(runner, demo_limbs_shl_to_out); register_demo!(runner, demo_limbs_slice_shl_in_place); register_demo!(runner, demo_limbs_vec_shl_in_place); register_demo!(runner, demo_limbs_shl_with_complement_to_out); register_unsigned_demos!(runner, demo_natural_shl_assign_unsigned); register_unsigned_demos!(runner, demo_natural_shl_unsigned); register_unsigned_demos!(runner, demo_natural_shl_unsigned_ref); register_signed_demos!(runner, demo_natural_shl_assign_signed); register_signed_demos!(runner, demo_natural_shl_signed); register_signed_demos!(runner, demo_natural_shl_signed_ref); register_bench!(runner, benchmark_limbs_shl); register_bench!(runner, benchmark_limbs_shl_to_out); register_bench!(runner, benchmark_limbs_slice_shl_in_place); register_bench!(runner, benchmark_limbs_vec_shl_in_place); register_bench!( runner, benchmark_limbs_shl_with_complement_to_out_algorithms ); register_bench!(runner, benchmark_natural_shl_assign_u32_library_comparison); register_bench!(runner, benchmark_natural_shl_u32_library_comparison); register_bench!(runner, benchmark_natural_shl_assign_i32_library_comparison); register_bench!(runner, benchmark_natural_shl_i32_library_comparison); register_unsigned_benches!(runner, benchmark_natural_shl_assign_unsigned); register_unsigned_benches!(runner, benchmark_natural_shl_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_natural_shl_assign_signed); register_signed_benches!(runner, benchmark_natural_shl_signed_evaluation_strategy); } fn demo_limbs_shl(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!("limbs_shl({:?}, {}) = {:?}", xs, bits, limbs_shl(&xs, bits)); } } fn demo_limbs_shl_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, bits) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22::() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_shl_to_out(&mut out, &xs, bits); println!( "out := {out_old:?}; \ limbs_shl_to_out(&mut out, {xs:?}, {bits}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_shl_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_32::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_shl_in_place(&mut xs, bits); println!( "xs := {xs_old:?}; limbs_slice_shl_in_place(&mut xs, {bits}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_shl_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_16::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_shl_in_place(&mut xs, bits); println!("xs := {xs_old:?}; limbs_vec_shl_in_place(&mut xs, {bits}); xs = {xs:?}"); } } fn demo_limbs_shl_with_complement_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, bits) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::() .get(gm, config) .take(limit) { let out_old = out.clone(); let carry = limbs_shl_with_complement_to_out(&mut out, &xs, bits); println!( "out := {out_old:?}; \ limbs_shl_with_complement_to_out(&mut out, {xs:?}, {bits}) = {carry}; out = {out:?}", ); } } fn demo_natural_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ShlAssign, { for (mut n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= u; println!("x := {n_old}; x <<= {u}; x = {n}"); } } fn demo_natural_shl_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shl, { for (n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, u, n << u); } } fn demo_natural_shl_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: Shl, { for (n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, u, &n << u); } } fn demo_natural_shl_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ShlAssign, { for (mut n, i) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= i; println!("x := {n_old}; x <<= {i}; x = {n}"); } } fn demo_natural_shl_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shl, { for (n, i) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, i, n << i); } } fn demo_natural_shl_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Natural: Shl, { for (n, i) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, i, &n << i); } } fn benchmark_limbs_shl(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shl(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits)| no_out!(limbs_shl(&xs, bits)))], ); } fn benchmark_limbs_shl_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shl_to_out(&mut [Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22::().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, bits)| { no_out!(limbs_shl_to_out(&mut out, &xs, bits)); })], ); } fn benchmark_limbs_slice_shl_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_shl_in_place(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_32::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { no_out!(limbs_slice_shl_in_place(&mut xs, bits)); })], ); } fn benchmark_limbs_vec_shl_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shl_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { limbs_vec_shl_in_place(&mut xs, bits); })], ); } fn benchmark_limbs_shl_with_complement_to_out_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_shl_with_complement_to_out(&mut [Limb], &[Limb], u64)", BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut out, xs, bits)| { no_out!(limbs_shl_with_complement_to_out(&mut out, &xs, bits)); }), ( "limbs_shl_to_out and limbs_not_in_place", &mut |(mut out, xs, bits)| { limbs_shl_to_out(&mut out, &xs, bits); limbs_not_in_place(&mut out); }, ), ], ); } fn benchmark_natural_shl_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural <<= u32", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_shl_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural << u32", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } fn benchmark_natural_shl_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural <<= u32", BenchmarkType::LibraryComparison, natural_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_shl_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural << i32", BenchmarkType::LibraryComparison, natural_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } fn benchmark_natural_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShlAssign, { run_benchmark( &format!("Natural <<= {}", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x <<= y))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl, for<'a> &'a Natural: Shl, { run_benchmark( &format!("Natural << {}", T::NAME), BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ (&format!("Natural << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Natural << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } fn benchmark_natural_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShlAssign, { run_benchmark( &format!("Natural <<= {}", T::NAME), BenchmarkType::Single, natural_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x <<= y))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl, for<'a> &'a Natural: Shl, { run_benchmark( &format!("Natural << {}", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ (&format!("Natural << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Natural << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShlRound, ShlRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::triple_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_signed_rounding_mode_triple_gen_var_1; use std::ops::Shr; pub(crate) fn register(runner: &mut Runner) { register_signed_demos!(runner, demo_natural_shl_round_assign); register_signed_demos!(runner, demo_natural_shl_round); register_signed_demos!(runner, demo_natural_shl_round_ref); register_signed_benches!(runner, benchmark_natural_shl_round_assign); register_signed_benches!(runner, benchmark_natural_shl_round_evaluation_strategy); } fn demo_natural_shl_round_assign(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ShlRoundAssign + Shr, { for (mut n, i, rm) in natural_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shl_round_assign(i, rm); println!("x := {n_old}; x.shl_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_natural_shl_round(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ShlRound + Shr, { for (n, i, rm) in natural_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shl_round({}, {}) = {:?}", n_old, i, rm, n.shl_round(i, rm) ); } } fn demo_natural_shl_round_ref(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shr, for<'a> &'a Natural: ShlRound, { for (n, i, rm) in natural_signed_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).shl_round({}, {}) = {:?}", n, i, rm, (&n).shl_round(i, rm) ); } } fn benchmark_natural_shl_round_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShlRoundAssign + Shr, { run_benchmark( &format!("Natural.shl_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, natural_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shl_round_assign(y, rm)); })], ); } fn benchmark_natural_shl_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShlRound + Shr, for<'a> &'a Natural: ShlRound, { run_benchmark( &format!("Natural.shl_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( &format!("Natural.shl_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shl_round(y, rm)), ), ( &format!("(&Natural).shl_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shl_round(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_33, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shr::{ limbs_shr, limbs_shr_to_out, limbs_slice_shr_in_place, limbs_vec_shr_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, pair_2_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_signed_pair_gen_var_2, natural_signed_pair_gen_var_2_rm, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_rm, }; use std::ops::{Shr, ShrAssign}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_shr); register_demo!(runner, demo_limbs_shr_to_out); register_demo!(runner, demo_limbs_slice_shr_in_place); register_demo!(runner, demo_limbs_vec_shr_in_place); register_unsigned_demos!(runner, demo_natural_shr_assign_unsigned); register_unsigned_demos!(runner, demo_natural_shr_unsigned); register_unsigned_demos!(runner, demo_natural_shr_unsigned_ref); register_signed_demos!(runner, demo_natural_shr_assign_signed); register_signed_demos!(runner, demo_natural_shr_signed); register_signed_demos!(runner, demo_natural_shr_signed_ref); register_bench!(runner, benchmark_limbs_shr); register_bench!(runner, benchmark_limbs_shr_to_out); register_bench!(runner, benchmark_limbs_slice_shr_in_place); register_bench!(runner, benchmark_limbs_vec_shr_in_place); register_bench!(runner, benchmark_natural_shr_assign_u32_library_comparison); register_bench!(runner, benchmark_natural_shr_u32_library_comparison); register_bench!(runner, benchmark_natural_shr_assign_i32_library_comparison); register_bench!(runner, benchmark_natural_shr_i32_library_comparison); register_unsigned_benches!(runner, benchmark_natural_shr_assign_unsigned); register_unsigned_benches!(runner, benchmark_natural_shr_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_natural_shr_assign_signed); register_signed_benches!(runner, benchmark_natural_shr_signed_evaluation_strategy); } fn demo_limbs_shr(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!("limbs_shr({:?}, {}) = {:?}", xs, bits, limbs_shr(&xs, bits)); } } fn demo_limbs_shr_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (out, xs, bits) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::() .get(gm, config) .take(limit) { let mut out = out.to_vec(); let out_old = out.clone(); let carry = limbs_shr_to_out(&mut out, &xs, bits); println!( "out := {out_old:?}; \ limbs_shr_to_out(&mut out, {xs:?}, {bits}) = {carry}; out = {out:?}", ); } } fn demo_limbs_slice_shr_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_33::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let carry = limbs_slice_shr_in_place(&mut xs, bits); println!( "xs := {xs_old:?}; limbs_slice_shr_in_place(&mut xs, {bits}) = {carry}; xs = {xs:?}", ); } } fn demo_limbs_vec_shr_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_vec_shr_in_place(&mut xs, bits); println!("xs := {xs_old:?}; limbs_vec_shr_in_place(&mut xs, {bits}); xs = {xs:?}"); } } fn demo_natural_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ShrAssign, { for (mut n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!("x := {n_old}; x >>= {u}; x = {n}"); } } fn demo_natural_shr_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shr, { for (n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_natural_shr_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: Shr, { for (n, u) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, u, &n >> u); } } fn demo_natural_shr_assign_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ShrAssign, { for (mut n, u) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!("x := {n_old}; x >>= {u}; x = {n}"); } } fn demo_natural_shr_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shr, { for (n, u) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_natural_shr_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Natural: Shr, { for (n, u) in natural_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, u, &n >> u); } } fn benchmark_limbs_shr(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shr(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits)| no_out!(limbs_shr(&xs, bits)))], ); } fn benchmark_limbs_shr_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shr_to_out(&mut [Limb], &[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, bits)| { no_out!(limbs_shr_to_out(&mut out, &xs, bits)); })], ); } fn benchmark_limbs_slice_shr_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_shr_in_place(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_33::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { no_out!(limbs_slice_shr_in_place(&mut xs, bits)); })], ); } fn benchmark_limbs_vec_shr_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shr_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { limbs_vec_shr_in_place(&mut xs, bits); })], ); } fn benchmark_natural_shr_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural >>= u32", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_shr_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural >> u32", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } fn benchmark_natural_shr_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural >>= u32", BenchmarkType::LibraryComparison, natural_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_shr_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural >> i32", BenchmarkType::LibraryComparison, natural_signed_pair_gen_var_2_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } fn benchmark_natural_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShrAssign, { run_benchmark( &format!("Natural >>= {}", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x >>= y))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_shr_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shr, for<'a> &'a Natural: Shr, { run_benchmark( &format!("Natural >> {}", T::NAME), BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ (&format!("Natural >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Natural >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } fn benchmark_natural_shr_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ShrAssign, { run_benchmark( &format!("Natural >>= {}", T::NAME), BenchmarkType::Single, natural_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y)| no_out!(x >>= y))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_shr_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shr, for<'a> &'a Natural: Shr, { run_benchmark( &format!("Natural >> {}", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ (&format!("Natural >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Natural >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, triple_1_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_20, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shr_round::{ limbs_shr_exact, limbs_shr_round, limbs_shr_round_nearest, limbs_shr_round_up, limbs_vec_shr_exact_in_place, limbs_vec_shr_round_in_place, limbs_vec_shr_round_nearest_in_place, limbs_vec_shr_round_up_in_place, }; use malachite_nz::test_util::bench::bucketers::triple_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{ natural_signed_rounding_mode_triple_gen_var_2, natural_unsigned_rounding_mode_triple_gen_var_1, }; use std::ops::Shl; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_shr_round_up); register_demo!(runner, demo_limbs_shr_round_nearest); register_demo!(runner, demo_limbs_shr_exact); register_demo!(runner, demo_limbs_shr_round); register_demo!(runner, demo_limbs_vec_shr_round_up_in_place); register_demo!(runner, demo_limbs_vec_shr_round_nearest_in_place); register_demo!(runner, demo_limbs_vec_shr_exact_in_place); register_demo!(runner, demo_limbs_vec_shr_round_in_place); register_unsigned_demos!(runner, demo_natural_shr_round_assign_unsigned); register_unsigned_demos!(runner, demo_natural_shr_round_unsigned); register_unsigned_demos!(runner, demo_natural_shr_round_unsigned_ref); register_signed_demos!(runner, demo_natural_shr_round_assign_signed); register_signed_demos!(runner, demo_natural_shr_round_signed); register_signed_demos!(runner, demo_natural_shr_round_signed_ref); register_bench!(runner, benchmark_limbs_shr_round_up); register_bench!(runner, benchmark_limbs_shr_round_nearest); register_bench!(runner, benchmark_limbs_shr_exact); register_bench!(runner, benchmark_limbs_shr_round); register_bench!(runner, benchmark_limbs_vec_shr_round_up_in_place); register_bench!(runner, benchmark_limbs_vec_shr_round_nearest_in_place); register_bench!(runner, benchmark_limbs_vec_shr_exact_in_place); register_bench!(runner, benchmark_limbs_vec_shr_round_in_place); register_unsigned_benches!(runner, benchmark_natural_shr_round_assign_unsigned); register_unsigned_benches!( runner, benchmark_natural_shr_round_unsigned_evaluation_strategy ); register_signed_benches!(runner, benchmark_natural_shr_round_assign_signed); register_signed_benches!( runner, benchmark_natural_shr_round_signed_evaluation_strategy ); } fn demo_limbs_shr_round_up(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_shr_round_up({:?}, {}) = {:?}", xs, bits, limbs_shr_round_up(&xs, bits) ); } } fn demo_limbs_shr_round_nearest(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_shr_round_nearest({:?}, {}) = {:?}", xs, bits, limbs_shr_round_nearest(&xs, bits) ); } } fn demo_limbs_shr_exact(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { println!( "limbs_shr_exact({:?}, {}) = {:?}", xs, bits, limbs_shr_exact(&xs, bits) ); } } fn demo_limbs_shr_round(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, bits, rm) in unsigned_vec_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { println!( "limbs_shr_round({:?}, {}, {}) = {:?}", xs, bits, rm, limbs_shr_round(&xs, bits, rm) ); } } fn demo_limbs_vec_shr_round_up_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let o = limbs_vec_shr_round_up_in_place(&mut xs, bits); println!( "xs := {xs_old:?}; \ limbs_vec_shr_round_up_in_place(&mut xs, {bits}) = {o:?}; xs = {xs:?}", ); } } fn demo_limbs_vec_shr_round_nearest_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let o = limbs_vec_shr_round_nearest_in_place(&mut xs, bits); println!( "limbs := {xs_old:?}; \ limbs_vec_shr_round_nearest_in_place(&mut limbs, {bits}) = {o:?}; limbs = {xs:?}", ); } } fn demo_limbs_vec_shr_exact_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits) in unsigned_vec_unsigned_pair_gen_var_20() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let result = limbs_vec_shr_exact_in_place(&mut xs, bits); println!( "xs := {xs_old:?}; \ limbs_vec_shr_exact_in_place(&mut xs, {bits}) = {result}; xs = {xs:?}", ); } } fn demo_limbs_vec_shr_round_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, bits, rm) in unsigned_vec_unsigned_rounding_mode_triple_gen_var_2() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let result = limbs_vec_shr_round_in_place(&mut xs, bits, rm); println!( "xs := {xs_old:?}; \ limbs_vec_shr_round_in_place(&mut xs, {bits}, {rm}) = {result:?}; xs = {xs:?}", ); } } fn demo_natural_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: Shl + ShrRoundAssign, { for (mut n, u, rm) in natural_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(u, rm); println!("x := {n_old}; x.shr_round_assign({u}, {rm}) = {o:?}; x = {n}"); } } fn demo_natural_shr_round_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: Shl + ShrRound, { for (n, u, rm) in natural_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, u, rm, n.shr_round(u, rm) ); } } fn demo_natural_shr_round_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: Shl, for<'a> &'a Natural: ShrRound, { for (n, u, rm) in natural_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, u, rm, (&n).shr_round(u, rm) ); } } fn demo_natural_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: Shl + ShrRoundAssign, { for (mut n, i, rm) in natural_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.shr_round_assign(i, rm); println!("x := {n_old}; x.shr_round_assign({i}, {rm}) = {o:?}; x = {n}"); } } fn demo_natural_shr_round_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Shl + ShrRound, { for (n, i, rm) in natural_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "{}.shr_round({}, {}) = {:?}", n_old, i, rm, n.shr_round(i, rm) ); } } fn demo_natural_shr_round_signed_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: Shl, for<'a> &'a Natural: ShrRound, { for (n, i, rm) in natural_signed_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "(&{}).shr_round({}, {}) = {:?}", n, i, rm, (&n).shr_round(i, rm) ); } } fn benchmark_limbs_shr_round_up(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shr_round_up(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits)| { no_out!(limbs_shr_round_up(&xs, bits)); })], ); } fn benchmark_limbs_shr_round_nearest( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_shr_round_nearest(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits)| { no_out!(limbs_shr_round_nearest(&xs, bits)); })], ); } fn benchmark_limbs_shr_exact(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shr_exact(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits)| { no_out!(limbs_shr_exact(&xs, bits)); })], ); } fn benchmark_limbs_shr_round(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_shr_round(&[Limb], u64, RoundingMode)", BenchmarkType::Single, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, bits, rm)| { no_out!(limbs_shr_round(&xs, bits, rm)); })], ); } fn benchmark_limbs_vec_shr_round_up_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shr_round_up_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { no_out!(limbs_vec_shr_round_up_in_place(&mut xs, bits)); })], ); } fn benchmark_limbs_vec_shr_round_nearest_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shr_round_nearest_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { no_out!(limbs_vec_shr_round_nearest_in_place(&mut xs, bits)); })], ); } fn benchmark_limbs_vec_shr_exact_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shr_exact_in_place(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_20().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits)| { no_out!(limbs_vec_shr_exact_in_place(&mut xs, bits)); })], ); } fn benchmark_limbs_vec_shr_round_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_shr_round_in_place(&mut Vec, u64, RoundingMode)", BenchmarkType::Single, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, bits, rm)| { no_out!(limbs_vec_shr_round_in_place(&mut xs, bits, rm)); })], ); } fn benchmark_natural_shr_round_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl + ShrRoundAssign, { run_benchmark( &format!("Natural.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, natural_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shr_round_assign(y, rm)); })], ); } fn benchmark_natural_shr_round_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl + ShrRound, for<'a> &'a Natural: ShrRound, { run_benchmark( &format!("Natural.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, natural_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( &format!("Natural.shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shr_round(y, rm)), ), ( &format!("(&Natural).shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shr_round(y, rm)), ), ], ); } fn benchmark_natural_shr_round_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl + ShrRoundAssign, { run_benchmark( &format!("Natural.shr_round_assign({}, RoundingMode)", T::NAME), BenchmarkType::Single, natural_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.shr_round_assign(y, rm)); })], ); } fn benchmark_natural_shr_round_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Shl + ShrRound, for<'a> &'a Natural: ShrRound, { run_benchmark( &format!("Natural.shr_round({}, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, natural_signed_rounding_mode_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( &format!("Natural.shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!(x.shr_round(y, rm)), ), ( &format!("(&Natural).shr_round({}, RoundingMode)", T::NAME), &mut |(x, y, rm)| no_out!((&x).shr_round(y, rm)), ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_2_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_sign); register_bench!(runner, benchmark_natural_sign_library_comparison); } fn demo_natural_sign(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { match n.sign() { Less => println!("{n} is negative"), Equal => println!("{n} is zero"), Greater => println!("{n} is positive"), } } } fn benchmark_natural_sign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sign()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.sign())), ("rug", &mut |(n, _)| no_out!(n.cmp0())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::sqrt::sqrt_rem_2_newton; use malachite_base::num::arithmetic::traits::{ CeilingSqrt, CeilingSqrtAssign, CheckedSqrt, FloorSqrt, FloorSqrtAssign, SqrtAssignRem, SqrtRem, Square, }; use malachite_base::test_util::bench::bucketers::{ pair_2_vec_len_bucketer, pair_max_bit_bucketer, quadruple_2_vec_len_bucketer, triple_3_vec_len_bucketer, vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ large_type_gen_var_2, unsigned_pair_gen_var_31, unsigned_vec_gen_var_1, unsigned_vec_pair_gen_var_4, unsigned_vec_pair_gen_var_5, unsigned_vec_triple_gen_var_28, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::sqrt::{ limbs_ceiling_sqrt, limbs_checked_sqrt, limbs_floor_sqrt, limbs_sqrt_helper, limbs_sqrt_rem, limbs_sqrt_rem_helper, limbs_sqrt_rem_helper_scratch_len, limbs_sqrt_rem_to_out, limbs_sqrt_to_out, }; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, triple_3_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_nrm, natural_gen_rm}; use malachite_nz::test_util::natural::arithmetic::sqrt::{ ceiling_sqrt_binary, checked_sqrt_binary, floor_sqrt_binary, sqrt_rem_binary, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_sqrt_rem_2_newton); register_demo!(runner, demo_limbs_sqrt_rem_helper); register_demo!(runner, demo_limbs_sqrt_helper); register_demo!(runner, demo_limbs_sqrt_to_out); register_demo!(runner, demo_limbs_sqrt_rem_to_out); register_demo!(runner, demo_limbs_floor_sqrt); register_demo!(runner, demo_limbs_ceiling_sqrt); register_demo!(runner, demo_limbs_checked_sqrt); register_demo!(runner, demo_limbs_sqrt_rem); register_demo!(runner, demo_natural_floor_sqrt); register_demo!(runner, demo_natural_floor_sqrt_ref); register_demo!(runner, demo_natural_floor_sqrt_assign); register_demo!(runner, demo_natural_ceiling_sqrt); register_demo!(runner, demo_natural_ceiling_sqrt_ref); register_demo!(runner, demo_natural_ceiling_sqrt_assign); register_demo!(runner, demo_natural_checked_sqrt); register_demo!(runner, demo_natural_checked_sqrt_ref); register_demo!(runner, demo_natural_sqrt_rem); register_demo!(runner, demo_natural_sqrt_rem_ref); register_demo!(runner, demo_natural_sqrt_assign_rem); register_bench!(runner, benchmark_sqrt_rem_2_newton); register_bench!(runner, benchmark_limbs_sqrt_rem_helper); register_bench!(runner, benchmark_limbs_sqrt_helper); register_bench!(runner, benchmark_limbs_sqrt_to_out); register_bench!(runner, benchmark_limbs_sqrt_rem_to_out); register_bench!(runner, benchmark_limbs_floor_sqrt); register_bench!(runner, benchmark_limbs_ceiling_sqrt); register_bench!(runner, benchmark_limbs_checked_sqrt); register_bench!(runner, benchmark_limbs_sqrt_rem); register_bench!(runner, benchmark_natural_floor_sqrt_evaluation_strategy); register_bench!(runner, benchmark_natural_floor_sqrt_algorithms); register_bench!(runner, benchmark_natural_floor_sqrt_library_comparison); register_bench!(runner, benchmark_natural_floor_sqrt_assign); register_bench!(runner, benchmark_natural_ceiling_sqrt_evaluation_strategy); register_bench!(runner, benchmark_natural_ceiling_sqrt_algorithms); register_bench!(runner, benchmark_natural_ceiling_sqrt_assign); register_bench!(runner, benchmark_natural_checked_sqrt_evaluation_strategy); register_bench!(runner, benchmark_natural_checked_sqrt_algorithms); register_bench!(runner, benchmark_natural_sqrt_rem_evaluation_strategy); register_bench!(runner, benchmark_natural_sqrt_rem_algorithms); register_bench!(runner, benchmark_natural_sqrt_rem_library_comparison); register_bench!(runner, benchmark_natural_sqrt_assign_rem); } fn demo_sqrt_rem_2_newton(gm: GenMode, config: &GenConfig, limit: usize) { for (h_hi, h_lo) in unsigned_pair_gen_var_31::() .get(gm, config) .take(limit) { println!( "sqrt_rem_2_newton({}, {}) = {:?}", h_hi, h_lo, sqrt_rem_2_newton::(h_hi, h_lo) ); } } fn demo_limbs_sqrt_rem_helper(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, mut xs) in unsigned_vec_pair_gen_var_4().get(gm, config).take(limit) { let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(out.len())]; let old_out = out.clone(); let old_xs = xs.clone(); let r_hi = limbs_sqrt_rem_helper(&mut out, &mut xs, 0, &mut scratch); println!( "out := {old_out:?}, xs := {old_xs:?}; \ limbs_sqrt_rem_helper(&mut out, &mut xs, 0, &mut scratch) = {r_hi}; \ out = {out:?}, xs = {xs:?}", ); } } fn demo_limbs_sqrt_helper(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, shift, odd) in large_type_gen_var_2().get(gm, config).take(limit) { let old_out = out.clone(); let r = limbs_sqrt_helper(&mut out, &xs, shift, odd); println!( "out := {old_out:?}, \ limbs_sqrt_helper(&mut out, {xs:?}, {shift}, {odd}) = {r}; out = {out:?}", ); } } fn demo_limbs_sqrt_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_5().get(gm, config).take(limit) { let old_out = out.clone(); limbs_sqrt_to_out(&mut out, &xs); println!("out := {old_out:?}, limbs_sqrt_to_out(&mut out, {xs:?}); out = {out:?}"); } } fn demo_limbs_sqrt_rem_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut sqrt_out, mut rem_out, xs) in unsigned_vec_triple_gen_var_28().get(gm, config).take(limit) { let old_sqrt_out = sqrt_out.clone(); let old_rem_out = rem_out.clone(); let r = limbs_sqrt_rem_to_out(&mut sqrt_out, &mut rem_out, &xs); println!( "out := {old_sqrt_out:?}, rem_out := {old_rem_out:?}; \ limbs_sqrt_rem_to_out(&mut sqrt_out, &mut rem_out, {xs:?}) = {r}; \ sqrt_out = {sqrt_out:?}, rem_out = {rem_out:?}", ); } } fn demo_limbs_floor_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!("limbs_floor_sqrt({:?}) = {:?}", xs, limbs_floor_sqrt(&xs)); } } fn demo_limbs_ceiling_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_ceiling_sqrt({:?}) = {:?}", xs, limbs_ceiling_sqrt(&xs) ); } } fn demo_limbs_checked_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!( "limbs_checked_sqrt({:?}) = {:?}", xs, limbs_checked_sqrt(&xs) ); } } fn demo_limbs_sqrt_rem(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1().get(gm, config).take(limit) { println!("limbs_sqrt_rem({:?}) = {:?}", xs, limbs_sqrt_rem(&xs)); } } fn demo_natural_floor_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.floor_sqrt() = {}", x, x.clone().floor_sqrt()); } } fn demo_natural_floor_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).floor_sqrt() = {}", x, (&x).floor_sqrt()); } } fn demo_natural_floor_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.floor_sqrt_assign(); println!("x := {old_x}; x.floor_sqrt_assign(); x = {x}"); } } fn demo_natural_ceiling_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.ceiling_sqrt() = {}", x, x.clone().ceiling_sqrt()); } } fn demo_natural_ceiling_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).ceiling_sqrt() = {}", x, (&x).ceiling_sqrt()); } } fn demo_natural_ceiling_sqrt_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); x.ceiling_sqrt_assign(); println!("x := {old_x}; x.ceiling_sqrt_assign(); x = {x}"); } } fn demo_natural_checked_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.checked_sqrt() = {:?}", x, x.clone().checked_sqrt()); } } fn demo_natural_checked_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).checked_sqrt() = {:?}", x, (&x).checked_sqrt()); } } fn demo_natural_sqrt_rem(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.sqrt_rem() = {:?}", x, x.clone().sqrt_rem()); } } fn demo_natural_sqrt_rem_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("(&{}).sqrt_rem() = {:?}", x, (&x).sqrt_rem()); } } fn demo_natural_sqrt_assign_rem(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in natural_gen().get(gm, config).take(limit) { let old_x = x.clone(); let rem = x.sqrt_assign_rem(); println!("x := {old_x}; x.sqrt_assign_rem() = {rem}; x = {x}"); } } fn benchmark_sqrt_rem_2_newton(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "sqrt_rem_2_newton(Limb, Limb)", BenchmarkType::Single, unsigned_pair_gen_var_31::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("n_hi", "n_lo"), &mut [("sqrt_rem_2_newton(Limb, Limb)", &mut |(n_hi, n_lo)| { no_out!(sqrt_rem_2_newton::(n_hi, n_lo)); })], ); } fn benchmark_limbs_sqrt_rem_helper(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sqrt_rem_helper(&mut [Limb], &mut [Limb], Limb, &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [( "limbs_sqrt_rem_helper(&mut [Limb], &mut [Limb], Limb, &mut [Limb])", &mut |(mut out, mut xs)| { let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(out.len())]; limbs_sqrt_rem_helper(&mut out, &mut xs, 0, &mut scratch); }, )], ); } fn benchmark_limbs_sqrt_helper(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sqrt_helper(&mut [Limb], &[Limb], u64, bool)", BenchmarkType::Single, large_type_gen_var_2().get(gm, config), gm.name(), limit, file_name, &quadruple_2_vec_len_bucketer("xs"), &mut [( "limbs_sqrt_helper(&mut [Limb], &[Limb], u64, bool)", &mut |(mut out, xs, shift, odd)| no_out!(limbs_sqrt_helper(&mut out, &xs, shift, odd)), )], ); } fn benchmark_limbs_sqrt_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sqrt_to_out(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [("limbs_sqrt_to_out(&mut [Limb], &[Limb])", &mut |( mut out, xs, )| { limbs_sqrt_to_out(&mut out, &xs); })], ); } fn benchmark_limbs_sqrt_rem_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sqrt_rem_to_out(&mut [Limb], &mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_28().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_len_bucketer("xs"), &mut [( "limbs_sqrt_rem_to_out(&mut [Limb], &mut [Limb], &[Limb])", &mut |(mut sqrt_out, mut rem_out, xs)| { no_out!(limbs_sqrt_rem_to_out(&mut sqrt_out, &mut rem_out, &xs)); }, )], ); } fn benchmark_limbs_floor_sqrt(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_floor_sqrt(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("limbs_floor_sqrt(&[Limb])", &mut |xs| { no_out!(limbs_floor_sqrt(&xs)); })], ); } fn benchmark_limbs_ceiling_sqrt(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_floor_sqrt(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("limbs_ceiling_sqrt(&[Limb])", &mut |xs| { no_out!(limbs_ceiling_sqrt(&xs)); })], ); } fn benchmark_limbs_checked_sqrt(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_checked_sqrt(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("limbs_checked_sqrt(&[Limb])", &mut |xs| { no_out!(limbs_checked_sqrt(&xs)); })], ); } fn benchmark_limbs_sqrt_rem(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sqrt_rem(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("limbs_sqrt_rem(&[Limb])", &mut |xs| { no_out!(limbs_sqrt_rem(&xs)); })], ); } fn benchmark_natural_floor_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_sqrt()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.floor_sqrt()", &mut |x| no_out!(x.floor_sqrt())), ("(&Natural).floor_sqrt()", &mut |x| { no_out!((&x).floor_sqrt()); }), ], ); } fn benchmark_natural_floor_sqrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_sqrt()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.floor_sqrt())), ("binary", &mut |x| no_out!(floor_sqrt_binary(&x))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_floor_sqrt_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_sqrt()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("num", &mut |(x, _, _)| no_out!(x.sqrt())), ("rug", &mut |(_, x, _)| no_out!(x.sqrt())), ("Malachite", &mut |(_, _, x)| no_out!(x.floor_sqrt())), ], ); } fn benchmark_natural_floor_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.floor_sqrt_assign()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.floor_sqrt_assign())], ); } fn benchmark_natural_ceiling_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_sqrt()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.ceiling_sqrt()", &mut |x| no_out!(x.ceiling_sqrt())), ("(&Natural).ceiling_sqrt()", &mut |x| { no_out!((&x).ceiling_sqrt()); }), ], ); } fn benchmark_natural_ceiling_sqrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_sqrt()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.ceiling_sqrt())), ("binary", &mut |x| no_out!(ceiling_sqrt_binary(&x))), ], ); } fn benchmark_natural_ceiling_sqrt_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ceiling_sqrt_assign()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.ceiling_sqrt_assign())], ); } fn benchmark_natural_checked_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sqrt()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.checked_sqrt()", &mut |x| no_out!(x.checked_sqrt())), ("(&Natural).checked_sqrt()", &mut |x| { no_out!((&x).checked_sqrt()); }), ], ); } fn benchmark_natural_checked_sqrt_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.checked_sqrt()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.checked_sqrt())), ("binary", &mut |x| no_out!(checked_sqrt_binary(&x))), ], ); } fn benchmark_natural_sqrt_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sqrt_rem()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("Natural.sqrt_rem()", &mut |x| no_out!(x.sqrt_rem())), ("(&Natural).sqrt_rem()", &mut |x| no_out!((&x).sqrt_rem())), ], ); } #[allow(clippy::no_effect)] fn benchmark_natural_sqrt_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sqrt_rem()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.sqrt_rem())), ("floor and subtraction", &mut |x| { let sqrt = (&x).floor_sqrt(); let square = (&sqrt).square(); (sqrt, x - square); }), ("binary", &mut |x| no_out!(sqrt_rem_binary(&x))), ], ); } fn benchmark_natural_sqrt_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sqrt_rem()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("x"), &mut [ ("rug", &mut |(x, _)| { no_out!(x.sqrt_rem(rug::Integer::new())); }), ("Malachite", &mut |(_, x)| no_out!(x.sqrt_rem())), ], ); } fn benchmark_natural_sqrt_assign_rem( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sqrt_assign_rem()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| no_out!(x.sqrt_assign_rem()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Square, SquareAssign}; use malachite_base::test_util::bench::bucketers::pair_2_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::mul::limbs_mul_greater_to_out_basecase; use malachite_nz::natural::arithmetic::square::{ limbs_square_to_out_basecase, limbs_square_to_out_toom_2, limbs_square_to_out_toom_2_scratch_len, limbs_square_to_out_toom_3, limbs_square_to_out_toom_3_scratch_len, limbs_square_to_out_toom_4, limbs_square_to_out_toom_4_scratch_len, limbs_square_to_out_toom_6, limbs_square_to_out_toom_6_scratch_len, limbs_square_to_out_toom_8, limbs_square_to_out_toom_8_scratch_len, }; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::{ natural_gen, unsigned_vec_pair_gen_var_22, unsigned_vec_pair_gen_var_23, unsigned_vec_pair_gen_var_24, unsigned_vec_pair_gen_var_26, unsigned_vec_pair_gen_var_27, unsigned_vec_pair_gen_var_28, }; use malachite_nz::test_util::natural::arithmetic::square::limbs_square_to_out_basecase_unrestricted; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_square_to_out_basecase); register_demo!(runner, demo_natural_square_assign); register_demo!(runner, demo_natural_square); register_demo!(runner, demo_natural_square_ref); register_bench!(runner, benchmark_limbs_square_to_out_basecase_algorithms); register_bench!(runner, benchmark_limbs_square_to_out_toom_2_algorithms); register_bench!(runner, benchmark_limbs_square_to_out_toom_3_algorithms); register_bench!(runner, benchmark_limbs_square_to_out_toom_4_algorithms); register_bench!(runner, benchmark_limbs_square_to_out_toom_6_algorithms); register_bench!(runner, benchmark_limbs_square_to_out_toom_8_algorithms); register_bench!(runner, benchmark_natural_square_assign); register_bench!(runner, benchmark_natural_square_algorithms); register_bench!(runner, benchmark_natural_square_evaluation_strategy); } fn demo_limbs_square_to_out_basecase(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_22().get(gm, config).take(limit) { let out_old = out.clone(); limbs_square_to_out_basecase(&mut out, &xs); println!( "out := {out_old:?}; limbs_square_to_out_basecase(&mut out, {xs:?}); out = {out:?}", ); } } fn demo_natural_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in natural_gen().get(gm, config).take(limit) { let old_n = n.clone(); n.square_assign(); println!("n := {n}; n.square_assign(); n = {old_n}"); } } fn demo_natural_square(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{} ^ 2 = {}", n.clone(), n.square()); } } fn demo_natural_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("&{} ^ 2 = {}", n, (&n).square()); } } fn benchmark_limbs_square_to_out_basecase_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_basecase(&mut [Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_22().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("default", &mut |(mut out, xs)| { limbs_square_to_out_basecase(&mut out, &xs); }), ( "using limbs_mul_greater_to_out_basecase", &mut |(mut out, xs)| limbs_mul_greater_to_out_basecase(&mut out, &xs, &xs), ), ], ); } fn benchmark_limbs_square_to_out_toom_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_toom_2(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_23().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs)| { limbs_square_to_out_basecase_unrestricted(&mut out, &xs); }), ("Toom2", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_2_scratch_len(xs.len())]; limbs_square_to_out_toom_2(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_limbs_square_to_out_toom_3_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_toom_3(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_24().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("Toom2", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_2_scratch_len(xs.len())]; limbs_square_to_out_toom_2(&mut out, &xs, &mut scratch); }), ("Toom3", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_3_scratch_len(xs.len())]; limbs_square_to_out_toom_3(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_limbs_square_to_out_toom_4_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_toom_4(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_26().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("Toom3", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_3_scratch_len(xs.len())]; limbs_square_to_out_toom_3(&mut out, &xs, &mut scratch); }), ("Toom4", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_4_scratch_len(xs.len())]; limbs_square_to_out_toom_4(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_limbs_square_to_out_toom_6_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_toom_6(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_27().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("Toom4", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_4_scratch_len(xs.len())]; limbs_square_to_out_toom_4(&mut out, &xs, &mut scratch); }), ("Toom6", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_6_scratch_len(xs.len())]; limbs_square_to_out_toom_6(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_limbs_square_to_out_toom_8_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_square_to_out_toom_8(&mut [Limb], &[Limb], &mut [Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_28().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [ ("Toom6", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_6_scratch_len(xs.len())]; limbs_square_to_out_toom_6(&mut out, &xs, &mut scratch); }), ("Toom8", &mut |(mut out, xs)| { let mut scratch = vec![0; limbs_square_to_out_toom_8_scratch_len(xs.len())]; limbs_square_to_out_toom_8(&mut out, &xs, &mut scratch); }), ], ); } fn benchmark_natural_square_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.square_assign()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |mut n| n.square_assign())], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.square()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("standard", &mut |n| no_out!(n.square())), ("using *", &mut |n| no_out!(&n * &n))], ); } fn benchmark_natural_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.square()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.square()", &mut |n| no_out!(n.square())), ("(&Natural).square()", &mut |n| no_out!((&n).square())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_min_len_bucketer, triple_1_2_vec_min_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_31, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_40, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_pair_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::sub::{ limbs_slice_sub_in_place_right, limbs_sub, limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb, limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_in_place_with_overlap, limbs_sub_same_length_to_out, limbs_sub_same_length_to_out_with_overlap, limbs_vec_sub_in_place_right, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen_var_10, natural_pair_gen_var_10_nrm, natural_pair_gen_var_10_rm, }; use malachite_nz::test_util::natural::arithmetic::sub::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_sub_limb); register_demo!(runner, demo_limbs_sub_limb_to_out); register_demo!(runner, demo_limbs_sub_limb_in_place); register_demo!(runner, demo_limbs_sub); register_demo!(runner, demo_limbs_sub_same_length_to_out); register_demo!(runner, demo_limbs_sub_greater_to_out); register_demo!(runner, demo_limbs_sub_same_length_in_place_left); register_demo!(runner, demo_limbs_sub_greater_in_place_left); register_demo!(runner, demo_limbs_sub_same_length_in_place_right); register_demo!(runner, demo_limbs_slice_sub_in_place_right); register_demo!(runner, demo_limbs_vec_sub_in_place_right); register_demo!(runner, demo_limbs_sub_same_length_in_place_with_overlap); register_demo!(runner, demo_limbs_sub_same_length_to_out_with_overlap); register_demo!(runner, demo_natural_sub_assign); register_demo!(runner, demo_natural_sub_assign_ref); register_demo!(runner, demo_natural_sub); register_demo!(runner, demo_natural_sub_val_ref); register_demo!(runner, demo_natural_sub_ref_val); register_demo!(runner, demo_natural_sub_ref_ref); register_bench!(runner, benchmark_limbs_sub_limb); register_bench!(runner, benchmark_limbs_sub_limb_to_out); register_bench!(runner, benchmark_limbs_sub_limb_in_place); register_bench!(runner, benchmark_limbs_sub); register_bench!(runner, benchmark_limbs_sub_same_length_to_out); register_bench!(runner, benchmark_limbs_sub_greater_to_out); register_bench!(runner, benchmark_limbs_sub_same_length_in_place_left); register_bench!(runner, benchmark_limbs_sub_greater_in_place_left); register_bench!(runner, benchmark_limbs_sub_same_length_in_place_right); register_bench!(runner, benchmark_limbs_slice_sub_in_place_right); register_bench!(runner, benchmark_limbs_vec_sub_in_place_right); register_bench!( runner, benchmark_limbs_sub_same_length_in_place_with_overlap_algorithms ); register_bench!( runner, benchmark_limbs_sub_same_length_to_out_with_overlap_algorithms ); register_bench!(runner, benchmark_natural_sub_assign_library_comparison); register_bench!(runner, benchmark_natural_sub_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_sub_library_comparison); register_bench!(runner, benchmark_natural_sub_evaluation_strategy); } fn demo_limbs_sub_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { println!( "limbs_sub_limb({:?}, {}) = {:?}", xs, y, limbs_sub_limb(&xs, y) ); } } fn demo_limbs_sub_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let out_old = out.clone(); let borrow = limbs_sub_limb_to_out(&mut out, &xs, y); println!( "out := {out_old:?}; \ limbs_sub_limb_to_out(&mut out, {xs:?}, {y}) = {borrow}; out = {out:?}", ); } } fn demo_limbs_sub_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_limb_in_place::(&mut xs, y); println!( "xs := {xs_old:?}; \ limbs_sub_limb_in_place(&mut xs, {y}) = {borrow}; xs = {xs:?}" ); } } fn demo_limbs_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_31().get(gm, config).take(limit) { println!("limbs_sub({:?}, {:?}) = {:?}", xs, ys, limbs_sub(&xs, &ys)); } } fn demo_limbs_sub_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_31().get(gm, config).take(limit) { let out_old = out.clone(); let borrow = limbs_sub_same_length_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_sub_same_length_to_out(&mut out, {xs:?}, {ys:?}) = {borrow}; out = {out:?}", ); } } fn demo_limbs_sub_greater_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_40().get(gm, config).take(limit) { let out_old = out.clone(); let borrow = limbs_sub_greater_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_sub_greater_to_out(&mut out, {xs:?}, {ys:?}) = {borrow}; out = {out:?}", ); } } fn demo_limbs_sub_same_length_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_same_length_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_sub_same_length_in_place_left(&mut xs, {ys:?}) = {borrow}; xs = {xs:?}", ); } } fn demo_limbs_sub_greater_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_31().get(gm, config).take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_greater_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_sub_greater_in_place_left(&mut xs, {ys:?}) = {borrow}; xs = {xs:?}", ); } } fn demo_limbs_sub_same_length_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let ys_old = ys.clone(); let borrow = limbs_sub_same_length_in_place_right(&xs, &mut ys); println!( "ys := {ys_old:?}; \ limbs_sub_same_length_in_place_right({xs:?}, &mut ys) = {borrow}; ys = {ys:?}", ); } } fn demo_limbs_slice_sub_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, len) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24() .get(gm, config) .take(limit) { let ys_old = ys.clone(); let borrow = limbs_slice_sub_in_place_right(&xs, &mut ys, len); println!( "ys := {ys_old:?}; \ limbs_slice_sub_in_place_right({xs:?}, &mut ys, {len}) = {borrow}; ys = {ys:?}", ); } } fn demo_limbs_vec_sub_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys) in unsigned_vec_pair_gen_var_31().get(gm, config).take(limit) { let ys_old = ys.clone(); let borrow = limbs_vec_sub_in_place_right(&xs, &mut ys); println!( "ys := {ys_old:?}; \ limbs_vec_sub_in_place_right({xs:?}, &mut ys) = {borrow}; ys = {ys:?}", ); } } fn demo_limbs_sub_same_length_in_place_with_overlap(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, right_start) in unsigned_vec_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_same_length_in_place_with_overlap(&mut xs, right_start); println!( "xs := {xs_old:?}; \ limbs_sub_same_length_in_place_with_overlap(&mut xs, {right_start}) = {borrow}; \ xs = {xs:?}", ); } } fn demo_limbs_sub_same_length_to_out_with_overlap(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_31().get(gm, config).take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_same_length_to_out_with_overlap(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_sub_same_length_to_out_with_overlap(&mut xs, {ys:?}) = {borrow}; xs = {xs:?}", ); } } fn demo_natural_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); x -= y.clone(); println!("x := {x_old}; x -= {y}; x = {x}"); } } fn demo_natural_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); x -= &y; println!("x := {x_old}; x -= &{y}; x = {x}"); } } fn demo_natural_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_natural_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_natural_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_natural_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_10().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn benchmark_limbs_sub_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sub_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_sub_limb(&xs, y)))], ); } fn benchmark_limbs_sub_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sub_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_sub_limb_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_sub_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { no_out!(limbs_sub_limb_in_place::(&mut xs, y)); })], ); } fn benchmark_limbs_sub(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sub(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_31().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_sub(&xs, &ys)))], ); } fn benchmark_limbs_sub_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { no_out!(limbs_sub_same_length_to_out(&mut out, &xs, &ys)); })], ); } fn benchmark_limbs_sub_greater_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_greater_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_40().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { no_out!(limbs_sub_greater_to_out(&mut out, &xs, &ys)); })], ); } fn benchmark_limbs_sub_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_same_length_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_sub_same_length_in_place_left(&mut xs, &ys)); })], ); } fn benchmark_limbs_sub_greater_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_greater_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_31().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_sub_greater_in_place_left(&mut xs, &ys)); })], ); } fn benchmark_limbs_sub_same_length_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_same_length_in_place_right(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, mut ys)| { no_out!(limbs_sub_same_length_in_place_right(&xs, &mut ys)); })], ); } fn benchmark_limbs_slice_sub_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_sub_in_place_right(&[Limb], &mut [Limb], usize)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24().get(gm, config), gm.name(), limit, file_name, &triple_1_2_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, mut ys, len)| { no_out!(limbs_slice_sub_in_place_right(&xs, &mut ys, len)); })], ); } fn benchmark_limbs_vec_sub_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_sub_in_place_right(&[Limb], &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen_var_31().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, mut ys)| { no_out!(limbs_vec_sub_in_place_right(&xs, &mut ys)); })], ); } fn benchmark_limbs_sub_same_length_in_place_with_overlap_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_same_length_in_place_with_overlap(&mut [Limb], usize)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut xs, right_start)| { no_out!(limbs_sub_same_length_in_place_with_overlap( &mut xs, right_start )); }), ("naive", &mut |(mut xs, right_start)| { no_out!(limbs_sub_same_length_in_place_with_overlap_naive( &mut xs, right_start )); }), ], ); } fn benchmark_limbs_sub_same_length_to_out_with_overlap_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_same_length_to_out_with_overlap(&mut [Limb], &[Limb])", BenchmarkType::Algorithms, unsigned_vec_pair_gen_var_31().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("standard", &mut |(mut xs, ys)| { no_out!(limbs_sub_same_length_to_out_with_overlap(&mut xs, &ys)); }), ("naive", &mut |(mut xs, ys)| { no_out!(limbs_sub_same_length_to_out_with_overlap_naive( &mut xs, &ys )); }), ], ); } fn benchmark_natural_sub_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural -= Natural", BenchmarkType::LibraryComparison, natural_pair_gen_var_10_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x -= y), ("rug", &mut |((mut x, y), _)| x -= y)], ); } fn benchmark_natural_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural -= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_10().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural -= Natural", &mut |(mut x, y)| x -= y), ("Natural -= &Natural", &mut |(mut x, y)| x -= &y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_sub_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural - Natural", BenchmarkType::LibraryComparison, natural_pair_gen_var_10_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x - y)), ("num", &mut |((x, y), _, _)| no_out!(x - y)), ("rug", &mut |(_, (x, y), _)| no_out!(x - y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural - Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_10().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural - Natural", &mut |(x, y)| no_out!(x - y)), ("Natural - &Natural", &mut |(x, y)| no_out!(x - &y)), ("&Natural - Natural", &mut |(x, y)| no_out!(&x - y)), ("&Natural - &Natural", &mut |(x, y)| no_out!(&x - &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{SubMul, SubMulAssign}; use malachite_base::test_util::bench::bucketers::triple_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_triple_gen_var_59, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::arithmetic::sub_mul::{ limbs_sub_mul, limbs_sub_mul_in_place_left, limbs_sub_mul_limb_greater, limbs_sub_mul_limb_greater_in_place_left, limbs_sub_mul_limb_greater_in_place_right, limbs_sub_mul_limb_same_length_in_place_left, limbs_sub_mul_limb_same_length_in_place_right, }; use malachite_nz::test_util::bench::bucketers::triple_natural_max_bit_bucketer; use malachite_nz::test_util::generators::natural_triple_gen_var_7; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_sub_mul_limb_greater); register_demo!(runner, demo_limbs_sub_mul_limb_same_length_in_place_left); register_demo!(runner, demo_limbs_sub_mul_limb_greater_in_place_left); register_demo!(runner, demo_limbs_sub_mul_limb_same_length_in_place_right); register_demo!(runner, demo_limbs_sub_mul_limb_greater_in_place_right); register_demo!(runner, demo_limbs_sub_mul); register_demo!(runner, demo_limbs_sub_mul_in_place_left); register_demo!(runner, demo_natural_sub_mul_assign); register_demo!(runner, demo_natural_sub_mul_assign_val_ref); register_demo!(runner, demo_natural_sub_mul_assign_ref_val); register_demo!(runner, demo_natural_sub_mul_assign_ref_ref); register_demo!(runner, demo_natural_sub_mul); register_demo!(runner, demo_natural_sub_mul_val_val_ref); register_demo!(runner, demo_natural_sub_mul_val_ref_val); register_demo!(runner, demo_natural_sub_mul_val_ref_ref); register_demo!(runner, demo_natural_sub_mul_ref_ref_ref); register_bench!(runner, benchmark_limbs_sub_mul_limb_greater); register_bench!( runner, benchmark_limbs_sub_mul_limb_same_length_in_place_left ); register_bench!(runner, benchmark_limbs_sub_mul_limb_greater_in_place_left); register_bench!( runner, benchmark_limbs_sub_mul_limb_same_length_in_place_right ); register_bench!(runner, benchmark_limbs_sub_mul_limb_greater_in_place_right); register_bench!(runner, benchmark_limbs_sub_mul); register_bench!(runner, benchmark_limbs_sub_mul_in_place_left); register_bench!(runner, benchmark_natural_sub_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_sub_mul_assign_algorithms); register_bench!(runner, benchmark_natural_sub_mul_assign_val_ref_algorithms); register_bench!(runner, benchmark_natural_sub_mul_assign_ref_val_algorithms); register_bench!(runner, benchmark_natural_sub_mul_assign_ref_ref_algorithms); register_bench!(runner, benchmark_natural_sub_mul_evaluation_stategy); register_bench!(runner, benchmark_natural_sub_mul_algorithms); register_bench!(runner, benchmark_natural_sub_mul_val_val_ref_algorithms); register_bench!(runner, benchmark_natural_sub_mul_val_ref_val_algorithms); register_bench!(runner, benchmark_natural_sub_mul_val_ref_ref_algorithms); register_bench!(runner, benchmark_natural_sub_mul_ref_ref_ref_algorithms); } fn demo_limbs_sub_mul_limb_greater(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, z) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "limbs_sub_mul_limb_greater({:?}, {:?}, {}) = {:?}", xs, ys, z, limbs_sub_mul_limb_greater(&xs, &ys, z), ); } } fn demo_limbs_sub_mul_limb_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut xs, ys, z) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_mul_limb_same_length_in_place_left(&mut xs, &ys, z); println!( "xs := {xs_old:?}; \ limbs_sub_mul_limb_same_length_in_place_left(&mut xs, {ys:?}, {z}) = {borrow}; \ xs = {xs:?}", ); } } fn demo_limbs_sub_mul_limb_greater_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, z) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let borrow = limbs_sub_mul_limb_greater_in_place_left(&mut xs, &ys, z); println!( "xs := {xs_old:?}; \ limbs_sub_mul_limb_greater_in_place_left(&mut xs, {ys:?}, {z}) = {borrow}; \ xs = {xs:?}", ); } } fn demo_limbs_sub_mul_limb_same_length_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, ) { for (xs, mut ys, z) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12() .get(gm, config) .take(limit) { let ys_old = ys.clone(); limbs_sub_mul_limb_same_length_in_place_right(&xs, &mut ys, z); println!( "ys := {ys_old:?}; \ limbs_sub_mul_limb_same_length_in_place_right({xs:?}, &mut ys, {z}); \ ys = {ys:?}", ); } } fn demo_limbs_sub_mul_limb_greater_in_place_right(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, mut ys, z) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { let ys_old = ys.clone(); limbs_sub_mul_limb_greater_in_place_right(&xs, &mut ys, z); println!( "ys := {ys_old:?}; \ limbs_sub_mul_limb_greater_in_place_right({xs:?}, &mut ys, {z}); ys = {ys:?}", ); } } fn demo_limbs_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys, zs) in unsigned_vec_triple_gen_var_59().get(gm, config).take(limit) { println!( "limbs_sub_mul({:?}, {:?}, {:?}) = {:?}", xs, ys, zs, limbs_sub_mul(&xs, &ys, &zs), ); } } fn demo_limbs_sub_mul_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys, zs) in unsigned_vec_triple_gen_var_59().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_sub_mul_in_place_left(&mut xs, &ys, &zs); println!( "xs := {xs_old:?}; limbs_sub_mul_in_place_left(&mut xs, {ys:?}, {zs:?}); xs = {xs:?}", ); } } fn demo_natural_sub_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); let c_old = c.clone(); a.sub_mul_assign(b, c); println!("a := {a_old}; x.sub_mul_assign({b_old}, {c_old}); x = {a}"); } } fn demo_natural_sub_mul_assign_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); a.sub_mul_assign(b, &c); println!("a := {a_old}; x.sub_mul_assign({b_old}, &{c}); x = {a}"); } } fn demo_natural_sub_mul_assign_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let c_old = c.clone(); a.sub_mul_assign(&b, c); println!("a := {a_old}; x.sub_mul_assign(&{b}, {c_old}); x = {a}"); } } fn demo_natural_sub_mul_assign_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); a.sub_mul_assign(&b, &c); println!("a := {a_old}; x.sub_mul_assign(&{b}, &{c}); x = {a}"); } } fn demo_natural_sub_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); let c_old = c.clone(); println!( "{}.sub_mul({}, {}) = {}", a_old, b_old, c_old, a.sub_mul(b, c) ); } } fn demo_natural_sub_mul_val_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let b_old = b.clone(); println!( "{}.sub_mul({}, &{}) = {}", a_old, b_old, c, a.sub_mul(b, &c) ); } } fn demo_natural_sub_mul_val_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); let c_old = c.clone(); println!( "{}.sub_mul(&{}, {}) = {}", a_old, b, c_old, a.sub_mul(&b, c) ); } } fn demo_natural_sub_mul_val_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { let a_old = a.clone(); println!("{}.sub_mul(&{}, &{}) = {}", a_old, b, c, a.sub_mul(&b, &c)); } } fn demo_natural_sub_mul_ref_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b, c) in natural_triple_gen_var_7().get(gm, config).take(limit) { println!( "(&{}).sub_mul(&{}, &{}) = {}", a, b, c, (&a).sub_mul(&b, &c) ); } } fn benchmark_limbs_sub_mul_limb_greater( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_limb_greater(&[Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys, z)| { no_out!(limbs_sub_mul_limb_greater(&xs, &ys, z)); })], ); } fn benchmark_limbs_sub_mul_limb_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_limb_same_length_in_place_left(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys, z)| { no_out!(limbs_sub_mul_limb_same_length_in_place_left( &mut xs, &ys, z )); })], ); } fn benchmark_limbs_sub_mul_limb_greater_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_limb_greater_in_place_left(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys, z)| { no_out!(limbs_sub_mul_limb_greater_in_place_left(&mut xs, &ys, z)); })], ); } fn benchmark_limbs_sub_mul_limb_same_length_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_limb_same_length_in_place_right(&[Limb], &mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, mut ys, z)| { no_out!(limbs_sub_mul_limb_same_length_in_place_right( &xs, &mut ys, z )); })], ); } fn benchmark_limbs_sub_mul_limb_greater_in_place_right( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_limb_greater_in_place_right(&[Limb], &mut Vec, Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, mut ys, z)| { no_out!(limbs_sub_mul_limb_same_length_in_place_right( &xs, &mut ys, z )); })], ); } fn benchmark_limbs_sub_mul(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_sub_mul(&[Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_59().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys, zs)| { no_out!(limbs_sub_mul(&xs, &ys, &zs)); })], ); } fn benchmark_limbs_sub_mul_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_sub_mul_in_place_left(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_59().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys, zs)| { no_out!(limbs_sub_mul_in_place_left(&mut xs, &ys, &zs)); })], ); } fn benchmark_natural_sub_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.sub_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(b, c), ), ( "Natural.sub_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(b, &c), ), ( "Natural.sub_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, c), ), ( "Natural.sub_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, &c), ), ], ); } fn benchmark_natural_sub_mul_assign_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul_assign(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.sub_mul_assign(Natural, Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(b, c), ), ("Natural += Natural * Natural", &mut |(mut a, b, c)| { a += b * c; }), ], ); } fn benchmark_natural_sub_mul_assign_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul_assign(Natural, &Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.sub_mul_assign(Natural, &Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(b, &c), ), ("Natural += Natural * &Natural", &mut |(mut a, b, c)| { a += b * &c; }), ], ); } fn benchmark_natural_sub_mul_assign_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul_assign(&Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.sub_mul_assign(&Natural, Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, c), ), ("Natural += &Natural * Natural", &mut |(mut a, b, c)| { a += &b * c; }), ], ); } fn benchmark_natural_sub_mul_assign_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul_assign(&Natural, &Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "Natural.sub_mul_assign(&Natural, &Natural)", &mut |(mut a, b, c)| a.sub_mul_assign(&b, &c), ), ("Natural += &Natural * &Natural", &mut |(mut a, b, c)| { a += &b * &c; }), ], ); } fn benchmark_natural_sub_mul_evaluation_stategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.sub_mul(Natural, Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, c)); }), ("Natural.sub_mul(Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, &c)); }), ("Natural.sub_mul(&Natural, Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, c)); }), ("Natural.sub_mul(&Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, &c)); }), ( "(&Natural).sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).sub_mul(&b, &c)), ), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul(Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.sub_mul(Natural, Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, c)); }), ("Natural - Natural * Natural", &mut |(a, b, c)| { no_out!(a - b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_mul_val_val_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul(Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.sub_mul(Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(b, &c)); }), ("Natural - Natural * &Natural", &mut |(a, b, c)| { no_out!(a - b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_mul_val_ref_val_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul(&Natural, Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.sub_mul(&Natural, Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, c)); }), ("Natural - &Natural * Natural", &mut |(a, b, c)| { no_out!(a - &b * c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_mul_val_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ("Natural.sub_mul(&Natural, &Natural)", &mut |(a, b, c)| { no_out!(a.sub_mul(&b, &c)); }), ("Natural - &Natural * &Natural", &mut |(a, b, c)| { no_out!(a - &b * &c); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_sub_mul_ref_ref_ref_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Natural).sub_mul(&Natural, &Natural)", BenchmarkType::Algorithms, natural_triple_gen_var_7().get(gm, config), gm.name(), limit, file_name, &triple_natural_max_bit_bucketer("a", "b", "c"), &mut [ ( "(&Natural).sub_mul(&Natural, &Natural)", &mut |(a, b, c)| no_out!((&a).sub_mul(&b, &c)), ), ("(&Natural) - &Natural * &Natural", &mut |(a, b, c)| { no_out!((&a) - &b * &c); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_max_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_7, unsigned_vec_pair_gen_var_19, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::comparison::cmp::{ limbs_cmp, limbs_cmp_normalized, limbs_cmp_same_length, }; use malachite_nz::test_util::bench::bucketers::{ pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_var_9, }; use malachite_nz::test_util::natural::comparison::cmp::natural_cmp_normalized_naive; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_cmp_same_length); register_demo!(runner, demo_limbs_cmp); register_demo!(runner, demo_limbs_cmp_normalized); register_demo!(runner, demo_natural_cmp); register_demo!(runner, demo_natural_cmp_normalized); register_bench!(runner, benchmark_limbs_cmp_same_length); register_bench!(runner, benchmark_limbs_cmp); register_bench!(runner, benchmark_limbs_cmp_normalized); register_bench!(runner, benchmark_natural_cmp_library_comparison); register_bench!(runner, benchmark_natural_cmp_normalized_algorithms); } fn demo_limbs_cmp_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { println!( "limbs_cmp_same_length({:?}, {:?}) = {:?}", xs, ys, limbs_cmp_same_length(&xs, &ys), ); } } fn demo_limbs_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_7().get(gm, config).take(limit) { println!("limbs_cmp({:?}, {:?}) = {:?}", xs, ys, limbs_cmp(&xs, &ys)); } } fn demo_limbs_cmp_normalized(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_19().get(gm, config).take(limit) { println!( "limbs_cmp_normalized({:?}, {:?}) = {:?}", xs, ys, limbs_cmp_normalized(&xs, &ys), ); } } fn demo_natural_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { match x.cmp(&y) { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } fn demo_natural_cmp_normalized(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen_var_9().get(gm, config).take(limit) { println!("cmp_normalized({}, {}) = {:?}", x, y, x.cmp_normalized(&y)); } } fn benchmark_limbs_cmp_same_length(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_cmp_same_length(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_cmp_same_length(&xs, &ys)); })], ); } fn benchmark_limbs_cmp(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_cmp(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_cmp(&xs, &ys)))], ); } fn benchmark_limbs_cmp_normalized(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_cmp_normalized(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_19().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_cmp_normalized(&xs, &ys)); })], ); } #[allow(unused_must_use)] fn benchmark_natural_cmp_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.cmp(&Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.cmp(&y))), ("num", &mut |((x, y), _, _)| no_out!(x.cmp(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.cmp(&y))), ], ); } fn benchmark_natural_cmp_normalized_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.cmp_normalized(&Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_9().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.cmp_normalized(&y))), ("naive", &mut |(x, y)| { no_out!(natural_cmp_normalized_naive(&x, &y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_pair_natural_max_bit_bucketer; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_eq); register_bench!(runner, benchmark_natural_eq_library_comparison); } fn demo_natural_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_eq_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural == Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x == y)), ("num", &mut |((x, y), _, _)| no_out!(x == y)), ("rug", &mut |(_, (x, y), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_primitive_float_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_eq_abs_primitive_float); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_natural); register_primitive_float_benches!(runner, benchmark_natural_eq_abs_primitive_float); register_primitive_float_benches!(runner, benchmark_primitive_float_eq_abs_natural); } fn demo_natural_eq_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: EqAbs, { for (n, x) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n.eq_abs(&x) { println!("|{}| = |{}|", n, NiceFloat(x)); } else { println!("|{}| ≠ |{}|", n, NiceFloat(x)); } } } fn demo_primitive_float_eq_abs_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, x) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x.eq_abs(&n) { println!("|{}| = |{}|", NiceFloat(x), n); } else { println!("|{}| ≠ |{}|", NiceFloat(x), n); } } } fn benchmark_natural_eq_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: EqAbs, { run_benchmark( &format!("Natural.eq_abs(&{})", T::NAME), BenchmarkType::Single, natural_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.eq_abs(&y)))], ); } fn benchmark_primitive_float_eq_abs_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.eq_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_signed_pair_gen, natural_unsigned_pair_gen}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_eq_abs_unsigned); register_signed_demos!(runner, demo_natural_eq_abs_signed); register_unsigned_demos!(runner, demo_unsigned_eq_abs_natural); register_signed_demos!(runner, demo_signed_eq_abs_natural); register_unsigned_benches!(runner, benchmark_natural_eq_abs_unsigned); register_signed_benches!(runner, benchmark_natural_eq_abs_signed); register_unsigned_benches!(runner, benchmark_unsigned_eq_abs_natural); register_signed_benches!(runner, benchmark_signed_eq_abs_natural); } fn demo_natural_eq_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: EqAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n.eq_abs(&u) { println!("|{n}| = |{u}|"); } else { println!("|{n}| ≠ |{u}|"); } } } fn demo_natural_eq_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: EqAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n.eq_abs(&i) { println!("|{n}| = |{i}|"); } else { println!("|{n}| ≠ |{i}|"); } } } fn demo_unsigned_eq_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u.eq_abs(&n) { println!("|{u}| = |{n}|"); } else { println!("|{u}| ≠ |{n}|"); } } } fn demo_signed_eq_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i.eq_abs(&n) { println!("|{i}| = |{n}|"); } else { println!("|{i}| ≠ |{n}|"); } } } fn benchmark_natural_eq_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: EqAbs, { run_benchmark( &format!("Natural.eq_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.eq_abs(&y)))], ); } fn benchmark_natural_eq_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: EqAbs, { run_benchmark( &format!("Natural.eq_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.eq_abs(&y)))], ); } fn benchmark_unsigned_eq_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.eq_abs(&x)))], ); } fn benchmark_signed_eq_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.eq_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::triple_3_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_gen, natural_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_hash); register_bench!(runner, benchmark_natural_hash_library_comparison); } fn demo_natural_hash(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("hash({}) = {}", n, hash(&n)); } } fn benchmark_natural_hash_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural hash", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(hash(&n))), ("num", &mut |(_, n, _)| no_out!(hash(&n))), ("rug", &mut |(n, _, _)| no_out!(hash(&n))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); eq::register(runner); eq_abs_primitive_float::register(runner); eq_abs_primitive_int::register(runner); hash::register(runner); partial_cmp_abs_primitive_float::register(runner); partial_cmp_abs_primitive_int::register(runner); partial_cmp_primitive_float::register(runner); partial_cmp_primitive_int::register(runner); partial_eq_primitive_int::register(runner); partial_eq_primitive_float::register(runner); } mod cmp; mod eq; mod eq_abs_primitive_float; mod eq_abs_primitive_int; mod hash; mod partial_cmp_abs_primitive_float; mod partial_cmp_abs_primitive_int; mod partial_cmp_primitive_float; mod partial_cmp_primitive_int; mod partial_eq_primitive_float; mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_primitive_float_pair_gen; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_partial_cmp_abs_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_natural); register_primitive_float_benches!(runner, benchmark_natural_partial_cmp_abs_float); register_primitive_float_benches!(runner, benchmark_float_partial_cmp_abs_natural); } fn demo_natural_partial_cmp_abs_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialOrdAbs, { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp_abs(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("|{}| < |{}|", n, NiceFloat(f)), Some(Equal) => println!("|{}| = |{}|", n, NiceFloat(f)), Some(Greater) => println!("|{}| > |{}|", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_abs_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp_abs(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("|{}| < |{}|", NiceFloat(f), n), Some(Equal) => println!("|{}| = |{}|", NiceFloat(f), n), Some(Greater) => println!("|{}| > |{}|", NiceFloat(f), n), } } } fn benchmark_natural_partial_cmp_abs_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Single, natural_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y)))], ); } fn benchmark_float_partial_cmp_abs_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_signed_pair_gen, natural_unsigned_pair_gen}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_partial_cmp_abs_unsigned); register_signed_demos!(runner, demo_natural_partial_cmp_abs_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_natural); register_signed_demos!(runner, demo_signed_partial_cmp_abs_natural); register_unsigned_demos!(runner, demo_natural_lt_abs_unsigned); register_signed_demos!(runner, demo_natural_lt_abs_signed); register_unsigned_demos!(runner, demo_natural_gt_abs_unsigned); register_signed_demos!(runner, demo_natural_gt_abs_signed); register_unsigned_demos!(runner, demo_natural_le_abs_unsigned); register_signed_demos!(runner, demo_natural_le_abs_signed); register_unsigned_demos!(runner, demo_natural_ge_abs_unsigned); register_signed_demos!(runner, demo_natural_ge_abs_signed); register_unsigned_demos!(runner, demo_unsigned_lt_abs_natural); register_signed_demos!(runner, demo_signed_lt_abs_natural); register_unsigned_demos!(runner, demo_unsigned_gt_abs_natural); register_signed_demos!(runner, demo_signed_gt_abs_natural); register_unsigned_demos!(runner, demo_unsigned_le_abs_natural); register_signed_demos!(runner, demo_signed_le_abs_natural); register_unsigned_demos!(runner, demo_unsigned_ge_abs_natural); register_signed_demos!(runner, demo_signed_ge_abs_natural); register_unsigned_benches!(runner, benchmark_natural_partial_cmp_abs_unsigned); register_signed_benches!(runner, benchmark_natural_partial_cmp_abs_signed); register_unsigned_benches!(runner, benchmark_unsigned_partial_cmp_abs_natural); register_signed_benches!(runner, benchmark_signed_partial_cmp_abs_natural); register_unsigned_benches!(runner, benchmark_natural_lt_abs_unsigned); register_signed_benches!(runner, benchmark_natural_lt_abs_signed); register_unsigned_benches!(runner, benchmark_natural_gt_abs_unsigned); register_signed_benches!(runner, benchmark_natural_gt_abs_signed); register_unsigned_benches!(runner, benchmark_natural_le_abs_unsigned); register_signed_benches!(runner, benchmark_natural_le_abs_signed); register_unsigned_benches!(runner, benchmark_natural_ge_abs_unsigned); register_signed_benches!(runner, benchmark_natural_ge_abs_signed); register_unsigned_benches!(runner, benchmark_unsigned_lt_abs_natural); register_signed_benches!(runner, benchmark_signed_lt_abs_natural); register_unsigned_benches!(runner, benchmark_unsigned_gt_abs_natural); register_signed_benches!(runner, benchmark_signed_gt_abs_natural); register_unsigned_benches!(runner, benchmark_unsigned_le_abs_natural); register_signed_benches!(runner, benchmark_signed_le_abs_natural); register_unsigned_benches!(runner, benchmark_unsigned_ge_abs_natural); register_signed_benches!(runner, benchmark_signed_ge_abs_natural); } fn demo_natural_partial_cmp_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialOrdAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp_abs(&u).unwrap() { Less => println!("|{n}| < |{u}|"), Equal => println!("|{n}| = |{u}|"), Greater => println!("|{n}| > |{u}|"), } } } fn demo_natural_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialOrdAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp_abs(&i).unwrap() { Less => println!("|{n}| < |{i}|"), Equal => println!("|{n}| = |{i}|"), Greater => println!("|{n}| > |{i}|"), } } } fn demo_unsigned_partial_cmp_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { match u.partial_cmp_abs(&n).unwrap() { Less => println!("|{u}| < |{n}|"), Equal => println!("|{u}| = |{n}|"), Greater => println!("|{u}| > |{n}|"), } } } fn demo_signed_partial_cmp_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp_abs(&n).unwrap() { Less => println!("|{i}| < |{n}|"), Equal => println!("|{i}| = |{n}|"), Greater => println!("|{i}| > |{n}|"), } } } fn demo_natural_lt_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n.lt_abs(&u) { println!("|{n}| < |{u}|"); } else { println!("|{n}| ≮ |{u}|"); } } } fn demo_natural_lt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n.lt_abs(&i) { println!("|{n}| < |{i}|"); } else { println!("|{n}| ≮ |{i}|"); } } } fn demo_natural_gt_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n.gt_abs(&u) { println!("|{n}| > |{u}|"); } else { println!("|{n}| ≯ |{u}|"); } } } fn demo_natural_gt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n.gt_abs(&i) { println!("|{n}| > |{i}|"); } else { println!("|{n}| ≯ |{i}|"); } } } fn demo_natural_le_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n.le_abs(&u) { println!("|{n}| ≤ |{u}|"); } else { println!("|{n}| ≰ |{u}|"); } } } fn demo_natural_le_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n.le_abs(&i) { println!("|{n}| ≤ |{i}|"); } else { println!("|{n}| ≰ |{i}|"); } } } fn demo_natural_ge_abs_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n.ge_abs(&u) { println!("|{n}| ≥ |{u}|"); } else { println!("|{n}| ≱ |{u}|"); } } } fn demo_natural_ge_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrdAbs, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n.ge_abs(&i) { println!("|{n}| ≥ |{i}|"); } else { println!("|{n}| ≱ |{i}|"); } } } fn demo_unsigned_lt_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u.lt_abs(&n) { println!("|{u}| < |{n}|"); } else { println!("|{u}| ≮ |{n}|"); } } } fn demo_signed_lt_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i.lt_abs(&n) { println!("|{i}| < |{n}|"); } else { println!("|{i}| ≮ |{n}|"); } } } fn demo_unsigned_gt_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u.gt_abs(&n) { println!("|{u}| > |{n}|"); } else { println!("|{u}| ≯ |{n}|"); } } } fn demo_signed_gt_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i.gt_abs(&n) { println!("|{i}| > |{n}|"); } else { println!("|{i}| ≯ |{n}|"); } } } fn demo_unsigned_le_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u.le_abs(&n) { println!("|{u}| ≤ |{n}|"); } else { println!("|{u}| ≰ |{n}|"); } } } fn demo_signed_le_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i.le_abs(&n) { println!("|{i}| ≤ |{n}|"); } else { println!("|{i}| ≰ |{n}|"); } } } fn demo_unsigned_ge_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u.ge_abs(&n) { println!("|{u}| ≥ |{n}|"); } else { println!("|{u}| ≱ |{n}|"); } } } fn demo_signed_ge_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i.ge_abs(&n) { println!("|{i}| ≥ |{n}|"); } else { println!("|{i}| ≱ |{n}|"); } } } fn benchmark_natural_partial_cmp_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y)))], ); } fn benchmark_natural_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y)))], ); } fn benchmark_unsigned_partial_cmp_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x)))], ); } fn benchmark_signed_partial_cmp_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x)))], ); } fn benchmark_natural_lt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.lt_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_natural_lt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.lt_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_natural_gt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.gt_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_natural_gt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.gt_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_natural_le_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.le_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_natural_le_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.le_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_natural_ge_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.ge_abs(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_natural_ge_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrdAbs, { run_benchmark( &format!("Natural.ge_abs(&{})", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_unsigned_lt_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_signed_lt_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_unsigned_gt_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_signed_gt_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_unsigned_le_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_signed_le_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_unsigned_ge_abs_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } fn benchmark_signed_ge_abs_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Natural)", T::NAME), BenchmarkType::Single, natural_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_2_pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{ natural_primitive_float_pair_gen, natural_primitive_float_pair_gen_rm, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_partial_cmp_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_natural); register_primitive_float_benches!( runner, benchmark_natural_partial_cmp_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_cmp_natural_library_comparison ); } fn demo_natural_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialOrd, { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("{} < {}", n, NiceFloat(f)), Some(Equal) => println!("{} = {}", n, NiceFloat(f)), Some(Greater) => println!("{} > {}", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("{} < {}", NiceFloat(f), n), Some(Equal) => println!("{} = {}", NiceFloat(f), n), Some(Greater) => println!("{} > {}", NiceFloat(f), n), } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Natural.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, natural_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_cmp_natural_library_comparison< T: PartialOrd + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Natural)", T::NAME), BenchmarkType::LibraryComparison, natural_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_signed_pair_gen, natural_signed_pair_gen_rm, natural_unsigned_pair_gen, natural_unsigned_pair_gen_nrm, natural_unsigned_pair_gen_rm, }; use malachite_nz::test_util::natural::comparison::partial_cmp_primitive_int::*; use num::BigUint; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_partial_cmp_unsigned); register_signed_demos!(runner, demo_natural_partial_cmp_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_natural); register_signed_demos!(runner, demo_signed_partial_cmp_natural); register_unsigned_benches!( runner, benchmark_natural_partial_cmp_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_natural_partial_cmp_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_natural_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_cmp_natural_library_comparison ); } fn demo_natural_partial_cmp_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialOrd, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp(&u).unwrap() { Less => println!("{n} < {u}"), Equal => println!("{n} = {u}"), Greater => println!("{n} > {u}"), } } } fn demo_natural_partial_cmp_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialOrd, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp(&i).unwrap() { Less => println!("{n} < {i}"), Equal => println!("{n} = {i}"), Greater => println!("{n} > {i}"), } } } fn demo_unsigned_partial_cmp_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { match u.partial_cmp(&n).unwrap() { Less => println!("{u} < {n}"), Equal => println!("{u} = {n}"), Greater => println!("{u} > {n}"), } } } fn demo_signed_partial_cmp_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp(&n).unwrap() { Less => println!("{i} < {n}"), Equal => println!("{i} = {n}"), Greater => println!("{i} > {n}"), } } } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BigUint: From, Natural: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Natural.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| { no_out!(x.partial_cmp(&y)); }), ("num", &mut |((x, y), _, _)| { no_out!(num_partial_cmp_unsigned(&x, y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialOrd, rug::Integer: PartialOrd, { run_benchmark( &format!("Natural.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, natural_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_natural_library_comparison< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Natural)", T::NAME), BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_natural_library_comparison< T: PartialOrd + PartialOrd + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Natural)", T::NAME), BenchmarkType::LibraryComparison, natural_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_2_pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{ natural_primitive_float_pair_gen, natural_primitive_float_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_partial_eq_float); register_primitive_float_demos!(runner, demo_float_partial_eq_natural); register_primitive_float_benches!( runner, benchmark_natural_partial_eq_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_eq_natural_library_comparison ); } fn demo_natural_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialEq, { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n == f { println!("{} = {}", n, NiceFloat(f)); } else { println!("{} ≠ {}", n, NiceFloat(f)); } } } fn demo_float_partial_eq_natural + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in natural_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if f == n { println!("{} = {}", NiceFloat(f), n); } else { println!("{} ≠ {}", NiceFloat(f), n); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Natural == {}", T::NAME), BenchmarkType::LibraryComparison, natural_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_eq_natural_library_comparison< T: PartialEq + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Natural", T::NAME), BenchmarkType::LibraryComparison, natural_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_1_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_signed_pair_gen, natural_signed_pair_gen_rm, natural_unsigned_pair_gen, natural_unsigned_pair_gen_nrm, natural_unsigned_pair_gen_rm, }; use malachite_nz::test_util::natural::comparison::partial_eq_primitive_int::num_partial_eq_unsigned; use num::BigUint; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_partial_eq_unsigned); register_signed_demos!(runner, demo_natural_partial_eq_signed); register_unsigned_demos!(runner, demo_unsigned_partial_eq_natural); register_signed_demos!(runner, demo_signed_partial_eq_natural); register_unsigned_benches!( runner, benchmark_natural_partial_eq_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_natural_partial_eq_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_eq_natural_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_eq_natural_library_comparison ); } fn demo_natural_partial_eq_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PartialEq, { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if n == u { println!("{n} = {u}"); } else { println!("{n} ≠ {u}"); } } } fn demo_natural_partial_eq_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: PartialEq, { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if n == i { println!("{n} = {i}"); } else { println!("{n} ≠ {i}"); } } } fn demo_unsigned_partial_eq_natural + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in natural_unsigned_pair_gen::().get(gm, config).take(limit) { if u == n { println!("{u} = {n}"); } else { println!("{u} ≠ {n}"); } } } fn demo_signed_partial_eq_natural + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in natural_signed_pair_gen::().get(gm, config).take(limit) { if i == n { println!("{i} = {n}"); } else { println!("{i} ≠ {n}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_eq_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where BigUint: From, Natural: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Natural == {}", T::NAME), BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_nrm::().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x == y)), ("num", &mut |((x, y), _, _)| { no_out!(num_partial_eq_unsigned(&x, y)); }), ("rug", &mut |(_, (x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_eq_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PartialEq, rug::Integer: PartialEq, { run_benchmark( &format!("Natural == {}", T::NAME), BenchmarkType::LibraryComparison, natural_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_unsigned_partial_eq_natural_library_comparison< T: PartialEq + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Natural", T::NAME), BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_signed_partial_eq_natural_library_comparison< T: PartialEq + PartialEq + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Natural", T::NAME), BenchmarkType::LibraryComparison, natural_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ triple_3_natural_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_nrm, natural_pair_gen, natural_pair_gen_nrm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_clone); register_demo!(runner, demo_natural_clone_from); register_bench!(runner, benchmark_natural_clone_library_comparison); register_bench!(runner, benchmark_natural_clone_from_library_comparison); } fn demo_natural_clone(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("clone({}) = {}", n, n.clone()); } } fn demo_natural_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } #[allow(clippy::redundant_clone, unused_must_use)] fn benchmark_natural_clone_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.clone()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.clone())), ("num", &mut |(n, _, _)| no_out!(n.clone())), ("rug", &mut |(_, n, _)| no_out!(n.clone())), ], ); } fn benchmark_natural_clone_from_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.clone_from(&Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (mut x, y))| x.clone_from(&y)), ("num", &mut |((mut x, y), _, _)| x.clone_from(&y)), ("rug", &mut |(_, (mut x, y), _)| x.clone_from(&y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/from_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, PowerOf2Digits, SaturatingFrom, WrappingFrom, }; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_1_vec_len_times_pair_2_bits_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_5, unsigned_vec_unsigned_pair_gen_var_12, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::digits::general_digits::{ from_digits_asc_large, from_digits_asc_limb, from_digits_desc_basecase, from_digits_desc_large, from_digits_desc_limb, from_digits_desc_naive, from_digits_desc_naive_primitive, limbs_from_digits_small_base, limbs_from_digits_small_base_basecase, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::pair_1_vec_len_times_pair_2_natural_bits_bucketer; use malachite_nz::test_util::generators::{ natural_vec_natural_pair_gen_var_1, natural_vec_natural_pair_gen_var_2, natural_vec_natural_pair_gen_var_3, natural_vec_natural_pair_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_limbs_from_digits_small_base_basecase); register_unsigned_demos!(runner, demo_limbs_from_digits_small_base_basecase_targeted); register_unsigned_demos!(runner, demo_limbs_from_digits_small_base); register_unsigned_demos!(runner, demo_limbs_from_digits_small_base_targeted); register_unsigned_demos!(runner, demo_from_digits_desc_basecase); register_unsigned_demos!(runner, demo_from_digits_desc_basecase_targeted); register_unsigned_demos!(runner, demo_from_digits_asc_limb); register_unsigned_demos!(runner, demo_from_digits_desc_limb); register_unsigned_demos!(runner, demo_from_digits_asc_limb_targeted); register_unsigned_demos!(runner, demo_from_digits_desc_limb_targeted); register_demo!(runner, demo_from_digits_asc_large); register_demo!(runner, demo_from_digits_desc_large); register_demo!(runner, demo_from_digits_asc_large_targeted); register_demo!(runner, demo_from_digits_desc_large_targeted); register_unsigned_demos!(runner, demo_from_digits_asc_unsigned); register_unsigned_demos!(runner, demo_from_digits_desc_unsigned); register_unsigned_demos!(runner, demo_from_digits_asc_unsigned_targeted); register_unsigned_demos!(runner, demo_from_digits_desc_unsigned_targeted); register_demo!(runner, demo_from_digits_asc); register_demo!(runner, demo_from_digits_desc); register_demo!(runner, demo_from_digits_asc_targeted); register_demo!(runner, demo_from_digits_desc_targeted); register_unsigned_benches!( runner, benchmark_limbs_from_digits_small_base_basecase_algorithms ); register_unsigned_benches!(runner, benchmark_limbs_from_digits_small_base_algorithms); register_unsigned_benches!(runner, benchmark_from_digits_desc_basecase_algorithms); register_unsigned_benches!(runner, benchmark_from_digits_asc_limb); register_unsigned_benches!(runner, benchmark_from_digits_desc_limb_algorithms); register_bench!(runner, benchmark_from_digits_asc_large); register_bench!(runner, benchmark_from_digits_desc_large_algorithms); register_unsigned_benches!(runner, benchmark_from_digits_asc_unsigned); register_unsigned_benches!(runner, benchmark_from_digits_desc_unsigned_algorithms); register_bench!(runner, benchmark_from_digits_asc); register_bench!(runner, benchmark_from_digits_desc_algorithms); } fn demo_limbs_from_digits_small_base_basecase( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: WrappingFrom, { for (mut out, xs, base) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_from_digits_small_base_basecase(&mut out, &xs, base); println!( "out := {old_out:?}; \ limbs_from_digits_small_base_basecase(&mut out, {xs:?}, {base}) = {out_len:?}; \ out = {out:?}", ); } } fn demo_limbs_from_digits_small_base_basecase_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: WrappingFrom, { for (mut out, xs, base) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_from_digits_small_base_basecase(&mut out, &xs, base).unwrap(); println!( "out := {old_out:?}; \ limbs_from_digits_small_base_basecase(&mut out, {xs:?}, {base}) = {out_len}; \ out = {out:?}", ); } } fn demo_limbs_from_digits_small_base( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: WrappingFrom, { for (mut out, xs, base) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_from_digits_small_base(&mut out, &xs, base); println!( "out := {old_out:?}; \ limbs_from_digits_small_base(&mut out, {xs:?}, {base}) = {out_len:?}; out = {out:?}", ); } } fn demo_limbs_from_digits_small_base_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: WrappingFrom, { for (mut out, xs, base) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_from_digits_small_base(&mut out, &xs, base).unwrap(); println!( "out := {old_out:?}; \ limbs_from_digits_small_base(&mut out, {xs:?}, {base}) = {out_len}; \ out = {out:?}", ); } } fn demo_from_digits_desc_basecase + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom + WrappingFrom, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "from_digits_desc_basecase(&{:?}, {}) = {:?}", xs, base, from_digits_desc_basecase(&xs, base) ); } } fn demo_from_digits_desc_basecase_targeted + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom + WrappingFrom, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "from_digits_desc_basecase(&{:?}, {}) = {}", xs, base, from_digits_desc_basecase(&xs, base).unwrap() ); } } fn demo_from_digits_asc_limb + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "from_digits_asc_limb(&{:?}, {}) = {:?}", xs.clone(), base, from_digits_asc_limb(xs.into_iter(), base) ); } } fn demo_from_digits_desc_limb + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "from_digits_desc_limb(&{:?}, {}) = {:?}", xs.clone(), base, from_digits_desc_limb(xs.into_iter(), base) ); } } fn demo_from_digits_asc_limb_targeted + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "from_digits_asc_limb(&{:?}, {}) = {}", xs.clone(), base, from_digits_asc_limb(xs.into_iter(), base).unwrap() ); } } fn demo_from_digits_desc_limb_targeted + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "from_digits_desc_limb(&{:?}, {}) = {}", xs.clone(), base, from_digits_desc_limb(xs.into_iter(), base).unwrap() ); } } fn demo_from_digits_asc_large(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "from_digits_asc_large(&{:?}, {}) = {:?}", xs.clone(), base, from_digits_asc_large(xs.into_iter(), &base) ); } } fn demo_from_digits_desc_large(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "from_digits_desc_large(&{:?}, {}) = {:?}", xs.clone(), base, from_digits_desc_large(xs.into_iter(), &base) ); } } fn demo_from_digits_asc_large_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "from_digits_asc_large(&{:?}, {}) = {}", xs.clone(), base, from_digits_asc_large(xs.into_iter(), &base).unwrap() ); } } fn demo_from_digits_desc_large_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "from_digits_desc_large(&{:?}, {}) = {}", xs.clone(), base, from_digits_desc_large(xs.into_iter(), &base).unwrap() ); } } fn demo_from_digits_asc_unsigned + WrappingFrom>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom, Natural: Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "Natural::from_digits_asc({}, &{:?}) = {:?}", base, xs.clone(), Natural::from_digits_asc(&base, xs.into_iter()) ); } } fn demo_from_digits_desc_unsigned + WrappingFrom>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom, Natural: Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "Natural::from_digits_desc({}, &{:?}) = {:?}", base, xs.clone(), Natural::from_digits_desc(&base, xs.into_iter()) ); } } fn demo_from_digits_asc_unsigned_targeted< T: PrimitiveUnsigned + SaturatingFrom + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom, Natural: Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "Natural::from_digits_asc({}, &{:?}) = {}", base, xs.clone(), Natural::from_digits_asc(&base, xs.into_iter()).unwrap() ); } } fn demo_from_digits_desc_unsigned_targeted< T: PrimitiveUnsigned + SaturatingFrom + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom, Natural: Digits, { for (xs, base) in unsigned_vec_unsigned_pair_gen_var_5::() .get(gm, config) .take(limit) { println!( "Natural::from_digits_desc({}, &{:?}) = {}", base, xs.clone(), Natural::from_digits_desc(&base, xs.into_iter()).unwrap() ); } } fn demo_from_digits_asc(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "Natural::from_digits_asc({}, &{:?}) = {:?}", base, xs.clone(), Natural::from_digits_asc(&base, xs.into_iter()) ); } } fn demo_from_digits_desc(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "Natural::from_digits_desc({}, &{:?}) = {:?}", base, xs.clone(), Natural::from_digits_desc(&base, xs.into_iter()) ); } } fn demo_from_digits_asc_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Natural::from_digits_asc({}, &{:?}) = {}", base, xs.clone(), Natural::from_digits_asc(&base, xs.into_iter()).unwrap() ); } } fn demo_from_digits_desc_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, base) in natural_vec_natural_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Natural::from_digits_desc({}, &{:?}) = {}", base, xs.clone(), Natural::from_digits_desc(&base, xs.into_iter()).unwrap() ); } } fn benchmark_limbs_from_digits_small_base_basecase_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: WrappingFrom, Natural: From, { run_benchmark( &format!( "limbs_from_digits_small_base_basecase(&mut [Limb], &[{}], u64)", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, xs, base)| { no_out!(limbs_from_digits_small_base_basecase(&mut out, &xs, base).unwrap()); }), ("naive", &mut |(_, xs, base)| { from_digits_desc_naive_primitive(&xs, T::exact_from(base)) .unwrap() .into_limbs_asc(); }), ], ); } fn benchmark_limbs_from_digits_small_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: WrappingFrom, Natural: From, { run_benchmark( &format!( "limbs_from_digits_small_base(&mut [Limb], &[{}], u64)", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [ ("full", &mut |(mut out, xs, base)| { no_out!(limbs_from_digits_small_base(&mut out, &xs, base)); }), ("basecase", &mut |(mut out, xs, base)| { no_out!(limbs_from_digits_small_base_basecase(&mut out, &xs, base)); }), ], ); } fn benchmark_from_digits_desc_basecase_algorithms + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: SaturatingFrom + WrappingFrom, Natural: From, { run_benchmark( &format!("from_digits_desc_basecase(&[{}], u64)", T::NAME), BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("default", &mut |(xs, base)| { no_out!(from_digits_desc_basecase(&xs, base).unwrap()); }), ("naive", &mut |(xs, base)| { from_digits_desc_naive_primitive(&xs, T::exact_from(base)) .unwrap() .into_limbs_asc(); }), ], ); } fn benchmark_from_digits_asc_limb + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { run_benchmark( &format!("from_digits_asc_limb(&[{}], Limb)", T::NAME), BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_bits_bucketer("xs", "base"), &mut [("Malachite", &mut |(xs, base)| { no_out!(from_digits_asc_limb(xs.into_iter(), base)); })], ); } fn benchmark_from_digits_desc_limb_algorithms + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { run_benchmark( &format!("from_digits_desc_limb(&[{}], Limb)", T::NAME), BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_bits_bucketer("xs", "base"), &mut [ ("full", &mut |(xs, base)| { no_out!(from_digits_desc_limb(xs.into_iter(), base)); }), ("basecase", &mut |(xs, base)| { no_out!(from_digits_desc_basecase(&xs, base)); }), ], ); } fn benchmark_from_digits_asc_large(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "from_digits_asc_large(&[Natural], Natural)", BenchmarkType::Single, natural_vec_natural_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_natural_bits_bucketer("xs", "base"), &mut [("Malachite", &mut |(xs, base)| { no_out!(from_digits_desc_large(xs.into_iter(), &base)); })], ); } fn benchmark_from_digits_desc_large_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "from_digits_desc_large(&[Natural], Natural)", BenchmarkType::Algorithms, natural_vec_natural_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_natural_bits_bucketer("xs", "base"), &mut [ ("large", &mut |(xs, base)| { no_out!(from_digits_desc_large(xs.into_iter(), &base)); }), ("naive", &mut |(xs, base)| { no_out!(from_digits_desc_naive(&xs, &base)); }), ], ); } fn benchmark_from_digits_asc_unsigned + WrappingFrom>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Digits, { run_benchmark( &format!( "Natural::from_digits_asc({}, Iterator)", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, base)| { no_out!(Natural::from_digits_asc(&base, xs.into_iter())); })], ); } fn benchmark_from_digits_desc_unsigned_algorithms< T: PrimitiveUnsigned + SaturatingFrom + WrappingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Digits + From, { run_benchmark( &format!( "Natural::from_digits_desc({}, Iterator)", T::NAME, T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("default", &mut |(xs, base)| { no_out!(Natural::from_digits_desc(&base, xs.into_iter())); }), ("naive", &mut |(xs, base)| { from_digits_desc_naive_primitive(&xs, T::exact_from(base)); }), ], ); } fn benchmark_from_digits_asc(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural::from_digits_asc(&Natural, Iterator)", BenchmarkType::Single, natural_vec_natural_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_natural_bits_bucketer("xs", "base"), &mut [("Malachite", &mut |(xs, base)| { no_out!(Natural::from_digits_asc(&base, xs.into_iter())); })], ); } fn benchmark_from_digits_desc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_digits_desc(&Natural, Iterator)", BenchmarkType::Algorithms, natural_vec_natural_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_natural_bits_bucketer("xs", "base"), &mut [ ("default", &mut |(xs, base)| { no_out!(Natural::from_digits_desc(&base, xs.into_iter())); }), ("naive", &mut |(xs, base)| { from_digits_desc_naive(&xs, &base); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_10, unsigned_vec_unsigned_pair_gen_var_11, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_vec_len_times_pair_2_bucketer; use malachite_nz::test_util::generators::{ natural_vec_unsigned_pair_gen_var_1, natural_vec_unsigned_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_from_power_of_2_digits_asc); register_unsigned_demos!(runner, demo_from_power_of_2_digits_desc); register_unsigned_demos!(runner, demo_from_power_of_2_digits_asc_targeted); register_unsigned_demos!(runner, demo_from_power_of_2_digits_desc_targeted); register_demo!(runner, demo_natural_from_power_of_2_digits_asc_natural); register_demo!(runner, demo_natural_from_power_of_2_digits_desc_natural); register_demo!( runner, demo_natural_from_power_of_2_digits_asc_natural_targeted ); register_demo!( runner, demo_natural_from_power_of_2_digits_desc_natural_targeted ); register_unsigned_benches!(runner, benchmark_from_power_of_2_digits_asc_algorithms); register_unsigned_benches!(runner, benchmark_from_power_of_2_digits_desc); register_bench!( runner, benchmark_natural_from_power_of_2_digits_asc_natural_algorithms ); register_bench!( runner, benchmark_natural_from_power_of_2_digits_desc_natural ); } fn demo_from_power_of_2_digits_asc( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (digits, log_base) in unsigned_vec_unsigned_pair_gen_var_11::() .get(gm, config) .take(limit) { println!( "Natural::from_power_of_2_digits_asc({}, {:?}) = {:?}", log_base, digits, Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()) ); } } fn demo_from_power_of_2_digits_desc( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (digits, log_base) in unsigned_vec_unsigned_pair_gen_var_11::() .get(gm, config) .take(limit) { println!( "Natural::from_power_of_2_digits_desc({}, {:?}) = {:?}", log_base, digits, Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()) ); } } fn demo_from_power_of_2_digits_asc_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (digits, log_base) in unsigned_vec_unsigned_pair_gen_var_10::() .get(gm, config) .take(limit) { println!( "Natural::from_power_of_2_digits_asc({}, {:?}) = {}", log_base, digits, Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap() ); } } fn demo_from_power_of_2_digits_desc_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (digits, log_base) in unsigned_vec_unsigned_pair_gen_var_10::() .get(gm, config) .take(limit) { println!( "Natural::from_power_of_2_digits_desc({}, {:?}) = {}", log_base, digits, Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap() ); } } fn demo_natural_from_power_of_2_digits_asc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (digits, log_base) in natural_vec_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Natural.from_power_of_2_digits_asc({}, {:?}) = {:?}", log_base, digits, Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()) ); } } fn demo_natural_from_power_of_2_digits_desc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (digits, log_base) in natural_vec_unsigned_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Natural.from_power_of_2_digits_desc({}, {:?}) = {:?}", log_base, digits, Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()) ); } } fn demo_natural_from_power_of_2_digits_asc_natural_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (digits, log_base) in natural_vec_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural.from_power_of_2_digits_asc({}, {:?}) = {}", log_base, digits, Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()).unwrap() ); } } fn demo_natural_from_power_of_2_digits_desc_natural_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (digits, log_base) in natural_vec_unsigned_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural.from_power_of_2_digits_desc({}, {:?}) = {}", log_base, digits, Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()).unwrap() ); } } fn benchmark_from_power_of_2_digits_asc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: From + PowerOf2Digits, { run_benchmark( &format!( "PowerOf2Digits::::from_power_of_2_digits_asc\ >(I, u64)", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("digits"), &mut [ ("default", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_asc( log_base, digits.into_iter() )); }), ("naive", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_asc_naive( log_base, digits.into_iter() )); }), ], ); } fn benchmark_from_power_of_2_digits_desc( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PowerOf2Digits, { run_benchmark( &format!( "PowerOf2Digits::::from_power_of_2_digits_desc\ >(I, u64)", T::NAME ), BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_10::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("digits"), &mut [("Malachite", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_desc( log_base, digits.into_iter() )); })], ); } fn benchmark_natural_from_power_of_2_digits_asc_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_power_of_2_digits_asc>(u64, I)", BenchmarkType::Algorithms, natural_vec_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_bucketer("digits", "log_base"), &mut [ ("default", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_asc( log_base, digits.into_iter() )); }), ("naive", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_asc_natural_naive( log_base, digits.into_iter() )); }), ], ); } fn benchmark_natural_from_power_of_2_digits_desc_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_power_of_2_digits_desc>(u64, I)", BenchmarkType::Single, natural_vec_unsigned_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_times_pair_2_bucketer("digits", "log_base"), &mut [("Malachite", &mut |(digits, log_base)| { no_out!(Natural::from_power_of_2_digits_desc( log_base, digits.into_iter() )); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_digits::register(runner); from_power_of_2_digits::register(runner); power_of_2_digits::register(runner); to_digits::register(runner); to_power_of_2_digits::register(runner); } mod from_digits; mod from_power_of_2_digits; mod power_of_2_digits; mod to_digits; mod to_power_of_2_digits; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, PowerOf2Digits, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ pair_1_natural_bit_bucketer, triple_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_6, natural_unsigned_pair_gen_var_7, natural_unsigned_unsigned_triple_gen_var_2, natural_unsigned_unsigned_triple_gen_var_3, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_power_of_2_digits); register_unsigned_demos!(runner, demo_natural_power_of_2_digits_rev); register_unsigned_demos!(runner, demo_natural_power_of_2_digits_size_hint); register_unsigned_demos!(runner, demo_natural_power_of_2_digits_get_digit); register_demo!(runner, demo_natural_power_of_2_digits_natural); register_demo!(runner, demo_natural_power_of_2_digits_rev_natural); register_demo!(runner, demo_natural_power_of_2_digits_size_hint_natural); register_demo!(runner, demo_natural_power_of_2_digits_get_digit_natural); register_unsigned_benches!(runner, benchmark_natural_power_of_2_digits_size_hint); register_unsigned_benches!( runner, benchmark_natural_power_of_2_digits_get_digit_algorithms ); register_bench!( runner, benchmark_natural_power_of_2_digits_size_hint_natural ); register_bench!( runner, benchmark_natural_power_of_2_digits_get_digit_natural_algorithms ); } fn demo_natural_power_of_2_digits( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: PowerOf2DigitIterable, { for (n, log_base) in natural_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}) = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).collect_vec() ); } } fn demo_natural_power_of_2_digits_rev( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: PowerOf2DigitIterable, { for (n, log_base) in natural_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).rev() = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base) .rev() .collect_vec() ); } } fn demo_natural_power_of_2_digits_size_hint( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: PowerOf2DigitIterable, { for (n, log_base) in natural_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).size_hint() = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).size_hint() ); } } fn demo_natural_power_of_2_digits_get_digit( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: PowerOf2DigitIterable, { for (n, log_base, i) in natural_unsigned_unsigned_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).get_digit({}) = {:?}", n, log_base, i, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).get_digit(i) ); } } fn demo_natural_power_of_2_digits_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}) = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).collect_vec() ); } } fn demo_natural_power_of_2_digits_rev_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).rev() = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base) .rev() .collect_vec() ); } } fn demo_natural_power_of_2_digits_size_hint_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).size_hint() = {:?}", n, log_base, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).size_hint() ); } } fn demo_natural_power_of_2_digits_get_digit_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base, i) in natural_unsigned_unsigned_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "power_of_2_digits({}, {}).get_digit({}) = {:?}", n, log_base, i, PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).get_digit(i) ); } } fn benchmark_natural_power_of_2_digits_size_hint( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Natural: PowerOf2DigitIterable, { run_benchmark( &format!( "PowerOf2DigitIterable::<{}>::power_of_2_digits(&Natural, u64).size_hint()", T::NAME ), BenchmarkType::Single, natural_unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [( &format!( "PowerOf2DigitIterable::<{}>::power_of_2_digits(&Natural, u64).size_hint()", T::NAME ), &mut |(n, log_base)| { no_out!(PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).size_hint()); }, )], ); } fn benchmark_natural_power_of_2_digits_get_digit_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Natural: PowerOf2DigitIterable, Natural: PowerOf2Digits, { run_benchmark( &format!( "PowerOf2DigitIterable::<{}>::power_of_2_digits(&Natural, u64).get_digit(u64)", T::NAME ), BenchmarkType::Algorithms, natural_unsigned_unsigned_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( "power_of_2_digits(&Natural, u64).get_digit(u64)", &mut |(n, log_base, i)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).get_digit(i) ); }, ), ( "Natural.to_power_of_2_digits_asc(u64)[u64]", &mut |(n, log_base, i)| { let digits = PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base); let i = usize::exact_from(i); if i >= digits.len() { T::ZERO } else { digits[i] }; }, ), ], ); } fn benchmark_natural_power_of_2_digits_size_hint_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "PowerOf2DigitIterable::::power_of_2_digits(&Natural, u64).size_hint()", BenchmarkType::Single, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [( "PowerOf2DigitIterable::::power_of_2_digits(&Natural, u64).size_hint()", &mut |(n, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).size_hint() ); }, )], ); } #[allow(clippy::let_unit_value)] fn benchmark_natural_power_of_2_digits_get_digit_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "PowerOf2DigitIterable::::power_of_2_digits(&Natural, u64).get_digit(u64)", BenchmarkType::Algorithms, natural_unsigned_unsigned_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ( "power_of_2_digits(&Natural, u64).get_digit(u64)", &mut |(n, log_base, i)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base) .get_digit(i) ); }, ), ( "Natural.to_power_of_2_digits_asc(u64)[u64]", &mut |(n, log_base, i)| { let digits = PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base); let i = usize::exact_from(i); let _result = if i >= digits.len() { let _ = Natural::ZERO; } else { let _ = digits[i]; }; }, ), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/to_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, Digits, PowerOf2Digits, SaturatingFrom, }; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, quadruple_3_vec_len_bucketer, triple_3_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::digits::general_digits::{ limbs_to_digits_basecase, limbs_to_digits_small_base, limbs_to_digits_small_base_basecase, to_digits_asc_large, to_digits_asc_limb, to_digits_asc_naive, to_digits_asc_naive_primitive, to_digits_desc_large, to_digits_desc_limb, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::{ natural_bit_ratio_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_limbs_to_digits_small_base_basecase); register_unsigned_demos!(runner, demo_limbs_to_digits_small_base); register_unsigned_demos!(runner, demo_limbs_to_digits_basecase); register_unsigned_demos!(runner, demo_to_digits_asc_limb); register_unsigned_demos!(runner, demo_to_digits_desc_limb); register_demo!(runner, demo_to_digits_asc_large); register_demo!(runner, demo_to_digits_desc_large); register_unsigned_demos!(runner, demo_to_digits_asc); register_unsigned_demos!(runner, demo_to_digits_desc); register_demo!(runner, demo_to_digits_asc_natural); register_demo!(runner, demo_to_digits_desc_natural); register_unsigned_benches!( runner, benchmark_limbs_to_digits_small_base_basecase_algorithms ); register_unsigned_benches!( runner, benchmark_limbs_to_digits_small_base_basecase_algorithms_2 ); register_unsigned_benches!(runner, benchmark_limbs_to_digits_small_base_algorithms); register_unsigned_benches!(runner, benchmark_limbs_to_digits_basecase_algorithms); register_unsigned_benches!(runner, benchmark_to_digits_asc_limb); register_unsigned_benches!(runner, benchmark_to_digits_desc_limb); register_bench!(runner, benchmark_to_digits_asc_large); register_bench!(runner, benchmark_to_digits_desc_large); register_unsigned_benches!(runner, benchmark_to_digits_asc_algorithms); register_unsigned_benches!(runner, benchmark_to_digits_desc); register_bench!(runner, benchmark_to_digits_asc_natural_algorithms); register_bench!(runner, benchmark_to_digits_desc_natural); } fn demo_limbs_to_digits_small_base_basecase( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut out, len, xs, base) in unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_to_digits_small_base_basecase(&mut out, len, &xs, base); println!( "out := {old_out:?}; \ limbs_to_digits_small_base_basecase(&mut out, {len}, {xs:?}, {base}) = {out_len}; \ out = {out:?}", ); } } fn demo_limbs_to_digits_small_base( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut out, base, mut xs) in unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1::() .get(gm, config) .take(limit) { let old_out = out.to_vec(); let out_len = limbs_to_digits_small_base(&mut out, base, &mut xs, None); println!( "out := {old_out:?}; \ limbs_to_digits_small_base(&mut out, {base}, {xs:?}) = {out_len}; out = {out:?}", ); } } fn demo_limbs_to_digits_basecase + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: SaturatingFrom, { for (mut xs, base) in unsigned_vec_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let xs_old = xs.clone(); let mut digits = Vec::new(); limbs_to_digits_basecase::(&mut digits, &mut xs, base); println!( "limbs_to_digits_basecase(&mut digits, &{xs_old:?}, {base}); \ digits = {digits:?}" ); } } fn demo_to_digits_asc_limb< T: ConvertibleFrom + for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { for (x, base) in natural_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "to_digits_asc_limb({}, {}) = {:?}", x, base, to_digits_asc_limb::(&x, base) ); } } fn demo_to_digits_desc_limb< T: ConvertibleFrom + for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { for (x, base) in natural_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "to_digits_desc_limb({}, {}) = {:?}", x, base, to_digits_desc_limb::(&x, base) ); } } fn demo_to_digits_asc_large(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_pair_gen_var_1().get(gm, config).take(limit) { println!( "to_digits_asc_large({}, {}) = {:?}", x, base, to_digits_asc_large(&x, &base) ); } } fn demo_to_digits_desc_large(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_pair_gen_var_1().get(gm, config).take(limit) { println!( "to_digits_asc_large({}, {}) = {:?}", x, base, to_digits_desc_large(&x, &base) ); } } fn demo_to_digits_asc(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Digits, { for (x, base) in natural_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "to_digits_asc({}, {}) = {:?}", x, base, x.to_digits_asc(&base) ); } } fn demo_to_digits_desc(gm: GenMode, config: &GenConfig, limit: usize) where Natural: Digits, { for (x, base) in natural_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "to_digits_desc({}, {}) = {:?}", x, base, x.to_digits_desc(&base) ); } } fn demo_to_digits_asc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_pair_gen_var_2().get(gm, config).take(limit) { println!( "to_digits_asc({}, {}) = {:?}", x, base, x.to_digits_asc(&base) ); } } fn demo_to_digits_desc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_pair_gen_var_2().get(gm, config).take(limit) { println!( "to_digits_desc({}, {}) = {:?}", x, base, x.to_digits_desc(&base) ); } } fn benchmark_limbs_to_digits_small_base_basecase_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "limbs_to_digits_small_base_basecase(&mut [{}], usize, &[Limb], u64)", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut out, len, xs, base)| { no_out!(limbs_to_digits_small_base_basecase( &mut out, len, &xs, base )); }), ("naive", &mut |(_, _, xs, base)| { let mut digits = Vec::new(); to_digits_asc_naive_primitive( &mut digits, &Natural::from_owned_limbs_asc(xs), base, ); }), ], ); } fn benchmark_limbs_to_digits_small_base_basecase_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "limbs_to_digits_small_base_basecase(&mut [{}], usize, &[Limb], u64)", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &quadruple_3_vec_len_bucketer("xs"), &mut [ ("limbs_to_digits_small_base_basecase", &mut |( mut out, _, xs, base, )| { no_out!(limbs_to_digits_small_base_basecase(&mut out, 0, &xs, base)); }), ("limbs_to_digits_small_base", &mut |( mut out, _, mut xs, base, )| { no_out!(limbs_to_digits_small_base(&mut out, base, &mut xs, None)); }), ], ); } fn benchmark_limbs_to_digits_small_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "limbs_to_digits_small_base(&mut [{}], u64, &[Limb])", T::NAME ), BenchmarkType::Algorithms, unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_len_bucketer("xs"), &mut [ ("default", &mut |(mut out, base, mut xs)| { no_out!(limbs_to_digits_small_base(&mut out, base, &mut xs, None)); }), ("naive", &mut |(_, base, xs)| { let mut digits = Vec::new(); to_digits_asc_naive_primitive( &mut digits, &Natural::from_owned_limbs_asc(xs), base, ); }), ], ); } fn benchmark_limbs_to_digits_basecase_algorithms< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { run_benchmark( "limbs_to_digits_basecase(&mut [Limb], u64)", BenchmarkType::Algorithms, unsigned_vec_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [ ("basecase", &mut |(mut xs, base)| { let mut digits = Vec::new(); limbs_to_digits_basecase::(&mut digits, &mut xs, base); }), ("full", &mut |(xs, base)| { to_digits_asc_limb::(&Natural::from_owned_limbs_asc(xs), base); }), ], ); } fn benchmark_to_digits_asc_limb< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { run_benchmark( "to_digits_asc_limb(&Natural, Limb)", BenchmarkType::Single, natural_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base)| { to_digits_asc_limb::(&x, base); })], ); } fn benchmark_to_digits_desc_limb< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { run_benchmark( "to_digits_desc_limb(&Natural, Limb)", BenchmarkType::Single, natural_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base)| { to_digits_desc_limb::(&x, base); })], ); } fn benchmark_to_digits_asc_large(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "to_digits_asc_large(&Natural, &Natural)", BenchmarkType::Single, natural_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("x", "base"), &mut [("Malachite", &mut |(x, base)| { to_digits_asc_large(&x, &base); })], ); } fn benchmark_to_digits_desc_large(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "to_digits_desc_large(&Natural, &Natural)", BenchmarkType::Single, natural_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("x", "base"), &mut [("Malachite", &mut |(x, base)| { to_digits_desc_large(&x, &base); })], ); } fn benchmark_to_digits_asc_algorithms TryFrom<&'a Natural> + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Digits + From, { run_benchmark( &format!("Natural.to_digits_asc(&{})", T::NAME), BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, base)| { x.to_digits_asc(&base); }), ("naive", &mut |(x, base)| { let mut digits = Vec::new(); to_digits_asc_naive_primitive(&mut digits, &x, base); }), ], ); } fn benchmark_to_digits_desc( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: Digits, { run_benchmark( &format!("Natural.to_digits_desc(&{})", T::NAME), BenchmarkType::Single, natural_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base)| { x.to_digits_desc(&base); })], ); } fn benchmark_to_digits_asc_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "to_digits_asc::(&Natural, &Natural)", BenchmarkType::Algorithms, natural_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("x", "base"), &mut [ ("default", &mut |(x, base)| no_out!(x.to_digits_asc(&base))), ("naive", &mut |(x, base)| { let mut digits: Vec = Vec::new(); to_digits_asc_naive(&mut digits, &x, &base); }), ], ); } fn benchmark_to_digits_desc_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "to_digits_desc::(&Natural, &Natural)", BenchmarkType::Single, natural_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_ratio_bucketer("x", "base"), &mut [("Malachite", &mut |(x, base)| { no_out!(x.to_digits_desc(&base)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{PowerOf2DigitIterable, PowerOf2Digits}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_6, natural_unsigned_pair_gen_var_7, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_to_power_of_2_digits_asc); register_unsigned_demos!(runner, demo_to_power_of_2_digits_desc); register_demo!(runner, demo_natural_to_power_of_2_digits_asc_natural); register_demo!(runner, demo_natural_to_power_of_2_digits_desc_natural); register_unsigned_benches!(runner, benchmark_to_power_of_2_digits_asc_algorithms); register_unsigned_benches!( runner, benchmark_to_power_of_2_digits_asc_evaluation_strategy ); register_unsigned_benches!( runner, benchmark_to_power_of_2_digits_desc_evaluation_strategy ); register_bench!( runner, benchmark_natural_to_power_of_2_digits_asc_natural_algorithms ); register_bench!(runner, benchmark_natural_to_power_of_2_digits_desc_natural); } fn demo_to_power_of_2_digits_asc( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (n, log_base) in natural_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_asc({}) = {:?}", n, log_base, PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base) ); } } fn demo_to_power_of_2_digits_desc( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: PowerOf2Digits, { for (n, log_base) in natural_unsigned_pair_gen_var_6::() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_desc({}) = {:?}", n, log_base, PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base) ); } } fn demo_natural_to_power_of_2_digits_asc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_asc({}) = {:?}", n, log_base, PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base) ); } } fn demo_natural_to_power_of_2_digits_desc_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in natural_unsigned_pair_gen_var_7() .get(gm, config) .take(limit) { println!( "{}.to_power_of_2_digits_desc({}) = {:?}", n, log_base, PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base) ); } } fn benchmark_to_power_of_2_digits_asc_algorithms< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PowerOf2Digits, { run_benchmark( &format!( "PowerOf2Digits::<{}>::to_power_of_2_digits_asc(&Natural, u64)", T::NAME ), BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base)); }), ("naive", &mut |(n, log_base)| { no_out!(Natural::to_power_of_2_digits_asc_naive::(&n, log_base)); }), ("using iterator", &mut |(n, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).collect_vec() ); }), ], ); } fn benchmark_to_power_of_2_digits_asc_evaluation_strategy< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PowerOf2Digits, for<'a> &'a Natural: PowerOf2DigitIterable, { run_benchmark( &format!( "PowerOf2Digits::<{}>::to_power_of_2_digits_asc(&Natural, u64)", T::NAME ), BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base)); }), ( "Natural.power_of_2_digits(u64).collect_vec()", &mut |(n, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base).collect_vec() ); }, ), ], ); } fn benchmark_to_power_of_2_digits_desc_evaluation_strategy< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: PowerOf2Digits, for<'a> &'a Natural: PowerOf2DigitIterable, { run_benchmark( &format!( "PowerOf2Digits::<{}>::to_power_of_2_digits_desc(&Natural, u64)", T::NAME ), BenchmarkType::EvaluationStrategy, natural_unsigned_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base)); }), ( "Natural.power_of_2_digits(u64).rev().collect_vec()", &mut |(n, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base) .rev() .collect_vec() ); }, ), ], ); } fn benchmark_natural_to_power_of_2_digits_asc_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "PowerOf2Digits::::to_power_of_2_digits_asc(&Natural, u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_asc( &n, log_base )); }), ("naive", &mut |(n, log_base)| { no_out!(n.to_power_of_2_digits_asc_natural_naive(log_base)); }), ("using iterator", &mut |(n, log_base)| { no_out!( PowerOf2DigitIterable::::power_of_2_digits(&n, log_base) .rev() .collect_vec() ); }), ], ); } fn benchmark_natural_to_power_of_2_digits_desc_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "PowerOf2Digits::::to_power_of_2_digits_desc(&Natural, u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(n, log_base)| { no_out!(PowerOf2Digits::::to_power_of_2_digits_desc( &n, log_base )); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/floating_point_from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::primitive_float_from_natural::PrimitiveFloatFromNaturalError; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_3, natural_rounding_mode_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_rounding_from_natural); register_primitive_float_demos!(runner, demo_float_try_from_natural); register_primitive_float_demos!(runner, demo_float_exact_from_natural); register_primitive_float_demos!(runner, demo_float_convertible_from_natural); register_primitive_float_benches!(runner, benchmark_float_rounding_from_natural); register_primitive_float_benches!(runner, benchmark_float_try_from_natural); register_primitive_float_benches!(runner, benchmark_float_exact_from_natural); register_primitive_float_benches!(runner, benchmark_float_convertible_from_natural); } fn demo_float_rounding_from_natural< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat + for<'a> RoundingFrom<&'a Natural>, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in natural_rounding_mode_pair_gen_var_1::() .get(gm, config) .take(limit) { let (f, o) = T::rounding_from(&n, rm); println!( "{}::rounding_from(&{}, {}) = {:?}", T::NAME, n, rm, (NiceFloat(f), o) ); } } fn demo_float_try_from_natural< T: for<'a> TryFrom<&'a Natural, Error = PrimitiveFloatFromNaturalError> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { println!( "{}::try_from(&{}) = {:?}", T::NAME, n.clone(), T::try_from(&n).map(NiceFloat) ); } } fn demo_float_exact_from_natural ExactFrom<&'a Natural> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: TryFrom, { for n in natural_gen_var_3::().get(gm, config).take(limit) { println!( "{}::exact_from(&{}) = {}", T::NAME, n.clone(), NiceFloat(T::exact_from(&n)) ); } } fn demo_float_convertible_from_natural ConvertibleFrom<&'a Natural> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { if T::convertible_from(&n) { println!("{} is convertible to an {}", n, T::NAME); } else { println!("{} is not convertible to an {}", n, T::NAME); } } } fn benchmark_float_rounding_from_natural< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat + for<'a> RoundingFrom<&'a Natural>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::rounding_from(Natural, RoundingMode)", T::NAME), BenchmarkType::Single, natural_rounding_mode_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(n, rm)| { no_out!(T::rounding_from(&n, rm)); })], ); } fn benchmark_float_try_from_natural TryFrom<&'a Natural> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(Natural)", T::NAME), BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::try_from(&n).ok()))], ); } fn benchmark_float_exact_from_natural ExactFrom<&'a Natural> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: TryFrom, { run_benchmark( &format!("{}::exact_from(Natural)", T::NAME), BenchmarkType::Single, natural_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } fn benchmark_float_convertible_from_natural< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(Natural)", T::NAME), BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::convertible_from(&n)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::bool_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_from_bool); } fn demo_natural_from_bool(gm: GenMode, config: &GenConfig, limit: usize) { for b in bool_gen().get(gm, config).take(limit) { println!("Natural::from({}) = {}", b, Natural::from(b)); } } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/from_floating_point.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_primitive_float_bucketer, primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_2, primitive_float_rounding_mode_pair_gen_var_1, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_rounding_from_float); register_primitive_float_demos!(runner, demo_natural_try_from_float); register_primitive_float_demos!(runner, demo_natural_exact_from_float); register_primitive_float_demos!(runner, demo_natural_convertible_from_float); register_primitive_float_benches!(runner, benchmark_natural_rounding_from_float); register_primitive_float_benches!(runner, benchmark_natural_try_from_float); register_primitive_float_benches!(runner, benchmark_natural_exact_from_float); register_primitive_float_benches!(runner, benchmark_natural_convertible_from_float_algorithms); } fn demo_natural_rounding_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: RoundingFrom, { for (f, rm) in primitive_float_rounding_mode_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "Natural::rounding_from({}, {}) = {:?}", NiceFloat(f), rm, Natural::rounding_from(f, rm) ); } } fn demo_natural_try_from_float(gm: GenMode, config: &GenConfig, limit: usize) where Natural: TryFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { println!( "Natural::try_from({}) = {:?}", NiceFloat(f), Natural::try_from(f) ); } } fn demo_natural_exact_from_float(gm: GenMode, config: &GenConfig, limit: usize) where Natural: ExactFrom, { for f in primitive_float_gen_var_2::().get(gm, config).take(limit) { println!( "Natural::exact_from({}) = {}", NiceFloat(f), Natural::exact_from(f) ); } } fn demo_natural_convertible_from_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ConvertibleFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { if Natural::convertible_from(f) { println!("{} is convertible to a Natural", NiceFloat(f)); } else { println!("{} is not convertible to a Natural", NiceFloat(f)); } } } fn benchmark_natural_rounding_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: RoundingFrom, { run_benchmark( &format!("Natural::rounding_from({}, RoundingMode)", T::NAME), BenchmarkType::Single, primitive_float_rounding_mode_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("f"), &mut [("Malachite", &mut |(f, rm)| { no_out!(Natural::rounding_from(f, rm)); })], ); } fn benchmark_natural_try_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: TryFrom, { run_benchmark( &format!("Natural::try_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Natural::try_from(f).ok()))], ); } fn benchmark_natural_exact_from_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ExactFrom, { run_benchmark( &format!("Natural::exact_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Natural::exact_from(f)))], ); } #[allow(unused_must_use)] fn benchmark_natural_convertible_from_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: TryFrom + ConvertibleFrom, { run_benchmark( &format!("Natural::convertible_from({})", T::NAME), BenchmarkType::Algorithms, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("standard", &mut |f| no_out!(Natural::convertible_from(f))), ("using try_from", &mut |f| { no_out!(Natural::try_from(f).is_ok()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/from_limbs.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_from_limbs_asc); register_demo!(runner, demo_natural_from_limbs_desc); register_demo!(runner, demo_natural_from_owned_limbs_asc); register_demo!(runner, demo_natural_from_owned_limbs_desc); register_bench!(runner, benchmark_natural_from_limbs_asc_evaluation_strategy); register_bench!( runner, benchmark_natural_from_limbs_desc_evaluation_strategy ); } fn demo_natural_from_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_limbs_asc({:?}) = {:?}", xs, Natural::from_limbs_asc(&xs) ); } } fn demo_natural_from_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_limbs_desc({:?}) = {:?}", xs, Natural::from_limbs_desc(&xs) ); } } fn demo_natural_from_owned_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_owned_limbs_asc({:?}) = {:?}", xs, Natural::from_owned_limbs_asc(xs.clone()) ); } } fn demo_natural_from_owned_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!( "from_owned_limbs_desc({:?}) = {:?}", xs, Natural::from_owned_limbs_desc(xs.clone()) ); } } fn benchmark_natural_from_limbs_asc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.from_limbs_asc(&[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("Natural::from_limbs_asc(&[u32])", &mut |ref xs| { no_out!(Natural::from_limbs_asc(xs)); }), ("Natural::from_owned_limbs_asc(&[u32])", &mut |xs| { no_out!(Natural::from_owned_limbs_asc(xs)); }), ], ); } fn benchmark_natural_from_limbs_desc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.from_limbs_desc(&[Limb])", BenchmarkType::EvaluationStrategy, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("Natural::from_limbs_desc(&[u32])", &mut |ref xs| { no_out!(Natural::from_limbs_desc(xs)); }), ("Natural::from_owned_limbs_desc(&[u32])", &mut |xs| { no_out!(Natural::from_owned_limbs_desc(xs)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, signed_gen_var_2, unsigned_gen}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::from_primitive_int::NaturalFromSignedError; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_natural_from_unsigned); register_signed_demos!(runner, demo_natural_try_from_signed); register_signed_demos!(runner, demo_natural_exact_from_signed); register_signed_demos!(runner, demo_natural_saturating_from_signed); register_signed_demos!(runner, demo_natural_convertible_from_signed); register_demo!(runner, demo_natural_const_from); register_unsigned_benches!(runner, benchmark_natural_from_unsigned); register_signed_benches!(runner, benchmark_natural_try_from_signed); register_signed_benches!(runner, benchmark_natural_exact_from_signed); register_signed_benches!(runner, benchmark_natural_saturating_from_signed); register_signed_benches!(runner, benchmark_natural_convertible_from_signed); register_bench!(runner, benchmark_natural_const_from); } fn demo_natural_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Natural: From, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("Natural::from({}) = {}", u, Natural::from(u)); } } fn demo_natural_try_from_signed(gm: GenMode, config: &GenConfig, limit: usize) where Natural: TryFrom, { for i in signed_gen::().get(gm, config).take(limit) { println!("Natural::try_from({}) = {:?}", i, Natural::try_from(i)); } } natural_signed_single_arg_demo_with_trait!( demo_natural_exact_from_signed, exact_from, signed_gen_var_2, ExactFrom ); natural_signed_single_arg_demo_with_trait!( demo_natural_saturating_from_signed, saturating_from, signed_gen, SaturatingFrom ); fn demo_natural_convertible_from_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ConvertibleFrom, { for i in signed_gen::().get(gm, config).take(limit) { println!( "{} is {}convertible to a Limb", i, if Natural::convertible_from(i) { "" } else { "not " }, ); } } fn demo_natural_const_from(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen().get(gm, config).take(limit) { println!("Natural::const_from({}) = {}", u, Natural::const_from(u)); } } #[allow(unused_must_use)] fn benchmark_natural_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: From, { run_benchmark( &format!("Natural::from({})", T::NAME), BenchmarkType::Single, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Natural::from(u)))], ); } fn benchmark_natural_try_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: TryFrom, { run_benchmark( &format!("Natural::try_from({})", T::NAME), BenchmarkType::Single, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |x| no_out!(Natural::try_from(x).ok()))], ); } natural_signed_single_arg_bench_with_trait!( benchmark_natural_exact_from_signed, exact_from, signed_gen_var_2, ExactFrom ); natural_signed_single_arg_bench_with_trait!( benchmark_natural_saturating_from_signed, saturating_from, signed_gen, SaturatingFrom ); natural_signed_single_arg_bench_with_trait!( benchmark_natural_convertible_from_signed, convertible_from, signed_gen, ConvertibleFrom ); fn benchmark_natural_const_from(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural::const_from(Limb)", BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Natural::const_from(u)))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/integer_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IntegerMantissaAndExponent; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen_var_2, natural_unsigned_pair_gen_var_4}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_integer_mantissa_and_exponent); register_demo!(runner, demo_natural_integer_mantissa); register_demo!(runner, demo_natural_integer_exponent); register_demo!(runner, demo_natural_from_integer_mantissa_and_exponent); register_bench!(runner, benchmark_natural_integer_mantissa_and_exponent); register_bench!(runner, benchmark_natural_integer_mantissa); register_bench!(runner, benchmark_natural_integer_exponent); register_bench!(runner, benchmark_natural_from_integer_mantissa_and_exponent); } fn demo_natural_integer_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!( "{}.integer_mantissa_and_exponent() = {:?}", n, n.integer_mantissa_and_exponent() ); } } fn demo_natural_integer_mantissa(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("{}.integer_mantissa() = {}", n, n.integer_mantissa()); } } fn demo_natural_integer_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("{}.integer_exponent() = {}", n, n.integer_exponent()); } } fn demo_natural_from_integer_mantissa_and_exponent(gm: GenMode, config: &GenConfig, limit: usize) { for (mantissa, exponent) in natural_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { let n = <&Natural as IntegerMantissaAndExponent::> ::from_integer_mantissa_and_exponent(mantissa.clone(), exponent); println!( "Natural::from_integer_mantissa_and_exponent({}, {}) = {}", mantissa, exponent, n.unwrap() ); } } fn benchmark_natural_integer_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.integer_mantissa_and_exponent()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |x| { no_out!(x.integer_mantissa_and_exponent()); })], ); } fn benchmark_natural_integer_mantissa( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.integer_mantissa()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.integer_mantissa()))], ); } fn benchmark_natural_integer_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.integer_exponent()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.integer_exponent()))], ); } fn benchmark_natural_from_integer_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_integer_mantissa_and_exponent(Natural, u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(mantissa, exponent)| { no_out!(<&Natural as IntegerMantissaAndExponent::< Natural, u64, Natural, >>::from_integer_mantissa_and_exponent( mantissa, exponent )); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_is_integer); register_bench!(runner, benchmark_natural_is_integer); } fn demo_natural_is_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.is_integer() { println!("{n} is an integer"); } else { println!("{n} is not an integer"); } } } fn benchmark_natural_is_integer(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.is_integer()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); digits::register(runner); floating_point_from_natural::register(runner); from_bool::register(runner); from_floating_point::register(runner); from_limbs::register(runner); from_primitive_int::register(runner); integer_mantissa_and_exponent::register(runner); is_integer::register(runner); primitive_int_from_natural::register(runner); sci_mantissa_and_exponent::register(runner); serde::register(runner); string::register(runner); to_limbs::register(runner); } mod clone; mod digits; mod floating_point_from_natural; mod from_bool; mod from_floating_point; mod from_limbs; mod from_primitive_int; mod integer_mantissa_and_exponent; mod is_integer; mod primitive_int_from_natural; mod sci_mantissa_and_exponent; mod serde; mod string; mod to_limbs; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/primitive_int_from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, OverflowingFrom, SaturatingFrom, WrappingFrom, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_rm, natural_gen_var_6, natural_gen_var_7, }; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_demos!(runner, demo_primitive_int_try_from_natural); register_unsigned_demos!(runner, demo_unsigned_exact_from_natural); register_signed_demos!(runner, demo_signed_exact_from_natural); register_primitive_int_demos!(runner, demo_primitive_int_wrapping_from_natural); register_primitive_int_demos!(runner, demo_primitive_int_saturating_from_natural); register_primitive_int_demos!(runner, demo_primitive_int_overflowing_from_natural); register_primitive_int_demos!(runner, demo_primitive_int_convertible_from_natural); register_primitive_int_benches!(runner, benchmark_primitive_int_try_from_natural_algorithms); register_unsigned_benches!(runner, benchmark_unsigned_exact_from_natural); register_signed_benches!(runner, benchmark_signed_exact_from_natural); register_primitive_int_benches!( runner, benchmark_primitive_int_wrapping_from_natural_algorithms ); register_primitive_int_benches!(runner, benchmark_primitive_int_saturating_from_natural); register_primitive_int_benches!( runner, benchmark_primitive_int_overflowing_from_natural_algorithms ); register_primitive_int_benches!( runner, benchmark_primitive_int_convertible_from_natural_algorithms ); register_bench!(runner, benchmark_u32_try_from_natural_library_comparison); register_bench!( runner, benchmark_u32_wrapping_from_natural_library_comparison ); register_bench!(runner, benchmark_u64_try_from_natural_library_comparison); register_bench!( runner, benchmark_u64_wrapping_from_natural_library_comparison ); register_bench!(runner, benchmark_i32_try_from_natural_library_comparison); register_bench!( runner, benchmark_i32_wrapping_from_natural_library_comparison ); register_bench!(runner, benchmark_i64_try_from_natural_library_comparison); register_bench!( runner, benchmark_i64_wrapping_from_natural_library_comparison ); } fn demo_primitive_int_try_from_natural TryFrom<&'a Natural> + PrimitiveInt>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> >::Error: Debug, { for n in natural_gen().get(gm, config).take(limit) { println!("{}::try_from(&{}) = {:?}", T::NAME, n, T::try_from(&n)); } } fn demo_unsigned_exact_from_natural ExactFrom<&'a Natural> + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: From, { for n in natural_gen_var_6::().get(gm, config).take(limit) { println!("{}::exact_from(&{}) = {}", T::NAME, n, T::exact_from(&n)); } } fn demo_signed_exact_from_natural ExactFrom<&'a Natural> + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) where Natural: ExactFrom, { for n in natural_gen_var_7::().get(gm, config).take(limit) { println!("{}::exact_from(&{}) = {}", T::NAME, n, T::exact_from(&n)); } } fn demo_primitive_int_wrapping_from_natural WrappingFrom<&'a Natural> + PrimitiveInt>( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { println!( "{}::wrapping_from(&{}) = {}", T::NAME, n, T::wrapping_from(&n) ); } } fn demo_primitive_int_saturating_from_natural< T: for<'a> SaturatingFrom<&'a Natural> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { println!( "{}::saturating_from(&{}) = {}", T::NAME, n, T::saturating_from(&n) ); } } fn demo_primitive_int_overflowing_from_natural< T: for<'a> OverflowingFrom<&'a Natural> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { println!( "{}::overflowing_from(&{}) = {:?}", T::NAME, n, T::overflowing_from(&n) ); } } fn demo_primitive_int_convertible_from_natural< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in natural_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", n, if T::convertible_from(&n) { "" } else { "not " }, T::NAME, ); } } fn benchmark_primitive_int_try_from_natural_algorithms< T: for<'a> TryFrom<&'a Natural> + for<'a> OverflowingFrom<&'a Natural> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(&Natural)", T::NAME), BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("standard", &mut |n| no_out!(T::try_from(&n).ok())), ("using overflowing_from", &mut |n| { let (value, overflow) = T::overflowing_from(&n); if overflow { None } else { Some(value) }; }), ], ); } fn benchmark_unsigned_exact_from_natural ExactFrom<&'a Natural> + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: From, { run_benchmark( &format!("{}::exact_from(&Natural)", T::NAME), BenchmarkType::Single, natural_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } fn benchmark_signed_exact_from_natural ExactFrom<&'a Natural> + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: ExactFrom, { run_benchmark( &format!("{}::exact_from(&Natural)", T::NAME), BenchmarkType::Single, natural_gen_var_7::().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::exact_from(&n)))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_primitive_int_wrapping_from_natural_algorithms< T: for<'a> OverflowingFrom<&'a Natural> + PrimitiveInt + for<'a> WrappingFrom<&'a Natural>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::wrapping_from(&Natural)", T::NAME), BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("standard", &mut |n| no_out!(T::wrapping_from(&n))), ("using overflowing_from", &mut |n| { T::overflowing_from(&n).0; }), ], ); } fn benchmark_primitive_int_saturating_from_natural< T: PrimitiveInt + for<'a> SaturatingFrom<&'a Natural>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::saturating_from(&Natural)", T::NAME), BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(T::saturating_from(&n)))], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_primitive_int_overflowing_from_natural_algorithms< T: for<'a> ConvertibleFrom<&'a Natural> + for<'a> OverflowingFrom<&'a Natural> + PrimitiveInt + for<'a> WrappingFrom<&'a Natural>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::overflowing_from(&Natural)", T::NAME), BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("standard", &mut |n| no_out!(T::overflowing_from(&n))), ("using wrapping_from and convertible_from", &mut |n| { no_out!((T::wrapping_from(&n), !T::convertible_from(&n))); }), ], ); } #[allow(unused_must_use)] fn benchmark_primitive_int_convertible_from_natural_algorithms< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Natural> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(&Natural)", T::NAME), BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("standard", &mut |n| no_out!(T::convertible_from(&n))), ("using try_from", &mut |n| no_out!(T::try_from(&n).is_ok())), ], ); } fn benchmark_u32_try_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32::try_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u32::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_u32())), ], ); } fn benchmark_u32_wrapping_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u32::wrapping_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u32::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_u32_wrapping())), ], ); } fn benchmark_u64_try_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64::try_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u64::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_u64())), ], ); } fn benchmark_u64_wrapping_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "u64::wrapping_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(u64::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_u64_wrapping())), ], ); } fn benchmark_i32_try_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i32::try_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i32::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_i32())), ], ); } fn benchmark_i32_wrapping_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i32::wrapping_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i32::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_i32_wrapping())), ], ); } fn benchmark_i64_try_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i64::try_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i64::try_from(&n).ok())), ("rug", &mut |(n, _)| no_out!(n.to_i64())), ], ); } fn benchmark_i64_wrapping_from_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "i64::wrapping_from(&Natural)", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(i64::wrapping_from(&n))), ("rug", &mut |(n, _)| no_out!(n.to_i64_wrapping())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::{ pair_1_primitive_float_bucketer, triple_1_primitive_float_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_unsigned_pair_gen_var_1, primitive_float_unsigned_pair_gen_var_2, primitive_float_unsigned_rounding_mode_triple_gen_var_1, primitive_float_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen_var_2, natural_rounding_mode_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_natural_sci_mantissa_and_exponent); register_primitive_float_demos!(runner, demo_natural_sci_mantissa); register_primitive_float_demos!(runner, demo_natural_sci_exponent); register_primitive_float_demos!(runner, demo_natural_sci_mantissa_and_exponent_round); register_primitive_float_demos!(runner, demo_natural_from_sci_mantissa_and_exponent); register_primitive_float_demos!(runner, demo_natural_from_sci_mantissa_and_exponent_targeted); register_primitive_float_demos!(runner, demo_natural_from_sci_mantissa_and_exponent_round); register_primitive_float_demos!( runner, demo_natural_from_sci_mantissa_and_exponent_round_targeted ); register_primitive_float_benches!(runner, benchmark_natural_sci_mantissa_and_exponent); register_primitive_float_benches!(runner, benchmark_natural_sci_mantissa_and_exponent_round); register_primitive_float_benches!(runner, benchmark_natural_from_sci_mantissa_and_exponent); register_primitive_float_benches!( runner, benchmark_natural_from_sci_mantissa_and_exponent_round ); } fn demo_natural_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: SciMantissaAndExponent, { for n in natural_gen_var_2().get(gm, config).take(limit) { let (mantissa, exponent) = n.sci_mantissa_and_exponent(); println!( "sci_mantissa_and_exponent({}) = {:?}", n, (NiceFloat(mantissa), exponent) ); } } fn demo_natural_sci_mantissa(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Natural: SciMantissaAndExponent, { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("sci_mantissa({}) = {}", n, NiceFloat(n.sci_mantissa())); } } fn demo_natural_sci_exponent(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Natural: SciMantissaAndExponent, { for n in natural_gen_var_2().get(gm, config).take(limit) { println!("sci_exponent({}) = {}", n, n.sci_exponent()); } } fn demo_natural_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in natural_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "sci_mantissa_and_exponent_round({}, {}) = {:?}", n, rm, n.sci_mantissa_and_exponent_round::(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)) ); } } fn demo_natural_from_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: SciMantissaAndExponent, { for (m, e) in primitive_float_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "Natural::from_sci_mantissa_and_exponent({}, {}) = {:?}", NiceFloat(m), e, <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) ); } } fn demo_natural_from_sci_mantissa_and_exponent_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Natural: SciMantissaAndExponent, { for (m, e) in primitive_float_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "Natural::from_sci_mantissa_and_exponent({}, {}) = {:?}", NiceFloat(m), e, <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) ); } } fn demo_natural_from_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (m, e, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_1::() .get(gm, config) .take(limit) { println!( "Natural::from_sci_mantissa_and_exponent_round({}, {}, {}) = {:?}", NiceFloat(m), e, rm, Natural::from_sci_mantissa_and_exponent_round(m, e, rm) ); } } fn demo_natural_from_sci_mantissa_and_exponent_round_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (m, e, rm) in primitive_float_unsigned_rounding_mode_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "Natural::from_sci_mantissa_and_exponent_round({}, {}, {}) = {:?}", NiceFloat(m), e, rm, Natural::from_sci_mantissa_and_exponent_round(m, e, rm) ); } } fn benchmark_natural_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Natural: SciMantissaAndExponent, { run_benchmark( "Natural.sci_mantissa_and_exponent()", BenchmarkType::Single, natural_gen_var_2().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.sci_mantissa_and_exponent()))], ); } fn benchmark_natural_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.sci_mantissa_and_exponent_round(RoundingMode)", BenchmarkType::Single, natural_rounding_mode_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(n, rm)| { no_out!(n.sci_mantissa_and_exponent_round::(rm)); })], ); } fn benchmark_natural_from_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Natural: SciMantissaAndExponent, { run_benchmark( &format!("Natural::from_sci_mantissa_and_exponent({}, u64)", T::NAME), BenchmarkType::Single, primitive_float_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(m, e)| { no_out!( <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) ); })], ); } fn benchmark_natural_from_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!( "Natural::from_sci_mantissa_and_exponent_round({}, u64, RoundingMode)", T::NAME ), BenchmarkType::Single, primitive_float_unsigned_rounding_mode_triple_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &triple_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(m, e, rm)| { no_out!(Natural::from_sci_mantissa_and_exponent_round(m, e, rm)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{string_gen, string_gen_var_8}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::{ natural_deserialize_bucketer, triple_3_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_nrm, string_triple_gen_var_1}; use num::BigUint; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_serialize_json); register_demo!(runner, demo_natural_deserialize_json); register_demo!(runner, demo_natural_deserialize_json_targeted); register_bench!(runner, benchmark_natural_serialize_json_library_comparison); register_bench!(runner, benchmark_natural_deserialize_json); register_bench!( runner, benchmark_natural_deserialize_json_library_comparison ); } fn demo_natural_serialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!( "serde_json::to_string({}) = {}", n, serde_json::to_string(&n).unwrap() ); } } fn demo_natural_deserialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { let n: Result = serde_json::from_str(&s); println!("serde_json::from_str({s}) = {n:?}"); } } fn demo_natural_deserialize_json_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_8().get(gm, config).take(limit) { let n: Natural = serde_json::from_str(&s).unwrap(); println!("serde_json::from_str({s}) = {n}"); } } fn benchmark_natural_serialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::to_string(&Natural)", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("num", &mut |(x, _, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("rug", &mut |(_, x, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ], ); } fn benchmark_natural_deserialize_json( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| { let _n: Natural = serde_json::from_str(&s).unwrap(); })], ); } fn benchmark_natural_deserialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::LibraryComparison, string_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &natural_deserialize_bucketer(), &mut [ ("Malachite", &mut |(_, _, s)| { let _n: Natural = serde_json::from_str(&s).unwrap(); }), ("num", &mut |(s, _, _)| { let _n: BigUint = serde_json::from_str(&s).unwrap(); }), ("rug", &mut |(_, s, _)| { let _n: rug::Integer = serde_json::from_str(&s).unwrap(); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::FromSciString; use malachite_base::test_util::bench::bucketers::{ pair_1_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_from_sci_string); register_demo!(runner, demo_natural_from_sci_string_targeted); register_demo!(runner, demo_natural_from_sci_string_with_options); register_demo!(runner, demo_natural_from_sci_string_with_options_targeted); register_bench!(runner, benchmark_natural_from_sci_string); register_bench!(runner, benchmark_natural_from_sci_string_with_options); } fn demo_natural_from_sci_string(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_14().get(gm, config).take(limit) { println!( "Natural::from_sci_string({}) = {:?}", s, Natural::from_sci_string(&s) ); } } fn demo_natural_from_sci_string_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_15().get(gm, config).take(limit) { println!( "Natural::from_sci_string({}) = {:?}", s, Natural::from_sci_string(&s) ); } } fn demo_natural_from_sci_string_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (s, options) in string_from_sci_string_options_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Natural::from_sci_string_with_options({}, {:?}) = {:?}", s, options, Natural::from_sci_string_with_options(&s, options) ); } } fn demo_natural_from_sci_string_with_options_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, options) in string_from_sci_string_options_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "Natural::from_sci_string_with_options({}, {:?}) = {:?}", s, options, Natural::from_sci_string_with_options(&s, options) ); } } fn benchmark_natural_from_sci_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_sci_string(&str)", BenchmarkType::Single, string_gen_var_15().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(Natural::from_sci_string(&s)))], ); } fn benchmark_natural_from_sci_string_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_sci_string_with_options(&str, FromSciStringOptions)", BenchmarkType::Single, string_from_sci_string_options_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_string_len_bucketer("s"), &mut [("Malachite", &mut |(s, options)| { no_out!(Natural::from_sci_string_with_options(&s, options)); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{FromStringBase, WrappingFrom}; use malachite_base::test_util::bench::bucketers::{ pair_2_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_gen, string_gen_var_3, string_gen_var_5, string_gen_var_6, string_gen_var_7, unsigned_string_pair_gen_var_1, unsigned_string_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::natural::conversion::string::from_string::from_string_base_naive; use num::{BigUint, Num}; use std::str::FromStr; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_from_str); register_demo!(runner, demo_natural_from_str_targeted); register_demo!(runner, demo_natural_from_string_base); register_demo!(runner, demo_natural_from_string_base_targeted); register_bench!(runner, benchmark_natural_from_str_library_comparison); register_bench!(runner, benchmark_natural_from_str_algorithms); register_bench!( runner, benchmark_natural_from_string_base_library_comparison ); register_bench!( runner, benchmark_natural_from_string_base_binary_library_comparison ); register_bench!( runner, benchmark_natural_from_string_base_octal_library_comparison ); register_bench!( runner, benchmark_natural_from_string_base_hex_library_comparison ); register_bench!(runner, benchmark_natural_from_string_base_algorithms); } fn demo_natural_from_string_base(gm: GenMode, config: &GenConfig, limit: usize) { for (base, s) in unsigned_string_pair_gen_var_2().get(gm, config).take(limit) { println!( "Natural::from_string_base({}, {}) = {:?}", base, s, Natural::from_string_base(base, &s) ); } } fn demo_natural_from_string_base_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for (base, s) in unsigned_string_pair_gen_var_1().get(gm, config).take(limit) { println!( "Natural::from_string_base({}, {}) = {}", base, s, Natural::from_string_base(base, &s).unwrap() ); } } fn demo_natural_from_str(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!("Natural::from_str({}) = {:?}", s, Natural::from_str(&s)); } } fn demo_natural_from_str_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_3().get(gm, config).take(limit) { println!( "Natural::from_str({}) = {}", s, Natural::from_str(&s).unwrap() ); } } fn benchmark_natural_from_str_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_str(&str)", BenchmarkType::LibraryComparison, string_gen_var_3().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Natural::from_str(&s).unwrap()); }), ("num", &mut |s| no_out!(BigUint::from_str(&s).unwrap())), ("rug", &mut |s| no_out!(rug::Integer::from_str(&s).unwrap())), ], ); } fn benchmark_natural_from_str_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_str(&str)", BenchmarkType::Algorithms, string_gen_var_3().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("default", &mut |s| no_out!(Natural::from_str(&s).unwrap())), ("naive", &mut |s| { no_out!(from_string_base_naive(10, &s).unwrap()); }), ], ); } fn benchmark_natural_from_string_base_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_string_base(u64, &str)", BenchmarkType::LibraryComparison, unsigned_string_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_2_string_len_bucketer("s"), &mut [ ("Malachite", &mut |(base, s)| { no_out!(Natural::from_string_base(base, &s).unwrap()); }), ("num", &mut |(base, s)| { no_out!(BigUint::from_str_radix(&s, u32::wrapping_from(base)).unwrap()); }), ("rug", &mut |(base, s)| { no_out!(rug::Integer::from_str_radix(&s, i32::wrapping_from(base)).unwrap()); }), ], ); } fn benchmark_natural_from_string_base_binary_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_string_base(2, &str)", BenchmarkType::LibraryComparison, string_gen_var_5().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Natural::from_string_base(2, &s).unwrap()); }), ("num", &mut |s| { no_out!(BigUint::from_str_radix(&s, 2).unwrap()); }), ("rug", &mut |s| { no_out!(rug::Integer::from_str_radix(&s, 2).unwrap()); }), ], ); } fn benchmark_natural_from_string_base_octal_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_string_base(8, &str)", BenchmarkType::LibraryComparison, string_gen_var_6().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Natural::from_string_base(8, &s).unwrap()); }), ("num", &mut |s| { no_out!(BigUint::from_str_radix(&s, 8).unwrap()); }), ("rug", &mut |s| { no_out!(rug::Integer::from_str_radix(&s, 8).unwrap()); }), ], ); } fn benchmark_natural_from_string_base_hex_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_string_base(16, &str)", BenchmarkType::LibraryComparison, string_gen_var_7().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Natural::from_string_base(16, &s).unwrap()); }), ("num", &mut |s| { no_out!(BigUint::from_str_radix(&s, 16).unwrap()); }), ("rug", &mut |s| { no_out!(rug::Integer::from_str_radix(&s, 16).unwrap()); }), ], ); } fn benchmark_natural_from_string_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_string_base(u8, &str)", BenchmarkType::Algorithms, unsigned_string_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_2_string_len_bucketer("s"), &mut [ ("default", &mut |(base, s)| { no_out!(Natural::from_string_base(base, &s).unwrap()); }), ("naive", &mut |(base, s)| { no_out!(from_string_base_naive(base, &s).unwrap()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/string/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sci_string::register(runner); from_string::register(runner); to_sci::register(runner); to_string::register(runner); } mod from_sci_string; mod from_string; mod to_sci; mod to_string; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ToSci; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_to_sci_options_pair_gen, natural_to_sci_options_pair_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_to_sci); register_demo!(runner, demo_natural_fmt_sci_valid); register_demo!(runner, demo_natural_to_sci_with_options); register_bench!(runner, benchmark_natural_to_sci); register_bench!(runner, benchmark_natural_fmt_sci_valid); register_bench!(runner, benchmark_natural_to_sci_with_options); } fn demo_natural_to_sci(gm: GenMode, config: &GenConfig, limit: usize) { for x in natural_gen().get(gm, config).take(limit) { println!("{}.to_sci() = {}", x, x.to_sci()); } } fn demo_natural_fmt_sci_valid(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in natural_to_sci_options_pair_gen() .get(gm, config) .take(limit) { if x.fmt_sci_valid(options) { println!("{x} can be converted to sci using {options:?}"); } else { println!("{x} cannot be converted to sci using {options:?}"); } } } fn demo_natural_to_sci_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in natural_to_sci_options_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "to_sci_with_options({}, {:?}) = {}", x, options, x.to_sci_with_options(options) ); } } fn benchmark_natural_to_sci(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.to_sci()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |x| no_out!(x.to_sci().to_string()))], ); } fn benchmark_natural_fmt_sci_valid(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.fmt_sci_valid(ToSciOptions)", BenchmarkType::Single, natural_to_sci_options_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.fmt_sci_valid(options)); })], ); } fn benchmark_natural_to_sci_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_sci_with_options(ToSciOptions)", BenchmarkType::Single, natural_to_sci_options_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.to_sci_with_options(options).to_string()); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ToStringBase, WrappingFrom}; use malachite_base::strings::{ToBinaryString, ToLowerHexString, ToOctalString, ToUpperHexString}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::conversion::string::to_string::{ BaseFmtWrapper, NaturalAlt, NaturalAlt2, }; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, triple_1_natural_bit_bucketer, triple_3_natural_bit_bucketer, triple_3_pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_nrm, natural_unsigned_pair_gen_var_3, natural_unsigned_pair_gen_var_3_nrm, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_triple_gen_var_1, }; use malachite_nz::test_util::natural::conversion::string::to_string::to_string_base_naive; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_to_string); register_demo!(runner, demo_natural_to_string_with_width); register_demo!(runner, demo_natural_to_binary_string); register_demo!(runner, demo_natural_to_binary_string_with_0b); register_demo!(runner, demo_natural_to_binary_string_with_width); register_demo!(runner, demo_natural_to_binary_string_with_0b_and_width); register_demo!(runner, demo_natural_to_octal_string); register_demo!(runner, demo_natural_to_octal_string_with_0o); register_demo!(runner, demo_natural_to_octal_string_with_width); register_demo!(runner, demo_natural_to_octal_string_with_0o_and_width); register_demo!(runner, demo_natural_to_lower_hex_string); register_demo!(runner, demo_natural_to_lower_hex_string_with_0x); register_demo!(runner, demo_natural_to_lower_hex_string_with_width); register_demo!(runner, demo_natural_to_lower_hex_string_with_0x_and_width); register_demo!(runner, demo_natural_to_upper_hex_string); register_demo!(runner, demo_natural_to_upper_hex_string_with_0x); register_demo!(runner, demo_natural_to_upper_hex_string_with_width); register_demo!(runner, demo_natural_to_upper_hex_string_with_0x_and_width); register_demo!(runner, demo_natural_to_string_base); register_demo!(runner, demo_natural_to_string_base_upper); register_demo!(runner, demo_natural_base_fmt_wrapper_fmt); register_demo!(runner, demo_natural_base_fmt_wrapper_fmt_upper); register_demo!(runner, demo_natural_base_fmt_wrapper_fmt_with_width); register_demo!(runner, demo_natural_base_fmt_wrapper_fmt_upper_with_width); register_bench!(runner, benchmark_natural_to_string_library_comparison); register_bench!(runner, benchmark_natural_to_string_algorithms); register_bench!(runner, benchmark_natural_to_string_with_width); register_bench!( runner, benchmark_natural_to_binary_string_library_comparison ); register_bench!(runner, benchmark_natural_to_binary_string_algorithms); register_bench!(runner, benchmark_natural_to_binary_string_with_width); register_bench!(runner, benchmark_natural_to_octal_string_library_comparison); register_bench!(runner, benchmark_natural_to_octal_string_algorithms); register_bench!(runner, benchmark_natural_to_octal_string_with_width); register_bench!( runner, benchmark_natural_to_lower_hex_string_library_comparison ); register_bench!(runner, benchmark_natural_to_lower_hex_string_algorithms); register_bench!(runner, benchmark_natural_to_lower_hex_string_with_width); register_bench!( runner, benchmark_natural_to_upper_hex_string_library_comparison ); register_bench!(runner, benchmark_natural_to_upper_hex_string_with_width); register_bench!(runner, benchmark_natural_to_string_base_library_comparison); register_bench!(runner, benchmark_natural_to_string_base_algorithms); register_bench!(runner, benchmark_natural_to_string_base_upper_algorithms); register_bench!(runner, benchmark_natural_base_fmt_wrapper_fmt_with_width); register_bench!( runner, benchmark_natural_base_fmt_wrapper_fmt_upper_with_width ); } fn demo_natural_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n}"); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", {}) = {}", width, n, format!("{n:0width$}") ); } } fn demo_natural_to_binary_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:b}"); } } fn demo_natural_to_binary_string_with_0b(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:#b}"); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_binary_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}b}}\", {}) = {}", width, n, format!("{n:0width$b}") ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_binary_string_with_0b_and_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}b}}\", {}) = {}", width, n, format!("{n:#0width$b}") ); } } fn demo_natural_to_octal_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:o}"); } } fn demo_natural_to_octal_string_with_0o(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:#o}"); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_octal_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}o}}\", {}) = {}", width, n, format!("{n:0width$o}") ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_octal_string_with_0o_and_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}o}}\", {}) = {}", width, n, format!("{n:#0width$o}") ); } } fn demo_natural_to_lower_hex_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:x}"); } } fn demo_natural_to_lower_hex_string_with_0x(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:#x}"); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_lower_hex_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}x}}\", {}) = {}", width, n, format!("{n:0width$x}") ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_lower_hex_string_with_0x_and_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}x}}\", {}) = {}", width, n, format!("{n:#0width$x}") ); } } fn demo_natural_to_upper_hex_string(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:X}"); } } fn demo_natural_to_upper_hex_string_with_0x(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{n:#X}"); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_upper_hex_string_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}X}}\", {}) = {}", width, n, format!("{n:0width$X}") ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_to_upper_hex_string_with_0x_and_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, width) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}X}}\", {}) = {}", width, n, format!("{n:#0width$X}") ); } } fn demo_natural_to_string_base(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "{}.to_string_base({}) = {}", x, base, x.to_string_base(base) ); } } fn demo_natural_to_string_base_upper(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "{}.to_string_base_upper({}) = {}", x, base, x.to_string_base_upper(base) ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_base_fmt_wrapper_fmt(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "format!(\"{{}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{}", BaseFmtWrapper::new(&x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_base_fmt_wrapper_fmt_upper(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base) in natural_unsigned_pair_gen_var_3() .get(gm, config) .take(limit) { println!( "format!(\"{{:#}}\", BaseFmtWrapper::new({}, {})) = {}", x, base, format!("{:#}", BaseFmtWrapper::new(&x, base)) ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_base_fmt_wrapper_fmt_with_width(gm: GenMode, config: &GenConfig, limit: usize) { for (x, base, width) in natural_unsigned_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{:0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:0width$}", BaseFmtWrapper::new(&x, base), width = width) ); } } #[allow(clippy::format_in_format_args)] fn demo_natural_base_fmt_wrapper_fmt_upper_with_width( gm: GenMode, config: &GenConfig, limit: usize, ) { for (x, base, width) in natural_unsigned_unsigned_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "format!(\"{{:#0{}}}\", BaseFmtWrapper::new({}, {})) = {}", width, x, base, format!("{:#0width$}", BaseFmtWrapper::new(&x, base), width = width) ); } } fn benchmark_natural_to_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_string()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_string())), ("num", &mut |(x, _, _)| no_out!(x.to_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_string())), ], ); } fn benchmark_natural_to_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_string()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(10))), ("naive", &mut |x| no_out!(to_string_base_naive(&x, 10))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usize}}\", Natural)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$}")); })], ); } fn benchmark_natural_to_binary_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_binary_string()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_binary_string())), ("num", &mut |(x, _, _)| no_out!(x.to_binary_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_binary_string())), ], ); } fn benchmark_natural_to_binary_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_binary_string()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_binary_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(2))), ("naive", &mut |x| no_out!(to_string_base_naive(&x, 2))), ("alt", &mut |x| no_out!(NaturalAlt(x).to_binary_string())), ("alt 2", &mut |x| no_out!(NaturalAlt2(x).to_binary_string())), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_binary_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeb}}\", Natural)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$b}")); })], ); } fn benchmark_natural_to_octal_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_octal_string()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_octal_string())), ("num", &mut |(x, _, _)| no_out!(x.to_octal_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_octal_string())), ], ); } fn benchmark_natural_to_octal_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_octal_string()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_octal_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(8))), ("naive", &mut |x| no_out!(to_string_base_naive(&x, 8))), ("alt", &mut |x| no_out!(NaturalAlt(x).to_octal_string())), ("alt 2", &mut |x| no_out!(NaturalAlt2(x).to_octal_string())), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_octal_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeo}}\", Natural)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$o}")); })], ); } fn benchmark_natural_to_lower_hex_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_lower_hex_string()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(x.to_lower_hex_string()); }), ("num", &mut |(x, _, _)| no_out!(x.to_lower_hex_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_lower_hex_string())), ], ); } fn benchmark_natural_to_lower_hex_string_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_lower_hex_string()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.to_lower_hex_string())), ("to_string_base", &mut |x| no_out!(x.to_string_base(16))), ("naive", &mut |x| no_out!(to_string_base_naive(&x, 16))), ("alt", &mut |x| no_out!(NaturalAlt(x).to_lower_hex_string())), ("alt 2", &mut |x| { no_out!(NaturalAlt2(x).to_lower_hex_string()); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_lower_hex_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizex}}\", Natural)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$x}")); })], ); } fn benchmark_natural_to_upper_hex_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_upper_hex_string()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(x.to_upper_hex_string()); }), ("num", &mut |(x, _, _)| no_out!(x.to_upper_hex_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_upper_hex_string())), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_upper_hex_string_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usizeX}}\", Natural)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, width)| { no_out!(format!("{x:0width$X}")); })], ); } fn benchmark_natural_to_string_base_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_string_base(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_3_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_natural_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, (x, base))| { no_out!(x.to_string_base(base)); }), ("num", &mut |((x, base), _, _)| { no_out!(x.to_str_radix(u32::wrapping_from(base))); }), ("rug", &mut |(_, (x, base), _)| { no_out!(x.to_string_radix(i32::wrapping_from(base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_string_base_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_string_base(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("default", &mut |(x, base)| no_out!(x.to_string_base(base))), ("using fmt", &mut |(x, base)| { no_out!(format!("{}", BaseFmtWrapper::new(&x, base))); }), ("naive", &mut |(x, base)| { no_out!(to_string_base_naive(&x, base)); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_to_string_base_upper_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_string_base_upper(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("to_string", &mut |(x, base)| { no_out!(x.to_string_base_upper(base)); }), ("using fmt", &mut |(x, base)| { no_out!(format!("{:#}", BaseFmtWrapper::new(&x, base))); }), ], ); } #[allow(unused_must_use)] fn benchmark_natural_base_fmt_wrapper_fmt_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:0usize}}\", BaseFmtWrapper::new(Natural, u64))", BenchmarkType::Single, natural_unsigned_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:0width$}", BaseFmtWrapper::new(&x, base), width = width )); })], ); } #[allow(unused_must_use)] fn benchmark_natural_base_fmt_wrapper_fmt_upper_with_width( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "format!(\"{{:#0usize}}\", BaseFmtWrapper::new(Natural, u64))", BenchmarkType::Single, natural_unsigned_unsigned_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("x"), &mut [("Malachite", &mut |(x, base, width)| { no_out!(format!( "{:#0width$}", BaseFmtWrapper::new(&x, base), width = width )); })], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/conversion/to_limbs.rs ================================================ // Copyright © 2026 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::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_to_limbs_asc); register_demo!(runner, demo_natural_to_limbs_desc); register_demo!(runner, demo_natural_into_limbs_asc); register_demo!(runner, demo_natural_into_limbs_desc); register_demo!(runner, demo_natural_as_limbs_asc); register_demo!(runner, demo_natural_limbs); register_demo!(runner, demo_natural_limbs_rev); register_demo!(runner, demo_natural_limbs_size_hint); register_demo!(runner, demo_natural_limbs_index); register_demo!(runner, demo_natural_limb_count); register_bench!(runner, benchmark_natural_limbs_evaluation_strategy); register_bench!(runner, benchmark_natural_limbs_rev_evaluation_strategy); register_bench!(runner, benchmark_natural_limbs_size_hint); register_bench!(runner, benchmark_natural_limbs_index_algorithms); register_bench!(runner, benchmark_natural_limb_count); } fn demo_natural_to_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("to_limbs_asc({}) = {:?}", n, n.to_limbs_asc()); } } fn demo_natural_to_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("to_limbs_desc({}) = {:?}", n, n.to_limbs_desc()); } } fn demo_natural_into_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("into_limbs_asc({}) = {:?}", n, n.clone().into_limbs_asc()); } } fn demo_natural_into_limbs_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("into_limbs_desc({}) = {:?}", n, n.clone().into_limbs_desc()); } } fn demo_natural_as_limbs_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("as_limbs_asc({}) = {:?}", n, n.as_limbs_asc()); } } fn demo_natural_limbs(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("limbs({}) = {:?}", n, n.limbs().collect_vec()); } } fn demo_natural_limbs_rev(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("limbs({}).rev() = {:?}", n, n.limbs().rev().collect_vec()); } } fn demo_natural_limbs_size_hint(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("limbs({}).size_hint() = {:?}", n, n.limbs().size_hint()); } } fn demo_natural_limbs_index(gm: GenMode, config: &GenConfig, limit: usize) { for (n, i) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!("limbs({})[{}] = {:?}", n, i, n.limbs()[i]); } } fn demo_natural_limb_count(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("limb_count({}) = {}", n, n.limb_count()); } } fn benchmark_natural_limbs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.limbs()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.to_limbs_asc()", &mut |n| no_out!(n.to_limbs_asc())), ("Natural.into_limbs_asc()", &mut |n| { no_out!(n.into_limbs_asc()); }), ("Natural.as_limbs_asc()", &mut |n| { no_out!(n.as_limbs_asc()); }), ("Natural.limbs().collect_vec()", &mut |n| { no_out!(n.limbs().collect_vec()); }), ], ); } fn benchmark_natural_limbs_rev_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.limbs().rev()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.to_limbs_desc()", &mut |n| { no_out!(n.to_limbs_desc()); }), ("Natural.into_limbs_desc()", &mut |n| { no_out!(n.into_limbs_desc()); }), ("Natural.limbs().rev().collect_vec()", &mut |n| { no_out!(n.limbs().rev().collect_vec()); }), ], ); } fn benchmark_natural_limbs_size_hint( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.limbs().size_hint()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Natural.limbs().size_hint()", &mut |n| { no_out!(n.limbs().size_hint()); })], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_limbs_index_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.limbs()[usize]", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("Natural.limbs()[u]", &mut |(n, u)| no_out!(n.limbs()[u])), ("Natural.into_limbs_asc()[u]", &mut |(n, u)| { let limbs = n.into_limbs_asc(); if u >= limbs.len() { 0 } else { limbs[u] }; }), ], ); } fn benchmark_natural_limb_count(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.limb_count()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.limb_count()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/factorization/is_power.rs ================================================ // Copyright © 2026 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 malachite_base::num::factorization::traits::{ExpressAsPower, IsPower}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_is_power); register_demo!(runner, demo_natural_express_as_power); register_bench!(runner, benchmark_natural_is_power_library_comparison); register_bench!(runner, benchmark_natural_is_power_algorithms); register_bench!(runner, benchmark_natural_express_as_power); } fn demo_natural_is_power(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.is_power() { println!("{n} is a perfect power"); } else { println!("{n} is not a perfect power"); } } } fn demo_natural_express_as_power(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("{}.express_as_power() = {:?}", n, n.express_as_power()); } } fn benchmark_natural_is_power_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.is_power()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.is_power())), ("rug", &mut |(n, _)| no_out!(n.is_perfect_power())), ], ); } #[allow(unused_must_use)] fn benchmark_natural_is_power_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.is_power()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.is_power())), ("using express_as_power", &mut |n| { no_out!(n.express_as_power().is_some()); }), ], ); } fn benchmark_natural_express_as_power( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.express_as_power()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("Malachite", &mut |n| no_out!(n.express_as_power()))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/factorization/is_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedSqrt; use malachite_base::num::factorization::traits::IsSquare; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_is_square); register_bench!(runner, benchmark_natural_is_square_library_comparison); register_bench!(runner, benchmark_natural_is_square_algorithms); } fn demo_natural_is_square(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { if n.is_square() { println!("{n} is a perfect square"); } else { println!("{n} is not a perfect square"); } } } fn benchmark_natural_is_square_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.is_square()", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| no_out!(n.is_square())), ("rug", &mut |(n, _)| no_out!(n.is_perfect_square())), ], ); } #[allow(unused_must_use)] fn benchmark_natural_is_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.is_square()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.is_square())), ("using checked_sqrt", &mut |n| { no_out!(n.checked_sqrt().is_some()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/factorization/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { is_power::register(runner); is_square::register(runner); primes::register(runner); } mod is_power; mod is_square; mod primes; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/factorization/primes.rs ================================================ // Copyright © 2026 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::num::factorization::traits::Primes; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::natural_bucketer; use malachite_nz::test_util::generators::natural_gen_var_9; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_primes_less_than); register_demo!(runner, demo_natural_primes_less_than_or_equal_to); register_demo!(runner, demo_natural_primes); register_bench!(runner, benchmark_natural_primes_less_than_algorithms); register_bench!( runner, benchmark_natural_primes_less_than_or_equal_to_algorithms ); } fn demo_natural_primes_less_than(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_9().get(gm, config).take(limit) { println!( "primes_less_than({}) = {:?}", n, Natural::primes_less_than(&n).collect_vec() ); } } fn demo_natural_primes_less_than_or_equal_to(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen_var_9().get(gm, config).take(limit) { println!( "primes_less_than_or_equal_to({}) = {:?}", n, Natural::primes_less_than_or_equal_to(&n).collect_vec() ); } } fn demo_natural_primes(_gm: GenMode, _config: &GenConfig, limit: usize) { for p in Natural::primes().take(limit) { println!("{p}"); } } fn benchmark_natural_primes_less_than_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::primes_less_than(&Natural)", BenchmarkType::Algorithms, natural_gen_var_9().get(gm, config), gm.name(), limit, file_name, &natural_bucketer("n"), &mut [ ("default", &mut |n| { no_out!(Natural::primes_less_than(&n).count()); }), ("using primes", &mut |n| { no_out!(Natural::primes().take_while(|p| *p < n).count()); }), ], ); } fn benchmark_natural_primes_less_than_or_equal_to_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::primes_less_than_or_equal_to(&Natural)", BenchmarkType::Algorithms, natural_gen_var_9().get(gm, config), gm.name(), limit, file_name, &natural_bucketer("n"), &mut [ ("default", &mut |n| { no_out!(Natural::primes_less_than_or_equal_to(&n).count()); }), ("using primes", &mut |n| { no_out!(Natural::primes().take_while(|p| *p <= n).count()); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/and.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_min_len_bucketer, triple_2_3_vec_min_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::and::{ limbs_and, limbs_and_in_place_either, limbs_and_limb, limbs_and_same_length_to_out, limbs_and_to_out, limbs_slice_and_in_place_left, limbs_slice_and_same_length_in_place_left, limbs_vec_and_in_place_left, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_min_bit_bucketer, pair_natural_min_bit_bucketer, triple_3_pair_natural_min_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_rm, }; use malachite_nz::test_util::natural::logic::and::{natural_and_alt_1, natural_and_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_and_limb); register_demo!(runner, demo_limbs_and); register_demo!(runner, demo_limbs_and_same_length_to_out); register_demo!(runner, demo_limbs_and_to_out); register_demo!(runner, demo_limbs_slice_and_same_length_in_place_left); register_demo!(runner, demo_limbs_slice_and_in_place_left); register_demo!(runner, demo_limbs_vec_and_in_place_left); register_demo!(runner, demo_limbs_and_in_place_either); register_demo!(runner, demo_natural_and_assign); register_demo!(runner, demo_natural_and_assign_ref); register_demo!(runner, demo_natural_and); register_demo!(runner, demo_natural_and_val_ref); register_demo!(runner, demo_natural_and_ref_val); register_demo!(runner, demo_natural_and_ref_ref); register_bench!(runner, benchmark_limbs_and_limb); register_bench!(runner, benchmark_limbs_and); register_bench!(runner, benchmark_limbs_and_same_length_to_out); register_bench!(runner, benchmark_limbs_and_to_out); register_bench!(runner, benchmark_limbs_slice_and_same_length_in_place_left); register_bench!(runner, benchmark_limbs_slice_and_in_place_left); register_bench!(runner, benchmark_limbs_vec_and_in_place_left); register_bench!(runner, benchmark_limbs_and_in_place_either); register_bench!(runner, benchmark_natural_and_assign_library_comparison); register_bench!(runner, benchmark_natural_and_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_and_library_comparison); register_bench!(runner, benchmark_natural_and_algorithms); register_bench!(runner, benchmark_natural_and_evaluation_strategy); } fn demo_limbs_and_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_and_limb({:?}, {}) = {:?}", xs, y, limbs_and_limb(&xs, y) ); } } fn demo_limbs_and(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { println!("limbs_and({:?}, {:?}) = {:?}", xs, ys, limbs_and(&xs, &ys)); } } fn demo_limbs_and_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_31().get(gm, config).take(limit) { let out_old = out.clone(); limbs_and_same_length_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_and_same_length_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_and_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_32().get(gm, config).take(limit) { let out_old = out.clone(); limbs_and_to_out(&mut out, &xs, &ys); println!("out := {out_old:?}; limbs_and_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}"); } } fn demo_limbs_slice_and_same_length_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let mut xs = xs.to_vec(); let xs_old = xs.clone(); limbs_slice_and_same_length_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_and_same_length_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_slice_and_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let truncate_size = limbs_slice_and_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; \ limbs_slice_and_in_place_left(&mut xs, {ys:?}) = {truncate_size:?}; xs = {xs:?}", ); } } fn demo_limbs_vec_and_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_vec_and_in_place_left(&mut xs, &ys); println!("xs := {xs_old:?}; limbs_vec_and_in_place_left(&mut xs, {ys:?}); xs = {xs:?}"); } } fn demo_limbs_and_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_and_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_and_in_place_either(&mut xs, &mut ys) = {right}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_and_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x &= y.clone(); println!("x := {x_old}; x &= {y}; x = {x}"); } } fn demo_natural_and_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x &= &y; println!("x := {x_old}; x &= &{y}; x = {x}"); } } fn demo_natural_and(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} & {} = {}", x_old, y_old, x & y); } } fn demo_natural_and_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} & &{} = {}", x_old, y, x & &y); } } fn demo_natural_and_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} & {} = {}", x, y_old, &x & y); } } fn demo_natural_and_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("&{} & &{} = {}", x, y, &x & &y); } } fn benchmark_limbs_and_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_and_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_and_limb(&xs, y)))], ); } fn benchmark_limbs_and(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_and(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_and(&xs, &ys)))], ); } fn benchmark_limbs_and_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_and_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_and_same_length_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_and_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_and_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_3_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_and_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_slice_and_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_and_same_length_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_slice_and_same_length_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_slice_and_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_slice_and_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, ys)| { no_out!(limbs_slice_and_in_place_left(&mut xs, &ys)); })], ); } fn benchmark_limbs_vec_and_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_vec_and_in_place_left(&Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_vec_and_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_and_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_and_in_place_either(&mut [Limb], &mut [Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_min_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { no_out!(limbs_and_in_place_either(&mut xs, &mut ys)); })], ); } fn benchmark_natural_and_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural &= Natural", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_min_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x &= y), ("rug", &mut |((mut x, y), _)| x &= y)], ); } fn benchmark_natural_and_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural &= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_min_bit_bucketer("x", "y"), &mut [ ("Natural &= Natural", &mut |(mut x, y)| no_out!(x &= y)), ("Natural &= &Natural", &mut |(mut x, y)| no_out!(x &= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_and_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural & Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_min_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x & y)), ("num", &mut |((x, y), _, _)| no_out!(x & y)), ("rug", &mut |(_, (x, y), _)| no_out!(x & y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_and_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural & Natural", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_min_bit_bucketer("x", "y"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x & y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(natural_and_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(natural_and_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_and_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural & Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_min_bit_bucketer("x", "y"), &mut [ ("Natural & Natural", &mut |(x, y)| no_out!(x & y)), ("Natural & &Natural", &mut |(x, y)| no_out!(x & &y)), ("&Natural & Natural", &mut |(x, y)| no_out!(&x & y)), ("&Natural & &Natural", &mut |(x, y)| no_out!(&x & &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_triple_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::generators::{ natural_unsigned_bool_triple_gen_var_1, natural_unsigned_bool_triple_gen_var_1_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_assign_bit); register_bench!(runner, benchmark_natural_assign_bit_library_comparison); } fn demo_natural_assign_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index, bit) in natural_unsigned_bool_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); n.assign_bit(index, bit); println!("x := {n_old}; x.assign_bit({index}, {bit}); x = {n}"); } } fn benchmark_natural_assign_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.assign_bit(u64, bool)", BenchmarkType::LibraryComparison, natural_unsigned_bool_triple_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_triple_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, (mut n, index, bit))| { n.assign_bit(index, bit); }), ("rug", &mut |((mut n, index, bit), _)| { no_out!(n.set_bit(u32::exact_from(index), bit)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::quadruple_3_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::large_type_gen_var_3; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_block_access::limbs_assign_bits; use malachite_nz::test_util::generators::natural_unsigned_unsigned_natural_quadruple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_assign_bits); register_demo!(runner, demo_natural_assign_bits); register_bench!(runner, benchmark_limbs_assign_bits); register_bench!(runner, benchmark_natural_assign_bits_algorithms); } fn demo_limbs_assign_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, start, end, bits) in large_type_gen_var_3().get(gm, config).take(limit) { let old_xs = xs.clone(); limbs_assign_bits(&mut xs, start, end, &bits); println!( "xs := {old_xs:?}; limbs_assign_bits(&mut xs, {start}, {end}, &{bits:?}); xs = {xs:?}", ); } } fn demo_natural_assign_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, start, end, bits) in natural_unsigned_unsigned_natural_quadruple_gen_var_1() .get(gm, config) .take(limit) { let old_n = n.clone(); n.assign_bits(start, end, &bits); println!("n := {old_n}; n.assign_bits({start}, {end}, &{bits}); n = {n}"); } } fn benchmark_limbs_assign_bits(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_assign_bits(&mut Vec, u64, u64, &[Limb])", BenchmarkType::Single, large_type_gen_var_3().get(gm, config), gm.name(), limit, file_name, &quadruple_3_bucketer("end"), &mut [("limbs_assign_bits", &mut |( ref mut limbs, start, end, ref bits, )| { limbs_assign_bits(limbs, start, end, bits); })], ); } fn benchmark_natural_assign_bits_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.assign_bits(u64, u64, &Natural)", BenchmarkType::Algorithms, natural_unsigned_unsigned_natural_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_3_bucketer("end"), &mut [ ("default", &mut |(mut n, start, end, bits)| { n.assign_bits(start, end, &bits); }), ("naive", &mut |(mut n, start, end, bits)| { assign_bits_naive::(&mut n, start, end, &bits); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/bits.rs ================================================ // Copyright © 2026 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::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_1_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_bits); register_demo!(runner, demo_natural_bits_rev); register_demo!(runner, demo_natural_bits_size_hint); register_bench!(runner, benchmark_natural_bits_size_hint); register_bench!(runner, benchmark_natural_bits_get_algorithms); } fn demo_natural_bits(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("bits({}) = {:?}", n, n.bits().collect_vec()); } } fn demo_natural_bits_rev(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("bits({}).rev() = {:?}", n, n.bits().rev().collect_vec()); } } fn demo_natural_bits_size_hint(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("bits({}).size_hint() = {:?}", n, n.bits().size_hint()); } } fn benchmark_natural_bits_size_hint( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.bits().size_hint()", BenchmarkType::Single, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("x"), &mut [("Natural.bits().size_hint()", &mut |n| { no_out!(n.bits().size_hint()); })], ); } #[allow(clippy::unnecessary_operation)] fn benchmark_natural_bits_get_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.bits()[u64]", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("x"), &mut [ ("Natural.bits()[u]", &mut |(n, u)| no_out!(n.bits()[u])), ("Natural.to_bits_asc()[u]", &mut |(n, u)| { let bits = n.to_bits_asc(); let u = usize::exact_from(u); if u >= bits.len() { n < 0 } else { bits[u] }; }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::bit_access::limbs_clear_bit; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_clear_bit); register_demo!(runner, demo_natural_clear_bit); register_bench!(runner, benchmark_limbs_clear_bit); register_bench!(runner, benchmark_natural_clear_bit); } fn demo_limbs_clear_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_clear_bit(&mut xs, index); println!("xs := {xs_old:?}; limbs_clear_bit(&mut xs, {index}); xs = {xs:?}"); } } fn demo_natural_clear_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.clear_bit(index); println!("x := {n_old}; x.clear_bit({index}); x = {n}"); } } fn benchmark_limbs_clear_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_clear_bit(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_clear_bit(&mut xs, index)); })], ); } fn benchmark_natural_clear_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural.clear_bit(u64)", BenchmarkType::Single, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut n, index)| n.clear_bit(index))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/count_ones.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::CountOnes; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::count_ones::limbs_count_ones; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::count_ones::{ natural_count_ones_alt_1, natural_count_ones_alt_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_count_ones); register_demo!(runner, demo_natural_count_ones); register_bench!(runner, benchmark_limbs_count_ones); register_bench!(runner, benchmark_natural_count_ones_algorithms); } fn demo_limbs_count_ones(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!("limbs_count_ones({:?}) = {}", xs, limbs_count_ones(&xs)); } } fn demo_natural_count_ones(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("count_ones({}) = {}", n, n.count_ones()); } } fn benchmark_limbs_count_ones(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_count_ones(&[Limb])", BenchmarkType::Single, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_count_ones(&xs)))], ); } fn benchmark_natural_count_ones_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.count_ones()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.count_ones())), ("using bits explicitly", &mut |n| { no_out!(natural_count_ones_alt_1(&n)); }), ("using limbs explicitly", &mut |n| { no_out!(natural_count_ones_alt_2(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::pair_2_pair_2_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_flip_bit); register_bench!(runner, benchmark_natural_flip_bit_library_comparison); } fn demo_natural_flip_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.flip_bit(index); println!("x := {n_old}; x.flip_bit({index}); x = {n}"); } } fn benchmark_natural_flip_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.flip_bit(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, (mut n, index))| n.flip_bit(index)), ("rug", &mut |((mut n, index), _)| { no_out!(n.toggle_bit(u32::exact_from(index))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/from_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitConvertible; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::bool_vec_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_desc_alt, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::natural::logic::from_bits::{ from_bits_asc_naive, from_bits_desc_naive, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_from_bits_asc); register_demo!(runner, demo_natural_from_bits_desc); register_bench!(runner, benchmark_natural_from_bits_asc_algorithms); register_bench!(runner, benchmark_natural_from_bits_desc_algorithms); } fn demo_natural_from_bits_asc(gm: GenMode, config: &GenConfig, limit: usize) { for bits in bool_vec_gen().get(gm, config).take(limit) { println!( "from_bits_asc({:?}) = {:?}", bits, Natural::from_bits_asc(bits.iter().copied()) ); } } fn demo_natural_from_bits_desc(gm: GenMode, config: &GenConfig, limit: usize) { for bits in bool_vec_gen().get(gm, config).take(limit) { println!( "from_bits_desc({:?}) = {:?}", bits, Natural::from_bits_desc(bits.iter().copied()) ); } } fn benchmark_natural_from_bits_asc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_bits_asc>(I)", BenchmarkType::Algorithms, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |bits| { no_out!(Natural::from_bits_asc(bits.into_iter())); }), ("alt", &mut |bits| { no_out!(from_bits_asc_alt::(bits.into_iter())); }), ("naive", &mut |bits| { no_out!(from_bits_asc_naive(bits.into_iter())); }), ], ); } fn benchmark_natural_from_bits_desc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::from_bits_desc>(I)", BenchmarkType::Algorithms, bool_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [ ("default", &mut |ref bits| { no_out!(Natural::from_bits_desc(bits.iter().copied())); }), ("alt", &mut |ref bits| { no_out!(from_bits_desc_alt::(bits.iter().copied())); }), ("naive", &mut |ref bits| { no_out!(from_bits_desc_naive(bits.iter().copied())); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::{pair_2_bucketer, triple_3_pair_2_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::bit_access::limbs_get_bit; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_nrm, }; use malachite_nz::test_util::natural::logic::get_bit::num_get_bit; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_get_bit); register_demo!(runner, demo_natural_get_bit); register_bench!(runner, benchmark_limbs_get_bit); register_bench!(runner, benchmark_natural_get_bit_library_comparison); } fn demo_limbs_get_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, index) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_get_bit({:?}, {}) = {}", xs, index, limbs_get_bit(&xs, index) ); } } fn demo_natural_get_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, index) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!("{}.get_bit({}) = {}", n, index, n.get_bit(index)); } } fn benchmark_limbs_get_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_get_bit(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(xs, index)| { no_out!(limbs_get_bit(&xs, index)); })], ); } fn benchmark_natural_get_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.get_bit(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, _, (n, index))| { no_out!(n.get_bit(index)); }), ("num", &mut |((n, index), _, _)| { no_out!(num_get_bit(&n, index)); }), ("rug", &mut |(_, (n, index), _)| { no_out!(n.get_bit(u32::exact_from(index))); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::bench::bucketers::triple_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_unsigned_triple_gen_var_3; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_block_access::{limbs_slice_get_bits, limbs_vec_get_bits}; use malachite_nz::test_util::bench::bucketers::triple_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_unsigned_triple_gen_var_4; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_slice_get_bits); register_demo!(runner, demo_limbs_vec_get_bits); register_demo!(runner, demo_natural_get_bits); register_demo!(runner, demo_natural_get_bits_owned); register_bench!(runner, benchmark_limbs_get_bits_evaluation_strategy); register_bench!(runner, benchmark_natural_get_bits_evaluation_strategy); register_bench!(runner, benchmark_natural_get_bits_algorithms); } fn demo_limbs_slice_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, start, end) in unsigned_vec_unsigned_unsigned_triple_gen_var_3() .get(gm, config) .take(limit) { println!( "limbs_slice_get_bits({:?}, {}, {}) = {:?}", xs, start, end, limbs_slice_get_bits(&xs, start, end) ); } } fn demo_limbs_vec_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, start, end) in unsigned_vec_unsigned_unsigned_triple_gen_var_3() .get(gm, config) .take(limit) { let old_xs = xs.clone(); println!( "limbs_vec_get_bits({:?}, {}, {}) = {:?}", old_xs, start, end, limbs_vec_get_bits(xs, start, end) ); } } fn demo_natural_get_bits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, start, end) in natural_unsigned_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { println!( "{}.get_bits({}, {}) = {}", n, start, end, n.get_bits(start, end) ); } } fn demo_natural_get_bits_owned(gm: GenMode, config: &GenConfig, limit: usize) { for (n, start, end) in natural_unsigned_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let old_n = n.clone(); println!( "{}.get_bits_owned({}, {}) = {}", old_n, start, end, n.get_bits_owned(start, end) ); } } fn benchmark_limbs_get_bits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_get_bits(&[Limb], u64, u64)", BenchmarkType::EvaluationStrategy, unsigned_vec_unsigned_unsigned_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &triple_1_vec_len_bucketer("xs"), &mut [ ("limbs_slice_get_bits", &mut |(xs, start, end)| { no_out!(limbs_slice_get_bits(&xs, start, end)); }), ("limbs_vec_get_bits", &mut |(xs, start, end)| { no_out!(limbs_vec_get_bits(xs, start, end)); }), ], ); } fn benchmark_natural_get_bits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.get_bits(u64, u64)", BenchmarkType::EvaluationStrategy, natural_unsigned_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ("get_bits", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("get_bits_owned", &mut |(n, start, end)| { no_out!(n.get_bits_owned(start, end)); }), ], ); } fn benchmark_natural_get_bits_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.get_bits(u64, u64)", BenchmarkType::Algorithms, natural_unsigned_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, start, end)| { no_out!(n.get_bits(start, end)); }), ("naive", &mut |(n, start, end)| { no_out!(get_bits_naive::(&n, start, end)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::HammingDistance; use malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_vec_max_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_7, unsigned_vec_unsigned_pair_gen_var_15, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::hamming_distance::{ limbs_hamming_distance, limbs_hamming_distance_limb, limbs_hamming_distance_same_length, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_pair_gen, natural_pair_gen_rm}; use malachite_nz::test_util::natural::logic::hamming_distance::{ natural_hamming_distance_alt_1, natural_hamming_distance_alt_2, rug_hamming_distance, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_hamming_distance_limb); register_demo!(runner, demo_limbs_hamming_distance_same_length); register_demo!(runner, demo_limbs_hamming_distance); register_demo!(runner, demo_natural_hamming_distance); register_bench!(runner, benchmark_limbs_hamming_distance_limb); register_bench!(runner, benchmark_limbs_hamming_distance_same_length); register_bench!(runner, benchmark_limbs_hamming_distance); register_bench!( runner, benchmark_natural_hamming_distance_library_comparison ); register_bench!(runner, benchmark_natural_hamming_distance_algorithms); } fn demo_limbs_hamming_distance_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_hamming_distance_limb({:?}, {}) = {}", xs, y, limbs_hamming_distance_limb(&xs, y) ); } } fn demo_limbs_hamming_distance_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { println!( "limbs_hamming_distance_same_length({:?}, {:?}) = {}", xs, ys, limbs_hamming_distance_same_length(&xs, &ys), ); } } fn demo_limbs_hamming_distance(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_7().get(gm, config).take(limit) { println!( "limbs_hamming_distance({:?}, {:?}) = {}", xs, ys, limbs_hamming_distance(&xs, &ys) ); } } fn demo_natural_hamming_distance(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!( "hamming_distance({}, {}) = {}", x, y, x.hamming_distance(&y) ); } } fn benchmark_limbs_hamming_distance_limb( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_hamming_distance_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| { no_out!(limbs_hamming_distance_limb(&xs, y)); })], ); } fn benchmark_limbs_hamming_distance_same_length( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_hamming_distance_same_length(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_hamming_distance_same_length(&xs, &ys)); })], ); } fn benchmark_limbs_hamming_distance( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_hamming_distance(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_hamming_distance(&xs, &ys)); })], ); } fn benchmark_natural_hamming_distance_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.hamming_distance(&Natural)", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| { no_out!(x.hamming_distance(&y)); }), ("rug", &mut |((x, y), _)| { no_out!(rug_hamming_distance(&x, &y)); }), ], ); } fn benchmark_natural_hamming_distance_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.hamming_distance(&Natural)", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.hamming_distance(&y))), ("using bits explicitly", &mut |(x, y)| { no_out!(natural_hamming_distance_alt_1(&x, &y)); }), ("using limbs explicitly", &mut |(x, y)| { no_out!(natural_hamming_distance_alt_2(&x, &y)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitScan; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::bit_scan::limbs_index_of_next_false_bit; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; use malachite_nz::test_util::natural::logic::index_of_next_false_bit::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_index_of_next_false_bit); register_demo!(runner, demo_natural_index_of_next_false_bit); register_bench!(runner, benchmark_limbs_index_of_next_false_bit); register_bench!(runner, benchmark_natural_index_of_next_false_bit_algorithms); } fn demo_limbs_index_of_next_false_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, u) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_index_of_next_false_bit({:?}, {}) = {}", xs, u, limbs_index_of_next_false_bit(&xs, u) ); } } fn demo_natural_index_of_next_false_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "index_of_next_false_bit({}, {}) = {:?}", n, u, n.index_of_next_false_bit(u) ); } } fn benchmark_limbs_index_of_next_false_bit( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_index_of_next_false_bit(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, u)| { no_out!(limbs_index_of_next_false_bit(&xs, u)); })], ); } fn benchmark_natural_index_of_next_false_bit_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.index_of_next_false_bit(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, u)| { no_out!(n.index_of_next_false_bit(u)); }), ("using bits explicitly", &mut |(n, u)| { no_out!(natural_index_of_next_false_bit_alt(&n, u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitScan; use malachite_base::test_util::bench::bucketers::pair_1_vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_16; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::bit_scan::limbs_index_of_next_true_bit; use malachite_nz::test_util::bench::bucketers::pair_1_natural_bit_bucketer; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; use malachite_nz::test_util::natural::logic::index_of_next_true_bit::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_index_of_next_true_bit); register_demo!(runner, demo_natural_index_of_next_true_bit); register_bench!(runner, benchmark_limbs_index_of_next_true_bit); register_bench!(runner, benchmark_natural_index_of_next_true_bit_algorithms); } fn demo_limbs_index_of_next_true_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, u) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { println!( "limbs_index_of_next_true_bit({:?}, {}) = {:?}", xs, u, limbs_index_of_next_true_bit(&xs, u) ); } } fn demo_natural_index_of_next_true_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (n, u) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "index_of_next_true_bit({}, {}) = {:?}", n, u, n.index_of_next_true_bit(u) ); } } fn benchmark_limbs_index_of_next_true_bit( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_index_of_next_true_bit(&[Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, u)| { no_out!(limbs_index_of_next_true_bit(&xs, u)); })], ); } fn benchmark_natural_index_of_next_true_bit_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.index_of_next_true_bit(u64)", BenchmarkType::Algorithms, natural_unsigned_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_natural_bit_bucketer("n"), &mut [ ("default", &mut |(n, u)| { no_out!(n.index_of_next_true_bit(u)); }), ("using bits explicitly", &mut |(n, u)| { no_out!(natural_index_of_next_true_bit_alt(&n, u)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::LowMask; use malachite_base::test_util::bench::bucketers::unsigned_direct_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::low_mask::limbs_low_mask; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_low_mask); register_demo!(runner, demo_natural_low_mask); register_bench!(runner, benchmark_limbs_low_mask); register_bench!(runner, benchmark_natural_low_mask_algorithms); } fn demo_limbs_low_mask(gm: GenMode, config: &GenConfig, limit: usize) { for bits in unsigned_gen_var_5().get(gm, config).take(limit) { println!("limbs_low_mask({}) = {:?}", bits, limbs_low_mask(bits)); } } fn demo_natural_low_mask(gm: GenMode, config: &GenConfig, limit: usize) { for bits in unsigned_gen_var_5().get(gm, config).take(limit) { println!("Natural::low_mask({}) = {}", bits, Natural::low_mask(bits)); } } fn benchmark_limbs_low_mask(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_low_mask(u64)", BenchmarkType::Single, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |bits| no_out!(limbs_low_mask(bits)))], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_low_mask_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.low_mask(u64)", BenchmarkType::Algorithms, unsigned_gen_var_5().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [ ("Natural.low_mask(u64)", &mut |bits| { no_out!(Natural::low_mask(bits)); }), ("Natural.power_of_2(u64) - 1", &mut |bits| { no_out!(Natural::power_of_2(bits) - Natural::ONE); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { and::register(runner); assign_bit::register(runner); assign_bits::register(runner); bits::register(runner); clear_bit::register(runner); count_ones::register(runner); flip_bit::register(runner); from_bits::register(runner); get_bit::register(runner); get_bits::register(runner); hamming_distance::register(runner); index_of_next_false_bit::register(runner); index_of_next_true_bit::register(runner); low_mask::register(runner); not::register(runner); or::register(runner); set_bit::register(runner); significant_bits::register(runner); to_bits::register(runner); trailing_zeros::register(runner); xor::register(runner); } mod and; mod assign_bit; mod assign_bits; mod bits; mod clear_bit; mod count_ones; mod flip_bit; mod from_bits; mod get_bit; mod get_bits; mod hamming_distance; mod index_of_next_false_bit; mod index_of_next_true_bit; mod low_mask; mod not; mod or; mod set_bit; mod significant_bits; mod to_bits; mod trailing_zeros; mod xor; ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/not.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{pair_2_vec_len_bucketer, vec_len_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{unsigned_vec_gen, unsigned_vec_pair_gen_var_1}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::not::{limbs_not, limbs_not_in_place, limbs_not_to_out}; use malachite_nz::test_util::bench::bucketers::{ natural_bit_bucketer, pair_2_natural_bit_bucketer, }; use malachite_nz::test_util::generators::{natural_gen, natural_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_not); register_demo!(runner, demo_limbs_not_to_out); register_demo!(runner, demo_limbs_not_in_place); register_demo!(runner, demo_natural_not); register_demo!(runner, demo_natural_not_ref); register_bench!(runner, benchmark_limbs_not); register_bench!(runner, benchmark_limbs_not_to_out); register_bench!(runner, benchmark_limbs_not_in_place); register_bench!(runner, benchmark_natural_not_library_comparison); register_bench!(runner, benchmark_natural_not_evaluation_strategy); } fn demo_limbs_not(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen().get(gm, config).take(limit) { println!("limbs_not({:?}) = {:?}", xs, limbs_not(&xs)); } } fn demo_limbs_not_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs) in unsigned_vec_pair_gen_var_1().get(gm, config).take(limit) { let out_old = out.clone(); limbs_not_to_out(&mut out, &xs); println!("out := {out_old:?}; limbs_not_to_out(&mut out, &{xs:?}); out = {out:?}"); } } fn demo_limbs_not_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for mut xs in unsigned_vec_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_not_in_place(&mut xs); println!("xs := {xs_old:?}; limbs_not_in_place(&mut xs); xs = {xs:?}"); } } fn demo_natural_not(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("!{} = {}", n.clone(), !n); } } fn demo_natural_not_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("!&{} = {}", n, !&n); } } fn benchmark_limbs_not(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_not(&[Limb])", BenchmarkType::Single, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_not(&xs)))], ); } fn benchmark_limbs_not_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_not_to_out(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs)| { limbs_not_to_out(&mut out, &xs); })], ); } fn benchmark_limbs_not_in_place(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_not_in_place(&mut [Limb])", BenchmarkType::Single, unsigned_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |mut xs| limbs_not_in_place(&mut xs))], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_not_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "!Natural", BenchmarkType::LibraryComparison, natural_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_natural_bit_bucketer("n"), &mut [("Malachite", &mut |(_, n)| no_out!(!n)), ("rug", &mut |(n, _)| no_out!(!n))], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_not_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "!Natural", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [("-Natural", &mut |n| no_out!(!n)), ("-&Natural", &mut |n| no_out!(!&n))], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/or.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_2_vec_len_bucketer, pair_vec_max_len_bucketer, triple_2_3_vec_max_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::or::{ limbs_or, limbs_or_in_place_either, limbs_or_in_place_left, limbs_or_limb, limbs_or_limb_in_place, limbs_or_limb_to_out, limbs_or_same_length, limbs_or_same_length_in_place_left, limbs_or_same_length_to_out, limbs_or_to_out, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_rm, }; use malachite_nz::test_util::natural::logic::or::{natural_or_alt_1, natural_or_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_or_limb); register_demo!(runner, demo_limbs_or_limb_to_out); register_demo!(runner, demo_limbs_or_limb_in_place); register_demo!(runner, demo_limbs_or_same_length); register_demo!(runner, demo_limbs_or); register_demo!(runner, demo_limbs_or_same_length_to_out); register_demo!(runner, demo_limbs_or_to_out); register_demo!(runner, demo_limbs_or_same_length_in_place_left); register_demo!(runner, demo_limbs_or_in_place_left); register_demo!(runner, demo_limbs_or_in_place_either); register_demo!(runner, demo_natural_or_assign); register_demo!(runner, demo_natural_or_assign_ref); register_demo!(runner, demo_natural_or); register_demo!(runner, demo_natural_or_val_ref); register_demo!(runner, demo_natural_or_ref_val); register_demo!(runner, demo_natural_or_ref_ref); register_bench!(runner, benchmark_limbs_or_limb); register_bench!(runner, benchmark_limbs_or_limb_to_out); register_bench!(runner, benchmark_limbs_or_limb_in_place); register_bench!(runner, benchmark_limbs_or_same_length); register_bench!(runner, benchmark_limbs_or); register_bench!(runner, benchmark_limbs_or_same_length_to_out); register_bench!(runner, benchmark_limbs_or_to_out); register_bench!(runner, benchmark_limbs_or_same_length_in_place_left); register_bench!(runner, benchmark_limbs_or_in_place_left); register_bench!(runner, benchmark_limbs_or_in_place_either); register_bench!(runner, benchmark_natural_or_assign_library_comparison); register_bench!(runner, benchmark_natural_or_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_or_library_comparison); register_bench!(runner, benchmark_natural_or_algorithms); register_bench!(runner, benchmark_natural_or_evaluation_strategy); } fn demo_limbs_or_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_or_limb({:?}, {}) = {:?}", xs, y, limbs_or_limb(&xs, y) ); } } fn demo_limbs_or_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_or_limb_to_out(&mut out, &xs, y); println!("out := {out_old:?}; limbs_or_limb_to_out(&mut out, {xs:?}, {y}); out = {out:?}"); } } fn demo_limbs_or_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_or_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_or_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_or_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { println!( "limbs_or_same_length({:?}, {:?}) = {:?}", xs, ys, limbs_or_same_length(&xs, &ys) ); } } fn demo_limbs_or(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { println!("limbs_or({:?}, {:?}) = {:?}", xs, ys, limbs_or(&xs, &ys)); } } fn demo_limbs_or_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_31().get(gm, config).take(limit) { let out_old = out.clone(); limbs_or_same_length_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_or_same_length_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_or_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_32().get(gm, config).take(limit) { let out_old = out.clone(); limbs_or_to_out(&mut out, &xs, &ys); println!("out := {out_old:?}; limbs_or_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}"); } } fn demo_limbs_or_same_length_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_or_same_length_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_or_same_length_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_or_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_or_in_place_left(&mut xs, &ys); println!("xs := {xs_old:?}; limbs_or_in_place_left(&mut xs, {ys:?}); xs = {xs:?}"); } } fn demo_limbs_or_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_or_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_or_in_place_either(&mut xs, &mut ys) = {right}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_or_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x |= y.clone(); println!("x := {x_old}; x |= {y}; x = {x}"); } } fn demo_natural_or_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x |= &y; println!("x := {x_old}; x |= &{y}; x = {x}"); } } fn demo_natural_or(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} | {} = {}", x_old, y_old, x | y); } } fn demo_natural_or_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} | &{} = {}", x_old, y, x | &y); } } fn demo_natural_or_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} | {} = {}", x, y_old, &x | y); } } fn demo_natural_or_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("&{} | &{} = {}", x, y, &x | &y); } } fn benchmark_limbs_or_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_or_limb(&xs, y)))], ); } fn benchmark_limbs_or_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_or_limb_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_or_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_or_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_or_same_length(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_same_length(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_or_same_length(&xs, &ys)); })], ); } fn benchmark_limbs_or(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_or(&xs, &ys)))], ); } fn benchmark_limbs_or_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_or_same_length_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_or_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_or_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_32().get(gm, config), gm.name(), limit, file_name, &triple_2_3_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_or_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_or_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_same_length_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_or_same_length_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_or_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("ys"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_or_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_or_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_or_in_place_either(&mut Vec, &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { no_out!(limbs_or_in_place_either(&mut xs, &mut ys)); })], ); } fn benchmark_natural_or_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural |= Natural", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x |= y), ("rug", &mut |((mut x, y), _)| x |= y)], ); } fn benchmark_natural_or_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural |= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural |= Natural", &mut |(mut x, y)| no_out!(x |= y)), ("Natural |= &Natural", &mut |(mut x, y)| no_out!(x |= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_or_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural | Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x | y)), ("num", &mut |((x, y), _, _)| no_out!(x | y)), ("rug", &mut |(_, (x, y), _)| no_out!(x | y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_or_algorithms(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Natural | Natural", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x | y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(natural_or_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(natural_or_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_or_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural | Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural | Natural", &mut |(x, y)| no_out!(x | y)), ("Natural | &Natural", &mut |(x, y)| no_out!(x | &y)), ("&Natural | Natural", &mut |(x, y)| no_out!(&x | y)), ("&Natural | &Natural", &mut |(x, y)| no_out!(&x | &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::bench::bucketers::{pair_2_bucketer, pair_2_pair_2_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_17, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::bit_access::{limbs_slice_set_bit, limbs_vec_set_bit}; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_4_nm, }; use malachite_nz::test_util::natural::logic::set_bit::num_set_bit; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_slice_set_bit); register_demo!(runner, demo_limbs_vec_set_bit); register_demo!(runner, demo_natural_set_bit); register_bench!(runner, benchmark_limbs_slice_set_bit); register_bench!(runner, benchmark_limbs_vec_set_bit); register_bench!(runner, benchmark_natural_set_bit_library_comparison); } fn demo_limbs_slice_set_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_17() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_slice_set_bit(&mut xs, index); println!("xs := {xs_old:?}; limbs_slice_set_bit(&mut xs, {index}); xs = {xs:?}"); } } fn demo_limbs_vec_set_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, index) in unsigned_vec_unsigned_pair_gen_var_16() .get(gm, config) .take(limit) { let old_xs = xs.clone(); limbs_vec_set_bit(&mut xs, index); println!("xs := {old_xs:?}; limbs_vec_set_bit(&mut xs, {index}); xs = {xs:?}"); } } fn demo_natural_set_bit(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, index) in natural_unsigned_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); n.set_bit(index); println!("x := {n_old}; x.set_bit({index}); x = {n}"); } } fn benchmark_limbs_slice_set_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_slice_set_bit(&mut [Limb], u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_17().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_slice_set_bit(&mut xs, index)); })], ); } fn benchmark_limbs_vec_set_bit(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_vec_set_bit(&mut Vec, u64)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_16().get(gm, config), gm.name(), limit, file_name, &pair_2_bucketer("index"), &mut [("Malachite", &mut |(mut xs, index)| { no_out!(limbs_vec_set_bit(&mut xs, index)); })], ); } fn benchmark_natural_set_bit_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.set_bit(u64)", BenchmarkType::LibraryComparison, natural_unsigned_pair_gen_var_4_nm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_2_bucketer("index"), &mut [ ("Malachite", &mut |(_, (mut n, index))| n.set_bit(index)), ("num", &mut |((mut n, index), _)| num_set_bit(&mut n, index)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_1; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::significant_bits::limbs_significant_bits; use malachite_nz::platform::Limb; use malachite_nz::test_util::bench::bucketers::triple_3_natural_bit_bucketer; use malachite_nz::test_util::generators::{natural_gen, natural_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_significant_bits); register_demo!(runner, demo_natural_significant_bits); register_bench!(runner, benchmark_limbs_significant_bits); register_bench!( runner, benchmark_natural_significant_bits_library_comparison ); } fn demo_limbs_significant_bits(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_1::().get(gm, config).take(limit) { println!( "limbs_significant_bits({:?}) = {}", xs, limbs_significant_bits(&xs) ); } } fn demo_natural_significant_bits(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("significant_bits({}) = {}", n, n.significant_bits()); } } fn benchmark_limbs_significant_bits( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_significant_bits(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_significant_bits(&xs)))], ); } fn benchmark_natural_significant_bits_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.significant_bits()", BenchmarkType::LibraryComparison, natural_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_natural_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.significant_bits())), ("num", &mut |(n, _, _)| no_out!(n.bits())), ("rug", &mut |(_, n, _)| no_out!(n.significant_bits())), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/to_bits.rs ================================================ // Copyright © 2026 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::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::num::logic::bit_convertible::{to_bits_asc_alt, to_bits_desc_alt}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::to_bits::{to_bits_asc_naive, to_bits_desc_naive}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_to_bits_asc); register_demo!(runner, demo_natural_to_bits_desc); register_bench!(runner, benchmark_natural_to_bits_asc_evaluation_strategy); register_bench!(runner, benchmark_natural_to_bits_asc_algorithms); register_bench!(runner, benchmark_natural_to_bits_desc_evaluation_strategy); register_bench!(runner, benchmark_natural_to_bits_desc_algorithms); } fn demo_natural_to_bits_asc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("to_bits_asc({}) = {:?}", n, n.to_bits_asc()); } } fn demo_natural_to_bits_desc(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("to_bits_desc({}) = {:?}", n, n.to_bits_desc()); } } fn benchmark_natural_to_bits_asc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_bits_asc()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.to_bits_asc()", &mut |n| no_out!(n.to_bits_asc())), ("Natural.bits().collect_vec()", &mut |n| { no_out!(n.bits().collect_vec()); }), ], ); } fn benchmark_natural_to_bits_asc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_bits_asc()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.to_bits_asc())), ("alt", &mut |n| no_out!(to_bits_asc_alt(&n))), ("naive", &mut |n| no_out!(to_bits_asc_naive(&n))), ], ); } fn benchmark_natural_to_bits_desc_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_bits_desc()", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Natural.to_bits_asc()", &mut |n| no_out!(n.to_bits_desc())), ("Natural.bits().rev().collect_vec()", &mut |n| { no_out!(n.bits().rev().collect_vec()); }), ], ); } fn benchmark_natural_to_bits_desc_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.to_bits_desc()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.to_bits_desc())), ("alt", &mut |n| no_out!(to_bits_desc_alt(&n))), ("naive", &mut |n| no_out!(to_bits_desc_naive(&n))), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::vec_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::unsigned_vec_gen_var_2; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::trailing_zeros::limbs_trailing_zeros; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::trailing_zeros::natural_trailing_zeros_alt; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_trailing_zeros); register_demo!(runner, demo_natural_trailing_zeros); register_bench!(runner, benchmark_limbs_trailing_zeros); register_bench!(runner, benchmark_natural_trailing_zeros_algorithms); } fn demo_limbs_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for xs in unsigned_vec_gen_var_2().get(gm, config).take(limit) { println!( "limbs_trailing_zeros({:?}) = {}", xs, limbs_trailing_zeros(&xs) ); } } fn demo_natural_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("trailing_zeros({}) = {:?}", n, n.trailing_zeros()); } } fn benchmark_limbs_trailing_zeros(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_trailing_zeros(&[Limb])", BenchmarkType::Single, unsigned_vec_gen_var_2().get(gm, config), gm.name(), limit, file_name, &vec_len_bucketer(), &mut [("Malachite", &mut |xs| no_out!(limbs_trailing_zeros(&xs)))], ); } fn benchmark_natural_trailing_zeros_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.trailing_zeros()", BenchmarkType::Algorithms, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("default", &mut |n| no_out!(n.trailing_zeros())), ("using bits explicitly", &mut |n| { no_out!(natural_trailing_zeros_alt(&n)); }), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/logic/xor.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::{ pair_1_vec_len_bucketer, pair_2_vec_len_bucketer, pair_vec_max_len_bucketer, triple_2_3_vec_max_len_bucketer, triple_2_vec_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, }; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::logic::xor::{ limbs_xor, limbs_xor_in_place_either, limbs_xor_in_place_left, limbs_xor_limb, limbs_xor_limb_in_place, limbs_xor_limb_to_out, limbs_xor_same_length, limbs_xor_same_length_in_place_left, limbs_xor_same_length_to_out, limbs_xor_to_out, }; use malachite_nz::test_util::bench::bucketers::{ pair_2_pair_natural_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_3_pair_natural_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_pair_gen_nrm, natural_pair_gen_rm, }; use malachite_nz::test_util::natural::logic::xor::{natural_xor_alt_1, natural_xor_alt_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_limbs_xor_limb); register_demo!(runner, demo_limbs_xor_limb_to_out); register_demo!(runner, demo_limbs_xor_limb_in_place); register_demo!(runner, demo_limbs_xor_same_length); register_demo!(runner, demo_limbs_xor); register_demo!(runner, demo_limbs_xor_same_length_to_out); register_demo!(runner, demo_limbs_xor_to_out); register_demo!(runner, demo_limbs_xor_same_length_in_place_left); register_demo!(runner, demo_limbs_xor_in_place_left); register_demo!(runner, demo_limbs_xor_in_place_either); register_demo!(runner, demo_natural_xor_assign); register_demo!(runner, demo_natural_xor_assign_ref); register_demo!(runner, demo_natural_xor); register_demo!(runner, demo_natural_xor_val_ref); register_demo!(runner, demo_natural_xor_ref_val); register_demo!(runner, demo_natural_xor_ref_ref); register_bench!(runner, benchmark_limbs_xor_limb); register_bench!(runner, benchmark_limbs_xor_limb_to_out); register_bench!(runner, benchmark_limbs_xor_limb_in_place); register_bench!(runner, benchmark_limbs_xor_same_length); register_bench!(runner, benchmark_limbs_xor); register_bench!(runner, benchmark_limbs_xor_same_length_to_out); register_bench!(runner, benchmark_limbs_xor_to_out); register_bench!(runner, benchmark_limbs_xor_same_length_in_place_left); register_bench!(runner, benchmark_limbs_xor_in_place_left); register_bench!(runner, benchmark_limbs_xor_in_place_either); register_bench!(runner, benchmark_natural_xor_assign_library_comparison); register_bench!(runner, benchmark_natural_xor_assign_evaluation_strategy); register_bench!(runner, benchmark_natural_xor_library_comparison); register_bench!(runner, benchmark_natural_xor_algorithms); register_bench!(runner, benchmark_natural_xor_evaluation_strategy); } fn demo_limbs_xor_limb(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { println!( "limbs_xor_limb({:?}, {}) = {:?}", xs, y, limbs_xor_limb(&xs, y) ); } } fn demo_limbs_xor_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, y) in unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4() .get(gm, config) .take(limit) { let out_old = out.clone(); limbs_xor_limb_to_out(&mut out, &xs, y); println!("out := {out_old:?}; limbs_xor_limb_to_out(&mut out, {xs:?}, {y}); out = {out:?}"); } } fn demo_limbs_xor_limb_in_place(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, y) in unsigned_vec_unsigned_pair_gen_var_15() .get(gm, config) .take(limit) { let xs_old = xs.clone(); limbs_xor_limb_in_place(&mut xs, y); println!("xs := {xs_old:?}; limbs_xor_limb_in_place(&mut xs, {y}); xs = {xs:?}"); } } fn demo_limbs_xor_same_length(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { println!( "limbs_xor_same_length({:?}, {:?}) = {:?}", xs, ys, limbs_xor_same_length(&xs, &ys) ); } } fn demo_limbs_xor(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { println!("limbs_xor({:?}, {:?}) = {:?}", xs, ys, limbs_xor(&xs, &ys)); } } fn demo_limbs_xor_same_length_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_31().get(gm, config).take(limit) { let out_old = out.clone(); limbs_xor_same_length_to_out(&mut out, &xs, &ys); println!( "out := {out_old:?}; \ limbs_xor_same_length_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}", ); } } fn demo_limbs_xor_to_out(gm: GenMode, config: &GenConfig, limit: usize) { for (mut out, xs, ys) in unsigned_vec_triple_gen_var_32().get(gm, config).take(limit) { let out_old = out.clone(); limbs_xor_to_out(&mut out, &xs, &ys); println!("out := {out_old:?}; limbs_xor_to_out(&mut out, {xs:?}, {ys:?}); out = {out:?}"); } } fn demo_limbs_xor_same_length_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen_var_6().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_xor_same_length_in_place_left(&mut xs, &ys); println!( "xs := {xs_old:?}; limbs_xor_same_length_in_place_left(&mut xs, {ys:?}); xs = {xs:?}", ); } } fn demo_limbs_xor_in_place_left(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); limbs_xor_in_place_left(&mut xs, &ys); println!("xs := {xs_old:?}; limbs_xor_in_place_left(&mut xs, {ys:?}); xs = {xs:?}"); } } fn demo_limbs_xor_in_place_either(gm: GenMode, config: &GenConfig, limit: usize) { for (mut xs, mut ys) in unsigned_vec_pair_gen().get(gm, config).take(limit) { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_xor_in_place_either(&mut xs, &mut ys); println!( "xs := {xs_old:?}; \ ys := {ys_old:?}; limbs_xor_in_place_either(&mut xs, &mut ys) = {right}; \ xs = {xs:?}; ys = {ys:?}", ); } } fn demo_natural_xor_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x ^= y.clone(); println!("x := {x_old}; x ^= {y}; x = {x}"); } } fn demo_natural_xor_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x ^= &y; println!("x := {x_old}; x ^= &{y}; x = {x}"); } } fn demo_natural_xor(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} ^ {} = {}", x_old, y_old, x ^ y); } } fn demo_natural_xor_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} ^ &{} = {}", x_old, y, x ^ &y); } } fn demo_natural_xor_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} ^ {} = {}", x, y_old, &x ^ y); } } fn demo_natural_xor_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in natural_pair_gen().get(gm, config).take(limit) { println!("&{} ^ &{} = {}", x, y, &x ^ &y); } } fn benchmark_limbs_xor_limb(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_limb(&[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, y)| no_out!(limbs_xor_limb(&xs, y)))], ); } fn benchmark_limbs_xor_limb_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_limb_to_out(&mut [Limb], &[Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, y)| { no_out!(limbs_xor_limb_to_out(&mut out, &xs, y)); })], ); } fn benchmark_limbs_xor_limb_in_place( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_limb_in_place(&mut [Limb], Limb)", BenchmarkType::Single, unsigned_vec_unsigned_pair_gen_var_15().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, y)| { limbs_xor_limb_in_place(&mut xs, y); })], ); } fn benchmark_limbs_xor_same_length(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_same_length(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| { no_out!(limbs_xor_same_length(&xs, &ys)); })], ); } fn benchmark_limbs_xor(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor(&[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(xs, ys)| no_out!(limbs_xor(&xs, &ys)))], ); } fn benchmark_limbs_xor_same_length_to_out( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_31().get(gm, config), gm.name(), limit, file_name, &triple_2_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_xor_same_length_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_xor_to_out(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "limbs_xor_same_length_to_out(&mut [Limb], &[Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_triple_gen_var_32().get(gm, config), gm.name(), limit, file_name, &triple_2_3_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut out, xs, ys)| { limbs_xor_to_out(&mut out, &xs, &ys); })], ); } fn benchmark_limbs_xor_same_length_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_same_length_in_place_left(&mut [Limb], &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_len_bucketer("xs"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_xor_same_length_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_xor_in_place_left( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_in_place_left(&mut Vec, &[Limb])", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_2_vec_len_bucketer("ys"), &mut [("Malachite", &mut |(mut xs, ys)| { limbs_xor_in_place_left(&mut xs, &ys); })], ); } fn benchmark_limbs_xor_in_place_either( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "limbs_xor_in_place_either(&mut Vec, &mut Vec)", BenchmarkType::Single, unsigned_vec_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_vec_max_len_bucketer("xs", "ys"), &mut [("Malachite", &mut |(mut xs, mut ys)| { no_out!(limbs_xor_in_place_either(&mut xs, &mut ys)); })], ); } fn benchmark_natural_xor_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural ^= Natural", BenchmarkType::LibraryComparison, natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x ^= y), ("rug", &mut |((mut x, y), _)| x ^= y)], ); } fn benchmark_natural_xor_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural ^= Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural ^= Natural", &mut |(mut x, y)| no_out!(x ^= y)), ("Natural ^= &Natural", &mut |(mut x, y)| no_out!(x ^= &y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_xor_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural ^ Natural", BenchmarkType::LibraryComparison, natural_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x ^ y)), ("num", &mut |((x, y), _, _)| no_out!(x ^ y)), ("rug", &mut |(_, (x, y), _)| no_out!(x ^ y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_xor_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural ^ Natural", BenchmarkType::Algorithms, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(ref x, ref y)| no_out!(x ^ y)), ("using bits explicitly", &mut |(ref x, ref y)| { no_out!(natural_xor_alt_1(x, y)); }), ("using limbs explicitly", &mut |(ref x, ref y)| { no_out!(natural_xor_alt_2(x, y)); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_natural_xor_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural ^ Natural", BenchmarkType::EvaluationStrategy, natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("x", "y"), &mut [ ("Natural ^ Natural", &mut |(x, y)| no_out!(x ^ y)), ("Natural ^ &Natural", &mut |(x, y)| no_out!(x ^ &y)), ("&Natural ^ Natural", &mut |(x, y)| no_out!(&x ^ y)), ("&Natural ^ &Natural", &mut |(x, y)| no_out!(&x ^ &y)), ], ); } ================================================ FILE: malachite-nz/src/bin_util/demo_and_bench/natural/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); comparison::register(runner); conversion::register(runner); factorization::register(runner); logic::register(runner); } mod arithmetic; mod comparison; mod conversion; mod factorization; mod logic; ================================================ FILE: malachite-nz/src/bin_util/generate/digits_data.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 2000, 2001, 2002, 2004, 2011, 2012, 2015-2018 Free // Software Foundation, Inc. // // 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 malachite_base::num::arithmetic::traits::{FloorSqrt, ModPowerOf2, Parity, Pow, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, LowMask, SignificantBits}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; // Calculate r satisfying r*d == 1 mod 2^n. // // This is equivalent to `mpz_invert_2exp` from `bootstrap.c`, GMP 6.2.1. fn invert_mod_power_of_2(x: &Natural, pow: u64) -> Natural { assert!(x.odd()); let mut inverse = Natural::ONE; for i in 0..pow { if (&inverse * x).get_bit(i) { inverse.set_bit(i); } } assert_eq!((&inverse * x).mod_power_of_2(pow), 1); inverse } // Compute log(2) / log(b) as a fixnum. // // This is equivalent to `mp_2logb` from `gen-bases.c`, GMP 6.2.1. fn get_log_base_of_2(base: u64, precision: u64) -> Natural { let extended_precision = precision + 16; let mut t = Natural::power_of_2(extended_precision); let two = &t << 1; let mut log = Natural::ZERO; let mut base = Natural::from(base) << extended_precision; for i in (0..precision).rev() { base = (&base << extended_precision).floor_sqrt(); let next_t = (&t * &base) >> extended_precision; if next_t < two { log.set_bit(i); t = next_t; } } log } struct BaseData { chars_per_limb: u64, big_base_trailing_zeros: u64, big_base: Natural, normalization_steps: u64, big_base_inverted: Natural, big_base_inverted_mod_b: Natural, } // This is equivalent to `generate` from `gen-bases.c`, GMP 6.2.1. fn generate(base: u64) -> BaseData { let limit = Natural::power_of_2(Limb::WIDTH); let mut big_base = Natural::ONE; let mut chars_per_limb = 0; while big_base <= limit { chars_per_limb += 1; big_base *= Natural::from(base); } chars_per_limb -= 1; big_base = Natural::from(base).pow(chars_per_limb); let normalization_steps = Limb::WIDTH.wrapping_sub(big_base.significant_bits()); let mut big_base_inverted = Natural::power_of_2((Limb::WIDTH << 1).wrapping_sub(normalization_steps)) / &big_base; big_base_inverted.clear_bit(Limb::WIDTH); let big_base_trailing_zeros = big_base.trailing_zeros().unwrap(); let big_base_odd = &big_base >> big_base_trailing_zeros; let big_base_inverted_mod_b = invert_mod_power_of_2(&big_base_odd, Limb::WIDTH); BaseData { chars_per_limb, big_base_trailing_zeros, big_base, normalization_steps, big_base_inverted, big_base_inverted_mod_b, } } // This is equivalent to `header` from `gen-bases.c`, GMP 6.2.1. fn header() { let data = generate(10); println!("// mp_bases[10] data, as literal values"); println!( "pub const MP_BASES_CHARS_PER_LIMB_10: usize = {};", data.chars_per_limb ); println!( "pub const MP_BASES_BIG_BASE_CTZ_10: usize = {};", data.big_base_trailing_zeros ); println!( "pub const MP_BASES_BIG_BASE_10: Limb = {:#x};", Limb::exact_from(&data.big_base) ); println!( "pub const MP_BASES_BIG_BASE_INVERTED_10: Limb = {:#x};", Limb::exact_from(&data.big_base_inverted) ); println!( "pub const MP_BASES_BIG_BASE_BINVERTED_10: Limb = {:#x};", Limb::exact_from(&data.big_base_inverted_mod_b) ); println!( "pub const MP_BASES_NORMALIZATION_STEPS_10: u64 = {};", data.normalization_steps ); } // This is equivalent to `table` from `gen-bases.c`, GMP 6.2.1. fn table() { println!("// Format is (chars_per_limb, logb2, log2b, big_base, big_base_inverted)"); println!("pub const BASES: [(usize, Limb, Limb, Limb, Limb); 257] = ["); println!(" (0, 0, 0, 0, 0), // 0"); println!(" (0, 0, 0, 0, 0), // 1"); for base in 2..=256 { let mut data = generate(base); let raw = get_log_base_of_2(base, Limb::WIDTH + 8); let log_base_of_2 = &raw >> 8; let log_2_of_base = Natural::low_mask((Limb::WIDTH << 1) + 5) / (raw + Natural::ONE); if base.is_power_of_two() { data.big_base = Natural::from(base.significant_bits() - 1); data.big_base_inverted = Natural::ZERO; } println!( " ({}, {:#x}, {:#x}, {:#x}, {:#x}), // {}", data.chars_per_limb, Limb::exact_from(&log_base_of_2), Limb::exact_from(&log_2_of_base), Limb::exact_from(&data.big_base), Limb::exact_from(&data.big_base_inverted), base ); } println!("];"); } pub(crate) fn generate_string_data() { println!("// This section is created by digits_data.rs."); println!(); header(); println!(); table(); } ================================================ FILE: malachite-nz/src/bin_util/generate/factorial_data.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2002, 2010-2018 Free Software Foundation, Inc. // // `mpz/bin_uiui.c` contributed to the GNU project by Torbjörn Granlund and Marco Bodrato. // // 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, BinomialCoefficient, CheckedDoubleFactorial, DivExactAssign, FloorRoot, ModPowerOf2Inverse, OverflowingMulAssign, WrappingMulAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::CountOnes; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; #[allow(clippy::useless_conversion)] fn odd_factorial_table() -> (u64, u64) { let mut xs = vec![1, 1, 1]; let mut x: Limb = 1; let mut limit = 0; for b in Limb::from(3u32).. { if x.overflowing_mul_assign(b >> b.trailing_zeros()) { limit = b; break; } xs.push(x); } xs.push(x); let mut y = Limb::binomial_coefficient(limit, limit >> 1); let mut ext_limit = 0; for b in limit + 1.. { let a = b >> b.trailing_zeros(); if a == b { y.div_exact_assign((a >> 1) + 1); if y.overflowing_mul_assign(a) { ext_limit = b; break; } } else if let Some(shifted) = y.arithmetic_checked_shl(1) { y = shifted; } else { ext_limit = b; break; } x.wrapping_mul_assign(a); xs.push(x); } println!( "// This is equivalent to `__gmp_oddfac_table` in `mpn/comb_tables.c`, GMP 6.2.1, which \ is the" ); println!( "// combination of `ONE_LIMB_ODD_FACTORIAL_TABLE` and `ONE_LIMB_ODD_FACTORIAL_EXTTABLE` in" ); println!("// `fac_table.h`, GMP 6.2.1."); print!( "pub const ONE_LIMB_ODD_FACTORIAL_TABLE: [Limb; {}] = [", xs.len() ); let mut first = true; for &x in &xs { if first { first = false; } else { print!(", "); } print!("{x:#x}"); } println!("];"); limit -= 1; ext_limit -= 1; println!("// This is equivalent to `ODD_FACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1."); println!("pub const ODD_FACTORIAL_TABLE_LIMIT: usize = {limit};"); println!( "// This is equivalent to `ODD_FACTORIAL_EXTTABLE_LIMIT` in `fac_table.h`, GMP 6.2.1." ); println!("pub const ODD_FACTORIAL_EXTTABLE_LIMIT: usize = {ext_limit};"); println!("// This is equivalent to `ODD_FACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1."); println!( "pub const ODD_FACTORIAL_TABLE_MAX: Limb = {:#x};", xs[usize::wrapping_from(limit)] ); (u64::from(limit), u64::from(ext_limit)) } fn odd_double_factorial_table() { let mut xs = vec![]; let mut limit = 0; for n in 0.. { let n = (n << 1) | 1; if let Some(x) = Limb::checked_double_factorial(n) { xs.push(x); } else { limit = n; break; } } println!( "// This is equivalent to `__gmp_odd2fac_table` in `mpn/comb_tables.c`, GMP 6.2.1, and" ); println!("// `ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE` from `fac_table.h`, GMP 6.2.1."); print!( "pub const ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE: [Limb; {}] = [", xs.len() ); let mut first = true; for &x in &xs { if first { first = false; } else { print!(", "); } print!("{x:#x}"); } println!("];"); limit -= 2; println!( "// This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1." ); println!("pub const ODD_DOUBLEFACTORIAL_TABLE_LIMIT: usize = {limit};"); println!( "// This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1." ); println!( "pub const ODD_DOUBLEFACTORIAL_TABLE_MAX: Limb = {:#x};", xs[usize::wrapping_from(limit >> 1)] ); } fn nth_root_mask_table() { println!( "// This is equivalent to `__gmp_limbroots_table` in `mpn/comb_tables.c`, GMP 6.2.1, and" ); println!("// `NTH_ROOT_NUMB_MASK_TABLE` from `fac_table.h`, GMP 6.2.1."); print!("pub const NTH_ROOT_NUMB_MASK_TABLE: [Limb; 8] = [Limb::MAX"); for b in 2..=8 { print!(", {:#x}", Limb::MAX.floor_root(b)); } println!("];"); } fn factorial_inverse_table(limit: u64) { println!( "// This is equivalent to `ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE` from `fac_table.h`, \ GMP 6.2.1." ); print!( "pub const ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE: [Limb; {}] = [0x1", limit - 3 ); let limit = Limb::wrapping_from(limit); let mut x: Limb = 1; for b in 3..=limit - 2 { x.wrapping_mul_assign(b >> b.trailing_zeros()); print!(", {:#x}", x.mod_power_of_2_inverse(Limb::WIDTH).unwrap()); } println!("];"); } fn factorial_2_count_table(limit: u64) { println!("// https://oeis.org/A005187, skipping the initial 0"); println!("//"); println!( "// This is equivalent to `__gmp_fac2cnt_table` in `mpn/comb_tables.c`, GMP 6.2.1, and" ); println!("// `TABLE_2N_MINUS_POPC_2N` from `fac_table.h`, GMP 6.2.1."); let limit = ((limit >> 4) + 1) << 4; let mut b = 4; print!( "pub const TABLE_2N_MINUS_POPC_2N: [u8; {}] = [1", ((limit - b) >> 1) + 2 ); while b <= limit { print!(", {}", b - CountOnes::count_ones(b)); b += 2; } println!("];"); println!(); println!( "pub const TABLE_LIMIT_2N_MINUS_POPC_2N: u64 = {};", limit + 1 ); } fn odd_central_binomial_table(limit: u64) -> u64 { println!("pub const ODD_CENTRAL_BINOMIAL_OFFSET: usize = {limit};"); println!(); println!("// This table contains binomial(2k, k) / 2 ^ t."); println!("//"); println!("// This is equivalent to `bin2kk` in `mpz/bin_uiui.c`, GMP 6.2.1, and"); println!("// `ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE` from `fac_table.h`, GMP 6.2.1."); let mut xs = Vec::new(); let mut binomial_limit = 0; for b in limit.. { binomial_limit = b; let mut x = Natural::binomial_coefficient(Natural::from(b) << 1u32, Natural::from(b)); x >>= x.trailing_zeros().unwrap(); if let Ok(x) = Limb::try_from(&x) { xs.push(x); } else { break; } } print!( "pub const ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE: [Limb; {}] = [", xs.len() ); let mut first = true; for &x in &xs { if first { first = false; } else { print!(", "); } print!("{x:#x}"); } println!("];"); u64::wrapping_from(binomial_limit) } fn odd_central_binomial_inverse_table(limit: u64, binomial_limit: u64) { let binomial_limit = binomial_limit - 1; println!("pub const ODD_CENTRAL_BINOMIAL_TABLE_LIMIT: usize = {binomial_limit};"); println!(); println!("// This table contains the inverses of elements in the previous table."); println!("//"); println!("// This is equivalent to `bin2kkinv` in `mpz/bin_uiui.c`, GMP 6.2.1, and"); println!("// `ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE` from `fac_table.h`, GMP 6.2.1."); let mut xs = Vec::new(); for b in limit..=binomial_limit { let mut x = Natural::binomial_coefficient(Natural::from(b) << 1u32, Natural::from(b)); x >>= x.trailing_zeros().unwrap(); xs.push(Limb::exact_from( &(x.mod_power_of_2_inverse(Limb::WIDTH).unwrap()), )); } print!( "pub const ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE: [Limb; {}] = [", xs.len() ); let mut first = true; for &x in &xs { if first { first = false; } else { print!(", "); } print!("{x:#x}"); } println!("];"); } fn central_binomial_2_fac_table(limit: u64, binomial_limit: u64) { let binomial_limit = binomial_limit - 1; println!("// This table contains the values t in the formula binomial(2k, k) / 2 ^ t."); println!("//"); println!("// This is equivalent to `fac2bin` in `mpz/bin_uiui.c`, GMP 6.2.1, and"); println!("// `CENTRAL_BINOMIAL_2FAC_TABLE` from `fac_table.h`, GMP 6.2.1."); let mut xs = Vec::new(); for b in limit..=binomial_limit { xs.push( Natural::binomial_coefficient(Natural::from(b) << 1u32, Natural::from(b)) .trailing_zeros() .unwrap(), ); } print!( "pub const CENTRAL_BINOMIAL_2FAC_TABLE: [u64; {}] = [", xs.len() ); let mut first = true; for &x in &xs { if first { first = false; } else { print!(", "); } print!("{x}"); } println!("];"); } pub(crate) fn generate_factorial_data() { println!("// This section is created by factorial_data.rs."); println!(); let (mut of_limit, ext_limit) = odd_factorial_table(); println!(); odd_double_factorial_table(); println!(); nth_root_mask_table(); println!(); factorial_inverse_table(ext_limit); println!(); of_limit = (of_limit + 1) >> 1; let binomial_limit = odd_central_binomial_table(of_limit); println!(); odd_central_binomial_inverse_table(of_limit, binomial_limit); println!(); central_binomial_2_fac_table(of_limit, binomial_limit); println!(); factorial_2_count_table(u64::exact_from(ext_limit)); } ================================================ FILE: malachite-nz/src/bin_util/generate/mod.rs ================================================ // Copyright © 2026 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 . pub mod digits_data; pub mod factorial_data; ================================================ FILE: malachite-nz/src/integer/arithmetic/abs.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{Abs, AbsAssign, UnsignedAbs}; impl Abs for Integer { type Output = Self; /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by value. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.abs(), 0); /// assert_eq!(Integer::from(123).abs(), 123); /// assert_eq!(Integer::from(-123).abs(), 123); /// ``` #[inline] fn abs(mut self) -> Self { self.sign = true; self } } impl Abs for &Integer { type Output = Integer; /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by reference. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::ZERO).abs(), 0); /// assert_eq!((&Integer::from(123)).abs(), 123); /// assert_eq!((&Integer::from(-123)).abs(), 123); /// ``` fn abs(self) -> Integer { Integer { sign: true, abs: self.abs.clone(), } } } impl AbsAssign for Integer { /// Replaces an [`Integer`] with its absolute value. /// /// $$ /// x \gets |x|. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.abs_assign(); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(123); /// x.abs_assign(); /// assert_eq!(x, 123); /// /// let mut x = Integer::from(-123); /// x.abs_assign(); /// assert_eq!(x, 123); /// ``` #[inline] fn abs_assign(&mut self) { self.sign = true; } } impl UnsignedAbs for Integer { type Output = Natural; /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by value and converting /// the result to a [`Natural`]. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::UnsignedAbs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.unsigned_abs(), 0); /// assert_eq!(Integer::from(123).unsigned_abs(), 123); /// assert_eq!(Integer::from(-123).unsigned_abs(), 123); /// ``` #[inline] fn unsigned_abs(self) -> Natural { self.abs } } impl UnsignedAbs for &Integer { type Output = Natural; /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by reference and /// converting the result to a [`Natural`]. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::UnsignedAbs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::ZERO).unsigned_abs(), 0); /// assert_eq!((&Integer::from(123)).unsigned_abs(), 123); /// assert_eq!((&Integer::from(-123)).unsigned_abs(), 123); /// ``` #[inline] fn unsigned_abs(self) -> Natural { self.abs.clone() } } impl Integer { /// Finds the absolute value of an [`Integer`], taking the [`Integer`] by reference and /// returning a reference to the internal [`Natural`] absolute value. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(*Integer::ZERO.unsigned_abs_ref(), 0); /// assert_eq!(*Integer::from(123).unsigned_abs_ref(), 123); /// assert_eq!(*Integer::from(-123).unsigned_abs_ref(), 123); /// ``` #[inline] pub const fn unsigned_abs_ref(&self) -> &Natural { &self.abs } /// Mutates the absolute value of an [`Integer`] using a provided closure, and then returns /// whatever the closure returns. /// /// This function is similar to the [`unsigned_abs_ref`](Integer::unsigned_abs_ref) function, /// which returns a reference to the absolute value. A function that returns a _mutable_ /// reference would be too dangerous, as it could leave the [`Integer`] in an invalid state /// (specifically, with a negative sign but a zero absolute value). So rather than returning a /// mutable reference, this function allows mutation of the absolute value using a closure. /// After the closure executes, this function ensures that the [`Integer`] remains valid. /// /// There is only constant time and memory overhead on top of the time and memory used by the /// closure. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// let mut n = Integer::from(-123); /// let remainder = n.mutate_unsigned_abs(|x| x.div_assign_mod(Natural::TWO)); /// assert_eq!(n, -61); /// assert_eq!(remainder, 1); /// /// let mut n = Integer::from(-123); /// n.mutate_unsigned_abs(|x| *x >>= 10); /// assert_eq!(n, 0); /// ``` pub fn mutate_unsigned_abs T, T>(&mut self, f: F) -> T { let out = f(&mut self.abs); if !self.sign && self.abs == 0 { self.sign = true; } out } } ================================================ FILE: malachite-nz/src/integer/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018, 2020 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{AbsAssign, AbsDiff, AbsDiffAssign, UnsignedAbs}; impl AbsDiff for Integer { type Output = Natural; /// Computes the absolute value of the difference between two [`Integer`]s, taking both by /// value. A [`Natural`] is returned. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123).abs_diff(Integer::ZERO), 123); /// assert_eq!(Integer::ZERO.abs_diff(Integer::from(123)), 123); /// assert_eq!(Integer::from(456).abs_diff(Integer::from(-123)), 579); /// assert_eq!(Integer::from(123).abs_diff(Integer::from(-456)), 579); /// assert_eq!( /// (Integer::from(10).pow(12) * Integer::from(3)).abs_diff(Integer::from(10).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (-Integer::from(10).pow(12)).abs_diff(-Integer::from(10).pow(12) * Integer::from(3)), /// 2000000000000u64 /// ); /// ``` #[inline] fn abs_diff(self, other: Self) -> Natural { (self - other).unsigned_abs() } } impl AbsDiff<&Self> for Integer { type Output = Natural; /// Computes the absolute value of the difference between two [`Integer`]s, taking the first by /// value and the second by reference. A [`Natural`] is returned. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123).abs_diff(&Integer::ZERO), 123); /// assert_eq!(Integer::ZERO.abs_diff(&Integer::from(123)), 123); /// assert_eq!(Integer::from(456).abs_diff(&Integer::from(-123)), 579); /// assert_eq!(Integer::from(123).abs_diff(&Integer::from(-456)), 579); /// assert_eq!( /// (Integer::from(10).pow(12) * Integer::from(3)).abs_diff(&Integer::from(10).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (-Integer::from(10).pow(12)).abs_diff(&(-Integer::from(10).pow(12) * Integer::from(3))), /// 2000000000000u64 /// ); /// ``` #[inline] fn abs_diff(self, other: &Self) -> Natural { (self - other).unsigned_abs() } } impl AbsDiff for &Integer { type Output = Natural; /// Computes the absolute value of the difference between two [`Integer`]s, taking the first by /// reference and the second by value. A [`Natural`] is returned. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(123)).abs_diff(Integer::ZERO), 123); /// assert_eq!((&Integer::ZERO).abs_diff(Integer::from(123)), 123); /// assert_eq!((&Integer::from(456)).abs_diff(Integer::from(-123)), 579); /// assert_eq!((&Integer::from(123)).abs_diff(Integer::from(-456)), 579); /// assert_eq!( /// (&(Integer::from(10).pow(12) * Integer::from(3))).abs_diff(Integer::from(10).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (&(-Integer::from(10).pow(12))).abs_diff(-Integer::from(10).pow(12) * Integer::from(3)), /// 2000000000000u64 /// ); /// ``` #[inline] fn abs_diff(self, other: Integer) -> Natural { (self - other).unsigned_abs() } } impl AbsDiff<&Integer> for &Integer { type Output = Natural; /// Computes the absolute value of the difference between two [`Integer`]s, taking both by /// reference. A [`Natural`] is returned. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(123)).abs_diff(&Integer::ZERO), 123); /// assert_eq!((&Integer::ZERO).abs_diff(&Integer::from(123)), 123); /// assert_eq!((&Integer::from(456)).abs_diff(&Integer::from(-123)), 579); /// assert_eq!((&Integer::from(123)).abs_diff(&Integer::from(-456)), 579); /// assert_eq!( /// (&(Integer::from(10).pow(12) * Integer::from(3))).abs_diff(&Integer::from(10).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (&(-Integer::from(10).pow(12))) /// .abs_diff(&(-Integer::from(10).pow(12) * Integer::from(3))), /// 2000000000000u64 /// ); /// ``` #[inline] fn abs_diff(self, other: &Integer) -> Natural { (self - other).unsigned_abs() } } impl AbsDiffAssign for Integer { /// Subtracts an [`Integer`] by another [`Integer`] in place and takes the absolute value, /// taking the [`Integer`] on the right-hand side by value. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiffAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(123); /// x.abs_diff_assign(Integer::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Integer::ZERO; /// x.abs_diff_assign(Integer::from(123)); /// assert_eq!(x, 123); /// /// let mut x = Integer::from(456); /// x.abs_diff_assign(Integer::from(-123)); /// assert_eq!(x, 579); /// /// let mut x = Integer::from(-123); /// x.abs_diff_assign(Integer::from(456)); /// assert_eq!(x, 579); /// /// let mut x = Integer::from(10).pow(12) * Integer::from(3); /// x.abs_diff_assign(Integer::from(10u32).pow(12)); /// assert_eq!(x, 2000000000000u64); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.abs_diff_assign(-(Integer::from(10).pow(12) * Integer::from(3))); /// assert_eq!(x, 2000000000000u64); /// ``` #[inline] fn abs_diff_assign(&mut self, other: Self) { *self -= other; self.abs_assign(); } } impl<'a> AbsDiffAssign<&'a Self> for Integer { /// Subtracts an [`Integer`] by another [`Integer`] in place and takes the absolute value, /// taking the [`Integer`] on the right-hand side by reference. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiffAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(123); /// x.abs_diff_assign(&Integer::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Integer::ZERO; /// x.abs_diff_assign(&Integer::from(123)); /// assert_eq!(x, 123); /// /// let mut x = Integer::from(456); /// x.abs_diff_assign(&Integer::from(-123)); /// assert_eq!(x, 579); /// /// let mut x = Integer::from(-123); /// x.abs_diff_assign(&Integer::from(456)); /// assert_eq!(x, 579); /// /// let mut x = Integer::from(10).pow(12) * Integer::from(3); /// x.abs_diff_assign(&Integer::from(10u32).pow(12)); /// assert_eq!(x, 2000000000000u64); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.abs_diff_assign(&(-(Integer::from(10).pow(12) * Integer::from(3)))); /// assert_eq!(x, 2000000000000u64); /// ``` #[inline] fn abs_diff_assign(&mut self, other: &'a Self) { *self -= other; self.abs_assign(); } } ================================================ FILE: malachite-nz/src/integer/arithmetic/add.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::iter::Sum; use core::mem::swap; use core::ops::{Add, AddAssign}; use malachite_base::num::basic::traits::Zero; impl Add for Integer { type Output = Self; /// Adds two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO + Integer::from(123), 123); /// assert_eq!(Integer::from(-123) + Integer::ZERO, -123); /// assert_eq!(Integer::from(-123) + Integer::from(456), 333); /// assert_eq!( /// -Integer::from(10u32).pow(12) + (Integer::from(10u32).pow(12) << 1), /// 1000000000000u64 /// ); /// ``` fn add(mut self, mut other: Self) -> Self { if self.abs.limb_count() >= other.abs.limb_count() { self += other; self } else { other += self; other } } } impl Add<&Self> for Integer { type Output = Self; /// Adds two [`Integer`]s, taking the first by reference and the second by value. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO + &Integer::from(123), 123); /// assert_eq!(Integer::from(-123) + &Integer::ZERO, -123); /// assert_eq!(Integer::from(-123) + &Integer::from(456), 333); /// assert_eq!( /// -Integer::from(10u32).pow(12) + &(Integer::from(10u32).pow(12) << 1), /// 1000000000000u64 /// ); /// ``` #[inline] fn add(mut self, other: &Self) -> Self { self += other; self } } impl Add for &Integer { type Output = Integer; /// Adds two [`Integer`]s, taking the first by value and the second by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ZERO + Integer::from(123), 123); /// assert_eq!(&Integer::from(-123) + Integer::ZERO, -123); /// assert_eq!(&Integer::from(-123) + Integer::from(456), 333); /// assert_eq!( /// &-Integer::from(10u32).pow(12) + (Integer::from(10u32).pow(12) << 1), /// 1000000000000u64 /// ); /// ``` #[inline] fn add(self, mut other: Integer) -> Integer { other += self; other } } impl Add<&Integer> for &Integer { type Output = Integer; /// Adds two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ZERO + &Integer::from(123), 123); /// assert_eq!(&Integer::from(-123) + &Integer::ZERO, -123); /// assert_eq!(&Integer::from(-123) + &Integer::from(456), 333); /// assert_eq!( /// &-Integer::from(10u32).pow(12) + &(Integer::from(10u32).pow(12) << 1), /// 1000000000000u64 /// ); /// ``` fn add(self, other: &Integer) -> Integer { match (self, other) { (x, y) if core::ptr::eq(x, y) => x << 1, (&integer_zero!(), y) => y.clone(), (x, &integer_zero!()) => x.clone(), // e.g. 10 + 5 or -10 + -5; sign of result is sign of self ( &Integer { sign: sx, abs: ref ax, }, &Integer { sign: sy, abs: ref ay, }, ) if sx == (sy && *ay != 0) => Integer { sign: sx, abs: ax + ay, }, // e.g. 10 + -5, -10 + 5, or 5 + -5; sign of result is sign of self ( &Integer { sign: sx, abs: ref ax, }, Integer { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => Integer { sign: sx, abs: ax - ay, }, // e.g. 5 + -10, -5 + 10, or -5 + 5; sign of result is sign of other ( Integer { abs: ax, .. }, &Integer { sign: sy, abs: ref ay, }, ) => Integer { sign: sy, abs: ay - ax, }, } } } impl AddAssign for Integer { /// Adds an [`Integer`] to an [`Integer`] in place, taking the [`Integer`] on the right-hand /// side by value. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x += -Integer::from(10u32).pow(12); /// x += Integer::from(10u32).pow(12) * Integer::from(2u32); /// x += -Integer::from(10u32).pow(12) * Integer::from(3u32); /// x += Integer::from(10u32).pow(12) * Integer::from(4u32); /// assert_eq!(x, 2000000000000u64); /// ``` fn add_assign(&mut self, mut other: Self) { match (&mut *self, &other) { (_, &integer_zero!()) => {} (&mut integer_zero!(), _) => { *self = other; } // e.g. 10 += 5 or -10 += -5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) if sx == (sy && *ay != 0) => *ax += ay, // e.g. 10 += -5, -10 += 5, or 5 += -5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, Self { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => *ax -= ay, // e.g. 5 += -10, -5 += 10, or -5 += 5; sign of self is flipped _ => { swap(self, &mut other); self.abs -= other.abs; } }; } } impl AddAssign<&Self> for Integer { /// Adds an [`Integer`] to an [`Integer`] in place, taking the [`Integer`] on the right-hand /// side by reference. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x += &(-Integer::from(10u32).pow(12)); /// x += &(Integer::from(10u32).pow(12) * Integer::from(2u32)); /// x += &(-Integer::from(10u32).pow(12) * Integer::from(3u32)); /// x += &(Integer::from(10u32).pow(12) * Integer::from(4u32)); /// assert_eq!(x, 2000000000000u64); /// ``` fn add_assign(&mut self, other: &Self) { match (&mut *self, other) { (_, &integer_zero!()) => {} (&mut integer_zero!(), _) => { *self = other.clone(); } // e.g. 10 += 5 or -10 += -5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) if sx == (sy && *ay != 0) => *ax += ay, // e.g. 10 += -5, -10 += 5, or 5 += -5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, Self { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => *ax -= ay, // e.g. 5 += -10, -5 += 10, or -5 += 5; sign of self is flipped ( &mut Self { sign: ref mut sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) => { *sx = sy; ax.sub_right_assign_no_panic(ay); } }; } } impl Sum for Integer { /// Adds up all the [`Integer`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Integer::sum(xs.map(Integer::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Sum; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::sum( /// vec_from_str::("[2, -3, 5, 7]") /// .unwrap() /// .into_iter() /// ), /// 11 /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut s = Self::ZERO; for x in xs { s += x; } s } } impl<'a> Sum<&'a Self> for Integer { /// Adds up all the [`Integer`]s in an iterator of [`Integer`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Integer::sum(xs.map(Integer::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Sum; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::sum(vec_from_str::("[2, -3, 5, 7]").unwrap().iter()), /// 11 /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut s = Self::ZERO; for x in xs { s += x; } s } } ================================================ FILE: malachite-nz/src/integer/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::arithmetic::sub_mul::{ limbs_overflowing_sub_mul, limbs_overflowing_sub_mul_in_place_left, limbs_overflowing_sub_mul_limb, limbs_overflowing_sub_mul_limb_in_place_either, limbs_overflowing_sub_mul_limb_in_place_left, }; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign}; use malachite_base::num::basic::traits::Zero; impl Natural { // self - b * c, returns sign (true means non-negative) fn add_mul_limb_neg(&self, b: &Self, c: Limb) -> (Self, bool) { match (self, b, c) { (x, &Self::ZERO, _) | (x, _, 0) => (x.clone(), true), (x, y, 1) if x >= y => (x - y, true), (x, y, 1) => (y - x, false), (Self(Large(xs)), Self(Large(ys)), z) => { let (out_limbs, sign) = limbs_overflowing_sub_mul_limb(xs, ys, z); (Self::from_owned_limbs_asc(out_limbs), sign) } (x, y, z) => { let yz = y * Self::from(z); if *x >= yz { (x - yz, true) } else { (yz - x, false) } } } } // self -= b * c, returns sign (true means non-negative) fn add_mul_assign_limb_neg(&mut self, mut b: Self, c: Limb) -> bool { match (&mut *self, &mut b, c) { (_, &mut Self::ZERO, _) | (_, _, 0) => true, (x, y, 1) if *x >= *y => { self.sub_assign_no_panic(b); true } (x, y, 1) => { x.sub_right_assign_no_panic(&*y); false } (Self(Large(xs)), Self(Large(ys)), z) => { let (right, sign) = limbs_overflowing_sub_mul_limb_in_place_either(xs, ys, z); if right { b.trim(); *self = b; } else { self.trim(); } sign } (x, _, z) => { let yz = b * Self(Small(z)); let sign = *x >= yz; if sign { x.sub_assign_no_panic(yz); } else { x.sub_right_assign_no_panic(&yz); } sign } } } // self -= &b * c, returns sign (true means non-negative) fn add_mul_assign_limb_neg_ref(&mut self, b: &Self, c: Limb) -> bool { match (&mut *self, b, c) { (_, &Self::ZERO, _) | (_, _, 0) => true, (x, y, 1) if *x >= *y => { self.sub_assign_ref_no_panic(y); true } (x, y, 1) => { x.sub_right_assign_no_panic(y); false } (Self(Large(xs)), Self(Large(ys)), z) => { let sign = limbs_overflowing_sub_mul_limb_in_place_left(xs, ys, z); self.trim(); sign } (x, _, z) => { let yz = b * Self(Small(z)); let sign = *x >= yz; if sign { x.sub_assign_no_panic(yz); } else { x.sub_right_assign_no_panic(&yz); } sign } } } // self - &b * c, returns sign (true means non-negative) pub(crate) fn add_mul_neg(&self, b: &Self, c: &Self) -> (Self, bool) { match (self, b, c) { (x, &Self(Small(y)), z) => x.add_mul_limb_neg(z, y), (x, y, &Self(Small(z))) => x.add_mul_limb_neg(y, z), (&Self(Small(x)), y, z) => ((y * z).sub_limb(x), false), (Self(Large(xs)), Self(Large(ys)), Self(Large(zs))) => { let (out_limbs, sign) = limbs_overflowing_sub_mul(xs, ys, zs); (Self::from_owned_limbs_asc(out_limbs), sign) } } } fn add_mul_assign_neg_large(&mut self, ys: &[Limb], zs: &[Limb]) -> bool { let xs = self.promote_in_place(); let sign = limbs_overflowing_sub_mul_in_place_left(xs, ys, zs); self.trim(); sign } // self -= b * c, returns sign (true means non-negative) fn add_mul_assign_neg(&mut self, b: Self, c: Self) -> bool { match (&mut *self, b, c) { (x, Self(Small(y)), z) => x.add_mul_assign_limb_neg(z, y), (x, y, Self(Small(z))) => x.add_mul_assign_limb_neg(y, z), (&mut Self::ZERO, y, z) => { *self = y * z; false } (_, Self(Large(ys)), Self(Large(zs))) => self.add_mul_assign_neg_large(&ys, &zs), } } // self -= b * &c, returns sign (true means non-negative) fn add_mul_assign_neg_val_ref(&mut self, b: Self, c: &Self) -> bool { match (&mut *self, b, c) { (x, Self(Small(y)), z) => x.add_mul_assign_limb_neg_ref(z, y), (x, y, &Self(Small(z))) => x.add_mul_assign_limb_neg(y, z), (&mut Self::ZERO, y, z) => { *self = y * z; false } (_, Self(Large(ys)), Self(Large(zs))) => self.add_mul_assign_neg_large(&ys, zs), } } // self -= &b * c, returns sign (true means non-negative) fn add_mul_assign_neg_ref_val(&mut self, b: &Self, c: Self) -> bool { match (&mut *self, b, c) { (x, &Self(Small(y)), z) => x.add_mul_assign_limb_neg(z, y), (x, y, Self(Small(z))) => x.add_mul_assign_limb_neg_ref(y, z), (&mut Self::ZERO, y, z) => { *self = y * z; false } (_, Self(Large(ys)), Self(Large(zs))) => self.add_mul_assign_neg_large(ys, &zs), } } // self -= &b * &c, returns sign (true means non-negative) fn add_mul_assign_neg_ref_ref(&mut self, b: &Self, c: &Self) -> bool { match (&mut *self, b, c) { (x, &Self(Small(y)), z) => x.add_mul_assign_limb_neg_ref(z, y), (x, y, &Self(Small(z))) => x.add_mul_assign_limb_neg_ref(y, z), (&mut Self::ZERO, y, z) => { *self = y * z; false } (_, Self(Large(ys)), Self(Large(zs))) => self.add_mul_assign_neg_large(ys, zs), } } } impl AddMul for Integer { type Output = Self; /// Adds an [`Integer`] and the product of two other [`Integer`]s, taking all three by value. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).add_mul(Integer::from(3u32), Integer::from(4u32)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .add_mul(Integer::from(0x10000), -Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn add_mul(mut self, y: Self, z: Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a> AddMul for Integer { type Output = Self; /// Adds an [`Integer`] and the product of two other [`Integer`]s, taking the first two by value /// and the third by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).add_mul(Integer::from(3u32), &Integer::from(4u32)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .add_mul(Integer::from(0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn add_mul(mut self, y: Self, z: &'a Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a> AddMul<&'a Self, Self> for Integer { type Output = Self; /// Adds an [`Integer`] and the product of two other [`Integer`]s, taking the first and third by /// value and the second by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).add_mul(&Integer::from(3u32), Integer::from(4u32)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .add_mul(&Integer::from(0x10000), -Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn add_mul(mut self, y: &'a Self, z: Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a, 'b> AddMul<&'a Self, &'b Self> for Integer { type Output = Self; /// Adds an [`Integer`] and the product of two other [`Integer`]s, taking the first by value and /// the second and third by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).add_mul(&Integer::from(3u32), &Integer::from(4u32)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .add_mul(&Integer::from(0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn add_mul(mut self, y: &'a Self, z: &'b Self) -> Self { self.add_mul_assign(y, z); self } } impl AddMul<&Integer, &Integer> for &Integer { type Output = Integer; /// Adds an [`Integer`] and the product of two other [`Integer`]s, taking all three by /// reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n, m) = O(m + n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(10u32)).add_mul(&Integer::from(3u32), &Integer::from(4u32)), /// 22 /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)) /// .add_mul(&Integer::from(0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` fn add_mul(self, y: &Integer, z: &Integer) -> Integer { if self.sign == (y.sign == z.sign) { Integer { sign: self.sign, abs: (&self.abs).add_mul(&y.abs, &z.abs), } } else { let (abs, abs_result_sign) = self.abs.add_mul_neg(&y.abs, &z.abs); Integer { sign: (self.sign == abs_result_sign) || abs == 0, abs, } } } } impl AddMulAssign for Integer { /// Adds the product of two other [`Integer`]s to an [`Integer`] in place, taking both /// [`Integer`]s on the right-hand side by value. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.add_mul_assign(Integer::from(3u32), Integer::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.add_mul_assign(Integer::from(0x10000), -Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn add_mul_assign(&mut self, y: Self, z: Self) { if self.sign == (y.sign == z.sign) { self.abs.add_mul_assign(y.abs, z.abs); } else { let sign = self.abs.add_mul_assign_neg(y.abs, z.abs); self.sign = (self.sign == sign) || self.abs == 0; } } } impl<'a> AddMulAssign for Integer { /// Adds the product of two other [`Integer`]s to an [`Integer`] in place, taking the first /// [`Integer`] on the right-hand side by value and the second by reference. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.add_mul_assign(Integer::from(3u32), &Integer::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.add_mul_assign(Integer::from(0x10000), &-Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn add_mul_assign(&mut self, y: Self, z: &'a Self) { if self.sign == (y.sign == z.sign) { self.abs.add_mul_assign(y.abs, &z.abs); } else { let sign = self.abs.add_mul_assign_neg_val_ref(y.abs, &z.abs); self.sign = (self.sign == sign) || self.abs == 0; } } } impl<'a> AddMulAssign<&'a Self, Self> for Integer { /// Adds the product of two other [`Integer`]s to an [`Integer`] in place, taking the first /// [`Integer`] on the right-hand side by reference and the second by value. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.add_mul_assign(&Integer::from(3u32), Integer::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.add_mul_assign(&Integer::from(0x10000), -Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn add_mul_assign(&mut self, y: &'a Self, z: Self) { if self.sign == (y.sign == z.sign) { self.abs.add_mul_assign(&y.abs, z.abs); } else { let sign = self.abs.add_mul_assign_neg_ref_val(&y.abs, z.abs); self.sign = (self.sign == sign) || self.abs == 0; } } } impl<'a, 'b> AddMulAssign<&'a Self, &'b Self> for Integer { /// Adds the product of two other [`Integer`]s to an [`Integer`] in place, taking both /// [`Integer`]s on the right-hand side by reference. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.add_mul_assign(&Integer::from(3u32), &Integer::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.add_mul_assign(&Integer::from(0x10000), &-Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn add_mul_assign(&mut self, y: &'a Self, z: &'b Self) { if self.sign == (y.sign == z.sign) { self.abs.add_mul_assign(&y.abs, &z.abs); } else { let sign = self.abs.add_mul_assign_neg_ref_ref(&y.abs, &z.abs); self.sign = (self.sign == sign) || self.abs == 0; } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{BinomialCoefficient, Parity}; use malachite_base::num::basic::traits::One; impl BinomialCoefficient for Integer { /// Computes the binomial coefficient of two [`Integer`]s, taking both by value. /// /// The second argument must be non-negative, but the first may be negative. If it is, the /// identity $\binom{-n}{k} = (-1)^k \binom{n+k-1}{k}$ is used. /// /// $$ /// f(n, k) = \\begin{cases} /// \binom{n}{k} & \text{if} \\quad n \geq 0, \\\\ /// (-1)^k \binom{-n+k-1}{k} & \text{if} \\quad n < 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// TODO /// /// # Panics /// Panics if $k$ is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::BinomialCoefficient; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(4), Integer::from(0)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(4), Integer::from(1)), /// 4 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(4), Integer::from(2)), /// 6 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(4), Integer::from(3)), /// 4 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(4), Integer::from(4)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(10), Integer::from(5)), /// 252 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(100), Integer::from(50)).to_string(), /// "100891344545564193334812497256" /// ); /// /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(-3), Integer::from(0)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(-3), Integer::from(1)), /// -3 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(-3), Integer::from(2)), /// 6 /// ); /// assert_eq!( /// Integer::binomial_coefficient(Integer::from(-3), Integer::from(3)), /// -10 /// ); /// ``` fn binomial_coefficient(n: Self, k: Self) -> Self { assert!(k.sign); if n.sign { Self::from(Natural::binomial_coefficient(n.abs, k.abs)) } else { let k_abs = k.abs; Self { sign: k_abs.even(), abs: Natural::binomial_coefficient(n.abs + &k_abs - Natural::ONE, k_abs), } } } } impl<'a> BinomialCoefficient<&'a Self> for Integer { /// Computes the binomial coefficient of two [`Integer`]s, taking both by reference. /// /// The second argument must be non-negative, but the first may be negative. If it is, the /// identity $\binom{-n}{k} = (-1)^k \binom{n+k-1}{k}$ is used. /// /// $$ /// f(n, k) = \\begin{cases} /// \binom{n}{k} & \text{if} \\quad n \geq 0, \\\\ /// (-1)^k \binom{-n+k-1}{k} & \text{if} \\quad n < 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// TODO /// /// # Panics /// Panics if $k$ is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::BinomialCoefficient; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(4), &Integer::from(0)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(4), &Integer::from(1)), /// 4 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(4), &Integer::from(2)), /// 6 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(4), &Integer::from(3)), /// 4 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(4), &Integer::from(4)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(10), &Integer::from(5)), /// 252 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(100), &Integer::from(50)).to_string(), /// "100891344545564193334812497256" /// ); /// /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(-3), &Integer::from(0)), /// 1 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(-3), &Integer::from(1)), /// -3 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(-3), &Integer::from(2)), /// 6 /// ); /// assert_eq!( /// Integer::binomial_coefficient(&Integer::from(-3), &Integer::from(3)), /// -10 /// ); /// ``` fn binomial_coefficient(n: &'a Self, k: &'a Self) -> Self { assert!(k.sign); if n.sign { Self::from(Natural::binomial_coefficient(&n.abs, &k.abs)) } else { let k_abs = &k.abs; Self { sign: k_abs.even(), abs: Natural::binomial_coefficient(&(&n.abs + k_abs - Natural::ONE), k_abs), } } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/div.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::{Div, DivAssign}; use malachite_base::num::arithmetic::traits::CheckedDiv; use malachite_base::num::basic::traits::Zero; impl Div for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value. The quotient is rounded /// towards zero. The quotient and remainder (which is not computed) satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23) / Integer::from(10), 2); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(Integer::from(23) / Integer::from(-10), -2); /// /// // -2 * 10 + -3 = -23 /// assert_eq!(Integer::from(-23) / Integer::from(10), -2); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23) / Integer::from(-10), 2); /// ``` #[inline] fn div(mut self, other: Self) -> Self { self /= other; self } } impl Div<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference. The quotient is rounded towards zero. The quotient and remainder (which is not /// computed) satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23) / &Integer::from(10), 2); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(Integer::from(23) / &Integer::from(-10), -2); /// /// // -2 * 10 + -3 = -23 /// assert_eq!(Integer::from(-23) / &Integer::from(10), -2); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23) / &Integer::from(-10), 2); /// ``` #[inline] fn div(mut self, other: &Self) -> Self { self /= other; self } } impl Div for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value. The quotient is rounded towards zero. The quotient and remainder (which is not /// computed) satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Integer::from(23) / Integer::from(10), 2); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(&Integer::from(23) / Integer::from(-10), -2); /// /// // -2 * 10 + -3 = -23 /// assert_eq!(&Integer::from(-23) / Integer::from(10), -2); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(&Integer::from(-23) / Integer::from(-10), 2); /// ``` #[inline] fn div(self, other: Integer) -> Integer { Integer::from_sign_and_abs(self.sign == other.sign, &self.abs / other.abs) } } impl Div<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference. The quotient is /// rounded towards zero. The quotient and remainder (which is not computed) satisfy $x = qy + /// r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Integer::from(23) / &Integer::from(10), 2); /// /// // -2 * -10 + 3 = 23 /// assert_eq!(&Integer::from(23) / &Integer::from(-10), -2); /// /// // -2 * 10 + -3 = -23 /// assert_eq!(&Integer::from(-23) / &Integer::from(10), -2); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(&Integer::from(-23) / &Integer::from(-10), 2); /// ``` #[inline] fn div(self, other: &Integer) -> Integer { Integer::from_sign_and_abs(self.sign == other.sign, &self.abs / &other.abs) } } impl DivAssign for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. The quotient is rounded towards zero. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x /= Integer::from(10); /// assert_eq!(x, 2); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// x /= Integer::from(-10); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// x /= Integer::from(10); /// assert_eq!(x, -2); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x /= Integer::from(-10); /// assert_eq!(x, 2); /// ``` #[inline] fn div_assign(&mut self, other: Self) { self.abs /= other.abs; self.sign = self.sign == other.sign || self.abs == 0; } } impl DivAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. The quotient is rounded towards zero. The quotient and /// remainder (which is not computed) satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x /= &Integer::from(10); /// assert_eq!(x, 2); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// x /= &Integer::from(-10); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// x /= &Integer::from(10); /// assert_eq!(x, -2); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x /= &Integer::from(-10); /// assert_eq!(x, 2); /// ``` #[inline] fn div_assign(&mut self, other: &Self) { self.abs /= &other.abs; self.sign = self.sign == other.sign || self.abs == 0; } } impl CheckedDiv for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value. The quotient is rounded /// towards negative infinity. The quotient and remainder (which is not computed) satisfy $x = /// qy + r$ and $0 \leq r < y$. Returns `None` when the second [`Integer`] is zero, `Some` /// otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .checked_div(Integer::from(-10)) /// .to_debug_string(), /// "Some(-2)" /// ); /// assert_eq!(Integer::ONE.checked_div(Integer::ZERO), None); /// ``` #[inline] fn checked_div(self, other: Self) -> Option { match (self, other) { (_, integer_zero!()) => None, (x, y) => Some(x / y), } } } impl CheckedDiv<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the /// second [`Integer`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .checked_div(&Integer::from(-10)) /// .to_debug_string(), /// "Some(-2)" /// ); /// assert_eq!(Integer::ONE.checked_div(&Integer::ZERO), None); /// ``` #[inline] fn checked_div(self, other: &Self) -> Option { match (self, other) { (_, &integer_zero!()) => None, (x, y) => Some(x / y), } } } impl CheckedDiv for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the /// second [`Integer`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .checked_div(Integer::from(-10)) /// .to_debug_string(), /// "Some(-2)" /// ); /// assert_eq!((&Integer::ONE).checked_div(Integer::ZERO), None); /// ``` fn checked_div(self, other: Integer) -> Option { match (self, other) { (_, integer_zero!()) => None, (x, y) => Some(x / y), } } } impl CheckedDiv<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference. The quotient is /// rounded towards negative infinity. The quotient and remainder (which is not computed) /// satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the second [`Integer`] is zero, /// `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .checked_div(&Integer::from(-10)) /// .to_debug_string(), /// "Some(-2)" /// ); /// assert_eq!((&Integer::ONE).checked_div(&Integer::ZERO), None); /// ``` fn checked_div(self, other: &Integer) -> Option { match (self, other) { (_, &integer_zero!()) => None, (x, y) => Some(x / y), } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign}; impl DivExact for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value. The first [`Integer`] /// must be exactly divisible by the second. If it isn't, this function may panic or return a /// meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self / other` instead. If you're /// unsure and you want to know, use `self.div_mod(other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `self.div_round(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// assert_eq!(Integer::from(-56088).div_exact(Integer::from(456)), -123); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// assert_eq!( /// Integer::from_str("121932631112635269000000") /// .unwrap() /// .div_exact(Integer::from_str("-987654321000").unwrap()), /// -123456789000i64 /// ); /// ``` #[inline] fn div_exact(mut self, other: Self) -> Self { self.div_exact_assign(other); self } } impl DivExact<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference. The first [`Integer`] must be exactly divisible by the second. If it isn't, this /// function may panic or return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self / &other` instead. If you're /// unsure and you want to know, use `self.div_mod(&other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `self.div_round(&other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// assert_eq!(Integer::from(-56088).div_exact(&Integer::from(456)), -123); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// assert_eq!( /// Integer::from_str("121932631112635269000000") /// .unwrap() /// .div_exact(&Integer::from_str("-987654321000").unwrap()), /// -123456789000i64 /// ); /// ``` #[inline] fn div_exact(mut self, other: &Self) -> Self { self.div_exact_assign(other); self } } impl DivExact for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value. The first [`Integer`] must be exactly divisible by the second. If it isn't, this /// function may panic or return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `&self / other` instead. If you're /// unsure and you want to know, use `self.div_mod(other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `(&self).div_round(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// assert_eq!((&Integer::from(-56088)).div_exact(Integer::from(456)), -123); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// assert_eq!( /// (&Integer::from_str("121932631112635269000000").unwrap()) /// .div_exact(Integer::from_str("-987654321000").unwrap()), /// -123456789000i64 /// ); /// ``` fn div_exact(self, other: Integer) -> Integer { let q_abs = (&self.abs).div_exact(other.abs); Integer { sign: self.sign == other.sign || q_abs == 0, abs: q_abs, } } } impl DivExact<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference. The first /// [`Integer`] must be exactly divisible by the second. If it isn't, this function may panic or /// return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `&self / &other` instead. If /// you're unsure and you want to know, use `(&self).div_mod(&other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `(&self).div_round(&other, Exact)`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// assert_eq!( /// (&Integer::from(-56088)).div_exact(&Integer::from(456)), /// -123 /// ); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// assert_eq!( /// (&Integer::from_str("121932631112635269000000").unwrap()) /// .div_exact(&Integer::from_str("-987654321000").unwrap()), /// -123456789000i64 /// ); /// ``` fn div_exact(self, other: &Integer) -> Integer { let q_abs = (&self.abs).div_exact(&other.abs); Integer { sign: self.sign == other.sign || q_abs == 0, abs: q_abs, } } } impl DivExactAssign for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. The first [`Integer`] must be exactly divisible by the second. If /// it isn't, this function may panic or return a meaningless result. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self /= other` instead. If you're /// unsure and you want to know, use `self.div_assign_mod(other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `self.div_round_assign(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExactAssign; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// let mut x = Integer::from(-56088); /// x.div_exact_assign(Integer::from(456)); /// assert_eq!(x, -123); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// let mut x = Integer::from_str("121932631112635269000000").unwrap(); /// x.div_exact_assign(Integer::from_str("-987654321000").unwrap()); /// assert_eq!(x, -123456789000i64); /// ``` fn div_exact_assign(&mut self, other: Self) { self.abs.div_exact_assign(other.abs); self.sign = self.sign == other.sign || self.abs == 0; } } impl DivExactAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. The first [`Integer`] must be exactly divisible by the second. /// If it isn't, this function may panic or return a meaningless result. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self /= &other` instead. If /// you're unsure and you want to know, use `self.div_assign_mod(&other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `self.div_round_assign(&other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExactAssign; /// use malachite_nz::integer::Integer; /// /// // -123 * 456 = -56088 /// let mut x = Integer::from(-56088); /// x.div_exact_assign(&Integer::from(456)); /// assert_eq!(x, -123); /// /// // -123456789000 * -987654321000 = 121932631112635269000000 /// let mut x = Integer::from_str("121932631112635269000000").unwrap(); /// x.div_exact_assign(&Integer::from_str("-987654321000").unwrap()); /// assert_eq!(x, -123456789000i64); /// ``` fn div_exact_assign(&mut self, other: &Self) { self.abs.div_exact_assign(&other.abs); self.sign = self.sign == other.sign || self.abs == 0; } } ================================================ FILE: malachite-nz/src/integer/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::{ CeilingDivAssignMod, CeilingDivAssignNegMod, CeilingDivMod, CeilingDivNegMod, DivAssignMod, DivAssignRem, DivMod, DivRem, }; impl DivMod for Integer { type DivOutput = Self; type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning the /// quotient and remainder. The quotient is rounded towards negative infinity, and the remainder /// has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_mod(Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -3 * -10 + -7 = 23 /// assert_eq!( /// Integer::from(23) /// .div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(-3, -7)" /// ); /// /// // -3 * 10 + 7 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_mod(Integer::from(10)) /// .to_debug_string(), /// "(-3, 7)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_mod(mut self, other: Self) -> (Self, Self) { let r = self.div_assign_mod(other); (self, r) } } impl DivMod<&Self> for Integer { type DivOutput = Self; type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and returning the quotient and remainder. The quotient is rounded towards negative /// infinity, and the remainder has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -3 * -10 + -7 = 23 /// assert_eq!( /// Integer::from(23) /// .div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(-3, -7)" /// ); /// /// // -3 * 10 + 7 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(-3, 7)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_mod(mut self, other: &Self) -> (Self, Self) { let r = self.div_assign_mod(other); (self, r) } } impl DivMod for &Integer { type DivOutput = Integer; type ModOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning the quotient and remainder. The quotient is rounded towards negative /// infinity, and the remainder has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_mod(Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -3 * -10 + -7 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(-3, -7)" /// ); /// /// // -3 * 10 + 7 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_mod(Integer::from(10)) /// .to_debug_string(), /// "(-3, 7)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` fn div_mod(self, other: Integer) -> (Integer, Integer) { let q_sign = self.sign == other.sign; let (q, r) = if q_sign { (&self.abs).div_mod(other.abs) } else { (&self.abs).ceiling_div_neg_mod(other.abs) }; ( Integer::from_sign_and_abs(q_sign, q), Integer::from_sign_and_abs(other.sign, r), ) } } impl DivMod<&Integer> for &Integer { type DivOutput = Integer; type ModOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning the /// quotient and remainder. The quotient is rounded towards negative infinity, and the remainder /// has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -3 * -10 + -7 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(-3, -7)" /// ); /// /// // -3 * 10 + 7 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(-3, 7)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` fn div_mod(self, other: &Integer) -> (Integer, Integer) { let q_sign = self.sign == other.sign; let (q, r) = if q_sign { (&self.abs).div_mod(&other.abs) } else { (&self.abs).ceiling_div_neg_mod(&other.abs) }; ( Integer::from_sign_and_abs(q_sign, q), Integer::from_sign_and_abs(other.sign, r), ) } } impl DivAssignMod for Integer { type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards /// negative infinity, and the remainder has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_mod(Integer::from(10)), 3); /// assert_eq!(x, 2); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_mod(Integer::from(-10)), -7); /// assert_eq!(x, -3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_mod(Integer::from(10)), 7); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_mod(Integer::from(-10)), -3); /// assert_eq!(x, 2); /// ``` fn div_assign_mod(&mut self, other: Self) -> Self { let r = if self.sign == other.sign { self.sign = true; self.abs.div_assign_mod(other.abs) } else { let r = self.abs.ceiling_div_assign_neg_mod(other.abs); if self.abs != 0 { self.sign = false; } r }; Self::from_sign_and_abs(other.sign, r) } } impl DivAssignMod<&Self> for Integer { type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference and returning the remainder. The quotient is rounded towards /// negative infinity, and the remainder has the same sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_mod(&Integer::from(10)), 3); /// assert_eq!(x, 2); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_mod(&Integer::from(-10)), -7); /// assert_eq!(x, -3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_mod(&Integer::from(10)), 7); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_mod(&Integer::from(-10)), -3); /// assert_eq!(x, 2); /// ``` fn div_assign_mod(&mut self, other: &Self) -> Self { let r = if self.sign == other.sign { self.sign = true; self.abs.div_assign_mod(&other.abs) } else { let r = self.abs.ceiling_div_assign_neg_mod(&other.abs); if self.abs != 0 { self.sign = false; } r }; Self::from_sign_and_abs(other.sign, r) } } impl DivRem for Integer { type DivOutput = Self; type RemOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning the /// quotient and remainder. The quotient is rounded towards zero and the remainder has the same /// sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor, \space /// x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_rem(Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_rem(Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_rem(Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_rem(Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_rem(mut self, other: Self) -> (Self, Self) { let r = self.div_assign_rem(other); (self, r) } } impl DivRem<&Self> for Integer { type DivOutput = Self; type RemOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and returning the quotient and remainder. The quotient is rounded towards zero and /// the remainder has the same sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor, \space /// x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_rem(&Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .div_rem(&Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_rem(&Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .div_rem(&Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_rem(mut self, other: &Self) -> (Self, Self) { let r = self.div_assign_rem(other); (self, r) } } impl DivRem for &Integer { type DivOutput = Integer; type RemOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning the quotient and remainder. The quotient is rounded towards zero and /// the remainder has the same sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor, \space /// x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_rem(Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_rem(Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_rem(Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_rem(Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_rem(self, other: Integer) -> (Integer, Integer) { let (q, r) = (&self.abs).div_mod(other.abs); ( Integer::from_sign_and_abs(self.sign == other.sign, q), Integer::from_sign_and_abs(self.sign, r), ) } } impl DivRem<&Integer> for &Integer { type DivOutput = Integer; type RemOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning the /// quotient and remainder. The quotient is rounded towards zero and the remainder has the same /// sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor, \space /// x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_rem(&Integer::from(10)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .div_rem(&Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_rem(&Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 2 * -10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .div_rem(&Integer::from(-10)) /// .to_debug_string(), /// "(2, -3)" /// ); /// ``` #[inline] fn div_rem(self, other: &Integer) -> (Integer, Integer) { let (q, r) = (&self.abs).div_mod(&other.abs); ( Integer::from_sign_and_abs(self.sign == other.sign, q), Integer::from_sign_and_abs(self.sign, r), ) } } impl DivAssignRem for Integer { type RemOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards zero /// and the remainder has the same sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor, /// $$ /// $$ /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignRem; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_rem(Integer::from(10)), 3); /// assert_eq!(x, 2); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_rem(Integer::from(-10)), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_rem(Integer::from(10)), -3); /// assert_eq!(x, -2); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_rem(Integer::from(-10)), -3); /// assert_eq!(x, 2); /// ``` #[inline] fn div_assign_rem(&mut self, other: Self) -> Self { let r = Self::from_sign_and_abs(self.sign, self.abs.div_assign_mod(other.abs)); self.sign = self.sign == other.sign || self.abs == 0; r } } impl DivAssignRem<&Self> for Integer { type RemOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference and returning the remainder. The quotient is rounded towards /// zero and the remainder has the same sign as the first [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor, /// $$ /// $$ /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right | /// \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DivAssignRem; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_rem(&Integer::from(10)), 3); /// assert_eq!(x, 2); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.div_assign_rem(&Integer::from(-10)), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_rem(&Integer::from(10)), -3); /// assert_eq!(x, -2); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.div_assign_rem(&Integer::from(-10)), -3); /// assert_eq!(x, 2); /// ``` #[inline] fn div_assign_rem(&mut self, other: &Self) -> Self { let r = Self::from_sign_and_abs(self.sign, self.abs.div_assign_mod(&other.abs)); self.sign = self.sign == other.sign || self.abs == 0; r } } impl CeilingDivMod for Integer { type DivOutput = Self; type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning the /// quotient and remainder. The quotient is rounded towards positive infinity and the remainder /// has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// x - y\left \lceil \frac{x}{y} \right \rceil \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// assert_eq!( /// Integer::from(23) /// .ceiling_div_mod(Integer::from(10)) /// .to_debug_string(), /// "(3, -7)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .ceiling_div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .ceiling_div_mod(Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 3 * -10 + 7 = -23 /// assert_eq!( /// Integer::from(-23) /// .ceiling_div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(3, 7)" /// ); /// ``` #[inline] fn ceiling_div_mod(mut self, other: Self) -> (Self, Self) { let r = self.ceiling_div_assign_mod(other); (self, r) } } impl CeilingDivMod<&Self> for Integer { type DivOutput = Self; type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`], taking both the first by value and the second /// by reference and returning the quotient and remainder. The quotient is rounded towards /// positive infinity and the remainder has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// x - y\left \lceil \frac{x}{y} \right \rceil \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// assert_eq!( /// Integer::from(23) /// .ceiling_div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(3, -7)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// Integer::from(23) /// .ceiling_div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// Integer::from(-23) /// .ceiling_div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 3 * -10 + 7 = -23 /// assert_eq!( /// Integer::from(-23) /// .ceiling_div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(3, 7)" /// ); /// ``` #[inline] fn ceiling_div_mod(mut self, other: &Self) -> (Self, Self) { let r = self.ceiling_div_assign_mod(other); (self, r) } } impl CeilingDivMod for &Integer { type DivOutput = Integer; type ModOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning the quotient and remainder. The quotient is rounded towards positive /// infinity and the remainder has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// x - y\left \lceil \frac{x}{y} \right \rceil \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .ceiling_div_mod(Integer::from(10)) /// .to_debug_string(), /// "(3, -7)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .ceiling_div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .ceiling_div_mod(Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 3 * -10 + 7 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .ceiling_div_mod(Integer::from(-10)) /// .to_debug_string(), /// "(3, 7)" /// ); /// ``` fn ceiling_div_mod(self, other: Integer) -> (Integer, Integer) { let q_sign = self.sign == other.sign; let (q, r) = if q_sign { (&self.abs).ceiling_div_neg_mod(other.abs) } else { (&self.abs).div_mod(other.abs) }; ( Integer::from_sign_and_abs(q_sign, q), Integer::from_sign_and_abs(!other.sign, r), ) } } impl CeilingDivMod<&Integer> for &Integer { type DivOutput = Integer; type ModOutput = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning the /// quotient and remainder. The quotient is rounded towards positive infinity and the remainder /// has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// x - y\left \lceil \frac{x}{y} \right \rceil \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .ceiling_div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(3, -7)" /// ); /// /// // -2 * -10 + 3 = 23 /// assert_eq!( /// (&Integer::from(23)) /// .ceiling_div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(-2, 3)" /// ); /// /// // -2 * 10 + -3 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .ceiling_div_mod(&Integer::from(10)) /// .to_debug_string(), /// "(-2, -3)" /// ); /// /// // 3 * -10 + 7 = -23 /// assert_eq!( /// (&Integer::from(-23)) /// .ceiling_div_mod(&Integer::from(-10)) /// .to_debug_string(), /// "(3, 7)" /// ); /// ``` fn ceiling_div_mod(self, other: &Integer) -> (Integer, Integer) { let q_sign = self.sign == other.sign; let (q, r) = if q_sign { (&self.abs).ceiling_div_neg_mod(&other.abs) } else { (&self.abs).div_mod(&other.abs) }; ( Integer::from_sign_and_abs(q_sign, q), Integer::from_sign_and_abs(!other.sign, r), ) } } impl CeilingDivAssignMod for Integer { type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards /// positive infinity and the remainder has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil\frac{x}{y} \right \rceil, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivAssignMod; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.ceiling_div_assign_mod(Integer::from(10)), -7); /// assert_eq!(x, 3); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.ceiling_div_assign_mod(Integer::from(-10)), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.ceiling_div_assign_mod(Integer::from(10)), -3); /// assert_eq!(x, -2); /// /// // 3 * -10 + 7 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.ceiling_div_assign_mod(Integer::from(-10)), 7); /// assert_eq!(x, 3); /// ``` fn ceiling_div_assign_mod(&mut self, other: Self) -> Self { let r = if self.sign == other.sign { self.sign = true; self.abs.ceiling_div_assign_neg_mod(other.abs) } else { let r = self.abs.div_assign_mod(other.abs); self.sign = self.abs == 0; r }; Self::from_sign_and_abs(!other.sign, r) } } impl CeilingDivAssignMod<&Self> for Integer { type ModOutput = Self; /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference and returning the remainder. The quotient is rounded towards /// positive infinity and the remainder has the opposite sign as the second [`Integer`]. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil\frac{x}{y} \right \rceil, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingDivAssignMod; /// use malachite_nz::integer::Integer; /// /// // 3 * 10 + -7 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.ceiling_div_assign_mod(&Integer::from(10)), -7); /// assert_eq!(x, 3); /// /// // -2 * -10 + 3 = 23 /// let mut x = Integer::from(23); /// assert_eq!(x.ceiling_div_assign_mod(&Integer::from(-10)), 3); /// assert_eq!(x, -2); /// /// // -2 * 10 + -3 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.ceiling_div_assign_mod(&Integer::from(10)), -3); /// assert_eq!(x, -2); /// /// // 3 * -10 + 7 = -23 /// let mut x = Integer::from(-23); /// assert_eq!(x.ceiling_div_assign_mod(&Integer::from(-10)), 7); /// assert_eq!(x, 3); /// ``` fn ceiling_div_assign_mod(&mut self, other: &Self) -> Self { let r = if self.sign == other.sign { self.sign = true; self.abs.ceiling_div_assign_neg_mod(&other.abs) } else { let r = self.abs.div_assign_mod(&other.abs); self.sign = self.abs == 0; r }; Self::from_sign_and_abs(!other.sign, r) } } ================================================ FILE: malachite-nz/src/integer/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{DivRound, DivRoundAssign}; use malachite_base::rounding_modes::RoundingMode; impl DivRound for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and rounding according /// to a specified rounding mode. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(4), Down), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(Integer::from(3), Floor), /// (Integer::from(-333333333334i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(4), Up), /// (Integer::from(-3), Less) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(Integer::from(3), Ceiling), /// (Integer::from(-333333333333i64), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(5), Exact), /// (Integer::from(-2), Equal) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(3), Nearest), /// (Integer::from(-3), Greater) /// ); /// assert_eq!( /// Integer::from(-20).div_round(Integer::from(3), Nearest), /// (Integer::from(-7), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(4), Nearest), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// Integer::from(-14).div_round(Integer::from(4), Nearest), /// (Integer::from(-4), Less) /// ); /// /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(-4), Down), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(Integer::from(-3), Floor), /// (Integer::from(333333333333i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(-4), Up), /// (Integer::from(3), Greater) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(Integer::from(-3), Ceiling), /// (Integer::from(333333333334i64), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(-5), Exact), /// (Integer::from(2), Equal) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(-3), Nearest), /// (Integer::from(3), Less) /// ); /// assert_eq!( /// Integer::from(-20).div_round(Integer::from(-3), Nearest), /// (Integer::from(7), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(-4), Nearest), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// Integer::from(-14).div_round(Integer::from(-4), Nearest), /// (Integer::from(4), Greater) /// ); /// ``` #[inline] fn div_round(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.div_round_assign(other, rm); (self, o) } } impl DivRound<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and rounding according to a specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(4), Down), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(&Integer::from(3), Floor), /// (Integer::from(-333333333334i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(4), Up), /// (Integer::from(-3), Less) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(&Integer::from(3), Ceiling), /// (Integer::from(-333333333333i64), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(5), Exact), /// (Integer::from(-2), Equal) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(3), Nearest), /// (Integer::from(-3), Greater) /// ); /// assert_eq!( /// Integer::from(-20).div_round(&Integer::from(3), Nearest), /// (Integer::from(-7), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(4), Nearest), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// Integer::from(-14).div_round(&Integer::from(4), Nearest), /// (Integer::from(-4), Less) /// ); /// /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(-4), Down), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(&Integer::from(-3), Floor), /// (Integer::from(333333333333i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(-4), Up), /// (Integer::from(3), Greater) /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).div_round(&Integer::from(-3), Ceiling), /// (Integer::from(333333333334i64), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(-5), Exact), /// (Integer::from(2), Equal) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(-3), Nearest), /// (Integer::from(3), Less) /// ); /// assert_eq!( /// Integer::from(-20).div_round(&Integer::from(-3), Nearest), /// (Integer::from(7), Greater) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(-4), Nearest), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// Integer::from(-14).div_round(&Integer::from(-4), Nearest), /// (Integer::from(4), Greater) /// ); /// ``` #[inline] fn div_round(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.div_round_assign(other, rm); (self, o) } } impl DivRound for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and rounding according to a specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(4), Down), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(Integer::from(3), Floor), /// (Integer::from(-333333333334i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(Integer::from(4), Up), /// (Integer::from(-3), Less) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(Integer::from(3), Ceiling), /// (Integer::from(-333333333333i64), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(5), Exact), /// (Integer::from(-2), Equal) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(3), Nearest), /// (Integer::from(-3), Greater) /// ); /// assert_eq!( /// (&Integer::from(-20)).div_round(Integer::from(3), Nearest), /// (Integer::from(-7), Less) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(4), Nearest), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (&Integer::from(-14)).div_round(Integer::from(4), Nearest), /// (Integer::from(-4), Less) /// ); /// /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(-4), Down), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(Integer::from(-3), Floor), /// (Integer::from(333333333333i64), Less) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(-4), Up), /// (Integer::from(3), Greater) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(Integer::from(-3), Ceiling), /// (Integer::from(333333333334i64), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(-5), Exact), /// (Integer::from(2), Equal) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(-3), Nearest), /// (Integer::from(3), Less) /// ); /// assert_eq!( /// (&Integer::from(-20)).div_round(Integer::from(-3), Nearest), /// (Integer::from(7), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(Integer::from(-4), Nearest), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (&Integer::from(-14)).div_round(Integer::from(-4), Nearest), /// (Integer::from(4), Greater) /// ); /// ``` fn div_round(self, other: Integer, rm: RoundingMode) -> (Integer, Ordering) { let q_sign = self.sign == other.sign; let (q_abs, o) = (&self.abs).div_round(other.abs, if q_sign { rm } else { -rm }); ( Integer::from_sign_and_abs(q_sign, q_abs), if q_sign { o } else { o.reverse() }, ) } } impl DivRound<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and rounding /// according to a specified rounding mode. An [`Ordering`] is also returned, indicating whether /// the returned value is less than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(4), Down), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(&Integer::from(3), Floor), /// (Integer::from(-333333333334i64), Less) /// ); /// assert_eq!( /// Integer::from(-10).div_round(&Integer::from(4), Up), /// (Integer::from(-3), Less) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(&Integer::from(3), Ceiling), /// (Integer::from(-333333333333i64), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(5), Exact), /// (Integer::from(-2), Equal) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(3), Nearest), /// (Integer::from(-3), Greater) /// ); /// assert_eq!( /// (&Integer::from(-20)).div_round(&Integer::from(3), Nearest), /// (Integer::from(-7), Less) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(4), Nearest), /// (Integer::from(-2), Greater) /// ); /// assert_eq!( /// (&Integer::from(-14)).div_round(&Integer::from(4), Nearest), /// (Integer::from(-4), Less) /// ); /// /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(-4), Down), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(&Integer::from(-3), Floor), /// (Integer::from(333333333333i64), Less) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(-4), Up), /// (Integer::from(3), Greater) /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)).div_round(&Integer::from(-3), Ceiling), /// (Integer::from(333333333334i64), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(-5), Exact), /// (Integer::from(2), Equal) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(-3), Nearest), /// (Integer::from(3), Less) /// ); /// assert_eq!( /// (&Integer::from(-20)).div_round(&Integer::from(-3), Nearest), /// (Integer::from(7), Greater) /// ); /// assert_eq!( /// (&Integer::from(-10)).div_round(&Integer::from(-4), Nearest), /// (Integer::from(2), Less) /// ); /// assert_eq!( /// (&Integer::from(-14)).div_round(&Integer::from(-4), Nearest), /// (Integer::from(4), Greater) /// ); /// ``` fn div_round(self, other: &Integer, rm: RoundingMode) -> (Integer, Ordering) { let q_sign = self.sign == other.sign; let (q_abs, o) = (&self.abs).div_round(&other.abs, if q_sign { rm } else { -rm }); ( Integer::from_sign_and_abs(q_sign, q_abs), if q_sign { o } else { o.reverse() }, ) } } impl DivRoundAssign for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value and rounding according to a specified rounding mode. An /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal to, or /// greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRoundAssign, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(4), Down), Greater); /// assert_eq!(n, -2); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(Integer::from(3), Floor), Less); /// assert_eq!(n, -333333333334i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(4), Up), Less); /// assert_eq!(n, -3); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(Integer::from(3), Ceiling), Greater); /// assert_eq!(n, -333333333333i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(5), Exact), Equal); /// assert_eq!(n, -2); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(3), Nearest), Greater); /// assert_eq!(n, -3); /// /// let mut n = Integer::from(-20); /// assert_eq!(n.div_round_assign(Integer::from(3), Nearest), Less); /// assert_eq!(n, -7); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(4), Nearest), Greater); /// assert_eq!(n, -2); /// /// let mut n = Integer::from(-14); /// assert_eq!(n.div_round_assign(Integer::from(4), Nearest), Less); /// assert_eq!(n, -4); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(-4), Down), Less); /// assert_eq!(n, 2); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(Integer::from(-3), Floor), Less); /// assert_eq!(n, 333333333333i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(-4), Up), Greater); /// assert_eq!(n, 3); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(Integer::from(-3), Ceiling), Greater); /// assert_eq!(n, 333333333334i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(-5), Exact), Equal); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(-3), Nearest), Less); /// assert_eq!(n, 3); /// /// let mut n = Integer::from(-20); /// assert_eq!(n.div_round_assign(Integer::from(-3), Nearest), Greater); /// assert_eq!(n, 7); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(Integer::from(-4), Nearest), Less); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-14); /// assert_eq!(n.div_round_assign(Integer::from(-4), Nearest), Greater); /// assert_eq!(n, 4); /// ``` fn div_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let q_sign = self.sign == other.sign; let o = self .abs .div_round_assign(other.abs, if q_sign { rm } else { -rm }); self.sign = q_sign || self.abs == 0; if q_sign { o } else { o.reverse() } } } impl DivRoundAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference and rounding according to a specified rounding mode. An /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal to, or /// greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRoundAssign, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(4), Down), Greater); /// assert_eq!(n, -2); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Integer::from(3), Floor), Less); /// assert_eq!(n, -333333333334i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(4), Up), Less); /// assert_eq!(n, -3); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Integer::from(3), Ceiling), Greater); /// assert_eq!(n, -333333333333i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(5), Exact), Equal); /// assert_eq!(n, -2); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(3), Nearest), Greater); /// assert_eq!(n, -3); /// /// let mut n = Integer::from(-20); /// assert_eq!(n.div_round_assign(&Integer::from(3), Nearest), Less); /// assert_eq!(n, -7); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(4), Nearest), Greater); /// assert_eq!(n, -2); /// /// let mut n = Integer::from(-14); /// assert_eq!(n.div_round_assign(&Integer::from(4), Nearest), Less); /// assert_eq!(n, -4); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(-4), Down), Less); /// assert_eq!(n, 2); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Integer::from(-3), Floor), Less); /// assert_eq!(n, 333333333333i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(-4), Up), Greater); /// assert_eq!(n, 3); /// /// let mut n = -Integer::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Integer::from(-3), Ceiling), Greater); /// assert_eq!(n, 333333333334i64); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(-5), Exact), Equal); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(-3), Nearest), Less); /// assert_eq!(n, 3); /// /// let mut n = Integer::from(-20); /// assert_eq!(n.div_round_assign(&Integer::from(-3), Nearest), Greater); /// assert_eq!(n, 7); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.div_round_assign(&Integer::from(-4), Nearest), Less); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-14); /// assert_eq!(n.div_round_assign(&Integer::from(-4), Nearest), Greater); /// assert_eq!(n, 4); /// ``` fn div_round_assign(&mut self, other: &Self, rm: RoundingMode) -> Ordering { let q_sign = self.sign == other.sign; let o = self .abs .div_round_assign(&other.abs, if q_sign { rm } else { -rm }); self.sign = q_sign || self.abs == 0; if q_sign { o } else { o.reverse() } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::DivisibleBy; impl DivisibleBy for Integer { /// Returns whether an [`Integer`] is divisible by another [`Integer`]; in other words, whether /// the first is a multiple of the second. Both [`Integer`]s are taken by value. /// /// This means that zero is divisible by any [`Integer`], including zero; but a nonzero /// [`Integer`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.divisible_by(Integer::ZERO), true); /// assert_eq!(Integer::from(-100).divisible_by(Integer::from(-3)), false); /// assert_eq!(Integer::from(102).divisible_by(Integer::from(-3)), true); /// assert_eq!( /// Integer::from_str("-1000000000000000000000000") /// .unwrap() /// .divisible_by(Integer::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, other: Self) -> bool { self.abs.divisible_by(other.abs) } } impl DivisibleBy<&Self> for Integer { /// Returns whether an [`Integer`] is divisible by another [`Integer`]; in other words, whether /// the first is a multiple of the second. The first [`Integer`] is taken by value and the /// second by reference. /// /// This means that zero is divisible by any [`Integer`], including zero; but a nonzero /// [`Integer`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.divisible_by(&Integer::ZERO), true); /// assert_eq!(Integer::from(-100).divisible_by(&Integer::from(-3)), false); /// assert_eq!(Integer::from(102).divisible_by(&Integer::from(-3)), true); /// assert_eq!( /// Integer::from_str("-1000000000000000000000000") /// .unwrap() /// .divisible_by(&Integer::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, other: &Self) -> bool { self.abs.divisible_by(&other.abs) } } impl DivisibleBy for &Integer { /// Returns whether an [`Integer`] is divisible by another [`Integer`]; in other words, whether /// the first is a multiple of the second. The first [`Integer`] is taken by reference and the /// second by value. /// /// This means that zero is divisible by any [`Integer`], including zero; but a nonzero /// [`Integer`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::ZERO).divisible_by(Integer::ZERO), true); /// assert_eq!( /// (&Integer::from(-100)).divisible_by(Integer::from(-3)), /// false /// ); /// assert_eq!((&Integer::from(102)).divisible_by(Integer::from(-3)), true); /// assert_eq!( /// (&Integer::from_str("-1000000000000000000000000").unwrap()) /// .divisible_by(Integer::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, other: Integer) -> bool { (&self.abs).divisible_by(other.abs) } } impl DivisibleBy<&Integer> for &Integer { /// Returns whether an [`Integer`] is divisible by another [`Integer`]; in other words, whether /// the first is a multiple of the second. Both [`Integer`]s are taken by reference. /// /// This means that zero is divisible by any [`Integer`], including zero; but a nonzero /// [`Integer`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::ZERO).divisible_by(&Integer::ZERO), true); /// assert_eq!( /// (&Integer::from(-100)).divisible_by(&Integer::from(-3)), /// false /// ); /// assert_eq!((&Integer::from(102)).divisible_by(&Integer::from(-3)), true); /// assert_eq!( /// (&Integer::from_str("-1000000000000000000000000").unwrap()) /// .divisible_by(&Integer::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, other: &Integer) -> bool { (&self.abs).divisible_by(&other.abs) } } ================================================ FILE: malachite-nz/src/integer/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; impl DivisibleByPowerOf2 for &Integer { /// Returns whether an [`Integer`] is divisible by $2^k$. /// /// $f(x, k) = (2^k|x)$. /// /// $f(x, k) = (\exists n \in \N : \ x = n2^k)$. /// /// If `self` is 0, the result is always true; otherwise, it is equivalent to /// `self.trailing_zeros().unwrap() <= pow`, but more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, self.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.divisible_by_power_of_2(100), true); /// assert_eq!(Integer::from(-100).divisible_by_power_of_2(2), true); /// assert_eq!(Integer::from(100u32).divisible_by_power_of_2(3), false); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).divisible_by_power_of_2(12), /// true /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).divisible_by_power_of_2(13), /// false /// ); /// ``` fn divisible_by_power_of_2(self, pow: u64) -> bool { self.abs.divisible_by_power_of_2(pow) } } ================================================ FILE: malachite-nz/src/integer/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{limbs_add, limbs_add_limb}; use crate::natural::arithmetic::divisible_by::{ limbs_divisible_by, limbs_divisible_by_limb, limbs_divisible_by_val_ref, }; use crate::natural::arithmetic::eq_mod::{limbs_eq_limb_mod_limb, limbs_mod_exact_odd_limb}; use crate::natural::arithmetic::mod_op::limbs_mod_limb; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{ DivisibleBy, EqMod, EqModPowerOf2, NegMod, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::TrailingZeros; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, determines // whether that `Natural` is equal to the negative of a limb mod a given `Limb` m. // // This function assumes that `m` is nonzero, `limbs` has at least two elements, and the last // element of `limbs` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `limbs` is less than 2. // // This is equivalent to `mpz_congruent_ui_p` from `mpz/cong_ui.c`, GMP 6.2.1, where `a` is // negative. pub_test! {limbs_eq_neg_limb_mod_limb(xs: &[Limb], y: Limb, m: Limb) -> bool { limbs_eq_limb_mod_limb(xs, y.neg_mod(m), m) }} /// Set r to -n mod d. n >= d is allowed. Can give r > d. d cannot equal 0. /// /// This is equivalent to `NEG_MOD` from `gmp-impl.h`, GMP 6.2.1, where `r` is returned. const fn quick_neg_mod(n: Limb, d: Limb) -> Limb { if n <= d { d - n } else { let d = d << d.leading_zeros(); (if n <= d { d } else { d << 1 }).wrapping_sub(n) } } // Interpreting two limbs `x` and `y` and slice of `Limb`s `m` as three numbers x, y, and m, // determines whether x ≡ -y mod m. // // This function assumes that the input slice has at least two elements, its last element is // nonzero, and `x` and `y` are nonzero. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, `a` and `d` are one limb long, and `c` is longer than one limb. pub_const_test! {limbs_pos_limb_eq_neg_limb_mod(x: Limb, y: Limb, ms: &[Limb]) -> bool { // We are checking whether x ≡ -y mod m; that is, whether x + y = k * m for some k in Z. But // because of the preconditions on m, the lowest possible value of m is `2 ^ Limb::WIDTH`, while // the highest possible value of x + y is `2 ^ (Limb::WIDTH + 1) - 2`, so we have x + y < 2 * m. // This means that k can only be 1, so we're actually checking whether x + y = m. ms.len() == 2 && ms[1] == 1 && { let (sum, overflow) = x.overflowing_add(y); overflow && sum == ms[0] } }} #[allow(clippy::absurd_extreme_comparisons)] fn limbs_pos_eq_neg_limb_mod_helper(xs: &[Limb], y: Limb, ms: &[Limb]) -> Option { let m_len = ms.len(); let x_len = xs.len(); assert!(m_len > 1); assert!(x_len > 1); assert_ne!(y, 0); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(*ms.last().unwrap(), 0); let m_0 = ms[0]; // Check x == y mod low zero bits of m_0. This might catch a few cases of x != y quickly. let twos = TrailingZeros::trailing_zeros(m_0); if !xs[0].wrapping_neg().eq_mod_power_of_2(y, twos) { return Some(false); } // m_0 == 0 is avoided since we don't want to bother handling extra low zero bits if m_1 is even // (would involve borrow if x_0, y_0 != 0). if m_len == 2 && m_0 != 0 { let m_1 = ms[1]; if m_1 < Limb::power_of_2(twos) { let m_0 = (m_0 >> twos) | (m_1 << (Limb::WIDTH - twos)); let y = quick_neg_mod(y, m_0); return Some(if x_len >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(xs, m_0) == if y < m_0 { y } else { y % m_0 } } else { let r = limbs_mod_exact_odd_limb(xs, m_0, y); r == 0 || r == m_0 }); } } None } // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `m` as three // numbers x, y, and m, determines whether x ≡ -y mod m. The second input slice is immutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `ms` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_pos_eq_neg_limb_mod_ref(xs: &[Limb], y: Limb, ms: &[Limb]) -> bool { if let Some(equal) = limbs_pos_eq_neg_limb_mod_helper(xs, y, ms) { return equal; } // calculate |x - y|. Different signs, add let mut scratch = limbs_add_limb(xs, y); scratch.len() >= ms.len() && limbs_divisible_by_val_ref(&mut scratch, ms) }} // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `ms` as three // numbers x, y, and m, determines whether x ≡ -y mod m. The second input slice is mutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `ms` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_pos_eq_neg_limb_mod(xs: &[Limb], y: Limb, ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_pos_eq_neg_limb_mod_helper(xs, y, ms) { return equal; } // calculate |x - y|. Different signs, add let mut scratch = limbs_add_limb(xs, y); scratch.len() >= ms.len() && limbs_divisible_by(&mut scratch, ms) }} // Interpreting two slices of `Limb`s `xs` and `ys` and a Limb `m` as three numbers x, y, and m, // determines whether x ≡ -y mod m. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `m` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs` or `ys` is less than 2, if the last element of either of the slices // is zero, or if `m` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, `a` and `c` are longer than one limb, and `m` is one limb long. pub_test! {limbs_pos_eq_neg_mod_limb(xs: &[Limb], ys: &[Limb], m: Limb) -> bool { if xs.len() >= ys.len() { limbs_pos_eq_mod_neg_limb_greater(xs, ys, m) } else { limbs_pos_eq_mod_neg_limb_greater(ys, xs, m) } }} // xs.len() >= ys.len() fn limbs_pos_eq_mod_neg_limb_greater(xs: &[Limb], ys: &[Limb], m: Limb) -> bool { assert!(xs.len() > 1); assert!(ys.len() > 1); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(*ys.last().unwrap(), 0); assert_ne!(m, 0); // Check x == y mod low zero bits of m_0. This might catch a few cases of x != y quickly. if !xs[0] .wrapping_neg() .eq_mod_power_of_2(ys[0], TrailingZeros::trailing_zeros(m)) { return false; } // calculate |x - y|. Different signs, add limbs_divisible_by_limb(&limbs_add(xs, ys), m) } fn limbs_pos_eq_neg_mod_greater_helper(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> Option { assert!(ms.len() > 1); assert!(xs.len() > 1); assert!(ys.len() > 1); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(*ys.last().unwrap(), 0); assert_ne!(*ms.last().unwrap(), 0); // Check x == y mod low zero bits of m_0. This might catch a few cases of x != y quickly. if xs[0] .wrapping_neg() .eq_mod_power_of_2(ys[0], TrailingZeros::trailing_zeros(ms[0])) { None } else { Some(false) } } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the negative of the second `Natural` mod the third `Natural`. The // second input slice is immutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, and each is longer than one limb. pub_test! {limbs_pos_eq_neg_mod_ref(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { if xs.len() >= ys.len() { limbs_pos_eq_neg_mod_greater_ref(xs, ys, ms) } else { limbs_pos_eq_neg_mod_greater_ref(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_pos_eq_neg_mod_greater_ref(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { if let Some(equal) = limbs_pos_eq_neg_mod_greater_helper(xs, ys, ms) { return equal; } // calculate |x - y|. Different signs, add let mut scratch = limbs_add(xs, ys); scratch.len() >= ms.len() && limbs_divisible_by_val_ref(&mut scratch, ms) } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the negative of the second `Natural` mod the third `Natural`. The // second input slice is mutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a` and `d` are // positive, `c` is negative, and each is longer than one limb. pub_test! {limbs_pos_eq_neg_mod(xs: &[Limb], ys: &[Limb], ms: &mut [Limb]) -> bool { if xs.len() >= ys.len() { limbs_pos_eq_neg_mod_greater(xs, ys, ms) } else { limbs_pos_eq_neg_mod_greater(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_pos_eq_neg_mod_greater(xs: &[Limb], ys: &[Limb], ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_pos_eq_neg_mod_greater_helper(xs, ys, ms) { return equal; } // calculate |x - y|. Different signs, add let mut scratch = limbs_add(xs, ys); scratch.len() >= ms.len() && limbs_divisible_by(&mut scratch, ms) } impl Natural { fn eq_neg_limb_mod_limb(&self, other: Limb, m: Limb) -> bool { m != 0 && match self { Self(Small(small)) => small % m == other.neg_mod(m), Self(Large(limbs)) => limbs_eq_neg_limb_mod_limb(limbs, other, m), } } fn pos_eq_neg_mod(&self, other: &Self, m: Self) -> bool { match (self, other, m) { (_, _, Self::ZERO) => false, (x, &Self::ZERO, m) => x.divisible_by(m), (&Self::ZERO, y, m) => y.divisible_by(m), (x, &Self(Small(y)), Self(Small(m))) => x.eq_neg_limb_mod_limb(y, m), (&Self(Small(x)), y, Self(Small(m))) => y.eq_neg_limb_mod_limb(x, m), (&Self(Small(x)), &Self(Small(y)), Self(Large(ref m))) => { limbs_pos_limb_eq_neg_limb_mod(x, y, m) } (&Self(Large(ref xs)), &Self(Large(ref ys)), Self(Small(m))) => { limbs_pos_eq_neg_mod_limb(xs, ys, m) } (&Self(Large(ref xs)), &Self(Small(y)), Self(Large(ref mut m))) => { limbs_pos_eq_neg_limb_mod(xs, y, m) } (&Self(Small(x)), &Self(Large(ref ys)), Self(Large(ref mut m))) => { limbs_pos_eq_neg_limb_mod(ys, x, m) } (&Self(Large(ref xs)), &Self(Large(ref ys)), Self(Large(ref mut m))) => { limbs_pos_eq_neg_mod(xs, ys, m) } } } fn pos_eq_neg_mod_ref(&self, other: &Self, m: &Self) -> bool { match (self, other, m) { (_, _, &Self::ZERO) => false, (x, &Self::ZERO, m) => x.divisible_by(m), (&Self::ZERO, y, m) => y.divisible_by(m), (x, &Self(Small(y)), &Self(Small(m))) => x.eq_neg_limb_mod_limb(y, m), (&Self(Small(x)), y, &Self(Small(m))) => y.eq_neg_limb_mod_limb(x, m), (&Self(Small(x)), &Self(Small(y)), &Self(Large(ref m))) => { limbs_pos_limb_eq_neg_limb_mod(x, y, m) } (&Self(Large(ref xs)), &Self(Large(ref ys)), &Self(Small(m))) => { limbs_pos_eq_neg_mod_limb(xs, ys, m) } (&Self(Large(ref xs)), &Self(Small(y)), &Self(Large(ref m))) => { limbs_pos_eq_neg_limb_mod_ref(xs, y, m) } (&Self(Small(x)), &Self(Large(ref ys)), &Self(Large(ref m))) => { limbs_pos_eq_neg_limb_mod_ref(ys, x, m) } (&Self(Large(ref xs)), &Self(Large(ref ys)), &Self(Large(ref m))) => { limbs_pos_eq_neg_mod_ref(xs, ys, m) } } } } impl EqMod for Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. All three numbers are taken by value. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Integer::from(123).eq_mod(Integer::from(223), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// Integer::from_str("-999999012346").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// Integer::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Self, m: Natural) -> bool { if self.sign == other.sign { self.abs.eq_mod(other.abs, m) } else { self.abs.pos_eq_neg_mod(&other.abs, m) } } } impl EqMod for Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first two numbers are taken by value and the third by reference. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Integer::from(123).eq_mod(Integer::from(223), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// Integer::from_str("-999999012346").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// Integer::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Self, m: &Natural) -> bool { if self.sign == other.sign { self.abs.eq_mod(other.abs, m) } else { self.abs.pos_eq_neg_mod_ref(&other.abs, m) } } } impl EqMod<&Self, Natural> for Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first and third numbers are taken by value and the second by reference. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Integer::from(123).eq_mod(&Integer::from(223), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// &Integer::from_str("-999999012346").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// &Integer::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Self, m: Natural) -> bool { if self.sign == other.sign { self.abs.eq_mod(&other.abs, m) } else { self.abs.pos_eq_neg_mod(&other.abs, m) } } } impl EqMod<&Self, &Natural> for Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first number is taken by value and the second and third by reference. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Integer::from(123).eq_mod(&Integer::from(223), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// &Integer::from_str("-999999012346").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Integer::from_str("1000000987654").unwrap().eq_mod( /// &Integer::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Self, m: &Natural) -> bool { if self.sign == other.sign { self.abs.eq_mod(&other.abs, m) } else { self.abs.pos_eq_neg_mod_ref(&other.abs, m) } } } impl EqMod for &Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first number is taken by reference and the second and third by value. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Integer::from(123)).eq_mod(Integer::from(223), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// Integer::from_str("-999999012346").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// Integer::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Integer, m: Natural) -> bool { if self.sign == other.sign { (&self.abs).eq_mod(other.abs, m) } else { self.abs.pos_eq_neg_mod(&other.abs, m) } } } impl EqMod for &Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first and third numbers are taken by reference and the third by value. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Integer::from(123)).eq_mod(Integer::from(223), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// Integer::from_str("-999999012346").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// Integer::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Integer, m: &Natural) -> bool { if self.sign == other.sign { (&self.abs).eq_mod(other.abs, m) } else { self.abs.pos_eq_neg_mod_ref(&other.abs, m) } } } impl EqMod<&Integer, Natural> for &Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. The first two numbers are taken by reference and the third by value. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Integer::from(123)).eq_mod(&Integer::from(223), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// &Integer::from_str("-999999012346").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// &Integer::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Integer, m: Natural) -> bool { if self.sign == other.sign { (&self.abs).eq_mod(&other.abs, m) } else { self.abs.pos_eq_neg_mod(&other.abs, m) } } } impl EqMod<&Integer, &Natural> for &Integer { /// Returns whether an [`Integer`] is equivalent to another [`Integer`] modulo a [`Natural`]; /// that is, whether the difference between the two [`Integer`]s is a multiple of the /// [`Natural`]. All three numbers are taken by reference. /// /// Two [`Integer`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Integer::from(123)).eq_mod(&Integer::from(223), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// &Integer::from_str("-999999012346").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Integer::from_str("1000000987654").unwrap()).eq_mod( /// &Integer::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Integer, m: &Natural) -> bool { if self.sign == other.sign { (&self.abs).eq_mod(&other.abs, m) } else { self.abs.pos_eq_neg_mod_ref(&other.abs, m) } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2001, 2002, 2013 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::EqModPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns whether // the negative of the `Natural` is equivalent to a limb mod two to the power of `pow`; that is, // whether the `pow` least-significant bits of the negative of the `Natural` and the limb are equal. // // This function assumes that `limbs` has length at least 2 and the last (most significant) limb is // nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_eq_mod_power_of_2_neg_limb(xs: &[Limb], y: Limb, pow: u64) -> bool { if y == 0 { return limbs_divisible_by_power_of_2(xs, pow); } let i = bit_to_limb_count_floor(pow); match i.cmp(&xs.len()) { Greater => false, Equal => { if pow & Limb::WIDTH_MASK == 0 { // Check whether the sum of X and y is 0 mod B ^ xs.len(). let mut carry = y; for &x in xs { let sum = x.wrapping_add(carry); if sum != 0 { return false; } carry = 1; } true } else { false } } Less => { if i == 0 { xs[0].eq_mod_power_of_2(y.wrapping_neg(), pow) } else { xs[0] == y.wrapping_neg() && xs[1..i].iter().all(|&x| x == Limb::MAX) && xs[i].eq_mod_power_of_2(Limb::MAX, pow & Limb::WIDTH_MASK) } } } }} fn limbs_eq_mod_power_of_2_neg_pos_greater(xs: &[Limb], ys: &[Limb], pow: u64) -> bool { let xs_len = xs.len(); let i = bit_to_limb_count_floor(pow); let small_pow = pow & Limb::WIDTH_MASK; if i > xs_len || i == xs_len && small_pow != 0 { false } else { let ys_len = ys.len(); let mut y_nonzero_seen = false; for j in 0..i { let y = if j >= ys_len { Limb::MAX } else if y_nonzero_seen { !ys[j] } else if ys[j] == 0 { 0 } else { y_nonzero_seen = true; ys[j].wrapping_neg() }; if xs[j] != y { return false; } } if small_pow == 0 { true } else { // i < xs_len let y = if i >= ys_len { Limb::MAX } else if y_nonzero_seen { !ys[i] } else { ys[i].wrapping_neg() }; xs[i].eq_mod_power_of_2(y, small_pow) } } } // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns // whether the first `Natural` and the negative of the second natural (equivalently, the negative of // the first `Natural` and the second `Natural`) are equivalent mod two to the power of `pow`; that // is, whether their `pow` least-significant bits are equal. // // This function assumes that neither slice is empty and their last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_congruent_2exp_p` from `mpz/cong_2exp.c`, GMP 6.2.1, where `a` is // negative and `c` is positive. pub_test! {limbs_eq_mod_power_of_2_neg_pos(xs: &[Limb], ys: &[Limb], pow: u64) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_power_of_2_neg_pos_greater(xs, ys, pow) } else { limbs_eq_mod_power_of_2_neg_pos_greater(ys, xs, pow) } }} impl Natural { fn eq_mod_power_of_2_neg_limb(&self, other: Limb, pow: u64) -> bool { match self { Self(Small(small)) => { pow <= Limb::WIDTH && small.wrapping_neg().eq_mod_power_of_2(other, pow) } Self(Large(limbs)) => limbs_eq_mod_power_of_2_neg_limb(limbs, other, pow), } } fn eq_mod_power_of_2_neg_pos(&self, other: &Self, pow: u64) -> bool { match (self, other) { (_, &Self(Small(y))) => self.eq_mod_power_of_2_neg_limb(y, pow), (&Self(Small(x)), _) => other.eq_mod_power_of_2_neg_limb(x, pow), (Self(Large(xs)), Self(Large(ys))) => limbs_eq_mod_power_of_2_neg_pos(xs, ys, pow), } } } impl EqModPowerOf2<&Integer> for &Integer { /// Returns whether one [`Integer`] is equal to another modulo $2^k$; that is, whether their $k$ /// least-significant bits (in two's complement) are equal. /// /// $f(x, y, k) = (x \equiv y \mod 2^k)$. /// /// $f(x, y, k) = (\exists n \in \Z : x - y = n2^k)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::EqModPowerOf2; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::ZERO.eq_mod_power_of_2(&Integer::from(-256), 8), /// true /// ); /// assert_eq!( /// Integer::from(-0b1101).eq_mod_power_of_2(&Integer::from(0b11011), 3), /// true /// ); /// assert_eq!( /// Integer::from(-0b1101).eq_mod_power_of_2(&Integer::from(0b11011), 4), /// false /// ); /// ``` fn eq_mod_power_of_2(self, other: &Integer, pow: u64) -> bool { if self.sign == other.sign { self.abs.eq_mod_power_of_2(&other.abs, pow) } else { self.abs.eq_mod_power_of_2_neg_pos(&other.abs, pow) } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ExtendedGcd, NegAssign, UnsignedAbs}; impl ExtendedGcd for Integer { type Gcd = Natural; type Cofactor = Self; /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Integer`]s are /// taken by value. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$, /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq /// \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(3) /// .extended_gcd(Integer::from(5)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// Integer::from(240) /// .extended_gcd(Integer::from(46)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// assert_eq!( /// Integer::from(-111) /// .extended_gcd(Integer::from(300)) /// .to_debug_string(), /// "(3, 27, 10)" /// ); /// ``` fn extended_gcd(self, other: Self) -> (Natural, Self, Self) { let a_sign = self.sign; let b_sign = other.sign; let (gcd, mut x, mut y) = self.unsigned_abs().extended_gcd(other.unsigned_abs()); if !a_sign { x.neg_assign(); } if !b_sign { y.neg_assign(); } (gcd, x, y) } } impl ExtendedGcd<&Self> for Integer { type Gcd = Natural; type Cofactor = Self; /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Integer`] is /// taken by value and the second by reference. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$, /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq /// \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(3) /// .extended_gcd(&Integer::from(5)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// Integer::from(240) /// .extended_gcd(&Integer::from(46)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// assert_eq!( /// Integer::from(-111) /// .extended_gcd(&Integer::from(300)) /// .to_debug_string(), /// "(3, 27, 10)" /// ); /// ``` fn extended_gcd(self, other: &Self) -> (Natural, Self, Self) { let a_sign = self.sign; let (gcd, mut x, mut y) = self.unsigned_abs().extended_gcd(other.unsigned_abs_ref()); if !a_sign { x.neg_assign(); } if !other.sign { y.neg_assign(); } (gcd, x, y) } } impl ExtendedGcd for &Integer { type Gcd = Natural; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Integer`] is /// taken by reference and the second by value. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$, /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq /// \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(3)) /// .extended_gcd(Integer::from(5)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// (&Integer::from(240)) /// .extended_gcd(Integer::from(46)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// assert_eq!( /// (&Integer::from(-111)) /// .extended_gcd(Integer::from(300)) /// .to_debug_string(), /// "(3, 27, 10)" /// ); /// ``` fn extended_gcd(self, other: Integer) -> (Natural, Integer, Integer) { let b_sign = other.sign; let (gcd, mut x, mut y) = self.unsigned_abs_ref().extended_gcd(other.unsigned_abs()); if !self.sign { x.neg_assign(); } if !b_sign { y.neg_assign(); } (gcd, x, y) } } impl ExtendedGcd<&Integer> for &Integer { type Gcd = Natural; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Integer`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Integer`]s are /// taken by reference. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(a, ak) = (-a, -1, 0)$ if $a < 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(bk, b) = (-b, 0, -1)$ if $b < 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(|a|, |b|)$, /// where $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq /// \lfloor a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(3)) /// .extended_gcd(&Integer::from(5)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// (&Integer::from(240)) /// .extended_gcd(&Integer::from(46)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// assert_eq!( /// (&Integer::from(-111)) /// .extended_gcd(&Integer::from(300)) /// .to_debug_string(), /// "(3, 27, 10)" /// ); /// ``` fn extended_gcd(self, other: &Integer) -> (Natural, Integer, Integer) { let (gcd, mut x, mut y) = self .unsigned_abs_ref() .extended_gcd(other.unsigned_abs_ref()); if !self.sign { x.neg_assign(); } if !other.sign { y.neg_assign(); } (gcd, x, y) } } ================================================ FILE: malachite-nz/src/integer/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000-2002, 2005, 2010-2012 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::div_mod::limbs_div_mod_to_out; use crate::natural::arithmetic::eq_mod::limbs_mod_exact_odd_limb; use crate::natural::arithmetic::kronecker_symbol::{ limbs_jacobi_symbol_init, limbs_jacobi_symbol_same_length, }; use crate::natural::arithmetic::mod_op::limbs_mod_limb_alt_2; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ JacobiSymbol, KroneckerSymbol, LegendreSymbol, Parity, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{BitAccess, NotAssign, TrailingZeros}; use malachite_base::slices::slice_leading_zeros; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_jacobi` from `mpz/jacobi.c`, GMP 6.2.1, where the absolute values of // both `a` and `b` fit in a limb. pub_crate_test! {limbs_kronecker_symbol_single( x_sign: bool, x: Limb, y_sign: bool, mut y: Limb, ) -> i8 { // Common factor of 2 => (a/b) = 0 if (x | y).even() { return 0; } // (a/-1) = -1 if a < 0, +1 if a >= 0 let mut negate = !x_sign && !y_sign; let y_twos = TrailingZeros::trailing_zeros(y); y >>= y_twos; // (-1/b) = -1 iff b = 3 (mod 4) if !x_sign && y.get_bit(1) { negate.not_assign(); } if y_twos.odd() & ((x >> 1) ^ x).get_bit(1) { negate.not_assign(); } let j = if y == 1 { 1 } else { x.jacobi_symbol(y) }; if negate { -j } else { j } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_jacobi` from `mpz/jacobi.c`, GMP 6.2.1. pub_crate_test! { limbs_kronecker_symbol(x_sign: bool, xs: &[Limb], y_sign: bool, ys: &[Limb]) -> i8 { let mut xs_len = xs.len(); let mut ys_len = ys.len(); // The `limbs_jacobi_symbol_same_length` function requires positive x and y, and x odd. So we // must handle the cases of x or y zero, then signs, and then the case of even y. // // (x / 0) = (x = 1 or x = -1) if ys_len == 0 { return i8::from(xs == [1]); } // (0 / y) = (y = 1 or y = -1) if xs_len == 0 { return i8::from(ys == [1]); } assert_ne!(xs[xs_len - 1], 0); assert_ne!(ys[ys_len - 1], 0); let mut xs = xs; let mut ys = ys; // Common factor of 2 => (x / y) = 0 if (xs[0] | ys[0]).even() { return 0; } // (x / -1) = -1 if x < 0, 1 if x >= 0 let mut negate = !x_sign && !y_sign; ys = &ys[slice_leading_zeros(ys)..]; ys_len = ys.len(); let mut y_lo = ys[0]; let mut y_twos = TrailingZeros::trailing_zeros(y_lo); y_lo >>= y_twos; if ys_len > 1 && y_twos != 0 { let y_1 = ys[1]; y_lo |= y_1 << (Limb::WIDTH - y_twos); if ys_len == 2 && y_1 >> y_twos == 0 { ys_len = 1; } } // (-1 / y) = -1 iff y ≡ 3 mod 4 if !x_sign && y_lo.get_bit(1) { negate.not_assign(); } xs = &xs[slice_leading_zeros(xs)..]; xs_len = xs.len(); let mut x_lo = xs[0]; // Ensure xs_len >= ys_len. Take advantage of the generalized reciprocity law: (x / y * 2 ^ n) = // (y * 2 ^ n / x) * recip(x, y) if xs_len < ys_len { swap(&mut xs, &mut ys); swap(&mut xs_len, &mut ys_len); swap(&mut x_lo, &mut y_lo); // The value of x_lo (old y_lo) is a bit subtle. For this code path, we get x_lo as the low, // always odd, limb of shifted x. Which is what we need for the reciprocity update below. // // However, all other uses of x_lo assumes that it is *not* shifted. Luckily, x_lo matters // only when either // - y_twos > 0, in which case x is always odd // - xs_len = ys_len = 1, in which case this code path is never taken. y_twos = TrailingZeros::trailing_zeros(y_lo); y_lo >>= y_twos; if ys_len > 1 && y_twos != 0 { let y_1 = ys[1]; y_lo |= y_1 << (Limb::WIDTH - y_twos); if ys_len == 2 && y_1 >> y_twos == 0 { ys_len = 1; } } if (x_lo & y_lo).get_bit(1) { negate.not_assign(); } } if ys_len == 1 { if y_twos.odd() & ((x_lo >> 1) ^ x_lo).get_bit(1) { negate.not_assign(); } if y_lo == 1 { return if negate { -1 } else { 1 }; } if xs_len > 1 { assert!(y_lo.odd()); x_lo = if xs.len() >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb_alt_2::(xs, y_lo) } else { if y_lo.get_bit(1) { negate.not_assign(); } limbs_mod_exact_odd_limb(xs, y_lo, 0) }; } let j = x_lo.jacobi_symbol(y_lo); return if negate { -j } else { j }; } // Allocation strategy: For x, we allocate a working copy only for x % y, but when x is much // larger than y, we have to allocate space for the large quotient. We use the same area, // pointed to by ys_alt, for both the quotient x / y and the working copy of y. let mut scratch = vec![ 0; if xs_len >= ys_len << 1 { xs_len + 1 } else { ys_len << 1 } ]; let (mut xs_alt, mut ys_alt) = scratch.split_at_mut(ys_len); // In the case of even y, we conceptually shift out the powers of two first, and then divide x % // y. Hence, when taking those powers of two into account, we must use alow *before* the // division. Doing the actual division first is ok, because the point is to remove multiples of // y from x, and multiples of 2 ^ k y are good enough. if xs_len > ys_len { limbs_div_mod_to_out(ys_alt, xs_alt, xs, ys); ys_alt = &mut ys_alt[..ys_len]; } else { xs_alt.copy_from_slice(xs); } if y_twos != 0 { if y_twos.odd() & ((x_lo >> 1) ^ x_lo).get_bit(1) { negate.not_assign(); } limbs_shr_to_out(ys_alt, ys, y_twos); if xs_alt[ys_len - 1] == 0 && ys_alt[ys_len - 1] == 0 { xs_alt = &mut xs_alt[..ys_len - 1]; ys_alt = &mut ys_alt[..ys_len - 1]; } } else { ys_alt.copy_from_slice(ys); } assert_eq!(y_lo, ys_alt[0]); let bits = limbs_jacobi_symbol_init(xs_alt[0], y_lo, u8::from(negate)); limbs_jacobi_symbol_same_length(xs_alt, ys_alt, bits) }} impl LegendreSymbol for Integer { /// Computes the Legendre symbol of two [`Integer`]s, taking both by value. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).legendre_symbol(Integer::from(5)), 0); /// assert_eq!(Integer::from(7).legendre_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(11).legendre_symbol(Integer::from(5)), 1); /// assert_eq!(Integer::from(-7).legendre_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).legendre_symbol(Integer::from(5)), 1); /// ``` #[inline] fn legendre_symbol(self, other: Self) -> i8 { assert!(other > 0u32); assert!(other.odd()); (&self).kronecker_symbol(&other) } } impl LegendreSymbol<&Self> for Integer { /// Computes the Legendre symbol of two [`Integer`]s, taking the first by value and the second /// by reference. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).legendre_symbol(&Integer::from(5)), 0); /// assert_eq!(Integer::from(7).legendre_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(11).legendre_symbol(&Integer::from(5)), 1); /// assert_eq!(Integer::from(-7).legendre_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).legendre_symbol(&Integer::from(5)), 1); /// ``` #[inline] fn legendre_symbol(self, other: &Self) -> i8 { assert!(*other > 0u32); assert!(other.odd()); (&self).kronecker_symbol(other) } } impl LegendreSymbol for &Integer { /// Computes the Legendre symbol of two [`Integer`]s, taking the first by reference and the /// second by value. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).legendre_symbol(Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).legendre_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).legendre_symbol(Integer::from(5)), 1); /// assert_eq!((&Integer::from(-7)).legendre_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).legendre_symbol(Integer::from(5)), 1); /// ``` #[inline] fn legendre_symbol(self, other: Integer) -> i8 { assert!(other > 0u32); assert!(other.odd()); self.kronecker_symbol(&other) } } impl LegendreSymbol<&Integer> for &Integer { /// Computes the Legendre symbol of two [`Integer`]s, taking both by reference. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).legendre_symbol(&Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).legendre_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).legendre_symbol(&Integer::from(5)), 1); /// assert_eq!((&Integer::from(-7)).legendre_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).legendre_symbol(&Integer::from(5)), 1); /// ``` #[inline] fn legendre_symbol(self, other: &Integer) -> i8 { assert!(*other > 0u32); assert!(other.odd()); self.kronecker_symbol(other) } } impl JacobiSymbol for Integer { /// Computes the Jacobi symbol of two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).jacobi_symbol(Integer::from(5)), 0); /// assert_eq!(Integer::from(7).jacobi_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(11).jacobi_symbol(Integer::from(5)), 1); /// assert_eq!(Integer::from(11).jacobi_symbol(Integer::from(9)), 1); /// assert_eq!(Integer::from(-7).jacobi_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).jacobi_symbol(Integer::from(5)), 1); /// assert_eq!(Integer::from(-11).jacobi_symbol(Integer::from(9)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: Self) -> i8 { assert!(other > 0u32); assert!(other.odd()); (&self).kronecker_symbol(&other) } } impl JacobiSymbol<&Self> for Integer { /// Computes the Jacobi symbol of two [`Integer`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).jacobi_symbol(&Integer::from(5)), 0); /// assert_eq!(Integer::from(7).jacobi_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(11).jacobi_symbol(&Integer::from(5)), 1); /// assert_eq!(Integer::from(11).jacobi_symbol(&Integer::from(9)), 1); /// assert_eq!(Integer::from(-7).jacobi_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).jacobi_symbol(&Integer::from(5)), 1); /// assert_eq!(Integer::from(-11).jacobi_symbol(&Integer::from(9)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: &Self) -> i8 { assert!(*other > 0u32); assert!(other.odd()); (&self).kronecker_symbol(other) } } impl JacobiSymbol for &Integer { /// Computes the Jacobi symbol of two [`Integer`]s, taking the first by reference and the second /// by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).jacobi_symbol(Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).jacobi_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).jacobi_symbol(Integer::from(5)), 1); /// assert_eq!((&Integer::from(11)).jacobi_symbol(Integer::from(9)), 1); /// assert_eq!((&Integer::from(-7)).jacobi_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).jacobi_symbol(Integer::from(5)), 1); /// assert_eq!((&Integer::from(-11)).jacobi_symbol(Integer::from(9)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: Integer) -> i8 { assert!(other > 0u32); assert!(other.odd()); self.kronecker_symbol(&other) } } impl JacobiSymbol<&Integer> for &Integer { /// Computes the Jacobi symbol of two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` is negative or if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).jacobi_symbol(&Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).jacobi_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).jacobi_symbol(&Integer::from(5)), 1); /// assert_eq!((&Integer::from(11)).jacobi_symbol(&Integer::from(9)), 1); /// assert_eq!((&Integer::from(-7)).jacobi_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).jacobi_symbol(&Integer::from(5)), 1); /// assert_eq!((&Integer::from(-11)).jacobi_symbol(&Integer::from(9)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: &Integer) -> i8 { assert!(*other > 0u32); assert!(other.odd()); self.kronecker_symbol(other) } } impl KroneckerSymbol for Integer { /// Computes the Kronecker symbol of two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).kronecker_symbol(Integer::from(5)), 0); /// assert_eq!(Integer::from(7).kronecker_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(11).kronecker_symbol(Integer::from(5)), 1); /// assert_eq!(Integer::from(11).kronecker_symbol(Integer::from(9)), 1); /// assert_eq!(Integer::from(11).kronecker_symbol(Integer::from(8)), -1); /// assert_eq!(Integer::from(-7).kronecker_symbol(Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).kronecker_symbol(Integer::from(5)), 1); /// assert_eq!(Integer::from(-11).kronecker_symbol(Integer::from(9)), 1); /// assert_eq!(Integer::from(-11).kronecker_symbol(Integer::from(8)), -1); /// assert_eq!(Integer::from(-11).kronecker_symbol(Integer::from(-8)), 1); /// ``` #[inline] fn kronecker_symbol(self, other: Self) -> i8 { (&self).kronecker_symbol(&other) } } impl KroneckerSymbol<&Self> for Integer { /// Computes the Kronecker symbol of two [`Integer`]s, taking the first by value and the second /// by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(10).kronecker_symbol(&Integer::from(5)), 0); /// assert_eq!(Integer::from(7).kronecker_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(11).kronecker_symbol(&Integer::from(5)), 1); /// assert_eq!(Integer::from(11).kronecker_symbol(&Integer::from(9)), 1); /// assert_eq!(Integer::from(11).kronecker_symbol(&Integer::from(8)), -1); /// assert_eq!(Integer::from(-7).kronecker_symbol(&Integer::from(5)), -1); /// assert_eq!(Integer::from(-11).kronecker_symbol(&Integer::from(5)), 1); /// assert_eq!(Integer::from(-11).kronecker_symbol(&Integer::from(9)), 1); /// assert_eq!(Integer::from(-11).kronecker_symbol(&Integer::from(8)), -1); /// assert_eq!(Integer::from(-11).kronecker_symbol(&Integer::from(-8)), 1); /// ``` #[inline] fn kronecker_symbol(self, other: &Self) -> i8 { (&self).kronecker_symbol(other) } } impl KroneckerSymbol for &Integer { /// Computes the Kronecker symbol of two [`Integer`]s, taking the first by reference and the /// second value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).kronecker_symbol(Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).kronecker_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(Integer::from(5)), 1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(Integer::from(9)), 1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(Integer::from(8)), -1); /// assert_eq!((&Integer::from(-7)).kronecker_symbol(Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(Integer::from(5)), 1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(Integer::from(9)), 1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(Integer::from(8)), -1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(Integer::from(-8)), 1); /// ``` #[inline] fn kronecker_symbol(self, other: Integer) -> i8 { self.kronecker_symbol(&other) } } impl KroneckerSymbol<&Integer> for &Integer { /// Computes the Kronecker symbol of two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(10)).kronecker_symbol(&Integer::from(5)), 0); /// assert_eq!((&Integer::from(7)).kronecker_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(&Integer::from(5)), 1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(&Integer::from(9)), 1); /// assert_eq!((&Integer::from(11)).kronecker_symbol(&Integer::from(8)), -1); /// assert_eq!((&Integer::from(-7)).kronecker_symbol(&Integer::from(5)), -1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(&Integer::from(5)), 1); /// assert_eq!((&Integer::from(-11)).kronecker_symbol(&Integer::from(9)), 1); /// assert_eq!( /// (&Integer::from(-11)).kronecker_symbol(&Integer::from(8)), /// -1 /// ); /// assert_eq!( /// (&Integer::from(-11)).kronecker_symbol(&Integer::from(-8)), /// 1 /// ); /// ``` fn kronecker_symbol(self, other: &Integer) -> i8 { match (self, other) { (x, integer_zero!()) => i8::from(*x.unsigned_abs_ref() == 1u32), (integer_zero!(), y) => i8::from(*y.unsigned_abs_ref() == 1u32), ( Integer { sign: x_sign, abs: Natural(Small(x_abs)), }, Integer { sign: y_sign, abs: Natural(Small(y_abs)), }, ) => limbs_kronecker_symbol_single(*x_sign, *x_abs, *y_sign, *y_abs), ( Integer { sign: x_sign, abs: Natural(Small(x_abs)), }, Integer { sign: y_sign, abs: Natural(Large(ys)), }, ) => limbs_kronecker_symbol(*x_sign, &[*x_abs], *y_sign, ys), ( Integer { sign: x_sign, abs: Natural(Large(xs)), }, Integer { sign: y_sign, abs: Natural(Small(y_abs)), }, ) => limbs_kronecker_symbol(*x_sign, xs, *y_sign, &[*y_abs]), ( Integer { sign: x_sign, abs: Natural(Large(xs)), }, Integer { sign: y_sign, abs: Natural(Large(ys)), }, ) => limbs_kronecker_symbol(*x_sign, xs, *y_sign, ys), } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . /// Absolute value of [`Integer`](super::Integer)s, including implementations of /// [`UnsignedAbs`](malachite_base::num::arithmetic::traits::UnsignedAbs). pub mod abs; /// Implementations of [`AbsDiff`](malachite_base::num::arithmetic::traits::AbsDiff) and /// [`AbsDiffAssign`](malachite_base::num::arithmetic::traits::AbsDiffAssign), traits for getting /// the absolute value of the difference between two numbers. pub mod abs_diff; /// Addition of [`Integer`](super::Integer)s. pub mod add; /// Implementations of [`AddMul`](malachite_base::num::arithmetic::traits::AddMul) and /// [`AddMulAssign`](malachite_base::num::arithmetic::traits::AddMulAssign), traits for adding a /// number and the product of two other numbers. pub mod add_mul; /// Implementations of /// [`BinomialCoefficient`](malachite_base::num::arithmetic::traits::BinomialCoefficient), a trait /// for computing the binomial coefficient of two numbers. pub mod binomial_coefficient; /// Division of [`Integer`](super::Integer)s. pub mod div; /// Implementations of [`DivExact`](malachite_base::num::arithmetic::traits::DivExact) and /// [`DivExactAssign`](malachite_base::num::arithmetic::traits::DivExactAssign), traits for dividing /// two numbers when it's known that the division is exact. pub mod div_exact; /// Implementations of raits for simultaneously finding the quotient and remainder of two numbers, /// subject to various rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |--------------|---------------------------------|----------------------------------------| /// | towards $-\infty$ | [`DivMod`](malachite_base::num::arithmetic::traits::DivMod) | [`DivAssignMod`](malachite_base::num::arithmetic::traits::DivAssignMod) | /// | towards 0 | [`DivRem`](malachite_base::num::arithmetic::traits::DivRem) | [`DivAssignRem`](malachite_base::num::arithmetic::traits::DivAssignRem) | /// | towards $\infty$ | [`CeilingDivMod`](malachite_base::num::arithmetic::traits::CeilingDivMod) | [`CeilingDivAssignMod`](malachite_base::num::arithmetic::traits::CeilingDivAssignMod) | pub mod div_mod; /// Implementations of [`DivRound`](malachite_base::num::arithmetic::traits::DivRound) and /// [`DivExactAssign`](malachite_base::num::arithmetic::traits::DivRoundAssign), traits for dividing /// two numbers according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). pub mod div_round; /// Implementations of [`DivisibleBy`](malachite_base::num::arithmetic::traits::DivisibleBy), a /// trait for determining whether one number is divisible by another. pub mod divisible_by; /// Implementations of /// [`DivisibleByPowerOf2`](malachite_base::num::arithmetic::traits::DivisibleByPowerOf2), a trait /// for determining whether a number is divisible by $2^k$. pub mod divisible_by_power_of_2; /// Implementations of [`EqMod`](malachite_base::num::arithmetic::traits::EqMod), a trait for /// determining whether one number is equal by another modulo a third. pub mod eq_mod; /// Implementations of [`EqModPowerOf2`](malachite_base::num::arithmetic::traits::EqModPowerOf2), a /// trait for determining whether one number is equal to another modulo $2^k$. pub mod eq_mod_power_of_2; /// Implementations of [`ExtendedGcd`](malachite_base::num::arithmetic::traits::ExtendedGcd), a /// trait for computing the extended GCD of two numbers. pub mod extended_gcd; /// Implementations of [`LegendreSymbol`](malachite_base::num::arithmetic::traits::LegendreSymbol), /// [`JacobiSymbol`](malachite_base::num::arithmetic::traits::JacobiSymbol), and /// [`KroneckerSymbol`](malachite_base::num::arithmetic::traits::KroneckerSymbol), traits for /// computing the Legendre, Jacobi, and Kronecker symbols of two numbers. pub mod kronecker_symbol; /// Implementations of traits for finding the remainder of two numbers, subject to various rounding /// rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |-------------------|----------------------------|----------------------------------------| /// | towards $-\infty$ | [`Mod`](malachite_base::num::arithmetic::traits::Mod) | [`ModAssign`](malachite_base::num::arithmetic::traits::ModAssign) | /// | towards $\infty$ | [`CeilingMod`](malachite_base::num::arithmetic::traits::CeilingMod) | [`CeilingModAssign`](malachite_base::num::arithmetic::traits::CeilingModAssign) | /// /// The [`Rem`](core::ops::Rem) trait in the standard library rounds towards 0. pub mod mod_op; /// Implementations of traits for finding the remainder of a number divided by $2^k$, subject to /// various rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |----------|-----------------------|-----------------------------------| /// | towards $-\infty$ | [`ModPowerOf2`](malachite_base::num::arithmetic::traits::ModPowerOf2) | [`ModPowerOf2Assign`](malachite_base::num::arithmetic::traits::ModPowerOf2Assign) | /// | towards 0 | [`RemPowerOf2`](malachite_base::num::arithmetic::traits::RemPowerOf2) | [`RemPowerOf2Assign`](malachite_base::num::arithmetic::traits::RemPowerOf2Assign) | /// | towards $\infty$ | [`CeilingModPowerOf2`](malachite_base::num::arithmetic::traits::CeilingModPowerOf2) | [`CeilingModPowerOf2Assign`](malachite_base::num::arithmetic::traits::CeilingModPowerOf2Assign) | pub mod mod_power_of_2; /// Multiplication of [`Integer`](super::Integer)s. pub mod mul; /// Negation of an [`Integer`](super::Integer). pub mod neg; /// Implementations of [`Parity`](malachite_base::num::arithmetic::traits::Parity), a trait for /// determining whether a number is even or odd. pub mod parity; /// Implementations of [`Pow`](malachite_base::num::arithmetic::traits::Pow) and /// [`PowAssign`](malachite_base::num::arithmetic::traits::PowAssign), traits for raising a number /// to a power. pub mod pow; /// Implementations of [`PowerOf2`](malachite_base::num::arithmetic::traits::PowerOf2), a trait for /// computing a power of 2. pub mod power_of_2; /// Implementations of traits for taking the $n$th root of a number. /// /// The traits are [`FloorRoot`](malachite_base::num::arithmetic::traits::FloorRoot), /// [`FloorRootAssign`](malachite_base::num::arithmetic::traits::FloorRootAssign), /// [`CeilingRoot`](malachite_base::num::arithmetic::traits::CeilingRoot), /// [`CeilingRootAssign`](malachite_base::num::arithmetic::traits::CeilingRootAssign), and /// [`CheckedRoot`](malachite_base::num::arithmetic::traits::CheckedRoot). pub mod root; /// Implementations of [`RoundToMultiple`](malachite_base::num::arithmetic::traits::RoundToMultiple) /// and [`RoundToMultipleAssign`](malachite_base::num::arithmetic::traits::RoundToMultipleAssign), /// traits for rounding a number to a multiple of another number. pub mod round_to_multiple; /// Implementations of /// [`RoundToMultipleOfPowerOf2`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2) /// and /// [`RoundToMultipleOfPowerOf2Assign`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign), /// traits for rounding a number to a multiple of a power of 2. pub mod round_to_multiple_of_power_of_2; /// Left-shifting an [`Integer`](super::Integer) (multiplying it by a power of 2). /// /// # shl /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO << 10u8, 0); /// assert_eq!(Integer::from(123) << 2u16, 492); /// assert_eq!( /// (Integer::from(123) << 100u32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(Integer::from(-123) << 2u64, -492); /// assert_eq!( /// (Integer::from(-123) << 100u8).to_string(), /// "-155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::ZERO << 10u8, 0); /// assert_eq!(&Integer::from(123) << 2u16, 492); /// assert_eq!( /// (&Integer::from(123) << 100u32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::from(-123) << 2u64, -492); /// assert_eq!( /// (&Integer::from(-123) << 100u8).to_string(), /// "-155921023828072216384094494261248" /// ); /// /// assert_eq!(Integer::ZERO << 10i8, 0); /// assert_eq!(Integer::from(123) << 2i16, 492); /// assert_eq!( /// (Integer::from(123) << 100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(Integer::from(-123) << 2i64, -492); /// assert_eq!( /// (Integer::from(-123) << 100i8).to_string(), /// "-155921023828072216384094494261248" /// ); /// assert_eq!(Integer::ZERO << -10i16, 0); /// assert_eq!(Integer::from(492) << -2i32, 123); /// assert_eq!(-Integer::from(10u32).pow(12) << -10i64, -976562500); /// assert_eq!(&Integer::ZERO << 10i8, 0); /// assert_eq!(&Integer::from(123) << 2i16, 492); /// assert_eq!( /// (&Integer::from(123) << 100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::from(-123) << 2i64, -492); /// assert_eq!( /// (&Integer::from(-123) << 100i8).to_string(), /// "-155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::ZERO << -10i16, 0); /// assert_eq!(&Integer::from(492) << -2i32, 123); /// assert_eq!(&(-Integer::from(10u32).pow(12)) << -10i64, -976562500); /// ``` /// /// # shl_assign /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ONE; /// x <<= 1u8; /// x <<= 2u16; /// x <<= 3u32; /// x <<= 4u64; /// assert_eq!(x, 1024); /// let mut x = Integer::NEGATIVE_ONE; /// x <<= 1u8; /// x <<= 2u16; /// x <<= 3u32; /// x <<= 4u64; /// assert_eq!(x, -1024); /// /// let mut x = Integer::ONE; /// x <<= 1i8; /// x <<= 2i16; /// x <<= 3i32; /// x <<= 4i64; /// assert_eq!(x, 1024); /// let mut x = Integer::NEGATIVE_ONE; /// x <<= 1i8; /// x <<= 2i16; /// x <<= 3i32; /// x <<= 4i64; /// assert_eq!(x, -1024); /// /// let mut x = Integer::from(1024); /// x <<= -1i8; /// x <<= -2i16; /// x <<= -3i32; /// x <<= -4i64; /// assert_eq!(x, 1); /// ``` pub mod shl; /// Implementations of [`ShlRound`](malachite_base::num::arithmetic::traits::ShlRound) and /// [`ShlRoundAssign`](malachite_base::num::arithmetic::traits::ShlRoundAssign), traits for /// multiplying a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). /// /// # shl_round /// ``` /// use malachite_base::num::arithmetic::traits::ShlRound; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(0x101).shl_round(-8i8, Down).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Integer::from(0x101).shl_round(-8i16, Up).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Integer::from(-0x101) /// .shl_round(-9i32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x101).shl_round(-9i64, Up).to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0x101) /// .shl_round(-9i8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0xff) /// .shl_round(-9i16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x100) /// .shl_round(-9i32, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// Integer::from(0x100) /// .shl_round(-8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// Integer::ZERO.shl_round(10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Integer::from(123u32) /// .shl_round(2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// Integer::from(123u32) /// .shl_round(100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// /// assert_eq!( /// (&Integer::from(0x101)) /// .shl_round(-8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Integer::from(0x101)) /// .shl_round(-8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(-0x101)) /// .shl_round(-9i32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shl_round(-9i64, Up) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shl_round(-9i8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0xff)) /// .shl_round(-9i16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x100)) /// .shl_round(-9i32, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(0x100)) /// .shl_round(-8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// (&Integer::ZERO).shl_round(10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// (&Integer::from(123u32)) /// .shl_round(2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// (&Integer::from(123u32)) /// .shl_round(100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// ``` /// /// # shl_round_assign /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::ShlRoundAssign; /// use malachite_base::num::basic::traits::One; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut n = Integer::from(0x101); /// assert_eq!(n.shl_round_assign(-8i8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Integer::from(0x101); /// assert_eq!(n.shl_round_assign(-8i16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shl_round_assign(-9i32, Down), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shl_round_assign(-9i64, Up), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shl_round_assign(-9i8, Nearest), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0xff); /// assert_eq!(n.shl_round_assign(-9i16, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x100); /// assert_eq!(n.shl_round_assign(-9i32, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(0x100); /// assert_eq!(n.shl_round_assign(-8i64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut x = Integer::ONE; /// assert_eq!(x.shl_round_assign(1i8, Exact), Equal); /// assert_eq!(x.shl_round_assign(2i16, Exact), Equal); /// assert_eq!(x.shl_round_assign(3i32, Exact), Equal); /// assert_eq!(x.shl_round_assign(4i64, Exact), Equal); /// assert_eq!(x, 1024); /// ``` pub mod shl_round; /// Right-shifting an [`Integer`](super::Integer) (dividing it by a power of 2). /// /// # shr /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO >> 10u8, 0); /// assert_eq!(Integer::from(492) >> 2u16, 123); /// assert_eq!(-Integer::from(10u32).pow(12) >> 10u32, -976562500); /// assert_eq!(&Integer::ZERO >> 10u8, 0); /// assert_eq!(&Integer::from(492) >> 2u16, 123); /// assert_eq!(&-Integer::from(10u32).pow(12) >> 10u32, -976562500); /// /// assert_eq!(Integer::ZERO >> 10i8, 0); /// assert_eq!(Integer::from(492) >> 2i16, 123); /// assert_eq!(-Integer::from(10u32).pow(12) >> 10i64, -976562500); /// assert_eq!(Integer::ZERO >> -10i8, 0); /// assert_eq!(Integer::from(123) >> -2i16, 492); /// assert_eq!( /// (Integer::from(123) >> -100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(Integer::from(-123) >> -2i64, -492); /// assert_eq!( /// (Integer::from(-123) >> -100i8).to_string(), /// "-155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::ZERO >> 10i8, 0); /// assert_eq!(&Integer::from(492) >> 2i16, 123); /// assert_eq!(&-Integer::from(10u32).pow(12) >> 10i64, -976562500); /// assert_eq!(&Integer::ZERO >> -10i8, 0); /// assert_eq!(&Integer::from(123) >> -2i16, 492); /// assert_eq!( /// (&Integer::from(123) >> -100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!(&Integer::from(-123) >> -2i64, -492); /// assert_eq!( /// (&Integer::from(-123) >> -100i8).to_string(), /// "-155921023828072216384094494261248" /// ); /// ``` /// /// # shr_assign /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(1024); /// x >>= 1u8; /// x >>= 2u16; /// x >>= 3u32; /// x >>= 4u64; /// assert_eq!(x, 1); /// /// let mut x = Integer::from(1024); /// x >>= 1i8; /// x >>= 2i16; /// x >>= 3i32; /// x >>= 4i64; /// assert_eq!(x, 1); /// /// let mut x = Integer::ONE; /// x >>= -1i8; /// x >>= -2i16; /// x >>= -3i32; /// x >>= -4i64; /// assert_eq!(x, 1024); /// /// let mut x = Integer::NEGATIVE_ONE; /// x >>= -1i8; /// x >>= -2i16; /// x >>= -3i32; /// x >>= -4i64; /// assert_eq!(x, -1024); /// ``` pub mod shr; /// Implementations of [`ShrRound`](malachite_base::num::arithmetic::traits::ShrRound) and /// [`ShrRoundAssign`](malachite_base::num::arithmetic::traits::ShrRoundAssign), traits for dividing /// a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). /// /// # shr_round /// ``` /// use malachite_base::num::arithmetic::traits::ShrRound; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(0x101).shr_round(8u8, Down).to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Integer::from(0x101).shr_round(8u16, Up).to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Integer::from(-0x101) /// .shr_round(9u32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x101).shr_round(9u64, Up).to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0x101) /// .shr_round(9u8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0xff) /// .shr_round(9u16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x100) /// .shr_round(9u64, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// Integer::from(0x100u32) /// .shr_round(8u32, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// (&Integer::from(0x101)) /// .shr_round(8u8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Integer::from(0x101)) /// .shr_round(8u16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9u32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9u64, Up) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9u8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0xff)) /// .shr_round(9u16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x100)) /// .shr_round(9u64, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(0x100u32)) /// .shr_round(8u32, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// Integer::from(0x101u32) /// .shr_round(8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Integer::from(0x101u32) /// .shr_round(8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// Integer::from(-0x101) /// .shr_round(9i32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x101).shr_round(9i64, Up).to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0x101) /// .shr_round(9i8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// Integer::from(-0xff) /// .shr_round(9i16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::from(-0x100) /// .shr_round(9i32, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// Integer::from(0x100u32) /// .shr_round(8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// Integer::ZERO.shr_round(-10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Integer::from(123u32) /// .shr_round(-2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// Integer::from(123u32) /// .shr_round(-100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// /// assert_eq!( /// (&Integer::from(0x101u32)) /// .shr_round(8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Integer::from(0x101u32)) /// .shr_round(8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9i32, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9i64, Up) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0x101)) /// .shr_round(9i8, Nearest) /// .to_debug_string(), /// "(-1, Less)" /// ); /// assert_eq!( /// (&Integer::from(-0xff)) /// .shr_round(9i16, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-0x100)) /// .shr_round(9i32, Nearest) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(0x100u32)) /// .shr_round(8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// (&Integer::ZERO).shr_round(-10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// (&Integer::from(123u32)) /// .shr_round(-2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// (&Integer::from(123u32)) /// .shr_round(-100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// ``` /// /// # shr_round_assign /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::ShrRoundAssign; /// use malachite_base::num::basic::traits::One; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut n = Integer::from(0x101); /// assert_eq!(n.shr_round_assign(8u8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Integer::from(0x101); /// assert_eq!(n.shr_round_assign(8u16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9u32, Down), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9u64, Up), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9u8, Nearest), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0xff); /// assert_eq!(n.shr_round_assign(9u16, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x100); /// assert_eq!(n.shr_round_assign(9u32, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(0x100); /// assert_eq!(n.shr_round_assign(8u64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut n = Integer::from(0x101u32); /// assert_eq!(n.shr_round_assign(8i8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Integer::from(0x101u32); /// assert_eq!(n.shr_round_assign(8i16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9i32, Down), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9i64, Up), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0x101); /// assert_eq!(n.shr_round_assign(9i8, Nearest), Less); /// assert_eq!(n, -1); /// /// let mut n = Integer::from(-0xff); /// assert_eq!(n.shr_round_assign(9i16, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(-0x100); /// assert_eq!(n.shr_round_assign(9i32, Nearest), Greater); /// assert_eq!(n, 0); /// /// let mut n = Integer::from(0x100u32); /// assert_eq!(n.shr_round_assign(8i64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut x = Integer::ONE; /// assert_eq!(x.shr_round_assign(-1i8, Exact), Equal); /// assert_eq!(x.shr_round_assign(-2i16, Exact), Equal); /// assert_eq!(x.shr_round_assign(-3i32, Exact), Equal); /// assert_eq!(x.shr_round_assign(-4i64, Exact), Equal); /// assert_eq!(x, 1024); /// ``` pub mod shr_round; /// Implementations of [`Sign`](malachite_base::num::arithmetic::traits::Sign), a trait for /// determining the sign of a number. pub mod sign; /// Implementations of traits for taking the square root of a number. /// /// The traits are [`FloorSqrt`](malachite_base::num::arithmetic::traits::FloorSqrt), /// [`FloorSqrtAssign`](malachite_base::num::arithmetic::traits::FloorSqrtAssign), /// [`CeilingSqrt`](malachite_base::num::arithmetic::traits::CeilingSqrt), /// [`CeilingSqrtAssign`](malachite_base::num::arithmetic::traits::CeilingSqrtAssign), and /// [`CheckedSqrt`](malachite_base::num::arithmetic::traits::CheckedSqrt). pub mod sqrt; /// Implementations of [`Square`](malachite_base::num::arithmetic::traits::Square) and /// [`SquareAssign`](malachite_base::num::arithmetic::traits::SquareAssign), traits for squaring a /// number. pub mod square; /// Subtraction of [`Integer`](super::Integer)s. pub mod sub; /// Implementations of [`SubMul`](malachite_base::num::arithmetic::traits::SubMul) and /// [`SubMulAssign`](malachite_base::num::arithmetic::traits::SubMulAssign), traits for subtracting /// the product of two numbers from a number. pub mod sub_mul; ================================================ FILE: malachite-nz/src/integer/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::ops::{Rem, RemAssign}; use malachite_base::num::arithmetic::traits::{ CeilingMod, CeilingModAssign, Mod, ModAssign, NegMod, NegModAssign, }; impl Mod for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning just the /// remainder. The remainder has the same sign as the second [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23).mod_op(Integer::from(10)), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23).mod_op(Integer::from(-10)), -7); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23).mod_op(Integer::from(10)), 7); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23).mod_op(Integer::from(-10)), -3); /// ``` #[inline] fn mod_op(mut self, other: Self) -> Self { self.mod_assign(other); self } } impl Mod<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and returning just the remainder. The remainder has the same sign as the second /// [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23).mod_op(&Integer::from(10)), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23).mod_op(&Integer::from(-10)), -7); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23).mod_op(&Integer::from(10)), 7); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23).mod_op(&Integer::from(-10)), -3); /// ``` #[inline] fn mod_op(mut self, other: &Self) -> Self { self.mod_assign(other); self } } impl Mod for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning just the remainder. The remainder has the same sign as the second /// [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Integer::from(23)).mod_op(Integer::from(10)), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!((&Integer::from(23)).mod_op(Integer::from(-10)), -7); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((&Integer::from(-23)).mod_op(Integer::from(10)), 7); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((&Integer::from(-23)).mod_op(Integer::from(-10)), -3); /// ``` fn mod_op(self, other: Integer) -> Integer { Integer::from_sign_and_abs( other.sign, if self.sign == other.sign { &self.abs % other.abs } else { (&self.abs).neg_mod(other.abs) }, ) } } impl Mod<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning just /// the remainder. The remainder has the same sign as the second [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Integer::from(23)).mod_op(&Integer::from(10)), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!((&Integer::from(23)).mod_op(&Integer::from(-10)), -7); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((&Integer::from(-23)).mod_op(&Integer::from(10)), 7); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((&Integer::from(-23)).mod_op(&Integer::from(-10)), -3); /// ``` fn mod_op(self, other: &Integer) -> Integer { Integer::from_sign_and_abs( other.sign, if self.sign == other.sign { &self.abs % &other.abs } else { (&self.abs).neg_mod(&other.abs) }, ) } } impl ModAssign for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the second [`Integer`] by value and /// replacing the first by the remainder. The remainder has the same sign as the second /// [`Integer`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x.mod_assign(Integer::from(10)); /// assert_eq!(x, 3); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x.mod_assign(Integer::from(-10)); /// assert_eq!(x, -7); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x.mod_assign(Integer::from(10)); /// assert_eq!(x, 7); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x.mod_assign(Integer::from(-10)); /// assert_eq!(x, -3); /// ``` fn mod_assign(&mut self, other: Self) { if self.sign == other.sign { self.abs %= other.abs; } else { self.abs.neg_mod_assign(other.abs); }; self.sign = other.sign || self.abs == 0; } } impl ModAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the second [`Integer`] by reference /// and replacing the first by the remainder. The remainder has the same sign as the second /// [`Integer`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x.mod_assign(&Integer::from(10)); /// assert_eq!(x, 3); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x.mod_assign(&Integer::from(-10)); /// assert_eq!(x, -7); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x.mod_assign(&Integer::from(10)); /// assert_eq!(x, 7); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x.mod_assign(&Integer::from(-10)); /// assert_eq!(x, -3); /// ``` fn mod_assign(&mut self, other: &Self) { if self.sign == other.sign { self.abs %= &other.abs; } else { self.abs.neg_mod_assign(&other.abs); }; self.sign = other.sign || self.abs == 0; } } impl Rem for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning just the /// remainder. The remainder has the same sign as the first [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23) % Integer::from(10), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23) % Integer::from(-10), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23) % Integer::from(10), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23) % Integer::from(-10), -3); /// ``` #[inline] fn rem(mut self, other: Self) -> Self { self %= other; self } } impl Rem<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and returning just the remainder. The remainder has the same sign as the first /// [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23) % &Integer::from(10), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23) % &Integer::from(-10), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23) % &Integer::from(10), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23) % &Integer::from(-10), -3); /// ``` #[inline] fn rem(mut self, other: &Self) -> Self { self %= other; self } } impl Rem for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning just the remainder. The remainder has the same sign as the first /// [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Integer::from(23) % Integer::from(10), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(&Integer::from(23) % Integer::from(-10), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(&Integer::from(-23) % Integer::from(10), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(&Integer::from(-23) % Integer::from(-10), -3); /// ``` #[inline] fn rem(self, other: Integer) -> Integer { Integer::from_sign_and_abs(self.sign, &self.abs % other.abs) } } impl Rem<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning just /// the remainder. The remainder has the same sign as the first [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Integer::from(23) % &Integer::from(10), 3); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(&Integer::from(23) % &Integer::from(-10), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(&Integer::from(-23) % &Integer::from(10), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(&Integer::from(-23) % &Integer::from(-10), -3); /// ``` #[inline] fn rem(self, other: &Integer) -> Integer { Integer::from_sign_and_abs(self.sign, &self.abs % &other.abs) } } impl RemAssign for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the second [`Integer`] by value and /// replacing the first by the remainder. The remainder has the same sign as the first /// [`Integer`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x %= Integer::from(10); /// assert_eq!(x, 3); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x %= Integer::from(-10); /// assert_eq!(x, 3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x %= Integer::from(10); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x %= Integer::from(-10); /// assert_eq!(x, -3); /// ``` #[inline] fn rem_assign(&mut self, other: Self) { self.abs %= other.abs; self.sign = self.sign || self.abs == 0; } } impl RemAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the second [`Integer`] by reference /// and replacing the first by the remainder. The remainder has the same sign as the first /// [`Integer`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x %= &Integer::from(10); /// assert_eq!(x, 3); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x %= &Integer::from(-10); /// assert_eq!(x, 3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x %= &Integer::from(10); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x %= &Integer::from(-10); /// assert_eq!(x, -3); /// ``` #[inline] fn rem_assign(&mut self, other: &Self) { self.abs %= &other.abs; self.sign = self.sign || self.abs == 0; } } impl CeilingMod for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking both by value and returning just the /// remainder. The remainder has the opposite sign as the second [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23).ceiling_mod(Integer::from(10)), -7); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23).ceiling_mod(Integer::from(-10)), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23).ceiling_mod(Integer::from(10)), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23).ceiling_mod(Integer::from(-10)), 7); /// ``` #[inline] fn ceiling_mod(mut self, other: Self) -> Self { self.ceiling_mod_assign(other); self } } impl CeilingMod<&Self> for Integer { type Output = Self; /// Divides an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference and returning just the remainder. The remainder has the opposite sign as the /// second [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Integer::from(23).ceiling_mod(&Integer::from(10)), -7); /// /// // -3 * -10 + -7 = 23 /// assert_eq!(Integer::from(23).ceiling_mod(&Integer::from(-10)), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!(Integer::from(-23).ceiling_mod(&Integer::from(10)), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!(Integer::from(-23).ceiling_mod(&Integer::from(-10)), 7); /// ``` #[inline] fn ceiling_mod(mut self, other: &Self) -> Self { self.ceiling_mod_assign(other); self } } impl CeilingMod for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking the first by reference and the second /// by value and returning just the remainder. The remainder has the opposite sign as the second /// [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Integer::from(23)).ceiling_mod(Integer::from(10)), -7); /// /// // -3 * -10 + -7 = 23 /// assert_eq!((&Integer::from(23)).ceiling_mod(Integer::from(-10)), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((&Integer::from(-23)).ceiling_mod(Integer::from(10)), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((&Integer::from(-23)).ceiling_mod(Integer::from(-10)), 7); /// ``` fn ceiling_mod(self, other: Integer) -> Integer { Integer::from_sign_and_abs( !other.sign, if self.sign == other.sign { (&self.abs).neg_mod(other.abs) } else { &self.abs % other.abs }, ) } } impl CeilingMod<&Integer> for &Integer { type Output = Integer; /// Divides an [`Integer`] by another [`Integer`], taking both by reference and returning just /// the remainder. The remainder has the opposite sign as the second [`Integer`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Integer::from(23)).ceiling_mod(&Integer::from(10)), -7); /// /// // -3 * -10 + -7 = 23 /// assert_eq!((&Integer::from(23)).ceiling_mod(&Integer::from(-10)), 3); /// /// // -3 * 10 + 7 = -23 /// assert_eq!((&Integer::from(-23)).ceiling_mod(&Integer::from(10)), -3); /// /// // 2 * -10 + -3 = -23 /// assert_eq!((&Integer::from(-23)).ceiling_mod(&Integer::from(-10)), 7); /// ``` fn ceiling_mod(self, other: &Integer) -> Integer { Integer::from_sign_and_abs( !other.sign, if self.sign == other.sign { (&self.abs).neg_mod(&other.abs) } else { &self.abs % &other.abs }, ) } } impl CeilingModAssign for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the [`Integer`] on the right-hand side /// by value and replacing the first number by the remainder. The remainder has the opposite /// sign as the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModAssign; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x.ceiling_mod_assign(Integer::from(10)); /// assert_eq!(x, -7); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x.ceiling_mod_assign(Integer::from(-10)); /// assert_eq!(x, 3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x.ceiling_mod_assign(Integer::from(10)); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x.ceiling_mod_assign(Integer::from(-10)); /// assert_eq!(x, 7); /// ``` fn ceiling_mod_assign(&mut self, other: Self) { if self.sign == other.sign { self.abs.neg_mod_assign(other.abs); } else { self.abs %= other.abs; }; self.sign = !other.sign || self.abs == 0; } } impl CeilingModAssign<&Self> for Integer { /// Divides an [`Integer`] by another [`Integer`], taking the [`Integer`] on the right-hand side /// by reference and replacing the first number by the remainder. The remainder has the opposite /// sign as the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModAssign; /// use malachite_nz::integer::Integer; /// /// // 2 * 10 + 3 = 23 /// let mut x = Integer::from(23); /// x.ceiling_mod_assign(&Integer::from(10)); /// assert_eq!(x, -7); /// /// // -3 * -10 + -7 = 23 /// let mut x = Integer::from(23); /// x.ceiling_mod_assign(&Integer::from(-10)); /// assert_eq!(x, 3); /// /// // -3 * 10 + 7 = -23 /// let mut x = Integer::from(-23); /// x.ceiling_mod_assign(&Integer::from(10)); /// assert_eq!(x, -3); /// /// // 2 * -10 + -3 = -23 /// let mut x = Integer::from(-23); /// x.ceiling_mod_assign(&Integer::from(-10)); /// assert_eq!(x, 7); /// ``` fn ceiling_mod_assign(&mut self, other: &Self) { if self.sign == other.sign { self.abs.neg_mod_assign(&other.abs); } else { self.abs %= &other.abs; }; self.sign = !other.sign || self.abs == 0; } } ================================================ FILE: malachite-nz/src/integer/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ CeilingModPowerOf2, CeilingModPowerOf2Assign, ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, NegModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign, }; impl ModPowerOf2 for Integer { type Output = Natural; /// Divides an [`Integer`] by $2^k$, taking it by value and returning just the remainder. The /// remainder is non-negative. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// Unlike /// [`rem_power_of_2`](malachite_base::num::arithmetic::traits::RemPowerOf2::rem_power_of_2), /// this function always returns a non-negative number. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(Integer::from(260).mod_power_of_2(8), 4); /// /// // -101 * 2^4 + 5 = -1611 /// assert_eq!(Integer::from(-1611).mod_power_of_2(4), 5); /// ``` fn mod_power_of_2(self, pow: u64) -> Natural { if self.sign { self.abs.mod_power_of_2(pow) } else { self.abs.neg_mod_power_of_2(pow) } } } impl ModPowerOf2 for &Integer { type Output = Natural; /// Divides an [`Integer`] by $2^k$, taking it by reference and returning just the remainder. /// The remainder is non-negative. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// Unlike /// [`rem_power_of_2`](malachite_base::num::arithmetic::traits::RemPowerOf2::rem_power_of_2), /// this function always returns a non-negative number. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!((&Integer::from(260)).mod_power_of_2(8), 4); /// // -101 * 2^4 + 5 = -1611 /// assert_eq!((&Integer::from(-1611)).mod_power_of_2(4), 5); /// ``` fn mod_power_of_2(self, pow: u64) -> Natural { if self.sign { (&self.abs).mod_power_of_2(pow) } else { (&self.abs).neg_mod_power_of_2(pow) } } } impl ModPowerOf2Assign for Integer { /// Divides an [`Integer`] by $2^k$, replacing the [`Integer`] by the remainder. The remainder /// is non-negative. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// Unlike [`rem_power_of_2_assign`](RemPowerOf2Assign::rem_power_of_2_assign), this function /// always assigns a non-negative number. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Assign; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = Integer::from(260); /// x.mod_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // -101 * 2^4 + 5 = -1611 /// let mut x = Integer::from(-1611); /// x.mod_power_of_2_assign(4); /// assert_eq!(x, 5); /// ``` fn mod_power_of_2_assign(&mut self, pow: u64) { if self.sign { self.abs.mod_power_of_2_assign(pow); } else { self.sign = true; self.abs.neg_mod_power_of_2_assign(pow); } } } impl RemPowerOf2 for Integer { type Output = Self; /// Divides an [`Integer`] by $2^k$, taking it by value and returning just the remainder. The /// remainder has the same sign as the first number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq |r| < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor. /// $$ /// /// Unlike /// [`mod_power_of_2`](malachite_base::num::arithmetic::traits::ModPowerOf2::mod_power_of_2), /// this function always returns zero or a number with the same sign as `self`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(Integer::from(260).rem_power_of_2(8), 4); /// /// // -100 * 2^4 + -11 = -1611 /// assert_eq!(Integer::from(-1611).rem_power_of_2(4), -11); /// ``` fn rem_power_of_2(self, pow: u64) -> Self { let abs_rem = self.abs.mod_power_of_2(pow); Self { sign: self.sign || abs_rem == 0, abs: abs_rem, } } } impl RemPowerOf2 for &Integer { type Output = Integer; /// Divides an [`Integer`] by $2^k$, taking it by reference and returning just the remainder. /// The remainder has the same sign as the first number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq |r| < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor. /// $$ /// /// Unlike /// [`mod_power_of_2`](malachite_base::num::arithmetic::traits::ModPowerOf2::mod_power_of_2), /// this function always returns zero or a number with the same sign as `self`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!((&Integer::from(260)).rem_power_of_2(8), 4); /// // -100 * 2^4 + -11 = -1611 /// assert_eq!((&Integer::from(-1611)).rem_power_of_2(4), -11); /// ``` fn rem_power_of_2(self, pow: u64) -> Integer { let abs_rem = (&self.abs).mod_power_of_2(pow); Integer { sign: self.sign || abs_rem == 0, abs: abs_rem, } } } impl RemPowerOf2Assign for Integer { /// Divides an [`Integer`] by $2^k$, replacing the [`Integer`] by the remainder. The remainder /// has the same sign as the [`Integer`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k + r$ and $0 /// \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor. /// $$ /// /// Unlike [`mod_power_of_2_assign`](ModPowerOf2Assign::mod_power_of_2_assign), this function /// does never changes the sign of `self`, except possibly to set `self` to 0. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2Assign; /// use malachite_nz::integer::Integer; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = Integer::from(260); /// x.rem_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // -100 * 2^4 + -11 = -1611 /// let mut x = Integer::from(-1611); /// x.rem_power_of_2_assign(4); /// assert_eq!(x, -11); /// ``` fn rem_power_of_2_assign(&mut self, pow: u64) { self.abs.mod_power_of_2_assign(pow); if self.abs == 0 { self.sign = true; } } } impl CeilingModPowerOf2 for Integer { type Output = Self; /// Divides an [`Integer`] by $2^k$, taking it by value and returning just the remainder. The /// remainder is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq -r < 2^k$. /// /// $$ /// f(x, y) = x - 2^k\left \lceil \frac{x}{2^k} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 2 * 2^8 + -252 = 260 /// assert_eq!(Integer::from(260).ceiling_mod_power_of_2(8), -252); /// /// // -100 * 2^4 + -11 = -1611 /// assert_eq!(Integer::from(-1611).ceiling_mod_power_of_2(4), -11); /// ``` fn ceiling_mod_power_of_2(self, pow: u64) -> Self { let abs_mod = if self.sign { self.abs.neg_mod_power_of_2(pow) } else { self.abs.mod_power_of_2(pow) }; Self { sign: abs_mod == 0, abs: abs_mod, } } } impl CeilingModPowerOf2 for &Integer { type Output = Integer; /// Divides an [`Integer`] by $2^k$, taking it by reference and returning just the remainder. /// The remainder is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq -r < 2^k$. /// /// $$ /// f(x, y) = x - 2^k\left \lceil \frac{x}{2^k} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModPowerOf2; /// use malachite_nz::integer::Integer; /// /// // 2 * 2^8 + -252 = 260 /// assert_eq!((&Integer::from(260)).ceiling_mod_power_of_2(8), -252); /// // -100 * 2^4 + -11 = -1611 /// assert_eq!((&Integer::from(-1611)).ceiling_mod_power_of_2(4), -11); /// ``` fn ceiling_mod_power_of_2(self, pow: u64) -> Integer { let abs_mod = if self.sign { (&self.abs).neg_mod_power_of_2(pow) } else { (&self.abs).mod_power_of_2(pow) }; Integer { sign: abs_mod == 0, abs: abs_mod, } } } impl CeilingModPowerOf2Assign for Integer { /// Divides an [`Integer`] by $2^k$, replacing the [`Integer`] by the remainder. The remainder /// is non-positive. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq -r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lceil\frac{x}{2^k} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModPowerOf2Assign; /// use malachite_nz::integer::Integer; /// /// // 2 * 2^8 + -252 = 260 /// let mut x = Integer::from(260); /// x.ceiling_mod_power_of_2_assign(8); /// assert_eq!(x, -252); /// /// // -100 * 2^4 + -11 = -1611 /// let mut x = Integer::from(-1611); /// x.ceiling_mod_power_of_2_assign(4); /// assert_eq!(x, -11); /// ``` fn ceiling_mod_power_of_2_assign(&mut self, pow: u64) { if self.sign { self.abs.neg_mod_power_of_2_assign(pow); } else { self.abs.mod_power_of_2_assign(pow); }; self.sign = self.abs == 0; } } ================================================ FILE: malachite-nz/src/integer/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use alloc::vec::Vec; use core::iter::Product; use core::ops::{Mul, MulAssign}; use malachite_base::num::basic::traits::{One, Zero}; impl Mul for Integer { type Output = Self; /// Multiplies two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ONE * Integer::from(123), 123); /// assert_eq!(Integer::from(123) * Integer::ZERO, 0); /// assert_eq!(Integer::from(123) * Integer::from(-456), -56088); /// assert_eq!( /// (Integer::from(-123456789000i64) * Integer::from(-987654321000i64)).to_string(), /// "121932631112635269000000" /// ); /// ``` fn mul(mut self, other: Self) -> Self { self *= other; self } } impl Mul<&Self> for Integer { type Output = Self; /// Multiplies two [`Integer`]s, taking the first by value and the second by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ONE * &Integer::from(123), 123); /// assert_eq!(Integer::from(123) * &Integer::ZERO, 0); /// assert_eq!(Integer::from(123) * &Integer::from(-456), -56088); /// assert_eq!( /// (Integer::from(-123456789000i64) * &Integer::from(-987654321000i64)).to_string(), /// "121932631112635269000000" /// ); /// ``` fn mul(mut self, other: &Self) -> Self { self *= other; self } } impl Mul for &Integer { type Output = Integer; /// Multiplies two [`Integer`]s, taking the first by reference and the second by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ONE * Integer::from(123), 123); /// assert_eq!(&Integer::from(123) * Integer::ZERO, 0); /// assert_eq!(&Integer::from(123) * Integer::from(-456), -56088); /// assert_eq!( /// (&Integer::from(-123456789000i64) * Integer::from(-987654321000i64)).to_string(), /// "121932631112635269000000" /// ); /// ``` fn mul(self, mut other: Integer) -> Integer { other *= self; other } } impl Mul<&Integer> for &Integer { type Output = Integer; /// Multiplies two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ONE * &Integer::from(123), 123); /// assert_eq!(&Integer::from(123) * &Integer::ZERO, 0); /// assert_eq!(&Integer::from(123) * &Integer::from(-456), -56088); /// assert_eq!( /// (&Integer::from(-123456789000i64) * &Integer::from(-987654321000i64)).to_string(), /// "121932631112635269000000" /// ); /// ``` fn mul(self, other: &Integer) -> Integer { let product_abs = &self.abs * &other.abs; Integer { sign: self.sign == other.sign || product_abs == 0, abs: product_abs, } } } impl MulAssign for Integer { /// Multiplies an [`Integer`] by an [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. /// /// $$ /// x \gets = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeOne; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::NEGATIVE_ONE; /// x *= Integer::from(1000); /// x *= Integer::from(2000); /// x *= Integer::from(3000); /// x *= Integer::from(4000); /// assert_eq!(x, -24000000000000i64); /// ``` fn mul_assign(&mut self, other: Self) { self.abs *= other.abs; self.sign = self.sign == other.sign || self.abs == 0; } } impl MulAssign<&Self> for Integer { /// Multiplies an [`Integer`] by an [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. /// /// $$ /// x \gets = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeOne; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::NEGATIVE_ONE; /// x *= &Integer::from(1000); /// x *= &Integer::from(2000); /// x *= &Integer::from(3000); /// x *= &Integer::from(4000); /// assert_eq!(x, -24000000000000i64); /// ``` fn mul_assign(&mut self, other: &Self) { self.abs *= &other.abs; self.sign = self.sign == other.sign || self.abs == 0; } } impl Product for Integer { /// Multiplies together all the [`Integer`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Integer::sum(xs.map(Integer::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Product; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::product( /// vec_from_str::("[2, -3, 5, 7]") /// .unwrap() /// .into_iter() /// ), /// -210 /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { if x == 0 { return Self::ZERO; } let mut p = x; for _ in 0..i.trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } impl<'a> Product<&'a Self> for Integer { /// Multiplies together all the [`Integer`]s in an iterator of [`Integer`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Integer::sum(xs.map(Integer::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Product; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::product(vec_from_str::("[2, -3, 5, 7]").unwrap().iter()), /// -210 /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { if *x == 0 { return Self::ZERO; } let mut p = x.clone(); for _ in 0..i.trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } ================================================ FILE: malachite-nz/src/integer/arithmetic/neg.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::ops::Neg; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::NotAssign; impl Neg for Integer { type Output = Self; /// Negates an [`Integer`], taking it by value. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(-Integer::ZERO, 0); /// assert_eq!(-Integer::from(123), -123); /// assert_eq!(-Integer::from(-123), 123); /// ``` fn neg(mut self) -> Self { if self.abs != 0 { self.sign.not_assign(); } self } } impl Neg for &Integer { type Output = Integer; /// Negates an [`Integer`], taking it by reference. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(-&Integer::ZERO, 0); /// assert_eq!(-&Integer::from(123), -123); /// assert_eq!(-&Integer::from(-123), 123); /// ``` fn neg(self) -> Integer { if self.abs == 0 { Integer::ZERO } else { Integer { sign: !self.sign, abs: self.abs.clone(), } } } } impl NegAssign for Integer { /// Negates an [`Integer`] in place. /// /// $$ /// x \gets -x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.neg_assign(); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(123); /// x.neg_assign(); /// assert_eq!(x, -123); /// /// let mut x = Integer::from(-123); /// x.neg_assign(); /// assert_eq!(x, 123); /// ``` fn neg_assign(&mut self) { if self.abs != 0 { self.sign.not_assign(); } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/parity.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::Parity; impl Parity for &Integer { /// Tests whether an [`Integer`] is even. /// /// $f(x) = (2|x)$. /// /// $f(x) = (\exists k \in \N : x = 2k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Parity, Pow}; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.even(), true); /// assert_eq!(Integer::from(123).even(), false); /// assert_eq!(Integer::from(-0x80).even(), true); /// assert_eq!(Integer::from(10u32).pow(12).even(), true); /// assert_eq!((-Integer::from(10u32).pow(12) - Integer::ONE).even(), false); /// ``` fn even(self) -> bool { self.abs.even() } /// Tests whether an [`Integer`] is odd. /// /// $f(x) = (2\nmid x)$. /// /// $f(x) = (\exists k \in \N : x = 2k+1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Parity, Pow}; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.odd(), false); /// assert_eq!(Integer::from(123).odd(), true); /// assert_eq!(Integer::from(-0x80).odd(), false); /// assert_eq!(Integer::from(10u32).pow(12).odd(), false); /// assert_eq!((-Integer::from(10u32).pow(12) - Integer::ONE).odd(), true); /// ``` fn odd(self) -> bool { self.abs.odd() } } ================================================ FILE: malachite-nz/src/integer/arithmetic/pow.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::{Parity, Pow, PowAssign}; impl Pow for Integer { type Output = Self; /// Raises an [`Integer`] to a power, taking the [`Integer`] by value. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(-3).pow(100).to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// assert_eq!( /// Integer::from_str("-12345678987654321") /// .unwrap() /// .pow(3) /// .to_string(), /// "-1881676411868862234942354805142998028003108518161" /// ); /// ``` #[inline] fn pow(mut self, exp: u64) -> Self { self.pow_assign(exp); self } } impl Pow for &Integer { type Output = Integer; /// Raises an [`Integer`] to a power, taking the [`Integer`] by reference. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(-3)).pow(100).to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// assert_eq!( /// (&Integer::from_str("-12345678987654321").unwrap()) /// .pow(3) /// .to_string(), /// "-1881676411868862234942354805142998028003108518161" /// ); /// ``` #[inline] fn pow(self, exp: u64) -> Integer { Integer { sign: exp.even() || self.sign, abs: (&self.abs).pow(exp), } } } impl PowAssign for Integer { /// Raises an [`Integer`] to a power in place. /// /// $x \gets x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::PowAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(-3); /// x.pow_assign(100); /// assert_eq!( /// x.to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// /// let mut x = Integer::from_str("-12345678987654321").unwrap(); /// x.pow_assign(3); /// assert_eq!( /// x.to_string(), /// "-1881676411868862234942354805142998028003108518161" /// ); /// ``` fn pow_assign(&mut self, exp: u64) { self.sign = self.sign || exp.even(); self.abs.pow_assign(exp); } } ================================================ FILE: malachite-nz/src/integer/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; impl PowerOf2 for Integer { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::power_of_2(0), 1); /// assert_eq!(Integer::power_of_2(3), 8); /// assert_eq!( /// Integer::power_of_2(100).to_string(), /// "1267650600228229401496703205376" /// ); /// ``` #[inline] fn power_of_2(pow: u64) -> Self { Self::ONE << pow } } ================================================ FILE: malachite-nz/src/integer/arithmetic/root.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::Neg; use malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CheckedRoot, FloorRoot, FloorRootAssign, Parity, UnsignedAbs, }; impl FloorRoot for Integer { type Output = Self; /// Returns the floor of the $n$th root of an [`Integer`], taking the [`Integer`] by value. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRoot; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(999).floor_root(3), 9); /// assert_eq!(Integer::from(1000).floor_root(3), 10); /// assert_eq!(Integer::from(1001).floor_root(3), 10); /// assert_eq!(Integer::from(100000000000i64).floor_root(5), 158); /// assert_eq!(Integer::from(-100000000000i64).floor_root(5), -159); /// ``` #[inline] fn floor_root(mut self, exp: u64) -> Self { self.floor_root_assign(exp); self } } impl FloorRoot for &Integer { type Output = Integer; /// Returns the floor of the $n$th root of an [`Integer`], taking the [`Integer`] by reference. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRoot; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(999)).floor_root(3), 9); /// assert_eq!((&Integer::from(1000)).floor_root(3), 10); /// assert_eq!((&Integer::from(1001)).floor_root(3), 10); /// assert_eq!((&Integer::from(100000000000i64)).floor_root(5), 158); /// assert_eq!((&Integer::from(-100000000000i64)).floor_root(5), -159); /// ``` #[inline] fn floor_root(self, exp: u64) -> Integer { if *self >= 0 { Integer::from(self.unsigned_abs_ref().floor_root(exp)) } else if exp.odd() { -self.unsigned_abs_ref().ceiling_root(exp) } else { panic!("Cannot take even root of {self}") } } } impl FloorRootAssign for Integer { /// Replaces an [`Integer`] with the floor of its $n$th root. /// /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRootAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(999); /// x.floor_root_assign(3); /// assert_eq!(x, 9); /// /// let mut x = Integer::from(1000); /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(1001); /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(100000000000i64); /// x.floor_root_assign(5); /// assert_eq!(x, 158); /// /// let mut x = Integer::from(-100000000000i64); /// x.floor_root_assign(5); /// assert_eq!(x, -159); /// ``` #[inline] fn floor_root_assign(&mut self, exp: u64) { if *self >= 0 { self.mutate_unsigned_abs(|n| n.floor_root_assign(exp)); } else if exp.odd() { self.mutate_unsigned_abs(|n| n.ceiling_root_assign(exp)); } else { panic!("Cannot take even root of {self}") } } } impl CeilingRoot for Integer { type Output = Self; /// Returns the ceiling of the $n$th root of an [`Integer`], taking the [`Integer`] by value. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRoot; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(999).ceiling_root(3), 10); /// assert_eq!(Integer::from(1000).ceiling_root(3), 10); /// assert_eq!(Integer::from(1001).ceiling_root(3), 11); /// assert_eq!(Integer::from(100000000000i64).ceiling_root(5), 159); /// assert_eq!(Integer::from(-100000000000i64).ceiling_root(5), -158); /// ``` #[inline] fn ceiling_root(mut self, exp: u64) -> Self { self.ceiling_root_assign(exp); self } } impl CeilingRoot for &Integer { type Output = Integer; /// Returns the ceiling of the $n$th root of an [`Integer`], taking the [`Integer`] by /// reference. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRoot; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(999).ceiling_root(3), 10); /// assert_eq!(Integer::from(1000).ceiling_root(3), 10); /// assert_eq!(Integer::from(1001).ceiling_root(3), 11); /// assert_eq!(Integer::from(100000000000i64).ceiling_root(5), 159); /// assert_eq!(Integer::from(-100000000000i64).ceiling_root(5), -158); /// ``` #[inline] fn ceiling_root(self, exp: u64) -> Integer { if *self >= 0 { Integer::from(self.unsigned_abs_ref().ceiling_root(exp)) } else if exp.odd() { -self.unsigned_abs_ref().floor_root(exp) } else { panic!("Cannot take even root of {self}") } } } impl CeilingRootAssign for Integer { /// Replaces an [`Integer`] with the ceiling of its $n$th root. /// /// $x \gets \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRootAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(999); /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(1000); /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(1001); /// x.ceiling_root_assign(3); /// assert_eq!(x, 11); /// /// let mut x = Integer::from(100000000000i64); /// x.ceiling_root_assign(5); /// assert_eq!(x, 159); /// /// let mut x = Integer::from(-100000000000i64); /// x.ceiling_root_assign(5); /// assert_eq!(x, -158); /// ``` #[inline] fn ceiling_root_assign(&mut self, exp: u64) { if *self >= 0 { self.mutate_unsigned_abs(|n| n.ceiling_root_assign(exp)); } else if exp.odd() { self.mutate_unsigned_abs(|n| n.floor_root_assign(exp)); } else { panic!("Cannot take even root of {self}") } } } impl CheckedRoot for Integer { type Output = Self; /// Returns the the $n$th root of an [`Integer`], or `None` if the [`Integer`] is not a perfect /// $n$th power. The [`Integer`] is taken by value. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(999).checked_root(3).to_debug_string(), "None"); /// assert_eq!( /// Integer::from(1000).checked_root(3).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Integer::from(1001).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Integer::from(100000000000i64) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Integer::from(-100000000000i64) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Integer::from(10000000000i64) /// .checked_root(5) /// .to_debug_string(), /// "Some(100)" /// ); /// assert_eq!( /// Integer::from(-10000000000i64) /// .checked_root(5) /// .to_debug_string(), /// "Some(-100)" /// ); /// ``` #[inline] fn checked_root(self, exp: u64) -> Option { if self >= 0 { self.unsigned_abs().checked_root(exp).map(Self::from) } else if exp.odd() { self.unsigned_abs().checked_root(exp).map(Natural::neg) } else { panic!("Cannot take even root of {self}") } } } impl CheckedRoot for &Integer { type Output = Integer; /// Returns the the $n$th root of an [`Integer`], or `None` if the [`Integer`] is not a perfect /// $n$th power. The [`Integer`] is taken by reference. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(999)).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(1000)).checked_root(3).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Integer::from(1001)).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(100000000000i64)) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(-100000000000i64)) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(10000000000i64)) /// .checked_root(5) /// .to_debug_string(), /// "Some(100)" /// ); /// assert_eq!( /// (&Integer::from(-10000000000i64)) /// .checked_root(5) /// .to_debug_string(), /// "Some(-100)" /// ); /// ``` #[inline] fn checked_root(self, exp: u64) -> Option { if *self >= 0 { self.unsigned_abs_ref().checked_root(exp).map(Integer::from) } else if exp.odd() { self.unsigned_abs_ref().checked_root(exp).map(Natural::neg) } else { panic!("Cannot take even root of {self}") } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign}; use malachite_base::rounding_modes::RoundingMode; impl RoundToMultiple for Integer { type Output = Self; /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified /// rounding mode. Both [`Integer`]s are taken by value. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the original /// value. /// /// Let $q = \frac{x}{|y|}$: /// /// $f(x, y, \mathrm{Down}) = \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$ /// /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(-5) /// .round_to_multiple(Integer::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// Integer::from(-20) /// .round_to_multiple(Integer::from(3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-14) /// .round_to_multiple(Integer::from(4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(-4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(-4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(-5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// Integer::from(-20) /// .round_to_multiple(Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-14) /// .round_to_multiple(Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple<&Self> for Integer { type Output = Self; /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified /// rounding mode. The first [`Integer`] is taken by value and the second by reference. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, /// or greater than the original value. /// /// Let $q = \frac{x}{|y|}$: /// /// $f(x, y, \mathrm{Down}) = \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$ /// /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(-5) /// .round_to_multiple(&Integer::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// Integer::from(-20) /// .round_to_multiple(&Integer::from(3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-14) /// .round_to_multiple(&Integer::from(4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(-4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(-4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(-5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// Integer::from(-20) /// .round_to_multiple(&Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple(&Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(-14) /// .round_to_multiple(&Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple for &Integer { type Output = Integer; /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified /// rounding mode. The first [`Integer`] is taken by reference and the second by value. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to, /// or greater than the original value. /// /// Let $q = \frac{x}{|y|}$: /// /// $f(x, y, \mathrm{Down}) = \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$ /// /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(-5)) /// .round_to_multiple(Integer::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-20)) /// .round_to_multiple(Integer::from(3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-14)) /// .round_to_multiple(Integer::from(4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(-4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(-4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(-5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-20)) /// .round_to_multiple(Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-14)) /// .round_to_multiple(Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// ``` fn round_to_multiple(self, other: Integer, rm: RoundingMode) -> (Integer, Ordering) { let (n, o) = (&self.abs).round_to_multiple(other.abs, if self.sign { rm } else { -rm }); ( Integer::from_sign_and_abs(self.sign, n), if self.sign { o } else { o.reverse() }, ) } } impl RoundToMultiple<&Integer> for &Integer { type Output = Integer; /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified /// rounding mode. Both [`Integer`]s are taken by reference. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the original /// value. /// /// Let $q = \frac{x}{|y|}$: /// /// $f(x, y, \mathrm{Down}) = \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$ /// /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(-5)) /// .round_to_multiple(&Integer::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-20)) /// .round_to_multiple(&Integer::from(3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-14)) /// .round_to_multiple(&Integer::from(4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(-4), Down) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(-4), Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(-5), Exact) /// .to_debug_string(), /// "(-10, Equal)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-9, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-20)) /// .round_to_multiple(&Integer::from(-3), Nearest) /// .to_debug_string(), /// "(-21, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple(&Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(-14)) /// .round_to_multiple(&Integer::from(-4), Nearest) /// .to_debug_string(), /// "(-16, Less)" /// ); /// ``` fn round_to_multiple(self, other: &Integer, rm: RoundingMode) -> (Integer, Ordering) { let (n, o) = (&self.abs).round_to_multiple(&other.abs, if self.sign { rm } else { -rm }); ( Integer::from_sign_and_abs(self.sign, n), if self.sign { o } else { o.reverse() }, ) } } impl RoundToMultipleAssign for Integer { /// Rounds an [`Integer`] to a multiple of another [`Integer`] in place, according to a /// specified rounding mode. The [`Integer`] on the right-hand side is taken by value. An /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(-5); /// assert_eq!(x.round_to_multiple_assign(Integer::ZERO, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Up), Less); /// assert_eq!(x, -12); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(5), Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(Integer::from(3), Nearest), /// Greater /// ); /// assert_eq!(x, -9); /// /// let mut x = Integer::from(-20); /// assert_eq!(x.round_to_multiple_assign(Integer::from(3), Nearest), Less); /// assert_eq!(x, -21); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(Integer::from(4), Nearest), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-14); /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Nearest), Less); /// assert_eq!(x, -16); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Up), Less); /// assert_eq!(x, -12); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(Integer::from(-5), Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(Integer::from(-3), Nearest), /// Greater /// ); /// assert_eq!(x, -9); /// /// let mut x = Integer::from(-20); /// assert_eq!(x.round_to_multiple_assign(Integer::from(-3), Nearest), Less); /// assert_eq!(x, -21); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(Integer::from(-4), Nearest), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-14); /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Nearest), Less); /// assert_eq!(x, -16); /// ``` fn round_to_multiple_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { if self.sign { self.abs.round_to_multiple_assign(other.abs, rm) } else { let o = self.abs.round_to_multiple_assign(other.abs, -rm); self.sign = self.abs == 0; o.reverse() } } } impl RoundToMultipleAssign<&Self> for Integer { /// Rounds an [`Integer`] to a multiple of another [`Integer`] in place, according to a /// specified rounding mode. The [`Integer`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(-5); /// assert_eq!(x.round_to_multiple_assign(&Integer::ZERO, Down), Greater); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Down), Greater); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Up), Less); /// assert_eq!(x, -12); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(5), Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(3), Nearest), /// Greater /// ); /// assert_eq!(x, -9); /// /// let mut x = Integer::from(-20); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(3), Nearest), Less); /// assert_eq!(x, -21); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(4), Nearest), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-14); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Nearest), Less); /// assert_eq!(x, -16); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(-4), Down), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(-4), Up), Less); /// assert_eq!(x, -12); /// /// let mut x = Integer::from(-10); /// assert_eq!(x.round_to_multiple_assign(&Integer::from(-5), Exact), Equal); /// assert_eq!(x, -10); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(-3), Nearest), /// Greater /// ); /// assert_eq!(x, -9); /// /// let mut x = Integer::from(-20); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(-3), Nearest), /// Less /// ); /// assert_eq!(x, -21); /// /// let mut x = Integer::from(-10); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(-4), Nearest), /// Greater /// ); /// assert_eq!(x, -8); /// /// let mut x = Integer::from(-14); /// assert_eq!( /// x.round_to_multiple_assign(&Integer::from(-4), Nearest), /// Less /// ); /// assert_eq!(x, -16); /// ``` fn round_to_multiple_assign(&mut self, other: &Self, rm: RoundingMode) -> Ordering { if self.sign { self.abs.round_to_multiple_assign(&other.abs, rm) } else { let o = self.abs.round_to_multiple_assign(&other.abs, -rm); self.sign = self.abs == 0; o.reverse() } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{ RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::rounding_modes::RoundingMode; impl RoundToMultipleOfPowerOf2 for Integer { type Output = Self; /// Rounds an [`Integer`] to a multiple of $2^k$ according to a specified rounding mode. The /// [`Integer`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = 2^k \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = 2^k \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2(pow, Exact)` /// - `{ assert!(x.divisible_by_power_of_2(pow)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10) /// .round_to_multiple_of_power_of_2(2, Floor) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple_of_power_of_2(2, Ceiling) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// Integer::from(10) /// .round_to_multiple_of_power_of_2(2, Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Integer::from(-10) /// .round_to_multiple_of_power_of_2(2, Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// Integer::from(10) /// .round_to_multiple_of_power_of_2(2, Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Integer::from(-12) /// .round_to_multiple_of_power_of_2(2, Exact) /// .to_debug_string(), /// "(-12, Equal)" /// ); /// ``` #[inline] fn round_to_multiple_of_power_of_2(mut self, pow: u64, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_of_power_of_2_assign(pow, rm); (self, o) } } impl RoundToMultipleOfPowerOf2 for &Integer { type Output = Integer; /// Rounds an [`Integer`] to a multiple of $2^k$ according to a specified rounding mode. The /// [`Integer`] is taken by reference. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = 2^k \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = 2^k \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2(pow, Exact)` /// - `{ assert!(x.divisible_by_power_of_2(pow)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(10)) /// .round_to_multiple_of_power_of_2(2, Floor) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple_of_power_of_2(2, Ceiling) /// .to_debug_string(), /// "(-8, Greater)" /// ); /// assert_eq!( /// (&Integer::from(10)) /// .round_to_multiple_of_power_of_2(2, Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Integer::from(-10)) /// .round_to_multiple_of_power_of_2(2, Up) /// .to_debug_string(), /// "(-12, Less)" /// ); /// assert_eq!( /// (&Integer::from(10)) /// .round_to_multiple_of_power_of_2(2, Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Integer::from(-12)) /// .round_to_multiple_of_power_of_2(2, Exact) /// .to_debug_string(), /// "(-12, Equal)" /// ); /// ``` fn round_to_multiple_of_power_of_2(self, pow: u64, rm: RoundingMode) -> (Integer, Ordering) { if self.sign { let (abs, o) = (&self.abs).round_to_multiple_of_power_of_2(pow, rm); ( Integer { sign: self.sign, abs, }, o, ) } else { let (abs, o) = (&self.abs).round_to_multiple_of_power_of_2(pow, -rm); (-abs, o.reverse()) } } } impl RoundToMultipleOfPowerOf2Assign for Integer { /// Rounds an [`Integer`] to a multiple of $2^k$ in place, according to a specified rounding /// mode. An [`Ordering`] is returned, indicating whether the returned value is less than, equal /// to, or greater than the original value. /// /// See the [`RoundToMultipleOfPowerOf2`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2_assign(pow, Exact);` /// - `assert!(x.divisible_by_power_of_2(pow));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut n = Integer::from(10); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Floor), Less); /// assert_eq!(n, 8); /// /// let mut n = Integer::from(-10); /// assert_eq!( /// n.round_to_multiple_of_power_of_2_assign(2, Ceiling), /// Greater /// ); /// assert_eq!(n, -8); /// /// let mut n = Integer::from(10); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Down), Less); /// assert_eq!(n, 8); /// /// let mut n = Integer::from(-10); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Up), Less); /// assert_eq!(n, -12); /// /// let mut n = Integer::from(10); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Nearest), Less); /// assert_eq!(n, 8); /// /// let mut n = Integer::from(-12); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Exact), Equal); /// assert_eq!(n, -12); /// ``` fn round_to_multiple_of_power_of_2_assign(&mut self, pow: u64, rm: RoundingMode) -> Ordering { if self.sign { self.abs.round_to_multiple_of_power_of_2_assign(pow, rm) } else { let o = self.abs.round_to_multiple_of_power_of_2_assign(pow, -rm); if self.abs == 0 { self.sign = true; } o.reverse() } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/shl.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; fn shl_unsigned(x: Integer, bits: T) -> Integer where Natural: Shl, { Integer { sign: x.sign, abs: x.abs << bits, } } fn shl_unsigned_ref<'a, T>(x: &'a Integer, bits: T) -> Integer where &'a Natural: Shl, { Integer { sign: x.sign, abs: &x.abs << bits, } } macro_rules! impl_shl_unsigned { ($t:ident) => { impl Shl<$t> for Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Integer { shl_unsigned(self, bits) } } impl<'a> Shl<$t> for &Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies it by a power of 2), taking it by reference. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Integer { shl_unsigned_ref(self, bits) } } impl ShlAssign<$t> for Integer { /// Left-shifts an [`Integer`] (multiplies it by a power of 2), in place. /// /// $$ /// x \gets x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl_assign). #[inline] fn shl_assign(&mut self, bits: $t) { self.abs <<= bits; } } }; } apply_to_unsigneds!(impl_shl_unsigned); fn shl_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Integer, bits: S, ) -> Integer where &'a Integer: Shl + Shr, { if bits >= S::ZERO { x << bits.unsigned_abs() } else { x >> bits.unsigned_abs() } } fn shl_assign_signed + Zero>(x: &mut Integer, bits: S) where Integer: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x <<= bits.unsigned_abs(); } else { *x >>= bits.unsigned_abs(); } } macro_rules! impl_shl_signed { ($t:ident) => { impl Shl<$t> for Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies it by a power of 2 or divides it by a power /// of 2 and takes the floor), taking it by value. /// /// $$ /// f(x, k) = \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(mut self, bits: $t) -> Integer { self <<= bits; self } } impl<'a> Shl<$t> for &Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies it by a power of 2 or divides it by a power /// of 2 and takes the floor), taking it by reference. /// /// $$ /// f(x, k) = \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Integer { shl_signed_ref(self, bits) } } impl ShlAssign<$t> for Integer { /// Left-shifts an [`Integer`] (multiplies it by a power of 2 or divides it by a power /// of 2 and takes the floor), in place. /// /// $$ /// x \gets \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl#shl_assign). fn shl_assign(&mut self, bits: $t) { shl_assign_signed(self, bits) } } }; } apply_to_signeds!(impl_shl_signed); ================================================ FILE: malachite-nz/src/integer/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign}; use malachite_base::num::arithmetic::traits::{ ShlRound, ShlRoundAssign, ShrRound, ShrRoundAssign, UnsignedAbs, }; use malachite_base::num::basic::traits::Zero; use malachite_base::rounding_modes::RoundingMode; fn shl_round_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Integer, bits: S, rm: RoundingMode, ) -> (Integer, Ordering) where &'a Integer: Shl + ShrRound, { if bits >= S::ZERO { (x << bits.unsigned_abs(), Equal) } else { x.shr_round(bits.unsigned_abs(), rm) } } fn shl_round_assign_i + Zero>( x: &mut Integer, bits: S, rm: RoundingMode, ) -> Ordering where Integer: ShlAssign + ShrRoundAssign, { if bits >= S::ZERO { *x <<= bits.unsigned_abs(); Equal } else { x.shr_round_assign(bits.unsigned_abs(), rm) } } macro_rules! impl_shl_round_signed { ($t:ident) => { impl ShlRound<$t> for Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies or divides it by a power of 2), taking it by /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the exact value. If `bits` is non-negative, then the returned [`Ordering`] is /// always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only be /// necessary if `bits` is negative. /// /// Let $q = x2^k$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is negative and `rm` is `Exact` but `self` is not /// divisible by $2^{-k}$. /// /// # Examples /// See [here](super::shl_round#shl_round). #[inline] fn shl_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { let o = self.shl_round_assign(bits, rm); (self, o) } } impl<'a> ShlRound<$t> for &Integer { type Output = Integer; /// Left-shifts an [`Integer`] (multiplies or divides it by a power of 2), taking it by /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is /// also returned, indicating whether the returned value is less than, equal to, or /// greater than the exact value. If `bits` is non-negative, then the returned /// [`Ordering`] is always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only be /// necessary if `bits` is negative. /// /// Let $q = x2^k$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is negative and `rm` is `Exact` but `self` is not /// divisible by $2^{-k}$. /// /// # Examples /// See [here](super::shl_round#shl_round). #[inline] fn shl_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { shl_round_signed_ref(self, bits, rm) } } impl ShlRoundAssign<$t> for Integer { /// Left-shifts an [`Integer`] (multiplies or divides it by a power of 2) and rounds /// according to the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater than the /// exact value. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only be /// necessary if `bits` is negative. /// /// See the [`ShlRound`] documentation for details. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl_round#shl_round_assign). #[inline] fn shl_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shl_round_assign_i(self, bits, rm) } } }; } apply_to_signeds!(impl_shl_round_signed); ================================================ FILE: malachite-nz/src/integer/arithmetic/shr.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs}; use malachite_base::num::basic::traits::Zero; use malachite_base::rounding_modes::RoundingMode::*; fn shr_unsigned_ref<'a, T>(x: &'a Integer, bits: T) -> Integer where &'a Natural: Shr + ShrRound, { match *x { Integer { sign: true, ref abs, } => Integer { sign: true, abs: abs >> bits, }, Integer { sign: false, ref abs, } => { let abs_shifted = abs.shr_round(bits, Ceiling).0; if abs_shifted == 0 { Integer::ZERO } else { Integer { sign: false, abs: abs_shifted, } } } } } fn shr_assign_unsigned(x: &mut Integer, bits: T) where Natural: ShrAssign + ShrRoundAssign, { match *x { Integer { sign: true, ref mut abs, } => { *abs >>= bits; } Integer { sign: false, ref mut abs, } => { abs.shr_round_assign(bits, Ceiling); if *abs == 0 { x.sign = true; } } } } macro_rules! impl_shr_unsigned { ($t:ident) => { impl Shr<$t> for Integer { type Output = Integer; /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), taking /// it by value. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Integer { self >>= bits; self } } impl<'a> Shr<$t> for &Integer { type Output = Integer; /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), taking /// it by reference. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Integer { shr_unsigned_ref(self, bits) } } impl ShrAssign<$t> for Integer { /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), in /// place. /// /// $$ /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_assign_unsigned(self, bits); } } }; } apply_to_unsigneds!(impl_shr_unsigned); fn shr_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Integer, bits: S, ) -> Integer where &'a Integer: Shl + Shr, { if bits >= S::ZERO { x >> bits.unsigned_abs() } else { x << bits.unsigned_abs() } } fn shr_assign_signed + Zero>(x: &mut Integer, bits: S) where Integer: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x >>= bits.unsigned_abs(); } else { *x <<= bits.unsigned_abs(); } } macro_rules! impl_shr_signed { ($t:ident) => { impl Shr<$t> for Integer { type Output = Integer; /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Integer { self >>= bits; self } } impl<'a> Shr<$t> for &Integer { type Output = Integer; /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), taking it by reference. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Integer { shr_signed_ref(self, bits) } } impl ShrAssign<$t> for Integer { /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), in place. /// /// $$ /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_assign_signed(self, bits) } } }; } apply_to_signeds!(impl_shr_signed); ================================================ FILE: malachite-nz/src/integer/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign}; use malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs}; use malachite_base::num::basic::traits::Zero; use malachite_base::rounding_modes::RoundingMode; fn shr_round_unsigned_ref_i<'a, T>(x: &'a Integer, bits: T, rm: RoundingMode) -> (Integer, Ordering) where &'a Natural: ShrRound, { match *x { Integer { sign: true, ref abs, } => { let (s, o) = abs.shr_round(bits, rm); (Integer { sign: true, abs: s }, o) } Integer { sign: false, ref abs, } => { let (abs_shifted, o) = abs.shr_round(bits, -rm); ( if abs_shifted == 0 { Integer::ZERO } else { Integer { sign: false, abs: abs_shifted, } }, o.reverse(), ) } } } fn shr_round_assign_unsigned_i(x: &mut Integer, bits: T, rm: RoundingMode) -> Ordering where Natural: ShrRoundAssign, { match *x { Integer { sign: true, ref mut abs, } => abs.shr_round_assign(bits, rm), Integer { sign: false, ref mut abs, } => { let o = abs.shr_round_assign(bits, -rm); if *abs == 0 { x.sign = true; } o.reverse() } } } macro_rules! impl_shr_round_unsigned { ($t:ident) => { impl ShrRound<$t> for Integer { type Output = Integer; /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by value, and /// rounds according to the specified rounding mode. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { let o = self.shr_round_assign(bits, rm); (self, o) } } impl<'a> ShrRound<$t> for &Integer { type Output = Integer; /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by reference, /// and rounds according to the specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the exact value. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { shr_round_unsigned_ref_i(self, bits, rm) } } impl ShrRoundAssign<$t> for Integer { /// Shifts a [`Natural`] right (divides it by a power of 2) and rounds according to the /// specified rounding mode, in place. Passing `Floor` is equivalent to using `>>=`. To /// test whether `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. An /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal /// to, or greater than the exact value. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shr_round_assign_unsigned_i(self, bits, rm) } } }; } apply_to_unsigneds!(impl_shr_round_unsigned); fn shr_round_signed_ref_i<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Integer, bits: S, rm: RoundingMode, ) -> (Integer, Ordering) where &'a Integer: Shl + ShrRound, { if bits >= S::ZERO { x.shr_round(bits.unsigned_abs(), rm) } else { (x << bits.unsigned_abs(), Equal) } } fn shr_round_assign_signed_i + Zero>( x: &mut Integer, bits: S, rm: RoundingMode, ) -> Ordering where Integer: ShlAssign + ShrRoundAssign, { if bits >= S::ZERO { x.shr_round_assign(bits.unsigned_abs(), rm) } else { *x <<= bits.unsigned_abs(); Equal } } macro_rules! impl_shr_round_signed { ($t:ident) => { impl ShrRound<$t> for Integer { type Output = Integer; /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the exact value. If `bits` is negative, then the returned [`Ordering`] is /// always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { let o = self.shr_round_assign(bits, rm); (self, o) } } impl<'a> ShrRound<$t> for &Integer { type Output = Integer; /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is /// also returned, indicating whether the returned value is less than, equal to, or /// greater than the exact value. If `bits` is negative, then the returned [`Ordering`] /// is always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) { shr_round_signed_ref_i(self, bits, rm) } } impl ShrRoundAssign<$t> for Integer { /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2) and rounds /// according to the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater than the /// exact value. If `bits` is negative, then the returned [`Ordering`] is always /// `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed, /// use `self.divisible_by_power_of_2(bits)`. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shr_round_assign_signed_i(self, bits, rm) } } }; } apply_to_signeds!(impl_shr_round_signed); ================================================ FILE: malachite-nz/src/integer/arithmetic/sign.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; impl Sign for Integer { /// Compares an [`Integer`] to zero. /// /// Returns `Greater`, `Equal`, or `Less`, depending on whether the [`Integer`] is positive, /// zero, or negative, respectively. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::Sign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.sign(), Equal); /// assert_eq!(Integer::from(123).sign(), Greater); /// assert_eq!(Integer::from(-123).sign(), Less); /// ``` fn sign(&self) -> Ordering { if self.sign { if self.abs == 0 { Equal } else { Greater } } else { Less } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ CeilingSqrt, CeilingSqrtAssign, CheckedSqrt, FloorSqrt, FloorSqrtAssign, UnsignedAbs, }; impl FloorSqrt for Integer { type Output = Self; /// Returns the floor of the square root of an [`Integer`], taking it by value. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrt; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(99).floor_sqrt(), 9); /// assert_eq!(Integer::from(100).floor_sqrt(), 10); /// assert_eq!(Integer::from(101).floor_sqrt(), 10); /// assert_eq!(Integer::from(1000000000).floor_sqrt(), 31622); /// assert_eq!(Integer::from(10000000000u64).floor_sqrt(), 100000); /// ``` #[inline] fn floor_sqrt(mut self) -> Self { self.floor_sqrt_assign(); self } } impl FloorSqrt for &Integer { type Output = Integer; /// Returns the floor of the square root of an [`Integer`], taking it by reference. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrt; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::from(99)).floor_sqrt(), 9); /// assert_eq!((&Integer::from(100)).floor_sqrt(), 10); /// assert_eq!((&Integer::from(101)).floor_sqrt(), 10); /// assert_eq!((&Integer::from(1000000000)).floor_sqrt(), 31622); /// assert_eq!((&Integer::from(10000000000u64)).floor_sqrt(), 100000); /// ``` #[inline] fn floor_sqrt(self) -> Integer { if *self >= 0 { Integer::from(self.unsigned_abs_ref().floor_sqrt()) } else { panic!("Cannot take square root of {self}") } } } impl FloorSqrtAssign for Integer { /// Replaces an [`Integer`] with the floor of its square root. /// /// $x \gets \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrtAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(99); /// x.floor_sqrt_assign(); /// assert_eq!(x, 9); /// /// let mut x = Integer::from(100); /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(101); /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(1000000000); /// x.floor_sqrt_assign(); /// assert_eq!(x, 31622); /// /// let mut x = Integer::from(10000000000u64); /// x.floor_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` #[inline] fn floor_sqrt_assign(&mut self) { if *self >= 0 { self.mutate_unsigned_abs(Natural::floor_sqrt_assign); } else { panic!("Cannot take square root of {self}") } } } impl CeilingSqrt for Integer { type Output = Self; /// Returns the ceiling of the square root of an [`Integer`], taking it by value. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrt; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(99).ceiling_sqrt(), 10); /// assert_eq!(Integer::from(100).ceiling_sqrt(), 10); /// assert_eq!(Integer::from(101).ceiling_sqrt(), 11); /// assert_eq!(Integer::from(1000000000).ceiling_sqrt(), 31623); /// assert_eq!(Integer::from(10000000000u64).ceiling_sqrt(), 100000); /// ``` #[inline] fn ceiling_sqrt(mut self) -> Self { self.ceiling_sqrt_assign(); self } } impl CeilingSqrt for &Integer { type Output = Integer; /// Returns the ceiling of the square root of an [`Integer`], taking it by reference. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrt; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(99).ceiling_sqrt(), 10); /// assert_eq!(Integer::from(100).ceiling_sqrt(), 10); /// assert_eq!(Integer::from(101).ceiling_sqrt(), 11); /// assert_eq!(Integer::from(1000000000).ceiling_sqrt(), 31623); /// assert_eq!(Integer::from(10000000000u64).ceiling_sqrt(), 100000); /// ``` #[inline] fn ceiling_sqrt(self) -> Integer { if *self >= 0 { Integer::from(self.unsigned_abs_ref().ceiling_sqrt()) } else { panic!("Cannot take square root of {self}") } } } impl CeilingSqrtAssign for Integer { /// Replaces an [`Integer`] with the ceiling of its square root. /// /// $x \gets \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrtAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(99u8); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(100); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Integer::from(101); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 11); /// /// let mut x = Integer::from(1000000000); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 31623); /// /// let mut x = Integer::from(10000000000u64); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` #[inline] fn ceiling_sqrt_assign(&mut self) { if *self >= 0 { self.mutate_unsigned_abs(Natural::ceiling_sqrt_assign); } else { panic!("Cannot take square root of {self}") } } } impl CheckedSqrt for Integer { type Output = Self; /// Returns the the square root of an [`Integer`], or `None` if it is not a perfect square. The /// [`Integer`] is taken by value. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(99u8).checked_sqrt().to_debug_string(), "None"); /// assert_eq!( /// Integer::from(100u8).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Integer::from(101u8).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// Integer::from(1000000000u32) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Integer::from(10000000000u64) /// .checked_sqrt() /// .to_debug_string(), /// "Some(100000)" /// ); /// ``` #[inline] fn checked_sqrt(self) -> Option { if self >= 0 { self.unsigned_abs().checked_sqrt().map(Self::from) } else { panic!("Cannot take square root of {self}") } } } impl CheckedSqrt for &Integer { type Output = Integer; /// Returns the the square root of an [`Integer`], or `None` if it is not a perfect square. The /// [`Integer`] is taken by reference. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(99u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(100u8)).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Integer::from(101u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(1000000000u32)) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Integer::from(10000000000u64)) /// .checked_sqrt() /// .to_debug_string(), /// "Some(100000)" /// ); /// ``` #[inline] fn checked_sqrt(self) -> Option { if *self >= 0 { self.unsigned_abs_ref().checked_sqrt().map(Integer::from) } else { panic!("Cannot take square root of {self}") } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::{Square, SquareAssign}; impl Square for Integer { type Output = Self; /// Squares an [`Integer`], taking it by value. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.square(), 0); /// assert_eq!(Integer::from(123).square(), 15129); /// assert_eq!(Integer::from(-123).square(), 15129); /// ``` #[inline] fn square(mut self) -> Self { self.square_assign(); self } } impl Square for &Integer { type Output = Integer; /// Squares an [`Integer`], taking it by reference. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!((&Integer::ZERO).square(), 0); /// assert_eq!((&Integer::from(123)).square(), 15129); /// assert_eq!((&Integer::from(-123)).square(), 15129); /// ``` #[inline] fn square(self) -> Integer { Integer { sign: true, abs: (&self.abs).square(), } } } impl SquareAssign for Integer { /// Squares an [`Integer`] in place. /// /// $$ /// x \gets x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SquareAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.square_assign(); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(123); /// x.square_assign(); /// assert_eq!(x, 15129); /// /// let mut x = Integer::from(-123); /// x.square_assign(); /// assert_eq!(x, 15129); /// ``` fn square_assign(&mut self) { self.sign = true; self.abs.square_assign(); } } ================================================ FILE: malachite-nz/src/integer/arithmetic/sub.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::mem::swap; use core::ops::{Sub, SubAssign}; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::NotAssign; impl Sub for Integer { type Output = Self; /// Subtracts an [`Integer`] by another [`Integer`], taking both by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO - Integer::from(123), -123); /// assert_eq!(Integer::from(123) - Integer::ZERO, 123); /// assert_eq!(Integer::from(456) - Integer::from(-123), 579); /// assert_eq!( /// -Integer::from(10u32).pow(12) - -Integer::from(10u32).pow(12) * Integer::from(2u32), /// 1000000000000u64 /// ); /// ``` #[inline] fn sub(mut self, other: Self) -> Self { self -= other; self } } impl Sub<&Self> for Integer { type Output = Self; /// Subtracts an [`Integer`] by another [`Integer`], taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO - &Integer::from(123), -123); /// assert_eq!(Integer::from(123) - &Integer::ZERO, 123); /// assert_eq!(Integer::from(456) - &Integer::from(-123), 579); /// assert_eq!( /// -Integer::from(10u32).pow(12) - &(-Integer::from(10u32).pow(12) * Integer::from(2u32)), /// 1000000000000u64 /// ); /// ``` #[inline] fn sub(mut self, other: &Self) -> Self { self -= other; self } } impl Sub for &Integer { type Output = Integer; /// Subtracts an [`Integer`] by another [`Integer`], taking the first by reference and the /// second by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ZERO - Integer::from(123), -123); /// assert_eq!(&Integer::from(123) - Integer::ZERO, 123); /// assert_eq!(&Integer::from(456) - Integer::from(-123), 579); /// assert_eq!( /// &-Integer::from(10u32).pow(12) - -Integer::from(10u32).pow(12) * Integer::from(2u32), /// 1000000000000u64 /// ); /// ``` fn sub(self, mut other: Integer) -> Integer { other -= self; -other } } impl Sub<&Integer> for &Integer { type Output = Integer; /// Subtracts an [`Integer`] by another [`Integer`], taking both by reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::ZERO - &Integer::from(123), -123); /// assert_eq!(&Integer::from(123) - &Integer::ZERO, 123); /// assert_eq!(&Integer::from(456) - &Integer::from(-123), 579); /// assert_eq!( /// &-Integer::from(10u32).pow(12) - &(-Integer::from(10u32).pow(12) * Integer::from(2u32)), /// 1000000000000u64 /// ); /// ``` fn sub(self, other: &Integer) -> Integer { match (self, other) { (x, y) if core::ptr::eq(x, y) => Integer::ZERO, (integer_zero!(), y) => -y.clone(), (x, &integer_zero!()) => x.clone(), // e.g. 10 - -5 or -10 - 5; sign of result is sign of self ( &Integer { sign: sx, abs: ref ax, }, &Integer { sign: sy, abs: ref ay, }, ) if sx == (!sy && *ay != 0) => Integer { sign: sx, abs: ax + ay, }, // e.g. 10 - 5, -10 - -5, or 5 - 5; sign of result is sign of self ( &Integer { sign: sx, abs: ref ax, }, Integer { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => Integer { sign: sx, abs: ax - ay, }, // e.g. 5 - 10, -5 - -10, or -5 - -5; sign of result is opposite of sign of other ( Integer { abs: ax, .. }, &Integer { sign: sy, abs: ref ay, }, ) => Integer { sign: !sy, abs: ay - ax, }, } } } impl SubAssign for Integer { /// Subtracts an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x -= -Integer::from(10u32).pow(12); /// x -= Integer::from(10u32).pow(12) * Integer::from(2u32); /// x -= -Integer::from(10u32).pow(12) * Integer::from(3u32); /// x -= Integer::from(10u32).pow(12) * Integer::from(4u32); /// assert_eq!(x, -2000000000000i64); /// ``` fn sub_assign(&mut self, mut other: Self) { match (&mut *self, &other) { (_, &integer_zero!()) => {} (&mut integer_zero!(), _) => { *self = other; self.neg_assign(); } // e.g. 10 - -5 or -10 - 5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) if sx == (!sy && *ay != 0) => *ax += ay, // e.g. 10 - 5, -10 - -5, or 5 - 5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, Self { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => *ax -= ay, // e.g. 5 - 10, -5 - -10, or -5 - -5; sign of self is flipped _ => { swap(self, &mut other); self.abs -= other.abs; self.sign.not_assign(); } } } } impl SubAssign<&Self> for Integer { /// Subtracts an [`Integer`] by another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x -= &(-Integer::from(10u32).pow(12)); /// x -= &(Integer::from(10u32).pow(12) * Integer::from(2u32)); /// x -= &(-Integer::from(10u32).pow(12) * Integer::from(3u32)); /// x -= &(Integer::from(10u32).pow(12) * Integer::from(4u32)); /// assert_eq!(x, -2000000000000i64); /// ``` fn sub_assign(&mut self, other: &Self) { match (&mut *self, other) { (_, &integer_zero!()) => {} (&mut integer_zero!(), y) => *self = -y.clone(), // e.g. 10 - -5 or -10 - 5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) if sx == (!sy && *ay != 0) => *ax += ay, // e.g. 10 - 5, -10 - -5, or 5 - 5; sign of self is unchanged ( &mut Self { sign: sx, abs: ref mut ax, }, Self { abs: ay, .. }, ) if sx && *ax == *ay || *ax > *ay => *ax -= ay, ( &mut Self { sign: ref mut sx, abs: ref mut ax, }, &Self { sign: sy, abs: ref ay, }, ) => { *sx = !sy; *ax = ay - &*ax; } } } } ================================================ FILE: malachite-nz/src/integer/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2001, 2004, 2005, 2012 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::mul::limb::{ limbs_mul_limb_with_carry_to_out, limbs_slice_mul_limb_with_carry_in_place, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::sub::{ limbs_slice_sub_in_place_right, limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_limb_to_out, }; use crate::natural::arithmetic::sub_mul::{ limbs_sub_mul_limb_same_length_in_place_left, limbs_sub_mul_limb_same_length_in_place_right, }; use crate::natural::comparison::cmp::limbs_cmp; use crate::natural::logic::not::limbs_not_in_place; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ AddMul, AddMulAssign, NegAssign, SubMul, SubMulAssign, WrappingAddAssign, WrappingSubAssign, }; use malachite_base::slices::slice_test_zero; // Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, returning the // limbs of the absolute value and the sign (true means non-negative). `xs` and `ys` should be // nonempty and have no trailing zeros, and `z` should be nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, and `w` is returned instead of overwriting the first input. `w_sign` // is also returned. pub_crate_test! {limbs_overflowing_sub_mul_limb( xs: &[Limb], ys: &[Limb], z: Limb ) -> (Vec, bool) { let mut result; let sign = if xs.len() >= ys.len() { result = xs.to_vec(); limbs_overflowing_sub_mul_limb_greater_in_place_left(&mut result, ys, z) } else { result = ys.to_vec(); limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, &mut result, z) }; (result, sign) }} // Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the // limbs of the absolute value to the first (left) slice and returning the sign (true means non- // negative). `xs` and `ys` should be nonempty and have no trailing zeros, and `z` should be // nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, and `w_sign` is returned. pub_crate_test! {limbs_overflowing_sub_mul_limb_in_place_left( xs: &mut Vec, ys: &[Limb], z: Limb, ) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { limbs_overflowing_sub_mul_limb_greater_in_place_left(xs, ys, z) } else { let (ys_lo, ys_hi) = ys.split_at(xs_len); // submul of absolute values let mut borrow = limbs_sub_mul_limb_same_length_in_place_left(xs, ys_lo, z); // ys bigger than xs, so want ys * limb - xs. Submul has given xs - ys * limb, so take twos' // complement and use an limbs_mul_limb_with_carry_to_out for the rest. -(-borrow * b ^ n + // xs - ys * limb) = (borrow - 1) * b ^ n + ~(xs - ys * limb) + 1 limbs_not_in_place(xs); if !limbs_slice_add_limb_in_place(xs, 1) { borrow.wrapping_sub_assign(1); } // If borrow - 1 == -1, then hold that -1 for later. // limbs_sub_mul_limb_same_length_in_place_left never returns borrow == Limb::MAX, so that // value always indicates a -1. let negative_one = borrow == Limb::MAX; if negative_one { borrow.wrapping_add_assign(1); } xs.resize(ys_len + 1, 0); let xs_hi = &mut xs[xs_len..]; let (xs_hi_last, xs_hi_init) = xs_hi.split_last_mut().unwrap(); *xs_hi_last = limbs_mul_limb_with_carry_to_out::(xs_hi_init, ys_hi, z, borrow); // Apply any -1 from above. The value at xs_hi is non-zero because z != 0 and the high limb // of ys will be non-zero. if negative_one { assert!(!limbs_sub_limb_in_place(xs_hi, 1)); } false } }} // xs.len() >= ys.len() fn limbs_overflowing_sub_mul_limb_greater_in_place_left( xs: &mut Vec, ys: &[Limb], z: Limb, ) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); xs.push(0); // submul of absolute values let (xs_lo, xs_hi) = xs.split_at_mut(ys_len); let mut borrow = limbs_sub_mul_limb_same_length_in_place_left(xs_lo, ys, z); // If xs bigger than ys, then propagate borrow through it. if xs_len != ys_len { borrow = Limb::from(limbs_sub_limb_in_place(xs_hi, borrow)); } if borrow == 0 { true } else { // Borrow out of xs, take twos' complement negative to get absolute value, flip sign of xs. let (xs_last, xs_init) = xs.split_last_mut().unwrap(); *xs_last = borrow.wrapping_sub(1); limbs_not_in_place(xs_init); limbs_slice_add_limb_in_place(xs, 1); false } } // Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the // limbs of the absolute value to the second (right) slice and returning the sign (true means non- // negative). `xs` and `ys` should be nonempty and have no trailing zeros, and `z` should be // nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, the limbs of the result are written to the second input rather than // the first, and `w_sign` is returned. pub_test! {limbs_overflowing_sub_mul_limb_in_place_right( xs: &[Limb], ys: &mut Vec, z: Limb, ) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { ys.resize(xs_len + 1, 0); // submul of absolute values let (xs_lo, xs_hi) = xs.split_at(ys_len); let (ys_lo, ys_hi) = ys.split_at_mut(ys_len); let mut borrow = limbs_sub_mul_limb_same_length_in_place_right(xs_lo, ys_lo, z); // If xs bigger than ys, then propagate borrow through it. if xs_len != ys_len { borrow = Limb::from(limbs_sub_limb_to_out(ys_hi, xs_hi, borrow)); } if borrow == 0 { true } else { // Borrow out of ys, take twos' complement negative to get absolute value, flip sign of // ys. let (ys_last, ys_init) = ys.split_last_mut().unwrap(); *ys_last = borrow.wrapping_sub(1); limbs_not_in_place(ys_init); limbs_slice_add_limb_in_place(ys, 1); false } } else { limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, ys, z) } }} // xs.len() < ys.len() fn limbs_overflowing_sub_mul_limb_smaller_in_place_right( xs: &[Limb], ys: &mut Vec, z: Limb, ) -> bool { ys.push(0); let (ys_lo, ys_hi) = ys.split_at_mut(xs.len()); // submul of absolute values let mut borrow = limbs_sub_mul_limb_same_length_in_place_right(xs, ys_lo, z); // ys bigger than xs, so want ys * z - xs. Submul has given xs - ys * z, so take twos' // complement and use an limbs_mul_limb_with_carry_to_out for the rest. -(-borrow * b ^ n + xs // - ys * z) = (borrow - 1) * b ^ n + ~(xs - ys * z) + 1 limbs_not_in_place(ys_lo); if !limbs_slice_add_limb_in_place(ys_lo, 1) { borrow.wrapping_sub_assign(1); } // If borrow - 1 == -1, then hold that -1 for later. // limbs_sub_mul_limb_same_length_in_place_left never returns borrow == Limb::MAX, so that value // always indicates a -1. let negative_one = borrow == Limb::MAX; if negative_one { borrow.wrapping_add_assign(1); } let (ys_hi_last, ys_hi_init) = ys_hi.split_last_mut().unwrap(); *ys_hi_last = limbs_slice_mul_limb_with_carry_in_place(ys_hi_init, z, borrow); if negative_one { assert!(!limbs_sub_limb_in_place(ys_hi, 1)); } false } // Given the limbs of two `Natural`s x and y, and a limb `z`, calculates x - y * z, writing the // limbs of the absolute value to whichever input is longer. The first `bool` returned is `false` if // the result is written to the first input, and `true` if it is written to the second. The second // `bool` is the sign of the result (true means non-negative). `xs` and `ys` should be nonempty and // have no trailing zeros, and `z` should be nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, the result is written to the longer input, and `w_sign` is returned. pub_crate_test! {limbs_overflowing_sub_mul_limb_in_place_either( xs: &mut Vec, ys: &mut Vec, z: Limb, ) -> (bool, bool) { if xs.len() >= ys.len() { ( false, limbs_overflowing_sub_mul_limb_greater_in_place_left(xs, ys, z), ) } else { ( true, limbs_overflowing_sub_mul_limb_smaller_in_place_right(xs, ys, z), ) } }} // Given the limbs of three `Natural`s x, y, and z, calculates x - y * z, returning the limbs of the // absolute value and the sign (true means non-negative). All of the input slices should be // non-empty and have no trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n, m) = O(m + n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` are empty. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive, `sub` is negative, and `w` is returned instead of overwriting the first input. `w_sign` // is also returned. pub_crate_test! {limbs_overflowing_sub_mul( xs: &[Limb], ys: &[Limb], zs: &[Limb] ) -> (Vec, bool) { let mut xs = xs.to_vec(); let sign = limbs_overflowing_sub_mul_in_place_left(&mut xs, ys, zs); (xs, sign) }} // Given the limbs of three `Natural`s x, y, and z, calculates x - y * z, writing the limbs of the // absolute value to the first (left) slice and returning the sign (true means non-negative). All of // the input slices should be non-empty and have no trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n, m) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` are empty. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive, `sub` is negative, and `w_sign` is returned. pub_crate_test! {limbs_overflowing_sub_mul_in_place_left( xs: &mut Vec, ys: &[Limb], zs: &[Limb], ) -> bool { if ys.len() >= zs.len() { limbs_overflowing_sub_mul_greater_in_place_left(xs, ys, zs) } else { limbs_overflowing_sub_mul_greater_in_place_left(xs, zs, ys) } }} // zs.len() >= ys.len() fn limbs_overflowing_sub_mul_greater_in_place_left( xs: &mut Vec, ys: &[Limb], zs: &[Limb], ) -> bool { let xs_len = xs.len(); let product_len = ys.len() + zs.len(); let mut product = vec![0; product_len]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ys.len(), zs.len())]; if limbs_mul_greater_to_out(&mut product, ys, zs, &mut mul_scratch) == 0 { product.pop(); } assert_ne!(*product.last().unwrap(), 0); if limbs_cmp(xs, &product) == Less { if xs_len < product_len { xs.resize(product.len(), 0); } assert!(!limbs_slice_sub_in_place_right( &product, &mut xs[..product.len()], xs_len, )); false } else { assert!(!limbs_sub_greater_in_place_left(xs, &product)); !slice_test_zero(xs) } } impl SubMul for Integer { type Output = Self; /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking all three by /// value. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).sub_mul(Integer::from(3u32), Integer::from(-4)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .sub_mul(Integer::from(-0x10000), -Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn sub_mul(mut self, y: Self, z: Self) -> Self { self.sub_mul_assign(y, z); self } } impl<'a> SubMul for Integer { type Output = Self; /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first two by /// value and the third by reference. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).sub_mul(Integer::from(3u32), &Integer::from(-4)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .sub_mul(Integer::from(-0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn sub_mul(mut self, y: Self, z: &'a Self) -> Self { self.sub_mul_assign(y, z); self } } impl<'a> SubMul<&'a Self, Self> for Integer { type Output = Self; /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first and /// third by value and the second by reference. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).sub_mul(&Integer::from(3u32), Integer::from(-4)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .sub_mul(&Integer::from(-0x10000), -Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn sub_mul(mut self, y: &'a Self, z: Self) -> Self { self.sub_mul_assign(y, z); self } } impl SubMul<&Self, &Self> for Integer { type Output = Self; /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking the first by value /// and the second and third by reference. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(10u32).sub_mul(&Integer::from(3u32), &Integer::from(-4)), /// 22 /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .sub_mul(&Integer::from(-0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` #[inline] fn sub_mul(mut self, y: &Self, z: &Self) -> Self { self.sub_mul_assign(y, z); self } } impl SubMul<&Integer, &Integer> for &Integer { type Output = Integer; /// Subtracts an [`Integer`] by the product of two other [`Integer`]s, taking all three by /// reference. /// /// $f(x, y, z) = x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n, m) = O(m + n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (&Integer::from(10u32)).sub_mul(&Integer::from(3u32), &Integer::from(-4)), /// 22 /// ); /// assert_eq!( /// (&-Integer::from(10u32).pow(12)) /// .sub_mul(&Integer::from(-0x10000), &-Integer::from(10u32).pow(12)), /// -65537000000000000i64 /// ); /// ``` fn sub_mul(self, y: &Integer, z: &Integer) -> Integer { if self.sign == (y.sign != z.sign) { Integer { sign: self.sign, abs: (&self.abs).add_mul(&y.abs, &z.abs), } } else { let (abs, abs_result_sign) = self.abs.add_mul_neg(&y.abs, &z.abs); Integer { sign: (self.sign == abs_result_sign) || abs == 0, abs, } } } } impl SubMulAssign for Integer { /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking both /// [`Integer`]s on the right-hand side by value. /// /// $x \gets x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.sub_mul_assign(Integer::from(3u32), Integer::from(-4)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.sub_mul_assign(Integer::from(-0x10000), -Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn sub_mul_assign(&mut self, y: Self, z: Self) { self.add_mul_assign(-y, z); } } impl<'a> SubMulAssign for Integer { /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking the /// first [`Integer`] on the right-hand side by value and the second by reference. /// /// $x \gets x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.sub_mul_assign(Integer::from(3u32), &Integer::from(-4)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.sub_mul_assign(Integer::from(-0x10000), &(-Integer::from(10u32).pow(12))); /// assert_eq!(x, -65537000000000000i64); /// ``` fn sub_mul_assign(&mut self, y: Self, z: &'a Self) { self.add_mul_assign(-y, z); } } impl<'a> SubMulAssign<&'a Self, Self> for Integer { /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking the /// first [`Integer`] on the right-hand side by reference and the second by value. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.sub_mul_assign(&Integer::from(3u32), Integer::from(-4)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.sub_mul_assign(&Integer::from(-0x10000), -Integer::from(10u32).pow(12)); /// assert_eq!(x, -65537000000000000i64); /// ``` fn sub_mul_assign(&mut self, y: &'a Self, z: Self) { self.add_mul_assign(y, -z); } } impl<'a, 'b> SubMulAssign<&'a Self, &'b Self> for Integer { /// Subtracts the product of two other [`Integer`]s from an [`Integer`] in place, taking both /// [`Integer`]s on the right-hand side by reference. /// /// $x \gets x - yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(10u32); /// x.sub_mul_assign(&Integer::from(3u32), &Integer::from(-4)); /// assert_eq!(x, 22); /// /// let mut x = -Integer::from(10u32).pow(12); /// x.sub_mul_assign(&Integer::from(-0x10000), &(-Integer::from(10u32).pow(12))); /// assert_eq!(x, -65537000000000000i64); /// ``` fn sub_mul_assign(&mut self, y: &'a Self, z: &'b Self) { self.neg_assign(); self.add_mul_assign(y, z); self.neg_assign(); } } ================================================ FILE: malachite-nz/src/integer/comparison/cmp.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering::{self, *}; impl PartialOrd for Integer { /// Compares two [`Integer`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Integer { /// Compares two [`Integer`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-123) < Integer::from(-122)); /// assert!(Integer::from(-123) <= Integer::from(-122)); /// assert!(Integer::from(-123) > Integer::from(-124)); /// assert!(Integer::from(-123) >= Integer::from(-124)); /// ``` fn cmp(&self, other: &Self) -> Ordering { if core::ptr::eq(self, other) { Equal } else { match (self.sign, other.sign) { (true, false) => Greater, (false, true) => Less, (true, true) => self.abs.cmp(&other.abs), (false, false) => other.abs.cmp(&self.abs), } } } } ================================================ FILE: malachite-nz/src/integer/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; impl PartialOrdAbs for Integer { /// Compares the absolute values of two [`Integer`]s. /// /// See the documentation for the [`OrdAbs`] implementation. #[inline] fn partial_cmp_abs(&self, other: &Self) -> Option { Some(self.cmp_abs(other)) } } impl OrdAbs for Integer { /// Compares the absolute values of two [`Integer`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-123).lt_abs(&Integer::from(-124))); /// assert!(Integer::from(-123).le_abs(&Integer::from(-124))); /// assert!(Integer::from(-124).gt_abs(&Integer::from(-123))); /// assert!(Integer::from(-124).ge_abs(&Integer::from(-123))); /// ``` fn cmp_abs(&self, other: &Self) -> Ordering { self.abs.cmp(&other.abs) } } ================================================ FILE: malachite-nz/src/integer/comparison/cmp_abs_natural.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::cmp::Ordering; use malachite_base::num::comparison::traits::PartialOrdAbs; impl PartialOrdAbs for Integer { /// Compares the absolute values of an [`Integer`] and a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Integer::from(123).gt_abs(&Natural::from(122u32))); /// assert!(Integer::from(123).ge_abs(&Natural::from(122u32))); /// assert!(Integer::from(123).lt_abs(&Natural::from(124u32))); /// assert!(Integer::from(123).le_abs(&Natural::from(124u32))); /// assert!(Integer::from(-124).gt_abs(&Natural::from(123u32))); /// assert!(Integer::from(-124).ge_abs(&Natural::from(123u32))); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Natural) -> Option { self.abs.partial_cmp(other) } } impl PartialOrdAbs for Natural { /// Compares the absolute values of a [`Natural`] and an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32).gt_abs(&Integer::from(122))); /// assert!(Natural::from(123u32).ge_abs(&Integer::from(122))); /// assert!(Natural::from(123u32).lt_abs(&Integer::from(124))); /// assert!(Natural::from(123u32).le_abs(&Integer::from(124))); /// assert!(Natural::from(123u32).lt_abs(&Integer::from(-124))); /// assert!(Natural::from(123u32).le_abs(&Integer::from(-124))); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Integer) -> Option { self.partial_cmp(&other.abs) } } ================================================ FILE: malachite-nz/src/integer/comparison/cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::comparison::traits::PartialOrdAbs; macro_rules! impl_float { ($t: ident) => { impl PartialOrdAbs<$t> for Integer { /// Compares the absolute values of an [`Integer`] and a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::cmp_abs_primitive_float#partial_cmp_abs). fn partial_cmp_abs(&self, other: &$t) -> Option { self.unsigned_abs().partial_cmp(&other.abs()) } } impl PartialOrdAbs for $t { /// Compares the absolute values of a primitive float and an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::cmp_abs_primitive_float#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Integer) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/integer/comparison/cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::comparison::traits::PartialOrdAbs; macro_rules! impl_unsigned { ($t: ident) => { impl PartialOrdAbs<$t> for Integer { /// Compares the absolute values of an [`Integer`] and an unsigned primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { self.abs.partial_cmp(other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of an unsigned primitive integer and an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Integer) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl PartialOrdAbs<$t> for Integer { /// Compares the absolute values of an [`Integer`] and a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::cmp_abs_primitive_int#partial_cmp_abs). fn partial_cmp_abs(&self, other: &$t) -> Option { self.abs.partial_cmp(&other.unsigned_abs()) } } impl PartialOrdAbs for $t { /// Compares the absolute values of a signed primitive integer and an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Integer) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/integer/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::comparison::traits::EqAbs; impl EqAbs for Integer { /// Determines whether the absolute values of two [`Integer`]s are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123).eq_abs(&Integer::from(-122)), false); /// assert_eq!(Integer::from(-123).eq_abs(&Integer::from(-124)), false); /// assert_eq!(Integer::from(123).eq_abs(&Integer::from(123)), true); /// assert_eq!(Integer::from(123).eq_abs(&Integer::from(-123)), true); /// assert_eq!(Integer::from(-123).eq_abs(&Integer::from(123)), true); /// assert_eq!(Integer::from(-123).eq_abs(&Integer::from(-123)), true); /// ``` #[inline] fn eq_abs(&self, other: &Self) -> bool { self.abs == other.abs } } ================================================ FILE: malachite-nz/src/integer/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::comparison::traits::EqAbs; impl EqAbs for Integer { /// Determines whether the absolute values of an [`Integer`] and a [`Natural`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Integer::from(-123).eq_abs(&Natural::from(122u32)), false); /// assert_eq!(Integer::from(-123).eq_abs(&Natural::from(124u32)), false); /// assert_eq!(Integer::from(123).eq_abs(&Natural::from(123u32)), true); /// assert_eq!(Integer::from(-123).eq_abs(&Natural::from(123u32)), true); /// ``` #[inline] fn eq_abs(&self, other: &Natural) -> bool { self.abs == *other } } impl EqAbs for Natural { /// Determines whether the absolute values of an [`Integer`] and a [`Natural`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(122u32).eq_abs(&Integer::from(-123)), false); /// assert_eq!(Natural::from(124u32).eq_abs(&Integer::from(-123)), false); /// assert_eq!(Natural::from(123u32).eq_abs(&Integer::from(123)), true); /// assert_eq!(Natural::from(123u32).eq_abs(&Integer::from(-123)), true); /// ``` #[inline] fn eq_abs(&self, other: &Integer) -> bool { *self == other.abs } } ================================================ FILE: malachite-nz/src/integer/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::comparison::traits::EqAbs; macro_rules! impl_eq_abs { ($t: ident) => { impl EqAbs<$t> for Integer { /// Determines whether the absolute values of an [`Integer`] and a primitive float are /// equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { *self.unsigned_abs_ref() == other.abs() } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive float and an [`Integer`] are /// equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &Integer) -> bool { self.abs() == *other.unsigned_abs_ref() } } }; } apply_to_primitive_floats!(impl_eq_abs); ================================================ FILE: malachite-nz/src/integer/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::comparison::traits::EqAbs; macro_rules! impl_unsigned { ($t: ident) => { impl EqAbs<$t> for Integer { /// Determines whether the absolute values of an [`Integer`] and a primitive unsigned /// integer are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { self.unsigned_abs_ref() == other } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive unsigned integer and an /// [`Integer`] are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Integer) -> bool { self == other.unsigned_abs_ref() } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl EqAbs<$t> for Integer { /// Determines whether the absolute values of an [`Integer`] and a primitive signed /// integer are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { *self.unsigned_abs_ref() == other.unsigned_abs() } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive signed integer and an /// [`Integer`] are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Integer) -> bool { self.unsigned_abs() == *other.unsigned_abs_ref() } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/integer/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// Comparison of [`Integer`](crate::integer::Integer)s. pub mod cmp; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// and [`OrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) (traits for comparing /// the absolute values of numbers by order) for [`Integer`](crate::integer::Integer)s. pub mod cmp_abs; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Integer`](crate::integer::Integer)s and [`Natural`](crate::natural::Natural)s. pub mod cmp_abs_natural; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Integer`](crate::integer::Integer)s and primitive floats. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-123).gt_abs(&-122.5f32)); /// assert!(Integer::from(123).lt_abs(&f32::NEGATIVE_INFINITY)); /// /// assert!((-122.5f32).lt_abs(&Integer::from(-123))); /// assert!(f32::NEGATIVE_INFINITY.gt_abs(&Integer::from(123))); /// ``` pub mod cmp_abs_primitive_float; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Integer`](crate::integer::Integer)s and primitive integers. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-122).lt_abs(&123u64)); /// assert!(Integer::from(-122).le_abs(&123u64)); /// assert!(Integer::from(-123).lt_abs(&124u64)); /// assert!(Integer::from(-123).le_abs(&124u64)); /// assert!(Integer::from(10u32).pow(12).gt_abs(&123u64)); /// assert!(Integer::from(10u32).pow(12).ge_abs(&123u64)); /// assert!((-Integer::from(10u32).pow(12)).gt_abs(&123u64)); /// assert!((-Integer::from(10u32).pow(12)).ge_abs(&123u64)); /// /// assert!(Integer::from(-122).lt_abs(&-123i64)); /// assert!(Integer::from(-122).le_abs(&-123i64)); /// assert!(Integer::from(-124).gt_abs(&-123i64)); /// assert!(Integer::from(-124).ge_abs(&-123i64)); /// assert!(Integer::from(10u32).pow(12).gt_abs(&123i64)); /// assert!(Integer::from(10u32).pow(12).ge_abs(&123i64)); /// assert!((-Integer::from(10u32).pow(12)).gt_abs(&123i64)); /// assert!((-Integer::from(10u32).pow(12)).ge_abs(&123i64)); /// /// assert!(123u64.gt_abs(&Integer::from(-122))); /// assert!(123u64.ge_abs(&Integer::from(-122))); /// assert!(124u64.gt_abs(&Integer::from(-123))); /// assert!(124u64.ge_abs(&Integer::from(-123))); /// assert!(123u64.lt_abs(&Integer::from(10u32).pow(12))); /// assert!(123u64.le_abs(&Integer::from(10u32).pow(12))); /// assert!(123u64.lt_abs(&-Integer::from(10u32).pow(12))); /// assert!(123u64.le_abs(&-Integer::from(10u32).pow(12))); /// /// assert!((-123i64).gt_abs(&Integer::from(-122))); /// assert!((-123i64).ge_abs(&Integer::from(-122))); /// assert!((-123i64).lt_abs(&Integer::from(-124))); /// assert!((-123i64).le_abs(&Integer::from(-124))); /// assert!(123i64.lt_abs(&Integer::from(10u32).pow(12))); /// assert!(123i64.le_abs(&Integer::from(10u32).pow(12))); /// assert!(123i64.lt_abs(&-Integer::from(10u32).pow(12))); /// assert!(123i64.le_abs(&-Integer::from(10u32).pow(12))); /// ``` pub mod cmp_abs_primitive_int; /// Equality of the absolute values of two [`Integer`](crate::integer::Integer)s. pub mod eq_abs; /// Equality of the absolute values of an [`Integer`](crate::integer::Integer) and a /// [`Natural`](crate::integer::Natural). pub mod eq_abs_natural; /// Equality of the absolute values of an [`Integer`](crate::integer::Integer) and a primitive /// float. /// /// # eq_abs /// ``` /// use malachite_base::num::basic::traits::{NegativeInfinity, Zero}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123).eq_abs(&123.0), true); /// assert_eq!(Integer::from(123).eq_abs(&5.0), false); /// assert_eq!(Integer::from(123).eq_abs(&-123.0), true); /// assert_eq!(Integer::from(123).eq_abs(&-5.0), false); /// assert_eq!(Integer::from(-123).eq_abs(&123.0), true); /// assert_eq!(Integer::from(-123).eq_abs(&5.0), false); /// assert_eq!(Integer::from(-123).eq_abs(&-123.0), true); /// assert_eq!(Integer::from(-123).eq_abs(&-5.0), false); /// assert_eq!(Integer::ZERO.eq_abs(&0.0), true); /// assert_eq!(Integer::ZERO.eq_abs(&-0.0), true); /// assert_eq!(Integer::ZERO.eq_abs(&f64::NAN), false); /// assert_eq!(Integer::ZERO.eq_abs(&f64::INFINITY), false); /// assert_eq!(Integer::ZERO.eq_abs(&f64::NEGATIVE_INFINITY), false); /// /// assert_eq!(123.0.eq_abs(&Integer::from(123)), true); /// assert_eq!(5.0.eq_abs(&Integer::from(123)), false); /// assert_eq!((-123.0).eq_abs(&Integer::from(123)), true); /// assert_eq!((-5.0).eq_abs(&Integer::from(123)), false); /// assert_eq!(123.0.eq_abs(&Integer::from(-123)), true); /// assert_eq!(5.0.eq_abs(&Integer::from(-123)), false); /// assert_eq!((-123.0).eq_abs(&Integer::from(-123)), true); /// assert_eq!((-5.0).eq_abs(&Integer::from(-123)), false); /// assert_eq!(0.0.eq_abs(&Integer::ZERO), true); /// assert_eq!((-0.0).eq_abs(&Integer::ZERO), true); /// assert_eq!(f64::NAN.eq_abs(&Integer::ZERO), false); /// assert_eq!(f64::INFINITY.eq_abs(&Integer::ZERO), false); /// assert_eq!(f64::NEGATIVE_INFINITY.eq_abs(&Integer::ZERO), false); /// ``` pub mod eq_abs_primitive_float; /// Equality of the absolute values of an [`Integer`](crate::integer::Integer) and a primitive /// integer. /// /// # eq_abs /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123).eq_abs(&123u32), true); /// assert_eq!(Integer::from(-123).eq_abs(&123u32), true); /// assert_eq!(Integer::from(123).eq_abs(&5u32), false); /// assert_eq!(Integer::from(-123).eq_abs(&5u32), false); /// /// assert_eq!(Integer::from(123).eq_abs(&123u64), true); /// assert_eq!(Integer::from(-123).eq_abs(&123u64), true); /// assert_eq!(Integer::from(123).eq_abs(&5u64), false); /// assert_eq!(Integer::from(-123).eq_abs(&5u64), false); /// /// assert_eq!(Integer::from(123).eq_abs(&123i64), true); /// assert_eq!(Integer::from(-123).eq_abs(&123i64), true); /// assert_eq!(Integer::from(123).eq_abs(&-123i64), true); /// assert_eq!(Integer::from(-123).eq_abs(&-123i64), true); /// /// assert_eq!(123u8.eq_abs(&Integer::from(123)), true); /// assert_eq!(123u8.eq_abs(&Integer::from(-123)), true); /// assert_eq!(5u8.eq_abs(&Integer::from(123)), false); /// assert_eq!(5u8.eq_abs(&Integer::from(-123)), false); /// /// assert_eq!(123u64.eq_abs(&Integer::from(123)), true); /// assert_eq!(123u64.eq_abs(&Integer::from(-123)), true); /// assert_eq!(5u64.eq_abs(&Integer::from(123)), false); /// assert_eq!(5u64.eq_abs(&Integer::from(-123)), false); /// /// assert_eq!(123i64.eq_abs(&Integer::from(123)), true); /// assert_eq!(123i64.eq_abs(&Integer::from(-123)), true); /// assert_eq!((-123i64).eq_abs(&Integer::from(123)), true); /// assert_eq!((-123i64).eq_abs(&Integer::from(-123)), true); /// ``` pub mod eq_abs_primitive_int; /// Comparison of [`Integer`](crate::integer::Integer)s and [`Natural`](crate::natural::Natural)s. pub mod partial_cmp_natural; /// Comparison of [`Integer`](crate::integer::Integer)s and primitive floats. /// /// # partial_cmp /// ``` /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-123) < -122.5f32); /// assert!(Integer::from(123) < f32::INFINITY); /// assert!(-122.5f32 > Integer::from(-123)); /// assert!(f32::INFINITY > Integer::from(123)); /// ``` pub mod partial_cmp_primitive_float; /// Comparison of [`Integer`](crate::integer::Integer)s and primitive integers. /// /// # partial_cmp /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(-123) < 122u64); /// assert!(Integer::from(-123) <= 122u64); /// assert!(Integer::from(-123) < 124u64); /// assert!(Integer::from(-123) <= 124u64); /// assert!(Integer::from(10u32).pow(12) > 123u64); /// assert!(Integer::from(10u32).pow(12) >= 123u64); /// assert!(-Integer::from(10u32).pow(12) < 123u64); /// assert!(-Integer::from(10u32).pow(12) <= 123u64); /// /// assert!(Integer::from(-123) < -122i64); /// assert!(Integer::from(-123) <= -122i64); /// assert!(Integer::from(-123) > -124i64); /// assert!(Integer::from(-123) >= -124i64); /// assert!(Integer::from(10u32).pow(12) > 123i64); /// assert!(Integer::from(10u32).pow(12) >= 123i64); /// assert!(-Integer::from(10u32).pow(12) < 123i64); /// assert!(-Integer::from(10u32).pow(12) <= 123i64); /// /// assert!(122u64 > Integer::from(-123)); /// assert!(122u64 >= Integer::from(-123)); /// assert!(124u64 > Integer::from(-123)); /// assert!(124u64 >= Integer::from(-123)); /// assert!(123u64 < Integer::from(10u32).pow(12)); /// assert!(123u64 <= Integer::from(10u32).pow(12)); /// assert!(123u64 > -Integer::from(10u32).pow(12)); /// assert!(123u64 >= -Integer::from(10u32).pow(12)); /// /// assert!(-122i64 > Integer::from(-123)); /// assert!(-122i64 >= Integer::from(-123)); /// assert!(-124i64 < Integer::from(-123)); /// assert!(-124i64 <= Integer::from(-123)); /// assert!(123i64 < Integer::from(10u32).pow(12)); /// assert!(123i64 <= Integer::from(10u32).pow(12)); /// assert!(123i64 > -Integer::from(10u32).pow(12)); /// assert!(123i64 >= -Integer::from(10u32).pow(12)); /// ``` pub mod partial_cmp_primitive_int; /// Equality of [`Integer`](crate::integer::Integer)s and [`Natural`](crate::natural::Natural)s. pub mod partial_eq_natural; /// Equality of [`Integer`](crate::integer::Integer)s and primitive floats. /// /// # partial_eq /// ``` /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(123u32) == 123.0f32); /// assert!(Integer::from(123u32) != -5.0f32); /// /// assert!(123.0f32 == Integer::from(123u32)); /// assert!(-5.0f32 != Integer::from(123u32)); /// ``` pub mod partial_eq_primitive_float; /// Equality of [`Integer`](crate::integer::Integer)s and primitive integers. /// /// # partial_eq /// ``` /// use malachite_nz::integer::Integer; /// /// assert!(Integer::from(123) == 123u64); /// assert!(Integer::from(-123) != 123u64); /// /// assert!(123u64 == Integer::from(123)); /// assert!(123u64 != Integer::from(-123)); /// /// assert!(123u64 == Integer::from(123)); /// assert!(123u64 != Integer::from(-123)); /// /// assert!(23i64 != Integer::from(123)); /// assert!(-123i64 == Integer::from(-123)); /// ``` pub mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/integer/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::cmp::Ordering::{self, *}; impl PartialOrd for Integer { /// Compares an [`Integer`] to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `min(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Integer::from(123) > Natural::from(122u32)); /// assert!(Integer::from(123) >= Natural::from(122u32)); /// assert!(Integer::from(123) < Natural::from(124u32)); /// assert!(Integer::from(123) <= Natural::from(124u32)); /// assert!(Integer::from(-123) < Natural::from(123u32)); /// assert!(Integer::from(-123) <= Natural::from(123u32)); /// ``` fn partial_cmp(&self, other: &Natural) -> Option { if self.sign { self.abs.partial_cmp(other) } else { Some(Less) } } } impl PartialOrd for Natural { /// Compares a [`Natural`] to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `min(self.significant_bits(), other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) > Integer::from(122)); /// assert!(Natural::from(123u32) >= Integer::from(122)); /// assert!(Natural::from(123u32) < Integer::from(124)); /// assert!(Natural::from(123u32) <= Integer::from(124)); /// assert!(Natural::from(123u32) > Integer::from(-123)); /// assert!(Natural::from(123u32) >= Integer::from(-123)); /// ``` fn partial_cmp(&self, other: &Integer) -> Option { if other.sign { self.partial_cmp(&other.abs) } else { Some(Greater) } } } ================================================ FILE: malachite-nz/src/integer/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::UnsignedAbs; macro_rules! impl_float { ($t: ident) => { impl PartialOrd<$t> for Integer { /// Compares an [`Integer`] to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). fn partial_cmp(&self, other: &$t) -> Option { if self.sign { self.unsigned_abs().partial_cmp(other) } else { self.unsigned_abs() .partial_cmp(&-other) .map(Ordering::reverse) } } } impl PartialOrd for $t { /// Compares a primitive float to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `other.significant_bits()` /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). #[inline] fn partial_cmp(&self, other: &Integer) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/integer/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; fn partial_cmp_unsigned(x: &Integer, other: &T) -> Option where Natural: PartialOrd, { if x.sign { x.abs.partial_cmp(other) } else { Some(Less) } } macro_rules! impl_unsigned { ($t: ident) => { impl PartialOrd<$t> for Integer { /// Compares an [`Integer`] to an unsigned primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { partial_cmp_unsigned(self, other) } } impl PartialOrd for $t { /// Compares an unsigned primitive integer to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Integer) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_unsigned); fn partial_cmp_signed, S: Copy + Ord + UnsignedAbs + Zero>( x: &Integer, other: &S, ) -> Option where Natural: PartialOrd, { if x.sign { if *other >= S::ZERO { x.abs.partial_cmp(&other.unsigned_abs()) } else { Some(Greater) } } else if *other >= S::ZERO { Some(Less) } else { other.unsigned_abs().partial_cmp(&x.abs) } } macro_rules! impl_signed { ($t: ident) => { impl PartialOrd<$t> for Integer { /// Compares an [`Integer`] to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { partial_cmp_signed(self, other) } } impl PartialOrd for $t { /// Compares a signed primitive integer to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Integer) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/integer/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; impl PartialEq for Integer { /// Determines whether an [`Integer`] is equal to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `min(self.significant_bits(), other.significant_bits())` /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Integer::from(123) == Natural::from(123u32)); /// assert!(Integer::from(123) != Natural::from(5u32)); /// ``` fn eq(&self, other: &Natural) -> bool { self.sign && self.abs == *other } } impl PartialEq for Natural { /// Determines whether a [`Natural`] is equal to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where n = `min(self.significant_bits(), other.significant_bits())` /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) == Integer::from(123)); /// assert!(Natural::from(123u32) != Integer::from(5)); /// ``` fn eq(&self, other: &Integer) -> bool { other.sign && *self == other.abs } } ================================================ FILE: malachite-nz/src/integer/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::arithmetic::traits::UnsignedAbs; macro_rules! impl_float { ($t: ident) => { impl PartialEq<$t> for Integer { /// Determines whether an [`Integer`] is equal to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). fn eq(&self, other: &$t) -> bool { if self.sign { self.unsigned_abs() == *other } else { self.unsigned_abs() == -other } } } impl PartialEq for $t { /// Determines whether a primitive float is equal to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[inline] fn eq(&self, other: &Integer) -> bool { other == self } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/integer/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; macro_rules! impl_unsigned { ($t: ident) => { impl PartialEq<$t> for Integer { /// Determines whether an [`Integer`] is equal to an unsigned primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &$t) -> bool { self.sign && self.abs == *other } } impl PartialEq for $t { /// Determines whether an unsigned primitive integer is equal to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Integer) -> bool { other == self } } }; } apply_to_unsigneds!(impl_unsigned); fn eq_signed + Zero>(x: &Integer, other: &S) -> bool where Natural: PartialEq, { x.sign == (*other >= S::ZERO) && x.abs == other.unsigned_abs() } macro_rules! impl_signed { ($t: ident) => { impl PartialEq<$t> for Integer { /// Determines whether an [`Integer`] is equal to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). fn eq(&self, other: &$t) -> bool { eq_signed(self, other) } } impl PartialEq for $t { /// Determines whether a signed primitive integer is equal to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Integer) -> bool { other == self } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/integer/conversion/from_bool.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::basic::traits::{One, Zero}; impl From for Integer { /// Converts a [`bool`] to 0 or 1. /// /// This function is known as the [Iverson /// bracket](https://en.wikipedia.org/wiki/Iverson_bracket). /// /// $$ /// f(P) = \[P\] = \\begin{cases} /// 1 & \text{if} \\quad P, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(false), 0); /// assert_eq!(Integer::from(true), 1); /// ``` #[inline] fn from(b: bool) -> Self { if b { Self::ONE } else { Self::ZERO } } } ================================================ FILE: malachite-nz/src/integer/conversion/from_natural.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; impl Integer { /// Converts a sign and a [`Natural`] to an [`Integer`], taking the [`Natural`] by value. The /// [`Natural`] becomes the [`Integer`]'s absolute value, and the sign indicates whether the /// [`Integer`] should be non-negative. If the [`Natural`] is zero, then the [`Integer`] will be /// non-negative regardless of the sign. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Integer::from_sign_and_abs(true, Natural::from(123u32)), 123); /// assert_eq!( /// Integer::from_sign_and_abs(false, Natural::from(123u32)), /// -123 /// ); /// ``` pub fn from_sign_and_abs(sign: bool, abs: Natural) -> Self { Self { sign: sign || abs == 0, abs, } } /// Converts a sign and an [`Natural`] to an [`Integer`], taking the [`Natural`] by reference. /// The [`Natural`] becomes the [`Integer`]'s absolute value, and the sign indicates whether the /// [`Integer`] should be non-negative. If the [`Natural`] is zero, then the [`Integer`] will be /// non-negative regardless of the sign. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `abs.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Integer::from_sign_and_abs_ref(true, &Natural::from(123u32)), /// 123 /// ); /// assert_eq!( /// Integer::from_sign_and_abs_ref(false, &Natural::from(123u32)), /// -123 /// ); /// ``` pub fn from_sign_and_abs_ref(sign: bool, abs: &Natural) -> Self { Self { sign: sign || *abs == 0, abs: abs.clone(), } } } impl From for Integer { /// Converts a [`Natural`] to an [`Integer`], taking the [`Natural`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Integer::from(Natural::from(123u32)), 123); /// assert_eq!( /// Integer::from(Natural::from(10u32).pow(12)), /// 1000000000000u64 /// ); /// ``` fn from(value: Natural) -> Self { Self { sign: true, abs: value, } } } impl<'a> From<&'a Natural> for Integer { /// Converts a [`Natural`] to an [`Integer`], taking the [`Natural`] by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Integer::from(&Natural::from(123u32)), 123); /// assert_eq!( /// Integer::from(&Natural::from(10u32).pow(12)), /// 1000000000000u64 /// ); /// ``` fn from(value: &'a Natural) -> Self { Self { sign: true, abs: value.clone(), } } } ================================================ FILE: malachite-nz/src/integer/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::cmp::Ordering; use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError}; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode; macro_rules! float_impls { ($f: ident) => { impl RoundingFrom<$f> for Integer { /// Converts a primitive float to an [`Integer`], using the specified rounding mode. An /// [`Ordering`] is also returned, indicating whether the returned value is less than, /// equal to, or greater than the original value. /// /// The floating-point value cannot be NaN or infinite. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.sci_exponent()`. /// /// # Panics /// Panics if `value` is NaN or infinite or if the rounding mode is `Exact` and `value` /// is not an integer. /// /// # Examples /// See [here](super::from_primitive_float#rounding_from). fn rounding_from(value: $f, rm: RoundingMode) -> (Self, Ordering) { if value >= 0.0 { let (abs, o) = Natural::rounding_from(value, rm); (Integer { sign: true, abs }, o) } else { let (n, o) = Natural::rounding_from(-value, -rm); (-n, o.reverse()) } } } impl TryFrom<$f> for Integer { type Error = SignedFromFloatError; /// Converts a primitive float to an [`Integer`]. /// /// If the input isn't exactly equal to some [`Integer`], an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.sci_exponent()`. /// /// # Examples /// See [here](super::from_primitive_float#try_from). fn try_from(value: $f) -> Result { Natural::try_from(value.abs()) .map(|n| Integer { sign: value >= 0.0, abs: n, }) .map_err(|e| match e { UnsignedFromFloatError::FloatInfiniteOrNan => { SignedFromFloatError::FloatInfiniteOrNan } UnsignedFromFloatError::FloatNonIntegerOrOutOfRange => { SignedFromFloatError::FloatNonIntegerOrOutOfRange } _ => unreachable!(), }) } } impl ConvertibleFrom<$f> for Integer { /// Determines whether a primitive float can be exactly converted to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_float#convertible_from). fn convertible_from(value: $f) -> bool { Natural::convertible_from(value.abs()) } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-nz/src/integer/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::platform::{Limb, SignedLimb}; impl Integer { /// Converts a [`Limb`](crate#limbs) to an [`Integer`]. /// /// This function is const, so it may be used to define constants. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// const TEN: Integer = Integer::const_from_unsigned(10); /// assert_eq!(TEN, 10); /// ``` pub const fn const_from_unsigned(x: Limb) -> Self { Self { sign: true, abs: Natural::const_from(x), } } /// Converts a [`SignedLimb`](crate#limbs) to an [`Integer`]. /// /// This function is const, so it may be used to define constants. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// const TEN: Integer = Integer::const_from_signed(10); /// assert_eq!(TEN, 10); /// /// const NEGATIVE_TEN: Integer = Integer::const_from_signed(-10); /// assert_eq!(NEGATIVE_TEN, -10); /// ``` pub const fn const_from_signed(x: SignedLimb) -> Self { Self { sign: x >= 0, abs: Natural::const_from(x.unsigned_abs()), } } } macro_rules! impl_from_unsigned { ($t: ident) => { impl From<$t> for Integer { /// Converts an unsigned primitive integer to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Integer { Integer { sign: true, abs: Natural::from(u), } } } }; } apply_to_unsigneds!(impl_from_unsigned); macro_rules! impl_from_signed { ($t: ident) => { impl From<$t> for Integer { /// Converts a signed primitive integer to an [`Integer`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(i: $t) -> Integer { Integer { sign: i >= 0, abs: Natural::from(i.unsigned_abs()), } } } }; } apply_to_signeds!(impl_from_signed); ================================================ FILE: malachite-nz/src/integer/conversion/from_twos_complement_limbs.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::conversion::to_twos_complement_limbs::{ limbs_twos_complement, limbs_twos_complement_in_place, }; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; impl Integer { /// Converts a slice of [limbs](crate#limbs) to an [`Integer`], in ascending order, so that less /// significant limbs have lower indices in the input slice. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is non-negative, and if the bit is one it is /// negative. If the slice is empty, zero is returned. /// /// This function borrows a slice. If taking ownership of a [`Vec`] is possible instead, /// [`from_owned_twos_complement_limbs_asc`](`Self::from_owned_twos_complement_limbs_asc`) is /// more efficient. /// /// This function is more efficient than /// [`from_twos_complement_limbs_desc`](`Self::from_twos_complement_limbs_desc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::from_twos_complement_limbs_asc(&[]), 0); /// assert_eq!(Integer::from_twos_complement_limbs_asc(&[123]), 123); /// assert_eq!(Integer::from_twos_complement_limbs_asc(&[4294967173]), -123); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from_twos_complement_limbs_asc(&[3567587328, 232]), /// 1000000000000u64 /// ); /// assert_eq!( /// Integer::from_twos_complement_limbs_asc(&[727379968, 4294967063]), /// -1000000000000i64 /// ); /// } /// ``` pub fn from_twos_complement_limbs_asc(xs: &[Limb]) -> Self { match xs { &[] => Self::ZERO, &[.., last] if !last.get_highest_bit() => Self::from(Natural::from_limbs_asc(xs)), xs => -Natural::from_owned_limbs_asc(limbs_twos_complement(xs)), } } /// Converts a slice of [limbs](crate#limbs) to an [`Integer`], in descending order, so that /// less significant limbs have higher indices in the input slice. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is non-negative, and if the bit is one it is /// negative. If the slice is empty, zero is returned. /// /// This function borrows a slice. If taking ownership of a [`Vec`] is possible instead, /// [`from_owned_twos_complement_limbs_desc`](`Self::from_owned_twos_complement_limbs_desc`) is /// more efficient. /// /// This function is less efficient than /// [`from_twos_complement_limbs_asc`](`Self::from_twos_complement_limbs_asc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::from_twos_complement_limbs_desc(&[]), 0); /// assert_eq!(Integer::from_twos_complement_limbs_desc(&[123]), 123); /// assert_eq!( /// Integer::from_twos_complement_limbs_desc(&[4294967173]), /// -123 /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from_twos_complement_limbs_desc(&[232, 3567587328]), /// 1000000000000u64 /// ); /// assert_eq!( /// Integer::from_twos_complement_limbs_desc(&[4294967063, 727379968]), /// -1000000000000i64 /// ); /// } /// ``` pub fn from_twos_complement_limbs_desc(xs: &[Limb]) -> Self { Self::from_owned_twos_complement_limbs_asc(xs.iter().copied().rev().collect()) } /// Converts a slice of [limbs](crate#limbs) to an [`Integer`], in ascending order, so that less /// significant limbs have lower indices in the input slice. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is non-negative, and if the bit is one it is /// negative. If the slice is empty, zero is returned. /// /// This function takes ownership of a [`Vec`]. If it's necessary to borrow a slice instead, use /// [`from_twos_complement_limbs_asc`](`Self::from_twos_complement_limbs_asc`) /// /// This function is more efficient than /// [`from_owned_twos_complement_limbs_desc`](`Self::from_owned_twos_complement_limbs_desc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::from_owned_twos_complement_limbs_asc(vec![]), 0); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_asc(vec![123]), /// 123 /// ); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_asc(vec![4294967173]), /// -123 /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_asc(vec![3567587328, 232]), /// 1000000000000i64 /// ); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_asc(vec![727379968, 4294967063]), /// -1000000000000i64 /// ); /// } /// ``` pub fn from_owned_twos_complement_limbs_asc(mut xs: Vec) -> Self { match *xs.as_slice() { [] => Self::ZERO, [.., last] if !last.get_highest_bit() => Self::from(Natural::from_owned_limbs_asc(xs)), _ => { assert!(!limbs_twos_complement_in_place(&mut xs)); -Natural::from_owned_limbs_asc(xs) } } } /// Converts a slice of [limbs](crate#limbs) to an [`Integer`], in descending order, so that /// less significant limbs have higher indices in the input slice. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is non-negative, and if the bit is one it is /// negative. If the slice is empty, zero is returned. /// /// This function takes ownership of a [`Vec`]. If it's necessary to borrow a slice instead, use /// [`from_twos_complement_limbs_desc`](`Self::from_twos_complement_limbs_desc`). /// /// This function is less efficient than /// [`from_owned_twos_complement_limbs_asc`](`Self::from_owned_twos_complement_limbs_asc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::from_owned_twos_complement_limbs_desc(vec![]), 0); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_desc(vec![123]), /// 123 /// ); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_desc(vec![4294967173]), /// -123 /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_desc(vec![232, 3567587328]), /// 1000000000000i64 /// ); /// assert_eq!( /// Integer::from_owned_twos_complement_limbs_desc(vec![4294967063, 727379968]), /// -1000000000000i64 /// ); /// } /// ``` pub fn from_owned_twos_complement_limbs_desc(mut xs: Vec) -> Self { xs.reverse(); Self::from_owned_twos_complement_limbs_asc(xs) } } ================================================ FILE: malachite-nz/src/integer/conversion/is_integer.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::IsInteger; impl IsInteger for &Integer { /// Determines whether an [`Integer`] is an integer. It always returns `true`. /// /// $f(x) = \textrm{true}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; /// use malachite_base::num::conversion::traits::IsInteger; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.is_integer(), true); /// assert_eq!(Integer::ONE.is_integer(), true); /// assert_eq!(Integer::from(100).is_integer(), true); /// assert_eq!(Integer::NEGATIVE_ONE.is_integer(), true); /// assert_eq!(Integer::from(-100).is_integer(), true); /// ``` #[inline] fn is_integer(self) -> bool { true } } ================================================ FILE: malachite-nz/src/integer/conversion/mod.rs ================================================ // Copyright © 2026 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 . /// An implementation of the [`From`] trait for converting a [`bool`] to an /// [`Integer`](crate::integer::Integer). pub mod from_bool; /// Functions for converting a [`Natural`](crate::natural::Natural) to an /// [`Integer`](crate::integer::Integer), and an implementation of the [`From`] trait. pub mod from_natural; /// Implementations of traits for converting a primitive float to an /// [`Integer`](crate::integer::Integer). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::rounding_from(0.0, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(-0.0, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(123.0, Exact).to_debug_string(), /// "(123, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(1.0e9, Exact).to_debug_string(), /// "(1000000000, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(1.0e9, Exact).to_debug_string(), /// "(1000000000, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(4294967295.0, Exact).to_debug_string(), /// "(4294967295, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(4294967296.0, Exact).to_debug_string(), /// "(4294967296, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(1.0e100, Exact).to_debug_string(), /// "(1000000000000000015902891109759918046836080856394528138978132755774783877217038106081346\ /// 9985856815104, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(123.1, Floor).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(123.1, Ceiling).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(123.1, Nearest).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(123.9, Floor).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(123.9, Ceiling).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(123.9, Nearest).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(123.5, Nearest).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(124.5, Nearest).to_debug_string(), /// "(124, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(-0.99, Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(-0.499, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(-0.5, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` /// /// # try_from /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::try_from(f64::NAN).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!( /// Integer::try_from(f64::INFINITY).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!( /// Integer::try_from(f64::NEGATIVE_INFINITY).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!(Integer::try_from(0.0).to_debug_string(), "Ok(0)"); /// assert_eq!(Integer::try_from(-0.0).to_debug_string(), "Ok(0)"); /// assert_eq!(Integer::try_from(123.0).to_debug_string(), "Ok(123)"); /// assert_eq!(Integer::try_from(-123.0).to_debug_string(), "Ok(-123)"); /// assert_eq!(Integer::try_from(1.0e9).to_debug_string(), "Ok(1000000000)"); /// assert_eq!( /// Integer::try_from(4294967295.0).to_debug_string(), /// "Ok(4294967295)" /// ); /// assert_eq!( /// Integer::try_from(4294967296.0).to_debug_string(), /// "Ok(4294967296)" /// ); /// assert_eq!( /// Integer::try_from(1.0e100).to_debug_string(), /// "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ /// 469985856815104)" /// ); /// assert_eq!( /// Integer::try_from(123.1).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Integer::try_from(123.9).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Integer::try_from(123.5).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Integer::try_from(124.5).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Integer::try_from(-0.499).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Integer::try_from(-0.5).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::convertible_from(f64::NAN), false); /// assert_eq!(Integer::convertible_from(f64::INFINITY), false); /// assert_eq!(Integer::convertible_from(f64::NEGATIVE_INFINITY), false); /// assert_eq!(Integer::convertible_from(0.0), true); /// assert_eq!(Integer::convertible_from(-0.0), true); /// assert_eq!(Integer::convertible_from(123.0), true); /// assert_eq!(Integer::convertible_from(-123.0), true); /// assert_eq!(Integer::convertible_from(1.0e9), true); /// assert_eq!(Integer::convertible_from(4294967295.0), true); /// assert_eq!(Integer::convertible_from(4294967296.0), true); /// assert_eq!(Integer::convertible_from(1.0e100), true); /// assert_eq!(Integer::convertible_from(123.1), false); /// assert_eq!(Integer::convertible_from(123.9), false); /// assert_eq!(Integer::convertible_from(123.5), false); /// assert_eq!(Integer::convertible_from(124.5), false); /// assert_eq!(Integer::convertible_from(-0.499), false); /// assert_eq!(Integer::convertible_from(-0.5), false); /// ``` pub mod from_primitive_float; /// Implementations of traits for converting a primitive integer to an /// [`Integer`](crate::integer::Integer). /// /// The traits are [`From`], [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`SaturatingFrom`](malachite_base::num::conversion::traits::SaturatingFrom). /// /// # from /// ``` /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123u32).to_string(), "123"); /// assert_eq!(Integer::from(-123i32).to_string(), "-123"); /// ``` pub mod from_primitive_int; /// Functions for constructing an [`Integer`](crate::integer::Integer) from two's complement /// [`Limb`](crate#limbs)s. pub mod from_twos_complement_limbs; /// An implementation of [`IsInteger`](malachite_base::num::conversion::traits::IsInteger), a trait /// for determining whether a number is an integer. /// /// An [`Integer`](crate::integer::Integer) is always an integer. pub mod is_integer; /// Implementations of traits for converting an [`Integer`](crate::integer::Integer) to a /// [`Natural`](crate::natural::Natural). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`SaturatingFrom`](malachite_base::num::conversion::traits::SaturatingFrom). pub mod natural_from_integer; /// Implementations of traits for converting an [`Integer`](crate::integer::Integer) to a primitive /// float. /// /// The traits are [`TryFrom`] /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use core::cmp::Ordering::*; /// use core::str::FromStr; /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// f32::rounding_from(&Integer::from_str("123").unwrap(), Exact), /// (123.0, Equal) /// ); /// assert_eq!( /// f32::rounding_from(&Integer::from_str("1000000001").unwrap(), Floor), /// (1.0e9, Less) /// ); /// assert_eq!( /// f32::rounding_from(&Integer::from_str("1000000001").unwrap(), Ceiling), /// (1.00000006e9, Greater) /// ); /// assert_eq!( /// f32::rounding_from(&Integer::from_str("-1000000001").unwrap(), Floor), /// (-1.00000006e9, Less) /// ); /// assert_eq!( /// f32::rounding_from(&Integer::from_str("-1000000001").unwrap(), Ceiling), /// (-1.0e9, Greater) /// ); /// assert_eq!( /// f32::rounding_from( /// &Integer::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), /// Nearest /// ), /// (f32::INFINITY, Greater) /// ); /// ``` /// /// # try_from /// ``` /// use core::str::FromStr; /// use malachite_nz::integer::conversion::primitive_float_from_integer::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!(f32::try_from(&Integer::from_str("123").unwrap()), Ok(123.0)); /// assert_eq!( /// f32::try_from(&Integer::from_str("-1000000000").unwrap()), /// Ok(-1.0e9) /// ); /// assert_eq!( /// f32::try_from(&Integer::from_str("1000000001").unwrap()), /// Err(PrimitiveFloatFromIntegerError) /// ); /// assert_eq!( /// f32::try_from( /// &Integer::from_str("-10000000000000000000000000000000000000000000000000000").unwrap() /// ), /// Err(PrimitiveFloatFromIntegerError) /// ); /// ``` /// /// # convertible_from /// ``` /// use core::str::FromStr; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// f32::convertible_from(&Integer::from_str("123").unwrap()), /// true /// ); /// assert_eq!( /// f32::convertible_from(&Integer::from_str("-1000000000").unwrap()), /// true /// ); /// assert_eq!( /// f32::convertible_from(&Integer::from_str("1000000001").unwrap()), /// false /// ); /// assert_eq!( /// f32::convertible_from( /// &Integer::from_str("-10000000000000000000000000000000000000000000000000000").unwrap() /// ), /// false /// ); /// ``` pub mod primitive_float_from_integer; /// Implementations of traits for converting an [`Integer`](crate::integer::Integer) to a primitive /// integer. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), /// [`OverflowingFrom`](malachite_base::num::conversion::traits::OverflowingFrom), /// [`SaturatingFrom`](malachite_base::num::conversion::traits::SaturatingFrom), and /// [`WrappingFrom`](malachite_base::num::conversion::traits::WrappingFrom). /// /// # try_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::integer::conversion::primitive_int_from_integer::{ /// SignedFromIntegerError, UnsignedFromIntegerError, /// }; /// use malachite_nz::integer::Integer; /// /// assert_eq!(u32::try_from(&Integer::from(123)), Ok(123)); /// assert_eq!( /// u32::try_from(&Integer::from(-123)), /// Err(UnsignedFromIntegerError) /// ); /// assert_eq!( /// u32::try_from(&Integer::from(10u32).pow(12)), /// Err(UnsignedFromIntegerError) /// ); /// assert_eq!( /// u32::try_from(&-Integer::from(10u32).pow(12)), /// Err(UnsignedFromIntegerError) /// ); /// /// assert_eq!(i32::try_from(&Integer::from(123)), Ok(123)); /// assert_eq!(i32::try_from(&Integer::from(-123)), Ok(-123)); /// assert_eq!( /// i32::try_from(&Integer::from(10u32).pow(12)), /// Err(SignedFromIntegerError) /// ); /// assert_eq!( /// i32::try_from(&-Integer::from(10u32).pow(12)), /// Err(SignedFromIntegerError) /// ); /// ``` /// /// # wrapping_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::WrappingFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!(u32::wrapping_from(&Integer::from(123)), 123); /// assert_eq!(u32::wrapping_from(&Integer::from(-123)), 4294967173); /// assert_eq!( /// u32::wrapping_from(&Integer::from(10u32).pow(12)), /// 3567587328 /// ); /// assert_eq!( /// u32::wrapping_from(&-Integer::from(10u32).pow(12)), /// 727379968 /// ); /// /// assert_eq!(i32::wrapping_from(&Integer::from(123)), 123); /// assert_eq!(i32::wrapping_from(&Integer::from(-123)), -123); /// assert_eq!( /// i32::wrapping_from(&Integer::from(10u32).pow(12)), /// -727379968 /// ); /// assert_eq!( /// i32::wrapping_from(&-Integer::from(10u32).pow(12)), /// 727379968 /// ); /// ``` /// /// # saturating_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::SaturatingFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!(u32::saturating_from(&Integer::from(123)), 123); /// assert_eq!(u32::saturating_from(&Integer::from(-123)), 0); /// assert_eq!( /// u32::saturating_from(&Integer::from(10u32).pow(12)), /// u32::MAX /// ); /// assert_eq!(u32::saturating_from(&-Integer::from(10u32).pow(12)), 0); /// /// assert_eq!(i32::saturating_from(&Integer::from(123)), 123); /// assert_eq!(i32::saturating_from(&Integer::from(-123)), -123); /// assert_eq!( /// i32::saturating_from(&Integer::from(10u32).pow(12)), /// 2147483647 /// ); /// assert_eq!( /// i32::saturating_from(&-Integer::from(10u32).pow(12)), /// -2147483648 /// ); /// ``` /// /// # overflowing_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::OverflowingFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!(u32::overflowing_from(&Integer::from(123)), (123, false)); /// assert_eq!( /// u32::overflowing_from(&Integer::from(-123)), /// (4294967173, true) /// ); /// assert_eq!( /// u32::overflowing_from(&Integer::from(10u32).pow(12)), /// (3567587328, true) /// ); /// assert_eq!( /// u32::overflowing_from(&-Integer::from(10u32).pow(12)), /// (727379968, true) /// ); /// /// assert_eq!(i32::overflowing_from(&Integer::from(123)), (123, false)); /// assert_eq!(i32::overflowing_from(&Integer::from(-123)), (-123, false)); /// assert_eq!( /// i32::overflowing_from(&Integer::from(10u32).pow(12)), /// (-727379968, true) /// ); /// assert_eq!( /// i32::overflowing_from(&-Integer::from(10u32).pow(12)), /// (727379968, true) /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// /// assert_eq!(u32::convertible_from(&Integer::from(123)), true); /// assert_eq!(u32::convertible_from(&Integer::from(-123)), false); /// assert_eq!(u32::convertible_from(&Integer::from(10u32).pow(12)), false); /// assert_eq!(u32::convertible_from(&-Integer::from(10u32).pow(12)), false); /// /// assert_eq!(i32::convertible_from(&Integer::from(123)), true); /// assert_eq!(i32::convertible_from(&Integer::from(-123)), true); /// assert_eq!(i32::convertible_from(&Integer::from(10u32).pow(12)), false); /// assert_eq!(i32::convertible_from(&-Integer::from(10u32).pow(12)), false); /// ``` pub mod primitive_int_from_integer; /// Implementations of traits for conversions between Python integers and /// [`Integer`](crate::integer::Integer)s using [pyo3](https://pyo3.rs/). pub mod pyo3; /// Implementations of traits for serialization and deserialization using /// [serde](https://serde.rs/). pub mod serde; /// Implementations of traits for converting [`Integer`](crate::integer::Integer)s to and from /// [`String`]s. pub mod string; /// Functions for extracting two's complement [`Limb`](crate#limbs)s from an /// [`Integer`](crate::integer::Integer). pub mod to_twos_complement_limbs; ================================================ FILE: malachite-nz/src/integer/conversion/natural_from_integer.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, SaturatingFrom}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct NaturalFromIntegerError; impl TryFrom for Natural { type Error = NaturalFromIntegerError; /// Converts an [`Integer`] to a [`Natural`], taking the [`Natural`] by value. If the /// [`Integer`] is negative, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::try_from(Integer::from(123)).to_debug_string(), /// "Ok(123)" /// ); /// assert_eq!( /// Natural::try_from(Integer::from(-123)).to_debug_string(), /// "Err(NaturalFromIntegerError)" /// ); /// assert_eq!( /// Natural::try_from(Integer::from(10u32).pow(12)).to_debug_string(), /// "Ok(1000000000000)" /// ); /// assert_eq!( /// Natural::try_from(-Integer::from(10u32).pow(12)).to_debug_string(), /// "Err(NaturalFromIntegerError)" /// ); /// ``` fn try_from(value: Integer) -> Result { match value { Integer { sign: false, .. } => Err(NaturalFromIntegerError), Integer { sign: true, abs } => Ok(abs), } } } impl<'a> TryFrom<&'a Integer> for Natural { type Error = NaturalFromIntegerError; /// Converts an [`Integer`] to a [`Natural`], taking the [`Natural`] by reference. If the /// [`Integer`] is negative, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::try_from(&Integer::from(123)).to_debug_string(), /// "Ok(123)" /// ); /// assert_eq!( /// Natural::try_from(&Integer::from(-123)).to_debug_string(), /// "Err(NaturalFromIntegerError)" /// ); /// assert_eq!( /// Natural::try_from(&Integer::from(10u32).pow(12)).to_debug_string(), /// "Ok(1000000000000)" /// ); /// assert_eq!( /// Natural::try_from(&(-Integer::from(10u32).pow(12))).to_debug_string(), /// "Err(NaturalFromIntegerError)" /// ); /// ``` fn try_from(value: &'a Integer) -> Result { match *value { Integer { sign: false, .. } => Err(NaturalFromIntegerError), Integer { sign: true, ref abs, } => Ok(abs.clone()), } } } impl SaturatingFrom for Natural { /// Converts an [`Integer`] to a [`Natural`], taking the [`Natural`] by value. If the /// [`Integer`] is negative, 0 is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::SaturatingFrom; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::saturating_from(Integer::from(123)), 123); /// assert_eq!(Natural::saturating_from(Integer::from(-123)), 0); /// assert_eq!( /// Natural::saturating_from(Integer::from(10u32).pow(12)), /// 1000000000000u64 /// ); /// assert_eq!(Natural::saturating_from(-Integer::from(10u32).pow(12)), 0); /// ``` fn saturating_from(value: Integer) -> Self { match value { Integer { sign: false, .. } => Self::ZERO, Integer { sign: true, abs } => abs, } } } impl<'a> SaturatingFrom<&'a Integer> for Natural { /// Converts an [`Integer`] to a [`Natural`], taking the [`Natural`] by reference. If the /// [`Integer`] is negative, 0 is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::SaturatingFrom; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::saturating_from(&Integer::from(123)), 123); /// assert_eq!(Natural::saturating_from(&Integer::from(-123)), 0); /// assert_eq!( /// Natural::saturating_from(&Integer::from(10u32).pow(12)), /// 1000000000000u64 /// ); /// assert_eq!(Natural::saturating_from(&-Integer::from(10u32).pow(12)), 0); /// ``` fn saturating_from(value: &'a Integer) -> Self { match *value { Integer { sign: false, .. } => Self::ZERO, Integer { sign: true, ref abs, } => abs.clone(), } } } impl ConvertibleFrom for Natural { /// Determines whether an [`Integer`] can be converted to a [`Natural`] (when the [`Integer`] is /// non-negative). Takes the [`Integer`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::convertible_from(Integer::from(123)), true); /// assert_eq!(Natural::convertible_from(Integer::from(-123)), false); /// assert_eq!( /// Natural::convertible_from(Integer::from(10u32).pow(12)), /// true /// ); /// assert_eq!( /// Natural::convertible_from(-Integer::from(10u32).pow(12)), /// false /// ); /// ``` #[inline] fn convertible_from(value: Integer) -> bool { value.sign } } impl<'a> ConvertibleFrom<&'a Integer> for Natural { /// Determines whether an [`Integer`] can be converted to a [`Natural`] (when the [`Integer`] is /// non-negative). Takes the [`Integer`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::convertible_from(&Integer::from(123)), true); /// assert_eq!(Natural::convertible_from(&Integer::from(-123)), false); /// assert_eq!( /// Natural::convertible_from(&Integer::from(10u32).pow(12)), /// true /// ); /// assert_eq!( /// Natural::convertible_from(&-Integer::from(10u32).pow(12)), /// false /// ); /// ``` #[inline] fn convertible_from(value: &'a Integer) -> bool { value.sign } } ================================================ FILE: malachite-nz/src/integer/conversion/primitive_float_from_integer.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::cmp::Ordering; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PrimitiveFloatFromIntegerError; macro_rules! float_impls { ($f: ident) => { impl<'a> RoundingFrom<&'a Integer> for $f { /// Converts an [`Integer`] to a primitive float according to a specified /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// - If the rounding mode is `Floor` the largest float less than or equal to the /// [`Integer`] is returned. If the [`Integer`] is greater than the maximum finite /// float, then the maximum finite float is returned. If it is smaller than the /// minimum finite float, then $-\infty$ is returned. /// - If the rounding mode is `Ceiling`, the smallest float greater than or equal to the /// [`Integer`] is returned. If the [`Integer`] is greater than the maximum finite /// float, then $\infty$ is returned. If it is smaller than the minimum finite float, /// then the minimum finite float is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the /// [`Integer`] is non-negative and as with `Ceiling` if the [`Integer`] is negative. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the /// [`Integer`] is non-negative and as with `Floor` if the [`Integer`] is negative. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If the /// [`Integer`] is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. If the [`Integer`] is /// greater than the maximum finite float, then $\infty$ is returned. If the /// [`Integer`] is smaller than the minimum finite float, then $-\infty$ is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the rounding mode is `Exact` and `value` cannot be represented exactly. /// /// # Examples /// See [here](super::primitive_float_from_integer#rounding_from). fn rounding_from(value: &'a Integer, rm: RoundingMode) -> ($f, Ordering) { if value.sign { $f::rounding_from(&value.abs, rm) } else { let (f, o) = $f::rounding_from(&value.abs, -rm); (-f, o.reverse()) } } } impl<'a> TryFrom<&'a Integer> for $f { type Error = PrimitiveFloatFromIntegerError; /// Converts an [`Integer`] to a primitive float. /// /// If the input isn't exactly equal to some float, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_integer#try_from). fn try_from(value: &'a Integer) -> Result<$f, Self::Error> { $f::try_from(&value.abs) .map(|f| if value.sign { f } else { -f }) .map_err(|_| PrimitiveFloatFromIntegerError) } } impl<'a> ConvertibleFrom<&'a Integer> for $f { /// Determines whether an [`Integer`] can be exactly converted to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_integer#convertible_from). fn convertible_from(value: &'a Integer) -> bool { $f::convertible_from(&value.abs) } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-nz/src/integer/conversion/primitive_int_from_integer.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::Neg; use malachite_base::comparison::traits::Min; use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, WrappingNeg}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ ConvertibleFrom, OverflowingFrom, SaturatingFrom, WrappingFrom, }; use malachite_base::num::logic::traits::SignificantBits; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct UnsignedFromIntegerError; fn try_from_unsigned<'a, T: TryFrom<&'a Natural>>( value: &'a Integer, ) -> Result { match *value { Integer { sign: false, .. } => Err(UnsignedFromIntegerError), Integer { sign: true, ref abs, } => T::try_from(abs).map_err(|_| UnsignedFromIntegerError), } } fn wrapping_from_unsigned<'a, T: WrappingFrom<&'a Natural> + WrappingNeg>( value: &'a Integer, ) -> T { match *value { Integer { sign: true, ref abs, } => T::wrapping_from(abs), Integer { sign: false, ref abs, } => T::wrapping_from(abs).wrapping_neg(), } } fn saturating_from_unsigned<'a, T: Copy + SaturatingFrom<&'a Natural> + Zero>( value: &'a Integer, ) -> T { match *value { Integer { sign: true, ref abs, } => T::saturating_from(abs), _ => T::ZERO, } } fn overflowing_from_unsigned< 'a, T: OverflowingFrom<&'a Natural> + WrappingFrom<&'a Natural> + WrappingNeg, >( value: &'a Integer, ) -> (T, bool) { match *value { Integer { sign: true, ref abs, } => T::overflowing_from(abs), Integer { sign: false, ref abs, } => (T::wrapping_from(abs).wrapping_neg(), true), } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct SignedFromIntegerError; fn try_from_signed<'a, T: ConvertibleFrom<&'a Integer> + WrappingFrom<&'a Integer>>( value: &'a Integer, ) -> Result { if T::convertible_from(value) { Ok(T::wrapping_from(value)) } else { Err(SignedFromIntegerError) } } fn saturating_from_signed< 'a, U: PrimitiveInt + SaturatingFrom<&'a Natural>, S: Min + Neg + SaturatingFrom + WrappingFrom, >( value: &'a Integer, ) -> S { match *value { Integer { sign: true, ref abs, } => S::saturating_from(U::saturating_from(abs)), Integer { sign: false, ref abs, } => { let abs = U::saturating_from(abs); if abs.get_highest_bit() { S::MIN } else { -S::wrapping_from(abs) } } } } fn convertible_from_signed(value: &Integer) -> bool { match *value { Integer { sign: true, ref abs, } => abs.significant_bits() < T::WIDTH, Integer { sign: false, ref abs, } => { let significant_bits = abs.significant_bits(); significant_bits < T::WIDTH || significant_bits == T::WIDTH && abs.divisible_by_power_of_2(T::WIDTH - 1) } } } macro_rules! impl_from { ($u: ident, $s: ident) => { impl<'a> TryFrom<&'a Integer> for $u { type Error = UnsignedFromIntegerError; /// Converts an [`Integer`] to an unsigned primitive integer, returning an error if the /// [`Integer`] cannot be represented. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#try_from). #[inline] fn try_from(value: &Integer) -> Result<$u, Self::Error> { try_from_unsigned(value) } } impl<'a> WrappingFrom<&'a Integer> for $u { /// Converts an [`Integer`] to an unsigned primitive integer, wrapping modulo $2^W$, /// where $W$ is the width of the primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#wrapping_from). #[inline] fn wrapping_from(value: &Integer) -> $u { wrapping_from_unsigned(value) } } impl<'a> SaturatingFrom<&'a Integer> for $u { /// Converts an [`Integer`] to an unsigned primitive integer. /// /// If the [`Integer`] cannot be represented by the output type, then either zero or the /// maximum representable value is returned, whichever is closer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#saturating_from). #[inline] fn saturating_from(value: &Integer) -> $u { saturating_from_unsigned(value) } } impl<'a> OverflowingFrom<&'a Integer> for $u { /// Converts an [`Integer`] to an unsigned primitive integer, wrapping modulo $2^W$, /// where $W$ is the width of the primitive integer. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#overflowing_from). #[inline] fn overflowing_from(value: &Integer) -> ($u, bool) { overflowing_from_unsigned(value) } } impl<'a> ConvertibleFrom<&'a Integer> for $u { /// Determines whether an [`Integer`] can be converted to an unsigned primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#convertible_from). #[inline] fn convertible_from(value: &Integer) -> bool { value.sign && $u::convertible_from(&value.abs) } } impl<'a> TryFrom<&'a Integer> for $s { type Error = SignedFromIntegerError; /// Converts an [`Integer`] to a signed primitive integer, returning an error if the /// [`Integer`] cannot be represented. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#try_from). #[inline] fn try_from(value: &Integer) -> Result<$s, Self::Error> { try_from_signed(value) } } impl<'a> WrappingFrom<&'a Integer> for $s { /// Converts an [`Integer`] to a signed primitive integer, wrapping modulo $2^W$, where /// $W$ is the width of the primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#wrapping_from). #[inline] fn wrapping_from(value: &Integer) -> $s { $s::wrapping_from($u::wrapping_from(value)) } } impl<'a> SaturatingFrom<&'a Integer> for $s { /// Converts an [`Integer`] to a signed primitive integer. /// /// If the [`Integer`] cannot be represented by the output type, then either the maximum /// or the minimum representable value is returned, whichever is closer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#saturating_from). #[inline] fn saturating_from(value: &Integer) -> $s { saturating_from_signed::<$u, $s>(value) } } impl<'a> OverflowingFrom<&'a Integer> for $s { /// Converts an [`Integer`] to a signed primitive integer, wrapping modulo $2^W$, where /// $W$ is the width of the primitive integer. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#overflowing_from). #[inline] fn overflowing_from(value: &Integer) -> ($s, bool) { ($s::wrapping_from(value), !$s::convertible_from(value)) } } impl<'a> ConvertibleFrom<&'a Integer> for $s { /// Determines whether an [`Integer`] can be converted to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_integer#convertible_from). #[inline] fn convertible_from(value: &Integer) -> bool { convertible_from_signed::<$u>(value) } } }; } apply_to_unsigned_signed_pairs!(impl_from); ================================================ FILE: malachite-nz/src/integer/conversion/pyo3.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // PyO3 integration contributed by Antonio Mamić. // // 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 . #![cfg(feature = "enable_pyo3")] //! //! This is useful for converting Python integers when they may not fit in Rust's built-in integer //! types. //! //! To use this enable the `enable_pyo3` feature. //! //! ## Examples //! //! Using [`Integer`](crate::integer::Integer) to correctly increment an arbitrary precision //! integer. This is not possible with Rust's native integers if the Python integer is too large, //! in which case it will fail its conversion and raise `OverflowError`. //! ```rust //! use malachite::Integer; //! use malachite::num::basic::traits::One; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(n: Integer) -> Integer { //! n + Integer::ONE //! } //! //! #[pymodule] //! fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import add_one //! //! n = 1 << 1337 //! value = add_one(n) //! //! assert n + 1 == value //! ``` use crate::integer::Integer; use alloc::vec::Vec; use core::convert::Infallible; use malachite_base::num::basic::traits::Zero; #[cfg(Py_LIMITED_API)] use pyo3::intern; #[allow(unused_imports)] use pyo3::{ Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, Py, PyErr, PyObject, PyResult, Python, ffi, types::*, }; #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'source> FromPyObject<'source> for Integer { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { // get the Python interpreter let py = ob.py(); // get PyInt object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; // check if number is zero, and if so, return zero let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(Integer::ZERO); } // the number of bytes needed to store the integer let mut n_bytes = (n_bits + 7 + 1) >> 3; // +1 for the sign bit #[cfg(feature = "32_bit_limbs")] { // convert the number of bytes to a multiple of 4, because of 32-bit limbs n_bytes = ((n_bytes + 7) >> 2) << 2; } #[cfg(not(feature = "32_bit_limbs"))] { // convert the number of bytes to a multiple of 8, because of 64-bit limbs n_bytes = ((n_bytes + 7) >> 3) << 3; } #[cfg(not(Py_LIMITED_API))] { let limbs = int_to_limbs(num, n_bytes, true)?; Ok(Integer::from_owned_twos_complement_limbs_asc(limbs)) } #[cfg(all(Py_LIMITED_API, feature = "32_bit_limbs"))] { let py_bytes = int_to_py_bytes(num, n_bytes, true)?; let bytes = py_bytes.as_bytes(); let n_limbs_32 = n_bytes >> 2; // the number of 32-bit limbs needed to store the integer let mut limbs_32 = Vec::with_capacity(n_limbs_32); for i in (0..n_bytes).step_by(4) { limbs_32.push(u32::from_le_bytes(bytes[i..(i + 4)].try_into().unwrap())); } Ok(Integer::from_owned_twos_complement_limbs_asc(limbs_32)) } #[cfg(all(Py_LIMITED_API, not(feature = "32_bit_limbs")))] { let bytes = int_to_py_bytes(num, n_bytes, true)?.as_bytes(); let n_limbs_64 = n_bytes >> 3; // the number of 64-bit limbs needed to store the integer let mut limbs_64 = Vec::with_capacity(n_limbs_64); for i in (0..n_bytes).step_by(8) { limbs_64.push(u64::from_le_bytes(bytes[i..(i + 8)].try_into().unwrap())); } Ok(Integer::from_owned_twos_complement_limbs_asc(limbs_64)) } } } #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'py> IntoPyObject<'py> for Integer { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'py> IntoPyObject<'py> for &Integer { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { if self == &Integer::ZERO { return Ok(0i32.into_pyobject(py).unwrap()); } let bytes = limbs_to_bytes( self.twos_complement_limbs(), self.twos_complement_limb_count(), ); #[cfg(not(Py_LIMITED_API))] unsafe { let obj = ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, // little endian true.into(), // signed ); Ok(Bound::from_owned_ptr(py, obj).downcast_into_unchecked::()) } #[cfg(Py_LIMITED_API)] { let bytes_obj = PyBytes::new(py, &bytes); let kwargs = PyDict::new(py); kwargs.set_item(intern!(py, "signed"), true).unwrap(); let result: Bound<'py, PyAny> = py .get_type::() .call_method("from_bytes", (bytes_obj, "little"), Some(&kwargs)) .expect("int.from_bytes() failed during into_pyobject()"); Ok(result) } } } /// Convert 32-bit limbs (little endian) used by malachite to bytes (little endian) #[cfg(feature = "32_bit_limbs")] #[inline] fn limbs_to_bytes(limbs: impl Iterator, limb_count: u64) -> Vec { let mut bytes = Vec::with_capacity((limb_count << 3) as usize); for limb in limbs { for byte in limb.to_le_bytes() { bytes.push(byte); } } bytes } /// Convert 64-bit limbs (little endian) used by malachite to bytes (little endian) #[cfg(not(feature = "32_bit_limbs"))] #[inline] fn limbs_to_bytes(limbs: impl Iterator, limb_count: u64) -> Vec { let mut bytes = Vec::with_capacity((limb_count << 3) as usize); for limb in limbs { for byte in limb.to_le_bytes() { bytes.push(byte); } } bytes } /// Converts a Python integer to a vector of 32-bit limbs (little endian). Takes number of bytes to /// convert to. Multiple of 4. If `is_signed` is true, the integer is treated as signed, and two's /// complement is returned. #[cfg(all(not(Py_LIMITED_API), feature = "32_bit_limbs"))] #[inline] fn int_to_limbs(long: &Bound, n_bytes: usize, is_signed: bool) -> PyResult> { let mut buffer = Vec::with_capacity(n_bytes); unsafe { let error_code = ffi::_PyLong_AsByteArray( long.as_ptr().cast(), // ptr to PyLong object buffer.as_mut_ptr() as *mut u8, // ptr to first byte of buffer n_bytes << 2, // 4 bytes per u32 1, // little endian is_signed.into(), // signed flag ); if error_code == -1 { return Err(PyErr::fetch(long.py())); } buffer.set_len(n_bytes); // set buffer length to the number of bytes }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } /// Converts a Python integer to a vector of 64-bit limbs (little endian). Takes number of bytes to /// convert to. Multiple of 8. If `is_signed` is true, the integer is treated as signed, and two's /// complement is returned. #[cfg(all(not(Py_LIMITED_API), not(feature = "32_bit_limbs")))] #[inline] fn int_to_limbs(long: &Bound, n_bytes: usize, is_signed: bool) -> PyResult> { let mut buffer = Vec::with_capacity(n_bytes); unsafe { let error_code = ffi::_PyLong_AsByteArray( long.as_ptr().cast(), // ptr to PyLong object buffer.as_mut_ptr() as *mut u8, // ptr to first byte of buffer n_bytes << 3, // 8 bytes per u64 1, // little endian is_signed.into(), // signed flag ); if error_code == -1 { return Err(PyErr::fetch(long.py())); } buffer.set_len(n_bytes); // set buffer length to the number of bytes }; buffer .iter_mut() .for_each(|chunk| *chunk = u64::from_le(*chunk)); Ok(buffer) } /// Converts a Python integer to a Python bytes object. Bytes are in little endian order. Takes /// number of bytes to convert to (can be calculated from the number of bits in the integer). If /// `is_signed` is true, the integer is treated as signed, and two's complement is returned. #[cfg(Py_LIMITED_API)] #[inline] fn int_to_py_bytes<'py>( long: &Bound<'py, PyInt>, n_bytes: usize, is_signed: bool, ) -> PyResult> { // get the Python interpreter let py = long.py(); // setup kwargs for to_bytes (only if signed) let kwargs_dict = PyDict::new(py); let kwargs = if is_signed { kwargs_dict.set_item(intern!(py, "signed"), true)?; Some(&kwargs_dict) } else { None }; // call to_bytes let bytes = long.call_method( intern!(py, "to_bytes"), (n_bytes, intern!(py, "little")), kwargs, )?; // downcast to PyBytes Ok(bytes.downcast_into()?) } /// Returns the number of bits in the absolute value of the given integer. The number of bits /// returned is the smallest number of bits that can represent the integer, not the multiple of 8 /// (bytes) that it would take up in memory. #[inline] fn int_n_bits(long: &Bound) -> PyResult { let py = long.py(); #[cfg(not(Py_LIMITED_API))] { // fast path let n_bits = unsafe { ffi::_PyLong_NumBits(long.as_ptr()) }; if n_bits == (-1isize as usize) { return Err(PyErr::fetch(py)); } Ok(n_bits) } #[cfg(Py_LIMITED_API)] { // slow path long.call_method0(intern!(py, "bit_length")) .and_then(|ob| ob.extract()) } } #[cfg(test)] mod tests { use super::*; /// Prepare Python fn prepare_python() { pyo3::prepare_freethreaded_python(); } /// Fibonacci sequence iterator (Rust) fn rust_fib() -> impl Iterator where T: From, for<'a> &'a T: std::ops::Add, { let mut f0: T = T::from(1); let mut f1: T = T::from(1); std::iter::from_fn(move || { let f2 = &f0 + &f1; Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } /// Fibonacci sequence iterator (Python) fn python_fib(py: Python<'_>) -> impl Iterator> { let mut f0 = 1i32.into_pyobject(py).unwrap(); let mut f1 = 1i32.into_pyobject(py).unwrap(); std::iter::from_fn(move || { let f2 = f0 .call_method1("__add__", (&f1,)) .unwrap() .downcast_into::() .unwrap(); Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2)).unbind()) }) } /// Generate test python class fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> { let index_code = std::ffi::CStr::from_bytes_with_nul( concat!( r#" class C: def __init__(self, x): self.x = x def __index__(self): return self.x "#, "\0" ) .as_bytes(), ) .unwrap(); let filename = c"index.py"; let modulename = c"index"; PyModule::from_code(py, index_code, filename, modulename).unwrap() } /// - Test conversion to and from Integer /// - Tests the first 2000 numbers in the fibonacci sequence and their negations #[test] fn convert_integer() { prepare_python(); Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!( py_result .bind(py) .as_any() .eq(rs_result.clone().into_pyobject(py).unwrap()) .unwrap() ); // negate let rs_result = rs_result * Integer::from(-1); let py_result = py_result.call_method0(py, "__neg__").unwrap(); // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!(py_result.bind(py).eq(&rs_result).unwrap()); } }); } /// Test Python class conversion #[test] fn convert_index_class() { prepare_python(); Python::with_gil(|py| { let index = python_index_class(py); let locals = PyDict::new(py); locals.set_item("index", &index).unwrap(); let expr = c"index.C(10)"; let ob = py.eval(expr, None, Some(&locals)).unwrap(); let integer: Integer = ::extract_bound(&ob).unwrap(); assert_eq!(integer, Integer::from(10)); let expr2 = c"index.C(-10)"; let ob2 = py.eval(expr2, None, Some(&locals)).unwrap(); let integer2: Integer = ::extract_bound(&ob2).unwrap(); assert_eq!(integer2, Integer::from(-10)); }); } /// Test conversion to and from zero #[test] fn handle_zero() { prepare_python(); Python::with_gil(|py| { // Python -> Rust let zero_integer: Integer = 0u8.into_pyobject(py).unwrap().extract().unwrap(); assert_eq!(zero_integer, Integer::from(0)); // Rust -> Python let zero_integer = zero_integer.into_pyobject(py).unwrap(); assert!( zero_integer .as_any() .eq(0u8.into_py_any(py).unwrap()) .unwrap() ); }); } /// Test for possible overflows #[test] fn check_overflow() { prepare_python(); Python::with_gil(|py| { macro_rules! test { ($T:ty, $value:expr, $py:expr) => { let value = $value; println!("{}: {}", stringify!($T), value); let python_value = value.clone().into_pyobject(py).unwrap(); let roundtrip_value = <$T as FromPyObject>::extract_bound(&python_value).unwrap(); assert_eq!(value, roundtrip_value); }; } for i in 0..=256usize { // test a lot of values to help catch other bugs too test!(Integer, Integer::from(i), py); test!(Integer, -Integer::from(i), py); test!(Integer, Integer::from(1) << i, py); test!(Integer, -Integer::from(1) << i, py); test!(Integer, (Integer::from(1) << i) + Integer::from(1u32), py); test!(Integer, (-Integer::from(1) << i) + Integer::from(1u32), py); test!(Integer, (Integer::from(1) << i) - Integer::from(1u32), py); test!(Integer, (-Integer::from(1) << i) - Integer::from(1u32), py); } }); } } ================================================ FILE: malachite-nz/src/integer/conversion/serde.rs ================================================ // Copyright © 2026 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 crate::integer::{Integer, SerdeInteger}; use crate::natural::Natural; use alloc::string::String; use core::convert::TryFrom; use malachite_base::num::conversion::traits::FromStringBase; impl From for SerdeInteger { #[inline] fn from(x: Integer) -> Self { Self(format!("{x:#x}")) } } impl TryFrom for Integer { type Error = String; #[inline] fn try_from(s: SerdeInteger) -> Result { if s.0.starts_with('-') { if s.0.starts_with("-0x") { Ok(Self::from_sign_and_abs( false, Natural::from_string_base(16, &s.0[3..]) .ok_or_else(|| format!("Unrecognized digits in {}", s.0))?, )) } else { Err(format!( "String '{}' starts with '-' but not with '-0x'", s.0 )) } } else if s.0.starts_with("0x") { Ok(Self::from( Natural::from_string_base(16, &s.0[2..]) .ok_or_else(|| format!("Unrecognized digits in {}", s.0))?, )) } else { Err(format!( "String '{}' does not start with '0x' or '-0x'", s.0 )) } } } ================================================ FILE: malachite-nz/src/integer/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::conversion::string::from_sci_string::{ FromSciStringHelper, from_sci_string_with_options_helper, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::{FromSciString, FromStringBase}; impl FromSciStringHelper for Integer { fn parse_int(mut cs: &[u8], base: u8) -> Option { if let Some(b'+') = cs.first() { cs = &cs[1..]; // If the string begins with a '+', the second character cannot be '+' or '-' match cs { [] | [b'+' | b'-', ..] => return None, _ => {} } } Self::from_string_base(base, core::str::from_utf8(cs).ok()?) } fn up_1(self, neg: bool) -> Option { Some(if neg { self - Self::ONE } else { self + Self::ONE }) } } impl FromSciString for Integer { /// Converts a string, possibly in scientfic notation, to an [`Integer`]. /// /// Use [`FromSciStringOptions`] to specify the base (from 2 to 36, inclusive) and the rounding /// mode, in case rounding is necessary because the string represents a non-integer. /// /// If the base is greater than 10, the higher digits are represented by the letters `'a'` /// through `'z'` or `'A'` through `'Z'`; the case doesn't matter and doesn't need to be /// consistent. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. If the base is /// 15 or greater, an ambiguity arises where it may not be clear whether `'e'` is a digit or an /// exponent indicator. To resolve this ambiguity, always use a `'+'` or `'-'` sign after the /// exponent indicator when the base is 15 or greater. /// /// The exponent itself is always parsed using base 10. /// /// Decimal (or other-base) points are allowed. These are most useful in conjunction with /// exponents, but they may be used on their own. If the string represents a non-integer, the /// rounding mode specified in `options` is used to round to an integer. /// /// If the string is unparseable, `None` is returned. `None` is also returned if the rounding /// mode in options is `Exact`, but rounding is necessary. /// /// # Worst-case complexity /// $T(n, m) = O(m^n n \log m (\log n + \log\log m))$ /// /// $M(n, m) = O(m^n n \log m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `options.base`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::FromSciStringOptions; /// use malachite_base::num::conversion::traits::FromSciString; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from_sci_string("123").unwrap(), 123); /// assert_eq!(Integer::from_sci_string("123.5").unwrap(), 124); /// assert_eq!(Integer::from_sci_string("-123.5").unwrap(), -124); /// assert_eq!(Integer::from_sci_string("1.23e10").unwrap(), 12300000000i64); /// /// let mut options = FromSciStringOptions::default(); /// assert_eq!( /// Integer::from_sci_string_with_options("123.5", options).unwrap(), /// 124 /// ); /// /// options.set_rounding_mode(Floor); /// assert_eq!( /// Integer::from_sci_string_with_options("123.5", options).unwrap(), /// 123 /// ); /// /// options = FromSciStringOptions::default(); /// options.set_base(16); /// assert_eq!( /// Integer::from_sci_string_with_options("ff", options).unwrap(), /// 255 /// ); /// ``` #[inline] fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option { from_sci_string_with_options_helper(s, options) } } ================================================ FILE: malachite-nz/src/integer/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::Neg; use core::str::FromStr; use malachite_base::num::conversion::traits::FromStringBase; impl FromStr for Integer { type Err = (); /// Converts an string to an [`Integer`]. /// /// If the string does not represent a valid [`Integer`], an `Err` is returned. To be valid, the /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`, with an optional /// leading `'-'`. Leading zeros are allowed, as is the string `"-0"`. The string `"-"` is not. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from_str("123456").unwrap(), 123456); /// assert_eq!(Integer::from_str("00123456").unwrap(), 123456); /// assert_eq!(Integer::from_str("0").unwrap(), 0); /// assert_eq!(Integer::from_str("-123456").unwrap(), -123456); /// assert_eq!(Integer::from_str("-00123456").unwrap(), -123456); /// assert_eq!(Integer::from_str("-0").unwrap(), 0); /// /// assert!(Integer::from_str("").is_err()); /// assert!(Integer::from_str("a").is_err()); /// ``` #[inline] fn from_str(s: &str) -> Result { Self::from_string_base(10, s).ok_or(()) } } impl FromStringBase for Integer { /// Converts an string, in a specified base, to an [`Integer`]. /// /// If the string does not represent a valid [`Integer`], an `Err` is returned. To be valid, the /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`, `'a'` through /// `'z'`, and `'A'` through `'Z'`, with an optional single leading `'-'` or `'+'`; and only /// characters that represent digits smaller than the base are allowed. Leading zeros are /// allowed, as is the string `"-0"`. The string `"-"` is not. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::FromStringBase; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from_string_base(10, "123456").unwrap(), 123456); /// assert_eq!(Integer::from_string_base(10, "00123456").unwrap(), 123456); /// assert_eq!(Integer::from_string_base(16, "0").unwrap(), 0); /// assert_eq!( /// Integer::from_string_base(16, "deadbeef").unwrap(), /// 3735928559i64 /// ); /// assert_eq!( /// Integer::from_string_base(16, "deAdBeEf").unwrap(), /// 3735928559i64 /// ); /// assert_eq!(Integer::from_string_base(10, "-123456").unwrap(), -123456); /// assert_eq!(Integer::from_string_base(10, "-00123456").unwrap(), -123456); /// assert_eq!(Integer::from_string_base(16, "-0").unwrap(), 0); /// assert_eq!( /// Integer::from_string_base(16, "-deadbeef").unwrap(), /// -3735928559i64 /// ); /// assert_eq!( /// Integer::from_string_base(16, "-deAdBeEf").unwrap(), /// -3735928559i64 /// ); /// /// assert!(Integer::from_string_base(10, "").is_none()); /// assert!(Integer::from_string_base(10, "a").is_none()); /// assert!(Integer::from_string_base(2, "2").is_none()); /// assert!(Integer::from_string_base(2, "-2").is_none()); /// ``` #[inline] fn from_string_base(base: u8, s: &str) -> Option { if let Some(abs_string) = s.strip_prefix('-') { if abs_string.starts_with('+') { None } else { Natural::from_string_base(base, abs_string).map(Neg::neg) } } else { Natural::from_string_base(base, s).map(Self::from) } } } ================================================ FILE: malachite-nz/src/integer/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`FromSciString`](malachite_base::num::conversion::traits::FromSciString). /// This is a trait for converting strings, possibly using scientific notation, to numbers. pub mod from_sci_string; /// Implementations of [`FromStr`](core::str::FromStr) and of /// [`FromStringBase`](malachite_base::num::conversion::traits::FromStringBase), a trait for /// converting strings in a specified base to numbers. pub mod from_string; /// Implementations of [`ToSci`](malachite_base::num::conversion::traits::ToSci), a trait for /// converting a number to string, possibly using scientific notation. pub mod to_sci; /// Implementations of [`Display`](core::fmt::Display), [`Debug`], [`Binary`](core::fmt::Binary), /// [`Octal`](core::fmt::Octal), [`LowerHex`](core::fmt::LowerHex), and /// [`UpperHex`](core::fmt::UpperHex), and of the /// [`ToStringBase`](malachite_base::num::conversion::traits::ToStringBase) trait, used for /// converting numbers to strings. pub mod to_string; ================================================ FILE: malachite-nz/src/integer/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::fmt::{Formatter, Write}; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::traits::ToSci; impl ToSci for Integer { /// Determines whether an [`Integer`] can be converted to a string using /// [`to_sci`](`Self::to_sci`) and a particular set of options. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// let mut options = ToSciOptions::default(); /// assert!(Integer::from(123).fmt_sci_valid(options)); /// assert!(Integer::from(u128::MAX).fmt_sci_valid(options)); /// // u128::MAX has more than 16 significant digits /// options.set_rounding_mode(Exact); /// assert!(!Integer::from(u128::MAX).fmt_sci_valid(options)); /// options.set_precision(50); /// assert!(Integer::from(u128::MAX).fmt_sci_valid(options)); /// ``` #[inline] fn fmt_sci_valid(&self, options: ToSciOptions) -> bool { self.unsigned_abs_ref().fmt_sci_valid(options) } /// Converts an [`Integer`] to a string using a specified base, possibly formatting the number /// using scientific notation. /// /// See [`ToSciOptions`] for details on the available options. Note that setting /// `neg_exp_threshold` has no effect, since there is never a need to use negative exponents /// when representing an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the input /// must be rounded. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(u128::MAX).to_sci().to_string(), /// "3.402823669209385e38" /// ); /// assert_eq!( /// Integer::from(i128::MIN).to_sci().to_string(), /// "-1.701411834604692e38" /// ); /// /// let n = Integer::from(123456u32); /// let mut options = ToSciOptions::default(); /// assert_eq!(n.to_sci_with_options(options).to_string(), "123456"); /// /// options.set_precision(3); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.23e5"); /// /// options.set_rounding_mode(Ceiling); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24e5"); /// /// options.set_e_uppercase(); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E5"); /// /// options.set_force_exponent_plus_sign(true); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E+5"); /// /// options = ToSciOptions::default(); /// options.set_base(36); /// assert_eq!(n.to_sci_with_options(options).to_string(), "2n9c"); /// /// options.set_uppercase(); /// assert_eq!(n.to_sci_with_options(options).to_string(), "2N9C"); /// /// options.set_base(2); /// options.set_precision(10); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.1110001e16"); /// /// options.set_include_trailing_zeros(true); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.111000100e16"); /// ``` fn fmt_sci(&self, f: &mut Formatter, mut options: ToSciOptions) -> core::fmt::Result { let abs = self.unsigned_abs_ref(); if *self >= 0u32 { abs.fmt_sci(f, options) } else { options.set_rounding_mode(-options.get_rounding_mode()); f.write_char('-')?; abs.fmt_sci(f, options) } } } ================================================ FILE: malachite-nz/src/integer/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::conversion::string::to_string::BaseFmtWrapper; use alloc::string::String; use alloc::string::ToString; use core::fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, Result, UpperHex, Write}; use malachite_base::num::conversion::string::to_string::{ digit_to_display_byte_lower, digit_to_display_byte_upper, }; use malachite_base::num::conversion::traits::{Digits, ToStringBase}; use malachite_base::vecs::vec_pad_left; impl Display for BaseFmtWrapper<&Integer> { /// Writes a wrapped [`Integer`] to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. Using the /// `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// /// let n = Integer::from(-1000000000); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{}", x), "-gjdgxs"); /// assert_eq!(format!("{:#}", x), "-GJDGXS"); /// assert_eq!(format!("{:010}", x), "-000gjdgxs"); /// assert_eq!(format!("{:#010}", x), "-000GJDGXS"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if !self.x.sign { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$}", &BaseFmtWrapper::new(self.x.unsigned_abs_ref(), self.base), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$}", &BaseFmtWrapper::new(self.x.unsigned_abs_ref(), self.base), width = width.saturating_sub(1) ) }; } } Display::fmt( &BaseFmtWrapper::new(self.x.unsigned_abs_ref(), self.base), f, ) } } impl Debug for BaseFmtWrapper<&Integer> { /// Writes a wrapped [`Integer`] to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. Using the /// `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// /// let n = Integer::from(-1000000000); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{:?}", x), "-gjdgxs"); /// assert_eq!(format!("{:#?}", x), "-GJDGXS"); /// assert_eq!(format!("{:010?}", x), "-000gjdgxs"); /// assert_eq!(format!("{:#010?}", x), "-000GJDGXS"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl ToStringBase for Integer { /// Converts an [`Integer`] to a [`String`] using a specified base. /// /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`. Digits from 10 to 35 become the /// lowercase [`char`]s `'a'` to `'z'`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(1000).to_string_base(2), "1111101000"); /// assert_eq!(Integer::from(1000).to_string_base(10), "1000"); /// assert_eq!(Integer::from(1000).to_string_base(36), "rs"); /// /// assert_eq!(Integer::from(-1000).to_string_base(2), "-1111101000"); /// assert_eq!(Integer::from(-1000).to_string_base(10), "-1000"); /// assert_eq!(Integer::from(-1000).to_string_base(36), "-rs"); /// ``` fn to_string_base(&self, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if *self == 0 { "0".to_string() } else { let mut digits = self.unsigned_abs_ref().to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } if *self < 0 { vec_pad_left(&mut digits, 1, b'-'); } String::from_utf8(digits).unwrap() } } /// Converts an [`Integer`] to a [`String`] using a specified base. /// /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`. Digits from 10 to 35 become the /// uppercase [`char`]s `'A'` to `'Z'`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(1000).to_string_base_upper(2), "1111101000"); /// assert_eq!(Integer::from(1000).to_string_base_upper(10), "1000"); /// assert_eq!(Integer::from(1000).to_string_base_upper(36), "RS"); /// /// assert_eq!(Integer::from(-1000).to_string_base_upper(2), "-1111101000"); /// assert_eq!(Integer::from(-1000).to_string_base_upper(10), "-1000"); /// assert_eq!(Integer::from(-1000).to_string_base_upper(36), "-RS"); /// ``` fn to_string_base_upper(&self, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if *self == 0 { "0".to_string() } else { let mut digits = self.unsigned_abs_ref().to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } if *self < 0 { vec_pad_left(&mut digits, 1, b'-'); } String::from_utf8(digits).unwrap() } } } impl Display for Integer { /// Converts an [`Integer`] to a [`String`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_string(), "0"); /// /// assert_eq!(Integer::from(123).to_string(), "123"); /// assert_eq!( /// Integer::from_str("1000000000000").unwrap().to_string(), /// "1000000000000" /// ); /// assert_eq!(format!("{:05}", Integer::from(123)), "00123"); /// /// assert_eq!(Integer::from(-123).to_string(), "-123"); /// assert_eq!( /// Integer::from_str("-1000000000000").unwrap().to_string(), /// "-1000000000000" /// ); /// assert_eq!(format!("{:05}", Integer::from(-123)), "-0123"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if *self < 0 { f.write_char('-')?; if let Some(width) = f.width() { return write!( f, "{:0width$}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ); } } Display::fmt(self.unsigned_abs_ref(), f) } } impl Debug for Integer { /// Converts an [`Integer`] to a [`String`]. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_debug_string(), "0"); /// /// assert_eq!(Integer::from(123).to_debug_string(), "123"); /// assert_eq!( /// Integer::from_str("1000000000000") /// .unwrap() /// .to_debug_string(), /// "1000000000000" /// ); /// assert_eq!(format!("{:05?}", Integer::from(123)), "00123"); /// /// assert_eq!(Integer::from(-123).to_debug_string(), "-123"); /// assert_eq!( /// Integer::from_str("-1000000000000") /// .unwrap() /// .to_debug_string(), /// "-1000000000000" /// ); /// assert_eq!(format!("{:05?}", Integer::from(-123)), "-0123"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl Binary for Integer { /// Converts an [`Integer`] to a binary [`String`]. /// /// Using the `#` format flag prepends `"0b"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_binary_string(), "0"); /// assert_eq!(Integer::from(123).to_binary_string(), "1111011"); /// assert_eq!( /// Integer::from_str("1000000000000") /// .unwrap() /// .to_binary_string(), /// "1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:011b}", Integer::from(123)), "00001111011"); /// assert_eq!(Integer::from(-123).to_binary_string(), "-1111011"); /// assert_eq!( /// Integer::from_str("-1000000000000") /// .unwrap() /// .to_binary_string(), /// "-1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:011b}", Integer::from(-123)), "-0001111011"); /// /// assert_eq!(format!("{:#b}", Integer::ZERO), "0b0"); /// assert_eq!(format!("{:#b}", Integer::from(123)), "0b1111011"); /// assert_eq!( /// format!("{:#b}", Integer::from_str("1000000000000").unwrap()), /// "0b1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:#011b}", Integer::from(123)), "0b001111011"); /// assert_eq!(format!("{:#b}", Integer::from(-123)), "-0b1111011"); /// assert_eq!( /// format!("{:#b}", Integer::from_str("-1000000000000").unwrap()), /// "-0b1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:#011b}", Integer::from(-123)), "-0b01111011"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if *self < 0 { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$b}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$b}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) }; } } Binary::fmt(self.unsigned_abs_ref(), f) } } impl Octal for Integer { /// Converts an [`Integer`] to an octal [`String`]. /// /// Using the `#` format flag prepends `"0o"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToOctalString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_octal_string(), "0"); /// assert_eq!(Integer::from(123).to_octal_string(), "173"); /// assert_eq!( /// Integer::from_str("1000000000000") /// .unwrap() /// .to_octal_string(), /// "16432451210000" /// ); /// assert_eq!(format!("{:07o}", Integer::from(123)), "0000173"); /// assert_eq!(Integer::from(-123).to_octal_string(), "-173"); /// assert_eq!( /// Integer::from_str("-1000000000000") /// .unwrap() /// .to_octal_string(), /// "-16432451210000" /// ); /// assert_eq!(format!("{:07o}", Integer::from(-123)), "-000173"); /// /// assert_eq!(format!("{:#o}", Integer::ZERO), "0o0"); /// assert_eq!(format!("{:#o}", Integer::from(123)), "0o173"); /// assert_eq!( /// format!("{:#o}", Integer::from_str("1000000000000").unwrap()), /// "0o16432451210000" /// ); /// assert_eq!(format!("{:#07o}", Integer::from(123)), "0o00173"); /// assert_eq!(format!("{:#o}", Integer::from(-123)), "-0o173"); /// assert_eq!( /// format!("{:#o}", Integer::from_str("-1000000000000").unwrap()), /// "-0o16432451210000" /// ); /// assert_eq!(format!("{:#07o}", Integer::from(-123)), "-0o0173"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if *self < 0 { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$o}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$o}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) }; } } Octal::fmt(self.unsigned_abs_ref(), f) } } impl LowerHex for Integer { /// Converts an [`Integer`] to a hexadecimal [`String`] using lowercase characters. /// /// Using the `#` format flag prepends `"0x"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToLowerHexString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_lower_hex_string(), "0"); /// assert_eq!(Integer::from(123).to_lower_hex_string(), "7b"); /// assert_eq!( /// Integer::from_str("1000000000000") /// .unwrap() /// .to_lower_hex_string(), /// "e8d4a51000" /// ); /// assert_eq!(format!("{:07x}", Integer::from(123)), "000007b"); /// assert_eq!(Integer::from(-123).to_lower_hex_string(), "-7b"); /// assert_eq!( /// Integer::from_str("-1000000000000") /// .unwrap() /// .to_lower_hex_string(), /// "-e8d4a51000" /// ); /// assert_eq!(format!("{:07x}", Integer::from(-123)), "-00007b"); /// /// assert_eq!(format!("{:#x}", Integer::ZERO), "0x0"); /// assert_eq!(format!("{:#x}", Integer::from(123)), "0x7b"); /// assert_eq!( /// format!("{:#x}", Integer::from_str("1000000000000").unwrap()), /// "0xe8d4a51000" /// ); /// assert_eq!(format!("{:#07x}", Integer::from(123)), "0x0007b"); /// assert_eq!(format!("{:#x}", Integer::from(-123)), "-0x7b"); /// assert_eq!( /// format!("{:#x}", Integer::from_str("-1000000000000").unwrap()), /// "-0xe8d4a51000" /// ); /// assert_eq!(format!("{:#07x}", Integer::from(-123)), "-0x007b"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if *self < 0 { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$x}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$x}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) }; } } LowerHex::fmt(self.unsigned_abs_ref(), f) } } impl UpperHex for Integer { /// Converts an [`Integer`] to a hexadecimal [`String`] using uppercase characters. /// /// Using the `#` format flag prepends `"0x"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToUpperHexString; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.to_upper_hex_string(), "0"); /// assert_eq!(Integer::from(123).to_upper_hex_string(), "7B"); /// assert_eq!( /// Integer::from_str("1000000000000") /// .unwrap() /// .to_upper_hex_string(), /// "E8D4A51000" /// ); /// assert_eq!(format!("{:07X}", Integer::from(123)), "000007B"); /// assert_eq!(Integer::from(-123).to_upper_hex_string(), "-7B"); /// assert_eq!( /// Integer::from_str("-1000000000000") /// .unwrap() /// .to_upper_hex_string(), /// "-E8D4A51000" /// ); /// assert_eq!(format!("{:07X}", Integer::from(-123)), "-00007B"); /// /// assert_eq!(format!("{:#X}", Integer::ZERO), "0x0"); /// assert_eq!(format!("{:#X}", Integer::from(123)), "0x7B"); /// assert_eq!( /// format!("{:#X}", Integer::from_str("1000000000000").unwrap()), /// "0xE8D4A51000" /// ); /// assert_eq!(format!("{:#07X}", Integer::from(123)), "0x0007B"); /// assert_eq!(format!("{:#X}", Integer::from(-123)), "-0x7B"); /// assert_eq!( /// format!("{:#X}", Integer::from_str("-1000000000000").unwrap()), /// "-0xE8D4A51000" /// ); /// assert_eq!(format!("{:#07X}", Integer::from(-123)), "-0x007B"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if *self < 0 { f.write_char('-')?; if let Some(width) = f.width() { return if f.alternate() { write!( f, "{:#0width$X}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) } else { write!( f, "{:0width$X}", self.unsigned_abs_ref(), width = width.saturating_sub(1) ) }; } } UpperHex::fmt(self.unsigned_abs_ref(), f) } } ================================================ FILE: malachite-nz/src/integer/conversion/to_twos_complement_limbs.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::conversion::to_limbs::LimbIterator; use crate::natural::logic::not::limbs_not_in_place; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{IsPowerOf2, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::slices::slice_leading_zeros; // Given the limbs of the absolute value of an `Integer`, in ascending order, returns the two's // complement limbs. The input limbs should not be all zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_twos_complement(xs: &[Limb]) -> Vec { let i = slice_leading_zeros(xs); let mut result = vec![0; i]; if i != xs.len() { result.push(xs[i].wrapping_neg()); for x in &xs[i + 1..] { result.push(!x); } } result }} // Given the limbs of a non-negative `Integer`, in ascending order, checks whether the most // significant bit is `false`; if it isn't, appends an extra zero bit. This way the `Integer`'s // non-negativity is preserved in its limbs. // // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_maybe_sign_extend_non_negative_in_place(xs: &mut Vec) { if let Some(last) = xs.last() && last.get_highest_bit() { // Sign-extend with an extra 0 limb to indicate a positive Integer xs.push(0); } }} // Given the limbs of the absolute value of an `Integer`, in ascending order, converts the limbs to // two's complement. Returns whether there is a carry left over from the two's complement conversion // process. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_twos_complement_in_place(xs: &mut [Limb]) -> bool { limbs_not_in_place(xs); limbs_slice_add_limb_in_place(xs, 1) }} // Given the limbs of the absolute value of a negative `Integer`, in ascending order, converts the // limbs to two's complement and checks whether the most significant bit is `true`; if it isn't, // appends an extra `Limb::MAX` bit. This way the `Integer`'s negativity is preserved in its limbs. // The limbs cannot be empty or contain only zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` contains only zeros. pub_test! {limbs_twos_complement_and_maybe_sign_extend_negative_in_place(xs: &mut Vec) { assert!(!limbs_twos_complement_in_place(xs)); if let Some(last) = xs.last() && !last.get_highest_bit() { // Sign-extend with an extra !0 limb to indicate a negative Integer xs.push(Limb::MAX); } }} #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct NegativeLimbIterator<'a>(NLIterator<'a>); // A double-ended iterator over the two's complement [limbs](crate#limbs) of the negative of an // [`Integer`]. // // The forward order is ascending (least-significant first). There may be at most one // most-significant `Limb::MAX` limb. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct NLIterator<'a> { pub(crate) limbs: LimbIterator<'a>, first_nonzero_index: Option, } impl NLIterator<'_> { fn get_limb(&self, index: u64) -> Limb { let index = usize::exact_from(index); if index >= self.limbs.len() { // We're indexing into the infinite suffix of Limb::MAXs Limb::MAX } else { for i in 0..index { if self.limbs[i] != 0 { return !self.limbs[index]; } } self.limbs[index].wrapping_neg() } } } impl Iterator for NLIterator<'_> { type Item = Limb; // A function to iterate through the two's complement limbs of the negative of a `Natural` in // ascending order (least-significant first). // // # Worst-case complexity // Constant time and additional memory. fn next(&mut self) -> Option { let previous_i = self.limbs.i; self.limbs.next().map(|limb| { if let Some(first_nonzero_index) = self.first_nonzero_index { if previous_i <= u64::wrapping_from(first_nonzero_index) { limb.wrapping_neg() } else { !limb } } else { if limb != 0 { self.first_nonzero_index = Some(usize::exact_from(previous_i)); } limb.wrapping_neg() } }) } // A function that returns the length of the negative limbs iterator; that is, the `Natural`'s // negative limb count (this is the same as its limb count). The format is (lower bound, // Option), but in this case it's trivial to always have an exact bound. // // # Worst-case complexity // Constant time and additional memory. #[inline] fn size_hint(&self) -> (usize, Option) { self.limbs.size_hint() } } impl DoubleEndedIterator for NLIterator<'_> { // A function to iterate through the two's complement limbs of the negative of a `Natural` in // descending order (most-significant first). This is worst-case linear since the first // `next_back` call needs to determine the index of the least-significant nonzero limb. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. fn next_back(&mut self) -> Option { let previous_j = self.limbs.j; self.limbs.next_back().map(|limb| { if self.first_nonzero_index.is_none() { let mut i = 0; while self.limbs[i] == 0 { i += 1; } self.first_nonzero_index = Some(i); } let first_nonzero_index = self.first_nonzero_index.unwrap(); if previous_j <= u64::wrapping_from(first_nonzero_index) { limb.wrapping_neg() } else { !limb } }) } } trait SignExtendedLimbIterator: DoubleEndedIterator { const EXTENSION: Limb; fn needs_sign_extension(&self) -> bool; fn iterate_forward(&mut self, extension_checked: &mut bool) -> Option { let next = self.next(); if next.is_none() { if *extension_checked { None } else { *extension_checked = true; if self.needs_sign_extension() { Some(Self::EXTENSION) } else { None } } } else { next } } fn iterate_backward(&mut self, extension_checked: &mut bool) -> Option { if !*extension_checked { *extension_checked = true; if self.needs_sign_extension() { return Some(Self::EXTENSION); } } self.next_back() } } impl SignExtendedLimbIterator for LimbIterator<'_> { const EXTENSION: Limb = 0; fn needs_sign_extension(&self) -> bool { self[self.limb_count - 1].get_highest_bit() } } impl SignExtendedLimbIterator for NLIterator<'_> { const EXTENSION: Limb = Limb::MAX; fn needs_sign_extension(&self) -> bool { let mut i = 0; while self.limbs[i] == 0 { i += 1; } let last_limb_index = self.limbs.limb_count - 1; let last_limb = self.limbs[last_limb_index]; let twos_complement_limb = if i == last_limb_index { last_limb.wrapping_neg() } else { !last_limb }; !twos_complement_limb.get_highest_bit() } } /// A double-ended iterator over the twos-complement [limbs](crate#limbs) of an [`Integer`]. /// /// The forward order is ascending (least-significant first). The most significant bit of the most /// significant limb corresponds to the sign of the [`Integer`]; `false` for non-negative and `true` /// for negative. This means that there may be a single most-significant sign-extension limb that is /// 0 or `Limb::MAX`. /// /// This struct also supports retrieving limbs by index. This functionality is completely /// independent of the iterator's state. Indexing the implicit leading limbs is allowed. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum TwosComplementLimbIterator<'a> { Zero, Positive(LimbIterator<'a>, bool), Negative(NegativeLimbIterator<'a>, bool), } impl TwosComplementLimbIterator<'_> { /// A function to retrieve twos-complement [limbs](crate#limbs) by index. Indexing at or above /// the limb count returns zero or `Limb::MAX` limbs, depending on the sign of the `[Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::ZERO.twos_complement_limbs().get_limb(0), 0); /// /// // 2^64 - 10^12 = 4294967063 * 2^32 + 727379968 /// let negative_trillion = -Integer::from(10u32).pow(12); /// let limbs = negative_trillion.twos_complement_limbs(); /// assert_eq!(limbs.get_limb(0), 727379968); /// assert_eq!(limbs.get_limb(1), 4294967063); /// assert_eq!(limbs.get_limb(2), 4294967295); /// assert_eq!(limbs.get_limb(100), 4294967295); /// } /// ``` pub fn get_limb(&self, index: u64) -> Limb { match self { Self::Zero => 0, Self::Positive(limbs, _) => limbs[usize::exact_from(index)], Self::Negative(limbs, _) => limbs.0.get_limb(index), } } } impl Iterator for TwosComplementLimbIterator<'_> { type Item = Limb; /// A function to iterate through the twos-complement [limbs](crate#limbs) of an [`Integer`] in /// ascending order (least-significant first). The last limb may be a sign-extension limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::ZERO.twos_complement_limbs().next(), None); /// /// // 2^64 - 10^12 = 4294967063 * 2^32 + 727379968 /// let negative_trillion = -Integer::from(10u32).pow(12); /// let mut limbs = negative_trillion.twos_complement_limbs(); /// assert_eq!(limbs.next(), Some(727379968)); /// assert_eq!(limbs.next(), Some(4294967063)); /// assert_eq!(limbs.next(), None); /// } /// ``` fn next(&mut self) -> Option { match self { Self::Zero => None, Self::Positive(limbs, extension_checked) => limbs.iterate_forward(extension_checked), Self::Negative(limbs, extension_checked) => limbs.0.iterate_forward(extension_checked), } } } impl DoubleEndedIterator for TwosComplementLimbIterator<'_> { /// A function to iterate through the twos-complement [limbs](crate#limbs) of an [`Integer`] in /// descending order (most-significant first). The first limb may be a sign-extension limb. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::ZERO.twos_complement_limbs().next_back(), None); /// /// // 2^64 - 10^12 = 4294967063 * 2^32 + 727379968 /// let negative_trillion = -Integer::from(10u32).pow(12); /// let mut limbs = negative_trillion.twos_complement_limbs(); /// assert_eq!(limbs.next_back(), Some(4294967063)); /// assert_eq!(limbs.next_back(), Some(727379968)); /// assert_eq!(limbs.next_back(), None); /// } /// ``` fn next_back(&mut self) -> Option { match self { Self::Zero => None, Self::Positive(limbs, extension_checked) => limbs.iterate_backward(extension_checked), Self::Negative(limbs, extension_checked) => limbs.0.iterate_backward(extension_checked), } } } impl Natural { /// Returns a double-ended iterator over the two's complement limbs of the negative of a /// [`Natural`]. The forward order is ascending, so that less significant limbs appear first. /// There may be at most one trailing `Limb::MAX` limb going forward, or leading `Limb::MAX` /// limb going backward. The [`Natural`] cannot be zero. /// /// # Worst-case complexity /// Constant time and additional memory. fn negative_limbs(&self) -> NegativeLimbIterator<'_> { assert_ne!(*self, 0, "Cannot get negative limbs of 0."); NegativeLimbIterator(NLIterator { limbs: self.limbs(), first_nonzero_index: None, }) } } impl Integer { /// Returns the [limbs](crate#limbs) of an [`Integer`], in ascending order, so that less /// significant limbs have lower indices in the output vector. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is positive, and if the bit is one it is negative. /// There are no trailing zero limbs if the [`Integer`] is positive or trailing `Limb::MAX` /// limbs if the [`Integer`] is negative, except as necessary to include the correct sign bit. /// Zero is a special case: it contains no limbs. /// /// This function borrows `self`. If taking ownership of `self` is possible, /// [`into_twos_complement_limbs_asc`](`Self::into_twos_complement_limbs_asc`) is more /// efficient. /// /// This function is more efficient than /// [`to_twos_complement_limbs_desc`](`Self::to_twos_complement_limbs_desc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Integer::ZERO.to_twos_complement_limbs_asc().is_empty()); /// assert_eq!(Integer::from(123).to_twos_complement_limbs_asc(), &[123]); /// assert_eq!( /// Integer::from(-123).to_twos_complement_limbs_asc(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32).pow(12).to_twos_complement_limbs_asc(), /// &[3567587328, 232] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).to_twos_complement_limbs_asc(), /// &[727379968, 4294967063] /// ); /// } /// ``` pub fn to_twos_complement_limbs_asc(&self) -> Vec { let mut limbs = self.abs.to_limbs_asc(); if self.sign { limbs_maybe_sign_extend_non_negative_in_place(&mut limbs); } else { limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut limbs); } limbs } /// Returns the [limbs](crate#limbs) of an [`Integer`], in descending order, so that less /// significant limbs have higher indices in the output vector. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is positive, and if the bit is one it is negative. /// There are no leading zero limbs if the [`Integer`] is non-negative or leading `Limb::MAX` /// limbs if the [`Integer`] is negative, except as necessary to include the correct sign bit. /// Zero is a special case: it contains no limbs. /// /// This is similar to how `BigInteger`s in Java are represented. /// /// This function borrows `self`. If taking ownership of `self` is possible, /// [`into_twos_complement_limbs_desc`](`Self::into_twos_complement_limbs_desc`) is more /// efficient. /// /// This function is less efficient than /// [`to_twos_complement_limbs_asc`](`Self::to_twos_complement_limbs_asc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Integer::ZERO.to_twos_complement_limbs_desc().is_empty()); /// assert_eq!(Integer::from(123).to_twos_complement_limbs_desc(), &[123]); /// assert_eq!( /// Integer::from(-123).to_twos_complement_limbs_desc(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32).pow(12).to_twos_complement_limbs_desc(), /// &[232, 3567587328] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).to_twos_complement_limbs_desc(), /// &[4294967063, 727379968] /// ); /// } /// ``` pub fn to_twos_complement_limbs_desc(&self) -> Vec { let mut xs = self.to_twos_complement_limbs_asc(); xs.reverse(); xs } /// Returns the [limbs](crate#limbs) of an [`Integer`], in ascending order, so that less /// significant limbs have lower indices in the output vector. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is positive, and if the bit is one it is negative. /// There are no trailing zero limbs if the [`Integer`] is positive or trailing `Limb::MAX` /// limbs if the [`Integer`] is negative, except as necessary to include the correct sign bit. /// Zero is a special case: it contains no limbs. /// /// This function takes ownership of `self`. If it's necessary to borrow `self` instead, use /// [`to_twos_complement_limbs_asc`](`Self::to_twos_complement_limbs_asc`). /// /// This function is more efficient than /// [`into_twos_complement_limbs_desc`](`Self::into_twos_complement_limbs_desc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Integer::ZERO.into_twos_complement_limbs_asc().is_empty()); /// assert_eq!(Integer::from(123).into_twos_complement_limbs_asc(), &[123]); /// assert_eq!( /// Integer::from(-123).into_twos_complement_limbs_asc(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32) /// .pow(12) /// .into_twos_complement_limbs_asc(), /// &[3567587328, 232] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).into_twos_complement_limbs_asc(), /// &[727379968, 4294967063] /// ); /// } /// ``` pub fn into_twos_complement_limbs_asc(self) -> Vec { let mut xs = self.abs.into_limbs_asc(); if self.sign { limbs_maybe_sign_extend_non_negative_in_place(&mut xs); } else { limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut xs); } xs } /// Returns the [limbs](crate#limbs) of an [`Integer`], in descending order, so that less /// significant limbs have higher indices in the output vector. /// /// The limbs are in two's complement, and the most significant bit of the limbs indicates the /// sign; if the bit is zero, the [`Integer`] is positive, and if the bit is one it is negative. /// There are no leading zero limbs if the [`Integer`] is non-negative or leading `Limb::MAX` /// limbs if the [`Integer`] is negative, except as necessary to include the correct sign bit. /// Zero is a special case: it contains no limbs. /// /// This is similar to how `BigInteger`s in Java are represented. /// /// This function takes ownership of `self`. If it's necessary to borrow `self` instead, use /// [`to_twos_complement_limbs_desc`](`Self::to_twos_complement_limbs_desc`). /// /// This function is less efficient than /// [`into_twos_complement_limbs_asc`](`Self::into_twos_complement_limbs_asc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Integer::ZERO.into_twos_complement_limbs_desc().is_empty()); /// assert_eq!(Integer::from(123).into_twos_complement_limbs_desc(), &[123]); /// assert_eq!( /// Integer::from(-123).into_twos_complement_limbs_desc(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32) /// .pow(12) /// .into_twos_complement_limbs_desc(), /// &[232, 3567587328] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)).into_twos_complement_limbs_desc(), /// &[4294967063, 727379968] /// ); /// } /// ``` pub fn into_twos_complement_limbs_desc(self) -> Vec { let mut xs = self.into_twos_complement_limbs_asc(); xs.reverse(); xs } /// Returns a double-ended iterator over the twos-complement [limbs](crate#limbs) of an /// [`Integer`]. /// /// The forward order is ascending, so that less significant limbs appear first. There may be a /// most-significant sign-extension limb. /// /// If it's necessary to get a [`Vec`] of all the twos_complement limbs, consider using /// [`to_twos_complement_limbs_asc`](`Self::to_twos_complement_limbs_asc`), /// [`to_twos_complement_limbs_desc`](`Self::to_twos_complement_limbs_desc`), /// [`into_twos_complement_limbs_asc`](`Self::into_twos_complement_limbs_asc`), or /// [`into_twos_complement_limbs_desc`](`Self::into_twos_complement_limbs_desc`) instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Integer::ZERO.twos_complement_limbs().next().is_none()); /// assert_eq!( /// Integer::from(123).twos_complement_limbs().collect_vec(), /// &[123] /// ); /// assert_eq!( /// Integer::from(-123).twos_complement_limbs().collect_vec(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32) /// .pow(12) /// .twos_complement_limbs() /// .collect_vec(), /// &[3567587328, 232] /// ); /// // Sign-extension for a non-negative `Integer` /// assert_eq!( /// Integer::from(4294967295i64) /// .twos_complement_limbs() /// .collect_vec(), /// &[4294967295, 0] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .twos_complement_limbs() /// .collect_vec(), /// &[727379968, 4294967063] /// ); /// // Sign-extension for a negative `Integer` /// assert_eq!( /// (-Integer::from(4294967295i64)) /// .twos_complement_limbs() /// .collect_vec(), /// &[1, 4294967295] /// ); /// /// assert!(Integer::ZERO.twos_complement_limbs().next_back().is_none()); /// assert_eq!( /// Integer::from(123) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[123] /// ); /// assert_eq!( /// Integer::from(-123) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[4294967173] /// ); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Integer::from(10u32) /// .pow(12) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[232, 3567587328] /// ); /// // Sign-extension for a non-negative `Integer` /// assert_eq!( /// Integer::from(4294967295i64) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[0, 4294967295] /// ); /// assert_eq!( /// (-Integer::from(10u32).pow(12)) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[4294967063, 727379968] /// ); /// // Sign-extension for a negative `Integer` /// assert_eq!( /// (-Integer::from(4294967295i64)) /// .twos_complement_limbs() /// .rev() /// .collect_vec(), /// &[4294967295, 1] /// ); /// } /// ``` pub fn twos_complement_limbs(&self) -> TwosComplementLimbIterator<'_> { if *self == 0 { TwosComplementLimbIterator::Zero } else if self.sign { TwosComplementLimbIterator::Positive(self.abs.limbs(), false) } else { TwosComplementLimbIterator::Negative(self.abs.negative_limbs(), false) } } /// Returns the number of twos-complement limbs of an [`Integer`]. There may be a /// most-significant sign-extension limb, which is included in the count. /// /// Zero has 0 limbs. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, PowerOf2}; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::integer::Integer; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Integer::ZERO.twos_complement_limb_count(), 0); /// assert_eq!(Integer::from(123u32).twos_complement_limb_count(), 1); /// assert_eq!(Integer::from(10u32).pow(12).twos_complement_limb_count(), 2); /// /// let n = Integer::power_of_2(Limb::WIDTH - 1); /// assert_eq!((&n - Integer::ONE).twos_complement_limb_count(), 1); /// assert_eq!(n.twos_complement_limb_count(), 2); /// assert_eq!((&n + Integer::ONE).twos_complement_limb_count(), 2); /// assert_eq!((-(&n - Integer::ONE)).twos_complement_limb_count(), 1); /// assert_eq!((-&n).twos_complement_limb_count(), 1); /// assert_eq!((-(&n + Integer::ONE)).twos_complement_limb_count(), 2); /// } /// ``` pub fn twos_complement_limb_count(&self) -> u64 { if *self == 0 { return 0; } let abs_limbs_count = self.unsigned_abs_ref().limb_count(); let highest_bit_of_highest_limb = self.unsigned_abs().limbs()[usize::exact_from(abs_limbs_count - 1)].get_highest_bit(); if highest_bit_of_highest_limb && (*self > 0 || (*self < 0 && !self.unsigned_abs_ref().is_power_of_2())) { abs_limbs_count + 1 } else { abs_limbs_count } } } ================================================ FILE: malachite-nz/src/integer/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use core::iter::{Chain, Once, Rev, once}; use itertools::{Interleave, Itertools}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; /// Generates all [`Integer`]s in a finite interval, in ascending order. /// /// This `struct` is created by the [`integer_increasing_range`] and /// [`integer_increasing_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IntegerIncreasingRange { a: Integer, b: Integer, } impl Iterator for IntegerIncreasingRange { type Item = Integer; fn next(&mut self) -> Option { if self.a == self.b { None } else { let result = self.a.clone(); self.a += Integer::ONE; Some(result) } } } impl DoubleEndedIterator for IntegerIncreasingRange { fn next_back(&mut self) -> Option { if self.a == self.b { None } else { self.b -= Integer::ONE; Some(self.b.clone()) } } } /// Generates all [`Integer`]s greater than or equal to some [`Integer`], in ascending order. /// /// This `struct` is created by [`integer_increasing_range_to_infinity`]; see its documentation for /// more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IntegerIncreasingRangeToInfinity { a: Integer, } impl Iterator for IntegerIncreasingRangeToInfinity { type Item = Integer; fn next(&mut self) -> Option { let result = self.a.clone(); self.a += Integer::ONE; Some(result) } } /// Generates all [`Integer`]s less than or equal to some [`Integer`], in ascending order. /// /// This `struct` is created by [`integer_decreasing_range_to_negative_infinity`]; see its /// documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IntegerDecreasingRangeToNegativeInfinity { a: Integer, } impl Iterator for IntegerDecreasingRangeToNegativeInfinity { type Item = Integer; fn next(&mut self) -> Option { let result = self.a.clone(); self.a -= Integer::ONE; Some(result) } } /// Generates all [`Integer`]s in a finite interval, in order of increasing absolute value. /// /// This `struct` is created [`exhaustive_integer_range`] and /// [`exhaustive_integer_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug)] pub enum ExhaustiveIntegerRange { NonNegative(IntegerIncreasingRange), NonPositive(Rev), BothSigns( Chain, Interleave>>, ), } impl Iterator for ExhaustiveIntegerRange { type Item = Integer; fn next(&mut self) -> Option { match self { Self::NonNegative(xs) => xs.next(), Self::NonPositive(xs) => xs.next(), Self::BothSigns(xs) => xs.next(), } } } /// Generates all [`Integer`]s greater than or equal to some [`Integer`], in order of increasing /// absolute value. /// /// This `struct` is created by [`exhaustive_integer_range_to_infinity`]; see its documentation for /// more. #[derive(Clone, Debug)] pub enum ExhaustiveIntegerRangeToInfinity { NonNegative(IntegerIncreasingRangeToInfinity), BothSigns( Chain< Once, Interleave>, >, ), } impl Iterator for ExhaustiveIntegerRangeToInfinity { type Item = Integer; fn next(&mut self) -> Option { match self { Self::NonNegative(xs) => xs.next(), Self::BothSigns(xs) => xs.next(), } } } /// Generates all [`Integer`]s less than or equal to some [`Integer`], in order of increasing /// absolute value. /// /// This `struct` is created by [`exhaustive_integer_range_to_negative_infinity`]; see its /// documentation for more. #[derive(Clone, Debug)] pub enum ExhaustiveIntegerRangeToNegativeInfinity { NonPositive(IntegerDecreasingRangeToNegativeInfinity), BothSigns( Chain< Once, Interleave, >, ), } impl Iterator for ExhaustiveIntegerRangeToNegativeInfinity { type Item = Integer; fn next(&mut self) -> Option { match self { Self::NonPositive(xs) => xs.next(), Self::BothSigns(xs) => xs.next(), } } } #[doc(hidden)] pub type IntegerUpDown = Interleave; /// Generates all [`Integer`]s, in order of increasing absolute value. When two [`Integer`]s have /// the same absolute value, the positive one comes first. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(1)$, amortized. /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_integers; /// /// assert_eq!( /// prefix_to_string(exhaustive_integers(), 10), /// "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, ...]" /// ) /// ``` #[inline] pub fn exhaustive_integers() -> Chain, IntegerUpDown> { once(Integer::ZERO).chain(exhaustive_nonzero_integers()) } /// Generates all natural [`Integer`]s in ascending order. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(1)$, amortized. /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_natural_integers; /// /// assert_eq!( /// prefix_to_string(exhaustive_natural_integers(), 10), /// "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_natural_integers() -> IntegerIncreasingRangeToInfinity { integer_increasing_range_to_infinity(Integer::ZERO) } /// Generates all positive [`Integer`]s in ascending order. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(1)$, amortized. /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_positive_integers; /// /// assert_eq!( /// prefix_to_string(exhaustive_positive_integers(), 10), /// "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_positive_integers() -> IntegerIncreasingRangeToInfinity { integer_increasing_range_to_infinity(Integer::ONE) } /// Generates all negative [`Integer`]s in descending order. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(1)$, amortized. /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_negative_integers; /// /// assert_eq!( /// prefix_to_string(exhaustive_negative_integers(), 10), /// "[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_negative_integers() -> IntegerDecreasingRangeToNegativeInfinity { integer_decreasing_range_to_negative_infinity(Integer::NEGATIVE_ONE) } /// Generates all nonzero [`Integer`]s, in order of increasing absolute value. When two [`Integer`]s /// have the same absolute value, the positive one comes first. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(1)$, amortized. /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_nonzero_integers; /// /// assert_eq!( /// prefix_to_string(exhaustive_nonzero_integers(), 10), /// "[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, ...]" /// ) /// ``` #[inline] pub fn exhaustive_nonzero_integers() -> IntegerUpDown { exhaustive_positive_integers().interleave(exhaustive_negative_integers()) } /// Generates all [`Integer`]s in the half-open interval $[a, b)$, in ascending order. /// /// $a$ must be less than or equal to $b$. If $a$ and $b$ are equal, the range is empty. To generate /// all [`Integer`]s in an infinite interval in ascending or descending order, use /// [`integer_increasing_range_to_infinity`] or [`integer_decreasing_range_to_negative_infinity`]. /// /// The output is $(k)_{k=a}^{b-1}$. /// /// The output length is $b - a$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is positive and its /// least-significant limb is `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::exhaustive::integer_increasing_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// integer_increasing_range(Integer::from(-4), Integer::from(4)) /// .collect_vec() /// .to_debug_string(), /// "[-4, -3, -2, -1, 0, 1, 2, 3]" /// ) /// ``` #[inline] pub fn integer_increasing_range(a: Integer, b: Integer) -> IntegerIncreasingRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); IntegerIncreasingRange { a, b } } /// Generates all [`Integer`]s in the closed interval $[a, b]$, in ascending order. /// /// $a$ must be less than or equal to $b$. If $a$ and $b$ are equal, the range contains a single /// element. To generate all [`Integer`]s in an infinite interval in ascending or descending order, /// use [`integer_increasing_range_to_infinity`] or /// [`integer_decreasing_range_to_negative_infinity`]. /// /// The output is $(k)_{k=a}^{b}$. /// /// The output length is $b - a + 1$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is positive and its /// least-significant limb is `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::exhaustive::integer_increasing_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// integer_increasing_inclusive_range(Integer::from(-4), Integer::from(4)) /// .collect_vec() /// .to_debug_string(), /// "[-4, -3, -2, -1, 0, 1, 2, 3, 4]" /// ) /// ``` #[inline] pub fn integer_increasing_inclusive_range(a: Integer, b: Integer) -> IntegerIncreasingRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); IntegerIncreasingRange { a, b: b + Integer::ONE, } } /// Generates all [`Integer`]s greater than or equal to some number $a$, in ascending order. /// /// The output is $(k)_{k=a}^{\infty}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is positive and its /// least-significant limb is `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::integer_increasing_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string(integer_increasing_range_to_infinity(Integer::from(-4)), 10), /// "[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, ...]" /// ) /// ``` #[inline] pub const fn integer_increasing_range_to_infinity(a: Integer) -> IntegerIncreasingRangeToInfinity { IntegerIncreasingRangeToInfinity { a } } /// Generates all [`Integer`]s less than or equal to some number $a$, in descending order. /// /// The output is $(-k)_{k=-a}^{\infty}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is negative and the /// least-significant limb of its absolute value is `Limb::MAX`, the worst case space and time /// complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::integer_decreasing_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// integer_decreasing_range_to_negative_infinity(Integer::from(4)), /// 10 /// ), /// "[4, 3, 2, 1, 0, -1, -2, -3, -4, -5, ...]" /// ) /// ``` #[inline] pub const fn integer_decreasing_range_to_negative_infinity( a: Integer, ) -> IntegerDecreasingRangeToNegativeInfinity { IntegerDecreasingRangeToNegativeInfinity { a } } /// Generates all [`Integer`]s in the half-open interval $[a, b)$, in order of increasing absolute /// value. /// /// When two [`Integer`]s have the same absolute value, the positive one comes first. $a$ must be /// less than or equal to $b$. If $a$ and $b$ are equal, the range is empty. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [0, b - a)$ and $i < j$. /// /// The output length is $b - a$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the least-significant limb of the absolute value of the /// previously-generated value is `Limb::MAX`, the worst case space and time complexities are /// constant. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::exhaustive::exhaustive_integer_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// exhaustive_integer_range(Integer::from(-4), Integer::from(4)) /// .collect_vec() /// .to_debug_string(), /// "[0, 1, -1, 2, -2, 3, -3, -4]" /// ) /// ``` pub fn exhaustive_integer_range(a: Integer, b: Integer) -> ExhaustiveIntegerRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= 0 { ExhaustiveIntegerRange::NonNegative(integer_increasing_range(a, b)) } else if b <= 0 { ExhaustiveIntegerRange::NonPositive(integer_increasing_range(a, b).rev()) } else { ExhaustiveIntegerRange::BothSigns( once(Integer::ZERO).chain( integer_increasing_range(Integer::ONE, b) .interleave(integer_increasing_range(a, Integer::ZERO).rev()), ), ) } } /// Generates all [`Integer`]s in the closed interval $[a, b]$, in order of increasing absolute /// value. /// /// When two [`Integer`]s have the same absolute value, the positive one comes first. $a$ must be /// less than or equal to $b$. If $a$ and $b$ are equal, the range contains a single element. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i, j \\in [0, b - a]$ and $i < j$. /// /// The output length is $b - a + 1$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the least-significant limb of the absolute value of the /// previously-generated value is `Limb::MAX`, the worst case space and time complexities are /// constant. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::exhaustive::exhaustive_integer_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// exhaustive_integer_inclusive_range(Integer::from(-4), Integer::from(4)) /// .collect_vec() /// .to_debug_string(), /// "[0, 1, -1, 2, -2, 3, -3, 4, -4]" /// ) /// ``` pub fn exhaustive_integer_inclusive_range(a: Integer, b: Integer) -> ExhaustiveIntegerRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); if a >= 0 { ExhaustiveIntegerRange::NonNegative(integer_increasing_inclusive_range(a, b)) } else if b <= 0 { ExhaustiveIntegerRange::NonPositive(integer_increasing_inclusive_range(a, b).rev()) } else { ExhaustiveIntegerRange::BothSigns( once(Integer::ZERO).chain( integer_increasing_inclusive_range(Integer::ONE, b) .interleave(integer_increasing_inclusive_range(a, Integer::NEGATIVE_ONE).rev()), ), ) } } /// Generates all [`Integer`]s greater than or equal to some number $a$, in order of increasing /// absolute value. /// /// When two [`Integer`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is positive and its /// least-significant limb is `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_integer_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string(exhaustive_integer_range_to_infinity(Integer::from(-2)), 10), /// "[0, 1, -1, 2, -2, 3, 4, 5, 6, 7, ...]" /// ) /// ``` #[inline] pub fn exhaustive_integer_range_to_infinity(a: Integer) -> ExhaustiveIntegerRangeToInfinity { if a >= 0 { ExhaustiveIntegerRangeToInfinity::NonNegative(integer_increasing_range_to_infinity(a)) } else { ExhaustiveIntegerRangeToInfinity::BothSigns( once(Integer::ZERO).chain( integer_increasing_range_to_infinity(Integer::ONE) .interleave(integer_increasing_range(a, Integer::ZERO).rev()), ), ) } } /// Generates all [`Integer`]s less than or equal to some number $a$, in order of increasing /// absolute value. /// /// When two [`Integer`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the the previously-generated value is positive and its /// least-significant limb is `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::integer::exhaustive::exhaustive_integer_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_integer_range_to_negative_infinity(Integer::from(2)), /// 10 /// ), /// "[0, 1, -1, 2, -2, -3, -4, -5, -6, -7, ...]" /// ) /// ``` #[inline] pub fn exhaustive_integer_range_to_negative_infinity( a: Integer, ) -> ExhaustiveIntegerRangeToNegativeInfinity { if a <= 0 { ExhaustiveIntegerRangeToNegativeInfinity::NonPositive( integer_decreasing_range_to_negative_infinity(a), ) } else { ExhaustiveIntegerRangeToNegativeInfinity::BothSigns(once(Integer::ZERO).chain( integer_increasing_range(Integer::ONE, a + Integer::ONE).interleave( integer_decreasing_range_to_negative_infinity(Integer::NEGATIVE_ONE), ), )) } } ================================================ FILE: malachite-nz/src/integer/logic/and.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2003, 2005, 2012, 2015-2018 Free // Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{limbs_add_limb_to_out, limbs_slice_add_limb_in_place}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::{Ordering::*, max}; use core::ops::{BitAnd, BitAndAssign}; use malachite_base::num::arithmetic::traits::WrappingNegAssign; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::NotAssign; use malachite_base::slices::{slice_leading_zeros, slice_set_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, returns the // limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y` // and whose other limbs are full of `true` bits. `xs` may not be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_pos_and_limb_neg(xs: &[Limb], y: Limb) -> Vec { let mut out = xs.to_vec(); out[0] &= y; out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the // limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y` // and whose other limbs are full of `true` bits, to an output slice. `xs` may not be empty. The // output slice must be at least as long as the input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or if `out` is shorter than `xs`. pub_test! {limbs_pos_and_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) { let len = xs.len(); assert!(out.len() >= len); let (xs_head, xs_tail) = xs.split_first().unwrap(); let (out_head, out_tail) = out[..len].split_first_mut().unwrap(); *out_head = xs_head & y; out_tail.copy_from_slice(xs_tail); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the // limbs of the bitwise and of the `Integer` and a negative number whose lowest limb is given by `y` // and whose other limbs are full of `true` bits, to the input slice. `xs` may not be empty. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_pos_and_limb_neg_in_place(xs: &mut [Limb], ys: Limb) { xs[0] &= ys; }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, returns the limbs of the bitwise and of the `Integer` and a negative number whose // lowest limb is given by `y` and whose other limbs are full of `true` bits. `xs` may not be empty // or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_neg_and_limb_neg(xs: &[Limb], y: Limb) -> Vec { let mut out = xs.to_vec(); limbs_vec_neg_and_limb_neg_in_place(&mut out, y); out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise and of the `Integer` and a negative number whose // lowest limb is given by `y` and whose other limbs are full of `true` bits to an output slice. // `xs` may not be empty or only contain zeros. Returns whether a carry occurs. The output slice // must be at least as long as the input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or if `out` is shorter than `xs`. pub_test! {limbs_neg_and_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool { let out = &mut out[..xs.len()]; if xs[0] == 0 { out.copy_from_slice(xs); false } else { let (xs_head, xs_tail) = xs.split_first().unwrap(); let (out_head, out_tail) = out.split_first_mut().unwrap(); let result_head = xs_head.wrapping_neg() & y; if result_head == 0 { *out_head = 0; limbs_add_limb_to_out(out_tail, xs_tail, 1) } else { *out_head = result_head.wrapping_neg(); out_tail.copy_from_slice(xs_tail); false } } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, takes the bitwise and of the `Integer` and a negative number whose lowest limb is // given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or // only contain zeros. Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_slice_neg_and_limb_neg_in_place(xs: &mut [Limb], y: Limb) -> bool { let (xs_head, xs_tail) = xs.split_first_mut().unwrap(); if *xs_head == 0 { false } else { *xs_head = xs_head.wrapping_neg() & y; if *xs_head == 0 { limbs_slice_add_limb_in_place(xs_tail, 1) } else { xs_head.wrapping_neg_assign(); false } } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, takes the bitwise and of the `Integer` and a negative number whose lowest limb is // given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or // only contain zeros. If there is a carry, increases the length of the `Vec` by 1. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_vec_neg_and_limb_neg_in_place(xs: &mut Vec, y: Limb) { if limbs_slice_neg_and_limb_neg_in_place(xs, y) { xs.push(1); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, returns the limbs of the bitwise and of the `Integer`s. `xs` and `ys` may // not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res` is returned, the first // input is positive, and the second is negative. pub_test! {limbs_and_pos_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { return Vec::new(); } else if x_i >= ys_len { return xs.to_vec(); } let max_i = max(x_i, y_i); let mut out = vec![0; max_i]; out.push( xs[max_i] & if x_i <= y_i { ys[max_i].wrapping_neg() } else { !ys[max_i] }, ); out.extend( xs[max_i + 1..] .iter() .zip(ys[max_i + 1..].iter()) .map(|(&x, &y)| x & !y), ); if xs_len > ys_len { out.extend_from_slice(&xs[ys_len..]); } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise and of the `Integer`s to an output slice. // `xs` and `ys` may not be empty or only contain zeros. The output slice must be at least as long // as the first input slice. `xs.len()` limbs will be written; if the number of significant limbs of // the result is lower, some of the written limbs will be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than `xs`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where the first input is positive // and the second is negative. pub_test! {limbs_and_pos_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= xs_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { slice_set_zero(&mut out[..xs_len]); return; } else if x_i >= ys_len { out[..xs_len].copy_from_slice(xs); return; } let max_i = max(x_i, y_i); slice_set_zero(&mut out[..max_i]); out[max_i] = xs[max_i] & if x_i <= y_i { ys[max_i].wrapping_neg() } else { !ys[max_i] }; for (z, (x, y)) in out[max_i + 1..] .iter_mut() .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter())) { *z = x & !y; } if xs_len > ys_len { out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise and of the `Integer`s to the first (left) // slice. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1`, the first input // is positive, and the second is negative. pub_test! {limbs_and_pos_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { slice_set_zero(xs); return; } else if x_i >= ys_len { return; } let max_i = max(x_i, y_i); slice_set_zero(&mut xs[..max_i]); xs[max_i] &= if x_i <= y_i { ys[max_i].wrapping_neg() } else { !ys[max_i] }; for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) { *x &= !y; } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the lowest min(`xs.len()`, `ys.len()`) limbs of the bitwise and of // the `Integer`s to the second (right) slice. `xs` and `ys` may not be empty or only contain zeros. // If `ys` is shorter than `xs`, the result may be too long to fit in `ys`. The extra limbs in this // case are just `xs[ys.len()..]`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op2`, the first input // is positive, the second is negative, and the length of `op2` is not changed; instead, a carry is // returned. pub_test! {limbs_slice_and_pos_neg_in_place_right(xs: &[Limb], ys: &mut [Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len || x_i >= ys_len { slice_set_zero(ys); return; } let max_i = max(x_i, y_i); slice_set_zero(&mut ys[..max_i]); { let ys_max_i = &mut ys[max_i]; if x_i <= y_i { ys_max_i.wrapping_neg_assign(); } else { ys_max_i.not_assign(); } *ys_max_i &= xs[max_i]; } for (x, y) in xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut()) { *y = !*y & x; } }} // Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of one // `Integer` and the negative of another, writes the limbs of the bitwise and of the `Integer`s to // the `Vec`. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op2`, the first input // is positive, and the second is negative. pub_test! {limbs_vec_and_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec) { limbs_slice_and_pos_neg_in_place_right(xs, ys); let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys_len) { Greater => { let ys_len = ys.len(); ys.extend(xs[ys_len..].iter()); } Less => { ys.truncate(xs_len); } _ => {} } }} const fn limbs_and_neg_neg_helper(input: Limb, boundary_limb_seen: &mut bool) -> Limb { if *boundary_limb_seen { input } else { let result = input.wrapping_add(1); if result != 0 { *boundary_limb_seen = true; } result } } // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, returns the limbs of the bitwise and of the `Integer`s. `xs` and `ys` may not be // empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res` is returned and both // inputs are negative. pub_test! {limbs_and_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { return ys.to_vec(); } else if x_i >= ys_len { return xs.to_vec(); } let max_i = max(x_i, y_i); let mut out = vec![0; max_i]; let x = if x_i >= y_i { xs[max_i].wrapping_sub(1) } else { xs[max_i] }; let y = if x_i <= y_i { ys[max_i].wrapping_sub(1) } else { ys[max_i] }; let mut boundary_limb_seen = false; out.push(limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen)); let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()); if boundary_limb_seen { out.extend(xys.map(|(&x, &y)| x | y)); } else { for (&x, &y) in xys { out.push(limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen)); } } if xs_len != ys_len { let zs = if xs_len > ys_len { &xs[ys_len..] } else { &ys[xs_len..] }; if boundary_limb_seen { out.extend_from_slice(zs); } else { for &z in zs { out.push(limbs_and_neg_neg_helper(z, &mut boundary_limb_seen)); } } } if !boundary_limb_seen { out.push(1); } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise and of the `Integer`s to // an output slice. `xs` and `ys` may not be empty or only contain zeros. Returns whether the // least-significant max(`xs.len()`, `ys.len()`) limbs of the output are not all zero. The output // slice must be at least as long as the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of // `xs` and `ys`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative. pub_test! {limbs_and_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { out[..ys_len].copy_from_slice(ys); if xs_len > ys_len { slice_set_zero(&mut out[ys_len..xs_len]); } return true; } else if x_i >= ys_len { out[..xs_len].copy_from_slice(xs); if ys_len > xs_len { slice_set_zero(&mut out[xs_len..ys_len]); } return true; } let max_i = max(x_i, y_i); slice_set_zero(&mut out[..max_i]); let x = if x_i >= y_i { xs[max_i].wrapping_sub(1) } else { xs[max_i] }; let y = if x_i <= y_i { ys[max_i].wrapping_sub(1) } else { ys[max_i] }; let mut boundary_limb_seen = false; out[max_i] = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen); let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()); if boundary_limb_seen { for (z, (x, y)) in out[max_i + 1..].iter_mut().zip(xys) { *z = x | y; } } else { for (z, (x, y)) in out[max_i + 1..].iter_mut().zip(xys) { *z = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen); } } let (xs, xs_len, ys_len) = if xs_len >= ys_len { (xs, xs_len, ys_len) } else { (ys, ys_len, xs_len) }; if xs_len != ys_len { let zs = &xs[ys_len..]; if boundary_limb_seen { out[ys_len..xs_len].copy_from_slice(zs); } else { for (z_out, &z_in) in out[ys_len..xs_len].iter_mut().zip(zs.iter()) { *z_out = limbs_and_neg_neg_helper(z_in, &mut boundary_limb_seen); } } } boundary_limb_seen }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the lower `xs.len()` limbs of the bitwise and of the `Integer`s to the first // (left) slice. `xs` and `ys` may not be empty or only contain zeros, and `xs` must be at least as // long as `ys`. Returns whether the least-significant `xs.len()` limbs of the output are not all // zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `xs` is shorter than `ys`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1`, both inputs are // negative, and the length of `op1` is not changed; instead, a carry is returned. pub_test! {limbs_slice_and_neg_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if x_i >= ys_len { return true; } let max_i = max(x_i, y_i); if y_i > x_i { slice_set_zero(&mut xs[x_i..y_i]); } let x = if x_i >= y_i { xs[max_i].wrapping_sub(1) } else { xs[max_i] }; let y = if x_i <= y_i { ys[max_i].wrapping_sub(1) } else { ys[max_i] }; let mut boundary_limb_seen = false; xs[max_i] = limbs_and_neg_neg_helper(x | y, &mut boundary_limb_seen); let xys = xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()); if boundary_limb_seen { for (x, &y) in xys { *x |= y; } } else { for (x, &y) in xys { *x = limbs_and_neg_neg_helper(*x | y, &mut boundary_limb_seen); } } if xs_len > ys_len && !boundary_limb_seen { for x in &mut xs[ys_len..] { *x = limbs_and_neg_neg_helper(*x, &mut boundary_limb_seen); } } boundary_limb_seen }} // Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of the // negatives of two `Integer`s, writes the limbs of the bitwise and of the `Integer`s to the `Vec`. // `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1` and both inputs // are negative. pub_test! {limbs_vec_and_neg_neg_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let y_i = slice_leading_zeros(ys); assert!(y_i < ys_len); if y_i >= xs_len { xs.resize(ys_len, 0); xs.copy_from_slice(ys); return; } let boundary_limb_seen = if ys_len > xs_len { let mut boundary_limb_seen = limbs_slice_and_neg_neg_in_place_left(xs, &ys[..xs_len]); let zs = &ys[xs_len..]; if boundary_limb_seen { xs.extend_from_slice(zs); } else { for &z in zs { xs.push(limbs_and_neg_neg_helper(z, &mut boundary_limb_seen)); } } boundary_limb_seen } else { limbs_slice_and_neg_neg_in_place_left(xs, ys) }; if !boundary_limb_seen { xs.push(1); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the lower max(`xs.len()`, `ys.len()`) limbs of the bitwise and of the // `Integer`s to the longer slice (or the first one, if they are equally long). `xs` and `ys` may // not be empty or only contain zeros. Returns a pair of `bool`s. The first is `false` when the // output is to the first slice and `true` when it's to the second slice, and the second is whether // the least-significant max(`xs.len()`, `ys.len()`) limbs of the output are not all zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative, the // result is written to the longer input slice, and the length of `op1` is not changed; instead, a // carry is returned. pub_test! {limbs_slice_and_neg_neg_in_place_either( xs: &mut [Limb], ys: &mut [Limb] ) -> (bool, bool) { if xs.len() >= ys.len() { (false, limbs_slice_and_neg_neg_in_place_left(xs, ys)) } else { (true, limbs_slice_and_neg_neg_in_place_left(ys, xs)) } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the limbs of the bitwise and of the `Integer`s to the longer `Vec` (or the // first one, if they are equally long). `xs` and `ys` may not be empty or only contain zeros. // Returns a `bool` which is `false` when the output is to the first slice and `true` when it's to // the second slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are negative and // the result is written to the longer input slice. pub_test! {limbs_vec_and_neg_neg_in_place_either(xs: &mut Vec, ys: &mut Vec) -> bool { if xs.len() >= ys.len() { limbs_vec_and_neg_neg_in_place_left(xs, ys); false } else { limbs_vec_and_neg_neg_in_place_left(ys, xs); true } }} impl Natural { fn and_assign_pos_limb_neg(&mut self, other: Limb) { match self { Self(Small(small)) => *small &= other, Self(Large(limbs)) => limbs_pos_and_limb_neg_in_place(limbs, other), } } fn and_pos_limb_neg(&self, other: Limb) -> Self { Self(match self { Self(Small(small)) => Small(small & other), Self(Large(limbs)) => Large(limbs_pos_and_limb_neg(limbs, other)), }) } fn and_assign_neg_limb_neg(&mut self, other: Limb) { match self { &mut Self::ZERO => {} Self(Small(small)) => { let result = small.wrapping_neg() & other; if result == 0 { *self = Self(Large(vec![0, 1])); } else { *small = result.wrapping_neg(); } } Self(Large(limbs)) => limbs_vec_neg_and_limb_neg_in_place(limbs, other), } } fn and_assign_pos_neg(&mut self, other: &Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.and_assign_pos_limb_neg(y.wrapping_neg()), (Self(Small(x)), Self(Large(ys))) => *x &= ys[0].wrapping_neg(), (Self(Large(xs)), Self(Large(ys))) => { limbs_and_pos_neg_in_place_left(xs, ys); self.trim(); } } } fn and_assign_neg_pos(&mut self, mut other: Self) { other.and_assign_pos_neg(self); *self = other; } fn and_assign_neg_pos_ref(&mut self, other: &Self) { match (&mut *self, other) { (Self(Small(x)), y) => *self = y.and_pos_limb_neg(x.wrapping_neg()), (Self(Large(xs)), Self(Small(y))) => { *self = Self(Small(xs[0].wrapping_neg() & *y)); } (Self(Large(xs)), Self(Large(ys))) => { limbs_vec_and_pos_neg_in_place_right(ys, xs); self.trim(); } } } fn and_pos_neg(&self, other: &Self) -> Self { match (self, other) { (_, &Self(Small(y))) => self.and_pos_limb_neg(y.wrapping_neg()), (Self(Small(x)), Self(Large(ys))) => Self(Small(x & ys[0].wrapping_neg())), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_and_pos_neg(xs, ys)) } } } fn and_neg_limb_neg(&self, other: Limb) -> Self { Self(match self { Self(Small(small)) => { let result = small.wrapping_neg() & other; if result == 0 { Large(vec![0, 1]) } else { Small(result.wrapping_neg()) } } Self(Large(limbs)) => Large(limbs_neg_and_limb_neg(limbs, other)), }) } fn and_assign_neg_neg(&mut self, mut other: Self) { match (&mut *self, &mut other) { (Self(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()), (_, Self(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { if limbs_vec_and_neg_neg_in_place_either(xs, ys) { *self = other; } self.trim(); } } } fn and_assign_neg_neg_ref(&mut self, other: &Self) { match (&mut *self, other) { (Self(Small(x)), _) => *self = other.and_neg_limb_neg(x.wrapping_neg()), (_, Self(Small(y))) => self.and_assign_neg_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { limbs_vec_and_neg_neg_in_place_left(xs, ys); self.trim(); } } } fn and_neg_neg(&self, other: &Self) -> Self { match (self, other) { (_, &Self(Small(y))) => self.and_neg_limb_neg(y.wrapping_neg()), (&Self(Small(x)), _) => other.and_neg_limb_neg(x.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_and_neg_neg(xs, ys)) } } } } impl BitAnd for Integer { type Output = Self; /// Takes the bitwise and of two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) & Integer::from(-456), -512); /// assert_eq!( /// -Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE), /// -1000000004096i64 /// ); /// ``` #[inline] fn bitand(mut self, other: Self) -> Self { self &= other; self } } impl BitAnd<&Self> for Integer { type Output = Self; /// Takes the bitwise and of two [`Integer`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) & &Integer::from(-456), -512); /// assert_eq!( /// -Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE), /// -1000000004096i64 /// ); /// ``` #[inline] fn bitand(mut self, other: &Self) -> Self { self &= other; self } } impl BitAnd for &Integer { type Output = Integer; /// Takes the bitwise and of two [`Integer`]s, taking the first by reference and the seocnd by /// value. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) & Integer::from(-456), -512); /// assert_eq!( /// &-Integer::from(10u32).pow(12) & -(Integer::from(10u32).pow(12) + Integer::ONE), /// -1000000004096i64 /// ); /// ``` #[inline] fn bitand(self, mut other: Integer) -> Integer { other &= self; other } } impl BitAnd<&Integer> for &Integer { type Output = Integer; /// Takes the bitwise and of two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) & &Integer::from(-456), -512); /// assert_eq!( /// &-Integer::from(10u32).pow(12) & &-(Integer::from(10u32).pow(12) + Integer::ONE), /// -1000000004096i64 /// ); /// ``` fn bitand(self, other: &Integer) -> Integer { match (self.sign, other.sign) { (true, true) => Integer { sign: true, abs: &self.abs & &other.abs, }, (true, false) => Integer { sign: true, abs: self.abs.and_pos_neg(&other.abs), }, (false, true) => Integer { sign: true, abs: other.abs.and_pos_neg(&self.abs), }, (false, false) => Integer { sign: false, abs: self.abs.and_neg_neg(&other.abs), }, } } } impl BitAndAssign for Integer { /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. /// /// $$ /// x \gets x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeOne; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::NEGATIVE_ONE; /// x &= Integer::from(0x70ffffff); /// x &= Integer::from(0x7ff0_ffff); /// x &= Integer::from(0x7ffff0ff); /// x &= Integer::from(0x7ffffff0); /// assert_eq!(x, 0x70f0f0f0); /// ``` fn bitand_assign(&mut self, other: Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitand_assign(other.abs), (true, false) => self.abs.and_assign_pos_neg(&other.abs), (false, true) => { self.sign = true; self.abs.and_assign_neg_pos(other.abs); } (false, false) => self.abs.and_assign_neg_neg(other.abs), } } } impl BitAndAssign<&Self> for Integer { /// Bitwise-ands an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. /// /// $$ /// x \gets x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::NegativeOne; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::NEGATIVE_ONE; /// x &= &Integer::from(0x70ffffff); /// x &= &Integer::from(0x7ff0_ffff); /// x &= &Integer::from(0x7ffff0ff); /// x &= &Integer::from(0x7ffffff0); /// assert_eq!(x, 0x70f0f0f0); /// ``` fn bitand_assign(&mut self, other: &Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitand_assign(&other.abs), (true, false) => self.abs.and_assign_pos_neg(&other.abs), (false, true) => { self.sign = true; self.abs.and_assign_neg_pos_ref(&other.abs); } (false, false) => self.abs.and_assign_neg_neg_ref(&other.abs), } } } ================================================ FILE: malachite-nz/src/integer/logic/bit_access.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1995, 1997, 1999, 2000, 2001, 2002, 2012 Free Software Foundation, // Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::sub::limbs_sub_limb_in_place; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{PowerOf2, WrappingAddAssign, WrappingNegAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::BitAccess; use malachite_base::slices::{slice_leading_zeros, slice_test_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an // action equivalent to taking the two's complement of the limbs and getting the bit at the // specified index. Sufficiently high indices will return `true`. The slice cannot be empty or // contain only zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpz_tstbit` from `mpz/tstbit.c`, GMP 6.2.1, where `d` is negative. pub_test! {limbs_get_bit_neg(xs: &[Limb], index: u64) -> bool { let x_i = bit_to_limb_count_floor(index); if x_i >= xs.len() { // We're indexing into the infinite suffix of 1s true } else { let x = if slice_test_zero(&xs[..x_i]) { xs[x_i].wrapping_neg() } else { !xs[x_i] }; x.get_bit(index & Limb::WIDTH_MASK) } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an // action equivalent to taking the two's complement of the limbs, setting a bit at the specified // index to `true`, and taking the two's complement again. Indices that are outside the bounds of // the slice will result in no action being taken, since negative numbers in two's complement have // infinitely many leading 1s. The slice cannot be empty or contain only zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `index`. // // # Panics // If the slice contains only zeros a panic may occur. // // This is equivalent to `mpz_setbit` from `mpz/setbit.c`, GMP 6.2.1, where `d` is negative. pub_test! {limbs_set_bit_neg(xs: &mut [Limb], index: u64) { let x_i = bit_to_limb_count_floor(index); if x_i >= xs.len() { return; } let reduced_index = index & Limb::WIDTH_MASK; let zero_bound = slice_leading_zeros(xs); match x_i.cmp(&zero_bound) { Equal => { let boundary = &mut xs[x_i]; // boundary != 0 here *boundary -= 1; boundary.clear_bit(reduced_index); // boundary != Limb::MAX here *boundary += 1; } Less => { assert!(!limbs_sub_limb_in_place( &mut xs[x_i..], Limb::power_of_2(reduced_index), )); } Greater => { xs[x_i].clear_bit(reduced_index); } } }} fn limbs_clear_bit_neg_helper(xs: &mut [Limb], x_i: usize, reduced_index: u64) -> bool { let zero_bound = slice_leading_zeros(xs); match x_i.cmp(&zero_bound) { Equal => { // xs[x_i] != 0 here let mut boundary = xs[x_i] - 1; boundary.set_bit(reduced_index); boundary.wrapping_add_assign(1); xs[x_i] = boundary; boundary == 0 && limbs_slice_add_limb_in_place(&mut xs[x_i + 1..], 1) } Greater => { xs[x_i].set_bit(reduced_index); false } _ => false, } } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an // action equivalent to taking the two's complement of the limbs, setting a bit at the specified // index to `false`, and taking the two's complement again. Inputs that would result in new `true` // bits outside of the slice will cause a panic. The slice cannot be empty or contain only zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `index`. // // # Panics // Panics if evaluation would require new `true` bits outside of the slice. If the slice contains // only zeros a panic may occur. // // This is equivalent to `mpz_clrbit` from `mpz/clrbit.c`, GMP 6.2.1, where `d` is negative and // `bit_idx` small enough that no additional memory needs to be given to `d`. pub fn limbs_slice_clear_bit_neg(xs: &mut [Limb], index: u64) { let x_i = bit_to_limb_count_floor(index); let reduced_index = index & Limb::WIDTH_MASK; assert!( x_i < xs.len() && !limbs_clear_bit_neg_helper(xs, x_i, reduced_index), "Setting bit cannot be done within existing slice" ); } // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an // action equivalent to taking the two's complement of the limbs, setting a bit at the specified // index to `false`, and taking the two's complement again. Sufficiently high indices will increase // the length of the limbs vector. The slice cannot be empty or contain only zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `index`. // // # Panics // If the slice contains only zeros a panic may occur. // // This is equivalent to `mpz_clrbit` from `mpz/clrbit.c`, GMP 6.2.1, where `d` is negative. pub_test! {limbs_vec_clear_bit_neg(xs: &mut Vec, index: u64) { let x_i = bit_to_limb_count_floor(index); let reduced_index = index & Limb::WIDTH_MASK; if x_i < xs.len() { if limbs_clear_bit_neg_helper(xs, x_i, reduced_index) { xs.push(1); } } else { xs.resize(x_i, 0); xs.push(Limb::power_of_2(reduced_index)); } }} impl Natural { // self cannot be zero pub(crate) fn get_bit_neg(&self, index: u64) -> bool { match self { Self(Small(small)) => index >= Limb::WIDTH || small.wrapping_neg().get_bit(index), Self(Large(limbs)) => limbs_get_bit_neg(limbs, index), } } // self cannot be zero fn set_bit_neg(&mut self, index: u64) { match self { Self(Small(small)) => { if index < Limb::WIDTH { small.wrapping_neg_assign(); small.set_bit(index); small.wrapping_neg_assign(); } } Self(Large(limbs)) => { limbs_set_bit_neg(limbs, index); self.trim(); } } } // self cannot be zero fn clear_bit_neg(&mut self, index: u64) { match self { Self(Small(small)) if index < Limb::WIDTH => { let mut cleared_small = small.wrapping_neg(); cleared_small.clear_bit(index); if cleared_small == 0 { *self = Self(Large(vec![0, 1])); } else { *small = cleared_small.wrapping_neg(); } } Self(Small(_)) => { let limbs = self.promote_in_place(); limbs_vec_clear_bit_neg(limbs, index); } Self(Large(limbs)) => { limbs_vec_clear_bit_neg(limbs, index); } } } } /// Provides functions for accessing and modifying the $i$th bit of a [`Integer`], or the /// coefficient of $2^i$ in its two's complement binary expansion. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, Zero}; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, 100); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, 0); /// /// let mut x = Integer::from(-0x100); /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, -156); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, -256); /// /// let mut x = Integer::ZERO; /// x.flip_bit(10); /// assert_eq!(x, 1024); /// x.flip_bit(10); /// assert_eq!(x, 0); /// /// let mut x = Integer::NEGATIVE_ONE; /// x.flip_bit(10); /// assert_eq!(x, -1025); /// x.flip_bit(10); /// assert_eq!(x, -1); /// ``` impl BitAccess for Integer { /// Determines whether the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its two's /// complement binary expansion, is 0 or 1. /// /// `false` means 0 and `true` means 1. Getting bits beyond the [`Integer`]'s width is allowed; /// those bits are `false` if the [`Integer`] is non-negative and `true` if it is negative. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. /// /// $f(n, i) = (b_i = 1)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(123).get_bit(2), false); /// assert_eq!(Integer::from(123).get_bit(3), true); /// assert_eq!(Integer::from(123).get_bit(100), false); /// assert_eq!(Integer::from(-123).get_bit(0), true); /// assert_eq!(Integer::from(-123).get_bit(1), false); /// assert_eq!(Integer::from(-123).get_bit(100), true); /// assert_eq!(Integer::from(10u32).pow(12).get_bit(12), true); /// assert_eq!(Integer::from(10u32).pow(12).get_bit(100), false); /// assert_eq!((-Integer::from(10u32).pow(12)).get_bit(12), true); /// assert_eq!((-Integer::from(10u32).pow(12)).get_bit(100), true); /// ``` fn get_bit(&self, index: u64) -> bool { match self { Self { sign: true, abs } => abs.get_bit(index), Self { sign: false, abs } => abs.get_bit_neg(index), } } /// Sets the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its two's complement /// binary expansion, to 1. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. /// $$ /// n \gets \\begin{cases} /// n + 2^j & \text{if} \\quad b_j = 0, \\\\ /// n & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `index`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, 100); /// /// let mut x = Integer::from(-0x100); /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, -156); /// ``` fn set_bit(&mut self, index: u64) { match self { Self { sign: true, abs } => abs.set_bit(index), Self { sign: false, abs } => abs.set_bit_neg(index), } } /// Sets the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its binary expansion, /// to 0. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. /// $$ /// n \gets \\begin{cases} /// n - 2^j & \text{if} \\quad b_j = 1, \\\\ /// n & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `index`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(0x7f); /// x.clear_bit(0); /// x.clear_bit(1); /// x.clear_bit(3); /// x.clear_bit(4); /// assert_eq!(x, 100); /// /// let mut x = Integer::from(-156); /// x.clear_bit(2); /// x.clear_bit(5); /// x.clear_bit(6); /// assert_eq!(x, -256); /// ``` fn clear_bit(&mut self, index: u64) { match self { Self { sign: true, abs } => abs.clear_bit(index), Self { sign: false, abs } => abs.clear_bit_neg(index), } } } ================================================ FILE: malachite-nz/src/integer/logic/bit_block_access.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_vec_add_limb_in_place; use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::limbs_sub_limb_in_place; use crate::natural::logic::bit_block_access::limbs_assign_bits_helper; use crate::natural::logic::not::limbs_not_in_place; use crate::natural::logic::trailing_zeros::limbs_trailing_zeros; use crate::natural::{Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::ModPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitBlockAccess, LeadingZeros, TrailingZeros}; use malachite_base::vecs::vec_delete_left; // Returns the limbs obtained by taking a slice of bits beginning at index `start` of the negative // of `limb` and ending at index `end - 1`. `start` must be less than or equal to `end`, but apart // from that there are no restrictions on the index values. If they index beyond the physical size // of the input limbs, the function interprets them as pointing to `true` bits. `x` must be // positive. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `end`. // // # Panics // Panics if `start > end`. pub_test! {limbs_neg_limb_get_bits(x: Limb, start: u64, end: u64) -> Vec { assert!(start <= end); let trailing_zeros = TrailingZeros::trailing_zeros(x); if trailing_zeros >= end { return Vec::new(); } let bit_len = end - start; let mut out = if start >= Limb::WIDTH { vec![ Limb::MAX; bit_to_limb_count_ceiling(bit_len) ] } else { let mut out = vec![x >> start]; out.resize(bit_to_limb_count_floor(end) + 1, 0); if trailing_zeros >= start { limbs_twos_complement_in_place(&mut out); } else { limbs_not_in_place(&mut out); } out }; limbs_vec_mod_power_of_2_in_place(&mut out, bit_len); out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs obtained by taking a slice of bits beginning at index `start` of the negative of the // `Natural` and ending at index `end - 1`. `start` must be less than or equal to `end`, but apart // from that there are no restrictions on the index values. If they index beyond the physical size // of the input limbs, the function interprets them as pointing to `true` bits. The input slice // cannot only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(xs.len(), end * Limb::WIDTH)`. // // # Panics // Panics if `start > end`. pub_test! {limbs_slice_neg_get_bits(xs: &[Limb], start: u64, end: u64) -> Vec { assert!(start <= end); let trailing_zeros = limbs_trailing_zeros(xs); if trailing_zeros >= end { return Vec::new(); } let start_i = bit_to_limb_count_floor(start); let len = xs.len(); let bit_len = end - start; if start_i >= len { let mut out = vec![Limb::MAX; bit_to_limb_count_ceiling(bit_len)]; limbs_vec_mod_power_of_2_in_place(&mut out, bit_len); return out; } let end_i = bit_to_limb_count_floor(end) + 1; let mut out = (if end_i >= len { &xs[start_i..] } else { &xs[start_i..end_i] }) .to_vec(); let offset = start & Limb::WIDTH_MASK; if offset != 0 { limbs_slice_shr_in_place(&mut out, offset); } out.resize(end_i - start_i, 0); if trailing_zeros >= start { limbs_twos_complement_in_place(&mut out); } else { limbs_not_in_place(&mut out); } limbs_vec_mod_power_of_2_in_place(&mut out, bit_len); out }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs obtained by taking a slice of bits beginning at index `start` of the negative of the // `Natural` and ending at index `end - 1`. `start` must be less than or equal to `end`, but apart // from that there are no restrictions on the index values. If they index beyond the physical size // of the input limbs, the function interprets them as pointing to `true` bits. The input slice // cannot only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(xs.len(), end * Limb::WIDTH)`. // // # Panics // Panics if `start > end`. pub_test! {limbs_vec_neg_get_bits(mut xs: Vec, start: u64, end: u64) -> Vec { assert!(start <= end); let trailing_zeros = limbs_trailing_zeros(&xs); if trailing_zeros >= end { return Vec::new(); } let start_i = bit_to_limb_count_floor(start); let len = xs.len(); let bit_len = end - start; if start_i >= len { xs = vec![Limb::MAX; bit_to_limb_count_ceiling(bit_len)]; limbs_vec_mod_power_of_2_in_place(&mut xs, bit_len); return xs; } let end_i = bit_to_limb_count_floor(end) + 1; xs.truncate(end_i); vec_delete_left(&mut xs, start_i); let offset = start & Limb::WIDTH_MASK; if offset != 0 { limbs_slice_shr_in_place(&mut xs, offset); } xs.resize(end_i - start_i, 0); if trailing_zeros >= start { limbs_twos_complement_in_place(&mut xs); } else { limbs_not_in_place(&mut xs); } limbs_vec_mod_power_of_2_in_place(&mut xs, bit_len); xs }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural` n, writes the // limbs of `bits` into the limbs of -n, starting at bit `start` of -n (inclusive) and ending at bit // `end` of -n (exclusive). The bit indices do not need to be aligned with any limb boundaries. If // `bits` has more than `end` - `start` bits, only the first `end` - `start` bits are written. If // `bits` has fewer than `end` - `start` bits, the remaining written bits are one. `xs` may be // extended to accommodate the new bits. `start` must be smaller than `end`, and `xs` cannot only // contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(n / 2 ^ Limb::WIDTH, m)`, and $m$ is // `end`. // // # Panics // Panics if `start >= end` or `xs` only contains zeros. pub_test! {limbs_neg_assign_bits(xs: &mut Vec, start: u64, end: u64, bits: &[Limb]) { assert!(start < end); assert!(!limbs_sub_limb_in_place(xs, 1)); limbs_assign_bits_helper(xs, start, end, bits, true); limbs_vec_add_limb_in_place(xs, 1); }} impl Natural { fn neg_get_bits(&self, start: u64, end: u64) -> Self { Self::from_owned_limbs_asc(match self { Self(Small(small)) => limbs_neg_limb_get_bits(*small, start, end), Self(Large(limbs)) => limbs_slice_neg_get_bits(limbs, start, end), }) } fn neg_get_bits_owned(self, start: u64, end: u64) -> Self { Self::from_owned_limbs_asc(match self { Self(Small(small)) => limbs_neg_limb_get_bits(small, start, end), Self(Large(limbs)) => limbs_vec_neg_get_bits(limbs, start, end), }) } fn neg_assign_bits(&mut self, start: u64, end: u64, bits: &Self) { if start == end { return; } let bits_width = end - start; if bits_width <= Limb::WIDTH && let (&mut Self(Small(ref mut small_self)), &Self(Small(small_bits))) = (&mut *self, bits) { let small_bits = (!small_bits).mod_power_of_2(bits_width); if small_bits == 0 || LeadingZeros::leading_zeros(small_bits) >= start { let mut new_small_self = *small_self - 1; new_small_self.assign_bits(start, end, &small_bits); let (sum, overflow) = new_small_self.overflowing_add(1); if !overflow { *small_self = sum; return; } } } let limbs = self.promote_in_place(); match bits { Self(Small(small_bits)) => limbs_neg_assign_bits(limbs, start, end, &[*small_bits]), Self(Large(bits_limbs)) => limbs_neg_assign_bits(limbs, start, end, bits_limbs), } self.trim(); } } impl BitBlockAccess for Integer { type Bits = Natural; /// Extracts a block of adjacent two's complement bits from an [`Integer`], taking the /// [`Integer`] by reference. /// /// The first index is `start` and last index is `end - 1`. /// /// Let $n$ be `self`, and let $p$ and $q$ be `start` and `end`, respectively. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), end)`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (-Natural::from(0xabcdef0112345678u64)).get_bits(16, 48), /// Natural::from(0x10feedcbu32) /// ); /// assert_eq!( /// Integer::from(0xabcdef0112345678u64).get_bits(4, 16), /// Natural::from(0x567u32) /// ); /// assert_eq!( /// (-Natural::from(0xabcdef0112345678u64)).get_bits(0, 100), /// Natural::from_str("1267650600215849587758112418184").unwrap() /// ); /// assert_eq!( /// Integer::from(0xabcdef0112345678u64).get_bits(10, 10), /// Natural::ZERO /// ); /// ``` fn get_bits(&self, start: u64, end: u64) -> Natural { if self.sign { self.abs.get_bits(start, end) } else { self.abs.neg_get_bits(start, end) } } /// Extracts a block of adjacent two's complement bits from an [`Integer`], taking the /// [`Integer`] by value. /// /// The first index is `start` and last index is `end - 1`. /// /// Let $n$ be `self`, and let $p$ and $q$ be `start` and `end`, respectively. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), end)`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (-Natural::from(0xabcdef0112345678u64)).get_bits_owned(16, 48), /// Natural::from(0x10feedcbu32) /// ); /// assert_eq!( /// Integer::from(0xabcdef0112345678u64).get_bits_owned(4, 16), /// Natural::from(0x567u32) /// ); /// assert_eq!( /// (-Natural::from(0xabcdef0112345678u64)).get_bits_owned(0, 100), /// Natural::from_str("1267650600215849587758112418184").unwrap() /// ); /// assert_eq!( /// Integer::from(0xabcdef0112345678u64).get_bits_owned(10, 10), /// Natural::ZERO /// ); /// ``` fn get_bits_owned(self, start: u64, end: u64) -> Natural { if self.sign { self.abs.get_bits_owned(start, end) } else { self.abs.neg_get_bits_owned(start, end) } } /// Replaces a block of adjacent two's complement bits in an [`Integer`] with other bits. /// /// The least-significant `end - start` bits of `bits` are assigned to bits `start` through `end /// - 1`, inclusive, of `self`. /// /// Let $n$ be `self` and let $m$ be `bits`, and let $p$ and $q$ be `start` and `end`, /// respectively. /// /// Let /// $$ /// m = \sum_{i=0}^k 2^{d_i}, /// $$ /// where for all $i$, $d_i\in \\{0, 1\\}$. /// /// If $n \geq 0$, let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}; /// $$ /// but if $n < 0$, let /// $$ /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$. Then /// $$ /// n \gets \sum_{i=0}^\infty 2^{c_i}, /// $$ /// where /// $$ /// \\{c_0, c_1, c_2, \ldots \\} = /// \\{b_0, b_1, b_2, \ldots, b_{p-1}, d_0, d_1, \ldots, d_{p-q-1}, b_q, b_{q+1}, \ldots \\}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), end)`, and /// $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::Natural; /// /// let mut n = Integer::from(123); /// n.assign_bits(5, 7, &Natural::from(456u32)); /// assert_eq!(n.to_string(), "27"); /// /// let mut n = Integer::from(-123); /// n.assign_bits(64, 128, &Natural::from(456u32)); /// assert_eq!(n.to_string(), "-340282366920938455033212565746503123067"); /// /// let mut n = Integer::from(-123); /// n.assign_bits(80, 100, &Natural::from(456u32)); /// assert_eq!(n.to_string(), "-1267098121128665515963862483067"); /// ``` fn assign_bits(&mut self, start: u64, end: u64, bits: &Natural) { if self.sign { self.abs.assign_bits(start, end, bits); } else { self.abs.neg_assign_bits(start, end, bits); } } } ================================================ FILE: malachite-nz/src/integer/logic/bit_convertible.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::Natural; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::platform::{Limb, SignedLimb}; use alloc::vec::Vec; use itertools::Itertools; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::{BitConvertible, LowMask, NotAssign}; // Given the bits of a non-negative `Integer`, in ascending order, checks whether the most // significant bit is `false`; if it isn't, appends an extra `false` bit. This way the `Integer`'s // non-negativity is preserved in its bits. // // # Worst-case complexity // Constant time and additional memory. pub_test! {bits_to_twos_complement_bits_non_negative(bits: &mut Vec) { if !bits.is_empty() && *bits.last().unwrap() { // Sign-extend with an extra false bit to indicate a positive Integer bits.push(false); } }} // Given the bits of the absolute value of a negative `Integer`, in ascending order, converts the // bits to two's complement. Returns whether there is a carry left over from the two's complement // conversion process. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bits.len()`. pub_test! {bits_slice_to_twos_complement_bits_negative(bits: &mut [bool]) -> bool { let mut true_seen = false; for bit in &mut *bits { if true_seen { bit.not_assign(); } else if *bit { true_seen = true; } } !true_seen }} // Given the bits of the absolute value of a negative `Integer`, in ascending order, converts the // bits to two's complement and checks whether the most significant bit is `true`; if it isn't, // appends an extra `true` bit. This way the `Integer`'s negativity is preserved in its bits. The // bits cannot be empty or contain only `false`s. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bits.len()`. // // # Panics // Panics if `bits` contains only `false`s. pub_test! {bits_vec_to_twos_complement_bits_negative(bits: &mut Vec) { assert!(!bits_slice_to_twos_complement_bits_negative(bits)); if bits.last() == Some(&false) { // Sign-extend with an extra true bit to indicate a negative Integer bits.push(true); } }} fn from_bits_helper(mut limbs: Vec, sign_bit: bool, last_width: u64) -> Integer { if sign_bit { if last_width != Limb::WIDTH { *limbs.last_mut().unwrap() |= !Limb::low_mask(last_width); } assert!(!limbs_twos_complement_in_place(&mut limbs)); } Integer::from_sign_and_abs(!sign_bit, Natural::from_owned_limbs_asc(limbs)) } impl BitConvertible for Integer { /// Returns a [`Vec`] containing the twos-complement bits of an [`Integer`] in ascending order: /// least- to most-significant. /// /// The most significant bit indicates the sign; if the bit is `false`, the [`Integer`] is /// positive, and if the bit is `true` it is negative. There are no trailing `false` bits if the /// [`Integer`] is positive or trailing `true` bits if the [`Integer`] is negative, except as /// necessary to include the correct sign bit. Zero is a special case: it contains no bits. /// /// This function is more efficient than [`to_bits_desc`](`Self::to_bits_desc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::ZERO.to_bits_asc().is_empty()); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// Integer::from(105).to_bits_asc(), /// &[true, false, false, true, false, true, true, false] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from(-105).to_bits_asc(), /// &[true, true, true, false, true, false, false, true] /// ); /// ``` fn to_bits_asc(&self) -> Vec { let mut bits = self.abs.to_bits_asc(); if self.sign { bits_to_twos_complement_bits_non_negative(&mut bits); } else { bits_vec_to_twos_complement_bits_negative(&mut bits); } bits } /// Returns a [`Vec`] containing the twos-complement bits of an [`Integer`] in descending order: /// most- to least-significant. /// /// The most significant bit indicates the sign; if the bit is `false`, the [`Integer`] is /// positive, and if the bit is `true` it is negative. There are no leading `false` bits if the /// [`Integer`] is positive or leading `true` bits if the [`Integer`] is negative, except as /// necessary to include the correct sign bit. Zero is a special case: it contains no bits. /// /// This is similar to how `BigInteger`s in Java are represented. /// /// This function is less efficient than [`to_bits_asc`](`Self::to_bits_asc`). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::integer::Integer; /// /// assert!(Integer::ZERO.to_bits_desc().is_empty()); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// Integer::from(105).to_bits_desc(), /// &[false, true, true, false, true, false, false, true] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from(-105).to_bits_desc(), /// &[true, false, false, true, false, true, true, true] /// ); /// ``` fn to_bits_desc(&self) -> Vec { let mut bits = self.to_bits_asc(); bits.reverse(); bits } /// Converts an iterator of twos-complement bits into an [`Integer`]. The bits should be in /// ascending order (least- to most-significant). /// /// Let $k$ be `bits.count()`. If $k = 0$ or $b_{k-1}$ is `false`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// If $b_{k-1}$ is `true`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^i \[b_i\] \right ) - 2^k. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. /// /// # Examples /// ``` /// use core::iter::empty; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from_bits_asc(empty()), 0); /// // 105 = 1101001b /// assert_eq!( /// Integer::from_bits_asc( /// [true, false, false, true, false, true, true, false] /// .iter() /// .cloned() /// ), /// 105 /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from_bits_asc( /// [true, true, true, false, true, false, false, true] /// .iter() /// .cloned() /// ), /// -105 /// ); /// ``` fn from_bits_asc>(xs: I) -> Self { let mut limbs = Vec::new(); let mut last_width = 0; let mut last_bit = false; for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) { let mut limb = 0; let mut i = 0; let mut mask = 1; for bit in chunk { if bit { limb |= mask; } mask <<= 1; i += 1; last_bit = bit; } last_width = i; limbs.push(limb); } from_bits_helper(limbs, last_bit, last_width) } /// Converts an iterator of twos-complement bits into an [`Integer`]. The bits should be in /// descending order (most- to least-significant). /// /// If `bits` is empty or $b_0$ is `false`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// If $b_0$ is `true`, then /// $$ /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\] \right ) - 2^k. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. /// /// # Examples /// ``` /// use core::iter::empty; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from_bits_desc(empty()), 0); /// // 105 = 1101001b /// assert_eq!( /// Integer::from_bits_desc( /// [false, true, true, false, true, false, false, true] /// .iter() /// .cloned() /// ), /// 105 /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from_bits_desc( /// [true, false, false, true, false, true, true, true] /// .iter() /// .cloned() /// ), /// -105 /// ); /// ``` fn from_bits_desc>(xs: I) -> Self { let mut limbs = Vec::new(); let mut last_width = 0; let mut first_bit = false; let mut first = true; for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) { let mut limb = 0; let mut i = 0; for bit in chunk { if first { first_bit = bit; first = false; } limb <<= 1; if bit { limb |= 1; } i += 1; } last_width = i; limbs.push(limb); } match limbs.len() { 0 => Self::ZERO, 1 => { if first_bit { if last_width != Limb::WIDTH { limbs[0] |= !Limb::low_mask(last_width); } Self::from(SignedLimb::wrapping_from(limbs[0])) } else { Self::from(limbs[0]) } } _ => { limbs.reverse(); if last_width != Limb::WIDTH { let smallest_limb = limbs[0]; limbs[0] = 0; limbs_slice_shr_in_place(&mut limbs, Limb::WIDTH - last_width); limbs[0] |= smallest_limb; } from_bits_helper(limbs, first_bit, last_width) } } } } ================================================ FILE: malachite-nz/src/integer/logic/bit_iterable.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::logic::bit_iterable::NaturalBitIterator; use core::ops::Index; use malachite_base::num::logic::traits::{BitAccess, BitIterable}; /// A double-ended iterator over the two's complement bits of the negative of an [`Integer`]. /// /// The forward order is ascending (least-significant first). There may be at most one implicit /// most-significant `true` bit. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct NegativeBitIterator<'a> { pub(crate) bits: NaturalBitIterator<'a>, i: u64, j: u64, first_true_index: Option, } impl Iterator for NegativeBitIterator<'_> { type Item = bool; fn next(&mut self) -> Option { let previous_i = self.i; self.bits.next().map(|bit| { self.i += 1; if let Some(first_true_index) = self.first_true_index { if previous_i <= first_true_index { bit } else { !bit } } else { if bit { self.first_true_index = Some(previous_i); } bit } }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.bits.size_hint() } } impl DoubleEndedIterator for NegativeBitIterator<'_> { fn next_back(&mut self) -> Option { let previous_j = self.j; self.bits.next_back().map(|bit| { if self.j != 0 { self.j -= 1; } if self.first_true_index.is_none() { let mut i = 0; while !self.bits[i] { i += 1; } self.first_true_index = Some(i); } let first_true_index = self.first_true_index.unwrap(); if previous_j <= first_true_index { bit } else { !bit } }) } } impl ExactSizeIterator for NegativeBitIterator<'_> {} trait SignExtendedBitIterator: DoubleEndedIterator { const EXTENSION: bool; fn needs_sign_extension(&self) -> bool; fn iterate_forward(&mut self, extension_checked: &mut bool) -> Option { let next = self.next(); if next.is_none() { if *extension_checked { None } else { *extension_checked = true; if self.needs_sign_extension() { Some(Self::EXTENSION) } else { None } } } else { next } } fn iterate_backward(&mut self, extension_checked: &mut bool) -> Option { if !*extension_checked { *extension_checked = true; if self.needs_sign_extension() { return Some(Self::EXTENSION); } } self.next_back() } } impl SignExtendedBitIterator for NaturalBitIterator<'_> { const EXTENSION: bool = false; fn needs_sign_extension(&self) -> bool { self[self.significant_bits - 1] } } impl SignExtendedBitIterator for NegativeBitIterator<'_> { const EXTENSION: bool = true; fn needs_sign_extension(&self) -> bool { let mut i = 0; while !self.bits[i] { i += 1; } let last_bit_index = self.bits.significant_bits - 1; if i == last_bit_index { !self.bits[last_bit_index] } else { self.bits[last_bit_index] } } } /// A double-ended iterator over the twos-complement bits of an [`Integer`]. /// /// The forward order is ascending (least-significant first). The most significant bit corresponds /// to the sign of the [`Integer`]; `false` for non-negative and `true` for negative. This means /// that there may be a single most-significant sign-extension bit. /// /// This `struct` is created by [`BitIterable::bits`]; see its documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum IntegerBitIterator<'a> { Zero, Positive(NaturalBitIterator<'a>, bool), Negative(NegativeBitIterator<'a>, bool), } impl Iterator for IntegerBitIterator<'_> { type Item = bool; fn next(&mut self) -> Option { match self { Self::Zero => None, Self::Positive(bits, extension_checked) => bits.iterate_forward(extension_checked), Self::Negative(bits, extension_checked) => bits.iterate_forward(extension_checked), } } } impl DoubleEndedIterator for IntegerBitIterator<'_> { fn next_back(&mut self) -> Option { match self { Self::Zero => None, Self::Positive(bits, extension_checked) => bits.iterate_backward(extension_checked), Self::Negative(bits, extension_checked) => bits.iterate_backward(extension_checked), } } } impl Index for IntegerBitIterator<'_> { type Output = bool; /// A function to retrieve an [`Integer`]'s two's complement bits by index. Indexing at or above /// the significant bit count returns `false` or `true` bits, depending on the [`Integer`]'s /// sign. /// /// This is equivalent to [`get_bit`](malachite_base::num::logic::traits::BitAccess::get_bit). /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitIterable; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.bits()[0], false); /// /// // -105 = 10010111 in two's complement /// let n = Integer::from(-105); /// let bits = n.bits(); /// assert_eq!(bits[0], true); /// assert_eq!(bits[1], true); /// assert_eq!(bits[2], true); /// assert_eq!(bits[3], false); /// assert_eq!(bits[4], true); /// assert_eq!(bits[5], false); /// assert_eq!(bits[6], false); /// assert_eq!(bits[7], true); /// assert_eq!(bits[100], true); /// ``` fn index(&self, index: u64) -> &bool { let bit = match self { Self::Zero => false, Self::Positive(bits, _) => bits.limbs.n.get_bit(index), Self::Negative(bits, _) => bits.bits.limbs.n.get_bit_neg(index), }; if bit { &true } else { &false } } } impl Natural { // Returns a double-ended iterator over the two's complement bits of the negative of a // `Natural`. The forward order is ascending, so that less significant bits appear first. There // may be at most one trailing `true` bit going forward, or leading `true` bit going backward. // The `Natural` cannot be zero. // // # Worst-case complexity // Constant time and additional memory. fn negative_bits(&self) -> NegativeBitIterator<'_> { assert_ne!(*self, 0, "Cannot get negative bits of 0."); let bits = self.bits(); NegativeBitIterator { bits, first_true_index: None, i: 0, j: bits.significant_bits - 1, } } } impl<'a> BitIterable for &'a Integer { type BitIterator = IntegerBitIterator<'a>; /// Returns a double-ended iterator over the bits of an [`Integer`]. /// /// The forward order is ascending, so that less significant bits appear first. There are no /// trailing false bits going forward, or leading falses going backward, except for possibly a /// most-significant sign-extension bit. /// /// If it's necessary to get a [`Vec`] of all the bits, consider using /// [`to_bits_asc`](malachite_base::num::logic::traits::BitConvertible::to_bits_asc) or /// [`to_bits_desc`](malachite_base::num::logic::traits::BitConvertible::to_bits_desc) instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitIterable; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.bits().next(), None); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// Integer::from(105).bits().collect_vec(), /// &[true, false, false, true, false, true, true, false] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from(-105).bits().collect_vec(), /// &[true, true, true, false, true, false, false, true] /// ); /// /// assert_eq!(Integer::ZERO.bits().next_back(), None); /// // 105 = 01101001b, with a leading false bit to indicate sign /// assert_eq!( /// Integer::from(105).bits().rev().collect_vec(), /// &[false, true, true, false, true, false, false, true] /// ); /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign /// assert_eq!( /// Integer::from(-105).bits().rev().collect_vec(), /// &[true, false, false, true, false, true, true, true] /// ); /// ``` fn bits(self) -> IntegerBitIterator<'a> { if *self == 0 { IntegerBitIterator::Zero } else if self.sign { IntegerBitIterator::Positive(self.abs.bits(), false) } else { IntegerBitIterator::Negative(self.abs.negative_bits(), false) } } } ================================================ FILE: malachite-nz/src/integer/logic/bit_scan.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000-2002, 2004, 2012, 2015 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::logic::bit_scan::{ limbs_index_of_next_false_bit, limbs_index_of_next_true_bit, }; use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::Limb; use core::cmp::Ordering::*; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitScan, LowMask, TrailingZeros}; use malachite_base::slices::slice_leading_zeros; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, finds the lowest index greater than or equal to `starting_index` at which the // `Integer` has a `false` bit. If the starting index is too large and there are no more `false` // bits above it, `None` is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpz_scan0` from `mpz/scan0.c`, GMP 6.2.1. pub_test! {limbs_index_of_next_false_bit_neg(xs: &[Limb], mut starting_index: u64) -> Option { let n = xs.len(); let i = slice_leading_zeros(xs); assert!(i < n); let starting_limb_index = bit_to_limb_count_floor(starting_index); if starting_limb_index >= n { return None; } let after_boundary_offset = limb_to_bit_count(i + 1); match starting_limb_index.cmp(&i) { Equal => { let within_limb_index = starting_index & Limb::WIDTH_MASK; if let Some(result) = xs[i] .wrapping_neg() .index_of_next_false_bit(within_limb_index) { if result < Limb::WIDTH { return Some(limb_to_bit_count(i) + result); } starting_index = 0; } } Less => { return Some(starting_index); } Greater => { starting_index -= after_boundary_offset; } } limbs_index_of_next_true_bit(&xs[i + 1..], starting_index) .map(|result| result + after_boundary_offset) }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, finds the lowest index greater than or equal to `starting_index` at which the // `Integer` has a `true` bit. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpz_scan1` from `mpz/scan1.c`, GMP 6.2.1. pub_test! {limbs_index_of_next_true_bit_neg(xs: &[Limb], mut starting_index: u64) -> u64 { let n = xs.len(); let i = slice_leading_zeros(xs); assert!(i < n); let mut starting_limb_index = bit_to_limb_count_floor(starting_index); if starting_limb_index >= n { return starting_index; } let after_boundary_offset = limb_to_bit_count(i + 1); if starting_limb_index < i { starting_index = limb_to_bit_count(i); starting_limb_index = i; } if starting_limb_index == i { let within_limb_index = starting_index & Limb::WIDTH_MASK; if let Some(result) = xs[i] .wrapping_neg() .index_of_next_true_bit(within_limb_index) { return limb_to_bit_count(i) + result; } starting_index = 0; } else { starting_index -= after_boundary_offset; } limbs_index_of_next_false_bit(&xs[i + 1..], starting_index) + after_boundary_offset }} impl Natural { // self != 0 fn index_of_next_false_bit_neg(&self, starting_index: u64) -> Option { match self { Self(Small(small)) => { if starting_index >= Limb::WIDTH { None } else { let index = TrailingZeros::trailing_zeros( (small - 1) & !Limb::low_mask(starting_index), ); if index == Limb::WIDTH { None } else { Some(index) } } } Self(Large(limbs)) => limbs_index_of_next_false_bit_neg(limbs, starting_index), } } // self != 0 fn index_of_next_true_bit_neg(&self, starting_index: u64) -> u64 { match self { Self(Small(small)) => { if starting_index >= Limb::WIDTH { starting_index } else { TrailingZeros::trailing_zeros(!((small - 1) | Limb::low_mask(starting_index))) } } Self(Large(limbs)) => limbs_index_of_next_true_bit_neg(limbs, starting_index), } } } impl BitScan for &Integer { /// Given an [`Integer`] and a starting index, searches the [`Integer`] for the smallest index /// of a `false` bit that is greater than or equal to the starting index. /// /// If the [`Integer]` is negative, and the starting index is too large and there are no more /// `false` bits above it, `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitScan; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(0), /// Some(0) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(20), /// Some(20) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(31), /// Some(31) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(32), /// Some(34) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(33), /// Some(34) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(34), /// Some(34) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(35), /// None /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_false_bit(100), /// None /// ); /// ``` fn index_of_next_false_bit(self, starting_index: u64) -> Option { if self.sign { self.abs.index_of_next_false_bit(starting_index) } else { self.abs.index_of_next_false_bit_neg(starting_index) } } /// Given an [`Integer`] and a starting index, searches the [`Integer`] for the smallest index /// of a `true` bit that is greater than or equal to the starting index. /// /// If the [`Integer`] is non-negative, and the starting index is too large and there are no /// more `true` bits above it, `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitScan; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(0), /// Some(32) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(20), /// Some(32) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(31), /// Some(32) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(32), /// Some(32) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(33), /// Some(33) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(34), /// Some(35) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(35), /// Some(35) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(36), /// Some(36) /// ); /// assert_eq!( /// (-Integer::from(0x500000000u64)).index_of_next_true_bit(100), /// Some(100) /// ); /// ``` fn index_of_next_true_bit(self, starting_index: u64) -> Option { if self.sign { self.abs.index_of_next_true_bit(starting_index) } else { Some(self.abs.index_of_next_true_bit_neg(starting_index)) } } } ================================================ FILE: malachite-nz/src/integer/logic/checked_count_ones.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::logic::traits::CountOnes; impl Integer { /// Counts the number of ones in the binary expansion of an [`Integer`]. If the [`Integer`] is /// negative, then the number of ones is infinite, so `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.checked_count_ones(), Some(0)); /// // 105 = 1101001b /// assert_eq!(Integer::from(105).checked_count_ones(), Some(4)); /// assert_eq!(Integer::from(-105).checked_count_ones(), None); /// // 10^12 = 1110100011010100101001010001000000000000b /// assert_eq!(Integer::from(10u32).pow(12).checked_count_ones(), Some(13)); /// ``` pub fn checked_count_ones(&self) -> Option { if self.sign { Some(self.abs.count_ones()) } else { None } } } ================================================ FILE: malachite-nz/src/integer/logic/checked_count_zeros.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{CountOnes, CountZeros}; // Interpreting a slice of `Limb`s, as the limbs (in ascending order) of a `Natural`, counts the // number of zeros in the binary expansion of the negative (two's complement) of the `Natural`. // `limbs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_count_zeros_neg(xs: &[Limb]) -> u64 { let mut sum = 0; let mut nonzero_seen = false; for &x in xs { sum += if nonzero_seen { CountOnes::count_ones(x) } else if x == 0 { Limb::WIDTH } else { nonzero_seen = true; CountZeros::count_zeros(x.wrapping_neg()) }; } sum }} impl Natural { fn count_zeros_neg(&self) -> u64 { match self { Self(Small(small)) => CountZeros::count_zeros(small.wrapping_neg()), Self(Large(limbs)) => limbs_count_zeros_neg(limbs), } } } impl Integer { /// Counts the number of zeros in the binary expansion of an [`Integer`]. If the [`Integer`] is /// non-negative, then the number of zeros is infinite, so `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.checked_count_zeros(), None); /// // -105 = 10010111 in two's complement /// assert_eq!(Integer::from(-105).checked_count_zeros(), Some(3)); /// assert_eq!(Integer::from(105).checked_count_zeros(), None); /// // -10^12 = 10001011100101011010110101111000000000000 in two's complement /// assert_eq!( /// (-Integer::from(10u32).pow(12)).checked_count_zeros(), /// Some(24) /// ); /// ``` pub fn checked_count_zeros(&self) -> Option { if self.sign { None } else { Some(self.abs.count_zeros_neg()) } } } ================================================ FILE: malachite-nz/src/integer/logic/checked_hamming_distance.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1994, 1996, 2001, 2002, 2009-2011 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::integer::logic::checked_count_zeros::limbs_count_zeros_neg; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::logic::count_ones::limbs_count_ones; use crate::natural::logic::hamming_distance::limbs_hamming_distance_same_length; use crate::platform::Limb; use core::cmp::Ordering::*; use malachite_base::num::logic::traits::{ CheckedHammingDistance, CountOnes, CountZeros, HammingDistance, }; use malachite_base::slices::slice_leading_zeros; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, returns the // Hamming distance between the negative of that `Natural` (two's complement) and the negative of a // `Limb`. Both have infinitely many implicit leading ones. `xs` cannot be empty or only contain // zeros; `y` cannot be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_hamming_distance_limb_neg(xs: &[Limb], y: Limb) -> u64 { let x_lo = xs[0].wrapping_neg(); limbs_count_zeros_neg(xs) - CountZeros::count_zeros(x_lo) + x_lo.hamming_distance(y.wrapping_neg()) }} fn limbs_count_zeros(xs: &[Limb]) -> u64 { xs.iter().map(|&limb| CountZeros::count_zeros(limb)).sum() } fn limbs_hamming_distance_neg_leading_limbs_helper(xs: &[Limb], ys: &[Limb], i: usize) -> u64 { let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys_len) { Equal => limbs_hamming_distance_same_length(&xs[i + 1..], &ys[i + 1..]), Less => { let (ys_lo, ys_hi) = ys.split_at(xs_len); limbs_hamming_distance_same_length(&ys_lo[i + 1..], &xs[i + 1..]) + limbs_count_ones(ys_hi) } Greater => { let (xs_lo, xs_hi) = xs.split_at(ys_len); limbs_hamming_distance_same_length(&xs_lo[i + 1..], &ys[i + 1..]) + limbs_count_ones(xs_hi) } } } // ``` // xs: nnnnnnnb000 // ys: nnb000000 // ``` // // or // ``` // xs: nnnnnb000 // ys: nnnnb000000 // ``` // // where 0 is a zero limb, n is a nonzero limb, and b is the boundary (least-significant) nonzero // limb. xs_i and ys_i are the indices of the boundary limbs in xs and ys. xs_i < ys_i but xs may be // shorter, longer, or the same length as ys. fn limbs_hamming_distance_neg_helper(xs: &[Limb], ys: &[Limb], xs_i: usize, ys_i: usize) -> u64 { let mut distance = CountOnes::count_ones(xs[xs_i].wrapping_neg()); let xs_len = xs.len(); if xs_i == xs_len - 1 { return distance + limbs_count_zeros_neg(&ys[xs_len..]); } if xs_len < ys_i { return distance + limbs_count_zeros(&xs[xs_i + 1..]) + limbs_count_zeros_neg(&ys[xs_len..]); } distance += limbs_count_zeros(&xs[xs_i + 1..ys_i]); if xs_len == ys_i { return distance + limbs_count_zeros_neg(&ys[xs_len..]); } distance += ys[ys_i].wrapping_neg().hamming_distance(!xs[ys_i]); if xs_len == ys_i + 1 { return distance + limbs_count_ones(&ys[xs_len..]); } distance + limbs_hamming_distance_neg_leading_limbs_helper(xs, ys, ys_i) } // Interpreting two equal-length slices of `Limb`s as the limbs of `Natural`s in ascending order, // returns the Hamming distance between their negatives (two's complement). Both have infinitely // many implicit leading ones. Neither slice may be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if `xs` or `ys` only contain zeros. // // This is equivalent to `mpz_hamdist` from `mpz/hamdist.c`, GMP 6.2.1, where both arguments are // negative and have the same length. pub_test! {limbs_hamming_distance_neg(xs: &[Limb], ys: &[Limb]) -> u64 { let xs_i = slice_leading_zeros(xs); let ys_i = slice_leading_zeros(ys); match xs_i.cmp(&ys_i) { Equal => { xs[xs_i] .wrapping_neg() .hamming_distance(ys[ys_i].wrapping_neg()) + limbs_hamming_distance_neg_leading_limbs_helper(xs, ys, xs_i) } Less => limbs_hamming_distance_neg_helper(xs, ys, xs_i, ys_i), Greater => limbs_hamming_distance_neg_helper(ys, xs, ys_i, xs_i), } }} impl Natural { fn hamming_distance_neg_limb(&self, other: Limb) -> u64 { match self { Self(Small(small)) => small.wrapping_neg().hamming_distance(other.wrapping_neg()), Self(Large(limbs)) => limbs_hamming_distance_limb_neg(limbs, other), } } fn hamming_distance_neg(&self, other: &Self) -> u64 { match (self, other) { (&Self(Small(x)), _) => other.hamming_distance_neg_limb(x), (_, &Self(Small(y))) => self.hamming_distance_neg_limb(y), (Self(Large(xs)), Self(Large(ys))) => limbs_hamming_distance_neg(xs, ys), } } } impl CheckedHammingDistance<&Integer> for &Integer { /// Determines the Hamming distance between two [`Integer`]s. /// /// The two [`Integer`]s have infinitely many leading zeros or infinitely many leading ones, /// depending on their signs. If they are both non-negative or both negative, the Hamming /// distance is finite. If one is non-negative and the other is negative, the Hamming distance /// is infinite, so `None` is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::CheckedHammingDistance; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// Integer::from(123).checked_hamming_distance(&Integer::from(123)), /// Some(0) /// ); /// // 105 = 1101001b, 123 = 1111011 /// assert_eq!( /// Integer::from(-105).checked_hamming_distance(&Integer::from(-123)), /// Some(2) /// ); /// assert_eq!( /// Integer::from(-105).checked_hamming_distance(&Integer::from(123)), /// None /// ); /// ``` fn checked_hamming_distance(self, other: &Integer) -> Option { match (self.sign, other.sign) { (true, true) => Some(self.abs.hamming_distance(&other.abs)), (false, false) => Some(self.abs.hamming_distance_neg(&other.abs)), _ => None, } } } ================================================ FILE: malachite-nz/src/integer/logic/low_mask.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::logic::traits::LowMask; impl LowMask for Integer { /// Returns an [`Integer`] whose least significant $b$ bits are `true` and whose other bits are /// `false`. /// /// $f(b) = 2^b - 1$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::LowMask; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::low_mask(0), 0); /// assert_eq!(Integer::low_mask(3), 7); /// assert_eq!( /// Integer::low_mask(100).to_string(), /// "1267650600228229401496703205375" /// ); /// ``` #[inline] fn low_mask(bits: u64) -> Self { Self::from(Natural::low_mask(bits)) } } ================================================ FILE: malachite-nz/src/integer/logic/mod.rs ================================================ // Copyright © 2026 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 . /// Bitwise and of [`Integer`](super::Integer)s. pub mod and; /// An implementation of [`BitAccess`](malachite_base::num::logic::traits::BitAccess), a trait for /// getting and setting individual bits of a number. pub mod bit_access; /// An implementation of [`BitBlockAccess`](malachite_base::num::logic::traits::BitBlockAccess), a /// trait for getting and setting adjacent blocks of bits in a number. pub mod bit_block_access; /// An implementation of [`BitConvertible`](malachite_base::num::logic::traits::BitConvertible), a /// trait for extracting all bits from a number or constructing a number from bits. pub mod bit_convertible; /// An implementation of [`BitIterable`](malachite_base::num::logic::traits::BitIterable), a trait /// for producing a double-ended iterator over a number's bits. pub mod bit_iterable; /// An implementation of [`BitScan`](malachite_base::num::logic::traits::BitScan), a trait for /// finding the next `true` or `false` bit in a number after a provided index. pub mod bit_scan; /// A function counting the number of ones in the binary representation of a number. pub mod checked_count_ones; /// A function counting the number of zeros in the binary representation of a number. pub mod checked_count_zeros; /// An implementation of /// [`CheckedHammingDistance`](malachite_base::num::logic::traits::CheckedHammingDistance), a trait /// for computing the Hamming distance between two numbers. pub mod checked_hamming_distance; /// An implementation of [`LowMask`](malachite_base::num::logic::traits::LowMask), a trait for /// generating a low bit mask (a number in which only the $k$ least-significant bits are 1). pub mod low_mask; /// Bitwise negation of [`Integer`](super::Integer)s. pub mod not; /// Bitwise or of [`Integer`](super::Integer)s. pub mod or; /// An implementation of [`SignificantBits`](malachite_base::num::logic::traits::SignificantBits), a /// trait for determining how many significant bits a number has. pub mod significant_bits; /// An implementation of [`TrailingZeros`](malachite_base::num::logic::traits::TrailingZeros), a /// trait for determining the number of zeros that a number ends with when written in binary. pub mod trailing_zeros; /// Bitwise xor of [`Integer`](super::Integer)s. pub mod xor; ================================================ FILE: malachite-nz/src/integer/logic/not.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use core::ops::Not; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::NotAssign; impl Not for Integer { type Output = Self; /// Returns the bitwise negation of an [`Integer`], taking it by value. /// /// $$ /// f(n) = -n - 1. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(!Integer::ZERO, -1); /// assert_eq!(!Integer::from(123), -124); /// assert_eq!(!Integer::from(-123), 122); /// ``` #[inline] fn not(mut self) -> Self { self.not_assign(); self } } impl Not for &Integer { type Output = Integer; /// Returns the bitwise negation of an [`Integer`], taking it by reference. /// /// $$ /// f(n) = -n - 1. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(!&Integer::ZERO, -1); /// assert_eq!(!&Integer::from(123), -124); /// assert_eq!(!&Integer::from(-123), 122); /// ``` fn not(self) -> Integer { match self { Integer { sign: true, abs } => Integer { sign: false, abs: abs.add_limb_ref(1), }, Integer { sign: false, abs } => Integer { sign: true, abs: abs.sub_limb_ref(1), }, } } } impl NotAssign for Integer { /// Replaces an [`Integer`] with its bitwise negation. /// /// $$ /// n \gets -n - 1. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::NotAssign; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x.not_assign(); /// assert_eq!(x, -1); /// /// let mut x = Integer::from(123); /// x.not_assign(); /// assert_eq!(x, -124); /// /// let mut x = Integer::from(-123); /// x.not_assign(); /// assert_eq!(x, 122); /// ``` fn not_assign(&mut self) { if self.sign { self.sign = false; self.abs += Natural::ONE; } else { self.sign = true; self.abs -= Natural::ONE; } } } ================================================ FILE: malachite-nz/src/integer/logic/or.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012, 2013, 2015-2018 Free // Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::logic::not::{limbs_not_in_place, limbs_not_to_out}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::{Ordering::*, max}; use core::ops::{BitOr, BitOrAssign}; use itertools::repeat_n; use malachite_base::num::arithmetic::traits::WrappingNegAssign; use malachite_base::slices::{slice_leading_zeros, slice_set_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, returns the limbs of the bitwise or of the `Integer` and a `Limb`. `xs` cannot be // empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if `xs` is empty or only contains zeros. pub_test! {limbs_neg_or_limb(xs: &[Limb], y: Limb) -> Vec { if y == 0 { return xs.to_vec(); } let mut out = vec![0; xs.len()]; let i = slice_leading_zeros(xs); if i == 0 { out[0] = (xs[0].wrapping_neg() | y).wrapping_neg(); out[1..].copy_from_slice(&xs[1..]); } else { out[0] = y.wrapping_neg(); for x in &mut out[1..i] { *x = Limb::MAX; } out[i] = xs[i] - 1; out[i + 1..].copy_from_slice(&xs[i + 1..]); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise or of the `Integer` and a `Limb` to an output slice. // The output slice must be at least as long as the input slice. `xs` cannot be empty or only // contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if `xs` is empty or only contains zeros, or if `out` is shorter than `xs`. pub_test! {limbs_neg_or_limb_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) { let len = xs.len(); assert!(out.len() >= len); if y == 0 { out[..len].copy_from_slice(xs); return; } let i = slice_leading_zeros(xs); if i == 0 { out[0] = (xs[0].wrapping_neg() | y).wrapping_neg(); out[1..len].copy_from_slice(&xs[1..]); } else { out[0] = y.wrapping_neg(); for x in &mut out[1..i] { *x = Limb::MAX; } out[i] = xs[i] - 1; out[i + 1..len].copy_from_slice(&xs[i + 1..]); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise or of the `Integer`, writes the limbs of the bitwise // or of the `Integer` and a `Limb` to the input slice. `xs` cannot be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if `xs` is empty or only contains zeros. pub_test! {limbs_neg_or_limb_in_place(xs: &mut [Limb], y: Limb) { if y == 0 { return; } let i = slice_leading_zeros(xs); if i == 0 { xs[0] = (xs[0].wrapping_neg() | y).wrapping_neg(); } else { xs[0] = y.wrapping_neg(); for x in &mut xs[1..i] { *x = Limb::MAX; } xs[i] -= 1; } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, returns the // negative of the bitwise or of the `Integer` and a negative number whose lowest limb is given by // `y` and whose other limbs are full of `true` bits. The slice cannot be empty or only contain // zeros. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_const_test! {limbs_pos_or_neg_limb(xs: &[Limb], y: Limb) -> Limb { (xs[0] | y).wrapping_neg() }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, returns the negative of the bitwise or of the `Integer` and a negative number whose // lowest limb is given by `y` and whose other limbs are full of `true` bits. The slice cannot be // empty or only contain zeros. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_const_test! {limbs_neg_or_neg_limb(xs: &[Limb], y: Limb) -> Limb { (xs[0].wrapping_neg() | y).wrapping_neg() }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, returns the limbs of the bitwise or of the `Integer`s. `xs` and `ys` may not // be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is // `ys.len()`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res` is returned, the first // input is positive, and the second is negative. pub_test! {limbs_or_pos_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { let mut out = vec![0; x_i]; out.push(xs[x_i].wrapping_neg()); out.extend(xs[x_i + 1..].iter().map(|x| !x)); out.extend(repeat_n(Limb::MAX, y_i - xs_len)); out.push(ys[y_i] - 1); out.extend_from_slice(&ys[y_i + 1..]); out } else if x_i >= ys_len { ys.to_vec() } else { let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; let mut out = vec![0; min_i]; match x_i.cmp(&y_i) { Equal => { out.push((!xs[x_i] & (ys[y_i] - 1)) + 1); } Less => { out.push(xs[x_i].wrapping_neg()); out.extend(xs[x_i + 1..y_i].iter().map(|x| !x)); out.push(!xs[y_i] & (ys[y_i] - 1)); } Greater => { out.extend_from_slice(&ys[y_i..x_i]); out.push(!xs[x_i] & ys[x_i]); } } out.extend( xs[max_i + 1..] .iter() .zip(ys[max_i + 1..].iter()) .map(|(x, y)| !x & y), ); if xs_len < ys_len { out.extend_from_slice(&ys[xs_len..]); } out } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise or of the `Integer`s to an output slice. // `xs` and `ys` may not be empty or only contain zeros. The output slice must be at least as long // as the second input slice. `ys.len()` limbs will be written; if the number of significant limbs // of the result is lower, some of the written limbs will be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than `ys`. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where the first input is positive // and the second is negative. pub_test! {limbs_or_pos_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= ys_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { slice_set_zero(&mut out[..x_i]); out[x_i] = xs[x_i].wrapping_neg(); limbs_not_to_out(&mut out[x_i + 1..xs_len], &xs[x_i + 1..]); for x in &mut out[xs_len..y_i] { *x = Limb::MAX; } out[y_i] = ys[y_i] - 1; out[y_i + 1..ys_len].copy_from_slice(&ys[y_i + 1..]); } else if x_i >= ys_len { out[..ys_len].copy_from_slice(ys); } else { let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; slice_set_zero(&mut out[..min_i]); match x_i.cmp(&y_i) { Equal => { out[x_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1; } Less => { out[x_i] = xs[x_i].wrapping_neg(); limbs_not_to_out(&mut out[x_i + 1..y_i], &xs[x_i + 1..y_i]); out[y_i] = !xs[y_i] & (ys[y_i] - 1); } Greater => { out[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); out[x_i] = !xs[x_i] & ys[x_i]; } } for (out, (x, y)) in out[max_i + 1..] .iter_mut() .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter())) { *out = !x & y; } if xs_len < ys_len { out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]); } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise or of the `Integer`s to the first (left) // slice. `xs` and `ys` may not be empty or only contain zeros. Returns whether the result is too // large to be contained in the first slice; if it is, only the lowest `xs.len()` limbs are written. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1`, the first input // is positive and the second is negative, and the length of `op1` is not changed; instead, a carry // is returned. pub_test! {limbs_slice_or_pos_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..]); true } else if x_i >= ys_len { xs[..ys_len].copy_from_slice(ys); slice_set_zero(&mut xs[ys_len..]); false } else { let max_i = max(x_i, y_i); match x_i.cmp(&y_i) { Equal => { xs[x_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1; } Less => { xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..y_i]); xs[y_i] = !xs[y_i] & (ys[y_i] - 1); } Greater => { xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); xs[x_i] = !xs[x_i] & ys[x_i]; } } if xs_len < ys_len { for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..xs_len].iter()) { *x = !*x & y; } true } else { for (x, y) in xs[max_i + 1..ys_len].iter_mut().zip(ys[max_i + 1..].iter()) { *x = !*x & y; } slice_set_zero(&mut xs[ys_len..]); false } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise or of the `Integer`s to the first (left) // slice. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1` and the first // input is positive and the second is negative. pub_test! {limbs_vec_or_pos_neg_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..]); xs.extend(repeat_n(Limb::MAX, y_i - xs_len)); xs.push(ys[y_i] - 1); xs.extend_from_slice(&ys[y_i + 1..]); } else if x_i >= ys_len { *xs = ys.to_vec(); } else { let max_i = max(x_i, y_i); match x_i.cmp(&y_i) { Equal => { xs[x_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1; } Less => { xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..y_i]); xs[y_i] = !xs[y_i] & (ys[y_i] - 1); } Greater => { xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); xs[x_i] = !xs[x_i] & ys[x_i]; } } if xs_len < ys_len { for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..xs_len].iter()) { *x = !*x & y; } xs.extend_from_slice(&ys[xs_len..]); } else { for (x, y) in xs[max_i + 1..ys_len].iter_mut().zip(ys[max_i + 1..].iter()) { *x = !*x & y; } xs.truncate(ys_len); } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise or of the `Integer`s to the second (right) // slice. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op2` and the first // input is positive and the second is negative. pub_test! {limbs_or_pos_neg_in_place_right(xs: &[Limb], ys: &mut [Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { ys[x_i] = xs[x_i].wrapping_neg(); limbs_not_to_out(&mut ys[x_i + 1..xs_len], &xs[x_i + 1..]); for y in &mut ys[xs_len..y_i] { *y = Limb::MAX; } ys[y_i] -= 1; } else if x_i < ys_len { let max_i = max(x_i, y_i); match x_i.cmp(&y_i) { Equal => { ys[y_i] = (!xs[x_i] & (ys[y_i] - 1)) + 1; } Less => { ys[x_i] = xs[x_i].wrapping_neg(); limbs_not_to_out(&mut ys[x_i + 1..y_i], &xs[x_i + 1..y_i]); ys[y_i] = !xs[y_i] & (ys[y_i] - 1); } Greater => { ys[x_i] &= !xs[x_i]; } } if xs_len < ys_len { for (x, y) in xs[max_i + 1..].iter().zip(ys[max_i + 1..xs_len].iter_mut()) { *y &= !x; } } else { for (x, y) in xs[max_i + 1..ys_len].iter().zip(ys[max_i + 1..].iter_mut()) { *y &= !x; } } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, returns the limbs of the bitwise or of the `Integer`s. `xs` and `ys` may not be empty // or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is // `min(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res` is returned and both // inputs are negative. pub_test! {limbs_or_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { xs.to_vec() } else if x_i >= ys_len { ys.to_vec() } else { let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; let mut out = vec![0; min_i]; let x = match x_i.cmp(&y_i) { Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1, Less => { out.extend_from_slice(&xs[x_i..y_i]); xs[y_i] & (ys[y_i] - 1) } Greater => { out.extend_from_slice(&ys[y_i..x_i]); (xs[x_i] - 1) & ys[x_i] } }; out.push(x); out.extend( xs[max_i + 1..] .iter() .zip(ys[max_i + 1..].iter()) .map(|(x, y)| x & y), ); out } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise or of the `Integer`s to // an output slice. `xs` and `ys` may not be empty or only contain zeros. The output slice must be // at least as long as the shorter input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the shorter // of `xs` and `ys`. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are negative. pub_test! {limbs_or_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= xs_len || out.len() >= ys_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { out[..xs_len].copy_from_slice(xs); } else if x_i >= ys_len { out[..ys_len].copy_from_slice(ys); } else { let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; slice_set_zero(&mut out[..min_i]); let x = match x_i.cmp(&y_i) { Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1, Less => { out[x_i..y_i].copy_from_slice(&xs[x_i..y_i]); xs[y_i] & (ys[y_i] - 1) } Greater => { out[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); (xs[x_i] - 1) & ys[x_i] } }; out[max_i] = x; for (out, (x, y)) in out[max_i + 1..] .iter_mut() .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter())) { *out = x & y; } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the limbs of the bitwise or of the `Integer`s to the first (left) slice. `xs` // and `ys` may not be empty or only contain zeros. If the result has fewer significant limbs than // the left slice, the remaining limbs in the left slice are set to `Limb::MAX`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1`, both inputs are // negative, and the length of `op1` is not changed. pub_test! {limbs_slice_or_neg_neg_in_place_left(xs: &mut [Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { } else if x_i >= ys_len { xs[..ys_len].copy_from_slice(ys); slice_set_zero(&mut xs[ys_len..]); } else { let max_i = max(x_i, y_i); if x_i > y_i { xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); } xs[max_i] = match x_i.cmp(&y_i) { Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1, Less => xs[y_i] & (ys[y_i] - 1), Greater => (xs[x_i] - 1) & ys[x_i], }; for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) { *x &= y; } if xs_len > ys_len { slice_set_zero(&mut xs[ys_len..]); } } }} // Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of the // negatives of two `Integer`s, writes the limbs of the bitwise or of the `Integer`s to the `Vec`. // `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1` and both inputs // are negative. pub_test! {limbs_vec_or_neg_neg_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { } else if x_i >= ys_len { xs.truncate(ys_len); xs.copy_from_slice(ys); } else { let max_i = max(x_i, y_i); if x_i > y_i { xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); } xs[max_i] = match x_i.cmp(&y_i) { Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1, Less => xs[y_i] & (ys[y_i] - 1), Greater => (xs[x_i] - 1) & ys[x_i], }; for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) { *x &= y; } xs.truncate(ys_len); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the lower min(`xs.len()`, `ys.len()`) limbs of the bitwise or of the // `Integer`s to the shorter slice (or the first one, if they are equally long). `xs` and `ys` may // not be empty or only contain zeros. Returns a `bool` which is `false` when the output is to the // first slice and `true` when it's to the second slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are negative and // the result is written to the shorter input slice. pub_test! {limbs_or_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { false } else if x_i >= ys_len { true } else { let max_i = max(x_i, y_i); let boundary = match x_i.cmp(&y_i) { Equal => ((xs[x_i] - 1) & (ys[y_i] - 1)) + 1, Less => xs[y_i] & (ys[y_i] - 1), Greater => (xs[x_i] - 1) & ys[x_i], }; if xs_len > ys_len { if y_i > x_i { ys[x_i..y_i].copy_from_slice(&xs[x_i..y_i]); } ys[max_i] = boundary; for (y, x) in ys[max_i + 1..].iter_mut().zip(xs[max_i + 1..].iter()) { *y &= x; } true } else { if x_i > y_i { xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); } xs[max_i] = boundary; for (x, y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) { *x &= y; } false } } }} impl Natural { fn or_assign_pos_limb_neg(&mut self, other: Limb) { *self = self.or_pos_limb_neg(other); } fn or_pos_limb_neg(&self, other: Limb) -> Self { Self(Small(match self { Self(Small(small)) => (small | other).wrapping_neg(), Self(Large(limbs)) => limbs_pos_or_neg_limb(limbs, other), })) } fn or_assign_neg_limb_neg(&mut self, other: Limb) { *self = self.or_neg_limb_neg(other); } #[allow(clippy::missing_const_for_fn)] fn or_neg_limb_neg(&self, other: Limb) -> Self { Self(Small(match self { Self(Small(small)) => (small.wrapping_neg() | other).wrapping_neg(), Self(Large(limbs)) => limbs_neg_or_neg_limb(limbs, other), })) } fn or_assign_neg_limb_pos(&mut self, other: Limb) { match self { Self(Small(small)) => { *small = (small.wrapping_neg() | other).wrapping_neg(); } Self(Large(limbs)) => { limbs_neg_or_limb_in_place(limbs, other); self.trim(); } } } fn or_neg_limb_pos(&self, other: Limb) -> Self { match self { Self(Small(small)) => Self(Small((small.wrapping_neg() | other).wrapping_neg())), Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_neg_or_limb(limbs, other)), } } fn or_assign_pos_neg_ref(&mut self, other: &Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.or_assign_pos_limb_neg(y.wrapping_neg()), (Self(Small(x)), _) => *self = other.or_neg_limb_pos(*x), (Self(Large(xs)), Self(Large(ys))) => { limbs_vec_or_pos_neg_in_place_left(xs, ys); self.trim(); } } } fn or_assign_pos_neg(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.or_assign_pos_limb_neg(y.wrapping_neg()), (Self(Small(x)), _) => { other.or_assign_neg_limb_pos(*x); *self = other; } (Self(Large(xs)), Self(Large(ys))) => { limbs_or_pos_neg_in_place_right(xs, ys); *self = other; self.trim(); } } } fn or_assign_neg_pos_ref(&mut self, other: &Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.or_assign_neg_limb_pos(*y), (Self(Small(x)), _) => *self = other.or_pos_limb_neg(x.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { limbs_or_pos_neg_in_place_right(ys, xs); self.trim(); } } } fn or_assign_neg_pos(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.or_assign_neg_limb_pos(*y), (Self(Small(x)), _) => { other.or_assign_pos_limb_neg(x.wrapping_neg()); *self = other; } (Self(Large(xs)), Self(Large(ys))) => { limbs_or_pos_neg_in_place_right(ys, xs); self.trim(); } } } fn or_pos_neg(&self, other: &Self) -> Self { match (self, other) { (_, &Self(Small(y))) => self.or_pos_limb_neg(y.wrapping_neg()), (&Self(Small(x)), _) => other.or_neg_limb_pos(x), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_or_pos_neg(xs, ys)) } } } fn or_assign_neg_neg_ref(&mut self, other: &Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.or_assign_neg_limb_neg(y.wrapping_neg()), (Self(Small(x)), _) => *self = other.or_neg_limb_neg(x.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { limbs_vec_or_neg_neg_in_place_left(xs, ys); self.trim(); } } } fn or_assign_neg_neg(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.or_assign_neg_limb_neg(y.wrapping_neg()), (Self(Small(x)), _) => { other.or_assign_neg_limb_neg(x.wrapping_neg()); *self = other; } (Self(Large(xs)), Self(Large(ys))) => { if limbs_or_neg_neg_in_place_either(xs, ys) { *self = other; } self.trim(); } } } fn or_neg_neg(&self, other: &Self) -> Self { match (self, other) { (_, &Self(Small(y))) => self.or_neg_limb_neg(y.wrapping_neg()), (&Self(Small(x)), _) => other.or_neg_limb_neg(x.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_or_neg_neg(xs, ys)) } } } } impl BitOr for Integer { type Output = Self; /// Takes the bitwise or of two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) | Integer::from(-456), -67); /// assert_eq!( /// -Integer::from(10u32).pow(12) | -(Integer::from(10u32).pow(12) + Integer::ONE), /// -999999995905i64 /// ); /// ``` #[inline] fn bitor(mut self, other: Self) -> Self { self |= other; self } } impl<'a> BitOr<&'a Self> for Integer { type Output = Self; /// Takes the bitwise or of two [`Integer`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) | &Integer::from(-456), -67); /// assert_eq!( /// -Integer::from(10u32).pow(12) | &-(Integer::from(10u32).pow(12) + Integer::ONE), /// -999999995905i64 /// ); /// ``` #[inline] fn bitor(mut self, other: &'a Self) -> Self { self |= other; self } } impl BitOr for &Integer { type Output = Integer; /// Takes the bitwise or of two [`Integer`]s, taking the first by reference and the second by /// value. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) | Integer::from(-456), -67); /// assert_eq!( /// &-Integer::from(10u32).pow(12) | -(Integer::from(10u32).pow(12) + Integer::ONE), /// -999999995905i64 /// ); /// ``` #[inline] fn bitor(self, mut other: Integer) -> Integer { other |= self; other } } impl BitOr<&Integer> for &Integer { type Output = Integer; /// Takes the bitwise or of two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) | &Integer::from(-456), -67); /// assert_eq!( /// &-Integer::from(10u32).pow(12) | &-(Integer::from(10u32).pow(12) + Integer::ONE), /// -999999995905i64 /// ); /// ``` fn bitor(self, other: &Integer) -> Integer { match (self.sign, other.sign) { (true, true) => Integer { sign: true, abs: &self.abs | &other.abs, }, (true, false) => Integer { sign: false, abs: self.abs.or_pos_neg(&other.abs), }, (false, true) => Integer { sign: false, abs: other.abs.or_pos_neg(&self.abs), }, (false, false) => Integer { sign: false, abs: self.abs.or_neg_neg(&other.abs), }, } } } impl BitOrAssign for Integer { /// Bitwise-ors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x |= Integer::from(0x0000000f); /// x |= Integer::from(0x00000f00); /// x |= Integer::from(0x000f_0000); /// x |= Integer::from(0x0f000000); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitor_assign(&mut self, other: Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitor_assign(other.abs), (true, false) => { self.sign = false; self.abs.or_assign_pos_neg(other.abs); } (false, true) => self.abs.or_assign_neg_pos(other.abs), (false, false) => self.abs.or_assign_neg_neg(other.abs), } } } impl<'a> BitOrAssign<&'a Self> for Integer { /// Bitwise-ors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::ZERO; /// x |= &Integer::from(0x0000000f); /// x |= &Integer::from(0x00000f00); /// x |= &Integer::from(0x000f_0000); /// x |= &Integer::from(0x0f000000); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitor_assign(&mut self, other: &'a Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitor_assign(&other.abs), (true, false) => { self.sign = false; self.abs.or_assign_pos_neg_ref(&other.abs); } (false, true) => self.abs.or_assign_neg_pos_ref(&other.abs), (false, false) => self.abs.or_assign_neg_neg_ref(&other.abs), } } } ================================================ FILE: malachite-nz/src/integer/logic/significant_bits.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::logic::traits::SignificantBits; impl SignificantBits for &Integer { /// Returns the number of significant bits of an [`Integer`]'s absolute value. /// /// $$ /// f(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \lfloor \log_2 |n| \rfloor + 1 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::SignificantBits; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.significant_bits(), 0); /// assert_eq!(Integer::from(100).significant_bits(), 7); /// assert_eq!(Integer::from(-100).significant_bits(), 7); /// ``` fn significant_bits(self) -> u64 { self.abs.significant_bits() } } ================================================ FILE: malachite-nz/src/integer/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; impl Integer { /// Returns the number of trailing zeros in the binary expansion of an [`Integer`] /// (equivalently, the multiplicity of 2 in its prime factorization), or `None` is the /// [`Integer`] is 0. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::ZERO.trailing_zeros(), None); /// assert_eq!(Integer::from(3).trailing_zeros(), Some(0)); /// assert_eq!(Integer::from(-72).trailing_zeros(), Some(3)); /// assert_eq!(Integer::from(100).trailing_zeros(), Some(2)); /// assert_eq!((-Integer::from(10u32).pow(12)).trailing_zeros(), Some(12)); /// ``` pub fn trailing_zeros(&self) -> Option { self.abs.trailing_zeros() } } ================================================ FILE: malachite-nz/src/integer/logic/xor.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012, 2015-2018 Free Software // Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_limb, limbs_add_limb_to_out, limbs_slice_add_limb_in_place, }; use crate::natural::arithmetic::sub::{ limbs_sub, limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb, limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_vec_sub_in_place_right, }; use crate::natural::logic::not::limbs_not_in_place; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::{Ordering::*, max}; use core::ops::{BitXor, BitXorAssign}; use itertools::repeat_n; use malachite_base::num::arithmetic::traits::WrappingNegAssign; use malachite_base::num::basic::traits::Zero; use malachite_base::slices::{slice_leading_zeros, slice_set_zero, slice_test_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, returns the limbs of the bitwise xor of the `Integer` and a `Limb`. `xs` cannot be // empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_neg_xor_limb(xs: &[Limb], y: Limb) -> Vec { if y == 0 { return xs.to_vec(); } let head = xs[0]; let tail = &xs[1..]; let mut out = Vec::with_capacity(xs.len()); if head != 0 { let head = head.wrapping_neg() ^ y; if head == 0 { out.push(0); out.extend_from_slice(&limbs_add_limb(tail, 1)); } else { out.push(head.wrapping_neg()); out.extend_from_slice(tail); } } else { out.push(y.wrapping_neg()); out.extend_from_slice(&limbs_sub_limb(tail, 1).0); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise and of the `Integer`, writes the limbs of the bitwise // xor of the `Integer` and a `Limb` to an output slice. The output slice must be at least as long // as the input slice. `xs` cannot be empty or only contain zeros. Returns whether a carry occurs. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_neg_xor_limb_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool { let len = xs.len(); assert!(out.len() >= len); if y == 0 { out[..len].copy_from_slice(xs); return false; } let head = xs[0]; let tail = &xs[1..]; if head != 0 { let head = head.wrapping_neg() ^ y; if head == 0 { out[0] = 0; limbs_add_limb_to_out(&mut out[1..len], tail, 1) } else { out[0] = head.wrapping_neg(); out[1..len].copy_from_slice(tail); false } } else { out[0] = y.wrapping_neg(); limbs_sub_limb_to_out(&mut out[1..len], tail, 1); false } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise xor of the `Integer` and a `Limb` to the input slice. // `xs` cannot be empty or only contain zeros. Returns whether a carry occurs. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_slice_neg_xor_limb_in_place(xs: &mut [Limb], y: Limb) -> bool { if y == 0 { return false; } let (head, tail) = xs.split_at_mut(1); let head = &mut head[0]; if *head != 0 { *head = head.wrapping_neg() ^ y; if *head == 0 { limbs_slice_add_limb_in_place(tail, 1) } else { head.wrapping_neg_assign(); false } } else { *head = y.wrapping_neg(); limbs_sub_limb_in_place(tail, 1); false } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise xor of the `Integer` and a `Limb` to the input slice. // `xs` cannot be empty or only contain zeros. If a carry occurs, extends the `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_vec_neg_xor_limb_in_place(xs: &mut Vec, y: Limb) { if limbs_slice_neg_xor_limb_in_place(xs, y) { xs.push(1); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, returns the // limbs of the bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` // and whose other limbs are full of `true` bits. `xs` may not be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_pos_xor_limb_neg(xs: &[Limb], y: Limb) -> Vec { let (head, tail) = xs.split_first().unwrap(); let lo = head ^ y; let mut out; if lo == 0 { out = limbs_add_limb(tail, 1); out.insert(0, 0); } else { out = xs.to_vec(); out[0] = lo.wrapping_neg(); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, writes the // limbs of the bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` // and whose other limbs are full of `true` bits to an output slice. `xs` may not be empty or only // contain zeros. The output slice must be at least as long as the input slice. Returns whether // there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or if `out` is shorter than `xs`. pub_test! {limbs_pos_xor_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) -> bool { let (head, tail) = xs.split_first().unwrap(); let (out_head, out_tail) = out[..xs.len()].split_first_mut().unwrap(); let lo = head ^ y; if lo == 0 { *out_head = 0; limbs_add_limb_to_out(out_tail, tail, 1) } else { *out_head = lo.wrapping_neg(); out_tail.copy_from_slice(tail); false } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of an `Integer`, takes the // bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` and whose // other limbs are full of `true` bits, in place. `xs` may not be empty. Returns whether there is a // carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_slice_pos_xor_limb_neg_in_place(xs: &mut [Limb], y: Limb) -> bool { let (head, tail) = xs.split_at_mut(1); let head = &mut head[0]; *head ^= y; if *head == 0 { limbs_slice_add_limb_in_place(tail, 1) } else { *head = head.wrapping_neg(); false } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of an `Integer`, takes the // bitwise xor of the `Integer` and a negative number whose lowest limb is given by `y` and whose // other limbs are full of `true` bits, in place. `xs` may not be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_vec_pos_xor_limb_neg_in_place(xs: &mut Vec, y: Limb) { if limbs_slice_pos_xor_limb_neg_in_place(xs, y) { xs.push(1); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, returns the limbs of the bitwise xor of the `Integer` and a negative number whose // lowest limb is given by `y` and whose other limbs are full of `true` bits. `xs` may not be empty // or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or only contains zeros. pub_test! {limbs_neg_xor_limb_neg(xs: &[Limb], y: Limb) -> Vec { let mut out; if xs[0] == 0 { let carry; (out, carry) = limbs_sub_limb(xs, 1); assert!(!carry); out[0] = y; } else { out = xs.to_vec(); out[0] = xs[0].wrapping_neg() ^ y; } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, writes the limbs of the bitwise xor of the `Integer` and a negative number whose // lowest limb is given by `y` and whose other limbs are full of `true` bits to an output slice. // `xs` may not be empty or only contain zeros. The output slice must be at least as long as the // input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or only contains zeros, or if `out` is shorter than `xs`. pub_test! {limbs_neg_xor_limb_neg_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) { let (head, tail) = xs.split_first().unwrap(); let (out_head, out_tail) = out[..xs.len()].split_first_mut().unwrap(); if *head == 0 { *out_head = y; assert!(!limbs_sub_limb_to_out(out_tail, tail, 1)); } else { *out_head = xs[0].wrapping_neg() ^ y; out_tail.copy_from_slice(tail); } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of the negative of an // `Integer`, takes the bitwise xor of the `Integer` and a negative number whose lowest limb is // given by `y` and whose other limbs are full of `true` bits, in place. `xs` may not be empty or // only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or only contains zeros. pub_test! {limbs_neg_xor_limb_neg_in_place(xs: &mut [Limb], y: Limb) { let (head, tail) = xs.split_first_mut().unwrap(); if *head == 0 { assert!(!limbs_sub_limb_in_place(tail, 1)); *head = y; } else { head.wrapping_neg_assign(); *head ^= y; } }} const fn limbs_xor_pos_neg_helper(x: Limb, boundary_seen: &mut bool) -> Limb { if *boundary_seen { !x } else if x == 0 { 0 } else { *boundary_seen = true; x.wrapping_neg() } } // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, returns the limbs of the bitwise xor of the `Integer`s. `xs` and `ys` may // not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned, the first // input is positive, and the second is negative. pub_test! {limbs_xor_pos_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { let mut out = vec![0; x_i]; out.push(xs[x_i].wrapping_neg()); out.extend(xs[x_i + 1..].iter().map(|x| !x)); out.extend(repeat_n(Limb::MAX, y_i - xs_len)); out.push(ys[y_i] - 1); out.extend_from_slice(&ys[y_i + 1..]); return out; } else if x_i >= ys_len { let mut out = ys.to_vec(); out.extend_from_slice(&xs[ys_len..]); return out; } let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; let mut out = vec![0; min_i]; let mut boundary_seen = false; let x = match x_i.cmp(&y_i) { Equal => { limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen) } Less => { boundary_seen = true; out.push(xs[x_i].wrapping_neg()); out.extend(xs[x_i + 1..y_i].iter().map(|x| !x)); xs[y_i] ^ (ys[y_i] - 1) } Greater => { boundary_seen = true; out.extend_from_slice(&ys[y_i..x_i]); xs[x_i] ^ ys[x_i] } }; out.push(x); let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter()); if boundary_seen { out.extend(xys.map(|(x, y)| x ^ y)); } else { for (&x, &y) in xys { out.push(limbs_xor_pos_neg_helper(x ^ !y, &mut boundary_seen)); } } if xs_len != ys_len { let zs = if xs_len > ys_len { &xs[ys_len..] } else { &ys[xs_len..] }; if boundary_seen { out.extend_from_slice(zs); } else { for &z in zs { out.push(limbs_xor_pos_neg_helper(!z, &mut boundary_seen)); } } } if slice_test_zero(&out) { out.push(1); } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise xor of the `Integer`s to an output slice. // `xs` and `ys` may not be empty or only contain zeros. The output slice must be at least as long // as the longer of the two input slices. max(`xs.len()`, `ys.len()`) limbs will be written; if the // number of significant limbs of the result is lower, some of the written limbs will be zero. // // Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of // `xs` and `ys`. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where the first input is positive // and the second is negative. pub_test! {limbs_xor_pos_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= xs_len); assert!(out.len() >= ys_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { slice_set_zero(&mut out[..x_i]); out[x_i] = xs[x_i].wrapping_neg(); for (out, &x) in out[x_i + 1..xs_len].iter_mut().zip(xs[x_i + 1..].iter()) { *out = !x; } for out in &mut out[xs_len..y_i] { *out = Limb::MAX; } out[y_i] = ys[y_i] - 1; out[y_i + 1..ys_len].copy_from_slice(&ys[y_i + 1..]); return false; } else if x_i >= ys_len { out[..ys_len].copy_from_slice(ys); out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); return false; } let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; slice_set_zero(&mut out[..min_i]); let mut boundary_seen = false; match x_i.cmp(&y_i) { Equal => { out[x_i] = limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen); } Less => { boundary_seen = true; out[x_i] = xs[x_i].wrapping_neg(); for (out, &x) in out[x_i + 1..y_i].iter_mut().zip(xs[x_i + 1..y_i].iter()) { *out = !x; } out[y_i] = xs[y_i] ^ (ys[y_i] - 1); } Greater => { boundary_seen = true; out[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); out[x_i] = xs[x_i] ^ ys[x_i]; } } let xys = out[max_i + 1..] .iter_mut() .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter())); if boundary_seen { for (out, (&x, &y)) in xys { *out = x ^ y; } } else { for (out, (&x, &y)) in xys { *out = limbs_xor_pos_neg_helper(x ^ !y, &mut boundary_seen); } } let max_len = max(xs_len, ys_len); if xs_len != ys_len { let (min_len, zs) = if max_len == xs_len { (ys_len, &xs[ys_len..]) } else { (xs_len, &ys[xs_len..]) }; if boundary_seen { out[min_len..max_len].copy_from_slice(zs); } else { for (out, &z) in out[min_len..].iter_mut().zip(zs.iter()) { *out = limbs_xor_pos_neg_helper(!z, &mut boundary_seen); } } } slice_test_zero(&out[..max_len]) }} fn limbs_xor_pos_neg_in_place_left_helper( xs: &mut [Limb], ys: &[Limb], x_i: usize, y_i: usize, ) -> bool { let max_i = max(x_i, y_i); let mut boundary_seen = false; match x_i.cmp(&y_i) { Equal => { xs[x_i] = limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen); } Less => { boundary_seen = true; xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..y_i]); xs[y_i] ^= ys[y_i] - 1; } Greater => { boundary_seen = true; xs[y_i..x_i].copy_from_slice(&ys[y_i..x_i]); xs[x_i] ^= ys[x_i]; } } let xys = xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()); if boundary_seen { for (x, &y) in xys { *x ^= y; } } else { for (x, &y) in xys { *x = limbs_xor_pos_neg_helper(*x ^ !y, &mut boundary_seen); } } boundary_seen } // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of one // `Integer` and the negative of another, writes the limbs of the bitwise xor of the `Integer`s to // the `Vec`. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and the first // input is positive and the second is negative. pub_test! {limbs_xor_pos_neg_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { xs[x_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[x_i + 1..]); xs.extend(repeat_n(Limb::MAX, y_i - xs_len)); xs.push(ys[y_i] - 1); xs.extend_from_slice(&ys[y_i + 1..]); return; } else if x_i >= ys_len { xs[..ys_len].copy_from_slice(ys); return; } let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i); match xs_len.cmp(&ys_len) { Less => { if boundary_seen { xs.extend_from_slice(&ys[xs_len..]); } else { for &y in &ys[xs_len..] { xs.push(limbs_xor_pos_neg_helper(!y, &mut boundary_seen)); } } } Greater => { if !boundary_seen { for x in &mut xs[ys_len..] { *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen); } } } _ => {} } if slice_test_zero(xs) { xs.push(1); } }} fn limbs_xor_pos_neg_in_place_right_helper( xs: &[Limb], ys: &mut [Limb], x_i: usize, y_i: usize, ) -> bool { let max_i = max(x_i, y_i); let mut boundary_seen = false; match x_i.cmp(&y_i) { Equal => { ys[y_i] = limbs_xor_pos_neg_helper(xs[x_i] ^ ys[y_i].wrapping_neg(), &mut boundary_seen); } Less => { boundary_seen = true; ys[x_i] = xs[x_i].wrapping_neg(); for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..y_i].iter()) { *y = !x; } ys[y_i] -= 1; ys[y_i] ^= xs[y_i]; } Greater => { boundary_seen = true; ys[x_i] ^= xs[x_i]; } } let xys = xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter_mut()); if boundary_seen { for (&x, y) in xys { *y ^= x; } } else { for (&x, y) in xys { *y = limbs_xor_pos_neg_helper(x ^ !*y, &mut boundary_seen); } } boundary_seen } // Interpreting a slice of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of one // `Integer` and the negative of another, writes the limbs of the bitwise xor of the `Integer`s to // the second (right) slice. `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op2` and the first // input is positive and the second is negative. pub_test! {limbs_xor_pos_neg_in_place_right(xs: &[Limb], ys: &mut Vec) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { ys[x_i] = xs[x_i].wrapping_neg(); for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) { *y = !x; } for y in ys.iter_mut().take(y_i).skip(xs_len) { *y = Limb::MAX; } ys[y_i] -= 1; return; } else if x_i >= ys_len { ys.extend_from_slice(&xs[ys_len..]); return; } let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i); if xs_len > ys_len { if boundary_seen { ys.extend_from_slice(&xs[ys_len..]); } else { for &x in &xs[ys_len..] { ys.push(limbs_xor_pos_neg_helper(!x, &mut boundary_seen)); } } } else if xs_len < ys_len && !boundary_seen { for y in &mut ys[xs_len..] { *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen); } } if slice_test_zero(ys) { ys.push(1); } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of one `Integer` and the // negative of another, writes the limbs of the bitwise xor of the `Integer`s to the longer `Vec` // (or the first one, if they are equally long). `xs` and `ys` may not be empty or only contain // zeros. Returns a `bool` which is `false` when the output is to the first `Vec` and `true` when // it's to the second `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where the first input is positive, // the second is negative, and the result is written to the longer input slice. pub_test! {limbs_xor_pos_neg_in_place_either(xs: &mut Vec, ys: &mut Vec) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { ys[x_i] = xs[x_i].wrapping_neg(); for (y, &x) in ys[x_i + 1..].iter_mut().zip(xs[x_i + 1..].iter()) { *y = !x; } for y in &mut ys[xs_len..y_i] { *y = Limb::MAX; } ys[y_i] -= 1; return true; } else if x_i >= ys_len { xs[..ys_len].copy_from_slice(ys); return false; } if xs_len >= ys_len { let mut boundary_seen = limbs_xor_pos_neg_in_place_left_helper(xs, ys, x_i, y_i); if xs_len != ys_len && !boundary_seen { for x in &mut xs[ys_len..] { *x = limbs_xor_pos_neg_helper(!*x, &mut boundary_seen); } } if slice_test_zero(xs) { xs.push(1); } false } else { let mut boundary_seen = limbs_xor_pos_neg_in_place_right_helper(xs, ys, x_i, y_i); if !boundary_seen { for y in &mut ys[xs_len..] { *y = limbs_xor_pos_neg_helper(!*y, &mut boundary_seen); } } if slice_test_zero(ys) { ys.push(1); } true } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, returns the limbs of the bitwise xor of the `Integer`s. `xs` and `ys` may not be // empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned and both // inputs are negative. pub_test! {limbs_xor_neg_neg(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { let (result, borrow) = limbs_sub(ys, xs); assert!(!borrow); return result; } else if x_i >= ys_len { let (result, borrow) = limbs_sub(xs, ys); assert!(!borrow); return result; } let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; let mut out = vec![0; min_i]; if x_i == y_i { out.push(xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg()); } else { let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) }; out.push(min_zs[min_i].wrapping_neg()); out.extend(min_zs[min_i + 1..max_i].iter().map(|z| !z)); out.push((max_zs[max_i] - 1) ^ min_zs[max_i]); } out.extend( xs[max_i + 1..] .iter() .zip(ys[max_i + 1..].iter()) .map(|(x, y)| x ^ y), ); match xs_len.cmp(&ys_len) { Less => out.extend_from_slice(&ys[xs_len..]), Greater => out.extend_from_slice(&xs[ys_len..]), _ => {} } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the max(`xs.len()`, `ys.len()`) limbs of the bitwise xor of the `Integer`s to // an output slice. `xs` and `ys` may not be empty or only contain zeros. The output slice must be // at least as long as the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros, or if `out` is shorter than the longer of // `xs` and `ys`. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative. pub_test! {limbs_xor_neg_neg_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= xs_len); assert!(out.len() >= ys_len); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { assert!(!limbs_sub_greater_to_out(out, ys, xs)); return; } else if x_i >= ys_len { assert!(!limbs_sub_greater_to_out(out, xs, ys)); return; } let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; slice_set_zero(&mut out[..min_i]); if x_i == y_i { out[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg(); } else { let (min_zs, max_zs) = if x_i <= y_i { (xs, ys) } else { (ys, xs) }; out[min_i] = min_zs[min_i].wrapping_neg(); for (out, &z) in out[min_i + 1..max_i] .iter_mut() .zip(min_zs[min_i + 1..max_i].iter()) { *out = !z; } out[max_i] = (max_zs[max_i] - 1) ^ min_zs[max_i]; } for (out, (&x, &y)) in out[max_i + 1..] .iter_mut() .zip(xs[max_i + 1..].iter().zip(ys[max_i + 1..].iter())) { *out = x ^ y; } match xs_len.cmp(&ys_len) { Less => out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]), Greater => out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]), _ => {} } }} fn limbs_xor_neg_neg_in_place_helper(xs: &mut [Limb], ys: &[Limb], x_i: usize, y_i: usize) { let (min_i, max_i) = if x_i <= y_i { (x_i, y_i) } else { (y_i, x_i) }; if x_i == y_i { xs[x_i] = xs[x_i].wrapping_neg() ^ ys[x_i].wrapping_neg(); } else if x_i <= y_i { xs[min_i].wrapping_neg_assign(); limbs_not_in_place(&mut xs[min_i + 1..max_i]); xs[max_i] ^= ys[max_i] - 1; } else { xs[min_i] = ys[min_i].wrapping_neg(); for (x, &y) in xs[min_i + 1..max_i].iter_mut().zip(ys[min_i + 1..].iter()) { *x = !y; } xs[max_i] -= 1; xs[max_i] ^= ys[max_i]; } for (x, &y) in xs[max_i + 1..].iter_mut().zip(ys[max_i + 1..].iter()) { *x ^= y; } } // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of the // negatives of two `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the `Vec`. // `xs` and `ys` may not be empty or only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and both inputs // are negative. pub_test! {limbs_xor_neg_neg_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { assert!(!limbs_vec_sub_in_place_right(ys, xs)); } else if x_i >= ys_len { assert!(!limbs_sub_greater_in_place_left(xs, ys)); } else { limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i); if xs_len < ys_len { xs.extend_from_slice(&ys[xs_len..]); } } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of the negatives of two // `Integer`s, writes the limbs of the bitwise xor of the `Integer`s to the longer slice (or the // first one, if they are equally long). `xs` and `ys` may not be empty or only contain zeros. // Returns `false` when the output is to the first slice and `true` when it's to the second slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` or `ys` are empty or contain only zeros. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are negative and // the result is written to the longer input slice. pub_test! {limbs_xor_neg_neg_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let x_i = slice_leading_zeros(xs); let y_i = slice_leading_zeros(ys); assert!(x_i < xs_len); assert!(y_i < ys_len); if y_i >= xs_len { assert!(!limbs_sub_greater_in_place_left(ys, xs)); true } else if x_i >= ys_len { assert!(!limbs_sub_greater_in_place_left(xs, ys)); false } else if xs_len >= ys_len { limbs_xor_neg_neg_in_place_helper(xs, ys, x_i, y_i); false } else { limbs_xor_neg_neg_in_place_helper(ys, xs, y_i, x_i); true } }} impl Natural { fn xor_assign_neg_limb_pos(&mut self, other: Limb) { match self { &mut Self::ZERO => {} Self(Small(small)) => { let result = small.wrapping_neg() ^ other; if result == 0 { *self = Self(Large(vec![0, 1])); } else { *small = result.wrapping_neg(); } } Self(Large(limbs)) => { limbs_vec_neg_xor_limb_in_place(limbs, other); self.trim(); } } } fn xor_neg_limb_pos(&self, other: Limb) -> Self { match self { &Self::ZERO => self.clone(), Self(Small(small)) => { let result = small.wrapping_neg() ^ other; Self(if result == 0 { Large(vec![0, 1]) } else { Small(result.wrapping_neg()) }) } Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_neg_xor_limb(limbs, other)), } } fn xor_assign_pos_limb_neg(&mut self, other: Limb) { match self { Self(Small(small)) => { let result = *small ^ other; if result == 0 { *self = Self(Large(vec![0, 1])); } else { *small = result.wrapping_neg(); } } Self(Large(limbs)) => { limbs_vec_pos_xor_limb_neg_in_place(limbs, other); self.trim(); } } } fn xor_pos_limb_neg(&self, other: Limb) -> Self { Self(match self { Self(Small(small)) => { let result = small ^ other; if result == 0 { Large(vec![0, 1]) } else { Small(result.wrapping_neg()) } } Self(Large(limbs)) => Large(limbs_pos_xor_limb_neg(limbs, other)), }) } fn xor_assign_neg_limb_neg(&mut self, other: Limb) { match &mut *self { Self(Small(small)) => *small = small.wrapping_neg() ^ other, Self(Large(limbs)) => { limbs_neg_xor_limb_neg_in_place(limbs, other); self.trim(); } } } fn xor_neg_limb_neg(&self, other: Limb) -> Self { match self { Self(Small(small)) => Self(Small(small.wrapping_neg() ^ other)), Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_neg_xor_limb_neg(limbs, other)), } } fn xor_assign_pos_neg(&mut self, mut other: Self) { match (&mut *self, &mut other) { (Self(Small(x)), _) => { other.xor_assign_neg_limb_pos(*x); *self = other; } (_, Self(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { if limbs_xor_pos_neg_in_place_either(xs, ys) { *self = other; } self.trim(); } } } fn xor_assign_pos_neg_ref(&mut self, other: &Self) { match (&mut *self, other) { (Self(Small(x)), _) => *self = other.xor_neg_limb_pos(*x), (_, Self(Small(y))) => self.xor_assign_pos_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { limbs_xor_pos_neg_in_place_left(xs, ys); self.trim(); } } } fn xor_assign_neg_pos(&mut self, mut other: Self) { other.xor_assign_pos_neg_ref(&*self); *self = other; } fn xor_assign_neg_pos_ref(&mut self, other: &Self) { match (&mut *self, other) { (Self(Small(x)), _) => *self = other.xor_pos_limb_neg(x.wrapping_neg()), (_, Self(Small(y))) => self.xor_assign_neg_limb_pos(*y), (Self(Large(xs)), Self(Large(ys))) => { limbs_xor_pos_neg_in_place_right(ys, xs); self.trim(); } } } fn xor_pos_neg(&self, other: &Self) -> Self { match (self, other) { (&Self(Small(x)), _) => other.xor_neg_limb_pos(x), (_, &Self(Small(y))) => self.xor_pos_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_xor_pos_neg(xs, ys)) } } } fn xor_assign_neg_neg(&mut self, mut other: Self) { match (&mut *self, &mut other) { (Self(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()), (_, Self(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { if limbs_xor_neg_neg_in_place_either(xs, ys) { *self = other; } self.trim(); } } } fn xor_assign_neg_neg_ref(&mut self, other: &Self) { match (&mut *self, other) { (Self(Small(x)), _) => *self = other.xor_neg_limb_neg(x.wrapping_neg()), (_, Self(Small(y))) => self.xor_assign_neg_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { limbs_xor_neg_neg_in_place_left(xs, ys); self.trim(); } } } fn xor_neg_neg(&self, other: &Self) -> Self { match (self, other) { (&Self(Small(x)), _) => other.xor_neg_limb_neg(x.wrapping_neg()), (_, &Self(Small(y))) => self.xor_neg_limb_neg(y.wrapping_neg()), (Self(Large(xs)), Self(Large(ys))) => { Self::from_owned_limbs_asc(limbs_xor_neg_neg(xs, ys)) } } } } impl BitXor for Integer { type Output = Self; /// Takes the bitwise xor of two [`Integer`]s, taking both by value. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) ^ Integer::from(-456), 445); /// assert_eq!( /// -Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(mut self, other: Self) -> Self { self ^= other; self } } impl BitXor<&Self> for Integer { type Output = Self; /// Takes the bitwise xor of two [`Integer`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(Integer::from(-123) ^ &Integer::from(-456), 445); /// assert_eq!( /// -Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(mut self, other: &Self) -> Self { self ^= other; self } } impl BitXor for &Integer { type Output = Integer; /// Takes the bitwise xor of two [`Integer`]s, taking the first by reference and the second by /// value. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) ^ Integer::from(-456), 445); /// assert_eq!( /// &-Integer::from(10u32).pow(12) ^ -(Integer::from(10u32).pow(12) + Integer::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(self, mut other: Integer) -> Integer { other ^= self; other } } impl BitXor<&Integer> for &Integer { type Output = Integer; /// Takes the bitwise xor of two [`Integer`]s, taking both by reference. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::integer::Integer; /// /// assert_eq!(&Integer::from(-123) ^ &Integer::from(-456), 445); /// assert_eq!( /// &-Integer::from(10u32).pow(12) ^ &-(Integer::from(10u32).pow(12) + Integer::ONE), /// 8191 /// ); /// ``` fn bitxor(self, other: &Integer) -> Integer { match (self.sign, other.sign) { (true, true) => Integer { sign: true, abs: &self.abs ^ &other.abs, }, (true, false) => Integer { sign: false, abs: self.abs.xor_pos_neg(&other.abs), }, (false, true) => Integer { sign: false, abs: other.abs.xor_pos_neg(&self.abs), }, (false, false) => Integer { sign: true, abs: self.abs.xor_neg_neg(&other.abs), }, } } } impl BitXorAssign for Integer { /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by value. /// /// $$ /// x \gets x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(u32::MAX); /// x ^= Integer::from(0x0000000f); /// x ^= Integer::from(0x00000f00); /// x ^= Integer::from(0x000f_0000); /// x ^= Integer::from(0x0f000000); /// assert_eq!(x, 0xf0f0_f0f0u32); /// ``` fn bitxor_assign(&mut self, other: Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitxor_assign(other.abs), (true, false) => { self.sign = false; self.abs.xor_assign_pos_neg(other.abs); } (false, true) => self.abs.xor_assign_neg_pos(other.abs), (false, false) => { self.sign = true; self.abs.xor_assign_neg_neg(other.abs); } } } } impl BitXorAssign<&Self> for Integer { /// Bitwise-xors an [`Integer`] with another [`Integer`] in place, taking the [`Integer`] on the /// right-hand side by reference. /// /// $$ /// x \gets x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.significant_bits())`, and $m$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// /// let mut x = Integer::from(u32::MAX); /// x ^= &Integer::from(0x0000000f); /// x ^= &Integer::from(0x00000f00); /// x ^= &Integer::from(0x000f_0000); /// x ^= &Integer::from(0x0f000000); /// assert_eq!(x, 0xf0f0_f0f0u32); /// ``` fn bitxor_assign(&mut self, other: &Self) { match (self.sign, other.sign) { (true, true) => self.abs.bitxor_assign(&other.abs), (true, false) => { self.sign = false; self.abs.xor_assign_pos_neg_ref(&other.abs); } (false, true) => self.abs.xor_assign_neg_pos_ref(&other.abs), (false, false) => { self.sign = true; self.abs.xor_assign_neg_neg_ref(&other.abs); } } } } ================================================ FILE: malachite-nz/src/integer/mod.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use alloc::string::String; use malachite_base::named::Named; use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; /// An integer. /// /// Any `Integer` whose absolute value is small enough to fit into a [`Limb`](crate#limbs) is /// represented inline. Only integers outside this range incur the costs of heap-allocation. #[derive(Clone, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr( feature = "serde", serde(try_from = "SerdeInteger", into = "SerdeInteger") )] pub struct Integer { // whether the `Integer` is non-negative pub(crate) sign: bool, pub(crate) abs: Natural, } #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] pub(crate) struct SerdeInteger(String); impl Integer { // Returns true iff `self` is valid. // // To be valid, its absolute value must be valid, and if the absolute value is zero, the sign // must be `true`. All `Integer`s must be valid. #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { self.abs.is_valid() && (self.sign || self.abs != 0) } } macro_rules! integer_zero { () => { Integer { sign: true, abs: Natural::ZERO, } }; } macro_rules! integer_one { () => { Integer { sign: true, abs: Natural::ONE, } }; } macro_rules! integer_two { () => { Integer { sign: true, abs: Natural::TWO, } }; } macro_rules! integer_negative_one { () => { Integer { sign: false, abs: Natural::ONE, } }; } /// The constant 0. impl Zero for Integer { const ZERO: Self = integer_zero!(); } /// The constant 1. impl One for Integer { const ONE: Self = integer_one!(); } /// The constant 2. impl Two for Integer { const TWO: Self = integer_two!(); } /// The constant -1. impl NegativeOne for Integer { const NEGATIVE_ONE: Self = integer_negative_one!(); } impl Default for Integer { /// The default value of an [`Integer`], 0. fn default() -> Self { Self::ZERO } } // Implements `Named` for `Integer`. impl_named!(Integer); /// Traits for arithmetic. pub mod arithmetic; /// Traits for comparing [`Integer`]s for equality or order. pub mod comparison; /// Traits for converting to and from [`Integer`]s, converting to and from strings, and extracting /// digits. pub mod conversion; /// Iterators that generate [`Integer`]s without repetition. pub mod exhaustive; /// Traits for logic and bit manipulation. pub mod logic; #[cfg(feature = "random")] /// Iterators that generate [`Integer`]s randomly. pub mod random; ================================================ FILE: malachite-nz/src/integer/random/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::random::{ RandomNaturalsLessThan, StripedRandomNaturalInclusiveRange, get_random_natural_less_than, get_random_natural_with_bits, get_striped_random_natural_from_inclusive_range, get_striped_random_natural_with_bits, random_naturals_less_than, striped_random_natural_inclusive_range, }; use malachite_base::bools::random::{RandomBools, random_bools}; use malachite_base::num::arithmetic::traits::{PowerOf2, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomNegativeSigneds, GeometricRandomNonzeroSigneds, GeometricRandomSignedRange, GeometricRandomSigneds, geometric_random_natural_signeds, geometric_random_negative_signeds, geometric_random_nonzero_signeds, geometric_random_positive_signeds, geometric_random_signed_inclusive_range, geometric_random_signeds, get_geometric_random_signed_from_inclusive_range, }; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::num::random::{ RandomPrimitiveInts, VariableRangeGenerator, random_primitive_ints, }; use malachite_base::random::Seed; /// Generates random [`Integer`]s, given an iterator of random signed bit lengths. /// /// The [`Integer`]'s signs are taken from the signs of the bit lengths. #[derive(Clone, Debug)] pub struct RandomIntegers> { bits: I, limbs: RandomPrimitiveInts, } impl> Iterator for RandomIntegers { type Item = Integer; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); Some(Integer::from_sign_and_abs( bits >= 0, get_random_natural_with_bits(&mut self.limbs, bits.unsigned_abs()), )) } } /// Generates random natural (non-negative) [`Integer`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 0. Then an [`Integer`] /// is chosen uniformly among all non-negative [`Integer`]s with that bit length. The resulting /// distribution resembles a Pareto distribution. It has no mean or higher-order statistics (unless /// $m < 1$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n < 0, \\\\ /// \\frac{1}{m + 1} & \text{if} \\quad n = 0, \\\\ /// \\frac{2}{m+1} \\left ( \\frac{m}{2(m+1)} \\right ) ^ {\\lfloor \\log_2 n \\rfloor + 1} & /// \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced /// to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_natural_integers; /// /// assert_eq!( /// prefix_to_string(random_natural_integers(EXAMPLE_SEED, 32, 1), 10), /// "[20431208470830262, 2777240, 114, 12184833305054, 1121025855008623490210, \ /// 13478874522577592, 115311695, 7, 18, 54522366353, ...]" /// ) /// ``` pub fn random_natural_integers( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegers> { RandomIntegers { bits: geometric_random_natural_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates random positive [`Integer`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. Then an [`Integer`] /// is chosen uniformly among all positive [`Integer`]s with that bit length. The resulting /// distribution resembles a Pareto distribution. It has no mean or higher-order statistics (unless /// $m < 2$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n \leq 0, \\\\ /// \frac{1}{m} \left ( \frac{m-1}{2m} \right ) ^ {\lfloor \log_2 n \rfloor} & /// \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_positive_integers; /// /// assert_eq!( /// prefix_to_string(random_positive_integers(EXAMPLE_SEED, 32, 1), 10), /// "[22, 4, 178, 55845661150, 93254818, 7577967529619388, 8, 11316951483471, 11, \ /// 1005760138411689342464923704482, ...]" /// ) /// ``` pub fn random_positive_integers( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegers> { RandomIntegers { bits: geometric_random_positive_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates random negative [`Integer`]s whose absolute values have a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. Then an [`Integer`] /// is chosen uniformly among all positive [`Integer`]s with that bit length, and negated. The /// resulting distribution resembles a negated Pareto distribution. It has no mean or higher-order /// statistics (unless $m < 2$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n \geq 0 ,\\\\ /// \frac{1}{m} \left ( \frac{m-1}{2m} \right ) ^ {\lfloor \log_2 (-n) \rfloor} /// & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_negative_integers; /// /// assert_eq!( /// prefix_to_string(random_negative_integers(EXAMPLE_SEED, 32, 1), 10), /// "[-22, -4, -178, -55845661150, -93254818, -7577967529619388, -8, -11316951483471, -11, \ /// -1005760138411689342464923704482, ...]" /// ) /// ``` pub fn random_negative_integers( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegers> { RandomIntegers { bits: geometric_random_negative_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates random nonzero [`Integer`]s whose absolute values have a specified mean bit length. /// /// The actual signed bit length is chosen from a distribution that produces values whose mean /// absolute values are $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator` (see /// [`geometric_random_nonzero_signeds`]); $m$ must be greater than 1. Then an [`Integer`] is chosen /// uniformly among all positive [`Integer`]s with that bit length, and its sign is set to the sign /// of the signed bit length. The resulting distribution has no mean or higher-order statistics /// (unless $m < 2$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \\frac{1}{2m} \\left ( \\frac{m-1}{2m} \\right ) ^ {\\lfloor \\log_2 |n| \\rfloor} /// & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_nonzero_integers; /// /// assert_eq!( /// prefix_to_string(random_nonzero_integers(EXAMPLE_SEED, 32, 1), 10), /// "[6, 373973144, 46887963477285686350042496363292819122, -93254818, -126908, \ /// -4471675267836600, 1860142159, -118004986915853475, -98, 346513, ...]" /// ) /// ``` pub fn random_nonzero_integers( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegers> { RandomIntegers { bits: geometric_random_nonzero_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates random [`Integer`]s whose absolute values have a specified mean bit length. /// /// The actual signed bit length is chosen from a distribution that produces values whose mean /// absolute values are $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator` (see /// [`geometric_random_signeds`]); $m$ must be greater than 0. Then an [`Integer`] is chosen /// uniformly among all [`Integer`]s with that bit length, and its sign is set to the sign of the /// signed bit length. The resulting distribution has no mean or higher-order statistics (unless $m /// < 1$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// \\frac{1}{2m+1} & \text{if} \\quad n = 0, \\\\ /// \\frac{2}{2m+1} \\left ( \\frac{m}{2(m+1)} \\right ) ^ {\\lfloor \\log_2 |n| \\rfloor + 1} /// & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced /// to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_integers; /// /// assert_eq!( /// prefix_to_string(random_integers(EXAMPLE_SEED, 32, 1), 10), /// "[89270, 69403499476962893258904, 62, -1848070042786, -64671510460, -696, 0, -79, 70819, \ /// 7330, ...]" /// ) /// ``` pub fn random_integers( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegers> { RandomIntegers { bits: geometric_random_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates striped random [`Integer`]s, given an iterator of random signed bit lengths. /// /// The [`Integer`]s signs are taken from the signs of the bit lengths. #[derive(Clone, Debug)] pub struct StripedRandomIntegers> { bits: I, bit_source: StripedBitSource, } impl> Iterator for StripedRandomIntegers { type Item = Integer; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); Some(Integer::from_sign_and_abs( bits >= 0, get_striped_random_natural_with_bits(&mut self.bit_source, bits.unsigned_abs()), )) } } /// Generates striped random natural (non-negative) [`Integer`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 0. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Integer`] is generated from the sequence. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if /// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_natural_integers; /// /// assert_eq!( /// prefix_to_string( /// striped_random_natural_integers(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[18014656207519744, 2228160, 64, 17592184995840, 1179440951012584587264, \ /// 9007749010526207, 67108864, 5, 24, 34359738879, ...]" /// ) /// ``` pub fn striped_random_natural_integers( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegers> { StripedRandomIntegers { bits: geometric_random_natural_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random positive [`Integer`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Integer`] is generated from the sequence. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_positive_integers; /// /// assert_eq!( /// prefix_to_string( /// striped_random_positive_integers(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[16, 4, 128, 34391195648, 75493376, 9007199120523391, 8, 8796094070783, 8, \ /// 950737950171027935941967741439, ...]" /// ) /// ``` pub fn striped_random_positive_integers( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegers> { StripedRandomIntegers { bits: geometric_random_positive_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random negative [`Integer`]s whose absolute values have a specified mean bit /// length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Integer`] is generated from the sequence and negated. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_negative_integers; /// /// assert_eq!( /// prefix_to_string( /// striped_random_negative_integers(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[-16, -4, -128, -34391195648, -75493376, -9007199120523391, -8, -8796094070783, -8, \ /// -950737950171027935941967741439, ...]" /// ) /// ``` pub fn striped_random_negative_integers( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegers> { StripedRandomIntegers { bits: geometric_random_negative_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random nonzero [`Integer`]s whose absolute values have a specified mean bit /// length. /// /// The actual signed bit length is chosen from a distribution that produces values whose mean /// absolute values are $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator` (see /// [`geometric_random_nonzero_signeds`]); $m$ must be greater than 1. A striped bit sequence with /// the given stripe parameter is generated and truncated at the bit length. The highest bit is /// forced to be 1, an [`Integer`] is generated from the sequence, and its sign is set to the sign /// of the signed bit length. The resulting distribution has no mean or higher-order statistics /// (unless $m < 2$, which is not typical). /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_nonzero_integers; /// /// assert_eq!( /// prefix_to_string( /// striped_random_nonzero_integers(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[4, 268435456, 84405977732342160290572740160760316144, -133169152, -131064, \ /// -2251834173421823, 1577058304, -126100789566374399, -76, 270335, ...]" /// ) /// ``` pub fn striped_random_nonzero_integers( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegers> { StripedRandomIntegers { bits: geometric_random_nonzero_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random [`Integer`]s whose absolute values have a specified mean bit length. /// /// The actual signed bit length is chosen from a distribution that produces values whose mean /// absolute values are $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator` (see /// [`geometric_random_signeds`]); $m$ must be greater than 0. A striped bit sequence with the given /// stripe parameter is generated and truncated at the bit length. The highest bit is forced to be /// 1, an [`Integer`] is generated from the sequence, and its sign is set to the sign of the signed /// bit length. The resulting distribution has no mean or higher-order statistics (unless $m < 1$, /// which is not typical). /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if /// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_integers; /// /// assert_eq!( /// prefix_to_string(striped_random_integers(EXAMPLE_SEED, 16, 1, 32, 1), 10), /// "[65536, 75521006248971741167616, 32, -2199023255520, -68719468544, -527, 0, -112, \ /// 131071, 4152, ...]" /// ) /// ``` pub fn striped_random_integers( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegers> { StripedRandomIntegers { bits: geometric_random_signeds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Uniformly generates random [`Integer`]s in an interval. #[derive(Clone, Debug)] pub struct UniformRandomIntegerRange { xs: RandomNaturalsLessThan, a: Integer, } impl Iterator for UniformRandomIntegerRange { type Item = Integer; fn next(&mut self) -> Option { self.xs.next().map(|x| &self.a + Integer::from(x)) } } /// Uniformly generates random [`Integer`]s in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a} & \text{if} \\quad a \leq x < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::uniform_random_integer_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// uniform_random_integer_range(EXAMPLE_SEED, Integer::from(-10), Integer::from(100)), /// 10 /// ), /// "[77, 83, -3, 95, 94, 97, 74, 17, 36, 83, ...]" /// ) /// ``` pub fn uniform_random_integer_range( seed: Seed, a: Integer, b: Integer, ) -> UniformRandomIntegerRange { assert!(a < b); UniformRandomIntegerRange { xs: random_naturals_less_than(seed, Natural::exact_from(b - &a)), a, } } /// Uniformly generates random [`Integer`]s in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a+1} & \text{if} \\quad a \leq x \leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::uniform_random_integer_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// uniform_random_integer_inclusive_range( /// EXAMPLE_SEED, /// Integer::from(-10), /// Integer::from(100) /// ), /// 10 /// ), /// "[77, 83, -3, 95, 94, 97, 74, 17, 36, 83, ...]" /// ) /// ``` #[inline] pub fn uniform_random_integer_inclusive_range( seed: Seed, a: Integer, b: Integer, ) -> UniformRandomIntegerRange { assert!(a <= b); uniform_random_integer_range(seed, a, b + Integer::ONE) } /// Generates a random [`Integer`] in the half-open interval $[a, b)$. /// /// The [`Integer`] is chosen uniformly from the interval. /// /// $$ /// P(n) = \\begin{cases} /// 1/(b-a) & \text{if} a\leq n, a: Integer, b: Integer, ) -> Integer { assert!(a < b); Integer::from(get_random_natural_less_than( limbs, &Natural::exact_from(b - &a), )) + a } /// Generates a random [`Integer`] in the closed interval $[a, b]$. /// /// The [`Integer`] is chosen uniformly from the interval. /// /// $$ /// P(n) = \\begin{cases} /// 1/(b-a+1) & \text{if} a\leq n\leq b, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $\ell$ is `limit`. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_bits_numerator + /// mean_bits_denominator`, and $m$ is `max(a.significant_bits(), b.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_uniform_random_integer_from_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_uniform_random_integer_from_inclusive_range( /// &mut random_primitive_ints(EXAMPLE_SEED), /// Integer::from(500u32), /// Integer::from(1001u32) /// ), /// 869 /// ); /// ``` pub fn get_uniform_random_integer_from_inclusive_range( limbs: &mut RandomPrimitiveInts, a: Integer, b: Integer, ) -> Integer { assert!(a <= b); get_uniform_random_integer_from_range(limbs, a, b + Integer::ONE) } fn signed_significant_bits(a: &Integer) -> (u64, i64) { let unsigned_bits = a.significant_bits(); let bits = if *a >= 0 { i64::exact_from(unsigned_bits) } else { -i64::exact_from(unsigned_bits) }; (unsigned_bits, bits) } fn signed_min_bit_range( seed: Seed, a: Integer, unsigned_min_bits: u64, ) -> UniformRandomIntegerRange { if a >= 0 { uniform_random_integer_range(seed, a, Integer::power_of_2(unsigned_min_bits)) } else { uniform_random_integer_inclusive_range(seed, a, -Integer::power_of_2(unsigned_min_bits - 1)) } } fn signed_max_bit_range( seed: Seed, a: Integer, unsigned_max_bits: u64, ) -> UniformRandomIntegerRange { if a > 0 { uniform_random_integer_inclusive_range(seed, Integer::power_of_2(unsigned_max_bits - 1), a) } else { // also handles a == 0 uniform_random_integer_inclusive_range( seed, -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, a, ) } } fn get_random_integer_from_signed_min_bit_range( limbs: &mut RandomPrimitiveInts, a: Integer, unsigned_min_bits: u64, ) -> Integer { if a >= 0 { get_uniform_random_integer_from_range(limbs, a, Integer::power_of_2(unsigned_min_bits)) } else { get_uniform_random_integer_from_inclusive_range( limbs, a, -Integer::power_of_2(unsigned_min_bits - 1), ) } } fn get_random_integer_from_signed_max_bit_range( limbs: &mut RandomPrimitiveInts, a: Integer, unsigned_max_bits: u64, ) -> Integer { if a > 0 { get_uniform_random_integer_from_inclusive_range( limbs, Integer::power_of_2(unsigned_max_bits - 1), a, ) } else { // also handles a == 0 get_uniform_random_integer_from_inclusive_range( limbs, -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, a, ) } } fn get_striped_random_integer_from_signed_min_bit_range( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, unsigned_min_bits: u64, ) -> Integer { if a >= 0 { get_striped_random_integer_from_range( xs, range_generator, a, Integer::power_of_2(unsigned_min_bits), ) } else { get_striped_random_integer_from_inclusive_range( xs, range_generator, a, -Integer::power_of_2(unsigned_min_bits - 1), ) } } fn get_striped_random_integer_from_signed_max_bit_range( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, unsigned_max_bits: u64, ) -> Integer { if a > 0 { get_striped_random_integer_from_inclusive_range( xs, range_generator, Integer::power_of_2(unsigned_max_bits - 1), a, ) } else { // also handles a == 0 get_striped_random_integer_from_inclusive_range( xs, range_generator, -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, a, ) } } /// Generates random [`Integer`]s greater than or equal to a lower bound, or less than or equal to /// an upper bound. #[derive(Clone, Debug)] pub struct RandomIntegerRangeToInfinity { boundary_bits: i64, bits: GeometricRandomSignedRange, limbs: RandomPrimitiveInts, boundary_bit_xs: UniformRandomIntegerRange, } impl Iterator for RandomIntegerRangeToInfinity { type Item = Integer; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.boundary_bits { self.boundary_bit_xs.next() } else { Some(Integer::from_sign_and_abs( bits >= 0, get_random_natural_with_bits(&mut self.limbs, bits.unsigned_abs()), )) } } } /// Generates random [`Integer`]s greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the absolute values of the generated values is specified. $m$ is /// equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_integer_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(-1000), 10, 1), /// 10 /// ), /// "[15542, 2, 1714, 27863518, -162, 956, 8, 14648399, -419, -98, ...]" /// ) /// ``` pub fn random_integer_range_to_infinity( seed: Seed, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegerRangeToInfinity { let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); RandomIntegerRangeToInfinity { boundary_bits: min_bits, bits: geometric_random_signed_inclusive_range( seed.fork("bits"), min_bits, i64::MAX, mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), boundary_bit_xs: signed_min_bit_range(seed.fork("min_bit_xs"), a, unsigned_min_bits), } } /// Generates a random [`Integer`] greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the absolute values of the generated value is specified. $m$ is equal /// to `mean_bits_numerator / mean_bits_denominator`. /// /// # Expected complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_random_integer_from_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_random_integer_from_range_to_infinity( /// &mut random_primitive_ints(EXAMPLE_SEED.fork("limbs")), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 /// ), /// -2 /// ) /// ``` pub fn get_random_integer_from_range_to_infinity( limbs: &mut RandomPrimitiveInts, range_generator: &mut VariableRangeGenerator, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> Integer { let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); let bits = get_geometric_random_signed_from_inclusive_range( range_generator, min_bits, i64::MAX, mean_bits_numerator, mean_bits_denominator, ); if bits == min_bits { get_random_integer_from_signed_min_bit_range(limbs, a, unsigned_min_bits) } else { Integer::from_sign_and_abs( bits >= 0, get_random_natural_with_bits(limbs, bits.unsigned_abs()), ) } } /// Generates random [`Integer`]s less than or equal to an upper bound $a$. /// /// The mean bit length $m$ of the absolute values of the generated values is specified. $m$ is /// equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a < 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_integer_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// random_integer_range_to_negative_infinity(EXAMPLE_SEED, Integer::from(1000), 10, 1), /// 10 /// ), /// "[6, 2, -1714, -235958584061012446, -455842, 514, -12, -14936760, 335, 99, ...]" /// ) /// ``` pub fn random_integer_range_to_negative_infinity( seed: Seed, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegerRangeToInfinity { let (unsigned_max_bits, max_bits) = signed_significant_bits(&a); RandomIntegerRangeToInfinity { boundary_bits: max_bits, bits: geometric_random_signed_inclusive_range( seed.fork("bits"), i64::MIN, max_bits, mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), boundary_bit_xs: signed_max_bit_range(seed.fork("max_bit_xs"), a, unsigned_max_bits), } } /// Generates a random [`Integer`] less than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the absolute values of the generated value is specified. $m$ is equal /// to `mean_bits_numerator / mean_bits_denominator`. /// /// # Expected complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a < 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_random_integer_from_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_random_integer_from_range_to_negative_infinity( /// &mut random_primitive_ints(EXAMPLE_SEED.fork("limbs")), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 /// ), /// -3254 /// ) /// ``` pub fn get_random_integer_from_range_to_negative_infinity( limbs: &mut RandomPrimitiveInts, range_generator: &mut VariableRangeGenerator, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> Integer { let (unsigned_max_bits, max_bits) = signed_significant_bits(&a); let bits = get_geometric_random_signed_from_inclusive_range( range_generator, i64::MIN, max_bits, mean_bits_numerator, mean_bits_denominator, ); if bits == max_bits { get_random_integer_from_signed_max_bit_range(limbs, a, unsigned_max_bits) } else { Integer::from_sign_and_abs( bits >= 0, get_random_natural_with_bits(limbs, bits.unsigned_abs()), ) } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomIntegerRangeMultipleOrders { min_bits: i64, max_bits: i64, bits: GeometricRandomSignedRange, limbs: RandomPrimitiveInts, min_bit_xs: UniformRandomIntegerRange, max_bit_xs: UniformRandomIntegerRange, } impl Iterator for RandomIntegerRangeMultipleOrders { type Item = Integer; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.min_bits { self.min_bit_xs.next() } else if bits == self.max_bits { self.max_bit_xs.next() } else { Some(Integer::from_sign_and_abs( bits >= 0, get_random_natural_with_bits(&mut self.limbs, bits.unsigned_abs()), )) } } } /// Generates random [`Integer`]s in an interval. #[derive(Clone, Debug)] #[allow(clippy::large_enum_variant)] pub enum RandomIntegerRange { SingleOrder(UniformRandomIntegerRange), MultipleOrders(RandomIntegerRangeMultipleOrders), } impl Iterator for RandomIntegerRange { type Item = Integer; fn next(&mut self) -> Option { match self { Self::SingleOrder(xs) => xs.next(), Self::MultipleOrders(xs) => xs.next(), } } } /// Generates random [`Integer`]s in the half-open interval $[a, b)$. /// /// In general, the [`Integer`]s are not generated uniformly; for that, use /// [`uniform_random_integer_range`]. Instead, [`Integer`]s with smaller bit lengths are generated /// more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_bits_numerator / mean_bits_denominator`. It is not actually the mean bit length, though it /// approaches the mean bit length of the values minus $a$ as $\log (b/a)$ approaches infinity. $m$ /// cannot be 0, and must be greater than the bit length of the smallest integer in the range, but /// it may be arbitrarily large. The smaller it is, the more quickly the probabilities decrease as /// bit length increases. The larger it is, the more closely the distribution approaches a uniform /// distribution over the bit lengths. /// /// Once a bit length is selected, the [`Integer`] is chosen uniformly from all [`Integer`]s with /// that bit length that are in $[a, b)$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_bits_numerator + /// mean_bits_denominator`, and $m$ is `max(a.significant_bits(), b.significant_bits())`. /// /// # Panics /// Panics if $a \geq b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their /// ratio is less than or equal to the bit length of the smallest integer in the range, or if they /// are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_integer_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// random_integer_range( /// EXAMPLE_SEED, /// Integer::from(-1000), /// Integer::from(1000000000), /// 20, /// 1 /// ), /// 10 /// ), /// "[1, 1728664, 434, -30, 5282, 515436476, 2353848, -15, 19, 418, ...]" /// ) /// ``` #[inline] pub fn random_integer_range( seed: Seed, a: Integer, b: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegerRange { assert!(a < b); random_integer_inclusive_range( seed, a, b - Integer::ONE, mean_bits_numerator, mean_bits_denominator, ) } /// Generates random [`Integer`]s in the closed interval $[a, b]$. /// /// In general, the [`Integer`]s are not generated uniformly; for that, use /// [`uniform_random_integer_inclusive_range`]. Instead, [`Integer`]s with smaller bit lengths are /// generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_bits_numerator / mean_bits_denominator`. It is not actually the mean bit length, though it /// approaches the mean bit length of the values minus $a$ as $\log (b/a)$ approaches infinity. $m$ /// cannot be 0, and must be greater than the bit length of the smallest integer in the range, but /// it may be arbitrarily large. The smaller it is, the more quickly the probabilities decrease as /// bit length increases. The larger it is, the more closely the distribution approaches a uniform /// distribution over the bit lengths. /// /// Once a bit length is selected, the [`Integer`] is chosen uniformly from all [`Integer`]s with /// that bit length that are in $[a, b]$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_bits_numerator + /// mean_bits_denominator`, and $m$ is `max(a.significant_bits(), b.significant_bits())`. /// /// # Panics /// Panics if $a > b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their ratio /// is less than or equal to the bit length of the smallest integer in the range, or if they are too /// large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::random_integer_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// random_integer_inclusive_range( /// EXAMPLE_SEED, /// Integer::from(-1000), /// Integer::from(999999999), /// 20, /// 1 /// ), /// 10 /// ), /// "[1, 1728664, 434, -30, 5282, 515436476, 2353848, -15, 19, 418, ...]" /// ) /// ``` pub fn random_integer_inclusive_range( seed: Seed, a: Integer, b: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomIntegerRange { assert!(a <= b); let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); let (unsigned_max_bits, max_bits) = signed_significant_bits(&b); if min_bits == max_bits { RandomIntegerRange::SingleOrder(uniform_random_integer_inclusive_range(seed, a, b)) } else { RandomIntegerRange::MultipleOrders(RandomIntegerRangeMultipleOrders { min_bits, max_bits, bits: geometric_random_signed_inclusive_range( seed.fork("bits"), min_bits, max_bits, mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), min_bit_xs: signed_min_bit_range(seed.fork("min_bit_xs"), a, unsigned_min_bits), max_bit_xs: signed_max_bit_range(seed.fork("max_bit_xs"), b, unsigned_max_bits), }) } } /// Generates random striped [`Integer`]s from a range. #[derive(Clone, Debug)] pub enum StripedRandomIntegerInclusiveRange { NonNegative(StripedRandomNaturalInclusiveRange), Negative(StripedRandomNaturalInclusiveRange), Both( RandomBools, Box, Box, ), } impl Iterator for StripedRandomIntegerInclusiveRange { type Item = Integer; fn next(&mut self) -> Option { match self { Self::NonNegative(xs) => xs.next().map(Integer::from), Self::Negative(xs) => xs.next().map(|x| Integer::from_sign_and_abs(false, x)), Self::Both(bs, xs_nn, xs_n) => { if bs.next().unwrap() { xs_nn.next().map(Integer::from) } else { xs_n.next().map(|x| Integer::from_sign_and_abs(false, x)) } } } } } /// Generates random striped [`Integer`]s in the range $[a, b)$. /// /// Because the [`Integer`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean /// run length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::integer::random::striped_random_integer_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// striped_random_integer_range(EXAMPLE_SEED, Integer::from(-4), Integer::from(7), 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[-100, -100, 110, 11, -100, 0, 110, 11, 0, 110, ...]" /// ); /// ``` #[inline] pub fn striped_random_integer_range( seed: Seed, a: Integer, b: Integer, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomIntegerInclusiveRange { assert!(a < b); striped_random_integer_inclusive_range( seed, a, b - Integer::ONE, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Integer`]s in the range $[a, b]$. /// /// Because the [`Integer`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean /// run length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::integer::random::striped_random_integer_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// striped_random_integer_inclusive_range( /// EXAMPLE_SEED, /// Integer::from(-4), /// Integer::from(6), /// 4, /// 1 /// ) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[-100, -100, 110, 11, -100, 0, 110, 11, 0, 110, ...]" /// ); /// ``` pub fn striped_random_integer_inclusive_range( seed: Seed, a: Integer, b: Integer, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomIntegerInclusiveRange { assert!(a <= b); if a >= 0u32 { StripedRandomIntegerInclusiveRange::NonNegative(striped_random_natural_inclusive_range( seed, a.unsigned_abs(), b.unsigned_abs(), mean_stripe_numerator, mean_stripe_denominator, )) } else if b < 0u32 { StripedRandomIntegerInclusiveRange::Negative(striped_random_natural_inclusive_range( seed, b.unsigned_abs(), a.unsigned_abs(), mean_stripe_numerator, mean_stripe_denominator, )) } else { StripedRandomIntegerInclusiveRange::Both( random_bools(seed.fork("sign")), Box::new(striped_random_natural_inclusive_range( seed.fork("non-negative"), Natural::ZERO, b.unsigned_abs(), mean_stripe_numerator, mean_stripe_denominator, )), Box::new(striped_random_natural_inclusive_range( seed.fork("negative"), Natural::ONE, a.unsigned_abs(), mean_stripe_numerator, mean_stripe_denominator, )), ) } } /// Generates a random striped [`Integer`] in the range $[a, b)$. /// /// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_striped_random_integer_from_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_striped_random_integer_from_range( /// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-4), /// Integer::from(7), /// ), /// -4 /// ); /// ``` #[inline] pub fn get_striped_random_integer_from_range( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, b: Integer, ) -> Integer { assert!(a < b); get_striped_random_integer_from_inclusive_range(xs, range_generator, a, b - Integer::ONE) } /// Generates a random striped [`Integer`] in the range $[a, b]$. /// /// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length /// will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean run /// length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(a.significant_bits(), /// b.significant_bits())`. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_striped_random_integer_from_inclusive_range; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_striped_random_integer_from_inclusive_range( /// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-4), /// Integer::from(7), /// ), /// -4 /// ); /// ``` pub fn get_striped_random_integer_from_inclusive_range( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, b: Integer, ) -> Integer { assert!(a <= b); if a >= 0u32 { Integer::from(get_striped_random_natural_from_inclusive_range( xs, a.unsigned_abs(), b.unsigned_abs(), )) } else if b < 0u32 { Integer::from_sign_and_abs( false, get_striped_random_natural_from_inclusive_range(xs, b.unsigned_abs(), a.unsigned_abs()), ) } else if range_generator.next_bool() { Integer::from(get_striped_random_natural_from_inclusive_range( xs, Natural::ZERO, b.unsigned_abs(), )) } else { Integer::from_sign_and_abs( false, get_striped_random_natural_from_inclusive_range(xs, Natural::ONE, a.unsigned_abs()), ) } } fn striped_signed_min_bit_range( seed: Seed, a: Integer, unsigned_min_bits: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomIntegerInclusiveRange { if a >= 0 { striped_random_integer_range( seed.fork("min_bit_xs"), a, Integer::power_of_2(unsigned_min_bits), mean_stripe_numerator, mean_stripe_denominator, ) } else { striped_random_integer_inclusive_range( seed.fork("min_bit_xs"), a, -Integer::power_of_2(unsigned_min_bits - 1), mean_stripe_numerator, mean_stripe_denominator, ) } } fn striped_signed_max_bit_range( seed: Seed, a: Integer, unsigned_max_bits: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomIntegerInclusiveRange { if a > 0 { striped_random_integer_inclusive_range( seed.fork("max_bit_xs"), Integer::power_of_2(unsigned_max_bits - 1), a, mean_stripe_numerator, mean_stripe_denominator, ) } else { // also handles a == 0 striped_random_integer_inclusive_range( seed.fork("max_bit_xs"), -Integer::power_of_2(unsigned_max_bits) + Integer::ONE, a, mean_stripe_numerator, mean_stripe_denominator, ) } } /// Generates striped random [`Integer`]s greater than or equal to a lower bound, or less than or /// equal to an upper bound. #[derive(Clone, Debug)] pub struct StripedRandomIntegerRangeToInfinity { boundary_bits: i64, bits: GeometricRandomSignedRange, bit_source: StripedBitSource, boundary_bit_xs: StripedRandomIntegerInclusiveRange, } impl Iterator for StripedRandomIntegerRangeToInfinity { type Item = Integer; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.boundary_bits { self.boundary_bit_xs.next() } else { Some(Integer::from_sign_and_abs( bits >= 0, get_striped_random_natural_with_bits(&mut self.bit_source, bits.unsigned_abs()), )) } } } /// Generates striped random [`Integer`]s greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the [`Integer`]s is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which /// is not typical). /// /// Because the [`Integer`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher /// mean run length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > /// 0$ and their ratio is less than or equal to the bit length of $a$, or if they are too large and /// manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_integer_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// striped_random_integer_range_to_infinity( /// EXAMPLE_SEED, /// Integer::from(-1000), /// 20, /// 1, /// 10, /// 1 /// ), /// 10 /// ), /// "[8192, 2, 1024, 33554400, -128, 1023, 8, 14745599, -256, -67, ...]" /// ) /// ``` pub fn striped_random_integer_range_to_infinity( seed: Seed, a: Integer, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegerRangeToInfinity { let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); StripedRandomIntegerRangeToInfinity { boundary_bits: min_bits, bits: geometric_random_signed_inclusive_range( seed.fork("bits"), min_bits, i64::MAX, mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), boundary_bit_xs: striped_signed_min_bit_range( seed.fork("min_bit_xs"), a, unsigned_min_bits, mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates a striped random [`Integer`] greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the [`Integer`] is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which /// is not typical). /// /// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length /// will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher mean run /// length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_striped_random_integer_from_range_to_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_striped_random_integer_from_range_to_infinity( /// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 /// ), /// -3 /// ); /// ``` pub fn get_striped_random_integer_from_range_to_infinity( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> Integer { let (unsigned_min_bits, min_bits) = signed_significant_bits(&a); let bits = get_geometric_random_signed_from_inclusive_range( range_generator, min_bits, i64::MAX, mean_bits_numerator, mean_bits_denominator, ); if bits == min_bits { get_striped_random_integer_from_signed_min_bit_range( xs, range_generator, a, unsigned_min_bits, ) } else { Integer::from_sign_and_abs( bits >= 0, get_striped_random_natural_with_bits(xs, bits.unsigned_abs()), ) } } /// Generates a striped random [`Integer`] less than or equal to an upper bound $a$. /// /// The mean bit length $m$ of the [`Integer`] is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which /// is not typical). /// /// Because the [`Integer`] is constrained to be within a certain range, the actual mean run length /// will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher mean run /// length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $b < 0$ and their ratio /// is less than or equal to the bit length of $b$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::num::random::VariableRangeGenerator; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::get_striped_random_integer_from_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// get_striped_random_integer_from_range_to_negative_infinity( /// &mut StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1), /// &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("rg")), /// Integer::from(-1000), /// 20, /// 1 /// ), /// -3975 /// ); /// ``` pub fn get_striped_random_integer_from_range_to_negative_infinity( xs: &mut StripedBitSource, range_generator: &mut VariableRangeGenerator, a: Integer, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> Integer { let (unsigned_max_bits, max_bits) = signed_significant_bits(&a); let bits = get_geometric_random_signed_from_inclusive_range( range_generator, i64::MIN, max_bits, mean_bits_numerator, mean_bits_denominator, ); if bits == max_bits { get_striped_random_integer_from_signed_max_bit_range( xs, range_generator, a, unsigned_max_bits, ) } else { Integer::from_sign_and_abs( bits >= 0, get_striped_random_natural_with_bits(xs, bits.unsigned_abs()), ) } } /// Generates striped random [`Integer`]s less than or equal to an upper bound $a$. /// /// The mean bit length $m$ of the [`Integer`]s is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which /// is not typical). /// /// Because the [`Integer`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $\mu$. Nonetheless, setting a higher $\mu$ will result in a higher /// mean run length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $b < /// 0$ and their ratio is less than or equal to the bit length of $b$, or if they are too large and /// manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::integer::random::striped_random_integer_range_to_negative_infinity; /// use malachite_nz::integer::Integer; /// /// assert_eq!( /// prefix_to_string( /// striped_random_integer_range_to_negative_infinity( /// EXAMPLE_SEED, /// Integer::from(1000), /// 20, /// 1, /// 10, /// 1 /// ), /// 10 /// ), /// "[4, 2, -1024, -144115188075919360, -516096, 992, -15, -16776704, 511, 64, ...]" /// ) /// ``` pub fn striped_random_integer_range_to_negative_infinity( seed: Seed, a: Integer, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomIntegerRangeToInfinity { let (unsigned_max_bits, max_bits) = signed_significant_bits(&a); StripedRandomIntegerRangeToInfinity { boundary_bits: max_bits, bits: geometric_random_signed_inclusive_range( seed.fork("bits"), i64::MIN, max_bits, mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), boundary_bit_xs: striped_signed_max_bit_range( seed.fork("max_bit_xs"), a, unsigned_max_bits, mean_stripe_numerator, mean_stripe_denominator, ), } } ================================================ FILE: malachite-nz/src/lib.rs ================================================ // Copyright © 2026 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 . //! This crate defines [`Natural`](natural::Natural)s (non-negative integers) and //! [`Integer`](integer::Integer)s. Unlike primitive integers ([`u32`], [`i32`], and so on), these //! may be arbitrarily large. The name of this crate refers to the mathematical symbols for natural //! numbers and integers, $\N$ and $\Z$. //! - There are many functions defined on [`Natural`](natural::Natural)s and //! [`Integer`](integer::Integer)s. These include //! - All the ones you'd expect, like addition, subtraction, multiplication, and integer //! division; //! - Implementations of [`DivRound`](malachite_base::num::arithmetic::traits::DivRound), which //! provides division that rounds according to a specified //! [`RoundingMode`](malachite_base::rounding_modes::RoundingMode); //! - Various mathematical functions, like implementations of //! [`FloorSqrt`](malachite_base::num::arithmetic::traits::FloorSqrt) and //! [`Gcd`](malachite_base::num::arithmetic::traits::Gcd); //! - Modular arithmetic functions, like implementations of //! [`ModAdd`](malachite_base::num::arithmetic::traits::ModAdd) and //! [`ModPow`](malachite_base::num::arithmetic::traits::ModPow), and of traits for arithmetic //! modulo a power of 2, like //! [`ModPowerOf2Add`](malachite_base::num::arithmetic::traits::ModPowerOf2Add) and //! [`ModPowerOf2Pow`](malachite_base::num::arithmetic::traits::ModPowerOf2Pow); //! - Various functions for logic and bit manipulation, like [`BitAnd`](core::ops::BitAnd) and //! [`BitAccess`](malachite_base::num::logic::traits::BitAccess). //! - The implementations of these functions use high-performance algorithms that work efficiently //! for large numbers. For example, multiplication uses the naive quadratic algorithm, or one of //! 13 variants of //! [Toom-Cook multiplication](https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication), //! or //! [Schönhage-Strassen (FFT) multiplication](https://en.wikipedia.org/wiki/Schonhage-Strassen_algorithm), //! depending on the input size. //! - Small numbers are also handled efficiently. Any [`Natural`](natural::Natural) smaller than //! $2^{64}$ does not use any allocated memory, and working with such numbers is almost as fast //! as working with primitive integers. As a result, Malachite does not provide implementations //! for _e.g._ adding a [`Natural`](natural::Natural) to a [`u64`], since the [`u64`] can be //! converted to a [`Natural`](natural::Natural) very cheaply. //! - Malachite handles memory intelligently. Consider the problem of adding a 1000-bit //! [`Natural`](natural::Natural) and a 500-bit [`Natural`](natural::Natural). If we only have //! references to the [`Natural`](natural::Natural)s, then we must allocate new memory for the //! result, and this is what the `&Natural + &Natural` implementation does. However, if we can //! take the first (larger) [`Natural`](natural::Natural) by value, then we do not need to //! allocate any memory (except in the unlikely case of a carry): we can reuse the memory of the //! first [`Natural`](natural::Natural) to store the result, and this is what the //! `Natural + &Natural` implementation does. On the other hand, if we can only take the second //! (smaller) [`Natural`](natural::Natural) by value, then we only have 500 bits of memory //! available, which is not enough to store the sum. In this case, the [`Vec`] containing the //! smaller [`Natural`](natural::Natural)'s data can be extended to hold 1000 bits, in hopes that //! this will be more efficient than allocating 1000 bits in a completely new [`Vec`]. Finally, //! if both [`Natural`](natural::Natural)s are taken by value, then the `Natural + Natural` //! implementation chooses to reuse the memory of the larger one. //! //! Now consider what happens when evaluating the expression `&x + &y + &z`, where each //! [`Natural`](natural::Natural) has $n$ bits. Malachite must allocate about $n$ bits for the //! result, but what about the intermediate sum `&x + &y`? Does Malachite need to allocate //! another $n$ bits for that, for a total of $2n$ bits? No! Malachite first allocates $n$ bits //! for `&x + &y`, but then that partial sum is taken by _value_ using the `Natural + &Natural` //! implementation described above; so those $n$ bits are reused for the final sum. //! //! # Limbs //! Large [`Natural`](natural::Natural)s and [`Integer`](integer::Integer)s store their data as //! [`Vec`]s of some primitive type. The elements of these //! [`Vec`]s are called "limbs" in GMP terminology, since they're large digits. //! By default, the type of a `Limb` is [`u64`], but you can set it to [`u32`] using the //! `32_bit_limbs` feature. //! //! # Demos and benchmarks //! This crate comes with a `bin` target that can be used for running demos and benchmarks. //! - Almost all of the public functions in this crate have an associated demo. Running a demo //! shows you a function's behavior on a large number of inputs. For example, to demo the //! [`mod_pow`](malachite_base::num::arithmetic::traits::ModPow::mod_pow) function on //! [`Natural`](natural::Natural)s, you can use the following command: //! ```text //! cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_natural_mod_pow //! ``` //! This command uses the `exhaustive` mode, which generates every possible input, generally //! starting with the simplest input and progressing to more complex ones. Another mode is //! `random`. The `-l` flag specifies how many inputs should be generated. //! - You can use a similar command to run benchmarks. The following command benchmarks various //! GCD algorithms for [`u64`]s: //! ```text //! cargo run --features bin_build --release -- -l 1000000 -m random -b \ //! benchmark_natural_gcd_algorithms -o gcd-bench.gp //! ``` //! or GCD implementations of other libraries: //! ```text //! cargo run --features bin_build --release -- -l 1000000 -m random -b \ //! benchmark_natural_gcd_library_comparison -o gcd-bench.gp //! ``` //! This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like //! so: //! ```text //! gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg //! ``` //! //! The list of available demos and benchmarks is not documented anywhere; you must find them by //! browsing through //! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-nz/src/bin_util/demo_and_bench). //! //! # Features //! - `32_bit_limbs`: Sets the type of [`Limb`](crate#limbs) to [`u32`] instead of the default, //! [`u64`]. //! - `test_build`: A large proportion of the code in this crate is only used for testing. For a //! typical user, building this code would result in an unnecessarily long compilation time and //! an unnecessarily large binary. Some of it is also used for testing `malachite-q`, so it can't //! just be confined to the `tests` directory. My solution is to only build this code when the //! `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`. //! However, doctests don't require it, since they only test the public interface. //! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also //! takes a long time to build. Enabling this feature also enables `test_build`. #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #![cfg_attr( not(any(feature = "test_build", feature = "random", feature = "std")), no_std )] #[macro_use] extern crate alloc; extern crate itertools; #[macro_use] extern crate malachite_base; #[cfg(feature = "serde")] #[macro_use] extern crate serde; #[cfg(feature = "test_build")] extern crate num; #[cfg(feature = "test_build")] extern crate rug; #[doc(hidden)] #[cfg(not(feature = "32_bit_limbs"))] pub use crate::platform_64 as platform; #[doc(hidden)] #[cfg(feature = "32_bit_limbs")] pub use platform_32 as platform; #[doc(hidden)] #[cfg(feature = "32_bit_limbs")] pub mod platform_32; #[doc(hidden)] #[cfg(not(feature = "32_bit_limbs"))] pub mod platform_64; #[cfg(feature = "doc-images")] extern crate embed_doc_image; /// [`Natural`](natural::Natural), a type representing arbitrarily large non-negative integers. #[macro_use] pub mod natural; /// [`Integer`](integer::Integer), a type representing integers with arbitrarily large absolute /// values. pub mod integer; #[cfg(feature = "test_build")] pub mod test_util; ================================================ FILE: malachite-nz/src/natural/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018, 2020 Free Software Foundation, Inc. // // 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{AbsDiff, AbsDiffAssign}; impl AbsDiff for Natural { type Output = Self; /// Computes the absolute value of the difference between two [`Natural`]s, taking both by /// value. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).abs_diff(Natural::ZERO), 123); /// assert_eq!(Natural::ZERO.abs_diff(Natural::from(123u32)), 123); /// assert_eq!(Natural::from(456u32).abs_diff(Natural::from(123u32)), 333); /// assert_eq!(Natural::from(123u32).abs_diff(Natural::from(456u32)), 333); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .abs_diff(Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .abs_diff(Natural::from(10u32).pow(12) * Natural::from(3u32)), /// 2000000000000u64 /// ); /// ``` fn abs_diff(self, other: Self) -> Self { if self >= other { self - other } else { other - self } } } impl<'a> AbsDiff<&'a Self> for Natural { type Output = Self; /// Computes the absolute value of the difference between two [`Natural`]s, taking the first by /// value and the second by reference. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).abs_diff(&Natural::ZERO), 123); /// assert_eq!(Natural::ZERO.abs_diff(&Natural::from(123u32)), 123); /// assert_eq!(Natural::from(456u32).abs_diff(&Natural::from(123u32)), 333); /// assert_eq!(Natural::from(123u32).abs_diff(&Natural::from(456u32)), 333); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .abs_diff(&Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .abs_diff(&(Natural::from(10u32).pow(12) * Natural::from(3u32))), /// 2000000000000u64 /// ); /// ``` fn abs_diff(self, other: &'a Self) -> Self { if self >= *other { self - other } else { other - self } } } impl AbsDiff for &Natural { type Output = Natural; /// Computes the absolute value of the difference between two [`Natural`]s, taking the first by /// reference and the second by value. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(123u32)).abs_diff(Natural::ZERO), 123); /// assert_eq!((&Natural::ZERO).abs_diff(Natural::from(123u32)), 123); /// assert_eq!( /// (&Natural::from(456u32)).abs_diff(Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (&Natural::from(123u32)).abs_diff(Natural::from(456u32)), /// 333 /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .abs_diff(Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .abs_diff(Natural::from(10u32).pow(12) * Natural::from(3u32)), /// 2000000000000u64 /// ); /// ``` fn abs_diff(self, other: Natural) -> Natural { if *self >= other { self - other } else { other - self } } } impl AbsDiff<&Natural> for &Natural { type Output = Natural; /// Computes the absolute value of the difference between two [`Natural`]s, taking both by /// reference. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiff, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(123u32)).abs_diff(&Natural::ZERO), 123); /// assert_eq!((&Natural::ZERO).abs_diff(&Natural::from(123u32)), 123); /// assert_eq!( /// (&Natural::from(456u32)).abs_diff(&Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (&Natural::from(123u32)).abs_diff(&Natural::from(456u32)), /// 333 /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .abs_diff(&Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .abs_diff(&(Natural::from(10u32).pow(12) * Natural::from(3u32))), /// 2000000000000u64 /// ); /// ``` fn abs_diff(self, other: &Natural) -> Natural { if self >= other { self - other } else { other - self } } } impl AbsDiffAssign for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place and takes the absolute value, taking /// the [`Natural`] on the right-hand side by value. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiffAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(123u32); /// x.abs_diff_assign(Natural::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Natural::ZERO; /// x.abs_diff_assign(Natural::from(123u32)); /// assert_eq!(x, 123); /// /// let mut x = Natural::from(456u32); /// x.abs_diff_assign(Natural::from(123u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(123u32); /// x.abs_diff_assign(Natural::from(456u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(10u32).pow(12) * Natural::from(3u32); /// x.abs_diff_assign(Natural::from(10u32).pow(12)); /// assert_eq!(x, 2000000000000u64); /// /// let mut x = Natural::from(10u32).pow(12); /// x.abs_diff_assign(Natural::from(10u32).pow(12) * Natural::from(3u32)); /// assert_eq!(x, 2000000000000u64); /// ``` fn abs_diff_assign(&mut self, other: Self) { if *self >= other { *self -= other; } else { self.sub_right_assign_no_panic(&other); } } } impl<'a> AbsDiffAssign<&'a Self> for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place and takes the absolute value, taking /// the [`Natural`] on the right-hand side by reference. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AbsDiffAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(123u32); /// x.abs_diff_assign(&Natural::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Natural::ZERO; /// x.abs_diff_assign(&Natural::from(123u32)); /// assert_eq!(x, 123); /// /// let mut x = Natural::from(456u32); /// x.abs_diff_assign(&Natural::from(123u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(123u32); /// x.abs_diff_assign(&Natural::from(456u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(10u32).pow(12) * Natural::from(3u32); /// x.abs_diff_assign(&Natural::from(10u32).pow(12)); /// assert_eq!(x, 2000000000000u64); /// /// let mut x = Natural::from(10u32).pow(12); /// x.abs_diff_assign(&Natural::from(10u32).pow(12) * Natural::from(3u32)); /// assert_eq!(x, 2000000000000u64); /// ``` fn abs_diff_assign(&mut self, other: &'a Self) { if *self >= *other { *self -= other; } else { self.sub_right_assign_no_panic(other); } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Some optimizations contributed by florian1345. // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018, 2020 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::shl::{limbs_shl, limbs_vec_shl_in_place}; use crate::platform::Limb; use alloc::vec::Vec; use core::iter::Sum; use core::ops::{Add, AddAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the sum of the `Natural` and a `Limb`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_add_1` from `gmp.h`, GMP 6.2.1, where the result is returned. pub_crate_test! {limbs_add_limb(xs: &[Limb], mut y: Limb) -> Vec { let len = xs.len(); let mut out = Vec::with_capacity(len); for i in 0..len { let (sum, overflow) = xs[i].overflowing_add(y); out.push(sum); if overflow { y = 1; } else { y = 0; out.extend_from_slice(&xs[i + 1..]); break; } } if y != 0 { out.push(y); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the sum of the `Natural` and a `Limb` to an output slice. The output slice must be at // least as long as the input slice. Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`. // // This is equivalent to `mpn_add_1` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_add_limb_to_out(out: &mut [Limb], xs: &[Limb], mut y: Limb) -> bool { let len = xs.len(); assert!(out.len() >= len); for i in 0..len { let overflow; (out[i], overflow) = xs[i].overflowing_add(y); if overflow { y = 1; } else { y = 0; let copy_index = i + 1; out[copy_index..len].copy_from_slice(&xs[copy_index..]); break; } } y != 0 }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the sum of the `Natural` and a `Limb` to the input slice. Returns whether there is a // carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_add_1` from `gmp.h`, GMP 6.2.1, where the result is written to the // input slice. pub_crate_test! {limbs_slice_add_limb_in_place( xs: &mut [T], mut y: T ) -> bool { for x in &mut *xs { if x.overflowing_add_assign(y) { y = T::ONE; } else { return false; } } y != T::ZERO }} // Interpreting a nonempty `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes // the limbs of the sum of the `Natural` and a `Limb` to the input `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ (only if the `Vec` reallocates) // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. // // This is equivalent to `mpz_add_ui` from `mpz/aors_ui.h`, GMP 6.2.1, where the input is // non-negative. pub_crate_test! {limbs_vec_add_limb_in_place(xs: &mut Vec, y: Limb) { assert!(!xs.is_empty()); if limbs_slice_add_limb_in_place(xs, y) { xs.push(1); } }} #[inline] pub(crate) fn add_with_carry_limb(x: T, y: T, carry: T) -> (T, T) { let result_no_carry = x.wrapping_add(y); let result = result_no_carry.wrapping_add(carry); let carry = T::from((result_no_carry < x) || (result < result_no_carry)); (result, carry) } // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the // first slice is at least as long as the second, returns a `Vec` of the limbs of the sum of the // `Natural`s. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the first input is at least as // long as the second, and the output is returned. pub_crate_test! {limbs_add_greater(xs: &[Limb], ys: &[Limb]) -> Vec { if core::ptr::eq(xs, ys) { return limbs_shl(xs, 1); } let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let mut out = Vec::with_capacity(xs_len); let mut carry = 0; for (&x, &y) in xs.iter().zip(ys.iter()) { let o; (o, carry) = add_with_carry_limb(x, y, carry); out.push(o); } if xs_len == ys_len { if carry != 0 { out.push(1); } } else { out.extend_from_slice(&xs[ys_len..]); if carry != 0 && limbs_slice_add_limb_in_place(&mut out[ys_len..], 1) { out.push(1); } } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the sum of the `Natural`s. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the output is returned. pub_crate_test! {limbs_add(xs: &[Limb], ys: &[Limb]) -> Vec { if xs.len() >= ys.len() { limbs_add_greater(xs, ys) } else { limbs_add_greater(ys, xs) } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the `xs.len()` least-significant limbs of the sum of the `Natural`s to an // output slice. The output must be at least as long as one of the input slices. Returns whether // there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `out` is too short. // // This is equivalent to `mpn_add_n` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_add_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); let mut carry = 0; for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { (*out, carry) = add_with_carry_limb(x, y, carry); } carry != 0 }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the // first slice is at least as long as the second, writes the `xs.len()` least-significant limbs of // the sum of the `Natural`s to an output slice. The output must be at least as long as `xs`. // Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys` or if `out` is too short. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the first input is at least as // long as the second. pub_crate_test! {limbs_add_greater_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); assert!(out.len() >= xs_len); let carry = limbs_add_same_length_to_out(out, &xs[..ys_len], ys); if xs_len == ys_len { carry } else if carry { limbs_add_limb_to_out(&mut out[ys_len..], &xs[ys_len..], 1) } else { out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); false } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `max(xs.len(), ys.len())` least-significant limbs of the sum of the `Natural`s to an output // slice. The output must be at least as long as the longer input slice. Returns whether there is a // carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_add_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { if xs.len() >= ys.len() { limbs_add_greater_to_out(out, xs, ys) } else { limbs_add_greater_to_out(out, ys, xs) } }} // Given two slices of `Limb`s as the limbs `xs` and `ys`, where `xs` is at least as long as `ys` // and `xs_len` is no greater than `ys.len()`, writes the `ys.len()` lowest limbs of the sum of // `xs[..xs_len]` and `ys` to `xs`. Returns whether there is a carry. // // For example, `limbs_add_to_out_aliased(&mut xs[..12], 7, &ys[..10])` would be equivalent to // `limbs_add_to_out(&mut xs[..12], &xs[..7], &ys[..10])` although the latter expression is not // allowed because `xs` cannot be borrowed in that way. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `xs` is shorter than `ys` or `xs_len` is greater than `ys.len()`. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the second argument is at least as // long as the first and the output pointer is the same as the first input pointer. pub_crate_test! {limbs_add_to_out_aliased(xs: &mut [Limb], xs_len: usize, ys: &[Limb]) -> bool { let ys_len = ys.len(); assert!(xs.len() >= ys_len); assert!(xs_len <= ys_len); let (ys_lo, ys_hi) = ys.split_at(xs_len); xs[xs_len..ys_len].copy_from_slice(ys_hi); limbs_slice_add_greater_in_place_left(&mut xs[..ys_len], ys_lo) }} // For example, `limbs_add_to_out_aliased_2(&mut xs[..15], 5, &ys[..10])` would be equivalent to // `limbs_add_to_out(&mut xs[..10], &xs[5..15], &ys[..10])` although the latter expression is not // allowed because `xs` cannot be borrowed in that way. pub_crate_test! { limbs_add_to_out_aliased_2(xs: &mut [Limb], xs_offset: usize, ys: &[Limb]) -> bool { let len = ys.len(); assert_eq!(xs.len(), len + xs_offset); let mut carry = 0; for i in 0..len { (xs[i], carry) = add_with_carry_limb(xs[i + xs_offset], ys[i], carry); } carry != 0 }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the `xs.len()` least-significant limbs of the sum of the `Natural`s to the // first (left) slice. Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_add_n` from `gmp.h`, GMP 6.2.1, where the output is written to the // first input. pub_crate_test! {limbs_slice_add_same_length_in_place_left( xs: &mut [T], ys: &[T], ) -> bool { let xs_len = xs.len(); assert_eq!(xs_len, ys.len()); let mut carry = T::ZERO; for (x, &y) in xs.iter_mut().zip(ys.iter()) { (*x, carry) = add_with_carry_limb(*x, y, carry); } carry != T::ZERO }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the // length of the first slice is greater than or equal to the length of the second, writes the // `xs.len()` least-significant limbs of the sum of the `Natural`s to the first (left) slice. // Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the first input is at least as // long as the second, and the output is written to the first input. pub_crate_test! {limbs_slice_add_greater_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let (xs_lo, xs_hi) = xs.split_at_mut(ys_len); let carry = limbs_slice_add_same_length_in_place_left(xs_lo, ys); if xs_len == ys_len { carry } else if carry { limbs_slice_add_limb_in_place(xs_hi, 1) } else { false } }} // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the sum of the `Natural`s to the first (left) slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. // // This is equivalent to `mpz_add` from `mpz/aors.h`, GMP 6.2.1, where both inputs are non-negative // and the output is written to the first input. pub_crate_test! {limbs_vec_add_in_place_left(xs: &mut Vec, ys: &[Limb]) { if core::ptr::eq(xs.as_slice(), ys) { limbs_vec_shl_in_place(xs, 1); return; } let xs_len = xs.len(); let ys_len = ys.len(); let carry = if xs_len >= ys_len { limbs_slice_add_greater_in_place_left(xs, ys) } else { let (ys_lo, ys_hi) = ys.split_at(xs_len); let mut carry = limbs_slice_add_same_length_in_place_left(xs, ys_lo); xs.extend_from_slice(ys_hi); if carry { carry = limbs_slice_add_limb_in_place(&mut xs[xs_len..], 1); } carry }; if carry { xs.push(1); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `max(xs.len(), ys.len())` least-significant limbs of the sum of the `Natural`s to the longer // slice (or the first one, if they are equally long). Returns a pair of `bool`s. The first is // `false` when the output is to the first slice and `true` when it's to the second slice, and the // second is whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpn_add` from `gmp.h`, GMP 6.2.1, where the output is written to the // longer input. pub_test! {limbs_slice_add_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> (bool, bool) { if xs.len() >= ys.len() { (false, limbs_slice_add_greater_in_place_left(xs, ys)) } else { (true, limbs_slice_add_greater_in_place_left(ys, xs)) } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the sum of the `Natural`s to the longer slice (or the first one, if they are equally // long). Returns a `bool` which is `false` when the output is to the first `Vec` and `true` when // it's to the second `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ (only if the `Vec` reallocates) // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_add` from `mpz/aors.h`, GMP 6.2.1, where both inputs are non-negative // and the output is written to the longer input. pub_test! {limbs_vec_add_in_place_either(xs: &mut Vec, ys: &mut Vec) -> bool { if xs.len() >= ys.len() { if limbs_slice_add_greater_in_place_left(xs, ys) { xs.push(1); } false } else { if limbs_slice_add_greater_in_place_left(ys, xs) { ys.push(1); } true } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the `xs.len()` least-significant limbs of the sum of the `Natural`s and a // carry (`false` is 0, `true` is 1) to an output slice. The output must be at least as long as one // of the input slices. Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `out` is too short. // // This is equivalent to `mpn_add_nc` from `gmp-impl.h`, GMP 6.2.1, where `rp` and `up` are // disjoint. pub_crate_test! {limbs_add_same_length_with_carry_in_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], carry_in: bool, ) -> bool { let mut carry = limbs_add_same_length_to_out(out, xs, ys); if carry_in { carry |= limbs_slice_add_limb_in_place(&mut out[..xs.len()], 1); } carry }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the `xs.len()` least-significant limbs of the sum of the `Natural`s and a // carry (`false` is 0, `true` is 1) to the first (left) slice. Returns whether there is a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_add_nc` from `gmp-impl.h`, GMP 6.2.1, where `rp` is the same as `up`. pub_crate_test! {limbs_add_same_length_with_carry_in_in_place_left( xs: &mut [Limb], ys: &[Limb], carry_in: bool, ) -> bool { let mut carry = limbs_slice_add_same_length_in_place_left(xs, ys); if carry_in { carry |= limbs_slice_add_limb_in_place(xs, 1); } carry }} impl Natural { #[inline] pub(crate) fn add_limb(mut self, other: Limb) -> Self { self.add_assign_limb(other); self } pub(crate) fn add_limb_ref(&self, other: Limb) -> Self { match (self, other) { (x, 0) => x.clone(), (Self(Small(small)), other) => match small.overflowing_add(other) { (sum, false) => Self::from(sum), (sum, true) => Self(Large(vec![sum, 1])), }, (Self(Large(limbs)), other) => Self(Large(limbs_add_limb(limbs, other))), } } fn add_assign_limb(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => {} (&mut Self::ZERO, _) => *self = Self::from(other), (&mut Self(Small(ref mut small)), other) => { let (sum, overflow) = small.overflowing_add(other); if overflow { *self = Self(Large(vec![sum, 1])); } else { *small = sum; } } (&mut Self(Large(ref mut limbs)), other) => { limbs_vec_add_limb_in_place(limbs, other); } } } #[cfg(feature = "float_helpers")] pub fn add_assign_at_limb(&mut self, i: usize, y: Limb) { if i == 0 { *self += Self::from(y); return; } let xs = self.promote_in_place(); if xs.len() <= i { xs.resize(i + 1, 0); } if limbs_slice_add_limb_in_place(&mut xs[i..], y) { xs.push(1); } } } impl Add for Natural { type Output = Self; /// Adds two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO + Natural::from(123u32), 123); /// assert_eq!(Natural::from(123u32) + Natural::ZERO, 123); /// assert_eq!(Natural::from(123u32) + Natural::from(456u32), 579); /// assert_eq!( /// Natural::from(10u32).pow(12) + (Natural::from(10u32).pow(12) << 1), /// 3000000000000u64 /// ); /// ``` fn add(mut self, other: Self) -> Self { self += other; self } } impl<'a> Add<&'a Self> for Natural { type Output = Self; /// Adds two [`Natural`]s, taking the first by reference and the second by value. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO + &Natural::from(123u32), 123); /// assert_eq!(Natural::from(123u32) + &Natural::ZERO, 123); /// assert_eq!(Natural::from(123u32) + &Natural::from(456u32), 579); /// assert_eq!( /// Natural::from(10u32).pow(12) + &(Natural::from(10u32).pow(12) << 1), /// 3000000000000u64 /// ); /// ``` #[inline] fn add(mut self, other: &'a Self) -> Self { self += other; self } } impl Add for &Natural { type Output = Natural; /// Adds two [`Natural`]s, taking the first by value and the second by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::ZERO + Natural::from(123u32), 123); /// assert_eq!(&Natural::from(123u32) + Natural::ZERO, 123); /// assert_eq!(&Natural::from(123u32) + Natural::from(456u32), 579); /// assert_eq!( /// &Natural::from(10u32).pow(12) + (Natural::from(10u32).pow(12) << 1), /// 3000000000000u64 /// ); /// ``` #[inline] fn add(self, mut other: Natural) -> Natural { other += self; other } } impl Add<&Natural> for &Natural { type Output = Natural; /// Adds two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::ZERO + &Natural::from(123u32), 123); /// assert_eq!(&Natural::from(123u32) + &Natural::ZERO, 123); /// assert_eq!(&Natural::from(123u32) + &Natural::from(456u32), 579); /// assert_eq!( /// &Natural::from(10u32).pow(12) + &(Natural::from(10u32).pow(12) << 1), /// 3000000000000u64 /// ); /// ``` fn add(self, other: &Natural) -> Natural { match (self, other) { (x, &Natural(Small(y))) => x.add_limb_ref(y), (&Natural(Small(x)), y) => y.add_limb_ref(x), (&Natural(Large(ref xs)), &Natural(Large(ref ys))) => Natural(Large(limbs_add(xs, ys))), } } } impl AddAssign for Natural { /// Adds a [`Natural`] to a [`Natural`] in place, taking the [`Natural`] on the right-hand side /// by value. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x += Natural::from(10u32).pow(12); /// x += Natural::from(10u32).pow(12) * Natural::from(2u32); /// x += Natural::from(10u32).pow(12) * Natural::from(3u32); /// x += Natural::from(10u32).pow(12) * Natural::from(4u32); /// assert_eq!(x, 10000000000000u64); /// ``` fn add_assign(&mut self, mut other: Self) { match (&mut *self, &mut other) { (x, &mut Self(Small(y))) => x.add_assign_limb(y), (&mut Self(Small(x)), y) => *self = y.add_limb_ref(x), (&mut Self(Large(ref mut xs)), &mut Self(Large(ref mut ys))) => { if limbs_vec_add_in_place_either(xs, ys) { *self = other; } } } } } impl<'a> AddAssign<&'a Self> for Natural { /// Adds a [`Natural`] to a [`Natural`] in place, taking the [`Natural`] on the right-hand side /// by reference. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x += &Natural::from(10u32).pow(12); /// x += &(Natural::from(10u32).pow(12) * Natural::from(2u32)); /// x += &(Natural::from(10u32).pow(12) * Natural::from(3u32)); /// x += &(Natural::from(10u32).pow(12) * Natural::from(4u32)); /// assert_eq!(x, 10000000000000u64); /// ``` fn add_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (x, &Self(Small(y))) => x.add_assign_limb(y), (&mut Self(Small(x)), y) => *self = y.add_limb_ref(x), (&mut Self(Large(ref mut xs)), &Self(Large(ref ys))) => { limbs_vec_add_in_place_left(xs, ys); } } } } impl Sum for Natural { /// Adds up all the [`Natural`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Natural::sum(xs.map(Natural::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Sum; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::sum(vec_from_str::("[2, 3, 5, 7]").unwrap().into_iter()), /// 17 /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut s = Self::ZERO; for x in xs { s += x; } s } } impl<'a> Sum<&'a Self> for Natural { /// Adds up all the [`Natural`]s in an iterator of [`Natural`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Natural::sum(xs.map(Natural::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Sum; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::sum(vec_from_str::("[2, 3, 5, 7]").unwrap().iter()), /// 17 /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut s = Self::ZERO; for x in xs { s += x; } s } } ================================================ FILE: malachite-nz/src/natural/arithmetic/add_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Some optimizations contributed by florian1345. // // Uses code adopted from the GNU MP Library. // // Copyright © 1992-1994, 1996, 2000, 2001, 2002, 2004, 2005, 2012, 2016 Free Software // Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_greater, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, }; use crate::natural::arithmetic::mul::limb::{limbs_mul_limb_to_out, limbs_slice_mul_limb_in_place}; use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use core::mem::swap; use malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign, XMulYToZZ}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{SplitInHalf, WrappingFrom}; // Given the limbs of two `Natural`s x and y, and a limb `z`, returns the limbs of x + y * z. `xs` // and `ys` should be nonempty and have no trailing zeros, and `z` should be nonzero. The result // will have no trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is positive, and `w` is returned instead of overwriting the first input. pub_test! {limbs_add_mul_limb(xs: &[Limb], ys: &[Limb], limb: Limb) -> Vec { let mut out; if xs.len() >= ys.len() { out = xs.to_vec(); limbs_vec_add_mul_limb_greater_in_place_left(&mut out, ys, limb); } else { out = ys.to_vec(); limbs_vec_add_mul_limb_smaller_in_place_right(xs, &mut out, limb); } out }} // Given the equal-length limbs of two `Natural`s x and y, and a limb `z`, computes x + y * z. The // lowest `xs.len()` limbs of the result are written to `xs`, and the highest limb of y * z, plus // the carry-out from the addition, is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_addmul_1` from `mpn/generic/addmul_1.c`, GMP 6.2.1. pub_crate_test! {limbs_slice_add_mul_limb_same_length_in_place_left( xs: &mut [Limb], ys: &[Limb], z: Limb, ) -> Limb { let len = xs.len(); assert_eq!(ys.len(), len); let mut carry = 0; for (x, &y) in xs.iter_mut().zip(ys.iter()) { let (product_hi, mut product_lo) = XMulYToZZ::x_mul_y_to_zz(y, z); product_lo = (*x).wrapping_add(product_lo); let mut add_carry = Limb::from(*x > product_lo); *x = product_lo.wrapping_add(carry); add_carry += Limb::from(product_lo > *x); carry = product_hi.wrapping_add(add_carry); } carry }} pub(crate) fn limbs_slice_add_mul_two_limbs_matching_length_in_place_left( xs: &mut [Limb], ys: &[Limb], zs: [Limb; 2], ) -> Limb { let len = ys.len(); assert_eq!(xs.len(), len + 1); let mut carry_hi: Limb = 0; let mut carry_lo: Limb = 0; for (x, &y) in xs.iter_mut().zip(ys.iter()) { let (mut product_hi, mut product_lo) = XMulYToZZ::x_mul_y_to_zz(y, zs[0]); product_lo = (*x).wrapping_add(product_lo); let mut add_carry = Limb::from(*x > product_lo); *x = product_lo.wrapping_add(carry_lo); add_carry += Limb::from(product_lo > *x); carry_lo = product_hi.wrapping_add(add_carry); carry_lo = carry_hi.wrapping_add(carry_lo); add_carry = Limb::from(carry_hi > carry_lo); (product_hi, product_lo) = XMulYToZZ::x_mul_y_to_zz(y, zs[1]); carry_lo = product_lo.wrapping_add(carry_lo); add_carry += Limb::from(product_lo > carry_lo); carry_hi = product_hi.wrapping_add(add_carry); } xs[len] = carry_lo; carry_hi } // Given the limbs of two `Natural`s x and y, and a limb `z`, computes x + y * z. The lowest limbs // of the result are written to `ys` and the highest limb is returned. `xs` must have the same // length as `ys`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive and have the same lengths, `sub` is positive, the lowest limbs of the result are written // to the second input rather than the first, and the highest limb is returned. pub_test! {limbs_slice_add_mul_limb_same_length_in_place_right( xs: &[Limb], ys: &mut [Limb], z: Limb, ) -> Limb { let xs_len = xs.len(); assert_eq!(ys.len(), xs_len); let mut carry = 0; let dz = DoubleLimb::from(z); for (&x, y) in xs.iter().zip(ys.iter_mut()) { let out = DoubleLimb::from(x) + DoubleLimb::from(*y) * dz + carry; *y = out.lower_half(); carry = out >> Limb::WIDTH; } Limb::wrapping_from(carry) }} // Given the limbs of two `Natural`s a and b, and a limb c, writes the limbs of a + b * c to the // first (left) input, corresponding to the limbs of a. `xs` and `ys` should be nonempty and have no // trailing zeros, and `z` should be nonzero. The result will have no trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())` and $m$ is `max(1, // ys.len() - xs.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive and sub is positive. pub_test! {limbs_vec_add_mul_limb_in_place_left(xs: &mut Vec, ys: &[Limb], z: Limb) { let xs_len = xs.len(); if xs_len >= ys.len() { limbs_vec_add_mul_limb_greater_in_place_left(xs, ys, z); } else { xs.resize(ys.len(), 0); let (xs_lo, xs_hi) = xs.split_at_mut(xs_len); let (ys_lo, ys_hi) = ys.split_at(xs_len); let mut carry = limbs_mul_limb_to_out::(xs_hi, ys_hi, z); let inner_carry = limbs_slice_add_mul_limb_same_length_in_place_left(xs_lo, ys_lo, z); if inner_carry != 0 && limbs_slice_add_limb_in_place(xs_hi, inner_carry) { carry += 1; } if carry != 0 { xs.push(carry); } } }} // ys.len() > 0, xs.len() >= ys.len(), z != 0 fn limbs_vec_add_mul_limb_greater_in_place_left(xs: &mut Vec, ys: &[Limb], z: Limb) { let ys_len = ys.len(); let carry = limbs_slice_add_mul_limb_same_length_in_place_left(&mut xs[..ys_len], ys, z); if carry != 0 { if xs.len() == ys_len { xs.push(carry); } else if limbs_slice_add_limb_in_place(&mut xs[ys_len..], carry) { xs.push(1); } } } // Given the limbs of two `Natural`s x and y, and a limb `z`, writes the limbs of x + y * z to the // second (right) input, corresponding to the limbs of y. `xs` and `ys` should be nonempty and have // no trailing zeros, and `z` should be nonzero. The result will have no trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())` and $m$ is `max(1, // ys.len() - xs.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is positive, and the result is written to the second input rather than the first. pub_test! {limbs_vec_add_mul_limb_in_place_right(xs: &[Limb], ys: &mut Vec, z: Limb) { let ys_len = ys.len(); if xs.len() >= ys_len { let carry = limbs_slice_add_mul_limb_same_length_in_place_right(&xs[..ys_len], ys, z); ys.extend_from_slice(&xs[ys_len..]); if carry != 0 { if xs.len() == ys_len { ys.push(carry); } else if limbs_slice_add_limb_in_place(&mut ys[ys_len..], carry) { ys.push(1); } } } else { limbs_vec_add_mul_limb_smaller_in_place_right(xs, ys, z); } }} // xs.len() > 0, xs.len() < ys.len(), z != 0 fn limbs_vec_add_mul_limb_smaller_in_place_right(xs: &[Limb], ys: &mut Vec, z: Limb) { let (ys_lo, ys_hi) = ys.split_at_mut(xs.len()); let mut carry = limbs_slice_mul_limb_in_place(ys_hi, z); let inner_carry = limbs_slice_add_mul_limb_same_length_in_place_right(xs, ys_lo, z); if inner_carry != 0 && limbs_slice_add_limb_in_place(ys_hi, inner_carry) { carry += 1; } if carry != 0 { ys.push(carry); } } // Given the limbs of two `Natural`s x and y, and a limb `z`, writes the limbs of x + y * z to // whichever input is longer. If the result is written to the first input, `false` is returned; if // to the second, `true` is returned. `xs` and `ys` should be nonempty and have no trailing zeros, // and `z` should be nonzero. The result will have no trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is positive, and the result is written to the longer input. pub_test! {limbs_vec_add_mul_limb_in_place_either( xs: &mut Vec, ys: &mut Vec, z: Limb, ) -> bool { if xs.len() >= ys.len() { limbs_vec_add_mul_limb_greater_in_place_left(xs, ys, z); false } else { limbs_vec_add_mul_limb_smaller_in_place_right(xs, ys, z); true } }} // Given the limbs `xs`, `ys` and `zs` of three `Natural`s x, y, and z, returns the limbs of x + y // * z. `xs` should be nonempty and `ys` and `zs` should have length at least 2. None of the slices // should have any trailing zeros. The result will have no trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n, m) = O(m + n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` are empty. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive, `sub` is positive, and `w` is returned instead of overwriting the first input. pub_test! {limbs_add_mul(xs: &[Limb], ys: &[Limb], zs: &[Limb]) -> Vec { let xs_len = xs.len(); let mut out_len = ys.len() + zs.len(); let mut out = vec![0; out_len]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ys.len(), zs.len())]; if limbs_mul_to_out(&mut out, ys, zs, &mut mul_scratch) == 0 { out_len -= 1; out.pop(); } assert_ne!(*out.last().unwrap(), 0); if xs_len >= out_len { limbs_add_greater(xs, &out) } else { if limbs_slice_add_greater_in_place_left(&mut out, xs) { out.push(1); } out } }} // Given the limbs `xs`, `ys` and `zs` of three `Natural`s x, y, and z, computes x + y * z. The // limbs of the result are written to `xs`. `xs` should be nonempty and `ys` and `zs` should have // length at least 2. None of the slices should have any trailing zeros. The result will have no // trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` are empty. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive and `sub` is positive. pub_test! {limbs_add_mul_in_place_left(xs: &mut Vec, ys: &[Limb], zs: &[Limb]) { let xs_len = xs.len(); let mut out_len = ys.len() + zs.len(); let mut out = vec![0; out_len]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ys.len(), zs.len())]; if limbs_mul_to_out(&mut out, ys, zs, &mut mul_scratch) == 0 { out_len -= 1; out.pop(); } assert_ne!(*out.last().unwrap(), 0); if xs_len < out_len { swap(xs, &mut out); } if limbs_slice_add_greater_in_place_left(xs, &out) { xs.push(1); } }} impl Natural { fn add_mul_limb_ref_ref(&self, y: &Self, z: Limb) -> Self { match (self, y, z) { (x, _, 0) | (x, &Self::ZERO, _) => x.clone(), (x, y, 1) => x + y, (x, &Self::ONE, z) => x + Self::from(z), (Self(Large(xs)), Self(Large(ys)), z) => Self(Large(limbs_add_mul_limb(xs, ys, z))), (x, y, z) => x + y * Self::from(z), } } fn add_mul_assign_limb(&mut self, mut y: Self, z: Limb) { match (&mut *self, &mut y, z) { (_, _, 0) | (_, &mut Self::ZERO, _) => {} (x, _, 1) => *x += y, (x, &mut Self::ONE, z) => *x += Self::from(z), (Self(Large(xs)), Self(Large(ys)), z) => { if limbs_vec_add_mul_limb_in_place_either(xs, ys, z) { *self = y; } } (x, _, z) => *x += y * Self::from(z), } } fn add_mul_assign_limb_ref(&mut self, y: &Self, z: Limb) { match (&mut *self, y, z) { (_, _, 0) | (_, &Self::ZERO, _) => {} (x, y, 1) => *x += y, (x, &Self::ONE, z) => *x += Self::from(z), (Self(Large(xs)), Self(Large(ys)), z) => { limbs_vec_add_mul_limb_in_place_left(xs, ys, z); } (x, y, z) => *x += y * Self::from(z), } } } impl AddMul for Natural { type Output = Self; /// Adds a [`Natural`] and the product of two other [`Natural`]s, taking all three by value. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).add_mul(Natural::from(3u32), Natural::from(4u32)), /// 22 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .add_mul(Natural::from(0x10000u32), Natural::from(10u32).pow(12)), /// 65537000000000000u64 /// ); /// ``` #[inline] fn add_mul(mut self, y: Self, z: Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a> AddMul for Natural { type Output = Self; /// Adds a [`Natural`] and the product of two other [`Natural`]s, taking the first two by value /// and the third by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).add_mul(Natural::from(3u32), &Natural::from(4u32)), /// 22 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .add_mul(Natural::from(0x10000u32), &Natural::from(10u32).pow(12)), /// 65537000000000000u64 /// ); /// ``` #[inline] fn add_mul(mut self, y: Self, z: &'a Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a> AddMul<&'a Self, Self> for Natural { type Output = Self; /// Adds a [`Natural`] and the product of two other [`Natural`]s, taking the first and third by /// value and the second by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).add_mul(&Natural::from(3u32), Natural::from(4u32)), /// 22 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .add_mul(&Natural::from(0x10000u32), Natural::from(10u32).pow(12)), /// 65537000000000000u64 /// ); /// ``` #[inline] fn add_mul(mut self, y: &'a Self, z: Self) -> Self { self.add_mul_assign(y, z); self } } impl<'a, 'b> AddMul<&'a Self, &'b Self> for Natural { type Output = Self; /// Adds a [`Natural`] and the product of two other [`Natural`]s, taking the first by value and /// the second and third by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).add_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 22 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .add_mul(&Natural::from(0x10000u32), &Natural::from(10u32).pow(12)), /// 65537000000000000u64 /// ); /// ``` #[inline] fn add_mul(mut self, y: &'a Self, z: &'b Self) -> Self { self.add_mul_assign(y, z); self } } impl AddMul<&Natural, &Natural> for &Natural { type Output = Natural; /// Adds a [`Natural`] and the product of two other [`Natural`]s, taking all three by reference. /// /// $f(x, y, z) = x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n, m) = O(m + n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMul, Pow}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).add_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 22 /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .add_mul(&Natural::from(0x10000u32), &Natural::from(10u32).pow(12)), /// 65537000000000000u64 /// ); /// ``` fn add_mul(self, y: &Natural, z: &Natural) -> Natural { match (self, y, z) { (Natural(Small(x)), y, z) => (y * z).add_limb(*x), (x, Natural(Small(y)), z) => x.add_mul_limb_ref_ref(z, *y), (x, y, Natural(Small(z))) => x.add_mul_limb_ref_ref(y, *z), (Natural(Large(xs)), Natural(Large(ys)), Natural(Large(zs))) => { Natural(Large(limbs_add_mul(xs, ys, zs))) } } } } impl AddMulAssign for Natural { /// Adds the product of two other [`Natural`]s to a [`Natural`] in place, taking both /// [`Natural`]s on the right-hand side by value. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.add_mul_assign(Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = Natural::from(10u32).pow(12); /// x.add_mul_assign(Natural::from(0x10000u32), Natural::from(10u32).pow(12)); /// assert_eq!(x, 65537000000000000u64); /// ``` fn add_mul_assign(&mut self, mut y: Self, mut z: Self) { match (&mut *self, &mut y, &mut z) { (Self(Small(x)), _, _) => *self = (y * z).add_limb(*x), (_, Self(Small(y)), _) => self.add_mul_assign_limb(z, *y), (_, _, Self(Small(z))) => self.add_mul_assign_limb(y, *z), (Self(Large(xs)), Self(Large(ys)), Self(Large(zs))) => { limbs_add_mul_in_place_left(xs, ys, zs); } } } } impl<'a> AddMulAssign for Natural { /// Adds the product of two other [`Natural`]s to a [`Natural`] in place, taking the first /// [`Natural`] on the right-hand side by value and the second by reference. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.add_mul_assign(Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = Natural::from(10u32).pow(12); /// x.add_mul_assign(Natural::from(0x10000u32), &Natural::from(10u32).pow(12)); /// assert_eq!(x, 65537000000000000u64); /// ``` fn add_mul_assign(&mut self, mut y: Self, z: &'a Self) { match (&mut *self, &mut y, z) { (Self(Small(x)), _, _) => *self = (y * z).add_limb(*x), (_, Self(Small(y)), _) => self.add_mul_assign_limb_ref(z, *y), (_, _, Self(Small(z))) => self.add_mul_assign_limb(y, *z), (Self(Large(xs)), Self(Large(ys)), Self(Large(zs))) => { limbs_add_mul_in_place_left(xs, ys, zs); } } } } impl<'a> AddMulAssign<&'a Self, Self> for Natural { /// Adds the product of two other [`Natural`]s to a [`Natural`] in place, taking the first /// [`Natural`] on the right-hand side by reference and the second by value. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.add_mul_assign(&Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = Natural::from(10u32).pow(12); /// x.add_mul_assign(&Natural::from(0x10000u32), Natural::from(10u32).pow(12)); /// assert_eq!(x, 65537000000000000u64); /// ``` fn add_mul_assign(&mut self, y: &'a Self, mut z: Self) { match (&mut *self, y, &mut z) { (Self(Small(x)), _, _) => *self = (y * z).add_limb(*x), (_, Self(Small(y)), _) => self.add_mul_assign_limb(z, *y), (_, _, Self(Small(z))) => self.add_mul_assign_limb_ref(y, *z), (Self(Large(xs)), Self(Large(ys)), Self(Large(zs))) => { limbs_add_mul_in_place_left(xs, ys, zs); } } } } impl<'a, 'b> AddMulAssign<&'a Self, &'b Self> for Natural { /// Adds the product of two other [`Natural`]s to a [`Natural`] in place, taking both /// [`Natural`]s on the right-hand side by reference. /// /// $x \gets x + yz$. /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{AddMulAssign, Pow}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.add_mul_assign(&Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 22); /// /// let mut x = Natural::from(10u32).pow(12); /// x.add_mul_assign(&Natural::from(0x10000u32), &Natural::from(10u32).pow(12)); /// assert_eq!(x, 65537000000000000u64); /// ``` fn add_mul_assign(&mut self, y: &'a Self, z: &'b Self) { match (&mut *self, y, z) { (Self(Small(x)), _, _) => *self = (y * z).add_limb(*x), (_, Self(Small(y)), _) => self.add_mul_assign_limb_ref(z, *y), (_, _, Self(Small(z))) => self.add_mul_assign_limb_ref(y, *z), (Self(Large(xs)), Self(Large(ys)), Self(Large(zs))) => { limbs_add_mul_in_place_left(xs, ys, zs); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed to the GNU project by Torbjörn Granlund and Marco Bodrato. // // Copyright © 1998-2012, 2013, 2015-2018 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::div::limbs_hensel_div_limb_in_place; use crate::natural::arithmetic::div_exact::{ limbs_modular_div_schoolbook_in_place, limbs_modular_invert_limb, }; use crate::natural::arithmetic::div_round::double_cmp; use crate::natural::arithmetic::factorial::{bit_to_n, limbs_odd_factorial, log_n_max}; use crate::natural::arithmetic::mul::limb::limbs_slice_mul_limb_in_place; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::mul::product_of_limbs::limbs_product; use crate::natural::arithmetic::neg::limbs_neg_in_place; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::{ CENTRAL_BINOMIAL_2FAC_TABLE, Limb, ODD_CENTRAL_BINOMIAL_OFFSET, ODD_CENTRAL_BINOMIAL_TABLE_LIMIT, ODD_FACTORIAL_EXTTABLE_LIMIT, ODD_FACTORIAL_TABLE_LIMIT, ODD_FACTORIAL_TABLE_MAX, ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE, ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE, ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE, ONE_LIMB_ODD_FACTORIAL_TABLE, TABLE_2N_MINUS_POPC_2N, }; use alloc::vec::Vec; use core::cmp::{Ordering::*, max, min}; use malachite_base::num::arithmetic::traits::{ AddMulAssign, BinomialCoefficient, DivAssignMod, DivExact, Parity, PowerOf2, Square, WrappingAddAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u32; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u64; use malachite_base::num::factorization::prime_sieve::{id_to_n, limbs_prime_sieve_size, n_to_bit}; use malachite_base::num::logic::traits::{CountOnes, LeadingZeros, SignificantBits}; // This is similar to `mulfunc` from `mpz/bin_uiui.c`, GMP 6.2.1. const fn apply_mul_func(n: Limb, m: Limb) -> Limb { match n { 1 => m, 2 => (m | 1) * ((m + 1) >> 1), 3 => { let m01 = (m * (m + 1)) >> 1; let m2 = m + 2; m01 * m2 } 4 => { let m03 = (m * (m + 3)) >> 1; m03 * (m03 + 1) } 5 => { let m03 = (m * (m + 3)) >> 1; let m034 = m03 * (m + 4); (m03 + 1) * m034 } 6 => { let m05 = m * (m + 5); let m1234 = ((m05 + 5) * (m05 + 5)) >> 3; m1234 * (m05 >> 1) } 7 => { let m05 = m * (m + 5); let m1234 = ((m05 + 5) * (m05 + 5)) >> 3; let m056 = (m05 * (m + 6)) >> 1; m1234 * m056 } 8 => { let m07 = m * (m + 7); let m0257 = (m07 * (m07 + 10)) >> 3; let m1346 = m07 + 9 + m0257; m0257 * m1346 } _ => panic!(), } } const M: Limb = 8; const SOME_THRESHOLD: usize = 20; // This is equivalent to `mpz_bdiv_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a `Vec` of // limbs is returned. pub_test! {limbs_binomial_coefficient_limb_limb_bdiv(n: Limb, k: Limb) -> Vec { assert!(k > Limb::wrapping_from(ODD_FACTORIAL_TABLE_LIMIT)); let max_n = 1 + usize::exact_from(n >> Limb::LOG_WIDTH); let alloc = min( SOME_THRESHOLD - 1 + max((3 * max_n) >> 1, SOME_THRESHOLD), usize::exact_from(k), ) + 1; let mut big_scratch = vec![0; alloc + SOME_THRESHOLD + 1]; let (ns, ks) = big_scratch.split_at_mut(alloc); let n_max = Limb::wrapping_from(log_n_max(n)); assert!(n_max <= M); let mut k_max = Limb::wrapping_from(log_n_max(k)); assert!(k_max <= M); assert!(k >= M); assert!(n >= k); let mut i = n - k + 1; ns[0] = 1; let mut n_len = 1; let mut num_fac = 1; let mut j = Limb::wrapping_from(ODD_FACTORIAL_TABLE_LIMIT + 1); let mut jjj = ODD_FACTORIAL_TABLE_MAX; assert_eq!( ONE_LIMB_ODD_FACTORIAL_TABLE[ODD_FACTORIAL_TABLE_LIMIT], ODD_FACTORIAL_TABLE_MAX ); loop { ks[0] = jjj; let mut k_len = 1; let mut t = k + 1 - j; k_max = min(k_max, t); while k_max != 0 && k_len < SOME_THRESHOLD { jjj = apply_mul_func(k_max, j); j += k_max; jjj >>= jjj.trailing_zeros(); let cy = limbs_slice_mul_limb_in_place(&mut ks[..k_len], jjj); ks[k_len] = cy; if cy != 0 { k_len += 1; } t = k + 1 - j; k_max = min(k_max, t); } num_fac = j - num_fac; while num_fac != 0 { let n_max_now = min(n_max, num_fac); let mut iii = apply_mul_func(n_max_now, i); i.wrapping_add_assign(n_max_now); iii >>= iii.trailing_zeros(); let carry = limbs_slice_mul_limb_in_place(&mut ns[..n_len], iii); ns[n_len] = carry; if carry != 0 { n_len += 1; } num_fac -= n_max_now; } if ns[n_len - 1] >= ks[k_len - 1] { n_len += 1; } n_len -= k_len; let d_inv = limbs_modular_invert_limb(ks[0]); limbs_modular_div_schoolbook_in_place(ns, &ks[..min(k_len, n_len)], d_inv.wrapping_neg()); limbs_neg_in_place(&mut ns[..n_len]); if k_max == 0 { break; } num_fac = j; jjj = apply_mul_func(k_max, j); j += k_max; jjj >>= jjj.trailing_zeros(); } // Put back the right number of factors of 2. let ones = CountOnes::count_ones(n - k) + CountOnes::count_ones(k) - CountOnes::count_ones(n); if ones != 0 { assert!(ones < Limb::WIDTH); let carry = limbs_slice_shl_in_place(&mut ns[..n_len], ones); ns[n_len] = carry; if carry != 0 { n_len += 1; } } if ns[n_len - 1] == 0 { n_len -= 1; } let mut ns = big_scratch; ns.truncate(n_len); ns }} // Number of factors-of-2 removed by the corresponding mulN function. // // This is equivalent to `tcnttab` from `mpz/bin_uiui.c`, GMP 6.2.1. const TCNT_TAB: [u8; 8] = [0, 1, 1, 2, 2, 4, 4, 6]; // This is equivalent to `mpz_smallk_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a `Vec` of // limbs is returned. pub_test! {limbs_binomial_coefficient_limb_limb_small_k(n: Limb, k: Limb) -> Vec { let n_max = Limb::wrapping_from(log_n_max(n)); let mut n_max = min(n_max, M); let mut i = n - k + 1; let k_u = usize::exact_from(k); assert!(k_u <= ODD_FACTORIAL_TABLE_LIMIT); let mut i2_count = TABLE_2N_MINUS_POPC_2N[(k_u >> 1) - 1]; let factorial_inverse = ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE[k_u - 2]; if n_max >= k { return vec![ (apply_mul_func(k, i).wrapping_mul(factorial_inverse)) >> (i2_count - TCNT_TAB[k_u - 1]), ]; } let alloc = bit_to_limb_count_floor(n.significant_bits() * u64::exact_from(k)) + 3; let mut out = vec![0; alloc]; out[0] = apply_mul_func(n_max, i); let mut out_len = 1; i += n_max; i2_count -= TCNT_TAB[usize::exact_from(n_max - 1)]; let mut num_fac = k - n_max; while num_fac != 0 { n_max = min(n_max, num_fac); let iii = apply_mul_func(n_max, i); i.wrapping_add_assign(n_max); i2_count -= TCNT_TAB[usize::exact_from(n_max - 1)]; let carry = limbs_slice_mul_limb_in_place(&mut out[..out_len], iii); out[out_len] = carry; if carry != 0 { out_len += 1; } num_fac -= n_max; } assert!(out_len < alloc); limbs_hensel_div_limb_in_place( &mut out[..out_len], ONE_LIMB_ODD_FACTORIAL_TABLE[k_u], factorial_inverse, u64::from(i2_count), ); while *out.last().unwrap() == 0 { out.pop(); } out }} // Tabulate factorials (k!/2^t)^(-1) mod B (where t is chosen such that k!/2^t is odd). // // This is equivalent to `bc_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a single limb is // returned. pub_test! {limbs_binomial_coefficient_limb_limb_basecase(n: Limb, k: Limb) -> Limb { assert!(n <= ODD_FACTORIAL_EXTTABLE_LIMIT as Limb); assert!(n >= k + 2); assert!(k >= 2); let n = usize::wrapping_from(n); let k = usize::wrapping_from(k); let diff = n - k; (ONE_LIMB_ODD_FACTORIAL_TABLE[n] .wrapping_mul(ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE[k - 2]) .wrapping_mul(ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE[diff - 2])) << (TABLE_2N_MINUS_POPC_2N[(n >> 1) - 1] - TABLE_2N_MINUS_POPC_2N[(k >> 1) - 1] - TABLE_2N_MINUS_POPC_2N[(diff >> 1) - 1]) }} pub(crate) const BIN_UIUI_RECURSIVE_SMALLDC: bool = Limb::WIDTH > u32::WIDTH; // Recursively exploit the relation bin(n, k) = bin(n, k >> 1) * bin(n - k >> 1, k - k >> 1) / // bin(k, k >> 1). // // Values for binomial(k, k >> 1) that fit in a limb are precomputed (with inverses). // // This is equivalent to `mpz_smallkdc_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a `Vec` of // limbs is returned. pub_test! {limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer( mut n: Limb, mut k: Limb, ) -> Vec { let half_k = k >> 1; let mut out = if !BIN_UIUI_RECURSIVE_SMALLDC || half_k <= ODD_FACTORIAL_TABLE_LIMIT as Limb { limbs_binomial_coefficient_limb_limb_small_k(n, half_k) } else { limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, half_k) }; k -= half_k; n -= half_k; let mut out_len = out.len(); if n <= ODD_FACTORIAL_EXTTABLE_LIMIT as Limb { out.push(0); let carry = limbs_slice_mul_limb_in_place( &mut out[..out_len], limbs_binomial_coefficient_limb_limb_basecase(n, k), ); out[out_len] = carry; if carry != 0 { out_len += 1; } } else { let t = if !BIN_UIUI_RECURSIVE_SMALLDC || k <= ODD_FACTORIAL_TABLE_LIMIT as Limb { limbs_binomial_coefficient_limb_limb_small_k(n, k) } else { limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, k) }; let out_copy = out[..out_len].to_vec(); out = limbs_mul(&out_copy, &t); out_len = out.len(); } let k_u = usize::exact_from(k); let mut shift = CENTRAL_BINOMIAL_2FAC_TABLE[k_u - ODD_CENTRAL_BINOMIAL_OFFSET]; if k != half_k { // k was odd shift -= 1; } let k_offset = k_u - ODD_CENTRAL_BINOMIAL_OFFSET; limbs_hensel_div_limb_in_place( &mut out[..out_len], ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE[k_offset], ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE[k_offset], shift, ); while *out.last().unwrap() == 0 { out.pop(); } out }} // Returns an approximation of the square root of x. It gives: // ``` // limb_apprsqrt (x) ^ 2 <= x < (limb_apprsqrt (x)+1) ^ 2 // ``` // or // ``` // x <= limb_apprsqrt (x) ^ 2 <= x * 9/8 // ``` fn limbs_approx_sqrt(x: Limb) -> Limb { assert!(x > 2); let s = (Limb::WIDTH - LeadingZeros::leading_zeros(x)) >> 1; (Limb::power_of_2(s) + (x >> s)) >> 1 } pub(crate) const BIN_GOETGHELUCK_THRESHOLD: Limb = 512; // Implementation of the algorithm by P. Goetgheluck, "Computing Binomial Coefficients", The // American Mathematical Monthly, Vol. 94, No. 4 (April 1987), pp. 360-365. // // This is equivalent to `mpz_goetgheluck_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a `Vec` // of limbs is returned. pub_test! { #[allow(clippy::useless_conversion)] limbs_binomial_coefficient_limb_limb_goetgheluck(n: Limb, k: Limb) -> Vec { assert!(BIN_GOETGHELUCK_THRESHOLD >= 13); assert!(n >= 25); let n_64 = u64::from(n); let k_64 = u64::from(k); let mut sieve = vec![0; limbs_prime_sieve_size::(n_64)]; #[cfg(feature = "32_bit_limbs")] let count = limbs_prime_sieve_u32(&mut sieve, n_64) + 1; #[cfg(not(feature = "32_bit_limbs"))] let count = limbs_prime_sieve_u64(&mut sieve, n) + 1; let mut factors = vec![0; usize::exact_from(count / log_n_max(n) + 1)]; let mut max_prod = Limb::MAX / n; // Handle primes = 2, 3 separately. let mut prod = Limb::power_of_2( CountOnes::count_ones(n - k) + CountOnes::count_ones(k) - CountOnes::count_ones(n), ); let mut j = 0; let mut a = n; let mut b = k; let mut mb = 0; if prod > max_prod { // would only happen for very large outputs factors[j] = prod; j += 1; prod = 1; } while a >= 3 { mb += b.div_assign_mod(3); let ma = a.div_assign_mod(3); if ma < mb { mb = 1; prod *= 3; } else { mb = 0; } } // Accumulate prime factors from 5 to n / 2 let s = n_to_bit(u64::from(limbs_approx_sqrt(n))); assert!(bit_to_n(s + 1).square() > n_64); let half_n_bit = n_to_bit(n_64 >> 1); assert!(s <= half_n_bit); let mut index = 0; let mut mask = 1; for i in 1..=s + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); let mut a = n; let mut b = k; let mut mb = 0; if prod > max_prod { factors[j] = prod; j += 1; prod = 1; } while a >= prime { mb += b.div_assign_mod(prime); let ma = a.div_assign_mod(prime); if ma < mb { mb = 1; prod *= prime; } else { mb = 0; } } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } assert!(max_prod <= Limb::MAX >> 1); max_prod <<= 1; for i in s + 2..=half_n_bit + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); if n % prime < k % prime { if prod > max_prod { factors[j] = prod; j += 1; prod = prime; } else { prod *= prime; } } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } max_prod >>= 1; // Store primes from (n-k)+1 to n let n_bit = n_to_bit(n_64); let n_minus_k_bit = n_to_bit(n_64 - k_64); assert!(n_minus_k_bit < n_bit); let i = n_minus_k_bit + 1; let mut index = bit_to_limb_count_floor(i); let mut mask = Limb::power_of_2(i & Limb::WIDTH_MASK); for i in i + 1..=n_bit + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); if prod > max_prod { factors[j] = prod; j += 1; prod = prime; } else { prod *= prime; } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } assert_ne!(j, 0); factors[j] = Limb::wrapping_from(prod); j += 1; let mut r = Vec::new(); let (size, new_r) = limbs_product(&mut r, &mut factors[..j]); r = new_r.unwrap(); r.truncate(size); r }} const BIN_UIUI_ENABLE_SMALLDC: bool = true; // This is equivalent to `mpz_bin_uiui` from `mpz/bin_uiui.c`, GMP 6.2.1, where a `Natural` is // returned. pub_test! {binomial_coefficient_limb_limb(n: Limb, mut k: Limb) -> Natural { if n < k { Natural::ZERO } else { // Rewrite bin(n, k) as bin(n, n - k) if that is smaller. k = min(k, n - k); if k == 0 { Natural::ONE } else if k == 1 { Natural::from(n) } else if n <= ODD_FACTORIAL_EXTTABLE_LIMIT as Limb { // k >= 2, n >= 4 Natural::from(limbs_binomial_coefficient_limb_limb_basecase(n, k)) } else if k <= ODD_FACTORIAL_TABLE_LIMIT as Limb { Natural::from_owned_limbs_asc(limbs_binomial_coefficient_limb_limb_small_k(n, k)) } else if BIN_UIUI_ENABLE_SMALLDC && k <= (if BIN_UIUI_RECURSIVE_SMALLDC { ODD_CENTRAL_BINOMIAL_TABLE_LIMIT } else { ODD_FACTORIAL_TABLE_LIMIT } as Limb) << 1 { Natural::from_owned_limbs_asc( limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, k), ) } else if k >= BIN_GOETGHELUCK_THRESHOLD && k > n >> 4 { // k > ODD_FACTORIAL_TABLE_LIMIT Natural::from_owned_limbs_asc(limbs_binomial_coefficient_limb_limb_goetgheluck(n, k)) } else { Natural::from_owned_limbs_asc(limbs_binomial_coefficient_limb_limb_bdiv(n, k)) } } }} // Computes r = n * (n + (2 * k - 1)) / 2. // // It uses a square instead of a product, computing r = ((n + k - 1) ^ 2 + n - (k - 1) ^ 2) / 2 As a // side effect, sets t = n + k - 1. // // This is equivalent to `mpz_hmul_nbnpk` from `mpz/bin_ui.c`, GMP 6.2.1. fn binomial_coefficient_hmul_nbnpk(n: &Natural, mut k: Limb) -> Natural { assert_ne!(k, 0); assert_ne!(*n, 0u32); k -= 1; (((n + Natural::from(k)).square() + n) >> 1u32) - Natural::from(k + (k & 1)) * Natural::from(k >> 1) } // This is equivalent to `rek_raising_fac4` from `mpz/bin_ui.c`, GMP 6.2.1. fn binomial_coefficient_raising_factorial_4_rec( r: &mut Natural, p: &mut Natural, big_p: &mut Natural, k: Limb, lk: Limb, ) { assert!(k >= lk); if k - lk < 5 { for i in (lk + 1..=k).rev() { let four_i = i << 2; *p += Natural::from(four_i + 2); big_p.add_mul_assign(&*p, Natural::from(four_i)); *big_p -= Natural::from(i); *r *= &*big_p; } } else { let m = ((k + lk) >> 1) + 1; binomial_coefficient_raising_factorial_4_rec(r, p, big_p, k, m); let four_m = m << 2; *p += Natural::from(four_m + 2); big_p.add_mul_assign(&*p, Natural::from(four_m)); *big_p -= Natural::from(m); let mut t = big_p.clone(); binomial_coefficient_raising_factorial_4_rec(&mut t, p, big_p, m - 1, lk); *r *= t; } } // This is equivalent to `mpz_raising_fac4` from `mpz/bin_ui.c`, GMP 6.2.1, where r is returned. fn binomial_coefficient_raising_factorial_4(mut n: Natural, mut k: Limb) -> Natural { assert!(k >= 2); n += Natural::ONE; let mut r = Natural::ZERO; if k.odd() { r = n.clone(); n += Natural::ONE; } k >>= 1; let mut p = binomial_coefficient_hmul_nbnpk(&n, k); if k.odd() { if r != 0u32 { r *= &p; } else { r = p.clone(); } p += Natural::from(k - 1); } k >>= 1; if k == 0 { return r; } let mut t = binomial_coefficient_hmul_nbnpk(&p, k); if r != 0u32 { r *= &t; } else { r = t.clone(); } if k > 1 { p -= Natural::from(k); binomial_coefficient_raising_factorial_4_rec(&mut r, &mut p, &mut t, k - 1, 0); } r } // This is equivalent to `mpz_bin_ui` from `mpz/bin_ui.c`, GMP 6.2.1, where n is non-negative, n >= // k, k <= n - k, and r is returned. fn binomial_coefficient_helper(n: Natural, k: Limb) -> Natural { assert_ne!(k, 0); if k < 2 { n } else if let Ok(small_n) = Limb::try_from(&n) { binomial_coefficient_limb_limb(small_n, k) } else { (binomial_coefficient_raising_factorial_4(n - Natural::from(k), k) >> (k - (k >> 1) - (k >> 2)) .checked_sub(Limb::wrapping_from(CountOnes::count_ones(k))) .unwrap()) .div_exact(Natural::from_owned_limbs_asc(limbs_odd_factorial( usize::exact_from(k), false, ))) } } impl BinomialCoefficient for Natural { /// Computes the binomial coefficient of two [`Natural`]s, taking both by value. /// /// $$ /// f(n, k) =binom{n}{k} =frac{n!}{k!(n-k)!}. /// $$ /// /// # Worst-case complexity /// TODO /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::BinomialCoefficient; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(4u32), Natural::from(0u32)), /// 1 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(4u32), Natural::from(1u32)), /// 4 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(4u32), Natural::from(2u32)), /// 6 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(4u32), Natural::from(3u32)), /// 4 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(4u32), Natural::from(4u32)), /// 1 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(10u32), Natural::from(5u32)), /// 252 /// ); /// assert_eq!( /// Natural::binomial_coefficient(Natural::from(100u32), Natural::from(50u32)).to_string(), /// "100891344545564193334812497256" /// ); /// ``` fn binomial_coefficient(n: Self, mut k: Self) -> Self { if k > n { return Self::ZERO; } if k == 0u32 || n == k { return Self::ONE; } if double_cmp(&k, &n) == Greater { k = &n - &k; } binomial_coefficient_helper(n, Limb::try_from(&k).expect("k is too large")) } } impl<'a> BinomialCoefficient<&'a Self> for Natural { /// Computes the binomial coefficient of two [`Natural`]s, taking both by reference. /// /// $$ /// f(n, k) =binom{n}{k} =frac{n!}{k!(n-k)!}. /// $$ /// /// # Worst-case complexity /// TODO /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::BinomialCoefficient; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(4u32), &Natural::from(0u32)), /// 1 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(4u32), &Natural::from(1u32)), /// 4 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(4u32), &Natural::from(2u32)), /// 6 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(4u32), &Natural::from(3u32)), /// 4 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(4u32), &Natural::from(4u32)), /// 1 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(10u32), &Natural::from(5u32)), /// 252 /// ); /// assert_eq!( /// Natural::binomial_coefficient(&Natural::from(100u32), &Natural::from(50u32)) /// .to_string(), /// "100891344545564193334812497256" /// ); /// ``` fn binomial_coefficient(n: &'a Self, k: &'a Self) -> Self { if k > n { return Self::ZERO; } if *k == 0u32 || n == k { return Self::ONE; } let k = if double_cmp(k, n) == Greater { Limb::try_from(&(n - k)) } else { Limb::try_from(k) } .expect("k is too large"); binomial_coefficient_helper(n.clone(), k) } } ================================================ FILE: malachite-nz/src/natural/arithmetic/checked_sub.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::sub::{ limbs_sub, limbs_sub_greater_in_place_left, limbs_sub_limb, limbs_sub_limb_in_place, limbs_vec_sub_in_place_right, }; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::CheckedSub; use malachite_base::num::basic::traits::Zero; impl Natural { pub(crate) fn checked_sub_limb(mut self, other: Limb) -> Option { if self.sub_assign_limb_no_panic(other) { None } else { Some(self) } } pub(crate) fn checked_sub_limb_ref(&self, other: Limb) -> Option { match (self, other) { (_, 0) => Some(self.clone()), (Self(Small(small)), other) => small.checked_sub(other).map(Self::from), (Self(Large(limbs)), other) => { if *self < other { None } else { Some(Self::from_owned_limbs_asc(limbs_sub_limb(limbs, other).0)) } } } } // self -= other, return borrow fn sub_assign_limb_no_panic(&mut self, other: Limb) -> bool { match (&mut *self, other) { (_, 0) => false, (Self(Small(x)), y) => match x.checked_sub(y) { Some(diff) => { *x = diff; false } None => true, }, (Self(Large(xs)), y) => { let borrow = limbs_sub_limb_in_place(xs, y); if !borrow { self.trim(); } borrow } } } // self -= other, return borrow pub(crate) fn sub_assign_no_panic(&mut self, other: Self) -> bool { match (&mut *self, other) { (_, Self::ZERO) => false, (x, Self(Small(y))) => x.sub_assign_limb_no_panic(y), (Self(Small(_)), _) => true, (&mut Self(Large(ref mut xs)), Self(Large(ys))) => { let borrow = xs.len() < ys.len() || limbs_sub_greater_in_place_left(xs, &ys); if !borrow { self.trim(); } borrow } } } // self -= &other, return borrow pub(crate) fn sub_assign_ref_no_panic(&mut self, other: &Self) -> bool { match (&mut *self, other) { (_, &Self::ZERO) => false, (x, y) if core::ptr::eq(&*x, y) => { *self = Self::ZERO; false } (x, &Self(Small(y))) => x.sub_assign_limb_no_panic(y), (Self(Small(_)), _) => true, (Self(Large(xs)), &Self(Large(ref ys))) => { let borrow = xs.len() < ys.len() || limbs_sub_greater_in_place_left(xs, ys); if !borrow { self.trim(); } borrow } } } // self = &other - self, return borrow pub(crate) fn sub_right_assign_no_panic(&mut self, other: &Self) -> bool { match (&mut *self, other) { (&mut Self::ZERO, y) => { *self = y.clone(); false } (x, y) if core::ptr::eq(x, y) => { *self = Self::ZERO; false } (Self(Small(x)), y) => y.checked_sub_limb_ref(*x).is_none_or(|result| { *self = result; false }), (_, Self(Small(_))) => true, (Self(Large(xs)), Self(Large(ys))) => { let borrow = xs.len() > ys.len() || limbs_vec_sub_in_place_right(ys, xs); if !borrow { self.trim(); } borrow } } } } impl CheckedSub for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking both by value and returning `None` if /// the result is negative. /// /// $$ /// f(x, y) = \\begin{cases} /// \operatorname{Some}(x - y) & \text{if} \\quad x \geq y, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSub, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO /// .checked_sub(Natural::from(123u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(123u32) /// .checked_sub(Natural::ZERO) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from(456u32) /// .checked_sub(Natural::from(123u32)) /// .to_debug_string(), /// "Some(333)" /// ); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .checked_sub(Natural::from(10u32).pow(12)) /// .to_debug_string(), /// "Some(2000000000000)" /// ); /// ``` fn checked_sub(mut self, other: Self) -> Option { if self.sub_assign_no_panic(other) { None } else { Some(self) } } } impl<'a> CheckedSub<&'a Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning `None` if the result is negative. /// /// $$ /// f(x, y) = \\begin{cases} /// \operatorname{Some}(x - y) & \text{if} \\quad x \geq y, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSub, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO /// .checked_sub(&Natural::from(123u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(123u32) /// .checked_sub(&Natural::ZERO) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from(456u32) /// .checked_sub(&Natural::from(123u32)) /// .to_debug_string(), /// "Some(333)" /// ); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .checked_sub(&Natural::from(10u32).pow(12)) /// .to_debug_string(), /// "Some(2000000000000)" /// ); /// ``` fn checked_sub(mut self, other: &'a Self) -> Option { if self.sub_assign_ref_no_panic(other) { None } else { Some(self) } } } impl CheckedSub for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning `None` if the result is negative. /// /// $$ /// f(x, y) = \\begin{cases} /// \operatorname{Some}(x - y) & \text{if} \\quad x \geq y, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSub, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO) /// .checked_sub(Natural::from(123u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .checked_sub(Natural::ZERO) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// (&Natural::from(456u32)) /// .checked_sub(Natural::from(123u32)) /// .to_debug_string(), /// "Some(333)" /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .checked_sub(Natural::from(10u32).pow(12)) /// .to_debug_string(), /// "Some(2000000000000)" /// ); /// ``` fn checked_sub(self, mut other: Natural) -> Option { if other.sub_right_assign_no_panic(self) { None } else { Some(other) } } } impl CheckedSub<&Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking both by reference and returning /// `None` if the result is negative. /// /// $$ /// f(x, y) = \\begin{cases} /// \operatorname{Some}(x - y) & \text{if} \\quad x \geq y, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSub, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO) /// .checked_sub(&Natural::from(123u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .checked_sub(&Natural::ZERO) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// (&Natural::from(456u32)) /// .checked_sub(&Natural::from(123u32)) /// .to_debug_string(), /// "Some(333)" /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .checked_sub(&Natural::from(10u32).pow(12)) /// .to_debug_string(), /// "Some(2000000000000)" /// ); /// ``` fn checked_sub(self, other: &Natural) -> Option { match (self, other) { (x, y) if core::ptr::eq(x, y) => Some(Natural::ZERO), (x, &Natural::ZERO) => Some(x.clone()), (x, &Natural(Small(y))) => x.checked_sub_limb_ref(y), (Natural(Small(_)), _) => None, (Natural(Large(xs)), Natural(Large(ys))) => { if self < other { None } else { Some(Natural::from_owned_limbs_asc(limbs_sub(xs, ys).0)) } } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::sub_mul::{ limbs_sub_mul, limbs_sub_mul_in_place_left, limbs_sub_mul_limb_greater, limbs_sub_mul_limb_greater_in_place_left, }; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{CheckedSub, CheckedSubMul}; use malachite_base::num::basic::traits::Zero; macro_rules! large_left { ($a_limbs: ident, $b_limbs: ident, $c_limbs: ident) => { ( Natural(Large($a_limbs)), Natural(Large($b_limbs)), Natural(Large($c_limbs)), ) }; } macro_rules! large_right { ($self: ident, $a_limbs: ident, $b_limbs: ident, $c_limbs: ident) => {{ let borrow = $a_limbs.len() < $b_limbs.len() + $c_limbs.len() - 1 || limbs_sub_mul_in_place_left($a_limbs, &$b_limbs, &$c_limbs); if !borrow { $self.trim(); } borrow }}; } impl Natural { fn checked_sub_mul_limb_ref_ref(&self, b: &Self, c: Limb) -> Option { match (self, b, c) { (a, _, 0) | (a, &Self::ZERO, _) => Some(a.clone()), (a, b @ Self(Small(_)), c) => a.checked_sub(b * Self::from(c)), (Self(Small(_)), _, _) => None, (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => { if a_limbs.len() >= b_limbs.len() { limbs_sub_mul_limb_greater(a_limbs, b_limbs, c).map(Self::from_owned_limbs_asc) } else { None } } } } fn sub_mul_assign_limb_no_panic(&mut self, b: Self, c: Limb) -> bool { match (&mut *self, b, c) { (_, _, 0) | (_, Self::ZERO, _) => false, (a, b @ Self(Small(_)), c) => a.sub_assign_no_panic(b * Self::from(c)), (Self(Small(_)), _, _) => true, (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => { let borrow = a_limbs.len() < b_limbs.len() || limbs_sub_mul_limb_greater_in_place_left(a_limbs, &b_limbs, c) != 0; if !borrow { self.trim(); } borrow } } } fn sub_mul_assign_limb_ref_no_panic(&mut self, b: &Self, c: Limb) -> bool { match (&mut *self, b, c) { (_, _, 0) | (_, &Self::ZERO, _) => false, (a, b @ Self(Small(_)), c) => a.sub_assign_no_panic(b * Self::from(c)), (Self(Small(_)), _, _) => true, (Self(Large(a_limbs)), Self(Large(b_limbs)), c) => { let borrow = a_limbs.len() < b_limbs.len() || limbs_sub_mul_limb_greater_in_place_left(a_limbs, b_limbs, c) != 0; if !borrow { self.trim(); } borrow } } } pub(crate) fn sub_mul_assign_no_panic(&mut self, b: Self, c: Self) -> bool { match (&mut *self, b, c) { (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_no_panic(c, small_b), (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_no_panic(b, small_c), (Self(Small(_)), _, _) => true, large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs), } } pub(crate) fn sub_mul_assign_val_ref_no_panic(&mut self, b: Self, c: &Self) -> bool { match (&mut *self, &b, c) { (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_ref_no_panic(c, *small_b), (a, _, Self(Small(small_c))) => a.sub_mul_assign_limb_no_panic(b, *small_c), (Self(Small(_)), _, _) => true, large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs), } } pub(crate) fn sub_mul_assign_ref_val_no_panic(&mut self, b: &Self, c: Self) -> bool { match (&mut *self, b, &c) { (a, Self(Small(small_b)), _) => a.sub_mul_assign_limb_no_panic(c, *small_b), (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_ref_no_panic(b, *small_c), (Self(Small(_)), _, _) => true, large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs), } } pub(crate) fn sub_mul_assign_ref_ref_no_panic(&mut self, b: &Self, c: &Self) -> bool { match (&mut *self, b, c) { (a, Self(Small(small_b)), c) => a.sub_mul_assign_limb_ref_no_panic(c, *small_b), (a, b, Self(Small(small_c))) => a.sub_mul_assign_limb_ref_no_panic(b, *small_c), (Self(Small(_)), _, _) => true, large_left!(a_limbs, b_limbs, c_limbs) => large_right!(self, a_limbs, b_limbs, c_limbs), } } } impl CheckedSubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by value /// and returning `None` if the result is negative. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32) /// .checked_sub_mul(Natural::from(3u32), Natural::from(4u32)) /// .to_debug_string(), /// "Some(8)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .checked_sub_mul(Natural::from(3u32), Natural::from(4u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .checked_sub_mul(Natural::from(0x10000u32), Natural::from(0x10000u32)) /// .to_debug_string(), /// "Some(995705032704)" /// ); /// ``` fn checked_sub_mul(mut self, y: Self, z: Self) -> Option { if self.sub_mul_assign_no_panic(y, z) { None } else { Some(self) } } } impl<'a> CheckedSubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first two by /// value and the third by reference and returning `None` if the result is negative. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32) /// .checked_sub_mul(Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "Some(8)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .checked_sub_mul(Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .checked_sub_mul(Natural::from(0x10000u32), &Natural::from(0x10000u32)) /// .to_debug_string(), /// "Some(995705032704)" /// ); /// ``` fn checked_sub_mul(mut self, y: Self, z: &'a Self) -> Option { if self.sub_mul_assign_val_ref_no_panic(y, z) { None } else { Some(self) } } } impl<'a> CheckedSubMul<&'a Self, Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first and third /// by value and the second by reference and returning `None` if the result is negative. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32) /// .checked_sub_mul(&Natural::from(3u32), Natural::from(4u32)) /// .to_debug_string(), /// "Some(8)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .checked_sub_mul(&Natural::from(3u32), Natural::from(4u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .checked_sub_mul(&Natural::from(0x10000u32), Natural::from(0x10000u32)) /// .to_debug_string(), /// "Some(995705032704)" /// ); /// ``` fn checked_sub_mul(mut self, y: &'a Self, z: Self) -> Option { if self.sub_mul_assign_ref_val_no_panic(y, z) { None } else { Some(self) } } } impl<'a, 'b> CheckedSubMul<&'a Self, &'b Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first by value /// and the second and third by reference and returning `None` if the result is negative. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32) /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "Some(8)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .checked_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)) /// .to_debug_string(), /// "Some(995705032704)" /// ); /// ``` fn checked_sub_mul(mut self, y: &'a Self, z: &'b Self) -> Option { if self.sub_mul_assign_ref_ref_no_panic(y, z) { None } else { Some(self) } } } impl CheckedSubMul<&Natural, &Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by /// reference and returning `None` if the result is negative. /// /// $$ /// f(x, y, z) = \\begin{cases} /// \operatorname{Some}(x - yz) & \text{if} \\quad x \geq yz, \\\\ /// \operatorname{None} & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n, m) = O(m + n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{CheckedSubMul, Pow}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(20u32)) /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "Some(8)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .checked_sub_mul(&Natural::from(3u32), &Natural::from(4u32)) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .checked_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)) /// .to_debug_string(), /// "Some(995705032704)" /// ); /// ``` fn checked_sub_mul(self, y: &Natural, z: &Natural) -> Option { match (self, y, z) { (x, Natural(Small(small_y)), z) => x.checked_sub_mul_limb_ref_ref(z, *small_y), (x, y, Natural(Small(small_z))) => x.checked_sub_mul_limb_ref_ref(y, *small_z), (Natural(Small(_)), _, _) => None, (Natural(Large(x_limbs)), Natural(Large(y_limbs)), Natural(Large(z_limbs))) => { if x_limbs.len() >= y_limbs.len() + z_limbs.len() - 1 { limbs_sub_mul(x_limbs, y_limbs, z_limbs).map(Natural::from_owned_limbs_asc) } else { None } } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; #[cfg(feature = "test_build")] use malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::num::arithmetic::traits::{CoprimeWith, Gcd, Parity}; pub_test! {coprime_with_check_2(x: Natural, y: Natural) -> bool { (x.odd() || y.odd()) && x.gcd(y) == 1u32 }} #[cfg(feature = "test_build")] pub fn coprime_with_check_2_3(x: Natural, y: Natural) -> bool { (x.odd() || y.odd()) && (!(&x).divisible_by(Natural::from(3u32)) || !(&y).divisible_by(Natural::from(3u32))) && x.gcd(y) == 1u32 } #[cfg(feature = "test_build")] pub fn coprime_with_check_2_3_5(x: Natural, y: Natural) -> bool { if x.even() && y.even() { false } else { let x15 = &x % Natural::from(15u32); let y15 = &y % Natural::from(15u32); if (x15 == 0u32 || x15 == 3u32 || x15 == 6u32 || x15 == 9u32 || x15 == 12u32) && (y15 == 0u32 || y15 == 3u32 || y15 == 6u32 || y15 == 9u32 || y15 == 12u32) { return false; } if (x15 == 0u32 || x15 == 5u32 || x15 == 10u32) && (y15 == 0u32 || y15 == 5u32 || y15 == 10u32) { return false; } x.gcd(y) == 1u32 } } pub_test! {coprime_with_check_2_val_ref(x: Natural, y: &Natural) -> bool { (x.odd() || y.odd()) && x.gcd(y) == 1u32 }} pub_test! {coprime_with_check_2_ref_val(x: &Natural, y: Natural) -> bool { (x.odd() || y.odd()) && x.gcd(y) == 1u32 }} pub_test! {coprime_with_check_2_ref_ref(x: &Natural, y: &Natural) -> bool { (x.odd() || y.odd()) && x.gcd(y) == 1u32 }} impl CoprimeWith for Natural { /// Returns whether two [`Natural`]s are coprime; that is, whether they have no common factor /// other than 1. Both [`Natural`]s are taken by value. /// /// Every [`Natural`] is coprime with 1. No [`Natural`] is coprime with 0, except 1. /// /// $f(x, y) = (\gcd(x, y) = 1)$. /// /// $f(x, y) = ((k,m,n \in \N \land x=km \land y=kn) \implies k=1)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CoprimeWith; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).coprime_with(Natural::from(5u32)), true); /// assert_eq!( /// Natural::from(12u32).coprime_with(Natural::from(90u32)), /// false /// ); /// ``` #[inline] fn coprime_with(self, other: Self) -> bool { coprime_with_check_2(self, other) } } impl<'a> CoprimeWith<&'a Self> for Natural { /// Returns whether two [`Natural`]s are coprime; that is, whether they have no common factor /// other than 1. The first [`Natural`] is taken by value and the second by reference. /// /// Every [`Natural`] is coprime with 1. No [`Natural`] is coprime with 0, except 1. /// /// $f(x, y) = (\gcd(x, y) = 1)$. /// /// $f(x, y) = ((k,m,n \in \N \land x=km \land y=kn) \implies k=1)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CoprimeWith; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).coprime_with(&Natural::from(5u32)), true); /// assert_eq!( /// Natural::from(12u32).coprime_with(&Natural::from(90u32)), /// false /// ); /// ``` #[inline] fn coprime_with(self, other: &'a Self) -> bool { coprime_with_check_2_val_ref(self, other) } } impl CoprimeWith for &Natural { /// Returns whether two [`Natural`]s are coprime; that is, whether they have no common factor /// other than 1. The first [`Natural`] is taken by reference and the second by value. /// /// Every [`Natural`] is coprime with 1. No [`Natural`] is coprime with 0, except 1. /// /// $f(x, y) = (\gcd(x, y) = 1)$. /// /// $f(x, y) = ((k,m,n \in \N \land x=km \land y=kn) \implies k=1)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CoprimeWith; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).coprime_with(Natural::from(5u32)), /// true /// ); /// assert_eq!( /// (&Natural::from(12u32)).coprime_with(Natural::from(90u32)), /// false /// ); /// ``` #[inline] fn coprime_with(self, other: Natural) -> bool { coprime_with_check_2_ref_val(self, other) } } impl CoprimeWith<&Natural> for &Natural { /// Returns whether two [`Natural`]s are coprime; that is, whether they have no common factor /// other than 1. Both [`Natural`]s are taken by reference. /// /// Every [`Natural`] is coprime with 1. No [`Natural`] is coprime with 0, except 1. /// /// $f(x, y) = (\gcd(x, y) = 1)$. /// /// $f(x, y) = ((k,m,n \in \N \land x=km \land y=kn) \implies k=1)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CoprimeWith; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).coprime_with(Natural::from(5u32)), /// true /// ); /// assert_eq!( /// (&Natural::from(12u32)).coprime_with(Natural::from(90u32)), /// false /// ); /// ``` fn coprime_with(self, other: &Natural) -> bool { coprime_with_check_2_ref_ref(self, other) } } ================================================ FILE: malachite-nz/src/natural/arithmetic/div.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_dcpi1_divappr_q`, `mpn_dcpi1_divappr_q_n`, `mpn_div_q`, `mpn_mu_divappr_q`, // `mpn_mu_divappr_q_choose_in`, `mpn_mu_divappr_q_itch`, `mpn_preinv_mu_divappr_q`, // `mpn_sbpi1_div_q`, and `mpn_sbpi1_divappr_q` contributed to the GNU project by Torbjörn // Granlund. // // `mpn_dcpi1_div_q`, `mpn_mu_div_q`, and `mpn_mu_div_q_itch` contributed to the GNU project by // Torbjörn Granlund and Marco Bodrato. // // `mpn_div_qr_1` contributed to the GNU project by Niels Möller and Torbjörn Granlund. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div_mod::{ MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD, MUPI_DIV_QR_THRESHOLD, div_mod_by_preinversion, limbs_div_barrett_large_product, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_divide_and_conquer_helper, limbs_div_mod_schoolbook, limbs_div_mod_three_limb_by_two_limb, limbs_invert_approx, limbs_invert_approx_scratch_len, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::mul::mul_mod::{ limbs_mul_mod_base_pow_n_minus_1_next_size, limbs_mul_mod_base_pow_n_minus_1_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, limbs_sub_same_length_with_borrow_in_in_place_right, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{ DC_DIV_QR_THRESHOLD, DC_DIVAPPR_Q_THRESHOLD, DoubleLimb, FUDGE, Limb, MU_DIVAPPR_Q_THRESHOLD, }; use alloc::boxed::Box; use alloc::vec::Vec; use core::cmp::Ordering::*; use core::cmp::max; use core::iter::once; use core::mem::swap; use core::ops::{Div, DivAssign}; use malachite_base::fail_on_untested_path; #[cfg(feature = "test_build")] use malachite_base::num::arithmetic::traits::DivRem; use malachite_base::num::arithmetic::traits::{ CheckedDiv, WrappingAddAssign, WrappingMulAssign, WrappingSubAssign, XMulYToZZ, XXAddYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, HasHalf, JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::{slice_move_left, slice_set_zero}; // Divide an number by a divisor of B - 1, where B is the limb base. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns`. // // This is equivalent to `mpn_bdiv_dbm1c` from `mpn/generic/bdiv_dbm1c.c`, GMP 6.2.1. pub_crate_test! {limbs_div_divisor_of_limb_max_with_carry_to_out< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], ns: &[T], d: T, mut carry: T, ) -> T { assert!(out.len() >= ns.len()); let d = DT::from(d); for (q, &n) in out.iter_mut().zip(ns.iter()) { let (hi, lo) = (DT::from(n) * d).split_in_half(); let inner_carry = carry < lo; carry.wrapping_sub_assign(lo); *q = carry; carry.wrapping_sub_assign(hi); if inner_carry { carry.wrapping_sub_assign(T::ONE); } } carry }} // Divide an number by a divisor of B - 1, where B is the limb base. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_bdiv_dbm1c` from `mpn/generic/bdiv_dbm1c.c`, GMP 6.2.1, where `qp == // ap`. pub_crate_test! {limbs_div_divisor_of_limb_max_with_carry_in_place( ns: &mut [Limb], d: Limb, mut carry: Limb, ) -> Limb { let d = DoubleLimb::from(d); for n in &mut *ns { let (hi, lo) = (DoubleLimb::from(*n) * d).split_in_half(); let inner_carry = carry < lo; carry.wrapping_sub_assign(lo); *n = carry; carry.wrapping_sub_assign(hi); if inner_carry { carry.wrapping_sub_assign(1); } } carry }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_qrnnd_preinv` from `gmp-impl.h`, GMP 6.2.1, but not computing the // remainder. pub_test! {div_by_preinversion(n_high: Limb, n_low: Limb, d: Limb, d_inv: Limb) -> Limb { let (mut q_high, q_low) = (DoubleLimb::from(n_high) * DoubleLimb::from(d_inv)) .wrapping_add(DoubleLimb::join_halves(n_high.wrapping_add(1), n_low)) .split_in_half(); let mut r = n_low.wrapping_sub(q_high.wrapping_mul(d)); if r > q_low { q_high.wrapping_sub_assign(1); r.wrapping_add_assign(d); } if r >= d { q_high.wrapping_add_assign(1); } q_high }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs of the `Natural` divided by a `Limb`. The divisor limb cannot be zero and the limb // slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if the length of `ns` is less than 2 or if `d` is zero. // // This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, where the quotient // is returned, but not computing the remainder. pub_test! {limbs_div_limb(ns: &[Limb], d: Limb) -> Vec { let mut qs = vec![0; ns.len()]; limbs_div_limb_to_out(&mut qs, ns, d); qs }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to an output slice. The output slice must be // at least as long as the input slice. The divisor limb cannot be zero and the input limb slice // must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns`, the length of `ns` is less than 2, or if `d` is zero. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qxn == 0` // and `un > 1`, but not computing the remainder. pub_crate_test! {limbs_div_limb_to_out(out: &mut [Limb], ns: &[Limb], d: Limb) { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let out = &mut out[..len]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { // High quotient limb is 0 or 1, skip a divide step. let (r, ns_init) = ns.split_last().unwrap(); let mut r = *r; let (out_last, out_init) = out.split_last_mut().unwrap(); let adjust = r >= d; if adjust { r -= d; } *out_last = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); for (out_q, &n) in out_init.iter_mut().zip(ns_init.iter()).rev() { (*out_q, r) = div_mod_by_preinversion(r, n, d, d_inv); } } else { // Skip a division if high < divisor (high quotient 0). Testing here before normalizing will // still skip as often as possible. let (ns_last, ns_init) = ns.split_last().unwrap(); let (ns, mut r) = if *ns_last < d { *out.last_mut().unwrap() = 0; (ns_init, *ns_last) } else { (ns, 0) }; let d = d << bits; r <<= bits; let d_inv = limbs_invert_limb::(d); let (previous_n, ns_init) = ns.split_last().unwrap(); let mut previous_n = *previous_n; let cobits = Limb::WIDTH - bits; r |= previous_n >> cobits; let (out_first, out_tail) = out.split_first_mut().unwrap(); for (out_q, &n) in out_tail.iter_mut().zip(ns_init.iter()).rev() { let shifted_n = (previous_n << bits) | (n >> cobits); (*out_q, r) = div_mod_by_preinversion(r, shifted_n, d, d_inv); previous_n = n; } *out_first = div_by_preinversion(r, previous_n << bits, d, d_inv); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to the input slice. The divisor limb cannot // be zero and the input limb slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if the length of `ns` is less than 2 or if `d` is zero. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qp == up`, // `qxn == 0`, and `un > 1`, but not computing the remainder. pub_test! {limbs_div_limb_in_place(ns: &mut [Limb], d: Limb) { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let bits = LeadingZeros::leading_zeros(d); let (ns_last, ns_init) = ns.split_last_mut().unwrap(); if bits == 0 { // High quotient limb is 0 or 1, skip a divide step. let mut r = *ns_last; let adjust = r >= d; if adjust { r -= d; } *ns_last = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); for n in ns_init.iter_mut().rev() { (*n, r) = div_mod_by_preinversion(r, *n, d, d_inv); } } else { // Skip a division if high < divisor (high quotient 0). Testing here before normalizing will // still skip as often as possible. let (ns, mut r) = if *ns_last < d { let r = *ns_last; *ns_last = 0; (ns_init, r) } else { (ns, 0) }; let d = d << bits; r <<= bits; let d_inv = limbs_invert_limb::(d); let last_index = ns.len() - 1; let mut previous_n = ns[last_index]; let cobits = Limb::WIDTH - bits; r |= previous_n >> cobits; for i in (0..last_index).rev() { let n = ns[i]; let shifted_n = (previous_n << bits) | (n >> cobits); (ns[i + 1], r) = div_mod_by_preinversion(r, shifted_n, d, d_inv); previous_n = n; } ns[0] = div_by_preinversion(r, previous_n << bits, d, d_inv); } }} // Schoolbook division using the Möller-Granlund 3/2 division algorithm. // // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs`. Returns the most significant limb of the quotient; `true` means 1 and `false` means 0. `ds` // must have length greater than 2, `ns` must be at least as long as `ds`, and the most significant // bit of `ds` must be set. `d_inv` should be the result of `limbs_two_limb_inverse_helper` applied // to the two highest limbs of the denominator. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 3, `ns` is shorter than `ds`, `qs` has length less than // `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_sbpi1_div_q` from `mpn/generic/sbpi1_div_q.c`, GMP 6.2.1. pub_test! {limbs_div_schoolbook( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len > 2); assert!(n_len >= d_len); let d_len_m_1 = d_len - 1; let d_1 = ds[d_len_m_1]; assert!(d_1.get_highest_bit()); let q_len = n_len - d_len; let ds_s = if q_len < d_len_m_1 { &ds[d_len_m_1 - q_len..] } else { ds }; let d_len_s = ds_s.len(); // d_len or n_len - d_len + 1 let d_sum = d_len + d_len_s; // 2 * d_len or n_len + 1 let d_diff = d_len - d_len_s; // 0 or 2 * d_len - n_len - 1 let ns_hi = &mut ns[n_len - d_len_s..]; let highest_q = limbs_cmp_same_length(ns_hi, ds_s) >= Equal; if highest_q { limbs_sub_same_length_in_place_left(ns_hi, ds_s); } // Offset d_len by 2 for main division loops, saving two iterations in // limbs_sub_mul_limb_same_length_in_place_left. let d_len_m_2 = d_len - 2; let d_len_s_m_1 = d_len_s - 1; let d_len_s_m_2 = d_len_s.wrapping_sub(2); // only used when d_len_s >= 2 let d_2 = ds[d_len_m_2]; let mut n_1 = ns[n_len - 1]; for i in (d_sum - 1..n_len).rev() { let ns = &mut ns[i - d_len_s..i]; let mut q; if n_1 == d_1 && ns[d_len_s_m_1] == d_2 { q = Limb::MAX; limbs_sub_mul_limb_same_length_in_place_left(ns, ds_s, q); n_1 = ns[d_len_s_m_1]; // update n_1; last loop's value will now be invalid } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb( n_1, ns[d_len_s_m_1], ns[d_len_s - 2], d_1, d_2, d_inv, ); let mut n_0; (n_1, n_0) = n.split_in_half(); let carry = limbs_sub_mul_limb_same_length_in_place_left( &mut ns[..d_len_s - 2], &ds_s[..d_len_s - 2], q, ); let carry_2 = n_0 < carry; n_0.wrapping_sub_assign(carry); let carry = carry_2 && n_1 == 0; if carry_2 { n_1.wrapping_sub_assign(1); } ns[d_len_s_m_2] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left( &mut ns[..d_len_s_m_1], &ds_s[..d_len_s_m_1], ) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } } qs[i - d_len] = q; } let mut flag = true; let offset = if d_len_s >= 2 { let mut ds_suffix = &ds[d_diff..]; for i in (1..d_len_s_m_1).rev() { let ns = &mut ns[d_len_m_2..d_len + i]; let mut q; if !flag || n_1 >= d_1 { q = Limb::MAX; let carry = limbs_sub_mul_limb_same_length_in_place_left(ns, ds_suffix, q); if n_1 != carry { if flag && n_1 < carry { q.wrapping_sub_assign(1); limbs_slice_add_same_length_in_place_left(ns, ds_suffix); } else { flag = false; } } n_1 = ns[i + 1]; } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns[i + 1], ns[i], d_1, d_2, d_inv); let mut n_0; (n_1, n_0) = n.split_in_half(); let carry = limbs_sub_mul_limb_same_length_in_place_left( &mut ns[..i], &ds_suffix[..ds_suffix.len() - 2], q, ); let carry_2 = n_0 < carry; n_0.wrapping_sub_assign(carry); let carry = carry_2 && n_1 == 0; if carry_2 { n_1.wrapping_sub_assign(1); } ns[i] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left( &mut ns[..=i], &ds_suffix[..ds_suffix.len() - 1], ) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } } qs[i] = q; ds_suffix = &ds_suffix[1..]; } let mut q; let ns = &mut ns[d_len_m_2..d_len]; if !flag || n_1 >= d_1 { q = Limb::MAX; let ds_hi = &ds[d_len_m_2..]; let carry = limbs_sub_mul_limb_same_length_in_place_left(ns, &ds_hi[..2], q); if n_1 != carry { if flag && n_1 < carry { q.wrapping_sub_assign(1); (ns[1], ns[0]) = Limb::xx_add_yy_to_zz(ns[1], ns[0], d_2, ds_hi[0]); } else { flag = false; } } n_1 = ns[1]; } else { let new_n; (q, new_n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns[1], ns[0], d_1, d_2, d_inv); (n_1, ns[0]) = new_n.split_in_half(); ns[1] = n_1; } qs[0] = q; d_len } else { d_sum - 1 }; let (ns_last, ns_init) = ns[..offset].split_last_mut().unwrap(); assert_eq!(*ns_last, n_1); if flag && n_1 < Limb::exact_from(d_len) { let qs = &mut qs[offset - d_len..]; let qs = &mut qs[..q_len]; // The quotient may be too large if the remainder is small. Recompute for above ignored // operand parts, until the remainder spills. Compensate for triangularization. let ns = ns_init; { let (ns_last, ns_init) = ns.split_last_mut().unwrap(); for i in 3..=d_len_s { let q = qs[d_len_s - i]; let carry = limbs_sub_mul_limb_same_length_in_place_left( &mut ns_init[offset - i..], &ds_s[..i - 2], q, ); if *ns_last < carry { if n_1 == 0 { assert!(!limbs_sub_limb_in_place(qs, 1)); return highest_q; } n_1 -= 1; } ns_last.wrapping_sub_assign(carry); } } if d_diff != 0 { // Compensate for ignored dividend and divisor tails. if highest_q { let mut carry = limbs_sub_same_length_in_place_left(&mut ns[q_len..d_len_m_1], &ds[..d_diff]); if carry { if n_1 == 0 { if q_len != 0 { carry = limbs_sub_limb_in_place(qs, 1); } assert!(highest_q || !carry); return highest_q != carry; } n_1 -= 1; } } if q_len == 0 { return highest_q; } let ns = &mut ns[..d_len_m_1]; for i in (0..d_diff).rev() { let (ns_lo, ns_hi) = ns[i..].split_at_mut(q_len); if limbs_sub_limb_in_place( ns_hi, limbs_sub_mul_limb_same_length_in_place_left(ns_lo, qs, ds[i]), ) { if n_1 == 0 { limbs_sub_limb_in_place(qs, 1); return highest_q; } n_1 -= 1; } } } } highest_q }} // Recursive divide-and-conquer division. // // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs`. Returns the most significant limb of the quotient; `true` means 1 and `false` means 0. `ds` // must have length greater than 2, `ns` must be at least as long as `ds`, and the most significant // bit of `ds` must be set. `d_inv` should be the result of `limbs_two_limb_inverse_helper` applied // to the two highest limbs of the denominator. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 6, `ns` is shorter than or the same length as `ds`, `qs` // has length less than `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest // bit set. // // This is equivalent to `mpn_dcpi1_div_q` from `mpn/generic/dcpi1_div_q.c`, GMP 6.2.1. pub_test! {limbs_div_divide_and_conquer( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 6); assert!(n_len - d_len >= 3); let q_len = n_len - d_len; assert!(ds[d_len - 1].get_highest_bit()); let qs = &mut qs[..q_len]; let mut scratch = Vec::with_capacity(n_len + 1); scratch.push(1); scratch.extend_from_slice(ns); let mut scratch_2 = vec![0; q_len + 1]; let highest_q = limbs_div_divide_and_conquer_approx(&mut scratch_2, &mut scratch, ds, d_inv); let (scratch_2_head, scratch_2_tail) = scratch_2.split_first_mut().unwrap(); if *scratch_2_head == 0 { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(q_len, d_len)]; limbs_mul_to_out(&mut scratch, scratch_2_tail, ds, &mut mul_scratch); let scratch_init = &mut scratch[..n_len]; // At most is wrong by one, no cycle. if highest_q && limbs_slice_add_same_length_in_place_left(&mut scratch_init[q_len..], ds) || limbs_cmp_same_length(scratch_init, ns) == Greater { return if limbs_sub_limb_to_out(qs, scratch_2_tail, 1) { assert!(highest_q); false } else { highest_q }; } } qs.copy_from_slice(scratch_2_tail); highest_q }} // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs`. Returns the most significant limb of the quotient; `true` means 1 and `false` means 0. `ds` // must have length greater than 2, `ns` must be longer than `ds`, and the most significant bit of // `ds` must be set. // // The idea of the algorithm used herein is to compute a smaller inverted value than used in the // standard Barrett algorithm, and thus save time in the Newton iterations, and pay just a small // price when using the inverted value for developing quotient bits. This algorithm was presented at // ICMS 2006. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mu_div_q` from `mpn/generic/mu_div_q.c`, GMP 6.2.1. pub_test! {limbs_div_barrett( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb] ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len > d_len); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let q_len_plus_1 = q_len + 1; let mut scratch_2 = vec![0; q_len_plus_1]; let highest_q; if q_len >= d_len { // ``` // |_______________________| dividend // |________| divisor // ``` let mut rs = Vec::with_capacity(n_len + 1); rs.push(0); rs.extend_from_slice(ns); let rs_hi = &mut rs[q_len_plus_1..]; highest_q = limbs_cmp_same_length(rs_hi, ds) >= Equal; if highest_q { limbs_sub_same_length_in_place_left(rs_hi, ds); } if limbs_div_barrett_approx(&mut scratch_2, &rs, ds, scratch) { // Since the partial remainder fed to limbs_div_barrett_approx_preinverted was // canonically reduced, replace the returned value of B ^ (q_len - d_len) + epsilon by // the largest possible value. scratch_2.fill(Limb::MAX); } // The max error of limbs_div_barrett_approx is +4. If the low quotient limb is smaller than // the max error, we cannot trust the quotient. let (scratch_2_head, scratch_2_tail) = scratch_2.split_first().unwrap(); if *scratch_2_head > 4 { qs.copy_from_slice(scratch_2_tail); } else { let rs = &mut rs[..n_len]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(scratch_2_tail.len(), ds.len())]; limbs_mul_greater_to_out(rs, scratch_2_tail, ds, &mut mul_scratch); if highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..], ds) || limbs_cmp_same_length(rs, ns) == Greater { // At most is wrong by one, no cycle. if limbs_sub_limb_to_out(qs, scratch_2_tail, 1) { fail_on_untested_path("limbs_div_barrett, limbs_sub_greater_to_out 1"); assert!(highest_q); return false; } } else { qs.copy_from_slice(scratch_2_tail); } } } else { // ``` // |_______________________| dividend // |________________| divisor // ``` let ghost_n = n_len == (d_len << 1) - 1; highest_q = limbs_div_barrett_approx_helper( &mut scratch_2, &ns[if ghost_n { 0 } else { n_len - (q_len_plus_1 << 1) }..], ghost_n, &ds[d_len - q_len_plus_1..], scratch, ); // The max error of limbs_div_barrett_approx is +4, but we get an additional error from the // divisor truncation. let (scratch_2_head, scratch_2_tail) = scratch_2.split_first().unwrap(); if *scratch_2_head > 6 { qs.copy_from_slice(scratch_2_tail); } else { let mut rs = vec![0; n_len]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), scratch_2_tail.len())]; limbs_mul_greater_to_out(&mut rs, ds, scratch_2_tail, &mut mul_scratch); if highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..], ds) || limbs_cmp_same_length(&rs, ns) == Greater { // At most is wrong by one, no cycle. if limbs_sub_limb_to_out(qs, scratch_2_tail, 1) { assert!(highest_q); return false; } } else { qs.copy_from_slice(scratch_2_tail); } } } highest_q }} // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$, where $n$ is `n_len`. // // This is equivalent to `mpn_mu_div_q_itch` from `mpn/generic/mu_div_q.c`, GMP 6.2.1, where `mua_k // == 0`. pub_test! {limbs_div_barrett_scratch_len(n_len: usize, d_len: usize) -> usize { let q_len = n_len - d_len; if q_len >= d_len { limbs_div_barrett_approx_scratch_len(n_len + 1, d_len) } else { let q_len_plus_1 = q_len + 1; limbs_div_barrett_approx_scratch_len(q_len_plus_1 << 1, q_len_plus_1) } }} // Schoolbook division using the Möller-Granlund 3/2 division algorithm, returning approximate // quotient. // // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs`. Returns the most significant limb of the quotient; `true` means 1 and `false` means 0. The // quotient is either correct, or one too large. `ds` must have length greater than 2, `ns` must be // at least as long as `ds`, and the most significant bit of `ds` must be set. `d_inv` should be the // result of `limbs_two_limb_inverse_helper` applied to the two highest limbs of the denominator. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 3, `ns` is shorter than `ds`, `qs` has length less than // `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_sbpi1_divappr_q` from `mpn/generic/sbpi1_divappr_q.c`, GMP 6.2.1. pub_crate_test! {limbs_div_schoolbook_approx( qs: &mut [Limb], ns: &mut [Limb], mut ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len > 2); assert!(n_len >= d_len); let a = d_len - 1; let d_1 = ds[a]; assert!(d_1.get_highest_bit()); let b = d_len - 2; let d_0 = ds[b]; let q_len = n_len - d_len; assert!(qs.len() >= q_len); if q_len + 1 < d_len { ds = &ds[d_len - (q_len + 1)..]; } let d_len = ds.len(); let d_len_minus_1 = d_len - 1; let ns_hi = &mut ns[n_len - d_len..]; let highest_q = limbs_cmp_same_length(ns_hi, ds) >= Equal; if highest_q { limbs_sub_same_length_in_place_left(ns_hi, ds); } let mut n_1 = *ns.last().unwrap(); let mut q; let mut n_0; for i in (d_len_minus_1..q_len).rev() { let j = i + a; if n_1 == d_1 && ns[j] == d_0 { q = Limb::MAX; limbs_sub_mul_limb_same_length_in_place_left(&mut ns[j - d_len_minus_1..=j], ds, q); n_1 = ns[j]; // update n_1, last loop's value will now be invalid } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns[j], ns[j - 1], d_1, d_0, d_inv); (n_1, n_0) = n.split_in_half(); let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left( &mut ns[j - d_len_minus_1..j - 1], &ds[..d_len_minus_1 - 1], q, ); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns[j - 1] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left( &mut ns[j - d_len_minus_1..j], &ds[..d_len_minus_1], ) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } } qs[i] = q; } let mut flag = true; if d_len_minus_1 > 0 { for i in (1..d_len_minus_1).rev() { let j = i + a; if !flag || n_1 >= d_1 { q = Limb::MAX; let carry = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[b..=j], ds, q); if n_1 != carry { if flag && n_1 < carry { q.wrapping_sub_assign(1); limbs_slice_add_same_length_in_place_left(&mut ns[b..=j], ds); } else { flag = false; } } n_1 = ns[j]; } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns[j], ns[j - 1], d_1, d_0, d_inv); (n_1, n_0) = n.split_in_half(); let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[b..j - 1], &ds[..i], q); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns[j - 1] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(&mut ns[b..j], &ds[..=i]) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } } qs[i] = q; ds = &ds[1..]; } let ns = &mut ns[b..]; if !flag || n_1 >= d_1 { q = Limb::MAX; let carry = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[..2], &ds[..2], q); if flag && n_1 < carry { q.wrapping_sub_assign(1); limbs_slice_add_same_length_in_place_left(&mut ns[..2], &ds[..2]); } n_1 = ns[1]; } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns[1], ns[0], d_1, d_0, d_inv); (n_1, ns[0]) = n.split_in_half(); ns[1] = n_1; } qs[0] = q; } assert_eq!(ns[a], n_1); highest_q }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_divappr_q_n` from `mpn/generic/dcpi1_divappr_q.c`, GMP 6.2.1, // where `ns` here is `np + (n >> 1)`. fn limbs_div_divide_and_conquer_approx_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) -> bool { let d_len = ds.len(); let lo = d_len >> 1; // floor(d_len / 2) let hi = d_len - lo; // ceil(d_len / 2) assert!(ns.len() >= d_len + hi); let (ds_lo, ds_hi) = ds.split_at(lo); let qs_hi = &mut qs[lo..]; let ns_hi = &mut ns[lo..]; let mut highest_q = if hi < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs_hi, &mut ns_hi[..hi << 1], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs_hi, ns_hi, ds_hi, d_inv, scratch) }; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(hi, ds_lo.len())]; limbs_mul_greater_to_out(scratch, &qs_hi[..hi], ds_lo, &mut mul_scratch); let ns_lo = &mut ns[..d_len]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left( ns_lo, &scratch[..d_len], )); if highest_q && limbs_sub_same_length_in_place_left(&mut ns_lo[hi..], ds_lo) { carry += 1; } while carry != 0 { if limbs_sub_limb_in_place(&mut qs_hi[..hi], 1) { assert!(highest_q); highest_q = false; } if limbs_slice_add_same_length_in_place_left(ns_lo, ds) { carry -= 1; } } let ds_hi = &ds[hi..]; let ns_hi = &mut ns[hi - lo..]; let q_lo = if lo < DC_DIVAPPR_Q_THRESHOLD { limbs_div_schoolbook_approx(qs, &mut ns_hi[..lo << 1], ds_hi, d_inv) } else { limbs_div_divide_and_conquer_approx_helper(qs, &mut ns_hi[lo >> 1..], ds_hi, d_inv, scratch) }; if q_lo { for q in &mut qs[..lo] { *q = Limb::MAX; } } highest_q } // Recursive divide-and-conquer division, returning approximate quotient. // // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs`. Returns the most significant limb of the quotient; `true` means 1 and `false` means 0. The // quotient is either correct, or one too large. `ds` must have length greater than 2, `ns` must be // at least as long as `ds`, and the most significant bit of `ds` must be set. `d_inv` should be the // result of `limbs_two_limb_inverse_helper` applied to the two highest limbs of the denominator. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 6, `ns` is shorter than or the same length as `ds`, `qs` // has length less than `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest // bit set. // // This is equivalent to `mpn_dcpi1_divappr_q` from `mpn/generic/dcpi1_divappr_q.c`, GMP 6.2.1. pub_crate_test! {limbs_div_divide_and_conquer_approx( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 6); assert!(n_len > d_len); let a = d_len - 1; assert!(ds[a].get_highest_bit()); let b = d_len - 2; let q_len = n_len - d_len; let mut highest_q; if q_len >= d_len { let q_len_mod_d_len = { let mut m = (q_len + 1) % d_len; if m == 0 { m = d_len; } m }; let mut scratch = vec![0; d_len]; let offset = q_len - q_len_mod_d_len; let ns_hi = &mut ns[offset..]; let qs_hi = &mut qs[offset..]; let r = d_len - q_len_mod_d_len; let (ds_lo, ds_hi) = ds.split_at(r); // Perform the typically smaller block first. if q_len_mod_d_len == 1 { // Handle highest_q up front, for simplicity. let ns_2 = &mut ns_hi[1..=d_len]; highest_q = limbs_cmp_same_length(ns_2, ds) >= Equal; if highest_q { assert!(!limbs_sub_same_length_in_place_left(ns_2, ds)); } // A single iteration of schoolbook: One 3/2 division, followed by the bignum update and // adjustment. let n_2 = ns_hi[d_len]; let mut n_1 = ns_hi[a]; let mut n_0 = ns_hi[b]; let d_1 = ds[a]; let d_0 = ds[b]; assert!(n_2 < d_1 || (n_2 == d_1 && n_1 <= d_0)); let mut q; if n_2 == d_1 && n_1 == d_0 { q = Limb::MAX; assert_eq!( limbs_sub_mul_limb_same_length_in_place_left(&mut ns_hi[..d_len], ds, q), n_2 ); } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, d_inv); (n_1, n_0) = n.split_in_half(); // d_len > 2 let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns_hi[..b], &ds[..b], q); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns_hi[b] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(&mut ns_hi[..a], &ds[..a]) { n_1.wrapping_add_assign(1); } if q == 0 { fail_on_untested_path("limbs_div_divide_and_conquer_approx, q == 0"); assert!(highest_q); highest_q = false; } q.wrapping_sub_assign(1); } ns_hi[a] = n_1; } qs_hi[0] = q; } else { let ns_hi_2 = &mut ns_hi[r..]; highest_q = if q_len_mod_d_len == 2 { limbs_div_mod_by_two_limb_normalized( qs_hi, &mut ns_hi_2[..q_len_mod_d_len + 2], ds_hi, ) } else if q_len_mod_d_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs_hi, ns_hi_2, ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs_hi, ns_hi_2, ds_hi, d_inv, &mut scratch) }; let qs = &mut qs_hi[..q_len_mod_d_len]; if q_len_mod_d_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(qs.len(), ds_lo.len())]; limbs_mul_to_out(&mut scratch, qs, ds_lo, &mut mul_scratch); let mut carry = Limb::from(limbs_sub_same_length_in_place_left( &mut ns_hi[..d_len], &scratch[..d_len], )); if highest_q && limbs_sub_same_length_in_place_left( &mut ns_hi[q_len_mod_d_len..d_len], ds_lo, ) { carry += 1; } while carry != 0 { if limbs_sub_limb_in_place(qs, 1) { assert!(highest_q); highest_q = false; } if limbs_slice_add_same_length_in_place_left(&mut ns_hi[..d_len], ds) { carry -= 1; } } } } let mut offset = q_len.checked_sub(q_len_mod_d_len).unwrap(); while offset >= d_len { offset -= d_len; limbs_div_mod_divide_and_conquer_helper( &mut qs[offset..], &mut ns[offset..], ds, d_inv, &mut scratch, ); } // Since we pretended we'd need an extra quotient limb before, we now have made sure the // code above left just ds.len() - 1 = qs.len() quotient limbs to develop. Develop that plus // a guard limb. let ns = &mut ns[offset + (d_len >> 1) - d_len..]; let q_save = qs[offset]; limbs_div_divide_and_conquer_approx_helper(qs, ns, ds, d_inv, &mut scratch); slice_move_left(&mut qs[..=offset], 1); qs[offset] = q_save; } else { let offset = a - q_len; let q_len_plus_one = q_len + 1; let mut qs_2 = vec![0; q_len_plus_one]; let ds = &ds[offset..]; highest_q = if q_len < DC_DIVAPPR_Q_THRESHOLD && offset > 0 { limbs_div_schoolbook_approx(&mut qs_2, &mut ns[offset - 1..], ds, d_inv) } else { let mut scratch = vec![0; q_len_plus_one]; limbs_div_divide_and_conquer_approx_helper( &mut qs_2, &mut ns[offset + (q_len_plus_one >> 1) - 1..], ds, d_inv, &mut scratch, ) }; qs[..q_len].copy_from_slice(&qs_2[1..]); } highest_q }} // Compute Q = floor(N / D) + e. N has n_len limbs, D has d_len limbs and must be normalized, and Q // must have n_len - d_len limbs, 0 <= e <= 4. The requirement that Q has n_len - d_len limbs (and // not n_len - d_len + 1 limbs) was put in place in order to allow us to let N be unmodified during // the operation. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mu_divappr_q` from `mpn/generic/mu_divappr_q.c`, GMP 6.2.1. pub_crate_test! {limbs_div_barrett_approx( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { limbs_div_barrett_approx_helper(qs, ns, false, ds, scratch) }} fn limbs_div_barrett_approx_helper( qs: &mut [Limb], ns: &[Limb], mut ns_ghost_limb: bool, ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = if ns_ghost_limb { ns.len() + 1 } else { ns.len() }; let d_len = ds.len(); assert!(d_len > 1); assert!(n_len >= d_len); assert!(ds[d_len - 1].get_highest_bit()); let q_len = n_len - d_len; // If Q is smaller than D, truncate operands. let (ns, ds) = if q_len + 1 < d_len { let start = d_len - q_len - 1; // start > 0 if ns_ghost_limb { ns_ghost_limb = false; (&ns[start - 1..], &ds[start..]) } else { (&ns[start..], &ds[start..]) } } else { (ns, ds) }; let d_len_s = ds.len(); // Compute the inverse size. let i_len = limbs_div_barrett_approx_is_len(q_len, d_len_s); assert!(i_len <= d_len_s); let n = i_len + 1; let (is, scratch_2) = scratch.split_at_mut(n); // compute an approximate inverse on i_len + 1 limbs if d_len_s == i_len { scratch_2[1..n].copy_from_slice(&ds[..i_len]); scratch_2[0] = 1; let (scratch_2_lo, scratch_2_hi) = scratch_2.split_at_mut(n); limbs_invert_approx(is, scratch_2_lo, scratch_2_hi); slice_move_left(is, 1); } else if limbs_add_limb_to_out(scratch_2, &ds[d_len_s - n..], 1) { slice_set_zero(&mut is[..i_len]); } else { let (scratch_2_lo, scratch_2_hi) = scratch_2.split_at_mut(n); limbs_invert_approx(is, scratch_2_lo, scratch_2_hi); slice_move_left(is, 1); } let (is, scratch_hi) = scratch.split_at_mut(i_len); limbs_div_barrett_approx_preinverted(qs, ns, ns_ghost_limb, ds, is, scratch_hi) } // $T(n, d) = O(n \log d \log\log d)$ // // $M(n) = O(d \log d)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // This is equivalent to `mpn_preinv_mu_divappr_q` from `mpn/generic/mu_divappr_q.c`, GMP 6.2.1. fn limbs_div_barrett_approx_preinverted( qs: &mut [Limb], ns: &[Limb], ns_ghost_limb: bool, ds: &[Limb], mut is: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = if ns_ghost_limb { ns.len() + 1 } else { ns.len() }; let d_len = ds.len(); let mut i_len = is.len(); let mut q_len = n_len - d_len; let qs = &mut qs[..q_len]; if ns_ghost_limb { assert_ne!(q_len, 0); assert_ne!(i_len, 0); } let (ns_lo, ns_hi) = ns.split_at(if ns_ghost_limb { q_len - 1 } else { q_len }); let highest_q = limbs_cmp_same_length(ns_hi, ds) >= Equal; if q_len == 0 { return highest_q; } let (rs, scratch) = scratch.split_at_mut(d_len); if highest_q { limbs_sub_same_length_to_out(rs, ns_hi, ds); } else { rs.copy_from_slice(ns_hi); } let scratch_len = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { 0 } else { limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1) }; let mut carry = false; // This value is never used let mut n = d_len - i_len; let empty_slice: &[Limb] = &[]; let ns_iter: Box> = if ns_ghost_limb { Box::new(ns_lo.rchunks(i_len).chain(once(empty_slice))) } else { Box::new(ns_lo.rchunks(i_len)) }; let mut mul_scratch = vec![ 0; max( limbs_mul_same_length_to_out_scratch_len(q_len % i_len), limbs_mul_same_length_to_out_scratch_len(i_len) ) ]; for (ns, qs) in ns_iter.zip(qs.rchunks_mut(i_len)) { let chunk_len = qs.len(); if i_len != chunk_len { // last iteration is = &is[i_len - chunk_len..]; i_len = chunk_len; n = d_len - i_len; } let (rs_lo, rs_hi) = rs.split_at_mut(n); // Compute the next block of quotient limbs by multiplying the inverse I by the upper part // of the partial remainder R. limbs_mul_same_length_to_out(scratch, rs_hi, is, &mut mul_scratch); // i's highest bit is implicit carry = limbs_add_same_length_to_out(qs, &scratch[i_len..i_len << 1], rs_hi); assert!(!carry); q_len -= i_len; if q_len == 0 { break; } // Compute the product of the quotient block and the divisor D, to be subtracted from the // partial remainder combined with new limbs from the dividend N. We only really need the // low d_len limbs. if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; limbs_mul_greater_to_out(scratch, ds, qs, &mut mul_scratch); } else { limbs_div_barrett_large_product(scratch, ds, qs, rs_hi, scratch_len, i_len); } let mut r = rs_hi[0].wrapping_sub(scratch[d_len]); // Subtract the product from the partial remainder combined with new limbs from the dividend // N, generating a new partial remainder R. let scratch = &mut scratch[..d_len]; if n == 0 { // get next i_len limbs from N carry = limbs_sub_same_length_to_out(rs, ns, scratch); } else { // get next i_len limbs from N. let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); carry = limbs_sub_same_length_with_borrow_in_in_place_right( rs_lo, scratch_hi, limbs_sub_same_length_in_place_right(ns, scratch_lo), ); rs.copy_from_slice(scratch); } // Check the remainder R and adjust the quotient as needed. if carry { r.wrapping_sub_assign(1); } while r != 0 { // We loop 0 times with about 69% probability, 1 time with about 31% probability, and 2 // times with about 0.6% probability, if inverse is computed as recommended. assert!(!limbs_slice_add_limb_in_place(qs, 1)); carry = limbs_sub_same_length_in_place_left(rs, ds); if carry { r -= 1; } } if limbs_cmp_same_length(rs, ds) >= Equal { // This is executed with about 76% probability. assert!(!limbs_slice_add_limb_in_place(qs, 1)); carry = limbs_sub_same_length_in_place_left(rs, ds); } } if limbs_slice_add_limb_in_place(qs, 3) || carry { if highest_q { // Return a quotient of just 1-bits, with highest_q set. for q in &mut *qs { *q = Limb::MAX; } } true } else { highest_q } } // We distinguish 3 cases: // // - d_len < q_len: i_len = ceil(q_len / ceil(q_len / d_len)) // - d_len / 3 < q_len <= d_len: i_len = ceil(q_len / 2) // - q_len < d_len / 3: i_len = q_len // // In all cases we have i_len <= d_len. // // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$, where $n$ is `q_len`. // // This is equivalent to `mpn_mu_divappr_q_choose_in` from `mpn/generic/mu_divappr_q.c`, GMP 6.2.1, // where `k == 0`. #[allow(clippy::missing_const_for_fn)] fn limbs_div_barrett_approx_is_len(q_len: usize, d_len: usize) -> usize { if q_len > d_len { // Compute an inverse size that is a nice partition of the quotient. let b = q_len.saturating_sub(1) / d_len + 1; // ceil(q_len / d_len), number of blocks q_len.saturating_sub(1) / b + 1 // ceil(q_len / b) = ceil(q_len / ceil(q_len / d_len)) } else if 3 * q_len > d_len { q_len.saturating_sub(1) / 2 + 1 // b = 2 } else { q_len.saturating_sub(1) + 1 // b = 1 } } // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$, where $n$ is `n_len`. // // This is equivalent to `mpn_mu_divappr_q_itch` from `mpn/generic/mu_divappr_q.c`, GMP 6.2.1, where // `mua_k == 0`. pub_crate_test! {limbs_div_barrett_approx_scratch_len(n_len: usize, mut d_len: usize) -> usize { let qn = n_len - d_len; if qn + 1 < d_len { d_len = qn + 1; } let is_len = limbs_div_barrett_approx_is_len(qn, d_len); let local_len = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); let out_len = limbs_mul_mod_base_pow_n_minus_1_scratch_len(local_len, d_len, is_len); // 3 * is_len + 4 let inv_approx_len = limbs_invert_approx_scratch_len(is_len + 1) + is_len + 2; assert!(d_len + local_len + out_len >= inv_approx_len); is_len + d_len + local_len + out_len }} // TODO tune const DC_DIV_Q_THRESHOLD: usize = DC_DIVAPPR_Q_THRESHOLD; // TODO tune const MU_DIV_Q_THRESHOLD: usize = MU_DIVAPPR_Q_THRESHOLD; // TODO tune const MUPI_DIV_Q_THRESHOLD: usize = MUPI_DIVAPPR_Q_THRESHOLD; // TODO tune const MUPI_DIVAPPR_Q_THRESHOLD: usize = MUPI_DIV_QR_THRESHOLD; fn limbs_div_dc_condition(n_len: usize, d_len: usize) -> bool { let n_64 = n_len as f64; let d_64 = d_len as f64; d_len < MUPI_DIV_Q_THRESHOLD || n_len < MU_DIV_Q_THRESHOLD << 1 || fma!( ((MU_DIV_Q_THRESHOLD - MUPI_DIV_Q_THRESHOLD) << 1) as f64, d_64, MUPI_DIV_Q_THRESHOLD as f64 * n_64 ) > d_64 * n_64 } // Division when n_len >= 2 * d_len - FUDGE. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_crate_test! {limbs_div_to_out_unbalanced(qs: &mut [Limb], ns: &mut [Limb], ds: &mut [Limb]) { // ``` // |________________________| // |_______| // ``` let n_len = ns.len(); let d_len = ds.len(); let highest_d = ds[d_len - 1]; let bits = LeadingZeros::leading_zeros(highest_d); if bits == 0 { let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, ns, ds) } else if d_len < DC_DIV_Q_THRESHOLD || n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_schoolbook(qs, ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_divide_and_conquer(qs, ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(n_len, d_len)]; limbs_div_barrett(qs, ns, ds, &mut scratch) }; qs[n_len - d_len] = Limb::from(highest_q); } else { let mut scratch = vec![0; n_len + 1]; let carry = limbs_shl_to_out(&mut scratch, ns, bits); scratch[n_len] = carry; let new_n_len = if carry == 0 { n_len } else { n_len + 1 }; let new_ns = &mut scratch[..new_n_len]; limbs_slice_shl_in_place(ds, bits); let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, new_ns, ds) } else if d_len < DC_DIV_Q_THRESHOLD || new_n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(ds[d_len - 1], ds[d_len - 2]); limbs_div_schoolbook(qs, new_ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(ds[d_len - 1], ds[d_len - 2]); limbs_div_divide_and_conquer(qs, new_ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(new_n_len, d_len)]; limbs_div_barrett(qs, new_ns, ds, &mut scratch) }; if carry == 0 { qs[n_len - d_len] = Limb::from(highest_q); } else { assert!(!highest_q); } } }} pub_test! {limbs_div_q_dc_helper(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) -> bool { let n_len = ns.len(); let d_len = ds.len(); let highest_d = ds[d_len - 1]; if d_len < DC_DIV_Q_THRESHOLD || ns.len() - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_schoolbook(qs, ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_divide_and_conquer(qs, ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(n_len, d_len)]; limbs_div_barrett(qs, ns, ds, &mut scratch) } }} /// Division when n_len >= 2 * d_len - FUDGE. /// // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_div_to_out_unbalanced_val_ref(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) { // ``` // |________________________| // |_______| // ``` let n_len = ns.len(); let d_len = ds.len(); let highest_d = ds[d_len - 1]; let bits = LeadingZeros::leading_zeros(highest_d); if bits == 0 { let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, ns, ds) } else { limbs_div_q_dc_helper(qs, ns, ds) }; qs[n_len - d_len] = Limb::from(highest_q); } else { let mut scratch = vec![0; n_len + 1]; let carry = limbs_shl_to_out(&mut scratch, ns, bits); scratch[n_len] = carry; let new_n_len = if carry == 0 { n_len } else { n_len + 1 }; let new_ns = &mut scratch[..new_n_len]; let mut new_ds = vec![0; d_len]; limbs_shl_to_out(&mut new_ds, ds, bits); let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, new_ns, &new_ds) } else if d_len < DC_DIV_Q_THRESHOLD || new_n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(new_ds[d_len - 1], new_ds[d_len - 2]); limbs_div_schoolbook(qs, new_ns, &new_ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(new_ds[d_len - 1], new_ds[d_len - 2]); limbs_div_divide_and_conquer(qs, new_ns, &new_ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(new_n_len, d_len)]; limbs_div_barrett(qs, new_ns, &new_ds, &mut scratch) }; if carry == 0 { qs[n_len - d_len] = Limb::from(highest_q); } else { assert!(!highest_q); } } } // Division when n_len >= 2 * d_len - FUDGE. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_div_to_out_unbalanced_ref_val(qs: &mut [Limb], ns: &[Limb], ds: &mut [Limb]) { // ``` // |________________________| // |_______| // ``` let n_len = ns.len(); let d_len = ds.len(); let highest_d = ds[d_len - 1]; let bits = LeadingZeros::leading_zeros(highest_d); if bits == 0 { let highest_q = if d_len == 2 { let mut new_ns = ns.to_vec(); limbs_div_mod_by_two_limb_normalized(qs, &mut new_ns, ds) } else if d_len < DC_DIV_Q_THRESHOLD || n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); let mut new_ns = ns.to_vec(); limbs_div_schoolbook(qs, &mut new_ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_divide_and_conquer(qs, ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(n_len, d_len)]; limbs_div_barrett(qs, ns, ds, &mut scratch) }; qs[n_len - d_len] = Limb::from(highest_q); } else { let mut scratch = vec![0; n_len + 1]; let carry = limbs_shl_to_out(&mut scratch, ns, bits); scratch[n_len] = carry; let new_n_len = if carry == 0 { n_len } else { n_len + 1 }; let new_ns = &mut scratch[..new_n_len]; limbs_slice_shl_in_place(ds, bits); let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, new_ns, ds) } else if d_len < DC_DIV_Q_THRESHOLD || new_n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(ds[d_len - 1], ds[d_len - 2]); limbs_div_schoolbook(qs, new_ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(ds[d_len - 1], ds[d_len - 2]); limbs_div_divide_and_conquer(qs, new_ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(new_n_len, d_len)]; limbs_div_barrett(qs, new_ns, ds, &mut scratch) }; if carry == 0 { qs[n_len - d_len] = Limb::from(highest_q); } else { assert!(!highest_q); } } } // Division when n_len >= 2 * d_len - FUDGE. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_div_to_out_unbalanced_ref_ref(qs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { // ``` // |________________________| // |_______| // ``` let n_len = ns.len(); let d_len = ds.len(); let highest_d = ds[d_len - 1]; let bits = LeadingZeros::leading_zeros(highest_d); if bits == 0 { let highest_q = if d_len == 2 { let mut new_ns = ns.to_vec(); limbs_div_mod_by_two_limb_normalized(qs, &mut new_ns, ds) } else if d_len < DC_DIV_Q_THRESHOLD || n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); let mut new_ns = ns.to_vec(); limbs_div_schoolbook(qs, &mut new_ns, ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); limbs_div_divide_and_conquer(qs, ns, ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(n_len, d_len)]; limbs_div_barrett(qs, ns, ds, &mut scratch) }; qs[n_len - d_len] = Limb::from(highest_q); } else { let mut scratch = vec![0; n_len + 1]; let carry = limbs_shl_to_out(&mut scratch, ns, bits); scratch[n_len] = carry; let new_n_len = if carry == 0 { n_len } else { n_len + 1 }; let new_ns = &mut scratch[..new_n_len]; let mut new_ds = vec![0; d_len]; limbs_shl_to_out(&mut new_ds, ds, bits); let highest_q = if d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, new_ns, &new_ds) } else if d_len < DC_DIV_Q_THRESHOLD || new_n_len - d_len < DC_DIV_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(new_ds[d_len - 1], new_ds[d_len - 2]); limbs_div_schoolbook(qs, new_ns, &new_ds, d_inv) } else if limbs_div_dc_condition(n_len, d_len) { let d_inv = limbs_two_limb_inverse_helper(new_ds[d_len - 1], new_ds[d_len - 2]); limbs_div_divide_and_conquer(qs, new_ns, &new_ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_scratch_len(new_n_len, d_len)]; limbs_div_barrett(qs, new_ns, &new_ds, &mut scratch) }; if carry == 0 { qs[n_len - d_len] = Limb::from(highest_q); } else { assert!(!highest_q); } } } // Division when n_len < 2 * d_len - FUDGE. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_test! {limbs_div_to_out_balanced(qs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { // ``` // |________________________| // |_________________| // ``` let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len + 1; let q_len_plus_1 = q_len + 1; let mut scratch_2 = vec![0; q_len_plus_1]; let new_n_len = q_len + q_len_plus_1; let ns_tail = &ns[n_len.checked_sub(new_n_len).unwrap()..]; let highest_d = ds[d_len - 1]; let bits = LeadingZeros::leading_zeros(highest_d); if bits == 0 { let new_ds = &ds[d_len - q_len_plus_1..]; let highest_q = if q_len_plus_1 == 2 { let mut new_ns = ns_tail.to_vec(); limbs_div_mod_by_two_limb_normalized(&mut scratch_2, &mut new_ns, new_ds) } else if q_len_plus_1 < DC_DIVAPPR_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, new_ds[q_len - 1]); let mut new_ns = ns_tail.to_vec(); limbs_div_schoolbook_approx(&mut scratch_2, &mut new_ns, new_ds, d_inv) } else if q_len_plus_1 < MU_DIVAPPR_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(highest_d, new_ds[q_len - 1]); let mut new_ns = ns_tail.to_vec(); limbs_div_divide_and_conquer_approx(&mut scratch_2, &mut new_ns, new_ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(new_n_len, q_len_plus_1)]; limbs_div_barrett_approx(&mut scratch_2, ns_tail, new_ds, &mut scratch) }; scratch_2[q_len] = Limb::from(highest_q); } else { let mut scratch = vec![0; n_len + 1]; let carry = limbs_shl_to_out(&mut scratch, ns_tail, bits); scratch[new_n_len] = carry; let new_n_len = if carry == 0 { new_n_len } else { new_n_len + 1 }; let new_ns = &mut scratch[..new_n_len]; let mut new_ds = vec![0; q_len_plus_1]; limbs_shl_to_out(&mut new_ds, &ds[d_len - q_len_plus_1..], bits); new_ds[0] |= ds[d_len - q_len_plus_1 - 1] >> (Limb::WIDTH - bits); let highest_q = if q_len_plus_1 == 2 { limbs_div_mod_by_two_limb_normalized(&mut scratch_2, new_ns, &new_ds) } else if q_len_plus_1 < DC_DIVAPPR_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(new_ds[q_len], new_ds[q_len - 1]); limbs_div_schoolbook_approx(&mut scratch_2, new_ns, &new_ds, d_inv) } else if q_len_plus_1 < MU_DIVAPPR_Q_THRESHOLD { let d_inv = limbs_two_limb_inverse_helper(new_ds[q_len], new_ds[q_len - 1]); limbs_div_divide_and_conquer_approx(&mut scratch_2, new_ns, &new_ds, d_inv) } else { let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(new_n_len, q_len_plus_1)]; limbs_div_barrett_approx(&mut scratch_2, new_ns, &new_ds, &mut scratch) }; if carry == 0 { scratch_2[q_len] = Limb::from(highest_q); } else if highest_q { fail_on_untested_path("limbs_div_to_out_balanced, highest_q"); // This happens only when the quotient is close to B ^ n and one of the approximate // division functions returned B ^ n. for s in &mut scratch_2[..new_n_len - q_len_plus_1] { *s = Limb::MAX; } } } let (scratch_2_head, scratch_2_tail) = scratch_2.split_first().unwrap(); qs[..q_len].copy_from_slice(scratch_2_tail); if *scratch_2_head <= 4 { let mut rs = vec![0; n_len + 1]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), scratch_2_tail.len())]; limbs_mul_greater_to_out(&mut rs, ds, scratch_2_tail, &mut mul_scratch); let r_len = if rs[n_len] == 0 { n_len } else { n_len + 1 }; if r_len > n_len || limbs_cmp_same_length(ns, &rs[..n_len]) == Less { assert!(!limbs_sub_limb_in_place(qs, 1)); } } }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, returning the quotient. The quotient has `ns.len() - ds.len() + 1` // limbs. // // `ns` must be at least as long as `ds` and `ds` must have length at least 2 and its most // significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` has length less than 2, or the most-significant limb of // `ds` is zero. // // This is equivalent to `mpn_div_q` from `mpn/generic/div_q.c`, GMP 6.2.1, where `scratch` is // allocated internally and `qp` is returned. pub_test! {limbs_div(ns: &[Limb], ds: &[Limb]) -> Vec { let mut qs = vec![0; ns.len() - ds.len() + 1]; limbs_div_to_out_ref_ref(&mut qs, ns, ds); qs }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must have length at least 2 and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` has length less than 2, or the // most-significant limb of `ds` is zero. // // This is equivalent to `mpn_div_q` from `mpn/generic/div_q.c`, GMP 6.2.1, where `scratch` is // allocated internally and `np` and `dp` are consumed, saving some memory allocations. pub_crate_test! {limbs_div_to_out(qs: &mut [Limb], ns: &mut [Limb], ds: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len >= d_len); assert!(d_len > 1); assert_ne!(ds[d_len - 1], 0); assert!(FUDGE >= 2); let q_len = n_len - d_len + 1; // Quotient size, high limb might be zero if q_len + FUDGE >= d_len { limbs_div_to_out_unbalanced(qs, ns, ds); } else { limbs_div_to_out_balanced(qs, ns, ds); } }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must have length at least 2 and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` has length less than 2, or the // most-significant limb of `ds` is zero. // // This is equivalent to `mpn_div_q` from `mpn/generic/div_q.c`, GMP 6.2.1, where `scratch` is // allocated internally and `np` is consumed, saving some memory allocations. pub_test! {limbs_div_to_out_val_ref(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len >= d_len); assert!(d_len > 1); assert_ne!(ds[d_len - 1], 0); assert!(FUDGE >= 2); let q_len = n_len - d_len + 1; // Quotient size, high limb might be zero if q_len + FUDGE >= d_len { limbs_div_to_out_unbalanced_val_ref(qs, ns, ds); } else { limbs_div_to_out_balanced(qs, ns, ds); } }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must have length at least 2 and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` has length less than 2, or the // most-significant limb of `ds` is zero. // // This is equivalent to `mpn_div_q` from `mpn/generic/div_q.c`, GMP 6.2.1, where `scratch` is // allocated internally and `dp` is consumed, saving some memory allocations. pub_test! {limbs_div_to_out_ref_val(qs: &mut [Limb], ns: &[Limb], ds: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len >= d_len); assert!(d_len > 1); assert_ne!(ds[d_len - 1], 0); assert!(FUDGE >= 2); let q_len = n_len - d_len + 1; // Quotient size, high limb might be zero if q_len + FUDGE >= d_len { limbs_div_to_out_unbalanced_ref_val(qs, ns, ds); } else { limbs_div_to_out_balanced(qs, ns, ds); } }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must have length at least 2 and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` has length less than 2, or the // most-significant limb of `ds` is zero. // // This is equivalent to `mpn_div_q` from `mpn/generic/div_q.c`, GMP 6.2.1, where `scratch` is // allocated internally. pub_test! {limbs_div_to_out_ref_ref(qs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len >= d_len); assert!(d_len > 1); assert_ne!(ds[d_len - 1], 0); assert!(FUDGE >= 2); let q_len = n_len - d_len + 1; // Quotient size, high limb might be zero if q_len + FUDGE >= d_len { limbs_div_to_out_unbalanced_ref_ref(qs, ns, ds); } else { limbs_div_to_out_balanced(qs, ns, ds); } }} // Divides using the naive (schoolbook) algorithm. // // # Worst-case complexity // Constant time and additional memory. #[cfg(feature = "test_build")] fn limbs_div_in_place_naive(ns: &mut [Limb], d: Limb) { let limb = DoubleLimb::from(d); let mut upper = 0; for n in ns.iter_mut().rev() { let lower = *n; let (q, r) = DoubleLimb::join_halves(upper, lower).div_rem(limb); *n = q.lower_half(); upper = r.lower_half(); } } // This is equivalent to `mpn_pi1_bdiv_q_1` from `mpn/generic/bdiv_q_1.c`, GMP 6.2.1, where rp == // up. pub(crate) fn limbs_hensel_div_limb_in_place( ns: &mut [Limb], d: Limb, d_inv: Limb, shift: u64, ) -> bool { let n_len = ns.len(); assert_ne!(n_len, 0); assert_ne!(d, 0); let mut carry = 0; if shift == 0 { let (ns_head, ns_tail) = ns.split_first_mut().unwrap(); let mut l = ns_head.wrapping_mul(d_inv); *ns_head = l; let mut carry_2 = false; for n in ns_tail { let mut carry = Limb::x_mul_y_to_zz(l, d).0; if carry_2 { carry += 1; } (l, carry_2) = n.overflowing_sub(carry); l.wrapping_mul_assign(d_inv); *n = l; } carry_2 } else { for i in 0..n_len - 1 { let n = (ns[i] >> shift) | (ns[i + 1] << (Limb::WIDTH - shift)); let (mut l, carry_2) = n.overflowing_sub(carry); l.wrapping_mul_assign(d_inv); ns[i] = l; carry = Limb::x_mul_y_to_zz(l, d).0; if carry_2 { carry += 1; } } let ns_last = ns.last_mut().unwrap(); let (l, carry_2) = (*ns_last >> shift).overflowing_sub(carry); *ns_last = l.wrapping_mul(d_inv); carry_2 } } impl Natural { fn div_limb_ref(&self, other: Limb) -> Self { match (self, other) { (_, 0) => panic!("division by zero"), (n, 1) => n.clone(), (Self(Small(small)), other) => Self(Small(small / other)), (Self(Large(limbs)), other) => Self::from_owned_limbs_asc(limbs_div_limb(limbs, other)), } } #[cfg(feature = "test_build")] #[inline] pub fn div_limb_naive(mut self, other: Limb) -> Self { self.div_assign_limb_naive(other); self } fn div_assign_limb(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => panic!("division by zero"), (_, 1) => {} (Self(Small(small)), other) => *small /= other, (Self(Large(limbs)), other) => { limbs_div_limb_in_place(limbs, other); self.trim(); } } } #[cfg(feature = "test_build")] pub fn div_assign_limb_naive(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => panic!("division by zero"), (_, 1) => {} (Self(Small(small)), other) => { *small /= other; } (Self(Large(limbs)), other) => { limbs_div_in_place_naive(limbs, other); self.trim(); } } } } impl Div for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value. The quotient is rounded /// towards negative infinity. The quotient and remainder (which is not computed) satisfy $x = /// qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32) / Natural::from(10u32), 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000").unwrap() /// / Natural::from_str("1234567890987").unwrap(), /// 810000006723u64 /// ); /// ``` #[inline] fn div(mut self, other: Self) -> Self { self /= other; self } } impl<'a> Div<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32) / &Natural::from(10u32), 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000").unwrap() /// / &Natural::from_str("1234567890987").unwrap(), /// 810000006723u64 /// ); /// ``` #[inline] fn div(mut self, other: &'a Self) -> Self { self /= other; self } } impl Div for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Natural::from(23u32) / Natural::from(10u32), 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// &Natural::from_str("1000000000000000000000000").unwrap() /// / Natural::from_str("1234567890987").unwrap(), /// 810000006723u64 /// ); /// ``` fn div(self, mut other: Natural) -> Natural { match (self, &mut other) { (_, &mut Natural::ZERO) => panic!("division by zero"), (x, y) if x == y => Natural::ONE, (n, &mut Natural::ONE) => n.clone(), (n, &mut Natural(Small(d))) => n.div_limb_ref(d), (Natural(Small(_)), _) => Natural::ZERO, (Natural(Large(ns)), Natural(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { Natural::ZERO } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out_ref_val(&mut qs, ns, ds); Natural::from_owned_limbs_asc(qs) } } } } } impl Div<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference. The quotient is /// rounded towards negative infinity. The quotient and remainder (which is not computed) /// satisfy $x = qy + r$ and $0 \leq r < y$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Natural::from(23u32) / &Natural::from(10u32), 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// &Natural::from_str("1000000000000000000000000").unwrap() /// / &Natural::from_str("1234567890987").unwrap(), /// 810000006723u64 /// ); /// ``` fn div(self, other: &Natural) -> Natural { match (self, other) { (_, &Natural::ZERO) => panic!("division by zero"), (x, y) if x == y => Natural::ONE, (n, &Natural::ONE) => n.clone(), (n, &Natural(Small(d))) => n.div_limb_ref(d), (Natural(Small(_)), _) => Natural::ZERO, (Natural(Large(ns)), Natural(Large(ds))) => { if ns.len() < ds.len() { Natural::ZERO } else { Natural::from_owned_limbs_asc(limbs_div(ns, ds)) } } } } } impl DivAssign for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. The quotient is rounded towards negative infinity. The quotient /// and remainder (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x /= Natural::from(10u32); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x /= Natural::from_str("1234567890987").unwrap(); /// assert_eq!(x, 810000006723u64); /// ``` fn div_assign(&mut self, other: Self) { match (&mut *self, other) { (_, Self::ZERO) => panic!("division by zero"), (x, y) if *x == y => { *self = Self::ONE; } (_, Self::ONE) => {} (n, Self(Small(d))) => n.div_assign_limb(d), (Self(Small(_)), _) => *self = Self::ZERO, (Self(Large(ns)), Self(Large(mut ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { *self = Self::ZERO; } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out(&mut qs, ns, &mut ds); swap(&mut qs, ns); self.trim(); } } } } } impl<'a> DivAssign<&'a Self> for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. The quotient is rounded towards negative infinity. The /// quotient and remainder (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x /= &Natural::from(10u32); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x /= &Natural::from_str("1234567890987").unwrap(); /// assert_eq!(x, 810000006723u64); /// ``` fn div_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, &Self::ZERO) => panic!("division by zero"), (x, y) if x == y => { *self = Self::ONE; } (_, &Self::ONE) => {} (n, &Self(Small(d))) => n.div_assign_limb(d), (Self(Small(_)), _) => *self = Self::ZERO, (Self(Large(ns)), Self(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { *self = Self::ZERO; } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out_val_ref(&mut qs, ns, ds); swap(&mut qs, ns); self.trim(); } } } } } impl CheckedDiv for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value. The quotient is rounded /// towards negative infinity. The quotient and remainder (which is not computed) satisfy $x = /// qy + r$ and $0 \leq r < y$. Returns `None` when the second [`Natural`] is zero, `Some` /// otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .checked_div(Natural::from(10u32)) /// .to_debug_string(), /// "Some(2)" /// ); /// assert_eq!(Natural::ONE.checked_div(Natural::ZERO), None); /// ``` #[inline] fn checked_div(self, mut other: Self) -> Option { match (self, &mut other) { (_, &mut Self::ZERO) => None, (x, y) if x == *y => Some(Self::ONE), (n, &mut Self::ONE) => Some(n), (mut n, &mut Self(Small(d))) => { n.div_assign_limb(d); Some(n) } (Self(Small(_)), _) => Some(Self::ZERO), (Self(Large(mut ns)), Self(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); Some(if ns_len < ds_len { Self::ZERO } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out(&mut qs, &mut ns, ds); Self::from_owned_limbs_asc(qs) }) } } } } impl<'a> CheckedDiv<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the /// second [`Natural`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .checked_div(&Natural::from(10u32)) /// .to_debug_string(), /// "Some(2)" /// ); /// assert_eq!(Natural::ONE.checked_div(&Natural::ZERO), None); /// ``` #[inline] fn checked_div(self, other: &'a Self) -> Option { match (self, other) { (_, &Self::ZERO) => None, (x, y) if x == *y => Some(Self::ONE), (n, &Self::ONE) => Some(n.clone()), (mut n, &Self(Small(d))) => { n.div_assign_limb(d); Some(n) } (Self(Small(_)), _) => Some(Self::ZERO), (Self(Large(mut ns)), Self(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); Some(if ns_len < ds_len { Self::ZERO } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out_val_ref(&mut qs, &mut ns, ds); Self::from_owned_limbs_asc(qs) }) } } } } impl CheckedDiv for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value. The quotient is rounded towards negative infinity. The quotient and remainder /// (which is not computed) satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the /// second [`Natural`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .checked_div(Natural::from(10u32)) /// .to_debug_string(), /// "Some(2)" /// ); /// assert_eq!((&Natural::ONE).checked_div(Natural::ZERO), None); /// ``` fn checked_div(self, mut other: Natural) -> Option { match (self, &mut other) { (_, &mut Natural::ZERO) => None, (x, y) if x == y => Some(Natural::ONE), (n, &mut Natural::ONE) => Some(n.clone()), (n, &mut Natural(Small(d))) => Some(n.div_limb_ref(d)), (Natural(Small(_)), _) => Some(Natural::ZERO), (Natural(Large(ns)), Natural(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); Some(if ns_len < ds_len { Natural::ZERO } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_to_out_ref_val(&mut qs, ns, ds); Natural::from_owned_limbs_asc(qs) }) } } } } impl CheckedDiv<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference. The quotient is /// rounded towards negative infinity. The quotient and remainder (which is not computed) /// satisfy $x = qy + r$ and $0 \leq r < y$. Returns `None` when the second [`Natural`] is zero, /// `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \left \lfloor \frac{x}{y} \right \rfloor \right ) & /// \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .checked_div(&Natural::from(10u32)) /// .to_debug_string(), /// "Some(2)" /// ); /// assert_eq!((&Natural::ONE).checked_div(&Natural::ZERO), None); /// ``` fn checked_div(self, other: &Natural) -> Option { match (self, other) { (_, &Natural::ZERO) => None, (x, y) if x == y => Some(Natural::ONE), (n, &Natural::ONE) => Some(n.clone()), (n, &Natural(Small(d))) => Some(n.div_limb_ref(d)), (Natural(Small(_)), _) => Some(Natural::ZERO), (Natural(Large(ns)), Natural(Large(ds))) => Some(if ns.len() < ds.len() { Natural::ZERO } else { Natural::from_owned_limbs_asc(limbs_div(ns, ds)) }), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/div_exact.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_bdiv_q`, `mpn_bdiv_q_itch`, `mpn_binvert`, `mpn_binvert_itch`, `mpn_divexact`, // `mpn_mu_bdiv_q`, `mpn_mu_bdiv_q_itch`, `mpn_dcpi1_bdiv_qr`, `mpn_dcpi1_bdiv_qr_n`, // `mpn_dcpi1_bdiv_qr_n_itch`, and `mpn_sbpi1_bdiv_q` contributed to the GNU project by // Torbjörn Granlund. // // `mpn_dcpi1_bdiv_q`, `mpn_dcpi1_bdiv_q_n`, `mpn_dcpi1_bdiv_q_n_itch`, `mpn_dcpi1_bdiv_qr`, // `mpn_dcpi1_bdiv_qr_n`, `mpn_dcpi1_bdiv_qr_n_itch`, and `mpn_sbpi1_bdiv_qr` contributed to // the GNU project by Niels Möller and Torbjörn Granlund. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div::{ limbs_div_divisor_of_limb_max_with_carry_in_place, limbs_div_divisor_of_limb_max_with_carry_to_out, }; use crate::natural::arithmetic::div_mod::MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD; use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length; use crate::natural::arithmetic::mul::mul_mod::{ limbs_mul_mod_base_pow_n_minus_1, limbs_mul_mod_base_pow_n_minus_1_next_size, limbs_mul_mod_base_pow_n_minus_1_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::neg::limbs_neg_in_place; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_to_out, limbs_sub_same_length_to_out_with_overlap, limbs_sub_same_length_with_borrow_in_to_out, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{ BINV_NEWTON_THRESHOLD, DC_BDIV_Q_THRESHOLD, DC_BDIV_QR_THRESHOLD, DoubleLimb, Limb, MU_BDIV_Q_THRESHOLD, MU_BDIV_QR_THRESHOLD, }; use alloc::vec::Vec; use core::cmp::{Ordering::*, max, min}; use core::mem::swap; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ DivExact, DivExactAssign, Parity, ShrRound, ShrRoundAssign, WrappingAddAssign, WrappingMulAssign, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, HasHalf, SplitInHalf}; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::{slice_leading_zeros, slice_set_zero, slice_test_zero}; const INVERT_LIMB_TABLE_LOG_SIZE: u64 = 7; const INVERT_LIMB_TABLE_SIZE: usize = 1 << INVERT_LIMB_TABLE_LOG_SIZE; // The entry at index `i` is the multiplicative inverse of `2 * i + 1 mod 2 ^ 8`. const INVERT_LIMB_TABLE: [u8; INVERT_LIMB_TABLE_SIZE] = [ 0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef, 0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf, 0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf, 0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf, 0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf, 0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f, 0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f, 0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f, 0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f, 0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f, 0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f, 0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f, 0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f, 0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f, 0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f, 0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff, ]; // Tests that `INVERT_LIMB_TABLE` is correct. #[cfg(feature = "test_build")] pub fn test_invert_limb_table() { for (i, &inv) in INVERT_LIMB_TABLE.iter().enumerate() { let value = (u8::exact_from(i) << 1) + 1; let product = value.wrapping_mul(inv); assert_eq!( product, 1, "INVERT_LIMB_TABLE gives incorrect inverse, {inv}, for value {value}", ); } } // Finds the inverse of a `Limb` mod `2 ^ Limb::WIDTH`; given x, returns y such that x * y ≡ 1 mod // `2 ^ Limb::WIDTH`. This inverse only exists for odd `Limb`s, so `x` must be odd. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `x` is even. // // This is equivalent to `binvert_limb` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_modular_invert_limb(x: T) -> T where usize: ExactFrom, { assert!(x.odd()); let index = (x >> 1u32).mod_power_of_2(INVERT_LIMB_TABLE_LOG_SIZE); let mut inv = T::from(INVERT_LIMB_TABLE[usize::exact_from(index)]); inv = (inv << 1u32).wrapping_sub((inv * inv).wrapping_mul(x)); inv = (inv << 1u32).wrapping_sub(inv.wrapping_mul(inv).wrapping_mul(x)); if T::WIDTH != u32::WIDTH { assert_eq!(T::WIDTH, u64::WIDTH); inv = (inv << 1u32).wrapping_sub(inv.wrapping_mul(inv).wrapping_mul(x)); } inv }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs of the `Natural` divided by a `Limb`. The divisor limb cannot be zero and the limb // slice must be nonempty. The `Natural` must be exactly divisible by the `Limb`. If it isn't, the // behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1, where the result // is returned. pub_test! {limbs_div_exact_limb_no_special_3(ns: &[Limb], d: Limb) -> Vec { let mut q = vec![0; ns.len()]; limbs_div_exact_limb_to_out::(&mut q, ns, d); q }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns`, `ns` is empty, or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1. pub_test! {limbs_div_exact_limb_to_out_no_special_3< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], ns: &[T], d: T, ) where usize: ExactFrom, { assert_ne!(d, T::ZERO); let len = ns.len(); assert_ne!(len, 0); let out = &mut out[..len]; let (ns_head, ns_tail) = ns.split_first().unwrap(); if d.even() { let shift = TrailingZeros::trailing_zeros(d); let shift_complement = T::WIDTH - shift; let shifted_d = d >> shift; let d_inv = limbs_modular_invert_limb(shifted_d); let (out_last, out_init) = out.split_last_mut().unwrap(); let mut upper_half = T::ZERO; let mut previous_n = *ns_head; for (out_q, n) in out_init.iter_mut().zip(ns_tail.iter()) { let shifted_n = (previous_n >> shift) | (*n << shift_complement); previous_n = *n; let (diff, carry) = shifted_n.overflowing_sub(upper_half); let q = diff.wrapping_mul(d_inv); *out_q = q; upper_half = (DT::from(q) * DT::from(shifted_d)).upper_half(); if carry { upper_half += T::ONE; } } *out_last = (previous_n >> shift) .wrapping_sub(upper_half) .wrapping_mul(d_inv); } else { let d_inv = limbs_modular_invert_limb(d); let (out_head, out_tail) = out.split_first_mut().unwrap(); let mut q = ns_head.wrapping_mul(d_inv); *out_head = q; let mut previous_carry = false; for (out_q, n) in out_tail.iter_mut().zip(ns_tail.iter()) { let mut upper_half = (DT::from(q) * DT::from(d)).upper_half(); if previous_carry { upper_half += T::ONE; } let diff; (diff, previous_carry) = n.overflowing_sub(upper_half); q = diff.wrapping_mul(d_inv); *out_q = q; } } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1, where `dst == // src`. pub_test! {limbs_div_exact_limb_in_place_no_special_3(ns: &mut [Limb], d: Limb) { assert_ne!(d, 0); let len = ns.len(); assert_ne!(len, 0); if d.even() { let shift = TrailingZeros::trailing_zeros(d); let shift_complement = Limb::WIDTH - shift; let shifted_d = d >> shift; let d_inv = limbs_modular_invert_limb(shifted_d); let shifted_d = DoubleLimb::from(shifted_d); let mut upper_half = 0; let mut previous_n = ns[0]; for i in 1..len { let n = ns[i]; let shifted_n = (previous_n >> shift) | (n << shift_complement); previous_n = n; let (diff, carry) = shifted_n.overflowing_sub(upper_half); let q = diff.wrapping_mul(d_inv); ns[i - 1] = q; upper_half = (DoubleLimb::from(q) * shifted_d).upper_half(); if carry { upper_half += 1; } } ns[len - 1] = (previous_n >> shift) .wrapping_sub(upper_half) .wrapping_mul(d_inv); } else { let d_inv = limbs_modular_invert_limb(d); let d = DoubleLimb::from(d); let (ns_head, ns_tail) = ns.split_first_mut().unwrap(); let mut q = ns_head.wrapping_mul(d_inv); *ns_head = q; let mut previous_carry = false; for n in &mut *ns_tail { let mut upper_half = (DoubleLimb::from(q) * d).upper_half(); if previous_carry { upper_half += 1; } let diff; (diff, previous_carry) = n.overflowing_sub(upper_half); q = diff.wrapping_mul(d_inv); *n = q; } } }} #[cfg(feature = "test_build")] pub(crate) const MAX_OVER_3: Limb = Limb::MAX / 3; #[cfg(not(feature = "test_build"))] const MAX_OVER_3: Limb = Limb::MAX / 3; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs of the `Natural` divided by 3. The limb slice must be nonempty. The `Natural` must // be exactly divisible by 3. If it isn't, the behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty. // // This is equivalent to `mpn_divexact_by3c` from `mpn/generic/diveby3.c`, GMP 6.2.1, with // `DIVEXACT_BY3_METHOD == 0` and no carry-in, where the result is returned. pub_test! {limbs_div_exact_3(ns: &[Limb]) -> Vec { let mut q = vec![0; ns.len()]; limbs_div_exact_3_to_out::(&mut q, ns); q }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and 3 to an output slice. The output slice must be at // least as long as the input slice. The input limb slice must be nonempty. The `Natural` must be // exactly divisible by 3. If it isn't, the behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns` or if `ns` is empty. // // This is equivalent to `mpn_divexact_by3c` from `mpn/generic/diveby3.c`, GMP 6.2.1, with // `DIVEXACT_BY3_METHOD == 0`, no carry-in, and no return value. pub_test! {limbs_div_exact_3_to_out< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], ns: &[T], ) { let (out_last, out_init) = out[..ns.len()].split_last_mut().unwrap(); let (ns_last, ns_init) = ns.split_last().unwrap(); let max_over_3 = T::MAX / T::from(3u8); let q = limbs_div_divisor_of_limb_max_with_carry_to_out::( out_init, ns_init, max_over_3, T::ZERO, ); let lower = (DT::from(*ns_last) * DT::from(max_over_3)).lower_half(); *out_last = q.wrapping_sub(lower); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and 3 to the input slice. The input limb slice must be // nonempty. The `Natural` must be exactly divisible by 3. If it isn't, the behavior of this // function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty. // // This is equivalent to `mpn_divexact_by3c` from `mpn/generic/diveby3.c`, GMP 6.2.1, with // `DIVEXACT_BY3_METHOD == 0`, no carry-in, and no return value, where `rp == up`. pub_crate_test! {limbs_div_exact_3_in_place(ns: &mut [Limb]) { let (ns_last, ns_init) = ns.split_last_mut().unwrap(); let q = limbs_div_divisor_of_limb_max_with_carry_in_place(ns_init, MAX_OVER_3, 0); let lower = (DoubleLimb::from(*ns_last) * DoubleLimb::from(MAX_OVER_3)).lower_half(); *ns_last = q.wrapping_sub(lower); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to an output slice. The output slice must be // at least as long as the input slice. The divisor limb cannot be zero and the input limb slice // must be nonempty. The `Natural` must be exactly divisible by the `Limb`. If it isn't, the // behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns`, `ns` is empty, or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1. pub_crate_test! {limbs_div_exact_limb_to_out< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], ns: &[T], d: T, ) where usize: ExactFrom, { if d == T::from(3u8) { limbs_div_exact_3_to_out::(out, ns); } else { limbs_div_exact_limb_to_out_no_special_3::(out, ns, d); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs of the `Natural` divided by a `Limb`. The divisor limb cannot be zero and the limb // slice must be nonempty. The `Natural` must be exactly divisible by the `Limb`. If it isn't, the // behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1, where the result // is returned. pub_test! {limbs_div_exact_limb(ns: &[Limb], d: Limb) -> Vec { if d == 3 { limbs_div_exact_3(ns) } else { limbs_div_exact_limb_no_special_3(ns, d) } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to the input slice. The divisor limb cannot // be zero and the input limb slice must be nonempty. The `Natural` must be exactly divisible by the // `Limb`. If it isn't, the behavior of this function is undefined. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is empty or if `d` is zero. // // This is equivalent to `mpn_divexact_1` from `mpn/generic/dive_1.c`, GMP 6.2.1, where `dest == // src`. pub_crate_test! {limbs_div_exact_limb_in_place(ns: &mut [Limb], d: Limb) { if d == 3 { limbs_div_exact_3_in_place(ns); } else { limbs_div_exact_limb_in_place_no_special_3(ns, d); } }} // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$. // // This is equivalent to `mpn_binvert_itch` from `mpn/generic/binvert.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_invert_scratch_len(n: usize) -> usize { let itch_local = limbs_mul_mod_base_pow_n_minus_1_next_size(n); let itch_out = limbs_mul_mod_base_pow_n_minus_1_scratch_len( itch_local, n, n.shr_round(1, Ceiling).0, ); itch_local + itch_out }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. pub_test! {limbs_modular_invert_small( size: usize, is: &mut [Limb], scratch: &mut [Limb], ds: &[Limb], d_inv: Limb, ) { if size < DC_BDIV_Q_THRESHOLD { limbs_modular_div_schoolbook(is, scratch, ds, d_inv); limbs_neg_in_place(is); } else { limbs_modular_div_divide_and_conquer(is, scratch, ds, d_inv); } }} // Finds the inverse of a slice `Limb` mod `2 ^ (ds.len() * Limb::WIDTH)`; given x, returns y such // that x * y ≡ 1 mod `2 ^ (ds.len() * Limb::WIDTH)`. This inverse only exists for odd x, so the // least-significant limb of `ds` must be odd. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // # Panics // Panics if `is` is shorter than `ds`, if `ds` is empty, or if `scratch` is too short. // // This is equivalent to `mpn_binvert` from `mpn/generic/binvert.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_invert(is: &mut [Limb], ds: &[Limb], scratch: &mut [Limb]) { let d_len = ds.len(); // Compute the computation precisions from highest to lowest, leaving the basecase size in // `size`. let mut size = d_len; let mut sizes = Vec::new(); while size >= BINV_NEWTON_THRESHOLD { sizes.push(size); size.shr_round_assign(1, Ceiling); } // Compute a base value of `size` limbs. let scratch_lo = &mut scratch[..size]; let ds_lo = &ds[..size]; slice_set_zero(scratch_lo); scratch_lo[0] = 1; let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_invert_small(size, is, scratch_lo, ds_lo, d_inv); let mut previous_size = size; // Use Newton iterations to get the desired precision. for &size in sizes.iter().rev() { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(size); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); let (is_lo, is_hi) = is.split_at_mut(previous_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, &ds[..size], is_lo, scratch_hi); limbs_sub_limb_to_out( scratch_hi, &scratch_lo[..previous_size - (mul_size - size)], 1, ); let diff = size - previous_size; limbs_mul_low_same_length(is_hi, &is_lo[..diff], &scratch[previous_size..size]); limbs_twos_complement_in_place(&mut is_hi[..diff]); previous_size = size; } }} // Computes a binary quotient of size `q_len` = `ns.len()` - `ds.len()`. D must be odd. `d_inv` is // (-D) ^ -1 mod 2 ^ `Limb::WIDTH`, or `limbs_modular_invert_limb(ds[0]).wrapping_neg()`. // // Output: // ``` // Q = N / D mod 2 ^ (`Limb::WIDTH` * `q_len`) // R = (N - Q * D) / 2 ^ (`Limb::WIDTH` * `q_len`) // ``` // // Stores the `ds.len()` least-significant limbs of R at `&np[q_len..]` and returns the borrow from // the subtraction N - Q * D. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_sbpi1_bdiv_qr` from `mpn/generic/sbpi1_bdiv_qr.c`, GMP 6.2.1. // Investigate changes from 6.1.2? pub_crate_test! {limbs_modular_div_mod_schoolbook( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len > d_len); assert!(ds[0].odd()); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let mut highest_r = false; // To complete the negation, this value is added to the quotient. let mut lowest_q = true; let mut q_len_s = q_len; while q_len_s > d_len { let q_diff = q_len - q_len_s; for i in q_diff..n_len - q_len_s { let ns = &mut ns[i..i + d_len]; let q = d_inv.wrapping_mul(ns[0]); ns[0] = limbs_slice_add_mul_limb_same_length_in_place_left(ns, ds, q); qs[i] = !q; } let (np_lo, np_hi) = ns[q_diff..].split_at_mut(d_len); if limbs_slice_add_greater_in_place_left(&mut np_hi[..q_len_s], np_lo) { highest_r = true; } if lowest_q && !limbs_slice_add_limb_in_place(&mut qs[q_diff..n_len - q_len_s], 1) { lowest_q = false; } q_len_s -= d_len; } let q_len_s = q_len_s; let q_diff = q_len - q_len_s; for i in q_diff..q_len { let ns = &mut ns[i..i + d_len]; let q = d_inv.wrapping_mul(ns[0]); ns[0] = limbs_slice_add_mul_limb_same_length_in_place_left(ns, ds, q); qs[i] = !q; } let (np_lo, np_hi) = ns[q_diff..].split_at_mut(d_len); if limbs_slice_add_same_length_in_place_left(&mut np_hi[..q_len_s], &np_lo[..q_len_s]) { assert!(!highest_r); highest_r = true; } if lowest_q && limbs_slice_add_limb_in_place(&mut qs[q_diff..], 1) { // quotient is zero assert!(!highest_r); false } else { let carry = limbs_sub_same_length_in_place_left(&mut ns[q_len..], ds); assert!(carry || !highest_r); carry != highest_r } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. fn limbs_modular_div_mod_helper( qs: &mut [Limb], ns: &mut [Limb], len: usize, ds_lo: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) -> bool { if len < DC_BDIV_QR_THRESHOLD { limbs_modular_div_mod_schoolbook(qs, &mut ns[..len << 1], ds_lo, d_inv) } else { limbs_modular_div_mod_divide_and_conquer_helper(qs, ns, ds_lo, d_inv, scratch) } } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_bdiv_qr_n` from `mpn/generic/dcpi1_bdiv_qr.c`, GMP 6.2.1. fn limbs_modular_div_mod_divide_and_conquer_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) -> bool { let n = ds.len(); let ns = &mut ns[..n << 1]; let scratch = &mut scratch[..n]; let lo = n >> 1; // floor(n / 2) let hi = n - lo; // ceil(n / 2) let (ds_lo, ds_hi) = ds.split_at(lo); let carry = limbs_modular_div_mod_helper(qs, ns, lo, ds_lo, d_inv, scratch); let (qs_lo, qs_hi) = qs.split_at_mut(lo); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds_hi.len(), qs_lo.len())]; limbs_mul_greater_to_out(scratch, ds_hi, qs_lo, &mut mul_scratch); if carry { assert!(!limbs_slice_add_limb_in_place(&mut scratch[lo..], 1)); } let ns = &mut ns[lo..]; let highest_r = limbs_sub_greater_in_place_left(ns, scratch); let (ds_lo, ds_hi) = ds.split_at(hi); let carry = limbs_modular_div_mod_helper(qs_hi, ns, hi, ds_lo, d_inv, scratch); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(hi, ds_hi.len())]; limbs_mul_greater_to_out(scratch, &qs_hi[..hi], ds_hi, &mut mul_scratch); if carry { assert!(!limbs_slice_add_limb_in_place(&mut scratch[hi..], 1)); } if limbs_sub_same_length_in_place_left(&mut ns[hi..], scratch) { assert!(!highest_r); true } else { highest_r } } // Computes a binary quotient of size `q_len` = `ns.len()` - `ds.len()` and a remainder of size // `rs.len()`. D must be odd. `d_inv` is (-D) ^ -1 mod 2 ^ `Limb::WIDTH`, or // `limbs_modular_invert_limb(ds[0]).wrapping_neg()`. // // Output: // ``` // Q = N / D mod 2 ^ (`Limb::WIDTH` * `q_len`) // R = (N - Q * D) / 2 ^ (`Limb::WIDTH` * `q_len`) // ``` // // Stores the `ds.len()` least-significant limbs of R at `&np[q_len..]` and returns the borrow from // the subtraction N - Q * D. // // # Worst-case complexity // $T(n, d) = O(n (\log d)^2 \log \log d)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_bdiv_qr` from `mpn/generic/dcpi1_bdiv_qr.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_div_mod_divide_and_conquer( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 2); // to adhere to limbs_modular_div_mod_schoolbook's limits assert!(n_len > d_len); // to adhere to limbs_modular_div_mod_schoolbook's limits assert!(ds[0].odd()); let mut scratch = vec![0; d_len]; let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let mut borrow = false; let mut carry; if q_len > d_len { let q_len_mod_d_len = { let mut m = q_len % d_len; if m == 0 { m = d_len; } m }; let (ds_lo, ds_hi) = ds.split_at(q_len_mod_d_len); // Perform the typically smaller block first. carry = limbs_modular_div_mod_helper(qs, ns, q_len_mod_d_len, ds_lo, d_inv, &mut scratch); if q_len_mod_d_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ds_hi.len(), q_len_mod_d_len)]; limbs_mul_to_out( &mut scratch, ds_hi, &qs[..q_len_mod_d_len], &mut mul_scratch, ); if carry { assert!(!limbs_slice_add_limb_in_place( &mut scratch[q_len_mod_d_len..], 1 )); } borrow = limbs_sub_greater_in_place_left(&mut ns[q_len_mod_d_len..], &scratch[..d_len]); carry = false; } let mut q_len_s = q_len - q_len_mod_d_len; // q_len_s is a multiple of d_len while q_len_s != 0 { let q_diff = q_len - q_len_s; let ns = &mut ns[q_diff..]; if carry && limbs_sub_limb_in_place(&mut ns[d_len..], 1) { assert!(!borrow); borrow = true; } carry = limbs_modular_div_mod_divide_and_conquer_helper( &mut qs[q_diff..], ns, ds, d_inv, &mut scratch, ); q_len_s -= d_len; } } else { let (ds_lo, ds_hi) = ds.split_at(q_len); carry = limbs_modular_div_mod_helper(qs, ns, q_len, ds_lo, d_inv, &mut scratch); if q_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ds_hi.len(), qs.len())]; limbs_mul_to_out(&mut scratch, ds_hi, qs, &mut mul_scratch); if carry { assert!(!limbs_slice_add_limb_in_place(&mut scratch[q_len..], 1)); } borrow = limbs_sub_greater_in_place_left(&mut ns[q_len..], &scratch[..d_len]); carry = false; } } if carry { assert!(!borrow); borrow = true; } borrow }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_dcpi1_bdiv_qr_n_itch` from `mpn/generic/dcpi1_bdiv_qr.c`, GMP 6.2.1. pub_const_test! {limbs_modular_div_mod_divide_and_conquer_helper_scratch_len(n: usize) -> usize { n }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_mu_bdiv_qr_itch` from `mpn/generic/mu_bdiv_qr.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_div_mod_barrett_scratch_len(n_len: usize, d_len: usize) -> usize { assert!(DC_BDIV_Q_THRESHOLD < MU_BDIV_Q_THRESHOLD); let q_len = n_len - d_len; let i_len = if q_len > d_len { let blocks = (q_len - 1) / d_len + 1; // ceil(q_len / d_len), number of blocks (q_len - 1) / blocks + 1 // ceil(q_len / ceil(q_len / d_len)) } else { q_len - (q_len >> 1) }; let (mul_len_1, mul_len_2) = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { (d_len + i_len, 0) } else { let t_len = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); ( t_len, limbs_mul_mod_base_pow_n_minus_1_scratch_len(t_len, d_len, i_len), ) }; let modular_invert_scratch_len = limbs_modular_invert_scratch_len(i_len); let scratch_len = mul_len_1 + mul_len_2; i_len + max(scratch_len, modular_invert_scratch_len) }} // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_modular_div_mod_barrett_unbalanced( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let rs = &mut rs[..d_len]; // ``` // |_______________________| dividend // |________| divisor // ``` // // Compute an inverse size that is a nice partition of the quotient. let blocks = (q_len - 1) / d_len + 1; // ceil(q_len / d_len), number of blocks let i_len = (q_len - 1) / blocks + 1; // ceil(q_len / b) = ceil(q_len / ceil(q_len / d_len)) let (is, scratch) = scratch.split_at_mut(i_len); limbs_modular_invert(is, &ds[..i_len], scratch); rs.copy_from_slice(&ns[..d_len]); let mut carry = false; let mut q_len_s = q_len; while q_len_s > i_len { let qs = &mut qs[q_len - q_len_s..]; let qs = &mut qs[..i_len]; let ns = &ns[n_len - q_len_s..]; limbs_mul_low_same_length(qs, &rs[..i_len], is); if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; limbs_mul_greater_to_out(scratch, ds, qs, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs, scratch_hi); if let Some(wrapped_len) = (d_len + i_len).checked_sub(mul_size) { if wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &rs[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } else { fail_on_untested_path( "limbs_modular_div_mod_barrett_unbalanced, wrapped_len is None", ); } } let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); if d_len != i_len { let (rp_lo, rp_hi) = rs.split_at_mut(i_len); if limbs_sub_same_length_to_out(rp_lo, &rp_hi[..d_len - i_len], &scratch_lo[i_len..]) { if carry { assert!(!limbs_slice_add_limb_in_place(scratch_hi, 1)); } else { carry = true; } } } carry = limbs_sub_same_length_with_borrow_in_to_out( &mut rs[d_len - i_len..], &ns[..i_len], &scratch_hi[..i_len], carry, ); q_len_s -= i_len; } // high q_len quotient limbs let qs = &mut qs[q_len - q_len_s..]; limbs_mul_low_same_length(qs, &rs[..q_len_s], &is[..q_len_s]); if q_len_s < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; limbs_mul_greater_to_out(scratch, ds, qs, &mut mul_scratch); } else { let tn = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(tn); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, tn, ds, qs, scratch_hi); if let Some(wrapped_len) = (d_len + q_len_s).checked_sub(tn) && wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(tn); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &rs[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); if d_len != q_len_s && limbs_sub_same_length_to_out_with_overlap(rs, &scratch_lo[q_len_s..]) { if carry { assert!(!limbs_slice_add_limb_in_place(scratch_hi, 1)); } else { carry = true; } } limbs_sub_same_length_with_borrow_in_to_out( &mut rs[d_len - q_len_s..], &ns[n_len - q_len_s..], &scratch_hi[..q_len_s], carry, ) } // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_modular_div_mod_barrett_balanced( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let rs = &mut rs[..d_len]; // ``` // |_______________________| dividend // |________________| divisor // ``` // // Compute a half-sized inverse. let i_len = q_len - (q_len >> 1); let (is, scratch) = scratch.split_at_mut(i_len); let (qs_lo, qs_hi) = qs.split_at_mut(i_len); limbs_modular_invert(is, &ds[..i_len], scratch); limbs_mul_low_same_length(qs_lo, &ns[..i_len], is); // low i_len quotient limbs if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs_lo.len())]; limbs_mul_greater_to_out(scratch, ds, qs_lo, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs_lo, scratch_hi); if let Some(wrapped_len) = (d_len + i_len).checked_sub(mul_size) && wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &ns[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } let q_len_s = q_len - i_len; let (ns_lo, ns_hi) = ns.split_at(i_len + d_len); let mut carry = limbs_sub_same_length_to_out(rs, &ns_lo[i_len..], &scratch[i_len..i_len + d_len]); // high q_len quotient limbs limbs_mul_low_same_length(qs_hi, &rs[..q_len_s], &is[..q_len_s]); if q_len_s < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs_hi.len())]; limbs_mul_greater_to_out(scratch, ds, qs_hi, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs_hi, scratch_hi); if let Some(wrapped_len) = (d_len + q_len_s).checked_sub(mul_size) && wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &rs[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); if limbs_sub_same_length_to_out_with_overlap(rs, &scratch_lo[q_len_s..]) { if carry { assert!(!limbs_slice_add_limb_in_place(scratch_hi, 1)); } else { carry = true; } } limbs_sub_same_length_with_borrow_in_to_out( &mut rs[d_len - q_len_s..], ns_hi, &scratch_hi[..q_len_s], carry, ) } // Computes a binary quotient of size `q_len` = `ns.len()` - `ds.len()` and a remainder of size // `ds.len()`. D must be odd. // // Output: // ``` // Q = N / D mod 2 ^ (`Limb::WIDTH` * `q_len`) // R = (N - Q * D) / 2 ^ (`Limb::WIDTH` * `q_len`) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 2, `ns.len()` is less than `ds.len()` + 2, `qs` has length // less than `ns.len()` - `ds.len()`, `rs` is shorter than `ds`, `scratch` is to short, or the last // limb of `ds` is even. // // This is equivalent to `mpn_mu_bdiv_qr` from `mpn/generic/mu_bdiv_qr.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_div_mod_barrett( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 2); assert!(n_len >= d_len + 2); if n_len > d_len << 1 { limbs_modular_div_mod_barrett_unbalanced(qs, rs, ns, ds, scratch) } else { limbs_modular_div_mod_barrett_balanced(qs, rs, ns, ds, scratch) } }} // Computes Q = -N/D mod B^un, destroys N. // // D must be odd. d_inv is (-D)^-1 mod B. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_sbpi1_bdiv_q` from `mpn/generic/sbpi1_bdiv_q.c`, GMP 6.2.1. pub_crate_test! {limbs_modular_div_schoolbook( mut qs: &mut [Limb], mut ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert!(ds[0].odd()); if n_len > d_len { let mut carry = 0; let limit = n_len - d_len - 1; for i in 0..limit { let (ns_lo, ns_hi) = ns[i..].split_at_mut(d_len); let q = d_inv.wrapping_mul(ns_lo[0]); let mut hi = limbs_slice_add_mul_limb_same_length_in_place_left(ns_lo, ds, q); assert_eq!(ns_lo[0], 0); qs[i] = q; let mut carry_b; (hi, carry_b) = hi.overflowing_add(carry); carry = Limb::from(carry_b); (hi, carry_b) = hi.overflowing_add(ns_hi[0]); if carry_b { carry += 1; } ns_hi[0] = hi; } ns = &mut ns[limit..]; qs = &mut qs[limit..]; let q = d_inv.wrapping_mul(ns[0]); let (ns_lo, ns_hi) = ns.split_at_mut(d_len); let hi = carry.wrapping_add(limbs_slice_add_mul_limb_same_length_in_place_left( ns_lo, ds, q, )); qs[0] = q; ns_hi[0].wrapping_add_assign(hi); ns = &mut ns[1..]; qs = &mut qs[1..]; } let ns = &mut ns[..d_len]; for i in 0..d_len - 1 { let ns_hi = &mut ns[i..]; let q = d_inv.wrapping_mul(ns_hi[0]); limbs_slice_add_mul_limb_same_length_in_place_left(ns_hi, &ds[..d_len - i], q); qs[i] = q; } let last_index = d_len - 1; qs[last_index] = d_inv.wrapping_mul(ns[last_index]); }} // This is equivalent to `mpn_sbpi1_bdiv_q` from `mpn/generic/sbpi1_bdiv_q.c`, GMP 6.2.1, where qp // == up. pub fn limbs_modular_div_schoolbook_in_place(mut ns: &mut [Limb], ds: &[Limb], d_inv: Limb) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert!(ds[0].odd()); if n_len > d_len { let mut carry = 0; let limit = n_len - d_len - 1; for i in 0..limit { let (ns_lo, ns_hi) = ns[i..].split_at_mut(d_len); let q = d_inv.wrapping_mul(ns_lo[0]); let mut hi = limbs_slice_add_mul_limb_same_length_in_place_left(ns_lo, ds, q); assert_eq!(ns_lo[0], 0); ns_lo[0] = q; let mut carry_b; (hi, carry_b) = hi.overflowing_add(carry); carry = Limb::from(carry_b); (hi, carry_b) = hi.overflowing_add(ns_hi[0]); if carry_b { carry += 1; } ns_hi[0] = hi; } ns = &mut ns[limit..]; let q = d_inv.wrapping_mul(ns[0]); let (ns_lo, ns_hi) = ns.split_at_mut(d_len); let hi = carry + limbs_slice_add_mul_limb_same_length_in_place_left(ns_lo, ds, q); ns_lo[0] = q; ns_hi[0].wrapping_add_assign(hi); ns = &mut ns[1..]; } let ns = &mut ns[..d_len]; for i in 0..d_len - 1 { let ns_hi = &mut ns[i..]; let q = d_inv.wrapping_mul(ns_hi[0]); limbs_slice_add_mul_limb_same_length_in_place_left(ns_hi, &ds[..d_len - i], q); ns_hi[0] = q; } let last_index = d_len - 1; ns[last_index].wrapping_mul_assign(d_inv); } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_dcpi1_bdiv_q_n_itch` from `mpn/generic/dcpi1_bdiv_q.c`, GMP 6.2.1. pub_const_test! {limbs_modular_div_divide_and_conquer_helper_scratch_len(n: usize) -> usize { n }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_bdiv_q_n` from `mpn/generic/dcpi1_bdiv_q.c`, GMP 6.2.1. // Investigate changes from 6.1.2? fn limbs_modular_div_divide_and_conquer_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) { let n = ds.len(); let mut n_rem = n; while n_rem >= DC_BDIV_Q_THRESHOLD { let m = n - n_rem; let lo = n_rem >> 1; // floor(n / 2) let hi = n_rem - lo; // ceil(n / 2) let qs = &mut qs[m..]; let ns = &mut ns[m..]; let carry_1 = limbs_modular_div_mod_divide_and_conquer_helper(qs, ns, &ds[..lo], d_inv, scratch); let qs = &qs[..lo]; limbs_mul_low_same_length(scratch, qs, &ds[hi..n_rem]); limbs_sub_same_length_in_place_left(&mut ns[hi..n_rem], &scratch[..lo]); if lo < hi { let carry_2 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[lo..lo << 1], qs, ds[lo]); let n_limb = &mut ns[n_rem - 1]; n_limb.wrapping_sub_assign(carry_2); if carry_1 { n_limb.wrapping_sub_assign(1); } } n_rem = hi; } let m = n - n_rem; limbs_modular_div_schoolbook(&mut qs[m..], &mut ns[m..n], &ds[..n_rem], d_inv); limbs_neg_in_place(&mut qs[m..]); } // Computes Q = N / D mod 2 ^ (`Limb::WIDTH` * `ns.len()`), destroying N. D must be odd. `d_inv` is // (-D) ^ -1 mod 2 ^ `Limb::WIDTH`, or `limbs_modular_invert_limb(ds[0]).wrapping_neg()`. // // # Worst-case complexity // $T(n, d) = O(n (\log d)^2 \log \log d)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_bdiv_q` from `mpn/generic/dcpi1_bdiv_q.c`, GMP 6.2.1. // Investigate changes from 6.1.2? pub_test! {limbs_modular_div_divide_and_conquer( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 2); assert!(n_len >= d_len); assert!(ds[0].odd()); if n_len > d_len { let n_len_mod_d_len = { let mut m = n_len % d_len; if m == 0 { m = d_len; } m }; let mut scratch = vec![0; d_len]; // Perform the typically smaller block first. let (ds_lo, ds_hi) = ds.split_at(n_len_mod_d_len); let mut carry = if n_len_mod_d_len < DC_BDIV_QR_THRESHOLD { limbs_modular_div_mod_schoolbook(qs, &mut ns[..n_len_mod_d_len << 1], ds_lo, d_inv) } else { limbs_modular_div_mod_divide_and_conquer_helper(qs, ns, ds_lo, d_inv, &mut scratch) }; if n_len_mod_d_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ds_hi.len(), n_len_mod_d_len)]; limbs_mul_to_out( &mut scratch, ds_hi, &qs[..n_len_mod_d_len], &mut mul_scratch, ); if carry { assert!(!limbs_slice_add_limb_in_place( &mut scratch[n_len_mod_d_len..], 1 )); } limbs_sub_greater_in_place_left(&mut ns[n_len_mod_d_len..], &scratch[..d_len]); carry = false; } let mut m = n_len_mod_d_len; let diff = n_len - d_len; while m != diff { if carry { limbs_sub_limb_in_place(&mut ns[m + d_len..], 1); } carry = limbs_modular_div_mod_divide_and_conquer_helper( &mut qs[m..], &mut ns[m..], ds, d_inv, &mut scratch, ); m += d_len; } limbs_modular_div_divide_and_conquer_helper( &mut qs[diff..], &mut ns[diff..], ds, d_inv, &mut scratch, ); } else if n_len < DC_BDIV_Q_THRESHOLD { limbs_modular_div_schoolbook(qs, ns, ds, d_inv); limbs_neg_in_place(qs); } else { let mut scratch = vec![0; n_len]; limbs_modular_div_divide_and_conquer_helper(qs, ns, ds, d_inv, &mut scratch); } }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_mu_bdiv_q_itch` from `mpn/generic/mu_bdiv_q.c`, GMP 6.2.1. pub_test! {limbs_modular_div_barrett_scratch_len(n_len: usize, d_len: usize) -> usize { assert!(DC_BDIV_Q_THRESHOLD < MU_BDIV_Q_THRESHOLD); let i_len; let mul_len = if n_len > d_len { let blocks = (n_len - 1) / d_len + 1; // ceil(q_len / d_len), number of blocks i_len = (n_len - 1) / blocks + 1; // ceil(q_len / b) = ceil(q_len / ceil(q_len / d_len)) let (mul_len_1, mul_len_2) = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { (d_len + i_len, 0) } else { let mul_len_1 = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); ( mul_len_1, limbs_mul_mod_base_pow_n_minus_1_scratch_len(mul_len_1, d_len, i_len), ) }; d_len + mul_len_1 + mul_len_2 } else { i_len = n_len - (n_len >> 1); let (mul_len_1, mul_len_2) = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { (n_len + i_len, 0) } else { let mul_len_1 = limbs_mul_mod_base_pow_n_minus_1_next_size(n_len); ( mul_len_1, limbs_mul_mod_base_pow_n_minus_1_scratch_len(mul_len_1, n_len, i_len), ) }; mul_len_1 + mul_len_2 }; let invert_len = limbs_modular_invert_scratch_len(i_len); i_len + max(mul_len, invert_len) }} // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_modular_div_barrett_greater( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); let d_len = ds.len(); // ``` // |_______________________| dividend // |________| divisor // ``` // // Compute an inverse size that is a nice partition of the quotient. let blocks = (n_len - 1) / d_len + 1; // ceil(q_len / d_len), number of blocks let i_len = (n_len - 1) / blocks + 1; // ceil(q_len / b) = ceil(q_len / ceil(q_len / d_len)) let (is, rs) = scratch.split_at_mut(i_len); limbs_modular_invert(is, &ds[..i_len], rs); let mut carry = false; let (rs, scratch) = rs.split_at_mut(d_len); rs.copy_from_slice(&ns[..d_len]); limbs_mul_low_same_length(qs, &rs[..i_len], is); let mut n_len_s = n_len; let limit = i_len << 1; while n_len_s > limit { let diff = n_len - n_len_s; let (qs_lo, qs_hi) = qs[diff..].split_at_mut(i_len); if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs_lo.len())]; limbs_mul_greater_to_out(scratch, ds, qs_lo, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs_lo, scratch_hi); if let Some(wrapped_len) = (d_len + i_len).checked_sub(mul_size) { if wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &rs[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } else { fail_on_untested_path("limbs_modular_div_mod_barrett_greater, wrapped_len is None"); } } let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); if d_len != i_len { let (rs_lo, rs_hi) = rs.split_at_mut(i_len); if limbs_sub_same_length_to_out(rs_lo, &rs_hi[..d_len - i_len], &scratch_lo[i_len..]) { if carry { assert!(!limbs_slice_add_limb_in_place(scratch_hi, 1)); } else { carry = true; } } } let ns = &ns[diff + d_len..]; carry = limbs_sub_same_length_with_borrow_in_to_out( &mut rs[d_len - i_len..], &ns[..i_len], &scratch_hi[..i_len], carry, ); limbs_mul_low_same_length(qs_hi, &rs[..i_len], is); n_len_s -= i_len; } let n_len_s = n_len_s; let diff = n_len - n_len_s; let (qs_lo, qs_hi) = qs[diff..].split_at_mut(i_len); // Generate last q_len limbs. if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs_lo.len())]; limbs_mul_greater_to_out(scratch, ds, qs_lo, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs_lo, scratch_hi); if let Some(wrapped_len) = (d_len + i_len).checked_sub(mul_size) && wrapped_len != 0 { let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); if limbs_sub_same_length_to_out( scratch_hi, &scratch_lo[..wrapped_len], &rs[..wrapped_len], ) { assert!(!limbs_sub_limb_in_place(&mut scratch[wrapped_len..], 1)); } } } if d_len != i_len { let (rs_lo, rs_hi) = rs.split_at_mut(i_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); if limbs_sub_same_length_to_out(rs_lo, rs_hi, &scratch_lo[i_len..]) { if carry { assert!(!limbs_slice_add_limb_in_place(scratch_hi, 1)); } else { carry = true; } } } limbs_sub_same_length_with_borrow_in_to_out( &mut rs[d_len - i_len..], &ns[diff + d_len..], &scratch[d_len..n_len_s], carry, ); let limit = n_len_s - i_len; limbs_mul_low_same_length(qs_hi, &rs[..limit], &is[..limit]); } // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_modular_div_barrett_same_length( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); // ``` // |________________| dividend // |________________| divisor // ``` // // Compute a half-sized inverse. let i_len = n_len - (n_len >> 1); let (is, scratch) = scratch.split_at_mut(i_len); limbs_modular_invert(is, &ds[..i_len], scratch); let (ns_lo, ns_hi) = ns.split_at(i_len); limbs_mul_low_same_length(qs, ns_lo, is); // low i_len quotient limbs let (qs_lo, qs_hi) = qs.split_at_mut(i_len); if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs_lo.len())]; limbs_mul_greater_to_out(scratch, ds, qs_lo, &mut mul_scratch); } else { let mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(n_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(mul_size); limbs_mul_mod_base_pow_n_minus_1(scratch_lo, mul_size, ds, qs_lo, scratch_hi); if let Some(wrapped_len) = (n_len + i_len).checked_sub(mul_size) { let (scratch_lo, scratch_hi) = scratch.split_at_mut(wrapped_len); if wrapped_len != 0 && limbs_cmp_same_length(scratch_lo, &ns[..wrapped_len]) == Less { assert!(!limbs_sub_limb_in_place(scratch_hi, 1)); } } else { fail_on_untested_path("limbs_modular_div_mod_barrett_same_length, wrapped_len is None"); } } let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); let diff = n_len - i_len; limbs_sub_same_length_to_out(scratch_lo, ns_hi, &scratch_hi[..diff]); // high n_len - i_len quotient limbs limbs_mul_low_same_length(qs_hi, &scratch[..diff], &is[..diff]); } // Computes Q = N / D mod 2 ^ (`Limb::WIDTH` * `ns.len()`). D must be odd. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mu_bdiv_q` from `mpn/generic/mu_bdiv_q.c`, GMP 6.2.1. pub_test! {limbs_modular_div_barrett( qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb] ) { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 2); assert!(n_len >= d_len); if n_len > d_len { limbs_modular_div_barrett_greater(qs, ns, ds, scratch); } else { limbs_modular_div_barrett_same_length(qs, ns, ds, scratch); } }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_bdiv_q_itch` from `mpn/generic/bdiv_q.c`, GMP 6.2.1, where nothing is // allocated for inputs that are too small for Barrett division. Investigate changes from 6.1.2? pub_test! {limbs_modular_div_scratch_len(n_len: usize, d_len: usize) -> usize { if d_len < MU_BDIV_Q_THRESHOLD { 0 } else { limbs_modular_div_barrett_scratch_len(n_len, d_len) } }} // Computes Q = N / D mod 2 ^ (`Limb::WIDTH` * `ns.len()`), taking N by value. D must be odd. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_bdiv_q` from `mpn/generic/bdiv_q.c`, GMP 6.2.1. Investigate changes // from 6.1.2? pub_test! {limbs_modular_div(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], scratch: &mut [Limb]) { let d_len = ds.len(); if d_len < DC_BDIV_Q_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(qs, ns, ds, d_inv); limbs_neg_in_place(qs); } else if d_len < MU_BDIV_Q_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(qs, ns, ds, d_inv); } else { limbs_modular_div_barrett(qs, ns, ds, scratch); } }} // This is equivalent to `mpn_bdiv_qr` from `mpn/generic/bdiv_qr.c` GMP 6.3.0. pub(crate) fn limbs_modular_div_mod( qp: &mut [Limb], // Quotient output rp: &mut [Limb], // Remainder output np: &[Limb], // Dividend dp: &[Limb], // Divisor tp: &mut [Limb], // Scratch workspace ) -> bool { let nn = np.len(); let dn = dp.len(); assert!(nn > dn, "Dividend must be larger than divisor"); let rh: bool; if dn < DC_BDIV_QR_THRESHOLD || (nn - dn) < DC_BDIV_QR_THRESHOLD { // **Small divisor case: Use simple binary division** // // Copy dividend to scratch space for in-place computation tp[..nn].copy_from_slice(np); // Compute modular inverse: di = -D[0]^(-1) mod B let mut di = limbs_modular_invert_limb(dp[0]); di = di.wrapping_neg(); // Negate the inverse // Perform simple binary division with precomputed inverse rh = limbs_modular_div_mod_schoolbook(qp, &mut tp[..nn], dp, di); // Extract remainder from high limbs of temp buffer rp.copy_from_slice(&tp[nn - dn..nn]); } else if dn < MU_BDIV_QR_THRESHOLD { // **Medium divisor case: Use divide-and-conquer binary division** // // Copy dividend to scratch space tp[..nn].copy_from_slice(np); // Compute modular inverse let mut di = limbs_modular_invert_limb(dp[0]); di = di.wrapping_neg(); // Perform divide-and-conquer binary division rh = limbs_modular_div_mod_divide_and_conquer(qp, &mut tp[..nn], dp, di); // Extract remainder rp.copy_from_slice(&tp[nn - dn..nn]); } else { // **Large divisor case: Use μ-division algorithm** rh = limbs_modular_div_mod_barrett(qp, rp, np, dp, tp); } rh } // This is equivalent to `mpn_bdiv_qr_itch` from `mpn/generic/bdiv_qr.c`, GMP 6.3.0. pub(crate) fn limbs_modular_div_mod_scratch_len(nn: usize, dn: usize) -> usize { if dn < MU_BDIV_QR_THRESHOLD { return nn; } limbs_modular_div_mod_barrett_scratch_len(nn, dn) } // This is equivalent to `mpn_bdiv_qr_wrap` from `mpn/generic/remove.c`, GMP 6.3.0. pub(crate) fn limbs_modular_div_mod_wrap( qp: &mut [Limb], // Quotient output rp: &mut [Limb], // Remainder output np: &[Limb], // Dividend dp: &[Limb], // Divisor ) { // Calculate required scratch space let scratch_size = limbs_modular_div_mod_scratch_len(np.len(), dp.len()); let mut scratch = vec![0; scratch_size]; // Perform the division limbs_modular_div_mod(qp, rp, np, dp, &mut scratch); } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_bdiv_q_itch` from `mpn/generic/bdiv_q.c`, GMP 6.2.1. pub_test! {limbs_modular_div_ref_scratch_len(n_len: usize, d_len: usize) -> usize { if d_len < MU_BDIV_Q_THRESHOLD { n_len } else { limbs_modular_div_barrett_scratch_len(n_len, d_len) } }} // Computes Q = N / D mod 2 ^ (`Limb::WIDTH` * `ns.len()`), taking N by reference. D must be odd. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_bdiv_q` from `mpn/generic/bdiv_q.c`, GMP 6.2.1. pub_test! {limbs_modular_div_ref(qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); if d_len < DC_BDIV_Q_THRESHOLD { let scratch = &mut scratch[..n_len]; scratch.copy_from_slice(ns); let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(qs, scratch, ds, d_inv); limbs_neg_in_place(qs); } else if d_len < MU_BDIV_Q_THRESHOLD { let scratch = &mut scratch[..n_len]; scratch.copy_from_slice(ns); let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(qs, scratch, ds, d_inv); } else { limbs_modular_div_barrett(qs, ns, ds, scratch); } }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, returning the quotient. The quotient has `ns.len() - ds.len() + 1` // limbs. // // `ns` must be exactly divisible by `ds`! If it isn't, the function will panic or return a // meaningless result. // // `ns` must be at least as long as `ds` and `ds` must have length at least 2 and its most // significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` is empty, or the most-significant limb of `ds` is zero. // // This is equivalent to `mpn_divexact` from `mpn/generic/divexact.c`, GMP 6.2.1, where `scratch` is // allocated internally and `qp` is returned. pub_test! {limbs_div_exact(ns: &[Limb], ds: &[Limb]) -> Vec { let mut qs = vec![0; ns.len() - ds.len() + 1]; limbs_div_exact_to_out_ref_ref(&mut qs, ns, ds); qs }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // `ns` and `ds` are taken by value. // // `ns` must be exactly divisible by `ds`! If it isn't, the function will panic or return a // meaningless result. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must be nonempty and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` is empty, or the most-significant // limb of `ds` is zero. // // This is equivalent to `mpn_divexact` from `mpn/generic/divexact.c`, GMP 6.2.1, except that `np` // and `dp` are consumed. pub_crate_test! {limbs_div_exact_to_out(qs: &mut [Limb], ns: &mut [Limb], ds: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(ds[d_len - 1], 0); let leading_zeros = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at_mut(leading_zeros); assert!(slice_test_zero(ns_lo), "division not exact"); let ds = &mut ds[leading_zeros..]; let n_len = ns.len(); let d_len = ds.len(); if d_len == 1 { limbs_div_exact_limb_to_out::(qs, ns, ds[0]); return; } let q_len = n_len - d_len + 1; let shift = TrailingZeros::trailing_zeros(ds[0]); if shift != 0 { let q_len_plus_1 = q_len + 1; let ds_limit_len = if d_len > q_len { q_len_plus_1 } else { d_len }; limbs_slice_shr_in_place(&mut ds[..ds_limit_len], shift); // Since we have excluded d_len == 1, we have n_len > q_len, and we need to shift one limb // beyond q_len. limbs_slice_shr_in_place(&mut ns[..q_len_plus_1], shift); } let d_len = min(d_len, q_len); let mut scratch = vec![0; limbs_modular_div_scratch_len(q_len, d_len)]; limbs_modular_div(qs, &mut ns[..q_len], &ds[..d_len], &mut scratch); }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // `ns` is taken by value and `ds` by reference. // // `ns` must be exactly divisible by `ds`! If it isn't, the function will panic or return a // meaningless result. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must be nonempty and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` is empty, or the most-significant // limb of `ds` is zero. // // This is equivalent to `mpn_divexact` from `mpn/generic/divexact.c`, GMP 6.2.1, except that `np` // is consumed. pub_test! {limbs_div_exact_to_out_val_ref(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(ds[d_len - 1], 0); let leading_zeros = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at_mut(leading_zeros); assert!(slice_test_zero(ns_lo), "division not exact"); let mut ds_scratch; let mut ds = &ds[leading_zeros..]; let n_len = ns.len(); let d_len = ds.len(); if d_len == 1 { limbs_div_exact_limb_to_out::(qs, ns, ds[0]); return; } let q_len = n_len - d_len + 1; let shift = TrailingZeros::trailing_zeros(ds[0]); if shift != 0 { let q_len_plus_1 = q_len + 1; let ds_scratch_len = if d_len > q_len { q_len_plus_1 } else { d_len }; ds_scratch = vec![0; ds_scratch_len]; limbs_shr_to_out(&mut ds_scratch, &ds[..ds_scratch_len], shift); ds = &ds_scratch; // Since we have excluded d_len == 1, we have n_len > q_len, and we need to shift one limb // beyond q_len. limbs_slice_shr_in_place(&mut ns[..q_len_plus_1], shift); } let d_len = min(d_len, q_len); let mut scratch = vec![0; limbs_modular_div_scratch_len(q_len, d_len)]; limbs_modular_div(qs, &mut ns[..q_len], &ds[..d_len], &mut scratch); }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // `ns` is taken by reference and `ds` by value. // // `ns` must be exactly divisible by `ds`! If it isn't, the function will panic or return a // meaningless result. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must be nonempty and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` is empty, or the most-significant // limb of `ds` is zero. // // This is equivalent to `mpn_divexact` from `mpn/generic/divexact.c`, GMP 6.2.1, except that `dp` // is consumed. pub_test! {limbs_div_exact_to_out_ref_val(qs: &mut [Limb], ns: &[Limb], ds: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(ds[d_len - 1], 0); let leading_zeros = slice_leading_zeros(ds); let (ns_lo, ns_hi) = ns.split_at(leading_zeros); assert!(slice_test_zero(ns_lo), "division not exact"); let mut ns_scratch; let mut ns = ns_hi; let ds = &mut ds[leading_zeros..]; let n_len = ns.len(); let d_len = ds.len(); if d_len == 1 { limbs_div_exact_limb_to_out::(qs, ns, ds[0]); return; } let q_len = n_len - d_len + 1; let shift = TrailingZeros::trailing_zeros(ds[0]); if shift != 0 { let q_len_plus_1 = q_len + 1; let ds_limit_len = if d_len > q_len { q_len_plus_1 } else { d_len }; limbs_slice_shr_in_place(&mut ds[..ds_limit_len], shift); // Since we have excluded d_len == 1, we have n_len > q_len, and we need to shift one limb // beyond q_len. ns_scratch = vec![0; q_len_plus_1]; limbs_shr_to_out(&mut ns_scratch, &ns[..q_len_plus_1], shift); ns = &ns_scratch; } let d_len = min(d_len, q_len); let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(q_len, d_len)]; limbs_modular_div_ref(qs, &ns[..q_len], &ds[..d_len], &mut scratch); }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs`. // `ns` and `ds` are taken by reference. // // `ns` must be exactly divisible by `ds`! If it isn't, the function will panic or return a // meaningless result. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // and `ds` must be nonempty and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` is too short, `ns` is shorter than `ds`, `ds` is empty, or the most-significant // limb of `ds` is zero. // // This is equivalent to `mpn_divexact` from `mpn/generic/divexact.c`, GMP 6.2.1. pub_test! {limbs_div_exact_to_out_ref_ref(qs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(ds[d_len - 1], 0); let leading_zeros = slice_leading_zeros(ds); let (ns_lo, ns_hi) = ns.split_at(leading_zeros); assert!(slice_test_zero(ns_lo), "division not exact"); let mut ns_scratch; let mut ds_scratch; let mut ns = ns_hi; let mut ds = &ds[leading_zeros..]; let n_len = ns.len(); let d_len = ds.len(); if d_len == 1 { limbs_div_exact_limb_to_out::(qs, ns, ds[0]); return; } let q_len = n_len - d_len + 1; let shift = TrailingZeros::trailing_zeros(ds[0]); if shift != 0 { let q_len_plus_1 = q_len + 1; let ds_scratch_len = if d_len > q_len { q_len_plus_1 } else { d_len }; ds_scratch = vec![0; ds_scratch_len]; limbs_shr_to_out(&mut ds_scratch, &ds[..ds_scratch_len], shift); ds = &ds_scratch; // Since we have excluded d_len == 1, we have n_len > q_len, and we need to shift one limb // beyond q_len. ns_scratch = vec![0; q_len_plus_1]; limbs_shr_to_out(&mut ns_scratch, &ns[..q_len_plus_1], shift); ns = &ns_scratch; } let d_len = min(d_len, q_len); let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(q_len, d_len)]; limbs_modular_div_ref(qs, &ns[..q_len], &ds[..d_len], &mut scratch); }} impl Natural { fn div_exact_limb_ref(&self, other: Limb) -> Self { match (self, other) { (_, 0) => panic!("division by zero"), (x, 1) => x.clone(), (Self(Small(small)), other) => Self(Small(small / other)), (Self(Large(limbs)), other) => { Self::from_owned_limbs_asc(limbs_div_exact_limb(limbs, other)) } } } fn div_exact_assign_limb(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => panic!("division by zero"), (_, 1) => {} (Self(Small(small)), other) => *small /= other, (Self(Large(limbs)), other) => { limbs_div_exact_limb_in_place(limbs, other); self.trim(); } } } } impl DivExact for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value. The first [`Natural`] /// must be exactly divisible by the second. If it isn't, this function may panic or return a /// meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self / other` instead. If you're /// unsure and you want to know, use `self.div_mod(other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `self.div_round(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// assert_eq!( /// Natural::from(56088u32).div_exact(Natural::from(456u32)), /// 123 /// ); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// assert_eq!( /// Natural::from_str("121932631112635269000000") /// .unwrap() /// .div_exact(Natural::from_str("987654321000").unwrap()), /// 123456789000u64 /// ); /// ``` #[inline] fn div_exact(mut self, other: Self) -> Self { self.div_exact_assign(other); self } } impl<'a> DivExact<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference. The first [`Natural`] must be exactly divisible by the second. If it isn't, this /// function may panic or return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self / &other` instead. If you're /// unsure and you want to know, use `self.div_mod(&other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `self.div_round(&other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// assert_eq!( /// Natural::from(56088u32).div_exact(&Natural::from(456u32)), /// 123 /// ); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// assert_eq!( /// Natural::from_str("121932631112635269000000") /// .unwrap() /// .div_exact(&Natural::from_str("987654321000").unwrap()), /// 123456789000u64 /// ); /// ``` #[inline] fn div_exact(mut self, other: &'a Self) -> Self { self.div_exact_assign(other); self } } impl DivExact for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value. The first [`Natural`] must be exactly divisible by the second. If it isn't, this /// function may panic or return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `&self / other` instead. If you're /// unsure and you want to know, use `self.div_mod(other)` and check whether the remainder is /// zero. If you want a function that panics if the division is not exact, use /// `(&self).div_round(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// assert_eq!( /// (&Natural::from(56088u32)).div_exact(Natural::from(456u32)), /// 123 /// ); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// assert_eq!( /// (&Natural::from_str("121932631112635269000000").unwrap()) /// .div_exact(Natural::from_str("987654321000").unwrap()), /// 123456789000u64 /// ); /// ``` fn div_exact(self, mut other: Natural) -> Natural { if *self == other { return Natural::ONE; } match (self, &mut other) { (_, &mut Natural::ZERO) => panic!("division by zero"), (n, &mut Natural::ONE) => n.clone(), (&Natural::ZERO, _) => Natural::ZERO, (n, &mut Natural(Small(d))) => n.div_exact_limb_ref(d), (Natural(Small(_)), Natural(Large(_))) => panic!("division not exact"), (Natural(Large(ns)), Natural(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { panic!("division not exact"); } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_exact_to_out_ref_val(&mut qs, ns, ds); Natural::from_owned_limbs_asc(qs) } } } } } impl DivExact<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference. The first /// [`Natural`] must be exactly divisible by the second. If it isn't, this function may panic or /// return a meaningless result. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `&self / &other` instead. If /// you're unsure and you want to know, use `(&self).div_mod(&other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `(&self).div_round(&other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExact; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// assert_eq!( /// (&Natural::from(56088u32)).div_exact(&Natural::from(456u32)), /// 123 /// ); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// assert_eq!( /// (&Natural::from_str("121932631112635269000000").unwrap()) /// .div_exact(&Natural::from_str("987654321000").unwrap()), /// 123456789000u64 /// ); /// ``` fn div_exact(self, other: &Natural) -> Natural { if self == other { return Natural::ONE; } match (self, other) { (_, &Natural::ZERO) => panic!("division by zero"), (n, &Natural::ONE) => n.clone(), (&Natural::ZERO, _) => Natural::ZERO, (n, Natural(Small(d))) => n.div_exact_limb_ref(*d), (Natural(Small(_)), Natural(Large(_))) => panic!("division not exact"), (Natural(Large(ns)), Natural(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { panic!("division not exact"); } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_exact_to_out_ref_ref(&mut qs, ns, ds); Natural::from_owned_limbs_asc(qs) } } } } } impl DivExactAssign for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. The first [`Natural`] must be exactly divisible by the second. If /// it isn't, this function may panic or return a meaningless result. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self /= other` instead. If you're /// unsure and you want to know, use `self.div_assign_mod(other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `self.div_round_assign(other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExactAssign; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// let mut x = Natural::from(56088u32); /// x.div_exact_assign(Natural::from(456u32)); /// assert_eq!(x, 123); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// let mut x = Natural::from_str("121932631112635269000000").unwrap(); /// x.div_exact_assign(Natural::from_str("987654321000").unwrap()); /// assert_eq!(x, 123456789000u64); /// ``` fn div_exact_assign(&mut self, mut other: Self) { if *self == other { *self = Self::ONE; return; } match (&mut *self, &mut other) { (_, &mut Self::ZERO) => panic!("division by zero"), (_, &mut Self::ONE) | (&mut Self::ZERO, _) => {} (n, &mut Self(Small(d))) => n.div_exact_assign_limb(d), (Self(Small(_)), Self(Large(_))) => panic!("division not exact"), (Self(Large(ns)), Self(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { panic!("division not exact"); } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_exact_to_out(&mut qs, ns, ds); swap(&mut qs, ns); self.trim(); } } } } } impl<'a> DivExactAssign<&'a Self> for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. The first [`Natural`] must be exactly divisible by the second. /// If it isn't, this function may panic or return a meaningless result. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// If you are unsure whether the division will be exact, use `self /= &other` instead. If /// you're unsure and you want to know, use `self.div_assign_mod(&other)` and check whether the /// remainder is zero. If you want a function that panics if the division is not exact, use /// `self.div_round_assign(&other, Exact)`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. May panic if `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivExactAssign; /// use malachite_nz::natural::Natural; /// /// // 123 * 456 = 56088 /// let mut x = Natural::from(56088u32); /// x.div_exact_assign(&Natural::from(456u32)); /// assert_eq!(x, 123); /// /// // 123456789000 * 987654321000 = 121932631112635269000000 /// let mut x = Natural::from_str("121932631112635269000000").unwrap(); /// x.div_exact_assign(&Natural::from_str("987654321000").unwrap()); /// assert_eq!(x, 123456789000u64); /// ``` fn div_exact_assign(&mut self, other: &'a Self) { if self == other { *self = Self::ONE; return; } match (&mut *self, other) { (_, &Self::ZERO) => panic!("division by zero"), (_, &Self::ONE) | (&mut Self::ZERO, _) => {} (_, Self(Small(d))) => self.div_exact_assign_limb(*d), (Self(Small(_)), Self(Large(_))) => panic!("division not exact"), (Self(Large(ns)), Self(Large(ds))) => { let ns_len = ns.len(); let ds_len = ds.len(); if ns_len < ds_len { panic!("division not exact"); } else { let mut qs = vec![0; ns_len - ds_len + 1]; limbs_div_exact_to_out_val_ref(&mut qs, ns, ds); swap(&mut qs, ns); self.trim(); } } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/div_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_dcpi1_div_qr`, `mpn_dcpi1_div_qr_n`, `mpn_preinv_mu_div_qr_itch`, // `mpn_preinv_mu_div_qr`, `mpn_mu_div_qr_choose_in`, `mpn_mu_div_qr2`, `mpn_mu_div_qr`, // `mpn_mu_div_qr_itch`, and `mpn_sbpi1_div_qr` contributed to the GNU project by Torbjörn // Granlund. // // `mpn_invertappr`, `mpn_bc_invertappr`, and `mpn_ni_invertappr` contributed to the GNU // project by Marco Bodrato. The algorithm used here was inspired by ApproximateReciprocal from // "Modern Computer Arithmetic", by Richard P. Brent and Paul Zimmermann. Special thanks to // Paul Zimmermann for his very valuable suggestions on all the theoretical aspects during the // work on this code. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_same_length_with_carry_in_in_place_left, limbs_add_same_length_with_carry_in_to_out, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div::{ limbs_div_divide_and_conquer_approx, limbs_div_schoolbook_approx, }; use crate::natural::arithmetic::mul::mul_mod::{ limbs_mul_mod_base_pow_n_minus_1, limbs_mul_mod_base_pow_n_minus_1_next_size, limbs_mul_mod_base_pow_n_minus_1_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, limbs_sub_same_length_with_borrow_in_in_place_left, limbs_sub_same_length_with_borrow_in_in_place_right, limbs_sub_same_length_with_borrow_in_to_out, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::logic::not::limbs_not_to_out; use crate::platform::{ DC_DIV_QR_THRESHOLD, DC_DIVAPPR_Q_THRESHOLD, DoubleLimb, INV_MULMOD_BNM1_THRESHOLD, INV_NEWTON_THRESHOLD, Limb, MAYBE_DCP1_DIVAPPR, MU_DIV_QR_SKEW_THRESHOLD, MU_DIV_QR_THRESHOLD, }; use alloc::vec::Vec; use core::cmp::{Ordering::*, min}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ CeilingDivAssignNegMod, CeilingDivNegMod, DivAssignMod, DivAssignRem, DivMod, DivRem, WrappingAddAssign, WrappingSub, WrappingSubAssign, XMulYToZZ, XXDivModYToQR, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::{slice_move_left, slice_set_zero}; // The highest bit of the input must be set. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `d` is zero. // // This is equivalent to `mpn_invert_limb`, or `invert_limb`, from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_invert_limb< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( d: T, ) -> T { (DT::join_halves(!d, T::MAX) / DT::from(d)).lower_half() }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_qrnnd_preinv` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {div_mod_by_preinversion( n_high: Limb, n_low: Limb, d: Limb, d_inv: Limb ) -> (Limb, Limb) { let (mut q_high, q_low) = (DoubleLimb::from(n_high) * DoubleLimb::from(d_inv)) .wrapping_add(DoubleLimb::join_halves(n_high.wrapping_add(1), n_low)) .split_in_half(); let mut r = n_low.wrapping_sub(q_high.wrapping_mul(d)); if r > q_low { let (r_plus_d, overflow) = r.overflowing_add(d); if overflow { q_high.wrapping_sub_assign(1); r = r_plus_d; } } else if r >= d { q_high.wrapping_add_assign(1); r -= d; } (q_high, r) }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs and remainder of the `Natural` divided by a `Limb`. The divisor limb cannot be // zero and the limb slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if the length of `ns` is less than 2 or if `d` is zero. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qxn == 0`, // `un > 1`, and both results are returned. Experiments show that `DIVREM_1_NORM_THRESHOLD` and // `DIVREM_1_UNNORM_THRESHOLD` are unnecessary (they would always be 0). pub_test! {limbs_div_limb_mod(ns: &[Limb], d: Limb) -> (Vec, Limb) { let mut qs = vec![0; ns.len()]; let r = limbs_div_limb_to_out_mod(&mut qs, ns, d); (qs, r) }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to an output slice, and returns the // remainder. The output slice must be at least as long as the input slice. The divisor limb cannot // be zero and the input limb slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `out` is shorter than `ns`, the length of `ns` is less than 2, or if `d` is zero. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qxn == 0` // and `un > 1`. Experiments show that `DIVREM_1_NORM_THRESHOLD` and `DIVREM_1_UNNORM_THRESHOLD` are // unnecessary (they would always be 0). pub_crate_test! {limbs_div_limb_to_out_mod(out: &mut [Limb], ns: &[Limb], d: Limb) -> Limb { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let out = &mut out[..len]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { // High quotient limb is 0 or 1, skip a divide step. let (r, ns_init) = ns.split_last().unwrap(); let mut r = *r; let (out_last, out_init) = out.split_last_mut().unwrap(); let adjust = r >= d; if adjust { r -= d; } *out_last = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); for (out_q, &n) in out_init.iter_mut().zip(ns_init.iter()).rev() { (*out_q, r) = div_mod_by_preinversion(r, n, d, d_inv); } r } else { // Skip a division if high < divisor (high quotient 0). Testing here before normalizing will // still skip as often as possible. let (ns_last, ns_init) = ns.split_last().unwrap(); let (ns, mut r) = if *ns_last < d { *out.last_mut().unwrap() = 0; (ns_init, *ns_last) } else { (ns, 0) }; let d = d << bits; r <<= bits; let d_inv = limbs_invert_limb::(d); let (previous_n, ns_init) = ns.split_last().unwrap(); let mut previous_n = *previous_n; let cobits = Limb::WIDTH - bits; r |= previous_n >> cobits; let (out_head, out_tail) = out.split_first_mut().unwrap(); for (out_q, &n) in out_tail.iter_mut().zip(ns_init.iter()).rev() { let n_shifted = (previous_n << bits) | (n >> cobits); (*out_q, r) = div_mod_by_preinversion(r, n_shifted, d, d_inv); previous_n = n; } let out_r; (*out_head, out_r) = div_mod_by_preinversion(r, previous_n << bits, d, d_inv); out_r >> bits } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the quotient of the `Natural` and a `Limb` to the input slice and returns the remainder. // The divisor limb cannot be zero and the input limb slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if the length of `ns` is less than 2 or if `d` is zero. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qp == up`, // `qxn == 0`, and `un > 1`. Experiments show that `DIVREM_1_NORM_THRESHOLD` and // `DIVREM_1_UNNORM_THRESHOLD` are unnecessary (they would always be 0). pub_crate_test! {limbs_div_limb_in_place_mod(ns: &mut [Limb], d: Limb) -> Limb { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let bits = LeadingZeros::leading_zeros(d); let (ns_last, ns_init) = ns.split_last_mut().unwrap(); if bits == 0 { // High quotient limb is 0 or 1, skip a divide step. let mut r = *ns_last; let adjust = r >= d; if adjust { r -= d; } *ns_last = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); for n in ns_init.iter_mut().rev() { (*n, r) = div_mod_by_preinversion(r, *n, d, d_inv); } r } else { // Skip a division if high < divisor (high quotient 0). Testing here before normalizing will // still skip as often as possible. let (ns, mut r) = if *ns_last < d { let r = *ns_last; *ns_last = 0; (ns_init, r) } else { (ns, 0) }; let d = d << bits; r <<= bits; let d_inv = limbs_invert_limb::(d); let last_index = ns.len() - 1; let mut previous_n = ns[last_index]; let cobits = Limb::WIDTH - bits; r |= previous_n >> cobits; for i in (0..last_index).rev() { let n = ns[i]; let shifted_n = (previous_n << bits) | (n >> cobits); (ns[i + 1], r) = div_mod_by_preinversion(r, shifted_n, d, d_inv); previous_n = n; } let out_r; (ns[0], out_r) = div_mod_by_preinversion(r, previous_n << bits, d, d_inv); out_r >> bits } }} // Let `ns` be the limbs of a `Natural` $n$, and let $f$ be `fraction_len`. This function performs // the integer division $B^fn / d$, writing the `ns.len() + fraction_len` limbs of the quotient to // `out` and returning the remainder. // // `shift` must be the number of leading zeros of `d`, and `d_inv` must be `limbs_invert_limb(d << // shift)`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len() + fraction_len`. // // # Panics // Panics if `out` is shorter than `ns.len()` + `fraction_len`, if `ns` is empty, or if `d` is zero. // // This is equivalent to `mpn_preinv_divrem_1` from `mpn/generic/pre_divrem_1.c`, GMP 6.2.1, where // `qp != ap`. pub_test! {limbs_div_mod_extra( out: &mut [Limb], fraction_len: usize, mut ns: &[Limb], d: Limb, d_inv: Limb, shift: u64, ) -> Limb { assert!(!ns.is_empty()); assert_ne!(d, 0); let (ns_last, ns_init) = ns.split_last().unwrap(); let ns_last = *ns_last; let d_norm = d << shift; let (fraction_out, integer_out) = out.split_at_mut(fraction_len); let mut integer_out = &mut integer_out[..ns.len()]; let mut r; if shift == 0 { r = ns_last; let q_high = r >= d_norm; if r >= d_norm { r -= d_norm; } let (integer_out_last, integer_out_init) = integer_out.split_last_mut().unwrap(); *integer_out_last = Limb::from(q_high); for (q, &n) in integer_out_init.iter_mut().zip(ns_init.iter()).rev() { (*q, r) = div_mod_by_preinversion(r, n, d_norm, d_inv); } } else { r = 0; if ns_last < d { r = ns_last << shift; let integer_out_last; (integer_out_last, integer_out) = integer_out.split_last_mut().unwrap(); *integer_out_last = 0; ns = ns_init; } if !ns.is_empty() { let co_shift = Limb::WIDTH - shift; let (ns_last, ns_init) = ns.split_last().unwrap(); let mut previous_n = *ns_last; r |= previous_n >> co_shift; let (integer_out_head, integer_out_tail) = integer_out.split_first_mut().unwrap(); for (q, &n) in integer_out_tail.iter_mut().zip(ns_init.iter()).rev() { assert!(r < d_norm); (*q, r) = div_mod_by_preinversion( r, (previous_n << shift) | (n >> co_shift), d_norm, d_inv, ); previous_n = n; } (*integer_out_head, r) = div_mod_by_preinversion(r, previous_n << shift, d_norm, d_inv); } } for q in fraction_out.iter_mut().rev() { (*q, r) = div_mod_by_preinversion(r, 0, d_norm, d_inv); } r >> shift }} // Let `&ns[fraction_len..]` be the limbs of a `Natural` $n$, and let $f$ be `fraction_len`. This // function performs the integer division $B^fn / d$, writing the `ns.len() + fraction_len` limbs of // the quotient to `ns` and returning the remainder. // // `shift` must be the number of leading zeros of `d`, and `d_inv` must be `limbs_invert_limb(d << // shift)`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len() + fraction_len`. // // # Panics // Panics if `ns` is empty, if `ns.len()` is less than `fraction_len`, or if `d` is zero. // // This is equivalent to `mpn_preinv_divrem_1` from `mpn/generic/pre_divrem_1.c`, GMP 6.2.1, where // `qp == ap`. pub_crate_test! {limbs_div_mod_extra_in_place( ns: &mut [Limb], fraction_len: usize, d: Limb, d_inv: Limb, shift: u64, ) -> Limb { assert_ne!(d, 0); let (fraction_ns, mut integer_ns) = ns.split_at_mut(fraction_len); let ns_last = *integer_ns.last().unwrap(); let d_norm = d << shift; let mut r; if shift == 0 { r = ns_last; let q_high = r >= d_norm; if r >= d_norm { r -= d_norm; } let (integer_ns_last, integer_ns_init) = integer_ns.split_last_mut().unwrap(); *integer_ns_last = Limb::from(q_high); for q in integer_ns_init.iter_mut().rev() { (*q, r) = div_mod_by_preinversion(r, *q, d_norm, d_inv); } } else { r = 0; if ns_last < d { r = ns_last << shift; let integer_ns_last; (integer_ns_last, integer_ns) = integer_ns.split_last_mut().unwrap(); *integer_ns_last = 0; } if !integer_ns.is_empty() { let co_shift = Limb::WIDTH - shift; let mut previous_n = *integer_ns.last().unwrap(); r |= previous_n >> co_shift; for i in (1..integer_ns.len()).rev() { assert!(r < d_norm); let n = integer_ns[i - 1]; (integer_ns[i], r) = div_mod_by_preinversion( r, (previous_n << shift) | (n >> co_shift), d_norm, d_inv, ); previous_n = n; } (integer_ns[0], r) = div_mod_by_preinversion(r, previous_n << shift, d_norm, d_inv); } } for q in fraction_ns.iter_mut().rev() { (*q, r) = div_mod_by_preinversion(r, 0, d_norm, d_inv); } r >> shift }} // Computes floor((B ^ 3 - 1) / (`hi` * B + `lo`)) - B, where B = 2 ^ `Limb::WIDTH`, assuming the // highest bit of `hi` is set. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `hi` is zero. // // This is equivalent to `invert_pi1` from `gmp-impl.h`, GMP 6.2.1, where the result is returned // instead of being written to `dinv`. pub_crate_test! {limbs_two_limb_inverse_helper(hi: Limb, lo: Limb) -> Limb { let mut d_inv = limbs_invert_limb::(hi); let mut hi_product = hi.wrapping_mul(d_inv); hi_product.wrapping_add_assign(lo); if hi_product < lo { d_inv.wrapping_sub_assign(1); if hi_product >= hi { hi_product.wrapping_sub_assign(hi); d_inv.wrapping_sub_assign(1); } hi_product.wrapping_sub_assign(hi); } let (lo_product_hi, lo_product_lo) = Limb::x_mul_y_to_zz(lo, d_inv); hi_product.wrapping_add_assign(lo_product_hi); if hi_product < lo_product_hi { d_inv.wrapping_sub_assign(1); if hi_product > hi || hi_product == hi && lo_product_lo >= lo { d_inv.wrapping_sub_assign(1); } } d_inv }} // Computes the quotient and remainder of `[n_2, n_1, n_0]` / `[d_1, d_0]`. Requires the highest bit // of `d_1` to be set, and `[n_2, n_1]` < `[d_1, d_0]`. `d_inv` is the inverse of `[d_1, d_0]` // computed by `limbs_two_limb_inverse_helper`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_qr_3by2` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_div_mod_three_limb_by_two_limb( n_2: Limb, n_1: Limb, n_0: Limb, d_1: Limb, d_0: Limb, d_inv: Limb, ) -> (Limb, DoubleLimb) { let (mut q, q_lo) = (DoubleLimb::from(n_2) * DoubleLimb::from(d_inv)) .wrapping_add(DoubleLimb::join_halves(n_2, n_1)) .split_in_half(); let d = DoubleLimb::join_halves(d_1, d_0); // Compute the two most significant limbs of n - q * d let mut r = DoubleLimb::join_halves(n_1.wrapping_sub(d_1.wrapping_mul(q)), n_0) .wrapping_sub(d) .wrapping_sub(DoubleLimb::from(d_0) * DoubleLimb::from(q)); q.wrapping_add_assign(1); // Conditionally adjust q and the remainder if r.upper_half() >= q_lo { let (r_plus_d, overflow) = r.overflowing_add(d); if overflow { q.wrapping_sub_assign(1); r = r_plus_d; } } else if r >= d { q.wrapping_add_assign(1); r.wrapping_sub_assign(d); } (q, r) }} // Divides `ns` by `ds` and writes the `ns.len()` - 2 least-significant quotient limbs to `qs` and // the 2-long remainder to `ns`. Returns the most significant limb of the quotient; `true` means 1 // and `false` means 0. `ds` must have length 2, `ns` must have length at least 2, and the most // significant bit of `ds[1]` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` does not have length 2, `ns` has length less than 2, `qs` has length less than // `ns.len() - 2`, or `ds[1]` does not have its highest bit set. // // This is equivalent to `mpn_divrem_2` from `mpn/generic/divrem_2.c`, GMP 6.2.1. pub_crate_test! {limbs_div_mod_by_two_limb_normalized( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb] ) -> bool { assert_eq!(ds.len(), 2); let n_len = ns.len(); assert!(n_len >= 2); let n_limit = n_len - 2; assert!(ds[1].get_highest_bit()); let d_1 = ds[1]; let d_0 = ds[0]; let d = DoubleLimb::join_halves(d_1, d_0); let mut r = DoubleLimb::join_halves(ns[n_limit + 1], ns[n_limit]); let highest_q = r >= d; if highest_q { r.wrapping_sub_assign(d); } let (mut r_1, mut r_0) = r.split_in_half(); let d_inv = limbs_two_limb_inverse_helper(d_1, d_0); for (&n, q) in ns[..n_limit].iter().zip(qs[..n_limit].iter_mut()).rev() { let r; (*q, r) = limbs_div_mod_three_limb_by_two_limb(r_1, r_0, n, d_1, d_0, d_inv); (r_1, r_0) = r.split_in_half(); } ns[1] = r_1; ns[0] = r_0; highest_q }} // Schoolbook division using the Möller-Granlund 3/2 division algorithm. // // Divides `ns` by `ds` and writes the `ns.len()` - `ds.len()` least-significant quotient limbs to // `qs` and the `ds.len()` limbs of the remainder to `ns`. Returns the most significant limb of the // quotient; `true` means 1 and `false` means 0. `ds` must have length greater than 2, `ns` must be // at least as long as `ds`, and the most significant bit of `ds` must be set. `d_inv` should be the // result of `limbs_two_limb_inverse_helper` applied to the two highest limbs of the denominator. // // # Worst-case complexity // $T(n, d) = O(d(n - d + 1)) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // # Panics // Panics if `ds` has length smaller than 3, `ns` is shorter than `ds`, `qs` has length less than // `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_sbpi1_div_qr` from `mpn/generic/sbpi1_div_qr.c`, GMP 6.2.1. pub_crate_test! {limbs_div_mod_schoolbook( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let d_len = ds.len(); assert!(d_len > 2); let n_len = ns.len(); assert!(n_len >= d_len); let d_1 = ds[d_len - 1]; assert!(d_1.get_highest_bit()); let d_0 = ds[d_len - 2]; let ds_except_last = &ds[..d_len - 1]; let ds_except_last_two = &ds[..d_len - 2]; let ns_hi = &mut ns[n_len - d_len..]; let highest_q = limbs_cmp_same_length(ns_hi, ds) >= Equal; if highest_q { limbs_sub_same_length_in_place_left(ns_hi, ds); } let mut n_1 = ns[n_len - 1]; for i in (d_len..n_len).rev() { let j = i - d_len; let mut q; if n_1 == d_1 && ns[i - 1] == d_0 { q = Limb::MAX; limbs_sub_mul_limb_same_length_in_place_left(&mut ns[j..i], ds, q); n_1 = ns[i - 1]; // update n_1, last loop's value will now be invalid } else { let (ns_lo, ns_hi) = ns.split_at_mut(i - 2); let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns_hi[1], ns_hi[0], d_1, d_0, d_inv); let mut n_0; (n_1, n_0) = n.split_in_half(); let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left( &mut ns_lo[j..], ds_except_last_two, q, ); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns_hi[0] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(&mut ns[j..i - 1], ds_except_last) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } } qs[j] = q; } ns[d_len - 1] = n_1; highest_q }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_div_qr_n` from `mpn/generic/dcpi1_div_qr.c`, GMP 6.2.1. pub(crate) fn limbs_div_mod_divide_and_conquer_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) -> bool { let n = ds.len(); let lo = n >> 1; // floor(n / 2) let hi = n - lo; // ceil(n / 2) let qs_hi = &mut qs[lo..]; let (ds_lo, ds_hi) = ds.split_at(lo); let mut highest_q = if hi < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs_hi, &mut ns[lo << 1..n << 1], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs_hi, &mut ns[lo << 1..], ds_hi, d_inv, scratch) }; let qs_hi = &mut qs_hi[..hi]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(qs_hi.len(), ds_lo.len())]; limbs_mul_greater_to_out(scratch, qs_hi, ds_lo, &mut mul_scratch); let ns_lo = &mut ns[..n + lo]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left( &mut ns_lo[lo..], &scratch[..n], )); if highest_q && limbs_sub_same_length_in_place_left(&mut ns_lo[n..], ds_lo) { carry += 1; } while carry != 0 { if limbs_sub_limb_in_place(qs_hi, 1) { assert!(highest_q); highest_q = false; } if limbs_slice_add_same_length_in_place_left(&mut ns_lo[lo..], ds) { carry -= 1; } } let (ds_lo, ds_hi) = ds.split_at(hi); let q_lo = if lo < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, &mut ns[hi..n + lo], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs, &mut ns[hi..], ds_hi, d_inv, scratch) }; let qs_lo = &mut qs[..lo]; let ns_lo = &mut ns[..n]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds_lo.len(), lo)]; limbs_mul_greater_to_out(scratch, ds_lo, qs_lo, &mut mul_scratch); let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns_lo, &scratch[..n])); if q_lo && limbs_sub_same_length_in_place_left(&mut ns_lo[lo..], ds_lo) { carry += 1; } while carry != 0 { limbs_sub_limb_in_place(qs_lo, 1); if limbs_slice_add_same_length_in_place_left(ns_lo, ds) { carry -= 1; } } highest_q } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. pub_test! {limbs_div_dc_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) -> bool { if qs.len() < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, ns, ds, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs, ns, ds, d_inv, scratch) } }} // Recursive divide-and-conquer division. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // # Panics // Panics if `ds` has length smaller than 6, `ns.len()` is less than `ds.len()` + 3, `qs` has length // less than `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_dcpi1_div_qr` from `mpn/generic/dcpi1_div_qr.c`, GMP 6.2.1. pub_test! {limbs_div_mod_divide_and_conquer( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 6); // to adhere to limbs_div_mod_schoolbook's limits assert!(n_len >= d_len + 3); // to adhere to limbs_div_mod_schoolbook's limits let a = d_len - 1; let d_1 = ds[a]; let b = d_len - 2; assert!(d_1.get_highest_bit()); let mut scratch = vec![0; d_len]; let mut highest_q; let q_len = n_len - d_len; if q_len > d_len { let q_len_mod_d_len = { let mut m = q_len % d_len; if m == 0 { m = d_len; } m }; // Perform the typically smaller block first. Point at low limb of next quotient block let qs_alt = &mut qs[q_len - q_len_mod_d_len..q_len]; if q_len_mod_d_len == 1 { // Handle highest_q up front, for simplicity. let ns_hi = &mut ns[q_len - 1..]; let ns_hi_hi = &mut ns_hi[1..]; highest_q = limbs_cmp_same_length(ns_hi_hi, ds) >= Equal; if highest_q { assert!(!limbs_sub_same_length_in_place_left(ns_hi_hi, ds)); } // A single iteration of schoolbook: One 3/2 division, followed by the bignum update and // adjustment. let (last_n, ns) = ns_hi.split_last_mut().unwrap(); let n_2 = *last_n; let mut n_1 = ns[a]; let mut n_0 = ns[b]; let d_0 = ds[b]; assert!(n_2 < d_1 || n_2 == d_1 && n_1 <= d_0); let mut q; if n_2 == d_1 && n_1 == d_0 { q = Limb::MAX; assert_eq!(limbs_sub_mul_limb_same_length_in_place_left(ns, ds, q), n_2); } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, d_inv); (n_1, n_0) = n.split_in_half(); // d_len > 2 because of precondition. No need to check let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[..b], &ds[..b], q); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns[b] = n_0; let (last_n, ns) = ns.split_last_mut().unwrap(); if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(ns, &ds[..a]) { n_1.wrapping_add_assign(1); } if q == 0 { assert!(highest_q); highest_q = false; } q.wrapping_sub_assign(1); } *last_n = n_1; } qs_alt[0] = q; } else { // Do a 2 * q_len_mod_d_len / q_len_mod_d_len division let (ds_lo, ds_hi) = ds.split_at(d_len - q_len_mod_d_len); highest_q = { let ns = &mut ns[n_len - (q_len_mod_d_len << 1)..]; if q_len_mod_d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs_alt, ns, ds_hi) } else { limbs_div_dc_helper(qs_alt, ns, ds_hi, d_inv, &mut scratch) } }; if q_len_mod_d_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(qs_alt.len(), ds_lo.len())]; limbs_mul_to_out(&mut scratch, qs_alt, ds_lo, &mut mul_scratch); let ns = &mut ns[q_len - q_len_mod_d_len..n_len - q_len_mod_d_len]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns, &scratch)); if highest_q && limbs_sub_same_length_in_place_left(&mut ns[q_len_mod_d_len..], ds_lo) { carry += 1; } while carry != 0 { if limbs_sub_limb_in_place(qs_alt, 1) { assert!(highest_q); highest_q = false; } if limbs_slice_add_same_length_in_place_left(ns, ds) { carry -= 1; } } } } // offset is a multiple of d_len let mut offset = n_len.checked_sub(d_len + q_len_mod_d_len).unwrap(); while offset != 0 { offset -= d_len; limbs_div_mod_divide_and_conquer_helper( &mut qs[offset..], &mut ns[offset..], ds, d_inv, &mut scratch, ); } } else { let m = d_len - q_len; let (ds_lo, ds_hi) = ds.split_at(m); highest_q = if q_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, &mut ns[m..], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs, &mut ns[m..], ds_hi, d_inv, &mut scratch) }; if m != 0 { let qs = &mut qs[..q_len]; let ns = &mut ns[..d_len]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(q_len, ds_lo.len())]; limbs_mul_to_out(&mut scratch, qs, ds_lo, &mut mul_scratch); let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns, &scratch)); if highest_q && limbs_sub_same_length_in_place_left(&mut ns[q_len..], ds_lo) { carry += 1; } while carry != 0 { if limbs_sub_limb_in_place(qs, 1) { assert!(highest_q); highest_q = false; } if limbs_slice_add_same_length_in_place_left(ns, ds) { carry -= 1; } } } } highest_q }} pub_test! {limbs_div_approx_helper(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb) { if ds.len() < DC_DIVAPPR_Q_THRESHOLD { limbs_div_schoolbook_approx(qs, ns, ds, d_inv); } else { limbs_div_divide_and_conquer_approx(qs, ns, ds, d_inv); } }} // Takes the strictly normalized value ds (i.e., most significant bit must be set) as an input, and // computes the approximate reciprocal of `ds`, with the same length as `ds`. See documentation for // `limbs_invert_approx` for an explanation of the return value. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // # Panics // Panics if `ds` is empty, `is` is shorter than `ds`, `scratch` is shorter than twice the length of // `ds`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_bc_invertappr` from `mpn/generic/invertappr.c`, GMP 6.2.1, where the // return value is `true` iff the return value of `mpn_bc_invertappr` would be 0. pub_test! {limbs_invert_basecase_approx( is: &mut [Limb], ds: &[Limb], scratch: &mut [Limb] ) -> bool { let d_len = ds.len(); assert_ne!(d_len, 0); let highest_d = ds[d_len - 1]; assert!(highest_d.get_highest_bit()); if d_len == 1 { let d = ds[0]; is[0] = limbs_invert_limb::(d); } else { let scratch = &mut scratch[..d_len << 1]; let (scratch_lo, scratch_hi) = scratch.split_at_mut(d_len); for s in &mut *scratch_lo { *s = Limb::MAX; } limbs_not_to_out(scratch_hi, ds); // Now scratch contains 2 ^ (2 * d_len * Limb::WIDTH) - d * 2 ^ (d_len * Limb::WIDTH) - 1 if d_len == 2 { limbs_div_mod_by_two_limb_normalized(is, scratch, ds); } else { let d_inv = limbs_two_limb_inverse_helper(highest_d, ds[d_len - 2]); if MAYBE_DCP1_DIVAPPR { limbs_div_approx_helper(is, scratch, ds, d_inv); } else { limbs_div_schoolbook_approx(is, scratch, ds, d_inv); } assert!(!limbs_sub_limb_in_place(&mut is[..d_len], 1)); return false; } } true }} // Takes the strictly normalized value ds (i.e., most significant bit must be set) as an input, and // computes the approximate reciprocal of `ds`, with the same length as `ds`. See documentation for // `limbs_invert_approx` for an explanation of the return value. // // Uses Newton's iterations (at least one). Inspired by Algorithm "ApproximateReciprocal", published // in "Modern Computer Arithmetic" by Richard P. Brent and Paul Zimmermann, algorithm 3.5, page 121 // in version 0.4 of the book. // // Some adaptations were introduced, to allow product mod B ^ m - 1 and return the value e. // // We introduced a correction in such a way that "the value of B ^ {n + h} - T computed at step 8 // cannot exceed B ^ n - 1" (the book reads "2 * B ^ n - 1"). // // Maximum scratch needed by this branch <= 2 * n, but have to fit 3 * rn in the scratch, i.e. 3 * // rn <= 2 * n: we require n > 4. // // We use a wrapped product modulo B ^ m - 1. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `is.len()`. // // # Panics // Panics if `ds` has length less than 5, `is` is shorter than `ds`, `scratch` is shorter than twice // the length of `ds`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_ni_invertappr` from `mpn/generic/invertappr.c`, GMP 6.2.1, where the // return value is `true` iff the return value of `mpn_ni_invertappr` would be 0. pub_test! {limbs_invert_newton_approx(is: &mut [Limb], ds: &[Limb], scratch: &mut [Limb]) -> bool { let d_len = ds.len(); assert!(d_len > 4); assert!(ds[d_len - 1].get_highest_bit()); let is = &mut is[..d_len]; // Compute the computation precisions from highest to lowest, leaving the base case size in // 'previous_d'. let mut size = d_len; let mut sizes = vec![size]; size = (size >> 1) + 1; let mut scratch2 = vec![]; let mut mul_size = 0; if d_len >= INV_MULMOD_BNM1_THRESHOLD { mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); scratch2 = vec![0; limbs_mul_mod_base_pow_n_minus_1_scratch_len(mul_size, d_len, size)]; } while size >= INV_NEWTON_THRESHOLD { sizes.push(size); size = (size >> 1) + 1; } // We compute the inverse of 0.ds as 1.is. Compute a base value of previous_d limbs. limbs_invert_basecase_approx(&mut is[d_len - size..], &ds[d_len - size..], scratch); let mut previous_size = size; let mut a = 0; // Use Newton's iterations to get the desired precision. for &size in sizes.iter().rev() { // ``` // v d v // +----+-------+ // ^ previous_d ^ // ``` // // Compute i_j * d let ds_hi = &ds[d_len - size..]; let condition = size < INV_MULMOD_BNM1_THRESHOLD || { mul_size = limbs_mul_mod_base_pow_n_minus_1_next_size(size + 1); mul_size > size + previous_size }; let diff = size - previous_size; let is_hi = &mut is[d_len - previous_size..]; if condition { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds_hi.len(), is_hi.len())]; limbs_mul_greater_to_out(scratch, ds_hi, is_hi, &mut mul_scratch); limbs_slice_add_same_length_in_place_left( &mut scratch[previous_size..=size], &ds_hi[..=diff], ); } else { // Remember we truncated mod B ^ (d + 1) We computed (truncated) xp of length d + 1 <- // 1.is * 0.ds Use B ^ mul_size - 1 wraparound limbs_mul_mod_base_pow_n_minus_1(scratch, mul_size, ds_hi, is_hi, &mut scratch2); let scratch = &mut scratch[..=mul_size]; // We computed {xp, mul_size} <- {is, previous_d} * {ds, d} mod (B ^ mul_size - 1) We // know that 2 * |is * ds + ds * B ^ previous_d - B ^ {previous_d + d}| < B ^ mul_size // - 1 Add ds * B ^ previous_d mod (B ^ mul_size - 1) let mul_diff = mul_size - previous_size; assert!(size >= mul_diff); let (ds_hi_lo, ds_hi_hi) = ds_hi.split_at(mul_diff); let carry = limbs_slice_add_same_length_in_place_left( &mut scratch[previous_size..mul_size], ds_hi_lo, ); // Subtract B ^ {previous_d + d}, maybe only compensate the carry scratch[mul_size] = 1; // set a limit for decrement let (scratch_lo, scratch_hi) = scratch.split_at_mut(size - mul_diff); if !limbs_add_same_length_with_carry_in_in_place_left(scratch_lo, ds_hi_hi, carry) { assert!(!limbs_sub_limb_in_place(scratch_hi, 1)); } // if decrement eroded xp[mul_size] let (scratch_last, scratch_init) = scratch.split_last_mut().unwrap(); assert!(!limbs_sub_limb_in_place( scratch_init, 1.wrapping_sub(*scratch_last) )); // Remember we are working mod B ^ mul_size - 1 } if scratch[size] < 2 { // "positive" residue class let (scratch_lo, scratch_hi) = scratch.split_at_mut(size); let mut carry = scratch_hi[0] + 1; // 1 <= carry <= 2 here. if carry == 2 && !limbs_sub_same_length_in_place_left(scratch_lo, ds_hi) { carry = 3; assert!(limbs_sub_same_length_in_place_left(scratch_lo, ds_hi)); } // 1 <= carry <= 3 here. if limbs_cmp_same_length(scratch_lo, ds_hi) == Greater { assert!(!limbs_sub_same_length_in_place_left(scratch_lo, ds_hi)); carry += 1; } let (scratch_lo, scratch_mid) = scratch_lo.split_at_mut(diff); let (ds_hi_lo, ds_hi_hi) = ds_hi.split_at(diff); let borrow = limbs_cmp_same_length(scratch_lo, ds_hi_lo) == Greater; assert!(!limbs_sub_same_length_with_borrow_in_to_out( &mut scratch_hi[diff..], ds_hi_hi, scratch_mid, borrow )); assert!(!limbs_sub_limb_in_place(is_hi, carry)); // 1 <= carry <= 4 here } else { // "negative" residue class assert!(scratch[size] >= Limb::MAX - 1); if condition { assert!(!limbs_sub_limb_in_place(&mut scratch[..=size], 1)); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(size); if scratch_hi[0] != Limb::MAX { assert!(!limbs_slice_add_limb_in_place(is_hi, 1)); assert!(limbs_slice_add_same_length_in_place_left(scratch_lo, ds_hi)); } limbs_not_to_out(&mut scratch_hi[diff..size], &scratch_lo[diff..]); } // Compute x_j * u_j let (scratch_lo, scratch_hi) = scratch.split_at_mut(size + diff); let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(is_hi.len())]; limbs_mul_same_length_to_out( scratch_lo, &scratch_hi[..previous_size], is_hi, &mut mul_scratch, ); a = (previous_size << 1) - diff; let carry = { let (scratch_lo, scratch_hi) = scratch.split_at_mut(a); limbs_slice_add_same_length_in_place_left( &mut scratch_lo[previous_size..], &scratch_hi[3 * diff - previous_size..diff << 1], ) }; if limbs_add_same_length_with_carry_in_to_out( &mut is[d_len - size..], &scratch[a..previous_size << 1], &scratch[size + previous_size..size << 1], carry, ) { assert!(!limbs_slice_add_limb_in_place( &mut is[d_len - previous_size..], 1 )); } previous_size = size; } // Check for possible carry propagation from below. Be conservative. scratch[a - 1] <= Limb::MAX - 7 }} // Takes the strictly normalized value ds (i.e., most significant bit must be set) as an input, and // computes the approximate reciprocal of `ds`, with the same length as `ds`. // // Let result_definitely_exact = limbs_invert_basecase_approx(is, ds, scratch) be the returned // value. If result_definitely_exact is `true`, the error e is 0; otherwise, it may be 0 or 1. The // following condition is satisfied by the output: // // ds * (2 ^ (n * Limb::WIDTH) + is) < 2 ^ (2 * n * Limb::WIDTH) <= ds * (2 ^ (n * Limb::WIDTH) + is // + 1 + e), where n = `ds.len()`. // // When the strict result is needed, i.e., e = 0 in the relation above, the function `mpn_invert` // (TODO!) should be used instead. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `is.len()`. // // # Panics // Panics if `ds` is empty, `is` is shorter than `ds`, `scratch` is shorter than twice the length of // `ds`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_invertappr` from `mpn/generic/invertappr.c`, GMP 6.2.1, where the // return value is `true` iff the return value of `mpn_invertappr` would be 0. pub_crate_test! {limbs_invert_approx(is: &mut [Limb], ds: &[Limb], scratch: &mut [Limb]) -> bool { if ds.len() < INV_NEWTON_THRESHOLD { limbs_invert_basecase_approx(is, ds, scratch) } else { limbs_invert_newton_approx(is, ds, scratch) } }} // TODO tune pub(crate) const MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD: usize = INV_MULMOD_BNM1_THRESHOLD >> 1; // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // - ds.len() >= 2 // - n_len >= 3 // - n_len >= ds.len() // - i_len == limbs_div_mod_barrett_is_len(n_len - ds.len(), ds.len()) // - qs.len() == i_len // - scratch_len == limbs_mul_mod_base_pow_n_minus_1_next_size(ds.len() + 1) // - scratch.len() == limbs_div_mod_barrett_scratch_len(n_len, d_len) - i_len // - rs_hi.len() == i_len pub_crate_test! {limbs_div_barrett_large_product( scratch: &mut [Limb], ds: &[Limb], qs: &[Limb], rs_hi: &[Limb], scratch_len: usize, i_len: usize, ) { let d_len = ds.len(); let (scratch, scratch_out) = scratch.split_at_mut(scratch_len); limbs_mul_mod_base_pow_n_minus_1(scratch, scratch_len, ds, qs, scratch_out); if d_len + i_len > scratch_len { let (rs_hi_lo, rs_hi_hi) = rs_hi.split_at(scratch_len - d_len); let carry_1 = limbs_sub_greater_in_place_left(scratch, rs_hi_hi); let carry_2 = limbs_cmp_same_length(rs_hi_lo, &scratch[d_len..]) == Less; if !carry_1 && carry_2 { assert!(!limbs_slice_add_limb_in_place(scratch, 1)); } else { assert_eq!(carry_1, carry_2); } } }} // # Worst-case complexity // $T(n, d) = O(n \log d \log\log d)$ // // $M(n) = O(d \log d)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // This is equivalent to `mpn_preinv_mu_div_qr` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1. fn limbs_div_mod_barrett_preinverted( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], mut is: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_eq!(rs.len(), d_len); let mut i_len = is.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let (ns_lo, ns_hi) = ns.split_at(q_len); let highest_q = limbs_cmp_same_length(ns_hi, ds) >= Equal; if highest_q { limbs_sub_same_length_to_out(rs, ns_hi, ds); } else { rs.copy_from_slice(ns_hi); } let scratch_len = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { 0 } else { limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1) }; let mut n = d_len - i_len; for (ns, qs) in ns_lo.rchunks(i_len).zip(qs.rchunks_mut(i_len)) { let chunk_len = ns.len(); if i_len != chunk_len { // last iteration is = &is[i_len - chunk_len..]; i_len = chunk_len; n = d_len - i_len; } let (rs_lo, rs_hi) = rs.split_at_mut(n); // Compute the next block of quotient limbs by multiplying the inverse by the upper part of // the partial remainder. let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(is.len())]; limbs_mul_same_length_to_out(scratch, rs_hi, is, &mut mul_scratch); // The inverse's most significant bit is implicit. assert!(!limbs_add_same_length_to_out( qs, &scratch[i_len..i_len << 1], rs_hi, )); // Compute the product of the quotient block and the divisor, to be subtracted from the // partial remainder combined with new limbs from the dividend. We only really need the low // d_len + 1 limbs. if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; limbs_mul_greater_to_out(scratch, ds, qs, &mut mul_scratch); } else { limbs_div_barrett_large_product(scratch, ds, qs, rs_hi, scratch_len, i_len); } let mut r = rs_hi[0].wrapping_sub(scratch[d_len]); // Subtract the product from the partial remainder combined with new limbs from the // dividend, generating a new partial remainder. let scratch = &mut scratch[..d_len]; let carry = if n == 0 { // Get next i_len limbs from n. limbs_sub_same_length_to_out(rs, ns, scratch) } else { let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); // Get next i_len limbs from n. let carry = limbs_sub_same_length_with_borrow_in_in_place_right( rs_lo, scratch_hi, limbs_sub_same_length_in_place_right(ns, scratch_lo), ); rs.copy_from_slice(scratch); carry }; // Check the remainder and adjust the quotient as needed. if carry { r.wrapping_sub_assign(1); } while r != 0 { // We loop 0 times with about 69% probability, 1 time with about 31% probability, and 2 // times with about 0.6% probability, if the inverse is computed as recommended. assert!(!limbs_slice_add_limb_in_place(qs, 1)); if limbs_sub_same_length_in_place_left(rs, ds) { r -= 1; } } if limbs_cmp_same_length(rs, ds) >= Equal { // This is executed with about 76% probability. assert!(!limbs_slice_add_limb_in_place(qs, 1)); limbs_sub_same_length_in_place_left(rs, ds); } } highest_q } // We distinguish 3 cases: // // - d_len < q_len: i_len = ceil(q_len / ceil(q_len / d_len)) // - d_len / 3 < q_len <= d_len: i_len = ceil(q_len / 2) // - q_len < d_len / 3: i_len = q_len // // In all cases we have i_len <= d_len. // // # Worst-case complexity // Constant time and additional memory. // // Result is O(`q_len`) // // This is equivalent to `mpn_mu_div_qr_choose_in` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1, where // `k == 0`. pub_const_crate_test! {limbs_div_mod_barrett_is_len(q_len: usize, d_len: usize) -> usize { let q_len_minus_1 = q_len - 1; if q_len > d_len { // Compute an inverse size that is a nice partition of the quotient. let b = q_len_minus_1 / d_len + 1; // ceil(q_len / d_len), number of blocks q_len_minus_1 / b + 1 // ceil(q_len / b) = ceil(q_len / ceil(q_len / d_len)) } else if 3 * q_len > d_len { (q_len_minus_1 >> 1) + 1 // b = 2 } else { q_len_minus_1 + 1 // b = 1 } }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mu_div_qr2` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1. pub_crate_test! {limbs_div_mod_barrett_helper( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_eq!(rs.len(), d_len); assert!(d_len > 1); assert!(n_len > d_len); let q_len = n_len - d_len; // Compute the inverse size. let i_len = limbs_div_mod_barrett_is_len(q_len, d_len); assert!(i_len <= d_len); let i_len_plus_1 = i_len + 1; let (is, scratch_hi) = scratch.split_at_mut(i_len_plus_1); // compute an approximate inverse on i_len + 1 limbs if d_len == i_len { let (scratch_lo, scratch_hi) = scratch_hi.split_at_mut(i_len_plus_1); let (scratch_first, scratch_lo_tail) = scratch_lo.split_first_mut().unwrap(); scratch_lo_tail.copy_from_slice(&ds[..i_len]); *scratch_first = 1; limbs_invert_approx(is, scratch_lo, scratch_hi); slice_move_left(is, 1); } else if limbs_add_limb_to_out(scratch_hi, &ds[d_len - i_len_plus_1..], 1) { slice_set_zero(&mut is[..i_len]); } else { let (scratch_lo, scratch_hi) = scratch_hi.split_at_mut(i_len_plus_1); limbs_invert_approx(is, scratch_lo, scratch_hi); slice_move_left(is, 1); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); limbs_div_mod_barrett_preinverted(qs, rs, ns, ds, scratch_lo, scratch_hi) }} // # Worst-case complexity // Constant time and additional memory. // // Result is O(`d_len`) // // This is equivalent to `mpn_preinv_mu_div_qr_itch` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1, but // `nn` is omitted from the arguments as it is unused. fn limbs_div_mod_barrett_preinverse_scratch_len(d_len: usize, is_len: usize) -> usize { let itch_local = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); let itch_out = limbs_mul_mod_base_pow_n_minus_1_scratch_len(itch_local, d_len, is_len); itch_local + itch_out } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_invertappr_itch` from `gmp-impl.h`, GMP 6.2.1. pub(crate) const fn limbs_invert_approx_scratch_len(is_len: usize) -> usize { is_len << 1 } // # Worst-case complexity // Constant time and additional memory. // // Result is O(`n_len`) // // This is equivalent to `mpn_mu_div_qr_itch` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1, where // `mua_k == 0`. pub_crate_test! {limbs_div_mod_barrett_scratch_len(n_len: usize, d_len: usize) -> usize { let is_len = limbs_div_mod_barrett_is_len(n_len - d_len, d_len); let preinverse_len = limbs_div_mod_barrett_preinverse_scratch_len(d_len, is_len); // 3 * is_len + 4 let inv_approx_len = limbs_invert_approx_scratch_len(is_len + 1) + is_len + 2; assert!(preinverse_len >= inv_approx_len); is_len + preinverse_len }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. pub_test! {limbs_div_mod_barrett_large_helper( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); let q_len = qs.len(); let q_len_plus_one = q_len + 1; let n = n_len - q_len - q_len_plus_one; // 2 * d_len - n_len - 1 let (ns_lo, ns_hi) = ns.split_at(n); let (ds_lo, ds_hi) = ds.split_at(d_len - q_len_plus_one); let (rs_lo, rs_hi) = rs.split_at_mut(n); let rs_hi = &mut rs_hi[..q_len_plus_one]; let mut highest_q = limbs_div_mod_barrett_helper(qs, rs_hi, ns_hi, ds_hi, scratch); // Multiply the quotient by the divisor limbs ignored above. The product is d_len - 1 limbs // long. let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ds_lo.len(), qs.len())]; limbs_mul_to_out(scratch, ds_lo, qs, &mut mul_scratch); let (scratch_last, scratch_init) = scratch[..d_len].split_last_mut().unwrap(); *scratch_last = Limb::from( highest_q && limbs_slice_add_same_length_in_place_left(&mut scratch_init[q_len..], ds_lo), ); let (scratch_lo, scratch_hi) = scratch.split_at(n); let scratch_hi = &scratch_hi[..q_len_plus_one]; if limbs_sub_same_length_with_borrow_in_in_place_left( rs_hi, scratch_hi, limbs_sub_same_length_to_out(rs_lo, ns_lo, scratch_lo), ) { if limbs_sub_limb_in_place(qs, 1) { assert!(highest_q); highest_q = false; } limbs_slice_add_same_length_in_place_left(&mut rs[..d_len], ds); } highest_q }} // Block-wise Barrett division. The idea of the algorithm used herein is to compute a smaller // inverted value than used in the standard Barrett algorithm, and thus save time in the Newton // iterations, and pay just a small price when using the inverted value for developing quotient // bits. This algorithm was presented at ICMS 2006. // // `ns` must have length at least 3, `ds` must have length at least 2 and be no longer than `ns`, // and the most significant bit of `ds` must be set. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 2, `ns.len()` is less than `ds.len()`, `qs` has length // less than `ns.len()` - `ds.len()`, `scratch` is too short, or the last limb of `ds` does not have // its highest bit set. // // This is equivalent to `mpn_mu_div_qr` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1. pub_test! {limbs_div_mod_barrett( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; // Test whether 2 * d_len - n_len > MU_DIV_QR_SKEW_THRESHOLD if d_len <= q_len + MU_DIV_QR_SKEW_THRESHOLD { limbs_div_mod_barrett_helper(qs, &mut rs[..d_len], ns, ds, scratch) } else { limbs_div_mod_barrett_large_helper(qs, rs, ns, ds, scratch) } }} // `ds` must have length 2, `ns` must have length at least 2, `qs` must have length at least // `ns.len() - 2`, `rs` must have length at least 2, and the most-significant limb of `ds` must be // nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_div_mod_by_two_limb(qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { let n_len = ns.len(); let ds_1 = ds[1]; let bits = LeadingZeros::leading_zeros(ds_1); if bits == 0 { let mut ns = ns.to_vec(); // always store n_len - 1 quotient limbs qs[n_len - 2] = Limb::from(limbs_div_mod_by_two_limb_normalized(qs, &mut ns, ds)); rs[0] = ns[0]; rs[1] = ns[1]; } else { let ds_0 = ds[0]; let cobits = Limb::WIDTH - bits; let mut ns_shifted = vec![0; n_len + 1]; let ns_shifted = &mut ns_shifted; let carry = limbs_shl_to_out(ns_shifted, ns, bits); let ds_shifted = &mut [ds_0 << bits, (ds_1 << bits) | (ds_0 >> cobits)]; if carry == 0 { // always store n_len - 1 quotient limbs qs[n_len - 2] = Limb::from(limbs_div_mod_by_two_limb_normalized( qs, &mut ns_shifted[..n_len], ds_shifted, )); } else { ns_shifted[n_len] = carry; limbs_div_mod_by_two_limb_normalized(qs, ns_shifted, ds_shifted); } let ns_shifted_1 = ns_shifted[1]; rs[0] = (ns_shifted[0] >> bits) | (ns_shifted_1 << cobits); rs[1] = ns_shifted_1 >> bits; } } // TODO tune pub(crate) const MUPI_DIV_QR_THRESHOLD: usize = 74; // # Worst-case complexity // Constant time and additional memory. fn limbs_div_mod_dc_condition(n_len: usize, d_len: usize) -> bool { let n_64 = n_len as f64; let d_64 = d_len as f64; d_len < MUPI_DIV_QR_THRESHOLD || n_len < MU_DIV_QR_THRESHOLD << 1 || fma!( ((MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD) << 1) as f64, d_64, MUPI_DIV_QR_THRESHOLD as f64 * n_64 ) > d_64 * n_64 } // This function is optimized for the case when the numerator has at least twice the length of the // denominator. // // `ds` must have length at least 3, `ns` must be at least as long as `ds`, `qs` must have length at // least `ns.len() - ds.len() + 1`, `rs` must have the same length as `ds`, and the most- // significant limb of `ds` must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. fn limbs_div_mod_unbalanced( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], adjusted_n_len: usize, ) { let mut n_len = ns.len(); let d_len = ds.len(); qs[n_len - d_len] = 0; // zero high quotient limb let mut ds_shifted_vec; let ds_shifted: &[Limb]; let mut ns_shifted_vec = vec![0; n_len + 1]; let ns_shifted = &mut ns_shifted_vec; let bits = LeadingZeros::leading_zeros(*ds.last().unwrap()); if bits == 0 { ds_shifted = ds; ns_shifted[..n_len].copy_from_slice(ns); } else { // normalize divisor ds_shifted_vec = vec![0; d_len]; limbs_shl_to_out(&mut ds_shifted_vec, ds, bits); ds_shifted = &ds_shifted_vec; let (ns_shifted_last, ns_shifted_init) = ns_shifted.split_last_mut().unwrap(); *ns_shifted_last = limbs_shl_to_out(ns_shifted_init, ns, bits); } n_len = adjusted_n_len; let d_inv = limbs_two_limb_inverse_helper(ds_shifted[d_len - 1], ds_shifted[d_len - 2]); let ns_shifted = &mut ns_shifted[..n_len]; if d_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, ns_shifted, ds_shifted, d_inv); let ns_shifted = &ns_shifted[..d_len]; if bits == 0 { rs.copy_from_slice(ns_shifted); } else { limbs_shr_to_out(rs, ns_shifted, bits); } } else if limbs_div_mod_dc_condition(n_len, d_len) { limbs_div_mod_divide_and_conquer(qs, ns_shifted, ds_shifted, d_inv); let ns_shifted = &ns_shifted[..d_len]; if bits == 0 { rs.copy_from_slice(ns_shifted); } else { limbs_shr_to_out(rs, ns_shifted, bits); } } else { let scratch_len = limbs_div_mod_barrett_scratch_len(n_len, d_len); let mut scratch = vec![0; scratch_len]; limbs_div_mod_barrett(qs, rs, ns_shifted, ds_shifted, &mut scratch); if bits != 0 { limbs_slice_shr_in_place(rs, bits); } } } // The numerator must have less than twice the length of the denominator. // // Problem: // // Divide a numerator N with `n_len` limbs by a denominator D with `d_len` limbs, forming a quotient // of `q_len` = `n_len` - `d_len` + 1 limbs. When `q_len` is small compared to `d_len`, conventional // division algorithms perform poorly. We want an algorithm that has an expected running time that // is dependent only on `q_len`. // // Algorithm (very informally stated): // // 1) Divide the 2 * `q_len` most significant limbs from the numerator by the `q_len` most- // significant limbs from the denominator. Call the result `qest`. This is either the correct // quotient, or 1 or 2 too large. Compute the remainder from the division. // // 2) Is the most significant limb from the remainder < p, where p is the product of the most- // significant limb from the quotient and the next(d)? (Next(d) denotes the next ignored limb from // the denominator.) If it is, decrement `qest`, and adjust the remainder accordingly. // // 3) Is the remainder >= `qest`? If it is, `qest` is the desired quotient. The algorithm // terminates. // // 4) Subtract `qest` * next(d) from the remainder. If there is borrow out, decrement `qest`, and // adjust the remainder accordingly. // // 5) Skip one word from the denominator (i.e., let next(d) denote the next less significant limb). // // `ds` must have length at least 3, `ns` must be at least as long as `ds` but no more than twice as // long, `qs` must have length at least `ns.len() - ds.len() + 1`,`rs` must have the same length as // `ds`, and the most-significant limb of `ds` must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub(crate) fn limbs_div_mod_balanced( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], adjust: bool, ) { let n_len = ns.len(); let d_len = ds.len(); let mut q_len = n_len - d_len; assert!(d_len >= q_len); qs[q_len] = 0; // zero high quotient limb if adjust { q_len += 1; } else if q_len == 0 { rs.copy_from_slice(&ns[..d_len]); return; } let q_len = q_len; // `i_len` is the (at least partially) ignored number of limbs. let i_len = d_len - q_len; // Normalize the denominator by shifting it to the left such that its most significant bit is // set. Then shift the numerator the same amount, to mathematically preserve the quotient. let bits = LeadingZeros::leading_zeros(ds[d_len - 1]); let cobits = Limb::WIDTH - bits; let q_len_2 = q_len << 1; let m = n_len - q_len_2; let mut ns_shifted_vec = vec![0; q_len_2 + 1]; let mut ds_shifted_vec; let ds_shifted: &[Limb]; let ds_hi = &ds[i_len..]; let ds_lo_last = ds[i_len - 1]; let carry = if bits == 0 { ds_shifted = ds_hi; ns_shifted_vec[..q_len_2].copy_from_slice(&ns[m..]); 0 } else { ds_shifted_vec = vec![0; q_len]; limbs_shl_to_out(&mut ds_shifted_vec, ds_hi, bits); ds_shifted_vec[0] |= ds_lo_last >> cobits; ds_shifted = &ds_shifted_vec; let carry = limbs_shl_to_out(&mut ns_shifted_vec, &ns[m..], bits); if !adjust { ns_shifted_vec[0] |= ns[m - 1] >> cobits; } carry }; let ns_shifted = if adjust { ns_shifted_vec[q_len_2] = carry; &mut ns_shifted_vec[1..] } else { &mut ns_shifted_vec }; // Get an approximate quotient using the extracted operands. if q_len == 1 { (qs[0], ns_shifted[0]) = Limb::xx_div_mod_y_to_qr(ns_shifted[1], ns_shifted[0], ds_shifted[0]); } else if q_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, ns_shifted, ds_shifted); } else { let ns_shifted = &mut ns_shifted[..q_len_2]; let d_inv = limbs_two_limb_inverse_helper(ds_shifted[q_len - 1], ds_shifted[q_len - 2]); if q_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, ns_shifted, ds_shifted, d_inv); } else if q_len < MU_DIV_QR_THRESHOLD { limbs_div_mod_divide_and_conquer(qs, ns_shifted, ds_shifted, d_inv); } else { let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(q_len_2, q_len)]; limbs_div_mod_barrett(qs, rs, ns_shifted, ds_shifted, &mut scratch); ns_shifted[..q_len].copy_from_slice(&rs[..q_len]); } } // Multiply the first ignored divisor limb by the most significant quotient limb. If that // product is > the partial remainder's most significant limb, we know the quotient is too // large. This test quickly catches most cases where the quotient is too large; it catches all // cases where the quotient is 2 too large. let mut r_len = q_len; let mut x = ds_lo_last << bits; if i_len >= 2 { x |= ds[i_len - 2] >> 1 >> (!bits & Limb::WIDTH_MASK); } if ns_shifted[q_len - 1] < (DoubleLimb::from(x) * DoubleLimb::from(qs[q_len - 1])).upper_half() { assert!(!limbs_sub_limb_in_place(qs, 1)); let carry = limbs_slice_add_same_length_in_place_left(&mut ns_shifted[..q_len], ds_shifted); if carry { // The partial remainder is safely large. ns_shifted[q_len] = 1; r_len += 1; } } let mut q_too_large = false; let mut do_extra_cleanup = true; let mut scratch = vec![0; d_len]; let mut i_len_alt = i_len; let qs_lo = &mut qs[..q_len]; if bits != 0 { // Append the partially used numerator limb to the partial remainder. let carry_1 = limbs_slice_shl_in_place(&mut ns_shifted[..r_len], cobits); let mask = Limb::MAX >> bits; ns_shifted[0] |= ns[i_len - 1] & mask; // Update partial remainder with partially used divisor limb. let (ns_shifted_last, ns_shifted_init) = ns_shifted[..=q_len].split_last_mut().unwrap(); let carry_2 = limbs_sub_mul_limb_same_length_in_place_left( ns_shifted_init, qs_lo, ds[i_len - 1] & mask, ); if q_len == r_len { (*ns_shifted_last, q_too_large) = carry_1.overflowing_sub(carry_2); r_len += 1; } else { assert!(*ns_shifted_last >= carry_2); ns_shifted_last.wrapping_sub_assign(carry_2); } i_len_alt -= 1; } // True: partial remainder now is neutral, i.e., it is not shifted up. if i_len_alt == 0 { rs.copy_from_slice(&ns_shifted[..r_len]); do_extra_cleanup = false; } else { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(qs_lo.len(), i_len_alt)]; limbs_mul_to_out(&mut scratch, qs_lo, &ds[..i_len_alt], &mut mul_scratch); } if do_extra_cleanup { let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len_alt); q_too_large |= limbs_sub_greater_in_place_left(&mut ns_shifted[..r_len], &scratch_hi[..q_len]); let (rs_lo, rs_hi) = rs.split_at_mut(i_len_alt); let rs_hi_len = rs_hi.len(); rs_hi.copy_from_slice(&ns_shifted[..rs_hi_len]); q_too_large |= limbs_sub_same_length_to_out(rs_lo, &ns[..i_len_alt], scratch_lo) && limbs_sub_limb_in_place(&mut rs_hi[..min(rs_hi_len, r_len)], 1); } if q_too_large { assert!(!limbs_sub_limb_in_place(qs, 1)); limbs_slice_add_same_length_in_place_left(rs, ds); } } // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, returning the quotient and remainder. The quotient has `ns.len() - // ds.len() + 1` limbs and the remainder `ds.len()` limbs. // // `ns` must be at least as long as `ds` and `ds` must have length at least 2 and its most // significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` has length less than 2, or the most-significant limb of // `ds` is zero. // // This is equivalent to `mpn_tdiv_qr` from `mpn/generic/tdiv_qr.c`, GMP 6.2.1, where `dn > 1` and // `qp` and `rp` are returned. pub_test! {limbs_div_mod(ns: &[Limb], ds: &[Limb]) -> (Vec, Vec) { let d_len = ds.len(); let mut qs = vec![0; ns.len() - d_len + 1]; let mut rs = vec![0; d_len]; limbs_div_mod_to_out(&mut qs, &mut rs, ns, ds); (qs, rs) }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ns.len() - ds.len() + 1` limbs of the quotient to `qs` and // the `ds.len()` limbs of the remainder to `rs`. // // `ns` must be at least as long as `ds`, `qs` must have length at least `ns.len() - ds.len() + 1`, // `rs` must be at least as long as `ds`, and `ds` must have length at least 2 and its most // significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `qs` or `rs` are too short, `ns` is shorter than `ds`, `ds` has length less than 2, or // the most-significant limb of `ds` is zero. // // This is equivalent to `mpn_tdiv_qr` from `mpn/generic/tdiv_qr.c`, GMP 6.2.1, where `dn > 1`. pub_crate_test! {limbs_div_mod_to_out(qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len > 1); assert!(n_len >= d_len); assert!(qs.len() > n_len - d_len); let rs = &mut rs[..d_len]; let ds_last = *ds.last().unwrap(); assert!(ds_last != 0); if d_len == 2 { limbs_div_mod_by_two_limb(qs, rs, ns, ds); } else { // conservative tests for quotient size let adjust = ns[n_len - 1] >= ds_last; let adjusted_n_len = if adjust { n_len + 1 } else { n_len }; if adjusted_n_len < d_len << 1 { limbs_div_mod_balanced(qs, rs, ns, ds, adjust); } else { limbs_div_mod_unbalanced(qs, rs, ns, ds, adjusted_n_len); } } }} // TODO improve! // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_crate_test! {limbs_div_mod_qs_to_out_rs_to_ns(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) { let ns_copy = ns.to_vec(); limbs_div_mod_to_out(qs, ns, &ns_copy, ds); }} impl Natural { fn div_mod_limb_ref(&self, other: Limb) -> (Self, Limb) { match (self, other) { (_, 0) => panic!("division by zero"), (n, 1) => (n.clone(), 0), (Self(Small(small)), other) => { let (q, r) = small.div_rem(other); (Self(Small(q)), r) } (Self(Large(limbs)), other) => { let (qs, r) = limbs_div_limb_mod(limbs, other); (Self::from_owned_limbs_asc(qs), r) } } } pub_test! {div_assign_mod_limb(&mut self, other: Limb) -> Limb { match (&mut *self, other) { (_, 0) => panic!("division by zero"), (_, 1) => 0, (Natural(Small(small)), other) => small.div_assign_rem(other), (Natural(Large(limbs)), other) => { let r = limbs_div_limb_in_place_mod(limbs, other); self.trim(); r } } }} } impl DivMod for Natural { type DivOutput = Self; type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and returning the /// quotient and remainder. The quotient is rounded towards negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .div_mod(Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .div_mod(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_mod(mut self, other: Self) -> (Self, Self) { let r = self.div_assign_mod(other); (self, r) } } impl<'a> DivMod<&'a Self> for Natural { type DivOutput = Self; type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning the quotient and remainder. The quotient is rounded towards negative /// infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .div_mod(&Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .div_mod(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_mod(mut self, other: &'a Self) -> (Self, Self) { let r = self.div_assign_mod(other); (self, r) } } impl DivMod for &Natural { type DivOutput = Natural; type ModOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning the quotient and remainder. The quotient is rounded towards negative /// infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .div_mod(Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .div_mod(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` fn div_mod(self, mut other: Natural) -> (Natural, Natural) { if *self == other { return (Natural::ONE, Natural::ZERO); } match (self, &mut other) { (_, &mut Natural::ZERO) => panic!("division by zero"), (n, &mut Natural::ONE) => (n.clone(), Natural::ZERO), (n, &mut Natural(Small(d))) => { let (q, r) = n.div_mod_limb_ref(d); (q, Natural(Small(r))) } (Natural(Small(_)), _) => (Natural::ZERO, self.clone()), (Natural(Large(ns)), Natural(Large(ds))) => { if ns.len() < ds.len() { (Natural::ZERO, self.clone()) } else { let (qs, mut rs) = limbs_div_mod(ns, ds); swap(&mut rs, ds); other.trim(); (Natural::from_owned_limbs_asc(qs), other) } } } } } impl DivMod<&Natural> for &Natural { type DivOutput = Natural; type ModOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and returning the /// quotient and remainder. The quotient is rounded towards negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .div_mod(&Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .div_mod(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` fn div_mod(self, other: &Natural) -> (Natural, Natural) { if self == other { return (Natural::ONE, Natural::ZERO); } match (self, other) { (_, &Natural::ZERO) => panic!("division by zero"), (n, &Natural::ONE) => (n.clone(), Natural::ZERO), (n, Natural(Small(d))) => { let (q, r) = n.div_mod_limb_ref(*d); (q, Natural(Small(r))) } (Natural(Small(_)), _) => (Natural::ZERO, self.clone()), (Natural(Large(ns)), Natural(Large(ds))) => { if ns.len() < ds.len() { (Natural::ZERO, self.clone()) } else { let (qs, rs) = limbs_div_mod(ns, ds); ( Natural::from_owned_limbs_asc(qs), Natural::from_owned_limbs_asc(rs), ) } } } } } impl DivAssignMod for Natural { type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards /// negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.div_assign_mod(Natural::from(10u32)), 3); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.div_assign_mod(Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// assert_eq!(x, 810000006723u64); /// ``` fn div_assign_mod(&mut self, mut other: Self) -> Self { if *self == other { *self = Self::ONE; return Self::ZERO; } match (&mut *self, &mut other) { (_, &mut Self::ZERO) => panic!("division by zero"), (_, &mut Self::ONE) => Self::ZERO, (n, &mut Self(Small(d))) => Self(Small(n.div_assign_mod_limb(d))), (Self(Small(_)), _) => { let mut r = Self::ZERO; swap(self, &mut r); r } (Self(Large(ns)), Self(Large(ds))) => { if ns.len() < ds.len() { let mut r = Self::ZERO; swap(self, &mut r); r } else { let (mut qs, mut rs) = limbs_div_mod(ns, ds); swap(&mut qs, ns); swap(&mut rs, ds); self.trim(); other.trim(); other } } } } } impl<'a> DivAssignMod<&'a Self> for Natural { type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards /// negative infinity. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivAssignMod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.div_assign_mod(&Natural::from(10u32)), 3); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.div_assign_mod(&Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// assert_eq!(x, 810000006723u64); /// ``` fn div_assign_mod(&mut self, other: &'a Self) -> Self { if self == other { *self = Self::ONE; return Self::ZERO; } match (&mut *self, other) { (_, &Self::ZERO) => panic!("division by zero"), (_, &Self::ONE) => Self::ZERO, (_, Self(Small(d))) => Self(Small(self.div_assign_mod_limb(*d))), (Self(Small(_)), _) => { let mut r = Self::ZERO; swap(self, &mut r); r } (Self(Large(ns)), Self(Large(ds))) => { if ns.len() < ds.len() { let mut r = Self::ZERO; swap(self, &mut r); r } else { let (mut qs, rs) = limbs_div_mod(ns, ds); swap(&mut qs, ns); self.trim(); Self::from_owned_limbs_asc(rs) } } } } } impl DivRem for Natural { type DivOutput = Self; type RemOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and returning the /// quotient and remainder. The quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// For [`Natural`]s, `div_rem` is equivalent to /// [`div_mod`](malachite_base::num::arithmetic::traits::DivMod::div_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .div_rem(Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .div_rem(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_rem(self, other: Self) -> (Self, Self) { self.div_mod(other) } } impl<'a> DivRem<&'a Self> for Natural { type DivOutput = Self; type RemOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning the quotient and remainder. The quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// For [`Natural`]s, `div_rem` is equivalent to /// [`div_mod`](malachite_base::num::arithmetic::traits::DivMod::div_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// Natural::from(23u32) /// .div_rem(&Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .div_rem(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_rem(self, other: &'a Self) -> (Self, Self) { self.div_mod(other) } } impl DivRem for &Natural { type DivOutput = Natural; type RemOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning the quotient and remainder. The quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// For [`Natural`]s, `div_rem` is equivalent to /// [`div_mod`](malachite_base::num::arithmetic::traits::DivMod::div_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .div_rem(Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .div_rem(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_rem(self, other: Natural) -> (Natural, Natural) { self.div_mod(other) } } impl DivRem<&Natural> for &Natural { type DivOutput = Natural; type RemOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and returning the /// quotient and remainder. The quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ). /// $$ /// /// For [`Natural`]s, `div_rem` is equivalent to /// [`div_mod`](malachite_base::num::arithmetic::traits::DivMod::div_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .div_rem(&Natural::from(10u32)) /// .to_debug_string(), /// "(2, 3)" /// ); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .div_rem(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006723, 530068894399)" /// ); /// ``` #[inline] fn div_rem(self, other: &Natural) -> (Natural, Natural) { self.div_mod(other) } } impl DivAssignRem for Natural { type RemOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and returning the remainder. The quotient is rounded towards zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `div_assign_rem` is equivalent to /// [`div_assign_mod`](malachite_base::num::arithmetic::traits::DivAssignMod::div_assign_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivAssignRem; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.div_assign_rem(Natural::from(10u32)), 3); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.div_assign_rem(Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// assert_eq!(x, 810000006723u64); /// ``` #[inline] fn div_assign_rem(&mut self, other: Self) -> Self { self.div_assign_mod(other) } } impl<'a> DivAssignRem<&'a Self> for Natural { type RemOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference and returning the remainder. The quotient is rounded towards /// zero. /// /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor, /// $$ /// $$ /// x \gets \left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `div_assign_rem` is equivalent to /// [`div_assign_mod`](malachite_base::num::arithmetic::traits::DivAssignMod::div_assign_mod). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivAssignRem; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.div_assign_rem(&Natural::from(10u32)), 3); /// assert_eq!(x, 2); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.div_assign_rem(&Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// assert_eq!(x, 810000006723u64); /// ``` #[inline] fn div_assign_rem(&mut self, other: &'a Self) -> Self { self.div_assign_mod(other) } } impl CeilingDivNegMod for Natural { type DivOutput = Self; type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and returning the ceiling /// of the quotient and the remainder of the negative of the first [`Natural`] divided by the /// second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// y\left \lceil \frac{x}{y} \right \rceil - x \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivNegMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!( /// Natural::from(23u32) /// .ceiling_div_neg_mod(Natural::from(10u32)) /// .to_debug_string(), /// "(3, 7)" /// ); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .ceiling_div_neg_mod(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006724, 704498996588)" /// ); /// ``` #[inline] fn ceiling_div_neg_mod(mut self, other: Self) -> (Self, Self) { let r = self.ceiling_div_assign_neg_mod(other); (self, r) } } impl<'a> CeilingDivNegMod<&'a Self> for Natural { type DivOutput = Self; type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning the ceiling of the quotient and the remainder of the negative of the /// first [`Natural`] divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// y\left \lceil \frac{x}{y} \right \rceil - x \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivNegMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!( /// Natural::from(23u32) /// .ceiling_div_neg_mod(&Natural::from(10u32)) /// .to_debug_string(), /// "(3, 7)" /// ); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .ceiling_div_neg_mod(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006724, 704498996588)" /// ); /// ``` #[inline] fn ceiling_div_neg_mod(mut self, other: &'a Self) -> (Self, Self) { let r = self.ceiling_div_assign_neg_mod(other); (self, r) } } impl CeilingDivNegMod for &Natural { type DivOutput = Natural; type ModOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning the ceiling of the quotient and the remainder of the negative of the /// first [`Natural`] divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// y\left \lceil \frac{x}{y} \right \rceil - x \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivNegMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .ceiling_div_neg_mod(Natural::from(10u32)) /// .to_debug_string(), /// "(3, 7)" /// ); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .ceiling_div_neg_mod(Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006724, 704498996588)" /// ); /// ``` fn ceiling_div_neg_mod(self, other: Natural) -> (Natural, Natural) { let (q, r) = self.div_mod(&other); if r == 0 { (q, r) } else { (q.add_limb(1), other - r) } } } impl CeilingDivNegMod<&Natural> for &Natural { type DivOutput = Natural; type ModOutput = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and returning the /// ceiling of the quotient and the remainder of the negative of the first [`Natural`] divided /// by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space /// y\left \lceil \frac{x}{y} \right \rceil - x \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivNegMod; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!( /// (&Natural::from(23u32)) /// .ceiling_div_neg_mod(&Natural::from(10u32)) /// .to_debug_string(), /// "(3, 7)" /// ); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .ceiling_div_neg_mod(&Natural::from_str("1234567890987").unwrap()) /// .to_debug_string(), /// "(810000006724, 704498996588)" /// ); /// ``` fn ceiling_div_neg_mod(self, other: &Natural) -> (Natural, Natural) { let (q, r) = self.div_mod(other); if r == 0 { (q, r) } else { (q.add_limb(1), other - r) } } } impl CeilingDivAssignNegMod for Natural { type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and returning the remainder of the negative of the first number /// divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivAssignNegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.ceiling_div_assign_neg_mod(Natural::from(10u32)), 7); /// assert_eq!(x, 3); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.ceiling_div_assign_neg_mod(Natural::from_str("1234567890987").unwrap()), /// 704498996588u64, /// ); /// assert_eq!(x, 810000006724u64); /// ``` fn ceiling_div_assign_neg_mod(&mut self, other: Self) -> Self { let r = self.div_assign_mod(&other); if r == 0 { Self::ZERO } else { *self += Self::ONE; other - r } } } impl<'a> CeilingDivAssignNegMod<&'a Self> for Natural { type ModOutput = Self; /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference and returning the remainder of the negative of the first number /// divided by the second. /// /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x, /// $$ /// $$ /// x \gets \left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CeilingDivAssignNegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// let mut x = Natural::from(23u32); /// assert_eq!(x.ceiling_div_assign_neg_mod(&Natural::from(10u32)), 7); /// assert_eq!(x, 3); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// assert_eq!( /// x.ceiling_div_assign_neg_mod(&Natural::from_str("1234567890987").unwrap()), /// 704498996588u64, /// ); /// assert_eq!(x, 810000006724u64); /// ``` fn ceiling_div_assign_neg_mod(&mut self, other: &'a Self) -> Self { let r = self.div_assign_mod(other); if r == 0 { Self::ZERO } else { *self += Self::ONE; other - r } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ DivAssignMod, DivMod, DivRound, DivRoundAssign, Parity, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // quotient limbs of a `Limb` divided by the `Natural` and rounded according to a specified // `RoundingMode`. The limb slice must have at least two elements and cannot have any trailing // zeros. An `Ordering` is also returned, indicating whether the returned value is less than, equal // to, or greater than the exact value. // // This function returns a `None` iff the rounding mode is `Exact` but the remainder of the division // would be nonzero. // // Note that this function may only return `None`, `Some((0, Less))`, or `Some((1, Greater))` // because of the restrictions placed on the input slice. // // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_limb_div_round_limbs(n: Limb, ds: &[Limb], rm: RoundingMode) -> Option<(Limb, Ordering)> { if n == 0 { Some((0, Equal)) } else { match rm { Down | Floor => Some((0, Less)), Up | Ceiling => Some((1, Greater)), Exact => None, // 1 if 2 * n > Natural::from_limbs_asc(ds); otherwise, 0 Nearest => Some( if ds.len() == 2 && ds[1] == 1 && n.get_highest_bit() && (n << 1) > ds[0] { (1, Greater) } else { (0, Less) }, ), } } }} // Compares 2x and y pub(crate) fn double_cmp(x: &Natural, y: &Natural) -> Ordering { (x.significant_bits() + 1) .cmp(&y.significant_bits()) .then_with(|| x.cmp_normalized(y)) } // assumes r != 0 fn div_round_nearest(q: Natural, r: &Natural, d: &Natural) -> (Natural, Ordering) { let compare = double_cmp(r, d); if compare == Greater || compare == Equal && q.odd() { (q.add_limb(1), Greater) } else { (q, Less) } } // assumes r != 0 fn div_round_assign_nearest(q: &mut Natural, r: &Natural, d: &Natural) -> Ordering { let compare = double_cmp(r, d); if compare == Greater || compare == Equal && q.odd() { *q += Natural::ONE; Greater } else { Less } } impl DivRound for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and rounding according to /// a specified rounding mode. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).div_round(Natural::from(4u32), Down), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .div_round(Natural::from(3u32), Floor), /// (Natural::from(333333333333u64), Less) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(Natural::from(4u32), Up), /// (Natural::from(3u32), Greater) /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .div_round(Natural::from(3u32), Ceiling), /// (Natural::from(333333333334u64), Greater) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(Natural::from(5u32), Exact), /// (Natural::from(2u32), Equal) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(Natural::from(3u32), Nearest), /// (Natural::from(3u32), Less) /// ); /// assert_eq!( /// Natural::from(20u32).div_round(Natural::from(3u32), Nearest), /// (Natural::from(7u32), Greater) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(Natural::from(4u32), Nearest), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// Natural::from(14u32).div_round(Natural::from(4u32), Nearest), /// (Natural::from(4u32), Greater) /// ); /// ``` #[inline] fn div_round(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.div_round_assign(other, rm); (self, o) } } impl<'a> DivRound<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and rounding according to a specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).div_round(&Natural::from(4u32), Down), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .div_round(&Natural::from(3u32), Floor), /// (Natural::from(333333333333u64), Less) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(&Natural::from(4u32), Up), /// (Natural::from(3u32), Greater) /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .div_round(&Natural::from(3u32), Ceiling), /// (Natural::from(333333333334u64), Greater) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(&Natural::from(5u32), Exact), /// (Natural::from(2u32), Equal) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(&Natural::from(3u32), Nearest), /// (Natural::from(3u32), Less) /// ); /// assert_eq!( /// Natural::from(20u32).div_round(&Natural::from(3u32), Nearest), /// (Natural::from(7u32), Greater) /// ); /// assert_eq!( /// Natural::from(10u32).div_round(&Natural::from(4u32), Nearest), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// Natural::from(14u32).div_round(&Natural::from(4u32), Nearest), /// (Natural::from(4u32), Greater) /// ); /// ``` #[inline] fn div_round(mut self, other: &'a Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.div_round_assign(other, rm); (self, o) } } impl DivRound for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and rounding according to a specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).div_round(Natural::from(4u32), Down), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)).div_round(Natural::from(3u32), Floor), /// (Natural::from(333333333333u64), Less) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(Natural::from(4u32), Up), /// (Natural::from(3u32), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)).div_round(Natural::from(3u32), Ceiling), /// (Natural::from(333333333334u64), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(Natural::from(5u32), Exact), /// (Natural::from(2u32), Equal) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(Natural::from(3u32), Nearest), /// (Natural::from(3u32), Less) /// ); /// assert_eq!( /// (&Natural::from(20u32)).div_round(Natural::from(3u32), Nearest), /// (Natural::from(7u32), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(Natural::from(4u32), Nearest), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// (&Natural::from(14u32)).div_round(Natural::from(4u32), Nearest), /// (Natural::from(4u32), Greater) /// ); /// ``` fn div_round(self, other: Natural, rm: RoundingMode) -> (Natural, Ordering) { let (q, r) = self.div_mod(&other); if r == 0 { (q, Equal) } else { match rm { Floor | Down => (q, Less), Ceiling | Up => (q.add_limb(1), Greater), Exact => panic!("Division is not exact"), Nearest => div_round_nearest(q, &r, &other), } } } } impl DivRound<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and rounding /// according to a specified rounding mode. An [`Ordering`] is also returned, indicating whether /// the returned value is less than, equal to, or greater than the exact value. /// /// Let $q = \frac{x}{y}$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $$ /// g(x, y, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor. /// $$ /// /// $$ /// g(x, y, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil. /// $$ /// /// $$ /// g(x, y, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $g(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then $f(x, y, r) = (g(x, y, r), \operatorname{cmp}(g(x, y, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRound, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).div_round(&Natural::from(4u32), Down), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)).div_round(&Natural::from(3u32), Floor), /// (Natural::from(333333333333u64), Less) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(&Natural::from(4u32), Up), /// (Natural::from(3u32), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)).div_round(&Natural::from(3u32), Ceiling), /// (Natural::from(333333333334u64), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(&Natural::from(5u32), Exact), /// (Natural::from(2u32), Equal) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(&Natural::from(3u32), Nearest), /// (Natural::from(3u32), Less) /// ); /// assert_eq!( /// (&Natural::from(20u32)).div_round(&Natural::from(3u32), Nearest), /// (Natural::from(7u32), Greater) /// ); /// assert_eq!( /// (&Natural::from(10u32)).div_round(&Natural::from(4u32), Nearest), /// (Natural::from(2u32), Less) /// ); /// assert_eq!( /// (&Natural::from(14u32)).div_round(&Natural::from(4u32), Nearest), /// (Natural::from(4u32), Greater) /// ); /// ``` fn div_round(self, other: &Natural, rm: RoundingMode) -> (Natural, Ordering) { let (q, r) = self.div_mod(other); if r == 0 { (q, Equal) } else { match rm { Floor | Down => (q, Less), Ceiling | Up => (q.add_limb(1), Greater), Exact => panic!("Division is not exact: {self} / {other}"), Nearest => div_round_nearest(q, &r, other), } } } } impl DivRoundAssign for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and rounding according to a specified rounding mode. An /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal to, or /// greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRoundAssign, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(Natural::from(4u32), Down), Less); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(Natural::from(3u32), Floor), Less); /// assert_eq!(n, 333333333333u64); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(Natural::from(4u32), Up), Greater); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Natural::from(3u32), Ceiling), Greater); /// assert_eq!(n, 333333333334u64); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(Natural::from(5u32), Exact), Equal); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(Natural::from(3u32), Nearest), Less); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(20u32); /// assert_eq!(n.div_round_assign(Natural::from(3u32), Nearest), Greater); /// assert_eq!(n, 7); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(Natural::from(4u32), Nearest), Less); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(14u32); /// assert_eq!(n.div_round_assign(Natural::from(4u32), Nearest), Greater); /// assert_eq!(n, 4); /// ``` fn div_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { let r = self.div_assign_mod(&other); if r == 0 { Equal } else { match rm { Floor | Down => Less, Ceiling | Up => { *self += Self::ONE; Greater } Exact => panic!("Division is not exact"), Nearest => div_round_assign_nearest(self, &r, &other), } } } } impl<'a> DivRoundAssign<&'a Self> for Natural { /// Divides a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference and rounding according to a specified rounding mode. An /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal to, or /// greater than the exact value. /// /// See the [`DivRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero, or if `rm` is `Exact` but `self` is not divisible by `other`. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::{DivRoundAssign, Pow}; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(&Natural::from(4u32), Down), Less); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Natural::from(3u32), Floor), Less); /// assert_eq!(n, 333333333333u64); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(&Natural::from(4u32), Up), Greater); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(10u32).pow(12); /// assert_eq!(n.div_round_assign(&Natural::from(3u32), Ceiling), Greater); /// assert_eq!(n, 333333333334u64); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(&Natural::from(5u32), Exact), Equal); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(&Natural::from(3u32), Nearest), Less); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(20u32); /// assert_eq!(n.div_round_assign(&Natural::from(3u32), Nearest), Greater); /// assert_eq!(n, 7); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.div_round_assign(&Natural::from(4u32), Nearest), Less); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(14u32); /// assert_eq!(n.div_round_assign(&Natural::from(4u32), Nearest), Greater); /// assert_eq!(n, 4); /// ``` fn div_round_assign(&mut self, other: &'a Self, rm: RoundingMode) -> Ordering { let r = self.div_assign_mod(other); if r == 0 { Equal } else { match rm { Floor | Down => Less, Ceiling | Up => { *self += Self::ONE; Greater } Exact => panic!("Division is not exact"), Nearest => div_round_assign_nearest(self, &r, other), } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000–2002, 2005, 2009, 2014, 2017, 2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::div_exact::{ limbs_modular_div_mod_barrett, limbs_modular_div_mod_barrett_scratch_len, limbs_modular_div_mod_divide_and_conquer, limbs_modular_div_mod_schoolbook, limbs_modular_invert_limb, }; use crate::natural::arithmetic::eq_mod::limbs_mod_exact_odd_limb; use crate::natural::arithmetic::mod_op::limbs_mod_limb; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::platform::{ BMOD_1_TO_MOD_1_THRESHOLD, DC_BDIV_QR_THRESHOLD, DoubleLimb, Limb, MU_BDIV_QR_THRESHOLD, }; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{DivisibleBy, DivisibleByPowerOf2, Parity}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::slices::{slice_leading_zeros, slice_test_zero}; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, determines // whether that `Natural` is divisible by a given limb. // // This function assumes that `ns` has at least two elements and that `d` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpz_divisible_ui_p` from `mpz/divis_ui.c`, GMP 6.2.1, where `a` is // non-negative and the `ABOVE_THRESHOLD` branch is excluded. pub_crate_test! {limbs_divisible_by_limb(ns: &[Limb], d: Limb) -> bool { assert!(ns.len() > 1); if d.even() { let twos = TrailingZeros::trailing_zeros(d); ns[0].divisible_by_power_of_2(twos) && limbs_mod_exact_odd_limb(ns, d >> twos, 0) == 0 } else { limbs_mod_exact_odd_limb(ns, d, 0) == 0 } }} fn limbs_mod_limb_helper(ns: &[Limb], d_low: Limb) -> Limb { if ns.len() < BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_exact_odd_limb(ns, d_low, 0) } else { limbs_mod_limb::(ns, d_low) } } // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, determines whether the first `Natural` is divisible by the second. Both `Natural`s // are taken by value. // // `ns` must be at least as long as `ds`, both slices must be nonempty, and the last limb of both // must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` is empty, or the last limbs of either slice are zero. // // This is equivalent to `mpn_divisible_p` from `mpn/generic/divis.c`, GMP 6.2.1, where `an >= dn` // and neither are zero. pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_divisible_by(ns: &mut [Limb], ds: &mut [Limb]) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(*ns.last().unwrap(), 0); assert_ne!(*ds.last().unwrap(), 0); // Strip low zero limbs from ds, requiring n == 0 on those. let offset = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at_mut(offset); if !slice_test_zero(ns_lo) { // n has fewer low zero limbs than d, so not divisible return false; } let n_len = ns.len(); let ds = &mut ds[offset..]; let d_len = ds.len(); let n_0 = ns[0]; let d_0 = ds[0]; // n must have at least as many low zero bits as d let d_mask = (d_0 & d_0.wrapping_neg()).wrapping_sub(1); if n_0 & d_mask != 0 { return false; } if d_len == 1 { return if n_len >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(ns, d_0) == 0 } else { limbs_mod_exact_odd_limb(ns, d_0 >> d_0.trailing_zeros(), 0) == 0 }; } let trailing_zeros = TrailingZeros::trailing_zeros(d_0); if d_len == 2 { let d_1 = ds[1]; if d_1 <= d_mask { let d_low = (d_0 >> trailing_zeros) | (d_1 << (Limb::WIDTH - trailing_zeros)); return limbs_mod_limb_helper(ns, d_low) == 0; } } let n_len_plus_1 = n_len + 1; let mut qs = vec![0; n_len_plus_1 - d_len]; if trailing_zeros != 0 { assert_eq!(limbs_slice_shr_in_place(ds, trailing_zeros), 0); assert_eq!(limbs_slice_shr_in_place(ns, trailing_zeros), 0); } let mut rs_vec; let rs = if ns[n_len - 1] >= ds[d_len - 1] { rs_vec = Vec::with_capacity(n_len_plus_1); rs_vec.extend_from_slice(ns); rs_vec.push(0); &mut rs_vec } else if n_len == d_len { return false; } else { ns }; let r_len = rs.len(); let q_len = r_len - d_len; let rs = if d_len < DC_BDIV_QR_THRESHOLD || q_len < DC_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(&mut qs, rs, ds, d_inv); &mut rs[q_len..] } else if d_len < MU_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(&mut qs, rs, ds, d_inv); &mut rs[q_len..] } else { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(r_len, d_len)]; let ns = rs.to_vec(); limbs_modular_div_mod_barrett(&mut qs, rs, &ns, ds, &mut scratch); &mut rs[..d_len] }; slice_test_zero(rs) }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, determines whether the first `Natural` is divisible by the second. The first // `Natural` is taken by value, and the second by reference. // // `ns` must be at least as long as `ds`, both slices must be nonempty, and the last limb of both // must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` is empty, or the last limbs of either slice are zero. // // This is equivalent to `mpn_divisible_p` from `mpn/generic/divis.c`, GMP 6.2.1, where `an >= dn` // and neither are zero. pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_divisible_by_val_ref(ns: &mut [Limb], ds: &[Limb]) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(*ns.last().unwrap(), 0); assert_ne!(*ds.last().unwrap(), 0); // Strip low zero limbs from ds, requiring n == 0 on those. let offset = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at_mut(offset); if !slice_test_zero(ns_lo) { // n has fewer low zero limbs than d, so not divisible return false; } let n_len = ns.len(); let mut scratch; let mut ds = &ds[offset..]; let d_len = ds.len(); let n_0 = ns[0]; let d_0 = ds[0]; // n must have at least as many low zero bits as d let d_mask = (d_0 & d_0.wrapping_neg()).wrapping_sub(1); if n_0 & d_mask != 0 { return false; } if d_len == 1 { return if n_len >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(ns, d_0) == 0 } else { limbs_mod_exact_odd_limb(ns, d_0 >> d_0.trailing_zeros(), 0) == 0 }; } let trailing_zeros = TrailingZeros::trailing_zeros(d_0); if d_len == 2 { let d_1 = ds[1]; if d_1 <= d_mask { let d_low = (d_0 >> trailing_zeros) | (d_1 << (Limb::WIDTH - trailing_zeros)); return limbs_mod_limb_helper(ns, d_low) == 0; } } let n_len_plus_1 = n_len + 1; let mut qs = vec![0; n_len_plus_1 - d_len]; if trailing_zeros != 0 { scratch = vec![0; d_len]; assert_eq!(limbs_shr_to_out(&mut scratch, ds, trailing_zeros), 0); ds = &scratch; assert_eq!(limbs_slice_shr_in_place(ns, trailing_zeros), 0); } let mut rs_vec; let rs = if ns[n_len - 1] >= ds[d_len - 1] { rs_vec = Vec::with_capacity(n_len_plus_1); rs_vec.extend_from_slice(ns); rs_vec.push(0); &mut rs_vec } else if n_len == d_len { return false; } else { ns }; let r_len = rs.len(); let q_len = r_len - d_len; let rs = if d_len < DC_BDIV_QR_THRESHOLD || q_len < DC_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(&mut qs, rs, ds, d_inv); &mut rs[q_len..] } else if d_len < MU_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(&mut qs, rs, ds, d_inv); &mut rs[q_len..] } else { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(r_len, d_len)]; let ns = rs.to_vec(); limbs_modular_div_mod_barrett(&mut qs, rs, &ns, ds, &mut scratch); &mut rs[..d_len] }; slice_test_zero(rs) }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, determines whether the first `Natural` is divisible by the second. The first // `Natural` is taken by reference, and the second by value. // // `ns` must be at least as long as `ds`, both slices must be nonempty, and the last limb of both // must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` is empty, or the last limbs of either slice are zero. // // This is equivalent to `mpn_divisible_p` from `mpn/generic/divis.c`, GMP 6.2.1, where `an >= dn` // and neither are zero. pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_divisible_by_ref_val(ns: &[Limb], ds: &mut [Limb]) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(*ns.last().unwrap(), 0); assert_ne!(*ds.last().unwrap(), 0); // Strip low zero limbs from ds, requiring n == 0 on those. let offset = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at(offset); if !slice_test_zero(ns_lo) { // n has fewer low zero limbs than d, so not divisible return false; } let n_len = ns.len(); let ds = &mut ds[offset..]; let d_len = ds.len(); let n_0 = ns[0]; let d_0 = ds[0]; // n must have at least as many low zero bits as d let d_mask = (d_0 & d_0.wrapping_neg()).wrapping_sub(1); if n_0 & d_mask != 0 { return false; } if d_len == 1 { return if n_len >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(ns, d_0) == 0 } else { limbs_mod_exact_odd_limb(ns, d_0 >> d_0.trailing_zeros(), 0) == 0 }; } let trailing_zeros = TrailingZeros::trailing_zeros(d_0); if d_len == 2 { let d_1 = ds[1]; if d_1 <= d_mask { let d_low = (d_0 >> trailing_zeros) | (d_1 << (Limb::WIDTH - trailing_zeros)); return limbs_mod_limb_helper(ns, d_low) == 0; } } let n_len_plus_1 = n_len + 1; let mut rs_qs = vec![0; (n_len_plus_1 << 1) - d_len]; let (rs, qs) = rs_qs.split_at_mut(n_len_plus_1); if trailing_zeros != 0 { assert_eq!(limbs_slice_shr_in_place(ds, trailing_zeros), 0); assert_eq!(limbs_shr_to_out(rs, ns, trailing_zeros), 0); } else { rs[..n_len].copy_from_slice(ns); } let r_len = if rs[n_len - 1] >= ds[d_len - 1] { n_len_plus_1 } else if n_len == d_len { return false; } else { n_len }; let rs = &mut rs[..r_len]; let q_len = r_len - d_len; let rs = if d_len < DC_BDIV_QR_THRESHOLD || q_len < DC_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(qs, rs, ds, d_inv); &mut rs[q_len..] } else if d_len < MU_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(qs, rs, ds, d_inv); &mut rs[q_len..] } else { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(r_len, d_len)]; let ns = rs.to_vec(); limbs_modular_div_mod_barrett(qs, rs, &ns, ds, &mut scratch); &mut rs[..d_len] }; slice_test_zero(rs) }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, determines whether the first `Natural` is divisible by the second. Both `Natural`s // are taken by reference. // // `ns` must be at least as long as `ds`, both slices must be nonempty, and the last limb of both // must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` is empty, or the last limbs of either slice are zero. // // This is equivalent to `mpn_divisible_p` from `mpn/generic/divis.c`, GMP 6.2.1, where `an >= dn` // and neither are zero. pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_divisible_by_ref_ref(ns: &[Limb], ds: &[Limb]) -> bool { let n_len = ns.len(); let d_len = ds.len(); assert_ne!(d_len, 0); assert!(n_len >= d_len); assert_ne!(*ns.last().unwrap(), 0); assert_ne!(*ds.last().unwrap(), 0); // Strip low zero limbs from ds, requiring n == 0 on those. let offset = slice_leading_zeros(ds); let (ns_lo, ns) = ns.split_at(offset); if !slice_test_zero(ns_lo) { // n has fewer low zero limbs than d, so not divisible return false; } let n_len = ns.len(); let mut scratch; let mut ds = &ds[offset..]; let d_len = ds.len(); let d_0 = ds[0]; // n must have at least as many low zero bits as d let d_mask = (d_0 & d_0.wrapping_neg()).wrapping_sub(1); if ns[0] & d_mask != 0 { return false; } if d_len == 1 { return if n_len >= BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(ns, d_0) == 0 } else { limbs_mod_exact_odd_limb(ns, d_0 >> d_0.trailing_zeros(), 0) == 0 }; } let trailing_zeros = TrailingZeros::trailing_zeros(d_0); if d_len == 2 { let d_1 = ds[1]; if d_1 <= d_mask { let d_low = (d_0 >> trailing_zeros) | (d_1 << (Limb::WIDTH - trailing_zeros)); return limbs_mod_limb_helper(ns, d_low) == 0; } } let n_len_plus_1 = n_len + 1; let mut rs_qs = vec![0; (n_len_plus_1 << 1) - d_len]; let (rs, qs) = rs_qs.split_at_mut(n_len_plus_1); if trailing_zeros != 0 { scratch = vec![0; d_len]; assert_eq!(limbs_shr_to_out(&mut scratch, ds, trailing_zeros), 0); ds = &scratch; assert_eq!(limbs_shr_to_out(rs, ns, trailing_zeros), 0); } else { rs[..n_len].copy_from_slice(ns); } let r_len = if rs[n_len - 1] >= ds[d_len - 1] { n_len_plus_1 } else if n_len == d_len { return false; } else { n_len }; let rs = &mut rs[..r_len]; let q_len = r_len - d_len; let rs = if d_len < DC_BDIV_QR_THRESHOLD || q_len < DC_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(qs, rs, ds, d_inv); &mut rs[q_len..] } else if d_len < MU_BDIV_QR_THRESHOLD { let d_inv = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(qs, rs, ds, d_inv); &mut rs[q_len..] } else { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(r_len, d_len)]; let ns = rs.to_vec(); limbs_modular_div_mod_barrett(qs, rs, &ns, ds, &mut scratch); &mut rs[..d_len] }; slice_test_zero(rs) }} impl Natural { fn divisible_by_limb(&self, other: Limb) -> bool { match (self, other) { (&Self::ZERO, _) => true, (_, 0) => false, (&Self(Small(small)), y) => small.divisible_by(y), (Self(Large(limbs)), y) => limbs_divisible_by_limb(limbs, y), } } // Tests whether other is divisible by self fn limb_divisible_by_natural(&self, other: Limb) -> bool { match (other, self) { (0, _) => true, (_, &Self::ZERO | &Self(Large(_))) => false, (x, &Self(Small(small))) => x.divisible_by(small), } } } impl DivisibleBy for Natural { /// Returns whether a [`Natural`] is divisible by another [`Natural`]; in other words, whether /// the first is a multiple of the second. Both [`Natural`]s are taken by value. /// /// This means that zero is divisible by any [`Natural`], including zero; but a nonzero /// [`Natural`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.divisible_by(Natural::ZERO), true); /// assert_eq!( /// Natural::from(100u32).divisible_by(Natural::from(3u32)), /// false /// ); /// assert_eq!( /// Natural::from(102u32).divisible_by(Natural::from(3u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .divisible_by(Natural::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(mut self, mut other: Self) -> bool { match (&mut self, &mut other) { (x, &mut Self(Small(y))) => x.divisible_by_limb(y), (&mut Self(Small(x)), y) => y.limb_divisible_by_natural(x), (Self(Large(xs)), Self(Large(ys))) => { xs.len() >= ys.len() && limbs_divisible_by(xs, ys) } } } } impl<'a> DivisibleBy<&'a Self> for Natural { /// Returns whether a [`Natural`] is divisible by another [`Natural`]; in other words, whether /// the first is a multiple of the second. The first [`Natural`]s is taken by reference and the /// second by value. /// /// This means that zero is divisible by any [`Natural`], including zero; but a nonzero /// [`Natural`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.divisible_by(&Natural::ZERO), true); /// assert_eq!( /// Natural::from(100u32).divisible_by(&Natural::from(3u32)), /// false /// ); /// assert_eq!( /// Natural::from(102u32).divisible_by(&Natural::from(3u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .divisible_by(&Natural::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(mut self, other: &'a Self) -> bool { match (&mut self, other) { (x, &Self(Small(y))) => x.divisible_by_limb(y), (&mut Self(Small(x)), y) => y.limb_divisible_by_natural(x), (Self(Large(xs)), Self(Large(ys))) => { xs.len() >= ys.len() && limbs_divisible_by_val_ref(xs, ys) } } } } impl DivisibleBy for &Natural { /// Returns whether a [`Natural`] is divisible by another [`Natural`]; in other words, whether /// the first is a multiple of the second. The first [`Natural`]s are taken by reference and the /// second by value. /// /// This means that zero is divisible by any [`Natural`], including zero; but a nonzero /// [`Natural`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).divisible_by(Natural::ZERO), true); /// assert_eq!( /// (&Natural::from(100u32)).divisible_by(Natural::from(3u32)), /// false /// ); /// assert_eq!( /// (&Natural::from(102u32)).divisible_by(Natural::from(3u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .divisible_by(Natural::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, mut other: Natural) -> bool { match (self, &mut other) { (x, &mut Natural(Small(y))) => x.divisible_by_limb(y), (&Natural(Small(x)), y) => y.limb_divisible_by_natural(x), (Natural(Large(xs)), Natural(Large(ys))) => { xs.len() >= ys.len() && limbs_divisible_by_ref_val(xs, ys) } } } } impl DivisibleBy<&Natural> for &Natural { /// Returns whether a [`Natural`] is divisible by another [`Natural`]; in other words, whether /// the first is a multiple of the second. Both [`Natural`]s are taken by reference. /// /// This means that zero is divisible by any [`Natural`], including zero; but a nonzero /// [`Natural`] is never divisible by zero. /// /// It's more efficient to use this function than to compute the remainder and check whether /// it's zero. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::DivisibleBy; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).divisible_by(&Natural::ZERO), true); /// assert_eq!( /// (&Natural::from(100u32)).divisible_by(&Natural::from(3u32)), /// false /// ); /// assert_eq!( /// (&Natural::from(102u32)).divisible_by(&Natural::from(3u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .divisible_by(&Natural::from_str("1000000000000").unwrap()), /// true /// ); /// ``` fn divisible_by(self, other: &Natural) -> bool { match (self, other) { (x, &Natural(Small(y))) => x.divisible_by_limb(y), (&Natural(Small(x)), y) => y.limb_divisible_by_natural(x), (Natural(Large(xs)), Natural(Large(ys))) => { xs.len() >= ys.len() && limbs_divisible_by_ref_ref(xs, ys) } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2001, 2002 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_test_zero; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, determines // whether that `Natural` is divisible by 2 raised to a given power. // // This function assumes that `xs` is nonempty and does not only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, xs.len())`. // // This is equivalent to `mpz_divisible_2exp_p` from `mpz/divis_2exp.c`, GMP 6.2.1, where `a` is // non-negative. pub_crate_test! {limbs_divisible_by_power_of_2(xs: &[Limb], pow: u64) -> bool { assert!(!xs.is_empty()); let zeros = bit_to_limb_count_floor(pow); zeros < xs.len() && slice_test_zero(&xs[..zeros]) && xs[zeros].divisible_by_power_of_2(pow & Limb::WIDTH_MASK) }} impl DivisibleByPowerOf2 for &Natural { /// Returns whether a [`Natural`] is divisible by $2^k$. /// /// $f(x, k) = (2^k|x)$. /// /// $f(x, k) = (\exists n \in \N : \ x = n2^k)$. /// /// If `self` is 0, the result is always true; otherwise, it is equivalent to /// `self.trailing_zeros().unwrap() <= pow`, but more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, self.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.divisible_by_power_of_2(100), true); /// assert_eq!(Natural::from(100u32).divisible_by_power_of_2(2), true); /// assert_eq!(Natural::from(100u32).divisible_by_power_of_2(3), false); /// assert_eq!( /// Natural::from(10u32).pow(12).divisible_by_power_of_2(12), /// true /// ); /// assert_eq!( /// Natural::from(10u32).pow(12).divisible_by_power_of_2(13), /// false /// ); /// ``` fn divisible_by_power_of_2(self, pow: u64) -> bool { match (self, pow) { (_, 0) => true, (&Natural(Small(small)), pow) => small.divisible_by_power_of_2(pow), (&Natural(Large(ref limbs)), pow) => limbs_divisible_by_power_of_2(limbs, pow), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::div_exact::limbs_modular_invert_limb; use crate::natural::arithmetic::divisible_by::{ limbs_divisible_by, limbs_divisible_by_limb, limbs_divisible_by_val_ref, }; use crate::natural::arithmetic::mod_op::limbs_mod_limb; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, }; use crate::natural::comparison::cmp::limbs_cmp; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ DivisibleBy, DivisibleByPowerOf2, EqMod, EqModPowerOf2, Parity, PowerOf2, WrappingAddAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::slices::slice_trailing_zeros; // See the description for `limbs_mod_exact_odd_limb`. divisor must be odd. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_modexact_1c_odd`, from `mpn/generic/mode1o.c`, GMP 6.2.1, where `size // == 1`. Pass `carry = 0` to get `mpn_modexact_1_odd` from `gmp-impl.c`, GMP 6.2.1, where `size == // 1`. pub_const_test! {limbs_limb_mod_exact_odd_limb(n: Limb, d: Limb, carry: Limb) -> Limb { if n > carry { let result = (n - carry) % d; if result == 0 { 0 } else { d - result } } else { (carry - n) % d } }} // Calculates an r satisfying // // r * B ^ k + n - c == q * d // // where B = `2 ^ Limb::WIDTH`, k is either `ns.len()` or `ns.len()` - 1 (the caller won't know // which), c is `carry`, and q is the quotient (discarded). `d` must be odd and `carry` can be any // limb value. // // If c < d then r will be in the range 0 <= r < d, or if c >= d then 0 <= r <= d. // // This slightly strange function suits the initial N x 1 reduction for GCDs or Jacobi symbols since // the factors of 2 in B ^ k can be ignored, leaving -r == a mod d (by passing c = 0). For a GCD the // factor of -1 on r can be ignored, or for the Jacobi symbol it can be accounted for. The function // also suits divisibility and congruence testing, since if r = 0 (or r = d) is obtained, then a ≡ // c mod d. // // ns must be nonempty and divisor must be odd. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_modexact_1c_odd` from mpn/generic/mode1o.c, GMP 6.2.1. Pass `carry = // 0` to get `mpn_modexact_1_odd` from `gmp-impl.c`, GMP 6.2.1. pub_crate_test! {limbs_mod_exact_odd_limb(ns: &[Limb], d: Limb, mut carry: Limb) -> Limb { let len = ns.len(); if len == 1 { return limbs_limb_mod_exact_odd_limb(ns[0], d, carry); } let d_inv = limbs_modular_invert_limb(d); let d_double = DoubleLimb::from(d); let (xs_last, xs_init) = ns.split_last().unwrap(); let xs_last = *xs_last; for x in xs_init { let (diff, small_carry) = x.overflowing_sub(carry); carry = (DoubleLimb::from(diff.wrapping_mul(d_inv)) * d_double).upper_half(); if small_carry { carry.wrapping_add_assign(1); } } if xs_last <= d { if carry >= xs_last { carry - xs_last } else { carry.wrapping_add(d - xs_last) } } else { let (diff, small_carry) = xs_last.overflowing_sub(carry); carry = (DoubleLimb::from(diff.wrapping_mul(d_inv)) * d_double).upper_half(); if small_carry { carry.wrapping_add_assign(1); } carry } }} // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, determines // whether that `Natural` is equal to a limb mod a given `Limb` `m`. // // This function assumes that `m` is nonzero, `xs` has at least two elements, and the last element // of `xs` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` is less than 2 or `m` is zero. // // This is equivalent to `mpz_congruent_ui_p` from `mpz/cong_ui.c`, GMP 6.2.1, where `a` is positive // and the `ABOVE_THRESHOLD` branch is excluded. pub_crate_test! {limbs_eq_limb_mod_limb(xs: &[Limb], y: Limb, m: Limb) -> bool { assert_ne!(m, 0); assert!(xs.len() > 1); let r = if m.even() { let twos = TrailingZeros::trailing_zeros(m); if !xs[0].wrapping_sub(y).divisible_by_power_of_2(twos) { return false; } limbs_mod_exact_odd_limb(xs, m >> twos, y) } else { limbs_mod_exact_odd_limb(xs, m, y) }; r == 0 || r == m }} #[allow(clippy::absurd_extreme_comparisons)] fn limbs_eq_limb_mod_helper(xs: &[Limb], y: Limb, ms: &[Limb]) -> Option { let m_len = ms.len(); assert!(m_len > 1); let x_len = xs.len(); assert!(x_len > 1); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(y, 0); assert_ne!(*ms.last().unwrap(), 0); if m_len > x_len { // x < m, y < m, and x != y, so x != y mod m return Some(false); } let m_0 = ms[0]; // Check xs == ys mod low zero bits of m_0. let m_0_trailing_zeros = TrailingZeros::trailing_zeros(m_0); if !xs[0].eq_mod_power_of_2(y, m_0_trailing_zeros) { return Some(false); } if m_len == 2 && m_0 != 0 { let m_1 = ms[1]; if m_1 < Limb::power_of_2(m_0_trailing_zeros) { let m_0 = (m_0 >> m_0_trailing_zeros) | (m_1 << (Limb::WIDTH - m_0_trailing_zeros)); return Some(if x_len >= BMOD_1_TO_MOD_1_THRESHOLD { let r = limbs_mod_limb::(xs, m_0); if y < m_0 { r == y } else { r == y % m_0 } } else { let r = limbs_mod_exact_odd_limb(xs, m_0, y); r == 0 || r == m_0 }); } } None } // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `ms` as three // numbers x, y, and m, determines whether x ≡ y mod m. Both input slices are immutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `ms` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_eq_limb_mod_ref_ref(xs: &[Limb], y: Limb, ms: &[Limb]) -> bool { if let Some(equal) = limbs_eq_limb_mod_helper(xs, y, ms) { return equal; } let mut scratch = vec![0; xs.len()]; // calculate |xs - y| assert!(!limbs_sub_limb_to_out(&mut scratch, xs, y)); scratch.truncate(scratch.len() - slice_trailing_zeros(&scratch)); scratch.len() >= ms.len() && limbs_divisible_by_val_ref(&mut scratch, ms) }} // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `ms` as three // numbers x, y, and m, determines whether x ≡ y mod m. The first input slice is immutable and the // second is mutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `ms` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_eq_limb_mod_ref_val(xs: &[Limb], y: Limb, ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_eq_limb_mod_helper(xs, y, ms) { return equal; } let mut scratch = vec![0; xs.len()]; // calculate |xs - y| assert!(!limbs_sub_limb_to_out(&mut scratch, xs, y)); scratch.truncate(scratch.len() - slice_trailing_zeros(&scratch)); scratch.len() >= ms.len() && limbs_divisible_by(&mut scratch, ms) }} // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `ms` as three // numbers x, y, and m, determines whether x ≡ y mod m. The first input slice is mutable and the // second is immutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `m` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_eq_limb_mod_val_ref(xs: &mut [Limb], y: Limb, ms: &[Limb]) -> bool { if let Some(equal) = limbs_eq_limb_mod_helper(xs, y, ms) { return equal; } // calculate |xs - y| assert!(!limbs_sub_limb_in_place(xs, y)); let new_len = xs.len() - slice_trailing_zeros(xs); new_len >= ms.len() && limbs_divisible_by_val_ref(&mut xs[..new_len], ms) }} // Interpreting a slice of `Limb`s `xs`, a Limb `y`, and another slice of `Limb`s `ms` as three // numbers x, y, and m, determines whether x ≡ y mod m. Both input slices are mutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `y` is nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if the length of `xs` or `ms` is less than 2, if the last element of either of the slices // is zero, or if `y` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `d` are longer than one limb, and `c` is one limb long. pub_test! {limbs_eq_limb_mod(xs: &mut [Limb], y: Limb, ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_eq_limb_mod_helper(xs, y, ms) { return equal; } // calculate |xs - y| assert!(!limbs_sub_limb_in_place(xs, y)); let new_len = xs.len() - slice_trailing_zeros(xs); new_len >= ms.len() && limbs_divisible_by(&mut xs[..new_len], ms) }} // xs.len() >= ys.len() fn limbs_eq_mod_limb_helper(xs: &[Limb], ys: &[Limb], m: Limb) -> Option { let x_len = xs.len(); let y_len = ys.len(); assert!(y_len > 1); assert!(x_len >= y_len); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(*ys.last().unwrap(), 0); assert_ne!(m, 0); if xs == ys { Some(true) } else if !xs[0].eq_mod_power_of_2(ys[0], u64::from(m.trailing_zeros())) { // Check xs == ys mod low zero bits of m. Some(false) } else { None } } // Interpreting two slices of `Limb`s `xs` and `ys` and a Limb `m` as three numbers x, y, and m, // determines whether x ≡ y mod m. Both input slices are immutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `m` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs` or `ys` is less than 2, if the last element of either of the slices // is zero, or if `m` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `c` are longer than one limb, and `m` is one limb long. pub_test! {limbs_eq_mod_limb_ref_ref(xs: &[Limb], ys: &[Limb], m: Limb) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_limb_ref_ref_greater(xs, ys, m) } else { limbs_eq_mod_limb_ref_ref_greater(ys, xs, m) } }} // xs.len() >= ys.len() fn limbs_eq_mod_limb_ref_ref_greater(xs: &[Limb], ys: &[Limb], m: Limb) -> bool { if let Some(equal) = limbs_eq_mod_limb_helper(xs, ys, m) { return equal; } let mut scratch = vec![0; xs.len()]; // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); } else { assert!(!limbs_sub_same_length_to_out(&mut scratch, ys, xs)); } scratch.truncate(scratch.len() - slice_trailing_zeros(&scratch)); // scratch is non-empty here because xs != ys if scratch.len() == 1 { scratch[0].divisible_by(m) } else { limbs_divisible_by_limb(&scratch, m) } } // Interpreting two slices of `Limb`s `xs` and `ys` and a Limb `m` as three numbers x, y, and m, // determines whether x ≡ y mod m. The first input slice is immutable and the second is mutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `m` is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs` or `ys` is less than 2, if the last element of either of the slices // is zero, or if `m` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `c` are longer than one limb, and `m` is one limb long. pub_test! {limbs_eq_mod_limb_ref_val(xs: &[Limb], ys: &mut [Limb], m: Limb) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_limb_ref_val_greater(xs, ys, m) } else { limbs_eq_mod_limb_val_ref_greater(ys, xs, m) } }} // xs.len() >= ys.len() fn limbs_eq_mod_limb_ref_val_greater(xs: &[Limb], ys: &mut [Limb], m: Limb) -> bool { if let Some(equal) = limbs_eq_mod_limb_helper(xs, ys, m) { return equal; } let mut scratch; // calculate |xs - ys| let scratch = if limbs_cmp(xs, ys) >= Equal { scratch = vec![0; xs.len()]; assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); &mut scratch } else { assert!(!limbs_sub_same_length_in_place_left(ys, xs)); ys }; let new_len = scratch.len() - slice_trailing_zeros(scratch); // scratch is non-empty here because xs != ys if new_len == 1 { scratch[0].divisible_by(m) } else { limbs_divisible_by_limb(&scratch[..new_len], m) } } // Interpreting two slices of `Limb`s `xs` and `ys` and a Limb `m` as three numbers x, y, and m, // determines whether x ≡ y mod m. The first input slice is mutable and the second is immutable. // // This function assumes that each of the two input slices have at least two elements, their last // elements are nonzero, and `m` is nonzero. Both input slices are immutable. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs` or `ys` is less than 2, if the last element of either of the slices // is zero, or if `m` is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive, `a` and `c` are longer than one limb, and `m` is one limb long. pub_test! {limbs_eq_mod_limb_val_ref(xs: &mut [Limb], ys: &[Limb], m: Limb) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_limb_val_ref_greater(xs, ys, m) } else { limbs_eq_mod_limb_ref_val_greater(ys, xs, m) } }} // xs.len() >= ys.len() fn limbs_eq_mod_limb_val_ref_greater(xs: &mut [Limb], ys: &[Limb], m: Limb) -> bool { if let Some(equal) = limbs_eq_mod_limb_helper(xs, ys, m) { return equal; } // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_in_place_left(xs, ys)); } else { assert!(!limbs_sub_same_length_in_place_right(ys, xs)); } let new_len = xs.len() - slice_trailing_zeros(xs); // xs is non-empty here because xs != ys if new_len == 1 { xs[0].divisible_by(m) } else { limbs_divisible_by_limb(&xs[..new_len], m) } } // xs.len() >= ys.len() fn limbs_eq_mod_helper(xs: &[Limb], ys: &[Limb], m: &[Limb]) -> Option { let m_len = m.len(); assert!(m_len > 1); let x_len = xs.len(); let y_len = ys.len(); assert!(y_len > 1); assert!(x_len >= y_len); assert_ne!(*xs.last().unwrap(), 0); assert_ne!(*ys.last().unwrap(), 0); assert_ne!(*m.last().unwrap(), 0); if xs == ys { Some(true) } else if m_len > x_len || !xs[0].eq_mod_power_of_2(ys[0], TrailingZeros::trailing_zeros(m[0])) { // - Either: x < m, y < m, and x != y, so x != y mod m // - Or: xs != ys mod low zero bits of m_0 Some(false) } else { None } } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the second `Natural` mod the third `Natural`. All input slices are // immutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive and each is longer than one limb. pub_test! {limbs_eq_mod_ref_ref_ref(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_greater_ref_ref_ref(xs, ys, ms) } else { limbs_eq_mod_greater_ref_ref_ref(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_eq_mod_greater_ref_ref_ref(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } let mut scratch = vec![0; xs.len()]; // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); } else { assert!(!limbs_sub_same_length_to_out(&mut scratch, ys, xs)); } scratch.truncate(scratch.len() - slice_trailing_zeros(&scratch)); scratch.len() >= ms.len() && limbs_divisible_by_val_ref(&mut scratch, ms) } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the second `Natural` mod the third `Natural`. The first two input // slices are immutable, and the third is mutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive and each is longer than one limb. pub_test! {limbs_eq_mod_ref_ref_val(xs: &[Limb], ys: &[Limb], ms: &mut [Limb]) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_greater_ref_ref_val(xs, ys, ms) } else { limbs_eq_mod_greater_ref_ref_val(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_eq_mod_greater_ref_ref_val(xs: &[Limb], ys: &[Limb], ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } let mut scratch = vec![0; xs.len()]; // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); } else { assert!(!limbs_sub_same_length_to_out(&mut scratch, ys, xs)); } scratch.truncate(scratch.len() - slice_trailing_zeros(&scratch)); scratch.len() >= ms.len() && limbs_divisible_by(&mut scratch, ms) } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the second `Natural` mod the third `Natural`. The first and third // input slices are immutable, and the second is mutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive and each is longer than one limb. pub_test! {limbs_eq_mod_ref_val_ref(xs: &[Limb], ys: &mut [Limb], ms: &[Limb]) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_greater_ref_val_ref(xs, ys, ms) } else { limbs_eq_mod_greater_val_ref_ref(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_eq_mod_greater_ref_val_ref(xs: &[Limb], ys: &mut [Limb], ms: &[Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } let mut scratch; // calculate |xs - ys| let scratch = if limbs_cmp(xs, ys) >= Equal { scratch = vec![0; xs.len()]; assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); &mut scratch } else { assert!(!limbs_sub_same_length_in_place_left(ys, xs)); ys }; let new_len = scratch.len() - slice_trailing_zeros(scratch); new_len >= ms.len() && limbs_divisible_by_val_ref(&mut scratch[..new_len], ms) } // xs.len() >= ys.len() fn limbs_eq_mod_greater_val_ref_ref(xs: &mut [Limb], ys: &[Limb], ms: &[Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_in_place_left(xs, ys)); } else { assert!(!limbs_sub_same_length_in_place_right(ys, xs)); } let new_len = xs.len() - slice_trailing_zeros(xs); new_len >= ms.len() && limbs_divisible_by_val_ref(&mut xs[..new_len], ms) } // Interpreting three slice of `Limb`s as the limbs of three `Natural`s, determines whether the // first `Natural` is equal to the second `Natural` mod the third `Natural`. The first input slice // is immutable, and the second and third are mutable. // // This function assumes that each of the three input slices have at least two elements, and their // last elements are nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log \log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if the length of `xs`, `ys`, or `ms` is less than 2, or if the last element of any of the // slices is zero. // // This is equivalent to `mpz_congruent_p` from `mpz/cong.c`, GMP 6.2.1, where `a`, `c`, and `d` are // positive and each is longer than one limb. pub_test! {limbs_eq_mod_ref_val_val(xs: &[Limb], ys: &mut [Limb], ms: &mut [Limb]) -> bool { if xs.len() >= ys.len() { limbs_eq_mod_greater_ref_val_val(xs, ys, ms) } else { limbs_eq_mod_greater_val_ref_val(ys, xs, ms) } }} // xs.len() >= ys.len() fn limbs_eq_mod_greater_ref_val_val(xs: &[Limb], ys: &mut [Limb], ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } let mut scratch; // calculate |xs - ys| let scratch = if limbs_cmp(xs, ys) >= Equal { scratch = vec![0; xs.len()]; assert!(!limbs_sub_greater_to_out(&mut scratch, xs, ys)); &mut scratch } else { assert!(!limbs_sub_same_length_in_place_left(ys, xs)); ys }; let new_len = scratch.len() - slice_trailing_zeros(scratch); new_len >= ms.len() && limbs_divisible_by(&mut scratch[..new_len], ms) } // xs.len() >= ys.len() fn limbs_eq_mod_greater_val_ref_val(xs: &mut [Limb], ys: &[Limb], ms: &mut [Limb]) -> bool { if let Some(equal) = limbs_eq_mod_helper(xs, ys, ms) { return equal; } // calculate |xs - ys| if limbs_cmp(xs, ys) >= Equal { assert!(!limbs_sub_greater_in_place_left(xs, ys)); } else { assert!(!limbs_sub_same_length_in_place_right(ys, xs)); } let new_len = xs.len() - slice_trailing_zeros(xs); new_len >= ms.len() && limbs_divisible_by(&mut xs[..new_len], ms) } impl Natural { fn eq_mod_limb(&self, other: Limb, m: Limb) -> bool { match self { Self(Small(small)) => small.eq_mod(other, m), Self(Large(_)) if m == 0 => false, Self(Large(limbs)) => limbs_eq_limb_mod_limb(limbs, other, m), } } } impl EqMod for Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. All three are taken /// by value. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).eq_mod(Natural::from(223u32), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// Natural::from_str("2000000987654").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// Natural::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Self, m: Self) -> bool { match (self, other, m) { (x, y, Self::ZERO) => x == y, (x, Self::ZERO, m) => x.divisible_by(m), (Self::ZERO, y, m) => y.divisible_by(m), (x, Self(Small(y)), Self(Small(m))) => x.eq_mod_limb(y, m), (Self(Small(x)), y, Self(Small(m))) => y.eq_mod_limb(x, m), (Self(Small(x)), Self(Small(y)), _) => x == y, (Self(Large(mut xs)), Self(Large(ys)), Self(Small(m))) => { limbs_eq_mod_limb_val_ref(&mut xs, &ys, m) } (Self(Large(mut xs)), Self(Small(y)), Self(Large(mut m))) => { limbs_eq_limb_mod(&mut xs, y, &mut m) } (Self(Small(x)), Self(Large(mut ys)), Self(Large(mut m))) => { limbs_eq_limb_mod(&mut ys, x, &mut m) } (Self(Large(mut xs)), Self(Large(ys)), Self(Large(mut m))) => { limbs_eq_mod_ref_val_val(&ys, &mut xs, &mut m) } } } } impl<'a> EqMod for Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first two are /// taken by value and the third by reference. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).eq_mod(Natural::from(223u32), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// Natural::from_str("2000000987654").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// Natural::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Self, m: &'a Self) -> bool { match (self, other, m) { (x, y, &Self::ZERO) => x == y, (x, Self::ZERO, m) => x.divisible_by(m), (Self::ZERO, y, m) => y.divisible_by(m), (x, Self(Small(y)), &Self(Small(m))) => x.eq_mod_limb(y, m), (Self(Small(x)), y, &Self(Small(m))) => y.eq_mod_limb(x, m), (Self(Small(x)), Self(Small(y)), _) => x == y, (Self(Large(mut xs)), Self(Large(ys)), Self(Small(m))) => { limbs_eq_mod_limb_val_ref(&mut xs, &ys, *m) } (Self(Large(mut xs)), Self(Small(y)), Self(Large(m))) => { limbs_eq_limb_mod_val_ref(&mut xs, y, m) } (Self(Small(x)), Self(Large(mut ys)), Self(Large(m))) => { limbs_eq_limb_mod_val_ref(&mut ys, x, m) } (Self(Large(mut xs)), Self(Large(ys)), Self(Large(m))) => { limbs_eq_mod_ref_val_ref(&ys, &mut xs, m) } } } } impl<'a> EqMod<&'a Self, Self> for Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first and third /// are taken by value and the second by reference. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).eq_mod(&Natural::from(223u32), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// &Natural::from_str("2000000987654").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// &Natural::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &'a Self, m: Self) -> bool { match (self, other, m) { (x, y, Self::ZERO) => x == *y, (x, &Self::ZERO, m) => x.divisible_by(m), (Self::ZERO, y, m) => y.divisible_by(m), (x, &Self(Small(y)), Self(Small(m))) => x.eq_mod_limb(y, m), (Self(Small(x)), y, Self(Small(m))) => y.eq_mod_limb(x, m), (Self(Small(x)), &Self(Small(y)), _) => x == y, (Self(Large(mut xs)), Self(Large(ys)), Self(Small(m))) => { limbs_eq_mod_limb_val_ref(&mut xs, ys, m) } (Self(Large(mut xs)), Self(Small(y)), Self(Large(mut m))) => { limbs_eq_limb_mod(&mut xs, *y, &mut m) } (Self(Small(x)), Self(Large(ys)), Self(Large(mut m))) => { limbs_eq_limb_mod_ref_val(ys, x, &mut m) } (Self(Large(mut xs)), Self(Large(ys)), Self(Large(mut m))) => { limbs_eq_mod_ref_val_val(ys, &mut xs, &mut m) } } } } impl<'a, 'b> EqMod<&'a Self, &'b Self> for Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first is taken /// by value and the second and third by reference. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).eq_mod(&Natural::from(223u32), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// &Natural::from_str("2000000987654").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// Natural::from_str("1000000987654").unwrap().eq_mod( /// &Natural::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &'a Self, m: &'b Self) -> bool { match (self, other, m) { (x, y, &Self::ZERO) => x == *y, (x, &Self::ZERO, m) => x.divisible_by(m), (Self::ZERO, y, m) => y.divisible_by(m), (x, &Self(Small(y)), &Self(Small(m))) => x.eq_mod_limb(y, m), (Self(Small(x)), y, &Self(Small(m))) => y.eq_mod_limb(x, m), (Self(Small(x)), &Self(Small(y)), _) => x == y, (Self(Large(mut xs)), Self(Large(ys)), Self(Small(m))) => { limbs_eq_mod_limb_val_ref(&mut xs, ys, *m) } (Self(Large(mut xs)), Self(Small(y)), Self(Large(m))) => { limbs_eq_limb_mod_val_ref(&mut xs, *y, m) } (Self(Small(x)), Self(Large(ys)), Self(Large(m))) => { limbs_eq_limb_mod_ref_ref(ys, x, m) } (Self(Large(mut xs)), Self(Large(ys)), Self(Large(m))) => { limbs_eq_mod_ref_val_ref(ys, &mut xs, m) } } } } impl EqMod for &Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first is taken /// by reference and the second and third by value. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(123u32)).eq_mod(Natural::from(223u32), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// Natural::from_str("2000000987654").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// Natural::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Natural, m: Natural) -> bool { match (self, other, m) { (x, y, Natural::ZERO) => *x == y, (x, Natural::ZERO, m) => x.divisible_by(m), (&Natural::ZERO, y, m) => y.divisible_by(m), (x, Natural(Small(y)), Natural(Small(m))) => x.eq_mod_limb(y, m), (&Natural(Small(x)), y, Natural(Small(m))) => y.eq_mod_limb(x, m), (&Natural(Small(x)), Natural(Small(y)), _) => x == y, (Natural(Large(xs)), Natural(Large(mut ys)), Natural(Small(m))) => { limbs_eq_mod_limb_ref_val(xs, &mut ys, m) } (Natural(Large(xs)), Natural(Small(y)), Natural(Large(mut m))) => { limbs_eq_limb_mod_ref_val(xs, y, &mut m) } (Natural(Small(x)), Natural(Large(mut ys)), Natural(Large(mut m))) => { limbs_eq_limb_mod(&mut ys, *x, &mut m) } (Natural(Large(xs)), Natural(Large(mut ys)), Natural(Large(mut m))) => { limbs_eq_mod_ref_val_val(xs, &mut ys, &mut m) } } } } impl EqMod for &Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first and third /// are taken by reference and the second by value. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(123u32)).eq_mod(Natural::from(223u32), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// Natural::from_str("2000000987654").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// Natural::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: Natural, m: &Natural) -> bool { match (self, other, m) { (x, y, &Natural::ZERO) => *x == y, (x, Natural::ZERO, m) => x.divisible_by(m), (&Natural::ZERO, y, m) => y.divisible_by(m), (x, Natural(Small(y)), &Natural(Small(m))) => x.eq_mod_limb(y, m), (&Natural(Small(x)), y, &Natural(Small(m))) => y.eq_mod_limb(x, m), (&Natural(Small(x)), Natural(Small(y)), _) => x == y, (Natural(Large(xs)), Natural(Large(mut ys)), Natural(Small(m))) => { limbs_eq_mod_limb_ref_val(xs, &mut ys, *m) } (Natural(Large(xs)), Natural(Small(y)), Natural(Large(m))) => { limbs_eq_limb_mod_ref_ref(xs, y, m) } (Natural(Small(x)), Natural(Large(mut ys)), Natural(Large(m))) => { limbs_eq_limb_mod_val_ref(&mut ys, *x, m) } (Natural(Large(xs)), Natural(Large(mut ys)), Natural(Large(m))) => { limbs_eq_mod_ref_val_ref(xs, &mut ys, m) } } } } impl EqMod<&Natural, Natural> for &Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. The first and /// second are taken by reference and the third by value. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(123u32)).eq_mod(&Natural::from(223u32), Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// &Natural::from_str("2000000987654").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// &Natural::from_str("2000000987655").unwrap(), /// Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Natural, m: Natural) -> bool { match (self, other, m) { (x, y, Natural::ZERO) => x == y, (x, &Natural::ZERO, m) => x.divisible_by(m), (&Natural::ZERO, y, m) => y.divisible_by(m), (x, &Natural(Small(y)), Natural(Small(m))) => x.eq_mod_limb(y, m), (&Natural(Small(x)), y, Natural(Small(m))) => y.eq_mod_limb(x, m), (&Natural(Small(x)), &Natural(Small(y)), _) => x == y, (Natural(Large(xs)), Natural(Large(ys)), Natural(Small(m))) => { limbs_eq_mod_limb_ref_ref(xs, ys, m) } (Natural(Large(xs)), Natural(Small(y)), Natural(Large(mut m))) => { limbs_eq_limb_mod_ref_val(xs, *y, &mut m) } (Natural(Small(x)), Natural(Large(ys)), Natural(Large(mut m))) => { limbs_eq_limb_mod_ref_val(ys, *x, &mut m) } (Natural(Large(xs)), Natural(Large(ys)), Natural(Large(mut m))) => { limbs_eq_mod_ref_ref_val(xs, ys, &mut m) } } } } impl EqMod<&Natural, &Natural> for &Natural { /// Returns whether a [`Natural`] is equivalent to another [`Natural`] modulo a third; that is, /// whether the difference between the first two is a multiple of the third. All three are taken /// by reference. /// /// Two [`Natural`]s are equal to each other modulo 0 iff they are equal. /// /// $f(x, y, m) = (x \equiv y \mod m)$. /// /// $f(x, y, m) = (\exists k \in \Z : x - y = km)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log \log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::EqMod; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(123u32)).eq_mod(&Natural::from(223u32), &Natural::from(100u32)), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// &Natural::from_str("2000000987654").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// true /// ); /// assert_eq!( /// (&Natural::from_str("1000000987654").unwrap()).eq_mod( /// &Natural::from_str("2000000987655").unwrap(), /// &Natural::from_str("1000000000000").unwrap() /// ), /// false /// ); /// ``` fn eq_mod(self, other: &Natural, m: &Natural) -> bool { match (self, other, m) { (x, y, &Natural::ZERO) => x == y, (x, &Natural::ZERO, m) => x.divisible_by(m), (&Natural::ZERO, y, m) => y.divisible_by(m), (x, &Natural(Small(y)), &Natural(Small(m))) => x.eq_mod_limb(y, m), (&Natural(Small(x)), y, &Natural(Small(m))) => y.eq_mod_limb(x, m), (&Natural(Small(x)), &Natural(Small(y)), _) => x == y, (Natural(Large(xs)), Natural(Large(ys)), Natural(Small(m))) => { limbs_eq_mod_limb_ref_ref(xs, ys, *m) } (Natural(Large(xs)), Natural(Small(y)), Natural(Large(m))) => { limbs_eq_limb_mod_ref_ref(xs, *y, m) } (Natural(Small(x)), Natural(Large(ys)), Natural(Large(m))) => { limbs_eq_limb_mod_ref_ref(ys, *x, m) } (Natural(Large(xs)), Natural(Large(ys)), Natural(Large(m))) => { limbs_eq_mod_ref_ref_ref(xs, ys, m) } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2001, 2002, 2013 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::EqModPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::WrappingFrom; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns whether // the `Natural` is equivalent to a limb mod two to the power of `pow`; that is, whether the `pow` // least-significant bits of the `Natural` and the limb are equal. // // This function assumes that `xs` has length at least 2 and the last (most significant) limb is // nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_eq_limb_mod_power_of_2(xs: &[Limb], y: Limb, pow: u64) -> bool { let i = bit_to_limb_count_floor(pow); if i >= xs.len() { false } else if i == 0 { xs[0].eq_mod_power_of_2(y, pow) } else { let (xs_head, xs_tail) = xs.split_first().unwrap(); *xs_head == y && limbs_divisible_by_power_of_2(xs_tail, pow - Limb::WIDTH) } }} // xs.len() == ys.len() fn limbs_eq_mod_power_of_2_same_length(xs: &[Limb], ys: &[Limb], pow: u64) -> bool { let i = bit_to_limb_count_floor(pow); let len = xs.len(); if i >= len { xs == ys } else { let (xs_last, xs_init) = xs[..=i].split_last().unwrap(); let (ys_last, ys_init) = ys[..=i].split_last().unwrap(); xs_init == ys_init && xs_last.eq_mod_power_of_2(*ys_last, pow & Limb::WIDTH_MASK) } } // xs.len() > ys.len() fn limbs_eq_mod_power_of_2_greater(xs: &[Limb], ys: &[Limb], pow: u64) -> bool { let i = bit_to_limb_count_floor(pow); let xs_len = xs.len(); let ys_len = ys.len(); if i >= xs_len { false } else if i >= ys_len { let (xs_lo, xs_hi) = xs.split_at(ys_len); xs_lo == ys && limbs_divisible_by_power_of_2(xs_hi, pow - Limb::WIDTH * u64::wrapping_from(ys_len)) } else { let (xs_last, xs_init) = xs[..=i].split_last().unwrap(); let (ys_last, ys_init) = ys[..=i].split_last().unwrap(); xs_init == ys_init && xs_last.eq_mod_power_of_2(*ys_last, pow & Limb::WIDTH_MASK) } } /// Interpreting two slices of `Limb`s as the limbs (in ascending order) of two [`Natural`]s, /// returns whether the [`Natural`]s are equivalent mod two to the power of `pow`; that is, whether /// their `pow` least-significant bits are equal. /// /// This function assumes that neither slice is empty and their last elements are nonzero. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, xs.len(), ys.len())`. /// /// This is equivalent to `mpz_congruent_2exp_p` from `mpz/cong_2exp.c`, GMP 6.2.1, where `a` and /// `c` are non-negative. #[doc(hidden)] pub fn limbs_eq_mod_power_of_2(xs: &[Limb], ys: &[Limb], pow: u64) -> bool { match xs.len().cmp(&ys.len()) { Equal => limbs_eq_mod_power_of_2_same_length(xs, ys, pow), Less => limbs_eq_mod_power_of_2_greater(ys, xs, pow), Greater => limbs_eq_mod_power_of_2_greater(xs, ys, pow), } } impl Natural { fn eq_mod_power_of_2_limb(&self, other: Limb, pow: u64) -> bool { match self { Self(Small(small)) => small.eq_mod_power_of_2(other, pow), Self(Large(limbs)) => limbs_eq_limb_mod_power_of_2(limbs, other, pow), } } } impl EqModPowerOf2<&Natural> for &Natural { /// Returns whether one [`Natural`] is equal to another modulo $2^k$; that is, whether their $k$ /// least-significant bits are equal. /// /// $f(x, y, k) = (x \equiv y \mod 2^k)$. /// /// $f(x, y, k) = (\exists n \in \Z : x - y = n2^k)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(pow, self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::EqModPowerOf2; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).eq_mod_power_of_2(&Natural::from(256u32), 8), /// true /// ); /// assert_eq!( /// (&Natural::from(0b1101u32)).eq_mod_power_of_2(&Natural::from(0b10101u32), 3), /// true /// ); /// assert_eq!( /// (&Natural::from(0b1101u32)).eq_mod_power_of_2(&Natural::from(0b10101u32), 4), /// false /// ); /// ``` fn eq_mod_power_of_2(self, other: &Natural, pow: u64) -> bool { match (self, other) { (_, &Natural(Small(y))) => self.eq_mod_power_of_2_limb(y, pow), (&Natural(Small(x)), _) => other.eq_mod_power_of_2_limb(x, pow), (Natural(Large(xs)), Natural(Large(ys))) => limbs_eq_mod_power_of_2(xs, ys, pow), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/factorial.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `limb_apprsqrt`, `mpz_2multiswing_1`, `mpz_oddfac_1`, `mpz_fac_ui`, and `mpz_2fac_ui` // contributed to the GNU project by Marco Bodrato. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::mul::product_of_limbs::limbs_product; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::{ Limb, NTH_ROOT_NUMB_MASK_TABLE, ODD_DOUBLEFACTORIAL_TABLE_LIMIT, ODD_DOUBLEFACTORIAL_TABLE_MAX, ODD_FACTORIAL_TABLE_LIMIT, ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE, ONE_LIMB_ODD_FACTORIAL_TABLE, TABLE_2N_MINUS_POPC_2N, TABLE_LIMIT_2N_MINUS_POPC_2N, }; use alloc::vec::Vec; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ DoubleFactorial, Factorial, Gcd, Multifactorial, Parity, Pow, PowerOf2, Square, Subfactorial, XMulYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom}; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u32; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u64; use malachite_base::num::factorization::prime_sieve::{id_to_n, limbs_prime_sieve_size, n_to_bit}; use malachite_base::num::logic::traits::{BitAccess, CountOnes, NotAssign, SignificantBits}; pub_test! {subfactorial_naive(n: u64) -> Natural { let mut f = Natural::ONE; let mut b = true; for i in 1..=n { f *= Natural::from(i); if b { f -= Natural::ONE; } else { f += Natural::ONE; } b.not_assign(); } f }} // Returns an approximation of the square root of x. // // It gives: // ``` // limb_apprsqrt(x) ^ 2 <= x < (limb_apprsqrt(x) + 1) ^ 2 // ``` // or // ``` // x <= limb_apprsqrt(x) ^ 2 <= x * 9 / 8 // ``` // // This is equivalent to `limb_apprsqrt` in `mpz/oddfac_1.c`, GMP 6.2.1. fn limbs_approx_sqrt(x: u64) -> u64 { assert!(x > 2); let s = x.significant_bits() >> 1; (u64::power_of_2(s) + (x >> s)) >> 1 } pub(crate) const fn bit_to_n(bit: u64) -> u64 { (bit * 3 + 4) | 1 } // `limbs_2_multiswing_odd` computes the odd part of the 2-multiswing factorial of the parameter n. // The result x is an odd positive integer so that multiswing(n, 2) = x * 2 ^ a. // // The algorithm is described by Peter Luschny in "Divide, Swing and Conquer the Factorial!". // // The pointer sieve points to `limbs_prime_sieve_size(n)` limbs containing a bit array where primes // are marked as 0. Enough limbs must be pointed by `factors`. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpz_2multiswing_1` from `mpz/oddfac_1.c`, GMP 6.2.1, where `x_and_sieve` // is provided as a single slice, allowing the sieve to be overwritten. #[allow(clippy::useless_conversion)] fn limbs_2_multiswing_odd( x_and_sieve: &mut [Limb], x_len: usize, mut n: Limb, factors: &mut [Limb], ) -> usize { assert!(n > 25); let mut prod = if n.odd() { n } else { 1 }; n.clear_bit(0); let max_prod = Limb::MAX / (n - 1); // Handle prime = 3 separately let mut j = 0; if prod > max_prod { factors[j] = prod; j += 1; prod = 1; } let mut q = n; while q >= 3 { q /= 3; if q.odd() { prod *= 3; } } let limb_n = n; let n = u64::exact_from(n); // Swing primes from 5 to n / 3 let mut s = limbs_approx_sqrt(n); assert!(s >= 5); s = n_to_bit(s); assert!(bit_to_n(s + 1).square() > n); assert!(s < n_to_bit(n / 3)); let start = const { n_to_bit(5) }; let mut index = bit_to_limb_count_floor(start); let mut mask = Limb::power_of_2(start & Limb::WIDTH_MASK); let sieve = &mut x_and_sieve[x_len..]; for i in start + 1..=s + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); if prod > max_prod { factors[j] = prod; j += 1; prod = 1; } let mut q = limb_n; while q >= prime { q /= prime; if q.odd() { prod *= prime; } } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } assert!(max_prod <= const { Limb::MAX / 3 }); let l_max_prod = max_prod * 3; for i in s + 2..=n_to_bit(n / 3) + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); if (limb_n / prime).odd() { if prod > l_max_prod { factors[j] = prod; j += 1; prod = prime; } else { prod *= prime; } } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } // Store primes from (n + 1) / 2 to n let start = n_to_bit(n >> 1) + 1; let mut index = bit_to_limb_count_floor(start); let mut mask = Limb::power_of_2(start & Limb::WIDTH_MASK); for i in start + 1..=n_to_bit(n) + 1 { if sieve[index] & mask == 0 { let prime = Limb::exact_from(id_to_n(i)); if prod > max_prod { factors[j] = prod; j += 1; prod = prime; } else { prod *= prime; } } mask <<= 1; if mask == 0 { mask = 1; index += 1; } } if j != 0 { factors[j] = prod; j += 1; match limbs_product(&mut x_and_sieve[..x_len], &mut factors[..j]) { (size, None) => size, (size, Some(new_x_and_sieve)) => { x_and_sieve[..size].copy_from_slice(&new_x_and_sieve[..size]); size } } } else { // not triggered by the first billion inputs fail_on_untested_path("limbs_2_multiswing_odd, j == 0"); x_and_sieve[0] = prod; 1 } } pub(crate) const FAC_DSC_THRESHOLD: usize = 236; const fn clb2(x: usize) -> usize { let floor_log_base_2 = (usize::WIDTH as usize - x.leading_zeros() as usize) - 1; if x.is_power_of_two() { floor_log_base_2 } else { floor_log_base_2 + 1 } } const FACTORS_PER_LIMB: usize = (Limb::WIDTH << 1) as usize / (clb2(FAC_DSC_THRESHOLD * FAC_DSC_THRESHOLD - 1) + 1) - 1; // n ^ log <= Limb::MAX: a limb can store log factors less than n. // // This is equivalent to log_n_max, `gmp-impl.h`, GMP 6.2.1. pub(crate) fn log_n_max(n: Limb) -> u64 { // NTH_ROOT_NUMB_MASK_TABLE[0] is Limb::MAX, so a match will always be found u64::wrapping_from( NTH_ROOT_NUMB_MASK_TABLE .iter() .rposition(|&x| n <= x) .unwrap(), ) + 1 } // `limbs_odd_factorial` computes the odd part of the factorial of the parameter n, i.e. n! = x * 2 // ^ a, where x is the returned value: an odd positive integer. // // If `double` is `true`, a square is skipped in the DSC part, e.g. if n is odd, n > // FAC_DSC_THRESHOLD and `double` is true, x is set to n!!. // // If n is too small, `double` is ignored, and an assert can be triggered. // // TODO: FAC_DSC_THRESHOLD is used here with two different roles: // - to decide when prime factorisation is needed, // - to stop the recursion, once sieving is done. // Maybe two thresholds can do a better job. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpz_oddfac_1` from `mpz/oddfac_1.c`, GMP 6.2.1. pub_crate_test! { #[allow(clippy::redundant_comparisons)] limbs_odd_factorial(n: usize, double: bool) -> Vec { assert!(Limb::convertible_from(n)); if double { assert!(n > ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 && n >= FAC_DSC_THRESHOLD); } if n <= ODD_FACTORIAL_TABLE_LIMIT { vec![ONE_LIMB_ODD_FACTORIAL_TABLE[n]] } else if n <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 { let (hi, lo) = Limb::x_mul_y_to_zz( ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE[(n - 1) >> 1], ONE_LIMB_ODD_FACTORIAL_TABLE[n >> 1], ); vec![lo, hi] } else { // Compute the number of recursive steps for the DSC algorithm let mut m = n; let mut s = 0; while m >= FAC_DSC_THRESHOLD { m >>= 1; s += 1; } let mut factors = vec![0; m / FACTORS_PER_LIMB + 1]; assert!(m >= FACTORS_PER_LIMB); const LIMIT_P1: usize = ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1; assert!(m > LIMIT_P1); let mut j = 0; let mut prod = 1; let mut max_prod = const { Limb::MAX / (FAC_DSC_THRESHOLD * FAC_DSC_THRESHOLD) as Limb }; assert!(m > LIMIT_P1); loop { factors[j] = ODD_DOUBLEFACTORIAL_TABLE_MAX; j += 1; let mut diff = (m - ODD_DOUBLEFACTORIAL_TABLE_LIMIT) & const { 2usize.wrapping_neg() }; if diff & 2 != 0 { let f = (ODD_DOUBLEFACTORIAL_TABLE_LIMIT + diff) as Limb; if prod > max_prod { factors[j] = prod; j += 1; prod = f; } else { prod *= f; } diff -= 2; } if diff != 0 { let mut fac = (ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 2) * (ODD_DOUBLEFACTORIAL_TABLE_LIMIT + diff); loop { let f = fac as Limb; if prod > max_prod { factors[j] = prod; j += 1; prod = f; } else { prod *= f; } diff -= 4; fac += diff << 1; if diff == 0 { break; } } } max_prod <<= 2; m >>= 1; if m <= LIMIT_P1 { break; } } factors[j] = prod; j += 1; factors[j] = ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE[(m - 1) >> 1]; j += 1; factors[j] = ONE_LIMB_ODD_FACTORIAL_TABLE[m >> 1]; j += 1; let mut out = Vec::new(); let (out_size, new_out) = limbs_product(&mut out, &mut factors[..j]); out = new_out.unwrap(); out.truncate(out_size); if s != 0 { // Use the algorithm described by Peter Luschny in "Divide, Swing and Conquer the // Factorial!". let mut size = (n >> Limb::LOG_WIDTH) + 4; let n_m_1 = u64::exact_from(n - 1); assert!(limbs_prime_sieve_size::(n_m_1) < size - (size >> 1)); // 2-multiswing(n) < 2^(n - 1) * sqrt(n / pi) < 2 ^ (n + Limb::WIDTH); One more can be // overwritten by mul, another for the sieve. let mut swing_and_sieve = vec![0; size]; // Put the sieve on the second half; it will be overwritten by the last // `limbs_2_multiswing_odd`. let sieve_offset = (size >> 1) + 1; let ss_len = swing_and_sieve.len() - 1; #[cfg(feature = "32_bit_limbs")] let count = limbs_prime_sieve_u32(&mut swing_and_sieve[sieve_offset..ss_len], n_m_1); #[cfg(not(feature = "32_bit_limbs"))] let count = limbs_prime_sieve_u64(&mut swing_and_sieve[sieve_offset..ss_len], n_m_1); size = usize::exact_from((count + 1) / log_n_max(Limb::exact_from(n)) + 1); let mut factors = vec![0; size]; let mut out_len = out.len(); for i in (0..s).rev() { let ns = limbs_2_multiswing_odd( &mut swing_and_sieve, sieve_offset, Limb::exact_from(n >> i), &mut factors, ); let mut square; if double && i == 0 { size = out_len; square = vec![0; size]; square[..out_len].copy_from_slice(&out[..out_len]); } else { size = out_len << 1; square = vec![0; size]; let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_len)]; limbs_square_to_out(&mut square, &out[..out_len], &mut square_scratch); if square[size - 1] == 0 { size -= 1; } } out_len = size + ns; out.resize(out_len, 0); assert!(ns <= size); // n != n$ * floor(n / 2)! ^ 2 let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(size, ns)]; if limbs_mul_greater_to_out( &mut out, &square[..size], &swing_and_sieve[..ns], &mut mul_scratch, ) == 0 { out_len -= 1; } } } if *out.last().unwrap() == 0 { out.pop(); } out } }} const FAC_ODD_THRESHOLD: Limb = 24; #[cfg(feature = "32_bit_limbs")] const SMALL_FACTORIAL_LIMIT: u64 = 13; #[cfg(not(feature = "32_bit_limbs"))] const SMALL_FACTORIAL_LIMIT: u64 = 21; impl Factorial for Natural { /// Computes the factorial of a number. /// /// $$ /// f(n) = n! = 1 \times 2 \times 3 \times \cdots \times n. /// $$ /// /// $n! = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `n`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Factorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::factorial(0), 1); /// assert_eq!(Natural::factorial(1), 1); /// assert_eq!(Natural::factorial(2), 2); /// assert_eq!(Natural::factorial(3), 6); /// assert_eq!(Natural::factorial(4), 24); /// assert_eq!(Natural::factorial(5), 120); /// assert_eq!( /// Natural::factorial(100).to_string(), /// "9332621544394415268169923885626670049071596826438162146859296389521759999322991560894\ /// 1463976156518286253697920827223758251185210916864000000000000000000000000" /// ); /// ``` /// /// This is equivalent to `mpz_fac_ui` from `mpz/fac_ui.c`, GMP 6.2.1. #[allow(clippy::useless_conversion)] fn factorial(n: u64) -> Self { assert!(Limb::convertible_from(n)); if n < SMALL_FACTORIAL_LIMIT { Self::from(Limb::factorial(n)) } else if n < u64::from(FAC_ODD_THRESHOLD) { let mut factors = vec![0; usize::wrapping_from(n - SMALL_FACTORIAL_LIMIT) / FACTORS_PER_LIMB + 2]; factors[0] = Limb::factorial(SMALL_FACTORIAL_LIMIT - 1); let mut j = 1; let n = Limb::wrapping_from(n); let mut prod = n; const MAX_PROD: Limb = Limb::MAX / (FAC_ODD_THRESHOLD | 1); const LIMB_SMALL_FACTORIAL_LIMIT: Limb = SMALL_FACTORIAL_LIMIT as Limb; for i in (LIMB_SMALL_FACTORIAL_LIMIT..n).rev() { if prod > MAX_PROD { factors[j] = prod; j += 1; prod = i; } else { prod *= i; } } factors[j] = prod; j += 1; let mut xs = Vec::new(); let new_xs = limbs_product(&mut xs, &mut factors[..j]).1; xs = new_xs.unwrap(); Self::from_owned_limbs_asc(xs) } else { let count = if n <= TABLE_LIMIT_2N_MINUS_POPC_2N { u64::from(TABLE_2N_MINUS_POPC_2N[usize::exact_from((n >> 1) - 1)]) } else { n - CountOnes::count_ones(n) }; Self::from_owned_limbs_asc(limbs_odd_factorial(usize::exact_from(n), false)) << count } } } const FAC_2DSC_THRESHOLD: Limb = ((FAC_DSC_THRESHOLD << 1) | (FAC_DSC_THRESHOLD & 1)) as Limb; impl DoubleFactorial for Natural { /// Computes the double factorial of a number. /// /// $$ /// f(n) = n!! = n \times (n - 2) \times (n - 4) \times \cdots \times i, /// $$ /// where $i$ is 1 if $n$ is odd and $2$ if $n$ is even. /// /// $n!! = O(\sqrt{n}(n/e)^{n/2})$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::DoubleFactorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::double_factorial(0), 1); /// assert_eq!(Natural::double_factorial(1), 1); /// assert_eq!(Natural::double_factorial(2), 2); /// assert_eq!(Natural::double_factorial(3), 3); /// assert_eq!(Natural::double_factorial(4), 8); /// assert_eq!(Natural::double_factorial(5), 15); /// assert_eq!(Natural::double_factorial(6), 48); /// assert_eq!(Natural::double_factorial(7), 105); /// assert_eq!( /// Natural::double_factorial(99).to_string(), /// "2725392139750729502980713245400918633290796330545803413734328823443106201171875" /// ); /// assert_eq!( /// Natural::double_factorial(100).to_string(), /// "34243224702511976248246432895208185975118675053719198827915654463488000000000000" /// ); /// ``` /// /// This is equivalent to `mpz_2fac_ui` from `mpz/2fac_ui.c`, GMP 6.2.1. fn double_factorial(n: u64) -> Self { assert!(Limb::convertible_from(n)); if n.even() { // n is even, n = 2k, (2k)!! = k! 2^k let half_n = usize::wrapping_from(n >> 1); let count = if n <= TABLE_LIMIT_2N_MINUS_POPC_2N && n != 0 { u64::from(TABLE_2N_MINUS_POPC_2N[half_n - 1]) } else { n - CountOnes::count_ones(n) }; Self::from_owned_limbs_asc(limbs_odd_factorial(half_n, false)) << count } else if n <= u64::wrapping_from(ODD_DOUBLEFACTORIAL_TABLE_LIMIT) { Self::from(ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE[usize::wrapping_from(n >> 1)]) } else if n < u64::wrapping_from(FAC_2DSC_THRESHOLD) { let mut factors = vec![0; usize::exact_from(n) / (FACTORS_PER_LIMB << 1) + 1]; factors[0] = ODD_DOUBLEFACTORIAL_TABLE_MAX; let mut j = 1; let mut n = Limb::wrapping_from(n); let mut prod = n; let max_prod = Limb::MAX / FAC_2DSC_THRESHOLD; const LIMIT: Limb = ODD_DOUBLEFACTORIAL_TABLE_LIMIT as Limb + 2; while n > LIMIT { n -= 2; if prod > max_prod { factors[j] = prod; j += 1; prod = n; } else { prod *= n; } } factors[j] = prod; j += 1; let mut xs = Vec::new(); let new_xs = limbs_product(&mut xs, &mut factors[..j]).1; xs = new_xs.unwrap(); Self::from_owned_limbs_asc(xs) } else { Self::from_owned_limbs_asc(limbs_odd_factorial(usize::exact_from(n), true)) } } } impl Multifactorial for Natural { /// Computes a multifactorial of a number. /// /// $$ /// f(n, m) = n!^{(m)} = n \times (n - m) \times (n - 2m) \times \cdots \times i. /// $$ /// If $n$ is divisible by $m$, then $i$ is $m$; otherwise, $i$ is the remainder when $n$ is /// divided by $m$. /// /// $n!^{(m)} = O(\sqrt{n}(n/e)^{n/m})$. /// /// # Worst-case complexity /// $T(n, m) = O(n (\log n)^2 \log\log n)$ /// /// $M(n, m) = O(n \log n)$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Multifactorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::multifactorial(0, 1), 1); /// assert_eq!(Natural::multifactorial(1, 1), 1); /// assert_eq!(Natural::multifactorial(2, 1), 2); /// assert_eq!(Natural::multifactorial(3, 1), 6); /// assert_eq!(Natural::multifactorial(4, 1), 24); /// assert_eq!(Natural::multifactorial(5, 1), 120); /// /// assert_eq!(Natural::multifactorial(0, 2), 1); /// assert_eq!(Natural::multifactorial(1, 2), 1); /// assert_eq!(Natural::multifactorial(2, 2), 2); /// assert_eq!(Natural::multifactorial(3, 2), 3); /// assert_eq!(Natural::multifactorial(4, 2), 8); /// assert_eq!(Natural::multifactorial(5, 2), 15); /// assert_eq!(Natural::multifactorial(6, 2), 48); /// assert_eq!(Natural::multifactorial(7, 2), 105); /// /// assert_eq!(Natural::multifactorial(0, 3), 1); /// assert_eq!(Natural::multifactorial(1, 3), 1); /// assert_eq!(Natural::multifactorial(2, 3), 2); /// assert_eq!(Natural::multifactorial(3, 3), 3); /// assert_eq!(Natural::multifactorial(4, 3), 4); /// assert_eq!(Natural::multifactorial(5, 3), 10); /// assert_eq!(Natural::multifactorial(6, 3), 18); /// assert_eq!(Natural::multifactorial(7, 3), 28); /// assert_eq!(Natural::multifactorial(8, 3), 80); /// assert_eq!(Natural::multifactorial(9, 3), 162); /// /// assert_eq!( /// Natural::multifactorial(100, 3).to_string(), /// "174548867015437739741494347897360069928419328000000000" /// ); /// ``` fn multifactorial(mut n: u64, mut m: u64) -> Self { assert_ne!(m, 0); assert!(Limb::convertible_from(n)); assert!(Limb::convertible_from(m)); if n < 3 || n - 3 < m - 1 { // n < 3 || n - 1 <= m if n == 0 { Self::ONE } else { Self::from(n) } } else { // 0 < m < n - 1 < Limb::MAX let gcd = n.gcd(m); if gcd > 1 { n /= gcd; m /= gcd; } if m <= 2 { // fac or 2fac if m == 1 { match gcd { gcd if gcd > 2 => Self::from(gcd).pow(n) * Self::factorial(n), 2 => Self::double_factorial(n << 1), _ => Self::factorial(n), } } else if gcd > 1 { // m == 2 Self::from(gcd).pow((n >> 1) + 1) * Self::double_factorial(n) } else { Self::double_factorial(n) } } else { // m >= 3, gcd(n,m) = 1 let reduced_n = n / m + 1; let mut n = Limb::exact_from(n); let m = Limb::exact_from(m); let mut j = 0; let mut prod = n; n -= m; let max_prod = Limb::MAX / n; let mut factors = vec![0; usize::exact_from(reduced_n / log_n_max(n) + 2)]; while n > m { if prod > max_prod { factors[j] = prod; j += 1; prod = n; } else { prod *= n; } n -= m; } factors[j] = n; j += 1; factors[j] = prod; j += 1; let mut xs = Vec::new(); let new_xs = limbs_product(&mut xs, &mut factors[..j]).1; xs = new_xs.unwrap(); let x = Self::from_owned_limbs_asc(xs); if gcd == 1 { x } else { Self::from(gcd).pow(reduced_n) * x } } } } } impl Subfactorial for Natural { /// Computes the subfactorial of a number. /// /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a /// derangement is a permutation with no fixed points. /// /// $$ /// f(n) = \\ !n = \lfloor n!/e \rfloor. /// $$ /// /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Subfactorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::subfactorial(0), 1); /// assert_eq!(Natural::subfactorial(1), 0); /// assert_eq!(Natural::subfactorial(2), 1); /// assert_eq!(Natural::subfactorial(3), 2); /// assert_eq!(Natural::subfactorial(4), 9); /// assert_eq!(Natural::subfactorial(5), 44); /// assert_eq!( /// Natural::subfactorial(100).to_string(), /// "3433279598416380476519597752677614203236578380537578498354340028268518079332763243279\ /// 1396429850988990237345920155783984828001486412574060553756854137069878601" /// ); /// ``` #[inline] fn subfactorial(n: u64) -> Self { subfactorial_naive(n) } } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 2004-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_to_out_aliased_2, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::float_add::RoundBit::*; use crate::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::{ LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor, limb_to_bit_count, }; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ NegModPowerOf2, OverflowingAddAssign, Parity, PowerOf2, SaturatingAddAssign, WrappingAddAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_test_zero; const TWICE_WIDTH: u64 = Limb::WIDTH * 2; const THRICE_WIDTH: u64 = Limb::WIDTH * 3; pub fn add_float_significands_in_place( mut x: &mut Natural, x_exp: &mut i32, x_prec: u64, mut y: &mut Natural, y_exp: i32, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Ordering, bool) { if x_prec == y_prec && out_prec == x_prec { add_float_significands_in_place_same_prec(x, x_exp, y, y_exp, out_prec, rm) } else if *x_exp >= y_exp { match (&mut x, &mut y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, &[*small_y], y_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; (o, false) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, &[*small_y], y_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; (o, false) } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, ys, y_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; (o, false) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, ys, y_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; (o, false) } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, &[*small_y], y_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; (o, false) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, &[*small_y], y_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; (o, false) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, ys, y_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; (o, false) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, ys, y_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; (o, false) } } } } else { match (&mut x, &mut y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, &[*small_x], *x_exp, out_prec, rm, ); *small_y = out[0]; *x_exp = out_exp; (o, true) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, &[*small_x], *x_exp, out_prec, rm, ); *y = Natural(Large(out)); *x_exp = out_exp; (o, true) } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, &[*small_x], *x_exp, out_prec, rm, ); *y = Natural(Small(out[0])); *x_exp = out_exp; (o, true) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, &[*small_x], *x_exp, out_prec, rm, ); *ys = out; *x_exp = out_exp; (o, true) } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, xs, *x_exp, out_prec, rm, ); *small_y = out[0]; *x_exp = out_exp; (o, true) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, xs, *x_exp, out_prec, rm, ); *y = Natural(Large(out)); *x_exp = out_exp; (o, true) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, xs, *x_exp, out_prec, rm, ); *y = Natural(Small(out[0])); *x_exp = out_exp; (o, true) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, xs, *x_exp, out_prec, rm, ); *ys = out; *x_exp = out_exp; (o, true) } } } } } pub fn add_float_significands_in_place_ref( mut x: &mut Natural, x_exp: &mut i32, x_prec: u64, y: &Natural, y_exp: i32, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> Ordering { if x_prec == y_prec && out_prec == x_prec { add_float_significands_in_place_same_prec_ref(x, x_exp, y, y_exp, out_prec, rm) } else if *x_exp >= y_exp { match (&mut x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, &[*small_y], y_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, &[*small_y], y_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; o } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, ys, y_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_x], *x_exp, ys, y_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; o } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, &[*small_y], y_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, &[*small_y], y_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; o } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, ys, y_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, *x_exp, ys, y_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; o } } } } else { match (&mut x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, &[*small_x], *x_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, &[*small_x], *x_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; o } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, &[*small_x], *x_exp, out_prec, rm, ); *small_x = out[0]; *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, &[*small_x], *x_exp, out_prec, rm, ); *x = Natural(Large(out)); *x_exp = out_exp; o } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, xs, *x_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*small_y], y_exp, xs, *x_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; o } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, xs, *x_exp, out_prec, rm, ); *x = Natural(Small(out[0])); *x_exp = out_exp; o } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, ys, y_exp, xs, *x_exp, out_prec, rm, ); *xs = out; *x_exp = out_exp; o } } } } } pub fn add_float_significands_ref_ref<'a>( mut x: &'a Natural, mut x_exp: i32, mut x_prec: u64, mut y: &'a Natural, mut y_exp: i32, mut y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { if x_prec == y_prec && out_prec == x_prec { add_float_significands_same_prec_ref_ref(x, x_exp, y, y_exp, out_prec, rm) } else { if x_exp < y_exp { swap(&mut x, &mut y); swap(&mut x_exp, &mut y_exp); swap(&mut x_prec, &mut y_prec); } match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*x], x_exp, &[*y], y_exp, out_prec, rm, ); (Natural(Small(out[0])), out_exp, o) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*x], x_exp, &[*y], y_exp, out_prec, rm, ); (Natural(Large(out)), out_exp, o) } } (Natural(Small(x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, &[*x], x_exp, ys, y_exp, out_prec, rm, ); (Natural(Small(out[0])), out_exp, o) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, &[*x], x_exp, ys, y_exp, out_prec, rm, ); (Natural(Large(out)), out_exp, o) } } (Natural(Large(xs)), Natural(Small(y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, x_exp, &[*y], y_exp, out_prec, rm, ); (Natural(Small(out[0])), out_exp, o) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, x_exp, &[*y], y_exp, out_prec, rm, ); (Natural(Large(out)), out_exp, o) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o) = add_float_significands_general( &mut out, xs, x_exp, ys, y_exp, out_prec, rm, ); (Natural(Small(out[0])), out_exp, o) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o) = add_float_significands_general( &mut out, xs, x_exp, ys, y_exp, out_prec, rm, ); (Natural(Large(out)), out_exp, o) } } } } } // This is mpfr_add1sp from add1sp.c, MPFR 4.2.0. fn add_float_significands_in_place_same_prec( x: &mut Natural, x_exp: &mut i32, y: &mut Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Ordering, bool) { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (sum, sum_exp, o) = if prec == Limb::WIDTH { add_float_significands_same_prec_w(*x, *x_exp, *y, y_exp, rm) } else { add_float_significands_same_prec_lt_w(*x, *x_exp, *y, y_exp, prec, rm) }; *x = sum; *x_exp = sum_exp; (o, false) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_mut_slice()) { ([x_0, x_1], [y_0, y_1]) => { let (sum_0, sum_1, sum_exp, o) = if prec == TWICE_WIDTH { add_float_significands_same_prec_2w(*x_0, *x_1, *x_exp, *y_0, *y_1, y_exp, rm) } else { add_float_significands_same_prec_gt_w_lt_2w( *x_0, *x_1, *x_exp, *y_0, *y_1, y_exp, prec, rm, ) }; *x_0 = sum_0; *x_1 = sum_1; *x_exp = sum_exp; (o, false) } ([x_0, x_1, x_2], [y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (sum_0, sum_1, sum_2, sum_exp, o) = add_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *x_exp, *y_0, *y_1, *y_2, y_exp, prec, rm, ); *x_0 = sum_0; *x_1 = sum_1; *x_2 = sum_2; *x_exp = sum_exp; (o, false) } (xs_slice, ys_slice) => { let (sum_exp, o, swapped) = add_float_significands_same_prec_ge_3w_val_val( xs_slice, *x_exp, ys_slice, y_exp, prec, rm, ); *x_exp = sum_exp; (o, swapped) } }, _ => unreachable!(), } } // This is mpfr_add1sp from add1sp.c, MPFR 4.2.0. fn add_float_significands_in_place_same_prec_ref( x: &mut Natural, x_exp: &mut i32, y: &Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> Ordering { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (sum, sum_exp, o) = if prec == Limb::WIDTH { add_float_significands_same_prec_w(*x, *x_exp, *y, y_exp, rm) } else { add_float_significands_same_prec_lt_w(*x, *x_exp, *y, y_exp, prec, rm) }; *x = sum; *x_exp = sum_exp; o } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_slice()) { ([x_0, x_1], &[y_0, y_1]) => { let (sum_0, sum_1, sum_exp, o) = if prec == TWICE_WIDTH { add_float_significands_same_prec_2w(*x_0, *x_1, *x_exp, y_0, y_1, y_exp, rm) } else { add_float_significands_same_prec_gt_w_lt_2w( *x_0, *x_1, *x_exp, y_0, y_1, y_exp, prec, rm, ) }; *x_0 = sum_0; *x_1 = sum_1; *x_exp = sum_exp; o } ([x_0, x_1, x_2], &[y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (sum_0, sum_1, sum_2, sum_exp, o) = add_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *x_exp, y_0, y_1, y_2, y_exp, prec, rm, ); *x_0 = sum_0; *x_1 = sum_1; *x_2 = sum_2; *x_exp = sum_exp; o } (xs, ys) => { if *x_exp >= y_exp { let (sum_exp, o) = add_float_significands_same_prec_ge_3w_val_ref( xs, *x_exp, ys, y_exp, prec, rm, ); *x_exp = sum_exp; o } else { let (sum_exp, o) = add_float_significands_same_prec_ge_3w_ref_val( ys, y_exp, xs, *x_exp, prec, rm, ); *x_exp = sum_exp; o } } }, _ => unreachable!(), } } // This is mpfr_add1sp from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_ref_ref( x: &Natural, x_exp: i32, y: &Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (sum, sum_exp, o) = if prec == Limb::WIDTH { add_float_significands_same_prec_w(*x, x_exp, *y, y_exp, rm) } else { add_float_significands_same_prec_lt_w(*x, x_exp, *y, y_exp, prec, rm) }; (Natural(Small(sum)), sum_exp, o) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { (&[x_0, x_1], &[y_0, y_1]) => { let (sum_0, sum_1, sum_exp, o) = if prec == TWICE_WIDTH { add_float_significands_same_prec_2w(x_0, x_1, x_exp, y_0, y_1, y_exp, rm) } else { add_float_significands_same_prec_gt_w_lt_2w( x_0, x_1, x_exp, y_0, y_1, y_exp, prec, rm, ) }; (Natural(Large(vec![sum_0, sum_1])), sum_exp, o) } (&[x_0, x_1, x_2], &[y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (sum_0, sum_1, sum_2, sum_exp, o) = add_float_significands_same_prec_gt_2w_lt_3w( x_0, x_1, x_2, x_exp, y_0, y_1, y_2, y_exp, prec, rm, ); (Natural(Large(vec![sum_0, sum_1, sum_2])), sum_exp, o) } (xs, ys) => { let mut out = vec![0; xs.len()]; let (sum_exp, o) = add_float_significands_same_prec_ge_3w_ref_ref( &mut out, xs, x_exp, ys, y_exp, prec, rm, ); (Natural(Large(out)), sum_exp, o) } }, _ => unreachable!(), } } const WIDTH_M1: u64 = Limb::WIDTH - 1; // This is mpfr_add1sp1 from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_lt_w( mut x: Limb, mut x_exp: i32, mut y: Limb, mut y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Limb, i32, Ordering) { assert!(prec < Limb::WIDTH); let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let (mut sum, sticky_bit, round_bit) = if x_exp == y_exp { // The following line is probably better than // ``` // sum = LIMB_HIGH_BIT | ((x + y) >> 1); // ``` // as it has less dependency and doesn't need a long constant on some processors. On ARM, it // can also probably benefit from shift-and-op in a better way. Timings cannot be // conclusive. let sum = (x >> 1) + (y >> 1); x_exp.saturating_add_assign(1); let round_bit = sum & (shift_bit >> 1); // since x + y fits on prec + 1 bits, the sticky bit is zero (sum ^ round_bit, 0, round_bit) } else { if x_exp < y_exp { swap(&mut x_exp, &mut y_exp); swap(&mut x, &mut y); } let exp_diff = u64::exact_from(x_exp - y_exp); let mask = shift_bit - 1; if exp_diff < shift { // we can shift y by exp_diff bits to the right without losing any bit. Moreover, we can // shift one more if there is an exponent increase. let (mut sum, overflow) = x.overflowing_add(y >> exp_diff); if overflow { // carry assert!(sum.even()); sum = LIMB_HIGH_BIT | (sum >> 1); x_exp.saturating_add_assign(1); } let round_bit = sum & (shift_bit >> 1); (sum & !mask, (sum & mask) ^ round_bit, round_bit) } else if exp_diff < Limb::WIDTH { // shift <= exp_diff < Limb::WIDTH let mut sticky_bit = y << (Limb::WIDTH - exp_diff); // bits from y[-1] after shift let (mut sum, overflow) = x.overflowing_add(y >> exp_diff); if overflow { // carry sticky_bit |= sum & 1; sum = LIMB_HIGH_BIT | (sum >> 1); x_exp.saturating_add_assign(1); } let round_bit = sum & (shift_bit >> 1); ( sum & !mask, sticky_bit | ((sum & mask) ^ round_bit), round_bit, ) } else { // - exp_diff >= Limb::WIDTH // - round_bit == 0 since prec < Limb::WIDTH // - sticky_bit == 1 since y != 0 (x, 1, 0) } }; if round_bit == 0 && sticky_bit == 0 { (sum, x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (sum & shift_bit) == 0) { (sum, x_exp, Less) } else if sum.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum, x_exp, Greater) } } Floor | Down => (sum, x_exp, Less), Ceiling | Up => { if sum.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum, x_exp, Greater) } } } } } // This is mpfr_add1sp1n from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_w( mut x: Limb, mut x_exp: i32, mut y: Limb, mut y_exp: i32, rm: RoundingMode, ) -> (Limb, i32, Ordering) { let (mut sum, sticky_bit, round_bit) = if x_exp == y_exp { let sum = x.wrapping_add(y); x_exp.saturating_add_assign(1); // since x + y fits on Limb::WIDTH + 1 bits, the sticky bit is zero (LIMB_HIGH_BIT | (sum >> 1), 0, sum & 1) } else { if x_exp < y_exp { swap(&mut x, &mut y); swap(&mut x_exp, &mut y_exp); } let exp_diff = u64::exact_from(x_exp - y_exp); if exp_diff < Limb::WIDTH { // - 1 <= exp_diff < Limb::WIDTH // - bits from y[-1] after shift let sticky_bit = y << (Limb::WIDTH - exp_diff); let (sum, overflow) = x.overflowing_add(y >> exp_diff); if overflow { // carry x_exp.saturating_add_assign(1); (LIMB_HIGH_BIT | (sum >> 1), sticky_bit, sum & 1) } else { // no carry (sum, sticky_bit & !LIMB_HIGH_BIT, sticky_bit & LIMB_HIGH_BIT) } } else { let round = exp_diff == Limb::WIDTH; // exp_diff >= Limb::WIDTH ( x, Limb::from(!round || y != LIMB_HIGH_BIT), Limb::from(round), ) } }; if round_bit == 0 && sticky_bit == 0 { (sum, x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (sum & 1) == 0) { (sum, x_exp, Less) } else if sum.overflowing_add_assign(1) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum, x_exp, Greater) } } Floor | Down => (sum, x_exp, Less), Ceiling | Up => { if sum.overflowing_add_assign(1) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum, x_exp, Greater) } } } } } // This is mpfr_add1sp2 from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_gt_w_lt_2w( mut x_0: Limb, mut x_1: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, i32, Ordering) { let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let shift_m1_bit = shift_bit >> 1; let (mut sum_0, mut sum_1, round_bit, sticky_bit) = if x_exp == y_exp { // since x_1, y_1 >= LIMB_HIGH_BIT, a carry always occurs let (mut a0, overflow) = x_0.overflowing_add(y_0); let mut a1 = x_1.wrapping_add(y_1); if overflow { a1.wrapping_add_assign(1); } a0 = (a0 >> 1) | (a1 << WIDTH_M1); x_exp.saturating_add_assign(1); let round_bit = a0 & shift_m1_bit; // Since x + y fits on prec + 1 bits, the sticky bit is zero. ( a0 ^ round_bit, LIMB_HIGH_BIT | (a1 >> 1), a0 & shift_m1_bit, 0, ) } else { if x_exp < y_exp { swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); swap(&mut x_exp, &mut y_exp); } let exp_diff = u64::exact_from(x_exp - y_exp); let mask = shift_bit - 1; if exp_diff < Limb::WIDTH { let comp_diff = Limb::WIDTH - exp_diff; // 0 < exp_diff < Limb::WIDTH let mut sticky_bit = y_0 << comp_diff; // bits from y[-1] after shift let (mut a0, overflow_1) = x_0.overflowing_add((y_1 << comp_diff) | (y_0 >> exp_diff)); let (mut a1, mut overflow_2) = x_1.overflowing_add(y_1 >> exp_diff); if overflow_1 { overflow_2 |= a1.overflowing_add_assign(1); } let sum_1 = if overflow_2 { // carry in high word sticky_bit |= a0 & 1; // shift a by 1 a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); LIMB_HIGH_BIT | (a1 >> 1) } else { a1 }; let round_bit = a0 & shift_m1_bit; ( a0 & !mask, sum_1, round_bit, sticky_bit | (a0 & mask) ^ round_bit, ) } else if exp_diff < TWICE_WIDTH { // Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 let mut sticky_bit = if exp_diff == Limb::WIDTH { y_0 } else { y_0 | (y_1 << (TWICE_WIDTH - exp_diff)) }; let (mut a0, overflow_1) = x_0.overflowing_add(y_1 >> (exp_diff - Limb::WIDTH)); let (a1, overflow_2) = if overflow_1 { x_1.overflowing_add(1) } else { (x_1, false) }; if overflow_2 { sticky_bit |= a0 & 1; // shift a by 1 a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); let round_bit = a0 & shift_m1_bit; ( a0 & !mask, LIMB_HIGH_BIT | (a1 >> 1), a0 & shift_m1_bit, sticky_bit | (a0 & mask) ^ round_bit, ) } else { let round_bit = a0 & shift_m1_bit; ( a0 & !mask, a1, round_bit, sticky_bit | (a0 & mask) ^ round_bit, ) } } else { // - exp_diff >= TWICE_WIDTH // - round_bit == 0 since prec < TWICE_WIDTH // - sticky_bit == since y != 0 (x_0, x_1, 0, 1) } }; if round_bit == 0 && sticky_bit == 0 { (sum_0, sum_1, x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (sum_0 & shift_bit) == 0) { (sum_0, sum_1, x_exp, Less) } else if sum_0.overflowing_add_assign(shift_bit) && sum_1.overflowing_add_assign(1) { (sum_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum_0, sum_1, x_exp, Greater) } } Floor | Down => (sum_0, sum_1, x_exp, Less), Ceiling | Up => { if sum_0.overflowing_add_assign(shift_bit) && sum_1.overflowing_add_assign(1) { (sum_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum_0, sum_1, x_exp, Greater) } } } } } // This is mpfr_add1sp2n from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_2w( mut x_0: Limb, mut x_1: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_exp: i32, rm: RoundingMode, ) -> (Limb, Limb, i32, Ordering) { let (mut sum_0, mut sum_1, round_bit, sticky_bit) = if x_exp == y_exp { // Since x_1, y_1 >= LIMB_HIGH_BIT, a carry always occurs. let (a0, overflow) = x_0.overflowing_add(y_0); let mut a1 = x_1.wrapping_add(y_1); if overflow { a1.wrapping_add_assign(1); } x_exp.saturating_add_assign(1); // Since x + y fits on prec + 1 bits, the sticky bit is zero. ( (a1 << WIDTH_M1) | (a0 >> 1), LIMB_HIGH_BIT | (a1 >> 1), a0 & 1, 0, ) } else { if x_exp < y_exp { swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); swap(&mut x_exp, &mut y_exp); } let exp_diff = u64::exact_from(x_exp - y_exp); if exp_diff >= TWICE_WIDTH { if exp_diff == TWICE_WIDTH { (x_0, x_1, 1, Limb::from(y_0 != 0 || y_1 > LIMB_HIGH_BIT)) } else { (x_0, x_1, 0, 1) } } else { // First, compute (a0, a1) = x + (y >> exp_diff), and determine the sticky bit from the // bits shifted out such that (MSB, other bits) is regarded as (rounding bit, sticky // bit), assuming no carry. let (sum_0, sum_1, sticky_bit) = if exp_diff < Limb::WIDTH { // 0 < exp_diff < Limb::WIDTH let comp_diff = Limb::WIDTH - exp_diff; let (sum_0, overflow) = x_0.overflowing_add((y_1 << comp_diff) | (y_0 >> exp_diff)); let mut sum_1 = x_1.wrapping_add(y_1 >> exp_diff); if overflow { sum_1.wrapping_add_assign(1); } (sum_0, sum_1, y_0 << comp_diff) } else { // Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 The most significant bit of sb should // be the rounding bit, while the other bits represent the sticky bit: // * If exp_diff = Limb::WIDTH, we get y_0; // * If exp_diff > Limb::WIDTH: we get the least exp_diff - Limb::WIDTH bits of y_1, // and those from y_0 as the LSB of sticky_bit. let sticky_bit = if exp_diff == Limb::WIDTH { y_0 } else { (y_1 << (TWICE_WIDTH - exp_diff)) | Limb::from(y_0 != 0) }; let (sum_0, overflow) = x_0.overflowing_add(y_1 >> (exp_diff - Limb::WIDTH)); ( sum_0, if overflow { x_1.wrapping_add(1) } else { x_1 }, sticky_bit, ) }; if sum_1 < x_1 { // carry in high word let round_bit = sum_0 << WIDTH_M1; // Shift the result by 1 to the right. x_exp.saturating_add_assign(1); ( (sum_1 << WIDTH_M1) | (sum_0 >> 1), LIMB_HIGH_BIT | (sum_1 >> 1), round_bit, sticky_bit, ) } else { (sum_0, sum_1, sticky_bit & LIMB_HIGH_BIT, sticky_bit << 1) } } }; if round_bit == 0 && sticky_bit == 0 { (sum_0, sum_1, x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (sum_0 & 1) == 0) { (sum_0, sum_1, x_exp, Less) } else if sum_0.overflowing_add_assign(1) && sum_1.overflowing_add_assign(1) { (sum_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum_0, sum_1, x_exp, Greater) } } Floor | Down => (sum_0, sum_1, x_exp, Less), Ceiling | Up => { if sum_0.overflowing_add_assign(1) && sum_1.overflowing_add_assign(1) { (sum_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater) } else { (sum_0, sum_1, x_exp, Greater) } } } } } // This is mpfr_add1sp3 from add1sp.c, MPFR 4.2.0. fn add_float_significands_same_prec_gt_2w_lt_3w( mut x_0: Limb, mut x_1: Limb, mut x_2: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_2: Limb, mut y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, Limb, i32, Ordering) { let shift = THRICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let shift_m1_bit = shift_bit >> 1; let (mut sum_0, mut sum_1, mut sum_2, round_bit, sticky_bit) = if x_exp == y_exp { // Since x_2, y_2 >= LIMB_HIGH_BIT, a carry always occurs let (mut a0, overflow_1) = x_0.overflowing_add(y_0); let (mut a1, mut overflow_2) = x_1.overflowing_add(y_1); if overflow_1 { overflow_2 |= a1.overflowing_add_assign(1); } let mut a2 = x_2.wrapping_add(y_2); if overflow_2 || (a1 == x_1 && overflow_1) { a2.wrapping_add_assign(1); } // Since prec < 3 * Limb::WIDTH, we lose no bit in a0 >> 1. a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); let round_bit = a0 & shift_m1_bit; // Since x + y fits on prec + 1 bits, the sticky bit is zero. ( a0 ^ round_bit, (a2 << WIDTH_M1) | (a1 >> 1), LIMB_HIGH_BIT | (a2 >> 1), round_bit, 0, ) } else { if x_exp < y_exp { swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); swap(&mut x_2, &mut y_2); swap(&mut x_exp, &mut y_exp); } let exp_diff = u64::exact_from(x_exp - y_exp); let mask = shift_bit - 1; if exp_diff < Limb::WIDTH { // 0 < exp_diff < Limb::WIDTH let comp_diff = Limb::WIDTH - exp_diff; let mut sticky_bit = y_0 << comp_diff; // bits from y[-1] after shift let (mut a0, overflow_1) = x_0.overflowing_add((y_1 << comp_diff) | (y_0 >> exp_diff)); let (mut a1, mut overflow_2) = x_1.overflowing_add((y_2 << comp_diff) | (y_1 >> exp_diff)); if overflow_1 { overflow_2 |= a1.overflowing_add_assign(1); } let (mut a2, mut overflow_3) = x_2.overflowing_add(y_2 >> exp_diff); if overflow_2 { overflow_3 |= a2.overflowing_add_assign(1); } let (sum_1, sum_2) = if overflow_3 || (a2 == x_2 && overflow_2) { sticky_bit |= a0 & 1; // shift a by 1 a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); ((a2 << WIDTH_M1) | (a1 >> 1), LIMB_HIGH_BIT | (a2 >> 1)) } else { (a1, a2) }; let round_bit = a0 & shift_m1_bit; sticky_bit |= (a0 & mask) ^ round_bit; (a0 & !mask, sum_1, sum_2, round_bit, sticky_bit) } else if exp_diff < TWICE_WIDTH { // Limb::WIDTH <= exp_diff < Limb::WIDTH * 2 let comp_diff = exp_diff - Limb::WIDTH; let comp_diff_2 = TWICE_WIDTH - exp_diff; let mut sticky_bit = if exp_diff == Limb::WIDTH { y_0 } else { (y_1 << comp_diff_2) | y_0 }; let y0shifted = if exp_diff == Limb::WIDTH { y_1 } else { (y_2 << comp_diff_2) | (y_1 >> comp_diff) }; let (mut a0, overflow_1) = x_0.overflowing_add(y0shifted); let (mut a1, mut overflow_2) = x_1.overflowing_add(y_2 >> comp_diff); if overflow_1 { overflow_2 |= a1.overflowing_add_assign(1); } // If a1 < x_1, there was a carry in the above addition, or when a1 = x_1 and one of the // added terms is nonzero (the sum of b_2 >> (exp_diff - Limb::WIDTH) and a0 < x_0 is at // most 2 ^ Limb::WIDTH - exp_diff) let (a2, overflow_3) = if overflow_2 || (a1 == x_1 && overflow_1) { x_2.overflowing_add(1) } else { (x_2, false) }; if overflow_3 { sticky_bit |= a0 & 1; // shift a by 1 a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); let round_bit = a0 & shift_m1_bit; sticky_bit |= (a0 & mask) ^ round_bit; ( a0 & !mask, (a2 << WIDTH_M1) | (a1 >> 1), LIMB_HIGH_BIT | (a2 >> 1), round_bit, sticky_bit, ) } else { let round_bit = a0 & shift_m1_bit; sticky_bit |= (a0 & mask) ^ round_bit; (a0 & !mask, a1, a2, round_bit, sticky_bit) } } else if exp_diff < THRICE_WIDTH { // Limb::WIDTH * 2 <= exp_diff < Limb::WIDTH * 3 let mut sticky_bit = if exp_diff == TWICE_WIDTH { y_1 | y_0 } else { (y_2 << (THRICE_WIDTH - exp_diff)) | y_1 | y_0 }; let (mut a0, overflow_1) = x_0.overflowing_add(y_2 >> (exp_diff - TWICE_WIDTH)); let (a1, overflow_2) = if overflow_1 { x_1.overflowing_add(1) } else { (x_1, false) }; let a2 = if overflow_2 { x_2.wrapping_add(1) } else { x_2 }; if a2 == 0 { sticky_bit |= a0 & 1; // shift a by 1 a0 = (a1 << WIDTH_M1) | (a0 >> 1); x_exp.saturating_add_assign(1); let round_bit = a0 & shift_m1_bit; sticky_bit |= (a0 & mask) ^ round_bit; ( a0 & !mask, (a2 << WIDTH_M1) | (a1 >> 1), LIMB_HIGH_BIT | (a2 >> 1), round_bit, sticky_bit, ) } else { let round_bit = a0 & shift_m1_bit; sticky_bit |= (a0 & mask) ^ round_bit; (a0 & !mask, a1, a2, round_bit, sticky_bit) } } else { // - exp_diff >= Limb::WIDTH * 2 // - round_bit == 0 since prec < Limb::WIDTH * 3 // - sticky_bit == 1 since c != 0 (x_0, x_1, x_2, 0, 1) } }; if round_bit == 0 && sticky_bit == 0 { (sum_0, sum_1, sum_2, x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (sum_0 & shift_bit) == 0) { (sum_0, sum_1, sum_2, x_exp, Less) } else { if sum_0.overflowing_add_assign(shift_bit) { sum_1.wrapping_add_assign(1); } if sum_1 == 0 && sum_0 == 0 { sum_2.wrapping_add_assign(1); } if sum_2 == 0 { ( sum_0, sum_1, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, ) } else { (sum_0, sum_1, sum_2, x_exp, Greater) } } } Floor | Down => (sum_0, sum_1, sum_2, x_exp, Less), Ceiling | Up => { if sum_0.overflowing_add_assign(shift_bit) { sum_1.wrapping_add_assign(1); } if sum_1 == 0 && sum_0 == 0 { sum_2.wrapping_add_assign(1); } if sum_2 == 0 { ( sum_0, sum_1, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, ) } else { (sum_0, sum_1, sum_2, x_exp, Greater) } } } } } // out <- x + y >> r where d = q * Limb::WIDTH + r. Return the carry at out[n + 1] (0 or 1) and // return low so that: // * the most significant bit of low would be that of out[-1] if we would compute one more limb of // the (infinite) addition // * the Limb::WIDTH - 1 least significant bits of low are zero iff all bits of out[-1], out[-2], // ... would be zero (except the most significant bit of out[-1]). // // Assume 0 < exp_diff < Limb::WIDTH * n. // // This is mpfr_addrsh from add1sp.c, MPFR 4.2.0, returning `low` before `carry`, where ap != bp and // ap != cp. fn add_significands_rsh_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], exp_diff: u64, ) -> (Limb, bool) { let n = xs.len(); assert_eq!(ys.len(), n); let out = &mut out[..n]; if exp_diff < Limb::WIDTH { // out <- x + y >> d assert_ne!(exp_diff, 0); let comp_diff = Limb::WIDTH - exp_diff; // Thus 0 < Limb::WIDTH - exp_diff < Limb::WIDTH let low = ys[0] << comp_diff; let mut carry = false; let (out_last, out_init) = out.split_last_mut().unwrap(); let (xs_last, xs_init) = xs.split_last().unwrap(); for (i, (o, &x)) in out_init.iter_mut().zip(xs_init.iter()).enumerate() { let mut carry_2; (*o, carry_2) = x.overflowing_add((ys[i + 1] << comp_diff) | (ys[i] >> exp_diff)); if carry { carry_2 |= o.overflowing_add_assign(1); } carry = carry_2; } // most significant limb is special let mut carry_2; (*out_last, carry_2) = xs_last.overflowing_add(ys[n - 1] >> exp_diff); if carry { carry_2 |= out_last.overflowing_add_assign(1); } (low, carry_2) } else { // exp_diff >= Limb::WIDTH let q = bit_to_limb_count_floor(exp_diff); let r = exp_diff & Limb::WIDTH_MASK; if r == 0 { assert_ne!(q, 0); let (ys_lo, ys_hi) = ys.split_at(q); let (ys_mid, ys_lo) = ys_lo.split_last().unwrap(); let mut low = *ys_mid; if !slice_test_zero(ys_lo) { low |= 1; } let nmq = n - q; let (out_lo, out_hi) = out.split_at_mut(nmq); let (xs_lo, xs_hi) = xs.split_at(nmq); let carry = if limbs_add_same_length_to_out(out_lo, xs_lo, ys_hi) { limbs_add_limb_to_out(out_hi, xs_hi, 1) } else { out_hi.copy_from_slice(xs_hi); false }; (low, carry) } else { // 0 < r < Limb::WIDTH let comp_diff = Limb::WIDTH - r; let (ys_lo, ys_hi) = ys.split_at(q); let mut low = ys_hi[0] << comp_diff; if !slice_test_zero(ys_lo) { low |= 1; } let nmq = n - q; let (out_lo, out_hi) = out.split_at_mut(nmq); let (out_lo_last, out_lo_init) = out_lo.split_last_mut().unwrap(); let (xs_lo, xs_hi) = xs.split_at(nmq); let (xs_lo_last, xs_lo_init) = xs_lo.split_last().unwrap(); let mut carry = false; for (i, (o, &x)) in out_lo_init.iter_mut().zip(xs_lo_init).enumerate() { let mut carry_2; (*o, carry_2) = x.overflowing_add((ys_hi[i + 1] << comp_diff) | (ys_hi[i] >> r)); if carry { carry_2 |= o.overflowing_add_assign(1); } carry = carry_2; } // most significant limb of y is special let mut carry_2; (*out_lo_last, carry_2) = xs_lo_last.overflowing_add(ys[n - 1] >> r); if carry { carry_2 |= out_lo_last.overflowing_add_assign(1); } // upper limbs are copied let carry = if carry_2 { limbs_add_limb_to_out(out_hi, xs_hi, 1) } else { out_hi.copy_from_slice(xs_hi); false }; (low, carry) } } } // x <- x + y >> r where d = q * Limb::WIDTH + r. Return the carry at x[n + 1] (0 or 1) and return // low so that: // * the most significant bit of low would be that of x[-1] if we would compute one more limb of the // (infinite) addition // * the Limb::WIDTH - 1 least significant bits of low are zero iff all bits of x[-1], x[-2], ... // would be zero (except the most significant bit of x[-1]). // // Assume 0 < exp_diff < Limb::WIDTH * n. // // This is mpfr_addrsh from add1sp.c, MPFR 4.2.0, returning `low` before `carry`, where ap == bp. fn add_significands_rsh_mut_ref(xs: &mut [Limb], ys: &[Limb], exp_diff: u64) -> (Limb, bool) { let n = xs.len(); assert_eq!(ys.len(), n); if exp_diff < Limb::WIDTH { // x <- x + y >> d assert_ne!(exp_diff, 0); let comp_diff = Limb::WIDTH - exp_diff; // Thus 0 < Limb::WIDTH - exp_diff < Limb::WIDTH let low = ys[0] << comp_diff; let mut carry = false; let (xs_last, xs_init) = xs.split_last_mut().unwrap(); for (i, x) in xs_init.iter_mut().enumerate() { let mut carry_2; (*x, carry_2) = x.overflowing_add((ys[i + 1] << comp_diff) | (ys[i] >> exp_diff)); if carry { carry_2 |= x.overflowing_add_assign(1); } carry = carry_2; } // most significant limb is special let mut carry_2 = xs_last.overflowing_add_assign(ys[n - 1] >> exp_diff); if carry { carry_2 |= xs_last.overflowing_add_assign(1); } (low, carry_2) } else { // exp_diff >= Limb::WIDTH let q = bit_to_limb_count_floor(exp_diff); let r = exp_diff & Limb::WIDTH_MASK; if r == 0 { assert_ne!(q, 0); let (ys_lo, ys_hi) = ys.split_at(q); let (ys_mid, ys_lo) = ys_lo.split_last().unwrap(); let mut low = *ys_mid; if !slice_test_zero(ys_lo) { low |= 1; } let (xs_lo, xs_hi) = xs.split_at_mut(n - q); let carry = limbs_slice_add_same_length_in_place_left(xs_lo, ys_hi) && limbs_slice_add_limb_in_place(xs_hi, 1); (low, carry) } else { // 0 < r < Limb::WIDTH let comp_diff = Limb::WIDTH - r; let (ys_lo, ys_hi) = ys.split_at(q); let mut low = ys_hi[0] << comp_diff; if !slice_test_zero(ys_lo) { low |= 1; } let (xs_lo, xs_hi) = xs.split_at_mut(n - q); let (xs_lo_last, xs_lo_init) = xs_lo.split_last_mut().unwrap(); let mut carry = false; for (i, x) in xs_lo_init.iter_mut().enumerate() { let mut carry_2; (*x, carry_2) = x.overflowing_add((ys_hi[i + 1] << comp_diff) | (ys_hi[i] >> r)); if carry { carry_2 |= x.overflowing_add_assign(1); } carry = carry_2; } // most significant limb of y is special let mut carry_2 = xs_lo_last.overflowing_add_assign(ys[n - 1] >> r); if carry { carry_2 |= xs_lo_last.overflowing_add_assign(1); } // upper limbs are copied let carry = if carry_2 { limbs_slice_add_limb_in_place(xs_hi, 1) } else { false }; (low, carry) } } } // y <- x + y >> r where d = q * Limb::WIDTH + r. Return the carry at y[n + 1] (0 or 1) and return // low so that: // * the most significant bit of low would be that of y[-1] if we would compute one more limb of the // (infinite) addition // * the Limb::WIDTH - 1 least significant bits of low are zero iff all bits of y[-1], y[-2], ... // would be zero (except the most significant bit of y[-1]). // // Assume 0 < exp_diff < Limb::WIDTH * n. // // This is mpfr_addrsh from add1sp.c, MPFR 4.2.0, returning `low` before `carry`, where ap == cp. fn add_significands_rsh_ref_mut(xs: &[Limb], ys: &mut [Limb], exp_diff: u64) -> (Limb, bool) { let n = xs.len(); assert_eq!(ys.len(), n); if exp_diff < Limb::WIDTH { // y <- x + y >> d assert_ne!(exp_diff, 0); let comp_diff = Limb::WIDTH - exp_diff; // Thus 0 < Limb::WIDTH - exp_diff < Limb::WIDTH let low = ys[0] << comp_diff; let mut carry = false; let (xs_last, xs_init) = xs.split_last().unwrap(); for (i, x) in xs_init.iter().enumerate() { let mut carry_2; (ys[i], carry_2) = x.overflowing_add((ys[i + 1] << comp_diff) | (ys[i] >> exp_diff)); if carry { carry_2 |= ys[i].overflowing_add_assign(1); } carry = carry_2; } // most significant limb is special let ys_last = ys.last_mut().unwrap(); let mut carry_2; (*ys_last, carry_2) = xs_last.overflowing_add(*ys_last >> exp_diff); if carry { carry_2 |= ys_last.overflowing_add_assign(1); } (low, carry_2) } else { // exp_diff >= Limb::WIDTH let q = bit_to_limb_count_floor(exp_diff); let r = exp_diff & Limb::WIDTH_MASK; let nmq = n - q; if r == 0 { assert_ne!(q, 0); let (ys_mid, ys_lo) = ys[..q].split_last_mut().unwrap(); let mut low = *ys_mid; if !slice_test_zero(ys_lo) { low |= 1; } let (xs_lo, xs_hi) = xs.split_at(nmq); let carry = if limbs_add_to_out_aliased_2(ys, q, xs_lo) { limbs_add_limb_to_out(&mut ys[nmq..], xs_hi, 1) } else { ys[nmq..].copy_from_slice(xs_hi); false }; (low, carry) } else { // 0 < r < Limb::WIDTH let comp_diff = Limb::WIDTH - r; let last_ys = ys[n - 1]; let (ys_lo, ys_hi) = ys.split_at(q); let mut low = ys_hi[0] << comp_diff; if !slice_test_zero(ys_lo) { low |= 1; } let (xs_lo, xs_hi) = xs.split_at(nmq); let (xs_lo_last, xs_lo_init) = xs_lo.split_last().unwrap(); let mut carry = false; for (i, &x) in xs_lo_init.iter().enumerate() { let qpi = q + i; let mut carry_2; (ys[i], carry_2) = x.overflowing_add((ys[qpi + 1] << comp_diff) | (ys[qpi] >> r)); if carry { carry_2 |= ys[i].overflowing_add_assign(1); } carry = carry_2; } // most significant limb of y is special let (ys_lo, ys_hi) = ys.split_at_mut(nmq); let ys_lo_last = ys_lo.last_mut().unwrap(); let mut carry_2; (*ys_lo_last, carry_2) = xs_lo_last.overflowing_add(last_ys >> r); if carry { carry_2 |= ys_lo_last.overflowing_add_assign(1); } let carry = if carry_2 { limbs_add_limb_to_out(ys_hi, xs_hi, 1) } else { ys_hi.copy_from_slice(xs_hi); false }; (low, carry) } } } fn add_float_significands_same_prec_ge_3w_ref_ref<'a>( out: &mut [Limb], mut xs: &'a [Limb], mut x_exp: i32, mut ys: &'a [Limb], mut y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { if x_exp < y_exp { swap(&mut xs, &mut ys); swap(&mut x_exp, &mut y_exp); } let n = xs.len(); assert_eq!(ys.len(), n); let out = &mut out[..n]; let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_m1_bit = shift_bit >> 1; let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; let last_index = n - 1; if exp_diff == 0 { x_exp.saturating_add_assign(1); assert!(limbs_add_same_length_to_out(out, xs, ys)); round_bit = out[0] & shift_bit; limbs_slice_shr_in_place(out, 1); out[last_index] |= LIMB_HIGH_BIT; out[0] &= !(shift_bit - 1); if round_bit == 0 { (x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if out[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else if exp_diff >= prec { if exp_diff > prec { match rm { Exact => panic!("Inexact float addition"), Nearest | Floor | Down => { out.copy_from_slice(xs); (x_exp, Less) } Ceiling | Up => { out.copy_from_slice(xs); if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { // Check if y was a power of 2 if limbs_is_power_of_2(ys) && xs[0] & shift_bit == 0 { out.copy_from_slice(xs); (x_exp, Less) } else { out.copy_from_slice(xs); if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => { out.copy_from_slice(xs); (x_exp, Less) } Ceiling | Up => { out.copy_from_slice(xs); if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else { // - 0 < exp_diff < prec // - General case: 1 <= exp_diff < prec let mask = !(shift_bit - 1); let carry; (sticky_bit, carry) = add_significands_rsh_to_out(out, xs, ys, exp_diff); // The most significant bit of sticky_bit contains what would be the most significant bit of // out[-1], and the remaining bits of stick_bit are 0 iff the remaining bits of out[-1], // out[-2], ... are all zero if shift != 0 { // The round bit and a part of the sticky bit are in out[0]. round_bit = out[0] & shift_m1_bit; sticky_bit |= out[0] & (shift_m1_bit - 1); } else { // The round bit and possibly a part of the sticky bit are in sticky_bit round_bit = sticky_bit & LIMB_HIGH_BIT; sticky_bit &= !LIMB_HIGH_BIT; } out[0] &= mask; // Check for carry out if carry { sticky_bit |= round_bit; round_bit = out[0] & shift_bit; limbs_slice_shr_in_place(out, 1); x_exp.saturating_add_assign(1); out[last_index] |= LIMB_HIGH_BIT; out[0] &= mask; } match rm { Nearest => { if round_bit == 0 { (x_exp, if sticky_bit != 0 { Less } else { Equal }) } else if sticky_bit == 0 && out[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down | Exact => { let inexact = round_bit != 0 || sticky_bit != 0; if rm == Exact && inexact { panic!("Inexact float addition"); } else { (x_exp, if inexact { Less } else { Equal }) } } Ceiling | Up => { if round_bit != 0 || sticky_bit != 0 { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } else { (x_exp, Equal) } } } } } fn add_float_significands_same_prec_ge_3w_val_val<'a>( xs: &'a mut [Limb], x_exp: i32, ys: &'a mut [Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering, bool) { if x_exp >= y_exp { let (exp, o) = add_float_significands_same_prec_ge_3w_val_ref(xs, x_exp, ys, y_exp, prec, rm); (exp, o, false) } else { let (exp, o) = add_float_significands_same_prec_ge_3w_val_ref(ys, y_exp, xs, x_exp, prec, rm); (exp, o, true) } } fn add_float_significands_same_prec_ge_3w_val_ref( xs: &mut [Limb], mut x_exp: i32, ys: &[Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { let n = xs.len(); assert_eq!(ys.len(), n); let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_m1_bit = shift_bit >> 1; let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; let last_index = n - 1; if exp_diff == 0 { x_exp.saturating_add_assign(1); assert!(limbs_slice_add_same_length_in_place_left(xs, ys)); round_bit = xs[0] & shift_bit; limbs_slice_shr_in_place(xs, 1); xs[last_index] |= LIMB_HIGH_BIT; xs[0] &= !(shift_bit - 1); if round_bit == 0 { (x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if xs[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else if exp_diff >= prec { if exp_diff > prec { match rm { Exact => panic!("Inexact float addition"), Nearest | Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { // Check if y was a power of 2 if limbs_is_power_of_2(ys) && xs[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else { // - 0 < exp_diff < prec // - General case: 1 <= exp_diff < prec let mask = !(shift_bit - 1); let carry; (sticky_bit, carry) = add_significands_rsh_mut_ref(xs, ys, exp_diff); // The most significant bit of sticky_bit contains what would be the most significant bit of // out[-1], and the remaining bits of stick_bit are 0 iff the remaining bits of out[-1], // out[-2], ... are all zero if shift != 0 { // The round bit and a part of the sticky bit are in out[0]. round_bit = xs[0] & shift_m1_bit; sticky_bit |= xs[0] & (shift_m1_bit - 1); } else { // The round bit and possibly a part of the sticky bit are in sticky_bit round_bit = sticky_bit & LIMB_HIGH_BIT; sticky_bit &= !LIMB_HIGH_BIT; } xs[0] &= mask; // Check for carry out if carry { sticky_bit |= round_bit; round_bit = xs[0] & shift_bit; limbs_slice_shr_in_place(xs, 1); x_exp.saturating_add_assign(1); xs[last_index] |= LIMB_HIGH_BIT; xs[0] &= mask; } match rm { Nearest => { if round_bit == 0 { (x_exp, if sticky_bit != 0 { Less } else { Equal }) } else if sticky_bit == 0 && xs[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down | Exact => { let inexact = round_bit != 0 || sticky_bit != 0; if rm == Exact && inexact { panic!("Inexact float addition"); } else { (x_exp, if inexact { Less } else { Equal }) } } Ceiling | Up => { if round_bit != 0 || sticky_bit != 0 { if limbs_slice_add_limb_in_place(xs, shift_bit) { x_exp.saturating_add_assign(1); xs[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } else { (x_exp, Equal) } } } } } fn add_float_significands_same_prec_ge_3w_ref_val( xs: &[Limb], mut x_exp: i32, ys: &mut [Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { let n = xs.len(); assert_eq!(ys.len(), n); let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_m1_bit = shift_bit >> 1; let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; let last_index = n - 1; if exp_diff == 0 { x_exp.saturating_add_assign(1); assert!(limbs_slice_add_same_length_in_place_left(ys, xs)); round_bit = ys[0] & shift_bit; limbs_slice_shr_in_place(ys, 1); ys[last_index] |= LIMB_HIGH_BIT; ys[0] &= !(shift_bit - 1); if round_bit == 0 { (x_exp, Equal) } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { if ys[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else if exp_diff >= prec { if exp_diff > prec { match rm { Exact => panic!("Inexact float addition"), Nearest | Floor | Down => { ys.copy_from_slice(xs); (x_exp, Less) } Ceiling | Up => { ys.copy_from_slice(xs); if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } else { match rm { Exact => panic!("Inexact float addition"), Nearest => { // Check if y was a power of 2 if limbs_is_power_of_2(ys) && xs[0] & shift_bit == 0 { ys.copy_from_slice(xs); (x_exp, Less) } else { ys.copy_from_slice(xs); if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => { ys.copy_from_slice(xs); (x_exp, Less) } Ceiling | Up => { ys.copy_from_slice(xs); if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } } } else { // - 0 < exp_diff < prec // - General case: 1 <= exp_diff < prec let mask = !(shift_bit - 1); let carry; (sticky_bit, carry) = add_significands_rsh_ref_mut(xs, ys, exp_diff); // The most significant bit of sticky_bit contains what would be the most significant bit of // y[-1], and the remaining bits of stick_bit are 0 iff the remaining bits of y[-1], y[-2], // ... are all zero if shift != 0 { // The round bit and a part of the sticky bit are in y[0]. round_bit = ys[0] & shift_m1_bit; sticky_bit |= ys[0] & (shift_m1_bit - 1); } else { // The round bit and possibly a part of the sticky bit are in sticky_bit round_bit = sticky_bit & LIMB_HIGH_BIT; sticky_bit &= !LIMB_HIGH_BIT; } ys[0] &= mask; // Check for carry out if carry { sticky_bit |= round_bit; round_bit = ys[0] & shift_bit; limbs_slice_shr_in_place(ys, 1); x_exp.saturating_add_assign(1); ys[last_index] |= LIMB_HIGH_BIT; ys[0] &= mask; } match rm { Nearest => { if round_bit == 0 { (x_exp, if sticky_bit != 0 { Less } else { Equal }) } else if sticky_bit == 0 && ys[0] & shift_bit == 0 { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down | Exact => { let inexact = round_bit != 0 || sticky_bit != 0; if rm == Exact && inexact { panic!("Inexact float addition"); } else { (x_exp, if inexact { Less } else { Equal }) } } Ceiling | Up => { if round_bit != 0 || sticky_bit != 0 { if limbs_slice_add_limb_in_place(ys, shift_bit) { x_exp.saturating_add_assign(1); ys[last_index] = LIMB_HIGH_BIT; } (x_exp, Greater) } else { (x_exp, Equal) } } } } } #[derive(Debug, Clone, Copy, Eq, PartialEq)] enum RoundBit { Uninitialized, False, True, } impl RoundBit { #[inline] const fn flip_assign(&mut self) { match self { False => *self = True, True => *self = False, _ => {} } } } impl From for RoundBit { #[inline] fn from(b: bool) -> Self { if b { True } else { False } } } fn add_float_significands_general_round( out: &mut [Limb], mut x_exp: i32, shift_bit: Limb, round_bit: RoundBit, following_bits: RoundBit, rm: RoundingMode, ) -> (i32, Ordering) { if following_bits == False && round_bit == False { return (x_exp, Equal); } match rm { Exact => panic!("Inexact float addition"), Nearest => { if following_bits == False { if out[0] & shift_bit != 0 { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (x_exp, Greater) } else { (x_exp, Less) } } else if round_bit == False { (x_exp, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (x_exp, Greater) } } Floor | Down => (x_exp, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (x_exp, Greater) } } } fn add_float_significands_general( out: &mut [Limb], xs: &[Limb], mut x_exp: i32, ys: &[Limb], y_exp: i32, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { assert!(x_exp >= y_exp); let out_len = out.len(); let out_bits = limb_to_bit_count(out_len); let shift = out_bits - out_prec; // non-significant bits in low limb let shift_bit = Limb::power_of_2(shift); let xs_len = xs.len(); let ys_len = ys.len(); let exp_diff = u64::exact_from(x_exp - y_exp); let k = bit_to_limb_count_floor(exp_diff); // Compute the significant part out', the non-significant bits of out are taken into account. // // Perform the rounding. At each iteration, we remember: // - r = rounding bit // - f = following bits (same value) // where the result has the form: [number A]rfff...fff + a remaining value in the interval [0,2) // ulp. We consider the most significant bits of the remaining value to update the result; a // possible carry is immediately taken into account and out is updated accordingly. As soon as // the bits f don't have the same value, out can be rounded. Variables: // // - round_bit = rounding bit (0 or 1). // - following_bits = following bits (0 or 1), then sticky bit. // - If following_bits == 0, the only thing that can change is the sticky bit. // - means: not initialized let mut round_bit = Uninitialized; let mut following_bits = Uninitialized; if out_bits <= exp_diff { // y does not overlap with out' if out_len > xs_len { out[out_len - xs_len..].copy_from_slice(xs); } else { out.copy_from_slice(&xs[xs_len - out_len..]); } } else { // - out_bits > exp_diff // - y overlaps with out' // - copy y (shifted) into out // overlap is the number of limbs of y which overlap with out' let mut overlap = bit_to_limb_count_ceiling(out_bits - exp_diff); // only the highest overlap limbs from y have to be considered if overlap > ys_len { // y doesn't have enough limbs assert!(overlap - ys_len <= out_len); overlap = ys_len; } let ys_hi = &ys[ys_len - overlap..]; let omk = out_len - k; let (out_lo, out_hi) = out.split_at_mut(omk - overlap); let out_hi = &mut out_hi[..overlap]; let shift2 = u64::exact_from(exp_diff & Limb::WIDTH_MASK); if shift2 != 0 { assert!(omk >= overlap); let y = limbs_shr_to_out(out_hi, ys_hi, shift2); if omk > overlap { *out_lo.last_mut().unwrap() = y; } } else { out_hi.copy_from_slice(ys_hi); } // add x to out let y = if out_len > xs_len { limbs_slice_add_same_length_in_place_left(&mut out[out_len - xs_len..], xs) } else { limbs_slice_add_same_length_in_place_left(out, &xs[xs_len - out_len..]) }; if y { x_exp.saturating_add_assign(1); round_bit = RoundBit::from((out[0] >> shift).odd()); // LSB(out) --> rounding bit after the shift if shift != 0 { let mask = shift_bit - 1; let x = out[0] & mask; out[0] &= !mask << 1; if x == 0 { following_bits = False; } else if x == mask { following_bits = True; } } limbs_slice_shr_in_place(out, 1); out[out_len - 1] |= LIMB_HIGH_BIT; if shift != 0 && following_bits == Uninitialized { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } } } if round_bit == Uninitialized && shift != 0 { let mut mask = shift_bit - 1; let mut x = out[0] & mask; out[0] &= !mask; round_bit = RoundBit::from(x >> (shift - 1) != 0); if shift > 1 { mask >>= 1; x &= mask; if x == 0 { following_bits = False; } else if x == mask { following_bits = True; } else { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } } } // Determine rounding and sticky bits (and possible carry). In faithful rounding, we may stop // two bits after ulp(out): the approximation is regarded as the number formed by out, the // rounding bit round_bit and an additional bit following_bits; and the corresponding error is < // 1/2 ulp of the unrounded result. if xs_len > out_len { // there are still limbs from x that haven't been taken into account if following_bits == False && out_len <= k { // y hasn't been taken into account ==> sticky bit != 0 return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } // index of lowest considered limb from x, > 0 let mut xi = xs_len - out_len; for _ in 0..k.saturating_sub(out_len) { // ulp(next limb from x) > msb(y) xi -= 1; let mut x = xs[xi]; assert_ne!(following_bits, False); if following_bits == True { // Note: Here, we can round to nearest, but the loop may still be necessary to // determine whether there is a carry from y, which will have an effect on the // ternary value. if x != Limb::MAX { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } } else { if round_bit == Uninitialized { round_bit = RoundBit::from(x >> (Limb::WIDTH - 1) != 0); x |= LIMB_HIGH_BIT; } following_bits = True; if x != Limb::MAX { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } } if xi == 0 { // x has entirely been read y hasn't been taken into account, so sticky_bit != 0 return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } } let difw = out_len.saturating_sub(k); assert!(xi != 0); let mut goto_c_read = false; if difw <= ys_len { let mut yi = ys_len - difw + 1; let exp_diff_rem = exp_diff & Limb::WIDTH_MASK; if exp_diff_rem != 0 || yi != 1 { let mut y_prev = if yi - 1 == ys_len { 0 } else { ys[yi - 1] }; if following_bits == Uninitialized { let mut y; if exp_diff_rem != 0 { y = y_prev << (Limb::WIDTH - exp_diff_rem); yi -= 1; if yi != 0 { y_prev = ys[yi - 1]; y += y_prev >> exp_diff_rem; } } else { yi -= 1; y = ys[yi - 1]; } xi -= 1; let mut x = xs[xi].wrapping_add(y); if x < y && (round_bit == Uninitialized || { round_bit.flip_assign(); round_bit == False }) && limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[out_len - 1] = LIMB_HIGH_BIT; round_bit = False; } if round_bit == Uninitialized { round_bit = RoundBit::from(x >> (Limb::WIDTH - 1) != 0); x <<= 1; x |= x >> (Limb::WIDTH - 1); } following_bits = RoundBit::from(x != 0); if x != 0 && x != Limb::MAX { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } } let mut y; while xi != 0 { if exp_diff_rem != 0 { if yi == 0 { goto_c_read = true; break; } y = y_prev << (Limb::WIDTH - exp_diff_rem); yi -= 1; if yi != 0 { y_prev = ys[yi - 1]; y += y_prev >> exp_diff_rem; } } else { if yi == 1 { goto_c_read = true; break; } yi -= 1; y = ys[yi - 1]; } let x = xs[xi - 1].wrapping_add(y); if x < y { following_bits.flip_assign(); if following_bits != False { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } round_bit.flip_assign(); if round_bit == False && limbs_slice_add_limb_in_place(out, shift_bit) { x_exp.saturating_add_assign(1); out[out_len - 1] = LIMB_HIGH_BIT; } } if following_bits == False && x != 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } if following_bits != False && x != Limb::MAX { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } xi -= 1; } if !goto_c_read { if following_bits != False || yi == 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, following_bits, rm, ); } if exp_diff_rem != 0 && y_prev << (Limb::WIDTH - exp_diff_rem) != 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } yi -= 1; while yi != 0 { yi -= 1; if ys[yi] != 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } } } } else { goto_c_read = true; } } if difw > ys_len || goto_c_read { // - y has entirely been read // - label c_read: if following_bits == Uninitialized { assert_ne!(xi, 0); xi -= 1; let mut x = xs[xi]; if round_bit == Uninitialized { round_bit = RoundBit::from(x >> (Limb::WIDTH - 1) != 0); x &= !LIMB_HIGH_BIT; } following_bits = RoundBit::from(x != 0); } if following_bits == True { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } while xi != 0 { xi -= 1; if xs[xi] != 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, True, rm, ); } } } } else if following_bits != True { if out_len.saturating_sub(k) > ys_len { if round_bit == Uninitialized { round_bit = False; } following_bits = False; } else if exp_diff > out_bits { // x is followed by at least a zero bit, then by y if round_bit == Uninitialized { round_bit = False; } following_bits = True; } else { // difw is the number of limbs from x (regarded as having an infinite precision) that // have already been combined with y; -n if the next n limbs from x won't be combined // with y. let difw = out_len - k; assert!(ys_len >= difw); let mut yi = ys_len - difw; let exp_diff_rem = exp_diff & Limb::WIDTH_MASK; if exp_diff_rem == 0 && yi == 0 { // y has entirely been read if round_bit == Uninitialized { round_bit = False; } following_bits = False; } else { let mut y = if exp_diff_rem != 0 { assert!(yi < ys_len); ys[yi] << (Limb::WIDTH - exp_diff_rem) } else { yi -= 1; ys[yi] }; if round_bit == Uninitialized { round_bit = RoundBit::from(y >> (Limb::WIDTH - 1) != 0); y &= !LIMB_HIGH_BIT; } while y == 0 { if yi == 0 { return add_float_significands_general_round( out, x_exp, shift_bit, round_bit, False, rm, ); } yi -= 1; y = ys[yi]; } following_bits = True; } } } add_float_significands_general_round(out, x_exp, shift_bit, round_bit, following_bits, rm) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_div.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div::limbs_div_schoolbook_approx; use crate::natural::arithmetic::div_mod::{ div_mod_by_preinversion, limbs_div_limb_in_place_mod, limbs_div_limb_to_out_mod, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_qs_to_out_rs_to_ns, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::float_extras::round_helper_2; use crate::natural::arithmetic::float_mul::{ limbs_float_mul_high_same_length, limbs_float_mul_high_same_length_scratch_len, }; use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling}; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, NegModPowerOf2, OverflowingAddAssign, OverflowingNegAssign, Parity, PowerOf2, WrappingAddAssign, WrappingNegAssign, WrappingSubAssign, XMulYToZZ, XXSubYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_test_zero; // This is mpfr_div from div.c, MPFR 4.3.0. pub fn div_float_significands_in_place( x: &mut Natural, x_prec: u64, y: &mut Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((increment_exp, o)) = div_float_significands_in_place_same_prec(x, y, out_prec, rm) { return (u64::from(increment_exp), o); } match (&mut *x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { let mut xs = vec![*small_x]; let result = div_float_significands_long_by_short_in_place(&mut xs, *small_y, out_prec, rm); *x = Natural::from_owned_limbs_asc(xs); result } (Natural(Large(xs)), Natural(Small(small_y))) => { let result = div_float_significands_long_by_short_in_place(xs, *small_y, out_prec, rm); x.demote_if_small(); result } (Natural(Small(small_x)), Natural(Large(ys))) => { let (out, exp_offset, o) = div_float_significands_general(&[*small_x], ys, out_prec, rm); *x = Natural::from_owned_limbs_asc(out); (exp_offset, o) } (Natural(Large(xs)), Natural(Large(ys))) => { let (out, exp_offset, o) = div_float_significands_general(xs, ys, out_prec, rm); *x = Natural::from_owned_limbs_asc(out); (exp_offset, o) } } } // This is mpfr_div from div.c, MPFR 4.3.0. pub fn div_float_significands_in_place_ref( x: &mut Natural, x_prec: u64, y: &Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((increment_exp, o)) = div_float_significands_in_place_same_prec_ref(x, y, out_prec, rm) { return (u64::from(increment_exp), o); } match (&mut *x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { let mut xs = vec![*small_x]; let result = div_float_significands_long_by_short_in_place(&mut xs, *small_y, out_prec, rm); *x = Natural::from_owned_limbs_asc(xs); result } (Natural(Large(xs)), Natural(Small(small_y))) => { let result = div_float_significands_long_by_short_in_place(xs, *small_y, out_prec, rm); x.demote_if_small(); result } (Natural(Small(small_x)), y) => { let mut ys = y.to_limbs_asc(); let (out, exp_offset, o) = div_float_significands_general(&[*small_x], &mut ys, out_prec, rm); *x = Natural::from_owned_limbs_asc(out); (exp_offset, o) } (Natural(Large(xs)), y) => { let mut ys = y.to_limbs_asc(); let (out, exp_offset, o) = div_float_significands_general(xs, &mut ys, out_prec, rm); *x = Natural::from_owned_limbs_asc(out); (exp_offset, o) } } } // This is mpfr_div from div.c, MPFR 4.3.0. pub fn div_float_significands_ref_val( x: &Natural, x_prec: u64, y: &mut Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, u64, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((quotient, increment_exp, o)) = div_float_significands_same_prec_ref_val(x, y, out_prec, rm) { return (quotient, u64::from(increment_exp), o); } match (x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { let (qs, exp_offset, o) = div_float_significands_long_by_short(&[*small_x], *small_y, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Large(xs)), Natural(Small(small_y))) => { let (qs, exp_offset, o) = div_float_significands_long_by_short(xs, *small_y, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Small(small_x)), Natural(Large(ys))) => { let (qs, exp_offset, o) = div_float_significands_general(&[*small_x], ys, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Large(xs)), Natural(Large(ys))) => { let (qs, exp_offset, o) = div_float_significands_general(xs, ys, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } } } // This is mpfr_div from div.c, MPFR 4.3.0. pub fn div_float_significands_ref_ref( x: &Natural, x_prec: u64, y: &Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, u64, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((quotient, increment_exp, o)) = div_float_significands_same_prec_ref_ref(x, y, out_prec, rm) { return (quotient, u64::from(increment_exp), o); } match (x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { let (qs, exp_offset, o) = div_float_significands_long_by_short(&[*small_x], *small_y, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Large(xs)), Natural(Small(small_y))) => { let (qs, exp_offset, o) = div_float_significands_long_by_short(xs, *small_y, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Small(small_x)), y) => { let mut ys = y.to_limbs_asc(); let (qs, exp_offset, o) = div_float_significands_general(&[*small_x], &mut ys, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } (Natural(Large(xs)), y) => { let mut ys = y.to_limbs_asc(); let (qs, exp_offset, o) = div_float_significands_general(xs, &mut ys, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } } } fn div_float_significands_in_place_same_prec( x: &mut Natural, y: &mut Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (quotient, increment_exp, o) = if prec == Limb::WIDTH { div_float_significands_same_prec_w(*x, *y, rm) } else { div_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; *x = quotient; Some((increment_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_mut_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (quotient_0, quotient_1, increment_exp, o) = div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); *x_0 = quotient_0; *x_1 = quotient_1; Some((increment_exp, o)) } _ => None, }, _ => None, } } fn div_float_significands_in_place_same_prec_ref( x: &mut Natural, y: &Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (quotient, increment_exp, o) = if prec == Limb::WIDTH { div_float_significands_same_prec_w(*x, *y, rm) } else { div_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; *x = quotient; Some((increment_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (quotient_0, quotient_1, increment_exp, o) = div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); *x_0 = quotient_0; *x_1 = quotient_1; Some((increment_exp, o)) } _ => None, }, _ => None, } } fn div_float_significands_same_prec_ref_val( x: &Natural, y: &mut Natural, prec: u64, rm: RoundingMode, ) -> Option<(Natural, bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (quotient, increment_exp, o) = if prec == Limb::WIDTH { div_float_significands_same_prec_w(*x, *y, rm) } else { div_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; Some((Natural(Small(quotient)), increment_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (quotient_0, quotient_1, increment_exp, o) = div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); Some(( Natural(Large(vec![quotient_0, quotient_1])), increment_exp, o, )) } _ => None, }, _ => None, } } fn div_float_significands_same_prec_ref_ref( x: &Natural, y: &Natural, prec: u64, rm: RoundingMode, ) -> Option<(Natural, bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (quotient, increment_exp, o) = if prec == Limb::WIDTH { div_float_significands_same_prec_w(*x, *y, rm) } else { div_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; Some((Natural(Small(quotient)), increment_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (quotient_0, quotient_1, increment_exp, o) = div_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); Some(( Natural(Large(vec![quotient_0, quotient_1])), increment_exp, o, )) } _ => None, }, _ => None, } } const WIDTH_M1: u64 = Limb::WIDTH - 1; const TWICE_WIDTH: u64 = Limb::WIDTH << 1; // This is mpfr_div_1 from mul.c, MPFR 4.3.0. fn div_float_significands_same_prec_lt_w( mut x: Limb, y: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let half_shift_bit = shift_bit >> 1; let mask = shift_bit - 1; let increment_exp = x >= y; if increment_exp { x -= y; } // First try with an approximate quotient. let mut round_bit = Limb::wrapping_from( (DoubleLimb::from(x) * DoubleLimb::from(limbs_invert_limb::(y))) >> Limb::WIDTH, ); round_bit.wrapping_add_assign(x); let mut q = if increment_exp { round_bit >> 1 } else { round_bit }; // round_bit does not exceed the true quotient floor(x * 2 ^ WIDTH / y), with error at most 2, // which means the rational quotient q satisfies round_bit <= q < round_bit + 3. We can round // correctly except when the last shift - 1 bits of q0 are 000..000 or 111..111 or 111..110. let sticky_bit = if (q + 2) & (mask >> 1) > 2 { round_bit = q & half_shift_bit; // result cannot be exact in this case 1 } else { // The true quotient is round_bit, round_bit + 1, or round_bit + 2 q = round_bit; let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, y); assert!(hi < x || (hi == x && lo == 0)); // subtract {hi, lo} from {x, 0} (hi, lo) = Limb::xx_sub_yy_to_zz(x, 0, hi, lo); // the remainder {hi, lo} should be < y. if hi != 0 || lo >= y { q += 1; if lo < y { hi.wrapping_sub_assign(1); } lo.wrapping_sub_assign(y); } if hi != 0 || lo >= y { q += 1; if lo < y { hi.wrapping_sub_assign(1); } lo.wrapping_sub_assign(y); } assert!(hi == 0 && lo < y); let sticky_bit; if increment_exp { sticky_bit = lo | (q & 1); q >>= 1; } else { sticky_bit = lo; } round_bit = q & half_shift_bit; sticky_bit | (q & (mask >> 1)) }; let quotient = (LIMB_HIGH_BIT | q) & !mask; if round_bit == 0 && sticky_bit == 0 { return (quotient, increment_exp, Equal); } match rm { Exact => panic!("Inexact float division"), Nearest => { if round_bit == 0 || sticky_bit == 0 && quotient & shift_bit == 0 { (quotient, increment_exp, Less) } else { (quotient.wrapping_add(shift_bit), increment_exp, Greater) } } Floor | Down => (quotient, increment_exp, Less), Ceiling | Up => (quotient.wrapping_add(shift_bit), increment_exp, Greater), } } // This is mpfr_div_1n from mul.c, MPFR 4.3.0. fn div_float_significands_same_prec_w( mut x: Limb, y: Limb, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let increment_exp = x >= y; if increment_exp { x -= y; } // First compute an approximate quotient. let mut q = x.wrapping_add(Limb::wrapping_from( (DoubleLimb::from(x) * DoubleLimb::from(limbs_invert_limb::(y))) >> Limb::WIDTH, )); // round_bit does not exceed the true quotient floor(x * 2 ^ WIDTH / y), with error at most 2, // which means the rational quotient q satisfies round_bit <= q < round_bit + 3, thus the true // quotient is round_bit, round_bit + 1 or round_bit + 2. let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, y); assert!(hi < x || (hi == x && lo == 0)); // subtract {hi, lo} from {x, 0} (hi, lo) = Limb::xx_sub_yy_to_zz(x, 0, hi, lo); // the remainder {hi, lo} should be < y. if hi != 0 || lo >= y { q += 1; if lo < y { hi.wrapping_sub_assign(1); } lo.wrapping_sub_assign(y); } if hi != 0 || lo >= y { q += 1; if lo < y { hi.wrapping_sub_assign(1); } lo.wrapping_sub_assign(y); } assert!(hi == 0 && lo < y); // now (x - extra * y) * 2 ^ WIDTH = q * y + lo with 0 <= lo < y // // If !increment_exp, the quotient is q0, the round bit is 1 if l >= y0 / 2, and sticky_bit are // the remaining bits from l. If increment_exp, the quotient is HIGH_BIT + (q >> 1), the round // bit is the least significant bit of q, and sticky_bit is lo. let round_bit; let (quotient, sticky_bit) = if increment_exp { round_bit = q.odd(); (LIMB_HIGH_BIT | (q >> 1), lo) } else { // If "lo + lo < lo", then there is a carry in lo + lo, thus 2 * lo > y. Otherwise if there // is no carry, we check whether 2 * lo >= v0. let two_lo = lo << 1; round_bit = (two_lo < lo) || (two_lo >= y); ( q, if round_bit { two_lo.wrapping_sub(y) } else { lo }, ) }; if !round_bit && sticky_bit == 0 { return (quotient, increment_exp, Equal); } match rm { Exact => panic!("Inexact float division"), Nearest => { if !round_bit || sticky_bit == 0 && quotient.even() { (quotient, increment_exp, Less) } else { (quotient.wrapping_add(1), increment_exp, Greater) } } Floor | Down => (quotient, increment_exp, Less), Ceiling | Up => (quotient.wrapping_add(1), increment_exp, Greater), } } // Given x = x_1 * B + x_0 < y = y_1 * B + y_0 with y normalized (high bit of y_1 set), put in q = // Q1 // * B + Q0 an approximation of floor(x * B ^ 2 / y), with: B = 2 ^ WIDTH and q <= floor(x * B ^ 2 / // y) <= q + 21. // // This is mpfr_div2_approx from div.c, MPFR 4.3.0, where Q0 and Q1 are returned. fn div_float_2_approx(x_1: Limb, x_0: Limb, y_1: Limb, y_0: Limb) -> (Limb, Limb) { // First compute an approximation of q_1, using a lower approximation of B ^ 2 / (y_1 + 1) - B let inv = if y_1 == Limb::MAX { 0 } else { limbs_invert_limb::(y_1 + 1) }; // Now inv <= B ^ 2 / (y_1 + 1) - B. let mut q_1 = Limb::wrapping_from((DoubleLimb::from(x_1) * DoubleLimb::from(inv)) >> Limb::WIDTH); q_1.wrapping_add_assign(x_1); // Now q_1 <= x_1 * B / (y_1 + 1) < (x_1 * B + x_0) * B / (y_1 * B + y_0). // // Compute q_1 * (y_1 * B + y_0) into r_1 : r_0 : yy and subtract from u_1 : x_0 : 0. let (mut r_1, mut r_0) = Limb::x_mul_y_to_zz(q_1, y_1); let (xx, yy) = Limb::x_mul_y_to_zz(q_1, y_0); if r_0.overflowing_add_assign(xx) { r_1.wrapping_add_assign(1); } // We ignore yy below, but first increment r_0, to ensure we get a lower approximation of the // remainder. if yy != 0 { r_0.wrapping_add_assign(1); } if r_0 == 0 && yy != 0 { r_1.wrapping_add_assign(1); } r_1 = x_1.wrapping_sub(r_1); let carry; (r_0, carry) = x_0.overflowing_sub(r_0); if carry { r_1.wrapping_sub_assign(1); } // r_1 : r_0 should be non-negative. assert!(!r_1.get_highest_bit()); // The second quotient limb is approximated by (r_1 * B ^ 2 + r_0 * B) / y_1, and since (B + // inv) / B approximates B / y_1, this is in turn approximated by (r * B + r_0) * (B + inv) / B // = r_1 * B * r_1 * inv + r_0 + (r0 * inv / B). q_1.wrapping_add_assign(r_1); // Add floor(r_0 * inv / B) to q_0. if r_0.overflowing_add_assign(Limb::wrapping_from( (DoubleLimb::from(r_0) * DoubleLimb::from(inv)) >> Limb::WIDTH, )) { q_1.wrapping_add_assign(1); } assert!(r_1 <= 4); for _ in 0..r_1 { if r_0.overflowing_add_assign(inv) { q_1.wrapping_add_assign(1); } } (q_1, r_0) } // This is mpfr_div_2 from div.c, MPFR 4.3.0, where Q1 and Q0 are returned. fn div_float_significands_same_prec_gt_w_lt_2w( mut x_0: Limb, mut x_1: Limb, y_0: Limb, y_1: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, bool, Ordering) { let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; let increment_exp = x_1 > y_1 || (x_1 == y_1 && x_0 >= y_0); if increment_exp { (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); } assert!(x_1 < y_1 || (x_1 == y_1 && x_0 < y_0)); let (mut q_1, mut q_0) = div_float_2_approx(x_1, x_0, y_1, y_0); // We know q1 * B + q0 is smaller or equal to the exact quotient, with difference at most 21. let mut sticky_bit = if (q_0.wrapping_add(21)) & (mask >> 1) > 21 { // The result is not exact when we can round with an approximation. 1 } else { // We know q_1 : q_0 is a good-enough approximation, so use it! // // Since we know the difference should be at most 21 * (y_1 : y_0) after the subtraction // below, thus at most 21 * 2 ^ 128, it suffices to compute the lower 3 limbs of (q_1 : q_0) // * (y_1 : y_0). let (mut s_1, mut s_0) = Limb::x_mul_y_to_zz(q_0, y_0); let (mut s_2, mut lo) = Limb::x_mul_y_to_zz(q_0, y_1); if s_1.overflowing_add_assign(lo) { s_2.wrapping_add_assign(1); } let hi; (hi, lo) = Limb::x_mul_y_to_zz(q_1, y_0); s_2.wrapping_add_assign(hi); if s_1.overflowing_add_assign(lo) { s_2.wrapping_add_assign(1); } s_2.wrapping_add_assign(q_1.wrapping_mul(y_1)); // Subtract s_2 : s_1 : s_0 from x_0 : 0 : 0, with result in s_2 : s_1 : s_0. s_2 = x_0.wrapping_sub(s_2); // Now negate s_1 : s_0. s_1.wrapping_neg_assign(); if s_0.overflowing_neg_assign() { s_1.wrapping_sub_assign(1); } // There is a borrow in s_2 when s_0 and s_1 are not both zero. if s_1 != 0 || s_0 != 0 { s_2.wrapping_sub_assign(1); } while s_2 > 0 || s_1 > y_1 || (s_1 == y_1 && s_0 >= y_0) { // Add 1 to q_1 : q_0. if q_0.overflowing_add_assign(1) { q_1.wrapping_add_assign(1); } // Subtract y_1 : y_0 to s_2 : s_1 : s_0 if (s_1 < y_1) || (s_1 == y_1 && s_0 < y_0) { s_2.wrapping_sub_assign(1); } (s_1, s_0) = Limb::xx_sub_yy_to_zz(s_1, s_0, y_1, y_0); } s_1 | s_0 }; if increment_exp { sticky_bit |= q_0 & 1; q_0 = (q_1 << WIDTH_M1) | (q_0 >> 1); q_1 = LIMB_HIGH_BIT | (q_1 >> 1); } let round_bit = q_0 & (shift_bit >> 1); sticky_bit |= (q_0 & mask) ^ round_bit; let mut z_1 = q_1; let mut z_0 = q_0 & !mask; if round_bit == 0 && sticky_bit == 0 { return (z_0, z_1, increment_exp, Equal); } match rm { Exact => panic!("Inexact float division"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0) { (z_0, z_1, increment_exp, Less) } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, increment_exp, Greater) } } Floor | Down => (z_0, z_1, increment_exp, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, increment_exp, Greater) } } } } // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, assuming the // highest bit of `d` is set. fn limbs_div_limb_to_out_mod_with_fraction( out: &mut [Limb], fraction_len: usize, ns: &[Limb], d: Limb, ) -> Limb { assert_ne!(d, 0); let len = ns.len().checked_add(fraction_len).unwrap(); assert_ne!(len, 0); let out = &mut out[..len]; assert!(d.get_highest_bit()); // High quotient limb is 0 or 1, skip a divide step. let (r, ns_init) = ns.split_last().unwrap(); let mut r = *r; let (out_last, out_init) = out.split_last_mut().unwrap(); let adjust = r >= d; if adjust { r -= d; } *out_last = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); let (out_lo, out_hi) = out_init.split_at_mut(fraction_len); for (out_q, &n) in out_hi.iter_mut().zip(ns_init.iter()).rev() { (*out_q, r) = div_mod_by_preinversion(r, n, d, d_inv); } for out_q in out_lo.iter_mut().rev() { (*out_q, r) = div_mod_by_preinversion(r, 0, d, d_inv); } r } // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, assuming the // highest bit of `d` is set. fn limbs_div_limb_in_place_mod_with_fraction( ns: &mut [Limb], ns_len: usize, fraction_len: usize, d: Limb, ) -> Limb { assert_ne!(d, 0); let len = ns_len.checked_add(fraction_len).unwrap(); assert_ne!(len, 0); let ns = &mut ns[..len]; assert!(d.get_highest_bit()); // High quotient limb is 0 or 1, skip a divide step. let mut r = ns[ns_len - 1]; let adjust = r >= d; if adjust { r -= d; } ns.copy_within(..ns_len, fraction_len); let (ns_high, ns_init) = ns.split_last_mut().unwrap(); *ns_high = Limb::from(adjust); // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); let (ns_lo, ns_hi) = ns_init.split_at_mut(fraction_len); for n in ns_hi.iter_mut().rev() { (*n, r) = div_mod_by_preinversion(r, *n, d, d_inv); } for n in ns_lo.iter_mut().rev() { (*n, r) = div_mod_by_preinversion(r, 0, d, d_inv); } r } // This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. fn div_float_significands_long_by_short( xs: &[Limb], y: Limb, prec: u64, rm: RoundingMode, ) -> (Vec, u64, Ordering) { let out_len = bit_to_limb_count_ceiling(prec); let mut out = vec![0; out_len + 1]; let (exp_offset, o) = div_float_significands_long_by_short_to_out(&mut out, xs, y, prec, rm); out.truncate(out_len); (out, exp_offset, o) } // y cannot be a power of 2. // // This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. fn div_float_significands_long_by_short_to_out( out: &mut [Limb], xs: &[Limb], y: Limb, prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { let xs_len = xs.len(); let out_ge_xs = out.len() >= xs_len; let diff = out.len().abs_diff(xs_len); // We need to store out_len + 1 = xs_len + diff limbs of the quotient. let (c, mut sticky_bit) = if out_ge_xs { // used the entire dividend // // X = ({scratch, xs_len + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * // B ^ (-dif) (limbs_div_limb_to_out_mod_with_fraction(out, diff, xs, y), 0) } else { // dif < 0, i.e. xs_len > out_len + 1; ignore the (-diff) low limbs from x // // {xs - dif, out_len + 1} = {scratch, out_len + 1} * y + c, thus X = {xs, -dif} + {xs - // diff, out_len + 1} * B ^ (-diff) = {xp, -diff} + ({scratch, out_len + 1} * y + c) * B ^ // (-dif) let (xs_lo, xs_hi) = xs.split_at(diff); ( limbs_div_limb_to_out_mod(out, xs_hi, y), Limb::from(!slice_test_zero(xs_lo)), ) }; // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. // // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-xs_len) * // 2 ^ exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= // (c + r) / y < 1. // // sticky_bit != 0 iff r != 0 // // If the highest limb of the result is 0 (xs[xs_len - 1] < y), remove it. Otherwise, compute // the left shift to be performed to normalize. In the latter case, we discard some low bits // computed. They contain information useful for the rounding, hence the updating of middle and // inexact. let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; let out_head = out[0]; let out_last = *out.last().unwrap(); let round_bit; let mut exp_offset = if out_last == 0 { // round bit is 1 iff (c + r) / u >= 1/2 if shift == 0 { // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we // should look at the most significant bit of r. if c >= y - c { // i.e. 2 * c >= y: round bit is always 1 round_bit = 1; // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. sticky_bit |= (c << 1).wrapping_sub(y); } else { // 2 * c < y // // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. let xdm1 = if diff == 0 { 0 } else { xs.get(diff - 1).copied().unwrap_or_default() }; round_bit = Limb::from(c == y >> 1 && !out_ge_xs && xdm1.get_highest_bit()); // If round_bit is set, we need to recompute sticky_bit, since it might have taken // into account the most-significant bit of xs[-diff - 1]. if round_bit != 0 { fail_on_untested_path("div_float_significands_long_by_short, round_bit != 0"); sticky_bit = xdm1 << 1; // discard the most significant bit if sticky_bit == 0 && !slice_test_zero(&xs[..diff]) { sticky_bit = 1; } } else { sticky_bit |= c; } } } else { // round bit is in scratch[0] round_bit = out_head & (shift_bit >> 1); sticky_bit |= (out_head & (shift_mask >> 1)) | c; } 0 } else { // scratch[out_len] != 0 assert_ne!(out_last, 0); let shift_2 = LeadingZeros::leading_zeros(out_last); let comp_shift_2 = Limb::WIDTH - shift_2; assert!(y >= 2); // see special cases at the beginning assert_ne!(shift_2, 0); // since y >= 2, shift left to normalize let old_head_1 = out_head >> comp_shift_2; let old_head_2 = out_head << shift_2; out.copy_within(1.., 0); limbs_slice_shl_in_place(out, shift_2); let out_head = out.first_mut().unwrap(); *out_head |= old_head_1; // now Y is the approximate quotient, w is the next limb. let w = old_head_2; if shift == 0 { // round bit is upper bit from w round_bit = w & LIMB_HIGH_BIT; sticky_bit |= (w - round_bit) | c; } else { round_bit = *out_head & (shift_bit >> 1); sticky_bit |= (*out_head & (shift_mask >> 1)) | w | c; } comp_shift_2 }; // Clear the lowest `shift` bits out[0] &= !shift_mask; if round_bit == 0 && sticky_bit == 0 { return (exp_offset, Equal); } let (_, out) = out.split_last_mut().unwrap(); match rm { Exact => panic!("Inexact float division"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (out[0] & shift_bit) == 0) { (exp_offset, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { exp_offset += 1; *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } Floor | Down => (exp_offset, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { exp_offset += 1; *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } } // y cannot be a power of 2. The returned offset is in [0, Limb::WIDTH + 1]. // // This is mpfr_div_ui from div_ui.c, MPFR 4.3.0. fn div_float_significands_long_by_short_in_place( xs: &mut Vec, y: Limb, prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { let xs_len = xs.len(); let out_len = bit_to_limb_count_ceiling(prec); let out_ge_xs = out_len + 1 >= xs_len; let diff = (out_len + 1).abs_diff(xs_len); let x_lo_nonzero = diff < xs_len && !slice_test_zero(&xs[..diff]); let xdm1 = if diff == 0 { 0 } else { xs.get(diff - 1).copied().unwrap_or_default() }; // We need to store out_len + 1 = xs_len + diff limbs of the quotient. let (c, mut sticky_bit) = if out_ge_xs { // used the entire dividend // // X = ({scratch, xs_len + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * // B ^ (-dif) xs.resize(out_len + 1, 0); ( limbs_div_limb_in_place_mod_with_fraction(xs, xs_len, diff, y), 0, ) } else { // dif < 0, i.e. xs_len > out_len + 1; ignore the (-diff) low limbs from x // // {xs - dif, out_len + 1} = {scratch, out_len + 1} * y + c, thus X = {xs, -dif} + {xs - // diff, out_len + 1} * B ^ (-diff) = {xp, -diff} + ({scratch, out_len + 1} * y + c) * B ^ // (-dif) let p = ( limbs_div_limb_in_place_mod(&mut xs[diff..], y), Limb::from(x_lo_nonzero), ); xs.drain(..diff); p }; // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. // // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-xs_len) * // 2 ^ exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= // (c + r) / y < 1. // // sticky_bit != 0 iff r != 0 // // If the highest limb of the result is 0 (xs[xs_len - 1] < y), remove it. Otherwise, compute // the left shift to be performed to normalize. In the latter case, we discard some low bits // computed. They contain information useful for the rounding, hence the updating of middle and // inexact. let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; let xs_head = xs[0]; let xs_last = *xs.last().unwrap(); let round_bit; let mut exp_offset = if xs_last == 0 { // round bit is 1 iff (c + r) / u >= 1/2 if shift == 0 { // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we // should look at the most significant bit of r. if c >= y - c { // i.e. 2 * c >= y: round bit is always 1 round_bit = 1; // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. sticky_bit |= (c << 1).wrapping_sub(y); } else { // 2 * c < y // // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. round_bit = Limb::from(c == y >> 1 && !out_ge_xs && xdm1.get_highest_bit()); // If round_bit is set, we need to recompute sticky_bit, since it might have taken // into account the most-significant bit of xs[-diff - 1]. if round_bit != 0 { fail_on_untested_path("div_float_significands_long_by_short, round_bit != 0"); sticky_bit = xdm1 << 1; // discard the most significant bit if sticky_bit == 0 && x_lo_nonzero { sticky_bit = 1; } } else { sticky_bit |= c; } } } else { // round bit is in scratch[0] round_bit = xs_head & (shift_bit >> 1); sticky_bit |= (xs_head & (shift_mask >> 1)) | c; } 0 } else { // scratch[out_len] != 0 assert_ne!(xs_last, 0); let shift_2 = LeadingZeros::leading_zeros(xs_last); let comp_shift_2 = Limb::WIDTH - shift_2; assert!(y >= 2); // see special cases at the beginning assert_ne!(shift_2, 0); // since y >= 2, shift left to normalize let old_head_1 = xs_head >> comp_shift_2; let old_head_2 = xs_head << shift_2; xs.copy_within(1.., 0); limbs_slice_shl_in_place(xs, shift_2); let xs_head = xs.first_mut().unwrap(); *xs_head |= old_head_1; // now Y is the approximate quotient, w is the next limb. let w = old_head_2; if shift == 0 { // round bit is upper bit from w round_bit = w & LIMB_HIGH_BIT; sticky_bit |= (w - round_bit) | c; } else { round_bit = *xs_head & (shift_bit >> 1); sticky_bit |= (*xs_head & (shift_mask >> 1)) | w | c; } comp_shift_2 }; // Clear the lowest `shift` bits xs[0] &= !shift_mask; xs.truncate(out_len); if round_bit == 0 && sticky_bit == 0 { return (exp_offset, Equal); } match rm { Exact => panic!("Inexact float division"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (xs[0] & shift_bit) == 0) { (exp_offset, Less) } else { if limbs_slice_add_limb_in_place(xs, shift_bit) { exp_offset += 1; *xs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } Floor | Down => (exp_offset, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(xs, shift_bit) { exp_offset += 1; *xs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } } pub(crate) const MPFR_DIVHIGH_TAB: [i8; 17] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // This is `mpn_divrem` from `mpn/divrem.c`, GMP 6.2.1, where qxn is 0. pub(crate) fn limbs_div_helper(qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb]) -> bool { let ns_len = ns.len(); let ds_len = ds.len(); assert!(ns_len >= ds_len); assert_ne!(ds_len, 0); assert!(ds[ds_len - 1].get_highest_bit()); if ds_len == 2 { limbs_div_mod_by_two_limb_normalized(qs, ns, ds) } else { let qs_len = ns_len - ds_len + 1; let mut scratch = vec![0; qs_len]; if ds_len == 1 { ns[0] = limbs_div_limb_to_out_mod(&mut scratch, ns, ds[0]); } else { limbs_div_mod_qs_to_out_rs_to_ns(&mut scratch, ns, ds); } let (scratch_last, scratch_init) = scratch.split_last().unwrap(); qs[..qs_len - 1].copy_from_slice(scratch_init); assert!(*scratch_last < 2); *scratch_last != 0 } } pub(crate) fn limbs_float_div_high_scratch_len(ds_len: usize) -> usize { let k = if ds_len < MPFR_DIVHIGH_TAB.len() { usize::exact_from(MPFR_DIVHIGH_TAB[ds_len]) } else { (ds_len / 3) << 1 }; if k == 0 { 0 } else { let l = ds_len - k; (l << 1) + limbs_float_mul_high_same_length_scratch_len(l) } } // Put in {qs, len} an approximation of N = {ns, 2 * len} divided by D = {ds, len}, // // with the most significant limb of the quotient as return value (0 or 1). Assumes the most // significant bit of D is set. Clobbers N. // // This implements the ShortDiv algorithm from Short Division of Long Integers, David Harvey and // Paul Zimmermann, Proceedings of the 20th Symposium on Computer Arithmetic (ARITH-20), July 25-27, // 2011, pages 7-14. // // Assumes len >= 2 (which should be fulfilled also in the recursive calls). // // This is mpfr_divhigh_n from mulders.c, MPFR 4.2.0. pub(crate) fn limbs_float_div_high( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], scratch: &mut [Limb], ) -> bool { let len = ds.len(); const LENGTH_VALID: bool = MPFR_DIVHIGH_TAB.len() >= 15; assert!(LENGTH_VALID); // so that 2*(n/3) >= (n+4)/2 assert!(len >= 2); let k = if len < MPFR_DIVHIGH_TAB.len() { usize::exact_from(MPFR_DIVHIGH_TAB[len]) } else { (len / 3) << 1 }; let ns = &mut ns[..len << 1]; let qs = &mut qs[..len]; if k == 0 { assert!(len > 2, "must implement mpfr_divhigh_n_basecase"); let inverse = limbs_two_limb_inverse_helper(ds[len - 1], ds[len - 2]); return limbs_div_schoolbook_approx(qs, ns, ds, inverse); } // Check the bounds from. In addition, we forbid k = len - 1, which would give l = 1 in the // recursive call. It follows len >= 5. assert!((len + 4) >> 1 <= k && k < len - 1); let l = len - k; let two_l = l << 1; let two_len_m_k = len + l; // first divide the most significant 2 * k limbs from N by the most significant k limbs of D // exact let (ds_lo, ds_hi) = ds.split_at(l); let mut q_high = limbs_div_helper(&mut qs[l..], &mut ns[two_l..], ds_hi); // It remains {ns, 2 * l + k} = {ns, len + l} as remainder // // now we have to subtract high(Q1) * D0 where Q1 = q_high * B ^ k + {qs + l, k} and D0 = {ds, // l} let (scratch_lo, scratch_hi) = scratch.split_at_mut(two_l); limbs_float_mul_high_same_length(scratch_lo, &qs[k..], ds_lo, scratch_hi); // We are only interested in the upper l limbs from {scratch, 2 * l} let ns_mid = &mut ns[len..two_len_m_k]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left( ns_mid, &scratch_lo[l..], )); if q_high && limbs_sub_same_length_in_place_left(ns_mid, ds_lo) { carry += 1; } while carry != 0 { // Q1 was too large: subtract 1 from Q1 and add D to ns + l if limbs_sub_limb_in_place(&mut qs[l..], 1) { q_high = false; } if limbs_slice_add_same_length_in_place_left(&mut ns[l..two_len_m_k], ds) { carry -= 1; } } // Now it remains {ns, len + l} to divide by D limbs_float_div_high(qs, &mut ns[k..], &ds[k..], scratch) && limbs_slice_add_limb_in_place(&mut qs[l..], 1) || q_high } // Compare {xs, xs_len} and {ys, ys_len} >> extra, aligned by the more significant limbs. Takes into // account ys[0] for extra = true. // // This is mpfr_mpn_cmp_aux from div.c, MPFR 4.2.0. pub fn cmp_helper(xs: &[Limb], ys: &[Limb], extra: bool) -> Ordering { let xs_len = xs.len(); let mut cmp = Equal; if extra { let ys_len = ys.len() - 1; if xs_len >= ys_len { let (xs_lo, xs_hi) = xs.split_at(xs_len - ys_len); for (i, x) in xs_hi.iter().enumerate().rev() { let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); cmp = x.cmp(&y); if cmp != Equal { break; } } let mut y = ys[0] << WIDTH_M1; for x in xs_lo.iter().rev() { if cmp != Equal { break; } cmp = x.cmp(&y); y = 0; // ensure we consider ys[0] & 1 only once } if cmp == Equal && y != 0 { cmp = Less; } } else { let k = ys_len - xs_len; let ys_hi = &ys[k..]; for (i, x) in xs.iter().enumerate().rev() { let y = (ys_hi[i + 1] << WIDTH_M1) | (ys_hi[i] >> 1); cmp = x.cmp(&y); if cmp != Equal { break; } } for i in (0..k).rev() { if cmp != Equal { break; } let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); cmp = if y != 0 { Less } else { Equal }; } if cmp == Equal && extra && ys[0].odd() { cmp = Less; } } } else { let ys_len = ys.len(); if xs_len >= ys_len { let (xs_lo, xs_hi) = xs.split_at(xs_len - ys_len); cmp = limbs_cmp_same_length(xs_hi, ys); if cmp == Equal && !slice_test_zero(xs_lo) { cmp = Greater; } } else { let (ys_lo, ys_hi) = ys.split_at(ys_len - xs_len); cmp = limbs_cmp_same_length(xs, ys_hi); if cmp == Equal && !slice_test_zero(ys_lo) { cmp = Less; } } } cmp } // xs <- xs - ys >> extra - carry, with carry = 0 or 1. Return borrow out. // // This is mpfr_mpn_sub_aux from div.c, MPFR 4.2.0. fn sub_helper(xs: &mut [Limb], ys: &[Limb], mut carry: bool, extra: bool) -> bool { if extra { for (i, x) in xs.iter_mut().enumerate() { let y = (ys[i + 1] << WIDTH_M1) | (ys[i] >> 1); let mut diff = x.wrapping_sub(y); if carry { diff.wrapping_sub_assign(1); } carry = *x < y || carry && diff == Limb::MAX; *x = diff; } } else { for (x, &y) in xs.iter_mut().zip(ys.iter()) { let mut diff = x.wrapping_sub(y); if carry { diff.wrapping_sub_assign(1); } carry = *x < y || carry && diff == Limb::MAX; *x = diff; } } carry } #[inline] fn div_float_significands_general( xs: &[Limb], ys: &mut [Limb], prec: u64, rm: RoundingMode, ) -> (Vec, u64, Ordering) { let mut out = vec![0; bit_to_limb_count_ceiling(prec)]; let (exp_offset, o) = div_float_significands_general_to_out(&mut out, xs, ys, prec, rm); (out, exp_offset, o) } pub(crate) const MPFR_DIV_THRESHOLD: usize = 25; #[derive(Eq, PartialEq, Clone, Copy)] pub(crate) enum Cleanup { None, TruncateCheckQHigh, Sub1Ulp, Sub2Ulp, } // TODO special case qs == ds // // This is mpfr_div from div.c, MPFR 4.2.0, skipping over various special cases fn div_float_significands_general_to_out( qs: &mut [Limb], ns: &[Limb], ds: &mut [Limb], prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { let ns_len = ns.len(); let ds_len = ds.len(); let qs_len = bit_to_limb_count_ceiling(prec); let qs = &mut qs[..qs_len]; // Determine if an extra bit comes from the division, i.e. if the significand of X (as a // fraction in [1/2, 1) ) is larger than that of Y let ns_last = *ns.last().unwrap(); let ds_last = *ds.last().unwrap(); let extra_bit = if ns_last == ds_last { // most significant limbs are equal, must look at further limbs if let Some((n, d)) = ns.iter().rev().zip(ds.iter().rev()).find(|&(n, d)| n != d) { n > d } else if ns_len >= ds_len { // no more divisor limb true } else { // k = 0: no more dividend limb slice_test_zero(&ds[..ds_len - ns_len]) } } else { ns_last > ds_last }; let mut exp_offset = u64::from(extra_bit); // shift is the number of zero bits in the low limb of the quotient let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let mut shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; let mut ys_vec; let mut ys: &mut [Limb]; let mut inex; // We first try Mulders' short division (for large operands) if qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD { // We will perform a short (2 * n) / n division let n = qs_len + 1; let two_n = n << 1; // since Mulders' short division clobbers the dividend, we have to copy it let mut xs = vec![0; two_n]; if ns_len >= two_n { // truncate the dividend xs[..two_n].copy_from_slice(&ns[ns_len - two_n..]); } else { // zero-pad the dividend xs[two_n - ns_len..].copy_from_slice(ns); } if ds_len >= n { // truncate the divisor ys = &mut ds[ds_len - n..]; } else { // zero-pad the divisor ys_vec = vec![0; n]; ys = &mut ys_vec; ys[n - ds_len..].copy_from_slice(ds); } // since n = qs_len + 1, we have n >= 2 here let mut scratch = vec![0; n + limbs_float_div_high_scratch_len(n)]; let (qs_2, scratch) = scratch.split_at_mut(n); let q_high = limbs_float_div_high(qs_2, &mut xs, &ys[..n], scratch); // in all cases, the error is at most (2 * n + 2) ulps on q_high * B ^ n + {qs_2, n}. let p = i32::exact_from( i64::exact_from(n << Limb::LOG_WIDTH) - i64::exact_from((two_n + 2).ceiling_log_base_2()), ); // If rm == Nearest, we need to be able to round with a directed rounding and one more bit. if q_high { let qs_2_lo = &mut qs_2[..n]; limbs_slice_shr_in_place(qs_2_lo, 1); *qs_2_lo.last_mut().unwrap() |= LIMB_HIGH_BIT; if round_helper_2(qs_2_lo, p, prec + u64::from(rm == Nearest)) { // We can round correctly whatever the rounding mode qs.copy_from_slice(&qs_2[1..=qs_len]); qs[0] &= !shift_mask; // put to zero low `shift` bits return match rm { Exact => panic!("Inexact float division"), Nearest => { // round to nearest // // We know we can round, thus we are never in the even rule case: // - if the round bit is 0, we truncate // - if the round bit is 1, we add 1 let round_bit = if shift == 0 { qs_2[0].get_highest_bit() } else { (qs_2[1] >> (shift - 1)).odd() }; if round_bit { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else exponent is now incorrect, but one will still get an // overflow qs[qs_len - 1] = LIMB_HIGH_BIT; } (exp_offset, Greater) } else { (exp_offset, Less) } } Up | Ceiling => { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else exponent is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } Down | Floor => (exp_offset, Less), }; } } } // Mulders' short division failed: we revert to integer division let mut qs_2_vec = vec![]; let mut qs_2: &mut [Limb] = if rm == Nearest && shift == 0 { // We compute the quotient with one more limb, in order to get the round bit in the // quotient, and the remainder only contains sticky bits. Need to allocate memory for the // quotient qs_2_vec = vec![0; qs_len + 1]; &mut qs_2_vec } else { qs // directly put the quotient in the destination }; let qs_2_len = qs_2.len(); let two_qs_2_len = qs_2_len << 1; // prepare the dividend let mut xs = vec![0; two_qs_2_len]; let mut sticky_x = false; if two_qs_2_len > ns_len { // use the full dividend let (xs_lo, xs_hi) = xs.split_at_mut(two_qs_2_len - ns_len); if extra_bit { *xs_lo.last_mut().unwrap() = limbs_shr_to_out(xs_hi, ns, 1); } else { xs_hi.copy_from_slice(ns); } } else { // truncate the dividend let (ns_lo, ns_hi) = ns.split_at(ns_len - two_qs_2_len); let ns_hi = &ns_hi[..two_qs_2_len]; if extra_bit { sticky_x = limbs_shr_to_out(&mut xs, ns_hi, 1) != 0; } else { xs.copy_from_slice(ns_hi); } sticky_x = sticky_x || !slice_test_zero(ns_lo); } let mut low_x = sticky_x; let mut k; // Now sticky_x is non-zero iff the truncated part of x is non-zero let mut sticky_y = false; // Prepare the divisor k = if ds_len >= qs_2_len { k = ds_len - qs_2_len; sticky_y = sticky_y || !slice_test_zero(&ds[..k]); ys = &mut ds[k..]; // avoid copying the divisor 0 } else { // ds_len < qs_2_len: small divisor case ys = ds; qs_2_len - ds_len }; // Here we perform the real division of {xs + k, two_qs_2_len - k} by {ys, qs_2_len - k} In the // general case (ns_len > 2 * qs_2_len and ds_len > qs_2_len), we have: // ``` // ______________________________________ // | | | x1 has 2 * qs_2_len limbs // | x1 | x0 | x0 has ns_len - 2 * qs_2_len limbs // |__________________________|___________| // ____________________ // | | | y1 has qs_2_len limbs // | y1 | y0 | y0 has ds_len - qs_2_len limbs // |___________|________| // ``` // // We divide x1 by y1, with quotient in q_high + {qs_2, qs_2_len} and remainder (denoted r // below) stored in place of the low qs_2_len limbs of x1. // // If Mulders' short division failed, we revert to division with remainder let mut q_high = limbs_div_helper(qs_2, &mut xs[k..], &ys[..qs_2_len - k]); // let x1 be the upper part of x, and y1 the upper part of y (with sticky_x and sticky_y // representing the lower parts), then the quotient of x1 by y1 is now in {qs_2, qs_2_len}, with // possible carry in q_high, and the remainder in {xs + k, qs_2_len - k}. // // Warning: q_high may be 1 if x1 == y1, but x < y. k = qs_2_len; sticky_x = sticky_x || !slice_test_zero(&xs[..k]); let mut sticky_bit = Limb::from(sticky_x | sticky_y); // now sticky_bit is non-zero iff one of the following holds: // - the truncated part of u is non-zero // - the truncated part of v is non-zero // - the remainder from division is non-zero let (mut sticky_3, shift_2) = if qs_2_len == qs_len { // does nothing when shift = 0 (qs_2[0] & shift_mask, shift) } else { // qs_2_len = qs_len + 1: only happens when rm == Nearest and shift = 0 qs.copy_from_slice(&qs_2_vec[1..=qs_len]); qs_2 = &mut qs_2_vec; (qs_2[0], Limb::WIDTH) }; qs_2[0] ^= sticky_3; // sticky_3 contains the truncated bits from the quotient, including the round bit, and 1 <= // shift_2 <= WIDTH is the number of bits in sticky_3 inex = if sticky_bit != 0 || sticky_3 != 0 { Greater } else { Equal }; // to round, we distinguish two cases: // - ds_len <= qs_2_len: we used the full divisor // - ds_len > qs_2_len: the divisor was truncated let mut round_bit = 0; let mut cleanup = Cleanup::None; if ds_len <= qs_2_len { // use the full divisor sticky_bit = if rm == Nearest { round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); (sticky_3 ^ round_bit) | Limb::from(sticky_x) } else if rm == Floor || rm == Down || inex == Equal { Limb::from(inex != Equal) } else if rm == Exact { panic!("Inexact float division"); } else { 1 }; } else { // ds_len > qs_2_len: need to truncate the divisor if inex == Equal { return (exp_offset, Equal); } // We know the estimated quotient is an upper bound of the exact quotient (with rounding // toward zero), with a difference of at most 2 in qs_2[0]. Thus we can round except when // sticky_3 is 000...000 or 000...001 for directed rounding, and 100...000 or 100...001 for // rounding to nearest. (For rounding to nearest, we cannot determine the inexact flag for // 000...000 or 000...001.) let sticky_3_orig = sticky_3; if rm == Nearest { round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); sticky_3 ^= round_bit; } if sticky_3 > 1 { sticky_bit = sticky_3; } else { // hard case: we have to compare q1 * v0 and r + u0, where q1 * v0 has qs_2_len + // (ds_len-qs_2_len) = ds_len limbs, and r + u0 has qs_2_len + (usize-2*qs_2_len) = // usize-qs_2_len limbs let k = ds_len - qs_2_len; // sp <- {qs_2, qs_2_len} * {ds, ds_len - qs_2_len} let mut scratch = vec![0; ds_len + limbs_mul_to_out_scratch_len(qs_2_len, k)]; let (sp, scratch) = scratch.split_at_mut(ds_len); qs_2[0] ^= sticky_3_orig; // restore original quotient let ds_lo = &ds[..k]; limbs_mul_to_out(sp, qs_2, ds_lo, scratch); let q_high_2 = if q_high { limbs_slice_add_same_length_in_place_left(&mut sp[qs_2_len..], ds_lo) } else { false }; qs_2[0] ^= sticky_3_orig; // restore truncated quotient // // Compare q_high_2 + {sp, ds_len} to {xs, qs_2_len} + u0 let (sp_lo, sp_hi) = sp.split_at_mut(k); let mut cmp_s_r = if q_high_2 { Greater } else { limbs_cmp_same_length(sp_hi, &xs[..qs_2_len]) }; if cmp_s_r == Equal { // compare {sp, k} and u0 cmp_s_r = if ns_len >= two_qs_2_len { cmp_helper( sp_lo, &ns[..ns_len - two_qs_2_len + usize::from(extra_bit)], extra_bit, ) } else if slice_test_zero(sp_lo) { Equal } else { Greater }; } // now // - cmp_s_r > 0 if {sp, ds_len} > {xs, qs_2_len} + u0 // - cmp_s_r = 0 if {sp, ds_len} = {xs, qs_2_len} + u0 // - cmp_s_r < 0 if {sp, ds_len} < {xs, qs_2_len} + u0 if cmp_s_r <= Equal { // quotient is in [q1, q1+1) sticky_bit = if cmp_s_r == Equal { sticky_3 } else { 1 }; } else { // cmp_s_r > 0, quotient is < q1: to determine if it is in [q1 - 2, q1 - 1] or in // [q1 - 1, q1], we need to subtract the low part u0 of the dividend from q*v0 let mut carry = false; // subtract u0 >> extra_bit if non-zero if q_high_2 { // whatever the value of {ns, m + k}, it will be smaller than q_high_2 + {sp, k} cmp_s_r = Greater; } else { if low_x { let l = ns_len - two_qs_2_len; // number of limbs in u0 let m = l.saturating_sub(k); carry = extra_bit && ns[m].odd(); if l >= k { // u0 has at least as many limbs than s: first look if {ns, m} is not // zero, and compare {sp, k} and {ns + m, k} if !carry { carry = !slice_test_zero(&ns[..m]); } low_x = carry; carry = sub_helper( sp_lo, &ns[m..m + k + usize::from(extra_bit)], carry, extra_bit, ); } else { // l < k: s has more limbs than u0 low_x = false; let kml = k - l; if carry { carry = limbs_sub_limb_in_place( &mut sp_lo[kml - 1..kml], LIMB_HIGH_BIT, ); } carry = sub_helper( &mut sp_lo[kml..], &ns[..l + usize::from(extra_bit)], carry, extra_bit, ); } } if carry { limbs_sub_limb_in_place(sp_hi, 1); } // subtract r limbs_sub_same_length_in_place_left(sp_hi, &xs[..qs_2_len]); // now compare {sp, ds_len} to y cmp_s_r = limbs_cmp_same_length(sp, ds); if cmp_s_r == Equal && low_x { cmp_s_r = Greater; // since in fact we subtracted less than 1 } } if cmp_s_r <= Equal { // q1 - 1 <= x / y < q1 if sticky_3 == 1 { // q1 - 1 is either representable (directed rounding), or the middle of two // numbers (nearest) sticky_bit = Limb::from(cmp_s_r != Equal); } else if round_bit == 0 { // round_bit=0, sticky_3=0: q1 - 1 is exact only when sh=0 inex = if cmp_s_r != Equal || shift != 0 { Less } else { Equal }; cleanup = if rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) { inex = Greater; Cleanup::TruncateCheckQHigh } else if inex != Equal && rm == Exact { panic!("Inexact float division"); } else { Cleanup::Sub1Ulp }; } else { // sticky_3 = 0, round_bit = 1 ==> rounding to nearest return (exp_offset, cmp_s_r); } } else { // q1 - 2 < x / y < q1 - 1 // // if rm == Nearest, the result is q1 when q1 - 2 >= q1 - 2 ^ (shift - 1), i.e. // shift >= 2, otherwise (shift = 1) it is q1 - 2 (inex, cleanup) = match rm { Exact => { panic!("Inexact float division"); } Nearest => { // shift > 0 // // Case shift = 1: sticky_bit = 0 always, and q1 - round_bit is exactly // representable, like q1 - round_bit - 2. // ``` // round_bit action // 0 subtract two ulps, inex = Less // 1 truncate, inex = Greater // ``` // // Case shift > 1: one ulp is 2 ^ (shift - 1) >= 2 // ``` // round_bit sticky_bit action // 0 0 truncate, inex = Greater // 0 1 truncate, inex = Greater // 1 x truncate, inex = Less // ``` if shift == 1 { if round_bit == 0 { shift_bit = 1; (Less, Cleanup::Sub2Ulp) } else { (Greater, Cleanup::TruncateCheckQHigh) } } else { ( if round_bit == 0 { Greater } else { Less }, Cleanup::TruncateCheckQHigh, ) } } Floor | Down => { // The result is down(q1 - 2), i.e. subtract one ulp if shift > 0, and // two ulps if shift = 0 ( Less, if shift == 0 { Cleanup::Sub2Ulp } else { Cleanup::Sub1Ulp }, ) } Ceiling | Up => ( Greater, if shift == 0 { Cleanup::Sub1Ulp } else { Cleanup::TruncateCheckQHigh }, ), }; } } } } match cleanup { Cleanup::None => { // quotient is in [q1, q1 + 1), round_bit is the round_bit (0 for directed rounding) return if rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0 { ( exp_offset, if round_bit == 0 && sticky_bit == 0 { Equal } else { Less }, ) } else if rm == Exact { panic!("Inexact float division"); } else if rm == Nearest { // sticky_bit != 0 or round != 0 if round_bit == 0 { // necessarily sticky_bit != 0 (exp_offset, Less) } else if sticky_bit != 0 { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } else { // round_bit = 1, sticky_bit = 0 if qs[0] & shift_bit == 0 { (exp_offset, Less) } else { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } } else { // round away from zero, sticky_bit != 0 if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) }; } Cleanup::Sub1Ulp => { // we cannot subtract 1 << (shift + 1), since this is undefined for shift = WIDTH if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } } Cleanup::Sub2Ulp => { if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } } _ => {} } if q_high { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, inex) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_extras.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{limbs_add_limb_to_out, limbs_slice_add_limb_in_place}; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::Limb; use core::cmp::min; use malachite_base::num::arithmetic::traits::{NegModPowerOf2, PowerOf2, WrappingSubAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_test_zero; // This is MPFR_CAN_ROUND from mpfr-impl.h, MPFR 4.2.0. pub fn float_can_round(x: &Natural, err0: u64, prec: u64, rm: RoundingMode) -> bool { match x { Natural(Small(small)) => limb_float_can_round(*small, err0, prec, rm), Natural(Large(xs)) => limbs_float_can_round(xs, err0, prec, rm), } } pub(crate) fn limb_float_can_round(x: Limb, err0: u64, mut prec: u64, rm: RoundingMode) -> bool { if rm == Nearest { prec += 1; } assert!(x.get_highest_bit()); let err = min(err0, u64::power_of_2(Limb::LOG_WIDTH)); if err <= prec { return false; } let mut s = Limb::WIDTH - (prec & Limb::WIDTH_MASK); let n = bit_to_limb_count_floor(err); // Check first limb let mask = Limb::low_mask(s); let mut tmp = x & mask; s = Limb::WIDTH - (err & Limb::WIDTH_MASK); if n == 0 { // prec and error are in the same limb assert!(s < Limb::WIDTH); tmp >>= s; tmp != 0 && tmp != mask >> s } else if tmp == 0 { // Check if error limb is 0 s != Limb::WIDTH && x >> s != 0 } else if tmp == mask { // Check if error limb is 0 s != Limb::WIDTH && x >> s != Limb::MAX >> s } else { // limb is different from 000000 or 1111111 true } } pub fn limbs_float_can_round(xs: &[Limb], err0: u64, mut prec: u64, rm: RoundingMode) -> bool { if rm == Nearest { prec += 1; } let len = xs.len(); assert!(xs[len - 1].get_highest_bit()); let err = min(err0, limb_to_bit_count(len)); if err <= prec { return false; } let k = bit_to_limb_count_floor(prec); let mut s = Limb::WIDTH - (prec & Limb::WIDTH_MASK); let n = bit_to_limb_count_floor(err) - k; assert!(len > k); // Check first limb let mut i = len - k - 1; let mask = Limb::low_mask(s); let mut tmp = xs[i] & mask; i.wrapping_sub_assign(1); if n == 0 { // prec and error are in the same limb s = Limb::WIDTH - (err & Limb::WIDTH_MASK); assert!(s < Limb::WIDTH); tmp >>= s; tmp != 0 && tmp != mask >> s } else if tmp == 0 { // Check if all (n - 1) limbs are 0 let j = i.wrapping_add(2) - n; if n > 1 && xs[j..=i].iter().any(|&x| x != 0) { return true; } // Check if final error limb is 0 s = Limb::WIDTH - (err & Limb::WIDTH_MASK); s != Limb::WIDTH && xs[j - 1] >> s != 0 } else if tmp == mask { // Check if all (n - 1) limbs are 11111111111111111 let j = i.wrapping_add(2) - n; if n > 1 && xs[j..=i].iter().any(|&x| x != Limb::MAX) { return true; } // Check if final error limb is 0 s = Limb::WIDTH - (err & Limb::WIDTH_MASK); s != Limb::WIDTH && xs[j - 1] >> s != Limb::MAX >> s } else { // First limb is different from 000000 or 1111111 true } } const WIDTH_M1_MASK: Limb = Limb::MAX >> 1; pub(crate) const MPFR_EVEN_INEX: i8 = 2; // This is MPFR_RNDRAW_EVEN from mpfr-impl.h, MPFR 4.2.0, returning `inexact` and a `bool` // signifying whether the returned exponent should be incremented. pub(crate) fn round_helper_even( out: &mut [Limb], out_prec: u64, xs: &[Limb], x_prec: u64, rm: RoundingMode, ) -> (i8, bool) { round_helper(out, out_prec, xs, x_prec, rm, |out, xs_hi, ulp| { let ulp_mask = !(ulp - 1); if xs_hi[0] & ulp == 0 { out.copy_from_slice(xs_hi); out[0] &= ulp_mask; (-MPFR_EVEN_INEX, false) } else { let increment = limbs_add_limb_to_out(out, xs_hi, ulp); if increment { *out.last_mut().unwrap() = LIMB_HIGH_BIT; } out[0] &= ulp_mask; (MPFR_EVEN_INEX, increment) } }) } // This is MPFR_RNDRAW and mpfr_round_raw from mpfr-impl.h, MPFR 4.2.0, returning `inexact` and a // `bool` signifying whether the returned exponent should be incremented. pub fn round_helper_raw( out: &mut [Limb], out_prec: u64, xs: &[Limb], x_prec: u64, rm: RoundingMode, ) -> (i8, bool) { round_helper(out, out_prec, xs, x_prec, rm, |out, xs_hi, ulp| { let ulp_mask = !(ulp - 1); if xs_hi[0] & ulp == 0 { out.copy_from_slice(xs_hi); out[0] &= ulp_mask; (-1, false) } else { let increment = limbs_add_limb_to_out(out, xs_hi, ulp); if increment { *out.last_mut().unwrap() = LIMB_HIGH_BIT; } out[0] &= ulp_mask; (1, increment) } }) } // This is MPFR_RNDRAW_GEN from mpfr-impl.h, MPFR 4.2.0, returning `inexact` and a `bool` signifying // whether the returned exponent should be incremented. fn round_helper (i8, bool)>( out: &mut [Limb], out_prec: u64, xs: &[Limb], x_prec: u64, rm: RoundingMode, middle_handler: F, ) -> (i8, bool) { let xs_len = xs.len(); let out_len = out.len(); // Check trivial case when out mantissa has more bits than source if out_prec >= x_prec { out[out_len - xs_len..].copy_from_slice(xs); (0, false) } else { // - Nontrivial case: rounding needed // - Compute position and shift let shift = out_prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let i = xs_len.checked_sub(out_len).unwrap(); let mut sticky_bit; let round_bit; // General case when prec % Limb::WIDTH != 0 let ulp = if shift != 0 { // Compute rounding bit and sticky bit // // Note: in directed rounding modes, if the rounding bit is 1, the behavior does not // depend on the sticky bit; thus we will not try to compute it in this case (this can // be much faster and avoids reading uninitialized data in the current mpfr_mul // implementation). We just make sure that sticky_bit is initialized. let mask = Limb::power_of_2(shift - 1); let x = xs[i]; round_bit = x & mask; sticky_bit = x & (mask - 1); if rm == Nearest || round_bit == 0 { let mut to = i; let mut n = xs_len - out_len; while n != 0 && sticky_bit == 0 { to -= 1; sticky_bit = xs[to]; n -= 1; } } mask << 1 } else { assert!(out_len < xs_len); // Compute rounding bit and sticky bit - see note above let x = xs[i - 1]; round_bit = x & LIMB_HIGH_BIT; sticky_bit = x & WIDTH_M1_MASK; if rm == Nearest || round_bit == 0 { let mut to = i - 1; let mut n = xs_len - out_len - 1; while n != 0 && sticky_bit == 0 { to -= 1; sticky_bit = xs[to]; n -= 1; } } 1 }; let xs_hi = &xs[i..]; let ulp_mask = !(ulp - 1); match rm { Floor | Down | Exact => { out.copy_from_slice(xs_hi); out[0] &= ulp_mask; (if sticky_bit | round_bit != 0 { -1 } else { 0 }, false) } Ceiling | Up => { if sticky_bit | round_bit == 0 { out.copy_from_slice(xs_hi); out[0] &= ulp_mask; (0, false) } else { let increment = limbs_add_limb_to_out(out, xs_hi, ulp); if increment { out[out_len - 1] = LIMB_HIGH_BIT; } out[0] &= ulp_mask; (1, increment) } } Nearest => { if round_bit == 0 { out.copy_from_slice(xs_hi); out[0] &= ulp_mask; (if (sticky_bit | round_bit) != 0 { -1 } else { 0 }, false) } else if sticky_bit == 0 { middle_handler(out, xs_hi, ulp) } else { let increment = limbs_add_limb_to_out(out, xs_hi, ulp); if increment { out[out_len - 1] = LIMB_HIGH_BIT; } out[0] &= ulp_mask; (1, increment) } } } } } // Assuming xs is an approximation of a non-singular number with error at most equal to 2 ^ (EXP(x) // - err0) (`err0` bits of x are known) of direction unknown, check if we can round x toward zero // with precision prec. // // This is mpfr_round_p from round_p.c, MPFR 4.2.0. pub(crate) fn round_helper_2(xs: &[Limb], err0: i32, prec: u64) -> bool { let len = xs.len(); assert!(xs.last().unwrap().get_highest_bit()); let mut err = limb_to_bit_count(len); if err0 <= 0 { return false; } let err0 = u64::from(err0.unsigned_abs()); if err0 <= prec || prec >= err { return false; } err = min(err, err0); let k = bit_to_limb_count_floor(prec); let n = bit_to_limb_count_floor(err) - k; assert!(len > k); // Check first limb let xs = &xs[len - k - n - 1..]; let (xs_last, xs_init) = xs[..=n].split_last().unwrap(); let mut tmp = *xs_last; let mask = Limb::MAX >> (prec & Limb::WIDTH_MASK); tmp &= mask; if n == 0 { // prec and error are in the same limb let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); assert!(s < Limb::WIDTH); tmp >>= s; tmp != 0 && tmp != mask >> s } else if tmp == 0 { let (xs_head, xs_tail) = xs_init.split_first().unwrap(); // Check if all (n - 1) limbs are 0 if !slice_test_zero(xs_tail) { return true; } // Check if final error limb is 0 let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); s != Limb::WIDTH && *xs_head >> s != 0 } else if tmp == mask { let (xs_head, xs_tail) = xs_init.split_first().unwrap(); // Check if all (n - 1) limbs are 11111111111111111 if xs_tail.iter().any(|&x| x != Limb::MAX) { return true; } // Check if final error limb is 0 let s = Limb::WIDTH - (err & Limb::WIDTH_MASK); s != Limb::WIDTH && *xs_head >> s != Limb::MAX >> s } else { // First limb is different from 000000 or 1111111 true } } #[inline] pub fn limbs_significand_slice_add_limb_in_place(xs: &mut [Limb], y: Limb) -> bool { limbs_slice_add_limb_in_place(xs, y) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::float_extras::{limbs_float_can_round, round_helper_raw}; use crate::natural::arithmetic::float_square::{ limbs_float_square_high, limbs_float_square_high_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out_basecase, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling, limb_to_bit_count}; use crate::platform::{DoubleLimb, Limb, MUL_FFT_THRESHOLD}; use alloc::vec::Vec; use core::cmp::{ Ordering::{self, *}, max, min, }; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, OverflowingAddAssign, Parity, PowerOf2, Sign, WrappingAddAssign, XMulYToZZ, XXAddYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{SplitInHalf, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_leading_zeros; // This is mpfr_mul from mul.c, MPFR 4.2.0. pub fn mul_float_significands_in_place( x: &mut Natural, x_prec: u64, y: &mut Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((decrement_exp, o)) = mul_float_significands_in_place_same_prec(x, y, out_prec, rm) { return (-i32::from(decrement_exp), o); } let (product, exp_offset, o) = if x_prec >= y_prec { match (&mut *x, &mut *y) { (Natural(Small(x)), Natural(Small(y))) => { mul_float_significands_general(&[*x], x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Small(y))) => { mul_float_significands_general(xs, x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Large(ys))) => { mul_float_significands_general(xs, x_prec, ys, y_prec, out_prec, rm) } _ => unreachable!(), } } else { match (&mut *x, &mut *y) { (Natural(Small(x)), Natural(Small(y))) => { mul_float_significands_general(&[*y], y_prec, &[*x], x_prec, out_prec, rm) } (Natural(Small(x)), Natural(Large(ys))) => { mul_float_significands_general(ys, y_prec, &[*x], x_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Large(ys))) => { mul_float_significands_general(ys, y_prec, xs, x_prec, out_prec, rm) } _ => unreachable!(), } }; *x = product; (exp_offset, o) } // This is mpfr_mul from mul.c, MPFR 4.2.0. pub fn mul_float_significands_in_place_ref( x: &mut Natural, x_prec: u64, y: &Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((decrement_exp, o)) = mul_float_significands_in_place_same_prec_ref(x, y, out_prec, rm) { return (-i32::from(decrement_exp), o); } let (product, exp_offset, o) = if x_prec >= y_prec { match (&mut *x, y) { (Natural(Small(x)), Natural(Small(y))) => { mul_float_significands_general(&[*x], x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Small(y))) => { mul_float_significands_general(xs, x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Large(ys))) => { mul_float_significands_general(xs, x_prec, ys, y_prec, out_prec, rm) } _ => unreachable!(), } } else { match (&mut *x, y) { (Natural(Small(x)), Natural(Small(y))) => { mul_float_significands_general(&[*y], y_prec, &[*x], x_prec, out_prec, rm) } (Natural(Small(x)), Natural(Large(ys))) => { mul_float_significands_general(ys, y_prec, &[*x], x_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Large(ys))) => { mul_float_significands_general(ys, y_prec, xs, x_prec, out_prec, rm) } _ => unreachable!(), } }; *x = product; (exp_offset, o) } // This is mpfr_mul from mul.c, MPFR 4.2.0. pub fn mul_float_significands_ref_ref( x: &Natural, x_prec: u64, y: &Natural, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { mul_float_significands_ref_ref_helper(&[*x], x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Small(y))) => { mul_float_significands_ref_ref_helper(xs, x_prec, &[*y], y_prec, out_prec, rm) } (Natural(Small(x)), Natural(Large(ys))) => { mul_float_significands_ref_ref_helper(&[*x], x_prec, ys, y_prec, out_prec, rm) } (Natural(Large(xs)), Natural(Large(ys))) => { mul_float_significands_ref_ref_helper(xs, x_prec, ys, y_prec, out_prec, rm) } } } pub(crate) fn mul_float_significands_ref_ref_helper( xs: &[Limb], x_prec: u64, ys: &[Limb], y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { if x_prec == y_prec && out_prec == x_prec && let Some((product, decrement_exp, o)) = mul_float_significands_same_prec_ref_ref(xs, ys, out_prec, rm) { return (product, -i32::from(decrement_exp), o); } if x_prec >= y_prec { mul_float_significands_general(xs, x_prec, ys, y_prec, out_prec, rm) } else { mul_float_significands_general(ys, y_prec, xs, x_prec, out_prec, rm) } } fn mul_float_significands_in_place_same_prec( x: &mut Natural, y: &mut Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (product, decrement_exp, o) = if prec == Limb::WIDTH { mul_float_significands_same_prec_w(*x, *y, rm) } else { mul_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; *x = product; Some((decrement_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_mut_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (product_0, product_1, decrement_exp, o) = mul_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); *x_0 = product_0; *x_1 = product_1; Some((decrement_exp, o)) } ([x_0, x_1, x_2], [y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (product_0, product_1, product_2, decrement_exp, o) = mul_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *y_0, *y_1, *y_2, prec, rm, ); *x_0 = product_0; *x_1 = product_1; *x_2 = product_2; Some((decrement_exp, o)) } _ => None, }, _ => unreachable!(), } } fn mul_float_significands_in_place_same_prec_ref( x: &mut Natural, y: &Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (product, decrement_exp, o) = if prec == Limb::WIDTH { mul_float_significands_same_prec_w(*x, *y, rm) } else { mul_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; *x = product; Some((decrement_exp, o)) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_slice()) { ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (product_0, product_1, decrement_exp, o) = mul_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); *x_0 = product_0; *x_1 = product_1; Some((decrement_exp, o)) } ([x_0, x_1, x_2], [y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (product_0, product_1, product_2, decrement_exp, o) = mul_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *y_0, *y_1, *y_2, prec, rm, ); *x_0 = product_0; *x_1 = product_1; *x_2 = product_2; Some((decrement_exp, o)) } _ => None, }, _ => unreachable!(), } } fn mul_float_significands_same_prec_ref_ref( xs: &[Limb], ys: &[Limb], prec: u64, rm: RoundingMode, ) -> Option<(Natural, bool, Ordering)> { match (xs, ys) { ([x], [y]) => { let (product, decrement_exp, o) = if prec == Limb::WIDTH { mul_float_significands_same_prec_w(*x, *y, rm) } else { mul_float_significands_same_prec_lt_w(*x, *y, prec, rm) }; Some((Natural(Small(product)), decrement_exp, o)) } ([x_0, x_1], [y_0, y_1]) if prec != TWICE_WIDTH => { let (product_0, product_1, decrement_exp, o) = mul_float_significands_same_prec_gt_w_lt_2w(*x_0, *x_1, *y_0, *y_1, prec, rm); Some((Natural(Large(vec![product_0, product_1])), decrement_exp, o)) } ([x_0, x_1, x_2], [y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (product_0, product_1, product_2, decrement_exp, o) = mul_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *y_0, *y_1, *y_2, prec, rm, ); Some(( Natural(Large(vec![product_0, product_1, product_2])), decrement_exp, o, )) } _ => None, } } const WIDTH_M1: u64 = Limb::WIDTH - 1; const COMP_HIGH_BIT: Limb = !LIMB_HIGH_BIT; // This is mpfr_mul_1 from mul.c, MPFR 4.2.0. fn mul_float_significands_same_prec_lt_w( x: Limb, y: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; let (mut z, mut sticky_bit) = Limb::x_mul_y_to_zz(x, y); let decrement_exp = !z.get_highest_bit(); if decrement_exp { z <<= 1; z |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; } let round_bit = z & (shift_bit >> 1); sticky_bit |= (z & mask) ^ round_bit; let mut product = z & !mask; if round_bit == 0 && sticky_bit == 0 { return (z, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float multiplication"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (product & shift_bit) == 0) { (product, decrement_exp, Less) } else if product.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, false, Greater) } else { (product, decrement_exp, Greater) } } Floor | Down => (product, decrement_exp, Less), Ceiling | Up => { if product.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, false, Greater) } else { (product, decrement_exp, Greater) } } } } // This is mpfr_mul_1n from mul.c, MPFR 4.2.0. fn mul_float_significands_same_prec_w( x: Limb, y: Limb, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let (mut z, mut sticky_bit) = Limb::x_mul_y_to_zz(x, y); let decrement_exp = !z.get_highest_bit(); if decrement_exp { z <<= 1; z |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; } let round_bit = sticky_bit & LIMB_HIGH_BIT; sticky_bit &= COMP_HIGH_BIT; let mut product = z; if round_bit == 0 && sticky_bit == 0 { return (z, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float multiplication"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && product.even()) { (product, decrement_exp, Less) } else if product.overflowing_add_assign(1) { (LIMB_HIGH_BIT, false, Greater) } else { (product, decrement_exp, Greater) } } Floor | Down => (product, decrement_exp, Less), Ceiling | Up => { if product.overflowing_add_assign(1) { (LIMB_HIGH_BIT, false, Greater) } else { (product, decrement_exp, Greater) } } } } const TWICE_WIDTH: u64 = Limb::WIDTH * 2; const THRICE_WIDTH: u64 = Limb::WIDTH * 3; // This is mpfr_mul_2 from mul.c, MPFR 4.2.0. fn mul_float_significands_same_prec_gt_w_lt_2w( x_0: Limb, x_1: Limb, y_0: Limb, y_1: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, bool, Ordering) { let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; // we store the 4-limb product in h = z[1], l = z[0], sticky_bit = z[-1], sticky_bit_2 = z[-2] let (mut hi, mut lo) = Limb::x_mul_y_to_zz(x_1, y_1); let (u, v) = Limb::x_mul_y_to_zz(x_1, y_0); if lo.overflowing_add_assign(u) { hi += 1; } let (u, w) = Limb::x_mul_y_to_zz(x_0, y_1); if lo.overflowing_add_assign(u) { hi.wrapping_add_assign(1); } // now the full product is {hi, lo, v + w + high(x_0 * y_0), low(x_0 * y_0)}, where the lower // part contributes to less than 3 ulps to {hi, lo}. // // If hi has its most significant bit set and the low shift - 1 bits of lo are not 000...000 nor // 111...111 nor 111...110, then we can round correctly; if hi has zero as most significant bit, // we have to shift left hi and lo, thus if the low sh-2 bits are not 000...000 nor 111...111 // nor 111...110, then we can round correctly. To avoid an extra test we consider the latter // case (if we can round, we can also round in the former case). For shift <= 3, we have mask <= // 7, thus (mask >> 2) <= 1, and the approximation cannot be enough. let (mut sticky_bit, sticky_bit_2); if lo.wrapping_add(2) & (mask >> 2) > 2 { // result cannot be exact in that case sticky_bit = 1; sticky_bit_2 = 1; } else { (sticky_bit, sticky_bit_2) = Limb::x_mul_y_to_zz(x_0, y_0); // The full product is {h, l, sticky_bit + v + w, sticky_bit_2} if sticky_bit.overflowing_add_assign(v) && lo.overflowing_add_assign(1) { hi.wrapping_add_assign(1); } if sticky_bit.overflowing_add_assign(w) && lo.overflowing_add_assign(1) { hi.wrapping_add_assign(1); } } let decrement_exp = !hi.get_highest_bit(); if decrement_exp { hi <<= 1; hi |= lo >> WIDTH_M1; lo <<= 1; lo |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; // no need to shift sticky_bit_2 since we only want to know if it is zero or not } let mut z_1 = hi; let round_bit = lo & (shift_bit >> 1); sticky_bit |= ((lo & mask) ^ round_bit) | sticky_bit_2; let mut z_0 = lo & !mask; if round_bit == 0 && sticky_bit == 0 { return (z_0, z_1, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float multiplication"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (z_0 & shift_bit) == 0) { (z_0, z_1, decrement_exp, Less) } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, decrement_exp, Greater) } } Floor | Down => (z_0, z_1, decrement_exp, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, decrement_exp, Greater) } } } } const LIMB_MASK: DoubleLimb = (1 << Limb::WIDTH) - 1; // This is mpfr_mul_3 from mul.c, MPFR 4.2.0. fn mul_float_significands_same_prec_gt_2w_lt_3w( x_0: Limb, x_1: Limb, x_2: Limb, y_0: Limb, y_1: Limb, y_2: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, Limb, bool, Ordering) { let shift = THRICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; // we store the upper 3-limb product in z2, z1, z0: x2 * y2, x2 * y1 + x1 * y2, x2 * y0 + x1 * // y1 + x0 * y2 let x_0 = DoubleLimb::from(x_0); let x_1 = DoubleLimb::from(x_1); let x_2 = DoubleLimb::from(x_2); let y_0 = DoubleLimb::from(y_0); let y_1 = DoubleLimb::from(y_1); let y_2 = DoubleLimb::from(y_2); let x_2_y_2 = x_2 * y_2; let x_2_y_1 = x_2 * y_1; let x_1_y_2 = x_1 * y_2; let x_2_y_0 = x_2 * y_0; let x_1_y_1 = x_1 * y_1; let x_0_y_2 = x_0 * y_2; let (mut a2, mut a1) = x_2_y_2.split_in_half(); let (hi, mut a0) = x_2_y_1.split_in_half(); if a1.overflowing_add_assign(hi) { a2 += 1; } let (hi, lo) = x_1_y_2.split_in_half(); if a1.overflowing_add_assign(hi) { a2.wrapping_add_assign(1); } let mut carry = Limb::from(a0.overflowing_add_assign(lo)); if a0.overflowing_add_assign(Limb::wrapping_from(x_2_y_0 >> Limb::WIDTH)) { carry += 1; } if a0.overflowing_add_assign(Limb::wrapping_from(x_1_y_1 >> Limb::WIDTH)) { carry += 1; } if a0.overflowing_add_assign(Limb::wrapping_from(x_0_y_2 >> Limb::WIDTH)) { carry += 1; } // now propagate carry if a1.overflowing_add_assign(carry) { a2.wrapping_add_assign(1); } // Now the approximate product {a2, a1, a0} has an error of less than 5 ulps (3 ulps for the // ignored low limbs of x_2 * y_0 + x_1 * y_1 + x_0 * y2, plus 2 ulps for the ignored x_1 * y_0 // + x_0 * y_1 (plus x_0 * y_0)). Since we might shift by 1 bit, we make sure the low shift - 2 // bits of a0 are not 0, -1, -2, -3 or -4. let (mut sticky_bit, sticky_bit_2) = if a0.wrapping_add(4) & (mask >> 2) > 4 { // result cannot be exact in that case (1, 1) } else { let out = x_0 * y_0; let p_0 = out & LIMB_MASK; let out = x_1 * y_0 + (out >> Limb::WIDTH); let mut p_1 = out & LIMB_MASK; let out = x_2_y_0 + (out >> Limb::WIDTH); let mut p_2 = out & LIMB_MASK; let mut p_3 = out >> Limb::WIDTH; let out = p_1 + x_0 * y_1; p_1 = out & LIMB_MASK; let out = p_2 + x_1_y_1 + (out >> Limb::WIDTH); p_2 = out & LIMB_MASK; let out = p_3 + x_2_y_1 + (out >> Limb::WIDTH); p_3 = out & LIMB_MASK; let p_4 = out >> Limb::WIDTH; let out = p_2 + x_0_y_2; p_2 = out & LIMB_MASK; let out = p_3 + x_1_y_2 + (out >> Limb::WIDTH); p_3 = out & LIMB_MASK; let out = p_4 + x_2_y_2 + (out >> Limb::WIDTH); (a2, a1) = out.split_in_half(); a0 = Limb::wrapping_from(p_3); ( Limb::wrapping_from(p_2), Limb::wrapping_from(p_1) | Limb::wrapping_from(p_0), ) }; let decrement_exp = !a2.get_highest_bit(); if decrement_exp { a2 <<= 1; a2 |= a1 >> WIDTH_M1; a1 <<= 1; a1 |= a0 >> WIDTH_M1; a0 <<= 1; a0 |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; // no need to shift sticky_bit_2: we only need to know if it is zero or not } let mut z_2 = a2; let mut z_1 = a1; let round_bit = a0 & (shift_bit >> 1); sticky_bit |= ((a0 & mask) ^ round_bit) | sticky_bit_2; let mut z_0 = a0 & !mask; if round_bit == 0 && sticky_bit == 0 { return (z_0, z_1, z_2, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float multiplication"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && z_0 & shift_bit == 0) { (z_0, z_1, z_2, decrement_exp, Less) } else { if z_0.overflowing_add_assign(shift_bit) { z_1.wrapping_add_assign(1); } if z_1 == 0 && z_0 == 0 { z_2.wrapping_add_assign(1); } if z_2 == 0 { (z_0, z_1, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, z_2, decrement_exp, Greater) } } } Floor | Down => (z_0, z_1, z_2, decrement_exp, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) { z_1.wrapping_add_assign(1); } if z_1 == 0 && z_0 == 0 { z_2.wrapping_add_assign(1); } if z_2 == 0 { (z_0, z_1, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, z_2, decrement_exp, Greater) } } } } pub(crate) const MPFR_MULHIGH_TAB: [i8; 17] = [-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // This is mpfr_mulhigh_n_basecase from mulders.c, MPFR 4.2.0. fn limbs_float_mul_high_same_length_basecase(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(ys.len(), len); // We neglect xs[0..len - 2] * ys[0], which is less than B ^ len let out = &mut out[len - 1..]; (out[1], out[0]) = Limb::x_mul_y_to_zz(*xs.last().unwrap(), ys[0]); for (i, y) in ys.iter().enumerate() { let i = i + 1; // Here, we neglect xs[0..len - i - 2] * ys[i], which is less than B ^ len too let (out_lo, out_hi) = out.split_at_mut(i); out_hi[0] = limbs_slice_add_mul_limb_same_length_in_place_left(out_lo, &xs[len - i..], *y); // In total, we neglect less than n * B ^ len, i.e., n ulps of out[len]. } } pub(crate) fn limbs_float_mul_high_same_length_scratch_len(len: usize) -> usize { if len > MUL_FFT_THRESHOLD { limbs_mul_same_length_to_out_scratch_len(len) } else { let k = MPFR_MULHIGH_TAB.get(len).map_or_else( || 3 * (len >> 2), |&m| if m == -1 { 0 } else { usize::wrapping_from(m) }, ); if k == 0 { 0 } else { limbs_mul_same_length_to_out_scratch_len(max(len, len - k)) } } } // Put in out[n..2 * len - 1] an approximation of the n high limbs of xs * ys. The error is less // than len ulps of out[len] (and the approximation is always less or equal to the truncated full // product). // // Implements Algorithm ShortMul from: // // [1] Short Division of Long Integers, David Harvey and Paul Zimmermann, Proceedings of the 20th // Symposium on Computer Arithmetic (ARITH-20), July 25-27, 2011, pages 7-14. // // This is mpfr_mulhigh_n from mulders.c, MPFR 4.2.0. pub(crate) fn limbs_float_mul_high_same_length( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let len = xs.len(); assert_eq!(ys.len(), len); const LENGTH_VALID: bool = MPFR_MULHIGH_TAB.len() >= 8; assert!(LENGTH_VALID); // so that 3 * (len / 4) > len / 2 let k = MPFR_MULHIGH_TAB.get(len).map_or_else( || Some(3 * (len >> 2)), |&m| { if m == -1 { None } else { Some(usize::wrapping_from(m)) } }, ); assert!(k.is_none() || k == Some(0) || (k.unwrap() >= (len + 4) >> 1 && k.unwrap() < len)); if let Some(k) = k { if k == 0 { // basecase error < len ulps limbs_float_mul_high_same_length_basecase(out, xs, ys); } else if len > MUL_FFT_THRESHOLD { // result is exact, no error limbs_mul_same_length_to_out(out, xs, ys, scratch); } else { let l = len - k; let out = &mut out[..len << 1]; let (out_lo, out_hi) = out.split_at_mut(l << 1); let (ys_lo, ys_hi) = ys.split_at(l); limbs_mul_same_length_to_out(out_hi, &xs[l..], ys_hi, scratch); limbs_float_mul_high_same_length(out_lo, &xs[k..], ys_lo, scratch); let out_hi = &mut out_hi[k - l - 1..k]; let mut carry = Limb::from(limbs_slice_add_same_length_in_place_left( out_hi, &out_lo[l - 1..], )); limbs_float_mul_high_same_length(out_lo, &xs[..l], &ys[k..], scratch); if limbs_slice_add_same_length_in_place_left(out_hi, &out_lo[l - 1..]) { carry += 1; } limbs_slice_add_limb_in_place(&mut out[len + l..], carry); } } else { // result is exact, no error limbs_mul_greater_to_out_basecase(out, xs, ys); } } const MPFR_MUL_THRESHOLD: usize = 20; // x.limb_count() >= y.limb_count() fn mul_float_significands_general( xs: &[Limb], x_prec: u64, ys: &[Limb], y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let mut new_xs; let mut new_ys; let orig_xs = xs; let orig_ys = ys; let mut xs = xs; let mut ys = ys; let k = xs_len.checked_add(ys_len).unwrap(); let tmp_len = bit_to_limb_count_ceiling(x_prec.checked_add(y_prec).unwrap()); assert!(tmp_len <= k); let mut tmp_vec: Vec; let mut tmp: &mut [Limb]; let mut b1 = false; let mut goto_full_multiply = xs_len > 2 && ys_len <= MPFR_MUL_THRESHOLD; let mut to = 0; if xs_len <= 2 { tmp_vec = vec![0; k]; tmp = &mut tmp_vec; // The 3 cases perform the same first operation. (tmp[1], tmp[0]) = Limb::x_mul_y_to_zz(xs[0], ys[0]); b1 = if xs_len == 1 { // 1 limb * 1 limb tmp[1] } else if ys_len == 1 { // 2 limbs * 1 limb let t; (tmp[2], t) = Limb::x_mul_y_to_zz(xs[1], ys[0]); (tmp[2], tmp[1]) = Limb::xx_add_yy_to_zz(tmp[2], tmp[1], 0, t); tmp[2] } else { // 2 limbs * 2 limbs // // First 2 limbs * 1 limb let mut t1; (tmp[2], t1) = Limb::x_mul_y_to_zz(xs[1], ys[0]); (tmp[2], tmp[1]) = Limb::xx_add_yy_to_zz(tmp[2], tmp[1], 0, t1); let t2; // Second, the other 2 limbs * 1 limb product (t1, t2) = Limb::x_mul_y_to_zz(xs[0], ys[1]); let t3; (tmp[3], t3) = Limb::x_mul_y_to_zz(xs[1], ys[1]); (tmp[3], t1) = Limb::xx_add_yy_to_zz(tmp[3], t1, 0, t3); // Sum those two partial products (tmp[2], tmp[1]) = Limb::xx_add_yy_to_zz(tmp[2], tmp[1], t1, t2); let tmp_2 = tmp[2]; if tmp_2 < t1 { tmp[3].wrapping_add_assign(1); } tmp[3] } .get_highest_bit(); to = k - tmp_len; if !b1 { limbs_slice_shl_in_place(&mut tmp[to..to + tmp_len], 1); } } else if ys_len > MPFR_MUL_THRESHOLD { // xs_len >= ys_len and xs_len >= 3 // // Mulders' mulhigh. // // First check if we can reduce the precision of x or y: exact values are a nightmare for // the short product trick if xs[0] == 0 && xs[1] == 0 || ys[0] == 0 && ys[1] == 0 { let xs_leading_zeros = slice_leading_zeros(xs); assert_ne!(xs_leading_zeros, xs_len); let ys_leading_zeros = slice_leading_zeros(ys); assert_ne!(ys_leading_zeros, ys_len); return mul_float_significands_ref_ref_helper( &xs[xs_leading_zeros..], limb_to_bit_count(xs_len - xs_leading_zeros), &ys[ys_leading_zeros..], limb_to_bit_count(ys_len - ys_leading_zeros), out_prec, rm, ); } // Compute estimated precision of mulhigh. let mut len = min(bit_to_limb_count_ceiling(out_prec) + 1, ys_len); assert!(len >= 1 && len << 1 <= k && len <= ys_len && len <= xs_len); let mut p = limb_to_bit_count(len) - (len + 2).ceiling_log_base_2(); // Check if MulHigh can produce a roundable result. We may lose 1 bit due to Nearest, 1 due // to final shift. let mut tmp_alloc = k; if out_prec > p - 5 { if out_prec > p - 5 + Limb::WIDTH || xs_len <= MPFR_MUL_THRESHOLD + 1 { // MulHigh can't produce a roundable result. goto_full_multiply = true; xs = &xs[xs_len - len..]; ys = &ys[ys_len - len..]; } else { // Add one extra limb to mantissa of x and y. if xs_len > len { xs = &xs[xs_len - len - 1..]; } else { new_xs = vec![0; len + 1]; new_xs[1..].copy_from_slice(&xs[xs_len - len..xs_len]); xs = &new_xs; } #[cfg(feature = "32_bit_limbs")] { if ys_len > len { ys = &ys[ys_len - len - 1..]; // This can only happen with 32-bit limbs, and is very unlikely to happen. // Indeed, since len = min(z_len + 1, ys_len), with z_len = prec / // Limb::WIDTH, we can have ys_len > len only when len = z_len + 1 < ys_len. // We are in the case prec > p - 5, p = len * Limb::WIDTH - ceil(log_2(len + // 2)), thus z_len * Limb::WIDTH - shift > len * Limb::WIDTH - // ceil(log_2(len + 2)) - 5. Thus len < z_len + (ceil(log_2(len + 2)) + 5 - // shift) / Limb::WIDTH. To get len = z_len + 1, we need ceil(log_2(len + // 2)) + 5 - shift > Limb::WIDTH, thus since shift >= 0 we need // ceil(log_2(len + 2)) + 5 > Limb::WIDTH. With Limb::WIDTH = 32 this can // only happen for len >= 2^27 - 1, thus for a precision of 2 ^ 32 - 64 for // z, and with Limb::WIDTH = 64 for n >= 2 ^ 59-1, which would give a // precision >= 2^64. } else { new_ys = vec![0; len + 1]; new_ys[1..].copy_from_slice(&ys[ys_len - len..ys_len]); ys = &new_ys; } } #[cfg(not(feature = "32_bit_limbs"))] { new_ys = vec![0; len + 1]; new_ys[1..].copy_from_slice(&ys[ys_len - len..ys_len]); ys = &new_ys; } // We will compute with one extra limb. len += 1; // ceil(log_2(len + 2)) takes into account the lost bits due to Mulders' short // product. p = limb_to_bit_count(len) - (len + 2).ceiling_log_base_2(); // Due to some nasty reasons we can have only 4 bits assert!(out_prec <= p - 4); let twice_len = len << 1; if k < twice_len { tmp_alloc = twice_len; to = twice_len - k; } else { fail_on_untested_path("mul_float_significands_general, k >= len << 1 "); } } } else { xs = &xs[xs_len - len..]; ys = &ys[ys_len - len..]; } if goto_full_multiply { tmp_vec = vec![0; tmp_alloc]; tmp = &mut tmp_vec; } else { // Compute an approximation of the product of x and y let square = core::ptr::eq(xs, ys) && x_prec == y_prec; tmp_vec = vec![ 0; if square { limbs_float_square_high_scratch_len(len) } else { limbs_float_mul_high_same_length_scratch_len(len) } + tmp_alloc ]; let scratch: &mut [Limb]; (tmp, scratch) = tmp_vec.split_at_mut(tmp_alloc); if square { limbs_float_square_high(&mut tmp[to + k - (len << 1)..], xs, scratch); } else { limbs_float_mul_high_same_length(&mut tmp[to + k - (len << 1)..], xs, ys, scratch); } // now tmp[k - len]..tmp[k - 1] contains an approximation of the `len` upper limbs of // the product, with tmp[k - 1] >= 2 ^ (Limb::WIDTH - 2) // // msb from the product // // If the mantissas of x and y are uniformly distributed in (1/2, 1], then their product // is in (1/4, 1/2] with probability 2 * ln(2) - 1 ~ 0.386 and in [1/2, 1] with // probability 2 - 2 * ln(2) ~ 0.614 b1 = tmp[to + k - 1].get_highest_bit(); if !b1 { limbs_slice_shl_in_place(&mut tmp[to + k - len - 1..to + k], 1); } // Now the approximation is in tmp[temp_len - len]...tmp[temp_len - 1] assert!(tmp[to + k - 1].get_highest_bit()); // if the most significant bit b1 is zero, we have only p - 1 correct bits if limbs_float_can_round( &tmp[to + k - tmp_len..to + k], p + u64::from(b1) - 1, out_prec, rm, ) { to += k - tmp_len; } else { goto_full_multiply = true; } } } else { tmp_vec = vec![0; k]; tmp = &mut tmp_vec; } tmp = &mut tmp[to..]; if goto_full_multiply { let mut scratch = vec![0; limbs_mul_to_out_scratch_len(xs_len, ys_len)]; b1 = limbs_mul_to_out(tmp, orig_xs, orig_ys, &mut scratch).get_highest_bit(); // Now tmp[0]..tmp[k - 1] contains the product of both mantissas, with tmp[k - 1] >= 2 ^ // (Limb::WIDTH - 2). // // msb from the product // // If the mantissas of x and y are uniformly distributed in (1/2, 1], then their product is // in (1/4, 1/2] with probability 2 * ln(2) - 1 ~ 0.386 and in [1/2, 1] with probability 2 - // 2 * ln(2) ~ 0.614 tmp = &mut tmp[k - tmp_len..]; if !b1 { limbs_slice_shl_in_place(&mut tmp[..tmp_len], 1); } } let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (inexact, increment_exp) = round_helper_raw( &mut out, out_prec, tmp, x_prec.checked_add(y_prec).unwrap(), rm, ); assert!(inexact == 0 || rm != Exact, "Inexact float multiplication"); let mut exp_offset = -i32::from(!b1); if increment_exp { exp_offset += 1; } ( Natural::from_owned_limbs_asc(out), exp_offset, inexact.sign(), ) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_reciprocal.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div_mod::{div_mod_by_preinversion, limbs_invert_limb}; use crate::natural::arithmetic::float_div::{ Cleanup, MPFR_DIV_THRESHOLD, limbs_div_helper, limbs_float_div_high, limbs_float_div_high_scratch_len, }; use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling}; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ NegModPowerOf2, OverflowingAddAssign, OverflowingNegAssign, Parity, PowerOf2, WrappingAddAssign, WrappingNegAssign, WrappingSubAssign, XMulYToZZ, XXSubYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_test_zero; const TWICE_WIDTH: u64 = Limb::WIDTH * 2; // This is mpfr_div from div.c, MPFR 4.3.0, specialized for reciprocation. pub fn reciprocal_float_significand_in_place( x: &mut Natural, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { if out_prec == x_prec && let Some((increment_exp, o)) = reciprocal_float_significand_in_place_same_prec(x, out_prec, rm) { return (u64::from(increment_exp), o); } match &mut *x { Natural(Small(small_x)) => { let (qs, exp_offset, o) = reciprocal_float_significand_short(*small_x, out_prec, rm); *x = Natural::from_owned_limbs_asc(qs); (exp_offset, o) } Natural(Large(xs)) => { let (out, exp_offset, o) = reciprocal_float_significand_general(xs, out_prec, rm); *x = Natural::from_owned_limbs_asc(out); (exp_offset, o) } } } // This is mpfr_div from div.c, MPFR 4.3.0, specialized for reciprocation. pub fn reciprocal_float_significand_ref( x: &Natural, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, u64, Ordering) { if out_prec == x_prec && let Some((reciprocal, increment_exp, o)) = reciprocal_float_significand_same_prec_ref(x, out_prec, rm) { return (reciprocal, u64::from(increment_exp), o); } match x { Natural(Small(small_x)) => { let (qs, exp_offset, o) = reciprocal_float_significand_short(*small_x, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } Natural(Large(xs)) => { let mut xs = xs.clone(); let (qs, exp_offset, o) = reciprocal_float_significand_general(&mut xs, out_prec, rm); (Natural::from_owned_limbs_asc(qs), exp_offset, o) } } } fn reciprocal_float_significand_in_place_same_prec( x: &mut Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match x { Natural(Small(x)) => { let (reciprocal, increment_exp, o) = if prec == Limb::WIDTH { reciprocal_float_significand_same_prec_w(*x, rm) } else { reciprocal_float_significand_same_prec_lt_w(*x, prec, rm) }; *x = reciprocal; Some((increment_exp, o)) } Natural(Large(xs)) => match xs.as_mut_slice() { [x_0, x_1] if prec != TWICE_WIDTH => { let (reciprocal_0, reciprocal_1, increment_exp, o) = reciprocal_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); *x_0 = reciprocal_0; *x_1 = reciprocal_1; Some((increment_exp, o)) } _ => None, }, } } fn reciprocal_float_significand_same_prec_ref( x: &Natural, prec: u64, rm: RoundingMode, ) -> Option<(Natural, bool, Ordering)> { match x { Natural(Small(x)) => { let (reciprocal, increment_exp, o) = if prec == Limb::WIDTH { reciprocal_float_significand_same_prec_w(*x, rm) } else { reciprocal_float_significand_same_prec_lt_w(*x, prec, rm) }; Some((Natural(Small(reciprocal)), increment_exp, o)) } Natural(Large(xs)) => match xs.as_slice() { [x_0, x_1] if prec != TWICE_WIDTH => { let (reciprocal_0, reciprocal_1, increment_exp, o) = reciprocal_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); Some(( Natural(Large(vec![reciprocal_0, reciprocal_1])), increment_exp, o, )) } _ => None, }, } } // x cannot be equal to `2 ^ (WIDTH - 1)`. // // This is mpfr_div_1 from mul.c, MPFR 4.3.0, specialized for reciprocation. fn reciprocal_float_significand_same_prec_lt_w( x: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let half_shift_bit = shift_bit >> 1; let mask = shift_bit - 1; // First try with an approximate reciprocal. let q = LIMB_HIGH_BIT | (limbs_invert_limb::(x) >> 1); // round_bit does not exceed the true reciprocal floor(LIMB_HIGH_BIT * 2 ^ WIDTH / x), with // error at most 2, which means the rational reciprocal q satisfies round_bit <= q < round_bit + // 3. We can round correctly except when the last shift - 1 bits of q0 are 000..000 or 111..111 // or 111..110. let (round_bit, sticky_bit) = if (q + 2) & (mask >> 1) > 2 { // result cannot be exact in this case (q & half_shift_bit, 1) } else { let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, x); assert!(hi < LIMB_HIGH_BIT || (hi == LIMB_HIGH_BIT && lo == 0)); // subtract {hi, lo} from {LIMB_HIGH_BIT, 0} (hi, lo) = Limb::xx_sub_yy_to_zz(LIMB_HIGH_BIT, 0, hi, lo); assert!(hi == 0 && lo < x); (q & half_shift_bit, lo | (q & (mask >> 1))) }; let reciprocal = (LIMB_HIGH_BIT | q) & !mask; match rm { Exact => panic!("Inexact float reciprocation"), Nearest => { if round_bit == 0 || sticky_bit == 0 && reciprocal & shift_bit == 0 { (reciprocal, false, Less) } else { (reciprocal.wrapping_add(shift_bit), false, Greater) } } Floor | Down => (reciprocal, false, Less), Ceiling | Up => (reciprocal.wrapping_add(shift_bit), false, Greater), } } // x cannot be equal to `2 ^ (WIDTH - 1)`. fn reciprocal_float_significand_same_prec_w(x: Limb, rm: RoundingMode) -> (Limb, bool, Ordering) { // First compute an approximate reciprocal. let q = LIMB_HIGH_BIT | (limbs_invert_limb::(x) >> 1); // round_bit does not exceed the true reciprocal floor(2 ^ WIDTH / x), with error at most 2, // which means the rational reciprocal q satisfies round_bit <= q < round_bit + 3, thus the true // reciprocal is round_bit, round_bit + 1 or round_bit + 2. let (mut hi, mut lo) = Limb::x_mul_y_to_zz(q, x); assert!(hi < LIMB_HIGH_BIT || (hi == LIMB_HIGH_BIT && lo == 0)); // subtract {hi, lo} from {LIMB_HIGH_BIT, 0} (hi, lo) = Limb::xx_sub_yy_to_zz(LIMB_HIGH_BIT, 0, hi, lo); assert!(hi == 0 && lo < x); // now (LIMB_HIGH_BIT - extra * x) * 2 ^ WIDTH = q * x + lo with 0 <= lo < x // // If !increment_exp, the reciprocal is q0, the round bit is 1 if l >= x0 / 2, and sticky_bit // are the remaining bits from l. If increment_exp, the reciprocal is LIMB_HIGH_BIT + (q >> 1), // the round bit is the least significant bit of q, and sticky_bit is lo. // // If "2 * lo < lo", then there is a carry in 2 * lo, thus 2 * lo > x. Otherwise if there is no // carry, we check whether 2 * lo >= y0. let two_lo = lo << 1; let round_bit = (two_lo < lo) || (two_lo >= x); let mut reciprocal = q; let sticky_bit = if round_bit { two_lo.wrapping_sub(x) } else { lo }; match rm { Exact => panic!("Inexact float reciprocation"), Nearest => { if !round_bit || sticky_bit == 0 && reciprocal.even() { (reciprocal, false, Less) } else { reciprocal.wrapping_add_assign(1); (reciprocal, false, Greater) } } Floor | Down => (reciprocal, false, Less), Ceiling | Up => { reciprocal.wrapping_add_assign(1); (reciprocal, false, Greater) } } } // Given (B << WIDTH) < x = x_1 * B + x_0 with x normalized (high bit of x_1 set), put in q = Q1 // * B + Q0 an approximation of floor(B ^ 2 / x), with: B = 2 ^ WIDTH and q <= floor(B ^ 2 / // x) <= q + 21. // // This is mpfr_div2_approx from div.c, MPFR 4.3.0, where Q0 and Q1 are returned, specialized for // reciprocation. fn reciprocal_float_2_approx(x_1: Limb, x_0: Limb) -> (Limb, Limb) { // First compute an approximation of q_1, using a lower approximation of B ^ 2 / (x_1 + 1) - B let inv = if x_1 == Limb::MAX { 0 } else { limbs_invert_limb::(x_1 + 1) }; // Now inv <= B ^ 2 / (x_1 + 1) - B. let mut q_1 = LIMB_HIGH_BIT | (inv >> 1); // Now q_1 <= x_1 * B / (x_1 + 1) < (x_1 * B + x_0) * B / (x_1 * B + x_0). // // Compute q_1 * (x_1 * B + x_0) into r_1 : r_0 : xx and subtract from u_1 : x_0 : 0. let (mut r_1, mut r_0) = Limb::x_mul_y_to_zz(q_1, x_1); let (xx, yy) = Limb::x_mul_y_to_zz(q_1, x_0); if r_0.overflowing_add_assign(xx) { r_1.wrapping_add_assign(1); } // We ignore yy below, but first increment r_0, to ensure we get a lower approximation of the // remainder. if yy != 0 { r_0.wrapping_add_assign(1); } if r_0 == 0 && yy != 0 { r_1.wrapping_add_assign(1); } r_1 = LIMB_HIGH_BIT.wrapping_sub(r_1); let carry; (r_0, carry) = r_0.overflowing_neg(); if carry { r_1.wrapping_sub_assign(1); } // r_1 : r_0 should be non-negative. assert!(!r_1.get_highest_bit()); // The second reciprocal limb is approximated by (r_1 * B ^ 2 + r_0 * B) / x_1, and since (B + // inv) / B approximates B / x_1, this is in turn approximated by (r * B + r_0) * (B + inv) / B // = r_1 * B * r_1 * inv + r_0 + (r0 * inv / B). q_1.wrapping_add_assign(r_1); // Add floor(r_0 * inv / B) to q_0. if r_0.overflowing_add_assign(Limb::wrapping_from( (DoubleLimb::from(r_0) * DoubleLimb::from(inv)) >> Limb::WIDTH, )) { q_1.wrapping_add_assign(1); } assert!(r_1 <= 4); for _ in 0..r_1 { if r_0.overflowing_add_assign(inv) { q_1.wrapping_add_assign(1); } } (q_1, r_0) } // [x_0, x_1] cannot be equal to `2 ^ (2 * WIDTH - 1)`. // // This is mpfr_div_2 from div.c, MPFR 4.3.0, where Q0 and Q1 are returned, specialized for // reciprocation. fn reciprocal_float_significand_same_prec_gt_w_lt_2w( x_0: Limb, x_1: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, bool, Ordering) { let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; assert!(LIMB_HIGH_BIT < x_1 || (LIMB_HIGH_BIT == x_1 && x_0 != 0)); let (mut q_1, mut q_0) = reciprocal_float_2_approx(x_1, x_0); // We know q1 * B + q0 is smaller or equal to the exact reciprocal, with difference at most 21. let mut sticky_bit = if (q_0.wrapping_add(21)) & (mask >> 1) > 21 { // The result is not exact when we can round with an approximation. 1 } else { // We know q_1 : q_0 is a good-enough approximation, so use it! // // Since we know the difference should be at most 21 * (x_1 : x_0) after the subtraction // below, thus at most 21 * 2 ^ 128, it suffices to compute the lower 3 limbs of (q_1 : q_0) // * (x_1 : x_0). let (mut s_1, mut s_0) = Limb::x_mul_y_to_zz(q_0, x_0); let (mut s_2, mut lo) = Limb::x_mul_y_to_zz(q_0, x_1); if s_1.overflowing_add_assign(lo) { s_2.wrapping_add_assign(1); } let hi; (hi, lo) = Limb::x_mul_y_to_zz(q_1, x_0); s_2.wrapping_add_assign(hi); if s_1.overflowing_add_assign(lo) { s_2.wrapping_add_assign(1); } s_2.wrapping_add_assign(q_1.wrapping_mul(x_1)); // Subtract s_2 : s_1 : s_0 from 0 : 0 : 0, with result in s_2 : s_1 : s_0. s_2.wrapping_neg_assign(); // Now negate s_1 : s_0. s_1.wrapping_neg_assign(); if s_0.overflowing_neg_assign() { s_1.wrapping_sub_assign(1); } // There is a borrow in s_2 when s_0 and s_1 are not both zero. if s_1 != 0 || s_0 != 0 { s_2.wrapping_sub_assign(1); } while s_2 > 0 || s_1 > x_1 || s_1 == x_1 && s_0 >= x_0 { // Add 1 to q_1 : q_0. if q_0.overflowing_add_assign(1) { q_1.wrapping_add_assign(1); } // Subtract x_1 : x_0 to s_2 : s_1 : s_0 if s_1 < x_1 || s_1 == x_1 && s_0 < x_0 { s_2.wrapping_sub_assign(1); } (s_1, s_0) = Limb::xx_sub_yy_to_zz(s_1, s_0, x_1, x_0); } s_1 | s_0 }; let round_bit = q_0 & (shift_bit >> 1); sticky_bit |= (q_0 & mask) ^ round_bit; let mut z_1 = q_1; let mut z_0 = q_0 & !mask; match rm { Exact => panic!("Inexact float reciprocation"), Nearest => { if round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0 { (z_0, z_1, false, Less) } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, false, Greater) } } Floor | Down => (z_0, z_1, false, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, false, Greater) } } } } // This is mpfr_div_ui from div_ui.c, MPFR 4.3.0, specialized for reciprocation. fn reciprocal_float_significand_short( y: Limb, prec: u64, rm: RoundingMode, ) -> (Vec, u64, Ordering) { let out_len = bit_to_limb_count_ceiling(prec); let mut out = vec![0; out_len + 1]; let (exp_offset, o) = reciprocal_float_significand_short_to_out(&mut out, y, prec, rm); out.truncate(out_len); (out, exp_offset, o) } fn limbs_reciprocal_limb_to_out_mod_with_fraction( out: &mut [Limb], fraction_len: usize, d: Limb, ) -> Limb { assert_ne!(d, 0); let len = fraction_len.checked_add(1).unwrap(); assert_ne!(len, 0); let out = &mut out[..len]; assert!(d.get_highest_bit()); let (out_last, out_init) = out.split_last_mut().unwrap(); *out_last = 0; // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); let mut r = LIMB_HIGH_BIT; for out_q in out_init[..fraction_len].iter_mut().rev() { (*out_q, r) = div_mod_by_preinversion(r, 0, d, d_inv); } r } // y cannot be a power of 2. // // This is mpfr_div_ui from div_ui.c, MPFR 4.3.0, specialized for reciprocation. fn reciprocal_float_significand_short_to_out( out: &mut [Limb], y: Limb, prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { let diff = out.len().abs_diff(1); // We need to store out_len + 1 = 1 + diff limbs of the reciprocal. used the entire dividend // // X = ({scratch, 1 + diff} * y + c) * B ^ (-diff} = ({scratch, out_len + 1} * y + c) * B ^ // (-dif) let c = limbs_reciprocal_limb_to_out_mod_with_fraction(out, diff, y); // Let r = {xp, -diff} / B ^ (-diff) if diff < 0, r = 0 otherwise; 0 <= r < 1. // // Then X = ({scratch, out_len + 1} * y + c + r) * B ^ (-dif). x / y = (X / y) * B ^ (-1) * 2 ^ // exp = ({scratch, out_len + 1} + (c + r) / y) * B ^ (-(out_len + 1)) * 2 ^ exp where 0 <= (c + // r) / y < 1. // // sticky_bit != 0 iff r != 0 // // If the highest limb of the result is 0 (xs[0] < y), remove it. Otherwise, compute the left // shift to be performed to normalize. In the latter case, we discard some low bits computed. // They contain information useful for the rounding, hence the updating of middle and inexact. let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; let out_head = out[0]; // round bit is 1 iff (c + r) / u >= 1/2 let (mut exp_offset, round_bit, sticky_bit) = if shift == 0 { // In this case scratch[out_len] = 0 and shift = 0, the round bit is not in {scratch, // out_len + 1}. It is 1 iff 2 * (c + r) - y >= 0. This means that in some cases, we should // look at the most significant bit of r. if c >= y - c { // i.e. 2 * c >= y: round bit is always 1 // // The sticky bit is 1 unless 2 * c - y = 0 and r = 0. (0, 1, (c << 1).wrapping_sub(y)) } else { // 2 * c < y // // The round bit is 1 iff r >= 1 / 2 and 2 * (c + 1 / 2) = y. // // If round_bit is set, we need to recompute sticky_bit, since it might have taken into // account the most-significant bit of xs[-diff - 1]. (0, 0, c) } } else { // round bit is in scratch[0] ( 0, out_head & (shift_bit >> 1), (out_head & (shift_mask >> 1)) | c, ) }; // Clear the lowest `shift` bits out[0] &= !shift_mask; let (_, out) = out.split_last_mut().unwrap(); match rm { Exact => panic!("Inexact float reciprocation"), Nearest => { if round_bit == 0 || sticky_bit == 0 && out[0] & shift_bit == 0 { (exp_offset, Less) } else { if limbs_slice_add_limb_in_place(out, shift_bit) { exp_offset += 1; *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } Floor | Down => (exp_offset, Less), Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { exp_offset += 1; *out.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } } #[inline] fn reciprocal_float_significand_general( ys: &mut [Limb], prec: u64, rm: RoundingMode, ) -> (Vec, u64, Ordering) { let mut out = vec![0; bit_to_limb_count_ceiling(prec)]; let (exp_offset, o) = reciprocal_float_significand_general_to_out(&mut out, ys, prec, rm); (out, exp_offset, o) } // TODO special case qs == ds // // This is mpfr_div from div.c, MPFR 4.2.0, skipping over various special cases, specialized for // reciprocation. fn reciprocal_float_significand_general_to_out( qs: &mut [Limb], ds: &mut [Limb], prec: u64, rm: RoundingMode, ) -> (u64, Ordering) { let ds_len = ds.len(); let qs_len = bit_to_limb_count_ceiling(prec); let qs = &mut qs[..qs_len]; // Determine if an extra bit comes from the division, i.e. if the significand of X (as a // fraction in [1/2, 1) ) is larger than that of Y let ds_last = *ds.last().unwrap(); let extra_bit = if ds_last == LIMB_HIGH_BIT { // k = 0: no more dividend limb slice_test_zero(&ds[..ds_len - 1]) } else { LIMB_HIGH_BIT > ds_last }; let mut exp_offset = u64::from(extra_bit); // shift is the number of zero bits in the low limb of the reciprocal let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let mut shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; let mut ys_vec; let mut ys: &mut [Limb]; // We first try Mulders' short division (for large operands) if qs_len >= MPFR_DIV_THRESHOLD && ds_len >= MPFR_DIV_THRESHOLD { // We will perform a short (2 * n) / n division let n = qs_len + 1; let two_n = n << 1; // since Mulders' short division clobbers the dividend, we have to copy it let mut xs = vec![0; two_n]; // zero-pad the dividend *xs.last_mut().unwrap() = LIMB_HIGH_BIT; if ds_len >= n { // truncate the divisor ys = &mut ds[ds_len - n..]; } else { // zero-pad the divisor ys_vec = vec![0; n]; ys = &mut ys_vec; ys[n - ds_len..].copy_from_slice(ds); } // Since n = qs_len + 1, we have n >= 2 here. let mut scratch = vec![0; n + limbs_float_div_high_scratch_len(n)]; let (qs_2, scratch) = scratch.split_at_mut(n); let q_high = limbs_float_div_high(qs_2, &mut xs, &ys[..n], scratch); // In all cases, the error is at most (2 * n + 2) ulps on q_high * B ^ n + {qs_2, n}. // // If rm == Nearest, we need to be able to round with a directed rounding and one more bit. if q_high { let qs_2_lo = &mut qs_2[..n]; limbs_slice_shr_in_place(qs_2_lo, 1); *qs_2_lo.last_mut().unwrap() |= LIMB_HIGH_BIT; // round_helper_2 would always return false, so no need to call it } } // Mulders' short division failed: we revert to integer division let mut qs_2_vec = vec![]; let mut qs_2: &mut [Limb] = if rm == Nearest && shift == 0 { // We compute the reciprocal with one more limb, in order to get the round bit in the // reciprocal, and the remainder only contains sticky bits. Need to allocate memory for the // reciprocal qs_2_vec = vec![0; qs_len + 1]; &mut qs_2_vec } else { qs // directly put the reciprocal in the destination }; let qs_2_len = qs_2.len(); let two_qs_2_len = qs_2_len << 1; // prepare the dividend let mut xs = vec![0; two_qs_2_len]; // use the full dividend xs[two_qs_2_len - 1] = if extra_bit { LIMB_HIGH_BIT >> 1 } else { LIMB_HIGH_BIT }; // Prepare the divisor let (mut k, sticky_y) = if ds_len >= qs_2_len { let k = ds_len - qs_2_len; let sy = !slice_test_zero(&ds[..k]); ys = &mut ds[k..]; // avoid copying the divisor (0, sy) } else { // ds_len < qs_2_len: small divisor case ys = ds; (qs_2_len - ds_len, false) }; // If Mulders' short division failed, we revert to division with remainder. let mut q_high = limbs_div_helper(qs_2, &mut xs[k..], &ys[..qs_2_len - k]); k = qs_2_len; let sticky_x = !slice_test_zero(&xs[..k]); let mut sticky_bit = Limb::from(sticky_x | sticky_y); // now sticky_bit is non-zero iff one of the following holds: // - the truncated part of u is non-zero // - the truncated part of v is non-zero // - the remainder from division is non-zero let (mut sticky_3, shift_2) = if qs_2_len == qs_len { // does nothing when shift = 0 (qs_2[0] & shift_mask, shift) } else { // qs_2_len = qs_len + 1: only happens when rm == Nearest and shift = 0 qs.copy_from_slice(&qs_2_vec[1..=qs_len]); qs_2 = &mut qs_2_vec; (qs_2[0], Limb::WIDTH) }; qs_2[0] ^= sticky_3; // sticky_3 contains the truncated bits from the reciprocal, including the round bit, and 1 <= // shift_2 <= WIDTH is the number of bits in sticky_3 to round, we distinguish two cases: // - ds_len <= qs_2_len: we used the full divisor // - ds_len > qs_2_len: the divisor was truncated let mut inex = Greater; let mut round_bit = 0; let mut cleanup = Cleanup::None; if ds_len <= qs_2_len { // use the full divisor sticky_bit = if rm == Nearest { round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); (sticky_3 ^ round_bit) | Limb::from(sticky_x) } else if rm == Exact { panic!("Inexact float reciprocation"); } else { 1 }; } else { // ds_len > qs_2_len: need to truncate the divisor // // We know the estimated reciprocal is an upper bound of the exact reciprocal (with rounding // toward zero), with a difference of at most 2 in qs_2[0]. Thus we can round except when // sticky_3 is 000...000 or 000...001 for directed rounding, and 100...000 or 100...001 for // rounding to nearest. (For rounding to nearest, we cannot determine the inexact flag for // 000...000 or 000...001.) let sticky_3_orig = sticky_3; if rm == Nearest { round_bit = sticky_3 & Limb::power_of_2(shift_2 - 1); sticky_3 ^= round_bit; } if sticky_3 > 1 { sticky_bit = sticky_3; } else { // hard case: we have to compare q1 * v0 and r + u0, where q1 * v0 has qs_2_len + // (ds_len-qs_2_len) = ds_len limbs, and r + u0 has qs_2_len + (usize-2*qs_2_len) = // usize-qs_2_len limbs let k = ds_len - qs_2_len; // sp <- {qs_2, qs_2_len} * {ds, ds_len - qs_2_len} let mut scratch = vec![0; ds_len + limbs_mul_to_out_scratch_len(qs_2_len, k)]; let (sp, scratch) = scratch.split_at_mut(ds_len); qs_2[0] ^= sticky_3_orig; // restore original reciprocal let ds_lo = &ds[..k]; limbs_mul_to_out(sp, qs_2, ds_lo, scratch); let q_high_2 = if q_high { limbs_slice_add_same_length_in_place_left(&mut sp[qs_2_len..], ds_lo) } else { false }; qs_2[0] ^= sticky_3_orig; // restore truncated reciprocal // // Compare q_high_2 + {sp, ds_len} to {xs, qs_2_len} + u0 let (sp_lo, sp_hi) = sp.split_at_mut(k); let mut cmp_s_r = if q_high_2 { Greater } else { limbs_cmp_same_length(sp_hi, &xs[..qs_2_len]) }; if cmp_s_r == Equal { // compare {sp, k} and u0 cmp_s_r = if slice_test_zero(sp_lo) { Equal } else { Greater }; } // now // - cmp_s_r > 0 if {sp, ds_len} > {xs, qs_2_len} + u0 // - cmp_s_r = 0 if {sp, ds_len} = {xs, qs_2_len} + u0 // - cmp_s_r < 0 if {sp, ds_len} < {xs, qs_2_len} + u0 if cmp_s_r <= Equal { // reciprocal is in [q1, q1+1) sticky_bit = if cmp_s_r == Equal { sticky_3 } else { 1 }; } else { // cmp_s_r > 0, reciprocal is < q1: to determine if it is in [q1 - 2, q1 - 1] or in // [q1 - 1, q1], we need to subtract the low part u0 of the dividend from q*v0 // subtract u0 >> extra_bit if non-zero if q_high_2 { // whatever the value of {ns, m + k}, it will be smaller than q_high_2 + {sp, k} cmp_s_r = Greater; } else { // subtract r limbs_sub_same_length_in_place_left(sp_hi, &xs[..qs_2_len]); // now compare {sp, ds_len} to y cmp_s_r = limbs_cmp_same_length(sp, ds); } if cmp_s_r <= Equal { // q1 - 1 <= x / y < q1 if sticky_3 == 1 { // q1 - 1 is either representable (directed rounding), or the middle of two // numbers (nearest) sticky_bit = Limb::from(cmp_s_r != Equal); } else if round_bit == 0 { // round_bit=0, sticky_3=0: q1 - 1 is exact only when sh=0 inex = if cmp_s_r != Equal || shift != 0 { Less } else { Equal }; cleanup = if rm == Nearest || ((rm == Ceiling || rm == Up) && inex != Equal) { inex = Greater; Cleanup::TruncateCheckQHigh } else if inex != Equal && rm == Exact { panic!("Inexact float reciprocation"); } else { Cleanup::Sub1Ulp }; } else { // sticky_3 = 0, round_bit = 1 ==> rounding to nearest return (exp_offset, cmp_s_r); } } else { // q1 - 2 < x / y < q1 - 1 // // if rm == Nearest, the result is q1 when q1 - 2 >= q1 - 2 ^ (shift - 1), i.e. // shift >= 2, otherwise (shift = 1) it is q1 - 2 (inex, cleanup) = if rm == Exact { panic!("Inexact float reciprocation"); } else if rm == Nearest { // shift > 0 // // Case shift = 1: sticky_bit = 0 always, and q1 - round_bit is exactly // representable, like q1 - round_bit - 2. // ``` // round_bit action // 0 subtract two ulps, inex = Less // 1 truncate, inex = Greater // ``` // // Case shift > 1: one ulp is 2 ^ (shift - 1) >= 2 // ``` // round_bit sticky_bit action // 0 0 truncate, inex = Greater // 0 1 truncate, inex = Greater // 1 x truncate, inex = Less // ``` if shift == 1 { if round_bit == 0 { shift_bit = 1; (Less, Cleanup::Sub2Ulp) } else { (Greater, Cleanup::TruncateCheckQHigh) } } else { ( if round_bit == 0 { Greater } else { Less }, Cleanup::TruncateCheckQHigh, ) } } else if rm == Floor || rm == Down { // The result is down(q1 - 2), i.e. subtract one ulp if shift > 0, and two // ulps if shift = 0 ( Less, if shift == 0 { Cleanup::Sub2Ulp } else { Cleanup::Sub1Ulp }, ) } else { ( Greater, if shift == 0 { Cleanup::Sub1Ulp } else { Cleanup::TruncateCheckQHigh }, ) }; } } } } match cleanup { Cleanup::None => { // reciprocal is in [q1, q1 + 1), round_bit is the round_bit (0 for directed rounding) return if rm == Floor || rm == Down || round_bit == 0 && sticky_bit == 0 { ( exp_offset, if round_bit == 0 && sticky_bit == 0 { Equal } else { Less }, ) } else if rm == Exact { panic!("Inexact float reciprocation"); } else if rm == Nearest { // sticky_bit != 0 or round != 0 if round_bit == 0 { // necessarily sticky_bit != 0 (exp_offset, Less) } else if sticky_bit != 0 { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } else { fail_on_untested_path( "div_float_significands_long_by_short, round_bit != 0 && sticky_bit != 0", ); // round_bit = 1, sticky_bit = 0 if qs[0] & shift_bit == 0 { (exp_offset, Less) } else { if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) } } } else { // round away from zero, sticky_bit != 0 if limbs_slice_add_limb_in_place(qs, shift_bit) { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, Greater) }; } Cleanup::Sub1Ulp => { // we cannot subtract 1 << (shift + 1), since this is undefined for shift = WIDTH if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } } Cleanup::Sub2Ulp => { if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } if limbs_sub_limb_in_place(qs, shift_bit) { q_high = false; } } _ => {} } if q_high { exp_offset += 1; // else qexp is now incorrect, but one will still get an overflow *qs.last_mut().unwrap() = LIMB_HIGH_BIT; } (exp_offset, inex) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_reciprocal_sqrt.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright 2008-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::arithmetic::add::{ limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::arithmetic::sub::{limbs_sub_greater_in_place_left, limbs_sub_limb_in_place}; use crate::natural::logic::not::{limbs_not_in_place, limbs_not_to_out}; use crate::natural::{ LIMB_HIGH_BIT, bit_to_limb_count_ceiling, bit_to_limb_count_floor, limb_to_bit_count, }; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{PowerOf2, Square, XMulYToZZ}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; // the following T1 and T2 are bipartite tables giving initial approximation for the inverse square // root, with 13-bit input split in 5 + 4 + 4, and 11-bit output. More precisely, if 2048 <= i < // 8192, with i = a * 2 ^ 8 + b * 2 ^ 4 + c, we use for approximation of 2048 / sqrt(i / 2048) the // value x = T1[16 * (a - 8) + b] + T2[16 * (a - 8) + c]. The largest error is obtained for i = // 2054, where x = 2044, and 2048 / sqrt(i / 2048) = 2045.006576... // // This is T1 from rec_sqrt.c, MPFR 4.3.0. const T1: [u16; 384] = [ 2040, 2033, 2025, 2017, 2009, 2002, 1994, 1987, 1980, 1972, 1965, 1958, 1951, 1944, 1938, 1931, 1925, 1918, 1912, 1905, 1899, 1892, 1886, 1880, 1874, 1867, 1861, 1855, 1849, 1844, 1838, 1832, 1827, 1821, 1815, 1810, 1804, 1799, 1793, 1788, 1783, 1777, 1772, 1767, 1762, 1757, 1752, 1747, 1742, 1737, 1733, 1728, 1723, 1718, 1713, 1709, 1704, 1699, 1695, 1690, 1686, 1681, 1677, 1673, 1669, 1664, 1660, 1656, 1652, 1647, 1643, 1639, 1635, 1631, 1627, 1623, 1619, 1615, 1611, 1607, 1603, 1600, 1596, 1592, 1588, 1585, 1581, 1577, 1574, 1570, 1566, 1563, 1559, 1556, 1552, 1549, 1545, 1542, 1538, 1535, 1532, 1528, 1525, 1522, 1518, 1515, 1512, 1509, 1505, 1502, 1499, 1496, 1493, 1490, 1487, 1484, 1481, 1478, 1475, 1472, 1469, 1466, 1463, 1460, 1457, 1454, 1451, 1449, 1446, 1443, 1440, 1438, 1435, 1432, 1429, 1427, 1424, 1421, 1419, 1416, 1413, 1411, 1408, 1405, 1403, 1400, 1398, 1395, 1393, 1390, 1388, 1385, 1383, 1380, 1378, 1375, 1373, 1371, 1368, 1366, 1363, 1360, 1358, 1356, 1353, 1351, 1349, 1346, 1344, 1342, 1340, 1337, 1335, 1333, 1331, 1329, 1327, 1325, 1323, 1321, 1319, 1316, 1314, 1312, 1310, 1308, 1306, 1304, 1302, 1300, 1298, 1296, 1294, 1292, 1290, 1288, 1286, 1284, 1282, 1280, 1278, 1276, 1274, 1272, 1270, 1268, 1266, 1265, 1263, 1261, 1259, 1257, 1255, 1253, 1251, 1250, 1248, 1246, 1244, 1242, 1241, 1239, 1237, 1235, 1234, 1232, 1230, 1229, 1227, 1225, 1223, 1222, 1220, 1218, 1217, 1215, 1213, 1212, 1210, 1208, 1206, 1204, 1203, 1201, 1199, 1198, 1196, 1195, 1193, 1191, 1190, 1188, 1187, 1185, 1184, 1182, 1181, 1180, 1178, 1177, 1175, 1174, 1172, 1171, 1169, 1168, 1166, 1165, 1163, 1162, 1160, 1159, 1157, 1156, 1154, 1153, 1151, 1150, 1149, 1147, 1146, 1144, 1143, 1142, 1140, 1139, 1137, 1136, 1135, 1133, 1132, 1131, 1129, 1128, 1127, 1125, 1124, 1123, 1121, 1120, 1119, 1117, 1116, 1115, 1114, 1113, 1111, 1110, 1109, 1108, 1106, 1105, 1104, 1103, 1101, 1100, 1099, 1098, 1096, 1095, 1093, 1092, 1091, 1090, 1089, 1087, 1086, 1085, 1084, 1083, 1081, 1080, 1079, 1078, 1077, 1076, 1075, 1073, 1072, 1071, 1070, 1069, 1068, 1067, 1065, 1064, 1063, 1062, 1061, 1060, 1059, 1058, 1057, 1056, 1055, 1054, 1052, 1051, 1050, 1049, 1048, 1047, 1046, 1045, 1044, 1043, 1042, 1041, 1040, 1039, 1038, 1037, 1036, 1035, 1034, 1033, 1032, 1031, 1030, 1029, 1028, 1027, 1026, 1025, ]; // This is T2 from rec_sqrt.c, MPFR 4.3.0. const T2: [u8; 384] = [ 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 2, 2, 1, 1, 0, 6, 5, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 0, 0, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; // Put in X a p-bit approximation of 1/sqrt(A), where X = {x, n} / B ^ n, n = ceil(p / Limb::WIDTH), // A = 2 ^ (1 + a_s) * {a, an} / B ^ an, a_s is 0 or 1, an = ceil(ap / Limb::WIDTH), where B = 2 ^ // Limb::WIDTH. // // We have 1 <= A < 4 and 1/2 <= X < 1. // // The error in the approximate result with respect to the true value 1/sqrt(A) is bounded by 1 // ulp(X), i.e., 2^{-p} since 1/2 <= X < 1. // // Note: x and a are left-aligned, i.e., the most significant bit of a[an-1] is set, and so is the // most significant bit of the output x[n-1]. // // If p is not a multiple of Limb::WIDTH, the extra low bits of the input A are taken into account // to compute the approximation of 1/sqrt(A), but whether or not they are zero, the error between X // and 1/sqrt(A) is bounded by 1 ulp(X) [in precision p]. The extra low bits of the output X (if p // is not a multiple of Limb::WIDTH) are set to 0. // // Assumptions: // - A should be normalized, i.e., the most significant bit of a[an-1] should be 1. If a_s = 0, we // have 1 <= A < 2; if a_s = 1, we have 2 <= A < 4. // - p >= 12 // - {a, an} and {x, n} should not overlap // - Limb::WIDTH >= 12 and is even // // Note: this routine is much more efficient when ap is small compared to p, including the case // where ap <= Limb::WIDTH, thus it can be used to implement an efficient mpfr_rec_sqrt_ui function. // // References: [1] Modern Computer Algebra, Richard Brent and Paul Zimmermann, // https://members.loria.fr/PZimmermann/mca/pub226.html // // This is mpfr_mpn_rec_sqrt from rec_sqrt.c, MPFR 4.3.0. pub fn limbs_reciprocal_sqrt( out: &mut [Limb], out_prec: u64, mut xs: &[Limb], x_prec: u64, parity: bool, ) { let out_len = bit_to_limb_count_ceiling(out_prec); let out = &mut out[..out_len]; let mut xs_len = bit_to_limb_count_ceiling(x_prec); // A should be normalized assert!(xs[xs_len - 1].get_highest_bit()); assert!(out_prec >= 11); if xs_len > out_len { // we can cut the input to n limbs xs = &xs[xs_len - out_len..]; xs_len = out_len; } if out_prec == 11 { // should happen only from recursive calls // // take the 12 + a_s most significant bits of A let i = usize::exact_from(xs[xs_len - 1] >> (const { Limb::WIDTH - 12 } - u64::from(parity))); let ab = i >> 4; let ac = (ab & 0x3f0) | (i & 0xf); let t = T1[ab - 0x80] + u16::from(T2[ac - 0x80]); // fits on 16 bits // x has only one limb out[0] = Limb::from(t) << (Limb::WIDTH - out_prec); } else { // p >= 12 // // compared to Algorithm 3.9 of [1], we have {a, an} = A / 2 if a_s = 0, and A / 4 if a_s = // 1. // // h = max(11, ceil((p + 3) / 2)) is the bitsize of the recursive call let h = if out_prec < 18 { 11 } else { (out_prec >> 1) + 2 }; // limb size of the recursive Xh let xs_rec_len = bit_to_limb_count_ceiling(h); // a priori limb size of Xh^2 let rn = bit_to_limb_count_ceiling(h << 1); let ln = out_len - xs_rec_len; // remaining limbs to be computed // Since |Xh - A ^ {-1 / 2}| <= 2 ^ {-h}, then by multiplying by Xh + A ^ {-1 / 2} we get // |Xh ^ 2 - 1 / A| <= 2 ^ {-h + 1}, thus |A * Xh ^ 2 - 1| <= 2 ^ {-h + 3}, thus the h-3 // most significant bits of t should be zero, which is in fact h + 1 + a_s - 3 because of // the normalization of A. This corresponds to th=floor((h + 1 + a_s - 3) / Limb::WIDTH) // limbs. // // More precisely we have |Xh ^ 2 - 1 / A| <= 2^{-h} * (Xh + A^{-1 / 2}) <= 2^{-h} * (2 // A^{-1 / 2} + 2^{-h}) <= 2.001 * 2^{-h} * A^{-1 / 2} since A < 4 and h >= 11, thus |A * Xh // ^ 2 - 1| <= 2.001 * 2^{-h} * A^{1 / 2} <= 1.001 * 2 ^ {2 - h}. This is sufficient to // prove that the upper limb of {t,tn} below is less that 0.501 * 2 ^ Limb::WIDTH, thus cu = // 0 below. let hp = h + 1 + u64::from(parity); let th = bit_to_limb_count_floor(hp - 3); let mut ts_len = bit_to_limb_count_ceiling(hp + h); // we need h + 1 + a_s bits of a // // number of high limbs of A needed for the recursive call let mut ahn = bit_to_limb_count_ceiling(hp); if ahn > xs_len { ahn = xs_len; } let (out_lo, out_hi) = out.split_at_mut(ln); limbs_reciprocal_sqrt( out_hi, h, &xs[xs_len - ahn..], limb_to_bit_count(ahn), parity, ); // the most h significant bits of X are set, X has ceil(h / Limb::WIDTH) limbs, the low (-h) // % Limb::WIDTH bits are zero // // compared to Algorithm 3.9 of [1], we have {x+ln,xn} = X_h // // first step: square X in r, result is exact let mut us_len = xs_rec_len + (ts_len - th); // We use the same temporary buffer to store r and u: r needs 2*xn limbs where u needs // xn+(tn-th) limbs. Since tn can store at least 2h bits, and th at most h bits, then tn-th // can store at least h bits, thus tn - th >= xn, and reserving the space for u is enough. assert!(xs_rec_len << 1 <= us_len); let sn = xs_len + rn; let mut scratch = vec![0; (us_len << 1) + sn]; split_into_chunks_mut!(scratch, us_len, [us, rs], ss); let mut rs = rs; if h << 1 <= Limb::WIDTH { // xn=rn=1, and since p <= 2h-3, n=1, thus ln = 0 assert_eq!(ln, 0); let cy = out_hi[0] >> const { Limb::WIDTH >> 1 }; rs = &mut rs[1..]; rs[0] = cy.square(); } else if xs_rec_len == 1 { // xn = 1, rn = 2 (rs[1], rs[0]) = Limb::x_mul_y_to_zz(out_hi[0], out_hi[0]); } else { let mut scratch = vec![0; limbs_square_to_out_scratch_len(xs_rec_len)]; limbs_square_to_out(rs, out_hi, &mut scratch); // we have {r, 2 * xn} = X_h ^ 2 if rn < xs_rec_len << 1 { rs = &mut rs[1..]; } } // now the 2h most significant bits of {r, rn} contains X ^ 2, r has rn limbs, and the low // (-2h) % Limb::WIDTH bits are zero // // Second step: s <- A * (r ^ 2), and truncate the low ap bits, i.e., at weight 2 ^ {-2h} (s // is aligned to the low significant bits) if rn == 1 { // rn=1 implies n=1, since rn*Limb::WIDTH >= 2h, and 2h >= p + 3 // // necessarily p <= Limb::WIDTH-3: we can ignore the two low bits from A // // since n=1, and we ensured an <= n, we also have an=1 assert_eq!(xs_len, 1); (ss[1], ss[0]) = Limb::x_mul_y_to_zz(rs[0], xs[0]); } else { // we have p <= n * Limb::WIDTH 2h <= rn * Limb::WIDTH with p+3 <= 2h <= p+4 thus n <= // rn <= n + 1 assert!(rn <= out_len + 1); // since we ensured an <= n, we have an <= rn assert!(xs_len <= rn); let mut scratch = vec![0; limbs_mul_greater_to_out_scratch_len(rn, xs_len)]; limbs_mul_greater_to_out(ss, &rs[..rn], xs, &mut scratch); // s should be near B ^ sn / 2 ^ (1 + a_s), thus s[sn-1] is either // - 100000... or 011111... if a_s = 0, or // - 010000... or 001111... if a_s = 1. // We ignore the bits of s after the first 2h + 1 + a_s ones. We have {s, rn+an} = A * // X_h ^ 2 / 2 if a_s = 0, A * X_h ^ 2 / 4 if a_s = 1. } // We ignore the bits of s after the first 2h + 1 + a_s ones: s has rn + an limbs, where rn // = LIMBS(2h), an = LIMBS(a), and tn = LIMBS(2h + 1 + a_s). let ts = &mut ss[sn - ts_len..]; // pointer to low limb of the high part of t // the upper h-3 bits of 1 - t should be zero, where 1 corresponds to the most significant // bit of t[tn - 1] if a_s = 0, and to the 2nd most significant bit of t[tn - 1] if a_s = 1 // // compute t <- 1 - t, which is B^tn - {t, tn + 1}, with rounding toward -Inf, i.e., // rounding the input t toward +Inf. We could only modify the low tn - th limbs from t, but // it gives only a small speedup, and would make the code more complex. let bit = if parity { const { LIMB_HIGH_BIT >> 1 } } else { LIMB_HIGH_BIT }; let ts_last = ts.last_mut().unwrap(); let neg = *ts_last & bit; if neg == 0 { // Ax ^ 2 < 1: we have t = th + eps, where 0 <= eps < ulp(th) is the part truncated // above, thus 1 - t rounded to -Inf is 1 - th - ulp(th) // // since the 1 + a_s most significant bits of t are zero, set them to 1 before the // one-complement *ts_last |= LIMB_HIGH_BIT | bit; limbs_not_in_place(ts); // we should add 1 here to get 1-th complement, and subtract 1 for -ulp(th), thus we do // nothing } else { // negative case: we want 1 - t rounded toward -Inf, i.e., th + eps rounded toward +Inf, // which is th + ulp(th): we discard the bit corresponding to 1, and we add 1 to the // least significant bit of t *ts_last ^= neg; limbs_slice_add_limb_in_place(ts, 1); } // we know at least th = floor((h + 1 + a_s - 3) / Limb::WIDTH) of the high limbs of {t, tn} // are zero ts_len -= th; // tn = rn - th, where rn * Limb::WIDTH >= 2 * h and th * Limb::WIDTH <= h + 1 + a_s - 3, // thus tn > 0 assert_ne!(ts_len, 0); // u <- x * t, where {t, tn} contains at least h + 3 bits, and {x, xn} contains h bits, thus // tn >= xn assert!(ts_len >= xs_rec_len); if ts_len == 1 { // necessarily xn = 1 (us[1], us[0]) = Limb::x_mul_y_to_zz(ts[0], out_hi[0]); } else { let mut scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ts_len, xs_rec_len)]; limbs_mul_greater_to_out(us, &ts[..ts_len], out_hi, &mut scratch); } // we have {u, tn+xn} = T_l X_h / 2 if a_s = 0, T_l X_h / 4 if a_s = 1 // // we have already discarded the upper th high limbs of t, thus we only have to consider the // upper n - th limbs of u us_len = out_len - th; // un cannot be zero, since p <= n * Limb::WIDTH, h = ceil((p + 3) / 2) <= (p + 4) / 2, th * // Limb::WIDTH <= h - 1 <= p / 2 + 1, thus (n - th) * Limb::WIDTH >= p / 2 - 1. assert_ne!(us_len, 0); let u_offset = ts_len + xs_rec_len - us_len; // xn + tn - un = xn + (original_tn - th) - (n - th) = xn + original_tn - n = LIMBS(h) + // LIMBS(2h + 1 + a_s) - LIMBS(p) > 0 since 2h >= p + 3 assert_ne!(u_offset, 0); // will allow to access u[-1] below // In case a_s = 0, u contains |x * (1 - Ax ^ 2) / 2|, which is exactly what we need to add // or subtract. In case a_s = 1, u contains |x * (1 - Ax ^ 2) / 4|, thus we need to multiply // u by 2. if parity { // shift on un+1 limbs to get most significant bit of u[-1] into least significant bit // of u[0] limbs_slice_shl_in_place(&mut us[u_offset - 1..u_offset + us_len], 1); } // now {u,un} represents U / 2 from Algorithm 3.9 let shift_bit = Limb::power_of_2(limb_to_bit_count(out_len) - out_prec); // We want that the low pl bits are zero after rounding to nearest, thus we round u to // nearest at bit pl - 1 of u[0] let (us_head, us_tail) = us[u_offset - 1..].split_first_mut().unwrap(); let us_tail = &mut us_tail[..us_len]; let cu = if shift_bit == 1 { // round bit is in u[-1] limbs_slice_add_limb_in_place(us_tail, *us_head >> const { Limb::WIDTH - 1 }) } else { let uu = us_tail[0]; let cu = limbs_slice_add_limb_in_place(us_tail, uu & (shift_bit >> 1)); // mask bits 0..pl - 1 of u[0] us_tail[0] &= !(shift_bit - 1); cu }; assert!(!cu); // We already have filled {x + ln, xn = n - ln}, and we want to add or subtract {u, un} at // position x. // - un = n - th, where th contains <= h + 1 + a_s - 3 <= h - 1 bits // - ln = n - xn, where xn contains >= h bits // - thus un > ln. // Warning: ln might be zero. assert!(us_len > ln); // we can have un = ln + 2, for example with Limb::WIDTH = 32 and p = 62, a_s = 0, then h = // 33, n = 2, th = 0, xn = 2, thus un = 2 and ln = 0. assert!(us_len == ln + 1 || us_len == ln + 2); // the high un-ln limbs of u will overlap the low part of {x+ln,xn}, we need to add or // subtract the overlapping part {u + ln, un - ln} // // Warning! th may be 0, in which case the mpn_add_1 and mpn_sub_1 below (with size = th) // mustn't be used. let mut carry; let (us_lo, us_hi) = us_tail.split_at_mut(ln); if neg == 0 { if ln != 0 { out_lo.copy_from_slice(us_lo); } carry = limbs_slice_add_greater_in_place_left(out_hi, us_hi); // cy is the carry at x + (ln + xn) = x + n } else { // negative case // // subtract {u+ln, un-ln} from {x+ln,un} carry = limbs_sub_greater_in_place_left(out_hi, us_hi); // cy is the borrow at x + (ln + xn) = x + n // // cy cannot be non-zero, since the most significant bit of Xh is 1, and the correction // is bounded by 2^{-h+3} assert!(!carry); if ln != 0 { limbs_not_to_out(out, us_lo); // we must add one for the 2-complement carry = limbs_slice_add_limb_in_place(out, 1); // ... and subtract 1 at x[ln], where n = ln + xn if limbs_sub_limb_in_place(&mut out[ln..], 1) { assert!(carry); carry = false; } } } // cy can be 1 when A=1, i.e., {a, n} = B ^ n. In that case we should have X = B ^ n, and // setting X to 1-2^{-p} satisfies the error bound of 1 ulp. if carry { assert!(limbs_sub_limb_in_place(out, shift_bit)); } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_sqrt.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::natural::arithmetic::sqrt::limbs_sqrt_to_out_return_inexact; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{NegModPowerOf2, Parity, PowerOf2}; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::arithmetic::traits::{ WrappingAddAssign, WrappingSubAssign, XMulYToZZ, XXAddYYToZZ, XXSubYYToZZ, XXXSubYYYToZZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; // For 257 <= d10 <= 1024, T[d10-257] = floor(sqrt(2 ^ 30 / d10)). // // Sage code: // // T = [floor(sqrt(2 ^ 30 / d10)) for d10 in [257..1024]] // // This is T from invsqrt_limb.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] const T: [u16; 768] = [ 2044, 2040, 2036, 2032, 2028, 2024, 2020, 2016, 2012, 2009, 2005, 2001, 1997, 1994, 1990, 1986, 1983, 1979, 1975, 1972, 1968, 1965, 1961, 1958, 1954, 1951, 1947, 1944, 1941, 1937, 1934, 1930, 1927, 1924, 1920, 1917, 1914, 1911, 1907, 1904, 1901, 1898, 1895, 1891, 1888, 1885, 1882, 1879, 1876, 1873, 1870, 1867, 1864, 1861, 1858, 1855, 1852, 1849, 1846, 1843, 1840, 1837, 1834, 1831, 1828, 1826, 1823, 1820, 1817, 1814, 1812, 1809, 1806, 1803, 1801, 1798, 1795, 1792, 1790, 1787, 1784, 1782, 1779, 1777, 1774, 1771, 1769, 1766, 1764, 1761, 1759, 1756, 1754, 1751, 1749, 1746, 1744, 1741, 1739, 1736, 1734, 1731, 1729, 1727, 1724, 1722, 1719, 1717, 1715, 1712, 1710, 1708, 1705, 1703, 1701, 1698, 1696, 1694, 1692, 1689, 1687, 1685, 1683, 1680, 1678, 1676, 1674, 1672, 1670, 1667, 1665, 1663, 1661, 1659, 1657, 1655, 1652, 1650, 1648, 1646, 1644, 1642, 1640, 1638, 1636, 1634, 1632, 1630, 1628, 1626, 1624, 1622, 1620, 1618, 1616, 1614, 1612, 1610, 1608, 1606, 1604, 1602, 1600, 1598, 1597, 1595, 1593, 1591, 1589, 1587, 1585, 1583, 1582, 1580, 1578, 1576, 1574, 1572, 1571, 1569, 1567, 1565, 1563, 1562, 1560, 1558, 1556, 1555, 1553, 1551, 1549, 1548, 1546, 1544, 1542, 1541, 1539, 1537, 1536, 1534, 1532, 1531, 1529, 1527, 1526, 1524, 1522, 1521, 1519, 1517, 1516, 1514, 1513, 1511, 1509, 1508, 1506, 1505, 1503, 1501, 1500, 1498, 1497, 1495, 1494, 1492, 1490, 1489, 1487, 1486, 1484, 1483, 1481, 1480, 1478, 1477, 1475, 1474, 1472, 1471, 1469, 1468, 1466, 1465, 1463, 1462, 1461, 1459, 1458, 1456, 1455, 1453, 1452, 1450, 1449, 1448, 1446, 1445, 1443, 1442, 1441, 1439, 1438, 1436, 1435, 1434, 1432, 1431, 1430, 1428, 1427, 1426, 1424, 1423, 1422, 1420, 1419, 1418, 1416, 1415, 1414, 1412, 1411, 1410, 1408, 1407, 1406, 1404, 1403, 1402, 1401, 1399, 1398, 1397, 1395, 1394, 1393, 1392, 1390, 1389, 1388, 1387, 1385, 1384, 1383, 1382, 1381, 1379, 1378, 1377, 1376, 1374, 1373, 1372, 1371, 1370, 1368, 1367, 1366, 1365, 1364, 1362, 1361, 1360, 1359, 1358, 1357, 1355, 1354, 1353, 1352, 1351, 1350, 1349, 1347, 1346, 1345, 1344, 1343, 1342, 1341, 1339, 1338, 1337, 1336, 1335, 1334, 1333, 1332, 1331, 1330, 1328, 1327, 1326, 1325, 1324, 1323, 1322, 1321, 1320, 1319, 1318, 1317, 1315, 1314, 1313, 1312, 1311, 1310, 1309, 1308, 1307, 1306, 1305, 1304, 1303, 1302, 1301, 1300, 1299, 1298, 1297, 1296, 1295, 1294, 1293, 1292, 1291, 1290, 1289, 1288, 1287, 1286, 1285, 1284, 1283, 1282, 1281, 1280, 1279, 1278, 1277, 1276, 1275, 1274, 1273, 1272, 1271, 1270, 1269, 1268, 1267, 1266, 1265, 1264, 1264, 1263, 1262, 1261, 1260, 1259, 1258, 1257, 1256, 1255, 1254, 1253, 1252, 1252, 1251, 1250, 1249, 1248, 1247, 1246, 1245, 1244, 1243, 1242, 1242, 1241, 1240, 1239, 1238, 1237, 1236, 1235, 1234, 1234, 1233, 1232, 1231, 1230, 1229, 1228, 1228, 1227, 1226, 1225, 1224, 1223, 1222, 1222, 1221, 1220, 1219, 1218, 1217, 1216, 1216, 1215, 1214, 1213, 1212, 1211, 1211, 1210, 1209, 1208, 1207, 1207, 1206, 1205, 1204, 1203, 1202, 1202, 1201, 1200, 1199, 1198, 1198, 1197, 1196, 1195, 1194, 1194, 1193, 1192, 1191, 1190, 1190, 1189, 1188, 1187, 1187, 1186, 1185, 1184, 1183, 1183, 1182, 1181, 1180, 1180, 1179, 1178, 1177, 1177, 1176, 1175, 1174, 1174, 1173, 1172, 1171, 1171, 1170, 1169, 1168, 1168, 1167, 1166, 1165, 1165, 1164, 1163, 1162, 1162, 1161, 1160, 1159, 1159, 1158, 1157, 1157, 1156, 1155, 1154, 1154, 1153, 1152, 1152, 1151, 1150, 1149, 1149, 1148, 1147, 1147, 1146, 1145, 1145, 1144, 1143, 1142, 1142, 1141, 1140, 1140, 1139, 1138, 1138, 1137, 1136, 1136, 1135, 1134, 1133, 1133, 1132, 1131, 1131, 1130, 1129, 1129, 1128, 1127, 1127, 1126, 1125, 1125, 1124, 1123, 1123, 1122, 1121, 1121, 1120, 1119, 1119, 1118, 1118, 1117, 1116, 1116, 1115, 1114, 1114, 1113, 1112, 1112, 1111, 1110, 1110, 1109, 1109, 1108, 1107, 1107, 1106, 1105, 1105, 1104, 1103, 1103, 1102, 1102, 1101, 1100, 1100, 1099, 1099, 1098, 1097, 1097, 1096, 1095, 1095, 1094, 1094, 1093, 1092, 1092, 1091, 1091, 1090, 1089, 1089, 1088, 1088, 1087, 1086, 1086, 1085, 1085, 1084, 1083, 1083, 1082, 1082, 1081, 1080, 1080, 1079, 1079, 1078, 1077, 1077, 1076, 1076, 1075, 1075, 1074, 1073, 1073, 1072, 1072, 1071, 1071, 1070, 1069, 1069, 1068, 1068, 1067, 1067, 1066, 1065, 1065, 1064, 1064, 1063, 1063, 1062, 1062, 1061, 1060, 1060, 1059, 1059, 1058, 1058, 1057, 1057, 1056, 1055, 1055, 1054, 1054, 1053, 1053, 1052, 1052, 1051, 1051, 1050, 1049, 1049, 1048, 1048, 1047, 1047, 1046, 1046, 1045, 1045, 1044, 1044, 1043, 1043, 1042, 1041, 1041, 1040, 1040, 1039, 1039, 1038, 1038, 1037, 1037, 1036, 1036, 1035, 1035, 1034, 1034, 1033, 1033, 1032, 1032, 1031, 1031, 1030, 1030, 1029, 1029, 1028, 1028, 1027, 1027, 1026, 1026, 1025, 1025, 1024, 1024, ]; // table of v0^3 // // This is T from invsqrt_limb.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] const T3: [u64; 768] = [ 8539701184, 8489664000, 8439822656, 8390176768, 8340725952, 8291469824, 8242408000, 8193540096, 8144865728, 8108486729, 8060150125, 8012006001, 7964053973, 7928215784, 7880599000, 7833173256, 7797729087, 7750636739, 7703734375, 7668682048, 7622111232, 7587307125, 7541066681, 7506509912, 7460598664, 7426288351, 7380705123, 7346640384, 7312680621, 7267563953, 7233848504, 7189057000, 7155584983, 7122217024, 7077888000, 7044762213, 7011739944, 6978821031, 6935089643, 6902411264, 6869835701, 6837362792, 6804992375, 6761990971, 6729859072, 6697829125, 6665900968, 6634074439, 6602349376, 6570725617, 6539203000, 6507781363, 6476460544, 6445240381, 6414120712, 6383101375, 6352182208, 6321363049, 6290643736, 6260024107, 6229504000, 6199083253, 6168761704, 6138539191, 6108415552, 6088387976, 6058428767, 6028568000, 5998805513, 5969141144, 5949419328, 5919918129, 5890514616, 5861208627, 5841725401, 5812581592, 5783534875, 5754585088, 5735339000, 5706550403, 5677858304, 5658783768, 5630252139, 5611284433, 5582912824, 5554637011, 5535839609, 5507723096, 5489031744, 5461074081, 5442488479, 5414689216, 5396209064, 5368567751, 5350192749, 5322708936, 5304438784, 5277112021, 5258946419, 5231776256, 5213714904, 5186700891, 5168743489, 5150827583, 5124031424, 5106219048, 5079577959, 5061868813, 5044200875, 5017776128, 5000211000, 4982686912, 4956477625, 4939055927, 4921675101, 4895680392, 4878401536, 4861163384, 4843965888, 4818245769, 4801149703, 4784094125, 4767078987, 4741632000, 4724717752, 4707843776, 4691010024, 4674216448, 4657463000, 4632407963, 4615754625, 4599141247, 4582567781, 4566034179, 4549540393, 4533086375, 4508479808, 4492125000, 4475809792, 4459534136, 4443297984, 4427101288, 4410944000, 4394826072, 4378747456, 4362708104, 4346707968, 4330747000, 4314825152, 4298942376, 4283098624, 4267293848, 4251528000, 4235801032, 4220112896, 4204463544, 4188852928, 4173281000, 4157747712, 4142253016, 4126796864, 4111379208, 4096000000, 4080659192, 4073003173, 4057719875, 4042474857, 4027268071, 4012099469, 3996969003, 3981876625, 3966822287, 3959309368, 3944312000, 3929352552, 3914430976, 3899547224, 3884701248, 3877292411, 3862503009, 3847751263, 3833037125, 3818360547, 3811036328, 3796416000, 3781833112, 3767287616, 3760028875, 3745539377, 3731087151, 3716672149, 3709478592, 3695119336, 3680797184, 3666512088, 3659383421, 3645153819, 3630961153, 3623878656, 3609741304, 3595640768, 3588604291, 3574558889, 3560550183, 3553559576, 3539605824, 3525688648, 3518743761, 3504881359, 3491055413, 3484156096, 3470384744, 3463512697, 3449795831, 3436115229, 3429288512, 3415662216, 3408862625, 3395290527, 3381754501, 3375000000, 3361517992, 3354790473, 3341362375, 3334661784, 3321287488, 3307949000, 3301293169, 3288008303, 3281379256, 3268147904, 3261545587, 3248367641, 3241792000, 3228667352, 3222118333, 3209046875, 3202524424, 3189506048, 3183010111, 3170044709, 3163575232, 3150662696, 3144219625, 3131359847, 3124943128, 3118535181, 3105745579, 3099363912, 3086626816, 3080271375, 3067586677, 3061257408, 3048625000, 3042321849, 3036027392, 3023464536, 3017196125, 3004685307, 2998442888, 2992209121, 2979767519, 2973559672, 2961169856, 2954987875, 2948814504, 2936493568, 2930345991, 2924207000, 2911954752, 2905841483, 2899736776, 2887553024, 2881473967, 2875403448, 2863288000, 2857243059, 2851206632, 2839159296, 2833148375, 2827145944, 2815166528, 2809189531, 2803221000, 2791309312, 2785366143, 2779431416, 2767587264, 2761677827, 2755776808, 2749884201, 2738124199, 2732256792, 2726397773, 2714704875, 2708870984, 2703045457, 2697228288, 2685619000, 2679826869, 2674043072, 2668267603, 2656741625, 2650991104, 2645248887, 2639514968, 2633789341, 2622362939, 2616662152, 2610969633, 2605285376, 2593941624, 2588282117, 2582630848, 2576987811, 2571353000, 2560108032, 2554497863, 2548895896, 2543302125, 2537716544, 2526569928, 2521008881, 2515456000, 2509911279, 2504374712, 2498846293, 2487813875, 2482309864, 2476813977, 2471326208, 2465846551, 2460375000, 2454911549, 2444008923, 2438569736, 2433138625, 2427715584, 2422300607, 2416893688, 2411494821, 2400721219, 2395346472, 2389979753, 2384621056, 2379270375, 2373927704, 2368593037, 2363266368, 2357947691, 2352637000, 2342039552, 2336752783, 2331473976, 2326203125, 2320940224, 2315685267, 2310438248, 2305199161, 2299968000, 2294744759, 2289529432, 2284322013, 2273930875, 2268747144, 2263571297, 2258403328, 2253243231, 2248091000, 2242946629, 2237810112, 2232681443, 2227560616, 2222447625, 2217342464, 2212245127, 2207155608, 2202073901, 2197000000, 2191933899, 2186875592, 2181825073, 2176782336, 2171747375, 2166720184, 2161700757, 2156689088, 2151685171, 2146689000, 2141700569, 2136719872, 2131746903, 2126781656, 2121824125, 2116874304, 2111932187, 2106997768, 2102071041, 2097152000, 2092240639, 2087336952, 2082440933, 2077552576, 2072671875, 2067798824, 2062933417, 2058075648, 2053225511, 2048383000, 2043548109, 2038720832, 2033901163, 2029089096, 2024284625, 2019487744, 2019487744, 2014698447, 2009916728, 2005142581, 2000376000, 1995616979, 1990865512, 1986121593, 1981385216, 1976656375, 1971935064, 1967221277, 1962515008, 1962515008, 1957816251, 1953125000, 1948441249, 1943764992, 1939096223, 1934434936, 1929781125, 1925134784, 1920495907, 1915864488, 1915864488, 1911240521, 1906624000, 1902014919, 1897413272, 1892819053, 1888232256, 1883652875, 1879080904, 1879080904, 1874516337, 1869959168, 1865409391, 1860867000, 1856331989, 1851804352, 1851804352, 1847284083, 1842771176, 1838265625, 1833767424, 1829276567, 1824793048, 1824793048, 1820316861, 1815848000, 1811386459, 1806932232, 1802485313, 1798045696, 1798045696, 1793613375, 1789188344, 1784770597, 1780360128, 1775956931, 1775956931, 1771561000, 1767172329, 1762790912, 1758416743, 1758416743, 1754049816, 1749690125, 1745337664, 1740992427, 1736654408, 1736654408, 1732323601, 1728000000, 1723683599, 1719374392, 1719374392, 1715072373, 1710777536, 1706489875, 1702209384, 1702209384, 1697936057, 1693669888, 1689410871, 1685159000, 1685159000, 1680914269, 1676676672, 1672446203, 1672446203, 1668222856, 1664006625, 1659797504, 1655595487, 1655595487, 1651400568, 1647212741, 1643032000, 1643032000, 1638858339, 1634691752, 1630532233, 1630532233, 1626379776, 1622234375, 1618096024, 1618096024, 1613964717, 1609840448, 1605723211, 1605723211, 1601613000, 1597509809, 1593413632, 1593413632, 1589324463, 1585242296, 1581167125, 1581167125, 1577098944, 1573037747, 1568983528, 1568983528, 1564936281, 1560896000, 1556862679, 1556862679, 1552836312, 1548816893, 1548816893, 1544804416, 1540798875, 1536800264, 1536800264, 1532808577, 1528823808, 1528823808, 1524845951, 1520875000, 1516910949, 1516910949, 1512953792, 1509003523, 1509003523, 1505060136, 1501123625, 1501123625, 1497193984, 1493271207, 1489355288, 1489355288, 1485446221, 1481544000, 1481544000, 1477648619, 1473760072, 1473760072, 1469878353, 1466003456, 1466003456, 1462135375, 1458274104, 1454419637, 1454419637, 1450571968, 1446731091, 1446731091, 1442897000, 1439069689, 1439069689, 1435249152, 1431435383, 1431435383, 1427628376, 1423828125, 1423828125, 1420034624, 1416247867, 1416247867, 1412467848, 1408694561, 1408694561, 1404928000, 1401168159, 1401168159, 1397415032, 1397415032, 1393668613, 1389928896, 1389928896, 1386195875, 1382469544, 1382469544, 1378749897, 1375036928, 1375036928, 1371330631, 1367631000, 1367631000, 1363938029, 1363938029, 1360251712, 1356572043, 1356572043, 1352899016, 1349232625, 1349232625, 1345572864, 1341919727, 1341919727, 1338273208, 1338273208, 1334633301, 1331000000, 1331000000, 1327373299, 1327373299, 1323753192, 1320139673, 1320139673, 1316532736, 1312932375, 1312932375, 1309338584, 1309338584, 1305751357, 1302170688, 1302170688, 1298596571, 1298596571, 1295029000, 1291467969, 1291467969, 1287913472, 1287913472, 1284365503, 1280824056, 1280824056, 1277289125, 1277289125, 1273760704, 1270238787, 1270238787, 1266723368, 1266723368, 1263214441, 1259712000, 1259712000, 1256216039, 1256216039, 1252726552, 1249243533, 1249243533, 1245766976, 1245766976, 1242296875, 1242296875, 1238833224, 1235376017, 1235376017, 1231925248, 1231925248, 1228480911, 1228480911, 1225043000, 1221611509, 1221611509, 1218186432, 1218186432, 1214767763, 1214767763, 1211355496, 1207949625, 1207949625, 1204550144, 1204550144, 1201157047, 1201157047, 1197770328, 1197770328, 1194389981, 1191016000, 1191016000, 1187648379, 1187648379, 1184287112, 1184287112, 1180932193, 1180932193, 1177583616, 1174241375, 1174241375, 1170905464, 1170905464, 1167575877, 1167575877, 1164252608, 1164252608, 1160935651, 1160935651, 1157625000, 1154320649, 1154320649, 1151022592, 1151022592, 1147730823, 1147730823, 1144445336, 1144445336, 1141166125, 1141166125, 1137893184, 1137893184, 1134626507, 1134626507, 1131366088, 1128111921, 1128111921, 1124864000, 1124864000, 1121622319, 1121622319, 1118386872, 1118386872, 1115157653, 1115157653, 1111934656, 1111934656, 1108717875, 1108717875, 1105507304, 1105507304, 1102302937, 1102302937, 1099104768, 1099104768, 1095912791, 1095912791, 1092727000, 1092727000, 1089547389, 1089547389, 1086373952, 1086373952, 1083206683, 1083206683, 1080045576, 1080045576, 1076890625, 1076890625, 1073741824, 1073741824, ]; // This is mpfr_sqrt from sqrt.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] pub fn sqrt_float_significand_in_place( x: &mut Natural, x_exp: i32, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { if out_prec == x_prec && let Some((exp, o)) = sqrt_float_significand_in_place_same_prec(x, x_exp, out_prec, rm) { return (exp, o); } let (sqrt, exp, o) = match &*x { Natural(Small(x)) => sqrt_float_significand_ref_helper(&[*x], x_exp, x_prec, out_prec, rm), Natural(Large(xs)) => sqrt_float_significand_ref_helper(xs, x_exp, x_prec, out_prec, rm), }; *x = sqrt; (exp, o) } // This is mpfr_sqrt from sqrt.c, MPFR 4.3.0. #[cfg(feature = "32_bit_limbs")] pub fn sqrt_float_significand_in_place( x: &mut Natural, x_exp: i32, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { let (sqrt, exp, o) = match &*x { Natural(Small(x)) => sqrt_float_significand_ref_helper(&[*x], x_exp, x_prec, out_prec, rm), Natural(Large(xs)) => sqrt_float_significand_ref_helper(xs, x_exp, x_prec, out_prec, rm), }; *x = sqrt; (exp, o) } // This is mpfr_sqrt from sqrt.c, MPFR 4.3.0. pub fn sqrt_float_significand_ref( x: &Natural, x_exp: i32, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { match x { Natural(Small(x)) => sqrt_float_significand_ref_helper(&[*x], x_exp, x_prec, out_prec, rm), Natural(Large(xs)) => sqrt_float_significand_ref_helper(xs, x_exp, x_prec, out_prec, rm), } } #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_ref_helper( xs: &[Limb], x_exp: i32, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { if out_prec == x_prec && let Some(out) = sqrt_float_significand_same_prec_ref(xs, x_exp, x_prec, rm) { return out; } sqrt_float_significands_general(xs, x_exp, out_prec, rm) } #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_in_place_same_prec( x: &mut Natural, x_exp: i32, prec: u64, rm: RoundingMode, ) -> Option<(i32, Ordering)> { match x { Natural(Small(x)) => { let (sqrt, exp, o) = if prec == Limb::WIDTH { sqrt_float_significand_same_prec_w(*x, x_exp, rm) } else { sqrt_float_significand_same_prec_lt_w(*x, x_exp, prec, rm) }; *x = sqrt; Some((exp, o)) } Natural(Large(xs)) => match xs.as_mut_slice() { [x_0, x_1] if prec != const { Limb::WIDTH << 1 } => { let (sqrt_0, sqrt_1, exp, o) = sqrt_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, x_exp, prec, rm); *x_0 = sqrt_0; *x_1 = sqrt_1; Some((exp, o)) } _ => None, }, } } #[cfg(feature = "32_bit_limbs")] #[inline] fn sqrt_float_significand_ref_helper( xs: &[Limb], x_exp: i32, _x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { sqrt_float_significands_general(xs, x_exp, out_prec, rm) } #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_same_prec_ref( xs: &[Limb], x_exp: i32, prec: u64, rm: RoundingMode, ) -> Option<(Natural, i32, Ordering)> { match xs { [x] => { let (sqrt, exp, o) = if prec == Limb::WIDTH { sqrt_float_significand_same_prec_w(*x, x_exp, rm) } else { sqrt_float_significand_same_prec_lt_w(*x, x_exp, prec, rm) }; Some((Natural::from(sqrt), exp, o)) } [x_0, x_1] if prec != const { Limb::WIDTH << 1 } => { let (sqrt_0, sqrt_1, exp, o) = sqrt_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, x_exp, prec, rm); Some((Natural(Large(vec![sqrt_0, sqrt_1])), exp, o)) } _ => None, } } // given 2 ^ 62 <= d < 2 ^ 64, return a 32-bit approximation r of sqrt(2 ^ 126 / d) // // This is __gmpfr_invsqrt_halflimb_approx from invsqrt_limb.c, MPFR 4.3.0, returning r. #[cfg(not(feature = "32_bit_limbs"))] fn half_limb_inverse_sqrt_approx(d: Limb) -> Limb { let i = usize::wrapping_from((d >> 54) - 256); // i = d10 - 256 let v0 = Limb::from(T[i]); let d37 = 1 + (d >> 27); let e0 = T3[i].wrapping_mul(d37); // the value (v0 << 57) - e0 is less than 2 ^ 61 let v1 = (v0 << 11) + ((v0 << 57).wrapping_sub(e0) >> 47); let e1 = v1.wrapping_neg().wrapping_mul(v1).wrapping_mul(d37); let h = Limb::x_mul_y_to_zz(v1, e1).0; // h = floor(e1 * v1 / 2 ^ 64) (v1 << 10) + (h >> 6) } // given 2^62 <= n < 2^64, put in s an approximation of sqrt(2^64*n), with: s <= floor(sqrt(2^64*n)) // <= s + 7 // // This is __gmpfr_sqrt_limb_approx from invsqrt_limb.c, MPFR 4.3.0, returning s. #[cfg(not(feature = "32_bit_limbs"))] fn limb_sqrt_approx(n: Limb) -> Limb { let x = half_limb_inverse_sqrt_approx(n); const LIMIT: u64 = 1 << 32; assert!(x < LIMIT); // x has 32 bits, and is near (by below) sqrt(2 ^ 126 / n) let mut y = (x * (n >> 31)) >> 32; assert!(y < LIMIT); // y is near (by below) sqrt(n) let mut z = n - y * y; // reduce z so that z <= 2 * y // // the maximal value of z is 2 * (2 ^ 32 - 1) while z > const { (LIMIT - 1) << 1 } { z -= (y << 1) + 1; y += 1; } // now z <= 2 * (2 ^ 32 - 1): one reduction is enough let two_y = y << 1; if z > two_y { z -= two_y + 1; y += 1; } // x * z should be < 2 ^ 64 (y << 32) + ((x * z) >> 32) } // Special code for prec(r) = prec(u) < Limb::WIDTH. We cannot have prec(u) = Limb::WIDTH here, // since when the exponent of u is odd, we need to shift u by one bit to the right without losing // any bit. // // This is mpfr_sqrt1 from sqrt.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_same_prec_lt_w( mut x: Limb, mut x_exp: i32, prec: u64, rm: RoundingMode, ) -> (Limb, i32, Ordering) { let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; if x_exp.odd() { x >>= 1; x_exp += 1; } let mut exp_r = x_exp >> 1; // then compute an approximation of the integer square root of x * 2 ^ Limb::WIDTH let mut r0 = limb_sqrt_approx(x); // when we can round correctly with the approximation, the sticky bit is non-zero let mut sticky_bit = 1; // the exact square root is in [r0, r0 + 7] if r0.wrapping_add(7) & (mask >> 1) <= 7 { // We should ensure r0 has its most significant bit set. Since r0 <= sqrt(2 ^ 64 * x) <= r0 // + 7, as soon as sqrt(2 ^ 64 * x) >= 2 ^ 63 + 7, which happens for x >= 2 ^ 62 + 8, then // r0 >= 2 ^ 63. It thus remains to check that for 2 ^ 62 <= x <= 2 ^ 62 + 7, // __gmpfr_sqrt_limb_approx (r0, x) gives r0 >= 2 ^ 63, which is indeed the case: // // ``` // x = 4611686018427387904 r0 = 9223372036854775808 // x = 4611686018427387905 r0 = 9223372036854775808 // x = 4611686018427387906 r0 = 9223372036854775809 // x = 4611686018427387907 r0 = 9223372036854775810 // x = 4611686018427387908 r0 = 9223372036854775811 // x = 4611686018427387909 r0 = 9223372036854775812 // x = 4611686018427387910 r0 = 9223372036854775813 // x = 4611686018427387911 r0 = 9223372036854775814 // ``` assert!(r0.get_highest_bit()); let mut round_bit; (round_bit, sticky_bit) = Limb::x_mul_y_to_zz(r0, r0); (round_bit, sticky_bit) = Limb::xx_sub_yy_to_zz(x, 0, round_bit, sticky_bit); // for the exact square root, we should have 0 <= round_bit:sticky_bit <= 2*r0 while round_bit != 0 && (round_bit != 1 || sticky_bit > r0 << 1) { // subtract 2 * r0 + 1 from round_bit:sticky_bit: subtract r0 before incrementing r0, // then r0 after (which is r0 + 1) if sticky_bit < r0 { round_bit.wrapping_sub_assign(1); } sticky_bit.wrapping_sub_assign(r0); r0 += 1; if sticky_bit < r0 { round_bit.wrapping_sub_assign(1); } sticky_bit.wrapping_sub_assign(r0); } // now we should have round_bit * 2 ^ 64 + sticky_bit <= 2 * r0 assert!(round_bit == 0 || (round_bit == 1 && sticky_bit <= r0 << 1)); sticky_bit |= round_bit; } let round_bit = r0 & (shift_bit >> 1); sticky_bit |= (r0 & mask) ^ round_bit; r0 &= !mask; // rounding: sticky_bit = 0 implies round_bit = 0, since (round_bit, sticky_bit) = (1, 0) is not // possible if sticky_bit == 0 { assert_eq!(round_bit, 0); return (r0, exp_r, Equal); } match rm { Floor | Down => (r0, exp_r, Less), Ceiling | Up => { r0.wrapping_add_assign(shift_bit); if r0 == 0 { r0 = LIMB_HIGH_BIT; exp_r += 1; } (r0, exp_r, Greater) } Nearest => { // since sticky_bit != 0, only round_bit is needed to decide how to round, and the exact // middle is not possible if round_bit == 0 { (r0, exp_r, Less) } else { r0.wrapping_add_assign(shift_bit); if r0 == 0 { r0 = LIMB_HIGH_BIT; exp_r += 1; } (r0, exp_r, Greater) } } Exact => panic!("Inexact float square root"), } } // This is mpfr_sqrt1n from sqrt.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_same_prec_w( mut x: Limb, mut x_exp: i32, rm: RoundingMode, ) -> (Limb, i32, Ordering) { let low = if x_exp.odd() { let low = x << (Limb::WIDTH - 1); x >>= 1; x_exp += 1; low } else { 0 }; let mut exp_r = x_exp >> 1; // then compute an approximation of the integer square root of x*2 ^ Limb::WIDTH let mut r0 = limb_sqrt_approx(x); // the exact square root is in [r0, r0 + 7] // // As shown in sqrt_float_significand_same_prec_lt_w above, r0 has its most significant bit set assert!(r0.get_highest_bit()); let (mut round_bit, mut sticky_bit) = Limb::x_mul_y_to_zz(r0, r0); (round_bit, sticky_bit) = Limb::xx_sub_yy_to_zz(x, low, round_bit, sticky_bit); // for the exact square root, we should have 0 <= round_bit:sticky_bit <= 2*r0 while round_bit != 0 && (round_bit != 1 || sticky_bit > r0 << 1) { // subtract 2 * r0 + 1 from round_bit:sticky_bit: subtract r0 before incrementing r0, then // r0 after (which is r0 + 1) if sticky_bit < r0 { round_bit -= 1; } sticky_bit.wrapping_sub_assign(r0); r0 += 1; if sticky_bit < r0 { round_bit -= 1; } sticky_bit.wrapping_sub_assign(r0); } // now we have x * 2 ^ 64 + low = r0 ^ 2 + round_bit * 2 ^ 64 + sticky_bit, with round_bit * 2 ^ // 64 + sticky_bit <= 2 * r0 // // We can't have the middle case x * 2 ^ 64 = (r0 + 1 / 2) ^ 2 since (r0 + 1 / 2) ^ 2 is not an // integer. We thus round_bit = 1 whenever x * 2 ^ 64 > (r0 + 1 / 2) ^ 2, thus round_bit * 2 ^ // 64 + sticky_bit > r0 and the sticky bit is always 1, unless we had round_bit = sticky_bit = // 0. if sticky_bit > r0 { round_bit |= 1; } sticky_bit |= round_bit; // sticky_bit = 0 can only occur when the square root is exact, i.e., round_bit = 0 if sticky_bit == 0 { assert_eq!(round_bit, 0); return (r0, exp_r, Equal); } match rm { Floor | Down => (r0, exp_r, Less), Ceiling | Up => { r0.wrapping_add_assign(1); if r0 == 0 { r0 = LIMB_HIGH_BIT; exp_r += 1; } (r0, exp_r, Greater) } Nearest => { // we can't have sticky_bit = 0, thus round_bit is enough if round_bit == 0 { (r0, exp_r, Less) } else { r0.wrapping_add_assign(1); if r0 == 0 { r0 = LIMB_HIGH_BIT; exp_r += 1; } (r0, exp_r, Greater) } } Exact => panic!("Inexact float square root"), } } // given 2^62 <= d < 2^64, return an approximation of s = floor(2^96/sqrt(d)) - 2^64, with r <= s // <= r + 15 // // This is __gmpfr_invsqrt_limb_approx from invsqrt_limb.c, MPFR 4.3.0, returning r. #[cfg(not(feature = "32_bit_limbs"))] fn limb_inverse_sqrt_approx(d: Limb) -> Limb { let i = ((d >> 54) - 256) as usize; // i = d10 - 256 let v0 = Limb::from(T[i]); let d37 = 1 + (d >> 27); let e0 = T3[i].wrapping_mul(d37); // the value (v0 << 57) - e0 is less than 2^61 let v1 = (v0 << 11) + ((v0 << 57).wrapping_sub(e0) >> 47); let e1 = v1.wrapping_neg().wrapping_mul(v1).wrapping_mul(d37); let mut h = Limb::x_mul_y_to_zz(v1, e1).0; // h = floor(e_1 * v_1 /2 ^ 64) let v2 = (v1 << 10) + (h >> 6); h = Limb::x_mul_y_to_zz(v2 * v2, d).0; // in h + 2, one +1 accounts for the lower neglected part of v2 ^ 2 * d. the other +1 is to // compute ceil((h + 1) / 2) let e2 = (1 << 61) - ((h + 2) >> 1); h = v2 * e2; (v2 << 33) + (h >> 29) } // given 2^62 <= u < 2^64, put in s the value floor(sqrt(2^64*u)), and in rh in rl the remainder: // 2^64*u - s^2 = 2^64*rh + rl, with 2^64*rh + rl <= 2*s, and in invs the approximation of // 2^96/sqrt(u) // // This is __gmpfr_sqrt_limb from invsqrt_limb.c, MPFR 4.3.0, returning s, rh, rl, and invs. #[cfg(not(feature = "32_bit_limbs"))] fn limb_sqrt(u: Limb) -> (Limb, Limb, Limb, Limb) { let invs = limb_inverse_sqrt_approx(u); let mut h = Limb::x_mul_y_to_zz(invs, u).0; let mut r = h + u; // make sure r has its most significant bit set if !r.get_highest_bit() { r = LIMB_HIGH_BIT; } // we know r <= sqrt(2 ^ 64 * u) <= r + 16 let mut l; (h, l) = Limb::x_mul_y_to_zz(r, r); (h, l) = Limb::xx_sub_yy_to_zz(u, 0, h, l); // now h:l <= 30 * r assert!(h < 30); if h >= 16 { // subtract 16r + 64 to h:l, add 8 to r (h, l) = Limb::xx_sub_yy_to_zz(h, l, r >> 60, r << 4); (h, l) = Limb::xx_sub_yy_to_zz(h, l, 0, 64); r += 8; } if h >= 8 { // subtract 8r + 16 to h:l, add 4 to r (h, l) = Limb::xx_sub_yy_to_zz(h, l, r >> 61, r << 3); (h, l) = Limb::xx_sub_yy_to_zz(h, l, 0, 16); r += 4; } if h >= 4 { // subtract 4r + 4 to h:l, add 2 to _r (h, l) = Limb::xx_sub_yy_to_zz(h, l, r >> 62, r << 2); (h, l) = Limb::xx_sub_yy_to_zz(h, l, 0, 4); r += 2; } while h > 1 || ((h == 1) && (l > r << 1)) { // subtract 2r + 1 to h:l, add 1 to r (h, l) = Limb::xx_sub_yy_to_zz(h, l, r >> 63, (r << 1) + 1); r += 1; } (r, h, l, invs) } // Put in rp[1] * 2 ^ 64 + rp[0] an approximation of floor(sqrt(2^128*n)), with 2 ^ 126 <= n := // np[1] * 2 ^ 64 + np[0] < 2 ^ 128. We have: {rp, 2} - 4 <= floor(sqrt(2 ^ 128 * n)) <= {rp, 2} + // 26. // // This is mpfr_sqrt2_approx from sqrt.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] fn limbs_2_sqrt_approx(n0: Limb, n1: Limb) -> (Limb, Limb) { let (mut r1, mut h, mut l, x) = limb_sqrt(n1); // now r1 = floor(sqrt(2 ^ 64 * n1)) and h:l = 2 ^ 64 * n1 - r1 ^ 2 with h:l <= 2 * r1, thus h // <= 1, and x is an approximation of 2 ^ 96 / sqrt(n1) - 2 ^ 64 l.wrapping_add_assign(n0); if l < n0 { h += 1; } // now 2 ^ 64 * n1 + n0 - r1 ^ 2 = 2 ^ 64 * h + l with h <= 2 // // divide by 2 l = (h << 63) | (l >> 1); h >>= 1; // now h <= 1 // // now add (2 ^ 64 + x) * (h * 2 ^ 64 + l) / 2 ^ 64 to [r1 * 2 ^ 64, 0] let mut r0 = Limb::x_mul_y_to_zz(x, l).0; // x * l r0.wrapping_add_assign(l); r1 += h + Limb::from(r0 < l); // now we have added 2 ^ 64 * (h * 2 ^ 64 + l) if h != 0 { r0 += x; if r0 < x { r1 += 1; } } assert!(r1.get_highest_bit()); (r0, r1) } // Doesn't compute highest limb, because caller doesn't need it #[cfg(not(feature = "32_bit_limbs"))] fn two_limbs_square(x_1: Limb, x_0: Limb) -> (Limb, Limb, Limb) { let (x_00_1, x_00_0) = Limb::x_mul_y_to_zz(x_0, x_0); let (mut x_01_1, mut x_01_0) = Limb::x_mul_y_to_zz(x_0, x_1); x_01_1 = (x_01_1 << 1) | (x_01_0 >> const { Limb::WIDTH - 1 }); x_01_0 <<= 1; (x_01_1, x_01_0) = Limb::xx_add_yy_to_zz(x_01_1, x_01_0, 0, x_00_1); (x_1.wrapping_mul(x_1).wrapping_add(x_01_1), x_01_0, x_00_0) } // This is mpfr_sqrt2 from sqrt.c, MPFR 4.3.0. #[cfg(not(feature = "32_bit_limbs"))] fn sqrt_float_significand_same_prec_gt_w_lt_2w( x_0: Limb, x_1: Limb, mut x_exp: i32, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, i32, Ordering) { let shift = const { Limb::WIDTH << 1 } - prec; let (n3, n2, n1) = if x_exp.odd() { const SHIFT: u64 = Limb::WIDTH - 1; x_exp += 1; (x_1 >> 1, (x_1 << SHIFT) | (x_0 >> 1), x_0 << SHIFT) } else { (x_1, x_0, 0) }; let mut exp_r = x_exp >> 1; let (mut r0, mut r1) = limbs_2_sqrt_approx(n2, n3); // with n = np[3]*2^64+np[2], we have: {rp, 2} - 4 <= floor(sqrt(2^128*n)) <= {rp, 2} + 26, thus // we can round correctly except when the number formed by the last shift-1 bits of rp[0] is in // the range [-26, 4]. let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; let mut sticky_bit = if r0.wrapping_add(26) & (mask >> 1) > 30 { 1 } else { let (mut t2, mut t1, mut t0) = two_limbs_square(r1, r0); // since we know s - 26 <= r <= s + 4 and 0 <= n^2 - s <= 2*s, we have -8*s-16 <= n - r^2 <= // 54*s - 676, thus it suffices to compute n - r^2 modulo 2^192 (t2, t1, t0) = Limb::xxx_sub_yyy_to_zzz(n2, n1, 0, t2, t1, t0); // invariant: h:l = 2 * {rp, 2}, with upper bit implicit let mut h = (r1 << 1) | (r0 >> const { Limb::WIDTH - 1 }); let mut l = r0 << 1; while t2.get_highest_bit() { // approximation was too large // // subtract 1 to {rp, 2}, thus 2 to h:l if l <= 1 { h -= 1; } l -= 2; // add (1:h:l)+1 to {tp,3} t0.wrapping_add_assign(l + 1); t1.wrapping_add_assign(h + Limb::from(t0 < l)); // necessarily r1 has its most significant bit set t2.wrapping_add_assign(1 + Limb::from(t1 < h || (t1 == h && t0 < l))); } // now tp[2] >= 0 // // now we want {tp, 4} <= 2 * {rp, 2}, which implies tp[2] <= 1 while t2 > 1 || (t2 == 1 && t1 > h) || (t2 == 1 && t1 == h && t0 > l) { // subtract (1:h:l)+1 from {tp,3} t2 -= 1 + Limb::from(t1 < h || (t1 == h && t0 <= l)); t1.wrapping_sub_assign(h + Limb::from(t0 <= l)); t0.wrapping_sub_assign(l + 1); // add 2 to h:l l.wrapping_add_assign(2); if l <= 1 { h += 1; } } // restore {rp, 2} from h:l r1 = LIMB_HIGH_BIT | (h >> 1); r0 = (h << const { Limb::WIDTH - 1 }) | (l >> 1); t2 | t0 | t1 }; let round_bit = r0 & (shift_bit >> 1); sticky_bit |= (r0 & mask) ^ round_bit; r0 &= !mask; if sticky_bit == 0 { return (r0, r1, exp_r, Equal); } match rm { Floor | Down => (r0, r1, exp_r, Less), Ceiling | Up => { r0.wrapping_add_assign(shift_bit); if r0 == 0 { r1.wrapping_add_assign(1); } if r1 == 0 { r1 = LIMB_HIGH_BIT; exp_r += 1; } (r0, r1, exp_r, Greater) } Nearest => { // since sticky_bit != 0 now, only round_bit is needed if round_bit == 0 { (r0, r1, exp_r, Less) } else { r0.wrapping_add_assign(shift_bit); if r0 == 0 { r1.wrapping_add_assign(1); } if r1 == 0 { r1 = LIMB_HIGH_BIT; exp_r += 1; } (r0, r1, exp_r, Greater) } } Exact => panic!("Inexact float square root"), } } fn sqrt_float_significands_general( xs: &[Limb], x_exp: i32, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { let mut shift = out_prec.neg_mod_power_of_2(Limb::LOG_WIDTH); if shift == 0 && rm == Nearest { // ugly case shift = Limb::WIDTH; } let mut rsize = bit_to_limb_count_ceiling(out_prec); if shift == Limb::WIDTH { rsize += 1; } // rsize is the number of limbs of r + 1 if exact limb multiple and rounding to nearest, this is // the number of wanted limbs for the square root let rrsize = rsize << 1; let xs_len = xs.len(); let mut out = vec![0; rsize]; let mut sticky0 = 0; // truncated part of input let odd_exp = x_exp.odd(); let mut sp = vec![0; rrsize]; // copy the most significant limbs of u to {sp, rrsize} if xs_len <= rrsize { // in case r and u have the same precision, we have indeed rrsize = 2 * xs_len let k = rrsize - xs_len; if odd_exp { if k == 0 { sticky0 = limbs_shr_to_out(&mut sp, xs, 1); } else { sp[k - 1] = limbs_shr_to_out(&mut sp[k..], xs, 1); } } else { sp[rrsize - xs_len..].copy_from_slice(xs); } } else { // xs_len > rrsize: truncate the input let k = xs_len - rrsize; let (xs_lo, xs_hi) = xs.split_at(k); if odd_exp { sticky0 = limbs_shr_to_out(&mut sp, xs_hi, 1); } else { sp.copy_from_slice(xs_hi); } for &x in xs_lo.iter().rev() { if sticky0 != 0 { break; } sticky0 = x; } } // sticky0 is non-zero iff the truncated part of the input is non-zero let sqrt_inexact = limbs_sqrt_to_out_return_inexact(&mut out, &sp); let mut sticky = sticky0 != 0 || sqrt_inexact; // truncate low bits of rp[0] let mut shift_bit = if shift == Limb::WIDTH { 0 } else { Limb::power_of_2(shift) }; let sticky1 = out[0] & shift_bit.wrapping_sub(1); out[0] -= sticky1; sticky |= sticky1 != 0; let mut out_exp = (x_exp + i32::from(odd_exp)) >> 1; // exact if !sticky { if shift_bit == 0 { out.remove(0); } return (Natural::from_owned_limbs_asc(out), out_exp, Equal); } let increment = match rm { Floor | Down => false, Ceiling | Up => true, Nearest => { // if shift < Limb::WIDTH: the round bit is bit (shift-1) of sticky1 and the sticky bit // is formed by the low shift-1 bits from sticky1, together with the sqrtrem remainder // and sticky0. // // if shift = Limb::WIDTH: the round bit is the most significant bit of rp[0], and the // remaining Limb::WIDTH - 1 bits contribute to the sticky bit let lower_bit = if shift_bit == 0 { LIMB_HIGH_BIT } else { shift_bit >> 1 }; if sticky1 & lower_bit == 0 { false } else { // round bit is set if sticky1 == lower_bit && !sqrt_inexact && sticky0 == 0 { if shift_bit == 0 { out[1].odd() } else { out[0] & shift_bit != 0 } } else { true } } } Exact => panic!("Inexact float square root"), }; if shift_bit == 0 { out.remove(0); shift_bit = 1; } let o = if increment { if limbs_slice_add_limb_in_place(&mut out, shift_bit) { out_exp += 1; *out.last_mut().unwrap() = LIMB_HIGH_BIT; } Greater } else { Less }; (Natural::from_owned_limbs_asc(out), out_exp, o) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_square.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2024 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::float_extras::round_helper_raw; use crate::natural::arithmetic::float_mul::{ limbs_float_mul_high_same_length, limbs_float_mul_high_same_length_scratch_len, mul_float_significands_ref_ref_helper, }; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::{LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling}; use crate::platform::{DoubleLimb, Limb}; use core::cmp::Ordering::{self, *}; use core::cmp::max; use malachite_base::num::arithmetic::traits::{ OverflowingAddAssign, Parity, PowerOf2, Sign, WrappingAddAssign, XMulYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, SplitInHalf, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; // This is mpfr_sqr from sqr.c, MPFR 4.3.0. pub fn square_float_significand_in_place( x: &mut Natural, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { if out_prec == x_prec && let Some((decrement_exp, o)) = square_float_significand_in_place_same_prec(x, out_prec, rm) { return (-i32::from(decrement_exp), o); } let (square, exp_offset, o) = match &*x { Natural(Small(x)) => square_float_significands_general(&[*x], x_prec, out_prec, rm), Natural(Large(xs)) => square_float_significands_general(xs, x_prec, out_prec, rm), }; *x = square; (exp_offset, o) } // This is mpfr_sqr from sqr.c, MPFR 4.3.0. pub fn square_float_significand_ref( x: &Natural, x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { match x { Natural(Small(x)) => square_float_significand_ref_helper(&[*x], x_prec, out_prec, rm), Natural(Large(xs)) => square_float_significand_ref_helper(xs, x_prec, out_prec, rm), } } fn square_float_significand_ref_helper( xs: &[Limb], x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { if out_prec == x_prec && let Some((square, decrement_exp, o)) = square_float_significand_same_prec_ref(xs, out_prec, rm) { return (square, -i32::from(decrement_exp), o); } square_float_significands_general(xs, x_prec, out_prec, rm) } fn square_float_significand_in_place_same_prec( x: &mut Natural, prec: u64, rm: RoundingMode, ) -> Option<(bool, Ordering)> { match x { Natural(Small(x)) => { let (square, decrement_exp, o) = if prec == Limb::WIDTH { square_float_significand_same_prec_w(*x, rm) } else { square_float_significand_same_prec_lt_w(*x, prec, rm) }; *x = square; Some((decrement_exp, o)) } Natural(Large(xs)) => match xs.as_mut_slice() { [x_0, x_1] if prec != TWICE_WIDTH => { let (square_0, square_1, decrement_exp, o) = square_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); *x_0 = square_0; *x_1 = square_1; Some((decrement_exp, o)) } [x_0, x_1, x_2] if prec != THRICE_WIDTH => { let (square_0, square_1, square_2, decrement_exp, o) = square_float_significand_same_prec_gt_2w_lt_3w(*x_0, *x_1, *x_2, prec, rm); *x_0 = square_0; *x_1 = square_1; *x_2 = square_2; Some((decrement_exp, o)) } _ => None, }, } } fn square_float_significand_same_prec_ref( xs: &[Limb], prec: u64, rm: RoundingMode, ) -> Option<(Natural, bool, Ordering)> { match xs { [x] => { let (square, decrement_exp, o) = if prec == Limb::WIDTH { square_float_significand_same_prec_w(*x, rm) } else { square_float_significand_same_prec_lt_w(*x, prec, rm) }; Some((Natural(Small(square)), decrement_exp, o)) } [x_0, x_1] if prec != TWICE_WIDTH => { let (square_0, square_1, decrement_exp, o) = square_float_significand_same_prec_gt_w_lt_2w(*x_0, *x_1, prec, rm); Some((Natural(Large(vec![square_0, square_1])), decrement_exp, o)) } [x_0, x_1, x_2] if prec != THRICE_WIDTH => { let (square_0, square_1, square_2, decrement_exp, o) = square_float_significand_same_prec_gt_2w_lt_3w(*x_0, *x_1, *x_2, prec, rm); Some(( Natural(Large(vec![square_0, square_1, square_2])), decrement_exp, o, )) } _ => None, } } const WIDTH_M1: u64 = Limb::WIDTH - 1; const COMP_HIGH_BIT: Limb = !LIMB_HIGH_BIT; // This is mpfr_sqr_1 from sqr.c, MPFR 4.3.0. fn square_float_significand_same_prec_lt_w( x: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, bool, Ordering) { let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; let (mut z, mut sticky_bit) = Limb::x_mul_y_to_zz(x, x); let decrement_exp = !z.get_highest_bit(); if decrement_exp { z <<= 1; z |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; } let round_bit = z & (shift_bit >> 1); sticky_bit |= (z & mask) ^ round_bit; let mut square = z & !mask; if round_bit == 0 && sticky_bit == 0 { return (z, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float squaring"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && square & shift_bit == 0) { (square, decrement_exp, Less) } else if square.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, false, Greater) } else { (square, decrement_exp, Greater) } } Floor | Down => (square, decrement_exp, Less), Ceiling | Up => { if square.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, false, Greater) } else { (square, decrement_exp, Greater) } } } } // This is mpfr_sqr_1n from sqr.c, MPFR 4.2.0. fn square_float_significand_same_prec_w(x: Limb, rm: RoundingMode) -> (Limb, bool, Ordering) { let (mut z, mut sticky_bit) = Limb::x_mul_y_to_zz(x, x); let decrement_exp = !z.get_highest_bit(); if decrement_exp { z <<= 1; z |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; } let round_bit = sticky_bit & LIMB_HIGH_BIT; sticky_bit &= COMP_HIGH_BIT; let mut square = z; if round_bit == 0 && sticky_bit == 0 { return (z, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float squaring"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && square.even()) { (square, decrement_exp, Less) } else if square.overflowing_add_assign(1) { (LIMB_HIGH_BIT, false, Greater) } else { (square, decrement_exp, Greater) } } Floor | Down => (square, decrement_exp, Less), Ceiling | Up => { if square.overflowing_add_assign(1) { (LIMB_HIGH_BIT, false, Greater) } else { (square, decrement_exp, Greater) } } } } const TWICE_WIDTH: u64 = Limb::WIDTH * 2; const THRICE_WIDTH: u64 = Limb::WIDTH * 3; // This is mpfr_sqr_2 from sqr.c, MPFR 4.2.0. fn square_float_significand_same_prec_gt_w_lt_2w( x_0: Limb, x_1: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, bool, Ordering) { let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; // we store the 4-limb square in h = z[1], l = z[0], sticky_bit = z[-1], sticky_bit_2 = z[-2] let (mut hi, mut lo) = Limb::x_mul_y_to_zz(x_1, x_1); let (u, v) = Limb::x_mul_y_to_zz(x_0, x_1); if lo.overflowing_add_assign(u) { hi += 1; } if lo.overflowing_add_assign(u) { hi.wrapping_add_assign(1); } // now the full square is {hi, lo, 2 * v + high(x_0 ^ 2), low(x_0 ^ 2)}, where the lower part // contributes to less than 3 ulps to {hi, lo}. // // If hi has its most significant bit set and the low shift - 1 bits of lo are not 000...000 nor // 111...111 nor 111...110, then we can round correctly; if hi has zero as most significant bit, // we have to shift left hi and lo, thus if the low sh-2 bits are not 000...000 nor 111...111 // nor 111...110, then we can round correctly. To avoid an extra test we consider the latter // case (if we can round, we can also round in the former case). For shift <= 3, we have mask <= // 7, thus (mask >> 2) <= 1, and the approximation cannot be enough. let (mut sticky_bit, sticky_bit_2); if lo.wrapping_add(2) & (mask >> 2) > 2 { // result cannot be exact in that case sticky_bit = 1; sticky_bit_2 = 1; } else { (sticky_bit, sticky_bit_2) = Limb::x_mul_y_to_zz(x_0, x_0); // The full square is {h, l, sticky_bit + v + w, sticky_bit_2} if sticky_bit.overflowing_add_assign(v) && lo.overflowing_add_assign(1) { hi.wrapping_add_assign(1); } if sticky_bit.overflowing_add_assign(v) && lo.overflowing_add_assign(1) { hi.wrapping_add_assign(1); } } let decrement_exp = !hi.get_highest_bit(); if decrement_exp { hi <<= 1; hi |= lo >> WIDTH_M1; lo <<= 1; lo |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; // no need to shift sticky_bit_2 since we only want to know if it is zero or not } let mut z_1 = hi; let round_bit = lo & (shift_bit >> 1); sticky_bit |= ((lo & mask) ^ round_bit) | sticky_bit_2; let mut z_0 = lo & !mask; if round_bit == 0 && sticky_bit == 0 { return (z_0, z_1, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float squaring"), Nearest => { if round_bit == 0 || sticky_bit == 0 && (z_0 & shift_bit) == 0 { (z_0, z_1, decrement_exp, Less) } else if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, decrement_exp, Greater) } } Floor | Down => (z_0, z_1, decrement_exp, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) && z_1.overflowing_add_assign(1) { (z_0, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, decrement_exp, Greater) } } } } const LIMB_MASK: DoubleLimb = (1 << Limb::WIDTH) - 1; // This is mpfr_sqr_3 from sqr.c, MPFR 4.2.0. fn square_float_significand_same_prec_gt_2w_lt_3w( x_0: Limb, x_1: Limb, x_2: Limb, prec: u64, rm: RoundingMode, ) -> (Limb, Limb, Limb, bool, Ordering) { let shift = THRICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; // we store the upper 3-limb square in z2, z1, z0: x2 ^ 2, 2 * x1 * x2, 2 * x0 * x2 + x1 ^ 2 let x_0 = DoubleLimb::from(x_0); let x_1 = DoubleLimb::from(x_1); let x_2 = DoubleLimb::from(x_2); let x_2_x_2 = x_2 * x_2; let x_1_x_2 = x_1 * x_2; let x_1_x_1 = x_1 * x_1; let x_0_x_2 = x_0 * x_2; let (mut a2, mut a1) = x_2_x_2.split_in_half(); let (hi, mut a0) = x_1_x_2.split_in_half(); if a1.overflowing_add_assign(hi) { a2 += 1; } if a1.overflowing_add_assign(hi) { a2.wrapping_add_assign(1); } let mut carry = Limb::from(a0.overflowing_add_assign(a0)); let x_0_x_2_hi = Limb::wrapping_from(x_0_x_2 >> Limb::WIDTH); if a0.overflowing_add_assign(x_0_x_2_hi) { carry += 1; } if a0.overflowing_add_assign(x_0_x_2_hi) { carry += 1; } if a0.overflowing_add_assign(Limb::wrapping_from(x_1_x_1 >> Limb::WIDTH)) { carry += 1; } // now propagate carry if a1.overflowing_add_assign(carry) { a2.wrapping_add_assign(1); } // Now the approximate square {a2, a1, a0} has an error of less than 5 ulps (3 ulps for the // ignored low limbs of x_2 * y_0 + x_1 * y_1 + x_0 * y2, plus 2 ulps for the ignored x_1 * y_0 // + x_0 * y_1 (plus x_0 * y_0)). Since we might shift by 1 bit, we make sure the low shift - 2 // bits of a0 are not 0, -1, -2, -3 or -4. let (mut sticky_bit, sticky_bit_2) = if a0.wrapping_add(4) & (mask >> 2) > 4 { // result cannot be exact in that case (1, 1) } else { let out = x_0 * x_0; let p_0 = out & LIMB_MASK; let x_0_x_1 = x_0 * x_1; let out = x_0_x_1 + (out >> Limb::WIDTH); let mut p_1 = out & LIMB_MASK; let out = x_0_x_2 + (out >> Limb::WIDTH); let mut p_2 = out & LIMB_MASK; let mut p_3 = out >> Limb::WIDTH; let out = p_1 + x_0_x_1; p_1 = out & LIMB_MASK; let out = p_2 + x_1_x_1 + (out >> Limb::WIDTH); p_2 = out & LIMB_MASK; let out = p_3 + x_1_x_2 + (out >> Limb::WIDTH); p_3 = out & LIMB_MASK; let p_4 = out >> Limb::WIDTH; let out = p_2 + x_0_x_2; p_2 = out & LIMB_MASK; let out = p_3 + x_1_x_2 + (out >> Limb::WIDTH); p_3 = out & LIMB_MASK; let out = p_4 + x_2_x_2 + (out >> Limb::WIDTH); (a2, a1) = out.split_in_half(); a0 = Limb::wrapping_from(p_3); ( Limb::wrapping_from(p_2), Limb::wrapping_from(p_1) | Limb::wrapping_from(p_0), ) }; let decrement_exp = !a2.get_highest_bit(); if decrement_exp { a2 <<= 1; a2 |= a1 >> WIDTH_M1; a1 <<= 1; a1 |= a0 >> WIDTH_M1; a0 <<= 1; a0 |= sticky_bit >> WIDTH_M1; sticky_bit <<= 1; // no need to shift sticky_bit_2: we only need to know if it is zero or not } let mut z_2 = a2; let mut z_1 = a1; let round_bit = a0 & (shift_bit >> 1); sticky_bit |= ((a0 & mask) ^ round_bit) | sticky_bit_2; let mut z_0 = a0 & !mask; if round_bit == 0 && sticky_bit == 0 { return (z_0, z_1, z_2, decrement_exp, Equal); } match rm { Exact => panic!("Inexact float squaring"), Nearest => { if round_bit == 0 || sticky_bit == 0 && z_0 & shift_bit == 0 { (z_0, z_1, z_2, decrement_exp, Less) } else { if z_0.overflowing_add_assign(shift_bit) { z_1.wrapping_add_assign(1); } if z_1 == 0 && z_0 == 0 { z_2.wrapping_add_assign(1); } if z_2 == 0 { (z_0, z_1, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, z_2, decrement_exp, Greater) } } } Floor | Down => (z_0, z_1, z_2, decrement_exp, Less), Ceiling | Up => { if z_0.overflowing_add_assign(shift_bit) { z_1.wrapping_add_assign(1); } if z_1 == 0 && z_0 == 0 { z_2.wrapping_add_assign(1); } if z_2 == 0 { (z_0, z_1, LIMB_HIGH_BIT, false, Greater) } else { (z_0, z_1, z_2, decrement_exp, Greater) } } } } pub(crate) fn limbs_float_square_high_scratch_len(n: usize) -> usize { let k = MPFR_SQRHIGH_TAB .get(n) .map_or_else(|| isize::exact_from((n + 4) >> 1), |&x| isize::from(x)); if k < 0 { limbs_square_to_out_scratch_len(n) } else if k == 0 { 0 } else { let k = usize::wrapping_from(k); max( limbs_square_to_out_scratch_len(k), limbs_float_mul_high_same_length_scratch_len(n - k), ) } } pub(crate) const MPFR_SQRHIGH_TAB: [i8; 17] = [-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // This is mpfr_mulhigh_n_basecase from mulders.c, MPFR 4.2.0, specialized for squaring. fn limbs_float_sqr_high_same_length_basecase(out: &mut [Limb], xs: &[Limb]) { let len = xs.len(); // We neglect xs[0..len - 2] * xs[0], which is less than B ^ len let out = &mut out[len - 1..]; (out[1], out[0]) = Limb::x_mul_y_to_zz(*xs.last().unwrap(), xs[0]); for (i, x) in xs.iter().enumerate() { let i = i + 1; // Here, we neglect xs[0..len - i - 2] * xs[i], which is less than B ^ len too let (out_lo, out_hi) = out.split_at_mut(i); out_hi[0] = limbs_slice_add_mul_limb_same_length_in_place_left(out_lo, &xs[len - i..], *x); // In total, we neglect less than n * B ^ len, i.e., n ulps of out[len]. } } // Put in out[n..2 * len - 1] an approximation of the n high limbs of xs ^ 2. The error is less than // len ulps of out[len] (and the approximation is always less or equal to the truncated full // square). // // Implements Algorithm ShortMul from: // // [1] Short Division of Long Integers, David Harvey and Paul Zimmermann, Proceedings of the 20th // Symposium on Computer Arithmetic (ARITH-20), July 25-27, 2011, pages 7-14. // // This is mpfr_sqrhigh_n from mulders.c, MPFR 4.2.0. pub(crate) fn limbs_float_square_high(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { const LEN_ASSERT: bool = MPFR_SQRHIGH_TAB.len() > 2; assert!(LEN_ASSERT); let n = xs.len(); let k = MPFR_SQRHIGH_TAB .get(n) .map_or_else(|| isize::exact_from((n + 4) >> 1), |&x| isize::from(x)); assert!( k == -1 || k == 0 || (k >= isize::exact_from((n + 4) >> 1) && k < isize::exact_from(n)) ); if k < 0 { limbs_square_to_out(out, xs, scratch); } else if k == 0 { limbs_float_sqr_high_same_length_basecase(out, xs); } else { let k = usize::wrapping_from(k); let l = n - k; limbs_square_to_out(&mut out[l << 1..], &xs[l..], scratch); let (xs_lo, xs_hi) = xs.split_at(k); limbs_float_mul_high_same_length(out, &xs_lo[..l], xs_hi, scratch); let (out_lo, out_hi) = out.split_at_mut(n - 1); let out_lo = &mut out_lo[l - 1..l << 1]; let mut carry = limbs_slice_shl_in_place(out_lo, 1); if limbs_slice_add_same_length_in_place_left(&mut out_hi[..=l], out_lo) { carry += 1; } limbs_slice_add_limb_in_place(&mut out[n + l..n << 1], carry); } } const MPFR_SQR_THRESHOLD: usize = 20; fn square_float_significands_general( xs: &[Limb], x_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering) { let xs_len = xs.len(); let tn = bit_to_limb_count_ceiling(x_prec << 1); if xs_len > MPFR_SQR_THRESHOLD { return mul_float_significands_ref_ref_helper(xs, x_prec, xs, x_prec, out_prec, rm); } let xs_len_2 = xs_len << 1; let mut scratch = vec![0; xs_len_2 + limbs_square_to_out_scratch_len(xs.len())]; let (tmp, scratch) = scratch.split_at_mut(xs_len_2); // Multiplies the mantissa in temporary allocated space limbs_square_to_out(tmp, xs, scratch); let mut b1 = tmp[xs_len_2 - 1]; // now tmp[0]..tmp[2 * xs_len - 1] contains the square of the mantissa, with tmp[2 * xs_len - 1] // >= 2 ^ (Limb::WIDTH - 2) b1 >>= const { Limb::WIDTH - 1 }; // msb from the product // if the mantissas of b and c are uniformly distributed in (1/2, 1], then their product is in // (1/4, 1/2] with probability 2 * ln(2) - 1 ~ 0.386 and in [1/2, 1] with probability 2 - 2 * // ln(2) ~ 0.614 let tmp = &mut tmp[xs_len_2 - tn..]; if b1 == 0 { limbs_slice_shl_in_place(&mut tmp[..tn], 1); } let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (inexact, increment_exp) = round_helper_raw(&mut out, out_prec, tmp, x_prec << 1, rm); assert!(inexact == 0 || rm != Exact, "Inexact float squaring"); let mut exp_offset = -i32::from(b1 == 0); if increment_exp { exp_offset += 1; } ( Natural::from_owned_limbs_asc(out), exp_offset, inexact.sign(), ) } ================================================ FILE: malachite-nz/src/natural/arithmetic/float_sub.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MPFR Library. // // Copyright © 1999-2022 Free Software Foundation, Inc. // // Contributed by the AriC and Caramba projects, INRIA. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::float_extras::{MPFR_EVEN_INEX, round_helper_even}; use crate::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, sub_with_carry, }; use crate::natural::{ LIMB_HIGH_BIT, Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor, limb_to_bit_count, }; use crate::platform::Limb; use core::cmp::{ Ordering::{self, *}, max, }; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ IsPowerOf2, ModPowerOf2, ModPowerOf2Sub, NegAssign, NegModPowerOf2, OverflowingAddAssign, OverflowingNegAssign, PowerOf2, SaturatingAddAssign, SaturatingSubAssign, Sign, WrappingAddAssign, WrappingNegAssign, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ExactFrom, SaturatingFrom, WrappingFrom}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::{slice_set_zero, slice_test_zero}; const WIDTH_M1: u64 = Limb::WIDTH - 1; const IWIDTH_M1: isize = WIDTH_M1 as isize; const WIDTH_M1_MASK: Limb = Limb::MAX >> 1; const WIDTH_M2_MASK: Limb = Limb::MAX >> 2; const HALF_LIMB_HIGH_BIT: Limb = LIMB_HIGH_BIT >> 1; const IWIDTH: i32 = Limb::WIDTH as i32; const NEG_ONE: Limb = Limb::MAX; const NEG_TWO: Limb = Limb::MAX - 1; const WIDTH_P1: u64 = Limb::WIDTH + 1; const TWICE_WIDTH: u64 = Limb::WIDTH * 2; const THRICE_WIDTH: u64 = Limb::WIDTH * 3; const TWICE_WIDTH_P1: u64 = Limb::WIDTH * 2 + 1; pub fn sub_float_significands_in_place( mut x: &mut Natural, x_exp: &mut i32, x_prec: u64, mut y: &mut Natural, y_exp: i32, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Ordering, bool, bool) { if x_prec == y_prec && out_prec == x_prec { sub_float_significands_in_place_same_prec(x, x_exp, y, y_exp, out_prec, rm) } else { match (&mut x, &mut y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *small_x = out[0]; *x_exp = diff_exp; } (o, false, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Large(out)); *x_exp = diff_exp; } (o, false, neg) } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *small_x = out[0]; *x_exp = diff_exp; } (o, false, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Large(out)); *x_exp = diff_exp; } (o, false, neg) } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Small(out[0])); *x_exp = diff_exp; } (o, false, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *xs = out; *x_exp = diff_exp; } (o, false, neg) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Small(out[0])); *x_exp = diff_exp; } (o, false, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *xs = out; *x_exp = diff_exp; } (o, false, neg) } } } } } pub fn sub_float_significands_in_place_ref( mut x: &mut Natural, x_exp: &mut i32, x_prec: u64, y: &Natural, y_exp: i32, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Ordering, bool) { if x_prec == y_prec && out_prec == x_prec { sub_float_significands_in_place_same_prec_ref(x, x_exp, y, y_exp, out_prec, rm) } else { match (&mut x, y) { (Natural(Small(small_x)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *small_x = out[0]; *x_exp = diff_exp; } (o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Large(out)); *x_exp = diff_exp; } (o, neg) } } (Natural(Small(small_x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *small_x = out[0]; *x_exp = diff_exp; } (o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, &[*small_x], *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Large(out)); *x_exp = diff_exp; } (o, neg) } } (Natural(Large(xs)), Natural(Small(small_y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Small(out[0])); *x_exp = diff_exp; } (o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, &[*small_y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *xs = out; *x_exp = diff_exp; } (o, neg) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x = Natural(Small(out[0])); *x_exp = diff_exp; } (o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (diff_exp, o, neg) = sub_float_significands_general( &mut out, xs, *x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); if *out.last().unwrap() == 0 { *x = Natural::ZERO; } else { *xs = out; *x_exp = diff_exp; } (o, neg) } } } } } pub fn sub_float_significands_ref_ref<'a>( x: &'a Natural, x_exp: i32, x_prec: u64, y: &'a Natural, y_exp: i32, y_prec: u64, out_prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering, bool) { if x_prec == y_prec && out_prec == x_prec { sub_float_significands_same_prec_ref_ref(x, x_exp, y, y_exp, out_prec, rm) } else { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, &[*x], x_exp, x_prec, &[*y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); (Natural(Small(out[0])), out_exp, o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, &[*x], x_exp, x_prec, &[*y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); ( if *out.last().unwrap() == 0 { Natural::ZERO } else { Natural(Large(out)) }, out_exp, o, neg, ) } } (Natural(Small(x)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, &[*x], x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); (Natural(Small(out[0])), out_exp, o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, &[*x], x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); ( if *out.last().unwrap() == 0 { Natural::ZERO } else { Natural(Large(out)) }, out_exp, o, neg, ) } } (Natural(Large(xs)), Natural(Small(y))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, xs, x_exp, x_prec, &[*y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); (Natural(Small(out[0])), out_exp, o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, xs, x_exp, x_prec, &[*y], y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); ( if *out.last().unwrap() == 0 { Natural::ZERO } else { Natural(Large(out)) }, out_exp, o, neg, ) } } (Natural(Large(xs)), Natural(Large(ys))) => { if out_prec <= Limb::WIDTH { let mut out = [0]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, xs, x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); (Natural(Small(out[0])), out_exp, o, neg) } else { let mut out = vec![0; bit_to_limb_count_ceiling(out_prec)]; let (out_exp, o, neg) = sub_float_significands_general( &mut out, xs, x_exp, x_prec, ys, y_exp, y_prec, out_prec, rm, ); assert!(rm != Exact || o == Equal, "Inexact float subtraction"); ( if *out.last().unwrap() == 0 { Natural::ZERO } else { Natural(Large(out)) }, out_exp, o, neg, ) } } } } } // This is mpfr_sub1sp from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_in_place_same_prec( x: &mut Natural, x_exp: &mut i32, y: &mut Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Ordering, bool, bool) { match (&mut *x, &mut *y) { (Natural(Small(x)), Natural(Small(y))) => { let (diff, diff_exp, o, neg) = if prec == Limb::WIDTH { sub_float_significands_same_prec_w(*x, *x_exp, *y, y_exp, rm) } else { sub_float_significands_same_prec_lt_w(*x, *x_exp, *y, y_exp, prec, rm) }; *x = diff; *x_exp = diff_exp; (o, false, neg) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_mut_slice()) { ([x_0, x_1], [y_0, y_1]) => { let (diff_0, diff_1, diff_exp, o, neg) = if prec == TWICE_WIDTH { sub_float_significands_same_prec_2w(*x_0, *x_1, *x_exp, *y_0, *y_1, y_exp, rm) } else { sub_float_significands_same_prec_gt_w_lt_2w( *x_0, *x_1, *x_exp, *y_0, *y_1, y_exp, prec, rm, ) }; if diff_1 == 0 { *x = Natural::ZERO; } else { *x_0 = diff_0; *x_1 = diff_1; } *x_exp = diff_exp; (o, false, neg) } ([x_0, x_1, x_2], [y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (diff_0, diff_1, diff_2, diff_exp, o, neg) = sub_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *x_exp, *y_0, *y_1, *y_2, y_exp, prec, rm, ); if diff_2 == 0 { *x = Natural::ZERO; } else { *x_0 = diff_0; *x_1 = diff_1; *x_2 = diff_2; } *x_exp = diff_exp; (o, false, neg) } (xs, ys) => { let (diff_exp, o, neg) = sub_float_significands_same_prec_ge_3w_val_val(xs, *x_exp, ys, y_exp, prec, rm); if *xs.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x_exp = diff_exp; } (o, neg, neg) } }, _ => unreachable!(), } } // This is mpfr_sub1sp from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_in_place_same_prec_ref( x: &mut Natural, x_exp: &mut i32, y: &Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Ordering, bool) { match (&mut *x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (diff, diff_exp, o, neg) = if prec == Limb::WIDTH { sub_float_significands_same_prec_w(*x, *x_exp, *y, y_exp, rm) } else { sub_float_significands_same_prec_lt_w(*x, *x_exp, *y, y_exp, prec, rm) }; *x = diff; *x_exp = diff_exp; (o, neg) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_mut_slice(), ys.as_slice()) { ([x_0, x_1], &[y_0, y_1]) => { let (diff_0, diff_1, diff_exp, o, neg) = if prec == TWICE_WIDTH { sub_float_significands_same_prec_2w(*x_0, *x_1, *x_exp, y_0, y_1, y_exp, rm) } else { sub_float_significands_same_prec_gt_w_lt_2w( *x_0, *x_1, *x_exp, y_0, y_1, y_exp, prec, rm, ) }; if diff_1 == 0 { *x = Natural::ZERO; } else { *x_0 = diff_0; *x_1 = diff_1; } *x_exp = diff_exp; (o, neg) } ([x_0, x_1, x_2], &[y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (diff_0, diff_1, diff_2, diff_exp, o, neg) = sub_float_significands_same_prec_gt_2w_lt_3w( *x_0, *x_1, *x_2, *x_exp, y_0, y_1, y_2, y_exp, prec, rm, ); if diff_2 == 0 { *x = Natural::ZERO; } else { *x_0 = diff_0; *x_1 = diff_1; *x_2 = diff_2; } *x_exp = diff_exp; (o, neg) } (xs, ys) => { let (diff_exp, o, neg) = sub_float_significands_same_prec_ge_3w_val_ref(xs, *x_exp, ys, y_exp, prec, rm); if *xs.last().unwrap() == 0 { *x = Natural::ZERO; } else { *x_exp = diff_exp; } (o, neg) } }, _ => unreachable!(), } } // This is mpfr_sub1sp from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_ref_ref( x: &Natural, x_exp: i32, y: &Natural, y_exp: i32, prec: u64, rm: RoundingMode, ) -> (Natural, i32, Ordering, bool) { match (x, y) { (Natural(Small(x)), Natural(Small(y))) => { let (diff, diff_exp, o, neg) = if prec == Limb::WIDTH { sub_float_significands_same_prec_w(*x, x_exp, *y, y_exp, rm) } else { sub_float_significands_same_prec_lt_w(*x, x_exp, *y, y_exp, prec, rm) }; (Natural(Small(diff)), diff_exp, o, neg) } (Natural(Large(xs)), Natural(Large(ys))) => match (xs.as_slice(), ys.as_slice()) { (&[x_0, x_1], &[y_0, y_1]) => { let (diff_0, diff_1, diff_exp, o, neg) = if prec == TWICE_WIDTH { sub_float_significands_same_prec_2w(x_0, x_1, x_exp, y_0, y_1, y_exp, rm) } else { sub_float_significands_same_prec_gt_w_lt_2w( x_0, x_1, x_exp, y_0, y_1, y_exp, prec, rm, ) }; ( if diff_1 == 0 { Natural::ZERO } else { Natural(Large(vec![diff_0, diff_1])) }, diff_exp, o, neg, ) } (&[x_0, x_1, x_2], &[y_0, y_1, y_2]) if prec != THRICE_WIDTH => { let (diff_0, diff_1, diff_2, diff_exp, o, neg) = sub_float_significands_same_prec_gt_2w_lt_3w( x_0, x_1, x_2, x_exp, y_0, y_1, y_2, y_exp, prec, rm, ); ( if diff_2 == 0 { Natural::ZERO } else { Natural(Large(vec![diff_0, diff_1, diff_2])) }, diff_exp, o, neg, ) } (xs, ys) => { let mut out = vec![0; xs.len()]; let (diff_exp, o, neg) = sub_float_significands_same_prec_ge_3w_ref_ref( &mut out, xs, x_exp, ys, y_exp, prec, rm, ); ( if slice_test_zero(&out) { Natural::ZERO } else { Natural(Large(out)) }, diff_exp, o, neg, ) } }, _ => unreachable!(), } } // This is mpfr_sub1sp1 from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_lt_w( mut x: Limb, mut x_exp: i32, mut y: Limb, mut y_exp: i32, prec: u64, mut rm: RoundingMode, ) -> (Limb, i32, Ordering, bool) { { let (mut diff, sticky_bit, round_bit, shift_bit, neg) = if x_exp == y_exp { let (a0, neg) = match x.cmp(&y) { Equal => return (0, 0, Equal, false), Less => (y - x, true), Greater => (x - y, false), }; let leading_zeros = a0.leading_zeros(); x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); (a0 << leading_zeros, 0, 0, 0, neg) } else { let neg = x_exp < y_exp; if neg { // swap x and y swap(&mut x_exp, &mut y_exp); swap(&mut x, &mut y); } let exp_diff = u64::exact_from(x_exp - y_exp); let shift = Limb::WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; if exp_diff < Limb::WIDTH { // neglected part of -y let mut sticky_bit = (y << (Limb::WIDTH - exp_diff)).wrapping_neg(); let mut a0 = x - Limb::from(sticky_bit != 0) - (y >> exp_diff); // a0 cannot be zero here since: // - if exp_diff >= 2, then a0 >= 2^(w-1) - (2^(w-2)-1) with w = Limb::WIDTH, thus // a0 - 1 >= 2 ^ (w - 2), // - if exp_diff = 1, then since prec < Limb::WIDTH we have sticky_bit = 0. // assert_ne!(a0, 0); let leading_zeros = LeadingZeros::leading_zeros(a0); if leading_zeros != 0 { a0 = (a0 << leading_zeros) | (sticky_bit >> (Limb::WIDTH - leading_zeros)); } sticky_bit <<= leading_zeros; x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); // shift > 0 since prec < Limb::WIDTH assert_ne!(shift, 0); let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, sticky_bit | (a0 & mask) ^ round_bit, round_bit, shift_bit, neg, ) } else if x > LIMB_HIGH_BIT { // We compute x - ulp(x), and the remainder ulp(x) - y satisfies: 1/2 ulp(x) < // ulp(x) - y < ulp(x), thus round_bit = sticky_bit = 1. (x - shift_bit, 1, 1, shift_bit, neg) } else { // - Warning: since we have an exponent decrease, when prec = Limb::WIDTH - 1 and d // = Limb::WIDTH, the round bit corresponds to the upper bit of -y. In that case // round_bit = 0 and sticky_bit = 1, except when y0 = LIMB_HIGH_BIT where // round_bit = 1 and sticky_bit = 0. // - sticky_bit = 1 below is incorrect when prec = Limb::WIDTH - 1, exp_diff = // Limb::WIDTH and y0 = LIMB_HIGH_BIT, but in that case the even rule would round // up too. // - Warning: if exp_diff = Limb::WIDTH and y0 = 1000...000, then x0 - y0 = // |0111...111|1000...000|, which after the shift becomes |111...111|000...000| // thus if prec = Limb::WIDTH - 1 we have round_bit = 1 but sticky_bit = 0. // However, in this case the round even rule will round up, which is what we get // with sticky_bit = 1: the final result will be correct, while sb is incorrect. x_exp.saturating_sub_assign(1); ( !mask, 1, Limb::from(shift > 1 || exp_diff > Limb::WIDTH || y == LIMB_HIGH_BIT), shift_bit, neg, ) } }; if round_bit == 0 && sticky_bit == 0 { (diff, x_exp, Equal, neg) } else { if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (diff & shift_bit) == 0) { (diff, x_exp, Less, neg) } else if diff.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff, x_exp, Greater, neg) } } Floor | Down => (diff, x_exp, Less, neg), Ceiling | Up => { if diff.overflowing_add_assign(shift_bit) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff, x_exp, Greater, neg) } } } } } } // This is mpfr_sub1sp1n from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_w( mut x: Limb, mut x_exp: i32, mut y: Limb, mut y_exp: i32, mut rm: RoundingMode, ) -> (Limb, i32, Ordering, bool) { let (mut diff, sticky_bit, round_bit, neg) = if x_exp == y_exp { let (a0, neg) = match x.cmp(&y) { Equal => return (0, 0, Equal, false), Less => (y - x, true), Greater => (x - y, false), }; let leading_zeros = LeadingZeros::leading_zeros(a0); x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); (a0 << leading_zeros, 0, 0, neg) } else { let neg = x_exp < y_exp; if neg { // swap x and y swap(&mut x_exp, &mut y_exp); swap(&mut x, &mut y); } let exp_diff = u64::exact_from(x_exp - y_exp); if exp_diff < Limb::WIDTH { let mut sticky_bit = (y << (Limb::WIDTH - exp_diff)).wrapping_neg(); let mut a0 = x.wrapping_sub(y >> exp_diff); if sticky_bit != 0 { a0.wrapping_sub_assign(1); } // a0 can only be zero when exp_diff = 1, x0 = B / 2, and y0 = B-1, where B = 2 ^ // Limb::WIDTH, thus x0 - y0 / 2 = 1/2 if a0 == 0 { x_exp.saturating_sub_assign(IWIDTH); (LIMB_HIGH_BIT, 0, 0, neg) } else { let leading_zeros = LeadingZeros::leading_zeros(a0); if leading_zeros != 0 { a0 = (a0 << leading_zeros) | (sticky_bit >> (Limb::WIDTH - leading_zeros)); } sticky_bit <<= leading_zeros; x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); let round_bit = sticky_bit & LIMB_HIGH_BIT; (a0, sticky_bit & !LIMB_HIGH_BIT, round_bit, neg) } } else { // We compute x - ulp(x) if x > LIMB_HIGH_BIT { // If exp_diff = Limb::WIDTH, round_bit = 0 and sticky_bit = 1, unless c0 = // LIMB_HIGH_BIT in which case round_bit = 1 and sticky_bit = 0. If exp_diff > // Limb::WIDTH, round_bit = sticky_bit = 1. let b = exp_diff > Limb::WIDTH; ( x - 1, Limb::from(b || y != LIMB_HIGH_BIT), Limb::from(b || y == LIMB_HIGH_BIT), neg, ) } else { // Warning: in this case a0 is shifted by one! // // If exp_diff = Limb::WIDTH // - a) If y0 = LIMB_HIGH_BIT, a0 = 111...111, round_bit = sticky_bit = 0 // - b) Otherwise, a0 = 111...110, round_bit = -y0 >= 01000...000, sticky_bit = // (-y0) << 2 // // If exp_diff = Limb::WIDTH + 1: a0 = 111...111 // - c) If y0 = LIMB_HIGH_BIT, round_bit = 1 and sticky_bit = 0 // - d) Otherwise round_bit = 0 and sticky_bit = 1 // // If exp_diff > Limb::WIDTH + 1: // - e) a0 = 111...111, round_bit = sticky_bit = 1 x_exp.saturating_sub_assign(1); if exp_diff == Limb::WIDTH && y > LIMB_HIGH_BIT { // case (b) ( NEG_TWO, y.wrapping_neg() << 2, Limb::from(y.wrapping_neg() >= (LIMB_HIGH_BIT >> 1)), neg, ) } else { // cases (a), (c), (d) and (e) // - round_bit = 1 in case (e) and case (c) // - sticky_bit = 1 in case (d) and (e) let b1 = exp_diff > WIDTH_P1; let b2 = exp_diff == WIDTH_P1; ( NEG_ONE, Limb::from(b1 || (b2 && y > LIMB_HIGH_BIT)), Limb::from(b1 || (b2 && y == LIMB_HIGH_BIT)), neg, ) } } } }; if round_bit == 0 && sticky_bit == 0 { (diff, x_exp, Equal, neg) } else { if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (diff & 1) == 0) { (diff, x_exp, Less, neg) } else if diff.overflowing_add_assign(1) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff, x_exp, Greater, neg) } } Floor | Down => (diff, x_exp, Less, neg), Ceiling | Up => { if diff.overflowing_add_assign(1) { (LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff, x_exp, Greater, neg) } } } } } // This is mpfr_sub1sp2 from sub1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_gt_w_lt_2w( mut x_0: Limb, mut x_1: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_exp: i32, prec: u64, mut rm: RoundingMode, ) -> (Limb, Limb, i32, Ordering, bool) { let (mut diff_0, mut diff_1, sticky_bit, round_bit, shift_bit, neg) = if x_exp == y_exp { // subtraction is exact in this case // // first compute a0: if the compiler is smart enough, it will use the generated borrow to // get for free the term (x_0 < y_0) let (mut a0, overflow) = x_0.overflowing_sub(y_0); let mut a1 = x_1.wrapping_sub(y_1); if overflow { a1.wrapping_sub_assign(1); } let neg = if a1 == 0 && a0 == 0 { return (0, 0, 0, Equal, false); } else if a1 >= x_1 { // out = x - y mod 2 ^ (2 * Limb::WIDTH) let overflow = a0.overflowing_neg_assign(); a1.wrapping_neg_assign(); if overflow { a1.wrapping_sub_assign(1); } true } else { false }; if a1 == 0 { a1 = a0; a0 = 0; x_exp.saturating_sub_assign(IWIDTH); } // now a1 != 0 let leading_zeros = LeadingZeros::leading_zeros(a1); if leading_zeros != 0 { x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); ( a0 << leading_zeros, (a1 << leading_zeros) | (a0 >> (Limb::WIDTH - leading_zeros)), 0, 0, 0, neg, ) } else { (a0, a1, 0, 0, 0, neg) } } else { let neg = x_exp < y_exp; if neg { swap(&mut x_exp, &mut y_exp); swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); } let exp_diff = u64::exact_from(x_exp - y_exp); let shift = TWICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; if exp_diff < Limb::WIDTH { let comp_diff = Limb::WIDTH - exp_diff; let t = (y_1 << comp_diff) | (y_0 >> exp_diff); let (mut sticky_bit, overflow_1) = (y_0 << comp_diff).overflowing_neg(); let (mut a0, overflow_2) = x_0.overflowing_sub(t); if overflow_1 { a0.wrapping_sub_assign(1); } let mut a1 = x_1.wrapping_sub(y_1 >> exp_diff); if overflow_2 || (x_0 == t && overflow_1) { a1.wrapping_sub_assign(1); } if a1 == 0 { // This implies exp_diff = 1, which in turn implies sticky_bit = 0 assert_eq!(sticky_bit, 0); a1 = a0; a0 = 0; // Since sticky_bit = 0 already, no need to set it to 0 x_exp.saturating_sub_assign(IWIDTH); } // now a1 != 0 assert_ne!(a1, 0); let leading_zeros = LeadingZeros::leading_zeros(a1); let diff_1 = if leading_zeros != 0 { let comp_zeros = Limb::WIDTH - leading_zeros; let diff_1 = (a1 << leading_zeros) | (a0 >> comp_zeros); a0 = (a0 << leading_zeros) | (sticky_bit >> comp_zeros); sticky_bit <<= leading_zeros; x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); diff_1 } else { a1 }; // shift > 0 since prec < 2 * Limb::WIDTH assert_ne!(shift, 0); let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, diff_1, sticky_bit | ((a0 & mask) ^ round_bit), round_bit, shift_bit, neg, ) } else if exp_diff < TWICE_WIDTH { // Warning: the most significant bit of sticky_bit might become the least significant // bit of a0 below let mut sticky_bit = if exp_diff == Limb::WIDTH { y_0 } else { let mut sticky_bit = y_1 << (TWICE_WIDTH - exp_diff); if y_0 != 0 { sticky_bit |= 1; } sticky_bit }; let mut t = y_1 >> (exp_diff - Limb::WIDTH); if sticky_bit != 0 { t.wrapping_add_assign(1); } // Warning: t might overflow to 0 if exp_diff == Limb::WIDTH and sticky_bit != 0 let (mut a0, overflow) = x_0.overflowing_sub(t); let mut a1 = x_1; if overflow { a1.wrapping_sub_assign(1); } if t == 0 && sticky_bit != 0 { a1.wrapping_sub_assign(1); } sticky_bit.wrapping_neg_assign(); // since x_1 has its most significant bit set, we can have an exponent decrease of at // most one let diff_1 = if a1 < LIMB_HIGH_BIT { let diff_1 = (a1 << 1) | (a0 >> WIDTH_M1); a0 = (a0 << 1) | (sticky_bit >> WIDTH_M1); sticky_bit <<= 1; x_exp.saturating_sub_assign(1); diff_1 } else { a1 }; let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, diff_1, sticky_bit | ((a0 & mask) ^ round_bit), round_bit, shift_bit, neg, ) } else { // We compute x - ulp(x), and the remainder ulp(x) - y satisfies: 1/2 ulp(x) < ulp(x) - // y < ulp(x), thus round_bit = sticky_bit = 1, unless we had an exponent decrease. let t = shift_bit; let (a0, overflow) = x_0.overflowing_sub(t); let mut a1 = x_1; if overflow { a1.wrapping_sub_assign(1); } if a1 < LIMB_HIGH_BIT { // Necessarily we had x = 1000...000 // // Warning: since we have an exponent decrease, when prec = Limb::WIDTH * 2 - 1 and // exp_diff = Limb::WIDTH * 2, the round bit corresponds to the upper bit of -y. In // that case round_bit = 0 and sticky_bit = 1, except when y = 1000...000 where // round_bit = 1 and sticky_bit = 0. // // sticky_bit = 1 below is incorrect when prec = Limb::WIDTH * 2 - 1, exp_diff = // Limb::WIDTH * 2, and y = 1000...000, but in that case the even rule would round // up too. x_exp.saturating_sub_assign(1); ( !mask, Limb::MAX, 1, Limb::from( shift > 1 || exp_diff > TWICE_WIDTH || (y_1 == LIMB_HIGH_BIT && y_0 == 0), ), shift_bit, neg, ) } else { (a0, a1, 1, 1, shift_bit, neg) } } }; if round_bit == 0 && sticky_bit == 0 { (diff_0, diff_1, x_exp, Equal, neg) } else { if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0) { (diff_0, diff_1, x_exp, Less, neg) } else if diff_0.overflowing_add_assign(shift_bit) && diff_1.overflowing_add_assign(1) { (diff_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff_0, diff_1, x_exp, Greater, neg) } } Floor | Down => (diff_0, diff_1, x_exp, Less, neg), Ceiling | Up => { if diff_0.overflowing_add_assign(shift_bit) && diff_1.overflowing_add_assign(1) { (diff_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff_0, diff_1, x_exp, Greater, neg) } } } } } // This is mpfr_sub1sp2n from add1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_2w( mut x_0: Limb, mut x_1: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_exp: i32, mut rm: RoundingMode, ) -> (Limb, Limb, i32, Ordering, bool) { let (mut diff_0, mut diff_1, sticky_bit, round_bit, neg) = if x_exp == y_exp { let (mut a0, overflow) = x_0.overflowing_sub(y_0); let mut a1 = x_1.wrapping_sub(y_1); if overflow { a1.wrapping_sub_assign(1); } let neg = if a1 == 0 && a0 == 0 { return (0, 0, 0, Equal, false); } else if a1 >= x_1 { // since B/2 <= x_1, y_1 < B with B = 2 ^ Limb::WIDTH, if no borrow we have 0 <= x_1 - // y_1 - x < B / 2, where x = (x_0 < y_0) is 0 or 1, thus a1 < B / 2 <= x_1 // // negate [a1,a0] let overflow = a0.overflowing_neg_assign(); a1.wrapping_neg_assign(); if overflow { a1.wrapping_sub_assign(1); } true } else { false }; // now [a1,a0] is the absolute value of x - y, maybe not normalized if a1 == 0 { a1 = a0; a0 = 0; x_exp.saturating_sub_assign(IWIDTH); } let leading_zeros = LeadingZeros::leading_zeros(a1); if leading_zeros != 0 { // shift [a1, a0] left by leading_zeros bits and store in result x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); ( a0 << leading_zeros, (a1 << leading_zeros) | (a0 >> (Limb::WIDTH - leading_zeros)), 0, 0, neg, ) } else { (a0, a1, 0, 0, neg) } } else { let neg = x_exp < y_exp; if neg { swap(&mut x_exp, &mut y_exp); swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); } let exp_diff = u64::exact_from(x_exp - y_exp); if exp_diff < Limb::WIDTH { let comp_diff = Limb::WIDTH - exp_diff; let t = (y_1 << comp_diff) | (y_0 >> exp_diff); // t is the part that should be subtracted to x_0: // ``` // | a1 | a0 | // | x_1 | x_0 | // | y_1 >> d | t | sticky_bit | // ``` let (mut sticky_bit, overflow_1) = (y_0 << comp_diff).overflowing_neg(); let (mut a0, overflow_2) = x_0.overflowing_sub(t); if overflow_1 { a0.wrapping_sub_assign(1); } let mut a1 = x_1.wrapping_sub(y_1 >> exp_diff); if overflow_2 || (x_0 == t && overflow_1) { a1.wrapping_sub_assign(1); } // Now the result is formed of [a1,a0,sticky_bit], which might not be normalized if a1 == 0 { // this implies d = 1 assert_eq!(exp_diff, 1); a1 = a0; a0 = sticky_bit; sticky_bit = 0; x_exp.saturating_sub_assign(IWIDTH); } if a1 == 0 { assert_eq!(a0, LIMB_HIGH_BIT); x_exp.saturating_sub_assign(IWIDTH); (sticky_bit, a0, 0, 0, neg) } else { let leading_zeros = LeadingZeros::leading_zeros(a1); if leading_zeros != 0 { let comp_zeros = Limb::WIDTH - leading_zeros; // shift [a1, a0, sticky_bit] left by leading_zeros bits and adjust exponent a1 = (a1 << leading_zeros) | (a0 >> comp_zeros); a0 = (a0 << leading_zeros) | (sticky_bit >> comp_zeros); sticky_bit <<= leading_zeros; x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); } ( a0, a1, sticky_bit & !LIMB_HIGH_BIT, sticky_bit & LIMB_HIGH_BIT, neg, ) } } else if exp_diff < TWICE_WIDTH { // Compute t, the part to be subtracted to x_0, and sticky_bit, the neglected part of y: // // ``` // | a1 | a0 | // | diff_1 | diff_0 | // | t | sticky_bit | // ``` // // Warning: we should not ignore the low bits from y_0 in case exp_diff > Limb::WIDTH let comp_diff_1 = exp_diff - Limb::WIDTH; let comp_diff_2 = TWICE_WIDTH - exp_diff; let mut sticky_bit = if comp_diff_1 == 0 { y_0 } else { let mut sticky_bit = (y_1 << comp_diff_2) | (y_0 >> comp_diff_1); if y_0 << comp_diff_2 != 0 { sticky_bit |= 1; } sticky_bit }; let mut t = y_1 >> comp_diff_1; if sticky_bit != 0 { t.wrapping_add_assign(1); } // Warning: t might overflow to 0 if exp_diff = Limb::WIDTH, sticky_bit != 0, and y_1 = // 111...111. let (mut a0, overflow) = x_0.overflowing_sub(t); let mut a1 = x_1; if overflow { a1.wrapping_sub_assign(1); } if t == 0 && sticky_bit != 0 { a1.wrapping_sub_assign(1); } sticky_bit.wrapping_neg_assign(); // Now the result is [a1, a0, sticky_bit]. Since x_1 has its most significant bit set, // we can have an exponent decrease of at most one if a1 < LIMB_HIGH_BIT { // shift [a1, a0] left by 1 bit a1 = (a1 << 1) | (a0 >> WIDTH_M1); assert!(a1 >= LIMB_HIGH_BIT); a0 = (a0 << 1) | (sticky_bit >> WIDTH_M1); sticky_bit <<= 1; x_exp.saturating_sub_assign(1); } ( a0, a1, sticky_bit & !LIMB_HIGH_BIT, sticky_bit & LIMB_HIGH_BIT, neg, ) } else { // ``` // | a1 | a0 | // | x_1 | x_0 | // | y_1 | y_0 | // ``` let tst = y_1 == LIMB_HIGH_BIT && y_0 == 0; // if exp_diff = Limb::WIDTH * 2 and tst = 1, y = 1 / 2 * ulp(x) if x_1 > LIMB_HIGH_BIT || x_0 > 0 { let g = exp_diff > TWICE_WIDTH; let mut diff_1 = x_1; if x_0 == 0 { diff_1.wrapping_sub_assign(1); } // no borrow in x - ulp(x) ( x_0.wrapping_sub(1), diff_1, Limb::from(g || !tst), Limb::from(g || tst), neg, ) } else { // x = 1000...000, thus subtracting y yields an exponent shift x_exp.saturating_sub_assign(1); if exp_diff == TWICE_WIDTH && !tst { // y > 1 / 2 * ulp(x) let mut t = y_1.wrapping_neg(); if y_0 != 0 { t.wrapping_sub_assign(1); } // The rounding bit is the 2nd most-significant bit of t (where the most // significant bit of t is necessarily 0), and the sticky bit is formed by the // remaining bits of t, and those from -y_0. ( NEG_TWO, Limb::MAX, (t << 2) | y_0, Limb::from(t >= HALF_LIMB_HIGH_BIT), neg, ) } else { // y <= 1 / 2 * ulp(x) let g = exp_diff > TWICE_WIDTH_P1; ( NEG_ONE, NEG_ONE, Limb::from(g || (exp_diff == TWICE_WIDTH_P1 && !tst)), Limb::from(g || (exp_diff == TWICE_WIDTH_P1 && tst)), neg, ) } } } }; if round_bit == 0 && sticky_bit == 0 { (diff_0, diff_1, x_exp, Equal, neg) } else { if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (diff_0 & 1) == 0) { (diff_0, diff_1, x_exp, Less, neg) } else if diff_0.overflowing_add_assign(1) && diff_1.overflowing_add_assign(1) { (diff_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff_0, diff_1, x_exp, Greater, neg) } } Floor | Down => (diff_0, diff_1, x_exp, Less, neg), Ceiling | Up => { if diff_0.overflowing_add_assign(1) && diff_1.overflowing_add_assign(1) { (diff_0, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg) } else { (diff_0, diff_1, x_exp, Greater, neg) } } } } } // This is mpfr_sub1sp3 from add1sp.c, MPFR 4.2.0. fn sub_float_significands_same_prec_gt_2w_lt_3w( mut x_0: Limb, mut x_1: Limb, mut x_2: Limb, mut x_exp: i32, mut y_0: Limb, mut y_1: Limb, mut y_2: Limb, mut y_exp: i32, prec: u64, mut rm: RoundingMode, ) -> (Limb, Limb, Limb, i32, Ordering, bool) { let (mut diff_0, mut diff_1, mut diff_2, sticky_bit, round_bit, shift_bit, neg) = if x_exp == y_exp { let (mut a0, overflow_1) = x_0.overflowing_sub(y_0); let (mut a1, overflow_2) = x_1.overflowing_sub(y_1); if overflow_1 { a1.wrapping_sub_assign(1); } // A borrow is generated for diff when either x_1 < y_1 or x_1 = y_1 and x_0 < y_0. let mut a2 = x_2.wrapping_sub(y_2); if overflow_2 || x_1 == y_1 && overflow_1 { a2.wrapping_sub_assign(1); } let neg = if a2 == 0 && a1 == 0 && a0 == 0 { return (0, 0, 0, 0, Equal, false); } else if a2 >= x_2 { // a = x - y mod 2 ^ (3 * Limb::WIDTH) let overflow_1 = a0.overflowing_neg_assign(); a1.wrapping_neg_assign(); if overflow_1 { a1.wrapping_sub_assign(1); } a2.wrapping_neg_assign(); if overflow_1 || a1 != 0 { a2.wrapping_sub_assign(1); } true } else { false }; if a2 == 0 { a2 = a1; a1 = a0; a0 = 0; x_exp.saturating_sub_assign(IWIDTH); if a2 == 0 { a2 = a1; a1 = 0; x_exp.saturating_sub_assign(IWIDTH); } } assert_ne!(a2, 0); let leading_zeros = LeadingZeros::leading_zeros(a2); if leading_zeros != 0 { x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); let comp_zeros = Limb::WIDTH - leading_zeros; ( a0 << leading_zeros, (a1 << leading_zeros) | (a0 >> comp_zeros), (a2 << leading_zeros) | (a1 >> comp_zeros), 0, 0, 0, neg, ) } else { (a0, a1, a2, 0, 0, 0, neg) } } else { let neg = x_exp < y_exp; if neg { swap(&mut x_exp, &mut y_exp); swap(&mut x_0, &mut y_0); swap(&mut x_1, &mut y_1); swap(&mut x_2, &mut y_2); } let exp_diff = u64::exact_from(x_exp - y_exp); let shift = THRICE_WIDTH - prec; let shift_bit = Limb::power_of_2(shift); let mask = shift_bit - 1; if exp_diff < Limb::WIDTH { // Warning: we must have the most significant bit of sticky_bit correct since it might // become the round bit below let comp_diff = Limb::WIDTH - exp_diff; let mut sticky_bit = y_0 << comp_diff; let (mut a0, overflow) = x_0.overflowing_sub((y_1 << comp_diff) | (y_0 >> exp_diff)); let mut a1 = x_1.wrapping_sub((y_2 << comp_diff) | (y_1 >> exp_diff)); if overflow { a1.wrapping_sub_assign(1); } let carry = a1 > x_1 || (a1 == x_1 && overflow); let mut a2 = x_2.wrapping_sub(y_2 >> exp_diff); if carry { a2.wrapping_sub_assign(1); } // if sticky_bit is non-zero, subtract 1 from a2, a1, a0 since we want a non-negative // neglected part if sticky_bit != 0 { if a1 == 0 && a0 == 0 { a2.wrapping_sub_assign(1); } if a0 == 0 { a1.wrapping_sub_assign(1); } a0.wrapping_sub_assign(1); // a = a2, a1, a0 cannot become zero here, since: // - if exp_diff >= 2, then a2 >= 2 ^ (w - 1) - (2 ^ (w - 2) - 1) with w = // Limb::WIDTH, thus a2 - 1 >= 2 ^ (w - 2), // - if exp_diff = 1, then since prec < 3 * Limb::WIDTH we have sticky_bit = 0. assert!(a2 > 0 || a1 > 0 || a0 > 0); // 2 ^ Limb::WIDTH - sticky_bit sticky_bit.wrapping_neg_assign(); } if a2 == 0 { // this implies exp_diff = 1, which in turn implies sticky_bit = 0 assert_eq!(sticky_bit, 0); a2 = a1; a1 = a0; a0 = 0; // since sticky_bit = 0 already, no need to set it to 0 x_exp.saturating_sub_assign(IWIDTH); if a2 == 0 { a2 = a1; a1 = 0; x_exp.saturating_sub_assign(IWIDTH); } } assert_ne!(a2, 0); let leading_zeros = LeadingZeros::leading_zeros(a2); let (diff_1, diff_2) = if leading_zeros != 0 { let comp_zeros = Limb::WIDTH - leading_zeros; let diff_1 = (a1 << leading_zeros) | (a0 >> comp_zeros); a0 = (a0 << leading_zeros) | (sticky_bit >> comp_zeros); sticky_bit <<= leading_zeros; x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); (diff_1, (a2 << leading_zeros) | (a1 >> comp_zeros)) } else { (a1, a2) }; // shift > 0 since prec < 2 * Limb::WIDTH assert_ne!(shift, 0); let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, diff_1, diff_2, sticky_bit | (a0 & mask) ^ round_bit, round_bit, shift_bit, neg, ) } else if exp_diff < TWICE_WIDTH { // Warning: we must have the most significant bit of sticky_bit correct since it might // become the round bit below let comp_diff = exp_diff - Limb::WIDTH; let (mut sticky_bit, y0shifted) = if exp_diff == Limb::WIDTH { (y_0, y_1) } else { let comp_diff_2 = TWICE_WIDTH - exp_diff; let mut sticky_bit = y_1 << comp_diff_2; if y_0 != 0 { sticky_bit |= 1; } (sticky_bit, (y_2 << comp_diff_2) | (y_1 >> comp_diff)) }; let (mut a0, overflow) = x_0.overflowing_sub(y0shifted); let mut a1 = x_1.wrapping_sub(y_2 >> comp_diff); if overflow { a1.wrapping_sub_assign(1); } let mut a2 = x_2; if a1 > x_1 || (a1 == x_1 && overflow) { a2.wrapping_sub_assign(1); } // if sticky_bit is non-zero, subtract 1 from a2, a1, a0 since we want a non-negative // neglected part if sticky_bit != 0 { if a1 == 0 && a0 == 0 { a2.wrapping_sub_assign(1); } if a0 == 0 { a1.wrapping_sub_assign(1); } a0.wrapping_sub_assign(1); // a = a2, a1, a0 cannot become zero here, since: // - if exp_diff >= 2, then a2 >= 2 ^ (w - 1) - (2 ^ (w - 2) - 1) with w = // Limb::WIDTH, thus a2 - 1 >= 2 ^ (w - 2), // - if exp_diff = 1, then since p < 3 * Limb::WIDTH we have sticky_bit = 0. assert!(a2 > 0 || a1 > 0 || a0 > 0); // 2 ^ Limb::WIDTH - sticky_bit sticky_bit.wrapping_neg_assign(); } // since x_2 has its most significant bit set, we can have an exponent decrease of at // most one let (diff_1, diff_2) = if a2 < LIMB_HIGH_BIT { let diff_1 = (a1 << 1) | (a0 >> WIDTH_M1); a0 = (a0 << 1) | (sticky_bit >> WIDTH_M1); sticky_bit <<= 1; x_exp.saturating_sub_assign(1); (diff_1, (a2 << 1) | (a1 >> WIDTH_M1)) } else { (a1, a2) }; let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, diff_1, diff_2, sticky_bit | (a0 & mask) ^ round_bit, round_bit, shift_bit, neg, ) } else if exp_diff < THRICE_WIDTH { // warning: we must have the most significant bit of sticky_bit correct since it might // become the round bit below let mut sticky_bit; if exp_diff == TWICE_WIDTH { sticky_bit = y_1; if y_0 != 0 { sticky_bit |= 1; } } else { sticky_bit = y_2 << (THRICE_WIDTH - exp_diff); if y_1 != 0 || y_0 != 0 { sticky_bit |= 1; } }; let overflow = sticky_bit.overflowing_neg_assign(); let mut a0 = x_0.wrapping_sub(y_2 >> (exp_diff - TWICE_WIDTH)); if overflow { a0.wrapping_sub_assign(1); } let mut a1 = x_1; if a0 > x_0 || (a0 == x_0 && overflow) { a1.wrapping_sub_assign(1); } let mut a2 = x_2; if a1 > x_1 { a2.wrapping_sub_assign(1); } let (diff_1, diff_2) = if a2 < LIMB_HIGH_BIT { let diff_1 = (a1 << 1) | (a0 >> WIDTH_M1); a0 = (a0 << 1) | (sticky_bit >> WIDTH_M1); sticky_bit <<= 1; x_exp.saturating_sub_assign(1); (diff_1, (a2 << 1) | (a1 >> WIDTH_M1)) } else { (a1, a2) }; let round_bit = a0 & (shift_bit >> 1); ( a0 & !mask, diff_1, diff_2, sticky_bit | (a0 & mask) ^ round_bit, round_bit, shift_bit, neg, ) } else { // We compute x - ulp(x), and the remainder ulp(x) - y satisfies: 1/2 ulp(x) < ulp(x) - // y < ulp(x), thus round_bit = sticky_bit = 1. let (a0, overflow) = x_0.overflowing_sub(shift_bit); let mut a1 = x_1; if overflow { a1.wrapping_sub_assign(1); } let mut a2 = x_2; if a1 > x_1 { a2.wrapping_sub_assign(1); } if a2 < LIMB_HIGH_BIT { // - necessarily we had b = 1000...000 // - Warning: since we have an exponent decrease, when prec = Limb::WIDTH * 3 - 1 // and exp_diff = Limb::WIDTH * 3, the round bit corresponds to the upper bit of // -y. In that case round_bit = 0 and sticky_bit = 1, except when y = 1000...000 // where round_bit = 1 and sticky_bit = 0. // - sticky_bit = 1 below is incorrect when prec = Limb::WIDTH * 2 - 1, exp_diff = // Limb::WIDTH * 2 and y = 1000...000, but in that case the even rule wound round // up too. x_exp.saturating_sub_assign(1); ( !mask, Limb::MAX, Limb::MAX, 1, Limb::from( shift > 1 || exp_diff > THRICE_WIDTH || (y_2 == LIMB_HIGH_BIT && y_1 == 0 && y_0 == 0), ), shift_bit, neg, ) } else { (a0, a1, a2, 1, 1, shift_bit, neg) } } }; if round_bit == 0 && sticky_bit == 0 { (diff_0, diff_1, diff_2, x_exp, Equal, neg) } else { if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if round_bit == 0 || (sticky_bit == 0 && (diff_0 & shift_bit) == 0) { (diff_0, diff_1, diff_2, x_exp, Less, neg) } else { if diff_0.overflowing_add_assign(shift_bit) { diff_1.wrapping_add_assign(1); } if diff_1 == 0 && diff_0 == 0 { diff_2.wrapping_add_assign(1); } if diff_2 == 0 { ( diff_0, diff_1, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg, ) } else { (diff_0, diff_1, diff_2, x_exp, Greater, neg) } } } Floor | Down => (diff_0, diff_1, diff_2, x_exp, Less, neg), Ceiling | Up => { if diff_0.overflowing_add_assign(shift_bit) { diff_1.wrapping_add_assign(1); } if diff_1 == 0 && diff_0 == 0 { diff_2.wrapping_add_assign(1); } if diff_2 == 0 { ( diff_0, diff_1, LIMB_HIGH_BIT, x_exp.saturating_add(1), Greater, neg, ) } else { (diff_0, diff_1, diff_2, x_exp, Greater, neg) } } } } } // Equivalent to shifting xs left by 1, then calling limbs_sub_same_length_to_out. fn limbs_sub_shl1_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); let mut carry = 0; let mut remaining_xs_bits = 0; for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { let shifted_x = (x << 1) | remaining_xs_bits; remaining_xs_bits = x >> WIDTH_M1; (*out, carry) = sub_with_carry(shifted_x, y, carry); } } // Equivalent to shifting ys right by `bits`, anding the least-significant limb with `ys0_and`, and // then calling limbs_sub_same_length_to_out. fn limbs_sub_shr_same_length_to_out_and_ys0( out: &mut [Limb], xs: &[Limb], ys: &[Limb], bits: u64, ys0_and: Limb, ) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(bits < Limb::WIDTH); assert!(out.len() >= len); let mut carry = 0; let comp_bits = Limb::WIDTH - bits; for i in 0..len { let mut shifted_y = (ys[i] >> bits) | (ys.get(i + 1).unwrap_or(&0) << comp_bits); if i == 0 { shifted_y &= ys0_and; } (out[i], carry) = sub_with_carry(xs[i], shifted_y, carry); } } // Equivalent to shifting ys right by `bits`, anding the least-significant limb with `ys0_and`, and // then calling limbs_sub_same_length_to_out. Also allows ys to be shorter than xs, and pretends // that the missing ys limbs are zeros. fn limbs_sub_shr_greater_to_out_and_ys0( out: &mut [Limb], xs: &[Limb], ys: &[Limb], bits: u64, ys0_and: Limb, ) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); assert!(bits < Limb::WIDTH); assert!(out.len() >= xs_len); let comp_bits = Limb::WIDTH - bits; let mut carry = 0; for i in 0..xs_len { let mut shifted_y = if let Some(y) = ys.get(i) { (y >> bits) | (ys.get(i + 1).unwrap_or(&0) << comp_bits) } else { 0 }; if i == 0 { shifted_y &= ys0_and; } (out[i], carry) = sub_with_carry(xs[i], shifted_y, carry); } } // Equivalent to replacing ys[0] with something else, then calling limbs_sub_same_length_to_out. // Also allows ys to be shorter than xs, and pretends that the missing ys limbs are zeros. fn limbs_sub_greater_to_out_different_ys0(out: &mut [Limb], xs: &[Limb], ys: &[Limb], ys0: Limb) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); assert!(out.len() >= xs_len); let mut carry = 0; let mut first = true; for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { (*out, carry) = if first { first = false; sub_with_carry(x, ys0, carry) } else { sub_with_carry(x, y, carry) }; } if carry != 0 { limbs_sub_limb_to_out(&mut out[ys_len..], &xs[ys_len..], 1); } else { out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); } } fn cmp_size_helper( xs: &[Limb], x_exp: i32, ys: &[Limb], y_exp: i32, prec: u64, ) -> (usize, usize, bool) { let n = bit_to_limb_count_ceiling(prec); let nm1 = n - 1; let mut k = nm1; let neg = match x_exp.cmp(&y_exp) { Equal => { // Check mantissa since exponents are equal let mut x_y_equal = false; while xs[k] == ys[k] { if k == 0 { x_y_equal = true; break; } k -= 1; } // If !x_y_equal, k is the largest integer < n such that xs[k] != ys[k] if x_y_equal { return (0, 0, false); } xs[k] < ys[k] } Less => true, Greater => false, }; (n, k, neg) } fn sub_float_significands_same_prec_ge_3w_ref_ref<'a>( out: &mut [Limb], mut xs: &'a [Limb], mut x_exp: i32, mut ys: &'a [Limb], mut y_exp: i32, prec: u64, mut rm: RoundingMode, ) -> (i32, Ordering, bool) { let (n, mut k, neg) = cmp_size_helper(xs, x_exp, ys, y_exp, prec); if n == 0 { // x == y. Return exact number 0. Setting the most-significant limb to 0 is a sufficient // signal to the caller that the entire output is 0, since in every other case the precision // of the output is the same as the precision of the inputs, and the most-significant limb // is therefore nonzero. *out.last_mut().unwrap() = 0; return (0, Equal, false); } let nm1 = n - 1; if neg { swap(&mut x_exp, &mut y_exp); swap(&mut xs, &mut ys); } let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; // round_bit_2 is the next bit after the round bit, and sticky_bit_2 the corresponding sticky // bit. let mut round_bit_2; let mut sticky_bit_2; let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let mut goto_exact_normalize = false; let mut goto_sub_d1_no_lose = false; let mut goto_sub_d1_lose = false; let mut limb = 0; loop { // loop for ExactNormalize, SubD1NoLose, and SubD1Lose if !goto_sub_d1_no_lose && !goto_sub_d1_lose && (exp_diff == 0 || goto_exact_normalize) { // ``` // <-- x --> // <-- y --> : exact sub // ``` if !goto_exact_normalize { limbs_sub_same_length_to_out(out, xs, ys); } // label ExactNormalize: limb = out[nm1]; if limb != 0 { // First limb is not zero. let leading_zeros = LeadingZeros::leading_zeros(limb); // Warning: leading_zeros can be 0 when we come from the case SubD1Lose with // ExactNormalize if leading_zeros != 0 { limbs_slice_shl_in_place(out, leading_zeros); x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); } // Last limb should be OK assert_eq!(out[0] & (shift_bit - 1), 0); } else { // - First limb is zero: this can only occur for n >= 2 // - Find the first limb not equal to zero. It necessarily exists since |x| > |y|. // We know that xs[k] > ys[k] and all upper limbs are equal. while out[k] == 0 { k -= 1; } limb = out[k]; // out[k] is the non-zero limb of largest index, thus we have to consider the k + 1 // least-significant limbs assert_ne!(limb, 0); let leading_zeros = LeadingZeros::leading_zeros(limb); k += 1; let len = n - k; // Number of most significant zero limbs assert_ne!(k, 0); if leading_zeros != 0 { limbs_slice_shl_in_place(&mut out[..k], leading_zeros); } out.copy_within(0..k, len); slice_set_zero(&mut out[..len]); x_exp = i32::saturating_from( i128::from(x_exp) - (i128::from(leading_zeros) + (i128::wrapping_from(len) << Limb::LOG_WIDTH)), ); // out[len] should have its low bits zero: it is x[0] - y[0]. assert_eq!(out[len] & Limb::wrapping_from(shift), 0); } // No rounding is necessary since the result is exact assert!(out[nm1].get_highest_bit()); return (x_exp, Equal, neg); } else if exp_diff == 1 || goto_sub_d1_no_lose || goto_sub_d1_lose { // ``` // | <-- x --> // | <-- y --> // ``` if !goto_sub_d1_no_lose && !goto_sub_d1_lose { // If we lose at least one bit, compute 2 * x - y (exact), else compute x - y / 2 limb = xs[k] - (ys[k] >> 1); } // Let W = 2 ^ Limb::WIDTH: we have |x| - |y| >= limb * W ^ k - (2 * W ^ k - 1) / 2 >= // limb // * W ^ k - W ^ k + 1 / 2. Thus, if limb > W / 2, |x| - |y| >= 1 / 2 * W ^ n. Moreover, // if // trunc(|y|) represents the first prec - 1 bits of |y|, minus the last significant bit // called y0 below (in fact y0 is that bit shifted by `shift` bits), then we have // |x|-trunc(|y|) >= 1 / 2 * W ^ n + 1, thus the two limbs_sub calls below necessarily // yield out > 1 / 2 * W ^ n. if !goto_sub_d1_lose && (limb > LIMB_HIGH_BIT || goto_sub_d1_no_lose) { // - case limb > W / 2 // - The exponent cannot decrease: compute x - y / 2. // - Shift y in the allocated temporary block // // label SubD1NoLose: let y0 = ys[0] & shift_bit; let mask = shift_bit - 1; // Zero last bit of y if set limbs_sub_shr_same_length_to_out_and_ys0(out, xs, ys, 1, !mask); assert!(out[nm1].get_highest_bit()); if y0 == 0 { // Result is exact: no need of rounding! return (x_exp, Equal, neg); } // - y0 is non-zero, thus we have to subtract 1 / 2 * ulp(out). // - However, we know (see analysis above) that this cannot make the exponent // decrease. // - Check last bits assert_eq!(out[0] & mask, 0); // - No normalization is needed // - Rounding is necessary since y0 is non-zero // - We have to subtract 1 at the round bit position, and 0 for the lower bits round_bit = 1; round_bit_2 = 0; sticky_bit_2 = 0; } else if limb < LIMB_HIGH_BIT || goto_sub_d1_lose { // - |x| - |y| <= (W / 2 - 1) * W ^ k + W ^ k - 1 = 1 / 2 * W ^ n - 1 // - The exponent decreases by one. // - Compute 2 * x - y (Exact) // // label SubD1Lose: goto_sub_d1_lose = false; limbs_sub_shl1_same_length_to_out(out, xs, ys); x_exp.saturating_sub_assign(1); assert_eq!(k, nm1); goto_exact_normalize = true; continue; } else { // - Case: limb = 100000000000 // - Check while b[l] == y'[l] (Y' is Y shifted by 1) // - If x[l] < y'[l] => We lose at least one bit // - If x[l] > y'[l] => We don't lose any bit // - If l == -1 => We don't lose any bit AND the result is 100000000000 0000000000 // 00000000000 let mut l = n; let mut yl_shifted; loop { // The first loop will compare x[n - 2] and y'[n - 2] yl_shifted = ys[l - 1] << WIDTH_M1; l -= 1; if l == 0 { break; } yl_shifted += ys[l - 1] >> 1; if xs[l - 1] != yl_shifted { break; } } if l == 0 { if yl_shifted != 0 { // Since yl_shifted is what should be subtracted from out[-1], if non-zero // then necessarily the precision is a multiple of Limb::WIDTH, and we lose // one bit, thus the (exact) result is a power of 2 minus 1. for o in out.iter_mut() { *o = Limb::MAX; } x_exp.saturating_sub_assign(1); } else { // yl_shifted = 0: result is a power of 2. let (out_last, out_init) = out.split_last_mut().unwrap(); slice_set_zero(out_init); *out_last = LIMB_HIGH_BIT; } // No Normalize is needed, no Rounding is needed return (x_exp, Equal, neg); } else if xs[l - 1] > yl_shifted { // - cl_shifted is the shifted value c'[l] // - |x| - |y| >= 1 / 2 * W ^ n // // goto SubD1NoLose; goto_sub_d1_no_lose = true; } else { // We cannot have xs[l] = yl_shifted since the only way we can exit the while // loop above is when xs[l] != yl_shifted or l < 0, and the case l < 0 was // already treated above. assert!(xs[l - 1] < yl_shifted); // |x| - |y| <= 1 / 2 * W ^ n - 1 and is exact goto_sub_d1_lose = true; } continue; } } else if exp_diff >= prec { // The difference of exponents is larger than the precision of all operands, thus the // result is either x or x - 1 ulp, with a possible exact result when x = prec, x = 2 ^ // e and y = 1 / 2 * ulp(x) // // - We can't set OUT before since we use ys for rounding... // - Perform rounding: check if out = b or out = x - ulp(x) if exp_diff == prec { // since y is normalized, we need to subtract 1 / 2 * ulp(x) round_bit = 1; // round_bit_2 is the bit of weight 1 / 4 * ulp(x) in y. We assume a limb has at // least 2 bits. If the precision is 1, we read in the unused bits, which should be // zero, and this is what we want. round_bit_2 = ys[nm1] & HALF_LIMB_HIGH_BIT; // We also need sticky_bit_2 sticky_bit_2 = ys[nm1] & WIDTH_M2_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit = 0; if exp_diff == prec + 1 { round_bit_2 = 1; sticky_bit_2 = ys[nm1] & WIDTH_M1_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit_2 = 0; sticky_bit_2 = 1; // since C is non-zero } } // Copy mantissa X in OUT out.copy_from_slice(xs); } else { // case 2 <= exp_diff < prec // // Compute round_bit = Cp and sticky_bit = C'p + 1 // // Compute round_bit and round_bit_2 from Y The round bit is bit prec - exp_diff in Y, // assuming the most significant bit of Y is bit 0 let x = prec - exp_diff; let mut kx = nm1 - bit_to_limb_count_floor(x); let mut sx_bit = Limb::power_of_2(WIDTH_M1 - (x & Limb::WIDTH_MASK)); // the round bit is in ys[kx], at position sx assert!(prec >= exp_diff); round_bit = ys[kx] & sx_bit; // Now compute rxx: since exp_diff >= 2 it always exists in Y sx_bit = if sx_bit == 1 { // rxx is in the next limb kx = kx.checked_sub(1).unwrap(); LIMB_HIGH_BIT } else { // round_bit and round_bit_2 are in the same limb sx_bit >> 1 }; round_bit_2 = ys[kx] & sx_bit; // Now look at the remaining low bits of Y to determine sticky_bit_2 sticky_bit_2 = ys[kx] & (sx_bit - 1); while sticky_bit_2 == 0 && kx > 0 { kx -= 1; sticky_bit_2 = ys[kx]; } // Clean shifted Y' let mask = shift_bit - 1; let dm = exp_diff & Limb::WIDTH_MASK; let m = bit_to_limb_count_floor(exp_diff); if dm == 0 { assert_ne!(m, 0); // - dm = 0 and m > 0: Just copy // - Subtract the mantissa y from x in out limbs_sub_greater_to_out_different_ys0(out, xs, &ys[m..], ys[m] & !mask); } else if m == 0 { // dm >=2 and m == 0: just shift assert!(dm >= 2); // Subtract the mantissa y from x in out limbs_sub_shr_same_length_to_out_and_ys0(out, xs, ys, dm, !mask); } else { // - dm > 0 and m > 0: shift and zero // - Subtract the mantissa y from x in out limbs_sub_shr_greater_to_out_and_ys0(out, xs, &ys[m..], dm, !mask); } // Normalize: we lose at most one bit if !out[nm1].get_highest_bit() { // - High bit is not set and we have to fix it. // - OUT >= 010000xxx001 limbs_slice_shl_in_place(out, 1); // OUT >= 100000xxx010 if round_bit != 0 { // - Check if Y = -1 // - Since Y == -1, we have to subtract one more limbs_sub_limb_in_place(out, shift_bit); assert!(out[nm1].get_highest_bit()); } // - OUT >= 10000xxx001 // - Final exponent -1 since we have shifted the mantissa x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; // We don't have anymore a valid Yp + 1, but since Oyr >= 100000xxx001, the final // sub can't unnormalize. } assert_eq!(out[0] & mask, 0); } // only loop when emulating gotos break; } let mut out_power_of_2; loop { // At this point out contains x - high(y), normalized, and we have to subtract round_bit * // 1/2 ulp(out), round_bit_2 * 1/4 ulp(out), and sticky_bit_2 * 1/8 ulp(out), interpreting // round_bit/round_bit_2/sticky_bit_2 as 1 if non-zero. sticky_bit = round_bit_2 | sticky_bit_2; if round_bit == 0 && sticky_bit == 0 { return (x_exp, Equal, neg); } out_power_of_2 = limbs_is_power_of_2(out); if out_power_of_2 && round_bit != 0 { limbs_sub_limb_in_place(out, shift_bit); out[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; sticky_bit_2 = 0; } else { break; } } // Now if out is a power of two, necessary round_bit = 0, which means the exact result is always // in (pred(out), out), and the bounds cannot be attained if neg { rm.neg_assign(); } match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if out_power_of_2 { assert_eq!(round_bit, 0); // Since we are at the end of the binade, we have in fact round_bit = round_bit_2 // and sticky_bit = sticky_bit_2 round_bit = round_bit_2; sticky_bit = sticky_bit_2; } if (prec == 1 || out[0] & shift_bit == 0 || round_bit == 0) && (sticky_bit == 0 || round_bit == 0) { (x_exp, Greater, neg) } else { limbs_sub_limb_in_place(out, shift_bit); if out_power_of_2 { // deal with cancellation out[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less, neg) } } Floor | Down => { limbs_sub_limb_in_place(out, shift_bit); if out_power_of_2 { // deal with cancellation out[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less, neg) } Ceiling | Up => (x_exp, Greater, neg), } } // Equivalent to shifting xs left by 1, then calling limbs_sub_same_length_to_out. fn limbs_sub_shl1_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); let mut carry = 0; let mut remaining_xs_bits = 0; for (x, &y) in xs.iter_mut().zip(ys.iter()) { let shifted_x = (*x << 1) | remaining_xs_bits; remaining_xs_bits = *x >> WIDTH_M1; (*x, carry) = sub_with_carry(shifted_x, y, carry); } } // Equivalent to shifting ys right by `bits`, anding the least-significant limb with `ys0_and`, and // then calling limbs_sub_same_length_in_place_left. fn limbs_sub_shr_same_length_in_place_left_and_ys0( xs: &mut [Limb], ys: &[Limb], bits: u64, ys0_and: Limb, ) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(bits < Limb::WIDTH); let mut carry = 0; let comp_bits = Limb::WIDTH - bits; for i in 0..len { let mut shifted_y = (ys[i] >> bits) | (ys.get(i + 1).unwrap_or(&0) << comp_bits); if i == 0 { shifted_y &= ys0_and; } (xs[i], carry) = sub_with_carry(xs[i], shifted_y, carry); } } // Equivalent to shifting ys right by `bits`, anding the least-significant limb with `ys0_and`, and // then calling limbs_sub_same_length_in_place_left. Also allows ys to be shorter than xs, and // pretends that the missing ys limbs are zeros. fn limbs_sub_shr_greater_in_place_left_and_ys0( xs: &mut [Limb], ys: &[Limb], bits: u64, ys0_and: Limb, ) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); assert!(bits < Limb::WIDTH); let comp_bits = Limb::WIDTH - bits; let mut carry = 0; for (i, x) in xs.iter_mut().enumerate() { let mut shifted_y = if let Some(y) = ys.get(i) { (y >> bits) | (ys.get(i + 1).unwrap_or(&0) << comp_bits) } else { 0 }; if i == 0 { shifted_y &= ys0_and; } (*x, carry) = sub_with_carry(*x, shifted_y, carry); } } // Equivalent to replacing ys[0] with something else, then calling // limbs_sub_same_length_in_place_left. Also allows ys to be shorter than xs, and pretends that the // missing ys limbs are zeros. fn limbs_sub_greater_in_place_left_different_ys0(xs: &mut [Limb], ys: &[Limb], ys0: Limb) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); let mut carry = 0; let mut first = true; for (x, &y) in xs.iter_mut().zip(ys.iter()) { (*x, carry) = if first { first = false; sub_with_carry(*x, ys0, carry) } else { sub_with_carry(*x, y, carry) }; } if carry != 0 { limbs_sub_limb_in_place(&mut xs[ys_len..], 1); } } fn sub_float_significands_same_prec_ge_3w_val_val<'a>( mut xs: &'a mut [Limb], mut x_exp: i32, mut ys: &'a mut [Limb], mut y_exp: i32, prec: u64, mut rm: RoundingMode, ) -> (i32, Ordering, bool) { let (n, _, neg) = cmp_size_helper(xs, x_exp, ys, y_exp, prec); if n == 0 { // x == y. Return exact number 0. Setting the most-significant limb to 0 is a sufficient // signal to the caller that the entire output is 0, since in every other case the precision // of the output is the same as the precision of the inputs, and the most-significant limb // is therefore nonzero. *xs.last_mut().unwrap() = 0; return (0, Equal, false); } if neg { rm.neg_assign(); swap(&mut x_exp, &mut y_exp); swap(&mut xs, &mut ys); } let (exp, o) = sub_float_significands_same_prec_ge_3w_val_ref_helper(xs, x_exp, ys, y_exp, prec, rm); (exp, o, neg) } fn sub_float_significands_same_prec_ge_3w_val_ref( xs: &mut [Limb], x_exp: i32, ys: &[Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering, bool) { let (n, _, neg) = cmp_size_helper(xs, x_exp, ys, y_exp, prec); if n == 0 { // x == y. Return exact number 0. Setting the most-significant limb to 0 is a sufficient // signal to the caller that the entire output is 0, since in every other case the precision // of the output is the same as the precision of the inputs, and the most-significant limb // is therefore nonzero. *xs.last_mut().unwrap() = 0; return (0, Equal, false); } if neg { let (exp, o) = sub_float_significands_same_prec_ge_3w_ref_val_helper(ys, y_exp, xs, x_exp, prec, -rm); (exp, o, true) } else { let (exp, o) = sub_float_significands_same_prec_ge_3w_val_ref_helper(xs, x_exp, ys, y_exp, prec, rm); (exp, o, false) } } fn sub_float_significands_same_prec_ge_3w_val_ref_helper( xs: &mut [Limb], mut x_exp: i32, ys: &[Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { let n = bit_to_limb_count_ceiling(prec); let nm1 = n - 1; let mut k = nm1; let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; // round_bit_2 is the next bit after the round bit, and sticky_bit_2 the corresponding sticky // bit. let mut round_bit_2; let mut sticky_bit_2; let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let mut goto_exact_normalize = false; let mut goto_sub_d1_no_lose = false; let mut goto_sub_d1_lose = false; let mut limb = 0; loop { // loop for ExactNormalize, SubD1NoLose, and SubD1Lose if !goto_sub_d1_no_lose && !goto_sub_d1_lose && (exp_diff == 0 || goto_exact_normalize) { // ``` // <-- x --> // <-- y --> : exact sub // ``` if !goto_exact_normalize { limbs_sub_same_length_in_place_left(xs, ys); } // label ExactNormalize: limb = xs[nm1]; if limb != 0 { // First limb is not zero. let leading_zeros = LeadingZeros::leading_zeros(limb); // Warning: leading_zeros can be 0 when we come from the case SubD1Lose with // ExactNormalize if leading_zeros != 0 { limbs_slice_shl_in_place(xs, leading_zeros); x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); } // Last limb should be OK assert_eq!(xs[0] & (shift_bit - 1), 0); } else { // - First limb is zero: this can only occur for n >= 2 // - Find the first limb not equal to zero. It necessarily exists since |x| > |y|. // We know that xs[k] > ys[k] and all upper limbs are equal. while xs[k] == 0 { k -= 1; } limb = xs[k]; // out[k] is the non-zero limb of largest index, thus we have to consider the k + 1 // least-significant limbs assert_ne!(limb, 0); let leading_zeros = LeadingZeros::leading_zeros(limb); k += 1; let len = n - k; // Number of most significant zero limbs assert_ne!(k, 0); if leading_zeros != 0 { limbs_slice_shl_in_place(&mut xs[..k], leading_zeros); } xs.copy_within(0..k, len); slice_set_zero(&mut xs[..len]); x_exp = i32::saturating_from( i128::from(x_exp) - (i128::from(leading_zeros) + (i128::wrapping_from(len) << Limb::LOG_WIDTH)), ); // out[len] should have its low bits zero: it is x[0] - y[0]. assert_eq!(xs[len] & Limb::wrapping_from(shift), 0); } // No rounding is necessary since the result is exact assert!(xs[nm1].get_highest_bit()); return (x_exp, Equal); } else if exp_diff == 1 || goto_sub_d1_no_lose || goto_sub_d1_lose { // ``` // | <-- x --> // | <-- y --> // ``` if !goto_sub_d1_no_lose && !goto_sub_d1_lose { // If we lose at least one bit, compute 2 * x - y (exact), else compute x - y / 2 limb = xs[k] - (ys[k] >> 1); } // Let W = 2 ^ Limb::WIDTH: we have |x| - |y| >= limb * W ^ k - (2 * W ^ k - 1) / 2 >= // limb // * W ^ k - W ^ k + 1 / 2. Thus, if limb > W / 2, |x| - |y| >= 1 / 2 * W ^ n. Moreover, // if // trunc(|y|) represents the first prec - 1 bits of |y|, minus the last significant bit // called y0 below (in fact y0 is that bit shifted by `shift` bits), then we have // |x|-trunc(|y|) >= 1 / 2 * W ^ n + 1, thus the two limbs_sub calls below necessarily // yield out > 1 / 2 * W ^ n. if !goto_sub_d1_lose && (limb > LIMB_HIGH_BIT || goto_sub_d1_no_lose) { // - case limb > W / 2 // - The exponent cannot decrease: compute x - y / 2. // - Shift y in the allocated temporary block // // label SubD1NoLose: let y0 = ys[0] & shift_bit; let mask = shift_bit - 1; // Zero last bit of y if set limbs_sub_shr_same_length_in_place_left_and_ys0(xs, ys, 1, !mask); assert!(xs[nm1].get_highest_bit()); if y0 == 0 { // Result is exact: no need of rounding! return (x_exp, Equal); } // - y0 is non-zero, thus we have to subtract 1 / 2 * ulp(out). // - However, we know (see analysis above) that this cannot make the exponent // decrease. // - Check last bits assert_eq!(xs[0] & mask, 0); // - No normalization is needed // - Rounding is necessary since y0 is non-zero // - We have to subtract 1 at the round bit position, and 0 for the lower bits round_bit = 1; round_bit_2 = 0; sticky_bit_2 = 0; } else if limb < LIMB_HIGH_BIT || goto_sub_d1_lose { // - |x| - |y| <= (W / 2 - 1) * W ^ k + W ^ k - 1 = 1 / 2 * W ^ n - 1 // - The exponent decreases by one. // - Compute 2 * x - y (Exact) // // label SubD1Lose: goto_sub_d1_lose = false; limbs_sub_shl1_same_length_in_place_left(xs, ys); x_exp.saturating_sub_assign(1); assert_eq!(k, nm1); goto_exact_normalize = true; continue; } else { // - Case: limb = 100000000000 // - Check while b[l] == y'[l] (Y' is Y shifted by 1) // - If x[l] < y'[l] => We lose at least one bit // - If x[l] > y'[l] => We don't lose any bit // - If l == -1 => We don't lose any bit AND the result is 100000000000 0000000000 // 00000000000 let mut l = n; let mut yl_shifted; loop { // The first loop will compare x[n - 2] and y'[n - 2] yl_shifted = ys[l - 1] << WIDTH_M1; l -= 1; if l == 0 { break; } yl_shifted += ys[l - 1] >> 1; if xs[l - 1] != yl_shifted { break; } } if l == 0 { if yl_shifted != 0 { // Since yl_shifted is what should be subtracted from out[-1], if non-zero // then necessarily the precision is a multiple of Limb::WIDTH, and we lose // one bit, thus the (exact) result is a power of 2 minus 1. for x in xs.iter_mut() { *x = Limb::MAX; } x_exp.saturating_sub_assign(1); } else { // yl_shifted = 0: result is a power of 2. let (xs_last, xs_init) = xs.split_last_mut().unwrap(); slice_set_zero(xs_init); *xs_last = LIMB_HIGH_BIT; } // No Normalize is needed, no Rounding is needed return (x_exp, Equal); } else if xs[l - 1] > yl_shifted { // - cl_shifted is the shifted value c'[l] // - |x| - |y| >= 1 / 2 * W ^ n // // goto SubD1NoLose; goto_sub_d1_no_lose = true; } else { // We cannot have xs[l] = yl_shifted since the only way we can exit the while // loop above is when xs[l] != yl_shifted or l < 0, and the case l < 0 was // already treated above. assert!(xs[l - 1] < yl_shifted); // |x| - |y| <= 1 / 2 * W ^ n - 1 and is exact goto_sub_d1_lose = true; } continue; } } else if exp_diff >= prec { // The difference of exponents is larger than the precision of all operands, thus the // result is either x or x - 1 ulp, with a possible exact result when x = prec, x = 2 ^ // e and y = 1 / 2 * ulp(x) // // - We can't set OUT before since we use ys for rounding... // - Perform rounding: check if out = b or out = x - ulp(x) if exp_diff == prec { // since y is normalized, we need to subtract 1 / 2 * ulp(x) round_bit = 1; // round_bit_2 is the bit of weight 1 / 4 * ulp(x) in y. We assume a limb has at // least 2 bits. If the precision is 1, we read in the unused bits, which should be // zero, and this is what we want. round_bit_2 = ys[nm1] & HALF_LIMB_HIGH_BIT; // We also need sticky_bit_2 sticky_bit_2 = ys[nm1] & WIDTH_M2_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit = 0; if exp_diff == prec + 1 { round_bit_2 = 1; sticky_bit_2 = ys[nm1] & WIDTH_M1_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit_2 = 0; sticky_bit_2 = 1; // since C is non-zero } } } else { // case 2 <= exp_diff < prec // // Compute round_bit = Cp and sticky_bit = C'p + 1 // // Compute round_bit and round_bit_2 from Y The round bit is bit prec - exp_diff in Y, // assuming the most significant bit of Y is bit 0 let x = prec - exp_diff; let mut kx = nm1 - bit_to_limb_count_floor(x); let mut sx_bit = Limb::power_of_2(WIDTH_M1 - (x & Limb::WIDTH_MASK)); // the round bit is in ys[kx], at position sx assert!(prec >= exp_diff); round_bit = ys[kx] & sx_bit; // Now compute rxx: since exp_diff >= 2 it always exists in Y sx_bit = if sx_bit == 1 { // rxx is in the next limb kx = kx.checked_sub(1).unwrap(); LIMB_HIGH_BIT } else { // round_bit and round_bit_2 are in the same limb sx_bit >> 1 }; round_bit_2 = ys[kx] & sx_bit; // Now look at the remaining low bits of Y to determine sticky_bit_2 sticky_bit_2 = ys[kx] & (sx_bit - 1); while sticky_bit_2 == 0 && kx > 0 { kx -= 1; sticky_bit_2 = ys[kx]; } // Clean shifted Y' let mask = shift_bit - 1; let dm = exp_diff & Limb::WIDTH_MASK; let m = bit_to_limb_count_floor(exp_diff); if dm == 0 { assert_ne!(m, 0); // - dm = 0 and m > 0: Just copy // - Subtract the mantissa y from x in out limbs_sub_greater_in_place_left_different_ys0(xs, &ys[m..], ys[m] & !mask); } else if m == 0 { // dm >=2 and m == 0: just shift assert!(dm >= 2); // Subtract the mantissa y from x in out limbs_sub_shr_same_length_in_place_left_and_ys0(xs, ys, dm, !mask); } else { // - dm > 0 and m > 0: shift and zero // - Subtract the mantissa y from x in out limbs_sub_shr_greater_in_place_left_and_ys0(xs, &ys[m..], dm, !mask); } // Normalize: we lose at most one bit if !xs[nm1].get_highest_bit() { // - High bit is not set and we have to fix it. // - OUT >= 010000xxx001 limbs_slice_shl_in_place(xs, 1); // OUT >= 100000xxx010 if round_bit != 0 { // - Check if Y = -1 // - Since Y == -1, we have to subtract one more limbs_sub_limb_in_place(xs, shift_bit); assert!(xs[nm1].get_highest_bit()); } // - OUT >= 10000xxx001 // - Final exponent -1 since we have shifted the mantissa x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; // We don't have anymore a valid Yp + 1, but since Oyr >= 100000xxx001, the final // sub can't unnormalize. } assert_eq!(xs[0] & mask, 0); } // only loop when emulating gotos break; } let mut out_power_of_2; loop { // At this point out contains x - high(y), normalized, and we have to subtract round_bit * // 1/2 ulp(out), round_bit_2 * 1/4 ulp(out), and sticky_bit_2 * 1/8 ulp(out), interpreting // round_bit/round_bit_2/sticky_bit_2 as 1 if non-zero. sticky_bit = round_bit_2 | sticky_bit_2; if round_bit == 0 && sticky_bit == 0 { return (x_exp, Equal); } out_power_of_2 = limbs_is_power_of_2(xs); if out_power_of_2 && round_bit != 0 { limbs_sub_limb_in_place(xs, shift_bit); xs[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; sticky_bit_2 = 0; } else { break; } } // Now if out is a power of two, necessary round_bit = 0, which means the exact result is always // in (pred(xs), xs), and the bounds cannot be attained match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if out_power_of_2 { assert_eq!(round_bit, 0); // Since we are at the end of the binade, we have in fact round_bit = round_bit_2 // and sticky_bit = sticky_bit_2 round_bit = round_bit_2; sticky_bit = sticky_bit_2; } if (prec == 1 || xs[0] & shift_bit == 0 || round_bit == 0) && (sticky_bit == 0 || round_bit == 0) { (x_exp, Greater) } else { limbs_sub_limb_in_place(xs, shift_bit); if out_power_of_2 { // deal with cancellation xs[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less) } } Floor | Down => { limbs_sub_limb_in_place(xs, shift_bit); if out_power_of_2 { // deal with cancellation xs[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less) } Ceiling | Up => (x_exp, Greater), } } // Equivalent to shifting xs left by 1, then calling limbs_sub_same_length_in_place_right. fn limbs_sub_shl1_same_length_in_place_right(xs: &[Limb], ys: &mut [Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); let mut carry = 0; let mut remaining_xs_bits = 0; for (&x, y) in xs.iter().zip(ys.iter_mut()) { let shifted_x = (x << 1) | remaining_xs_bits; remaining_xs_bits = x >> WIDTH_M1; (*y, carry) = sub_with_carry(shifted_x, *y, carry); } } // Equivalent to shifting ys right by `bits`, anding the least-significant limb with `ys0_and`, and // then calling limbs_sub_same_length_in_place_right. fn limbs_sub_shr_same_length_in_place_right_and_ys0( xs: &[Limb], ys: &mut [Limb], bits: u64, ys0_and: Limb, ) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(bits < Limb::WIDTH); let mut carry = 0; let comp_bits = Limb::WIDTH - bits; for i in 0..len { let mut shifted_y = (ys[i] >> bits) | (ys.get(i + 1).unwrap_or(&0) << comp_bits); if i == 0 { shifted_y &= ys0_and; } (ys[i], carry) = sub_with_carry(xs[i], shifted_y, carry); } } fn limbs_sub_shr_greater_in_place_right_and_ys0( xs: &[Limb], ys: &mut [Limb], bits: u64, ys0_and: Limb, m: usize, ) { let n = xs.len(); assert_ne!(n, 0); assert!(bits < Limb::WIDTH); let comp_bits = Limb::WIDTH - bits; let mut carry = 0; for i in 0..n { let mut shifted_y = if let Some(y) = ys.get(i + m) { (y >> bits) | (ys.get(i + m + 1).unwrap_or(&0) << comp_bits) } else { 0 }; if i == 0 { shifted_y &= ys0_and; } (ys[i], carry) = sub_with_carry(xs[i], shifted_y, carry); } } fn limbs_sub_greater_in_place_right_different_ys0( xs: &[Limb], ys: &mut [Limb], ys0: Limb, m: usize, ) { let mut carry = 0; for i in 0..xs.len() { (ys[i], carry) = sub_with_carry( xs[i], if i == 0 { ys0 } else { ys.get(i + m).copied().unwrap_or(0) }, carry, ); } } fn sub_float_significands_same_prec_ge_3w_ref_val_helper( xs: &[Limb], mut x_exp: i32, ys: &mut [Limb], y_exp: i32, prec: u64, rm: RoundingMode, ) -> (i32, Ordering) { let n = bit_to_limb_count_ceiling(prec); let nm1 = n - 1; let mut k = nm1; let exp_diff = u64::exact_from(x_exp - y_exp); let mut round_bit; let mut sticky_bit; // round_bit_2 is the next bit after the round bit, and sticky_bit_2 the corresponding sticky // bit. let mut round_bit_2; let mut sticky_bit_2; let shift = prec.neg_mod_power_of_2(Limb::LOG_WIDTH); let shift_bit = Limb::power_of_2(shift); let mut goto_exact_normalize = false; let mut goto_sub_d1_no_lose = false; let mut goto_sub_d1_lose = false; let mut limb = 0; loop { // loop for ExactNormalize, SubD1NoLose, and SubD1Lose if !goto_sub_d1_no_lose && !goto_sub_d1_lose && (exp_diff == 0 || goto_exact_normalize) { // ``` // <-- x --> // <-- y --> : exact sub // ``` if !goto_exact_normalize { limbs_sub_same_length_in_place_right(xs, ys); } // label ExactNormalize: limb = ys[nm1]; if limb != 0 { // First limb is not zero. let leading_zeros = LeadingZeros::leading_zeros(limb); // Warning: leading_zeros can be 0 when we come from the case SubD1Lose with // ExactNormalize if leading_zeros != 0 { limbs_slice_shl_in_place(ys, leading_zeros); x_exp.saturating_sub_assign(i32::wrapping_from(leading_zeros)); } // Last limb should be OK assert_eq!(ys[0] & (shift_bit - 1), 0); } else { // - First limb is zero: this can only occur for n >= 2 // - Find the first limb not equal to zero. It necessarily exists since |x| > |y|. // We know that xs[k] > ys[k] and all upper limbs are equal. while ys[k] == 0 { k -= 1; } limb = ys[k]; // out[k] is the non-zero limb of largest index, thus we have to consider the k + 1 // least-significant limbs assert_ne!(limb, 0); let leading_zeros = LeadingZeros::leading_zeros(limb); k += 1; let len = n - k; // Number of most significant zero limbs assert_ne!(k, 0); if leading_zeros != 0 { limbs_slice_shl_in_place(&mut ys[..k], leading_zeros); } ys.copy_within(0..k, len); slice_set_zero(&mut ys[..len]); x_exp = i32::saturating_from( i128::from(x_exp) - (i128::from(leading_zeros) + (i128::wrapping_from(len) << Limb::LOG_WIDTH)), ); // out[len] should have its low bits zero: it is x[0] - y[0]. assert_eq!(ys[len] & Limb::wrapping_from(shift), 0); } // No rounding is necessary since the result is exact assert!(ys[nm1].get_highest_bit()); return (x_exp, Equal); } else if exp_diff == 1 || goto_sub_d1_no_lose || goto_sub_d1_lose { // ``` // | <-- x --> // | <-- y --> // ``` if !goto_sub_d1_no_lose && !goto_sub_d1_lose { // If we lose at least one bit, compute 2 * x - y (exact), else compute x - y / 2 limb = xs[k] - (ys[k] >> 1); } // Let W = 2 ^ Limb::WIDTH: we have |x| - |y| >= limb * W ^ k - (2 * W ^ k - 1) / 2 >= // limb // * W ^ k - W ^ k + 1 / 2. Thus, if limb > W / 2, |x| - |y| >= 1 / 2 * W ^ n. Moreover, // if // trunc(|y|) represents the first prec - 1 bits of |y|, minus the last significant bit // called y0 below (in fact y0 is that bit shifted by `shift` bits), then we have // |x|-trunc(|y|) >= 1 / 2 * W ^ n + 1, thus the two limbs_sub calls below necessarily // yield out > 1 / 2 * W ^ n. if !goto_sub_d1_lose && (limb > LIMB_HIGH_BIT || goto_sub_d1_no_lose) { // - case limb > W / 2 // - The exponent cannot decrease: compute x - y / 2. // - Shift y in the allocated temporary block // // label SubD1NoLose: let y0 = ys[0] & shift_bit; let mask = shift_bit - 1; // Zero last bit of y if set limbs_sub_shr_same_length_in_place_right_and_ys0(xs, ys, 1, !mask); assert!(ys[nm1].get_highest_bit()); if y0 == 0 { // Result is exact: no need of rounding! return (x_exp, Equal); } // - y0 is non-zero, thus we have to subtract 1 / 2 * ulp(out). // - However, we know (see analysis above) that this cannot make the exponent // decrease. // - Check last bits assert_eq!(ys[0] & mask, 0); // - No normalization is needed // - Rounding is necessary since y0 is non-zero // - We have to subtract 1 at the round bit position, and 0 for the lower bits round_bit = 1; round_bit_2 = 0; sticky_bit_2 = 0; } else if limb < LIMB_HIGH_BIT || goto_sub_d1_lose { // - |x| - |y| <= (W / 2 - 1) * W ^ k + W ^ k - 1 = 1 / 2 * W ^ n - 1 // - The exponent decreases by one. // - Compute 2 * x - y (Exact) // // label SubD1Lose: goto_sub_d1_lose = false; limbs_sub_shl1_same_length_in_place_right(xs, ys); x_exp.saturating_sub_assign(1); assert_eq!(k, nm1); goto_exact_normalize = true; continue; } else { // - Case: limb = 100000000000 // - Check while b[l] == y'[l] (Y' is Y shifted by 1) // - If x[l] < y'[l] => We lose at least one bit // - If x[l] > y'[l] => We don't lose any bit // - If l == -1 => We don't lose any bit AND the result is 100000000000 0000000000 // 00000000000 let mut l = n; let mut yl_shifted; loop { // The first loop will compare x[n - 2] and y'[n - 2] yl_shifted = ys[l - 1] << WIDTH_M1; l -= 1; if l == 0 { break; } yl_shifted += ys[l - 1] >> 1; if xs[l - 1] != yl_shifted { break; } } if l == 0 { if yl_shifted != 0 { // Since yl_shifted is what should be subtracted from out[-1], if non-zero // then necessarily the precision is a multiple of Limb::WIDTH, and we lose // one bit, thus the (exact) result is a power of 2 minus 1. for o in ys.iter_mut() { *o = Limb::MAX; } x_exp.saturating_sub_assign(1); } else { // yl_shifted = 0: result is a power of 2. let (ys_last, ys_init) = ys.split_last_mut().unwrap(); slice_set_zero(ys_init); *ys_last = LIMB_HIGH_BIT; } // No Normalize is needed, no Rounding is needed return (x_exp, Equal); } else if xs[l - 1] > yl_shifted { // - cl_shifted is the shifted value c'[l] // - |x| - |y| >= 1 / 2 * W ^ n // // goto SubD1NoLose; goto_sub_d1_no_lose = true; } else { // We cannot have xs[l] = yl_shifted since the only way we can exit the while // loop above is when xs[l] != yl_shifted or l < 0, and the case l < 0 was // already treated above. assert!(xs[l - 1] < yl_shifted); // |x| - |y| <= 1 / 2 * W ^ n - 1 and is exact goto_sub_d1_lose = true; } continue; } } else if exp_diff >= prec { // The difference of exponents is larger than the precision of all operands, thus the // result is either x or x - 1 ulp, with a possible exact result when x = prec, x = 2 ^ // e and y = 1 / 2 * ulp(x) // // - We can't set OUT before since we use ys for rounding... // - Perform rounding: check if out = b or out = x - ulp(x) if exp_diff == prec { // since y is normalized, we need to subtract 1 / 2 * ulp(x) round_bit = 1; // round_bit_2 is the bit of weight 1 / 4 * ulp(x) in y. We assume a limb has at // least 2 bits. If the precision is 1, we read in the unused bits, which should be // zero, and this is what we want. round_bit_2 = ys[nm1] & HALF_LIMB_HIGH_BIT; // We also need sticky_bit_2 sticky_bit_2 = ys[nm1] & WIDTH_M2_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit = 0; if exp_diff == prec + 1 { round_bit_2 = 1; sticky_bit_2 = ys[nm1] & WIDTH_M1_MASK; let mut k = nm1; while sticky_bit_2 == 0 && k > 0 { k -= 1; sticky_bit_2 = ys[k]; } } else { round_bit_2 = 0; sticky_bit_2 = 1; // since C is non-zero } } // Copy mantissa X to Y ys.copy_from_slice(xs); } else { // case 2 <= exp_diff < prec // // Compute round_bit = Cp and sticky_bit = C'p + 1 // // Compute round_bit and round_bit_2 from Y The round bit is bit prec - exp_diff in Y, // assuming the most significant bit of Y is bit 0 let x = prec - exp_diff; let mut kx = nm1 - bit_to_limb_count_floor(x); let mut sx_bit = Limb::power_of_2(WIDTH_M1 - (x & Limb::WIDTH_MASK)); // the round bit is in ys[kx], at position sx assert!(prec >= exp_diff); round_bit = ys[kx] & sx_bit; // Now compute rxx: since exp_diff >= 2 it always exists in Y sx_bit = if sx_bit == 1 { // rxx is in the next limb kx = kx.checked_sub(1).unwrap(); LIMB_HIGH_BIT } else { // round_bit and round_bit_2 are in the same limb sx_bit >> 1 }; round_bit_2 = ys[kx] & sx_bit; // Now look at the remaining low bits of Y to determine sticky_bit_2 sticky_bit_2 = ys[kx] & (sx_bit - 1); while sticky_bit_2 == 0 && kx > 0 { kx -= 1; sticky_bit_2 = ys[kx]; } // Clean shifted Y' let mask = shift_bit - 1; let dm = exp_diff & Limb::WIDTH_MASK; let m = bit_to_limb_count_floor(exp_diff); if dm == 0 { assert_ne!(m, 0); // - dm = 0 and m > 0: Just copy // - Subtract the mantissa y from x in out limbs_sub_greater_in_place_right_different_ys0(xs, ys, ys[m] & !mask, m); } else if m == 0 { // dm >=2 and m == 0: just shift assert!(dm >= 2); // Subtract the mantissa y from x in out limbs_sub_shr_same_length_in_place_right_and_ys0(xs, ys, dm, !mask); } else { // - dm > 0 and m > 0: shift and zero // - Subtract the mantissa y from x in out limbs_sub_shr_greater_in_place_right_and_ys0(xs, ys, dm, !mask, m); } // Normalize: we lose at most one bit if !ys[nm1].get_highest_bit() { // - High bit is not set and we have to fix it. // - OUT >= 010000xxx001 limbs_slice_shl_in_place(ys, 1); // OUT >= 100000xxx010 if round_bit != 0 { // - Check if Y = -1 // - Since Y == -1, we have to subtract one more limbs_sub_limb_in_place(ys, shift_bit); assert!(ys[nm1].get_highest_bit()); } // - OUT >= 10000xxx001 // - Final exponent -1 since we have shifted the mantissa x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; // We don't have anymore a valid Yp + 1, but since Oyr >= 100000xxx001, the final // sub can't unnormalize. } assert_eq!(ys[0] & mask, 0); } // only loop when emulating gotos break; } let mut ys_power_of_2; loop { // At this point out contains x - high(y), normalized, and we have to subtract round_bit * // 1/2 ulp(out), round_bit_2 * 1/4 ulp(out), and sticky_bit_2 * 1/8 ulp(out), interpreting // round_bit/round_bit_2/sticky_bit_2 as 1 if non-zero. sticky_bit = round_bit_2 | sticky_bit_2; if round_bit == 0 && sticky_bit == 0 { return (x_exp, Equal); } ys_power_of_2 = limbs_is_power_of_2(ys); if ys_power_of_2 && round_bit != 0 { limbs_sub_limb_in_place(ys, shift_bit); ys[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); round_bit = round_bit_2; round_bit_2 = sticky_bit_2; sticky_bit_2 = 0; } else { break; } } // Now if out is a power of two, necessary round_bit = 0, which means the exact result is always // in (pred(ys), ys), and the bounds cannot be attained match rm { Exact => panic!("Inexact float subtraction"), Nearest => { if ys_power_of_2 { assert_eq!(round_bit, 0); // Since we are at the end of the binade, we have in fact round_bit = round_bit_2 // and sticky_bit = sticky_bit_2 round_bit = round_bit_2; sticky_bit = sticky_bit_2; } if (prec == 1 || ys[0] & shift_bit == 0 || round_bit == 0) && (sticky_bit == 0 || round_bit == 0) { (x_exp, Greater) } else { limbs_sub_limb_in_place(ys, shift_bit); if ys_power_of_2 { // deal with cancellation ys[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less) } } Floor | Down => { limbs_sub_limb_in_place(ys, shift_bit); if ys_power_of_2 { // deal with cancellation ys[nm1] |= LIMB_HIGH_BIT; x_exp.saturating_sub_assign(1); } (x_exp, Less) } Ceiling | Up => (x_exp, Greater), } } // This is mpfr_cmp2 from cmp2.c, MPFR 4.2.0, returning `cancel` along with `sign`. pub fn exponent_shift_compare<'a>( mut xs: &'a [Limb], mut x_exp: i64, mut x_prec: u64, mut ys: &'a [Limb], mut y_exp: i64, mut y_prec: u64, ) -> (Ordering, u64) { // x == y should not happen, since cmp2 is called only from agm (with different variables) and // from sub1 (if b=c, then sub1sp would be called instead). So, no need for a particular // optimization here. // // the cases b=0 or c=0 are also treated apart in agm and sub (which calls sub1) let sdiff_exp = x_exp - y_exp; let mut sign; let mut diff_exp; // index of the most significant limb of x and y let mut xi = bit_to_limb_count_floor(x_prec - 1); let mut yi = bit_to_limb_count_floor(y_prec - 1); let mut xi_done = false; let mut yi_done = false; let mut res = 0; if sdiff_exp >= 0 { sign = Greater; // assumes |x| > |y|; will be changed if not. diff_exp = u64::wrapping_from(sdiff_exp); let mut cancel = 0; // If diff_exp != 0, i.e. diff_exp > 0, then |x| > |y|. Otherwise... if diff_exp == 0 { // Skip the identical most significant limbs, adding Limb::WIDTH to the number of // canceled bits at each iteration. while !xi_done && !yi_done && xs[xi] == ys[yi] { if xi == 0 { xi_done = true; } else { xi -= 1; } if yi == 0 { yi_done = true; } else { yi -= 1; } res += Limb::WIDTH; } if xi_done { // |x| = |y| if yi_done { return (Equal, cancel); } // x has been read entirely, but not y. Thus |x| <= |y|. Swap xs and ys, and take // the opposite sign for the symmetric case below (simulating a swap). Note: // "yi_done = true;" is necessary to enter the following "if" (probably less // confusing than a "goto"). swap(&mut xs, &mut ys); swap(&mut xi, &mut yi); swap(&mut x_exp, &mut y_exp); swap(&mut x_prec, &mut y_prec); xi_done = yi_done; yi_done = true; sign = Less; } if yi_done { // y discards exactly the upper part of x assert!(!xi_done); // Skip null limbs of x (= non-represented null limbs of y), adding Limb::WIDTH to // the number of canceled bits at each iteration. while xs[xi] == 0 { // |x| = |y| if xi == 0 { xi_done = true; } else { xi -= 1; } if xi_done { return (Equal, cancel); } res += Limb::WIDTH; } let z = LeadingZeros::leading_zeros(xs[xi]); // xs[xn] != 0 cancel = res + z; return (sign, cancel); } assert!(!xi_done); assert!(!yi_done); assert!(xs[xi] != ys[yi]); // |x| != |y|. If |x| < |y|: swap xs and ys, and take the opposite sign. if xs[xi] < ys[yi] { swap(&mut xs, &mut ys); swap(&mut xi, &mut yi); swap(&mut xi_done, &mut yi_done); swap(&mut x_exp, &mut y_exp); swap(&mut x_prec, &mut y_prec); sign = Less; } } } else { // We necessarily have |x| < |y|. sign = Less; diff_exp = u64::exact_from(-sdiff_exp); swap(&mut xs, &mut ys); swap(&mut xi, &mut yi); swap(&mut x_exp, &mut y_exp); swap(&mut x_prec, &mut y_prec); } // Now we have removed the identical upper limbs of x and y (when diff_exp = 0), and after the // possible swap, we have |x| > |y|. The value diff_exp = EXP(x) - EXP(y) can be regarded as the // number of leading zeros of y, when aligned with x. // // When a limb of y is read from memory, the part that is not taken into account for the // operation with a limb xs[xn] of x will be put in lasty, shifted to the leftmost part (for // alignment with x): // ``` // [-------- xs[xn] --------][------- xs[xn-1] -------] // [-- old_lasty --][-------- ys[yn] --------] // [-- new_lastc --] // ``` // Note: if diff_exp == 0, then lasty will always remain 0. let mut lasty = 0; // Compute the next limb difference, which cannot be 0 (dif >= 1). let mut yy; if diff_exp < Limb::WIDTH { yy = ys[yi] >> diff_exp; if diff_exp != 0 { lasty = ys[yi] << (Limb::WIDTH - diff_exp); } if yi == 0 { yi_done = true; } else { yi -= 1; } } else { yy = 0; // remove Limb::WIDTH leading zeros diff_exp -= Limb::WIDTH; } // no borrow out in subtraction below assert!(xs[xi] >= yy); let mut dif = xs[xi] - yy; if xi == 0 { xi_done = true; } else { xi -= 1; } assert!(dif >= 1); let mut high_dif = false; // The current difference, here and later, is expressed under the form [high_dif][dif], where // high_dif is 0 or 1, and dif is a limb. Here, since we have computed a difference of limbs // (with x >= y), high_dif = 0. // // One needs to accumulate canceled bits for the remaining case where x and y are close to each // other due to a long borrow propagation: // ``` // x = [common part]1000...000[low(x)] // y = [common part]0111...111[low(y)] // ``` // After eliminating the common part above, we have computed a difference of the most // significant parts, which has been stored in [high_dif][dif] with high_dif = 0. We will loop // as long as the currently computed difference [high_dif][dif] = 1 (it is >= 1 by // construction). The computation of the difference will be: // ``` // 1xxx...xxx // - yyy...yyy // ``` // where the leading 1 before xxx...xxx corresponds to [high_dif][dif] at the beginning of the // loop. We will exit the loop also when y has entirely been taken into account as cancellation // is no longer possible in this case (it is no longer possible to cancel the leading 1). Note: // We can enter the loop only with diff_exp = 0 (with a non-empty common part, partly or // entirely removed) or with diff_exp = 1 (with an empty common part). Indeed, if diff_exp > 1, // then no limbs have been skipped, so that xs[xn] had its MSB equal to 1 and the most two // significant bits of yy are 0, which implies that dif > 1. while (!yi_done || lasty != 0) && !high_dif && dif == 1 { // Since we consider the next limb, we assume a cancellation of Limb::WIDTH (the new // exponent of the difference now being the one of the MSB of the next limb). But if the // leading 1 remains 1 in the difference (i.e. high_dif = 1 at the end of the loop), then we // will need to decrease res. res += Limb::WIDTH; // - See comment before the loop // - Next limb of x or non-represented 0 assert!(diff_exp <= 1); let xx = if xi_done { 0 } else { let r = xs[xi]; if xi == 0 { xi_done = true; } else { xi -= 1; } r }; if yi_done { yy = lasty; lasty = 0; } else if diff_exp == 0 { yy = ys[yi]; if yi == 0 { yi_done = true; } else { yi -= 1; } } else { assert_eq!(diff_exp, 1); assert!(lasty == 0 || lasty == LIMB_HIGH_BIT); yy = lasty + (ys[yi] >> 1); lasty = ys[yi] << (Limb::WIDTH - 1); if yi == 0 { yi_done = true; } else { yi -= 1; } } dif = xx.wrapping_sub(yy); high_dif = xx >= yy; } // Now, y has entirely been taken into account or [high_dif][dif] > 1. In any case, // [high_dif][dif] >= 1 by construction. First, we determine the currently number of canceled // bits, corresponding to the exponent of the current difference. The trailing bits of y, if // any, can still decrease the exponent of the difference when [high_dif][dif] is a power of // two, but since [high_dif][dif] > 1 in this case, by not more than 1. if high_dif { // high_dif == 1 See comment at the beginning of the above loop. res = res.checked_sub(1).unwrap(); // Terminate if [high_dif][dif] is not a power of two. if dif != 0 { return (sign, res); } } else { // high_dif == 0 assert!(dif >= 1); // [high_dif][dif] >= 1 res += LeadingZeros::leading_zeros(dif); // Terminate if [high_dif][dif] is not a power of two. if !dif.is_power_of_2() { return (sign, res); } } // Now, the result will be res + (low(x) < low(y)). // // If y has entirely been taken into account, it can no longer modify the current result. if yi_done && lasty == 0 { return (sign, res); } if !xi_done { for &x in xs[..=xi].iter().rev() { if diff_exp >= Limb::WIDTH { diff_exp -= Limb::WIDTH; assert_eq!(yy, 0); } else if yi_done { yy = lasty; lasty = 0; } else if diff_exp == 0 { yy = ys[yi]; if yi == 0 { yi_done = true; } else { yi -= 1; } } else { assert!((1..Limb::WIDTH).contains(&diff_exp)); yy = lasty + (ys[yi] >> diff_exp); lasty = ys[yi] << (Limb::WIDTH - diff_exp); if yi == 0 { yi_done = true; } else { yi -= 1; } } if x != yy { return (sign, if x < yy { res + 1 } else { res }); } } } // x has entirely been read. Determine whether the trailing part of y is non-zero. if lasty != 0 || !slice_test_zero(&ys[..=yi]) { res += 1; } (sign, res) } fn sub_float_significands_general<'a>( out: &mut [Limb], mut xs: &'a [Limb], mut x_exp: i32, mut x_prec: u64, mut ys: &'a [Limb], mut y_exp: i32, mut y_prec: u64, out_prec: u64, mut rm: RoundingMode, ) -> (i32, Ordering, bool) { let mut xs_len = xs.len(); let mut ys_len = ys.len(); let out_len = out.len(); let mut add_exp = false; let (sign, cancel) = exponent_shift_compare(xs, i64::from(x_exp), x_prec, ys, i64::from(y_exp), y_prec); if sign == Equal { // x == y. Return exact number 0. Setting the most-significant limb to 0 is a sufficient // signal to the caller that the entire output is 0, since in every other case the precision // of the output is the same as the precision of the inputs, and the most-significant limb // is therefore nonzero. *out.last_mut().unwrap() = 0; return (0, Equal, false); } // sign != 0, so that cancel has a valid value. // // If subtraction: sign(out) = sign * sign(x) If addition: sign(out) = sign of the larger // argument in absolute value. // // Both cases can be simplified in: // ``` // if (sign>0) // if addition: sign(out) = sign * sign(x) = sign(x) // if subtraction, x is greater, so sign(out) = sign(x) // else // if subtraction, sign(out) = -sign(x) // if addition, sign(out) = sign(y) (since y is greater) // But if it is an addition, sign(x) and sign(y) are opposed! // So sign(out) = -sign(x) // ``` let neg = sign == Less; if neg { // swap x and y so that |x| > |y| swap(&mut xs, &mut ys); swap(&mut xs_len, &mut ys_len); swap(&mut x_exp, &mut y_exp); swap(&mut x_prec, &mut y_prec); rm.neg_assign(); } let exp_diff = u64::exact_from(x_exp - y_exp); // Check if y is too small. let mut inexact = 0; if max(out_prec, x_prec) + 2 <= exp_diff { // Remember, we can't have an exact result! // ``` // A.AAAAAAAAAAAAAAAAA // = B.BBBBBBBBBBBBBBB // - C.CCCCCCCCCCCCC // A = S*ABS(B) +/- ulp(a) // ``` assert_ne!(rm, Exact, "Inexact float subtraction"); let mut exp_a = x_exp; let increment_exp; (inexact, increment_exp) = round_helper_even(out, out_prec, xs, x_prec, rm); if increment_exp { exp_a += 1; } if inexact == 0 && rm != Down && rm != Floor { // out = x, but the exact value of x - y is a bit below. Then, except for directed // rounding similar to toward zero and before overflow checking: a is the correctly // rounded value and since |x| - |y| < |out|, the ternary value is given by the sign of // out. inexact = 1; } else if inexact != 0 && inexact != MPFR_EVEN_INEX { // ``` // O.OOOOOOOOOOOOOO // = X.XXXXXXXXXXXXXXX // - Y.YYYYYYYYYYYYY // ``` // // It isn't exact, so PREC(x) > PREC(out) and the last PREC(x)-PREC(out) bits of x are // not all zeros. Subtracting y from x will not have an effect on the rounding except in // case of a midpoint in the round-to-nearest mode, when the even rounding was done away // from zero instead of toward zero. // // In case of even rounding: // ``` // 1.BBBBBBBBBBBBBx10 // - 1.CCCCCCCCCCCC // = 1.BBBBBBBBBBBBBx01 Rounded to PREC(x) // = 1.BBBBBBBBBBBBBx Nearest / Rounded to PREC(out) // ``` // // Set gives: // ``` // 1.BBBBBBBBBBBBB0 if inexact == EVEN_INEX (x == 0) // 1.BBBBBBBBBBBBB1+1 if inexact == -EVEN_INEX (x == 1) // ```` // which means we get a wrong rounded result if x == 1, i.e. inexact == MPFR_EVEN_INEX // (for positive numbers). // // Nothing to do. } else { // We need to take the value preceding |out|. We can't use mpfr_nexttozero due to a // possible out-of-range exponent. But this will allow us to have more specific code. limbs_sub_limb_in_place(out, Limb::power_of_2(limb_to_bit_count(out_len) - out_prec)); let last_out = out.last_mut().unwrap(); if !last_out.get_highest_bit() { exp_a.saturating_sub_assign(1); // The following is valid whether out_len = 1 or out_len > 1. *last_out |= LIMB_HIGH_BIT; } inexact = -1; } return (exp_a, inexact.sign(), neg); } // Reserve a space to store x aligned with the result, i.e. shifted by (-cancel) % Limb::WIDTH // to the right let shift_x = cancel.neg_mod_power_of_2(Limb::LOG_WIDTH); let cancel1 = bit_to_limb_count_floor(cancel + shift_x); let mut shifted_x; // the `high cancel1` limbs from x should not be taken into account let xs = if shift_x == 0 { // no need of an extra space xs } else { shifted_x = vec![0; xs_len + 1]; let (shifted_head, shifted_tail) = shifted_x.split_first_mut().unwrap(); *shifted_head = limbs_shr_to_out(shifted_tail, xs, shift_x); xs_len += 1; &shifted_x }; // Reserve a space to store y aligned with the result, i.e. shifted by (diff_exp - cancel) % // Limb::WIDTH to the right let shift_y = exp_diff .mod_power_of_2(Limb::LOG_WIDTH) .mod_power_of_2_sub(cancel.mod_power_of_2(Limb::LOG_WIDTH), Limb::LOG_WIDTH); assert!(shift_y < Limb::WIDTH); let mut shifted_y; let ys = if shift_y == 0 { ys } else { shifted_y = vec![0; ys_len + 1]; let (shifted_head, shifted_tail) = shifted_y.split_first_mut().unwrap(); *shifted_head = limbs_shr_to_out(shifted_tail, ys, shift_y); ys_len += 1; &shifted_y }; // here we have shift_y = (diff_exp - cancel) % Limb::WIDTH, 0 <= shift_y < Limb::WIDTH, thus we // want cancel2 = ceil((cancel - diff_exp) / Limb::WIDTH) let cancel2 = if cancel >= exp_diff { // Note that cancel is signed and will be converted to mpfr_uexp_t (type of diff_exp) in the // expression below, so that this will work even if cancel is very large and diff_exp = 0. (i128::from(cancel) - i128::from(exp_diff) + i128::wrapping_from(IWIDTH_M1)) >> Limb::LOG_WIDTH } else { -((i128::from(exp_diff) - i128::from(cancel)) >> Limb::LOG_WIDTH) }; // The high cancel2 limbs from x should not be taken into account // // ``` // ap[an-1] ap[0] // <----------------+-----------|----> // <----------PREC(a)----------><-sh-> // cancel1 // limbs bp[bn-cancel1-1] // <--...-----><----------------+-----------+-----------> // cancel2 // limbs cp[cn-cancel2-1] cancel2 >= 0 // <--...--><----------------+----------------+----------------> // (-cancel2) cancel2 < 0 // limbs <----------------+----------------> // ``` // // First part: put in out[0..out_len - 1] the value of high(x) - high(y), where high(x) consists // of the high out_len + cancel1 limbs of x, and high(y) consists of the high out_len + cancel2 // limbs of y. // // Copy high(x) into out if out_len + cancel1 <= xs_len { // ``` // out: <----------------+-----------|----> // xs: <-----------------------------------------> // ``` let xs_hi = &xs[xs_len - out_len - cancel1..]; out.copy_from_slice(&xs_hi[..out_len]); } else { // ``` // out: <----------------+-----------|----> // xs: <-------------------------> // ``` if cancel1 < xs_len { let (out_lo, out_hi) = out.split_at_mut(out_len + cancel1 - xs_len); slice_set_zero(out_lo); out_hi.copy_from_slice(&xs[..xs_len - cancel1]); } } // subtract high(y) if i128::wrapping_from(out_len) + cancel2 > 0 { if cancel2 >= 0 { let cancel2 = usize::exact_from(cancel2); if out_len + cancel2 <= ys_len { // ``` // out: <-----------------------------> // ys: <-----------------------------------------> // ``` let ys_hi = &ys[ys_len - out_len - cancel2..]; limbs_sub_same_length_in_place_left(out, &ys_hi[..out_len]); } else { // ``` // out: <----------------------------> // ys: <-------------------------> // ``` if ys_len > cancel2 { limbs_sub_same_length_in_place_left( &mut out[out_len + cancel2 - ys_len..], &ys[..ys_len - cancel2], ); } } } else { // cancel2 < 0 let neg_cancel2 = usize::exact_from(-cancel2); let (out_lo, out_hi) = out.split_at_mut(out_len - neg_cancel2); let borrow = if out_len - neg_cancel2 <= ys_len { // ``` // a: <-----------------------------> // c: <-----------------------------> // ``` limbs_sub_same_length_in_place_left(out_lo, &ys[ys_len - (out_len - neg_cancel2)..]) } else { // ``` // a: <----------------------------> // c: <----------------> // ``` let len = out_lo.len(); limbs_sub_same_length_in_place_left(&mut out_lo[len - ys_len..], ys) }; limbs_sub_limb_in_place(out_hi, Limb::from(borrow)); } } // Now perform rounding let shift = limb_to_bit_count(out_len) - out_prec; let shift_bit = Limb::power_of_2(shift); let shift_mask = shift_bit - 1; // Last unused bits from out let out_head = out.first_mut().unwrap(); let carry = *out_head & shift_mask; *out_head -= carry; let mut cmp_low = 0; let mut goto_truncate = false; let mut goto_end_of_sub = false; if rm == Nearest { if shift != 0 { let half_shift_bit = shift_bit >> 1; // Can decide except when carry = 2 ^ (sh - 1) [middle] or carry = 0 [truncate, but // cannot decide inexact flag] if carry > half_shift_bit { if limbs_slice_add_limb_in_place(out, shift_bit) { // result is a power of 2: 11111111111111 + 1 = 1000000000000000 out[out_len - 1] = LIMB_HIGH_BIT; add_exp = true; } // result larger than exact value inexact = 1; goto_truncate = true; } else if carry != 0 && carry < half_shift_bit { inexact = -1; // result if smaller than exact value goto_truncate = true; } else { // now carry = 2 ^ (sh - 1), in which case cmp_low = 2, or carry = 0, in which case // cmp_low = 0 cmp_low = if carry == 0 { 0 } else { 2 }; } } } else if carry != 0 { if rm == Floor || rm == Down || rm == Exact { inexact = -1; } else { if limbs_slice_add_limb_in_place(out, shift_bit) { // result is a power of 2: 11111111111111 + 1 = 1000000000000000 out[out_len - 1] = LIMB_HIGH_BIT; add_exp = true; } // result larger than exact value inexact = 1; } goto_truncate = true; } if !goto_truncate { // We have to consider the low (xs_len - (out_len + cancel1)) limbs from x, and the (ys_len // - (out_len + cancel2)) limbs from y. xs_len.saturating_sub_assign(out_len + cancel1); let ys_len0 = ys_len; ys_len = usize::saturating_from( i128::wrapping_from(ys_len) - (i128::wrapping_from(out_len) + cancel2), ); // For rounding to nearest, we couldn't conclude up to here in the following cases: // - shift = 0, then cmp_low = 0: we can either truncate, subtract one ulp or add one ulp: // -1 ulp < low(x) - low(y) < 1 ulp // - shift > 0 but the low `shift` bits from high(x) - high(y) equal 2 ^ (shift - 1): -0.5 // ulp <= -1 / 2 ^ shift < low(x) - low(y) - 0.5 < 1 / 2 ^ shift <= 0.5 ulp we can't // decide the rounding, in that case cmp_low = 2: either we truncate and flag = -1, or we // add one ulp and flag = 1 // - The low shift > 0 bits from high(x)-high(y) equal 0: we know we have to truncate but we // can't decide the ternary value, here cmp_low = 0: -0.5 ulp <= -1 / 2 ^ shift < low(x) // -low(y) < 1 / 2 ^ shift <= 0.5 ulp we always truncate and inexact can be any of -1, 0, // 1 // - Note: here ys_len might exceed ys_len0, in which case we consider a zero limb let mut k: i32 = 0; while xs_len != 0 || ys_len != 0 { // - If cmp_low < 0, we know low(x) - low(y) < 0 // - If cmp_low > 0, we know low(x) - low(y) > 0 (more precisely if cmp_low = 2, low(x) // - low(y) = 0.5 ulp so far) // - If cmp_low = 0, so far low(x) - low(y) = 0 // - get next limbs let mut xx = if xs_len != 0 { xs_len -= 1; xs[xs_len] } else { 0 }; let mut yy = if ys_len != 0 && { let c = ys_len <= ys_len0; ys_len -= 1; c } { ys[ys_len] } else { 0 }; // cmp_low compares low(x) and low(y) if cmp_low == 0 { // case 1 or 3 cmp_low = match xx.cmp(&yy) { Greater => 1, Less => -2 + k, Equal => 0, }; } // Case 1 for k=0 splits into 7 subcases: // - 1a: xx > yy + half // - 1b: xx = yy + half // - 1c: 0 < xx - yy < half // - 1d: xx = yy // - 1e: -half < xx - yy < 0 // - 1f: xx - yy = -half // - 1g: xx - yy < -half // // Case 2 splits into 3 subcases: // - 2a: xx > yy // - 2b: xx = yy // - 2c: xx < yy // // Case 3 splits into 3 subcases: // - 3a: xx > yy // - 3b: xx = yy // - 3c: xx < yy // // The case rounding to nearest with sh=0 is special since one couldn't subtract above // 1/2 ulp in the trailing limb of the result if rm == Nearest && shift == 0 && k == 0 { // case 1 for k = 0 // - add one ulp if xx > yy + half // - truncate if yy - half < xx < yy + half // - sub one ulp if xx < yy - half if cmp_low < 0 { // - xx < yy: -1 ulp < low(b) - low(c) < 0, // - cases 1e, 1f and 1g if yy >= LIMB_HIGH_BIT { yy -= LIMB_HIGH_BIT; } else { // since xx < yy < half, xx + half < 2 * half xx += LIMB_HIGH_BIT; } // Now we have xx < yy + half: we have to subtract one ulp if xx < yy, and // truncate if xx > yy } else { // xx >= yy, cases 1a to 1d if yy < LIMB_HIGH_BIT { yy += LIMB_HIGH_BIT; } else { // since xx >= yy >= half, xx - half >= 0 xx -= LIMB_HIGH_BIT; } // Now we have xx > yy - half: we have to add one ulp if xx > yy, and truncate // if xx < yy if cmp_low > 0 { cmp_low = 2; } } } match cmp_low.sign() { Less => { // low(x) - low(y) < 0: either truncate or subtract one ulp match rm { Floor | Down => { limbs_sub_limb_in_place(out, shift_bit); inexact = -1; goto_end_of_sub = true; } Ceiling | Up | Exact => { inexact = 1; goto_truncate = true; } Nearest => { // - If cmp_low < 0 and xx > yy, then -0.5 ulp < low(x) - low(y) < 0, // whatever the value of shift. // - If shift > 0, then cmp_low < 0 implies that the initial neglected // shift bits were 0 (otherwise cmp_low = 2 initially), thus the // weight of the new bits is less than 0.5 ulp too. // - If k > 0 (and shift = 0) this means that either the first neglected // limbs xx and yy were equal (thus cmp_low was 0 for k = 0), or we // had xx - yy = -0.5 ulp or 0.5 ulp. // - The last case is not possible here since we would have cmp_low > 0 // which is sticky. // - In the first case (where we have cmp_low = -1), we truncate, // whereas in the 2nd case we have cmp_low = -2 and we subtract one // ulp. if xx > yy || shift > 0 || cmp_low == -1 { // - -0.5 ulp < low(b)-low(c) < 0, // - xx > yy corresponds to cases 1e and 1f1 // - shift > 0 corresponds to cases 3c and 3b3 // - cmp_low = -1 corresponds to case 1d3 (also 3b3) inexact = 1; goto_truncate = true; } else if xx < yy { // Here shift = 0 and low(x) - low(y) < -0.5 ulp, this corresponds // to cases 1g and 1f3 // limbs_sub_limb_in_place(out, shift_bit); inexact = -1; goto_end_of_sub = true; } // The only case where we can't conclude is shift = 0 and xx = yy, i.e., // we have low(x) // - low(y) = -0.5 ulp (up to now), thus we don't know if we must // truncate or // subtract one ulp. Note: for shift = 0 we can't have low(x) - low(y) = // -0.5 ulp up to now, since low(x) - low(y) > 1 / 2 ^ shift } } } Greater => { // 0 < low(x) - low(y): either truncate or add one ulp match rm { Floor | Down | Exact => { inexact = -1; goto_truncate = true; } Ceiling | Up => { if limbs_slice_add_limb_in_place(out, shift_bit) { // result is a power of 2: 11111111111111 + 1 = 1000000000000000 out[out_len - 1] = LIMB_HIGH_BIT; add_exp = true; } // result larger than exact value inexact = 1; goto_truncate = true; } Nearest => { match xx.cmp(&yy) { Greater => { // If sh = 0, then xx > yy means that low(x) - low(y) > 0.5 ulp, // and similarly when cmp_low = 2. if cmp_low == 2 { // cases 1a, 1b1, 2a and 2b1 // // shift > 0 and cmp_low > 0: this implies that the `shift` // initial neglected bits were 0, and the remaining low(x) - // low(y) > 0, but its weight is less than 0.5 ulp if limbs_slice_add_limb_in_place(out, shift_bit) { // result is a power of 2: 11111111111111 + 1 = // 1000000000000000 out[out_len - 1] = LIMB_HIGH_BIT; add_exp = true; } // result larger than exact value inexact = 1; } else { // 0 < low(x) - low(y) < 0.5 ulp, this corresponds to cases // 3a, 1d1 and 3b1 inexact = -1; } goto_truncate = true; } Less => { // 0 < low(x) - low(y) < 0.5 ulp, cases 1c, 1b3, 2b3 and 2c inexact = -1; goto_truncate = true; } Equal => { // The only case where we can't conclude is xx = yy, i.e., // low(x) - low(y) = 0.5 ulp (up to now), thus we don't know if // we must truncate or add one ulp. } } } } } _ => {} } // After k = 0, we cannot conclude in the following cases, we split them according to // the values of xx and yy for k = 1: // ``` // 1b. shift = 0 and cmp_low = 1 and xx-yy = half [around 0.5 ulp] // 1b1. xx > yy: add one ulp, inex = 1 // 1b2: xx = yy: cannot conclude // 1b3: xx < yy: truncate, inex = -1 // 1d. shift = 0 and cmp_low = 0 and xx-yy = 0 [around 0] // 1d1: xx > yy: truncate, inex = -1 // 1d2: xx = yy: cannot conclude // 1d3: xx < yy: truncate, inex = +1 // 1f. shift = 0 and cmp_low = -1 and xx-yy = -half [around -0.5 ulp] // 1f1: xx > yy: truncate, inex = +1 // 1f2: xx = yy: cannot conclude // 1f3: xx < yy: sub one ulp, inex = -1 // 2b. shift > 0 and cmp_low = 2 and xx=yy [around 0.5 ulp] // 2b1. xx > yy: add one ulp, inex = 1 // 2b2: xx = yy: cannot conclude // 2b3: xx < yy: truncate, inex = -1 // 3b. shift > 0 and cmp_low = 0 [around 0] // 3b1. xx > yy: truncate, inex = -1 // 3b2: xx = yy: cannot conclude // 3b3: xx < yy: truncate, inex = +1 // ``` if goto_truncate || goto_end_of_sub { break; } k = 1; } if !goto_truncate && !goto_end_of_sub { inexact = if rm == Nearest && cmp_low != 0 { // Even rounding rule if (out[0] >> shift) & 1 != 0 { if cmp_low < 0 { limbs_sub_limb_in_place(out, shift_bit); goto_end_of_sub = true; -1 } else { if limbs_slice_add_limb_in_place(out, shift_bit) { // result is a power of 2: 11111111111111 + 1 = 1000000000000000 out[out_len - 1] = LIMB_HIGH_BIT; add_exp = true; } // result larger than exact value 1 } } else if cmp_low > 0 { -1 } else { 1 } } else { 0 }; } } let last_out = &mut out[out_len - 1]; if !goto_end_of_sub && *last_out >> WIDTH_M1 == 0 { // case 1 - varepsilon *last_out = LIMB_HIGH_BIT; add_exp = true; } // We have to set MPFR_EXP(out) to MPFR_EXP(x) - cancel + diff_exp, taking care of // underflows/overflows in that computation, and of the allowed exponent range let exp_a = if cancel != 0 { x_exp = i32::saturating_from(i128::from(x_exp) - i128::from(cancel)); if add_exp { x_exp.saturating_add_assign(1); } x_exp } else { // cancel = 0: MPFR_EXP(out) <- MPFR_EXP(x) + diff_exp // // In case cancel = 0, diff_exp can still be 1, in case x is just below a power of two, y is // very small, prec(out) < prec(x), and rnd = away or nearest if add_exp { x_exp.saturating_add_assign(1); } x_exp }; // check that result is msb-normalized assert!(last_out.get_highest_bit()); (exp_a, inexact.sign(), neg) } ================================================ FILE: malachite-nz/src/natural/arithmetic/gcd/extended_gcd.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // Uses code adopted from the FLINT Library. // // Copyright © 2009, 2016 William Hart // // 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 crate::integer::Integer; use crate::natural::InnerNatural::Small; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div_exact::limbs_div_exact_to_out; use crate::natural::arithmetic::div_mod::{ limbs_div_limb_to_out_mod, limbs_div_mod_qs_to_out_rs_to_ns, }; use crate::natural::arithmetic::gcd::half_gcd::{ GcdSubdivideStepContext, HalfGcdMatrix, HalfGcdMatrix1, extract_number, limbs_gcd_subdivide_step, limbs_half_gcd, limbs_half_gcd_2, limbs_half_gcd_matrix_1_mul_inverse_vector, limbs_half_gcd_matrix_1_mul_vector, limbs_half_gcd_matrix_adjust, limbs_half_gcd_matrix_init_scratch_len, limbs_half_gcd_scratch_len, }; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; use crate::natural::arithmetic::sub::limbs_sub_greater_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{DoubleLimb, Limb}; use core::cmp::{Ordering::*, max}; use core::mem::swap; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ DivExact, ExtendedGcd, NegAssign, OverflowingAddAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::slices::{slice_set_zero, slice_test_zero, slice_trailing_zeros}; // This is equivalent to `gcdext_ctx` from `gmp-impl.h`, GMP 6.2.1. struct ExtendedGcdContext<'a> { // Result parameters. gs: &'a mut [Limb], gs_len: usize, ss: &'a mut [Limb], ss_len: usize, ss_sign: bool, // Cofactors updated in each step. us_len: usize, us0: &'a mut [Limb], us1: &'a mut [Limb], scratch: &'a mut [Limb], } impl<'a> ExtendedGcdContext<'a> { const fn new( gs: &'a mut [Limb], ss: &'a mut [Limb], us_len: usize, us0: &'a mut [Limb], us1: &'a mut [Limb], scratch: &'a mut [Limb], ) -> Self { let gs_len = gs.len(); Self { gs, gs_len, ss, ss_len: 0, ss_sign: false, us_len, us0, us1, scratch, } } } impl GcdSubdivideStepContext for ExtendedGcdContext<'_> { // This is equivalent to `mpn_gcdext_hook` from `mpn/gcdext_lehmer.c`, GMP 6.2.1. fn gcd_subdiv_step_hook( &mut self, gs: Option<&[Limb]>, qs: Option<&mut [Limb]>, mut qs_len: usize, mut d: i8, ) { let mut us_len = self.us_len; if let Some(gs) = gs { let gs_len = gs.len(); assert_ne!(gs_len, 0); assert!(gs[gs_len - 1] > 0); self.gs_len = gs_len; self.gs[..gs_len].copy_from_slice(gs); if d == -1 { // Must return the smallest cofactor, +us1 or -us0 let c = limbs_cmp_same_length(&self.us0[..us_len], &self.us1[..us_len]); assert!(c != Equal || us_len == 1 && self.us0[0] == 1 && self.us1[0] == 1); d = i8::from(c == Less); } let ss = if d == 0 { &mut *self.us1 } else { &mut *self.us0 }; us_len -= slice_trailing_zeros(&ss[..us_len]); self.ss[..us_len].copy_from_slice(&ss[..us_len]); self.us_len = us_len; self.ss_len = us_len; self.ss_sign = d == 0; } else { let mut us0 = &mut *self.us0; let mut us1 = &mut *self.us1; if d != 0 { swap(&mut us0, &mut us1); } let qs = qs.as_ref().unwrap(); if qs[qs_len - 1] == 0 { qs_len -= 1; } // Update us0 += q * us1 let carry = if qs_len == 1 { let q = qs[0]; let us0 = &mut us0[..us_len]; let us1 = &us1[..us_len]; if q == 1 { Limb::from(limbs_slice_add_same_length_in_place_left(us0, us1)) } else { limbs_slice_add_mul_limb_same_length_in_place_left(us0, us1, q) } } else { let mut us1_len = us_len; us1_len -= slice_trailing_zeros(&us1[..us1_len]); if us1_len == 0 { return; } // Should always have us1_len == us_len here, and us1 >= us0. The reason is that we // alternate adding us0 to us1 and us1 to us0 (corresponding to subtractions a - b // and b - a), and we can get a large quotient only just after a swscratch_len, // which means that we'll add (a multiple of) the larger u to the smaller. let scratch = &mut *self.scratch; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(qs_len, us1_len)]; limbs_mul_to_out(scratch, &qs[..qs_len], &us1[..us1_len], &mut mul_scratch); us1_len += qs_len; if scratch[us1_len - 1] == 0 { us1_len -= 1; } let us0 = &mut us0[..us1_len]; let scratch = &scratch[..us1_len]; Limb::from(if us1_len >= us_len { let us_len_old = us_len; us_len = us1_len; limbs_add_to_out_aliased(us0, us_len_old, scratch) } else { fail_on_untested_path("gcd_subdiv_step_hook, us1_len < us_len"); // Note: Unlikely case, maybe never happens? limbs_slice_add_greater_in_place_left(us0, scratch) }) }; us0[us_len] = carry; self.us_len = us_len; if carry > 0 { self.us_len += 1; } } } } // This is equivalent to `mpn_gcdext_lehmer_n` from `mpn/generic/gcdext_lehmer.c`, GMP 6.2.1. fn limbs_extended_gcd_same_length_lehmer<'a>( gs: &mut [Limb], ss: &mut [Limb], mut xs: &'a mut [Limb], ys: &mut [Limb], scratch: &'a mut [Limb], ) -> (usize, usize, bool) { // Keeps track of the second row of the reduction matrix // // M = (v0, v1 ; us0, us1) // // which correspond to the first column of the inverse // // M^{-1} = (us1, -v1; -us0, v0) // // This implies that // // ``` // a = us1 A (mod B) // b = -us0 A (mod B) // ``` // // where A, B denotes the input values. let mut n = xs.len(); assert_eq!(ys.len(), n); let scratch_len = n + 1; let (us, mut scratch) = scratch.split_at_mut(3 * scratch_len); slice_set_zero(us); let (mut us0, remainder) = us.split_at_mut(scratch_len); let (us1, mut u2) = remainder.split_at_mut(scratch_len); us1[0] = 1; let mut us_len = 1; while n >= 2 { let mut m = HalfGcdMatrix1::default(); let mask = xs[n - 1] | ys[n - 1]; assert_ne!(mask, 0); let (ah, al, bh, bl) = if mask.get_highest_bit() { (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else if n == 2 { // We use the full inputs without truncation, so we can safely shift left. let shift = u64::from(mask.leading_zeros()); ( extract_number(shift, xs[1], xs[0]), xs[0] << shift, extract_number(shift, ys[1], ys[0]), ys[0] << shift, ) } else { let shift = u64::from(mask.leading_zeros()); ( extract_number(shift, xs[n - 1], xs[n - 2]), extract_number(shift, xs[n - 2], xs[n - 3]), extract_number(shift, ys[n - 1], ys[n - 2]), extract_number(shift, ys[n - 2], ys[n - 3]), ) }; // Try a `limbs_half_gcd_2` step if limbs_half_gcd_2(ah, al, bh, bl, &mut m) { n = limbs_half_gcd_matrix_1_mul_inverse_vector( &m, &mut scratch[..n], &xs[..n], &mut ys[..n], ); swap(&mut xs, &mut scratch); us_len = limbs_half_gcd_matrix_1_mul_vector(&m, u2, &us0[..us_len], us1); swap(&mut us0, &mut u2); } else { // `limbs_half_gcd_2` has failed. Then either one of a or b is very small, or the // difference is very small. Perform one subtraction followed by one division. let mut context = ExtendedGcdContext::new(gs, ss, us_len, us0, us1, u2); // Temporary storage `n` for the quotient and `scratch_len` for the new cofactor. n = limbs_gcd_subdivide_step(&mut xs[..n], &mut ys[..n], 0, &mut context, scratch); if n == 0 { return (context.gs_len, context.ss_len, context.ss_sign); } us_len = context.us_len; } } assert_ne!(xs[0], 0); assert_ne!(ys[0], 0); let negate; if xs[0] == ys[0] { // Which cofactor to return now? Candidates are +us1 and -us0, depending on which of a and b // was most recently reduced, which we don't keep track of. So compare and get the smallest // one. gs[0] = xs[0]; let c = limbs_cmp_same_length(&us0[..us_len], &us1[..us_len]); assert!(c != Equal || us_len == 1 && us0[0] == 1 && us1[0] == 1); let ss_sign = c != Less; let u = if ss_sign { us1 } else { us0 }; us_len -= slice_trailing_zeros(&u[..us_len]); ss[..us_len].copy_from_slice(&u[..us_len]); (1, us_len, ss_sign) } else { let (g, mut u, mut v) = xs[0].extended_gcd(ys[0]); gs[0] = g; // Set ss = u us1 - v us0. Keep track of size, us_len grows by one or two limbs. if u == 0 { assert_eq!(v, 1); us_len -= slice_trailing_zeros(&us0[..us_len]); ss[..us_len].copy_from_slice(&us0[..us_len]); return (1, us_len, false); } else if v == 0 { assert_eq!(u, 1); us_len -= slice_trailing_zeros(&us1[..us_len]); ss[..us_len].copy_from_slice(&us1[..us_len]); return (1, us_len, true); } else if u > 0 { negate = false; assert!(v < 0); v.neg_assign(); } else { negate = true; assert!(v > 0); u.neg_assign(); } let mut u_high = limbs_mul_limb_to_out::(ss, &us1[..us_len], Limb::exact_from(u)); let v_high = limbs_slice_add_mul_limb_same_length_in_place_left( &mut ss[..us_len], &us0[..us_len], Limb::exact_from(v), ); if u_high != 0 || v_high != 0 { let overflow = u_high.overflowing_add_assign(v_high); ss[us_len] = u_high; us_len += 1; if overflow { fail_on_untested_path("limbs_extended_gcd_same_length_lehmer, overflow"); ss[us_len] = 1; us_len += 1; } } us_len -= slice_trailing_zeros(&ss[..us_len]); assert_ne!(us_len, 0); (1, us_len, !negate) } } // Computes (r;b) = (a; b) M. Result is of size n + M->n +/- 1, and the size is returned (if inputs // are non-normalized, result may be non-normalized too). Temporary space needed is M->n + n. // // This is equivalent to `hgcd_mul_matrix_vector` from `mpn/generic/gcdext.c`, GMP 6.2.1. fn limbs_half_gcd_matrix_mul_vector( m: &mut HalfGcdMatrix<'_>, rp: &mut [Limb], xs: &[Limb], ys: &mut [Limb], scratch: &mut [Limb], ) -> usize { // Compute (r,b) <-- (u00 a + u10 b, u01 a + u11 b) as // // ``` // t = u00 * a // r = u10 * b // r += t; // // t = u11 * b // b = u01 * a // b += t; // ``` let n = xs.len(); let ys_lo = &ys[..n]; let m_n = m.n; let mut big_n = n + m_n; let scratch = &mut scratch[..big_n]; let (m00, m01, m10, m11) = m.get_four(); let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(m_n, n)]; limbs_mul_to_out(scratch, &m00[..m_n], xs, &mut mul_scratch); limbs_mul_to_out(&mut rp[..big_n], &m10[..m_n], ys_lo, &mut mul_scratch); let a_high = limbs_slice_add_same_length_in_place_left(&mut rp[..big_n], scratch); limbs_mul_to_out(scratch, &m11[..m_n], ys_lo, &mut mul_scratch); limbs_mul_to_out(ys, &m01[..m_n], xs, &mut mul_scratch); let b_high = limbs_slice_add_same_length_in_place_left(&mut ys[..big_n], scratch); if a_high || b_high { rp[big_n] = Limb::from(a_high); ys[big_n] = Limb::from(b_high); big_n += 1; } else { // Normalize while rp[big_n - 1] == 0 && ys[big_n - 1] == 0 { big_n -= 1; } } big_n } // Computes |v| = |(g - u a)| / b, where u may be positive or negative, and v is of the opposite // sign. max(a, b) is of size n, u and v at most size n, and v must have space for n+1 limbs. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `compute_v` from `mpn/generic/gcdext.c`, GMP 6.2.1, except that `ys` is // consumed. fn limbs_extended_gcd_cofactor( vs: &mut [Limb], xs: &[Limb], ys: &mut [Limb], gs: &[Limb], ss: &[Limb], ss_len: usize, ss_sign: bool, scratch: &mut [Limb], ) -> usize { let n = xs.len(); assert_eq!(ys.len(), n); let gs_len = gs.len(); assert_ne!(n, 0); assert_ne!(gs_len, 0); assert_ne!(ss_len, 0); let mut size = ss_len; assert!(size <= n); assert_ne!(ss[size - 1], 0); let xs_len = n - slice_trailing_zeros(xs); assert!(gs_len <= xs_len); let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs_len, size)]; limbs_mul_to_out(scratch, &xs[..xs_len], &ss[..size], &mut mul_scratch); size += xs_len; let scratch = &mut scratch[..size]; if ss_len != 0 && ss_sign { // |v| = -v = (u a - g) / b assert!(!limbs_sub_greater_in_place_left(scratch, gs)); size -= slice_trailing_zeros(scratch); if size == 0 { return 0; } } else { // |v| = v = (g - u a) / b = (g + |u| a) / b. Since g <= a, (g + |u| a) always fits in // (|usize| + xs_len) limbs. assert!(!limbs_slice_add_greater_in_place_left(scratch, gs)); if scratch[size - 1] == 0 { size -= 1; } } // Now divide t / b. There must be no remainder let ys_len = n - slice_trailing_zeros(ys); assert!(size >= ys_len); let vs_len = size + 1 - ys_len; assert!(vs_len <= n + 1); limbs_div_exact_to_out(vs, &mut scratch[..size], &mut ys[..ys_len]); if vs[vs_len - 1] == 0 { vs_len - 1 } else { vs_len } } // This is equivalent to `CHOOSE_P_1` from `mpn/generic/gcdext.c`, GMP 6.2.1. const fn choose_p_1(n: usize) -> usize { n >> 1 } // This is equivalent to `CHOOSE_P_2` from `mpn/generic/gcdext.c`, GMP 6.2.1. const fn choose_p_2(n: usize) -> usize { n / 3 } // This is equivalent to `MPN_GCDEXT_LEHMER_N_ITCH` from `gmp-impl.h`, GMP 6.2.1. const fn limbs_extended_gcd_same_length_lehmer_scratch_len(n: usize) -> usize { (n << 2) + 3 } // TODO tune const GCDEXT_DC_THRESHOLD: usize = 242; // Temporary storage: // // Initial division: Quotient of at most xs_len - n + 1 <= xs_len limbs. // // Storage for us0 and us1: 2(n+1). // // Storage for hgcd matrix M, with input ceil(n/2): 5 * ceil(n/4) // // Storage for hgcd, input (n + 1)/2: 9 n/4 plus some. // // When hgcd succeeds: 1 + floor(3n/2) for adjusting a and b, and 2(n+1) for the cofactors. // // When hgcd fails: 2n + 1 for mpn_gcdext_subdiv_step, which is less. // // For the lehmer call after the loop, Let T denote GCDEXT_DC_THRESHOLD. For the gcdext_lehmer call, // we need T each for u, a and b, and 4T+3 scratch space. Next, for compute_v, we need T for u, T+1 // for v and 2T scratch space. In all, 7T + 3 is sufficient for both operations. // // Optimal choice of p seems difficult. In each iteration the division of work between hgcd and the // updates of us0 and us1 depends on the current size of the u. It may be desirable to use a // different choice of p in each iteration. Also the input size seems to matter; choosing p = n / 3 // in the first iteration seems to improve performance slightly for input size just above the // threshold, but degrade performance for larger inputs. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpn_gcdext` from `mpn/generic/gcdext.c`, GMP 6.2.1, where the sign of // `usizep` is returned, but its magnitude is not indicated anywhere; it can be inferred by taking // the length of the nonzero portion of `ss`. pub fn limbs_extended_gcd( gs: &mut [Limb], ss: &mut [Limb], xs: &mut [Limb], ys: &mut [Limb], ) -> (usize, bool) { let xs_len = xs.len(); let mut n = ys.len(); let scratch_len = n + 1; assert!(xs_len >= n); assert_ne!(n, 0); assert_ne!(ys[n - 1], 0); let scratch = xs_len - n + 1; let mut scratch_2 = max( scratch, limbs_extended_gcd_same_length_lehmer_scratch_len(n), ); let mut matrix_scratch = 0; if n >= GCDEXT_DC_THRESHOLD { // For hgcd loop. If the definitions of choose_p_1 and choose_p_2 change, the min and max // might change too. let max_p = choose_p_1(n); let min_p = choose_p_2(n); matrix_scratch = limbs_half_gcd_matrix_init_scratch_len(n - min_p); let hgcd_scratch = limbs_half_gcd_scratch_len(n - min_p); let update_scratch = max_p + n - 1; let mut scratch = matrix_scratch + max(hgcd_scratch, update_scratch); scratch_2 = max(scratch_2, scratch); // Final `limbs_extended_gcd_same_length_lehmer` call. Need space for u and for copies of a // and b. scratch = limbs_extended_gcd_same_length_lehmer_scratch_len(GCDEXT_DC_THRESHOLD) + 3 * GCDEXT_DC_THRESHOLD; scratch_2 = max(scratch_2, scratch); // Cofactors us0 and us1 scratch_2 += (n + 1) << 1; } let mut scratch = vec![0; scratch_2]; if xs_len > n { if n == 1 { xs[0] = limbs_div_limb_to_out_mod(&mut scratch, xs, ys[0]); } else { limbs_div_mod_qs_to_out_rs_to_ns(&mut scratch, xs, ys); } if slice_test_zero(&xs[..n]) { gs[..n].copy_from_slice(ys); return (n, true); } } let xs_lo = &mut xs[..n]; if n < GCDEXT_DC_THRESHOLD { let (gs_len, _, ss_sign) = limbs_extended_gcd_same_length_lehmer(gs, ss, xs_lo, ys, &mut scratch); return (gs_len, ss_sign); } slice_set_zero(&mut scratch[..scratch_len << 1]); split_into_chunks_mut!(scratch, scratch_len, [us0, us1], scratch); // For the first hgcd call, there are no u updates, and it makes some sense to use a different // choice for p. let p = choose_p_1(n); let (scratch_lo, scratch_hi) = scratch.split_at_mut(matrix_scratch); let mut m = HalfGcdMatrix::init(n - p, scratch_lo); let nn = limbs_half_gcd(&mut xs_lo[p..], &mut ys[p..], &mut m, scratch_hi); let mut ss_sign; let mut us_len; if nn != 0 { assert!(m.n <= (n - p - 1) >> 1); assert!(m.n + p <= (p + n - 1) >> 1); // Temporary storage 2 (p + m.n) <= p + n - 1 n = limbs_half_gcd_matrix_adjust(&m, p + nn, xs, ys, p, scratch_hi); us0[..m.n].copy_from_slice(&m.get(1, 0)[..m.n]); us1[..m.n].copy_from_slice(&m.get(1, 1)[..m.n]); us_len = m.n; while us0[us_len - 1] == 0 && us1[us_len - 1] == 0 { us_len -= 1; } } else { // mpn_hgcd has failed. Then either one of a or b is very small, or the difference is very // small. Perform one subtraction followed by one division. us1[0] = 1; let (scratch, scratch_hi) = scratch.split_at_mut(n); let mut context = ExtendedGcdContext::new(gs, ss, 1, us0, us1, &mut scratch_hi[n..]); // Temporary storage n n = limbs_gcd_subdivide_step(&mut xs[..n], ys, 0, &mut context, scratch); ss_sign = context.ss_sign; if n == 0 { return (context.gs_len, ss_sign); } us_len = context.us_len; assert!(us_len < scratch_len); } while n >= GCDEXT_DC_THRESHOLD { let p = choose_p_2(n); let (scratch_lo, scratch_hi) = scratch.split_at_mut(matrix_scratch); let mut m = HalfGcdMatrix::init(n - p, scratch_lo); let nn = limbs_half_gcd(&mut xs[p..n], &mut ys[p..n], &mut m, scratch_hi); if nn != 0 { let t0 = scratch_hi; assert!(m.n <= (n - p - 1) >> 1); assert!(m.n + p <= (p + n - 1) >> 1); // Temporary storage 2 (p + M->n) <= p + n - 1 n = limbs_half_gcd_matrix_adjust(&m, p + nn, xs, ys, p, t0); // By the same analysis as for mpn_hgcd_matrix_mul assert!(m.n + us_len <= scratch_len); t0[..us_len].copy_from_slice(&us0[..us_len]); // Temporary storage scratch_len let (t0_lo, t0_hi) = t0.split_at_mut(us_len); us_len = limbs_half_gcd_matrix_mul_vector(&mut m, us0, t0_lo, us1, t0_hi); assert!(us_len < scratch_len); assert!(us0[us_len - 1] != 0 || us1[us_len - 1] != 0); } else { // mpn_hgcd has failed. Then either one of a or b is very small, or the difference is // very small. Perform one subtraction followed by one division. let (scratch_lo, scratch_hi) = scratch.split_at_mut(n); let mut context = ExtendedGcdContext::new(gs, ss, us_len, us0, us1, scratch_hi); // Temporary storage n n = limbs_gcd_subdivide_step(&mut xs[..n], &mut ys[..n], 0, &mut context, scratch_lo); ss_sign = context.ss_sign; if n == 0 { return (context.gs_len, ss_sign); } us_len = context.us_len; assert!(us_len < scratch_len); } } let n = n; let xs = &mut xs[..n]; let ys = &mut ys[..n]; // We have // ``` // A = ... a + ... b // B = us0 a + us1 b // // a = us1 A + ... B // b = -us0 A + ... B // ``` // // with bounds |us0|, |us1| <= B / min(a, b) // // We always have us1 > 0, and us0 == 0 is possible only if us1 == 1, in which case the only // reduction done so far is a = A - k B for some k. // // Compute g = u a + v b = (u us1 - v us0) A + (...) B. Here, u, v are bounded by // ``` // |u| <= b, // |v| <= a // ``` assert!(*xs.last().unwrap() != 0 || *ys.last().unwrap() != 0); if limbs_cmp_same_length(xs, ys) == Equal { // Must return the smallest cofactor, +us1 or -us0 gs[..n].copy_from_slice(xs); let c = limbs_cmp_same_length(&us0[..us_len], &us1[..us_len]); // c == 0 can happen only when A = (2k+1) G, B = 2 G. And in this case we choose the // cofactor + 1, corresponding to G = A - k B, rather than -1, corresponding to G = - A + // (k+1) B. assert!(c != Equal || us_len == 1 && us0[0] == 1 && us1[0] == 1); if c == Less { us_len -= slice_trailing_zeros(&us0[..us_len]); ss[..us_len].copy_from_slice(&us0[..us_len]); ss_sign = false; } else { us_len -= slice_trailing_zeros(&us1[..us_len]); assert_ne!(us_len, 0); ss[..us_len].copy_from_slice(&us1[..us_len]); ss_sign = true; } (n, ss_sign) } else if us0[0] == 0 && us_len == 1 { fail_on_untested_path( "limbs_extended_gcd, \ limbs_cmp_same_length(..) != Equal && us0[0] == 0 && us_len == 1", ); assert_eq!(us1[0], 1); // g = u a + v b = (u us1 - v us0) A + (...) B = u A + (...) B let (gs_len, _, ss_sign) = limbs_extended_gcd_same_length_lehmer(gs, ss, xs, ys, scratch); (gs_len, ss_sign) } else { let (lehmer_ss, scratch) = scratch.split_at_mut(n); // Call limbs_extended_gcd_same_length_lehmer with copies of a and b. split_into_chunks_mut!(scratch, n, [scratch_0, scratch_1], scratch_2); scratch_0.copy_from_slice(xs); scratch_1.copy_from_slice(ys); let (gs_len, lehmer_us_len, lehmer_us_sign) = limbs_extended_gcd_same_length_lehmer(gs, lehmer_ss, scratch_0, scratch_1, scratch_2); let us0_len = us_len - slice_trailing_zeros(&us0[..us_len]); let us0 = &us0[..us0_len]; assert_ne!(us0_len, 0); if lehmer_us_len == 0 { // u == 0 ==> v = g / b == 1 ==> g = - us0 A + (...) B ss[..us0_len].copy_from_slice(us0); return (gs_len, false); } let lehmer_ss = &lehmer_ss[..lehmer_us_len]; let (lehmer_vs, scratch_hi) = scratch.split_at_mut(n + 1); // Compute v = (g - u a) / b let lehmer_vs_len = limbs_extended_gcd_cofactor( lehmer_vs, xs, ys, &gs[..gs_len], lehmer_ss, lehmer_us_len, lehmer_us_sign, scratch_hi, ); let mut us1_len = us_len - slice_trailing_zeros(&us1[..us_len]); assert_ne!(us1_len, 0); assert!(lehmer_vs_len + us0_len <= scratch_len); // - We may still have v == 0 // - Compute u us0 let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(us1_len, lehmer_ss.len())]; limbs_mul_to_out(ss, &us1[..us1_len], lehmer_ss, &mut mul_scratch); us_len = us1_len + lehmer_us_len; assert!(us_len <= scratch_len); if ss[us_len - 1] == 0 { us_len -= 1; } if lehmer_vs_len != 0 { // Overwrites old us1 value let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(us0.len(), lehmer_vs_len)]; limbs_mul_to_out(us1, us0, &lehmer_vs[..lehmer_vs_len], &mut mul_scratch); us1_len = us0_len + lehmer_vs_len; if us1[us1_len - 1] == 0 { us1_len -= 1; } let us1 = &us1[..us1_len]; let carry = if us1_len <= us_len { limbs_slice_add_greater_in_place_left(&mut ss[..us_len], us1) } else { let old_us_len = us_len; us_len = us1_len; limbs_add_to_out_aliased(&mut ss[..us1_len], old_us_len, us1) }; ss[us_len] = Limb::from(carry); if carry { us_len += 1; } assert!(us_len < scratch_len); } (gs_len, lehmer_us_sign) } } fn extended_gcd_helper(a: Natural, b: Natural) -> (Natural, Integer, Integer) { let mut xs = a.to_limbs_asc(); let mut ys = b.to_limbs_asc(); let mut a = Integer::from(a); let mut b = Integer::from(b); let mut swapped = false; if xs.len() < ys.len() { swap(&mut xs, &mut ys); swap(&mut a, &mut b); swapped = true; } let mut gs = vec![0; ys.len()]; let mut ss = vec![0; ys.len() + 1]; let (g_len, ss_sign) = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); gs.truncate(g_len); let gcd = Natural::from_owned_limbs_asc(gs); let mut s = Integer::from_sign_and_abs(ss_sign, Natural::from_owned_limbs_asc(ss)); let mut t = (Integer::from(&gcd) - a * &s).div_exact(b); if swapped { swap(&mut s, &mut t); } (gcd, s, t) } impl ExtendedGcd for Natural { type Gcd = Self; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Natural`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Natural`]s are /// taken by value. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(a, b)$, where /// $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq \lfloor /// a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32) /// .extended_gcd(Natural::from(5u32)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// Natural::from(240u32) /// .extended_gcd(Natural::from(46u32)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// ``` fn extended_gcd(self, other: Self) -> (Self, Integer, Integer) { match (self, other) { (Self::ZERO, Self::ZERO) => (Self::ZERO, Integer::ZERO, Integer::ZERO), (a, b) if a == b => (b, Integer::ZERO, Integer::ONE), (Self::ZERO, b) => (b, Integer::ZERO, Integer::ONE), (a, Self::ZERO) => (a, Integer::ONE, Integer::ZERO), (Self(Small(x)), Self(Small(y))) => { let (gcd, s, t) = x.extended_gcd(y); (Self::from(gcd), Integer::from(s), Integer::from(t)) } (a, b) => extended_gcd_helper(a, b), } } } impl<'a> ExtendedGcd<&'a Self> for Natural { type Gcd = Self; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Natural`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Natural`] is /// taken by value and the second by reference. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(a, b)$, where /// $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq \lfloor /// a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32) /// .extended_gcd(&Natural::from(5u32)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// Natural::from(240u32) /// .extended_gcd(&Natural::from(46u32)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// ``` fn extended_gcd(self, other: &'a Self) -> (Self, Integer, Integer) { match (self, other) { (Self::ZERO, &Self::ZERO) => (Self::ZERO, Integer::ZERO, Integer::ZERO), (a, b) if a == *b => (b.clone(), Integer::ZERO, Integer::ONE), (Self::ZERO, b) => (b.clone(), Integer::ZERO, Integer::ONE), (a, &Self::ZERO) => (a, Integer::ONE, Integer::ZERO), (Self(Small(x)), Self(Small(y))) => { let (gcd, s, t) = x.extended_gcd(*y); (Self::from(gcd), Integer::from(s), Integer::from(t)) } (a, b) => extended_gcd_helper(a, b.clone()), } } } impl ExtendedGcd for &Natural { type Gcd = Natural; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Natural`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. The first [`Natural`] is /// taken by reference and the second by value. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(a, b)$, where /// $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq \lfloor /// a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)) /// .extended_gcd(Natural::from(5u32)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// (&Natural::from(240u32)) /// .extended_gcd(Natural::from(46u32)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// ``` fn extended_gcd(self, other: Natural) -> (Natural, Integer, Integer) { match (self, other) { (&Natural::ZERO, Natural::ZERO) => (Natural::ZERO, Integer::ZERO, Integer::ZERO), (a, b) if *a == b => (b, Integer::ZERO, Integer::ONE), (&Natural::ZERO, b) => (b, Integer::ZERO, Integer::ONE), (a, Natural::ZERO) => (a.clone(), Integer::ONE, Integer::ZERO), (Natural(Small(x)), Natural(Small(y))) => { let (gcd, s, t) = x.extended_gcd(y); (Natural::from(gcd), Integer::from(s), Integer::from(t)) } (a, b) => extended_gcd_helper(a.clone(), b), } } } impl ExtendedGcd<&Natural> for &Natural { type Gcd = Natural; type Cofactor = Integer; /// Computes the GCD (greatest common divisor) of two [`Natural`]s $a$ and $b$, and also the /// coefficients $x$ and $y$ in Bézout's identity $ax+by=\gcd(a,b)$. Both [`Natural`]s are /// taken by reference. /// /// The are infinitely many $x$, $y$ that satisfy the identity for any $a$, $b$, so the full /// specification is more detailed: /// /// - $f(0, 0) = (0, 0, 0)$. /// - $f(a, ak) = (a, 1, 0)$ if $a > 0$ and $k \neq 1$. /// - $f(bk, b) = (b, 0, 1)$ if $b > 0$. /// - $f(a, b) = (g, x, y)$ if $a \neq 0$ and $b \neq 0$ and $\gcd(a, b) \neq \min(a, b)$, where /// $g = \gcd(a, b) \geq 0$, $ax + by = g$, $x \leq \lfloor b/g \rfloor$, and $y \leq \lfloor /// a/g \rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ExtendedGcd; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)) /// .extended_gcd(&Natural::from(5u32)) /// .to_debug_string(), /// "(1, 2, -1)" /// ); /// assert_eq!( /// (&Natural::from(240u32)) /// .extended_gcd(&Natural::from(46u32)) /// .to_debug_string(), /// "(2, -9, 47)" /// ); /// ``` fn extended_gcd(self, other: &Natural) -> (Natural, Integer, Integer) { match (self, other) { (&Natural::ZERO, &Natural::ZERO) => (Natural::ZERO, Integer::ZERO, Integer::ZERO), (a, b) if a == b => (b.clone(), Integer::ZERO, Integer::ONE), (&Natural::ZERO, b) => (b.clone(), Integer::ZERO, Integer::ONE), (a, &Natural::ZERO) => (a.clone(), Integer::ONE, Integer::ZERO), (Natural(Small(x)), Natural(Small(y))) => { let (gcd, s, t) = x.extended_gcd(*y); (Natural::from(gcd), Integer::from(s), Integer::from(t)) } (a, b) => extended_gcd_helper(a.clone(), b.clone()), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/gcd/half_gcd.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2019 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div_mod::{ limbs_div_limb_to_out_mod, limbs_div_mod_qs_to_out_rs_to_ns, }; use crate::natural::arithmetic::gcd::matrix_2_2::limbs_matrix_2_2_mul; use crate::natural::arithmetic::mul::limb::{limbs_mul_limb_to_out, limbs_slice_mul_limb_in_place}; use crate::natural::arithmetic::mul::mul_mod::{ limbs_mul_mod_base_pow_n_minus_1, limbs_mul_mod_base_pow_n_minus_1_next_size, limbs_mul_mod_base_pow_n_minus_1_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::{bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::{DoubleLimb, Limb}; use core::cmp::{Ordering::*, max, min}; use core::mem::swap; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ DivMod, Gcd, Parity, WrappingAddAssign, XMulYToZZ, XXDivModYToQR, XXSubYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, JoinHalves, SplitInHalf, WrappingFrom}; use malachite_base::num::logic::traits::{LeadingZeros, NotAssign, TrailingZeros}; use malachite_base::slices::{slice_set_zero, slice_test_zero, slice_trailing_zeros}; pub(crate) trait GcdSubdivideStepContext { fn gcd_subdiv_step_hook( &mut self, g: Option<&[Limb]>, q: Option<&mut [Limb]>, q_len: usize, d: i8, ); fn gcd_subdiv_step_hook_with_1(&mut self, d: i8) { self.gcd_subdiv_step_hook(None, Some(&mut [1]), 1, d); } } /// This is equivalent to `gcd_ctx` from `mpn/gcd.c`, GMP 6.2.1. struct GcdContext<'a>(&'a mut [Limb]); impl GcdSubdivideStepContext for GcdContext<'_> { /// This is equivalent to `gcd_hook` from `mpn/gcd.c`, GMP 6.2.1. fn gcd_subdiv_step_hook( &mut self, g: Option<&[Limb]>, _q: Option<&mut [Limb]>, _q_len: usize, _d: i8, ) { if let Some(g) = g { self.0[..g.len()].copy_from_slice(g); } } } #[cfg(feature = "test_build")] pub struct HalfGcdMatrix<'a> { pub(crate) data: &'a mut [Limb], pub(crate) s: usize, pub(crate) two_s: usize, pub(crate) three_s: usize, pub(crate) n: usize, } #[cfg(not(feature = "test_build"))] pub(crate) struct HalfGcdMatrix<'a> { data: &'a mut [Limb], pub(crate) s: usize, two_s: usize, three_s: usize, pub(crate) n: usize, } impl HalfGcdMatrix<'_> { // # Worst-case complexity // Constant time and additional memory. pub_crate_test! {get(&self, row: u8, column: u8) -> &[Limb] { match (row, column) { (0, 0) => &self.data[..self.s], (0, 1) => &self.data[self.s..self.two_s], (1, 0) => &self.data[self.two_s..self.three_s], (1, 1) => &self.data[self.three_s..], _ => panic!(), } }} // # Worst-case complexity // Constant time and additional memory. pub_test! {get_mut(&mut self, row: u8, column: u8) -> &mut [Limb] { match (row, column) { (0, 0) => &mut self.data[..self.s], (0, 1) => &mut self.data[self.s..self.two_s], (1, 0) => &mut self.data[self.two_s..self.three_s], (1, 1) => &mut self.data[self.three_s..], _ => panic!(), } }} // # Worst-case complexity // Constant time and additional memory. #[inline] fn get_two_mut( &mut self, row_1: u8, column_1: u8, row_2: u8, column_2: u8, ) -> (&mut [Limb], &mut [Limb]) { match (row_1, column_1, row_2, column_2) { (0, 0, 0, 1) => self.data[..self.two_s].split_at_mut(self.s), (0, 1, 0, 0) => { let (xs, ys) = self.data[..self.two_s].split_at_mut(self.s); (ys, xs) } (1, 0, 1, 1) => self.data[self.two_s..].split_at_mut(self.s), (1, 1, 1, 0) => { let (xs, ys) = self.data[self.two_s..].split_at_mut(self.s); (ys, xs) } _ => panic!(), } } // # Worst-case complexity // Constant time and additional memory. #[inline] pub(crate) fn get_four(&mut self) -> (&[Limb], &[Limb], &[Limb], &[Limb]) { split_into_chunks!(self.data, self.s, [x00, x01, x10], x11); (x00, x01, x10, x11) } // # Worst-case complexity // Constant time and additional memory. #[inline] fn get_four_mut(&mut self) -> (&mut [Limb], &mut [Limb], &mut [Limb], &mut [Limb]) { split_into_chunks_mut!(self.data, self.s, [x00, x01, x10], x11); (x00, x01, x10, x11) } // # Worst-case complexity // Constant time and additional memory. pub_const_test! {min_init_scratch(n: usize) -> usize { (((n + 1) >> 1) + 1) << 2 }} // For input of size n, matrix elements are of size at most ceil(n / 2) - 1, but we need two // limbs extra. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `p.len()`. // // This is equivalent to `mpn_hgcd_matrix_init` from `mpn/generic/hgcd_matrix.c`, GMP 6.2.1, // where the matrix is returned. pub_crate_test! {init(n: usize, p: &mut [Limb]) -> HalfGcdMatrix<'_> { let s = n.div_ceil(2) + 1; let two_s = s << 1; let three_s = two_s + s; slice_set_zero(&mut p[..s << 2]); let mut m = HalfGcdMatrix { data: p, s, two_s, three_s, n: 1, }; m.get_mut(0, 0)[0] = 1; m.get_mut(1, 1)[0] = 1; m }} // # Worst-case complexity // Constant time and additional memory. pub_const_test! {update_q_scratch_len(&self, qs_len: usize) -> usize { self.n + qs_len }} // # Worst-case complexity // Constant time and additional memory. fn all_elements_zero_at_index(&self, i: usize) -> bool { self.get(0, 0)[i] == 0 && self.get(0, 1)[i] == 0 && self.get(1, 0)[i] == 0 && self.get(1, 1)[i] == 0 } } // Multiply M by M1 from the right. Needs 3*(M->n + M1->n) + 5 limbs of temporary storage (see // mpn_matrix22_mul_itch). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(a.n, b.n)`. // // This is equivalent to `mpn_hgcd_matrix_mul` from `mpn/generic/hgcd_matrix.c`, GMP 6.2.1. pub_crate_test! {limbs_half_gcd_matrix_mul_matrix( a: &mut HalfGcdMatrix, b: &HalfGcdMatrix, scratch: &mut [Limb] ) { // About the new size of M:s elements. Since M1's diagonal elements are > 0, no element can // decrease. The new elements are of size M->n + M1->n, one limb more or less. The computation // of the matrix product produces elements of size M->n + M1->n + 1. But the true size, after // normalization, may be three limbs smaller. // // The reason that the product has normalized size >= M->n + M1->n - 2 is subtle. It depends on // the fact that M and M1 can be factored as products of (1,1; 0,1) and (1,0; 1,1), and that we // can't have M ending with a large power and M1 starting with a large power of the same matrix. assert!(a.n + b.n < a.s); assert!(!a.all_elements_zero_at_index(a.n - 1)); let b_n = b.n; assert!(!b.all_elements_zero_at_index(b_n - 1)); let n = a.n; let (x00, x01, x10, x11) = a.get_four_mut(); limbs_matrix_2_2_mul( x00, x01, x10, x11, n, &b.get(0, 0)[..b_n], &b.get(0, 1)[..b_n], &b.get(1, 0)[..b_n], &b.get(1, 1)[..b_n], scratch, ); // Index of last potentially non-zero limb, size is one greater. let mut n = a.n + b_n; for _ in 0..3 { if a.all_elements_zero_at_index(n) { n -= 1; } } assert!(!a.all_elements_zero_at_index(n)); a.n = n + 1; }} // Multiply M by M1 from the right. Since the M1 elements fit in Limb::WIDTH - 1 bits, M grows by at // most one limb. Needs temporary space M->n // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `a.n`. // // This is equivalent to `mpn_hgcd_matrix_mul_1` from `mpn/generic/hgcd_matrix.c`, GMP 6.2.1. pub_crate_test! {limbs_half_gcd_matrix_mul_matrix_1( a: &mut HalfGcdMatrix, b: &HalfGcdMatrix1, scratch: &mut [Limb], ) { let n = a.n; let scratch = &mut scratch[..n]; scratch.copy_from_slice(&a.get(0, 0)[..n]); let (a_0_0, a_0_1) = a.get_two_mut(0, 0, 0, 1); let n0 = limbs_half_gcd_matrix_1_mul_vector(b, a_0_0, scratch, a_0_1); scratch.copy_from_slice(&a.get(1, 0)[..n]); let (a_1_0, a_1_1) = a.get_two_mut(1, 0, 1, 1); let n1 = limbs_half_gcd_matrix_1_mul_vector(b, a_1_0, scratch, a_1_1); a.n = max(n0, n1); assert!(a.n <= a.s); }} // Update column `column`, adding in Q * column (1-`col`). Temporary storage: qn + n <= `self.s`, // where n is the size of the largest element in column 1 - `column`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `m.n`. // // This is equivalent to `mpn_hgcd_matrix_update_q` from `mpn/generic/hgcd_matrix.c`, GMP 6.2.1. pub_crate_test! {limbs_half_gcd_matrix_update_q( m: &mut HalfGcdMatrix, qs: &[Limb], column: u8, scratch: &mut [Limb], ) { let qs_len = qs.len(); assert!(qs_len + m.n <= m.s); assert!(column < 2); if qs_len == 1 { let q = qs[0]; let n = m.n; let (m_0_a, m_0_b) = m.get_two_mut(0, column, 0, 1 - column); let carry_0 = limbs_slice_add_mul_limb_same_length_in_place_left(&mut m_0_a[..n], &m_0_b[..n], q); let (m_1_a, m_1_b) = m.get_two_mut(1, column, 1, 1 - column); let carry_1 = limbs_slice_add_mul_limb_same_length_in_place_left(&mut m_1_a[..n], &m_1_b[..n], q); m.get_mut(0, column)[n] = carry_0; m.get_mut(1, column)[n] = carry_1; if carry_0 != 0 || carry_1 != 0 { m.n += 1; } } else { // Carries for the unlikely case that we get both high words from the multiplication and // carries from the addition. let mut carries = [0; 2]; // The matrix will not necessarily grow in size by qn, so we need normalization in order not // to overflow m. let mut n = m.n; while n + qs_len > m.n { assert_ne!(n, 0); if m.get(0, 1 - column)[n - 1] > 0 || m.get(1, 1 - column)[n - 1] > 0 { break; } n -= 1; } assert!(qs_len + n <= m.s); if n != 0 { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(n, qs_len)]; for row in 0..2 { limbs_mul_to_out( scratch, &m.get(row, 1 - column)[..n], &qs[..qs_len], &mut mul_scratch, ); assert!(n + qs_len >= m.n); let m_n = m.n; if limbs_add_to_out_aliased(m.get_mut(row, column), m_n, &scratch[..n + qs_len]) { carries[usize::wrapping_from(row)] = 1; } } } n += qs_len; if carries[0] != 0 || carries[1] != 0 { m.get_mut(0, column)[n] = carries[0]; m.get_mut(1, column)[n] = carries[1]; n += 1; } else if m.get(0, column)[n - 1] == 0 && m.get(1, column)[n - 1] == 0 { n -= 1; } m.n = n; } assert!(m.n <= m.s); }} // - Multiplies the least significant p limbs of (X;Y) by M^-1. // - Temporary space needed: 2 * (p + m.n) // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_hgcd_matrix_adjust` from `mpn/generic/hgcd_matrix.c`, GMP 6.2.1. pub(crate) fn limbs_half_gcd_matrix_adjust( m: &HalfGcdMatrix, mut n: usize, xs: &mut [Limb], ys: &mut [Limb], p: usize, scratch: &mut [Limb], ) -> usize { // M^-1 (X; Y) = (r11, -r01; -r10, r00) (a ; b) = (r11 x - r01 y; - r10 x + r00 y) let xs_init = &mut xs[..n]; let ys_init = &mut ys[..n]; let (scratch_lo, scratch_hi) = scratch.split_at_mut(p + m.n); assert!(p + m.n < n); let (xs_lo, xs_hi) = xs_init.split_at_mut(p); // First compute the two values depending on X, before overwriting X let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(m.n, p)]; limbs_mul_to_out(scratch_lo, &m.get(1, 1)[..m.n], xs_lo, &mut mul_scratch); limbs_mul_to_out(scratch_hi, &m.get(1, 0)[..m.n], xs_lo, &mut mul_scratch); // Update X let (scratch_lo_lo, scratch_lo_hi) = scratch_lo.split_at(p); xs_lo.copy_from_slice(scratch_lo_lo); let mut x_high = limbs_slice_add_greater_in_place_left(xs_hi, scratch_lo_hi); let (ys_lo, ys_hi) = ys_init.split_at_mut(p); limbs_mul_to_out(scratch_lo, &m.get(0, 1)[..m.n], ys_lo, &mut mul_scratch); if limbs_sub_greater_in_place_left(xs_init, scratch_lo) { assert!(x_high); x_high = false; } // Update Y limbs_mul_to_out(scratch_lo, &m.get(0, 0)[..m.n], ys_lo, &mut mul_scratch); let (scratch_lo_lo, scratch_lo_hi) = scratch_lo.split_at(p); ys_lo.copy_from_slice(scratch_lo_lo); let mut y_high = limbs_slice_add_greater_in_place_left(ys_hi, scratch_lo_hi); if limbs_sub_greater_in_place_left(ys_init, &scratch_hi[..p + m.n]) { assert!(y_high); y_high = false; } if x_high || y_high { xs[n] = Limb::from(x_high); ys[n] = Limb::from(y_high); n += 1; } else { // The subtraction can reduce the size by at most one limb. if xs[n - 1] == 0 && ys[n - 1] == 0 { n -= 1; } } assert!(xs[n - 1] != 0 || ys[n - 1] != 0); n } // Computes (x, y) <- M^(-1) (x; y) // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `m.len()`. // // This is equivalent to `mpn_hgcd_matrix_apply` from `mpn/generic/hgcd_reduce.c`, GMP 6.2.1. fn limbs_half_gcd_matrix_apply(m: &HalfGcdMatrix, xs: &mut [Limb], ys: &mut [Limb]) -> usize { let mut n = xs.len(); assert_eq!(ys.len(), n); assert!(xs[n - 1] != 0 || ys[n - 1] != 0); let xs_len = n - slice_trailing_zeros(&xs[..n]); let ys_len = n - slice_trailing_zeros(&ys[..n]); let xs_lo = &mut xs[..xs_len]; let ys_lo = &mut ys[..ys_len]; let mut m_lens = [[0usize; 2]; 2]; for (i, row) in m_lens.iter_mut().enumerate() { for (j, len) in row.iter_mut().enumerate() { *len = m.n - slice_trailing_zeros(&m.get(i as u8, j as u8)[..m.n]); } } assert_ne!(m_lens[0][0], 0); assert_ne!(m_lens[1][1], 0); assert!(m_lens[0][1] != 0 || m_lens[1][0] != 0); if m_lens[0][1] == 0 { // X unchanged, M = (1, 0; q, 1) assert_eq!(m_lens[0][0], 1); assert_eq!(m.get(0, 0)[0], 1); assert_eq!(m_lens[1][1], 1); assert_eq!(m.get(1, 1)[0], 1); // Put Y <- Y - q X limbs_gcd_sub_mul(ys_lo, xs_lo, &m.get(1, 0)[..m_lens[1][0]]) } else if m_lens[1][0] == 0 { fail_on_untested_path("limbs_half_gcd_matrix_apply, m_lens[1][0] == 0"); // Y unchanged, M = (1, q; 0, 1) assert_eq!(m_lens[0][0], 1); assert_eq!(m.get(0, 0)[0], 1); assert_eq!(m_lens[1][1], 1); assert_eq!(m.get(1, 1)[0], 1); // Put X <- X - q * Y limbs_gcd_sub_mul(xs_lo, ys_lo, &m.get(0, 1)[..m_lens[0][1]]) } else { // - X = m00 x + m01 y => x <= X / m00, y <= X / m01. // - Y = m10 x + m11 y => x <= Y / m10, y <= Y / m11. let mut new_n = max( min(xs_len - m_lens[0][0], ys_len - m_lens[1][0]), min(xs_len - m_lens[0][1], ys_len - m_lens[1][1]), ) + 1; // In the range of interest, mulmod_bnm1 should always beat mullo. let mod_n = limbs_mul_mod_base_pow_n_minus_1_next_size(new_n + 1); let mut big_scratch = vec![0; (mod_n << 1) + limbs_mul_mod_base_pow_n_minus_1_scratch_len(mod_n, mod_n, m.n)]; split_into_chunks_mut!(big_scratch, mod_n, [scratch, scratch_lo], scratch_hi); assert!(n <= mod_n << 1); if n > mod_n { let (xs_lo, xs_hi) = xs.split_at_mut(mod_n); if limbs_slice_add_greater_in_place_left(xs_lo, xs_hi) { assert!(!limbs_slice_add_limb_in_place(xs, 1)); } let (ys_lo, ys_hi) = ys.split_at_mut(mod_n); if limbs_slice_add_greater_in_place_left(ys_lo, ys_hi) { assert!(!limbs_slice_add_limb_in_place(ys, 1)); } n = mod_n; } let xs = &mut xs[..n]; let ys = &mut ys[..n]; limbs_mul_mod_base_pow_n_minus_1( scratch, mod_n, xs, &m.get(1, 1)[..m_lens[1][1]], scratch_hi, ); limbs_mul_mod_base_pow_n_minus_1( scratch_lo, mod_n, ys, &m.get(0, 1)[..m_lens[0][1]], scratch_hi, ); if n + m_lens[1][1] < mod_n { slice_set_zero(&mut scratch[n + m_lens[1][1]..]); } if n + m_lens[0][1] < mod_n { slice_set_zero(&mut scratch_lo[n + m_lens[0][1]..]); } if limbs_sub_same_length_in_place_left(scratch, scratch_lo) { assert!(!limbs_sub_limb_in_place(scratch, 1)); } let (scratch_0, scratch_1) = scratch.split_at(new_n); assert!(slice_test_zero(scratch_1)); limbs_mul_mod_base_pow_n_minus_1( scratch_lo, mod_n, xs, &m.get(1, 0)[..m_lens[1][0]], scratch_hi, ); xs[..new_n].copy_from_slice(scratch_0); limbs_mul_mod_base_pow_n_minus_1( scratch, mod_n, ys, &m.get(0, 0)[..m_lens[0][0]], scratch_hi, ); if n + m_lens[1][0] < mod_n { slice_set_zero(&mut scratch_lo[n + m_lens[1][0]..]); } if n + m_lens[0][0] < mod_n { slice_set_zero(&mut scratch[n + m_lens[0][0]..]); } if limbs_sub_same_length_in_place_left(scratch, scratch_lo) { assert!(!limbs_sub_limb_in_place(scratch, 1)); } let (scratch_0, scratch_1) = scratch.split_at(new_n); assert!(slice_test_zero(scratch_1)); ys[..new_n].copy_from_slice(scratch_0); while xs[new_n - 1] | ys[new_n - 1] == 0 { new_n -= 1; assert_ne!(new_n, 0); } new_n } } /// This is equivalent to `mpn_hgcd_reduce` from `mpn/generic/hgcd_reduce.c`, GMP 6.2.1. fn limbs_half_gcd_matrix_reduce( m: &mut HalfGcdMatrix, xs: &mut [Limb], ys: &mut [Limb], p: usize, scratch: &mut [Limb], ) -> usize { let n = xs.len(); assert_eq!(ys.len(), n); let com_p = n - p; if n < HGCD_REDUCE_THRESHOLD { let new_n = limbs_half_gcd(&mut xs[p..], &mut ys[p..], m, scratch); if new_n == 0 { 0 } else { // Needs 2 * (p + m.n) <= 2 * (floor(n / 2) + ceil(n / 2) - 1) = 2 (n - 1) limbs_half_gcd_matrix_adjust(m, p + new_n, xs, ys, p, scratch) } } else { split_into_chunks_mut!(scratch, com_p, [scratch_0, scratch_1], scratch_2); scratch_0.copy_from_slice(&xs[p..]); scratch_1.copy_from_slice(&ys[p..]); if limbs_half_gcd_approx(scratch_0, scratch_1, m, scratch_2) { limbs_half_gcd_matrix_apply(m, xs, ys) } else { 0 } } } // Computes R -= X * Y. Result must be non-negative. Normalized down to size xs_len, and resulting // size is returned. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `submul` from `mpn/generic/hgcd_reduce.c`, GMP 6.2.1. fn limbs_gcd_sub_mul(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> usize { let mut out_len = out.len(); let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); assert!(out_len >= xs_len); let sum_len = xs_len + ys_len; assert!(sum_len <= out_len + 1); let mut scratch = vec![0; sum_len]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; limbs_mul_greater_to_out(&mut scratch, xs, ys, &mut mul_scratch); assert!(sum_len <= out_len || scratch[out_len] == 0); let mut scratch_len = sum_len; if scratch_len > out_len { scratch_len -= 1; } assert!(!limbs_sub_greater_in_place_left( out, &scratch[..scratch_len] )); while out_len > xs_len && out[out_len - 1] == 0 { out_len -= 1; } out_len } #[cfg(feature = "test_build")] #[derive(Clone, Debug, Default)] pub struct HalfGcdMatrix1 { pub data: [[Limb; 2]; 2], } #[cfg(not(feature = "test_build"))] #[derive(Default)] pub(crate) struct HalfGcdMatrix1 { pub(crate) data: [[Limb; 2]; 2], } // Sets (r;b) = (a;b) M, with M = (u00, u01; u10, u11). Vector must have space for n + 1 limbs. Uses // three buffers to avoid a copy // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `m.n`. // // This is equivalent to `mpn_hgcd_mul_matrix1_vector` from `mpn/generic/hgcd2.c`, GMP 6.2.1. pub_crate_test! {limbs_half_gcd_matrix_1_mul_vector( m: &HalfGcdMatrix1, out: &mut [Limb], xs: &[Limb], ys: &mut [Limb], ) -> usize { let n = xs.len(); assert!(ys.len() > n); assert!(out.len() > n); let (out_lo, out_hi) = out.split_at_mut(n); let (ys_lo, ys_hi) = ys.split_at_mut(n); let mut x_high = limbs_mul_limb_to_out::(out_lo, xs, m.data[0][0]); x_high.wrapping_add_assign( limbs_slice_add_mul_limb_same_length_in_place_left(out_lo, ys_lo, m.data[1][0]) ); let mut y_high = limbs_slice_mul_limb_in_place(ys_lo, m.data[1][1]); y_high.wrapping_add_assign( limbs_slice_add_mul_limb_same_length_in_place_left(ys_lo, xs, m.data[0][1]) ); out_hi[0] = x_high; ys_hi[0] = y_high; if x_high == 0 && y_high == 0 { n } else { n + 1 } }} // Compute (r;y) <- (u11 x - u01 y; -u10 x + u00 y) xs // ``` // r = u11 * x // r -= u01 * y // y *= u00 // y -= u10 * x // ``` // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `m.len()`. // // This is equivalent to `mpn_matrix22_mul1_inverse_vector` from // `mpn/generic/matrix22_mul1_inverse_vector.c`, GMP 6.2.1. pub(crate) fn limbs_half_gcd_matrix_1_mul_inverse_vector( m: &HalfGcdMatrix1, out: &mut [Limb], xs: &[Limb], ys: &mut [Limb], ) -> usize { let n = xs.len(); assert_eq!(ys.len(), n); assert_eq!(out.len(), n); let h0 = limbs_mul_limb_to_out::(out, xs, m.data[1][1]); let h1 = limbs_sub_mul_limb_same_length_in_place_left(out, ys, m.data[0][1]); assert_eq!(h0, h1); let h0 = limbs_slice_mul_limb_in_place(ys, m.data[0][0]); let h1 = limbs_sub_mul_limb_same_length_in_place_left(ys, xs, m.data[1][0]); assert_eq!(h0, h1); if out[n - 1] == 0 && ys[n - 1] == 0 { n - 1 } else { n } } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_gcd_subdiv_step` from `mpn/generic/gcd_subdiv_step.c`, GMP 6.2.1. pub(crate) fn limbs_gcd_subdivide_step<'a, CTX: GcdSubdivideStepContext>( mut xs: &'a mut [Limb], mut ys: &'a mut [Limb], s: usize, context: &mut CTX, scratch: &mut [Limb], ) -> usize { let n = xs.len(); assert_eq!(ys.len(), n); assert_ne!(n, 0); assert!(xs[n - 1] > 0 || ys[n - 1] > 0); let mut xs_len = n - slice_trailing_zeros(xs); let mut ys_len = n - slice_trailing_zeros(ys); let mut xs_init = &mut xs[..xs_len]; let mut ys_init = &mut ys[..ys_len]; let mut swapped = false; // Arrange so that x < y, subtract y -= x, and maintain normalization. match xs_len.cmp(&ys_len) { Equal => { match limbs_cmp_same_length(xs_init, ys_init) { Equal => { // For gcdext, return the smallest of the two cofactors. if s == 0 { context.gcd_subdiv_step_hook(Some(xs_init), None, 0, -1); } return 0; } Greater => { swap(&mut xs, &mut ys); xs_init = &mut xs[..xs_len]; ys_init = &mut ys[..ys_len]; swapped.not_assign(); } _ => {} } } Greater => { swap(&mut xs, &mut ys); swap(&mut xs_len, &mut ys_len); xs_init = &mut xs[..xs_len]; ys_init = &mut ys[..ys_len]; swapped.not_assign(); } Less => {} } if xs_len <= s { if s == 0 { context.gcd_subdiv_step_hook(Some(ys_init), None, 0, i8::from(!swapped)); } return 0; } assert!(!limbs_sub_greater_in_place_left(ys_init, xs_init)); ys_len -= slice_trailing_zeros(ys_init); ys_init = &mut ys_init[..ys_len]; assert_ne!(ys_len, 0); if ys_len <= s { // Undo subtraction if limbs_add_to_out_aliased(ys, ys_len, xs_init) { ys[xs_len] = 1; } return 0; } // Arrange so that x < y match xs_len.cmp(&ys_len) { Equal => { match limbs_cmp_same_length(xs_init, ys_init) { Equal => { fail_on_untested_path("limbs_gcd_subdivide_step, c == Equal"); if s != 0 { // Just record subtraction and return context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); } else { // Found gcd. context.gcd_subdiv_step_hook(Some(ys_init), None, 0, i8::from(swapped)); return 0; } } Greater => { context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); swap(&mut xs, &mut ys); xs_init = &mut xs[..xs_len]; ys_init = &mut ys[..ys_len]; swapped.not_assign(); } Less => { context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); } } } Greater => { context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); swap(&mut xs, &mut ys); swap(&mut xs_len, &mut ys_len); xs_init = &mut xs[..xs_len]; ys_init = &mut ys[..ys_len]; swapped.not_assign(); } Less => { context.gcd_subdiv_step_hook_with_1(i8::from(swapped)); } } if xs_len == 1 { if ys_init.len() == 1 { (scratch[0], ys_init[0]) = ys_init[0].div_mod(xs_init[0]); } else { ys_init[0] = limbs_div_limb_to_out_mod(scratch, ys_init, xs_init[0]); } } else { limbs_div_mod_qs_to_out_rs_to_ns(scratch, ys_init, xs_init); } let qn = ys_len - xs_len + 1; let ys_len = xs_len - slice_trailing_zeros(&ys_init[..xs_len]); if ys_len <= s { if s == 0 { context.gcd_subdiv_step_hook(Some(xs_init), Some(scratch), qn, i8::from(swapped)); return 0; } // Quotient is one too large, so decrement it and add back X. if ys_len != 0 { if limbs_add_to_out_aliased(ys, ys_len, xs_init) { ys[xs_len] = 1; xs_len += 1; } } else { ys[..xs_len].copy_from_slice(xs_init); } assert!(!limbs_sub_limb_in_place(&mut scratch[..qn], 1)); } context.gcd_subdiv_step_hook(None, Some(scratch), qn, i8::from(swapped)); xs_len } impl GcdSubdivideStepContext for HalfGcdMatrix<'_> { // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `q_len`. // // This is equivalent to `hgcd_hook` from `mpn/generic/hgcd_step.c`, GMP 6.2.1. fn gcd_subdiv_step_hook( &mut self, g: Option<&[Limb]>, q: Option<&mut [Limb]>, mut q_len: usize, d: i8, ) { assert!(g.is_none()); let q = q.unwrap(); q_len -= slice_trailing_zeros(&q[..q_len]); if q_len != 0 { let (q, scratch) = q.split_at_mut(q_len); limbs_half_gcd_matrix_update_q(self, q, u8::exact_from(d), scratch); } } } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `MPN_EXTRACT_NUMB` from `gmp-impl.h`, GMP 6.2.1. pub(crate) const fn extract_number(count: u64, x1: Limb, x0: Limb) -> Limb { (x1 << count) | (x0 >> (Limb::WIDTH - count)) } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `div2` from `mpn/generic/hgcd2.c`, GMP 6.2.1, where `HGCD2_DIV2_METHOD == // 1`. pub_crate_test! {limbs_gcd_div( mut n1: Limb, mut n0: Limb, mut d1: Limb, mut d0: Limb ) -> (Limb, Limb, Limb) { let (mut q, r) = n1.div_mod(d1); if q > d1 { // Normalize let c = LeadingZeros::leading_zeros(d1); let width_comp = Limb::WIDTH - c; assert_ne!(c, 0); let n2 = n1 >> width_comp; n1 = (n1 << c) | (n0 >> width_comp); n0 <<= c; d1 = (d1 << c) | (d0 >> width_comp); d0 <<= c; (q, n1) = Limb::xx_div_mod_y_to_qr(n2, n1, d1); let (mut t1, mut t0) = Limb::x_mul_y_to_zz(q, d0); if t1 > n1 || t1 == n1 && t0 > n0 { assert_ne!(q, 0); q -= 1; (t1, t0) = Limb::xx_sub_yy_to_zz(t1, t0, d1, d0); } (n1, n0) = Limb::xx_sub_yy_to_zz(n1, n0, t1, t0); // Undo normalization (q, n1 >> c, (n0 >> c) | (n1 << width_comp)) } else { n1 = r; let (mut t1, mut t0) = Limb::x_mul_y_to_zz(q, d0); if t1 >= n1 && (t1 > n1 || t0 > n0) { assert_ne!(q, 0); q -= 1; (t1, t0) = Limb::xx_sub_yy_to_zz(t1, t0, d1, d0); } let (r1, r0) = Limb::xx_sub_yy_to_zz(n1, n0, t1, t0); (q, r1, r0) } }} // Reduces a, b until |a - b| (almost) fits in one limb + 1 bit. Constructs matrix M. Returns 1 if // we make progress, i.e. can perform at least one subtraction. Otherwise returns zero. // // This is equivalent to `mpn_hgcd2` from `mpn/generic/hgcd2.c`, GMP 6.2.1. pub(crate) fn limbs_half_gcd_2( mut x_high: Limb, mut a_low: Limb, mut y_high: Limb, mut b_low: Limb, m: &mut HalfGcdMatrix1, ) -> bool { if x_high < 2 || y_high < 2 { return false; } let mut m01; let mut m10; if x_high > y_high || x_high == y_high && a_low > b_low { (x_high, a_low) = Limb::xx_sub_yy_to_zz(x_high, a_low, y_high, b_low); if x_high < 2 { return false; } m01 = 1; m10 = 0; } else { (y_high, b_low) = Limb::xx_sub_yy_to_zz(y_high, b_low, x_high, a_low); if y_high < 2 { return false; } m01 = 0; m10 = 1; } let mut m00 = 1; let mut m11 = 1; const HALF_WIDTH: u64 = Limb::WIDTH >> 1; const HALF_LIMIT_1: Limb = 1 << HALF_WIDTH; let mut subtract_a = x_high < y_high; let mut subtract_a1 = false; let mut done = false; loop { if subtract_a { subtract_a = false; } else { assert!(x_high >= y_high); if x_high == y_high { done = true; break; } if x_high < HALF_LIMIT_1 { x_high = (x_high << HALF_WIDTH) + (a_low >> HALF_WIDTH); y_high = (y_high << HALF_WIDTH) + (b_low >> HALF_WIDTH); break; } // Subtract a -= q * b, and multiply M from the right by (1 q ; 0 1), affecting the // second column of M. assert!(x_high > y_high); (x_high, a_low) = Limb::xx_sub_yy_to_zz(x_high, a_low, y_high, b_low); if x_high < 2 { done = true; break; } if x_high <= y_high { // Use q = 1. m01 += m00; m11 += m10; } else { let mut q; (q, x_high, a_low) = limbs_gcd_div(x_high, a_low, y_high, b_low); if x_high < 2 { // A is too small, but q is correct. m01 += q * m00; m11 += q * m10; done = true; break; } q += 1; m01 += q * m00; m11 += q * m10; } } assert!(y_high >= x_high); if x_high == y_high { done = true; break; } if y_high < HALF_LIMIT_1 { x_high = (x_high << HALF_WIDTH) + (a_low >> HALF_WIDTH); y_high = (y_high << HALF_WIDTH) + (b_low >> HALF_WIDTH); subtract_a1 = true; break; } // Subtract b -= q * a, and multiply M from the right by (1 0 ; q 1), affecting the first // column of M. (y_high, b_low) = Limb::xx_sub_yy_to_zz(y_high, b_low, x_high, a_low); if y_high < 2 { done = true; break; } if x_high >= y_high { // Use q = 1. m00 += m01; m10 += m11; } else { let mut q; (q, y_high, b_low) = limbs_gcd_div(y_high, b_low, x_high, a_low); if y_high < 2 { // B is too small, but q is correct. m00 += q * m01; m10 += q * m11; done = true; break; } q += 1; m00 += q * m01; m10 += q * m11; } } // Since we discard the least significant half limb, we don't get a truly maximal M // corresponding to |a - b| < 2 ^ (W + 1)). if !done { const HALF_LIMIT_2: Limb = 1 << (HALF_WIDTH + 1); loop { if subtract_a1 { subtract_a1 = false; } else { assert!(x_high >= y_high); x_high -= y_high; if x_high < HALF_LIMIT_2 { break; } if x_high <= y_high { // Use q = 1. m01 += m00; m11 += m10; } else { let mut q; (q, x_high) = x_high.div_mod(y_high); if x_high < HALF_LIMIT_2 { // A is too small, but q is correct. m01 += q * m00; m11 += q * m10; break; } q += 1; m01 += q * m00; m11 += q * m10; } } assert!(y_high >= x_high); y_high -= x_high; if y_high < HALF_LIMIT_2 { break; } if x_high >= y_high { // Use q = 1. m00 += m01; m10 += m11; } else { let mut q; (q, y_high) = y_high.div_mod(x_high); if y_high < HALF_LIMIT_2 { // B is too small, but q is correct. m00 += q * m01; m10 += q * m11; break; } q += 1; m00 += q * m01; m10 += q * m11; } } } m.data[0][0] = m00; m.data[0][1] = m01; m.data[1][0] = m10; m.data[1][1] = m11; true } /// This is equivalent to `mpn_hgcd_step` from `mpn/generic/hgcd_step.c`, GMP 6.2.1. fn limbs_half_gcd_step( xs: &mut [Limb], ys: &mut [Limb], s: usize, a: &mut HalfGcdMatrix, scratch: &mut [Limb], ) -> usize { let n = xs.len(); assert_eq!(ys.len(), n); assert!(n > s); let mask = xs[n - 1] | ys[n - 1]; assert_ne!(mask, 0); let (x_high, a_low, y_high, b_low) = if n == s + 1 { if mask < 4 { return limbs_gcd_subdivide_step(xs, ys, s, a, scratch); } (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else if mask.get_highest_bit() { (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else { let shift = LeadingZeros::leading_zeros(mask); ( extract_number(shift, xs[n - 1], xs[n - 2]), extract_number(shift, xs[n - 2], xs[n - 3]), extract_number(shift, ys[n - 1], ys[n - 2]), extract_number(shift, ys[n - 2], ys[n - 3]), ) }; // Try a limbs_half_gcd_2 step let mut b = HalfGcdMatrix1::default(); if limbs_half_gcd_2(x_high, a_low, y_high, b_low, &mut b) { // Multiply A <- A * B. limbs_half_gcd_matrix_mul_matrix_1(a, &b, scratch); let scratch = &mut scratch[..n]; // Can't swap inputs, so we need to copy. scratch.copy_from_slice(xs); // Multiply B^(-1) (x; y). limbs_half_gcd_matrix_1_mul_inverse_vector(&b, xs, scratch, ys) } else { limbs_gcd_subdivide_step(xs, ys, s, a, scratch) } } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `MPN_GCD_SUBDIV_STEP_ITCH` from `gmp-impl.h`, GMP 6.2.1. pub(crate) const fn limbs_gcd_subdivide_step_scratch_len(n: usize) -> usize { n } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `CHOOSE_P` from `mpn/generic/gcd.c`, GMP 6.2.1. const fn limbs_gcd_choose_p(n: usize) -> usize { (n << 1) / 3 } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `MPN_HGCD_MATRIX_INIT_ITCH` from `gmp-impl.h`, GMP 6.2.1. pub(crate) const fn limbs_half_gcd_matrix_init_scratch_len(n: usize) -> usize { (((n + 1) >> 1) + 1) << 2 } // TODO tune pub(crate) const HGCD_THRESHOLD: usize = 101; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_hgcd_itch` from `mpn/generic/hgcd.c`, GMP 6.2.1. pub(crate) fn limbs_half_gcd_scratch_len(n: usize) -> usize { if n < HGCD_THRESHOLD { n } else { // Get the recursion depth. let count = LeadingZeros::leading_zeros((n - 1) / (HGCD_THRESHOLD - 1)); 20 * ((n + 3) >> 2) + 22 * usize::exact_from(usize::WIDTH - count) + HGCD_THRESHOLD } } // TODO tune const HGCD_REDUCE_THRESHOLD: usize = 1679; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_hgcd_reduce_itch` from `mpn/generic/hgcd_reduce.c`, GMP 6.2.1. pub_test! {limbs_half_gcd_reduce_scratch_len(n: usize, p: usize) -> usize { assert!(n >= p); let diff = n - p; if n < HGCD_REDUCE_THRESHOLD { let scratch_len = limbs_half_gcd_scratch_len(diff); // - For arbitrary p, the storage for adjust is // - 2 * (p + M.n) = 2 * (p + ceil((n - p) / 2) - 1 <= n + p - 1 let sum = n + p - 1; if scratch_len < sum { sum } else { scratch_len } } else { (diff << 1) + limbs_half_gcd_scratch_len(diff) } }} // TODO tune const HGCD_APPR_THRESHOLD: usize = 104; /// Destroys inputs. /// /// This is equivalent to `mpn_hgcd_appr` from `mpn/generic/hgcd_appr.c`, GMP 6.2.1. fn limbs_half_gcd_approx( mut xs: &mut [Limb], mut ys: &mut [Limb], a: &mut HalfGcdMatrix, scratch: &mut [Limb], ) -> bool { let mut n = xs.len(); assert_eq!(ys.len(), n); assert_ne!(n, 0); assert!(xs[n - 1] != 0 || ys[n - 1] != 0); if n <= 2 { fail_on_untested_path("limbs_half_gcd_approx, n <= 2"); // Implies s = n return false; } assert!(((n + 1) >> 1) - 1 < a.s); // We aim for reduction of to W * s bits. But each time we discard some of the least significant // limbs, we must keep one additional bit to account for the truncation error. We maintain the W // * s - extra_bits as the current target size. let mut s = (n >> 1) + 1; let mut offset = 0; let mut success = false; if n < HGCD_APPR_THRESHOLD { let mut extra_bits = 0u64; let mut xs_chunk = &mut *xs; let mut ys_chunk = &mut *ys; while n > 2 { assert!(n > s); assert!(n <= s << 1); let new_n = limbs_half_gcd_step(xs_chunk, ys_chunk, s, a, scratch); if new_n == 0 { break; } n = new_n; xs_chunk = &mut xs_chunk[..n]; ys_chunk = &mut ys_chunk[..n]; success = true; // We can truncate and discard the lower p bits whenever n <= 2 * s - p. To account for // the truncation error, we must adjust s <- s + 1 - p, rather than just sbits <- sbits // - p. This adjustment makes the produced matrix slightly smaller than it could be. if limb_to_bit_count(n + 1) + (extra_bits << 1) <= limb_to_bit_count(s << 1) { let p = bit_to_limb_count_floor(limb_to_bit_count((s << 1) - n) - (extra_bits << 1)); if extra_bits == 0 { // We cross a limb boundary and bump s. We can't do that if the result is that // it makes makes min(X, Y) smaller than 2^W * s. if s + 1 == n || slice_test_zero(&xs_chunk[s + 1..]) || slice_test_zero(&ys_chunk[s + 1..]) { continue; } extra_bits = Limb::WIDTH - 1; s += 1; } else { extra_bits -= 1; } // Drop the p least-significant limbs. offset += p; xs_chunk = &mut xs_chunk[p..]; ys_chunk = &mut ys_chunk[p..]; n -= p; s -= p; } } assert_ne!(s, 0); if extra_bits != 0 { // We can get here only of we have dropped at least one of the least-significant bits, // so we can decrement xs and ys. We can then shift left extra bits using // limbs_slice_shr_in_place. assert_ne!(offset, 0); let xs = &mut xs[offset - 1..]; let ys = &mut ys[offset - 1..]; let (xs_head, xs_tail) = xs[..=n].split_first_mut().unwrap(); let (ys_head, ys_tail) = ys[..=n].split_first_mut().unwrap(); let comp_bits = Limb::WIDTH - extra_bits; *xs_head = limbs_slice_shr_in_place(xs_tail, comp_bits); *ys_head = limbs_slice_shr_in_place(ys_tail, comp_bits); if xs[n] != 0 || ys[n] != 0 { n += 1; } assert!(success); while n > 2 { assert!(n > s); assert!(n <= s << 1); n = limbs_half_gcd_step(&mut xs[..n], &mut ys[..n], s, a, scratch); if n == 0 { return true; } } } if n == 2 { fail_on_untested_path("limbs_half_gcd_approx, n == 2"); assert_eq!(s, 1); let mut b = HalfGcdMatrix1::default(); if limbs_half_gcd_2(xs[1], xs[0], ys[1], ys[0], &mut b) { // Multiply A <- A * B. limbs_half_gcd_matrix_mul_matrix_1(a, &b, scratch); success = true; } } success } else { let limit = ((3 * n) >> 2) + 1; let mut p = n >> 1; let new_n = limbs_half_gcd_matrix_reduce(a, xs, ys, p, scratch); if new_n != 0 { n = new_n; xs = &mut xs[..n]; ys = &mut ys[..n]; success = true; } while n > limit { // Needs n + 1 storage n = limbs_half_gcd_step(xs, ys, s, a, scratch); if n == 0 { return success; } xs = &mut xs[..n]; ys = &mut ys[..n]; success = true; } if n > s + 2 { p = (s << 1) - n + 1; let scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let (scratch_lo, scratch_hi) = scratch.split_at_mut(scratch_len); let mut b = HalfGcdMatrix::init(n - p, scratch_lo); if limbs_half_gcd_approx(&mut xs[p..], &mut ys[p..], &mut b, scratch_hi) { // We always have max(A) > 2 ^ (-(W + 1)) * max(B). assert!(a.n + 2 >= b.n); // Furthermore, assume A ends with a quotient (1, q; 0, 1); then either q or q + 1 // is a correct quotient, and B will start with either (1, 0; 1, 1) or (2, 1; 1, 1). // This rules out the case that the size of A * B is much smaller than the expected // A.n + B.n. assert!(a.n + b.n < a.s); // We need a bound for of A.n + B.n. Let n be the original input size. Then ceil(n / // 2) - 1 >= size of product >= A.n + B.n - 2, and it follows that A.n + B.n <= // ceil(n / 2) + 1. Then 3 * (A.n + B.n) + 5 <= 3 * ceil(n / 2) + 8 is the amount of // needed scratch space. limbs_half_gcd_matrix_mul_matrix(a, &b, scratch_hi); return true; } } loop { assert!(n > s); assert!(n <= s << 1); let new_n = limbs_half_gcd_step(xs, ys, s, a, scratch); if new_n == 0 { return success; } n = new_n; xs = &mut xs[..n]; ys = &mut ys[..n]; success = true; } } } // Reduces x, y until |x - y| fits in n / 2 + 1 limbs. Constructs matrix A with elements of size at // most (n + 1) / 2 - 1. Returns new size of a, b, or zero if no reduction is possible. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_hgcd` from `mpn/generic/hgcd.c`, GMP 6.2.1. pub(crate) fn limbs_half_gcd( xs: &mut [Limb], ys: &mut [Limb], a: &mut HalfGcdMatrix, scratch: &mut [Limb], ) -> usize { let mut n = xs.len(); assert_eq!(ys.len(), n); let s = (n >> 1) + 1; let mut success = false; if n <= s { fail_on_untested_path("limbs_half_gcd, n <= s"); return 0; } assert!(xs[n - 1] != 0 || ys[n - 1] != 0); assert!(((n + 1) >> 1) - 1 < a.s); if n >= HGCD_THRESHOLD { let limit = ((3 * n) >> 2) + 1; let p = n >> 1; let mut new_n = limbs_half_gcd_matrix_reduce(a, xs, ys, p, scratch); if new_n != 0 { n = new_n; success = true; } while n > limit { // Needs n + 1 storage let new_n = limbs_half_gcd_step(&mut xs[..n], &mut ys[..n], s, a, scratch); if new_n == 0 { return if success { n } else { 0 }; } n = new_n; success = true; } if n > s + 2 { let p = (s << 1) - n + 1; let scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let (scratch_lo, scratch_hi) = scratch.split_at_mut(scratch_len); let mut b = HalfGcdMatrix::init(n - p, scratch_lo); new_n = limbs_half_gcd(&mut xs[p..n], &mut ys[p..n], &mut b, scratch_hi); if new_n != 0 { // We always have max(A) > 2 ^ (-(W + 1)) * max(B). assert!(a.n + 2 >= b.n); // Furthermore, assume A ends with a quotient (1, q; 0, 1); then either q or q + 1 // is a correct quotient, and B will start with either (1, 0; 1, 1) or (2, 1; 1, // 1).This rules out the case that the size of A * B is much smaller than the // expected A.n + B.n. assert!(a.n + b.n < a.s); // Needs 2 * (p + A.n) <= 2 * (2 * s - limit + 1 + limit - s - 1) = 2 * s <= 2 * // (floor(n / 2) + 1) <= n + 2. n = limbs_half_gcd_matrix_adjust(&b, p + new_n, xs, ys, p, scratch_hi); // We need a bound for of A.n + B.n. Let n be the original input size. Then ceil(n / // 2) - 1 >= size of product >= A.n + B.n - 2 and it follows that A.n + B.n <= // ceil(n / 2) + 1. Then 3 * (A.n + B.n) + 5 <= 3 * ceil(n / 2) + 8 is the amount of // needed scratch space. limbs_half_gcd_matrix_mul_matrix(a, &b, scratch_hi); success = true; } } } loop { // Needs s + 3 < n let new_n = limbs_half_gcd_step(&mut xs[..n], &mut ys[..n], s, a, scratch); if new_n == 0 { return if success { n } else { 0 }; } n = new_n; success = true; } } // TODO tune pub(crate) const GCD_DC_THRESHOLD: usize = 330; // X >= Y, X and Y not both even. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_gcd` from `mpn/generic/gcd.c`, GMP 6.2.1. pub_crate_test! {limbs_gcd_reduced(out: &mut [Limb], xs: &mut [Limb], ys: &mut [Limb]) -> usize { let mut xs = &mut *xs; let mut ys = &mut *ys; let xs_len = xs.len(); let mut n = ys.len(); assert!(xs_len >= n); assert_ne!(n, 0); assert_ne!(ys[n - 1], 0); let mut scratch_len = max(xs_len - n + 1, limbs_gcd_subdivide_step_scratch_len(n)); if n >= GCD_DC_THRESHOLD { let p = limbs_gcd_choose_p(n); let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let half_gcd_scratch_len = limbs_half_gcd_scratch_len(n - p); let update_scratch_len = p + n - 1; scratch_len = max( scratch_len, matrix_scratch_len + max(half_gcd_scratch_len, update_scratch_len), ); } let mut scratch = vec![0; scratch_len]; let mut scratch = &mut scratch[..]; if xs_len > n { limbs_div_mod_qs_to_out_rs_to_ns(scratch, xs, ys); if slice_test_zero(&xs[..n]) { out[..n].copy_from_slice(ys); return n; } } while n >= GCD_DC_THRESHOLD { let xs = &mut xs[..n]; let ys = &mut ys[..n]; let p = limbs_gcd_choose_p(n); let comp_p = n - p; let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(comp_p); let (scratch_lo, scratch_hi) = scratch.split_at_mut(matrix_scratch_len); let mut m = HalfGcdMatrix::init(comp_p, scratch_lo); let new_n = limbs_half_gcd(&mut xs[p..], &mut ys[p..], &mut m, scratch_hi); if new_n != 0 { assert!(m.n <= (comp_p - 1) >> 1); assert!(m.n + p <= (p + n - 1) >> 1); // Temporary storage 2 * (p + M.n) <= p + n - 1. n = limbs_half_gcd_matrix_adjust(&m, p + new_n, xs, ys, p, scratch_hi); } else { // Temporary storage n. let out_len = n; n = limbs_gcd_subdivide_step(xs, ys, 0, &mut GcdContext(out), scratch); if n == 0 { return out_len; } } } while n > 2 { let mask = xs[n - 1] | ys[n - 1]; assert_ne!(mask, 0); let (x_hi, x_lo, y_hi, y_lo) = if mask.get_highest_bit() { (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else { let shift = LeadingZeros::leading_zeros(mask); ( extract_number(shift, xs[n - 1], xs[n - 2]), extract_number(shift, xs[n - 2], xs[n - 3]), extract_number(shift, ys[n - 1], ys[n - 2]), extract_number(shift, ys[n - 2], ys[n - 3]), ) }; let mut m = HalfGcdMatrix1::default(); // Try a limbs_half_gcd_2 step. if limbs_half_gcd_2(x_hi, x_lo, y_hi, y_lo, &mut m) { n = limbs_half_gcd_matrix_1_mul_inverse_vector( &m, &mut scratch[..n], &xs[..n], &mut ys[..n], ); swap(&mut xs, &mut scratch); } else { // limbs_half_gcd_2 has failed. Then either one of x or y is very small, or the // difference is very small. Perform one subtraction followed by one division. let out_len = n; n = limbs_gcd_subdivide_step( &mut xs[..n], &mut ys[..n], 0, &mut GcdContext(out), scratch, ); if n == 0 { return out_len; } } } assert!(xs[n - 1] != 0 || ys[n - 1] != 0); // Due to the calling convention for limbs_gcd_reduced, at most one can be even. if xs[0].even() { swap(&mut xs, &mut ys); } assert!(xs[0].odd()); let x_0 = xs[0]; let mut y_0 = ys[0]; if n == 1 { out[0] = x_0.gcd(y_0 >> y_0.trailing_zeros()); return 1; } let mut y_1 = ys[1]; if y_0 == 0 { y_0 = y_1; y_1 = 0; } if y_0.even() { let zeros = TrailingZeros::trailing_zeros(y_0); y_0 = (y_1 << (Limb::WIDTH - zeros)) | (y_0 >> zeros); y_1 >>= zeros; } let x_1 = xs[1]; // TODO try mpn_gcd_22 (out[1], out[0]) = DoubleLimb::join_halves(x_1, x_0) .gcd(DoubleLimb::join_halves(y_1, y_0)) .split_in_half(); if out[1] == 0 { 1 } else { 2 } }} ================================================ FILE: malachite-nz/src/natural/arithmetic/gcd/matrix_2_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed by Niels Möller and Marco Bodrato. // // Copyright © 2003-2005, 2008, 2009 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_same_length_to_out, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::sub::{ limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{Limb, MATRIX22_STRASSEN_THRESHOLD}; use core::cmp::Ordering::*; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `abs_sub_n` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1, where `rp != ap`. fn limbs_sub_abs_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let n = xs.len(); assert_eq!(ys.len(), n); if limbs_cmp_same_length(xs, ys) == Less { limbs_sub_same_length_to_out(out, ys, xs); true } else { limbs_sub_same_length_to_out(out, xs, ys); false } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. This is equivalent to // `abs_sub_n` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1, where `rp == ap`. fn limbs_sub_abs_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { let n = xs.len(); assert_eq!(ys.len(), n); if limbs_cmp_same_length(xs, ys) == Less { limbs_sub_same_length_in_place_right(ys, xs); true } else { limbs_sub_same_length_in_place_left(xs, ys); false } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `abs_sub_n` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1, where `rp == bp`. fn limbs_sub_abs_same_length_in_place_right(xs: &[Limb], ys: &mut [Limb]) -> bool { let n = xs.len(); assert_eq!(ys.len(), n); if limbs_cmp_same_length(xs, ys) == Less { limbs_sub_same_length_in_place_left(ys, xs); true } else { limbs_sub_same_length_in_place_right(xs, ys); false } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `add_signed_n` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1, where `rp != // ap`. fn limbs_add_signed_same_length_to_out( out: &mut [Limb], xs: &[Limb], x_sign: bool, ys: &[Limb], y_sign: bool, ) -> bool { if x_sign == y_sign { assert!(!limbs_add_same_length_to_out(out, xs, ys)); x_sign } else { x_sign != limbs_sub_abs_same_length_to_out(out, xs, ys) } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `add_signed_n` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1, where `rp == // ap`. fn limbs_add_signed_same_length_in_place_left( xs: &mut [Limb], x_sign: bool, ys: &[Limb], y_sign: bool, ) -> bool { if x_sign == y_sign { assert!(!limbs_slice_add_same_length_in_place_left(xs, ys)); x_sign } else { x_sign != limbs_sub_abs_same_length_in_place_left(xs, ys) } } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_matrix22_mul_itch` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1. pub_const_test! {limbs_matrix_mul_2_2_scratch_len(xs_len: usize, ys_len: usize) -> usize { if xs_len < MATRIX22_STRASSEN_THRESHOLD || ys_len < MATRIX22_STRASSEN_THRESHOLD { 3 * xs_len + 2 * ys_len } else { 3 * (xs_len + ys_len) + 5 } }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs_len, ys00.len())`. pub_test! {limbs_matrix_2_2_mul_small( xs00: &mut [Limb], xs01: &mut [Limb], xs10: &mut [Limb], xs11: &mut [Limb], xs_len: usize, ys00: &[Limb], ys01: &[Limb], ys10: &[Limb], ys11: &[Limb], scratch: &mut [Limb], ) { let ys_len = ys00.len(); // The actual output length is one limb larger than this let out_len = xs_len + ys_len; let (scratch, remainder) = scratch.split_at_mut(xs_len); split_into_chunks_mut!(remainder, out_len, [p0, p1], _unused); let mut t0 = &mut *xs00; let mut t1 = &mut *xs01; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs_len, ys_len)]; for _ in 0..2 { let t0_0 = &t0[..xs_len]; scratch.copy_from_slice(t0_0); if xs_len >= ys_len { limbs_mul_greater_to_out(p0, t0_0, ys00, &mut mul_scratch); let t1_0 = &t1[..xs_len]; limbs_mul_greater_to_out(p1, t1_0, ys11, &mut mul_scratch); limbs_mul_greater_to_out(t0, t1_0, ys10, &mut mul_scratch); limbs_mul_greater_to_out(t1, scratch, ys01, &mut mul_scratch); } else { limbs_mul_greater_to_out(p0, ys00, t0_0, &mut mul_scratch); let t1_0 = &t1[..xs_len]; limbs_mul_greater_to_out(p1, ys11, t1_0, &mut mul_scratch); limbs_mul_greater_to_out(t0, ys10, t1_0, &mut mul_scratch); limbs_mul_greater_to_out(t1, ys01, scratch, &mut mul_scratch); } let (t0_last, t0_init) = t0[..=out_len].split_last_mut().unwrap(); *t0_last = Limb::from(limbs_slice_add_same_length_in_place_left(t0_init, p0)); let (t1_last, t1_init) = t1[..=out_len].split_last_mut().unwrap(); *t1_last = Limb::from(limbs_slice_add_same_length_in_place_left(t1_init, p1)); t0 = &mut *xs10; t1 = &mut *xs11; } }} // Algorithm: // // ``` // / s0 \ / 1 0 0 0 \ / xs00 \ // | s1 | | 0 1 0 1 | | xs01 | // | s2 | | 0 0 -1 1 | | xs10 | // | s3 | = | 0 1 -1 1 | \ xs11 / // | s4 | | -1 1 -1 1 | // | s5 | | 0 1 0 0 | // \ s6 / \ 0 0 1 0 / // // / t0 \ / 1 0 0 0 \ / ys00 \ // | t1 | | 0 1 0 1 | | ys01 | // | t2 | | 0 0 -1 1 | | ys10 | // | t3 | = | 0 1 -1 1 | \ ys11 / // | t4 | | -1 1 -1 1 | // | t5 | | 0 1 0 0 | // \ t6 / \ 0 0 1 0 / // ``` // // Note: the two matrices above are the same, but s_i and t_i are used in the same product, only for // i < 4, see "A Strassen-like Matrix Multiplication suited for squaring and higher power // computation" by M. Bodrato, in Proceedings of ISSAC 2010. // // ``` // / xs00 \ / 1 0 0 0 0 1 0 \ / s0 * t0 \ // | xs01 | = | 0 0 -1 1 -1 1 0 | | s1 * t1 | // | xs10 | | 0 1 0 -1 0 -1 -1 | | s2 * t2 | // \ xs11 / \ 0 1 1 -1 0 -1 0 / | s3 * t3 | // | s4 * t5 | // | s5 * t6 | // \ s6 * t4 / // ``` // // The scheduling uses two temporaries U0 and U1 to store products, and two, S0 and T0, to store // combinations of entries of the two operands. // // Computes R = R * M. Elements are numbers R = (xs00, xs01; xs10, xs11). // // Resulting elements are of size up to xs_len + ys_len + 1. // // Temporary storage: 3 * xs_len + 3 * ys_len + 5. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs_len, ys00.len())`. // // This is equivalent to `mpn_matrix22_mul_strassen` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1. pub_test! {limbs_matrix_2_2_mul_strassen( xs00: &mut [Limb], xs01: &mut [Limb], xs10: &mut [Limb], xs11: &mut [Limb], xs_len: usize, ys00: &[Limb], ys01: &[Limb], ys10: &[Limb], ys11: &[Limb], scratch: &mut [Limb], ) { let ys_len = ys00.len(); let sum_len = xs_len + ys_len; let (s0, remainder) = scratch.split_at_mut(xs_len + 1); let (s0_last, s0_init) = s0.split_last_mut().unwrap(); let (t0, remainder) = remainder.split_at_mut(ys_len + 1); let (t0_last, t0_init) = t0.split_last_mut().unwrap(); let (u0, u1) = remainder.split_at_mut(sum_len + 1); let u1 = &mut u1[..sum_len + 2]; let xs00_lo = &xs00[..xs_len]; let xs01_lo = &mut xs01[..=xs_len]; let (xs01_lo_last, xs01_lo_init) = xs01_lo.split_last_mut().unwrap(); let xs10 = &mut xs10[..=sum_len]; let xs10_lo = &xs10[..xs_len]; let xs11 = &mut xs11[..=sum_len]; let xs11_lo = &mut xs11[..xs_len]; // u5 = s5 * t6 let mut mul_scratch = vec![ 0; max!( limbs_mul_to_out_scratch_len(xs_len, ys_len), limbs_mul_to_out_scratch_len(xs_len, ys_len + 1), limbs_mul_to_out_scratch_len(xs_len + 1, ys_len), limbs_mul_to_out_scratch_len(xs_len + 1, ys_len + 1) ) ]; assert!(xs01_lo_init.len() <= sum_len + 1); assert!(ys10.len() <= ys_len + 1); // size: xs_len, ys_len limbs_mul_to_out(u0, xs01_lo_init, ys10, &mut mul_scratch); // xs11 - xs10 let mut x11_sign = limbs_sub_abs_same_length_in_place_left(xs11_lo, xs10_lo); let x01_sign = if x11_sign { *xs01_lo_last = 0; limbs_sub_abs_same_length_in_place_left(xs01_lo_init, xs11_lo) } else { // xs01 - xs10 + xs11 *xs01_lo_last = Limb::from(limbs_slice_add_same_length_in_place_left( xs01_lo_init, xs11_lo, )); false }; let s0_sign = if x01_sign { *s0_last = Limb::from(limbs_add_same_length_to_out(s0_init, xs01_lo_init, xs00_lo)); false } else if *xs01_lo_last != 0 { *s0_last = *xs01_lo_last; if limbs_sub_same_length_to_out(s0_init, xs01_lo_init, xs00_lo) { s0[xs_len] -= 1; } // Reverse sign! s4 = -xs00 + xs01 - xs10 + xs11 true } else { *s0_last = 0; limbs_sub_abs_same_length_to_out(s0_init, xs00_lo, xs01_lo_init) }; // u0 = s0 * t0 // // size: xs_len, ys_len limbs_mul_to_out(u1, xs00_lo, ys00, &mut mul_scratch); let (u0_last, u0_init) = u0.split_last_mut().unwrap(); xs00[sum_len] = Limb::from(limbs_add_same_length_to_out(xs00, u0_init, &u1[..sum_len])); // u0 + u5 assert!(xs00[sum_len] < 2); let mut t0_sign = limbs_sub_abs_same_length_to_out(t0_init, ys11, ys10); // Reverse sign! let u1_sign = x11_sign == t0_sign; // u2 = s2 * t2 // // size: xs_len, ys_len limbs_mul_to_out(u1, xs11_lo, t0_init, &mut mul_scratch); u1[sum_len] = 0; *t0_last = if t0_sign { t0_sign = limbs_sub_abs_same_length_in_place_right(ys01, t0_init); 0 } else { Limb::from(limbs_slice_add_same_length_in_place_left(t0_init, ys01)) }; if *t0_last != 0 { // u3 = s3 * t3 // // size: xs_len, ys_len + 1 limbs_mul_to_out(xs11, xs01_lo_init, t0, &mut mul_scratch); assert!(*xs01_lo_last < 2); if *xs01_lo_last != 0 { limbs_slice_add_same_length_in_place_left(&mut xs11[xs_len..], t0); } } else { // size: xs_len + 1, ys_len limbs_mul_to_out(xs11, xs01_lo, t0_init, &mut mul_scratch); } assert!(xs11[sum_len] < 4); *u0_last = 0; x11_sign = if x01_sign == t0_sign { // u3 + u5 assert!(!limbs_slice_add_same_length_in_place_left(xs11, u0)); false } else { limbs_sub_abs_same_length_in_place_right(u0, xs11) }; let (t0_last, t0_init) = t0.split_last_mut().unwrap(); if t0_sign { *t0_last = Limb::from(limbs_slice_add_same_length_in_place_left(t0_init, ys00)); } else if *t0_last != 0 { if limbs_sub_same_length_in_place_left(t0_init, ys00) { *t0_last -= 1; } } else { t0_sign = limbs_sub_abs_same_length_in_place_left(t0_init, ys00); } // u6 = s6 * t4 // // size: xs_len, ys_len + 1 limbs_mul_to_out(u0, xs10_lo, t0, &mut mul_scratch); assert!(u0[sum_len] < 2); let (xs01_lo_last, xs01_lo_init) = xs01_lo.split_last_mut().unwrap(); if x01_sign { assert!(!limbs_sub_same_length_in_place_right(xs10_lo, xs01_lo_init)); } else if limbs_slice_add_same_length_in_place_left(xs01_lo_init, xs10_lo) { *xs01_lo_last += 1; } t0_sign = limbs_add_signed_same_length_to_out(xs10, xs11, x11_sign, u0, t0_sign); // u3 + u5 + u6 assert!(xs10[sum_len] < 4); x11_sign = limbs_add_signed_same_length_in_place_left(xs11, x11_sign, &u1[..=sum_len], u1_sign); // -u2 + u3 + u5 assert!(xs11[sum_len] < 3); // u4 = s4 * t5 // // size: xs_len + 1, ys_len limbs_mul_to_out(u0, s0, ys01, &mut mul_scratch); assert!(u0[sum_len] < 2); t0[ys_len] = Limb::from(limbs_add_same_length_to_out(t0, ys11, ys01)); // u1 = s1 * t1 // // size: xs_len + 1, ys_len + 1 limbs_mul_to_out(u1, xs01_lo, t0, &mut mul_scratch); assert!(u1[sum_len] < 4); let (u1_last, u1_init) = u1.split_last_mut().unwrap(); assert_eq!(*u1_last, 0); limbs_add_signed_same_length_to_out(xs01, xs11, x11_sign, u0, s0_sign); // -u2 + u3 - u4 + u5 assert!(xs01[sum_len] < 2); if x11_sign { assert!(!limbs_slice_add_same_length_in_place_left(xs11, u1_init)); } else { // u1 + u2 - u3 - u5 assert!(!limbs_sub_same_length_in_place_right(u1_init, xs11)); } assert!(xs11[sum_len] < 2); if t0_sign { assert!(!limbs_slice_add_same_length_in_place_left(xs10, u1_init)); } else { // u1 - u3 - u5 - u6 assert!(!limbs_sub_same_length_in_place_right(u1_init, xs10)); } assert!(xs10[sum_len] < 2); }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs_len, ys00.len())`. // // This is equivalent to `mpn_matrix22_mul` from `mpn/generic/matrix22_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_matrix_2_2_mul( xs00: &mut [Limb], xs01: &mut [Limb], xs10: &mut [Limb], xs11: &mut [Limb], xs_len: usize, ys00: &[Limb], ys01: &[Limb], ys10: &[Limb], ys11: &[Limb], scratch: &mut [Limb], ) { let ys_len = ys00.len(); assert_eq!(ys01.len(), ys_len); assert_eq!(ys10.len(), ys_len); assert_eq!(ys11.len(), ys_len); if xs_len < MATRIX22_STRASSEN_THRESHOLD || ys_len < MATRIX22_STRASSEN_THRESHOLD { limbs_matrix_2_2_mul_small( xs00, xs01, xs10, xs11, xs_len, ys00, ys01, ys10, ys11, scratch, ); } else { limbs_matrix_2_2_mul_strassen( xs00, xs01, xs10, xs11, xs_len, ys00, ys01, ys10, ys11, scratch, ); } }} ================================================ FILE: malachite-nz/src/natural/arithmetic/gcd/mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2019 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::eq_mod::limbs_mod_exact_odd_limb; use crate::natural::arithmetic::gcd::half_gcd::limbs_gcd_reduced; use crate::natural::arithmetic::mod_op::limbs_mod_limb_alt_2; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::comparison::cmp::limbs_cmp; use crate::natural::{Natural, limb_to_bit_count}; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use core::cmp::{Ordering::*, min}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{Gcd, GcdAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::slices::slice_leading_zeros; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `MPN_MOD_OR_MODEXACT_1_ODD` from `gmp-impl.h`, GMP 6.2.1, where `size > 1`. fn limbs_mod_or_modexact(ns: &[Limb], d: Limb) -> Limb { if ns.len() < BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_exact_odd_limb(ns, d, 0) } else { limbs_mod_limb_alt_2::(ns, d) } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_gcd_1` from `mpn/generic/gcd_1.c`, GMP 6.2.1. pub_test! {limbs_gcd_limb(xs: &[Limb], mut y: Limb) -> Limb { assert!(xs.len() > 1); assert_ne!(y, 0); let mut x = xs[0]; let mut zeros = y.trailing_zeros(); y >>= zeros; if x != 0 { zeros = min(zeros, x.trailing_zeros()); } x = limbs_mod_or_modexact(xs, y); if x != 0 { y.gcd_assign(x >> x.trailing_zeros()); } y << zeros }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn gcd_greater_helper(mut xs: &mut [Limb], mut ys: &mut [Limb]) -> Natural { let xs_zero_limbs = slice_leading_zeros(xs); let ys_zero_limbs = slice_leading_zeros(ys); let common_zero_limbs = min(xs_zero_limbs, ys_zero_limbs); xs = &mut xs[common_zero_limbs..]; ys = &mut ys[common_zero_limbs..]; let xs_zero_bits = TrailingZeros::trailing_zeros(xs[0]); let ys_zero_bits = TrailingZeros::trailing_zeros(ys[0]); let common_zero_bits = min(xs_zero_bits, ys_zero_bits); if common_zero_bits != 0 { limbs_slice_shr_in_place(xs, common_zero_bits); limbs_slice_shr_in_place(ys, common_zero_bits); if *xs.last().unwrap() == 0 { let n = xs.len(); xs = &mut xs[..n - 1]; } if *ys.last().unwrap() == 0 { let n = ys.len(); ys = &mut ys[..n - 1]; } } let n = if ys.len() == 1 { Natural::from(if xs.len() == 1 { xs[0].gcd(ys[0]) } else { limbs_gcd_limb(xs, ys[0]) }) } else { let mut out = vec![0; xs.len()]; let out_len = limbs_gcd_reduced(&mut out, xs, ys); out.resize(out_len, 0); Natural::from_owned_limbs_asc(out) }; n << (limb_to_bit_count(common_zero_limbs) + common_zero_bits) } impl Gcd for Natural { type Output = Self; /// Computes the GCD (greatest common divisor) of two [`Natural`]s, taking both by value. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which makes sense /// if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// f(x, y) = \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Gcd; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).gcd(Natural::from(5u32)), 1); /// assert_eq!(Natural::from(12u32).gcd(Natural::from(90u32)), 6); /// ``` fn gcd(mut self, other: Self) -> Self { self.gcd_assign(other); self } } impl<'a> Gcd<&'a Self> for Natural { type Output = Self; /// Computes the GCD (greatest common divisor) of two [`Natural`]s, taking the first by value /// and the second by reference. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which makes sense /// if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// f(x, y) = \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Gcd; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).gcd(&Natural::from(5u32)), 1); /// assert_eq!(Natural::from(12u32).gcd(&Natural::from(90u32)), 6); /// ``` #[inline] fn gcd(mut self, other: &'a Self) -> Self { self.gcd_assign(other); self } } impl Gcd for &Natural { type Output = Natural; /// Computes the GCD (greatest common divisor) of two [`Natural`]s, taking the first by /// reference and the second by value. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which makes sense /// if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// f(x, y) = \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Gcd; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(3u32)).gcd(Natural::from(5u32)), 1); /// assert_eq!((&Natural::from(12u32)).gcd(Natural::from(90u32)), 6); /// ``` #[inline] fn gcd(self, mut other: Natural) -> Natural { other.gcd_assign(self); other } } impl Gcd<&Natural> for &Natural { type Output = Natural; /// Computes the GCD (greatest common divisor) of two [`Natural`]s, taking both by reference. /// /// The GCD of 0 and $n$, for any $n$, is 0. In particular, $\gcd(0, 0) = 0$, which makes sense /// if we interpret "greatest" to mean "greatest by the divisibility order". /// /// $$ /// f(x, y) = \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Gcd; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(3u32)).gcd(&Natural::from(5u32)), 1); /// assert_eq!((&Natural::from(12u32)).gcd(&Natural::from(90u32)), 6); /// ``` #[inline] fn gcd(self, other: &Natural) -> Natural { match (self, other) { (x, &Natural::ZERO) => x.clone(), (&Natural::ZERO, y) => y.clone(), (x, y) if core::ptr::eq(x, y) => x.clone(), (Natural(Small(x)), Natural(Small(y))) => Natural::from(x.gcd(*y)), (Natural(Large(xs)), Natural(Small(y))) => Natural::from(limbs_gcd_limb(xs, *y)), (Natural(Small(x)), Natural(Large(ys))) => Natural::from(limbs_gcd_limb(ys, *x)), (Natural(Large(xs)), Natural(Large(ys))) => { let c = limbs_cmp(xs, ys); if c == Equal { return self.clone(); } let mut xs = xs.clone(); let mut xs: &mut [Limb] = &mut xs; let mut ys = ys.clone(); let mut ys: &mut [Limb] = &mut ys; if c == Less { swap(&mut xs, &mut ys); } gcd_greater_helper(xs, ys) } } } } impl GcdAssign for Natural { /// Replaces a [`Natural`] by its GCD (greatest common divisor) with another [`Natural`], taking /// the [`Natural`] on the right-hand side by value. /// /// $$ /// x \gets \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::GcdAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.gcd_assign(Natural::from(5u32)); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(12u32); /// x.gcd_assign(Natural::from(90u32)); /// assert_eq!(x, 6); /// ``` #[inline] fn gcd_assign(&mut self, other: Self) { match (&mut *self, other) { (_, Self::ZERO) => {} (&mut Self::ZERO, y) => *self = y, (Self(Small(x)), Self(Small(y))) => x.gcd_assign(y), (Self(Large(xs)), Self(Small(y))) => { *self = Self::from(limbs_gcd_limb(xs, y)); } (Self(Small(x)), Self(Large(ys))) => { *self = Self::from(limbs_gcd_limb(&ys, *x)); } (Self(Large(xs)), Self(Large(mut ys))) => { let mut xs: &mut [Limb] = &mut *xs; let mut ys: &mut [Limb] = &mut ys; match limbs_cmp(xs, ys) { Equal => return, Less => { swap(&mut xs, &mut ys); } _ => {} } *self = gcd_greater_helper(xs, ys); } } } } impl<'a> GcdAssign<&'a Self> for Natural { /// Replaces a [`Natural`] by its GCD (greatest common divisor) with another [`Natural`], taking /// the [`Natural`] on the right-hand side by reference. /// /// $$ /// x \gets \gcd(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::GcdAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.gcd_assign(&Natural::from(5u32)); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(12u32); /// x.gcd_assign(&Natural::from(90u32)); /// assert_eq!(x, 6); /// ``` #[inline] fn gcd_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, &Self::ZERO) => {} (&mut Self::ZERO, y) => self.clone_from(y), (Self(Small(x)), Self(Small(y))) => x.gcd_assign(*y), (Self(Large(xs)), Self(Small(y))) => { *self = Self::from(limbs_gcd_limb(xs, *y)); } (Self(Small(x)), Self(Large(ys))) => { *self = Self::from(limbs_gcd_limb(ys, *x)); } (Self(Large(xs)), Self(Large(ys))) => { let c = limbs_cmp(xs, ys); if c == Equal { return; } let mut xs: &mut [Limb] = &mut *xs; let mut ys = ys.clone(); let mut ys: &mut [Limb] = &mut ys; if c == Less { swap(&mut xs, &mut ys); } *self = gcd_greater_helper(xs, ys); } } } } /// Implementations of [`ExtendedGcd`](malachite_base::num::arithmetic::traits::ExtendedGcd), a /// trait for computing the extended GCD of two numbers. pub mod extended_gcd; /// Code for the half-GCD algorithm, described [here](https://gmplib.org/manual/Subquadratic-GCD). pub mod half_gcd; /// Code for working with 2-by-2 matrices. pub mod matrix_2_2; ================================================ FILE: malachite-nz/src/natural/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::slices::slice_test_zero; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, determines // whether that `Natural` is an integer power of 2. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_crate_test! {limbs_is_power_of_2(xs: &[Limb]) -> bool { let (xs_last, xs_init) = xs.split_last().unwrap(); slice_test_zero(xs_init) && xs_last.is_power_of_2() }} impl IsPowerOf2 for Natural { /// Determines whether a [`Natural`] is an integer power of 2. /// /// $f(x) = (\exists n \in \Z : 2^n = x)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::{IsPowerOf2, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.is_power_of_2(), false); /// assert_eq!(Natural::from(123u32).is_power_of_2(), false); /// assert_eq!(Natural::from(0x80u32).is_power_of_2(), true); /// assert_eq!(Natural::from(10u32).pow(12).is_power_of_2(), false); /// assert_eq!( /// Natural::from_str("1099511627776").unwrap().is_power_of_2(), /// true /// ); /// ``` fn is_power_of_2(&self) -> bool { match self { Self(Small(small)) => small.is_power_of_2(), Self(Large(limbs)) => limbs_is_power_of_2(limbs), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::integer::arithmetic::kronecker_symbol::{ limbs_kronecker_symbol, limbs_kronecker_symbol_single, }; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::gcd::half_gcd::{ GCD_DC_THRESHOLD, GcdSubdivideStepContext, HGCD_THRESHOLD, HalfGcdMatrix, HalfGcdMatrix1, extract_number, limbs_gcd_div, limbs_gcd_subdivide_step, limbs_gcd_subdivide_step_scratch_len, limbs_half_gcd_matrix_1_mul_inverse_vector, limbs_half_gcd_matrix_adjust, limbs_half_gcd_matrix_init_scratch_len, limbs_half_gcd_matrix_mul_matrix, limbs_half_gcd_matrix_mul_matrix_1, limbs_half_gcd_matrix_update_q, limbs_half_gcd_scratch_len, }; use crate::platform::{DoubleLimb, Limb}; use core::cmp::max; use core::mem::swap; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ DivMod, JacobiSymbol, KroneckerSymbol, LegendreSymbol, ModPowerOf2, Parity, XXSubYYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{JoinHalves, WrappingFrom}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::slice_trailing_zeros; // This is equivalent to `jacobi_table` from `mpn/jacobi.c`, GMP 6.2.1. const JACOBI_TABLE: [u8; 208] = [ 0, 0, 0, 0, 0, 12, 8, 4, 1, 1, 1, 1, 1, 13, 9, 5, 2, 2, 2, 2, 2, 6, 10, 14, 3, 3, 3, 3, 3, 7, 11, 15, 4, 16, 6, 18, 4, 0, 12, 8, 5, 17, 7, 19, 5, 1, 13, 9, 6, 18, 4, 16, 6, 10, 14, 2, 7, 19, 5, 17, 7, 11, 15, 3, 8, 10, 9, 11, 8, 4, 0, 12, 9, 11, 8, 10, 9, 5, 1, 13, 10, 9, 11, 8, 10, 14, 2, 6, 11, 8, 10, 9, 11, 15, 3, 7, 12, 22, 24, 20, 12, 8, 4, 0, 13, 23, 25, 21, 13, 9, 5, 1, 25, 21, 13, 23, 14, 2, 6, 10, 24, 20, 12, 22, 15, 3, 7, 11, 16, 6, 18, 4, 16, 16, 16, 16, 17, 7, 19, 5, 17, 17, 17, 17, 18, 4, 16, 6, 18, 22, 19, 23, 19, 5, 17, 7, 19, 23, 18, 22, 20, 12, 22, 24, 20, 20, 20, 20, 21, 13, 23, 25, 21, 21, 21, 21, 22, 24, 20, 12, 22, 19, 23, 18, 23, 25, 21, 13, 23, 18, 22, 19, 24, 20, 12, 22, 15, 3, 7, 11, 25, 21, 13, 23, 14, 2, 6, 10, ]; // This is equivalent to `mpn_jacobi_update` from `gmp-impl.h`, GMP 6.2.1. fn limbs_jacobi_update(bits: u8, denominator: u8, q: Limb) -> u8 { assert!(bits < 26); assert!(denominator < 2); assert!(q < 4); JACOBI_TABLE[usize::wrapping_from(((bits << 3) + (denominator << 2)) | u8::wrapping_from(q))] } // This is equivalent to `hgcd_jacobi_context` from `mpn/hgcd_jacobi.c`, GMP 6.2.1. struct HalfGcdJacobiContext<'a, 'b, 'c> { m: &'a mut HalfGcdMatrix<'b>, bits_mut: &'c mut u8, } impl GcdSubdivideStepContext for HalfGcdJacobiContext<'_, '_, '_> { // This is equivalent to `hgcd_jacobi_hook` from `mpn/hgcd_jacobi.c`, GMP 6.2.1. fn gcd_subdiv_step_hook( &mut self, gs: Option<&[Limb]>, qs: Option<&mut [Limb]>, mut qs_len: usize, d: i8, ) { assert!(gs.is_none()); assert!(d >= 0); let qs = qs.unwrap(); qs_len -= slice_trailing_zeros(&qs[..qs_len]); if qs_len != 0 { let (qs, scratch) = qs.split_at_mut(qs_len); let d = u8::wrapping_from(d); limbs_half_gcd_matrix_update_q(self.m, qs, d, scratch); *self.bits_mut = limbs_jacobi_update(*self.bits_mut, d, qs[0].mod_power_of_2(2)); } } } const HALF_WIDTH: u64 = Limb::WIDTH >> 1; const TWO_POW_HALF_WIDTH: Limb = 1 << HALF_WIDTH; const TWICE_TWO_POW_HALF_WIDTH: Limb = TWO_POW_HALF_WIDTH << 1; // This is equivalent to `mpn_hgcd2_jacobi` from `mpn/hgcd2_jacobi.c`, GMP 6.2.1, returning `bitsp` // along with a bool. fn limbs_half_gcd_2_jacobi( mut x_1: Limb, mut x_0: Limb, mut y_1: Limb, mut y_0: Limb, m: &mut HalfGcdMatrix1, mut bits: u8, ) -> (u8, bool) { if x_1 < 2 || y_1 < 2 { return (bits, false); } let mut u00 = 1; let mut u01; let mut u10; let mut u11 = 1; (u01, u10, bits) = if x_1 > y_1 || x_1 == y_1 && x_0 > y_0 { (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); if x_1 < 2 { return (bits, false); } (1, 0, limbs_jacobi_update(bits, 1, 1)) } else { (y_1, y_0) = Limb::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0); if y_1 < 2 { return (bits, false); } (0, 1, limbs_jacobi_update(bits, 0, 1)) }; let mut subtract_a = x_1 < y_1; let mut subtract_a_1 = false; loop { if !subtract_a { assert!(x_1 >= y_1); if x_1 == y_1 { m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } if x_1 < TWO_POW_HALF_WIDTH { x_1 = (x_1 << HALF_WIDTH) + (x_0 >> HALF_WIDTH); y_1 = (y_1 << HALF_WIDTH) + (y_0 >> HALF_WIDTH); break; } // Subtract x -= q * y, and multiply m from the right by (1 q ; 0 1), affecting the // second column of m. assert!(x_1 > y_1); (x_1, x_0) = Limb::xx_sub_yy_to_zz(x_1, x_0, y_1, y_0); if x_1 < 2 { m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } let bits_copy = bits; bits = limbs_jacobi_update( bits_copy, 1, if x_1 <= y_1 { // Use q = 1 u01 += u00; u11 += u10; 1 } else { let mut q; (q, x_1, x_0) = limbs_gcd_div(x_1, x_0, y_1, y_0); if x_1 < 2 { // X is too small, but q is correct. u01 += q * u00; u11 += q * u10; bits = limbs_jacobi_update(bits, 1, q.mod_power_of_2(2)); m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } q += 1; u01 += q * u00; u11 += q * u10; q.mod_power_of_2(2) }, ); } subtract_a = false; assert!(y_1 >= x_1); if x_1 == y_1 { m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } if y_1 < TWO_POW_HALF_WIDTH { x_1 = (x_1 << HALF_WIDTH) + (x_0 >> HALF_WIDTH); y_1 = (y_1 << HALF_WIDTH) + (y_0 >> HALF_WIDTH); subtract_a_1 = true; break; } // Subtract b -= q a, and multiply M from the right by (1 0 ; q 1), affecting the first // column of M. (y_1, y_0) = Limb::xx_sub_yy_to_zz(y_1, y_0, x_1, x_0); if y_1 < 2 { m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } let bits_copy = bits; bits = limbs_jacobi_update( bits_copy, 0, if y_1 <= x_1 { // Use q = 1 u00 += u01; u10 += u11; 1 } else { let mut q; (q, y_1, y_0) = limbs_gcd_div(y_1, y_0, x_1, x_0); if y_1 < 2 { // Y is too small, but q is correct. u00 += q * u01; u10 += q * u11; bits = limbs_jacobi_update(bits, 0, q.mod_power_of_2(2)); m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; return (bits, true); } q += 1; u00 += q * u01; u10 += q * u11; q.mod_power_of_2(2) }, ); } // Since we discard the least significant half limb, we don't get a truly maximal m // (corresponding to |x - y| < 2^(W+1)). // // Single precision loop loop { if !subtract_a_1 { assert!(x_1 >= y_1); if x_1 == y_1 { break; } x_1 -= y_1; if x_1 < TWICE_TWO_POW_HALF_WIDTH { break; } let bits_copy = bits; bits = limbs_jacobi_update( bits_copy, 1, if x_1 <= y_1 { // Use q = 1 u01 += u00; u11 += u10; 1 } else { let (mut q, r) = x_1.div_mod(y_1); x_1 = r; if x_1 < TWICE_TWO_POW_HALF_WIDTH { // X is too small, but q is correct. u01 += q * u00; u11 += q * u10; bits = limbs_jacobi_update(bits, 1, q.mod_power_of_2(2)); break; } q += 1; u01 += q * u00; u11 += q * u10; q.mod_power_of_2(2) }, ); } subtract_a_1 = false; assert!(y_1 >= x_1); if x_1 == y_1 { break; } y_1 -= x_1; if y_1 < TWICE_TWO_POW_HALF_WIDTH { break; } let bits_copy = bits; bits = limbs_jacobi_update( bits_copy, 0, if y_1 <= x_1 { // Use q = 1 u00 += u01; u10 += u11; 1 } else { let mut q; (q, y_1) = y_1.div_mod(x_1); if y_1 < TWICE_TWO_POW_HALF_WIDTH { // Y is too small, but q is correct. u00 += q * u01; u10 += q * u11; bits = limbs_jacobi_update(bits, 0, q.mod_power_of_2(2)); break; } q += 1; u00 += q * u01; u10 += q * u11; q.mod_power_of_2(2) }, ); } m.data[0][0] = u00; m.data[0][1] = u01; m.data[1][0] = u10; m.data[1][1] = u11; (bits, true) } // Perform a few steps, using some of `limbs_half_gcd_2_jacobi`, subtraction and division. Reduces // the size by almost one limb or more, but never below the given size s. Return new size for x and // y, or 0 if no more steps are possible. // // If `limbs_half_gcd_2_jacobi` succeeds, needs temporary space for // `limbs_half_gcd_matrix_mul_matrix_1`, m.n limbs, and // `limbs_half_gcd_matrix_1_mul_inverse_vector`, n limbs. If `limbs_half_gcd_2_jacobi` fails, needs // space for the quotient, qs_len <= n - s + 1 limbs, for and `update_q`, qs_len + (size of the // appropriate column of M) <= resulting size of m. // // If n is the input size to the calling hgcd, then s = floor(N / 2) + 1, m.n < N, qs_len + matrix // size <= n - s + 1 + n - s = 2 (n - s) + 1 < N, so N is sufficient. // // This is equivalent to `hgcd_jacobi_step` from `mpn/hgcd_jacobi.c`, GMP 6.2.1, where `bitsp` is // returned along with the `usize`. fn limbs_half_gcd_jacobi_step( xs: &mut [Limb], ys: &mut [Limb], s: usize, m: &mut HalfGcdMatrix, mut bits: u8, scratch: &mut [Limb], ) -> (u8, usize) { let n = xs.len(); assert_eq!(ys.len(), n); let scratch = &mut scratch[..n]; assert!(n > s); let mask = xs[n - 1] | ys[n - 1]; assert_ne!(mask, 0); let (x_hi, x_lo, y_hi, y_lo) = if n == s + 1 { if mask < 4 { let u = limbs_gcd_subdivide_step( xs, ys, s, &mut HalfGcdJacobiContext { m, bits_mut: &mut bits, }, scratch, ); return (bits, u); } (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else if mask.get_highest_bit() { (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else { let shift = LeadingZeros::leading_zeros(mask); ( extract_number(shift, xs[n - 1], xs[n - 2]), extract_number(shift, xs[n - 2], xs[n - 3]), extract_number(shift, ys[n - 1], ys[n - 2]), extract_number(shift, ys[n - 2], ys[n - 3]), ) }; // Try a `limbs_half_gcd_2_jacobi` step let mut m1 = HalfGcdMatrix1::default(); let b; (bits, b) = limbs_half_gcd_2_jacobi(x_hi, x_lo, y_hi, y_lo, &mut m1, bits); if b { // Multiply m <- m * m1 limbs_half_gcd_matrix_mul_matrix_1(m, &m1, scratch); // Can't swap inputs, so we need to copy scratch.copy_from_slice(xs); // Multiply m1^(-1) (x;y) ( bits, limbs_half_gcd_matrix_1_mul_inverse_vector(&m1, xs, scratch, ys), ) } else { let u = limbs_gcd_subdivide_step( xs, ys, s, &mut HalfGcdJacobiContext { m, bits_mut: &mut bits, }, scratch, ); (bits, u) } } // Reduces x, y until |x - y| fits in n / 2 + 1 limbs. Constructs matrix m with elements of size at // most (n + 1) / 2 - 1. Returns new size of x, y, or zero if no reduction is possible. // // Same scratch requirements as for `limbs_half_gcd`. // // This is equivalent to `mpn_hgcd_jacobi` from `mpn/hgcd_jacobi.c`, GMP 6.2.1, where `bitsp` is // also returned. fn limbs_half_gcd_jacobi( xs: &mut [Limb], ys: &mut [Limb], m: &mut HalfGcdMatrix<'_>, mut bits: u8, scratch: &mut [Limb], ) -> (u8, usize) { let mut n = xs.len(); assert_eq!(ys.len(), n); let s = (n >> 1) + 1; let mut success = false; assert!(s < n); assert!(xs[n - 1] != 0 || ys[n - 1] != 0); assert!(((n + 1) >> 1) - 1 < s); if n >= HGCD_THRESHOLD { let n2 = ((3 * n) >> 2) + 1; let p = n >> 1; let mut nn; (bits, nn) = limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], m, bits, scratch); if nn != 0 { // Needs 2 * (p + m.n) <= 2 * (floor(n / 2) + ceiling(n / 2) - 1) = 2 * (n - 1) n = limbs_half_gcd_matrix_adjust(m, p + nn, xs, ys, p, scratch); success = true; } while n > n2 { // Needs n + 1 storage (bits, nn) = limbs_half_gcd_jacobi_step(&mut xs[..n], &mut ys[..n], s, m, bits, scratch); if nn == 0 { return (bits, if success { n } else { 0 }); } n = nn; success = true; } if n > s + 2 { let p = 2 * s - n + 1; let scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let (scratch_lo, scratch_hi) = scratch.split_at_mut(scratch_len); let mut m1 = HalfGcdMatrix::init(n - p, scratch_lo); (bits, nn) = limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], &mut m1, bits, scratch_hi); if nn != 0 { // We always have max(m) > 2^(-(W + 1)) * max(m1) assert!(m.n + 2 >= m1.n); // Furthermore, assume m ends with a quotient (1, q; 0, 1); then either q or q + 1 // is a correct quotient, and m1 will start with either (1, 0; 1, 1) or (2, 1; 1, // 1). This rules out the case that the size of m * m1 is much smaller than the // expected m.n + m1.n. assert!(m.n + m1.n < m.s); // Needs 2 * (p + m.n) <= 2 * (2 * s - nn + 1 + nn - s - 1) = 2 * s <= 2 * (floor(n // / 2) + 1) <= n + 2. n = limbs_half_gcd_matrix_adjust(&m1, p + nn, xs, ys, p, scratch_hi); // We need a bound for of m.n + m1.n. Let n be the original input size. Then // // ceiling(n / 2) - 1 >= size of product >= m.n + m1.n - 2 // // and it follows that // // m.n + m1.n <= ceiling(n / 2) + 1 // // Then 3 * (m.n + m1.n) + 5 <= 3 * ceiling(n / 2) + 8 is the amount of needed // scratch space. limbs_half_gcd_matrix_mul_matrix(m, &m1, scratch_hi); success = true; } } } loop { // Needs s + 3 < n let nn; (bits, nn) = limbs_half_gcd_jacobi_step(&mut xs[..n], &mut ys[..n], s, m, bits, scratch); if nn == 0 { return (bits, if success { n } else { 0 }); } n = nn; success = true; } } // This is equivalent to `CHOOSE_P` from `mpn/jacobi.c`, GMP 6.2.1. const fn choose_p(n: usize) -> usize { (n << 1) / 3 } const BITS_FAIL: u8 = 31; // This is equivalent to `mpn_jacobi_finish` from `gmp-impl.h`, GMP 6.2.1, which also handles the // `bits == BITS_FAIL` case. fn limbs_jacobi_finish(bits: u8) -> i8 { // (a, b) = (1,0) or (0,1) if bits == BITS_FAIL { 0 } else if bits.even() { 1 } else { -1 } } // This is equivalent to `mpn_jacobi_init` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_jacobi_symbol_init(a: Limb, b: Limb, s: u8) -> u8 { assert!(b.odd()); assert!(s <= 1); u8::wrapping_from((a.mod_power_of_2(2) << 2) + (b & 2)) + s }} struct JacobiContext<'a> { bits_mut: &'a mut u8, } impl GcdSubdivideStepContext for JacobiContext<'_> { // This is equivalent to `jacobi_hook` from `mpn/jacobi.c`, GMP 6.2.1. fn gcd_subdiv_step_hook( &mut self, gs: Option<&[Limb]>, qs: Option<&mut [Limb]>, qs_len: usize, d: i8, ) { if let Some(gs) = gs { let gs_len = gs.len(); assert_ne!(gs_len, 0); if gs_len != 1 || gs[0] != 1 { *self.bits_mut = BITS_FAIL; return; } } if let Some(qs) = qs { assert_ne!(qs_len, 0); assert!(d >= 0); *self.bits_mut = limbs_jacobi_update( *self.bits_mut, u8::wrapping_from(d), qs[0].mod_power_of_2(2), ); } else { fail_on_untested_path("JacobiContext::gcd_subdiv_step_hook, qs == None"); } } } const JACOBI_DC_THRESHOLD: usize = GCD_DC_THRESHOLD; // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_jacobi_n` from `mpn/jacobi.c`, GMP 6.2.1. pub_crate_test! { limbs_jacobi_symbol_same_length(xs: &mut [Limb], ys: &mut [Limb], mut bits: u8) -> i8 { let mut n = xs.len(); assert_eq!(ys.len(), n); assert_ne!(n, 0); assert!(xs[n - 1] != 0 || ys[n - 1] != 0); assert!((ys[0] | xs[0]).odd()); let mut scratch_len = limbs_gcd_subdivide_step_scratch_len(n); if n >= JACOBI_DC_THRESHOLD { let p = choose_p(n); let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let hgcd_scratch_len = limbs_half_gcd_scratch_len(n - p); let update_scratch_len = p + n - 1; let dc_scratch_len = matrix_scratch_len + max(hgcd_scratch_len, update_scratch_len); assert!(dc_scratch_len > scratch_len); scratch_len = dc_scratch_len; } let mut scratch = vec![0; scratch_len]; let mut xs: &mut [Limb] = &mut xs[..]; let mut ys: &mut [Limb] = &mut ys[..]; let mut scratch: &mut [Limb] = &mut scratch; while n >= JACOBI_DC_THRESHOLD { let p = (n << 1) / 3; let matrix_scratch_len = limbs_half_gcd_matrix_init_scratch_len(n - p); let (scratch_lo, scratch_hi) = scratch.split_at_mut(matrix_scratch_len); let mut m = HalfGcdMatrix::init(n - p, scratch_lo); let nn; (bits, nn) = limbs_half_gcd_jacobi(&mut xs[p..n], &mut ys[p..n], &mut m, bits, scratch_hi); if nn != 0 { assert!(m.n <= (n - p - 1) >> 1); assert!(m.n + p <= (p + n - 1) >> 1); // Temporary storage 2 (p + M->n) <= p + n - 1. n = limbs_half_gcd_matrix_adjust(&m, p + nn, xs, ys, p, scratch_hi); } else { // Temporary storage n n = limbs_gcd_subdivide_step( &mut xs[..n], &mut ys[..n], 0, &mut JacobiContext { bits_mut: &mut bits, }, scratch, ); if n == 0 { return limbs_jacobi_finish(bits); } } } while n > 2 { let mask = xs[n - 1] | ys[n - 1]; assert_ne!(mask, 0); let (xs_hi, xs_lo, ys_hi, ys_lo) = if mask.get_highest_bit() { (xs[n - 1], xs[n - 2], ys[n - 1], ys[n - 2]) } else { let shift = LeadingZeros::leading_zeros(mask); ( extract_number(shift, xs[n - 1], xs[n - 2]), extract_number(shift, xs[n - 2], xs[n - 3]), extract_number(shift, ys[n - 1], ys[n - 2]), extract_number(shift, ys[n - 2], ys[n - 3]), ) }; let mut m = HalfGcdMatrix1::default(); // Try a `limbs_half_gcd_2_jacobi` step let b; (bits, b) = limbs_half_gcd_2_jacobi(xs_hi, xs_lo, ys_hi, ys_lo, &mut m, bits); if b { n = limbs_half_gcd_matrix_1_mul_inverse_vector( &m, &mut scratch[..n], &xs[..n], &mut ys[..n], ); swap(&mut xs, &mut scratch); } else { // `limbs_half_gcd_2_jacobi` has failed. Then either one of x or y is very small, or the // difference is very small. Perform one subtraction followed by one division. n = limbs_gcd_subdivide_step( &mut xs[..n], &mut ys[..n], 0, &mut JacobiContext { bits_mut: &mut bits, }, scratch, ); if n == 0 { return limbs_jacobi_finish(bits); } } } if bits >= 16 { swap(&mut xs, &mut ys); } assert!(ys[0].odd()); let j = if n == 1 { let x_lo = xs[0]; let y_lo = ys[0]; if y_lo == 1 { 1 } else { x_lo.jacobi_symbol(y_lo) } } else { DoubleLimb::join_halves(xs[1], xs[0]).jacobi_symbol(DoubleLimb::join_halves(ys[1], ys[0])) }; if bits.even() { j } else { -j } }} impl LegendreSymbol for Natural { /// Computes the Legendre symbol of two [`Natural`]s, taking both by value. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(10u32).legendre_symbol(Natural::from(5u32)), 0); /// assert_eq!(Natural::from(7u32).legendre_symbol(Natural::from(5u32)), -1); /// assert_eq!(Natural::from(11u32).legendre_symbol(Natural::from(5u32)), 1); /// ``` #[inline] fn legendre_symbol(self, other: Self) -> i8 { assert_ne!(other, 0u32); assert!(other.odd()); (&self).kronecker_symbol(&other) } } impl<'a> LegendreSymbol<&'a Self> for Natural { /// Computes the Legendre symbol of two [`Natural`]s, taking the first by value and the second /// by reference. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).legendre_symbol(&Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(7u32).legendre_symbol(&Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// Natural::from(11u32).legendre_symbol(&Natural::from(5u32)), /// 1 /// ); /// ``` #[inline] fn legendre_symbol(self, other: &'a Self) -> i8 { assert_ne!(*other, 0u32); assert!(other.odd()); (&self).kronecker_symbol(other) } } impl LegendreSymbol for &Natural { /// Computes the Legendre symbol of two [`Natural`]s, taking both the first by reference and the /// second by value. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).legendre_symbol(Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).legendre_symbol(Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).legendre_symbol(Natural::from(5u32)), /// 1 /// ); /// ``` #[inline] fn legendre_symbol(self, other: Natural) -> i8 { assert_ne!(other, 0u32); assert!(other.odd()); self.kronecker_symbol(&other) } } impl LegendreSymbol<&Natural> for &Natural { /// Computes the Legendre symbol of two [`Natural`]s, taking both by reference. /// /// This implementation is identical to that of [`JacobiSymbol`], since there is no /// computational benefit to requiring that the denominator be prime. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LegendreSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).legendre_symbol(&Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).legendre_symbol(&Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).legendre_symbol(&Natural::from(5u32)), /// 1 /// ); /// ``` #[inline] fn legendre_symbol(self, other: &Natural) -> i8 { assert_ne!(*other, 0u32); assert!(other.odd()); self.kronecker_symbol(other) } } impl JacobiSymbol for Natural { /// Computes the Jacobi symbol of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(10u32).jacobi_symbol(Natural::from(5u32)), 0); /// assert_eq!(Natural::from(7u32).jacobi_symbol(Natural::from(5u32)), -1); /// assert_eq!(Natural::from(11u32).jacobi_symbol(Natural::from(5u32)), 1); /// assert_eq!(Natural::from(11u32).jacobi_symbol(Natural::from(9u32)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: Self) -> i8 { assert_ne!(other, 0u32); assert!(other.odd()); (&self).kronecker_symbol(&other) } } impl<'a> JacobiSymbol<&'a Self> for Natural { /// Computes the Jacobi symbol of two [`Natural`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(10u32).jacobi_symbol(&Natural::from(5u32)), 0); /// assert_eq!(Natural::from(7u32).jacobi_symbol(&Natural::from(5u32)), -1); /// assert_eq!(Natural::from(11u32).jacobi_symbol(&Natural::from(5u32)), 1); /// assert_eq!(Natural::from(11u32).jacobi_symbol(&Natural::from(9u32)), 1); /// ``` #[inline] fn jacobi_symbol(self, other: &'a Self) -> i8 { assert_ne!(*other, 0u32); assert!(other.odd()); (&self).kronecker_symbol(other) } } impl JacobiSymbol for &Natural { /// Computes the Jacobi symbol of two [`Natural`]s, taking the first by reference and the second /// by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).jacobi_symbol(Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).jacobi_symbol(Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).jacobi_symbol(Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).jacobi_symbol(Natural::from(9u32)), /// 1 /// ); /// ``` #[inline] fn jacobi_symbol(self, other: Natural) -> i8 { assert_ne!(other, 0u32); assert!(other.odd()); self.kronecker_symbol(&other) } } impl JacobiSymbol<&Natural> for &Natural { /// Computes the Jacobi symbol of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is even. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::JacobiSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).jacobi_symbol(&Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).jacobi_symbol(&Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).jacobi_symbol(&Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).jacobi_symbol(&Natural::from(9u32)), /// 1 /// ); /// ``` #[inline] fn jacobi_symbol(self, other: &Natural) -> i8 { assert_ne!(*other, 0u32); assert!(other.odd()); self.kronecker_symbol(other) } } impl KroneckerSymbol for Natural { /// Computes the Kronecker symbol of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).kronecker_symbol(Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(7u32).kronecker_symbol(Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(Natural::from(9u32)), /// 1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(Natural::from(8u32)), /// -1 /// ); /// ``` #[inline] fn kronecker_symbol(self, other: Self) -> i8 { (&self).kronecker_symbol(&other) } } impl<'a> KroneckerSymbol<&'a Self> for Natural { /// Computes the Kronecker symbol of two [`Natural`]s, taking the first by value and the second /// by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32).kronecker_symbol(&Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(7u32).kronecker_symbol(&Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(&Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(&Natural::from(9u32)), /// 1 /// ); /// assert_eq!( /// Natural::from(11u32).kronecker_symbol(&Natural::from(8u32)), /// -1 /// ); /// ``` #[inline] fn kronecker_symbol(self, other: &'a Self) -> i8 { (&self).kronecker_symbol(other) } } impl KroneckerSymbol for &Natural { /// Computes the Kronecker symbol of two [`Natural`]s, taking the first by reference and the /// second by value. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).kronecker_symbol(Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).kronecker_symbol(Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(9u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(8u32)), /// -1 /// ); /// ``` #[inline] fn kronecker_symbol(self, other: Natural) -> i8 { self.kronecker_symbol(&other) } } impl KroneckerSymbol<&Natural> for &Natural { /// Computes the Kronecker symbol of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = \left ( \frac{x}{y} \right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::KroneckerSymbol; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).kronecker_symbol(Natural::from(5u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(7u32)).kronecker_symbol(Natural::from(5u32)), /// -1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(5u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(9u32)), /// 1 /// ); /// assert_eq!( /// (&Natural::from(11u32)).kronecker_symbol(Natural::from(8u32)), /// -1 /// ); /// ``` fn kronecker_symbol(self, other: &Natural) -> i8 { match (self, other) { (x, &Natural::ZERO) => i8::from(*x == 1u32), (&Natural::ZERO, y) => i8::from(*y == 1u32), (Natural(Small(x)), Natural(Small(y))) => { limbs_kronecker_symbol_single(true, *x, true, *y) } (Natural(Small(x)), Natural(Large(ys))) => { limbs_kronecker_symbol(true, &[*x], true, ys) } (Natural(Large(xs)), Natural(Small(y))) => { limbs_kronecker_symbol(true, xs, true, &[*y]) } (Natural(Large(xs)), Natural(Large(ys))) => limbs_kronecker_symbol(true, xs, true, ys), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign, Gcd, Lcm, LcmAssign}; use malachite_base::num::basic::traits::Zero; impl Lcm for Natural { type Output = Self; /// Computes the LCM (least common multiple) of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Lcm; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).lcm(Natural::from(5u32)), 15); /// assert_eq!(Natural::from(12u32).lcm(Natural::from(90u32)), 180); /// ``` fn lcm(mut self, other: Self) -> Self { self.lcm_assign(other); self } } impl<'a> Lcm<&'a Self> for Natural { type Output = Self; /// Computes the LCM (least common multiple) of two [`Natural`]s, taking the first by value and /// the second by reference. /// /// $$ /// f(x, y) = \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Lcm; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).lcm(&Natural::from(5u32)), 15); /// assert_eq!(Natural::from(12u32).lcm(&Natural::from(90u32)), 180); /// ``` #[inline] fn lcm(mut self, other: &'a Self) -> Self { self.lcm_assign(other); self } } impl Lcm for &Natural { type Output = Natural; /// Computes the LCM (least common multiple) of two [`Natural`]s, taking the first by reference /// and the second by value. /// /// $$ /// f(x, y) = \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Lcm; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(3u32)).lcm(Natural::from(5u32)), 15); /// assert_eq!((&Natural::from(12u32)).lcm(Natural::from(90u32)), 180); /// ``` #[inline] fn lcm(self, mut other: Natural) -> Natural { other.lcm_assign(self); other } } impl Lcm<&Natural> for &Natural { type Output = Natural; /// Computes the LCM (least common multiple) of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Lcm; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(3u32)).lcm(&Natural::from(5u32)), 15); /// assert_eq!((&Natural::from(12u32)).lcm(&Natural::from(90u32)), 180); /// ``` #[inline] fn lcm(self, other: &Natural) -> Natural { if *self == 0 || *other == 0 { return Natural::ZERO; } let gcd = self.gcd(other); // Division is slower than multiplication, so we choose the arguments to div_exact to be as // small as possible. This also allows the special case of lcm(x, y) when x is a multiple of // y to be quickly reduced to x. if self >= other { self * other.div_exact(gcd) } else { other * self.div_exact(gcd) } } } impl LcmAssign for Natural { /// Replaces a [`Natural`] by its LCM (least common multiple) with another [`Natural`], taking /// the [`Natural`] on the right-hand side by value. /// /// $$ /// x \gets \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LcmAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.lcm_assign(Natural::from(5u32)); /// assert_eq!(x, 15); /// /// let mut x = Natural::from(12u32); /// x.lcm_assign(Natural::from(90u32)); /// assert_eq!(x, 180); /// ``` #[inline] fn lcm_assign(&mut self, mut other: Self) { if *self == 0 { return; } else if other == 0 { *self = Self::ZERO; return; } let gcd = (&*self).gcd(&other); if *self >= other { other.div_exact_assign(gcd); } else { self.div_exact_assign(gcd); } *self *= other; } } impl<'a> LcmAssign<&'a Self> for Natural { /// Replaces a [`Natural`] by its LCM (least common multiple) with another [`Natural`], taking /// the [`Natural`] on the right-hand side by reference. /// /// $$ /// x \gets \operatorname{lcm}(x, y). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::LcmAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.lcm_assign(&Natural::from(5u32)); /// assert_eq!(x, 15); /// /// let mut x = Natural::from(12u32); /// x.lcm_assign(&Natural::from(90u32)); /// assert_eq!(x, 180); /// ``` #[inline] fn lcm_assign(&mut self, other: &'a Self) { if *self == 0 { return; } else if *other == 0 { *self = Self::ZERO; return; } self.div_exact_assign((&*self).gcd(other)); *self *= other; } } ================================================ FILE: malachite-nz/src/natural/arithmetic/log_base.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2011 Sebastian Pancratz // // Copyright © 2011 Fredrik Johansson // // 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 crate::natural::Natural; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBasePowerOf2, CheckedLogBase, CheckedLogBase2, CheckedLogBasePowerOf2, DivExactAssign, FloorLogBase, FloorLogBasePowerOf2, Pow, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::rounding_modes::RoundingMode::*; impl Natural { /// Calculates the approximate natural logarithm of a nonzero [`Natural`]. /// /// $f(x) = (1+\varepsilon)(\ln x)$, where $|\varepsilon| < 2^{-52}.$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::float::NiceFloat; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// NiceFloat(Natural::from(10u32).approx_ln()), /// NiceFloat(2.3025850929940455) /// ); /// assert_eq!( /// NiceFloat(Natural::from(10u32).pow(10000).approx_ln()), /// NiceFloat(23025.850929940454) /// ); /// ``` /// /// This is equivalent to `fmpz_dlog` from `fmpz/dlog.c`, FLINT 2.7.1. pub fn approx_ln(&self) -> f64 { assert_ne!(*self, 0); let (mantissa, exponent): (f64, u64) = self.sci_mantissa_and_exponent(); libm::log(mantissa) + (exponent as f64) * core::f64::consts::LN_2 } } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. fn log_base_helper(x: &Natural, base: &Natural) -> (u64, bool) { assert_ne!(*x, 0); assert!(*base > 1); if *x == 1 { return (0, true); } else if x < base { return (0, false); } let mut log = u64::rounding_from(x.approx_ln() / base.approx_ln(), Floor).0; let mut power = base.pow(log); match power.cmp(x) { Equal => (log, true), Less => loop { power *= base; match power.cmp(x) { Equal => { return (log + 1, true); } Less => { log += 1; } Greater => { return (log, false); } } }, Greater => loop { power.div_exact_assign(base); match power.cmp(x) { Equal => { return (log - 1, true); } Less => { return (log - 1, false); } Greater => { log -= 1; } } }, } } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. // // Also returns base^p and p, where base^p is close to x. pub(crate) fn log_base_helper_with_pow(x: &Natural, base: &Natural) -> (u64, bool, Natural, u64) { assert_ne!(*x, 0); assert!(*base > 1); if *x == 1 { return (0, true, Natural::ONE, 0); } else if x < base { return (0, false, Natural::ONE, 0); } let mut log = (x.approx_ln() / base.approx_ln()) as u64; let mut power = base.pow(log); match power.cmp(x) { Equal => (log, true, power, log), Less => loop { power *= base; match power.cmp(x) { Equal => { log += 1; return (log, true, power, log); } Less => { log += 1; } Greater => { return (log, false, power, log + 1); } } }, Greater => loop { power.div_exact_assign(base); match power.cmp(x) { Equal => { log -= 1; return (log, true, power, log); } Less => { log -= 1; return (log, false, power, log); } Greater => { log -= 1; } } }, } } impl FloorLogBase<&Natural> for &Natural { type Output = u64; /// Returns the floor of the base-$b$ logarithm of a positive [`Natural`]. /// /// $f(x, b) = \lfloor\log_b x\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(80u32).floor_log_base(&Natural::from(3u32)), 3); /// assert_eq!(Natural::from(81u32).floor_log_base(&Natural::from(3u32)), 4); /// assert_eq!(Natural::from(82u32).floor_log_base(&Natural::from(3u32)), 4); /// assert_eq!( /// Natural::from(4294967296u64).floor_log_base(&Natural::from(10u32)), /// 9 /// ); /// ``` /// /// This is equivalent to `fmpz_flog` from `fmpz/flog.c`, FLINT 2.7.1. fn floor_log_base(self, base: &Natural) -> u64 { if let Some(log_base) = base.checked_log_base_2() { return self.floor_log_base_power_of_2(log_base); } log_base_helper(self, base).0 } } impl CeilingLogBase<&Natural> for &Natural { type Output = u64; /// Returns the ceiling of the base-$b$ logarithm of a positive [`Natural`]. /// /// $f(x, b) = \lceil\log_b x\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(80u32).ceiling_log_base(&Natural::from(3u32)), /// 4 /// ); /// assert_eq!( /// Natural::from(81u32).ceiling_log_base(&Natural::from(3u32)), /// 4 /// ); /// assert_eq!( /// Natural::from(82u32).ceiling_log_base(&Natural::from(3u32)), /// 5 /// ); /// assert_eq!( /// Natural::from(4294967296u64).ceiling_log_base(&Natural::from(10u32)), /// 10 /// ); /// ``` /// /// This is equivalent to `fmpz_clog` from `fmpz/clog.c`, FLINT 2.7.1. fn ceiling_log_base(self, base: &Natural) -> u64 { if let Some(log_base) = base.checked_log_base_2() { return self.ceiling_log_base_power_of_2(log_base); } let (log, exact) = log_base_helper(self, base); if exact { log } else { log + 1 } } } impl CheckedLogBase<&Natural> for &Natural { type Output = u64; /// Returns the base-$b$ logarithm of a positive [`Natural`]. If the [`Natural`] is not a power /// of $b$, then `None` is returned. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(\log_b x) & \text{if} \\quad \log_b x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(80u32).checked_log_base(&Natural::from(3u32)), /// None /// ); /// assert_eq!( /// Natural::from(81u32).checked_log_base(&Natural::from(3u32)), /// Some(4) /// ); /// assert_eq!( /// Natural::from(82u32).checked_log_base(&Natural::from(3u32)), /// None /// ); /// assert_eq!( /// Natural::from(4294967296u64).checked_log_base(&Natural::from(10u32)), /// None /// ); /// ``` fn checked_log_base(self, base: &Natural) -> Option { if let Some(log_base) = base.checked_log_base_2() { return self.checked_log_base_power_of_2(log_base); } let (log, exact) = log_base_helper(self, base); if exact { Some(log) } else { None } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::natural::{Natural, limb_to_bit_count}; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{CeilingLogBase2, CheckedLogBase2, FloorLogBase2}; use malachite_base::slices::slice_test_zero; // Given the limbs of a `Natural`, returns the floor of its base-2 logarithm. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $f((d_i)_ {i=0}^k) = \lfloor\log_2 x\rfloor$, where $x = \sum_{i=0}^kB^id_i$ and $B$ is one more // than `Limb::MAX`. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_floor_log_base_2(xs: &[Limb]) -> u64 { limbs_significant_bits(xs) - 1 }} // Given the limbs of a `Natural`, returns the ceiling of its base-2 logarithm. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $f((d_i)_ {i=0}^k) = \lceil\log_2 x\rceil$, where $x = \sum_{i=0}^kB^id_i$ and $B$ is one more // than `Limb::MAX`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_ceiling_log_base_2(xs: &[Limb]) -> u64 { let floor_log_base_2 = limbs_floor_log_base_2(xs); if limbs_is_power_of_2(xs) { floor_log_base_2 } else { floor_log_base_2 + 1 } }} // Given the limbs of a `Natural`, returns the its base-2 logarithm. If the `Natural` is not a power // of 2, returns `None`. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $$ // f((d_i)_ {i=0}^k) = \\begin{cases} // \operatorname{Some}(\log_2 x) & \text{if} \\quad \log_2 x \in \Z, \\\\ // \operatorname{None} & \textrm{otherwise}. // \\end{cases} // $$ // where $x = \sum_{i=0}^kB^id_i$ and $B$ is one more than `Limb::MAX`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_checked_log_base_2(xs: &[Limb]) -> Option { let (xs_last, xs_init) = xs.split_last().unwrap(); if slice_test_zero(xs_init) { xs_last .checked_log_base_2() .map(|log| log + limb_to_bit_count(xs_init.len())) } else { None } }} impl FloorLogBase2 for &Natural { type Output = u64; /// Returns the floor of the base-2 logarithm of a positive [`Natural`]. /// /// $f(x) = \lfloor\log_2 x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).floor_log_base_2(), 1); /// assert_eq!(Natural::from(100u32).floor_log_base_2(), 6); /// ``` fn floor_log_base_2(self) -> u64 { match self { Natural(Small(small)) => small.floor_log_base_2(), Natural(Large(limbs)) => limbs_floor_log_base_2(limbs), } } } impl CeilingLogBase2 for &Natural { type Output = u64; /// Returns the ceiling of the base-2 logarithm of a positive [`Natural`]. /// /// $f(x) = \lceil\log_2 x\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).ceiling_log_base_2(), 2); /// assert_eq!(Natural::from(100u32).ceiling_log_base_2(), 7); /// ``` fn ceiling_log_base_2(self) -> u64 { match self { Natural(Small(small)) => small.ceiling_log_base_2(), Natural(Large(limbs)) => limbs_ceiling_log_base_2(limbs), } } } impl CheckedLogBase2 for &Natural { type Output = u64; /// Returns the base-2 logarithm of a positive [`Natural`]. If the [`Natural`] is not a power of /// 2, then `None` is returned. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\log_2 x) & \text{if} \\quad \log_2 x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::CheckedLogBase2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(3u32).checked_log_base_2(), None); /// assert_eq!(Natural::from(4u32).checked_log_base_2(), Some(2)); /// assert_eq!( /// Natural::from_str("1267650600228229401496703205376") /// .unwrap() /// .checked_log_base_2(), /// Some(100) /// ); /// ``` fn checked_log_base_2(self) -> Option { match self { Natural(Small(small)) => small.checked_log_base_2(), Natural(Large(limbs)) => limbs_checked_log_base_2(limbs), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{ CeilingLogBasePowerOf2, CheckedLogBasePowerOf2, DivMod, FloorLogBasePowerOf2, }; // Given the limbs of a `Natural`, returns the floor of its base-$2^p$ logarithm. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $f((d_i)_ {i=0}^k, p) = \lfloor\log_{2^p} x\rfloor$, where $x = \sum_{i=0}^kB^id_i$ and $B$ is // one more than `Limb::MAX`. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty or `pow` is 0. pub_test! {limbs_floor_log_base_power_of_2(xs: &[Limb], pow: u64) -> u64 { assert_ne!(pow, 0); (limbs_significant_bits(xs) - 1) / pow }} // Given the limbs of a `Natural`, returns the ceiling of its base-$2^p$ logarithm. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $f((d_i)_ {i=0}^k, p) = \lceil\log_{2^p} x\rceil$, where $x = \sum_{i=0}^kB^id_i$ and $B$ is one // more than `Limb::MAX`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or `pow` is 0. pub_test! {limbs_ceiling_log_base_power_of_2(xs: &[Limb], pow: u64) -> u64 { assert_ne!(pow, 0); let significant_bits_m_1 = limbs_significant_bits(xs) - 1; let (floor_log, rem) = significant_bits_m_1.div_mod(pow); if limbs_is_power_of_2(xs) && rem == 0 { floor_log } else { floor_log + 1 } }} // Given the limbs of a `Natural`, returns the its base-$2^p$ logarithm. If the `Natural` is not a // power of $2^p$, returns `None`. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // $$ // f((d_i)_ {i=0}^k, p) = \\begin{cases} // \operatorname{Some}(\log_{2^p} x) & \text{if} \\quad \log_{2^p} x \in \Z, \\\\ // \operatorname{None} & \textrm{otherwise}. // \\end{cases} // $$ // where $x = \sum_{i=0}^kB^id_i$ and $B$ is one more than `Limb::MAX`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty or `pow` is 0. pub_test! {limbs_checked_log_base_power_of_2(xs: &[Limb], pow: u64) -> Option { assert_ne!(pow, 0); let significant_bits_m_1 = limbs_significant_bits(xs) - 1; let (floor_log, rem) = significant_bits_m_1.div_mod(pow); if limbs_is_power_of_2(xs) && rem == 0 { Some(floor_log) } else { None } }} impl FloorLogBasePowerOf2 for &Natural { type Output = u64; /// Returns the floor of the base-$2^k$ logarithm of a positive [`Natural`]. /// /// $f(x, k) = \lfloor\log_{2^k} x\rfloor$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `self` is 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBasePowerOf2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(100u32).floor_log_base_power_of_2(2), 3); /// assert_eq!(Natural::from(4294967296u64).floor_log_base_power_of_2(8), 4); /// ``` fn floor_log_base_power_of_2(self, pow: u64) -> u64 { match self { Natural(Small(small)) => small.floor_log_base_power_of_2(pow), Natural(Large(limbs)) => limbs_floor_log_base_power_of_2(limbs, pow), } } } impl CeilingLogBasePowerOf2 for &Natural { type Output = u64; /// Returns the ceiling of the base-$2^k$ logarithm of a positive [`Natural`]. /// /// $f(x, k) = \lceil\log_{2^k} x\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBasePowerOf2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(100u32).ceiling_log_base_power_of_2(2), 4); /// assert_eq!( /// Natural::from(4294967296u64).ceiling_log_base_power_of_2(8), /// 4 /// ); /// ``` fn ceiling_log_base_power_of_2(self, pow: u64) -> u64 { match self { Natural(Small(small)) => small.ceiling_log_base_power_of_2(pow), Natural(Large(limbs)) => limbs_ceiling_log_base_power_of_2(limbs, pow), } } } impl CheckedLogBasePowerOf2 for &Natural { type Output = u64; /// Returns the base-$2^k$ logarithm of a positive [`Natural`]. If the [`Natural`] is not a /// power of $2^k$, then `None` is returned. /// /// $$ /// f(x, k) = \\begin{cases} /// \operatorname{Some}(\log_{2^k} x) & \text{if} \\quad \log_{2^k} x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBasePowerOf2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(100u32).checked_log_base_power_of_2(2), None); /// assert_eq!( /// Natural::from(4294967296u64).checked_log_base_power_of_2(8), /// Some(4) /// ); /// ``` fn checked_log_base_power_of_2(self, pow: u64) -> Option { match self { Natural(Small(small)) => small.checked_log_base_power_of_2(pow), Natural(Large(limbs)) => limbs_checked_log_base_power_of_2(limbs, pow), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`AbsDiff`](malachite_base::num::arithmetic::traits::AbsDiff) and /// [`AbsDiffAssign`](malachite_base::num::arithmetic::traits::AbsDiffAssign), traits for getting /// the absolute value of the difference between two numbers. pub mod abs_diff; /// Addition of [`Natural`](super::Natural)s. pub mod add; /// Implementations of [`AddMul`](malachite_base::num::arithmetic::traits::AddMul) and /// [`AddMulAssign`](malachite_base::num::arithmetic::traits::AddMulAssign), traits for adding a /// number and the product of two other numbers. pub mod add_mul; /// Implementations of /// [`BinomialCoefficient`](malachite_base::num::arithmetic::traits::BinomialCoefficient), a trait /// for computing the binomial coefficient of two numbers. pub mod binomial_coefficient; /// Implementations of [`CheckedSub`](malachite_base::num::arithmetic::traits::CheckedSub), a trait /// for subtracting two numbers and checking whether the result is representable. pub mod checked_sub; /// Implementations of [`CheckedSubMul`](malachite_base::num::arithmetic::traits::CheckedSubMul), a /// trait for subtracting the product of two numbers from another number, and checking whether the /// result is representable. pub mod checked_sub_mul; /// Implementations of [`CoprimeWith`](malachite_base::num::arithmetic::traits::CoprimeWith), a /// trait for determining whether two numbers are coprime. pub mod coprime_with; /// Division of [`Natural`](super::Natural)s. pub mod div; /// Implementations of [`DivExact`](malachite_base::num::arithmetic::traits::DivExact) and /// [`DivExactAssign`](malachite_base::num::arithmetic::traits::DivExactAssign), traits for dividing /// two numbers when it's known that the division is exact. pub mod div_exact; /// Implementations of raits for simultaneously finding the quotient and remainder of two numbers, /// subject to various rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |--------------|---------------------------------|----------------------------------------| /// | towards $-\infty$ | [`DivMod`](malachite_base::num::arithmetic::traits::DivMod) | [`DivAssignMod`](malachite_base::num::arithmetic::traits::DivAssignMod) | /// | towards 0 | [`DivRem`](malachite_base::num::arithmetic::traits::DivRem) | [`DivAssignRem`](malachite_base::num::arithmetic::traits::DivAssignRem) | /// | towards $\infty$ | [`CeilingDivNegMod`](malachite_base::num::arithmetic::traits::CeilingDivNegMod) | [`CeilingDivAssignNegMod`](malachite_base::num::arithmetic::traits::CeilingDivAssignNegMod) | /// /// [`CeilingDivNegMod`](malachite_base::num::arithmetic::traits::CeilingDivNegMod) returns a /// remainder greater than or equal to zero. This allows the remainder to have an unsigned type, but /// modifies the usual relation $x = qy + r$ to $x = qy - r$. pub mod div_mod; /// Implementations of [`DivRound`](malachite_base::num::arithmetic::traits::DivRound) and /// [`DivExactAssign`](malachite_base::num::arithmetic::traits::DivRoundAssign), traits for dividing /// two numbers according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). pub mod div_round; /// Implementations of [`DivisibleBy`](malachite_base::num::arithmetic::traits::DivisibleBy), a /// trait for determining whether one number is divisible by another. pub mod divisible_by; /// Implementations of /// [`DivisibleByPowerOf2`](malachite_base::num::arithmetic::traits::DivisibleByPowerOf2), a trait /// for determining whether a number is divisible by $2^k$. pub mod divisible_by_power_of_2; /// Implementations of [`EqMod`](malachite_base::num::arithmetic::traits::EqMod), a trait for /// determining whether one number is equal by another modulo a third. pub mod eq_mod; /// Implementations of [`EqModPowerOf2`](malachite_base::num::arithmetic::traits::EqModPowerOf2), a /// trait for determining whether one number is equal to another modulo $2^k$. pub mod eq_mod_power_of_2; /// Implementations of [`Factorial`](malachite_base::num::arithmetic::traits::Factorial), /// [`DoubleFactorial`](malachite_base::num::arithmetic::traits::DoubleFactorial), /// [`Multifactorial`](malachite_base::num::arithmetic::traits::Multifactorial), and /// [`Subfactorial`](malachite_base::num::arithmetic::traits::Subfactorial). pub mod factorial; #[cfg(feature = "float_helpers")] pub mod float_add; #[cfg(feature = "float_helpers")] pub mod float_div; #[cfg(feature = "float_helpers")] pub mod float_extras; #[cfg(feature = "float_helpers")] pub mod float_mul; #[cfg(feature = "float_helpers")] pub mod float_reciprocal; #[cfg(feature = "float_helpers")] pub mod float_reciprocal_sqrt; #[cfg(feature = "float_helpers")] pub mod float_sqrt; #[cfg(feature = "float_helpers")] pub mod float_square; #[cfg(feature = "float_helpers")] pub mod float_sub; /// Implementations of [`Gcd`](malachite_base::num::arithmetic::traits::Gcd) and /// [`GcdAssign`](malachite_base::num::arithmetic::traits::GcdAssign), traits for computing the GCD /// (greatest common divisor) of two numbers. pub mod gcd; /// Implementations of [`IsPowerOf2`](malachite_base::num::arithmetic::traits::IsPowerOf2), a trait /// for determining whether a number is an integer power of 2. pub mod is_power_of_2; /// Implementations of [`LegendreSymbol`](malachite_base::num::arithmetic::traits::LegendreSymbol), /// [`JacobiSymbol`](malachite_base::num::arithmetic::traits::JacobiSymbol), and /// [`KroneckerSymbol`](malachite_base::num::arithmetic::traits::KroneckerSymbol), traits for /// computing the Legendre, Jacobi, and Kronecker symbols of two numbers. pub mod kronecker_symbol; /// Implementations of [`Lcm`](malachite_base::num::arithmetic::traits::Lcm), /// [`LcmAssign`](malachite_base::num::arithmetic::traits::LcmAssign), and /// [`CheckedLcm`](malachite_base::num::arithmetic::traits::CheckedLcm), traits for computing the /// LCM (least common multiple) of two numbers. pub mod lcm; /// Implementations of traits for taking the base-$b$ logarithm of a number. /// /// The traits are [`FloorLogBase`](malachite_base::num::arithmetic::traits::FloorLogBase), /// [`CeilingLogBase`](malachite_base::num::arithmetic::traits::CeilingLogBase), and /// [`CheckedLogBase`](malachite_base::num::arithmetic::traits::CheckedLogBase). pub mod log_base; /// Implementations of traits for taking the base-2 logarithm of a number. /// /// The traits are [`FloorLogBase2`](malachite_base::num::arithmetic::traits::FloorLogBase2), /// [`CeilingLogBase2`](malachite_base::num::arithmetic::traits::CeilingLogBase2), and /// [`CheckedLogBase2`](malachite_base::num::arithmetic::traits::CheckedLogBase2). pub mod log_base_2; /// Implementations of traits for taking the base-$2^k$ logarithm of a number. /// /// The traits are /// [`FloorLogBasePowerOf2`](malachite_base::num::arithmetic::traits::FloorLogBasePowerOf2), /// [`CeilingLogBasePowerOf2`](malachite_base::num::arithmetic::traits::CeilingLogBasePowerOf2), and /// [`CheckedLogBasePowerOf2`](malachite_base::num::arithmetic::traits::CheckedLogBasePowerOf2). pub mod log_base_power_of_2; /// Implementations of [`ModAdd`](malachite_base::num::arithmetic::traits::ModAdd) and /// [`ModAddAssign`](malachite_base::num::arithmetic::traits::ModAddAssign), traits for adding two /// numbers modulo another number. pub mod mod_add; /// Implementations of [`ModInverse`](malachite_base::num::arithmetic::traits::ModInverse), a trait /// for finding the multiplicative inverse of a number modulo another number. pub mod mod_inverse; /// Implementations of [`ModIsReduced`](malachite_base::num::arithmetic::traits::ModIsReduced), a /// trait for checking whether a number is reduced modulo another number. pub mod mod_is_reduced; /// Implementations of traits for multiplying two numbers modulo another number. /// /// The traits are [`ModMul`](malachite_base::num::arithmetic::traits::ModMul), /// [`ModMulAssign`](malachite_base::num::arithmetic::traits::ModMulAssign), /// [`ModMulPrecomputed`](malachite_base::num::arithmetic::traits::ModMulPrecomputed), and /// [`ModMulPrecomputedAssign`](malachite_base::num::arithmetic::traits::ModMulPrecomputedAssign). /// [`ModMulPrecomputed`](malachite_base::num::arithmetic::traits::ModMulPrecomputed) and /// [`ModMulPrecomputedAssign`](malachite_base::num::arithmetic::traits::ModMulPrecomputedAssign) /// are useful when having to make several multiplications modulo the same modulus. pub mod mod_mul; /// Implementations of [`ModNeg`](malachite_base::num::arithmetic::traits::ModNeg) and /// [`ModNegAssign`](malachite_base::num::arithmetic::traits::ModNegAssign), traits for negating a /// number modulo another number. pub mod mod_neg; /// Implementations of traits for finding the remainder of two numbers, subject to various rounding /// rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |-------------------|----------------------------|----------------------------------------| /// | towards $-\infty$ | [`Mod`](malachite_base::num::arithmetic::traits::Mod) | [`ModAssign`](malachite_base::num::arithmetic::traits::ModAssign) | /// | towards $\infty$ | [`NegMod`](malachite_base::num::arithmetic::traits::NegMod) | [`NegModAssign`](malachite_base::num::arithmetic::traits::NegModAssign) | /// /// [`NegMod`](malachite_base::num::arithmetic::traits::NegMod) returns a remainder greater than or /// equal to zero. This allows the remainder to have an unsigned type, but modifies the usual /// relation $x = qy + r$ to $x = qy - r$. /// /// The [`Rem`](core::ops::Rem) trait in the standard library rounds towards 0. pub mod mod_op; /// Implementations of traits for raising a number to a power modulo another number. /// /// The traits are [`ModPow`](malachite_base::num::arithmetic::traits::ModPow), /// [`ModPowAssign`](malachite_base::num::arithmetic::traits::ModPowAssign), and /// [`ModPowPrecomputed`](malachite_base::num::arithmetic::traits::ModPowPrecomputed). /// [`ModPowPrecomputed`](malachite_base::num::arithmetic::traits::ModPowPrecomputed) is useful when /// having to make several exponentiations modulo the same modulus. pub mod mod_pow; /// Implementations of traits for finding the remainder of a number divided by $2^k$, subject to /// various rounding rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |----------|-----------------------|-----------------------------------| /// | towards $-\infty$ | [`ModPowerOf2`](malachite_base::num::arithmetic::traits::ModPowerOf2) | [`ModPowerOf2Assign`](malachite_base::num::arithmetic::traits::ModPowerOf2Assign) | /// | towards 0 | [`RemPowerOf2`](malachite_base::num::arithmetic::traits::RemPowerOf2) | [`RemPowerOf2Assign`](malachite_base::num::arithmetic::traits::RemPowerOf2Assign) | /// | towards $\infty$ | [`NegModPowerOf2`](malachite_base::num::arithmetic::traits::NegModPowerOf2) | [`NegModPowerOf2Assign`](malachite_base::num::arithmetic::traits::NegModPowerOf2Assign) | /// /// [`NegModPowerOf2`](malachite_base::num::arithmetic::traits::NegModPowerOf2) returns a remainder /// greater than or equal to zero. This allows the remainder to have an unsigned type, but modifies /// the usual relation $x = q2^k + r$ to $x = q2^k - r$. pub mod mod_power_of_2; /// Implementations of [`ModPowerOf2Add`](malachite_base::num::arithmetic::traits::ModPowerOf2Add) /// and [`ModPowerOf2AddAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign), /// traits for adding two numbers modulo $2^k$. pub mod mod_power_of_2_add; /// Implementations of /// [`ModPowerOf2Inverse`](malachite_base::num::arithmetic::traits::ModPowerOf2Inverse), a trait for /// finding the multiplicative inverse of a number modulo $2^k$. pub mod mod_power_of_2_inverse; /// Implementations of /// [`ModPowerOf2IsReduced`](malachite_base::num::arithmetic::traits::ModPowerOf2IsReduced), a trait /// for checking whether a number is reduced modulo $2^k$. pub mod mod_power_of_2_is_reduced; /// Implementations of [`ModPowerOf2Mul`](malachite_base::num::arithmetic::traits::ModPowerOf2Mul) /// and [`ModPowerOf2MulAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2MulAssign), /// traits for multiplying two numbers modulo $2^k$. pub mod mod_power_of_2_mul; /// Implementations of [`ModPowerOf2Neg`](malachite_base::num::arithmetic::traits::ModPowerOf2Neg) /// and [`ModPowerOf2NegAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2NegAssign), /// traits for negating a number modulo $2^k$. pub mod mod_power_of_2_neg; /// Implementations of [`ModPowerOf2Pow`](malachite_base::num::arithmetic::traits::ModPowerOf2Pow) /// and [`ModPowerOf2PowAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign), /// traits for raising a number to a power modulo $2^k$. pub mod mod_power_of_2_pow; /// Implementations of [`ModPowerOf2Shl`](malachite_base::num::arithmetic::traits::ModPowerOf2Shl) /// and [`ModPowerOf2ShlAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2ShlAssign), /// traits for left-shifting a number modulo $2^k$. /// /// # mod_power_of_2_shl /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Shl; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).mod_power_of_2_shl(5u16, 8), 96); /// assert_eq!(Natural::from(123u32).mod_power_of_2_shl(100u64, 80), 0); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shl(5u16, 8), 96); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shl(100u64, 80), 0); /// /// assert_eq!(Natural::from(123u32).mod_power_of_2_shl(5i16, 8), 96); /// assert_eq!(Natural::from(123u32).mod_power_of_2_shl(100i64, 80), 0); /// assert_eq!(Natural::from(123u32).mod_power_of_2_shl(-2i8, 8), 30); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shl(5i16, 8), 96); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shl(100i64, 80), 0); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shl(-2i8, 8), 30); /// ``` /// /// # mod_power_of_2_shl_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2ShlAssign; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shl_assign(5u16, 8); /// assert_eq!(n, 96); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shl_assign(100u64, 80); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shl_assign(5i16, 8); /// assert_eq!(n, 96); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shl_assign(100i64, 80); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shl_assign(-2i8, 8); /// assert_eq!(n, 30); /// ``` pub mod mod_power_of_2_shl; /// Implementations of [`ModPowerOf2Shr`](malachite_base::num::arithmetic::traits::ModPowerOf2Shr) /// and [`ModPowerOf2ShrAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2ShrAssign), /// traits for right-shifting a number modulo $2^k$. /// /// # mod_power_of_2_shr /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Shr; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).mod_power_of_2_shr(-5i16, 8), 96); /// assert_eq!(Natural::from(123u32).mod_power_of_2_shr(-100i64, 80), 0); /// assert_eq!(Natural::from(123u32).mod_power_of_2_shr(2i8, 8), 30); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shr(-5i16, 8), 96); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shr(-100i64, 80), 0); /// assert_eq!((&Natural::from(123u32)).mod_power_of_2_shr(2i8, 8), 30); /// ``` /// /// # mod_power_of_2_shr_assign /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2ShrAssign; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shr_assign(-5i16, 8); /// assert_eq!(n, 96); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shr_assign(-100i64, 80); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(123u32); /// n.mod_power_of_2_shr_assign(2i8, 8); /// assert_eq!(n, 30); /// ``` pub mod mod_power_of_2_shr; /// Implementations of /// `ModPowerOf2Square`](malachite_base::num::arithmetic::traits::ModPowerOf2Square) and /// [`ModPowerOf2SquareAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2SquareAssign), /// traits for squaring a number modulo $2^k$. pub mod mod_power_of_2_square; /// Implementations of [`ModPowerOf2Sub`](malachite_base::num::arithmetic::traits::ModPowerOf2Sub) /// and [`ModPowerOf2SubAssign`](malachite_base::num::arithmetic::traits::ModPowerOf2SubAssign), /// traits for subtracting one number by another modulo $2^k$. pub mod mod_power_of_2_sub; /// Implementations of [`ModShl`](malachite_base::num::arithmetic::traits::ModShl) and /// [`ModShlAssign`](malachite_base::num::arithmetic::traits::ModShlAssign), traits for /// left-shifting a number modulo another number. /// /// # mod_shl /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModShl; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(8u32).mod_shl(2u16, Natural::from(10u32)), 2); /// assert_eq!( /// Natural::from(123456u32).mod_shl(100u64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!(Natural::from(8u32).mod_shl(2u16, &Natural::from(10u32)), 2); /// assert_eq!( /// Natural::from(123456u32).mod_shl(100u64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!( /// (&Natural::from(8u32)).mod_shl(2u16, Natural::from(10u32)), /// 2 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shl(100u64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!( /// (&Natural::from(8u32)).mod_shl(2u16, &Natural::from(10u32)), /// 2 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shl(100u64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// /// assert_eq!(Natural::from(8u32).mod_shl(2i8, Natural::from(10u32)), 2); /// assert_eq!( /// Natural::from(5u32).mod_shl(-100i32, Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(123456u32).mod_shl(100i64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!(Natural::from(8u32).mod_shl(2i8, &Natural::from(10u32)), 2); /// assert_eq!( /// Natural::from(5u32).mod_shl(-100i32, &Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(123456u32).mod_shl(100i64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!((&Natural::from(8u32)).mod_shl(2i8, Natural::from(10u32)), 2); /// assert_eq!( /// (&Natural::from(5u32)).mod_shl(-100i32, Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shl(100i64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!( /// (&Natural::from(8u32)).mod_shl(2i8, &Natural::from(10u32)), /// 2 /// ); /// assert_eq!( /// (&Natural::from(5u32)).mod_shl(-100i32, &Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shl(100i64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// ``` /// /// # mod_shl_assign /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModShlAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(8u32); /// x.mod_shl_assign(2u16, Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(123456u32); /// x.mod_shl_assign(100u64, Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// /// let mut x = Natural::from(8u32); /// x.mod_shl_assign(2u16, &Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(123456u32); /// x.mod_shl_assign(100u64, &Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// /// let mut x = Natural::from(8u32); /// x.mod_shl_assign(2i8, Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(5u32); /// x.mod_shl_assign(-100i32, Natural::from(10u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123456u32); /// x.mod_shl_assign(100i64, Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// /// let mut x = Natural::from(8u32); /// x.mod_shl_assign(2i8, &Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(5u32); /// x.mod_shl_assign(-100i32, &Natural::from(10u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123456u32); /// x.mod_shl_assign(100i64, &Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// ``` pub mod mod_shl; /// Implementations of [`ModShr`](malachite_base::num::arithmetic::traits::ModShr) and /// [`ModShrAssign`](malachite_base::num::arithmetic::traits::ModShrAssign), traits for /// right-shifting a number modulo another number. /// /// # mod_shr /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModShr; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(8u32).mod_shr(-2i8, Natural::from(10u32)), 2); /// assert_eq!(Natural::from(5u32).mod_shr(100i32, Natural::from(10u32)), 0); /// assert_eq!( /// Natural::from(123456u32).mod_shr(-100i64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!(Natural::from(8u32).mod_shr(-2i8, &Natural::from(10u32)), 2); /// assert_eq!( /// Natural::from(5u32).mod_shr(100i32, &Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(123456u32).mod_shr(-100i64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!( /// (&Natural::from(8u32)).mod_shr(-2i8, Natural::from(10u32)), /// 2 /// ); /// assert_eq!( /// (&Natural::from(5u32)).mod_shr(100i32, Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shr(-100i64, Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// assert_eq!( /// (&Natural::from(8u32)).mod_shr(-2i8, &Natural::from(10u32)), /// 2 /// ); /// assert_eq!( /// (&Natural::from(5u32)).mod_shr(100i32, &Natural::from(10u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(123456u32)) /// .mod_shr(-100i64, &Natural::from_str("12345678987654321").unwrap()), /// 7436663564915145u64 /// ); /// ``` /// /// # mod_shr_assign /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModShrAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(8u32); /// x.mod_shr_assign(-2i8, Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(5u32); /// x.mod_shr_assign(100i32, Natural::from(10u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123456u32); /// x.mod_shr_assign(-100i64, Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// /// let mut x = Natural::from(8u32); /// x.mod_shr_assign(-2i8, &Natural::from(10u32)); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(5u32); /// x.mod_shr_assign(100i32, &Natural::from(10u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123456u32); /// x.mod_shr_assign(-100i64, &Natural::from_str("12345678987654321").unwrap()); /// assert_eq!(x, 7436663564915145u64); /// ``` pub mod mod_shr; /// Implementations of traits for squaring a number modulo another number. /// /// The traits are [`ModSquare`](malachite_base::num::arithmetic::traits::ModSquare), /// [`ModSquareAssign`](malachite_base::num::arithmetic::traits::ModSquareAssign), and /// [`ModSquarePrecomputed`](malachite_base::num::arithmetic::traits::ModSquarePrecomputed). /// [`ModSquarePrecomputed`](malachite_base::num::arithmetic::traits::ModSquarePrecomputed) is /// useful when having to make several squarings modulo the same modulus. pub mod mod_square; /// Implementations of [`ModSub`](malachite_base::num::arithmetic::traits::ModSub) and /// [`ModSubAssign`](malachite_base::num::arithmetic::traits::ModSubAssign), traits for subtracting /// two numbers modulo another number. pub mod mod_sub; /// Multiplication of [`Natural`](super::Natural)s. pub mod mul; /// Negation of a [`Natural`](super::Natural), returning an [`Integer`](crate::integer::Integer). pub mod neg; /// Implementations of [`NextPowerOf2`](malachite_base::num::arithmetic::traits::NextPowerOf2) and /// [`NextPowerOf2Assign`](malachite_base::num::arithmetic::traits::NextPowerOf2Assign), traits for /// getting the next-highest power of 2. pub mod next_power_of_2; /// Implementations of [`Parity`](malachite_base::num::arithmetic::traits::Parity), a trait for /// determining whether a number is even or odd. pub mod parity; /// Implementations of [`Pow`](malachite_base::num::arithmetic::traits::Pow) and /// [`PowAssign`](malachite_base::num::arithmetic::traits::PowAssign), traits for raising a number /// to a power. pub mod pow; /// Implementations of [`PowerOf2`](malachite_base::num::arithmetic::traits::PowerOf2), a trait for /// computing a power of 2. pub mod power_of_2; /// An implementation of [`Primorial`](malachite_base::num::arithmetic::traits::Primorial), a trait /// for computing the primorial of a number. pub mod primorial; /// Implementations of traits for taking the $n$th root of a number. /// /// The traits are [`FloorRoot`](malachite_base::num::arithmetic::traits::FloorRoot), /// [`FloorRootAssign`](malachite_base::num::arithmetic::traits::FloorRootAssign), /// [`CeilingRoot`](malachite_base::num::arithmetic::traits::CeilingRoot), /// [`CeilingRootAssign`](malachite_base::num::arithmetic::traits::CeilingRootAssign), /// [`CheckedRoot`](malachite_base::num::arithmetic::traits::CheckedRoot), /// [`RootRem`](malachite_base::num::arithmetic::traits::RootRem), and /// [`RootAssignRem`](malachite_base::num::arithmetic::traits::RootAssignRem). pub mod root; /// Implementations of [`RoundToMultiple`](malachite_base::num::arithmetic::traits::RoundToMultiple) /// and [`RoundToMultipleAssign`](malachite_base::num::arithmetic::traits::RoundToMultipleAssign), /// traits for rounding a number to a multiple of another number. pub mod round_to_multiple; /// Implementations of /// [`RoundToMultipleOfPowerOf2`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2) /// and /// [`RoundToMultipleOfPowerOf2Assign`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign), /// traits for rounding a number to a multiple of a power of 2. pub mod round_to_multiple_of_power_of_2; /// Implementations of [`SaturatingSub`](malachite_base::num::arithmetic::traits::SaturatingSub) and /// [`SaturatingSubAssign`](malachite_base::num::arithmetic::traits::SaturatingSubAssign), traits /// for subtracting two numbers and saturating at numeric bounds instead of overflowing. pub mod saturating_sub; /// Implementations of /// [`SaturatingSubMul`](malachite_base::num::arithmetic::traits::SaturatingSubMul) and /// [`SaturatingSubMulAssign`](malachite_base::num::arithmetic::traits::SaturatingSubMulAssign), /// traits for subtracting a number by the product of two numbers and saturating at numeric bounds /// instead of overflowing. pub mod saturating_sub_mul; /// Left-shifting a [`Natural`](super::Natural) (multiplying it by a power of 2). /// /// # shl /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((Natural::ZERO << 10u8), 0); /// assert_eq!((Natural::from(123u32) << 2u16), 492); /// assert_eq!( /// (Natural::from(123u32) << 100u64).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!((&Natural::ZERO << 10u8), 0); /// assert_eq!((&Natural::from(123u32) << 2u16), 492); /// assert_eq!( /// (&Natural::from(123u32) << 100u64).to_string(), /// "155921023828072216384094494261248" /// ); /// /// assert_eq!((Natural::ZERO << 10i8), 0); /// assert_eq!((Natural::from(123u32) << 2i16), 492); /// assert_eq!( /// (Natural::from(123u32) << 100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!((Natural::ZERO << -10i64), 0); /// assert_eq!((Natural::from(10u32).pow(12) << -10i16), 976562500); /// assert_eq!((&Natural::ZERO << 10i8), 0); /// assert_eq!((&Natural::from(123u32) << 2i16), 492); /// assert_eq!( /// (&Natural::from(123u32) << 100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!((&Natural::ZERO << -10i64), 0); /// assert_eq!((&Natural::from(492u32) << -2i8), 123); /// assert_eq!((&Natural::from(10u32).pow(12) << -10i16), 976562500); /// ``` /// /// # shl_assign /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ONE; /// x <<= 1u8; /// x <<= 2u16; /// x <<= 3u32; /// x <<= 4u64; /// assert_eq!(x, 1024); /// /// let mut x = Natural::ONE; /// x <<= 1i8; /// x <<= 2i16; /// x <<= 3i32; /// x <<= 4i64; /// assert_eq!(x, 1024); /// /// let mut x = Natural::from(1024u32); /// x <<= -1i8; /// x <<= -2i16; /// x <<= -3i32; /// x <<= -4i64; /// assert_eq!(x, 1); /// ``` pub mod shl; /// Implementations of [`ShlRound`](malachite_base::num::arithmetic::traits::ShlRound) and /// [`ShlRoundAssign`](malachite_base::num::arithmetic::traits::ShlRoundAssign), traits for /// multiplying a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). /// /// # shl_round /// ``` /// use malachite_base::num::arithmetic::traits::ShlRound; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0x101u32) /// .shl_round(-8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shl_round(-8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shl_round(-9i32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shl_round(-9i64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shl_round(-9i8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0xffu32) /// .shl_round(-9i16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shl_round(-9i32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shl_round(-8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// assert_eq!( /// Natural::ZERO.shl_round(10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Natural::from(123u32) /// .shl_round(2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// Natural::from(123u32) /// .shl_round(100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shl_round(-8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shl_round(-8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shl_round(-9i32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shl_round(-9i64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shl_round(-9i8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0xffu32)) /// .shl_round(-9i16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shl_round(-9i32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shl_round(-8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// assert_eq!( /// (&Natural::ZERO).shl_round(10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .shl_round(2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .shl_round(100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// ``` /// /// # shl_round_assign /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::ShlRoundAssign; /// use malachite_base::num::basic::traits::One; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shl_round_assign(-8i8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shl_round_assign(-8i16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shl_round_assign(-9i32, Down), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shl_round_assign(-9i64, Up), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shl_round_assign(-9i8, Nearest), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0xffu32); /// assert_eq!(n.shl_round_assign(-9i16, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shl_round_assign(-9i32, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shl_round_assign(-8i64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut x = Natural::ONE; /// assert_eq!(x.shl_round_assign(1i8, Exact), Equal); /// assert_eq!(x.shl_round_assign(2i16, Exact), Equal); /// assert_eq!(x.shl_round_assign(3i32, Exact), Equal); /// assert_eq!(x.shl_round_assign(4i64, Exact), Equal); /// assert_eq!(x, 1024); /// ``` pub mod shl_round; /// Right-shifting a [`Natural`](super::Natural) (dividing it by a power of 2). /// /// # shr /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((Natural::ZERO >> 10u8), 0); /// assert_eq!((Natural::from(492u32) >> 2u32), 123); /// assert_eq!((Natural::from(10u32).pow(12) >> 10u64), 976562500); /// assert_eq!((&Natural::ZERO >> 10u8), 0); /// assert_eq!((&Natural::from(492u32) >> 2u32), 123); /// assert_eq!((&Natural::from(10u32).pow(12) >> 10u64), 976562500); /// /// assert_eq!((Natural::ZERO >> 10i8), 0); /// assert_eq!((Natural::from(492u32) >> 2i16), 123); /// assert_eq!((Natural::from(10u32).pow(12) >> 10i32), 976562500); /// assert_eq!((Natural::ZERO >> -10i64), 0); /// assert_eq!((Natural::from(123u32) >> -2i8), 492); /// assert_eq!( /// (Natural::from(123u32) >> -100i16).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!((&Natural::ZERO >> -10i8), 0); /// assert_eq!((&Natural::from(123u32) >> -2i16), 492); /// assert_eq!( /// (&Natural::from(123u32) >> -100i32).to_string(), /// "155921023828072216384094494261248" /// ); /// assert_eq!((&Natural::ZERO >> 10i64), 0); /// assert_eq!((&Natural::from(492u32) >> 2i8), 123); /// assert_eq!((&Natural::from(10u32).pow(12) >> 10i16), 976562500); /// ``` /// /// # shr_assign /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(1024u32); /// x >>= 1u8; /// x >>= 2u16; /// x >>= 3u32; /// x >>= 4u64; /// assert_eq!(x, 1); /// /// let mut x = Natural::ONE; /// x >>= -1i8; /// x >>= -2i16; /// x >>= -3i32; /// x >>= -4i64; /// assert_eq!(x, 1024); /// /// let mut x = Natural::from(1024u32); /// x >>= 1i8; /// x >>= 2i16; /// x >>= 3i32; /// x >>= 4i64; /// assert_eq!(x, 1); /// ``` pub mod shr; /// Implementations of [`ShrRound`](malachite_base::num::arithmetic::traits::ShrRound) and /// [`ShrRoundAssign`](malachite_base::num::arithmetic::traits::ShrRoundAssign), traits for dividing /// a number by a power of 2 and rounding according to a specified /// [`RoundingMode`](malachite_base::rounding_modes::RoundingMode). /// /// # shr_round /// ``` /// use malachite_base::num::arithmetic::traits::ShrRound; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(8u8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(8u16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9u32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9u64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9u8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0xffu32) /// .shr_round(9u16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shr_round(9u32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shr_round(8u64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(8u8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(8u16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9u32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9u64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9u8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0xffu32)) /// .shr_round(9u16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shr_round(9u32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shr_round(8u64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9i32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9i64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0x101u32) /// .shr_round(9i8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// Natural::from(0xffu32) /// .shr_round(9i16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shr_round(9i32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// Natural::from(0x100u32) /// .shr_round(8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// assert_eq!( /// Natural::ZERO.shr_round(-10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Natural::from(123u32) /// .shr_round(-2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// Natural::from(123u32) /// .shr_round(-100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(8i8, Down) /// .to_debug_string(), /// "(1, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(8i16, Up) /// .to_debug_string(), /// "(2, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9i32, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9i64, Up) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0x101u32)) /// .shr_round(9i8, Nearest) /// .to_debug_string(), /// "(1, Greater)" /// ); /// assert_eq!( /// (&Natural::from(0xffu32)) /// .shr_round(9i16, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shr_round(9i32, Nearest) /// .to_debug_string(), /// "(0, Less)" /// ); /// assert_eq!( /// (&Natural::from(0x100u32)) /// .shr_round(8i64, Exact) /// .to_debug_string(), /// "(1, Equal)" /// ); /// assert_eq!( /// (&Natural::ZERO).shr_round(-10i8, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .shr_round(-2i16, Exact) /// .to_debug_string(), /// "(492, Equal)" /// ); /// assert_eq!( /// (&Natural::from(123u32)) /// .shr_round(-100i32, Exact) /// .to_debug_string(), /// "(155921023828072216384094494261248, Equal)" /// ); /// ``` /// /// # shr_round_assign /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::ShrRoundAssign; /// use malachite_base::num::basic::traits::One; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(8u8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(8u16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9u32, Down), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9u64, Up), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9u8, Nearest), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0xffu32); /// assert_eq!(n.shr_round_assign(9u16, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shr_round_assign(9u32, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shr_round_assign(8u64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(8i8, Down), Less); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(8i16, Up), Greater); /// assert_eq!(n, 2); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9i32, Down), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9i64, Up), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0x101u32); /// assert_eq!(n.shr_round_assign(9i8, Nearest), Greater); /// assert_eq!(n, 1); /// /// let mut n = Natural::from(0xffu32); /// assert_eq!(n.shr_round_assign(9i16, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shr_round_assign(9i32, Nearest), Less); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(0x100u32); /// assert_eq!(n.shr_round_assign(8i64, Exact), Equal); /// assert_eq!(n, 1); /// /// let mut x = Natural::ONE; /// assert_eq!(x.shr_round_assign(-1i8, Exact), Equal); /// assert_eq!(x.shr_round_assign(-2i16, Exact), Equal); /// assert_eq!(x.shr_round_assign(-3i32, Exact), Equal); /// assert_eq!(x.shr_round_assign(-4i64, Exact), Equal); /// assert_eq!(x, 1024); /// ``` pub mod shr_round; /// Implementations of [`Sign`](malachite_base::num::arithmetic::traits::Sign), a trait for /// determining the sign of a number. pub mod sign; /// Implementations of traits for taking the square root of a number. /// /// The traits are [`FloorSqrt`](malachite_base::num::arithmetic::traits::FloorSqrt), /// [`FloorSqrtAssign`](malachite_base::num::arithmetic::traits::FloorSqrtAssign), /// [`CeilingSqrt`](malachite_base::num::arithmetic::traits::CeilingSqrt), /// [`CeilingSqrtAssign`](malachite_base::num::arithmetic::traits::CeilingSqrtAssign), /// [`CheckedSqrt`](malachite_base::num::arithmetic::traits::CheckedSqrt), /// [`SqrtRem`](malachite_base::num::arithmetic::traits::SqrtRem), and /// [`SqrtAssignRem`](malachite_base::num::arithmetic::traits::SqrtAssignRem). pub mod sqrt; /// Implementations of [`Square`](malachite_base::num::arithmetic::traits::Square) and /// [`SquareAssign`](malachite_base::num::arithmetic::traits::SquareAssign), traits for squaring a /// number. pub mod square; /// Subtraction of [`Natural`](super::Natural)s. pub mod sub; /// Implementations of [`SubMul`](malachite_base::num::arithmetic::traits::SubMul) and /// [`SubMulAssign`](malachite_base::num::arithmetic::traits::SubMulAssign), traits for subtracting /// the product of two numbers from a number. pub mod sub_mul; ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2019 Daniel Schultz // // 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModAdd, ModAddAssign}; impl ModAdd for Natural { type Output = Self; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. All three [`Natural`]s are taken by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO.mod_add(Natural::from(3u32), Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// Natural::from(7u32).mod_add(Natural::from(5u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value. #[inline] fn mod_add(mut self, other: Self, m: Self) -> Self { self.mod_add_assign(other, m); self } } impl<'a> ModAdd for Natural { type Output = Self; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first two [`Natural`]s are taken by value and the third by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO.mod_add(Natural::from(3u32), &Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// Natural::from(7u32).mod_add(Natural::from(5u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value and `m` is taken by reference. #[inline] fn mod_add(mut self, other: Self, m: &'a Self) -> Self { self.mod_add_assign(other, m); self } } impl<'a> ModAdd<&'a Self, Self> for Natural { type Output = Self; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first and third [`Natural`]s are taken by value and the second by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO.mod_add(&Natural::from(3u32), Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// Natural::from(7u32).mod_add(&Natural::from(5u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value and `c` is taken by reference. #[inline] fn mod_add(mut self, other: &'a Self, m: Self) -> Self { self.mod_add_assign(other, m); self } } impl<'a, 'b> ModAdd<&'a Self, &'b Self> for Natural { type Output = Self; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first [`Natural`] is taken by value and the second and third by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO.mod_add(&Natural::from(3u32), &Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// Natural::from(7u32).mod_add(&Natural::from(5u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` is /// taken by value and `c` and `m` are taken by reference. #[inline] fn mod_add(mut self, other: &'a Self, m: &'b Self) -> Self { self.mod_add_assign(other, m); self } } impl ModAdd for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first [`Natural`] is taken by reference and the second and third by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO) /// .mod_add(Natural::from(3u32), Natural::from(5u32)) /// .to_string(), /// "3" /// ); /// assert_eq!( /// (&Natural::from(7u32)) /// .mod_add(Natural::from(5u32), Natural::from(10u32)) /// .to_string(), /// "2" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` is /// taken by reference and `c` and `m` are taken by value. #[inline] fn mod_add(self, mut other: Natural, m: Natural) -> Natural { other.mod_add_assign(self, m); other } } impl ModAdd for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first and third [`Natural`]s are taken by reference and the second by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).mod_add(Natural::from(3u32), &Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_add(Natural::from(5u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `m` /// are taken by reference and `c` is taken by value. #[inline] fn mod_add(self, mut other: Natural, m: &Natural) -> Natural { other.mod_add_assign(self, m); other } } impl ModAdd<&Natural, Natural> for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. The first two [`Natural`]s are taken by reference and the third by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).mod_add(&Natural::from(3u32), Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_add(&Natural::from(5u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `c` /// are taken by reference and `m` is taken by value. fn mod_add(self, other: &Natural, m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); let sum = self + other; if sum < m { sum } else { sum - m } } } impl ModAdd<&Natural, &Natural> for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already reduced /// modulo $m$. All three [`Natural`]s are taken by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAdd; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).mod_add(&Natural::from(3u32), &Natural::from(5u32)), /// 3 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_add(&Natural::from(5u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by reference. fn mod_add(self, other: &Natural, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); let sum = self + other; if sum < *m { sum } else { sum - m } } } impl ModAddAssign for Natural { /// Adds two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be already /// reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value. /// /// $x \gets z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_add_assign(Natural::from(3u32), Natural::from(5u32)); /// assert_eq!(x, 3); /// /// let mut x = Natural::from(7u32); /// x.mod_add_assign(Natural::from(5u32), Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value and `a == b`. fn mod_add_assign(&mut self, other: Self, m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); *self += other; if *self >= m { *self -= m; } } } impl<'a> ModAddAssign for Natural { /// Adds two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be already /// reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value and the /// second by reference. /// /// $x \gets z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_add_assign(Natural::from(3u32), &Natural::from(5u32)); /// assert_eq!(x, 3); /// /// let mut x = Natural::from(7u32); /// x.mod_add_assign(Natural::from(5u32), &Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value, `m` is taken by reference, and `a == b`. fn mod_add_assign(&mut self, other: Self, m: &'a Self) { assert!(*self < *m, "self must be reduced mod m, but {self} >= {m}"); assert!( other < *m, "other must be reduced mod m, but {other} >= {m}" ); *self += other; if *self >= *m { *self -= m; } } } impl<'a> ModAddAssign<&'a Self, Self> for Natural { /// Adds two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be already /// reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by reference and /// the second by value. /// /// $x \gets z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_add_assign(&Natural::from(3u32), Natural::from(5u32)); /// assert_eq!(x, 3); /// /// let mut x = Natural::from(7u32); /// x.mod_add_assign(&Natural::from(5u32), Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value, `c` is taken by reference, and `a == b`. fn mod_add_assign(&mut self, other: &'a Self, m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); *self += other; if *self >= m { *self -= m; } } } impl<'a, 'b> ModAddAssign<&'a Self, &'b Self> for Natural { /// Adds two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be already /// reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference. /// /// $x \gets z$, where $x, y, z < m$ and $x + y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_add_assign(&Natural::from(3u32), &Natural::from(5u32)); /// assert_eq!(x, 3); /// /// let mut x = Natural::from(7u32); /// x.mod_add_assign(&Natural::from(5u32), &Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_addN` from `fmpz_mod/add.c`, FLINT 2.7.1, where `b` is /// taken by value, `c` and `m` are taken by reference, and `a == b`. fn mod_add_assign(&mut self, other: &'a Self, m: &'b Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); *self += other; if *self >= *m { *self -= m; } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::Small; use crate::natural::Natural; use crate::natural::arithmetic::gcd::extended_gcd::limbs_extended_gcd; use crate::natural::arithmetic::sub::limbs_sub_same_length_in_place_right; use malachite_base::num::arithmetic::traits::ModInverse; use malachite_base::num::basic::traits::One; fn mod_inverse_helper(x: Natural, m: Natural) -> Option { let mut xs = x.into_limbs_asc(); let mut ys = m.to_limbs_asc(); let len = ys.len(); xs.resize(len, 0); let mut gs = vec![0; len]; let mut ss = vec![0; len + 1]; let (g_len, ss_sign) = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); gs.truncate(g_len); if Natural::from_owned_limbs_asc(gs) != 1u32 { return None; } if !ss_sign { assert_eq!(ss.pop(), Some(0)); limbs_sub_same_length_in_place_right(&m.into_limbs_asc(), &mut ss); } Some(Natural::from_owned_limbs_asc(ss)) } impl ModInverse for Natural { type Output = Self; /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The /// input must be already reduced modulo $m$. Both [`Natural`]s are taken by value. /// /// Returns `None` if $x$ and $m$ are not coprime. /// /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// m.significant_bits())`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModInverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_inverse(Natural::from(10u32)), /// Some(Natural::from(7u32)) /// ); /// assert_eq!(Natural::from(4u32).mod_inverse(Natural::from(10u32)), None); /// ``` fn mod_inverse(self, m: Self) -> Option { assert_ne!(self, 0u32); assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, m) { (x @ Self::ONE, _) => Some(x), (Self(Small(x)), Self(Small(y))) => x.mod_inverse(y).map(Self::from), (a, b) => mod_inverse_helper(a, b), } } } impl<'a> ModInverse<&'a Self> for Natural { type Output = Self; /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The /// input must be already reduced modulo $m$. The first [`Natural`] is taken by value and the /// second by reference. /// /// Returns `None` if $x$ and $m$ are not coprime. /// /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// m.significant_bits())`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModInverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_inverse(&Natural::from(10u32)), /// Some(Natural::from(7u32)) /// ); /// assert_eq!(Natural::from(4u32).mod_inverse(&Natural::from(10u32)), None); /// ``` fn mod_inverse(self, m: &'a Self) -> Option { assert_ne!(self, 0u32); assert!(self < *m, "self must be reduced mod m, but {self} >= {m}"); match (self, m) { (x @ Self::ONE, _) => Some(x), (Self(Small(x)), Self(Small(y))) => x.mod_inverse(*y).map(Self::from), (a, b) => mod_inverse_helper(a, b.clone()), } } } impl ModInverse for &Natural { type Output = Natural; /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The /// input must be already reduced modulo $m$. The first [`Natural`]s is taken by reference and /// the second by value. /// /// Returns `None` if $x$ and $m$ are not coprime. /// /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// m.significant_bits())`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModInverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_inverse(Natural::from(10u32)), /// Some(Natural::from(7u32)) /// ); /// assert_eq!( /// (&Natural::from(4u32)).mod_inverse(Natural::from(10u32)), /// None /// ); /// ``` fn mod_inverse(self, m: Natural) -> Option { assert_ne!(*self, 0u32); assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, m) { (&Natural::ONE, _) => Some(Natural::ONE), (Natural(Small(x)), Natural(Small(y))) => x.mod_inverse(y).map(Natural::from), (a, b) => mod_inverse_helper(a.clone(), b), } } } impl ModInverse<&Natural> for &Natural { type Output = Natural; /// Computes the multiplicative inverse of a [`Natural`] modulo another [`Natural`] $m$. The /// input must be already reduced modulo $m$. Both [`Natural`]s are taken by reference. /// /// Returns `None` if $x$ and $m$ are not coprime. /// /// $f(x, m) = y$, where $x, y < m$, $\gcd(x, y) = 1$, and $xy \equiv 1 \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// m.significant_bits())`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModInverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_inverse(&Natural::from(10u32)), /// Some(Natural::from(7u32)) /// ); /// assert_eq!( /// (&Natural::from(4u32)).mod_inverse(&Natural::from(10u32)), /// None /// ); /// ``` fn mod_inverse(self, m: &Natural) -> Option { assert_ne!(*self, 0u32); assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, m) { (&Natural::ONE, _) => Some(Natural::ONE), (Natural(Small(x)), Natural(Small(y))) => x.mod_inverse(*y).map(Natural::from), (a, b) => mod_inverse_helper(a.clone(), b.clone()), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::ModIsReduced; use malachite_base::num::basic::traits::Zero; impl ModIsReduced for Natural { /// Returns whether a [`Natural`] is reduced modulo another [`Natural`] $m$; in other words, /// whether it is less than $m$. /// /// $m$ cannot be zero. /// /// $f(x, m) = (x < m)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `m` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModIsReduced, Pow}; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_is_reduced(&Natural::from(5u32)), true); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .mod_is_reduced(&Natural::from(10u32).pow(12)), /// false /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .mod_is_reduced(&(Natural::from(10u32).pow(12) + Natural::ONE)), /// true /// ); /// ``` #[inline] fn mod_is_reduced(&self, m: &Self) -> bool { assert_ne!(*m, Self::ZERO); self < m } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2019 Daniel Schultz // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::div_mod::limbs_div_mod_by_two_limb_normalized; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{ ModMul, ModMulAssign, ModMulPrecomputed, ModMulPrecomputedAssign, ModPowerOf2Mul, ModPowerOf2MulAssign, PowerOf2, XMulYToZZ, XXXAddYYYToZZZ, XXXSubYYYToZZZ, XXXXAddYYYYToZZZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; // m_1 cannot be zero, and we cannot have m_1 == 1 and m_0 == 0. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. pub_test! {limbs_precompute_mod_mul_two_limbs(m_1: Limb, m_0: Limb) -> (Limb, Limb, Limb) { let xs = &mut [0; 5]; let out = &mut [0; 3]; let bits = LeadingZeros::leading_zeros(m_1); if bits == 0 { xs[4] = 1; assert!(!limbs_div_mod_by_two_limb_normalized(out, xs, &[m_0, m_1])); } else { xs[4] = Limb::power_of_2(bits); assert!(!limbs_div_mod_by_two_limb_normalized( out, xs, &[m_0 << bits, (m_1 << bits) | (m_0 >> (Limb::WIDTH - bits))] )); } assert_ne!(out[2], 0); (out[2], out[1], out[0]) }} // Standard Barrett reduction: (set r = `Limb::WIDTH`) // // We have m fits into 2 words and 2 ^ r < m < 2 ^ (2 * r). Therefore 2 ^ (3 * r) > 2 ^ (4 * r) / m // > 2 ^ (2 * r) and the precomputed number inv = floor(2 ^ (4 * r) / m) fits into 3 words. The // inputs x and y are < m and therefore fit into 2 words. // // The computation of a = x*y mod m is: // ``` // w = x * y x < m ^ 2 and therefore fits into 4 words // z = (w >> r) * inv z <= m * 2 ^ (3 * r) and therefore fits into 5 words // q = (z >> (3 * r)) * n q fits into 4 words // w = w - q w fits into 3 words after the subtraction // ``` // // at this point the canonical reduction in the range [0, m) is one of a = w, a = w - n, or a = w - // 2 * m // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `_fmpz_mod_mul2` from `fmpz_mod/mul.c`, FLINT 2.7.1. pub_test! {limbs_mod_mul_two_limbs( x_1: Limb, x_0: Limb, y_1: Limb, y_0: Limb, m_1: Limb, m_0: Limb, inv_2: Limb, inv_1: Limb, inv_0: Limb, ) -> (Limb, Limb) { // w[3:0] = x[1:0] * y[1:0] let (w_3, w_2) = Limb::x_mul_y_to_zz(x_1, y_1); let (w_1, w_0) = Limb::x_mul_y_to_zz(x_0, y_0); let (t, carry) = (DoubleLimb::from(x_1) * DoubleLimb::from(y_0)) .overflowing_add(DoubleLimb::from(x_0) * DoubleLimb::from(y_1)); let (t_2, t_1) = t.split_in_half(); let (w_3, w_2, w_1) = Limb::xxx_add_yyy_to_zzz(w_3, w_2, w_1, Limb::from(carry), t_2, t_1); // z[5:0] = w[3:1] * ninv[2:0], z[5] should end up zero let (z_3, z_2) = Limb::x_mul_y_to_zz(w_2, inv_1); let (t, carry) = (DoubleLimb::from(w_1) * DoubleLimb::from(inv_2)) .overflowing_add(DoubleLimb::from(w_3) * DoubleLimb::from(inv_0)); let (t_3, t_2) = t.split_in_half(); let (u_2, u_1) = Limb::x_mul_y_to_zz(w_2, inv_0); let (u_4, u_3) = Limb::x_mul_y_to_zz(w_3, inv_1); let (z_4, z_3, z_2) = Limb::xxx_add_yyy_to_zzz( w_3.wrapping_mul(inv_2), z_3, z_2, Limb::from(carry), t_3, t_2, ); let (v_2, v_1) = Limb::x_mul_y_to_zz(w_1, inv_1); let (v_4, v_3) = Limb::x_mul_y_to_zz(w_2, inv_2); let (z_4, z_3, z_2, z_1) = Limb::xxxx_add_yyyy_to_zzzz( z_4, z_3, z_2, (DoubleLimb::from(w_1) * DoubleLimb::from(inv_0)).upper_half(), u_4, u_3, u_2, u_1, ); let (z_4, z_3, _, _) = Limb::xxxx_add_yyyy_to_zzzz(z_4, z_3, z_2, z_1, v_4, v_3, v_2, v_1); // - q[3:0] = z[4:3] * n[1:0], q[3] is not needed // - x[3:0] -= q[3:0], w[3] should end up zero let (q_1, q_0) = Limb::x_mul_y_to_zz(z_3, m_0); let (w_2, w_1) = DoubleLimb::join_halves(w_2, w_1) .wrapping_sub(DoubleLimb::from(z_4) * DoubleLimb::from(m_0)) .wrapping_sub(DoubleLimb::from(z_3) * DoubleLimb::from(m_1)) .split_in_half(); let (w_2, w_1, w_0) = Limb::xxx_sub_yyy_to_zzz(w_2, w_1, w_0, z_4.wrapping_mul(m_1), q_1, q_0); // at most two subtractions of n, use q as temp space let (q_2, q_1, q_0) = Limb::xxx_sub_yyy_to_zzz(w_2, w_1, w_0, 0, m_1, m_0); if q_2.get_highest_bit() { (w_1, w_0) } else { let (w_2, w_1, w_0) = Limb::xxx_sub_yyy_to_zzz(q_2, q_1, q_0, 0, m_1, m_0); if w_2.get_highest_bit() { (q_1, q_0) } else { (w_1, w_0) } } }} #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[doc(hidden)] pub enum ModMulData { OneLimb(Limb), MinTwoLimbs, TwoLimbs(Limb, Limb, Limb), MoreThanTwoLimbs, } fn precompute_mod_mul_data_helper(m: &Natural) -> ModMulData { match *m { Natural::ZERO => panic!("division by zero"), Natural(Small(ref x)) => ModMulData::OneLimb(Limb::precompute_mod_mul_data(x)), Natural(Large(ref xs)) => match xs[..] { [0, 1] => ModMulData::MinTwoLimbs, [m_0, m_1] => { let (inv_2, inv_1, inv_0) = limbs_precompute_mod_mul_two_limbs(m_1, m_0); ModMulData::TwoLimbs(inv_2, inv_1, inv_0) } _ => ModMulData::MoreThanTwoLimbs, }, } } impl Natural { fn mod_mul_precomputed_two_limbs( &self, y: &Self, m: &Self, inv_2: Limb, inv_1: Limb, inv_0: Limb, ) -> Self { let (r_1, r_0) = match (self, y, m) { (&Self(Small(x)), &Self(Small(y)), &Self(Large(ref ms))) => { limbs_mod_mul_two_limbs(0, x, 0, y, ms[1], ms[0], inv_2, inv_1, inv_0) } (&Self(Large(ref xs)), &Self(Small(y)), &Self(Large(ref ms))) | (&Self(Small(y)), &Self(Large(ref xs)), &Self(Large(ref ms))) => { limbs_mod_mul_two_limbs(xs[1], xs[0], 0, y, ms[1], ms[0], inv_2, inv_1, inv_0) } (&Self(Large(ref xs)), &Self(Large(ref ys)), &Self(Large(ref ms))) => { limbs_mod_mul_two_limbs( xs[1], xs[0], ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0, ) } _ => unreachable!(), }; Self::from_owned_limbs_asc(vec![r_0, r_1]) } fn mod_mul_precomputed_two_limbs_assign( &mut self, y: &Self, m: &Self, inv_2: Limb, inv_1: Limb, inv_0: Limb, ) { match (&mut *self, y, m) { (&mut Self(Small(x)), &Self(Small(y)), &Self(Large(ref ms))) => { let (r_1, r_0) = limbs_mod_mul_two_limbs(0, x, 0, y, ms[1], ms[0], inv_2, inv_1, inv_0); *self = Self::from_owned_limbs_asc(vec![r_0, r_1]); } (&mut Self(Small(x)), &Self(Large(ref ys)), &Self(Large(ref ms))) => { let (r_1, r_0) = limbs_mod_mul_two_limbs(0, x, ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0); *self = Self::from_owned_limbs_asc(vec![r_0, r_1]); } (&mut Self(Large(ref mut xs)), &Self(Small(y)), &Self(Large(ref ms))) => { let (r_1, r_0) = limbs_mod_mul_two_limbs(xs[1], xs[0], 0, y, ms[1], ms[0], inv_2, inv_1, inv_0); *xs = vec![r_0, r_1]; self.trim(); } (&mut Self(Large(ref mut xs)), &Self(Large(ref ys)), &Self(Large(ref ms))) => { let (r_1, r_0) = limbs_mod_mul_two_limbs( xs[1], xs[0], ys[1], ys[0], ms[1], ms[0], inv_2, inv_1, inv_0, ); *xs = vec![r_0, r_1]; self.trim(); } _ => unreachable!(), } } } impl ModMulPrecomputed for Natural { type Output = Self; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &Self) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// Natural::from(6u8).mod_mul_precomputed( /// Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// Natural::from(9u8).mod_mul_precomputed( /// Natural::from(9u32), /// Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// Natural::from(4u8).mod_mul_precomputed( /// Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value. fn mod_mul_precomputed(mut self, other: Self, m: Self, data: &ModMulData) -> Self { self.mod_mul_precomputed_assign(other, m, data); self } } impl<'a> ModMulPrecomputed for Natural { type Output = Self; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &&Self) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by /// reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// Natural::from(6u8).mod_mul_precomputed( /// Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// Natural::from(9u8).mod_mul_precomputed( /// Natural::from(9u32), /// &Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// Natural::from(4u8).mod_mul_precomputed( /// Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value and `m` is taken by reference. fn mod_mul_precomputed(mut self, other: Self, m: &'a Self, data: &ModMulData) -> Self { self.mod_mul_precomputed_assign(other, m, data); self } } impl<'a> ModMulPrecomputed<&'a Self, Self> for Natural { type Output = Self; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &Self) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by value and the second by /// reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// Natural::from(6u8).mod_mul_precomputed( /// &Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// Natural::from(9u8).mod_mul_precomputed( /// &Natural::from(9u32), /// Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// Natural::from(4u8).mod_mul_precomputed( /// &Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value and `c` is taken by reference. fn mod_mul_precomputed(mut self, other: &'a Self, m: Self, data: &ModMulData) -> Self { self.mod_mul_precomputed_assign(other, m, data); self } } impl<'a, 'b> ModMulPrecomputed<&'a Self, &'b Self> for Natural { type Output = Self; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &&Self) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by value and the second and third by /// reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// Natural::from(6u8).mod_mul_precomputed( /// &Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// Natural::from(9u8).mod_mul_precomputed( /// &Natural::from(9u32), /// &Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// Natural::from(4u8).mod_mul_precomputed( /// &Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by value and `c` and `m` are taken by reference. fn mod_mul_precomputed(mut self, other: &'a Self, m: &'b Self, data: &ModMulData) -> Self { self.mod_mul_precomputed_assign(other, m, data); self } } impl ModMulPrecomputed for &Natural { type Output = Natural; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &Natural) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by reference and the second and third by /// value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// (&Natural::from(6u8)).mod_mul_precomputed( /// Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// (&Natural::from(9u8)).mod_mul_precomputed( /// Natural::from(9u32), /// Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// (&Natural::from(4u8)).mod_mul_precomputed( /// Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by reference and `c` and `m` are taken by value. fn mod_mul_precomputed(self, other: Natural, m: Natural, data: &ModMulData) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); match (self, other, m, data) { (&Natural::ZERO, _, _, _) | (_, Natural::ZERO, _, _) => Natural::ZERO, (x, Natural::ONE, _, _) => x.clone(), (&Natural::ONE, y, _, _) => y, ( &Natural(Small(x)), Natural(Small(y)), Natural(Small(m)), &ModMulData::OneLimb(inv), ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)), (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs(&y, &m, inv_2, inv_1, inv_0) } (x, y, m, _) => x * y % m, } } } impl ModMulPrecomputed for &Natural { type Output = Natural; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &&Natural) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the second /// by value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// (&Natural::from(6u8)).mod_mul_precomputed( /// Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// (&Natural::from(9u8)).mod_mul_precomputed( /// Natural::from(9u32), /// &Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// (&Natural::from(4u8)).mod_mul_precomputed( /// Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by reference and `c` is taken by value. #[inline] fn mod_mul_precomputed(self, other: Natural, m: &Natural, data: &ModMulData) -> Natural { other.mod_mul_precomputed(self, m, data) } } impl ModMulPrecomputed<&Natural, Natural> for &Natural { type Output = Natural; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &Natural) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third by /// value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// (&Natural::from(6u8)).mod_mul_precomputed( /// &Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// (&Natural::from(9u8)).mod_mul_precomputed( /// &Natural::from(9u32), /// Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// (&Natural::from(4u8)).mod_mul_precomputed( /// &Natural::from(7u32), /// Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by reference and `m` is taken by value. fn mod_mul_precomputed(self, other: &Natural, m: Natural, data: &ModMulData) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); match (self, other, m, data) { (&Natural::ZERO, _, _, _) | (_, &Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _, _) => x.clone(), (&Natural::ONE, y, _, _) => y.clone(), ( &Natural(Small(x)), &Natural(Small(y)), Natural(Small(m)), &ModMulData::OneLimb(inv), ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)), (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs(y, &m, inv_2, inv_1, inv_0) } (x, y, m, _) => x * y % m, } } } impl ModMulPrecomputed<&Natural, &Natural> for &Natural { type Output = Natural; type Data = ModMulData; /// Precomputes data for modular multiplication. See `mod_mul_precomputed` and /// [`mod_mul_precomputed_assign`](ModMulPrecomputedAssign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// This is equivalent to part of `fmpz_mod_ctx_init` from `fmpz_mod/ctx_init.c`, FLINT 2.7.1. #[inline] fn precompute_mod_mul_data(m: &&Natural) -> ModMulData { precompute_mod_mul_data_helper(m) } /// Multiplies two [`Natural`] modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulPrecomputed; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// assert_eq!( /// (&Natural::from(6u8)).mod_mul_precomputed( /// &Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 2 /// ); /// assert_eq!( /// (&Natural::from(9u8)).mod_mul_precomputed( /// &Natural::from(9u32), /// &Natural::from(10u32), /// &data /// ), /// 1 /// ); /// assert_eq!( /// (&Natural::from(4u8)).mod_mul_precomputed( /// &Natural::from(7u32), /// &Natural::from(10u32), /// &data /// ), /// 8 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from fmpz_mod/mul.c, FLINT 2.7.1, where `b`, `c`, and /// `m` are taken by reference. fn mod_mul_precomputed(self, other: &Natural, m: &Natural, data: &ModMulData) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); match (self, other, m, data) { (&Natural::ZERO, _, _, _) | (_, &Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _, _) => x.clone(), (&Natural::ONE, y, _, _) => y.clone(), ( &Natural(Small(x)), &Natural(Small(y)), &Natural(Small(m)), &ModMulData::OneLimb(inv), ) => Natural::from(x.mod_mul_precomputed(y, m, &inv)), (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs(y, m, inv_2, inv_1, inv_0) } (x, y, m, _) => x * y % m, } } } impl ModMulPrecomputedAssign for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign}; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// /// let mut x = Natural::from(6u8); /// x.mod_mul_precomputed_assign(Natural::from(7u32), Natural::from(10u32), &data); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(9u8); /// x.mod_mul_precomputed_assign(Natural::from(9u32), Natural::from(10u32), &data); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(4u8); /// x.mod_mul_precomputed_assign(Natural::from(7u32), Natural::from(10u32), &data); /// assert_eq!(x, 8); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value and `a == b`. fn mod_mul_precomputed_assign(&mut self, other: Self, m: Self, data: &ModMulData) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); match (&mut *self, other, m, data) { (&mut Self::ZERO, _, _, _) | (_, Self::ONE, _, _) => {} (x, Self::ZERO, _, _) => *x = Self::ZERO, (&mut Self::ONE, y, _, _) => *self = y, (&mut Self(Small(x)), Self(Small(y)), Self(Small(m)), &ModMulData::OneLimb(inv)) => { *self = Self::from(x.mod_mul_precomputed(y, m, &inv)); } (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs_assign(&y, &m, inv_2, inv_1, inv_0); } (x, y, m, _) => { *x *= y; *x %= m; } } } } impl<'a> ModMulPrecomputedAssign for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value /// and the second by reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign}; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// /// let mut x = Natural::from(6u8); /// x.mod_mul_precomputed_assign(Natural::from(7u32), &Natural::from(10u32), &data); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(9u8); /// x.mod_mul_precomputed_assign(Natural::from(9u32), &Natural::from(10u32), &data); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(4u8); /// x.mod_mul_precomputed_assign(Natural::from(7u32), &Natural::from(10u32), &data); /// assert_eq!(x, 8); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value, `m` is taken by reference, and `a == b`. fn mod_mul_precomputed_assign(&mut self, other: Self, m: &'a Self, data: &ModMulData) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( other < *m, "other must be reduced mod m, but {other} >= {m}" ); match (&mut *self, other, m, data) { (&mut Self::ZERO, _, _, _) | (_, Self::ONE, _, _) => {} (x, Self::ZERO, _, _) => *x = Self::ZERO, (&mut Self::ONE, y, _, _) => *self = y, (&mut Self(Small(x)), Self(Small(y)), &Self(Small(m)), &ModMulData::OneLimb(inv)) => { *self = Self::from(x.mod_mul_precomputed(y, m, &inv)); } (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs_assign(&y, m, inv_2, inv_1, inv_0); } (x, y, m, _) => { *x *= y; *x %= m; } } } } impl<'a> ModMulPrecomputedAssign<&'a Self, Self> for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by /// reference and the second by value. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign}; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// /// let mut x = Natural::from(6u8); /// x.mod_mul_precomputed_assign(&Natural::from(7u32), Natural::from(10u32), &data); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(9u8); /// x.mod_mul_precomputed_assign(&Natural::from(9u32), Natural::from(10u32), &data); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(4u8); /// x.mod_mul_precomputed_assign(&Natural::from(7u32), Natural::from(10u32), &data); /// assert_eq!(x, 8); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value, `c` is taken by reference, and `a == b`. fn mod_mul_precomputed_assign(&mut self, other: &'a Self, m: Self, data: &ModMulData) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); match (&mut *self, other, m, data) { (&mut Self::ZERO, _, _, _) | (_, &Self::ONE, _, _) => {} (x, &Self::ZERO, _, _) => *x = Self::ZERO, (&mut Self::ONE, y, _, _) => *self = y.clone(), (&mut Self(Small(x)), &Self(Small(y)), Self(Small(m)), &ModMulData::OneLimb(inv)) => { *self = Self::from(x.mod_mul_precomputed(y, m, &inv)); } (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs_assign(y, &m, inv_2, inv_1, inv_0); } (x, y, m, _) => { *x *= y; *x %= m; } } } } impl<'a, 'b> ModMulPrecomputedAssign<&'a Self, &'b Self> for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference. /// /// Some precomputed data is provided; this speeds up computations involving several modular /// multiplications with the same modulus. The precomputed data should be obtained using /// [`precompute_mod_mul_data`](ModMulPrecomputed::precompute_mod_mul_data). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModMulPrecomputed, ModMulPrecomputedAssign}; /// use malachite_nz::natural::Natural; /// /// let data = ModMulPrecomputed::::precompute_mod_mul_data(&Natural::from(10u32)); /// /// let mut x = Natural::from(6u8); /// x.mod_mul_precomputed_assign(&Natural::from(7u32), &Natural::from(10u32), &data); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(9u8); /// x.mod_mul_precomputed_assign(&Natural::from(9u32), &Natural::from(10u32), &data); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(4u8); /// x.mod_mul_precomputed_assign(&Natural::from(7u32), &Natural::from(10u32), &data); /// assert_eq!(x, 8); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by value, `c` and `m` are taken by reference, and `a == b`. fn mod_mul_precomputed_assign(&mut self, other: &'a Self, m: &'b Self, data: &ModMulData) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); match (&mut *self, other, m, data) { (&mut Self::ZERO, _, _, _) | (_, &Self::ONE, _, _) => {} (x, &Self::ZERO, _, _) => *x = Self::ZERO, (&mut Self::ONE, y, _, _) => *self = y.clone(), (&mut Self(Small(x)), &Self(Small(y)), &Self(Small(m)), &ModMulData::OneLimb(inv)) => { *self = Self::from(x.mod_mul_precomputed(y, m, &inv)); } (x, y, _, &ModMulData::MinTwoLimbs) => x.mod_power_of_2_mul_assign(y, Limb::WIDTH), (x, y, m, &ModMulData::TwoLimbs(inv_2, inv_1, inv_0)) => { x.mod_mul_precomputed_two_limbs_assign(y, m, inv_2, inv_1, inv_0); } (x, y, m, _) => { *x *= y; *x %= m; } } } } impl ModMul for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_mul(Natural::from(4u32), Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// Natural::from(7u32).mod_mul(Natural::from(6u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value. #[inline] fn mod_mul(self, other: Self, m: Self) -> Self { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed(other, m, &data) } } impl<'a> ModMul for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_mul(Natural::from(4u32), &Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// Natural::from(7u32).mod_mul(Natural::from(6u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value and `m` is taken by reference. #[inline] fn mod_mul(self, other: Self, m: &'a Self) -> Self { self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m)) } } impl<'a> ModMul<&'a Self, Self> for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by value and the second by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_mul(&Natural::from(4u32), Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// Natural::from(7u32).mod_mul(&Natural::from(6u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value and `c` is taken by reference. #[inline] fn mod_mul(self, other: &'a Self, m: Self) -> Self { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed(other, m, &data) } } impl<'a, 'b> ModMul<&'a Self, &'b Self> for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by value and the second and third by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_mul(&Natural::from(4u32), &Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// Natural::from(7u32).mod_mul(&Natural::from(6u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by value and `c` and `m` are taken by reference. #[inline] fn mod_mul(self, other: &'a Self, m: &'b Self) -> Self { self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m)) } } impl ModMul for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by reference and the second and third by /// value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_mul(Natural::from(4u32), Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_mul(Natural::from(6u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by reference and `c` and `m` are taken by value. #[inline] fn mod_mul(self, other: Natural, m: Natural) -> Natural { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed(other, m, &data) } } impl ModMul for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the second /// by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_mul(Natural::from(4u32), &Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_mul(Natural::from(6u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by reference and `c` is taken by value. #[inline] fn mod_mul(self, other: Natural, m: &Natural) -> Natural { self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m)) } } impl ModMul<&Natural, Natural> for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third by /// value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_mul(&Natural::from(4u32), Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_mul(&Natural::from(6u32), Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by reference and `m` is taken by value. #[inline] fn mod_mul(self, other: &Natural, m: Natural) -> Natural { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed(other, m, &data) } } impl ModMul<&Natural, &Natural> for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_mul(&Natural::from(4u32), &Natural::from(15u32)), /// 12 /// ); /// assert_eq!( /// (&Natural::from(7u32)).mod_mul(&Natural::from(6u32), &Natural::from(10u32)), /// 2 /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by reference. #[inline] fn mod_mul(self, other: &Natural, m: &Natural) -> Natural { self.mod_mul_precomputed(other, m, &precompute_mod_mul_data_helper(m)) } } impl ModMulAssign for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value. /// /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_mul_assign(Natural::from(4u32), Natural::from(15u32)); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(7u32); /// x.mod_mul_assign(Natural::from(6u32), Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value and `a == b`. #[inline] fn mod_mul_assign(&mut self, other: Self, m: Self) { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed_assign(other, m, &data); } } impl<'a> ModMulAssign for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value /// and the second by reference. /// /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_mul_assign(Natural::from(4u32), &Natural::from(15u32)); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(7u32); /// x.mod_mul_assign(Natural::from(6u32), &Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value, `m` is taken by reference, and `a == b`. #[inline] fn mod_mul_assign(&mut self, other: Self, m: &'a Self) { self.mod_mul_precomputed_assign(other, m, &precompute_mod_mul_data_helper(m)); } } impl<'a> ModMulAssign<&'a Self, Self> for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by /// reference and the second by value. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_mul_assign(&Natural::from(4u32), Natural::from(15u32)); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(7u32); /// x.mod_mul_assign(&Natural::from(6u32), Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value, `c` is taken by reference, and `a == b`. #[inline] fn mod_mul_assign(&mut self, other: &'a Self, m: Self) { let data = precompute_mod_mul_data_helper(&m); self.mod_mul_precomputed_assign(other, m, &data); } } impl<'a, 'b> ModMulAssign<&'a Self, &'b Self> for Natural { /// Multiplies two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference. /// /// $x \gets z$, where $x, y, z < m$ and $xy \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModMulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_mul_assign(&Natural::from(4u32), &Natural::from(15u32)); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(7u32); /// x.mod_mul_assign(&Natural::from(6u32), &Natural::from(10u32)); /// assert_eq!(x, 2); /// ``` /// /// This is equivalent to `_fmpz_mod_mulN` from `fmpz_mod/mul.c`, FLINT 2.7.1, where `b` is /// taken by value, `c` and `m` are taken by reference, and `a == b`. #[inline] fn mod_mul_assign(&mut self, other: &'a Self, m: &'b Self) { self.mod_mul_precomputed_assign(other, m, &precompute_mod_mul_data_helper(m)); } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModNeg, ModNegAssign}; use malachite_base::num::basic::traits::Zero; impl ModNeg for Natural { type Output = Self; /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. Both [`Natural`]s are taken by value. /// /// $f(x, m) = y$, where $x, y < m$ and $-x \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNeg, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_neg(Natural::from(5u32)), 0); /// assert_eq!(Natural::from(7u32).mod_neg(Natural::from(10u32)), 3); /// assert_eq!( /// Natural::from(7u32).mod_neg(Natural::from(10u32).pow(12)), /// 999999999993u64 /// ); /// ``` #[inline] fn mod_neg(mut self, m: Self) -> Self { self.mod_neg_assign(&m); self } } impl<'a> ModNeg<&'a Self> for Natural { type Output = Self; /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The first [`Natural`] is taken by value and the second by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNeg, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_neg(&Natural::from(5u32)), 0); /// assert_eq!(Natural::from(7u32).mod_neg(&Natural::from(10u32)), 3); /// assert_eq!( /// Natural::from(7u32).mod_neg(&Natural::from(10u32).pow(12)), /// 999999999993u64 /// ); /// ``` #[inline] fn mod_neg(mut self, m: &'a Self) -> Self { self.mod_neg_assign(m); self } } impl ModNeg for &Natural { type Output = Natural; /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The first [`Natural`] is taken by reference and the second by value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNeg, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).mod_neg(Natural::from(5u32)), 0); /// assert_eq!((&Natural::from(7u32)).mod_neg(Natural::from(10u32)), 3); /// assert_eq!( /// (&Natural::from(7u32)).mod_neg(Natural::from(10u32).pow(12)), /// 999999999993u64 /// ); /// ``` fn mod_neg(self, m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); if *self == 0 { Natural::ZERO } else { m - self } } } impl ModNeg<&Natural> for &Natural { type Output = Natural; /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. Both [`Natural`]s are taken by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNeg, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).mod_neg(&Natural::from(5u32)), 0); /// assert_eq!((&Natural::from(7u32)).mod_neg(&Natural::from(10u32)), 3); /// assert_eq!( /// (&Natural::from(7u32)).mod_neg(&Natural::from(10u32).pow(12)), /// 999999999993u64 /// ); /// ``` fn mod_neg(self, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); if *self == 0 { Natural::ZERO } else { m - self } } } impl ModNegAssign for Natural { /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < m$ and $-x \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNegAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::ZERO; /// n.mod_neg_assign(Natural::from(5u32)); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(7u32); /// n.mod_neg_assign(Natural::from(10u32)); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(7u32); /// n.mod_neg_assign(Natural::from(10u32).pow(12)); /// assert_eq!(n, 999999999993u64); /// ``` #[inline] fn mod_neg_assign(&mut self, m: Self) { self.mod_neg_assign(&m); } } impl<'a> ModNegAssign<&'a Self> for Natural { /// Negates a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < m$ and $-x \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModNegAssign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::ZERO; /// n.mod_neg_assign(&Natural::from(5u32)); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(7u32); /// n.mod_neg_assign(&Natural::from(10u32)); /// assert_eq!(n, 3); /// /// let mut n = Natural::from(7u32); /// n.mod_neg_assign(&Natural::from(10u32).pow(12)); /// assert_eq!(n, 999999999993u64); /// ``` fn mod_neg_assign(&mut self, m: &'a Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); if *self != 0 { assert!(!self.sub_right_assign_no_panic(m)); } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_op.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_dcpi1_div_qr`, `mpn_dcpi1_div_qr_n`, `mpn_mu_div_qr`, `mpn_mu_div_qr2`, // `mpn_preinv_mu_div_qr`, and `mpn_sbpi1_div_qr` contributed to the GNU project by Torbjörn // Granlund. // // `mpn_mod_1s_2p_cps`, `mpn_mod_1s_2p`, `mpn_mod_1s_4p_cps`, and `mpn_mod_1s_4p` contributed // to the GNU project by Torbjörn Granlund. Based on a suggestion by Peter L. Montgomery. // // `mpn_div_qr_1` contributed to the GNU project by Niels Möller and Torbjörn Granlund. // // `mpn_div_qr_1n_pi1` contributed to the GNU project by Niels Möller. // // Copyright © 1991, 1993-1996, 1997, 1998-2002, 2003, 2005-2010, 2012, 2013, 2015 Free // Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div_mod::{ MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD, MUPI_DIV_QR_THRESHOLD, limbs_div_barrett_large_product, limbs_div_mod_balanced, limbs_div_mod_barrett_helper, limbs_div_mod_barrett_is_len, limbs_div_mod_barrett_scratch_len, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_divide_and_conquer_helper, limbs_div_mod_schoolbook, limbs_div_mod_three_limb_by_two_limb, limbs_invert_approx, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::mul::mul_mod::limbs_mul_mod_base_pow_n_minus_1_next_size; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shl::limbs_shl_to_out; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, limbs_sub_same_length_with_borrow_in_in_place_left, limbs_sub_same_length_with_borrow_in_in_place_right, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{ DC_DIV_QR_THRESHOLD, DoubleLimb, Limb, MOD_1_1_TO_MOD_1_2_THRESHOLD, MOD_1_1P_METHOD, MOD_1_2_TO_MOD_1_4_THRESHOLD, MOD_1_NORM_THRESHOLD, MOD_1_UNNORM_THRESHOLD, MOD_1N_TO_MOD_1_1_THRESHOLD, MOD_1U_TO_MOD_1_1_THRESHOLD, MU_DIV_QR_SKEW_THRESHOLD, MU_DIV_QR_THRESHOLD, }; use alloc::vec::Vec; use core::cmp::Ordering::*; use core::mem::swap; use core::ops::{Rem, RemAssign}; use malachite_base::num::arithmetic::traits::{ Mod, ModAssign, ModPowerOf2, NegMod, NegModAssign, Parity, WrappingAddAssign, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::{slice_move_left, slice_set_zero}; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_qrnnd_preinv` from `gmp-impl.h`, GMP 6.2.1, but not computing the // quotient. pub_test! {mod_by_preinversion< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( n_high: T, n_low: T, d: T, d_inv: T, ) -> T { let (q_high, q_low) = (DT::from(n_high) * DT::from(d_inv)) .wrapping_add(DT::join_halves(n_high.wrapping_add(T::ONE), n_low)) .split_in_half(); let mut r = n_low.wrapping_sub(q_high.wrapping_mul(d)); if r > q_low { r.wrapping_add_assign(d); } if r >= d { r -= d; } r }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // remainder when the `Natural` is divided by a `Limb`. // // The divisor limb cannot be zero and the input limb slice must have at least two elements. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if the length of `ns` is less than 2 or if `d` is zero. #[cfg(feature = "32_bit_limbs")] #[cfg(feature = "test_build")] #[inline] pub fn limbs_mod_limb< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { limbs_mod_limb_alt_2::(ns, d) } #[cfg(feature = "32_bit_limbs")] #[cfg(not(feature = "test_build"))] #[inline] pub(crate) fn limbs_mod_limb< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { limbs_mod_limb_alt_2::(ns, d) } #[cfg(not(feature = "32_bit_limbs"))] #[cfg(feature = "test_build")] #[inline] pub fn limbs_mod_limb< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[Limb], d: Limb, ) -> Limb { limbs_mod_limb_alt_1::(ns, d) } #[cfg(not(feature = "32_bit_limbs"))] #[cfg(not(feature = "test_build"))] pub(crate) fn limbs_mod_limb< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { limbs_mod_limb_alt_1::(ns, d) } // Computes the remainder of `[n_2, n_1, n_0]` / `[d_1, d_0]`. Requires the highest bit of `d_1` to // be set, and `[n_2, n_1]` < `[d_1, d_0]`. `d_inv` is the inverse of `[d_1, d_0]` computed by // `limbs_two_limb_inverse_helper`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_qr_3by2` from `gmp-impl.h`, GMP 6.2.1, returning only the remainder. pub_test! {limbs_mod_three_limb_by_two_limb( n_2: Limb, n_1: Limb, n_0: Limb, d_1: Limb, d_0: Limb, d_inv: Limb, ) -> DoubleLimb { let (q, q_lo) = (DoubleLimb::from(n_2) * DoubleLimb::from(d_inv)) .wrapping_add(DoubleLimb::join_halves(n_2, n_1)) .split_in_half(); let d = DoubleLimb::join_halves(d_1, d_0); // Compute the two most significant limbs of n - q * d let r = DoubleLimb::join_halves(n_1.wrapping_sub(d_1.wrapping_mul(q)), n_0) .wrapping_sub(d) .wrapping_sub(DoubleLimb::from(d_0) * DoubleLimb::from(q)); // Conditionally adjust the remainder if r.upper_half() >= q_lo { let (r_plus_d, overflow) = r.overflowing_add(d); if overflow { return r_plus_d; } } else if r >= d { return r.wrapping_sub(d); } r }} // Divides `ns` by `ds`, returning the limbs of the remainder. `ds` must have length 2, `ns` must // have length at least 2, and the most significant bit of `ds[1]` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // # Panics // Panics if `ds` does not have length 2, `ns` has length less than 2, `qs` has length less than // `ns.len() - 2`, or `ds[1]` does not have its highest bit set. // // This is equivalent to `mpn_divrem_2` from `mpn/generic/divrem_2.c`, GMP 6.2.1, returning the two // limbs of the remainder. pub_test! {limbs_mod_by_two_limb_normalized(ns: &[Limb], ds: &[Limb]) -> (Limb, Limb) { assert_eq!(ds.len(), 2); let n_len = ns.len(); assert!(n_len >= 2); let n_limit = n_len - 2; assert!(ds[1].get_highest_bit()); let d_1 = ds[1]; let d_0 = ds[0]; let d = DoubleLimb::join_halves(d_1, d_0); let mut r = DoubleLimb::join_halves(ns[n_limit + 1], ns[n_limit]); if r >= d { r.wrapping_sub_assign(d); } let (mut r_1, mut r_0) = r.split_in_half(); let d_inv = limbs_two_limb_inverse_helper(d_1, d_0); for &n in ns[..n_limit].iter().rev() { (r_1, r_0) = limbs_mod_three_limb_by_two_limb(r_1, r_0, n, d_1, d_0, d_inv).split_in_half(); } (r_0, r_1) }} // Divides `ns` by `ds` and writes the `ds.len()` limbs of the remainder to `ns`. `ds` must have // length greater than 2, `ns` must be at least as long as `ds`, and the most significant bit of // `ds` must be set. `d_inv` should be the result of `limbs_two_limb_inverse_helper` applied to the // two highest limbs of the denominator. // // # Worst-case complexity // $T(n, d) = O(d(n - d + 1)) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ns.len()`, and $d$ is `ds.len()`. // // # Panics // Panics if `ds` has length smaller than 3, `ns` is shorter than `ds`, or the last limb of `ds` // does not have its highest bit set. // // This is equivalent to `mpn_sbpi1_div_qr` from `mpn/generic/sbpi1_div_qr.c`, GMP 6.2.1, where only // the remainder is calculated. pub_test! {limbs_mod_schoolbook(ns: &mut [Limb], ds: &[Limb], d_inv: Limb) { let d_len = ds.len(); assert!(d_len > 2); let n_len = ns.len(); assert!(n_len >= d_len); let (d_1, ds_init) = ds.split_last().unwrap(); let d_1 = *d_1; assert!(d_1.get_highest_bit()); let (d_0, ds_init_init) = ds_init.split_last().unwrap(); let d_0 = *d_0; let ns_hi = &mut ns[n_len - d_len..]; if limbs_cmp_same_length(ns_hi, ds) >= Equal { limbs_sub_same_length_in_place_left(ns_hi, ds); } let mut n_1 = ns[n_len - 1]; for i in (d_len..n_len).rev() { let j = i - d_len; if n_1 == d_1 && ns[i - 1] == d_0 { limbs_sub_mul_limb_same_length_in_place_left(&mut ns[j..i], ds, Limb::MAX); n_1 = ns[i - 1]; // update n_1, last loop's value will now be invalid } else { let (ns_lo, ns_hi) = ns.split_at_mut(i - 2); let (q, n) = limbs_div_mod_three_limb_by_two_limb(n_1, ns_hi[1], ns_hi[0], d_1, d_0, d_inv); let mut n_0; (n_1, n_0) = n.split_in_half(); let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns_lo[j..], ds_init_init, q); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns_hi[0] = n_0; if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(&mut ns[j..i - 1], ds_init) { n_1.wrapping_add_assign(1); } } } } ns[d_len - 1] = n_1; }} // `qs` is just used as scratch space. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n(\log n)^2)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // This is equivalent to `mpn_dcpi1_div_qr_n` from `mpn/generic/dcpi1_div_qr.c`, GMP 6.2.1, where // only the remainder is calculated. fn limbs_mod_divide_and_conquer_helper( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb, scratch: &mut [Limb], ) { let n = ds.len(); let lo = n >> 1; // floor(n / 2) let hi = n - lo; // ceil(n / 2) let qs_hi = &mut qs[lo..]; let (ds_lo, ds_hi) = ds.split_at(lo); let highest_q = if hi < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs_hi, &mut ns[lo << 1..n << 1], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs_hi, &mut ns[lo << 1..], ds_hi, d_inv, scratch) }; let qs_hi = &mut qs_hi[..hi]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(qs_hi.len(), ds_lo.len())]; limbs_mul_greater_to_out(scratch, qs_hi, ds_lo, &mut mul_scratch); let ns_lo = &mut ns[..n + lo]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left( &mut ns_lo[lo..], &scratch[..n], )); if highest_q && limbs_sub_same_length_in_place_left(&mut ns_lo[n..], ds_lo) { carry += 1; } while carry != 0 { limbs_sub_limb_in_place(qs_hi, 1); if limbs_slice_add_same_length_in_place_left(&mut ns_lo[lo..], ds) { carry -= 1; } } let (ds_lo, ds_hi) = ds.split_at(hi); let q_lo = if lo < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, &mut ns[hi..n + lo], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs, &mut ns[hi..], ds_hi, d_inv, scratch) }; let qs_lo = &mut qs[..lo]; let ns_lo = &mut ns[..n]; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds_lo.len(), lo)]; limbs_mul_greater_to_out(scratch, ds_lo, qs_lo, &mut mul_scratch); let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns_lo, &scratch[..n])); if q_lo && limbs_sub_same_length_in_place_left(&mut ns_lo[lo..], ds_lo) { carry += 1; } while carry != 0 { if limbs_slice_add_same_length_in_place_left(ns_lo, ds) { carry -= 1; } } } // `qs` is just used as scratch space. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n(\log n)^2)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ds.len()`. // // # Panics // Panics if `ds` has length smaller than 6, `ns.len()` is less than `ds.len()` + 3, `qs` has length // less than `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_dcpi1_div_qr` from `mpn/generic/dcpi1_div_qr.c`, GMP 6.2.1, where only // the remainder is calculated. pub_test! {limbs_mod_divide_and_conquer( qs: &mut [Limb], ns: &mut [Limb], ds: &[Limb], d_inv: Limb ) { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len >= 6); // to adhere to limbs_div_mod_schoolbook's limits assert!(n_len >= d_len + 3); // to adhere to limbs_div_mod_schoolbook's limits let a = d_len - 1; let d_1 = ds[a]; let b = d_len - 2; assert!(d_1.get_highest_bit()); let mut scratch = vec![0; d_len]; let q_len = n_len - d_len; if q_len > d_len { let q_len_mod_d_len = { let mut m = q_len % d_len; if m == 0 { m = d_len; } m }; // Perform the typically smaller block first. point at low limb of next quotient block let qs_block = &mut qs[q_len - q_len_mod_d_len..q_len]; if q_len_mod_d_len == 1 { // Handle highest_q up front, for simplicity. let ns = &mut ns[q_len - 1..]; let ns_tail = &mut ns[1..]; if limbs_cmp_same_length(ns_tail, ds) >= Equal { assert!(!limbs_sub_same_length_in_place_left(ns_tail, ds)); } // A single iteration of schoolbook: One 3/2 division, followed by the bignum update and // adjustment. let (last_n, ns) = ns.split_last_mut().unwrap(); let n_2 = *last_n; let mut n_1 = ns[a]; let mut n_0 = ns[b]; let d_0 = ds[b]; assert!(n_2 < d_1 || n_2 == d_1 && n_1 <= d_0); let mut q; if n_2 == d_1 && n_1 == d_0 { q = Limb::MAX; assert_eq!(limbs_sub_mul_limb_same_length_in_place_left(ns, ds, q), n_2); } else { let n; (q, n) = limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, d_inv); (n_1, n_0) = n.split_in_half(); // d_len > 2 because of precondition. No need to check let local_carry_1 = limbs_sub_mul_limb_same_length_in_place_left(&mut ns[..b], &ds[..b], q); let local_carry_2 = n_0 < local_carry_1; n_0.wrapping_sub_assign(local_carry_1); let carry = local_carry_2 && n_1 == 0; if local_carry_2 { n_1.wrapping_sub_assign(1); } ns[b] = n_0; let (ns_last, ns_init) = ns.split_last_mut().unwrap(); if carry { n_1.wrapping_add_assign(d_1); if limbs_slice_add_same_length_in_place_left(ns_init, &ds[..a]) { n_1.wrapping_add_assign(1); } q.wrapping_sub_assign(1); } *ns_last = n_1; } qs_block[0] = q; } else { // Do a 2 * q_len_mod_d_len / q_len_mod_d_len division let (ds_lo, ds_hi) = ds.split_at(d_len - q_len_mod_d_len); let highest_q = { let ns = &mut ns[n_len - (q_len_mod_d_len << 1)..]; if q_len_mod_d_len == 2 { limbs_div_mod_by_two_limb_normalized(qs_block, ns, ds_hi) } else if q_len_mod_d_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs_block, ns, ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper( qs_block, ns, ds_hi, d_inv, &mut scratch, ) } }; if q_len_mod_d_len != d_len { let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(qs_block.len(), ds_lo.len())]; limbs_mul_to_out(&mut scratch, qs_block, ds_lo, &mut mul_scratch); let ns = &mut ns[q_len - q_len_mod_d_len..n_len - q_len_mod_d_len]; let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns, &scratch)); if highest_q && limbs_sub_same_length_in_place_left(&mut ns[q_len_mod_d_len..], ds_lo) { carry += 1; } while carry != 0 { limbs_sub_limb_in_place(qs_block, 1); if limbs_slice_add_same_length_in_place_left(ns, ds) { carry -= 1; } } } } // offset is a multiple of d_len let mut offset = n_len.checked_sub(d_len + q_len_mod_d_len).unwrap(); while offset != 0 { offset -= d_len; limbs_mod_divide_and_conquer_helper( &mut qs[offset..], &mut ns[offset..], ds, d_inv, &mut scratch, ); } } else { let m = d_len - q_len; let (ds_lo, ds_hi) = ds.split_at(m); let highest_q = if q_len < DC_DIV_QR_THRESHOLD { limbs_div_mod_schoolbook(qs, &mut ns[m..], ds_hi, d_inv) } else { limbs_div_mod_divide_and_conquer_helper(qs, &mut ns[m..], ds_hi, d_inv, &mut scratch) }; if m != 0 { let qs = &mut qs[..q_len]; let ns = &mut ns[..d_len]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(q_len, ds_lo.len())]; limbs_mul_to_out(&mut scratch, qs, ds_lo, &mut mul_scratch); let mut carry = Limb::from(limbs_sub_same_length_in_place_left(ns, &scratch)); if highest_q && limbs_sub_same_length_in_place_left(&mut ns[q_len..], ds_lo) { carry += 1; } while carry != 0 { if limbs_slice_add_same_length_in_place_left(ns, ds) { carry -= 1; } } } } }} // `qs` is just used as scratch space. // // # Worst-case complexity // $T(n, d) = O(n \log d \log\log d)$ // // $M(n) = O(d(\log d)^2)$ // // where $T$ is time, $M$ is additional memory, n$ is `ns.len()`, and $d$ is `ds.len()`. // // This is equivalent to `mpn_preinv_mu_div_qr` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1, where // only the remainder is calculated. fn limbs_mod_barrett_preinverted( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], mut is: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); let d_len = ds.len(); assert_eq!(rs.len(), d_len); let mut i_len = is.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; let (ns_lo, ns_hi) = ns.split_at(q_len); if limbs_cmp_same_length(ns_hi, ds) >= Equal { limbs_sub_same_length_to_out(rs, ns_hi, ds); } else { rs.copy_from_slice(ns_hi); } let scratch_len = if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { 0 } else { limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1) }; let mut n = d_len - i_len; for (ns, qs) in ns_lo.rchunks(i_len).zip(qs.rchunks_mut(i_len)) { let chunk_len = ns.len(); if i_len != chunk_len { // last iteration is = &is[i_len - chunk_len..]; i_len = chunk_len; n = d_len - i_len; } let (rs_lo, rs_hi) = rs.split_at_mut(n); // Compute the next block of quotient limbs by multiplying the inverse by the upper part of // the partial remainder. let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(is.len())]; limbs_mul_same_length_to_out(scratch, rs_hi, is, &mut mul_scratch); // The inverse's most significant bit is implicit. assert!(!limbs_add_same_length_to_out( qs, &scratch[i_len..i_len << 1], rs_hi, )); // Compute the product of the quotient block and the divisor, to be subtracted from the // partial remainder combined with new limbs from the dividend. We only really need the low // d_len + 1 limbs. if i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ds.len(), qs.len())]; limbs_mul_greater_to_out(scratch, ds, qs, &mut mul_scratch); } else { limbs_div_barrett_large_product(scratch, ds, qs, rs_hi, scratch_len, i_len); } let mut r = rs_hi[0].wrapping_sub(scratch[d_len]); // Subtract the product from the partial remainder combined with new limbs from the // dividend, generating a new partial remainder. let scratch = &mut scratch[..d_len]; let carry = if n == 0 { // Get next i_len limbs from n. limbs_sub_same_length_to_out(rs, ns, scratch) } else { let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); // Get next i_len limbs from n. let carry = limbs_sub_same_length_with_borrow_in_in_place_right( rs_lo, scratch_hi, limbs_sub_same_length_in_place_right(ns, scratch_lo), ); rs.copy_from_slice(scratch); carry }; // Check the remainder. if carry { r.wrapping_sub_assign(1); } while r != 0 { // We loop 0 times with about 69% probability, 1 time with about 31% probability, and 2 // times with about 0.6% probability, if the inverse is computed as recommended. if limbs_sub_same_length_in_place_left(rs, ds) { r -= 1; } } if limbs_cmp_same_length(rs, ds) >= Equal { // This is executed with about 76% probability. limbs_sub_same_length_in_place_left(rs, ds); } } } // `qs` is just used as scratch space. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. // // This is equivalent to `mpn_mu_div_qr2` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1, where only the // remainder is calculated. pub_test! {limbs_mod_barrett_helper( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); let d_len = ds.len(); assert_eq!(rs.len(), d_len); assert!(d_len > 1); assert!(n_len > d_len); let q_len = n_len - d_len; // Compute the inverse size. let i_len = limbs_div_mod_barrett_is_len(q_len, d_len); assert!(i_len <= d_len); let i_len_plus_1 = i_len + 1; let (is, scratch_hi) = scratch.split_at_mut(i_len_plus_1); // compute an approximate inverse on i_len + 1 limbs if d_len == i_len { let (scratch_lo, scratch_hi) = scratch_hi.split_at_mut(i_len_plus_1); let (scratch_first, scratch_lo_tail) = scratch_lo.split_first_mut().unwrap(); scratch_lo_tail.copy_from_slice(&ds[..i_len]); *scratch_first = 1; limbs_invert_approx(is, scratch_lo, scratch_hi); slice_move_left(is, 1); } else if limbs_add_limb_to_out(scratch_hi, &ds[d_len - i_len_plus_1..], 1) { slice_set_zero(&mut is[..i_len]); } else { let (scratch_lo, scratch_hi) = scratch_hi.split_at_mut(i_len_plus_1); limbs_invert_approx(is, scratch_lo, scratch_hi); slice_move_left(is, 1); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(i_len); limbs_mod_barrett_preinverted(qs, rs, ns, ds, scratch_lo, scratch_hi); }} // `qs` is just used as scratch space. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. fn limbs_mod_barrett_large_helper( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); let d_len = ds.len(); let q_len = qs.len(); let q_len_plus_one = q_len + 1; let n = n_len - q_len - q_len_plus_one; // 2 * d_len - n_len - 1 let (ns_lo, ns_hi) = ns.split_at(n); let (ds_lo, ds_hi) = ds.split_at(d_len - q_len_plus_one); let (rs_lo, rs_hi) = rs.split_at_mut(n); let rs_hi = &mut rs_hi[..q_len_plus_one]; let highest_q = limbs_div_mod_barrett_helper(qs, rs_hi, ns_hi, ds_hi, scratch); // Multiply the quotient by the divisor limbs ignored above. The product is d_len - 1 limbs // long. let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ds_lo.len(), qs.len())]; limbs_mul_to_out(scratch, ds_lo, qs, &mut mul_scratch); let (scratch_last, scratch_init) = scratch[..d_len].split_last_mut().unwrap(); *scratch_last = Limb::from( highest_q && limbs_slice_add_same_length_in_place_left(&mut scratch_init[q_len..], ds_lo), ); let (scratch_lo, scratch_hi) = scratch.split_at(n); let scratch_hi = &scratch_hi[..q_len_plus_one]; if limbs_sub_same_length_with_borrow_in_in_place_left( rs_hi, scratch_hi, limbs_sub_same_length_to_out(rs_lo, ns_lo, scratch_lo), ) { limbs_slice_add_same_length_in_place_left(&mut rs[..d_len], ds); } } // `qs` is just used as scratch space. // // `ns` must have length at least 3, `ds` must have length at least 2 and be no longer than `ns`, // and the most significant bit of `ds` must be set. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. // // # Panics // Panics if `ds` has length smaller than 2, `ns.len()` is less than `ds.len()`, `qs` has length // less than `ns.len()` - `ds.len()`, or the last limb of `ds` does not have its highest bit set. // // This is equivalent to `mpn_mu_div_qr` from `mpn/generic/mu_div_qr.c`, GMP 6.2.1. pub_test! {limbs_mod_barrett( qs: &mut [Limb], rs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb], ) { let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len; let qs = &mut qs[..q_len]; // Test whether 2 * d_len - n_len > MU_DIV_QR_SKEW_THRESHOLD if d_len <= q_len + MU_DIV_QR_SKEW_THRESHOLD { limbs_mod_barrett_helper(qs, &mut rs[..d_len], ns, ds, scratch); } else { limbs_mod_barrett_large_helper(qs, rs, ns, ds, scratch); } }} /// `ds` must have length 2, `ns` must have length at least 2, and the most-significant limb of `ds` /// must be nonzero. /// // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. fn limbs_mod_by_two_limb(ns: &[Limb], ds: &[Limb]) -> (Limb, Limb) { let n_len = ns.len(); let ds_1 = ds[1]; let bits = LeadingZeros::leading_zeros(ds_1); if bits == 0 { limbs_mod_by_two_limb_normalized(ns, ds) } else { let ds_0 = ds[0]; let cobits = Limb::WIDTH - bits; let mut ns_shifted = vec![0; n_len + 1]; let ns_shifted = &mut ns_shifted; let carry = limbs_shl_to_out(ns_shifted, ns, bits); let ds_shifted = &mut [ds_0 << bits, (ds_1 << bits) | (ds_0 >> cobits)]; let (r_0, r_1) = if carry == 0 { limbs_mod_by_two_limb_normalized(&ns_shifted[..n_len], ds_shifted) } else { ns_shifted[n_len] = carry; limbs_mod_by_two_limb_normalized(ns_shifted, ds_shifted) }; ((r_0 >> bits) | (r_1 << cobits), r_1 >> bits) } } // # Worst-case complexity // Constant time and additional memory. fn limbs_mod_dc_condition(n_len: usize, d_len: usize) -> bool { let n_64 = n_len as f64; let d_64 = d_len as f64; d_len < MUPI_DIV_QR_THRESHOLD || n_len < MU_DIV_QR_THRESHOLD << 1 || fma!( ((MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD) << 1) as f64, d_64, MUPI_DIV_QR_THRESHOLD as f64 * n_64 ) > d_64 * n_64 } // This function is optimized for the case when the numerator has at least twice the length of the // denominator. // // `ds` must have length at least 3, `ns` must be at least as long as `ds`, `rs` must have the same // length as `ds`, and the most-significant limb of `ds` must be nonzero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. fn limbs_mod_unbalanced(rs: &mut [Limb], ns: &[Limb], ds: &[Limb], adjusted_n_len: usize) { let mut n_len = ns.len(); let d_len = ds.len(); let mut ds_shifted_vec; let ds_shifted: &[Limb]; let mut ns_shifted_vec = vec![0; n_len + 1]; let ns_shifted = &mut ns_shifted_vec; let bits = LeadingZeros::leading_zeros(*ds.last().unwrap()); if bits == 0 { ds_shifted = ds; ns_shifted[..n_len].copy_from_slice(ns); } else { // normalize divisor ds_shifted_vec = vec![0; d_len]; limbs_shl_to_out(&mut ds_shifted_vec, ds, bits); ds_shifted = &ds_shifted_vec; let (ns_shifted_last, ns_shifted_init) = ns_shifted.split_last_mut().unwrap(); *ns_shifted_last = limbs_shl_to_out(ns_shifted_init, ns, bits); } n_len = adjusted_n_len; let d_inv = limbs_two_limb_inverse_helper(ds_shifted[d_len - 1], ds_shifted[d_len - 2]); let ns_shifted = &mut ns_shifted[..n_len]; if d_len < DC_DIV_QR_THRESHOLD { limbs_mod_schoolbook(ns_shifted, ds_shifted, d_inv); let ns_shifted = &ns_shifted[..d_len]; if bits == 0 { rs.copy_from_slice(ns_shifted); } else { limbs_shr_to_out(rs, ns_shifted, bits); } } else if limbs_mod_dc_condition(n_len, d_len) { let mut qs = vec![0; n_len - d_len]; limbs_mod_divide_and_conquer(&mut qs, ns_shifted, ds_shifted, d_inv); let ns_shifted = &ns_shifted[..d_len]; if bits == 0 { rs.copy_from_slice(ns_shifted); } else { limbs_shr_to_out(rs, ns_shifted, bits); } } else { let scratch_len = limbs_div_mod_barrett_scratch_len(n_len, d_len); let mut qs = vec![0; n_len - d_len]; let mut scratch = vec![0; scratch_len]; limbs_mod_barrett(&mut qs, rs, ns_shifted, ds_shifted, &mut scratch); if bits != 0 { limbs_slice_shr_in_place(rs, bits); } } } // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, returning the remainder. The remainder has `ds.len()` limbs. // // `ns` must be at least as long as `ds` and `ds` must have length at least 2 and its most // significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. // // # Panics // Panics if `ns` is shorter than `ds`, `ds` has length less than 2, or the most-significant limb of // `ds` is zero. // // This is equivalent to `mpn_tdiv_qr` from `mpn/generic/tdiv_qr.c`, GMP 6.2.1, where `qp` is not // calculated and `rp` is returned. pub_test! {limbs_mod(ns: &[Limb], ds: &[Limb]) -> Vec { let mut rs = vec![0; ds.len()]; limbs_mod_to_out(&mut rs, ns, ds); rs }} // Interpreting two slices of `Limb`s, `ns` and `ds`, as the limbs (in ascending order) of two // `Natural`s, divides them, writing the `ds.len()` limbs of the remainder to `rs`. // // `ns` must be at least as long as `ds`, `rs` must be at least as long as `ds`, and `ds` must have // length at least 2 and its most significant limb must be greater than zero. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and n$ is `ns.len()`. // // # Panics // Panics if `rs` is too short, `ns` is shorter than `ds`, `ds` has length less than 2, or the // most-significant limb of `ds` is zero. // // This is equivalent to `mpn_tdiv_qr` from `mpn/generic/tdiv_qr.c`, GMP 6.2.1, where `qp` is not // calculated. pub_crate_test! {limbs_mod_to_out(rs: &mut [Limb], ns: &[Limb], ds: &[Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(n_len >= d_len); let rs = &mut rs[..d_len]; let ds_last = *ds.last().unwrap(); assert!(d_len > 1 && ds_last != 0); if d_len == 2 { (rs[0], rs[1]) = limbs_mod_by_two_limb(ns, ds); } else { // conservative tests for quotient size let adjust = ns[n_len - 1] >= ds_last; let adjusted_n_len = if adjust { n_len + 1 } else { n_len }; if adjusted_n_len < d_len << 1 { let mut qs = vec![0; n_len - d_len + 1]; limbs_div_mod_balanced(&mut qs, rs, ns, ds, adjust); } else { limbs_mod_unbalanced(rs, ns, ds, adjusted_n_len); } } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. #[cfg(feature = "test_build")] fn limbs_rem_naive(ns: &[Limb], d: Limb) -> Limb { let d = DoubleLimb::from(d); let mut r = 0; for &n in ns.iter().rev() { r = (DoubleLimb::join_halves(r, n) % d).lower_half(); } r } // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`, but not computing the quotient. pub fn limbs_mod_limb_normalized< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[T], ns_high: T, d: T, d_inv: T, ) -> T { let len = ns.len(); if len == 1 { return mod_by_preinversion::(ns_high, ns[0], d, d_inv); } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let (sum, mut big_carry) = DT::join_halves(ns[len - 1], ns[len - 2]) .overflowing_add(DT::from(power_of_2) * DT::from(ns_high)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for &n in ns[..len - 2].iter().rev() { if big_carry && sum_low.overflowing_add_assign(power_of_2) { sum_low.wrapping_sub_assign(d); } let sum; (sum, big_carry) = DT::join_halves(sum_low, n).overflowing_add(DT::from(sum_high) * DT::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); } if big_carry { sum_high.wrapping_sub_assign(d); } if sum_high >= d { sum_high.wrapping_sub_assign(d); } mod_by_preinversion::(sum_high, sum_low, d, d_inv) } // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`, but not computing the quotient, and where the input is left-shifted by // `bits`. pub_test! {limbs_mod_limb_normalized_shl< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >( ns: &[T], ns_high: T, d: T, d_inv: T, bits: u64, ) -> T { let len = ns.len(); if len == 1 { return mod_by_preinversion::(ns_high, ns[0] << bits, d, d_inv); } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let cobits = T::WIDTH - bits; let second_highest = ns[len - 2]; let highest_after_shl = (ns[len - 1] << bits) | (second_highest >> cobits); let mut second_highest_after_shl = second_highest << bits; if len > 2 { second_highest_after_shl |= ns[len - 3] >> cobits; } let (sum, mut big_carry) = DT::join_halves(highest_after_shl, second_highest_after_shl) .overflowing_add(DT::from(power_of_2) * DT::from(ns_high)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for j in (0..len - 2).rev() { if big_carry && sum_low.overflowing_add_assign(power_of_2) { sum_low.wrapping_sub_assign(d); } let mut n = ns[j] << bits; if j != 0 { n |= ns[j - 1] >> cobits; } let sum; (sum, big_carry) = DT::join_halves(sum_low, n).overflowing_add(DT::from(sum_high) * DT::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); } if big_carry { sum_high.wrapping_sub_assign(d); } if sum_high >= d { sum_high.wrapping_sub_assign(d); } mod_by_preinversion::(sum_high, sum_low, d, d_inv) }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, where the quotient // is not computed and the remainder is returned. Experiments show that this is always slower than // `limbs_mod_limb`. pub_test! {limbs_mod_limb_alt_1< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf + JoinHalves, T: PrimitiveUnsigned, >(ns: &[T], d: T) -> T { assert_ne!(d, T::ZERO); let len = ns.len(); assert!(len > 1); let len_minus_1 = len - 1; let mut ns_high = ns[len_minus_1]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { if ns_high >= d { ns_high -= d; } let d_inv = limbs_invert_limb::(d); limbs_mod_limb_normalized::(&ns[..len_minus_1], ns_high, d, d_inv) } else { let d = d << bits; let cobits = T::WIDTH - bits; let d_inv = limbs_invert_limb::(d); let r = mod_by_preinversion::( ns_high >> cobits, (ns_high << bits) | (ns[len - 2] >> cobits), d, d_inv, ); limbs_mod_limb_normalized_shl::(&ns[..len_minus_1], r, d, d_inv, bits) >> bits } }} // Dividing (`n_high`, `n_low`) by `d`, returning the remainder only. Unlike `mod_by_preinversion`, // works also for the case `n_high` == `d`, where the quotient doesn't quite fit in a single limb. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `udiv_rnnd_preinv` from `gmp-impl.h`, GMP 6.2.1. fn mod_by_preinversion_special< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( n_high: T, n_low: T, d: T, d_inv: T, ) -> T { let (q_high, q_low) = ((DT::from(n_high) * DT::from(d_inv)) .wrapping_add(DT::join_halves(n_high.wrapping_add(T::ONE), n_low))) .split_in_half(); let mut r = n_low.wrapping_sub(q_high.wrapping_mul(d)); // both > and >= are OK if r > q_low { r.wrapping_add_assign(d); } if r >= d { r.wrapping_sub_assign(d); } r } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_test! {limbs_mod_limb_small_small< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >(ns: &[T], d: T, mut r: T) -> T { let d = DT::from(d); for &n in ns.iter().rev() { r = (DT::join_halves(r, n) % d).lower_half(); } r }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_test! {limbs_mod_limb_small_normalized_large< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, mut r: T, ) -> T { let d_inv = limbs_invert_limb::(d); for &n in ns.iter().rev() { r = mod_by_preinversion_special::(r, n, d, d_inv); } r }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1_norm` from `mpn/generic/mod_1.c`, GMP 6.2.1. pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_mod_limb_small_normalized< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let mut len = ns.len(); assert_ne!(len, 0); assert!(d.get_highest_bit()); // High limb is initial remainder, possibly with one subtraction of d to get r < d. let mut r = ns[len - 1]; if r >= d { r -= d; } len -= 1; if len == 0 { r } else { let ns = &ns[..len]; if len < MOD_1_NORM_THRESHOLD { limbs_mod_limb_small_small::(ns, d, r) } else { limbs_mod_limb_small_normalized_large::(ns, d, r) } } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_test! {limbs_mod_limb_small_unnormalized_large< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], mut d: T, mut r: T, ) -> T { let shift = LeadingZeros::leading_zeros(d); d <<= shift; let (ns_last, ns_init) = ns.split_last().unwrap(); let mut previous_n = *ns_last; let co_shift = T::WIDTH - shift; r = (r << shift) | (previous_n >> co_shift); let d_inv = limbs_invert_limb::(d); for &n in ns_init.iter().rev() { let shifted_n = (previous_n << shift) | (n >> co_shift); r = mod_by_preinversion_special::(r, shifted_n, d, d_inv); previous_n = n; } mod_by_preinversion_special::(r, previous_n << shift, d, d_inv) >> shift }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1_unnorm` from `mpn/generic/mod_1.c`, GMP 6.2.1, where // `UDIV_NEEDS_NORMALIZATION` is `false`. pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_mod_limb_small_unnormalized< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >(ns: &[T], d: T) -> T { let mut len = ns.len(); assert_ne!(len, 0); assert_ne!(d, T::ZERO); assert!(!d.get_highest_bit()); // Skip a division if high < divisor. Having the test here before normalizing will still skip as // often as possible. let mut r = ns[len - 1]; if r < d { len -= 1; if len == 0 { return r; } } else { r = T::ZERO; } let ns = &ns[..len]; if len < MOD_1_UNNORM_THRESHOLD { limbs_mod_limb_small_small::(ns, d, r) } else { limbs_mod_limb_small_unnormalized_large::(ns, d, r) } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. pub_test! {limbs_mod_limb_any_leading_zeros< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { if MOD_1_1P_METHOD { limbs_mod_limb_any_leading_zeros_1::(ns, d) } else { limbs_mod_limb_any_leading_zeros_2::(ns, d) } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1_1p_cps_1` combined with `mpn_mod_1_1p_1` from // `mpn/generic/mod_1.c`, GMP 6.2.1. pub_test! {limbs_mod_limb_any_leading_zeros_1< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let len = ns.len(); assert!(len >= 2); let shift = d.leading_zeros(); let d = d << shift; let d_inv = limbs_invert_limb::(d); let mut base_mod_d = d.wrapping_neg(); if shift != 0 { base_mod_d.wrapping_mul_assign((d_inv >> (T::WIDTH - shift)) | T::power_of_2(shift)); } assert!(base_mod_d <= d); // not fully reduced mod divisor let base_pow_2_mod_d = DT::from(mod_by_preinversion_special::(base_mod_d, T::ZERO, d, d_inv) >> shift); let base_mod_d = DT::from(base_mod_d >> shift); let (mut r_hi, mut r_lo) = (DT::from(ns[len - 1]) * base_mod_d) .wrapping_add(DT::from(ns[len - 2])) .split_in_half(); for &n in ns[..len - 2].iter().rev() { (r_hi, r_lo) = (DT::from(r_hi) * base_pow_2_mod_d) .wrapping_add(DT::from(r_lo) * base_mod_d) .wrapping_add(DT::from(n)) .split_in_half(); } if shift != 0 { r_hi = (r_hi << shift) | (r_lo >> (T::WIDTH - shift)); } if r_hi >= d { r_hi.wrapping_sub_assign(d); } mod_by_preinversion_special::(r_hi, r_lo << shift, d, d_inv) >> shift }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1_1p_cps_2` combined with `mpn_mod_1_1p_2` from // `mpn/generic/mod_1.c`, GMP 6.2.1. pub_test! {limbs_mod_limb_any_leading_zeros_2< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let len = ns.len(); assert!(len >= 2); let shift = LeadingZeros::leading_zeros(d); let d = d << shift; let d_inv = limbs_invert_limb::(d); let base_mod_d = if shift == 0 { DT::ZERO } else { let base_mod_d = d .wrapping_neg() .wrapping_mul((d_inv >> (T::WIDTH - shift)) | T::power_of_2(shift)); assert!(base_mod_d <= d); // not fully reduced mod divisor DT::from(base_mod_d >> shift) }; let small_base_pow_2_mod_d = d.wrapping_neg().wrapping_mul(d_inv); // equality iff divisor = 2 ^ (Limb::WIDTH - 1) assert!(small_base_pow_2_mod_d <= d); let base_pow_2_mod_d = DT::from(small_base_pow_2_mod_d); let mut r_lo = ns[len - 2]; let mut r_hi = ns[len - 1]; if len > 2 { let (r, mut carry) = DT::join_halves(r_lo, ns[len - 3]).overflowing_add(DT::from(r_hi) * base_pow_2_mod_d); (r_hi, r_lo) = r.split_in_half(); for &n in ns[..len - 3].iter().rev() { if carry && r_lo.overflowing_add_assign(small_base_pow_2_mod_d) { r_lo.wrapping_sub_assign(d); } let r; (r, carry) = DT::join_halves(r_lo, n).overflowing_add(DT::from(r_hi) * base_pow_2_mod_d); (r_hi, r_lo) = r.split_in_half(); } if carry { r_hi.wrapping_sub_assign(d); } } if shift != 0 { let (new_r_hi, t) = (DT::from(r_hi) * base_mod_d).split_in_half(); (r_hi, r_lo) = (DT::join_halves(new_r_hi, r_lo).wrapping_add(DT::from(t)) << shift).split_in_half(); } else if r_hi >= d { // might get r_hi == divisor here, but `mod_by_preinversion_special` allows that. r_hi.wrapping_sub_assign(d); } mod_by_preinversion_special::(r_hi, r_lo, d, d_inv) >> shift }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1s_2p_cps` combined with `mpn_mod_1s_2p` from // `mpn/generic/mod_1_2.c`, GMP 6.2.1. pub_test! {limbs_mod_limb_at_least_1_leading_zero< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let mut len = ns.len(); assert_ne!(len, 0); let shift = LeadingZeros::leading_zeros(d); assert_ne!(shift, 0); let co_shift = T::WIDTH - shift; let d = d << shift; let d_inv = limbs_invert_limb::(d); let base_mod_d = d .wrapping_neg() .wrapping_mul((d_inv >> co_shift) | T::power_of_2(shift)); assert!(base_mod_d <= d); // not fully reduced mod divisor let base_pow_2_mod_d = mod_by_preinversion_special::(base_mod_d, T::ZERO, d, d_inv); let base_mod_d = DT::from(base_mod_d >> shift); let base_pow_3_mod_d = DT::from( mod_by_preinversion_special::(base_pow_2_mod_d, T::ZERO, d, d_inv) >> shift, ); let base_pow_2_mod_d = DT::from(base_pow_2_mod_d >> shift); let (mut r_hi, mut r_lo) = if len.odd() { len -= 1; if len == 0 { let rl = ns[len]; return mod_by_preinversion_special::(rl >> co_shift, rl << shift, d, d_inv) >> shift; } (DT::from(ns[len]) * base_pow_2_mod_d) .wrapping_add(DT::from(ns[len - 1]) * base_mod_d) .wrapping_add(DT::from(ns[len - 2])) .split_in_half() } else { (ns[len - 1], ns[len - 2]) }; for chunk in ns[..len - 2].rchunks_exact(2) { (r_hi, r_lo) = (DT::from(r_hi) * base_pow_3_mod_d) .wrapping_add(DT::from(r_lo) * base_pow_2_mod_d) .wrapping_add(DT::from(chunk[1]) * base_mod_d) .wrapping_add(DT::from(chunk[0])) .split_in_half(); } let (r_hi, r_lo) = (DT::from(r_hi) * base_mod_d) .wrapping_add(DT::from(r_lo)) .split_in_half(); mod_by_preinversion_special::( (r_hi << shift) | (r_lo >> co_shift), r_lo << shift, d, d_inv, ) >> shift }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1s_4p_cps` combined with `mpn_mod_1s_4p` from // `mpn/generic/mod_1_4.c`, GMP 6.2.1. pub_test! {limbs_mod_limb_at_least_2_leading_zeros< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let mut len = ns.len(); assert_ne!(len, 0); let shift = LeadingZeros::leading_zeros(d); assert!(shift >= 2); let co_shift = T::WIDTH - shift; let d = d << shift; let d_inv = limbs_invert_limb::(d); let base_mod_d = d .wrapping_neg() .wrapping_mul((d_inv >> co_shift) | T::power_of_2(shift)); assert!(base_mod_d <= d); // not fully reduced mod divisor let base_pow_2_mod_d = mod_by_preinversion_special::(base_mod_d, T::ZERO, d, d_inv); let base_mod_d = DT::from(base_mod_d >> shift); let base_pow_3_mod_d = mod_by_preinversion_special::(base_pow_2_mod_d, T::ZERO, d, d_inv); let base_pow_2_mod_d = DT::from(base_pow_2_mod_d >> shift); let base_pow_4_mod_d = mod_by_preinversion_special::(base_pow_3_mod_d, T::ZERO, d, d_inv); let base_pow_3_mod_d = DT::from(base_pow_3_mod_d >> shift); let base_pow_5_mod_d = DT::from( mod_by_preinversion_special::(base_pow_4_mod_d, T::ZERO, d, d_inv) >> shift, ); let base_pow_4_mod_d = DT::from(base_pow_4_mod_d >> shift); let (mut r_hi, mut r_lo) = match len.mod_power_of_2(2) { 0 => { len -= 4; (DT::from(ns[len + 3]) * base_pow_3_mod_d) .wrapping_add(DT::from(ns[len + 2]) * base_pow_2_mod_d) .wrapping_add(DT::from(ns[len + 1]) * base_mod_d) .wrapping_add(DT::from(ns[len])) .split_in_half() } 1 => { len -= 1; (T::ZERO, ns[len]) } 2 => { len -= 2; (ns[len + 1], ns[len]) } 3 => { len -= 3; (DT::from(ns[len + 2]) * base_pow_2_mod_d) .wrapping_add(DT::from(ns[len + 1]) * base_mod_d) .wrapping_add(DT::from(ns[len])) .split_in_half() } _ => unreachable!(), }; for chunk in ns[..len].rchunks_exact(4) { (r_hi, r_lo) = (DT::from(r_hi) * base_pow_5_mod_d) .wrapping_add(DT::from(r_lo) * base_pow_4_mod_d) .wrapping_add(DT::from(chunk[3]) * base_pow_3_mod_d) .wrapping_add(DT::from(chunk[2]) * base_pow_2_mod_d) .wrapping_add(DT::from(chunk[1]) * base_mod_d) .wrapping_add(DT::from(chunk[0])) .split_in_half(); } let (r_hi, r_lo) = (DT::from(r_hi) * base_mod_d) .wrapping_add(DT::from(r_lo)) .split_in_half(); mod_by_preinversion_special::( (r_hi << shift) | (r_lo >> co_shift), r_lo << shift, d, d_inv, ) >> shift }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_mod_1` from `mpn/generic/mod_1.c`, GMP 6.2.1, where `n > 1`. pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_mod_limb_alt_2< DT: From + HasHalf + PrimitiveUnsigned + JoinHalves + SplitInHalf, T: PrimitiveUnsigned, >( ns: &[T], d: T, ) -> T { let len = ns.len(); assert!(len > 1); assert_ne!(d, T::ZERO); if d.get_highest_bit() { if len < MOD_1N_TO_MOD_1_1_THRESHOLD { limbs_mod_limb_small_normalized::(ns, d) } else { limbs_mod_limb_any_leading_zeros::(ns, d) } } else if len < MOD_1U_TO_MOD_1_1_THRESHOLD { limbs_mod_limb_small_unnormalized::(ns, d) } else if len < MOD_1_1_TO_MOD_1_2_THRESHOLD { limbs_mod_limb_any_leading_zeros::(ns, d) } else if len < MOD_1_2_TO_MOD_1_4_THRESHOLD || d & !(T::MAX >> 2u32) != T::ZERO { limbs_mod_limb_at_least_1_leading_zero::(ns, d) } else { limbs_mod_limb_at_least_2_leading_zeros::(ns, d) } }} impl Natural { #[cfg(feature = "test_build")] pub fn mod_limb_naive(&self, other: Limb) -> Limb { match (self, other) { (_, 0) => panic!("division by zero"), (Self(Small(small)), other) => small % other, (Self(Large(limbs)), other) => limbs_rem_naive(limbs, other), } } fn rem_limb_ref(&self, other: Limb) -> Limb { match (self, other) { (_, 0) => panic!("division by zero"), (Self(Small(small)), other) => small % other, (Self(Large(limbs)), other) => limbs_mod_limb::(limbs, other), } } fn rem_assign_limb(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => panic!("division by zero"), (Self(Small(small)), other) => *small %= other, (Self(Large(limbs)), other) => { *self = Self(Small(limbs_mod_limb::(limbs, other))); } } } } impl Mod for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and returning just the /// remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32).mod_op(Natural::from(10u32)), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .mod_op(Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// ``` #[inline] fn mod_op(self, other: Self) -> Self { self % other } } impl<'a> Mod<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32).mod_op(&Natural::from(10u32)), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .mod_op(&Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// ``` #[inline] fn mod_op(self, other: &'a Self) -> Self { self % other } } impl Mod for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Natural::from(23u32)).mod_op(Natural::from(10u32)), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .mod_op(Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// ``` #[inline] fn mod_op(self, other: Natural) -> Natural { self % other } } impl Mod<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and returning just /// the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!((&Natural::from(23u32)).mod_op(&Natural::from(10u32)), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .mod_op(&Natural::from_str("1234567890987").unwrap()), /// 530068894399u64 /// ); /// ``` #[inline] fn mod_op(self, other: &Natural) -> Natural { self % other } } impl ModAssign for Natural { /// Divides a [`Natural`] by another [`Natural`], taking the second [`Natural`] by value and /// replacing the first by the remainder. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x.mod_assign(Natural::from(10u32)); /// assert_eq!(x, 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x.mod_assign(Natural::from_str("1234567890987").unwrap()); /// assert_eq!(x, 530068894399u64); /// ``` #[inline] fn mod_assign(&mut self, other: Self) { *self %= other; } } impl<'a> ModAssign<&'a Self> for Natural { /// Divides a [`Natural`] by another [`Natural`], taking the second [`Natural`] by reference and /// replacing the first by the remainder. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x.mod_assign(&Natural::from(10u32)); /// assert_eq!(x, 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x.mod_assign(&Natural::from_str("1234567890987").unwrap()); /// assert_eq!(x, 530068894399u64); /// ``` fn mod_assign(&mut self, other: &'a Self) { *self %= other; } } impl Rem for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking both by value and returning just the /// remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem` is equivalent to [`mod_op`](Mod::mod_op). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32) % Natural::from(10u32), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000").unwrap() /// % Natural::from_str("1234567890987").unwrap(), /// 530068894399u64 /// ); /// ``` #[inline] fn rem(mut self, other: Self) -> Self { self %= other; self } } impl<'a> Rem<&'a Self> for Natural { type Output = Self; /// Divides a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem` is equivalent to [`mod_op`](Mod::mod_op). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(Natural::from(23u32) % &Natural::from(10u32), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000").unwrap() /// % &Natural::from_str("1234567890987").unwrap(), /// 530068894399u64 /// ); /// ``` #[inline] fn rem(mut self, other: &'a Self) -> Self { self %= other; self } } impl Rem for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem` is equivalent to [`mod_op`](Mod::mod_op). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Natural::from(23u32) % Natural::from(10u32), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// &Natural::from_str("1000000000000000000000000").unwrap() /// % Natural::from_str("1234567890987").unwrap(), /// 530068894399u64 /// ); /// ``` fn rem(self, other: Natural) -> Natural { match (self, other) { (_, Natural::ZERO) => panic!("division by zero"), (_, Natural::ONE) => Natural::ZERO, (n, Natural(Small(d))) => Natural(Small(n.rem_limb_ref(d))), (Natural(Small(_)), _) => self.clone(), (Natural(Large(ns)), Natural(Large(ds))) => { if ns.len() >= ds.len() { Natural::from_owned_limbs_asc(limbs_mod(ns, &ds)) } else { self.clone() } } } } } impl Rem<&Natural> for &Natural { type Output = Natural; /// Divides a [`Natural`] by another [`Natural`], taking both by reference and returning just /// the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem` is equivalent to [`mod_op`](Mod::mod_op). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// assert_eq!(&Natural::from(23u32) % &Natural::from(10u32), 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// assert_eq!( /// &Natural::from_str("1000000000000000000000000").unwrap() /// % &Natural::from_str("1234567890987").unwrap(), /// 530068894399u64 /// ); /// ``` fn rem(self, other: &Natural) -> Natural { match (self, other) { (_, &Natural::ZERO) => panic!("division by zero"), (_, &Natural::ONE) => Natural::ZERO, (n, d) if core::ptr::eq(n, d) => Natural::ZERO, (n, Natural(Small(d))) => Natural(Small(n.rem_limb_ref(*d))), (Natural(Small(_)), _) => self.clone(), (Natural(Large(ns)), Natural(Large(ds))) => { if ns.len() >= ds.len() { Natural::from_owned_limbs_asc(limbs_mod(ns, ds)) } else { self.clone() } } } } } impl RemAssign for Natural { /// Divides a [`Natural`] by another [`Natural`], taking the second [`Natural`] by value and /// replacing the first by the remainder. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem_assign` is equivalent to [`mod_assign`](ModAssign::mod_assign). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x %= Natural::from(10u32); /// assert_eq!(x, 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x %= Natural::from_str("1234567890987").unwrap(); /// assert_eq!(x, 530068894399u64); /// ``` #[inline] fn rem_assign(&mut self, other: Self) { *self %= &other; } } impl<'a> RemAssign<&'a Self> for Natural { /// Divides a [`Natural`] by another [`Natural`], taking the second [`Natural`] by reference and /// replacing the first by the remainder. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem_assign` is equivalent to [`mod_assign`](ModAssign::mod_assign). /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// // 2 * 10 + 3 = 23 /// let mut x = Natural::from(23u32); /// x %= &Natural::from(10u32); /// assert_eq!(x, 3); /// /// // 810000006723 * 1234567890987 + 530068894399 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x %= &Natural::from_str("1234567890987").unwrap(); /// assert_eq!(x, 530068894399u64); /// ``` fn rem_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, &Self::ZERO) => panic!("division by zero"), (_, &Self::ONE) => *self = Self::ZERO, (_, Self(Small(d))) => self.rem_assign_limb(*d), (Self(Small(_)), _) => {} (Self(Large(ns)), Self(Large(ds))) => { if ns.len() >= ds.len() { let mut rs = vec![0; ds.len()]; limbs_mod_to_out(&mut rs, ns, ds); swap(&mut rs, ns); self.trim(); } } } } } impl NegMod for Natural { type Output = Self; /// Divides the negative of a [`Natural`] by another [`Natural`], taking both by value and /// returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!(Natural::from(23u32).neg_mod(Natural::from(10u32)), 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .neg_mod(Natural::from_str("1234567890987").unwrap()), /// 704498996588u64 /// ); /// ``` #[inline] fn neg_mod(mut self, other: Self) -> Self { self.neg_mod_assign(other); self } } impl<'a> NegMod<&'a Self> for Natural { type Output = Self; /// Divides the negative of a [`Natural`] by another [`Natural`], taking the first by value and /// the second by reference and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!(Natural::from(23u32).neg_mod(&Natural::from(10u32)), 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// Natural::from_str("1000000000000000000000000") /// .unwrap() /// .neg_mod(&Natural::from_str("1234567890987").unwrap()), /// 704498996588u64 /// ); /// ``` #[inline] fn neg_mod(mut self, other: &'a Self) -> Self { self.neg_mod_assign(other); self } } impl NegMod for &Natural { type Output = Natural; /// Divides the negative of a [`Natural`] by another [`Natural`], taking the first by reference /// and the second by value and returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!((&Natural::from(23u32)).neg_mod(Natural::from(10u32)), 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .neg_mod(Natural::from_str("1234567890987").unwrap()), /// 704498996588u64 /// ); /// ``` fn neg_mod(self, other: Natural) -> Natural { let r = self % &other; if r == 0 { r } else { other - r } } } impl NegMod<&Natural> for &Natural { type Output = Natural; /// Divides the negative of a [`Natural`] by another [`Natural`], taking both by reference and /// returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegMod; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// assert_eq!((&Natural::from(23u32)).neg_mod(&Natural::from(10u32)), 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// assert_eq!( /// (&Natural::from_str("1000000000000000000000000").unwrap()) /// .neg_mod(&Natural::from_str("1234567890987").unwrap()), /// 704498996588u64 /// ); /// ``` fn neg_mod(self, other: &Natural) -> Natural { let r = self % other; if r == 0 { r } else { other - r } } } impl NegModAssign for Natural { /// Divides the negative of a [`Natural`] by another [`Natural`], taking the second [`Natural`]s /// by value and replacing the first by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegModAssign; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// let mut x = Natural::from(23u32); /// x.neg_mod_assign(Natural::from(10u32)); /// assert_eq!(x, 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x.neg_mod_assign(Natural::from_str("1234567890987").unwrap()); /// assert_eq!(x, 704498996588u64); /// ``` fn neg_mod_assign(&mut self, other: Self) { *self %= &other; if *self != 0 { self.sub_right_assign_no_panic(&other); } } } impl<'a> NegModAssign<&'a Self> for Natural { /// Divides the negative of a [`Natural`] by another [`Natural`], taking the second [`Natural`]s /// by reference and replacing the first by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy - r$ and $0 /// \leq r < y$. /// /// $$ /// x \gets y\left \lceil \frac{x}{y} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::NegModAssign; /// use malachite_nz::natural::Natural; /// /// // 3 * 10 - 7 = 23 /// let mut x = Natural::from(23u32); /// x.neg_mod_assign(&Natural::from(10u32)); /// assert_eq!(x, 7); /// /// // 810000006724 * 1234567890987 - 704498996588 = 1000000000000000000000000 /// let mut x = Natural::from_str("1000000000000000000000000").unwrap(); /// x.neg_mod_assign(&Natural::from_str("1234567890987").unwrap()); /// assert_eq!(x, 704498996588u64); /// ``` fn neg_mod_assign(&mut self, other: &'a Self) { *self %= other; if *self != 0 { self.sub_right_assign_no_panic(other); } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `getbits`, `MPN_REDC_1`, `win_size`, `redcify`, `mpn_powm`, and `mpz_powm` contributed to // the GNU project by Torbjörn Granlund. // // Copyright (C) 2000-2002, 2004, 2007–2012 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::Small; use crate::natural::arithmetic::add::{ limbs_add_same_length_to_out, limbs_add_to_out_aliased, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div_exact::{ limbs_modular_invert, limbs_modular_invert_limb, limbs_modular_invert_scratch_len, }; use crate::natural::arithmetic::div_mod::limbs_div_limb_to_out_mod; use crate::natural::arithmetic::mod_op::limbs_mod_to_out; use crate::natural::arithmetic::mod_power_of_2_pow::limbs_pow_low; use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length; use crate::natural::arithmetic::mul::mul_mod::{ limbs_mul_mod_base_pow_n_minus_1, limbs_mul_mod_base_pow_n_minus_1_next_size, limbs_mul_mod_base_pow_n_minus_1_scratch_len, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out_basecase, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::natural::arithmetic::square::{ limbs_square_to_out, limbs_square_to_out_basecase, limbs_square_to_out_scratch_len, }; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_to_out, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::logic::bit_access::limbs_get_bit; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::{Limb, MUL_TOOM22_THRESHOLD, SQR_BASECASE_THRESHOLD, SQR_TOOM2_THRESHOLD}; use alloc::vec::Vec; use core::cmp::{Ordering::*, max, min}; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ ModPow, ModPowAssign, ModPowerOf2, ModPowerOf2Assign, Parity, PowerOf2, WrappingNegAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::slices::{slice_leading_zeros, slice_set_zero}; // Equivalent to limbs_slice_get_bits(xs, end.saturating_sub(len), end)[0] // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `getbits` from `mpn/generic/powm.c` and `mpn/generic/powlo.c`, GMP 6.2.1. // Investigate changes from 6.1.2? pub(crate) fn get_bits(xs: &[Limb], mut end: u64, len: u64) -> usize { usize::exact_from(if end < len { xs[0].mod_power_of_2(end) } else { end -= len; let i = bit_to_limb_count_floor(end); end &= Limb::WIDTH_MASK; let mut bits = xs[i] >> end; let coend = Limb::WIDTH - end; if coend < len { bits += xs[i + 1] << coend; } bits.mod_power_of_2(len) }) } // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. // // This is equivalent to `mpn_redc_1` from `mpn/generic/redc_1.c`, GMP 6.2.1. #[allow(clippy::redundant_slicing)] fn limbs_redc_limb_raw(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], m_inv: Limb) -> bool { let len = ms.len(); assert_ne!(len, 0); let xs = &mut xs[..len << 1]; let mut xs_tail = &mut xs[..]; // force borrow rather than move for _ in 0..len { let product = xs_tail[0].wrapping_mul(m_inv); let carry = limbs_slice_add_mul_limb_same_length_in_place_left(&mut xs_tail[..len], ms, product); assert_eq!(xs_tail[0], 0); xs_tail[0] = carry; xs_tail = &mut xs_tail[1..]; } let (xs_lo, xs_hi) = xs.split_at(len); limbs_add_same_length_to_out(out, xs_hi, xs_lo) } // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. // // This is equivalent to `MPN_REDC_1` from `mpn/generic/powm.c`, GMP 6.2.1. Investigate changes from // 6.1.2? fn limbs_redc_limb(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], m_inv: Limb) { if limbs_redc_limb_raw(out, xs, ms, m_inv) { limbs_sub_same_length_in_place_left(&mut out[..ms.len()], ms); } } const WIDTH_LIMITS: [u64; 10] = [7, 25, 81, 241, 673, 1793, 4609, 11521, 28161, u64::MAX]; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `win_size` from `mpn/generic/powm.c`, 6.2.1. Investigate changes from // 6.1.2? pub(crate) fn get_window_size(width: u64) -> u64 { u64::wrapping_from( WIDTH_LIMITS .iter() .position(|&limit| width <= limit) .unwrap() + 1, ) } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. // // This is equivalent to `mpn_redc_n` from `mpn/generic/redc_n.c`, GMP 6.2.1. fn limbs_redc(out: &mut [Limb], xs: &[Limb], ms: &[Limb], is: &[Limb]) { let ms_len = ms.len(); assert!(ms_len > 8); let n = limbs_mul_mod_base_pow_n_minus_1_next_size(ms_len); let mut scratch = vec![0; limbs_mul_mod_base_pow_n_minus_1_scratch_len(n, ms_len, ms_len) + ms_len + n]; let (scratch_0, scratch) = scratch.split_at_mut(ms_len); limbs_mul_low_same_length(scratch_0, &xs[..ms_len], &is[..ms_len]); let (scratch_1, scratch_2) = scratch.split_at_mut(n); limbs_mul_mod_base_pow_n_minus_1(scratch_1, n, scratch_0, ms, scratch_2); let two_ms_len = ms_len << 1; assert!(two_ms_len > n); let m = two_ms_len - n; let carry = limbs_sub_same_length_to_out(scratch_2, &scratch_1[..m], &xs[..m]); let scratch = &mut scratch[..two_ms_len]; if carry { assert!(!limbs_sub_limb_in_place(&mut scratch[m..], 1)); } if limbs_sub_same_length_to_out(out, &xs[ms_len..two_ms_len], &scratch[ms_len..]) { limbs_slice_add_same_length_in_place_left(&mut out[..ms_len], ms); } } // Convert U to REDC form, U_r = B^n * U mod M // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. // // This is equivalent to `redcify` from `mpn/generic/powm.c`, 6.2.1. Investigate changes from 6.1.2? fn to_redc(out: &mut [Limb], xs: &[Limb], ms: &[Limb]) { let xs_len = xs.len(); let ms_len = ms.len(); if ms_len == 1 { let mut scratch = vec![0; (xs_len << 1) + ms_len + 1]; let (scratch, qs) = scratch.split_at_mut(xs_len + ms_len); scratch[ms_len..].copy_from_slice(xs); out[0] = limbs_div_limb_to_out_mod(qs, scratch, ms[0]); } else { let mut scratch = vec![0; xs_len + ms_len]; scratch[ms_len..].copy_from_slice(xs); limbs_mod_to_out(out, &scratch, ms); } } // TODO tune const REDC_1_TO_REDC_N_THRESHOLD: usize = 100; // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_mod_pow_odd_scratch_len(n: usize) -> usize { max(limbs_modular_invert_scratch_len(n), n << 1) }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn square_using_basecase_mul(out: &mut [Limb], xs: &[Limb]) { limbs_mul_greater_to_out_basecase(out, xs, xs); } // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. fn limbs_redc_limb_helper(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], is: &[Limb]) { limbs_redc_limb(out, xs, ms, is[0]); } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ms.len()`. fn limbs_redc_helper(out: &mut [Limb], xs: &mut [Limb], ms: &[Limb], is: &[Limb]) { limbs_redc(out, xs, ms, is); } // # Worst-case complexity // Constant time and additional memory. #[allow(clippy::absurd_extreme_comparisons, clippy::type_complexity)] fn select_fns( ms_len: usize, ) -> ( &'static dyn Fn(&mut [Limb], &[Limb], &[Limb]), &'static dyn Fn(&mut [Limb], &[Limb]), &'static dyn Fn(&mut [Limb], &mut [Limb], &[Limb], &[Limb]), ) { if REDC_1_TO_REDC_N_THRESHOLD < MUL_TOOM22_THRESHOLD { if ms_len < REDC_1_TO_REDC_N_THRESHOLD { ( &limbs_mul_greater_to_out_basecase, if REDC_1_TO_REDC_N_THRESHOLD < SQR_BASECASE_THRESHOLD || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len) { &square_using_basecase_mul } else { &limbs_square_to_out_basecase }, &limbs_redc_limb_helper, ) } else if ms_len < MUL_TOOM22_THRESHOLD { ( &limbs_mul_greater_to_out_basecase, if MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len) { &square_using_basecase_mul } else { &limbs_square_to_out_basecase }, &limbs_redc_helper, ) } else { ( &|out, xs, ys| { let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(out, xs, ys, &mut mul_scratch); }, &|out, xs| { let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())]; limbs_square_to_out(out, xs, &mut square_scratch); }, &limbs_redc_helper, ) } } else if ms_len < MUL_TOOM22_THRESHOLD { ( &limbs_mul_greater_to_out_basecase, if MUL_TOOM22_THRESHOLD < SQR_BASECASE_THRESHOLD || !(SQR_BASECASE_THRESHOLD..=SQR_TOOM2_THRESHOLD).contains(&ms_len) { &square_using_basecase_mul } else { &limbs_square_to_out_basecase }, &limbs_redc_limb_helper, ) } else { ( &|out, xs, ys| { let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(out, xs, ys, &mut mul_scratch); }, &|out, xs| { let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())]; limbs_square_to_out(out, xs, &mut square_scratch); }, if ms_len < REDC_1_TO_REDC_N_THRESHOLD { &limbs_redc_limb_helper } else { &limbs_redc_helper }, ) } } // Given the limbs of $x$, $E$, and odd $m$, writes the limbs of $x^E \mod m$ to an output slice. // // `xs`, `es`, and `ms` must be nonempty and their last elements must be nonzero. $m$ must be odd, // $E$ must be greater than 1, and `out` must be at least as long as `ms`. It is not required than // `xs` be less than `ms`. // // # Worst-case complexity // $T(n, m) = O(mn \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ms.len()`, and $m$ is `es.len()`. // // # Panics // Panics if `xs`, `es`, or `ms` are empty, if `xs` is longer than `ms`, if the first element of // `ms` is even, or if $E$ less than 2. // // This is equivalent to `mpn_powm` from `mpn/generic/powm.c`, GMP 6.2.1. pub_test! {limbs_mod_pow_odd( out: &mut [Limb], xs: &[Limb], es: &[Limb], ms: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let es_len = es.len(); let ms_len = ms.len(); assert_ne!(xs_len, 0); assert_ne!(es_len, 0); if es_len == 1 { assert!(es[0] > 1); } assert!(ms[0].odd()); let out = &mut out[..ms_len]; let width = limbs_significant_bits(es); let window_size = get_window_size(width); let mut small_is = [0; 2]; let mut is_vec; let is: &mut [Limb]; let redc_fn: &dyn Fn(&mut [Limb], &mut [Limb], &[Limb], &[Limb]); if ms_len < REDC_1_TO_REDC_N_THRESHOLD { is = &mut small_is; is[0] = limbs_modular_invert_limb(ms[0]); is[0].wrapping_neg_assign(); redc_fn = &limbs_redc_limb_helper; } else { is_vec = vec![0; ms_len]; is = &mut is_vec; limbs_modular_invert(is, ms, scratch); redc_fn = &limbs_redc_helper; } let mut powers = vec![0; ms_len << (window_size - 1)]; let mut powers: Vec<&mut [Limb]> = powers.chunks_mut(ms_len).collect(); to_redc(powers[0], xs, ms); // Store x ^ 2 at `out`. let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(powers[0].len())]; limbs_square_to_out(scratch, powers[0], &mut square_scratch); redc_fn(out, scratch, ms, is); // Precompute odd powers of x and put them in `powers`. let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(out.len())]; for i in 1..usize::power_of_2(window_size - 1) { let (powers_lo, powers_hi) = powers.split_at_mut(i); limbs_mul_same_length_to_out(scratch, powers_lo[i - 1], out, &mut mul_scratch); redc_fn(powers_hi[0], scratch, ms, is); } let exp_bits = get_bits(es, width, window_size); let mut bit_index = if width < window_size { fail_on_untested_path("limbs_mod_pow_odd, width < window_size"); 0 } else { width - window_size }; let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits)); bit_index += trailing_zeros; out.copy_from_slice(powers[exp_bits >> trailing_zeros >> 1]); let (mul_fn, square_fn, reduce_fn) = select_fns(ms_len); 'outer: while bit_index != 0 { while !limbs_get_bit(es, bit_index - 1) { square_fn(scratch, out); reduce_fn(out, scratch, ms, is); bit_index -= 1; if bit_index == 0 { break 'outer; } } // The next bit of the exponent is 1. Now extract the largest block of bits <= window_size, // and such that the least significant bit is 1. let exp_bits = get_bits(es, bit_index, window_size); let mut this_window_size = window_size; if bit_index < window_size { this_window_size -= window_size - bit_index; bit_index = 0; } else { bit_index -= window_size; } let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits)); bit_index += trailing_zeros; for _ in 0..this_window_size - trailing_zeros { square_fn(scratch, out); reduce_fn(out, scratch, ms, is); } mul_fn(scratch, out, powers[exp_bits >> trailing_zeros >> 1]); reduce_fn(out, scratch, ms, is); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(ms_len); scratch_lo.copy_from_slice(out); slice_set_zero(&mut scratch_hi[..ms_len]); redc_fn(out, scratch, ms, is); if limbs_cmp_same_length(out, ms) != Less { limbs_sub_same_length_in_place_left(out, ms); } }} // Interpreting a `Vec` and two `&[Limb]` as the limbs (in ascending order) of three // `Natural`s, `x`, `exp`, and `m`, writes the limbs of `x ^ exp` mod `2 ^ m` to an output slice. // Assumes the input is already reduced mod `m`. No input may be empty or have trailing zeros, the // exponent must be greater than 1, and the output slice must be at least as long as `ms`. // // # Worst-case complexity // $T(n, m) = O(mn \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `ms.len()`, and $m$ is `es.len()`. // // # Panics // Panics if the exponent has trailing zeros or is 1. // // This is equivalent to `mpz_powm` from `mpn/generic/powm.c`, GMP 6.2.1, where `b`, `e`, and `m` // are non-negative. Investigate changes from 6.1.2? pub_test! {limbs_mod_pow(out: &mut [Limb], xs: &[Limb], es: &[Limb], ms: &[Limb]) { let ms_len = ms.len(); let es_len = es.len(); let xs_len = xs.len(); let mut ms_zero_len = slice_leading_zeros(ms); let mut ms = &ms[ms_zero_len..]; let mut ms_nonzero_len = ms_len - ms_zero_len; let mut ms_vec; let mut ms_twos = 0; if ms[0].even() { ms_vec = vec![0; ms_nonzero_len]; ms_twos = TrailingZeros::trailing_zeros(ms[0]); limbs_shr_to_out(&mut ms_vec, &ms[..ms_nonzero_len], ms_twos); if ms_vec[ms_nonzero_len - 1] == 0 { ms_nonzero_len -= 1; } ms = &ms_vec; ms_zero_len += 1; } let scratch_len = if ms_zero_len != 0 { // We will call both `limbs_mod_pow_odd` and `limbs_pow_low`. let max_invert_len = max(ms_zero_len, ms_nonzero_len); let invert_scratch_len = limbs_modular_invert_scratch_len(max_invert_len); (ms_len << 1) + max(invert_scratch_len, ms_len << 1) } else { // We will call just `limbs_mod_pow_odd`. let invert_scratch_len = limbs_modular_invert_scratch_len(ms_nonzero_len); max(invert_scratch_len, ms_len << 1) }; let mut scratch = vec![0; scratch_len]; limbs_mod_pow_odd(out, xs, es, &ms[..ms_nonzero_len], &mut scratch); let mut xs_vec; let mut xs = xs; if ms_zero_len != 0 { if xs_len < ms_zero_len { xs_vec = vec![0; ms_zero_len]; xs_vec[..xs_len].copy_from_slice(xs); xs = &xs_vec; } let mut do_pow_low = true; let (scratch_lo, scratch_hi) = scratch.split_at_mut(ms_zero_len); if xs[0].even() { if es_len > 1 { slice_set_zero(scratch_lo); do_pow_low = false; } else { assert_eq!(es_len, 1); let t = if ms_twos == 0 { limb_to_bit_count(ms_zero_len) } else { limb_to_bit_count(ms_zero_len - 1) + ms_twos }; // Count number of low zero bits in `xs`, up to 3. let bits = (Limb::exact_from(0x1213) >> (xs[0].mod_power_of_2(3) << 1)).mod_power_of_2(2); // Note that es[0] * bits might overflow, but that just results in a missed // optimization. #[cfg(feature = "32_bit_limbs")] if let Ok(t) = Limb::try_from(t) && es[0].wrapping_mul(bits) >= t { slice_set_zero(scratch_lo); do_pow_low = false; } #[cfg(not(feature = "32_bit_limbs"))] if es[0].wrapping_mul(bits) >= t { slice_set_zero(scratch_lo); do_pow_low = false; } } } if do_pow_low { scratch_lo.copy_from_slice(&xs[..ms_zero_len]); limbs_pow_low(scratch_lo, &es[..es_len], scratch_hi); } let mut ms_vec; if ms_nonzero_len < ms_zero_len { ms_vec = vec![0; ms_zero_len]; ms_vec[..ms_nonzero_len].copy_from_slice(&ms[..ms_nonzero_len]); ms = &ms_vec; } let (scratch_0_1, scratch_2) = scratch.split_at_mut(ms_len << 1); let (scratch_0, scratch_1) = scratch_0_1.split_at_mut(ms_len); let scratch_0 = &mut scratch_0[..ms_zero_len]; limbs_modular_invert(scratch_1, &ms[..ms_zero_len], scratch_2); limbs_sub_greater_in_place_left(scratch_0, &out[..min(ms_zero_len, ms_nonzero_len)]); limbs_mul_low_same_length(scratch_2, &scratch_1[..ms_zero_len], scratch_0); if ms_twos != 0 { scratch_2[ms_zero_len - 1].mod_power_of_2_assign(ms_twos); } let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(ms_zero_len, ms_nonzero_len)]; limbs_mul_to_out( scratch_0_1, &scratch_2[..ms_zero_len], &ms[..ms_nonzero_len], &mut mul_scratch, ); limbs_add_to_out_aliased(out, ms_nonzero_len, &scratch_0_1[..ms_len]); } }} impl ModPow for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. All three [`Natural`]s are taken by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32).mod_pow(Natural::from(13u32), Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// Natural::from(10u32).mod_pow(Natural::from(1000u32), Natural::from(30u32)), /// 10 /// ); /// ``` #[inline] fn mod_pow(mut self, exp: Self, m: Self) -> Self { self.mod_pow_assign(exp, m); self } } impl<'a> ModPow for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by /// reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32).mod_pow(Natural::from(13u32), &Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// Natural::from(10u32).mod_pow(Natural::from(1000u32), &Natural::from(30u32)), /// 10 /// ); /// ``` #[inline] fn mod_pow(mut self, exp: Self, m: &'a Self) -> Self { self.mod_pow_assign(exp, m); self } } impl<'a> ModPow<&'a Self, Self> for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. The first and third [`Natural`]s are taken by value and the /// second by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32).mod_pow(&Natural::from(13u32), Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// Natural::from(10u32).mod_pow(&Natural::from(1000u32), Natural::from(30u32)), /// 10 /// ); /// ``` #[inline] fn mod_pow(mut self, exp: &'a Self, m: Self) -> Self { self.mod_pow_assign(exp, m); self } } impl<'a, 'b> ModPow<&'a Self, &'b Self> for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. The first [`Natural`] is taken by value and the second and third /// by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32).mod_pow(&Natural::from(13u32), &Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// Natural::from(10u32).mod_pow(&Natural::from(1000u32), &Natural::from(30u32)), /// 10 /// ); /// ``` #[inline] fn mod_pow(mut self, exp: &'a Self, m: &'b Self) -> Self { self.mod_pow_assign(exp, m); self } } impl ModPow for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`]$m$. The base must be /// already reduced modulo $m$. The first [`Natural`] is taken by reference and the second and /// third by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)).mod_pow(Natural::from(13u32), Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_pow(Natural::from(1000u32), Natural::from(30u32)), /// 10 /// ); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow(self, mut exp: Natural, mut m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, &exp, &m) { (_, _, &Natural::ONE) => Natural::ZERO, (_, &Natural::ZERO, _) => Natural::ONE, (&Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _) => x.clone(), (&Natural::ONE, _, _) => Natural::ONE, (Natural(Small(x)), Natural(Small(e)), Natural(Small(m))) if u64::convertible_from(*e) => { Natural::from(x.mod_pow(u64::wrapping_from(*e), *m)) } _ => { let ms = m.promote_in_place(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.promote_in_place(), ms); Natural::from_owned_limbs_asc(out) } } } } impl ModPow for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the /// second by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)).mod_pow(Natural::from(13u32), &Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_pow(Natural::from(1000u32), &Natural::from(30u32)), /// 10 /// ); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow(self, mut exp: Natural, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, &exp, m) { (_, _, &Natural::ONE) => Natural::ZERO, (_, &Natural::ZERO, _) => Natural::ONE, (&Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _) => x.clone(), (&Natural::ONE, _, _) => Natural::ONE, (Natural(Small(x)), Natural(Small(e)), Natural(Small(m))) if u64::convertible_from(*e) => { Natural::from(x.mod_pow(u64::wrapping_from(*e), *m)) } _ => { let ms = m.as_limbs_asc(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.promote_in_place(), ms); Natural::from_owned_limbs_asc(out) } } } } impl ModPow<&Natural, Natural> for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third /// by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)).mod_pow(&Natural::from(13u32), Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_pow(&Natural::from(1000u32), Natural::from(30u32)), /// 10 /// ); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow(self, exp: &Natural, mut m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, exp, &m) { (_, _, &Natural::ONE) => Natural::ZERO, (_, &Natural::ZERO, _) => Natural::ONE, (&Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _) => x.clone(), (&Natural::ONE, _, _) => Natural::ONE, (Natural(Small(x)), Natural(Small(e)), Natural(Small(m))) if u64::convertible_from(*e) => { Natural::from(x.mod_pow(u64::wrapping_from(*e), *m)) } _ => { let ms = m.promote_in_place(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.as_limbs_asc(), ms); Natural::from_owned_limbs_asc(out) } } } } impl ModPow<&Natural, &Natural> for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$. The base must be /// already reduced modulo $m$. All three [`Natural`]s are taken by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)).mod_pow(&Natural::from(13u32), &Natural::from(497u32)), /// 445 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_pow(&Natural::from(1000u32), &Natural::from(30u32)), /// 10 /// ); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow(self, exp: &Natural, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); match (self, exp, m) { (_, _, &Natural::ONE) => Natural::ZERO, (_, &Natural::ZERO, _) => Natural::ONE, (&Natural::ZERO, _, _) => Natural::ZERO, (x, &Natural::ONE, _) => x.clone(), (&Natural::ONE, _, _) => Natural::ONE, (Natural(Small(x)), Natural(Small(e)), Natural(Small(m))) if u64::convertible_from(*e) => { Natural::from(x.mod_pow(u64::wrapping_from(*e), *m)) } _ => { let ms = m.as_limbs_asc(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.as_limbs_asc(), exp.as_limbs_asc(), ms); Natural::from_owned_limbs_asc(out) } } } } impl ModPowAssign for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The /// base must be already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken /// by value. /// /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_pow_assign(Natural::from(13u32), Natural::from(497u32)); /// assert_eq!(x, 445); /// /// let mut x = Natural::from(10u32); /// x.mod_pow_assign(Natural::from(1000u32), Natural::from(30u32)); /// assert_eq!(x, 10); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow_assign(&mut self, mut exp: Self, mut m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); match (&mut *self, &exp, &m) { (_, _, &Self::ONE) => *self = Self::ZERO, (_, &Self::ZERO, _) => *self = Self::ONE, (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {} (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => { x.mod_pow_assign(u64::wrapping_from(*e), *m); } _ => { let ms = m.promote_in_place(); let mut out = vec![0; ms.len()]; limbs_mod_pow( &mut out, self.promote_in_place(), exp.promote_in_place(), ms, ); *self = Self::from_owned_limbs_asc(out); } } } } impl<'a> ModPowAssign for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The /// base must be already reduced modulo $m$. The first [`Natural`] on the right-hand side is /// taken by value and the second by reference. /// /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_pow_assign(Natural::from(13u32), &Natural::from(497u32)); /// assert_eq!(x, 445); /// /// let mut x = Natural::from(10u32); /// x.mod_pow_assign(Natural::from(1000u32), &Natural::from(30u32)); /// assert_eq!(x, 10); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow_assign(&mut self, mut exp: Self, m: &'a Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); match (&mut *self, &exp, m) { (_, _, &Self::ONE) => *self = Self::ZERO, (_, &Self::ZERO, _) => *self = Self::ONE, (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {} (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => { x.mod_pow_assign(u64::wrapping_from(*e), *m); } _ => { let ms = m.as_limbs_asc(); let mut out = vec![0; ms.len()]; limbs_mod_pow( &mut out, self.promote_in_place(), exp.promote_in_place(), ms, ); *self = Self::from_owned_limbs_asc(out); } } } } impl<'a> ModPowAssign<&'a Self, Self> for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The /// base must be already reduced modulo $m$. The first [`Natural`] on the right-hand side is /// taken by reference and the second by value. /// /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_pow_assign(&Natural::from(13u32), Natural::from(497u32)); /// assert_eq!(x, 445); /// /// let mut x = Natural::from(10u32); /// x.mod_pow_assign(&Natural::from(1000u32), Natural::from(30u32)); /// assert_eq!(x, 10); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow_assign(&mut self, exp: &'a Self, mut m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); match (&mut *self, exp, &m) { (_, _, &Self::ONE) => *self = Self::ZERO, (_, &Self::ZERO, _) => *self = Self::ONE, (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {} (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => { x.mod_pow_assign(u64::wrapping_from(*e), *m); } _ => { let ms = m.promote_in_place(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.promote_in_place(), exp.as_limbs_asc(), ms); *self = Self::from_owned_limbs_asc(out); } } } } impl<'a, 'b> ModPowAssign<&'a Self, &'b Self> for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo a third [`Natural`] $m$, in place. The /// base must be already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken /// by reference. /// /// $x \gets y$, where $x, y < m$ and $x^n \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_pow_assign(&Natural::from(13u32), &Natural::from(497u32)); /// assert_eq!(x, 445); /// /// let mut x = Natural::from(10u32); /// x.mod_pow_assign(&Natural::from(1000u32), &Natural::from(30u32)); /// assert_eq!(x, 10); /// ``` #[allow(clippy::match_same_arms)] // matches are order-dependent fn mod_pow_assign(&mut self, exp: &'a Self, m: &'b Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); match (&mut *self, exp, m) { (_, _, &Self::ONE) => *self = Self::ZERO, (_, &Self::ZERO, _) => *self = Self::ONE, (&mut (Self::ZERO | Self::ONE), _, _) | (_, &Self::ONE, _) => {} (Self(Small(x)), Self(Small(e)), Self(Small(m))) if u64::convertible_from(*e) => { x.mod_pow_assign(u64::wrapping_from(*e), *m); } _ => { let ms = m.as_limbs_asc(); let mut out = vec![0; ms.len()]; limbs_mod_pow(&mut out, self.promote_in_place(), exp.as_limbs_asc(), ms); *self = Self::from_owned_limbs_asc(out); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1995, 2001, 2002, 2012 Free Software Foundation, Inc. // // 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 crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, NegModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::slices::slice_set_zero; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` mod two raised to `pow`. Equivalently, retains only the least-significant // `pow` bits. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where in is // non-negative and the result is returned. pub_test! {limbs_mod_power_of_2(xs: &[Limb], pow: u64) -> Vec { if pow == 0 { return Vec::new(); } let leftover_bits = pow & Limb::WIDTH_MASK; let result_size = bit_to_limb_count_floor(pow); if result_size >= xs.len() { return xs.to_vec(); } let mut result = xs[..result_size].to_vec(); if leftover_bits != 0 { result.push(xs[result_size].mod_power_of_2(leftover_bits)); } result }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` mod two raised to `pow` to the input slice. Equivalently, retains only the // least-significant `pow` bits. If the upper limbs of the input slice are no longer needed, they // are set to zero. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is // non-negative, `res == in`, and instead of possibly being truncated, the high limbs of `res` are // possibly filled with zeros. pub_crate_test! {limbs_slice_mod_power_of_2_in_place(xs: &mut [Limb], pow: u64) { if pow == 0 { slice_set_zero(xs); return; } let new_size = bit_to_limb_count_ceiling(pow); if new_size > xs.len() { return; } slice_set_zero(&mut xs[new_size..]); let leftover_bits = pow & Limb::WIDTH_MASK; if leftover_bits != 0 { xs[new_size - 1].mod_power_of_2_assign(leftover_bits); } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` mod two raised to `pow` to the input `Vec`. Equivalently, retains only the // least-significant `pow` bits. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is // non-negative and `res == in`. pub_crate_test! {limbs_vec_mod_power_of_2_in_place(xs: &mut Vec, pow: u64) { if pow == 0 { xs.clear(); return; } let new_size = bit_to_limb_count_ceiling(pow); if new_size > xs.len() { return; } xs.truncate(new_size); let leftover_bits = pow & Limb::WIDTH_MASK; if leftover_bits != 0 { xs[new_size - 1].mod_power_of_2_assign(leftover_bits); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the negative of the `Natural` mod two raised to `pow`. Equivalently, takes the two's // complement and retains only the least-significant `pow` bits. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is // negative and the result is returned. `xs` is the limbs of `-in`. pub_crate_test! {limbs_neg_mod_power_of_2(xs: &[Limb], pow: u64) -> Vec { let mut result = xs.to_vec(); limbs_neg_mod_power_of_2_in_place(&mut result, pow); result }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the negative of the `Natural` mod two raised to `pow` to the input `Vec`. Equivalently, // takes the two's complement and retains only the least-significant `pow` bits. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // This is equivalent to `mpz_tdiv_r_2exp` from `mpz/tdiv_r_2exp.c`, GMP 6.2.1, where `in` is // negative and `res == in`. `xs` is the limbs of `-in`. pub_crate_test! {limbs_neg_mod_power_of_2_in_place(xs: &mut Vec, pow: u64) { let new_size = bit_to_limb_count_ceiling(pow); xs.resize(new_size, 0); limbs_twos_complement_in_place(xs); let leftover_bits = pow & Limb::WIDTH_MASK; if leftover_bits != 0 { xs[new_size - 1].mod_power_of_2_assign(leftover_bits); } }} impl ModPowerOf2 for Natural { type Output = Self; /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by /// value. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(Natural::from(260u32).mod_power_of_2(8), 4); /// /// // 100 * 2^4 + 11 = 1611 /// assert_eq!(Natural::from(1611u32).mod_power_of_2(4), 11); /// ``` #[inline] fn mod_power_of_2(mut self, pow: u64) -> Self { self.mod_power_of_2_assign(pow); self } } impl ModPowerOf2 for &Natural { type Output = Natural; /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by /// reference. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!((&Natural::from(260u32)).mod_power_of_2(8), 4); /// // 100 * 2^4 + 11 = 1611 /// assert_eq!((&Natural::from(1611u32)).mod_power_of_2(4), 11); /// ``` fn mod_power_of_2(self, pow: u64) -> Natural { match self { Natural(Small(small)) => Natural(Small(small.mod_power_of_2(pow))), Natural(Large(limbs)) => { Natural::from_owned_limbs_asc(limbs_mod_power_of_2(limbs, pow)) } } } } impl ModPowerOf2Assign for Natural { /// Divides a [`Natural`]by $2^k$, replacing the [`Natural`] by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Assign; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = Natural::from(260u32); /// x.mod_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // 100 * 2^4 + 11 = 1611 /// let mut x = Natural::from(1611u32); /// x.mod_power_of_2_assign(4); /// assert_eq!(x, 11); /// ``` fn mod_power_of_2_assign(&mut self, pow: u64) { match &mut *self { Self(Small(small)) => small.mod_power_of_2_assign(pow), Self(Large(limbs)) => { limbs_vec_mod_power_of_2_in_place(limbs, pow); self.trim(); } } } } impl RemPowerOf2 for Natural { type Output = Self; /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by /// value. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem_power_of_2` is equivalent to /// [`mod_power_of_2`](ModPowerOf2::mod_power_of_2). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!(Natural::from(260u32).rem_power_of_2(8), 4); /// /// // 100 * 2^4 + 11 = 1611 /// assert_eq!(Natural::from(1611u32).rem_power_of_2(4), 11); /// ``` #[inline] fn rem_power_of_2(self, pow: u64) -> Self { self.mod_power_of_2(pow) } } impl RemPowerOf2 for &Natural { type Output = Natural; /// Divides a [`Natural`] by $2^k$, returning just the remainder. The [`Natural`] is taken by /// reference. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem_power_of_2` is equivalent to /// [`mod_power_of_2`](ModPowerOf2::mod_power_of_2). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// assert_eq!((&Natural::from(260u32)).rem_power_of_2(8), 4); /// // 100 * 2^4 + 11 = 1611 /// assert_eq!((&Natural::from(1611u32)).rem_power_of_2(4), 11); /// ``` #[inline] fn rem_power_of_2(self, pow: u64) -> Natural { self.mod_power_of_2(pow) } } impl RemPowerOf2Assign for Natural { /// Divides a [`Natural`] by $2^k$, replacing the first [`Natural`] by the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k + r$ and /// $0 \leq r < 2^k$. /// /// $$ /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// For [`Natural`]s, `rem_power_of_2_assign` is equivalent to /// [`mod_power_of_2_assign`](ModPowerOf2Assign::mod_power_of_2_assign). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RemPowerOf2Assign; /// use malachite_nz::natural::Natural; /// /// // 1 * 2^8 + 4 = 260 /// let mut x = Natural::from(260u32); /// x.rem_power_of_2_assign(8); /// assert_eq!(x, 4); /// /// // 100 * 2^4 + 11 = 1611 /// let mut x = Natural::from(1611u32); /// x.rem_power_of_2_assign(4); /// assert_eq!(x, 11); /// ``` #[inline] fn rem_power_of_2_assign(&mut self, pow: u64) { self.mod_power_of_2_assign(pow); } } impl NegModPowerOf2 for Natural { type Output = Self; /// Divides the negative of a [`Natural`] by a $2^k$, returning just the remainder. The /// [`Natural`] is taken by value. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegModPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 2 * 2^8 - 252 = 260 /// assert_eq!(Natural::from(260u32).neg_mod_power_of_2(8), 252); /// /// // 101 * 2^4 - 5 = 1611 /// assert_eq!(Natural::from(1611u32).neg_mod_power_of_2(4), 5); /// ``` #[inline] fn neg_mod_power_of_2(mut self, pow: u64) -> Self { self.neg_mod_power_of_2_assign(pow); self } } impl NegModPowerOf2 for &Natural { type Output = Natural; /// Divides the negative of a [`Natural`] by a $2^k$, returning just the remainder. The /// [`Natural`] is taken by reference. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and /// $0 \leq r < 2^k$. /// /// $$ /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegModPowerOf2; /// use malachite_nz::natural::Natural; /// /// // 2 * 2^8 - 252 = 260 /// assert_eq!((&Natural::from(260u32)).neg_mod_power_of_2(8), 252); /// // 101 * 2^4 - 5 = 1611 /// assert_eq!((&Natural::from(1611u32)).neg_mod_power_of_2(4), 5); /// ``` fn neg_mod_power_of_2(self, pow: u64) -> Natural { match (self, pow) { (&Natural::ZERO, _) => Natural::ZERO, (_, pow) if pow <= Limb::WIDTH => { Natural::from(Limb::wrapping_from(self).neg_mod_power_of_2(pow)) } (Natural(Small(small)), pow) => { Natural::from_owned_limbs_asc(limbs_neg_mod_power_of_2(&[*small], pow)) } (Natural(Large(limbs)), pow) => { Natural::from_owned_limbs_asc(limbs_neg_mod_power_of_2(limbs, pow)) } } } } impl NegModPowerOf2Assign for Natural { /// Divides the negative of a [`Natural`] by $2^k$, returning just the remainder. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k - r$ and /// $0 \leq r < 2^k$. /// /// $$ /// x \gets 2^k\left \lceil \frac{x}{2^k} \right \rceil - x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegModPowerOf2Assign; /// use malachite_nz::natural::Natural; /// /// // 2 * 2^8 - 252 = 260 /// let mut x = Natural::from(260u32); /// x.neg_mod_power_of_2_assign(8); /// assert_eq!(x, 252); /// /// // 101 * 2^4 - 5 = 1611 /// let mut x = Natural::from(1611u32); /// x.neg_mod_power_of_2_assign(4); /// assert_eq!(x, 5); /// ``` fn neg_mod_power_of_2_assign(&mut self, pow: u64) { if *self == 0 { } else if pow <= Limb::WIDTH { *self = Self::from(Limb::wrapping_from(&*self).neg_mod_power_of_2(pow)); } else { let limbs = self.promote_in_place(); limbs_neg_mod_power_of_2_in_place(limbs, pow); self.trim(); } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_add_limb, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, limbs_vec_add_in_place_left, }; use crate::natural::logic::bit_access::limbs_clear_bit; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ ModPowerOf2Add, ModPowerOf2AddAssign, ModPowerOf2Shl, ModPowerOf2ShlAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::SignificantBits; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`. Assumes the input is already // reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_mod_power_of_2_add_limb(xs: &[Limb], y: Limb, pow: u64) -> Vec { if xs.len() < bit_to_limb_count_ceiling(pow) { limbs_add_limb(xs, y) } else { let mut out = xs.to_vec(); if !limbs_slice_add_limb_in_place(&mut out, y) { limbs_clear_bit(&mut out, pow); } out } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`, to the input slice. Returns // whether there is a carry. Assumes the input is already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_slice_mod_power_of_2_add_limb_in_place( xs: &mut [Limb], y: Limb, pow: u64 ) -> bool { if xs.len() < bit_to_limb_count_ceiling(pow) { limbs_slice_add_limb_in_place(xs, y) } else { if !limbs_slice_add_limb_in_place(xs, y) { limbs_clear_bit(xs, pow); } false } }} // Interpreting a nonempty `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes // the limbs of the sum of the `Natural` and a `Limb`, mod `2 ^ pow`, to the input `Vec`. Assumes // the input is already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_crate_test! {limbs_vec_mod_power_of_2_add_limb_in_place(xs: &mut Vec, y: Limb, pow: u64) { assert!(!xs.is_empty()); if limbs_slice_mod_power_of_2_add_limb_in_place(xs, y, pow) { xs.push(1); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the // first slice is at least as long as the second, returns a `Vec` of the limbs of the sum of the // `Natural`s mod `2 ^ pow`. Assumes the inputs are already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. pub_test! {limbs_mod_power_of_2_add_greater(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec { let mut out = xs.to_vec(); if limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut out, ys, pow) { out.push(1); } out }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the sum of the `Natural`s mod `2 ^ pow`. Assumes the inputs are already // reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. pub_test! {limbs_mod_power_of_2_add(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec { if xs.len() >= ys.len() { limbs_mod_power_of_2_add_greater(xs, ys, pow) } else { limbs_mod_power_of_2_add_greater(ys, xs, pow) } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, where the // length of the first slice is greater than or equal to the length of the second, writes the // `xs.len()` least-significant limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the first // (left) slice. Returns whether there is a carry. Assumes the inputs are already reduced mod `2 ^ // pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. pub_test! {limbs_slice_mod_power_of_2_add_greater_in_place_left( xs: &mut [Limb], ys: &[Limb], pow: u64, ) -> bool { if xs.len() < bit_to_limb_count_ceiling(pow) { limbs_slice_add_greater_in_place_left(xs, ys) } else { if !limbs_slice_add_greater_in_place_left(xs, ys) { limbs_clear_bit(xs, pow); } false } }} // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the first (left) // slice. Assumes the inputs are already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(xs.len(), ys.len())`, and $m$ is `max(1, // ys.len() - xs.len())`. pub_test! {limbs_vec_mod_power_of_2_add_in_place_left(xs: &mut Vec, ys: &[Limb], pow: u64) { let xs_len = xs.len(); let ys_len = ys.len(); let max_len =bit_to_limb_count_ceiling(pow); if xs_len < max_len && ys_len < max_len { limbs_vec_add_in_place_left(xs, ys); } else { let carry = if xs_len >= ys_len { limbs_slice_mod_power_of_2_add_greater_in_place_left(xs, ys, pow) } else { let (ys_lo, ys_hi) = ys.split_at(xs_len); let mut carry = limbs_slice_add_same_length_in_place_left(xs, ys_lo); xs.extend_from_slice(ys_hi); if carry { carry = limbs_slice_add_limb_in_place(&mut xs[xs_len..], 1); } carry }; if !carry { limbs_clear_bit(xs, pow); } } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the sum of the `Natural`s, mod `2 ^ pow`, to the longer slice (or the first one, if // they are equally long). Returns a `bool` which is `false` when the output is to the first `Vec` // and `true` when it's to the second `Vec`. Assumes the inputs are already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. pub_test! {limbs_mod_power_of_2_add_in_place_either( xs: &mut Vec, ys: &mut Vec, pow: u64, ) -> bool { if xs.len() >= ys.len() { if limbs_slice_mod_power_of_2_add_greater_in_place_left(xs, ys, pow) { xs.push(1); } false } else { if limbs_slice_mod_power_of_2_add_greater_in_place_left(ys, xs, pow) { ys.push(1); } true } }} impl Natural { fn mod_power_of_2_add_limb_ref(&self, y: Limb, pow: u64) -> Self { match (self, y, pow) { (_, 0, _) => self.clone(), (&Self::ZERO, _, _) => Self(Small(y)), (&Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { Self(Small(small.mod_power_of_2_add(other, pow))) } (&Self(Small(small)), other, _) => { let (sum, overflow) = small.overflowing_add(other); if overflow { Self(Large(vec![sum, 1])) } else { Self(Small(sum)) } } (&Self(Large(ref limbs)), other, pow) => { Self::from_owned_limbs_asc(limbs_mod_power_of_2_add_limb(limbs, other, pow)) } } } fn mod_power_of_2_add_assign_limb(&mut self, y: Limb, pow: u64) { match (&mut *self, y, pow) { (_, 0, _) => {} (&mut Self::ZERO, _, _) => *self = Self(Small(y)), (&mut Self(Small(ref mut small)), other, pow) if pow <= Limb::WIDTH => { small.mod_power_of_2_add_assign(other, pow); } (&mut Self(Small(ref mut small)), other, _) => { let (sum, overflow) = small.overflowing_add(other); if overflow { *self = Self(Large(vec![sum, 1])); } else { *small = sum; } } (&mut Self(Large(ref mut limbs)), y, pow) => { limbs_vec_mod_power_of_2_add_limb_in_place(limbs, y, pow); self.trim(); } } } } impl ModPowerOf2Add for Natural { type Output = Self; /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. Both /// [`Natural`]s are taken by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_power_of_2_add(Natural::from(2u32), 5), 2); /// assert_eq!( /// Natural::from(10u32).mod_power_of_2_add(Natural::from(14u32), 4), /// 8 /// ); /// ``` fn mod_power_of_2_add(mut self, other: Self, pow: u64) -> Self { self.mod_power_of_2_add_assign(other, pow); self } } impl<'a> ModPowerOf2Add<&'a Self> for Natural { type Output = Self; /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. The /// first [`Natural`] is taken by value and the second by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_power_of_2_add(&Natural::from(2u32), 5), 2); /// assert_eq!( /// Natural::from(10u32).mod_power_of_2_add(&Natural::from(14u32), 4), /// 8 /// ); /// ``` #[inline] fn mod_power_of_2_add(mut self, other: &'a Self, pow: u64) -> Self { self.mod_power_of_2_add_assign(other, pow); self } } impl ModPowerOf2Add for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. The /// first [`Natural`] is taken by reference and the second by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).mod_power_of_2_add(Natural::from(2u32), 5), /// 2 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_add(Natural::from(14u32), 4), /// 8 /// ); /// ``` #[inline] fn mod_power_of_2_add(self, mut other: Natural, pow: u64) -> Natural { other.mod_power_of_2_add_assign(self, pow); other } } impl ModPowerOf2Add<&Natural> for &Natural { type Output = Natural; /// Adds two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. Both /// [`Natural`]s are taken by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Add; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::ZERO).mod_power_of_2_add(&Natural::from(2u32), 5), /// 2 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_add(&Natural::from(14u32), 4), /// 8 /// ); /// ``` fn mod_power_of_2_add(self, other: &Natural, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (self, other) { (x, y) if core::ptr::eq(x, y) => self.mod_power_of_2_shl(1, pow), (x, &Natural(Small(y))) => x.mod_power_of_2_add_limb_ref(y, pow), (&Natural(Small(x)), y) => y.mod_power_of_2_add_limb_ref(x, pow), (&Natural(Large(ref xs)), &Natural(Large(ref ys))) => { Natural::from_owned_limbs_asc(limbs_mod_power_of_2_add(xs, ys, pow)) } } } } impl ModPowerOf2AddAssign for Natural { /// Adds two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced modulo /// $2^k$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_power_of_2_add_assign(Natural::from(2u32), 5); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_add_assign(Natural::from(14u32), 4); /// assert_eq!(x, 8); /// ``` fn mod_power_of_2_add_assign(&mut self, mut other: Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, &mut other) { (x, &mut Self(Small(y))) => x.mod_power_of_2_add_assign_limb(y, pow), (&mut Self(Small(x)), y) => *self = y.mod_power_of_2_add_limb_ref(x, pow), (&mut Self(Large(ref mut xs)), _) => { if let Self(Large(mut ys)) = other { if limbs_mod_power_of_2_add_in_place_either(xs, &mut ys, pow) { *xs = ys; } self.trim(); } } } } } impl<'a> ModPowerOf2AddAssign<&'a Self> for Natural { /// Adds two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced modulo /// $2^k$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2AddAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.mod_power_of_2_add_assign(&Natural::from(2u32), 5); /// assert_eq!(x, 2); /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_add_assign(&Natural::from(14u32), 4); /// assert_eq!(x, 8); /// ``` fn mod_power_of_2_add_assign(&mut self, other: &'a Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, other) { (x, y) if core::ptr::eq(x, y) => { self.mod_power_of_2_shl_assign(pow, 1); } (x, &Self(Small(y))) => x.mod_power_of_2_add_assign_limb(y, pow), (&mut Self(Small(x)), y) => *self = y.mod_power_of_2_add_limb_ref(x, pow), (&mut Self(Large(ref mut xs)), &Self(Large(ref ys))) => { limbs_vec_mod_power_of_2_add_in_place_left(xs, ys, pow); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::mod_power_of_2::limbs_slice_mod_power_of_2_in_place; use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{ModPowerOf2Inverse, Parity}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::SignificantBits; // - out should be just long enough for `pow` bits. // - xs should have the same length as out. // - scratch should be at least twice as long as out. // - out should be filled with zeros. fn limbs_mod_power_of_2_inverse(out: &mut [Limb], xs: &[Limb], pow: u64, scratch: &mut [Limb]) { let len = out.len(); split_into_chunks_mut!(scratch, len, [scratch_0, scratch_1], _unused); let mut limb_pow = 1; out[0] = xs[0].mod_power_of_2_inverse(Limb::WIDTH).unwrap(); while limb_pow < len { limb_pow <<= 1; if limb_pow > len { limb_pow = len; } let out_lo = &mut out[..limb_pow]; let scratch_0_lo = &mut scratch_0[..limb_pow]; let scratch_1_lo = &mut scratch_1[..limb_pow]; limbs_mul_low_same_length(scratch_0_lo, out_lo, &xs[..limb_pow]); limbs_twos_complement_in_place(scratch_0_lo); limbs_slice_add_limb_in_place(scratch_0_lo, 2); limbs_mul_low_same_length(scratch_1_lo, scratch_0_lo, out_lo); out_lo.copy_from_slice(scratch_1_lo); } limbs_slice_mod_power_of_2_in_place(out, pow); } #[allow(clippy::unnecessary_wraps)] fn mod_power_of_2_inverse_helper(xs: &[Limb], pow: u64) -> Option { let len = xs.len(); let mut big_scratch = vec![0; len * 3]; let (out, scratch) = big_scratch.split_at_mut(len); limbs_mod_power_of_2_inverse(out, xs, pow, scratch); big_scratch.truncate(len); Some(Natural::from_owned_limbs_asc(big_scratch)) } impl ModPowerOf2Inverse for Natural { type Output = Self; /// Computes the multiplicative inverse of a [`Natural`] modulo $2^k$. The input must be already /// reduced modulo $2^k$. The [`Natural`] is taken by value. /// /// Returns `None` if $x$ is even. /// /// $f(x, k) = y$, where $x, y < 2^k$, $x$ is odd, and $xy \equiv 1 \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Inverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_power_of_2_inverse(8), /// Some(Natural::from(171u32)) /// ); /// assert_eq!(Natural::from(4u32).mod_power_of_2_inverse(8), None); /// ``` fn mod_power_of_2_inverse(self, pow: u64) -> Option { assert_ne!(self, 0u32); assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match (self, pow) { (Self::ONE, _) => Some(Self::ONE), (x, _) if x.even() => None, (Self(Small(x)), pow) if pow <= Limb::WIDTH => { x.mod_power_of_2_inverse(pow).map(Self::from) } (Self(Small(x)), pow) => { let len = bit_to_limb_count_ceiling(pow); let mut xs = vec![0; len]; xs[0] = x; mod_power_of_2_inverse_helper(&xs, pow) } (Self(Large(mut xs)), pow) => { let len = bit_to_limb_count_ceiling(pow); xs.resize(len, 0); mod_power_of_2_inverse_helper(&xs, pow) } } } } impl ModPowerOf2Inverse for &Natural { type Output = Natural; /// Computes the multiplicative inverse of a [`Natural`] modulo $2^k$. The input must be already /// reduced modulo $2^k$. The [`Natural`] is taken by reference. /// /// Returns `None` if $x$ is even. /// /// $f(x, k) = y$, where $x, y < 2^k$, $x$ is odd, and $xy \equiv 1 \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is 0 or if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Inverse; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_power_of_2_inverse(8), /// Some(Natural::from(171u32)) /// ); /// assert_eq!((&Natural::from(4u32)).mod_power_of_2_inverse(8), None); /// ``` fn mod_power_of_2_inverse(self, pow: u64) -> Option { assert_ne!(*self, 0u32); assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match (self, pow) { (&Natural::ONE, _) => Some(Natural::ONE), (x, _) if x.even() => None, (Natural(Small(x)), pow) if pow <= Limb::WIDTH => { x.mod_power_of_2_inverse(pow).map(Natural::from) } (Natural(Small(x)), pow) => { let mut xs = vec![0; bit_to_limb_count_ceiling(pow)]; xs[0] = *x; mod_power_of_2_inverse_helper(&xs, pow) } (Natural(Large(xs)), pow) => { let mut xs = xs.clone(); xs.resize(bit_to_limb_count_ceiling(pow), 0); mod_power_of_2_inverse_helper(&xs, pow) } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::ModPowerOf2IsReduced; use malachite_base::num::logic::traits::SignificantBits; impl ModPowerOf2IsReduced for Natural { /// Returns whether a [`Natural`] is reduced modulo 2^k$; in other words, whether it has no more /// than $k$ significant bits. /// /// $f(x, k) = (x < 2^k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{ModPowerOf2IsReduced, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_power_of_2_is_reduced(5), true); /// assert_eq!( /// Natural::from(10u32).pow(12).mod_power_of_2_is_reduced(39), /// false /// ); /// assert_eq!( /// Natural::from(10u32).pow(12).mod_power_of_2_is_reduced(40), /// true /// ); /// ``` #[inline] fn mod_power_of_2_is_reduced(&self, pow: u64) -> bool { self.significant_bits() <= pow } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place; use crate::natural::arithmetic::mod_power_of_2_square::{ limbs_mod_power_of_2_square, limbs_mod_power_of_2_square_ref, }; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Assign, ModPowerOf2Mul, ModPowerOf2MulAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::SignificantBits; // Interpreting two `Vec`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the product of the `Natural`s mod `2 ^ pow`. Assumes the inputs are already // reduced mod `2 ^ pow`. The input `Vec`s may be mutated. Neither input may be empty or have // trailing zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if either input is empty. May panic if either input has trailing zeros. pub_test! {limbs_mod_power_of_2_mul(xs: &mut Vec, ys: &mut Vec, pow: u64) -> Vec { if core::ptr::eq(xs.as_slice(), ys.as_slice()) { return limbs_mod_power_of_2_square(xs, pow); } let xs_len = xs.len(); assert_ne!(xs_len, 0); let ys_len = ys.len(); assert_ne!(ys_len, 0); let max_len = bit_to_limb_count_ceiling(pow); if max_len > xs_len + ys_len + 1 { return limbs_mul(xs, ys); } // Should really be max_len / sqrt(2); 0.75 * max_len is close enough let limit = max_len.checked_mul(3).unwrap() >> 2; let mut product = if xs_len >= limit && ys_len >= limit { if xs_len != max_len { xs.resize(max_len, 0); } if ys_len != max_len { ys.resize(max_len, 0); } let mut product_limbs = vec![0; max_len]; limbs_mul_low_same_length(&mut product_limbs, xs, ys); product_limbs } else { limbs_mul(xs, ys) }; limbs_vec_mod_power_of_2_in_place(&mut product, pow); product }} // Interpreting a slice of `Limb` and a `Vec` as the limbs (in ascending order) of two // `Natural`s, returns a `Vec` of the limbs of the product of the `Natural`s mod `2 ^ pow`. Assumes // the inputs are already reduced mod `2 ^ pow`. The input `Vec` may be mutated. Neither input may // be empty or have trailing zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if either input is empty. May panic if either input has trailing zeros. pub_test! {limbs_mod_power_of_2_mul_val_ref( xs: &mut Vec, ys: &[Limb], pow: u64 ) -> Vec { if core::ptr::eq(xs.as_slice(), ys) { return limbs_mod_power_of_2_square(xs, pow); } let xs_len = xs.len(); assert_ne!(xs_len, 0); let ys_len = ys.len(); assert_ne!(ys_len, 0); let max_len = bit_to_limb_count_ceiling(pow); if max_len > xs_len + ys_len + 1 { return limbs_mul(xs, ys); } // Should really be max_len / sqrt(2); 0.75 * max_len is close enough let limit = max_len.checked_mul(3).unwrap() >> 2; let mut product = if xs_len >= limit && ys_len >= limit { if xs_len != max_len { xs.resize(max_len, 0); } let mut ys_adjusted_vec; let ys_adjusted = if ys_len == max_len { ys } else { ys_adjusted_vec = vec![0; max_len]; ys_adjusted_vec[..ys_len].copy_from_slice(ys); &ys_adjusted_vec }; let mut product = vec![0; max_len]; limbs_mul_low_same_length(&mut product, xs, ys_adjusted); product } else { limbs_mul(xs, ys) }; limbs_vec_mod_power_of_2_in_place(&mut product, pow); product }} // Interpreting two slices of `Limb` as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the product of the `Natural`s mod `2 ^ pow`. Assumes the inputs are already // reduced mod `2 ^ pow`. Neither input may be empty or have trailing zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if either input is empty. May panic if either input has trailing zeros. pub_test! {limbs_mod_power_of_2_mul_ref_ref(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec { if core::ptr::eq(xs, ys) { return limbs_mod_power_of_2_square_ref(xs, pow); } let xs_len = xs.len(); assert_ne!(xs_len, 0); let ys_len = ys.len(); assert_ne!(ys_len, 0); let max_len = bit_to_limb_count_ceiling(pow); if max_len > xs_len + ys_len + 1 { return limbs_mul(xs, ys); } // Should really be max_len / sqrt(2); 0.75 * max_len is close enough let limit = max_len.checked_mul(3).unwrap() >> 2; let mut product = if xs_len >= limit && ys_len >= limit { let mut xs_adjusted_vec; let mut ys_adjusted_vec; let xs_adjusted = if xs_len == max_len { xs } else { xs_adjusted_vec = vec![0; max_len]; xs_adjusted_vec[..xs_len].copy_from_slice(xs); &xs_adjusted_vec }; let ys_adjusted = if ys_len == max_len { ys } else { ys_adjusted_vec = vec![0; max_len]; ys_adjusted_vec[..ys_len].copy_from_slice(ys); &ys_adjusted_vec }; let mut product = vec![0; max_len]; limbs_mul_low_same_length(&mut product, xs_adjusted, ys_adjusted); product } else { limbs_mul(xs, ys) }; limbs_vec_mod_power_of_2_in_place(&mut product, pow); product }} impl Natural { fn mod_power_of_2_mul_limb_ref(&self, y: Limb, pow: u64) -> Self { match (self, y, pow) { (_, 0, _) | (&Self::ZERO, _, _) => Self::ZERO, (_, 1, _) => self.clone(), (&Self::ONE, _, _) => Self(Small(y)), (&Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { Self(Small(small.mod_power_of_2_mul(other, pow))) } (&Self(Small(small)), other, pow) => { Self::from((DoubleLimb::from(small) * DoubleLimb::from(other)).mod_power_of_2(pow)) } (x, other, pow) => (x * Self::from(other)).mod_power_of_2(pow), } } fn mod_power_of_2_mul_limb_assign(&mut self, y: Limb, pow: u64) { match (&mut *self, y, pow) { (_, 1, _) | (&mut Self::ZERO, _, _) => {} (_, 0, _) => *self = Self::ZERO, (&mut Self::ONE, _, _) => *self = Self(Small(y)), (&mut Self(Small(ref mut small)), other, pow) if pow <= Limb::WIDTH => { small.mod_power_of_2_mul_assign(other, pow); } (&mut Self(Small(small)), other, pow) => { *self = Self::from( (DoubleLimb::from(small) * DoubleLimb::from(other)).mod_power_of_2(pow), ); } (x, other, pow) => { *x *= Self::from(other); x.mod_power_of_2_assign(pow); } } } } impl ModPowerOf2Mul for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// Both [`Natural`]s are taken by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Mul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_power_of_2_mul(Natural::from(2u32), 5), /// 6 /// ); /// assert_eq!( /// Natural::from(10u32).mod_power_of_2_mul(Natural::from(14u32), 4), /// 12 /// ); /// ``` #[inline] fn mod_power_of_2_mul(mut self, other: Self, pow: u64) -> Self { self.mod_power_of_2_mul_assign(other, pow); self } } impl<'a> ModPowerOf2Mul<&'a Self> for Natural { type Output = Self; /// Multiplies two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// The first [`Natural`] is taken by value and the second by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Mul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_power_of_2_mul(&Natural::from(2u32), 5), /// 6 /// ); /// assert_eq!( /// Natural::from(10u32).mod_power_of_2_mul(&Natural::from(14u32), 4), /// 12 /// ); /// ``` #[inline] fn mod_power_of_2_mul(mut self, other: &'a Self, pow: u64) -> Self { self.mod_power_of_2_mul_assign(other, pow); self } } impl ModPowerOf2Mul for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// The first [`Natural`] is taken by reference and the second by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Mul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_power_of_2_mul(Natural::from(2u32), 5), /// 6 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_mul(Natural::from(14u32), 4), /// 12 /// ); /// ``` #[inline] fn mod_power_of_2_mul(self, mut other: Natural, pow: u64) -> Natural { other.mod_power_of_2_mul_assign(self, pow); other } } impl ModPowerOf2Mul<&Natural> for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// Both [`Natural`]s are taken by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $xy \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Mul; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_power_of_2_mul(&Natural::from(2u32), 5), /// 6 /// ); /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_mul(&Natural::from(14u32), 4), /// 12 /// ); /// ``` fn mod_power_of_2_mul(self, other: &Natural, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (self, other) { (x, &Natural(Small(y))) => x.mod_power_of_2_mul_limb_ref(y, pow), (&Natural(Small(x)), y) => y.mod_power_of_2_mul_limb_ref(x, pow), (&Natural(Large(ref xs)), &Natural(Large(ref ys))) => { Natural::from_owned_limbs_asc(limbs_mod_power_of_2_mul_ref_ref(xs, ys, pow)) } } } } impl ModPowerOf2MulAssign for Natural { /// Multiplies two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced /// modulo $2^k$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2MulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_power_of_2_mul_assign(Natural::from(2u32), 5); /// assert_eq!(x, 6); /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_mul_assign(Natural::from(14u32), 4); /// assert_eq!(x, 12); /// ``` fn mod_power_of_2_mul_assign(&mut self, mut other: Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, &mut other) { (x, &mut Self(Small(y))) => x.mod_power_of_2_mul_limb_assign(y, pow), (&mut Self(Small(x)), y) => { y.mod_power_of_2_mul_limb_assign(x, pow); *self = other; } (&mut Self(Large(ref mut xs)), &mut Self(Large(ref mut ys))) => { *xs = limbs_mod_power_of_2_mul(xs, ys, pow); self.trim(); } } } } impl<'a> ModPowerOf2MulAssign<&'a Self> for Natural { /// Multiplies two [`Natural`]s modulo $2^k$, in place. The inputs must be already reduced /// modulo $2^k$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x + y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2MulAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_power_of_2_mul_assign(&Natural::from(2u32), 5); /// assert_eq!(x, 6); /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_mul_assign(&Natural::from(14u32), 4); /// assert_eq!(x, 12); /// ``` fn mod_power_of_2_mul_assign(&mut self, other: &'a Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, other) { (x, &Self(Small(y))) => x.mod_power_of_2_mul_limb_assign(y, pow), (&mut Self(Small(x)), y) => { *self = y.mod_power_of_2_mul_limb_ref(x, pow); } (&mut Self(Large(ref mut xs)), &Self(Large(ref ys))) => { *xs = limbs_mod_power_of_2_mul_val_ref(xs, ys, pow); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ ModPowerOf2Neg, ModPowerOf2NegAssign, NegModPowerOf2, NegModPowerOf2Assign, }; use malachite_base::num::logic::traits::SignificantBits; impl ModPowerOf2Neg for Natural { type Output = Self; /// Negates a [`Natural`] modulo $2^k$. The input must be already reduced modulo $2^k$. The /// [`Natural`] is taken by value. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Neg; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_power_of_2_neg(5), 0); /// assert_eq!(Natural::ZERO.mod_power_of_2_neg(100), 0); /// assert_eq!(Natural::from(100u32).mod_power_of_2_neg(8), 156); /// assert_eq!( /// Natural::from(100u32).mod_power_of_2_neg(100).to_string(), /// "1267650600228229401496703205276" /// ); /// ``` #[inline] fn mod_power_of_2_neg(mut self, pow: u64) -> Self { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); self.neg_mod_power_of_2_assign(pow); self } } impl ModPowerOf2Neg for &Natural { type Output = Natural; /// Negates a [`Natural`] modulo $2^k$. The input must be already reduced modulo $2^k$. The /// [`Natural`] is taken by reference. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $-x \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Neg; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).mod_power_of_2_neg(5), 0); /// assert_eq!((&Natural::ZERO).mod_power_of_2_neg(100), 0); /// assert_eq!((&Natural::from(100u32)).mod_power_of_2_neg(8), 156); /// assert_eq!( /// (&Natural::from(100u32)).mod_power_of_2_neg(100).to_string(), /// "1267650600228229401496703205276" /// ); /// ``` #[inline] fn mod_power_of_2_neg(self, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); self.neg_mod_power_of_2(pow) } } impl ModPowerOf2NegAssign for Natural { /// Negates a [`Natural`] modulo $2^k$, in place. The input must be already reduced modulo /// $2^k$. /// /// $x \gets y$, where $x, y < 2^p$ and $-x \equiv y \mod 2^p$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2NegAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::ZERO; /// n.mod_power_of_2_neg_assign(5); /// assert_eq!(n, 0); /// /// let mut n = Natural::ZERO; /// n.mod_power_of_2_neg_assign(100); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(100u32); /// n.mod_power_of_2_neg_assign(8); /// assert_eq!(n, 156); /// /// let mut n = Natural::from(100u32); /// n.mod_power_of_2_neg_assign(100); /// assert_eq!(n.to_string(), "1267650600228229401496703205276"); /// ``` #[inline] fn mod_power_of_2_neg_assign(&mut self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); self.neg_mod_power_of_2_assign(pow); } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2007-2009, 2012, 2015, 2016, 2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::mod_pow::{get_bits, get_window_size}; use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place; use crate::natural::arithmetic::mod_power_of_2_square::limbs_square_low; use crate::natural::arithmetic::mul::mul_low::limbs_mul_low_same_length; use crate::natural::logic::bit_access::limbs_get_bit; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ModPowerOf2Pow, ModPowerOf2PowAssign, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::{SignificantBits, TrailingZeros}; // Raise an n-limb number to a power and return the lowest n limbs of the result. // // # Worst-case complexity // $T(n, m) = O(mn \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `es.len()`. // // This is equivalent to `mpn_powlo` from `mpn/generic/powlo.c`, GMP 6.2.1, where `rp == bp`. // Investigate changes from 6.1.2? pub_crate_test! {limbs_pow_low(xs: &mut [Limb], es: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); assert_ne!(xs_len, 0); let scratch = &mut scratch[..xs_len]; let es_len = es.len(); assert_ne!(es_len, 0); assert_ne!(es[es_len - 1], 0); assert!(es_len > 1 || es_len == 1 && es[0] > 1); let mut bit_index = limbs_significant_bits(es); let window_size = get_window_size(bit_index); assert!(window_size < bit_index); let mut powers = vec![0; xs_len << (window_size - 1)]; let mut powers: Vec<&mut [Limb]> = powers.chunks_mut(xs_len).collect(); powers[0].copy_from_slice(xs); // Store x ^ 2 in scratch. limbs_square_low(scratch, xs); // Precompute odd powers of x and put them in `powers`. for i in 1..usize::power_of_2(window_size - 1) { let (powers_lo, powers_hi) = powers.split_at_mut(i); limbs_mul_low_same_length(powers_hi[0], powers_lo[i - 1], scratch); } let mut exp_bits = get_bits(es, bit_index, window_size); let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits)); bit_index += trailing_zeros; bit_index -= window_size; xs.copy_from_slice(powers[exp_bits >> trailing_zeros >> 1]); while bit_index != 0 { while bit_index != 0 && !limbs_get_bit(es, bit_index - 1) { limbs_square_low(scratch, xs); xs.copy_from_slice(scratch); bit_index -= 1; } if bit_index == 0 { break; } // The next bit of the exponent is 1. Now extract the largest block of bits <= window_size, // and such that the least significant bit is 1. exp_bits = get_bits(es, bit_index, window_size); let mut this_windowsize = window_size; if bit_index < window_size { this_windowsize -= window_size - bit_index; bit_index = 0; } else { bit_index -= window_size; } let trailing_zeros = TrailingZeros::trailing_zeros(Limb::exact_from(exp_bits)); this_windowsize -= trailing_zeros; bit_index += trailing_zeros; while this_windowsize > 1 { limbs_square_low(scratch, xs); limbs_square_low(xs, scratch); this_windowsize -= 2; } if this_windowsize == 1 { limbs_square_low(scratch, xs); } else { scratch.copy_from_slice(xs); } limbs_mul_low_same_length(xs, scratch, powers[exp_bits >> trailing_zeros >> 1]); } }} // Interpreting a `Vec` and a `&[Limb]` as the limbs (in ascending order) of two `Natural`s, // writes the limbs of the first `Natural` raised to the second, mod $2^k$, to the input `Vec`. // Assumes the input is already reduced mod $2^k$. Neither input may be empty or have trailing // zeros, and the exponent must be greater than 1. // // # Worst-case complexity // $T(n, m) = O(mn \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `es.len()`. // // # Panics // Panics if the exponent has trailing zeros or is 1. pub_test! {limbs_mod_power_of_2_pow(xs: &mut Vec, es: &[Limb], pow: u64) { let out_len = bit_to_limb_count_ceiling(pow); xs.resize(out_len, 0); let mut scratch = vec![0; out_len]; limbs_pow_low(xs, es, &mut scratch); limbs_vec_mod_power_of_2_in_place(xs, pow); }} impl ModPowerOf2Pow for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced /// modulo $2^k$. Both [`Natural`]s are taken by value. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_power_of_2_pow(Natural::from(10u32), 8), /// 169 /// ); /// assert_eq!( /// Natural::from(11u32).mod_power_of_2_pow(Natural::from(1000u32), 30), /// 289109473 /// ); /// ``` #[inline] fn mod_power_of_2_pow(mut self, exp: Self, pow: u64) -> Self { self.mod_power_of_2_pow_assign(exp, pow); self } } impl ModPowerOf2Pow<&Self> for Natural { type Output = Self; /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced /// modulo $2^k$. The first [`Natural`] is taken by value and the second by reference. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).mod_power_of_2_pow(&Natural::from(10u32), 8), /// 169 /// ); /// assert_eq!( /// Natural::from(11u32).mod_power_of_2_pow(&Natural::from(1000u32), 30), /// 289109473 /// ); /// ``` #[inline] fn mod_power_of_2_pow(mut self, exp: &Self, pow: u64) -> Self { self.mod_power_of_2_pow_assign(exp, pow); self } } impl ModPowerOf2Pow for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced /// modulo $2^k$. The first [`Natural`] is taken by reference and the second by value. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_power_of_2_pow(Natural::from(10u32), 8), /// 169 /// ); /// assert_eq!( /// (&Natural::from(11u32)).mod_power_of_2_pow(Natural::from(1000u32), 30), /// 289109473 /// ); /// ``` #[inline] fn mod_power_of_2_pow(self, exp: Natural, pow: u64) -> Natural { self.mod_power_of_2_pow(&exp, pow) } } impl ModPowerOf2Pow<&Natural> for &Natural { type Output = Natural; /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$. The base must be already reduced /// modulo $2^k$. Both [`Natural`]s are taken by reference. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).mod_power_of_2_pow(&Natural::from(10u32), 8), /// 169 /// ); /// assert_eq!( /// (&Natural::from(11u32)).mod_power_of_2_pow(&Natural::from(1000u32), 30), /// 289109473 /// ); /// ``` #[inline] fn mod_power_of_2_pow(self, exp: &Natural, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match (self, exp) { _ if pow == 0 => Natural::ZERO, (_, &Natural::ZERO) => Natural::ONE, (&Natural::ZERO | &Natural::ONE, _) | (_, &Natural::ONE) => self.clone(), (Natural(Small(x)), Natural(Small(e))) if pow <= Limb::WIDTH && u64::convertible_from(*e) => { Natural(Small(x.mod_power_of_2_pow(u64::wrapping_from(*e), pow))) } (_, Natural(Small(e))) => { let mut xs = self.to_limbs_asc(); limbs_mod_power_of_2_pow(&mut xs, &[*e], pow); Natural::from_owned_limbs_asc(xs) } (_, Natural(Large(es))) => { let mut xs = self.to_limbs_asc(); limbs_mod_power_of_2_pow(&mut xs, es, pow); Natural::from_owned_limbs_asc(xs) } } } } impl ModPowerOf2PowAssign for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$, in place. The base must be already /// reduced modulo $2^k$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_power_of_2_pow_assign(Natural::from(10u32), 8); /// assert_eq!(x, 169); /// /// let mut x = Natural::from(11u32); /// x.mod_power_of_2_pow_assign(Natural::from(1000u32), 30); /// assert_eq!(x, 289109473); /// ``` #[inline] fn mod_power_of_2_pow_assign(&mut self, exp: Self, pow: u64) { self.mod_power_of_2_pow_assign(&exp, pow); } } impl ModPowerOf2PowAssign<&Self> for Natural { /// Raises a [`Natural`] to a [`Natural`] power modulo $2^k$, in place. The base must be already /// reduced modulo $2^k$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < 2^k$ and $x^n \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `pow`, and $m$ is /// `exp.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2PowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.mod_power_of_2_pow_assign(&Natural::from(10u32), 8); /// assert_eq!(x, 169); /// /// let mut x = Natural::from(11u32); /// x.mod_power_of_2_pow_assign(&Natural::from(1000u32), 30); /// assert_eq!(x, 289109473); /// ``` fn mod_power_of_2_pow_assign(&mut self, exp: &Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match (&mut *self, exp) { _ if pow == 0 => *self = Self::ZERO, (_, &Self::ZERO) => *self = Self::ONE, (&mut (Self::ZERO | Self::ONE), _) | (_, &Self::ONE) => {} (Self(Small(x)), Self(Small(e))) if pow <= Limb::WIDTH && u64::convertible_from(*e) => { x.mod_power_of_2_pow_assign(u64::wrapping_from(*e), pow); } (_, Self(Small(e))) => { let xs = self.promote_in_place(); limbs_mod_power_of_2_pow(xs, &[*e], pow); self.trim(); } (_, Self(Large(es))) => { let xs = self.promote_in_place(); limbs_mod_power_of_2_pow(xs, es, pow); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::ops::{Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Assign, ModPowerOf2Shl, ModPowerOf2ShlAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; fn mod_power_of_2_shl_unsigned_nz(x: &Natural, bits: T, pow: u64) -> Natural where u64: ExactFrom, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let bits = u64::exact_from(bits); if bits >= pow { Natural::ZERO } else { x.mod_power_of_2(pow - bits) << bits } } fn mod_power_of_2_shl_assign_unsigned_nz(x: &mut Natural, bits: T, pow: u64) where u64: ExactFrom, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); let bits = u64::exact_from(bits); if bits >= pow { *x = Natural::ZERO; } else { x.mod_power_of_2_assign(pow - bits); *x <<= bits; } } macro_rules! impl_mod_power_of_2_shl_unsigned { ($t:ident) => { impl ModPowerOf2Shl<$t> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by value. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $2^nx \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(mut self, bits: $t, pow: u64) -> Natural { self.mod_power_of_2_shl_assign(bits, pow); self } } impl ModPowerOf2Shl<$t> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by /// reference. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $2^nx \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(self, bits: $t, pow: u64) -> Natural { mod_power_of_2_shl_unsigned_nz(self, bits, pow) } } impl ModPowerOf2ShlAssign<$t> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$, in place. /// The [`Natural`] must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $2^nx \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl_assign). #[inline] fn mod_power_of_2_shl_assign(&mut self, bits: $t, pow: u64) { mod_power_of_2_shl_assign_unsigned_nz(self, bits, pow); } } }; } apply_to_unsigneds!(impl_mod_power_of_2_shl_unsigned); fn mod_power_of_2_shl_signed_nz<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, pow: u64, ) -> Natural where &'a Natural: ModPowerOf2Shl + Shr, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if bits >= S::ZERO { x.mod_power_of_2_shl(bits.unsigned_abs(), pow) } else { x >> bits.unsigned_abs() } } fn mod_power_of_2_shl_assign_signed_nz>( x: &mut Natural, bits: S, pow: u64, ) where Natural: ModPowerOf2ShlAssign + ShrAssign, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if bits >= S::ZERO { x.mod_power_of_2_shl_assign(bits.unsigned_abs(), pow); } else { *x >>= bits.unsigned_abs(); } } macro_rules! impl_mod_power_of_2_shl_signed { ($t:ident) => { impl ModPowerOf2Shl<$t> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by value. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^nx \rfloor \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(mut self, bits: $t, pow: u64) -> Natural { self.mod_power_of_2_shl_assign(bits, pow); self } } impl ModPowerOf2Shl<$t> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by /// reference. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^nx \rfloor \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl). #[inline] fn mod_power_of_2_shl(self, bits: $t, pow: u64) -> Natural { mod_power_of_2_shl_signed_nz(self, bits, pow) } } impl ModPowerOf2ShlAssign<$t> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo $2^k$, in place. /// The [`Natural`] must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $\lfloor 2^nx \rfloor \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shl#mod_power_of_2_shl_assign). #[inline] fn mod_power_of_2_shl_assign(&mut self, bits: $t, pow: u64) { mod_power_of_2_shl_assign_signed_nz(self, bits, pow) } } }; } apply_to_signeds!(impl_mod_power_of_2_shl_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::ops::{Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, ModPowerOf2ShrAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::logic::traits::SignificantBits; fn mod_power_of_2_shr_ref<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, pow: u64, ) -> Natural where &'a Natural: ModPowerOf2Shl + Shr, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if bits >= S::ZERO { x >> bits.unsigned_abs() } else { x.mod_power_of_2_shl(bits.unsigned_abs(), pow) } } fn mod_power_of_2_shr_assign>( x: &mut Natural, bits: S, pow: u64, ) where Natural: ModPowerOf2ShlAssign + ShrAssign, { assert!( x.significant_bits() <= pow, "x must be reduced mod 2^pow, but {x} >= 2^{pow}" ); if bits >= S::ZERO { *x >>= bits.unsigned_abs(); } else { x.mod_power_of_2_shl_assign(bits.unsigned_abs(), pow); } } macro_rules! impl_mod_power_of_2_shr_signed { ($t:ident) => { impl ModPowerOf2Shr<$t> for Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by value. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod /// 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr). #[inline] fn mod_power_of_2_shr(mut self, bits: $t, pow: u64) -> Natural { self.mod_power_of_2_shr_assign(bits, pow); self } } impl ModPowerOf2Shr<$t> for &Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$. The /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by /// reference. /// /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod /// 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr). #[inline] fn mod_power_of_2_shr(self, bits: $t, pow: u64) -> Natural { mod_power_of_2_shr_ref(self, bits, pow) } } impl ModPowerOf2ShrAssign<$t> for Natural { /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$, in place. The /// [`Natural`] must be already reduced modulo $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr_assign). #[inline] fn mod_power_of_2_shr_assign(&mut self, bits: $t, pow: u64) { mod_power_of_2_shr_assign(self, bits, pow); } } }; } apply_to_signeds!(impl_mod_power_of_2_shr_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-1994, 1996, 1997, 2000-2005, 2008, 2009, 2010, 2011, 2012, 2015 Free // Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_same_length_in_place_left; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::limbs_mul_greater_to_out_basecase; use crate::natural::arithmetic::mul::mul_low::{ limbs_mul_low_same_length, limbs_mul_low_same_length_basecase, }; use crate::natural::arithmetic::mul::toom::{TUNE_PROGRAM_BUILD, WANT_FAT_BINARY}; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::square::{ limbs_square, limbs_square_diagonal, limbs_square_to_out, limbs_square_to_out_basecase, limbs_square_to_out_scratch_len, }; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::{ DoubleLimb, Limb, MULLO_BASECASE_THRESHOLD, MULLO_DC_THRESHOLD, SQR_TOOM2_THRESHOLD, SQR_TOOM3_THRESHOLD, SQR_TOOM4_THRESHOLD, SQR_TOOM8_THRESHOLD, SQRLO_DC_THRESHOLD, }; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ ModPowerOf2Square, ModPowerOf2SquareAssign, Parity, Square, WrappingSquare, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::num::logic::traits::SignificantBits; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `MPN_SQRLO_DIAGONAL` from `mpn/generic/sqrlo_basecase.c`, GMP 6.2.1. fn limbs_square_low_diagonal(out: &mut [Limb], xs: &[Limb]) { let n = xs.len(); let half_n = n >> 1; limbs_square_diagonal(out, &xs[..half_n]); if n.odd() { out[n - 1] = xs[half_n].wrapping_square(); } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `MPN_SQRLO_DIAG_ADDLSH1` from `mpn/generic/sqrlo_basecase.c`, GMP 6.2.1. pub_test! {limbs_square_diagonal_shl_add(out: &mut [Limb], scratch: &mut [Limb], xs: &[Limb]) { let n = xs.len(); assert_eq!(scratch.len(), n - 1); assert_eq!(out.len(), n); limbs_square_low_diagonal(out, xs); limbs_slice_shl_in_place(scratch, 1); limbs_slice_add_same_length_in_place_left(&mut out[1..], scratch); }} // TODO tune #[cfg(feature = "test_build")] pub const SQRLO_DC_THRESHOLD_LIMIT: usize = 500; #[cfg(not(feature = "test_build"))] const SQRLO_DC_THRESHOLD_LIMIT: usize = 500; // TODO tune const SQRLO_BASECASE_ALLOC: usize = if SQRLO_DC_THRESHOLD_LIMIT < 2 { 1 } else { SQRLO_DC_THRESHOLD_LIMIT - 1 }; // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sqrlo_basecase` from `mpn/generic/sqrlo_basecase.c`, GMP 6.2.1. pub_test! {limbs_square_low_basecase(out: &mut [Limb], xs: &[Limb]) { let n = xs.len(); let out = &mut out[..n]; assert_ne!(n, 0); let xs_0 = xs[0]; match n { 1 => out[0] = xs_0.wrapping_square(), 2 => { let p_hi; (p_hi, out[0]) = DoubleLimb::from(xs_0).square().split_in_half(); out[1] = (xs_0.wrapping_mul(xs[1]) << 1).wrapping_add(p_hi); } _ => { let scratch = &mut [0; SQRLO_BASECASE_ALLOC]; // must fit n - 1 limbs in scratch assert!(n <= SQRLO_DC_THRESHOLD_LIMIT); let scratch = &mut scratch[..n - 1]; limbs_mul_limb_to_out::(scratch, &xs[1..], xs_0); for i in 1.. { let two_i = i << 1; if two_i >= n - 1 { break; } limbs_slice_add_mul_limb_same_length_in_place_left( &mut scratch[two_i..], &xs[i + 1..n - i], xs[i], ); } limbs_square_diagonal_shl_add(out, scratch, xs); } } }} // TODO tune const SQRLO_BASECASE_THRESHOLD: usize = 8; // TODO tune /// This is equivalent to `MAYBE_range_basecase` from `mpn/generic/sqrlo.c`, GMP 6.2.1. Investigate /// changes from 6.1.2? const MAYBE_RANGE_BASECASE_MOD_SQUARE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || (if SQRLO_DC_THRESHOLD == 0 { SQRLO_BASECASE_THRESHOLD } else { SQRLO_DC_THRESHOLD }) < SQR_TOOM2_THRESHOLD * 36 / (36 - 11); // TODO tune /// This is equivalent to `MAYBE_range_toom22` from `mpn/generic/sqrlo.c`, GMP 6.2.1. Investigate /// changes from 6.1.2? const MAYBE_RANGE_TOOM22_MOD_SQUARE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || (if SQRLO_DC_THRESHOLD == 0 { SQRLO_BASECASE_THRESHOLD } else { SQRLO_DC_THRESHOLD }) < SQR_TOOM3_THRESHOLD * 36 / (36 - 11); // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_sqrlo_itch` from `mpn/generic/sqrlo.c`, GMP 6.2.1. Investigate changes // from 6.1.2? pub_const_test! {limbs_square_low_scratch_len(len: usize) -> usize { len << 1 }} // Requires a scratch space of 2 * `xs.len()` limbs at `scratch`. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_sqrlo` from `mpn/generic/sqrlo.c`, GMP 6.2.1. Investigate changes // from 6.1.2? pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_square_low_divide_and_conquer( out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb] ) { let len = xs.len(); let out = &mut out[..len]; assert!(len > 1); // We need a fractional approximation of the value 0 < a <= 1/2, giving the minimum in the // function k = (1 - a) ^ e / (1 - 2 * a ^ e). let len_small = if MAYBE_RANGE_BASECASE_MOD_SQUARE && len < SQR_TOOM2_THRESHOLD * 36 / (36 - 11) { len >> 1 } else if MAYBE_RANGE_TOOM22_MOD_SQUARE && len < SQR_TOOM3_THRESHOLD * 36 / (36 - 11) { len * 11 / 36 // n1 ~= n*(1-.694...) } else if len < SQR_TOOM4_THRESHOLD * 40 / (40 - 9) { len * 9 / 40 // n1 ~= n*(1-.775...) } else if len < SQR_TOOM8_THRESHOLD * 10 / 9 { len * 7 / 39 // n1 ~= n*(1-.821...) } else { len / 10 // n1 ~= n*(1-.899...) [TOOM88] }; let len_big = len - len_small; // x0 ^ 2 let (xs_lo, xs_hi) = xs.split_at(len_big); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs_lo.len())]; limbs_square_to_out(scratch, xs_lo, &mut square_scratch); let xs_lo = &xs_lo[..len_small]; let (out_lo, out_hi) = out.split_at_mut(len_big); let (scratch_lo, scratch_hi) = scratch.split_at_mut(len); out_lo.copy_from_slice(&scratch_lo[..len_big]); // x1 * x0 * 2^(n2 Limb::WIDTH) if len_small < MULLO_BASECASE_THRESHOLD { limbs_mul_greater_to_out_basecase(scratch_hi, xs_hi, xs_lo); } else if len_small < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(scratch_hi, xs_hi, xs_lo); } else { limbs_mul_low_same_length(scratch_hi, xs_hi, xs_lo); } limbs_shl_to_out(out_hi, &scratch_hi[..len_small], 1); limbs_slice_add_same_length_in_place_left(out_hi, &scratch_lo[len_big..]); }} // TODO tune // must be at least SQRLO_BASECASE_THRESHOLD const SQRLO_BASECASE_THRESHOLD_LIMIT: usize = 8; // TODO tune const SQRLO_SQR_THRESHOLD: usize = 6440; // TODO tune const SQR_BASECASE_ALLOC: usize = if SQRLO_BASECASE_THRESHOLD_LIMIT == 0 { 1 } else { SQRLO_BASECASE_THRESHOLD_LIMIT << 1 }; // Square an n-limb number and return the lowest n limbs of the result. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sqrlo` from `mpn/generic/sqrlo.c`, GMP 6.2.1. Investigate changes from // 6.1.2? pub_crate_test! {limbs_square_low(out: &mut [Limb], xs: &[Limb]) { assert!(SQRLO_BASECASE_THRESHOLD_LIMIT >= SQRLO_BASECASE_THRESHOLD); let len = xs.len(); assert_ne!(len, 0); let out = &mut out[..len]; if len < SQRLO_BASECASE_THRESHOLD { // Allocate workspace of fixed size on stack: fast! let scratch = &mut [0; SQR_BASECASE_ALLOC]; limbs_square_to_out_basecase(scratch, xs); out.copy_from_slice(&scratch[..len]); } else if len < SQRLO_DC_THRESHOLD { limbs_square_low_basecase(out, xs); } else { let mut scratch = vec![0; limbs_square_low_scratch_len(len)]; if len < SQRLO_SQR_THRESHOLD { limbs_square_low_divide_and_conquer(out, xs, &mut scratch); } else { // For really large operands, use plain mpn_mul_n but throw away upper n limbs of the // result. let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())]; limbs_square_to_out(&mut scratch, xs, &mut square_scratch); out.copy_from_slice(&scratch[..len]); } } }} // Interpreting a `Vec` as the limbs (in ascending order) of a `Natural`, returns a `Vec` of // the limbs of the square of the `Natural` mod `2 ^ pow`. Assumes the input is already reduced mod // `2 ^ pow`. The input `Vec` may be mutated. The input may not be empty or have trailing zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if the input is empty. May panic if the input has trailing zeros. pub_crate_test! {limbs_mod_power_of_2_square(xs: &mut Vec, pow: u64) -> Vec { let len = xs.len(); assert_ne!(len, 0); let max_len = bit_to_limb_count_ceiling(pow); if max_len > len << 1 { return limbs_square(xs); } // Should really be max_len / sqrt(2); 0.75 * max_len is close enough let limit = max_len.checked_mul(3).unwrap() >> 2; let mut square = if len >= limit { if len != max_len { xs.resize(max_len, 0); } let mut square_limbs = vec![0; max_len]; limbs_square_low(&mut square_limbs, xs); square_limbs } else { limbs_square(xs) }; limbs_vec_mod_power_of_2_in_place(&mut square, pow); square }} // Interpreting a slice of `Limb` as the limbs (in ascending order) of a `Natural`, returns a `Vec` // of the limbs of the square of the `Natural` mod `2 ^ pow`. Assumes the input is already reduced // mod `2 ^ pow`. The input may not be empty or have trailing zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if the input is empty. May panic if the input has trailing zeros. pub_crate_test! {limbs_mod_power_of_2_square_ref(xs: &[Limb], pow: u64) -> Vec { let len = xs.len(); assert_ne!(len, 0); let max_len = bit_to_limb_count_ceiling(pow); if max_len > len << 1 { return limbs_square(xs); } // Should really be max_len / sqrt(2); 0.75 * max_len is close enough let limit = max_len.checked_mul(3).unwrap() >> 2; let mut square = if len >= limit { let mut xs_adjusted_vec; let xs_adjusted = if len == max_len { xs } else { xs_adjusted_vec = vec![0; max_len]; xs_adjusted_vec[..len].copy_from_slice(xs); &xs_adjusted_vec }; let mut square = vec![0; max_len]; limbs_square_low(&mut square, xs_adjusted); square } else { limbs_square(xs) }; limbs_vec_mod_power_of_2_in_place(&mut square, pow); square }} impl ModPowerOf2Square for Natural { type Output = Self; /// Squares a [`Natural`] modulo $2^k$. The input must be already reduced modulo $2^k$. The /// [`Natural`] is taken by value. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $x^2 \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModPowerOf2Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.mod_power_of_2_square(2), 0); /// assert_eq!(Natural::from(5u32).mod_power_of_2_square(3), 1); /// assert_eq!( /// Natural::from_str("12345678987654321") /// .unwrap() /// .mod_power_of_2_square(64) /// .to_string(), /// "16556040056090124897" /// ); /// ``` #[inline] fn mod_power_of_2_square(mut self, pow: u64) -> Self { self.mod_power_of_2_square_assign(pow); self } } impl ModPowerOf2Square for &Natural { type Output = Natural; /// Squares a [`Natural`] modulo $2^k$. The input must be already reduced modulo $2^k$. The /// [`Natural`] is taken by reference. /// /// $f(x, k) = y$, where $x, y < 2^k$ and $x^2 \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModPowerOf2Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).mod_power_of_2_square(2), 0); /// assert_eq!((&Natural::from(5u32)).mod_power_of_2_square(3), 1); /// assert_eq!( /// (&Natural::from_str("12345678987654321").unwrap()) /// .mod_power_of_2_square(64) /// .to_string(), /// "16556040056090124897" /// ); /// ``` #[inline] fn mod_power_of_2_square(self, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match self { &Natural::ZERO => Natural::ZERO, Natural(Small(x)) if pow <= Limb::WIDTH => Natural(Small(x.mod_power_of_2_square(pow))), Natural(Small(x)) => { let x_double = DoubleLimb::from(*x); Natural::from(if pow <= Limb::WIDTH << 1 { x_double.mod_power_of_2_square(pow) } else { x_double.square() }) } Natural(Large(xs)) => { Natural::from_owned_limbs_asc(limbs_mod_power_of_2_square_ref(xs, pow)) } } } } impl ModPowerOf2SquareAssign for Natural { /// Squares a [`Natural`] modulo $2^k$, in place. The input must be already reduced modulo /// $2^k$. /// /// $x \gets y$, where $x, y < 2^k$ and $x^2 \equiv y \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` is greater than or equal to $2^k$. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::ModPowerOf2SquareAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::ZERO; /// n.mod_power_of_2_square_assign(2); /// assert_eq!(n, 0); /// /// let mut n = Natural::from(5u32); /// n.mod_power_of_2_square_assign(3); /// assert_eq!(n, 1); /// /// let mut n = Natural::from_str("12345678987654321").unwrap(); /// n.mod_power_of_2_square_assign(64); /// assert_eq!(n.to_string(), "16556040056090124897"); /// ``` #[inline] fn mod_power_of_2_square_assign(&mut self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); match self { &mut Self::ZERO => {} Self(Small(x)) if pow <= Limb::WIDTH => x.mod_power_of_2_square_assign(pow), Self(Small(x)) => { let x_double = DoubleLimb::from(*x); *self = Self::from(if pow <= Limb::WIDTH << 1 { x_double.mod_power_of_2_square(pow) } else { x_double.square() }); } Self(Large(xs)) => { *xs = limbs_mod_power_of_2_square(xs, pow); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 crate::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place; use crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::mod_power_of_2::{ limbs_neg_mod_power_of_2, limbs_neg_mod_power_of_2_in_place, limbs_slice_mod_power_of_2_in_place, }; use crate::natural::arithmetic::mod_power_of_2_add::limbs_vec_mod_power_of_2_add_limb_in_place; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_right, limbs_vec_sub_in_place_right, }; use crate::natural::logic::low_mask::limbs_low_mask; use crate::natural::logic::not::limbs_not_in_place; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use alloc::vec::Vec; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ ModPowerOf2Neg, ModPowerOf2NegAssign, ModPowerOf2Sub, ModPowerOf2SubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::SignificantBits; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. fn extend_with_ones(xs: &mut Vec, pow: u64) { xs.resize(bit_to_limb_count_ceiling(pow), Limb::MAX); } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, subtracts the // `Natural` from a `Limb`, mod `2 ^ pow`. Assumes the input is already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if `pow` is zero. pub_test! {limbs_mod_power_of_2_limb_sub_limbs(x: Limb, ys: &[Limb], pow: u64) -> Vec { let mut diff = limbs_neg_mod_power_of_2(ys, pow); limbs_vec_mod_power_of_2_add_limb_in_place(&mut diff, x, pow); diff }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, subtracts the // `Natural` from a `Limb`, mod `2 ^ pow`, and writes the limbs of the difference to the input // slice. Assumes the input is already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. // // # Panics // Panics if `pow` is zero. pub_test! {limbs_mod_power_of_2_limb_sub_limbs_in_place(x: Limb, ys: &mut Vec, pow: u64) { limbs_neg_mod_power_of_2_in_place(ys, pow); limbs_vec_mod_power_of_2_add_limb_in_place(ys, x, pow); }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, subtracts // the second `Natural` from the first, mod `2 ^ pow`, and returns a `Vec` of the limbs of the // difference. Assumes the inputs are already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. pub_test! {limbs_mod_power_of_2_sub(xs: &[Limb], ys: &[Limb], pow: u64) -> Vec { let ys_len = ys.len(); let mut out_limbs = xs.to_vec(); if ys_len > xs.len() { out_limbs.resize(ys_len, 0); } if limbs_sub_greater_in_place_left(&mut out_limbs, ys) { extend_with_ones(&mut out_limbs, pow); limbs_slice_mod_power_of_2_in_place(&mut out_limbs, pow); } out_limbs }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, subtracts // the second `Natural` from the first, mod `2 ^ pow`, and writes the limbs of the difference to the // first (left) slice. Assumes the inputs are already reduced mod `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. pub_test! {limbs_mod_power_of_2_sub_in_place_left(xs: &mut Vec, ys: &[Limb], pow: u64) { let ys_len = ys.len(); if ys_len > xs.len() { xs.resize(ys_len, 0); } if limbs_sub_greater_in_place_left(xs, ys) { extend_with_ones(xs, pow); limbs_slice_mod_power_of_2_in_place(xs, pow); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, subtracts // the second `Natural` from the first, mod `2 ^ pow`, and writes the limbs of the difference to the // second (right) slice. Assumes the inputs are already reduced mod `2 ^ pow`. // // Neither input slice may have trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. pub_test! {limbs_mod_power_of_2_sub_in_place_right(xs: &[Limb], ys: &mut Vec, pow: u64) { let xs_len = xs.len(); if xs_len >= ys.len() { if limbs_vec_sub_in_place_right(xs, ys) { extend_with_ones(ys, pow); limbs_slice_mod_power_of_2_in_place(ys, pow); } } else { let (ys_lo, ys_hi) = ys.split_at_mut(xs_len); if limbs_sub_same_length_in_place_right(xs, ys_lo) { limbs_not_in_place(ys_hi); } else { limbs_twos_complement_in_place(ys_hi); } extend_with_ones(ys, pow); limbs_slice_mod_power_of_2_in_place(ys, pow); } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, subtracts // the second `Natural` from the first, mod `2 ^ pow`, and writes the limbs of the difference to to // the longer slice (or the first one, if they are equally long). Returns a `bool` which is `false` // when the output is to the first `Vec` and `true` when it's to the second `Vec`. Assumes the // inputs are already reduced mod `2 ^ pow`. // // Neither input slice may have trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `pow`. pub_test! {limbs_mod_power_of_2_sub_in_place_either( xs: &mut Vec, ys: &mut Vec, pow: u64, ) -> bool { if xs.len() >= ys.len() { limbs_mod_power_of_2_sub_in_place_left(xs, ys, pow); false } else { limbs_mod_power_of_2_sub_in_place_right(xs, ys, pow); true } }} impl Natural { fn mod_power_of_2_sub_limb_ref(&self, y: Limb, pow: u64) -> Self { match (self, y, pow) { (x, 0, _) => x.clone(), (&Self::ZERO, _, _) => Self(Small(y)).mod_power_of_2_neg(pow), (&Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { Self(Small(small.mod_power_of_2_sub(other, pow))) } (&Self(Small(small)), other, _) => { let (diff, overflow) = small.overflowing_sub(other); if overflow { let mut out = limbs_low_mask(pow); out[0] = diff; Self(Large(out)) } else { Self(Small(diff)) } } (Self(Large(limbs)), other, _) => { Self::from_owned_limbs_asc(limbs_sub_limb(limbs, other).0) } } } // other - self fn mod_power_of_2_right_sub_limb_ref(&self, y: Limb, pow: u64) -> Self { match (self, y, pow) { (_, 0, _) => self.mod_power_of_2_neg(pow), (&Self::ZERO, _, _) => Self(Small(y)), (&Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { Self(Small(other.mod_power_of_2_sub(small, pow))) } (&Self(Small(small)), other, _) => { let (diff, overflow) = other.overflowing_sub(small); if overflow { let mut out = limbs_low_mask(pow); out[0] = diff; Self(Large(out)) } else { Self(Small(diff)) } } (Self(Large(limbs)), other, _) => { Self::from_owned_limbs_asc(limbs_mod_power_of_2_limb_sub_limbs(other, limbs, pow)) } } } fn mod_power_of_2_sub_assign_limb(&mut self, y: Limb, pow: u64) { match (&mut *self, y, pow) { (_, 0, _) => {} (&mut Self::ZERO, _, _) => *self = Self(Small(y)).mod_power_of_2_neg(pow), (Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { small.mod_power_of_2_sub_assign(other, pow); } (Self(Small(small)), other, _) => { let (diff, overflow) = small.overflowing_sub(other); if overflow { let mut out = limbs_low_mask(pow); out[0] = diff; *self = Self(Large(out)); } else { *small = diff; } } (Self(Large(limbs)), other, _) => { limbs_sub_limb_in_place(limbs, other); self.trim(); } } } // other -= self fn mod_power_of_2_right_sub_assign_limb(&mut self, other: Limb, pow: u64) { match (&mut *self, other, pow) { (_, 0, _) => self.mod_power_of_2_neg_assign(pow), (&mut Self::ZERO, _, _) => *self = Self(Small(other)), (Self(Small(small)), other, pow) if pow <= Limb::WIDTH => { *small = other.mod_power_of_2_sub(*small, pow); } (Self(Small(small)), other, _) => { let (diff, overflow) = other.overflowing_sub(*small); if overflow { let mut out = limbs_low_mask(pow); out[0] = diff; *self = Self(Large(out)); } else { *small = diff; } } (Self(Large(limbs)), other, _) => { limbs_mod_power_of_2_limb_sub_limbs_in_place(other, limbs, pow); self.trim(); } } } } impl ModPowerOf2Sub for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// Both [`Natural`]s are taken by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Sub; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(10u32).mod_power_of_2_sub(Natural::TWO, 4), 8); /// assert_eq!( /// Natural::from(56u32).mod_power_of_2_sub(Natural::from(123u32), 9), /// 445 /// ); /// ``` fn mod_power_of_2_sub(mut self, other: Self, pow: u64) -> Self { self.mod_power_of_2_sub_assign(other, pow); self } } impl ModPowerOf2Sub<&Self> for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// The first [`Natural`] is taken by value and the second by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Sub; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(10u32).mod_power_of_2_sub(&Natural::TWO, 4), 8); /// assert_eq!( /// Natural::from(56u32).mod_power_of_2_sub(&Natural::from(123u32), 9), /// 445 /// ); /// ``` #[inline] fn mod_power_of_2_sub(mut self, other: &Self, pow: u64) -> Self { self.mod_power_of_2_sub_assign(other, pow); self } } impl ModPowerOf2Sub for &Natural { type Output = Natural; /// Subtracts two [`Natural`]s modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// The first [`Natural`] is taken by reference and the second by value. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Sub; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_sub(Natural::TWO, 4), /// 8 /// ); /// assert_eq!( /// (&Natural::from(56u32)).mod_power_of_2_sub(Natural::from(123u32), 9), /// 445 /// ); /// ``` #[inline] fn mod_power_of_2_sub(self, mut other: Natural, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (self, &mut other) { (x, Natural(Small(y))) => x.mod_power_of_2_sub_limb_ref(*y, pow), (&Natural(Small(x)), y) => { y.mod_power_of_2_right_sub_assign_limb(x, pow); other } (Natural(Large(xs)), Natural(Large(ys))) => { limbs_mod_power_of_2_sub_in_place_right(xs, ys, pow); other.trim(); other } } } } impl ModPowerOf2Sub<&Natural> for &Natural { type Output = Natural; /// Subtracts two [`Natural`] modulo $2^k$. The inputs must be already reduced modulo $2^k$. /// Both [`Natural`]s are taken by reference. /// /// $f(x, y, k) = z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2Sub; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)).mod_power_of_2_sub(&Natural::TWO, 4), /// 8 /// ); /// assert_eq!( /// (&Natural::from(56u32)).mod_power_of_2_sub(&Natural::from(123u32), 9), /// 445 /// ); /// ``` fn mod_power_of_2_sub(self, other: &Natural, pow: u64) -> Natural { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (self, other) { (x, y) if core::ptr::eq(x, y) => Natural::ZERO, (x, &Natural(Small(y))) => x.mod_power_of_2_sub_limb_ref(y, pow), (&Natural(Small(x)), y) => y.mod_power_of_2_right_sub_limb_ref(x, pow), (Natural(Large(xs)), Natural(Large(ys))) => { Natural::from_owned_limbs_asc(limbs_mod_power_of_2_sub(xs, ys, pow)) } } } } impl ModPowerOf2SubAssign for Natural { /// Subtracts two [`Natural`] modulo $2^k$, in place. The inputs must be already reduced modulo /// $2^k$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2SubAssign; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_sub_assign(Natural::TWO, 4); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(56u32); /// x.mod_power_of_2_sub_assign(Natural::from(123u32), 9); /// assert_eq!(x, 445); /// ``` fn mod_power_of_2_sub_assign(&mut self, mut other: Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, &mut other) { (x, &mut Self(Small(y))) => x.mod_power_of_2_sub_assign_limb(y, pow), (&mut Self(Small(x)), y) => { y.mod_power_of_2_right_sub_assign_limb(x, pow); *self = other; } (Self(Large(xs)), Self(Large(ys))) => { if limbs_mod_power_of_2_sub_in_place_either(xs, ys, pow) { swap(xs, ys); } self.trim(); } } } } impl<'a> ModPowerOf2SubAssign<&'a Self> for Natural { /// Subtracts two [`Natural`] modulo $2^k$, in place. The inputs must be already reduced modulo /// $2^k$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets z$, where $x, y, z < 2^k$ and $x - y \equiv z \mod 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to $2^k$. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModPowerOf2SubAssign; /// use malachite_base::num::basic::traits::Two; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32); /// x.mod_power_of_2_sub_assign(&Natural::TWO, 4); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(56u32); /// x.mod_power_of_2_sub_assign(&Natural::from(123u32), 9); /// assert_eq!(x, 445); /// ``` fn mod_power_of_2_sub_assign(&mut self, other: &'a Self, pow: u64) { assert!( self.significant_bits() <= pow, "self must be reduced mod 2^pow, but {self} >= 2^{pow}" ); assert!( other.significant_bits() <= pow, "other must be reduced mod 2^pow, but {other} >= 2^{pow}" ); match (&mut *self, other) { (x, y) if core::ptr::eq(x, y) => *self = Self::ZERO, (x, &Self(Small(y))) => x.mod_power_of_2_sub_assign_limb(y, pow), (&mut Self(Small(x)), y) => *self = y.mod_power_of_2_right_sub_limb_ref(x, pow), (Self(Large(xs)), Self(Large(ys))) => { limbs_mod_power_of_2_sub_in_place_left(xs, ys, pow); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::*; use core::ops::{Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ ModMul, ModMulAssign, ModPow, ModShl, ModShlAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; fn mod_shl_ref_val_unsigned(x: &Natural, bits: T, m: Natural) -> Natural where Natural: From, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); if bits == T::ZERO { x.clone() } else { match m { Natural::ONE | Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits), &m), m), } } } fn mod_shl_ref_ref_unsigned(x: &Natural, bits: T, m: &Natural) -> Natural where Natural: From, { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); if bits == T::ZERO { x.clone() } else { match m { &Natural::ONE | &Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits), m), m), } } } fn mod_shl_assign_unsigned_nz(x: &mut Natural, bits: T, m: Natural) where Natural: From, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); if bits != T::ZERO { match m { Natural::ONE | Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits), &m), m), } } } fn mod_shl_assign_ref_unsigned(x: &mut Natural, bits: T, m: &Natural) where Natural: From, { assert!(*x < *m, "x must be reduced mod m, but {x} >= {m}"); if bits != T::ZERO { match m { &Natural::ONE | &Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits), m), m), } } } macro_rules! impl_mod_shl_unsigned { ($t:ident) => { impl ModShl<$t, Natural> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(mut self, bits: $t, m: Natural) -> Natural { self.mod_shl_assign(bits, m); self } } impl<'a> ModShl<$t, &'a Natural> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by value and the second by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(mut self, bits: $t, m: &'a Natural) -> Natural { self.mod_shl_assign(bits, m); self } } impl ModShl<$t, Natural> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by reference and the second by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, bits: $t, m: Natural) -> Natural { mod_shl_ref_val_unsigned(self, bits, m) } } impl ModShl<$t, &Natural> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, bits: $t, m: &Natural) -> Natural { mod_shl_ref_ref_unsigned(self, bits, m) } } impl ModShlAssign<$t, Natural> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, bits: $t, m: Natural) { mod_shl_assign_unsigned_nz(self, bits, m); } } impl ModShlAssign<$t, &Natural> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < m$ and $2^nx \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, bits: $t, m: &Natural) { mod_shl_assign_ref_unsigned(self, bits, m); } } }; } apply_to_unsigneds!(impl_mod_shl_unsigned); fn mod_shl_ref_val_signed<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, m: Natural, ) -> Natural where Natural: From, &'a Natural: Shr, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => x.clone(), Less => x >> bits_abs, Greater => match m { Natural::ONE | Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits_abs), &m), m), }, } } fn mod_shl_ref_ref_signed<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, m: &Natural, ) -> Natural where Natural: From, &'a Natural: Shr, { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => x.clone(), Less => x >> bits_abs, Greater => match m { &Natural::ONE | &Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits_abs), m), m), }, } } fn mod_shl_assign_signed_nz>( x: &mut Natural, bits: S, m: Natural, ) where Natural: From + ShrAssign, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => {} Less => *x >>= bits_abs, Greater => match m { Natural::ONE | Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits_abs), &m), m), }, } } fn mod_shl_assign_ref_signed>( x: &mut Natural, bits: S, m: &Natural, ) where Natural: From + ShrAssign, { assert!(*x < *m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => {} Less => *x >>= bits_abs, Greater => match m { &Natural::ONE | &Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits_abs), m), m), }, } } macro_rules! impl_mod_shl_signed { ($t:ident) => { impl ModShl<$t, Natural> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(mut self, bits: $t, m: Natural) -> Natural { self.mod_shl_assign(bits, m); self } } impl ModShl<$t, &Natural> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by value and the second by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(mut self, bits: $t, m: &Natural) -> Natural { self.mod_shl_assign(bits, m); self } } impl ModShl<$t, Natural> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by reference and the second by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, bits: $t, m: Natural) -> Natural { mod_shl_ref_val_signed(self, bits, m) } } impl ModShl<$t, &Natural> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl). #[inline] fn mod_shl(self, bits: $t, m: &Natural) -> Natural { mod_shl_ref_ref_signed(self, bits, m) } } impl ModShlAssign<$t, Natural> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, bits: $t, m: Natural) { mod_shl_assign_signed_nz(self, bits, m); } } impl ModShlAssign<$t, &Natural> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^nx \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shl#mod_shl_assign). #[inline] fn mod_shl_assign(&mut self, bits: $t, m: &Natural) { mod_shl_assign_ref_signed(self, bits, m); } } }; } apply_to_signeds!(impl_mod_shl_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::*; use core::ops::{Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ ModMul, ModMulAssign, ModPow, ModShr, ModShrAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two, Zero}; fn mod_shr_ref_val<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, m: Natural, ) -> Natural where Natural: From, &'a Natural: Shr, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => x.clone(), Greater => x >> bits_abs, Less => match m { Natural::ONE | Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits_abs), &m), m), }, } } fn mod_shr_ref_ref<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, m: &Natural, ) -> Natural where Natural: From, &'a Natural: Shr, { assert!(x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => x.clone(), Greater => x >> bits_abs, Less => match m { &Natural::ONE | &Natural::TWO => Natural::ZERO, _ => x.mod_mul(Natural::TWO.mod_pow(Natural::from(bits_abs), m), m), }, } } fn mod_shr_assign>( x: &mut Natural, bits: S, m: Natural, ) where Natural: From + ShrAssign, { assert!(*x < m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => {} Greater => *x >>= bits_abs, Less => match m { Natural::ONE | Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits_abs), &m), m), }, } } fn mod_shr_assign_ref>( x: &mut Natural, bits: S, m: &Natural, ) where Natural: From + ShrAssign, { assert!(*x < *m, "x must be reduced mod m, but {x} >= {m}"); let bits_abs = bits.unsigned_abs(); match bits.cmp(&S::ZERO) { Equal => {} Greater => *x >>= bits_abs, Less => match m { &Natural::ONE | &Natural::TWO => *x = Natural::ZERO, _ => x.mod_mul_assign(Natural::TWO.mod_pow(Natural::from(bits_abs), m), m), }, } } macro_rules! impl_mod_shr { ($t:ident) => { impl ModShr<$t, Natural> for Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr(mut self, bits: $t, m: Natural) -> Natural { self.mod_shr_assign(bits, m); self } } impl<'a> ModShr<$t, &'a Natural> for Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by value and the second by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr(mut self, bits: $t, m: &'a Natural) -> Natural { self.mod_shr_assign(bits, m); self } } impl ModShr<$t, Natural> for &Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. The first [`Natural`] /// is taken by reference and the second by value. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr(self, bits: $t, m: Natural) -> Natural { mod_shr_ref_val(self, bits, m) } } impl ModShr<$t, &Natural> for &Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$. The first [`Natural`] must be already reduced modulo $m$. Both [`Natural`]s are /// taken by reference. /// /// $f(x, n, m) = y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr). #[inline] fn mod_shr(self, bits: $t, m: &Natural) -> Natural { mod_shr_ref_ref(self, bits, m) } } impl ModShrAssign<$t, Natural> for Natural { /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr_assign). #[inline] fn mod_shr_assign(&mut self, bits: $t, m: Natural) { mod_shr_assign(self, bits, m); } } impl<'a> ModShrAssign<$t, &'a Natural> for Natural { /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo another [`Natural`] /// $m$, in place. The first [`Natural`] must be already reduced modulo $m$. The /// [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < m$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n, m) = O(mn \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `m.significant_bits()`, and $m$ /// is `bits`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// See [here](super::mod_shr#mod_shr_assign). #[inline] fn mod_shr_assign(&mut self, bits: $t, m: &'a Natural) { mod_shr_assign_ref(self, bits, m); } } }; } apply_to_signeds!(impl_mod_shr); ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModPow, ModPowAssign, ModSquare, ModSquareAssign}; use malachite_base::num::basic::traits::Two; impl ModSquare for Natural { type Output = Self; /// Squares a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. Both [`Natural`]s are taken by value. /// /// $f(x, m) = y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquare; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(2u32).mod_square(Natural::from(10u32)), 4); /// assert_eq!(Natural::from(100u32).mod_square(Natural::from(497u32)), 60); /// ``` fn mod_square(self, m: Self) -> Self { (&self).mod_pow(&Self::TWO, &m) } } impl ModSquare<&Self> for Natural { type Output = Self; /// Squares a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The first [`Natural`] is taken by value and the second by reference. /// /// $f(x, m) = y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquare; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(2u32).mod_square(&Natural::from(10u32)), 4); /// assert_eq!(Natural::from(100u32).mod_square(&Natural::from(497u32)), 60); /// ``` fn mod_square(self, m: &Self) -> Self { (&self).mod_pow(&Self::TWO, m) } } impl ModSquare for &Natural { type Output = Natural; /// Squares a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. The first [`Natural`] is taken by reference and the second by value. /// /// $f(x, m) = y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquare; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(2u32)).mod_square(Natural::from(10u32)), 4); /// assert_eq!( /// (&Natural::from(100u32)).mod_square(Natural::from(497u32)), /// 60 /// ); /// ``` fn mod_square(self, m: Natural) -> Natural { self.mod_pow(&Natural::TWO, &m) } } impl ModSquare<&Natural> for &Natural { type Output = Natural; /// Squares a [`Natural`] modulo another [`Natural`] $m$. The input must be already reduced /// modulo $m$. Both [`Natural`]s are taken by reference. /// /// $f(x, m) = y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquare; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(2u32)).mod_square(&Natural::from(10u32)), 4); /// assert_eq!( /// (&Natural::from(100u32)).mod_square(&Natural::from(497u32)), /// 60 /// ); /// ``` fn mod_square(self, m: &Natural) -> Natural { self.mod_pow(&Natural::TWO, m) } } impl ModSquareAssign for Natural { /// Squares a [`Natural`] modulo another [`Natural`] $m$, in place. The input must be already /// reduced modulo $m$. The [`Natural`] on the right-hand side is taken by value. /// /// $x \gets y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquareAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(2u32); /// x.mod_square_assign(Natural::from(10u32)); /// assert_eq!(x, 4); /// /// let mut x = Natural::from(100u32); /// x.mod_square_assign(Natural::from(497u32)); /// assert_eq!(x, 60); /// ``` #[inline] fn mod_square_assign(&mut self, m: Self) { self.mod_pow_assign(&Self::TWO, &m); } } impl ModSquareAssign<&Self> for Natural { /// Squares a [`Natural`] modulo another [`Natural`] $m$, in place. The input must be already /// reduced modulo $m$. The [`Natural`] on the right-hand side is taken by reference. /// /// $x \gets y$, where $x, y < m$ and $x^2 \equiv y \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` is greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSquareAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(2u32); /// x.mod_square_assign(&Natural::from(10u32)); /// assert_eq!(x, 4); /// /// let mut x = Natural::from(100u32); /// x.mod_square_assign(&Natural::from(497u32)); /// assert_eq!(x, 60); /// ``` #[inline] fn mod_square_assign(&mut self, m: &Self) { self.mod_pow_assign(&Self::TWO, m); } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModSub, ModSubAssign}; impl ModSub for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32) /// .mod_sub(Natural::from(3u32), Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// Natural::from(7u32) /// .mod_sub(Natural::from(9u32), Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value. #[inline] fn mod_sub(mut self, other: Self, m: Self) -> Self { self.mod_sub_assign(other, m); self } } impl ModSub for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by value and the third by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32) /// .mod_sub(Natural::from(3u32), &Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// Natural::from(7u32) /// .mod_sub(Natural::from(9u32), &Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value and `m` is taken by reference. #[inline] fn mod_sub(mut self, other: Self, m: &Self) -> Self { self.mod_sub_assign(other, m); self } } impl ModSub<&Self, Self> for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by value and the second by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32) /// .mod_sub(&Natural::from(3u32), Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// Natural::from(7u32) /// .mod_sub(&Natural::from(9u32), Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This isequivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value and `c` is taken by reference. #[inline] fn mod_sub(mut self, other: &Self, m: Self) -> Self { self.mod_sub_assign(other, m); self } } impl ModSub<&Self, &Self> for Natural { type Output = Self; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by value and the second and third by /// reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(4u32) /// .mod_sub(&Natural::from(3u32), &Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// Natural::from(7u32) /// .mod_sub(&Natural::from(9u32), &Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` is /// taken by value and `c` and `m` are taken by reference. #[inline] fn mod_sub(mut self, other: &Self, m: &Self) -> Self { self.mod_sub_assign(other, m); self } } impl ModSub for &Natural { type Output = Natural; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first [`Natural`] is taken by reference and the second and third by /// value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)) /// .mod_sub(Natural::from(3u32), Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// (&Natural::from(7u32)) /// .mod_sub(Natural::from(9u32), Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` is /// taken by reference and `c` and `m` are taken by value. fn mod_sub(self, other: Natural, m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); if *self >= other { self - other } else { m - other + self } } } impl ModSub for &Natural { type Output = Natural; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first and third [`Natural`]s are taken by reference and the second /// by value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)) /// .mod_sub(Natural::from(3u32), &Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// (&Natural::from(7u32)) /// .mod_sub(Natural::from(9u32), &Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `m` /// are taken by reference and `c` is taken by value. fn mod_sub(self, other: Natural, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( other < *m, "other must be reduced mod m, but {other} >= {m}" ); if *self >= other { self - other } else { m - other + self } } } impl ModSub<&Natural, Natural> for &Natural { type Output = Natural; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. The first two [`Natural`]s are taken by reference and the third by /// value. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)) /// .mod_sub(&Natural::from(3u32), Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// (&Natural::from(7u32)) /// .mod_sub(&Natural::from(9u32), Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `c` /// are taken by reference and `m` is taken by value. fn mod_sub(self, other: &Natural, m: Natural) -> Natural { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); if self >= other { self - other } else { m - other + self } } } impl ModSub<&Natural, &Natural> for &Natural { type Output = Natural; /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$. The inputs must be already /// reduced modulo $m$. All three [`Natural`]s are taken by reference. /// /// $f(x, y, m) = z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSub; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(4u32)) /// .mod_sub(&Natural::from(3u32), &Natural::from(5u32)) /// .to_string(), /// "1" /// ); /// assert_eq!( /// (&Natural::from(7u32)) /// .mod_sub(&Natural::from(9u32), &Natural::from(10u32)) /// .to_string(), /// "8" /// ); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by reference. fn mod_sub(self, other: &Natural, m: &Natural) -> Natural { assert!(self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); if self >= other { self - other } else { m - other + self } } } impl ModSubAssign for Natural { /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by value. /// /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSubAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_sub_assign(Natural::from(3u32), Natural::from(5u32)); /// assert_eq!(x.to_string(), "1"); /// /// let mut x = Natural::from(7u32); /// x.mod_sub_assign(Natural::from(9u32), Natural::from(10u32)); /// assert_eq!(x.to_string(), "8"); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b`, `c`, /// and `m` are taken by value and `a == b`. fn mod_sub_assign(&mut self, other: Self, m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); if *self >= other { *self -= other; } else { *self += m - other; } } } impl ModSubAssign for Natural { /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by value /// and the second by reference. /// /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSubAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_sub_assign(Natural::from(3u32), &Natural::from(5u32)); /// assert_eq!(x.to_string(), "1"); /// /// let mut x = Natural::from(7u32); /// x.mod_sub_assign(Natural::from(9u32), &Natural::from(10u32)); /// assert_eq!(x.to_string(), "8"); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `c` /// are taken by value, `m` is taken by reference, and `a == b`. fn mod_sub_assign(&mut self, other: Self, m: &Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( other < *m, "other must be reduced mod m, but {other} >= {m}" ); if *self >= other { *self -= other; } else { *self += m - other; } } } impl ModSubAssign<&Self, Self> for Natural { /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. The first [`Natural`] on the right-hand side is taken by /// reference and the second by value. /// /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSubAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_sub_assign(&Natural::from(3u32), Natural::from(5u32)); /// assert_eq!(x.to_string(), "1"); /// /// let mut x = Natural::from(7u32); /// x.mod_sub_assign(&Natural::from(9u32), Natural::from(10u32)); /// assert_eq!(x.to_string(), "8"); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` and `m` /// are taken by value, `c` is taken by reference, and `a == b`. fn mod_sub_assign(&mut self, other: &Self, m: Self) { assert!(*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!( *other < m, "other must be reduced mod m, but {other} >= {m}" ); if *self >= *other { *self -= other; } else { *self += m - other; } } } impl ModSubAssign<&Self, &Self> for Natural { /// Subtracts two [`Natural`]s modulo a third [`Natural`] $m$, in place. The inputs must be /// already reduced modulo $m$. Both [`Natural`]s on the right-hand side are taken by reference. /// /// $x \gets z$, where $x, y, z < m$ and $x - y \equiv z \mod m$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `m.significant_bits()`. /// /// # Panics /// Panics if `self` or `other` are greater than or equal to `m`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModSubAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(4u32); /// x.mod_sub_assign(&Natural::from(3u32), &Natural::from(5u32)); /// assert_eq!(x.to_string(), "1"); /// /// let mut x = Natural::from(7u32); /// x.mod_sub_assign(&Natural::from(9u32), &Natural::from(10u32)); /// assert_eq!(x.to_string(), "8"); /// ``` /// /// This is equivalent to `_fmpz_mod_subN` from `fmpz_mod/sub.c`, FLINT 2.7.1, where `b` is /// taken by value, `c` and `m` are taken by reference, and `a == b`. fn mod_sub_assign(&mut self, other: &Self, m: &Self) { assert!(&*self < m, "self must be reduced mod m, but {self} >= {m}"); assert!(other < m, "other must be reduced mod m, but {other} >= {m}"); if *self >= *other { *self -= other; } else { *self += m - other; } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/context.rs ================================================ // Copyright © 2026 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 crate::natural::arithmetic::mul::fft::{ MPNToFFTFunc, ModData, ProfileEntry, SerializedCRTData, SerializedContext, SerializedFFTContext, }; pub_const_crate_test_const! {CONTEXT: SerializedContext = SerializedContext { ffts: [ SerializedFFTContext { p: 4832221662680186888, pinv: 4382073923139863564, mod_data: ModData { n: 1108307720798209, ninv: 292805461487436291, norm: 14, }, primitive_root: 11, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 14046483040696548224, 14041266564791292416, 14046654607898308576, 14048474171345687056, 4825280988129212736, 4823070262100768512, 4825145705455639920, 14048719511357028512, 4813041419429792512, 14047460680378998560, 4823932171918830848, 14048012741190537504, 14049414971616717552, 14040214421382992192, 14050594040212820512, 14048118403069104272, 14051037750155633584, 4826427714660192064, 14042408583631808640, 4815500119549053952, 14048055777734951184, 14044695660409383360, 4819649398905565088, 14045427149334620256, 4823381304004007728, 4815599231986874624, 14049509440854704336, 14047614079244213184, 14042020442567623936, 4823837246712104864, 14047202918495667568, 4824606943046356768, 14046144365724386304, 4826338243139809296, 4825776016666020752, 14041974982291700928, 4821075954353764384, 4818934199985439168, 4826844709835937088, 14045053681550184064, 4825846602928402784, 14048339714062651280, 14048236519775616432, 4813167748879223040, 4814427186749045568, 4801993905695418880, 14047921481845181584, 4800715846833548288, 14050051937776320720, 14047329130950929136, 4825192028434603936, 14033557391598349440, 4811583918684201600, 4826394491523750912, 4827607900400231040, 4815035465331248256, 14050309097969302944, 4826895466358131152, 4822554631046226720, 14036931337007205248, 4825205012118472032, 4825308579084571232, 14045241352176863040, 4810918236012237824, 4797249783404725248, 4827236163907204256, 14047069118495169488, 14049026285404870560, 4818738903444956800, 14045230990509550592, 14031635412619855616, 4827474457339444832, 4824129028022177616, 4823340064380744192, 14044739687417710432, 14045128433022754176, 14047993490571051712, 14045870974207516800, 4813634929117924736, 4825324746932035648, 14039469803807068096, 4820611054736759936, 4822256754287614912, 14021738051791665152, 4825010562180111408, 14048190222917392928, 4819182008851661728, 4826030548176723616, 14046692545027997760, 4819198852482536064, 4815055146123290688, 4820857779201672672, 4826571770796088800, 4824763373960046432, 4826207330779558000, 4815138139495074624, 4824204430389702192, 14049556824142364176, 4824454081787068800, 14049189919930928896, 14044179955986812000, 14046271736812641696, 4824060318425401312, 14050747509266926912, 4825142450362155552, 4816533874169214976, 4827160896341891104, 4820570784529409856, 4821137938370792928, 14049846250466738816, 4826774199463379360, 14030945197938521856, 14049603588453280640, 14043351094687337600, 4824626990036934288, 14031802698386156288, 4822255187199184928, 14048726292367537312, 4823397034388116864, 4826762790423412384, 14049636050427273072, 4819718048613067424, 4825536657712000208, 14048626728823809376, 4819184994000744512, 14045446525187476192, 4827104583110771904, 4818006370840631488, 4818680646777312000, 4827071932865285376, 4827445384756072704, 4817780525507956992, 4817161839406250816, 4824195591743519120, 14043192498422708128, 14051017367425719104, 14048200105821986928, 4825004025033499872, 4819844802597583264, 14047050195186803632, 4824163142215258384, 4824248279185254512, 4820199679800643328, 4823002747338444320, 4824075640393983264, 14038926028439106752, 4808013985434214144, 14049668227092583920, 4819620504808480992, 4824559823719753504, 4825286829547784608, 4810092177519262464, 4825087873481068240, 4823714322660276192, 14038645532674298624, 14040020995286578688, 4825599849329234928, 4813819847671611520, 14048896310852447216, 14045384088795470912, 4805668865339335424, 14048576381293985696, 4824781826700605200, 4822357966667501056, 4824073675312833952, 4824461384396031488, 14041618821648592640, 4820424204835760288, 14049446565963314096, 4825914703018903344, 4824320050456920240, 14047216851637180048, 4826845605120967488, 14046990281984208896, 4803301096677755392, 14048087048487187312, 14048267125598031568, 14049219203991515232, 4823791154502875456, 4824813478518749264, 4826761756073767856, 14045890088146478048, 14047127224416405504, 4825308406718036624, 4826524740619734384, 14039473079911134080, 14051006953175174096, 4822044751034231200, 14045192674302691168, 4821202192697375744, 4819313830282205792, 4824199172058020496, 4824128930307876912, 4815704995150873728, 4824923227130951120, 4822596689055455808, 4823049360411012608, 4819306590744902016, 4826591080181301456, 14049635164099591392, 14030468778628478464, 4827052116848378224, 4819206832265809568, 4825055614504367120, 4823918165860660496, 14042633715279387808, 14049596467118077264, 4825263238083522368, 14031413503257703936, 4815679279413013824, 14038672289249759872, 14038909836703556160, 14038242927481553280, 14047635090853167248, 14051018802502624176, 14042983528167630848, 4805682748104838912, 14039978362163436608, 14048792868698251440, 14034098702346825344, 4820243268433542592, 4819910547530873024, 4824173475856074032, 14048139949516686880, 14037002837738441856, 14035085540317849216, 4820329208711005184, 4818481772245505984, 14046160799527187488, 14037689673424876800, 4823583889208340128, 4826155876156847680, 14050588077073411760, 14043231202974999008, 14044835822719360000, 14050162147253726352, 4825994224944672832, 14036443957070478976, 14049322393135056224, 4827593390471561312, 4810251343749604352, 4825452261412231632, 4826216935547207120, 14045481310938361856, 14047172324274992944, 14049403413423105552, 14042745788132748640, 4822179390531901216, 4817091570614064960, 4817032356022110656, 14050750681875133904, 14044068818421252416, 4825073596177150656, 4821524366611283232, 4825245299496273760, 14048522608956380368, 14047269914571844320, 14026979281596195328, 14048637741933060032, 4812924759510915456, 4823791571623482416, 4819364326935767520, 14048615469363975744, 14048223789395992496, 4822067875914460928, 4812844665382721408, 14047185591090111504, 14048278565984707120, 14042266618224066208, 14046140076805973664, 4822011185608477568, 4821375973811010784, 14045850264554840448, 4825253119507244880, 14050856228650986592, 14039727714170773888, 14041667864897455872, 14050661261201644784, 14041751979740895808, 14046874492511972464, 14043800344359399840, 14048457429015702784, 14048917430359400128, 14042764907603421984, 14042382814754304160, 14029268887713520384, 14050944396847437904, 4815176157982052608, 4826823196257196448, 14045365898906697056, 4819172934441799744, 14045936955907546368, 4823566126366426288, 14050209728573336256, 14046986837514138704, 4814904289452726912, 4820746400431198912, 4820784338626452896, 14047590789083965024, 14050165047405310016, 4818140992688887424, 4815407965458868736, 14042371101755937088, 4820627440088072544, 14043470953967812096, 14049107355544595424, 4819505155127182240, 14046183897776881952, 4822936423049905632, 4823971831127090240, 14043135196912923744, 14049182014391677296, 14034046123976283136, 14046811435933691632, 14022498559883549696, 4824763649716131600, 14048257837414730656, 14034119430308336384, 4823856510552235008, 14043255227566739200, 4826998889025437824, 14046546893774345312, 14044554777814164864, 4820417871504712192, 4824097658741020752, 14048265955335196560, 14048723582937471984, 4811351800357217664, 14049621229982541584, 14048269579186701840, 4822731413398345664, 14048568447829647504, 14047272161047292352, 4825958042234336112, 4824953413136992880, 14049793694230404512, 4824858220134808816, 4825694514610506336, 14051076155048251232, 14047583081180249024, 4821226398019722720, 4815936484729315584, 4806342673533014016, 14035013194025497600, 14047809908198516608, 14040392727468692096, 4827411667643419792, 4814282660731462656, 14050087885837953632, 14044912089655399392, 14049311980611036608, 4816333361033769856, 14049386058612116992, 14042232823497699424, 14041619273212419200, 14047287722435667584, 14050118733590641840, 4823849828665473648, 14046824244044652064, 14047657990103172176, 14045276687864563680, 14047370000355839712, 14047308608616217264, 4827682614884533744, 14047319421821095872, 4815919970748835904, 4825492136127470800, 14047530779696310976, 14040786623432398784, 4825522590368690448, 4810010342263356032, 14049378355821000400, 14043790937380510144, 14042591317386920288, 14042693356712405856, 4826427066641869376, 4823486517647396592, 4816793397773071168, 14047837490033714352, 14049709592061729072, 14050022679623089984, 14050152793643129040, 14049847128285324384, 4819442534710903776, 14038772444489239552, 4821821467032183200, 14042798754962017344, 14041244107263114880, 4827512962414264224, 14047472473965405456, 4825329610943058128, 14049900603450083040, 14049934082860131360, 4814455544346235200, 14047142381153297520, 4826644084028141856, 14047085174347850784, 14034063809682956416, 4823099380073302400, 14012223001864626176, 4825074551368201440, 4824858100641346352, 14049041245033723072, 4822373292844632416, 14050204891093079520, 4815076031447749504, 14047584520893664336, 14040320315309779264, 14046337944112227456, 14047877078142909248, 14035466038416465536, 14050478143558961360, 14049260042868949536, 14037672082656803968, 4824963523432087232, 14049340336395875664, 14046910530902793104, 14045444748947415648, 14047177271606125312, 4821990434795555200, 14044419518738293344, 4819945184119759648, 14041032232841913728, 14048763430668217488, 4823619084349412576, 14042801532148048256, 14042347407205647616, 4825621341096362400, 14048040123758626192, 4824682598948631008, 14038564188098452480, 14050638994166165504, 14035505984064535808, 4823533888126971008, 4806675099723725056, 4817865399384972352, 14049297014298640768, 4824259560240576528, 14049611781423650688, 14029959399145138688, 14037242542246288896, 4825751297384132848, 14046850998927723312, 4826211820473417808, 14030498426865137152, 4814705398582830784, 14034450775430002176, 4823706404100106736, 4822157538441493216, 4823426478537610624, 14049146411892380512, 14044219782276401984, 14050670223392374624, 14051028838390376768, 14045915779506876064, 4823558930160020128, 4825244377568960640, 4807591992296692480, 4823758301839896160, 4826142634230447840, 4819088486472748480, 14042685438782441216, 4824822936255775984, 14031749427877780736, 4823324524495060576, 14049289602396136640, 4827146294076208352, 4816847446884583616, 4824446731668680448, 14043542548998325984, 14047173703129147072, 4824118336375205616, 14050641862556008704, 14047751130241162976, 4806693690923252992, 4827586275371484976, 4822678311433221440, 4826573937920286992, 14048153007760356912, 14049004955509556128, 4824778240945409696, 14036529543114140416, 4824945237162002112, 14050310219556371632, 4818989118935674304, 14049132194814866272, 14043852533528500864, 14046127599306224672, 14046755170205931376, 14038084636413186432, 14045762785437682496, 14046731548459908768, 4822132427385229408, 4822456890616758080, 4810418936055242368, 4822718343374728704, 4827637059920517616, 4819427585591130880, 14043691531324087648, 14037383153404967552, 4820563762056005280, 14050819228458052688, 4827095853942521792, 14045971781255204352, 14043014250328850784, 14039548785370054656, 14049753755436084336, 14044911373014465248, 14035462916292590848, 4822053619758865600, 14038080494600610560, 14048389317093962048, 14035193936213624704, 14050250939632282608, 4819008650820837120, 14036592514031676160, 4816931626055282816, 4813566330015433088, 14044351404457903264, 4825322526433315104, 4824771951280955344, 14038805418786009984, 14048890978650719680, 14050468113100330848, 4821828605537414112, 14047174553190971664, 14049425161611228672, 4823837449135753024, 14048056088373853408, 14045038441127697920, 4822734584214799744, 4825994138165977392, 14039327426371662208, 14047363506710856576, 4818444698442537664, 14031089761854012672, 14049871459928539312, 4824321216613372160, 4825649307690949872, 4796988492555425792, 14041251693586588288, 4821024448229029184, 4826919181845170944, 14048341116163477984, 14045399563606076608, 4817900579996075136, 14049030473429325072, 4825276324930707024, 4824572232687531584, 14050576318790848720, 14048973466044014944, 4821922910084220320, 4821750207397119200, 4825603708836400080, 14043133702734724288, 14035176049538710144, 14046895249368355328, 14043003277378234752, 4823947386255577152, 4824896708370961632, 14047205499523794016, 4821717118544614656, 14044833001674968960, 14038717957195825216, 14049164410395341536, 14048782641585623056, 4792448378576891904, 14050208830239565808, 14030361909789717760, 14048055817760640912, 14046243174679042816, 14050008850696821200, 14049931393597862912, 14048134459644229184, 4823601079135387488, 4820591677239373888, 4827081636870501520, 14050995059743268320, 14043784197742915776, 4825812946351759632, 4826970763627606240, 14030044983182958848, 14044139643617881632, 4824726842733191920, 14049740409859275952, 4827680076108604192, 14044917199660457984, 14034940658526484608, 4808463339559038208, 14045422847133900608, 4825854603158192128, 4818081818263350784, 4821344529459973952, 4813619312253060736, 14043652839812545248, 4827437810137513424, 4821669099732525696, 14039369361079539456, 14049156464208464256, 14048195764173334656, 14050522863552142784, 4824938742031900752, 4824928488290445872, 4814871612147637696, 14015311739133556736, 14041908890339829760, 4824144497432211968, 4818382806586852096, 14040099449000027712, 14042951673715602912, 14040778137255815104, 4825062764527490384, 4817303522963686912, 14050085523192606944, 14049518587648221616, 4827670732149058192, 4823145697700376000, 14044260934986973664, 14049696201554602640, 14048108127626746032, 4826179626828927232, 14025411070459712512, 14043126295386998272, 14042215012924440576, 4817138123172843072, 14039659159559786624, 4827465257896231840, 14048700151011937152, 14044145462090976832, 14044240267743751168, 14051014947497155792, 4825792464940578096, 14045429016722256896, 4820419454094284960, 4816881735781510912, 14040636933071128448, 14042687405981482496, 14031602415484818432, 14043159942599446208, 4823680538966477888, 4826944835012779808, 4826603141001502816, 4826478223155301520, 14048128849987772736, 4822322466570815616, 14049218559407890512, 14047304711675162112, 14042094920924952256, 4817824202519944000, 4825189996172164608, 4818421383587950080, 4823833599386250000, 4816562725450519104, 14034691421119442432, 4824993328069840064, 14043245000696696352, 4797625995430700032, 14048526673318310592, 4824286505259134480, 14042053994169972480, 4812300173882833152, 4827082155612445760, 14049381679719453920, 14049274138105394912, 14044913171158146112, 14050373527917723984, 14048316983198268272, 4817876332410355840, 14049032695401610784, 14050097281675712128, 4821460861520460672, 4823737627459473552, 4823982265570123936, 4820056428764819712, 14049353536247509456, 14050472218798172352, 4826755432408624016, 4824803968710798544, 4820031489267798592, 4821967137830257824, 4825015224569409792, 4824838961161096688, 4825800065348432656, 14049952585096929616, 4827104314850334688, 14042705266240876928, 4819926754454714560, 4824018972128983168, 14050795241954013984, 4805014905477674496, 14050038971813359200, 4822044814930407040, 4820411605327367744, 14049688902799295104, 4819142804284420768, 4825886917665679248, 14048747937899510416, 14042037124403658304, 14049176071280358352, 14044055017356814816, 4825469840564567632, 4824905342407590544, 4818504074420354816, 4815458176558902464, 4815188453051336448, 14036807263994892160, 4827498343826201664, 14049119379953410128, 4823302775604405376, 14043016715203301664, 4827495641790033104, 4823363857277762688, 14038033438167736064, 4814847157876722496, 4814251124741317248, 4819195415170804448, 14050528980015152576, 4825411202855366608, 14047125621080780672, 14047959588196616240, 4825051940528699280, 14050521634850489216, 14050017475456693200, 4820379686704611264, 14035910600422123136, 14047326493300457424, 14050571215156938256, 4823652418888649696, 14050417988381761264, 4820387977337772736, 4818314072083754240, 14051017487741226912, 14037050973462570112, 4823704255755433136, 14049427498142413264, 14040878793519066496, 4824929473640154320, 14047664547066175872, 4818037308111769600, 4826743500546108048, 14044957773744784448, 4810005278012207744, 4823919620547018928, 4820321268535672416, 4818908408295628128, 14043313622182274368, 14044813162330105760, 4813160655793087872, 4823385822014157392, 14046760915264564288, 4823786982390816112, 4827296165539996304, 4823642076546874576, 14042724646872466528, 14048553575357552560, 14047780490992593744, 14046445349514871488, 14047521390871206144, 4820418130056209440, 4826057571897478464, 14038613586342552960, 4818400212677276096, 4826763177360602672, 14047467554376226640, 14048174401070517808, 14044467821834138496, 14042917213813070048, 4823973937344713312, 4824802598723866432, 4810374765008782848, 4823313025639697728, 14047663970055997744, 14042087037471012800, 4820438914229217856, 14049376909377142672, 14033903211948548224, 4825987015351910048, 14041826251995452288, 14034672944557374464, 4806721659360261632, 4823504542259255104, 14049386929894760304, 14042167594739367872, 4819735892051179072, 4826234150372706352, 4825635028466205696, 4825682256751671408, 4826055702446774672, 4821388320759786848, 4821631503468549312, 4821239842242658848, 14044068914730140320, 14048039872714796704, 14047720135151209552, 14043322227654425504, 4825120915116238928, 4824561218852411520, 4799089433073063936, 14041671799794458944, 14045470044109872608, 4819833243804254816, 14050818584461557184, 14011000164004884480, 4821574614677297728, 4818409231908242944, 14047772101476957008, 14028656681432691712, 4826369189318387600, 4826047476251163104, 4826626888858870256, 4827179954026736880, 14044775829680114976, 14044398407826933440, 4814560448369338496, 4819574707907834176, 14050221278744849424, 14050489287540949120, 14047444516093491344, 14050910635606165344, 14047856588118826768, 14050830839860001552, 4821056253933807904, 4822526238105877088, 4823136705466425216, 4824598052275447584, 14046721130553494464, 14030105928680120064, 14050129392130375760, 14048399179017431104, 4822062910989996128, 14045832027205446304, 4827426182310374864, 4826803922508817136, 4824725648271379040, 14034047469209378176, 14031946455468987136, 14040993140600164736, 14043883714586794240, 14049753207724580032, 14040274828053123904, 14038075165461151488, 14048394431476414240, 4819914078759153664, 14048700303594925936, 14048319457910827600, 14031159189659777792, 4810951811591987584, 14047736580788544352, 14050220993756874384, 14047994611929683824, 4812993739683130880, 14050612673831094928, 4823077962950726880, 14049324931122414224, 4807056624159824128, 4822181562188094144, 14049500243183956304, 4825066038008814960, 4821520350432733632, 4826360018397011440, 14033543939808361344, 4826441453874137008, 14049470627390374496, 4823491673007346512, 14049306039481578160, 14049318778861924688, 14049433456593114432, 4815193853112816128, 4824208031904870272, 4822978959369136000, 14050129686200503776, 14048301535758838144, 4824038246796583168, 14019990247193713664, 14047173327800554336, 4827005370443939232, 4819059803056283136, 14050985684827130912, 14049692948841202048, 14038741239917574400, 4823981374889807680, 14042558626126699168, 14040184482525000000, 4824731944975032352, 14047108356132470864, 14049050995698017840, 4822353234150518592, 4826298778478247248, 4827074656938274112, 14040027358764133888, 4809399905530755072, 14048245229180783072, 4824278461063835232, 4818264080879098624, 14042573514164921184, 14046780630583738992, 14048342525722425392, 4817603500973679680, 4819355347407624384, 14032021090460038400, 4824782255042232384, 14045389521665389504, 14024409243401035776, 4823739530006398416, 4827190975852845184, 14050460958769218208, 14047972934133372160, 14043237056584784160, 14045246492667673408, 14048248890478175024, 4824033266785191440, 14041306932511527680, 4824201948414407648, 14035746306137014784, 4826608797457487136, 4825804477667002240, 14043458486220994944, 14039931440313117440, 4825680090629775552, 14038874845851296512, 4827633008316686240, 14049708630484377120, 4825969499993660960, 4827670181244286672, 14046073782105463360, 14032244290825528576, 4820333566335309088, 14001185667743121408, 4826877747219171088, 4810503667078950528, 4815969264516539712, 14046872477003629472, 14050474979328471360, 4823938516431877552, 4822696416038111904, 4825330112667078304, 4817726654421807424, 14049534591293289408, 4819622695209296288, 14036484605168766336, 14040477302657828672, 4827238155886872208, 14047555417981665392, 4823724132021569344, 14050451441238069248, 14043073339329737536, 14043085447748119520, 4822810482732216384, 4811736601657569920, 14040312215997210816, 14043598447053454176, 14045110381196836064, 14046819728878511344, 4823802266536485248, 4823865206430002048, 14049996697967239248, 14044341517830000928, 14049724357239109920, 4820791278730805472, 4825197387206310000, 4825827918262292960, 14044132766436536544, 14041268228672924032, 14047201944379888240, 14032735196274474752, 4809112834775911936, 4818003131852559040, 4802243099366344704, 14050182649627319328, 14047909231480107088, 4812137897655606784, 14049705564967831168, 14033976512708240896, 14027931435200795648, 4824337775157688944, 4821357004530333184, 14048717017850817536, 14048728071702574160, 4827670279212212256, 4824166125754012000, 4822765038570455968, 14037244243850448384, 4803066520386499072, 14042263836442361600, 4796999112019733504, 14046089892588727136, 4825179684649838944, 4823500156715498032, 14048848520911285376, 4818161119440225728, 4822495930307914208, 4826439904916876544, 4827100542241410544, 14050741909833905152, 14050347714602958160, 4822430311858673856, 14025262676021335552, 4824211547973375648, 14050974329678990624, 14042676524287139040, 4817472113258527424, 14047610723732217488, 14049946287408552704, 4803674739935610368, 4826087269076794352, 4823267877903293472, 4824223373330637536, 4801118048153637888, 4816149158066276800, 14049850220279978576, 14047638012785179888, 4827670034037597360, 4808599677359184384, 4825199449878897232, 14050497912851002416, 14041591445852857088, 4820637808789058688, 4811178381842720640, 14044426604533850592, 14048055342465439344, 4827641084103665792, 4823634593854848704, 4827135429311388656, 4811421929041603072, 4824264860205137088, 14049235855245066656, 4809994195048449792, 4812398687601299200, 4799737892864008192, 4812639104270494336, 4821783757551691904, 4823762185457199696, 14049391731391316272, 14043795866412463072, 4819163028129517024, 4826311011295981904, 14048864487497926672, 4814216756732007168, 14045091618957046176, 4820679856320506528, 14042133889935211136, 4804794786083888640, 14049247742810533296, 14033200741560652288, 14045367357496828544, 14043088686934028256, 14043594812964895840, 14041441548351936128, 4823459811836453168, 14042586208531821408, 4826111767986921904, 14047777047226615312, 4818990093768923616, 14040054768560402240, 14046476804754734560, 14043510144205915616, 4819940633648600928, 4823753316141818048, 14050881073941911744, 4824885911148528304, 14046698637174888160, 14047458767313100800, 4806398597017638656, 4813942231709614592, 4824232339651744880, 14048730126332423680, 4818714442459357824, 14049366445346794016, 4826312939247337696, 14048006279033415440, 14042782612048154592, 14048740776264692208, 14042881147351247296, 14042065059306533760, 4824096451484427520, 14050610853646856784, 14048397085743005952, 4813789006044855296, 4821801979214705824, 14043520699521108992, 4802840056561442304, 4823864102796060576, 4823525999223474000, 4824706085613404320, 4820295627894130080, 4823544168582647904, 4804994324847129600, 14043494716301654336, 4821997976030029024, 14047881418499838864, 14049388816561862624, 4825922794789602800, 14046012998850089856, 14038799663733567232, 14048053782188155056, 14050968423657705712, 14047423957593545168, 4820943035580785376, 4826980164489391808, 14045044462552138496, 4812702268248144512, 4821826116850782496, 14042649674563675360, 14047887038785699920, 4825847111692139040, 4825083159516926544, 14050282990916501840, 14047371306406156496, 4813624770547960448, 14041107897071280064, 4818179172666332032, 4806607923258368256, 14047972280383725456, 14047710483752884880, 4825566470899741280, 4827633472773783312, 14048895436467717776, 4826526829160628560, 14047821533715008400, 4826356385626289264, 4818623174480530944, 4820126229807775296, 4816559678143028352, 4826763985400077600, 14048591364024177664, 4824736719850303744, 14048281471776530400, 4815193594621049408, 14029521606013841408, 14046942316399706224, 14049141353658527552, 14048790086622898752, 14043365918462265920, 14035295414311566848, 4825513921554817664, 4825769449850664080, 14035287333485237632, 14039068086671078272, 4823804547424765136, 4823648732167960784, 14031442911559868928, 4796686174254595072, 4814678091057292928, 14048307304165791136, 4818885944091279936, 4827404505191560288, 4811071555081036032, 4821483615965647360, 4824590594527788928, 4823492577593275104, 4824474008253487152, 4821850323476073984, 4817773315630970752, 14048305156564457984, 14050699803713024544, 14045885427511678752, 14042798892269549728, 4822115307729688448, 14045145185572353024, 14047929644166078320, 14050114217549470640, 4823389360071748304, 4825285574720321392, 4824059602368387536, 14048566002654176976, 14048142872528450400, 4826379947123452064, 14047550402831225648, 4826313022610942096, 14038574554613437248, 14017387027466635264, 14045938320822787712, 14046924477127197904, 4820543124300843328, 4826984292151300880, 4820780794260132832, 4820311018256293600, 4821088497043329920, 14031285923684652288, 14050208023762320720, 4823154468781830496, 14024221014024868864, 4827545810710818544, 4803770425606217728, 4815833483577915328, 14047948581737379344, 14035830390547190784, 4826536315839360752, 4820373725338630752, 4823793970031509152, 4820612029768570976, 4807861656405345536, 4825785990719501568, 4823931299084811600, 4826487899239145904, 4824929895976138192, 4823687050699006352, 14035270889360028416, 4817085968707752192, 14047221565498090064, 4827608698755319856, 14022965825106377728, 4826023156446274000, 4822774230966204640, 4826662755377551888, 14045246278306345504, 14045210904717919680, 14050255574983527728, 4819753640331101632, 4817379519334513152, 14044090049767361344, 14048182622205039440, 4823988193033827344, 4826097815083829792, 14042726040813921536, 14049672100162419040, 14034763801898471552, 4812792188198274048, 4826961330126910000, 4822540034503062848, 4820897453194200320, 14048772375141864976, 14049181354669862912, 14050759248192090848, 14042834203342692544, 4819669466011728768, 4816083940476311808, 14048499021916310880, 4808405822684878080, 4824984268712939808, 4824118205980250352, 14050668975253147040, 14048707224589576464, 4827183255647135648, 4826151874233119008, 14046983094248641696, 14049301561251323280, 4818115213590563584, 14044673444400616992, 14047443406712906304, 14031027101722540800, 4824097134306830640, 14031316359760125184, 14046891485875874064, 14047220734626503520, 4821102982322572000, 14041247686193285440, 14047011331989882624, 4822142354097115840, 4826338805104120080, 4825404623007600288, 4822459353770083424, 4808020038486670080, 14050974077795101984, 14046790294847422416, 14049249972180910768, 14047241068169001024, 14050543760247434784, 4816902829497605504, 4805751018085177088, 4823948647611760176, 4827394871616739472, 14049674043206788736, 4825810122965890496, 4819911126381611136, 4815925995176838720, 4823371458677150352, 14042717089041157536, 14032455400918530048, 4827411287266581296, 4820652585886907232, 4825077981930103536, 4819555259465834080, 14040875238305174784, 4817766492375635072, 4822669011838381696, 4827466219917713328, 4827048618674559392, 4824897529043500592, 4824874891956432880, 4824200863393844464, 14040308079211922304, 4818370054817360832, 14042519095379283264, 4816653920016617472, 14043663008969520032, 4823511258765714320, 14039392752081414208, 4826036898486457840, 4825402200590193440, 14027938839169893888, 4823728344907461936, 14045664793858061920, 14038107196253930048, 4815301754434298688, 4825258778408648688, 14045857112140246080, 14043390724342676544, 4815849137218845696, 4826649084435575456, 4805958791929560832, 14048537968184792592, 14049091228753016912, 14036186466028463744, 14039261025174243904, 4826319658239455152, 4820065375866440416, 14047371851533913408, 4826106825619478128, 14048013833904203760, 4826035994409429280, 14015058383664095232, 14043838777961254528, 4824202454094419232, 14048351032218719888, 14046198107125211232, 4816121044939971328, 14049226478982094880, 4814848534768442688, 14038520142436121472, 14038246757609779968, 4826476906199083168, 4809462203309062656, 14047161664700644032, 4823376409147757712, 14046607631393091904, 4823242148841808416, 14044824267096326048, 4822786214030842400, 4827418661768953936, 14049422066138325600, 4814964056013024448, 14043383934020347520, 14047864846296047472, 14043513789210561856, 4820026682781140288, 14030960717774562816, 4811873976512967936, 14045044059703654624, 4823527423684777584, 14047528149116157872, 4823835791738285472, 4823896730670086000, 14049469981769096080, 14047832717898471024, 4825369438676787488, 4827191782322799008, 4825057605352803264, 4820756585569507040, 4808084823852582144, 14045051186973999008, 14047145195118349104, 14036643925099944448, 4814941830252912000, 14050973286917179088, 14042685647050006304, 14039065486163422464, 4821855905304276000, 14049924940458569888, 4825952151283509504, 14042961181224440448, 4804605176609667072, 14049913132331992832, 4824827504858597456, 4822773597922257984, 14040026980928625216, 4826779941577806976, 4815960767651894720, 14036631522244737920, 14039093758150116096, 14050549914943705984, 14051001522018262064, 14040313834729597184, 14048640518487531040, 4824010406447783472, 14048797096208923088, 4827168991544262768, 4821583906004469760, 14030744967826738176, 14049394615343466864, 14045782442650237664, 4825099293470491120, 4818957323014426752, 14038630476874445568, 4826603945834925680, 4826131358529539744, 14048236112110473024, 14051035493720566448, 4814630088838820224, 4820989018267810976, 14048246886449846912, 4826471765553943744, 14040209684948417984, 14048587924311158400, 4811772396496130816, 14038200391603697024, 14046633568261573248, 4822092685938815168, 4824621315641089520, 14047214195608651968, 4819010212900246592, 4809127000458138368, 4816728096965108352, 4821412288747976320, 14043488377933560448, 4823733951057920928, 14050089753909609680, 4822838457933772896, 4822803359764372448, 4819941737103643904, 4823747831448535184, 4827504327015385024, 14051051056718676672, 4824658099726637744, 4825411260933834960, 4823043002615955616, 14048910447521457632, 4811059987606457984, 14049685749077831520, 14048603028352395952, 4824144463675470288, 4827642918647245552, 14041182725316451008, 14043226584804013856, 4824376221296616048, 4824143174738645744, 4819544534746024288, 4819357397217110432, 4821475286766059200, 14051082127157782208, 4822856974009252576, 4817648785063775488, 14043881878702764224, 14041782930361304256, 4823512157551936768, 14022263306753145856, 4826711052921488784, 4819230706615873056, 14047975792163191008, 4811307173663393664, 14048415312568857584, 14031965883123745792, 4826855737456213168, 4808721559732013568, 4824860569998859408, 14045602767638314912, 4822539963520467360, 4823281430241485248, 4814075181149041408, 14027415616102775808, 4816630093244011520, 4817327204481828224, 14042632846383276736, 4827298496948764736, 4824216370439993664, 4824875883070530864, 14051056959248631920, 4827708255740512400, 14047390629272803008, 4824106277282720656, 14041731834229461056, 14046868792931710064, 4820199782790721888, 14039141845818192064, 4821697901999706528, 4826323686207068864, 4820217808752684736, 14038098233776185664, 4827630130636869408, 4827448787185918544, 4821686207487274208, 14039533057964429120, 4822772496609909696, 14045588520227685824, 4815382937617482304, 4827658186492441664, 14033455317055026432, 14043062359825904736, 14050602729445589840, 14046576125365225728, 14050140227265044048, 4821762868503691136, 14038055881211665664, 14045374949720539104, 14048805945577493936, 14046602041622258912, 14049220179107149040, 4825794462053744032, 4822937066223620096, 4826103508198147392, 4816628568434180864, 14040012361554649600, 4823389924688200752, 4822799382082689600, 4820433380855794592, 4823428114210331216, 14044965541929404992, 4826445539118309840, 4819727460073753632, 14017380542168121344, 14050542271589125024, 14035631237608591488, 4818306784191398016, 14048677121080367984, 4826633669332172336, 14042358042698410624, 14038281643458277952, 4801883021905472512, 4825729462398887408, 14047742637522574944, 4825684679274142608, 4825326523302221568, 4821931566862920928, 14046925427475931968, 4822622403057852256, 4824008119366823968, 4825412246870318496, 4814443743652895872, 14045570833795369760, 14036531238324141952, 4827540081414505600, 14047571202954087312, 14045816147737524672, 14046020380372169312, 4826644568044572352, 14035501766537650688, 14050162292280528352, 4823549234826249264, 14049116307292674608, 4817908452864409216, 4819538173329123424, 4807334874615023104, 14047278227632520080, 14050289513387397808, 4813757782267819520, 4820740961289909312, 14047555562635806992, 14049350418844801744, 14048109124623256864, 4825353928764013744, 14045323485318942208, 4823124540316155968, 4826945668128171280, 4812600737105759616, 14048087404177149440, 4821835838770093824, 14046833059605891984, 14044258118020022624, 14049870430866339824, 4816128397606519168, 4817398809169279296, 14044470459828437824, 4823295078466394912, 14038953643923701120, 14045511321756949312, 4822636253160679488, 14048945516375699504, 4820845912369012160, 4820253679365997824, 14040939353509877248, 14048884198746175328, 4818949865824361920, 14041209950309868672, 14044719304210324480, 4826777336089560928, 14043481839483825152, 4823821105684543344, 4822783255043803904, 14049281732649294112, 4825248220119865344, 4821333000366636672, 4823881024519973504, 4824913348784392592, 4818259024263396800, 14032450027187251712, 14046898721463804624, 4824299014303891648, 4821675762816370944, 14040144928351822784, 14044073059975003744, 4826456315736606336, 4814765110873584960, 14042341214254781856, 4825119399469174640, 4819306516110165728, 4823816956272018240, 14047804251838868112, 4825986531739597584, 4817786160319507008, 4824867828566145408, 14050880528513780384, 14043917704907488192, 14036130547913246080, 4822752087190713664, 4827700593398496192, 4819395347940782528, 4816389306831085696, 14046779516268288656, 4819237370757801248, 4800804938021174272, 14021563430131771392, 4825427096657175504, 4823502588867530832, 4818609538104890112, 4825769672844657456, 4826256650008051200, 4810852091300554496, 14050610256335269904, 4826795460142347152, 14041247008925071872, 14036220111299612928, 14048303144863796144, 4813598234548998144, 4819963595741132640, 14048295403856279360, 4827451367021476512, 14048783298885132032, 14047454131434375184, 14043315376803241088, 4823618581136908352, 14049607457175579696, 4819406522244055520, 4826742818956699152, 4826698289508748352, 4814501787864231488, 14043573233526010656, 14039917697807371136, 4824135265879415936, 14049660427355387152, 4794445503981279232, 14050723597514702832, 4815768972598708608, 14047732750054641952, 4820415654805654176, 4817206566278107904, 14045272609101309248, 4823715358250807328, 4825536955963543408, 14044509227807849568, 14047569418033310480, 14047787329280058480, 4824985852951599376, 4825562841097208784, 14050916608157128528, 4818400025255088256, 4823456282262852688, 4811105345790366720, 4811584187347914368, 14031811081013298432, 4818769723044596992, 4820460926610461664, 4815848166012674944, 4820275576080913664, 14050873393436755600, 4824425879580314144, 4824372893567186256, 14047251161746509632, 14044115041160724768, 4823373125817114352, 14049020671407397968, 4793387164187516928, 4824700864388409568, 4819469392294336320, 4813861749344003712, 14049355181746156016, 14038671019862213184, 4799453382307109888, 14047473053284071376, 14035074230730264704, 4789441156622323712, 14049750095640513424, 14028766377577940736, 14044362760215333120, 14048811573425986848, 4825496545540172768, 4818576125127002816, 14002317238196781056, 14038691195772444864, 14048069196267150368, 4822082814895215904, 4815803962309064064, 14027339280850575360, 4827135305534509968, 4814818124101868032, 4813345373256541824, 4817638647746724096, 4824373030474564128, 4825648653439495664, 14049345770806273232, 14049243472281443264, 4827145263229278576, 14049415116506242736, 4825623018156637312, 14049952156943357792, 4825949819055276464, 14039942214431684672, 14047552189685927520, 14049084433484129536, 14033341594490121216, 4827010506476908640, 4818630732592711360, 14049121257479556192, 14047006154293683296, 14048042991193559920, 4826073845437503248, 4826685808269654720, 4818829496363635264, 14050114020472834128, 4826462260087830016, 14049535119760430368, 4825546559926265488, 4824746670337213968, 4817523703688575104, 4827259814437917248, 14042747410057185984, 4826245894705949328, 4819833622760730432, 14048506405753240544, 14045152059638856576, 4826503398883375040, 14049807727116798496, 14050402678886026240, 4818933267441513760, 14042201592086615808, 14046054339890160224, 14047596103326278896, 4826476310251226704, 14045015639041745504, 4805512153501563136, 4818944150914046240, 14047536185839953536, 4814018051555214720, 14045569331692669888, 14031923946096272896, 4822744718018811264, 4813041749200906624, 4823739002983875712, 14050416099789506240, 4812532390170866048, 14044018607668059616, 4812594222363244416, 4824533827419506512, 14047945508894542128, 4825160357465678816, 14044850966048374560, 4821732301126715584, 14048781142659208512, 14045295458759605472, 14045747937482891776, 14049875747390274144, 4826263784714438848, 14045419806793099168, 4816847734945561984, 14050471988211152064, 14034027783913372544, 4811039969273479424, 4826061620360441520, 4826020893728525728, 14050695307263748944, 14040210327260752384, 14046066411706034592, 14048986597260644608, 14048680064231740496, 14034068088366424448, 4815880263468846592, 14050380068302458048, 14050712827672616992, 14041514622421967872, 4811808016357075328, 4821053480822345824, 4822084757716810176, 14034595235122872576, 4823335848888561216, 14046309064205824608, 4827192738319963904, 4815965535827510656, 14047161583949895072, 4825152738562587808, 14049524903595168592, 4807520680282924544, 14014952280814137344, 4819937128696271040, 4819690794432981504, 14044951262803899648, 14050536497208329328, 14050726497683702000, 14047157075416915568, 14050344951798916752, 4821294569716946336, 4826498010776526784, 4810410287348127872, 14050360672171799008, 14050276586573855856, 14049070813262950160, 4822104404044246720, 14041285704916763968, 4814510634132239616, 14048840496894155136, 4817115272425660672, 4826029144080926624, 14050516695415704000, 4813788770163077120, 4811712358643152384, 4822003623490960224, 4826349453877262400, 14020896018135100416, 14050264276156357936, 14042442432518723392, 4821177593899727392, 14048235998661582960, 4823046834486961216, 4802090634954478080, 4823234803757015456, 4823359912584577248, 4798138492814368768, 14037705807159493632, 14040634568070943360, 14048793475402835872, 14047495603926305968, 4825973246811017728, 14029372530558797312, 4827538921072190544, 4815697206367026560, 4825816215435880448, 14042516384431609856, 14048458169513524240, 4826538547916483168, 14045759692194711200, 4823356392169040144, 4826154477102249440, 4814700885952551552, 4826252183308865776, 4824974757520155360, 14048190175174438496, 14046780224363057888, 4824752379951631632, 4824273186611894928, 14048331081068352368, 4811220580560222848, 14042272568235610752, 14042424494305154848, 14032608611505335296, 4824025893487889680, 4824027966548269088, 4823590363937651008, 4814356610060848512, 4826838467660879440, 14044721877138426976, 14043470233755728832, 14049774152821533648, 14040265088001192320, 14047879387366574048, 14050614733786296464, 14050212279612829968, 4826312285210207712, 4823700262216313488, 14033586002042470272, 4802541170718196224, 4813907315216517376, 14035910052010553728, 4825800464099422112, 4820969367225557760, 14049038840578138752, 14049900830371037584, 4823901587034998032, 14048293997006090656, 4824182657273064800, 4823741987730466064, 14044992982005551872, 4823971155694406496, 4824012131354625936, 4810419183559103104, 14039232665577073920, 4823503002216754320, 14048479922122598464, 14045821635095769824, 14032619406190974976, 4826263072035324768, 4825908837174979584, 4824730955112305728, 4823300671091514016, 14049749821391910448, 4827419749602629664, 14043579820283284480, 4820173794904810752, 4824746101078912880, 14048347833062625456, 4823630418979936752, 14032149438537020672, 4816490517680249152, 4823710088697930928, 14037226153989010048, 4802851431372572160, 14050295528836265168, 14026534686342483968, 4823972278471873904, 14048831944521334912, 4823417418211768608, 14038631889625598080, 4824264453434680192, 4827657067963844064, 14049789466880124192, 14050953137808377712, 14038701017207764224, 14044652475405505088, 14050203842233181472, 14025668692392048640, 14047917883741893120, 4825378123742632256, 4819760767486964480, 4819637858563459552, 14042289796141181152, 4822726670269952192, 14047800645053939056, 14045752520235844864, 14031493106082523648, 4825502782200421728, 14046858860010065872, 4818326939641915200, 14050180241097002688, 4823528937802000000, 14047884438794068640, 4820556805226138560, 14042920202783121440, 4809119854597300992, 14043107100923736992, 14050197377518432128, 4813144646356519680, 14039157615251800640, 4820739080255024224, 14038530291968152704, 4817109036695824832, 4810269873700408192, 4826374684931792224, 4817981061335538688, 4825609053903741808, 14037951083207326784, 4821246643305950592, 4823998090620773872, 4825628602898931552, 4814358593247632768, 14047233835690411136, 14042671400751724288, 4824984488789790192, 4827641642617006720, 4814595523582769856, 14041621114572618240, 4822715435316322784, 4821281605523032800, 4824981848572901328, 14049628629421054448, 4825117417531266176, 4826828645496426080, 4810521467321621888, 4801772399391783424, 14046195818203651680, 14048173351184043680, 14040075043384437952, 14034535372035786240, 14037913214565410048, 14050613723821736016, 14047938634625013504, 14043623817771747616, 4811112362530416896, 4817290454357732864, 14047083115582902832, 14048271140227889840, 4808090717497775104, 4827387335383872992, 14045501921018674656, 14045825954815159392, 14047154605124648896, 4823410539906505200, 4826164532708620224, 4823734664880947200, 4826171033707836768, 4824788422668330048, 14047514839978030048, 14049417132519270272, 4826140779517619504, 14049855918019013904, 4819371684235387584, 4826219031919154640, 14045783381604152896, 4811333879680225792, 4825623414536728736, 4825032680706994608, 14048998262597218640, 14041631406053670848, 4814866568511247872, 14035959184549976832, 14051075047855447584, 4826457870499446768, 14049415331188041424, 4814151555245021952, 14043745520358470976, 4823986348588245488, 14043305856018952960, 14040454147282728448, 14035536714113912064, 14027874297207997952, 14047733285989575024, 14038152840867900864, 4825529851820564160, 14028413230963145216, 4812190226581242112, 4816268091817225664, 14030328950209231616, 4822172364975014240, 4826081343803695520, 14050972247282182032, 4821498934439557248, 14044636428436912448, 14042626498947446112, 14047352162255241760, 14047706225166302256, 14049234248672795568, 14048036411601144960, 4822851661565697440, 14048222720729285440, 14045547016399182688, 4824012405606903120, 14049548482211983232, 4806786551763581440, 4820100274329244288, 14048887797359332288, 4826869046890293072, 4826035734992846032, 4825550577096920848, 4819552821142361440, 14050264143699670816, 14050299240317652864, 14032787871273484288, 14029310519282707968, 14029772401589264640, 14036857108884439808, 14042685422861408384, 4826671868544077408, 4824393569072236048, 4827433708726031328, 14047445532620181328, 4824617460995290000, 14048421672400906032, 4824275415644965984, 4818106584495411584, 4811038908479089024, 14046976420087815072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4828632856727126024, pinv: 4385184981168167747, mod_data: ModData { n: 659706976665601, ninv: 13035699145421368753, norm: 14, }, primitive_root: 11, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 14022680714634054656, 4820712691211757408, 4819249779558219328, 4814848747229190976, 14022729685023594496, 4819165647952025408, 14042771579763669792, 14042347485588792416, 4810322147605490176, 4819746801432125088, 14045876426525876800, 14045422124162931744, 4822911455828147456, 14040501214504649280, 4818246507580775360, 14038295065953428160, 4821876636497526944, 14046070764013118464, 14035753502278090368, 14038717782756693184, 4815949059311277952, 4822672929233018816, 4820769715554402368, 14040796714214300352, 4823374512110701792, 14040765101311988096, 14037964577281404480, 14043374672138121056, 14029609600473224192, 4820470819738241184, 4817534789551762112, 14041395260030327168, 4823329126402176672, 4821463746447382432, 14033287482559375872, 14043057443239284960, 14047337337290524352, 4823271721378525536, 4823103375123745344, 14034740446563932928, 14040343733629255616, 14037159334362785792, 4815131337730935872, 4819499553550657824, 14040361778298498304, 4816889594662260544, 14045507617035855776, 14036692362406926848, 4822010001847494400, 4821374737789289472, 14045139395684334368, 14043715882869823872, 14037049689699825024, 4802708576056335360, 4824028972484406336, 14047303564099489504, 14047434029246607456, 14038094888762036160, 4821847493476766848, 14044077935175739104, 4814535035013448960, 14032569346990249984, 14039102684246736256, 4822516397464357760, 4822393846196709536, 4819968889018665632, 4802111971169878016, 14041330249657258752, 14045847829584049344, 4820038440796376416, 4820040481785133088, 14046920661922258320, 14040268282486967936, 14046522987992208384, 4823683088334476528, 14046746121206313248, 14044940456568775744, 4810734461243463168, 4816744108380203904, 4823527173842664176, 14046857810758224752, 4821062067491491936, 4803443929230962176, 4819717550856432384, 4824084669763567392, 14043025870045175936, 4818747919521542848, 14038502710830179136, 4823386796571280784, 14042327815495895840, 4822111759078927008, 4814977299231950912, 4817588110536056832, 14042279251053151712, 4821840109955956096, 14040653630420899264, 4817930989932559296, 14042622665069547872, 14034721616857048064, 4820074523136886144, 4823707295292562272, 4804482854961802752, 14043161980881380672, 14044718689173440288, 14039631036301203904, 4819820497643926656, 14039994898299412160, 14046909480325279984, 4806584974209728512, 4819109486192351232, 4824112834507130432, 14044689868337704224, 14039765492989067840, 14043041832818968352, 14043727011455858880, 14039034406029932352, 4820811091750771168, 4811003096932815488, 14047111264276690432, 4821175079436430912, 4817287546362851264, 14029505646696510720, 4823484453479471888, 14043740279272244128, 4817944497882481792, 4821050694690922208, 14044521596829420544, 14044790036724851904, 4821982659053236288, 4814547529164107712, 4818740620071045760, 14043968098221152352, 14047287577677973056, 4823601395070219872, 14020765748402148352, 14026516655440028672, 14045047884142750080, 14044993358829835040, 4809209870993103360, 4811412376222931456, 4811886058664630272, 14019215786600765440, 4823462958103153136, 4823290887582221664, 4815895052336918592, 4806919841636668672, 14044463654034514112, 14042255812751477280, 14044086488879062528, 14028218328931315712, 14043039730882272640, 14046925510749453168, 4823577691849640512, 14046643057261962208, 14038438719733707008, 4817916262237805760, 14040252588598165760, 14043202199643897120, 14042361669199462304, 14042613428712936960, 14032438839976769792, 4815469530610619904, 4819138093917083328, 14040352515635012544, 4823883037538166208, 4812470229139847680, 14040507027709688192, 14038639940949316224, 4817983541071607168, 4805509274672941568, 14035408214278025216, 14035036614773646464, 14035739355815424512, 4809312053682963456, 14038282086058492608, 14044014777021488256, 4817945462026109248, 4815657952001174016, 14044470231760413280, 4822556559184983776, 4819731033665559360, 14047059349763525248, 14029206869563360768, 14046309220833051808, 4817602434335160896, 14047114861219612880, 4814650343617271936, 4816193752358088896, 14042464035020253472, 4821849412880885248, 14035428022684829568, 14040069398432507520, 4805383728751683840, 4809882104865608192, 4823341438746873568, 14047103598397220528, 4820262523631462304, 14047008368067779072, 14043092783527359840, 4823704730762207056, 4823686600044731456, 4820535842771284928, 14047289388162766768, 4821441019148283232, 14044132007970833120, 4823592241207882784, 4809097044155193600, 14036553207955736064, 4809170343200448768, 4823690651786384848, 14045568788876540032, 14039839023848964928, 4815495658276152384, 14043142510096238880, 14044667661348971520, 4804377184246858240, 14036559547074397056, 14028947537588717056, 4819939632983572832, 4817123622609749632, 4819758823408731680, 4822922983748985248, 14038763342059353984, 4814548196696302656, 4814595859187778304, 4814293307734695552, 14031451914127218176, 14047454277665020400, 14044547338072658336, 14042676013325982400, 4823950722660703104, 14035859784584876160, 4821711633490773088, 14039137336233276864, 14022833524913299456, 4822874552451964928, 4823007173792612640, 14038119426893418560, 4824117245655304768, 4816205206434565952, 14037070723215900800, 4818368252873733312, 14045919480036429120, 14044749570872477728, 14043364308773138592, 4821660391531334880, 4820256454065847104, 4820231442658191552, 14043934164815453120, 4811819433064607232, 14042356227007051488, 14029094423779336192, 14037660794830753024, 14036996017993602816, 14041046522910001024, 14047116219678424336, 14026177626017395712, 4819050027016169728, 4823781462658225664, 14047129250563115648, 14031851399433750784, 14042146160743595648, 14039974409580301248, 4815403280020890240, 4822328580842176960, 4818040911621798208, 14041710250584451968, 14046315908512876320, 4815464798232036800, 14040808794125169408, 4822016293584513120, 14043308576447945120, 14046693652007237440, 14045577994213000000, 14047380616614746368, 4808718582135990272, 14044982733111443008, 14038238938183694336, 4823738603176979456, 4799411612127715328, 4821047899071022816, 14047490865833513408, 14044035091755091712, 14042410880368495520, 4814756149736951360, 14047007315568217152, 14022376323223775232, 14041707679464380864, 14041186908778767232, 4823078632967598208, 4823447984648066288, 14044699007395880416, 4820524093171390432, 14039322323836094208, 4816303409342446080, 4811196517421352064, 4812607645670833152, 4824118109127387280, 4822486706433366048, 14010746719618039808, 4812813077972245376, 4819912942786780384, 14039393147862990208, 4809261358601790464, 4802578457651204096, 4819055953343625216, 14047306806092835520, 14045653526069814496, 14044582021905637600, 14039755126784276352, 4823389216414505968, 4811203070307879296, 14046226136989021888, 4814472113709883520, 4810905083817094144, 14043393148676703840, 14039797527143377088, 14044995974956452096, 14040477317544600576, 14046269344125844416, 4808030733178213888, 14042348121230718816, 14033346594218093696, 14042637836856688512, 14038943331040251200, 14037114248785428992, 14046807794943784000, 14036201226957750912, 4823895618915669072, 14038556340029466368, 4822956377903820992, 4824069573376912528, 14043135066660958176, 14026604451271281152, 14038363321840365120, 14043693197255255296, 14046883884765863664, 4814912756393204480, 4814069497504095360, 14034051250771085824, 4822820909601806144, 14042100848433460608, 14036500234451803904, 4816568041285323008, 14045721196433563840, 14047090746736507552, 14047215162764973408, 4822789089314390496, 4822083451364898016, 4819881468059480192, 4808515797837834752, 4821483981221378048, 4816320040953219072, 4817573936067886592, 4818410623036340224, 4815636977908845312, 4811763508050834176, 4803173088059140608, 4813852541820428032, 4818165827782973696, 4819013970154393984, 14037813247431430720, 4813242321747934592, 14040296650756964736, 4822457889284067840, 4814142798008455168, 14044750594843946528, 14047161291673777728, 4810329483713191552, 14036074716735492736, 14038171602412163456, 14039941072745809216, 14042477070087347168, 14043210864203278592, 4815105309413393024, 14007481333521776640, 4818975111574063968, 4813357892706549248, 14047116615475173248, 14036506338757299200, 4818008438152944960, 4818421194522831808, 4813408541245848064, 4810675467103056000, 4823711764081777168, 14045282608274164736, 14046437406945342208, 4789675703982116864, 4814226727953549184, 14045480468658618560, 14046643121006720032, 14043316343048022944, 4819582568191330304, 4820697580024568768, 14026400404284275712, 14038884436626239488, 14039793353905564416, 4821882382221644416, 14046989453609375872, 14028608346519543296, 4813856374925788928, 14046933272341906976, 14041733291849840640, 14046193338964718272, 14029749416615012608, 14008667499160313856, 4821031463613096032, 4821094240267533440, 14043028777688811840, 14045910274105611648, 14023955125171160064, 4822418739057433088, 14046787177892432176, 4818187363512031104, 4817743609349753600, 4820055930851207104, 4819847234491765824, 14044863838920091040, 4823670922938214496, 4822764973916805024, 4808832116202588160, 4811684220456504064, 14046293438160036288, 4820537689466184768, 4821733830774473824, 14046612066301586720, 4817532712770942848, 4822685744375756608, 4818759157899174016, 14028724347357063168, 14041830198129768448, 14036344666610436608, 14040323179555480128, 4823746133896211824, 4823221511981163520, 14046699740007808928, 4822957187907335168, 4819405699738379264, 4819438318464273952, 14044810232557298176, 14046849905972347296, 14042248634109431904, 14044532864438065120, 14035136877280465024, 14046393352858336352, 14039701827418801472, 4822716368445853280, 14039536497402850560, 14039334523410160576, 14039797141231677696, 4823113715985570976, 4817747628290547008, 14042812082446271136, 4813729698985979520, 4820356605140550432, 4809252862094656256, 14046568441523315360, 14046310566391754208, 14039624299785957056, 14031889117283188224, 4819205760061489344, 4821266245190442176, 4823573256897809472, 4818230664775002432, 4761382017729822720, 14046321782092180224, 4823991330419029856, 4816981208511728640, 14046280676724399520, 14043911203190585728, 4821722909307034688, 14042336350419369344, 14043081597176352192, 4822238989999752640, 4813323622230135040, 4819479969178453920, 14046673775195096576, 4822746454817367328, 14037940523917228480, 4808218210793240576, 14044911857947482528, 4822632405562891840, 14047024327850261760, 4824080957566290800, 4823552086410294080, 14044777830772381344, 4819702949337907136, 4816086063520677824, 4820519969818823072, 14022872577629170688, 4818383745947697728, 14046166513966093184, 4820058378580902080, 4817916270469662336, 14042617394985060544, 14044596089363140672, 4818985421984799520, 14046732240460260720, 14043462475813731616, 14037355457397961216, 14044794232562871456, 14028293322124921344, 14045636679319878208, 14042481863718810368, 14047247491105393792, 4822458750819063168, 14030659778785043968, 14043833472166895904, 4822313669184477824, 4817899473009487232, 4803788293057803776, 14043941681394536320, 14042373463191821120, 4823404759023487808, 14044780914684384704, 14039268276222143488, 4816042300707062784, 4815446149316687744, 4815491395841920000, 4820973370017418144, 4822119801271255520, 14021589681635712000, 4809446134923886080, 14042718051431356544, 14044063165685195392, 14047485897162058976, 14037879433503924800, 4823914357040724688, 4824033705821649728, 4814823466447710592, 14041904958291630208, 4822608577643321216, 4800910610103177728, 4810947297500713728, 14030233436446985216, 4816694488678761472, 14047137913047852144, 14045343311827569088, 14046848596280512176, 14040462067435045888, 4823066754800109952, 14034421534334573696, 4813235632454499200, 14032885324730906880, 4822273038293927936, 4822254081173935840, 4820958755975331808, 4824032060406757024, 4823094704385835072, 4824060563548864720, 4819420339598795552, 14015805132095299584, 14046079983205059744, 14036559663417226112, 4822080860488830752, 4810201547902970112, 14038866180848913920, 4820677051769647456, 4814235200910405504, 14046824661375750416, 4813588912007940992, 4823694568251371264, 4814207448614980096, 14031704389383817216, 14033853494219613824, 4817390739517288000, 4816645688451000704, 4817749826578561664, 14038517610490541952, 14046205303469157856, 4822230337757929376, 4806957836876844288, 14047498789056107680, 14047189667303467552, 14039785431304624192, 14044124348115237120, 14041724116931741184, 4824121870661311472, 14035079847618938112, 4821999107498541792, 4822773613800314112, 14041787110701319616, 4813997316342108032, 4819537219386131840, 14036982043067753344, 14046655010716349792, 4822540567279174240, 14047098073610125088, 14040232473459531648, 14038233256023442496, 14039302519583481600, 4820546647750909184, 14047226175328405440, 14035852088016843520, 4823376094355464192, 4823037186739420256, 4819382521750075488, 14046976765202420592, 4815425452451253248, 14043886071298983872, 4821625471008554560, 4816844333957271296, 4822125858149512608, 4820834062174058272, 4823949622974739104, 4823631853929970560, 14046756020457365712, 4824072775279631360, 4823157691523098624, 4819412561842715712, 4821711787860576128, 14044205723979976352, 14042848964047274016, 4815595288338732672, 4811290605164790016, 14041295940152597184, 14044152556144923200, 4823481078326404688, 4819796360145091808, 14040232337328770752, 4819096611732257536, 14042271352187171392, 14046341208751328192, 14043259704623333984, 14039416569433984704, 14035259146595790848, 14043597587962598752, 4823794061722747824, 14045394402041258688, 14041664318255492992, 4824011715294152144, 14047182850784171200, 4818379432968531200, 14040056253711039936, 14024755683593077248, 4815982009750323136, 14043165812760657152, 4799166218741269504, 14046085610239732096, 14039424292079066624, 4822274694427205568, 4794358408973070336, 14046958810460073616, 4807447807406093056, 14018394255620046848, 14038476758997304448, 14045724555017076864, 14037302522624510464, 14046928604667483840, 4822554717644761920, 4822878774813976544, 4820705277458645824, 4816107349473405248, 14043642712354907264, 4823245056493711328, 14045373716489657888, 4819180148419784064, 14045163509224132768, 14043817140837482112, 14025791069688133632, 14044488205247893152, 14044017675137152064, 14042732588460381504, 14046304029965461376, 14045089470708041568, 4823369668689471696, 4821220610727702432, 14046911270526342864, 4817579335270385280, 14044691267028319104, 4821227064853461600, 14042344892263778112, 4820720974439910368, 14022766134604633088, 4823269281011446624, 14043432316949895392, 4818894263721311456, 14040377717009404864, 4822647346481329696, 4821699515430018496, 14028077026423474688, 4817557932702790912, 14044383800484257120, 4823665637029237792, 14043820798354006304, 14033076679602080000, 14042327622374391840, 14047260405945129072, 4820636860018443168, 4812191441784315904, 14037917772226225664, 4823899439311424624, 4822033578944059360, 4805966167502031616, 4823466961012864272, 4821054860756024096, 4822527541706653088, 14043838404532236544, 14044446149810642400, 14044031800027279456, 14038711459048334080, 14040041961306825536, 14026336402234876928, 14046883837249453168, 4821909097932492480, 14044544088370095456, 14043760552704173152, 4819649833376765216, 14036524335305462400, 14044235953127967136, 4819888308368959456, 14042513543893949920, 14046255556696021664, 4821017447808372864, 4808391523058194688, 4821246106167148672, 4823794142716503680, 14045609308200076128, 4814322361633144576, 4824082437111424176, 4815242360691093952, 4823489924531879488, 4821793360149654752, 14039529196834787968, 14042931495374359168, 4822207043214631296, 14045889141034063712, 14046934810695187264, 4819233873517202176, 14042572688586014080, 4819524480379887360, 14042373285444997952, 14046166930287668128, 14044038401318121632, 14046242716416552608, 4822019036249625728, 14046128892999401376, 14045659384835308640, 4821618996238505920, 14033321836878275200, 4817105381495746048, 4819421212509030368, 4815511896646205888, 4819291732207164864, 4814623623362994688, 14039791898298758336, 4822656176961099104, 14045058409198700064, 14043439769165685216, 4821786513163802912, 4800070130247992320, 14044480442594057536, 4815023689511117760, 14046856298904896416, 4824060463334351920, 14047011728189053376, 14047449392218806304, 14043072636762376224, 4822795979625324576, 4820848953200563904, 4819556404437545088, 14033614011256829824, 4814374893833611840, 4793139648904071168, 14035335573727593984, 14045461480156290176, 4821206998364986848, 14036922699826802304, 4815554604340740096, 4821636644830473504, 14041650945068569664, 4820939767798377632, 4797656916403511296, 14044697667089888544, 14041246024578569472, 14036993870463762688, 4820897320492639168, 14041481775051314560, 4818531097727857024, 4802588126438515712, 4820182915473146272, 4823074603746320864, 4809145847237585920, 4798783142015828992, 14034719666053115008, 4821703675051402336, 14044849592187605344, 14044941850175584480, 14046561159826992032, 4819677494563634112, 4810867687044574848, 14033511170465564416, 14040107576756789888, 4820288758912491072, 14034222784986415488, 4823515507520839376, 4813366639822757248, 4816487660728711040, 14042487217769909152, 4819606658237363200, 14045967413130617856, 4818970528373539296, 14046867761976906928, 14047241861057974000, 4792806782283632640, 4823923121266641920, 14038122342859874176, 4813931524406361344, 14040955554324451136, 14033046759452960256, 14045025153353754464, 14041824314132611456, 4813410108420516864, 4817493423868752000, 4818945471047610784, 4811916798496423808, 14038170097712571712, 4807210308010360832, 4818999971588965056, 14044720083864563904, 14046063409632212640, 4820593621986151840, 14042121142850950464, 14047444358045394192, 4821242933447912640, 14045701450705743264, 4822608652257225504, 4816121186125800320, 14022641400520940544, 4822235577594344576, 4820818878147718112, 4821813656728771584, 4823393811335520032, 4812662589977544448, 14043120786420024320, 14044571178147012032, 14045933182683827680, 4822521203257907872, 14047014566700721312, 4820797329466096288, 4821192265000701216, 14041102899453264256, 14037126305492183168, 14047022188183292544, 14045829041139578336, 4820004151318876032, 14039676569325289472, 4821354969070576544, 4822900322234764608, 4820924227351107360, 14032570190573244416, 14044144349825143648, 4817350408279433280, 14038746639715655168, 14035537784849444480, 4814744030119768320, 4819523815871146112, 14045502353302404576, 14045699119794785376, 14043000798510653248, 14046968012069164464, 4819622361926939712, 4820074837716972864, 14047341243289429632, 14025309665505894912, 14024701743558333440, 14040181442697290752, 14028808678629110784, 4797292785021455360, 14042095035215234944, 4816550808046938944, 4823356199020518400, 14035869243089819008, 14036210028218821888, 4807279985289316096, 4823069624276870016, 14044943822533434848, 14042776510329650464, 14042499180403934784, 4821373270265770016, 14045786588700925568, 4811914484471932928, 4806613225654606336, 4823768609204563072, 14043897965989753728, 4818293755620989760, 4819859700468330784, 14004801607202897920, 4824017513547630112, 4823978802077757072, 4811506598032761984, 14037299078074427648, 14033235220325517184, 4815739045043193920, 14047277174567657712, 4823748268781303168, 14028718654629710848, 14044316463565045632, 14046765516897655056, 14042310880665501024, 4823791661560914960, 4822387308009871968, 14044780598653110336, 14044400072611719232, 4820740915992458016, 14040494265726269376, 14047205254244982176, 4818225526970177216, 14037900575915157184, 4822219160874755488, 4812692093784145664, 4821715452497307008, 14041166205603164096, 14044565547953054624, 4814617644740894528, 4822939032789664928, 14034608707708412800, 4822866853207902368, 14047127967245985040, 14046106961386103328, 14045582860543927680, 4820173024944134688, 4804784091795986432, 4807935949926320896, 4809085326616123648, 4820758306097450560, 14047037595707218688, 14046994894871673984, 4814773844798992000, 14043250224867192320, 14039116892766709312, 4814623480008647296, 4823349351674771072, 4821853865904467168, 14043257453802491904, 14043384698312157248, 4808004162349238528, 4815741349821026624, 14043176519562033824, 4821952685361690304, 14042628498912668672, 14044188011937121472, 14046093904052350176, 14041501491335280768, 14042469499688583136, 4810436757785617408, 4818662393499736768, 14046723329011646720, 4823443837227239104, 14045366633413788192, 14046968887098845280, 4814911163004364544, 14042447825700077568, 4798283492030341120, 14027072700842153984, 4820194441192439616, 14041711858580995264, 14038069383084359296, 14026590278867922432, 14046896907735844352, 4823803140673402448, 4815776664945193024, 4820261429951379776, 4823226737069167872, 14040117196345040320, 4819609571130025696, 4823557386918859584, 14044691078301435360, 14039872306803966656, 4820136525520219488, 4820440095280437696, 4807428604124868352, 4818200200854840384, 14043078065489555040, 14046851247370771712, 14042615905046766656, 4819419559074095648, 4819112756380643456, 4808948302827880960, 4820130107936008704, 14036698063470440960, 14046903312288905408, 14026588781053335040, 4816269192506426624, 14045850795683210432, 14039252365685061440, 4810020597805412864, 14045356094921604160, 14043097288932800896, 14044665434266344256, 14044562962925736768, 14044516530214969920, 4823414511899322128, 4820204739225923008, 14042542236139031776, 14047100595192298144, 14046729058137353536, 14044796766035074912, 4819966076551926592, 14031825281874523392, 14041096210268183360, 14039544134449878528, 4823383796766809392, 14047492982535475648, 14046301091467990368, 4823862562924047296, 14047249839214803536, 4821006253017118080, 14040428187817643456, 4824005993688368320, 14045138135432056544, 14046446365037435488, 14038935721085282368, 14047471169940503792, 14033495835719313536, 14042798896398731776, 4813157751014127488, 14044474447533584000, 4819567554994267392, 14040431189854779520, 14043090970797978144, 4820463635250632032, 14040961570653283520, 4785209584446308352, 4821073353742914272, 4809100580981404928, 4808607489358899200, 14042846816211251424, 14030700313171563776, 14046720907453635680, 14042920768275761344, 4816644796496144640, 14042497014721546976, 14028145922326999040, 14042465958683418368, 14044255534365527392, 4822617211641397280, 14043122364769447616, 4805631511629792256, 4810205474183461376, 4819606117760729376, 4819049237311854400, 4819638313986968992, 14043789396857654336, 4804022758989834752, 14040964261201084992, 14036392944012153984, 14038391049626679488, 14030847539825835264, 4822839210649299776, 4819499685647439136, 14040253761405135168, 14032606430339451648, 14045174730775718624, 14029735463763564800, 4823038293124335712, 14033238609233370624, 4821316923062445408, 4823074215882770208, 14045908717898737824, 4802781908572011520, 4817384894172195072, 4818144007497931136, 4816665432062572160, 14033354940862010880, 4823914536535917280, 14044295144949067360, 14035870561435002496, 4814539839156746432, 14043215015797880384, 14047315189023095792, 14035369152291028480, 4808681504791904768, 4822493077036618048, 14033266594244150272, 14043932721849060672, 14042948378965998240, 4822978822084341600, 14032741532056719104, 4819249622307109536, 14044748600480618240, 4817576212678360192, 14046405478477518496, 14046847117436838192, 4820149646918266304, 4823553674312880880, 4815301385385155520, 4822312140696970912, 4824032081417544704, 14044992801371797696, 4819349535848911936, 4823584106532590608, 14031880114206224640, 14047329892044412320, 4813463750358693248, 14043127682725156128, 14042550868905487392, 4819526262316173056, 4823492042802582928, 4813747665811519744, 14038408769714612864, 14025515924506802176, 14040206776833417408, 4822275175649790528, 14041651661965319808, 14045853943419993056, 14043505194734274752, 14039929575754856768, 14029446928943123968, 4819471829690483680, 4822358238606616160, 4815952782782718016, 4816579803919977088, 4803172268559085568, 14037574520474544896, 14041023293749826496, 4819669316338293184, 4822381886685121664, 4814949541608513024, 14046518209777144768, 14044962088148458176, 14043712021470579552, 14045462025555960128, 4823290296369894272, 14042875242047187712, 4811227996257409152, 4820094657302172000, 14047268026412358496, 14044261627055153888, 4816676027372550080, 4818988112406057056, 14047168323392133104, 14036812146916278144, 4822647148745983232, 4806416580925257984, 4822687338421398592, 14040659473392140992, 4807617116341448448, 4823754125084250656, 14041898383959664640, 4823928215263594528, 4823590608007128736, 14046984033857514832, 4810656040128120320, 4819166525645750080, 14034041966182391040, 4822822987161371488, 14045127101047551840, 4820068862666826144, 14043434095527401760, 14040921218767197376, 14047495591310846416, 14046903687920233824, 14042797441888326400, 4822894497633561792, 4818982771651696608, 14043137429542590112, 14042750052873796832, 14038252924793468416, 14040282646075979520, 14033895360297905152, 4818821017394163840, 14042916399651292128, 4814798536125483904, 14046806191966722304, 4823139113113045504, 14015297166206785536, 14046827572606184720, 14047080180235629808, 14041618148976860928, 4817363782277768384, 14037345265549837824, 4816921621327639168, 14046700883851729792, 4812798785083198720, 4819777826789112832, 4824093621144554736, 4821050479025166432, 4821499796823920384, 4810080753381523200, 14035266888196645504, 14046152857191322464, 14045147555265602880, 4819720101365537216, 14035884162226495104, 4814557221934779584, 14028975157409673472, 4823557713114728720, 4823011986069562560, 4814353235093053888, 14046113294532890976, 4824039762260425360, 4819140546758649024, 4815737341935295680, 4815435286943200512, 14043610898880614688, 14042238454686872704, 4822589053593557440, 4811562170768949888, 4798285318942627840, 4821598444014079232, 4816137313013105280, 4810772711755612544, 4821153687260206944, 4809418545373824256, 4823363559742400304, 14045337467805364608, 14046314655885555520, 4819478119637254400, 4820824064880936960, 14042617384550599648, 14046529274567364192, 14044756763057829536, 14030372190572887552, 4824074930273949312, 14043260157563907072, 14041404044477393216, 4821675538426049472, 14042047253238559104, 4822573073662088960, 14024232844721237504, 4801746691493966336, 14042024041810355328, 4817468615484937728, 4820419564910000672, 4820037981555363520, 14035413828192259328, 14029374584420809216, 4820125659001981920, 4822231509270238976, 4820084760969442624, 4807221227979781632, 14024955392120029696, 4815923338424602496, 4822666603030589888, 4817857794247714880, 4815815094706722880, 14039111549850603520, 14046810693373296288, 4816792165915616128, 14042480920902775904, 14043147966907082912, 14046633061170736640, 4803887935008955904, 14047447627957748080, 14025361448608221184, 14042481898715989632, 4822695462269299520, 14031561667074544896, 4823926475793359232, 14045111035514535456, 14033792475926343552, 14037740230693659072, 14032282177726076928, 4808147722149140224, 4821904534654980992, 14046352571106276384, 14038572443947110336, 4819841449235128064, 4820639502405138368, 14040803203057666880, 4820325840742393280, 14046838066772351792, 4788234228701003776, 4819746011374314432, 14040290217118963584, 4801568121055811072, 4821642371227288992, 4823859126348224128, 4822472635232691392, 4817395005835428160, 4815561947371879232, 14045612890817049376, 14041556355980214656, 4821271401332285600, 4820785860094018304, 4821807788617917888, 14037922882662542976, 4818149007691290816, 14042374597710097760, 4810322861417925504, 14045073620949091104, 4813468108857660928, 14041187569759368192, 14047192491651720240, 4821234452466636992, 4818342463455319424, 4822782853860455840, 14038532268403006656, 14038776597179011520, 4816140734456347456, 14036383282552424192, 14043860887023185824, 14039366923205984128, 14042853905491540096, 4823867769016818448, 14042038332447023936, 4814029249873877120, 14024977505123907072, 4822596351476697152, 14036603772330247680, 4821667776901388352, 14047173462717938672, 4820019591090057632, 4823640503739676496, 4820298114112882688, 14043783508696328032, 14028726705776916992, 4819628803029101696, 4823318710764586240, 4818970967084412864, 4814388435310996032, 4821298175323663744, 4819443772850088160, 14042759174029573536, 14046851936453335328, 4821852725460364672, 14038131602748077120, 14037083922071075840, 4819163326499610912, 4820948724870138720, 14044040439348105472, 4823784312647558816, 14040969568888977536, 4820908349952007200, 14042755081944579840, 4816556754237347136, 4820193859696014240, 14045762037814251072, 14043224991715790112, 4823873628123189328, 14046419856357617280, 4821573046117805824, 14035737978225647872, 14045940787308872320, 4822957791173172128, 14046835227131674544, 14036756773597010304, 4821015227653029472, 14039382347475567616, 4814385784409341120, 14033447077064123136, 4810745352876379776, 4823831421451721440, 4817115890056272704, 4819464457500141728, 4813724091834970752, 4818029070339465920, 4823358951554819424, 14044001591236914144, 4823607839163985056, 4811772911301224704, 14043056632030466464, 4806416960801803520, 14042996277296042272, 14039648365580371200, 4820152409711828192, 4820642108352588928, 14029090544416495104, 14041179479721601536, 14038340485397973632, 14046472002264079520, 4810726478000431488, 4812009031527654400, 4819315764315930944, 4817317575146479808, 14045868707891930848, 4821658017381554144, 14040757173430545088, 4814447920884705472, 14030005929563398144, 4802073332771989504, 4822128050040569376, 4822359116259091168, 14046325319246567328, 4798595665430469632, 14034379409710560000, 4821891553341924320, 4797501343319888896, 14044255277761127040, 14043973271698199456, 14046689262494093248, 14045764001054923488, 14034054619097519488, 4819601995670726176, 14046954568177349824, 14044406139628367264, 4823401493582609232, 4822416999492889344, 4820050606249603456, 14041729305763569152, 14039655485946678592, 14045766340286793728, 14040271984167585984, 14040068671774277632, 4800418279539573760, 14044601480897545664, 14032304512413818624, 4819238340117434304, 14045303005801748608, 14042052206746599936, 4818709615573168256, 14047238791822630944, 4820616519029229856, 14040734105350532224, 14043536928763529824, 4821182466082456960, 14047132411445369904, 14045526532385780256, 14039398073026549824, 14039320474256265216, 14032575787568917248, 4819224304095574112, 4820798639573090464, 4816803522852885632, 4816690685012090176, 14044419713595851520, 4815882743657667968, 4815627252727524736, 4821439474473379424, 4820457307381208864, 4822114080786367552, 4821072314498901696, 4822960767583985696, 4822119231875931200, 4820234832863064800, 4815964594203463168, 4822125426508014368, 14046439196670498432, 4806951098695948288, 14046157477473920768, 4822634881928081888, 14038034950202540608, 4820677684055701728, 14045369508204984320, 14044122534704717888, 4823063123614395520, 14038968612466453440, 4823482431263559264, 4824086635725295776, 4818021184677034048, 14034115880897733632, 4819966612056855296, 14028856255443871744, 4800970581927577600, 4811537776786762112, 4822273483660427136, 4822261797596690656, 4810073792655816448, 4820682091626689152, 4822520554778299040, 4809573375960721664, 14033507278063002752, 4819985856232579392, 14041838307938890368, 4820345444333655744, 4820045267160635008, 4823412697257961792, 4818000365087560128, 14041737325021053504, 14047420526262344784, 4823910521414846000, 14045717418532570176, 4823490868950751600, 4822367534293583520, 4819676090810798944, 4811349907640715776, 4823629015488249504, 4820422126990451136, 14042952444763607680, 4819470720981846400, 14042642332972833376, 14042879472544650400, 4821689528655304224, 4820456291005022720, 14045670581054078720, 14043533367729650176, 4801290734701679616, 4815957326919023552, 14042269834789089376, 14044890606275740736, 4805823458217711104, 14044227724496891904, 4823402092703335760, 4822608778533371456, 14045645732149140416, 4818546952019434304, 14046986317644262624, 14047017506194726832, 4810372028260206720, 14038123799911812608, 14039190125026145984, 14033897456602033408, 4822522716631995136, 14047277130431192832, 4823048297695750368, 14047160333283775552, 14045884679782399968, 4819005120583910944, 14045210385634400384, 14024182039035762688, 4821503792210971840, 4821239335458938688, 14029227748219801600, 4806053637299426816, 14046959868323274320, 4817859294125530368, 4824023714355564032, 14041619919901260416, 14046344807772762880, 14045728851633937376, 4823996386441260224, 4823231065333489344, 4815340192858770880, 14024570343524751360, 4819074915229193536, 4817140994373176192, 4806987178036726528, 4821323123908480320, 14039472839561286016, 14043310271355162464, 14033691387627211008, 4823370929661135536, 4815816211742494080, 14040717840444771840, 14037221380182369024, 14035238055346100736, 14045517733303433152, 14046736322858406528, 14046834828517165536, 4821757995531734848, 4816864785469041408, 14040887163328182144, 4815875329662489280, 14045265484758465344, 14041282294720095360, 4819505244894497728, 14041105549822131264, 14046973493111895504, 4819206136788759200, 14038365770000307584, 4823427509993365872, 14033010494170406400, 4820446292889421568, 14046794481251997888, 14044648872133409376, 4819249534589534720, 14035527248940838656, 14034261935081950720, 4821114772958933984, 4821449709258136256, 14044634765029429536, 4822502883067568896, 4823750421928062432, 14044475807416224640, 14047395748166022000, 14038624747672163584, 4821953175416184288, 4819337235590158304, 4816176896428906624, 14043552516085828512, 4823659750748469504, 4823683180204692768, 4819997721808574464, 4815874811355983424, 14044557403550214848, 14025471573734111744, 4820066535420159168, 14032070845741869312, 4814013559997335936, 14044613861689086528, 14044770624394437824, 4821753792832931872, 4820674071879711584, 4815143732755754496, 4823696691243399216, 14040690485748854464, 14046372584328571552, 4810316635939921280, 4820058528214213472, 4814589008542662720, 4823019936059684544, 14043745495751175296, 4809960520597146240, 4817891850758788928, 4819871283148638688, 14045981412032529152, 14024263113188784640, 14042363120210719520, 14035929970487290496, 4821586563237456672, 14047213692821423168, 14045648439711035456, 4812069453271974272, 14046489394534793600, 4818862190486623072, 4808013714969195008, 14041167052405707200, 14046821750574420768, 14036010153277055488, 4819386390564190656, 4823781272583221984, 14023960969868794880, 14044126354803288000, 14047070891540887984, 14042892667241457120, 14042790486042985952, 14043417583987223840, 14046822480908767856, 4822443996441927104, 14041182822950817152, 14042470704843533632, 4817810673950360832, 14028254104561745920, 4822853609835256000, 4822687333974972192, 4823105465648033632, 14047168012439471328, 4816515961740858432, 4823655675590455088, 14043630635174836448, 4817238579574709504, 4818887415767244032, 14042948046481616512, 4819499091780365920, 4814537184253533248, 14041117198205066560, 14042269925194334528, 14038993805610214336, 14047085432758954080, 14046004408873853344, 14035307190491619456, 14035750526682482048, 4812935339925737600, 14047392809644506672, 4822050445836341952, 4822276249439436576, 14025776736980483072, 14046451362205787168, 14037794483080965056, 14039099824723814016, 14037187434997084800, 14042520867569309088, 14030876598110204416, 4806439727629671424, 14045370440314431648, 14028462420745052672, 4819831674947039776, 14043180639921156608, 4817196335626270208, 4810518035491653504, 14044514992861280736, 14034100268864493824, 14043428755539938400, 4819292575565933408, 4823404944481193360, 14046532532064297216, 14047472477624072768, 14043796311434510752, 14045823429637120544, 4817094531227128768, 4820273109354296864, 14044187814073736352, 4820681851865697440, 4809819994148775168, 14031928359088231424, 14043303660277451360, 4823682648839184192, 14046785722576646656, 14040611234845209984, 14047323800234668544, 14031218062741227008, 14045293700618496064, 4814655726080799488, 14043819821868333152, 14044990505834243872, 14042901196048561920, 14046538964966124160, 14040995813292683136, 4816648289674201152, 14038059195782628480, 14043330863112450048, 4823301218443024832, 14041088300757269440, 4819176144373985312, 14042796397761668384, 14045435018910573312, 4823404304185780400, 14039555351035942336, 4820920303791018880, 14040854872510018176, 14046743312847922464, 4822881867229273152, 4822870278549681056, 4811103157650820608, 14037406497670069248, 14028703409747387392, 14043621620318579776, 4820726158279935840, 14022755949943558144, 4817424135002080896, 14034183528196808192, 14046743189766499744, 4818145017427955456, 14047098241361704912, 4822031672980739488, 14047486743546703440, 4822720214560048832, 14046866291759700288, 4810690458462979840, 4823357412844257952, 14042744863780213952, 14042483051657633024, 4818970366540676512, 4823721411484328720, 14040676837878843968, 4810095970686856192, 14043516463327118080, 14047208816258402480, 14044244102809007840, 4817728788172846912, 14046683228058724000, 4823387798116752080, 14047210412729299680, 14040925792872235008, 4798877000723968000, 14045414675307446080, 14043875385242020992, 4797879142046307328, 4817921002095611840, 4823743980582138848, 14018857531252613120, 4811018041032142848, 4822554275062634784, 4819271512461310144, 14047353681180690992, 14043478909672306272, 4823505019154075792, 4814124833699803136, 4821114957311013824, 4810032675234218880, 4822825136326632480, 14040903881332537280, 14046618424900302272, 4815706534555082560, 4816557647165239360, 4822282997572038240, 4821300566469104608, 14044452451623232832, 14042249790520235232, 4816643808720172736, 14042345021733912352, 4824030406189854080, 4819463084060812512, 14043765414262537152, 4810206240462452352, 14043923729116800032, 4814299821805958272, 4809031675552807936, 14040575704732681152, 14045961286555755744, 14047092257262150464, 4821127030371987712, 4815680639666405504, 14043989989130508640, 4814495686803074240, 14041013770551388800, 14046804052561675792, 4824083484623816768, 4805959629248404736, 4819254724173426144, 4815498382544308672, 14045240350390341664, 14043434896227629888, 14046242209451825504, 4822075008167544800, 4818900657748672256, 4824017930179475040, 4819035268997084256, 4821198595678204736, 4823866870401895760, 4821687226397580768, 4823457498141729136, 14032766839416975872, 14034180913410412928, 4823270494794457024, 4814228505680265088, 14046502457513541216, 4819843442159029728, 14031221433860364800, 4823218008825225536, 4820770492673680768, 4820907245418401568, 4821799766882749120, 4823551620227722784, 14036396276658314112, 4822683185419534592, 4821021667082329696, 4810658381506673280, 4818326933037005824, 14040019254838181504, 14047141118489096048, 14046851990945858032, 4817899070559940224, 14043664375618992576, 4823358103274378544, 4814633522209839168, 14044434554669951840, 14042464678335108928, 4803947108354246144, 14043729159908509120, 4806752781581983488, 14039512807242246912, 4814182576743198592, 14013310543475191808, 4819572507635344928, 14032217613873326848, 14046877226571895632, 14031883947433794816, 14041134052009196864, 4820262456286575040, 4823102712585947296, 4820812845360118048, 14047364617322776352, 14043184012347870112, 4816685999375297152, 14047322654131286768, 14044134362835530048, 14044413255469116608, 14034164336633090304, 4787698460410433536, 14033456942139026048, 4820438074479234272, 14043663622764917952, 4820347709485749536, 14047041855185071472, 4814837930561079040, 4814896320994780800, 14040951312912705792, 14047145540870023360, 14041513833326171008, 4822244114432649024, 4824099341068386240, 4820877528574901952, 4814397176188211136, 4816095989087295040, 4814398741154217920, 4812869438225019008, 14045327725506778368, 14038823124142416256, 4818118098727541440, 14045050372325388480, 14045736641499755680, 14037389938219797632, 14044296384704244800, 4819493595272932384, 4811047750359747328, 14046225899084480832, 14046895973279952272, 14044402994596927040, 14036576705465070592, 14046253512832852800, 4820117361875512288, 14045011063567676320, 14025432054961825792, 14047021960672323840, 14045151997080962720, 14042613099088985024, 14022039240238833664, 4809878213988696448, 14047009627734491744, 14033820054263929984, 4821319698923306496, 4822955497384013216, 14047276388020295184, 14047096184241382528, 4823611135109299216, 4818857901030648448, 4819991900036441696, 14045019654580228288, 14033462813119154176, 14043566788775828800, 4818171916692428864, 14042436133615592096, 4822339466750503456, 4817660958014563456, 14046114236509905632, 4820567137475811360, 14042977698243467072, 14047202509523767072, 4810023793922915200, 4823672534259544192, 14046903960203434752, 4802629115109755392, 4819462104396276512, 4812742613521022464, 14041319921609080128, 4822777110685846336, 4820803370591781472, 4818564115490740480, 4823922322425850448, 4812402951175645440, 14033518230887070720, 4816160224236722368, 14040547656584289536, 4815258088449519808, 4816665446776801856, 4821749414027722432, 4821658077509654272, 4820598676166545120, 4822901554356922336, 4822811876720564416, 4821861187996165664, 14039426922870091520, 14044082577254496960, 14046939850957662064, 4823775979979532832, 4823203846411833408, 14046639349080753536, 4817248548485416384, 14041112161043629824, 14047125616403237680, 4820156295970459808, 4815062623491864896, 4815287171972422848, 14044392931892569856, 4823123590979828672, 4821026966198218816, 14028092806058881024, 4805459034923118592, 4821426196700519872, 14040566195010002688, 14040567022575945856, 14039209106098959936, 14035976994464630272, 14039341238410081792, 14045948473375729344, 4819525811375133600, 4822234098134713472, 14041126459144131392, 4822877398980337824, 14047382703435330128, 14046964242539972928, 4804761455703464448, 4823252973748797280, 4821781334453699232, 14047102543725413584, 14047230505615006960, 4798404689703901184, 4821770082167910976, 14046833103580599744, 14033590219261963776, 4814285438091985280, 4819188577589261792, 4807581900448057088, 4788229220792360960, 4817586859723202880, 4813483577183812352, 4815855429285315264, 4814915057301381376, 14038845522429040832, 14038536283360610560, 4815989346122288320, 14042298156668553120, 4812764814252530048, 14039025463701560768, 14041740394287555392, 14034363885515192448, 14044435557273584096, 4813182912998061184, 14045320263552488192, 4817176567279651264, 14030865552733326592, 4819176655909761920, 4817626217967129664, 4819170569235376544, 4822620760926410656, 14042656347952278304, 4807587715613936640, 4816095088198837376, 4821563891152559680, 4822935863857873120, 14045307167176802464, 14043388248859445600, 14034150862208892800, 4821319654284821056, 4820771116049600832, 4822686954182576992, 14042531582392307008, 14037205680375455616, 14039345402214513600, 14036936694793475968, 14029535206724152064, 4820767578646556384, 14039724192881549120, 14039236788833008256, 14040012737763614528, 4811115643675009152, 4819935651310128128, 14044181276260289152, 4814890797881035712, 14039456412996557824, 14045428678483319520, 4822933752871245312, 4822384383068537152, 4823574143491257328, 14034676801947316864, 4822132900080793120, 4822892826528701568, 4822616577678764192, 14034164286534441088, 4811101677600318592, 14045849806927348320, 4823808520393398512, 14042747041188638528, 4820937431326125856, 4816222786347003968, 4812588908975165696, 14045672835051327776, 4811796911361400832, 14044616555411920960, 4821712305243947392, 14047024814661021184, 14040296648016037952, 4821976839110633344, 4823834746414167616, 14037766440292819136, 14041585671469505856, 14047382033960289152, 4818914562640192224, 14044810836460242080, 14040318143590506304, 4813172150722496768, 4814567200328487872, 14045973751089579232, 14039974436792780352, 4814017694229352704, 4823374971972368896, 4811705943173248128, 4823387947946393888, 14045704697300347840, 14035606548230141440, 14047135251221734544, 4819271609366685024, 4821711502139901440, 4823307836216475520, 4820124345830491968, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4832045740819742728, pinv: 4382166536203340112, mod_data: ModData { n: 1086317488242689, ninv: 672148569487374969, norm: 14, }, primitive_root: 3, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 4823669075673047008, 4821074455055476960, 4824464537976271760, 14048002495736585952, 4827439284260349632, 14045174112482972512, 14039465322840855680, 14047583530830462000, 4798363000744307712, 14048239708373958992, 14050731133834628688, 14045823572033926208, 14036443235440844672, 4809811901440654080, 14043401806652668352, 4808386844270543616, 14046190428065778400, 4817669223458730688, 14043371806395188608, 4822976686508107008, 4824081006318536176, 14038968715275889792, 4820995090977744864, 4815514108829272640, 4824223029550427296, 14048023909235321328, 4825184773604796608, 14048926648418871232, 14045264925715693408, 14049487039993555776, 4807139543325878784, 4824694269976575168, 14047745396193975056, 4807414549950819584, 14050283736512803712, 14047380340439613968, 4822245813524250784, 4815121391312415552, 4817319226064926656, 14046026847444144288, 4818542464428741952, 4825474976241824960, 4825883541323858144, 14043630627172369888, 14038210136376732416, 14048095265420288624, 14050146014957033344, 14036703814359031424, 4821179515390904960, 4825254774599650096, 4818943853169667136, 4825344953747088864, 14049223642061362160, 14038104667124981504, 4814642515765468160, 14046875111226459936, 4825274776540997216, 4824758610727820256, 4822047654827000032, 14043071888295319616, 14048272450443581408, 4822809755460662048, 14048371011079552256, 4817890523762114880, 14050078310196389712, 4811518488726426368, 14050309357289728432, 14032911088151142400, 4827439317977199872, 4823676834199080496, 14042791722262758368, 4816645695503448768, 14043772842778193216, 14049284017012965184, 14048601325101869536, 14047718930951295616, 4819267058212090560, 4824099035806433072, 14033006406012555776, 14043499847196152128, 4821391322272425856, 14047502591584659744, 14041594654704280192, 14048388332327342688, 4826788402113082880, 14027957855955036672, 14044349817504397984, 4822785975466479072, 4825021337472606464, 14042117320824563456, 14050045834334406448, 14045479945677456640, 4823934452865734304, 4824021508034647504, 14046523383579655392, 14050613509346282560, 14039688745224568576, 4823777794160657616, 4827411646543862736, 14033469933313939200, 4824561909263682464, 14040881506509483968, 14050009786714029680, 4821737654230683584, 14037826153710720960, 4825211351128951216, 4823947906853884240, 4824929118128215600, 14046566347705385824, 14039400665966879424, 14049833831990796528, 4803965375031389696, 4804033221111239680, 14048609834703906304, 14048876309803297680, 4825058732463787200, 14046281325866019808, 14042656181443171392, 14048468389490078752, 14046629866667473824, 4815648663079374016, 4824636691110615776, 14046292328489376224, 14047234639821289872, 14050560215382968176, 14049631567673748032, 4823148432576698336, 4802943429249333248, 14049396806737399680, 14044576390503023744, 4819402246238207200, 4809004640979239424, 4803348419635223040, 4811984509382260992, 4822383556949577344, 4819119172704411488, 4819442373740876576, 14047358631759256576, 4827527633223030416, 4823581603372731232, 4826333822449531472, 4824434491347899040, 14046231939514884256, 14047839749561180624, 4823302281790578688, 4827332296145373568, 4821004722894627968, 14043428318609857440, 14046464745538966784, 14044430118382302240, 14046962868751032240, 4819749396157453728, 14047720029535616496, 4815689013086704576, 4825117483528982000, 4809049348110900736, 4822250853185248992, 4826784585253298160, 14050013836007357360, 14038247436067576896, 4816623911501482112, 4809721466716274944, 14032104006738276096, 14050453813473198416, 14044827212156913216, 4825814047818603664, 14047696222193534336, 4819935698048810304, 4820272253567008224, 14050394096636982688, 4820961846915642400, 14050214420523755280, 14039463322110126272, 14046654697802883296, 14049135136049004992, 4815835742090743808, 4827103202308012656, 14046442482662991392, 14032980059939564032, 4818178058703800256, 14031953734386717696, 14049782453639499536, 4818455757661749376, 4825920593060035744, 4820501258139105088, 14043400192667825760, 14049304658124207632, 4826568395635961696, 14048703594788780624, 4820152776394181024, 14048537087304784576, 4823344774229103744, 4816707756803048832, 14047618536844999760, 14049775357525453664, 4814772330083138368, 4827420245671905808, 14037924894210417088, 4809897730877532160, 4821184383292930400, 14047543661664225760, 14048638760050180800, 14047369323019232352, 14047849344985776672, 14046936203645396896, 4814891176592263424, 4825387344334058000, 4826743556251727808, 14044078116837800704, 4803341727680464384, 4827414730611485440, 14042747480909186304, 4818124830547924096, 14048714295026209504, 4825930031181648880, 14050487440567268672, 14046266506787087584, 4811767368486241536, 4826682832693370352, 14035679294129261952, 4825775857735184160, 4825030095907060368, 14022195793590770688, 14044300021171104960, 4814518461424370432, 14049487139996102720, 14046070997212271840, 4826268793383341984, 14040023801552677888, 14029954758406551040, 4824383474699739888, 14044527367765150592, 4826539774740602896, 4811936105639091584, 14046897708320262816, 14027441443096358400, 4825937439798110320, 4824750672857837968, 14043111181614510752, 4796984850429614080, 4824438361337115008, 4822121441594657312, 14046875487308859712, 4825565678444384448, 14040433727900966208, 14050835357100859312, 14049088240414533680, 4824539341897979664, 4824390763060039760, 14046739705553552720, 14050542238461109536, 4822375761204541408, 14047627358704858976, 14041209662298350784, 14049975128274292416, 14047218219103102384, 14047533272021738320, 14036558530282903040, 14050314400576337584, 14047688371808784528, 14047400949758842288, 4824878335747892736, 14044198019162131104, 4827413344841394544, 4825502070144544048, 4813124933629621120, 14046538532219547392, 14048464581086399472, 14048853380031323520, 4825899505590411456, 4824227957268193168, 4813485207076762880, 4824938087296934864, 4825466350429488000, 4822877910404392896, 4822033347796440736, 14047520654944302096, 4812974512988636672, 4817513278571148928, 14039105229129261440, 4824143723196474688, 4826438126922600992, 14046090930232306496, 14047440142812144432, 4825821199555780000, 4825242251935149152, 4825344557574263296, 14029362673351473408, 4824553695908829728, 4827200774914309184, 14032779564718697728, 14047378468772007936, 4804346442806902272, 14043539288856989056, 4816548937806409408, 14046636351351898912, 4822567550447625728, 14048145064544052272, 4825954776696536608, 4825275041514837600, 4825171923706505408, 14043433243494698880, 4822057195094010432, 4827442164502080064, 14043575592671461728, 4824512812840564672, 4820367435398346848, 4826646780773983472, 4817971560207341184, 14035138585708664960, 4824708695056569184, 14044840415547853248, 4794942435704320000, 4813614598824218624, 14046864234405290544, 4825872643584083520, 4825124448481593632, 4826732744772695504, 14047893795576817808, 14042705121682420576, 4825368735764351472, 14045403131278602336, 14047308711687675504, 14046962429182494064, 14049282401120782240, 4824304440995204800, 4817506698370480448, 14046248643692129248, 4815594164916306752, 14036920489128619904, 4822096166890467200, 4815780323351711616, 4822621976458002048, 4818936132427483840, 14034441510654750848, 14033409571470493696, 4826346738386027072, 14047563968588042128, 4814699469008606656, 4823815188190957040, 14039606925036258112, 4819847602078066400, 4821544525797217248, 4824669260376545424, 4823927018555261024, 4812819383269788416, 14046833901108044256, 4819283554150873952, 4826116757227458672, 14038431583242843712, 14038390930967815232, 4820412992442146176, 14049220816671762176, 4824956053214170320, 4820252989827651584, 14049010785158733680, 4826039612838542352, 4815327208107521664, 14048512799808813488, 14037068283532484352, 14044295226939709184, 14049413994963762752, 4823925675993854896, 14046309163702963968, 14047880879843850816, 4824707508981109872, 14045726704666720992, 4827282687894680848, 14049460838775650144, 4826377726238276640, 4812003281287413888, 14043601869758682368, 4823289351738063072, 4821974746981674656, 14045243755266945120, 14046791047058545040, 14036920018457088000, 14047797079560177840, 4824627395782606864, 4824148908627448928, 4823488120076808000, 14048650841191402624, 4825505594331450560, 4826573194393033152, 4822568027987764768, 14049807963597616384, 14034175756783419136, 14041901302763657408, 14037079691831737088, 4813686074082473216, 14030064716923749888, 14045887661478971488, 4826118309940170928, 4827027249126472368, 14050158947176759920, 14049354830472744064, 4815616631111631360, 4819992598618900832, 14044194233282059584, 4823712699055877264, 4825018352088548800, 14046897227593925504, 14041604000149550976, 14040560266786768896, 14048967780734609792, 14047840323819025216, 14044325931583514176, 14045547485985099808, 14046631565103956704, 14048551069591981312, 4824794158486501792, 4811422361474846848, 4824950247308644176, 4825111990250182560, 14043101314036845216, 4827052454849733232, 14038017500267018944, 14040305083250122880, 4826042980419585104, 4825342870991037216, 4824345918573050960, 14044268591040691904, 4824232359648627792, 4819095538717736512, 4825592566920967504, 4824155977869705632, 14032901262052418048, 4827166364929704576, 14044702639346002720, 14027394674715025920, 14047938656523355600, 4825724886335524496, 4823653336949540496, 4825858236687455376, 14040328641177979328, 14046324230905685600, 14048449633302727024, 4822633743438984128, 14041275186719642688, 14049620416879981296, 4823596465737975904, 14046605937688023040, 4816312569683389120, 14039205226164440000, 4823385745818104432, 4819648477556025856, 4825755172146410496, 4825622765449648928, 4815361583976938944, 4824713188744657744, 14049028327055436160, 4827305698993413904, 14029661602861399552, 4817686341641616704, 14041395471567971200, 4823997409702007600, 14046099648078241280, 14049511999725689808, 14049142078802085744, 14043696076429037088, 4823833498319832064, 14037873040031993536, 14036108229920586624, 14048746745203428048, 4825437259130218288, 4823317370725625952, 14050820871013216032, 14050256815821251744, 4802232718919720448, 14040619075253068416, 14050296154584916928, 4826499751522105376, 4826833756388793040, 4820342546705239584, 14049809462564536928, 4827332662364497568, 14046990049847494016, 4827426402078713232, 4823913864879564000, 4817588255977783296, 14047400696779163312, 4824324443623408960, 4810325341099306752, 14048806887871202704, 14043790796546123680, 4822761639474895072, 4816575825813205440, 4810149439538732672, 14046549005160757920, 14047120466166117120, 4825035325271754192, 4823843293609031664, 14050361129275027344, 14030109335402705408, 14048576876456287712, 14048999259784570784, 4790925337410015232, 14049980284560711872, 4826213771281123840, 14038175791516320192, 14047381052028298816, 4825250805728601344, 14039469659193018624, 4813118754624969728, 14042345909057223456, 4825207612711029568, 14046821627311010048, 14049701615942508384, 4813818125305525760, 14047325910355584624, 4825907182981559904, 14049096289898746624, 14037167020144745856, 4824736967870173520, 4816789162740948288, 14041582344218197120, 14047971026127931344, 14045344112028650656, 14047662222744629136, 4822314102716085952, 4816853376218690944, 14050052232207516416, 14045591215317552768, 14050280918360536480, 4824732898298706032, 4827106723794861248, 4827106688684748928, 4826431103400572112, 14037403549302600832, 14049080723883127296, 4804363289251495424, 14030185571426728960, 14038397699034456064, 14045714778166485408, 14048600410042614656, 4820046394897588800, 14050087337343283808, 4811207210550991488, 4823459273999405872, 14048204491775548864, 14047877046328385536, 4826189115062196864, 14046942449006734160, 14035292849025363328, 4824368563833866912, 14029830211734635008, 14042360205479957376, 14040748725018832384, 4827417388923238144, 4824214415418328080, 4794572512130633728, 14040704638232068096, 4826023450780372880, 4822057102906710240, 14048575305002802496, 14049453498414305040, 14040672410733960768, 4806661874397268736, 14048064619753234416, 14042485457419007200, 4818454219423700864, 14050812107621478640, 4824053940518913152, 14047032699674498272, 14040893024799306432, 4821972793164645472, 14046447913518408608, 4814733385354665984, 4803005377339220480, 4820997982661777472, 4813812449711378048, 14038224756913255552, 4826217103919067648, 4807414013853091584, 4814500654973011840, 14023677137426848768, 14049193694176265584, 14047284826100604016, 14047244433643270448, 4826509870751570768, 14048449038250270096, 14048445421564885312, 4812895393896041472, 4820277622734007936, 14043465674397110176, 14035734551323447296, 4819539715644416128, 4827016561723629280, 4820879077951299296, 14047782665357449456, 14048229597543700528, 4823587264191490560, 4825923755597799504, 4826905897660217968, 4810744060330181760, 14047628793872262544, 4820301758343638528, 4810504686841833472, 4820169556005786688, 14045916074324387616, 14049014381670234416, 14043266343409649984, 4825544080529000128, 14049195231911444336, 4816305309518378752, 4825892666215854096, 4820228635692091424, 14039460297863506368, 14047457486192875952, 14027478790385997824, 4827375209142228272, 4827475596075372240, 14048942690042111136, 4816435754268609600, 14034411773510640768, 4825032276685385440, 4818359447447602752, 14050104396649896688, 4817671314828727616, 4816447939916698048, 4825021181004138400, 4816605047621449600, 14048486843705778416, 4826505842000732128, 4825500461705777360, 14042472703736636256, 4817734717229416768, 4809291162203853568, 14044404169266544352, 4815914602910284800, 14048858698130966224, 14036101460776935552, 4824869906749882560, 14038073056611875712, 4821055069919318240, 4823726146217129904, 4824644346638022096, 4821488729281420128, 4823232972595818240, 4815861306409708352, 4825923761784874416, 4822145926880519424, 14043912345987186368, 4825698727528483552, 4827496799336028672, 4827388878526922032, 14047342903851918848, 14043618080006794176, 14025656170871706624, 4818375882812654784, 4825192101448469120, 14048290697117854992, 4827152212331464288, 14036861650235655680, 4827234691243587584, 4824342384021011520, 14043981782818117216, 4826118500189347856, 14048471797006108048, 14048861362986108736, 14046759496182247024, 4819399305753481440, 14049043476823649440, 14046823839356329904, 4816176769121146496, 4825786095999036160, 4826241788276223088, 4818986940494195776, 14043162540286299168, 4822722492022500704, 14050880285328092464, 4823751698888846336, 14048300498998944208, 4817656981259625344, 4818536874967188160, 14045195514416569120, 14047992542429093088, 14048809850657987056, 14016791382348544000, 4824527203528682176, 4822702137615992672, 4819969141731513280, 14035896674846163712, 4821407164580298464, 4810656810818985600, 14045505777984169472, 14045739340100364480, 14047566683676771408, 4752053734082609152, 14049958816077011232, 4817174979660770176, 14035497289759830016, 4821984623625848256, 4820332707657795168, 14050264520749145664, 14047303025466811488, 4827524633316930864, 4824609681466904704, 14049962564799521728, 14048309409744718784, 4797189451316329472, 14049391175624572864, 14048037928382118368, 4808463840777550848, 4823655610175715008, 14046890486795299776, 4827139455543994224, 4824062291165692144, 14048138520258705344, 14050291427696716896, 14047562554493802480, 4822978777890482304, 14048103010413563072, 14042417322581688640, 14050700820548139456, 4825783824557932624, 4818927202554383616, 4808164301425248512, 14044462280281847008, 4820008554015526816, 14046704173389119424, 14046583594210522848, 14048108219532375232, 4824901683177351968, 14034600529698837888, 14050873228138384256, 4825970650938056160, 4819337656592692480, 14043378739545879616, 4825545752452926704, 4820199722098596896, 14044880618866974112, 4823426618700293552, 14048119187221489792, 4821469617978702304, 4823924085889139328, 4824898702371513600, 14042556653214304256, 14042895511619905376, 14049927365129203936, 14025903512464595968, 4825989434132668688, 14042638914587954880, 14047248376159271936, 4825163128923226416, 14041707578127073728, 14050836205556948736, 4811433388398753920, 14038868351932557568, 4823470498895325024, 14050244933080351696, 14049293595355266560, 4825546240672869056, 4826141924215864208, 14028289912637442560, 4827331827729561072, 14047298610156851440, 14050467202633790160, 4825326846767646944, 14044014249753023744, 4816080187705344832, 4818560413173935424, 4820850650591711072, 14048387854682275488, 14045320099582269504, 4825872951407024512, 14050240230394505152, 4802732933867449856, 4824654101838303104, 4814857720289123456, 4823915462642254512, 14042986165354480992, 14039261896837337344, 14039830524213336384, 14048461303041803536, 14018697476565278720, 4821699702366270336, 14037812504947253184, 4821262929071637440, 14049822765899686912, 4824796203103431600, 4806740995057848320, 14034053820166908544, 14048448581552980336, 14050299546710641584, 4826614252035880768, 14049770777747138592, 14049789067993336320, 4800811229952730112, 14048674540297025472, 4826156229654389232, 14032335315118612480, 4790364003619381248, 4826125868533998336, 14044038920330800352, 14047391396420267744, 4814452009523781312, 14043674053754524928, 14050735290451595744, 14034175436955393664, 4824023548064048592, 4814944850516883776, 14049646918486097728, 4810418144167598976, 4827320259443302928, 14042738094118667232, 14047726635959205248, 4827391603372602400, 4815213772740262848, 14032927041490024448, 14036010962913791744, 4811648836022465152, 14038660053253260032, 4823320696941159392, 14047788010599234592, 14040664049174184448, 4817346080097335744, 4822696317625127808, 14042955765420976544, 4822749736868095456, 4807440476460350464, 14047107902801890400, 14048531638141195952, 4817570981414272832, 4813629601315548672, 4824569750345782640, 4821633959043983648, 4825469606876584800, 14050675032572867344, 14038938372769741312, 4816684898491130496, 4824349953305523664, 14045873936439766848, 14048099006358527632, 4824774608527428368, 4826106306343912944, 4813515605280634624, 4810542851617532288, 4802979431790181888, 14047910718875129408, 4825885865135236144, 4822599683782904320, 4816442549103467456, 4827520882371575552, 4805409822583963904, 4822394640436706368, 14043112041065373472, 14043920380321423968, 14046222368244592512, 14041105383378377984, 4825589209030717584, 14041005813848277952, 4823525612521249568, 4822505980892172224, 14046698847473091584, 14046198652065521824, 14050216727789838400, 4808889700304526336, 4824187863070011680, 4820982992489883360, 14046443535205793472, 4818985967885981152, 4824590689752775728, 14049755323165779440, 4797117954635166720, 14047234474970918544, 14047967707960953376, 14040584620609446016, 4827134377446770864, 14043399782642098656, 14049086943138672832, 14036286968742574592, 4825428831539644032, 14050351703285447264, 4820618771246673504, 4821753888671166304, 14049749698514023344, 14047565878872144656, 4812281368355519616, 4821545735149027488, 4814360522434904384, 14047269841809463536, 4826818880800809248, 14048767300672146352, 4817089660786771200, 4824328699688647344, 4826330049959783088, 4825474219405237552, 14042529898353777664, 14045911615046701344, 14040779063915970176, 14048354308363775648, 4813222816533646080, 14044282134997088416, 14050090031980771952, 4827271456927878544, 14047543190389293424, 14050069041780897984, 4817205539946377088, 14047551075085999328, 4818154749411420160, 4811851224349411200, 4822867542037627328, 4816652535647179520, 14046447335895992800, 14037700084876808192, 14047251554064535888, 14046499755852653600, 14049968091456070032, 4819682568827203232, 4820916056718771456, 14042499295391146432, 14042159031019988800, 4819525742772475328, 14044307436851058304, 14037814893308110720, 4822300462032130464, 14050291413508816592, 14047474084194200128, 14030693945142926080, 4811865913107018368, 4822739796415177632, 14046029358772332768, 4815637940745949120, 4820582764103204672, 14039731535567729152, 14037544277190028160, 14033929324348290176, 4812694965287397632, 14049328209367101920, 4825594854553298736, 14043239976808655488, 14049153053754529120, 4815354172699059456, 4815817954694293696, 14042362261548803232, 14045206833773344384, 14034816333524678784, 4826910615981259616, 4825846050844994032, 14035476247042449280, 14047632965272013104, 4826897261774151552, 14046476870082609280, 14036143952589557504, 4815195417778694464, 14044026400811556160, 14045420358992383968, 4821718503690183808, 14031795509465220096, 4825309571374527808, 4827389448398884432, 14046775619633908512, 14046806371983507248, 14049447486936208960, 14049440506105992256, 14043677160848197312, 14050172918142501200, 14043762569795054208, 14049934524037237872, 4826867870261576128, 4827286835851558576, 4806143666869979392, 14048922574192087664, 4827214449426121120, 14039999205344759616, 4826073020979652880, 4816990759827235328, 14045615613507186720, 4823657355241872848, 14044788239382283072, 4820811915670830016, 4820117965313582432, 4824184546227654032, 4805372051231269376, 14034439078448139008, 4817539105828261184, 14044307641696930592, 14046271979856627072, 14047951184380695712, 14039693765695234624, 14047557315560712256, 4825969509629932272, 4827538221666079984, 4820219396764646912, 4820991796866674272, 4817541247142691776, 14044225817051180224, 14037439556916622336, 4824457733099428880, 4823679759637159488, 14038556262951558784, 4827438241020549152, 4819687211860892160, 14049451345734005504, 4826284605323864816, 4825152961927119152, 14049572812692583968, 4821040761572401280, 4819818093690164832, 4827117322194468704, 14050679583135120528, 4821648425909622176, 14038096139607875200, 4808674625776397568, 4819809164432985312, 4811409762472002304, 14038883530020770880, 4817368785957615296, 4825570609990811008, 4825392391898120176, 14042699532495128736, 14050583730812302896, 4826659672355578304, 14045773069910965824, 4811900109399415552, 4826384868179719456, 4826137677250241008, 4822598014691342016, 14047549635022054304, 14042803236689179680, 4820917015969801920, 14048220794093985760, 4825490342405589456, 14050779192957904288, 4825430427542135296, 14038700658918012800, 4826058423629640752, 14041540798002694336, 14043277527130728192, 4824628043828371376, 14040916580488203200, 14050077324647863024, 4826380063284196272, 14046589991038668896, 14050499877900179040, 4823973675530891920, 4825693329167187184, 4826072800579081200, 14045486880605870880, 14048373661487016304, 4826907023128104496, 14049480417396667328, 4817725360848926080, 4818540360628950016, 14049833783619408960, 4789738689436200960, 4818889026841473248, 14048699032871017392, 14035626354097818112, 14040993989110635584, 14030844108281171200, 14042981850819225984, 4824885858604141648, 14049506138838128768, 14042570485376980896, 4824097918057795136, 4821253448194608512, 14048100209479694960, 4821135898288099616, 14049081478406706000, 14044517733238218752, 14046668366931898176, 14047546260800595648, 4807588188995015424, 14050529442169741152, 4822567646897763424, 4824052387832233968, 14049532792484758016, 14043372367620093792, 4821782306490755520, 14042943356258703200, 4818038684068530112, 14040559390870544832, 4827512512636644896, 14049663201837070992, 4815967538710357120, 4809965276574625024, 14049151600144544144, 4827524526732729872, 4821288915894488640, 4796750543907596288, 14049685422934961872, 4825358836984044592, 4824311776782263760, 4799820440580381696, 14037988452810018048, 4826145508676277952, 14047095223977211984, 4826014728301725088, 14034626616776958464, 14038708410135778048, 4820586549683437760, 4825479486824845072, 4817855097183345024, 4815930523981551168, 14045655197291088448, 14050309170853145552, 14047650296299121984, 4820013468421902432, 14041297358760458176, 14042699574526062720, 4821833443125081472, 14050108093538474304, 14030375229338249728, 14044984721761994208, 4827070815129472384, 4826396407918438992, 4822760694962129568, 4814440197576533376, 14047943658896591632, 4815653495464315072, 14044463156639709824, 4820060408129761024, 4817765066312719744, 4826710444907733728, 14046511125764393888, 14050709392201865520, 14039897241069626688, 4821000919479208640, 14044219509765568928, 4805027040659365376, 14050438489462040096, 4813035256688970752, 4823851084331092320, 14012455677553266688, 4809923512089517696, 14049960963113202064, 14030802230154784256, 4813329603483211904, 14046152649105750688, 14042217226154760256, 4823687529311181472, 4825023163695672624, 4825023378770437456, 14049237787250617952, 4822947758432855232, 14049600103051778096, 4824926332635571760, 4819524260103066432, 4826044227063143152, 14033244570576339712, 14050687531630496224, 4823745694549864192, 4822761204795245600, 4826379907695171584, 4827489510798892432, 14048012016273213744, 14038694339874021568, 14036748857082834304, 14048833197502169824, 14048217926710073536, 14045689587086360992, 14037787259748863104, 14043097026653372256, 14044635381777187392, 14048225041862610320, 14048770609316029216, 4804977741722480128, 4825321224700966320, 4800220111277785088, 14043442521272979968, 4825909089225981312, 4824513766379962976, 4823870501696420864, 4816650998669627648, 14040121625067562688, 14044523904667088608, 4825807870433166736, 14047057535301194544, 4823814500642216688, 14043365899367635232, 4816406064445231040, 4826263352627281424, 14047013970916072896, 4821117458664213696, 14044507400270140992, 4825975153264440368, 4823120098842564960, 14034543949629549056, 4814689783561743808, 14050029546606905472, 14041276856331759232, 4820442159264978624, 14047799844189071312, 4826453477726942464, 14046134594232840576, 4814890551115058240, 14046248988448574656, 14050002085753334256, 4825866515410765904, 14044453177905086784, 4827170700347221392, 4820931836573598208, 14049605138965574912, 14043210774064383328, 4826597074495445568, 4814213929796513664, 14042121901078362816, 4824713729118017104, 4823029722794282496, 14047294620577788448, 4823328725385913920, 4821742935851688864, 14048079577359533088, 4827369676205252320, 14049902212472525296, 4811932235002354048, 4826518470198570576, 4822108316021943392, 4820381392089958016, 4823746493360387360, 4818867677990904288, 4820017553903449312, 4820957215413289856, 14040100557547119872, 4803408029714062336, 4822217410659601792, 14038073424807886848, 4818544598829997824, 4814019917385576960, 14049873819441567088, 4827472511627503136, 4804697258652760576, 4822363670461187168, 4826223681760378960, 4818371615432063936, 4825410909472836592, 14050566737821298640, 14044970817227698880, 4820390392873326176, 4821936539900920032, 4823385137912684496, 14045633760725393248, 14044658673874254144, 4825856308246054544, 4803558198063867904, 14049801508680345264, 4818015224341775040, 4825063065994072800, 14030205757538919424, 4808802554133322240, 14036060224228209408, 14050655370894546480, 14045256328143746656, 4813746999852420224, 4818347686664185344, 4822523515865525408, 4822181937430099488, 14048203193318009600, 4825641198872371072, 4818125169991300544, 4827126309964315952, 4822324608988395040, 4811154868835276544, 14049251929630659376, 4826790543908816144, 14048346496416447296, 14044997500025140160, 4820997880011417152, 4826694297030078496, 4826523585620066672, 4820987166198646752, 14028654173445591552, 14036949535500764672, 14047472727436919744, 4825028262747784176, 4826276512785204464, 14049002064478769584, 14045792827528888928, 4822907025802413248, 4819093965991109536, 14050719614483158096, 14049911185973797136, 14038255833428036608, 14045702740511516352, 14046343786939408992, 4824803736570329472, 4820749615190259776, 14033789142699563136, 4824664740731543664, 4810596563945365120, 4826985991060703360, 14047104887939171344, 4822593358103381024, 14041768820159614528, 14050179831944910656, 4822975744517806080, 4820809442889686464, 4821657249105344128, 14049494804715260224, 4823463545667200112, 4825091619570902608, 4816659595849054528, 14047642041402662432, 4822617244831186144, 14048265285144342480, 14043413586657170784, 14050544478340453824, 4818974290900593088, 14050291639403017264, 4823188246754458144, 14049225262847383856, 14050474355542890080, 4827506822629080832, 14040931360994469184, 14019942073152442368, 14047451438871506256, 4810603835864989568, 14022513656549353472, 14045788808727580128, 4824334810630821728, 14018682891098083328, 14039957450564285376, 4822879880281669888, 14036940283619224192, 14029354777665927424, 14048454513306374192, 4819982392044529632, 14042767370707103136, 4822736432620661120, 14048404593452857024, 14049283530646971232, 14045808374076604832, 14047223903156728752, 14047180825357952896, 14048624410072117776, 14049336048107771520, 4819554192596037632, 4827092978433806208, 4810118552391494400, 4826692659736847328, 14046089543596634400, 4823977352043713200, 4816203662778689152, 14049634833079222096, 4826101002856109760, 4825429156831265632, 4827421331538066352, 4823821455165611104, 14027597363570988032, 14050112678498391472, 14022873427945430016, 14050471526360541632, 14048180999441940128, 14047069482431905936, 14046182363014307040, 4794196803435882496, 4815391253384178624, 14050180295339060256, 4824887629352012992, 14045268277999328096, 14050307536562943232, 14047940319558644160, 14045751264001221984, 4815876874570541696, 4825445029765670768, 14050729575798393632, 4825801663153120096, 4817748590413628352, 14031355845451897088, 14048852067629400432, 4823036813032966944, 14049533748394722000, 14046772638929125392, 14048523132918560672, 14045372429393576032, 14049214494669939824, 14047082836134608240, 4811266020377325952, 4814774508194516736, 4809915077152572928, 4826665247702822224, 4820143764721380512, 14046670199595657632, 4802431421646786560, 4822641704561109600, 4824930993783765088, 4802144404521020928, 14034780170709607936, 4821751474473472320, 14049298800854277264, 14045421448637922528, 4814768763870693696, 4824367268709780944, 4823884230130873312, 4815452285659675136, 14047716253881801456, 14049013520174956112, 14050261248405261104, 4825076658505055008, 14043594259851181760, 14038932597036082944, 4824733526815516928, 14042570109117421728, 4822314610181687584, 4826943684329973168, 14042508323346198848, 14035695575419164160, 14044195475706875008, 4822256929819681344, 4824776955382945728, 4820736289951554400, 4824587143688499664, 4824979744300740624, 4819969571161827552, 4823147499402255712, 14043124829693532608, 4824715988204073472, 4809412333651321344, 4817618821739681984, 4822587804868824096, 4799921925377231872, 4822826724302940224, 4825123135569557824, 4827471205971946336, 14047378112159624736, 4826573071239109872, 14050398375395817808, 4826223012403801712, 14047554599342413712, 14046204387464520160, 4824614093765751280, 14048070963445095424, 4824920686352845728, 14048836956503377488, 14042033653767829568, 14045220400231792032, 4824629501893930400, 4819734906215831680, 4825443236016069616, 4826711979761802880, 4821146484393830368, 4826777864702804688, 14047221764860915792, 14042026417581312832, 4820285560699197280, 14047226999559571760, 4787602508735610880, 4823936981115367216, 4823591495175996864, 14033741879784349696, 14048361774471680016, 14050822882427221280, 14049567207357729616, 14050567733116709344, 14044298050788024672, 4821948804293039776, 14047944342994330464, 4824490210950416224, 4823697657900140080, 14043900304960523360, 4824226103093316784, 14033728005607968128, 14050398296653486032, 4815002566237056128, 4824972401781073568, 4823399058762957904, 4821647344827854912, 14043506142490625440, 14046900087792493920, 14026937414561577984, 4804363751547990016, 4822396623250197312, 4819919500543536864, 14047578144727888400, 14048505909572123088, 4824995475208691360, 14048399882332694944, 4819662007181144576, 14045817039662018272, 4825359733401114512, 4782900175721742336, 14048595915477955632, 14024671839365934592, 14033702678381508096, 14034082286008763264, 14032193188209399296, 14043823712926008928, 4815904838782364992, 4825474027556688528, 14048453841421097056, 14048711897358954128, 4817264954216958336, 14045790320795312224, 4825977759322491088, 4811108932895345408, 14050619395026507456, 14047546194496197552, 4821281558749465536, 4826323819509116848, 4825069327449529760, 14046472657775065536, 4826943144128455792, 14041016364621278720, 14047031318265985072, 4826657357752326336, 14050903483722911424, 4825862329558265952, 14041830234763096192, 4821002482792071968, 14045141090235591168, 14034120605084120064, 14041746674067750720, 14048961147925078576, 4824506967465471072, 4810218555031910656, 4817334227632935104, 4819673687848678080, 14047035987480697776, 4823707647925674800, 14050753368027079232, 14050751128734157568, 4826312425000941664, 14049998191138379392, 14044687554861509728, 14043736602194200768, 4827197903823811568, 4827127297527704256, 4823750329270282224, 4815125194873689728, 4827022189289690896, 14044938720144388608, 4824680263300379440, 14049456147030673328, 14049754162131054608, 14038077139704340544, 14048205603808229152, 14047403131663614976, 4813495894821509504, 4825978479301031840, 4826179911661365728, 4820574390857220928, 4823632496301265808, 14049957197783526208, 4825427331190650400, 4825592472852119008, 14035332547723591424, 14049499533359377424, 14049522382471897520, 4822573083094077632, 4822226755648871136, 4826074696507201584, 14045770062522718528, 4826439870924835984, 4821541377173092128, 14050827733559938432, 4823910365809511952, 4820611184836479744, 4823591249804754624, 14034788110938435328, 4810433476642056960, 14042792414334466048, 4827329776650402304, 14049733642563550352, 14029839347643400704, 14042240822891272960, 4815197401178689856, 14048934715739207104, 4826327471363181968, 14026532946730756608, 4824238593354989232, 4827534234690181840, 14050257916270278208, 14047735853276302704, 14039907775963307136, 14050428504992850192, 14049114833708133008, 14049449998125502720, 14040991952554807488, 14047483726311056992, 14046432757916023680, 14048033604615045600, 4818716246421539392, 4822517009167618912, 14034952150285154944, 14049943432368571504, 4815949131064252672, 14044675735970686656, 14047343592979287392, 14048640225518876960, 4826811033709229856, 4819288071959575168, 4822927236896679424, 4823099178847253280, 4821709943674780864, 4814678903250604032, 14050090007387814384, 14046919834140492352, 4811583017113625088, 4821441865138998848, 14029066363982651648, 14037031379643669120, 4823367907325536656, 14031935670364565504, 4826031729053701456, 14030592987771446528, 14042320154001939968, 14038163677117582720, 14049705917369389744, 14023166337212724224, 14034028223875524992, 14049229907346033120, 4825975422726138560, 14048824751234473376, 4820314256783915840, 14045984979326855008, 4827144204312868192, 4823964591121316160, 4817985657136715328, 4821500380213644384, 14044721794582030016, 4822476391350697856, 4815605548300137728, 4813304855034136576, 4820821160961760800, 4824830586517209392, 14050092328835294400, 4827270122667852176, 14038816622389051136, 14037722797843146240, 4817285703013165376, 14047855397411323008, 14048534949378627104, 4826322119666881056, 14047594419604411520, 4818245841206746816, 14033871995781988352, 4825203060820458544, 14044923631564411584, 14042722353808932832, 4825303756678937888, 14038209922191202048, 14046932769278311648, 4822034464997039936, 4807265624864805632, 14046125009671282048, 4823673755687687248, 14047553077547373424, 14050289850285319920, 4823402464296434864, 4813514856479012480, 4823973674097274880, 4826697050359314960, 14047931556667538432, 14026032745708298752, 4819254213422082464, 14050410949763823440, 14043253312615272224, 14050286302552970464, 14047471872370744864, 14043808468669004192, 4826165539587482624, 4820760110085622720, 14049458073641455488, 14035821210798496768, 14046894523026764736, 4825584863612294000, 4824635487878757200, 14047926159819913104, 4806077858399183360, 14042978102166706592, 14040743173511341632, 4815912675432628096, 14047950993586569936, 4819825749892560288, 4817106096189092736, 4815477945362809472, 4824027672990393888, 4823136474217280160, 4816765255167841984, 4826426447667747392, 4825697785836847312, 4826148514549848672, 14018139189444648960, 14048824640855377536, 4826087354719701344, 14045337436546218208, 4824827062987726160, 4824303789194450832, 14033930753729546752, 14041534810055173312, 14049572454444343680, 4826668033060512512, 4821593613436720352, 14047908856414982784, 14040754983644121280, 14043650093291714592, 14043971627959739776, 14048345285746207584, 4827470481687982512, 14034972829643104256, 4825876074492582080, 4824156051457566080, 14050241455177549856, 4824547522687808368, 4825690118020054944, 14042449363575596896, 4826536632009297040, 14047114662869147520, 4811474144798917888, 14048199364761032256, 14050312744345024432, 4819427969999402048, 4823580393309598400, 14033264272005404928, 4813017592658180864, 4818345531655184448, 4821813430172926976, 4815949157081662016, 4825646060944816640, 4821133920102791392, 4826755056978629552, 14048861007595561872, 4821906485362212000, 14049526204527277776, 14049705701990684352, 14039638815157811200, 14049572982917386896, 14047273650490327792, 4825277340358538432, 14047367318477927872, 4824706573041473664, 4822647582773721312, 14047804777454083792, 4827372578751824736, 4825079779431517888, 4827160403100192320, 4824103390694118000, 14034886834366445696, 4801829262160078848, 14039762585011989504, 4815294276729558528, 4826894437963996912, 14042229328219276672, 4811086186472434176, 14013526282223071232, 4809287210836285440, 14049778182087927344, 14044732544344534400, 14028937117232335872, 4822993231573216096, 14050613592851272992, 4827324457778488912, 4820037198918391968, 14041102401015397824, 4825401255649667040, 4820520102616682144, 14032065290285577728, 4819988161791230176, 4825074429088906928, 14028093281216314368, 4825902395936467728, 14050006555322218912, 14046737675514665616, 4808796036947104512, 4825200938220528048, 4823969928474717840, 4825039799455237616, 14045844224917100448, 14042067174906836416, 14050278727575344896, 4825751062043614256, 4823706312059070352, 4825012483574840672, 4822847443248041376, 4814659527826940608, 14050017934257601392, 14038450298828449344, 4827245570764288352, 14048862037354472064, 4826418814259171360, 4823913297148910704, 4816104279061863808, 14034017109329083008, 4813095091177205760, 14048219376269528000, 14044747138651652608, 14048904809164598816, 14047675737241597584, 14048389781924186112, 14049688445689735792, 14049561007035039232, 4816715160504330752, 14048289741721088912, 14045790956092582688, 14033758530111134592, 14045903142651934208, 4819054037742504864, 14038833284531211840, 14047432247490239920, 14037937180325997056, 4815468126803496704, 14049489987750221456, 14048736606123453888, 14048410273649090272, 4825205747388996048, 4818382142166444480, 4823442846389619040, 14046852454240607104, 14047381251339453920, 4825431114848987200, 4816210102156059648, 14048546464514646080, 4825211768181471536, 4826410336425282768, 14049529815677378320, 14046772419246927440, 4814906014225211136, 4812028328282472064, 14049355839577694272, 14045307973039600128, 14043015181550925888, 14043184442480630240, 14044695593169561856, 14047700506902293184, 14047524065584890544, 14047207783201930928, 4827368092493634704, 14025687234495816192, 4818213448122143552, 4824135894511944560, 4826188062098920912, 4824087500061719296, 4824860403265937504, 14049078248388160864, 4824263586222235344, 4814372308045610816, 14049401025871879872, 4826513770040956064, 4826926321838507952, 14049241687990881936, 14048206632566548080, 4825522080418198912, 14049305165946982208, 14047149351841519200, 14046203123113878112, 14040930842304126784, 14040007461961851456, 4814556857962670080, 4824221088434885712, 14047420720794598592, 4801917292426891776, 4823725261690029744, 4808429160253275136, 14044115518076677376, 4827060715213216224, 14045820660171675136, 4815990217718815936, 14044128444329909376, 14034025466636798976, 4826968336662012464, 4827457089673258512, 14037713619515486976, 4820687048034723072, 14047399391908959088, 4824843002582742304, 4824616997766990512, 4827364691500590352, 4822706623510900768, 14044036417534410976, 4820314385196276832, 14050578607574502768, 14047593507232460240, 14050719269215028288, 14033437509402462336, 14047717883930505520, 4823690402705489760, 14049101757737550064, 14046958557282545600, 4823659171409903760, 14024758379697304576, 4801132068328516608, 4825381563035240192, 14049621005844140672, 14049100130676469952, 14050435179636612784, 14040930408184823296, 14048996112254772064, 4824218254522013936, 14043401774999325440, 14030361860190806272, 4823406631495159632, 4827399112849435152, 14041692300575804544, 4814072169833773312, 14049266232522196736, 14049448467368422544, 14047717269449736960, 14048917952352454784, 14044794656751510272, 4802950731667485184, 4823743900915225216, 14048182339037749168, 4793842383082405888, 14034211709575233664, 14048781755939040992, 4823621822123394256, 14049552480197563600, 14047666760619420464, 4820223605471142848, 14048228442525089568, 4822676681465611040, 4812662680993679488, 4824752815960458800, 14026896154810910720, 4825259576539552560, 14048498286076379600, 4824151478002402304, 4801136464720155648, 4824889430092670352, 4826415277196794608, 4810928722964551168, 14042286429905445728, 14048392744814175920, 14050151719985668320, 4826992050373487248, 4816291980325788864, 14039545878587970304, 14043631370147431616, 4819092225593443456, 14040347530954600384, 14046783632004125376, 4823589933606790944, 14048688399459479232, 14046207497733367776, 4810803205586402944, 14026188340085927936, 14046618758614173408, 4815550900307929856, 4819787244044644288, 4810642813400592128, 4817446151690797440, 14041172904004259136, 14050034382488672032, 14048557700185702112, 4825328991444815120, 4820215203916191456, 4815610250177554176, 4815577598021148800, 4816242307723599936, 14048531150030771296, 4824749835675082912, 4825918944139598480, 4821906665940949056, 4821126800484833088, 14046407663870124512, 4814631182226612352, 14035308017630417024, 4806955943362115328, 4825949302261867808, 14042654450308971552, 4819002226610695616, 4816920352321078720, 4823104680385367104, 14046083325877690592, 14047264774843374576, 14045936558956279392, 14038987754355189056, 14046727273650193504, 14032393852681471232, 14044501927911542336, 4819112070292472288, 14046422359134930336, 4806436395944237824, 4826144895517751072, 4825996881753209344, 14046765211523567440, 14050769606019933456, 4815848057591745280, 4824413486326639360, 4810715011400012032, 4827283648904997392, 14045200247545704832, 4821272495297799488, 4818070754547789504, 14039722428426476864, 4825410079729698048, 14000285193140699136, 14040974942146253760, 14047730788081596896, 4826354336072926896, 4825532282265360128, 14044679958358097184, 4805876032793872896, 14047495126766447248, 14049248750835755424, 4819155539256106944, 14038840155410299968, 4824435005034634464, 4814569590254206336, 14047765783031600448, 4813871772627196544, 4821481839601562336, 4826641754344493760, 4824526777896244096, 4819061296163744160, 14039944886244769408, 14039915038434647680, 4827443872741467776, 14045585699229411584, 14032378653259896064, 4821189559285876096, 4826370528286312320, 4824677925515610768, 14045060943439282080, 14049901342413930496, 4813371528538449920, 14044684542653168992, 14049568489926521600, 14036656762722131200, 14037125842619706112, 14039738301263239744, 4823359585567389760, 14037389131326764416, 4824088163260013648, 4820998053844144800, 4827072556256991424, 4823551499735679872, 4825617025705500368, 4826398773626268944, 4827079271409614304, 14040163236363352704, 4825740876669531024, 4827053366299701920, 4823923043686703488, 4813641184365473536, 14041923015940546368, 4826755357356721856, 14048682357901566352, 14050182151085603520, 4820026226778570240, 4824120137725686144, 14047927810959947072, 4821612800595171904, 14049360691055243600, 4823430008624704112, 4808836303728278016, 14047738652259099360, 14050365317738478864, 4823709498600428000, 4826248400919049088, 4815770902191781376, 4821516438339962592, 4809300794441592320, 4817901470915381760, 14045531788116694656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4830638365936189448, pinv: 4383068506908503009, mod_data: ModData { n: 910395627798529, ninv: 4366620577834603101, norm: 14, }, primitive_root: 7, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 4823953248388537392, 4825083993720127840, 14049275608845979040, 4824558626898942528, 4803703128081250816, 14047217599387735920, 14045860596578195104, 4823704989170698784, 4812117899404575232, 14029321031068354304, 4817683911404602752, 14049274581278795600, 14041025923768159808, 14048591530656053200, 4823224929182377440, 14044807356283555680, 14048565011689080224, 14048449022444332320, 4824619472446582144, 4823545490913121568, 14048194762364833840, 14043725730480177248, 4820997252961902688, 14046969896560937456, 14047944254408845424, 4814509113908708992, 4820477893383007712, 4822886236437798624, 14030159836736439296, 4822273251020797280, 4824537938186787216, 4825647061013664432, 4823728502996949664, 4821165689330117568, 4818024201873709568, 14039361062917015616, 4821924234251739584, 4825479218392732880, 4821220156209760192, 14023539604117214208, 14046701094988933632, 14038513230084538304, 4825632302374308352, 4814590346725569280, 14046991709532908576, 4800002922553151488, 4816494586703843520, 14048611296086688256, 14048428041204873072, 4824178991170477632, 14048490301387049200, 14042705275438139840, 4821684822767825376, 4813424424977668736, 4803161907772867584, 14042394905524651136, 14040982099804935552, 4806735342721739008, 4820924352012881504, 14046277953908248512, 4818426322503451072, 4819296472033449440, 14048201536697058832, 14045292507001908416, 4823509433060748064, 14038811872899390208, 4823749491126068816, 14045633668192059904, 4814957669901982016, 4820728484829706720, 4810826174971240960, 14047010399146799952, 14047627826635961456, 4824503278026854640, 4810778845404246784, 14018769033322659840, 4823718911246657056, 14034213468509213312, 14048318162641566272, 14045922188606898912, 4808715529640919296, 14042831698965526592, 4825980062247441920, 4819934294852330240, 4824873661851166528, 4788410949623271424, 4822667211326123904, 4819447364204318624, 4810347438158859136, 4808913645787965952, 4821158218039483552, 4823547875455008192, 14043959405600712992, 4810762224885885312, 4796071786087073792, 4821113327210515232, 4823092688685074208, 4820596459587901088, 14045872098857687488, 4825734698328484176, 4819652954745367136, 14049375417232557296, 4822957853727417856, 4823376422399993536, 4818342611857321664, 4812217687694509824, 4824601140231727040, 14039279975802662144, 14040584312719823872, 4825871844980382656, 4823533362441899216, 4823460032919144944, 14048528666393331472, 14048620582578066320, 14047253482568712976, 4818386184811889536, 4804993988781171712, 14048718481021689536, 14049275508725685552, 14023555239694610432, 4812180889514960896, 4823456411053849280, 4825959825926376512, 4821664253171391936, 4825223272740620416, 4825599422265346592, 4825459023037646448, 4816433534926346304, 4805921150676023296, 4822650003309728768, 14044855148220296224, 14044851843919453024, 4822712319063919968, 14041858962814587584, 4824084971789193328, 4823683832102123808, 4826094734836133216, 4821042713112845536, 4810552068489937536, 14009150108824190976, 4821288213246124416, 4815774814643972736, 14047134923109627056, 4820656392250524320, 14047562180646757936, 14049422473494486512, 14049504298399032288, 14044624869283200608, 14047105636895727040, 4811057924139905920, 14046547085047285056, 4823529845578198544, 14042634533201991072, 14047920321929641248, 4816379969293490560, 14048766282100756928, 14046327830295601408, 4820461407562753952, 14043906922314265216, 4804374488389633536, 4821307016383498112, 4824810200504819488, 14048444257415607520, 4826026480753740864, 4824466787276303808, 4806523135315836672, 4822279514727872640, 4823036130075245600, 14043069692977278880, 14035967625060981760, 4822948649596260544, 14048596972578474224, 4821970848247535200, 4811842985463049216, 4824260309925335376, 4821990808009911168, 14049120049240933312, 4823408644246315584, 4819668409327055680, 14047298351547703296, 4820109343585729216, 4825223498588132640, 14043550967936567456, 4815364838631025600, 4797209284497325056, 4814174389837234944, 14040591645354942528, 14049072477378298592, 14042760207936687776, 14048872208147027248, 14048018172151038176, 4819409765338495616, 14038704454474944576, 14046134763060242144, 14048963994710033056, 4818948776086721088, 4820589624317163168, 4808445475087085824, 4823397744013543488, 14048792545867666096, 14046568923146552352, 4817033876557824256, 4824492821322020448, 14046849022540854560, 14034105467648868736, 14045261550903268192, 14043410693888634848, 14046826761071100480, 4816755163740240320, 14044755616210738528, 14049291586897935216, 4825858830293189168, 14048239312138930720, 4783651790069874688, 14047013225808426384, 14043506562133739360, 4822057256751904032, 4815320473529030976, 14047620675719663936, 14048354017908925520, 4825883180799872272, 4824372690969326928, 14046832549511142016, 4818630927824896640, 4824484475076486672, 4824078425153333680, 14043468921944181440, 14047066873492539072, 14039792182053281728, 14047073419824636976, 4822188982574306912, 14046270787629103904, 4825874270076618944, 14048815527454091600, 14048711876016877152, 14042389048580125600, 14045841002915635328, 4824537658458520208, 4824113124921987520, 14048823020259652448, 14046529088258217632, 14048401133198012784, 14049455056945456624, 4821795723484087776, 14047054645656454096, 4820149308939004000, 14025018424296692224, 4817996996499996288, 4813706085482655488, 14049308552360670624, 4820405028202317312, 14027587350854545408, 4818109941484212352, 14042405548863531840, 14041703772267821504, 14047224471701078480, 4824726043440232320, 4807526909313088256, 4821293380873255040, 14042405776601684352, 4823468121353609648, 4821456035857869664, 14048656217488111008, 4825102598476292384, 4810961974498593408, 4825467610202686352, 14043694176453104768, 4821820863778876768, 4825391895584308464, 14039154425849546240, 4808138383129685760, 4825188621388997888, 14047648612396323760, 4820363324486896416, 14034719057045182720, 4823645272290631904, 14049335325575376928, 4824599323870394016, 4811024792146314112, 14042724664691536896, 4826025145299946688, 14033715910156323072, 4819443651062763104, 4815984832222008704, 4824229659689360768, 14045463557354927584, 4825376651425853440, 4819438192701056032, 4817116815552996224, 4821308831284607136, 4822633234101551648, 4812743346687088384, 14048240421667925056, 14037641820484748672, 4816137993421516096, 4803501548758763008, 4825525825748241248, 4815122249009667456, 4824477335476147408, 14017203941536200704, 4824038273196424432, 14029281820040242432, 14044126003483769056, 14047878397914920240, 14048034874375319648, 4814986718331060224, 4819306150039353632, 14038154729728284864, 4823482525960242736, 14045901837959338336, 14038541098886310720, 14047338117915928560, 4823566307707468816, 14047039770878715472, 14044569679087154592, 4825365567720527840, 4825584344455624160, 14049442328935842192, 4823250404931640224, 4824148534724784672, 4817980249632793088, 14044216122860790752, 14046830544426702064, 4826128759605670704, 4812014905373941504, 14048105824940779504, 14045417170434438464, 14048863639040829728, 14037530276010274816, 4817922093356476736, 14035279143420302208, 14044186296602954912, 4822342874949691424, 14038416957021400256, 4817414357615335552, 4822844826938921792, 4824258832129913648, 14045521092932721248, 4804206449353889280, 14047796647945882240, 4816747602877404096, 4823903987944072864, 14032799037965747200, 4814330751977444736, 14045968555905400000, 14048157126397274960, 14041407820743605440, 4825174991528644720, 4810352550957093888, 4825830854087414848, 4823018937621715232, 14043179403893050752, 4826087643510056208, 14040404768956755712, 14045769913846005664, 4823836853493768688, 14047675630400060096, 4825591976428686000, 4820160704103389696, 4825977261315662448, 4820011116443432064, 4814151471421857024, 4803280076769162752, 4819521148737191040, 14049022167673547760, 4819679658566226784, 14047068513268930560, 14047072616017833792, 4819378615714481536, 14046650759539548800, 14035364453431222144, 14030053348789753600, 4825700719359063984, 14044526584110923520, 14043957901269283968, 14049313297550170672, 14048939875429568128, 4791216540694831104, 4822961721116407296, 4822406362512763776, 14049082284145589168, 4820217992215437024, 14044480275792773312, 14040788003404518976, 4822380564178811776, 4817034878203484032, 14049313872328390080, 4818960524102592256, 14043628023005129440, 4825269036803627168, 4823157895937672704, 14043288357667439712, 14028276451788894208, 4805512658545223936, 14048735525210923056, 14043744743516957344, 14041544352493287744, 14049364012766889232, 14033296220318315392, 4816901082524599680, 4818264975119238976, 14039628942079135872, 14048314832662593152, 14041835736408685312, 14047337492884856176, 4820478272354778400, 14048000513096537760, 4825065748009982944, 4822048610394722784, 14046871100847718624, 4815811072385848960, 4824331831052059744, 14047943547581407712, 4809151315902813696, 14046241942888731296, 4822146993129050560, 4822096017086327648, 14044327745697293696, 4820350550652206752, 14024521197801320448, 4823889543663640720, 4824008856115605200, 14046140174888396960, 14048623052416985888, 4819399009524512864, 4815024815889547648, 14044839606423821280, 14047892606675986032, 14043455633135033376, 14046124297122335808, 4824950207011665936, 14039856917326082432, 4822119435580499744, 4822573960278262528, 14044640620977698048, 4821439571202711264, 4786678533351006208, 14042177753641602624, 4821095366244187552, 14031215686492833024, 4809909582778345728, 14036087898714888448, 4824114371515345824, 14044583842528841632, 14049017165550411344, 14024424309353656832, 4821193836839761696, 4824893979607517136, 4825288280109719856, 4824156359951471232, 4824492980103616192, 14049368081538950592, 4817993961340249152, 14048383596497315648, 14043114754878088992, 14047293100659476704, 4797946862342383616, 4825307821932793168, 14031166591573483264, 4815090634218279872, 4813615659856295552, 4808247220082154240, 4817654756707757248, 4825189900209521056, 4819285444664320160, 14040983986961982912, 4821194793193993504, 14047192053775109824, 4815201361173582208, 14049245296529701728, 4810994209390792448, 4826020194031829184, 4810173151544425344, 4820522164401433056, 4806065339722821632, 4812429038963743104, 14037730777429739456, 4823382627940347184, 4804763631472912896, 4824062613331113536, 4820103988356859904, 4822151469707373952, 4825752120103231280, 14048126007571492656, 14044141848136231360, 14045426663779173856, 4821386596066810848, 14043580103710371776, 14049286625576349328, 4817518229588646912, 4823425813215830224, 4813031980038996736, 4809649605305686272, 14036888054973053184, 4819701922567040768, 14037214991419952384, 4823547303553466080, 14046123571309766784, 4800343520334873600, 14038709976900367296, 14037866488732471168, 4818966594847896832, 4817460729130668288, 14049056114215253184, 14043730197059700416, 4824570229506735008, 4821237415053814432, 4817144072762029184, 4824591333785347776, 14042584898417558656, 4788947292574593024, 14047790630409759696, 14047550726237428608, 4822238171356125760, 4809612428219089408, 14016609240414943232, 4824295347346960064, 4824055408006797232, 14039796386350428672, 14047063945169299104, 14043984014069088512, 14036685261505493760, 14040895782250957824, 4823918355798592832, 14049312825137551808, 14045273802766847360, 14047407748782060224, 14048183745300366800, 14045642687482105024, 14048753373521557040, 14037835168048565696, 14046458220779203936, 14039677876305374080, 4821227751631967840, 14040713637218013440, 14043786070643033504, 14044335093639923392, 14048306763172282432, 4820744701446598272, 4798425194468366336, 14034842320022247424, 4819694546609863136, 4824575687450819808, 4823878248212043856, 4823978141389907552, 4825570065782731376, 14037716658545033088, 4820305726901694816, 14045699945363178848, 4825013278618348480, 4789062431559569408, 4814784471433347072, 14048111086211267168, 14020619167057711104, 14047369775899941392, 4815600764618304064, 14049103172804421984, 4825873890332338944, 4823593289310521344, 4819666153957478848, 4823237514960742272, 14027744525602444288, 4825584569701882864, 14043665139329496672, 4823405538168842576, 14049395684821107136, 4825668465713925808, 4820658444380342144, 4819820867580648160, 14047295166845210656, 14044625836677581792, 4824306993923413824, 14043277352294806208, 14017104583530530816, 14041408743768704192, 4825337046133245888, 14043459424015837152, 4818791005747982464, 14043484365494872832, 4814492915334685440, 14048850156880681760, 4823474313372550144, 14049478105414574064, 4801752853527157760, 4824412154244619280, 14048347277736416752, 4824984710439790800, 4822677850292147872, 14048583931900137376, 14044797665892990368, 14048733968986519872, 4824128807849208928, 4821678795456354368, 4823730962631421824, 4806759091449108992, 4807846115789023488, 4824499778241538656, 14044061864598245056, 4817520835622736128, 4823593575572307792, 14034016916414466048, 14036382201833365632, 14043567033351683104, 14028777689424467456, 14041130407231636032, 14039161108259370240, 14042753570276657472, 14043515335673833920, 14042764250335561280, 14045674049059466816, 4822083705534830048, 14039932944491941952, 14046812451228188128, 4825508675374609936, 4821856665246076992, 4822451886731514432, 4824505200319042496, 14033938158495151488, 14043282851803953728, 4823469851512349408, 4823627755471563616, 14047731341168771776, 14048654130466885248, 4820895642519157024, 14036320232891451776, 14043483891116644544, 4821966039262706944, 14047759090244674656, 14048283538237087696, 4817325311904711616, 14047681406781325600, 4806821252655495936, 14036988929254572160, 4824053983005699200, 4823837402328387824, 14041921342841544832, 14044139196087001824, 14036606647725917184, 4824282786237130096, 4816645144209495808, 4825799925434165232, 14047788571233848544, 14045484886748963328, 14028524439307377664, 4824434132537116000, 4813386901685951616, 14042350400140175136, 4825772706005453408, 14047582611626698912, 4820203911544131744, 14047681484591723424, 14048140874029456864, 4819792003275038528, 14044795721922856768, 4817800535066705536, 14049464148580589792, 4824402420292726608, 14044791699938753216, 14041037612342588032, 14041863687808391040, 4824217249110654640, 4826001519285196192, 14038296375136873920, 14045504147248822432, 4823910714973418928, 14044658950155976672, 14034624867941200000, 4821395930520335712, 14041084919486166720, 4824713508867757472, 14044145840700107008, 14035463543032299776, 14045772754813139008, 4823934497472800752, 4821887790389361952, 14045693729910927712, 4821011501311774016, 14046651368575184064, 4819273244675296448, 4818937185678030816, 4815006552904790976, 14046837901756820160, 4824894121203218144, 14029417748654791680, 14043852708649155808, 4817388874652616576, 14042420722934610848, 14047316871774709344, 4821441426874899424, 4814488714718053888, 4823970978275452688, 14048532072002852144, 4822797158083407488, 4818672100457414144, 14048890263534194800, 4823706211534315872, 14049222297326893392, 4820502980005779552, 14047822342166140208, 4803375436592053248, 14034388047058697728, 14044718981433919904, 4820567863148559520, 14048359635938309648, 14048692051816816624, 4812575163169714816, 14045787787949337408, 14043431647812779968, 14039365734592012608, 4806765885879651584, 4826078626326100832, 4824947731783341072, 14048991121840381152, 14047181734527671760, 14039127034250110208, 14048579771075486288, 4812404479463878400, 14046834645793195248, 14035985937727458944, 14049325749853941536, 4821548085463008640, 4823666538394645136, 4809514371974909952, 4825757322419148240, 4822869662775097440, 4825511594891152192, 4819754070485701696, 14049159941061074000, 4819970646820991264, 4824277650513278864, 14047516265122351424, 4822572389353899040, 4825350190125892544, 14046614883698788768, 4823654199878109296, 14035138305084036992, 4811990183293041920, 4826035914029913616, 4825698265038752576, 4823279320258954080, 14045043386872232096, 14032313217007383040, 14044716117862326208, 14039912072061881984, 4818702736289266560, 4819280411070815040, 14042535436479928640, 14041359070074589056, 4821741215284991072, 4821200099087147584, 14043952106648267616, 4820642937196403328, 14043577356478246272, 14035334688054819072, 4820435266939396192, 14048260440663814736, 4811261387761558784, 4815488970708472512, 14027137219464487424, 4823440788349503728, 14043882337908217376, 14046627618549570944, 14047650697836113344, 14048874955758520800, 4820531222934491968, 14045207416096249088, 4824768247361016048, 14039494650865925568, 14046955488514550048, 14029753947182124288, 4823491728644163072, 4819132326111815104, 14046113486044344256, 4823212333688003616, 14047867124922568240, 4823390081715787728, 4811210057896234880, 4825672659316091600, 4800837885380390912, 14044424782998466272, 14046230913752192224, 14048539060472864464, 4814841269326680192, 4818569149948283776, 14017499162106810368, 4819798846932783104, 14048256146398728496, 14049246514430649648, 14042747735810799904, 14043899415607785440, 14042838619177541600, 4824699167035684176, 14043366427858079232, 4821987329132626720, 14024981376105126912, 4823819010093279792, 4819508395545464640, 14039112515896504192, 4824960560275669040, 14044730414669784672, 14045641623050641312, 4807890101022833152, 4820481868470320928, 14040582983228397696, 14045551746283425984, 4824638423022658640, 14047656300588076992, 4825969301827138976, 14045312358402798592, 4823577108282775520, 14033616809426549632, 4817491117598835008, 14047711946463647920, 14017138652370186240, 4814293604152200576, 4824102080247326992, 4825433674921535344, 4798417727273772032, 4814324715392750592, 4812067189281820672, 14048395574014847296, 14048049620421384416, 14043816034495334592, 4825168853606119680, 14048077812649100640, 14031278426934983168, 4822664076090005728, 14046283724158469280, 14046397305112937344, 14044078079401517856, 14046696762035599520, 14044740860603369152, 14047660498738846960, 4823406115891044256, 4819069147344075712, 4820791313144706144, 14049342494831757536, 14042125833078413184, 14046610092037569408, 14043206480554774176, 14047225107883394880, 4808267773743216128, 4825259889410030112, 14048511323990994576, 4821439076136109792, 14046728194360194384, 4819779687808646368, 4821793955451956480, 14039616051002245568, 4825279428809623056, 4812321188306878848, 14044417556593216832, 4802055490669989376, 4825569268326390960, 4813353961982797312, 4821421246022231872, 4812712769663062400, 14047912393825697392, 14029879764366103552, 14044602560736059968, 4819389678868075936, 4819469864864033568, 14049030020002894256, 4825809929265716736, 4823466089207036480, 14048058366392993776, 4816327221950730304, 14044401464447192320, 14046192040418349760, 4825800845017736224, 14043247397321882368, 14047435935261124928, 14026278802031792640, 4818595201097564160, 14039768967160682752, 4814951722629826880, 4820950228631234336, 4825755955743165232, 14037600389560718336, 4816047617698501248, 4824951705205037088, 4825155018005046032, 4814848860227197376, 14048026684245231328, 14049313033631808624, 14043219760842215904, 14047803494729399424, 4823453214814382048, 14046514954384740960, 14047860897014330336, 14047450644731600016, 4822455909461261632, 14036485032092318080, 14046976674331557728, 4819986508671765664, 4818002125417966592, 14032538563042080256, 4825048953203652272, 14029580896322983168, 14049174892412748320, 14044230671416116128, 4823658494405287456, 14041956290103877760, 14043370539869093920, 14045932750545528928, 4820745277503115488, 14042652751282579680, 4819006166548595104, 14048886013270025760, 14044450198352722880, 14045987899762385312, 4821132896166465888, 4820989999654882208, 14043817331432645312, 14043702900469742848, 4823893719766536400, 4819150065671148896, 14048997539790314816, 4824223298867460272, 4811488256658291200, 14040895757855661824, 4814940521819383232, 14045037166395535072, 4820979872845301536, 14042017155350596672, 14047799170698495552, 14048843603260619280, 14046989267163272384, 14045058189431876160, 14031860262367677184, 14044474133754137664, 4812035333352927872, 14049037963410711680, 4825433836344307216, 14043926239572147232, 4825513164329647872, 14047311588323725424, 4820470992176524128, 14020386550114670592, 14046318549084136768, 4820182586433668128, 4822980553650086624, 14036203821106896128, 4823614865262100592, 14044926533851591360, 14046851331722533280, 14043055454296643456, 14049412885736566592, 14037962133299571648, 14046726545222149696, 14047233090964272336, 4820243825114128352, 14048122226215720944, 14047785455716015824, 14034545164818383744, 4823995569577665360, 4823327236798981824, 14038367756990910528, 4816831357013840000, 14048180586227254880, 14038685789818344064, 14044039710535779744, 14047089040127758112, 14037731580207534592, 4826072655394979712, 14048772946211184912, 4825081764317694704, 4821037360437271392, 14048712226592224128, 14032276393761443840, 14046590115601460224, 4812202559676208768, 14048707391287436672, 14035196666207079808, 14005118577718411264, 14042244056269009216, 14035607602456641920, 4814352533958761216, 4816543099905685824, 14048874608064266832, 4820994560502018848, 4810358340105771520, 14046610122499428928, 14046528530208643648, 4825461544937897216, 4823898034442875648, 4814367885492178816, 4822197692549141792, 14047305180238238080, 4816145561671869760, 4824669847616201728, 14048054343846250944, 4815756824126371328, 14041544450269063744, 4824677648755486144, 14046840423158103856, 4817043518068634944, 14040250979245767104, 14043758755912371840, 4821268600956909888, 14046008919841912128, 4825392626389228560, 14042580446738220384, 14039922328993447168, 4825630664115612160, 14041155724508215040, 4792643680791646208, 4821483983637609632, 4826027883545339136, 4823380272997187520, 14045598350099886304, 4822211037250860736, 14048586166521851536, 14047316714340847648, 14046108997129038496, 4825973181750430080, 4822731795905911744, 4820243279775614144, 14049477753663947104, 14041400369918972672, 4826016429988591504, 14048784505175397872, 14043559231572284608, 4825801116114137184, 4813792139219027328, 4817120541254506240, 14048605693470775040, 4814514237594887168, 14045871682631817472, 14038037860458179520, 14049144366911703168, 14047078364978124240, 4821578850101173632, 14042503800921864736, 14047585718518784768, 4823898561283142976, 4820195917385416192, 14048131952484830384, 14048815666915868544, 14033069274113456640, 4791109880713076736, 4816923386739969344, 14047158716388820192, 4824938869558284784, 4825773172994281440, 14040892554145098240, 4816392176988898816, 14047481057265452016, 4824995365003637168, 4817178940449582400, 14041333023725420416, 4825902518291647696, 4824224703019913424, 4818359081892465472, 14042019507024938432, 4820115281765526208, 4825422854567360944, 14048311046053536112, 14040554322491422592, 14047201761315155200, 4823938414170343088, 4824131217405710928, 4818602537712200256, 14036507693119973760, 14040174584276268800, 4824511641089796192, 4816768193009903872, 14049417503782867632, 14045802698487560544, 14036415098945234944, 4825806809042773792, 4821803859698855840, 4821706560609429248, 14043950492062286496, 4806348157045050624, 4824205771810647584, 14046840541695864656, 4820093121819765504, 14042221118025045952, 14039033129001135552, 14024834083471730688, 14046053268531866496, 4825747432888281536, 14034735252829027200, 4819407444096563008, 4825776961600077552, 4825622611514804208, 14048922431405344784, 4823575863063018272, 4826097939875141968, 4824104640104825488, 4825229295947606032, 14048614793357476960, 14047185989290037600, 14047918960664482256, 14048931590782925104, 4823581891259939136, 4815904832697979904, 14047783094569982160, 14041133873969093376, 14042764293975414464, 4824529762334589328, 14028889369648239104, 4823571553164030624, 4824108213141242928, 4822701387282037248, 4819210585340427584, 4825073816309822080, 4801181965573444096, 4825273702021404576, 4822362538534677056, 4824673292872169056, 14042715161676276000, 14035556319780078336, 14047075390563732576, 14038193007681453504, 14049035568577790400, 4825957900710263088, 4825075603521313088, 4824920044992839104, 14047283042243859408, 4819866246981433920, 4819520142077709568, 4796219354047746048, 14025696480474423296, 4808070510798359040, 14048724072351326272, 4813791367816548096, 4824136296419628240, 14047290770581145216, 4811613783782124032, 4824716458215033264, 14049193684361639824, 4824887242313707520, 4823553167882904192, 14046758600947613232, 14049472643415484816, 14048428575969953568, 14048287845359904560, 4817278761485318976, 14036002867647282816, 4821209578793184064, 14045674501377842336, 4824243647453932736, 4824282339143702992, 14047145559857134048, 14025476409726808064, 4818896932169975968, 14040906064674985088, 14048168451095962224, 14049089748406725632, 14048704023497263152, 14048150783587470480, 4822512835324467456, 4823994949317633232, 4815664991151044096, 14037835844266088448, 4818544623252718400, 4823559265504350080, 14049014372719636112, 14048726995513878304, 14038446133556496448, 4820453953457846240, 14048728709258864160, 14049391623685815664, 4815919554030401280, 14049436839238695632, 4807654763886386432, 14042340011054494816, 14046143334093746304, 14046395121339726240, 14042709817675441376, 4823218290686018944, 14039524482455525696, 4821643517508801664, 4821344155552875264, 4815057852126473728, 4819050196005058560, 4824769265987336688, 4780195458809905152, 14049400165700265760, 14048264862205766816, 14044717835737217056, 4819363063391618176, 14045211094051997056, 4824535084576824096, 14047351529205034496, 14047316924839105392, 4823457650360081952, 14047799523690450976, 4790675648332267520, 14042685120438631584, 4820628442932832064, 14045168614168261856, 4815881384862278528, 4820941785371617856, 14044037031280312448, 4819951329614367808, 4815601513799558720, 14047524630295599328, 4806848435573614592, 4805082018605693952, 4812165917170155392, 4825634985135820528, 14035377770703175296, 14043620814667969440, 14037289847389732096, 4810173282423828224, 14045091722065906720, 14047736985873469712, 14047159734014983584, 4796843728240861184, 4822842023823075776, 14047645847783393184, 4825262280288905472, 14046926577037285296, 4825708274313418464, 4816375971527638784, 4816079575756826880, 4802315244269506048, 14031407977182087936, 14042859032938692736, 4824651513548786752, 14042403972358535264, 4815513811610422976, 4824031751120927280, 4820368773111658848, 14047327578405552832, 14048139784817839216, 14048903780190245120, 4824679601556008672, 4821525365964237152, 14047980094937954912, 14046914586551752992, 4815522155359847232, 14048766649811889360, 4825339377984455584, 14040849116159867968, 4825380102605593408, 14028936561556855040, 4824066714949823904, 4823685275335365888, 14048546344076282768, 14024249881007655424, 4825441330886989392, 14042336718477837824, 14047588027390388672, 4810559102577410688, 14049469961464651488, 14044375115535440608, 14036526016648102272, 14037172609928812032, 14034784115223076992, 14005883356502654976, 4821930011170387744, 14038596110466247872, 4819832764693149440, 14047940677392518848, 14039209994486083328, 14044608821966055552, 14041527405263008192, 4813347701156180992, 14048738693952185392, 14047704419943755504, 4825499083079993728, 4823793258039762560, 4825974426075657632, 4823776888165760800, 4825076614479252816, 4824828268633283520, 4821520245219284736, 14045103040895871136, 14040105978725592000, 14044455540809411744, 4821255116484757664, 4820572155642001216, 4815906244300186688, 4818301484052122240, 4822025372794514880, 4813226163572852096, 14016126667663247360, 4825212005243271760, 4810940255103567104, 4818038529194043456, 4808159400565080064, 4816282564000707648, 14048007772477561696, 14047427371050800176, 14042306618792801920, 14042378149257190816, 14049187310313806896, 4824073156392015184, 14043790606248614336, 4821858753777262112, 4818547565089876736, 4816342130135081216, 4823422266196108064, 4824393098916643296, 4811688966856403200, 4822637684602825120, 14047071538622103088, 4820556898691694528, 14039391832509022528, 14046932837057954704, 4804323275571257344, 14042807049188526464, 14040076212099371776, 4825319052928248240, 14040719425333898688, 4825973161023122752, 4823424284211613408, 4823861060942531392, 14046003355238590336, 14034118309842195968, 14049463893476095680, 4819414672164774080, 14038950728213323008, 4820624590894352000, 4818856612532597792, 14049292297362220960, 4824908737594090512, 14043641611839267584, 4819515721171865056, 14047505470388100256, 14040229780935253120, 14036385049973158144, 4824262771965927536, 14043730052512700000, 4815552318541366976, 14031915238178992640, 4825679069718080144, 4825650127575950160, 4822473210592656384, 4822716798786426080, 4824280892040739440, 14029031520201799424, 14047128722833269424, 4824517242373028416, 4824240066839333824, 14045531873696035200, 14019910079452430336, 4820686741244024416, 4819218099392045760, 4821061996366075936, 14048558065279703392, 4824498885699672624, 4820014654224262720, 14047031567580460944, 4823585548683642160, 14047419844159976048, 4820645762754922496, 4821767849614181600, 14044019317817631808, 4824041970730964000, 14040372688366445760, 4819023751049888320, 4796783719874294784, 4822394878317892960, 4811255662829104512, 14046255989154242720, 14018691780982368256, 4823906857116502048, 4824947099868674528, 4815077993369358016, 4824676904222281872, 14049461670953825216, 4824380393482377648, 4823092832404079008, 14047221037352793040, 4818142618789344256, 14046053765980814688, 14034378720987832832, 4822641344974928224, 14042740407405435584, 4824850015132325744, 14049316634820538352, 4821006028404887104, 14034226857388254080, 4813097240535685760, 4803528448741088768, 4825657536779356592, 4825731288649859584, 4819872991112554176, 14047634600807230592, 14045306340314436640, 4820772029082735648, 4821920239224421952, 4825546438441354480, 14033205191326861824, 14047579848110928720, 4825370371105331456, 14045662227878121824, 14044051806111074016, 14048306009450001888, 14048758655792713072, 14044473951699608032, 4821898022998453248, 14048433348254323072, 14047746151592458560, 4814876098472972416, 14043734318701961696, 14049302738815623616, 14047187847308799728, 4819219583649028128, 4823110807455759456, 4823467586745394640, 14048951010778301920, 4817278396609124352, 4824566251280759040, 4825218202205848576, 14042859581684650528, 4825062579313568304, 14038947275537904192, 4823914837506054240, 4819161919869362720, 14045357549603490592, 14049026223845267120, 14049438853404335424, 14049308253820962752, 14030159217023705600, 4818203778939214784, 4816425904442885824, 4821854826531764224, 14040845777828796160, 14037951351055134656, 4814804962303242880, 14048536593531299552, 4824570330373403440, 14047908527096471200, 14048076993120677216, 14042792447079171424, 14047358164534244768, 4825576172781743216, 14042995724935741344, 14047477028768425984, 14039756904882394304, 4825390044167561040, 4820667773681926400, 14039717477028927744, 4824648373540873376, 4825967444870362144, 14044939894450495264, 4825456092001724288, 14043106475575138464, 4826031093638521888, 4817979695198177280, 4822841723383758752, 4824838658898018240, 14046841277763714752, 4814239301420616192, 4825570989749270432, 14045386014346263936, 14038056849774306560, 4824703473195605056, 4825584703537205872, 14043218471419296224, 4824709831590088752, 4803862519866614784, 14032551272601084416, 14044182426497724608, 4818620508808124928, 4823207887549416736, 4823681047231857616, 14040481433244148160, 14034244083461213824, 14044970558620028160, 14049033070035396880, 4814587343372635712, 4824734172206688480, 4823780917462373504, 14045764904282614272, 4824371193007716096, 14049365917718006688, 14047075079977112240, 14042705639472853120, 14040412562659582976, 14045091432669031360, 4821333853854633440, 4825375510360198752, 4819082499160857984, 14045714299176656448, 14049081224274257904, 14041956490390223424, 4822321001281496000, 4825742476353279552, 14049065088377326016, 14029315677724130048, 4819190960769378912, 14042907443872146912, 4803425732686631424, 4826072834069822480, 4815540272732431424, 14043361673160659520, 14049248718876758320, 4825998874078804112, 14048729476439267664, 4825809443478487840, 14048120198493568880, 14044738514824770176, 14048873644732655072, 14047590477313707776, 14049054856840135872, 14043451856793396928, 14022405299356661760, 4820490648150391552, 14043256753375672992, 4824391533925071056, 4823097374685449568, 14024508975674640384, 14045630244377295712, 14028806457685102080, 14042650859930931136, 14047111125117091056, 14041185644203448256, 14048985448923763248, 14043619921060370112, 14047326906115662960, 14048657177649624720, 14048497124548970080, 14044676923680603392, 4813171192760564992, 14043307650283889792, 4823889382630955920, 4806692602052838656, 14048244790539753104, 14046021874097741728, 14048023067084921824, 14042490741265074400, 14035990249621202816, 4825824781419750176, 14044554385485625568, 14048851215330664864, 14046943539867223456, 14029078460959363072, 14036004473463703936, 14045606893672060544, 14046409678468354592, 14048033822599107408, 14047971611914430640, 14046792584439944752, 14041868153127954816, 4822659215769591680, 4825755282921193840, 4816671974918267840, 4821115976688527040, 14042702122733295136, 4815091505599602624, 4815605164961396672, 4810005875329161600, 4817205759075486016, 4807657564097075200, 4825294836739854080, 14047430437156370704, 4814383337109266176, 4823752340651761920, 14037976023854481408, 4822235389010100576, 14043050587987948128, 13996682174067703808, 4818033039420465152, 4825250219623421824, 14048929583122700144, 14045052191284055264, 14035435174872359040, 4824954400487123472, 4810887326570066816, 4772013213576265728, 14046892975615256272, 14044222308976202048, 14049044829453335312, 4807648011826990080, 4823158702993336672, 4824597888008003344, 4824896899180464128, 4825714446188229744, 14045545769439664576, 4825887631338930096, 14047101974651363728, 4818352816021585536, 14042647971660574560, 4824116624676444480, 14036322822408096768, 4819005108630444896, 4821308921147918656, 4820699808843720512, 14046867958948479968, 4815665711649760384, 4820738583016020288, 4797057068646591488, 4818522619710394688, 14043463664252902656, 14040782616925617344, 14027069236061724160, 14043013569888157792, 4811236931491163648, 14037732504159876160, 14044454238352781792, 4808240641602471680, 4814261254421637888, 4824615592094282048, 4825625882797936304, 4826107716041171104, 14049169937769497776, 14041733767654775424, 14049386921283965904, 4817701954404875776, 14033831974902502144, 4815017250778785472, 4819958851594276800, 14046935395852688176, 14027703185633212416, 4821367711502553920, 14048168060275756112, 4824981591216558624, 14037181756105496192, 14041071860705387136, 4806131581256441344, 4824164830901797392, 14031008769674067200, 14042638303367250144, 14048995480723402768, 4825481810707194928, 4820843121741740800, 4824607341824331152, 4819656791844545344, 4810538957876212736, 14045126081814421920, 4824022596455340576, 14043776037038854656, 4825432054744660400, 14048198840929610432, 14048295951799414848, 14011745542449807360, 14043397204078868768, 14045984386075468544, 4821102207098806752, 14030805302206060288, 4809929375606476672, 4822819582539387360, 4818743293603630464, 14042480325243741504, 4822577150516546720, 14048792005909866800, 4812226271062418304, 14048267016365053680, 14045053738879417888, 14043403185992236736, 14038848117672041920, 14042495632758302944, 4825203403940055104, 4823155601414092352, 14042292929242555936, 14043295705729395520, 4824390256797995088, 4824788576253410176, 14039117549342101440, 14046929448794273792, 14045938525766895168, 14047180560100179024, 4825636041992423952, 14043010637192762368, 14047184546528746640, 14036249651858988800, 14040192401804557376, 14048692200692341200, 14042836114031696544, 14031744324563649792, 4824591506722032912, 4818153786178878464, 4820558019365270624, 4824797307342564736, 4822260355243384544, 14043594517210427136, 4820590286483827808, 4818951146682830528, 14045407653358760832, 4816400647425864320, 14048869907398063056, 4825185492861331312, 14049151211878298592, 14034801237514465152, 4796992939868878848, 14038392605521538816, 4810724391398766976, 4823181724992309056, 4817100580799474880, 4819699672687728800, 14043901784075455680, 14048977913582474784, 4824636694958947728, 14047408189128739904, 4823811888465729744, 4814473862462062912, 4816366796509624128, 14049139232926434144, 4818730331126065728, 4815298740199792640, 4800661970276634624, 4797534822088979456, 4822244154465125440, 14048447337676907104, 14041057052061026752, 14040773298390113152, 4820612934798466784, 4823318431755368448, 14029556916406815232, 14045944328776929056, 4824845315896753296, 14042583567146315488, 14047737192188980240, 4821462247596004288, 4813595094717716992, 4823616883218023072, 14045212025504628480, 4813108904091509632, 4818469734389131968, 14044757486455116320, 4816972518788146816, 4819683002147815808, 4824173819060184320, 14039450015401213376, 4820424705743848000, 4820839725594160224, 14034551967967741184, 4825080499778044544, 14044041589466984160, 14049039333486054336, 4806602919535342848, 4818700011736314112, 4822538523765737280, 4824382965078694896, 14041902772234098304, 4824237288610453360, 14046831556157034720, 4814845785237918720, 14046897622289712064, 4824620131882342784, 14042532972881543040, 4815119674515879424, 14047947513181789952, 14040451477640662784, 4821208121540503744, 4814053300957567488, 4821819844351069728, 14047629914344027488, 4817958729685370240, 14031770142241237504, 14044352450847890016, 14028092292329113088, 14049173855662117136, 4821489147587003520, 4825393231510414816, 4816587896926043584, 14038669045262392000, 4826112081390253296, 14048244149719511040, 14044978304958092704, 14042879469581325280, 14047990989255782816, 4825409723702621872, 4818884777805559648, 4816419155821253824, 14034919406712995712, 4823133687202126016, 14038607720124004800, 4822286561576807616, 4822260931419015872, 4813012055893198336, 4820578923075325088, 14038140370196862144, 4824382268923450448, 14043567278679383616, 4823552579815315664, 4821790270410893792, 14048132096760867472, 4821978643873519488, 14048188087888229328, 4825499609220579008, 14047984753749767312, 14042466327433861376, 14029893333343486976, 14047535968311779152, 14047557452438877056, 4822627378513280768, 14036818453481021568, 4824912654509633600, 14041726746972559552, 4824106279155864304, 14043418095994417952, 4803116275213315584, 4823566597828160992, 14041761321219023168, 4810379818947513344, 14045510424921823168, 4811754761000817664, 4821906632488989728, 4815096383337692096, 14047542845157394032, 4822848993038502880, 4819456631258319904, 4822727259725573408, 4823986910134373760, 14047170596937602672, 14046897254727875200, 14040077344334118528, 14040899048908620992, 4823375846897111936, 14041781426061703360, 4824641192445356064, 14022268178799889408, 4814129730951775744, 14048796573012468000, 14042399171867924480, 14045954719682565472, 14046545194540246208, 14045244851398842912, 4820272687960210880, 14047390047434165312, 14046278831698285024, 14037436958055175040, 4821776659163575360, 4824543825542467440, 4811482767314956800, 14040288803249597184, 14035253240151331072, 4821715884245035680, 4819051953633670048, 14048840184787734080, 14048461930705752720, 4826104299469651376, 14046954350179926560, 14048799971822595072, 4825956652400283616, 4814585895407026368, 4816118928550544320, 4825693321851677632, 4824306772860527616, 14046145695133705248, 4824670895886044224, 4824984420502205040, 14046757309880988608, 14037850422373253248, 14040490362389863872, 14048655952136170432, 14040361922788276096, 14044513833750573472, 4822074760257551456, 4819897032723333120, 4821879424832142688, 14041645708105249728, 4822698100372988832, 4769382678855090176, 4824416239948476480, 4824184770882028192, 14033286647956071808, 4824277990100371312, 14042677436634696640, 4825796985200076944, 4811934966415820672, 4824956497349613936, 14049080114768413008, 4821302276642317472, 4816185732763096704, 14041003154558285184, 14041849722295935872, 14042095665098442048, 14046765349444140096, 4823417160342708560, 14049055943231807040, 4824356156037244096, 14048712769202459344, 14049022432231894896, 4810481548198206976, 4820793766834305920, 14049404426116073056, 14026584218614313472, 14046377525596372096, 14037160552242612480, 4825438237651103216, 4824565539385965472, 14047353912631895904, 4823743228092602720, 14044255753598116768, 4818043524384019648, 14049428144266440144, 14049369226999554080, 14048685168941676432, 4824652422686914944, 14049419684778306848, 14047127409917783088, 14034528702478299648, 14043533643187181824, 14047132377292058128, 14043460673816996512, 4783359583883214848, 4822006319237000224, 4822194500623665824, 4794675492266926080, 4823265792846555648, 4814027937094236416, 4824101655379145152, 14042950922221528320, 14038325207794778880, 14048750879072725104, 14030844322825829888, 14037622250831881344, 14043920401321528448, 14044784105639808896, 4815462022231653888, 4816124197111810496, 14038723667232665408, 14048595349410294032, 4825974137205583712, 14044105223831518688, 14043938311348614304, 4825069442163264800, 4819112179562838976, 14040654754187275840, 14048751193535242240, 4815308145543523328, 14015422292051261440, 4825351676772921680, 14044350090446031008, 4823682496192554288, 14043174864867054560, 14037309698334639360, 4801028987059078144, 14048472544522176304, 14048164459519026144, 14029598524037666048, 4823225613997541408, 14046185289839958784, 14044193389445317440, 14049255195022175248, 14048842451255185088, 4823391854863890256, 14046618366497075616, 14044850773938128928, 4810830775688146432, 14015786448413880320, 4810501707121132288, 4812642632825899648, 14042998384337562816, 14044274816819490304, 4824861648590340496, 4824286565732335904, 4806941321644365312, 14030487126634521344, 4805598864205244672, 4824392085685162880, 14043011847145156224, 4798442266469725184, 14046134534072593664, 14042268165205901152, 14047295748668881856, 4823266060931175840, 14043605609315993760, 4824097695465351360, 14047846618118058976, 14048031471485058032, 14047275204363369904, 4807462349740220416, 4819511344131059328, 4823729613383934592, 4823811170184019904, 14036097919948041088, 4821699566704247104, 14048032517521740160, 4822614747095277088, 14044354243816428992, 14043805724068549792, 14042374067959400640, 4812518790674045056, 4823884912164455056, 14042236504579985536, 14049406471192098288, 4825030496684047040, 4825186483886753392, 4823783518265645696, 14045271666221143328, 14037005880688230144, 14037060398469251968, 14047550698584150128, 14038042917576651840, 14048356879725605344, 4824802777396462672, 4820084697453743680, 14046059821839046080, 14041621992269793600, 4820953398134286720, 4824272495401843664, 4823672112317320864, 4807244252795201024, 14039447917070851008, 4820221792489145312, 14046263992910333824, 4820378214053610048, 14049305241114861840, 14035582490745490432, 14046940638736251888, 4812361753545414272, 14044355165553484512, 4824471852330480032, 4823832628572480688, 4816229459415984000, 14036360707813798784, 4822332225055689216, 14045966870913586560, 14045537307402781376, 4821633100838645376, 14045828351767763296, 4824388769982014544, 14047059316928551392, 14049202112606955200, 4811395280921612032, 14049478264043877760, 14043068542761814656, 4821928761914013632, 14043654340270384864, 4821063345988320000, 4820497088082072864, 4821630392490327360, 14043904291594592064, 14044468838323855584, 14046506042023143904, 14028389909469078016, 14048686219154726624, 14045528671236498912, 4821146503347831040, 14040778038683541248, 4815926276788897152, 14046626749148089344, 14047026658313383680, 14048969457063630448, 4821462222995653792, 4822300136827196864, 4811826401062109824, 14042960056612821888, 14039967300100255744, 14049466609464251024, 14037796681763199168, 14043885509709874080, 4819851305991772928, 14037974093083905024, 4814429736733341120, 4814576073597498112, 4824958556196312864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4828949516075925512, pinv: 4384749916449448183, mod_data: ModData { n: 699289395265537, ninv: 11253674057546036186, norm: 14, }, primitive_root: 5, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 14043622169812404576, 4820260646800627072, 4822573843679186272, 14038877097332927808, 14046789977532042656, 14040713522786628864, 4820318765268317568, 4816131317178144384, 14038210499179756032, 14034957500497820672, 14046779774437867536, 14046128589799704960, 4820756715955919520, 4824138563762302192, 14041563707511352064, 14032199640911435520, 4820094505759813760, 14043445196645936320, 4799321977349047296, 4822760672783583840, 14044080953280510016, 4822523068557746592, 14026336481545697280, 4818294762781998720, 14046537768768901696, 4814149164508726912, 14044679199084454432, 4814454491016390016, 4812371157287901440, 14030047316150949632, 4814010356613300352, 4822158243140402464, 4818887362516281024, 14044694573841889888, 4820981925724966464, 4811888475589693824, 14034062459116458112, 14047005782346875232, 4822729425437265248, 4823655726712856848, 14043037793104442784, 4820917078078769824, 14039972651024706688, 4821888537163889760, 4812395179851828224, 4824016768529508592, 14042680746024769984, 4822441165244596544, 14044515236017049568, 4819206254053179168, 4822883195612228256, 14046379120446889120, 4811091376783488512, 14043437165170076608, 14039185161466973888, 14045508837599775648, 14039892832563519680, 4820074524887993920, 4824101005073826768, 4817518632395394176, 14046934402978041536, 4810925620462777856, 14042667939352407456, 4821996414453731744, 4824050690961512688, 14045054452615266784, 4811410312514628608, 14020667972812045312, 4817607100219359232, 4814368951648908736, 4817564953312376000, 14043752184207923712, 4823907058541388384, 4817340186786187840, 4801444388224095744, 4817743510261775232, 14041537792859798080, 4812242691984983296, 14043873430346643200, 14046720773401538080, 4814253760473245056, 14043187474037793632, 4820601772358799648, 14045432882452764256, 4820900973366881312, 4823671623248192832, 14042375358230552064, 4822961560921908832, 14046341684750854528, 14034872908559974400, 14045673850935154208, 14029268316669150208, 4821975219248184416, 14037881574677811072, 4823647178519455504, 4821648941924734464, 4824171319922972672, 4823438770983749680, 4824247795801318816, 4815867839057086912, 14037724999193881920, 4817548391051320384, 4806258190725730304, 4816520467902283456, 14043313577414176320, 14038527723907451456, 14044074853032869344, 14034096991020673152, 14043968160581506752, 4818777410307253056, 4814642181812998400, 14044350324362495744, 14043368496364589760, 4819821581630061760, 14041349104641567616, 14047163315950227552, 14043554826534533856, 14047189380119438624, 14044858954455262176, 4820128832851998816, 14047428064220476624, 14044274040160876864, 4820829726595801184, 14042039755839511232, 4822419882713052896, 14037225492272940416, 14046963845062170688, 4820099090541598848, 4823852019483065600, 14034248747490327552, 14044643570980827488, 4821556909575146880, 4818430834453135680, 4821928841695917504, 4823156828571927104, 4810889972902040448, 14046509955294258784, 4824093576705813840, 14041590503602655488, 14040098001600446528, 4820280809288724000, 4813907434516782592, 14042429183096496160, 14043674829125885440, 4816282725486917504, 14039992787601905600, 4814216617720513280, 14047535996141040896, 14034239836294137984, 14041030856545134144, 4810871949714195456, 4819451437098533920, 4823901371604669360, 14039765802660186176, 14030019569933987328, 14041675386841725952, 14047633612471047648, 14043614323179790624, 14033790638749349504, 14033888789444894976, 14037349057875565824, 4806766194143211776, 4823799573121956848, 4823402433425703664, 14040937207348252800, 4820360742863475776, 14034832389925438848, 14034493482725009920, 4820354681490794912, 4818482190339795136, 14033530162271277440, 14045119797399565792, 14043340740026992864, 4820667382640596384, 14047694009375627424, 14047024917097743232, 4809923789654065024, 14047591276808957888, 4821532897338383008, 4810432822819576192, 14037419401854811264, 14039134448345630912, 4819941097337078528, 14041365389354265728, 14045781663357997760, 14042237466566778272, 14045509568781967264, 4818103450094096256, 4823932290543593264, 14046215671105456032, 14047246413984495360, 14044429366592736448, 4819953078662576448, 14044459359221533248, 4819464507767685952, 14043353343820478368, 4816611966817897472, 14045655143175751808, 4814681875637925184, 4811093334935509760, 4820033184784169280, 14047281546861695424, 4814961490307933312, 14045404447320625792, 14047676172173846944, 14038633807406693440, 14043407695779075424, 4823044641922566528, 14047407281020006304, 14033912883990579072, 4815601122006018176, 14043047140831385152, 14037856019262704192, 14047038263980883312, 14042047826908587456, 4820380867193468096, 4817816531671256704, 4816212912883396544, 14043501535211092224, 4823429979313086192, 4820042440627305376, 14046793868041777232, 4818885770280867840, 4819034605394032992, 4819571796108807616, 14023453306044328960, 14045650647085269760, 14043801547175169280, 14046186570240108192, 14047483681688135760, 4821290887276774240, 14033217278498342656, 4819911857498680384, 4808340188163989504, 4815333207238273152, 14034832845719066112, 4822135365517782624, 14039789843977418432, 4803668765432732160, 14047583816746123984, 14046640226131609408, 14045008295670867552, 14045933732607524544, 14043978625119140128, 4824058248590978832, 14038404182674419008, 14044118930343270304, 14039883046456645312, 4821081913489825184, 4814398025824142208, 4824058901242842592, 14025075400061671936, 4822122106120202304, 4819808804479115104, 4823466419039476496, 14015804925431586816, 14046689924603614592, 4821092173317015936, 4811433636320527104, 4820701025712794304, 14038668452057523456, 4819142796082036640, 14030291785226319104, 4822534139109102592, 4819974328558699392, 14047111197194485808, 4823522585981342080, 14043326400199287328, 14041158113909547776, 4820066968442715744, 14038284821883315456, 14046454559332973696, 4816863152391875264, 4801844642556047360, 14030838457869437184, 14044245485609018624, 4824002761257276320, 14047201605907862880, 14047470344364679248, 4823442205683944784, 14039136091797708288, 14042829870255358208, 14042453736200543296, 14046510112333758656, 4810111882680845312, 14035030130417796224, 4823962173626402464, 14042029922203515200, 4824036221686191328, 4819518786094181344, 14043580622539006880, 14045400293764423872, 4820862570444941568, 4809348836144409600, 4820028051821109856, 4815527810206517120, 14045228816188525568, 4819164213445513280, 4809646368961016064, 14046452663811927744, 14025694194603387904, 4823117543791448768, 4821122636779388160, 4823108859459870112, 14032294317663131392, 14047756100522196192, 4823676480650987600, 14043736326378521216, 14041549032997534400, 14031469241185101312, 4812466407924748288, 14047509160669308224, 14047414333192198960, 4824002467170509904, 4821858009671189952, 14040091836428805376, 4822217370431250304, 14047425005988311072, 4814830103186837568, 14047702057678751104, 4807940491001978368, 14039263309563137600, 14046872156462453536, 14034447162012730624, 14042465887387803200, 14036592982926213376, 14044786340166289376, 4824386400086355680, 14043005857572139968, 4820781543195351520, 14038020901410037952, 14042573320898817184, 14045202238081672352, 14040836508132771712, 4815950739044206144, 14046604953799357504, 14043569712193431392, 4817652991098281152, 14047679835368999936, 4819860404236049408, 4816338417212381952, 14030471744253419520, 14012962421188407296, 14043206600420825472, 4822510664899144160, 4818457576664356096, 14041697943456771712, 14046058705042125280, 14039167911876574080, 14035851575353102080, 14013054850496634880, 14046044976447218976, 4823751821983431264, 4822984316768337696, 4815844127523398080, 4814375942658755072, 4814695690189876032, 4823454173919204272, 14047452212117662672, 14042812125404062624, 4819865431687444928, 14045802026688278112, 4821003521003799040, 4808364794116682240, 4817807316505935936, 14037581177733054976, 14042043248586366656, 4820046458460908800, 4812164612270672640, 14046654129173130560, 14047028683554418048, 14045526640024013536, 14045713671736887648, 14046738285767606768, 4819325252867581280, 14037301465152720256, 14021796180965095424, 14043033520629742176, 14045715766151803456, 14045134234030252544, 4821090419031665888, 14043632688864235552, 4814443574702891264, 14032540235963274496, 4818856530772798976, 14042688069984519072, 4817056524521545024, 14033846136224726912, 14046877321506387296, 4823540057395483472, 4819961233825566976, 4824084153442196256, 4813323162036251648, 14047054658779337024, 14039636265290296832, 14046370224734734176, 14011988691951890432, 14045068111392108160, 4808841565679293952, 4824175760497460256, 4823879744258072640, 4823616708974570176, 4816122353194917696, 4819608760767729760, 14043333733207115680, 14041581415907576832, 14045553617792299392, 14032720118534142720, 4818669332546279616, 14026377232137765888, 4820410821450748864, 4816202042025028480, 14039750124826510656, 14046402519547720960, 14046982624331150976, 14039216802048463360, 14035620496669053824, 14043994442163451136, 14044603530843385440, 14047197749305031792, 14047202301398791712, 14045478327086566240, 4812835584192394880, 4809948737117772416, 4821199302567040352, 14033665550503202560, 14038156641033573888, 14047225690915886032, 14047136181268232688, 14046071615915710912, 4811781641904160768, 4821898166512144480, 4814572013159245056, 14037225920096226560, 4823594233837227200, 14046196277058815424, 4823884165551758928, 14043315232960542176, 4821175535986151328, 14042616457197594496, 14044319524801472672, 4810593049454641664, 14046956031271516480, 14041306620889620160, 4821493126648458816, 4817591451093321152, 4800838502195677696, 14045807721087566304, 14044828202376958656, 14043037583512972480, 14033463612184828544, 14041327813539761024, 4817384796826576512, 4810658033262625152, 4821734735177489536, 4821667046011553728, 4814614355515668864, 4818695820502350912, 4804051854443058688, 4823673616019886528, 4823004514785253600, 4824285018759717328, 4819434538446183168, 14046870845312110960, 4794221853083949056, 4823036053742170656, 4820491386959525184, 14036553047416682112, 4820904373366483360, 4823966639664836464, 14047143128583705520, 14041888647535081792, 14038351455690147264, 14041402637267737088, 14046563369396852544, 14044405222571455168, 4821733245809106656, 14041296320886141504, 14029182595785412096, 4810613454136512384, 4824155311598023840, 14036554454700787200, 14046783552962743856, 14045739126607319712, 4823717255777627008, 4822117072162131584, 4821325161344766624, 14041339293954118720, 14032983494146037248, 14043727192940695808, 14045730233505128256, 14035457906643770112, 4821444944054979456, 14044211377564050880, 4818964265012595456, 14039140048919979328, 14043954114552936320, 4824258882281306800, 14024314903945856512, 4816051272643639488, 14033098932633552640, 4812856766119812992, 14030655565170129408, 4822232571614508224, 14046864565567694288, 4817030799777859392, 14038747192528326912, 4824330384189775440, 4822504753350063712, 14031812946410993664, 4793487639464667136, 4820840318078287136, 14042963498816043264, 14047403077778826064, 14045770482712163456, 4823971822618995008, 14041709635758112448, 14045422595035857024, 4819934385958348768, 14046966949366733968, 4823788193090275552, 4818574439711966464, 14042366643440688096, 14040679777762224256, 14036475782379602304, 4823090045290943968, 14045193000021854336, 14047210510611244496, 4823370883855062656, 14044192438102974400, 4823172849935395680, 14044225369908184288, 14034435656948726144, 14044595568539341696, 4819843238134021376, 14039236751501446080, 4815999922638303552, 14046506960797797920, 4824202189178808784, 14045840884842992256, 4823496428407902272, 14037259741467357056, 14043622418241040704, 14043059494606156928, 14038156977094539968, 4783978436742053888, 4818132683076678656, 4813426806276434560, 14046746601476066048, 4818996469832819360, 4821908214814757312, 14045129393805524000, 14043555536151410144, 4818359763290334144, 4816531298906286208, 4809050785284685312, 4820687565394306912, 4814962452183171968, 4816748216926943616, 4823363748359853632, 4824154252412549984, 4820166780470940416, 14047237557269939792, 4809009933805922560, 4813083720545387136, 4817310522289793216, 4808193529407754752, 14035993606406228352, 4822839965905744352, 4816286824866341632, 4824398709287367408, 4817951279683016000, 14035220148909657344, 4809375484956807168, 14041757651118764928, 14027307665113732608, 14047205508875497056, 14042499981999691424, 14032227273470490880, 4822126230674729568, 14043123241540916608, 4807652468853835776, 14031133270441010688, 14042360401905887168, 4820914221227115200, 14037435489212567168, 14044084425749825696, 4802179898236015616, 4823551942955099344, 14046918219052111920, 14026823325253606400, 4796095687483103232, 14026789765757129216, 4821147753823584864, 14041818953012312448, 4823163643539026048, 4766042926904115200, 14042311063187861824, 14043677731116685632, 14023518806729462784, 4817883846808087040, 4820457992998218944, 4819872476039679008, 14041368555148452672, 14044912701208465792, 4815929607722593920, 4819988750094976960, 4816627786067625728, 14047223259176871584, 4822490460766517888, 4823483232183730720, 14040846908839080896, 14038974442322030656, 14045074022424090048, 4798963152046280704, 14037957902305924928, 4821690006425703744, 4823411257956384368, 4823992799853228208, 14043786027421583232, 4820750559898109568, 14047741898484199712, 4814488575167785664, 14040587549682378048, 14044471466730240064, 14044552144996588288, 4822454133142842432, 4818888246343293056, 14043307761330580064, 4815511458374083264, 14047145333009124400, 4811563159049379456, 14040580528924771840, 4821425709764831104, 14044856613195920896, 4819417043021988832, 14045954889587736864, 4819944663728237632, 14043310348455819008, 4815975069841904192, 14040175661232084096, 4824107697156858960, 4824353630469378864, 14046018757555336416, 4806990858200654080, 14041993464964108032, 4823684758329874976, 14038563780437312768, 4819175075508282336, 4823874181292764112, 14043144080914987648, 14040042897433577280, 4821895222841946560, 4823132903861166112, 4824079204884126304, 14046946443043562384, 14047720022943653216, 4819540031306070208, 4819357409200788384, 4817468216411049472, 14047173831390564256, 14047123920917366928, 4818178365637546304, 4820530769269769056, 14047157357336623872, 4823347699934185600, 14033043259111935232, 4821818413153605696, 4817198502996766336, 4824187978197310864, 14045100641827239392, 14047038361393043072, 14046605285666345312, 14039305344636488448, 4810523087717874688, 14026524969219397632, 4803872913560872448, 14044844408500523744, 4817526612956464896, 14027674970290599936, 14029179487705461760, 4819949486005550016, 14046854149593771168, 14044201139038381440, 4823209412318806464, 4820970325931014336, 4814250609519187328, 4820326288038460128, 14039766727968974272, 14045348013855690336, 14035707004503463936, 14043687304030906528, 4805380190266265088, 14043226173178851840, 14043324881835903936, 4824294074677586704, 14044663791410196576, 4810117436090050176, 14043238005528761440, 4822936899357343296, 4815454000118893184, 14040897901983854528, 4819306997691563616, 14037162276539896448, 4819609759356024064, 4823489891231088656, 14044646305517983360, 14046879365114303888, 4823943150623105024, 14045771174191091232, 4821346449465260352, 4819581426122145280, 14039526531889766592, 4819506159990865440, 14043119839825452480, 4814848318451207488, 4817774253451244160, 14033118546134105088, 4822616679730318560, 4820679990685140640, 14043768648330125728, 4823367146092250992, 14039519310753470144, 4823237822014886016, 14046686107588891968, 14046865775558950576, 4809103308284029440, 14034866622232945408, 14043985310248309440, 14024452337409473024, 4821663172441960352, 4823546136580278448, 14047136659300635936, 4802285799709803520, 4823425069428663136, 4822126090050887744, 14047119497713103984, 14037071496746457472, 14042510845646411136, 4810744590775204736, 4821373128345012192, 14042399760732162464, 14032786096245446912, 4816613113329098944, 14012605496929517568, 4824061245623153328, 14043502198842249600, 14046813127770734352, 4819734390975394112, 4818369390807601600, 4795893271938328576, 14047442016166096496, 4822786277664820096, 14043915354124806752, 4820157834971302816, 14043270839095819584, 14044245160504810240, 4823926365893410032, 14045855751513110752, 4819915969166955968, 4819034108168235264, 14033412400007804160, 14043984856887490560, 14047342318824105024, 4817475156129353856, 14041466827699587712, 14040675632413207808, 4824181990246711056, 4815970480796887296, 4822047264229300448, 14040144833860637696, 4811279055512741504, 14040371541105193920, 14046282590089387072, 14039280122820808576, 14040688022735639744, 4804760781293358080, 14021313057689651200, 14046788451590536784, 4821417974426725408, 4805270108595715584, 4819861924579995712, 4823789505175069472, 4823498502611394912, 4822730964651350080, 14047805676004729376, 14039661977931821440, 4817944660572179264, 4824291948519746768, 14044298070743509856, 14045484585407742784, 4822551436983163552, 4815543611252325248, 4824138358834474608, 14039224806601896192, 14044539381100877184, 14041648675405619264, 4796778203629168640, 14039200678751936064, 4824214494743993168, 14040485861987321600, 4822852223001953024, 4822076728507849152, 4815983234994135936, 4808366224312305920, 4815099879688953792, 14042247284177313344, 14042437404126597952, 14047812873348838304, 4823069288735457056, 14041347010159477248, 14043894429400383776, 4819635122802553248, 4814201408701105664, 14044639037278289824, 14039409820255928640, 14046838717014631424, 14035993071963813376, 4821277331901735008, 4816909351676540032, 14047251431830400176, 4823386327318295584, 14043720908594367616, 4824386002378177184, 4812679633421980800, 4817421229549538048, 14033452516393702528, 14044800509343097920, 14033229931787345280, 4817889888602242048, 4821390566307734656, 4819892278784002592, 14042457067283930016, 4816362956143920192, 14047202244297569216, 14045012888550132256, 4805521806100503040, 4822854508495359168, 14036777155852232832, 4821621989105673184, 4822787163933571616, 4811881962806754688, 4818733485796270912, 14026740726560588800, 4823316387193691776, 4813063882923683200, 14045289969087003616, 14037999651314512192, 14043375513149635872, 4814923814646151552, 4821041720292596576, 14043620217465391136, 4823648192736489456, 4818973826825290240, 4813652998116532480, 14043232546410813152, 4819027547726639136, 14045478387193786208, 14039157476229041152, 14025614513382237696, 14044429658342186304, 14047203122135595456, 4824105151430563488, 4800457286325762048, 14043750156781419776, 4811278816331313664, 4816175674365221952, 14046782384356416304, 4823728238871735584, 4819393609505329312, 4822142690440658240, 4820939274248517984, 4817969547440828672, 14033371660031957888, 4821694922204432160, 4823895697141775440, 4816615263466927744, 14042639520078681824, 14044849793104973440, 14037351968203753856, 14032879055835801856, 14047747907821636544, 14019625697997414400, 14044667941025892576, 4821162679917262656, 4814481077713604480, 14046415865069205760, 14031671723543405824, 4807864248816519936, 4821950446119995296, 14045530015871105120, 14042326353034790176, 14044507126665772128, 4824325313948793920, 4822274309197656352, 4811040600690807680, 14047323673568081264, 4822183065425030272, 4815867489894007296, 14046350567857243904, 14040193659206467008, 14045347602934944512, 4823223568518759808, 14036067751827837056, 4818132043388972544, 14047468777877987584, 4820343031604131200, 4812399488116299392, 4816008373029099200, 4821481485189605248, 4819337461674651168, 14046679949678637504, 14047815089873968336, 14042947909259589376, 14037261240246042112, 4818058723696343552, 14042726144028443136, 14043368531914356448, 4822972953928057024, 4819273939932173856, 4824020200243955040, 4823455050795745984, 4821624143044066976, 4813831970443995648, 14042766079320147968, 4823963453842999952, 4823942240464260240, 4815103213467292736, 14037984822979324800, 4819456754642742304, 4824004654800969568, 14035054418122695040, 4800861817045789696, 14044257814735385664, 4823839124462615664, 14046074964494274880, 14043526065680249728, 14043690562130644736, 4819849880524195616, 4813705100284043520, 14043017636332461920, 4823277396894680480, 14046771103108435904, 4811701252214606080, 14044074701934453472, 14046691510459560512, 14035590490954711808, 4821582773325890272, 4821026842438069344, 4824348100021438192, 14027294365644390400, 14037373555536799232, 4816353349070511104, 4824093909524020016, 14033525834677674752, 4796550316280591360, 14046799848272269824, 14043288919595671680, 4823875330713175664, 14044828494615906560, 14039135898914167616, 14040087203332719616, 4820694628967938816, 14043203501399302560, 14043214455983603840, 4811846308115197696, 14044466400820524992, 4820418802992555872, 14044095171702292224, 14047196262663958496, 14037253022752426880, 14043311279324989696, 4821993449993954208, 4824167910211928096, 4820504733221238912, 4823328096244781280, 14042459008937992544, 4818521394997896064, 4822132793564605728, 4819808722954947072, 4817063439390191296, 4822866384427722112, 4818995693736758688, 14045805217667766400, 4824085392327121968, 14043456638406588544, 14043910448931916736, 4816646781953200704, 4823426723838847424, 14039362996229706496, 4802112402200382976, 4813690592250630784, 14036681282497341184, 14046486183015637952, 14038651310703014464, 14046772694437265104, 14046366383968819168, 4815079338717749696, 4823285429037740320, 14047487969137554992, 14046727326390886624, 14045374426879913056, 4805425183921085440, 14043469041260087904, 14044567288922222848, 14037120031637651712, 4819761250553177280, 4824234216913190768, 4806692794488079616, 4810127876327453184, 14038081110549116672, 4814567855690719872, 4813083631402520960, 4822861541160848064, 14046273295588046912, 4817838498090627584, 14042599055953016288, 4819004256292943712, 4822178453996379168, 4822667289824115072, 14046712362839916512, 4823993970596108832, 4820510323589020192, 14044462363846754144, 14036637511010782976, 14046321934247365792, 4823265277364256800, 14037305606934383488, 4823504002887360736, 14043928817053838688, 14047678883796565920, 4806703235479384320, 14043423715690290784, 14047086673479039744, 4806925163618326528, 14042377459093944704, 14047734693509710528, 4823429713392018864, 14039394641841434240, 14036661003382078464, 4810056547256150912, 4809190772735646976, 14038964654704901312, 4810292617849562880, 4821900892222560768, 4813603724124372736, 4819280735755495296, 4822610566489478880, 4816006883859259392, 14042634560297810816, 4816898174306484416, 14041415729104604928, 14043204774323879424, 14032263812185247744, 4824251022306511168, 4815714708448250176, 4824352099176760064, 4822771627786350400, 14045456005608666432, 4818150845709286592, 14046492672684653568, 4816196911150624896, 14024289203754354688, 4816132990815136512, 4820722995010682368, 14045548618391181152, 14047335087038948656, 14047483236205469840, 4815287811986221376, 4819392621112817312, 14046788616729130368, 14040185748553312832, 4822521488495523104, 4819037459709960256, 4821857412005156160, 14031289661305577472, 14043592793576397216, 14038079824613482048, 4819796039201375072, 14044855003696071424, 14047348241374504656, 14042668096284843232, 4823787437636000992, 14047143116912036928, 14043405734570576224, 4809161337669878272, 4823652707003485152, 14016115953265508352, 14042493814881047136, 14040564740421615232, 14043693961272589024, 14043558905470939840, 4819128362036283232, 14045160005047581824, 4820459876836838368, 4820740460149114272, 14037838192801226240, 4821324465880169984, 14047713368799961760, 14046136698295636576, 4818957119718662848, 14043087881275217504, 14045321649620690080, 14047751558931847168, 4814481604469777728, 4809688636361510912, 14032747037574260736, 14045950286585398176, 14045468384871546688, 4821035325058280736, 4823893253549734672, 4824235338383295664, 14039822301124175936, 4813737672817582208, 14039059043318756288, 14047355953993082944, 4814448375291251136, 4815373750324788224, 4804740873396689408, 4821050269607314400, 14040139703997154880, 4800843072695213568, 14039950304279988800, 14046483720400632864, 4816236974661058304, 14044510976345469568, 4820845278245663840, 4823921198926354352, 4820982581941428384, 14045302150871070848, 4818976014650297344, 14037399115891802880, 4819452753883066976, 4809857189520310400, 14030285707320278784, 14042171374130253312, 14043546346655092192, 14044504015016730048, 14046750616062742272, 14040128030505077760, 4821975792296201056, 14047735014810467472, 14047590122618461920, 14029594415300371456, 14047281100856681888, 4816831069296658624, 14045486262967254848, 4816209115508185152, 14045870558914631808, 14046952042967399840, 14042892920375540864, 14034595799128908928, 4819129793108769632, 4820688790156186304, 14042322096102552448, 4821428817846958144, 4819289188876866976, 4820802049049149472, 4821885868268199424, 14028583769458949632, 14038065367203005568, 4820964596614892768, 14044587721461000768, 4823273201925636832, 4821577155318449536, 14046068461590181568, 4819177116451387296, 4815199045803863808, 4812986310863715712, 14042320457874115968, 4821728869175179328, 4817118290021593728, 14044465515386736704, 14043013489679421888, 4795212145455230976, 4806010771812087808, 14037825921087217088, 14025382076973410304, 14046340635113923968, 14032305161331090432, 4814754911905610240, 14043531567504032640, 4812425179533299456, 14038261719361869696, 4819873550969124032, 14047109864937727872, 14046395427080352640, 14036812773169494528, 4812480689164345600, 4819100447569198080, 4807237462296128512, 14043731760297209248, 14043723129297686816, 14042645333447402144, 14037835835822670400, 14029110348785317632, 14047006297395373120, 4821913063741499040, 14044936016405150112, 4822717712052554784, 14045122524653940768, 4821591284936040768, 14040457461073027392, 14016146425523748864, 14047012642170281520, 14042544041986816384, 4809028432532429568, 14038156633758640448, 4807954720591889920, 14045947572926379328, 14047159803845178544, 4815611164880093120, 14044686521039847744, 14045495830219821600, 4820319362502675936, 4809294525693260544, 14026738281151544832, 14044109710240746336, 4813233988649725952, 4809210244393566464, 14046096384653893120, 4820502585899403200, 14039073281870312384, 4819381377692448544, 4811759195293818496, 4824252495791743248, 4819209359266834624, 4818434242659458688, 4796651384639742976, 14047304526397579088, 4819057072899896704, 14043886702060342112, 14035702716919901312, 14040144809997392576, 4816691232206152896, 4803928499375954944, 4780354733611663360, 14045782709149081248, 4822204646955057312, 4805702824993946112, 14043870095802326976, 4821653791802953248, 14036088984019447680, 4821693308789346496, 4819780132599639616, 14043391129296452352, 14019928981721321472, 4821046524681233216, 4806594942043273728, 14038297889287020032, 4806870243188259072, 14039290441169335424, 4811819949339144960, 4823651863586002976, 14041377308417522752, 14047065904518268464, 4823984547277953344, 14039579719176256832, 4816809430984693824, 14047330352750505536, 14047267481834992016, 14046145811618960896, 14038887624297920320, 14044618032489246976, 4820233682049965248, 14042452114862676192, 14042458847591791616, 14023180132084197376, 14038444346622941120, 4824299395723656016, 4818272672822072832, 14041604791378313792, 4822579585108401376, 4814511963403040768, 14040815467222898240, 14047225347427368896, 14040018757898264832, 14015889855587938304, 4823517098469829184, 4798166518074552320, 14042240202746069856, 4817631435430149440, 4820248451816436352, 4819095661418445280, 4817153832058025792, 14046924599444585104, 14043006637709542784, 4821207532900752928, 4822614504780526464, 4822005759589214752, 4819224138882024512, 14044557171411834368, 14033963449974099584, 4815613233092124992, 4811504947924010368, 14043191541465349024, 4823597637253280480, 4818528872451487680, 14044792103934095424, 14037985647362476352, 14043504252721566208, 14027294662693879808, 4819925851587257184, 4806433837706846720, 4815540747419930176, 14046849628928559136, 4820726315660429312, 4824030503091524288, 4822969168663340224, 14047146896339617040, 4821737278308029504, 14046209731321115488, 14044771878530547424, 4823761369698104336, 4822423121304083072, 14046875776775005424, 4816365006486358016, 4824122976934244912, 4810358632108605056, 14039862300397851072, 14040819618519188672, 14047311647881819536, 14044181267499570144, 14044941080029631264, 4823209471822802432, 14033305008224706432, 14044453522730380704, 14043563134412925472, 14047391853295458368, 14032052360908685568, 14047107929229772432, 4816477744177171200, 4819553124043671264, 4823003935814415040, 14046743297769601776, 4817713036143886720, 14033661123323239552, 4816430168316126144, 4817288844680599360, 4823785270842236416, 4819943196091629184, 14047704534451122336, 4814975870930787520, 4823170433987067456, 4818949894631688832, 4818213648479335744, 4823533175616710144, 14044434197586028384, 14037386034400436608, 4816598624796006720, 14047688961801601536, 4823976763447732832, 4818592093900749184, 14034360070733327360, 14046314264033446592, 4811856828549281536, 4823838852269394576, 14047442732139253408, 4819316904174790752, 4823822818513649056, 4797176268169957376, 4821076299014588288, 14043004763967198304, 14047394444087282528, 14038558150485732352, 14039208544327764864, 4805995204463727616, 14043415203445288544, 4818938431963797568, 14041147250445818752, 14035902534539939200, 14035572161475482112, 14041859923234640000, 14046278991373593824, 14045561005429541824, 14047698248554093440, 4819767166932819936, 14046302624715167456, 14038586048938875520, 14037400739175106304, 14042122143525630208, 4822779434321705440, 4819396562793443552, 14047484202957279728, 14047276338225352096, 14046973764803038160, 14041324231951552768, 4817913118120430464, 14044321112560685696, 4808302502776418304, 14047484695052835088, 14042458043994762368, 14042282896502234048, 14047700643038000928, 14043567711430682976, 4821471676990267168, 4823551122999922816, 14043287067297406784, 14045580200133713120, 4822068449999930976, 14044728823497951168, 4822152951607183392, 14047452110552317120, 14040074895901297472, 14042584425914731712, 14032488491824062464, 4798059679430110208, 4823717022874466288, 14046144831806163040, 14046210206509672576, 14033479115400395648, 4824359822644662784, 14045855510849158016, 4818409429647746240, 4806216260485526528, 4814820692188803904, 4823591340736127120, 4823568540118250928, 4821120247392047456, 4817611644243472832, 14047173753915574480, 4822781831765644448, 4819987300824400768, 14042910370310382432, 4823751810699436240, 4814559528094715840, 4820311686548119360, 4816097610281400832, 4824240795786472928, 14047429247787647920, 4814691235347679040, 4823193839528439936, 14045426810151784704, 4822228182782064832, 4821164008598388992, 4824205683657917648, 14030327408881482240, 14047210223843661888, 4784967496909733888, 14047254377239966096, 4808675887359889408, 14045131801245577856, 14046693708346473728, 14047363469138028048, 4820458432932222176, 14042165364655198144, 4812125949821001984, 4816626998785899968, 14044865070543061504, 4821676881830030400, 4813504641694460288, 14046899868673928176, 4819975639416213920, 4817062688781018944, 4805183220337536000, 14047339600066537600, 4814737995099640512, 14046081227197250464, 4823205884508119072, 14044375238697131264, 4815355389786951872, 14046777796006780480, 4819711576898985952, 14045844984252640256, 4819098066893399872, 4821524325555791104, 14042360239091200224, 4824356953009671552, 14047585420050962560, 4820897390846449632, 14042923926948395296, 4820923135385604224, 14031883854365357824, 14025977562247279616, 14047701158989305616, 4822882602605464352, 14035521514946993152, 14038459521056192832, 14046824278319491744, 14039302645939582016, 14046234379387811296, 14046706673405358944, 14031836686169992192, 14032916828081384960, 14034478277204661248, 14043483872421376288, 4807027326922350080, 14045457851614463616, 14039712657470712704, 14043535995640645152, 4781190069002698752, 4822493394911715360, 4820913865558426880, 14042848467254687360, 14044218300540241024, 14042416492279749376, 14047112192154268496, 4809062849980522752, 4822869183616651264, 14034196479917200640, 14043512056511054624, 14038046419294490624, 4805428344831387648, 4822272129022904992, 14035821435293192064, 4824403183863076128, 4815312947740003584, 14046751268344853824, 14046368717321639808, 14043888645459893280, 4822979728090420576, 14044764797717959360, 14042860928432459328, 14028520610043415552, 14034495580753253888, 4823242528857728960, 4816074563009374336, 14043237273945100832, 14045006107865117824, 14042980733972470176, 4818953101523468608, 14043755405108586464, 14041952680977708928, 4820862160181132448, 4819111188669601664, 4824376700572963520, 14036515688631302016, 4819259890832796672, 14042796629121605088, 14047229467203266640, 4820352897094299744, 4814512119779175872, 14040697385971595072, 14042836612688433376, 4823312526753240768, 14044430062932059744, 14047177198079744240, 4824193127097398400, 14047247811573483984, 14042643370545074912, 4821238751087753248, 14046285498965468096, 4801252367047785472, 14045214017015720896, 4800387493571614720, 14044971559762065760, 4820916656771517664, 14043134737591819424, 14047250594244384368, 14027618577795354624, 4803390966439840256, 14044580793709814848, 4820795576566887072, 14044121145263671296, 4823639300082839904, 14046242893781764896, 4824169055156469472, 4820622911656633376, 4818407494553344064, 4823132595943840544, 14047788261233029264, 14047812518264244624, 14047132692478265440, 4823797766372715584, 14012799994927599616, 4816616543693390976, 14039837999880766272, 4819897048216118752, 14040656393087780224, 14047797001760125664, 14037145585324746880, 4823492515381645184, 4824222078569410384, 4805843460972864768, 4814952543945210752, 14033031904786615040, 14047660965375379888, 14044048253245572512, 4822321577190644864, 4810128316400017024, 4821861530746518560, 14028718968555846912, 14044975852117647840, 14047400130017730912, 14042225248557556256, 14039811888342550080, 14044384438147288832, 14042040219040749632, 14042955093508832352, 14047213254448203392, 14047779678765732496, 14040060911340891008, 4823572615632682688, 14038863884918282688, 14043910394752092192, 4798083768317329408, 14029674447043756544, 14043902370111713408, 14030235128450219264, 14045986978923457280, 4802412758610304512, 4807843497383963392, 14047309969602672256, 14047113491932135728, 14038824108967523968, 4818986369390365152, 4812029209816684544, 14046934480698203808, 4823200712926546592, 14046889795365757136, 4822380915785931328, 4824077442888265840, 4814659809643589824, 14045319376819342976, 4816101734923469696, 14044439244143813344, 14042896548077394528, 4822172772786270048, 14036867072506479488, 14047695942324142944, 4816733372420111424, 4820083093962932384, 14047491085798036576, 4819764610424076928, 4819819130727716448, 14043710494891363360, 14044466825481203008, 4823695981929359216, 4815959408186151680, 4821903456732700224, 4817141770277991104, 4812857953904731904, 4821801557214778784, 14047040383521345888, 4823661919184471920, 4822587644078091392, 4817450020359373824, 14034882454485799040, 14045375642432151616, 14046504918605976096, 14046776485600802704, 14046705019211443328, 4819623183750355936, 4819865638067829984, 14038322995019137920, 14046783798459969808, 4813560665203641728, 14025122310054795264, 4823063871266427456, 14033981220724207360, 14046721154144792864, 14042822518445384128, 4822034619507504512, 4823106131960710048, 4823940965030420240, 14043786577559703008, 14044097391667306656, 14030050004434320384, 4822512125000163040, 14033594303258450304, 4819475898398384928, 4818045198789927040, 4817389518368260672, 14047771640547672128, 14043730397633921856, 4809559532635950336, 14044726126453256480, 4821309576545680192, 4816759391062564544, 14046853696255503424, 4819100830260411616, 4824419424788298064, 14046723202305094656, 4814544556670724224, 14039271499722070656, 14026696599710756352, 4823474363640589328, 14047028948189274400, 4819682008796086912, 14039470959076852928, 14044389816826803392, 4819741696910764608, 14041095107925719296, 4824420569627771520, 4824390506741089664, 14041672947656198656, 4821408791372344288, 4819540375374127776, 4819248293728082816, 4806936962710708736, 4819895515521051488, 4823884919635526832, 4820504163864409824, 14043698716671279296, 4823766888655161760, 14047151464206465696, 4817790191762082048, 4819349715404774496, 14031104874573218816, 14047790445837353520, 14045301380157162240, 4815580632890572672, 4820684797750426112, 14037983152210994112, 4797907297199373312, 14045146575882641568, 14044799477421043968, 14040169095956681408, 14038803861642804544, 14044097748261439712, 4818698150820339520, 4823012883833596288, 14047701964549510448, 4818370161758307072, 4820576457891488928, 4820459963548459360, 14047214712514987344, 14040442517581042368, 14025077579885121024, 14044805968493898656, 14045941706387944512, 14043686832438064960, 4809849891935518720, 4816705191054570560, 14046786392345949920, 4820380062344707744, 4818950219923920704, 4822272170511120736, 4812710800443716992, 4824276746619615120, 4819029035601163872, 14033293684377528960, 14041159640329023552, 4812483688115637632, 14031904573127046144, 14042457741636850016, 14039091781613372480, 4820927318019567680, 14043242319895159200, 14046475949894047616, 4822394121775350016, 4822636981833431680, 14047740530364838784, 4818694985451997312, 14033660649117541248, 4816018022615028928, 14040709576279109568, 14044703221840300608, 14029143281194108160, 4811085600218215040, 14041872488248484096, 4816440343283382144, 14038148684625784512, 4818039173569096192, 14044409957248009184, 14047717140772428896, 4822233654567273792, 14045014413904331232, 14038262630384989120, 4801034892246536704, 4820593581912697504, 14047431067404474736, 14042106118517394112, 14045679394771324480, 14045803964235293568, 4819571530039989280, 4817992542385581120, 14040716220003257088, 4821116160787218560, 4818960771374593696, 4819982081755677888, 14047031616543895616, 14046914178948953168, 4823801245206784688, 4815421408875968064, 14045722841755548928, 14046403992055730688, 4822265548039847392, 4820146594545107808, 14041354286291536832, 14045331692075098848, 4824104892957147216, 14037279099111422976, 14011505073551974400, 4797650488381337600, 4819930329719833536, 14034802315388413824, 4808582432654663424, 14043446955206387936, 4816701342642924800, 4819646896307486304, 14046959463050292832, 4822035124047226208, 14047804957498600304, 14040768612265496000, 4824082909256640608, 4821180563040851936, 4820737570396308992, 14028017667358446080, 4816220679882033344, 4820346820568523584, 14046695006976102016, 14032358063715759872, 4823272221586211200, 4819497935761788032, 4821879668523470112, 4823163038679642976, 4807558364765489664, 14047298086389419056, 4824423895118097824, 14040807996560257088, 14035815559751593856, 14042532594863171072, 4820173317409088960, 14046802420907552768, 4819648386414263200, 14043487188473131296, 4824407500215816656, 14032104065896952320, 4823913852248665712, 4810786061275712256, 14038120040170306560, 4824395745741625648, 4820550564083913792, 4804983809098205696, 4810160583923365760, 4800920352084143104, 14038304061985251200, 14034224554573983104, 4823773871870311920, 14036993344616877056, 4814477525440594944, 14046339579442061056, 4814590255428767424, 14045634308801758272, 14042953266319071936, 14047556597275717568, 14044390333021886336, 4819334215623260128, 14043485036108604576, 14046931377355619744, 14047693987350213808, 14047153494676446288, 4820582167050542080, 4820521939630448192, 14042651207160465216, 14019164222742009856, 14040032540273711936, 14046984778975810496, 14044137808748154240, 14047309611699410048, 4808449249573603328, 14041668472275926144, 4822575134359994080, 14044530254705037696, 4820416867876643040, 14041120892287766784, 4824241054272468896, 4823878293680742848, 14046865154093029600, 4821103105562856736, 14047465985844151024, 4819533786135150144, 14035024961257298304, 4818147753074575296, 4815964475886735296, 14043995115057475360, 4819937301192730592, 4815634586181721536, 14038766028606549696, 4814052806435341440, 4822096862987138816, 14047000522048339328, 14043127205223093376, 14039377820943484416, 4816608043046676864, 4823383351250016032, 14043049200640220704, 14032474406907333120, 4819801521307356416, 14043838539212011488, 4817809623341709760, 14043998079897956768, 4820880415016955072, 14033806712317000192, 14043050433861409312, 4823275798491550112, 14016682380955770880, 14034654062998027392, 4802446900394471424, 14032910497553583616, 14036377827472265600, 14047268673396894576, 4815581361225974912, 4808680875431067136, 4823954636654102624, 4821012926300724640, 14026070393259743744, 4818333383944114816, 14047586860192220144, 4822182193071175680, 14001873419040800768, 14044876342317314912, 4824287414674145264, 14046754953470993936, 4803093063968686080, 14043762683810490016, 4817587022019678656, 4816890792834352768, 4824041454783903696, 4822712377862611424, 14040386227273706944, 14046870618327012976, 14040653515509152320, 14036381356472305024, 14044406049077472160, 14038169909068977216, 14044114754412481600, 14042473098198077856, 14043202667742072032, 4811089924723728384, 4814708407105828032, 14032588426475405824, 4811822749608269568, 14046080434926323744, 14047147017273093456, 4814798375379535168, 14040202090153608064, 4824250093547825520, 4790709949686468608, 14044306778958041888, 4821293350483223392, 4824199321065388992, 4820676055722140896, 4819710845777098496, 4810420442862988544, 4815772297745774336, 4822247186631767584, 4812128131286420736, 4807319470975566336, 14043478617439591968, 14046839708255231408, 14046936415890011328, 4817970800367820928, 4823922460348815696, 14040139312965802752, 4820578199785300480, 14042744759733613088, 14045692182572326880, 14047800216092907008, 14043327008426986656, 14044235718400261536, 14045379468488903968, 14016357975001667584, 14040780393514288640, 14033997341388145792, 4823577954063905840, 14046861150808723024, 14047023416068008752, 4820298006957654496, 4807272254180607488, 4822220961123556736, 14037977470476288064, 4811234236807556096, 14036155846884299904, 4819330245586116544, 14045492250189204800, 4806774316409191936, 4813911127496019200, 14044258906467680960, 14035352415961263232, 4815492584012832448, 4823609875070311296, 4822894388576332448, 4819704637700896064, 4793116888844077056, 4823253146680873824, 4821048659881089920, 14030085037827512576, 14042722297151539872, 4791912151281739776, 14039205817442027136, 14037391109510543104, 14045098705965703584, 14035482324306170368, 14032226153664657152, 14046126367165035840, 14046920457521751568, 4822133760502083168, 4798067730175451136, 4818312350801927936, 14025910390769230848, 4821145361315738112, 14043463146632464384, 14035299930156616320, 14040285292402275200, 14046877045717181488, 14046664442283222208, 14047049341459729920, 14040261755018405120, 14029336578645687552, 4824013524059117920, 4821290860306103680, 14041683553610992576, 4813162394110489088, 4816020308622307712, 14046992609389370608, 14040658539594748928, 14041993908508617728, 4823545052902757264, 14040570851463978240, 4822324835731300896, 4822746580944419936, 14046767543716330912, 4822287850681802432, 14044769004683313600, 14047514460164226112, 4815405545693814784, 14046842051945763568, 4823758680262007104, 14036989946088182784, 4823767499620493120, 4806629308959177472, 14041081555847939328, 14047332956358413136, 4822329096416309440, 14045311011202963616, 4817493622147959552, 4820852129889496192, 4823910067768544096, 4816022299331604480, 14044604703129190944, 4815653675378373504, 4824039697430039296, 4810814449147564800, 4817492533314167872, 4819097795669798432, 4817726280046190272, 14041705101123566912, 14045969773679644960, 4813751384276521984, 14042605939098632160, 14020928961658515456, 14046287249357044736, 4822820247812969408, 14045758115066664640, 4824073289404049136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4831535567424454664, pinv: 4382457639974474137, mod_data: ModData { n: 1022545813831681, ninv: 1864509616052343418, norm: 14, }, primitive_root: 11, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 4825439846457185120, 4821496375955681152, 14049432074167511120, 14048478640921129008, 14046841195274624976, 4825650894409250288, 14046178618945972768, 14047385253808960784, 4825851319364483808, 14046707542787468928, 14035437132771416064, 14049249919714584256, 14048315649665522912, 4819544071387224864, 14047809862777334032, 4804231751593389056, 4823540658199560512, 14035096759338017024, 14047985492045227712, 14047232511187730096, 14045558067334366240, 4818401787736819520, 4823971754795709104, 4824274440945422448, 4813373805408107648, 14046847133865445168, 4824874467674102608, 14047057175127032928, 14047337512356251696, 4824688535832160864, 14039642814059537600, 4825431061631096736, 4823857135317523216, 14047651134929528208, 4819853611199351008, 4824891664215266576, 14049196726504201936, 14048838363086239424, 14048788033313157344, 4821837116763697312, 4824165132311920512, 14042851180804928544, 4806543476166756352, 4821188583758948480, 4806058251952569088, 14047071222383024288, 14048983310422191728, 4817331328054397120, 4819257789212167040, 4822319399608984352, 14046288430572866432, 4826308677866686368, 4826710067006638368, 14049100323906066576, 4824669008026338704, 4823647945755946512, 4824144516159091040, 4802106136673379328, 14040754280317357760, 14042788466786814368, 4821615795891559008, 14044834037282175840, 14039478854006833984, 14040607596865999552, 4821946028368516800, 14049516732419034976, 14049206857969660736, 14049984964483129792, 4822786634136944320, 14048645380840578640, 4796586952420560896, 14048299641909678272, 14050223579179019984, 4821639862341614496, 4826083448808429712, 4818925895533524288, 14046140310705855360, 4824447739708704416, 14040583634108787136, 4817697548870899712, 14038495319671992576, 14049539081702425216, 4823973861279393648, 14043953473761831872, 14040821937507886080, 14042972836596274880, 4824241469782134688, 4826614002054715008, 14048661006473149200, 4826158942876350080, 4820498697288848960, 14042943144166162848, 4825476814041280064, 14046209373554872448, 14050369711676841760, 4826625113375115072, 14048775627815185280, 14047794119296666112, 4809037424436230912, 4819886308662117120, 14046702230224517120, 4806171070467751680, 4823663048961988048, 4823609660477321120, 14049121204679784768, 14043455999063375008, 4826221803976297536, 14044128325784850656, 14033765383685192832, 14049295679214985392, 14045637752390369472, 4824726587349038368, 4822910890163108864, 4824418996765631024, 4824746760597292320, 14046919827427072720, 14042940658021060192, 14035795643607627648, 14048353366022992208, 14043457251233012064, 14049341231454216304, 14036079412522896384, 4824023015558510672, 14047234394853446736, 14042165854941764096, 14035059051908634624, 4826395138883607632, 4825757721551474000, 14040808625615315456, 14047834766764041376, 4824255872273792688, 4822487547942965568, 4825798908091777600, 14030536133004097024, 14041347918954649600, 14049429496376697168, 4815425678752495744, 14043007954767362368, 14032926333973469696, 4825736866983086112, 14045816627924422912, 14043732880686297984, 4814842852911510720, 14047357888419900320, 4825907827293800144, 14047966526424251616, 14002559716742758400, 4810073521747832960, 14049973814603675072, 4821674598945080928, 4825295768309609568, 14048887066852165264, 4810619265463375616, 14048624081486644272, 4824421793077052992, 4823991882571222832, 14048256545945987456, 4820291280021689888, 4820266633957734976, 4819009480151447744, 4821204518766480448, 4823875594070730128, 14049259478421229360, 14050321028404402480, 4818877658333212640, 14047554331660805296, 14041219495619620928, 4824537814371695376, 14025713186051705344, 14048847933772515792, 14048859218688977104, 14049476186512291040, 4824383929827360064, 4826518874873005312, 4815726028918689536, 14030692357902129408, 4823625139044720240, 4818013809370647232, 14047648467880875952, 4819479411981134208, 14048094514946480224, 14049621633589141200, 4823094328091085056, 4809945138134605824, 4822896877449584544, 14033399590924075392, 4817875473122529984, 4820898691632714112, 4817176120574170560, 14049483272303519520, 4824857280230884176, 4810265091033998592, 14042291333033269344, 14042240775611339872, 4819290206020753504, 14049992373047944896, 4826794530549922064, 14049407313043269264, 4822222138002923616, 4816715619420569088, 14049419955940566608, 14041725160979721536, 14047329107528684720, 4821888646645182112, 4819584455773980768, 4815684254437081728, 4825751281298205024, 14046551727574677632, 4824465785789955200, 14044243325953149408, 14035621024797297152, 14045156568874581088, 4824530800850812304, 14046314914821141760, 4826092114703573360, 4826784285577746032, 14048559484278655232, 14047217799016411136, 14049371450465537136, 14045902624781340736, 14047837948620381584, 14036397915340799616, 4825556903921301504, 14046744415782606864, 14037076939308192256, 14050116905265819696, 14048477057662066992, 4814018216343754368, 4797599443515247616, 14050155978648458432, 4815898157752423296, 14047892865499719536, 14048282980144324816, 14042207184694697088, 14048226518381435872, 4821603726844806304, 14046234806401221952, 4826001184804767344, 14047819008011546704, 4825566132635704752, 14047250970282086272, 14050176659091494576, 4825734802991863312, 14040170659585065088, 14036681382702296576, 4821824713381115200, 4818152594735670016, 14035406496419305344, 14049243037275575216, 4825017005959015552, 4826635783914605664, 4822346645713292704, 4826637544877222064, 4825294442525891200, 4825830785175699776, 14040697121801716672, 14045012117981227424, 4824168735652351216, 4826447266245115904, 14046516602256015040, 4817202642448776768, 14046855072105445872, 4825260965865601232, 14049762559979192336, 14038359549076815424, 4824880816583420592, 4825969418483895200, 4824674280745916160, 4825318513062859184, 14048787506801188032, 4826769947669656320, 14048133072431917552, 4825983939612366240, 14049386051819287024, 4820228311272340480, 14045269817483728608, 14048530851330290112, 4824382435936497936, 14048802284956680592, 14036396827522221568, 4822532016225992416, 4817702104052781376, 4823847534414169648, 4816715516567467456, 4825092875893318368, 4826482831842853136, 4825021622063929360, 14048795651545758320, 14040963313355219712, 14045204371684147424, 4824312270644756224, 4810581102974092672, 4826430318245484096, 4822295706121617952, 4820411158551192608, 14042277403359517824, 4819068179216221920, 4820878151923922016, 14048372605695284080, 4817182474358183616, 14040395635930603584, 14049168165703315216, 14036987055459178880, 4819201072549382112, 4824082106520130544, 4823756490292596112, 4821452835792602080, 4820771256439777472, 14049410599165310288, 14045277100298570528, 14046213307027472864, 4825242206270109456, 4811532625785862016, 14040688091704011904, 4822619394684522816, 4816333038347396416, 14026674975446486016, 4815862890758514624, 4826645760117212544, 4825272946715171968, 4823604178010629040, 14049904196728932320, 14050067685668342848, 4825171982775794432, 4815388921128173312, 4826119520486388272, 4823788409425996112, 4824765239299562864, 4826779432598009200, 4811440425768318720, 14049505734665451152, 14042391975464536320, 14049381343011974656, 14044540453754271008, 14020587942509486080, 14043647104960028576, 4823849829521596512, 4825885184058158208, 4825902361501455152, 14040184349038736832, 14023730280822118400, 4819637203821021024, 4814864937783417536, 14045140967046545856, 4801549417825792512, 4814424904006263232, 4815169646328046464, 4819500496277027232, 14049552317581345632, 14045889270549134048, 4821832716006128320, 14041965506656694592, 4825498982319318720, 4825619054106821248, 14047141004118321648, 4814936855401470336, 14043783962626559936, 4826727388778005168, 14048006119331581104, 14042731692928365120, 4822013985983097728, 4824232106235068720, 14049409117379024480, 14044085783029509056, 4820200493272226336, 4822479442500902368, 14039364370094074368, 14047325203924138560, 4819684284883995424, 4819070679250932864, 4821267478059587904, 14040885711575448960, 4826764026048432480, 4826802182038415312, 4822162150327408512, 4811662723463885056, 4822740194952644512, 4824408842656977472, 14047552556339420432, 4823955575677817328, 14049845523229576432, 14049767743838189616, 14045318914905471712, 4825328220400156112, 4823638354597169440, 14042363969061733312, 4824140736343351344, 14041904554047165312, 4825190543136406064, 4815783965092671680, 14023972928314634240, 14040597923386037056, 4823131374472999840, 14049919093648136768, 4825356348717539792, 4816951159099933120, 4819453906571232064, 14040716287590795584, 14049013900291608288, 14040234476364309888, 4825970269891838448, 4820752838051846368, 4823498853947566016, 14048380975301037776, 4821452588103068352, 4823783301985832816, 14021403150307355648, 14040721939593446144, 14049535717764115056, 14048461964356772480, 14048496183702034480, 4824409224561906000, 14042603297674050528, 4823922282601109504, 4825466993846379920, 4826995751540017216, 4823281069958606464, 14045646770566069088, 4824575750684921408, 14043208150546584640, 4826996588836298656, 4824736778634036528, 14042286746572494432, 4822504839104164672, 14048691040060141952, 14047355978975364080, 4823750966892361088, 14028188694380263936, 4821011994680771936, 14041983186979442624, 4822254982781049984, 14034940666250038656, 14046682469371083456, 14049926134188778384, 4816280370878262144, 4826343908792766976, 4820894682002475104, 14047904237205727536, 4821237398477175776, 14045658287882346240, 4818359231666234496, 4825236691698971904, 14039499859206479104, 4824019573488824800, 14050285875103353168, 4824391398762946432, 4816119493188454144, 14047889610306379936, 14046864442446616384, 14048353843027293696, 4826910037252760192, 14049942324334851408, 4824231023076788032, 4819510038671787040, 14043876694452371232, 14039741973866638400, 14041073622438834048, 4824934762448348416, 4824433818469612496, 4819733937074020672, 14045521682297220576, 14049299785189010448, 14045877844421124160, 4824639572617382464, 4823677039543959424, 14048558464022900544, 14031024396471978240, 4816337874438634048, 14048955707982341856, 4807748437136682752, 14036607901753294336, 4822933451224082656, 4818489078521299776, 14045939638836249152, 14030084009143558400, 14049987984258383040, 4826686622448442816, 4819803611899043200, 4825797068268621248, 14037683166895959936, 4824414103396857488, 14039846689628315264, 4826558905340836752, 4821283912522613184, 4823749785067243552, 4825089353421362096, 14036844074703361024, 14048759031375612400, 4824736654607524592, 4824837390459668688, 14017030017284132864, 14048549363791237888, 14048268963466243728, 14049843957187662208, 4824958833567658384, 4815364328462287552, 4807307617245065472, 4826500897732746976, 4824337483163992400, 4817062577208958464, 14042407853197218208, 4824690927746163664, 14049468599377236944, 4826648924684605888, 14039071815433929856, 14038148806069372672, 14042775386823149952, 14047156478776688304, 14048872969713169920, 4811547568881958784, 14037113358034368256, 14039662166213802240, 14036822908249530368, 4825075158881459616, 4795119593266028544, 14038906582407862336, 14024313017620431360, 4823960575994067824, 4799472508850048000, 4825650290575776624, 14043324890206042848, 4818979306384984544, 4822071500741073088, 14036128351785239808, 4817226027045636416, 4826554358365942144, 4825661727902174672, 14049039392648512656, 14046641398275848672, 4813515345678205824, 4825898830368634704, 14044312294333542464, 4821549216934020128, 4822016692002862816, 14046493545003971936, 4825162770744742384, 4823516311344336816, 4823706597452143360, 4824666357692637984, 4823584262980329520, 14033601008849362816, 4824234970790291648, 4823060903647197888, 4814849777588118208, 14045520557179463424, 14048744670606424576, 4826270678208114976, 4820865186154251296, 4825568802975275728, 14049542671919275456, 14039931685086816576, 4824237336375659472, 14050045806336407600, 14047271232968161536, 4816723896056407936, 4821525035261909440, 14045864470024110560, 14049602534072716656, 4824688150974602448, 14036798330832329728, 4812286073985733760, 14047145630953159328, 4826455677854903968, 14047344046922410432, 14037127073201500928, 14043542973236493600, 14033912162969075968, 14043462748018882752, 14049425767573745872, 4820568386167520096, 14046080505180103552, 14046053370511627456, 4818828357635448640, 4826331097166840720, 4810638366685441664, 14033340269387483264, 14042709212052946880, 14045052978390783936, 14048142430406778768, 14048440192607175008, 14038481930555397056, 14048898918960950736, 14022631639189305344, 14044545110440436864, 4824569540153180560, 14048979119157150160, 4817506697255589888, 14045871076192335648, 14042730057149022304, 4818175592273592128, 4823431183585260864, 4820617230021939968, 14042474368019836736, 14046372771584161120, 14043422801323945280, 14036572240553991040, 14034662342192216576, 4825320004088378192, 4807800418904261376, 4817045316579373888, 14042747936623150944, 4824176106466215408, 4822594936836978976, 4816017344086285312, 4813664948448407040, 4820244204869737280, 4819148758840189280, 4817949881454028032, 14032814218523377920, 4817641178576458880, 14045849068800341888, 14049940644631331408, 4824856006764364368, 4821147618192466304, 14048652779938710752, 4803826622211950080, 14043336844994776640, 4824763929097326560, 14047410002213487888, 4824757238532195120, 14045303433252424320, 14046079823483535680, 14042394042499877408, 14048154907769951792, 14048711639123229024, 14049131229502242896, 4824871085925037328, 4817531397551552256, 14049810863594677696, 14047899945136881504, 14046755647165919936, 14048677382877737856, 4821295906805741312, 4820367788584550400, 14049528022891518848, 14049179816082274736, 4824403309474203616, 4826130448927041328, 14038761107343131904, 4810852209145262720, 14049973225576423312, 4800308232723200000, 14049995619627505456, 4807717568771531520, 4812823248937967616, 14047573210008597280, 4825124177681552320, 4823880704686516480, 14049169339115445472, 14047664367957566576, 4824080487495534656, 4822110916558156832, 4822474728988646976, 4815547369838738880, 4813759360908208384, 4826393960327734496, 14045403110379662624, 14048138448148485488, 4824412996159721328, 4826449173214665440, 4812119531866916480, 14039064264952847040, 4810038100637919872, 4822061851829804160, 4819607045127841696, 4824971342012011152, 14043235008871433312, 14038603410745437248, 14045115613112012192, 4820378306860499520, 14048292795468980528, 4820485536164221152, 14048592981206063104, 4825634304340203024, 4826361706128051776, 4823923018594407984, 4821067687723533920, 14034718645823337600, 4824876054991360080, 4796846518314719232, 4824720487400231264, 14047062858483509152, 4812604756067401856, 4822539066659357664, 4827000063820702464, 4824178633920672992, 4815274196970367872, 4825338915440250384, 4826152124684246416, 14042542906148414752, 14042525956216601504, 14043099611161991840, 14033459074969784064, 14049866209312737680, 14041437704515657408, 4820663341206715872, 4819599997341311584, 4825659499550340080, 14047400607394115056, 14042389168941073760, 14043454830622202304, 14048039578958039504, 14046836207905883184, 4826454662676513088, 14039045173613872256, 14046128589203081152, 4826030772614305824, 4811518011268153728, 14036217924826495872, 4805744518735155968, 4820658237813497440, 14047951338530823264, 14050149103677225536, 4823251641267295616, 14035891587959352960, 14043771124136676768, 14047484707462289248, 14033870594489282432, 14035382387270127744, 14049413597009271872, 4826495797908445728, 14044302384756198208, 4808798022799624960, 4816266262628546880, 14015765324118446080, 14029583277355657216, 14027425222137940992, 4825548741658910240, 4820486782811366880, 14049627269157569264, 4820869070258316704, 14047897776056204224, 14046709688696975808, 4797351224611823616, 14044306594147305216, 14048759603106942224, 4824921994972638576, 4819093160934810880, 4819777150824746400, 4825469984026456576, 4821855056544062752, 14041484337592020352, 14047162457818414288, 4825579489031771392, 14045409921482667776, 14049502986651713216, 14044089508238178592, 4805584847020056064, 14049642162491457408, 14047392605268107136, 14038191608691707712, 14045926630779467008, 4826961446116550480, 4809423666134189568, 4824685277725351312, 4815855588104679680, 14048091258367868496, 4819217259501132800, 14047777463802578288, 14047246937568362048, 4825755712070607680, 14049268546762237712, 4814576355710964800, 4821694409038310496, 4823244017262304928, 14042371362774673792, 4826785512340213488, 4818902671001911904, 14023406777958383616, 14046259886234207488, 4823926147925104976, 14033455468399341696, 14035239372554111104, 4826453350357865728, 4824400787144292592, 14040639694771469440, 14032511588392805376, 14042278402574395232, 4821443001047528800, 14047510164774242608, 14046127177886709856, 14049387924701320544, 14043463601800607616, 4822875730173340832, 4820354706127420448, 4826623659534784112, 14033968932604615680, 4814905870122492800, 4825735847869654800, 4799689029665595392, 4824079747914595696, 4826371673164429840, 14049950732580699312, 4820367999390297472, 4824322495376996208, 4820090362278880064, 14045929780988237152, 4826192249397381312, 14049836059559425216, 4826633796876354400, 4826075003648160720, 14049512940147944032, 4815195885277015680, 4826979736650115232, 4809986930076721536, 4820213035302990176, 4824741945156946816, 4815890841606257984, 14029183012973093120, 14046130537650035744, 4819315693364971840, 14042917069162641728, 14046669144130864608, 4818859157581594752, 14030328471082210304, 14039443063793102016, 4823418770397502672, 4823818180144152976, 4826904007596055936, 14043744198151351840, 14037374062775425408, 14047927914571752736, 4825564456034688016, 4824533421499704352, 4823939785236395632, 14044229703397373568, 4820601716647929536, 4819487496734492640, 4826526329396875328, 14043231179398194304, 14045545737844476352, 14046002242483695232, 14047763197586319872, 4826987405878869296, 4818542575417747072, 14042858460978928384, 4823877262103057472, 4824258821813163520, 14042651024878868800, 4814930319937262784, 4816798607497173760, 4815823823167915264, 14050353905051478832, 14042885595953849248, 4812575329450717184, 4825231872087973152, 4825282376062237888, 14037676278814186368, 14050302740000229488, 14049894648032058400, 14049206713474606080, 14044838246628745984, 14049095836655535552, 14049968214001048720, 14044227582927963840, 14048641082553657024, 14048372273111292080, 14046654014624341216, 14047033100361827488, 4810301788389754624, 4819652107322060800, 14047938053517573664, 4822499302560775072, 14048095407390508864, 4819789371325841152, 14042888958448864768, 14048969430698072048, 4818031726029999040, 14045642808305735936, 4825968564518465424, 4820557431700935392, 14040743629522074304, 4815000782626714240, 4822477092099813184, 4819378807116125952, 14043143846145778880, 4810173887417183104, 14047046126653069616, 14046235874810864352, 4821956453653179552, 4822019943690503392, 14045969616696886304, 14047182795170331712, 4822770793588756544, 4821429285262282240, 14043454524442908992, 4821515647695305184, 4823600111391195872, 4823769809983629952, 4826201393072381712, 4824733559659976928, 14048338761246973504, 14039278764680940096, 4819203263347387328, 4826823705040708560, 4820141583604387872, 14047246367360338608, 14048863302639523280, 14048017404046559984, 4822765405561003424, 4824942651098081520, 4812718003030252416, 4820468236814268768, 4825066985069040096, 4825569512721551296, 4819671786241032416, 14034625309146908032, 4820839568389181696, 4820946277405463424, 14049844745794832672, 14049215085359949776, 4818334344290953472, 14046127869628347680, 14022220936127863808, 4826516177736531936, 4821366808516176352, 14041435382413692480, 14049375929547494288, 4812796398722643072, 4813289227877067008, 14037312721648543616, 14049005237534088528, 4826829034573383392, 4826488458664625472, 4825524396028412144, 14046636513540159136, 14048825164605475824, 4813356299740130048, 14032842616344302592, 4811065878872511616, 4823991091686203536, 14048705018704599376, 14044971868279260320, 14046018082164159200, 4821797347583687968, 14043987263225202752, 4815038065148411200, 14042345223280430080, 14048620122827002736, 14044118514012857152, 14043744435022921536, 14046519768891554176, 4826051844271858176, 14045014223420747008, 14035373638332441856, 14049682757039302432, 4823270303523298624, 4822064180558385920, 14041694855809086400, 14032837796621953792, 4816438443657809024, 4826788103791773728, 4826520238854468256, 14047636733556707136, 4824418530271369424, 4823410202322094352, 4817599598034374592, 4824685115979946816, 14029764788408598528, 14047307215220347104, 14046504293845433952, 14047589664575596832, 14042387774984080256, 14046670580002995936, 14040923813559830912, 4826790217518370672, 14049261678863331216, 4816375768647296896, 14049629842661921056, 14042967395677096960, 14047270587850405472, 4824741100189444192, 14034231755276104064, 14047674892218507360, 4823547538853694384, 4826656806385249680, 4825956739762067568, 14048530764307271344, 14042343636662625280, 14047958383424955792, 4819550859965958208, 4815211313426282112, 14042965360708413728, 14049705793243530208, 14047434928515237408, 4820554446173328736, 14015506114511925248, 4822929228433297792, 4825784103807786064, 14043284597103888192, 14049561312226384544, 4817127930150870208, 4819987335537630112, 14047126856689396352, 14043008935335511456, 4826948320477658480, 14039613373101957440, 4816065657029506880, 4821127159174599904, 14042962080275296832, 14049718837132357280, 4819079995865709152, 14034848005353102976, 4825044032733391648, 4819984866554399808, 14047000303049511808, 4819989828606245024, 4823954289410169840, 4823915094795780000, 4820079626384799488, 4813226839480610944, 4826628316346224960, 14034502223421584896, 14044143276650279584, 14033488023314340992, 4816300966530191872, 4822369313988188896, 4818179196508826944, 4821668373061070112, 14040802742465851264, 4823162495545218240, 4825024222162203008, 4825316907755618096, 14044333239230684544, 4826437049633839248, 4819954104206541056, 4823696242301690800, 14048628076877786176, 14044073929032496960, 4819785834658580928, 4826274314036046864, 14049129466280858640, 4822305249037436608, 4824676915362923760, 14030626858710564608, 14047548513061270800, 4826299696939748048, 14047677687271339952, 4819703657166055296, 4826123106258670656, 4814494561027482496, 14047595719191995952, 4820290370792754336, 14048588448461892176, 4825489440091287104, 14038430452169271744, 4821943257095109056, 4810570234222318464, 4814441036464969472, 4826432144159867488, 14038876040000856320, 14049846460802877824, 4797446831860947968, 4800452802573444096, 14046806877626272304, 14029788929538882560, 4818909271150376640, 14043585412179423072, 4823962447889166624, 4819223493994120800, 14047818317681896848, 4826689597366998160, 4823313439603733984, 4792767879105748992, 4822492540107020128, 4817325418698451328, 4819374804666530144, 4810906165122853248, 14046973755419059312, 14049143398304481392, 4823915832138753360, 14047456354968544192, 14048030057206810080, 14049080069005429664, 4825329629560243824, 14050203466536735376, 14047259869801015264, 4824549576136668736, 4825422072700504176, 4821047988790626240, 4823171540843029376, 14040605886499666944, 14047588690533763920, 14039861601899159488, 14048919388030028032, 4791879807981289472, 4822619776376717504, 4820136989492235136, 14039787137695227712, 14047777870197080944, 4821778475313640544, 4824603659490274960, 4823121015640963456, 14047272632378851264, 14046902723877733024, 4823914248522111904, 4825432797714302368, 14049283862014817024, 4820147655076425536, 4821438503795564000, 14044249101722111936, 4820679207125281248, 4824030319502576704, 14047412760310556736, 14040491766856776448, 14048433310975025184, 14045138227902389472, 14038246844811241280, 14013182530125299712, 14044337679270986784, 14048141994381478032, 4803044374332002304, 14044242565610171424, 14046307199516274432, 14049756400785096416, 4807131973487489792, 4820852463101817696, 4818359712902447616, 4811919784360547968, 14048755303230566480, 14050269981455532288, 14037870852578746112, 4825520135781005072, 4820354070894826464, 4823794715321659936, 4826053468822012288, 14036991397143189376, 14037431300751563776, 4811530836259894528, 4810926535090671872, 4825592620633234592, 4824097521296087616, 14044175780359309856, 4819847400102978464, 4822744404688184192, 14031160185260761856, 14048607097045334736, 14046939316674684512, 4817330339518588544, 4812759831043427200, 14044108570754980960, 4826009000771851584, 14037848495792716544, 4808929004254640896, 14037065678234222336, 14020857437520893952, 4823183312704643264, 14046950564152196320, 4815747721095218432, 14050314493195724672, 4826225363998048992, 4804148171821246464, 4825752542128104880, 14049709949051090320, 14048130094101239232, 4826337035164226016, 14043381932350579328, 14049353777096587344, 4822471464151734112, 4826245182002943600, 14048909659817754336, 14047909261643443568, 4821221176591159136, 4826711140177431440, 4825458692263520400, 14044860238871633888, 4824306477632930864, 4815951350281205440, 4819253086299931456, 4796543367766173696, 4825101563299500896, 4819999581443394560, 4824482264609853632, 4826811345746284752, 4820922701782187168, 14047948790565785904, 4825541011185013104, 4823196259360788480, 4816319632084924800, 14036471294960703104, 4823035655924240736, 14046938119666594320, 14050176578974035424, 4824509524606850720, 4816123365714627456, 14038742311889040320, 14040494386843939392, 4825718956116088128, 4806889039969765376, 4814575420765909248, 14042412615453765280, 4817771483819901376, 4814495640955967104, 4822153577161486336, 14037554026376755456, 4824727050046397712, 14039172958646028096, 4824236915291075472, 4820762957900082368, 14032479336683529472, 14046641404795147008, 14032056089182161664, 14032197948507593216, 14043745007938122784, 4823584857958768352, 4820323913366312576, 14046185783913124096, 14047429041491562448, 14047965095846403456, 4824788802286565696, 14049654991143129808, 4825885452662721184, 14045476205272549504, 4825868815597100208, 4819420769586381760, 4819822403642163808, 4825592746953216032, 4813605056777581184, 4825552316431883088, 14047765912609298496, 4824138522888393536, 14049587860241542400, 14048173277158064800, 4813439619653685376, 4826089665418992304, 4826196899562722496, 4825081416070216240, 14048276227124763248, 14034284957261792896, 14046170815933109184, 4816086607136520064, 4822809563083392288, 4824829074996751072, 4816836911373258240, 4826046162427789520, 4824797222859209648, 14048446240795550400, 4824143743560886000, 14046985642333586352, 14048909038628702448, 4814301446758108160, 14048464017215606000, 4823888234356872880, 4819423383845975136, 14048421304194497808, 4813339900290152960, 4826728691086466832, 14046015903365080224, 4824236855735842112, 4813915471922892032, 14039463645589175680, 14048796532573511456, 14044598060993028992, 14042942765800923520, 4823406627730367792, 4814163796892690560, 4820536026366912064, 14038169298413220224, 14047611918471099792, 4826741809243464448, 14048070145981044512, 14047871351779314624, 4826219963917336112, 14048111882735954848, 14041990737815684544, 14039471523651096960, 4824258170952457072, 4826255987486838784, 4811852247995185152, 4826403842148221728, 14048178215624261616, 4820747532149644672, 14019751516481141760, 4825537450867081456, 4806894111534958080, 4815892556662859392, 14048042338679889920, 14044939536066528608, 4821582547498918976, 14040933604370686272, 14043943305402206560, 14048476690997752864, 4808318502219236352, 14043164964543085440, 4825485388567324352, 4822552672395115712, 4818789949735707136, 14047053024070127328, 4819654097025476480, 4826804190407413760, 4824133763811074336, 4816648722922354560, 4817393400097349440, 4820293062245492736, 14043953091056011168, 14049711376046639744, 4824917227063910096, 14047134730213249296, 14031038240764570368, 14044434224538882496, 4821748476715239456, 4823504041115816768, 14048797153992188864, 14049938008208514528, 14047149066117257024, 4806351249621259520, 14048120193485889952, 4809840470600779776, 4816026615325588672, 4804948647360359424, 14048963088481197328, 14045240901348843712, 4809394648214140672, 14048185385951011568, 14044836711974848896, 14033785658298971776, 14047641065199970416, 14047583799743240976, 14050181407417338816, 4820737802524540896, 14041891759427852032, 14044457651661143168, 14046944166956308032, 14035567746451128832, 4823013155896423264, 4824285675630475616, 4825084525051707024, 14050269478797102064, 14050359236633670192, 14047607623552658144, 4825652509333356176, 4822255951798439744, 4819772822830510464, 14046978867928959424, 14046917968702578544, 4824456049594556144, 4819625950844985440, 4816387432303887232, 4812083553806669312, 14043985391311278336, 14044480740720573472, 4823211887556564096, 14016583140060821504, 4819906212071993536, 14041483172895711616, 4824949774559324464, 4817542567014155712, 4826728159076317840, 4821520786034099808, 14049863634959999008, 14038741117966392192, 14049368136722705808, 14048186632629201536, 4821102470974378752, 14048244569498905552, 14044953601067135968, 4815230950245974336, 14040974555162249472, 14043347516161419936, 14029617310758649600, 14039860776417689856, 4820583943804101024, 14046254775406378272, 4808329137798987520, 4825986483115752928, 14048899265200552800, 4824739304425436480, 14035739421423227392, 14042787038294124992, 4825817632497591232, 14047375320605378368, 4803952415216879616, 14046234405827477696, 14032419552812955392, 4816145077642689280, 4826889270591175808, 4825060462423522144, 4826592297688266352, 4823356264334252880, 4824288247621825760, 14047511999047995296, 14045946291583477984, 4824903689575812384, 4824798081038212240, 4821186856290193856, 14049981337315338560, 4827000395756173584, 14043124773056072032, 14046037551195392000, 4813111672367320576, 14045120941965299232, 14048604636422214576, 14042648769702025984, 14046716642684931328, 14046095853466408064, 4822941483311167904, 4824259468642938848, 4823504475960459856, 14045849879349392864, 4825771480509140128, 14044990403509249792, 14049556253943900592, 14037445488276187904, 14044578198019793216, 14044387310190291936, 14046298048276456480, 14042569721787555168, 14050380414401739792, 4820817181633632192, 4821654779093982656, 14050022148261812144, 4824553590009302496, 4824513668487248208, 14045922401824014816, 4825145125914348832, 4826955639517804704, 14050088439872854224, 4826342717404428928, 4823504375151870944, 14046905484156924320, 14038246643554791232, 4825640588322413216, 4817440889399166080, 4826619704933710928, 4819828544130119360, 14047911018518934480, 4823476427886154576, 4826741533517054528, 4823819962658517024, 4823017985615223680, 14007972156868919296, 4817915087741585024, 14038019531852635264, 14049971652863745680, 4826732531823049632, 4806702662171230208, 4800280155724620800, 14048582412558968976, 14050176775204780512, 14038841642857498240, 4821522603856178848, 4812159375519389056, 4817483175532139840, 4826757774988687920, 14046042218686540704, 4811907985366866048, 14048710865644571664, 14045554630980844512, 14033776592126946176, 14042478820511500608, 4819032866156458016, 4816951991993230912, 14049836654866279920, 4825002966912610992, 4824350437780540432, 14042658649619208064, 4816387912109924288, 4822249872411261728, 14048749082715245136, 14048910350591238768, 4821075825689468704, 4814156455305786112, 4820352753242367296, 4824817474869839648, 4823766221737785424, 4821413945503262336, 4824018909257097568, 14044327407090908000, 4824092044126163104, 14047932041556017456, 4823955314026203472, 4821899966424712256, 4824560176261311760, 4819556483839416992, 4823582584189814944, 14048396706455320944, 14042462281834194880, 4821415590976539072, 4818875693049439744, 14048022164592874640, 4816359248765248960, 14048553219247178768, 4824993443519122608, 14047470201004715360, 4814725086017628800, 14048362820662586752, 4824201274119435136, 4817525552815527040, 4826816321960095920, 4822495284665335648, 4823495312536349984, 4823423546369904976, 14049804948284949120, 14045794597291580128, 4825363654137113088, 4824304627970683680, 14045307964267453984, 14042616500024715200, 14048545974147001024, 4826701935269041600, 4816097250299011072, 4825040314247223536, 14042546208692535264, 4820181521171473504, 14046979231743893376, 4824757982060070368, 4823510128064686176, 14043456597105802400, 14048145368947174560, 14047831280027726976, 4826306259893735392, 14037392716565903872, 4820227960395513600, 4822837955691074560, 4823682107330982832, 14048021331878239312, 4822613793903993248, 4824468923427139856, 14046763139382734080, 14046570501544411040, 14043831027226196576, 14041488578648610560, 14046438164875921312, 14046807851315383712, 14037131730701250176, 4826859771957013680, 14041861951313989248, 14048969939287891072, 14044464260514826944, 4815747147179601600, 4807228720428141824, 4825335964692005440, 14038579359248175808, 4824296091476457520, 4823371145629464512, 4811974800141394176, 4824954027672691616, 14049017521573291776, 14033804773590299648, 14049900982598159968, 14047900234773537568, 14048053924107199824, 4807025578591968512, 14044049452599187040, 4822675330746200832, 4817849261617340352, 4825166319042070832, 4818034409673005952, 14049230956802255232, 4820342335007337504, 4815288980825441728, 14050202921602986352, 14044226444113633344, 14046710569192130400, 4822403151516937632, 14047111266617014688, 14045311161844417696, 4824437209140276208, 4824294536233436048, 4826583464122238128, 14048343277757924144, 4812534467063176960, 4811070970808184448, 4820676808825991520, 4815520262510235072, 14041953380187747200, 4824659542538461296, 4825924445854376832, 4821369459846907488, 14049788119375923168, 14043389625569876832, 4816097146744870912, 4817819963198776448, 14038935813634969088, 14050314137765697152, 4810630835809058304, 14044439962977664832, 4822692796627273056, 14037916695401171776, 4821948988798858880, 14047530027596012448, 4821148769758957888, 4812741877952696704, 4826121857522812784, 14042955203190647488, 14043838241508323168, 4826455829917334000, 14044506214913952544, 4817242318425768448, 14046962336677935776, 14049646546102863056, 14038373574308968192, 14049638247713734416, 4806787291405901824, 4823593115746579872, 4819093118386918592, 4822994777755530688, 4809961387020574848, 4823085436466622880, 4812713748662732800, 14049334583722684176, 4822929660385233088, 4815025488364019264, 4825057688321364368, 4821779996738790208, 14045221209337665344, 4825587530221902864, 4818024601764440448, 4824400704834961504, 14048429024546680736, 14037590158187846784, 14048308392828760432, 4816861049524085632, 4816208878815724864, 4803995892228722688, 4825194003812114880, 4823661329109171312, 14049740215485385808, 4824223353761470816, 4819437827420016320, 14034491112708651776, 4820503272556359488, 4825896176477528608, 4814739028080879104, 4823916997167553776, 4826486557849964880, 14028417292665296896, 14041312909684077952, 4820599057763908032, 4819070306181481504, 4823509856779361776, 4823612348510249152, 14044557735548507104, 4825357238952569728, 14049782571897932992, 14048448058465315408, 4817196628885106816, 4826706291810242016, 14034389231462510208, 4823972713464442240, 14049548100495544176, 14043928937181569344, 4820947218881948864, 4824682919731118800, 4823960403920997568, 4821872811296834048, 14047081796615753200, 14047203450685982704, 14038660813630139648, 4826883210122778064, 14048734369853168240, 4821246693342109888, 4824113443298676208, 14049327646808716464, 4827008645489881552, 14050130863787317440, 4819894905687163648, 4818824874114218688, 4826126527355560960, 4817814506978647104, 4822235975726277856, 4825387855685014848, 4825404711346732368, 14047662240244513168, 4820583721379047552, 14044202145464581888, 14028086285990765568, 14043445865816615936, 14045417496689893440, 14032225424463567104, 14047795867073309328, 14048239301865053136, 4809511958832710912, 4821639854725086880, 14048210935271976672, 4826207876711999248, 4823932418190385200, 14045322633841252448, 14048744025555198304, 14004519280049324032, 14047006101882084560, 14048309591520782144, 4826370485642349904, 4823464484389071584, 4825633686374016880, 4819818250586263232, 14029662975750372608, 4823645398383868448, 14044140273208182848, 14050346319433422224, 4823780705985484768, 4824448774291990656, 4826387294426337008, 4824904733477846800, 4826257345629324144, 4823568242425851808, 14047494598402896576, 14049556025970338160, 14045346765518864064, 4816882271685640128, 4812928322042141952, 4822202457637178464, 4822743282355661280, 14048446989852183648, 4824136861647769232, 14034110703522126464, 14037890672735795264, 14049229296017695104, 4825494913203540496, 4822287670857857344, 4817896458487387200, 4825984135807891488, 14044795731299322368, 4826869491530128944, 14047557388804465792, 14045273610727535008, 14044622858232728928, 4817795697797931776, 4813807398642846848, 14049836151809199248, 4824575904371739184, 14045484026610000512, 4808120005931792640, 4825049572854158608, 4807416235454870272, 14039181824665880192, 14042122446237690304, 4826825440926239904, 4819386461792489376, 4825454054599997536, 4824175878193000432, 14049041100006051040, 14046256726845991712, 4826228254255950912, 14043589627205975744, 14032719653987641600, 4825055616313143648, 14042462378922748416, 4825679120283502160, 14048327036877893648, 4824380379149475152, 4825324485563110224, 14047991840588314464, 14049340628751140944, 14050386581483220384, 14049022429583085872, 14033312282245391360, 14046732985129364944, 4812652715911210240, 4816213878965598720, 14040038480545065472, 14025160878632648704, 4826963780137039648, 14047522265028865632, 4820349660205531136, 14036883772189656960, 14044152749069925696, 4825552828696468320, 14048563823690479024, 14030455256348985600, 4825985257305659520, 14049119559190809664, 4824407092655869120, 4826876864970481472, 4819589842567840480, 14043844513007503360, 14047701361816516112, 14038673881964376448, 4818578847743258624, 4825009922789398752, 4794647900895479808, 4826584262023826784, 4825475835751686336, 4818935633117503968, 14046311634240345824, 4816243175557617408, 14047316128610743712, 14050124867208011776, 4808382482357242368, 4824642767332485792, 14046690852699346880, 14042258888921612928, 14042913818238120992, 4823601825046207232, 4819795939960280384, 14043305642111563680, 4825428231513926416, 4820120878080386592, 14047037798896737696, 4823516157604645888, 4815747829737092992, 4826252426656470000, 4819926446552226976, 14040010428707993920, 14043435723798294848, 14043233969202285504, 4824445073012859360, 14045006988632565856, 4820560834806834240, 4815294002732771072, 14042501223771940000, 4821592541054222560, 14045554554677133472, 4826372287928391536, 14048744121856970672, 14043538274880890784, 14045509255011748448, 4812244562852267520, 14049968039044416848, 4826915182655836496, 4819351863690680736, 14046443947125096064, 4823646985388566560, 4825102256140644624, 14048823737051732032, 14049714216147792000, 14048500942435690432, 14046967218525159712, 14034345696757952640, 14040537946971417472, 4825102698915087280, 4825010718277323440, 14040220089583963840, 14038953125165337472, 14050052470812233552, 14033724626394242432, 14040529519055901376, 4807618178158558464, 14048034691616895360, 4824206041696383136, 14045748618996727968, 14048176028304207888, 4817774454980068352, 4819022413307113536, 14048038073258886528, 4824255453644224464, 4819334078957093184, 4822953738851166784, 4819777161106546016, 4824371788628917008, 4821180978528803232, 4818210681043392704, 14050220024392281264, 4814460917429043584, 14048782837587198768, 14044897144280841088, 14034285676187728000, 4822114357786113792, 14047222359279277696, 4803356161066532352, 14047390369256095616, 4824669783340554528, 4823807521836723872, 4821428959640002464, 14024500817583929344, 14041572821642777536, 4820334721759161184, 4815093687146802176, 14049192922549600848, 4826107246492551200, 14038255593217494720, 14048070915991946496, 14037017753525203072, 14049162615217054880, 14040261855872021120, 4819358922875158464, 4803459961727256064, 4819041052901324384, 14049829626863457904, 14048302278328593088, 14036184300521872512, 4810111472734145536, 4815629102568766976, 14049725704914389040, 14048698355980350736, 14046907874083368928, 14044219613299633120, 4826843843341551344, 4825814879252869680, 14050387031982471616, 14046611041701457568, 4825304392467587744, 4825482345109604528, 14050360798251040944, 14046781266396278960, 14039512020855226752, 14050166359293773648, 14033601036272941440, 14045892173451118368, 4810107325648705280, 4819596456235106848, 14034676051888983040, 4825538221735414288, 4820736741307720384, 4816406278538255232, 4825098644895795552, 4815890859717271168, 14047493601964200880, 14047612289691821872, 4823232864194843616, 14040337312209482048, 14047094853312119584, 14047603550125293728, 14047395006479348256, 14049004644282541696, 4819829006639404512, 4826127954952750512, 4820053235145574784, 4821752284220280800, 4822190597677158880, 4825318946518790880, 14047594724273745616, 14050009994324352304, 4820650890674854240, 14039451415979393216, 14047260395530473568, 14047652180770077440, 4824098156969192480, 4823382309099936000, 14035860561104472064, 14039390791156409280, 4796408937667940352, 4810481476953535616, 14047990478854565408, 4826515146318441680, 4805488446506747136, 14043705800095967296, 14046172787990548864, 14037755041527788160, 14021610300325761024, 14043147634800268928, 14041663058837872704, 14041544739256108480, 14047161686811858560, 4825906789220059360, 4824196507355004752, 14048415935474726752, 14042348734584953472, 14049548813523729184, 4819393917570848512, 4825765607257631520, 14045723735397976896, 4812499529122388608, 14047746179937980096, 4824643863796155792, 14048372722326881152, 14033904761883055488, 14049729029885848944, 4819540472962949664, 4826951853175949824, 4825769893550953648, 14049775327798027744, 4824672908039304864, 14042159892508817920, 14049038105367161232, 14048055525241910688, 4821612229112130048, 4818789576123961280, 14048422127579856528, 4822296188468900832, 4819087040934395136, 14042220494334781632, 4825411306427650624, 14042923719704688832, 14044761843608653856, 14040944860831471936, 14048964086407954528, 4824104588097178208, 14035923090899508096, 14030524012802870784, 14047422351335699472, 4823015253974865408, 14040383510463157888, 14047275360713146336, 14047391090409943232, 14047850381142283008, 14039516883028265152, 14006415774645075968, 14048499678039701200, 14036545505289196672, 14048847478039742336, 4826623829027218368, 14046837267005826096, 4818915438175823680, 14037399254739363712, 4816033507981116864, 4820385877433056832, 14047615650387250288, 4807038628806562304, 14044422482325045664, 14047812237176520288, 14048509833824251840, 14042212732525123008, 4825198427790427104, 4825624362522840928, 4815008762717817984, 14047036551828177136, 14050222615451067152, 14040214265193336640, 14032230174190772480, 14044050054574931136, 14039995569462228480, 14042357303480415328, 14032273916463947776, 14044167584954213920, 4823621736779969056, 14049200019094823072, 4826076196071654448, 4802918797468423680, 14045735987758439104, 14047247353592620288, 4824778785395283888, 14049983280216469728, 4822128190067187072, 14049367367560314064, 14037517315011367936, 14041349824715694720, 14047878350251701536, 4823891494123471168, 14040075337064462848, 14046868729889458672, 14041731896359393856, 4820078566836918560, 4820902115747632640, 14048826124561595408, 4824227353872573392, 4800915695091262976, 4826636136481301248, 4814982297116827136, 4821828722561273344, 4820498837584286336, 14042939358816585056, 14045418282475930496, 4819640142905624704, 14033731889993414016, 4821479698086380768, 4819397642454309344, 14041335567837243648, 14036140589121085312, 4816870774372371968, 14044494726856080512, 4824703986083544784, 4826965952713317280, 14047924308892749968, 4824118392422061456, 4823746317588446384, 14049046926733949296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4831465198680277000, pinv: 4382500666457514068, mod_data: ModData { n: 1013749720809473, ninv: 2040746090583899817, norm: 14, }, primitive_root: 3, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 4817247727980125568, 4825321074127147056, 14045897366133639168, 4799076302293404672, 4815096634960094144, 14032413498573211392, 14048131086875926720, 4824961258136783936, 14048647426631102048, 14033844839309557120, 4812376598533030016, 14040476274729997696, 14049317458526386944, 14047091506787708368, 4820111890967091360, 14045519652690835840, 4825423312945966352, 14050221761703734416, 14049879988542651136, 14045653392598027936, 4809658051387331072, 4823047852989701184, 14043897352608058944, 14048856151523561904, 4815848502957585856, 4826892684983434640, 14042869236451698656, 14049880623794938528, 4819578146339783840, 14044812389203359168, 14049149527341699872, 4817426255157415616, 4810616878939192704, 14040675184820247616, 14043338056002125888, 4825988602241020304, 14043675625404483392, 14046484360952658048, 4823071036591053984, 4823785102892147392, 4815640938452832064, 14040906557683203392, 14049442167416609552, 14050082520665835008, 4825529645800553248, 14045697111833594848, 4809701732190784000, 14046740669301075680, 4818491503596189184, 4819271739338795968, 4814994381110367936, 4814287932015059328, 4826893216458965200, 14049374347974003856, 14049690523986300064, 14046993172634227424, 14049922908470693056, 14038060216251590720, 4818989473290089376, 14047074031023484528, 14046432866756713568, 14035276392248976000, 4817754412243740800, 14037883319745406720, 4802212562804460544, 4821270173053818208, 14039683621379689216, 4825703143847413680, 14046988017117655168, 14048612349944228592, 14030193643659148800, 14048133864531518976, 4816534743448840960, 14032202866638982912, 14044953737445956608, 4826590184334372560, 14046844280201201664, 4820640033542428512, 4816841558156658560, 4800610735082861568, 14041087126981829504, 14049013824293805328, 4820326027993933472, 14046814625996616816, 14048695259430989968, 14043991882890555584, 4825301109404366816, 4811252942205037440, 4825607720404157760, 14047707233972303376, 4818518089915074432, 14038543403062469888, 14049111493964486560, 4822421055549660992, 4825303102579638048, 4820051247094122240, 4815452854279961728, 14044032486787756480, 14043357989756589312, 4822365832989823456, 14027286583426888704, 4812051851201686400, 4821556755010824928, 14040830369786274240, 14046607602693685888, 14041542586621442816, 4817363364845815424, 4824077197219980240, 14035164600336721024, 14049117324932605856, 4805496587839898112, 14043070558021474592, 14042393142787556800, 14047267672452546016, 14050203426318129744, 14050205212826655856, 14042011226601735872, 4820790042538903392, 4821450440634288032, 4798803893457392640, 14047500319381373104, 14031666317021128192, 14044037260676175872, 14047435325672699520, 4824401055608835136, 14047229578779307424, 14047290655869536768, 4817775182462038080, 4817839968247378880, 4826727467825576032, 4825705393107090640, 4819245725442869728, 4816732980152952768, 4821480803481381536, 14046033895611066784, 14047517011185894016, 4821776036603368256, 14047933236563027712, 4826435711911637664, 4820501196403473088, 14042855259192733728, 4825294802508505696, 4811783740398346112, 14043393108172016608, 4812227194344915968, 14048478971209265328, 4819052380929893888, 14048267554488027248, 4823831305139698784, 14048560878999062144, 14048888262160795248, 4813401423847082496, 4822321984566678432, 4825411103948254160, 14049956069210542544, 4822373800028262240, 4820785044898098240, 14042436161317528416, 14050022381485030240, 4824885920824324416, 4826172787133621248, 4820012297158944896, 14036247539392002688, 4825378076858837040, 14043132369698897088, 14044103387171144960, 14024863020143131136, 4825118156218632576, 4810485575720084864, 14033248211791048960, 14049396061044568080, 4810490341997276672, 14047827549995917376, 4825153696758014448, 14048783455109537632, 4799927289216800768, 14045711037293712192, 4824825183013633920, 14041375434691079424, 14041984292342412864, 4820252426055550848, 4826067712725732960, 14048296872887875408, 14041865134026575104, 14044281813490105088, 14037713456342445312, 14049614924845659728, 14048019028511673904, 4821983803495383872, 4823335156631948352, 14036381263410124160, 4817445037286628352, 4824728085145249360, 4812457641990374400, 4825867696990924448, 14050313017841934816, 14050075819775351616, 4816908024084271744, 14047918857752990416, 4825073243497182864, 4821468600371419488, 4825669557015477856, 4825895375065998720, 4826543597171310096, 4814685298716716416, 14047254363350515392, 4819059368480581600, 14043156558178590848, 14049586759268805728, 14047820557986704576, 4820007423222845440, 4826784660194864688, 14039838824737512512, 4809922061111647616, 4820717299139551520, 4816346758052272064, 14030193050466259712, 4807027060315917824, 4797114810679913472, 14049272329023560496, 4823737395222962384, 14043780618518719968, 4826169169264256672, 14049051289844378496, 4824688892948045152, 4819002335038054432, 14046913438012915344, 4825618611410595584, 14038807439231778624, 4821166297978331968, 14044189910563672480, 14045689696735212672, 4810926285687961216, 4826046957226221808, 14046299921412173152, 14043932173396777856, 4819358751019051776, 14033774489891646848, 14045459624458070784, 14049340655944428272, 4819933974381387840, 14041514089948438272, 14048879830235182480, 14043357388614516960, 14046139160351580096, 14043257177500582912, 4814571168449543360, 14038054265897331072, 14050162231718555440, 14043855283120998880, 4816605869219511936, 4821692244655636832, 14045908279964528896, 4824161211664133248, 14044623744673721792, 4818625522523472512, 14049803851566399776, 14048702450340064400, 4824709352340310160, 14048042223671935040, 4822146589031120512, 4817227680101645440, 4826484027378866800, 4815383370009139648, 4824430616525852928, 4816297551031623232, 4826293191961438432, 4826121693898336832, 14040272768988886336, 4822794872035475392, 4819178925861825216, 14040930387960073408, 14043845036815974816, 14048858663024925776, 4824219575099298224, 4812708167864436224, 4824781804083932400, 4823386089894994848, 14046476056355188672, 4816710127987636928, 4825052195407440784, 14046789934236262240, 14045283020417087904, 4818339673445823872, 14046931085037218848, 4814570516628108096, 4821597740470276128, 14045715297449567456, 14046799343966158592, 14044526979886664096, 4822590163478787456, 14048944124198852624, 14048037612365859680, 4825374552605309616, 4825883494317744400, 14043651043260695072, 4825783811623427840, 14002529360831528960, 4820998670401813920, 4824011924454919584, 4825940018090815264, 14018822878973458432, 14049672696347445328, 14034702410133325952, 4821354039653970848, 4824919630999725216, 14048260826578930672, 14049322901801867808, 14025396975639941120, 4820421926977429472, 4824952101725667344, 4826069920802110816, 4826400069372329104, 4810293334654057984, 4824339524613870944, 4825557554763124432, 14037987054156467520, 14046015563539831232, 14047519151376571600, 4821542814897532352, 14025023093008722432, 4824573049926996496, 14047889467680928480, 4826447026563549616, 4810243419264615808, 4826676334017085168, 14049138981758873424, 14045309689852550368, 4826257931627573744, 4815882363200098880, 4815766465308388480, 4809996137606160512, 4819536572687478112, 14045095257580854912, 14046899717161879360, 4816660067459389248, 14048423701644560960, 14034053766605905536, 4824840291761964848, 4826893092015778512, 14047033290823828240, 14044854007769184640, 4824595704843934688, 4824739528485642208, 14048090265605705024, 14046972269284891488, 4822287088818254016, 14036292660791469568, 14047479066706692960, 4826059055465154688, 4805217788935621120, 14039929529930651712, 14045579995840724736, 4821028449249191264, 14048633041888341040, 14048700923782786224, 4817082879672406464, 14049705608751836720, 4821150750313838112, 14047206191228607392, 14042506440118707200, 14047361221958137088, 4819863867688203744, 4811068521210525312, 4824873851817057552, 4822760170925511296, 4801420263170261504, 4823434161378211280, 4797541161619253248, 4823831900861184672, 4793531812516716544, 14050238926341491824, 14040930320701782336, 14047933410996576016, 4819683150271984544, 14045730136551340704, 4810504454175822208, 14047009818833638752, 14047812851283968912, 4825514204256313680, 4819815371168489216, 14028149300567108608, 14048821856356385328, 4821709813957582912, 4826925035543150864, 4824385933560766112, 14042551645153713152, 14046872573205029424, 4806908526872391168, 14040632295050160640, 4826201876143785680, 4824573620087514544, 14049336286930974160, 4806435030947848448, 14050262510935517536, 14047994999201748720, 4810549870652156672, 14044225502951681280, 4823826953806031424, 4824563562880265056, 14037408746295225216, 14048793781541068768, 14047919632595832688, 4821063592540214048, 4819464693928865344, 4823851066292438960, 14038077009473914624, 4815870078126786944, 4820413949281085856, 14048381398248761168, 14047781361523048256, 14048190403104487280, 14035827290296305024, 4825722656047968256, 4825583003686548592, 4822593431742379648, 4823839111780243408, 14026908170648473088, 4807646277057426432, 14047352483697346400, 14048773854632410080, 4825821991769392912, 4824531381501430688, 14044876376391119968, 4810786286085069056, 4823404794866865632, 4818768938731229760, 14049154589141956912, 14046397336735781824, 14038617669938231616, 4824914636947133632, 4826290250455565344, 4817664509448726144, 4826261276281810416, 14038877300792047744, 14045113414164871296, 14049639085809418528, 14042971026722054240, 14032740906178474496, 4821185458492525344, 14036705879821549440, 14035044639995235584, 14049022278692248592, 14046483307483724096, 14043661628638383328, 4818093367173774656, 14040476733919508224, 14049163111699653744, 14045437876906763712, 14045758151386091168, 4821480813655307392, 4825952211794413888, 4793951600858667008, 14035129932671057792, 14049333757598101280, 14048205968065322928, 14039245339415826880, 4826204962667300560, 4815414079499956864, 14042490622445243904, 14045769223322912288, 14048586673093989264, 14047014276973146000, 4823580973391122832, 14037466350456584576, 14049359445535476096, 14047297078540720224, 4811787419445252352, 14028900113309792768, 4824240337277109472, 4816547074395133824, 14037397287508535296, 14045110014875789248, 4826123424112271440, 4797350601556633600, 14041518906197837696, 4820529605923954368, 4825190814279963824, 4815321990733636032, 4826582632475960368, 14043393699986467616, 4823916116940856544, 14050195792884740016, 14031645050948277760, 4826077430167600016, 4815711447509679744, 4826901187515376976, 14047568802398895456, 4818884524874976288, 14040187179418917504, 14041510136669915840, 4822851777368962080, 14049179291689597776, 4809054163488595712, 14049511936722004368, 14049443848248981968, 4821883686839722848, 4822317592557665024, 4820933286182567648, 14042539615341990432, 14049565438113034208, 4826254480637490656, 14043008279789330592, 4820030287370943456, 4818802015336235136, 14049840906431819424, 4826038665313220208, 4824662433783319904, 14044142809064929056, 14046752340706113632, 14049876585425099744, 4826229668489658816, 14043255517149582144, 4819107838797533856, 4819694943498257568, 14049909971315187712, 14043187220776154112, 4820311334255641088, 4825258002643439184, 14050128850472564560, 14041209073460566848, 4810976488444294784, 4823618207383722784, 14048630895509271424, 4823539148065537776, 14050135555417231456, 14040655362754024704, 14033616761445810176, 14041691844414895104, 14050320916628430080, 14049124774173115328, 14035319571415079040, 14048699395981034384, 14049095948128942752, 14048926419471587696, 14050058752937606432, 14046831644390647920, 4821470706560000544, 4818363553368584448, 14026630451652196864, 14049834904153395200, 4824860412181453760, 14045689841766635040, 4825182705554027904, 14047798498244471328, 4824012117900795600, 4822478178905397024, 4826096103588816336, 14047580743331772720, 4825430160754486112, 4823127884763617472, 14033694608093543680, 14035586030643123328, 14047842109729376384, 14048167281019064144, 14050154990887546592, 4824138704351804944, 4817143288096894272, 14048061818425130736, 4817706371691658624, 14046746823486324464, 14044375444772357376, 4824309274559565072, 4824320249358117344, 14042689886707067424, 14043454515401690496, 14039087968893311552, 4825935819913731360, 4824383397909951616, 4814484324684005952, 4819577087919466080, 14048101058097173760, 4824927411552890048, 4805959722732647424, 4826271371045042400, 4818626670550594816, 14043408062671562592, 4814560135319369472, 14048920724651993280, 14050024079913756720, 4816655759203087936, 4825471561409238096, 4826915875022509872, 14050231928991914832, 4823638122275032832, 14038554271987794368, 4819084626709039296, 4820472390486184320, 14044838543423845792, 14047719534458722944, 4816085638089357568, 14045723399422283968, 4824395432876887040, 4817922828175261504, 4824684725355074528, 4809975698137597952, 4825779005969581360, 4824652933432589568, 14043666893341873600, 4825612640208968912, 14047975420344355920, 4786978507628683264, 14040769739506090752, 14048409043299729488, 14044744986252845696, 14047344966096101408, 4811165537628197760, 4822941956264106304, 4816057076874422976, 14033242976542914048, 14049829326051514384, 14048051758011764304, 14034260906215013376, 14050152093276452384, 14045160038234589600, 14048266368775294928, 4816206936817654592, 4815101186579795904, 4825968563325836848, 4824364409306105104, 4825636546095512576, 14046769672401285904, 14031918399171531264, 4825550189494056336, 4814541607317456960, 14033491541048930816, 14045690057850890656, 4802767042748937216, 14048371390733981824, 14046825329767057184, 4824818656724774976, 14033443567766374016, 14049598424820232416, 14049030248131398944, 14046979659025601136, 4812934853586468224, 14037745419383400000, 14047798955405701712, 14048412153231304256, 4826678622688850352, 14049679056020007984, 4826803449031923648, 14048484583406910928, 4814511303219655040, 4815222835682892672, 14047061295177712032, 4823995697094804432, 14042463937266084608, 14047067789412636224, 14044508290484253920, 14050203866494847296, 14048621081002088288, 4821689750421510496, 4825366472969600496, 14049786833126483360, 14021432429700867072, 14047400305681501312, 14047157483025862688, 14035891889080145792, 14048451975820597408, 4823003925825723840, 4822941707106765632, 4822066021741098784, 14044738465294511136, 4816756103666551424, 4819850210025292480, 14047095445248234768, 14049241641059216144, 14048398067929671136, 14048767550551961056, 14047496300270598944, 4811909507216142848, 4799024801365312512, 4826595031267162320, 4824390859054002656, 14048132904256476288, 4818233267543254016, 14049006817536756064, 14049372407728530272, 4815425732848367680, 4825892109393936400, 4821747396259684096, 4819118424667024608, 4796462607974899712, 14037123605610355072, 14048727823331434608, 14044917453734940288, 14030191905886627840, 4809432075117755136, 4825131942972153488, 4825949344106449872, 4806619522554018560, 4823615112182119344, 14043569243837980064, 14038669094821695424, 4825237033959089440, 14045908771484399584, 4823892701164094496, 14044134670781049056, 14040025907226767552, 4805328444848555008, 4825933992639767168, 14047650787185673904, 4818839670387821120, 14044121155032277152, 14049234577508221456, 4816425340173759872, 14049865421537271520, 4822530421945224160, 14042275633722909216, 4815269864310197760, 4815507000795249536, 4819318177621888704, 4826366625421524512, 4824341714701900800, 14049786711066844432, 14038838971763903872, 14050208519389623696, 4825987249978294288, 14046310523685566720, 14050166585083853856, 14044236536628223456, 14041566084122202112, 14044601176253674752, 14045746114518815776, 14047825871604318384, 14045748509616889600, 4824896069042970960, 4815681103907160832, 14039019360194180608, 14043136526094787008, 14049522165432313280, 14044824767302418464, 4820259762042386464, 14034391132653060864, 4819806861728229056, 4815177723391939200, 4824821687299382752, 14034167427550307712, 14027994832328501760, 4819742118653682368, 4826284060157550496, 14049797621315469216, 14045514310149370976, 4820778765529905504, 14049494127544297824, 4813861410196148480, 4826104822685119136, 4817066621055353152, 14034373091663632768, 4811287658855612544, 14049008343322368784, 14048243208946989824, 14049597113988013040, 14043502262025973440, 4823878020634670256, 4820679423514715584, 4823018892214500128, 4816831146529527104, 14041620601628831104, 14042294240788787200, 14039695798833516928, 14048889493018925584, 14044502654623655904, 4814334260551099264, 14048654833481089376, 4815694363615094848, 14047421979063561392, 4819199469837470880, 14044845553357749568, 4815758790417902592, 4815462067064319040, 14045518664255117120, 14048522976973641936, 4817175035022535680, 4810338678673849856, 14046542040971371616, 4824240308981853584, 4816471078617809728, 4823724605489689216, 14045694238483946144, 14046520713912716192, 4823500299169456160, 4812083763592010496, 4823985822057411856, 4816634651574984576, 4823740590247787808, 4824282134247508400, 4816062785382170752, 4825619746344117184, 4823912139976035344, 14048675424662902672, 14042939885674523424, 4821624402847589344, 14049007550489459664, 14046331685242379104, 4822554852884839008, 14049747681362846944, 4813184206679021312, 14047066134311707472, 4820820259085746016, 4815662347878129920, 4820551052513217824, 14043124730426127648, 4815101220031491264, 4819455526624935936, 14049898863557837104, 4807289677020162816, 4805829356415959808, 14047965674250709040, 14040136117962901824, 4815507543518433856, 4825623386341106672, 4815856688992445120, 14038510960212613632, 14043680886784916320, 14049441336926428016, 14042561819160995616, 14033765482838049152, 14048213742507053664, 14042047508359348544, 14047645253136802272, 4818581100918459136, 4822934330491954144, 4825598065719643936, 14038482410683762944, 14048316668686995968, 14043947716148251968, 4824311298492920976, 14048369931211422016, 14042847951216838336, 4826917181362397344, 4821522437948429088, 14021150816372140032, 4821316945228902368, 14049800850834786800, 4818877886408567968, 4804036933624215552, 4813660962439297024, 14039061955985228736, 14042481528347465728, 4815343921417232640, 4813033908711305088, 4823190010914186592, 4813501654668972544, 14049764259323347632, 4825686801023153440, 4824749651623456288, 4826366151590533200, 14042863130472813952, 4817721990984510976, 4824173051796002288, 14028800575884833280, 14024609263881438208, 14037220253630006912, 14048412866819204320, 14042581745818108992, 4822689549024319456, 4820419339235596160, 4824421530321601024, 4825859610368592688, 14039572945181449536, 4820987246690320576, 4825344265006339776, 4819546325047122432, 4825291774233448832, 14047242210352665808, 14046828194192830960, 4820792259458170752, 14019627585624745984, 14049431601287193440, 14035491022620441600, 14020769037385361408, 14048543181998637088, 4813475114576069888, 14048550552911199440, 14039821272519929792, 14047100360468475840, 14024219802742226944, 4821782981289337792, 14045308445804968032, 14044906799280268192, 14043295173858398688, 14031885951784964352, 14045478486265331968, 4825468511369567984, 14046006499878247968, 4824878292398498576, 4825382953520901808, 14039814746421640512, 14035990051551264896, 4824216047668151856, 4821021150233557952, 4815175965809316992, 4824711755678594208, 14042131662160587904, 14046790590764246464, 14048569552876582624, 4821624953849427712, 4814043525519353600, 14050203280581311344, 4823731604342113312, 4824911616728419408, 4820196491582223680, 4810429532919018880, 4822190182100799584, 4826772259511108048, 4803763847718480896, 4817631166608410944, 4826590278193928272, 14043580606556829056, 14048824762071397424, 14044912323819590688, 4825868292679894592, 4825154300159856256, 14050110175022115824, 14047859417880894304, 4820026358652404704, 4817237118153420160, 4819146540813001088, 14040394777020196416, 4826111566665222832, 4817920400597215744, 14049512809596988368, 4822477386213783456, 4822645937828777792, 14050064663568410512, 4822210632246529472, 4824324264052326640, 14038518332673861632, 14049598044163080432, 14035673663585692288, 14047689305557722992, 14033388469789937792, 14039809171386309120, 14043949727104152128, 4822972836137302304, 4810855576822244096, 4826539129364821808, 4824603841237380032, 4821864584250289568, 14048632679247674976, 14036793094333882624, 14047925592039309328, 4824653457492522864, 4825871936971540048, 14048576465561437424, 14024610100978245120, 4810540742116280320, 4823956380359175584, 4822707087601131808, 4802620402126849536, 14046334207775196224, 4821174982928947264, 4802846403564153344, 14049266538475637568, 4808850643825442048, 14050301257407021936, 14040586408748265472, 14049830648169289968, 4826379937068506960, 4818957934909462400, 4814622985871031040, 4820613361651953344, 14046256360993203648, 4826805614007695728, 14041151319512331072, 4823681476165661888, 14049859238794401376, 14048648296448771008, 4821879794722405472, 4820719939125484928, 14041881127082587008, 14042945285866221792, 14039500415128635328, 4817090972240461760, 14044696434556812704, 14046422206168833792, 4826323303096491440, 4825375922828193376, 4818840990549136704, 4823964574461564896, 4814890768699297280, 14036611279488544768, 4826083103752923728, 14042812927173664352, 14047413986230291600, 4805564067941945088, 4817514956410754560, 4824975970523952800, 14050231891602647232, 14049961206181387168, 14050212595411043296, 14048346110030177360, 4824614032947703488, 14036986207363709440, 14041157670583370560, 14049778515500089904, 14047105661380568240, 14038444686944273216, 14047824257011488592, 14046777986997232848, 14049569146145233312, 4822011828346373824, 14046419121918514592, 14047299613483835792, 14048261979949853904, 4822114390072989248, 14043007440337998400, 4820385573103708352, 4802755167629208576, 14048029743312987840, 4824804698925307216, 4824517644622516896, 4804312500609511936, 14044804324760050816, 14050299319780785728, 4818812611163396160, 4818914735497844896, 14037923899594549952, 4806914803854025728, 4823855671493782080, 4824938766814820240, 14045047802481543776, 4823710904618536656, 4801151897131472896, 4810471032896192640, 14042919441463922272, 4824645279463541616, 14048545031687348672, 4821442781824600160, 14039726724744515904, 4820640678625198560, 14042575444748416480, 4823878546802610352, 14044068862098677088, 14034354528286481792, 14047476926720607920, 14032178582844491008, 14047930339899884480, 14047509864096854752, 4826678430448873088, 4822516940025661856, 14049453956792296128, 14049838119601362976, 4826481272856355680, 4826318640303867536, 4825506368441949616, 4825022007861316832, 4820921832299512672, 14045818337179549152, 4818098033005847040, 14036432480280821376, 14050171878416033632, 14050125404423452240, 4811625315005181056, 4824386137318990272, 14045173072756503840, 14031906694195139584, 4825700730707832592, 4814924687069149568, 4816802454571175488, 4821160121534093280, 4822511029048724928, 4825409474142888656, 4825473252844903200, 14047292370171146368, 14037665394332372992, 14043948280129620896, 4819258095941803392, 14045074045605102752, 4816794549039724288, 14043829607258225216, 14048471408774628816, 4826652500105106112, 4826354426784644208, 14040110278804448960, 4824639931259022176, 14037315726303117952, 14050048266696721680, 4819851025585314816, 14046009066308168608, 4823434993616185376, 4825753558535047104, 4822327051868229792, 4802970576429953536, 14047026830261247296, 14049189304802691520, 14049093584275153904, 4819902555315921824, 4826456219583485024, 14049409329959976112, 14046086467962991872, 4797803988727835648, 14047427519949842544, 14048639211188112624, 14045266517437051616, 14042731419909285728, 4816663150541298816, 4822777613850569344, 4826698796270417712, 14048133399859796896, 4816414454972982144, 14031211772545969920, 14036930816947345920, 14048850140412403200, 14042547861214274400, 4815720106637119872, 4824280276900405488, 14050145557281474448, 4824367741353982032, 4818762423935229696, 4806825133483597824, 14038868528432410240, 4817906767256899520, 14046328665710018912, 14035459749581470976, 4826466041866350480, 4822385112634071040, 14030560733044676864, 4823871054553724064, 4816085873843739200, 14037983327044601856, 14048177183659682464, 14048614095689390784, 4825442662302350640, 14040483019737266944, 4822963667763986144, 14034731786143349248, 4824912513434329856, 14042254108134298976, 14048311090745317472, 4813240083022987264, 4826575419615642368, 14049446992884145280, 14050101263253739568, 14044393036622020864, 14038583217634284864, 14048213535983753808, 4823729731080926256, 4814400493933272000, 14047660495382054880, 14035377540454069504, 4809650856007455488, 4817123923399032640, 4821535002754424736, 4826690193755012320, 4814507285350845888, 14050331062732985824, 4826546141758795952, 4826793168025620320, 14049897789369177344, 4824986586630702592, 14039826350773989696, 14041597744631778496, 4820687216782492704, 4826174412867434064, 4822124395090062432, 14039110365246141504, 4826809959601279312, 4824398176685925536, 4824180217737185504, 14036616628866637440, 14044234317904744960, 4819022025410504640, 4820390089579366720, 4818759743132623552, 14047881189077442368, 14047324877210731840, 4815665847331630528, 4824071446394561808, 4823931062690657200, 14047779299900247696, 14043538470067181056, 14046658134796199136, 4826505722051825136, 14043893067006883552, 14047168985010279008, 4823266219662441824, 4824964677937329472, 4816413032973682496, 14042801962553008192, 4812909484450620416, 14030721988088970496, 4806186986602184448, 14047427347158047056, 4819331045524401792, 4826948408941322176, 4824100628303842912, 4826937203088584752, 14041859089079198336, 14043403242206972320, 4822499151623263680, 14045278435963308480, 14042743180850591136, 4817457096824119296, 14031655228992721920, 14039065715210283136, 14045263630049835520, 4815316882086869760, 4822325555224290016, 4819292073990938592, 14046012602259221856, 14040348696823431168, 4812703759350432384, 14047284798945988720, 4813318780878870144, 4819927281196159360, 14045166110170720864, 4807315067395886336, 4824415473787439376, 4821477474301857600, 14046062684528029600, 14045792485273857984, 4824820070469760400, 14050008418968197360, 4814431323810466816, 14037242051725248640, 14039792178429578368, 14046534595444825344, 14050327269550633424, 14038710286172470976, 4816689841131331584, 14045582315906886464, 4805689689836821504, 14039895835775547328, 4825430874036856624, 4811105933231247232, 4810304558110137984, 4824219036519864976, 14042871459590589792, 4812295649960950272, 14046398301748287072, 14046729200965126752, 14045086009291187264, 4814592710686625984, 4826499199371484496, 14042456195845784192, 14043782362564128320, 14046538000328054592, 14044957119342174400, 14038747155968993536, 14038089157257823552, 4822192525314914560, 14038173977685434048, 4825908726109267280, 4818955311322269248, 14049177326111980144, 4811641936083464576, 4820403222966988960, 4823429509854849936, 14046506076265233408, 4809647396425148160, 14047396951276662496, 4825721596193774000, 4825271106397595824, 14045185689561125536, 14032131274278046464, 14034259451901156864, 14049410332045906096, 4815458437517500800, 4826216665503370176, 4826057797324400272, 14044742488404534240, 14045881049265113120, 14046714628993528544, 4820739042443125248, 14031124069933872896, 4819091616929653408, 14045802672477544640, 14042565149325177248, 4815853371272416768, 14036472405094239232, 14047595727699691520, 4815583161355561024, 4824668870202229280, 14049576532217676288, 4819584553504868288, 14049832133891394048, 14046744458085234832, 4826959249228020144, 4826419644405293504, 4824790826334228048, 4826741738923454336, 14047770551390614992, 4817928088000460544, 4820417684139858464, 4826779216732479488, 14048610546891668128, 4826658347749369424, 14045703293186572448, 4823800417434260752, 14038359543956871296, 14049399791614362000, 14045161464364385600, 14044283900328685440, 4821098404986123488, 4821591689417088256, 14049310532663755584, 4826550543477429872, 14039268201603397056, 14046035221918146784, 14047109469419852432, 14039921568895164608, 14043114517720362016, 14048104634279366112, 4826721395303155680, 4815748957255838272, 14045561875698613280, 14039865165698559104, 14040499865021454016, 4823540176588596608, 14042958006809962304, 14043784542557953248, 14033626412027598720, 14049083773360983952, 4823925773472677552, 14047599591385616288, 4819818191127520032, 4821005279758539104, 4821729544138992672, 4826806165639067136, 4824191090524116368, 4809889998738795008, 14044903948787625440, 14032314074474503936, 14045082214915465344, 14046874855807370336, 4819130127576333696, 4815314312382352576, 4824827397931913968, 4820006662479595776, 14043343613480873024, 4813709130292190592, 14041186794177400448, 14047225905084627488, 14040160034003550848, 4819345984403310016, 14046940334722481072, 14037147952713442048, 14049248859633135584, 14049592861044562176, 14046948466181513808, 14034485791480281600, 14043828365458618240, 4823653520617894016, 4815977720741612288, 14049472440275706752, 14016927522388590592, 14048143890579627312, 14043531116254385280, 14036741312203048320, 14049340686131019440, 14048298100268450752, 4822524323174652768, 14049623756928336576, 4825353722969032112, 4826238407930097936, 4810134574992762496, 14025008228204036608, 14045344398672473952, 4801239008936496128, 14039424172869117888, 4823050422979333056, 4809333033203437312, 4825977946368591760, 4817647886340551872, 14042526567082607136, 14044071085684323584, 4819942239172214784, 14047988716290887280, 4813665758315836928, 4822473289705901856, 14036590519625924096, 4821475674926317056, 4812275257145741952, 14046940670853183936, 14041056289975149888, 4820979076768268320, 4821277445435551072, 14038212966596109696, 14043670554936683712, 4824843372559980432, 14047851622576791600, 14042554910194468224, 4826426587794629072, 14045471588977557632, 4819809082358957824, 4823537787401180944, 14048787871363009440, 14043485195716361440, 14050169507038767408, 14015563508529203200, 4810907430930699904, 4817690189083001984, 14043731529721203040, 4813740448502300288, 14045504917971409184, 4823724864256285120, 4819702667795472064, 4819113474981210208, 14041470889409578624, 14046061472608016320, 4826180033562468080, 4808695882335891712, 14045607038789187136, 4820833771722894880, 4824624489003467392, 14047464721468051072, 4825756304856139184, 14035361360545765888, 4820320048909808224, 4814903707711663744, 14043641807356974400, 14047596103714766608, 14048308796984851952, 4823599795472242000, 4825802073788910032, 14047912793425508880, 14040285522013028864, 14041830881993127040, 4824183292120291152, 4823573551243175008, 4826205950630512080, 4826110827002683824, 4821242033139421856, 14046595489967649024, 14046739193208183968, 14047643596190989248, 14044291972541684064, 4825907996605884912, 4824142005641012096, 4823946050461684416, 14043158685662281984, 14047774044448959104, 14049388812257621824, 4819419990613361440, 4822764514783642912, 4819657173591701696, 4819217837594722176, 14040460477505672000, 4823973258504315664, 14043374741689165664, 4821282242964747776, 4823799306074397616, 14046936828426049680, 4821870868572990208, 14050181882516785232, 14047714736943783520, 4801189891334238720, 4823669923153445056, 14038779706521375552, 14011724012760666112, 14043133033429311456, 4825448895436383520, 14030681777952812032, 14046303604562837696, 4823674596948371952, 4818477128188028288, 14043554174717082496, 4826719173625740080, 14048868851668976752, 14046067626884145056, 4815744371828726720, 14039482495414675968, 14043611891754084672, 4825280466981079408, 4825325697870563424, 4797889082578248704, 14029968121472800768, 14037877367918907968, 4826344598558717008, 4826287233065469232, 4821517119455963744, 14042700711639103328, 14043224446664263936, 14040023591716085952, 4819638586368484736, 14046773166104972912, 14036557916447469184, 14048580532509234256, 14048782163996708864, 4825866189477949680, 4806479525456668928, 4824639020910807056, 4824727552510192064, 14037090994808603904, 14046193470301857504, 4825362055723210880, 4813839296816154112, 4810757570570752256, 14045944309298065344, 14050123291995155120, 14048087995480347632, 14039194283985143616, 14036456245704149248, 14049568704188914112, 4826890451140417472, 14049137183358473552, 4824009969348381936, 4824658336934616096, 4825014840655641232, 14038446790400409024, 14048292818172862864, 14049483891062560016, 14048881951936602816, 4825439233560778032, 14045741073164180032, 4823508094722707584, 4818939132062635904, 4801839018533815808, 14050158950402119872, 14037852181763395328, 14044975830208267744, 4799562953612472320, 14032198474991196416, 14048769762474074432, 4825925540746191152, 14043826615226574240, 14037788219577848192, 4821679672579468960, 4823412204567093584, 14042844801014694144, 4824908230413536080, 4821237909489727040, 4823741029165099792, 4820451874095959040, 14046994755965290032, 14042882028746882912, 14048599596335834800, 4820848393900347296, 14033683658742444544, 14048119267795480960, 4825626937940377104, 14033247092982311808, 14045094672442789024, 4825424570497252272, 4822625571632936096, 14049846876382433872, 4819756326969954368, 14048589339926688272, 4824733792226706368, 4817435680015633216, 14034068072994805120, 4813425517930099200, 4825467456567002672, 14029417442193019648, 14036127128759831424, 14038222524000804608, 14037954555900257536, 4824678865942379808, 14038162264942015552, 14047059466415571344, 4808507988300786176, 14047379236945366720, 4824811852524353984, 4825962833071723072, 14043780554457397696, 4822089103969874656, 4825553895462155408, 14047847253606307264, 4813198280742542976, 4806281969197665024, 14050047802891852176, 14050044672452234528, 14048685310196268192, 14041845629847243648, 14042909401919375040, 14047009485653365264, 4811930836955190656, 14036232868650257024, 4820312497040000256, 14046845953074549168, 14039037345199055488, 4826948064122195376, 4819352333468647040, 4825532842426705056, 4814740447995174912, 4823135385403874304, 14048861480097149504, 14037685768899205760, 14046792983934469728, 4825251501912806304, 14049949959941555008, 14047015735900433344, 14047775801851290240, 4823769351458372208, 4821734858053597312, 4824112191616721760, 14049644203490906256, 14044659766388767808, 14040285202816623936, 14039555910774034496, 4795269880864606208, 14047782673931289248, 14034299402360590080, 14040734064196177856, 4818127639049477568, 14029571732868275456, 14043957490970947680, 4814268799672511360, 14039802785517223360, 4811316200358008704, 4804697987078153728, 14048574842010763216, 14038428763584605760, 14048410284206602032, 4803652145280393216, 4812070588564075520, 4826819746102603808, 4824782154337212160, 14046915438265674896, 14050110971093036128, 14047977440341485056, 4826007721019444528, 4821288512102514944, 4824966357532074928, 4799554366440880128, 4817087393414771968, 4825910302229906000, 14047364116365411488, 4825931848481007712, 4820196379780346592, 14040837484181335104, 14045249196849348896, 14031550817935136768, 14033830564203800960, 4821581662032552512, 14046522807449830432, 14041071366655870976, 4824494867117277312, 4825964145785616336, 14040627439725476864, 4825150616996436560, 14036811163683064576, 4819742155660645216, 14049560784928292000, 14046142716521787392, 14049165830367134864, 4804268100711416320, 14049029777049091744, 14048061304451135600, 14045977088088006208, 14049354119559599840, 14048700462223856352, 4819328453895107232, 4810016650773992448, 14042076993880854528, 4822666318759786848, 4824157062810021920, 4818074328918507328, 14044136367018160864, 14048102642163619664, 14049364593594341632, 4824384636622035248, 4825525204670665920, 14048571388829208160, 4825630694036067680, 4781602868934770688, 4816705570011381120, 14039487888907608000, 4823824959782903616, 14046378137120881248, 4826287749556244864, 14020249323286068224, 4825343030790815568, 4812977226661632128, 14048313768339534192, 4825763233476029456, 4798567689904268288, 4825926956838313264, 4825557832701644064, 14034486574935069952, 4825875637790215840, 4802967726807395840, 14044236065860212832, 14049296903521964912, 4819661500929950912, 14047034740043047664, 14033582588293634688, 14049279682039536096, 14035314929688738176, 4808924784577974016, 4824127989476453872, 4821108251331829280, 4824086529359302560, 4823874788038901968, 4815779500299794432, 14047859315038723088, 4826694264288990512, 4826508450846926400, 14050081463863713744, 4819596585376210912, 4826588269179974256, 14042134436867156224, 14028721364846511104, 4822494940425982336, 4819016011950519008, 4808065936599183360, 4821088347734886016, 14046837107321043024, 14049488663081340112, 14049770814093768800, 14043856530070793376, 14047418558191558000, 4825731355264696368, 14037330966336571264, 14047339261970925648, 14044508102413389408, 14047377461334258336, 14048866529485113552, 4822735036807800832, 14047825754760376384, 4825100869502078240, 14021632233654950912, 4811711937731716992, 4823519138679137088, 14050260469037443536, 14048050032868952064, 14038453007250838016, 14049969897280517680, 14045028052625692000, 4826925310446028640, 4820593196368871488, 14038400997552674496, 4816834426523102400, 4821101677950620352, 4817380245898972544, 14043719992269401632, 4819613368858676992, 4825739745506537440, 14047034600635341008, 4791185688169639936, 4823567157551617472, 4825405059998762496, 4808683623717294336, 4826819031055544832, 14044400931839100512, 4812269819130522496, 14049619972031732336, 14046060365758934880, 14048829357910777488, 14039942286399539712, 14049217736751488032, 4825019749012772960, 14046481301877367712, 4809755820681807360, 14034931753381590144, 4820623931121564736, 4824977818136784320, 14043903134420377632, 4814610827820452160, 4812024989837711360, 14044842678283248480, 14049710692705613904, 4811623510677114240, 4820858475068412800, 4818652668250115008, 4825467603666672128, 14049296665541506048, 14040843436138507136, 14039794059207799936, 14049447146463822816, 4820382369956742112, 4820629838718541120, 14046206083871117696, 4821310291094453600, 4820392991419503392, 14048942569461123408, 14016876797060233216, 14048651390415477456, 14039274293743808384, 14011226921604186112, 4805022918510459904, 14049444451553260256, 4826271924849156928, 4819558993038724384, 4825612176276985296, 4817172745039958976, 14031710083534521088, 4825215892169349760, 14048589175132542160, 14045609652487719808, 4820294449069408544, 14043945640553982848, 4815814847435082240, 4821053469099567648, 14041209371022388480, 4822246834760564256, 14049131127272228128, 4806580903063107328, 4823675747324566080, 4825754762546058944, 14041389070809651456, 4814151173954179584, 14046311006627619872, 4824742871550435952, 14043403762418688032, 4817442215958204608, 14048452020987022256, 14048083251126236112, 14047789106465549472, 4825118519925331968, 14045985869796732480, 4806338785680196096, 14049860396272606448, 4824992526356272960, 4810300319471518976, 4811846211442415872, 4824922953257709200, 14045493501841980864, 14039844980945745344, 14041996272697490816, 4821801317070200352, 14049371652385225328, 4819481722947731232, 4825913950314967024, 4804157024224937472, 14037166276036356480, 14036290982871222400, 4825743400327333440, 14048852253472926112, 4821440144854897984, 14033754280946242944, 4816627956302891328, 14038608876587441152, 14049934931933749632, 4826332914797029792, 4820454979232198528, 14040391891247570880, 14045036698586386720, 14045981682928912640, 14049732951170840832, 4825341256578527808, 14047079871842308080, 4820372931725386720, 4819996848224670176, 4824878349717131328, 14042907893200628448, 14042325612592508256, 14049780534290595072, 4825569995644470336, 14028251182685343232, 4820739364643074400, 14030008662815248896, 4802921735795429888, 14042695433088040928, 14047336377220835936, 14047344489686119776, 4822589092573212128, 4818857219782288960, 14047754867792374656, 14047050134487578768, 4825780315750226624, 4817413901576596864, 14047256223096132576, 14048539161216325744, 14039105851251281408, 4826762629996954736, 14049214055512534144, 4821732831230411680, 14047912734441563248, 14047729054116542864, 14029575474804608512, 14046160937765504096, 4813033628318880384, 14049205924693891648, 14049054588582980672, 14039702812641552256, 14038881886775874752, 14047122305293384496, 4824307385378216704, 14036971194039520384, 14041166166604219584, 4821294545064671200, 4821235713695939968, 4821584140063203712, 14050041792424639904, 14046726149986308928, 14049650439069122176, 14040926824655945984, 14049670756987411152, 14049094159229408368, 14045991127544591680, 14050072842447325440, 4823303132068986880, 4814824043338737664, 14047706742967928160, 4819712948692548960, 4824068427540981664, 14045927148042741312, 14037638282930654592, 4819290210038685312, 14047515600221722704, 14048498828390954448, 4818865422356400352, 14021816576989010944, 4825236157255052880, 14036407210164043776, 4824163677193185648, 4822605170417242080, 4805944635898422016, 14045438646090817408, 4826259382309007680, 14048998173569764288, 4825989353064943248, 4826403958670544784, 4822452853008918688, 14037337428208347136, 14044013034419674592, 14043136324289841792, 4821540350940488224, 14031918041872049664, 4816168519761424320, 4814404645281789312, 14048635715316806784, 4826702309336811328, 4822333786360623776, 14040833841760326528, 4820541293564453696, 14047530675431387280, 4814272839122453120, 4822624134567601536, 4803362015905946112, 14041787737373813376, 4826533385285333104, 4825524782678921120, 4815620834722150144, 4825199305415704128, 14049012846271227504, 4817164476807641920, 14044957405400082784, 14047309613699346336, 14044054326412418144, 4817570512876238720, 14044253700519634048, 4824381525990644704, 4798086108912438272, 4819867128032419680, 14042250538756632608, 4824901122443871072, 4814490478832659136, 14049540765266276032, 14041179593912429184, 14042313229836733472, 14047211594023816256, 14050213186065067504, 14044286070512332096, 14035691182974036480, 4825284505319701104, 14044085722086261408, 14043597567539006560, 4817403911024083904, 4820284432111798336, 14043329331356165024, 4816644506959309120, 14038349973868458880, 14038109515839231680, 14029706865694825472, 4816142263581370048, 4823461323901894624, 4817851841953979328, 14045302135694605824, 14034541951408060544, 4822868116947773120, 14046932086423087984, 14044042994029073728, 14050232477255837520, 4824132224690131760, 4810307163224214400, 4825991895482074992, 4810613745463803264, 14042372932696761120, 14046754476403833216, 14041544320346888768, 14049954068094901760, 14034920533801847808, 4822730554387418848, 14046005213975127584, 14041988650538038720, 4820754630688166656, 4822078668495877440, 14046813384168253808, 14027568759679188992, 4815292706762136448, 14039472939035111232, 4824873505574911952, 4825851644463274000, 14050183574814181344, 4821450232022766048, 14047763178436700624, 4823406727004291728, 14035947178632160384, 4825060952979661792, 4818172395009685760, 14044890897904312960, 14039828885739508288, 4801625667033952768, 4809707871339315200, 14047037091871758576, 14049724886169234352, 14045857263744979264, 14046568553060396160, 14047482683942887824, 4823533464616027008, 14048608119480333440, 14039688484120061760, 14044675344318986592, 4825834429329575264, 4824686440876648272, 14025076799742054400, 4822753550810898176, 4821810185452530240, 4823615469977353872, 4824409015872223216, 14043936778888232512, 14043444080472609728, 14041108678828827712, 14048197215196928432, 14047205196063837360, 14047021970143933168, 4821920784109661600, 14049281981729604256, 14038437896084173824, 4825822516895912000, 14048774195667936544, 4821856141862019360, 4820114299063921792, 4824003949400487408, 14048825701361332496, 4818996249356312800, 4807468211705052672, 4822969887678456480, 14049004818151757120, 4825243034325856896, 4806110113346621184, 14046847826494862720, 14050259454522843088, 4821492900901991840, 4818587239210906496, 4818477893547100352, 14043421070573427616, 4826813199526290160, 4819536773944629312, 14043172806022311648, 4823546528938830160, 4812513254292338304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, SerializedFFTContext { p: 4830304114401345544, pinv: 4383336415042637786, mod_data: ModData { n: 868614185943041, ninv: 5463972295250649786, norm: 14, }, primitive_root: 3, w2tab_depth: 12, w2tab_backing: [ 4607182418800017408, 14043228097021372032, 14042817191572437888, 4819605159994420960, 14047581432524294064, 14039677153516493120, 14021517279837736960, 4825573147916255904, 14046786866629089872, 4816556504985579904, 14045007839975801248, 4823493081183302560, 4823374360624130144, 14049115856735280752, 4814783368078661824, 14045776367532642240, 4813211216664688640, 14046748403814652160, 14048094306135921008, 4816074495325307968, 14025445256807130112, 4822275123098533952, 4822868403043080448, 4825057915767726816, 4824538351066130512, 14043575823342944992, 4819890865056798624, 4809740873623140352, 4824063588250253728, 4825643869443244592, 14032476193136987136, 4819041622153057952, 4823616243278662176, 4816789000370097408, 14045168516972838368, 4824936663882930448, 4804025334237775872, 4824592636802917712, 4821173042409316736, 14042455943764399904, 4824842605659959680, 14044205851848637536, 4823238844129275008, 14040622713825906048, 14045683995220758720, 14047016110888916192, 4820629377494216416, 14029496107202945536, 4818946574080300160, 4825164588638135296, 4807959773326895616, 4806684889484666880, 14044015744520577696, 14045043195219040512, 14037661998141788800, 14048280430169695664, 4818794394705152512, 4823710638713947296, 4815006634046066688, 4823556240445652400, 4801268250072522752, 4821934618660915520, 14040665625652734784, 14045782609231479744, 14048153043798963424, 14043913606556118208, 14045467300185766208, 14043491892675332384, 4815197558347393920, 4823846501176797312, 4814629072152215872, 14042741063698376800, 4817701856292165952, 14044266561572250784, 14039905706471689984, 4818416290211374592, 14046433847459287552, 4811752856996228480, 14043016220096694912, 14048030876028483648, 4822271558355174080, 4824998052596069552, 14046734170965334592, 4825204217636478800, 14020170227317134336, 14048158682205633344, 14048851174006661152, 14047486398249945088, 4823541227391590320, 4819293698107807648, 4819813913348754496, 4822633609117653856, 14046334987985762496, 14031010408771188992, 14030348505737732352, 4823056625361965216, 4823852187578458432, 14047649528334422384, 14039795666187369920, 4825317899076089200, 4824648989411968688, 4812366575593819392, 14039306853856624448, 14049038433022781488, 4820117641493807648, 4824724090423447680, 14047953256333565552, 14045813264857351904, 4825770006041219312, 4825716442757008160, 14041182826615153216, 4818543307551362176, 4812153361844840448, 14048304395677791632, 4823389970041179648, 14044605781322472896, 4824311899833575120, 14045021054794832480, 14048485350653332448, 4824248837739626208, 4823956668219443744, 4806453406743994112, 14042561300008624960, 4807478167973515264, 14039233389488045632, 4824023082963240960, 4824356469014786384, 14040455366948864064, 4811146009991142400, 14048492574812532144, 14044248268865570272, 4818762803725290496, 14047578387515440864, 14046743480560656320, 14048937241972521648, 4809601641300267520, 14039857620376310208, 4810889622697800448, 4823032225851786848, 4807771494236538880, 4817151130329423360, 14039494299158070912, 4821014657694789088, 4819372361948962240, 14034567216733372416, 4823696913086053200, 14044751232279002848, 14023125857922617344, 14048595210380632080, 4808325146790618880, 14045819608409311680, 4816873565206425216, 14043977785984785440, 14047532055007916272, 14048573190700393872, 4819831787784499520, 4821336011224334592, 14047400630617533888, 14048140469986330928, 4823887202767065424, 14046789542532691216, 4821211000139485632, 14042511090656306400, 14044463033323023872, 14035697884481155328, 4815537213924490368, 4817883194768016640, 4817291324728961600, 14045375626186159904, 14039322302281897216, 14042597358834456224, 14048581247628822832, 14042468013007756192, 14047530682838137584, 4822749486898855136, 14036942136986220928, 4818872741954901568, 14039558937777904448, 14047246767204121344, 14048353810966509456, 14044278130680061952, 14047082403861123088, 4823879166754666080, 14048830676703197936, 4824467442917944976, 4818252656652572672, 14047490588578878576, 4825397574725751152, 4801587996619713024, 14040301569897250688, 14045464350015452192, 4822493008984130720, 14048257471581994576, 14043386344636854048, 4819684406345089440, 4825421962233155376, 14044853963976721792, 14048418775057315296, 4796356120043623424, 4818928717414739136, 14041846000285873664, 4825443561341982240, 14048125546774998560, 4823399690524872896, 14048423220730846976, 14044449649622759392, 14048815104229701616, 14039817011373274944, 14046136611741309600, 14048456080134091872, 14044902860034504352, 4825657928293665296, 4811544117288883456, 14042002652392637184, 4820184220383988032, 14037488626801430784, 14040692634491958592, 4824966814558508048, 14017294735675809792, 4817025807106292352, 4822350897607845696, 4821416249275903584, 4816988467499206144, 4816591084442674112, 4824915733173046192, 4824345130832153824, 14039472746644277824, 14047703966491578752, 4808735245956530176, 14048048521386073408, 4822616820716423328, 4823711842643187824, 4823680176880773600, 4823969249593708336, 4785975436417843200, 4822052261069128544, 14044032827683610912, 4821123266422297152, 4819573562239676992, 14045300722060315936, 14037932071484928000, 14047150856875119600, 14017796322560208896, 14048886515267072768, 4823937141761900880, 4816525263002487232, 4821560040537881312, 14043049127940811008, 14045109143434532224, 4823254216694120000, 14039481553174771968, 14040290700967531712, 4822566376907020800, 4822695861706298912, 14046952990065715280, 4824513378017517168, 4824823435977420960, 4818951160076784256, 14042295278648503968, 4825190818327628432, 14042287724691899456, 4825496108321101056, 14047102573233849856, 14047868361374624688, 14045170022524073504, 14047837248355976288, 14043496329717280160, 4820043614202620544, 14044277656781778240, 4825274243410493920, 14048717589150544544, 14038410788865076736, 14035816807981539968, 14046795909796069280, 14018170533872201728, 14045544571148311296, 14048362076129690528, 14042230008467320448, 4824254051598430384, 4824749629501762048, 14043224935777164192, 4821818949915751424, 14036157627346449152, 14047502583610411760, 4818694112881786752, 14048710150381433600, 4824556054338182736, 14047056328729011936, 14028224915517056512, 4824798578828433680, 14045824593035869376, 14038485642051598784, 4803438157391490048, 14047521899047352176, 4809565254022689536, 4809462367543568384, 14047083115694135440, 4812469832573374720, 14047835160068902704, 4818774500081596992, 14045373419636137728, 14046823325959267088, 4825440105679591968, 4821405120788440096, 14048912332811238736, 14040587886319056128, 4821951430529851808, 4820723733550290944, 14048955995979799152, 4819410070494934848, 4817705066446278720, 4823932032405782320, 14047336587541093152, 14044323616133786432, 14040655733887880128, 4823412699245564992, 14042443200543240192, 14046635720139267328, 4809345389930984192, 4816936625687693440, 4815644120315787136, 14040009288647017088, 4823331664349444224, 14042906320792794656, 14038407256768144896, 14044605720100835264, 14046068016489800192, 14041957149422180992, 14047924659096534528, 14044262261262093440, 14012689275923214336, 4815948114216399424, 14035209197836205568, 14044737985059552224, 4824128229217487888, 4823374042255367008, 4821548916339568544, 14035688220421668864, 4821590559915433184, 4818567241480520512, 4819805682681621600, 4818345885301512384, 4824341147448967168, 4823405898452287600, 14029487420349151488, 14040093542562044992, 14047015892723834144, 4814686549252682880, 14047362048569403008, 4815317326327131968, 4824165113650089680, 4824434014823559808, 4811194322361416448, 4824980264473546320, 14048344334685303808, 14020802325539778560, 14042152634613383680, 4825758940138348240, 4817526706204524544, 4821186510476286976, 14038404272613930368, 14038004583880895424, 14048454621355116064, 14047367841231139680, 14046806755773781024, 14048138183264354176, 14048589155742149376, 14047429612013606432, 14029157834045246208, 14048766466314769104, 4823631879534589840, 4815999987879628992, 4820163772323651776, 14048563721887823792, 4815139124790407296, 4817619384968446656, 4824314914129774240, 4822014268429311008, 4824295806396779296, 14048710604396895984, 14047365797250896416, 4816833727037317056, 14038887232791438592, 14041247402057501440, 4818292974470206976, 4825253778847974128, 4821983807267931392, 4823878213511816368, 14037546185492343936, 4820030849238970624, 4804459468026718720, 14041750227165653440, 14039576697340134016, 4819161529531549600, 4824745178681213248, 4819701239283249344, 14047754633764038336, 4814327162678704896, 14048530731728601728, 4821912622719414624, 4808167531754461696, 14045728385546240832, 14044053520441863808, 14047434719592489840, 14037401128502595584, 14046861241151263424, 14022208777514068992, 14041959922282851584, 14037758751625253440, 14043450847621283552, 4818393804998841344, 4820085613654887744, 4814364981542683776, 4819656246768450944, 14048747044915088944, 14027608620531751424, 14046430507935750656, 14043933511036770048, 4816267946201320512, 4819011455589756704, 14044654194769966720, 14042556849826320576, 14047410235151134928, 4810541084821220864, 4783378357999992832, 4824169676573682016, 4825194992135601584, 4820829692712282048, 14045234815888724672, 4824536951587011872, 14038634379291224128, 14047920816213613024, 4824240546755815216, 14048810525711174528, 4818887892976219008, 14047981706810162336, 14042817254998608480, 14039650495529741888, 14026431103085966848, 4821086022437241152, 14044908123376528672, 4821942098105353696, 14047990977267455776, 14045822226120079200, 4820750006881336576, 14048224679307755232, 14048239171818288000, 14048825942491131360, 14042410946871682240, 4823859872194970512, 4821500405583493376, 4824968047514252832, 4818497623928069312, 14045756123989134656, 4825245620074935792, 4820436738597915264, 4811304233764865280, 14037844308624685248, 4823914143377133408, 14048316925372661840, 4814087281058600320, 14041513559587289152, 4819347685468512544, 4819237760509496896, 14044622635128790912, 4823873503725295664, 14047614194401523776, 14048413934677668160, 4823607109400202288, 14046849912092914176, 4824154642579472176, 4821361500887907648, 4823942390615114112, 4825229832920725904, 4824179731758597440, 4825006815771701264, 4822608534557168800, 14032885571326626560, 4820143275860926176, 4811594963418491648, 4824881501322501552, 4807134495379920384, 14047604891892185840, 14047332957012664528, 14048078456623843904, 14038662957961723264, 4815626585925600640, 14047868938395736560, 14043710698861738016, 4824611750219152784, 14043993046101387136, 4825242014597327392, 4818116102667389696, 14047728342120029392, 14022219049402516480, 14038048719047372288, 4823968979684594624, 14046887907478004464, 14045288438306444192, 4818283008160113728, 4823451558568972592, 14046287008020350944, 4824832758625711200, 4819652812670393184, 14046825290634125120, 4814456286971480576, 14042302887881969056, 14044836835438148960, 14047838534528495824, 4816702947033893120, 14019678658256308224, 4825636301326055520, 14030861431732603392, 14042743351495309696, 14035937802676778496, 14048022267163631152, 4822848956880109920, 14042364094287160544, 14040143720674356800, 14044637126181639776, 4792716801032855552, 4821773211317746112, 4824019668689826096, 4812424785661291136, 14045885847204700320, 14048356180248350208, 14046966570176105520, 4811494437115600256, 14048689693908169552, 4818506356145420480, 14047472041030630800, 14045127798519704192, 4815681458997155840, 14038550225824590784, 14040270621590114880, 4821360487145246944, 14045457175217474208, 4818534578906627584, 4825252099883082544, 4823540340658053488, 14046785363053377040, 4816945205242537472, 4824221625712923904, 4819111678335613632, 4823494238427749936, 4813566095802117632, 14044686251276656192, 14039016618663065856, 14035591542985836672, 14048110990063373024, 4825010637444282832, 14047716180911378432, 14047022329380671840, 4824232742807896592, 4822509014179726592, 4823298498913008864, 4821496670768081952, 14046321931468516576, 4820428733251579744, 4817218941935424000, 4812933224489377920, 4802797542327358464, 4824496402866146848, 14048218916817746896, 14034546284361348608, 14038355548285699520, 14044702691585707168, 14049024625112457184, 4823202762755908288, 14043609575577517184, 4811154369008552192, 14042795875821682368, 14040182360109089984, 14034013046950897280, 4823072652860753824, 14046972952640013536, 14039343913731150336, 14044319793744245568, 4812650534253177088, 14046371812627101504, 4821063192203342624, 4816924948346064512, 4822872909638449856, 14046185065798809632, 4823075209095194016, 4824812749989680208, 14032131995952173056, 14046598159936915488, 4824338718474497744, 14040417984111794496, 14047434972759928240, 14047713965230483408, 4811805958561124352, 4823661434788375392, 4819371101476383872, 4820368836068829024, 4822601097759280320, 14035601872838437632, 14042585095347772224, 4820211343488097856, 4785100483842703360, 14046485788724875328, 4823620521064961808, 4823958279807517936, 14048946927087735920, 4825067580189147632, 14041610004630052800, 4824171629500849904, 14046682938938099328, 14045817550738463456, 14043905289703031456, 14043207014105289920, 14026280079566404096, 14042851025125833120, 4825056853645007456, 4823178747794311520, 4820867314915536160, 14045758619376659712, 4821772027815496480, 4823469709834069136, 14048745474488465952, 14044708671883746048, 14047462456265114192, 4814515730598206144, 14042620790796421600, 4823522554720315824, 4818230251858751616, 14042796273302997088, 4818105121608829824, 14043261364282836928, 4823692751597217328, 4814807973994157888, 14047455597442272880, 4818460671558840896, 14045112515845387840, 14047637957357090320, 14043788692012826400, 14037733980508571392, 4811056429270741888, 14033974608165490304, 4817892642233619648, 4825444696005299840, 14044148709143213760, 4824898509546609296, 4823783601325098704, 4816917189341124928, 4823670859580445312, 4816105355467003840, 4818438040889401408, 14043492641661840064, 14048989600483952144, 4824270426581410848, 4825285819311812560, 4809003322107628288, 4821778204908211296, 4822777819699761696, 4815409247251764992, 14046896183798847984, 4824682763596078304, 4817008793446921792, 4812958265950076928, 4821088619569523104, 4820593058516318912, 14043975487509986944, 14047621300427075520, 4811744799544471040, 4816791978625591616, 4824802506771449008, 4819604751910446944, 14045784959723410656, 4825552964609381216, 4825600846414555664, 14046429139785310304, 4825664339865192544, 4817402314147039040, 14046674036541752416, 4823659676638521888, 14043094088489140640, 14045460970277451488, 4820706698326074112, 4819592168162455680, 4820339872951433344, 14038585544076013760, 14044363882277070016, 4823132024209448672, 4810720209485323136, 14048126467681110144, 14036130612338681472, 14037641435922013440, 4825290837153705648, 4821682231586133472, 14048508866230148560, 14043055749983035840, 14047912405750249056, 4823080210441220608, 4823777842033183696, 4823820002656487936, 4825799721898478864, 14046636435075699648, 4825480010489585520, 4823581677442506688, 4822250372574087200, 14033302697861504640, 14045693919176894912, 4823358046825654224, 14048272816343027904, 4823413803268144096, 4825463800618642384, 14046026414240434176, 4816033709328416768, 14040908040559709056, 4824480404421529872, 14047779831783860704, 4809530260274340096, 4821829968700340672, 14039105607067115648, 14042242818078999424, 4824280037184775648, 14047422510889145904, 4811354492706416512, 14038703788439499328, 4824314904346435840, 4823721605852964928, 4825390660868555616, 4824393569512251664, 4822969447700513408, 14047013774182033344, 4822458840987607872, 14046834031563964480, 4823972782196108480, 4825720711634082448, 4824447418339265472, 14047469975413542928, 14047625963598415952, 4799468734284798976, 4825408554609456528, 4824410355098476240, 14038597314327841536, 4824493909051150592, 14047444315067137952, 14037918024033555520, 14046262630488680320, 14037324877806814464, 4824023445801633760, 14046887947282102000, 14044940070320078944, 4823641899469778080, 4824123234429243392, 4823860495067764112, 4803433872244803584, 14048616725384401872, 4824408377942691040, 4824514206593680928, 4824350346873041088, 14042388346432008352, 14048439262684646528, 14048991124704661936, 4815892311406985664, 4824134086696805360, 14044132095110882816, 4815158786482322816, 14048650388135545088, 14044921312257901536, 14047142758640897136, 14045293876766700032, 4815499533728784512, 4819668747697122912, 4820025237521622112, 4822940764057731072, 4823019288024570176, 4820365750874427744, 4820730122761988064, 14048875947967487136, 4821016435912748704, 14044140892818081664, 14048113318515215456, 4818867018662177504, 4825615440028521632, 4813565970332964096, 4821379434016807648, 14048984548531799216, 4824737372497321440, 4824537491254704192, 14043661628615990592, 14047581081479198544, 14048524243159034704, 4824342523339760768, 14049063797956166208, 14046320395644539840, 4820327652416853088, 14041210068769242432, 4825222744942625312, 4820783551179446016, 14042929054388566304, 4825185980008379888, 4819774187262191552, 4824688749300207616, 4824163308595914000, 4813900956304566016, 14048722398222204528, 4822549480334712544, 14035255403370842624, 14042986249689417280, 14042818161816751872, 4805077075890746368, 4824173084024554960, 14046765958292228480, 4820339171570542688, 4825711291054058304, 4807092377174223616, 4810822891367042944, 4819103894964737376, 14048963089960440368, 4823547061017868944, 4822093383424033664, 4818886068543277408, 14047131226867724496, 14045352715678334752, 4818627784578037312, 4814504138869771456, 14047561869935177072, 4823699041501809472, 14030085388505836288, 4821984907811720672, 4819263651972265856, 14049036633608379920, 4824857816255758960, 4816705633918291264, 4825515089957303776, 14030441610146929152, 14047152086431763568, 14045934717468309888, 14046239514229562656, 4816664242405193920, 14040488042159794176, 4801246988415622656, 4821179326921310592, 14046000518988881600, 4812140807020007296, 14044961783589598912, 4823639809789632496, 14040745514798170496, 14047726171579062528, 14048415161159316592, 14044732776655038144, 4821739117710811392, 14049165323498981024, 14028373760152723968, 4814979032221229440, 4813717948683407872, 4820759981033289984, 14048007857030982320, 14047680862765500608, 14042681424022127072, 4821808387038366752, 14048399085692705840, 4821865710990341184, 14041279171555902144, 4822390394090191360, 4824618662500613104, 14043490887518243584, 4813629834794785792, 4824484195353297744, 4821558475914252896, 4823118423615618848, 4818595084526150016, 4816568009332876736, 14039102753865354048, 14048242540863132912, 14045884521152186272, 14047757444607404160, 14044652017933776736, 14032793007844305664, 14049027279532698192, 14046892829488229968, 14026797022747316736, 4825163595661451920, 14044455581861546976, 14042727201393173792, 14048685766115795312, 14046025959264294272, 4820511945091319840, 4823743909907030624, 14042949939972600256, 14039580159555560064, 4819015937985659712, 4824362982326659216, 4824552111129251792, 4823457638671805424, 4823921140191502080, 14040345307052881216, 4823533418350332032, 4825338171039361216, 4822612552487225120, 14038700238698098688, 14043715555620946880, 4819904199248797376, 14039743487162291648, 4825070690262801600, 14038985231958932352, 14042815702035420160, 14047505889168939776, 4824086563950945248, 14036804189463831680, 4813414579830468224, 4816539955452386432, 14043599782684410272, 4821145681434145120, 4815103961915534336, 14045934264249440512, 4814959335414219392, 14041846622307731520, 4825155188489548992, 14040131482669972224, 4820739432987995872, 14037981962948801600, 4825299708248529184, 4823510448253360048, 14046833288683250624, 4824607805015615744, 14044315509699201728, 14048393865545262640, 4824244048683455248, 4810670042511891840, 4824691539254249968, 14046296444243381344, 14045557391572858880, 14046261225365569760, 14035749892700217472, 4806369623280819968, 4822332825577109760, 4819555559649771360, 14030060638786317312, 14047941426888210016, 4821728909065972096, 4819665495462708064, 4803717209641332736, 4825197891685549568, 4820659740520598496, 4825493605265544336, 14049022842860213632, 14046087634811030624, 4823436116850100976, 14033145032014503424, 14046767118481846688, 4816500336190882304, 14046242707297517568, 14046776031495662816, 4815703354135552320, 14043360699546394784, 4825051797675560016, 14046724073075621312, 14046614971263859424, 4825138949304023168, 4816214500039761408, 14045119227321720544, 14043811896782311488, 4815202472834941376, 4824902240377816288, 4817916989179734272, 14038744235187764864, 14048130188551567312, 14040422021022565568, 14047572286945449088, 4819493806941414080, 4824757416212172544, 4823142472158525664, 4816810368623767936, 14046764252318726768, 14046840463438634624, 14045433209606397824, 4819834990348396448, 4824913541516905952, 4818428436337149760, 14041081194394334016, 14043197886526868416, 14049002736020079632, 4822008707556525120, 14032669599490028288, 4824846972709498688, 14048389408623910080, 4820581640170525440, 14044299140972670176, 4825205011168604096, 4825522397425522000, 14040506994769310656, 4819704023598634752, 4806084138736763648, 4824595862144404208, 14048767342883926880, 14045420265757879552, 14041096228393989376, 4820967791712436000, 4812267997001086720, 14047859097364719184, 14042623333028794272, 4815019804759284416, 4825483745771451824, 14043713502251792224, 14048100419397610224, 4817956529314049344, 4825099698095493680, 14047603064479999376, 4821677781523566720, 4824675647976840240, 14041044320136109312, 14048357716882199312, 4820832261441515840, 4818307872204423616, 4824900621368785328, 4819228265911136512, 14046291018795745760, 14038138648593437504, 14044533727359865344, 14047529370610032800, 4814749962329873600, 14048876665590507952, 14047261473896587296, 14048265991775029968, 4818982682813134784, 14030627681786138368, 14041004067595664448, 4824633852670295840, 14048578467832803648, 14048969123484945664, 14048613237520856832, 14044920039306676352, 14048079665556436256, 4825635219583812128, 14044224953991823040, 4810080860085029888, 4823516978872418752, 14048985187750213584, 14042926472270744768, 4818098313978017600, 4822987407276604448, 4825268175142055680, 4808063063380076800, 4784705798763724800, 4822191680941913632, 14043989991150913728, 4814565868856249152, 4824908724883329552, 4825491385159090256, 14046867539259995504, 14033661380005742336, 14047331556102338720, 4823316224765885632, 4825303165855541696, 4819599262551974592, 14045174835131343712, 4797811320920848384, 4825399016814281648, 14048769460534934608, 4823550245189390816, 4822556106598021440, 4821330865977190144, 4823634967448699472, 4825770823169695536, 14042508098622725504, 4825765859659562640, 14042311761928053216, 4823939054384931984, 4815799315823292672, 14045870005443132480, 14048819568468780400, 4823810729965960224, 14028743388748786944, 14048139468978053232, 14048515423817757280, 14047863303690080336, 4818039579239938816, 4817677313551843584, 4820854682816799328, 14048973544294974368, 14014616574546919424, 14048564014456705424, 14043667026177980256, 4820913313671891392, 4824838162898347088, 14045466989798356736, 14040620994713362176, 14042020059809823616, 4810151737271640064, 14034922773766791808, 14041167727637456384, 14048921480856579088, 14047505225963272688, 4823884869399481472, 4813303195463768832, 14043732960720243424, 4821704450958995968, 14048726718832678736, 14030664253432975616, 14029442077796864768, 14046857880889520304, 4811411208422272512, 4824691826138273024, 4810929180882090624, 4825713654706116016, 14043277707007597472, 4823814842162294848, 4825061298287918544, 4811395359900589952, 14040093784478105920, 14010846819932356608, 14047609996612463824, 4820589049093050784, 14046043014746844032, 14035347817301138944, 14047165054493622784, 14043001489257504096, 4824796042815448800, 4823940060130537152, 4812053543038616960, 4810504410389741312, 4815675717771747904, 4817343667700242368, 14047867209982106576, 14042553564915148448, 14041674310627193856, 4824626747854791472, 4809469662999577600, 4816853196745531328, 14039415523564640576, 14047366217729915568, 4804512050904220672, 14044061893743300512, 14040877084533261824, 4825149794512835168, 14043369298173682080, 14032920822853072640, 4815451004354370048, 4820031712543295456, 4824864106082153728, 14048745447546426768, 14042979561052101792, 4821363200561319680, 4822188232926783040, 4823731095105076720, 14024330928877349376, 4822124569350486144, 14046181020766844096, 4816008032659257600, 4823505532255655232, 14048608926876817744, 14043086816360609152, 14043431218222617024, 4823742227279148896, 14033434271271102848, 14043254654206696352, 4820799526351658208, 4810042652985639168, 4818464096024626048, 4820810156746239552, 4821861130857032736, 4817824308536477184, 14047859633748925680, 4819153922482361760, 4824647649089435648, 14046758314719623072, 14029987412182777856, 14046822443461942432, 14039953205051747328, 4825718202891572000, 4811552120232699392, 14047432855865009888, 14048929586987963552, 14042662844130310208, 14033607778619611392, 4819441198173008800, 4818917877881869824, 14049085323745459216, 4823860559748031344, 4807365921367104256, 4824861016138671968, 14031654614643143680, 4817914381448875776, 4825198479846029904, 14047939231914667456, 4819277230271576256, 14047371905361045008, 4822149782054294400, 14039237228312403328, 14047050714534011008, 4824316363071183616, 4806274560160168192, 4820570106516500704, 4824191688082688400, 4812114795851291008, 4823590921617211760, 14039375058746366720, 4823822080073498736, 14031968529294401536, 4823638948432959920, 14035302807104554112, 14048814407632134160, 4814120764064260992, 4819008980077095968, 14037959542815727808, 4820454790779644032, 14008603624705097728, 4811994176005042816, 14030279414180350976, 14042582547940812512, 14047104138168244432, 14046010004457038048, 14048513193303984672, 4806572390951808000, 14049020594390580960, 4821598109261442784, 14035158615887344768, 4817734477992260160, 4824699225026522000, 14041047372336474176, 14042919785460425792, 14045990127414022048, 4796735231262048256, 4824997937700429040, 4824968653599102176, 4825417884620012464, 4813592728514745344, 14046786361181204368, 14047632926479269440, 4822646764126377696, 14043336938170193248, 4822392379978847936, 4825446974385574320, 4824474636133764528, 14041518929823639552, 4824039833716783600, 14040235325891868800, 4824746124298134272, 14047634769619181984, 14045313348135125376, 14041436195472132224, 4824664257085369088, 14044357955201268992, 4821441676178600160, 14032154578807784704, 14047432270807972608, 14041150570552848640, 4802039259094374400, 14046547865216255840, 14034665588260917120, 4822198523984619360, 14024155782596941824, 4822550622765951488, 14039723891016340160, 14034531657195725568, 14046402720168212160, 14048815450179842816, 14047068368869358448, 14041082432262534720, 4824471937691770512, 14035399376366849536, 14041787027145811264, 14033307753871640704, 14049130446858848736, 4824880548850009248, 4815164664896434624, 14038337419048270720, 14044589637814572928, 14036308343873620736, 4811765600305797248, 4821093404696239488, 4824499179044062416, 14044796935843991552, 4825044229752982976, 14047016579479895648, 14023645206820292608, 4823835181733434800, 4807508680976417792, 14041429724337838912, 14047946070668179568, 14043533962612662528, 14043033764563326048, 14034149244040961664, 14047781173396705728, 14042978827476653952, 14048316289435030752, 4821422836857409664, 14048182187160617440, 14040211650041108288, 4824637274054143536, 4822076319777330752, 4824498758037584416, 14047423287414214288, 14047990392117113696, 4811259113780879104, 14048886565567525616, 4824094482538051680, 14047618874943624544, 14027399186241871360, 4820902637664070176, 4821122205470090976, 4825308486408796000, 14036214974157370496, 4820396805880857184, 4823766232033999008, 4825514506451478160, 4802033423964268032, 14045883021204027744, 14031276819043171072, 14047924286335157552, 4825172419180734480, 4823970631424233440, 4821779064645009952, 4812773864779906560, 4803271333529530880, 4825492139971995424, 14036413216541245312, 14044356743822607840, 4816682525860259968, 4818463722202679232, 4818808340069366784, 4824850732171055776, 14041264449465872640, 14048183324220056400, 14047291514935738304, 4817334145361688640, 14040263704621852928, 4814897156578506816, 4820103469433420576, 14049098392876593520, 14046874669210997440, 14037204041975831936, 4821142109959339200, 14033357282232927232, 4795366749952940032, 4825073699214020976, 14048643664617618288, 4823975143141394608, 14042259665693915872, 4817288477211253504, 14039804331806362816, 14039597521658132032, 4822245547121096000, 14044364854982553280, 4823163843499253280, 14042434601051075968, 4825771636441478256, 4825696122035969024, 4819057330289958240, 4824451369999172128, 4825660860991803968, 14046095891170898368, 14047815988034435024, 4822222424956392288, 14040454923402367680, 4818759848294333440, 4814869787699289088, 14048168241346501888, 14034492491026147712, 14037781350341329408, 4818046862503595200, 14048674650136630112, 4809043926402394368, 4822130643009194144, 4825584322019064032, 14043463764490388928, 14047711734126476496, 14042028771981653632, 4821213783731303008, 4824097787867862848, 4824552947270173088, 4825510007112537888, 4824914528218860432, 14038334858020807168, 14030665390759691776, 4823020534669674528, 4810083679642412928, 4824384252572698528, 14047566306679343776, 14038912295696402560, 4823717782054597264, 4808200379836104192, 4824394076386796656, 4820330319581919776, 14045325426999314656, 14046365120501436832, 14044149789380628704, 4819039223841385856, 14039235563336614848, 14045969129271658624, 14041817754655880128, 4825131551847934256, 4811254555456829568, 14043670928709967232, 4825332575611757680, 4821088497814710496, 14048048589564974960, 14044612644721478880, 4823905787144242640, 14043759638687472608, 4825689559050848240, 4820920774517506016, 4821109658015699552, 4809168362666924288, 14032159081907142144, 4823941424989302368, 4824422034810973536, 4824329055777266784, 14046990117354139552, 14048781017505987008, 14049165448903487424, 4823396333782532592, 4808897556958704128, 14043869462381141568, 4823625411153540944, 14045044730168242816, 14048512604526218176, 4806320010870609920, 4780960499617218560, 14048305794661702272, 4825502815947091904, 14035111104035609472, 14046494058493286272, 14038098854484362688, 4822281089241756736, 4819478842187358240, 14043342756211376992, 4825118434462241936, 4822680930955796352, 4823486188302607248, 4824708561328341456, 4820411491316775584, 14047652395226744976, 14043556844085627648, 4795329193623121920, 14045229224944328608, 14045505766908476224, 14043410007211580544, 14046431309206230560, 14044352395881500096, 14047091179732440912, 14040660958297720896, 4821817055165850944, 4819199782566382816, 4820552519312091552, 14044038080378180224, 4823626586759988288, 14049029660881844256, 4823432679904451936, 4816937081132080384, 14044918008458111424, 14020902098382045184, 4825319351585650272, 4815961531267460672, 14048587033792391584, 4815021075536897536, 14036479029193372544, 4819185431676456448, 14048663720639524448, 14038583725798463104, 4813159270269736448, 4825780158746887536, 14048645304410417152, 14042715766195774336, 14011700343665528832, 14048351210226755120, 14034421464178087808, 4824683488419712752, 14046799120506050944, 4823325141407800960, 4824828138576424432, 14021094136442047488, 4823638235325125392, 14034017471368043264, 14042288828097558816, 14043156075144106336, 4806837410053747968, 14039925246703034816, 14042136769992976192, 4825294132408825440, 4824795331719690688, 14043192984385229536, 4820394933017762400, 4820158500518951232, 4820563390870483168, 4824587126480364048, 14048921609774002400, 14047415578198840048, 4822498766602738752, 14042318320626030880, 4812727538142044032, 14044952908571129728, 14049006924595280848, 14036687082704309760, 14038118743210154304, 4816879028373490944, 14047830244698481744, 4824775736211304000, 4814172527318878464, 4824523525066340544, 4815098745828375040, 4815101512388185856, 14015215148728569856, 4824554621870243872, 14047131527335992640, 14037040587996897664, 14046826979045978352, 4823810932579291328, 4820479286536100096, 4824025064337768448, 14031625757285242880, 4809664499448005376, 4824003556673392016, 4814462241983823744, 14047183313265195856, 4819427535743887392, 4824864172787250080, 4825599773713811008, 4823430056784091840, 14036617675265517824, 14044697207842096768, 14028793082616640256, 14047767428554719104, 14046228029542860736, 14048357082089106688, 14039046738265045696, 14036966647204158976, 4823901096678996656, 4825265566354568736, 4823313053677949760, 14046729053382192432, 4803677510675791872, 4822072021462983520, 14047882657639345600, 4815989131287157888, 4824648798597445312, 4823596800095263776, 4825452425024528880, 4817059429024057088, 4822849296170395872, 14044635622196772896, 4819361904919562496, 14049068364825738960, 4810501446803364224, 4824485945741776448, 4823259803769131136, 14044747587695985472, 4820908189929728608, 4818794376220434816, 4816108343408973760, 4825403958920374368, 4823793936674110640, 14043807775905800256, 14036431093034641280, 4823428374613190160, 4823456223292231312, 4815422236714533824, 14042335396392254432, 4822552706222506912, 14044868192340871520, 4822247264741971456, 14045261901037167712, 4814120624571797632, 14038417954804688000, 14035810273727324800, 4824668946196266800, 4822946311429356928, 4824865598517886784, 14047989092002799952, 14047189150594752928, 4824529248758541888, 4822959577716853792, 14043967904406082336, 14044025182676338144, 4823055223635684160, 4820258622215998240, 4823708037201768336, 14048686191809961712, 14040526815067820864, 4814321300577441280, 4821662091867274560, 4825696541231398816, 4824536689847720384, 14040069041008209344, 14048116803683574192, 14044339303715978080, 4820922439718925184, 4821347579251020256, 14046205369346919328, 4814820021000367360, 14048010483661446336, 4824246456163389840, 14043862768895973312, 14041578814391084480, 4821828337744762016, 4817625345557820160, 4819625978766232672, 4822261489834261664, 4824797767744218112, 4825467190193831088, 14044944519505486080, 4825257099096686752, 4822844067889225472, 14049062794721039088, 14048419495768346192, 14048358845022615392, 4821940456313966208, 4825781222648606272, 14044770118777752960, 4822477589161561344, 14045903838232765248, 14042525171771461760, 14047894001338874944, 4822117288483348576, 14047103947997857184, 4814703670485199808, 4822716150688547040, 4818747066279927808, 14042317720043200384, 4822782618761166080, 14046221411775730336, 14042180291607736896, 4823198288935028608, 14045640872416596896, 14049069445492502832, 14048407156054820144, 4816408571398304448, 4824886878132944752, 14042901405467415424, 14048983891005575440, 4811277492240575104, 14039592740227219968, 14037720094846931968, 4824103161134812208, 14041228168804467392, 14049084259695085552, 4823028054587460672, 14034617407306666752, 14027205404510754304, 14045596794367193952, 14049109822368874736, 4814700155417299392, 14038205574719259200, 4821133414948934240, 4807658014437523712, 14046818250910660240, 14043500660972239680, 14048927820078980528, 14042223465469575296, 14044466448556423008, 4818839803760532672, 14042554233179444000, 4824652631904467808, 14042150581838090944, 14047104815928853792, 4824849657250712416, 14048255013656985072, 4825612138913241424, 4822638137927943936, 14048572819666547536, 4825233263122045456, 4819910553766348384, 4821715471609333568, 4814875770870063808, 4819786472723278688, 4818402455693673984, 14046186192283658272, 14048260117997113040, 14038419085957396544, 4823725894356626624, 4819446055545337792, 14040300318702617728, 4822360928336805824, 4823373043301644432, 14035351792974377728, 14045293124139190464, 14044525947970532160, 4825748900760840688, 14020353453775311872, 14042235348754988992, 14048959636038672560, 14041420114076209920, 4824580918715324960, 4810129767972218240, 14048518287661526624, 14048965794690965088, 4823501006594178784, 14040998374858042432, 14042327360407432992, 14045160048934373312, 14024832427335436800, 14042999912589697376, 4821342494564902848, 14045602366058426688, 14042556540900780960, 4805581525172769536, 4815753853996979392, 14048234469037794032, 14029812006270044160, 14042500138902327872, 4822172984996334336, 4819838152469835072, 4819399941274559712, 4819347064913619872, 14041326363585569856, 4823139506591837568, 14047979518243091328, 14041606606399951680, 4824297525055589696, 14036333397661454336, 14044505619532453280, 4816831158832552384, 4821666117537948960, 14042478164651294208, 4817589718173583680, 14048191343534622448, 14048645125773154608, 4814233095401211392, 14047483709747098320, 4818680658625789248, 14040636169532221632, 14040803336369050944, 14044593280942246944, 14047129120235775072, 14038823200748777152, 14046763680973508656, 14046608882492330432, 14047481293264791312, 4825589446653083744, 4824920886445615776, 4824531828603699616, 4818988687019059488, 14045414187235242880, 14036111466687911168, 4819160184232783808, 14048805170158592512, 4824035378279041872, 4824237923961393072, 4825132171646934880, 14048257841820499040, 4819528509169402688, 14043657591186423872, 14046387890913359424, 4824134418209535264, 14048743834403249888, 14042294856302848352, 14047148995976767104, 4825031720907314480, 14042052453229739136, 14046676121336856224, 14049054967715551472, 14038599511694023424, 4825162663832051264, 14047442025147249216, 14037723993555736512, 4821940087027561280, 14024900525013959680, 4817253328084959296, 4819461413846577344, 14044882395932832128, 4824528870231913088, 14037070311974496640, 14046342472613602112, 4824951359190630624, 4825546747119167232, 14044781802203471584, 4816600845839623488, 4825778936880648768, 14048620634226905392, 4821974040045795584, 4822259517303351968, 4823831795524903504, 4799950832228170752, 14048979205247875120, 4812537347165889792, 4824337283629199376, 14045670381235236992, 14045244379693435200, 14036459055618907648, 4822888550680909920, 4823635667656511824, 14049134823592440912, 4824069872689553152, 4816595357216173824, 4808710766082249216, 14042418790464045632, 14046477506892596800, 14043398260487037152, 14047020603191320272, 4823794606714205136, 4825208919820651920, 4810255898296833280, 14048174993702557472, 14031218065677010688, 4815370418413929344, 4824486838814085024, 4822739708391689568, 4822586152193057248, 14045954091572279264, 4802778812519639552, 14042773259051778624, 4823700719930457424, 14044502550048991872, 14030560325937258496, 4812722163493309568, 14042869278648109312, 4823954717183032640, 4808510638068955392, 14044754168329762240, 4824952843856497776, 14043625850189021792, 4825018626037774912, 4816537793204529408, 4815421908627850432, 14047954475478614496, 14037690995066713728, 4822356440614009856, 4825547180506781600, 4814430861172927616, 14048326267377747344, 14047980604595262016, 14046556665036832224, 14044802675006348800, 4815077004599362368, 14037523503206304640, 4822411895407200480, 14042969473449009984, 14045443781189650112, 14044508042724035136, 4823079439063141504, 4825601113859181872, 4810021666733410176, 4824277006514015152, 4823987077946328576, 4818233613479956864, 4825438135440397184, 4814524885019299136, 14024573821519523328, 4815307854132227072, 14047459192522621856, 4825115332910152704, 14045060474407595840, 14045251198651260096, 4821903354082042496, 4824656606233529056, 4812983876140134912, 14039958129181022272, 4823437081122836688, 14039773269233049344, 14047100644790258960, 4820120081736677344, 14042081864130170624, 4824891684722971296, 14043200110983080416, 14046198772202153312, 14039743336140037504, 14047164062653083696, 4823776775075343536, 4819020122735314048, 4825241065497721072, 14041883400219110144, 14048491980588049008, 14034733642170184064, 4816623046341058368, 4819448054750859776, 4821959319467467104, 4816595589642135744, 14031406190985562880, 14046723341210022880, 4822121187834219680, 4819409601088840192, 4825555928031439568, 14043166967486658880, 4824518984465831024, 14042639801898105344, 14040080437567239872, 14044159693466196736, 4814683868293188608, 14046251883788447776, 4812865744470700672, 4821028470729843968, 4823993597005770000, 14043813122652458400, 4819786778529327168, 4823580361172319984, 4823992542478761104, 4823907011920804240, 14037775829442203328, 4796402677603721216, 4815028467032232384, 14047961248981739168, 14041153369005993280, 14046881044539894448, 14046922994809413696, 14039906385651157312, 4825227028615957616, 4823770328847239184, 14047449421980167376, 4824287127141871648, 4819027602398519616, 4819914689616567584, 14043404391358018688, 4822837655710840128, 14046791501974347424, 14048942270802509472, 14045452733107151840, 14039554327645985536, 14045827934158284032, 14047239433789808256, 14037130380023548160, 14034867204809081472, 14035241676013645824, 14048207166401850240, 14047991323392969440, 4824246953235221056, 14043851835145181760, 4818367307904894464, 4824652778964147552, 14048730476311653600, 14040418399699816704, 14047456050418096416, 4824430752514720832, 4819492142642010592, 4825227620005671216, 4820263067040228352, 4819284821463994560, 4821934641184135872, 14039829019717110208, 14047082653720845536, 4811937098022243328, 14048203816622421248, 4818121595931286784, 4824371128853501840, 4824500741613638064, 14033485559620271744, 14040671843562067584, 14044378526694689952, 14046860384716577184, 14048728206259739136, 14041876662741834048, 14047149212732573824, 14039936263056435584, 4817745944332642560, 14047853251317322544, 4824052561202876528, 14046032242323604608, 14048949668235440368, 4801409254327659008, 4820801340618463968, 4813837026340930304, 14042746947779002752, 14043737286503750112, 14048572057235414832, 14044021129288586496, 4825411860536978096, 4816253493935780288, 14039587257297321600, 4816802878535489216, 4825254207903054640, 4817108214976570432, 4825522844708905248, 14046236965204166528, 14048428679290519712, 14041403454063425920, 4824920652007546144, 4822076402978010432, 14040782966056027968, 14045469910120356224, 14040817268304582592, 4823537046448287360, 4825542199994661728, 4816795274138577408, 4803516639061754880, 14048031366099736640, 4822170201496685792, 4823917485742546144, 4824650573257132432, 4824520928744856064, 14042850428874976544, 14042551426705223744, 4823073668841395072, 14043677174658654688, 4819885514414555648, 4820567441476092768, 14037822649441574656, 4815507352615158272, 14048069958799448320, 14035956905390485632, 4824006387258217312, 14047825084095033664, 4825497617704600336, 4823710251822915952, 4818564662891733760, 4802540568370867200, 4817783542940734784, 4819097907965471552, 4815770203467603456, 4823503628351117552, 4825575873764536032, 4819964201468093600, 14047110080179873952, 14037976031954335616, 14047206272173840192, 4819555700974924192, 4819682760681990048, 4814575666592819712, 4824593570341773600, 14045731131286984032, 4820453382547030080, 14035579719987047552, 4823394873587251984, 14038409257607009152, 14008802837672419328, 4823119450280492928, 4823697101508112944, 14045803432805343744, 4825235470573760592, 4824362808272949840, 4823141118950601248, 4818402729592626048, 14047965960600300160, 4820480098771281920, 4825075385656996960, 14045375639208778912, 4818870980556533568, 14045744963691315328, 4825743495166271600, 14024465663582709760, 4825218767317859104, 4825456778648256128, 4819959260922282048, 14023603196420501504, 14025329975515606528, 4795643535283232768, 4824039028940734384, 4824328230144321984, 4817359991911098176, 4813965683063214592, 14044153524067540608, 14041007745824524544, 4820060462529641216, 14048272011270279664, 4822516552777929056, 14042790287495060736, 14049030264483091920, 4814897236898586944, 14041714513845410368, 14045645552131582752, 4824902083693964608, 14045635924064324800, 4821197816935667328, 4824493519784159488, 14045059031499263712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], w2tab_offsets: [ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, ], crts: [ SerializedCRTData { prime: 1108307720798209, coeff_len: 1, nprimes: 1, }, SerializedCRTData { prime: 659706976665601, coeff_len: 2, nprimes: 2, }, SerializedCRTData { prime: 1086317488242689, coeff_len: 3, nprimes: 3, }, SerializedCRTData { prime: 910395627798529, coeff_len: 4, nprimes: 4, }, SerializedCRTData { prime: 699289395265537, coeff_len: 4, nprimes: 5, }, SerializedCRTData { prime: 1022545813831681, coeff_len: 5, nprimes: 6, }, SerializedCRTData { prime: 1013749720809473, coeff_len: 6, nprimes: 7, }, SerializedCRTData { prime: 868614185943041, coeff_len: 7, nprimes: 8, }, ], crts_data_0: [1, 1108307720798209, 1], crts_data_1: [ 659706976665601, 0, 1108307720798209, 0, 1768014697463809, 39636172800, 659706976665601, 448600744132608, ], crts_data_2: [ 1746024464908289, 38849740800, 0, 2194625209040897, 65267564544, 0, 1768014697463809, 39636172800, 0, 2854332185706497, 143753478144, 2334150, 571641331050399, 264058712526685, 369275654225854, ], crts_data_3: [ 2656420092706817, 9223372161875443712, 1917337, 0, 3105020836839425, 173578125312, 3221127, 0, 2678410325262337, 126892376064, 1956150, 0, 2854332185706497, 143753478144, 2334150, 0, 3764727813505025, 9223372321477099520, 3624386149345124124, 115, 458320576515567, 97569782239540, 1036168050845794, 811521334526211, ], crts_data_4: [ 3355709487972353, 4611686244149100544, 12608207587853570738, 72, 3804310232104961, 13835058346567139328, 1997174910934683142, 122, 3377699720527873, 9223372265281814528, 2855889094178193272, 74, 3553621580972033, 9223372288811859968, 8932863472618095828, 88, 3764727813505025, 9223372321477099520, 3624386149345124124, 115, 4464017208770561, 4611686445765099520, 11571777141199897105, 80555675693875672, 50394861723794, 258028603731868, 773781365962580, 227761278779927, 298113091205252, ], crts_data_5: [ 4378255301804033, 6917529439377555456, 12530393500700933832, 74322200788992441, 0, 4826856045936641, 11529215548235186176, 7614436330990988976, 124861297325507225, 0, 4400245534359553, 2305843424874463232, 4338630002270041433, 75826698780672449, 0, 4576167394803713, 2305843458156265472, 17511087166284620218, 90479200960512519, 0, 4787273627336705, 2305843502523613184, 15767648752728317208, 117793676722176637, 0, 4464017208770561, 4611686445765099520, 11571777141199897105, 80555675693875672, 0, 5486563022602241, 16140901739284398080, 6996870336501118609, 14398896805553899065, 4465387963968, 465694486061214, 121967058613713, 753509900459637, 334781288330872, 601064818874366, 857013090336611, ], crts_data_6: [ 5392005022613505, 17293823221448310784, 2198478172704326192, 14933593249072088535, 4084412403550, 0, 5840605766746113, 14987980327317929984, 7157356428090476222, 6564030839720445995, 6861812837965, 0, 5413995255169025, 4611686675905773568, 17498989514742629167, 2837081764142908908, 4167092816578, 0, 5589917115613185, 13835058755710222336, 4466506778020173865, 2923420645518345907, 4972328143453, 0, 5801023348146177, 13835058811679014912, 1196502022415599580, 3070261776836331495, 6473408337703, 0, 5477766929580033, 6917529700301012992, 13621513655758281367, 14394739531794089519, 4426976024493, 0, 5486563022602241, 16140901739284398080, 6996870336501118609, 14398896805553899065, 4465387963968, 0, 6500312743411713, 12682137526980575232, 5414242920244170579, 1602665819603013542, 613989000473298913, 245397550, 369585359167388, 139053507976977, 197670239731636, 810816405262515, 464183612954890, 207483271871031, 455632918774715, ], crts_data_7: [ 6260619208556545, 2882304667759673344, 3730551556212422699, 6864787753339620743, 15487482481366708770, 192325460, 0, 6709219952689153, 576461794752856064, 12548400340138486966, 16018745093780771332, 3882874023334036815, 323106774, 0, 6282609441112065, 1729383169321074688, 7686718500326172996, 13089866517368245683, 14606063416176826766, 196218688, 0, 6458531301556225, 10952755257409273856, 2741863966014413374, 15654288961721831229, 11636034492611489364, 234135343, 0, 6669637534089217, 10952755323318566912, 9393959891602620577, 11456823266980106630, 9579969358296738720, 304817711, 0, 6346381115523073, 14987980490484219904, 11211844038443280667, 14041014936563027513, 6670475906452161904, 208455983, 0, 6355177208545281, 10376294474599628800, 15564451032506485917, 16359389422381633100, 1246349985313081608, 210264712, 0, 6500312743411713, 12682137526980575232, 5414242920244170579, 1602665819603013542, 613989000473298913, 245397550, 0, 7368926929354753, 16717363099189116928, 17073008061340272950, 7820777766012624523, 8382868381485621416, 3665382864143079344, 11555, 880374631983717, 648658714639505, 567379657715946, 136167427417685, 657261478444690, 163175436259942, 815098541074103, 656711192629307, ], vec_two_pow_tab_backing: [ [4607182418800017408, 4607182418800017408, 4607182418800017408, 4607182418800017408], [4611686018427387904, 4611686018427387904, 4611686018427387904, 4611686018427387904], [4616189618054758400, 4616189618054758400, 4616189618054758400, 4616189618054758400], [4620693217682128896, 4620693217682128896, 4620693217682128896, 4620693217682128896], [4625196817309499392, 4625196817309499392, 4625196817309499392, 4625196817309499392], [4629700416936869888, 4629700416936869888, 4629700416936869888, 4629700416936869888], [4634204016564240384, 4634204016564240384, 4634204016564240384, 4634204016564240384], [4638707616191610880, 4638707616191610880, 4638707616191610880, 4638707616191610880], [4643211215818981376, 4643211215818981376, 4643211215818981376, 4643211215818981376], [4647714815446351872, 4647714815446351872, 4647714815446351872, 4647714815446351872], [4652218415073722368, 4652218415073722368, 4652218415073722368, 4652218415073722368], [4656722014701092864, 4656722014701092864, 4656722014701092864, 4656722014701092864], [4661225614328463360, 4661225614328463360, 4661225614328463360, 4661225614328463360], [4665729213955833856, 4665729213955833856, 4665729213955833856, 4665729213955833856], [4670232813583204352, 4670232813583204352, 4670232813583204352, 4670232813583204352], [4674736413210574848, 4674736413210574848, 4674736413210574848, 4674736413210574848], [4679240012837945344, 4679240012837945344, 4679240012837945344, 4679240012837945344], [4683743612465315840, 4683743612465315840, 4683743612465315840, 4683743612465315840], [4688247212092686336, 4688247212092686336, 4688247212092686336, 4688247212092686336], [4692750811720056832, 4692750811720056832, 4692750811720056832, 4692750811720056832], [4697254411347427328, 4697254411347427328, 4697254411347427328, 4697254411347427328], [4701758010974797824, 4701758010974797824, 4701758010974797824, 4701758010974797824], [4706261610602168320, 4706261610602168320, 4706261610602168320, 4706261610602168320], [4710765210229538816, 4710765210229538816, 4710765210229538816, 4710765210229538816], [4715268809856909312, 4715268809856909312, 4715268809856909312, 4715268809856909312], [4719772409484279808, 4719772409484279808, 4719772409484279808, 4719772409484279808], [4724276009111650304, 4724276009111650304, 4724276009111650304, 4724276009111650304], [4728779608739020800, 4728779608739020800, 4728779608739020800, 4728779608739020800], [4733283208366391296, 4733283208366391296, 4733283208366391296, 4733283208366391296], [4737786807993761792, 4737786807993761792, 4737786807993761792, 4737786807993761792], [4742290407621132288, 4742290407621132288, 4742290407621132288, 4742290407621132288], [4746794007248502784, 4746794007248502784, 4746794007248502784, 4746794007248502784], [4751297606875873280, 4751297606875873280, 4751297606875873280, 4751297606875873280], [4755801206503243776, 4755801206503243776, 4755801206503243776, 4755801206503243776], [4760304806130614272, 4760304806130614272, 4760304806130614272, 4760304806130614272], [4764808405757984768, 4764808405757984768, 4764808405757984768, 4764808405757984768], [4769312005385355264, 4769312005385355264, 4769312005385355264, 4769312005385355264], [4773815605012725760, 4773815605012725760, 4773815605012725760, 4773815605012725760], [4778319204640096256, 4778319204640096256, 4778319204640096256, 4778319204640096256], [4782822804267466752, 4782822804267466752, 4782822804267466752, 4782822804267466752], [4787326403894837248, 4787326403894837248, 4787326403894837248, 4787326403894837248], [4791830003522207744, 4791830003522207744, 4791830003522207744, 4791830003522207744], [4796333603149578240, 4796333603149578240, 4796333603149578240, 4796333603149578240], [4800837202776948736, 4800837202776948736, 4800837202776948736, 4800837202776948736], [4805340802404319232, 4805340802404319232, 4805340802404319232, 4805340802404319232], [4809844402031689728, 4809844402031689728, 4809844402031689728, 4809844402031689728], [4814348001659060224, 4814348001659060224, 4814348001659060224, 4814348001659060224], [4818851601286430720, 4818851601286430720, 4818851601286430720, 4818851601286430720], [4823355200913801216, 4823355200913801216, 4823355200913801216, 4823355200913801216], [14050949362419236880, 14039408888374100032, 14050597518698348560, 14047782768931242000], [4805340802404318720, 14043912488001470528, 4810407351985110912, 4821244138588471264], [4809844402031689216, 4823073725937090464, 4814910951612481408, 4825747738215841760], [4814348001659059712, 14040534788280943040, 4819414551239851904, 14034905288746730112], [4818851601286430208, 14045038387908313536, 4823918150867222400, 14039408888374100608], [4823355200913800704, 4820821926123404448, 14049471618791506192, 14043912488001471104], [14050949362419237392, 14045882812838446816, 4820118238681627616, 14048416087628841600], [4805340802404285952, 4819133076263137888, 4824621838308998112, 4818570126309715008], [4809844402031656448, 4823636675890508384, 14048064243907954768, 4823073725937085504], [4814348001659026944, 14036594138607049344, 4824551469564817264, 14048064243907957712], [4818851601286397440, 14041097738234419840, 14048204981396316464, 4820118238681608416], [4823355200913767936, 14045601337861790336, 4824269994588093872, 4824621838308978912], [14050949362419270160, 4819696026216450848, 14048767931349763248, 14043771750513196192], [4805340802402188800, 14047430925210465520, 4822932988448599392, 14048275350140566688], [4809844402029559296, 4800837202762632192, 4827436588075969888, 4819273813751172512], [4814348001656929792, 4805340802390002688, 14026461039454104064, 4823777413378543008], [4818851601284300288, 4809844402017373184, 14030964639081474560, 14046938344001758416], [4823355200911670784, 4814348001644743680, 14035468238708845056, 4823988519610103408], [14050949362421367312, 4818851601272114176, 14039971838336215552, 14046305025308698208], [4805340802267971072, 4823355200899484672, 14044475437963586048, 4824832944536345008], [4809844401895341568, 14039408888431366208, 14048979037590956544, 14042927325603731808], [4814348001522712064, 14043912488058736704, 4822088563483826208, 14047430925231102304], [4818851601150082560, 4823073725822558112, 4826592163111196704, 4822651513389030048], [4823355200777453056, 14040534788739072448, 14040816263535869760, 14048486456456013168], [14050949362555585040, 14045038388366442944, 14045319863163240256, 4818007175692342464], [4805340793678036480, 4820821925207145632, 14049823462790610752, 4822510775319712960], [4809844393305406976, 14045882814670964448, 4818570124083988032, 14048627194525330256], [4814347992932777472, 4819133072598102624, 4823073723711358528, 4816881271137805760], [4818851592560147968, 4823636672225473120, 14050878995900791248, 4821384870765176256], [4823355192187518464, 14036594197247613568, 4796333033362176000, 4825888470392546752], [14050949371145519632, 14041097796874984064, 4800836632989546496, 14032090708952434944], [4805340243922222592, 14045601396502354560, 4805340232616916992, 14036594308579805440], [4809843843549593088, 4819695908935322400, 4809843832244287488, 14041097908207175936], [4814347443176963584, 14047431042491593968, 4814347431871657984, 14045601507834546432], [4818851042804334080, 4800822190778190848, 4818851031499028480, 4825536462010496784], [4823354642431704576, 4805325790405561344, 4823354631126398976, 14038002873273042880], [14050949920901333520, 4809829390032931840, 14050598088485750800, 14042506472900413376], [4805305059550133760, 4814332989660302336, 4810398235386675072, 14047010072527783872], [4809808659177504256, 4818836589287672832, 4814901835014045568, 4823845062558052496], [4814312258804874752, 4823340188915043328, 4819405434641416064, 14046803045642739440], [4818815858432245248, 14039468936369131584, 4823909034268786560, 4824259116328141360], [4823319458059615744, 14043972535996502080, 14049489851988377872, 14045222638436546400], [14050985105273422352, 4822953629947027360, 4820045305894140896, 4825915331408496816], [4803053259736448512, 14041015172241195456, 4824548905521511392, 14031231156442032896], [4807556859363819008, 14045518771868565952, 14048210109482928208, 14035734756069403392], [4812060458991189504, 4819861158202899616, 4824259738414870384, 14040238355696773888], [4816564058618560000, 14047265793224016752, 14048788443696210224, 14044741955324144384], [4821067658245930496, 4808373226153415424, 4822850939062811488, 14049245554951514880], [4825571257873300992, 4812876825780785920, 4827354538690181984, 4809197145563504896], [14046307259231897632, 4817380425408156416, 14030212519701812480, 4813700745190875392], [14050810858859268128, 4821884025035526912, 14034716119329182976, 4818204344818245888], [4809772916323319040, 14043758615014201888, 14039219718956553472, 4822707944445616384], [4814276515950689536, 4823368336412714480, 14043723318583923968, 14048430025399426832], [4818780115578060032, 14039303804382793920, 14048226918211294464, 4818458624145033152], [4823283715205430528, 14043807404010164416, 4824226120958137872, 4822962223772403648], [14051020848127607568, 4823283893919702688, 14048855678609675248, 14048175746072639568], [4800694231360240640, 14039694116350494144, 4822581999408951392, 4819672230022880992], [4805197830987611136, 14044197715977864640, 4827085599036321888, 4824175829650251488], [4809701430614981632, 4822503269984302240, 14036017513755900544, 14045555785148105888], [4814205030242352128, 14042520125116651232, 14040521113383271040, 4825582184696937328], [4818708629869722624, 14047023724744021728, 14045024713010641536, 14037554145049201024], [4823212229497093120, 4812981909772472960, 14049528312638012032, 14042057744676571520], [4827715829124463616, 4817485509399843456, 4819891463295604256, 14046561344303942016], [14001762727133986816, 4821989109027213952, 4824395062922974752, 4824576625541101200], [14006266326761357312, 14043548447030827808, 14048517794680001488, 14043952601584707040], [14010769926388727808, 4823578504396088560, 4823644368020723824, 14048456201212077536], [14015273526016098304, 14037524882517766528, 14050019184484503344, 4818249217643827520], [14019777125643468800, 14042028482145137024, 4817004350532847296, 4822752817271198016], [14024280725270839296, 14046532081772507520, 4821507950160217792, 14048385152573845200], [14028784324898209792, 4816817475503602240, 4826011549787588288, 4818817606749686208], [14033287924525580288, 4821321075130972736, 14043842404132971808, 4823321206377056704], [14037791524152950784, 14044884514823310240, 14048346003760342304, 14047816763467986512], [14042295123780321280, 4821129672293411040, 4823987949860042192, 4821108160441493216], [14046798723407691776, 14045267320498433632, 14049332020805866608, 4825611760068863712], [4827434354286231568, 4820364060943164256, 4820676630624185952, 14037080939098378880], [14033252179524452224, 14046762890483752112, 4825180230251556448, 14041584538725749376], [14037755779151822720, 4815751629797923520, 14046947460022838096, 14046088138353119872], [14042259378779193216, 4820255229425294016, 4826785037335050608, 4825049831491923344], [14046762978406563712, 14046871722001622352, 14039273269745038528, 14041895917421630400], [4827505844288487696, 4814880977654961600, 14043776869372409024, 14046399517049000896], [14031000240090242816, 4819384577282332096, 14048280468999779520, 4824738452796042320], [14035503839717613312, 4823888176909702592, 4824119019381167760, 14043305292564942560], [14040007439344983808, 14031923805713418496, 14049069881763615472, 14047808892192313056], [14044511038972354304, 14036427405340788992, 4821725186793190496, 4821139645544187040], [14049014638599724800, 14040931004968159488, 4826228786420560992, 4825643245171557536], [4822649846890529824, 14045434604595529984, 14042973457601080992, 14036577177455277696], [4827153446517900320, 4820029492748971552, 14047477057228451488, 14041080777082648192], [14037733371165794112, 14047097458677944816, 4825725842923823824, 14045584376710018688], [14042236970793164608, 4811802166829703552, 14044985231588029664, 4825553593135024528], [14046740570420535104, 4816305766457074048, 14049488831215400160, 14037865824276820928], [4827550660260544912, 4820809366084444544, 4820049388986051744, 14042369423904191424], [14029566128984411904, 14045907932916366624, 4824552988613422240, 14046873023531561920], [14034069728611782400, 4819082836107298272, 14048201943299106512, 4824119160550496400], [14038573328239152896, 4823586435734668768, 4824276070782513776, 14045782461547126240], [14043076927866523392, 14037397981100483200, 14048755778960923440, 4825355508297916976], [14047580527493893888, 14041901580727853696, 4822981598003958624, 14039450502973681344], [4825870746113827344, 14046405180355224192, 4827485197631329120, 14043954102601051840], [14045109306269792224, 4817325081172735552, 14022490816190501888, 14048457702228422336], [14049612905897162720, 4821828680800106048, 14026994415817872384, 4818237209513069120], [4820256777700778144, 14043869303485043616, 14031498015445242880, 4822740809140439616], [4824760377328148640, 4823160094969944288, 14036001615072613376, 14048397160704603600], [14048139009590542032, 14040189312149527744, 14040505214699983872, 4818721541703619008], [4824753781920531056, 14044692911776898240, 14045008814327354368, 4823225141330989504], [14048152200405777200, 4821512878386235040, 14049512413954724864, 14047912828514053712], [4824727400290060720, 14044500908312785632, 4819955058028752928, 4820723900257224416], [14048204963666717872, 4821896885314460256, 4824458657656123424, 4825227499884594912], [4824621873768179376, 14043732894456335200, 14048390605213704144, 14040474570280257856], [14048416016710480560, 4823394056970581168, 4823898746953318512, 14044978169907628352], [4824199767680654000, 14039098039919860416, 14049510426619313968, 14049481769534998848], [14049260228885531312, 14043601639547230912, 4819963007370396512, 4793735012815390720], [4821667485747303776, 4823525311879685456, 4824466606997767008, 4798238612442761216], [4826171085374674272, 14038048000647026112, 14048374706530416976, 4802742212070131712], [14043907949226404512, 14042551600274396608, 4823930544319892848, 4807245811697502208], [14048411548853775008, 14047055199901767104, 14049446831886165296, 4811749411324872704], [4824208703394065104, 4812478307248546944, 4820217386302991200, 4816253010952243200], [14049242357458709104, 4816981906875917440, 4824720985930361696, 4820756610579613696], [4821738971454592608, 4821485506503287936, 14047865948665227600, 4825260210206984192], [4826242571081963104, 14044555652078679840, 4824948060050271600, 14040212887701143616], [14043622006397249184, 4821787397782671840, 14047411800425407792, 14044716487328514112], [14048125606024619680, 14043951869519912032, 4825856356529911216, 14049220086955884608], [4824780589052375760, 4822994962900207456, 14044463177163680096, 4809928261727681664], [14048098586142087792, 14040849840428475072, 14048966776791050592, 4814431861355052160], [4824834628817439536, 14045353440055845568, 4822137606683450016, 4818935460982422656], [14047990506611960240, 4820191821828340384, 4826641206310820512, 4823439060609793152], [4825050787877694640, 14046935129598575984, 14040423917938879296, 14047615049539258128], [14047558188491450032, 4814373716879332544, 14044927517566249792, 4821915016156406752], [4825915424118715056, 4818877316506703040, 14049431117193620288, 14049222953688636464], [14044930594250241376, 4823380916134073536, 4820280245073171232, 4809882394003651968], [14049434193877611872, 14039203166611921472, 4824783844700541728, 4814385993631022464], [4820971625778981536, 14043706766239291968, 14047740231124867536, 4818889593258392960], [4825475225406352032, 4823420185187624400, 4825199495130991728, 4823393192885763456], [14046691389099693472, 14038889014183514560, 14046908930263967536, 14047706784987317520], [4827613174233344624, 14043392613810885056, 4826862096852791728, 4821548074364169184], [14026418524450547200, 4823734337616031312, 14038656793603109568, 4826051673991539680], [14030922124077917696, 14035031550998682496, 14043160393230480064, 14025023548310227456], [14035425723705288192, 14039535150626052992, 14047663992857850560, 14029527147937597952], [14039929323332658688, 14044038750253423488, 4825351971665025680, 14034030747564968448], [14044432922960029184, 4822821201433184544, 14046480716623222240, 14038534347192338944], [14048936522587399680, 14041544886296566720, 4827472002988927536, 14043037946819709440], [4822962310939830304, 14046048485923937216, 14024179730417904640, 14047541546447079936], [4827465910567200800, 4818751858897883456, 14028683330045275136, 4822209028525119520], [14032278119171423488, 4823255458525253952, 14033186929672645632, 14048928941319923696], [14036781718798793984, 14039807857928289088, 14037690529300016128, 4814467296781058240], [14041285318426164480, 14044311457555659584, 14042194128927386624, 4818970896408428736], [14045788918053534976, 4822275786828712352, 14046697728554757120, 4823474496035799232], [14050292517680905472, 14042975091427831008, 4827254991057392656, 14047544178687245968], [4816225059845183552, 14047478691055201504, 14033307241418768256, 4822198499564455392], [4820728659472554048, 4793112746123274240, 14037810841046138752, 14048939470280587824], [4825232259099924544, 4797616345750644736, 14042314440673509248, 4814383065095745216], [14047195246046990224, 4802119945378015232, 14046818040300879744, 4818886664723115712], [4826641309007634672, 4806623545005385728, 4827043876778967312, 4823390264350486208], [14041830471247919296, 4811127144632756224, 14036685069873573760, 14047712642057872016], [14046334070875289792, 4815630744260126720, 14041188669500944256, 4821524646081951200], [14050837670502660288, 4820134343887497216, 14045692269128314752, 4826028245709321696], [4808914943734769920, 14046992607539419152, 14050195868755685248, 14026522958372178432], [4813418543362140416, 4813479785046114176, 4815590876363392064, 14031026557999548928], [4817922142989510912, 4817983384673484672, 4820094475990762560, 14035530157626919424], [4822425742616881408, 4822486984300855168, 4824598075618133056, 14040033757254289920], [4826929342244251904, 14042552696483545376, 14048111769289684880, 14044537356881660416], [14039526205354981440, 14047056296110915872, 4824456418801357040, 14049040956509030912], [14044029804982351936, 4812460767902166656, 14048395082923236912, 4812794348877340800], [14048533404609722432, 4816964367529537152, 4823889791534252976, 4817297948504711296], [4823964991882170256, 4821467967156907648, 14049528337457445040, 4821801548132081792], [14049729780482498800, 14044590730771440416, 4819891364017872224, 14049336421712961424], [4819789279359433824, 4821717240397150688, 4824394963645242720, 4806289409197215488], [4824292878986804320, 14044092184290954336, 14048517993235465552, 4810793008824585984], [14049074006273230672, 4822714333358122848, 4823643970909795696, 4815296608451956480], [4822412376196506336, 14041972358596813504, 14050019978706359600, 4819800208079326976], [4826915975823876832, 14046475958224184000, 4816997996757997248, 4824303807706697472], [14039633136717982016, 4817041969696896320, 4821501596385367744, 14045043872922321952], [14044136736345352512, 4821545569324266816, 4826005196012738240, 4826094096922721264], [14048640335972723008, 14044435526436722080, 14043867819232372000, 14020407721797487616], [4823751129156169104, 4822027649066587360, 14048371418859742496, 14024911321424858112], [14050157505934501104, 14043471366952080992, 4823937119661241808, 14029414921052228608], [4817305153816418496, 4823655584474835376, 14049433681203467376, 14033918520679599104], [4821808753443788992, 14036291601257817472, 4820269989033782880, 14038422120306969600], [4826312353071159488, 14040795200885187968, 4824773588661153376, 14042925719934340096], [14043342878440463648, 14045298800512558464, 14047760743203644240, 14047429319561710592], [14047846478067834144, 4820301100914914592, 4825158470973438320, 4822657936066596896], [4825338844965946832, 14046825850512001776, 14046990978579074352, 14048480033778446320], [14046982074314945648, 4815247949571926208, 4826698000222578096, 4818058557112877248], [4827067652471723824, 4819751549199296704, 14039969566644818624, 4822562156740247744], [14038419723535206080, 14047375402227619664, 14044473166272189120, 14048575813104795472], [14042923323162576576, 4804390673671925248, 14048976765899559616, 4817292322502084032], [14047426922789947072, 4808894273299295744, 4822097650249413920, 4821795922129454528], [4826177955521720976, 4813397872926666240, 4826601249876784416, 14049342047715588688], [14043880468638217696, 4817901472554036736, 14040743569411168064, 4806109377113143040], [14048384068265588192, 4822405072181407232, 14045247169038538560, 4810612976740513536], [4824263664570438736, 14042716520722441248, 14049750768665909056, 4815116576367884032], [14049132435105961840, 14047220120349811744, 4819001639184016160, 4819620175995254528], [4822178660865581664, 4809834758127975680, 4823505238811386656, 4824123775622625024], [4826682260492952160, 4814338357755346176, 14050297442903177680, 14045764001258611744], [14041502859365379392, 4818841957382716672, 4814778283183452608, 4825373968586431472], [14046006458992749888, 4823345557010087168, 4819281882810823104, 14039302820665565376], [14050510058620120384, 14039447463988956224, 4823785482438193600, 14043806420292935872], [4814484732331464256, 14043951063616326720, 14049736955649563792, 14048310019920306368], [4818988331958834752, 4822996574707378080, 4819056891249397216, 4819135134632213792], [4823491931586205248, 14040843393199792576, 4823560490876767712, 4823638734259584288], [14050675901074428816, 14045346992827163072, 14050186938772415568, 14047215702239675856], [4811967983734933376, 4820204716285705376, 4815662316229549504, 4823433803134268528], [4816471583362303872, 14046922235141210992, 4820165915856920000, 14047625564490307376], [4820975182989674368, 4814476872538252480, 4824669515484290496, 4821872956352209760], [4825478782617044864, 4818980472165622976, 14047968889557370000, 14049265013492833456], [14046677160256922144, 4823484071792993472, 4824742178265986800, 4808574472241310464], [4827627403076115952, 14038377921340561984, 14047823563993977392, 4813078071868680960], [14025507878513182208, 14042881520967932480, 4825032829392772016, 4817581671496051456], [14030011478140552704, 14047385120595302976, 14047242261740406960, 4822085271123421952], [4607182418800017408, 4607182418800017408, 4607182418800017408, 4607182418800017408], [4607182418800017408, 4607182418800017408, 4607182418800017408, 4607182418800017408], [4611686018427387904, 4611686018427387904, 4611686018427387904, 4611686018427387904], [4611686018427387904, 4611686018427387904, 4611686018427387904, 4611686018427387904], [4616189618054758400, 4616189618054758400, 4616189618054758400, 4616189618054758400], [4616189618054758400, 4616189618054758400, 4616189618054758400, 4616189618054758400], [4620693217682128896, 4620693217682128896, 4620693217682128896, 4620693217682128896], [4620693217682128896, 4620693217682128896, 4620693217682128896, 4620693217682128896], [4625196817309499392, 4625196817309499392, 4625196817309499392, 4625196817309499392], [4625196817309499392, 4625196817309499392, 4625196817309499392, 4625196817309499392], [4629700416936869888, 4629700416936869888, 4629700416936869888, 4629700416936869888], [4629700416936869888, 4629700416936869888, 4629700416936869888, 4629700416936869888], [4634204016564240384, 4634204016564240384, 4634204016564240384, 4634204016564240384], [4634204016564240384, 4634204016564240384, 4634204016564240384, 4634204016564240384], [4638707616191610880, 4638707616191610880, 4638707616191610880, 4638707616191610880], [4638707616191610880, 4638707616191610880, 4638707616191610880, 4638707616191610880], [4643211215818981376, 4643211215818981376, 4643211215818981376, 4643211215818981376], [4643211215818981376, 4643211215818981376, 4643211215818981376, 4643211215818981376], [4647714815446351872, 4647714815446351872, 4647714815446351872, 4647714815446351872], [4647714815446351872, 4647714815446351872, 4647714815446351872, 4647714815446351872], [4652218415073722368, 4652218415073722368, 4652218415073722368, 4652218415073722368], [4652218415073722368, 4652218415073722368, 4652218415073722368, 4652218415073722368], [4656722014701092864, 4656722014701092864, 4656722014701092864, 4656722014701092864], [4656722014701092864, 4656722014701092864, 4656722014701092864, 4656722014701092864], [4661225614328463360, 4661225614328463360, 4661225614328463360, 4661225614328463360], [4661225614328463360, 4661225614328463360, 4661225614328463360, 4661225614328463360], [4665729213955833856, 4665729213955833856, 4665729213955833856, 4665729213955833856], [4665729213955833856, 4665729213955833856, 4665729213955833856, 4665729213955833856], [4670232813583204352, 4670232813583204352, 4670232813583204352, 4670232813583204352], [4670232813583204352, 4670232813583204352, 4670232813583204352, 4670232813583204352], [4674736413210574848, 4674736413210574848, 4674736413210574848, 4674736413210574848], [4674736413210574848, 4674736413210574848, 4674736413210574848, 4674736413210574848], [4679240012837945344, 4679240012837945344, 4679240012837945344, 4679240012837945344], [4679240012837945344, 4679240012837945344, 4679240012837945344, 4679240012837945344], [4683743612465315840, 4683743612465315840, 4683743612465315840, 4683743612465315840], [4683743612465315840, 4683743612465315840, 4683743612465315840, 4683743612465315840], [4688247212092686336, 4688247212092686336, 4688247212092686336, 4688247212092686336], [4688247212092686336, 4688247212092686336, 4688247212092686336, 4688247212092686336], [4692750811720056832, 4692750811720056832, 4692750811720056832, 4692750811720056832], [4692750811720056832, 4692750811720056832, 4692750811720056832, 4692750811720056832], [4697254411347427328, 4697254411347427328, 4697254411347427328, 4697254411347427328], [4697254411347427328, 4697254411347427328, 4697254411347427328, 4697254411347427328], [4701758010974797824, 4701758010974797824, 4701758010974797824, 4701758010974797824], [4701758010974797824, 4701758010974797824, 4701758010974797824, 4701758010974797824], [4706261610602168320, 4706261610602168320, 4706261610602168320, 4706261610602168320], [4706261610602168320, 4706261610602168320, 4706261610602168320, 4706261610602168320], [4710765210229538816, 4710765210229538816, 4710765210229538816, 4710765210229538816], [4710765210229538816, 4710765210229538816, 4710765210229538816, 4710765210229538816], [4715268809856909312, 4715268809856909312, 4715268809856909312, 4715268809856909312], [4715268809856909312, 4715268809856909312, 4715268809856909312, 4715268809856909312], [4719772409484279808, 4719772409484279808, 4719772409484279808, 4719772409484279808], [4719772409484279808, 4719772409484279808, 4719772409484279808, 4719772409484279808], [4724276009111650304, 4724276009111650304, 4724276009111650304, 4724276009111650304], [4724276009111650304, 4724276009111650304, 4724276009111650304, 4724276009111650304], [4728779608739020800, 4728779608739020800, 4728779608739020800, 4728779608739020800], [4728779608739020800, 4728779608739020800, 4728779608739020800, 4728779608739020800], [4733283208366391296, 4733283208366391296, 4733283208366391296, 4733283208366391296], [4733283208366391296, 4733283208366391296, 4733283208366391296, 4733283208366391296], [4737786807993761792, 4737786807993761792, 4737786807993761792, 4737786807993761792], [4737786807993761792, 4737786807993761792, 4737786807993761792, 4737786807993761792], [4742290407621132288, 4742290407621132288, 4742290407621132288, 4742290407621132288], [4742290407621132288, 4742290407621132288, 4742290407621132288, 4742290407621132288], [4746794007248502784, 4746794007248502784, 4746794007248502784, 4746794007248502784], [4746794007248502784, 4746794007248502784, 4746794007248502784, 4746794007248502784], [4751297606875873280, 4751297606875873280, 4751297606875873280, 4751297606875873280], [4751297606875873280, 4751297606875873280, 4751297606875873280, 4751297606875873280], [4755801206503243776, 4755801206503243776, 4755801206503243776, 4755801206503243776], [4755801206503243776, 4755801206503243776, 4755801206503243776, 4755801206503243776], [4760304806130614272, 4760304806130614272, 4760304806130614272, 4760304806130614272], [4760304806130614272, 4760304806130614272, 4760304806130614272, 4760304806130614272], [4764808405757984768, 4764808405757984768, 4764808405757984768, 4764808405757984768], [4764808405757984768, 4764808405757984768, 4764808405757984768, 4764808405757984768], [4769312005385355264, 4769312005385355264, 4769312005385355264, 4769312005385355264], [4769312005385355264, 4769312005385355264, 4769312005385355264, 4769312005385355264], [4773815605012725760, 4773815605012725760, 4773815605012725760, 4773815605012725760], [4773815605012725760, 4773815605012725760, 4773815605012725760, 4773815605012725760], [4778319204640096256, 4778319204640096256, 4778319204640096256, 4778319204640096256], [4778319204640096256, 4778319204640096256, 4778319204640096256, 4778319204640096256], [4782822804267466752, 4782822804267466752, 4782822804267466752, 4782822804267466752], [4782822804267466752, 4782822804267466752, 4782822804267466752, 4782822804267466752], [4787326403894837248, 4787326403894837248, 4787326403894837248, 4787326403894837248], [4787326403894837248, 4787326403894837248, 4787326403894837248, 4787326403894837248], [4791830003522207744, 4791830003522207744, 4791830003522207744, 4791830003522207744], [4791830003522207744, 4791830003522207744, 4791830003522207744, 4791830003522207744], [4796333603149578240, 4796333603149578240, 4796333603149578240, 4796333603149578240], [4796333603149578240, 4796333603149578240, 4796333603149578240, 4796333603149578240], [4800837202776948736, 4800837202776948736, 4800837202776948736, 4800837202776948736], [4800837202776948736, 4800837202776948736, 4800837202776948736, 4800837202776948736], [4805340802404319232, 4805340802404319232, 4805340802404319232, 4805340802404319232], [4805340802404319232, 4805340802404319232, 4805340802404319232, 4805340802404319232], [4809844402031689728, 4809844402031689728, 4809844402031689728, 4809844402031689728], [4809844402031689728, 4809844402031689728, 4809844402031689728, 4809844402031689728], [4814348001659060224, 4814348001659060224, 4814348001659060224, 4814348001659060224], [4814348001659060224, 4814348001659060224, 4814348001659060224, 4814348001659060224], [4818851601286430720, 4818851601286430720, 4818851601286430720, 4818851601286430720], [4818851601286430720, 4818851601286430720, 4818851601286430720, 4818851601286430720], [4823355200913801216, 4823355200913801216, 4823355200913801216, 4823355200913801216], [4823355200913801216, 4823355200913801216, 4823355200913801216, 4823355200913801216], [14050949362419236880, 14039408888374100032, 14050597518698348560, 14047782768931242000], [14041942163164495936, 14049577171907772432, 14049436434419417104, 14047114265861554192], [4805340802404318720, 14043912488001470528, 4810407351985110912, 4821244138588471264], [14046445762791866432, 4816459063984390080, 4817022013937811392, 4822581144727846880], [4809844402031689216, 4823073725937090464, 4814910951612481408, 4825747738215841760], [4819273813751496608, 4820962663611760576, 4821525613565181888, 14047888322047508528], [4814348001659059712, 14040534788280943040, 4819414551239851904, 14034905288746730112], [4823777413378867104, 4825466263239131072, 4826029213192552384, 4819484919984029536], [4818851601286430208, 14045038387908313536, 4823918150867222400, 14039408888374100608], [14038564463443968832, 14043982856745648416, 14040675525769298496, 4823988519611400032], [4823355200913800704, 4820821926123404448, 14049471618791506192, 14043912488001471104], [14043068063071339328, 14048486456373018912, 14045179125396668992, 14044968019164136096], [14050949362419237392, 14045882812838446816, 4820118238681627616, 14048416087628841600], [14047571662698709824, 4822018194774424480, 14049682725024039488, 4825501447611219312], [4805340802404285952, 4819133076263137888, 4824621838308998112, 4818570126309715008], [4808718502124820736, 4826521794401794976, 4815051689100832320, 14033497913863186816], [4809844402031656448, 4823636675890508384, 14048064243907954768, 4823073725937085504], [4813222101752191232, 14036875613583722112, 4819555288728202816, 14038001513490557312], [4814348001659026944, 14036594138607049344, 4824551469564817264, 14048064243907957712], [4817725701379561728, 14041379213211092608, 4824058888355573312, 14042505113117927808], [4818851601286397440, 14041097738234419840, 14048204981396316464, 4820118238681608416], [4822229301006932224, 14045882812838463104, 14048029059535872912, 14047008712745298304], [4823355200913767936, 14045601337861790336, 4824269994588093872, 4824621838308978912], [14044334700466589216, 14050386412465833600, 4823460754030049520, 4823003357192870432], [14050949362419270160, 4819696026216450848, 14048767931349763248, 14043771750513196192], [4823425569657926128, 4791830003512971264, 14049225328186920496, 14047466109582484976], [4805340802402188800, 14047430925210465520, 4822932988448599392, 14048275350140566688], [14041379213211496640, 4796333603140341760, 4818710863797784256, 4821173769844123744], [4809844402029559296, 4800837202762632192, 4827436588075969888, 4819273813751172512], [14045882812838867136, 4800837202767712256, 4823214463425154752, 4825677369471494240], [4814348001656929792, 4805340802390002688, 14026461039454104064, 4823777413378543008], [4820399713657495200, 4805340802395082752, 14049577171908063568, 14027586939363125760], [4818851601284300288, 4809844402017373184, 14030964639081474560, 14046938344001758416], [14047360556467020144, 4809844402022453248, 4815896114028639680, 14032090538990496256], [4823355200911670784, 4814348001644743680, 14035468238708845056, 4823988519610103408], [4812659151785290112, 4814348001649823744, 4820399713656010176, 14036594138617866752], [14050949362421367312, 4818851601272114176, 14039971838336215552, 14046305025308698208], [4817162751412660608, 4818851601277194240, 4824903313283380672, 14041097738245237248], [4805340802267971072, 4823355200899484672, 14044475437963586048, 4824832944536345008], [4821666351040031104, 4823355200904564736, 14045953181591939360, 14045601337872607744], [4809844401895341568, 14039408888431366208, 14048979037590956544, 14042927325603731808], [14045460600400391456, 14049577171917008912, 4826838453741278960, 4824868128902747664], [4814348001522712064, 14043912488058736704, 4822088563483826208, 14047430925231102304], [4821244138534446560, 4816459063910498240, 14027586939948516864, 14040675525856284608], [4818851601150082560, 4823073725822558112, 4826592163111196704, 4822651513389030048], [14046305025411560544, 4820962663537868736, 14032090539575887360, 14045179125483655104], [4823355200777453056, 14040534788739072448, 14040816263535869760, 14048486456456013168], [4819555288512108384, 4825466263165239232, 14036594139203257856, 4825290341291700304], [14050949362555585040, 14045038388366442944, 14045319863163240256, 4818007175692342464], [4824058888139478880, 14043982857041215776, 14041097738830628352, 14036875614975490944], [4805340793678036480, 4820821925207145632, 14049823462790610752, 4822510775319712960], [14034905292204313216, 14048486456668586272, 14045601338457998848, 14041379214602861440], [4809844393305406976, 14045882814670964448, 4818570124083988032, 14048627194525330256], [14039408891831683712, 4822018193592155040, 14050104938085369344, 14045882814230231936], [4814347992932777472, 4819133072598102624, 4823073723711358528, 4816881271137805760], [14043912491459054208, 4826521793219525536, 4808155533090963712, 4824586652545123472], [4818851592560147968, 4823636672225473120, 14050878995900791248, 4821384870765176256], [4823847778665461136, 14036875632500033152, 4812659132718334208, 14042575487429242336], [4823355192187518464, 14036594197247613568, 4796333033362176000, 4825888470392546752], [14038001541151216576, 14041379232127403648, 4817162732345704704, 14047079087056612832], [14050949371145519632, 14041097796874984064, 4800836632989546496, 14032090708952434944], [14042505140778587072, 14045882831754774144, 4821666331973075200, 4822721859947612320], [4805340243922222592, 14045601396502354560, 4805340232616916992, 14036594308579805440], [14047008740405957568, 14050386431382144640, 4826169931600445696, 14047747606827743088], [4809843843549593088, 4819695908935322400, 4809843832244287488, 14041097908207175936], [4816318105210675776, 4791820318361718784, 14039549778506152000, 4820047780863091296], [4814347443176963584, 14047431042491593968, 4814347431871657984, 14045601507834546432], [4820821704838046272, 4796323917989089280, 14044053378133522496, 4824551380490461792], [4818851042804334080, 4800822190778190848, 4818851031499028480, 4825536462010496784], [14046938565286469072, 4800827517616459776, 14048556977760892992, 14042716575647889056], [4823354642431704576, 4805325790405561344, 4823354631126398976, 14038002873273042880], [4816879506166583744, 4805331117243830272, 4821454634246217504, 14047220175275259552], [14050949920901333520, 4809829390032931840, 14050598088485750800, 14042506472900413376], [4821383105793954240, 4809834716871200768, 4825958233873588000, 4822157507073025440], [4805305059550133760, 4814332989660302336, 4810398235386675072, 14047010072527783872], [14046027090892545184, 4814338316498571264, 14041243360321013568, 14048311959702329968], [4809808659177504256, 4818836589287672832, 4814901835014045568, 4823845062558052496], [4820111157550139104, 4818841916125941760, 14045746959948384064, 4816729137443056832], [4814312258804874752, 4823340188915043328, 4819405434641416064, 14046803045642739440], [14047649112574376240, 4823345515753312256, 14050250559575754560, 4821232737070427328], [4818815858432245248, 14039468936369131584, 4823909034268786560, 4824259116328141360], [4806240106103495424, 14049586857068261392, 4801650488392954368, 4825736336697797824], [4823319458059615744, 14043972535996502080, 14049489851988377872, 14045222638436546400], [4810743705730865920, 4816381582700478400, 4806154088020324864, 14023416834127668224], [14050985105273422352, 4822953629947027360, 4820045305894140896, 4825915331408496816], [4815247305358236416, 4820885182327848896, 4810657687647695360, 14027920433755038720], [4803053259736448512, 14041015172241195456, 4824548905521511392, 14031231156442032896], [4819750904985606912, 4825388781955219392, 4815161287275065856, 14032424033382409216], [4807556859363819008, 14045518771868565952, 14048210109482928208, 14035734756069403392], [4824254504612977408, 14044292781881295136, 4819664886902436352, 14036927633009779712], [4812060458991189504, 4819861158202899616, 4824259738414870384, 14040238355696773888], [14030334418370208000, 14048796381508665632, 4824168486529806848, 14041431232637150208], [4816564058618560000, 14047265793224016752, 14048788443696210224, 14044741955324144384], [14034838017997578496, 4820778494231837600, 14047809863187405840, 14045934832264520704], [4821067658245930496, 4808373226153415424, 4822850939062811488, 14049245554951514880], [14039341617624948992, 4825282093859208096, 4823899146726983664, 4824534634510834704], [4825571257873300992, 4812876825780785920, 4827354538690181984, 4809197145563504896], [14043845217252319488, 14044719534265340320, 14048348542793052208, 14042783559566397408], [14046307259231897632, 4817380425408156416, 14030212519701812480, 4813700745190875392], [4823915052872195856, 14049223133892710816, 4822288374117580640, 14047287159193767904], [14050810858859268128, 4821884025035526912, 14034716119329182976, 4818204344818245888], [14037206656480841600, 4819071484695656864, 4826791973744951136, 4821889571398992032], [4809772916323319040, 14043758615014201888, 14039219718956553472, 4822707944445616384], [14041710256108212096, 4823575084323027360, 14029637249486296320, 14048579895376363376], [4814276515950689536, 4823368336412714480, 14043723318583923968, 14048430025399426832], [14046213855735582592, 14049137405089320144, 14034140849113666816, 4814585652050789568], [4818780115578060032, 14039303804382793920, 14048226918211294464, 4818458624145033152], [4819737627864064288, 4819414399909219552, 14038644448741037312, 4819089251678160064], [4823283715205430528, 14043807404010164416, 4824226120958137872, 4822962223772403648], [4824241227491434784, 4823917999536590048, 14043148048368407808, 4823592851305530560], [14051020848127607568, 4823283893919702688, 14048855678609675248, 14048175746072639568], [14030759286259571968, 14048451574662194768, 14047651647995778304, 14046550692387613984], [4800694231360240640, 14039694116350494144, 4822581999408951392, 4819672230022880992], [14035262885886942464, 4822157721617721056, 4824215577110238736, 4823918774387741424], [4805197830987611136, 14044197715977864640, 4827085599036321888, 4824175829650251488], [14039766485514312960, 4826661321245091552, 14047715682026542064, 14045247000058770528], [4809701430614981632, 4822503269984302240, 14036017513755900544, 14045555785148105888], [14044270085141683456, 14034643184090976896, 4824087509048711216, 4825222466716584880], [4814205030242352128, 14042520125116651232, 14040521113383271040, 4825582184696937328], [4823490184982831888, 14039146783718347392, 14047971818149597104, 14037840823345586880], [4818708629869722624, 14047023724744021728, 14045024713010641536, 14037554145049201024], [14040862290612250560, 14043650383345717888, 4823575236802601136, 14042344422972957376], [4823212229497093120, 4812981909772472960, 14049528312638012032, 14042057744676571520], [14045365890239621056, 14048153982973088384, 14048996362641817264, 14046848022600327872], [4827715829124463616, 4817485509399843456, 4819891463295604256, 14046561344303942016], [4821433558855987360, 4823348088374146592, 4819697094722520416, 4823500659343276688], [14001762727133986816, 4821989109027213952, 4824395062922974752, 4824576625541101200], [14045926184768478944, 14049584284447427056, 4824200694349890912, 14046823349002603248], [14006266326761357312, 14043548447030827808, 14048517794680001488, 14043952601584707040], [4820312969798271584, 4816402163667153088, 14047745447547237712, 4823550006538725936], [14010769926388727808, 4823578504396088560, 4823644368020723824, 14048456201212077536], [14047447300326243760, 4820905763294523584, 4824027978007319920, 14046722071454832480], [14015273526016098304, 14037524882517766528, 14050019184484503344, 4818249217643827520], [4811271250037712256, 4825409362921894080, 14048090880232379696, 4823747395320522928], [14019777125643468800, 14042028482145137024, 4817004350532847296, 4822752817271198016], [4815774849665082752, 14044210458014596384, 4823319024360270688, 14045932516327644512], [14024280725270839296, 14046532081772507520, 4821507950160217792, 14048385152573845200], [4820278449292453248, 14048714057641966880, 14049472610972947632, 4824536950447710896], [14028784324898209792, 4816817475503602240, 4826011549787588288, 4818817606749686208], [14047481820832062096, 4821107789698632608, 4816732601509567168, 14042774295818892640], [14033287924525580288, 4821321075130972736, 14043842404132971808, 4823321206377056704], [4810718921944618880, 4825611389326003104, 4821236201136937664, 14047277895446263136], [14037791524152950784, 14044884514823310240, 14048346003760342304, 14047816763467986512], [4815222521571989376, 14043402352398160288, 4825739800764308160, 4821926626389011104], [14042295123780321280, 4821129672293411040, 4823987949860042192, 4821108160441493216], [4819726121199359872, 14047905952025530784, 14042607231668229408, 14048542840386344304], [14046798723407691776, 14045267320498433632, 14049332020805866608, 4825611760068863712], [4824229720826730368, 4823847706539089104, 14047110831295599904, 4814882091970942144], [4827434354286231568, 4820364060943164256, 4820676630624185952, 14037080939098378880], [14031127499530113280, 14048592160657196656, 4825297210510595536, 4819385691598312640], [14033252179524452224, 14046762890483752112, 4825180230251556448, 14041584538725749376], [14035631099157483776, 4821595377637713504, 14044377592683079904, 4823889291225683136], [14037755779151822720, 4815751629797923520, 14046947460022838096, 14046088138353119872], [14040134698784854272, 4826098977265084000, 14048881192310450400, 14045364932707003680], [14042259378779193216, 4820255229425294016, 4826785037335050608, 4825049831491923344], [14044638298412224768, 14040680363142466880, 4820157776047987872, 4825104534068351728], [14046762978406563712, 14046871722001622352, 14039273269745038528, 14041895917421630400], [4822888742510779936, 14045183962769837376, 4824661375675358368, 14038784284531452096], [4827505844288487696, 4814880977654961600, 14043776869372409024, 14046399517049000896], [14043015817458893792, 14049687562397207872, 14046824084896302800, 14043287884158822592], [14031000240090242816, 4819384577282332096, 14048280468999779520, 4824738452796042320], [14047519417086264288, 4815575940068906560, 4825870703309189744, 14047791483786193088], [14035503839717613312, 4823888176909702592, 4824119019381167760, 14043305292564942560], [4810117381877383808, 4820079539696277056, 14041943604836199616, 4819872273029291296], [14040007439344983808, 14031923805713418496, 14049069881763615472, 14047808892192313056], [4814620981504754304, 4824583139323647552, 14046447204463570112, 4824375872656661792], [14044511038972354304, 14036427405340788992, 4821725186793190496, 4821139645544187040], [4819124581132124800, 14047121295088079760, 4826344430869648208, 14043418606983089056], [14049014638599724800, 14040931004968159488, 4826228786420560992, 4825643245171557536], [4823628180759495296, 4825417020413991152, 14038153784352531904, 14047922206610459552], [4822649846890529824, 14045434604595529984, 14042973457601080992, 14036577177455277696], [14039758324398943296, 14044179828046208096, 14042657383979902400, 4819349381732225440], [4827153446517900320, 4820029492748971552, 14047477057228451488, 14041080777082648192], [14044261924026313792, 14048683427673578592, 14047160983607272896, 4823852981359595936], [14037733371165794112, 14047097458677944816, 4825725842923823824, 14045584376710018688], [4823498346098201552, 4821230309572185760, 4825196905887249552, 14045510172171352480], [14042236970793164608, 4811802166829703552, 14044985231588029664, 4825553593135024528], [14040797001689293248, 4825733909199556256, 14044778811176463840, 4824959294604002928], [14046740570420535104, 4816305766457074048, 14049488831215400160, 14037865824276820928], [14045300601316663744, 14042912272903947680, 14049282410803834336, 14039946200246242496], [4827550660260544912, 4820809366084444544, 4820049388986051744, 14042369423904191424], [4821564136701901984, 14047415872531318176, 4818254202862473536, 14044449799873612992], [14029566128984411904, 14045907932916366624, 4824552988613422240, 14046873023531561920], [14045665029076649696, 4824827865527514320, 4822757802489844032, 14048953399500983488], [14034069728611782400, 4819082836107298272, 14048201943299106512, 4824119160550496400], [4820835281181930080, 14046536447592115424, 14050033832843374288, 4807850070865504512], [14038573328239152896, 4823586435734668768, 4824276070782513776, 14045782461547126240], [14046924988942585264, 4826395925229458224, 4810137651433247616, 4812353670492875008], [14043076927866523392, 14037397981100483200, 14048755778960923440, 4825355508297916976], [4816988116917654208, 14038304779427473088, 4814641251060618112, 4816857270120245504], [14047580527493893888, 14041901580727853696, 4822981598003958624, 14039450502973681344], [4821491716545024704, 14042808379054843584, 4819144850687988608, 4821360869747616000], [4825870746113827344, 14046405180355224192, 4827485197631329120, 14043954102601051840], [14045809869390404256, 14047311978682214080, 4823648450315359104, 14049108597027739408], [14045109306269792224, 4817325081172735552, 14022490816190501888, 14048457702228422336], [4820545600554420960, 4825035653225722512, 14048849935616301328, 4800016192451673088], [14049612905897162720, 4821828680800106048, 14026994415817872384, 4818237209513069120], [14047214669570094384, 14045705296799282656, 4820282802824584160, 4804519792079043584], [4820256777700778144, 14043869303485043616, 14031498015445242880, 4822740809140439616], [4814670671897581248, 14050208896426653152, 4824786402451954656, 4809023391706414080], [4824760377328148640, 4823160094969944288, 14036001615072613376, 14048397160704603600], [4819174271524951744, 4807080665983567104, 14046420824917643424, 4813526991333784576], [14048139009590542032, 14040189312149527744, 14040505214699983872, 4818721541703619008], [4823677871152322240, 4811584265610937600, 4826370810415574896, 4818030590961155072], [4824753781920531056, 14044692911776898240, 14045008814327354368, 4823225141330989504], [14039360801256327744, 4816087865238308096, 14037942747985118400, 4822534190588525568], [14048152200405777200, 4821512878386235040, 14049512413954724864, 14047912828514053712], [14043864400883698240, 4820591464865678592, 14042446347612488896, 14047935276186829840], [4824727400290060720, 14044500908312785632, 4819955058028752928, 4820723900257224416], [4823895869240817104, 4825095064493049088, 14046949947239859392, 4819297103426744288], [14048204963666717872, 4821896885314460256, 4824458657656123424, 4825227499884594912], [14037513594582901632, 14045467651729976352, 4825618978622076560, 4823800703054114784], [4824621873768179376, 14043732894456335200, 14048390605213704144, 14040474570280257856], [14042017194210272128, 14049971251357346848, 14043090520237155808, 14045719285393277088], [14048416016710480560, 4823394056970581168, 4823898746953318512, 14044978169907628352], [14046520793837642624, 4812264855116529280, 14047594119864526304, 4824750181382078320], [4824199767680654000, 14039098039919860416, 14049510426619313968, 14049481769534998848], [4819123751659944224, 4816768454743899776, 4824330633372742736, 14041619106021639360], [14049260228885531312, 14043601639547230912, 4819963007370396512, 4793735012815390720], [4823627351287314720, 4821272054371270272, 14047485569501534064, 14046122705649009856], [4821667485747303776, 4823525311879685456, 4824466606997767008, 4798238612442761216], [14039764960176387904, 4825775653998640768, 4824547734098727216, 4824346761126345552], [4826171085374674272, 14038048000647026112, 14048374706530416976, 4802742212070131712], [14044268559803758400, 14042745293707609632, 14047051368049565104, 14043535053104354016], [14043907949226404512, 14042551600274396608, 4823930544319892848, 4807245811697502208], [4823491710320756944, 14047248893334980128, 4825416137002665136, 14048038652731724512], [14048411548853775008, 14047055199901767104, 14049446831886165296, 4811749411324872704], [14040850087908850112, 4825161823920190416, 14043901886714801504, 4818883597247165600], [4824208703394065104, 4812478307248546944, 4820217386302991200, 4816253010952243200], [14045353687536220608, 14045200614021411040, 14048405486342172000, 4823387196874536096], [14049242357458709104, 4816981906875917440, 4824720985930361696, 4820756610579613696], [4821457964262788256, 14049704213648781536, 4822060599921101472, 14047050273940084432], [4821738971454592608, 4821485506503287936, 14047865948665227600, 4825260210206984192], [14045877373954877152, 4815442730056317248, 4826564199548471968, 4822837112413725920], [4826242571081963104, 14044555652078679840, 4824948060050271600, 14040212887701143616], [4820410591425475168, 4819946329683687744, 14035071231330047616, 14047632354361629488], [14043622006397249184, 4821787397782671840, 14047411800425407792, 14044716487328514112], [14047349678699040176, 4824449929311058240, 14039574830957418112, 4820508790727545696], [14048125606024619680, 14043951869519912032, 4825856356529911216, 14049220086955884608], [4812833196072969600, 14047387715113258384, 14044078430584788608, 4825012390354916192], [4824780589052375760, 4822994962900207456, 14044463177163680096, 4809928261727681664], [4817336795700340096, 4824884180363633904, 14048582030212159104, 14039521434238936384], [14048098586142087792, 14040849840428475072, 14048966776791050592, 4814431861355052160], [4821840395327710592, 14046311188247637088, 4821354424441153056, 14044025033866306880], [4824834628817439536, 14045353440055845568, 4822137606683450016, 4818935460982422656], [14045112511825032480, 4826621184573936560, 4825858024068523552, 14048528633493677376], [14047990506611960240, 4820191821828340384, 4826641206310820512, 4823439060609793152], [4821940315685164512, 14035285370829456768, 14042045038761529152, 4814995747112277568], [4825050787877694640, 14046935129598575984, 14040423917938879296, 14047615049539258128], [14044912671110124640, 14039788970456827264, 14046548638388899648, 4819499346739648064], [14047558188491450032, 4814373716879332544, 14044927517566249792, 4821915016156406752], [4822339997114980192, 14044292570084197760, 4826242996944318672, 4824002946367018560], [4825915424118715056, 4818877316506703040, 14049431117193620288, 14049222953688636464], [14044113308250493280, 14048796169711568256, 14038965255755168192, 14044910312141661984], [14044930594250241376, 4823380916134073536, 4820280245073171232, 4809882394003651968], [4823646961874022064, 4820779341420227104, 14043468855382538688, 4825559154633693424], [14049434193877611872, 14039203166611921472, 4824783844700541728, 4814385993631022464], [14039608075482729152, 4825282941047597600, 14047972455009909184, 14031932764120736512], [4820971625778981536, 14043706766239291968, 14047740231124867536, 4818889593258392960], [14044111675110099648, 14044716145511782304, 4823573963081976976, 14036436363748107008], [4825475225406352032, 4823420185187624400, 4825199495130991728, 4823393192885763456], [4823648595014415696, 14049219745139152800, 14048998910083065584, 14040939963375477504], [14046691389099693472, 14038889014183514560, 14046908930263967536, 14047706784987317520], [14039595010359580096, 4819085039709888928, 4819686904957527136, 14045443563002848000], [4827613174233344624, 14043392613810885056, 4826862096852791728, 4821548074364169184], [14044098609986950592, 4823588639337259424, 4824190504584897632, 4825025903772507408], [14026418524450547200, 4823734337616031312, 14038656793603109568, 4826051673991539680], [4823661660137564752, 14049110295060856016, 14047765827077224272, 14039413326898206656], [14030922124077917696, 14035031550998682496, 14043160393230480064, 14025023548310227456], [14039490489374387648, 4819522840023076064, 4823987218947346800, 14043916926525577152], [14035425723705288192, 14039535150626052992, 14047663992857850560, 14029527147937597952], [14043994089001758144, 4824026439650446560, 14048172398352325936, 14048420526152947648], [14039929323332658688, 14044038750253423488, 4825351971665025680, 14034030747564968448], [4823766181122757200, 14048234694434481744, 4822992951880485728, 4815860605838115392], [14044432922960029184, 4822821201433184544, 14046480716623222240, 14038534347192338944], [14038654321492848064, 4823025242528573152, 14049798683452732592, 4820364205465485888], [14048936522587399680, 14041544886296566720, 4827472002988927536, 14043037946819709440], [14043157921120218560, 14049907130293000496, 4813900041683514752, 4824867805092856384], [4822962310939830304, 14046048485923937216, 14024179730417904640, 14047541546447079936], [14047661520747589056, 4813290792146070912, 4818403641310885248, 14040678116335414848], [4827465910567200800, 4818751858897883456, 14028683330045275136, 4822209028525119520], [4805843044560685312, 4817794391773441408, 4822907240938255744, 14045181715962785344], [14032278119171423488, 4823255458525253952, 14033186929672645632, 14048928941319923696], [4810346644188055808, 4822297991400811904, 14049884394394962576, 4825287750812570064], [14036781718798793984, 14039807857928289088, 14037690529300016128, 4814467296781058240], [4814850243815426304, 4826801591028182400, 4812528666607835008, 14036917062641574784], [14041285318426164480, 14044311457555659584, 14042194128927386624, 4818970896408428736], [4819353843442796800, 14031581296236581120, 4817032266235205504, 14041420662268945280], [14045788918053534976, 4822275786828712352, 14046697728554757120, 4823474496035799232], [4823857443070167296, 14036084895863951616, 4821535865862576000, 14045924261896315776], [14050292517680905472, 14042975091427831008, 4827254991057392656, 14047544178687245968], [14037924225913567296, 14040588495491322112, 4826039465489946496, 4824545204879039632], [4816225059845183552, 14047478691055201504, 14033307241418768256, 4822198499564455392], [14042427825540937792, 14045092095118692608, 14040593507390145600, 14042741278093577696], [4820728659472554048, 4793112746123274240, 14037810841046138752, 14048939470280587824], [14046931425168308288, 14049595694746063104, 14045097107017516096, 14047244877720948192], [4825232259099924544, 4797616345750644736, 14042314440673509248, 4814383065095745216], [4816936627111870016, 4816310881278064704, 14049600706644886592, 4822058697290270880], [14047195246046990224, 4802119945378015232, 14046818040300879744, 4818886664723115712], [4821440226739240512, 4820814480905435200, 4815707836134055488, 14048410769485084528], [4826641309007634672, 4806623545005385728, 4827043876778967312, 4823390264350486208], [14045912849001972640, 4825318080532805696, 4820211435761425984, 4815938659181020352], [14041830471247919296, 4811127144632756224, 14036685069873573760, 14047712642057872016], [4820339641331284192, 14044575587570949920, 4824715035388796480, 4820442258808390848], [14046334070875289792, 4815630744260126720, 14041188669500944256, 4821524646081951200], [14047420628793231152, 14049079187198320416, 14046706293170276128, 4824945858435761344], [14050837670502660288, 4820134343887497216, 14045692269128314752, 4826028245709321696], [4811697994565913984, 4819647271473218464, 4826085342162942192, 14040053689592175168], [4808914943734769920, 14046992607539419152, 14050195868755685248, 14026522958372178432], [4816201594193284480, 4824150871100588960, 14040226494006180032, 14044557289219545664], [4813418543362140416, 4813479785046114176, 4815590876363392064, 14031026557999548928], [4820705193820654976, 14047985831534196944, 14044730093633550528, 14049060888846916160], [4817922142989510912, 4817983384673484672, 4820094475990762560, 14035530157626919424], [14047055076303860368, 4823687947521756784, 14049233693260921024, 4803480021186998784], [4822425742616881408, 4822486984300855168, 4824598075618133056, 14040033757254289920], [4815947418027453376, 14048911678691861296, 4818643943205780032, 4807983620814369280], [4826929342244251904, 14042552696483545376, 14048111769289684880, 14044537356881660416], [4820451017654823872, 4820317305499054944, 4823147542833150528, 4812487220441739776], [14039526205354981440, 14047056296110915872, 4824456418801357040, 14049040956509030912], [14047309252469691472, 4824820905126425440, 14049644092500067792, 4816990820069110272], [14044029804982351936, 4812460767902166656, 14048395082923236912, 4812794348877340800], [4813480015742548864, 14046564289196470944, 4815360749292605888, 4821494419696480768], [14048533404609722432, 4816964367529537152, 4823889791534252976, 4817297948504711296], [4817983615369919360, 4826368083625102704, 4819864348919976384, 14048975047078874640], [4823964991882170256, 4821467967156907648, 14049528337457445040, 4821801548132081792], [4822487214997289856, 14038527512262317248, 4824367948547346880, 4807157348372987648], [14049729780482498800, 14044590730771440416, 4819891364017872224, 14049336421712961424], [14043818872485873952, 14043031111889687744, 14047410939152325776, 4811660948000358144], [4819789279359433824, 4821717240397150688, 4824394963645242720, 4806289409197215488], [4823941397638641392, 14047534711517058240, 4824696994797143792, 4816164547627728640], [4824292878986804320, 14044092184290954336, 14048517993235465552, 4810793008824585984], [14036785140217713024, 4824590187556034192, 14046752846652731952, 4820668147255099136], [14049074006273230672, 4822714333358122848, 4823643970909795696, 4815296608451956480], [14041288739845083520, 14047107198623306480, 4826013179796331440, 4825171746882469632], [4822412376196506336, 14041972358596813504, 14050019978706359600, 4819800208079326976], [14045792339472454016, 4825445213343537712, 14040803792939066048, 14038246582018508864], [4826915975823876832, 14046475958224184000, 4816997996757997248, 4824303807706697472], [4820580660390321440, 14044067056328021856, 14045307392566436544, 14042750181645879360], [14039633136717982016, 4817041969696896320, 4821501596385367744, 14045043872922321952], [14047179609734193904, 14048570655955392352, 14049810992193807040, 14047253781273249856], [14044136736345352512, 4821545569324266816, 4826005196012738240, 4826094096922721264], [4814951150584785088, 4821681396444930720, 4813703101826323584, 4822023083081064224], [14048640335972723008, 14044435526436722080, 14043867819232372000, 14020407721797487616], [4819454750212155584, 4826184996072301216, 4818206701453694080, 14048446383694291184], [4823751129156169104, 4822027649066587360, 14048371418859742496, 14024911321424858112], [4823958349839526080, 14039992212684729152, 4822710301081064576, 4815653745507367104], [14050157505934501104, 14043471366952080992, 4823937119661241808, 14029414921052228608], [14036513905003558016, 14044495812312099648, 14050081334252153744, 4820157345134737600], [4817305153816418496, 4823655584474835376, 14049433681203467376, 14033918520679599104], [14041017504630928512, 14048999411939470144, 4808910855753862912, 4824660944762108096], [4821808753443788992, 14036291601257817472, 4820269989033782880, 14038422120306969600], [14045521104258299008, 4819966372508619552, 4813414455381233408, 14042278318561303840], [4826312353071159488, 14040795200885187968, 4824773588661153376, 14042925719934340096], [4821123130818631456, 4824469972135990048, 4817918055008603904, 14046781918188674336], [14043342878440463648, 14045298800512558464, 14047760743203644240, 14047429319561710592], [14046547040843190752, 14047347629463394768, 4822421654635974400, 4823632868166583760], [14047846478067834144, 4820301100914914592, 4825158470973438320, 4822657936066596896], [4819071257648847968, 4824964351663361136, 4826925254263344896, 14046390624943401184], [4825338844965946832, 14046825850512001776, 14046990978579074352, 14048480033778446320], [4823574857276218464, 14045990503048728160, 14019854173440869376, 4824078841831954224], [14046982074314945648, 4815247949571926208, 4826698000222578096, 4818058557112877248], [14040184912265157952, 4826941869772845488, 14024357773068239872, 14044606730281919328], [4827067652471723824, 4819751549199296704, 14039969566644818624, 4822562156740247744], [14044688511892528448, 14025471913555629568, 14028861372695610368, 14049110329909289824], [14038419723535206080, 14047375402227619664, 14044473166272189120, 14048575813104795472], [4822788315550172576, 14029975513183000064, 14033364972322980864, 4799794383613219840], [14042923323162576576, 4804390673671925248, 14048976765899559616, 4817292322502084032], [14043216671380108512, 14034479112810370560, 14037868571950351360, 4804297983240590336], [14047426922789947072, 4808894273299295744, 4822097650249413920, 4821795922129454528], [14047720271007479008, 14038982712437741056, 14042372171577721856, 4808801582867960832], [4826177955521720976, 4813397872926666240, 4826601249876784416, 14049342047715588688], [4802585270084094464, 14043486312065111552, 14046875771205092352, 4813305182495331328], [14043880468638217696, 4817901472554036736, 14040743569411168064, 4806109377113143040], [4807088869711464960, 14047989911692482048, 4825767330691610640, 4817808782122701824], [14048384068265588192, 4822405072181407232, 14045247169038538560, 4810612976740513536], [4811592469338835456, 4823679787205186576, 14042497111959019488, 4822312381750072320], [4824263664570438736, 14042716520722441248, 14049750768665909056, 4815116576367884032], [4816096068966205952, 14048927999325001712, 14047000711586389984, 14048157085025283088], [14049132435105961840, 14047220120349811744, 4819001639184016160, 4819620175995254528], [4820599668593576448, 4820252022966493280, 4825517449929015376, 4817968134859431872], [4822178660865581664, 4809834758127975680, 4823505238811386656, 4824123775622625024], [14047160601530938896, 4824755622593863776, 14043496635009400544, 4822471734486802368], [4826682260492952160, 4814338357755346176, 14050297442903177680, 14045764001258611744], [4815103216210825152, 14046776328547647312, 14048000234636771040, 14047997732288553040], [14041502859365379392, 4818841957382716672, 4814778283183452608, 4825373968586431472], [4819606815838195648, 4826106953494856048, 4823518403828253264, 4819047279019851488], [14046006458992749888, 4823345557010087168, 4819281882810823104, 14039302820665565376], [4824110415465566144, 14040616553304290496, 14049110028590513008, 4823550878647221984], [14050510058620120384, 14039447463988956224, 4823785482438193600, 14043806420292935872], [14034080854986916992, 14045120152931660992, 4819242430927737440, 14046718583020848288], [4814484732331464256, 14043951063616326720, 14049736955649563792, 14048310019920306368], [14038584454614287488, 14049623752559031488, 4823746030555107936, 4823750883754507120], [4818988331958834752, 4822996574707378080, 4819056891249397216, 4819135134632213792], [14043088054241657984, 4816086418774317632, 14048654775136803664, 14045918562591707744], [4823491931586205248, 14040843393199792576, 4823560490876767712, 4823638734259584288], [14047591653869028480, 4820590018401688128, 4821063444742574816, 4824550904183647664], [14050675901074428816, 14045346992827163072, 14050186938772415568, 14047215702239675856], [4808078784674623744, 4825093618029058624, 4825567044369945312, 14042718480875145568], [4811967983734933376, 4820204716285705376, 4815662316229549504, 4823433803134268528], [4812582384301994240, 14045473437585938208, 14043298257245680800, 14047222080502516064], [4816471583362303872, 14046922235141210992, 4820165915856920000, 14047625564490307376], [4817085983929364736, 14049977037213308704, 14047801856873051296, 4822149886163999392], [4820975182989674368, 4814476872538252480, 4824669515484290496, 4821872956352209760], [4821589583556735232, 4812172281421139584, 4823915159355692752, 14048319580611356016], [4825478782617044864, 4818980472165622976, 14047968889557370000, 14049265013492833456], [14045614135366983200, 4816675881048510080, 14048316517535634032, 4816668170170848448], [14046677160256922144, 4823484071792993472, 4824742178265986800, 4808574472241310464], [4820937068601263072, 4821179480675880576, 4822416475147253344, 4821171769798218944], [4827627403076115952, 14038377921340561984, 14047823563993977392, 4813078071868680960], [14046823201523252272, 4825683080303251072, 4826920074774623840, 4825675369425589440], [14025507878513182208, 14042881520967932480, 4825032829392772016, 4817581671496051456], [4817802416272318144, 14043115588489168416, 14020517147997164544, 14027714942301032960], [14030011478140552704, 14047385120595302976, 14047242261740406960, 4822085271123421952], [4822306015899688640, 14047619188116538912, 14025020747624535040, 14032218541928403456], ], vec_two_pow_tab_offsets: [0, 256], slow_two_pow_backing: [ 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14050949362419236880, 4805340802404318720, 4809844402031689216, 4814348001659059712, 4818851601286430208, 4823355200913800704, 14050949362419237392, 4805340802404285952, 4809844402031656448, 4814348001659026944, 4818851601286397440, 4823355200913767936, 14050949362419270160, 4805340802402188800, 4809844402029559296, 4814348001656929792, 4818851601284300288, 4823355200911670784, 14050949362421367312, 4805340802267971072, 4809844401895341568, 4814348001522712064, 4818851601150082560, 4823355200777453056, 14050949362555585040, 4805340793678036480, 4809844393305406976, 4814347992932777472, 4818851592560147968, 4823355192187518464, 14050949371145519632, 4805340243922222592, 4809843843549593088, 4814347443176963584, 4818851042804334080, 4823354642431704576, 14050949920901333520, 4805305059550133760, 4809808659177504256, 4814312258804874752, 4818815858432245248, 4823319458059615744, 14050985105273422352, 4803053259736448512, 4807556859363819008, 4812060458991189504, 4816564058618560000, 4821067658245930496, 4825571257873300992, 14046307259231897632, 14050810858859268128, 4809772916323319040, 4814276515950689536, 4818780115578060032, 4823283715205430528, 14051020848127607568, 4800694231360240640, 4805197830987611136, 4809701430614981632, 4814205030242352128, 4818708629869722624, 4823212229497093120, 4827715829124463616, 14001762727133986816, 14006266326761357312, 14010769926388727808, 14015273526016098304, 14019777125643468800, 14024280725270839296, 14028784324898209792, 14033287924525580288, 14037791524152950784, 14042295123780321280, 14046798723407691776, 4827434354286231568, 14033252179524452224, 14037755779151822720, 14042259378779193216, 14046762978406563712, 4827505844288487696, 14031000240090242816, 14035503839717613312, 14040007439344983808, 14044511038972354304, 14049014638599724800, 4822649846890529824, 4827153446517900320, 14037733371165794112, 14042236970793164608, 14046740570420535104, 4827550660260544912, 14029566128984411904, 14034069728611782400, 14038573328239152896, 14043076927866523392, 14047580527493893888, 4825870746113827344, 14045109306269792224, 14049612905897162720, 4820256777700778144, 4824760377328148640, 14048139009590542032, 4824753781920531056, 14048152200405777200, 4824727400290060720, 14048204963666717872, 4824621873768179376, 14048416016710480560, 4824199767680654000, 14049260228885531312, 4821667485747303776, 4826171085374674272, 14043907949226404512, 14048411548853775008, 4824208703394065104, 14049242357458709104, 4821738971454592608, 4826242571081963104, 14043622006397249184, 14048125606024619680, 4824780589052375760, 14048098586142087792, 4824834628817439536, 14047990506611960240, 4825050787877694640, 14047558188491450032, 4825915424118715056, 14044930594250241376, 14049434193877611872, 4820971625778981536, 4825475225406352032, 14046691389099693472, 4827613174233344624, 14026418524450547200, 14030922124077917696, 14035425723705288192, 14039929323332658688, 14044432922960029184, 14048936522587399680, 4822962310939830304, 4827465910567200800, 14032278119171423488, 14036781718798793984, 14041285318426164480, 14045788918053534976, 14050292517680905472, 4816225059845183552, 4820728659472554048, 4825232259099924544, 14047195246046990224, 4826641309007634672, 14041830471247919296, 14046334070875289792, 14050837670502660288, 4808914943734769920, 4813418543362140416, 4817922142989510912, 4822425742616881408, 4826929342244251904, 14039526205354981440, 14044029804982351936, 14048533404609722432, 4823964991882170256, 14049729780482498800, 4819789279359433824, 4824292878986804320, 14049074006273230672, 4822412376196506336, 4826915975823876832, 14039633136717982016, 14044136736345352512, 14048640335972723008, 4823751129156169104, 14050157505934501104, 4817305153816418496, 4821808753443788992, 4826312353071159488, 14043342878440463648, 14047846478067834144, 4825338844965946832, 14046982074314945648, 4827067652471723824, 14038419723535206080, 14042923323162576576, 14047426922789947072, 4826177955521720976, 14043880468638217696, 14048384068265588192, 4824263664570438736, 14049132435105961840, 4822178660865581664, 4826682260492952160, 14041502859365379392, 14046006458992749888, 14050510058620120384, 4814484732331464256, 4818988331958834752, 4823491931586205248, 14050675901074428816, 4811967983734933376, 4816471583362303872, 4820975182989674368, 4825478782617044864, 14046677160256922144, 4827627403076115952, 14025507878513182208, 14030011478140552704, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14039408888374100032, 14043912488001470528, 4823073725937090464, 14040534788280943040, 14045038387908313536, 4820821926123404448, 14045882812838446816, 4819133076263137888, 4823636675890508384, 14036594138607049344, 14041097738234419840, 14045601337861790336, 4819696026216450848, 14047430925210465520, 4800837202762632192, 4805340802390002688, 4809844402017373184, 4814348001644743680, 4818851601272114176, 4823355200899484672, 14039408888431366208, 14043912488058736704, 4823073725822558112, 14040534788739072448, 14045038388366442944, 4820821925207145632, 14045882814670964448, 4819133072598102624, 4823636672225473120, 14036594197247613568, 14041097796874984064, 14045601396502354560, 4819695908935322400, 14047431042491593968, 4800822190778190848, 4805325790405561344, 4809829390032931840, 4814332989660302336, 4818836589287672832, 4823340188915043328, 14039468936369131584, 14043972535996502080, 4822953629947027360, 14041015172241195456, 14045518771868565952, 4819861158202899616, 14047265793224016752, 4808373226153415424, 4812876825780785920, 4817380425408156416, 4821884025035526912, 14043758615014201888, 4823368336412714480, 14039303804382793920, 14043807404010164416, 4823283893919702688, 14039694116350494144, 14044197715977864640, 4822503269984302240, 14042520125116651232, 14047023724744021728, 4812981909772472960, 4817485509399843456, 4821989109027213952, 14043548447030827808, 4823578504396088560, 14037524882517766528, 14042028482145137024, 14046532081772507520, 4816817475503602240, 4821321075130972736, 14044884514823310240, 4821129672293411040, 14045267320498433632, 4820364060943164256, 14046762890483752112, 4815751629797923520, 4820255229425294016, 14046871722001622352, 4814880977654961600, 4819384577282332096, 4823888176909702592, 14031923805713418496, 14036427405340788992, 14040931004968159488, 14045434604595529984, 4820029492748971552, 14047097458677944816, 4811802166829703552, 4816305766457074048, 4820809366084444544, 14045907932916366624, 4819082836107298272, 4823586435734668768, 14037397981100483200, 14041901580727853696, 14046405180355224192, 4817325081172735552, 4821828680800106048, 14043869303485043616, 4823160094969944288, 14040189312149527744, 14044692911776898240, 4821512878386235040, 14044500908312785632, 4821896885314460256, 14043732894456335200, 4823394056970581168, 14039098039919860416, 14043601639547230912, 4823525311879685456, 14038048000647026112, 14042551600274396608, 14047055199901767104, 4812478307248546944, 4816981906875917440, 4821485506503287936, 14044555652078679840, 4821787397782671840, 14043951869519912032, 4822994962900207456, 14040849840428475072, 14045353440055845568, 4820191821828340384, 14046935129598575984, 4814373716879332544, 4818877316506703040, 4823380916134073536, 14039203166611921472, 14043706766239291968, 4823420185187624400, 14038889014183514560, 14043392613810885056, 4823734337616031312, 14035031550998682496, 14039535150626052992, 14044038750253423488, 4822821201433184544, 14041544886296566720, 14046048485923937216, 4818751858897883456, 4823255458525253952, 14039807857928289088, 14044311457555659584, 4822275786828712352, 14042975091427831008, 14047478691055201504, 4793112746123274240, 4797616345750644736, 4802119945378015232, 4806623545005385728, 4811127144632756224, 4815630744260126720, 4820134343887497216, 14046992607539419152, 4813479785046114176, 4817983384673484672, 4822486984300855168, 14042552696483545376, 14047056296110915872, 4812460767902166656, 4816964367529537152, 4821467967156907648, 14044590730771440416, 4821717240397150688, 14044092184290954336, 4822714333358122848, 14041972358596813504, 14046475958224184000, 4817041969696896320, 4821545569324266816, 14044435526436722080, 4822027649066587360, 14043471366952080992, 4823655584474835376, 14036291601257817472, 14040795200885187968, 14045298800512558464, 4820301100914914592, 14046825850512001776, 4815247949571926208, 4819751549199296704, 14047375402227619664, 4804390673671925248, 4808894273299295744, 4813397872926666240, 4817901472554036736, 4822405072181407232, 14042716520722441248, 14047220120349811744, 4809834758127975680, 4814338357755346176, 4818841957382716672, 4823345557010087168, 14039447463988956224, 14043951063616326720, 4822996574707378080, 14040843393199792576, 14045346992827163072, 4820204716285705376, 14046922235141210992, 4814476872538252480, 4818980472165622976, 4823484071792993472, 14038377921340561984, 14042881520967932480, 14047385120595302976, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14050597518698348560, 4810407351985110912, 4814910951612481408, 4819414551239851904, 4823918150867222400, 14049471618791506192, 4820118238681627616, 4824621838308998112, 14048064243907954768, 4824551469564817264, 14048204981396316464, 4824269994588093872, 14048767931349763248, 4822932988448599392, 4827436588075969888, 14026461039454104064, 14030964639081474560, 14035468238708845056, 14039971838336215552, 14044475437963586048, 14048979037590956544, 4822088563483826208, 4826592163111196704, 14040816263535869760, 14045319863163240256, 14049823462790610752, 4818570124083988032, 4823073723711358528, 14050878995900791248, 4796333033362176000, 4800836632989546496, 4805340232616916992, 4809843832244287488, 4814347431871657984, 4818851031499028480, 4823354631126398976, 14050598088485750800, 4810398235386675072, 4814901835014045568, 4819405434641416064, 4823909034268786560, 14049489851988377872, 4820045305894140896, 4824548905521511392, 14048210109482928208, 4824259738414870384, 14048788443696210224, 4822850939062811488, 4827354538690181984, 14030212519701812480, 14034716119329182976, 14039219718956553472, 14043723318583923968, 14048226918211294464, 4824226120958137872, 14048855678609675248, 4822581999408951392, 4827085599036321888, 14036017513755900544, 14040521113383271040, 14045024713010641536, 14049528312638012032, 4819891463295604256, 4824395062922974752, 14048517794680001488, 4823644368020723824, 14050019184484503344, 4817004350532847296, 4821507950160217792, 4826011549787588288, 14043842404132971808, 14048346003760342304, 4823987949860042192, 14049332020805866608, 4820676630624185952, 4825180230251556448, 14046947460022838096, 4826785037335050608, 14039273269745038528, 14043776869372409024, 14048280468999779520, 4824119019381167760, 14049069881763615472, 4821725186793190496, 4826228786420560992, 14042973457601080992, 14047477057228451488, 4825725842923823824, 14044985231588029664, 14049488831215400160, 4820049388986051744, 4824552988613422240, 14048201943299106512, 4824276070782513776, 14048755778960923440, 4822981598003958624, 4827485197631329120, 14022490816190501888, 14026994415817872384, 14031498015445242880, 14036001615072613376, 14040505214699983872, 14045008814327354368, 14049512413954724864, 4819955058028752928, 4824458657656123424, 14048390605213704144, 4823898746953318512, 14049510426619313968, 4819963007370396512, 4824466606997767008, 14048374706530416976, 4823930544319892848, 14049446831886165296, 4820217386302991200, 4824720985930361696, 14047865948665227600, 4824948060050271600, 14047411800425407792, 4825856356529911216, 14044463177163680096, 14048966776791050592, 4822137606683450016, 4826641206310820512, 14040423917938879296, 14044927517566249792, 14049431117193620288, 4820280245073171232, 4824783844700541728, 14047740231124867536, 4825199495130991728, 14046908930263967536, 4826862096852791728, 14038656793603109568, 14043160393230480064, 14047663992857850560, 4825351971665025680, 14046480716623222240, 4827472002988927536, 14024179730417904640, 14028683330045275136, 14033186929672645632, 14037690529300016128, 14042194128927386624, 14046697728554757120, 4827254991057392656, 14033307241418768256, 14037810841046138752, 14042314440673509248, 14046818040300879744, 4827043876778967312, 14036685069873573760, 14041188669500944256, 14045692269128314752, 14050195868755685248, 4815590876363392064, 4820094475990762560, 4824598075618133056, 14048111769289684880, 4824456418801357040, 14048395082923236912, 4823889791534252976, 14049528337457445040, 4819891364017872224, 4824394963645242720, 14048517993235465552, 4823643970909795696, 14050019978706359600, 4816997996757997248, 4821501596385367744, 4826005196012738240, 14043867819232372000, 14048371418859742496, 4823937119661241808, 14049433681203467376, 4820269989033782880, 4824773588661153376, 14047760743203644240, 4825158470973438320, 14046990978579074352, 4826698000222578096, 14039969566644818624, 14044473166272189120, 14048976765899559616, 4822097650249413920, 4826601249876784416, 14040743569411168064, 14045247169038538560, 14049750768665909056, 4819001639184016160, 4823505238811386656, 14050297442903177680, 4814778283183452608, 4819281882810823104, 4823785482438193600, 14049736955649563792, 4819056891249397216, 4823560490876767712, 14050186938772415568, 4815662316229549504, 4820165915856920000, 4824669515484290496, 14047968889557370000, 4824742178265986800, 14047823563993977392, 4825032829392772016, 14047242261740406960, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14047782768931242000, 4821244138588471264, 4825747738215841760, 14034905288746730112, 14039408888374100608, 14043912488001471104, 14048416087628841600, 4818570126309715008, 4823073725937085504, 14048064243907957712, 4820118238681608416, 4824621838308978912, 14043771750513196192, 14048275350140566688, 4819273813751172512, 4823777413378543008, 14046938344001758416, 4823988519610103408, 14046305025308698208, 4824832944536345008, 14042927325603731808, 14047430925231102304, 4822651513389030048, 14048486456456013168, 4818007175692342464, 4822510775319712960, 14048627194525330256, 4816881271137805760, 4821384870765176256, 4825888470392546752, 14032090708952434944, 14036594308579805440, 14041097908207175936, 14045601507834546432, 4825536462010496784, 14038002873273042880, 14042506472900413376, 14047010072527783872, 4823845062558052496, 14046803045642739440, 4824259116328141360, 14045222638436546400, 4825915331408496816, 14031231156442032896, 14035734756069403392, 14040238355696773888, 14044741955324144384, 14049245554951514880, 4809197145563504896, 4813700745190875392, 4818204344818245888, 4822707944445616384, 14048430025399426832, 4818458624145033152, 4822962223772403648, 14048175746072639568, 4819672230022880992, 4824175829650251488, 14045555785148105888, 4825582184696937328, 14037554145049201024, 14042057744676571520, 14046561344303942016, 4824576625541101200, 14043952601584707040, 14048456201212077536, 4818249217643827520, 4822752817271198016, 14048385152573845200, 4818817606749686208, 4823321206377056704, 14047816763467986512, 4821108160441493216, 4825611760068863712, 14037080939098378880, 14041584538725749376, 14046088138353119872, 4825049831491923344, 14041895917421630400, 14046399517049000896, 4824738452796042320, 14043305292564942560, 14047808892192313056, 4821139645544187040, 4825643245171557536, 14036577177455277696, 14041080777082648192, 14045584376710018688, 4825553593135024528, 14037865824276820928, 14042369423904191424, 14046873023531561920, 4824119160550496400, 14045782461547126240, 4825355508297916976, 14039450502973681344, 14043954102601051840, 14048457702228422336, 4818237209513069120, 4822740809140439616, 14048397160704603600, 4818721541703619008, 4823225141330989504, 14047912828514053712, 4820723900257224416, 4825227499884594912, 14040474570280257856, 14044978169907628352, 14049481769534998848, 4793735012815390720, 4798238612442761216, 4802742212070131712, 4807245811697502208, 4811749411324872704, 4816253010952243200, 4820756610579613696, 4825260210206984192, 14040212887701143616, 14044716487328514112, 14049220086955884608, 4809928261727681664, 4814431861355052160, 4818935460982422656, 4823439060609793152, 14047615049539258128, 4821915016156406752, 14049222953688636464, 4809882394003651968, 4814385993631022464, 4818889593258392960, 4823393192885763456, 14047706784987317520, 4821548074364169184, 4826051673991539680, 14025023548310227456, 14029527147937597952, 14034030747564968448, 14038534347192338944, 14043037946819709440, 14047541546447079936, 4822209028525119520, 14048928941319923696, 4814467296781058240, 4818970896408428736, 4823474496035799232, 14047544178687245968, 4822198499564455392, 14048939470280587824, 4814383065095745216, 4818886664723115712, 4823390264350486208, 14047712642057872016, 4821524646081951200, 4826028245709321696, 14026522958372178432, 14031026557999548928, 14035530157626919424, 14040033757254289920, 14044537356881660416, 14049040956509030912, 4812794348877340800, 4817297948504711296, 4821801548132081792, 14049336421712961424, 4806289409197215488, 4810793008824585984, 4815296608451956480, 4819800208079326976, 4824303807706697472, 14045043872922321952, 4826094096922721264, 14020407721797487616, 14024911321424858112, 14029414921052228608, 14033918520679599104, 14038422120306969600, 14042925719934340096, 14047429319561710592, 4822657936066596896, 14048480033778446320, 4818058557112877248, 4822562156740247744, 14048575813104795472, 4817292322502084032, 4821795922129454528, 14049342047715588688, 4806109377113143040, 4810612976740513536, 4815116576367884032, 4819620175995254528, 4824123775622625024, 14045764001258611744, 4825373968586431472, 14039302820665565376, 14043806420292935872, 14048310019920306368, 4819135134632213792, 4823638734259584288, 14047215702239675856, 4823433803134268528, 14047625564490307376, 4821872956352209760, 14049265013492833456, 4808574472241310464, 4813078071868680960, 4817581671496051456, 4822085271123421952, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14041942163164495936, 14046445762791866432, 4819273813751496608, 4823777413378867104, 14038564463443968832, 14043068063071339328, 14047571662698709824, 4808718502124820736, 4813222101752191232, 4817725701379561728, 4822229301006932224, 14044334700466589216, 4823425569657926128, 14041379213211496640, 14045882812838867136, 4820399713657495200, 14047360556467020144, 4812659151785290112, 4817162751412660608, 4821666351040031104, 14045460600400391456, 4821244138534446560, 14046305025411560544, 4819555288512108384, 4824058888139478880, 14034905292204313216, 14039408891831683712, 14043912491459054208, 4823847778665461136, 14038001541151216576, 14042505140778587072, 14047008740405957568, 4816318105210675776, 4820821704838046272, 14046938565286469072, 4816879506166583744, 4821383105793954240, 14046027090892545184, 4820111157550139104, 14047649112574376240, 4806240106103495424, 4810743705730865920, 4815247305358236416, 4819750904985606912, 4824254504612977408, 14030334418370208000, 14034838017997578496, 14039341617624948992, 14043845217252319488, 4823915052872195856, 14037206656480841600, 14041710256108212096, 14046213855735582592, 4819737627864064288, 4824241227491434784, 14030759286259571968, 14035262885886942464, 14039766485514312960, 14044270085141683456, 4823490184982831888, 14040862290612250560, 14045365890239621056, 4821433558855987360, 14045926184768478944, 4820312969798271584, 14047447300326243760, 4811271250037712256, 4815774849665082752, 4820278449292453248, 14047481820832062096, 4810718921944618880, 4815222521571989376, 4819726121199359872, 4824229720826730368, 14031127499530113280, 14035631099157483776, 14040134698784854272, 14044638298412224768, 4822888742510779936, 14043015817458893792, 14047519417086264288, 4810117381877383808, 4814620981504754304, 4819124581132124800, 4823628180759495296, 14039758324398943296, 14044261924026313792, 4823498346098201552, 14040797001689293248, 14045300601316663744, 4821564136701901984, 14045665029076649696, 4820835281181930080, 14046924988942585264, 4816988116917654208, 4821491716545024704, 14045809869390404256, 4820545600554420960, 14047214669570094384, 4814670671897581248, 4819174271524951744, 4823677871152322240, 14039360801256327744, 14043864400883698240, 4823895869240817104, 14037513594582901632, 14042017194210272128, 14046520793837642624, 4819123751659944224, 4823627351287314720, 14039764960176387904, 14044268559803758400, 4823491710320756944, 14040850087908850112, 14045353687536220608, 4821457964262788256, 14045877373954877152, 4820410591425475168, 14047349678699040176, 4812833196072969600, 4817336795700340096, 4821840395327710592, 14045112511825032480, 4821940315685164512, 14044912671110124640, 4822339997114980192, 14044113308250493280, 4823646961874022064, 14039608075482729152, 14044111675110099648, 4823648595014415696, 14039595010359580096, 14044098609986950592, 4823661660137564752, 14039490489374387648, 14043994089001758144, 4823766181122757200, 14038654321492848064, 14043157921120218560, 14047661520747589056, 4805843044560685312, 4810346644188055808, 4814850243815426304, 4819353843442796800, 4823857443070167296, 14037924225913567296, 14042427825540937792, 14046931425168308288, 4816936627111870016, 4821440226739240512, 14045912849001972640, 4820339641331284192, 14047420628793231152, 4811697994565913984, 4816201594193284480, 4820705193820654976, 14047055076303860368, 4815947418027453376, 4820451017654823872, 14047309252469691472, 4813480015742548864, 4817983615369919360, 4822487214997289856, 14043818872485873952, 4823941397638641392, 14036785140217713024, 14041288739845083520, 14045792339472454016, 4820580660390321440, 14047179609734193904, 4814951150584785088, 4819454750212155584, 4823958349839526080, 14036513905003558016, 14041017504630928512, 14045521104258299008, 4821123130818631456, 14046547040843190752, 4819071257648847968, 4823574857276218464, 14040184912265157952, 14044688511892528448, 4822788315550172576, 14043216671380108512, 14047720271007479008, 4802585270084094464, 4807088869711464960, 4811592469338835456, 4816096068966205952, 4820599668593576448, 14047160601530938896, 4815103216210825152, 4819606815838195648, 4824110415465566144, 14034080854986916992, 14038584454614287488, 14043088054241657984, 14047591653869028480, 4808078784674623744, 4812582384301994240, 4817085983929364736, 4821589583556735232, 14045614135366983200, 4820937068601263072, 14046823201523252272, 4817802416272318144, 4822306015899688640, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14049577171907772432, 4816459063984390080, 4820962663611760576, 4825466263239131072, 14043982856745648416, 14048486456373018912, 4822018194774424480, 4826521794401794976, 14036875613583722112, 14041379213211092608, 14045882812838463104, 14050386412465833600, 4791830003512971264, 4796333603140341760, 4800837202767712256, 4805340802395082752, 4809844402022453248, 4814348001649823744, 4818851601277194240, 4823355200904564736, 14049577171917008912, 4816459063910498240, 4820962663537868736, 4825466263165239232, 14043982857041215776, 14048486456668586272, 4822018193592155040, 4826521793219525536, 14036875632500033152, 14041379232127403648, 14045882831754774144, 14050386431382144640, 4791820318361718784, 4796323917989089280, 4800827517616459776, 4805331117243830272, 4809834716871200768, 4814338316498571264, 4818841916125941760, 4823345515753312256, 14049586857068261392, 4816381582700478400, 4820885182327848896, 4825388781955219392, 14044292781881295136, 14048796381508665632, 4820778494231837600, 4825282093859208096, 14044719534265340320, 14049223133892710816, 4819071484695656864, 4823575084323027360, 14049137405089320144, 4819414399909219552, 4823917999536590048, 14048451574662194768, 4822157721617721056, 4826661321245091552, 14034643184090976896, 14039146783718347392, 14043650383345717888, 14048153982973088384, 4823348088374146592, 14049584284447427056, 4816402163667153088, 4820905763294523584, 4825409362921894080, 14044210458014596384, 14048714057641966880, 4821107789698632608, 4825611389326003104, 14043402352398160288, 14047905952025530784, 4823847706539089104, 14048592160657196656, 4821595377637713504, 4826098977265084000, 14040680363142466880, 14045183962769837376, 14049687562397207872, 4815575940068906560, 4820079539696277056, 4824583139323647552, 14047121295088079760, 4825417020413991152, 14044179828046208096, 14048683427673578592, 4821230309572185760, 4825733909199556256, 14042912272903947680, 14047415872531318176, 4824827865527514320, 14046536447592115424, 4826395925229458224, 14038304779427473088, 14042808379054843584, 14047311978682214080, 4825035653225722512, 14045705296799282656, 14050208896426653152, 4807080665983567104, 4811584265610937600, 4816087865238308096, 4820591464865678592, 4825095064493049088, 14045467651729976352, 14049971251357346848, 4812264855116529280, 4816768454743899776, 4821272054371270272, 4825775653998640768, 14042745293707609632, 14047248893334980128, 4825161823920190416, 14045200614021411040, 14049704213648781536, 4815442730056317248, 4819946329683687744, 4824449929311058240, 14047387715113258384, 4824884180363633904, 14046311188247637088, 4826621184573936560, 14035285370829456768, 14039788970456827264, 14044292570084197760, 14048796169711568256, 4820779341420227104, 4825282941047597600, 14044716145511782304, 14049219745139152800, 4819085039709888928, 4823588639337259424, 14049110295060856016, 4819522840023076064, 4824026439650446560, 14048234694434481744, 4823025242528573152, 14049907130293000496, 4813290792146070912, 4817794391773441408, 4822297991400811904, 4826801591028182400, 14031581296236581120, 14036084895863951616, 14040588495491322112, 14045092095118692608, 14049595694746063104, 4816310881278064704, 4820814480905435200, 4825318080532805696, 14044575587570949920, 14049079187198320416, 4819647271473218464, 4824150871100588960, 14047985831534196944, 4823687947521756784, 14048911678691861296, 4820317305499054944, 4824820905126425440, 14046564289196470944, 4826368083625102704, 14038527512262317248, 14043031111889687744, 14047534711517058240, 4824590187556034192, 14047107198623306480, 4825445213343537712, 14044067056328021856, 14048570655955392352, 4821681396444930720, 4826184996072301216, 14039992212684729152, 14044495812312099648, 14048999411939470144, 4819966372508619552, 4824469972135990048, 14047347629463394768, 4824964351663361136, 14045990503048728160, 4826941869772845488, 14025471913555629568, 14029975513183000064, 14034479112810370560, 14038982712437741056, 14043486312065111552, 14047989911692482048, 4823679787205186576, 14048927999325001712, 4820252022966493280, 4824755622593863776, 14046776328547647312, 4826106953494856048, 14040616553304290496, 14045120152931660992, 14049623752559031488, 4816086418774317632, 4820590018401688128, 4825093618029058624, 14045473437585938208, 14049977037213308704, 4812172281421139584, 4816675881048510080, 4821179480675880576, 4825683080303251072, 14043115588489168416, 14047619188116538912, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14049436434419417104, 4817022013937811392, 4821525613565181888, 4826029213192552384, 14040675525769298496, 14045179125396668992, 14049682725024039488, 4815051689100832320, 4819555288728202816, 4824058888355573312, 14048029059535872912, 4823460754030049520, 14049225328186920496, 4818710863797784256, 4823214463425154752, 14049577171908063568, 4815896114028639680, 4820399713656010176, 4824903313283380672, 14045953181591939360, 4826838453741278960, 14027586939948516864, 14032090539575887360, 14036594139203257856, 14041097738830628352, 14045601338457998848, 14050104938085369344, 4808155533090963712, 4812659132718334208, 4817162732345704704, 4821666331973075200, 4826169931600445696, 14039549778506152000, 14044053378133522496, 14048556977760892992, 4821454634246217504, 4825958233873588000, 14041243360321013568, 14045746959948384064, 14050250559575754560, 4801650488392954368, 4806154088020324864, 4810657687647695360, 4815161287275065856, 4819664886902436352, 4824168486529806848, 14047809863187405840, 4823899146726983664, 14048348542793052208, 4822288374117580640, 4826791973744951136, 14029637249486296320, 14034140849113666816, 14038644448741037312, 14043148048368407808, 14047651647995778304, 4824215577110238736, 14047715682026542064, 4824087509048711216, 14047971818149597104, 4823575236802601136, 14048996362641817264, 4819697094722520416, 4824200694349890912, 14047745447547237712, 4824027978007319920, 14048090880232379696, 4823319024360270688, 14049472610972947632, 4816732601509567168, 4821236201136937664, 4825739800764308160, 14042607231668229408, 14047110831295599904, 4825297210510595536, 14044377592683079904, 14048881192310450400, 4820157776047987872, 4824661375675358368, 14046824084896302800, 4825870703309189744, 14041943604836199616, 14046447204463570112, 4826344430869648208, 14038153784352531904, 14042657383979902400, 14047160983607272896, 4825196905887249552, 14044778811176463840, 14049282410803834336, 4818254202862473536, 4822757802489844032, 14050033832843374288, 4810137651433247616, 4814641251060618112, 4819144850687988608, 4823648450315359104, 14048849935616301328, 4820282802824584160, 4824786402451954656, 14046420824917643424, 4826370810415574896, 14037942747985118400, 14042446347612488896, 14046949947239859392, 4825618978622076560, 14043090520237155808, 14047594119864526304, 4824330633372742736, 14047485569501534064, 4824547734098727216, 14047051368049565104, 4825416137002665136, 14043901886714801504, 14048405486342172000, 4822060599921101472, 4826564199548471968, 14035071231330047616, 14039574830957418112, 14044078430584788608, 14048582030212159104, 4821354424441153056, 4825858024068523552, 14042045038761529152, 14046548638388899648, 4826242996944318672, 14038965255755168192, 14043468855382538688, 14047972455009909184, 4823573963081976976, 14048998910083065584, 4819686904957527136, 4824190504584897632, 14047765827077224272, 4823987218947346800, 14048172398352325936, 4822992951880485728, 14049798683452732592, 4813900041683514752, 4818403641310885248, 4822907240938255744, 14049884394394962576, 4812528666607835008, 4817032266235205504, 4821535865862576000, 4826039465489946496, 14040593507390145600, 14045097107017516096, 14049600706644886592, 4815707836134055488, 4820211435761425984, 4824715035388796480, 14046706293170276128, 4826085342162942192, 14040226494006180032, 14044730093633550528, 14049233693260921024, 4818643943205780032, 4823147542833150528, 14049644092500067792, 4815360749292605888, 4819864348919976384, 4824367948547346880, 14047410939152325776, 4824696994797143792, 14046752846652731952, 4826013179796331440, 14040803792939066048, 14045307392566436544, 14049810992193807040, 4813703101826323584, 4818206701453694080, 4822710301081064576, 14050081334252153744, 4808910855753862912, 4813414455381233408, 4817918055008603904, 4822421654635974400, 4826925254263344896, 14019854173440869376, 14024357773068239872, 14028861372695610368, 14033364972322980864, 14037868571950351360, 14042372171577721856, 14046875771205092352, 4825767330691610640, 14042497111959019488, 14047000711586389984, 4825517449929015376, 14043496635009400544, 14048000234636771040, 4823518403828253264, 14049110028590513008, 4819242430927737440, 4823746030555107936, 14048654775136803664, 4821063444742574816, 4825567044369945312, 14043298257245680800, 14047801856873051296, 4823915159355692752, 14048316517535634032, 4822416475147253344, 4826920074774623840, 14020517147997164544, 14025020747624535040, 4607182418800017408, 4611686018427387904, 4616189618054758400, 4620693217682128896, 4625196817309499392, 4629700416936869888, 4634204016564240384, 4638707616191610880, 4643211215818981376, 4647714815446351872, 4652218415073722368, 4656722014701092864, 4661225614328463360, 4665729213955833856, 4670232813583204352, 4674736413210574848, 4679240012837945344, 4683743612465315840, 4688247212092686336, 4692750811720056832, 4697254411347427328, 4701758010974797824, 4706261610602168320, 4710765210229538816, 4715268809856909312, 4719772409484279808, 4724276009111650304, 4728779608739020800, 4733283208366391296, 4737786807993761792, 4742290407621132288, 4746794007248502784, 4751297606875873280, 4755801206503243776, 4760304806130614272, 4764808405757984768, 4769312005385355264, 4773815605012725760, 4778319204640096256, 4782822804267466752, 4787326403894837248, 4791830003522207744, 4796333603149578240, 4800837202776948736, 4805340802404319232, 4809844402031689728, 4814348001659060224, 4818851601286430720, 4823355200913801216, 14047114265861554192, 4822581144727846880, 14047888322047508528, 4819484919984029536, 4823988519611400032, 14044968019164136096, 4825501447611219312, 14033497913863186816, 14038001513490557312, 14042505113117927808, 14047008712745298304, 4823003357192870432, 14047466109582484976, 4821173769844123744, 4825677369471494240, 14027586939363125760, 14032090538990496256, 14036594138617866752, 14041097738245237248, 14045601337872607744, 4824868128902747664, 14040675525856284608, 14045179125483655104, 4825290341291700304, 14036875614975490944, 14041379214602861440, 14045882814230231936, 4824586652545123472, 14042575487429242336, 14047079087056612832, 4822721859947612320, 14047747606827743088, 4820047780863091296, 4824551380490461792, 14042716575647889056, 14047220175275259552, 4822157507073025440, 14048311959702329968, 4816729137443056832, 4821232737070427328, 4825736336697797824, 14023416834127668224, 14027920433755038720, 14032424033382409216, 14036927633009779712, 14041431232637150208, 14045934832264520704, 4824534634510834704, 14042783559566397408, 14047287159193767904, 4821889571398992032, 14048579895376363376, 4814585652050789568, 4819089251678160064, 4823592851305530560, 14046550692387613984, 4823918774387741424, 14045247000058770528, 4825222466716584880, 14037840823345586880, 14042344422972957376, 14046848022600327872, 4823500659343276688, 14046823349002603248, 4823550006538725936, 14046722071454832480, 4823747395320522928, 14045932516327644512, 4824536950447710896, 14042774295818892640, 14047277895446263136, 4821926626389011104, 14048542840386344304, 4814882091970942144, 4819385691598312640, 4823889291225683136, 14045364932707003680, 4825104534068351728, 14038784284531452096, 14043287884158822592, 14047791483786193088, 4819872273029291296, 4824375872656661792, 14043418606983089056, 14047922206610459552, 4819349381732225440, 4823852981359595936, 14045510172171352480, 4824959294604002928, 14039946200246242496, 14044449799873612992, 14048953399500983488, 4807850070865504512, 4812353670492875008, 4816857270120245504, 4821360869747616000, 14049108597027739408, 4800016192451673088, 4804519792079043584, 4809023391706414080, 4813526991333784576, 4818030590961155072, 4822534190588525568, 14047935276186829840, 4819297103426744288, 4823800703054114784, 14045719285393277088, 4824750181382078320, 14041619106021639360, 14046122705649009856, 4824346761126345552, 14043535053104354016, 14048038652731724512, 4818883597247165600, 4823387196874536096, 14047050273940084432, 4822837112413725920, 14047632354361629488, 4820508790727545696, 4825012390354916192, 14039521434238936384, 14044025033866306880, 14048528633493677376, 4814995747112277568, 4819499346739648064, 4824002946367018560, 14044910312141661984, 4825559154633693424, 14031932764120736512, 14036436363748107008, 14040939963375477504, 14045443563002848000, 4825025903772507408, 14039413326898206656, 14043916926525577152, 14048420526152947648, 4815860605838115392, 4820364205465485888, 4824867805092856384, 14040678116335414848, 14045181715962785344, 4825287750812570064, 14036917062641574784, 14041420662268945280, 14045924261896315776, 4824545204879039632, 14042741278093577696, 14047244877720948192, 4822058697290270880, 14048410769485084528, 4815938659181020352, 4820442258808390848, 4824945858435761344, 14040053689592175168, 14044557289219545664, 14049060888846916160, 4803480021186998784, 4807983620814369280, 4812487220441739776, 4816990820069110272, 4821494419696480768, 14048975047078874640, 4807157348372987648, 4811660948000358144, 4816164547627728640, 4820668147255099136, 4825171746882469632, 14038246582018508864, 14042750181645879360, 14047253781273249856, 4822023083081064224, 14048446383694291184, 4815653745507367104, 4820157345134737600, 4824660944762108096, 14042278318561303840, 14046781918188674336, 4823632868166583760, 14046390624943401184, 4824078841831954224, 14044606730281919328, 14049110329909289824, 4799794383613219840, 4804297983240590336, 4808801582867960832, 4813305182495331328, 4817808782122701824, 4822312381750072320, 14048157085025283088, 4817968134859431872, 4822471734486802368, 14047997732288553040, 4819047279019851488, 4823550878647221984, 14046718583020848288, 4823750883754507120, 14045918562591707744, 4824550904183647664, 14042718480875145568, 14047222080502516064, 4822149886163999392, 14048319580611356016, 4816668170170848448, 4821171769798218944, 4825675369425589440, 14027714942301032960, 14032218541928403456, ], slow_two_pow_offsets: [0, 256, 512, 768, 1024, 1280, 1536, 1792], profiles: [ ProfileEntry { np: 4, bits: 84, bn_bound: 2536637511, to_ffts: Some(MPNToFFTFunc { np: 4, bits: 84 }), }, ProfileEntry { np: 4, bits: 88, bn_bound: 10380583, to_ffts: Some(MPNToFFTFunc { np: 4, bits: 88 }), }, ProfileEntry { np: 4, bits: 92, bn_bound: 42390, to_ffts: Some(MPNToFFTFunc { np: 4, bits: 92 }), }, ProfileEntry { np: 5, bits: 112, bn_bound: 32822700, to_ffts: Some(MPNToFFTFunc { np: 5, bits: 112 }), }, ProfileEntry { np: 5, bits: 116, bn_bound: 132790, to_ffts: Some(MPNToFFTFunc { np: 5, bits: 116 }), }, ProfileEntry { np: 5, bits: 120, bn_bound: 534, to_ffts: Some(MPNToFFTFunc { np: 5, bits: 120 }), }, ProfileEntry { np: 6, bits: 136, bn_bound: 144789875, to_ffts: Some(MPNToFFTFunc { np: 6, bits: 136 }), }, ProfileEntry { np: 6, bits: 140, bn_bound: 582218, to_ffts: Some(MPNToFFTFunc { np: 6, bits: 140 }), }, ProfileEntry { np: 6, bits: 144, bn_bound: 2337, to_ffts: Some(MPNToFFTFunc { np: 6, bits: 144 }), }, ProfileEntry { np: 7, bits: 160, bn_bound: 613493872, to_ffts: Some(MPNToFFTFunc { np: 7, bits: 160 }), }, ProfileEntry { np: 7, bits: 164, bn_bound: 2456369, to_ffts: Some(MPNToFFTFunc { np: 7, bits: 164 }), }, ProfileEntry { np: 7, bits: 168, bn_bound: 9826, to_ffts: Some(MPNToFFTFunc { np: 7, bits: 168 }), }, ProfileEntry { np: 8, bits: 184, bn_bound: 2177184315, to_ffts: Some(MPNToFFTFunc { np: 8, bits: 184 }), }, ProfileEntry { np: 8, bits: 188, bn_bound: 8689506, to_ffts: Some(MPNToFFTFunc { np: 8, bits: 188 }), }, ProfileEntry { np: 8, bits: 192, bn_bound: 34662, to_ffts: Some(MPNToFFTFunc { np: 8, bits: 192 }), }, ProfileEntry { np: 0, bits: 0, bn_bound: 0, to_ffts: None, }, ProfileEntry { np: 0, bits: 0, bn_bound: 0, to_ffts: None, }, ProfileEntry { np: 0, bits: 0, bn_bound: 0, to_ffts: None, }, ProfileEntry { np: 0, bits: 0, bn_bound: 0, to_ffts: None, }, ProfileEntry { np: 0, bits: 0, bn_bound: 0, to_ffts: None, }, ], profiles_size: 15, buffer_alloc: 0, };} ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/fft.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright © 2022 Daniel Schultz // // 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 . #[cfg(feature = "32_bit_limbs")] use crate::natural::arithmetic::add::add_with_carry_limb; #[cfg(not(feature = "32_bit_limbs"))] use crate::natural::arithmetic::add::limbs_slice_add_same_length_in_place_left; use crate::natural::arithmetic::mul::context::CONTEXT; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::limbs_sub_limb_in_place; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use core::cmp::{max, min}; use core::fmt::Debug; use malachite_base::fail_on_untested_path; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::arithmetic::traits::ShrRound; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, DivRound, ModInverse, ModPow, OverflowingAddAssign, OverflowingSubAssign, Parity, PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, WrappingAddAssign, WrappingSubAssign, XMulYToZZ, XXAddYYToZZ, XXXAddYYYToZZZ, XXXXAddYYYYToZZZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ExactFrom, SplitInHalf}; use malachite_base::num::logic::traits::{LeadingZeros, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::*; use wide::{f64x4, f64x8, u64x4}; // This is nmod_t from flint.h, FLINT 3.3.0-dev. #[derive(Debug, Default, Clone, Eq, PartialEq)] pub(crate) struct ModData { pub(crate) n: u64, pub(crate) ninv: u64, pub(crate) norm: u64, } const SD_FFT_CTX_W2TAB_SIZE: usize = 40; pub(crate) const SD_FFT_CTX_W2TAB_INIT: u64 = 12; #[derive(Debug, Eq, PartialEq)] pub(crate) struct SerializedFFTContext { pub(crate) p: u64, pub(crate) pinv: u64, pub(crate) mod_data: ModData, pub(crate) primitive_root: u64, pub(crate) w2tab_depth: u64, pub(crate) w2tab_backing: [u64; 4096], pub(crate) w2tab_offsets: [usize; SD_FFT_CTX_W2TAB_SIZE], } impl SerializedFFTContext { fn deserialize(self) -> FFTContext { FFTContext { p: f64::from_bits(self.p), pinv: f64::from_bits(self.pinv), mod_data: self.mod_data, primitive_root: self.primitive_root, w2tab_depth: self.w2tab_depth, w2tab_backing: self.w2tab_backing.into_iter().map(f64::from_bits).collect(), w2tab_offsets: self.w2tab_offsets, } } } // This is sd_fft_ctx_struct from fft_small.h, FLINT 3.3.0-dev. #[derive(Clone, Debug, PartialEq)] pub(crate) struct FFTContext { pub(crate) p: f64, pub(crate) pinv: f64, pub(crate) mod_data: ModData, pub(crate) primitive_root: u64, pub(crate) w2tab_depth: u64, pub(crate) w2tab_backing: Vec, pub(crate) w2tab_offsets: [usize; SD_FFT_CTX_W2TAB_SIZE], } impl Default for FFTContext { fn default() -> Self { Self { p: 0.0, pinv: 0.0, mod_data: ModData::default(), primitive_root: 0, w2tab_depth: 0, w2tab_backing: Vec::new(), w2tab_offsets: [0; SD_FFT_CTX_W2TAB_SIZE], } } } macro_rules! w2tab { ($q: expr, $i: expr, $j: expr) => { $q.w2tab_backing[$q.w2tab_offsets[$i] + $j] }; } #[derive(Debug, Eq, PartialEq)] pub(crate) struct SerializedCRTData { pub(crate) prime: u64, pub(crate) coeff_len: usize, pub(crate) nprimes: usize, } impl SerializedCRTData { fn deserialize(self, data: &[u64]) -> CRTData { CRTData { prime: self.prime, coeff_len: self.coeff_len, nprimes: self.nprimes, data: data.to_vec(), } } } // This is crt_data_struct from fft_small.h, FLINT 3.3.0-dev. #[derive(Debug, Default, Clone, Eq, PartialEq)] pub(crate) struct CRTData { pub(crate) prime: u64, pub(crate) coeff_len: usize, pub(crate) nprimes: usize, pub(crate) data: Vec, } impl CRTData { // This is crt_data_co_prime_red from fft_small.h, FLINT 3.3.0-dev, read-only. #[inline] fn co_prime_red(&self, i: usize) -> u64 { assert!(i < self.nprimes); self.data[self.nprimes * self.coeff_len + self.coeff_len + i] } // return mpn of length C->coeff_len // // This is crt_data_co_prime from fft_small.h, FLINT 3.3.0-dev, read-only. #[inline] pub(crate) fn co_prime(&mut self, i: usize) -> &mut [u64] { assert!(i < self.nprimes); &mut self.data[i * self.coeff_len..] } #[inline] fn prod_primes_ref(&self) -> &[u64] { &self.data[self.nprimes * self.coeff_len..] } } // This is profile_entry_struct from fft_small.h, FLINT 3.3.0-dev. #[derive(Debug, Default, Clone, Eq, PartialEq)] pub(crate) struct ProfileEntry { pub(crate) np: usize, pub(crate) bits: u64, pub(crate) bn_bound: usize, pub(crate) to_ffts: Option, } pub(crate) const MPN_CTX_NCRTS: usize = 8; pub(crate) const VEC_SZ: usize = 4; pub(crate) const MAX_NPROFILES: usize = 20; pub_test_struct! { #[derive(Debug, Eq, PartialEq)] SerializedContext { pub(crate) ffts: [SerializedFFTContext; MPN_CTX_NCRTS], pub(crate) crts: [SerializedCRTData; MPN_CTX_NCRTS], pub(crate) crts_data_0: [u64; 3], pub(crate) crts_data_1: [u64; 8], pub(crate) crts_data_2: [u64; 15], pub(crate) crts_data_3: [u64; 24], pub(crate) crts_data_4: [u64; 29], pub(crate) crts_data_5: [u64; 41], pub(crate) crts_data_6: [u64; 55], pub(crate) crts_data_7: [u64; 71], pub(crate) vec_two_pow_tab_backing: [[u64; 4]; 768], pub(crate) vec_two_pow_tab_offsets: [usize; MPN_CTX_NCRTS.div_ceil(VEC_SZ)], pub(crate) slow_two_pow_backing: [u64; 1 << 11], pub(crate) slow_two_pow_offsets: [usize; MPN_CTX_NCRTS], pub(crate) profiles: [ProfileEntry; MAX_NPROFILES], pub(crate) profiles_size: usize, pub(crate) buffer_alloc: usize, }} impl SerializedContext { pub_test! {deserialize(self) -> Context { let [f0, f1, f2, f3, f4, f5, f6, f7] = self.ffts; let [c0, c1, c2, c3, c4, c5, c6, c7] = self.crts; Context { ffts: [ f0.deserialize(), f1.deserialize(), f2.deserialize(), f3.deserialize(), f4.deserialize(), f5.deserialize(), f6.deserialize(), f7.deserialize(), ], crts: [ c0.deserialize(&self.crts_data_0), c1.deserialize(&self.crts_data_1), c2.deserialize(&self.crts_data_2), c3.deserialize(&self.crts_data_3), c4.deserialize(&self.crts_data_4), c5.deserialize(&self.crts_data_5), c6.deserialize(&self.crts_data_6), c7.deserialize(&self.crts_data_7), ], vec_two_pow_tab_backing: self .vec_two_pow_tab_backing .into_iter() .map(|[u0, u1, u2, u3]| { f64x4::from([ f64::from_bits(u0), f64::from_bits(u1), f64::from_bits(u2), f64::from_bits(u3), ]) }) .collect(), vec_two_pow_tab_offsets: self.vec_two_pow_tab_offsets, slow_two_pow_backing: self .slow_two_pow_backing .into_iter() .map(f64::from_bits) .collect(), slow_two_pow_offsets: self.slow_two_pow_offsets, profiles: self.profiles, profiles_size: self.profiles_size, buffer: Vec::new(), buffer_alloc: self.buffer_alloc, } }} } // This is mpn_ctx_struct from fft_small.h, FLINT 3.3.0-dev. pub_test_struct! { #[derive(Debug, Default, Clone, PartialEq)] Context { pub(crate) ffts: [FFTContext; MPN_CTX_NCRTS], pub(crate) crts: [CRTData; MPN_CTX_NCRTS], pub(crate) vec_two_pow_tab_backing: Vec, pub(crate) vec_two_pow_tab_offsets: [usize; MPN_CTX_NCRTS.div_ceil(VEC_SZ)], pub(crate) slow_two_pow_backing: Vec, pub(crate) slow_two_pow_offsets: [usize; MPN_CTX_NCRTS], pub(crate) profiles: [ProfileEntry; MAX_NPROFILES], pub(crate) profiles_size: usize, pub(crate) buffer: Vec, pub(crate) buffer_alloc: usize, }} // This is vec1d_reduce_pm1n_to_pmhn from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_pm1n_to_pmhn { ($a: expr, $n: expr) => {{ let a = $a; let n = $n; let halfn = 0.5 * n; if a > halfn { a - n } else { let t = a + n; if t < halfn { t } else { a } } }}; } #[cfg(feature = "test_build")] pub(crate) use f64_reduce_pm1n_to_pmhn; // This is vec4d_reduce_pm1n_to_pmhn from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_reduce_pm1n_to_pmhn { ($a: expr, $n: expr) => {{ let [a0, a1, a2, a3] = $a.to_array(); let [n0, n1, n2, n3] = $n.to_array(); f64x4::from([ f64_reduce_pm1n_to_pmhn!(a0, n0), f64_reduce_pm1n_to_pmhn!(a1, n1), f64_reduce_pm1n_to_pmhn!(a2, n2), f64_reduce_pm1n_to_pmhn!(a3, n3), ]) }}; } // This is vec8d_reduce_pm1n_to_pmhn from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x8_reduce_pm1n_to_pmhn { ($a: expr, $n: expr) => {{ let [a0, a1, a2, a3, a4, a5, a6, a7] = $a.to_array(); let [n0, n1, n2, n3, n4, n5, n6, n7] = $n.to_array(); f64x8::from([ f64_reduce_pm1n_to_pmhn!(a0, n0), f64_reduce_pm1n_to_pmhn!(a1, n1), f64_reduce_pm1n_to_pmhn!(a2, n2), f64_reduce_pm1n_to_pmhn!(a3, n3), f64_reduce_pm1n_to_pmhn!(a4, n4), f64_reduce_pm1n_to_pmhn!(a5, n5), f64_reduce_pm1n_to_pmhn!(a6, n6), f64_reduce_pm1n_to_pmhn!(a7, n7), ]) }}; } // [0,n] -> [-n/2, n/2] // // This is f64_reduce_0n_to_pmhn from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_0n_to_pmhn { ($a: expr, $n: expr) => {{ let a = $a; let n = $n; if a > 0.5 * n { a - n } else { a } }}; } #[cfg(feature = "test_build")] pub(crate) use f64_reduce_0n_to_pmhn; // return a mod n in [0,n) assuming a in (-n,n) // // This is vec1d_reduce_pm1no_to_0n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_pm1no_to_0n { ($a: expr, $n: expr) => {{ let a = $a; if a >= 0.0 { a } else { a + $n } }}; } // return a mod n in [0,n) assuming a in (-n,n) // // This is vec4d_reduce_pm1no_to_0n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_reduce_pm1no_to_0n { ($a: expr, $n: expr) => {{ let [a0, a1, a2, a3] = $a.to_array(); let [n0, n1, n2, n3] = $n.to_array(); f64x4::from([ f64_reduce_pm1no_to_0n!(a0, n0), f64_reduce_pm1no_to_0n!(a1, n1), f64_reduce_pm1no_to_0n!(a2, n2), f64_reduce_pm1no_to_0n!(a3, n3), ]) }}; } macro_rules! f64x4_round { ($x: expr) => {{ let [x0, x1, x2, x3] = $x.to_array(); f64x4::from([round_even!(x0), round_even!(x1), round_even!(x2), round_even!(x3)]) }}; } macro_rules! f64x8_round { ($x: expr) => {{ let [x0, x1, x2, x3, x4, x5, x6, x7] = $x.to_array(); f64x8::from([ round_even!(x0), round_even!(x1), round_even!(x2), round_even!(x3), round_even!(x4), round_even!(x5), round_even!(x6), round_even!(x7), ]) }}; } // In this case f64x4::mul_add is not perfectly accurate, so we must fall back to a slower, more // accurate implementation #[cfg(not(any( all( target_feature = "fma", any(target_arch = "x86", target_arch = "x86_64") ), all(target_feature = "neon", target_arch = "aarch64") )))] macro_rules! f64x4_mul_add { ($a: expr, $b: expr, $c: expr) => {{ let [a0, a1, a2, a3] = $a.to_array(); let [b0, b1, b2, b3] = $b.to_array(); let [c0, c1, c2, c3] = $c.to_array(); f64x4::from([fma!(a0, b0, c0), fma!(a1, b1, c1), fma!(a2, b2, c2), fma!(a3, b3, c3)]) }}; } #[cfg(any( all( target_feature = "fma", any(target_arch = "x86", target_arch = "x86_64") ), all(target_feature = "neon", target_arch = "aarch64") ))] macro_rules! f64x4_mul_add { ($a: expr, $b: expr, $c: expr) => {{ $a.mul_add($b, $c) }}; } #[cfg(feature = "test_build")] pub(crate) use f64x4_mul_add; // In this case f64x8::mul_add is not perfectly accurate, so we must fall back to a slower, more // accurate implementation #[cfg(not(any( all( target_feature = "fma", any(target_arch = "x86", target_arch = "x86_64") ), all(target_feature = "neon", target_arch = "aarch64") )))] macro_rules! f64x8_mul_add { ($a: expr, $b: expr, $c: expr) => {{ let [a0, a1, a2, a3, a4, a5, a6, a7] = $a.to_array(); let [b0, b1, b2, b3, b4, b5, b6, b7] = $b.to_array(); let [c0, c1, c2, c3, c4, c5, c6, c7] = $c.to_array(); f64x8::from([ fma!(a0, b0, c0), fma!(a1, b1, c1), fma!(a2, b2, c2), fma!(a3, b3, c3), fma!(a4, b4, c4), fma!(a5, b5, c5), fma!(a6, b6, c6), fma!(a7, b7, c7), ]) }}; } #[cfg(any( all( target_feature = "fma", any(target_arch = "x86", target_arch = "x86_64") ), all(target_feature = "neon", target_arch = "aarch64") ))] macro_rules! f64x8_mul_add { ($a: expr, $b: expr, $c: expr) => {{ $a.mul_add($b, $c) }}; } // return a mod n in (-n,n) // // This is vec4d_reduce_to_pm1no from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_reduce_to_pm1no { ($a: expr, $n: expr, $ninv: expr) => {{ let a = $a; f64x4_mul_add!(-f64x4_round!(a * $ninv), $n, a) }}; } // return a mod n in (-n,n) // // This is vec1d_reduce_to_pm1no from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_to_pm1no { ($a: expr, $n: expr, $ninv: expr) => {{ let a = $a; fma!(-round_even!(a * $ninv), $n, a) }}; } // return a mod n in [0,n) // // This is vec4d_reduce_to_0n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_reduce_to_0n { ($a: expr, $n: expr, $ninv: expr) => {{ let n = $n; f64x4_reduce_pm1no_to_0n!(f64x4_reduce_to_pm1no!($a, n, $ninv), n) }}; } // return a mod n in [0,n) // // This is vec1d_reduce_to_0n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_to_0n { ($a: expr, $n: expr, $ninv: expr) => {{ let n = $n; f64_reduce_pm1no_to_0n!(f64_reduce_to_pm1no!($a, n, $ninv), n) }}; } // This is vec1d_mulmod from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_mulmod { ($a: expr, $b: expr, $n: expr, $ninv: expr) => {{ let a = $a; let b = $b; let h = a * b; fma!(-round_even!(h * $ninv), $n, h) - fma!(-a, b, h) }}; } #[cfg(feature = "test_build")] pub(crate) use f64_mulmod; // This is vec4d_mulmod from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_mulmod { ($a: expr, $b: expr, $n: expr, $ninv: expr) => {{ let a = $a; let b = $b; let h = a * b; f64x4_mul_add!(-f64x4_round!(h * $ninv), $n, h) - f64x4_mul_add!(-a, b, h) }}; } // This is vec8d_mulmod from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x8_mulmod { ($a: expr, $b: expr, $n: expr, $ninv: expr) => {{ let a = $a; let b = $b; let h = a * b; f64x8_mul_add!(-f64x8_round!(h * $ninv), $n, h) - f64x8_mul_add!(-a, b, h) }}; } // This is vec4d_nmulmod from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_nmulmod { ($a: expr, $b: expr, $n: expr, $ninv: expr) => {{ let a = $a; let b = $b; let h = a * b; f64x4_mul_add!(-a, b, h) - f64x4_mul_add!(-f64x4_round!(h * $ninv), $n, h) }}; } // This is vec4d_nmulmod from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x8_nmulmod { ($a: expr, $b: expr, $n: expr, $ninv: expr) => {{ let a = $a; let b = $b; let h = a * b; f64x8_mul_add!(-a, b, h) - f64x8_mul_add!(-f64x8_round!(h * $ninv), $n, h) }}; } // This is vec1d_reduce_to_pm1n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64_reduce_to_pm1n { ($a: expr, $n: expr, $ninv: expr) => {{ let a = $a; fma!(-round_even!(a * $ninv), $n, a) }}; } // This is vec4d_reduce_to_pm1n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_reduce_to_pm1n { ($a: expr, $n: expr, $ninv: expr) => {{ let a = $a; f64x4_mul_add!(-f64x4_round!(a * $ninv), $n, a) }}; } // This is vec8d_reduce_to_pm1n from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x8_reduce_to_pm1n { ($a: expr, $n: expr, $ninv: expr) => {{ let a = $a; f64x8_mul_add!(-f64x8_round!(a * $ninv), $n, a) }}; } // need ceil(64 * bn / bits) <= prod_primes / 2 ^ (2 * bits) i.e. (64 * bn + bits - 1) / bits <= // prod_primes / 2 ^ (2 * bits) 64 * bn <= bits * prod_primes / 2 ^ (2 * bits) - (bits - 1) // // This is crt_data_find_bn_bound from fft_small/mpn_mul.c, FLINT 3.3.0-dev. pub(crate) fn crt_data_find_bn_bound(c: &CRTData, bits: u64) -> usize { let two_bits = bits << 1; let q = usize::exact_from(two_bits >> u64::LOG_WIDTH); let r = two_bits & u64::WIDTH_MASK; let n = c.coeff_len; let n_p1 = n + 1; let mut xs = [0; 8]; let xs = &mut xs[..n_p1]; xs[n] = limbs_mul_limb_to_out::(xs, &c.prod_primes_ref()[..n], bits); let mut bound = 0; if q < n_p1 { let xs_hi = &mut xs[q..]; if r != 0 { limbs_slice_shr_in_place::(xs_hi, r); } if !limbs_sub_limb_in_place::(xs_hi, bits - 1) { limbs_slice_shr_in_place::(xs_hi, 6); bound = usize::exact_from(xs_hi[0]); if xs_hi[1..].iter().any(|&x| x != 0) { return usize::ONE.wrapping_neg(); } } } bound } // need ceil(64*bn/bits) <= prod_primes/2^(2*bits). first try bits = (nbits(prod_primes) - // nbits(bn))/2 then adjust. also require bits > 64 for some applications below // // This is crt_data_find_bits from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn crt_data_find_bits(c: &CRTData, bn: usize) -> u64 { let p_nbits = limbs_significant_bits(&c.prod_primes_ref()[..c.coeff_len]); let mut bits = max(66, (p_nbits - bn.significant_bits()) >> 1); if bn > crt_data_find_bn_bound(c, bits) { bits -= 1; while bits > 65 && bn > crt_data_find_bn_bound(c, bits) { bits -= 1; } } else { while bn <= crt_data_find_bn_bound(c, bits + 1) { bits += 1; } } bits } #[cfg(feature = "32_bit_limbs")] macro_rules! get { ($a: ident, $i: expr) => { $a[$i] }; } #[cfg(not(feature = "32_bit_limbs"))] macro_rules! get { ($a: ident, $i: expr) => {{ let i = $i; let x = $a[i >> 1]; if i & 1 == 0 { x.lower_half() } else { x.upper_half() } }}; } // This is CODE from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! code { ( $ir: expr, $nvs: expr, $np: expr, $ds: ident, $dstride: ident, $xs: ident, $ps: ident, $pinvs: ident, $two_pow: ident, $a: ident, $i: ident, $bits: expr ) => { let mut k = (($i + $ir) * $bits) / 32; let mut j = const { ($ir * $bits) % 32 }; $xs[..$nvs].fill(f64x4::splat(f64::from(get!($a, k) >> j))); k += 1; j = const { 32 - ($ir * $bits) % 32 }; let mut m = const { (32 - ($ir * $bits) % 32) * $nvs }; while j <= const { $bits - 32 } { let ak = f64x4::splat(f64::from(get!($a, k))); let two_pow_hi = &$two_pow[m..]; for l in 0..$nvs { $xs[l] += f64x4_mulmod!(ak, two_pow_hi[l], $ps[l], $pinvs[l]); } k += 1; j += 32; m += const { $nvs << 5 }; } let bmj = $bits - j; if bmj != 0 { let ak = f64x4::splat(f64::from(get!($a, k) << (32 - bmj))); let two_pow_hi = &$two_pow[const { ($bits - 32) * $nvs }..]; for l in 0..$nvs { $xs[l] += f64x4_mulmod!(ak, two_pow_hi[l], $ps[l], $pinvs[l]); } } for l in 0..$nvs { $xs[l] = f64x4_reduce_to_pm1n!($xs[l], $ps[l], $pinvs[l]); } let ds_hi = &mut $ds[$i + $ir..]; let mut m = 0; for l in 0..$np { ds_hi[m] = $xs[l >> 2].to_array()[l & 3]; m += $dstride; } }; } #[cfg(feature = "32_bit_limbs")] macro_rules! get_or_default { ($a: ident, $i: expr) => { $a.get($i).copied().unwrap_or_default() }; } #[cfg(not(feature = "32_bit_limbs"))] macro_rules! get_or_default { ($a: ident, $i: expr) => {{ let i = $i; let j = i >> 1; if j < $a.len() { let x = $a[j]; if i & 1 == 0 { x.lower_half() } else { x.upper_half() } } else { 0 } }}; } // This is mpn_to_ffts_hard from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! mpn_to_ffts_hard { ( $np: expr, $nvs: expr, $rffts: ident, $ds: ident, $dstride: ident, $a: ident, $atrunc: ident, $two_pow: ident, $start_hard: ident, $stop_hard: ident, $bits: expr ) => {{ let mut xs = [f64x4::default(); $nvs]; let mut ps = [f64x4::default(); $nvs]; let mut pinvs = [f64x4::default(); $nvs]; for (i, r) in $rffts.chunks(4).enumerate() { ps[i] = f64x4::new([r[0].p, r[1].p, r[2].p, r[3].p]); pinvs[i] = f64x4::new([r[0].pinv, r[1].pinv, r[2].pinv, r[3].pinv]); } for i in $start_hard..$stop_hard { let ib = i * $bits; let mut k = ib >> 5; let mut j = ib & 31; xs[..$nvs].fill(f64x4::splat(f64::from(get_or_default!($a, k) >> j))); k += 1; j = 32 - j; let bm32 = $bits - 32; while j <= bm32 { let ak = f64x4::splat(f64::from(get_or_default!($a, k))); let two_pow_hi = &$two_pow[j * $nvs..]; for l in 0..$nvs { xs[l] += f64x4_mulmod!(ak, two_pow_hi[l], ps[l], pinvs[l]); } k += 1; j += 32; } let bmj = $bits - j; if bmj != 0 { let ak = f64x4::splat(f64::from(get_or_default!($a, k) << (32 - bmj))); let two_pow_hi = &$two_pow[bm32 * $nvs..]; for l in 0..$nvs { xs[l] += f64x4_mulmod!(ak, two_pow_hi[l], ps[l], pinvs[l]); } } for l in 0..$nvs { xs[l] = f64x4_reduce_to_pm1n!(xs[l], ps[l], pinvs[l]); } let ds_hi = &mut $ds[i..]; let mut m = 0; for l in 0..$np { ds_hi[m] = xs[l / VEC_SZ].to_array()[l % VEC_SZ]; m += $dstride; } } for l in 0..$np { $ds[l * $dstride..][$stop_hard..$atrunc].fill(0.0); } }}; } // The tables for powers of two each have this fixed length. This has to go up linearly with the max // number of primes MPN_CTX_NCRTS involved in chinese remaindering. This length is checked with // asserts in the code. pub(crate) const MPN_CTX_TWO_POWER_TAB_SIZE: usize = 256; #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub(crate) struct MPNToFFTFunc { pub(crate) np: usize, pub(crate) bits: u64, } // The the l^th fft ctx Rffts[l] is expected to have data at d + l*dstride // // This is mpn_to_ffts from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! apply_mpn_to_fft_func { ($f: ident, $np: expr, $bits: expr, $nvs: expr) => { fn $f( rffts: &[FFTContext], ds: &mut [f64], dstride: usize, a: &[Limb], atrunc: usize, two_pow: &[f64x4], stop_easy: usize, start_hard: usize, stop_hard: usize, ) { let mut xs = [f64x4::default(); $nvs]; let mut ps = [f64x4::default(); $nvs]; let mut pinvs = [f64x4::default(); $nvs]; for (i, r) in rffts.chunks(4).enumerate() { ps[i] = f64x4::from([r[0].p, r[1].p, r[2].p, r[3].p]); pinvs[i] = f64x4::from([r[0].pinv, r[1].pinv, r[2].pinv, r[3].pinv]); } if const { $bits & 7 == 0 } { assert_eq!(stop_easy & 3, 0); for i in (0..stop_easy).step_by(4) { code!( 0, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 1, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 2, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 3, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); } } else { assert_eq!(stop_easy & 7, 0); for i in (0..stop_easy).step_by(8) { code!( 0, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 1, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 2, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 3, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 4, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 5, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 6, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); code!( 7, $nvs, $np, ds, dstride, xs, ps, pinvs, two_pow, a, i, $bits ); } } mpn_to_ffts_hard!( $np, $nvs, rffts, ds, dstride, a, atrunc, two_pow, start_hard, stop_hard, $bits ); } }; } // nvs == np.div_ceil(4) apply_mpn_to_fft_func!(apply_mpn_to_fft_func_4_84, 4, 84, 1); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_4_88, 4, 88, 1); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_4_92, 4, 92, 1); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_5_112, 5, 112, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_5_116, 5, 116, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_5_120, 5, 120, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_6_136, 6, 136, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_6_140, 6, 140, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_6_144, 6, 144, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_7_160, 7, 160, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_7_164, 7, 164, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_7_168, 7, 168, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_8_184, 8, 184, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_8_188, 8, 188, 2); apply_mpn_to_fft_func!(apply_mpn_to_fft_func_8_192, 8, 192, 2); const LG_BLK_SZ: u64 = 8; const BLK_SZ: usize = 256; // This is mpn_ctx_best_profile from fft_small/mpn_mul.c, FLINT 3.3.0-dev, returning the context. fn mpn_ctx_best_profile(r: &Context, p: &mut ProfileEntry, an: usize, bn: usize) { // The first profile is supposed to have the biggest bn_bound. If the given bn is too large, we // must fill in p.to_ffts = None because we don't have a fast mod function. // // We can also fill in p.to_ffts = None any time to not use the fast mod function and use the // slow generic one instead. const BIGGEST_BOUND: usize = CONTEXT.profiles[0].bn_bound; const PROFILES_SIZE: usize = CONTEXT.profiles_size; if bn > BIGGEST_BOUND { p.np = 4; p.bits = crt_data_find_bits(&r.crts[p.np - 1], bn); p.to_ffts = None; return; } let mut i = 0; let mut best_i = 0; let mut best_score = 100000000.0 * (an.checked_add(bn).unwrap() as f64); loop { // maximize r.profiles[i].bits assert!(i < PROFILES_SIZE); assert!(bn <= r.profiles[i].bn_bound); while i + 1 < PROFILES_SIZE && bn <= r.profiles[i + 1].bn_bound && r.profiles[i + 1].np == r.profiles[i].np { i += 1; } let np = r.profiles[i].np; let bits = r.profiles[i].bits as usize; let alen = (an << 6).div_round(bits, Ceiling).0; let blen = (bn << 6).div_round(bits, Ceiling).0; let zlen = alen + blen - 1; let ztrunc = zlen.round_to_multiple(BLK_SZ, Ceiling).0; let depth = max(LG_BLK_SZ, ztrunc.ceiling_log_base_2()); let ratio = (ztrunc as f64) / (f64::power_of_2(depth)); let mut score = (1.0 - 0.25 * ratio) * const { 1.0 / 1000000.0 }; score *= (np * usize::exact_from(depth)) as f64; score *= ztrunc as f64; if score < best_score { best_i = i; best_score = score; } loop { i += 1; if i >= PROFILES_SIZE { p.np = r.profiles[best_i].np; p.bits = r.profiles[best_i].bits; p.to_ffts = r.profiles[best_i].to_ffts; return; } if bn <= r.profiles[i].bn_bound { break; } } } } // This is mpn_ctx_fit_buffer from fft_small/mpn_mul.c, FLINT 3.3.0-dev, not returning the buffer. fn mpn_ctx_fit_buffer(r: &mut Context, n: usize) { if n > r.buffer_alloc { let n = max(n, (r.buffer_alloc * 17) >> 4) .round_to_multiple_of_power_of_2(12, Ceiling) .0; r.buffer.resize(n >> 3, 0.0); r.buffer_alloc = n; } } // This is slow_mpn_to_fft_easy from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn slow_mpn_to_fft_easy( q: &FFTContext, zs: &mut [f64], a: &[Limb], iq_stop_easy: usize, bits: usize, two_pow: &[f64], ) { let p = f64x8::splat(q.p); let pinv = f64x8::splat(q.pinv); let b2 = bits << 1; let b3 = b2 + bits; let b4 = b3 + bits; let b5 = b4 + bits; let b6 = b5 + bits; let b7 = b6 + bits; for iq in 0..iq_stop_easy { let zi = &mut zs[iq << LG_BLK_SZ..]; let mut m = 0; for ir in 0..const { BLK_SZ >> 3 } { let mut k = iq * const { BLK_SZ >> 5 } * bits + (m >> 5); let mut j = m & 31; let mut ak = f64x8::from([ f64::from(get!(a, k) >> j), f64::from(get!(a, k + bits) >> j), f64::from(get!(a, k + b2) >> j), f64::from(get!(a, k + b3) >> j), f64::from(get!(a, k + b4) >> j), f64::from(get!(a, k + b5) >> j), f64::from(get!(a, k + b6) >> j), f64::from(get!(a, k + b7) >> j), ]); let mut x = ak; k += 1; j = 32 - j; let bm32 = bits - 32; while j <= bm32 { ak = f64x8::from([ f64::from(get!(a, k)), f64::from(get!(a, k + bits)), f64::from(get!(a, k + b2)), f64::from(get!(a, k + b3)), f64::from(get!(a, k + b4)), f64::from(get!(a, k + b5)), f64::from(get!(a, k + b6)), f64::from(get!(a, k + b7)), ]); x += f64x8_mulmod!(ak, f64x8::splat(two_pow[j]), p, pinv); k += 1; j += 32; } let bmj = bits - j; if bmj != 0 { let shift = 32 - bmj; ak = f64x8::from([ f64::from(get!(a, k) << shift), f64::from(get!(a, k + bits) << shift), f64::from(get!(a, k + b2) << shift), f64::from(get!(a, k + b3) << shift), f64::from(get!(a, k + b4) << shift), f64::from(get!(a, k + b5) << shift), f64::from(get!(a, k + b6) << shift), f64::from(get!(a, k + b7) << shift), ]); x += f64x8_mulmod!(ak, f64x8::splat(two_pow[bm32]), p, pinv); } x = f64x8_reduce_to_pm1n!(x, p, pinv); let [x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7] = x.to_array(); let zi_hi = &mut zi[ir..]; const B: usize = BLK_SZ >> 3; zi_hi[0] = x_0; zi_hi[B] = x_1; zi_hi[const { 2 * B }] = x_2; zi_hi[const { 3 * B }] = x_3; zi_hi[const { 4 * B }] = x_4; zi_hi[const { 5 * B }] = x_5; zi_hi[const { 6 * B }] = x_6; zi_hi[const { 7 * B }] = x_7; m += bits; } } } // This is slow_mpn_to_fft from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn slow_mpn_to_fft( q: &FFTContext, zs: &mut [f64], ztrunc: usize, a: &[Limb], bits: usize, two_pow: &[f64], ) { let an = a.len(); #[cfg(not(feature = "32_bit_limbs"))] let an = an << 1; let bm32 = bits - 32; // the highest index read from two_pow is bits - 32 assert!(bm32 < MPN_CTX_TWO_POWER_TAB_SIZE); // if i*bits + 32 < 32*an, then the index into a is always in bounds let i_stop_easy = min(ztrunc, ((an << 5) - 33) / bits); let iq_stop_easy = i_stop_easy >> LG_BLK_SZ; slow_mpn_to_fft_easy(q, zs, a, iq_stop_easy, bits, two_pow); // now the hard ones let p = q.p; let pinv = q.pinv; for iq in iq_stop_easy..ztrunc >> LG_BLK_SZ { let big_i = iq << LG_BLK_SZ; for (i, z) in zs[big_i..].iter_mut().enumerate().take(BLK_SZ) { let n = (big_i + i) * bits; let mut k = n >> 5; let mut j = n & 31; let mut x = f64::from(get_or_default!(a, k) >> j); k += 1; j = 32 - j; while j <= bm32 { x += f64_mulmod!(f64::from(get_or_default!(a, k)), two_pow[j], p, pinv); k += 1; j += 32; } let bmj = bits - j; if bmj != 0 { x += f64_mulmod!( f64::from(get_or_default!(a, k) << (32 - bmj)), two_pow[bm32], p, pinv ); } *z = f64_reduce_to_pm1n!(x, p, pinv); } } } // This is n_nbits_nz from fft_small.h, FLINT 3.3.0-dev. macro_rules! n_nbits_nz { ($x: expr) => {{ (LeadingZeros::leading_zeros($x) ^ const { usize::WIDTH - 1 }) + 1 }}; } // for the fft look up of powers of w // // This is SET_J_BITS_AND_J_R from fft_small.h, FLINT 3.3.0-dev, returning j_bits and j_r. macro_rules! set_j_bits_and_j_r { ($j: ident, $j_bits: ident, $j_r: ident) => { let ($j_bits, $j_r) = if $j == 0 { (0, 0) } else { let j_bits = n_nbits_nz!($j); (j_bits, $j - usize::power_of_2(j_bits - 1)) }; }; } // This is RADIX_4_FORWARD_PARAM_J_IS_Z from fft_small/sd_fft.c, FLINT 3.3.0-dev, returning iw, n, // and ninv. macro_rules! radix_4_forward_param_j_is_z { ($q: ident, $iw: ident, $n: ident, $ninv: ident) => { let $iw = f64x8::splat(w2tab!($q, 1, 0)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_4_FORWARD_MOTH_J_IS_Z from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_4_forward_moth_j_is_z { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $iw: ident, $n: ident, $ninv: ident ) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x2 = f64x8_reduce_to_pm1n!($x2, $n, $ninv); $x3 = f64x8_reduce_to_pm1n!($x3, $n, $ninv); let y0 = $x0 + $x2; let y1 = f64x8_reduce_to_pm1n!($x1 + $x3, $n, $ninv); let y2 = $x0 - $x2; let y3 = f64x8_mulmod!($x1 - $x3, $iw, $n, $ninv); $x0 = y0 + y1; $x1 = y0 - y1; $x2 = y2 + y3; $x3 = y2 - y3; }; } // This is RADIX_4_FORWARD_PARAM_J_IS_NZ from fft_small/sd_fft.c, FLINT 3.3.0-dev, returning w, w2, // iw, n, and ninv. macro_rules! radix_4_forward_param_j_is_nz { ( $q: ident, $j_r: ident, $j_bits: ident, $w: ident, $w2: ident, $iw: ident, $n: ident, $ninv: ident ) => { assert_ne!($j_bits, 0); let j_bits = usize::exact_from($j_bits); let j_bits_p_1 = j_bits + 1; let j_2 = $j_r << 1; let $w = f64x8::splat(w2tab!($q, j_bits_p_1, j_2)); let $w2 = f64x8::splat(w2tab!($q, j_bits, $j_r)); let $iw = f64x8::splat(w2tab!($q, j_bits_p_1, j_2 + 1)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_4_FORWARD_MOTH_J_IS_NZ from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_4_forward_moth_j_is_nz { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $w: ident, $w2: ident, $iw: ident, $n: ident, $ninv: ident ) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x2 = f64x8_mulmod!($x2, $w2, $n, $ninv); $x3 = f64x8_mulmod!($x3, $w2, $n, $ninv); let y0 = $x0 + $x2; let y1 = f64x8_mulmod!($x1 + $x3, $w, $n, $ninv); let y2 = $x0 - $x2; let y3 = f64x8_mulmod!($x1 - $x3, $iw, $n, $ninv); $x0 = y0 + y1; $x1 = y0 - y1; $x2 = y2 + y3; $x3 = y2 - y3; }; } // This is RADIX_2_FORWARD_PARAM_J_IS_Z from fft_small/sd_fft.c, FLINT 3.3.0-dev, returning n and // ninv. macro_rules! radix_2_forward_param_j_is_z { ($q: ident, $n: ident, $ninv: ident) => { let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_2_FORWARD_MOTH_J_IS_Z from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_2_forward_moth_j_is_z { ($x0: ident, $x1: ident, $n: ident, $ninv: ident) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x1 = f64x8_reduce_to_pm1n!($x1, $n, $ninv); ($x0, $x1) = ($x0 + $x1, $x0 - $x1); }; } // This is RADIX_2_FORWARD_PARAM_J_IS_NZ from fft_small/sd_fft.c, FLINT 3.3.0-dev, returning w, n, // and ninv. macro_rules! radix_2_forward_param_j_is_nz { ($q: ident, $j_r: ident, $j_bits: ident, $w: ident, $n: ident, $ninv: ident) => { let $w = f64x8::splat(w2tab!($q, usize::exact_from($j_bits), $j_r)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_2_FORWARD_MOTH_J_IS_NZ from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_2_forward_moth_j_is_nz { ($x0: ident, $x1: ident, $w: ident, $n: ident, $ninv: ident) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x1 = f64x8_mulmod!($x1, $w, $n, $ninv); ($x0, $x1) = ($x0 + $x1, $x0 - $x1); }; } const BIG_N: usize = 8; macro_rules! read_f64x4 { ($xs: expr, $i: expr) => {{ let i = $i; f64x4::from(&$xs[i..i + 4]) }}; } macro_rules! read_f64x8 { ($xs: expr, $i: expr) => {{ let i = $i; f64x8::from(&$xs[i..i + 8]) }}; } macro_rules! read_f64x4_w2tab { ($q: expr, $i: expr, $j: expr) => { read_f64x4!($q.w2tab_backing, $q.w2tab_offsets[$i] + $j) }; } macro_rules! read_f64x8_w2tab { ($q: expr, $i: expr, $j: expr) => { read_f64x8!($q.w2tab_backing, $q.w2tab_offsets[$i] + $j) }; } macro_rules! write_f64x4 { ($xs: ident, $i: expr, $f: expr) => {{ let i = $i; $xs[i..i + 4].copy_from_slice(&$f.to_array()) }}; } macro_rules! write_f64x8 { ($xs: ident, $i: expr, $f: expr) => {{ let i = $i; $xs[i..i + 8].copy_from_slice(&$f.to_array()) }}; } macro_rules! write_f64x8_w2tab { ($q: expr, $i: expr, $j: expr, $f: expr) => { let start = $q.w2tab_offsets[$i] + $j; $q.w2tab_backing[start..start + 8].copy_from_slice(&$f.to_array()); }; } macro_rules! process_2_2 { ($f: ident, $limit: expr, $x0: ident, $x1: ident, $p0: ident, $p1: ident) => { for i in (0..$limit).step_by(BIG_N) { let mut f0 = read_f64x8!($x0, i); let mut f1 = read_f64x8!($x1, i); $f!(f0, f1, $p0, $p1); write_f64x8!($x0, i, f0); write_f64x8!($x1, i, f1); } }; } macro_rules! process_2_3 { ($f: ident, $limit: expr, $x0: ident, $x1: ident, $p0: ident, $p1: ident, $p2: ident) => { for i in (0..$limit).step_by(BIG_N) { let mut f0 = read_f64x8!($x0, i); let mut f1 = read_f64x8!($x1, i); $f!(f0, f1, $p0, $p1, $p2); write_f64x8!($x0, i, f0); write_f64x8!($x1, i, f1); } }; } macro_rules! process_4_3 { ( $f: ident, $limit: expr, $x0: ident, $x1: ident, $x2: ident, $x3: ident, $p0: ident, $p1: ident, $p2: ident ) => { for i in (0..$limit).step_by(BIG_N) { let mut f0 = read_f64x8!($x0, i); let mut f1 = read_f64x8!($x1, i); let mut f2 = read_f64x8!($x2, i); let mut f3 = read_f64x8!($x3, i); $f!(f0, f1, f2, f3, $p0, $p1, $p2); write_f64x8!($x0, i, f0); write_f64x8!($x1, i, f1); write_f64x8!($x2, i, f2); write_f64x8!($x3, i, f3); } }; } macro_rules! process_4_5 { ( $f: ident, $limit: expr, $x0: ident, $x1: ident, $x2: ident, $x3: ident, $p0: ident, $p1: ident, $p2: ident, $p3: ident, $p4: ident ) => { for i in (0..$limit).step_by(BIG_N) { let mut f0 = read_f64x8!($x0, i); let mut f1 = read_f64x8!($x1, i); let mut f2 = read_f64x8!($x2, i); let mut f3 = read_f64x8!($x3, i); $f!(f0, f1, f2, f3, $p0, $p1, $p2, $p3, $p4); write_f64x8!($x0, i, f0); write_f64x8!($x1, i, f1); write_f64x8!($x2, i, f2); write_f64x8!($x3, i, f3); } }; } // S is stride; BLK_SZ transforms each of length 2^k // // This is sd_fft_no_trunc_block from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_no_trunc_block(q: &FFTContext, xs: &mut [f64], s: usize, k: u64, j: usize) { let big_s = s << LG_BLK_SZ; if k > 4 { let k1 = k >> 1; let k2 = k - k1; let shifted = s << k2; let mut m = 0; for _ in 0..usize::power_of_2(k2) { sd_fft_no_trunc_block(q, &mut xs[m..], shifted, k1, j); m += big_s; } // row ffts let big_s = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut m = 0; for b in 0..usize::power_of_2(k1) { sd_fft_no_trunc_block(q, &mut xs[m..], s, k2, shifted + b); m += big_s; } return; } set_j_bits_and_j_r!(j, j_bits, j_r); if k >= 2 { let k1 = 2; let k2 = k - k1; let l2 = usize::power_of_2(k2); let big_s_2 = s << (k2 + LG_BLK_SZ); // column ffts if j_bits == 0 { radix_4_forward_param_j_is_z!(q, iw, n, ninv); for a in 0..l2 { split_into_chunks_mut!(&mut xs[a * big_s..], big_s_2, [x0, x1, x2], x3); process_4_3!( radix_4_forward_moth_j_is_z, BLK_SZ, x0, x1, x2, x3, iw, n, ninv ); } } else { radix_4_forward_param_j_is_nz!(q, j_r, j_bits, w, w2, iw, n, ninv); for a in 0..l2 { split_into_chunks_mut!(&mut xs[a * big_s..], big_s_2, [x0, x1, x2], x3); process_4_5!( radix_4_forward_moth_j_is_nz, BLK_SZ, x0, x1, x2, x3, w, w2, iw, n, ninv ); } } if l2 == 1 { return; } // row ffts let shifted = j << k1; let mut m = 0; for b in 0..usize::power_of_2(k1) { sd_fft_no_trunc_block(q, &mut xs[m..], s, k2, shifted + b); m += big_s_2; } } else if k == 1 { let (x0, x1) = xs.split_at_mut(big_s); if j_bits == 0 { radix_2_forward_param_j_is_z!(q, n, ninv); process_2_2!(radix_2_forward_moth_j_is_z, BLK_SZ, x0, x1, n, ninv); } else { radix_2_forward_param_j_is_nz!(q, j_r, j_bits, w, n, ninv); process_2_3!(radix_2_forward_moth_j_is_nz, BLK_SZ, x0, x1, w, n, ninv); } } } // This is LENGTH4_ZERO_J from fft_small/sd_fft.c, FLINT 3.3.0-dev, for vec1d. macro_rules! f64_length4_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: expr, $ninv: expr, $e14: expr ) => { let n = $n; let ninv = $ninv; *$x0 = f64_reduce_to_pm1n!(*$x0, n, ninv); *$x2 = f64_reduce_to_pm1n!(*$x2, n, ninv); *$x3 = f64_reduce_to_pm1n!(*$x3, n, ninv); let y0 = *$x0 + *$x2; let y1 = f64_reduce_to_pm1n!(*$x1 + *$x3, n, ninv); let y2 = *$x0 - *$x2; let y3 = f64_mulmod!(*$x1 - *$x3, $e14, n, ninv); *$x0 = y0 + y1; *$x1 = y0 - y1; *$x2 = y2 + y3; *$x3 = y2 - y3; }; } // This is LENGTH4_ZERO_J from fft_small/sd_fft.c, FLINT 3.3.0-dev, for vec4d. macro_rules! f64x4_length4_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: ident, $ninv: ident, $e14: ident ) => { $x0 = f64x4_reduce_to_pm1n!($x0, $n, $ninv); $x2 = f64x4_reduce_to_pm1n!($x2, $n, $ninv); $x3 = f64x4_reduce_to_pm1n!($x3, $n, $ninv); let y0 = $x0 + $x2; let y1 = f64x4_reduce_to_pm1n!($x1 + $x3, $n, $ninv); let y2 = $x0 - $x2; let y3 = f64x4_mulmod!($x1 - $x3, $e14, $n, $ninv); $x0 = y0 + y1; $x1 = y0 - y1; $x2 = y2 + y3; $x3 = y2 - y3; }; } // This is LENGTH4_ANY_J from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! length4_any_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: ident, $ninv: ident, $w2: ident, $w: ident, $iw: ident ) => { $x0 = f64x4_reduce_to_pm1n!($x0, $n, $ninv); $x2 = f64x4_mulmod!($x2, $w2, $n, $ninv); $x3 = f64x4_mulmod!($x3, $w2, $n, $ninv); let y0 = $x0 + $x2; let y1 = f64x4_mulmod!($x1 + $x3, $w, $n, $ninv); let y2 = $x0 - $x2; let y3 = f64x4_mulmod!($x1 - $x3, $iw, $n, $ninv); $x0 = y0 + y1; $x1 = y0 - y1; $x2 = y2 + y3; $x3 = y2 - y3; }; } // This is LENGTH8_ZERO_J from fft_small/sd_fft.c, FLINT 3.3.0-dev, for vec1d. macro_rules! f64_length8_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: expr, $ninv: expr, $e14: expr, $e18: expr, $e38: expr ) => { let n = $n; let ninv = $ninv; let e14 = $e14; let y0 = f64_reduce_to_pm1n!(*$x0 + *$x4, n, ninv); let y1 = f64_reduce_to_pm1n!(*$x1 + *$x5, n, ninv); let y2 = f64_reduce_to_pm1n!(*$x2 + *$x6, n, ninv); let y3 = f64_reduce_to_pm1n!(*$x3 + *$x7, n, ninv); let y4 = f64_reduce_to_pm1n!(*$x0 - *$x4, n, ninv); let y5 = f64_reduce_to_pm1n!(*$x1 - *$x5, n, ninv); let y6 = f64_mulmod!(e14, f64_reduce_to_pm1n!(*$x2 - *$x6, n, ninv), n, ninv); let y7 = f64_mulmod!(e14, f64_reduce_to_pm1n!(*$x3 - *$x7, n, ninv), n, ninv); let z0 = y0 + y2; let z1 = y1 + y3; let z2 = y0 - y2; let z3 = f64_mulmod!(e14, y1 - y3, n, ninv); let z4 = y4 + y6; let z5 = f64_mulmod!($e18, y5 + y7, n, ninv); let z6 = y4 - y6; let z7 = f64_mulmod!($e38, y5 - y7, n, ninv); *$x0 = z0 + z1; *$x1 = z0 - z1; *$x2 = z2 + z3; *$x3 = z2 - z3; *$x4 = z4 + z5; *$x5 = z4 - z5; *$x6 = z6 + z7; *$x7 = z6 - z7; }; } // This is LENGTH8_ZERO_J from fft_small/sd_fft.c, FLINT 3.3.0-dev, for vec4d. macro_rules! f64x4_length8_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: ident, $ninv: ident, $e14: ident, $e18: ident, $e38: ident ) => { let y0 = f64x4_reduce_to_pm1n!($x0 + $x4, $n, $ninv); let y1 = f64x4_reduce_to_pm1n!($x1 + $x5, $n, $ninv); let y2 = f64x4_reduce_to_pm1n!($x2 + $x6, $n, $ninv); let y3 = f64x4_reduce_to_pm1n!($x3 + $x7, $n, $ninv); let y4 = f64x4_reduce_to_pm1n!($x0 - $x4, $n, $ninv); let y5 = f64x4_reduce_to_pm1n!($x1 - $x5, $n, $ninv); let y6 = f64x4_mulmod!($e14, f64x4_reduce_to_pm1n!($x2 - $x6, $n, $ninv), $n, $ninv); let y7 = f64x4_mulmod!($e14, f64x4_reduce_to_pm1n!($x3 - $x7, $n, $ninv), $n, $ninv); let z0 = y0 + y2; let z1 = y1 + y3; let z2 = y0 - y2; let z3 = f64x4_mulmod!($e14, y1 - y3, $n, $ninv); let z4 = y4 + y6; let z5 = f64x4_mulmod!($e18, y5 + y7, $n, $ninv); let z6 = y4 - y6; let z7 = f64x4_mulmod!($e38, y5 - y7, $n, $ninv); $x0 = z0 + z1; $x1 = z0 - z1; $x2 = z2 + z3; $x3 = z2 - z3; $x4 = z4 + z5; $x5 = z4 - z5; $x6 = z6 + z7; $x7 = z6 - z7; }; } // This is LENGTH8_ANY_J from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! length8_any_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: ident, $ninv: ident, $w2: ident, $w: ident, $iw: ident, $ww0: ident, $ww1: ident, $ww2: ident, $ww3: ident ) => { $x0 = f64x4_reduce_to_pm1n!($x0, $n, $ninv); $x1 = f64x4_reduce_to_pm1n!($x1, $n, $ninv); $x4 = f64x4_mulmod!($x4, $w2, $n, $ninv); $x5 = f64x4_mulmod!($x5, $w2, $n, $ninv); $x6 = f64x4_mulmod!($x6, $w2, $n, $ninv); $x7 = f64x4_mulmod!($x7, $w2, $n, $ninv); let y0 = $x0 + $x4; let y1 = $x1 + $x5; let y2 = f64x4_mulmod!($x2 + $x6, $w, $n, $ninv); let y3 = f64x4_mulmod!($x3 + $x7, $w, $n, $ninv); let y4 = $x0 - $x4; let y5 = $x1 - $x5; let y6 = f64x4_mulmod!($x2 - $x6, $iw, $n, $ninv); let y7 = f64x4_mulmod!($x3 - $x7, $iw, $n, $ninv); let z0 = f64x4_reduce_to_pm1n!(y0 + y2, $n, $ninv); let z1 = f64x4_mulmod!(y1 + y3, $ww0, $n, $ninv); let z2 = f64x4_reduce_to_pm1n!(y0 - y2, $n, $ninv); let z3 = f64x4_mulmod!(y1 - y3, $ww1, $n, $ninv); let z4 = f64x4_reduce_to_pm1n!(y4 + y6, $n, $ninv); let z5 = f64x4_mulmod!(y5 + y7, $ww2, $n, $ninv); let z6 = f64x4_reduce_to_pm1n!(y4 - y6, $n, $ninv); let z7 = f64x4_mulmod!(y5 - y7, $ww3, $n, $ninv); $x0 = z0 + z1; $x1 = z0 - z1; $x2 = z2 + z3; $x3 = z2 - z3; $x4 = z4 + z5; $x5 = z4 - z5; $x6 = z6 + z7; $x7 = z6 - z7; }; } // This is vec4d_unpack_lo_permute_0_2_1_3 from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_unpack_lo_permute_0_2_1_3 { ($u: ident, $v: ident) => {{ let [u0, _, u2, _] = $u.to_array(); let [v0, _, v2, _] = $v.to_array(); f64x4::from([u0, u2, v0, v2]) }}; } // This is vec4d_unpack_hi_permute_0_2_1_3 from machine_vectors.h, FLINT 3.3.0-dev. macro_rules! f64x4_unpack_hi_permute_0_2_1_3 { ($u: ident, $v: ident) => {{ let [_, u1, _, u3] = $u.to_array(); let [_, v1, _, v3] = $v.to_array(); f64x4::from([u1, u3, v1, v3]) }}; } // view the 4 vectors as the rows of a 4x4 matrix // // This is VEC4D_TRANSPOSE from machine_vectors.h, FLINT 3.3.0-dev, modifying the vectors in place. macro_rules! f64x4_transpose { ($a0: ident, $a1: ident, $a2: ident, $a3: ident) => {{ let [a00, a01, a02, a03] = $a0.to_array(); let [a10, a11, a12, a13] = $a1.to_array(); let [a20, a21, a22, a23] = $a2.to_array(); let [a30, a31, a32, a33] = $a3.to_array(); $a0 = f64x4::from([a00, a10, a20, a30]); $a1 = f64x4::from([a01, a11, a21, a31]); $a2 = f64x4::from([a02, a12, a22, a32]); $a3 = f64x4::from([a03, a13, a23, a33]); }}; } // This is sd_fft_basecase_0_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. const fn sd_fft_basecase_0_1(_q: &FFTContext, _xs: &mut [f64]) {} // This is sd_fft_basecase_1_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_1_1(q: &FFTContext, xs: &mut [f64]) { let n = q.p; let ninv = q.pinv; let x0 = f64_reduce_to_pm1n!(xs[0], n, ninv); let x1 = f64_reduce_to_pm1n!(xs[1], n, ninv); xs[0] = x0 + x1; xs[1] = x0 - x1; } // This is sd_fft_basecase_2_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_2_1(q: &FFTContext, xs: &mut [f64]) { if let &mut [ref mut x0, ref mut x1, ref mut x2, ref mut x3, ..] = xs { f64_length4_zero_j!(x0, x1, x2, x3, q.p, q.pinv, w2tab!(q, 1, 0)); } } // This is sd_fft_basecase_3_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_3_1(q: &FFTContext, xs: &mut [f64]) { if let &mut [ ref mut x0, ref mut x1, ref mut x2, ref mut x3, ref mut x4, ref mut x5, ref mut x6, ref mut x7, .., ] = xs { f64_length8_zero_j!( x0, x1, x2, x3, x4, x5, x6, x7, q.p, q.pinv, w2tab!(q, 1, 0), w2tab!(q, 2, 0), w2tab!(q, 2, 1) ); } } // This is sd_fft_basecase_4_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_4_1(q: &FFTContext, xs: &mut [f64]) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); // q.w2tab[0] points to consecutive entries const _: () = assert!(SD_FFT_CTX_W2TAB_INIT >= 4); let iw = f64x4::splat(w2tab!(q, 0, 1)); f64x4_length4_zero_j!(x0, x1, x2, x3, n, ninv, iw); let u = read_f64x4_w2tab!(q, 0, 0); let v = read_f64x4_w2tab!(q, 0, 4); let w = f64x4_unpack_lo_permute_0_2_1_3!(u, v); let iw = f64x4_unpack_hi_permute_0_2_1_3!(u, v); f64x4_transpose!(x0, x1, x2, x3); length4_any_j!(x0, x1, x2, x3, n, ninv, u, w, iw); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); } // This is sd_fft_basecase_4_0 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_4_0(q: &FFTContext, xs: &mut [f64], j_r: usize, j_bits: u64) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let j_bits = usize::exact_from(j_bits); let w2 = f64x4::splat(w2tab!(q, j_bits, j_r)); let jp1 = j_bits + 1; let j_2 = j_r << 1; let w = f64x4::splat(w2tab!(q, jp1, j_2)); let iw = f64x4::splat(w2tab!(q, jp1, j_2 + 1)); length4_any_j!(x0, x1, x2, x3, n, ninv, w2, w, iw); let jp3 = j_bits + 3; let j_8 = j_r << 3; let u = read_f64x4_w2tab!(q, jp3, j_8); let v = read_f64x4_w2tab!(q, jp3, j_8 + 4); let w2 = read_f64x4_w2tab!(q, j_bits + 2, j_r << 2); let w = f64x4_unpack_lo_permute_0_2_1_3!(u, v); let iw = f64x4_unpack_hi_permute_0_2_1_3!(u, v); f64x4_transpose!(x0, x1, x2, x3); length4_any_j!(x0, x1, x2, x3, n, ninv, w2, w, iw); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); } // The length 32 transform can be broken up as // - 8 transforms of length 4 within columns, followed by 4 transforms of length 8 in the rows, or // - 4 transforms of length 8 within columns, followed by 8 transforms of length 4 in the rows // Since the length 16 basecase is missing the final 4x4 transpose, so the output is worse than // bit-reversed. If the length 32 transform used a order different from 16's, then we will have a // problem at a higher level since it would be difficult to keep track of what basecase happened to // have be used. Therefore, the length 16 and 32 basecases should produce the same order, and this // is easier with (b). // // This is sd_fft_basecase_5_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_5_1(q: &FFTContext, xs: &mut [f64]) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let mut x4 = read_f64x4!(xs, 16); let mut x5 = read_f64x4!(xs, 20); let mut x6 = read_f64x4!(xs, 24); let mut x7 = read_f64x4!(xs, 28); let q00 = w2tab!(q, 0, 0); let q10 = w2tab!(q, 1, 0); let q20 = w2tab!(q, 2, 0); let q21 = w2tab!(q, 2, 1); let ww1 = f64x4::splat(q10); let www2 = f64x4::splat(q20); let www3 = f64x4::splat(q21); f64x4_length8_zero_j!(x0, x1, x2, x3, x4, x5, x6, x7, n, ninv, ww1, www2, www3); f64x4_transpose!(x0, x1, x2, x3); f64x4_transpose!(x4, x5, x6, x7); // j = 0, 1, 2, 3 let mut w0 = f64x4::from([q00, q10, q20, q21]); let mut ww0 = f64x4::from([q00, q20, w2tab!(q, 3, 0), w2tab!(q, 3, 2)]); let mut ww1 = f64x4::from([q10, q21, w2tab!(q, 3, 1), w2tab!(q, 3, 3)]); length4_any_j!(x0, x1, x2, x3, n, ninv, w0, ww0, ww1); // j = 4, 5, 6, 7 w0 = f64x4::from([w2tab!(q, 3, 0), w2tab!(q, 3, 1), w2tab!(q, 3, 2), w2tab!(q, 3, 3)]); let u = read_f64x4_w2tab!(q, 4, 0); let v = read_f64x4_w2tab!(q, 4, 4); ww0 = f64x4_unpack_lo_permute_0_2_1_3!(u, v); ww1 = f64x4_unpack_hi_permute_0_2_1_3!(u, v); length4_any_j!(x4, x5, x6, x7, n, ninv, w0, ww0, ww1); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); write_f64x4!(xs, 16, x4); write_f64x4!(xs, 20, x5); write_f64x4!(xs, 24, x6); write_f64x4!(xs, 28, x7); } // This is sd_fft_basecase_5_0 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_basecase_5_0(q: &FFTContext, xs: &mut [f64], j_r: usize, j_bits: u64) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let mut x4 = read_f64x4!(xs, 16); let mut x5 = read_f64x4!(xs, 20); let mut x6 = read_f64x4!(xs, 24); let mut x7 = read_f64x4!(xs, 28); let j_bits = usize::exact_from(j_bits); let w0 = f64x4::splat(w2tab!(q, j_bits, j_r)); let jp1 = j_bits + 1; let j_2 = j_r << 1; let ww0 = f64x4::splat(w2tab!(q, jp1, j_2)); let ww1 = f64x4::splat(w2tab!(q, jp1, j_2 + 1)); let jp2 = j_bits + 2; let j_4 = j_r << 2; let www0 = f64x4::splat(w2tab!(q, jp2, j_4)); let www1 = f64x4::splat(w2tab!(q, jp2, j_4 + 1)); let www2 = f64x4::splat(w2tab!(q, jp2, j_4 + 2)); let www3 = f64x4::splat(w2tab!(q, jp2, j_4 + 3)); length8_any_j!( x0, x1, x2, x3, x4, x5, x6, x7, n, ninv, w0, ww0, ww1, www0, www1, www2, www3 ); f64x4_transpose!(x0, x1, x2, x3); f64x4_transpose!(x4, x5, x6, x7); // j = 8*j+0, 8*j+1, 8*j+2, 8*j+3 let jp3 = j_bits + 3; let jp4 = j_bits + 4; let j_8 = j_r << 3; let w0 = read_f64x4_w2tab!(q, jp3, j_8); let sixteen_j = j_r << 4; let u = read_f64x4_w2tab!(q, jp4, sixteen_j); let v = read_f64x4_w2tab!(q, jp4, sixteen_j + 4); let ww0 = f64x4_unpack_lo_permute_0_2_1_3!(u, v); let ww1 = f64x4_unpack_hi_permute_0_2_1_3!(u, v); length4_any_j!(x0, x1, x2, x3, n, ninv, w0, ww0, ww1); // j = 8*j+4, 8*j+5, 8*j+6, 8*j+7 let w0 = read_f64x4_w2tab!(q, jp3, j_8 + 4); let u = read_f64x4_w2tab!(q, jp4, sixteen_j + 8); let v = read_f64x4_w2tab!(q, jp4, sixteen_j + 12); let ww0 = f64x4_unpack_lo_permute_0_2_1_3!(u, v); let ww1 = f64x4_unpack_hi_permute_0_2_1_3!(u, v); length4_any_j!(x4, x5, x6, x7, n, ninv, w0, ww0, ww1); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); write_f64x4!(xs, 16, x4); write_f64x4!(xs, 20, x5); write_f64x4!(xs, 24, x6); write_f64x4!(xs, 28, x7); } macro_rules! sd_fft_basecase { ($n: expr, $f0: ident, $f1: ident, $fs0: ident, $fs1: ident) => { // This is sd_fft_basecase_n_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn $f1(q: &FFTContext, xs: &mut [f64]) { const LIMIT: usize = 1 << ($n - 2); radix_4_forward_param_j_is_z!(q, iw, n, ninv); split_into_chunks_mut!(xs, LIMIT, [xs0, xs1, xs2], xs3); process_4_3!( radix_4_forward_moth_j_is_z, LIMIT, xs0, xs1, xs2, xs3, iw, n, ninv ); $fs1(q, xs0); $fs0(q, xs1, 0, 1); $fs0(q, xs2, 0, 2); $fs0(q, xs3, 1, 2); } // This is sd_fft_basecase_n_0 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn $f0(q: &FFTContext, xs: &mut [f64], j_r: usize, j_bits: u64) { const LIMIT: usize = 1 << ($n - 2); radix_4_forward_param_j_is_nz!(q, j_r, j_bits, w, w2, iw, n, ninv); split_into_chunks_mut!(xs, LIMIT, [xs0, xs1, xs2], xs3); process_4_5!( radix_4_forward_moth_j_is_nz, LIMIT, xs0, xs1, xs2, xs3, w, w2, iw, n, ninv ); let j_r_4 = j_r << 2; let j_bits_p_2 = j_bits + 2; $fs0(q, xs0, j_r_4, j_bits_p_2); $fs0(q, xs1, j_r_4 + 1, j_bits_p_2); $fs0(q, xs2, j_r_4 + 2, j_bits_p_2); $fs0(q, xs3, j_r_4 + 3, j_bits_p_2); } }; } sd_fft_basecase!( 6, sd_fft_basecase_6_0, sd_fft_basecase_6_1, sd_fft_basecase_4_0, sd_fft_basecase_4_1 ); sd_fft_basecase!( 7, sd_fft_basecase_7_0, sd_fft_basecase_7_1, sd_fft_basecase_5_0, sd_fft_basecase_5_1 ); sd_fft_basecase!( 8, sd_fft_basecase_8_0, sd_fft_basecase_8_1, sd_fft_basecase_6_0, sd_fft_basecase_6_1 ); sd_fft_basecase!( 9, sd_fft_basecase_9_0, sd_fft_basecase_9_1, sd_fft_basecase_7_0, sd_fft_basecase_7_1 ); // parameter 1: j can be zero // // This is sd_fft_base_8_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_base_8_1(q: &FFTContext, xs: &mut [f64], j: usize) { set_j_bits_and_j_r!(j, j_bits, j_r); if j == 0 { sd_fft_basecase_8_1(q, xs); } else { sd_fft_basecase_8_0(q, xs, j_r, j_bits); } } // parameter 0: j cannot be zero // // This is sd_fft_base_8_0 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_base_8_0(q: &FFTContext, xs: &mut [f64], j: usize) { assert_ne!(j, 0); set_j_bits_and_j_r!(j, j_bits, j_r); sd_fft_basecase_8_0(q, xs, j_r, j_bits); } // This is sd_fft_base_9_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_base_9_1(q: &FFTContext, xs: &mut [f64], j: usize) { set_j_bits_and_j_r!(j, j_bits, j_r); if j == 0 { sd_fft_basecase_9_1(q, xs); } else { sd_fft_basecase_9_0(q, xs, j_r, j_bits); } } // This is sd_fft_no_trunc_internal from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_no_trunc_internal( q: &FFTContext, xs: &mut [f64], // stride s: usize, // 1 transform of length BLK_SZ*2^k k: u64, // twist param j: usize, ) { if k > 2 { let k1 = k >> 1; let k2 = k - k1; // column ffts let shift = s << k2; let big_s = s << LG_BLK_SZ; let mut m = 0; for _ in 0..usize::power_of_2(k2) { sd_fft_no_trunc_block(q, &mut xs[m..], shift, k1, j); m += big_s; } // row ffts let shift = k2 + LG_BLK_SZ; let shifted = j << k1; let big_s = s << shift; let mut m = 0; for b in 0..usize::power_of_2(k1) { sd_fft_no_trunc_internal(q, &mut xs[m..], s, k2, shifted + b); m += big_s; } return; } if k == 2 { // k1 = 2; k2 = 0 sd_fft_no_trunc_block(q, xs, s, 2, j); split_into_chunks_mut!(xs, s << LG_BLK_SZ, [xs0, xs1, xs2], xs3); let j_4 = j << 2; sd_fft_base_8_1(q, xs0, j_4); sd_fft_base_8_0(q, xs1, j_4 + 1); sd_fft_base_8_0(q, xs2, j_4 + 2); sd_fft_base_8_0(q, xs3, j_4 + 3); } else if k == 1 { sd_fft_base_9_1(q, xs, j); } else { // currently unreachable because all ffts are called with k > 0 sd_fft_base_8_1(q, xs, j); } } // This is sd_fft_moth_trunc_block_i_j_1 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_moth_trunc_block_1( q: &FFTContext, _j_r: usize, _j_bits: u64, xs: &mut [f64], gap: usize, ) { radix_4_forward_param_j_is_z!(q, iw, n, ninv); let gap_2 = gap << 1; let gap_3 = gap_2 + gap; for i in (0..BLK_SZ).step_by(BIG_N) { let mut x0 = f64x8::default(); let mut x1 = f64x8::default(); let mut x2 = f64x8::default(); let mut x3 = f64x8::default(); if 0 < ITRUNC { x0 = read_f64x8!(xs, i); } if 0 < ITRUNC { x0 = f64x8_reduce_to_pm1n!(x0, n, ninv); } if 1 < ITRUNC { x1 = read_f64x8!(xs, gap + i); } if 2 < ITRUNC { x2 = read_f64x8!(xs, gap_2 + i); } if 2 < ITRUNC { x2 = f64x8_reduce_to_pm1n!(x2, n, ninv); } if 3 < ITRUNC { x3 = read_f64x8!(xs, gap_3 + i); } if 3 < ITRUNC { x3 = f64x8_reduce_to_pm1n!(x3, n, ninv); } let y0 = if 2 < ITRUNC { x0 + x2 } else { x0 }; let mut y1 = if 3 < ITRUNC { x1 + x3 } else { x1 }; let y2 = if 2 < ITRUNC { x0 - x2 } else { x0 }; let mut y3 = if 3 < ITRUNC { x1 - x3 } else { x1 }; y1 = f64x8_reduce_to_pm1n!(y1, n, ninv); y3 = f64x8_mulmod!(y3, iw, n, ninv); x0 = y0 + y1; x1 = y0 - y1; x2 = y2 + y3; x3 = y2 - y3; if 0 < OTRUNC { write_f64x8!(xs, i, x0); } if 1 < OTRUNC { write_f64x8!(xs, gap + i, x1); } if 2 < OTRUNC { write_f64x8!(xs, gap_2 + i, x2); } if 3 < OTRUNC { write_f64x8!(xs, gap_3 + i, x3); } } } // This is sd_fft_moth_trunc_block_i_j_0 from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_moth_trunc_block_0( q: &FFTContext, j_r: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { radix_4_forward_param_j_is_nz!(q, j_r, j_bits, w, w2, iw, n, ninv); let gap_2 = gap << 1; let gap_3 = gap_2 + gap; for i in (0..BLK_SZ).step_by(BIG_N) { let mut x0 = f64x8::default(); let mut x1 = f64x8::default(); let mut x2 = f64x8::default(); let mut x3 = f64x8::default(); if 0 < ITRUNC { x0 = read_f64x8!(xs, i); } if 0 < ITRUNC { x0 = f64x8_reduce_to_pm1n!(x0, n, ninv); } if 1 < ITRUNC { x1 = read_f64x8!(xs, gap + i); } if 2 < ITRUNC { x2 = read_f64x8!(xs, gap_2 + i); } if 2 < ITRUNC { x2 = f64x8_mulmod!(x2, w2, n, ninv); } if 3 < ITRUNC { x3 = read_f64x8!(xs, gap_3 + i); } if 3 < ITRUNC { x3 = f64x8_mulmod!(x3, w2, n, ninv); } let y0 = if 2 < ITRUNC { x0 + x2 } else { x0 }; let mut y1 = if 3 < ITRUNC { x1 + x3 } else { x1 }; let y2 = if 2 < ITRUNC { x0 - x2 } else { x0 }; let mut y3 = if 3 < ITRUNC { x1 - x3 } else { x1 }; y1 = f64x8_mulmod!(y1, w, n, ninv); y3 = f64x8_mulmod!(y3, iw, n, ninv); x0 = y0 + y1; x1 = y0 - y1; x2 = y2 + y3; x3 = y2 - y3; if 0 < OTRUNC { write_f64x8!(xs, i, x0); } if 1 < OTRUNC { write_f64x8!(xs, gap + i, x1); } if 2 < OTRUNC { write_f64x8!(xs, gap_2 + i, x2); } if 3 < OTRUNC { write_f64x8!(xs, gap_3 + i, x3); } } } type Sd2MothTruncBlockFn = for<'a, 'b, 'c, 'd> fn(&'a FFTContext, usize, &'b mut [f64], &'c mut [f64]); type Sd4MothTruncBlockFn = for<'a, 'b, 'c> fn(&'a FFTContext, usize, u64, &'b mut [f64], usize); const SD_FFT_4_MOTH_TRUNC_BLOCK_TABLE: [Sd4MothTruncBlockFn; 24] = [ sd_fft_moth_trunc_block_0::<2, 1>, sd_fft_moth_trunc_block_1::<2, 1>, sd_fft_moth_trunc_block_0::<2, 2>, sd_fft_moth_trunc_block_1::<2, 2>, sd_fft_moth_trunc_block_0::<2, 3>, sd_fft_moth_trunc_block_1::<2, 3>, sd_fft_moth_trunc_block_0::<2, 4>, sd_fft_moth_trunc_block_1::<2, 4>, sd_fft_moth_trunc_block_0::<3, 1>, sd_fft_moth_trunc_block_1::<3, 1>, sd_fft_moth_trunc_block_0::<3, 2>, sd_fft_moth_trunc_block_1::<3, 2>, sd_fft_moth_trunc_block_0::<3, 3>, sd_fft_moth_trunc_block_1::<3, 3>, sd_fft_moth_trunc_block_0::<3, 4>, sd_fft_moth_trunc_block_1::<3, 4>, sd_fft_moth_trunc_block_0::<4, 1>, sd_fft_moth_trunc_block_1::<4, 1>, sd_fft_moth_trunc_block_0::<4, 2>, sd_fft_moth_trunc_block_1::<4, 2>, sd_fft_moth_trunc_block_0::<4, 3>, sd_fft_moth_trunc_block_1::<4, 3>, sd_fft_moth_trunc_block_0::<4, 4>, sd_fft_moth_trunc_block_1::<4, 4>, ]; // This is RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_Z from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_2_forward_moth_trunc_2_1_j_is_z { ($x0: ident, $x1: ident, $n: ident, $ninv: ident) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x1 = f64x8_reduce_to_pm1n!($x1, $n, $ninv); $x0 += $x1; }; } // This is RADIX_2_FORWARD_MOTH_TRUNC_2_1_J_IS_NZ from fft_small/sd_fft.c, FLINT 3.3.0-dev. macro_rules! radix_2_forward_moth_trunc_2_1_j_is_nz { ($x0: ident, $x1: ident, $w: ident, $n: ident, $ninv: ident) => { $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x1 = f64x8_mulmod!($x1, $w, $n, $ninv); $x0 += $x1; }; } // This is sd_fft_trunc_block from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_trunc_block( q: &FFTContext, xs: &mut [f64], s: usize, // transform length 2^k k: u64, j: usize, itrunc: usize, otrunc: usize, ) { let pow = usize::power_of_2(k); assert!(itrunc <= pow); assert!(otrunc <= pow); if otrunc < 1 { fail_on_untested_path("sd_fft_trunc_block, otrunc < 1"); return; } if itrunc <= 1 { let big_s = s << LG_BLK_SZ; if itrunc < 1 { fail_on_untested_path("sd_fft_trunc_block, itrunc < 1"); for c in xs[..big_s * otrunc].chunks_mut(big_s) { c[..BLK_SZ].fill(0.0); } } else { let mut m = big_s; for _ in 1..otrunc { let (xs_lo, xs_hi) = xs.split_at_mut(m); xs_hi[..BLK_SZ].copy_from_slice(&xs_lo[..BLK_SZ]); m += big_s; } } return; } if itrunc == otrunc && otrunc == pow { sd_fft_no_trunc_block(q, xs, s, k, j); return; } let big_s = s << LG_BLK_SZ; if k > 2 { let k1 = k >> 1; let k2 = k - k1; let l2 = usize::power_of_2(k2); let n1 = otrunc >> k2; let mask = l2 - 1; let n2 = otrunc & mask; let z1 = itrunc >> k2; let z2 = itrunc & mask; let n1p = n1 + usize::from(n2 != 0); let z2p = min(l2, itrunc); // columns let shifted = s << k2; let mut m = 0; for a in 0..z2p { sd_fft_trunc_block( q, &mut xs[m..], shifted, k1, j, z1 + usize::from(a < z2), n1p, ); m += big_s; } // full rows let big_s_2 = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut m = 0; for b in 0..n1 { sd_fft_trunc_block(q, &mut xs[m..], s, k2, shifted + b, z2p, l2); m += big_s_2; } // last partial row if n2 != 0 { sd_fft_trunc_block(q, &mut xs[n1 * big_s_2..], s, k2, shifted + n1, z2p, n2); } return; } set_j_bits_and_j_r!(j, j_bits, j_r); if k == 2 { let index = usize::from(j == 0) + ((otrunc - 1 + ((itrunc - 2) << 2)) << 1); SD_FFT_4_MOTH_TRUNC_BLOCK_TABLE[index](q, j_r, j_bits, xs, big_s); } else if k == 1 { let (xs0, xs1) = xs.split_at_mut(big_s); assert_eq!(itrunc, 2); assert_eq!(otrunc, 1); if j_bits == 0 { fail_on_untested_path("sd_fft_trunc_block, j_bits == 0"); radix_2_forward_param_j_is_z!(q, n, ninv); process_2_2!( radix_2_forward_moth_trunc_2_1_j_is_z, BLK_SZ, xs0, xs1, n, ninv ); } else { radix_2_forward_param_j_is_nz!(q, j_r, j_bits, w, n, ninv); process_2_3!( radix_2_forward_moth_trunc_2_1_j_is_nz, BLK_SZ, xs0, xs1, w, n, ninv ); } } } // This is sd_fft_trunc_internal from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_trunc_internal( q: &FFTContext, // x = data + BLK_SZ*I where I = starting index xs: &mut [f64], // stride s: usize, // transform length BLK_SZ*2^k k: u64, j: usize, // actual trunc is BLK_SZ*itrunc itrunc: usize, // actual trunc is BLK_SZ*otrunc otrunc: usize, ) { if otrunc < 1 { fail_on_untested_path("sd_fft_trunc_internal, otrunc < 1"); return; } if itrunc < 1 { fail_on_untested_path("sd_fft_trunc_internal, itrunc < 1"); let big_s = s << LG_BLK_SZ; for c in xs[..big_s * otrunc].chunks_mut(big_s) { c[..BLK_SZ].fill(0.0); } return; } if itrunc == otrunc && otrunc == usize::power_of_2(k) { sd_fft_no_trunc_internal(q, xs, s, k, j); return; } let big_s = s << LG_BLK_SZ; if k > 2 { let k1 = k >> 1; let k2 = k - k1; let l2 = usize::power_of_2(k2); let n1 = otrunc >> k2; let mask = l2 - 1; let n2 = otrunc & mask; let z1 = itrunc >> k2; let z2 = itrunc & mask; let n1p = n1 + usize::from(n2 != 0); let z2p = min(l2, itrunc); // columns let shifted = s << k2; let mut m = 0; for a in 0..z2p { sd_fft_trunc_block( q, &mut xs[m..], shifted, k1, j, z1 + usize::from(a < z2), n1p, ); m += big_s; } // full rows let big_s_2 = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut m = 0; for b in 0..n1 { sd_fft_trunc_internal(q, &mut xs[m..], s, k2, shifted + b, z2p, l2); m += big_s_2; } // last partial row if n2 > 0 { sd_fft_trunc_internal(q, &mut xs[n1 * big_s_2..], s, k2, shifted + n1, z2p, n2); } return; } if k == 2 { sd_fft_trunc_block(q, xs, s, 2, j, itrunc, otrunc); let j_4 = j << 2; sd_fft_base_8_1(q, xs, j_4); if otrunc > 1 { sd_fft_base_8_0(q, &mut xs[big_s..], j_4 + 1); } if otrunc > 2 { sd_fft_base_8_0(q, &mut xs[big_s << 1..], j_4 + 2); } if otrunc > 3 { sd_fft_base_8_0(q, &mut xs[big_s * 3..], j_4 + 3); } } else if k == 1 { sd_fft_trunc_block(q, xs, s, 1, j, itrunc, otrunc); let j_2 = j << 1; sd_fft_base_8_1(q, xs, j_2); if otrunc > 1 { sd_fft_base_8_0(q, &mut xs[big_s..], j_2 + 1); } } else { // currently unreachable sd_fft_base_8_1(q, xs, j); } } // This is sd_fft_ctx_fit_depth_with_lock from fft_small/sd_fft_ctx.c, FLINT 3.3.0-dev. fn sd_fft_ctx_fit_depth_with_lock(q: &mut FFTContext, depth: u64) { for k in q.w2tab_depth..depth { let ww = q .primitive_root .mod_pow((q.mod_data.n - 1) >> (k + 1), q.mod_data.n); let w = f64x8::splat(f64_reduce_0n_to_pmhn!(ww as f64, q.p)); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let big_n = usize::power_of_2(k - 1); let old_len = q.w2tab_backing.len(); q.w2tab_backing.resize( old_len + big_n.round_to_multiple_of_power_of_2(12, Ceiling).0, 0.0, ); let ku = k as usize; q.w2tab_offsets[ku] = old_len; // The first few tables are stored consecutively, so vec16 is ok. let mut off = 0; let mut l = const { 1 << (SD_FFT_CTX_W2TAB_INIT - 1) }; let mut kk = 0; for j in SD_FFT_CTX_W2TAB_INIT - 1..k { for i in (0..l).step_by(16) { let x0 = read_f64x8_w2tab!(q, kk, i); let x1 = read_f64x8_w2tab!(q, kk, i + 8); let y0 = f64x8_reduce_pm1n_to_pmhn!(f64x8_mulmod!(x0, w, n, ninv), n); let y1 = f64x8_reduce_pm1n_to_pmhn!(f64x8_mulmod!(x1, w, n, ninv), n); write_f64x8_w2tab!(q, ku, off + i, y0); write_f64x8_w2tab!(q, ku, off + i + 8, y1); } kk = j as usize + 1; l += off; off = l; } q.w2tab_depth = k; } } // This is sd_fft_ctx_fit_depth from fft_small.h, FLINT 3.3.0-dev. fn sd_fft_ctx_fit_depth(q: &mut FFTContext, depth: u64) { if q.w2tab_depth < depth { sd_fft_ctx_fit_depth_with_lock(q, depth); } } // This is sd_fft_trunc from fft_small/sd_fft.c, FLINT 3.3.0-dev. fn sd_fft_trunc( q: &mut FFTContext, ds: &mut [f64], // convolution length 2^L l: u64, itrunc: usize, otrunc: usize, ) { let pow = usize::power_of_2(l); assert!(itrunc <= pow); assert!(otrunc <= pow); if l > LG_BLK_SZ { sd_fft_ctx_fit_depth(q, l); let new_itrunc = itrunc.div_round(BLK_SZ, Ceiling).0; let new_otrunc = otrunc.div_round(BLK_SZ, Ceiling).0; ds[itrunc..][..itrunc.wrapping_neg() & const { BLK_SZ - 1 }].fill(0.0); sd_fft_trunc_internal(q, ds, 1, l - LG_BLK_SZ, 0, new_itrunc, new_otrunc); return; } fail_on_untested_path("sd_fft_trunc, l <= LG_BLK_SZ"); ds[itrunc..][..usize::power_of_2(l)].fill(0.0); // L=8 reads from w2tab[7] const _: () = assert!(LG_BLK_SZ <= SD_FFT_CTX_W2TAB_INIT); match l { 0 => sd_fft_basecase_0_1(q, ds), 1 => sd_fft_basecase_1_1(q, ds), 2 => sd_fft_basecase_2_1(q, ds), 3 => sd_fft_basecase_3_1(q, ds), 4 => sd_fft_basecase_4_1(q, ds), 5 => sd_fft_basecase_5_1(q, ds), 6 => sd_fft_basecase_6_1(q, ds), 7 => sd_fft_basecase_7_1(q, ds), 8 => sd_fft_basecase_8_1(q, ds), _ => unreachable!(), } } // for the ifft look up of powers of w^-1: the remainder has to be flipped // // This is SET_J_BITS_AND_J_MR from fft_small.h, FLINT 3.3.0-dev, returning j_bits and j_mr. macro_rules! set_j_bits_and_j_mr { ($j: ident, $j_bits: ident, $j_mr: ident) => { let ($j_bits, $j_mr) = if $j == 0 { (0, 0) } else { let j_bits = n_nbits_nz!($j); (j_bits, usize::power_of_2(j_bits) - 1 - $j) }; }; } // This is RADIX_4_REVERSE_PARAM_J_IS_Z from fft_small/sd_ifft.c, FLINT 3.3.0-dev, returning iw, n, // and ninv. macro_rules! radix_4_reverse_param_j_is_z { ($q: ident, $iw: ident, $n: ident, $ninv: ident) => { let $iw = f64x8::splat(w2tab!($q, 0, 1)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_4_REVERSE_PARAM_J_IS_NZ from fft_small/sd_ifft.c, FLINT 3.3.0-dev, returning w, w2, // iw, n, and ninv. macro_rules! radix_4_reverse_param_j_is_nz { ( $q: ident, $j_mr: ident, $j_bits: ident, $w: ident, $w2: ident, $iw: ident, $n: ident, $ninv: ident ) => { let j_bits = usize::exact_from($j_bits); let jp1 = j_bits + 1; let j_2 = $j_mr << 1; let $w = f64x8::splat(w2tab!($q, jp1, j_2 + 1)); let $w2 = f64x8::splat(w2tab!($q, j_bits, $j_mr)); let $iw = f64x8::splat(w2tab!($q, jp1, j_2)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_4_REVERSE_MOTH_J_IS_Z from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! radix_4_reverse_moth_j_is_z { ($x0: ident, $x1: ident, $x2: ident, $x3: ident, $iw: ident, $n: ident, $ninv: ident ) => { let mut y0 = $x0 + $x1; let mut y1 = $x2 + $x3; let mut y2 = $x0 - $x1; let mut y3 = $x2 - $x3; y0 = f64x8_reduce_to_pm1n!(y0, $n, $ninv); y1 = f64x8_reduce_to_pm1n!(y1, $n, $ninv); y2 = f64x8_reduce_to_pm1n!(y2, $n, $ninv); y3 = f64x8_mulmod!(y3, $iw, $n, $ninv); $x0 = y0 + y1; $x2 = y0 - y1; $x1 = y2 - y3; $x3 = y2 + y3; }; } // This is RADIX_4_REVERSE_MOTH_J_IS_NZ from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! radix_4_reverse_moth_j_is_nz { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $w: ident, $w2: ident, $iw: ident, $n: ident, $ninv: ident ) => { let y0 = $x0 + $x1; let y1 = $x2 + $x3; let y2 = f64x8_mulmod!($x0 - $x1, $w, $n, $ninv); let y3 = f64x8_mulmod!($x3 - $x2, $iw, $n, $ninv); $x0 = y0 + y1; $x1 = y3 - y2; $x2 = y1 - y0; $x3 = y3 + y2; $x0 = f64x8_reduce_to_pm1n!($x0, $n, $ninv); $x2 = f64x8_mulmod!($x2, $w2, $n, $ninv); $x3 = f64x8_mulmod!($x3, $w2, $n, $ninv); }; } // This is RADIX_2_REVERSE_PARAM_J_IS_Z from fft_small/sd_ifft.c, FLINT 3.3.0-dev, returning n and // ninv. macro_rules! radix_2_reverse_param_j_is_z { ($q: ident, $n: ident, $ninv: ident) => { let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_2_REVERSE_PARAM_J_IS_NZ from fft_small/sd_ifft.c, FLINT 3.3.0-dev, returning w, n, // and ninv. macro_rules! radix_2_reverse_param_j_is_nz { ( $q: ident, $j_mr: ident, $j_bits: ident, $w: ident, $n: ident, $ninv: ident ) => { let $w = f64x8::splat(w2tab!($q, usize::exact_from($j_bits), $j_mr)); let $n = f64x8::splat($q.p); let $ninv = f64x8::splat($q.pinv); }; } // This is RADIX_2_REVERSE_MOTH_J_IS_Z from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! radix_2_reverse_moth_j_is_z { ($x0: ident, $x1: ident, $n: ident, $ninv: ident) => { let y0 = f64x8_reduce_to_pm1n!($x0 + $x1, $n, $ninv); let y1 = f64x8_reduce_to_pm1n!($x0 - $x1, $n, $ninv); $x0 = y0; $x1 = y1; }; } // This is RADIX_2_REVERSE_MOTH_J_IS_NZ from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! radix_2_reverse_moth_j_is_nz { ($x0: ident, $x1: ident, $w: ident, $n: ident, $ninv: ident) => { let y0 = f64x8_reduce_to_pm1n!($x0 + $x1, $n, $ninv); let y1 = f64x8_mulmod!($x1 - $x0, $w, $n, $ninv); $x0 = y0; $x1 = y1; }; } // This is sd_ifft_no_trunc_block from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_no_trunc_block( q: &FFTContext, xs: &mut [f64], // stride s: usize, // BLK_SZ transforms each of length 2^k k: u64, j: usize, ) { let big_s = s << LG_BLK_SZ; if k > 2 { let k1 = k >> 1; let k2 = k - k1; // row ffts let big_s_2 = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut m = 0; for b in 0..usize::power_of_2(k1) { sd_ifft_no_trunc_block(q, &mut xs[m..], s, k2, shifted + b); m += big_s_2; } // column ffts let shifted = s << k2; let mut m = 0; for _ in 0..usize::power_of_2(k2) { sd_ifft_no_trunc_block(q, &mut xs[m..], shifted, k1, j); m += big_s; } return; } set_j_bits_and_j_mr!(j, j_bits, j_mr); if k == 2 { split_into_chunks_mut!(xs, big_s, [xs0, xs1, xs2], xs3); if j_bits == 0 { radix_4_reverse_param_j_is_z!(q, iw, n, ninv); process_4_3!( radix_4_reverse_moth_j_is_z, BLK_SZ, xs0, xs1, xs2, xs3, iw, n, ninv ); } else { radix_4_reverse_param_j_is_nz!(q, j_mr, j_bits, w, w2, iw, n, ninv); process_4_5!( radix_4_reverse_moth_j_is_nz, BLK_SZ, xs0, xs1, xs2, xs3, w, w2, iw, n, ninv ); } } else if k == 1 { let (xs0, xs1) = xs.split_at_mut(big_s); if j_bits == 0 { radix_2_reverse_param_j_is_z!(q, n, ninv); process_2_2!(radix_2_reverse_moth_j_is_z, BLK_SZ, xs0, xs1, n, ninv); } else { radix_2_reverse_param_j_is_nz!(q, j_mr, j_bits, w, n, ninv); process_2_3!(radix_2_reverse_moth_j_is_nz, BLK_SZ, xs0, xs1, w, n, ninv); } } } // This is LENGTH2INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64_length2inv_zero_j_mut { ($x0: ident, $x1: ident, $n: expr, $ninv: expr) => { (*$x0, *$x1) = ( f64_reduce_to_pm1n!(*$x0 + *$x1, $n, $ninv), f64_reduce_to_pm1n!(*$x0 - *$x1, $n, $ninv), ); }; } // This is LENGTH2INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length2inv_zero_j { ($x0: ident, $x1: ident, $n: ident, $ninv: ident) => { ($x0, $x1) = ( f64x4_reduce_to_pm1n!($x0 + $x1, $n, $ninv), f64x4_reduce_to_pm1n!($x0 - $x1, $n, $ninv), ); }; } // This is LENGTH2INV_ANY_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64_length2inv_any_j_mut { ($x0: ident, $x1: ident, $n: ident, $ninv: ident, $w0: expr) => { (*$x0, *$x1) = ( f64_reduce_to_pm1n!(*$x0 + *$x1, $n, $ninv), f64_mulmod!(*$x1 - *$x0, $w0, $n, $ninv), ); }; } // This is LENGTH2INV_ANY_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length2inv_any_j { ($x0: ident, $x1: ident, $n: ident, $ninv: ident, $w0: ident) => { ($x0, $x1) = ( f64x4_reduce_to_pm1n!($x0 + $x1, $n, $ninv), f64x4_mulmod!($x1 - $x0, $w0, $n, $ninv), ); }; } // This is LENGTH4INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64_length4inv_zero_j_mut { ($x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: expr, $ninv: expr, $ww1: expr) => { let n = $n; let ninv = $ninv; let y0 = f64_reduce_to_pm1n!(*$x0 + *$x1, n, ninv); let y1 = f64_reduce_to_pm1n!(*$x2 + *$x3, n, ninv); let y2 = f64_reduce_to_pm1n!(*$x0 - *$x1, n, ninv); let y3 = f64_mulmod!(*$x2 - *$x3, $ww1, n, ninv); *$x0 = y0 + y1; *$x2 = y0 - y1; *$x1 = y2 - y3; *$x3 = y2 + y3; }; } // This is LENGTH4INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length4inv_zero_j { ($x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: ident, $ninv: ident, $ww1: ident) => { let y0 = f64x4_reduce_to_pm1n!($x0 + $x1, $n, $ninv); let y1 = f64x4_reduce_to_pm1n!($x2 + $x3, $n, $ninv); let y2 = f64x4_reduce_to_pm1n!($x0 - $x1, $n, $ninv); let y3 = f64x4_mulmod!($x2 - $x3, $ww1, $n, $ninv); $x0 = y0 + y1; $x2 = y0 - y1; $x1 = y2 - y3; $x3 = y2 + y3; }; } // This is LENGTH4INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length4inv_any_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $n: expr, $ninv: ident, $w0: ident, $ww0: ident, $ww1: ident ) => { let y0 = $x0 + $x1; let y1 = $x2 + $x3; let y2 = f64x4_mulmod!($x0 - $x1, $ww0, $n, $ninv); let y3 = f64x4_mulmod!($x3 - $x2, $ww1, $n, $ninv); $x0 = f64x4_reduce_to_pm1n!(y0 + y1, $n, $ninv); $x1 = y3 - y2; $x2 = f64x4_mulmod!(y1 - y0, $w0, $n, $ninv); $x3 = f64x4_mulmod!(y3 + y2, $w0, $n, $ninv); }; } // This is LENGTH8INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64_length8inv_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: expr, $ninv: expr, $ww1: expr, $www2: expr, $www3: expr ) => { let n = $n; let ninv = $ninv; let ww1 = $ww1; f64_length2inv_zero_j_mut!($x0, $x1, n, ninv); f64_length2inv_any_j_mut!($x2, $x3, n, ninv, ww1); f64_length2inv_any_j_mut!($x4, $x5, n, ninv, $www2); f64_length2inv_any_j_mut!($x6, $x7, n, ninv, $www3); f64_length4inv_zero_j_mut!($x0, $x2, $x4, $x6, n, ninv, ww1); f64_length4inv_zero_j_mut!($x1, $x3, $x5, $x7, n, ninv, ww1); }; } // This is LENGTH8INV_ZERO_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length8inv_zero_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: ident, $ninv: ident, $ww1: ident, $www2: ident, $www3: ident ) => { f64x4_length2inv_zero_j!($x0, $x1, $n, $ninv); f64x4_length2inv_any_j!($x2, $x3, $n, $ninv, $ww1); f64x4_length2inv_any_j!($x4, $x5, $n, $ninv, $www2); f64x4_length2inv_any_j!($x6, $x7, $n, $ninv, $www3); f64x4_length4inv_zero_j!($x0, $x2, $x4, $x6, $n, $ninv, $ww1); f64x4_length4inv_zero_j!($x1, $x3, $x5, $x7, $n, $ninv, $ww1); }; } // This is LENGTH8INV_ANY_J from fft_small/sd_ifft.c, FLINT 3.3.0-dev. macro_rules! f64x4_length8inv_any_j { ( $x0: ident, $x1: ident, $x2: ident, $x3: ident, $x4: ident, $x5: ident, $x6: ident, $x7: ident, $n: ident, $ninv: ident, $w0: ident, $ww0: ident, $ww1: ident, $www0: ident, $www1: ident, $www2: ident, $www3: ident ) => { f64x4_length2inv_any_j!($x0, $x1, $n, $ninv, $www0); f64x4_length2inv_any_j!($x2, $x3, $n, $ninv, $www1); f64x4_length2inv_any_j!($x4, $x5, $n, $ninv, $www2); f64x4_length2inv_any_j!($x6, $x7, $n, $ninv, $www3); f64x4_length4inv_any_j!($x0, $x2, $x4, $x6, $n, $ninv, $w0, $ww0, $ww1); f64x4_length4inv_any_j!($x1, $x3, $x5, $x7, $n, $ninv, $w0, $ww0, $ww1); }; } // This is sd_ifft_basecase_0_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. const fn sd_ifft_basecase_0_1(_q: &FFTContext, _xs: &mut [f64]) {} // This is sd_ifft_basecase_1_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_1_1(q: &FFTContext, xs: &mut [f64]) { if let &mut [ref mut x0, ref mut x1, ..] = xs { f64_length2inv_zero_j_mut!(x0, x1, q.p, q.pinv); } } // This is sd_ifft_basecase_2_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_2_1(q: &FFTContext, xs: &mut [f64]) { if let &mut [ref mut x0, ref mut x1, ref mut x2, ref mut x3, ..] = xs { f64_length4inv_zero_j_mut!(x0, x1, x2, x3, q.p, q.pinv, w2tab!(q, 1, 0)); } } // This is sd_ifft_basecase_3_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_3_1(q: &FFTContext, xs: &mut [f64]) { if let &mut [ ref mut x0, ref mut x1, ref mut x2, ref mut x3, ref mut x4, ref mut x5, ref mut x6, ref mut x7, .., ] = xs { f64_length8inv_zero_j!( x0, x1, x2, x3, x4, x5, x6, x7, q.p, q.pinv, w2tab!(q, 1, 0), w2tab!(q, 2, 1), w2tab!(q, 2, 0) ); } } // This is sd_ifft_basecase_4_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_4_1(q: &FFTContext, xs: &mut [f64]) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let q00 = w2tab!(q, 0, 0); let q01 = w2tab!(q, 0, 1); let q02 = w2tab!(q, 0, 2); let q03 = w2tab!(q, 0, 3); let w = f64x4::from([-q00, q03, w2tab!(q, 0, 7), w2tab!(q, 0, 5)]); let iw = f64x4::from([q01, q02, w2tab!(q, 0, 6), w2tab!(q, 0, 4)]); let w2 = f64x4::from([-q00, q01, q03, q02]); f64x4_length4inv_any_j!(x0, x1, x2, x3, n, ninv, w2, w, iw); f64x4_transpose!(x0, x1, x2, x3); let iw = f64x4::splat(q01); f64x4_length4inv_zero_j!(x0, x1, x2, x3, n, ninv, iw); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); } // This is sd_ifft_basecase_4_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_4_0(q: &FFTContext, xs: &mut [f64], j_mr: usize, j_bits: u64) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let j_bits = usize::exact_from(j_bits); let w2 = read_f64x4_w2tab!(q, j_bits + 2, j_mr << 2); let [w20, w21, w22, w23] = w2.to_array(); let w2 = f64x4::from([w23, w22, w21, w20]); let jp3 = j_bits + 3; let j_8 = j_mr << 3; let [u0, u1, u2, u3] = read_f64x4_w2tab!(q, jp3, j_8).to_array(); let [v0, v1, v2, v3] = read_f64x4_w2tab!(q, jp3, j_8 + 4).to_array(); let mut w = f64x4::from([v3, v1, u3, u1]); let mut iw = f64x4::from([v2, v0, u2, u0]); f64x4_length4inv_any_j!(x0, x1, x2, x3, n, ninv, w2, w, iw); f64x4_transpose!(x0, x1, x2, x3); let jp1 = j_bits + 1; let j_2 = j_mr << 1; w = f64x4::splat(w2tab!(q, jp1, j_2 + 1)); iw = f64x4::splat(w2tab!(q, jp1, j_2)); let w2 = f64x4::splat(w2tab!(q, j_bits, j_mr)); f64x4_length4inv_any_j!(x0, x1, x2, x3, n, ninv, w2, w, iw); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); } // This is sd_ifft_basecase_5_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_5_1(q: &FFTContext, xs: &mut [f64]) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let mut x4 = read_f64x4!(xs, 16); let mut x5 = read_f64x4!(xs, 20); let mut x6 = read_f64x4!(xs, 24); let mut x7 = read_f64x4!(xs, 28); let q00 = w2tab!(q, 0, 0); let q10 = w2tab!(q, 1, 0); let q20 = w2tab!(q, 2, 0); let q21 = w2tab!(q, 2, 1); let q30 = w2tab!(q, 3, 0); let q31 = w2tab!(q, 3, 1); let q32 = w2tab!(q, 3, 2); let q33 = w2tab!(q, 3, 3); // j = 0, 1, 2, 3 then {j,2j+0,2j+1}^-1 in each column let mut w0 = f64x4::from([-q00, q10, q21, q20]); let mut ww0 = f64x4::from([-q00, q21, q33, q31]); let mut ww1 = f64x4::from([q10, q20, q32, q30]); f64x4_length4inv_any_j!(x0, x1, x2, x3, n, ninv, w0, ww0, ww1); // j = 4, 5, 6, 7 then {j,2j+0,2j+1}^-1 in each column w0 = f64x4::from([q33, q32, q31, q30]); ww0 = f64x4::from([w2tab!(q, 4, 7), w2tab!(q, 4, 5), w2tab!(q, 4, 3), w2tab!(q, 4, 1)]); ww1 = f64x4::from([w2tab!(q, 4, 6), w2tab!(q, 4, 4), w2tab!(q, 4, 2), w2tab!(q, 4, 0)]); f64x4_length4inv_any_j!(x4, x5, x6, x7, n, ninv, w0, ww0, ww1); f64x4_transpose!(x0, x1, x2, x3); f64x4_transpose!(x4, x5, x6, x7); ww1 = f64x4::splat(q10); let www2 = f64x4::splat(q21); let www3 = f64x4::splat(q20); f64x4_length8inv_zero_j!(x0, x1, x2, x3, x4, x5, x6, x7, n, ninv, ww1, www2, www3); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); write_f64x4!(xs, 16, x4); write_f64x4!(xs, 20, x5); write_f64x4!(xs, 24, x6); write_f64x4!(xs, 28, x7); } // This is sd_ifft_basecase_5_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_basecase_5_0(q: &FFTContext, xs: &mut [f64], j_mr: usize, j_bits: u64) { let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let mut x0 = read_f64x4!(xs, 0); let mut x1 = read_f64x4!(xs, 4); let mut x2 = read_f64x4!(xs, 8); let mut x3 = read_f64x4!(xs, 12); let mut x4 = read_f64x4!(xs, 16); let mut x5 = read_f64x4!(xs, 20); let mut x6 = read_f64x4!(xs, 24); let mut x7 = read_f64x4!(xs, 28); let j_bits = usize::exact_from(j_bits); let j_8 = j_mr << 3; let jp3 = j_bits + 3; let [w00, w01, w02, w03] = read_f64x4_w2tab!(q, jp3, j_8 + 4).to_array(); let w0 = f64x4::from([w03, w02, w01, w00]); let jp4 = j_bits + 4; let j_16 = j_mr << 4; let [u0, u1, u2, u3] = read_f64x4_w2tab!(q, jp4, j_16 + 8).to_array(); let [v0, v1, v2, v3] = read_f64x4_w2tab!(q, jp4, j_16 + 12).to_array(); let mut ww0 = f64x4::from([v3, v1, u3, u1]); let mut ww1 = f64x4::from([v2, v0, u2, u0]); f64x4_length4inv_any_j!(x0, x1, x2, x3, n, ninv, w0, ww0, ww1); let [w00, w01, w02, w03] = read_f64x4_w2tab!(q, jp3, j_8).to_array(); let w0 = f64x4::from([w03, w02, w01, w00]); let [u0, u1, u2, u3] = read_f64x4_w2tab!(q, jp4, j_16).to_array(); let [v0, v1, v2, v3] = read_f64x4_w2tab!(q, jp4, j_16 + 4).to_array(); ww0 = f64x4::from([v3, v1, u3, u1]); ww1 = f64x4::from([v2, v0, u2, u0]); f64x4_length4inv_any_j!(x4, x5, x6, x7, n, ninv, w0, ww0, ww1); f64x4_transpose!(x0, x1, x2, x3); f64x4_transpose!(x4, x5, x6, x7); let w0 = f64x4::splat(w2tab!(q, j_bits, j_mr)); let jp1 = j_bits + 1; let j_2 = j_mr << 1; ww0 = f64x4::splat(w2tab!(q, jp1, j_2 + 1)); ww1 = f64x4::splat(w2tab!(q, jp1, j_2)); let jp2 = j_bits + 2; let j_4 = j_mr << 2; let www0 = f64x4::splat(w2tab!(q, jp2, j_4 + 3)); let www1 = f64x4::splat(w2tab!(q, jp2, j_4 + 2)); let www2 = f64x4::splat(w2tab!(q, jp2, j_4 + 1)); let www3 = f64x4::splat(w2tab!(q, jp2, j_4)); f64x4_length8inv_any_j!( x0, x1, x2, x3, x4, x5, x6, x7, n, ninv, w0, ww0, ww1, www0, www1, www2, www3 ); write_f64x4!(xs, 0, x0); write_f64x4!(xs, 4, x1); write_f64x4!(xs, 8, x2); write_f64x4!(xs, 12, x3); write_f64x4!(xs, 16, x4); write_f64x4!(xs, 20, x5); write_f64x4!(xs, 24, x6); write_f64x4!(xs, 28, x7); } macro_rules! sd_ifft_basecase { ($n: expr, $f0: ident, $f1: ident, $fs0: ident, $fs1: ident) => { // This is sd_ifft_basecase_n_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn $f1(q: &FFTContext, xs: &mut [f64]) { const LIMIT: usize = 1 << ($n - 2); split_into_chunks_mut!(xs, LIMIT, [xs0, xs1, xs2], xs3); $fs1(q, xs0); $fs0(q, xs1, 0, 1); $fs0(q, xs2, 1, 2); $fs0(q, xs3, 0, 2); radix_4_reverse_param_j_is_z!(q, iw, n, ninv); process_4_3!( radix_4_reverse_moth_j_is_z, LIMIT, xs0, xs1, xs2, xs3, iw, n, ninv ); } // This is sd_ifft_basecase_n_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn $f0(q: &FFTContext, xs: &mut [f64], j_mr: usize, j_bits: u64) { const LIMIT: usize = 1 << ($n - 2); assert_ne!(j_bits, 0); split_into_chunks_mut!(xs, LIMIT, [xs0, xs1, xs2], xs3); let j_mr_4 = j_mr << 2; let j_bits_p_2 = j_bits + 2; $fs0(q, xs0, j_mr_4 + 3, j_bits_p_2); $fs0(q, xs1, j_mr_4 + 2, j_bits_p_2); $fs0(q, xs2, j_mr_4 + 1, j_bits_p_2); $fs0(q, xs3, j_mr_4, j_bits_p_2); radix_4_reverse_param_j_is_nz!(q, j_mr, j_bits, w, w2, iw, n, ninv); process_4_5!( radix_4_reverse_moth_j_is_nz, LIMIT, xs0, xs1, xs2, xs3, w, w2, iw, n, ninv ); } }; } sd_ifft_basecase!( 6, sd_ifft_basecase_6_0, sd_ifft_basecase_6_1, sd_ifft_basecase_4_0, sd_ifft_basecase_4_1 ); sd_ifft_basecase!( 7, sd_ifft_basecase_7_0, sd_ifft_basecase_7_1, sd_ifft_basecase_5_0, sd_ifft_basecase_5_1 ); sd_ifft_basecase!( 8, sd_ifft_basecase_8_0, sd_ifft_basecase_8_1, sd_ifft_basecase_6_0, sd_ifft_basecase_6_1 ); sd_ifft_basecase!( 9, sd_ifft_basecase_9_0, sd_ifft_basecase_9_1, sd_ifft_basecase_7_0, sd_ifft_basecase_7_1 ); // parameter 1: j can be zero // // This is sd_ifft_base_8_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_base_8_1(q: &FFTContext, x: &mut [f64], j: usize) { set_j_bits_and_j_mr!(j, j_bits, j_mr); if j == 0 { sd_ifft_basecase_8_1(q, x); } else { sd_ifft_basecase_8_0(q, x, j_mr, j_bits); } } // parameter 1: j cannot be zero // // This is sd_ifft_base_8_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_base_8_0(q: &FFTContext, x: &mut [f64], j: usize) { set_j_bits_and_j_mr!(j, j_bits, j_mr); sd_ifft_basecase_8_0(q, x, j_mr, j_bits); } // parameter 1: j can be zero // // This is sd_ifft_base_9_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_base_9_1(q: &FFTContext, x: &mut [f64], j: usize) { set_j_bits_and_j_mr!(j, j_bits, j_mr); if j == 0 { sd_ifft_basecase_9_1(q, x); } else { sd_ifft_basecase_9_0(q, x, j_mr, j_bits); } } // This is sd_ifft_no_trunc_internal from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_no_trunc_internal( q: &FFTContext, xs: &mut [f64], // stride s: usize, // transform length BLK_SZ*2^k k: u64, j: usize, ) { if k > 2 { let k1 = k >> 1; let k2 = k - k1; let big_s_2 = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut m = 0; for b in 0..usize::power_of_2(k1) { sd_ifft_no_trunc_internal(q, &mut xs[m..], s, k2, shifted + b); m += big_s_2; } let big_s = s << LG_BLK_SZ; let shifted = s << k2; let mut m = 0; for _ in 0..usize::power_of_2(k2) { sd_ifft_no_trunc_block(q, &mut xs[m..], shifted, k1, j); m += big_s; } return; } if k == 2 { let big_s = s << LG_BLK_SZ; // k1 = 2; k2 = 0 split_into_chunks_mut!(xs, big_s, [xs0, xs1, xs2], xs3); let j_4 = j << 2; sd_ifft_base_8_1(q, xs0, j_4); sd_ifft_base_8_0(q, xs1, j_4 + 1); sd_ifft_base_8_0(q, xs2, j_4 + 2); sd_ifft_base_8_0(q, xs3, j_4 + 3); sd_ifft_no_trunc_block(q, xs, s, 2, j); } else if k == 1 { sd_ifft_base_9_1(q, xs, j); } else { sd_ifft_base_8_1(q, xs, j); } } const BIG_M: usize = 4; // ``` // k = 2, n = 3, z = 4, f = true // [ -r + 1 r + 1 2 r*w^3] // [ 2//w -2//w 0 -w^2] // [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2 -r*w] // [ -r r 1 r*w^3] // ``` // // This is radix_4_moth_inv_trunc_block_3_4_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_3_4_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let pow = usize::power_of_2(j_bits); let j_mr = pow - 1 - j; let j_r = j & ((pow >> 1) - 1); let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let w = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let w2 = if j == 0 { -1.0 } else { w2tab!(q, j_bits, j_mr) }; let two_w = f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p); let f0 = f64x4::splat(w2tab!(q, 0, 1)); // r let f1 = f64x4::splat(two_w); // 2*w^-1 let f2 = f64x4::splat(2.0); let f3 = f64x4::splat(w2); // -w^-2 let rw = if j == 0 { w2tab!(q, 0, 1) } else { w2tab!(q, 1 + j_bits, (j_r << 1) + 1) }; let fr = f64x4::splat(rw); // r*w let fq = f64x4::splat(w2tab!(q, j_bits, j_r)); // w^2 let fp_alt = f64x4_mulmod!(fr, fq, n, ninv); let fp = f64x4_reduce_pm1n_to_pmhn!(fp_alt, n); // r*w^3 for i in (0..BLK_SZ).step_by(BIG_M) { let a = read_f64x4!(xs0, i); let mut b = read_f64x4!(xs1, i); let mut c = read_f64x4!(xs2, i); let mut d = read_f64x4!(xs3, i); let mut v = a - b; let p = f64x4_mulmod!(d, fp, n, ninv); let q = f64x4_mulmod!(d, fq, n, ninv); let r = f64x4_mulmod!(d, fr, n, ninv); c = f64x4_reduce_to_pm1n!(c, n, ninv); let u = f64x4_reduce_to_pm1n!(a + b, n, ninv); b = f64x4_mulmod!(v, f1, n, ninv); v = f64x4_mulmod!(v, f0, n, ninv); d = c - v; c = f64x4_mul_add!(f2, c, -v); write_f64x4!(xs0, i, c + u + p); write_f64x4!(xs1, i, b - q); write_f64x4!(xs2, i, f64x4_mulmod!(c - u, f3, n, ninv) - r); write_f64x4!(xs3, i, d + p); } } // ``` // k = 2, n = 3, z = 4, f = false // [ -r + 1 r + 1 2 r*w^3] // [ 2//w -2//w 0 -w^2] // [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2 -r*w] // ``` // // This is radix_4_moth_inv_trunc_block_3_4_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_3_4_0( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let pow = usize::power_of_2(j_bits); let j_mr = pow - 1 - j; let j_r = j & ((pow >> 1) - 1); let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let jp1 = j_bits + 1; let w = if j == 0 { -1.0 } else { w2tab!(q, jp1, (j_mr << 1) + 1) }; let w2 = if j == 0 { -1.0 } else { w2tab!(q, j_bits, j_mr) }; let two_w = f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p); let f0 = f64x4::splat(w2tab!(q, 0, 1)); // r let f1 = f64x4::splat(two_w); // 2*w^-1 let f2 = f64x4::splat(2.0); let f3 = f64x4::splat(w2); // -w^-2 let rw = if j == 0 { w2tab!(q, 0, 1) } else { w2tab!(q, jp1, (j_r << 1) + 1) }; let fr = f64x4::splat(rw); // r*w let fq = f64x4::splat(w2tab!(q, j_bits, j_r)); // w^2 let fp_alt = f64x4_mulmod!(fr, fq, n, ninv); let fp = f64x4_reduce_pm1n_to_pmhn!(fp_alt, n); // r*w^3 for i in (0..BLK_SZ).step_by(BIG_M) { let a = read_f64x4!(xs0, i); let b = read_f64x4!(xs1, i); let mut c = read_f64x4!(xs2, i); let d = read_f64x4!(xs3, i); let u = f64x4_reduce_to_pm1n!(a + b, n, ninv); let v = a - b; c = f64x4_mul_add!( f2, f64x4_reduce_to_pm1n!(c, n, ninv), -f64x4_mulmod!(v, f0, n, ninv) ); write_f64x4!(xs0, i, c + u + f64x4_mulmod!(d, fp, n, ninv)); write_f64x4!( xs1, i, f64x4_mulmod!(v, f1, n, ninv) - f64x4_mulmod!(d, fq, n, ninv) ); write_f64x4!( xs2, i, f64x4_mulmod!(c - u, f3, n, ninv) - f64x4_mulmod!(d, fr, n, ninv) ); } } // ``` // k = 2, n = 3, z = 3, f = true // [ -r + 1 r + 1 2] // [ 2//w -2//w 0] // [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2] // [ -r r 1] // // {x0, x1, x3, x4} = { -r*(x0 - x1) + (x0 + x1) + 2*x2, // 2*w^-1* (x0 - x1), // -w^-2*(-r*(x0 - x1) - (x0 + x1) + 2*x2), // -r*(x0 - x1) + x2 } // ``` // // This is radix_4_moth_inv_trunc_block_3_3_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_3_3_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let j_mr = usize::power_of_2(j_bits) - 1 - j; let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let w = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let w2 = if j == 0 { -1.0 } else { w2tab!(q, j_bits, j_mr) }; let two_w = f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p); let f0 = f64x8::splat(w2tab!(q, 0, 1)); // r let f1 = f64x8::splat(two_w); // 2*w^-1 let f2 = f64x8::splat(2.0); let f3 = f64x8::splat(w2); // -w^-2 for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); let mut c = read_f64x8!(xs2, i); let mut v = a - b; write_f64x8!(xs1, i, f64x8_mulmod!(v, f1, n, ninv)); c = f64x8_reduce_to_pm1n!(c, n, ninv); v = f64x8_mulmod!(v, f0, n, ninv); write_f64x8!(xs3, i, c - v); let u = f64x8_reduce_to_pm1n!(a + b, n, ninv); c = f64x8_mul_add!(-f2, c, v); write_f64x8!(xs0, i, u - c); write_f64x8!(xs2, i, f64x8_nmulmod!(u + c, f3, n, ninv)); } } // ``` // k = 2, n = 3, z = 3, f = false // [ -r + 1 r + 1 2] // [ 2//w -2//w 0] // [(r + 1)//w^2 (-r + 1)//w^2 -2//w^2] // // {x0, x1, x3} = { -r*(x0 - x1) + (x0 + x1) + 2*x2, // 2*w^-1*(x0 - x1), // -w^-2*(-r*(x0 - x1) - (x0 + x1) + 2*x2)} // // = { 2*x2 - r*v + u, // 2*w^-1*v, // -w^-2*(2*x2 - r*v - u)} // ``` // // This is radix_4_moth_inv_trunc_block_3_3_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_3_3_0( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1], xs2); let j_mr = usize::power_of_2(j_bits) - 1 - j; let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let w = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let w2 = if j == 0 { -1.0 } else { w2tab!(q, j_bits, j_mr) }; let two_w = f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p); let f0 = f64x8::splat(w2tab!(q, 0, 1)); // r let f1 = f64x8::splat(two_w); // 2*w^-1 let f2 = f64x8::splat(2.0); let f3 = f64x8::splat(w2); // -w^-2 for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); let mut c = read_f64x8!(xs2, i); let v = a - b; write_f64x8!(xs1, i, f64x8_mulmod!(v, f1, n, ninv)); c = f64x8_reduce_to_pm1n!(c, n, ninv); let mut u = a + b; u = f64x8_reduce_to_pm1n!(u, n, ninv); c = f64x8_mul_add!(-f2, c, f64x8_mulmod!(v, f0, n, ninv)); write_f64x8!(xs0, i, u - c); write_f64x8!(xs2, i, f64x8_nmulmod!(u + c, f3, n, ninv)); } } // ``` // k = 2, n = 2, z = 4, f = true // [ 2 2 -w^2 0] // [ 2//w -2//w 0 -w^2] // [1//2*r + 1//2 -1//2*r + 1//2 -1//2*w^2 -1//2*r*w^3] // ``` // // This is radix_4_moth_inv_trunc_block_2_4_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_2_4_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let pow = usize::power_of_2(j_bits); let j_mr = pow - 1 - j; let j_r = j & ((pow >> 1) - 1); let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let jp1 = j_bits + 1; let big_w = if j == 0 { -1.0 } else { w2tab!(q, jp1, (j_mr << 1) + 1) }; let rw = if j == 0 { w2tab!(q, 0, 1) } else { w2tab!(q, jp1, (j_r << 1) + 1) }; let w = w2tab!(q, j_bits, j_r); let two_w = f64_reduce_pm1n_to_pmhn!(-2.0 * big_w, q.p); let rw3 = f64_mulmod!(w, rw, q.p, q.pinv); let f0 = f64x4::splat(2.0); let f1 = f64x4::splat(two_w); // 2*w^-1 let f2 = f64x4::splat(fma!(-0.5f64, q.p, 0.5)); // 1/2 let f3 = f64x4::splat(w2tab!(q, 0, 1)); // r let f4 = f64x4::splat(w); // w^2 let f5 = f64x4::splat(f64_reduce_pm1n_to_pmhn!(rw3, q.p)); // r*w^3 for i in (0..BLK_SZ).step_by(BIG_M) { let u = read_f64x4!(xs0, i); let v = read_f64x4!(xs1, i); let a = read_f64x4!(xs2, i); let b = read_f64x4!(xs3, i); let p = f64x4_mulmod!(a, f4, n, ninv); let q = f64x4_mulmod!(b, f4, n, ninv); let r = f64x4_mulmod!(b, f5, n, ninv); let s = f64x4_reduce_to_pm1n!(u + v, n, ninv); let t = u - v; write_f64x4!(xs0, i, f64x4_mulmod!(s, f0, n, ninv) - p); write_f64x4!(xs1, i, f64x4_mulmod!(t, f1, n, ninv) - q); write_f64x4!( xs2, i, f64x4_mulmod!((s + f64x4_mulmod!(t, f3, n, ninv)) - (p + r), f2, n, ninv) ); } } // ``` // k = 2, n = 2, z = 4, f = false // [ 2 2 -w^2 0] // [2//w -2//w 0 -w^2] // ``` // // This is radix_4_moth_inv_trunc_block_2_4_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_2_4_0( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let pow = usize::power_of_2(j_bits); let j_mr = pow - 1 - j; let j_r = j & ((pow >> 1) - 1); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let wi = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let w2 = f64x8::splat(w2tab!(q, j_bits, j_r)); let twowi = f64x8::splat(f64_reduce_pm1n_to_pmhn!(-2.0 * wi, q.p)); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); let c = read_f64x8!(xs2, i); let d = read_f64x8!(xs3, i); let mut u = a + b; u += u; write_f64x8!( xs0, i, f64x8_reduce_to_pm1n!(u, n, ninv) - f64x8_mulmod!(c, w2, n, ninv) ); write_f64x8!( xs1, i, f64x8_mulmod!(a - b, twowi, n, ninv) - f64x8_mulmod!(d, w2, n, ninv) ); } } // ``` // k = 2, n = 2, z = 2, f = true // [ 2 2] // [ 2//w -2//w] // [1//2*r + 1//2 -1//2*r + 1//2] // // {x0, x1, x2} = {2*(x0 + x1), 2*w^-1*(x0 - x1), (x0+x1)/2 + (x0-x1)*i/2} // ``` // // This is radix_4_moth_inv_trunc_block_2_2_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_2_2_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1], xs2); let j_mr = usize::power_of_2(j_bits) - 1 - j; let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let w = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let c1 = f64x8::splat(f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p)); // 2/w let c2 = f64x8::splat(fma!(-0.5f64, q.p, 0.5)); // 1/2 let c3 = f64x8::splat(w2tab!(q, 1, 0)); // r for i in (0..BLK_SZ).step_by(BIG_N) { let mut u = read_f64x8!(xs0, i); let v = read_f64x8!(xs1, i); let s = u + v; let t = u - v; u = s + s; write_f64x8!(xs0, i, f64x8_reduce_to_pm1n!(u, n, ninv)); write_f64x8!(xs1, i, f64x8_mulmod!(t, c1, n, ninv)); write_f64x8!( xs2, i, f64x8_mulmod!(s + f64x8_mulmod!(t, c3, n, ninv), c2, n, ninv) ); } } // ``` // k = 2, n = 2, z = 2, f = 0 // // {x0, x1} = {2*(x0 + x1), 2*w^-1*(x0 - x1)} // // ``` // // This is radix_4_moth_inv_trunc_block_2_2_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_2_2_0( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { fail_on_untested_path("radix_4_moth_inv_trunc_block_2_2_0"); let (xs0, xs1) = xs.split_at_mut(gap); let j_mr = usize::power_of_2(j_bits) - 1 - j; let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let j_bits = usize::exact_from(j_bits); let w = if j == 0 { -1.0 } else { w2tab!(q, 1 + j_bits, (j_mr << 1) + 1) }; let c0 = f64x8::splat(2.0); let c1 = f64x8::splat(f64_reduce_pm1n_to_pmhn!(-2.0 * w, q.p)); for i in (0..BLK_SZ).step_by(BIG_N) { let u = read_f64x8!(xs0, i); let v = read_f64x8!(xs1, i); write_f64x8!(xs0, i, f64x8_mulmod!(u + v, c0, n, ninv)); write_f64x8!(xs1, i, f64x8_mulmod!(u - v, c1, n, ninv)); } } // ``` // k = 2, n = 1, z = 4, f = true // [4 -w -w^2 -w^3] // [1 -1//2*w 0 -1//2*w^3] // ``` // // This is radix_4_moth_inv_trunc_block_1_4_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_1_4_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let j_r = j & ((usize::power_of_2(j_bits) >> 1) - 1); let j_bits = usize::exact_from(j_bits); let big_w2 = w2tab!(q, j_bits, j_r); let w = if j == 0 { 1.0 } else { w2tab!(q, 1 + j_bits, (j_r << 1)) }; let n = f64x4::splat(q.p); let ninv = f64x4::splat(q.pinv); let f2 = f64x4::splat(2.0); let w2 = f64x4::splat(big_w2); let ha = fma!(-0.5f64, q.p, 0.5); let ha_w = f64_mulmod!(w, ha, q.p, q.pinv); let wo2 = f64x4::splat(f64_reduce_pm1n_to_pmhn!(ha_w, q.p)); for i in (0..BLK_SZ).step_by(BIG_M) { let mut a = read_f64x4!(xs0, i); a = f64x4_reduce_to_pm1n!(a, n, ninv); let mut b = read_f64x4!(xs1, i); let mut c = read_f64x4!(xs2, i); let mut d = read_f64x4!(xs3, i); c = f64x4_nmulmod!(c, w2, n, ninv); d = f64x4_mulmod!(d, w2, n, ninv); b = f64x4_mulmod!(b + d, wo2, n, ninv); let u = f64x4_mul_add!(-f2, a, b); write_f64x4!(xs0, i, c - f64x4_reduce_to_pm1n!(u + u, n, ninv)); write_f64x4!(xs1, i, a - b); } } // ``` // k = 2, n = 1, z = 4, f = false // [4 -w -w^2 -w^3] // ``` // // This is radix_4_moth_inv_trunc_block_1_4_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_1_4_0( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let j_r = j & ((usize::power_of_2(j_bits) >> 1) - 1); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let f1 = f64x8::splat(4.0); let j_bits = usize::exact_from(j_bits); let w2 = f64x8::splat(w2tab!(q, j_bits, j_r)); let w = f64x8::splat(if j == 0 { 1.0 } else { w2tab!(q, 1 + j_bits, j_r << 1) }); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); let c = read_f64x8!(xs2, i); let d = read_f64x8!(xs3, i); write_f64x8!( xs0, i, f64x8_reduce_to_pm1n!(a * f1, n, ninv) - f64x8_mulmod!(b, w, n, ninv) - f64x8_mulmod!(c + f64x8_mulmod!(d, w, n, ninv), w2, n, ninv) ); } } // ``` // k = 2, n = 1, z = 1, f = true // [4] // [1] // ``` // // This is radix_4_moth_inv_trunc_block_1_1_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_1_1_1( q: &FFTContext, _j: usize, _j_bits: u64, xs: &mut [f64], gap: usize, ) { fail_on_untested_path("radix_4_moth_inv_trunc_block_1_1_1"); let (xs0, xs1) = xs.split_at_mut(gap); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let f = f64x8::splat(4.0); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); write_f64x8!(xs0, i, f64x8_reduce_to_pm1n!(f * a, n, ninv)); write_f64x8!(xs1, i, f64x8_reduce_to_pm1n!(a, n, ninv)); } } // ``` // k = 2, n = 1, z = 1, f = false // [4] // ``` // // This is radix_4_moth_inv_trunc_block_1_1_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_1_1_0( q: &FFTContext, _j: usize, _j_bits: u64, xs: &mut [f64], _gap: usize, ) { fail_on_untested_path("radix_4_moth_inv_trunc_block_1_1_0"); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let f = f64x8::splat(4.0); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs, i); write_f64x8!(xs, i, f64x8_reduce_to_pm1n!(f * a, n, ninv)); } } // ``` // k = 2, n = 0, z = 4, f = true // [1//4 1//4*w 1//4*w^2 1//4*w^3] // ``` // // This is radix_4_moth_inv_trunc_block_0_4_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_4_moth_inv_trunc_block_0_4_1( q: &FFTContext, j: usize, j_bits: u64, xs: &mut [f64], gap: usize, ) { split_into_chunks_mut!(xs, gap, [xs0, xs1, xs2], xs3); let j_r = j & ((usize::power_of_2(j_bits) >> 1) - 1); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let one4th = f64x8::splat(fma!(-0.25f64, q.p, 0.25)); let j_bits = usize::exact_from(j_bits); let w2 = f64x8::splat(w2tab!(q, j_bits, j_r)); let w = f64x8::splat(if j == 0 { 1.0 } else { w2tab!(q, 1 + j_bits, j_r << 1) }); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); let c = read_f64x8!(xs2, i); let d = read_f64x8!(xs3, i); write_f64x8!( xs0, i, f64x8_mulmod!( a + f64x8_mulmod!(b, w, n, ninv) + f64x8_mulmod!(c + f64x8_mulmod!(d, w, n, ninv), w2, n, ninv), one4th, n, ninv ) ); } } // This is sd_fft_ctx_w2 from fft_small.h, FLINT 3.3.0-dev. fn sd_fft_ctx_w2(q: &FFTContext, j: usize) -> f64 { set_j_bits_and_j_r!(j, j_bits, j_r); w2tab!(q, usize::exact_from(j_bits), j_r) } // {x0, x1} = {2*x0 - w*x1, x0 - w*x1} // // This is radix_2_moth_inv_trunc_block_1_2_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_1_2_1(q: &FFTContext, j: usize, xs0: &mut [f64], xs1: &mut [f64]) { let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let w = f64x8::splat(sd_fft_ctx_w2(q, j)); let c = f64x8::splat(2.0); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let mut b = read_f64x8!(xs1, i); b = f64x8_nmulmod!(b, w, n, ninv); write_f64x8!( xs0, i, f64x8_reduce_to_pm1n!(f64x8_mul_add!(c, a, b), n, ninv) ); write_f64x8!(xs1, i, f64x8_reduce_to_pm1n!(a + b, n, ninv)); } } // {x0} = {2*x0 - w*x1} // // This is radix_2_moth_inv_trunc_block_1_2_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_1_2_0(q: &FFTContext, j: usize, xs0: &mut [f64], xs1: &mut [f64]) { let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let w = f64x8::splat(sd_fft_ctx_w2(q, j)); let c = f64x8::splat(2.0); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); write_f64x8!( xs0, i, f64x8_reduce_to_pm1n!(f64x8_mul_add!(c, a, -f64x8_mulmod!(b, w, n, ninv)), n, ninv) ); } } // {x0, x1} = {2*x0, x0} // // This is radix_2_moth_inv_trunc_block_1_1_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_1_1_1(q: &FFTContext, _j: usize, xs0: &mut [f64], xs1: &mut [f64]) { let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let u = a + a; write_f64x8!(xs0, i, f64x8_reduce_to_pm1n!(u, n, ninv)); write_f64x8!(xs1, i, a); } } // {x0} = {2*x0} // // This is radix_2_moth_inv_trunc_block_1_1_0 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_1_1_0( q: &FFTContext, _j: usize, xs0: &mut [f64], _xs1: &mut [f64], ) { fail_on_untested_path("radix_2_moth_inv_trunc_block_1_1_0"); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); for i in (0..BLK_SZ).step_by(BIG_N) { let mut a = read_f64x8!(xs0, i); a = a + a; write_f64x8!(xs0, i, f64x8_reduce_to_pm1n!(a, n, ninv)); } } // {x0} = {(x0 + w*x1)/2} // // This is radix_2_moth_inv_trunc_block_0_2_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_0_2_1(q: &FFTContext, j: usize, xs0: &mut [f64], xs1: &mut [f64]) { let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let w = f64x8::splat(sd_fft_ctx_w2(q, j)); let c = f64x8::splat(fma!(-0.5f64, q.p, 0.5)); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); let b = read_f64x8!(xs1, i); write_f64x8!( xs0, i, f64x8_mulmod!(a + f64x8_mulmod!(b, w, n, ninv), c, n, ninv) ); } } // {x0} = {(x0)/2} // // This is radix_2_moth_inv_trunc_block_0_1_1 from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn radix_2_moth_inv_trunc_block_0_1_1( q: &FFTContext, _j: usize, xs0: &mut [f64], _xs1: &mut [f64], ) { fail_on_untested_path("radix_2_moth_inv_trunc_block_0_1_1"); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); let c = f64x8::splat(fma!(-0.5f64, q.p, 0.5)); for i in (0..BLK_SZ).step_by(BIG_N) { let a = read_f64x8!(xs0, i); write_f64x8!(xs0, i, f64x8_mulmod!(a, c, n, ninv)); } } const SD_IFFT_4_MOTH_TRUNC_BLOCK_TABLE: [Option; 40] = [ None, None, None, None, None, None, None, Some(radix_4_moth_inv_trunc_block_0_4_1), Some(radix_4_moth_inv_trunc_block_1_1_0), Some(radix_4_moth_inv_trunc_block_1_1_1), None, None, None, None, Some(radix_4_moth_inv_trunc_block_1_4_0), Some(radix_4_moth_inv_trunc_block_1_4_1), None, None, Some(radix_4_moth_inv_trunc_block_2_2_0), Some(radix_4_moth_inv_trunc_block_2_2_1), None, None, Some(radix_4_moth_inv_trunc_block_2_4_0), Some(radix_4_moth_inv_trunc_block_2_4_1), None, None, None, None, Some(radix_4_moth_inv_trunc_block_3_3_0), Some(radix_4_moth_inv_trunc_block_3_3_1), Some(radix_4_moth_inv_trunc_block_3_4_0), Some(radix_4_moth_inv_trunc_block_3_4_1), None, None, None, None, None, None, None, None, ]; const SD_IFFT_2_MOTH_TRUNC_BLOCK_TABLE: [Option; 12] = [ None, Some(radix_2_moth_inv_trunc_block_0_1_1), None, Some(radix_2_moth_inv_trunc_block_0_2_1), Some(radix_2_moth_inv_trunc_block_1_1_0), Some(radix_2_moth_inv_trunc_block_1_1_1), Some(radix_2_moth_inv_trunc_block_1_2_0), Some(radix_2_moth_inv_trunc_block_1_2_1), None, None, None, None, ]; // This is sd_ifft_trunc_block from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_trunc_block( q: &FFTContext, // data + BLK_SZ*I xs: &mut [f64], // stride s: usize, // BLK_SZ transforms each of length 2^k k: u64, j: usize, // actual trunc is z z: usize, // actual trunc is n n: usize, f: bool, ) { assert!(n <= z); let pow = usize::power_of_2(k); assert!(1 <= z && z <= pow); let sum = n + usize::from(f); assert!(1 <= sum && sum <= pow); if !f && z == n && n == pow { sd_ifft_no_trunc_block(q, xs, s, k, j); return; } let big_s = s << LG_BLK_SZ; if k == 2 && let Some(fxn) = SD_IFFT_4_MOTH_TRUNC_BLOCK_TABLE[usize::from(f) + ((z - 1 + (n << 2)) << 1)] { fxn(q, j, j.significant_bits(), xs, big_s); return; } if k > 1 { let k1 = k >> 1; let k2 = k - k1; let l2 = usize::power_of_2(k2); let n1 = n >> k2; let mask = l2 - 1; let n2 = n & mask; let z1 = z >> k2; let z2 = z & mask; let fp = f || n2 != 0; let z2p = min(l2, z); let m = min(n2, z2); let mp = max(n2, z2); // complete rows let big_s_2 = s << (k2 + LG_BLK_SZ); let shifted = j << k1; let mut p = 0; for b in 0..n1 { sd_ifft_no_trunc_block(q, &mut xs[p..], s, k2, shifted + b); p += big_s_2; } // rightmost columns let shifted2 = s << k2; let mut p = n2 * big_s; for a in n2..z2p { sd_ifft_trunc_block( q, &mut xs[p..], shifted2, k1, j, z1 + usize::from(a < mp), n1, fp, ); p += big_s; } // last partial row if fp { sd_ifft_trunc_block(q, &mut xs[n1 * big_s_2..], s, k2, shifted + n1, z2p, n2, f); } let sum = n1 + 1; let mut p = 0; // leftmost columns for a in 0..n2 { sd_ifft_trunc_block( q, &mut xs[p..], shifted2, k1, j, z1 + usize::from(a < m), sum, false, ); p += big_s; } return; } if k == 1 && let Some(fxn) = SD_IFFT_2_MOTH_TRUNC_BLOCK_TABLE[usize::from(f) + ((z - 1 + (n << 1)) << 1)] { let (xs0, xs1) = xs.split_at_mut(big_s); fxn(q, j, xs0, xs1); } } // This is sd_ifft_trunc_internal from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_trunc_internal( q: &FFTContext, // x = data + BLK_SZ*I where I = starting index xs: &mut [f64], // stride s: usize, // transform length 2^(k + LG_BLK_SZ) k: u64, j: usize, // actual trunc is z*BLK_SZ z: usize, // actual trunc is n*BLK_SZ n: usize, f: bool, ) { assert!(n <= z); let big_z = z << LG_BLK_SZ; let pow = usize::power_of_2(k + LG_BLK_SZ); assert!(1 <= big_z && big_z <= pow); let uf = usize::from(f); let big_n = n << LG_BLK_SZ; assert!(1 <= big_n + uf && big_n + uf <= pow); if !f && z == n && n == usize::power_of_2(k) { sd_ifft_no_trunc_internal(q, xs, s, k, j); return; } let big_s = s << LG_BLK_SZ; if k > 2 { let k1 = k >> 1; let k2 = k - k1; let l2 = usize::power_of_2(k2); let n1 = n >> k2; let mask = l2 - 1; let n2 = n & mask; let z1 = z >> k2; let z2 = z & mask; let fp = f || n2 != 0; let z2p = min(l2, z); let m = min(n2, z2); let mp = max(n2, z2); // complete rows let shifted = j << k1; let big_s_2 = s << (k2 + LG_BLK_SZ); let mut p = 0; for b in 0..n1 { sd_ifft_no_trunc_internal(q, &mut xs[p..], s, k2, shifted + b); p += big_s_2; } // rightmost columns let shifted_2 = s << k2; let mut p = n2 * big_s; for a in n2..z2p { sd_ifft_trunc_block( q, &mut xs[p..], shifted_2, k1, j, z1 + usize::from(a < mp), n1, fp, ); p += big_s; } // last partial row if fp { sd_ifft_trunc_internal(q, &mut xs[n1 * big_s_2..], s, k2, shifted + n1, z2p, n2, f); } // leftmost columns let sum = n1 + 1; let mut p = 0; for a in 0..n2 { sd_ifft_trunc_block( q, &mut xs[p..], shifted_2, k1, j, z1 + usize::from(a < m), sum, false, ); p += big_s; } return; } if k == 2 { let four_j = j << 2; sd_ifft_base_8_1(q, xs, four_j); if n > 1 { sd_ifft_base_8_0(q, &mut xs[big_s..], four_j + 1); } if n > 2 { sd_ifft_base_8_0(q, &mut xs[big_s << 1..], four_j + 2); } if n > 3 { sd_ifft_base_8_0(q, &mut xs[big_s * 3..], four_j + 3); } sd_ifft_trunc_block(q, xs, s, 2, j, z, n, f); if f { sd_ifft_trunc_internal(q, &mut xs[big_s * n..], s, 0, four_j + n, 1, 0, f); } } else if k == 1 { fail_on_untested_path("sd_ifft_trunc_internal, k == 1"); let two_j = j << 1; sd_ifft_base_8_1(q, xs, two_j); if n > 1 { sd_ifft_base_8_0(q, &mut xs[big_s..], two_j + 1); } sd_ifft_trunc_block(q, xs, s, 1, j, z, n, f); if f { sd_ifft_trunc_internal(q, &mut xs[big_s * n..], s, 0, two_j + n, 1, 0, f); } } else { assert!(!f); sd_ifft_base_8_1(q, xs, j); } } // This is sd_ifft_trunc from fft_small/sd_ifft.c, FLINT 3.3.0-dev. fn sd_ifft_trunc( q: &mut FFTContext, d: &mut [f64], // convolution length 2^L l: u64, trunc: usize, ) { assert!(trunc <= usize::power_of_2(l)); if l > LG_BLK_SZ { let new_trunc = trunc.div_round(BLK_SZ, Ceiling).0; sd_fft_ctx_fit_depth(q, l); sd_ifft_trunc_internal(q, d, 1, l - LG_BLK_SZ, 0, new_trunc, new_trunc, false); return; } fail_on_untested_path("sd_ifft_trunc, l <= LG_BLK_SZ"); match l { 0 => sd_ifft_basecase_0_1(q, d), 1 => sd_ifft_basecase_1_1(q, d), 2 => sd_ifft_basecase_2_1(q, d), 3 => sd_ifft_basecase_3_1(q, d), 4 => sd_ifft_basecase_4_1(q, d), 5 => sd_ifft_basecase_5_1(q, d), 6 => sd_ifft_basecase_6_1(q, d), 7 => sd_ifft_basecase_7_1(q, d), 8 => sd_ifft_basecase_8_1(q, d), _ => unreachable!(), } } // pointwise mul of a with b and m // // This is sd_fft_ctx_point_mul from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn sd_fft_ctx_point_mul(q: &FFTContext, a: &mut [f64], b: &[f64], m_orig: u64, depth: u64) { let m = f64x8::splat(f64_reduce_0n_to_pmhn!(m_orig as f64, q.p)); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); assert!(depth >= LG_BLK_SZ); let mut k = 0; for _ in 0..usize::power_of_2(depth - LG_BLK_SZ) { let ax = &mut a[k..]; let bx = &b[k..]; for j in (0..BLK_SZ).step_by(16) { let mut x0 = read_f64x8!(ax, j); let mut x1 = read_f64x8!(ax, j + 8); let b0 = read_f64x8!(bx, j); let b1 = read_f64x8!(bx, j + 8); x0 = f64x8_mulmod!(x0, m, n, ninv); x1 = f64x8_mulmod!(x1, m, n, ninv); x0 = f64x8_mulmod!(x0, b0, n, ninv); x1 = f64x8_mulmod!(x1, b1, n, ninv); write_f64x8!(ax, j, x0); write_f64x8!(ax, j + 8, x1); } k += BLK_SZ; } } // This is sd_fft_ctx_point_sqr from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn sd_fft_ctx_point_sqr(q: &FFTContext, a: &mut [f64], m_orig: u64, depth: u64) { let m = f64x8::splat(f64_reduce_0n_to_pmhn!(m_orig as f64, q.p)); let n = f64x8::splat(q.p); let ninv = f64x8::splat(q.pinv); assert!(depth >= LG_BLK_SZ); let mut k = 0; for _ in 0..usize::power_of_2(depth - LG_BLK_SZ) { let ax = &mut a[k..]; for j in (0..BLK_SZ).step_by(16) { let mut x0 = read_f64x8!(ax, j); let mut x1 = read_f64x8!(ax, j + 8); x0 = f64x8_mulmod!(x0, x0, n, ninv); x1 = f64x8_mulmod!(x1, x1, n, ninv); x0 = f64x8_mulmod!(x0, m, n, ninv); x1 = f64x8_mulmod!(x1, m, n, ninv); write_f64x8!(ax, j, x0); write_f64x8!(ax, j + 8, x1); } k += BLK_SZ; } } // cmp(a, b*2^e), a does not have to be normalized // // This is flint_mpn_cmp_ui_2exp from fft_small/mul_helpers.c, FLINT 3.3.0-dev. fn flint_mpn_cmp_ui_2exp(a: &[u64], b: u64, e: u64) -> Ordering { let mut an = a.len(); let mut q = usize::exact_from(e >> u64::LOG_WIDTH); let r = e & u64::WIDTH_MASK; while an != 0 && a[an - 1] == 0 { an -= 1; } if an == 0 { return if b == 0 { Equal } else { Greater }; } // ``` // b*2^e = (b*2^r )*2^(64*q) // = (b0 + b1*2^64)*2^(64*q) // ``` let (b0, b1) = if r == 0 { (b, 0) } else { (b << r, b >> (u64::WIDTH - r)) }; // ``` // check words [q+2,infty) // then check words [q+1, 64*q+128) against b1 // then check words [q, q+1) against b0 // then check words [0, q) // ``` if an > q + 2 { return Greater; } let mut x = if q + 1 < an { a[q + 1] } else { 0 }; if x != b1 { return x.cmp(&b1); } x = if q < an { a[q] } else { 0 }; if x != b0 { return x.cmp(&b0); } q = min(q, an); if a[..q].iter().any(|&x| x != 0) { return Greater; } Less } // This is mod_worker_func from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn process_mod( to_ffts: MPNToFFTFunc, ffts: &[FFTContext], stride: usize, two_pow_tab: &[f64x4], abuf: &mut [f64], a: &[Limb], atrunc: usize, a_stop_easy: usize, a_start_hard: usize, a_stop_hard: usize, bbuf: &mut [f64], b: &[Limb], btrunc: usize, b_stop_easy: usize, b_start_hard: usize, b_stop_hard: usize, squaring: bool, ) { let f = match to_ffts { MPNToFFTFunc { np: 4, bits: 84 } => apply_mpn_to_fft_func_4_84, MPNToFFTFunc { np: 4, bits: 88 } => apply_mpn_to_fft_func_4_88, MPNToFFTFunc { np: 4, bits: 92 } => apply_mpn_to_fft_func_4_92, MPNToFFTFunc { np: 5, bits: 112 } => apply_mpn_to_fft_func_5_112, MPNToFFTFunc { np: 5, bits: 116 } => apply_mpn_to_fft_func_5_116, MPNToFFTFunc { np: 5, bits: 120 } => apply_mpn_to_fft_func_5_120, MPNToFFTFunc { np: 6, bits: 136 } => apply_mpn_to_fft_func_6_136, MPNToFFTFunc { np: 6, bits: 140 } => apply_mpn_to_fft_func_6_140, MPNToFFTFunc { np: 6, bits: 144 } => apply_mpn_to_fft_func_6_144, MPNToFFTFunc { np: 7, bits: 160 } => apply_mpn_to_fft_func_7_160, MPNToFFTFunc { np: 7, bits: 164 } => apply_mpn_to_fft_func_7_164, MPNToFFTFunc { np: 7, bits: 168 } => apply_mpn_to_fft_func_7_168, MPNToFFTFunc { np: 8, bits: 184 } => apply_mpn_to_fft_func_8_184, MPNToFFTFunc { np: 8, bits: 188 } => apply_mpn_to_fft_func_8_188, MPNToFFTFunc { np: 8, bits: 192 } => apply_mpn_to_fft_func_8_192, _ => unreachable!(), }; f( ffts, abuf, stride, a, atrunc, two_pow_tab, a_stop_easy, a_start_hard, a_stop_hard, ); if !squaring { f( ffts, bbuf, stride, b, btrunc, two_pow_tab, b_stop_easy, b_start_hard, b_stop_hard, ); } } // This is NMOD_RED2 from nmod.h, FLINT 3.3.0-dev. macro_rules! nmod_red2 { ($a_hi: expr, $a_lo: expr, $mod_data: expr) => {{ let a_lo = $a_lo; let mod_data = $mod_data; let u1xx = ($a_hi << mod_data.norm) + (if mod_data.norm == 0 { 0 } else { a_lo >> (u64::WIDTH - mod_data.norm) }); let u0xx = a_lo << mod_data.norm; let nxx = mod_data.n << mod_data.norm; let (mut q1xx, mut q0xx) = u64::x_mul_y_to_zz(mod_data.ninv, u1xx); (q1xx, q0xx) = u64::xx_add_yy_to_zz(q1xx, q0xx, u1xx, u0xx); let mut r1xx = u0xx.wrapping_sub((q1xx + 1).wrapping_mul(nxx)); if r1xx > q0xx { r1xx.wrapping_add_assign(nxx); } if r1xx < nxx { r1xx >> mod_data.norm } else { (r1xx - nxx) >> mod_data.norm } }}; } // This is fft_worker_func from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn process_fft( fctx: &mut FFTContext, cop: u64, depth: u64, ztrunc: usize, abuf: &mut [f64], atrunc: usize, bbuf: &mut [f64], btrunc: usize, squaring: bool, ) { let q = &mut *fctx; if !squaring { sd_fft_trunc(q, bbuf, depth, btrunc, ztrunc); } sd_fft_trunc(q, abuf, depth, atrunc, ztrunc); let m = nmod_red2!(cop >> (u64::WIDTH - depth), cop << depth, &q.mod_data) .mod_inverse(q.mod_data.n) .unwrap(); if squaring { sd_fft_ctx_point_sqr(q, abuf, m, depth); } else { sd_fft_ctx_point_mul(q, abuf, bbuf, m, depth); } sd_ifft_trunc(q, abuf, depth, ztrunc); } // This is mod_fft_worker_func from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn process_mod_fft( bits: usize, fctx: &mut FFTContext, two_pow_tab: &[f64], cop: u64, depth: u64, ztrunc: usize, a: &[Limb], abuf: &mut [f64], atrunc: usize, b: &[Limb], bbuf: &mut [f64], btrunc: usize, squaring: bool, ) { let q = fctx; if !squaring { slow_mpn_to_fft(q, bbuf, btrunc, b, bits, two_pow_tab); sd_fft_trunc(q, bbuf, depth, btrunc, ztrunc); } slow_mpn_to_fft(q, abuf, atrunc, a, bits, two_pow_tab); sd_fft_trunc(q, abuf, depth, atrunc, ztrunc); let m = nmod_red2!(cop >> (u64::WIDTH - depth), cop << depth, &q.mod_data) .mod_inverse(q.mod_data.n) .unwrap(); if squaring { sd_fft_ctx_point_sqr(q, abuf, m, depth); } else { sd_fft_ctx_point_mul(q, abuf, bbuf, m, depth); } sd_ifft_trunc(q, abuf, depth, ztrunc); } // This is _madd from crt_helpers.h, FLINT 3.3.0-dev, modifying hi and lo. macro_rules! madd { ($hi: expr, $lo: expr, $y: expr, $x: expr) => { let (r1, r0) = u64::x_mul_y_to_zz($x, $y); ($hi, $lo) = u64::xx_add_yy_to_zz(r1, r0, $hi, $lo); }; } // This is big_mul from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! big_mul { ($n: expr, $m: expr, $r: ident, $t: ident, $c: expr, $y: expr) => { let y = $y; let c = $c; for k in (0..$n).step_by(2) { if k < const { $n - 1 } { assert!(k < $m); ($r[k + 1], $r[k]) = u64::x_mul_y_to_zz(c[k], y); } else { assert_eq!(k, const { $n - 1 }); $r[k] = if k < $m { c[k] * y } else { 0 }; } if k < const { $n - 2 } { assert!(k < const { $m - 1 }); let kp1 = k + 1; ($t[k + 2], $t[kp1]) = u64::x_mul_y_to_zz(c[kp1], y); } else if k < const { $n - 1 } { let kp1 = k + 1; $t[kp1] = if k < const { $m - 1 } { c[kp1] * y } else { 0 } } } }; } // This is big_addmul from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! big_add_mul { ($n: expr, $m: expr, $r: ident, $t: ident, $c: expr, $y: expr) => { let y = $y; let c = $c; for k in (0..$n).step_by(2) { if k < const { $n - 1 } { assert!(k < $m); madd!($r[k + 1], $r[k], c[k], y); } else { assert_eq!(k, const { $n - 1 }); if k < $m { $r[k] += c[k] * y; } } #[allow(clippy::redundant_comparisons)] if k < const { $n - 2 } { assert!(k < const { $m - 1 }); let kp1 = k + 1; madd!($t[k + 2], $t[kp1], c[kp1], y); } else if k < const { $n - 1 } && k < const { $m - 1 } { let kp1 = k + 1; $t[kp1] += c[kp1] * y; } } }; } // This is multi_add_3 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_add_3{($z: expr, $a: expr) => {{ let z = $z; let a = $a; (z[2], z[1], z[0]) = u64::xxx_add_yyy_to_zzz(z[2], z[1], z[0], a[2], a[1], a[0]); }}} // This is multi_add_4 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_add_4{($z: expr, $a: expr) => {{ let z = $z; let a = $a; (z[3], z[2], z[1], z[0]) = u64::xxxx_add_yyyy_to_zzzz(z[3], z[2], z[1], z[0], a[3], a[2], a[1], a[0]); }}} // This is multi_add_5 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_add_5 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let carry_1 = z[0].overflowing_add_assign(a[0]); let mut carry_2 = z[1].overflowing_add_assign(a[1]); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a[2]); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a[3]); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } z[4].wrapping_add_assign(a[4]); if carry_4 { z[4].wrapping_add_assign(1); } }}; } // This is multi_add_6 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_add_6 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let carry_1 = z[0].overflowing_add_assign(a[0]); let mut carry_2 = z[1].overflowing_add_assign(a[1]); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a[2]); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a[3]); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a[4]); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } z[5].wrapping_add_assign(a[5]); if carry_5 { z[5].wrapping_add_assign(1); } }}; } // This is multi_add_7 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(not(feature = "32_bit_limbs"))] macro_rules! multi_add_7 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let carry_1 = z[0].overflowing_add_assign(a[0]); let mut carry_2 = z[1].overflowing_add_assign(a[1]); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a[2]); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a[3]); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a[4]); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a[5]); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } z[6].wrapping_add_assign(a[6]); if carry_6 { z[6].wrapping_add_assign(1); } }}; } // This is multi_add_8 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(not(feature = "32_bit_limbs"))] macro_rules! multi_add_8 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let carry_1 = z[0].overflowing_add_assign(a[0]); let mut carry_2 = z[1].overflowing_add_assign(a[1]); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a[2]); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a[3]); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a[4]); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a[5]); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a[6]); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } z[7].wrapping_add_assign(a[7]); if carry_7 { z[7].wrapping_add_assign(1); } }}; } // This is multi_add_4 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(feature = "32_bit_limbs")] macro_rules! multi_add_4_alt { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let (a_1, a_0) = a[0].split_in_half(); let (a_3, a_2) = a[1].split_in_half(); let (a_5, a_4) = a[2].split_in_half(); let (a_7, a_6) = a[3].split_in_half(); let carry_1 = z[0].overflowing_add_assign(a_0); let mut carry_2 = z[1].overflowing_add_assign(a_1); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a_2); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a_3); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a_4); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a_5); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a_6); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } if 7 < z.len() { z[7].wrapping_add_assign(a_7); if carry_7 { z[7].wrapping_add_assign(1); } } }}; } // This is multi_add_5 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(feature = "32_bit_limbs")] macro_rules! multi_add_5_alt { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let (a_1, a_0) = a[0].split_in_half(); let (a_3, a_2) = a[1].split_in_half(); let (a_5, a_4) = a[2].split_in_half(); let (a_7, a_6) = a[3].split_in_half(); let (a_9, a_8) = a[4].split_in_half(); let carry_1 = z[0].overflowing_add_assign(a_0); let mut carry_2 = z[1].overflowing_add_assign(a_1); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a_2); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a_3); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a_4); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a_5); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a_6); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } let mut carry_8 = z[7].overflowing_add_assign(a_7); if carry_7 { carry_8 |= z[7].overflowing_add_assign(1); } let mut carry_9 = z[8].overflowing_add_assign(a_8); if carry_8 { carry_9 |= z[8].overflowing_add_assign(1); } if 9 < z.len() { z[9].wrapping_add_assign(a_9); if carry_9 { z[9].wrapping_add_assign(1); } } }}; } // This is multi_add_6 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(feature = "32_bit_limbs")] macro_rules! multi_add_6_alt { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let (a_1, a_0) = a[0].split_in_half(); let (a_3, a_2) = a[1].split_in_half(); let (a_5, a_4) = a[2].split_in_half(); let (a_7, a_6) = a[3].split_in_half(); let (a_9, a_8) = a[4].split_in_half(); let (a_11, a_10) = a[5].split_in_half(); let carry_1 = z[0].overflowing_add_assign(a_0); let mut carry_2 = z[1].overflowing_add_assign(a_1); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a_2); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a_3); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a_4); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a_5); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a_6); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } let mut carry_8 = z[7].overflowing_add_assign(a_7); if carry_7 { carry_8 |= z[7].overflowing_add_assign(1); } let mut carry_9 = z[8].overflowing_add_assign(a_8); if carry_8 { carry_9 |= z[8].overflowing_add_assign(1); } let mut carry_10 = z[9].overflowing_add_assign(a_9); if carry_9 { carry_10 |= z[9].overflowing_add_assign(1); } let mut carry_11 = z[10].overflowing_add_assign(a_10); if carry_10 { carry_11 |= z[10].overflowing_add_assign(1); } if 11 < z.len() { z[11].wrapping_add_assign(a_11); if carry_11 { z[11].wrapping_add_assign(1); } } }}; } // This is multi_add_7 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(feature = "32_bit_limbs")] macro_rules! multi_add_7_alt { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let (a_1, a_0) = a[0].split_in_half(); let (a_3, a_2) = a[1].split_in_half(); let (a_5, a_4) = a[2].split_in_half(); let (a_7, a_6) = a[3].split_in_half(); let (a_9, a_8) = a[4].split_in_half(); let (a_11, a_10) = a[5].split_in_half(); let (a_13, a_12) = a[6].split_in_half(); let carry_1 = z[0].overflowing_add_assign(a_0); let mut carry_2 = z[1].overflowing_add_assign(a_1); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a_2); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a_3); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a_4); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a_5); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a_6); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } let mut carry_8 = z[7].overflowing_add_assign(a_7); if carry_7 { carry_8 |= z[7].overflowing_add_assign(1); } let mut carry_9 = z[8].overflowing_add_assign(a_8); if carry_8 { carry_9 |= z[8].overflowing_add_assign(1); } let mut carry_10 = z[9].overflowing_add_assign(a_9); if carry_9 { carry_10 |= z[9].overflowing_add_assign(1); } let mut carry_11 = z[10].overflowing_add_assign(a_10); if carry_10 { carry_11 |= z[10].overflowing_add_assign(1); } let mut carry_12 = z[11].overflowing_add_assign(a_11); if carry_11 { carry_12 |= z[11].overflowing_add_assign(1); } let mut carry_13 = z[12].overflowing_add_assign(a_12); if carry_12 { carry_13 |= z[12].overflowing_add_assign(1); } if 13 < z.len() { z[13].wrapping_add_assign(a_13); if carry_13 { z[13].wrapping_add_assign(1); } } }}; } // This is multi_add_8 from crt_helpers.h, FLINT 3.3.0-dev. #[cfg(feature = "32_bit_limbs")] macro_rules! multi_add_8_alt { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let (a_1, a_0) = a[0].split_in_half(); let (a_3, a_2) = a[1].split_in_half(); let (a_5, a_4) = a[2].split_in_half(); let (a_7, a_6) = a[3].split_in_half(); let (a_9, a_8) = a[4].split_in_half(); let (a_11, a_10) = a[5].split_in_half(); let (a_13, a_12) = a[6].split_in_half(); let (a_15, a_14) = a[7].split_in_half(); let carry_1 = z[0].overflowing_add_assign(a_0); let mut carry_2 = z[1].overflowing_add_assign(a_1); if carry_1 { carry_2 |= z[1].overflowing_add_assign(1); } let mut carry_3 = z[2].overflowing_add_assign(a_2); if carry_2 { carry_3 |= z[2].overflowing_add_assign(1); } let mut carry_4 = z[3].overflowing_add_assign(a_3); if carry_3 { carry_4 |= z[3].overflowing_add_assign(1); } let mut carry_5 = z[4].overflowing_add_assign(a_4); if carry_4 { carry_5 |= z[4].overflowing_add_assign(1); } let mut carry_6 = z[5].overflowing_add_assign(a_5); if carry_5 { carry_6 |= z[5].overflowing_add_assign(1); } let mut carry_7 = z[6].overflowing_add_assign(a_6); if carry_6 { carry_7 |= z[6].overflowing_add_assign(1); } let mut carry_8 = z[7].overflowing_add_assign(a_7); if carry_7 { carry_8 |= z[7].overflowing_add_assign(1); } let mut carry_9 = z[8].overflowing_add_assign(a_8); if carry_8 { carry_9 |= z[8].overflowing_add_assign(1); } let mut carry_10 = z[9].overflowing_add_assign(a_9); if carry_9 { carry_10 |= z[9].overflowing_add_assign(1); } let mut carry_11 = z[10].overflowing_add_assign(a_10); if carry_10 { carry_11 |= z[10].overflowing_add_assign(1); } let mut carry_12 = z[11].overflowing_add_assign(a_11); if carry_11 { carry_12 |= z[11].overflowing_add_assign(1); } let mut carry_13 = z[12].overflowing_add_assign(a_12); if carry_12 { carry_13 |= z[12].overflowing_add_assign(1); } let mut carry_14 = z[13].overflowing_add_assign(a_13); if carry_13 { carry_14 |= z[13].overflowing_add_assign(1); } let mut carry_15 = z[14].overflowing_add_assign(a_14); if carry_14 { carry_15 |= z[14].overflowing_add_assign(1); } if 15 < z.len() { z[15].wrapping_add_assign(a_15); if carry_15 { z[15].wrapping_add_assign(1); } } }}; } // This is multi_sub_4 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_sub_4 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let borrow_1 = z[0].overflowing_sub_assign(a[0]); let mut borrow_2 = z[1].overflowing_sub_assign(a[1]); if borrow_1 { borrow_2 |= z[1].overflowing_sub_assign(1); } let mut borrow_3 = z[2].overflowing_sub_assign(a[2]); if borrow_2 { borrow_3 |= z[2].overflowing_sub_assign(1); } z[3].wrapping_sub_assign(a[3]); if borrow_3 { z[3].wrapping_sub_assign(1); } }}; } // This is multi_sub_5 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_sub_5 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let borrow_1 = z[0].overflowing_sub_assign(a[0]); let mut borrow_2 = z[1].overflowing_sub_assign(a[1]); if borrow_1 { borrow_2 |= z[1].overflowing_sub_assign(1); } let mut borrow_3 = z[2].overflowing_sub_assign(a[2]); if borrow_2 { borrow_3 |= z[2].overflowing_sub_assign(1); } let mut borrow_4 = z[3].overflowing_sub_assign(a[3]); if borrow_3 { borrow_4 |= z[3].overflowing_sub_assign(1); } z[4].wrapping_sub_assign(a[4]); if borrow_4 { z[4].wrapping_sub_assign(1); } }}; } // This is multi_sub_6 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_sub_6 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let borrow_1 = z[0].overflowing_sub_assign(a[0]); let mut borrow_2 = z[1].overflowing_sub_assign(a[1]); if borrow_1 { borrow_2 |= z[1].overflowing_sub_assign(1); } let mut borrow_3 = z[2].overflowing_sub_assign(a[2]); if borrow_2 { borrow_3 |= z[2].overflowing_sub_assign(1); } let mut borrow_4 = z[3].overflowing_sub_assign(a[3]); if borrow_3 { borrow_4 |= z[3].overflowing_sub_assign(1); } let mut borrow_5 = z[4].overflowing_sub_assign(a[4]); if borrow_4 { borrow_5 |= z[4].overflowing_sub_assign(1); } z[5].wrapping_sub_assign(a[5]); if borrow_5 { z[5].wrapping_sub_assign(1); } }}; } // This is multi_sub_7 from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! multi_sub_7 { ($z: expr, $a: expr) => {{ let z = $z; let a = $a; let borrow_1 = z[0].overflowing_sub_assign(a[0]); let mut borrow_2 = z[1].overflowing_sub_assign(a[1]); if borrow_1 { borrow_2 |= z[1].overflowing_sub_assign(1); } let mut borrow_3 = z[2].overflowing_sub_assign(a[2]); if borrow_2 { borrow_3 |= z[2].overflowing_sub_assign(1); } let mut borrow_4 = z[3].overflowing_sub_assign(a[3]); if borrow_3 { borrow_4 |= z[3].overflowing_sub_assign(1); } let mut borrow_5 = z[4].overflowing_sub_assign(a[4]); if borrow_4 { borrow_5 |= z[4].overflowing_sub_assign(1); } let mut borrow_6 = z[5].overflowing_sub_assign(a[5]); if borrow_5 { borrow_6 |= z[5].overflowing_sub_assign(1); } z[6].wrapping_sub_assign(a[6]); if borrow_6 { z[6].wrapping_sub_assign(1); } }}; } // This is _reduce_big_sum from crt_helpers.h, FLINT 3.3.0-dev. macro_rules! reduce_big_sum { ($n: expr, $faddm1: ident, $fsub: ident, $r: ident, $t: ident, $limit: expr) => { let limit = $limit; $faddm1!(&mut $r[1..], &$t[1..]); 'outer: loop { let mut goto_sub = false; for k in (2..=$n).rev() { let km1 = k - 1; if $r[km1] > limit[km1] { goto_sub = true; break; } if $r[km1] < limit[km1] { break 'outer; } } if !goto_sub && $r[0] < limit[0] { break 'outer; } $fsub!(&mut $r, limit); } }; } // This is _add_to_answer_easy from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! add_to_answer_easy { ( $n: expr, $fadd: ident, $fadd_alt: ident, $faddp1: ident, $fadd_altp1: ident, $z: ident, $r: ident, $toff: ident, $tshift: ident ) => {{ #[cfg(feature = "32_bit_limbs")] let z_len = $z.len().shr_round(1, Ceiling).0; #[cfg(not(feature = "32_bit_limbs"))] let z_len = $z.len(); assert!(z_len > $toff); if $tshift == 0 { #[cfg(feature = "32_bit_limbs")] $fadd_alt!(&mut $z[$toff << 1..], $r); #[cfg(not(feature = "32_bit_limbs"))] $fadd!(&mut $z[$toff..], $r); } else { let comp_shift = 64 - $tshift; $r[$n] = $r[$n - 1] >> comp_shift; for k in (2..=$n).rev() { $r[k - 1] = ($r[k - 1] << $tshift) | ($r[k - 2] >> comp_shift); } $r[0] <<= $tshift; #[cfg(feature = "32_bit_limbs")] $fadd_altp1!(&mut $z[$toff << 1..], $r); #[cfg(not(feature = "32_bit_limbs"))] $faddp1!(&mut $z[$toff..], $r); } }}; } #[cfg(feature = "32_bit_limbs")] fn limbs_slice_add_same_length_in_place_left_alt(xs: &mut [u32], ys: &[u64]) -> bool { let mut carry = 0; let mut xi = xs.iter_mut(); for &y in ys { let (y_hi, y_lo) = y.split_in_half(); let x = xi.next().unwrap(); (*x, carry) = add_with_carry_limb(*x, y_lo, carry); if let Some(x) = xi.next() { (*x, carry) = add_with_carry_limb(*x, y_hi, carry); } } carry != 0 } // This is _add_to_answer_hard from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! add_to_answer_hard { ( $n: expr, $fadd: ident, $fadd_alt: ident, $faddp1: ident, $fadd_altp1: ident, $z: ident, $r: ident, $toff: ident, $tshift: ident ) => {{ #[cfg(feature = "32_bit_limbs")] let z_len = $z.len().shr_round(1, Ceiling).0; #[cfg(not(feature = "32_bit_limbs"))] let z_len = $z.len(); assert!(z_len > $toff); let mut do_add = true; if $tshift == 0 { if z_len - $toff >= const { $n as usize } { #[cfg(feature = "32_bit_limbs")] $fadd_alt!(&mut $z[$toff << 1..], $r); #[cfg(not(feature = "32_bit_limbs"))] $fadd!(&mut $z[$toff..], $r); do_add = false; } } else { let comp_shift = 64 - $tshift; $r[$n] = $r[const { $n - 1 }] >> comp_shift; for k in (2..=$n).rev() { $r[k - 1] = ($r[k - 1] << $tshift) | ($r[k - 2] >> comp_shift); } $r[0] <<= $tshift; if z_len - $toff > const { $n as usize } { #[cfg(feature = "32_bit_limbs")] $fadd_altp1!(&mut $z[$toff << 1..], $r); #[cfg(not(feature = "32_bit_limbs"))] $faddp1!(&mut $z[$toff..], $r); do_add = false; } } if do_add { let diff = z_len - $toff; assert!(diff <= const { $n as usize }); #[cfg(feature = "32_bit_limbs")] limbs_slice_add_same_length_in_place_left_alt(&mut $z[$toff << 1..], &$r[..diff]); #[cfg(not(feature = "32_bit_limbs"))] limbs_slice_add_same_length_in_place_left(&mut $z[$toff..], &$r[..diff]); } }}; } macro_rules! f64x4_to_u64x4 { ($x: ident) => {{ let [a, b, c, d] = $x.to_array(); u64x4::from([ round_even!(a) as u64, round_even!(b) as u64, round_even!(c) as u64, round_even!(d) as u64, ]) }}; } // transpose a block // // This is _convert_block from fft_small/mpn_helpers.c, FLINT 3.3.0-dev. macro_rules! convert_block { ( $xs: ident, $rffts: ident, $d: ident, $dstride: ident, $np: expr, $i: expr ) => { let d_hi = &$d[$i << LG_BLK_SZ..]; let mut m = 0; for l in 0..$np { let xs_hi = &mut $xs[l << LG_BLK_SZ..]; let ds = &d_hi[m..]; let p = f64x4::splat($rffts[l].p); let pinv = f64x4::splat($rffts[l].pinv); for j in (0..BLK_SZ).step_by(VEC_SZ << 2) { let mut x0 = read_f64x4!(ds, j); let mut x1 = read_f64x4!(ds, j + VEC_SZ); let mut x2 = read_f64x4!(ds, j + const { 2 * VEC_SZ }); let mut x3 = read_f64x4!(ds, j + const { 3 * VEC_SZ }); x0 = f64x4_reduce_to_0n!(x0, p, pinv); x1 = f64x4_reduce_to_0n!(x1, p, pinv); x2 = f64x4_reduce_to_0n!(x2, p, pinv); x3 = f64x4_reduce_to_0n!(x3, p, pinv); let y0 = f64x4_to_u64x4!(x0); let y1 = f64x4_to_u64x4!(x1); let y2 = f64x4_to_u64x4!(x2); let y3 = f64x4_to_u64x4!(x3); write_f64x4!(xs_hi, j, y0); write_f64x4!(xs_hi, j + VEC_SZ, y1); write_f64x4!(xs_hi, j + const { 2 * VEC_SZ }, y2); write_f64x4!(xs_hi, j + const { 3 * VEC_SZ }, y3); } m += $dstride; } }; } // The "n" here is the limb count Rcrts[np-1].coeff_len, which is big enough to hold (product of // primes)*(number of primes), so it can hold the intermediate dot products f[0]*x[0] + ... + // f[np-1]*x[np-1]. The x[i] are single limb and the f[i] are of length "m". The number of primes // is "np". // // The coefficient of X^i, 0 <= i < zlen needs to be reconstructed and added to the answer mpn (z, // zn). This involves the limbs // // z[floor(i*bits/64)] ... z[floor(i*bits/64)+n] // // so is easy if floor(i*bits/64)+n < zn. // // The the l^th fft ctx Rffts[l] is expected to have data at d + l*dstride // // handle output coefficients from [start_easy, zlen) end_easy is still expected to be valid // // This is _mpn_from_ffts and crt_worker_func from fft_small/mpn_mul.c, FLINT 3.3.0-dev. macro_rules! process_crt { ( $f: ident, $np: expr, $n: expr, $m: expr, $faddm1: ident, $fadd: ident, $faddp1: ident, $fadd_alt: ident, $faddp1_alt: ident, $fsub: ident ) => { fn $f( zs: &mut [Limb], zlen: usize, rffts: &[FFTContext], ds: &[f64], dstride: usize, rcrts: &mut [CRTData], bits: usize, stop_easy: usize, ) { #[cfg(feature = "32_bit_limbs")] let zn_stop = zs.len().shr_round(1, Ceiling).0; #[cfg(not(feature = "32_bit_limbs"))] let zn_stop = zs.len(); let rcrt = &mut rcrts[const {$np - 1}]; assert_eq!($n, rcrt.coeff_len); if const{$n != $m} { for l in 0..$np { assert_eq!(rcrt.co_prime(l)[$m], 0); } } zs.fill(0); let mut xs = [0; $np << LG_BLK_SZ]; let mut r = [0; $n + 1]; let mut t = [0; $n + 1]; let mut k = 0; for i in (0..stop_easy).step_by(BLK_SZ) { convert_block!(xs, rffts, ds, dstride, $np, i >> LG_BLK_SZ); for j in 0..BLK_SZ { big_mul!($n, $m, r, t, rcrt.co_prime(0), xs[j]); let xs_hi = &xs[j..]; let mut m = BLK_SZ; for l in 1..$np { big_add_mul!($n, $m, r, t, rcrt.co_prime(l), xs_hi[m]); m += BLK_SZ; } reduce_big_sum!($n, $faddm1, $fsub, r, t, rcrt.prod_primes_ref()); let toff = k >> u64::LOG_WIDTH; let tshift = k & const {u64::WIDTH_MASK as usize}; assert!(zn_stop > $n + toff); add_to_answer_easy!( $n, $fadd, $fadd_alt, $faddp1, $faddp1_alt, zs, r, toff, tshift ); k += bits; } } let mut j = stop_easy * bits; for i in stop_easy..zlen { let ds_hi = &ds[i..]; let mut xx = ds_hi[0]; let rfft = &rffts[0]; let mut x = f64_reduce_to_0n!(xx, rfft.p, rfft.pinv) as u64; big_mul!($n, $m, r, t, rcrt.co_prime(0), x); let mut m = dstride; for l in 1..$np { xx = ds_hi[m]; let rfft = &rffts[l]; x = f64_reduce_to_0n!(xx, rfft.p, rfft.pinv) as u64; big_add_mul!($n, $m, r, t, rcrt.co_prime(l), x); m += dstride; } reduce_big_sum!($n, $faddm1, $fsub, r, t, rcrt.prod_primes_ref()); let toff = j >> u64::LOG_WIDTH; let tshift = j & const {u64::WIDTH_MASK as usize}; if toff >= zn_stop { break; } add_to_answer_hard!( $n, $fadd, $fadd_alt, $faddp1, $faddp1_alt, zs, r, toff, tshift ); j += bits; } } } } process_crt!( process_crt_4_4_3, 4, 4, 3, multi_add_3, multi_add_4, multi_add_5, multi_add_4_alt, multi_add_5_alt, multi_sub_4 ); process_crt!( process_crt_5_4_4, 5, 4, 4, multi_add_3, multi_add_4, multi_add_5, multi_add_4_alt, multi_add_5_alt, multi_sub_4 ); process_crt!( process_crt_6_5_4, 6, 5, 4, multi_add_4, multi_add_5, multi_add_6, multi_add_5_alt, multi_add_6_alt, multi_sub_5 ); process_crt!( process_crt_7_6_5, 7, 6, 5, multi_add_5, multi_add_6, multi_add_7, multi_add_6_alt, multi_add_7_alt, multi_sub_6 ); process_crt!( process_crt_8_7_6, 8, 7, 6, multi_add_6, multi_add_7, multi_add_8, multi_add_7_alt, multi_add_8_alt, multi_sub_7 ); // This is mpn_ctx_mpn_mul from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn mpn_ctx_mpn_mul(r: &mut Context, z: &mut [Limb], a: &[Limb], b: &[Limb], test_slow: bool) { let squaring = core::ptr::addr_eq(a as *const [Limb], b as *const [Limb]) && a.len() == b.len(); let an = a.len(); let bn = b.len(); #[cfg(feature = "32_bit_limbs")] let an = an.shr_round(1, Ceiling).0; #[cfg(feature = "32_bit_limbs")] let bn = bn.shr_round(1, Ceiling).0; let mut p = ProfileEntry::default(); mpn_ctx_best_profile(r, &mut p, an, bn); let zn = an + bn; let alen = usize::exact_from( u64::exact_from(an << u64::LOG_WIDTH) .div_round(p.bits, Ceiling) .0, ); let blen = usize::exact_from( u64::exact_from(bn << u64::LOG_WIDTH) .div_round(p.bits, Ceiling) .0, ); let zlen = alen + blen - 1; let atrunc = alen.round_to_multiple(BLK_SZ, Ceiling).0; let btrunc = blen.round_to_multiple(BLK_SZ, Ceiling).0; let ztrunc = zlen.round_to_multiple(BLK_SZ, Ceiling).0; let depth = max(LG_BLK_SZ, ztrunc.ceiling_log_base_2()); let stride = usize::power_of_2(depth) .round_to_multiple_of_power_of_2(7, Ceiling) .0; assert_ne!(an, 0); assert_ne!(bn, 0); let coeff_len = CONTEXT.crts[p.np - 1].coeff_len; assert_ne!( flint_mpn_cmp_ui_2exp( &r.crts[p.np - 1].prod_primes_ref()[..coeff_len], blen as u64, p.bits << 1, ), Less ); let abuf; // Normally, p.to_ffts is None only for extremely large arguments, which are impractical to // test, so we set a test_slow flag instead if !test_slow && let Some(to_ffts) = p.to_ffts { let bits = p.bits as usize; let an_64 = an << 6; let bn_64 = bn << 6; // if i*bits + 32 < 64*an, then the index into a is always in bounds let mut a_stop_easy = min(atrunc, (an_64 - 33) / bits); // if i*bits >= 64*an, then the index into a is always out of bounds let a_stop_hard = min(atrunc, an_64.div_ceil(bits)); // ditto let mut b_stop_easy = min(btrunc, (bn_64 - 33) / bits); let b_stop_hard = min(btrunc, bn_64.div_ceil(bits)); let rounding: usize = if bits & 7 == 0 { 4 } else if bits & 3 == 0 { 8 } else { 16 }; let prod = p.np * stride; mpn_ctx_fit_buffer(r, prod << 4); let bbuf; (abuf, bbuf) = r.buffer.split_at_mut(prod); // some fixups for loop unrollings: round down the easy stops assert!(bits.even()); a_stop_easy &= rounding.wrapping_neg(); b_stop_easy &= rounding.wrapping_neg(); process_mod( to_ffts, &r.ffts, stride, &r.vec_two_pow_tab_backing [r.vec_two_pow_tab_offsets[p.np.div_round(VEC_SZ, Ceiling).0 - 1]..], abuf, a, atrunc, a_stop_easy.round_to_multiple(rounding, Ceiling).0, a_stop_easy, a_stop_hard, bbuf, b, btrunc, b_stop_easy.round_to_multiple(rounding, Ceiling).0, b_stop_easy, b_stop_hard, squaring, ); let crt = &r.crts[p.np - 1]; let mut m = 0; for l in 0..p.np { process_fft( &mut r.ffts[l], crt.co_prime_red(l), depth, ztrunc, &mut abuf[m..], atrunc, &mut bbuf[m..], btrunc, squaring, ); m += stride; } } else { mpn_ctx_fit_buffer(r, ((p.np + 1) * stride) << 3); let crt = &r.crts[p.np - 1]; let bbuf; (abuf, bbuf) = r.buffer.split_at_mut(p.np * stride); let mut m = 0; for l in 0..p.np { process_mod_fft( p.bits as usize, &mut r.ffts[l], &r.slow_two_pow_backing[r.slow_two_pow_offsets[l]..], crt.co_prime_red(l), depth, ztrunc, a, &mut abuf[m..], atrunc, b, bbuf, btrunc, squaring, ); m += stride; } } let n = r.crts[p.np - 1].coeff_len; let mut end_easy = ((if zn > n { zn - (n + 1) } else { 0 }) << 6) / (p.bits as usize); // this is how much space was statically allocated in each struct assert!(n <= MPN_CTX_NCRTS); end_easy &= BLK_SZ.wrapping_neg(); assert!(4 <= p.np && p.np <= 8); let process_crt = match p.np { 4 => process_crt_4_4_3, 5 => process_crt_5_4_4, 6 => process_crt_6_5_4, 7 => process_crt_7_6_5, 8 => process_crt_8_7_6, _ => unreachable!(), }; process_crt( z, zlen, &r.ffts, abuf, stride, &mut r.crts, p.bits as usize, end_easy.round_to_multiple(BLK_SZ, Ceiling).0, ); } // This is mpn_mul_default_mpn_ctx from fft_small/default_ctx.c, FLINT 3.3.0-dev. pub(crate) fn mpn_mul_default_mpn_ctx(r1: &mut [Limb], i1: &[Limb], i2: &[Limb], test_slow: bool) { let mut context = CONTEXT.deserialize(); mpn_ctx_mpn_mul(&mut context, r1, i1, i2, test_slow); } pub(crate) fn mpn_square_default_mpn_ctx(r1: &mut [Limb], i1: &[Limb]) { let mut context = CONTEXT.deserialize(); mpn_ctx_mpn_mul(&mut context, r1, i1, i1, false); } ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/limb.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::XMulYToZZ; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{HasHalf, SplitInHalf}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the product of the `Natural` and a `Limb`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mul_1` from `mpn/generic/mul_1.c`, GMP 6.2.1, where the result is // returned. pub_test! {limbs_mul_limb(xs: &[Limb], y: Limb) -> Vec { let mut carry = 0; let y = DoubleLimb::from(y); let mut out = Vec::with_capacity(xs.len()); for &x in xs { let product = DoubleLimb::from(x) * y + DoubleLimb::from(carry); out.push(product.lower_half()); carry = product.upper_half(); } if carry != 0 { out.push(carry); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the product of the `Natural` and a `Limb`, plus a carry, to an output slice. The output // slice must be at least as long as the input slice. Returns the carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`. // // This is equivalent to `mul_1c` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_limb_with_carry_to_out< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], xs: &[T], y: T, mut carry: T, ) -> T { let y = DT::from(y); for (out, x) in out[..xs.len()].iter_mut().zip(xs.iter()) { let product = DT::from(*x) * y + DT::from(carry); (carry, *out) = product.split_in_half(); } carry }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the product of the `Natural` and a `Limb` to an output slice. The output slice must be // at least as long as the input slice. Returns the carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`. // // This is equivalent to `mpn_mul_1` from `mpn/generic/mul_1.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_limb_to_out< DT: From + HasHalf + PrimitiveUnsigned + SplitInHalf, T: PrimitiveUnsigned, >( out: &mut [T], xs: &[T], y: T, ) -> T { limbs_mul_limb_with_carry_to_out::(out, xs, y, T::ZERO) }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the product of the `Natural` and a `Limb`, plus a carry, to the input slice. Returns the // carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mul_1c` from `gmp-impl.h`, GMP 6.2.1, where the output is the same as the // input. pub_crate_test! {limbs_slice_mul_limb_with_carry_in_place( xs: &mut [Limb], y: Limb, mut carry: Limb ) -> Limb { let y = DoubleLimb::from(y); for x in &mut *xs { let product = DoubleLimb::from(*x) * y + DoubleLimb::from(carry); *x = product.lower_half(); carry = product.upper_half(); } carry }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the product of the `Natural` and a `Limb` to the input slice. Returns the carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mul_1` from `mpn/generic/mul_1.c`, GMP 6.2.1, where `rp == up`. pub_crate_test! {limbs_slice_mul_limb_in_place(xs: &mut [Limb], y: Limb) -> Limb { limbs_slice_mul_limb_with_carry_in_place(xs, y, 0) }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the product of the `Natural` and a `Limb` to the input `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mul_1` from `mpn/generic/mul_1.c`, GMP 6.2.1, where the `rp == up` and // instead of returning the carry, it is appended to `rp`. pub_test! {limbs_vec_mul_limb_in_place(xs: &mut Vec, y: Limb) { let carry = limbs_slice_mul_limb_in_place(xs, y); if carry != 0 { xs.push(carry); } }} impl Natural { pub(crate) fn mul_assign_limb(&mut self, other: Limb) { match (&mut *self, other) { (_, 0) => *self = Self::ZERO, (_, 1) | (&mut Self::ZERO, _) => {} (&mut Self::ONE, _) => *self = Self::from(other), (Self(Small(small)), other) => { let (upper, lower) = Limb::x_mul_y_to_zz(*small, other); if upper == 0 { *small = lower; } else { *self = Self(Large(vec![lower, upper])); } } (Self(Large(limbs)), other) => { limbs_vec_mul_limb_in_place(limbs, other); } } } pub(crate) fn mul_limb_ref(&self, other: Limb) -> Self { match (self, other) { (_, 0) => Self::ZERO, (_, 1) | (&Self::ZERO, _) => self.clone(), (&Self::ONE, _) => Self::from(other), (Self(Small(small)), other) => Self({ let (upper, lower) = Limb::x_mul_y_to_zz(*small, other); if upper == 0 { Small(lower) } else { Large(vec![lower, upper]) } }), (Self(Large(limbs)), other) => Self(Large(limbs_mul_limb(limbs, other))), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Some optimizations contributed by florian1345. // // Uses code adopted from the GNU MP Library. // // `mpn_mul` and `TOOM44_OK` contributed to the GNU project by Torbjörn Granlund. // // Copyright © 1991—1994, 1996, 1996-2003, 2005-2007, 2008, 2009, 2010, 2012, 2014, 2019 // Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::limbs_slice_add_greater_in_place_left; use crate::natural::arithmetic::add_mul::{ limbs_slice_add_mul_limb_same_length_in_place_left, limbs_slice_add_mul_two_limbs_matching_length_in_place_left, }; use crate::natural::arithmetic::mul::fft::mpn_mul_default_mpn_ctx; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::toom::MUL_TOOM33_THRESHOLD_LIMIT; use crate::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h, limbs_mul_greater_to_out_toom_6h_scratch_len, limbs_mul_greater_to_out_toom_8h, limbs_mul_greater_to_out_toom_8h_scratch_len, limbs_mul_greater_to_out_toom_22, limbs_mul_greater_to_out_toom_22_scratch_len, limbs_mul_greater_to_out_toom_32, limbs_mul_greater_to_out_toom_32_scratch_len, limbs_mul_greater_to_out_toom_33, limbs_mul_greater_to_out_toom_33_scratch_len, limbs_mul_greater_to_out_toom_42, limbs_mul_greater_to_out_toom_42_scratch_len, limbs_mul_greater_to_out_toom_43, limbs_mul_greater_to_out_toom_43_scratch_len, limbs_mul_greater_to_out_toom_44, limbs_mul_greater_to_out_toom_44_scratch_len, limbs_mul_greater_to_out_toom_53, limbs_mul_greater_to_out_toom_53_scratch_len, limbs_mul_greater_to_out_toom_63, limbs_mul_greater_to_out_toom_63_scratch_len, }; use crate::platform::{ DoubleLimb, Limb, MUL_FFT_THRESHOLD, MUL_TOOM6H_THRESHOLD, MUL_TOOM8H_THRESHOLD, MUL_TOOM22_THRESHOLD, MUL_TOOM32_TO_TOOM43_THRESHOLD, MUL_TOOM32_TO_TOOM53_THRESHOLD, MUL_TOOM33_THRESHOLD, MUL_TOOM42_TO_TOOM53_THRESHOLD, MUL_TOOM42_TO_TOOM63_THRESHOLD, MUL_TOOM44_THRESHOLD, }; use alloc::vec::Vec; use core::cmp::max; use core::iter::Product; use core::ops::{Mul, MulAssign}; use malachite_base::num::basic::traits::One; use malachite_base::num::basic::traits::Zero; // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns // the limbs of the product of the `Natural`s. `xs` must be as least as long as `ys` and `ys` cannot // be empty. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys` or `ys` is empty. // // This is equivalent to `mpn_mul` from `mpn/generic/mul.c`, GMP 6.2.1, where `prodp` is returned. pub_test! {limbs_mul_greater(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let out_len = xs_len + ys_len; let mut scratch = vec![0; out_len + limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; let (out, mul_scratch) = scratch.split_at_mut(out_len); limbs_mul_greater_to_out(out, xs, ys, mul_scratch); scratch.truncate(out_len); scratch.shrink_to_fit(); scratch }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns // the limbs of the product of the `Natural`s. Neither slice can be empty. The length of the // resulting slice is always the sum of the lengths of the input slices, so it may have trailing // zeros. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if either slice is empty. // // This is equivalent to `mpn_mul` from mpn/generic/mul.c, GMP 6.2.1, where `un` may be less than // `vn` and `prodp` is returned. pub_crate_test! {limbs_mul(xs: &[Limb], ys: &[Limb]) -> Vec { if xs.len() >= ys.len() { limbs_mul_greater(xs, ys) } else { limbs_mul_greater(ys, xs) } }} pub_crate_test! { limbs_mul_same_length_to_out_scratch_len(len: usize) -> usize { if len < MUL_TOOM22_THRESHOLD { 0 } else if len < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22_scratch_len( MUL_TOOM33_THRESHOLD_LIMIT - 1, MUL_TOOM33_THRESHOLD_LIMIT - 1, ) } else if len < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33_scratch_len(len, len) } else if len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44_scratch_len(len, len) } else if len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h_scratch_len(len, len) } else if len < FFT_MUL_THRESHOLD { limbs_mul_greater_to_out_toom_8h_scratch_len(len, len) } else { 0 } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the `2 * xs.len()` least-significant limbs of the product of the `Natural`s to // an output slice. The output must be at least as long as `2 * xs.len()`, `xs` must be as long as // `ys`, and neither slice can be empty. Returns the result limb at index `2 * xs.len() - 1` (which // may be zero). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is too short, `xs` and `ys` have different lengths, or either slice is empty. // // This is equivalent to `mpn_mul_n` from `mpn/generic/mul_n.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_same_length_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb] ) { let len = xs.len(); assert_eq!(ys.len(), len); assert_ne!(len, 0); let out = &mut out[..len << 1]; if len < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if len < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if len < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else if len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } else if len < FFT_MUL_THRESHOLD { limbs_mul_greater_to_out_toom_8h(out, xs, ys, scratch); } else { mpn_mul_default_mpn_ctx(out, xs, ys, false); } }} // This is equivalent to `TOOM44_OK` from `mpn/generic/mul.c`, GMP 6.2.1. pub_const_crate_test! {toom44_ok(xs_len: usize, ys_len: usize) -> bool { 12 + 3 * xs_len < ys_len << 2 }} pub_crate_test! { limbs_mul_greater_to_out_scratch_len(xs_len: usize, ys_len: usize) -> usize { assert!(xs_len >= ys_len); assert_ne!(ys_len, 0); if xs_len == ys_len { limbs_mul_same_length_to_out_scratch_len(xs_len) } else if ys_len < MUL_TOOM22_THRESHOLD { 0 } else if ys_len < MUL_TOOM33_THRESHOLD { if xs_len >= 3 * ys_len { let two_ys_len = ys_len << 1; let three_ys_len = two_ys_len + ys_len; let four_ys_len = two_ys_len << 1; let mut xs_len = xs_len - two_ys_len; while xs_len >= three_ys_len { xs_len -= two_ys_len; } let four_xs_len = xs_len << 2; let first_mul_scratch_len = limbs_mul_greater_to_out_toom_42_scratch_len(two_ys_len, ys_len); let second_mul_scratch_len = if four_xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22_scratch_len(xs_len, ys_len) } else if four_xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_42_scratch_len(xs_len, ys_len) }; max(first_mul_scratch_len, second_mul_scratch_len) + four_ys_len } else if 4 * xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22_scratch_len(xs_len, ys_len) } else if 4 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_42_scratch_len(xs_len, ys_len) } } else if (xs_len + ys_len) >> 1 < MUL_FFT_THRESHOLD || 3 * ys_len < MUL_FFT_THRESHOLD { if ys_len < MUL_TOOM44_THRESHOLD || !toom44_ok(xs_len, ys_len) { // Use ToomX3 variants if xs_len << 1 >= 5 * ys_len { let two_ys_len = ys_len << 1; let four_ys_len = two_ys_len << 1; let first_mul_scratch_len = if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42_scratch_len(two_ys_len, ys_len) } else { limbs_mul_greater_to_out_toom_63_scratch_len(two_ys_len, ys_len) }; let mut xs_len = xs_len - two_ys_len; while xs_len << 1 >= 5 * ys_len { xs_len -= two_ys_len; } let second_mul_scratch_len = limbs_mul_to_out_scratch_len(xs_len, ys_len); max(first_mul_scratch_len, second_mul_scratch_len) + four_ys_len } else if 6 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_33_scratch_len(xs_len, ys_len) } else if xs_len << 1 < 3 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM43_THRESHOLD { limbs_mul_greater_to_out_toom_32_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_43_scratch_len(xs_len, ys_len) } } else if 6 * xs_len < 11 * ys_len { if xs_len << 2 < 7 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_32_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_53_scratch_len(xs_len, ys_len) } } else if ys_len < MUL_TOOM42_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_42_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_53_scratch_len(xs_len, ys_len) } } else if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_63_scratch_len(xs_len, ys_len) } } else if ys_len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44_scratch_len(xs_len, ys_len) } else if ys_len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_toom_8h_scratch_len(xs_len, ys_len) } } else { 0 } }} pub_const_crate_test_const! {FFT_MUL_THRESHOLD: usize = 1000;} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. The output must be at least as long as `xs.len() + ys.len()`, `xs` must be as least as // long as `ys`, and `ys` cannot be empty. Returns the result limb at index `xs.len() + ys.len() - // 1` (which may be zero). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is too short, `xs` is shorter than `ys`, or `ys` is empty. // // This is _flint_mpn_mul from mpn_extras/mul.c, FLINT 3.3.0-dev. pub_crate_test! {limbs_mul_greater_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) -> Limb { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let out_len = xs_len + ys_len; assert!(out.len() >= out_len); if xs_len == ys_len { limbs_mul_same_length_to_out(out, xs, ys, scratch); } else if ys_len < FFT_MUL_THRESHOLD { let mut scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; limbs_mul_greater_to_out_old(out, xs, ys, &mut scratch); } else { mpn_mul_default_mpn_ctx(out, xs, ys, false); } out[xs_len + ys_len - 1] }} pub_crate_test! {limbs_mul_greater_to_out_old( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb] ) -> Limb { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); assert_ne!(ys_len, 0); assert!(out.len() >= xs_len + ys_len); if ys_len < MUL_TOOM22_THRESHOLD { // Plain schoolbook multiplication. Unless xs_len is very large, or else if // `limbs_mul_same_length_to_out` applies, perform basecase multiply directly. limbs_mul_greater_to_out_basecase(out, xs, ys); } else if ys_len < MUL_TOOM33_THRESHOLD { if xs_len >= 3 * ys_len { let two_ys_len = ys_len << 1; let three_ys_len = two_ys_len + ys_len; let four_ys_len = two_ys_len << 1; let (scratch, mul_scratch) = scratch.split_at_mut(four_ys_len); limbs_mul_greater_to_out_toom_42(out, &xs[..two_ys_len], ys, mul_scratch); let mut xs = &xs[two_ys_len..]; let mut out_offset = two_ys_len; while xs.len() >= three_ys_len { let out = &mut out[out_offset..]; let (xs_lo, xs_hi) = xs.split_at(two_ys_len); limbs_mul_greater_to_out_toom_42(scratch, xs_lo, ys, mul_scratch); let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..three_ys_len].copy_from_slice(&scratch_hi[..two_ys_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); xs = xs_hi; out_offset += two_ys_len; } let xs_len = xs.len(); let out = &mut out[out_offset..]; // ys_len <= xs_len < 3 * ys_len let four_xs_len = xs_len << 2; if four_xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22(scratch, xs, ys, mul_scratch); } else if four_xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32(scratch, xs, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_42(scratch, xs, ys, mul_scratch); } let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..ys_len + xs_len].copy_from_slice(&scratch_hi[..xs_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); } else if 4 * xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if 4 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } } else if (xs_len + ys_len) >> 1 < MUL_FFT_THRESHOLD || 3 * ys_len < MUL_FFT_THRESHOLD { // Handle the largest operands that are not in the FFT range. The 2nd condition makes very // unbalanced operands avoid the FFT code (except perhaps as coefficient products of the // Toom code). if ys_len < MUL_TOOM44_THRESHOLD || !toom44_ok(xs_len, ys_len) { // Use ToomX3 variants if xs_len << 1 >= 5 * ys_len { let two_ys_len = ys_len << 1; let four_ys_len = two_ys_len << 1; let (scratch, mul_scratch) = scratch.split_at_mut(four_ys_len); let (xs_lo, mut xs) = xs.split_at(two_ys_len); if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs_lo, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_63(out, xs_lo, ys, mul_scratch); } let mut out_offset = two_ys_len; // xs_len >= 2.5 * ys_len while xs.len() << 1 >= 5 * ys_len { let out = &mut out[out_offset..]; let (xs_lo, xs_hi) = xs.split_at(two_ys_len); if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(scratch, xs_lo, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_63(scratch, xs_lo, ys, mul_scratch); } let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..ys_len + two_ys_len].copy_from_slice(&scratch_hi[..two_ys_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); xs = xs_hi; out_offset += two_ys_len; } let xs_len = xs.len(); let out = &mut out[out_offset..]; // ys_len / 2 <= xs_len < 2.5 * ys_len limbs_mul_to_out(scratch, xs, ys, mul_scratch); let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..xs_len + ys_len].copy_from_slice(&scratch_hi[..xs_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); } else if 6 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if xs_len << 1 < 3 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM43_THRESHOLD { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_43(out, xs, ys, scratch); } } else if 6 * xs_len < 11 * ys_len { if xs_len << 2 < 7 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_53(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM42_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_53(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_63(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else if ys_len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_8h(out, xs, ys, scratch); } } else { mpn_mul_default_mpn_ctx(out, xs, ys, false); } out[xs_len + ys_len - 1] }} pub_crate_test! {limbs_mul_to_out_scratch_len(xs_len: usize, ys_len: usize) -> usize { if xs_len >= ys_len { limbs_mul_greater_to_out_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_scratch_len(ys_len, xs_len) } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. The output must be at least as long as `xs.len() + ys.len()`, and neither slice can be // empty. Returns the result limb at index `xs.len() + ys.len() - 1` (which may be zero). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short or either slice is empty. // // This is equivalent to `mpn_mul` from `mpn/generic/mul.c`, GMP 6.2.1, where `un` may be less than // `vn`. pub_crate_test! {limbs_mul_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb] ) -> Limb { if xs.len() >= ys.len() { limbs_mul_greater_to_out(out, xs, ys, scratch) } else { limbs_mul_greater_to_out(out, ys, xs, scratch) } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. The output must be at least as long as `xs.len() + ys.len()`, `xs` must be as least as // long as `ys`, and `ys` cannot be empty. Returns the result limb at index `xs.len() + ys.len() - // 1` (which may be zero). // // This uses the basecase, quadratic, schoolbook algorithm, and it is most critical code for // multiplication. All multiplies rely on this, both small and huge. Small ones arrive here // immediately, and huge ones arrive here as this is the base case for Karatsuba's recursive // algorithm. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short, `xs` is shorter than `ys`, or `ys` is empty. // // This is equivalent to `mpn_mul_basecase` from `mpn/generic/mul_basecase.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_basecase(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); assert!(out.len() >= xs_len + ys_len); let out = &mut out[..(xs_len + ys_len)]; // We first multiply by the low order limb. This result can be stored, not added, to out. out[xs_len] = limbs_mul_limb_to_out::(out, xs, ys[0]); // Now accumulate the product of xs and the next higher limb from ys. let window_size = xs_len + 1; let mut i = 1; let max = ys_len - 1; while i < max { let (out_last, out_init) = out[i..=i + window_size].split_last_mut().unwrap(); *out_last = limbs_slice_add_mul_two_limbs_matching_length_in_place_left( out_init, xs, [ys[i], ys[i + 1]], ); i += 2; } if i <= max { let (out_last, out_init) = out[i..i + window_size].split_last_mut().unwrap(); *out_last = limbs_slice_add_mul_limb_same_length_in_place_left(out_init, xs, ys[i]); } }} impl Mul for Natural { type Output = Self; /// Multiplies two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ONE * Natural::from(123u32), 123); /// assert_eq!(Natural::from(123u32) * Natural::ZERO, 0); /// assert_eq!(Natural::from(123u32) * Natural::from(456u32), 56088); /// assert_eq!( /// (Natural::from_str("123456789000").unwrap() /// * Natural::from_str("987654321000").unwrap()) /// .to_string(), /// "121932631112635269000000" /// ); /// ``` #[inline] fn mul(mut self, other: Self) -> Self { self *= other; self } } impl<'a> Mul<&'a Self> for Natural { type Output = Self; /// Multiplies two [`Natural`]s, taking the first by value and the second by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ONE * &Natural::from(123u32), 123); /// assert_eq!(Natural::from(123u32) * &Natural::ZERO, 0); /// assert_eq!(Natural::from(123u32) * &Natural::from(456u32), 56088); /// assert_eq!( /// (Natural::from_str("123456789000").unwrap() /// * &Natural::from_str("987654321000").unwrap()) /// .to_string(), /// "121932631112635269000000" /// ); /// ``` #[inline] fn mul(mut self, other: &'a Self) -> Self { self *= other; self } } impl Mul for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s, taking the first by reference and the second by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::ONE * Natural::from(123u32), 123); /// assert_eq!(&Natural::from(123u32) * Natural::ZERO, 0); /// assert_eq!(&Natural::from(123u32) * Natural::from(456u32), 56088); /// assert_eq!( /// (&Natural::from_str("123456789000").unwrap() /// * Natural::from_str("987654321000").unwrap()) /// .to_string(), /// "121932631112635269000000" /// ); /// ``` #[inline] fn mul(self, mut other: Natural) -> Natural { other *= self; other } } impl Mul<&Natural> for &Natural { type Output = Natural; /// Multiplies two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::ONE * &Natural::from(123u32), 123); /// assert_eq!(&Natural::from(123u32) * &Natural::ZERO, 0); /// assert_eq!(&Natural::from(123u32) * &Natural::from(456u32), 56088); /// assert_eq!( /// (&Natural::from_str("123456789000").unwrap() /// * &Natural::from_str("987654321000").unwrap()) /// .to_string(), /// "121932631112635269000000" /// ); /// ``` fn mul(self, other: &Natural) -> Natural { match (self, other) { (Natural(Small(x)), y) => y.mul_limb_ref(*x), (x, Natural(Small(y))) => x.mul_limb_ref(*y), (Natural(Large(xs)), Natural(Large(ys))) => { Natural::from_owned_limbs_asc(limbs_mul(xs, ys)) } } } } impl MulAssign for Natural { /// Multiplies a [`Natural`] by a [`Natural`] in place, taking the [`Natural`] on the right-hand /// side by value. /// /// $$ /// x \gets = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ONE; /// x *= Natural::from_str("1000").unwrap(); /// x *= Natural::from_str("2000").unwrap(); /// x *= Natural::from_str("3000").unwrap(); /// x *= Natural::from_str("4000").unwrap(); /// assert_eq!(x.to_string(), "24000000000000"); /// ``` fn mul_assign(&mut self, mut other: Self) { match (&mut *self, &mut other) { (Self(Small(x)), _) => { other.mul_assign_limb(*x); *self = other; } (_, Self(Small(y))) => self.mul_assign_limb(*y), (Self(Large(xs)), Self(Large(ys))) => { *xs = limbs_mul(xs, ys); self.trim(); } } } } impl<'a> MulAssign<&'a Self> for Natural { /// Multiplies a [`Natural`] by a [`Natural`] in place, taking the [`Natural`] on the right-hand /// side by reference. /// /// $$ /// x \gets = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ONE; /// x *= &Natural::from_str("1000").unwrap(); /// x *= &Natural::from_str("2000").unwrap(); /// x *= &Natural::from_str("3000").unwrap(); /// x *= &Natural::from_str("4000").unwrap(); /// assert_eq!(x.to_string(), "24000000000000"); /// ``` fn mul_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (Self(Small(x)), _) => *self = other.mul_limb_ref(*x), (_, Self(Small(y))) => self.mul_assign_limb(*y), (Self(Large(xs)), Self(Large(ys))) => { *xs = limbs_mul(xs, ys); self.trim(); } } } } impl Product for Natural { /// Multiplies together all the [`Natural`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Natural::sum(xs.map(Natural::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Product; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::product(vec_from_str::("[2, 3, 5, 7]").unwrap().into_iter()), /// 210 /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { if x == 0 { return Self::ZERO; } let mut p = x; for _ in 0..i.trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } impl<'a> Product<&'a Self> for Natural { /// Multiplies together all the [`Natural`]s in an iterator of [`Natural`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Natural::sum(xs.map(Natural::significant_bits))`. /// /// # Examples /// ``` /// use core::iter::Product; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::product(vec_from_str::("[2, 3, 5, 7]").unwrap().iter()), /// 210 /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { if *x == 0 { return Self::ZERO; } let mut p = x.clone(); for _ in 0..i.trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } /// A precomputed object used by FFT code. pub mod context; /// Code for multiplying large integers. Derived from Daniel Schultz's small-prime FFT /// implementation for FLINT. pub mod fft; /// Code for multiplying a many-limbed [`Natural`] by a single [limb](crate#limbs). pub mod limb; /// Code for computing only the lowest [limbs](crate#limbs) of the product of two [`Natural`]s. pub mod mul_low; /// Code for multiplying two [`Natural`]s modulo one less than a large power of 2; used by the /// Schönhage-Strassen algorithm. pub mod mul_mod; /// Code for evaluating polynomials at various points; used in Toom-Cook multiplication. pub mod poly_eval; /// Code for reconstructing polynomials from their values at various points; used in Toom-Cook /// multiplication. pub mod poly_interpolate; #[cfg(feature = "test_build")] /// Code for multiplying several limbs together. pub mod product_of_limbs; #[cfg(not(feature = "test_build"))] /// Code for multiplying several limbs together. pub(crate) mod product_of_limbs; /// Code for Toom-Cook multiplication. pub mod toom; ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/mul_low.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_mullo_n`, `mpn_mullo_n_itch`, and `mpn_dc_mullo_n` contributed to the GNU project by // Torbjörn Granlund and Marco Bodrato. // // Copyright © 2000, 2002, 2004, 2005, 2009, 2010, 2012, 2015 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_same_length_to_out, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::toom::{TUNE_PROGRAM_BUILD, WANT_FAT_BINARY}; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out_basecase, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, }; use crate::platform::{ DoubleLimb, Limb, MUL_TOOM8H_THRESHOLD, MUL_TOOM22_THRESHOLD, MUL_TOOM33_THRESHOLD, MUL_TOOM44_THRESHOLD, MULLO_BASECASE_THRESHOLD, MULLO_DC_THRESHOLD, MULLO_MUL_N_THRESHOLD, }; use malachite_base::num::arithmetic::traits::WrappingAddAssign; // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mullo_basecase` from `mpn/generic/mullo_basecase.c`, GMP 6.2.1, // `MULLO_VARIANT == 2`. pub_crate_test! {limbs_mul_low_same_length_basecase(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let n = xs.len(); assert_ne!(n, 0); assert_eq!(ys.len(), n); let (ys_last, ys_init) = ys.split_last().unwrap(); let (out_last, out_init) = out[..n].split_last_mut().unwrap(); let mut p = xs[0].wrapping_mul(*ys_last); if n != 1 { let y = ys_init[0]; let (xs_last, xs_init) = xs.split_last().unwrap(); let product = xs_last .wrapping_mul(y) .wrapping_add(limbs_mul_limb_to_out::(out_init, xs_init, y)); p.wrapping_add_assign(product); let m = n - 1; for i in 1..m { let y = ys_init[i]; let (xs_lo, xs_hi) = xs_init.split_at(m - i); let limb_p = xs_hi[0].wrapping_mul(y).wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(&mut out_init[i..], xs_lo, y), ); p.wrapping_add_assign(limb_p); } } *out_last = p; }} // TODO tune const SCALED_MUL_TOOM22_THRESHOLD: usize = MUL_TOOM22_THRESHOLD * 36 / (36 - 11); // TODO tune const SCALED_MUL_TOOM33_THRESHOLD: usize = MUL_TOOM33_THRESHOLD * 36 / (36 - 11); // TODO tune const SCALED_MUL_TOOM44_THRESHOLD: usize = MUL_TOOM44_THRESHOLD.saturating_mul(40) / (40 - 9); // TODO tune const SCALED_MUL_TOOM8H_THRESHOLD: usize = MUL_TOOM8H_THRESHOLD * 10 / 9; // TODO tune const MAYBE_RANGE_BASECASE_MUL_LOW: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || (MULLO_DC_THRESHOLD == 0 && MULLO_BASECASE_THRESHOLD < SCALED_MUL_TOOM22_THRESHOLD || MULLO_DC_THRESHOLD != 0 && MULLO_DC_THRESHOLD < SCALED_MUL_TOOM22_THRESHOLD); // TODO tune const MAYBE_RANGE_TOOM22_MUL_LOW: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || (MULLO_DC_THRESHOLD == 0 && MULLO_BASECASE_THRESHOLD < SCALED_MUL_TOOM33_THRESHOLD || MULLO_DC_THRESHOLD != 0 && MULLO_DC_THRESHOLD < SCALED_MUL_TOOM33_THRESHOLD); // We need fractional approximation of the value 0 < a <= 1/2 giving the minimum in the function k = // (1 - a) ^ e / (1 - 2 * a ^ e). const fn get_n_lo(n: usize) -> usize { if MAYBE_RANGE_BASECASE_MUL_LOW && n < SCALED_MUL_TOOM22_THRESHOLD { n >> 1 } else if MAYBE_RANGE_TOOM22_MUL_LOW && n < SCALED_MUL_TOOM33_THRESHOLD { n * 11 / 36 // n_lo ~= n * (1 - .694...) } else if n < SCALED_MUL_TOOM44_THRESHOLD { n * 9 / 40 // n_lo ~= n * (1 - .775...) } else if n < SCALED_MUL_TOOM8H_THRESHOLD { n * 7 / 39 // n_lo ~= n * (1 - .821...) } else { n / 10 // n_lo ~= n * (1 - .899...) [TOOM88] } } // See `limbs_mul_low_same_length_divide_and_conquer` documentation for more details. // // # Worst-case complexity // $T(n) = O(n^{\log_8 15}) \approx O(n^{1.302})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_mullo_n` from `mpn/generic/mullo_n.c`, GMP 6.2.1, where `rp == tp`. pub_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_mul_low_same_length_divide_and_conquer_shared_scratch( out: &mut [Limb], xs: &[Limb], ys: &[Limb], ) { let n = xs.len(); assert_eq!(ys.len(), n); assert!(n >= 2); let n_lo = get_n_lo(n); let n_hi = n - n_lo; // Split as x = x_1 * 2 ^ (n_hi * Limb::WIDTH) + x_0, y = y_1 * 2 ^ (n_hi * Limb::WIDTH) + y_0 let (xs_lo, xs_hi) = xs.split_at(n_hi); // x_0 * y_0 let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(n_hi)]; limbs_mul_same_length_to_out(out, xs_lo, &ys[..n_hi], &mut mul_scratch); let ys_lo = &ys[..n_lo]; let (out_lo, out_hi) = out.split_at_mut(n); // x_1 * y_0 * 2 ^ (n_hi * Limb::WIDTH) if n_lo < MULLO_BASECASE_THRESHOLD { limbs_mul_greater_to_out_basecase(out_hi, xs_hi, ys_lo); } else if n_lo < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(out_hi, xs_hi, ys_lo); } else { limbs_mul_low_same_length_divide_and_conquer_shared_scratch(out_hi, xs_hi, ys_lo); } limbs_slice_add_same_length_in_place_left(&mut out_lo[n_hi..], &out_hi[..n_lo]); let xs_lo = &xs[..n_lo]; let ys_hi = &ys[n_hi..]; // x_0 * y_1 * 2 ^ (n_hi * Limb::WIDTH) if n_lo < MULLO_BASECASE_THRESHOLD { limbs_mul_greater_to_out_basecase(out_hi, xs_lo, ys_hi); } else if n_lo < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(out_hi, xs_lo, ys_hi); } else { limbs_mul_low_same_length_divide_and_conquer_shared_scratch(out_hi, xs_lo, ys_hi); } limbs_slice_add_same_length_in_place_left(&mut out_lo[n_hi..], &out_hi[..n_lo]); }} // Compute the least significant half of the product {xs, n} * {ys, n}, or formally {rp, n} = {xs, // n} * {ys, n} mod (2 ^ `Limb::WIDTH * n`). // // Above the given threshold, the Divide and Conquer strategy is used. The operands are split in // two, and a full product plus two mul_low are used to obtain the final result. The more natural // strategy is to split in two halves, but this is far from optimal when a sub-quadratic // multiplication is used. // // Mulders suggests an unbalanced split in favour of the full product, split n = n_lo + n_hi, where // a * n = n_lo <= n_hi = (1 - a) * n; i.e. 0 < a <= 1/2. // // To compute the value of a, we assume that the cost of mul_lo for a given size ML(n) is a fraction // of the cost of a full product with same size M(n), and the cost M(n) = n ^ e for some exponent 1 // < e <= 2. Then we can write: // // ML(n) = 2 * ML(a * n) + M((1 - a) * n) => k * M(n) = 2 * k * M(n) * a ^ e + M(n) * (1 - a) ^ e // // Given a value for e, want to minimise the value of k, i.e. the function k = (1 - a) ^ e / (1 - 2 // * a ^ e). // // With e = 2, the exponent for schoolbook multiplication, the minimum is given by the values a = 1 // - a = 1/2. // // With e = log(3) / log(2), the exponent for Karatsuba (aka toom22), Mulders computes (1 - a) = // 0.694... and we approximate a with 11 / 36. // // Other possible approximations follow: // - e = log(5) / log(3) [Toom-3] -> a ~= 9/40 // - e = log(7) / log(4) [Toom-4] -> a ~= 7/39 // - e = log(11) / log(6) [Toom-6] -> a ~= 1/8 // - e = log(15) / log(8) [Toom-8] -> a ~= 1/10 // // The values above where obtained with the following trivial commands in the gp-pari shell: // // - fun(e,a)=(1-a)^e/(1-2*a^e) // - mul(a,b,c)={local(m,x,p);if(b-c<1/10000,(b+c)/2,m=1;x=b; // - forstep(p=c,b,(b-c)/8,if(fun(a,p)= 2); let n_lo = get_n_lo(n); let n_hi = n - n_lo; let (out_lo, out_hi) = out[..n].split_at_mut(n_hi); // Split as x = x_1 * 2 ^ (n_hi * Limb::WIDTH) + x_0, y = y_1 * 2 ^ (n_hi * Limb::WIDTH) + y_0 let (xs_lo, xs_hi) = xs.split_at(n_hi); // x_0 * y_0 let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(n_hi)]; limbs_mul_same_length_to_out(scratch, xs_lo, &ys[..n_hi], &mut mul_scratch); out_lo.copy_from_slice(&scratch[..n_hi]); let ys_lo = &ys[..n_lo]; let (scratch_lo, scratch_hi) = scratch.split_at_mut(n); // x_1 * y_0 * 2 ^ (n_hi * Limb::WIDTH) if n_lo < MULLO_BASECASE_THRESHOLD { limbs_mul_greater_to_out_basecase(scratch_hi, xs_hi, ys_lo); } else if n_lo < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(scratch_hi, xs_hi, ys_lo); } else { limbs_mul_low_same_length_divide_and_conquer_shared_scratch(scratch_hi, xs_hi, ys_lo); } limbs_add_same_length_to_out(out_hi, &scratch_lo[n_hi..], &scratch_hi[..n_lo]); let xs_lo = &xs[..n_lo]; let ys_hi = &ys[n_hi..]; // x_0 * y_1 * 2 ^ (n_hi * Limb::WIDTH) if n_lo < MULLO_BASECASE_THRESHOLD { limbs_mul_greater_to_out_basecase(scratch_hi, xs_lo, ys_hi); } else if n_lo < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(scratch_hi, xs_lo, ys_hi); } else { limbs_mul_low_same_length_divide_and_conquer_shared_scratch(scratch_hi, xs_lo, ys_hi); } limbs_slice_add_same_length_in_place_left(out_hi, &scratch_hi[..n_lo]); }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_mullo_n_itch` from `mpn/generic/mullo_n.c`, GMP 6.2.1. pub_const_test! {limbs_mul_low_same_length_divide_and_conquer_scratch_len(n: usize) -> usize { n << 1 }} // TODO tune const MULLO_BASECASE_THRESHOLD_LIMIT: usize = MULLO_BASECASE_THRESHOLD; pub_test! {limbs_mul_low_same_length_large( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let n = xs.len(); // For really large operands, use plain limbs_mul_same_length_to_out but throw away the upper n // limbs of the result. let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(n)]; limbs_mul_same_length_to_out(scratch, xs, ys, &mut mul_scratch); out.copy_from_slice(&scratch[..n]); }} // Multiply two n-limb numbers and return the lowest n limbs of their products. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$, assuming $k = O(\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mullo_n` from `mpn/generic/mullo_n.c`, GMP 6.2.1. pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_mul_low_same_length(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let n = xs.len(); assert_eq!(ys.len(), n); assert!(n >= 1); let out = &mut out[..n]; if n < MULLO_BASECASE_THRESHOLD { // Allocate workspace of fixed size on stack: fast! let scratch = &mut [0; MULLO_BASECASE_THRESHOLD_LIMIT]; limbs_mul_greater_to_out_basecase(scratch, xs, ys); out.copy_from_slice(&scratch[..n]); } else if n < MULLO_DC_THRESHOLD { limbs_mul_low_same_length_basecase(out, xs, ys); } else { let mut scratch = vec![0; limbs_mul_low_same_length_divide_and_conquer_scratch_len(n)]; if n < MULLO_MUL_N_THRESHOLD { limbs_mul_low_same_length_divide_and_conquer(out, xs, ys, &mut scratch); } else { limbs_mul_low_same_length_large(out, xs, ys, &mut scratch); } } }} // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_mullo_basecase` from `mpn/generic/mullo_basecase.c`, GMP 6.2.1, // `MULLO_VARIANT == 1`. pub_crate_test! {limbs_mul_low_same_length_basecase_alt( out: &mut [Limb], xs: &[Limb], ys: &[Limb] ) { let n = xs.len(); assert_ne!(n, 0); assert_eq!(ys.len(), n); let out = &mut out[..n]; limbs_mul_limb_to_out::(out, xs, ys[0]); for i in 1..n { limbs_slice_add_mul_limb_same_length_in_place_left(&mut out[i..], &xs[..n - i], ys[i]); } }} ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/mul_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_bc_mulmod_bnm1`, `mpn_bc_mulmod_bnp1`, `mpn_mulmod_bnm1`, and // `mpn_mulmod_bnm1_next_size` contributed to the GNU project by Niels Möller, Torbjörn // Granlund and Marco Bodrato. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_same_length_to_out, limbs_add_to_out, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, }; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_to_out, limbs_sub_same_length_with_borrow_in_in_place_right, }; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{Parity, RoundToMultipleOfPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::slice_test_zero; // TODO tune pub(crate) const MULMOD_BNM1_THRESHOLD: usize = 13; // # Worst-case complexity // Constant time and additional memory. pub(crate) fn limbs_mul_mod_base_pow_n_minus_1_next_size_helper( n: usize, low_threshold: usize, ) -> usize { if n < low_threshold { n } else if n <= (low_threshold - 1) << 2 { n.round_to_multiple_of_power_of_2(1, Ceiling).0 } else if n <= (low_threshold - 1) << 3 { n.round_to_multiple_of_power_of_2(2, Ceiling).0 } else { n.round_to_multiple_of_power_of_2(3, Ceiling).0 } } // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$. // // This is equivalent to `mpn_mulmod_bnm1_next_size` from `mpn/generic/mulmod_bnm1.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_mod_base_pow_n_minus_1_next_size(n: usize) -> usize { limbs_mul_mod_base_pow_n_minus_1_next_size_helper( n, MULMOD_BNM1_THRESHOLD, ) }} // # Worst-case complexity // Constant time and additional memory. // // The result is $O(n)$. // // This is equivalent to `mpn_mulmod_bnm1_itch` from `gmp-impl.h`, GMP 6.2.1. pub(crate) const fn limbs_mul_mod_base_pow_n_minus_1_scratch_len( n: usize, xs_len: usize, ys_len: usize, ) -> usize { let half_n = n >> 1; if xs_len > half_n { if ys_len > half_n { (n + 2) << 1 } else { n + 4 + half_n } } else { n + 4 } } // Interpreting two equal-length, nonempty slices of `Limb`s as the limbs (in ascending order) of // two `Natural`s, multiplies the `Natural`s mod `2 ^ (Limb::WIDTH * n) - 1`, where n is the length // of either slice. The result is semi-normalized: zero is represented as either 0 or `Limb::WIDTH ^ // n - 1`. The limbs of the result are written to `out`. `out` should have length at least n, and // `scratch` at least 2 * n. This is the basecase algorithm. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths, if `out` or `scratch` are too short, or if the // input slices are empty. // // This is equivalent to `mpn_bc_mulmod_bnm1` from `mpn/generic/mulmod_bnm1.c`, GMP 6.2.1. fn limbs_mul_mod_base_pow_n_minus_1_basecase( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let n = xs.len(); assert_ne!(n, 0); let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(n)]; limbs_mul_same_length_to_out(scratch, xs, ys, &mut mul_scratch); split_into_chunks_mut!(scratch, n, [scratch_lo, scratch_hi], _unused); if limbs_add_same_length_to_out(out, scratch_lo, scratch_hi) { // If carry == 1, then the value of out is at most B ^ n - 2, so there can be no overflow // when adding in the carry. limbs_slice_add_limb_in_place(&mut out[..n], 1); } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. pub(crate) fn limbs_mul_mod_base_pow_n_plus_1_basecase_helper(out: &mut [Limb], n: usize) { split_into_chunks_mut!(out, n, [out_0, out_1], out_2); assert_eq!(out_2[1], 0); let mut carry = out_2[0]; assert_ne!(carry, Limb::MAX); if limbs_sub_same_length_in_place_left(out_0, out_1) { carry += 1; } out_1[0] = 0; assert!(!limbs_slice_add_limb_in_place(&mut out[..=n], carry)); } // Interpreting the first n + 1 limbs of two slices of `Limb`s as the limbs (in ascending order) of // two `Natural`s, multiplies the `Natural`s mod `2 ^ (Limb::WIDTH * n) + 1`. The limbs of the // result are written to `out`, which should have length at least 2 * n + 2. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // # Panics // Panics if `xs`, `ys`, or `out` are too short, or if n is zero. // // This is equivalent to `mpn_bc_mulmod_bnp1` from `mpn/generic/mulmod_bnm1.c`, GMP 6.2.1, where `rp // == tp`. fn limbs_mul_mod_base_pow_n_plus_1_basecase(out: &mut [Limb], xs: &[Limb], ys: &[Limb], n: usize) { assert_ne!(0, n); let m = n + 1; let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(m)]; limbs_mul_same_length_to_out(out, &xs[..m], &ys[..m], &mut mul_scratch); limbs_mul_mod_base_pow_n_plus_1_basecase_helper(out, n); } // Interpreting two nonempty slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, // multiplies the `Natural`s mod `2 ^ (Limb::WIDTH * n) - 1`. The limbs of the result are written to // `out`. // // The result is expected to be 0 if and only if one of the operands already is. Otherwise the class // 0 mod `(Limb::WIDTH ^ n - 1)` is represented by `2 ^ (n * Limb::WIDTH) - 1`. This should not be a // problem if `limbs_mul_mod_base_pow_n_minus_1` is used to combine results and obtain a natural // number when one knows in advance that the final value is less than `2 ^ (n * Limb::WIDTH) - 1`. // Moreover it should not be a problem if `limbs_mul_mod_base_pow_n_minus_1` is used to compute the // full product with `xs.len() + ys.len() <= n`, because this condition implies `(2 ^ (Limb::WIDTH * // xs.len()) - 1)(2 ^ (Limb::WIDTH * ys.len()) - 1) < 2 ^ (Limb::WIDTH * n) - 1`. // // Requires 0 < `ys.len()` <= `xs.len()` <= n and an + `ys.len()` > n / 2. Scratch need: n + (need // for recursive call OR n + 4). This gives S(n) <= n + MAX (n + 4, S(n / 2)) <= 2 * n + 4 // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`, if `ys` is empty, is `xs` is longer than n, or if `out` or // `scratch` are too short. // // This is equivalent to `mpn_mulmod_bnm1` from `mpn/generic/mulmod_bnm1.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_mod_base_pow_n_minus_1( out: &mut [Limb], n: usize, xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert_ne!(0, ys_len); assert!(xs_len >= ys_len); assert!(xs_len <= n); let sum = xs_len + ys_len; if n < MULMOD_BNM1_THRESHOLD || n.odd() { if ys_len < n { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; if sum <= n { limbs_mul_greater_to_out(out, xs, ys, &mut mul_scratch); } else { limbs_mul_greater_to_out(scratch, xs, ys, &mut mul_scratch); if limbs_add_to_out(out, &scratch[..n], &scratch[n..sum]) { assert!(!limbs_slice_add_limb_in_place(&mut out[..n], 1)); } } } else { limbs_mul_mod_base_pow_n_minus_1_basecase(out, &xs[..n], ys, scratch); } } else { let half_n = n >> 1; // We need at least xs_len + ys_len >= half_n, to be able to fit one of the recursive // products at out. Requiring strict inequality makes the code slightly simpler. If desired, // we could avoid this restriction by initially halving n as long as n is even and xs_len + // ys_len <= n / 2. assert!(sum > half_n); // Compute xm = a * b mod (2 ^ (Limb::WIDTH * half_n) - 1), xp = a * b mod (2 ^ (Limb::WIDTH // * half_n) + 1), and Chinese-Remainder-Theorem together as x = -xp * 2 ^ (Limb::WIDTH * // half_n) + (2 ^ (Limb::WIDTH * half_n) + 1) * ((xp + xm) / 2 mod (2 ^ (Limb::WIDTH * // half_n) - 1)) let m = half_n + 1; if xs_len <= half_n { limbs_mul_mod_base_pow_n_minus_1(out, half_n, xs, ys, scratch); assert!(sum <= (half_n << 1) | 1); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; limbs_mul_greater_to_out(scratch, xs, ys, &mut mul_scratch); let mut limit = sum - half_n; assert!(limit <= half_n || scratch[half_n << 1] == 0); if limit > half_n { limit -= 1; } let carry = { let (scratch_lo, scratch_hi) = scratch.split_at_mut(half_n); limbs_sub_greater_in_place_left(scratch_lo, &scratch_hi[..limit]) }; scratch[half_n] = 0; if carry { assert!(!limbs_slice_add_limb_in_place(&mut scratch[..m], 1)); } } else { let (xs_0, xs_1) = xs.split_at(half_n); let carry = limbs_add_to_out(scratch, xs_0, xs_1); let (scratch_lo, scratch_hi) = scratch.split_at_mut(half_n); if carry { assert!(!limbs_slice_add_limb_in_place(scratch_lo, 1)); } if ys_len <= half_n { limbs_mul_mod_base_pow_n_minus_1(out, half_n, scratch_lo, ys, scratch_hi); let scratch_2 = &mut scratch[m << 1..3 * m]; let carry = limbs_sub_greater_to_out(scratch_2, xs_0, xs_1); *scratch_2.last_mut().unwrap() = 0; if carry { assert!(!limbs_slice_add_limb_in_place(scratch_2, 1)); } let a = half_n + usize::exact_from(*scratch_2.last_mut().unwrap()); let sum_2 = a + ys_len; assert!(sum_2 <= (half_n << 1) + 1); assert!(sum_2 > half_n); assert!(a >= ys_len); let (scratch_lo, scratch_hi) = scratch.split_at_mut(m << 1); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(a, ys_len)]; limbs_mul_greater_to_out(scratch_lo, &scratch_hi[..a], ys, &mut mul_scratch); let mut a = sum_2 - half_n; assert!(a <= half_n || scratch[half_n << 1] == 0); if a > half_n { a -= 1; } let carry = { let (scratch_lo, scratch_hi) = scratch.split_at_mut(half_n); limbs_sub_greater_in_place_left(scratch_lo, &scratch_hi[..a]) }; scratch[half_n] = 0; if carry { assert!(!limbs_slice_add_limb_in_place(&mut scratch[..m], 1)); } } else { let (ys_0, ys_1) = ys.split_at(half_n); let carry = limbs_add_to_out(scratch_hi, ys_0, ys_1); let (scratch_1, scratch_2) = scratch_hi.split_at_mut(half_n); if carry { assert!(!limbs_slice_add_limb_in_place(scratch_1, 1)); } limbs_mul_mod_base_pow_n_minus_1(out, half_n, scratch_lo, scratch_1, scratch_2); let (scratch_2, scratch_3) = scratch[m << 1..].split_at_mut(m); let carry = limbs_sub_greater_to_out(scratch_2, xs_0, xs_1); *scratch_2.last_mut().unwrap() = 0; if carry { assert!(!limbs_slice_add_limb_in_place(scratch_2, 1)); } let scratch_3 = &mut scratch_3[..m]; let (ys_0, ys_1) = ys.split_at(half_n); let carry = limbs_sub_greater_to_out(scratch_3, ys_0, ys_1); *scratch_3.last_mut().unwrap() = 0; if carry { assert!(!limbs_slice_add_limb_in_place(scratch_3, 1)); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(m << 1); limbs_mul_mod_base_pow_n_plus_1_basecase( scratch_lo, scratch_hi, &scratch_hi[m..], half_n, ); } } // Here the Chinese Remainder Theorem recomposition begins. // // let xm = (scratch + xm) / 2 = (scratch + xm) * 2 ^ (Limb::WIDTH * half_n) / 2 mod (2 ^ // (Limb::WIDTH * half_n) - 1). Division by 2 is a bitwise rotation. // // Assumes scratch normalised mod (2 ^ (Limb::WIDTH * half_n) + 1). // // The residue class 0 is represented by [2 ^ (Limb::WIDTH * half_n) - 1]; except when both // inputs are zero. // // scratch[half_n] == 1 implies slice_test_zero(scratch[..half_n]). let mut carry = scratch[half_n]; let (out_lo, out_hi) = out.split_at_mut(half_n); if limbs_slice_add_same_length_in_place_left(out_lo, &scratch[..half_n]) { carry += 1; } if out_lo[0].odd() { carry += 1; } limbs_slice_shr_in_place(out_lo, 1); let out_lo_last = out_lo.last_mut().unwrap(); assert!(!out_lo_last.get_highest_bit()); match carry { 1 => out_lo_last.set_bit(Limb::WIDTH - 1), 2 => { assert!(!out_lo_last.get_highest_bit()); assert!(!limbs_slice_add_limb_in_place(out_lo, 1)); } _ => assert_eq!(carry, 0), } // Compute the highest half: ([(scratch + xm) / 2 mod (2 ^ (Limb::WIDTH * half_n) - 1)] - // scratch) * 2 ^ (Limb::WIDTH * half_n) if sum < n { let a = sum - half_n; // Note that in this case, the only way the result can equal zero mod 2 ^ (Limb::WIDTH // * n) - 1 is if one of the inputs is zero, and then the output of both the recursive // calls and this CRT reconstruction is zero, not 2 ^ (Limb::WIDTH * n) - 1. Which is // good, since the latter representation doesn't fit in the output area. let borrow = limbs_sub_same_length_to_out(out_hi, &out_lo[..a], &scratch[..a]); let mut carry = scratch[half_n]; let scratch = &mut scratch[..n - half_n]; if limbs_sub_same_length_with_borrow_in_in_place_right( &out[a..n - half_n], &mut scratch[a..], borrow, ) { carry += 1; } assert!(sum == n - 1 || slice_test_zero(&scratch[a + 1..])); assert_eq!( scratch[a], Limb::from(limbs_sub_limb_in_place(&mut out[..sum], carry)) ); } else { let mut carry = scratch[half_n]; if limbs_sub_same_length_to_out(out_hi, out_lo, &scratch[..half_n]) { carry += 1; } // carry == 1 only if &scratch[..half_n + 1] is not zero, i.e. out[..half_n] is not // zero. The decrement will affect _at most_ the lowest half_n limbs. assert!(!limbs_sub_limb_in_place(&mut out[..half_n << 1], carry)); } } }} ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/poly_eval.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_toom_eval_dgr3_pm2`, `mpn_toom_eval_dgr3_pm1`, `mpn_toom_eval_pm1`, and // `mpn_toom_eval_pm2exp` contributed to the GNU project by Niels Möller. // // `DO_addlsh2` and `mpn_toom_eval_pm2` contributed to the GNU project by Niels Möller and // Marco Bodrato. // // `DO_mpn_addlsh_n` and `mpn_toom_eval_pm2rexp` contributed to the GNU project by Marco // Bodrato. // // Copyright © 2009 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_to_out, limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::sub::limbs_sub_same_length_to_out; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::Limb; use core::cmp::Ordering::*; use itertools::Itertools; use malachite_base::num::arithmetic::traits::{Parity, WrappingAddAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::NotAssign; // Evaluate a degree-3 polynomial in +1 and -1, where each coefficient has width `n` limbs, except // the last, which has width `n_high` limbs. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_eval_dgr3_pm1` in `mpn/generic/toom_eval_dgr3_pm1.c`, GMP 6.2.1, // where `s` is omitted from the inputs because it can be determined from `ap` and `n`. pub(crate) fn limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1( v_1: &mut [Limb], v_neg_1: &mut [Limb], poly: &[Limb], n: usize, scratch: &mut [Limb], ) -> bool { assert_eq!(v_1.len(), n + 1); assert_eq!(scratch.len(), n + 1); split_into_chunks!(poly, n, [poly_0, poly_1, poly_2], poly_3); assert!(poly_3.len() <= n); v_1[n] = Limb::from(limbs_add_same_length_to_out(v_1, poly_0, poly_2)); scratch[n] = Limb::from(limbs_add_to_out(scratch, poly_1, poly_3)); let v_neg_1_neg = limbs_cmp_same_length(v_1, scratch) == Less; if v_neg_1_neg { limbs_sub_same_length_to_out(v_neg_1, scratch, v_1); } else { limbs_sub_same_length_to_out(v_neg_1, v_1, scratch); } limbs_slice_add_same_length_in_place_left(v_1, scratch); assert!(v_1[n] <= 3); assert!(v_neg_1[n] <= 1); v_neg_1_neg } // Evaluate a degree-3 polynomial in +2 and -2, where each coefficient has width `n` limbs, except // the last, which has width `n_high` limbs. // // Needs n + 1 limbs of temporary storage. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_eval_dgr3_pm2` from `mpn/generic/toom_eval_dg3_pm2.c`, GMP 6.2.1, // where `s` is omitted from the inputs because it can be determined from `ap` and `n`. pub(crate) fn limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2( v_2: &mut [Limb], v_neg_2: &mut [Limb], poly: &[Limb], n: usize, scratch: &mut [Limb], ) -> bool { split_into_chunks!(poly, n, [poly_0, poly_1, poly_2], poly_3); let n_high = poly_3.len(); assert!(n_high <= n); assert_eq!(v_2.len(), n + 1); let (scratch_last, scratch_init) = scratch.split_last_mut().unwrap(); assert_eq!(scratch_init.len(), n); // scratch <- (poly_0 + 4 * poly_2) +/- (2 * poly_1 + 8 * poly_3) v_2[n] = limbs_shl_to_out(scratch_init, poly_2, 2); if limbs_add_same_length_to_out(v_2, scratch_init, poly_0) { v_2[n] += 1; } if n_high < n { scratch_init[n_high] = limbs_shl_to_out(scratch_init, poly_3, 2); *scratch_last = Limb::from(limbs_add_to_out_aliased(scratch_init, n_high + 1, poly_1)); } else { *scratch_last = limbs_shl_to_out(scratch_init, poly_3, 2); if limbs_slice_add_same_length_in_place_left(scratch_init, poly_1) { *scratch_last += 1; } } limbs_slice_shl_in_place(scratch, 1); let v_neg_2_neg = limbs_cmp_same_length(v_2, scratch) == Less; if v_neg_2_neg { limbs_sub_same_length_to_out(v_neg_2, scratch, v_2); } else { limbs_sub_same_length_to_out(v_neg_2, v_2, scratch); } limbs_slice_add_same_length_in_place_left(v_2, scratch); assert!(v_2[n] < 15); assert!(v_neg_2[n] < 10); v_neg_2_neg } // Evaluates a polynomial of degree 3 < `degree` < `Limb::WIDTH`, in the points +1 and -1, where // each coefficient has width `n` limbs, except the last, which has width `n_high` limbs. // // # Worst-case complexity // $T(m) = O(m)$ // // $M(m) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $m$ is `n * degree`. // // This is equivalent to `mpn_toom_eval_pm1` from `mpn/generic/toom_eval_pm1.c`, GMP 6.2.1, where // `hn` is omitted from the inputs because it can be determined from `xp` and `n`. pub(crate) fn limbs_mul_toom_evaluate_poly_in_1_and_neg_1( v_1: &mut [Limb], v_neg_1: &mut [Limb], degree: usize, poly: &[Limb], n: usize, scratch: &mut [Limb], ) -> bool { assert!(degree > 3); assert_eq!(v_1.len(), n + 1); assert_eq!(scratch.len(), n + 1); // The degree `degree` is also the number of full-size coefficients, so that the last // coefficient, of size `n_high`, starts at `poly[degree * n..]`. let coefficients = poly.chunks(n).collect_vec(); assert_eq!(coefficients.len(), degree + 1); // The degree `degree` is also the number of full-size coefficients, so that the last // coefficient, of size `n_high`, starts at poly + degree * n. v_1[n] = Limb::from(limbs_add_same_length_to_out( v_1, coefficients[0], coefficients[2], )); let mut i = 4; while i < degree { assert!(!limbs_slice_add_greater_in_place_left(v_1, coefficients[i])); i += 2; } scratch[n] = Limb::from(limbs_add_same_length_to_out( scratch, coefficients[1], coefficients[3], )); let mut i = 5; while i < degree { assert!(!limbs_slice_add_greater_in_place_left( scratch, coefficients[i], )); i += 2; } assert!(!limbs_slice_add_greater_in_place_left( if degree.even() { v_1 } else { scratch }, coefficients[degree], )); let v_neg_1_neg = limbs_cmp_same_length(v_1, scratch) == Less; if v_neg_1_neg { limbs_sub_same_length_to_out(v_neg_1, scratch, v_1); } else { limbs_sub_same_length_to_out(v_neg_1, v_1, scratch); } limbs_slice_add_same_length_in_place_left(v_1, scratch); let degree = Limb::exact_from(degree); assert!(v_1[n] <= degree); assert!(v_neg_1[n] <= (degree >> 1) + 1); v_neg_1_neg } // Given a `Natural` whose highest limb is `carry` and remaining limbs are `xs`, multiplies the // `Natural` by 4 and adds the `Natural` whose limbs are `ys`. The highest limb of the result is // written back to `carry` and the remaining limbs are written to `out`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `DO_addlsh2` from `mpn/generic/toom_eval_pm2.c`, GMP 6.2.1, with `d == // out`, `a == xs`, and `b == ys`. fn shl_2_and_add_with_carry_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb], carry: &mut Limb) { *carry <<= 2; *carry += limbs_shl_to_out(out, xs, 2); if limbs_slice_add_same_length_in_place_left(&mut out[..ys.len()], ys) { *carry += 1; } } // Given a `Natural` whose highest limb is `carry` and remaining limbs are `xs`, multiplies the // `Natural` by 4 and adds the `Natural` whose limbs are `ys`. The highest limb of the result is // written back to `carry` and the remaining limbs are written to `xs`. `xs` and `ys` must have the // same length. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // This is equivalent to `DO_addlsh2` from `mpn/generic/toom_eval_pm2.c`, GMP 6.2.1, with `d == b == // ys` and `a == xs`. fn shl_2_and_add_with_carry_in_place_left(xs: &mut [Limb], ys: &[Limb], carry: &mut Limb) { *carry <<= 2; *carry += limbs_slice_shl_in_place(xs, 2); if limbs_slice_add_same_length_in_place_left(xs, ys) { *carry += 1; } } // Evaluates a polynomial of degree 3 < `degree` < `Limb::WIDTH`, in the points +2 and -2, where // each coefficient has width `n` limbs, except the last, which has width `n_high` limbs. // // # Worst-case complexity // $T(m) = O(m)$ // // $M(m) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $m$ is `n * degree`. // // This is equivalent to `mpn_toom_eval_pm2` from `mpn/generic/toom_eval_pm2.c`, GMP 6.2.1, where // `hn` is omitted from the inputs because it can be determined from `xp` and `n`. pub(crate) fn limbs_mul_toom_evaluate_poly_in_2_and_neg_2( v_2: &mut [Limb], v_neg_2: &mut [Limb], degree: usize, poly: &[Limb], n: usize, scratch: &mut [Limb], ) -> bool { assert!(degree >= 3); assert!(degree < usize::wrapping_from(Limb::WIDTH)); assert_eq!(v_2.len(), n + 1); assert_eq!(scratch.len(), n + 1); // The degree `degree` is also the number of full-size coefficients, so that the last // coefficient, of size `n_high`, starts at `poly[degree * n..]`. let coefficients = poly.chunks(n).collect_vec(); assert_eq!(coefficients.len(), degree + 1); let n_high = coefficients[degree].len(); let (v_2_last, v_2_init) = v_2.split_last_mut().unwrap(); let mut carry = 0; shl_2_and_add_with_carry_to_out( v_2_init, coefficients[degree], &coefficients[degree - 2][..n_high], &mut carry, ); if n_high != n { carry = Limb::from(limbs_add_limb_to_out( &mut v_2_init[n_high..], &coefficients[degree - 2][n_high..], carry, )); } if degree >= 4 { let mut i = degree - 4; loop { shl_2_and_add_with_carry_in_place_left(v_2_init, coefficients[i], &mut carry); if i < 2 { break; } i -= 2; } } *v_2_last = carry; let (scratch_last, scratch_init) = scratch.split_last_mut().unwrap(); let mut carry = 0; shl_2_and_add_with_carry_to_out( scratch_init, coefficients[degree - 1], coefficients[degree - 3], &mut carry, ); if degree >= 5 { let mut i = degree - 5; loop { shl_2_and_add_with_carry_in_place_left(scratch_init, coefficients[i], &mut carry); if i < 2 { break; } i -= 2; } } *scratch_last = carry; assert_eq!( limbs_slice_shl_in_place(if degree.even() { scratch } else { v_2 }, 1), 0 ); let mut v_neg_2_neg = limbs_cmp_same_length(v_2, scratch) == Less; if v_neg_2_neg { limbs_sub_same_length_to_out(v_neg_2, scratch, v_2); } else { limbs_sub_same_length_to_out(v_neg_2, v_2, scratch); } if degree.odd() { v_neg_2_neg.not_assign(); } limbs_slice_add_same_length_in_place_left(v_2, scratch); let mut shift = 1 << (degree + 1); if shift != 0 { assert!(v_2[n] < shift - 1); } shift <<= 1; if shift != 0 { assert!(v_neg_2[n] < shift / 3); } v_neg_2_neg } // Evaluates a polynomial of degree `degree` > 2, in the points 2 ^ `shift` and -2 ^ `shift`, where // each coefficient has width `n` limbs, except the last, which has width `n_high` limbs. // // # Worst-case complexity // $T(m) = O(m)$ // // $M(m) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $m$ is `n * degree`. // // This is equivalent to `mpn_toom_eval_pm2exp` from `mpn/generic/toom_eval_pm2exp.c`, GMP 6.2.1, // where `hn` is omitted from the inputs because it can be determined from `xp` and `n`. pub(crate) fn limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow( v_2_pow: &mut [Limb], v_neg_2_pow: &mut [Limb], degree: usize, poly: &[Limb], n: usize, shift: u64, scratch: &mut [Limb], ) -> bool { assert!(degree >= 3); let degree_u64 = u64::exact_from(degree); assert!(shift * degree_u64 < Limb::WIDTH); assert_eq!(v_2_pow.len(), n + 1); assert_eq!(scratch.len(), n + 1); let coefficients = poly.chunks(n).collect_vec(); assert_eq!(coefficients.len(), degree + 1); let n_high = coefficients[degree].len(); let (scratch_last, scratch_init) = scratch.split_last_mut().unwrap(); let (v_2_pow_last, v_2_pow_init) = v_2_pow.split_last_mut().unwrap(); // The degree `degree` is also the number of full-size coefficients, so that the last // coefficient, of size `n_high`, starts at `poly + degree * n`. *v_2_pow_last = limbs_shl_to_out(scratch_init, coefficients[2], shift << 1); if limbs_add_same_length_to_out(v_2_pow_init, coefficients[0], scratch_init) { v_2_pow_last.wrapping_add_assign(1); } let mut i = 4; let mut local_shift = shift << 2; while i < degree { v_2_pow_last.wrapping_add_assign(limbs_shl_to_out( scratch_init, coefficients[i], local_shift, )); if limbs_slice_add_same_length_in_place_left(v_2_pow_init, scratch_init) { v_2_pow_last.wrapping_add_assign(1); } i += 2; local_shift += shift << 1; } *scratch_last = limbs_shl_to_out(scratch_init, coefficients[1], shift); let mut i = 3; let mut local_shift = shift * 3; while i < degree { *scratch_last += limbs_shl_to_out(v_neg_2_pow, coefficients[i], local_shift); if limbs_slice_add_same_length_in_place_left(scratch_init, &v_neg_2_pow[..n]) { scratch_last.wrapping_add_assign(1); } i += 2; local_shift += shift << 1; } v_neg_2_pow[n_high] = limbs_shl_to_out(v_neg_2_pow, coefficients[degree], degree_u64 * shift); limbs_slice_add_greater_in_place_left( if degree.even() { v_2_pow } else { scratch }, &v_neg_2_pow[..=n_high], ); let v_neg_2_pow_neg = limbs_cmp_same_length(v_2_pow, scratch) == Less; if v_neg_2_pow_neg { limbs_sub_same_length_to_out(v_neg_2_pow, scratch, v_2_pow); } else { limbs_sub_same_length_to_out(v_neg_2_pow, v_2_pow, scratch); } limbs_slice_add_same_length_in_place_left(v_2_pow, scratch); v_neg_2_pow_neg } // Given a `Natural` whose limbs are `ys`, multiplies the `Natural` by `2 ^ shift` and adds the // `Natural` whose limbs are the lowest `ys.len()` limbs of `xs`, writing the lowest `ys.len()` // limbs of the result to those limbs, and returning the highest limb as a carry. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // This is equivalent to `DO_mpn_addlsh_n` from `mpn/generic/toom_eval_pm2rexp.c`, GMP 6.2.1. pub(crate) fn limbs_shl_and_add_same_length_in_place_left( xs: &mut [Limb], ys: &[Limb], shift: u64, scratch: &mut [Limb], ) -> Limb { let n = ys.len(); let scratch = &mut scratch[..n]; let mut carry = limbs_shl_to_out(scratch, ys, shift); if limbs_slice_add_same_length_in_place_left(&mut xs[..n], scratch) { carry.wrapping_add_assign(1); } carry } // Evaluates a polynomial of degree `degree` > 2, in the points 2 ^ -`shift` and -2 ^ -`shift`, // where each coefficient has width `n` limbs, except the last, which has width `n_high` limbs. // // # Worst-case complexity // $T(m) = O(m)$ // // $M(m) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $m$ is `n * degree`. // // This is equivalent to `mpn_toom_eval_pm2rexp` from `mpn/generic/toom_eval_pm2rexp.c`, GMP 6.2.1, // where `t` is omitted from the inputs because it can be determined from `ap` and `n`. pub(crate) fn limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v_2_pow_neg: &mut [Limb], v_neg_2_pow_neg: &mut [Limb], degree: usize, poly: &[Limb], n: usize, shift: u64, scratch: &mut [Limb], ) -> bool { assert_ne!(shift, 0); // or `limbs_mul_toom_evaluate_poly_in_1_and_neg_1` should be used assert!(degree > 1); let degree_u64 = u64::exact_from(degree); assert_eq!(v_2_pow_neg.len(), n + 1); assert_eq!(scratch.len(), n + 1); let coefficients = poly.chunks(n).collect_vec(); assert_eq!(coefficients.len(), degree + 1); v_2_pow_neg[n] = limbs_shl_to_out(v_2_pow_neg, coefficients[0], shift * degree_u64); scratch[n] = limbs_shl_to_out(scratch, coefficients[1], shift * (degree_u64 - 1)); if degree.even() { assert!(!limbs_slice_add_greater_in_place_left( v_2_pow_neg, coefficients[degree], )); } else { assert!(!limbs_slice_add_greater_in_place_left( scratch, coefficients[degree], )); let carry = limbs_shl_and_add_same_length_in_place_left( v_2_pow_neg, coefficients[degree - 1], shift, v_neg_2_pow_neg, ); v_2_pow_neg[n].wrapping_add_assign(carry); } let mut i = 2; let mut local_shift = shift * (degree_u64 - 2); while i < degree - 1 { let carry = limbs_shl_and_add_same_length_in_place_left( v_2_pow_neg, coefficients[i], local_shift, v_neg_2_pow_neg, ); v_2_pow_neg[n].wrapping_add_assign(carry); i += 1; local_shift -= shift; let carry = limbs_shl_and_add_same_length_in_place_left( scratch, coefficients[i], local_shift, v_neg_2_pow_neg, ); scratch[n].wrapping_add_assign(carry); i += 1; local_shift -= shift; } let v_2_pow_neg_neg = limbs_cmp_same_length(v_2_pow_neg, scratch) == Less; if v_2_pow_neg_neg { limbs_sub_same_length_to_out(v_neg_2_pow_neg, scratch, v_2_pow_neg); } else { limbs_sub_same_length_to_out(v_neg_2_pow_neg, v_2_pow_neg, scratch); } assert!(!limbs_slice_add_same_length_in_place_left( v_2_pow_neg, scratch, )); v_2_pow_neg_neg } ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/poly_interpolate.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `DO_mpn_sublsh_n`, `DO_mpn_subrsh`, `mpn_toom_interpolate_6pts`, // `mpn_toom_interpolate_8pts`, `mpn_toom_interpolate_12pts`, and `mpn_toom_interpolate_16pts` // contributed to the GNU project by Marco Bodrato. // // `mpn_toom_interpolate_5pts` and `mpn_toom_interpolate_7pts` contributed to the GNU project // by Robert Harley, with improvements by Paul Zimmermann and Marco Bodrato. // // Copyright © 2000-2003, 2005-2007, 2009, 2010, 2011, 2012, 2015, 2020 Free Software // Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div::limbs_div_divisor_of_limb_max_with_carry_in_place; use crate::natural::arithmetic::div_exact::{ limbs_div_exact_3_in_place, limbs_div_exact_limb_in_place, }; use crate::natural::arithmetic::mul::poly_eval::limbs_shl_and_add_same_length_in_place_left; use crate::natural::arithmetic::mul::toom::BIT_CORRECTION; use crate::natural::arithmetic::shl::limbs_shl_to_out; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_in_place_with_overlap, limbs_sub_same_length_to_out, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::platform::{ AORSMUL_FASTER_2AORSLSH, AORSMUL_FASTER_3AORSLSH, AORSMUL_FASTER_AORS_2AORSLSH, AORSMUL_FASTER_AORS_AORSLSH, Limb, }; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ DivisibleByPowerOf2, Parity, WrappingAddAssign, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_test_zero; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `k`. // // This is equivalent to `mpn_toom_interpolate_5pts` in `mpn/generic/toom_interpolate_5pts.c`, GMP // 6.2.1. pub(crate) fn limbs_mul_toom_interpolate_5_points( c: &mut [Limb], v_2: &mut [Limb], v_neg_1: &mut [Limb], k: usize, two_r: usize, v_neg_1_neg: bool, mut v_inf_0: Limb, ) { let two_k = k << 1; let two_k_plus_1 = two_k + 1; let four_k_plus_1 = two_k_plus_1 + two_k; assert_eq!(v_neg_1.len(), two_k_plus_1); assert!(two_r <= two_k); let v_1 = &c[two_k..four_k_plus_1]; // v_1 length: 2 * k + 1 let v_2 = &mut v_2[..two_k_plus_1]; // ``` // (1) v_2 <- v_2 - v_neg_1 < v_2 + |v_neg_1|, (16 8 4 2 1) - (1 -1 1 -1 1) = // thus 0 <= v_2 < 50 * B ^ (2 * k) < 2 ^ 6 * B ^ (2 * k) (15 9 3 3 0) // ``` if v_neg_1_neg { assert!(!limbs_slice_add_same_length_in_place_left(v_2, v_neg_1)); } else { assert!(!limbs_sub_same_length_in_place_left(v_2, v_neg_1)); } // ``` // {c,2k} {c + 2k,2k + 1} {c + 4k + 1,2r - 1} {t,2k + 1} {t + 2k + 1,2k + 1} {t + 4k + 2,2r} // v0 v_1 hi(v_inf) |v_neg_1| v_2-v_neg_1 EMPTY // v_2 <- v_2 / 3 // (5 3 1 1 0) // {c,2k} {c + 2k,2k + 1} {c + 4k + 1,2r - 1} {t,2k + 1} {t + 2k + 1,2k + 1} {t + 4k + 2,2r} // v0 v_1 hi(v_inf) |v_neg_1| (v_2-v_neg_1)/3 EMPTY // // (2) v_neg_1 <- tm1 := (v_1 - v_neg_1) / 2 [(1 1 1 1 1) - (1 -1 1 -1 1)] / 2 = // tm1 >= 0 (0 1 0 1 0) // ``` // No carry comes out from {v_1, two_k_plus_1} +/- {v_neg_1, two_k_plus_1}, and the division by // two is exact. If v_neg_1_neg the sign of v_neg_1 is negative limbs_div_exact_3_in_place(v_2); if v_neg_1_neg { assert!(!limbs_slice_add_same_length_in_place_left(v_neg_1, v_1)); } else { assert!(!limbs_sub_same_length_in_place_right(v_1, v_neg_1)); } assert_eq!(limbs_slice_shr_in_place(v_neg_1, 1), 0); // ``` // {c,2k} {c + 2k,2k + 1} {c + 4k + 1,2r - 1} {t,2k + 1} {t + 2k + 1,2k + 1} {t + 4k + 2,2r} // v0 v_1 hi(v_inf) tm1 (v_2-v_neg_1)/3 EMPTY // // (3) v_1 <- t1 := v_1 - v0 (1 1 1 1 1) - (0 0 0 0 1) = (1 1 1 1 0) // t1 >= 0 // ``` let (c_lo, v_1) = c.split_at_mut(two_k); if limbs_sub_same_length_in_place_left(&mut v_1[..two_k], c_lo) { v_1[two_k].wrapping_sub_assign(1); } let v_1 = &mut v_1[..two_k_plus_1]; // ``` // {c,2k} {c + 2k,2k + 1} {c + 4k + 1,2r - 1} {t,2k + 1} {t + 2k + 1,2k + 1} {t + 4k + 2,2r} // v0 v_1-v0 hi(v_inf) tm1 (v_2-v_neg_1)/3 EMPTY // // (4) v_2 <- t2 := ((v_2 - v_neg_1) / 3 - t1) / 2 = (v_2 - v_neg_1 - 3 * t1) / 6 // t2 >= 0 [(5 3 1 1 0) - (1 1 1 1 0)]/2 = (2 1 0 0 0) // ``` assert!(!limbs_sub_same_length_in_place_left(v_2, v_1)); assert_eq!(limbs_slice_shr_in_place(v_2, 1), 0); // ``` // {c,2k} {c + 2k,2k + 1} {c + 4k + 1,2r - 1} {t,2k + 1} {t + 2k + 1,2k + 1} {t + 4k + 2,2r} // v0 v_1 - v0 hi(v_inf) tm1 (v_2 - v_neg_1 - 3t1) / 6 EMPTY // // (5) v_1 <- t1 - tm1 (1 1 1 1 0) - (0 1 0 1 0) = (1 0 1 0 0) // result is v_1 >= 0 // ``` assert!(!limbs_sub_same_length_in_place_left(v_1, v_neg_1)); // We do not need to read the value in v_neg_1, so we add it in {c + k, ..} let (c_lo, c_hi) = c.split_at_mut(3 * k + 1); if limbs_slice_add_same_length_in_place_left(&mut c_lo[k..], v_neg_1) { // ``` // 2 * n - (3 * k + 1) = 2 * r + k - 1 // ``` // // Memory allocated for v_neg_1 is now free, it can be recycled assert!(!limbs_slice_add_limb_in_place( &mut c_hi[..two_r + k - 1], 1, )); } let v_inf = &mut c_hi[k - 1..two_r + k - 1]; // ``` // (6) v_2 <- v_2 - 2 * v_inf, (2 1 0 0 0) - 2 * (1 0 0 0 0) = (0 1 0 0 0) // ``` // // result is v_2 >= 0 let saved = v_inf[0]; // Remember v1's highest byte (will be overwritten). v_inf[0] = v_inf_0; // Set the right value for v_inf_0 // Overwrite unused v_neg_1 let mut carry = limbs_shl_to_out(v_neg_1, &v_inf[..two_r], 1); if limbs_sub_same_length_in_place_left(&mut v_2[..two_r], &v_neg_1[..two_r]) { carry += 1; } assert!(!limbs_sub_limb_in_place(&mut v_2[two_r..], carry)); // Current matrix is // ``` // [1 0 0 0 0; v_inf // 0 1 0 0 0; v_2 // 1 0 1 0 0; v1 // 0 1 0 1 0; v_neg_1 // 0 0 0 0 1] v0 // ``` // Some values already are in-place (we added v_neg_1 in the correct position) // ``` // | v_inf| v1 | v0 | // | v_neg_1 | // ``` // One still is in a separated area // ``` // | +v_2 | // ``` // We have to compute v1-=v_inf; v_neg_1 -= v_2, // ``` // | -v_inf| // | -v_2 | // ``` // Carefully reordering operations we can avoid to compute twice the sum of the high half of v_2 // plus the low half of v_inf. // // Add the high half of t2 in {v_inf} if two_r > k + 1 { // This is the expected flow let (c_lo, c_hi) = c[k << 2..].split_at_mut(k + 1); if limbs_slice_add_same_length_in_place_left(c_lo, &v_2[k..]) { // 2n-(5k+1) = 2r-k-1 assert!(!limbs_slice_add_limb_in_place( &mut c_hi[..two_r - k - 1], 1, )); } } else { // - triggered only by very unbalanced cases like (k+k+(k-2))x(k+k+1), should be handled by // toom32 // - two_r < k + 1 so k + two_r < two_k, the size of v_2 assert!(!limbs_slice_add_same_length_in_place_left( &mut c[k << 2..(k << 2) + two_r], &v_2[k..k + two_r], )); } split_into_chunks_mut!(c, k << 1, [_unused, v_1], v_inf); // - (7) v_1 <- v_1 - v_inf, (1 0 1 0 0) - (1 0 0 0 0) = (0 0 1 0 0) // - result is >= 0 // - Side effect: we also subtracted (high half) v_neg_1 -= v_2 // - v_inf is at most two_r long. let carry = limbs_sub_same_length_in_place_left(&mut v_1[..two_r], &v_inf[..two_r]); v_inf_0 = v_inf[0]; // Save again the right value for v_inf_0 v_inf[0] = saved; split_into_chunks_mut!(c, k, [_unused, c1], v1); let v1 = &mut v1[..two_k_plus_1]; if carry { assert!(!limbs_sub_limb_in_place(&mut v1[two_r..], 1)); // Treat the last bytes. } // - (8) v_neg_1 <- v_neg_1 - v_2 (0 1 0 1 0) - (0 1 0 0 0) = (0 0 0 1 0) // - Operate only on the low half. if limbs_sub_same_length_in_place_left(c1, &v_2[..k]) { assert!(!limbs_sub_limb_in_place(v1, 1)); } let (c3, v_inf) = c[3 * k..].split_at_mut(k); // - Beginning the final phase // - Most of the recomposition was done // - add t2 in {c + 3 * k, ...}, but only the low half if limbs_slice_add_same_length_in_place_left(c3, &v_2[..k]) { v_inf[0].wrapping_add_assign(1); assert!(v_inf[0] >= 1); // No carry } // Add v_inf_0, propagate carry. assert!(!limbs_slice_add_limb_in_place(&mut v_inf[..two_r], v_inf_0)); } // Interpolation for Toom-3.5, using the evaluation points infinity, 1, -1, 2, -2. More precisely, // we want to compute f(2 ^ (`Limb::WIDTH` * n)) for a polynomial f of degree 5, given the six // values // // ``` // w5 = f(0), // w4 = f(-1), // w3 = f(1) // w2 = f(-2), // w1 = f(2), // w0 = limit at infinity of f(x) / x^5, // ``` // // The result is stored in {out, 5 * n + n_high}. At entry, w5 is stored at {out, 2 * n}, w3 is // stored at {out + 2 * n, 2 * n + 1}, and w0 is stored at {out + 5 * n, n_high}. The other values // are 2 * n + 1 limbs each (with most significant limbs small). f(-1) and f(-2) may be negative; // signs are passed in. All intermediate results are positive. Inputs are destroyed. // // Interpolation sequence was taken from the paper: "Integer and Polynomial Multiplication: Towards // Optimal Toom-Cook Matrices". Some slight variations were introduced: adaptation to "gmp // instruction set", and a final saving of an operation by interlacing interpolation and // recomposition phases. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_interpolate_6pts` from `mpn/generic/toom_interpolate_6pts.c`, GMP // 6.2.1, but the argument `w0n == n_high` is moved to immediately after `n`. pub(crate) fn limbs_mul_toom_interpolate_6_points( out: &mut [Limb], n: usize, n_high: usize, w4_neg: bool, w4: &mut [Limb], w2_neg: bool, w2: &mut [Limb], w1: &mut [Limb], ) { assert_ne!(n, 0); let m = 2 * n + 1; assert_ne!(n_high, 0); assert!(n_high < m); assert_eq!(w1.len(), m); assert_eq!(w2.len(), m); assert_eq!(w4.len(), m); // w5 length: 2 * n // // Interpolate with sequence: // - w2 = (w1 - w2) >> 2 // - w1 = (w1 - w5) >> 1 // - w1 = (w1 - w2) >> 1 // - w4 = (w3 - w4) >> 1 // - w2 = (w2 - w4) / 3 // - w3 = w3 - w4 - w5 // - w1 = (w1 - w3) / 3 // // Last steps are mixed with recomposition: // - w2 = w2 - w0 << 2 // - w4 = w4 - w2 // - w3 = w3 - w1 // - w2 = w2 - w0 // // w2 = (w1 - w2) >> 2 let (w5, w3) = out[..=n << 2].split_at_mut(n << 1); if w2_neg { limbs_slice_add_same_length_in_place_left(w2, w1); } else { limbs_sub_same_length_in_place_right(w1, w2); } limbs_slice_shr_in_place(w2, 2); // w1 = (w1 - w5) >> 1 let (w1_last, w1_init) = w1.split_last_mut().unwrap(); if limbs_sub_same_length_in_place_left(w1_init, w5) { w1_last.wrapping_sub_assign(1); } limbs_slice_shr_in_place(w1, 1); // w1 = (w1 - w2) >> 1 limbs_sub_same_length_in_place_left(w1, w2); limbs_slice_shr_in_place(w1, 1); // w4 = (w3 - w4) >> 1 if w4_neg { limbs_slice_add_same_length_in_place_left(w4, w3); } else { limbs_sub_same_length_in_place_right(w3, w4); } limbs_slice_shr_in_place(w4, 1); // w2 = (w2 - w4) / 3 limbs_sub_same_length_in_place_left(w2, w4); limbs_div_exact_3_in_place(w2); // w3 = w3 - w4 - w5 limbs_sub_same_length_in_place_left(w3, w4); let (w3_last, w3_init) = w3.split_last_mut().unwrap(); if limbs_sub_same_length_in_place_left(w3_init, w5) { w3_last.wrapping_sub_assign(1); } // w1 = (w1 - w3) / 3 limbs_sub_same_length_in_place_left(w1, w3); limbs_div_exact_3_in_place(w1); // ``` // [1 0 0 0 0 0; // 0 1 0 0 0 0; // 1 0 1 0 0 0; // 0 1 0 1 0 0; // 1 0 1 0 1 0; // 0 0 0 0 0 1] // ``` // // out[] prior to operations: // ``` // |_H w0__|_L w0__|______||_H w3__|_L w3__|_H w5__|_L w5__| // ``` // // summation scheme for remaining operations: // ``` // |______________5|n_____4|n_____3|n_____2|n______|n______| out // |_H w0__|_L w0__|______||_H w3__|_L w3__|_H w5__|_L w5__| // || H w4 | L w4 | // || H w2 | L w2 | // || H w1 | L w1 | // ||-H w1 |-L w1 | // |-H w0 |-L w0 ||-H w2 |-L w2 | // ``` let out = &mut out[n..]; let (out_lo, out_hi) = out.split_at_mut(m); if limbs_slice_add_same_length_in_place_left(out_lo, w4) { assert!(!limbs_slice_add_limb_in_place(&mut out_hi[..n], 1)); } // ``` // w2 -= w0 << 2 // ``` // // {w4, 2 * n + 1} is now free and can be overwritten. let out_hi = &out[n << 2..]; let mut carry = limbs_shl_to_out(w4, &out_hi[..n_high], 2); let (w2_lo, w2_hi) = w2.split_at_mut(n_high); if limbs_sub_same_length_in_place_left(w2_lo, &w4[..n_high]) { carry += 1; } assert!(!limbs_sub_limb_in_place(w2_hi, carry)); // w4L = w4L - w2L let (w2_lo, w2_hi) = w2.split_at(n); let (out_lo, out) = out.split_at_mut(n); if limbs_sub_same_length_in_place_left(out_lo, w2_lo) { assert!(!limbs_sub_limb_in_place(&mut out[..m], 1)); } let (out_lo, out_hi) = out.split_at_mut(n << 1); let carry = Limb::from(limbs_slice_add_same_length_in_place_left( &mut out_lo[n..], w2_lo, )); // w3H = w3H + w2L let carry_1 = out_hi[0] + carry; // w1L + w2H let (w2_hi_last, w2_hi_init) = w2_hi.split_last().unwrap(); let mut carry = *w2_hi_last; let (w1_lo, w1_hi) = w1.split_at_mut(n); if limbs_add_same_length_to_out(out_hi, w1_lo, w2_hi_init) { carry += 1; } assert!(!limbs_slice_add_limb_in_place(w1_hi, carry)); // w0 = w0 + w1H let mut carry_2 = 0; let (w1_last, w1_init) = w1.split_last().unwrap(); let w1_init = &w1_init[n..]; let out_hi = &mut out[3 * n..]; if n_high > n { carry_2 = *w1_last; if limbs_slice_add_same_length_in_place_left(&mut out_hi[..n], w1_init) { carry_2.wrapping_add_assign(1); } } else if limbs_slice_add_same_length_in_place_left(&mut out_hi[..n_high], &w1_init[..n_high]) { carry_2 = 1; } // summation scheme for the next operation: // ``` // |...____5|n_____4|n_____3|n_____2|n______|n______| out // |...w0___|_w1_w2_|_H w3__|_L w3__|_H w5__|_L w5__| // ...-w0___|-w1_w2 | // ``` // // if (LIKELY(n_high > n)) the two operands below DO overlap! let out = &mut out[..3 * n + n_high]; let carry = limbs_sub_same_length_in_place_with_overlap(out, n << 1); let out_high = out.last_mut().unwrap(); let embankment = out_high.wrapping_sub(1); *out_high = 1; let out = &mut out[n..]; if n_high > n { if carry_1 > carry_2 { assert!(!limbs_slice_add_limb_in_place( &mut out[n..], carry_1 - carry_2, )); } else { assert!(!limbs_sub_limb_in_place(&mut out[n..], carry_2 - carry_1)); } if carry { assert!(!limbs_sub_limb_in_place(&mut out[n_high..], 1)); } assert!(!limbs_slice_add_limb_in_place(&mut out[3 * n..], carry_2)); } else { assert!(!limbs_slice_add_limb_in_place(&mut out[n..], carry_1)); if carry { carry_2.wrapping_add_assign(1); } assert!(!limbs_sub_limb_in_place(&mut out[n_high..], carry_2)); } out.last_mut().unwrap().wrapping_add_assign(embankment); } const WANT_ASSERT: bool = true; // Interpolation for toom4, using the evaluation points 0, infinity, 1, -1, 2, -2, 1 / 2. More // precisely, we want to compute f(2 ^ (Limb::WIDTH * n)) for a polynomial f of degree 6, given the // seven values // - w0 = f(0), // - w1 = f(-2), // - w2 = f(1), // - w3 = f(-1), // - w4 = f(2) // - w5 = 64 * f(1/2) // - w6 = limit at infinity of f(x) / x ^ 6, // // The result is 6 * n + n_high limbs. At entry, w0 is stored at {out, 2 * n}, w2 is stored at {out // + 2 * n, 2 * n + 1}, and w6 is stored at {out + 6 * n, n_high}. The other values are 2 * n + 1 // limbs each (with most significant limbs small). f(-1) and f(-1/2) may be negative, signs // determined by the flag bits. Inputs are destroyed. // // Needs 2 * n + 1 limbs of temporary storage. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_interpolate_7pts` from `mpn/generic/toom_interpolate_7pts.c`, GMP // 6.2.1, but the argument `w6n == n_high` is moved to immediately after `n`. pub(crate) fn limbs_mul_toom_interpolate_7_points( out: &mut [Limb], n: usize, n_high: usize, w1_neg: bool, w1: &mut [Limb], w3_neg: bool, w3: &mut [Limb], w4: &mut [Limb], w5: &mut [Limb], scratch: &mut [Limb], ) { let m = 2 * n + 1; assert_ne!(n_high, 0); assert!(n_high < m); assert_eq!(w1.len(), m); assert_eq!(w3.len(), m); assert_eq!(w4.len(), m); assert_eq!(w5.len(), m); let (w0, remainder) = out.split_at_mut(n << 1); let (w2, w6) = remainder.split_at_mut(n << 2); let w2 = &mut w2[..m]; let w6 = &mut w6[..n_high]; // Using formulas similar to Marco Bodrato's // // - w5 = w5 + w4 // - w1 = (w4 - w1) / 2 // - w4 = w4 - w0 // - w4 = (w4 - w1) / 4 - w6 * 16 // - w3 = (w2 - w3) / 2 // - w2 = w2 - w3 // // - w5 = w5 - w2 * 65 May be negative. // - w2 = w2 - w6 - w0 // - w5 = (w5 + w2 * 45) / 2 Now >= 0 again. // - w4 = (w4 - w2) / 3 // - w2 = w2 - w4 // // - w1 = w5 - w1 May be negative. // - w5 = (w5 - w3 * 8) / 9 // - w3 = w3 - w5 // - w1 = (w1 / 15 + w5) / 2 Now >= 0 again. // - w5 = w5 - w1 // // where w0 = f(0), w1 = f(-2), w2 = f(1), w3 = f(-1), w4 = f(2), w5 = f(1/2), w6 = f(infinity). // // Note that most intermediate results are positive; the ones that may be negative are // represented in two's complement. We must never shift right a value that may be negative, // since that would invalidate the sign bit. On the other hand, divexact by odd numbers works // fine with two's complement. limbs_slice_add_same_length_in_place_left(w5, w4); if w1_neg { limbs_slice_add_same_length_in_place_left(w1, w4); } else { limbs_sub_same_length_in_place_right(w4, w1); } assert!(w1[0].even()); limbs_slice_shr_in_place(w1, 1); limbs_sub_greater_in_place_left(w4, w0); limbs_sub_same_length_in_place_left(w4, w1); assert!(w4[0].divisible_by_power_of_2(2)); limbs_slice_shr_in_place(w4, 2); // w4 >= 0 scratch[n_high] = limbs_shl_to_out(scratch, w6, 4); limbs_sub_greater_in_place_left(w4, &scratch[..=n_high]); if w3_neg { limbs_slice_add_same_length_in_place_left(w3, w2); } else { limbs_sub_same_length_in_place_right(w2, w3); } assert!(w3[0].even()); limbs_slice_shr_in_place(w3, 1); limbs_sub_same_length_in_place_left(w2, w3); limbs_sub_mul_limb_same_length_in_place_left(w5, w2, 65); limbs_sub_greater_in_place_left(w2, w6); limbs_sub_greater_in_place_left(w2, w0); limbs_slice_add_mul_limb_same_length_in_place_left(w5, w2, 45); assert!(w5[0].even()); limbs_slice_shr_in_place(w5, 1); limbs_sub_same_length_in_place_left(w4, w2); limbs_div_exact_3_in_place(w4); limbs_sub_same_length_in_place_left(w2, w4); limbs_sub_same_length_in_place_right(w5, w1); limbs_shl_to_out(scratch, w3, 3); limbs_sub_same_length_in_place_left(w5, &scratch[..m]); limbs_div_exact_limb_in_place(w5, 9); limbs_sub_same_length_in_place_left(w3, w5); limbs_div_exact_limb_in_place(w1, 15); limbs_slice_add_same_length_in_place_left(w1, w5); assert!(w1[0].even()); limbs_slice_shr_in_place(w1, 1); // w1 >= 0 now limbs_sub_same_length_in_place_left(w5, w1); // These bounds are valid for the 4x4 polynomial product of toom44, and they are conservative // for toom53 and toom62. let two_n = n << 1; assert!(w1[two_n] < 2); assert!(w2[two_n] < 3); assert!(w3[two_n] < 4); assert!(w4[two_n] < 3); assert!(w5[two_n] < 2); // Addition chain. Note carries and the 2n'th limbs that need to be added in. // // Special care is needed for w2[2 * n] and the corresponding carry, since the "simple" way of // adding it all together would overwrite the limb at wp[2 * n] and out[4 * n] (same location) // with the sum of the high half of w3 and the low half of w4. // ``` // // 7 6 5 4 3 2 1 0 // | | | | | | | | | // ||w3 (2n+1)| // ||w4 (2n+1)| // ||w5 (2n+1)| ||w1 (2n+1)| // + |w6(n_high)| ||w2 (2n+1)| w0 (2n) | (share storage with r) // ----------------------------------------------- // r | | | | | | | | | // c7 c6 c5 c4 c3 Carries to propagate // ``` let (out_lo, out_hi) = out[n..].split_at_mut(m); if limbs_slice_add_same_length_in_place_left(out_lo, w1) { assert!(!limbs_slice_add_limb_in_place(&mut out_hi[..n], 1)); } split_into_chunks_mut!(&mut out[3 * n..], n, [out_3, out_4, out_5], remainder); let mut addend = out_4[0]; let (w3_lo, w3_hi) = w3.split_at_mut(n); if limbs_slice_add_same_length_in_place_left(out_3, w3_lo) { addend.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place(w3_hi, addend)); let (w3_hi_last, w3_hi_init) = w3_hi.split_last_mut().unwrap(); let mut addend = *w3_hi_last; let (w4_lo, w4_hi) = w4.split_at_mut(n); if limbs_add_same_length_to_out(out_4, w3_hi_init, w4_lo) { addend += 1; } assert!(!limbs_slice_add_limb_in_place(w4_hi, addend)); let (w4_last, w4_init) = w4_hi.split_last_mut().unwrap(); let mut addend = *w4_last; let (w5_lo, w5_hi) = w5.split_at_mut(n); if limbs_add_same_length_to_out(out_5, w4_init, w5_lo) { addend += 1; } assert!(!limbs_slice_add_limb_in_place(w5_hi, addend)); if n_high > n + 1 { assert!(!limbs_slice_add_greater_in_place_left(remainder, w5_hi)); } else { let (w5_hi_lo, w5_hi_hi) = w5_hi.split_at_mut(n_high); assert!(!limbs_slice_add_same_length_in_place_left( &mut remainder[..n_high], w5_hi_lo, )); if WANT_ASSERT && n + n_high < m { slice_test_zero(w5_hi_hi); } } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // This is equivalent to `DO_mpn_sublsh_n` from `mpn/generic/toom_interpolate_8pts.c`, GMP 6.2.1. pub_test! {limbs_shl_and_sub_same_length( xs: &mut [Limb], ys: &[Limb], shift: u64, scratch: &mut [Limb], ) -> Limb { let n = ys.len(); let mut carry = limbs_shl_to_out(scratch, ys, shift); if limbs_sub_same_length_in_place_left(&mut xs[..n], &scratch[..n]) { carry.wrapping_add_assign(1); } carry }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `DO_mpn_subrsh` from `mpn/generic/toom_interpolate_8pts.c`, GMP 6.2.1. fn limbs_shl_and_sub(xs: &mut [Limb], ys: &[Limb], shift: u64, scratch: &mut [Limb]) { let (ys_head, ys_tail) = ys.split_first().unwrap(); assert!(!limbs_sub_limb_in_place(xs, *ys_head >> shift)); let carry = limbs_shl_and_sub_same_length(xs, ys_tail, Limb::WIDTH - shift, scratch); assert!(!limbs_sub_limb_in_place(&mut xs[ys.len() - 1..], carry)); } fn limbs_shl_and_sub_special( xs_init: &mut [Limb], xs_last: &mut Limb, ys: &[Limb], shift: u64, scratch: &mut [Limb], ) { let (ys_head, ys_tail) = ys.split_first().unwrap(); if limbs_sub_limb_in_place(xs_init, *ys_head >> shift) { *xs_last = xs_last.checked_sub(1).unwrap(); } let carry = limbs_shl_and_sub_same_length(xs_init, ys_tail, Limb::WIDTH - shift, scratch); if limbs_sub_limb_in_place(&mut xs_init[ys_tail.len()..], carry) { *xs_last = xs_last.checked_sub(1).unwrap(); } } // Interpolation for Toom-4.5 (or Toom-4), using the evaluation points: infinity(4.5 only), 4, -4, // 2, -2, 1, -1, 0. More precisely, we want to compute f(2 ^ (`Limb::WIDTH` * n)) for a polynomial f // of degree 7 (or 6), given the 8 (rsp. 7) values: // // - r1 = limit at infinity of f(x) / x ^ 7, // - r2 = f(4), // - r3 = f(-4), // - r4 = f(2), // - r5 = f(-2), // - r6 = f(1), // - r7 = f(-1), // - r8 = f(0). // // All couples of the form f(n),f(-n) must be already mixed with // `limbs_toom_couple_handling`(f(n),..., f(-n), ...) // // The result is stored in {`out`, `s_plus_t` + 7 * n (or 6 * n)}. At entry, `r8` is stored at // {`out`, 2 * `n`}, and r5 is stored at {`out` + 3 * `n`, 3 * `n` + 1}. // // The other values are 2 * `n` + ... limbs each (with most significant limbs small). // // All intermediate results are positive. Inputs are destroyed. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_interpolate_8pts` from `mpn/generic/toom_interpolate_8pts.c`, GMP // 6.2.1, but the argument spt == `s_plus_t` is moved to immediately after `n`. pub(crate) fn limbs_mul_toom_interpolate_8_points( out: &mut [Limb], n: usize, s_plus_t: usize, r3: &mut [Limb], r7: &mut [Limb], scratch: &mut [Limb], ) { assert!(s_plus_t >= n); let m = 3 * n + 1; assert_eq!(r3.len(), m); assert_eq!(r7.len(), m); let (out, remainder) = out.split_at_mut(n << 1); let (out_2, remainder) = remainder.split_at_mut(n); let (r5, r1) = remainder.split_at_mut(n << 2); let r1 = &mut r1[..s_plus_t]; let r5_lo = &mut r5[..m]; // Interpolation limbs_shl_and_sub(&mut r3[n..], out, 4, scratch); let carry = limbs_shl_and_sub_same_length(r3, r1, 12, scratch); assert!(!limbs_sub_limb_in_place(&mut r3[s_plus_t..], carry)); limbs_shl_and_sub(&mut r5_lo[n..], out, 2, scratch); let carry = limbs_shl_and_sub_same_length(r5_lo, r1, 6, scratch); assert!(!limbs_sub_limb_in_place(&mut r5_lo[s_plus_t..], carry)); let (r7_last, r7_init) = r7.split_last_mut().unwrap(); if limbs_sub_same_length_in_place_left(&mut r7_init[n..], out) { r7_last.wrapping_sub_assign(1); } let (r7_lo, r7_hi) = r7.split_at_mut(s_plus_t); if limbs_sub_same_length_in_place_left(r7_lo, r1) { assert!(!limbs_sub_limb_in_place(r7_hi, 1)); } assert!(!limbs_sub_same_length_in_place_left(r3, r5_lo)); assert_eq!(limbs_slice_shr_in_place(r3, 2), 0); assert!(!limbs_sub_same_length_in_place_left(r5_lo, r7)); assert!(!limbs_sub_same_length_in_place_left(r3, r5_lo)); limbs_div_exact_limb_in_place(r3, 45); limbs_div_exact_3_in_place(r5_lo); assert_eq!(limbs_shl_and_sub_same_length(r5_lo, r3, 2, scratch), 0); // Last interpolation steps are mixed with recomposition. // // out[] prior to operations: // ``` // |_H r1|_L r1|____||_H r5|_M_r5|_L r5|_____|_H r8|_L r8|out // ``` // // summation scheme for remaining operations: // ``` // |____8|n___7|n___6|n___5|n___4|n___3|n___2|n____|n____|out // |_H r1|_L r1|____||_H*r5|_M r5|_L r5|_____|_H_r8|_L r8|out // ||_H r3|_M r3|_L*r3| // ||_H_r7|_M_r7|_L_r7| // ||-H r3|-M r3|-L*r3| // ||-H*r5|-M_r5|-L_r5| // Hr8+Lr7-Lr5 // ``` split_into_chunks_mut!(r5_lo, n, [r5_lo_0, r5_lo_1, r5_lo_2], r5_lo_3); let (r7_lo, r7) = r7.split_at_mut(n); let out = &mut out[n..]; let carry_1 = limbs_slice_add_same_length_in_place_left(out, r7_lo); let carry_2 = limbs_sub_same_length_in_place_left(out, r5_lo_0); if carry_1 && !carry_2 { assert!(!limbs_slice_add_limb_in_place(r7, 1)); } else if !carry_1 && carry_2 { assert!(!limbs_sub_limb_in_place(r7, 1)); } let (r7_lo, r7_hi) = r7.split_at_mut(n); // Mr7-Mr5 if limbs_sub_same_length_to_out(out_2, r7_lo, r5_lo_1) { assert!(!limbs_sub_limb_in_place(r7_hi, 1)); } // Hr5+Lr3 let (r3_lo, r3) = r3.split_at_mut(n); if limbs_slice_add_same_length_in_place_left(r5_lo_2, r3_lo) { r5_lo_3[0].wrapping_add_assign(1); } // Hr7+Lr5 let carry_1 = limbs_slice_add_same_length_in_place_left(&mut r5_lo[..=n], r7_hi); // Hr7-Hr5+Lr5-Lr3 let (r5_lo_lo, r5_lo_hi) = r5_lo.split_at_mut(n << 1); let carry_2 = limbs_sub_same_length_in_place_left(&mut r5_lo_lo[..=n], r5_lo_hi); if carry_1 && !carry_2 { assert!(!limbs_slice_add_limb_in_place(&mut r5_lo[n + 1..], 1)); } else if !carry_1 && carry_2 { assert!(!limbs_sub_limb_in_place(&mut r5_lo[n + 1..], 1)); } // Mr5-Mr3,Hr5-Hr3 assert!(!limbs_sub_same_length_in_place_left(&mut r5_lo[n..], r3)); let r5_3n = r5[3 * n]; let (r3_lo, r3) = r3.split_at_mut(n); if limbs_add_limb_to_out(&mut r5[3 * n..], r3_lo, r5_3n) { assert!(!limbs_slice_add_limb_in_place(r3, 1)); } let mut r3_n = r3[n]; let (r1_lo, r1_hi) = r1.split_at_mut(n); if limbs_slice_add_same_length_in_place_left(r1_lo, &r3[..n]) { r3_n.wrapping_add_assign(1); } if s_plus_t == n { assert_eq!(r3_n, 0); } else { assert!(!limbs_slice_add_limb_in_place(r1_hi, r3_n)); } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn limbs_div_255_in_place(xs: &mut [Limb]) { limbs_div_divisor_of_limb_max_with_carry_in_place(xs, Limb::MAX / 255, 0); } fn limbs_aors_mul_or_two_sh_aors_helper( xs: &mut [Limb], ys: &[Limb], s: Limb, sign: bool, s1: u64, sign1: bool, s2: u64, sign2: bool, scratch: &mut [Limb], ) { if AORSMUL_FASTER_2AORSLSH { if sign { limbs_slice_add_mul_limb_same_length_in_place_left(xs, ys, s); } else { limbs_sub_mul_limb_same_length_in_place_left(xs, ys, s); } } else { if sign1 { limbs_shl_and_add_same_length_in_place_left(xs, ys, s1, scratch); } else { limbs_shl_and_sub_same_length(xs, ys, s1, scratch); } if sign2 { limbs_shl_and_add_same_length_in_place_left(xs, ys, s2, scratch); } else { limbs_shl_and_sub_same_length(xs, ys, s2, scratch); } } } fn limbs_aors_mul_or_three_sh_aors_helper( xs: &mut [Limb], ys: &[Limb], s: Limb, s1: u64, s2: u64, s3: u64, no_carry: bool, scratch: &mut [Limb], ) { if AORSMUL_FASTER_3AORSLSH { let c = limbs_sub_mul_limb_same_length_in_place_left(xs, ys, s); if no_carry { assert_eq!(c, 0); } } else { let c = limbs_shl_and_sub_same_length(xs, ys, s1, scratch); if no_carry { assert_eq!(c, 0); } let c = limbs_shl_and_sub_same_length(xs, ys, s2, scratch); if no_carry { assert_eq!(c, 0); } let c = limbs_shl_and_sub_same_length(xs, ys, s3, scratch); if no_carry { assert_eq!(c, 0); } } } fn limbs_aors_mul_or_aors_and_two_sh_aors_helper( xs: &mut [Limb], ys: &[Limb], s: Limb, s1: u64, s2: u64, scratch: &mut [Limb], ) { if AORSMUL_FASTER_AORS_2AORSLSH { assert_eq!(limbs_sub_mul_limb_same_length_in_place_left(xs, ys, s), 0); } else { assert!(!limbs_sub_same_length_in_place_left(xs, ys)); assert_eq!( limbs_shl_and_add_same_length_in_place_left(xs, ys, s1, scratch), 0 ); assert_eq!(limbs_shl_and_sub_same_length(xs, ys, s2, scratch), 0); } } fn limbs_aors_mul_or_aors_and_sh_aors_helper( xs: &mut [Limb], ys: &[Limb], s: Limb, sign1: bool, s2: u64, scratch: &mut [Limb], ) { if AORSMUL_FASTER_AORS_AORSLSH { limbs_sub_mul_limb_same_length_in_place_left(xs, ys, s); } else { if sign1 { limbs_slice_add_same_length_in_place_left(xs, ys); } else { limbs_sub_same_length_in_place_left(xs, ys); } limbs_shl_and_sub_same_length(xs, ys, s2, scratch); } } // Interpolation for Toom-6.5 (or Toom-6), using the evaluation points: // - Infinity(6.5 only), +-4, +-2, +-1, +-1/4, +-1/2, 0. // // More precisely, we want to compute f(2 ^ (`Limb::WIDTH` * n)) for a polynomial f of degree 11 (or // 10), given the 12 (resp. 11) values: // // - r0 = limit at infinity of f(x) / x ^ 7, // - r1 = f(4),f(-4), // - r2 = f(2),f(-2), // - r3 = f(1),f(-1), // - r4 = f(1 / 4), f(-1 / 4), // - r5 = f(1 / 2), f(-1 / 2), // - r6 = f(0). // // All couples of the form f(n),f(-n) must be already mixed with `limbs_toom_couple_handling`(f(n), // ..., f(-n),...) // // - The result is stored in {out, s_plus_t + 7 * n (or 6 * n)}. // - At entry, r6 is stored at {out, 2 * n}, // - r4 is stored at {out + 3 * n, 3 * n + 1}. // - r2 is stored at {out + 7 * n, 3 * n + 1}. // - r0 is stored at {out + 11 * n, s_plus_t}. // // The other values are 3 * n + 1 limbs each (with most significant limbs small). // // Negative intermediate results are stored two-complemented. Inputs are destroyed. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_interpolate_12pts` from `mpn/generic/toom_interpolate_12pts.c`, // GMP 6.2.1. pub_crate_test! {limbs_mul_toom_interpolate_12_points<'a>( out: &mut [Limb], mut r1: &'a mut [Limb], r3: &mut [Limb], mut r5: &'a mut [Limb], n: usize, s_plus_t: usize, half: bool, mut scratch: &'a mut [Limb], ) { let m = 3 * n + 1; assert_eq!(r1.len(), m); assert_eq!(r3.len(), m); assert_eq!(r5.len(), m); let (out_lo, remainder) = out.split_at_mut(3 * n); let out_lo = &mut out_lo[..n << 1]; let (r4, r2) = remainder.split_at_mut(n << 2); let r4 = &mut r4[..m]; // Interpolation if half { let (r2, r0) = r2.split_at_mut(4 * n); let r0 = &mut r0[..s_plus_t]; let (r3_lo, r3_hi) = r3.split_at_mut(s_plus_t); if limbs_sub_same_length_in_place_left(r3_lo, r0) { assert!(!limbs_sub_limb_in_place(r3_hi, 1)); } let carry = limbs_shl_and_sub_same_length(r2, r0, 10, scratch); assert!(!limbs_sub_limb_in_place(&mut r2[s_plus_t..m], carry)); limbs_shl_and_sub(r5, r0, 2, scratch); let carry = limbs_shl_and_sub_same_length(r1, r0, 20, scratch); assert!(!limbs_sub_limb_in_place(&mut r1[s_plus_t..], carry)); limbs_shl_and_sub(r4, r0, 4, scratch); }; let r2 = &mut r2[..m]; let carry = limbs_shl_and_sub_same_length(&mut r4[n..], out_lo, 20, scratch); r4.last_mut().unwrap().wrapping_sub_assign(carry); limbs_shl_and_sub(&mut r1[n..], out_lo, 4, scratch); assert!(!limbs_add_same_length_to_out(scratch, r1, r4)); limbs_sub_same_length_in_place_left(r4, r1); // can be negative swap(&mut r1, &mut scratch); let r1 = &mut r1[..m]; let carry = limbs_shl_and_sub_same_length(&mut r5[n..], out_lo, 10, scratch); r5.last_mut().unwrap().wrapping_sub_assign(carry); limbs_shl_and_sub(&mut r2[n..], out_lo, 2, scratch); limbs_sub_same_length_to_out(scratch, r5, r2); // can be negative assert!(!limbs_slice_add_same_length_in_place_left(r2, r5)); swap(&mut r5, &mut scratch); let (r3_last, r3_init) = r3.split_last_mut().unwrap(); if limbs_sub_same_length_in_place_left(&mut r3_init[n..], out_lo) { r3_last.wrapping_sub_assign(1); } limbs_aors_mul_or_aors_and_sh_aors_helper(r4, r5, 257, false, 8, scratch); // A division by 2835 * 4 follows. Warning: the operand can be negative! limbs_div_exact_limb_in_place(r4, 2835 << 2); let r4_last = r4.last_mut().unwrap(); if r4_last.leading_zeros() < 3 { *r4_last |= Limb::MAX << (Limb::WIDTH - 2); } limbs_aors_mul_or_two_sh_aors_helper(r5, r4, 60, true, 2, false, 6, true, scratch); limbs_div_255_in_place(r5); assert_eq!(limbs_shl_and_sub_same_length(r2, r3, 5, scratch), 0); limbs_aors_mul_or_three_sh_aors_helper(r1, r2, 100, 6, 5, 2, true, scratch); assert_eq!(limbs_shl_and_sub_same_length(r1, r3, 9, scratch), 0); limbs_div_exact_limb_in_place(r1, 42525); limbs_aors_mul_or_aors_and_two_sh_aors_helper(r2, r1, 225, 5, 8, scratch); limbs_div_exact_limb_in_place(r2, 9 << 2); assert!(!limbs_sub_same_length_in_place_left(r3, r2)); limbs_sub_same_length_in_place_right(r2, r4); assert_eq!(limbs_slice_shr_in_place(r4, 1), 0); assert!(!limbs_sub_same_length_in_place_left(r2, r4)); let r1 = &mut r1[..m]; limbs_slice_add_same_length_in_place_left(r5, r1); assert_eq!(limbs_slice_shr_in_place(r5, 1), 0); // Last interpolation steps... assert!(!limbs_sub_same_length_in_place_left(r3, r1)); assert!(!limbs_sub_same_length_in_place_left(r1, r5)); // ...could be mixed with recomposition // ``` // ||H-r5|M-r5|L-r5| ||H-r1|M-r1|L-r1| // ``` // // Recomposition // // out[] prior to operations: // ``` // |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|____|H_r6|L r6|out // ``` // // Summation scheme for remaining operations: // ``` // |__12|n_11|n_10|n__9|n__8|n__7|n__6|n__5|n__4|n__3|n__2|n___|n___|out // |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|____|H_r6|L r6|out // ||H r1|M r1|L r1| ||H r3|M r3|L r3| ||H_r5|M_r5|L_r5| // ``` split_into_chunks_mut!(out, n, [_unused, out_1, out_2, out_3], out_4); split_into_chunks_mut!(r5, n, [r5_0, r5_1], r5_2); if limbs_slice_add_same_length_in_place_left(out_1, r5_0) { if limbs_add_limb_to_out(out_2, r5_1, 1) { assert!(!limbs_slice_add_limb_in_place(r5_2, 1)); } } else { out_2.copy_from_slice(r5_1); } let (r5_last, r5_2) = r5_2.split_last_mut().unwrap(); let mut carry = *r5_last; if limbs_slice_add_same_length_in_place_left(out_3, r5_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place( &mut out_4[..=n<<1], carry, )); split_into_chunks_mut!(out_4, n, [_unused, out_5, out_6, out_7], out_8); split_into_chunks_mut!(r3, n, [r3_0, r3_1], r3_2); if limbs_slice_add_same_length_in_place_left(out_5, r3_0) { out_6[0].wrapping_add_assign(1); } let out_6_first = out_6[0]; if limbs_add_limb_to_out(out_6, r3_1, out_6_first) { assert!(!limbs_slice_add_limb_in_place(r3_2, 1)); } let (r3_last, r3_2) = r3_2.split_last_mut().unwrap(); let mut carry = *r3_last; if limbs_slice_add_same_length_in_place_left(out_7, r3_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place( &mut out_8[..=n<<1], carry, )); split_into_chunks_mut!(out_8, n, [_unused, out_9], out_10); let (r1_0, r1_1) = r1.split_at_mut(n); if limbs_slice_add_same_length_in_place_left(out_9, r1_0) { out_10[0].wrapping_add_assign(1); } let out_10_first = out_10[0]; if half { let (out_10, out_11) = out_10.split_at_mut(n); let (r1_1, r1_2) = r1_1.split_at_mut(n); if limbs_add_limb_to_out(out_10, r1_1, out_10_first) { assert!(!limbs_slice_add_limb_in_place(r1_2, 1)); } if s_plus_t > n { let (out_11, out_12) = out_11.split_at_mut(n); let (r1_last, r1_2) = r1_2.split_last_mut().unwrap(); let mut carry = *r1_last; if limbs_slice_add_same_length_in_place_left(out_11, r1_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place( &mut out_12[..s_plus_t - n], carry, )); } else { assert!(!limbs_slice_add_same_length_in_place_left( &mut out_11[..s_plus_t], &r1_2[..s_plus_t], )); } } else { assert!(!limbs_add_limb_to_out( out_10, &r1_1[..s_plus_t], out_10_first, )); } }} #[cfg(feature = "32_bit_limbs")] const CORRECTED_WIDTH: u64 = 42 - Limb::WIDTH; #[cfg(not(feature = "32_bit_limbs"))] const CORRECTED_WIDTH: u64 = 42; // Interpolation for Toom-8.5 (or Toom-8), using the evaluation points: Infinity(8.5 only), +-8, // +-4, +-2, +-1, +-1/4, +-1/2, +-1/8, 0. // // More precisely, we want to compute f(2 ^ (`Limb::WIDTH` * n)) for a polynomial f of degree 15 (or // 14), given the 16 (rsp. 15) values: // // - r0 = limit at infinity of f(x) / x ^ 7, // - r1 = f(8), f(-8), // - r2 = f(4), f(-4), // - r3 = f(2), f(-2), // - r4 = f(1), f(-1), // - r5 = f(1/4), f(-1/4), // - r6 = f(1/2), f(-1/2), // - r7 = f(1/8), f(-1/8), // - r8 = f(0). // // All couples of the form f(n),f(-n) must be already mixed with // toom_couple_handling(f(n),...,f(-n),...) // // - The result is stored in {out, s_plus_t + 7 * n (or 8 * n)}. // - At entry, r8 is stored at {out, 2 * n}, // - r6 is stored at {out + 3 * n, 3 * n + 1}. // - r4 is stored at {out + 7 * n, 3 * n + 1}. // - r2 is stored at {out + 11 * n, 3 * n + 1}. // - r0 is stored at {out + 15 * n, s_plus_t}. // // The other values are 3 * n + 1 limbs each (with most significant limbs small). // // Negative intermediate results are stored two-complemented. Inputs are destroyed. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `n`. // // This is equivalent to `mpn_toom_interpolate_16pts` from `mpn/generic/toom_interpolate_16pts.c`, // GMP 6.2.1. pub_crate_test! {limbs_mul_toom_interpolate_16_points<'a>( out: &mut [Limb], r1: &mut [Limb], mut r3: &'a mut [Limb], mut r5: &'a mut [Limb], mut r7: &'a mut [Limb], n: usize, s_plus_t: usize, half: bool, mut scratch: &'a mut [Limb], ) { let m = 3 * n + 1; assert!(s_plus_t <= n << 1); assert_eq!(r1.len(), m); assert_eq!(r3.len(), m); assert_eq!(r5.len(), m); assert_eq!(r7.len(), m); let (pp_lo, remainder) = out.split_at_mut(3 * n); let pp_lo = &mut pp_lo[..n << 1]; split_into_chunks_mut!(remainder, n << 2, [r6, r4], r2); let r4 = &mut r4[..m]; let r6 = &mut r6[..m]; // Interpolation if half { let (r2, r0) = r2.split_at_mut(n << 2); let r0 = &mut r0[..s_plus_t]; let r2 = &mut r2[..m]; let (r4_lo, r4_hi) = r4.split_at_mut(s_plus_t); if limbs_sub_same_length_in_place_left(r4_lo, r0) { assert!(!limbs_sub_limb_in_place(r4_hi, 1)); } let carry = limbs_shl_and_sub_same_length(r3, r0, 14, scratch); assert!(!limbs_sub_limb_in_place(&mut r3[s_plus_t..], carry)); limbs_shl_and_sub(r6, r0, 2, scratch); let carry = limbs_shl_and_sub_same_length(r2, r0, 28, scratch); assert!(!limbs_sub_limb_in_place(&mut r2[s_plus_t..], carry)); limbs_shl_and_sub(r5, r0, 4, scratch); if BIT_CORRECTION { let carry = limbs_shl_and_sub_same_length(&mut r1[1..], r0, CORRECTED_WIDTH, scratch); limbs_sub_limb_in_place(&mut r1[s_plus_t + 1..], carry); let r5_first = r5.first_mut().unwrap(); let carry = *r5_first; *r5_first = 0x80; limbs_shl_and_sub_special(r7, r5_first, r0, 6, scratch); *r5_first = carry; } else { let carry = limbs_shl_and_sub_same_length(r1, r0, CORRECTED_WIDTH, scratch); assert!(!limbs_sub_limb_in_place(&mut r1[s_plus_t..], carry)); limbs_shl_and_sub(r7, r0, 6, scratch); } } let r2 = &mut r2[..m]; let (r5_last, r5_init) = r5[n..].split_last_mut().unwrap(); r5_last.wrapping_sub_assign(limbs_shl_and_sub_same_length(r5_init, pp_lo, 28, scratch)); limbs_shl_and_sub(&mut r2[n..], pp_lo, 4, scratch); limbs_sub_same_length_to_out(scratch, r5, r2); // can be negative assert!(!limbs_slice_add_same_length_in_place_left(r2, r5)); swap(&mut r5, &mut scratch); let (r6_last, r6_init) = r6[n..].split_last_mut().unwrap(); r6_last.wrapping_sub_assign(limbs_shl_and_sub_same_length(r6_init, pp_lo, 14, scratch)); limbs_shl_and_sub(&mut r3[n..], pp_lo, 2, scratch); assert!(!limbs_add_same_length_to_out(scratch, r3, r6)); limbs_sub_same_length_in_place_left(r6, r3); // can be negative swap(&mut r3, &mut scratch); let r1_hi = &mut r1[n..]; if BIT_CORRECTION { limbs_shl_and_sub_same_length(&mut r7[n + 1..], pp_lo, CORRECTED_WIDTH, scratch); let (pp_lo_first, pp_lo_tail) = pp_lo.split_first().unwrap(); assert!(!limbs_sub_limb_in_place(r1_hi, pp_lo_first >> 6)); let carry = limbs_shl_and_sub_same_length(r1_hi, pp_lo_tail, Limb::WIDTH - 6, scratch); limbs_sub_limb_in_place(&mut r1_hi[2 * n - 1..], carry); } else { let carry = limbs_shl_and_sub_same_length(&mut r7[n..], pp_lo, CORRECTED_WIDTH, scratch); r7.last_mut().unwrap().wrapping_sub_assign(carry); limbs_shl_and_sub(r1_hi, pp_lo, 6, scratch); } // can be negative limbs_sub_same_length_to_out(scratch, r7, r1); // if BIT_CORRECTION, can give a carry. limbs_slice_add_same_length_in_place_left(r1, r7); swap(&mut r7, &mut scratch); let (r4_last, r4_init) = r4[n..].split_last_mut().unwrap(); if limbs_sub_same_length_in_place_left(r4_init, pp_lo) { r4_last.wrapping_sub_assign(1); } limbs_aors_mul_or_two_sh_aors_helper(r5, r6, 1028, false, 2, false, 10, false, scratch); limbs_sub_mul_limb_same_length_in_place_left(r7, r5, 1300); // can be negative limbs_aors_mul_or_three_sh_aors_helper(r7, r6, 1052688, 4, 12, 20, false, scratch); limbs_div_exact_limb_in_place(r7, 188513325); limbs_div_255_in_place(r7); // can be negative limbs_sub_mul_limb_same_length_in_place_left(r5, r7, 12567555); // A division by 2835x64 follows. Warning: the operand can be negative! limbs_div_exact_limb_in_place(r5, 2835 << 6); let r5_last = r5.last_mut().unwrap(); if r5_last.leading_zeros() < 7 { *r5_last |= Limb::MAX << (Limb::WIDTH - 6); } limbs_aors_mul_or_aors_and_sh_aors_helper(r6, r7, 4095, true, 12, scratch); limbs_aors_mul_or_two_sh_aors_helper(r6, r5, 240, true, 8, true, 4, false, scratch); // A division by 255x4 follows. Warning: the operand can be negative! limbs_div_exact_limb_in_place(r6, 255 << 2); let r6_last = r6.last_mut().unwrap(); if r6_last.leading_zeros() < 3 { *r6_last |= Limb::MAX << (Limb::WIDTH - 2); } assert_eq!(limbs_shl_and_sub_same_length(r3, r4, 7, scratch), 0); assert_eq!(limbs_shl_and_sub_same_length(r2, r4, 13, scratch), 0); assert_eq!(limbs_sub_mul_limb_same_length_in_place_left(r2, r3, 400), 0); // If `Limb::WIDTH` < 42 next operations on r1 can give a carry! limbs_shl_and_sub_same_length(r1, r4, 19, scratch); limbs_sub_mul_limb_same_length_in_place_left(r1, r2, 1428); limbs_sub_mul_limb_same_length_in_place_left(r1, r3, 112896); limbs_div_exact_limb_in_place(r1, 182712915); limbs_div_255_in_place(r1); assert_eq!( limbs_sub_mul_limb_same_length_in_place_left(r2, r1, 15181425), 0 ); limbs_div_exact_limb_in_place(r2, 42525 << 4); limbs_aors_mul_or_aors_and_two_sh_aors_helper(r3, r1, 3969, 7, 12, scratch); assert_eq!(limbs_sub_mul_limb_same_length_in_place_left(r3, r2, 900), 0); limbs_div_exact_limb_in_place(r3, 9 << 4); assert!(!limbs_sub_same_length_in_place_left(r4, r1)); assert!(!limbs_sub_same_length_in_place_left(r4, r3)); assert!(!limbs_sub_same_length_in_place_left(r4, r2)); limbs_slice_add_same_length_in_place_left(r6, r2); assert_eq!(limbs_slice_shr_in_place(r6, 1), 0); assert!(!limbs_sub_greater_in_place_left(r2, r6)); limbs_sub_same_length_in_place_right(r3, r5); assert_eq!(limbs_slice_shr_in_place(r5, 1), 0); assert!(!limbs_sub_same_length_in_place_left(r3, r5)); limbs_slice_add_same_length_in_place_left(r7, r1); assert_eq!(limbs_slice_shr_in_place(r7, 1), 0); assert!(!limbs_sub_same_length_in_place_left(r1, r7)); // Last interpolation steps could be mixed with recomposition. // ``` // ||H-r7|M-r7|L-r7| ||H-r5|M-r5|L-r5| // ``` // // Recomposition // // out[] prior to operations: // ``` // |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|___||H r6|M r6|L r6|____|H_r8|L r8|out // ``` // // summation scheme for remaining operations: // ``` // |__16|n_15|n_14|n_13|n_12|n_11|n_10|n__9|n__8|n__7|n__6|n__5|n__4|n__3|n__2|n___|n___|out // |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|___||H r6|M r6|L r6|____|H_r8|L r8|out // ||H r1|M r1|L r1| ||H r3|M r3|L r3| ||H_r5|M_r5|L_r5| ||H r7|M r7|L r7| // ``` split_into_chunks_mut!(out, n, [_unused, out_1, out_2, out_3], out_4); split_into_chunks_mut!(r7, n, [r7_0, r7_1], r7_2); if limbs_slice_add_same_length_in_place_left(out_1, r7_0) { if limbs_add_limb_to_out(out_2, r7_1, 1) { assert!(!limbs_slice_add_limb_in_place(r7_2, 1)); } } else { out_2.copy_from_slice(r7_1); } let (r7_last, r7_2) = r7_2.split_last_mut().unwrap(); let mut carry = *r7_last; if limbs_slice_add_same_length_in_place_left(out_3, r7_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place(out_4, carry)); split_into_chunks_mut!(out_4, n, [_unused, out_5, out_6, out_7], out_8); split_into_chunks_mut!(r5, n, [r5_0, r5_1], r5_2); if limbs_slice_add_same_length_in_place_left(out_5, r5_0) { out_6[0].wrapping_add_assign(1); } let out_6_first = out_6[0]; if limbs_add_limb_to_out(out_6, r5_1, out_6_first) { assert!(!limbs_slice_add_limb_in_place(r5_2, 1)); } let (r5_last, r5_2) = r5_2.split_last_mut().unwrap(); let mut carry = *r5_last; if limbs_slice_add_same_length_in_place_left(out_7, r5_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place(out_8, carry)); split_into_chunks_mut!(out_8, n, [_unused, out_9, out_10, out_11], out_12); split_into_chunks_mut!(r3, n, [r3_0, r3_1], r3_2); if limbs_slice_add_same_length_in_place_left(out_9, r3_0) { out_10[0].wrapping_add_assign(1); } let out_10_first = out_10[0]; if limbs_add_limb_to_out(out_10, r3_1, out_10_first) { assert!(!limbs_slice_add_limb_in_place(r3_2, 1)); } let (r3_last, r3_2) = r3_2.split_last_mut().unwrap(); let mut carry = *r3_last; if limbs_slice_add_same_length_in_place_left(out_11, r3_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place(out_12, carry)); split_into_chunks_mut!(out_12, n, [_unused, out_13], out_14); let (r1_0, r1_1) = r1.split_at_mut(n); if limbs_slice_add_same_length_in_place_left(out_13, r1_0) { out_14[0].wrapping_add_assign(1); } let out_14_first = out_14[0]; if half { let (out_14, out_15) = out_14.split_at_mut(n); let (r1_1, r1_2) = r1_1.split_at_mut(n); if limbs_add_limb_to_out(out_14, r1_1, out_14_first) { assert!(!limbs_slice_add_limb_in_place(r1_2, 1)); } if s_plus_t > n { let (out_15, out_16) = out_15.split_at_mut(n); let (r1_last, r1_2) = r1_2.split_last_mut().unwrap(); let mut carry = *r1_last; if limbs_slice_add_same_length_in_place_left(out_15, r1_2) { carry.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place( &mut out_16[..s_plus_t - n], carry, )); } else { assert!(!limbs_slice_add_same_length_in_place_left( &mut out_15[..s_plus_t], &r1_2[..s_plus_t], )); } } else { assert!(!limbs_add_limb_to_out( &mut out_14[..s_plus_t], &r1_1[..s_plus_t], out_14_first, )); } }} ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/product_of_limbs.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed to the GNU project by Marco Bodrato. // // Copyright © 2010-2012 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::mul::limb::limbs_slice_mul_limb_in_place; use crate::natural::arithmetic::mul::{ MUL_TOOM22_THRESHOLD, limbs_mul_limb_to_out, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; const RECURSIVE_PROD_THRESHOLD: usize = MUL_TOOM22_THRESHOLD; // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `factors.len()`. // // This is equivalent to `mpz_prodlimbs` from `mpz/prodlimbs.c`, GMP 6.3.0. If x is too small to // contain the output, a newly-allocated vector containing the output is returned. pub fn limbs_product(xs: &mut [Limb], factors: &mut [Limb]) -> (usize, Option>) { let xs_len = xs.len(); let factors_len = factors.len(); assert_ne!(factors_len, 0); assert!(const { RECURSIVE_PROD_THRESHOLD > 3 }); if factors_len < RECURSIVE_PROD_THRESHOLD { let j = factors_len - 1; let mut size = 1; for i in 1..j { let factor = factors[i]; let carry = limbs_slice_mul_limb_in_place(&mut factors[..size], factor); factors[size] = carry; if carry != 0 { size += 1; } } let fj = factors[j]; let factors = &factors[..size]; let sp1 = size + 1; if sp1 > xs_len { let mut prod = vec![0; sp1]; prod[..xs_len].copy_from_slice(xs); let carry = limbs_mul_limb_to_out::(&mut prod, factors, fj); prod[size] = carry; (size + usize::from(carry != 0), Some(prod)) } else { let carry = limbs_mul_limb_to_out::(xs, factors, fj); xs[size] = carry; (size + usize::from(carry != 0), None) } } else { let mut i = factors_len >> 1; let mut j = factors_len - i; let mut x2 = vec![0; j]; let (factors_lo, x1) = factors.split_at_mut(i); let ox2; (j, ox2) = limbs_product(&mut x2, x1); if let Some(new_x2) = ox2 { x2 = new_x2; } let x2 = &x2[..j]; let new_x1; let ox1; (i, ox1) = limbs_product(x1, factors_lo); let x1 = if let Some(new_x1_temp) = ox1 { new_x1 = new_x1_temp; &new_x1[..i] } else { &x1[..i] }; let size = i + j; let mut scratch = vec![0; limbs_mul_to_out_scratch_len(i, j)]; if size > xs_len { let mut prod = vec![0; size]; prod[..xs_len].copy_from_slice(xs); let carry = limbs_mul_to_out(&mut prod, x1, x2, &mut scratch); (size - usize::from(carry == 0), Some(prod)) } else { let carry = limbs_mul_to_out(xs, x1, x2, &mut scratch); (size - usize::from(carry == 0), None) } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/mul/toom.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `TOOM22_MUL_REC`, `TOOM22_MUL_N_REC`, and `mpn_toom22_mul` contributed to the GNU project by // Torbjörn Granlund. // // `mpn_toom32_mul` contributed to the GNU project by Torbjörn Granlund, with improvements by // Marco Bodrato and Niels Möller. // // `TOOM33_MUL_N_REC`, `mpn_toom33_mul`, and `mpn_toom42_mul` contributed to the GNU project by // Torbjörn Granlund, with additional improvements by Marco Bodrato. // // `mpn_toom43_mul`, `mpn_toom52_mul`, `mpn_toom54_mul`, `abs_sub_n`, `abs_sub_add_n`, // `mpn_toom63_mul`, `TOOM6H_MUL_N_REC`, `mpn_toom6h_mul`, `TOOM8H_MUL_N_REC`, // `mpn_toom8h_mul`, and `mpn_toom_couple_handling` contributed to the GNU project by Marco // Bodrato. // // `mpn_toom44_mul`, `mpn_toom53_mul`, and `mpn_toom62_mul` contributed to the GNU project by // Torbjörn Granlund and Marco Bodrato. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_same_length_with_carry_in_in_place_left, limbs_add_to_out, limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mul::poly_eval::{ limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1, limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2, limbs_mul_toom_evaluate_poly_in_1_and_neg_1, limbs_mul_toom_evaluate_poly_in_2_and_neg_2, limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow, limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg, }; use crate::natural::arithmetic::mul::poly_interpolate::{ limbs_mul_toom_interpolate_5_points, limbs_mul_toom_interpolate_6_points, limbs_mul_toom_interpolate_7_points, limbs_mul_toom_interpolate_8_points, limbs_mul_toom_interpolate_12_points, limbs_mul_toom_interpolate_16_points, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_basecase, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::arithmetic::square::{ limbs_square_to_out_toom_6_scratch_len, limbs_square_to_out_toom_8_scratch_len, }; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_to_out, limbs_sub_same_length_with_borrow_in_in_place_left, limbs_sub_same_length_with_borrow_in_to_out, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{ Limb, MUL_FFT_THRESHOLD, MUL_TOOM6H_THRESHOLD, MUL_TOOM8H_THRESHOLD, MUL_TOOM22_THRESHOLD, MUL_TOOM33_THRESHOLD, MUL_TOOM44_THRESHOLD, }; use core::cmp::{Ordering::*, max}; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, DivRound, EqModPowerOf2, ShrRound, WrappingAddAssign, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::NotAssign; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::{slice_set_zero, slice_test_zero}; // TODO tune pub(crate) const MUL_TOOM33_THRESHOLD_LIMIT: usize = MUL_TOOM33_THRESHOLD; // Helper function for high degree Toom-Cook algorithms. // // Gets {`xs`, `n`} and (`y_sign` ? -1 : 1) * {`ys`, `n`}. Computes at once: // ``` // {`xs`, `n`} <- ({`xs`, `n`} + {`ys`, `n`}) / 2 ^ {`x_shift` + 1} // {`ys`, `n`} <- ({`xs`, `n`} - {`ys`, `n`}) / 2 ^ {`y_shift` + 1} // ``` // // Finally recompose them obtaining: // ``` // {`xs`, `n` + `offset`} <- {`xs`, `n`} + {`ys`, `n`} * 2 ^ {`offset` * `Limb::WIDTH`} // ``` // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpn_toom_couple_handling` from `mpn/generic/toom_couple_handling.c`, GMP // 6.2.1. The argument `n` is excluded as it is just the length of `ys`. pub(crate) fn limbs_toom_couple_handling( xs: &mut [Limb], ys: &mut [Limb], y_sign: bool, offset: usize, x_shift: u64, y_shift: u64, ) { let n = ys.len(); assert!(xs.len() >= n + offset); let (xs_lo, xs_hi) = xs.split_at_mut(n); if y_sign { limbs_sub_same_length_in_place_right(xs_lo, ys); } else { limbs_slice_add_same_length_in_place_left(ys, xs_lo); } limbs_slice_shr_in_place(ys, 1); limbs_sub_same_length_in_place_left(xs_lo, ys); if x_shift != 0 { limbs_slice_shr_in_place(xs_lo, x_shift); } if y_shift != 0 { limbs_slice_shr_in_place(ys, y_shift); } let (ys_lo, ys_hi) = ys.split_at(n - offset); if limbs_slice_add_same_length_in_place_left(&mut xs_lo[offset..], ys_lo) { assert!(!limbs_add_limb_to_out(xs_hi, ys_hi, 1)); } else { xs_hi[..offset].copy_from_slice(ys_hi); } } // TODO make these compiler flags? // TODO tune #[cfg(feature = "test_build")] pub const TUNE_PROGRAM_BUILD: bool = false; #[cfg(not(feature = "test_build"))] pub(crate) const TUNE_PROGRAM_BUILD: bool = false; // TODO tune #[cfg(feature = "test_build")] pub const WANT_FAT_BINARY: bool = true; #[cfg(not(feature = "test_build"))] pub(crate) const WANT_FAT_BINARY: bool = true; // TODO tune #[cfg(feature = "test_build")] pub const TOOM22_MAYBE_MUL_TOOM22: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM33_THRESHOLD >= 2 * MUL_TOOM22_THRESHOLD; #[cfg(not(feature = "test_build"))] const TOOM22_MAYBE_MUL_TOOM22: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM33_THRESHOLD >= 2 * MUL_TOOM22_THRESHOLD; fn limbs_mul_same_length_to_out_toom_22_recursive_scratch_len(xs_len: usize) -> usize { if !TOOM22_MAYBE_MUL_TOOM22 || xs_len < MUL_TOOM22_THRESHOLD { 0 } else { limbs_mul_greater_to_out_toom_22_scratch_len(xs_len, xs_len) } } // A helper function for `limbs_mul_greater_to_out_toom_22`. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM22_MUL_N_REC` from `mpn/generic/toom22_mul.c`, GMP 6.2.1. fn limbs_mul_same_length_to_out_toom_22_recursive( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { assert_eq!(xs.len(), ys.len()); if !TOOM22_MAYBE_MUL_TOOM22 || xs.len() < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } } fn limbs_mul_greater_to_out_toom_22_recursive_scratch_len(xs_len: usize, ys_len: usize) -> usize { if !TOOM22_MAYBE_MUL_TOOM22 || ys_len < MUL_TOOM22_THRESHOLD { 0 } else if xs_len << 2 < 5 * ys_len { limbs_mul_greater_to_out_toom_22_scratch_len(xs_len, ys_len) } else if limbs_mul_greater_to_out_toom_32_input_sizes_valid(xs_len, ys_len) { limbs_mul_greater_to_out_toom_32_scratch_len(xs_len, ys_len) } else { limbs_mul_greater_to_out_scratch_len(xs_len, ys_len) } } // A helper function for `limbs_mul_greater_to_out_toom_22`. // // Normally, this calls `limbs_mul_greater_to_out_basecase` or `limbs_mul_greater_to_out_toom_22`. // But when the fraction MUL_TOOM33_THRESHOLD / MUL_TOOM22_THRESHOLD is large, an initially small // relative unbalance will become a larger and larger relative unbalance with each recursion (the // difference s - t will be invariant over recursive calls). Therefore, we need to call // `limbs_mul_greater_to_out_toom_32`. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM22_MUL_REC` from `mpn/generic/toom22_mul.c`, GMP 6.2.1. fn limbs_mul_greater_to_out_toom_22_recursive( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); if !TOOM22_MAYBE_MUL_TOOM22 || ys_len < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if xs_len << 2 < 5 * ys_len { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if limbs_mul_greater_to_out_toom_32_input_sizes_valid(xs_len, ys_len) { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out(out, xs, ys, scratch); } } // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_22` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_mul_greater_to_out_toom_22_input_sizes_valid( xs_len: usize, ys_len: usize, ) -> bool { xs_len >= ys_len && xs_len + 1 < ys_len << 1 }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_22`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom22_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_22_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let s = xs_len >> 1; let n = xs_len - s; let t = ys_len - n; let len = n << 1; let mut mul_len = limbs_mul_same_length_to_out_toom_22_recursive_scratch_len(n); let n = if s > t { limbs_mul_greater_to_out_toom_22_recursive_scratch_len(s, t) } else { limbs_mul_same_length_to_out_toom_22_recursive_scratch_len(s) }; if n > mul_len { mul_len = n; } len + mul_len }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_22_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - `xs`.len() + 1 < 2 * `ys`.len() // // Approximately, `ys`.len() < `xs`.len() < 2 * `ys`.len(). // // The smallest allowable `xs` length is 2. The smallest allowable `ys` length is also 2. // // This uses the Toom-22, aka Toom-2, aka Karatsuba algorithm. // // Evaluate in: -1, 0, Infinity. // ``` // <--s--><--n---> // ______________ // |_xs1_|__xs0__| // |ys1_|__ys0__| // <-t--><--n---> // // v_0 = xs0 * ys0 # X(0) * Y(0) // v_neg_1 = (xs0 - xs1) * (ys0 - ys1) # X(-1) * Y(-1) // v_inf = xs1 * ys1 # X(inf) * Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_2 3}) \approx O(n^{1.585}), but // `limbs_mul_same_length_to_out_toom_22_recursive` calls `limbs_mul_greater_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom22_mul` from `mpn/generic/toom22_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_22( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); assert!(xs_len > 1); let ys_len = ys.len(); assert_ne!(ys_len, 0); assert!(xs_len >= ys_len); let out = &mut out[..xs_len + ys_len]; let s = xs_len >> 1; let n = xs_len - s; assert!(ys_len >= n); let t = ys_len - n; let (xs_0, xs_1) = xs.split_at(n); // xs_0: length n, xs_1: length s let (ys_0, ys_1) = ys.split_at(n); // ys_0: length n, ys_1: length t let mut v_neg_1_neg = false; split_into_chunks_mut!(out, n, [asm1, bsm1], _unused); // Compute bsm1. if s == n { if limbs_cmp_same_length(xs_0, xs_1) == Less { limbs_sub_same_length_to_out(asm1, xs_1, xs_0); v_neg_1_neg = true; } else { limbs_sub_same_length_to_out(asm1, xs_0, xs_1); } } else { // n - s == 1 let (xs_0_last, xs_0_init) = xs_0.split_last().unwrap(); let (asm1_last, asm1_init) = asm1.split_last_mut().unwrap(); if *xs_0_last == 0 && limbs_cmp_same_length(xs_0_init, xs_1) == Less { limbs_sub_same_length_to_out(asm1_init, xs_1, xs_0_init); *asm1_last = 0; v_neg_1_neg = true; } else { *asm1_last = *xs_0_last; if limbs_sub_same_length_to_out(asm1_init, xs_0_init, xs_1) { asm1_last.wrapping_sub_assign(1); } } } // Compute bsm1. if t == n { if limbs_cmp_same_length(ys_0, ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, ys_0); v_neg_1_neg.not_assign(); } else { limbs_sub_same_length_to_out(bsm1, ys_0, ys_1); } } else { let (ys_0_lo, ys_0_hi) = ys_0.split_at(t); if slice_test_zero(ys_0_hi) && limbs_cmp_same_length(ys_0_lo, ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, ys_0_lo); slice_set_zero(&mut bsm1[t..]); v_neg_1_neg.not_assign(); } else { limbs_sub_greater_to_out(bsm1, ys_0, ys_1); } } let (v_neg_1, scratch_out) = scratch.split_at_mut(n << 1); // size: n limbs_mul_same_length_to_out_toom_22_recursive(v_neg_1, asm1, bsm1, scratch_out); let (v_0, v_pos_inf) = out.split_at_mut(n << 1); // v_0: length 2 * n if s > t { // size: s, t limbs_mul_greater_to_out_toom_22_recursive(v_pos_inf, xs_1, ys_1, scratch_out); } else { // size: s limbs_mul_same_length_to_out_toom_22_recursive(v_pos_inf, xs_1, &ys_1[..s], scratch_out); } // size: n limbs_mul_same_length_to_out_toom_22_recursive(v_0, xs_0, ys_0, scratch_out); // L(v_pos_inf) + H(v_pos_inf) let (v_pos_inf_lo, v_pos_inf_hi) = v_pos_inf.split_at_mut(n); // v_pos_inf_lo: length n let (v_0_lo, v_0_hi) = v_0.split_at_mut(n); // v_0_lo: length n, vo_hi: length n // H(v_0) + L(v_pos_inf) let mut carry = Limb::from(limbs_slice_add_same_length_in_place_left( v_pos_inf_lo, v_0_hi, )); // L(v_0) + H(v_0) let mut carry2 = carry; if limbs_add_same_length_to_out(v_0_hi, v_pos_inf_lo, v_0_lo) { carry2 += 1; } // - s + t - n == either ys_len - (xs_len >> 1) or ys_len - (xs_len >> 1) - 2. // - n == xs_len - (xs_len >> 1) and xs_len >= ys_len. // - So n >= s + t - n. if limbs_slice_add_greater_in_place_left(v_pos_inf_lo, &v_pos_inf_hi[..s + t - n]) { carry += 1; } let out_lo = &mut out[n..3 * n]; if v_neg_1_neg { if limbs_slice_add_same_length_in_place_left(out_lo, v_neg_1) { carry += 1; } } else if limbs_sub_same_length_in_place_left(out_lo, v_neg_1) { carry.wrapping_sub_assign(1); } assert!(!limbs_slice_add_limb_in_place(&mut out[n << 1..], carry2)); let out_hi = &mut out[3 * n..]; if carry <= 2 { assert!(!limbs_slice_add_limb_in_place(out_hi, carry)); } else { assert!(!limbs_sub_limb_in_place(out_hi, 1)); } }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_32`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom32_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_32_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if xs_len << 1 >= 3 * ys_len { (xs_len - 1) / 3 } else { (ys_len - 1) >> 1 }; let s = xs_len - (n << 1); let t = ys_len - n; 2 * n + 1 + max( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_to_out_scratch_len(s, t), ) }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_32` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_mul_greater_to_out_toom_32_input_sizes_valid( xs_len: usize, ys_len: usize, ) -> bool { xs_len > ys_len + 1 && (xs_len == 6 || ys_len > 4) && xs_len << 1 < 3 * (ys_len + 1) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_32_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() > `ys`.len() + 1 // - 2 * `xs`.len() < 3 * (`ys`.len() + 1) // - `xs`.len() == 6 or `ys`.len() > 4 // // Approximately, `ys`.len() < `xs`.len() < 3 / 2 * `ys`.len(). // // The smallest allowable `xs` length is 6. The smallest allowable `ys` length is 4. // // This uses the Toom-32 aka Toom-2.5 algorithm. // // Evaluate in: -1, 0, 1, Infinity. // ``` // <-s-><--n--><--n--> // ___________________ // |xs2_|__xs1_|__xs0_| // |ys1_|__ys0_| // <-t--><--n--> // // v0 = xs0 * ys0 # X(0) * Y(0) // v1 = (xs0 + xs1 + xs2) * (ys0 + ys1) # X(1) * Y(1) xh <= 2 yh <= 1 // vm1 = (xs0 - xs1 + xs2) * (ys0 - ys1) # X(-1) * Y(-1) |xh| <= 1 yh = 0 // vinf = xs2 * ys1 # X(inf) * Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_3 4}) \approx O(n^{1.262}), but `limbs_mul_same_length_to_out` is // called. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom32_mul` from `mpn/generic/toom32_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_32( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = 1 + if xs_len << 1 >= 3 * ys_len { (xs_len - 1) / 3 } else { (ys_len - 1) >> 1 }; // Required, to ensure that s + t >= n. assert!(ys_len + 2 <= xs_len && xs_len + 6 <= 3 * ys_len); split_into_chunks!(xs, n, [xs_0, xs_1], xs_2); let s = xs_2.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0], ys_1); let t = ys_1.len(); assert_ne!(t, 0); assert!(t <= n); assert!(s + t >= n); // Product area of size xs_len + ys_len = 3 * n + s + t >= 4 * n + 2. split_into_chunks_mut!(out, n << 1, [out_lo, out_hi], _unused); let (ap1, bp1) = out_lo.split_at_mut(n); let (am1, bm1) = out_hi.split_at_mut(n); // Compute ap1 = xs0 + xs1 + a3, am1 = xs0 - xs1 + a3 let mut hi = limbs_add_to_out(ap1, xs_0, xs_2); let mut ap1_hi = Limb::from(hi); let mut v_neg_1_neg = ap1_hi == 0 && limbs_cmp_same_length(ap1, xs_1) == Less; if v_neg_1_neg { assert!(!limbs_sub_same_length_to_out(am1, xs_1, ap1)); } else if limbs_sub_same_length_to_out(am1, ap1, xs_1) { hi.not_assign(); } if limbs_slice_add_same_length_in_place_left(ap1, xs_1) { ap1_hi += 1; } let bp1_hi; // Compute bp1 = ys0 + ys1 and bm1 = ys0 - ys1. if t == n { bp1_hi = limbs_add_same_length_to_out(bp1, ys_0, ys_1); if limbs_cmp_same_length(ys_0, ys_1) == Less { assert!(!limbs_sub_same_length_to_out(bm1, ys_1, ys_0)); v_neg_1_neg.not_assign(); } else { assert!(!limbs_sub_same_length_to_out(bm1, ys_0, ys_1)); } } else { bp1_hi = limbs_add_to_out(bp1, ys_0, ys_1); let (ys_0_lo, ys_0_hi) = ys_0.split_at(t); if slice_test_zero(ys_0_hi) && limbs_cmp_same_length(ys_0_lo, ys_1) == Less { let (bm1_lo, bm1_hi) = bm1.split_at_mut(t); assert!(!limbs_sub_same_length_to_out(bm1_lo, ys_1, ys_0_lo)); slice_set_zero(bm1_hi); v_neg_1_neg.not_assign(); } else { assert!(!limbs_sub_greater_to_out(bm1, ys_0, ys_1)); } } let m = (n << 1) + 1; let (scratch, mul_scratch) = scratch.split_at_mut(m); // size: n limbs_mul_same_length_to_out(scratch, ap1, bp1, mul_scratch); split_into_chunks_mut!(scratch, n, [_unused, scratch_lo], scratch_hi); let mut carry = 0; match ap1_hi { 1 => { if limbs_slice_add_same_length_in_place_left(scratch_lo, bp1) { carry = 1; } if bp1_hi { carry += 1; } } 2 => { carry = limbs_slice_add_mul_limb_same_length_in_place_left(scratch_lo, bp1, 2); if bp1_hi { carry += 2; } } _ => {} } if bp1_hi && limbs_slice_add_same_length_in_place_left(scratch_lo, ap1) { carry += 1; } scratch_hi[0] = carry; // size: n limbs_mul_same_length_to_out(out_lo, am1, bm1, mul_scratch); out_hi[0] = Limb::from(hi && limbs_slice_add_same_length_in_place_left(&mut out_lo[n..], bm1)); // v1 <-- (v1 + vm1) / 2 = x0 + x2 let out_b = &out[..m]; if v_neg_1_neg { limbs_sub_same_length_in_place_left(scratch, out_b); } else { limbs_slice_add_same_length_in_place_left(scratch, out_b); } assert_eq!(limbs_slice_shr_in_place(scratch, 1), 0); split_into_chunks_mut!(out, n, [out_0, out_1, out_2], _unused); // We get x1 + x3 = (x0 + x2) - (x0 - x1 + x2 - x3), and hence // ``` // y = x1 + x3 + (x0 + x2) * B // = (x0 + x2) * B + (x0 + x2) - vm1. // ``` // // y is 3 * n + 1 limbs, y = y0 + y1 B + y2 B^2. We store them as follows: y0 at scratch, y1 at // out + 2 * n, and y2 at scratch + n (already in place, except for carry propagation). // // We thus add // ``` // B^3 B^2 B 1 // | | | | // +-----+----+ // + | x0 + x2 | // +----+-----+----+ // + | x0 + x2 | // +----------+ // - | vm1 | // --+----++----+----+- // | y2 | y1 | y0 | // +-----+----+----+ // ``` // // Since we store y0 at the same location as the low half of x0 + x2, we need to do the middle // sum first. let mut hi = out_2[0]; let (scratch_lo, scratch_hi) = scratch.split_at_mut(n); let scratch_hi = &mut scratch_hi[..=n]; let (scratch_hi_last, scratch_hi_init) = scratch_hi.split_last().unwrap(); let mut x = *scratch_hi_last; if limbs_add_same_length_to_out(out_2, scratch_lo, scratch_hi_init) { x += 1; } assert!(!limbs_slice_add_limb_in_place(scratch_hi, x)); if v_neg_1_neg { let carry = limbs_slice_add_same_length_in_place_left(scratch_lo, out_0); // out_lo: length 2 * n if limbs_add_same_length_with_carry_in_in_place_left(out_2, out_1, carry) { hi.wrapping_add_assign(1); } assert!(!limbs_slice_add_limb_in_place(scratch_hi, hi)); } else { let carry = limbs_sub_same_length_in_place_left(scratch_lo, out_0); // out_lo: length 2 * n if limbs_sub_same_length_with_borrow_in_in_place_left(out_2, out_1, carry) { hi.wrapping_add_assign(1); } assert!(!limbs_sub_limb_in_place(scratch_hi, hi)); } // size: n limbs_mul_same_length_to_out(out, xs_0, ys_0, mul_scratch); // size: s, t limbs_mul_to_out(&mut out[3 * n..], xs_2, ys_1, mul_scratch); // Remaining interpolation. // // ``` // y * B + x0 + x3 B^3 - x0 B^2 - x3 B // = (x1 + x3) B + (x0 + x2) B^2 + x0 + x3 B^3 - x0 B^2 - x3 B // = y0 B + y1 B^2 + y3 B^3 + Lx0 + H x0 B // + L x3 B^3 + H x3 B^4 - Lx0 B^2 - H x0 B^3 - L x3 B - H x3 B^2 // = L x0 + (y0 + H x0 - L x3) B + (y1 - L x0 - H x3) B^2 // + (y2 - (H x0 - L x3)) B^3 + H x3 B^4 // // B^4 B^3 B^2 B 1 // | | | | | | // +-------+ +---------+---------+ // | Hx3 | | Hx0-Lx3 | Lx0 | // +------+----------+---------+---------+---------+ // | y2 | y1 | y0 | // ++---------+---------+---------+ // -| Hx0-Lx3 | - Lx0 | // +---------+---------+ // | - Hx3 | // +--------+ // ``` // We must take into account the carry from Hx0 - Lx3. split_into_chunks_mut!(out, n, [out_0, out_1, out_2], out_3); let carry = limbs_sub_same_length_in_place_left(out_1, &out_3[..n]); let (scratch_hi_last, scratch_hi_init) = scratch_hi.split_last().unwrap(); let mut hi = *scratch_hi_last; if carry { hi.wrapping_add_assign(1); } let borrow = limbs_sub_same_length_with_borrow_in_in_place_left(out_2, out_0, carry); if limbs_sub_same_length_with_borrow_in_to_out(out_3, scratch_hi_init, out_1, borrow) { hi.wrapping_sub_assign(1); } if limbs_slice_add_greater_in_place_left(&mut out[n..n << 2], scratch_lo) { hi.wrapping_add_assign(1); } if s + t > n { split_into_chunks_mut!(out, n << 1, [_unused, out_lo], out_hi); let out_hi = &mut out_hi[..s + t - n]; if limbs_sub_greater_in_place_left(out_lo, out_hi) { hi.wrapping_sub_assign(1); } if hi.get_highest_bit() { fail_on_untested_path("limbs_mul_greater_to_out_toom_32, hi.get_highest_bit()"); assert!(!limbs_sub_limb_in_place(out_hi, hi.wrapping_neg())); } else { assert!(!limbs_slice_add_limb_in_place(out_hi, hi)); } } else { assert_eq!(hi, 0); } }} // TODO tune #[cfg(feature = "test_build")] pub const TOOM33_MAYBE_MUL_BASECASE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM33_THRESHOLD < 3 * MUL_TOOM22_THRESHOLD; #[cfg(not(feature = "test_build"))] const TOOM33_MAYBE_MUL_BASECASE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM33_THRESHOLD < 3 * MUL_TOOM22_THRESHOLD; // TODO tune #[cfg(feature = "test_build")] #[allow(clippy::absurd_extreme_comparisons)] pub const TOOM33_MAYBE_MUL_TOOM33: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM44_THRESHOLD >= 3 * MUL_TOOM33_THRESHOLD; #[cfg(not(feature = "test_build"))] #[allow(clippy::absurd_extreme_comparisons)] const TOOM33_MAYBE_MUL_TOOM33: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || MUL_TOOM44_THRESHOLD >= 3 * MUL_TOOM33_THRESHOLD; fn limbs_mul_same_length_to_out_toom_33_recursive_scratch_len(xs_len: usize) -> usize { if TOOM33_MAYBE_MUL_BASECASE && xs_len < MUL_TOOM22_THRESHOLD { 0 } else if !TOOM33_MAYBE_MUL_TOOM33 || xs_len < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22_scratch_len(xs_len, xs_len) } else { limbs_mul_greater_to_out_toom_33_scratch_len(xs_len, xs_len) } } // A helper function for `limbs_mul_greater_to_out_toom_33`. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM33_MUL_N_REC` from `mpn/generic/toom33_mul.c`, GMP 6.2.1. pub_test! {limbs_mul_same_length_to_out_toom_33_recursive( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let n = xs.len(); assert_eq!(xs.len(), n); if TOOM33_MAYBE_MUL_BASECASE && n < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if !TOOM33_MAYBE_MUL_TOOM33 || n < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } }} // TODO tune const SMALLER_RECURSION_TOOM_33_AND_53: bool = true; // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_33` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_mul_greater_to_out_toom_33_input_sizes_valid( xs_len: usize, ys_len: usize ) -> bool { xs_len >= ys_len && xs_len.div_round(3, Ceiling).0 << 1 < ys_len }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_33`. // // Scratch need is 5 * xs_len / 2 + 10 * k, where k is the recursion depth. We use 3 * xs_len + C, // so that we can use a smaller constant. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom33_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_33_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = xs_len.div_round(3, Ceiling).0; let m = n + 1; assert!(m < xs_len); let s = xs_len - (n << 1); let t = ys_len - (n << 1); let st_mul_scratch_len = if s > t { limbs_mul_greater_to_out_scratch_len(s, t) } else { limbs_mul_same_length_to_out_toom_33_recursive_scratch_len(s) }; 5 * m + max!( limbs_mul_same_length_to_out_toom_33_recursive_scratch_len(m), limbs_mul_same_length_to_out_toom_33_recursive_scratch_len(n), st_mul_scratch_len ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_33_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - 2 * ceiling(`xs`.len() / 3) < `ys`.len() // // Approximately, `ys`.len() < `xs`.len() < 3 / 2 * `ys`.len(). // // The smallest allowable `xs` length is 3. The smallest allowable `ys` length is also 3. // // This uses the Toom-33 aka Toom-3 algorithm. // // Evaluate in: -1, 0, 1, 2, Infinity. // ``` // <--s--><--n--><--n--> // ____________________ // |_xs2_|__xs1_|__xs0_| // |ys2_|__ys1_|__ys0_| // <-t--><--n--><--n--> // // v0 = xs0 * b0 # X(0) * Y(0) // v1 = (xs0 + * xs1 + a2) * (ys0 + ys1+ ys2) # X(1) * Y(1) xh <= 2, yh <= 2 // vm1 = (xs0 - * xs1 + a2) * (ys0 - ys1+ ys2) # X(-1) * Y(-1) |xh| <= 1, yh <= 1 // v2 = (xs0 + 2 * xs1 + 4 * a2) * (ys0 + 2 * ys1 + 4 * ys2) # X(2) * Y(2) xh <= 6, yh <= 6 // vinf = xs2 * ys2 # X(inf) * Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_3 5}) \approx O(n^{1.465}), but // `limbs_mul_same_length_to_out_toom_33_recursive` ultimately calls `limbs_mul_greater_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom33_mul` from `mpn/generic/toom33_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_33( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = xs_len.div_round(3, Ceiling).0; let m = n + 1; split_into_chunks!(xs, n, [xs_0, xs_1], xs_2); let s = xs_2.len(); split_into_chunks!(ys, n, [ys_0, ys_1], ys_2); let t = ys_2.len(); assert_ne!(t, 0); split_into_chunks_mut!(out, m, [bs1, as2, bs2], _unused); // we need 4 * n + 4 <= 4 * n + s + t let (v_neg_1, remainder) = scratch.split_at_mut(m << 1); split_into_chunks_mut!(remainder, m, [asm1, bsm1, as1], mul_scratch); let gp = &mut v_neg_1[..n]; // Compute as1 and asm1. let mut carry = Limb::from(limbs_add_to_out(gp, xs_0, xs_2)); let (as1_last, as1_init) = as1.split_last_mut().unwrap(); *as1_last = carry; if limbs_add_same_length_to_out(as1_init, gp, xs_1) { as1_last.wrapping_add_assign(1); } let mut v_neg_1_neg = carry == 0 && limbs_cmp_same_length(gp, xs_1) == Less; let (asm1_last, asm1_init) = asm1.split_last_mut().unwrap(); if v_neg_1_neg { limbs_sub_same_length_to_out(asm1_init, xs_1, gp); *asm1_last = 0; } else { if limbs_sub_same_length_to_out(asm1_init, gp, xs_1) { carry.wrapping_sub_assign(1); } *asm1_last = carry; } // Compute as2. let (as2_last, as2_init) = as2.split_last_mut().unwrap(); let carry = if s == n { limbs_add_same_length_to_out(as2_init, xs_2, &as1_init[..s]) } else if limbs_add_same_length_to_out(as2_init, xs_2, &as1_init[..s]) { limbs_add_limb_to_out(&mut as2_init[s..], &as1_init[s..], 1) } else { as2_init[s..].copy_from_slice(&as1_init[s..]); false }; let mut carry = Limb::from(carry) .wrapping_add(*as1_last) .arithmetic_checked_shl(1u64) .unwrap() .wrapping_add(limbs_slice_shl_in_place(as2_init, 1)); if limbs_sub_same_length_in_place_left(as2_init, xs_0) { carry.wrapping_sub_assign(1); } *as2_last = carry; // Compute bs1 and bsm1. let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); let mut carry = Limb::from(limbs_add_to_out(gp, ys_0, ys_2)); *bs1_last = carry; if limbs_add_same_length_to_out(bs1_init, gp, ys_1) { *bs1_last += 1; } let (bsm1_last, bsm1_init) = bsm1.split_last_mut().unwrap(); if carry == 0 && limbs_cmp_same_length(gp, ys_1) == Less { limbs_sub_same_length_to_out(bsm1_init, ys_1, gp); *bsm1_last = 0; v_neg_1_neg.not_assign(); } else { if limbs_sub_same_length_to_out(bsm1_init, gp, ys_1) { carry.wrapping_sub_assign(1); } *bsm1_last = carry; } // Compute bs2. let (bs2_last, bs2_init) = bs2.split_last_mut().unwrap(); let carry = if t == n { limbs_add_same_length_to_out(bs2_init, &bs1_init[..t], ys_2) } else if limbs_add_same_length_to_out(bs2_init, &bs1_init[..t], ys_2) { limbs_add_limb_to_out(&mut bs2_init[t..], &bs1_init[t..], 1) } else { bs2_init[t..].copy_from_slice(&bs1_init[t..]); false }; let mut carry = Limb::from(carry) .wrapping_add(*bs1_last) .arithmetic_checked_shl(1u64) .unwrap() .wrapping_add(limbs_slice_shl_in_place(bs2_init, 1)); if limbs_sub_same_length_in_place_left(bs2_init, ys_0) { carry.wrapping_sub_assign(1); } *bs2_last = carry; assert!(*as1_last <= 2); assert!(*bs1_last <= 2); assert!(*asm1_last <= 1); assert!(*bsm1_last <= 1); assert!(*as2_last <= 6); assert!(*bs2_last <= 6); if SMALLER_RECURSION_TOOM_33_AND_53 { // size: n limbs_mul_same_length_to_out_toom_33_recursive(v_neg_1, asm1_init, bsm1_init, mul_scratch); let (v_neg_1_last, v_neg_1_init) = v_neg_1[n..=n<<1].split_last_mut().unwrap(); let mut carry = 0; if *asm1_last != 0 { carry = *bsm1_last; if limbs_slice_add_same_length_in_place_left(v_neg_1_init, bsm1_init) { carry.wrapping_add_assign(1); } } if *bsm1_last != 0 && limbs_slice_add_same_length_in_place_left(v_neg_1_init, asm1_init) { carry.wrapping_add_assign(1); } *v_neg_1_last = carry; } else { fail_on_untested_path("limbs_mul_greater_to_out_toom_33, !SMALLER_RECURSION"); // size: m limbs_mul_same_length_to_out_toom_33_recursive(v_neg_1, asm1, bsm1, mul_scratch); } let (v_2, mul_scratch) = scratch[2 * n + 1..].split_at_mut(3 * n + 4); // size: m limbs_mul_same_length_to_out_toom_33_recursive(v_2, as2, bs2, mul_scratch); let v_inf = &mut out[n << 2..]; // v_inf, s + t limbs if s > t { // size: s, t limbs_mul_greater_to_out(v_inf, xs_2, ys_2, mul_scratch); } else { // size: s limbs_mul_same_length_to_out_toom_33_recursive(v_inf, xs_2, &ys_2[..s], mul_scratch); } let v_inf0 = v_inf[0]; // v1 overlaps with this let (as1, mul_scratch) = scratch[m << 2..].split_at_mut(m); let (bs1, v_1) = out.split_at_mut(n << 1); let bs1 = &bs1[..m]; if SMALLER_RECURSION_TOOM_33_AND_53 { let (as1_last, as1_init) = as1.split_last().unwrap(); let (bs1_last, bs1_init) = bs1.split_last().unwrap(); // size: n limbs_mul_same_length_to_out_toom_33_recursive(v_1, as1_init, bs1_init, mul_scratch); let (v_1_lo, v_1_hi) = v_1[n..].split_at_mut(n); let mut carry = 0; if *as1_last == 1 { carry = *bs1_last; if limbs_slice_add_same_length_in_place_left(v_1_lo, bs1_init) { carry += 1; } } else if *as1_last != 0 { carry = bs1_last.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_add_mul_limb_same_length_in_place_left( v_1_lo, bs1_init, 2, )); } if *bs1_last == 1 { if limbs_slice_add_same_length_in_place_left(v_1_lo, as1_init) { carry += 1; } } else if *bs1_last != 0 { carry += limbs_slice_add_mul_limb_same_length_in_place_left(v_1_lo, as1_init, 2); } v_1_hi[0] = carry; } else { let carry = v_1[2 * n + 1]; // size: m limbs_mul_same_length_to_out_toom_33_recursive(v_1, as1, bs1, mul_scratch); v_1[2 * n + 1] = carry; } // size: n limbs_mul_same_length_to_out_toom_33_recursive(out, &xs[..n], &ys[..n], mul_scratch); let (v_neg_1, v_2) = scratch.split_at_mut(2 * n + 1); limbs_mul_toom_interpolate_5_points(out, v_2, v_neg_1, n, s + t, v_neg_1_neg, v_inf0); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_42` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! { limbs_mul_greater_to_out_toom_42_input_sizes_valid(xs_len: usize, ys_len: usize) -> bool { !(xs_len == 9 && ys_len == 4) && xs_len + 3 < ys_len << 2 && xs_len.div_round(3, Ceiling).0 > ys_len.shr_round(1, Ceiling).0 }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_42`. // // This is equivalent to `mpn_toom42_mul_itch` from `gmp-impl.h`, GMP 6.2.1. // // # Worst-case complexity // Constant time and additional memory. pub_crate_test! {limbs_mul_greater_to_out_toom_42_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = if xs_len >= ys_len << 1 { xs_len.shr_round(2, Ceiling).0 } else { ys_len.shr_round(1, Ceiling).0 }; let s = xs_len - 3 * n; let t = ys_len - n; assert!(n + 1 < xs_len); 10 * n + 8 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(n + 1), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_42_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - ceiling(`xs`.len() / 3) > ceiling(`ys`.len() / 2) // - `xs`.len() + 3 < 4 * `ys`.len() // - (`xs`.len(), `ys`.len()) != (9, 4) // // Approximately, 3 / 2 * `ys`.len() < `xs`.len() < 4 * `ys`.len(). // // The smallest allowable `xs` length is 4. The smallest allowable `ys` length is 2. // // This uses the Toom-42 algorithm. // // Evaluate in: -1, 0, 1, 2, Infinity. // ``` // <-s--><--n---><--n---><--n---> // _____________________________ // |xs3_|__xs2__|__xs1__|__xs0__| // |_ys1__|__ys0__| // <--t--><---n---> // // v_0 = xs0 * ys0 # X(0) * Y(0) // v_1 = (xs0 + xs1 + xs2 + xs3) * (ys0 + ys1) # X(1) * Y(1) xh <= 3 yh <= 1 // v_neg_1 = (xs0 - xs1 + xs2 - xs3) * (ys0 - ys1) # X(-1) * Y(-1) |xh| <= 1 yh = 0 // v_2 = (xs0 + 2*xs1 + 4*xs2 + 8*xs3) * (ys0 + 2*ys1) # X(2) * Y(2) xh <= 14 yh <= 2 // v_inf = xs3 * b1 # A(inf)*B(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_4 5}) \approx O(n^{1.161}), but `limbs_mul_same_length_to_out` is // called. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom42_mul` from `mpn/generic/toom42_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_42( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); let n = if xs_len >= ys_len << 1 { xs_len.shr_round(2, Ceiling).0 } else { ys_len.shr_round(1, Ceiling).0 }; split_into_chunks!(xs, n, [xs_0, xs_1, xs_2], xs_3); let s = xs_3.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0], ys_1); let t = ys_1.len(); assert_ne!(t, 0); assert!(t <= n); let (scratch, mul_scratch) = scratch.split_at_mut(10 * n + 8); let (scratch_lo, scratch_hi) = scratch.split_at_mut(6 * n + 5); split_into_chunks_mut!(scratch_lo, n + 1, [as1, asm1, as2, bs1], remainder); let (bsm1, bs2) = remainder.split_at_mut(n); // Compute as1 and asm1. let mut v_neg_1_neg = limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(as1, asm1, xs, n, &mut out[..=n]); // Compute as2. let (as2_last, as2_init) = as2.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(as2_init, xs_3, 1); if limbs_slice_add_same_length_in_place_left(&mut as2_init[..s], &xs_2[..s]) { carry += 1; } if s != n { carry = Limb::from(limbs_add_limb_to_out(&mut as2_init[s..], &xs_2[s..], carry)); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(as2_init, 1)); if limbs_slice_add_same_length_in_place_left(as2_init, xs_1) { carry += 1; } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(as2_init, 1)); if limbs_slice_add_same_length_in_place_left(as2_init, xs_0) { carry += 1; } *as2_last = carry; // Compute bs1 and bsm1. let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); if t == n { *bs1_last = Limb::from(limbs_add_same_length_to_out(bs1_init, ys_0, ys_1)); if limbs_cmp_same_length(ys_0, ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, ys_0); v_neg_1_neg.not_assign(); } else { limbs_sub_same_length_to_out(bsm1, ys_0, ys_1); } } else { *bs1_last = Limb::from(limbs_add_to_out(bs1_init, ys_0, ys_1)); if slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, &ys_0[..t]); slice_set_zero(&mut bsm1[t..]); v_neg_1_neg.not_assign(); } else { limbs_sub_greater_to_out(bsm1, ys_0, ys_1); } } // Compute bs2, recycling bs1. bs2 = bs1 + ys_1 limbs_add_to_out(bs2, bs1, ys_1); let (as1_last, as1_init) = as1.split_last().unwrap(); let (bs1_last, bs1_init) = bs1.split_last().unwrap(); let (asm1_last, asm1_init) = asm1.split_last().unwrap(); assert!(*as1_last <= 3); assert!(*bs1_last <= 1); assert!(*asm1_last <= 1); assert!(*as2_last <= 14); assert!(bs2[n] <= 2); let (v_neg_1, v_2) = scratch_hi.split_at_mut(2 * n + 1); split_into_chunks_mut!(out, n << 1, [v_0, v_1], v_inf); // size: n limbs_mul_same_length_to_out(v_neg_1, asm1_init, bsm1, mul_scratch); let (v_neg_1_last, v_neg_1_init) = v_neg_1.split_last_mut().unwrap(); *v_neg_1_last = Limb::from( *asm1_last != 0 && limbs_slice_add_same_length_in_place_left(&mut v_neg_1_init[n..], bsm1), ); // size: n + 1 limbs_mul_same_length_to_out(v_2, as2, bs2, mul_scratch); // size: s, t limbs_mul_to_out(v_inf, xs_3, ys_1, mul_scratch); // size: n limbs_mul_same_length_to_out(v_1, as1_init, bs1_init, mul_scratch); let v_1 = &mut v_1[n..]; let mut carry = match *as1_last { 1 => { let mut carry = *bs1_last; if limbs_slice_add_same_length_in_place_left(v_1, bs1_init) { carry += 1; } carry } 2 => (*bs1_last << 1).wrapping_add(limbs_slice_add_mul_limb_same_length_in_place_left( v_1, bs1_init, 2, )), 3 => bs1_last.wrapping_mul(3).wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(v_1, bs1_init, 3), ), _ => *v_neg_1_last, }; if *bs1_last != 0 && limbs_slice_add_same_length_in_place_left(v_1, as1_init) { carry += 1; } let v_inf_0 = v_inf[0]; // v_1 overlaps with this v_inf[0] = carry; // size: n limbs_mul_same_length_to_out(v_0, xs_0, ys_0, mul_scratch); limbs_mul_toom_interpolate_5_points(out, v_2, v_neg_1, n, s + t, v_neg_1_neg, v_inf_0); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_43` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! { limbs_mul_greater_to_out_toom_43_input_sizes_valid(xs_len: usize, ys_len: usize) -> bool { !(xs_len == 16 && ys_len == 13) && xs_len.div_round(3, Ceiling).0 > ys_len.div_round(3, Ceiling).0 && { let xs_len_div_4: usize = xs_len.shr_round(2, Ceiling).0; xs_len_div_4 < ys_len.shr_round(1, Ceiling).0 && xs_len + ys_len >= 5 * (xs_len_div_4 + 1) } }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_43`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom43_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_43_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if 3 * xs_len >= ys_len << 2 { (xs_len - 1) >> 2 } else { (ys_len - 1) / 3 }; let s = xs_len - 3 * n; let t = ys_len - (n << 1); assert!(n + 1 < xs_len); 6 * n + 4 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(n + 1), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_43_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - ceiling(`xs`.len() / 3) > ceiling(`ys`.len() / 3) // - ceiling(`xs`.len() / 4) < ceiling(`ys`.len() / 2) // - (`xs`.len(), `ys`.len()) != (16, 13) // - `xs`.len() + `ys`.len() >= 5 * (ceiling(`xs`.len() / 4) + 1) // // Approximately, `ys`.len() < `xs`.len() < 2 * `ys`.len(). // // The smallest allowable `xs` length is 11. The smallest allowable `ys` length is 8. // // This uses the Toom-43 algorithm. // ``` // <-s--><--n--><--n--><--n--> // __________________________ // |xs3_|__xs2_|__xs1_|__xs0_| // |_ys2_|__ys1_|__ys0_| // <-t--><--n--><--n--> // // v_0 = xs0 * ys0 # X(0) *Y(0) // v_1 = (xs0 + xs1 + xs2 + xs3) * (ys0 + ys1 + ys2) # X(1) *Y(1) xh <= 3 yh <= 2 // v_neg_1 = (xs0 - xs1 + xs2 - xs3) * (ys0 - ys1 + ys2) # X(-1)*Y(-1) |xh| <= 1 |yh|<= 1 // v_2 = (xs0 + 2*xs1 + 4*xs2 + 8*xs3) * (ys0 + 2*ys1 + 4*ys2) # X(2) *Y(2) xh <= 14 yh <= 6 // v_neg_2 = (xs0 - 2*xs1 + 4*xs2 - 8*xs3) * (ys0 - 2*ys1 + 4*ys2) # X(-2)*Y(-2) |xh| <= 9 |yh|<= 4 // v_inf = xs3 * ys2 # X(inf)*Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_4 6}) \approx O(n^{1.292}), but this function calls // `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom43_mul` from `mpn/generic/toom43_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_43( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); let n = 1 + if 3 * xs_len >= ys_len << 2 { (xs_len - 1) >> 2 } else { (ys_len - 1) / 3 }; let xs_3 = &xs[3 * n..]; let s = xs_3.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0, ys_1], ys_2); let t = ys_2.len(); assert_ne!(t, 0); assert!(t <= n); // This is probably true whenever `xs_len` >= 25 or `ys_len` >= 19. It guarantees that we can // fit 5 values of size n + 1 in the product area. assert!(s + t >= 5); let m = n + 1; let mut v_neg_1_neg = false; let mut v_neg_2_neg = false; split_into_chunks_mut!(out, m, [bs1, bsm2, bs2, as2, as1], _unused); let (scratch, mul_scratch) = scratch.split_at_mut(6 * n + 4); split_into_chunks_mut!(scratch, m, [small_scratch, _unused, bsm1, asm1], asm2); // Compute as2 and asm2. if limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2(as2, asm2, xs, n, asm1) { v_neg_2_neg = true; } // Compute bs2 and bsm2. bsm1[n] = limbs_shl_to_out(bsm1, ys_1, 1); // 2 * ys_1 let mut carry = limbs_shl_to_out(small_scratch, ys_2, 2); // 4 * ys_2 if limbs_slice_add_same_length_in_place_left(&mut small_scratch[..t], &ys_0[..t]) { carry += 1; } // 4 * ys_2 + ys_0 if t != n { carry = Limb::from(limbs_add_limb_to_out( &mut small_scratch[t..], &ys_0[t..], carry, )); } small_scratch[n] = carry; limbs_add_same_length_to_out(bs2, small_scratch, bsm1); if limbs_cmp_same_length(small_scratch, bsm1) == Less { limbs_sub_same_length_to_out(bsm2, bsm1, small_scratch); v_neg_2_neg.not_assign(); } else { limbs_sub_same_length_to_out(bsm2, small_scratch, bsm1); } // Compute as1 and asm1. if limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(as1, asm1, xs, n, small_scratch) { v_neg_1_neg = true; } let (bsm1_last, bsm1_init) = bsm1.split_last_mut().unwrap(); // Compute bs1 and bsm1. *bsm1_last = Limb::from(limbs_add_to_out(bsm1_init, ys_0, ys_2)); let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); *bs1_last = *bsm1_last; if limbs_add_same_length_to_out(bs1_init, bsm1_init, ys_1) { *bs1_last += 1; } if *bsm1_last == 0 && limbs_cmp_same_length(bsm1_init, ys_1) == Less { limbs_sub_same_length_in_place_right(ys_1, bsm1_init); v_neg_1_neg.not_assign(); } else if limbs_sub_same_length_in_place_left(bsm1_init, ys_1) { bsm1_last.wrapping_sub_assign(1); } assert!(as1[n] <= 3); assert!(*bs1_last <= 2); assert!(asm1[n] <= 1); assert!(*bsm1_last <= 1); assert!(as2[n] <= 14); assert!(bs2[n] <= 6); assert!(asm2[n] <= 9); assert!(bsm2[n] <= 4); let (v_neg_1, remainder) = scratch.split_at_mut(m << 1); split_into_chunks_mut!(remainder, m, [bsm1, asm1], _unused); // size: m limbs_mul_same_length_to_out(v_neg_1, asm1, bsm1, mul_scratch); // W4 let two_n = n << 1; let (v_neg_2, asm2) = scratch[two_n + 1..].split_at_mut(two_n + 3); split_into_chunks_mut!(out, m, [_unused, out_lo, bs2, as2], _unused); // size: m limbs_mul_same_length_to_out(v_neg_2, &asm2[..m], out_lo, mul_scratch); // size: m limbs_mul_same_length_to_out(&mut scratch[(n << 2) + 2..], as2, bs2, mul_scratch); let (bs1, remainder) = out.split_at_mut(two_n); let (v_1, as1) = remainder.split_at_mut(two_n + 4); // size: m limbs_mul_same_length_to_out(v_1, &as1[..m], &bs1[..m], mul_scratch); // size: s, t limbs_mul_to_out(&mut out[5 * n..], xs_3, ys_2, mul_scratch); // size: n limbs_mul_same_length_to_out(&mut out[..two_n], &xs[..n], ys_0, mul_scratch); split_into_chunks_mut!(scratch, two_n + 1, [v_neg_1, v_neg_2, v_2], _unused); limbs_mul_toom_interpolate_6_points( out, n, t + s, v_neg_1_neg, v_neg_1, v_neg_2_neg, v_neg_2, v_2, ); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_44` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_mul_greater_to_out_toom_44_input_sizes_valid( xs_len: usize, ys_len: usize ) -> bool { xs_len >= ys_len && 3usize * xs_len.shr_round(2, Ceiling).0 < ys_len }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_44`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom44_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_44_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = xs_len.shr_round(2, Ceiling).0; let s = xs_len - 3 * n; let t = ys_len - 3 * n; assert!(n + 1 < xs_len); let alt_mul_scratch_len = if s > t { limbs_mul_greater_to_out_scratch_len(s, t) } else { limbs_mul_same_length_to_out_scratch_len(s) }; max( 9 * n + 6 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(n + 1), alt_mul_scratch_len ), (n << 3) + 6usize + max(n << 1, s + t), ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_44_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - 3 * ceiling(`xs`.len() / 4) < `ys`.len() // // Approximately, `ys`.len() < `xs`.len() < 4 / 3 * `ys`.len(). // // The smallest allowable `xs` length is 4. The smallest allowable `ys` length is also 4. // // This uses the Toom-44 algorithm. // // Evaluate in: 0, 1, -1, 2, -2, 1 / 2, Infinity. // ``` // <-s--><--n--><--n--><--n--> // __________________________ // |_xs3|__xs2_|__xs1_|__xs0_| // |ys3|__ys2_|__ys1_|__ys0_| // <-t-><--n--><--n--><--n--> // // v_0 = x0 * y0 # X(0)*Y(0) // v_1 = ( x0+ x1+ x2+ x3)*( y0+ y1+ y2+ y3) # X(1)*Y(1) xh <= 3 yh <= 3 // v_neg_1 = ( x0- x1+ x2- x3)*( y0- y1+ y2- y3) # X(-1)*Y(-1) |xh| <= 1 |yh| <= 1 // v_2 = ( x0+2x1+4x2+8x3)*( y0+2y1+4y2+8y3) # X(2)*Y(2) xh <= 14 yh <= 14 // v_neg_2 = ( x0-2x1+4x2-8x3)*( y0-2y1+4y2-8y3) # X(2)*Y(2) xh <= 9 |yh| <= 9 // v_half = (8x0+4x1+2x2+ x3)*(8y0+4y1+2y2+ y3) # X(1/2)*Y(1/2) xh <= 14 yh <= 14 // v_inf = x3 * y2 # X(inf)*Y(inf) // ``` // // Use of scratch space: In the product area, we store // ``` // _______________________ // |v_inf|____|_v_1_|_v_0_| // s+t 2n-1 2n+1 2n // ``` // // The other recursive products, v_neg_1, v_2, v_neg_2, and v_half, are stored in the scratch area. // When computing them, we use the product area for intermediate values. // // Next, we compute v_1. We can store the intermediate factors at v_0 and at v_half + 2 * n + 2. // // Finally, for v_0 and v_inf, factors are parts of the input operands, and we need scratch space // only for the recursive multiplication. // // In all, if S(xs_len) is the scratch need, the needed space is bounded by // // S(xs_len) <= 4 (2 * ceil(xs_len / 4) + 1) + 1 + S(ceil(xs_len / 4) + 1) // // which should give S(n) = 8 * n / 3 + c * log(n) for some constant c. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_4 7}) \approx O(n^{1.404}), but // `limbs_mul_same_length_to_out_toom_44_recursive` calls `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom44_mul` from `mpn/generic/toom44_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_44( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = xs_len.shr_round(2, Ceiling).0; let m = 2 * n + 1; split_into_chunks!(xs, n, [xs_0, xs_1, xs_2], xs_3); let s = xs_3.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0, ys_1, ys_2], ys_3); let t = ys_3.len(); assert_ne!(t, 0); assert!(t <= n); let k = n + 1; // NOTE: The multiplications to v_2, v_neg_2, v_half, and v_neg_1 overwrite the following limb, // so these must be computed in order, and we need a one limb gap to scratch2. apx and bpx must // not overlap with v1 split_into_chunks_mut!(out, k, [apx, amx], remainder); let (bmx, bpx) = remainder.split_at_mut(n << 1); let bmx = &mut bmx[..k]; let bpx = &mut bpx[..k]; // Total scratch need: 8 * n + 5 + scratch for recursive calls. This gives roughly 32 * n / 3 + // log term. let (scratch_lo, mul_scratch) = scratch.split_at_mut(9 * n + 6); let (v_2, scratch_hi) = scratch_lo.split_at_mut((n << 3) + 5); let scratch_hi = &mut scratch_hi[..k]; // Compute apx = xs_0 + 2 * xs_1 + 4 * xs_2 + 8 xs_3 and amx = xs_0 - 2 * xs_1 + 4 * xs_2 - 8 * // xs_3. let mut w1_neg = limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2(&mut apx[..k], amx, xs, n, scratch_hi); // Compute bpx = ys_0 + 2 * ys_1 + 4 * ys_2 + 8 * ys_3 and bmx = ys_0 - 2 * ys_1 + 4 * ys_2 - 8 // * ys_3. if limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2(bpx, bmx, ys, n, scratch_hi) { w1_neg.not_assign(); } // size: n + 1 limbs_mul_same_length_to_out(v_2, apx, bpx, mul_scratch); // size: n + 1 limbs_mul_same_length_to_out(&mut scratch_lo[m..], amx, bmx, mul_scratch); // Compute apx = 8 * xs_0 + 4 * xs_1 + 2 * xs_2 + xs_3 = (((2 * xs_0 + xs_1) * 2 + xs_2) * 2 + // xs_3 let (apx_last, apx_init) = apx.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(apx_init, xs_0, 1); if limbs_slice_add_same_length_in_place_left(apx_init, xs_1) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(apx_init, 1)); if limbs_slice_add_same_length_in_place_left(apx_init, xs_2) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); *apx_last = carry.wrapping_add(limbs_slice_shl_in_place(apx_init, 1)); if limbs_slice_add_greater_in_place_left(apx_init, xs_3) { apx_last.wrapping_add_assign(1); } // Compute bpx = 8 ys_0 + 4 ys_1 + 2 ys_2 + ys_3 = (((2*ys_0 + ys_1) * 2 + ys_2) * 2 + ys_3 let (bpx_last, bpx_init) = bpx.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(bpx_init, ys_0, 1); if limbs_slice_add_same_length_in_place_left(bpx_init, ys_1) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(bpx_init, 1)); if limbs_slice_add_same_length_in_place_left(bpx_init, ys_2) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); *bpx_last = carry.wrapping_add(limbs_slice_shl_in_place(bpx_init, 1)); if limbs_slice_add_greater_in_place_left(bpx_init, ys_3) { bpx_last.wrapping_add_assign(1); } assert!(*apx_last < 15); assert!(*bpx_last < 15); let (v_half, scratch_hi) = scratch_lo[m << 1..].split_at_mut((n << 2) + 3); let scratch_hi = &mut scratch_hi[..k]; // size: n + 1 limbs_mul_same_length_to_out(v_half, apx, bpx, mul_scratch); // Compute apx = xs_0 + xs_1 + xs_2 + xs_3 and amx = xs_0 - xs_1 + xs_2 - xs_3. let mut w3_neg = limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(apx, amx, xs, n, scratch_hi); // Compute bpx = ys_0 + ys_1 + ys_2 + ys_3 and bmx = ys_0 - ys_1 + ys_2 - ys_3. if limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(bpx, bmx, ys, n, scratch_hi) { w3_neg.not_assign(); } // size: n + 1 limbs_mul_same_length_to_out(&mut scratch_lo[3 * m..], amx, bmx, mul_scratch); let (apx, remainder) = out.split_at_mut(n << 1); let (v_1, bpx) = remainder.split_at_mut(m + 1); // - Clobbers amx, bmx. // - size: n + 1 limbs_mul_same_length_to_out(v_1, &apx[..k], &bpx[..k], mul_scratch); let (v_0, v_inf) = out.split_at_mut(n << 1); // v_0 length: 2 * n let v_inf = &mut v_inf[n << 2..]; // size: n limbs_mul_same_length_to_out(v_0, xs_0, ys_0, mul_scratch); if s > t { // size: s, t limbs_mul_greater_to_out(v_inf, xs_3, ys_3, mul_scratch); } else { // size: s, s limbs_mul_same_length_to_out(v_inf, xs_3, ys_3, mul_scratch); } split_into_chunks_mut!(scratch, m, [v_2, v_neg_2, v_half], remainder); let (v_neg_1, scratch_hi) = remainder.split_at_mut(m + 1); limbs_mul_toom_interpolate_7_points( out, n, s + t, w1_neg, v_neg_2, w3_neg, &mut v_neg_1[..m], v_2, v_half, scratch_hi, ); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_52` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! { limbs_mul_greater_to_out_toom_52_input_sizes_valid(xs_len: usize, ys_len: usize) -> bool { xs_len + 4 < 5 * ys_len && xs_len.shr_round(2, Ceiling).0 > ys_len.shr_round(1, Ceiling).0 && xs_len + ys_len >= 5 * (xs_len.div_round(5, Ceiling).0 + 1) }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_52`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom52_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_mul_greater_to_out_toom_52_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if xs_len << 1 >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) >> 1 }; let s = xs_len - (n << 2); let t = ys_len - n; let m = n + 1; assert!(m < xs_len); 6 * n + 4 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(m), limbs_mul_greater_to_out_scratch_len(m, n), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_52_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - ceiling(`xs`.len() / 4) > ceiling(`ys`.len() / 2) // - `xs`.len() + 4 < 5 * `ys`.len() // - `xs`.len() + `ys`.len() >= 5 * (ceiling(`xs`.len() / 5) + 1) // // Approximately, 2 * `ys`.len() < `xs`.len() < 5 * `ys`.len(). // // The smallest allowable `xs` length is 14. The smallest allowable `ys` length is 5. // // This uses the Toom-52 algorithm. // // Evaluate in: -2, -1, 0, 1, 2, Infinity. // ``` // <-s--><--n--><--n--><--n--><--n--> // _________________________________ // |xs4_|__xs3_|__xs2_|__xs1_|__xs0_| // |ys1|__ys0_| // <-t-><--n--> // // v_0 = xs0 * ys0 # X(0) * Y(0) // v_1 = (xs0 + xs1 + xs2 + xs3 + xs4) * (ys0 + ys1) # X(1) * Y(1) xh <= 4 yh <= 1 // v_neg_1 = (xs0 - xs1 + xs2 - xs3 + xs4) * (ys0 - ys1) # X(-1) * Y(-1) |xh| <= 2 yh = 0 // v_2 = (xs0 + 2xs1 + 4xs2 + 8xs3 + 16xs4) * (ys0 + 2ys1) # X(2) * Y(2) xh <= 30 yh <= 2 // v_neg_2 = (xs0 - 2xs1 + 4xs2 - 8xs3 + 16xs4) * (ys0 - 2ys1) # X(-2) * Y(-2) |xh| <= 20 |yh|<= 1 // v_inf = xs4 * ys1 # X(inf) * Y(inf) // ``` // // Some slight optimization in evaluation are taken from the paper: "Towards Optimal Toom-Cook // Multiplication for Univariate and Multivariate Polynomials in Characteristic 2 and 0." // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_5 6}) \approx O(n^{1.113}), but this function calls // `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom52_mul` from `mpn/generic/toom52_mul.c`, GMP 6.2.1. pub_test! {limbs_mul_greater_to_out_toom_52( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = 1 + if xs_len << 1 >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) >> 1 }; let (ys_0, ys_1) = ys.split_at(n); let t = ys_1.len(); assert_ne!(t, 0); assert!(t <= n); let s = xs_len - (n << 2); assert_ne!(s, 0); assert!(s <= n); // Ensures that 5 values of n + 1 limbs each fits in the product area. Borderline cases are // xs_len = 32, ys_len = 8, n = 7, and xs_len = 36, ys_len = 9, n = 8. assert!(s + t >= 5); // - Scratch need is 6 * n + 4. We need one extra limb, because products will overwrite 2 * n + // 2 limbs. // - Compute as2 and asm2. let mut v_neg_1_neg = false; let m = n + 1; let (scratch, mul_scratch) = scratch.split_at_mut(6 * n + 4); split_into_chunks_mut!(out, m, [bs1, bsm2, bs2, as2, as1], _unused); let (v_neg_1, scratch_hi) = scratch.split_at_mut(m << 1); split_into_chunks_mut!(scratch_hi, m, [bsm1, asm1, asm2], _unused); let bsm1 = &mut bsm1[..n]; let mut v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(as2, asm2, 4, xs, n, asm1); // Compute bs1 and bsm1. let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); *bs1_last = 0; if t == n { if limbs_add_same_length_to_out(bs1_init, ys_0, ys_1) { *bs1_last = 1; } if limbs_cmp_same_length(ys_0, ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, ys_0); v_neg_1_neg = true; } else { limbs_sub_same_length_to_out(bsm1, ys_0, ys_1); } } else { if limbs_add_to_out(bs1_init, ys_0, ys_1) { *bs1_last = 1; } let (ys_0_lo, ys_0_hi) = ys_0.split_at(t); if slice_test_zero(ys_0_hi) && limbs_cmp_same_length(ys_0_lo, ys_1) == Less { let (bsm1_lo, bsm1_hi) = bsm1.split_at_mut(t); limbs_sub_same_length_to_out(bsm1_lo, ys_1, ys_0_lo); slice_set_zero(bsm1_hi); v_neg_1_neg.not_assign(); } else { limbs_sub_greater_to_out(bsm1, ys_0, ys_1); } } // Compute bs2 and bsm2, recycling bs1 and bsm1. bs2 = bs1 + ys_1; bsm2 = bsm1 - ys_1 limbs_add_to_out(bs2, bs1, ys_1); let (bsm2_last, bsm2_init) = bsm2.split_last_mut().unwrap(); *bsm2_last = 0; if v_neg_1_neg { if limbs_add_to_out(bsm2_init, bsm1, ys_1) { *bsm2_last = 1; } v_neg_2_neg.not_assign(); } else if t == n { if limbs_cmp_same_length(bsm1, ys_1) == Less { limbs_sub_same_length_to_out(bsm2_init, ys_1, bsm1); v_neg_2_neg.not_assign(); } else { limbs_sub_same_length_to_out(bsm2_init, bsm1, ys_1); } } else { let (bsm1_lo, bsm1_hi) = bsm1.split_at(t); if slice_test_zero(bsm1_hi) && limbs_cmp_same_length(bsm1_lo, ys_1) == Less { limbs_sub_same_length_to_out(bsm2_init, ys_1, bsm1_lo); slice_set_zero(&mut bsm2_init[t..]); v_neg_2_neg.not_assign(); } else { limbs_sub_greater_to_out(bsm2_init, bsm1, ys_1); } } // Compute as1 and asm1. if limbs_mul_toom_evaluate_poly_in_1_and_neg_1(as1, asm1, 4, xs, n, &mut v_neg_1[..m]) { v_neg_1_neg.not_assign(); } assert!(as1[n] <= 4); assert!(bs1[n] <= 1); assert!(asm1[n] <= 2); assert!(as2[n] <= 30); assert!(bs2[n] <= 2); assert!(asm2[n] <= 20); assert!(*bsm2_last <= 1); // size: m, n limbs_mul_greater_to_out(v_neg_1, asm1, bsm1, mul_scratch); // W4 let k = (n << 1) + 1; let (v_neg_2, asm2) = scratch[k..].split_at_mut(k + 2); // size: m limbs_mul_same_length_to_out(v_neg_2, &asm2[..m], bsm2, mul_scratch); // W2 // size: m limbs_mul_same_length_to_out(&mut scratch[k << 1..], as2, bs2, mul_scratch); // W1 let (bs1, remainder) = out.split_at_mut(n << 1); let (v_1, as1) = remainder.split_at_mut(k + 3); // size: m limbs_mul_same_length_to_out(v_1, &as1[..m], &bs1[..m], mul_scratch); // W3 let (v_0, v_inf) = out.split_at_mut(5 * n); // size: s, t limbs_mul_to_out(v_inf, &xs[n << 2..], ys_1, mul_scratch); // W0 // size: n limbs_mul_same_length_to_out(v_0, &xs[..n], ys_0, mul_scratch); // W5 split_into_chunks_mut!(scratch, k, [v_neg_1, v_neg_2, v_2], _unused); limbs_mul_toom_interpolate_6_points( out, n, s + t, v_neg_1_neg, v_neg_1, v_neg_2_neg, v_neg_2, v_2, ); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_53` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! { limbs_mul_greater_to_out_toom_53_input_sizes_valid(xs_len: usize, ys_len: usize) -> bool { !(xs_len == 16 && ys_len == 9) && xs_len.shr_round(2, Ceiling).0 > ys_len.div_round(3, Ceiling).0 && xs_len.div_round(5, Ceiling).0 < ys_len.shr_round(1, Ceiling).0 }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_53`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom53_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_53_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if 3 * xs_len >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) / 3 }; let s = xs_len - (n << 2); let t = ys_len - (n << 1); let m = n + 1; assert!(m < xs_len); 18 * n + 15 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(m), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_53_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - ceiling(`xs`.len() / 4) > ceiling(`xs`.len() / 3) // - ceiling(`xs`.len() / 5) < ceiling(`ys`.len() / 2) // - (`xs`.len(), `ys`.len()) != (16, 9) // // Approximately, 4 / 3 * `ys`.len() < `xs`.len() < 5 / 2 * `ys`.len(). // // The smallest allowable `xs` length is 5. The smallest allowable `ys` length is 3. // // This uses the Toom-53 algorithm. // // Evaluate in: 0, 1, -1, 2, -2, 1 / 2, Infinity. // ``` // <-s-><--n--><--n--><--n--><--n--> // _________________________________ // |xs4_|__xs3_|__xs2_|__xs1_|__xs0_| // |ys2_|__ys1_|__ys0_| // <-t--><--n--><--n--> // // v_0 = x0 * y0 # X(0) * Y(0) // v_1 = ( x0+ x1+ x2+ x3+ x4) * ( y0+ y1+ y2) # X(1) * Y(1) xh <= 4 yh <= 2 // v_neg_1 = ( x0- x1+ x2- x3+ x4) * ( y0- y1+ y2) # X(-1) * Y(-1) |xh| <= 2 yh <= 1 // v_2 = ( x0+2x1+4x2+8x3+16x4) * ( y0+2y1+4y2) # X(2) * Y(2) xh <= 30 yh <= 6 // v_neg_2 = ( x0-2x1+4x2-8x3+16x4) * ( y0-2y1+4y2) # X(2) * Y(2) -9<=xh<=20 -1<=yh <= 4 // v_half = (16x0+8x1+4x2+2x3+ x4) * (4y0+2y1+ y2) # X(1/2) * Y(1/2) xh <= 30 yh <= 6 // v_inf= x4 * y2 # X(inf) * Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_5 7}) \approx O(n^{1.209}), but this function calls // `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom53_mul` from `mpn/generic/toom53_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_53( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = 1 + if 3 * xs_len >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) / 3 }; split_into_chunks!(xs, n, [xs_0, xs_1, xs_2, xs_3], xs_4); let s = xs_4.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0, ys_1], ys_2); let t = ys_2.len(); assert_ne!(t, 0); assert!(t <= n); let (scratch, mul_scratch) = scratch.split_at_mut(18 * n + 15); let (scratch2, scratch) = scratch.split_at_mut(10 * (n + 1)); split_into_chunks_mut!( scratch2, n + 1, [as1, asm1, as2, asm2, ash, bs1, bsm1, bs2, bsm2, bsh], _unused ); let out_lo = &mut out[..=n]; // Compute as1 and asm1. let mut v_neg_1_neg = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(as1, asm1, 4, xs, n, out_lo); // Compute as2 and asm2. let mut v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(as2, asm2, 4, xs, n, out_lo); // Compute ash = 16 * xs_0 + 8 * xs_1 + 4 * xs_2 + 2 * xs_3 + xs_4 = 2 * (2 * (2 * (2 * xs_0 + // xs_1) + xs_2) + xs_3) + xs_4 let (ash_last, ash_init) = ash.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(ash_init, xs_0, 1); if limbs_slice_add_same_length_in_place_left(ash_init, xs_1) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(ash_init, 1)); if limbs_slice_add_same_length_in_place_left(ash_init, xs_2) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(ash_init, 1)); if limbs_slice_add_same_length_in_place_left(ash_init, xs_3) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(ash_init, 1)); if limbs_slice_add_greater_in_place_left(ash_init, xs_4) { carry.wrapping_add_assign(1); } *ash_last = carry; // Compute bs1 and bsm1. let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); // ys_0 + ys_2 *bs1_last = Limb::from(limbs_add_to_out(bs1_init, ys_0, ys_2)); let (bsm1_last, bsm1_init) = bsm1.split_last_mut().unwrap(); if *bs1_last == 0 && limbs_cmp_same_length(bs1_init, ys_1) == Less { limbs_sub_same_length_to_out(bsm1_init, ys_1, bs1_init); *bsm1_last = 0; v_neg_1_neg.not_assign(); } else { *bsm1_last = *bs1_last; if limbs_sub_same_length_to_out(bsm1_init, bs1_init, ys_1) { bsm1_last.wrapping_sub_assign(1); } } // ys_0 + ys_1 + ys_2 if limbs_slice_add_same_length_in_place_left(bs1_init, ys_1) { bs1_last.wrapping_add_assign(1); } // Compute bs2 and bsm2. let (out_lo_last, out_lo_init) = out_lo.split_last_mut().unwrap(); let carry = limbs_shl_to_out(out_lo_init, ys_2, 2); let (bs2_last, bs2_init) = bs2.split_last_mut().unwrap(); *bs2_last = Limb::from(limbs_add_to_out(bs2_init, ys_0, &out_lo_init[..t])); assert!(!limbs_slice_add_limb_in_place(&mut bs2[t..], carry)); *out_lo_last = limbs_shl_to_out(out_lo_init, ys_1, 1); if limbs_cmp_same_length(bs2, out_lo) == Less { assert!(!limbs_sub_same_length_to_out(bsm2, out_lo, bs2)); v_neg_2_neg.not_assign(); } else { assert!(!limbs_sub_same_length_to_out(bsm2, bs2, out_lo)); } limbs_slice_add_same_length_in_place_left(bs2, out_lo); // Compute bsh = 4 * ys_0 + 2 * ys_1 + ys_2 = 2 * (2 * ys_0 + ys_1) + ys_2. let (bsh_last, bsh_init) = bsh.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(bsh_init, ys_0, 1); if limbs_slice_add_same_length_in_place_left(bsh_init, ys_1) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(bsh_init, 1)); if limbs_slice_add_greater_in_place_left(bsh_init, ys_2) { carry.wrapping_add_assign(1); } *bsh_last = carry; let (as1_last, as1_init) = as1.split_last().unwrap(); let (asm1_last, asm1_init) = asm1.split_last().unwrap(); assert!(*as1_last <= 4); assert!(*bs1_last <= 2); assert!(*asm1_last <= 2); assert!(*bsm1_last <= 1); assert!(as2[n] <= 30); assert!(bs2[n] <= 6); assert!(asm2[n] <= 20); assert!(bsm2[n] <= 4); assert!(*ash_last <= 30); assert!(*bsh_last <= 6); let (v_0, remainder) = out.split_at_mut(n << 1); let (v_1, v_inf) = remainder.split_at_mut(n << 2); // size: n + 1 limbs_mul_same_length_to_out(scratch, as2, bs2, mul_scratch); let m = 2 * n + 1; // size: n + 1 limbs_mul_same_length_to_out(&mut scratch[m..], asm2, bsm2, mul_scratch); // size: n + 1 limbs_mul_same_length_to_out(&mut scratch[m << 1..], ash, bsh, mul_scratch); let v_neg_1 = &mut scratch[3 * m..m << 2]; let (v_neg_1_last, v_neg_1_init) = v_neg_1.split_last_mut().unwrap(); if SMALLER_RECURSION_TOOM_33_AND_53 { // size: n limbs_mul_same_length_to_out(v_neg_1_init, asm1_init, bsm1_init, mul_scratch); let v_neg_1_init = &mut v_neg_1_init[n..]; let mut carry = match *asm1_last { 1 => { let mut carry = *bsm1_last; if limbs_slice_add_same_length_in_place_left(v_neg_1_init, bsm1_init) { carry.wrapping_add_assign(1); } carry } 2 => (*bsm1_last << 1).wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(v_neg_1_init, bsm1_init, 2), ), _ => 0, }; if *bsm1_last != 0 && limbs_slice_add_same_length_in_place_left(v_neg_1_init, asm1_init) { carry.wrapping_add_assign(1); } *v_neg_1_last = carry; // size: n limbs_mul_same_length_to_out(v_1, as1_init, bs1_init, mul_scratch); split_into_chunks_mut!(v_1, n, [_unused, v_1_lo], v_1_hi); let mut carry = match *as1_last { 1 => { let mut carry = *bs1_last; if limbs_slice_add_same_length_in_place_left(v_1_lo, bs1_init) { carry.wrapping_add_assign(1); } carry } 2 => (*bs1_last << 1).wrapping_add(limbs_slice_add_mul_limb_same_length_in_place_left( v_1_lo, bs1_init, 2, )), 0 => 0, _ => { as1_last.wrapping_mul(*bs1_last) + limbs_slice_add_mul_limb_same_length_in_place_left( v_1_lo, bs1_init, *as1_last, ) } }; if *bs1_last == 1 && limbs_slice_add_same_length_in_place_left(v_1_lo, as1_init) { carry.wrapping_add_assign(1); } else if *bs1_last == 2 { carry.wrapping_add_assign(limbs_slice_add_mul_limb_same_length_in_place_left( v_1_lo, as1_init, 2, )); } v_1_hi[0] = carry; } else { fail_on_untested_path("limbs_mul_greater_to_out_toom_53, !SMALLER_RECURSION"); *v_neg_1_last = 0; if (*asm1_last | *bsm1_last) == 0 { // size: n limbs_mul_same_length_to_out(v_neg_1_init, asm1_init, bsm1_init, mul_scratch); } else { // size: n + 1 limbs_mul_same_length_to_out(&mut scratch[3 * m..8 * n + 5], asm1, bsm1, mul_scratch); } v_1[n << 1] = 0; if (*as1_last | *bs1_last) == 0 { // size: n limbs_mul_same_length_to_out(v_1, as1_init, bs1_init, mul_scratch); } else { // size: n + 1 limbs_mul_same_length_to_out(v_1, as1, bs1, mul_scratch); } } // size: n limbs_mul_same_length_to_out(v_0, xs_0, ys_0, mul_scratch); // v_0, 2 * n limbs // size: s, t limbs_mul_to_out(v_inf, xs_4, ys_2, mul_scratch); // v_inf, s + t limbs split_into_chunks_mut!( scratch, m, [v_2, v_neg_2, v_half, v_neg_1], _unused ); limbs_mul_toom_interpolate_7_points( out, n, s + t, v_neg_2_neg, v_neg_2, v_neg_1_neg, v_neg_1, v_2, v_half, scratch2, ); }} // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_54` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_mul_greater_to_out_toom_54_input_sizes_valid( xs_len: usize, ys_len: usize, ) -> bool { xs_len != 0 && xs_len >= ys_len && { let sum = xs_len + ys_len; let n = 1 + if xs_len << 2 >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) >> 2 }; n > 2 && xs_len > n << 2 && xs_len <= 5 * n && ys_len > 3 * n && ys_len <= n << 2 && sum >= n << 3 && sum > 7 * n + 4 } }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_54`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom54_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_mul_greater_to_out_toom_54_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + (if xs_len << 2 >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) >> 2 }); let m = n + 1; assert!(m < xs_len); let s = xs_len - (n << 2); let t = ys_len - 3 * n; 6 * n + 2 + max!( 3 * n + 1, limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(m), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_54_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - Others; see `limbs_mul_greater_to_out_toom_54_input_sizes_valid`. The gist is that 3 times // `xs.len()` must be less than 5 times `ys.len()`. // // This uses the Toom-54 algorithm (the splitting unbalanced version). // // Evaluate in: Infinity, 4, -4, 2, -2, 1, -1, 0. // ``` // <--s-><--n--><--n--><--n--><--n--> // _________________________________ // |xs4_|_xs3__|_xs2__|_xs1__|_xs0__| // |ys3_|_ys2__|_ys1__|_ys0__| // <-t-><--n--><--n--><--n--> // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_5 8}) \approx O(n^{1.292}), but `limbs_mul_same_length_to_out` is // called. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom54_mul` from `mpn/generic/toom54_mul.c`, GMP 6.2.1. #[cfg(feature = "test_build")] pub fn limbs_mul_greater_to_out_toom_54( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); // Decomposition let n = 1 + if xs_len << 2 >= 5 * ys_len { (xs_len - 1) / 5 } else { (ys_len - 1) >> 2 }; assert!(n > 2); let m = n + 1; let a4 = &xs[n << 2..]; let b3 = &ys[3 * n..]; let s = a4.len(); assert_ne!(s, 0); assert!(s <= n); let t = b3.len(); assert_ne!(t, 0); assert!(t <= n); let sum = s + t; assert!(sum >= n); assert!(sum > 4); // Also allocate 3 * `n` + 1 limbs for `scratch_hi`. `limbs_mul_toom_interpolate_8_points` may // need all of them, when `shl_and_sub_same_length` uses a scratch. let (scratch, mul_scratch) = scratch.split_at_mut(6 * n + 2); let (r7, r3) = scratch.split_at_mut(3 * n + 1); let (out_lo, out_hi) = out.split_at_mut(3 * n); split_into_chunks_mut!(out_hi, m, [v0, v1, v2, v3], _unused); // - Evaluation and recursive calls // - 4, -4 let out_lo_lo = &mut out_lo[..m]; let neg_2_pow_sign = limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, 4, xs, n, 2, out_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v3, v1, 3, ys, n, 2, out_lo_lo); // - X(-4) * Y(-4) // - size: m limbs_mul_same_length_to_out(out_lo, v0, v1, mul_scratch); // - X(+4) * Y(+4) // - size: m limbs_mul_same_length_to_out(r3, v2, v3, mul_scratch); limbs_toom_couple_handling(r3, &mut out_lo[..=n << 1], neg_2_pow_sign, n, 2, 4); // 1, -1 let out_lo_lo = &mut out_lo[..m]; let neg_1_sign = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, 4, xs, n, out_lo_lo) != limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(v3, v1, ys, n, out_lo_lo); // - X(-1) * Y(-1) // - size: m limbs_mul_same_length_to_out(out_lo, v0, v1, mul_scratch); // - X(1) * Y(1) // - size: m limbs_mul_same_length_to_out(r7, v2, v3, mul_scratch); limbs_toom_couple_handling(r7, &mut out_lo[..=n << 1], neg_1_sign, n, 0, 0); // 2, -2 let out_lo_lo = &mut out_lo[..m]; let neg_2_sign = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, 4, xs, n, out_lo_lo) != limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2(v3, v1, ys, n, out_lo_lo); // - X(-2) * Y(-2) // - size: m limbs_mul_same_length_to_out(out_lo, v0, v1, mul_scratch); let (r5, remainder) = out[3 * n..].split_at_mut(m << 1); split_into_chunks_mut!(remainder, m, [v2, v3], _unused); // - X(2) * Y(2) // - size: m limbs_mul_same_length_to_out(r5, v2, v3, mul_scratch); let (out_lo, r5) = out.split_at_mut(3 * n); limbs_toom_couple_handling(r5, &mut out_lo[..=n << 1], neg_2_sign, n, 1, 2); // - X(0) * Y(0) // - size: n limbs_mul_same_length_to_out(out, &xs[..n], &ys[..n], mul_scratch); // - Infinity // - size: s, t limbs_mul_to_out(&mut out[7 * n..], a4, b3, mul_scratch); limbs_mul_toom_interpolate_8_points(out, n, sum, r3, r7, mul_scratch); } // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_62` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_mul_greater_to_out_toom_62_input_sizes_valid( xs_len: usize, ys_len: usize, ) -> bool { xs_len != 0 && xs_len >= ys_len && { let n = 1 + if xs_len >= 3 * ys_len { (xs_len - 1) / 6 } else { (ys_len - 1) >> 1 }; xs_len > 5 * n && xs_len <= 6 * n && ys_len > n && ys_len <= n << 1 } }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_62`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom62_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_mul_greater_to_out_toom_62_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if xs_len >= 3 * ys_len { (xs_len - 1) / 6 } else { (ys_len - 1) >> 1 }; let s = xs_len - 5 * n; let t = ys_len - n; let m = n + 1; assert!(m < xs_len); 20 * n + 14 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(m), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_62_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - See `limbs_mul_greater_to_out_toom_62_input_sizes_valid`. The gist is that `xs.len()` must be // less than 6 times `ys.len()`. // // This uses the Toom-62 algorithm. // // Evaluate in: 0, 1, -1, 2, -2, 1 / 2, Infinity. // ``` // <-s-><--n--><--n--><--n--><--n--><--n--> // ________________________________________ // |xs5_|__xs4_|__xs3_|__xs2_|__xs1_|__xs0_| // |ys1_|__ys0_| // <-t--><--n--> // // v_0 = x0 * y0 # X(0) * Y(0) // v_1 = ( x0+ x1+ x2+ x3+ x4+ x5) * ( y0+ y1) # X(1) * Y(1) xh <= 5 yh <= 1 // v_neg_1 = ( x0- x1+ x2- x3+ x4- x5) * ( y0- y1) # X(-1) * Y(-1) |xh|<= 2 yh = 0 // v_2 = ( x0+ 2x1+4x2+8x3+16x4+32x5) * ( y0+2y1) # X(2) * Y(2) xh <= 62 yh <= 2 // v_neg_2 = ( x0- 2x1+4x2-8x3+16x4-32x5) * ( y0-2y1) # X(-2) * Y(-2) -41<=xh <= 20 -1<=yh <= 0 // v_half = (32x0+16x1+8x2+4x3+ 2x4+ x5) * (2y0+ y1) # X(1/2) * Y(1/2) xh <= 62 yh <= 2 // v_inf = x5 * y1 # X(inf) * Y(inf) // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_6 7}) \approx O(n^{1.086}), but this function calls // `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom62_mul` from `mpn/generic/toom62_mul.c`, GMP 6.2.1. pub_test! {limbs_mul_greater_to_out_toom_62( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = 1 + if xs_len >= 3 * ys_len { (xs_len - 1) / 6 } else { (ys_len - 1) >> 1 }; split_into_chunks!(xs, n, [xs_0, xs_1, xs_2, xs_3, xs_4], xs_5); let s = xs_5.len(); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(ys, n, [ys_0], ys_1); let t = ys_1.len(); assert_ne!(t, 0); assert!(t <= n); let m = n + 1; let (scratch, mul_scratch) = scratch.split_at_mut(20 * n + 14); let (scratch2, scratch) = scratch.split_at_mut(10 * n + 9); split_into_chunks_mut!( scratch2, m, [as1, asm1, as2, asm2, ash, bs1, bs2, bsm2, bsh], bsm1 ); // Compute as1 and asm1. let out_lo = &mut out[..m]; let v_neg_1_neg_a = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(as1, asm1, 5, xs, n, out_lo); // Compute as2 and asm2. let v_neg_2_neg_a = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(as2, asm2, 5, xs, n, out_lo); let (ash_last, ash_init) = ash.split_last_mut().unwrap(); // Compute ash = 32 * xs_0 + 16 * xs_1 + 8 * xs_2 + 4 * xs_3 + 2 * xs_4 + xs_5 = 2 * (2 * (2 * // (2 * (2 * xs_0 + xs_1) + xs_2) + xs_3) + xs_4) + xs_5 let mut carry = limbs_shl_to_out(ash_init, xs_0, 1); for xs_i in &[xs_1, xs_2, xs_3, xs_4] { if limbs_slice_add_same_length_in_place_left(ash_init, xs_i) { carry += 1; } carry <<= 1; carry |= limbs_slice_shl_in_place(ash_init, 1); } *ash_last = carry; if limbs_slice_add_greater_in_place_left(ash_init, xs_5) { *ash_last += 1; } // Compute bs1 and bsm1. let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); let v_neg_1_neg_b = if t == n { *bs1_last = Limb::from(limbs_add_same_length_to_out(bs1_init, ys_0, ys_1)); if limbs_cmp_same_length(ys_0, ys_1) == Less { limbs_sub_same_length_to_out(bsm1, ys_1, ys_0); true } else { limbs_sub_same_length_to_out(bsm1, ys_0, ys_1); false } } else { *bs1_last = Limb::from(limbs_add_to_out(bs1_init, ys_0, ys_1)); let (ys_0_lo, ys_0_hi) = ys_0.split_at(t); if slice_test_zero(ys_0_hi) && limbs_cmp_same_length(ys_0_lo, ys_1) == Less { let (bsm1_lo, bsm1_hi) = bsm1.split_at_mut(t); limbs_sub_same_length_to_out(bsm1_lo, ys_1, ys_0_lo); slice_set_zero(bsm1_hi); true } else { limbs_sub_greater_to_out(bsm1, ys_0, ys_1); false } }; // Compute bs2 and bsm2. Recycling bs1 and bsm1: bs2 = bs1 + ys_1, bsm2 = bsm1 - ys_1 limbs_add_to_out(bs2, bs1, ys_1); let v_neg_2_neg_b = if v_neg_1_neg_b { bsm2[n] = Limb::from(limbs_add_to_out(bsm2, bsm1, ys_1)); true } else if t < n { let (bsm1_lo, bsm1_hi) = bsm1.split_at(t); if slice_test_zero(bsm1_hi) && limbs_cmp_same_length(bsm1_lo, ys_1) == Less { let (bsm2_lo, bsm2_hi) = bsm2.split_at_mut(t); assert!(!limbs_sub_same_length_to_out(bsm2_lo, ys_1, bsm1_lo)); slice_set_zero(bsm2_hi); true } else { assert!(!limbs_sub_greater_to_out(bsm2, bsm1, ys_1)); bsm2[n] = 0; false } } else { bsm2[n] = 0; if limbs_cmp_same_length(bsm1, ys_1) == Less { assert!(!limbs_sub_same_length_to_out(bsm2, ys_1, bsm1)); true } else { assert!(!limbs_sub_same_length_to_out(bsm2, bsm1, ys_1)); false } }; // Compute bsh, recycling bs1. bsh = bs1 + ys_0 let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); let (bsh_last, bsh_init) = bsh.split_last_mut().unwrap(); *bsh_last = *bs1_last; if limbs_add_same_length_to_out(bsh_init, bs1_init, ys_0) { bsh_last.wrapping_add_assign(1); } assert!(as1[n] <= 5); assert!(*bs1_last <= 1); assert!(asm1[n] <= 2); assert!(as2[n] <= 62); assert!(bs2[n] <= 2); assert!(asm2[n] <= 41); assert!(bsm2[n] <= 1); assert!(*ash_last <= 62); assert!(*bsh_last <= 2); let (as1_last, as1_init) = as1.split_last_mut().unwrap(); let (asm1_last, asm1_init) = asm1.split_last_mut().unwrap(); let (bs1_last, bs1_init) = bs1.split_last_mut().unwrap(); let p = 2 * n + 1; // size: m limbs_mul_same_length_to_out(scratch, as2, bs2, mul_scratch); // size: m limbs_mul_same_length_to_out(&mut scratch[p..], asm2, bsm2, mul_scratch); // size: m limbs_mul_same_length_to_out(&mut scratch[p << 1..], ash, bsh, mul_scratch); split_into_chunks_mut!( scratch, p, [v_2, v_neg_2, v_half, v_neg_1, scratch_out], _unused ); // size: n limbs_mul_same_length_to_out(v_neg_1, asm1_init, bsm1, mul_scratch); let (v_neg_1_last, v_neg_1_hi) = v_neg_1[n..p].split_last_mut().unwrap(); *v_neg_1_last = if *asm1_last == 2 { limbs_slice_add_mul_limb_same_length_in_place_left(v_neg_1_hi, bsm1, 2) } else { Limb::from( *asm1_last == 1 && limbs_slice_add_same_length_in_place_left(v_neg_1_hi, bsm1), ) }; let (v_0, remainder) = out.split_at_mut(n << 1); let (v_1, v_inf) = remainder.split_at_mut(n << 2); // size: n limbs_mul_same_length_to_out(v_1, as1_init, bs1_init, mul_scratch); let (v_1_last, v_1_hi) = v_1[n..p].split_last_mut().unwrap(); *v_1_last = match *as1_last { 1 => { let mut carry = *bs1_last; if limbs_slice_add_same_length_in_place_left(v_1_hi, bs1_init) { carry.wrapping_add_assign(1); } carry } 2 => bs1_last.arithmetic_checked_shl(1u64).unwrap().wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(v_1_hi, bs1_init, 2), ), 0 => 0, _ => as1_last.wrapping_mul(*bs1_last).wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(v_1_hi, bs1_init, *as1_last), ), }; if *bs1_last != 0 && limbs_slice_add_same_length_in_place_left(v_1_hi, as1_init) { v_1_last.wrapping_add_assign(1); } // size: n limbs_mul_same_length_to_out(v_0, xs_0, ys_0, mul_scratch); // size: s, t limbs_mul_to_out(v_inf, xs_5, ys_1, mul_scratch); limbs_mul_toom_interpolate_7_points( out, n, s + t, v_neg_2_neg_a != v_neg_2_neg_b, v_neg_2, v_neg_1_neg_a != v_neg_1_neg_b, v_neg_1, v_2, v_half, scratch_out, ); }} // Stores |{xs,n}-{ys,n}| in {out,n}, returns the sign. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `abs_sub_n` from `mpn/generic/toom63_mul.c`, GMP 6.2.1. fn limbs_abs_sub_same_length(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let n = xs.len(); assert_eq!(ys.len(), n); for i in (0..n).rev() { let x = xs[i]; let y = ys[i]; if x != y { let n = i + 1; return if x > y { limbs_sub_same_length_to_out(out, &xs[..n], &ys[..n]); false } else { limbs_sub_same_length_to_out(out, &ys[..n], &xs[..n]); true }; } out[i] = 0; } false } // Given the limbs `xs` and `ys` of two integers, writes the limbs of the absolute difference to // `out_diff` and the limbs of the sum to `xs`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `abs_sub_add_n` from `mpn/generic/toom63_mul.c`, GMP 6.2.1. fn limbs_abs_sub_add_same_length(out_diff: &mut [Limb], xs: &mut [Limb], ys: &[Limb]) -> bool { let result = limbs_abs_sub_same_length(out_diff, xs, ys); assert!(!limbs_slice_add_same_length_in_place_left(xs, ys)); result } // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_63` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_mul_greater_to_out_toom_63_input_sizes_valid( xs_len: usize, ys_len: usize, ) -> bool { xs_len != 0 && xs_len >= ys_len && { let sum = xs_len + ys_len; let n = 1 + if xs_len >= ys_len << 1 { (xs_len - 1) / 6 } else { (ys_len - 1) / 3 }; n > 2 && xs_len > 5 * n && xs_len <= 6 * n && ys_len > n << 1 && ys_len <= 3 * n && sum >= n << 3 && sum > 7 * n + 4 } }} // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_63`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom63_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_63_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n = 1 + if xs_len >= ys_len << 1 { (xs_len - 1) / 6 } else { (ys_len - 1) / 3 }; let m = n + 1; assert!(m < xs_len); let s = xs_len - 5 * n; let t = ys_len - (n << 1); 9 * n + 3 + max!( limbs_mul_same_length_to_out_scratch_len(n), limbs_mul_same_length_to_out_scratch_len(m), limbs_mul_to_out_scratch_len(s, t) ) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_63_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - Others; see `limbs_mul_greater_to_out_toom_63_input_sizes_valid`. The gist is that // `xs.len()` must be less than 3 times `ys.len()`. // // This uses the Toom-63 algorithm (aka Toom-4.5, the splitting 6x3 unbalanced version). // // Evaluate in: Infinity, 4, -4, 2, -2, 1, -1, 0. // ``` // <--s-><--n--><--n--><--n--><--n--><--n--> // ________________________________________ // |xs5_|_xs4__|_xs3__|_xs2__|_xs1__|_xs0__| // |ys2_|_ys1__|_ys0__| // <--t-><--n--><--n--> // ``` // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_6 8}) \approx O(n^{1.161}), but // `limbs_mul_same_length_to_out_toom_63_recursive` calls `limbs_mul_same_length_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom63_mul` from `mpn/generic/toom63_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_63( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let n = 1 + if xs_len >= ys_len << 1 { (xs_len - 1) / 6 } else { (ys_len - 1) / 3 }; assert!(n > 2); let m = n + 1; // Decomposition split_into_chunks!(ys, n, [ys_0, ys_1], ys_2); let t = ys_2.len(); assert_ne!(t, 0); assert!(t <= n); let s = xs_len - 5 * n; assert_ne!(s, 0); assert!(s <= n); assert!(s + t >= n); assert!(s + t > 4); // - Also allocate 3 * n + 1 limbs for `scratch2`. `limbs_mul_toom_interpolate_8_points` may // need all of them, when `shl_and_sub_same_length` uses a scratch. // - Evaluation and recursive calls // - 4, -4 let (scratch, mul_scratch) = scratch.split_at_mut(9 * n + 3); split_into_chunks_mut!(scratch, 3 * n + 1, [r7, r3], scratch2); let (r8, remainder) = out.split_at_mut(3 * n); split_into_chunks_mut!(remainder, m, [v0, v1, v2, v3], _unused); let r8_lo = &mut r8[..m]; let mut v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, 5, xs, n, 2, r8_lo); let (r8_lo_last, r8_lo_init) = r8_lo.split_last_mut().unwrap(); *r8_lo_last = limbs_shl_to_out(r8_lo_init, ys_1, 2); // 4 * ys_1 v3[t] = limbs_shl_to_out(v3, ys_2, 4); // 16 * ys_2 let (v3_last, v3_init) = v3.split_last_mut().unwrap(); if n != t { // 16 * ys_2 + ys_0 *v3_last = Limb::from(limbs_add_to_out_aliased(v3_init, t + 1, ys_0)); } else if limbs_slice_add_same_length_in_place_left(v3_init, ys_0) { // 16 * ys_2 + ys_0 *v3_last += 1; } if limbs_abs_sub_add_same_length(v1, v3, r8_lo) { v_neg_2_neg.not_assign(); } // - A(-4) * B(-4) // - size: m limbs_mul_same_length_to_out(r8, v0, v1, mul_scratch); // - A(+4) * B(+4) // - size: m limbs_mul_same_length_to_out(r3, v2, v3, mul_scratch); limbs_toom_couple_handling(r3, &mut r8[..=n<<1], v_neg_2_neg, n, 2, 4); // $pm1$ v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, 5, xs, n, &mut r8[..m]); // Compute bs1 and bsm1. Code taken from toom33 let scratch2_lo = &mut scratch2[..n]; let (v3_last, v3_init) = v3.split_last_mut().unwrap(); *v3_last = 0; let carry = limbs_add_to_out(scratch2_lo, ys_0, ys_2); *v3_last = Limb::from(carry); if limbs_add_same_length_to_out(v3_init, scratch2_lo, ys_1) { *v3_last += 1; } let (v1_last, v1_init) = v1.split_last_mut().unwrap(); if !carry && limbs_cmp_same_length(scratch2_lo, ys_1) == Less { limbs_sub_same_length_to_out(v1_init, ys_1, scratch2_lo); *v1_last = 0; v_neg_2_neg.not_assign(); } else { *v1_last = Limb::from(carry); if limbs_sub_same_length_to_out(v1_init, scratch2_lo, ys_1) { v1_last.wrapping_sub_assign(1); } } // - A(-1) * B(-1) // - size: m limbs_mul_same_length_to_out(r8, v0, v1, mul_scratch); // - A(1) * B(1) // - size: m limbs_mul_same_length_to_out(r7, v2, v3, mul_scratch); limbs_toom_couple_handling(r7, &mut r8[..=n<<1], v_neg_2_neg, n, 0, 0); // 2, -2 let r8_lo = &mut r8[..m]; v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, 5, xs, n, r8_lo); let (r8_lo_last, r8_lo_init) = r8_lo.split_last_mut().unwrap(); *r8_lo_last = limbs_shl_to_out(r8_lo_init, ys_1, 1); // 2 * ys_1 v3[t] = limbs_shl_to_out(v3, ys_2, 2); // 4 * ys_2 if n == t { // 4 * ys_2 + ys_0 let (v3_last, v3_init) = v3.split_last_mut().unwrap(); if limbs_slice_add_same_length_in_place_left(v3_init, ys_0) { v3_last.wrapping_add_assign(1); } } else { // 4 * ys_2 + ys_0 v3[n] = Limb::from(limbs_add_to_out_aliased(v3, t + 1, ys_0)); } if limbs_abs_sub_add_same_length(v1, v3, &r8[..m]) { v_neg_2_neg.not_assign(); } // - A(-2) * B(-2) // - size: m limbs_mul_same_length_to_out(r8, v0, v1, mul_scratch); let (r8, r5) = out.split_at_mut(3 * n); let (r5_lo, remainder) = r5.split_at_mut(m << 1); split_into_chunks_mut!(remainder, m, [v2, v3], _unused); // - A(2) * B(2) // - size: m limbs_mul_same_length_to_out(r5_lo, v2, v3, mul_scratch); limbs_toom_couple_handling(r5, &mut r8[..=n<<1], v_neg_2_neg, n, 1, 2); // - A(0) * B(0) // - size: n limbs_mul_same_length_to_out(r8, &xs[..n], &ys[..n], mul_scratch); // Infinity let xs_5 = &xs[5 * n..]; let r1 = &mut out[7 * n..]; // size: s, t limbs_mul_to_out(r1, xs_5, ys_2, mul_scratch); limbs_mul_toom_interpolate_8_points(out, n, s + t, r3, r7, scratch2); }} // - The limit is a rational number between (12 / 11) ^ (log(4) / log(2 * 4 - 1)) and // - (12 / 11) ^ (log(6) / log(2 * 6 - 1)) const TOOM_6H_LIMIT_NUMERATOR: usize = 18; const TOOM_6H_LIMIT_DENOMINATOR: usize = 17; // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_6h` are valid. // // # Worst-case complexity // Constant time and additional memory. pub_test! {limbs_mul_greater_to_out_toom_6h_input_sizes_valid( xs_len: usize, ys_len: usize ) -> bool { if xs_len == 0 || xs_len < ys_len || ys_len < 42 || xs_len * 3 >= ys_len << 3 && (ys_len < 46 || xs_len * 6 >= ys_len * 17) { return false; } let n; let mut half = false; let mut xl = xs_len; let mut yl = ys_len; let (xr, yr) = if xs_len * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * ys_len { // xs.len() < 18 / 17 * ys.len() n = 1 + (xs_len - 1) / 6; let n5 = 5 * n; (n5, n5) } else { let (p, q) = if xs_len * 5 * TOOM_6H_LIMIT_NUMERATOR < TOOM_6H_LIMIT_DENOMINATOR * 7 * ys_len { (7, 6) // xs.len() < 119 / 90 * ys.len() } else if xs_len * 5 * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * 7 * ys_len { (7, 5) // xs.len() < 126 / 85 * ys.len() } else if xs_len * TOOM_6H_LIMIT_NUMERATOR < (TOOM_6H_LIMIT_DENOMINATOR * ys_len) << 1 { (8, 5) // xs.len() < 17 / 9 * ys.len() } else if xs_len * TOOM_6H_LIMIT_DENOMINATOR < (TOOM_6H_LIMIT_NUMERATOR * ys_len) << 1 { (8, 4) // xs.len() < 36 / 17 * ys.len() } else { (9, 4) // xs.len() >= 36 / 17 * ys.len() }; // With LIMIT = 16 / 15, the following recovery is needed only if `ys_len` <= 73. n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; let pn = (p - 1) * n; let qn = (q - 1) * n; if !p.eq_mod_power_of_2(q, 1) { // Recover from-badly chosen splitting if xs_len <= pn { xl += n; } else if ys_len <= qn { yl += n; } else { half = true; } } (pn, qn) }; xl > xr && yl > yr && { let (s, t) = (xl - xr, yl - yr); let limit = 12 * n + 6; s <= n && t <= n && (half || s + t > 3) && n > 2 && limit <= limbs_mul_greater_to_out_toom_6h_scratch_len(xs_len, ys_len) && limit <= limbs_square_to_out_toom_6_scratch_len(n * 6) } }} // TODO tune const TOOM_6H_MAYBE_MUL_BASECASE: bool = TUNE_PROGRAM_BUILD || MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM22_THRESHOLD; // TODO tune const TOOM_6H_MAYBE_MUL_TOOM22: bool = TUNE_PROGRAM_BUILD || MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM33_THRESHOLD; const TOOM_6H_MAYBE_MUL_TOOM33: bool = TUNE_PROGRAM_BUILD || MUL_TOOM6H_THRESHOLD < 6usize.saturating_mul(MUL_TOOM44_THRESHOLD); const TOOM_6H_MAYBE_MUL_TOOM6H: bool = TUNE_PROGRAM_BUILD || MUL_FFT_THRESHOLD >= 6 * MUL_TOOM6H_THRESHOLD; fn limbs_mul_same_length_to_out_toom_6h_recursive_scratch_len(n: usize) -> usize { if TOOM_6H_MAYBE_MUL_BASECASE && n < MUL_TOOM22_THRESHOLD { 0 } else if TOOM_6H_MAYBE_MUL_TOOM22 && n < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22_scratch_len(n, n) } else if TOOM_6H_MAYBE_MUL_TOOM33 && n < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33_scratch_len(n, n) } else if !TOOM_6H_MAYBE_MUL_TOOM6H || n < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44_scratch_len(n, n) } else { limbs_mul_greater_to_out_toom_6h_scratch_len(n, n) } } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM6H_MUL_N_REC` from `mpn/generic/toom6h_mul.c`, GMP 6.2.1, when `f` is // false. fn limbs_mul_same_length_to_out_toom_6h_recursive( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let n = xs.len(); assert_eq!(ys.len(), n); if TOOM_6H_MAYBE_MUL_BASECASE && n < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if TOOM_6H_MAYBE_MUL_TOOM22 && n < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if TOOM_6H_MAYBE_MUL_TOOM33 && n < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if !TOOM_6H_MAYBE_MUL_TOOM6H || n < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } } // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_6h`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom6h_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_6h_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n; let mut half = false; let (pn, qn) = if xs_len * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * ys_len { // - xs.len() < 18 / 17 * ys.len() // - This is the slowest variation n = 1 + (xs_len - 1) / 6; let n5 = 5 * n; (n5, n5) } else { let (mut p, mut q) = if xs_len * 5 * TOOM_6H_LIMIT_NUMERATOR < TOOM_6H_LIMIT_DENOMINATOR * 7 * ys_len { // xs.len() < 119 / 90 * ys.len(), half (7, 6) } else if xs_len * 5 * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * 7 * ys_len { // xs.len() < 126 / 85 * ys.len(), !half (7, 5) } else if xs_len * TOOM_6H_LIMIT_NUMERATOR < (TOOM_6H_LIMIT_DENOMINATOR * ys_len) << 1 { // xs.len() < 17 / 9 * ys.len(), half (8, 5) } else if xs_len * TOOM_6H_LIMIT_DENOMINATOR < (TOOM_6H_LIMIT_NUMERATOR * ys_len) << 1 { // xs.len() < 36 / 17 * ys.len(), !half (8, 4) } else { // xs.len() >= 36 / 17 * ys.len(), half (9, 4) }; n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; p -= 1; q -= 1; let mut pn = p * n; let mut qn = q * n; // With LIMIT = 16 / 15, the following recovery is needed only if `ys_len` <= 73. if !p.eq_mod_power_of_2(q, 1) { // Recover from badly-chosen splitting if xs_len <= pn { pn -= n; } else if ys_len <= qn { qn -= n; } else { half = true; } } (pn, qn) }; let m = n + 1; assert!(m < xs_len); let s = xs_len - pn; let t = ys_len - qn; let mut mul_scratch_len = max!( 3 * n - 1, limbs_mul_same_length_to_out_toom_6h_recursive_scratch_len(n), limbs_mul_same_length_to_out_toom_6h_recursive_scratch_len(m) ); if half { mul_scratch_len = max(mul_scratch_len, limbs_mul_to_out_scratch_len(s, t)); } 10 * n + 4 + mul_scratch_len }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_6h_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - Others; see `limbs_mul_greater_to_out_toom_6h_input_sizes_valid`. // // This uses the Toom-6h algorithm (Toom-6.5). // // Evaluate in: Infinity, 4, -4, 2, -2, 1, -1, 1 / 2, -1 / 2, 1 / 4, -1 / 4, 0. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_5 11}) \approx O(n^{1.490}) (assuming worst-possible splitting), but // `limbs_mul_same_length_to_out_toom_6h_recursive` ultimately calls `limbs_mul_greater_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom6h_mul` from `mpn/generic/toom6h_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_6h( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); // - Decomposition // - Can not handle too much unbalance assert!(ys_len >= 42); assert!(xs_len * 3 < ys_len << 3 || ys_len >= 46 && xs_len * 6 < ys_len * 17); let n; let mut half = false; let (p, q, pn, qn) = if xs_len * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * ys_len { // - xs.len() < 18 / 17 * ys.len() // - This is the slowest variation n = 1 + (xs_len - 1) / 6; let n5 = 5 * n; (5, 5, n5, n5) } else { let (mut p, mut q) = if xs_len * 5 * TOOM_6H_LIMIT_NUMERATOR < TOOM_6H_LIMIT_DENOMINATOR * 7 * ys_len { // xs.len() < 119 / 90 * ys.len(), half (7, 6) } else if xs_len * 5 * TOOM_6H_LIMIT_DENOMINATOR < TOOM_6H_LIMIT_NUMERATOR * 7 * ys_len { // xs.len() < 126 / 85 * ys.len(), !half (7, 5) } else if xs_len * TOOM_6H_LIMIT_NUMERATOR < (TOOM_6H_LIMIT_DENOMINATOR * ys_len) << 1 { // xs.len() < 17 / 9 * ys.len(), half (8, 5) } else if xs_len * TOOM_6H_LIMIT_DENOMINATOR < (TOOM_6H_LIMIT_NUMERATOR * ys_len) << 1 { // xs.len() < 36 / 17 * ys.len(), !half (8, 4) } else { // xs.len() >= 36 / 17 * ys.len(), half (9, 4) }; n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; p -= 1; q -= 1; let mut pn = p * n; let mut qn = q * n; // With LIMIT = 16 / 15, the following recovery is needed only if `ys_len` <= 73. if !p.eq_mod_power_of_2(q, 1) { // Recover from badly-chosen splitting if xs_len <= pn { p -= 1; pn -= n; } else if ys_len <= qn { q -= 1; qn -= n; } else { half = true; } } (p, q, pn, qn) }; assert!(n > 2); assert!(xs_len > pn); let s = xs_len - pn; assert!(s <= n); assert!(ys_len > qn); let t = ys_len - qn; assert!(t <= n); assert!(half || s + t > 3); let m = n + 1; // r == 2 * n + 1 let r = m + n; split_into_chunks_mut!(scratch, 3 * n + 1, [r5, r3, r1], scratch2); let (out_lo, remainder) = out.split_at_mut(3 * n); let (r4, remainder) = remainder.split_at_mut(n << 2); split_into_chunks_mut!(remainder, m, [v0, v1, v2], _unused); let (v3, mul_scratch) = scratch2.split_at_mut(m); // - Evaluation and recursive calls // - 1/2, -1/2 let out_lo_lo = &mut out_lo[..m]; let v_neg_half_neg = limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg(v2, v0, p, xs, n, 1, out_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v3, v1, q, ys, n, 1, out_lo_lo, ); // - X(-1/2) * Y(-1/2) * 2^ // - X(1/2) * Y(1/2) * 2^ // - size: m limbs_mul_same_length_to_out_toom_6h_recursive(out_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_6h_recursive(r5, v2, v3, mul_scratch); if half { limbs_toom_couple_handling(r5, &mut out_lo[..r], v_neg_half_neg, n, 2, 1); } else { limbs_toom_couple_handling(r5, &mut out_lo[..r], v_neg_half_neg, n, 1, 0); } // 1, -1 let out_lo_lo = &mut out_lo[..m]; let mut v_neg_1_neg = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, p, xs, n, out_lo_lo); let flip = if q == 3 { limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(v3, v1, ys, n, out_lo_lo) } else { limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v3, v1, q, ys, n, out_lo_lo) }; if flip { v_neg_1_neg.not_assign(); } // - X(-1) * Y(-1) // - X(1) * Y(1) // - size: m limbs_mul_same_length_to_out_toom_6h_recursive(out_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_6h_recursive(r3, v2, v3, mul_scratch); limbs_toom_couple_handling(r3, &mut out_lo[..r], v_neg_1_neg, n, 0, 0); // 4, -4 let out_lo_lo = &mut out_lo[..m]; let v_neg_4_neg = limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, p, xs, n, 2, out_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v3, v1, q, ys, n, 2, out_lo_lo); // - X(-4) * Y(-4) // - size: m limbs_mul_same_length_to_out_toom_6h_recursive(out_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_6h_recursive(r1, v2, v3, mul_scratch); // X(4) * B(4) limbs_toom_couple_handling(r1, &mut out_lo[..r], v_neg_4_neg, n, 2, 4); // 1/4, -1/4 let out_lo_lo = &mut out_lo[..m]; let v_neg_quarter_neg = limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg(v2, v0, p, xs, n, 2, out_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v3, v1, q, ys, n, 2, out_lo_lo, ); // - X(-1/4) * Y(-1/4) * 4^ // - X(1/4) * Y(1/4) * 4^ // - size: m limbs_mul_same_length_to_out_toom_6h_recursive(out_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_6h_recursive(r4, v2, v3, mul_scratch); if half { limbs_toom_couple_handling(r4, &mut out_lo[..r], v_neg_quarter_neg, n, 4, 2); } else { limbs_toom_couple_handling(r4, &mut out_lo[..r], v_neg_quarter_neg, n, 2, 0); } let out_lo = &mut out_lo[..m]; // 2, -2 let v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, p, xs, n, out_lo) != limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v3, v1, q, ys, n, out_lo); // - X(-2) * Y(-2) // - X(2) * Y(2) let (out_lo, r2) = out.split_at_mut(7 * n); let (r2_v1, v2) = r2.split_at_mut(m << 1); let v2 = &mut v2[..m]; { let (r2, v1) = r2_v1.split_at_mut(m); // size: m limbs_mul_same_length_to_out_toom_6h_recursive(out_lo, r2, v1, mul_scratch); } // size: m limbs_mul_same_length_to_out_toom_6h_recursive(r2_v1, v2, v3, mul_scratch); limbs_toom_couple_handling(r2, &mut out_lo[..r], v_neg_2_neg, n, 1, 2); // - X(0) * Y(0) // - size: n limbs_mul_same_length_to_out_toom_6h_recursive(out, &xs[..n], &ys[..n], mul_scratch); // Infinity if half { // size: s, t limbs_mul_to_out(&mut out[11 * n..], &xs[pn..], &ys[qn..], mul_scratch); } limbs_mul_toom_interpolate_12_points(out, r1, r3, r5, n, s + t, half, scratch2); }} // Limit num/den is a rational number between (16 / 15) ^ (log(6) / log(2 * 6 - 1)) and (16 / 15) ^ // (log(8) / log(2 * 8 - 1)) const TOOM_8H_LIMIT_NUMERATOR: usize = 21; const TOOM_8H_LIMIT_DENOMINATOR: usize = 20; // # Worst-case complexity // Constant time and additional memory. // // This function can be used to determine whether the sizes of the input slices to // `limbs_mul_greater_to_out_toom_8h` are valid. pub_test! {limbs_mul_greater_to_out_toom_8h_input_sizes_valid( xs_len: usize, ys_len: usize ) -> bool { if xs_len == 0 || ys_len < 86 || xs_len < ys_len || xs_len > ys_len << 2 || Limb::WIDTH <= 11 * 3 && xs_len << 2 > ys_len * 11 || Limb::WIDTH <= 10 * 3 && xs_len > ys_len << 1 || Limb::WIDTH <= 9 * 3 && xs_len << 1 > ys_len * 3 { return false; } let n; let mut half = false; let mut xl = xs_len; let mut yl = ys_len; let (xr, yr) = if xs_len == ys_len || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < TOOM_8H_LIMIT_NUMERATOR * (ys_len >> 1) { // - xs_len == ys_len || xs_len < 21 / 20 * ys_len, !half // - This is the slowest variation n = 1 + ((xs_len - 1) >> 3); let n7 = 7 * n; (n7, n7) } else { let (p, q) = if xs_len * 13 < ys_len << 4 { // xs_len < 16 / 13 * ys_len, half (9, 8) } else if Limb::WIDTH <= 9 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < (TOOM_8H_LIMIT_NUMERATOR / 7 * 9) * (ys_len >> 1) { // Limb::WIDTH <= 27 || xs_len < 27 / 20 * ys_len, !half (9, 7) } else if xs_len * 10 < 33 * (ys_len >> 1) { // xs_len < 33 / 20 * ys_len, half (10, 7) } else if Limb::WIDTH <= 10 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR / 5) < (TOOM_8H_LIMIT_NUMERATOR / 3) * ys_len { // Limb::WIDTH <= 30 || xs_len < 7 / 4 * ys_len, !half (10, 6) } else if xs_len * 6 < 13 * ys_len { // xs_len < 13 / 6 * ys_len, half (11, 6) } else if Limb::WIDTH <= 11 * 3 || xs_len << 2 < 9 * ys_len { // Limb::WIDTH <= 33 || xs_len < 9 / 4 * ys_len, !half (11, 5) } else if xs_len * (TOOM_8H_LIMIT_NUMERATOR / 3) < TOOM_8H_LIMIT_DENOMINATOR * ys_len { // xs_len < 20 / 7 * ys_len, half (12, 5) } else if Limb::WIDTH <= 12 * 3 || xs_len * 9 < 28 * ys_len { // Limb::WIDTH <= 36 || xs_len < 28 / 9 * ys_len, !half (12, 4) } else { // half (13, 4) }; n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; let pn = (p - 1) * n; let qn = (q - 1) * n; if !p.eq_mod_power_of_2(q, 1) { // Recover from badly chosen splitting if xs_len <= pn { xl += n; } else if ys_len <= qn { yl += n; } else { half = true; } } (pn, qn) }; xl > xr && yl > yr && { let (s, t) = (xl - xr, yl - yr); let limit = 15 * n + 6; s <= n && t <= n && (half || s + t > 3) && n > 2 && limit <= limbs_mul_greater_to_out_toom_8h_scratch_len(xs_len, ys_len) && limit <= limbs_square_to_out_toom_8_scratch_len(n << 3) } }} #[cfg(feature = "32_bit_limbs")] pub(crate) const BIT_CORRECTION: bool = true; #[cfg(not(feature = "32_bit_limbs"))] pub(crate) const BIT_CORRECTION: bool = false; // TODO tune const TOOM_8H_MAYBE_MUL_BASECASE: bool = TUNE_PROGRAM_BUILD || MUL_TOOM8H_THRESHOLD < MUL_TOOM22_THRESHOLD << 3; // TODO tune const TOOM_8H_MAYBE_MUL_TOOM22: bool = TUNE_PROGRAM_BUILD || MUL_TOOM8H_THRESHOLD < MUL_TOOM33_THRESHOLD << 3; // TODO tune const TOOM_8H_MAYBE_MUL_TOOM33: bool = TUNE_PROGRAM_BUILD || MUL_TOOM8H_THRESHOLD < MUL_TOOM44_THRESHOLD << 3; // TODO tune const TOOM_8H_MAYBE_MUL_TOOM44: bool = TUNE_PROGRAM_BUILD || MUL_TOOM8H_THRESHOLD < MUL_TOOM6H_THRESHOLD << 3; // TODO tune const TOOM_8H_MAYBE_MUL_TOOM8H: bool = TUNE_PROGRAM_BUILD || MUL_FFT_THRESHOLD >= MUL_TOOM8H_THRESHOLD << 3; fn limbs_mul_same_length_to_out_toom_8h_recursive_scratch_len(n: usize) -> usize { if TOOM_8H_MAYBE_MUL_BASECASE && n < MUL_TOOM22_THRESHOLD { 0 } else if TOOM_8H_MAYBE_MUL_TOOM22 && n < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22_scratch_len(n, n) } else if TOOM_8H_MAYBE_MUL_TOOM33 && n < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33_scratch_len(n, n) } else if TOOM_8H_MAYBE_MUL_TOOM44 && n < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44_scratch_len(n, n) } else if !TOOM_8H_MAYBE_MUL_TOOM8H || n < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h_scratch_len(n, n) } else { limbs_mul_greater_to_out_toom_8h_scratch_len(n, n) } } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_7 15}) \approx O(n^{1.392}), but // `limbs_mul_same_length_to_out_toom_22` ultimately calls `limbs_mul_greater_to_out`. // // This is equivalent to `TOOM8H_MUL_N_REC` from `mpn/generic/toom8h_mul.c`, GMP 6.2.1, when `f` is // false. fn limbs_mul_same_length_to_out_toom_8h_recursive( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let n = xs.len(); assert_eq!(ys.len(), n); if TOOM_8H_MAYBE_MUL_BASECASE && n < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if TOOM_8H_MAYBE_MUL_TOOM22 && n < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if TOOM_8H_MAYBE_MUL_TOOM33 && n < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if TOOM_8H_MAYBE_MUL_TOOM44 && n < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else if !TOOM_8H_MAYBE_MUL_TOOM8H || n < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_8h(out, xs, ys, scratch); } } // This function can be used to determine the length of the input `scratch` slice in // `limbs_mul_greater_to_out_toom_8h`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom8h_mul_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_8h_scratch_len( xs_len: usize, ys_len: usize ) -> usize { let n; let mut half = false; let (pn, qn) = if xs_len == ys_len || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < TOOM_8H_LIMIT_NUMERATOR * (ys_len >> 1) { // - xs_len == ys_len || xs_len < 21 / 20 * ys_len, !half // - This is the slowest variation n = 1 + ((xs_len - 1) >> 3); let n7 = 7 * n; (n7, n7) } else { let (mut p, mut q) = if xs_len * 13 < ys_len << 4 { // xs_len < 16 / 13 * ys_len, half (9, 8) } else if Limb::WIDTH <= 9 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < (TOOM_8H_LIMIT_NUMERATOR / 7 * 9) * (ys_len >> 1) { // Limb::WIDTH <= 27 || xs_len < 27 / 20 * ys_len, !half (9, 7) } else if xs_len * 10 < 33 * (ys_len >> 1) { // xs_len < 33 / 20 * ys_len, half (10, 7) } else if Limb::WIDTH <= 10 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR / 5) < (TOOM_8H_LIMIT_NUMERATOR / 3) * ys_len { // Limb::WIDTH <= 30 || xs_len < 7 / 4 * ys_len, !half (10, 6) } else if xs_len * 6 < 13 * ys_len { // xs_len < 13 / 6 * ys_len, half (11, 6) } else if Limb::WIDTH <= 11 * 3 || xs_len << 2 < 9 * ys_len { // Limb::WIDTH <= 33 || xs_len < 9 / 4 * ys_len, !half (11, 5) } else if xs_len * (TOOM_8H_LIMIT_NUMERATOR / 3) < TOOM_8H_LIMIT_DENOMINATOR * ys_len { // xs_len < 20 / 7 * ys_len, half (12, 5) } else if Limb::WIDTH <= 12 * 3 || xs_len * 9 < 28 * ys_len { // Limb::WIDTH <= 36 || xs_len < 28 / 9 * ys_len, !half (12, 4) } else { // half (13, 4) }; n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; p -= 1; q -= 1; let mut pn = p * n; let mut qn = q * n; if !p.eq_mod_power_of_2(q, 1) { // Recover from badly chosen splitting if xs_len <= pn { pn -= n; } else if ys_len <= qn { qn -= n; } else { half = true; } } (pn, qn) }; let s = xs_len - pn; let t = ys_len - qn; let m = n + 1; assert!(m < xs_len); let mut mul_scratch_len = max!( 3 * n + 1, limbs_mul_same_length_to_out_toom_8h_recursive_scratch_len(n), limbs_mul_same_length_to_out_toom_8h_recursive_scratch_len(m) ); if half { mul_scratch_len = max(mul_scratch_len, limbs_mul_to_out_scratch_len(s, t)); } 13 * n + 5 + mul_scratch_len }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the `xs.len() + ys.len()` least-significant limbs of the product of the `Natural`s to an output // slice. A scratch slice is provided for the algorithm to use. An upper bound for the number of // scratch limbs needed is provided by `limbs_mul_greater_to_out_toom_8h_scratch_len`. The following // restrictions on the input slices must be met: // - `out`.len() >= `xs`.len() + `ys`.len() // - `xs`.len() >= `ys`.len() // - Others; see `limbs_mul_greater_to_out_toom_8h_input_sizes_valid`. // // This uses the Toom-8h algorithm (Toom-8.5). // // Evaluate in: Infinity, 8, -8, 4, -4, 2, -2, 1, -1, 1 / 2, -1 / 2, 1 / 4, -1 / 4, 1 / 8, -1 / 8, // 0. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // The time would be O(n^{\log_7 15}) \approx O(n^{1.392}), but // `limbs_mul_same_length_to_out_toom_8h_recursive` ultimately calls `limbs_mul_greater_to_out`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom8h_mul` from `mpn/generic/toom8h_mul.c`, GMP 6.2.1. pub_crate_test! {limbs_mul_greater_to_out_toom_8h( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); // - Decomposition // - Can not handle too small operands assert!(ys_len >= 86); // Can not handle too much unbalance assert!(xs_len <= ys_len << 2); assert!(Limb::WIDTH > 11 * 3 || xs_len << 2 <= ys_len * 11); assert!(Limb::WIDTH > 10 * 3 || xs_len <= ys_len << 1); assert!(Limb::WIDTH > 9 * 3 || xs_len << 1 <= ys_len * 3); let n; let mut half = false; let (p, q, pn, qn) = if xs_len == ys_len || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < TOOM_8H_LIMIT_NUMERATOR * (ys_len >> 1) { // - xs_len == ys_len || xs_len < 21 / 20 * ys_len, !half // - This is the slowest variation n = 1 + ((xs_len - 1) >> 3); let n7 = 7 * n; (7, 7, n7, n7) } else { let (mut p, mut q) = if xs_len * 13 < ys_len << 4 { // xs_len < 16 / 13 * ys_len, half (9, 8) } else if Limb::WIDTH <= 9 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < (TOOM_8H_LIMIT_NUMERATOR / 7 * 9) * (ys_len >> 1) { // Limb::WIDTH <= 27 || xs_len < 27 / 20 * ys_len, !half (9, 7) } else if xs_len * 10 < 33 * (ys_len >> 1) { // xs_len < 33 / 20 * ys_len, half (10, 7) } else if Limb::WIDTH <= 10 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR / 5) < (TOOM_8H_LIMIT_NUMERATOR / 3) * ys_len { // Limb::WIDTH <= 30 || xs_len < 7 / 4 * ys_len, !half (10, 6) } else if xs_len * 6 < 13 * ys_len { // xs_len < 13 / 6 * ys_len, half (11, 6) } else if Limb::WIDTH <= 11 * 3 || xs_len << 2 < 9 * ys_len { // Limb::WIDTH <= 33 || xs_len < 9 / 4 * ys_len, !half (11, 5) } else if xs_len * (TOOM_8H_LIMIT_NUMERATOR / 3) < TOOM_8H_LIMIT_DENOMINATOR * ys_len { // xs_len < 20 / 7 * ys_len, half (12, 5) } else if Limb::WIDTH <= 12 * 3 || xs_len * 9 < 28 * ys_len { // Limb::WIDTH <= 36 || xs_len < 28 / 9 * ys_len, !half (12, 4) } else { // half (13, 4) }; n = 1 + if q * xs_len >= p * ys_len { (xs_len - 1) / p } else { (ys_len - 1) / q }; p -= 1; q -= 1; let mut pn = p * n; let mut qn = q * n; if !p.eq_mod_power_of_2(q, 1) { // Recover from badly chosen splitting if xs_len <= pn { p -= 1; pn -= n; } else if ys_len <= qn { q -= 1; qn -= n; } else { half = true; } } (p, q, pn, qn) }; assert!(n > 2); assert!(xs_len > pn); let s = xs_len - pn; assert!(s <= n); assert!(ys_len > qn); let t = ys_len - qn; assert!(t <= n); assert!(half || s + t > 3); let m = n + 1; let u = m + n; // 2 * n + 1 let r = 3 * n + 1; // Evaluation and recursive calls let (pp_lo, remainder) = out.split_at_mut(3 * n); split_into_chunks_mut!(remainder, n << 2, [r6, r4], remainder); split_into_chunks_mut!(remainder, m, [v0, v1, v2], _unused); let (r7, remainder) = scratch.split_at_mut(r); let (v3, mul_scratch) = remainder[3 * r..].split_at_mut(m); // 1/8, -1/8 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_8th_neg = limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg(v2, v0, p, xs, n, 3, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v3, v1, q, ys, n, 3, pp_lo_lo, ); // - X(-1/8) * Y(-1/8) * 8^ // - X(1/8) * Y(1/8) * 8^ // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r7, v2, v3, mul_scratch); let limit = if BIT_CORRECTION { m << 1 } else { u }; let pp_lo_lo = &mut pp_lo[..limit]; if half { limbs_toom_couple_handling(scratch, pp_lo_lo, v_neg_8th_neg, n, 6, 3); } else { limbs_toom_couple_handling(scratch, pp_lo_lo, v_neg_8th_neg, n, 3, 0); } split_into_chunks_mut!(scratch, r, [_unused, r5, r3, r1], remainder); let (v3, mul_scratch) = remainder.split_at_mut(m); // 1/4, -1/4 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_quarter_neg = limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg(v2, v0, p, xs, n, 2, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v3, v1, q, ys, n, 2, pp_lo_lo, ); // - X(-1/4) * Y(-1/4) * 4^ // - X(1/4) * Y(1/4) * 4^ // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r5, v2, v3, mul_scratch); let pp_lo_lo = &mut pp_lo[..u]; if half { limbs_toom_couple_handling(r5, pp_lo_lo, v_neg_quarter_neg, n, 4, 2); } else { limbs_toom_couple_handling(r5, pp_lo_lo, v_neg_quarter_neg, n, 2, 0); } // 2, -2 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_2_neg = limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, p, xs, n, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v3, v1, q, ys, n, pp_lo_lo); // - X(-2) * Y(-2) // - X(2) * Y(2) // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r3, v2, v3, mul_scratch); limbs_toom_couple_handling(r3, &mut pp_lo[..u], v_neg_2_neg, n, 1, 2); // 8, -8 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_8_neg = limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, p, xs, n, 3, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v3, v1, q, ys, n, 3, pp_lo_lo); // - X(-8) * Y(-8) // - X(8) * Y(8) // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r1, v2, v3, mul_scratch); limbs_toom_couple_handling( &mut scratch[3 * r..], &mut pp_lo[..limit], v_neg_8_neg, n, 3, 6, ); let (v3, mul_scratch) = scratch[r << 2..].split_at_mut(m); // 1/2, -1/2 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_half_neg = limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg(v2, v0, p, xs, n, 1, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v3, v1, q, ys, n, 1, pp_lo_lo, ); // - X(-1/2) * Y(-1/2) * 2^ // - X(1/2) * Y(1/2) * 2^ // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r6, v2, v3, mul_scratch); let pp_lo_lo = &mut pp_lo[..u]; if half { limbs_toom_couple_handling(r6, pp_lo_lo, v_neg_half_neg, n, 2, 1); } else { limbs_toom_couple_handling(r6, pp_lo_lo, v_neg_half_neg, n, 1, 0); } // 1, -1 let pp_lo_lo = &mut pp_lo[..m]; let mut v_neg_1_neg = limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, p, xs, n, pp_lo_lo); if if Limb::WIDTH > 36 && q == 3 { limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(v3, v1, ys, n, pp_lo_lo) } else { limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v3, v1, q, ys, n, pp_lo_lo) } { v_neg_1_neg.not_assign(); } // - X(-1) * Y(-1) // - X(1) * Y(1) // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r4, v2, v3, mul_scratch); limbs_toom_couple_handling(r4, &mut pp_lo[..u], v_neg_1_neg, n, 0, 0); // 4, -4 let pp_lo_lo = &mut pp_lo[..m]; let v_neg_4_neg = limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, p, xs, n, 2, pp_lo_lo) != limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v3, v1, q, ys, n, 2, pp_lo_lo); // - X(-4) * Y(-4) // - X(4) * Y(4) // - size: m limbs_mul_same_length_to_out_toom_8h_recursive(pp_lo, v0, v1, mul_scratch); split_into_chunks_mut!(scratch, r, [r7, r5, r3, r1], mul_scratch); let (v3, mul_scratch) = mul_scratch.split_at_mut(m); let (r2, v2) = out[11 * n..].split_at_mut(m << 1); // size: m limbs_mul_same_length_to_out_toom_8h_recursive(r2, &v2[..m], v3, mul_scratch); let (pp_lo, r2) = out.split_at_mut(11 * n); limbs_toom_couple_handling(r2, &mut pp_lo[..u], v_neg_4_neg, n, 2, 4); // - X(0) * Y(0) // - size: n limbs_mul_same_length_to_out_toom_8h_recursive(out, &xs[..n], &ys[..n], mul_scratch); // Infinity if half { // size: s, t limbs_mul_to_out(&mut out[15 * n..], &xs[pn..], &ys[qn..], mul_scratch); } limbs_mul_toom_interpolate_16_points( out, r1, r3, r5, r7, n, s + t, half, &mut mul_scratch[..r], ); }} ================================================ FILE: malachite-nz/src/natural/arithmetic/neg.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1997, 1999-2016, 2020 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::logic::not::limbs_not_in_place; use crate::platform::Limb; use core::ops::Neg; use malachite_base::num::arithmetic::traits::WrappingNegAssign; use malachite_base::slices::slice_leading_zeros; // This is equivalent to `mpn_neg` from `gmp.h`, GMP 6.2.1, where rp == up. pub(crate) fn limbs_neg_in_place(xs: &mut [Limb]) -> bool { let n = xs.len(); let zeros = slice_leading_zeros(xs); if zeros == n { return false; } xs[zeros].wrapping_neg_assign(); let offset = zeros + 1; if offset != n { limbs_not_in_place(&mut xs[offset..]); } true } impl Neg for Natural { type Output = Integer; /// Negates a [`Natural`], taking it by value and returning an [`Integer`]. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(-Natural::ZERO, 0); /// assert_eq!(-Natural::from(123u32), -123); /// ``` fn neg(self) -> Integer { Integer::from_sign_and_abs(self == 0, self) } } impl Neg for &Natural { type Output = Integer; /// Negates a [`Natural`], taking it by reference and returning an [`Integer`]. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(-&Natural::ZERO, 0); /// assert_eq!(-&Natural::from(123u32), -123); /// ``` fn neg(self) -> Integer { Integer::from_sign_and_abs_ref(*self == 0, self) } } ================================================ FILE: malachite-nz/src/natural/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, NextPowerOf2, NextPowerOf2Assign, }; use malachite_base::slices::{slice_set_zero, slice_test_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the smallest integer power of 2 greater than or equal to the `Natural`. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_next_power_of_2(xs: &[Limb]) -> Vec { let (xs_last, xs_init) = xs.split_last().unwrap(); let mut out; if let Some(x) = xs_last.checked_next_power_of_two() { out = vec![0; xs_init.len()]; if x == *xs_last && !slice_test_zero(xs_init) { if let Some(x) = x.arithmetic_checked_shl(1) { out.push(x); } else { out.push(0); out.push(1); } } else { out.push(x); } } else { out = vec![0; xs.len()]; out.push(1); } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the smallest integer power of 2 greater than or equal to the `Natural` to the input // slice. If the input slice is too small to hold the result, the limbs are all set to zero and the // carry bit, `true`, is returned. Otherwise, `false` is returned. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_slice_next_power_of_2_in_place(xs: &mut [Limb]) -> bool { let (xs_last, xs_init) = xs.split_last_mut().unwrap(); if let Some(x) = xs_last.checked_next_power_of_two() { if x == *xs_last && !slice_test_zero(xs_init) { slice_set_zero(xs_init); if let Some(x) = x.arithmetic_checked_shl(1) { *xs_last = x; false } else { *xs_last = 0; true } } else { slice_set_zero(xs_init); *xs_last = x; false } } else { slice_set_zero(xs_init); *xs_last = 0; true } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the smallest integer power of 2 greater than or equal to the `Natural` to the input // `Vec`. // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_vec_next_power_of_2_in_place(xs: &mut Vec) { if limbs_slice_next_power_of_2_in_place(xs) { xs.push(1); } }} impl NextPowerOf2 for Natural { type Output = Self; /// Finds the smallest power of 2 greater than or equal to a [`Natural`]. The [`Natural`] is /// taken by value. /// /// $f(x) = 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{NextPowerOf2, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.next_power_of_2(), 1); /// assert_eq!(Natural::from(123u32).next_power_of_2(), 128); /// assert_eq!( /// Natural::from(10u32).pow(12).next_power_of_2(), /// 1099511627776u64 /// ); /// ``` #[inline] fn next_power_of_2(mut self) -> Self { self.next_power_of_2_assign(); self } } impl NextPowerOf2 for &Natural { type Output = Natural; /// Finds the smallest power of 2 greater than or equal to a [`Natural`]. The [`Natural`] is /// taken by reference. /// /// $f(x) = 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{NextPowerOf2, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).next_power_of_2(), 1); /// assert_eq!((&Natural::from(123u32)).next_power_of_2(), 128); /// assert_eq!( /// (&Natural::from(10u32).pow(12)).next_power_of_2(), /// 1099511627776u64 /// ); /// ``` fn next_power_of_2(self) -> Natural { Natural(match self { Natural(Small(small)) => { if let Some(result) = small.checked_next_power_of_two() { Small(result) } else { Large(vec![0, 1]) } } Natural(Large(limbs)) => Large(limbs_next_power_of_2(limbs)), }) } } impl NextPowerOf2Assign for Natural { /// Replaces a [`Natural`] with the smallest power of 2 greater than or equal to it. /// /// $x \gets 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ (only if the underlying [`Vec`] needs to reallocate) /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{NextPowerOf2Assign, Pow}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.next_power_of_2_assign(); /// assert_eq!(x, 1); /// /// let mut x = Natural::from(123u32); /// x.next_power_of_2_assign(); /// assert_eq!(x, 128); /// /// let mut x = Natural::from(10u32).pow(12); /// x.next_power_of_2_assign(); /// assert_eq!(x, 1099511627776u64); /// ``` fn next_power_of_2_assign(&mut self) { match self { Self(Small(small)) => { if let Some(pow) = small.checked_next_power_of_two() { *small = pow; } else { *self = Self(Large(vec![0, 1])); } } Self(Large(limbs)) => { limbs_vec_next_power_of_2_in_place(limbs); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/parity.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::Parity; impl Parity for &Natural { /// Tests whether a [`Natural`] is even. /// /// $f(x) = (2|x)$. /// /// $f(x) = (\exists k \in \N : x = 2k)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Parity, Pow}; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.even(), true); /// assert_eq!(Natural::from(123u32).even(), false); /// assert_eq!(Natural::from(0x80u32).even(), true); /// assert_eq!(Natural::from(10u32).pow(12).even(), true); /// assert_eq!((Natural::from(10u32).pow(12) + Natural::ONE).even(), false); /// ``` fn even(self) -> bool { match self { Natural(Small(small)) => small.even(), Natural(Large(limbs)) => limbs[0].even(), } } /// Tests whether a [`Natural`] is odd. /// /// $f(x) = (2\nmid x)$. /// /// $f(x) = (\exists k \in \N : x = 2k+1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Parity, Pow}; /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.odd(), false); /// assert_eq!(Natural::from(123u32).odd(), true); /// assert_eq!(Natural::from(0x80u32).odd(), false); /// assert_eq!(Natural::from(10u32).pow(12).odd(), false); /// assert_eq!((Natural::from(10u32).pow(12) + Natural::ONE).odd(), true); /// ``` fn odd(self) -> bool { match self { Natural(Small(small)) => small.odd(), Natural(Large(limbs)) => limbs[0].odd(), } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/pow.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1997, 1999-2016, 2020 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::mul::limb::limbs_slice_mul_limb_in_place; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; #[cfg(feature = "test_build")] use crate::natural::bit_to_limb_count_ceiling; #[cfg(feature = "test_build")] use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count}; #[cfg(feature = "test_build")] use crate::platform::DoubleLimb; use crate::platform::Limb; use alloc::vec::Vec; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ EqModPowerOf2, Parity, Pow, PowAssign, Square, SquareAssign, }; #[cfg(feature = "test_build")] use malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; #[cfg(feature = "test_build")] use malachite_base::num::conversion::traits::SplitInHalf; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; #[cfg(feature = "test_build")] use malachite_base::num::logic::traits::BitAccess; use malachite_base::num::logic::traits::{ BitIterable, CountOnes, LeadingZeros, SignificantBits, TrailingZeros, }; use malachite_base::slices::slice_leading_zeros; /// This is equivalent to `GMP_NUMB_HALFMAX` from `mpz/n_pow_ui.c`, GMP 6.2.1. const HALF_MAX: Limb = (1 << (Limb::WIDTH >> 1)) - 1; // # Worst-case complexity // $T(n, m) = O(nm \log (nm) \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `exp`. pub_crate_test! {limbs_pow(xs: &[Limb], exp: u64) -> Vec { let mut out = Vec::new(); let out_len = limbs_pow_to_out(&mut out, xs, exp); out.truncate(out_len); out }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `exp`. fn len_1_helper(x_0: &mut Limb, out_0: &mut Limb, trailing_zero_bits_out: &mut u64, exp: &mut u64) { // Power up as far as possible within `x_0`. We start here with `exp` != 0, but if `exp` is // small then we might reach `exp` == 0 and the whole `x` ^ `exp` in `out_0`. while *x_0 <= HALF_MAX { assert_ne!(*exp, 0); if exp.odd() { *out_0 *= *x_0; } *exp >>= 1; if *exp == 0 { break; } x_0.square_assign(); } // Combine leftover `trailing_zero_bits_out` into `out_0` to be handled by the final // `limbs_slice_mul_limb_in_place` rather than a separate `limbs_slice_shl_in_place`. // - `out_0` mustn't be 1 (since then there's no final mul) // - `out_0` mustn't overflow if *trailing_zero_bits_out != 0 && *out_0 != 1 && *out_0 >> (Limb::WIDTH - *trailing_zero_bits_out) == 0 { *out_0 <<= *trailing_zero_bits_out; *trailing_zero_bits_out = 0; } } // # Worst-case complexity // $T(n, m) = O(nm \log (nm) \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `exp`. // // This is equivalent to `mpz_n_pow_ui` from `mpz/n_pow_ui.c`, GMP 6.2.1, where `e > 1` and // `bp.len() != 0`. Returns `rsize`. fn limbs_pow_to_out(out: &mut Vec, xs: &[Limb], mut exp: u64) -> usize { assert!(exp > 1); let leading_zeros_in = slice_leading_zeros(xs); let mut leading_zeros_out = leading_zeros_in * usize::exact_from(exp); let mut xs = &xs[leading_zeros_in..]; let mut x = xs[0]; // Strip low zero bits from b. let trailing_zero_bits_in = TrailingZeros::trailing_zeros(x); x >>= trailing_zero_bits_in; let mut trailing_zero_bits_out = exp * trailing_zero_bits_in; leading_zeros_out += bit_to_limb_count_floor(trailing_zero_bits_out); trailing_zero_bits_out &= Limb::WIDTH_MASK; let mut out_0 = 1; let mut scratch; let mut x_0_x_1 = [0; 2]; match xs.len() { 1 => len_1_helper(&mut x, &mut out_0, &mut trailing_zero_bits_out, &mut exp), 2 => { let mut x_1 = xs[1]; if trailing_zero_bits_in != 0 { x |= x_1 << (Limb::WIDTH - trailing_zero_bits_in); } x_1 >>= trailing_zero_bits_in; if x_1 == 0 { // Two limbs became one after rshift. xs = &xs[..1]; len_1_helper(&mut x, &mut out_0, &mut trailing_zero_bits_out, &mut exp); } else { x_0_x_1[0] = x; x_0_x_1[1] = x_1; xs = &x_0_x_1; x = x_1; } } len => { if trailing_zero_bits_in != 0 { scratch = vec![0; len]; limbs_shr_to_out(&mut scratch, xs, trailing_zero_bits_in); if *scratch.last().unwrap() == 0 { scratch.pop(); } xs = &scratch; } x = *xs.last().unwrap(); } } let len = xs.len(); // At this point `x` is the most significant limb of the base to use. // // Each factor of `xs` takes (len * 2 ^ `Limb::WIDTH` - `bits`) bits and there's `exp` of them; // +1 limb to round up the division; +1 for multiplies all using an extra limb over the true // size; +2 for `out_0` at the end; +1 for `limbs_slice_shl_in_place` at the end. // // The size calculation here is reasonably accurate. The base is at least half a limb, so in 32 // bits the worst case is 2 ^ 16 + 1 treated as 17 bits when it will power up as just over 16, // an overestimate of 17/16 = 6.25%. For a 64-bit limb it's half that. assert_ne!(x, 0); let mut out_alloc = bit_to_limb_count_floor((limb_to_bit_count(len) - LeadingZeros::leading_zeros(x)) * exp) + 5; out.resize(out_alloc + leading_zeros_out, 0); // Low zero limbs resulting from powers of 2. let out_original = out; let mut out = &mut out_original[leading_zeros_out..]; let mut out_len; let mut scratch; if exp == 0 { out[0] = out_0; out_len = 1; assert_ne!(out[0], 0); } else { // In the `limbs_slice_mul_limb_in_place` loop or in the `limbs_mul_greater_to_out` loop // when the low bit of `exp` is zero, `scratch` only has to hold the second last power step, // which is half the size of the final result. There's no need to round up the divide by 2, // since `out_alloc` includes a +2 for `out_0` which is not needed by `scratch`. In the // `limbs_mul_greater_to_out` loop when the low bit of `exp` is 1, `scratch` must hold // nearly the full result, so just size it the same as `out`. let mut scratch_len = out_alloc; if len == 1 || exp.even() { scratch_len >>= 1; } scratch = vec![0; scratch_len]; let mut scratch: &mut [Limb] = &mut scratch; let bits = LeadingZeros::leading_zeros(exp); if len == 1 { // Arrange the final result ends up in `out`, not in `scratch` if bits.even() { swap(&mut out, &mut scratch); swap(&mut out_alloc, &mut scratch_len); } out[0] = x; out_len = 1; for bit in exp.bits().rev().skip(1) { assert!(out_len << 1 <= scratch_len); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_len)]; limbs_square_to_out(scratch, &out[..out_len], &mut square_scratch); out_len <<= 1; if scratch[out_len - 1] == 0 { out_len -= 1; } swap(&mut out, &mut scratch); swap(&mut out_alloc, &mut scratch_len); if bit { assert!(out_len < out_alloc); let carry = limbs_slice_mul_limb_in_place(&mut out[..out_len], x); out[out_len] = carry; if carry != 0 { out_len += 1; } } } if out_0 != 1 { assert!(out_len < out_alloc); let carry = limbs_slice_mul_limb_in_place(&mut out[..out_len], out_0); out[out_len] = carry; if carry != 0 { out_len += 1; } } } else { // Arrange the final result ends up in `out`, not in `scratch` if !CountOnes::count_ones(exp).eq_mod_power_of_2(bits, 1) { swap(&mut out, &mut scratch); swap(&mut out_alloc, &mut scratch_len); } out[..len].copy_from_slice(xs); out_len = len; for bit in exp.bits().rev().skip(1) { assert!(out_len << 1 <= scratch_len); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_len)]; limbs_square_to_out(scratch, &out[..out_len], &mut square_scratch); out_len <<= 1; if scratch[out_len - 1] == 0 { out_len -= 1; } swap(&mut out, &mut scratch); swap(&mut out_alloc, &mut scratch_len); if bit { assert!(out_len + len <= scratch_len); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(out_len, len)]; let carry = limbs_mul_greater_to_out(scratch, &out[..out_len], xs, &mut mul_scratch); out_len += len; if carry == 0 { out_len -= 1; } swap(&mut out, &mut scratch); swap(&mut out_alloc, &mut scratch_len); } } } } // Apply any partial limb factors of 2. if trailing_zero_bits_out != 0 { assert!(out_len < out_alloc); let carry = limbs_slice_shl_in_place(&mut out[..out_len], trailing_zero_bits_out); out[out_len] = carry; if carry != 0 { out_len += 1; } } assert_eq!( out as *const [Limb], &out_original[leading_zeros_out..] as *const [Limb] ); out_len + leading_zeros_out } // # Worst-case complexity // Constant time and additional memory. #[cfg(feature = "test_build")] fn exp_predecessor(exp: u64) -> u64 { if exp.even() { exp >> 1 } else { exp - 1 } } // # Worst-case complexity // Constant time and additional memory. #[cfg(feature = "test_build")] fn estimated_limb_len_helper(x: Limb, exp: u64) -> usize { bit_to_limb_count_ceiling(x.significant_bits() * exp) } // # Worst-case complexity // Constant time and additional memory. // // Never an underestimate. #[cfg(feature = "test_build")] fn limb_pow_alt_estimated_out_len(x: Limb, exp: u64) -> usize { if exp.even() { estimated_limb_len_helper(x, exp >> 1) << 1 } else { estimated_limb_len_helper(x, exp - 1) + 1 } } // # Worst-case complexity // Constant time and additional memory. // // Never an underestimate. #[cfg(feature = "test_build")] #[inline] fn limb_pow_alt_estimated_scratch_len(x: Limb, exp: u64) -> usize { limb_pow_alt_estimated_out_len(x, exp_predecessor(exp)) } // TODO figure out how to find scratch len using mp_bases. x > 1. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `exp`. // // This is equivalent to `mpn_pow_1` from `mpn/generic/pow_1.c`, GMP 6.2.1, where `exp > 1` and `bn // == 1`. #[cfg(feature = "test_build")] fn limb_pow_to_out_alt<'a>( mut out: &'a mut [Limb], x: Limb, exp: u64, mut scratch: &'a mut [Limb], ) -> usize { assert!(x > 1); assert!(exp > 1); // Count number of bits in exp, and compute where to put initial square in order to magically // get results in the entry out. let bits = exp.significant_bits(); if bits.odd() { swap(&mut out, &mut scratch); } (out[1], out[0]) = DoubleLimb::from(x).square().split_in_half(); let mut out_len = if out[1] == 0 { 1 } else { 2 }; for i in (0..bits - 1).rev() { if exp.get_bit(i) { let (out_last, out_init) = out[..=out_len].split_last_mut().unwrap(); *out_last = limbs_slice_mul_limb_in_place(out_init, x); if *out_last != 0 { out_len += 1; } } if i == 0 { break; } let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_len)]; limbs_square_to_out(scratch, &out[..out_len], &mut square_scratch); out_len <<= 1; if scratch[out_len - 1] == 0 { out_len -= 1; } swap(&mut out, &mut scratch); } out_len } // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `exp`. #[cfg(feature = "test_build")] fn limb_pow_alt(x: Limb, exp: u64) -> Vec { let mut out = vec![0; limb_pow_alt_estimated_out_len(x, exp)]; let mut scratch = vec![0; limb_pow_alt_estimated_scratch_len(x, exp)]; let out_len = limb_pow_to_out_alt(&mut out, x, exp, &mut scratch); assert!(out_len <= out.len()); out.truncate(out_len); out } // # Worst-case complexity // Constant time and additional memory. #[cfg(feature = "test_build")] fn estimated_limbs_len_helper(xs: &[Limb], exp: u64) -> usize { bit_to_limb_count_ceiling(limbs_significant_bits(xs) * exp) } // # Worst-case complexity // Constant time and additional memory. // // Never an underestimate. #[cfg(feature = "test_build")] fn limbs_pow_alt_estimated_out_len(xs: &[Limb], exp: u64) -> usize { if exp.even() { estimated_limbs_len_helper(xs, exp >> 1) << 1 } else { estimated_limbs_len_helper(xs, exp - 1) + xs.len() } } // # Worst-case complexity // Constant time and additional memory. // // Never an underestimate. #[cfg(feature = "test_build")] #[inline] fn limbs_pow_alt_estimated_scratch_len(xs: &[Limb], exp: u64) -> usize { limbs_pow_alt_estimated_out_len(xs, exp_predecessor(exp)) } // TODO figure out how to find scratch len using mp_bases. // // # Worst-case complexity // $T(n, m) = O(nm \log (nm) \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `exp`. // // This is equivalent to `mpn_pow_1` from `mpn/generic/pow_1.c`, GMP 6.2.1, where `exp > 1`, `bn > // 1`, and the last element of `xs` is nonzero. #[cfg(feature = "test_build")] fn limbs_pow_to_out_alt<'a>( mut out: &'a mut [Limb], xs: &[Limb], exp: u64, mut scratch: &'a mut [Limb], ) -> usize { let len = xs.len(); assert!(len > 1); assert!(exp > 1); // Count number of bits in exp, and compute where to put initial square in order to magically // get results in the entry out. let bits = exp.significant_bits(); if bits.eq_mod_power_of_2(CountOnes::count_ones(exp), 1) { swap(&mut out, &mut scratch); } let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())]; limbs_square_to_out(out, xs, &mut square_scratch); let mut out_len = len << 1; if out[out_len - 1] == 0 { out_len -= 1; } for i in (0..bits - 1).rev() { if exp.get_bit(i) { let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(out_len, len)]; if limbs_mul_greater_to_out(scratch, &out[..out_len], xs, &mut mul_scratch) == 0 { out_len -= 1; } out_len += len; swap(&mut out, &mut scratch); } if i == 0 { break; } let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_len)]; limbs_square_to_out(scratch, &out[..out_len], &mut square_scratch); out_len <<= 1; if scratch[out_len - 1] == 0 { out_len -= 1; } swap(&mut out, &mut scratch); } out_len } // # Worst-case complexity // $T(n, m) = O(nm \log (nm) \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `exp`. #[cfg(feature = "test_build")] fn limbs_pow_alt(xs: &[Limb], exp: u64) -> Vec { let mut out = vec![0; limbs_pow_alt_estimated_out_len(xs, exp)]; let mut scratch = vec![0; limbs_pow_alt_estimated_scratch_len(xs, exp)]; let out_len = limbs_pow_to_out_alt(&mut out, xs, exp, &mut scratch); assert!(out_len <= out.len()); out.truncate(out_len); out } #[cfg(feature = "test_build")] impl Natural { pub fn pow_ref_alt(&self, exp: u64) -> Self { match (self, exp) { (_, 0) | (&Self::ONE, _) => Self::ONE, (&Self::ZERO, _) => Self::ZERO, (x, 1) => x.clone(), (x, 2) => x.square(), (x, exp) if x.is_power_of_2() => Self::power_of_2((x.significant_bits() - 1) * exp), (Self(Small(small)), exp) => { if small.significant_bits() * exp <= Limb::WIDTH { Self(Small(small.checked_pow(u32::wrapping_from(exp)).unwrap())) } else { Self::from_owned_limbs_asc(limb_pow_alt(*small, exp)) } } (Self(Large(limbs)), exp) => Self::from_owned_limbs_asc(limbs_pow_alt(limbs, exp)), } } pub fn pow_assign_alt(&mut self, exp: u64) { match (&mut *self, exp) { (x, 0) => *x = Self::ONE, (_, 1) | (&mut (Self::ZERO | Self::ONE), _) => {} (x, 2) => x.square_assign(), (x, exp) if x.is_power_of_2() => { *x = Self::power_of_2((x.significant_bits() - 1) * exp); } (Self(Small(small)), exp) => { if small.significant_bits() * exp <= Limb::WIDTH { *small = small.checked_pow(u32::wrapping_from(exp)).unwrap(); } else { *self = Self::from_owned_limbs_asc(limb_pow_alt(*small, exp)); } } (Self(Large(limbs)), exp) => { *self = Self::from_owned_limbs_asc(limbs_pow_alt(limbs, exp)); } } } } impl Pow for Natural { type Output = Self; /// Raises a [`Natural`] to a power, taking the [`Natural`] by value. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(3u32).pow(100).to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// assert_eq!( /// Natural::from_str("12345678987654321") /// .unwrap() /// .pow(3) /// .to_string(), /// "1881676411868862234942354805142998028003108518161" /// ); /// ``` #[inline] fn pow(mut self, exp: u64) -> Self { self.pow_assign(exp); self } } impl Pow for &Natural { type Output = Natural; /// Raises a [`Natural`] to a power, taking the [`Natural`] by reference. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(3u32)).pow(100).to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// assert_eq!( /// (&Natural::from_str("12345678987654321").unwrap()) /// .pow(3) /// .to_string(), /// "1881676411868862234942354805142998028003108518161" /// ); /// ``` #[inline] fn pow(self, exp: u64) -> Natural { match (self, exp) { (_, 0) | (&Natural::ONE, _) => Natural::ONE, (&Natural::ZERO, _) => Natural::ZERO, (x, 1) => x.clone(), (x, 2) => x.square(), (Natural(Small(small)), exp) => { if small.significant_bits() * exp <= Limb::WIDTH { Natural(Small(small.checked_pow(u32::wrapping_from(exp)).unwrap())) } else { let mut out = Natural(Large(limbs_pow(&[*small], exp))); out.demote_if_small(); out } } (Natural(Large(limbs)), exp) => { let mut out = Natural(Large(limbs_pow(limbs, exp))); out.demote_if_small(); out } } } } impl PowAssign for Natural { /// Raises a [`Natural`] to a power in place. /// /// $x \gets x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::arithmetic::traits::PowAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(3u32); /// x.pow_assign(100); /// assert_eq!( /// x.to_string(), /// "515377520732011331036461129765621272702107522001" /// ); /// /// let mut x = Natural::from_str("12345678987654321").unwrap(); /// x.pow_assign(3); /// assert_eq!( /// x.to_string(), /// "1881676411868862234942354805142998028003108518161" /// ); /// ``` fn pow_assign(&mut self, exp: u64) { match (&mut *self, exp) { (x, 0) => *x = Self::ONE, (_, 1) | (&mut (Self::ZERO | Self::ONE), _) => {} (x, 2) => x.square_assign(), (Self(Small(small)), exp) => { if small.significant_bits() * exp <= Limb::WIDTH { *small = small.checked_pow(u32::wrapping_from(exp)).unwrap(); } else { *self = Self(Large(limbs_pow(&[*small], exp))); self.demote_if_small(); } } (Self(Large(limbs)), exp) => { *self = Self(Large(limbs_pow(limbs, exp))); self.demote_if_small(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; impl PowerOf2 for Natural { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::power_of_2(0), 1); /// assert_eq!(Natural::power_of_2(3), 8); /// assert_eq!( /// Natural::power_of_2(100).to_string(), /// "1267650600228229401496703205376" /// ); /// ``` #[inline] fn power_of_2(pow: u64) -> Self { Self::ONE << pow } } ================================================ FILE: malachite-nz/src/natural/arithmetic/primorial.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed to the GNU project by Marco Bodrato. // // Copyright © 2012, 2015, 2016 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::factorial::log_n_max; use crate::natural::arithmetic::mul::product_of_limbs::limbs_product; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{PowerOf2, Primorial, RotateLeftAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, WrappingFrom}; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u32; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::factorization::prime_sieve::limbs_prime_sieve_u64; use malachite_base::num::factorization::prime_sieve::{id_to_n, limbs_prime_sieve_size, n_to_bit}; use malachite_base::num::factorization::traits::Primes; #[cfg(feature = "32_bit_limbs")] const SMALL_PRIMORIAL_LIMIT: u64 = 29; #[cfg(not(feature = "32_bit_limbs"))] const SMALL_PRIMORIAL_LIMIT: u64 = 53; // This is equivalent to `mpz_primorial_ui` from `mpz/primorial_ui.c`, GMP 6.2.1, where n is too // large for the primorial of n to fit in a single limb. #[allow(clippy::useless_conversion)] fn limbs_primorial(n: Limb) -> Vec { let n_u64 = u64::from(n); let size = usize::exact_from(n >> Limb::LOG_WIDTH); let size = size + (size >> 1) + 1; assert!(size >= limbs_prime_sieve_size::(n_u64)); let mut sieve = vec![0; size]; #[cfg(feature = "32_bit_limbs")] let count = limbs_prime_sieve_u32(&mut sieve, n_u64); #[cfg(not(feature = "32_bit_limbs"))] let count = limbs_prime_sieve_u64(&mut sieve, n); let size = usize::exact_from((count + 1) / log_n_max(n) + 1); let mut factors = vec![0; size]; let mut j = 0; let mut prod = 6; // Store primes from 5 to n let max_prod = Limb::MAX / n; let i = n_to_bit(5); let mut index = bit_to_limb_count_floor(i); let mut mask = Limb::power_of_2(i & Limb::WIDTH_MASK); for i in i + 1..=n_to_bit(n_u64) + 1 { if sieve[index] & mask == 0 { let prime = Limb::wrapping_from(id_to_n(i)); if prod > max_prod { factors[j] = prod; j += 1; prod = prime; } else { prod *= prime; } } mask.rotate_left_assign(1); if mask == 1 { index += 1; } } // j != 0 factors[j] = prod; j += 1; sieve.resize(j, 0); let (out_len, new_sieve) = limbs_product(&mut sieve, &mut factors[..j]); assert!(new_sieve.is_none()); sieve.truncate(out_len); sieve } #[cfg(feature = "32_bit_limbs")] const SMALL_PRODUCT_OF_FIRST_N_PRIMES_LIMIT: u64 = 10; #[cfg(not(feature = "32_bit_limbs"))] const SMALL_PRODUCT_OF_FIRST_N_PRIMES_LIMIT: u64 = 16; fn limbs_product_of_first_n_primes(n: usize) -> Vec { let mut prod: Limb = 1; let mut factors = Vec::new(); for prime in Limb::primes().take(n) { if let Some(p) = prod.checked_mul(prime) { prod = p; } else { factors.push(prod); prod = prime; } } factors.push(prod); let mut out = Vec::new(); let (out_len, new_out) = limbs_product(&mut out, &mut factors); out = new_out.unwrap(); out.truncate(out_len); out } impl Primorial for Natural { /// Computes the primorial of a [`Natural`]: the product of all primes less than or equal to it. /// /// The [`product_of_first_n_primes`](Natural::product_of_first_n_primes) function is similar; /// it computes the primorial of the $n$th prime. /// /// $$ /// f(n) = n\\# =prod_{pleq natop p\\text {prime}} p. /// $$ /// /// $n\\# = O(e^{(1+o(1))n})$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Primorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::primorial(0), 1); /// assert_eq!(Natural::primorial(1), 1); /// assert_eq!(Natural::primorial(2), 2); /// assert_eq!(Natural::primorial(3), 6); /// assert_eq!(Natural::primorial(4), 6); /// assert_eq!(Natural::primorial(5), 30); /// assert_eq!( /// Natural::primorial(100).to_string(), /// "2305567963945518424753102147331756070" /// ); /// ``` /// /// This is equivalent to `mpz_primorial_ui` from `mpz/primorial_ui.c`, GMP 6.2.1. #[inline] fn primorial(n: u64) -> Self { assert!(Limb::convertible_from(n)); if n < SMALL_PRIMORIAL_LIMIT { Self::from(Limb::primorial(n)) } else { Self::from_owned_limbs_asc(limbs_primorial(Limb::wrapping_from(n))) } } /// Computes the product of the first $n$ primes. /// /// The [`primorial`](Natural::primorial) function is similar; it computes the product of all /// primes less than or equal to $n$. /// /// $$ /// f(n) = p_n\\# = \prod_{k=1}^n p_n, /// $$ /// where $p_n$ is the $n$th prime number. /// /// $p_n\\# = O\left (\left (\frac{1}{e}k\log k\left (\frac{\log k}{e^2}k \right )^{1/\log /// k}\right )^k\omega(1)\right )$. /// /// This asymptotic approximation is due to [Bart /// Michels](https://math.stackexchange.com/a/1594930). /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Primorial; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::product_of_first_n_primes(0), 1); /// assert_eq!(Natural::product_of_first_n_primes(1), 2); /// assert_eq!(Natural::product_of_first_n_primes(2), 6); /// assert_eq!(Natural::product_of_first_n_primes(3), 30); /// assert_eq!(Natural::product_of_first_n_primes(4), 210); /// assert_eq!(Natural::product_of_first_n_primes(5), 2310); /// assert_eq!( /// Natural::product_of_first_n_primes(100).to_string(), /// "4711930799906184953162487834760260422020574773409675520188634839616415335845034221205\ /// 28925670554468197243910409777715799180438028421831503871944494399049257903072063599053\ /// 8452312528339864352999310398481791730017201031090" /// ); /// ``` #[inline] fn product_of_first_n_primes(n: u64) -> Self { assert!(Limb::convertible_from(n)); if n < SMALL_PRODUCT_OF_FIRST_N_PRIMES_LIMIT { Self::from(Limb::product_of_first_n_primes(n)) } else { Self::from_owned_limbs_asc(limbs_product_of_first_n_primes(usize::exact_from(n))) } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/root.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed by Paul Zimmermann (algorithm) and Paul Zimmermann and Torbjörn Granlund // (implementation). Marco Bodrato wrote `logbased_root` to seed the loop. // // Copyright © 2002, 2005, 2009-2012, 2015 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::div::{limbs_div_limb_to_out, limbs_div_to_out}; use crate::natural::arithmetic::mul::limb::limbs_slice_mul_limb_in_place; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::pow::limbs_pow; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::limbs_shr_to_out; use crate::natural::arithmetic::sub::{ limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb_in_place, limbs_sub_limb_to_out, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::*; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CeilingSqrt, CheckedRoot, CheckedSqrt, DivMod, DivRound, FloorRoot, FloorRootAssign, FloorSqrt, ModPowerOf2Assign, PowerOf2, RootAssignRem, RootRem, SqrtRem, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::{LeadingZeros, LowMask, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::{slice_set_zero, slice_trailing_zeros}; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn limbs_shl_helper(xs: &mut [Limb], len: usize, out_start_index: usize, bits: u64) -> Limb { assert!(bits < Limb::WIDTH); if len == 0 { 0 } else { xs.copy_within(0..len, out_start_index); if bits == 0 { 0 } else { limbs_slice_shl_in_place(&mut xs[out_start_index..out_start_index + len], bits) } } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn shr_helper(out: &mut [Limb], xs: &[Limb], shift: u64) { if shift == 0 { out[..xs.len()].copy_from_slice(xs); } else { limbs_shr_to_out(out, xs, shift); } } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn div_helper(qs: &mut [Limb], ns: &mut [Limb], ds: &mut [Limb]) { assert!(*ns.last().unwrap() != 0); assert!(*ds.last().unwrap() != 0); if ns.len() == 1 { if ds.len() == 1 { qs[0] = ns[0] / ds[0]; } else { qs[0] = 0; } } else if ds.len() == 1 { limbs_div_limb_to_out(qs, ns, ds[0]); } else { limbs_div_to_out(qs, ns, ds); } } // vlog=vector(256,i,floor((log(256+i)/log(2)-8)*256)-(i>255)) const V_LOG: [u8; 256] = [ 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 40, 42, 43, 44, 46, 47, 48, 49, 51, 52, 53, 54, 56, 57, 58, 59, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 91, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 173, 174, 175, 176, 177, 178, 179, 180, 181, 181, 182, 183, 184, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, 194, 194, 195, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 214, 215, 216, 217, 218, 218, 219, 220, 221, 222, 222, 223, 224, 225, 225, 226, 227, 228, 229, 229, 230, 231, 232, 232, 233, 234, 235, 235, 236, 237, 238, 239, 239, 240, 241, 242, 242, 243, 244, 245, 245, 246, 247, 247, 248, 249, 250, 250, 251, 252, 253, 253, 254, 255, 255, ]; // vexp=vector(256,i,floor(2^(8+i/256)-256)-(i>255)) const V_EXP: [u8; 256] = [ 0, 1, 2, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 23, 24, 25, 26, 26, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66, 67, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 166, 167, 168, 169, 171, 172, 173, 174, 175, 176, 178, 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, 191, 192, 193, 194, 196, 197, 198, 199, 200, 202, 203, 204, 205, 207, 208, 209, 210, 212, 213, 214, 216, 217, 218, 219, 221, 222, 223, 225, 226, 227, 229, 230, 231, 232, 234, 235, 236, 238, 239, 240, 242, 243, 245, 246, 247, 249, 250, 251, 253, 254, 255, ]; const LOGROOT_USED_BITS: u64 = 8; const LOGROOT_NEEDS_TWO_CORRECTIONS: bool = true; const NEEDED_CORRECTIONS: u64 = if LOGROOT_NEEDS_TWO_CORRECTIONS { 2 } else { 1 }; const LOGROOT_RETURNED_BITS: u64 = if LOGROOT_NEEDS_TWO_CORRECTIONS { LOGROOT_USED_BITS + 1 } else { LOGROOT_USED_BITS }; // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `logbased_root` from `mpn/generic/rootrem.c`, GMP 6.2.1. fn log_based_root(out: &mut Limb, x: Limb, mut bit_count: u64, exp: u64) -> u64 { const LOGROOT_USED_BITS_COMP: u64 = Limb::WIDTH - LOGROOT_USED_BITS; let len; let b = u64::from(V_LOG[usize::exact_from(x >> LOGROOT_USED_BITS_COMP)]); if bit_count.significant_bits() > LOGROOT_USED_BITS_COMP { // In this branch, the input is unreasonably large. In the unlikely case, we use two // divisions and a modulo. fail_on_untested_path("bit_count.significant_bits() > LOGROOT_USED_BITS_COMP"); let r; (len, r) = bit_count.div_mod(exp); bit_count = ((r << LOGROOT_USED_BITS) | b) / exp; } else { bit_count = ((bit_count << LOGROOT_USED_BITS) | b) / exp; len = bit_count >> LOGROOT_USED_BITS; bit_count.mod_power_of_2_assign(LOGROOT_USED_BITS); } assert!(bit_count.significant_bits() <= LOGROOT_USED_BITS); *out = Limb::power_of_2(LOGROOT_USED_BITS) | Limb::from(V_EXP[usize::exact_from(bit_count)]); if !LOGROOT_NEEDS_TWO_CORRECTIONS { *out >>= 1; } len } // If approx is non-zero, does not compute the final remainder. // /// # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_rootrem_internal` from `mpn/generic/rootrem.c`, GMP 6.2.1. fn limbs_root_to_out_internal( out_root: &mut [Limb], out_rem: Option<&mut [Limb]>, xs: &[Limb], exp: u64, approx: bool, ) -> usize { let mut xs_len = xs.len(); let mut xs_hi = xs[xs_len - 1]; let leading_zeros = LeadingZeros::leading_zeros(xs_hi) + 1; let bit_count = limb_to_bit_count(xs_len) - leading_zeros; let out_rem_is_some = out_rem.is_some(); if bit_count < exp { // root is 1 out_root[0] = 1; if out_rem_is_some { let out_rem = out_rem.unwrap(); limbs_sub_limb_to_out(out_rem, xs, 1); // There should be at most one zero limb, if we demand x to be normalized if out_rem[xs_len - 1] == 0 { xs_len -= 1; } } else if xs[0] == 1 { xs_len -= 1; } return xs_len; } xs_hi = if leading_zeros == Limb::WIDTH { xs[xs_len - 2] } else { let mut i = xs_len - 1; if xs_len != 1 { i -= 1; } (xs_hi << leading_zeros) | (xs[i] >> (Limb::WIDTH - leading_zeros)) }; assert!(xs_len != 1 || xs[xs_len - 1] >> (Limb::WIDTH - leading_zeros) == 1); // - root_bits + 1 is the number of bits of the root R // - APPROX_BITS + 1 is the number of bits of the current approximation S let mut root_bits = log_based_root(&mut out_root[0], xs_hi, bit_count, exp); const APPROX_BITS: u64 = LOGROOT_RETURNED_BITS - 1; let mut input_bits = exp * root_bits; // number of truncated bits in the input xs_hi = (Limb::exact_from(exp) - 1) >> 1; let mut log_exp = 3; loop { xs_hi >>= 1; if xs_hi == 0 { break; } log_exp += 1; } // log_exp = ceil(log_2(exp)) + 1 let mut i = 0; let mut sizes = [0u64; (Limb::WIDTH + 1) as usize]; loop { // Invariant: here we want root_bits + 1 total bits for the kth root. If c is the new value // of root_bits, this means that we'll go from a root of c + 1 bits (say s') to a root of // root_bits + 1 bits. It is proved in the book "Modern Computer Arithmetic" by Brent and // Zimmermann, Chapter 1, that if s' >= exp * beta, then at most one correction is // necessary. Here beta = 2 ^ (root_bits - c), and s' >= 2 ^ c, thus it suffices that c >= // ceil((root_bits + log_2(exp)) / 2). sizes[i] = root_bits; if root_bits <= APPROX_BITS { break; } if root_bits > log_exp { root_bits = (root_bits + log_exp) >> 1; } else { // add just one bit at a time root_bits -= 1; } i += 1; } out_root[0] >>= APPROX_BITS - root_bits; input_bits -= root_bits; assert!(i < usize::wrapping_from(Limb::WIDTH + 1)); // We have sizes[0] = next_bits > sizes[1] > ... > sizes[ni] = 0, with sizes[i] <= 2 * sizes[i + // 1]. Newton iteration will first compute sizes[i - 1] extra bits, then sizes[i - 2], ..., then // sizes[0] = next_bits. qs and ws need enough space to store S' ^ exp, where S' is an // approximate root. Since S' can be as large as S + 2, the worst case is when S = 2 and S' = 4. // But then since we know the number of bits of S in advance, S' can only be 3 at most. // Similarly for S = 4, then S' can be 6 at most. So the worst case is S' / S = 3 / 2, thus S' ^ // exp <= (3 / 2) ^ exp * S ^ exp. Since S ^ exp fits in xs_len limbs, the number of extra limbs // needed is bounded by ceil(exp * log_2(3 / 2) / B), where B is `Limb::WIDTH`. let extra = (((0.585 * (exp as f64)) / (Limb::WIDTH as f64)) as usize) + 2; let mut big_scratch = vec![0; 3 * xs_len + 2 * extra + 1]; let (scratch, remainder) = big_scratch.split_at_mut(xs_len + 1); // - qs will contain quotient and remainder of R / (exp * S ^ (exp - 1)). // - ws will contain S ^ (k-1) and exp *S^(k-1). let (qs, ws) = remainder.split_at_mut(xs_len + extra); let rs = if out_rem_is_some { out_rem.unwrap() } else { scratch }; let ss = out_root; // Initial approximation has one limb let mut ss_len = 1; let mut next_bits = root_bits; let mut rs_len = 0; let mut save_1; let mut save_2 = 0; let mut qs_len; let mut pow_cmp; while i != 0 { // Loop invariant: // - &ss[..ss_len] is the current approximation of the root, which has exactly 1 + sizes[i] // bits. // - &rs[..rs_len] is the current remainder. // - &ws[..ws_len] = ss[..ss_len] ^ (exp - 1) // - input_bits = number of truncated bits of the input // // Since each iteration treats next_bits bits from the root and thus exp * next_bits bits // from the input, and we already considered next_bits bits from the input, we now have to // take another (exp - 1) * next_bits bits from the input. input_bits -= (exp - 1) * next_bits; // &rs[..rs_len] = floor(&xs[..xs_len] / 2 ^ input_bits) let input_len = bit_to_limb_count_floor(input_bits); let input_bits_rem = input_bits & Limb::WIDTH_MASK; shr_helper(rs, &xs[input_len..xs_len], input_bits_rem); rs_len = xs_len - input_len; if rs[rs_len - 1] == 0 { rs_len -= 1; } // Current buffers: &ss[..ss_len], &ss[..ss_len] let mut correction = 0; let mut ws_len; loop { // - Compute S ^ exp in &qs[..qs_len] // - W <- S ^ (exp - 1) for the next iteration, and S ^ k = W * S. let ss_trimmed = &mut ss[..ss_len]; let pow_xs = limbs_pow(ss_trimmed, exp - 1); ws[..pow_xs.len()].copy_from_slice(&pow_xs); ws_len = pow_xs.len(); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(ws_len, ss_len)]; limbs_mul_greater_to_out(qs, &ws[..ws_len], ss_trimmed, &mut mul_scratch); qs_len = ws_len + ss_len; if qs[qs_len - 1] == 0 { qs_len -= 1; } pow_cmp = Greater; // if S^k > floor(U/2^input_bits), the root approximation was too large let mut need_adjust = qs_len > rs_len; if !need_adjust && qs_len == rs_len { pow_cmp = limbs_cmp_same_length(&qs[..rs_len], &rs[..rs_len]); need_adjust = pow_cmp == Greater; } if need_adjust { assert!(!limbs_sub_limb_in_place(ss_trimmed, 1)); } else { break; } correction += 1; } // - Current buffers: &ss[..ss_len], &rs[..rs_len], &qs[..qs_len], &ws[..ws_len] // - Sometimes two corrections are needed with logbased_root. assert!(correction <= NEEDED_CORRECTIONS); assert!(rs_len >= qs_len); // next_bits is the number of bits to compute in the next iteration. next_bits = sizes[i - 1] - sizes[i]; // next_len is the lowest limb from the high part of rs, after shift. let next_len = bit_to_limb_count_floor(next_bits); let next_bits_rem = next_bits & Limb::WIDTH_MASK; input_bits -= next_bits; let input_len = bit_to_limb_count_floor(input_bits); let input_bits_rem = input_bits & Limb::WIDTH_MASK; // - n_len is the number of limbs in x which contain bits // - [input_bits, input_bits + next_bits - 1] // // n_len = 1 + floor((input_bits + next_bits - 1) / B) - floor(input_bits / B) <= 1 + // (input_bits + next_bits - 1) / B - (input_bits - B + 1) / B = 2 + (next_bits - 2) / B, // where B is `Limb::WIDTH`. // // Thus, since n_len is an integer: n_len <= 2 + floor(next_bits / B) <= 2 + next_len. let n_len = bit_to_limb_count_floor(input_bits + next_bits - 1) + 1 - input_len; // - Current buffers: &ss[..ss_len], &rs[..rs_len], &ws[..ws_len] // - R = R - Q = floor(X / 2 ^ input_bits) - S ^ exp if pow_cmp == Equal { rs_len = next_len; save_2 = 0; save_1 = 0; } else { let rs_trimmed = &mut rs[..rs_len]; limbs_sub_greater_in_place_left(rs_trimmed, &qs[..qs_len]); rs_len -= slice_trailing_zeros(rs_trimmed); // first multiply the remainder by 2^next_bits let carry = limbs_shl_helper(rs, rs_len, next_len, next_bits_rem); rs_len += next_len; if carry != 0 { rs[rs_len] = carry; rs_len += 1; } save_1 = rs[next_len]; // we have to save rs[next_len] up to rs[n_len - 1], i.e. 1 or 2 limbs if n_len - 1 > next_len { save_2 = rs[next_len + 1]; } } // - Current buffers: &ss[..ss_len], &rs[..rs_len], &ws[..ws_len] // - Now insert bits [input_bits, input_bits + next_bits - 1] from the input X shr_helper(rs, &xs[input_len..input_len + n_len], input_bits_rem); // Set to zero high bits of rs[next_len] rs[next_len].mod_power_of_2_assign(next_bits_rem); // Restore corresponding bits rs[next_len] |= save_1; if n_len - 1 > next_len { // The low next_bits bits go in rs[0..next_len] only, since they start by bit 0 in // rs[0], so they use at most ceil(next_bits / B) limbs rs[next_len + 1] = save_2; } // - Current buffers: &ss[..ss_len], &rs[..rs_len], &ws[..ws_len] // - Compute &ws[..ws_len] = exp * &ss[..ss_len] ^ (exp-1). let carry = limbs_slice_mul_limb_in_place(&mut ws[..ws_len], Limb::exact_from(exp)); ws[ws_len] = carry; if carry != 0 { ws_len += 1; } // - Current buffers: &ss[..ss_len], &qs[..qs_len] // - Multiply the root approximation by 2 ^ next_bits let carry = limbs_shl_helper(ss, ss_len, next_len, next_bits_rem); ss_len += next_len; if carry != 0 { ss[ss_len] = carry; ss_len += 1; } save_1 = ss[next_len]; // Number of limbs used by next_bits bits, when least significant bit is aligned to least // limb let b_rem = bit_to_limb_count_floor(next_bits - 1) + 1; // - Current buffers: &ss[..ss_len], &rs[..rs_len], &ws[..ws_len] // - Now divide &rs[..rs_len] by &ws[..ws_len] to get the low part of the root if rs_len < ws_len { slice_set_zero(&mut ss[..b_rem]); } else { let mut qs_len = rs_len - ws_len; // Expected quotient size if qs_len <= b_rem { // Divide only if result is not too big. div_helper(qs, &mut rs[..rs_len], &mut ws[..ws_len]); if qs[qs_len] != 0 { qs_len += 1; } } else { fail_on_untested_path("limbs_root_to_out_internal, qs_len > b_rem"); } // - Current buffers: &ss[..ss_len], &qs[..qs_len] // - Note: &rs[..rs_len]is not needed any more since we'll compute it from scratch at // the end of the loop. // // The quotient should be smaller than 2 ^ next_bits, since the previous approximation // was correctly rounded toward zero. if qs_len > b_rem || (qs_len == b_rem && (next_bits_rem != 0) && qs[qs_len - 1].significant_bits() > next_bits_rem) { qs_len = 1; while qs_len < b_rem { ss[qs_len - 1] = Limb::MAX; qs_len += 1; } ss[qs_len - 1] = Limb::low_mask(((next_bits - 1) & Limb::WIDTH_MASK) + 1); } else { // - Current buffers: &ss[..ss_len], &qs[..qs_len] // - Combine sB and q to form sB + q. let (ss_lo, ss_hi) = ss.split_at_mut(qs_len); ss_lo.copy_from_slice(&qs[..qs_len]); slice_set_zero(&mut ss_hi[..b_rem - qs_len]); } } ss[next_len] |= save_1; // 8: current buffer: &ss[..ss_len] i -= 1; } // otherwise we have rn > 0, thus the return value is ok if !approx || ss[0] <= 1 { let mut c = 0; loop { // - Compute S ^ exp in &qs[..qs_len]. // - Last iteration: we don't need W anymore. let pow_xs = limbs_pow(&ss[..ss_len], exp); qs[..pow_xs.len()].copy_from_slice(&pow_xs); qs_len = pow_xs.len(); pow_cmp = Greater; let mut need_adjust = qs_len > xs_len; if !need_adjust && qs_len == xs_len { pow_cmp = limbs_cmp_same_length(&qs[..xs_len], &xs[..xs_len]); need_adjust = pow_cmp == Greater; } if need_adjust { assert!(!limbs_sub_limb_in_place(&mut ss[..ss_len], 1)); } else { break; } c += 1; } // Sometimes two corrections are needed with log_based_root. assert!(c <= NEEDED_CORRECTIONS); rs_len = usize::from(pow_cmp != Equal); if rs_len != 0 && out_rem_is_some { limbs_sub_greater_to_out(rs, &xs[..xs_len], &qs[..qs_len]); rs_len = xs_len; rs_len -= slice_trailing_zeros(rs); } } rs_len } // Returns the size (in limbs) of the remainder. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_rootrem` from `mpn/generic/rootrem.c`, GMP 6.2.1, where `k != 2` and // `remp` is not `NULL`. pub_test! {limbs_root_rem_to_out( out_root: &mut [Limb], out_rem: &mut [Limb], xs: &[Limb], exp: u64, ) -> usize { let xs_len = xs.len(); assert_ne!(xs_len, 0); assert_ne!(xs[xs_len - 1], 0); assert!(exp > 2); // (xs_len - 1) / exp > 2 <=> xs_len > 3 * exp <=> (xs_len + 2) / 3 > exp limbs_root_to_out_internal(out_root, Some(out_rem), xs, exp, false) }} // Returns a non-zero value iff the remainder is non-zero. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_rootrem` from `mpn/generic/rootrem.c`, GMP 6.2.1, where `remp` is // `NULL`. pub_test! {limbs_floor_root_to_out(out_root: &mut [Limb], xs: &[Limb], exp: u64) -> bool { let xs_len = xs.len(); assert_ne!(xs_len, 0); assert_ne!(xs[xs_len - 1], 0); assert!(exp > 2); // (xs_len - 1) / exp > 2 <=> xs_len > 3 * exp <=> (xs_len + 2) / 3 > exp let u_exp = usize::exact_from(exp); if xs_len.div_ceil(3) > u_exp { // Pad xs with exp zero limbs. This will produce an approximate root with one more limb, // allowing us to compute the exact integral result. let ws_len = xs_len + u_exp; let ss_len = (xs_len - 1) / u_exp + 2; // ceil(xs_len / exp) + 1 let mut scratch = vec![0; ws_len + ss_len]; // - ws will contain the padded input. // - ss is the approximate root of padded input. let (ws, ss) = scratch.split_at_mut(ws_len); ws[u_exp..].copy_from_slice(xs); let rs_len = limbs_root_to_out_internal(ss, None, ws, exp, true); // The approximate root S = ss is either the correct root of ss, or 1 too large. Thus, // unless the least significant limb of S is 0 or 1, we can deduce the root of xs is S // truncated by one limb. (In case xs[0] = 1, we can deduce the root, but not decide whether // it is exact or not.) out_root[..ss_len - 1].copy_from_slice(&ss[1..]); rs_len != 0 } else { limbs_root_to_out_internal(out_root, None, xs, exp, false) != 0 } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_floor_root(xs: &[Limb], exp: u64) -> (Vec, bool) { let mut out = vec![ 0; xs.len() .div_round(usize::exact_from(exp), Ceiling).0 ]; let inexact = limbs_floor_root_to_out(&mut out, xs, exp); (out, inexact) }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_root_rem(xs: &[Limb], exp: u64) -> (Vec, Vec) { let mut root_out = vec![ 0; xs.len() .div_round(usize::exact_from(exp), Ceiling).0 ]; let mut rem_out = vec![0; xs.len()]; let rem_len = limbs_root_rem_to_out(&mut root_out, &mut rem_out, xs, exp); rem_out.truncate(rem_len); (root_out, rem_out) }} impl FloorRoot for Natural { type Output = Self; /// Returns the floor of the $n$th root of a [`Natural`], taking the [`Natural`] by value. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRoot; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(999u16).floor_root(3), 9); /// assert_eq!(Natural::from(1000u16).floor_root(3), 10); /// assert_eq!(Natural::from(1001u16).floor_root(3), 10); /// assert_eq!(Natural::from(100000000000u64).floor_root(5), 158); /// ``` fn floor_root(self, exp: u64) -> Self { match exp { 0 => panic!("Cannot take 0th root"), 1 => self, 2 => self.floor_sqrt(), exp => match self { Self(Small(x)) => Self(Small(x.floor_root(exp))), Self(Large(xs)) => Self::from_owned_limbs_asc(limbs_floor_root(&xs, exp).0), }, } } } impl FloorRoot for &Natural { type Output = Natural; /// Returns the floor of the $n$th root of a [`Natural`], taking the [`Natural`] by reference. /// /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRoot; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(999u16)).floor_root(3), 9); /// assert_eq!((&Natural::from(1000u16)).floor_root(3), 10); /// assert_eq!((&Natural::from(1001u16)).floor_root(3), 10); /// assert_eq!((&Natural::from(100000000000u64)).floor_root(5), 158); /// ``` fn floor_root(self, exp: u64) -> Natural { match exp { 0 => panic!("Cannot take 0th root"), 1 => self.clone(), 2 => self.floor_sqrt(), exp => match self { Natural(Small(x)) => Natural(Small(x.floor_root(exp))), Natural(Large(xs)) => Natural::from_owned_limbs_asc(limbs_floor_root(xs, exp).0), }, } } } impl FloorRootAssign for Natural { /// Replaces a [`Natural`] with the floor of its $n$th root. /// /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorRootAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(999u16); /// x.floor_root_assign(3); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(1000u16); /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1001u16); /// x.floor_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(100000000000u64); /// x.floor_root_assign(5); /// assert_eq!(x, 158); /// ``` #[inline] fn floor_root_assign(&mut self, exp: u64) { *self = (&*self).floor_root(exp); } } impl CeilingRoot for Natural { type Output = Self; /// Returns the ceiling of the $n$th root of a [`Natural`], taking the [`Natural`] by value. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRoot; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(999u16).ceiling_root(3), 10); /// assert_eq!(Natural::from(1000u16).ceiling_root(3), 10); /// assert_eq!(Natural::from(1001u16).ceiling_root(3), 11); /// assert_eq!(Natural::from(100000000000u64).ceiling_root(5), 159); /// ``` fn ceiling_root(self, exp: u64) -> Self { match exp { 0 => panic!("Cannot take 0th root"), 1 => self, 2 => self.ceiling_sqrt(), exp => match self { Self(Small(x)) => Self(Small(x.ceiling_root(exp))), Self(Large(xs)) => { let (floor_root_limbs, inexact) = limbs_floor_root(&xs, exp); let floor_root = Self::from_owned_limbs_asc(floor_root_limbs); if inexact { floor_root + Self::ONE } else { floor_root } } }, } } } impl CeilingRoot for &Natural { type Output = Natural; /// Returns the ceiling of the $n$th root of a [`Natural`], taking the [`Natural`] by reference. /// /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRoot; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(999u16).ceiling_root(3), 10); /// assert_eq!(Natural::from(1000u16).ceiling_root(3), 10); /// assert_eq!(Natural::from(1001u16).ceiling_root(3), 11); /// assert_eq!(Natural::from(100000000000u64).ceiling_root(5), 159); /// ``` fn ceiling_root(self, exp: u64) -> Natural { match exp { 0 => panic!("Cannot take 0th root"), 1 => self.clone(), 2 => self.ceiling_sqrt(), exp => match self { Natural(Small(x)) => Natural(Small(x.ceiling_root(exp))), Natural(Large(xs)) => { let (floor_root_limbs, inexact) = limbs_floor_root(xs, exp); let floor_root = Natural::from_owned_limbs_asc(floor_root_limbs); if inexact { floor_root + Natural::ONE } else { floor_root } } }, } } } impl CeilingRootAssign for Natural { /// Replaces a [`Natural`] with the ceiling of its $n$th root. /// /// $x \gets \lceil\sqrt\[n\]{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingRootAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(999u16); /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1000u16); /// x.ceiling_root_assign(3); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1001u16); /// x.ceiling_root_assign(3); /// assert_eq!(x, 11); /// /// let mut x = Natural::from(100000000000u64); /// x.ceiling_root_assign(5); /// assert_eq!(x, 159); /// ``` #[inline] fn ceiling_root_assign(&mut self, exp: u64) { *self = (&*self).ceiling_root(exp); } } impl CheckedRoot for Natural { type Output = Self; /// Returns the the $n$th root of a [`Natural`], or `None` if the [`Natural`] is not a perfect /// $n$th power. The [`Natural`] is taken by value. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(999u16).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(1000u16).checked_root(3).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Natural::from(1001u16).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(100000000000u64) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10000000000u64) /// .checked_root(5) /// .to_debug_string(), /// "Some(100)" /// ); /// ``` fn checked_root(self, exp: u64) -> Option { match exp { 0 => panic!("Cannot take 0th root"), 1 => Some(self), 2 => self.checked_sqrt(), exp => match self { Self(Small(x)) => x.checked_root(exp).map(|x| Self(Small(x))), Self(Large(xs)) => { let (floor_root_limbs, inexact) = limbs_floor_root(&xs, exp); let floor_root = Self::from_owned_limbs_asc(floor_root_limbs); if inexact { None } else { Some(floor_root) } } }, } } } impl CheckedRoot for &Natural { type Output = Natural; /// Returns the the $n$th root of a [`Natural`], or `None` if the [`Natural`] is not a perfect /// $n$th power. The [`Natural`] is taken by reference. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(999u16)).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(1000u16)).checked_root(3).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Natural::from(1001u16)).checked_root(3).to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(100000000000u64)) /// .checked_root(5) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(10000000000u64)) /// .checked_root(5) /// .to_debug_string(), /// "Some(100)" /// ); /// ``` fn checked_root(self, exp: u64) -> Option { match exp { 0 => panic!("Cannot take 0th root"), 1 => Some(self.clone()), 2 => self.checked_sqrt(), exp => match self { Natural(Small(x)) => x.checked_root(exp).map(|x| Natural(Small(x))), Natural(Large(xs)) => { let (floor_root_limbs, inexact) = limbs_floor_root(xs, exp); let floor_root = Natural::from_owned_limbs_asc(floor_root_limbs); if inexact { None } else { Some(floor_root) } } }, } } } impl RootRem for Natural { type RootOutput = Self; type RemOutput = Self; /// Returns the floor of the $n$th root of a [`Natural`], and the remainder (the difference /// between the [`Natural`] and the $n$th power of the floor). The [`Natural`] is taken by /// value. /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^n)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RootRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(999u16).root_rem(3).to_debug_string(), /// "(9, 270)" /// ); /// assert_eq!( /// Natural::from(1000u16).root_rem(3).to_debug_string(), /// "(10, 0)" /// ); /// assert_eq!( /// Natural::from(1001u16).root_rem(3).to_debug_string(), /// "(10, 1)" /// ); /// assert_eq!( /// Natural::from(100000000000u64).root_rem(5).to_debug_string(), /// "(158, 1534195232)" /// ); /// ``` fn root_rem(self, exp: u64) -> (Self, Self) { match exp { 0 => panic!("Cannot take 0th root"), 1 => (self, Self::ZERO), 2 => self.sqrt_rem(), exp => match self { Self(Small(x)) => { let (root, rem) = x.root_rem(exp); (Self(Small(root)), Self(Small(rem))) } Self(Large(xs)) => { let (root_limbs, rem_limbs) = limbs_root_rem(&xs, exp); ( Self::from_owned_limbs_asc(root_limbs), Self::from_owned_limbs_asc(rem_limbs), ) } }, } } } impl RootRem for &Natural { type RootOutput = Natural; type RemOutput = Natural; /// Returns the floor of the $n$th root of a [`Natural`], and the remainder (the difference /// between the [`Natural`] and the $n$th power of the floor). The [`Natural`] is taken by /// reference. /// /// $f(x, n) = (\lfloor\sqrt\[n\]{x}\rfloor, x - \lfloor\sqrt\[n\]{x}\rfloor^n)$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RootRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(999u16)).root_rem(3).to_debug_string(), /// "(9, 270)" /// ); /// assert_eq!( /// (&Natural::from(1000u16)).root_rem(3).to_debug_string(), /// "(10, 0)" /// ); /// assert_eq!( /// (&Natural::from(1001u16)).root_rem(3).to_debug_string(), /// "(10, 1)" /// ); /// assert_eq!( /// (&Natural::from(100000000000u64)) /// .root_rem(5) /// .to_debug_string(), /// "(158, 1534195232)" /// ); /// ``` fn root_rem(self, exp: u64) -> (Natural, Natural) { match exp { 0 => panic!("Cannot take 0th root"), 1 => (self.clone(), Natural::ZERO), 2 => self.sqrt_rem(), exp => match self { Natural(Small(x)) => { let (root, rem) = x.root_rem(exp); (Natural(Small(root)), Natural(Small(rem))) } Natural(Large(xs)) => { let (root_limbs, rem_limbs) = limbs_root_rem(xs, exp); ( Natural::from_owned_limbs_asc(root_limbs), Natural::from_owned_limbs_asc(rem_limbs), ) } }, } } } impl RootAssignRem for Natural { type RemOutput = Self; /// Replaces a [`Natural`] with the floor of its $n$th root, and returns the remainder (the /// difference between the original [`Natural`] and the $n$th power of the floor). /// /// $f(x, n) = x - \lfloor\sqrt\[n\]{x}\rfloor^n$, /// /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RootAssignRem; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(999u16); /// assert_eq!(x.root_assign_rem(3), 270); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(1000u16); /// assert_eq!(x.root_assign_rem(3), 0); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1001u16); /// assert_eq!(x.root_assign_rem(3), 1); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(100000000000u64); /// assert_eq!(x.root_assign_rem(5), 1534195232); /// assert_eq!(x, 158); /// ``` #[inline] fn root_assign_rem(&mut self, exp: u64) -> Self { let rem; (*self, rem) = (&*self).root_rem(exp); rem } } ================================================ FILE: malachite-nz/src/natural/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl RoundToMultiple for Natural { type Output = Self; /// Rounds a [`Natural`] to a multiple of another [`Natural`], according to a specified rounding /// mode. Both [`Natural`]s are taken by value. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \N$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(5u32) /// .round_to_multiple(Natural::ZERO, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(Natural::from(4u32), Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(Natural::from(4u32), Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(Natural::from(5u32), Exact) /// .to_debug_string(), /// "(10, Equal)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(9, Less)" /// ); /// assert_eq!( /// Natural::from(20u32) /// .round_to_multiple(Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(21, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(14u32) /// .round_to_multiple(Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(16, Greater)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple<&Self> for Natural { type Output = Self; /// Rounds a [`Natural`] to a multiple of another [`Natural`], according to a specified rounding /// mode. The first [`Natural`] is taken by value and the second by reference. An [`Ordering`] /// is also returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \N$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(5u32) /// .round_to_multiple(&Natural::ZERO, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(&Natural::from(4u32), Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(&Natural::from(4u32), Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(&Natural::from(5u32), Exact) /// .to_debug_string(), /// "(10, Equal)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(&Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(9, Less)" /// ); /// assert_eq!( /// Natural::from(20u32) /// .round_to_multiple(&Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(21, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple(&Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(14u32) /// .round_to_multiple(&Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(16, Greater)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple for &Natural { type Output = Natural; /// Rounds a [`Natural`] to a multiple of another [`Natural`], according to a specified rounding /// mode. The first [`Natural`] is taken by reference and the second by value. An [`Ordering`] /// is also returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \N$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(5u32)) /// .round_to_multiple(Natural::ZERO, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(Natural::from(4u32), Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(Natural::from(4u32), Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(Natural::from(5u32), Exact) /// .to_debug_string(), /// "(10, Equal)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(9, Less)" /// ); /// assert_eq!( /// (&Natural::from(20u32)) /// .round_to_multiple(Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(21, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(14u32)) /// .round_to_multiple(Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(16, Greater)" /// ); /// ``` fn round_to_multiple(self, other: Natural, rm: RoundingMode) -> (Natural, Ordering) { match (self, other) { (x, y) if *x == y => (y, Equal), (x, Natural::ZERO) => match rm { Down | Floor | Nearest => (Natural::ZERO, Less), _ => panic!("Cannot round {x} to zero using RoundingMode {rm}"), }, (x, y) => { let r = x % &y; if r == 0 { (x.clone(), Equal) } else { let floor = x - &r; match rm { Down | Floor => (floor, Less), Up | Ceiling => (floor + y, Greater), Nearest => { match (r << 1u64).cmp(&y) { Less => (floor, Less), Greater => (floor + y, Greater), Equal => { // The even multiple of y will have more trailing zeros. if floor == 0 { (floor, Less) } else { let ceiling = &floor + y; if floor.trailing_zeros() > ceiling.trailing_zeros() { (floor, Less) } else { (ceiling, Greater) } } } } } Exact => { panic!("Cannot round {x} to {y} using RoundingMode {rm}") } } } } } } } impl RoundToMultiple<&Natural> for &Natural { type Output = Natural; /// Rounds a [`Natural`] to a multiple of another [`Natural`], according to a specified rounding /// mode. Both [`Natural`]s are taken by reference. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \N$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple(other, Exact)` /// - `{ assert!(x.divisible_by(other)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(5u32)) /// .round_to_multiple(&Natural::ZERO, Down) /// .to_debug_string(), /// "(0, Less)" /// ); /// /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(&Natural::from(4u32), Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(&Natural::from(4u32), Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(&Natural::from(5u32), Exact) /// .to_debug_string(), /// "(10, Equal)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(&Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(9, Less)" /// ); /// assert_eq!( /// (&Natural::from(20u32)) /// .round_to_multiple(&Natural::from(3u32), Nearest) /// .to_debug_string(), /// "(21, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple(&Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(14u32)) /// .round_to_multiple(&Natural::from(4u32), Nearest) /// .to_debug_string(), /// "(16, Greater)" /// ); /// ``` fn round_to_multiple(self, other: &Natural, rm: RoundingMode) -> (Natural, Ordering) { match (self, other) { (x, y) if x == y => (x.clone(), Equal), (x, &Natural::ZERO) => match rm { Down | Floor | Nearest => (Natural::ZERO, Less), _ => panic!("Cannot round {x} to zero using RoundingMode {rm}"), }, (x, y) => { let r = x % y; if r == 0 { (x.clone(), Equal) } else { let floor = x - &r; match rm { Down | Floor => (floor, Less), Up | Ceiling => (floor + y, Greater), Nearest => { match (r << 1u64).cmp(y) { Less => (floor, Less), Greater => (floor + y, Greater), Equal => { // The even multiple of y will have more trailing zeros. if floor == 0 { (floor, Less) } else { let ceiling = &floor + y; if floor.trailing_zeros() > ceiling.trailing_zeros() { (floor, Less) } else { (ceiling, Greater) } } } } } Exact => { panic!("Cannot round {x} to {y} using RoundingMode {rm}") } } } } } } } impl RoundToMultipleAssign for Natural { /// Rounds a [`Natural`] to a multiple of another [`Natural`] in place, according to a specified /// rounding mode. The [`Natural`] on the right-hand side is taken by value. An [`Ordering`] is /// returned, indicating whether the returned value is less than, equal to, or greater than the /// original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(5u32); /// assert_eq!(x.round_to_multiple_assign(Natural::ZERO, Down), Less); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32); /// assert_eq!(x.round_to_multiple_assign(Natural::from(4u32), Down), Less); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// assert_eq!(x.round_to_multiple_assign(Natural::from(4u32), Up), Greater); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(Natural::from(5u32), Exact), /// Equal /// ); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(Natural::from(3u32), Nearest), /// Less /// ); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(20u32); /// assert_eq!( /// x.round_to_multiple_assign(Natural::from(3u32), Nearest), /// Greater /// ); /// assert_eq!(x, 21); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(Natural::from(4u32), Nearest), /// Less /// ); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(14u32); /// assert_eq!( /// x.round_to_multiple_assign(Natural::from(4u32), Nearest), /// Greater /// ); /// assert_eq!(x, 16); /// ``` fn round_to_multiple_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering { match (&mut *self, other) { (x, y) if *x == y => Equal, (x, Self::ZERO) => match rm { Down | Floor | Nearest => { *self = Self::ZERO; Less } _ => panic!("Cannot round {x} to zero using RoundingMode {rm}"), }, (x, y) => { let r = &*x % &y; if r == 0 { Equal } else { *x -= &r; match rm { Down | Floor => Less, Up | Ceiling => { *x += y; Greater } Nearest => { match (r << 1u64).cmp(&y) { Less => Less, Greater => { *x += y; Greater } Equal => { // The even multiple of y will have more trailing zeros. if *x == 0 { Less } else { let ceiling = &*x + y; if x.trailing_zeros() < ceiling.trailing_zeros() { *x = ceiling; Greater } else { Less } } } } } Exact => { panic!("Cannot round {x} to {y} using RoundingMode {rm}") } } } } } } } impl RoundToMultipleAssign<&Self> for Natural { /// Rounds a [`Natural`] to a multiple of another [`Natural`] in place, according to a specified /// rounding mode. The [`Natural`] on the right-hand side is taken by reference. An [`Ordering`] /// is also returned, indicating whether the returned value is less than, equal to, or greater /// than the original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_assign(other, Exact);` /// - `assert!(x.divisible_by(other));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(5u32); /// assert_eq!(x.round_to_multiple_assign(&Natural::ZERO, Down), Less); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32); /// assert_eq!(x.round_to_multiple_assign(&Natural::from(4u32), Down), Less); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(4u32), Up), /// Greater /// ); /// assert_eq!(x, 12); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(5u32), Exact), /// Equal /// ); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(3u32), Nearest), /// Less /// ); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(20u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(3u32), Nearest), /// Greater /// ); /// assert_eq!(x, 21); /// /// let mut x = Natural::from(10u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(4u32), Nearest), /// Less /// ); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(14u32); /// assert_eq!( /// x.round_to_multiple_assign(&Natural::from(4u32), Nearest), /// Greater /// ); /// assert_eq!(x, 16); /// ``` fn round_to_multiple_assign(&mut self, other: &Self, rm: RoundingMode) -> Ordering { match (&mut *self, other) { (x, y) if *x == *y => Equal, (x, &Self::ZERO) => match rm { Down | Floor | Nearest => { *self = Self::ZERO; Less } _ => panic!("Cannot round {x} to zero using RoundingMode {rm}"), }, (x, y) => { let r = &*x % y; if r == 0 { Equal } else { *x -= &r; match rm { Down | Floor => Less, Up | Ceiling => { *x += y; Greater } Nearest => { match (r << 1u64).cmp(y) { Less => Less, Greater => { *x += y; Greater } Equal => { // The even multiple of y will have more trailing zeros. if *x == 0 { Less } else { let ceiling = &*x + y; if x.trailing_zeros() < ceiling.trailing_zeros() { *x = ceiling; Greater } else { Less } } } } } Exact => { panic!("Cannot round {x} to {y} using RoundingMode {rm}") } } } } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use crate::natural::logic::bit_access::limbs_get_bit; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ ModPowerOf2, PowerOf2, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, ShrRound, ShrRoundAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{BitAccess, LowMask}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::{slice_set_zero, slice_test_zero}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` rounded down to a multiple of `2 ^ pow`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! { limbs_round_to_multiple_of_power_of_2_down(xs: &[Limb], pow: u64) -> (Vec, Ordering) { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); if clear_count >= xs_len { (Vec::new(), if slice_test_zero(xs) {Equal} else {Less}) } else { let mut out = vec![0; xs_len]; let (xs_lo, xs_hi) = xs.split_at(clear_count); let mut exact = slice_test_zero(xs_lo); out[clear_count..].copy_from_slice(xs_hi); let small_pow = pow & Limb::WIDTH_MASK; if small_pow != 0 { let out_cc = &mut out[clear_count]; let old = *out_cc; *out_cc &= !Limb::low_mask(small_pow); exact &= *out_cc == old; } (out, if exact {Equal} else {Less}) } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` rounded up to a multiple of `2 ^ pow`. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! { limbs_round_to_multiple_of_power_of_2_up(xs: &[Limb], pow: u64) -> (Vec, Ordering) { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); let mut out; let small_pow = pow & Limb::WIDTH_MASK; let mut exact; if clear_count >= xs_len { out = vec![0; clear_count + 1]; out[clear_count] = Limb::power_of_2(small_pow); exact = false; } else { let (xs_lo, xs_hi) = xs.split_at(clear_count); exact = slice_test_zero(xs_lo); out = vec![0; xs_len]; let out_hi = &mut out[clear_count..]; out_hi.copy_from_slice(xs_hi); if small_pow != 0 { let remainder = out_hi[0].mod_power_of_2(small_pow); if remainder != 0 { out_hi[0] -= remainder; exact = false; } } if !exact && limbs_slice_add_limb_in_place(out_hi, Limb::power_of_2(small_pow)) { out.push(1); } } (out, if exact {Equal} else {Greater}) }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`.s fn limbs_round_to_multiple_of_power_of_2_half_integer_to_even( xs: &[Limb], pow: u64, ) -> (Vec, Ordering) { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); if clear_count >= xs_len { (Vec::new(), if slice_test_zero(xs) { Equal } else { Less }) } else { let (xs_lo, xs_hi) = xs.split_at(clear_count); let mut exact = slice_test_zero(xs_lo); let mut out = vec![0; xs_len]; let out_hi = &mut out[clear_count..]; out_hi.copy_from_slice(xs_hi); let small_pow = pow & Limb::WIDTH_MASK; if small_pow != 0 { out_hi[0] &= !Limb::low_mask(small_pow); exact = false; } if xs_hi[0].get_bit(small_pow) { if limbs_slice_add_limb_in_place(out_hi, Limb::power_of_2(small_pow)) { out.push(1); } (out, Greater) } else { (out, if exact { Equal } else { Less }) } } } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` rounded to the nearest multiple of `2 ^ pow`. If the original value is // exactly between two multiples, it is rounded to the one whose `pow`th bit is zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! { limbs_round_to_multiple_of_power_of_2_nearest(xs: &[Limb], pow: u64) -> (Vec, Ordering) { if pow == 0 { (xs.to_vec(), Equal) } else if !limbs_get_bit(xs, pow - 1) { limbs_round_to_multiple_of_power_of_2_down(xs, pow) } else if !limbs_divisible_by_power_of_2(xs, pow - 1) { limbs_round_to_multiple_of_power_of_2_up(xs, pow) } else { limbs_round_to_multiple_of_power_of_2_half_integer_to_even(xs, pow) } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` rounded to a multiple of `2 ^ pow`, using a specified rounding format. If // the original value is not already a multiple of the power of 2, and the `RoundingMode` is // `Exact`, `None` is returned. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! {limbs_round_to_multiple_of_power_of_2( xs: &[Limb], pow: u64, rm: RoundingMode, ) -> Option<(Vec, Ordering)> { match rm { Down | Floor => { Some(limbs_round_to_multiple_of_power_of_2_down(xs, pow)) } Up | Ceiling => { Some(limbs_round_to_multiple_of_power_of_2_up(xs, pow)) } Nearest => Some(limbs_round_to_multiple_of_power_of_2_nearest(xs, pow)), Exact => { if limbs_divisible_by_power_of_2(xs, pow) { Some((xs.to_vec(), Equal)) } else { None } } } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural`, rounded down to a multiple of `2 ^ pow`, to the input `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! { limbs_round_to_multiple_of_power_of_2_down_in_place(xs: &mut Vec, pow: u64) -> Ordering { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); let mut exact; if clear_count >= xs_len { exact = slice_test_zero(xs); xs.clear(); } else { let (xs_lo, xs_hi) = xs.split_at_mut(clear_count); exact = slice_test_zero(xs_lo); slice_set_zero(xs_lo); let small_pow = pow & Limb::WIDTH_MASK; if small_pow != 0 { let x0 = &mut xs_hi[0]; let old = *x0; *x0 &= !Limb::low_mask(small_pow); exact &= *x0 == old; } } if exact {Equal} else {Less} }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural`, rounded up to a multiple of `2 ^ pow`, to the input `Vec`. The limbs // should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! { limbs_round_to_multiple_of_power_of_2_up_in_place(xs: &mut Vec, pow: u64) -> Ordering { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); let small_pow = pow & Limb::WIDTH_MASK; if clear_count >= xs_len { *xs = vec![0; clear_count + 1]; xs[clear_count] = Limb::power_of_2(small_pow); Greater } else { let (xs_lo, xs_hi) = xs.split_at_mut(clear_count); let mut exact = slice_test_zero(xs_lo); slice_set_zero(xs_lo); if small_pow != 0 { let remainder = xs_hi[0].mod_power_of_2(small_pow); if remainder != 0 { xs_hi[0] -= remainder; exact = false; } } if !exact && limbs_slice_add_limb_in_place(xs_hi, Limb::power_of_2(small_pow)) { xs.push(1); } if exact {Equal} else {Greater} } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. fn limbs_round_to_multiple_of_power_of_2_half_integer_to_even_in_place( xs: &mut Vec, pow: u64, ) -> Ordering { let clear_count = bit_to_limb_count_floor(pow); let xs_len = xs.len(); if clear_count >= xs_len { let exact = slice_test_zero(xs); xs.clear(); if exact { Equal } else { Less } } else { let (xs_lo, xs_hi) = xs.split_at_mut(clear_count); let mut exact = true; if let Some(last) = xs_lo.last_mut() { if *last != 0 { exact = false; } *last = 0; } let small_pow = pow & Limb::WIDTH_MASK; if small_pow != 0 { xs_hi[0] &= !Limb::low_mask(small_pow); exact = false; } if xs_hi[0].get_bit(small_pow) { if limbs_slice_add_limb_in_place(xs_hi, Limb::power_of_2(small_pow)) { xs.push(1); } Greater } else if exact { Equal } else { Less } } } // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural`, rounded to the nearest multiple of `2 ^ pow`, to the input `Vec`. If the // original value is exactly between two multiples, it is rounded to the one whose `pow`th bit is // zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! {limbs_round_to_multiple_of_power_of_2_nearest_in_place( xs: &mut Vec, pow: u64 ) -> Ordering { if pow == 0 { Equal } else if !limbs_get_bit(xs, pow - 1) { limbs_round_to_multiple_of_power_of_2_down_in_place(xs, pow) } else if !limbs_divisible_by_power_of_2(xs, pow - 1) { limbs_round_to_multiple_of_power_of_2_up_in_place(xs, pow) } else { limbs_round_to_multiple_of_power_of_2_half_integer_to_even_in_place(xs, pow) } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` rounded to the nearest multiple of `2 ^ pow` to the input `Vec`, using a // specified rounding format. If the original value is not already a multiple of the power of two, // and the `RoundingMode` is `Exact`, the value of `xs` becomes unspecified and `None` is returned. // Otherwise, an `Ordering` is returned. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), pow / Limb::WIDTH)`. pub_test! {limbs_round_to_multiple_of_power_of_2_in_place( xs: &mut Vec, pow: u64, rm: RoundingMode, ) -> Option { match rm { Down | Floor => { Some(limbs_round_to_multiple_of_power_of_2_down_in_place(xs, pow)) } Up | Ceiling => { Some(limbs_round_to_multiple_of_power_of_2_up_in_place(xs, pow)) } Nearest => Some(limbs_round_to_multiple_of_power_of_2_nearest_in_place( xs, pow, )), Exact => { if limbs_divisible_by_power_of_2(xs, pow) { Some(Equal) } else { None } } } }} impl RoundToMultipleOfPowerOf2 for Natural { type Output = Self; /// Rounds a [`Natural`] to a multiple of $2^k$ according to a specified rounding mode. The /// [`Natural`] is taken by value. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2(pow, Exact)` /// - `{ assert!(x.divisible_by_power_of_2(pow)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple_of_power_of_2(2, Floor) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple_of_power_of_2(2, Ceiling) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple_of_power_of_2(2, Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple_of_power_of_2(2, Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// Natural::from(10u32) /// .round_to_multiple_of_power_of_2(2, Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// Natural::from(12u32) /// .round_to_multiple_of_power_of_2(2, Exact) /// .to_debug_string(), /// "(12, Equal)" /// ); /// ``` #[inline] fn round_to_multiple_of_power_of_2(mut self, pow: u64, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_of_power_of_2_assign(pow, rm); (self, o) } } impl RoundToMultipleOfPowerOf2 for &Natural { type Output = Natural; /// Rounds a [`Natural`] to a multiple of $2^k$ according to a specified rounding mode. The /// [`Natural`] is taken by reference. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2(pow, Exact)` /// - `{ assert!(x.divisible_by_power_of_2(pow)); x }` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple_of_power_of_2(2, Floor) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple_of_power_of_2(2, Ceiling) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple_of_power_of_2(2, Down) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple_of_power_of_2(2, Up) /// .to_debug_string(), /// "(12, Greater)" /// ); /// assert_eq!( /// (&Natural::from(10u32)) /// .round_to_multiple_of_power_of_2(2, Nearest) /// .to_debug_string(), /// "(8, Less)" /// ); /// assert_eq!( /// (&Natural::from(12u32)) /// .round_to_multiple_of_power_of_2(2, Exact) /// .to_debug_string(), /// "(12, Equal)" /// ); /// ``` fn round_to_multiple_of_power_of_2(self, pow: u64, rm: RoundingMode) -> (Natural, Ordering) { match (self, pow) { (_, 0) | (&Natural::ZERO, _) => (self.clone(), Equal), (Natural(Small(small)), pow) => { let (s, o) = small.shr_round(pow, rm); (Natural::from(s) << pow, o) } (Natural(Large(limbs)), pow) => { if let Some((result_limbs, o)) = limbs_round_to_multiple_of_power_of_2(limbs, pow, rm) { (Natural::from_owned_limbs_asc(result_limbs), o) } else { panic!("Rounding {self} to multiple of 2^{pow} is not exact"); } } } } } impl RoundToMultipleOfPowerOf2Assign for Natural { /// Rounds a [`Natural`] to a multiple of $2^k$ in place, according to a specified rounding /// mode. An [`Ordering`] is returned, indicating whether the returned value is less than, equal /// to, or greater than the original value. /// /// See the [`RoundToMultipleOfPowerOf2`] documentation for details. /// /// The following two expressions are equivalent: /// - `x.round_to_multiple_of_power_of_2_assign(pow, Exact);` /// - `assert!(x.divisible_by_power_of_2(pow));` /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Floor), Less); /// assert_eq!(n, 8); /// /// let mut n = Natural::from(10u32); /// assert_eq!( /// n.round_to_multiple_of_power_of_2_assign(2, Ceiling), /// Greater /// ); /// assert_eq!(n, 12); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Down), Less); /// assert_eq!(n, 8); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Up), Greater); /// assert_eq!(n, 12); /// /// let mut n = Natural::from(10u32); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Nearest), Less); /// assert_eq!(n, 8); /// /// let mut n = Natural::from(12u32); /// assert_eq!(n.round_to_multiple_of_power_of_2_assign(2, Exact), Equal); /// assert_eq!(n, 12); /// ``` fn round_to_multiple_of_power_of_2_assign(&mut self, pow: u64, rm: RoundingMode) -> Ordering { match (&mut *self, pow) { (_, 0) | (&mut Self::ZERO, _) => Equal, (Self(Small(small)), pow) => { let o = small.shr_round_assign(pow, rm); *self <<= pow; o } (Self(Large(limbs)), pow) => { if let Some(o) = limbs_round_to_multiple_of_power_of_2_in_place(limbs, pow, rm) { self.trim(); o } else { panic!("Rounding is not exact"); } } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{CheckedSub, SaturatingSub, SaturatingSubAssign}; use malachite_base::num::basic::traits::Zero; impl SaturatingSub for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking both by value and returning 0 if the /// result is negative. /// /// $$ /// f(x, y) = \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSub}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.saturating_sub(Natural::from(123u32)), 0); /// assert_eq!(Natural::from(123u32).saturating_sub(Natural::ZERO), 123); /// assert_eq!( /// Natural::from(456u32).saturating_sub(Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .saturating_sub(Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// ``` #[inline] fn saturating_sub(self, other: Self) -> Self { CheckedSub::checked_sub(self, other).unwrap_or(Self::ZERO) } } impl<'a> SaturatingSub<&'a Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference and returning 0 if the result is negative. /// /// $$ /// f(x, y) = \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSub}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.saturating_sub(&Natural::from(123u32)), 0); /// assert_eq!(Natural::from(123u32).saturating_sub(&Natural::ZERO), 123); /// assert_eq!( /// Natural::from(456u32).saturating_sub(&Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (Natural::from(10u32).pow(12) * Natural::from(3u32)) /// .saturating_sub(&Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// ``` #[inline] fn saturating_sub(self, other: &'a Self) -> Self { CheckedSub::checked_sub(self, other).unwrap_or(Self::ZERO) } } impl SaturatingSub for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value and returning 0 if the result is negative. /// /// $$ /// f(x, y) = \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSub}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).saturating_sub(Natural::from(123u32)), 0); /// assert_eq!((&Natural::from(123u32)).saturating_sub(Natural::ZERO), 123); /// assert_eq!( /// (&Natural::from(456u32)).saturating_sub(Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .saturating_sub(Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// ``` #[inline] fn saturating_sub(self, other: Natural) -> Natural { CheckedSub::checked_sub(self, other).unwrap_or(Natural::ZERO) } } impl SaturatingSub<&Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking both by reference and returning 0 if /// the result is negative. /// /// $$ /// f(x, y) = \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSub}; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).saturating_sub(&Natural::from(123u32)), 0); /// assert_eq!((&Natural::from(123u32)).saturating_sub(&Natural::ZERO), 123); /// assert_eq!( /// (&Natural::from(456u32)).saturating_sub(&Natural::from(123u32)), /// 333 /// ); /// assert_eq!( /// (&(Natural::from(10u32).pow(12) * Natural::from(3u32))) /// .saturating_sub(&Natural::from(10u32).pow(12)), /// 2000000000000u64 /// ); /// ``` #[inline] fn saturating_sub(self, other: &Natural) -> Natural { CheckedSub::checked_sub(self, other).unwrap_or(Natural::ZERO) } } impl SaturatingSubAssign for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value and setting the left-hand side to 0 if the result is negative. /// /// $$ /// x \gets \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSubAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(Natural::from(123u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(Natural::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Natural::from(456u32); /// x.saturating_sub_assign(Natural::from(123u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(Natural::from(456u32)); /// assert_eq!(x, 0); /// ``` #[inline] fn saturating_sub_assign(&mut self, other: Self) { if self.sub_assign_ref_no_panic(&other) { *self = Self::ZERO; } } } impl<'a> SaturatingSubAssign<&'a Self> for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference and setting the left-hand side to 0 if the result is negative. /// /// $$ /// x \gets \max(x - y, 0). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SaturatingSubAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(&Natural::from(123u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(&Natural::ZERO); /// assert_eq!(x, 123); /// /// let mut x = Natural::from(456u32); /// x.saturating_sub_assign(&Natural::from(123u32)); /// assert_eq!(x, 333); /// /// let mut x = Natural::from(123u32); /// x.saturating_sub_assign(&Natural::from(456u32)); /// assert_eq!(x, 0); /// ``` #[inline] fn saturating_sub_assign(&mut self, other: &'a Self) { if self.sub_assign_ref_no_panic(other) { *self = Self::ZERO; } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ CheckedSubMul, SaturatingSubMul, SaturatingSubMulAssign, }; use malachite_base::num::basic::traits::Zero; impl SaturatingSubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by value /// and returning 0 if the result is negative. /// /// $$ /// f(x, y, z) = \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).saturating_sub_mul(Natural::from(3u32), Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32).saturating_sub_mul(Natural::from(3u32), Natural::from(4u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .saturating_sub_mul(Natural::from(0x10000u32), Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` #[inline] fn saturating_sub_mul(self, y: Self, z: Self) -> Self { self.checked_sub_mul(y, z).unwrap_or(Self::ZERO) } } impl SaturatingSubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first two by /// value and the third by reference and returning 0 if the result is negative. /// /// $$ /// f(x, y, z) = \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).saturating_sub_mul(Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32).saturating_sub_mul(Natural::from(3u32), &Natural::from(4u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .saturating_sub_mul(Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` #[inline] fn saturating_sub_mul(self, y: Self, z: &Self) -> Self { self.checked_sub_mul(y, z).unwrap_or(Self::ZERO) } } impl SaturatingSubMul<&Self, Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first and third /// by value and the second by reference and returning 0 if the result is negative. /// /// $$ /// f(x, y, z) = \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).saturating_sub_mul(&Natural::from(3u32), Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32).saturating_sub_mul(&Natural::from(3u32), Natural::from(4u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .saturating_sub_mul(&Natural::from(0x10000u32), Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` #[inline] fn saturating_sub_mul(self, y: &Self, z: Self) -> Self { self.checked_sub_mul(y, z).unwrap_or(Self::ZERO) } } impl SaturatingSubMul<&Self, &Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first by value /// and the second and third by reference and returning 0 if the result is negative. /// /// $$ /// f(x, y, z) = \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).saturating_sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32).saturating_sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 0 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .saturating_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` #[inline] fn saturating_sub_mul(self, y: &Self, z: &Self) -> Self { self.checked_sub_mul(y, z).unwrap_or(Self::ZERO) } } impl SaturatingSubMul<&Natural, &Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by /// reference and returning 0 if the result is negative. /// /// $$ /// f(x, y, z) = \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(20u32)).saturating_sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// (&Natural::from(10u32)).saturating_sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 0 /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .saturating_sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` #[inline] fn saturating_sub_mul(self, y: &Natural, z: &Natural) -> Natural { self.checked_sub_mul(y, z).unwrap_or(Natural::ZERO) } } impl SaturatingSubMulAssign for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking both /// [`Natural`]s on the right-hand side by value and replacing the left-hand side [`Natural`] /// with 0 if the result is negative. /// /// $$ /// x \gets \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.saturating_sub_mul_assign(Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// x.saturating_sub_mul_assign(Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32).pow(12); /// x.saturating_sub_mul_assign(Natural::from(0x10000u32), Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` #[inline] fn saturating_sub_mul_assign(&mut self, y: Self, z: Self) { if self.sub_mul_assign_no_panic(y, z) { *self = Self::ZERO; } } } impl SaturatingSubMulAssign for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking the first /// [`Natural`] on the right-hand side by value and the second by reference and replacing the /// left-hand side [`Natural`] with 0 if the result is negative. /// /// $$ /// x \gets \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.saturating_sub_mul_assign(Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// x.saturating_sub_mul_assign(Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32).pow(12); /// x.saturating_sub_mul_assign(Natural::from(0x10000u32), &Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` #[inline] fn saturating_sub_mul_assign(&mut self, y: Self, z: &Self) { if self.sub_mul_assign_val_ref_no_panic(y, z) { *self = Self::ZERO; } } } impl SaturatingSubMulAssign<&Self, Self> for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking the first /// [`Natural`] on the right-hand side by reference and the second by value and replacing the /// left-hand side [`Natural`] with 0 if the result is negative. /// /// $$ /// x \gets \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.saturating_sub_mul_assign(&Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// x.saturating_sub_mul_assign(&Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32).pow(12); /// x.saturating_sub_mul_assign(&Natural::from(0x10000u32), Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` #[inline] fn saturating_sub_mul_assign(&mut self, y: &Self, z: Self) { if self.sub_mul_assign_ref_val_no_panic(y, z) { *self = Self::ZERO; } } } impl SaturatingSubMulAssign<&Self, &Self> for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking both /// [`Natural`]s on the right-hand side by reference and replacing the left-hand side /// [`Natural`] with 0 if the result is negative. /// /// $$ /// x \gets \max(x - yz, 0). /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SaturatingSubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.saturating_sub_mul_assign(&Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32); /// x.saturating_sub_mul_assign(&Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(10u32).pow(12); /// x.saturating_sub_mul_assign(&Natural::from(0x10000u32), &Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` #[inline] fn saturating_sub_mul_assign(&mut self, y: &Self, z: &Self) { if self.sub_mul_assign_ref_ref_no_panic(y, z) { *self = Self::ZERO; } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/shl.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::vecs::vec_pad_left; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` left-shifted by a `Limb`. // // # Worst-case complexity // $T(n, m) = O(n + m)$ // // $M(n, m) = O(n + m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `bits / Limb::WIDTH`. // // This is equivalent to `mpn_lshift` from `mpn/generic/lshift.c`, GMP 6.2.1, where the result is // returned. pub_crate_test! {limbs_shl(xs: &[Limb], bits: u64) -> Vec { let small_bits = bits & Limb::WIDTH_MASK; let mut out = vec![0; bit_to_limb_count_floor(bits)]; if small_bits == 0 { out.extend_from_slice(xs); } else { let cobits = Limb::WIDTH - small_bits; let mut remaining_bits = 0; for x in xs { out.push((x << small_bits) | remaining_bits); remaining_bits = x >> cobits; } if remaining_bits != 0 { out.push(remaining_bits); } } out }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` left-shifted by a `Limb` to an output slice. The output slice must be at // least as long as the input slice. The `Limb` must be between 1 and `Limb::WIDTH` - 1, inclusive. // The carry, or the bits that are shifted past the width of the input slice, is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`, `bits` is 0, or `bits` is greater than or equal to // `Limb::WIDTH`. // // This is equivalent to `mpn_lshift` from `mpn/generic/lshift.c`, GMP 6.2.1. pub_crate_test! {limbs_shl_to_out(out: &mut [Limb], xs: &[Limb], bits: u64) -> Limb { assert_ne!(bits, 0); assert!(bits < Limb::WIDTH); let cobits = Limb::WIDTH - bits; let mut remaining_bits = 0; for (out, x) in out[..xs.len()].iter_mut().zip(xs.iter()) { *out = (x << bits) | remaining_bits; remaining_bits = x >> cobits; } remaining_bits }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` left-shifted by a `Limb` to the input slice. The `Limb` must be between 1 // and `Limb::WIDTH` - 1, inclusive. The carry, or the bits that are shifted past the width of the // input slice, is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_lshift` from `mpn/generic/lshift.c`, GMP 6.2.1, where `rp == up`. pub_crate_test! {limbs_slice_shl_in_place(xs: &mut [Limb], bits: u64) -> Limb { assert_ne!(bits, 0); assert!(bits < Limb::WIDTH); let cobits = Limb::WIDTH - bits; let mut remaining_bits = 0; for x in &mut *xs { let previous_x = *x; *x = (previous_x << bits) | remaining_bits; remaining_bits = previous_x >> cobits; } remaining_bits }} // Interpreting a nonempty `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes // the limbs of the `Natural` left-shifted by a `Limb` to the input `Vec`. // // # Worst-case complexity // $T(n, m) = O(n + m)$ // // $M(n, m) = O(n + m)$ // // # Panics // Panics if `xs` is empty. // // This is equivalent to `mpn_lshift` from `mpn/generic/lshift.c`, GMP 6.2.1, where `rp == up` and // the carry is appended to `rp`. pub_crate_test! {limbs_vec_shl_in_place(xs: &mut Vec, bits: u64) { let small_bits = bits & Limb::WIDTH_MASK; let remaining_bits = if small_bits == 0 { 0 } else { limbs_slice_shl_in_place(xs, small_bits) }; vec_pad_left(xs, bit_to_limb_count_floor(bits), 0); if remaining_bits != 0 { xs.push(remaining_bits); } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` left-shifted by a `Limb`, and complemented, to an output slice. The output // slice must be at least as long as the input slice. The `Limb` must be between 1 and `Limb::WIDTH` // - 1, inclusive. The carry, or the bits that are shifted past the width of the input slice, is // returned. The carry is not complemented. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`, `xs` is empty, `bits` is 0, or `bits` is greater than or // equal to `Limb::WIDTH`. // // This is equivalent to `mpn_lshiftc` from `mpn/generic/lshift.c`, GMP 6.2.1. pub_crate_test! {limbs_shl_with_complement_to_out( out: &mut [Limb], xs: &[Limb], bits: u64 ) -> Limb { let n = xs.len(); assert_ne!(n, 0); assert_ne!(bits, 0); assert!(bits < Limb::WIDTH); let cobits = Limb::WIDTH - bits; let (xs_last, xs_init) = xs.split_last().unwrap(); let remaining_bits = xs_last >> cobits; let mut previous_x = xs_last << bits; let (out_head, out_tail) = out[..n].split_first_mut().unwrap(); for (out, x) in out_tail.iter_mut().rev().zip(xs_init.iter().rev()) { *out = !(previous_x | (x >> cobits)); previous_x = x << bits; } *out_head = !previous_x; remaining_bits }} fn shl_ref_unsigned(x: &Natural, bits: T) -> Natural where u64: ExactFrom, Limb: ArithmeticCheckedShl, { match (x, bits) { (&Natural::ZERO, _) => x.clone(), (_, bits) if bits == T::ZERO => x.clone(), (Natural(Small(small)), bits) => { Natural(if let Some(shifted) = small.arithmetic_checked_shl(bits) { Small(shifted) } else { Large(limbs_shl(&[*small], u64::exact_from(bits))) }) } (Natural(Large(limbs)), bits) => Natural(Large(limbs_shl(limbs, u64::exact_from(bits)))), } } fn shl_assign(x: &mut Natural, bits: T) where u64: ExactFrom, Limb: ArithmeticCheckedShl, { match (&mut *x, bits) { (&mut Natural::ZERO, _) => {} (_, bits) if bits == T::ZERO => {} (Natural(Small(small)), bits) => { if let Some(shifted) = small.arithmetic_checked_shl(bits) { *small = shifted; } else { *x = Natural(Large(limbs_shl(&[*small], u64::exact_from(bits)))); } } (Natural(Large(limbs)), bits) => { limbs_vec_shl_in_place(limbs, u64::exact_from(bits)); } } } macro_rules! impl_natural_shl_unsigned { ($t:ident) => { impl Shl<$t> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2), taking it by value. /// /// $f(x, k) = x2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(mut self, bits: $t) -> Natural { self <<= bits; self } } impl Shl<$t> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2), taking it by reference. /// /// $f(x, k) = x2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Natural { shl_ref_unsigned(self, bits) } } impl ShlAssign<$t> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2), in place. /// /// $x \gets x2^k$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`.s /// /// # Examples /// See [here](super::shl#shl_assign). #[inline] fn shl_assign(&mut self, bits: $t) { shl_assign(self, bits); } } }; } apply_to_unsigneds!(impl_natural_shl_unsigned); fn shl_ref_signed<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, ) -> Natural where &'a Natural: Shl + Shr, { if bits >= S::ZERO { x << bits.unsigned_abs() } else { x >> bits.unsigned_abs() } } fn shl_assign_signed>(x: &mut Natural, bits: S) where Natural: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x <<= bits.unsigned_abs(); } else { *x >>= bits.unsigned_abs(); } } macro_rules! impl_natural_shl_signed { ($t:ident) => { impl Shl<$t> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2 or divides it by a power of /// 2 and takes the floor), taking it by value. /// /// $$ /// f(x, k) = \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(mut self, bits: $t) -> Natural { self <<= bits; self } } impl<'a> Shl<$t> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies it by a power of 2 or divides it by a power of /// 2 and takes the floor), taking it by reference. /// /// $$ /// f(x, k) = \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Natural { shl_ref_signed(self, bits) } } impl ShlAssign<$t> for Natural { /// Left-shifts a [`Natural`] (multiplies it by a power of 2 or divides it by a power of /// 2 and takes the floor), in place. /// /// $$ /// x \gets \lfloor x2^k \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shl#shl_assign). #[inline] fn shl_assign(&mut self, bits: $t) { shl_assign_signed(self, bits); } } }; } apply_to_signeds!(impl_natural_shl_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign}; use malachite_base::num::arithmetic::traits::{ ShlRound, ShlRoundAssign, ShrRound, ShrRoundAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::rounding_modes::RoundingMode; fn shl_round_ref<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, rm: RoundingMode, ) -> (Natural, Ordering) where &'a Natural: Shl + ShrRound, { if bits >= S::ZERO { (x << bits.unsigned_abs(), Equal) } else { x.shr_round(bits.unsigned_abs(), rm) } } fn shl_round_assign_n>( x: &mut Natural, bits: S, rm: RoundingMode, ) -> Ordering where Natural: ShlAssign + ShrRoundAssign, { if bits >= S::ZERO { *x <<= bits.unsigned_abs(); Equal } else { x.shr_round_assign(bits.unsigned_abs(), rm) } } macro_rules! impl_natural_shl_round_signed { ($t:ident) => { impl ShlRound<$t> for Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies or divides it by a power of 2), taking it by /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the exact value. If `bits` is non-negative, then the returned [`Ordering`] is /// always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only /// be necessary if `bits` is negative. /// /// Let $q = x2^k$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is negative and `rm` is `Exact` but `self` is not /// divisible by $2^{-k}$. /// /// # Examples /// See [here](super::shl_round#shl_round). #[inline] fn shl_round(mut self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { let o = self.shl_round_assign(bits, rm); (self, o) } } impl ShlRound<$t> for &Natural { type Output = Natural; /// Left-shifts a [`Natural`] (multiplies or divides it by a power of 2), taking it by /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is /// also returned, indicating whether the returned value is less than, equal to, or /// greater than the exact value. If `bits` is non-negative, then the returned /// [`Ordering`] is always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only /// be necessary if `bits` is negative. /// /// Let $q = x2^k$, and let $g$ be the function that just returns the first element of /// the pair, without the [`Ordering`]: /// /// $g(x, k, \mathrm{Down}) = g(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $g(x, k, \mathrm{Up}) = g(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// g(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $g(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is negative and `rm` is `Exact` but `self` is not /// divisible by $2^{-k}$. /// /// # Examples /// See [here](super::shl_round#shl_round). #[inline] fn shl_round(self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { shl_round_ref(self, bits, rm) } } impl ShlRoundAssign<$t> for Natural { /// Left-shifts a [`Natural`] (multiplies or divides it by a power of 2) and rounds /// according to the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater than the /// exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `bits > 0 || self.divisible_by_power_of_2(bits)`. Rounding might only /// be necessary if `bits` is negative. /// /// See the [`ShlRound`] documentation for details. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is negative and `rm` is `Exact` but `self` is not /// divisible by $2^{-k}$. /// /// # Examples /// See [here](super::shl_round#shl_round_assign). #[inline] fn shl_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shl_round_assign_n(self, bits, rm) } } }; } apply_to_signeds!(impl_natural_shl_round_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/shr.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::vecs::vec_delete_left; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` right-shifted by a `Limb`, rounding down. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. // // This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where the result is // returned. pub_crate_test! {limbs_shr(xs: &[Limb], bits: u64) -> Vec { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { Vec::new() } else { let mut out = xs[delete_count..].to_vec(); let small_bits = bits & Limb::WIDTH_MASK; if small_bits != 0 { limbs_slice_shr_in_place(&mut out, small_bits); } out } }} // Interpreting a nonempty slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes // the limbs of the `Natural` right-shifted by a `Limb` to an output slice. The output slice must be // at least as long as the input slice. The `Limb` must be between 1 and `Limb::WIDTH` - 1, // inclusive. The carry, or the bits that are shifted past the width of the input slice, is // returned. The input slice should not only contain zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty, `out` is shorter than `xs`, `bits` is 0, or `bits` is greater than or // equal to `Limb::WIDTH`. // // This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1. pub_crate_test! {limbs_shr_to_out(out: &mut [Limb], xs: &[Limb], bits: u64) -> Limb { let len = xs.len(); assert_ne!(len, 0); assert_ne!(bits, 0); assert!(bits < Limb::WIDTH); assert!(out.len() >= len); let cobits = Limb::WIDTH - bits; let (xs_head, xs_tail) = xs.split_first().unwrap(); let remaining_bits = xs_head << cobits; let mut previous_x = xs_head >> bits; let (out_last, out_init) = out[..len].split_last_mut().unwrap(); for (out, x) in out_init.iter_mut().zip(xs_tail.iter()) { *out = previous_x | (x << cobits); previous_x = x >> bits; } *out_last = previous_x; remaining_bits }} // Interpreting a nonempty slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes // the limbs of the `Natural` right-shifted by a `Limb` to the input slice. The `Limb` must be // between 1 and `Limb::WIDTH` - 1, inclusive. The carry, or the bits that are shifted past the // width of the input slice, is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty, `bits` is 0, or `bits` is greater than or equal to `Limb::WIDTH`. // // This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where `rp == up`. pub_crate_test! {limbs_slice_shr_in_place(xs: &mut [T], bits: u64) -> T { assert_ne!(bits, 0); assert!(bits < T::WIDTH); let len = xs.len(); assert_ne!(len, 0); let cobits = T::WIDTH - bits; let mut x = xs[0]; let remaining_bits = x << cobits; let mut previous_x = x >> bits; for i in 1..len { x = xs[i]; xs[i - 1] = previous_x | (x << cobits); previous_x = x >> bits; } *xs.last_mut().unwrap() = previous_x; remaining_bits }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` right-shifted by a `Limb` to the input `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. // // This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where `rp == up` and // if `cnt` is sufficiently large, limbs are removed from `rp`. pub_crate_test! {limbs_vec_shr_in_place(xs: &mut Vec, bits: u64) { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { xs.clear(); } else { let small_shift = bits & Limb::WIDTH_MASK; vec_delete_left(xs, delete_count); if small_shift != 0 { limbs_slice_shr_in_place(xs, small_shift); } } }} fn shr_unsigned_ref + Zero>(x: &Natural, bits: T) -> Natural where u64: ExactFrom, Limb: Shr, { match (x, bits) { (&Natural::ZERO, _) => x.clone(), (_, bits) if bits == T::ZERO => x.clone(), (Natural(Small(_)), bits) if bits >= T::wrapping_from(Limb::WIDTH) => Natural::ZERO, (Natural(Small(small)), bits) => Natural(Small(*small >> bits)), (Natural(Large(limbs)), bits) => { Natural::from_owned_limbs_asc(limbs_shr(limbs, u64::exact_from(bits))) } } } fn shr_assign_unsigned(x: &mut Natural, bits: T) where u64: ExactFrom, Limb: ShrAssign, { match (&mut *x, bits) { (&mut Natural::ZERO, _) => {} (_, bits) if bits == T::ZERO => {} (Natural(Small(small)), bits) if bits >= T::wrapping_from(Limb::WIDTH) => { *small = 0; } (Natural(Small(small)), bits) => { *small >>= bits; } (Natural(Large(limbs)), bits) => { limbs_vec_shr_in_place(limbs, u64::exact_from(bits)); x.trim(); } } } macro_rules! impl_natural_shr_unsigned { ($t:ident) => { impl Shr<$t> for Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), taking /// it by value. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Natural { self >>= bits; self } } impl<'a> Shr<$t> for &Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), taking /// it by reference. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Natural { shr_unsigned_ref(self, bits) } } impl ShrAssign<$t> for Natural { /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), in /// place. /// /// $$ /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_assign_unsigned(self, bits); } } }; } apply_to_unsigneds!(impl_natural_shr_unsigned); fn shr_signed_ref<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, ) -> Natural where &'a Natural: Shl + Shr, { if bits >= S::ZERO { x >> bits.unsigned_abs() } else { x << bits.unsigned_abs() } } fn shr_assign_signed>(x: &mut Natural, bits: S) where Natural: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x >>= bits.unsigned_abs(); } else { *x <<= bits.unsigned_abs(); } } macro_rules! impl_natural_shr_signed { ($t:ident) => { impl Shr<$t> for Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Natural { self >>= bits; self } } impl<'a> Shr<$t> for &Natural { type Output = Natural; /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), taking it by reference. /// /// $$ /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Natural { shr_signed_ref(self, bits) } } impl ShrAssign<$t> for Natural { /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or /// multiplies it by a power of 2), in place. /// /// $$ /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `max(1, /// self.significant_bits() - bits)`. /// /// # Examples /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_assign_signed(self, bits); } } }; } apply_to_signeds!(impl_natural_shr_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/shr_round.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 1998, 1999, 2001, 2002, 2004, 2012, 2015 Free Software // Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::limbs_vec_add_limb_in_place; use crate::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use crate::natural::arithmetic::shr::{ limbs_shr, limbs_slice_shr_in_place, limbs_vec_shr_in_place, }; use crate::natural::logic::bit_access::limbs_get_bit; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::{self, *}; use core::ops::{Shl, ShlAssign}; use malachite_base::num::arithmetic::traits::{Parity, ShrRound, ShrRoundAssign, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::slice_test_zero; use malachite_base::vecs::vec_delete_left; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` right-shifted by a `Limb`, rounding up. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. // // This is equivalent to `cfdiv_q_2exp` from `mpz/cfdiv_q_2exp.c`, GMP 6.2.1, where `u` is // non-negative, `dir == 1`, and the result is returned. pub_test! {limbs_shr_round_up(xs: &[Limb], bits: u64) -> (Vec, Ordering) { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { (vec![1], Greater) } else { let (xs_lo, xs_hi) = xs.split_at(delete_count); let mut exact = slice_test_zero(xs_lo); let mut out = xs_hi.to_vec(); let small_bits = bits & Limb::WIDTH_MASK; if small_bits != 0 { exact &= limbs_slice_shr_in_place(&mut out, small_bits) == 0; } if !exact { limbs_vec_add_limb_in_place(&mut out, 1); } ( out, if exact { Equal } else { Greater }, ) } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. fn limbs_shr_round_half_integer_to_even(xs: &[Limb], bits: u64) -> (Vec, Ordering) { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { (Vec::new(), if slice_test_zero(xs) { Equal } else { Less }) } else { let small_bits = bits & Limb::WIDTH_MASK; let (xs_lo, xs_hi) = xs.split_at(delete_count); let mut exact = slice_test_zero(xs_lo); let mut out = xs_hi.to_vec(); if small_bits != 0 { exact &= limbs_slice_shr_in_place(&mut out, small_bits) == 0; } if !out.is_empty() && out[0].odd() { limbs_vec_add_limb_in_place(&mut out, 1); (out, Greater) } else { (out, if exact { Equal } else { Less }) } } } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` right-shifted by a `Limb`, rounding to the `Natural` nearest to the actual // value of `self` divided by `2 ^ bits`. If the actual value is exactly between two integers, it is // rounded to the even one. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `max(1, xs.len() - // bits / Limb::WIDTH)`. pub_test! {limbs_shr_round_nearest(xs: &[Limb], bits: u64) -> (Vec, Ordering) { if bits == 0 { (xs.to_vec(), Equal) } else { let d = slice_test_zero(xs) || limbs_divisible_by_power_of_2(xs, bits - 1); if !limbs_get_bit(xs, bits - 1) { ( limbs_shr(xs, bits), if d { Equal } else { Less }, ) } else if d { limbs_shr_round_half_integer_to_even(xs, bits) } else { limbs_shr_round_up(xs, bits) } } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` right-shifted by a `Limb`, if the shift is exact (doesn't remove any // `true` bits). If the shift is inexact, `None` is returned. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `max(1, xs.len() - // bits / Limb::WIDTH)`. pub_test! {limbs_shr_exact(xs: &[Limb], bits: u64) -> Option> { if limbs_divisible_by_power_of_2(xs, bits) { Some(limbs_shr(xs, bits)) } else { None } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the `Natural` right-shifted by a `Limb`, rounded using a specified rounding format. The // limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `max(1, xs.len() - // bits / Limb::WIDTH)`. pub_test! { limbs_shr_round(xs: &[Limb], bits: u64, rm: RoundingMode) -> Option<(Vec, Ordering)> { match rm { Down | Floor => Some(( limbs_shr(xs, bits), if limbs_divisible_by_power_of_2(xs, bits) { Equal } else { Less }, )), Up | Ceiling => Some(limbs_shr_round_up(xs, bits)), Nearest => Some(limbs_shr_round_nearest(xs, bits)), Exact => limbs_shr_exact(xs, bits).map(|ss| (ss, Equal)), } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` right-shifted by a `Limb`, rounding up, to the input `Vec`. The limbs // should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. // // This is equivalent to `cfdiv_q_2exp` from `mpz/cfdiv_q_2exp.c`, GMP 6.2.1, where `u` is // non-negative, `dir == 1`, and `w == u`. pub_test! {limbs_vec_shr_round_up_in_place(xs: &mut Vec, bits: u64) -> Ordering { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { xs.truncate(1); xs[0] = 1; Greater } else { let mut exact = slice_test_zero(&xs[..delete_count]); let small_bits = bits & Limb::WIDTH_MASK; vec_delete_left(xs, delete_count); if small_bits != 0 { exact &= limbs_slice_shr_in_place(xs, small_bits) == 0; } if !exact { limbs_vec_add_limb_in_place(xs, 1); } if exact { Equal } else { Greater } } }} // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`. fn limbs_vec_shr_round_half_integer_to_even_in_place(xs: &mut Vec, bits: u64) -> Ordering { let delete_count = bit_to_limb_count_floor(bits); if delete_count >= xs.len() { let o = if slice_test_zero(xs) { Equal } else { Less }; xs.clear(); o } else { let small_bits = bits & Limb::WIDTH_MASK; let mut exact = slice_test_zero(&xs[..delete_count]); vec_delete_left(xs, delete_count); if small_bits != 0 { exact &= limbs_slice_shr_in_place(xs, small_bits) == 0; } if !xs.is_empty() && xs[0].odd() { limbs_vec_add_limb_in_place(xs, 1); Greater } else if exact { Equal } else { Less } } } // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` right-shifted by a `Limb` to the input `Vec`, rounding to the `Natural` // nearest to the actual value of `self` divided by `2 ^ bits`. If the actual value is exactly // between two integers, it is rounded to the even one. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`. pub_test! {limbs_vec_shr_round_nearest_in_place(xs: &mut Vec, bits: u64) -> Ordering { if bits == 0 { Equal } else { let d = slice_test_zero(xs) || limbs_divisible_by_power_of_2(xs, bits - 1); if !limbs_get_bit(xs, bits - 1) { limbs_vec_shr_in_place(xs, bits); if d { Equal } else { Less } } else if d { limbs_vec_shr_round_half_integer_to_even_in_place(xs, bits) } else { limbs_vec_shr_round_up_in_place(xs, bits) } } }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` right-shifted by a `Limb` to the input `Vec`, if the shift is exact // (doesn't remove any `true` bits). Returns whether the shift was exact. The limbs should not all // be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`. pub_test! {limbs_vec_shr_exact_in_place(xs: &mut Vec, bits: u64) -> bool { if limbs_divisible_by_power_of_2(xs, bits) { limbs_vec_shr_in_place(xs, bits); true } else { false } }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the `Natural` right-shifted by a `Limb` to the input `Vec`, rounded using a specified // rounding format. If the shift is inexact (removes some `true` bits) and the `RoundingMode` is // `Exact`, the value of `xs` becomes unspecified and `false` is returned. Otherwise, `true` is // returned. The limbs should not all be zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`. pub_test! {limbs_vec_shr_round_in_place( xs: &mut Vec, bits: u64, rm: RoundingMode, ) -> (bool, Ordering) { match rm { Down | Floor => { let exact = limbs_divisible_by_power_of_2(xs, bits); limbs_vec_shr_in_place(xs, bits); ( true, if exact { Equal } else { Less }, ) } Up | Ceiling => { (true, limbs_vec_shr_round_up_in_place(xs, bits)) } Nearest => (true, limbs_vec_shr_round_nearest_in_place(xs, bits)), Exact => (limbs_vec_shr_exact_in_place(xs, bits), Equal), } }} fn shr_round_unsigned_ref_n( x: &Natural, bits: T, rm: RoundingMode, ) -> (Natural, Ordering) where u64: ExactFrom, Limb: ShrRound, { match (x, bits) { (&Natural::ZERO, _) => (x.clone(), Equal), (_, bits) if bits == T::ZERO => (x.clone(), Equal), (Natural(Small(small)), bits) => { let (s, o) = small.shr_round(bits, rm); (Natural(Small(s)), o) } (Natural(Large(limbs)), bits) => { if let Some((out, o)) = limbs_shr_round(limbs, u64::exact_from(bits), rm) { (Natural::from_owned_limbs_asc(out), o) } else { panic!("Right shift is not exact: {x} >> {bits}"); } } } } fn shr_round_assign_unsigned_n( x: &mut Natural, bits: T, rm: RoundingMode, ) -> Ordering where u64: ExactFrom, Limb: ShrRoundAssign, { match (&mut *x, bits) { (&mut Natural::ZERO, _) => Equal, (_, bits) if bits == T::ZERO => Equal, (Natural(Small(small)), bits) => small.shr_round_assign(bits, rm), (Natural(Large(limbs)), bits) => { let (b, o) = limbs_vec_shr_round_in_place(limbs, u64::exact_from(bits), rm); assert!(b, "Right shift is not exact."); x.trim(); o } } } macro_rules! impl_natural_shr_round_unsigned { ($t:ident) => { impl ShrRound<$t> for Natural { type Output = Natural; /// Shifts a [`Natural`] right (divides it by a power of 2), taking it by value, and /// rounds according to the specified rounding mode. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { let o = self.shr_round_assign(bits, rm); (self, o) } } impl<'a> ShrRound<$t> for &Natural { type Output = Natural; /// Shifts a [`Natural`] right (divides it by a power of 2), taking it by reference, and /// rounds according to the specified rounding mode. An [`Ordering`] is also returned, /// indicating whether the returned value is less than, equal to, or greater than the /// exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(1, self.significant_bits() - bits)`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { shr_round_unsigned_ref_n(self, bits, rm) } } impl ShrRoundAssign<$t> for Natural { /// Shifts a [`Natural`] right (divides it by a power of 2) and rounds according to the /// specified rounding mode, in place. An [`Ordering`] is returned, indicating whether /// the assigned value is less than, equal to, or greater than the exact value. /// /// Passing `Floor` or `Down` is equivalent to using `>>=`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shr_round_assign_unsigned_n(self, bits, rm) } } }; } apply_to_unsigneds!(impl_natural_shr_round_unsigned); fn shr_round_signed_ref_n<'a, U, S: PrimitiveSigned + UnsignedAbs>( x: &'a Natural, bits: S, rm: RoundingMode, ) -> (Natural, Ordering) where &'a Natural: Shl + ShrRound, { if bits >= S::ZERO { x.shr_round(bits.unsigned_abs(), rm) } else { (x << bits.unsigned_abs(), Equal) } } fn shr_round_assign_signed_n>( x: &mut Natural, bits: S, rm: RoundingMode, ) -> Ordering where Natural: ShlAssign + ShrRoundAssign, { if bits >= S::ZERO { x.shr_round_assign(bits.unsigned_abs(), rm) } else { *x <<= bits.unsigned_abs(); Equal } } macro_rules! impl_natural_shr_round_signed { ($t:ident) => { impl ShrRound<$t> for Natural { type Output = Natural; /// Shifts a [`Natural`] right (divides or multiplies it by a power of 2), taking it by /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater /// than the exact value. If `bits` is negative, then the returned [`Ordering`] is /// always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { let o = self.shr_round_assign(bits, rm); (self, o) } } impl<'a> ShrRound<$t> for &Natural { type Output = Natural; /// Shifts a [`Natural`] right (divides or multiplies it by a power of 2), taking it by /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is /// also returned, indicating whether the returned value is less than, equal to, or /// greater than the exact value. If `bits` is negative, then the returned [`Ordering`] /// is always `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first /// element of the pair, without the [`Ordering`]: /// /// $f(x, k, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// \lfloor q \rfloor & \text{if} /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\ /// \lceil q \rceil & \text{if} /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\ /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even}, \\\\ /// \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} /// \\ \lfloor q \rfloor \\ \text{is odd}. /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \N$. /// /// Then /// /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round). #[inline] fn shr_round(self, bits: $t, rm: RoundingMode) -> (Natural, Ordering) { shr_round_signed_ref_n(self, bits, rm) } } impl ShrRoundAssign<$t> for Natural { /// Shifts a [`Natural`] right (divides or multiplies it by a power of 2) and rounds /// according to the specified rounding mode, in place. An [`Ordering`] is returned, /// indicating whether the assigned value is less than, equal to, or greater than the /// exact value. If `bits` is negative, then the returned [`Ordering`] is always /// `Equal`, even if the higher bits of the result are lost. /// /// Passing `Floor` or `Down` is equivalent to using `>>`. To test whether `Exact` can /// be passed, use `self.divisible_by_power_of_2(bits)`. /// /// See the [`ShrRound`] documentation for details. /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(-bits, 0)`. /// /// # Panics /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not /// divisible by $2^k$. /// /// # Examples /// See [here](super::shr_round#shr_round_assign). #[inline] fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering { shr_round_assign_signed_n(self, bits, rm) } } }; } apply_to_signeds!(impl_natural_shr_round_signed); ================================================ FILE: malachite-nz/src/natural/arithmetic/sign.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; impl Sign for Natural { /// Compares a [`Natural`] to zero. /// /// Returns `Greater` or `Equal` depending on whether the [`Natural`] is positive or zero, /// respectively. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_base::num::arithmetic::traits::Sign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.sign(), Equal); /// assert_eq!(Natural::from(123u32).sign(), Greater); /// ``` fn sign(&self) -> Ordering { if *self == 0 { Equal } else { Greater } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/sqrt.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Contributed to the GNU project by Paul Zimmermann (most code), Torbjörn Granlund // (`mpn_sqrtrem1`) and Marco Bodrato (`mpn_dc_sqrt`). // // Copyright © 1999-2002, 2004, 2005, 2008, 2010, 2012, 2015, 2017 Free Software Foundation, // Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, limbs_vec_add_limb_in_place, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::div::{ limbs_div_barrett_approx, limbs_div_barrett_approx_scratch_len, limbs_div_divide_and_conquer_approx, limbs_div_schoolbook_approx, }; use crate::natural::arithmetic::div_mod::{ limbs_div_limb_to_out_mod, limbs_div_mod_qs_to_out_rs_to_ns, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::mul::{ limbs_mul_greater_to_out, limbs_mul_greater_to_out_scratch_len, }; use crate::natural::arithmetic::shl::limbs_shl_to_out; use crate::natural::arithmetic::shr::{limbs_shr_to_out, limbs_slice_shr_in_place}; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, }; use crate::natural::arithmetic::sub_mul::limbs_sub_mul_limb_same_length_in_place_left; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{DC_DIVAPPR_Q_THRESHOLD, Limb, MU_DIVAPPR_Q_THRESHOLD, SignedLimb}; use alloc::vec::Vec; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::sqrt::sqrt_rem_2_newton; use malachite_base::num::arithmetic::sqrt::sqrt_rem_newton; use malachite_base::num::arithmetic::traits::{ CeilingSqrt, CeilingSqrtAssign, CheckedSqrt, FloorSqrt, FloorSqrtAssign, ModPowerOf2, Parity, ShrRound, SqrtAssignRem, SqrtRem, Square, WrappingSquare, WrappingSubAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, LeadingZeros, LowMask}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::slice_test_zero; pub_const_test! {limbs_sqrt_rem_helper_scratch_len(n: usize) -> usize { (n >> 1) + 1 }} // - Let n be out.len(). // - Let x be xs[..2 * n] before execution. // - Let s be out after execution. // - Let r be xs[..n] after execution. // // xs[2 * n - 1].leading_zeros() must be less than 2. // // If approx = 0, then s = floor(sqrt(x)) and r = x - s ^ 2. // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1. pub_test! {limbs_sqrt_rem_helper( out: &mut [Limb], xs: &mut [Limb], approx: Limb, scratch: &mut [Limb], ) -> bool { let n = out.len(); assert!(n > 1); let xs = &mut xs[..n << 1]; assert!(xs.last().unwrap().leading_zeros() < 2); let h1 = n >> 1; let h2 = n - h1; let two_h1 = h1 << 1; let xs_hi = &mut xs[two_h1..]; let out_hi = &mut out[h1..]; let q = if h2 == 1 { let r_hi; (out_hi[0], r_hi, xs_hi[0]) = sqrt_rem_2_newton::(xs_hi[1], xs_hi[0]); r_hi } else { limbs_sqrt_rem_helper(out_hi, xs_hi, 0, scratch) }; if q { assert!(limbs_sub_same_length_in_place_left( &mut xs_hi[..h2], out_hi )); } let xs_hi = &mut xs[h1..]; if h2 == 1 { xs_hi[0] = limbs_div_limb_to_out_mod(scratch, &xs_hi[..n], out_hi[0]); } else { limbs_div_mod_qs_to_out_rs_to_ns(scratch, &mut xs_hi[..n], out_hi); } let mut q = Limb::from(q); q += scratch[h1]; let mut r_hi = scratch[0].odd(); limbs_shr_to_out(out, &scratch[..h1], 1); out[h1 - 1] |= q << (Limb::WIDTH - 1); if (out[0] & approx) != 0 { return true; } q >>= 1; let (out_lo, out_hi) = out.split_at_mut(h1); if r_hi { r_hi = limbs_slice_add_same_length_in_place_left(&mut xs_hi[..h2], out_hi); } let (xs, xs_hi_hi) = xs.split_at_mut(n); let (xs_lo, xs_hi) = xs.split_at_mut(two_h1); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(h1)]; limbs_square_to_out(xs_hi_hi, out_lo, &mut square_scratch); let mut b = q; if limbs_sub_same_length_in_place_left(xs_lo, &xs_hi_hi[..two_h1]) { b += 1; } let mut r_hi = SignedLimb::from(r_hi); r_hi -= if h1 == h2 { SignedLimb::exact_from(b) } else { SignedLimb::from(limbs_sub_limb_in_place(xs_hi, b)) }; if r_hi < 0 { q = Limb::from(limbs_slice_add_limb_in_place(out_hi, q)); r_hi += SignedLimb::exact_from( limbs_slice_add_mul_limb_same_length_in_place_left(xs, out, 2) + (q << 1), ); if limbs_sub_limb_in_place(xs, 1) { r_hi -= 1; } limbs_sub_limb_in_place(out, 1); } assert!(r_hi >= 0); assert!(r_hi < 2); r_hi == 1 }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_divappr_q` from `mpn/generic/sqrtrem.c`, GMP 6.2.1. fn limbs_sqrt_div_approx_helper(qs: &mut [Limb], ns: &[Limb], ds: &[Limb], scratch: &mut [Limb]) { let n_len = ns.len(); let d_len = ds.len(); assert!(d_len > 2); assert!(n_len >= d_len); assert!(ds.last().unwrap().get_highest_bit()); let scratch = &mut scratch[..n_len]; scratch.copy_from_slice(ns); let inv = limbs_two_limb_inverse_helper(ds[d_len - 1], ds[d_len - 2]); qs[n_len - d_len] = Limb::from(if d_len < DC_DIVAPPR_Q_THRESHOLD { limbs_div_schoolbook_approx(qs, scratch, ds, inv) } else if d_len < MU_DIVAPPR_Q_THRESHOLD { limbs_div_divide_and_conquer_approx(qs, scratch, ds, inv) } else { let mut new_scratch = vec![0; limbs_div_barrett_approx_scratch_len(n_len, d_len)]; limbs_div_barrett_approx(qs, ns, ds, &mut new_scratch) }); } // - Let n be out.len(). // - Let m be xs.len(). // - n must be ceiling(m / 2). // - odd must be m.odd(). // - shift must be floor(xs[m - 1].leading_zeros() / 2). // - Let x be xs before execution. // - Let s be out after execution. // - Then s = floor(sqrt(x)). // - The return value is true iff there is a remainder (that is, x is not a perfect square). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_sqrt` from `mpn/generic/sqrtrem.c`, GMP 6.2.1. pub_test! { limbs_sqrt_helper(out: &mut [Limb], xs: &[Limb], shift: u64, odd: bool) -> bool { let n = out.len(); let odd = usize::from(odd); assert_eq!(xs.len(), (n << 1) - odd); assert_ne!(*xs.last().unwrap(), 0); assert!(n > 4); assert!(shift < Limb::WIDTH >> 1); let h1 = (n - 1) >> 1; let h2 = n - h1; let (out_lo, out_hi) = out.split_at_mut(h1); let mut scratch = vec![0; (n << 1) + h1 + 4]; let scratch_hi = &mut scratch[n..]; // length is n + h1 + 4 if shift != 0 { // o is used to exactly set the lowest bits of the dividend. let o = usize::from(h1 > (1 + odd)); assert_eq!( limbs_shl_to_out( &mut scratch_hi[1 - o..], &xs[h1 - 1 - o - odd..(n << 1) - odd], shift << 1 ), 0 ); } else { scratch_hi[1..n + h2 + 2].copy_from_slice(&xs[h1 - 1 - odd..(n << 1) - odd]); } let (scratch_lo, scratch_hi) = scratch.split_at_mut(n + 1); // scratch_hi len is n + h1 + 3 let r_hi = limbs_sqrt_rem_helper(out_hi, &mut scratch_hi[h1 + 1..=n + h2], 0, scratch_lo); if r_hi { assert!(limbs_sub_same_length_in_place_left( &mut scratch_hi[h1 + 1..=n], out_hi )); } // qs len is h1 + 2 let (scratch_hi_lo, qs) = scratch_hi.split_at_mut(n + 1); limbs_sqrt_div_approx_helper(qs, scratch_hi_lo, out_hi, scratch_lo); // qs_tail len is h1 + 1 let (qs_head, qs_tail) = qs.split_first_mut().unwrap(); let mut qs_last = Limb::from(r_hi); qs_last += qs_tail[h1]; let mut nonzero_remainder = true; if qs_last > 1 { for x in out_lo { *x = Limb::MAX; } } else { limbs_shr_to_out(out_lo, &qs_tail[..h1], 1); if qs_last != 0 { out_lo.last_mut().unwrap().set_bit(Limb::WIDTH - 1); } let s = (Limb::WIDTH >> odd) - shift - 1; if (*qs_head >> 3) | qs_tail[0].mod_power_of_2(Limb::WIDTH - s) == 0 { // Approximation is not good enough, the extra limb(+ shift bits) is smaller than needed // to absorb the possible error. {qs + 1, h1 + 1} equals 2*{out, h1} let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(out_hi.len(), qs_tail.len())]; assert_eq!( limbs_mul_greater_to_out(scratch_lo, out_hi, qs_tail, &mut mul_scratch), 0 ); // scratch_hi_1 len is n + h1 + 2 let scratch_hi_1 = &mut scratch_hi[1..]; // scratch_lo_hi len is h1 + 1 let (scratch_lo_lo, scratch_lo_hi) = scratch_lo.split_at_mut(h2); // scratch_hi_1_hi len is 2 * h1 + 2 let (scratch_hi_1_lo, scratch_hi_1_hi) = scratch_hi_1.split_at_mut(h2); // Compute the remainder of the previous mpn_div(appr)_q. if limbs_sub_same_length_in_place_left(scratch_hi_1_lo, scratch_lo_lo) { assert!(!limbs_sub_limb_in_place(&mut scratch_hi_1_hi[..h1], 1)); } let cmp = limbs_cmp_same_length(&scratch_hi_1_hi[..h1], &scratch_lo_hi[..h1]); assert_ne!(cmp, Greater); if cmp == Less { // May happen only if div result was not exact. let carry = limbs_slice_add_mul_limb_same_length_in_place_left(scratch_hi_1_lo, out_hi, 2); assert!(!limbs_slice_add_limb_in_place( &mut scratch_hi_1_hi[..h1], carry )); assert!(!limbs_sub_limb_in_place(out_lo, 1)); } // scratch_hi_1_hi len is 2 * h1 + 2 let (scratch_hi_1_lo, scratch_hi_1_hi) = scratch_hi_1.split_at_mut(h1); if slice_test_zero(&scratch_hi_1_hi[..h2 - h1]) { let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(out_lo.len())]; limbs_square_to_out(scratch_lo, out_lo, &mut square_scratch); // scratch_lo_hi len is h2 + 1 let (scratch_lo_lo, scratch_lo_hi) = scratch_lo.split_at(h1); let mut cmp = limbs_cmp_same_length(scratch_hi_1_lo, &scratch_lo_hi[..h1]); if cmp == Equal { let scratch = &scratch_lo_lo[odd..]; cmp = if shift != 0 { limbs_shl_to_out(scratch_hi, &xs[..h1], shift << 1); limbs_cmp_same_length(&scratch_hi[..h1 - odd], scratch) } else { limbs_cmp_same_length(&xs[..h1 - odd], scratch) }; } if cmp == Less { assert!(!limbs_sub_limb_in_place(out_lo, 1)); } nonzero_remainder = cmp != Equal; } } } if odd == 1 || shift != 0 { let mut shift = shift; if odd == 1 { shift.set_bit(Limb::LOG_WIDTH - 1); } limbs_slice_shr_in_place(out, shift); } nonzero_remainder }} // Computes the floor of the square root of a `Natural`. // // - Let $n$ be `xs.len()` and $x$ be the `Natural` whose limbs are `xs`. // - Let $s$ be the `Natural` whose limbs are the first $\lceil n/2 \rceil$ limbs of `out`. // - Then $s = \lfloor \sqrt x \rfloor$. // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where `rp` is // `NULL`. pub_test! {limbs_sqrt_to_out(out: &mut [Limb], xs: &[Limb]) { let xs_len = xs.len(); let high = xs[xs_len - 1]; assert_ne!(high, 0); let mut shift = LeadingZeros::leading_zeros(high) >> 1; let two_shift = shift << 1; match xs_len { 1 => { out[0] = sqrt_rem_newton::(high << two_shift).0 >> shift; } 2 => { out[0] = if shift == 0 { sqrt_rem_2_newton::(xs[1], xs[0]).0 } else { let lo = xs[0]; sqrt_rem_2_newton::( (high << two_shift) | (lo >> (Limb::WIDTH - two_shift)), lo << two_shift, ) .0 >> shift }; } _ if xs_len > 8 => { let out_len = xs_len.shr_round(1, Ceiling).0; limbs_sqrt_helper(&mut out[..out_len], xs, shift, xs_len.odd()); } _ => { let out_len = xs_len.shr_round(1, Ceiling).0; let out = &mut out[..out_len]; if xs_len.odd() || shift != 0 { let scratch_1_len = out_len << 1; let mut scratch = vec![0; scratch_1_len + (out_len >> 1) + 1]; let (scratch_1, scratch_2) = scratch.split_at_mut(scratch_1_len); // needed only when 2 * out_len > xs_len, but saves a test let shifted_scratch_1 = if xs_len.odd() { &mut scratch_1[1..] } else { scratch_1[0] = 0; &mut *scratch_1 }; if shift == 0 { shifted_scratch_1.copy_from_slice(xs); } else { limbs_shl_to_out(shifted_scratch_1, xs, two_shift); } if xs_len.odd() { shift += Limb::WIDTH >> 1; } limbs_sqrt_rem_helper(out, scratch_1, Limb::low_mask(shift) - 1, scratch_2); limbs_slice_shr_in_place(out, shift); } else { let mut rem = xs.to_vec(); let mut scratch = vec![0; (out_len >> 1) + 1]; limbs_sqrt_rem_helper(out, &mut rem, 0, &mut scratch); } } } }} // Computes the square root and remainder of a `Natural`. // // Let $n$ be `xs.len()` and $x$ be the `Natural` whose limbs are `xs`. Let $s$ be the `Natural` // whose limbs are the first $\lceil n/2 \rceil$ limbs of `out_sqrt`, $m$ the return value, and $r$ // be the `Natural` whose limbs are the first $m$ limbs of `out_rem`. Then $s = \lfloor \sqrt x // \rfloor$ and $s^2 + r = x$. This implies that $r \leq 2x$. // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where `rp` is not // `NULL`. pub_test! {limbs_sqrt_rem_to_out( out_sqrt: &mut [Limb], out_rem: &mut [Limb], xs: &[Limb] ) -> usize { let xs_len = xs.len(); let high = xs[xs_len - 1]; assert_ne!(high, 0); let mut shift = LeadingZeros::leading_zeros(high) >> 1; let two_shift = shift << 1; match xs_len { 1 => { let r_lo = if shift == 0 { let r; (out_sqrt[0], r) = sqrt_rem_newton::(high); r } else { let sqrt = sqrt_rem_newton::(high << two_shift).0 >> shift; out_sqrt[0] = sqrt; high - sqrt.square() }; out_rem[0] = r_lo; usize::from(r_lo != 0) } 2 => { if shift == 0 { let r_hi; (out_sqrt[0], r_hi, out_rem[0]) = sqrt_rem_2_newton::(xs[1], xs[0]); if r_hi { out_rem[1] = 1; 2 } else { usize::from(out_rem[0] != 0) } } else { let mut lo = xs[0]; let hi = (high << two_shift) | (lo >> (Limb::WIDTH - two_shift)); out_sqrt[0] = sqrt_rem_2_newton::(hi, lo << two_shift).0 >> shift; lo.wrapping_sub_assign(out_sqrt[0].wrapping_square()); out_rem[0] = lo; usize::from(lo != 0) } } _ => { let mut out_len = xs_len.shr_round(1, Ceiling).0; let out_sqrt = &mut out_sqrt[..out_len]; if xs_len.odd() || shift != 0 { let scratch_1_len = out_len << 1; let mut scratch = vec![0; scratch_1_len + (out_len >> 1) + 1]; let (mut scratch_1, scratch_2) = scratch.split_at_mut(scratch_1_len); // needed only when 2 * out_len > xs_len, but saves a test let shifted_scratch_1 = if xs_len.odd() { &mut scratch_1[1..] } else { scratch_1[0] = 0; &mut *scratch_1 }; if shift == 0 { shifted_scratch_1.copy_from_slice(xs); } else { limbs_shl_to_out(shifted_scratch_1, xs, two_shift); } if xs_len.odd() { shift += Limb::WIDTH >> 1; } let r_hi = limbs_sqrt_rem_helper(out_sqrt, scratch_1, 0, scratch_2); let s = out_sqrt[0] & Limb::low_mask(shift); let scratch_1_lo = &mut scratch_1[..out_len]; let mut r_lo = limbs_slice_add_mul_limb_same_length_in_place_left( scratch_1_lo, out_sqrt, s << 1, ); if r_hi { r_lo += 1; } let (scratch_1_lo_lo, scratch_1_lo_hi) = scratch_1_lo.split_at_mut(1); let carry = limbs_sub_mul_limb_same_length_in_place_left(scratch_1_lo_lo, &[s], s); if limbs_sub_limb_in_place(scratch_1_lo_hi, carry) { r_lo -= 1; } limbs_slice_shr_in_place(out_sqrt, shift); scratch_1[out_len] = r_lo; shift <<= 1; if shift < Limb::WIDTH { out_len += 1; } else { scratch_1 = &mut scratch_1[1..]; shift -= Limb::WIDTH; } let scratch_1 = &mut scratch_1[..out_len]; if shift == 0 { out_rem[..out_len].copy_from_slice(scratch_1); } else { limbs_shr_to_out(out_rem, scratch_1, shift); } } else { out_rem[..xs_len].copy_from_slice(xs); let mut scratch = vec![0; (out_len >> 1) + 1]; if limbs_sqrt_rem_helper(out_sqrt, out_rem, 0, &mut scratch) { out_rem[out_len] = 1; out_len += 1; } } out_len } } }} // This is equivalent to `mpn_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where `rp` is not // `NULL`, only returning whether the remainder is nonzero, rather than computing it in full. pub(crate) fn limbs_sqrt_to_out_return_inexact(out_sqrt: &mut [Limb], xs: &[Limb]) -> bool { let xs_len = xs.len(); let high = xs[xs_len - 1]; assert_ne!(high, 0); let mut shift = LeadingZeros::leading_zeros(high) >> 1; let two_shift = shift << 1; match xs_len { 1 => { let r_lo = if shift == 0 { let r; (out_sqrt[0], r) = sqrt_rem_newton::(high); r } else { let sqrt = sqrt_rem_newton::(high << two_shift).0 >> shift; out_sqrt[0] = sqrt; high - sqrt.square() }; r_lo != 0 } 2 => { if shift == 0 { let r_hi; let r_0; (out_sqrt[0], r_hi, r_0) = sqrt_rem_2_newton::(xs[1], xs[0]); r_hi || r_0 != 0 } else { let mut lo = xs[0]; let hi = (high << two_shift) | (lo >> (Limb::WIDTH - two_shift)); out_sqrt[0] = sqrt_rem_2_newton::(hi, lo << two_shift).0 >> shift; lo.wrapping_sub_assign(out_sqrt[0].wrapping_square()); lo != 0 } } _ => { let mut out_len = xs_len.shr_round(1, Ceiling).0; let out_sqrt = &mut out_sqrt[..out_len]; let mut out_rem; let mut scratch; let out = if xs_len.odd() || shift != 0 { let scratch_1_len = out_len << 1; scratch = vec![0; scratch_1_len + (out_len >> 1) + 1]; let (mut scratch_1, scratch_2) = scratch.split_at_mut(scratch_1_len); // needed only when 2 * out_len > xs_len, but saves a test let shifted_scratch_1 = if xs_len.odd() { &mut scratch_1[1..] } else { scratch_1[0] = 0; &mut *scratch_1 }; if shift == 0 { shifted_scratch_1.copy_from_slice(xs); } else { limbs_shl_to_out(shifted_scratch_1, xs, two_shift); } if xs_len.odd() { shift += Limb::WIDTH >> 1; } let r_hi = limbs_sqrt_rem_helper(out_sqrt, scratch_1, 0, scratch_2); let s = out_sqrt[0] & Limb::low_mask(shift); let scratch_1_lo = &mut scratch_1[..out_len]; let mut r_lo = limbs_slice_add_mul_limb_same_length_in_place_left( scratch_1_lo, out_sqrt, s << 1, ); if r_hi { r_lo += 1; } let (scratch_1_lo_lo, scratch_1_lo_hi) = scratch_1_lo.split_at_mut(1); let carry = limbs_sub_mul_limb_same_length_in_place_left(scratch_1_lo_lo, &[s], s); if limbs_sub_limb_in_place(scratch_1_lo_hi, carry) { r_lo -= 1; } limbs_slice_shr_in_place(out_sqrt, shift); scratch_1[out_len] = r_lo; shift <<= 1; if shift < Limb::WIDTH { out_len += 1; } else { scratch_1 = &mut scratch_1[1..]; } scratch_1 } else { let mut scratch = vec![0; (out_len >> 1) + 1]; out_rem = xs.to_vec(); if limbs_sqrt_rem_helper(out_sqrt, &mut out_rem, 0, &mut scratch) { out_rem[out_len] = 1; out_len += 1; } &out_rem[..] }; out[..out_len].iter().any(|&x| x != 0) } } } // Computes the floor of the square root of a `Natural`. // // Let $x$ be the `Natural` whose limbs are `xs` and $s$ be the `Natural` whose limbs are returned. // Then $s = \lfloor \sqrt x \rfloor$. // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_floor_sqrt(xs: &[Limb]) -> Vec { let mut out = vec![0; xs.len().shr_round(1, Ceiling).0]; limbs_sqrt_to_out(&mut out, xs); out }} // Computes the ceiling of the square root of a `Natural`. // // Let $x$ be the `Natural` whose limbs are `xs` and $s$ be the `Natural` whose limbs are returned. // Then $s = \lceil \sqrt x \rceil$. // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // TODO pub_test! {limbs_ceiling_sqrt(xs: &[Limb]) -> Vec { let xs_len = xs.len(); let mut out_sqrt = vec![0; xs_len.shr_round(1, Ceiling).0]; let mut out_rem = vec![0; xs_len]; let rem_len = limbs_sqrt_rem_to_out(&mut out_sqrt, &mut out_rem, xs); if !slice_test_zero(&out_rem[..rem_len]) { limbs_vec_add_limb_in_place(&mut out_sqrt, 1); } out_sqrt }} // Computes the square root of a `Natural`, returning `None` if the `Natural` is not a perfect // square. // // Let $x$ be the `Natural` whose limbs are `xs` and $s$ be the `Natural` whose limbs are returned. // // $$ // s = \\begin{cases} // \operatorname{Some}(\sqrt{x}) & \sqrt{x} \in \Z \\\\ // \operatorname{None} & \textrm{otherwise}. // \\end{cases} // $$ // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_checked_sqrt(xs: &[Limb]) -> Option> { let xs_len = xs.len(); let mut out_sqrt = vec![0; xs_len.shr_round(1, Ceiling).0]; if limbs_sqrt_to_out_return_inexact(&mut out_sqrt, xs) { None } else { Some(out_sqrt) } }} // Computes the square root and remainder of a `Natural`. // // Let `out_sqrt` and `out_rem` be the two returned `Limb` `Vec`s. Let $n$ be `xs.len()` and $x$ be // the `Natural` whose limbs are `xs`. Let $s$ be the `Natural` whose limbs are the first $\lceil // n/2 \rceil$ limbs of `out_sqrt` and $r$ be the `Natural` whose limbs are the first $n$ limbs of // `out_rem`. Then $s = \lfloor \sqrt x \rfloor$ and $s^2 + r = x$. This implies that $r \leq 2x$. // // All limbs are in ascending order (least-significant first). // // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {limbs_sqrt_rem(xs: &[Limb]) -> (Vec, Vec) { let xs_len = xs.len(); let mut out_sqrt = vec![0; xs_len.shr_round(1, Ceiling).0]; let mut out_rem = vec![0; xs_len]; let rem_len = limbs_sqrt_rem_to_out(&mut out_sqrt, &mut out_rem, xs); out_rem.truncate(rem_len); (out_sqrt, out_rem) }} impl FloorSqrt for Natural { type Output = Self; /// Returns the floor of the square root of a [`Natural`], taking it by value. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrt; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(99u8).floor_sqrt(), 9); /// assert_eq!(Natural::from(100u8).floor_sqrt(), 10); /// assert_eq!(Natural::from(101u8).floor_sqrt(), 10); /// assert_eq!(Natural::from(1000000000u32).floor_sqrt(), 31622); /// assert_eq!(Natural::from(10000000000u64).floor_sqrt(), 100000); /// ``` #[inline] fn floor_sqrt(self) -> Self { (&self).floor_sqrt() } } impl FloorSqrt for &Natural { type Output = Natural; /// Returns the floor of the square root of a [`Natural`], taking it by value. /// /// $f(x) = \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrt; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::from(99u8)).floor_sqrt(), 9); /// assert_eq!((&Natural::from(100u8)).floor_sqrt(), 10); /// assert_eq!((&Natural::from(101u8)).floor_sqrt(), 10); /// assert_eq!((&Natural::from(1000000000u32)).floor_sqrt(), 31622); /// assert_eq!((&Natural::from(10000000000u64)).floor_sqrt(), 100000); /// ``` fn floor_sqrt(self) -> Natural { match self { Natural(Small(small)) => Natural::from(small.floor_sqrt()), Natural(Large(limbs)) => Natural::from_owned_limbs_asc(limbs_floor_sqrt(limbs)), } } } impl FloorSqrtAssign for Natural { /// Replaces a [`Natural`] with the floor of its square root. /// /// $x \gets \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorSqrtAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(99u8); /// x.floor_sqrt_assign(); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(100u8); /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(101u8); /// x.floor_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1000000000u32); /// x.floor_sqrt_assign(); /// assert_eq!(x, 31622); /// /// let mut x = Natural::from(10000000000u64); /// x.floor_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` #[inline] fn floor_sqrt_assign(&mut self) { *self = (&*self).floor_sqrt(); } } impl CeilingSqrt for Natural { type Output = Self; /// Returns the ceiling of the square root of a [`Natural`], taking it by value. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrt; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(99u8).ceiling_sqrt(), 10); /// assert_eq!(Natural::from(100u8).ceiling_sqrt(), 10); /// assert_eq!(Natural::from(101u8).ceiling_sqrt(), 11); /// assert_eq!(Natural::from(1000000000u32).ceiling_sqrt(), 31623); /// assert_eq!(Natural::from(10000000000u64).ceiling_sqrt(), 100000); /// ``` #[inline] fn ceiling_sqrt(self) -> Self { (&self).ceiling_sqrt() } } impl CeilingSqrt for &Natural { type Output = Natural; /// Returns the ceiling of the square root of a [`Natural`], taking it by value. /// /// $f(x) = \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrt; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(99u8).ceiling_sqrt(), 10); /// assert_eq!(Natural::from(100u8).ceiling_sqrt(), 10); /// assert_eq!(Natural::from(101u8).ceiling_sqrt(), 11); /// assert_eq!(Natural::from(1000000000u32).ceiling_sqrt(), 31623); /// assert_eq!(Natural::from(10000000000u64).ceiling_sqrt(), 100000); /// ``` fn ceiling_sqrt(self) -> Natural { match self { Natural(Small(small)) => Natural::from(small.ceiling_sqrt()), Natural(Large(limbs)) => Natural::from_owned_limbs_asc(limbs_ceiling_sqrt(limbs)), } } } impl CeilingSqrtAssign for Natural { /// Replaces a [`Natural`] with the ceiling of its square root. /// /// $x \gets \lceil\sqrt{x}\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingSqrtAssign; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(99u8); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(100u8); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(101u8); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 11); /// /// let mut x = Natural::from(1000000000u32); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 31623); /// /// let mut x = Natural::from(10000000000u64); /// x.ceiling_sqrt_assign(); /// assert_eq!(x, 100000); /// ``` #[inline] fn ceiling_sqrt_assign(&mut self) { *self = (&*self).ceiling_sqrt(); } } impl CheckedSqrt for Natural { type Output = Self; /// Returns the the square root of a [`Natural`], or `None` if it is not a perfect square. The /// [`Natural`] is taken by value. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(99u8).checked_sqrt().to_debug_string(), "None"); /// assert_eq!( /// Natural::from(100u8).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Natural::from(101u8).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(1000000000u32) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Natural::from(10000000000u64) /// .checked_sqrt() /// .to_debug_string(), /// "Some(100000)" /// ); /// ``` #[inline] fn checked_sqrt(self) -> Option { (&self).checked_sqrt() } } impl CheckedSqrt for &Natural { type Output = Natural; /// Returns the the square root of a [`Natural`], or `None` if it is not a perfect square. The /// [`Natural`] is taken by value. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\sqrt{x}) & \text{if} \\quad \sqrt{x} \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(99u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(100u8)).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Natural::from(101u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(1000000000u32)) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Natural::from(10000000000u64)) /// .checked_sqrt() /// .to_debug_string(), /// "Some(100000)" /// ); /// ``` fn checked_sqrt(self) -> Option { match self { Natural(Small(small)) => small.checked_sqrt().map(Natural::from), Natural(Large(limbs)) => limbs_checked_sqrt(limbs).map(Natural::from_owned_limbs_asc), } } } impl SqrtRem for Natural { type SqrtOutput = Self; type RemOutput = Self; /// Returns the floor of the square root of a [`Natural`] and the remainder (the difference /// between the [`Natural`] and the square of the floor). The [`Natural`] is taken by value. /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SqrtRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(99u8).sqrt_rem().to_debug_string(), "(9, 18)"); /// assert_eq!(Natural::from(100u8).sqrt_rem().to_debug_string(), "(10, 0)"); /// assert_eq!(Natural::from(101u8).sqrt_rem().to_debug_string(), "(10, 1)"); /// assert_eq!( /// Natural::from(1000000000u32).sqrt_rem().to_debug_string(), /// "(31622, 49116)" /// ); /// assert_eq!( /// Natural::from(10000000000u64).sqrt_rem().to_debug_string(), /// "(100000, 0)" /// ); /// ``` #[inline] fn sqrt_rem(self) -> (Self, Self) { (&self).sqrt_rem() } } impl SqrtRem for &Natural { type SqrtOutput = Natural; type RemOutput = Natural; /// Returns the floor of the square root of a [`Natural`] and the remainder (the difference /// between the [`Natural`] and the square of the floor). The [`Natural`] is taken by reference. /// /// $f(x) = (\lfloor\sqrt{x}\rfloor, x - \lfloor\sqrt{x}\rfloor^2)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SqrtRem; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(99u8)).sqrt_rem().to_debug_string(), /// "(9, 18)" /// ); /// assert_eq!( /// (&Natural::from(100u8)).sqrt_rem().to_debug_string(), /// "(10, 0)" /// ); /// assert_eq!( /// (&Natural::from(101u8)).sqrt_rem().to_debug_string(), /// "(10, 1)" /// ); /// assert_eq!( /// (&Natural::from(1000000000u32)).sqrt_rem().to_debug_string(), /// "(31622, 49116)" /// ); /// assert_eq!( /// (&Natural::from(10000000000u64)) /// .sqrt_rem() /// .to_debug_string(), /// "(100000, 0)" /// ); /// ``` fn sqrt_rem(self) -> (Natural, Natural) { match self { Natural(Small(small)) => { let (sqrt, rem) = small.sqrt_rem(); (Natural::from(sqrt), Natural::from(rem)) } Natural(Large(limbs)) => { let (sqrt_limbs, rem_limbs) = limbs_sqrt_rem(limbs); ( Natural::from_owned_limbs_asc(sqrt_limbs), Natural::from_owned_limbs_asc(rem_limbs), ) } } } } impl SqrtAssignRem for Natural { type RemOutput = Self; /// Replaces a [`Natural`] with the floor of its square root and returns the remainder (the /// difference between the original [`Natural`] and the square of the floor). /// /// $f(x) = x - \lfloor\sqrt{x}\rfloor^2$, /// /// $x \gets \lfloor\sqrt{x}\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SqrtAssignRem; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(99u8); /// assert_eq!(x.sqrt_assign_rem(), 18); /// assert_eq!(x, 9); /// /// let mut x = Natural::from(100u8); /// assert_eq!(x.sqrt_assign_rem(), 0); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(101u8); /// assert_eq!(x.sqrt_assign_rem(), 1); /// assert_eq!(x, 10); /// /// let mut x = Natural::from(1000000000u32); /// assert_eq!(x.sqrt_assign_rem(), 49116); /// assert_eq!(x, 31622); /// /// let mut x = Natural::from(10000000000u64); /// assert_eq!(x.sqrt_assign_rem(), 0); /// assert_eq!(x, 100000); /// ``` #[inline] fn sqrt_assign_rem(&mut self) -> Self { let rem; (*self, rem) = (&*self).sqrt_rem(); rem } } ================================================ FILE: malachite-nz/src/natural/arithmetic/square.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `MAYBE_sqr_toom2`, `TOOM2_SQR_REC`, and `mpn_toom2_sqr` contributed to the GNU project by // Torbjörn Granlund. // // `SQR_TOOM6_MAX`, `MAYBE_sqr_basecase`, `MAYBE_sqr_toom2`, `MAYBE_sqr_above_toom2`, // `MAYBE_sqr_toom3`, `MAYBE_sqr_above_toom3`, `MAYBE_sqr_above_toom4`, `TOOM6_SQR_REC`, // `mpn_toom6_sqr`, `SQR_TOOM8_MAX`, `MAYBE_sqr_basecase`, `MAYBE_sqr_above_basecase`, // `MAYBE_sqr_toom2`, `MAYBE_sqr_above_toom2`, `MAYBE_sqr_toom3`, `MAYBE_sqr_above_toom3`, // `MAYBE_sqr_toom4`, `MAYBE_sqr_above_toom4`, `MAYBE_sqr_above_toom6`, `TOOM8_SQR_REC`, and // `mpn_toom8_sqr` contributed to the GNU project by Marco Bodrato. // // `MAYBE_sqr_toom3`, `MAYBE_sqr_basecase`, `TOOM3_SQR_REC`, and `mpn_toom3_sqr` contributed to // the GNU project by Torbjörn Granlund, with additional improvements by Marco Bodrato. // // `MAYBE_sqr_toom2`, `MAYBE_sqr_toom4`, `TOOM4_SQR_REC`, and `mpn_toom4_sqr` contributed to // the GNU project by Torbjörn Granlund and Marco Bodrato. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::{ limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_to_out, limbs_slice_add_greater_in_place_left, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mul::fft::mpn_square_default_mpn_ctx; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::limbs_mul_greater_to_out_basecase; use crate::natural::arithmetic::mul::poly_eval::{ limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1, limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2, limbs_mul_toom_evaluate_poly_in_1_and_neg_1, limbs_mul_toom_evaluate_poly_in_2_and_neg_2, limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow, limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg, }; use crate::natural::arithmetic::mul::poly_interpolate::{ limbs_mul_toom_interpolate_5_points, limbs_mul_toom_interpolate_7_points, limbs_mul_toom_interpolate_12_points, limbs_mul_toom_interpolate_16_points, }; use crate::natural::arithmetic::mul::toom::{ BIT_CORRECTION, TUNE_PROGRAM_BUILD, WANT_FAT_BINARY, limbs_toom_couple_handling, }; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::natural::arithmetic::sub::{ limbs_sub_limb_in_place, limbs_sub_same_length_in_place_left, limbs_sub_same_length_to_out, }; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::{ DoubleLimb, Limb, SQR_BASECASE_THRESHOLD, SQR_TOOM2_THRESHOLD, SQR_TOOM3_THRESHOLD, SQR_TOOM4_THRESHOLD, SQR_TOOM6_THRESHOLD, SQR_TOOM8_THRESHOLD, }; use alloc::vec::Vec; use core::cmp::{Ordering::*, max}; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, DivRound, ShrRound, Square, SquareAssign, WrappingAddAssign, WrappingSubAssign, XMulYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{SplitInHalf, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; const SQR_FFT_MODF_THRESHOLD: usize = SQR_TOOM3_THRESHOLD * 3; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `MPN_SQR_DIAGONAL` from `mpn/generic/sqr_basecase.c`, GMP 6.2.1. #[inline] pub(crate) fn limbs_square_diagonal(out: &mut [Limb], xs: &[Limb]) { for (i, &x) in xs.iter().enumerate() { let i_2 = i << 1; (out[i_2 | 1], out[i_2]) = DoubleLimb::from(x).square().split_in_half(); } } // scratch must have length 2 * xs.len() - 2 and out must have length 2 * xs.len(). // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `MPN_SQR_DIAG_ADDLSH1` from `mpn/generic/sqr_basecase.c`, GMP 6.2.1. pub_test! {limbs_square_diagonal_add_shl_1(out: &mut [Limb], scratch: &mut [Limb], xs: &[Limb]) { limbs_square_diagonal(out, xs); let (out_last, out_init) = out.split_last_mut().unwrap(); *out_last += limbs_slice_shl_in_place(scratch, 1); if limbs_slice_add_same_length_in_place_left(&mut out_init[1..], scratch) { *out_last += 1; } }} // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`s, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural`s to an output slice. The // output must be at least twice as long as `xs.len()`, `xs.len()` must be less than // `SQR_TOOM2_THRESHOLD`, and `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is less than twice the length of `xs`, `xs.len()` > SQR_TOOM2_THRESHOLD, or if // `xs` is empty. // // This is equivalent to `mpn_sqr_basecase` from `mpn/generic/sqr_basecase.c`, GMP 6.2.1. pub_crate_test! {limbs_square_to_out_basecase(out: &mut [Limb], xs: &[Limb]) { let n = xs.len(); let (xs_head, xs_tail) = xs.split_first().unwrap(); (out[1], out[0]) = DoubleLimb::from(*xs_head).square().split_in_half(); if n > 1 { assert!(n <= SQR_TOOM2_THRESHOLD); let scratch = &mut [0; SQR_TOOM2_THRESHOLD << 1]; let two_n = n << 1; let scratch = &mut scratch[..two_n - 2]; let (scratch_last, scratch_init) = scratch[..n].split_last_mut().unwrap(); *scratch_last = limbs_mul_limb_to_out::(scratch_init, xs_tail, *xs_head); for i in 1..n - 1 { let (scratch_last, scratch_init) = scratch[i..][i..n].split_last_mut().unwrap(); let (xs_head, xs_tail) = xs[i..].split_first().unwrap(); *scratch_last = limbs_slice_add_mul_limb_same_length_in_place_left(scratch_init, xs_tail, *xs_head); } limbs_square_diagonal_add_shl_1(&mut out[..two_n], scratch, xs); } }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom2_sqr_itch` from `gmp-impl.h`, GMP 6.2.1. pub_const_test! {limbs_square_to_out_toom_2_scratch_len(xs_len: usize) -> usize { (xs_len + Limb::WIDTH as usize) << 1 }} // TODO tune /// This is equivalent to `MAYBE_sqr_toom2` from `mpn/generic/toom2_sqr.c`, GMP 6.2.1. const TOOM2_MAYBE_SQR_TOOM2: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || SQR_TOOM3_THRESHOLD >= 2 * SQR_TOOM2_THRESHOLD; // # Worst-case complexity // $T(n) = O(n^{\log_2 3}) \approx O(n^{1.585})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM2_SQR_REC` from `mpn/generic/toom2_sqr.c`, GMP 6.2.1. fn limbs_square_to_out_toom_2_recursive(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { if !TOOM2_MAYBE_SQR_TOOM2 || xs.len() < SQR_TOOM2_THRESHOLD { limbs_square_to_out_basecase(out, xs); } else { limbs_square_to_out_toom_2(out, xs, scratch); } } // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural` to an output slice. A scratch // slice is provided for the algorithm to use. An upper bound for the number of scratch limbs needed // is provided by `limbs_square_to_out_toom_2_scratch_len`. The following restrictions on the input // slices must be met: // - `out`.len() >= 2 * `xs`.len() // - `xs`.len() > 1 // // The smallest allowable `xs` length is 2. // // Evaluate in: -1, 0, infinity. // ``` // <-s--><--n--> // ____ ______ // |xs1_|__xs0_| // // v_0 = xs_0 ^ 2 # X(0) ^ 2 // v_neg_1 = (xs_0 - xs_1) ^ 2 # X(-1) ^ 2 // v_inf = xs_1 ^ 2 # X(inf) ^ 2 // ``` // // # Worst-case complexity // $T(n) = O(n^{\log_2 3}) \approx O(n^{1.585})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom2_sqr` from `mpn/generic/toom2_sqr.c`, GMP 6.2.1. pub_test! {limbs_square_to_out_toom_2(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); assert!(xs_len > 1); let out = &mut out[..xs_len << 1]; let s = xs_len >> 1; let n = xs_len - s; let (xs_0, xs_1) = xs.split_at(n); if s == n { if limbs_cmp_same_length(xs_0, xs_1) == Less { limbs_sub_same_length_to_out(out, xs_1, xs_0); } else { limbs_sub_same_length_to_out(out, xs_0, xs_1); } } else { // n - s == 1 let (xs_0_last, xs_0_init) = xs_0.split_last().unwrap(); let (out_last, out_init) = out[..n].split_last_mut().unwrap(); if *xs_0_last == 0 && limbs_cmp_same_length(xs_0_init, xs_1) == Less { limbs_sub_same_length_to_out(out_init, xs_1, xs_0_init); *out_last = 0; } else { *out_last = *xs_0_last; if limbs_sub_same_length_to_out(out_init, xs_0_init, xs_1) { out_last.wrapping_sub_assign(1); } } } let (v_0, v_inf) = out.split_at_mut(n << 1); let (v_neg_1, scratch_out) = scratch.split_at_mut(n << 1); limbs_square_to_out_toom_2_recursive(v_neg_1, &v_0[..n], scratch_out); limbs_square_to_out_toom_2_recursive(v_inf, xs_1, scratch_out); limbs_square_to_out_toom_2_recursive(v_0, xs_0, scratch_out); let (v_0_lo, v_0_hi) = v_0.split_at_mut(n); let (v_inf_lo, v_inf_hi) = v_inf.split_at_mut(n); let mut carry = Limb::from(limbs_slice_add_same_length_in_place_left(v_inf_lo, v_0_hi)); let mut carry2 = carry; if limbs_add_same_length_to_out(v_0_hi, v_inf_lo, v_0_lo) { carry2 += 1; } if limbs_slice_add_greater_in_place_left(v_inf_lo, &v_inf_hi[..s + s - n]) { carry += 1; } if limbs_sub_same_length_in_place_left(&mut out[n..3 * n], v_neg_1) { carry.wrapping_sub_assign(1); } assert!(carry.wrapping_add(1) <= 3); assert!(carry2 <= 2); let carry3 = limbs_slice_add_limb_in_place(&mut out[n << 1..], carry2); let out_hi = &mut out[3 * n..]; if carry <= 2 { assert!(!limbs_slice_add_limb_in_place(out_hi, carry)); } else if limbs_sub_limb_in_place(out_hi, 1) { assert!(carry3); } }} // This function can be used to determine whether the size of the input slice to // `limbs_square_to_out_toom_3` is valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_square_to_out_toom_3_input_size_valid(xs_len: usize) -> bool { xs_len == 3 || xs_len > 4 }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom3_sqr_itch` from `gmp-impl.h`, GMP 6.2.1. pub_const_test! {limbs_square_to_out_toom_3_scratch_len(xs_len: usize) -> usize { 3 * xs_len + Limb::WIDTH as usize }} // TODO tune const SMALLER_RECURSION_TOOM_3: bool = true; // TODO tune // This is equivalent to `MAYBE_sqr_toom3` from `mpn/generic/toom3_sqr.c`, GMP 6.2.1. #[cfg(feature = "test_build")] pub const TOOM3_MAYBE_SQR_TOOM3: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || SQR_TOOM4_THRESHOLD >= 3 * SQR_TOOM3_THRESHOLD; #[cfg(not(feature = "test_build"))] const TOOM3_MAYBE_SQR_TOOM3: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || SQR_TOOM4_THRESHOLD >= 3 * SQR_TOOM3_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_basecase` from `mpn/generic/toom3_sqr.c`, GMP 6.2.1. #[cfg(feature = "test_build")] pub const TOOM3_MAYBE_SQR_BASECASE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || SQR_TOOM3_THRESHOLD < 3 * SQR_TOOM2_THRESHOLD; #[cfg(not(feature = "test_build"))] const TOOM3_MAYBE_SQR_BASECASE: bool = TUNE_PROGRAM_BUILD || WANT_FAT_BINARY || SQR_TOOM3_THRESHOLD < 3 * SQR_TOOM2_THRESHOLD; // # Worst-case complexity // $T(n) = O(n^{\log_3 5}) \approx O(n^{1.465})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM3_SQR_REC` from `mpn/generic/toom3_sqr.c`, GMP 6.2.1. fn limbs_square_to_out_toom_3_recursive(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let n = xs.len(); if TOOM3_MAYBE_SQR_BASECASE && n < SQR_TOOM2_THRESHOLD { limbs_square_to_out_basecase(out, xs); } else if !TOOM3_MAYBE_SQR_TOOM3 || n < SQR_TOOM3_THRESHOLD { limbs_square_to_out_toom_2(out, xs, scratch); } else { limbs_square_to_out_toom_3(out, xs, scratch); } } // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural` to an output slice. A scratch // slice is provided for the algorithm to use. An upper bound for the number of scratch limbs needed // is provided by `limbs_square_to_out_toom_3_scratch_len`. The following restrictions on the input // slices must be met: // - `out`.len() >= 2 * `xs`.len() // - `xs`.len() == 3 or `xs`.len() > 4 // // The smallest allowable `xs` length is 3. // // Evaluate in: -1, 0, +1, +2, +inf // ``` // <-s--><--n--><--n--> // ____ ______ ______ // |xs_2|_xs_1_|_xs_0_| // // v_0 = xs_0 ^ 2 # X(0)^2 // v_1 = (xs_0 + xs_1 + xs_2) ^ 2 # X(1)^2 xh <= 2 // v_neg_1 = (xs_0 - xs_1 + xs_2) ^ 2 # X(-1)^2 |xh| <= 1 // v_2 = (xs_0 + 2 * xs_1 + 4 * xs_2) ^ 2 # X(2)^2 xh <= 6 // v_inf = xs_2 ^ 2 # X(inf)^2 // ``` // // # Worst-case complexity // $T(n) = O(n^{\log_3 5}) \approx O(n^{1.465})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom3_sqr` from `mpn/generic/toom3_sqr.c`, GMP 6.2.1. pub_test! {limbs_square_to_out_toom_3(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); let n = xs_len.div_round(3, Ceiling).0; let m = n + 1; let k = m + n; let s = xs_len - (n << 1); assert_ne!(s, 0); assert!(s <= n); split_into_chunks!(xs, n, [xs_0, xs_1], xs_2); split_into_chunks_mut!(scratch, m << 1, [scratch_lo, asm1], as1); let (asm1_last, asm1_init) = asm1[..m].split_last_mut().unwrap(); let (as1_last, as1_init) = as1[..m].split_last_mut().unwrap(); let scratch_lo = &mut scratch_lo[..n]; let mut carry = Limb::from(limbs_add_to_out(scratch_lo, xs_0, xs_2)); *as1_last = carry; if limbs_add_same_length_to_out(as1_init, scratch_lo, xs_1) { *as1_last += 1; } if carry == 0 && limbs_cmp_same_length(scratch_lo, xs_1) == Less { limbs_sub_same_length_to_out(asm1_init, xs_1, scratch_lo); } else if limbs_sub_same_length_to_out(asm1_init, scratch_lo, xs_1) { carry.wrapping_sub_assign(1); } *asm1_last = carry; let as2 = &mut out[m..m << 1]; let (as2_last, as2_init) = as2.split_last_mut().unwrap(); let (as1_lo, as1_hi) = as1_init.split_at_mut(s); let mut carry = Limb::from(limbs_add_same_length_to_out(as2_init, xs_2, as1_lo)); if s != n { carry = Limb::from(limbs_add_limb_to_out(&mut as2_init[s..], as1_hi, carry)); } carry.wrapping_add_assign(*as1_last); carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(as2_init, 1)); if limbs_sub_same_length_in_place_left(as2_init, xs_0) { carry.wrapping_sub_assign(1); } *as2_last = carry; assert!(*as1_last <= 2); assert!(*asm1_last <= 1); let (scratch_lo, scratch_out) = scratch.split_at_mut(5 * m); if SMALLER_RECURSION_TOOM_3 { let (v_neg_1, asm1) = scratch_lo.split_at_mut(k); let (v_neg_1_last, v_neg_1_init) = v_neg_1.split_last_mut().unwrap(); let (asm1_last, asm1_init) = asm1[1..n + 2].split_last().unwrap(); limbs_square_to_out_toom_3_recursive(v_neg_1_init, asm1_init, scratch_out); *v_neg_1_last = if *asm1_last != 0 { asm1_last.wrapping_add(limbs_slice_add_mul_limb_same_length_in_place_left( &mut v_neg_1_init[n..], asm1_init, 2, )) } else { 0 }; } else { fail_on_untested_path("limbs_square_to_out_toom_3, !SMALLER_RECURSION"); let (v_neg_1, asm1) = scratch_lo.split_at_mut(m << 1); limbs_square_to_out_toom_3_recursive(v_neg_1, &asm1[..m], scratch_out); } limbs_square_to_out_toom_3_recursive(&mut scratch_lo[k..], as2, scratch_out); let v_inf = &mut out[n << 2..]; limbs_square_to_out_toom_3_recursive(v_inf, xs_2, scratch_out); let v_inf_0 = v_inf[0]; let (as1, scratch_out) = &mut scratch[m << 2..].split_at_mut(m); let out_hi = &mut out[n << 1..]; if SMALLER_RECURSION_TOOM_3 { let (v_1_last, v_1_init) = out_hi[..k].split_last_mut().unwrap(); let (as1_last, as1_init) = as1.split_last_mut().unwrap(); limbs_square_to_out_toom_3_recursive(v_1_init, as1_init, scratch_out); let v_1_init = &mut v_1_init[n..]; *v_1_last = if *as1_last == 1 { limbs_slice_add_mul_limb_same_length_in_place_left(v_1_init, as1_init, 2) .wrapping_add(1) } else if *as1_last != 0 { as1_last.arithmetic_checked_shl(1u64).unwrap().wrapping_add( limbs_slice_add_mul_limb_same_length_in_place_left(v_1_init, as1_init, 4), ) } else { 0 }; } else { let carry = out_hi[k]; limbs_square_to_out_toom_3_recursive(out_hi, as1, scratch_out); out_hi[k] = carry; } let (v_neg_1, remainder) = scratch.split_at_mut(k); let (v_2, scratch_out) = remainder.split_at_mut(3 * n + 4); limbs_square_to_out_toom_3_recursive(out, xs_0, scratch_out); limbs_mul_toom_interpolate_5_points(out, v_2, v_neg_1, n, s << 1, false, v_inf_0); }} // This function can be used to determine whether the size of the input slice to // `limbs_square_to_out_toom_4` is valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_square_to_out_toom_4_input_size_valid(xs_len: usize) -> bool { xs_len == 4 || xs_len == 7 || xs_len == 8 || xs_len > 9 }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom4_sqr_itch` from `gmp-impl.h`, GMP 6.2.1. pub_const_test! {limbs_square_to_out_toom_4_scratch_len(xs_len: usize) -> usize { 3 * xs_len + Limb::WIDTH as usize }} // TODO tune // This is equivalent to `MAYBE_sqr_toom2` from `mpn/generic/toom4_sqr.c`, GMP 6.2.1. const TOOM4_MAYBE_SQR_TOOM2: bool = TUNE_PROGRAM_BUILD || SQR_TOOM4_THRESHOLD < 4 * SQR_TOOM3_THRESHOLD; // TODO tune // This is equivalent to `MAYBE_sqr_toom4` from `mpn/generic/toom4_sqr.c`, GMP 6.2.1. const TOOM4_MAYBE_SQR_TOOM4: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_THRESHOLD >= 4 * SQR_TOOM4_THRESHOLD; // # Worst-case complexity // $T(n) = O(n^{\log_4 7}) \approx O(n^{1.404})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM4_SQR_REC` from `mpn/generic/toom4_sqr.c`, GMP 6.2.1. fn limbs_square_to_out_toom_4_recursive(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let n = xs.len(); if n < SQR_TOOM2_THRESHOLD { // We don't check TOOM4_MAYBE_SQR_BASECASE because we never want the Toom functions to // handle very small inputs. limbs_square_to_out_basecase(out, xs); } else if TOOM4_MAYBE_SQR_TOOM2 && n < SQR_TOOM3_THRESHOLD { limbs_square_to_out_toom_2(out, xs, scratch); } else if !TOOM4_MAYBE_SQR_TOOM4 || n < SQR_TOOM4_THRESHOLD { limbs_square_to_out_toom_3(out, xs, scratch); } else { limbs_square_to_out_toom_4(out, xs, scratch); } } // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural` to an output slice. A scratch // slice is provided for the algorithm to use. An upper bound for the number of scratch limbs needed // is provided by `limbs_square_to_out_toom_4_scratch_len`. The following restrictions on the input // slices must be met: // - `out`.len() >= 2 * `xs`.len() // - `xs`.len() is 4, 7, or 8, or `xs`.len() > 9. // // The smallest allowable `xs` length is 4. // // Evaluate in: -1, -1/2, 0, +1/2, +1, +2, +inf // ``` // <-s--><--n--><--n--><--n--> // ____ ______ ______ ______ // |xs_3|_xs_2_|_xs_1_|_xs_0_| // // v_0 = xs_0 ^ 2 # X(0) ^ 2 // v_1 = (xs_0 + xs_1 + xs_2 + xs_3) ^ 2 # X(1) ^ 2 xh <= 3 // v_neg_1 = (xs_0 - xs_1 + xs_2 - xs_3) ^ 2 # X(-1) ^ 2 |xh| <= 1 // v_2 = (xs_0 + 2 * xs_1 + 4 * xs_2 + 8 * xs_3) ^ 2 # X(2) ^ 2 xh <= 14 // vh = (8 * xs_0 + 4 * xs_1 + 2 * xs_2 + xs_3) ^ 2 # X(1/2) ^ 2 xh <= 14 // vmh = (8 * xs_0 - 4 * xs_1 + 2 * xs_2 - xs_3) ^ 2 # X(-1/2) ^ 2 -4 <= xh <= 9 // v_inf = xs_3 ^ 2 # X(inf) ^ 2 // ``` // // # Worst-case complexity // $T(n) = O(n^{\log_4 7}) \approx O(n^{1.404})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom4_sqr` from `mpn/generic/toom4_sqr.c`, GMP 6.2.1. pub_test! {limbs_square_to_out_toom_4(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); let n = (xs_len + 3) >> 2; let s = xs_len - 3 * n; assert_ne!(s, 0); assert!(s <= n); let m = n + 1; let k = m + n; split_into_chunks!(xs, n, [xs_0, xs_1, xs_2], xs_3); // Total scratch need: 8 * n + 5 + scratch for recursive calls. This gives roughly 32 * n / 3 + // log term. Compute apx = xs_0 + 2 * xs_1 + 4 * xs_2 + 8 * xs_3 and amx = xs_0 - 2 * xs_1 + 4 // * xs_2 - 8 * xs_3. let (apx, remainder) = out.split_at_mut(n << 1); let apx = &mut apx[..m]; let (v1, amx) = remainder.split_at_mut(m << 1); let amx = &mut amx[..m]; let (scratch_lo, scratch_hi) = scratch.split_at_mut((k << 2) + 1); limbs_mul_toom_evaluate_deg_3_poly_in_2_and_neg_2(apx, amx, xs, n, &mut scratch_hi[..m]); limbs_square_to_out_toom_4_recursive(scratch_lo, apx, scratch_hi); let scratch_lo = &mut scratch_lo[k..]; limbs_square_to_out_toom_4_recursive(scratch_lo, amx, scratch_hi); // Compute apx = 8 xs_0 + 4 xs_1 + 2 xs_2 + xs_3 = (((2 xs_0 + xs_1) * 2 + xs_2) * 2 + xs_3 let (apx_last, apx_init) = apx.split_last_mut().unwrap(); let mut carry = limbs_shl_to_out(apx_init, xs_0, 1); if limbs_slice_add_same_length_in_place_left(apx_init, xs_1) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(apx_init, 1)); if limbs_slice_add_same_length_in_place_left(apx_init, xs_2) { carry.wrapping_add_assign(1); } carry = carry.arithmetic_checked_shl(1).unwrap(); carry.wrapping_add_assign(limbs_slice_shl_in_place(apx_init, 1)); if limbs_slice_add_greater_in_place_left(apx_init, xs_3) { carry.wrapping_add_assign(1); } *apx_last = carry; assert!(*apx_last < 15); let scratch_lo = &mut scratch_lo[k..]; limbs_square_to_out_toom_4_recursive(scratch_lo, apx, scratch_hi); // Compute apx = xs_0 + xs_1 + xs_2 + xs_3 and amx = xs_0 - xs_1 + xs_2 - xs_3. limbs_mul_toom_evaluate_deg_3_poly_in_1_and_neg_1(apx, amx, xs, n, &mut scratch_hi[..m]); limbs_square_to_out_toom_4_recursive(v1, apx, scratch_hi); let scratch_lo = &mut scratch_lo[k..]; limbs_square_to_out_toom_4_recursive(scratch_lo, amx, scratch_hi); let (v0, vinf) = out.split_at_mut(n << 1); let vinf = &mut vinf[n << 2..]; limbs_square_to_out_toom_4_recursive(v0, xs_0, scratch_hi); limbs_square_to_out_toom_4_recursive(vinf, xs_3, scratch_hi); split_into_chunks_mut!(scratch, k, [v2, vm2, vh, vm1], scratch_hi); limbs_mul_toom_interpolate_7_points(out, n, s << 1, false, vm2, false, vm1, v2, vh, scratch_hi); }} // This function can be used to determine whether the size of the input slice to // `limbs_square_to_out_toom_6` is valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_square_to_out_toom_6_input_size_valid(xs_len: usize) -> bool { xs_len == 18 || xs_len > 21 && xs_len != 25 && xs_len != 26 && xs_len != 31 }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom6_sqr_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_square_to_out_toom_6_scratch_len(n: usize) -> usize { (n << 1) + max( (SQR_TOOM6_THRESHOLD << 1) + usize::wrapping_from(Limb::WIDTH) * 6, limbs_square_to_out_toom_4_scratch_len(SQR_TOOM6_THRESHOLD), ) - (SQR_TOOM6_THRESHOLD << 1) }} // TODO tune /// This is equivalent to `SQR_TOOM6_MAX` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const SQR_TOOM6_MAX: usize = (SQR_TOOM8_THRESHOLD + 6 * 2 - 1).div_ceil(6); // TODO tune /// This is equivalent to `MAYBE_sqr_basecase` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_BASECASE: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_THRESHOLD < 6 * SQR_TOOM2_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_toom2` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_TOOM2: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_THRESHOLD < 6 * SQR_TOOM3_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom2` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_ABOVE_TOOM2: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_MAX >= SQR_TOOM3_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_toom3` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_TOOM3: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_THRESHOLD < 6 * SQR_TOOM4_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom3` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_ABOVE_TOOM3: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_MAX >= SQR_TOOM4_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom4` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. const TOOM6_MAYBE_SQR_ABOVE_TOOM4: bool = TUNE_PROGRAM_BUILD || SQR_TOOM6_MAX >= SQR_TOOM6_THRESHOLD; // # Worst-case complexity // $T(n) = O(n^{\log_6 11}) \approx O(n^{1.338})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM6_SQR_REC` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. fn limbs_square_to_out_toom_6_recursive(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let n = xs.len(); if TOOM6_MAYBE_SQR_BASECASE && n < SQR_TOOM2_THRESHOLD { limbs_square_to_out_basecase(out, xs); } else if TOOM6_MAYBE_SQR_TOOM2 && (!TOOM6_MAYBE_SQR_ABOVE_TOOM2 || n < SQR_TOOM3_THRESHOLD) { limbs_square_to_out_toom_2(out, xs, scratch); } else if TOOM6_MAYBE_SQR_TOOM3 && (!TOOM6_MAYBE_SQR_ABOVE_TOOM3 || n < SQR_TOOM4_THRESHOLD) { limbs_square_to_out_toom_3(out, xs, scratch); } else if !TOOM6_MAYBE_SQR_ABOVE_TOOM4 || n < SQR_TOOM6_THRESHOLD { limbs_square_to_out_toom_4(out, xs, scratch); } else { limbs_square_to_out_toom_6(out, xs, scratch); } } // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural` to an output slice. A scratch // slice is provided for the algorithm to use. An upper bound for the number of scratch limbs needed // is provided by `limbs_square_to_out_toom_6_scratch_len`. The following restrictions on the input // slices must be met: // - `out`.len() >= 2 * `xs`.len() // - `xs`.len() is 18, or `xs.len()` > 21 but `xs`.len() is not 25, 26, or 31. // // The smallest allowable `xs` length is 18. // // # Worst-case complexity // $T(n) = O(n^{\log_6 11}) \approx O(n^{1.338})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom6_sqr` from `mpn/generic/toom6_sqr.c`, GMP 6.2.1. pub_test! {limbs_square_to_out_toom_6(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); assert!(xs_len >= 18); let n = 1 + (xs_len - 1) / 6; assert!(xs_len > 5 * n); let s = xs_len - 5 * n; assert!(s <= n); assert!(10 * n + 3 <= xs_len << 1); let m = n + 1; let k = m + n; let (out_lo, remainder) = out.split_at_mut(3 * n); let (r4, r2) = remainder.split_at_mut(n << 2); let (v0, v2) = r2.split_at_mut(m << 1); let v0 = &mut v0[..m]; let v2 = &mut v2[..m]; // +/- 1/2 limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v2, v0, 5, xs, n, 1, &mut out_lo[..m], ); split_into_chunks_mut!(scratch, 3 * n + 1, [r5, r3, r1], wse); limbs_square_to_out_toom_6_recursive(out_lo, v0, wse); // X(-1/2) ^ 2 * 2 ^ limbs_square_to_out_toom_6_recursive(r5, v2, wse); // X(1/2) ^ 2 * 2 ^ limbs_toom_couple_handling(r5, &mut out_lo[..k], false, n, 1, 0); // +/- 1 limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, 5, xs, n, &mut out_lo[..m]); limbs_square_to_out_toom_6_recursive(out_lo, v0, wse); // X(-1) ^ 2 limbs_square_to_out_toom_6_recursive(r3, v2, wse); // X(1) ^ 2 limbs_toom_couple_handling(r3, &mut out_lo[..k], false, n, 0, 0); // +/- 4 limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, 5, xs, n, 2, &mut out_lo[..m]); limbs_square_to_out_toom_6_recursive(out_lo, v0, wse); // X(-4) ^ 2 limbs_square_to_out_toom_6_recursive(r1, v2, wse); // X(4) ^ 2 limbs_toom_couple_handling(r1, &mut out_lo[..k], false, n, 2, 4); // +/- 1/4 limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v2, v0, 5, xs, n, 2, &mut out_lo[..m], ); limbs_square_to_out_toom_6_recursive(out_lo, v0, wse); // X(-1/4) ^ 2 * 4 ^ limbs_square_to_out_toom_6_recursive(r4, v2, wse); // X(1/4) ^ 2 * 4 ^ limbs_toom_couple_handling(r4, &mut out_lo[..k], false, n, 2, 0); // +/- 2 limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, 5, xs, n, &mut out_lo[..m]); limbs_square_to_out_toom_6_recursive(out_lo, v0, wse); // X(-2) ^ 2 let (v0, v2) = r2.split_at_mut(m << 1); limbs_square_to_out_toom_6_recursive(v0, &v2[..m], wse); // X(2) ^ 2 limbs_toom_couple_handling(r2, &mut out_lo[..k], false, n, 1, 2); limbs_square_to_out_toom_6_recursive(out_lo, &xs[..n], wse); // X(0) ^ 2 limbs_mul_toom_interpolate_12_points(out, r1, r3, r5, n, s << 1, false, wse); }} // TODO tune pub(crate) const SQR_FFT_THRESHOLD: usize = SQR_FFT_MODF_THRESHOLD * 10; // This function can be used to determine whether the size of the input slice to // `limbs_square_to_out_toom_8` is valid. // // # Worst-case complexity // Constant time and additional memory. pub_const_test! {limbs_square_to_out_toom_8_input_size_valid(xs_len: usize) -> bool { xs_len == 40 || xs_len > 43 && xs_len != 49 && xs_len != 50 && xs_len != 57 }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_toom8_sqr_itch` from `gmp-impl.h`, GMP 6.2.1. pub_crate_test! {limbs_square_to_out_toom_8_scratch_len(n: usize) -> usize { ((n * 15) >> 3) + max( ((SQR_TOOM8_THRESHOLD * 15) >> 3) + usize::wrapping_from(Limb::WIDTH) * 6, limbs_square_to_out_toom_6_scratch_len(SQR_TOOM8_THRESHOLD), ) - ((SQR_TOOM8_THRESHOLD * 15) >> 3) }} // TODO tune /// This is equivalent to `SQR_TOOM8_MAX` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const SQR_TOOM8_MAX: usize = if SQR_FFT_THRESHOLD <= usize::MAX - (8 * 2 - 1 + 7) { (SQR_FFT_THRESHOLD + 8 * 2 - 1).div_ceil(8) } else { usize::MAX }; // TODO tune /// This is equivalent to `MAYBE_sqr_basecase` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_BASECASE: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_THRESHOLD < 8 * SQR_TOOM2_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_basecase` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_ABOVE_BASECASE: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_MAX >= SQR_TOOM2_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_toom2` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_TOOM2: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_THRESHOLD < 8 * SQR_TOOM3_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom2` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_ABOVE_TOOM2: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_MAX >= SQR_TOOM3_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_toom3` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_TOOM3: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_THRESHOLD < 8 * SQR_TOOM4_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom3` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_ABOVE_TOOM3: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_MAX >= SQR_TOOM4_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_toom4` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_TOOM4: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_THRESHOLD < 8 * SQR_TOOM6_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom4` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_ABOVE_TOOM4: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_MAX >= SQR_TOOM6_THRESHOLD; // TODO tune /// This is equivalent to `MAYBE_sqr_above_toom6` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. const TOOM8_MAYBE_SQR_ABOVE_TOOM6: bool = TUNE_PROGRAM_BUILD || SQR_TOOM8_MAX >= SQR_TOOM8_THRESHOLD; // # Worst-case complexity // $T(n) = O(n^{\log_6 11}) \approx O(n^{1.302})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `TOOM8_SQR_REC` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1, when `f` is // `false`. fn limbs_square_to_out_toom_8_recursive(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let n = xs.len(); if TOOM8_MAYBE_SQR_BASECASE && (!TOOM8_MAYBE_SQR_ABOVE_BASECASE || n < SQR_TOOM2_THRESHOLD) { limbs_square_to_out_basecase(out, xs); } else if TOOM8_MAYBE_SQR_TOOM2 && (!TOOM8_MAYBE_SQR_ABOVE_TOOM2 || n < SQR_TOOM3_THRESHOLD) { limbs_square_to_out_toom_2(out, xs, scratch); } else if TOOM8_MAYBE_SQR_TOOM3 && (!TOOM8_MAYBE_SQR_ABOVE_TOOM3 || n < SQR_TOOM4_THRESHOLD) { limbs_square_to_out_toom_3(out, xs, scratch); } else if TOOM8_MAYBE_SQR_TOOM4 && (!TOOM8_MAYBE_SQR_ABOVE_TOOM4 || n < SQR_TOOM6_THRESHOLD) { limbs_square_to_out_toom_4(out, xs, scratch); } else if !TOOM8_MAYBE_SQR_ABOVE_TOOM6 || n < SQR_TOOM8_THRESHOLD { limbs_square_to_out_toom_6(out, xs, scratch); } else { limbs_square_to_out_toom_8(out, xs, scratch); } } // Interpreting a slices of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the `2 // * xs.len()` least-significant limbs of the square of the `Natural` to an output slice. A scratch // slice is provided for the algorithm to use. An upper bound for the number of scratch limbs needed // is provided by `limbs_square_to_out_toom_8_scratch_len`. The following restrictions on the input // slices must be met: // - `out`.len() >= 2 * `xs`.len() // - `xs`.len() is 40, or `xs.len()` > 43 but `xs`.len() is not 49, 50, or 57. // // The smallest allowable `xs` length is 40. // // # Worst-case complexity // $T(n) = O(n^{\log_6 11}) \approx O(n^{1.302})$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // May panic if the input slice conditions are not met. // // This is equivalent to `mpn_toom8_sqr` from `mpn/generic/toom8_sqr.c`, GMP 6.2.1. pub_test! {limbs_square_to_out_toom_8(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let xs_len = xs.len(); assert!(xs_len >= 40); let n: usize = xs_len.shr_round(3, Ceiling).0; let m = n + 1; let k = m + n; let p = k + n; assert!(xs_len > 7 * n); let s = xs_len - 7 * n; assert!(s <= n); assert!(s << 1 > 3); let (pp_lo, remainder) = out.split_at_mut(3 * n); split_into_chunks_mut!(remainder, n << 2, [r6, r4], pp_hi); split_into_chunks_mut!(pp_hi, m, [v0, _unused, v2], _unused); // +/- 1/8 limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v2, v0, 7, xs, n, 3, &mut pp_lo[..m], ); let (r7_r5, remainder) = scratch.split_at_mut(p << 1); let (r3, r1_wse) = remainder.split_at_mut(p); let (r1, wse) = r1_wse.split_at_mut(p); // A(-1/8) * B(-1/8) * 8 ^, A(1/8) * B(1/8) * 8 ^ limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); limbs_square_to_out_toom_8_recursive(r7_r5, v2, wse); let limit = if BIT_CORRECTION { m << 1 } else { k }; limbs_toom_couple_handling(r7_r5, &mut pp_lo[..limit], false, n, 3, 0); // +/- 1/4 limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v2, v0, 7, xs, n, 2, &mut pp_lo[..m], ); // A(-1/4) * B(-1/4) * 4 ^, A(1/4) * B(1/4) * 4^ limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); let (r7, r5) = r7_r5.split_at_mut(p); limbs_square_to_out_toom_8_recursive(r5, v2, wse); limbs_toom_couple_handling(r5, &mut pp_lo[..k], false, n, 2, 0); // +/- 2 limbs_mul_toom_evaluate_poly_in_2_and_neg_2(v2, v0, 7, xs, n, &mut pp_lo[..m]); // A(-2)*B(-2), A(+2)*B(+2) limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); limbs_square_to_out_toom_8_recursive(r3, v2, wse); limbs_toom_couple_handling(r3, &mut pp_lo[..k], false, n, 1, 2); // +/- 8 limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, 7, xs, n, 3, &mut pp_lo[..m]); // A(-8) * B(-8), A(8) * B(8) limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); limbs_square_to_out_toom_8_recursive(r1, v2, wse); limbs_toom_couple_handling(r1_wse, &mut pp_lo[..limit], false, n, 3, 6); // +/- 1/2 limbs_mul_toom_evaluate_poly_in_2_pow_neg_and_neg_2_pow_neg( v2, v0, 7, xs, n, 1, &mut pp_lo[..m], ); // A(-1/2) * B(-1/2) * 2 ^, A(1/2) * B(1/2) * 2 ^ let (r1, wse) = r1_wse.split_at_mut(p); limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); limbs_square_to_out_toom_8_recursive(r6, v2, wse); limbs_toom_couple_handling(r6, &mut pp_lo[..k], false, n, 1, 0); // +/- 1 limbs_mul_toom_evaluate_poly_in_1_and_neg_1(v2, v0, 7, xs, n, &mut pp_lo[..m]); // A(-1) * B(-1), A(1) * B(1) limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); limbs_square_to_out_toom_8_recursive(r4, v2, wse); limbs_toom_couple_handling(r4, &mut pp_lo[..k], false, n, 0, 0); // +/- 4 limbs_mul_toom_evaluate_poly_in_2_pow_and_neg_2_pow(v2, v0, 7, xs, n, 2, &mut pp_lo[..m]); // A(-4) * B(-4), A(4) * B(4) limbs_square_to_out_toom_8_recursive(pp_lo, v0, wse); let (r2, v2) = pp_hi.split_at_mut(m << 1); limbs_square_to_out_toom_8_recursive(r2, &v2[..m], wse); limbs_toom_couple_handling(pp_hi, &mut pp_lo[..k], false, n, 2, 4); // A(0) * B(0) limbs_square_to_out_toom_8_recursive(pp_lo, &xs[..n], wse); limbs_mul_toom_interpolate_16_points(out, r1, r3, r5, r7, n, s << 1, false, &mut wse[..p]); }} pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_square_to_out_scratch_len(n: usize) -> usize { if n < SQR_BASECASE_THRESHOLD || n < SQR_TOOM2_THRESHOLD { 0 } else if n < SQR_TOOM3_THRESHOLD { limbs_square_to_out_toom_2_scratch_len(n) } else if n < SQR_TOOM4_THRESHOLD { limbs_square_to_out_toom_3_scratch_len(n) } else if n < SQR_TOOM6_THRESHOLD { limbs_square_to_out_toom_4_scratch_len(n) } else if n < SQR_TOOM8_THRESHOLD { limbs_square_to_out_toom_6_scratch_len(n) } else if n < SQR_FFT_THRESHOLD { limbs_square_to_out_toom_8_scratch_len(n) } else { 0 } }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sqr` from `mpn/generic/sqr.c`, GMP 6.2.1. pub_crate_test! { #[allow(clippy::absurd_extreme_comparisons)] limbs_square_to_out(out: &mut [Limb], xs: &[Limb], scratch: &mut [Limb]) { let n = xs.len(); assert!(n >= 1); if n < SQR_BASECASE_THRESHOLD { // limbs_mul_greater_to_out_basecase is faster than limbs_square_to_out_basecase on small // sizes sometimes limbs_mul_greater_to_out_basecase(out, xs, xs); } else if n < SQR_TOOM2_THRESHOLD { limbs_square_to_out_basecase(out, xs); } else if n < SQR_TOOM3_THRESHOLD { limbs_square_to_out_toom_2(out, xs, scratch); } else if n < SQR_TOOM4_THRESHOLD { limbs_square_to_out_toom_3(out, xs, scratch); } else if n < SQR_TOOM6_THRESHOLD { limbs_square_to_out_toom_4(out, xs, scratch); } else if n < SQR_TOOM8_THRESHOLD { limbs_square_to_out_toom_6(out, xs, scratch); } else if n < SQR_FFT_THRESHOLD { limbs_square_to_out_toom_8(out, xs, scratch); } else { mpn_square_default_mpn_ctx(out, xs); } }} pub_crate_test! {limbs_square(xs: &[Limb]) -> Vec { let mut out = vec![0; xs.len() << 1]; let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(xs.len())]; limbs_square_to_out(&mut out, xs, &mut square_scratch); out }} impl Square for Natural { type Output = Self; /// Squares a [`Natural`], taking it by value. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.square(), 0); /// assert_eq!(Natural::from(123u32).square(), 15129); /// ``` #[inline] fn square(mut self) -> Self { self.square_assign(); self } } impl Square for &Natural { type Output = Natural; /// Squares a [`Natural`], taking it by reference. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!((&Natural::ZERO).square(), 0); /// assert_eq!((&Natural::from(123u32)).square(), 15129); /// ``` #[inline] fn square(self) -> Natural { match self { &Natural::ZERO | &Natural::ONE => self.clone(), Natural(Small(x)) => Natural({ let (upper, lower) = Limb::x_mul_y_to_zz(*x, *x); if upper == 0 { Small(lower) } else { Large(vec![lower, upper]) } }), Natural(Large(xs)) => Natural::from_owned_limbs_asc(limbs_square(xs)), } } } impl SquareAssign for Natural { /// Squares a [`Natural`] in place. /// /// $$ /// x \gets x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SquareAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.square_assign(); /// assert_eq!(x, 0); /// /// let mut x = Natural::from(123u32); /// x.square_assign(); /// assert_eq!(x, 15129); /// ``` fn square_assign(&mut self) { match self { &mut (Self::ZERO | Self::ONE) => {} Self(Small(x)) => { let (upper, lower) = Limb::x_mul_y_to_zz(*x, *x); if upper == 0 { *x = lower; } else { *self = Self(Large(vec![lower, upper])); } } Self(Large(xs)) => { *xs = limbs_square(xs); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/arithmetic/sub.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Some optimizations contributed by florian1345. // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018, 2020 Free Software Foundation, Inc. // // 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 crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::fmt::Display; use core::ops::{Sub, SubAssign}; use malachite_base::num::arithmetic::traits::CheckedSub; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, subtracts the // `Limb` from the `Natural`. Returns a pair consisting of the limbs of the result, and whether // there was a borrow left over; that is, whether the `Limb` was greater than the `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_sub_1` from `gmp.h`, GMP 6.2.1, where the result is returned. pub_crate_test! {limbs_sub_limb(xs: &[Limb], mut y: Limb) -> (Vec, bool) { let len = xs.len(); let mut out = Vec::with_capacity(len); for i in 0..len { let (diff, overflow) = xs[i].overflowing_sub(y); out.push(diff); if overflow { y = 1; } else { y = 0; out.extend_from_slice(&xs[i + 1..]); break; } } (out, y != 0) }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, subtracts the // `Limb` from the `Natural`, writing the `xs.len()` limbs of the result to an output slice. Returns // whether there was a borrow left over; that is, whether the `Limb` was greater than the `Natural`. // The output slice must be at least as long as the input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs`. // // This is equivalent to `mpn_sub_1` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_sub_limb_to_out(out: &mut [Limb], xs: &[Limb], mut y: Limb) -> bool { let len = xs.len(); assert!(out.len() >= len); for i in 0..len { let overflow; (out[i], overflow) = xs[i].overflowing_sub(y); if overflow { y = 1; } else { y = 0; let copy_index = i + 1; out[copy_index..len].copy_from_slice(&xs[copy_index..]); break; } } y != 0 }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, subtracts the // `Limb` from the `Natural` and writes the limbs of the result to the input slice. Returns whether // there was a borrow left over; that is, whether the `Limb` was greater than the `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_add_1` from `gmp.h`, GMP 6.2.1, where the result is written to the // input slice. pub_crate_test! {limbs_sub_limb_in_place(xs: &mut [T], mut y: T) -> bool { for x in &mut *xs { if x.overflowing_sub_assign(y) { y = T::ONE; } else { return false; } } y != T::ZERO }} #[inline] pub(crate) fn sub_with_carry(x: Limb, y: Limb, carry: Limb) -> (Limb, Limb) { let result_no_carry = x.wrapping_sub(y); let result = result_no_carry.wrapping_sub(carry); let carry = Limb::from((result_no_carry > x) || (result > result_no_carry)); (result, carry) } // Interpreting a two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, // subtracts the second from the first. Returns a pair consisting of the limbs of the result, and // whether there was a borrow left over; that is, whether the second `Natural` was greater than the // first `Natural`. The first slice must be at least as long as the second. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpn_sub` from `gmp.h`, GMP 6.2.1, where the output is returned. pub_crate_test! {limbs_sub(xs: &[Limb], ys: &[Limb]) -> (Vec, bool) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let mut out = Vec::with_capacity(xs_len); let mut carry = 0; for (&x, &y) in xs.iter().zip(ys.iter()) { let o; (o, carry) = sub_with_carry(x, y, carry); out.push(o); } let mut borrow = carry != 0; if xs_len != ys_len { out.extend_from_slice(&xs[ys_len..]); if borrow { borrow = limbs_sub_limb_in_place(&mut out[ys_len..], 1); } } (out, borrow) }} // Interpreting a two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, writing the `xs.len()` limbs of the result to an // output slice. Returns whether there was a borrow left over; that is, whether the second `Natural` // was greater than the first `Natural`. The output slice must be at least as long as either input // slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs` or if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_sub_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); let mut carry = 0; for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { (*out, carry) = sub_with_carry(x, y, carry); } carry > 0 }} // Interpreting a two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, // subtracts the second from the first, writing the `xs.len()` limbs of the result to an output // slice. Returns whether there was a borrow left over; that is, whether the second `Natural` was // greater than the first `Natural`. The output slice must be at least as long as the first input // slice and the first input slice must be at least as long as the second. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs` or if `xs` is shorter than `ys`. // // This is equivalent to `mpn_sub` from `gmp.h`, GMP 6.2.1. pub_crate_test! {limbs_sub_greater_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(out.len() >= xs_len); let (xs_lo, xs_hi) = xs.split_at(ys_len); let borrow = limbs_sub_same_length_to_out(out, xs_lo, ys); if xs_len == ys_len { borrow } else if borrow { limbs_sub_limb_to_out(&mut out[ys_len..], xs_hi, 1) } else { out[ys_len..xs_len].copy_from_slice(xs_hi); false } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, writing the `xs.len()` limbs of the result to // the first (left) slice. Returns whether there was a borrow left over; that is, whether the second // `Natural` was greater than the first `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1, where the output is written to the // first input. pub_crate_test! {limbs_sub_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { assert_eq!(xs.len(), ys.len()); let mut carry = 0; for (x, &y) in xs.iter_mut().zip(ys.iter()) { (*x, carry) = sub_with_carry(*x, y, carry); } carry > 0 }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, subtracts // the second from the first, writing the `xs.len()` limbs of the result to the first (left) slice. // Returns whether there was a borrow left over; that is, whether the second `Natural` was greater // than the first `Natural`. The first slice must be at least as long as the second. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpn_sub` from `gmp.h`, GMP 6.2.1, where the output is written to the first // input. pub_crate_test! {limbs_sub_greater_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let (xs_lo, xs_hi) = xs.split_at_mut(ys_len); let borrow = limbs_sub_same_length_in_place_left(xs_lo, ys); if xs_len == ys_len { borrow } else if borrow { limbs_sub_limb_in_place(xs_hi, 1) } else { false } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, writing the `xs.len()` limbs of the result to // the second (right) slice. Returns whether there was a borrow left over; that is, whether the // second `Natural` was greater than the first `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1, where the output is written to the // second input. pub_crate_test! {limbs_sub_same_length_in_place_right(xs: &[Limb], ys: &mut [Limb]) -> bool { assert_eq!(xs.len(), ys.len()); let mut carry = 0; for (&x, y) in xs.iter().zip(ys.iter_mut()) { (*y, carry) = sub_with_carry(x, *y, carry); } carry > 0 }} // Given two equal-length slices `xs` and `ys`, computes the difference between the `Natural`s whose // limbs are `xs` and `&ys[..len]`, and writes the limbs of the result to `ys`. Returns whether // there was a borrow left over; that is, whether the second `Natural` was greater than the first // `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `len` is greater than `xs.len()`. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1, where the output is written to the // second input (which has `len` limbs) and the second input has enough space past `len` to // accomodate the output. pub_crate_test! {limbs_slice_sub_in_place_right(xs: &[Limb], ys: &mut [Limb], len: usize) -> bool { let xs_len = xs.len(); assert_eq!(xs_len, ys.len()); let (xs_lo, xs_hi) = xs.split_at(len); let (ys_lo, ys_hi) = ys.split_at_mut(len); let borrow = limbs_sub_same_length_in_place_right(xs_lo, ys_lo); if xs_len == len { borrow } else if borrow { limbs_sub_limb_to_out(ys_hi, xs_hi, 1) } else { ys_hi.copy_from_slice(xs_hi); false } }} // Interpreting a of `Limb`s and a `Vec` of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, writing the `xs.len()` limbs of the result to // the `Vec`, possibly extending the `Vec`'s length. Returns whether there was a borrow left over; // that is, whether the second `Natural` was greater than the first `Natural`. The first slice must // be at least as long as the second. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `xs.len()` - // `ys.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. pub_crate_test! {limbs_vec_sub_in_place_right(xs: &[Limb], ys: &mut Vec) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let (xs_lo, xs_hi) = xs.split_at(ys_len); let borrow = limbs_sub_same_length_in_place_right(xs_lo, ys); if xs_len == ys_len { borrow } else { ys.extend_from_slice(xs_hi); if borrow { limbs_sub_limb_in_place(&mut ys[ys_len..], 1) } else { false } } }} // Given a slice `xs`, computes the difference between the `Natural`s whose limbs are // `&xs[..xs.len() - right_start]` and `&xs[right_start..]`, and writes the limbs of the result to // `&xs[..xs.len() - right_start]`. Returns whether there was a borrow left over; that is, whether // the second `Natural` was greater than the first `Natural`. As implied by the name, the input // slices may overlap. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len() - right_start`. // // # Panics // Panics if `right_start` is greater than `xs.len()`. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1, where the output is written to the // first input, and the two inputs are possibly-overlapping subslices of a single slice. pub_crate_test! {limbs_sub_same_length_in_place_with_overlap( xs: &mut [Limb], right_start: usize ) -> bool { let len = xs.len() - right_start; let mut carry = 0; for i in 0..len { (xs[i], carry) = sub_with_carry(xs[i], xs[i + right_start], carry); } carry != 0 }} // Given two slices `xs` and `ys`, computes the difference between the `Natural`s whose limbs are // `&xs[xs.len() - ys.len()..]` and `&ys`, and writes the limbs of the result to `&xs[..ys.len()]`. // Returns whether there was a borrow left over; that is, whether the second `Natural` was greater // than the first `Natural`. As implied by the name, the input and output ranges may overlap. `xs` // must be at least as long as `ys`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // # Panics // Panics if `xs.len()` is shorter than `ys.len()`. // // This is equivalent to `mpn_sub_n` from `gmp.h`, GMP 6.2.1, where the output is a prefix of a // slice and the left operand of the subtraction is a suffix of the same slice, and the prefix and // suffix may overlap. pub_crate_test! {limbs_sub_same_length_to_out_with_overlap(xs: &mut [Limb], ys: &[Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); let right_start = xs_len - ys_len; let mut carry = 0; for i in 0..ys_len { (xs[i], carry) = sub_with_carry(xs[i + right_start], ys[i], carry); } carry != 0 }} // Interpreting a two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, and then subtracts a borrow (`false` is 0, // `true` is 1), writing the `xs.len()` limbs of the result to an output slice. Returns whether // there was a borrow left over. The output slice must be at least as long as either input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs` or if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_nc` from `gmp-impl.h`, GMP 6.2.1, where `rp`, `up`, and `vp` are // disjoint. pub_crate_test! {limbs_sub_same_length_with_borrow_in_to_out( out: &mut [Limb], xs: &[Limb], ys: &[Limb], borrow_in: bool, ) -> bool { let mut borrow = limbs_sub_same_length_to_out(out, xs, ys); if borrow_in { borrow |= limbs_sub_limb_in_place(&mut out[..xs.len()], 1); } borrow }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, and then subtracts a borrow (`false` is 0, // `true` is 1), writing the `xs.len()` limbs of the result to the first (left) slice. Return // whether there was a borrow left over. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_nc` from `gmp-impl.h`, GMP 6.2.1, where `rp` is the same as `up`. pub_crate_test! {limbs_sub_same_length_with_borrow_in_in_place_left( xs: &mut [Limb], ys: &[Limb], borrow_in: bool, ) -> bool { let mut borrow = limbs_sub_same_length_in_place_left(xs, ys); if borrow_in { borrow |= limbs_sub_limb_in_place(xs, 1); } borrow }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, subtracts the second from the first, and then subtracts a borrow (`false` is 0, // `true` is 1), writing the `xs.len()` limbs of the result to the second (right) slice. Returns // whether there was a borrow left over. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_sub_nc` from `gmp-impl.h`, GMP 6.2.1, where `rp` is the same as `vp`. pub_crate_test! {limbs_sub_same_length_with_borrow_in_in_place_right( xs: &[Limb], ys: &mut [Limb], borrow_in: bool, ) -> bool { let mut borrow = limbs_sub_same_length_in_place_right(xs, ys); if borrow_in { borrow |= limbs_sub_limb_in_place(ys, 1); } borrow }} fn sub_panic(x: S, y: T) -> ! { panic!("Cannot subtract a number from a smaller number. self: {x}, other: {y}"); } impl Natural { pub(crate) fn sub_limb(self, other: Limb) -> Self { self.checked_sub_limb(other) .expect("Cannot subtract a Limb from a smaller Natural") } pub(crate) fn sub_limb_ref(&self, other: Limb) -> Self { self.checked_sub_limb_ref(other).unwrap_or_else(|| { sub_panic(self, other); }) } #[cfg(feature = "float_helpers")] pub fn sub_assign_at_limb(&mut self, i: usize, y: Limb) { if i == 0 { *self -= Self::from(y); return; } let xs = self.promote_in_place(); if xs.len() <= i { xs.resize(i + 1, 0); } assert!(!limbs_sub_limb_in_place(&mut xs[i..], y)); self.trim(); } } impl Sub for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking both by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) - Natural::ZERO, 123); /// assert_eq!(Natural::from(456u32) - Natural::from(123u32), 333); /// assert_eq!( /// Natural::from(10u32).pow(12) * Natural::from(3u32) - Natural::from(10u32).pow(12), /// 2000000000000u64 /// ); /// ``` fn sub(self, other: Self) -> Self { self.checked_sub(other) .expect("Cannot subtract a Natural from a smaller Natural") } } impl Sub<&Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) - &Natural::ZERO, 123); /// assert_eq!(Natural::from(456u32) - &Natural::from(123u32), 333); /// assert_eq!( /// Natural::from(10u32).pow(12) * Natural::from(3u32) - &Natural::from(10u32).pow(12), /// 2000000000000u64 /// ); /// ``` fn sub(self, other: &Self) -> Self { self.checked_sub(other) .expect("Cannot subtract a Natural from a smaller Natural") } } impl Sub for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking the first by reference and the second /// by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) - Natural::ZERO, 123); /// assert_eq!(&Natural::from(456u32) - Natural::from(123u32), 333); /// assert_eq!( /// &(Natural::from(10u32).pow(12) * Natural::from(3u32)) - Natural::from(10u32).pow(12), /// 2000000000000u64 /// ); /// ``` fn sub(self, other: Natural) -> Natural { self.checked_sub(other) .expect("Cannot subtract a Natural from a smaller Natural") } } impl Sub<&Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by another [`Natural`], taking both by reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) - &Natural::ZERO, 123); /// assert_eq!(&Natural::from(456u32) - &Natural::from(123u32), 333); /// assert_eq!( /// &(Natural::from(10u32).pow(12) * Natural::from(3u32)) - &Natural::from(10u32).pow(12), /// 2000000000000u64 /// ); /// ``` fn sub(self, other: &Natural) -> Natural { self.checked_sub(other).unwrap_or_else(|| { sub_panic(self, other); }) } } impl SubAssign for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32).pow(12) * Natural::from(10u32); /// x -= Natural::from(10u32).pow(12); /// x -= Natural::from(10u32).pow(12) * Natural::from(2u32); /// x -= Natural::from(10u32).pow(12) * Natural::from(3u32); /// x -= Natural::from(10u32).pow(12) * Natural::from(4u32); /// assert_eq!(x, 0); /// ``` fn sub_assign(&mut self, other: Self) { assert!( !self.sub_assign_no_panic(other), "Cannot subtract a Natural from a smaller Natural" ); } } impl SubAssign<&Self> for Natural { /// Subtracts a [`Natural`] by another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(10u32).pow(12) * Natural::from(10u32); /// x -= &Natural::from(10u32).pow(12); /// x -= &(Natural::from(10u32).pow(12) * Natural::from(2u32)); /// x -= &(Natural::from(10u32).pow(12) * Natural::from(3u32)); /// x -= &(Natural::from(10u32).pow(12) * Natural::from(4u32)); /// assert_eq!(x, 0); /// ``` fn sub_assign(&mut self, other: &Self) { assert!( !self.sub_assign_ref_no_panic(other), "Cannot subtract a Natural from a smaller Natural" ); } } ================================================ FILE: malachite-nz/src/natural/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1992-1994, 1996, 2000, 2001, 2002, 2004, 2005, 2012 Free Software Foundation, // Inc. // // 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 crate::natural::Natural; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::sub::{limbs_sub_greater_in_place_left, limbs_sub_limb_in_place}; use crate::natural::comparison::cmp::limbs_cmp; use crate::platform::{DoubleLimb, Limb}; use alloc::vec::Vec; use core::cmp::Ordering::*; use core::fmt::Display; use malachite_base::num::arithmetic::traits::{ CheckedSubMul, SubMul, SubMulAssign, WrappingAddAssign, }; use malachite_base::num::conversion::traits::SplitInHalf; // Given the limbs of two `Natural`s x and y, and a limb z, returns the limbs of x - y * z. If y * z // > x, `None` is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, and `w` is returned instead of overwriting the first input. pub_crate_test! {limbs_sub_mul_limb_greater( xs: &[Limb], ys: &[Limb], z: Limb ) -> Option> { let ys_len = ys.len(); let mut result = xs.to_vec(); let borrow = limbs_sub_mul_limb_same_length_in_place_left(&mut result[..ys_len], ys, z); if borrow == 0 { Some(result) } else if xs.len() == ys_len || limbs_sub_limb_in_place(&mut result[ys_len..], borrow) { None } else { Some(result) } }} // Given the equal-length limbs of two `Natural`s x and y, and a limb z, calculates x - y * z and // writes the limbs of the result to the first (left) input slice. If y * z > x, a nonzero borrow is // returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_submul_1` from `mpn/generic/submul_1.c`, GMP 6.2.1. pub_crate_test! {limbs_sub_mul_limb_same_length_in_place_left( xs: &mut [Limb], ys: &[Limb], z: Limb ) -> Limb { assert_eq!(xs.len(), ys.len()); let mut borrow = 0; let z = DoubleLimb::from(z); for (x, &y) in xs.iter_mut().zip(ys.iter()) { let (upper, mut lower) = (DoubleLimb::from(y) * z).split_in_half(); lower.wrapping_add_assign(borrow); if lower < borrow { borrow = upper.wrapping_add(1); } else { borrow = upper; } lower = x.wrapping_sub(lower); if lower > *x { borrow.wrapping_add_assign(1); } *x = lower; } borrow }} // Given the limbs of two `Natural`s x and y, and a limb z, calculates x - y * z and writes the // limbs of the result to the first (left) input slice. If y * z > x, a nonzero borrow is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpn_submul_1` from `mpn/generic/submul_1.c`, GMP 6.2.1, but where the // first input may be longer than the second. pub_crate_test! {limbs_sub_mul_limb_greater_in_place_left( xs: &mut [Limb], ys: &[Limb], limb: Limb ) -> Limb { let (xs_lo, xs_hi) = xs.split_at_mut(ys.len()); let borrow = limbs_sub_mul_limb_same_length_in_place_left(xs_lo, ys, limb); if borrow == 0 || xs_hi.is_empty() { borrow } else { Limb::from(limbs_sub_limb_in_place(xs_hi, borrow)) } }} // Given the equal-length limbs of two `Natural`s x and y, and a limb z, calculates x - y * z and // writes the limbs of the result to the second (right) input slice. If y * z > x, a nonzero borrow // is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive and have the same lengths, sub is negative, and the lowest limbs of the result are // written to the second input rather than the first. pub_crate_test! {limbs_sub_mul_limb_same_length_in_place_right( xs: &[Limb], ys: &mut [Limb], z: Limb, ) -> Limb { assert_eq!(xs.len(), ys.len()); let mut borrow = 0; let z = DoubleLimb::from(z); for (&x, y) in xs.iter().zip(ys.iter_mut()) { let (upper, mut lower) = (DoubleLimb::from(*y) * z).split_in_half(); lower.wrapping_add_assign(borrow); if lower < borrow { borrow = upper.wrapping_add(1); } else { borrow = upper; } lower = x.wrapping_sub(lower); if lower > x { borrow.wrapping_add_assign(1); } *y = lower; } borrow }} // Given the limbs of two `Natural`s x and y, and a limb z, calculates x - y * z and writes the // limbs of the result to the second (right) input `Vec`. If y * z > x, a nonzero borrow is // returned. // # Worst-case complexity // $T(n) = O(n)$ // // $M(m) = O(m)$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is `xs.len() - ys.len()`. // // # Panics // Panics if `xs` is shorter than `ys`. // // This is equivalent to `mpz_aorsmul_1` from `mpz/aorsmul_i.c`, GMP 6.2.1, where `w` and `x` are // positive, `sub` is negative, and the result is written to the second input rather than the first. pub_test! {limbs_sub_mul_limb_greater_in_place_right( xs: &[Limb], ys: &mut Vec, z: Limb ) -> Limb { let ys_len = ys.len(); let (xs_lo, xs_hi) = xs.split_at(ys_len); let borrow = limbs_sub_mul_limb_same_length_in_place_right(xs_lo, ys, z); if xs_hi.is_empty() { borrow } else { ys.extend(&xs[ys_len..]); if borrow == 0 { 0 } else { Limb::from(limbs_sub_limb_in_place(&mut ys[ys_len..], borrow)) } } }} // Given the limbs `xs`, `ys` and `zs` of three `Natural`s x, y, and z, returns the limbs of x - y // * z. If x < y * z, `None` is returned. `ys` and `zs` should have length at least 2, and the // length of `xs` should be at least `ys.len()` + `zs.len()` - 1 (if the latter condition is false, // the result would be `None` and there's no point in calling this function). None of the slices // should have any trailing zeros. The result, if it exists, will have no trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n, m) = O(m + n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` have fewer than two elements each, or if `xs.len()` < `ys.len()` + // `zs.len()` - 1. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive, `sub` is negative, negative results are converted to `None`, and `w` is returned // instead of overwriting the first input. pub_crate_test! {limbs_sub_mul(xs: &[Limb], ys: &[Limb], zs: &[Limb]) -> Option> { let mut xs = xs.to_vec(); if limbs_sub_mul_in_place_left(&mut xs, ys, zs) { None } else { Some(xs) } }} // Given the limbs `xs`, `ys` and `zs` of three `Natural`s x, y, and z, computes x - y * z. The // limbs of the result are written to `xs`. Returns whether a borrow (overflow) occurred: if x < y // * z, `true` is returned and the value of `xs` should be ignored. `ys` and `zs` should have // length at least 2, and the length of `xs` should be at least `ys.len()` + `zs.len()` - 1 (if the // latter condition is false, the result would be negative and there would be no point in calling // this function). None of the slices should have any trailing zeros. The result, if it exists, will // have no trailing zeros. // // # Worst-case complexity // $T(n, m) = O(m + n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `max(ys.len(), zs.len())`, and $m$ is // `xs.len()`. // // # Panics // Panics if `ys` or `zs` have fewer than two elements each, or if `xs.len() < ys.len() + zs.len() // - 1`. // // This is equivalent to `mpz_aorsmul` from `mpz/aorsmul.c`, GMP 6.2.1, where `w`, `x`, and `y` are // positive, `sub` is negative and negative results are discarded. pub_crate_test! {limbs_sub_mul_in_place_left(xs: &mut [Limb], ys: &[Limb], zs: &[Limb]) -> bool { assert!(ys.len() > 1); assert!(zs.len() > 1); let mut scratch = limbs_mul(ys, zs); assert!(xs.len() >= scratch.len() - 1); if *scratch.last().unwrap() == 0 { scratch.pop(); } let borrow = limbs_cmp(xs, &scratch) == Less; if !borrow { assert!(!limbs_sub_greater_in_place_left(xs, &scratch)); } borrow }} fn sub_mul_panic(a: S, b: T, c: U) -> ! { panic!("Cannot perform sub_mul. a: {a}, b: {b}, c: {c}"); } impl SubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by value. /// /// $$ /// f(x, y, z) = x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).sub_mul(Natural::from(3u32), Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .sub_mul(Natural::from(0x10000u32), Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` fn sub_mul(self, y: Self, z: Self) -> Self { self.checked_sub_mul(y, z) .expect("Natural sub_mul_assign cannot have a negative result") } } impl<'a> SubMul for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first two by /// value and the third by reference. /// /// $$ /// f(x, y, z) = x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).sub_mul(Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .sub_mul(Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` fn sub_mul(self, y: Self, z: &'a Self) -> Self { self.checked_sub_mul(y, z) .expect("Natural sub_mul_assign cannot have a negative result") } } impl<'a> SubMul<&'a Self, Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first and third /// by value and the second by reference. /// /// $$ /// f(x, y, z) = x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).sub_mul(&Natural::from(3u32), Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .sub_mul(&Natural::from(0x10000u32), Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` fn sub_mul(self, y: &'a Self, z: Self) -> Self { self.checked_sub_mul(y, z) .expect("Natural sub_mul_assign cannot have a negative result") } } impl<'a, 'b> SubMul<&'a Self, &'b Self> for Natural { type Output = Self; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking the first by value /// and the second and third by reference. /// /// $$ /// f(x, y, z) = x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(20u32).sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// Natural::from(10u32) /// .pow(12) /// .sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` fn sub_mul(self, y: &'a Self, z: &'b Self) -> Self { self.checked_sub_mul(y, z) .expect("Natural sub_mul_assign cannot have a negative result") } } impl SubMul<&Natural, &Natural> for &Natural { type Output = Natural; /// Subtracts a [`Natural`] by the product of two other [`Natural`]s, taking all three by /// reference. /// /// $$ /// f(x, y, z) = x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n, m) = O(m + n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMul}; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// (&Natural::from(20u32)).sub_mul(&Natural::from(3u32), &Natural::from(4u32)), /// 8 /// ); /// assert_eq!( /// (&Natural::from(10u32).pow(12)) /// .sub_mul(&Natural::from(0x10000u32), &Natural::from(0x10000u32)), /// 995705032704u64 /// ); /// ``` fn sub_mul(self, y: &Natural, z: &Natural) -> Natural { self.checked_sub_mul(y, z).unwrap_or_else(|| { sub_mul_panic(self, y, z); }) } } impl SubMulAssign for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking both /// [`Natural`]s on the right-hand side by value. /// /// $$ /// x \gets x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.sub_mul_assign(Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32).pow(12); /// x.sub_mul_assign(Natural::from(0x10000u32), Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` fn sub_mul_assign(&mut self, y: Self, z: Self) { assert!( !self.sub_mul_assign_no_panic(y, z), "Natural sub_mul_assign cannot have a negative result" ); } } impl<'a> SubMulAssign for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking the first /// [`Natural`] on the right-hand side by value and the second by reference. /// /// $$ /// x \gets x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.sub_mul_assign(Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32).pow(12); /// x.sub_mul_assign(Natural::from(0x10000u32), &Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` fn sub_mul_assign(&mut self, y: Self, z: &'a Self) { assert!( !self.sub_mul_assign_val_ref_no_panic(y, z), "Natural sub_mul_assign cannot have a negative result" ); } } impl<'a> SubMulAssign<&'a Self, Self> for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking the first /// [`Natural`] on the right-hand side by reference and the second by value. /// /// $$ /// x \gets x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.sub_mul_assign(&Natural::from(3u32), Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32).pow(12); /// x.sub_mul_assign(&Natural::from(0x10000u32), Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` fn sub_mul_assign(&mut self, y: &'a Self, z: Self) { assert!( !self.sub_mul_assign_ref_val_no_panic(y, z), "Natural sub_mul_assign cannot have a negative result" ); } } impl<'a, 'b> SubMulAssign<&'a Self, &'b Self> for Natural { /// Subtracts a [`Natural`] by the product of two other [`Natural`]s in place, taking both /// [`Natural`]s on the right-hand side by reference. /// /// $$ /// x \gets x - yz. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(m + n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(y.significant_bits(), /// z.significant_bits())`, and $m$ is `x.significant_bits()`. /// /// # Panics /// Panics if `y * z` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, SubMulAssign}; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(20u32); /// x.sub_mul_assign(&Natural::from(3u32), &Natural::from(4u32)); /// assert_eq!(x, 8); /// /// let mut x = Natural::from(10u32).pow(12); /// x.sub_mul_assign(&Natural::from(0x10000u32), &Natural::from(0x10000u32)); /// assert_eq!(x, 995705032704u64); /// ``` fn sub_mul_assign(&mut self, y: &'a Self, z: &'b Self) { assert!( !self.sub_mul_assign_ref_ref_no_panic(y, z), "Natural sub_mul_assign cannot have a negative result" ); } } ================================================ FILE: malachite-nz/src/natural/comparison/cmp.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1997, 1999-2016, 2020 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use core::mem::swap; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::{slice_leading_zeros, slice_test_zero}; // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, compares the two `Natural`s. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_cmp` from `gmp.h`, GMP 6.2.1. // // # Panics // Panics if `xs` and `ys` have different lengths. pub_crate_test! {limbs_cmp_same_length(xs: &[Limb], ys: &[Limb]) -> Ordering { assert_eq!(xs.len(), ys.len()); xs.iter().rev().cmp(ys.iter().rev()) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, compares // the two `Natural`s. Neither limb slice can contain trailing zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // # Panics // Panics if the last element of `xs` or `ys` is zero. pub_crate_test! {limbs_cmp(xs: &[Limb], ys: &[Limb]) -> Ordering { assert_ne!(xs.last(), Some(&0)); assert_ne!(ys.last(), Some(&0)); xs.len() .cmp(&ys.len()) .then_with(|| limbs_cmp_same_length(xs, ys)) }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns // their normalized comparison. See `Natural::cmp_normalized` for details. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // # Panics // Panics if either `xs` or `ys` is empty, or if the last element of `xs` or `ys` is zero. pub_test! {limbs_cmp_normalized(xs: &[Limb], ys: &[Limb]) -> Ordering { let mut xs = &xs[slice_leading_zeros(xs)..]; let mut ys = &ys[slice_leading_zeros(ys)..]; let mut xs_leading = LeadingZeros::leading_zeros(*xs.last().unwrap()); assert_ne!(xs_leading, Limb::WIDTH); let mut ys_leading = LeadingZeros::leading_zeros(*ys.last().unwrap()); assert_ne!(ys_leading, Limb::WIDTH); let mut xs_len = xs.len(); let mut ys_len = ys.len(); let mut swapped = false; match xs_leading.cmp(&ys_leading) { Equal => { return match xs_len.cmp(&ys_len) { Equal => limbs_cmp_same_length(xs, ys), Less => { let leading_cmp = limbs_cmp_same_length(xs, &ys[ys_len - xs_len..]); if leading_cmp == Greater { Greater } else { Less } } Greater => { let leading_cmp = limbs_cmp_same_length(&xs[xs_len - ys_len..], ys); if leading_cmp == Less { Less } else { Greater } } }; } Less => { swap(&mut xs, &mut ys); swap(&mut xs_leading, &mut ys_leading); swap(&mut xs_len, &mut ys_len); swapped = true; } _ => {} } let xs_shift = xs_leading - ys_leading; let comp_xs_shift = Limb::WIDTH - xs_shift; let mut xs_i = xs_len - 1; let mut ys_i = ys_len - 1; loop { let y = ys[ys_i]; let xs_hi = xs[xs_i]; let xs_lo = if xs_i == 0 { 0 } else { xs[xs_i - 1] }; let x = (xs_hi << xs_shift) | (xs_lo >> comp_xs_shift); let cmp = x.cmp(&y); if cmp != Equal { return if swapped { cmp.reverse() } else { cmp }; } if xs_i == 0 { return if ys_i == 0 { Equal } else if swapped { Greater } else { Less }; } else if ys_i == 0 { return if xs_lo << xs_shift == 0 && slice_test_zero(&xs[..xs_i - 1]) { Equal } else if swapped { Less } else { Greater }; } xs_i -= 1; ys_i -= 1; } }} impl PartialOrd for Natural { /// Compares two [`Natural`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Natural { /// Compares two [`Natural`]s. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) > Natural::from(122u32)); /// assert!(Natural::from(123u32) >= Natural::from(122u32)); /// assert!(Natural::from(123u32) < Natural::from(124u32)); /// assert!(Natural::from(123u32) <= Natural::from(124u32)); /// ``` fn cmp(&self, other: &Self) -> Ordering { if core::ptr::eq(self, other) { return Equal; } match (self, other) { (&Self(Small(ref x)), &Self(Small(ref y))) => x.cmp(y), (&Self(Small(_)), &Self(Large(_))) => Less, (&Self(Large(_)), &Self(Small(_))) => Greater, (&Self(Large(ref xs)), &Self(Large(ref ys))) => limbs_cmp(xs, ys), } } } impl Natural { /// Returns a result of a comparison between two [`Natural`]s as if each had been multiplied by /// some power of 2 to bring it into the interval $[1, 2)$. /// /// That is, the comparison is equivalent to a comparison between $f(x)$ and $f(y)$, where /// $$ /// f(n) = n2^{\lfloor\log_2 n \rfloor}. /// $$ /// /// The multiplication is not actually performed. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if either argument is zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::*; /// use malachite_nz::natural::Natural; /// /// // 1 == 1.0 * 2^0, 4 == 1.0 * 2^2 /// // 1.0 == 1.0 /// assert_eq!( /// Natural::from(1u32).cmp_normalized(&Natural::from(4u32)), /// Equal /// ); /// /// // 5 == 1.25 * 2^2, 6 == 1.5 * 2^2 /// // 1.25 < 1.5 /// assert_eq!( /// Natural::from(5u32).cmp_normalized(&Natural::from(6u32)), /// Less /// ); /// /// // 3 == 1.5 * 2^1, 17 == 1.0625 * 2^4 /// // 1.5 > 1.0625 /// assert_eq!( /// Natural::from(3u32).cmp_normalized(&Natural::from(17u32)), /// Greater /// ); /// /// // 9 == 1.125 * 2^3, 36 == 1.125 * 2^5 /// // 1.125 == 1.125 /// assert_eq!( /// Natural::from(9u32).cmp_normalized(&Natural::from(36u32)), /// Equal /// ); /// ``` pub fn cmp_normalized(&self, other: &Self) -> Ordering { assert_ne!(*self, 0); assert_ne!(*other, 0); if core::ptr::eq(self, other) { return Equal; } match (self, other) { (&Self(Small(x)), &Self(Small(y))) => { let leading_x = x.leading_zeros(); let leading_y = y.leading_zeros(); match leading_x.cmp(&leading_y) { Equal => x.cmp(&y), Less => x.cmp(&(y << (leading_y - leading_x))), Greater => (x << (leading_x - leading_y)).cmp(&y), } } (&Self(Small(x)), &Self(Large(ref ys))) => limbs_cmp_normalized(&[x], ys), (&Self(Large(ref xs)), &Self(Small(y))) => limbs_cmp_normalized(xs, &[y]), (&Self(Large(ref xs)), &Self(Large(ref ys))) => limbs_cmp_normalized(xs, ys), } } #[cfg(feature = "float_helpers")] pub fn cmp_normalized_no_shift(&self, other: &Self) -> Ordering { assert_ne!(*self, 0); assert_ne!(*other, 0); if core::ptr::eq(self, other) { return Equal; } match (self, other) { (&Self(Small(x)), &Self(Small(y))) => x.cmp(&y), (Self(Small(x)), &Self(Large(ref ys))) => { let (ys_last, ys_init) = ys.split_last().unwrap(); let c = x.cmp(ys_last); if c != Equal { c } else if slice_test_zero(ys_init) { Equal } else { Less } } (&Self(Large(ref xs)), Self(Small(y))) => { let (xs_last, xs_init) = xs.split_last().unwrap(); let c = xs_last.cmp(y); if c != Equal { c } else if slice_test_zero(xs_init) { Equal } else { Greater } } (&Self(Large(ref xs)), &Self(Large(ref ys))) => { let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys_len) { Equal => xs.iter().rev().cmp(ys.iter().rev()), Less => { let (ys_lo, ys_hi) = ys.split_at(ys_len - xs_len); let c = xs.iter().rev().cmp(ys_hi.iter().rev()); if c != Equal { c } else if slice_test_zero(ys_lo) { Equal } else { Less } } Greater => { let (xs_lo, xs_hi) = xs.split_at(xs_len - ys_len); let c = xs_hi.iter().rev().cmp(ys.iter().rev()); if c != Equal { c } else if slice_test_zero(xs_lo) { Equal } else { Greater } } } } } } } ================================================ FILE: malachite-nz/src/natural/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::comparison::traits::EqAbs; macro_rules! impl_eq_abs { ($t: ident) => { impl EqAbs<$t> for Natural { /// Determines whether the absolute values of a [`Natural`] and a primitive float are /// equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { *self == other.abs() } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive float and a [`Natural`] are /// equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &Natural) -> bool { self.abs() == *other } } }; } apply_to_primitive_floats!(impl_eq_abs); ================================================ FILE: malachite-nz/src/natural/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::comparison::traits::EqAbs; macro_rules! impl_unsigned { ($t: ident) => { impl EqAbs<$t> for Natural { /// Determines whether the absolute values of a [`Natural`] and a primitive unsigned /// integer are equal. /// /// Since both values are non-negative, this is the same as ordinary equality. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { self == other } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive unsigned integer and a /// [`Natural`] are equal. /// /// Since both values are non-negative, this is the same as ordinary equality. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Natural) -> bool { self == other } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl EqAbs<$t> for Natural { /// Determines whether the absolute values of a [`Natural`] and a primitive signed /// integer are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { *self == other.unsigned_abs() } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive signed integer and a /// [`Natural`] are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Natural) -> bool { self.unsigned_abs() == *other } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/natural/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// Comparison of [`Natural`](crate::natural::Natural)s. pub mod cmp; /// Equality of the absolute values of a [`Natural`](crate::natural::Natural) and a primitive float. /// /// # eq_abs /// ``` /// use malachite_base::num::basic::traits::{NegativeInfinity, Zero}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).eq_abs(&123.0), true); /// assert_eq!(Natural::from(123u32).eq_abs(&5.0), false); /// assert_eq!(Natural::from(123u32).eq_abs(&-123.0), true); /// assert_eq!(Natural::from(123u32).eq_abs(&-5.0), false); /// assert_eq!(Natural::ZERO.eq_abs(&0.0), true); /// assert_eq!(Natural::ZERO.eq_abs(&-0.0), true); /// assert_eq!(Natural::ZERO.eq_abs(&f64::NAN), false); /// assert_eq!(Natural::ZERO.eq_abs(&f64::INFINITY), false); /// assert_eq!(Natural::ZERO.eq_abs(&f64::NEGATIVE_INFINITY), false); /// /// assert_eq!(123.0.eq_abs(&Natural::from(123u32)), true); /// assert_eq!(5.0.eq_abs(&Natural::from(123u32)), false); /// assert_eq!((-123.0).eq_abs(&Natural::from(123u32)), true); /// assert_eq!((-5.0).eq_abs(&Natural::from(123u32)), false); /// assert_eq!(0.0.eq_abs(&Natural::ZERO), true); /// assert_eq!((-0.0).eq_abs(&Natural::ZERO), true); /// assert_eq!(f64::NAN.eq_abs(&Natural::ZERO), false); /// assert_eq!(f64::INFINITY.eq_abs(&Natural::ZERO), false); /// assert_eq!(f64::NEGATIVE_INFINITY.eq_abs(&Natural::ZERO), false); /// ``` pub mod eq_abs_primitive_float; /// Equality of the absolute values of a [`Natural`](crate::natural::Natural) and a primitive /// integer. /// /// # eq_abs /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).eq_abs(&123u32), true); /// assert_eq!(Natural::from(123u32).eq_abs(&5u32), false); /// /// assert_eq!(Natural::from(123u32).eq_abs(&123u64), true); /// assert_eq!(Natural::from(123u32).eq_abs(&5u64), false); /// /// assert_eq!(Natural::from(123u32).eq_abs(&123i64), true); /// assert_eq!(Natural::from(123u32).eq_abs(&-123i64), true); /// /// assert_eq!(123u8.eq_abs(&Natural::from(123u32)), true); /// assert_eq!(5u8.eq_abs(&Natural::from(123u32)), false); /// /// assert_eq!(123u64.eq_abs(&Natural::from(123u32)), true); /// assert_eq!(5u64.eq_abs(&Natural::from(123u32)), false); /// /// assert_eq!(123i64.eq_abs(&Natural::from(123u32)), true); /// assert_eq!((-123i64).eq_abs(&Natural::from(123u32)), true); /// ``` pub mod eq_abs_primitive_int; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Natural`](crate::natural::Natural)s and primitive floats. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32).gt_abs(&-122.5f32)); /// assert!(Natural::from(123u32).lt_abs(&f32::NEGATIVE_INFINITY)); /// assert!((-122.5f32).lt_abs(&Natural::from(123u32))); /// assert!(f32::NEGATIVE_INFINITY.gt_abs(&Natural::from(123u32))); /// ``` pub mod partial_cmp_abs_primitive_float; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Natural`](crate::natural::Natural)s and primitive integers. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(122u32).lt_abs(&123u64)); /// assert!(Natural::from(122u32).le_abs(&123u64)); /// assert!(Natural::from(123u32).lt_abs(&124u64)); /// assert!(Natural::from(123u32).le_abs(&124u64)); /// assert!(Natural::from(10u32).pow(12).gt_abs(&123u64)); /// assert!(Natural::from(10u32).pow(12).ge_abs(&123u64)); /// /// assert!(Natural::from(122u32).lt_abs(&-123i64)); /// assert!(Natural::from(122u32).le_abs(&-123i64)); /// assert!(Natural::from(124u32).gt_abs(&-123i64)); /// assert!(Natural::from(124u32).ge_abs(&-123i64)); /// assert!(Natural::from(10u32).pow(12).gt_abs(&123i64)); /// assert!(Natural::from(10u32).pow(12).ge_abs(&123i64)); /// /// assert!(123u64.gt_abs(&Natural::from(122u32))); /// assert!(123u64.ge_abs(&Natural::from(122u32))); /// assert!(124u64.gt_abs(&Natural::from(123u32))); /// assert!(124u64.ge_abs(&Natural::from(123u32))); /// assert!(123u64.lt_abs(&Natural::from(10u32).pow(12))); /// assert!(123u64.le_abs(&Natural::from(10u32).pow(12))); /// /// assert!((-123i64).gt_abs(&Natural::from(122u32))); /// assert!((-123i64).ge_abs(&Natural::from(122u32))); /// assert!((-123i64).lt_abs(&Natural::from(124u32))); /// assert!((-123i64).le_abs(&Natural::from(124u32))); /// assert!(123i64.lt_abs(&Natural::from(10u32).pow(12))); /// assert!(123i64.le_abs(&Natural::from(10u32).pow(12))); /// ``` pub mod partial_cmp_abs_primitive_int; /// Comparison of [`Natural`](crate::natural::Natural)s and primitive floats. /// /// # partial_cmp /// ``` /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) > 122.5f32); /// assert!(Natural::from(123u32) < f32::INFINITY); /// assert!(122.5f32 < Natural::from(123u32)); /// assert!(f32::INFINITY > Natural::from(123u32)); /// ``` pub mod partial_cmp_primitive_float; /// Comparison of [`Natural`](crate::natural::Natural)s and primitive integers. /// /// # partial_cmp /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) > 122u32); /// assert!(Natural::from(123u32) >= 122u32); /// assert!(Natural::from(123u32) < 124u32); /// assert!(Natural::from(123u32) <= 124u32); /// assert!(Natural::from(10u32).pow(12) > 123u32); /// assert!(Natural::from(10u32).pow(12) >= 123u32); /// /// assert!(Natural::from(123u32) > 122u8); /// assert!(Natural::from(123u32) >= 122u8); /// assert!(Natural::from(123u32) < 124u8); /// assert!(Natural::from(123u32) <= 124u8); /// assert!(Natural::from(10u32).pow(12) > 123u8); /// assert!(Natural::from(10u32).pow(12) >= 123u8); /// /// assert!(Natural::from(123u32) > 122u64); /// assert!(Natural::from(123u32) >= 122u64); /// assert!(Natural::from(123u32) < 124u64); /// assert!(Natural::from(123u32) <= 124u64); /// assert!(Natural::from(10u32).pow(12) > 123u64); /// assert!(Natural::from(10u32).pow(12) >= 123u64); /// /// assert!(Natural::from(123u32) > 122i64); /// assert!(Natural::from(123u32) >= 122i64); /// assert!(Natural::from(123u32) < 124i64); /// assert!(Natural::from(123u32) <= 124i64); /// assert!(Natural::from(123u32) > -124i64); /// assert!(Natural::from(123u32) >= -124i64); /// assert!(Natural::from(10u32).pow(12) > 123i64); /// assert!(Natural::from(10u32).pow(12) >= 123i64); /// /// assert!(122u32 < Natural::from(123u32)); /// assert!(122u32 <= Natural::from(123u32)); /// assert!(124u32 > Natural::from(123u32)); /// assert!(124u32 >= Natural::from(123u32)); /// assert!(123u32 < Natural::from(10u32).pow(12)); /// assert!(123u32 <= Natural::from(10u32).pow(12)); /// /// assert!(122u8 < Natural::from(123u32)); /// assert!(122u8 <= Natural::from(123u32)); /// assert!(124u8 > Natural::from(123u32)); /// assert!(124u8 >= Natural::from(123u32)); /// assert!(123u8 < Natural::from(10u32).pow(12)); /// assert!(123u8 <= Natural::from(10u32).pow(12)); /// /// assert!(122u64 < Natural::from(123u32)); /// assert!(122u64 <= Natural::from(123u32)); /// assert!(124u64 > Natural::from(123u32)); /// assert!(124u64 >= Natural::from(123u32)); /// assert!(123u64 < Natural::from(10u32).pow(12)); /// assert!(123u64 <= Natural::from(10u32).pow(12)); /// /// assert!(122i64 < Natural::from(123u32)); /// assert!(122i64 <= Natural::from(123u32)); /// assert!(124i64 > Natural::from(123u32)); /// assert!(124i64 >= Natural::from(123u32)); /// assert!(-124i64 < Natural::from(123u32)); /// assert!(-124i64 <= Natural::from(123u32)); /// assert!(123i64 < Natural::from(10u32).pow(12)); /// assert!(123i64 <= Natural::from(10u32).pow(12)); /// ``` pub mod partial_cmp_primitive_int; /// Equality of [`Natural`](crate::natural::Natural)s and primitive floats. /// /// # partial_eq /// ``` /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) == 123.0f32); /// assert!(Natural::from(123u32) != -5.0f32); /// /// assert!(123.0f32 == Natural::from(123u32)); /// assert!(-5.0f32 != Natural::from(123u32)); /// ``` pub mod partial_eq_primitive_float; /// Equality of [`Natural`](crate::natural::Natural)s and primitive integers. /// /// # partial_eq /// ``` /// use malachite_nz::natural::Natural; /// /// assert!(Natural::from(123u32) == 123u32); /// assert!(Natural::from(123u32) != 5u32); /// /// assert!(Natural::from(123u32) == 123u64); /// assert!(Natural::from(123u32) != 5u64); /// /// assert!(Natural::from(123u32) == 123i64); /// assert!(Natural::from(123u32) != -123i64); /// /// assert!(123u8 == Natural::from(123u32)); /// assert!(5u8 != Natural::from(123u32)); /// /// assert!(123u64 == Natural::from(123u32)); /// assert!(5u64 != Natural::from(123u32)); /// /// assert!(123i64 == Natural::from(123u32)); /// assert!(-123i64 != Natural::from(123u32)); /// ``` pub mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/natural/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; use malachite_base::num::logic::traits::SignificantBits; macro_rules! impl_float { ($t: ident) => { impl PartialOrdAbs<$t> for Natural { /// Compares a [`Natural`] to the absolute value of a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs). fn partial_cmp_abs(&self, other: &$t) -> Option { if other.is_nan() { None } else if !other.is_finite() { Some(Less) } else if *other == 0.0 { self.partial_cmp_abs(&0u32) } else if *self == 0u32 { Some(Less) } else { let (m, e) = other.integer_mantissa_and_exponent(); let log_cmp = i64::exact_from(self.significant_bits()) .cmp(&(i64::exact_from(m.significant_bits()) + e)); Some(if log_cmp != Equal { log_cmp } else { self.cmp_normalized(&Natural::from(m)) }) } } } impl PartialOrdAbs for $t { /// Compares the absolute value of a primitive float to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Natural) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/natural/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering; use malachite_base::num::comparison::traits::PartialOrdAbs; macro_rules! impl_unsigned { ($t: ident) => { impl PartialOrdAbs<$t> for Natural { /// Compares a [`Natural`] to an unsigned primitive integer. /// /// Since both values are non-negative, this is the same as ordinary /// [`partial_cmp`](PartialOrd::partial_cmp). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { self.partial_cmp(other) } } impl PartialOrdAbs for $t { /// Compares a value of unsigned primitive integer type to a [`Natural`]. /// /// Since both values are non-negative, this is the same as ordinary /// [`partial_cmp`](PartialOrd::partial_cmp). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Natural) -> Option { self.partial_cmp(other) } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl PartialOrdAbs<$t> for Natural { /// Compares a [`Natural`] to the absolute value of a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). fn partial_cmp_abs(&self, other: &$t) -> Option { self.partial_cmp(&other.unsigned_abs()) } } impl PartialOrdAbs for $t { /// Compares the absolute value of a signed primitive integer to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Natural) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/natural/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::conversion::traits::{ExactFrom, IntegerMantissaAndExponent}; use malachite_base::num::logic::traits::SignificantBits; macro_rules! impl_float { ($t: ident) => { impl PartialOrd<$t> for Natural { /// Compares a [`Natural`] to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// See [here](super::partial_cmp_primitive_float#partial_cmp). fn partial_cmp(&self, other: &$t) -> Option { if other.is_nan() { None } else if *other < 0.0 { Some(Greater) } else if !other.is_finite() { Some(Less) } else if *other == 0.0 { self.partial_cmp(&0u32) } else if *self == 0u32 { Some(Less) } else { let (m, e) = other.integer_mantissa_and_exponent(); let log_cmp = i64::exact_from(self.significant_bits()) .cmp(&(i64::exact_from(m.significant_bits()) + e)); Some(if log_cmp != Equal { log_cmp } else { self.cmp_normalized(&Natural::from(m)) }) } } } impl PartialOrd for $t { /// Compares a primitive float to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_primitive_float#partial_cmp). #[inline] fn partial_cmp(&self, other: &Natural) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/natural/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_ceiling, limb_to_bit_count}; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use malachite_base::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::SignificantBits; macro_rules! impl_partial_ord_limb { ($u: ident) => { impl PartialOrd<$u> for Natural { /// Compares a [`Natural`] to a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). fn partial_cmp(&self, other: &$u) -> Option { match self { Natural(Small(small)) => small.partial_cmp(other), Natural(Large(_)) => Some(Greater), } } } impl PartialOrd for $u { /// Compares a [`Limb`](crate#limbs) to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Natural) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } macro_rules! impl_partial_ord_smaller_than_limb { ($u: ident) => { impl PartialOrd<$u> for Natural { /// Compares a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$u) -> Option { self.partial_cmp(&Limb::from(*other)) } } impl PartialOrd for $u { /// Compares a value of an unsigned primitive integer type that's smaller than a /// [`Limb`](crate#limbs) to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Natural) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } macro_rules! impl_partial_ord_larger_than_limb_or_usize { ($u: ident) => { impl PartialOrd for $u { /// Compares a value of an unsigned primitive integer type that's larger than a /// [`Limb`](crate#limbs) to a [`Natural`]. This implementation is general enough to /// also work for [`usize`], regardless of whether it is equal in width to /// [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Natural) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } macro_rules! impl_partial_ord_larger_than_limb { ($u: ident) => { impl_partial_ord_larger_than_limb_or_usize!($u); impl PartialOrd<$u> for Natural { /// Compares a [`Natural`] to a value of an unsigned primitive integer type that's /// larger than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$u) -> Option { let limb_count = bit_to_limb_count_ceiling(other.significant_bits()); let limb_count_cmp = usize::wrapping_from(self.limb_count()).cmp(&limb_count); if limb_count_cmp != Equal || limb_count == 0 { return Some(limb_count_cmp); } let width = Limb::WIDTH; let mut i = limb_to_bit_count(limb_count); let mut mask = $u::from(Limb::MAX) << (i - width); for limb in self.limbs().rev() { i -= width; let limb_cmp = limb.cmp(&Limb::wrapping_from((other & mask) >> i)); if limb_cmp != Equal { return Some(limb_cmp); } mask >>= width; } Some(Equal) } } }; } macro_rules! impl_signed { ($t: ident) => { impl PartialOrd<$t> for Natural { /// Compares a [`Natural`] to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). fn partial_cmp(&self, other: &$t) -> Option { if *other < 0 { Some(Greater) } else { self.partial_cmp(&other.unsigned_abs()) } } } impl PartialOrd for $t { /// Compares a signed primitive integer to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Natural) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } impl_partial_ord_smaller_than_limb!(u8); impl_partial_ord_smaller_than_limb!(u16); #[cfg(feature = "32_bit_limbs")] impl_partial_ord_limb!(u32); #[cfg(not(feature = "32_bit_limbs"))] impl_partial_ord_smaller_than_limb!(u32); #[cfg(feature = "32_bit_limbs")] impl_partial_ord_larger_than_limb!(u64); #[cfg(not(feature = "32_bit_limbs"))] impl_partial_ord_limb!(u64); impl_partial_ord_larger_than_limb!(u128); impl_partial_ord_larger_than_limb_or_usize!(usize); apply_to_signeds!(impl_signed); impl PartialOrd for Natural { /// Compares a [`Natural`] to a [`usize`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &usize) -> Option { if USIZE_IS_U32 { self.partial_cmp(&u32::wrapping_from(*other)) } else { assert_eq!(usize::WIDTH, u64::WIDTH); self.partial_cmp(&u64::wrapping_from(*other)) } } } ================================================ FILE: malachite-nz/src/natural/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::*; use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; use malachite_base::num::logic::traits::SignificantBits; macro_rules! impl_float { ($t: ident) => { impl PartialEq<$t> for Natural { /// Determines whether a [`Natural`] is equal to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). fn eq(&self, other: &$t) -> bool { if !other.is_finite() { false } else if *other == 0.0 { *self == 0u32 } else if *other < 1.0 || *self == 0u32 { false } else { let (m, e) = other.integer_mantissa_and_exponent(); if let Ok(e) = u64::try_from(e) { self.significant_bits() == m.significant_bits() + e && self.cmp_normalized(&Natural::from(m)) == Equal } else { false } } } } impl PartialEq for $t { /// Determines whether a primitive float is equal to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[inline] fn eq(&self, other: &Natural) -> bool { other == self } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-nz/src/natural/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use malachite_base::num::conversion::traits::WrappingFrom; macro_rules! impl_partial_eq_limb { ($u: ident) => { impl PartialEq<$u> for Natural { /// Determines whether a [`Natural`] is equal to a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). fn eq(&self, other: &$u) -> bool { match self { Natural(Small(x)) => *x == *other, Natural(Large(_)) => false, } } } impl PartialEq for $u { /// Determines whether a [`Limb`](crate#limbs) is equal to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Natural) -> bool { other == self } } }; } macro_rules! impl_partial_eq_smaller_than_limb { ($u: ident) => { impl PartialEq<$u> for Natural { /// Determines whether a [`Natural`] is equal to a value of an unsigned primitive /// integer type that's smaller than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[allow(clippy::cmp_owned)] #[inline] fn eq(&self, other: &$u) -> bool { *self == Limb::from(*other) } } impl PartialEq for $u { /// Determines whether a value of an unsigned primitive integer type that's smaller than /// a [`Limb`](crate#limbs) is equal to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[allow(clippy::cmp_owned)] #[inline] fn eq(&self, other: &Natural) -> bool { Limb::from(*self) == *other } } }; } macro_rules! impl_partial_eq_larger_than_limb_or_usize { ($u: ident) => { impl PartialEq for $u { /// Determines whether a value of an unsigned primitive integer type that's larger than /// a [`Limb`](crate#limbs) is equal to a [`Natural`]. /// /// This implementation is general enough to also work for [`usize`], regardless of /// whether it is equal in width to [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Natural) -> bool { other == self } } }; } macro_rules! impl_partial_eq_larger_than_limb { ($u: ident) => { impl_partial_eq_larger_than_limb_or_usize!($u); impl PartialEq<$u> for Natural { /// Determines whether a [`Natural`] is equal to a value of an unsigned primitive /// integer type that's larger than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &$u) -> bool { let mut other = *other; for limb in self.limbs() { if other == 0 || limb != Limb::wrapping_from(other) { return false; } other >>= Limb::WIDTH; } other == 0 } } }; } macro_rules! impl_signed { ($t: ident) => { impl PartialEq<$t> for Natural { /// Determines whether a [`Natural`] is equal to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). fn eq(&self, other: &$t) -> bool { *other >= 0 && *self == other.unsigned_abs() } } impl PartialEq for $t { /// Determines whether a signed primitive integer is equal to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Natural) -> bool { other == self } } }; } impl_partial_eq_smaller_than_limb!(u8); impl_partial_eq_smaller_than_limb!(u16); #[cfg(feature = "32_bit_limbs")] impl_partial_eq_limb!(u32); #[cfg(not(feature = "32_bit_limbs"))] impl_partial_eq_smaller_than_limb!(u32); #[cfg(feature = "32_bit_limbs")] impl_partial_eq_larger_than_limb!(u64); #[cfg(not(feature = "32_bit_limbs"))] impl_partial_eq_limb!(u64); impl_partial_eq_larger_than_limb!(u128); impl_partial_eq_larger_than_limb_or_usize!(usize); apply_to_signeds!(impl_signed); impl PartialEq for Natural { /// Determines whether a [`Natural`] is equal to a [`usize`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &usize) -> bool { if USIZE_IS_U32 { *self == u32::wrapping_from(*other) } else { assert_eq!(usize::WIDTH, u64::WIDTH); *self == u64::wrapping_from(*other) } } } ================================================ FILE: malachite-nz/src/natural/conversion/digits/general_digits.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_bc_get_str`, `mpn_dc_get_str`, `mpn_get_str`, `mpn_bc_set_str`, `mpn_dc_set_str`, // `mpn_set_str`, `powtab_decide`, `mpn_compute_powtab_mul`, `mpn_compute_powtab_div`, and // `mpn_compute_powtab` contributed to the GNU project by Torbjörn Granlund. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::add::{ limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, }; use crate::natural::arithmetic::div_exact::limbs_div_exact_limb_in_place; use crate::natural::arithmetic::div_mod::{ limbs_div_limb_in_place_mod, limbs_div_mod_extra_in_place, limbs_div_mod_qs_to_out_rs_to_ns, }; use crate::natural::arithmetic::mul::limb::{limbs_mul_limb_to_out, limbs_slice_mul_limb_in_place}; use crate::natural::arithmetic::mul::toom::TUNE_PROGRAM_BUILD; use crate::natural::arithmetic::mul::{limbs_mul_to_out, limbs_mul_to_out_scratch_len}; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::natural::{Natural, limb_to_bit_count}; use crate::platform::{ BASES, DoubleLimb, FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD, Limb, MP_BASES_BIG_BASE_10, MP_BASES_BIG_BASE_INVERTED_10, MP_BASES_CHARS_PER_LIMB_10, MP_BASES_NORMALIZATION_STEPS_10, }; use alloc::vec::Vec; use core::cmp::Ordering::*; use itertools::Itertools; use malachite_base::fail_on_untested_path; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, CheckedMul, DivAssignMod, DivMod, DivisibleByPowerOf2, ModPowerOf2Assign, Parity, PowerOf2, ShrRound, ShrRoundAssign, SquareAssign, XMulYToZZ, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, ExactInto, PowerOf2Digits, WrappingFrom, WrappingInto, }; use malachite_base::num::logic::traits::{LeadingZeros, SignificantBits, TrailingZeros}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::{slice_set_zero, slice_test_zero, slice_trailing_zeros}; // TODO tune const GET_STR_THRESHOLD_LIMIT: usize = 150; // TODO tune #[cfg(feature = "test_build")] pub const GET_STR_PRECOMPUTE_THRESHOLD: usize = 29; #[cfg(not(feature = "test_build"))] const GET_STR_PRECOMPUTE_THRESHOLD: usize = 29; // # Worst-case complexity // Constant time and additional memory. pub_const_test! {get_chars_per_limb(base: u64) -> usize { BASES[base as usize].0 }} // # Worst-case complexity // Constant time and additional memory. const fn get_log_base_of_2(base: u64) -> Limb { BASES[base as usize].1 } // # Worst-case complexity // Constant time and additional memory. const fn get_log_2_of_base(base: u64) -> Limb { BASES[base as usize].2 } // # Worst-case complexity // Constant time and additional memory. const fn get_big_base(base: u64) -> Limb { BASES[base as usize].3 } // # Worst-case complexity // Constant time and additional memory. const fn get_big_base_inverted(base: u64) -> Limb { BASES[base as usize].4 } // Compute the number of base-`base` digits corresponding to `limb_count` limbs, rounding down. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `DIGITS_IN_BASE_PER_LIMB` from `gmp-impl.h`, where `res` is returned. fn digits_in_base_per_limb(limb_count: usize, base: u64) -> u64 { u64::exact_from( Limb::x_mul_y_to_zz( get_log_base_of_2(base), Limb::exact_from(limb_count) << Limb::LOG_WIDTH, ) .0, ) } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `DIGITS_IN_BASEGT2_FROM_BITS` from `gmp-impl.h`, GMP 6.2.1, where `res` is // returned and `base` is not a power of 2. fn limbs_digit_count_helper(bit_count: u64, base: u64) -> u64 { u64::exact_from(Limb::x_mul_y_to_zz(get_log_base_of_2(base) + 1, Limb::exact_from(bit_count)).0) .checked_add(1) .unwrap() } // The result is either exact or one too big. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `MPN_SIZEINBASE` from `gmp-impl.h`, GMP 6.2.1, where result is returned and // base is not a power of 2. pub_crate_test! {limbs_digit_count(xs: &[Limb], base: u64) -> u64 { assert!(base > 2); assert!(base < u64::wrapping_from(BASES.len())); assert!(!base.is_power_of_two()); let size = xs.len(); if size == 0 { 1 } else { limbs_digit_count_helper( limb_to_bit_count(size) - LeadingZeros::leading_zeros(*xs.last().unwrap()), base, ) } }} macro_rules! base_10_normalization_step { ($j: expr, $buffer: ident, $i: ident, $frac: ident) => { if MP_BASES_NORMALIZATION_STEPS_10 <= $j { let digit; (digit, $frac) = Limb::x_mul_y_to_zz($frac, 10); $buffer[$i] = T::wrapping_from(digit); $i += 1; } }; } // TODO tune const RP_LEN: usize = if TUNE_PROGRAM_BUILD { GET_STR_THRESHOLD_LIMIT } else { GET_STR_PRECOMPUTE_THRESHOLD }; // Convert `xs` to digits in base `base`, and put the result in `out`. Generate `len` digits, // possibly padding with zeros to the left. If `len` is zero, generate as many characters as // required. Return the number of significant digits. Complexity is quadratic; intended for small // conversions. // // - `base` must not be a power of 2, and 2 < `base` < 256. // - `xs.len()` < `GET_STR_PRECOMPUTE_THRESHOLD`. // - `len` must be at least as large as the actual number of digits. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_bc_get_str` from `mpn/generic/get_str.c`, GMP 6.2.1. pub_crate_test! {limbs_to_digits_small_base_basecase( out: &mut [T], len: usize, xs: &[Limb], base: u64, ) -> usize { assert!(base > 2); assert!(base < 256); assert!(out.len() >= len); let mut xs_len = xs.len(); assert!(xs_len < GET_STR_PRECOMPUTE_THRESHOLD); // Allocate memory for largest possible string, given that we only get here for operands with // `xs_len` < GET_STR_PRECOMPUTE_THRESHOLD and that the smallest base is 3. 7 / 11 is an // approximation to 1 / log_2(3). const BUFFER_LEN: usize = (RP_LEN << Limb::LOG_WIDTH) * 7 / 11; let mut buffer = [T::ZERO; BUFFER_LEN]; let mut rs = [0; RP_LEN]; let mut i = BUFFER_LEN; if base == 10 { // Special case code for base 10 so that the compiler has a chance to optimize things. const DIGIT_SHIFT: u64 = Limb::WIDTH - 4; const LIMIT: usize = MP_BASES_CHARS_PER_LIMB_10 - 4usize.wrapping_sub(MP_BASES_NORMALIZATION_STEPS_10 as usize); rs[1..=xs_len].copy_from_slice(xs); while xs_len > 1 { limbs_div_mod_extra_in_place( &mut rs[..=xs_len], 1, MP_BASES_BIG_BASE_10, MP_BASES_BIG_BASE_INVERTED_10, MP_BASES_NORMALIZATION_STEPS_10, ); if rs[xs_len] == 0 { xs_len -= 1; } let mut frac = rs[0].wrapping_add(1); i -= MP_BASES_CHARS_PER_LIMB_10; // Use the fact that 10 in binary is 1010, with the lowest bit 0. After a few // `x_mul_y_to_zz`s, we will have accumulated enough low zeros to use a plain multiply. base_10_normalization_step!(0, buffer, i, frac); base_10_normalization_step!(1, buffer, i, frac); base_10_normalization_step!(2, buffer, i, frac); base_10_normalization_step!(3, buffer, i, frac); frac.shr_round_assign(4, Ceiling); for _ in 0..LIMIT { frac *= 10; let digit = frac >> DIGIT_SHIFT; buffer[i] = T::wrapping_from(digit); i += 1; frac.mod_power_of_2_assign(DIGIT_SHIFT); } i -= MP_BASES_CHARS_PER_LIMB_10; } let mut r = rs[1]; while r != 0 { let d = r.div_assign_mod(10); i -= 1; buffer[i] = T::wrapping_from(d); } } else { // not base 10 let digits_per_limb = get_chars_per_limb(base); let big_base = get_big_base(base); let big_base_inverted = get_big_base_inverted(base); let normalization_steps = LeadingZeros::leading_zeros(big_base); let limb_base = Limb::wrapping_from(base); rs[1..=xs_len].copy_from_slice(&xs[..xs_len]); while xs_len > 1 { limbs_div_mod_extra_in_place( &mut rs[..=xs_len], 1, big_base, big_base_inverted, normalization_steps, ); if rs[xs_len] == 0 { xs_len -= 1; } let mut frac = rs[0].wrapping_add(1); let old_i = i; i -= digits_per_limb; for d in &mut buffer[i..old_i] { let digit; (digit, frac) = Limb::x_mul_y_to_zz(frac, limb_base); *d = T::wrapping_from(digit); } } let mut r = rs[1]; while r != 0 { let digit = r.div_assign_mod(limb_base); i -= 1; buffer[i] = T::wrapping_from(digit); } } let nonzero_len = BUFFER_LEN - i; let zero_len = len.saturating_sub(nonzero_len); // Accounts for len == 0 case let (out_zero, out_nonzero) = out.split_at_mut(zero_len); slice_set_zero(out_zero); out_nonzero[..nonzero_len].copy_from_slice(&buffer[i..]); zero_len + nonzero_len }} // This is equivalent to `powers` from `gmp-impl.h`, GMP 6.2.1. struct PowerTableIndicesRow { start: usize, // actual power value len: usize, shift: usize, // weight of lowest limb, in limb base B digits_in_base: usize, // number of corresponding digits } #[cfg(feature = "test_build")] pub struct PowerTableRow<'a> { power: &'a [Limb], shift: usize, // weight of lowest limb, in limb base B digits_in_base: usize, // number of corresponding digits } #[cfg(not(feature = "test_build"))] struct PowerTableRow<'a> { power: &'a [Limb], shift: usize, // weight of lowest limb, in limb base B digits_in_base: usize, // number of corresponding digits } // TODO tune const DIV_1_VS_MUL_1_PERCENT: usize = 150; // TODO tune const HAVE_MPN_COMPUTE_POWTAB_MUL: bool = DIV_1_VS_MUL_1_PERCENT > 120; // TODO tune const HAVE_MPN_COMPUTE_POWTAB_DIV: bool = DIV_1_VS_MUL_1_PERCENT < 275; #[cfg(feature = "test_build")] pub enum PowerTableAlgorithm { Mul, Div, } #[cfg(not(feature = "test_build"))] enum PowerTableAlgorithm { Mul, Div, } // # Worst-case complexity // $T(n) = O(\log n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs_len`. // // This is equivalent to `powtab_decide` from `mpn/compute_powtab.c`, GMP 6.2.1. pub_test! {limbs_choose_power_table_algorithm( exptab: &mut [usize], xs_len: usize, base: u64, ) -> (usize, PowerTableAlgorithm) { let digits_per_limb = get_chars_per_limb(base); let mut number_of_powers = 0; let mut power: usize = xs_len.shr_round(1, Ceiling).0; while power != 1 { exptab[number_of_powers] = power * digits_per_limb; number_of_powers += 1; power = (power + 1) >> 1; } exptab[number_of_powers] = digits_per_limb; if HAVE_MPN_COMPUTE_POWTAB_MUL && HAVE_MPN_COMPUTE_POWTAB_DIV { let power = xs_len - 1; let n = xs_len.shr_round(1, Ceiling).0; let mut mul_cost = 1; let mut div_cost = 1; for i in (1..number_of_powers).rev() { let pow = (power >> i) + 1; if n != pow << (i - 1) { if pow.odd() { div_cost += pow; } mul_cost += if pow > 2 && pow.even() { pow << 1 } else { pow }; } else if pow.odd() { mul_cost += pow; div_cost += pow; } } div_cost = div_cost * DIV_1_VS_MUL_1_PERCENT / 100; ( number_of_powers, if mul_cost <= div_cost { PowerTableAlgorithm::Mul } else { PowerTableAlgorithm::Div }, ) } else if HAVE_MPN_COMPUTE_POWTAB_MUL { (number_of_powers, PowerTableAlgorithm::Mul) } else if HAVE_MPN_COMPUTE_POWTAB_DIV { (number_of_powers, PowerTableAlgorithm::Div) } else { panic!("no powtab function available"); } }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_str_powtab_alloc` from `gmp-impl.h`, GMP 6.2.1. const fn limbs_digits_power_table_scratch_len(xs_len: usize) -> usize { xs_len + ((Limb::WIDTH as usize) << 1) } // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_dc_get_str_itch` from `gmp-impl.h`, GMP 6.2.1. const fn limbs_to_digits_small_base_divide_and_conquer_scratch_len(xs_len: usize) -> usize { xs_len + (Limb::WIDTH as usize) } // # Worst-case complexity // $T(n) = O(2^n n \log n)$ // // $M(n) = O(2^n n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `power_len`. // // This is equivalent to `mpn_compute_powtab_mul` from `mpn/compute_powtab.c`, GMP 6.2.1. pub_test! {limbs_compute_power_table_using_mul<'a>( power_table_memory: &'a mut [Limb], base: u64, exponents: &[usize], power_len: usize, ) -> Vec> { let mut power_indices = Vec::new(); let big_base = get_big_base(base); let digits_per_limb = get_chars_per_limb(base); let mut digits_in_base = digits_per_limb; let (head, mut remainder) = power_table_memory.split_first_mut().unwrap(); *head = big_base; (remainder[1], remainder[0]) = Limb::x_mul_y_to_zz(big_base, big_base); power_indices.push(PowerTableIndicesRow { start: 0, len: 1, digits_in_base, shift: 0, }); // `a` and `n` are the start index and length of a power subslice. let (mut start, mut len, mut shift) = if remainder[0] == 0 { (2, 1, 1) } else { (1, 2, 0) }; digits_in_base <<= 1; power_indices.push(PowerTableIndicesRow { start, len, shift, digits_in_base, }); let start_index = if exponents[0] == digits_per_limb << power_len { let power; (power, remainder) = remainder[shift..].split_at_mut(len); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(len)]; limbs_square_to_out(remainder, power, &mut square_scratch); start = 3; isize::exact_from(power_len) - 2 } else { if (digits_in_base + digits_per_limb) << (power_len - 2) <= exponents[0] { // a = 3, sometimes adjusted to 4. let power; (power, remainder) = remainder[shift..].split_at_mut(len); let carry = limbs_mul_limb_to_out::(remainder, power, big_base); remainder[len] = carry; if carry != 0 { len += 1; } start = 3; digits_in_base += digits_per_limb; if remainder[1] == 0 { start = 4; len -= 1; shift += 1; } power_indices.push(PowerTableIndicesRow { start, len, shift, digits_in_base, }); let power; (power, remainder) = remainder[start - 3..].split_at_mut(7 - start); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(len)]; limbs_square_to_out(remainder, &power[..len], &mut square_scratch); start = 7; } else { remainder[2] = remainder[start - 1]; remainder[3] = remainder[start]; remainder = &mut remainder[2..]; power_indices.push(PowerTableIndicesRow { start: 3, len, digits_in_base, shift, }); let power; (power, remainder) = remainder.split_at_mut(3); let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(len)]; limbs_square_to_out(remainder, &power[..len], &mut square_scratch); start = 6; } isize::exact_from(power_len) - 3 }; if start_index >= 0 { for i in (0..=start_index).rev() { let increment = (len + 1) << 1; digits_in_base <<= 1; len <<= 1; if remainder[len - 1] == 0 { len -= 1; } shift <<= 1; let mut adjust = 0; if remainder[0] == 0 { len -= 1; shift += 1; remainder = &mut remainder[1..]; adjust += 1; } // Adjust new value if it is too small as input to the next squaring. if (digits_in_base + digits_per_limb) << i <= exponents[0] { let carry = limbs_slice_mul_limb_in_place(&mut remainder[..len], big_base); remainder[len] = carry; if carry != 0 { len += 1; } digits_in_base += digits_per_limb; if remainder[0] == 0 { len -= 1; shift += 1; adjust += 1; remainder = &mut remainder[1..]; } } power_indices.push(PowerTableIndicesRow { start: start + adjust, len, digits_in_base, shift, }); start += increment; let power; (power, remainder) = remainder.split_at_mut(increment - adjust); if i != 0 { let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(len)]; limbs_square_to_out(remainder, &power[..len], &mut square_scratch); } } for (&exponent, row) in exponents[1..usize::exact_from(start_index + 2)] .iter() .rev() .zip(power_indices[power_len - usize::exact_from(start_index + 1)..].iter_mut()) { if row.digits_in_base < exponent { let start = row.start; let end = start + row.len; let carry = limbs_slice_mul_limb_in_place(&mut power_table_memory[start..end], big_base); power_table_memory[end] = carry; if carry != 0 { row.len += 1; } assert!(row.digits_in_base + digits_per_limb == exponent); row.digits_in_base = exponent; if power_table_memory[start] == 0 { row.start += 1; row.len -= 1; row.shift += 1; } } } } let mut powers = Vec::with_capacity(power_indices.len()); let mut remainder: &mut [Limb] = power_table_memory; let mut consumed_len = 0; for row in power_indices { remainder = &mut remainder[row.start - consumed_len..]; let power; (power, remainder) = remainder.split_at_mut(row.len); consumed_len = row.start + power.len(); powers.push(PowerTableRow { power, digits_in_base: row.digits_in_base, shift: row.shift, }); } powers }} // # Worst-case complexity // $T(n) = O(2^n n \log n)$ // // $M(n) = O(2^n n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `power_len`. // // This is equivalent to `mpn_compute_powtab_div` from `mpn/compute_powtab.c`, GMP 6.2.1. pub_test! {limbs_compute_power_table_using_div<'a>( power_table_memory: &'a mut [Limb], base: u64, exponents: &[usize], power_len: usize, ) -> Vec> { let big_base = get_big_base(base); let digits_per_limb = get_chars_per_limb(base); let big_base_trailing_zeros = TrailingZeros::trailing_zeros(big_base); power_table_memory[0] = big_base; let mut powers = Vec::with_capacity(power_len + 1); let (mut power, mut remainder) = power_table_memory.split_at_mut(1); powers.push(PowerTableRow { power: &*power, digits_in_base: digits_per_limb, shift: 0, }); let mut digits_in_base = digits_per_limb; let mut len = 1; let mut shift = 0; for &exp in exponents[..power_len].iter().rev() { let two_n = len << 1; let mut square_scratch = vec![0; limbs_square_to_out_scratch_len(power.len())]; limbs_square_to_out(remainder, power, &mut square_scratch); len = two_n - 1; if remainder[len] != 0 { len += 1; } digits_in_base <<= 1; if digits_in_base != exp { limbs_div_exact_limb_in_place(&mut remainder[..len], big_base); if remainder[len - 1] == 0 { len -= 1; } digits_in_base -= digits_per_limb; } shift <<= 1; // Strip low zero limbs, but be careful to keep the result divisible by big_base. let mut adjust = 0; while remainder[adjust] == 0 && remainder[adjust + 1].divisible_by_power_of_2(big_base_trailing_zeros) { adjust += 1; } len -= adjust; shift += adjust; remainder = &mut remainder[adjust..]; let next_power; (next_power, remainder) = remainder.split_at_mut(two_n); power = &mut next_power[..len]; powers.push(if power[0] == 0 { PowerTableRow { power: &power[1..], digits_in_base, shift: shift + 1, } } else { PowerTableRow { power, shift, digits_in_base, } }); } powers }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs_len`. // // This is equivalent to `mpn_compute_powtab` from `mpn/compute_powtab.c`, GMP 6.2.1. pub_test! {limbs_compute_power_table( power_table_memory: &mut [Limb], xs_len: usize, base: u64, forced_algorithm: Option, ) -> (usize, Vec>) { let mut exponents = [0; Limb::WIDTH as usize]; let (power_len, auto_algorithm) = limbs_choose_power_table_algorithm(&mut exponents, xs_len, base); let algorithm = forced_algorithm.unwrap_or(auto_algorithm); let powers = match algorithm { PowerTableAlgorithm::Mul => { limbs_compute_power_table_using_mul(power_table_memory, base, &exponents, power_len) } PowerTableAlgorithm::Div => { limbs_compute_power_table_using_div(power_table_memory, base, &exponents, power_len) } }; (power_len, powers) }} // TODO tune const GET_STR_DC_THRESHOLD: usize = 15; // Convert `xs` to a string with a base as represented in `powers`, and put the string in `out`. // Generate `len` characters, possibly padding with zeros to the left. If `len` is zero, generate as // many characters as required. Return a pointer immediately after the last digit of the result // string. This uses divide-and-conquer and is intended for large conversions. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_get_str` from `mpn/generic/get_str.c`, GMP 6.2.1. fn limbs_to_digits_small_base_divide_and_conquer( out: &mut [T], mut len: usize, xs: &mut [Limb], base: u64, powers: &[PowerTableRow], i: usize, scratch: &mut [Limb], ) -> usize { let xs_len = xs.len(); if xs_len < GET_STR_DC_THRESHOLD { if xs_len != 0 { limbs_to_digits_small_base_basecase(out, len, xs, base) } else { fail_on_untested_path("limbs_to_digits_small_base_divide_and_conquer, xs_len == 0"); slice_set_zero(&mut out[..len]); len } } else { let power = &powers[i]; let power_len = power.power.len(); let shift = power.shift; let total_len = power_len + shift; if xs_len < total_len || xs_len == total_len && limbs_cmp_same_length(&xs[shift..], power.power) == Less { fail_on_untested_path( "limbs_to_digits_small_base_divide_and_conquer, \ xs_len < total_len || \ xs_len == total_len && \ limbs_cmp_same_length(&xs[shift..], power.power) == Less", ); limbs_to_digits_small_base_divide_and_conquer( out, len, xs, base, powers, i - 1, scratch, ) } else { let power = &powers[i]; limbs_div_mod_qs_to_out_rs_to_ns(scratch, &mut xs[shift..], power.power); let mut q_len = xs_len - total_len; if scratch[q_len] != 0 { q_len += 1; } assert!( q_len < total_len || q_len == total_len && limbs_cmp_same_length(&scratch[shift..total_len], power.power) == Less ); if len != 0 { len -= powers[i].digits_in_base; } let (scratch_lo, scratch_hi) = scratch.split_at_mut(q_len); let next_index = limbs_to_digits_small_base_divide_and_conquer( out, len, scratch_lo, base, powers, i - 1, scratch_hi, ); limbs_to_digits_small_base_divide_and_conquer( &mut out[next_index..], power.digits_in_base, &mut xs[..total_len], base, powers, i - 1, scratch, ) + next_index } } } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_to_digits_small_base_no_alg_specified( out: &mut [T], base: u64, xs: &mut [Limb], ) -> usize { limbs_to_digits_small_base(out, base, xs, None) }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_get_str` from `mpn/generic/get_str.c`, GMP 6.2.1, where `un != 0` and // base is not a power of 2. pub_test! {limbs_to_digits_small_base( out: &mut [T], base: u64, xs: &mut [Limb], forced_algorithm: Option, ) -> usize { let xs_len = xs.len(); if xs_len == 0 { 0 } else if xs_len < GET_STR_PRECOMPUTE_THRESHOLD { limbs_to_digits_small_base_basecase(out, 0, xs, base) } else { // Allocate one large block for the powers of big_base. let mut power_table_memory = vec![0; limbs_digits_power_table_scratch_len(xs_len)]; // Compute a table of powers, were the largest power is >= sqrt(U). let digits_len = digits_in_base_per_limb(xs_len, base); let len = 1 + usize::exact_from(digits_len) / get_chars_per_limb(base); let (power_len, powers) = limbs_compute_power_table(&mut power_table_memory, len, base, forced_algorithm); // Using our precomputed powers, convert our number. let mut scratch = vec![0; limbs_to_digits_small_base_divide_and_conquer_scratch_len(xs_len)]; limbs_to_digits_small_base_divide_and_conquer( out, 0, xs, base, &powers, power_len, &mut scratch, ) } }} // Returns digits in ascending order. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `digits.len()`. pub_test! {limbs_to_digits_basecase + PrimitiveUnsigned>( digits: &mut Vec, xs: &mut [Limb], base: Limb, ) { assert!(base >= 2); assert!(xs.len() > 1); assert!(T::convertible_from(base)); let mut digits_per_limb = 0; let mut big_base = 1; while let Some(next) = big_base.checked_mul(base) { big_base = next; digits_per_limb += 1; } while !slice_test_zero(xs) { let mut big_digit = limbs_div_limb_in_place_mod(xs, big_base); for _ in 0..digits_per_limb - 1 { digits.push(T::wrapping_from(big_digit.div_assign_mod(base))); } digits.push(T::wrapping_from(big_digit)); } let trailing_zeros = slice_trailing_zeros(digits); digits.truncate(digits.len() - trailing_zeros); }} // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `digits.len()`. pub_test! {to_digits_asc_naive_primitive ExactFrom<&'a Natural> + PrimitiveUnsigned>( digits: &mut Vec, x: &Natural, base: T, ) where Natural: From, { assert!(base > T::ONE); let mut remainder = x.clone(); let nat_base = Natural::from(base); while remainder != 0 { digits.push(T::exact_from(&remainder.div_assign_mod(&nat_base))); } }} // # Worst-case complexity // $T(n) = O((n^2/m) \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `x.significant_bits()`, and $m$ is // `base.significant_bits()`. pub_test! {to_digits_asc_naive(digits: &mut Vec, x: &Natural, base: &Natural) { assert!(*base > 1); let mut remainder = x.clone(); while remainder != 0 { digits.push(remainder.div_assign_mod(base)); } }} // TODO tune const TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD: u64 = 50; const SQRT_MAX_LIMB: Limb = (1 << (Limb::WIDTH >> 1)) - 1; // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bits`. fn compute_powers_for_to_digits(base: &Natural, bits: u64) -> Vec { if bits / base.significant_bits() < TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { return Vec::new(); } let limit = (bits + 3).shr_round(1, Ceiling).0; let mut powers = Vec::new(); let mut power = base.clone(); loop { powers.push(power.clone()); power.square_assign(); if power.significant_bits() >= limit { break; } } powers.push(power); powers } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. fn to_digits_asc_divide_and_conquer_limb< T: ConvertibleFrom + for<'a> ExactFrom<&'a Natural> + PrimitiveUnsigned, >( digits: &mut Vec, mut x: Natural, base: Limb, powers: &[Natural], power_index: usize, ) where Limb: Digits, Natural: From, { let bits = x.significant_bits(); if bits / base.significant_bits() < TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { if base <= SQRT_MAX_LIMB { match x { Natural(Small(x)) => { digits.extend_from_slice(&x.to_digits_asc(&T::wrapping_from(base))); } Natural(Large(ref mut xs)) => limbs_to_digits_basecase(digits, xs, base), } } else { to_digits_asc_naive_primitive(digits, &x, T::exact_from(base)); } } else { let (q, r) = x.div_mod(&powers[power_index]); let start_len = digits.len(); to_digits_asc_divide_and_conquer_limb(digits, r, base, powers, power_index - 1); if q != 0 { for _ in digits.len() - start_len..1 << power_index { digits.push(T::ZERO); } to_digits_asc_divide_and_conquer_limb(digits, q, base, powers, power_index - 1); } } } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. fn to_digits_asc_divide_and_conquer( digits: &mut Vec, x: &Natural, base: &Natural, powers: &[Natural], power_index: usize, ) { let bits = x.significant_bits(); if bits / base.significant_bits() < TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { to_digits_asc_naive(digits, x, base); } else { let (q, r) = x.div_mod(&powers[power_index]); let start_len = digits.len(); to_digits_asc_divide_and_conquer(digits, &r, base, powers, power_index - 1); if q != 0 { for _ in digits.len() - start_len..1 << power_index { digits.push(Natural::ZERO); } to_digits_asc_divide_and_conquer(digits, &q, base, powers, power_index - 1); } } } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. pub_test! {to_digits_asc_limb< T: ConvertibleFrom + for<'a> ExactFrom<&'a Natural> + PrimitiveUnsigned, >( x: &Natural, base: Limb, ) -> Vec where Limb: Digits, Natural: From + PowerOf2Digits, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_asc(log_base) } else { let t_base = T::exact_from(base); match x { Natural(Small(x)) => x.to_digits_asc(&t_base), Natural(Large(xs)) => { if base < 256 { let mut digits = vec![ T::ZERO; usize::exact_from(limbs_digit_count(xs, u64::wrapping_from(base))) ]; let mut xs = xs.clone(); let len = limbs_to_digits_small_base( &mut digits, u64::wrapping_from(base), &mut xs, None, ); digits.truncate(len); digits.reverse(); digits } else { let powers = compute_powers_for_to_digits( &From::::from(base), x.significant_bits(), ); let mut digits = Vec::new(); to_digits_asc_divide_and_conquer_limb( &mut digits, x.clone(), base, &powers, powers.len().saturating_sub(1), ); digits } } } } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. pub_test! {to_digits_desc_limb< T: ConvertibleFrom + for<'a> ExactFrom<&'a Natural> + PrimitiveUnsigned, >( x: &Natural, base: Limb, ) -> Vec where Limb: Digits, Natural: From + PowerOf2Digits, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_desc(log_base) } else { let t_base = T::exact_from(base); match x { Natural(Small(x)) => x.to_digits_desc(&t_base), Natural(Large(xs)) => { if base < 256 { let mut digits = vec![ T::ZERO; usize::exact_from(limbs_digit_count(xs, u64::wrapping_from(base))) ]; let mut xs = xs.clone(); let len = limbs_to_digits_small_base( &mut digits, u64::wrapping_from(base), &mut xs, None, ); digits.truncate(len); digits } else { let powers = compute_powers_for_to_digits( &From::::from(base), x.significant_bits(), ); let mut digits = Vec::new(); to_digits_asc_divide_and_conquer_limb( &mut digits, x.clone(), base, &powers, powers.len().saturating_sub(1), ); digits.reverse(); digits } } } } }} // optimized for large base // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. pub_test! {to_digits_asc_large(x: &Natural, base: &Natural) -> Vec { if *x == 0 { Vec::new() } else if x < base { vec![x.clone()] } else if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_asc(log_base) } else { match x { Natural(Large(_)) => { let powers = compute_powers_for_to_digits(base, x.significant_bits()); let mut digits = Vec::new(); to_digits_asc_divide_and_conquer( &mut digits, x, base, &powers, powers.len().saturating_sub(1), ); digits } _ => panic!("x must be large"), } } }} // optimized for large base // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. pub_test! {to_digits_desc_large(x: &Natural, base: &Natural) -> Vec { if *x == 0 { Vec::new() } else if x < base { vec![x.clone()] } else if let Some(log_base) = base.checked_log_base_2() { x.to_power_of_2_digits_desc(log_base) } else { match x { Natural(Large(_)) => { let powers = compute_powers_for_to_digits(base, x.significant_bits()); let mut digits = Vec::new(); to_digits_asc_divide_and_conquer( &mut digits, x, base, &powers, powers.len().saturating_sub(1), ); digits.reverse(); digits } _ => panic!("x must be large"), } } }} // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {from_digits_desc_naive_primitive( xs: &[T], base: T ) -> Option where Natural: From, { assert!(base > T::ONE); let mut n = Natural::ZERO; let n_base = Natural::from(base); for &x in xs { if x >= base { return None; } n *= &n_base; n += Natural::from(x); } Some(n) }} // # Worst-case complexity // $T(n) = O(m^2 n \log (m n) \log\log (m n))$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, $n$ is `base.significant_bits()`, and $m$ is // `xs.len()`. pub_test! {from_digits_desc_naive(xs: &[Natural], base: &Natural) -> Option { assert!(*base > 1); let mut n = Natural::ZERO; for x in xs { if x >= base { return None; } n *= base; n += x; } Some(n) }} // Compute the number of limbs corresponding to `digit_count` base-`base` digits, rounding up. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `LIMBS_PER_DIGIT_IN_BASE` from `gmp-impl.h`, where `res` is returned and // `base` is not a power of 2. pub_test! {limbs_per_digit_in_base(digit_count: usize, base: u64) -> u64 { (u64::exact_from(Limb::x_mul_y_to_zz(get_log_2_of_base(base), Limb::exact_from(digit_count)).0) >> (Limb::LOG_WIDTH - 3)) + 2 }} // The input digits are in descending order. // // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_bc_set_str` from `mpn/generic/set_str.c`, GMP 6.2.1, where `base` is // not a power of 2. pub_test! {limbs_from_digits_small_base_basecase( out: &mut [Limb], xs: &[T], base: u64, ) -> Option where Limb: WrappingFrom, { let xs_len = xs.len(); assert!(base > 2); assert!(base < 256); assert_ne!(xs_len, 0); let big_base = get_big_base(base); let digits_per_limb = get_chars_per_limb(base); let limb_base: Limb = base.wrapping_into(); let t_base = T::wrapping_from(base); let mut size = 0; let mut i = 0; for chunk in xs[..xs_len - 1].chunks_exact(digits_per_limb) { let (&chunk_head, chunk_tail) = chunk.split_first().unwrap(); if chunk_head >= t_base { return None; } let mut y = Limb::wrapping_from(chunk_head); if limb_base == 10 { // This is a common case. Help the compiler avoid multiplication. for &x in chunk_tail { if x >= t_base { return None; } let x = Limb::wrapping_from(x); assert!(x < 10); y = y * 10 + x; } } else { for &x in chunk_tail { if x >= t_base { return None; } let x = Limb::wrapping_from(x); assert!(x < limb_base); y = y * limb_base + x; } } if size == 0 { if y != 0 { out[0] = y; size = 1; } } else { let (out_last, out_init) = out[..=size].split_last_mut().unwrap(); let mut carry = limbs_slice_mul_limb_in_place(out_init, big_base); if limbs_slice_add_limb_in_place(out_init, y) { carry += 1; } if carry != 0 { *out_last = carry; size += 1; } } i += digits_per_limb; } let mut big_base = limb_base; let (&remainder_head, remainder_tail) = xs[i..].split_first().unwrap(); if remainder_head >= t_base { return None; } let mut y = Limb::wrapping_from(remainder_head); if limb_base == 10 { // This is a common case. Help the compiler avoid multiplication. for &x in remainder_tail { if x >= t_base { return None; } let x = Limb::wrapping_from(x); assert!(x < 10); y = y * 10 + x; big_base *= 10; } } else { for &x in remainder_tail { if x >= t_base { return None; } let x = Limb::wrapping_from(x); assert!(x < limb_base); y = y * limb_base + x; big_base *= limb_base; } } if size == 0 { if y != 0 { out[0] = y; size = 1; } } else { let (out_last, out_init) = out[..=size].split_last_mut().unwrap(); let mut carry = limbs_slice_mul_limb_in_place(out_init, big_base); if limbs_slice_add_limb_in_place(out_init, y) { carry += 1; } if carry != 0 { *out_last = carry; size += 1; } } Some(size) }} // TODO tune // must be greater than get_chars_per_limb(3), which is 40 for 64-bit build const SET_STR_DC_THRESHOLD: usize = 7100; // The input digits are in descending order. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_dc_set_str` from `mpn/generic/set_str.c`, GMP 6.2.1, where `base` is // not a power of 2. pub_test! {limbs_from_digits_small_base_divide_and_conquer( out: &mut [Limb], xs: &[T], base: u64, powers: &[PowerTableRow], i: usize, scratch: &mut [Limb], ) -> Option where Limb: WrappingFrom, { if i == 0 { return limbs_from_digits_small_base_basecase(out, xs, base); } let xs_len = xs.len(); let power = &powers[i]; let len_lo = power.digits_in_base; if xs_len <= len_lo { return if xs_len < SET_STR_DC_THRESHOLD { fail_on_untested_path( "limbs_from_digits_small_base_divide_and_conquer, xs_len < SET_STR_DC_THRESHOLD", ); limbs_from_digits_small_base_basecase(out, xs, base) } else { limbs_from_digits_small_base_divide_and_conquer(out, xs, base, powers, i - 1, scratch) }; } let len_hi = xs_len - len_lo; let (xs_lo, xs_hi) = xs.split_at(len_hi); assert!(len_lo >= len_hi); let out_len_hi = if len_hi < SET_STR_DC_THRESHOLD { limbs_from_digits_small_base_basecase(scratch, xs_lo, base) } else { limbs_from_digits_small_base_divide_and_conquer(scratch, xs_lo, base, powers, i - 1, out) }?; let shift = power.shift; let adjusted_power_len = power.power.len() + shift; if out_len_hi == 0 { // Zero +1 limb here, to avoid reading an allocated but uninitialized limb in // limbs_slice_add_limb_in_place below. slice_set_zero(&mut out[..=adjusted_power_len]); } else { let (out_lo, out_hi) = out.split_at_mut(shift); let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(power.power.len(), out_len_hi)]; limbs_mul_to_out(out_hi, power.power, &scratch[..out_len_hi], &mut mul_scratch); slice_set_zero(out_lo); } let out_len_lo = if len_lo < SET_STR_DC_THRESHOLD { limbs_from_digits_small_base_basecase(scratch, xs_hi, base) } else { let (scratch_lo, scratch_hi) = scratch.split_at_mut(adjusted_power_len + 1); limbs_from_digits_small_base_divide_and_conquer( scratch_lo, xs_hi, base, powers, i - 1, scratch_hi, ) }?; if out_len_lo != 0 { let (out_lo, out_hi) = out.split_at_mut(out_len_lo); if limbs_slice_add_same_length_in_place_left(out_lo, &scratch[..out_len_lo]) { assert!(!limbs_slice_add_limb_in_place(out_hi, 1)); } } let mut n = out_len_hi + adjusted_power_len; if out[n - 1] == 0 { n -= 1; } Some(n) }} // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpn_dc_set_str_itch` from `gmp-impl.h`, GMP 6.2.1. const fn limbs_from_digits_small_base_divide_and_conquer_scratch_len(xs_len: usize) -> usize { xs_len + (Limb::WIDTH as usize) } // must be greater than get_chars_per_limb(3), which is 40 for 64-bit build const SET_STR_PRECOMPUTE_THRESHOLD: usize = 7100; // The input digits are in descending order. // // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_set_str` from `mpn/generic/set_str.c`, GMP 6.2.1, where `base` is not // a power of 2. pub_test! {limbs_from_digits_small_base( out: &mut [Limb], xs: &[T], base: u64, ) -> Option where Limb: WrappingFrom, { let xs_len = xs.len(); if xs_len < SET_STR_PRECOMPUTE_THRESHOLD { limbs_from_digits_small_base_basecase(out, xs, base) } else { let chars_per_limb = get_chars_per_limb(base); let len = xs_len / chars_per_limb + 1; // Allocate one large block for the powers of big_base. let mut power_table_memory = vec![0; limbs_digits_power_table_scratch_len(len)]; let (power_len, powers) = limbs_compute_power_table(&mut power_table_memory, len, base, None); let mut scratch = vec![0; limbs_from_digits_small_base_divide_and_conquer_scratch_len(len)]; limbs_from_digits_small_base_divide_and_conquer( out, xs, base, &powers, power_len, &mut scratch, ) } }} // # Worst-case complexity // $T(n) = O(n^2)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {from_digits_desc_basecase(xs: &[T], base: Limb) -> Option where Limb: WrappingFrom, { assert!(base >= 2); let t_base = T::try_from(base).ok()?; let mut digits_per_limb = 0; let mut big_base = 1; while let Some(next) = big_base.checked_mul(base) { big_base = next; digits_per_limb += 1; } let big_big_base = Natural::from(big_base); let mut x = Natural::ZERO; for chunk in xs.rchunks(digits_per_limb).rev() { for &y in chunk { if y >= t_base { return None; } } let big_digit = Limb::from_digits_desc(&base, chunk.iter().map(|&x| Limb::wrapping_from(x)))?; x *= &big_big_base; x += Natural::from(big_digit); } Some(x) }} // # Worst-case complexity // $T(n) = O(n \log n \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `digits`. fn compute_powers_for_from_digits(base: &Natural, digits: usize) -> Vec { if u64::exact_from(digits) * base.significant_bits() < FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { return Vec::new(); } let limit = digits.shr_round(1u64, Ceiling).0; let mut powers = Vec::new(); let mut power = base.clone(); let mut p = 1; loop { powers.push(power.clone()); if p >= limit { break; } power.square_assign(); p <<= 1; } powers } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn from_digits_desc_divide_and_conquer_limb( xs: &[T], base: Limb, powers: &[Natural], power_index: usize, ) -> Option where Limb: WrappingFrom, Natural: From, { let xs_len = xs.len(); let b = u64::exact_from(xs_len) * base.significant_bits(); if power_index == 0 || b < FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { if base <= SQRT_MAX_LIMB { from_digits_desc_basecase(xs, base) } else { from_digits_desc_naive_primitive(xs, T::exact_from(base)) } } else { let p = usize::power_of_2(power_index.exact_into()); if xs_len <= p { from_digits_desc_divide_and_conquer_limb(xs, base, powers, power_index - 1) } else { let (xs_hi, xs_lo) = xs.split_at(xs_len - p); let out_hi = from_digits_desc_divide_and_conquer_limb(xs_hi, base, powers, power_index - 1)?; let out_lo = from_digits_desc_divide_and_conquer_limb(xs_lo, base, powers, power_index - 1)?; Some(out_hi * &powers[power_index] + out_lo) } } } // # Worst-case complexity // $T(n, m) = O(nm (\log (nm))^2 \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.len()`, and $m$ is // `base.significant_bits()`. pub_test! {from_digits_desc_divide_and_conquer( xs: &[Natural], base: &Natural, powers: &[Natural], power_index: usize, ) -> Option { let xs_len = xs.len(); if power_index == 0 || u64::exact_from(xs_len) * base.significant_bits() < FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD { from_digits_desc_naive(xs, base) } else { let p = usize::power_of_2(u64::exact_from(power_index)); if xs_len <= p { from_digits_desc_divide_and_conquer(xs, base, powers, power_index - 1) } else { let (xs_hi, xs_lo) = xs.split_at(xs_len - p); let out_hi = from_digits_desc_divide_and_conquer(xs_hi, base, powers, power_index - 1)?; let out_lo = from_digits_desc_divide_and_conquer(xs_lo, base, powers, power_index - 1)?; Some(out_hi * &powers[power_index] + out_lo) } } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_test! {from_digits_asc_limb, T: TryFrom + PrimitiveUnsigned>( xs: I, base: Limb, ) -> Option where Limb: ExactFrom + WrappingFrom, Natural: From + PowerOf2Digits, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_asc(log_base, xs) } else { let mut xs = xs.collect_vec(); T::try_from(base).ok()?; if xs.is_empty() { return Some(Natural::ZERO); } xs.reverse(); if base < 256 { let u64_base = base.exact_into(); let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), u64_base))]; let len = limbs_from_digits_small_base(&mut out, &xs, u64_base)?; out.truncate(len); Some(Natural::from_owned_limbs_asc(out)) } else { let t_base = T::wrapping_from(base); let powers = compute_powers_for_from_digits(&Natural::from(t_base), xs.len()); from_digits_desc_divide_and_conquer_limb( &xs, base, &powers, powers.len().saturating_sub(1), ) } } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. #[allow(clippy::trait_duplication_in_bounds)] fn from_digits_asc_limb_from_natural< I: Iterator, T: TryFrom + for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( xs: I, base: Limb, ) -> Option where Limb: WrappingFrom, Natural: From, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_asc(log_base, xs) } else { let large_xs = xs; let mut xs = Vec::new(); T::try_from(base).ok()?; for x in large_xs { xs.push(T::try_from(&x).ok()?); } if xs.is_empty() { return Some(Natural::ZERO); } xs.reverse(); if base < 256 { let u64_base = base.exact_into(); let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), u64_base))]; let len = limbs_from_digits_small_base(&mut out, &xs, u64_base)?; out.truncate(len); Some(Natural::from_owned_limbs_asc(out)) } else { let t_base = T::wrapping_from(base); let powers = compute_powers_for_from_digits(&Natural::from(t_base), xs.len()); from_digits_desc_divide_and_conquer_limb( &xs, base, &powers, powers.len().saturating_sub(1), ) } } } // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. pub_test! {from_digits_desc_limb, T: PrimitiveUnsigned>( xs: I, base: Limb, ) -> Option where Limb: WrappingFrom, Natural: From + PowerOf2Digits, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_desc(log_base, xs) } else { let xs = xs.collect_vec(); T::try_from(base).ok()?; if xs.is_empty() { return Some(Natural::ZERO); } if base < 256 { let u64_base = base.exact_into(); let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), u64_base))]; let len = limbs_from_digits_small_base(&mut out, &xs, u64_base)?; out.truncate(len); Some(Natural::from_owned_limbs_asc(out)) } else { let t_base = T::wrapping_from(base); let powers = compute_powers_for_from_digits(&Natural::from(t_base), xs.len()); from_digits_desc_divide_and_conquer_limb( &xs, base, &powers, powers.len().saturating_sub(1), ) } } }} // # Worst-case complexity // $T(n) = O(n (\log n)^2 \log\log n)$ // // $M(n) = O(n \log n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. #[allow(clippy::trait_duplication_in_bounds)] fn from_digits_desc_limb_from_natural< I: Iterator, T: TryFrom + for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( xs: I, base: Limb, ) -> Option where Limb: WrappingFrom, Natural: From, { assert!(base >= 2); if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_desc(log_base, xs) } else { let large_xs = xs; let mut xs = Vec::new(); T::try_from(base).ok()?; for x in large_xs { xs.push(T::try_from(&x).ok()?); } if xs.is_empty() { return Some(Natural::ZERO); } if base < 256 { let u64_base = base.exact_into(); let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), u64_base))]; let len = limbs_from_digits_small_base(&mut out, &xs, u64_base)?; out.truncate(len); Some(Natural::from_owned_limbs_asc(out)) } else { let t_base = T::wrapping_from(base); let powers = compute_powers_for_from_digits(&Natural::from(t_base), xs.len()); from_digits_desc_divide_and_conquer_limb( &xs, base, &powers, powers.len().saturating_sub(1), ) } } } // # Worst-case complexity // $T(n, m) = O(nm (\log (nm))^2 \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is // `base.significant_bits()`. // // optimized for large base pub_test! {from_digits_asc_large>( xs: I, base: &Natural, ) -> Option { if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_asc(log_base, xs) } else { let mut xs = xs.collect_vec(); xs.reverse(); let powers = compute_powers_for_from_digits(base, xs.len()); from_digits_desc_divide_and_conquer(&xs, base, &powers, powers.len().saturating_sub(1)) } }} // # Worst-case complexity // $T(n, m) = O(nm (\log (nm))^2 \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `xs.count()`, and $m$ is // `base.significant_bits()`. // // optimized for large base pub_test! {from_digits_desc_large>( xs: I, base: &Natural, ) -> Option { if let Some(log_base) = base.checked_log_base_2() { Natural::from_power_of_2_digits_desc(log_base, xs) } else { let xs = xs.collect_vec(); let powers = compute_powers_for_from_digits(base, xs.len()); from_digits_desc_divide_and_conquer(&xs, base, &powers, powers.len().saturating_sub(1)) } }} impl Digits for Natural { /// Returns a [`Vec`] containing the digits of a [`Natural`] in ascending order (least- to /// most-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it ends with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or $d_{k-1} \neq /// 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#to_digits_asc). #[inline] fn to_digits_asc(&self, base: &u8) -> Vec { match self { Self(Small(x)) => x.to_digits_asc(base), Self(Large(xs)) => { if let Some(log_base) = base.checked_log_base_2() { self.to_power_of_2_digits_asc(log_base) } else { let mut digits = vec![0; usize::exact_from(limbs_digit_count(xs, u64::from(*base)))]; let mut xs = xs.clone(); let len = limbs_to_digits_small_base(&mut digits, u64::from(*base), &mut xs, None); digits.truncate(len); digits.reverse(); digits } } } } /// Returns a [`Vec`] containing the digits of a [`Natural`] in descending order (most- to /// least-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it begins with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or $d_{k-1} \neq /// 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_{k-i-1} = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#to_digits_desc). #[inline] fn to_digits_desc(&self, base: &u8) -> Vec { match self { Self(Small(x)) => x.to_digits_desc(base), Self(Large(xs)) => { if let Some(log_base) = base.checked_log_base_2() { self.to_power_of_2_digits_desc(log_base) } else { let mut digits = vec![0; usize::exact_from(limbs_digit_count(xs, u64::from(*base)))]; let mut xs = xs.clone(); let len = limbs_to_digits_small_base(&mut digits, u64::from(*base), &mut xs, None); digits.truncate(len); digits } } } } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in ascending order (least- to most-significant). The function returns /// `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^id_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#from_digits_asc). #[inline] fn from_digits_asc>(base: &u8, digits: I) -> Option { if let Some(log_base) = base.checked_log_base_2() { Self::from_power_of_2_digits_asc(log_base, digits) } else { let base = u64::from(*base); let mut xs = digits.collect_vec(); if xs.is_empty() { return Some(Self::ZERO); } xs.reverse(); let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), base))]; let _ = limbs_from_digits_small_base(&mut out, &xs, base)?; Some(Self::from_owned_limbs_asc(out)) } } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in descending order (most- to least-significant). The function returns /// `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^{k-i-1}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#from_digits_desc). #[inline] fn from_digits_desc>(base: &u8, digits: I) -> Option { if let Some(log_base) = base.checked_log_base_2() { Self::from_power_of_2_digits_desc(log_base, digits) } else { let base = u64::from(*base); let xs = digits.collect_vec(); if xs.is_empty() { return Some(Self::ZERO); } let mut out = vec![0; usize::exact_from(limbs_per_digit_in_base(xs.len(), base))]; let _ = limbs_from_digits_small_base(&mut out, &xs, base)?; Some(Self::from_owned_limbs_asc(out)) } } } fn to_digits_asc_unsigned< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned + for<'a> WrappingFrom<&'a Natural>, >( x: &Natural, base: &T, ) -> Vec where Limb: TryFrom + Digits, Natural: From + PowerOf2Digits, { if let Ok(base) = Limb::try_from(*base) { to_digits_asc_limb(x, base) } else { to_digits_asc_large(x, &Natural::from(*base)) .into_iter() .map(|n| T::wrapping_from(&n)) .collect() } } fn to_digits_desc_unsigned< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned + for<'a> WrappingFrom<&'a Natural>, >( x: &Natural, base: &T, ) -> Vec where Limb: TryFrom + Digits, Natural: From + PowerOf2Digits, { if let Ok(base) = Limb::try_from(*base) { to_digits_desc_limb(x, base) } else { to_digits_desc_large(x, &Natural::from(*base)) .into_iter() .map(|n| T::wrapping_from(&n)) .collect() } } fn from_digits_asc_unsigned + PrimitiveUnsigned, I: Iterator>( base: &T, digits: I, ) -> Option where Limb: TryFrom + WrappingFrom, Natural: From + PowerOf2Digits, { if let Ok(base) = Limb::try_from(*base) { from_digits_asc_limb(digits, base) } else { from_digits_asc_large(digits.map(Natural::from), &Natural::from(*base)) } } fn from_digits_desc_unsigned + PrimitiveUnsigned, I: Iterator>( base: &T, digits: I, ) -> Option where Limb: TryFrom + WrappingFrom, Natural: From + PowerOf2Digits, { if let Ok(base) = Limb::try_from(*base) { from_digits_desc_limb(digits, base) } else { from_digits_desc_large(digits.map(Natural::from), &Natural::from(*base)) } } macro_rules! digits_unsigned { ($d: ident) => { impl Digits<$d> for Natural { /// Returns a [`Vec`] containing the digits of a [`Natural`] in ascending order (least- /// to most-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it ends with a nonzero /// digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or /// $d_{k-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#to_digits_asc). #[inline] fn to_digits_asc(&self, base: &$d) -> Vec<$d> { to_digits_asc_unsigned(self, base) } /// Returns a [`Vec`] containing the digits of a [`Natural`] in descending order (most- /// to least-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it begins with a nonzero /// digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or /// $d_{k-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_{k-i-1} = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#to_digits_desc). #[inline] fn to_digits_desc(&self, base: &$d) -> Vec<$d> { to_digits_desc_unsigned(self, base) } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in ascending order (least- to most-significant). The function /// returns `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^id_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#from_digits_asc). #[inline] fn from_digits_asc>(base: &$d, digits: I) -> Option { from_digits_asc_unsigned(base, digits) } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in descending order (most- to least-significant). The function /// returns `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^{k-i-1}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// See [here](super::general_digits#to_digits_desc). #[inline] fn from_digits_desc>(base: &$d, digits: I) -> Option { from_digits_desc_unsigned(base, digits) } } }; } digits_unsigned!(u16); digits_unsigned!(u32); digits_unsigned!(u64); digits_unsigned!(u128); digits_unsigned!(usize); impl Digits for Natural { /// Returns a [`Vec`] containing the digits of a [`Natural`] in ascending order (least- to /// most-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it ends with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or $d_{k-1} \neq /// 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO /// .to_digits_asc(&Natural::from(6u32)) /// .to_debug_string(), /// "[]" /// ); /// assert_eq!( /// Natural::TWO /// .to_digits_asc(&Natural::from(6u32)) /// .to_debug_string(), /// "[2]" /// ); /// assert_eq!( /// Natural::from(123456u32) /// .to_digits_asc(&Natural::from(3u32)) /// .to_debug_string(), /// "[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2]" /// ); /// ``` fn to_digits_asc(&self, base: &Self) -> Vec { match base { Self(Small(b)) => self.to_digits_asc(b).into_iter().map(Self::from).collect(), _ => to_digits_asc_large(self, base), } } /// Returns a [`Vec`] containing the digits of a [`Natural`] in descending order (most- to /// least-significant). /// /// If the [`Natural`] is 0, the [`Vec`] is empty; otherwise, it begins with a nonzero digit. /// /// $f(x, b) = (d_i)_ {i=0}^{k-1}$, where $0 \leq d_i < b$ for all $i$, $k=0$ or $d_{k-1} \neq /// 0$, and /// /// $$ /// \sum_{i=0}^{k-1}b^i d_{k-i-1} = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::ZERO /// .to_digits_desc(&Natural::from(6u32)) /// .to_debug_string(), /// "[]" /// ); /// assert_eq!( /// Natural::TWO /// .to_digits_desc(&Natural::from(6u32)) /// .to_debug_string(), /// "[2]" /// ); /// assert_eq!( /// Natural::from(123456u32) /// .to_digits_desc(&Natural::from(3u32)) /// .to_debug_string(), /// "[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0]" /// ); /// ``` fn to_digits_desc(&self, base: &Self) -> Vec { match base { Self(Small(b)) => self.to_digits_desc(b).into_iter().map(Self::from).collect(), _ => to_digits_desc_large(self, base), } } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in ascending order (least- to most-significant). The function returns /// `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^id_i. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(nm (\log (nm))^2 \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `digits.count()`, and $m$ is /// `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_digits_asc( /// &Natural::from(64u32), /// vec_from_str::("[0, 0, 0]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_digits_asc( /// &Natural::from(3u32), /// vec_from_str::("[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2]") /// .unwrap() /// .into_iter() /// ) /// .to_debug_string(), /// "Some(123456)" /// ); /// assert_eq!( /// Natural::from_digits_asc( /// &Natural::from(8u32), /// vec_from_str::("[3, 7, 1]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_digits_asc( /// &Natural::from(8u32), /// vec_from_str::("[1, 10, 3]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "None" /// ); /// ``` #[inline] fn from_digits_asc>(base: &Self, digits: I) -> Option { match base { Self(Small(b)) => from_digits_asc_limb_from_natural::<_, Limb>(digits, *b), _ => from_digits_asc_large(digits, base), } } /// Converts an iterator of digits into a [`Natural`]. /// /// The input digits are in descending order (most- to least-significant). The function returns /// `None` if any of the digits are greater than or equal to the base. /// /// $$ /// f((d_i)_ {i=0}^{k-1}, b) = \sum_{i=0}^{k-1}b^{k-i-1}d_i. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(nm (\log (nm))^2 \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `digits.count()`, and $m$ is /// `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_digits_desc( /// &Natural::from(64u32), /// vec_from_str::("[0, 0, 0]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_digits_desc( /// &Natural::from(3u32), /// vec_from_str::("[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0]") /// .unwrap() /// .into_iter() /// ) /// .to_debug_string(), /// "Some(123456)" /// ); /// assert_eq!( /// Natural::from_digits_desc( /// &Natural::from(8u32), /// vec_from_str::("[1, 7, 3]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_digits_desc( /// &Natural::from(8u32), /// vec_from_str::("[3, 10, 1]").unwrap().into_iter() /// ) /// .to_debug_string(), /// "None" /// ); /// ``` #[inline] fn from_digits_desc>(base: &Self, digits: I) -> Option { match base { Self(Small(b)) => from_digits_desc_limb_from_natural::<_, Limb>(digits, *b), _ => from_digits_desc_large(digits, base), } } } ================================================ FILE: malachite-nz/src/natural/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`Digits`](malachite_base::num::conversion::traits::Digits), a trait for /// extracting digits from [`Natural`](crate::natural::Natural)s and constructing /// [`Natural`](crate::natural::Natural)s from digits. /// /// # to_digits_asc /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::Digits; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::ZERO.to_digits_asc(&6u64).is_empty()); /// assert_eq!(Natural::TWO.to_digits_asc(&6u32), &[2]); /// assert_eq!( /// Natural::from(123456u32).to_digits_asc(&3u16), /// &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2] /// ); /// ``` /// /// # to_digits_desc /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::Digits; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::ZERO.to_digits_desc(&6u64).is_empty()); /// assert_eq!(Natural::TWO.to_digits_desc(&6u32), &[2]); /// assert_eq!( /// Natural::from(123456u32).to_digits_desc(&3u16), /// &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0] /// ); /// ``` /// /// # from_digits_asc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_digits_asc(&64u64, [0, 0, 0].iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_digits_asc(&3u64, [0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2].iter().cloned()) /// .to_debug_string(), /// "Some(123456)" /// ); /// assert_eq!( /// Natural::from_digits_asc(&8u16, [3, 7, 1].iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_digits_asc(&8u16, [3, 10, 1].iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` /// /// # from_digits_desc /// ``` /// use malachite_base::num::conversion::traits::Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_digits_desc(&64u64, [0, 0, 0].iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_digits_desc(&3u64, [2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0].iter().cloned()) /// .to_debug_string(), /// "Some(123456)" /// ); /// assert_eq!( /// Natural::from_digits_desc(&8u16, [1, 7, 3].iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_digits_desc(&8u16, [3, 10, 1].iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` pub mod general_digits; /// An implementation of /// [`PowerOf2DigitIterable`](malachite_base::num::conversion::traits::PowerOf2DigitIterable), a /// trait for iterating over a [`Natural`](crate::natural::Natural)'s base-$2^k$ digits. /// /// # power_of_2_digits /// ``` /// use itertools::Itertools; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::PowerOf2DigitIterable; /// use malachite_nz::natural::Natural; /// /// let n = Natural::ZERO; /// assert!(PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .next() /// .is_none()); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2).collect_vec(), /// vec![3, 2, 2, 1] /// ); /// /// let n = Natural::ZERO; /// assert!(PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .next_back() /// .is_none()); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .rev() /// .collect_vec(), /// vec![1, 2, 2, 3] /// ); /// ``` pub mod power_of_2_digit_iterable; /// Implementations of [`PowerOf2Digits`](malachite_base::num::conversion::traits::PowerOf2Digits), /// a trait for extracting base-$2^k$ digits from [`Natural`](crate::natural::Natural)s and /// constructing [`Natural`](crate::natural::Natural)s from such digits. /// /// # to_power_of_2_digits_asc /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::ZERO, 6), /// Vec::::new() /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::TWO, 6), /// vec![2] /// ); /// /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::from(123u32), 3), /// vec![3, 7, 1] /// ); /// ``` /// /// # to_power_of_2_digits_desc /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::ZERO, 6), /// Vec::::new() /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::TWO, 6), /// vec![2] /// ); /// /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::from(123u32), 3), /// vec![1, 7, 3] /// ); /// ``` /// /// # from_power_of_2_digits_asc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_power_of_2_digits_asc(6, [0u64, 0, 0].iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_asc(6, [2u64, 0].iter().cloned()).to_debug_string(), /// "Some(2)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_asc(3, [3u16, 7, 1].iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_asc(3, [100u8].iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` /// /// # from_power_of_2_digits_desc /// ``` /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from_power_of_2_digits_desc(6, [0u64, 0, 0].iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_desc(6, [0u64, 2].iter().cloned()).to_debug_string(), /// "Some(2)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_desc(3, [1u16, 7, 3].iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// assert_eq!( /// Natural::from_power_of_2_digits_desc(3, [100u8].iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` pub mod power_of_2_digits; ================================================ FILE: malachite-nz/src/natural/conversion/digits/power_of_2_digit_iterable.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::logic::bit_block_access::limbs_slice_get_bits; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use core::cmp::{Ordering::*, min}; use core::marker::PhantomData; use core::slice::Chunks; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, DivRound, FloorLogBase2, ModPowerOf2, PowerOf2, SaturatingSubAssign, ShrRound, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::digits::power_of_2_digit_iterable::*; use malachite_base::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, }; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::*; #[doc(hidden)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct FitsInLimbIterator<'a, T>(FILIterator<'a, T>); #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct FILIterator<'a, T> { limbs: &'a [Limb], log_base: u64, remaining: usize, limb_i: usize, limb_j: usize, // This index initially points to the least-significant digit, and is incremented by next(). i: u64, // This index initially points to the most-significant nonzero digit, and is decremented by // next_back(). j: u64, mask: Limb, phantom: PhantomData<*const T>, } impl Iterator for FILIterator<'_, T> { type Item = T; fn next(&mut self) -> Option { if self.remaining != 0 { let digit = T::wrapping_from((self.limbs[self.limb_i] >> self.i) & self.mask); self.i += self.log_base; if self.i == Limb::WIDTH { self.i = 0; self.limb_i += 1; } self.remaining -= 1; Some(digit) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for FILIterator<'_, T> { fn next_back(&mut self) -> Option { if self.remaining != 0 { let digit = T::wrapping_from((self.limbs[self.limb_j] >> self.j) & self.mask); if self.j == 0 { self.j = Limb::WIDTH - self.log_base; self.limb_j.saturating_sub_assign(1); } else { self.j -= self.log_base; } self.remaining -= 1; Some(digit) } else { None } } } impl ExactSizeIterator for FILIterator<'_, T> {} impl PowerOf2DigitIterator for FILIterator<'_, T> { fn get_digit(&self, index: u64) -> T { let log_log_base = self.log_base.floor_log_base_2(); let log_ratio = Limb::LOG_WIDTH - log_log_base; let limb_index = usize::exact_from(index >> log_ratio); let digit_index = index.mod_power_of_2(log_ratio); if limb_index < self.limbs.len() { T::wrapping_from((self.limbs[limb_index] >> (digit_index << log_log_base)) & self.mask) } else { T::ZERO } } } #[doc(hidden)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SizeOfLimbIterator<'a, T>(SOLIterator<'a, T>); #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct SOLIterator<'a, T> { limbs: &'a [Limb], remaining: usize, // This index initially points to the least-significant digit, and is incremented by next(). i: usize, // This index initially points to the most-significant nonzero digit, and is decremented by // next_back(). j: usize, phantom: PhantomData<*const T>, } impl Iterator for SOLIterator<'_, T> { type Item = T; fn next(&mut self) -> Option { if self.remaining != 0 { let digit = T::wrapping_from(self.limbs[self.i]); self.i += 1; self.remaining -= 1; Some(digit) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for SOLIterator<'_, T> { fn next_back(&mut self) -> Option { if self.remaining != 0 { let digit = T::wrapping_from(self.limbs[self.j]); self.j.saturating_sub_assign(1); self.remaining -= 1; Some(digit) } else { None } } } impl ExactSizeIterator for SOLIterator<'_, T> {} impl SOLIterator<'_, T> { fn get_digit(&self, index: u64) -> T { let index = usize::exact_from(index); if index < self.limbs.len() { T::wrapping_from(self.limbs[index]) } else { T::ZERO } } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct MultipleOfLimbIterator<'a, T>(MOLIterator<'a, T>); #[derive(Clone, Debug)] struct MOLIterator<'a, T> { log_ratio: u64, limbs: &'a [Limb], chunks: Chunks<'a, Limb>, phantom: PhantomData<*const T>, } impl Iterator for MOLIterator<'_, T> { type Item = T; fn next(&mut self) -> Option { self.chunks.next().map(T::from_other_type_slice) } #[inline] fn size_hint(&self) -> (usize, Option) { self.chunks.size_hint() } } impl DoubleEndedIterator for MOLIterator<'_, T> { fn next_back(&mut self) -> Option { self.chunks.next_back().map(T::from_other_type_slice) } } impl ExactSizeIterator for MOLIterator<'_, T> {} impl PowerOf2DigitIterator for MOLIterator<'_, T> { fn get_digit(&self, index: u64) -> T { let start_index = usize::exact_from(index << self.log_ratio); if start_index >= self.limbs.len() { T::ZERO } else { let end_index = min( self.limbs.len(), start_index + usize::power_of_2(self.log_ratio), ); T::from_other_type_slice(&self.limbs[start_index..end_index]) } } } #[doc(hidden)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct IrregularIterator<'a, T>(IIterator<'a, T>); #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct IIterator<'a, T> { limbs: &'a [Limb], log_base: u64, remaining: usize, // This index initially points to the least-significant digit, and is incremented by next(). i: u64, // This index initially points to the most-significant nonzero digit, and is decremented by // next_back(). j: u64, phantom: PhantomData<*const T>, } impl Iterator for IIterator<'_, T> { type Item = T; fn next(&mut self) -> Option { if self.remaining != 0 { let digit = self.get_digit(self.i); self.i += 1; self.remaining -= 1; Some(digit) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for IIterator<'_, T> { fn next_back(&mut self) -> Option { if self.remaining != 0 { let digit = self.get_digit(self.j); self.j.saturating_sub_assign(1); self.remaining -= 1; Some(digit) } else { None } } } impl ExactSizeIterator for IIterator<'_, T> {} impl IIterator<'_, T> { fn get_digit(&self, index: u64) -> T { let start = index * self.log_base; let limb_start = bit_to_limb_count_floor(start); let len = self.limbs.len(); let mut result = T::ZERO; if limb_start >= len { return result; } let mut result_index = 0; let mut limb_index = start & Limb::WIDTH_MASK; for &limb in &self.limbs[limb_start..] { let remaining_result_bits = self.log_base - result_index; let remaining_limb_bits = Limb::WIDTH - limb_index; if remaining_limb_bits <= remaining_result_bits { result |= T::wrapping_from(limb >> limb_index) << result_index; result_index += remaining_limb_bits; limb_index = 0; } else { result |= T::wrapping_from((limb >> limb_index).mod_power_of_2(remaining_result_bits)) << result_index; break; } } result } } /// A double-ended iterator over the base-$2^k$ $digits of a [`Natural`]. /// /// The base-2 logarithm of the base is specified. Each digit has primitive integer type, and /// `log_base` must be no larger than the width of that type. The forward order is ascending /// (least-significant first). The iterator does not iterate over the implicit leading zero digits. /// /// This struct also supports retrieving digits by index. This functionality is completely /// independent of the iterator's state. Indexing the implicit leading zero digits is allowed. #[derive(Clone, Debug)] pub enum NaturalPowerOf2DigitPrimitiveIterator<'a, T: PrimitiveUnsigned> { Small(PrimitivePowerOf2DigitIterator), FitsInLimb(FitsInLimbIterator<'a, T>), SizeOfLimb(SizeOfLimbIterator<'a, T>), MultipleOfLimb(MultipleOfLimbIterator<'a, T>), Irregular(IrregularIterator<'a, T>), } impl Iterator for NaturalPowerOf2DigitPrimitiveIterator<'_, T> { type Item = T; /// Iterates through the base-$2^k$ digits of a [`Natural`] in ascending order /// (least-significant first). /// /// # Worst-case complexity /// Constant time and additional memory. fn next(&mut self) -> Option { match self { Self::Small(xs) => xs.next(), Self::FitsInLimb(xs) => xs.0.next(), Self::SizeOfLimb(xs) => xs.0.next(), Self::MultipleOfLimb(xs) => xs.0.next(), Self::Irregular(xs) => xs.0.next(), } } fn size_hint(&self) -> (usize, Option) { match self { Self::Small(xs) => xs.size_hint(), Self::FitsInLimb(xs) => xs.0.size_hint(), Self::SizeOfLimb(xs) => xs.0.size_hint(), Self::MultipleOfLimb(xs) => xs.0.size_hint(), Self::Irregular(xs) => xs.0.size_hint(), } } } impl DoubleEndedIterator for NaturalPowerOf2DigitPrimitiveIterator<'_, T> { /// Iterates through the base-$2^k$ digits of a [`Natural`] in descending order /// (most-significant first). /// /// # Worst-case complexity /// Constant time and additional memory. fn next_back(&mut self) -> Option { match self { Self::Small(xs) => xs.next_back(), Self::FitsInLimb(xs) => xs.0.next_back(), Self::SizeOfLimb(xs) => xs.0.next_back(), Self::MultipleOfLimb(xs) => xs.0.next_back(), Self::Irregular(xs) => xs.0.next_back(), } } } impl ExactSizeIterator for NaturalPowerOf2DigitPrimitiveIterator<'_, T> {} impl PowerOf2DigitIterator for NaturalPowerOf2DigitPrimitiveIterator<'_, T> { /// Retrieves the base-$2^k$ digits of a [`Natural`] by index. /// /// $f(x, k, i) = d_i$, where $0 \leq d_i < 2^k$ for all $i$ and /// $$ /// \sum_{i=0}^\infty2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::{ /// PowerOf2DigitIterable, PowerOf2DigitIterator, /// }; /// use malachite_nz::natural::Natural; /// /// let n = Natural::ZERO; /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2).get_digit(0), /// 0 /// ); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// let digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); /// assert_eq!(digits.get_digit(0), 3); /// assert_eq!(digits.get_digit(1), 2); /// assert_eq!(digits.get_digit(2), 2); /// assert_eq!(digits.get_digit(3), 1); /// assert_eq!(digits.get_digit(4), 0); /// assert_eq!(digits.get_digit(100), 0); /// ``` fn get_digit(&self, index: u64) -> T { match self { Self::Small(xs) => xs.get_digit(index), Self::FitsInLimb(xs) => xs.0.get_digit(index), Self::SizeOfLimb(xs) => xs.0.get_digit(index), Self::MultipleOfLimb(xs) => xs.0.get_digit(index), Self::Irregular(xs) => xs.0.get_digit(index), } } } fn fits_in_limb_iterator( xs: &[Limb], log_base: u64, ) -> FitsInLimbIterator<'_, T> { let significant_bits = limbs_significant_bits(xs); let log_log_base = log_base.floor_log_base_2(); let significant_digits = significant_bits.shr_round(log_log_base, Ceiling).0; FitsInLimbIterator(FILIterator { limbs: xs, log_base, remaining: usize::exact_from(significant_digits), limb_i: 0, limb_j: xs.len() - 1, i: 0, j: (significant_digits - 1).mod_power_of_2(Limb::LOG_WIDTH - log_log_base) << log_log_base, mask: Limb::low_mask(log_base), phantom: PhantomData, }) } const fn size_of_limb_iterator(xs: &[Limb]) -> SizeOfLimbIterator<'_, T> { SizeOfLimbIterator(SOLIterator { limbs: xs, remaining: xs.len(), i: 0, j: xs.len() - 1, phantom: PhantomData, }) } fn multiple_of_limb_iterator( xs: &[Limb], log_base: u64, ) -> MultipleOfLimbIterator<'_, T> { let log_log_base = log_base.floor_log_base_2(); let log_ratio = log_log_base - Limb::LOG_WIDTH; MultipleOfLimbIterator(MOLIterator { log_ratio, limbs: xs, chunks: xs.chunks(usize::power_of_2(log_ratio)), phantom: PhantomData, }) } fn irregular_iterator( xs: &[Limb], log_base: u64, ) -> IrregularIterator<'_, T> { let significant_digits = limbs_significant_bits(xs).div_round(log_base, Ceiling).0; IrregularIterator(IIterator { limbs: xs, log_base, remaining: usize::exact_from(significant_digits), i: 0, j: significant_digits - 1, phantom: PhantomData, }) } fn power_of_2_digits( x: &Natural, log_base: u64, ) -> NaturalPowerOf2DigitPrimitiveIterator<'_, T> where Limb: PowerOf2DigitIterable>, { assert_ne!(log_base, 0); assert!( log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); match x { Natural(Small(small)) => NaturalPowerOf2DigitPrimitiveIterator::Small( PowerOf2DigitIterable::::power_of_2_digits(*small, log_base), ), Natural(Large(limbs)) => { if let Some(log_log_base) = log_base.checked_log_base_2() { match log_log_base.cmp(&Limb::LOG_WIDTH) { Equal => NaturalPowerOf2DigitPrimitiveIterator::SizeOfLimb( size_of_limb_iterator(limbs), ), Less => NaturalPowerOf2DigitPrimitiveIterator::FitsInLimb( fits_in_limb_iterator(limbs, log_base), ), Greater => NaturalPowerOf2DigitPrimitiveIterator::MultipleOfLimb( multiple_of_limb_iterator(limbs, log_base), ), } } else { NaturalPowerOf2DigitPrimitiveIterator::Irregular(irregular_iterator( limbs, log_base, )) } } } } macro_rules! iterables { ( $t: ident ) => { impl<'a> PowerOf2DigitIterable<$t> for &'a Natural { type PowerOf2DigitIterator = NaturalPowerOf2DigitPrimitiveIterator<'a, $t>; /// Returns a double-ended iterator over the base-$2^k$ digits of a [`Natural`]. /// /// The base-2 logarithm of the base is specified. Each digit has primitive integer /// type, and `log_base` must be no larger than the width of that type. The forward /// order is ascending, so that less significant digits appear first. There are no /// trailing zero digits going forward, or leading zero digits going backward. /// /// If it's necessary to get a [`Vec`] of all the digits, consider using /// [`to_power_of_2_digits_asc`](malachite_base::num::conversion::traits::PowerOf2Digits::to_power_of_2_digits_asc) /// or /// [`to_power_of_2_digits_desc`](malachite_base::num::conversion::traits::PowerOf2Digits::to_power_of_2_digits_desc) /// instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::power_of_2_digit_iterable#power_of_2_digits). #[inline] fn power_of_2_digits( self, log_base: u64, ) -> NaturalPowerOf2DigitPrimitiveIterator<'a, $t> { power_of_2_digits(self, log_base) } } }; } apply_to_unsigneds!(iterables); #[doc(hidden)] #[derive(Clone, Debug)] pub struct NaturalMultipleOfLimbIterator<'a>(NMOLIterator<'a>); #[derive(Clone, Debug)] struct NMOLIterator<'a> { log_ratio: u64, limbs: &'a [Limb], chunks: Chunks<'a, Limb>, } impl Iterator for NMOLIterator<'_> { type Item = Natural; fn next(&mut self) -> Option { self.chunks.next().map(Natural::from_limbs_asc) } #[inline] fn size_hint(&self) -> (usize, Option) { self.chunks.size_hint() } } impl DoubleEndedIterator for NMOLIterator<'_> { fn next_back(&mut self) -> Option { self.chunks.next_back().map(Natural::from_limbs_asc) } } impl ExactSizeIterator for NMOLIterator<'_> {} impl PowerOf2DigitIterator for NMOLIterator<'_> { fn get_digit(&self, index: u64) -> Natural { let start_index = usize::exact_from(index << self.log_ratio); if start_index >= self.limbs.len() { Natural::ZERO } else { let end_index = min( self.limbs.len(), start_index + usize::power_of_2(self.log_ratio), ); Natural::from_limbs_asc(&self.limbs[start_index..end_index]) } } } #[doc(hidden)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct NaturalIrregularIterator<'a>(NIIterator<'a>); #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct NIIterator<'a> { limbs: &'a [Limb], log_base: u64, remaining: usize, // This index initially points to the least-significant digit, and is incremented by next(). i: u64, // This index initially points to the most-significant nonzero digit, and is decremented by // next_back(). j: u64, } impl Iterator for NIIterator<'_> { type Item = Natural; fn next(&mut self) -> Option { if self.remaining != 0 { let digit = self.get_digit(self.i); self.i += 1; self.remaining -= 1; Some(digit) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for NIIterator<'_> { fn next_back(&mut self) -> Option { if self.remaining != 0 { let digit = self.get_digit(self.j); self.j.saturating_sub_assign(1); self.remaining -= 1; Some(digit) } else { None } } } impl ExactSizeIterator for NIIterator<'_> {} impl NIIterator<'_> { fn get_digit(&self, index: u64) -> Natural { let start_index = index.checked_mul(self.log_base).unwrap(); Natural::from_owned_limbs_asc(limbs_slice_get_bits( self.limbs, start_index, start_index + self.log_base, )) } } /// A double-ended iterator over the base-$2^k$ digits of a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The type of each digit is [`Natural`]. The /// forward order is ascending (least-significant first). The iterator does not iterate over the /// implicit leading zero digits. /// /// This struct also supports retrieving digits by index. This functionality is completely /// independent of the iterator's state. Indexing the implicit leading zero digits is allowed. #[derive(Clone, Debug)] pub enum NaturalPowerOf2DigitIterator<'a> { Small(PrimitivePowerOf2DigitIterator), SmallerThanLimb(NaturalPowerOf2DigitPrimitiveIterator<'a, Limb>), MultipleOfLimb(NaturalMultipleOfLimbIterator<'a>), Irregular(NaturalIrregularIterator<'a>), } impl Iterator for NaturalPowerOf2DigitIterator<'_> { type Item = Natural; /// Iterates through the base-$2^k$ digits of a [`Natural`] in ascending order /// (least-significant first). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `log_base`. fn next(&mut self) -> Option { match self { Self::Small(xs) => xs.next().map(Natural::from), Self::SmallerThanLimb(xs) => xs.next().map(Natural::from), Self::MultipleOfLimb(xs) => xs.0.next(), Self::Irregular(xs) => xs.0.next(), } } fn size_hint(&self) -> (usize, Option) { match self { Self::Small(xs) => xs.size_hint(), Self::SmallerThanLimb(xs) => xs.size_hint(), Self::MultipleOfLimb(xs) => xs.0.size_hint(), Self::Irregular(xs) => xs.0.size_hint(), } } } impl DoubleEndedIterator for NaturalPowerOf2DigitIterator<'_> { /// Iterate through the base-$2^k$ digits of a [`Natural`] in descending order (most-significant /// first). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `log_base`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::PowerOf2DigitIterable; /// use malachite_nz::natural::Natural; /// /// let n = Natural::ZERO; /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2).next(), /// None /// ); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); /// assert_eq!(digits.next_back(), Some(Natural::from(1u32))); /// assert_eq!(digits.next_back(), Some(Natural::from(2u32))); /// assert_eq!(digits.next_back(), Some(Natural::from(2u32))); /// assert_eq!(digits.next_back(), Some(Natural::from(3u32))); /// assert_eq!(digits.next_back(), None); /// ``` fn next_back(&mut self) -> Option { match self { Self::Small(xs) => xs.next_back().map(Natural::from), Self::SmallerThanLimb(xs) => xs.next_back().map(Natural::from), Self::MultipleOfLimb(xs) => xs.0.next_back(), Self::Irregular(xs) => xs.0.next_back(), } } } impl ExactSizeIterator for NaturalPowerOf2DigitIterator<'_> {} impl PowerOf2DigitIterator for NaturalPowerOf2DigitIterator<'_> { /// Retrieves the base-$2^k$ digits of a [`Natural`] by index. /// /// $f(x, k, i) = d_i$, where $0 \leq d_i < 2^k$ for all $i$ and /// $$ /// \sum_{i=0}^\infty2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `log_base`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::{ /// PowerOf2DigitIterable, PowerOf2DigitIterator, /// }; /// use malachite_nz::natural::Natural; /// /// let n = Natural::ZERO; /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2).get_digit(0), /// 0 /// ); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// let digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); /// assert_eq!(digits.get_digit(0), 3); /// assert_eq!(digits.get_digit(1), 2); /// assert_eq!(digits.get_digit(2), 2); /// assert_eq!(digits.get_digit(3), 1); /// assert_eq!(digits.get_digit(4), 0); /// assert_eq!(digits.get_digit(100), 0); /// ``` fn get_digit(&self, index: u64) -> Natural { match self { Self::Small(xs) => Natural::from(xs.get_digit(index)), Self::SmallerThanLimb(xs) => Natural::from(xs.get_digit(index)), Self::MultipleOfLimb(xs) => xs.0.get_digit(index), Self::Irregular(xs) => xs.0.get_digit(index), } } } fn multiple_of_limb_fn(xs: &[Limb], log_base: u64) -> NaturalMultipleOfLimbIterator<'_> { let log_ratio = log_base.floor_log_base_2() - Limb::LOG_WIDTH; NaturalMultipleOfLimbIterator(NMOLIterator { log_ratio, limbs: xs, chunks: xs.chunks(usize::power_of_2(log_ratio)), }) } fn irregular_fn(xs: &[Limb], log_base: u64) -> NaturalIrregularIterator<'_> { let significant_digits = limbs_significant_bits(xs).div_round(log_base, Ceiling).0; NaturalIrregularIterator(NIIterator { limbs: xs, log_base, remaining: usize::exact_from(significant_digits), i: 0, j: significant_digits - 1, }) } impl<'a> PowerOf2DigitIterable for &'a Natural { type PowerOf2DigitIterator = NaturalPowerOf2DigitIterator<'a>; /// Returns a double-ended iterator over the base-$2^k$ digits of a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The type of each digit is [`Natural`]. The /// forward order is ascending, so that less significant digits appear first. There are no /// trailing zero digits going forward, or leading zero digits going backward. /// /// If it's necessary to get a [`Vec`] of all the digits, consider using /// [`to_power_of_2_digits_asc`](malachite_base::num::conversion::traits::PowerOf2Digits::to_power_of_2_digits_asc) /// or /// [`to_power_of_2_digits_desc`](malachite_base::num::conversion::traits::PowerOf2Digits::to_power_of_2_digits_desc) /// instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::PowerOf2DigitIterable; /// use malachite_nz::natural::Natural; /// /// let n = Natural::ZERO; /// assert!(PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .next() /// .is_none()); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2).collect_vec(), /// vec![ /// Natural::from(3u32), /// Natural::from(2u32), /// Natural::from(2u32), /// Natural::from(1u32) /// ] /// ); /// /// let n = Natural::ZERO; /// assert!(PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .next_back() /// .is_none()); /// /// // 107 = 1223_4 /// let n = Natural::from(107u32); /// assert_eq!( /// PowerOf2DigitIterable::::power_of_2_digits(&n, 2) /// .rev() /// .collect_vec(), /// vec![ /// Natural::from(1u32), /// Natural::from(2u32), /// Natural::from(2u32), /// Natural::from(3u32) /// ] /// ); /// ``` fn power_of_2_digits(self, log_base: u64) -> NaturalPowerOf2DigitIterator<'a> { assert_ne!(log_base, 0); match self { Natural(Small(small)) => NaturalPowerOf2DigitIterator::Small(PowerOf2DigitIterable::< Limb, >::power_of_2_digits( *small, min(log_base, Limb::WIDTH), )), Natural(Large(limbs)) => { if let Some(log_log_base) = log_base.checked_log_base_2() { if log_log_base <= Limb::LOG_WIDTH { NaturalPowerOf2DigitIterator::SmallerThanLimb( PowerOf2DigitIterable::::power_of_2_digits(self, log_base), ) } else { NaturalPowerOf2DigitIterator::MultipleOfLimb(multiple_of_limb_fn( limbs, log_base, )) } } else { NaturalPowerOf2DigitIterator::Irregular(irregular_fn(limbs, log_base)) } } } } } ================================================ FILE: malachite-nz/src/natural/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::{Ordering::*, min}; use itertools::Itertools; use malachite_base::num::arithmetic::traits::{CheckedLogBase2, DivRound, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, PowerOf2Digits, WrappingFrom}; use malachite_base::num::iterators::iterator_to_bit_chunks; use malachite_base::num::logic::traits::{BitBlockAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::slice_trailing_zeros; impl Natural { pub_test! {to_power_of_2_digits_asc_naive< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( &self, log_base: u64, ) -> Vec { assert_ne!(log_base, 0); assert!(log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); let digit_len = self .significant_bits() .div_round(log_base, Ceiling).0; let mut digits = Vec::with_capacity(usize::exact_from(digit_len)); let mut previous_index = 0; for _ in 0..digit_len { let index = previous_index + log_base; digits.push(T::exact_from(&self.get_bits(previous_index, index))); previous_index = index; } digits }} pub_test! {from_power_of_2_digits_asc_naive>( log_base: u64, digits: I, ) -> Option where Natural: From, { assert_ne!(log_base, 0); assert!(log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); let mut n = Natural::ZERO; let mut previous_index = 0; for digit in digits { if digit.significant_bits() > log_base { return None; } let index = previous_index + log_base; n.assign_bits(previous_index, index, &Natural::from(digit)); previous_index = index; } Some(n) }} } fn to_power_of_2_digits_asc_nz(x: &Natural, log_base: u64) -> Vec where Limb: PowerOf2Digits, { assert_ne!(log_base, 0); assert!( log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); let limbs = match x { Natural(Small(small)) => { return PowerOf2Digits::::to_power_of_2_digits_asc( small, min(log_base, Limb::WIDTH), ); } Natural(Large(limbs)) => limbs, }; let mut digits = iterator_to_bit_chunks(limbs.iter().copied(), Limb::WIDTH, log_base) .map(Option::unwrap) .collect_vec(); digits.truncate(digits.len() - slice_trailing_zeros(&digits)); digits } fn to_power_of_2_digits_desc_nz(x: &Natural, log_base: u64) -> Vec where Natural: PowerOf2Digits, { let mut digits = x.to_power_of_2_digits_asc(log_base); digits.reverse(); digits } fn from_power_of_2_digits_asc_nz>( log_base: u64, digits: I, ) -> Option where Limb: WrappingFrom, { assert_ne!(log_base, 0); assert!( log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); let mut limbs = Vec::new(); for digit in iterator_to_bit_chunks(digits, log_base, Limb::WIDTH) { limbs.push(digit?); } Some(Natural::from_owned_limbs_asc(limbs)) } fn from_power_of_2_digits_desc_nz>( log_base: u64, digits: I, ) -> Option where Limb: WrappingFrom, { assert_ne!(log_base, 0); assert!( log_base <= T::WIDTH, "type {:?} is too small for a digit of width {}", T::NAME, log_base ); let digits = digits.collect_vec(); let mut limbs = Vec::new(); for digit in iterator_to_bit_chunks(digits.iter().copied().rev(), log_base, Limb::WIDTH) { limbs.push(digit?); } Some(Natural::from_owned_limbs_asc(limbs)) } macro_rules! power_of_2_digits_unsigned { ( $t: ident ) => { impl PowerOf2Digits<$t> for Natural { /// Returns a [`Vec`] containing the base-$2^k$ digits of a [`Natural`] in ascending /// order: least- to most-significant. /// /// The base-2 logarithm of the base is specified. Each digit has primitive integer /// type, and `log_base` must be no larger than the width of that type. If the /// [`Natural`] is 0, the [`Vec`] is empty; otherwise, it ends with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ or /// $d_{n-1} \neq 0$, and /// /// $$ /// \sum_{i=0}^{n-1}2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the digit type, or if `log_base` /// is zero. /// /// # Examples /// See [here](super::power_of_2_digits#to_power_of_2_digits_asc). #[inline] fn to_power_of_2_digits_asc(&self, log_base: u64) -> Vec<$t> { to_power_of_2_digits_asc_nz(self, log_base) } /// Returns a [`Vec`] containing the base-$2^k$ digits of a [`Natural`] in descending /// order: most- to least-significant. /// /// The base-2 logarithm of the base is specified. Each digit has primitive integer /// type, and `log_base` must be no larger than the width of that type. If the /// [`Natural`] is 0, the [`Vec`] is empty; otherwise, it begins with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ or $d_0 /// \neq 0$, and /// /// $$ /// \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is greater than the width of the digit type, or if `log_base` /// is zero. /// /// # Examples /// See [here](super::power_of_2_digits#to_power_of_2_digits_desc). #[inline] fn to_power_of_2_digits_desc(&self, log_base: u64) -> Vec<$t> { to_power_of_2_digits_desc_nz(self, log_base) } /// Converts an iterator of base-$2^k$ digits into a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The input digits are in ascending /// order: least- to most-significant. Each digit has primitive integer type, and /// `log_base` must be no larger than the width of that type. /// /// If some digit is greater than $2^k$, `None` is returned. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{ki}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `log_base` is zero or greater than the width of the digit type. /// /// # Examples /// See [here](super::power_of_2_digits#from_power_of_2_digits_asc). #[inline] fn from_power_of_2_digits_asc>( log_base: u64, digits: I, ) -> Option { from_power_of_2_digits_asc_nz(log_base, digits) } /// Converts an iterator of base-$2^k$ digits into a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The input digits are in descending /// order: most- to least-significant. Each digit has primitive integer type, and /// `log_base` must be no larger than the width of that type. /// /// If some digit is greater than $2^k$, `None` is returned. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `digits.count()`. /// /// # Panics /// Panics if `log_base` is zero or greater than the width of the digit type. /// /// # Examples /// See [here](super::power_of_2_digits#from_power_of_2_digits_desc). #[inline] fn from_power_of_2_digits_desc>( log_base: u64, digits: I, ) -> Option { from_power_of_2_digits_desc_nz(log_base, digits) } } }; } apply_to_unsigneds!(power_of_2_digits_unsigned); impl PowerOf2Digits for Natural { /// Returns a [`Vec`] containing the base-$2^k$ digits of a [`Natural`] in ascending order: /// least- to most-significant. /// /// The base-2 logarithm of the base is specified. The type of each digit is [`Natural`]. If the /// [`Natural`] is 0, the [`Vec`] is empty; otherwise, it ends with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ or $d_{n-1} \neq /// 0$, and /// /// $$ /// \sum_{i=0}^{n-1}2^{ki}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::ZERO, 6) /// .to_debug_string(), /// "[]" /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::TWO, 6).to_debug_string(), /// "[2]" /// ); /// /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::from(123u32), 3) /// .to_debug_string(), /// "[3, 7, 1]" /// ); /// ``` fn to_power_of_2_digits_asc(&self, log_base: u64) -> Vec { assert_ne!(log_base, 0); if log_base <= Limb::WIDTH || self.limb_count() < 2 { return PowerOf2Digits::::to_power_of_2_digits_asc( self, min(log_base, Limb::WIDTH), ) .iter() .copied() .map(Self::from) .collect(); } let limbs = match self { Self(Large(limbs)) => limbs, _ => unreachable!(), }; let mut digits = Vec::new(); if let Some(log_log_base) = log_base.checked_log_base_2() { assert!(log_log_base > Limb::LOG_WIDTH); digits.extend( limbs .chunks(usize::power_of_2(log_log_base - Limb::LOG_WIDTH)) .map(Self::from_limbs_asc), ); } else { let mut digit = Self::ZERO; let mut remaining_digit_bits = log_base; for &limb in limbs { let mut limb = limb; let mut remaining_limb_bits = Limb::WIDTH; while remaining_limb_bits != 0 { let digit_index = log_base - remaining_digit_bits; if remaining_limb_bits <= remaining_digit_bits { digit.assign_bits( digit_index, digit_index + remaining_limb_bits, &Self::from(limb), ); remaining_digit_bits -= remaining_limb_bits; remaining_limb_bits = 0; } else { digit.assign_bits(digit_index, log_base, &Self::from(limb)); limb >>= remaining_digit_bits; remaining_limb_bits -= remaining_digit_bits; remaining_digit_bits = 0; } if remaining_digit_bits == 0 { digits.push(digit); digit = Self::ZERO; remaining_digit_bits = log_base; } } } if digit != 0 { digits.push(digit); } } digits.truncate(digits.len() - slice_trailing_zeros(&digits)); digits } /// Returns a [`Vec`] containing the base-$2^k$ digits of a [`Natural`] in descending order: /// most- to least-significant. /// /// The base-2 logarithm of the base is specified. The type of each digit is [`Natural`]. If the /// [`Natural`] is 0, the [`Vec`] is empty; otherwise, it begins with a nonzero digit. /// /// $f(x, k) = (d_i)_ {i=0}^{n-1}$, where $0 \leq d_i < 2^k$ for all $i$, $n=0$ or $d_0 \neq 0$, /// and /// /// $$ /// \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i = x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::ZERO, 6) /// .to_debug_string(), /// "[]" /// ); /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::TWO, 6) /// .to_debug_string(), /// "[2]" /// ); /// /// // 123_10 = 173_8 /// assert_eq!( /// PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::from(123u32), 3) /// .to_debug_string(), /// "[1, 7, 3]" /// ); /// ``` fn to_power_of_2_digits_desc(&self, log_base: u64) -> Vec { let mut digits = self.to_power_of_2_digits_asc(log_base); digits.reverse(); digits } /// Converts an iterator of base-$2^k$ digits into a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The input digits are in ascending order: /// least- to most-significant. The type of each digit is [`Natural`]. /// /// If some digit is greater than $2^k$, `None` is returned. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{ki}d_i. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(nm)$ /// /// $M(n, m) = O(nm)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `digits.count()`, and $m$ is `log_base`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// let digits = &[Natural::ZERO, Natural::ZERO, Natural::ZERO]; /// assert_eq!( /// Natural::from_power_of_2_digits_asc(6, digits.iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// /// let digits = &[Natural::TWO, Natural::ZERO]; /// assert_eq!( /// Natural::from_power_of_2_digits_asc(6, digits.iter().cloned()).to_debug_string(), /// "Some(2)" /// ); /// /// let digits = &[Natural::from(3u32), Natural::from(7u32), Natural::ONE]; /// assert_eq!( /// Natural::from_power_of_2_digits_asc(3, digits.iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// /// let digits = &[Natural::from(100u32)]; /// assert_eq!( /// Natural::from_power_of_2_digits_asc(3, digits.iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` fn from_power_of_2_digits_asc>( log_base: u64, digits: I, ) -> Option { assert_ne!(log_base, 0); if let Some(log_log_base) = log_base.checked_log_base_2() { let mut limbs = Vec::new(); match log_log_base.cmp(&Limb::LOG_WIDTH) { Equal => { for digit in digits { if digit.significant_bits() > log_base { return None; } limbs.push(Limb::wrapping_from(&digit)); } } Less => { for chunk in &digits.chunks(usize::wrapping_from(Limb::WIDTH >> log_log_base)) { let mut limb = 0; let mut offset = 0; for digit in chunk { if digit.significant_bits() > log_base { return None; } limb |= Limb::wrapping_from(&digit) << offset; offset += log_base; } limbs.push(limb); } } Greater => { let mut offset = 0; let chunk_size = bit_to_limb_count_floor(log_base); for digit in digits { if digit.significant_bits() > log_base { return None; } offset += chunk_size; limbs.extend(digit.limbs()); limbs.resize(offset, 0); } } } Some(Self::from_owned_limbs_asc(limbs)) } else { let mut n = Self::ZERO; let mut previous_index = 0; for digit in digits { if digit.significant_bits() > log_base { return None; } let index = previous_index + log_base; n.assign_bits(previous_index, index, &digit); previous_index = index; } Some(n) } } /// Converts an iterator of base-$2^k$ digits into a [`Natural`]. /// /// The base-2 logarithm of the base is specified. The input digits are in descending order: /// most- to least-significant. The type of each digit is [`Natural`]. /// /// If some digit is greater than $2^k$, `None` is returned. /// /// $$ /// f((d_i)_ {i=0}^{n-1}, k) = \sum_{i=0}^{n-1}2^{k (n-i-1)}d_i. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(nm)$ /// /// $M(n, m) = O(nm)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `digits.count()`, and $m$ is `log_base`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Two, Zero}; /// use malachite_base::num::conversion::traits::PowerOf2Digits; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// let digits = &[Natural::ZERO, Natural::ZERO, Natural::ZERO]; /// assert_eq!( /// Natural::from_power_of_2_digits_desc(6, digits.iter().cloned()).to_debug_string(), /// "Some(0)" /// ); /// /// let digits = &[Natural::ZERO, Natural::TWO]; /// assert_eq!( /// Natural::from_power_of_2_digits_desc(6, digits.iter().cloned()).to_debug_string(), /// "Some(2)" /// ); /// /// let digits = &[Natural::ONE, Natural::from(7u32), Natural::from(3u32)]; /// assert_eq!( /// Natural::from_power_of_2_digits_desc(3, digits.iter().cloned()).to_debug_string(), /// "Some(123)" /// ); /// /// let digits = &[Natural::from(100u32)]; /// assert_eq!( /// Natural::from_power_of_2_digits_desc(3, digits.iter().cloned()).to_debug_string(), /// "None" /// ); /// ``` fn from_power_of_2_digits_desc>( log_base: u64, digits: I, ) -> Option { assert_ne!(log_base, 0); if let Some(log_log_base) = log_base.checked_log_base_2() { let mut limbs = Vec::new(); match log_log_base.cmp(&Limb::LOG_WIDTH) { Equal => { for digit in digits { if digit.significant_bits() > log_base { return None; } limbs.push(Limb::wrapping_from(&digit)); } limbs.reverse(); } Less => { let digits = digits.collect_vec(); for chunk in digits.rchunks(usize::wrapping_from(Limb::WIDTH >> log_log_base)) { let mut limb = 0; let mut offset = 0; for digit in chunk.iter().rev() { if digit.significant_bits() > log_base { return None; } limb |= Limb::wrapping_from(digit) << offset; offset += log_base; } limbs.push(limb); } } Greater => { let digits = digits.collect_vec(); let mut offset = 0; let chunk_size = bit_to_limb_count_floor(log_base); for digit in digits.iter().rev() { if digit.significant_bits() > log_base { return None; } offset += chunk_size; limbs.extend(digit.limbs()); limbs.resize(offset, 0); } } } Some(Self::from_owned_limbs_asc(limbs)) } else { let digits = digits.collect_vec(); let mut n = Self::ZERO; let mut previous_index = 0; for digit in digits.iter().rev() { if digit.significant_bits() > log_base { return None; } let index = previous_index + log_base; n.assign_bits(previous_index, index, digit); previous_index = index; } Some(n) } } } impl Natural { pub_test! {to_power_of_2_digits_asc_natural_naive(&self, log_base: u64) -> Vec { assert_ne!(log_base, 0); let digit_len = self .significant_bits() .div_round(log_base, Ceiling).0; let mut digits = Vec::with_capacity(usize::exact_from(digit_len)); let mut previous_index = 0; for _ in 0..digit_len { let index = previous_index + log_base; digits.push(self.get_bits(previous_index, index)); previous_index = index; } digits }} pub_test! {from_power_of_2_digits_asc_natural_naive>( log_base: u64, digits: I, ) -> Option { assert_ne!(log_base, 0); let mut n = Natural::ZERO; let mut previous_index = 0; for digit in digits { if digit.significant_bits() > log_base { return None; } let index = previous_index + log_base; n.assign_bits(previous_index, index, &digit); previous_index = index; } Some(n) }} } ================================================ FILE: malachite-nz/src/natural/conversion/from_bool.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::basic::traits::{One, Zero}; impl From for Natural { /// Converts a [`bool`] to 0 or 1. /// /// This function is known as the [Iverson /// bracket](https://en.wikipedia.org/wiki/Iverson_bracket). /// /// $$ /// f(P) = \[P\] = \\begin{cases} /// 1 & \text{if} \\quad P, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(false), 0); /// assert_eq!(Natural::from(true), 1); /// ``` #[inline] fn from(b: bool) -> Self { if b { Self::ONE } else { Self::ZERO } } } ================================================ FILE: malachite-nz/src/natural/conversion/from_limbs.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::basic::traits::Zero; // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // Returns the length of `xs`, excluding trailing zeros. fn limbs_significant_length(xs: &[Limb]) -> usize { xs.iter() .enumerate() .rev() .find(|&(_, &x)| x != 0) .map_or(0, |(i, _)| i + 1) } impl Natural { /// Converts a slice of [limbs](crate#limbs) to a [`Natural`]. /// /// The limbs are in ascending order, so that less-significant limbs have lower indices in the /// input slice. /// /// This function borrows the limbs. If taking ownership of limbs is possible, /// [`from_owned_limbs_asc`](Self::from_owned_limbs_asc) is more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// This function is more efficient than [`from_limbs_desc`](Self::from_limbs_desc). /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::from_limbs_asc(&[]), 0); /// assert_eq!(Natural::from_limbs_asc(&[123]), 123); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from_limbs_asc(&[3567587328, 232]), /// 1000000000000u64 /// ); /// } /// ``` pub fn from_limbs_asc(xs: &[Limb]) -> Self { let significant_length = limbs_significant_length(xs); match significant_length { 0 => Self::ZERO, 1 => Self(Small(xs[0])), _ => Self(Large(xs[..significant_length].to_vec())), } } /// Converts a slice of [limbs](crate#limbs) to a [`Natural`]. /// /// The limbs in descending order, so that less-significant limbs have higher indices in the /// input slice. /// /// This function borrows the limbs. If taking ownership of the limbs is possible, /// [`from_owned_limbs_desc`](Self::from_owned_limbs_desc) is more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// This function is less efficient than [`from_limbs_asc`](Self::from_limbs_asc). /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::from_limbs_desc(&[]), 0); /// assert_eq!(Natural::from_limbs_desc(&[123]), 123); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from_limbs_desc(&[232, 3567587328]), /// 1000000000000u64 /// ); /// } /// ``` pub fn from_limbs_desc(xs: &[Limb]) -> Self { Self::from_owned_limbs_asc(xs.iter().copied().rev().collect()) } /// Converts a [`Vec`] of [limbs](crate#limbs) to a [`Natural`]. /// /// The limbs are in ascending order, so that less-significant limbs have lower indices in the /// input [`Vec`]. /// /// This function takes ownership of the limbs. If it's necessary to borrow the limbs instead, /// use [`from_limbs_asc`](Self::from_limbs_asc). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// This function is more efficient than [`from_limbs_desc`](Self::from_limbs_desc). /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::from_owned_limbs_asc(vec![]), 0); /// assert_eq!(Natural::from_owned_limbs_asc(vec![123]), 123); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from_owned_limbs_asc(vec![3567587328, 232]), /// 1000000000000u64 /// ); /// } /// ``` pub fn from_owned_limbs_asc(mut xs: Vec) -> Self { let significant_length = limbs_significant_length(&xs); match significant_length { 0 => Self::ZERO, 1 => Self(Small(xs[0])), _ => { xs.truncate(significant_length); Self(Large(xs)) } } } /// Converts a [`Vec`] of [limbs](crate#limbs) to a [`Natural`]. /// /// The limbs are in descending order, so that less-significant limbs have higher indices in the /// input [`Vec`]. /// /// This function takes ownership of the limbs. If it's necessary to borrow the limbs instead, /// use [`from_limbs_desc`](Self::from_limbs_desc). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. /// /// This function is less efficient than [`from_limbs_asc`](Self::from_limbs_asc). /// /// # Examples /// ``` /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::from_owned_limbs_desc(vec![]), 0); /// assert_eq!(Natural::from_owned_limbs_desc(vec![123]), 123); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from_owned_limbs_desc(vec![232, 3567587328]), /// 1000000000000u64 /// ); /// } /// ``` pub fn from_owned_limbs_desc(mut xs: Vec) -> Self { xs.reverse(); Self::from_owned_limbs_asc(xs) } } ================================================ FILE: malachite-nz/src/natural/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::ShlRound; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ ConvertibleFrom, IntegerMantissaAndExponent, IsInteger, RoundingFrom, }; use malachite_base::rounding_modes::RoundingMode::{self, *}; macro_rules! float_impls { ($f: ident) => { impl RoundingFrom<$f> for Natural { /// Converts a floating-point value to a [`Natural`], using the specified rounding mode. /// An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the original value. /// /// The floating-point value cannot be NaN or infinite, and it cannot round to a /// negative integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.sci_exponent()`. /// /// # Panics /// Panics if `value` is NaN or infinite, if it would round to a negative integer, or if /// the rounding mode is `Exact` and `value` is not an integer. /// /// # Examples /// See [here](super::from_primitive_float#rounding_from). fn rounding_from(value: $f, rm: RoundingMode) -> (Self, Ordering) { if value.is_nan() || value == $f::INFINITY { panic!("Cannot convert {} to Natural", value); } else if value == 0.0 { (Natural::ZERO, Equal) } else if value < 0.0 { if rm == Down || rm == Ceiling || rm == Nearest { (Natural::ZERO, Greater) } else { panic!("Result is negative and cannot be converted to a Natural"); } } else { let (mantissa, exponent) = value.integer_mantissa_and_exponent(); Natural::from(mantissa).shl_round(exponent, rm) } } } impl TryFrom<$f> for Natural { type Error = UnsignedFromFloatError; /// Converts a floating-point value to a [`Natural`]. /// /// If the input isn't exactly equal to some [`Natural`], an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.sci_exponent()`. /// /// # Examples /// See [here](super::from_primitive_float#try_from). fn try_from(value: $f) -> Result { if value.is_nan() || value.is_infinite() { Err(UnsignedFromFloatError::FloatInfiniteOrNan) } else if value < 0.0 { Err(UnsignedFromFloatError::FloatNegative) } else if value == 0.0 { Ok(Natural::ZERO) } else { let (mantissa, exponent) = value.integer_mantissa_and_exponent(); if exponent >= 0 { Ok(Natural::from(mantissa) << exponent) } else { Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange) } } } } impl ConvertibleFrom<$f> for Natural { /// Determines whether a floating-point value can be exactly converted to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_float#convertible_from). #[inline] fn convertible_from(value: $f) -> bool { value >= 0.0 && value.is_integer() } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-nz/src/natural/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::Small; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, SaturatingFrom, VecFromOtherType}; impl Natural { /// Converts a [`Limb`](crate#limbs) to a [`Natural`]. /// /// This function is const, so it may be used to define constants. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// /// const TEN: Natural = Natural::const_from(10); /// assert_eq!(TEN, 10); /// ``` pub const fn const_from(x: Limb) -> Self { Self(Small(x)) } } macro_rules! impl_from_limb { ($t: ident) => { impl From<$t> for Natural { /// Converts a [`Limb`](crate#limbs) to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Natural { Natural(Small(u)) } } }; } macro_rules! impl_from_smaller_than_limb { ($t: ident) => { impl From<$t> for Natural { /// Converts an unsigned primitive integer to a [`Natural`], where the integer's width /// is smaller than a [`Limb`](crate#limbs)'s. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Natural { Natural(Small(Limb::from(u))) } } }; } macro_rules! impl_from_larger_than_limb_or_usize { ($t: ident) => { impl From<$t> for Natural { /// Converts an unsigned primitive integer to a [`Natural`], where the integer's width /// is larger than a [`Limb`](crate#limbs)'s. /// /// This implementation is general enough to also work for [`usize`], regardless of /// whether it is equal in width to [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Natural { Natural::from_owned_limbs_asc(Limb::vec_from_other_type(u)) } } }; } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct NaturalFromSignedError; macro_rules! impl_signed { ($t: ident) => { impl TryFrom<$t> for Natural { type Error = NaturalFromSignedError; /// Converts a signed primitive integer to a [`Natural`]. If the integer is negative, an /// error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#try_from). #[inline] fn try_from(i: $t) -> Result { if i >= 0 { Ok(Natural::from(i.unsigned_abs())) } else { Err(NaturalFromSignedError) } } } impl ConvertibleFrom<$t> for Natural { /// Determines whether a signed primitive integer can be converted to a [`Natural`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#convertible_from). #[inline] fn convertible_from(i: $t) -> bool { i >= 0 } } impl SaturatingFrom<$t> for Natural { /// Converts a signed primitive primitive integer to a [`Natural`]. If the integer is /// negative, 0 is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#saturating_from). #[inline] fn saturating_from(i: $t) -> Natural { if i >= 0 { Natural::from(i.unsigned_abs()) } else { Natural::ZERO } } } }; } impl_from_smaller_than_limb!(u8); impl_from_smaller_than_limb!(u16); #[cfg(feature = "32_bit_limbs")] impl_from_limb!(u32); #[cfg(not(feature = "32_bit_limbs"))] impl_from_smaller_than_limb!(u32); #[cfg(feature = "32_bit_limbs")] impl_from_larger_than_limb_or_usize!(u64); #[cfg(not(feature = "32_bit_limbs"))] impl_from_limb!(u64); impl_from_larger_than_limb_or_usize!(u128); impl_from_larger_than_limb_or_usize!(usize); apply_to_signeds!(impl_signed); ================================================ FILE: malachite-nz/src/natural/conversion/is_integer.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::IsInteger; impl IsInteger for &Natural { /// Determines whether a [`Natural`] is an integer. It always returns `true`. /// /// $f(x) = \textrm{true}$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::num::conversion::traits::IsInteger; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.is_integer(), true); /// assert_eq!(Natural::ONE.is_integer(), true); /// assert_eq!(Natural::from(100u32).is_integer(), true); /// ``` #[inline] fn is_integer(self) -> bool { true } } ================================================ FILE: malachite-nz/src/natural/conversion/limb_count.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::WrappingFrom; impl Natural { /// Returns the number of limbs of a [`Natural`]. /// /// Zero has 0 limbs. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::ZERO.limb_count(), 0); /// assert_eq!(Natural::from(123u32).limb_count(), 1); /// assert_eq!(Natural::from(10u32).pow(12).limb_count(), 2); /// } /// ``` pub fn limb_count(&self) -> u64 { match self { &Self::ZERO => 0, Self(Small(_)) => 1, Self(Large(limbs)) => u64::wrapping_from(limbs.len()), } } } ================================================ FILE: malachite-nz/src/natural/conversion/mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::logic::bit_access::limbs_get_bit; use crate::natural::logic::bit_scan::limbs_index_of_next_true_bit; use crate::natural::{LIMB_HIGH_BIT, Natural}; use crate::natural::{bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::Limb; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Assign, Parity, ShrRound, Sign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ ExactFrom, FromOtherTypeSlice, IntegerMantissaAndExponent, SciMantissaAndExponent, WrappingFrom, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::slices::{slice_set_zero, slice_test_zero}; const TWICE_WIDTH: u64 = Limb::WIDTH << 1; impl Natural { /// Returns a [`Natural`]'s scientific mantissa and exponent, rounding according to the /// specified rounding mode. An [`Ordering`] is also returned, indicating whether the mantissa /// and exponent represent a value that is less than, equal to, or greater than the original /// value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is /// a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as a float. The /// conversion might not be exact, so we round to the nearest float using the provided rounding /// mode. If the rounding mode is `Exact` but the conversion is not exact, `None` is returned. /// $$ /// f(x, r) \approx \left (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, /// \lfloor \log_2 x \rfloor\right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::cmp::Ordering::{self, *}; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use malachite_nz::natural::Natural; /// /// let test = |n: Natural, rm: RoundingMode, out: Option<(f32, u64, Ordering)>| { /// assert_eq!( /// n.sci_mantissa_and_exponent_round(rm) /// .map(|(m, e, o)| (NiceFloat(m), e, o)), /// out.map(|(m, e, o)| (NiceFloat(m), e, o)) /// ); /// }; /// test(Natural::from(3u32), Floor, Some((1.5, 1, Equal))); /// test(Natural::from(3u32), Down, Some((1.5, 1, Equal))); /// test(Natural::from(3u32), Ceiling, Some((1.5, 1, Equal))); /// test(Natural::from(3u32), Up, Some((1.5, 1, Equal))); /// test(Natural::from(3u32), Nearest, Some((1.5, 1, Equal))); /// test(Natural::from(3u32), Exact, Some((1.5, 1, Equal))); /// /// test(Natural::from(123u32), Floor, Some((1.921875, 6, Equal))); /// test(Natural::from(123u32), Down, Some((1.921875, 6, Equal))); /// test(Natural::from(123u32), Ceiling, Some((1.921875, 6, Equal))); /// test(Natural::from(123u32), Up, Some((1.921875, 6, Equal))); /// test(Natural::from(123u32), Nearest, Some((1.921875, 6, Equal))); /// test(Natural::from(123u32), Exact, Some((1.921875, 6, Equal))); /// /// test( /// Natural::from(1000000000u32), /// Nearest, /// Some((1.8626451, 29, Equal)), /// ); /// test( /// Natural::from(10u32).pow(52), /// Nearest, /// Some((1.670478, 172, Greater)), /// ); /// /// test(Natural::from(10u32).pow(52), Exact, None); /// ``` pub fn sci_mantissa_and_exponent_round( &self, rm: RoundingMode, ) -> Option<(T, u64, Ordering)> { assert_ne!(*self, 0); // Worst case: 32-bit limbs, 64-bit float output, most-significant limb is 1. In this case, // the 3 most-significant limbs are needed. let mut most_significant_limbs = [0; 3]; let mut exponent = T::MANTISSA_WIDTH; let significant_bits; let mut exact = true; let mut half_compare = Less; // (mantissa - floor(mantissa)).cmp(&0.5) let mut highest_discarded_limb = 0; match self { Self(Small(x)) => { most_significant_limbs[0] = *x; significant_bits = x.significant_bits(); } Self(Large(xs)) => { let len = xs.len(); if len == 2 { most_significant_limbs[0] = xs[0]; most_significant_limbs[1] = xs[1]; significant_bits = xs[1].significant_bits() + Limb::WIDTH; } else { most_significant_limbs[2] = xs[len - 1]; most_significant_limbs[1] = xs[len - 2]; most_significant_limbs[0] = xs[len - 3]; exponent += limb_to_bit_count(len - 3); if !slice_test_zero(&xs[..len - 3]) { if rm == Exact { return None; } exact = false; highest_discarded_limb = xs[len - 4]; } significant_bits = most_significant_limbs[2].significant_bits() + TWICE_WIDTH; } } } let shift = i128::wrapping_from(T::MANTISSA_WIDTH + 1) - i128::wrapping_from(significant_bits); match shift.sign() { Greater => { let mut shift = u64::exact_from(shift); exponent -= shift; let limbs_to_shift = bit_to_limb_count_floor(shift); if limbs_to_shift != 0 { shift.mod_power_of_2_assign(Limb::LOG_WIDTH); most_significant_limbs.copy_within(..3 - limbs_to_shift, limbs_to_shift); slice_set_zero(&mut most_significant_limbs[..limbs_to_shift]); } if shift != 0 { limbs_slice_shl_in_place(&mut most_significant_limbs, shift); } } Less => { let mut shift = u64::exact_from(-shift); let one_index = limbs_index_of_next_true_bit(&most_significant_limbs, 0).unwrap(); if one_index < shift { if rm == Exact { return None; } if rm == Nearest { // If `exact` is true here, that means all lower limbs are 0 half_compare = if exact && one_index == shift - 1 { Equal } else if limbs_get_bit(&most_significant_limbs, shift - 1) { Greater } else { Less }; } exact = false; } exponent += shift; let limbs_to_shift = bit_to_limb_count_floor(shift); if limbs_to_shift != 0 { shift.mod_power_of_2_assign(Limb::LOG_WIDTH); most_significant_limbs.copy_within(limbs_to_shift.., 0); } if shift != 0 { limbs_slice_shr_in_place(&mut most_significant_limbs, shift); } } Equal => { if !exact && rm == Nearest { // len is at least 4, since the only way `exact` is false at this point is if // xs[..len - 3] is nonzero half_compare = highest_discarded_limb.cmp(&LIMB_HIGH_BIT); } } } let raw_mantissa = u64::from_other_type_slice(&most_significant_limbs).mod_power_of_2(T::MANTISSA_WIDTH); let mantissa = T::from_raw_mantissa_and_exponent(raw_mantissa, u64::wrapping_from(T::MAX_EXPONENT)); let increment = !exact && (rm == Up || rm == Ceiling || rm == Nearest && (half_compare == Greater || half_compare == Equal && raw_mantissa.odd())); Some(if increment { let next_mantissa = mantissa.next_higher(); if next_mantissa == T::TWO { (T::ONE, exponent + 1, Greater) } else { (next_mantissa, exponent, Greater) } } else { (mantissa, exponent, if exact { Equal } else { Less }) }) } /// Constructs a [`Natural`] from its scientific mantissa and exponent, rounding according to /// the specified rounding mode. An [`Ordering`] is also returned, indicating whether the /// returned value is less than, equal to, or greater than the exact value represented by the /// mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is /// a rational number with $1 \leq m_s < 2$. Here, the rational mantissa is provided as a float. /// If the mantissa is outside the range $[1, 2)$, `None` is returned. /// /// Some combinations of mantissas and exponents do not specify a [`Natural`], in which case the /// resulting value is rounded to a [`Natural`] using the specified rounding mode. If the /// rounding mode is `Exact` but the input does not exactly specify a [`Natural`], `None` is /// returned. /// /// $$ /// f(x, r) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `sci_exponent`. /// /// # Panics /// Panics if `sci_mantissa` is zero. /// /// # Examples /// ``` /// use core::cmp::Ordering::{self, *}; /// use core::str::FromStr; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use malachite_nz::natural::Natural; /// /// let test = /// |mantissa: f32, exponent: u64, rm: RoundingMode, out: Option<(Natural, Ordering)>| { /// assert_eq!( /// Natural::from_sci_mantissa_and_exponent_round(mantissa, exponent, rm), /// out /// ); /// }; /// test(1.5, 1, Floor, Some((Natural::from(3u32), Equal))); /// test(1.5, 1, Down, Some((Natural::from(3u32), Equal))); /// test(1.5, 1, Ceiling, Some((Natural::from(3u32), Equal))); /// test(1.5, 1, Up, Some((Natural::from(3u32), Equal))); /// test(1.5, 1, Nearest, Some((Natural::from(3u32), Equal))); /// test(1.5, 1, Exact, Some((Natural::from(3u32), Equal))); /// /// test(1.51, 1, Floor, Some((Natural::from(3u32), Less))); /// test(1.51, 1, Down, Some((Natural::from(3u32), Less))); /// test(1.51, 1, Ceiling, Some((Natural::from(4u32), Greater))); /// test(1.51, 1, Up, Some((Natural::from(4u32), Greater))); /// test(1.51, 1, Nearest, Some((Natural::from(3u32), Less))); /// test(1.51, 1, Exact, None); /// /// test( /// 1.670478, /// 172, /// Nearest, /// Some(( /// Natural::from_str("10000000254586612611935772707803116801852191350456320").unwrap(), /// Equal, /// )), /// ); /// /// test(2.0, 1, Floor, None); /// test(10.0, 1, Floor, None); /// test(0.5, 1, Floor, None); /// ``` #[inline] pub fn from_sci_mantissa_and_exponent_round( sci_mantissa: T, sci_exponent: u64, rm: RoundingMode, ) -> Option<(Self, Ordering)> { assert_ne!(sci_mantissa, T::ZERO); if sci_mantissa < T::ONE || sci_mantissa >= T::TWO { return None; } let (integer_mantissa, integer_exponent) = sci_mantissa.integer_mantissa_and_exponent(); if integer_exponent > 0 { Some(( Self::from(integer_mantissa) << (sci_exponent + u64::exact_from(integer_exponent)), Equal, )) } else { let integer_exponent = u64::exact_from(-integer_exponent); if integer_exponent <= sci_exponent { Some(( Self::from(integer_mantissa) << (sci_exponent - integer_exponent), Equal, )) } else if rm == Exact { None } else { Some(Self::from(integer_mantissa).shr_round(integer_exponent - sci_exponent, rm)) } } } } impl IntegerMantissaAndExponent for &Natural { /// Returns a [`Natural`]'s integer mantissa and exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and $m_i$ is /// an odd integer. /// $$ /// f(x) = (\frac{|x|}{2^{e_i}}, e_i), /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// The inverse operation is /// [`from_integer_mantissa_and_exponent`](IntegerMantissaAndExponent::from_integer_mantissa_and_exponent). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).integer_mantissa_and_exponent(), /// (Natural::from(123u32), 0) /// ); /// assert_eq!( /// Natural::from(100u32).integer_mantissa_and_exponent(), /// (Natural::from(25u32), 2) /// ); /// ``` #[inline] fn integer_mantissa_and_exponent(self) -> (Natural, u64) { let trailing_zeros = self.trailing_zeros().unwrap(); (self >> trailing_zeros, trailing_zeros) } /// Returns a [`Natural`]'s integer mantissa. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and $m_i$ is /// an odd integer. /// $$ /// f(x) = \frac{|x|}{2^{e_i}}, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).integer_mantissa(), 123); /// assert_eq!(Natural::from(100u32).integer_mantissa(), 25); /// ``` #[inline] fn integer_mantissa(self) -> Natural { self >> self.trailing_zeros().unwrap() } /// Returns a [`Natural`]'s integer exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and $m_i$ is /// an odd integer. /// $$ /// f(x) = e_i, /// $$ /// where $e_i$ is the unique integer such that $x/2^{e_i}$ is an odd integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).integer_exponent(), 0); /// assert_eq!(Natural::from(100u32).integer_exponent(), 2); /// ``` #[inline] fn integer_exponent(self) -> u64 { self.trailing_zeros().unwrap() } /// Constructs a [`Natural`] from its integer mantissa and exponent. /// /// When $x$ is nonzero, we can write $x = 2^{e_i}m_i$, where $e_i$ is an integer and $m_i$ is /// an odd integer. /// /// $$ /// f(x) = 2^{e_i}m_i. /// $$ /// /// The input does not have to be reduced; that is, the mantissa does not have to be odd. /// /// The result is an [`Option`], but for this trait implementation the result is always `Some`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `integer_mantissa.significant_bits() /// + integer_exponent`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; /// use malachite_nz::natural::Natural; /// /// let n = /// <&Natural as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::from(123u32), /// 0, /// ) /// .unwrap(); /// assert_eq!(n, 123); /// let n = /// <&Natural as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( /// Natural::from(25u32), /// 2, /// ) /// .unwrap(); /// assert_eq!(n, 100); /// ``` #[inline] fn from_integer_mantissa_and_exponent( integer_mantissa: Natural, integer_exponent: u64, ) -> Option { Some(integer_mantissa << integer_exponent) } } macro_rules! impl_mantissa_and_exponent { ($t:ident) => { impl SciMantissaAndExponent<$t, u64, Natural> for &Natural { /// Returns a [`Natural`]'s scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa /// as a float. The conversion might not be exact, so we round to the nearest float /// using the `Nearest` rounding mode. To use other rounding modes, use /// [`sci_mantissa_and_exponent_round`](Natural::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, \lfloor \log_2 x \rfloor). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($t, u64) { let (m, e, _) = self.sci_mantissa_and_exponent_round(Nearest).unwrap(); (m, e) } /// Constructs a [`Natural`] from its scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. Here, the rational mantissa is /// provided as a float. If the mantissa is outside the range $[1, 2)$, `None` is /// returned. /// /// Some combinations of mantissas and exponents do not specify a [`Natural`], in which /// case the resulting value is rounded to a [`Natural`] using the `Nearest` rounding /// mode. To specify other rounding modes, use /// [`from_sci_mantissa_and_exponent_round`](Natural::from_sci_mantissa_and_exponent_round). /// /// $$ /// f(x) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `sci_exponent`. /// /// # Examples /// See [here](super::mantissa_and_exponent#from_sci_mantissa_and_exponent). #[inline] fn from_sci_mantissa_and_exponent( sci_mantissa: $t, sci_exponent: u64, ) -> Option { Natural::from_sci_mantissa_and_exponent_round(sci_mantissa, sci_exponent, Nearest) .map(|p| p.0) } } }; } apply_to_primitive_floats!(impl_mantissa_and_exponent); ================================================ FILE: malachite-nz/src/natural/conversion/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of traits for working with the digits of [`Natural`](crate::natural::Natural)s. pub mod digits; /// An implementation of the [`From`] trait for converting a [`bool`] to a /// [`Natural`](crate::natural::Natural). pub mod from_bool; /// Functions for constructing a [`Natural`](crate::natural::Natural) from [`Limb`](crate#limbs)s. pub mod from_limbs; /// Implementations of traits for converting a primitive float to a /// [`Natural`](crate::natural::Natural). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::rounding_from(0.0, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(-0.0, Exact).to_debug_string(), /// "(0, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(123.0, Exact).to_debug_string(), /// "(123, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(1.0e9, Exact).to_debug_string(), /// "(1000000000, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(1.0e9, Exact).to_debug_string(), /// "(1000000000, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(4294967295.0, Exact).to_debug_string(), /// "(4294967295, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(4294967296.0, Exact).to_debug_string(), /// "(4294967296, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(1.0e100, Exact).to_debug_string(), /// "(1000000000000000015902891109759918046836080856394528138978132755774783877217038106081346\ /// 9985856815104, Equal)" /// ); /// assert_eq!( /// Natural::rounding_from(123.1, Floor).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(123.1, Ceiling).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(123.1, Nearest).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(123.9, Floor).to_debug_string(), /// "(123, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(123.9, Ceiling).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(123.9, Nearest).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(123.5, Nearest).to_debug_string(), /// "(124, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(124.5, Nearest).to_debug_string(), /// "(124, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(-0.99, Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(-0.499, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(-0.5, Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` /// /// # try_from /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::try_from(f64::NAN).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!( /// Natural::try_from(f64::INFINITY).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!( /// Natural::try_from(f64::NEGATIVE_INFINITY).to_debug_string(), /// "Err(FloatInfiniteOrNan)" /// ); /// assert_eq!(Natural::try_from(0.0).to_debug_string(), "Ok(0)"); /// assert_eq!(Natural::try_from(-0.0).to_debug_string(), "Ok(0)"); /// assert_eq!(Natural::try_from(123.0).to_debug_string(), "Ok(123)"); /// assert_eq!(Natural::try_from(1.0e9).to_debug_string(), "Ok(1000000000)"); /// assert_eq!( /// Natural::try_from(4294967295.0).to_debug_string(), /// "Ok(4294967295)" /// ); /// assert_eq!( /// Natural::try_from(4294967296.0).to_debug_string(), /// "Ok(4294967296)" /// ); /// assert_eq!( /// Natural::try_from(1.0e100).to_debug_string(), /// "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ /// 469985856815104)" /// ); /// assert_eq!( /// Natural::try_from(123.1).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Natural::try_from(123.9).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Natural::try_from(123.5).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Natural::try_from(124.5).to_debug_string(), /// "Err(FloatNonIntegerOrOutOfRange)" /// ); /// assert_eq!( /// Natural::try_from(-0.499).to_debug_string(), /// "Err(FloatNegative)" /// ); /// assert_eq!( /// Natural::try_from(-0.5).to_debug_string(), /// "Err(FloatNegative)" /// ); /// assert_eq!( /// Natural::try_from(-123.0).to_debug_string(), /// "Err(FloatNegative)" /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::basic::traits::NegativeInfinity; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::convertible_from(f64::NAN), false); /// assert_eq!(Natural::convertible_from(f64::INFINITY), false); /// assert_eq!(Natural::convertible_from(f64::NEGATIVE_INFINITY), false); /// assert_eq!(Natural::convertible_from(0.0), true); /// assert_eq!(Natural::convertible_from(-0.0), true); /// assert_eq!(Natural::convertible_from(123.0), true); /// assert_eq!(Natural::convertible_from(1.0e9), true); /// assert_eq!(Natural::convertible_from(4294967295.0), true); /// assert_eq!(Natural::convertible_from(4294967296.0), true); /// assert_eq!(Natural::convertible_from(1.0e100), true); /// assert_eq!(Natural::convertible_from(123.1), false); /// assert_eq!(Natural::convertible_from(123.9), false); /// assert_eq!(Natural::convertible_from(123.5), false); /// assert_eq!(Natural::convertible_from(124.5), false); /// assert_eq!(Natural::convertible_from(-0.499), false); /// assert_eq!(Natural::convertible_from(-0.5), false); /// assert_eq!(Natural::convertible_from(-123.0), false); /// ``` pub mod from_primitive_float; /// Implementations of traits for converting a primitive integer to a /// [`Natural`](crate::natural::Natural). /// /// The traits are [`From`], [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`SaturatingFrom`](malachite_base::num::conversion::traits::SaturatingFrom). /// /// # from /// ``` /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u64), 123); /// assert_eq!(Natural::from(123u8), 123); /// assert_eq!(Natural::from(123u128), 123); /// ``` /// /// # try_from /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::try_from(123i32).to_debug_string(), "Ok(123)"); /// assert_eq!( /// Natural::try_from(-123i32).to_debug_string(), /// "Err(NaturalFromSignedError)" /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::convertible_from(123i32), true); /// assert_eq!(Natural::convertible_from(-123i32), false); /// ``` /// /// # saturating_from /// ``` /// use malachite_base::num::conversion::traits::SaturatingFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::saturating_from(123i32), 123); /// assert_eq!(Natural::saturating_from(-123i32), 0); /// ``` pub mod from_primitive_int; /// An implementation of [`IsInteger`](malachite_base::num::conversion::traits::IsInteger), a trait /// for determining whether a number is an integer. /// /// A [`Natural`](crate::natural::Natural) is always an integer. pub mod is_integer; /// A function for counting a [`Natural`](crate::natural::Natural)'s [`Limb`](crate#limbs)s. pub mod limb_count; /// Implementations of traits for converting numbers to and from mantissa-and-exponent /// representations. /// /// See [`PrimitiveFloat`](malachite_base::num::basic::floats::PrimitiveFloat) for a description of /// the different types of mantissas and exponents. The traits are /// [`IntegerMantissaAndExponent`](malachite_base::num::conversion::traits::IntegerMantissaAndExponent) /// and [`SciMantissaAndExponent`](malachite_base::num::conversion::traits::SciMantissaAndExponent). /// /// Here are some examples of the macro-generated functions: /// /// # sci_mantissa_and_exponent /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// use malachite_nz::natural::Natural; /// /// let test = |n: Natural, mantissa: f32, exponent: u64| { /// let (m, e) = n.sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(mantissa)); /// assert_eq!(e, exponent); /// }; /// test(Natural::from(3u32), 1.5, 1); /// test(Natural::from(123u32), 1.921875, 6); /// test(Natural::from(1000000000u32), 1.8626451, 29); /// test(Natural::from(10u32).pow(52), 1.670478, 172); /// ``` /// /// # from_sci_mantissa_and_exponent /// ``` /// use core::str::FromStr; /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_nz::natural::Natural; /// /// let test = |mantissa: f32, exponent: u64, out: Option| { /// assert_eq!( /// <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( /// mantissa, exponent /// ), /// out /// ); /// }; /// test(1.5, 1, Some(Natural::from(3u32))); /// test(1.51, 1, Some(Natural::from(3u32))); /// test(1.921875, 6, Some(Natural::from(123u32))); /// test( /// 1.670478, /// 172, /// Some(Natural::from_str("10000000254586612611935772707803116801852191350456320").unwrap()), /// ); /// /// test(2.0, 1, None); /// test(10.0, 1, None); /// test(0.5, 1, None); /// ``` pub mod mantissa_and_exponent; /// Implementations of traits for converting a [`Natural`](crate::natural::Natural) to a primitive /// float. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use core::cmp::Ordering::*; /// use core::str::FromStr; /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// f32::rounding_from(&Natural::from_str("123").unwrap(), Exact), /// (123.0, Equal) /// ); /// assert_eq!( /// f32::rounding_from(&Natural::from_str("1000000001").unwrap(), Floor), /// (1.0e9, Less) /// ); /// assert_eq!( /// f32::rounding_from(&Natural::from_str("1000000001").unwrap(), Ceiling), /// (1.00000006e9, Greater) /// ); /// assert_eq!( /// f32::rounding_from( /// &Natural::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), /// Nearest /// ), /// (f32::INFINITY, Greater) /// ); /// ``` /// /// # try_from /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::conversion::primitive_float_from_natural::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!(f32::try_from(&Natural::from_str("123").unwrap()), Ok(123.0)); /// assert_eq!( /// f32::try_from(&Natural::from_str("1000000000").unwrap()), /// Ok(1.0e9) /// ); /// assert_eq!( /// f32::try_from(&Natural::from_str("1000000001").unwrap()), /// Err(PrimitiveFloatFromNaturalError) /// ); /// assert_eq!( /// f32::try_from( /// &Natural::from_str("10000000000000000000000000000000000000000000000000000").unwrap() /// ), /// Err(PrimitiveFloatFromNaturalError) /// ); /// ``` /// /// # convertible_from /// ``` /// use core::str::FromStr; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// f32::convertible_from(&Natural::from_str("123").unwrap()), /// true /// ); /// assert_eq!( /// f32::convertible_from(&Natural::from_str("1000000000").unwrap()), /// true /// ); /// assert_eq!( /// f32::convertible_from(&Natural::from_str("1000000001").unwrap()), /// false /// ); /// assert_eq!( /// f32::convertible_from( /// &Natural::from_str("10000000000000000000000000000000000000000000000000000").unwrap() /// ), /// false /// ); /// ``` pub mod primitive_float_from_natural; /// Implementations of traits for converting a [`Natural`](crate::natural::Natural) to a primitive /// integer. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), /// [`OverflowingFrom`](malachite_base::num::conversion::traits::OverflowingFrom), /// [`SaturatingFrom`](malachite_base::num::conversion::traits::SaturatingFrom), and /// [`WrappingFrom`](malachite_base::num::conversion::traits::WrappingFrom). /// /// # try_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::conversion::primitive_int_from_natural::{ /// SignedFromNaturalError, UnsignedFromNaturalError, /// }; /// use malachite_nz::natural::Natural; /// /// assert_eq!(u32::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// u32::try_from(&Natural::from(10u32).pow(12)), /// Err(UnsignedFromNaturalError) /// ); /// assert_eq!(u8::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// u8::try_from(&Natural::from(10u32).pow(12)), /// Err(UnsignedFromNaturalError) /// ); /// assert_eq!(u64::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// u64::try_from(&(Natural::ONE << 100)), /// Err(UnsignedFromNaturalError) /// ); /// /// assert_eq!(i32::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// i32::try_from(&Natural::from(10u32).pow(12)), /// Err(SignedFromNaturalError) /// ); /// assert_eq!(i8::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// i8::try_from(&Natural::from(10u32).pow(12)), /// Err(SignedFromNaturalError) /// ); /// assert_eq!(i64::try_from(&Natural::from(123u32)), Ok(123)); /// assert_eq!( /// i64::try_from(&(Natural::ONE << 100)), /// Err(SignedFromNaturalError) /// ); /// ``` /// /// # wrapping_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::WrappingFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(u32::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!( /// u32::wrapping_from(&Natural::from(10u32).pow(12)), /// 3567587328 /// ); /// assert_eq!(u8::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!(u8::wrapping_from(&Natural::from(10u32).pow(12)), 0); /// assert_eq!(u64::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!(u64::wrapping_from(&(Natural::ONE << 100)), 0); /// /// assert_eq!(i32::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!( /// i32::wrapping_from(&Natural::from(10u32).pow(12)), /// -727379968 /// ); /// assert_eq!(i8::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!(i8::wrapping_from(&Natural::from(10u32).pow(12)), 0); /// assert_eq!(i64::wrapping_from(&Natural::from(123u32)), 123); /// assert_eq!(i64::wrapping_from(&(Natural::ONE << 100)), 0); /// ``` /// /// # saturating_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::SaturatingFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(u32::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!( /// u32::saturating_from(&Natural::from(10u32).pow(12)), /// u32::MAX /// ); /// assert_eq!(u8::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!(u8::saturating_from(&Natural::from(10u32).pow(12)), 255); /// assert_eq!(u64::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!( /// u64::saturating_from(&(Natural::ONE << 100)), /// 18446744073709551615 /// ); /// /// assert_eq!(i32::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!( /// i32::saturating_from(&Natural::from(10u32).pow(12)), /// 2147483647 /// ); /// assert_eq!(i8::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!(i8::saturating_from(&Natural::from(10u32).pow(12)), 127); /// assert_eq!(i64::saturating_from(&Natural::from(123u32)), 123); /// assert_eq!( /// i64::saturating_from(&(Natural::ONE << 100)), /// 9223372036854775807 /// ); /// ``` /// /// # overflowing_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::OverflowingFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(u32::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!( /// u32::overflowing_from(&Natural::from(10u32).pow(12)), /// (3567587328, true) /// ); /// assert_eq!(u8::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!( /// u8::overflowing_from(&Natural::from(10u32).pow(12)), /// (0, true) /// ); /// assert_eq!(u64::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!(u64::overflowing_from(&(Natural::ONE << 100)), (0, true)); /// /// assert_eq!(i32::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!( /// i32::overflowing_from(&Natural::from(10u32).pow(12)), /// (-727379968, true) /// ); /// assert_eq!(i8::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!( /// i8::overflowing_from(&Natural::from(10u32).pow(12)), /// (0, true) /// ); /// assert_eq!(i64::overflowing_from(&Natural::from(123u32)), (123, false)); /// assert_eq!(i64::overflowing_from(&(Natural::ONE << 100)), (0, true)); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::natural::Natural; /// /// assert_eq!(u32::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(u32::convertible_from(&Natural::from(10u32).pow(12)), false); /// assert_eq!(u8::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(u8::convertible_from(&Natural::from(10u32).pow(12)), false); /// assert_eq!(u64::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(u64::convertible_from(&(Natural::ONE << 100)), false); /// /// assert_eq!(i32::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(i32::convertible_from(&Natural::from(10u32).pow(12)), false); /// assert_eq!(i8::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(i8::convertible_from(&Natural::from(10u32).pow(12)), false); /// assert_eq!(i64::convertible_from(&Natural::from(123u32)), true); /// assert_eq!(i64::convertible_from(&(Natural::ONE << 100)), false); /// ``` pub mod primitive_int_from_natural; /// Implementations of traits for conversions between Python integers and /// [`Natural`](crate::natural::Natural)s using [pyo3](https://pyo3.rs/). pub mod pyo3; /// Implementations of traits for serialization and deserialization using /// [serde](https://serde.rs/). pub mod serde; /// Implementations of traits for converting [`Natural`](crate::natural::Natural)s to and from /// [`String`]s. pub mod string; /// Functions for extracting [`Limb`](crate#limbs)s from a [`Natural`](crate::natural::Natural). pub mod to_limbs; ================================================ FILE: malachite-nz/src/natural/conversion/primitive_float_from_natural.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::{self, *}; use malachite_base::named::Named; use malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, RawMantissaAndExponent, RoundingFrom, SciMantissaAndExponent, WrappingFrom, }; use malachite_base::rounding_modes::RoundingMode::{self, *}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PrimitiveFloatFromNaturalError; macro_rules! float_impls { ($f: ident) => { impl<'a> RoundingFrom<&'a Natural> for $f { /// Converts a [`Natural`] to a primitive float according to a specified /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// - If the rounding mode is `Floor` or `Down`, the largest float less than or equal to /// the [`Natural`] is returned. If the [`Natural`] is greater than the maximum finite /// float, then the maximum finite float is returned. /// - If the rounding mode is `Ceiling` or `Up`, the smallest float greater than or /// equal to the [`Natural`] is returned. If the [`Natural`] is greater than the /// maximum finite float, then $\infty$ is returned. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If the /// [`Natural`] is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. If the [`Natural`] is /// greater than the maximum finite float, then $\infty$ is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the rounding mode is `Exact` and `value` cannot be represented exactly. /// /// # Examples /// See [here](super::primitive_float_from_natural#rounding_from). fn rounding_from(value: &'a Natural, rm: RoundingMode) -> ($f, Ordering) { if *value == 0 { (0.0, Equal) } else { let (mantissa, exponent, o) = value .sci_mantissa_and_exponent_round(rm) .expect("Value cannot be represented exactly as a float"); if let Some(f) = $f::from_sci_mantissa_and_exponent(mantissa, i64::exact_from(exponent)) { (f, o) } else { match rm { Exact => { panic!("Value cannot be represented exactly as an {}", $f::NAME) } Floor | Down => ($f::MAX_FINITE, Less), _ => ($f::INFINITY, Greater), } } } } } impl<'a> TryFrom<&'a Natural> for $f { type Error = PrimitiveFloatFromNaturalError; /// Converts a [`Natural`] to a primitive float. /// /// If the input isn't exactly equal to some float, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_natural#try_from). fn try_from(value: &'a Natural) -> Result<$f, Self::Error> { if *value == 0 { Ok(0.0) } else { let (mantissa, exponent, _) = value .sci_mantissa_and_exponent_round(Exact) .ok_or(PrimitiveFloatFromNaturalError)?; $f::from_sci_mantissa_and_exponent(mantissa, i64::exact_from(exponent)) .ok_or(PrimitiveFloatFromNaturalError) } } } impl<'a> ConvertibleFrom<&'a Natural> for $f { /// Determines whether a [`Natural`] can be exactly converted to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_natural#convertible_from). fn convertible_from(value: &'a Natural) -> bool { if *value == 0 { true } else { if let Some((mantissa, exponent, _)) = value.sci_mantissa_and_exponent_round::<$f>(Exact) { let exponent = i64::exact_from(exponent); if !($f::MIN_EXPONENT..=$f::MAX_EXPONENT).contains(&exponent) { return false; } let (orig_mantissa, orig_exponent) = mantissa.raw_mantissa_and_exponent(); orig_exponent == u64::wrapping_from($f::MAX_EXPONENT) && exponent >= $f::MIN_NORMAL_EXPONENT || orig_mantissa.divisible_by_power_of_2(u64::wrapping_from( $f::MIN_NORMAL_EXPONENT - exponent, )) } else { false } } } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-nz/src/natural/conversion/primitive_int_from_natural.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::basic::integers::{PrimitiveInt, USIZE_IS_U32}; use malachite_base::num::conversion::traits::{ ConvertibleFrom, FromOtherTypeSlice, OverflowingFrom, SaturatingFrom, WrappingFrom, }; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct UnsignedFromNaturalError; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct SignedFromNaturalError; macro_rules! impl_from_limb { ($u: ident, $s: ident) => { impl<'a> TryFrom<&'a Natural> for $u { type Error = UnsignedFromNaturalError; /// Converts a [`Natural`] to a [`Limb`](crate#limbs), returning an error if the /// [`Natural`] is too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). fn try_from(value: &Natural) -> Result<$u, Self::Error> { match *value { Natural(Small(small)) => Ok(small), Natural(Large(_)) => Err(UnsignedFromNaturalError), } } } impl<'a> WrappingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ /// is the width of a limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). fn wrapping_from(value: &Natural) -> $u { match *value { Natural(Small(small)) => small, Natural(Large(ref limbs)) => limbs[0], } } } impl<'a> SaturatingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a [`Limb`](crate#limbs). /// /// If the [`Natural`] is too large to fit in a [`Limb`](crate#limbs), the maximum /// representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). fn saturating_from(value: &Natural) -> $u { match *value { Natural(Small(small)) => small, Natural(Large(_)) => $u::MAX, } } } impl<'a> OverflowingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ /// is the width of a limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). fn overflowing_from(value: &Natural) -> ($u, bool) { match *value { Natural(Small(small)) => (small, false), Natural(Large(ref limbs)) => (limbs[0], true), } } } impl<'a> ConvertibleFrom<&'a Natural> for $u { /// Determines whether a [`Natural`] can be converted to a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { match *value { Natural(Small(_)) => true, Natural(Large(_)) => false, } } } impl<'a> TryFrom<&'a Natural> for $s { type Error = SignedFromNaturalError; /// Converts a [`Natural`] to a `SignedLimb` (the signed type whose width is the same as /// a [limb](crate#limbs)'s), returning an error if the [`Natural`] is too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). fn try_from(value: &Natural) -> Result<$s, Self::Error> { match *value { Natural(Small(small)) => { $s::try_from(small).map_err(|_| SignedFromNaturalError) } Natural(Large(_)) => Err(SignedFromNaturalError), } } } impl<'a> WrappingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a `SignedLimb` (the signed type whose width is the same as /// a [limb](crate#limbs)'s), wrapping modulo $2^W$, where $W$ is the width of a limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). #[inline] fn wrapping_from(value: &Natural) -> $s { $s::wrapping_from($u::wrapping_from(value)) } } impl<'a> SaturatingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a `SignedLimb` (the signed type whose width is the same as /// a [limb](crate#limbs)'s). /// /// If the [`Natural`] is too large to fit in a `SignedLimb`, the largest representable /// value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). #[inline] fn saturating_from(value: &Natural) -> $s { $s::saturating_from($u::saturating_from(value)) } } impl<'a> OverflowingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a `SignedLimb` (the signed type whose width is the same as /// a [limb](crate#limbs)'s), wrapping modulo $2^W$, where $W$ is the width of a limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). fn overflowing_from(value: &Natural) -> ($s, bool) { let (result, overflow_1) = $u::overflowing_from(value); let (result, overflow_2) = $s::overflowing_from(result); (result, overflow_1 || overflow_2) } } impl<'a> ConvertibleFrom<&'a Natural> for $s { /// Determines whether a [`Natural`] can be converted to a `SignedLimb` (the signed type /// whose width is the same as a [limb](crate#limbs)'s). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { match *value { Natural(Small(small)) => $s::convertible_from(small), Natural(Large(_)) => false, } } } }; } macro_rules! impl_from_smaller_than_limb { ($u: ident, $s: ident) => { impl<'a> TryFrom<&'a Natural> for $u { type Error = UnsignedFromNaturalError; /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs), returning an error if the [`Natural`] is too /// large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). #[inline] fn try_from(value: &Natural) -> Result<$u, Self::Error> { Limb::try_from(value) .map_err(|_| UnsignedFromNaturalError) .and_then(|x| $u::try_from(x).map_err(|_| UnsignedFromNaturalError)) } } impl<'a> WrappingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the width /// of a limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). #[inline] fn wrapping_from(value: &Natural) -> $u { $u::wrapping_from(Limb::wrapping_from(value)) } } impl<'a> SaturatingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs). If the [`Natural`] is too large to fit in the /// output type, the largest representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). #[inline] fn saturating_from(value: &Natural) -> $u { $u::saturating_from(Limb::saturating_from(value)) } } impl<'a> OverflowingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the width /// of a limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). #[inline] fn overflowing_from(value: &Natural) -> ($u, bool) { let (result, overflow_1) = Limb::overflowing_from(value); let (result, overflow_2) = $u::overflowing_from(result); (result, overflow_1 || overflow_2) } } impl<'a> ConvertibleFrom<&'a Natural> for $u { /// Determines whether a [`Natural`] can be converted to a value of a primitive unsigned /// integer type that's smaller than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { match *value { Natural(Small(small)) => $u::convertible_from(small), Natural(Large(_)) => false, } } } impl<'a> TryFrom<&'a Natural> for $s { type Error = SignedFromNaturalError; /// Converts a [`Natural`] to a value of a signed primitive integer type that's smaller /// than a [`Limb`](crate#limbs), returning an error if the [`Natural`] is too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). #[inline] fn try_from(value: &Natural) -> Result<$s, Self::Error> { Limb::try_from(value) .map_err(|_| SignedFromNaturalError) .and_then(|x| $s::try_from(x).map_err(|_| SignedFromNaturalError)) } } impl<'a> WrappingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a value of a signed primitive integer type that's smaller /// than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the width of a /// limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). #[inline] fn wrapping_from(value: &Natural) -> $s { $s::wrapping_from(Limb::wrapping_from(value)) } } impl<'a> SaturatingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// smaller than a [`Limb`](crate#limbs). If the [`Natural`] is too large to fit in the /// output type, the largest representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). #[inline] fn saturating_from(value: &Natural) -> $s { $s::saturating_from(Limb::saturating_from(value)) } } impl<'a> OverflowingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to a value of a signed primitive integer type that's smaller /// than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the width of a /// limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). #[inline] fn overflowing_from(value: &Natural) -> ($s, bool) { let (result, overflow_1) = Limb::overflowing_from(value); let (result, overflow_2) = $s::overflowing_from(result); (result, overflow_1 || overflow_2) } } impl<'a> ConvertibleFrom<&'a Natural> for $s { /// Determines whether a [`Natural`] can be converted to a value of a signed primitive /// integer type that's smaller than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { match *value { Natural(Small(small)) => $s::convertible_from(small), Natural(Large(_)) => false, } } } }; } macro_rules! impl_from_larger_than_limb_or_xsize { ($u: ident, $s: ident) => { impl<'a> WrappingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a [`usize`] or a value of an unsigned primitive integer /// type that's larger than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is /// the width of a limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). fn wrapping_from(value: &Natural) -> $u { match *value { Natural(Small(small)) => $u::wrapping_from(small), Natural(Large(ref limbs)) => $u::from_other_type_slice(limbs), } } } impl<'a> TryFrom<&'a Natural> for $s { type Error = SignedFromNaturalError; /// Converts a [`Natural`] to an [`isize`] or value of a signed primitive integer type /// that's larger than a [`Limb`](crate#limbs), returning an error if the [`Natural`] is /// too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). #[inline] fn try_from(value: &Natural) -> Result<$s, Self::Error> { $u::try_from(value) .map_err(|_| SignedFromNaturalError) .and_then(|x| $s::try_from(x).map_err(|_| SignedFromNaturalError)) } } impl<'a> WrappingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to an [`isize`] or a value of a signed primitive integer type /// that's larger than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the /// width of a limb. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#wrapping_from). #[inline] fn wrapping_from(value: &Natural) -> $s { $s::wrapping_from($u::wrapping_from(value)) } } impl<'a> SaturatingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to an [`isize`] or a value of a signed primitive integer type /// that's larger than a [`Limb`](crate#limbs), If the [`Natural`] is too large to fit /// in the output type, the largest representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). #[inline] fn saturating_from(value: &Natural) -> $s { $s::saturating_from($u::saturating_from(value)) } } impl<'a> OverflowingFrom<&'a Natural> for $s { /// Converts a [`Natural`] to an [`isize`] or a value of a signed primitive integer type /// that's larger than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the /// width of a limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). fn overflowing_from(value: &Natural) -> ($s, bool) { let (result, overflow_1) = $u::overflowing_from(value); let (result, overflow_2) = $s::overflowing_from(result); (result, overflow_1 || overflow_2) } } }; } macro_rules! impl_from_larger_than_limb { ($u: ident, $s: ident) => { impl_from_larger_than_limb_or_xsize!($u, $s); impl<'a> TryFrom<&'a Natural> for $u { type Error = UnsignedFromNaturalError; /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// larger than a [`Limb`](crate#limbs), returning an error if the [`Natural`] is too /// large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). fn try_from(value: &Natural) -> Result<$u, Self::Error> { const SIZE_RATIO: usize = 1 << ($u::LOG_WIDTH - Limb::LOG_WIDTH); match *value { Natural(Small(small)) => Ok($u::from(small)), Natural(Large(ref limbs)) if limbs.len() <= SIZE_RATIO => { Ok($u::from_other_type_slice(limbs)) } Natural(Large(_)) => Err(UnsignedFromNaturalError), } } } impl<'a> SaturatingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// larger than a [`Limb`](crate#limbs). If the [`Natural`] is too large to fit in the /// output type, the largest representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). fn saturating_from(value: &Natural) -> $u { const SIZE_RATIO: usize = 1 << ($u::LOG_WIDTH - Limb::LOG_WIDTH); match *value { Natural(Small(small)) => $u::from(small), Natural(Large(ref limbs)) if limbs.len() <= SIZE_RATIO => { $u::from_other_type_slice(limbs) } Natural(Large(_)) => $u::MAX, } } } impl<'a> OverflowingFrom<&'a Natural> for $u { /// Converts a [`Natural`] to a value of an unsigned primitive integer type that's /// larger than a [`Limb`](crate#limbs), wrapping modulo $2^W$, where $W$ is the width /// of a limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). fn overflowing_from(value: &Natural) -> ($u, bool) { const SIZE_RATIO: usize = 1 << ($u::LOG_WIDTH - Limb::LOG_WIDTH); match *value { Natural(Small(small)) => ($u::from(small), false), Natural(Large(ref limbs)) => { ($u::from_other_type_slice(limbs), limbs.len() > SIZE_RATIO) } } } } impl<'a> ConvertibleFrom<&'a Natural> for $u { /// Determines whether a [`Natural`] can be converted to a value of a primitive unsigned /// integer type that's larger than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { const SIZE_RATIO: usize = 1 << ($u::LOG_WIDTH - Limb::LOG_WIDTH); match *value { Natural(Small(_)) => true, Natural(Large(ref limbs)) => limbs.len() <= SIZE_RATIO, } } } impl<'a> ConvertibleFrom<&'a Natural> for $s { /// Determines whether a [`Natural`] can be converted to a value of a signed primitive /// integer type that's larger than a [`Limb`](crate#limbs). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { const SIZE_RATIO: usize = 1 << ($u::LOG_WIDTH - Limb::LOG_WIDTH); match *value { Natural(Small(_)) => true, Natural(Large(ref limbs)) => { limbs.len() < SIZE_RATIO || limbs.len() == SIZE_RATIO && !limbs[SIZE_RATIO - 1].get_highest_bit() } } } } }; } impl TryFrom<&Natural> for usize { type Error = UnsignedFromNaturalError; /// Converts a [`Natural`] to a [`usize`], returning an error if the [`Natural`] is too large. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#try_from). fn try_from(value: &Natural) -> Result { if USIZE_IS_U32 { u32::try_from(value).map(Self::wrapping_from) } else { assert_eq!(Self::WIDTH, u64::WIDTH); u64::try_from(value).map(Self::wrapping_from) } } } impl SaturatingFrom<&Natural> for usize { /// Converts a [`Natural`] to a [`usize`]. If the [`Natural`] is too large to fit in a /// [`usize`], the largest representable value is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#saturating_from). fn saturating_from(value: &Natural) -> Self { if USIZE_IS_U32 { Self::wrapping_from(u32::saturating_from(value)) } else { assert_eq!(Self::WIDTH, u64::WIDTH); Self::wrapping_from(u64::saturating_from(value)) } } } impl OverflowingFrom<&Natural> for usize { /// Converts a [`Natural`] to a [`usize`], wrapping modulo $2^W$, where $W$ is the width of a /// limb. /// /// The returned boolean value indicates whether wrapping occurred. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#overflowing_from). fn overflowing_from(value: &Natural) -> (Self, bool) { if USIZE_IS_U32 { let (result, overflow) = u32::overflowing_from(value); (Self::wrapping_from(result), overflow) } else { assert_eq!(Self::WIDTH, u64::WIDTH); let (result, overflow) = u64::overflowing_from(value); (Self::wrapping_from(result), overflow) } } } impl ConvertibleFrom<&Natural> for usize { /// Determines whether a [`Natural`] can be converted to a [`usize`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { if USIZE_IS_U32 { u32::convertible_from(value) } else { assert_eq!(Self::WIDTH, u64::WIDTH); u64::convertible_from(value) } } } impl ConvertibleFrom<&Natural> for isize { /// Determines whether a [`Natural`] can be converted to an [`isize`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_natural#convertible_from). fn convertible_from(value: &Natural) -> bool { if USIZE_IS_U32 { i32::convertible_from(value) } else { assert_eq!(usize::WIDTH, u64::WIDTH); i64::convertible_from(value) } } } impl_from_smaller_than_limb!(u8, i8); impl_from_smaller_than_limb!(u16, i16); #[cfg(feature = "32_bit_limbs")] impl_from_limb!(u32, i32); #[cfg(not(feature = "32_bit_limbs"))] impl_from_smaller_than_limb!(u32, i32); #[cfg(feature = "32_bit_limbs")] impl_from_larger_than_limb!(u64, i64); #[cfg(not(feature = "32_bit_limbs"))] impl_from_limb!(u64, i64); impl_from_larger_than_limb!(u128, i128); impl_from_larger_than_limb_or_xsize!(usize, isize); ================================================ FILE: malachite-nz/src/natural/conversion/pyo3.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // PyO3 integration contributed by Antonio Mamić. // // 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 . #![cfg(feature = "enable_pyo3")] //! //! This is useful for converting Python integers when they may not fit in Rust's built-in integer //! types. //! //! To use this enable the `enable_pyo3` feature. //! //! ## Examples //! //! Using [`Natural`](crate::natural::Natural) to correctly increment an arbitrary precision //! integer. This is not possible with Rust's native integers if the Python integer is too large, //! in which case it will fail its conversion and raise `OverflowError`. //! ```rust //! use malachite::Natural; //! use malachite::num::basic::traits::One; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(n: Natural) -> Natural { //! // negative n would raise ValueError here //! n + Natural::ONE //! } //! //! #[pymodule] //! fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import add_one //! //! n = 1 << 1337 //! value = add_one(n) //! //! assert n + 1 == value //! ``` use crate::natural::Natural; use alloc::vec::Vec; use core::convert::Infallible; use malachite_base::num::basic::traits::Zero; #[cfg(Py_LIMITED_API)] use pyo3::intern; #[allow(unused_imports)] use pyo3::{ Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, Py, PyErr, PyObject, PyResult, Python, exceptions::PyValueError, ffi, types::*, }; #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'source> FromPyObject<'source> for Natural { fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { // get the Python interpreter let py = ob.py(); // get PyInt object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; // check if number is negative, and if so, raise TypeError if num.lt(0)? { return Err(PyErr::new::( "expected non-negative integer", )); } // check if number is zero, and if so, return zero let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(Natural::ZERO); } // the number of bytes needed to store the integer let mut n_bytes = (n_bits + 7) >> 3; #[cfg(feature = "32_bit_limbs")] { // convert the number of bytes to a multiple of 4, because of 32-bit limbs n_bytes = ((n_bytes + 7) >> 2) << 2; } #[cfg(not(feature = "32_bit_limbs"))] { // convert the number of bytes to a multiple of 8, because of 64-bit limbs n_bytes = ((n_bytes + 7) >> 3) << 3; } #[cfg(not(Py_LIMITED_API))] { let limbs = int_to_limbs(num, n_bytes, false)?; Ok(Natural::from_owned_limbs_asc(limbs)) } #[cfg(all(Py_LIMITED_API, feature = "32_bit_limbs"))] { let py_bytes = int_to_py_bytes(num, n_bytes, false)?; let bytes = py_bytes.as_bytes(); let n_limbs_32 = n_bytes >> 2; // the number of 32-bit limbs needed to store the integer let mut limbs_32 = Vec::with_capacity(n_limbs_32); for i in (0..n_bytes).step_by(4) { limbs_32.push(u32::from_le_bytes(bytes[i..(i + 4)].try_into().unwrap())); } Ok(Natural::from_owned_limbs_asc(limbs_32)) } #[cfg(all(Py_LIMITED_API, not(feature = "32_bit_limbs")))] { let bytes = int_to_py_bytes(num, n_bytes, false)?.as_bytes(); let n_limbs_64 = n_bytes >> 3; // the number of 64-bit limbs needed to store the integer let mut limbs_64 = Vec::with_capacity(n_limbs_64); for i in (0..n_bytes).step_by(8) { limbs_64.push(u64::from_le_bytes(bytes[i..(i + 8)].try_into().unwrap())); } Ok(Natural::from_owned_limbs_asc(limbs_64)) } } } #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'py> IntoPyObject<'py> for Natural { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } #[cfg_attr(docsrs, doc(cfg(feature = "enable_pyo3")))] impl<'py> IntoPyObject<'py> for &Natural { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { if self == &Natural::ZERO { return 0i32.into_pyobject(py); } let bytes = limbs_to_bytes(self.limbs(), self.limb_count()); #[cfg(not(Py_LIMITED_API))] unsafe { let obj = ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, // little endian false.into(), // unsigned ); Ok(Bound::from_owned_ptr(py, obj).downcast_into_unchecked()) } #[cfg(Py_LIMITED_API)] { let bytes_obj = PyBytes::new(py, &bytes); let kwargs = None; let result: Bound<'py, PyAny> = py .get_type::() .call_method("from_bytes", (bytes_obj, "little"), kwargs) .expect("int.from_bytes() failed during into_pyobject()"); Ok(result) } } } /// Convert 32-bit limbs (little endian) used by malachite to bytes (little endian) #[cfg(feature = "32_bit_limbs")] #[inline] fn limbs_to_bytes(limbs: impl Iterator, limb_count: u64) -> Vec { let mut bytes = Vec::with_capacity((limb_count << 3) as usize); for limb in limbs { for byte in limb.to_le_bytes() { bytes.push(byte); } } bytes } /// Convert 64-bit limbs (little endian) used by malachite to bytes (little endian) #[cfg(not(feature = "32_bit_limbs"))] #[inline] fn limbs_to_bytes(limbs: impl Iterator, limb_count: u64) -> Vec { let mut bytes = Vec::with_capacity((limb_count << 3) as usize); for limb in limbs { for byte in limb.to_le_bytes() { bytes.push(byte); } } bytes } /// Converts a Python integer to a vector of 32-bit limbs (little endian). Takes number of bytes to /// convert to. Multiple of 4. If `is_signed` is true, the integer is treated as signed, and two's /// complement is returned. #[cfg(all(not(Py_LIMITED_API), feature = "32_bit_limbs"))] #[inline] fn int_to_limbs(long: &Bound, n_bytes: usize, is_signed: bool) -> PyResult> { let mut buffer = Vec::with_capacity(n_bytes); unsafe { let error_code = ffi::_PyLong_AsByteArray( long.as_ptr().cast(), // ptr to PyInt object buffer.as_mut_ptr() as *mut u8, // ptr to first byte of buffer n_bytes << 2, // 4 bytes per u32 1, // little endian is_signed.into(), // signed flag ); if error_code == -1 { return Err(PyErr::fetch(long.py())); } buffer.set_len(n_bytes); // set buffer length to the number of bytes }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } /// Converts a Python integer to a vector of 64-bit limbs (little endian). Takes number of bytes to /// convert to. Multiple of 8. If `is_signed` is true, the integer is treated as signed, and two's /// complement is returned. #[cfg(all(not(Py_LIMITED_API), not(feature = "32_bit_limbs")))] #[inline] fn int_to_limbs(long: &Bound, n_bytes: usize, is_signed: bool) -> PyResult> { let mut buffer = Vec::with_capacity(n_bytes); unsafe { let error_code = ffi::_PyLong_AsByteArray( long.as_ptr().cast(), // ptr to PyLong object buffer.as_mut_ptr() as *mut u8, // ptr to first byte of buffer n_bytes << 3, // 8 bytes per u64 1, // little endian is_signed.into(), // signed flag ); if error_code == -1 { return Err(PyErr::fetch(long.py())); } buffer.set_len(n_bytes); // set buffer length to the number of bytes }; buffer .iter_mut() .for_each(|chunk| *chunk = u64::from_le(*chunk)); Ok(buffer) } /// Converts a Python integer to a Python bytes object. Bytes are in little endian order. Takes /// number of bytes to convert to (can be calculated from the number of bits in the integer). If /// `is_signed` is true, the integer is treated as signed, and two's complement is returned. #[cfg(Py_LIMITED_API)] #[inline] fn int_to_py_bytes<'py>( long: &Bound<'py, PyInt>, n_bytes: usize, is_signed: bool, ) -> PyResult> { // get the Python interpreter let py = long.py(); // setup kwargs for to_bytes (only if signed) let kwargs_dict = PyDict::new(py); let kwargs = if is_signed { kwargs_dict.set_item(intern!(py, "signed"), true)?; Some(&kwargs_dict) } else { None }; // call to_bytes let bytes = long.call_method( intern!(py, "to_bytes"), (n_bytes, intern!(py, "little")), kwargs, )?; // downcast to PyBytes Ok(bytes.downcast_into()?) } /// Returns the number of bits in the absolute value of the given integer. The number of bits /// returned is the smallest number of bits that can represent the integer, not the multiple of 8 /// (bytes) that it would take up in memory. #[inline] fn int_n_bits(long: &Bound) -> PyResult { let py = long.py(); #[cfg(not(Py_LIMITED_API))] { // fast path let n_bits = unsafe { ffi::_PyLong_NumBits(long.as_ptr()) }; if n_bits == (-1isize as usize) { return Err(PyErr::fetch(py)); } Ok(n_bits) } #[cfg(Py_LIMITED_API)] { // slow path long.call_method0(intern!(py, "bit_length")) .and_then(|l| l.extract::()) } } #[cfg(test)] mod tests { use super::*; /// Prepare Python fn prepare_python() { pyo3::prepare_freethreaded_python(); } /// Fibonacci sequence iterator (Rust) fn rust_fib() -> impl Iterator where T: From, for<'a> &'a T: std::ops::Add, { let mut f0: T = T::from(1); let mut f1: T = T::from(1); std::iter::from_fn(move || { let f2 = &f0 + &f1; Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } /// Fibonacci sequence iterator (Python) fn python_fib(py: Python<'_>) -> impl Iterator> { let mut f0 = 1u32.into_pyobject(py).unwrap(); let mut f1 = 1u32.into_pyobject(py).unwrap(); std::iter::from_fn(move || { let f2 = f0 .call_method1("__add__", (&f1,)) .unwrap() .downcast_into::() .unwrap(); Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2)).unbind()) }) } /// Generate test python class fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> { let index_code = c" class C: def __init__(self, x): self.x = x def __index__(self): return self.x "; let filename = c"index.py"; let modulename = c"index"; PyModule::from_code(py, index_code, filename, modulename).unwrap() } /// - Test conversion to and from Natural /// - Tests the first 2000 numbers in the fibonacci sequence #[test] fn convert_natural() { prepare_python(); Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!( py_result .bind(py) .as_any() .eq(rs_result.into_pyobject(py).unwrap()) .unwrap() ); } }); } /// Test Python class conversion #[test] fn convert_index_class() { prepare_python(); Python::with_gil(|py| { let index = python_index_class(py); let locals = PyDict::new(py); locals.set_item("index", &index).unwrap(); let expr = c"index.C(10)"; let ob = py.eval(expr, None, Some(&locals)).unwrap(); let natural: Natural = ::extract_bound(&ob).unwrap(); assert_eq!(natural, Natural::from(10_u8)); }); } /// Test conversion to and from zero #[test] fn handle_zero() { prepare_python(); Python::with_gil(|py| { // Python -> Rust let zero_natural: Natural = 0u32.into_pyobject(py).unwrap().extract().unwrap(); assert_eq!(zero_natural, Natural::from(0_u8)); // Rust -> Python let zero_natural = zero_natural.into_pyobject(py).unwrap(); assert!( zero_natural .as_any() .eq(0u8.into_py_any(py).unwrap()) .unwrap() ); }); } /// Test for possible overflows #[test] fn check_overflow() { prepare_python(); Python::with_gil(|py| { macro_rules! test { ($T:ty, $value:expr, $py:expr) => { let value = $value; println!("{}: {}", stringify!($T), value); let python_value = value.clone().into_pyobject(py).unwrap(); let roundtrip_value = <$T as FromPyObject>::extract_bound(&python_value).unwrap(); assert_eq!(value, roundtrip_value); }; } for i in 0..=256usize { // test a lot of values to help catch other bugs too test!(Natural, Natural::from(i), py); test!(Natural, Natural::from(1u32) << i, py); test!( Natural, (Natural::from(1u32) << i) + Natural::from(1u32), py ); test!( Natural, (Natural::from(1u32) << i) - Natural::from(1u32), py ); } }); } /// Test error when converting negative integer to Natural #[test] fn negative_natural() { prepare_python(); Python::with_gil(|py| { let zero = 0u32.into_pyobject(py).unwrap(); let minus_one = (-1i32).into_pyobject(py).unwrap(); assert_eq!(zero.extract::().unwrap(), Natural::ZERO); assert!( minus_one .extract::() .unwrap_err() .get_type(py) .is(&PyType::new::(py)) ); }); } } ================================================ FILE: malachite-nz/src/natural/conversion/serde.rs ================================================ // Copyright © 2026 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 crate::natural::{Natural, SerdeNatural}; use alloc::string::String; use core::convert::TryFrom; use malachite_base::num::conversion::traits::FromStringBase; impl From for SerdeNatural { #[inline] fn from(x: Natural) -> Self { Self(format!("{x:#x}")) } } impl TryFrom for Natural { type Error = String; #[inline] fn try_from(s: SerdeNatural) -> Result { if s.0.starts_with("0x") { Self::from_string_base(16, &s.0[2..]) .ok_or_else(|| format!("Unrecognized digits in {}", s.0)) } else { Err(format!("String '{}' does not start with '0x'", s.0)) } } } ================================================ FILE: malachite-nz/src/natural/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use core::cmp::Ordering::*; use core::ops::Mul; use malachite_base::num::arithmetic::traits::{CheckedSub, Parity, Pow}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::string::from_sci_string::{ cmp_half_helper, is_zero_helper, preprocess_sci_string, validate_helper, }; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::{FromSciString, FromStringBase}; use malachite_base::rounding_modes::RoundingMode::*; #[doc(hidden)] pub trait FromSciStringHelper: Sized { fn parse_int(cs: &[u8], base: u8) -> Option; fn up_1(self, neg: bool) -> Option; } impl FromSciStringHelper for Natural { fn parse_int(mut cs: &[u8], base: u8) -> Option { // if T is unsigned, from_string_base won't handle -0 let mut test_neg_zero = false; if let Some(&b'-') = cs.first() { test_neg_zero = true; } if test_neg_zero { if cs.len() == 1 { return None; } for &c in &cs[1..] { if c != b'0' { return None; } } Some(Self::ZERO) } else { if let Some(b'+') = cs.first() { cs = &cs[1..]; // If the string begins with a '+', the second character cannot be '+' or '-' match cs { [] | [b'+' | b'-', ..] => return None, _ => {} } } Self::from_string_base(base, core::str::from_utf8(cs).ok()?) } } fn up_1(self, neg: bool) -> Option { if neg { self.checked_sub(Self::ONE) } else { Some(self + Self::ONE) } } } pub(crate) fn from_sci_string_with_options_helper< T: From + FromSciStringHelper + Mul + Pow + Zero, >( s: &str, options: FromSciStringOptions, ) -> Option where for<'a> &'a T: Parity, { let (s, exponent) = preprocess_sci_string(s, options)?; if exponent >= 0 { let x = T::parse_int(&s, options.get_base())?; Some(x * T::from(options.get_base()).pow(exponent.unsigned_abs())) } else { let neg_exponent = usize::try_from(exponent.unsigned_abs()).ok()?; let len = s.len(); if len == 0 { return None; } let first = s[0]; let neg = first == b'-'; let sign = neg || first == b'+'; let rm = if neg { -options.get_rounding_mode() } else { options.get_rounding_mode() }; let sig_len = if sign { len - 1 } else { len }; if sig_len == 0 { return None; } if neg_exponent > sig_len { let s = if sign { &s[1..] } else { &s[..] }; return match rm { Down | Floor | Nearest => { validate_helper(s, options.get_base())?; Some(T::ZERO) } Up | Ceiling => { if is_zero_helper(s, options.get_base())? { Some(T::ZERO) } else { T::ZERO.up_1(neg) } } Exact => None, }; } let (before_e, after_e) = s.split_at(len - neg_exponent); let x = match before_e { &[] | &[b'-'] | &[b'+'] => T::ZERO, before_e => T::parse_int(before_e, options.get_base())?, }; if after_e.is_empty() { return Some(x); } match rm { Down | Floor => { validate_helper(after_e, options.get_base())?; Some(x) } Up | Ceiling => { if is_zero_helper(after_e, options.get_base())? { Some(x) } else { x.up_1(neg) } } Exact => { if is_zero_helper(after_e, options.get_base())? { Some(x) } else { None } } Nearest => match cmp_half_helper(after_e, options.get_base())? { Less => Some(x), Greater => x.up_1(neg), Equal => { if x.even() { Some(x) } else { x.up_1(neg) } } }, } } } impl FromSciString for Natural { /// Converts a string, possibly in scientfic notation, to a [`Natural`]. /// /// Use [`FromSciStringOptions`] to specify the base (from 2 to 36, inclusive) and the rounding /// mode, in case rounding is necessary because the string represents a non-integer. /// /// If the base is greater than 10, the higher digits are represented by the letters `'a'` /// through `'z'` or `'A'` through `'Z'`; the case doesn't matter and doesn't need to be /// consistent. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. If the base is /// 15 or greater, an ambiguity arises where it may not be clear whether `'e'` is a digit or an /// exponent indicator. To resolve this ambiguity, always use a `'+'` or `'-'` sign after the /// exponent indicator when the base is 15 or greater. /// /// The exponent itself is always parsed using base 10. /// /// Decimal (or other-base) points are allowed. These are most useful in conjunction with /// exponents, but they may be used on their own. If the string represents a non-integer, the /// rounding mode specified in `options` is used to round to an integer. /// /// If the string is unparseable, `None` is returned. `None` is also returned if the rounding /// mode in options is `Exact`, but rounding is necessary. /// /// # Worst-case complexity /// $T(n, m) = O(m^n n \log m (\log n + \log\log m))$ /// /// $M(n, m) = O(m^n n \log m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `options.base`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::FromSciStringOptions; /// use malachite_base::num::conversion::traits::FromSciString; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from_sci_string("123").unwrap(), 123); /// assert_eq!(Natural::from_sci_string("123.5").unwrap(), 124); /// assert_eq!(Natural::from_sci_string("-123.5"), None); /// assert_eq!(Natural::from_sci_string("1.23e10").unwrap(), 12300000000u64); /// /// let mut options = FromSciStringOptions::default(); /// assert_eq!( /// Natural::from_sci_string_with_options("123.5", options).unwrap(), /// 124 /// ); /// /// options.set_rounding_mode(Floor); /// assert_eq!( /// Natural::from_sci_string_with_options("123.5", options).unwrap(), /// 123 /// ); /// /// options = FromSciStringOptions::default(); /// options.set_base(16); /// assert_eq!( /// Natural::from_sci_string_with_options("ff", options).unwrap(), /// 255 /// ); /// /// options = FromSciStringOptions::default(); /// options.set_base(36); /// assert_eq!( /// Natural::from_sci_string_with_options("1e5", options).unwrap(), /// 1805 /// ); /// assert_eq!( /// Natural::from_sci_string_with_options("1e+5", options).unwrap(), /// 60466176 /// ); /// assert_eq!( /// Natural::from_sci_string_with_options("1e-5", options).unwrap(), /// 0 /// ); /// ``` #[inline] fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option { from_sci_string_with_options_helper(s, options) } } ================================================ FILE: malachite-nz/src/natural/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::Small; use crate::natural::Natural; use crate::platform::{Limb, MAX_DIGITS_PER_LIMB}; use core::str::FromStr; use malachite_base::num::arithmetic::traits::{ModPowerOf2, ShrRound}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::string::from_string::digit_from_display_byte; use malachite_base::num::conversion::traits::{Digits, ExactFrom, FromStringBase, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; impl FromStr for Natural { type Err = (); /// Converts an string to a [`Natural`]. /// /// If the string does not represent a valid [`Natural`], an `Err` is returned. To be valid, the /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`. Leading zeros /// are allowed. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from_str("123456").unwrap(), 123456); /// assert_eq!(Natural::from_str("00123456").unwrap(), 123456); /// assert_eq!(Natural::from_str("0").unwrap(), 0); /// /// assert!(Natural::from_str("").is_err()); /// assert!(Natural::from_str("a").is_err()); /// assert!(Natural::from_str("-5").is_err()); /// ``` #[inline] fn from_str(s: &str) -> Result { Self::from_string_base(10, s).ok_or(()) } } fn from_binary_str(s: &str) -> Option { let len = s.len(); if len <= usize::wrapping_from(Limb::WIDTH) { Limb::from_str_radix(s, 2).ok().map(Natural::from) } else { let mut xs = vec![0; len.shr_round(Limb::LOG_WIDTH, Ceiling).0]; let mut remaining = u64::wrapping_from(len & usize::wrapping_from(Limb::WIDTH_MASK)); let mut i = xs.len(); let mut x = xs.last_mut().unwrap(); if remaining != 0 { i -= 1; } for b in s.bytes() { if remaining == 0 { i -= 1; x = &mut xs[i]; remaining = Limb::WIDTH; } *x <<= 1; match b { b'1' => *x |= 1, b'0' => {} _ => return None, } remaining -= 1; } Some(Natural::from_owned_limbs_asc(xs)) } } fn from_oct_str(s: &str) -> Option { let len = s.len(); if len <= usize::wrapping_from(Limb::WIDTH / 3) { Limb::from_str_radix(s, 8).ok().map(Natural::from) } else { let bit_len = len.checked_mul(3).unwrap(); let mut xs = vec![0; bit_len.shr_round(Limb::LOG_WIDTH, Ceiling).0]; let mut remaining = u64::exact_from(bit_len) & Limb::WIDTH_MASK; let mut i = xs.len(); let mut x = xs.last_mut().unwrap(); if remaining != 0 { i -= 1; } for b in s.bytes() { let digit = digit_from_display_byte(b)?; if digit >= 8 { return None; } let digit = Limb::wrapping_from(digit); match remaining { 0 => { i -= 1; x = &mut xs[i]; *x = digit; remaining = Limb::WIDTH - 3; } 1 => { *x <<= 1; *x |= digit >> 2; i -= 1; x = &mut xs[i]; *x = digit & 3; remaining = Limb::WIDTH - 2; } 2 => { *x <<= 2; *x |= digit >> 1; i -= 1; x = &mut xs[i]; *x = digit & 1; remaining = Limb::WIDTH - 1; } _ => { *x <<= 3; *x |= digit; remaining -= 3; } } } Some(Natural::from_owned_limbs_asc(xs)) } } fn from_hex_str(s: &str) -> Option { let len = s.len(); if len <= usize::wrapping_from(Limb::WIDTH >> 2) { Limb::from_str_radix(s, 16).ok().map(Natural::from) } else { let mut xs = vec![0; len.shr_round(Limb::LOG_WIDTH - 2, Ceiling).0]; let mut remaining = u64::wrapping_from(len.mod_power_of_2(Limb::LOG_WIDTH - 2)) << 2; let mut i = xs.len(); let mut x = xs.last_mut().unwrap(); if remaining != 0 { i -= 1; } for b in s.bytes() { if remaining == 0 { i -= 1; x = &mut xs[i]; remaining = Limb::WIDTH; } *x <<= 4; let digit = digit_from_display_byte(b)?; if digit >= 16 { return None; } *x |= Limb::wrapping_from(digit); remaining -= 4; } Some(Natural::from_owned_limbs_asc(xs)) } } impl FromStringBase for Natural { /// Converts an string, in a specified base, to a [`Natural`]. /// /// If the string does not represent a valid [`Natural`], an `Err` is returned. To be valid, the /// string must be nonempty and only contain the [`char`]s `'0'` through `'9'`, `'a'` through /// `'z'`, and `'A'` through `'Z'`, with an optional single leading `'+'`; and only characters /// that represent digits smaller than the base are allowed. Leading zeros are always allowed. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::FromStringBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from_string_base(10, "123456").unwrap(), 123456); /// assert_eq!(Natural::from_string_base(10, "00123456").unwrap(), 123456); /// assert_eq!(Natural::from_string_base(16, "0").unwrap(), 0); /// assert_eq!( /// Natural::from_string_base(16, "deadbeef").unwrap(), /// 3735928559u32 /// ); /// assert_eq!( /// Natural::from_string_base(16, "deAdBeEf").unwrap(), /// 3735928559u32 /// ); /// /// assert!(Natural::from_string_base(10, "").is_none()); /// assert!(Natural::from_string_base(10, "a").is_none()); /// assert!(Natural::from_string_base(10, "-5").is_none()); /// assert!(Natural::from_string_base(2, "2").is_none()); /// ``` #[inline] fn from_string_base(base: u8, mut s: &str) -> Option { assert!((2..=36).contains(&base), "base out of range"); if s.is_empty() { None } else { match base { 2 => from_binary_str(s), 8 => from_oct_str(s), 16 => from_hex_str(s), 10 => { if s.len() < MAX_DIGITS_PER_LIMB { Limb::from_str(s).ok().map(|x| Self(Small(x))) } else { if let Some(prefix_s) = s.strip_prefix('+') { s = prefix_s; } Self::from_digits_desc( &10, s.bytes() .map(|b| if b >= b'0' { b - b'0' } else { u8::MAX }), ) } } _ => { for b in s.bytes() { let digit = digit_from_display_byte(b)?; if digit >= base { return None; } } Self::from_digits_desc( &u8::wrapping_from(base), s.bytes().map(|b| digit_from_display_byte(b).unwrap()), ) } } } } } ================================================ FILE: malachite-nz/src/natural/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`FromSciString`](malachite_base::num::conversion::traits::FromSciString). /// This is a trait for converting strings, possibly using scientific notation, to numbers. pub mod from_sci_string; /// Implementations of [`FromStr`](core::str::FromStr) and of /// [`FromStringBase`](malachite_base::num::conversion::traits::FromStringBase), a trait for /// converting strings in a specified base to numbers. pub mod from_string; /// Implementations of [`ToSci`](malachite_base::num::conversion::traits::ToSci), a trait for /// converting a number to string, possibly using scientific notation. pub mod to_sci; /// The [`BaseFmtWrapper`](to_string::BaseFmtWrapper) struct and implementations of /// [`Display`](core::fmt::Display), [`Debug`], [`Binary`](core::fmt::Binary), /// [`Octal`](core::fmt::Octal), [`LowerHex`](core::fmt::LowerHex), and /// [`UpperHex`](core::fmt::UpperHex), and of the /// [`ToStringBase`](malachite_base::num::conversion::traits::ToStringBase) trait, used for /// converting numbers to strings. pub mod to_string; ================================================ FILE: malachite-nz/src/natural/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::natural::arithmetic::log_base::log_base_helper_with_pow; use crate::natural::conversion::string::to_string::BaseFmtWrapper; use crate::natural::slice_trailing_zeros; use alloc::string::String; use core::fmt::{Display, Formatter, Write}; use malachite_base::num::arithmetic::traits::{ CheckedLogBase2, DivExact, DivRound, DivisibleBy, DivisibleByPowerOf2, FloorLogBase, FloorLogBasePowerOf2, Pow, ShrRound, }; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::string::options::{SciSizeOptions, ToSciOptions}; use malachite_base::num::conversion::string::to_sci::write_exponent; use malachite_base::num::conversion::string::to_string::{ digit_to_display_byte_lower, digit_to_display_byte_upper, }; use malachite_base::num::conversion::traits::{Digits, ExactFrom, ToSci}; use malachite_base::rounding_modes::RoundingMode::*; fn write_helper(x: &T, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result where for<'a> BaseFmtWrapper<&'a T>: Display, { let w = BaseFmtWrapper { x, base: options.get_base(), }; if options.get_lowercase() { Display::fmt(&w, f) } else { write!(f, "{w:#}") } } impl ToSci for Natural { /// Determines whether a [`Natural`] can be converted to a string using /// [`to_sci`](`Self::to_sci`) and a particular set of options. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// let mut options = ToSciOptions::default(); /// assert!(Natural::from(123u8).fmt_sci_valid(options)); /// assert!(Natural::from(u128::MAX).fmt_sci_valid(options)); /// // u128::MAX has more than 16 significant digits /// options.set_rounding_mode(Exact); /// assert!(!Natural::from(u128::MAX).fmt_sci_valid(options)); /// options.set_precision(50); /// assert!(Natural::from(u128::MAX).fmt_sci_valid(options)); /// ``` fn fmt_sci_valid(&self, options: ToSciOptions) -> bool { if *self == 0u32 || options.get_rounding_mode() != Exact { return true; } match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => true, SciSizeOptions::Precision(precision) => { let n_base = Self::from(options.get_base()); let log = self.floor_log_base(&n_base); if log < precision { return true; } let scale = log - precision + 1; if let Some(base_log) = options.get_base().checked_log_base_2() { self.divisible_by_power_of_2(base_log * scale) } else { self.divisible_by(n_base.pow(scale)) } } } } /// Converts a [`Natural`] to a string using a specified base, possibly formatting the number /// using scientific notation. /// /// See [`ToSciOptions`] for details on the available options. Note that setting /// `neg_exp_threshold` has no effect, since there is never a need to use negative exponents /// when representing a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the input /// must be rounded. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// format!("{}", Natural::from(u128::MAX).to_sci()), /// "3.402823669209385e38" /// ); /// assert_eq!( /// Natural::from(u128::MAX).to_sci().to_string(), /// "3.402823669209385e38" /// ); /// /// let n = Natural::from(123456u32); /// let mut options = ToSciOptions::default(); /// assert_eq!(format!("{}", n.to_sci_with_options(options)), "123456"); /// assert_eq!(n.to_sci_with_options(options).to_string(), "123456"); /// /// options.set_precision(3); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.23e5"); /// /// options.set_rounding_mode(Ceiling); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24e5"); /// /// options.set_e_uppercase(); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E5"); /// /// options.set_force_exponent_plus_sign(true); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E+5"); /// /// options = ToSciOptions::default(); /// options.set_base(36); /// assert_eq!(n.to_sci_with_options(options).to_string(), "2n9c"); /// /// options.set_uppercase(); /// assert_eq!(n.to_sci_with_options(options).to_string(), "2N9C"); /// /// options.set_base(2); /// options.set_precision(10); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.1110001e16"); /// /// options.set_include_trailing_zeros(true); /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.111000100e16"); /// ``` fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result { match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(0) => write_helper(self, f, options), SciSizeOptions::Scale(scale) => { write_helper(self, f, options)?; if options.get_include_trailing_zeros() { f.write_char('.')?; for _ in 0..scale { f.write_char('0')?; } } Ok(()) } SciSizeOptions::Precision(precision) => { let n_base = Self::from(options.get_base()); let (base_log, log, power, p) = if *self == 0u32 { // power and p unused (None, 0, Self::ZERO, 0) } else if let Some(base_log) = options.get_base().checked_log_base_2() { // power and p unused ( Some(base_log), self.floor_log_base_power_of_2(base_log), Self::ZERO, 0, ) } else { // We save base^p so that we can save some computation later let (log, _, power, p) = log_base_helper_with_pow(self, &n_base); (None, log, power, p) }; if log < precision { // no exponent write_helper(self, f, options)?; if options.get_include_trailing_zeros() { let extra_zeros = precision - log - 1; if extra_zeros != 0 { f.write_char('.')?; for _ in 0..extra_zeros { f.write_char('0')?; } } } Ok(()) } else { // exponent let mut e = log; let scale = log - precision + 1; let shifted = if let Some(base_log) = base_log { self.shr_round(base_log * scale, options.get_rounding_mode()) .0 } else { let n = if precision > log >> 1 { n_base.pow(scale) } else if p >= scale { power.div_exact(n_base.pow(p - scale)) } else { // Not sure if this ever happens assert!(p == scale + 1); power * n_base }; self.div_round(n, options.get_rounding_mode()).0 }; let mut chars = shifted.to_digits_desc(&options.get_base()); let mut len = chars.len(); let p = usize::exact_from(precision); if len > p { // rounded up to a power of the base, need to reduce precision assert_eq!(chars.pop().unwrap(), 0); len -= 1; e += 1; } assert_eq!(len, p); if !options.get_include_trailing_zeros() { chars.truncate(len - slice_trailing_zeros(&chars)); } if options.get_lowercase() { for digit in &mut chars { *digit = digit_to_display_byte_lower(*digit).unwrap(); } } else { for digit in &mut chars { *digit = digit_to_display_byte_upper(*digit).unwrap(); } } len = chars.len(); if len != 1 { chars.push(b'0'); chars.copy_within(1..len, 2); chars[1] = b'.'; } f.write_str(&String::from_utf8(chars).unwrap())?; write_exponent(f, options, e) } } } } } ================================================ FILE: malachite-nz/src/natural/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::conversion::digits::general_digits::{ limbs_digit_count, limbs_to_digits_small_base_no_alg_specified, }; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::platform::Limb; use alloc::string::String; #[cfg(feature = "test_build")] use core::fmt::Write; use core::fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, Result, UpperHex}; #[cfg(feature = "test_build")] use itertools::Itertools; use malachite_base::num::arithmetic::traits::{DivRound, Parity, ShrRound}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::string::to_string::{ BaseFmtWrapper as BaseBaseFmtWrapper, digit_to_display_byte_lower, digit_to_display_byte_upper, }; #[cfg(feature = "test_build")] use malachite_base::num::conversion::traits::PowerOf2DigitIterable; use malachite_base::num::conversion::traits::{Digits, ExactFrom, ToStringBase, WrappingFrom}; #[cfg(feature = "test_build")] use malachite_base::num::logic::traits::{BitIterable, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::*; /// A `struct` that allows for formatting a [`Natural`] or [`Integer`](crate::integer::Integer) and /// rendering its digits in a specified base. #[derive(Clone, Eq, Hash, PartialEq)] pub struct BaseFmtWrapper { pub(crate) x: T, pub(crate) base: u8, } impl BaseFmtWrapper { /// Creates a new `BaseFmtWrapper`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// use malachite_nz::natural::Natural; /// /// let n = Natural::from(1000000000u32); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{}", x), "gjdgxs"); /// assert_eq!(format!("{:#}", x), "GJDGXS"); /// /// let n = Integer::from(-1000000000); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{}", x), "-gjdgxs"); /// assert_eq!(format!("{:#}", x), "-GJDGXS"); /// ``` pub fn new(x: T, base: u8) -> Self { assert!((2..=36).contains(&base), "base out of range"); Self { x, base } } /// Recovers the value from a `BaseFmtWrapper`. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// BaseFmtWrapper::new(Natural::from(1000000000u32), 36).unwrap(), /// 1000000000 /// ); /// ``` #[allow(clippy::missing_const_for_fn)] pub fn unwrap(self) -> T { self.x } } impl Display for BaseFmtWrapper<&Natural> { /// Writes a wrapped [`Natural`] to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. Using the /// `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// use malachite_nz::natural::Natural; /// /// let n = Natural::from(1000000000u32); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{}", x), "gjdgxs"); /// assert_eq!(format!("{:#}", x), "GJDGXS"); /// assert_eq!(format!("{:010}", x), "0000gjdgxs"); /// assert_eq!(format!("{:#010}", x), "0000GJDGXS"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { assert!((2..=36).contains(&self.base), "base out of range"); if let Natural(Small(x)) = self.x { Display::fmt(&BaseBaseFmtWrapper::new(*x, self.base), f) } else { let mut digits = self.x.to_digits_desc(&u8::wrapping_from(self.base)); if f.alternate() { for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } } else { for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } } f.pad_integral(true, "", core::str::from_utf8(&digits).unwrap()) } } } impl Debug for BaseFmtWrapper<&Natural> { /// Writes a wrapped [`Natural`] to a string using a specified base. /// /// If the base is greater than 10, lowercase alphabetic letters are used by default. Using the /// `#` flag switches to uppercase letters. Padding with zeros works as usual. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; /// use malachite_nz::natural::Natural; /// /// let n = Natural::from(1000000000u32); /// let x = BaseFmtWrapper::new(&n, 36); /// assert_eq!(format!("{:?}", x), "gjdgxs"); /// assert_eq!(format!("{:#?}", x), "GJDGXS"); /// assert_eq!(format!("{:010?}", x), "0000gjdgxs"); /// assert_eq!(format!("{:#010?}", x), "0000GJDGXS"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } impl ToStringBase for Natural { /// Converts a [`Natural`] to a [`String`] using a specified base. /// /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`. Digits from 10 to 35 become the /// lowercase [`char`]s `'a'` to `'z'`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(1000u32).to_string_base(2), "1111101000"); /// assert_eq!(Natural::from(1000u32).to_string_base(10), "1000"); /// assert_eq!(Natural::from(1000u32).to_string_base(36), "rs"); /// ``` fn to_string_base(&self, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if let Self(Small(x)) = self { x.to_string_base(base) } else { let mut digits = self.to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } String::from_utf8(digits).unwrap() } } /// Converts a [`Natural`] to a [`String`] using a specified base. /// /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`. Digits from 10 to 35 become the /// uppercase [`char`]s `'A'` to `'Z'`. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ToStringBase; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(1000u32).to_string_base_upper(2), "1111101000"); /// assert_eq!(Natural::from(1000u32).to_string_base_upper(10), "1000"); /// assert_eq!(Natural::from(1000u32).to_string_base_upper(36), "RS"); /// ``` fn to_string_base_upper(&self, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); if let Self(Small(x)) = self { x.to_string_base_upper(base) } else { let mut digits = self.to_digits_desc(&base); for digit in &mut digits { *digit = digit_to_display_byte_upper(*digit).unwrap(); } String::from_utf8(digits).unwrap() } } } impl Display for Natural { /// Converts a [`Natural`] to a [`String`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_string(), "0"); /// assert_eq!(Natural::from(123u32).to_string(), "123"); /// assert_eq!( /// Natural::from_str("1000000000000").unwrap().to_string(), /// "1000000000000" /// ); /// assert_eq!(format!("{:05}", Natural::from(123u32)), "00123"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { match self { Self(Small(x)) => Display::fmt(x, f), Self(Large(xs)) => { let mut digits = vec![0; usize::exact_from(limbs_digit_count(xs, 10))]; let mut xs = xs.clone(); let len = limbs_to_digits_small_base_no_alg_specified(&mut digits, 10, &mut xs); digits.truncate(len); for digit in &mut digits { *digit = digit_to_display_byte_lower(*digit).unwrap(); } f.pad_integral(true, "", core::str::from_utf8(&digits).unwrap()) } } } } impl Debug for Natural { /// Converts a [`Natural`] to a [`String`]. /// /// This is the same as the [`Display::fmt`] implementation. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_debug_string(), "0"); /// assert_eq!(Natural::from(123u32).to_debug_string(), "123"); /// assert_eq!( /// Natural::from_str("1000000000000") /// .unwrap() /// .to_debug_string(), /// "1000000000000" /// ); /// assert_eq!(format!("{:05?}", Natural::from(123u32)), "00123"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } #[cfg(feature = "test_build")] pub struct NaturalAlt(pub Natural); #[cfg(feature = "test_build")] pub struct NaturalAlt2(pub Natural); #[cfg(feature = "test_build")] impl Binary for NaturalAlt { fn fmt(&self, f: &mut Formatter) -> Result { if let Natural(Small(x)) = self.0 { Binary::fmt(&x, f) } else { if f.alternate() { f.write_str("0b")?; } if let Some(width) = f.width() { let mut len = usize::exact_from(self.0.significant_bits()); if f.alternate() { len += 2; } for _ in 0..width.saturating_sub(len) { f.write_char('0')?; } } for bit in self.0.bits().rev() { f.write_char(if bit { '1' } else { '0' })?; } Ok(()) } } } #[cfg(feature = "test_build")] impl Binary for NaturalAlt2 { fn fmt(&self, f: &mut Formatter) -> Result { match &self.0 { Natural(Small(x)) => Binary::fmt(x, f), Natural(Large(xs)) => { let (xs_last, xs_init) = xs.split_last().unwrap(); let width = if let Some(width) = f.width() { width.saturating_sub(xs_init.len() << Limb::LOG_WIDTH) } else { 0 }; let mut result = if f.alternate() { write!(f, "{xs_last:#0width$b}") } else { write!(f, "{xs_last:0width$b}") }; for x in xs_init.iter().rev() { #[cfg(feature = "32_bit_limbs")] { result = write!(f, "{x:032b}"); } #[cfg(not(feature = "32_bit_limbs"))] { result = write!(f, "{x:064b}"); } } result } } } } impl Binary for Natural { /// Converts a [`Natural`] to a binary [`String`]. /// /// Using the `#` format flag prepends `"0b"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_binary_string(), "0"); /// assert_eq!(Natural::from(123u32).to_binary_string(), "1111011"); /// assert_eq!( /// Natural::from_str("1000000000000") /// .unwrap() /// .to_binary_string(), /// "1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:011b}", Natural::from(123u32)), "00001111011"); /// /// assert_eq!(format!("{:#b}", Natural::ZERO), "0b0"); /// assert_eq!(format!("{:#b}", Natural::from(123u32)), "0b1111011"); /// assert_eq!( /// format!("{:#b}", Natural::from_str("1000000000000").unwrap()), /// "0b1110100011010100101001010001000000000000" /// ); /// assert_eq!(format!("{:#011b}", Natural::from(123u32)), "0b001111011"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { match self { Self(Small(x)) => Binary::fmt(x, f), Self(Large(xs)) => { let mut bits = vec![0; usize::exact_from(limbs_significant_bits(xs))]; let mut limbs = xs.iter(); let mut limb = *limbs.next().unwrap(); let mut remaining_bits = Limb::WIDTH; for bit in bits.iter_mut().rev() { if remaining_bits == 0 { remaining_bits = Limb::WIDTH; limb = *limbs.next().unwrap(); } *bit = if limb.even() { b'0' } else { b'1' }; limb >>= 1; remaining_bits -= 1; } f.pad_integral(true, "0b", core::str::from_utf8(&bits).unwrap()) } } } } #[cfg(feature = "test_build")] impl Octal for NaturalAlt { fn fmt(&self, f: &mut Formatter) -> Result { if let Natural(Small(x)) = self.0 { Octal::fmt(&x, f) } else { if f.alternate() { f.write_str("0o")?; } if let Some(width) = f.width() { let mut len = usize::exact_from(self.0.significant_bits().div_round(3, Ceiling).0); if f.alternate() { len += 2; } for _ in 0..width.saturating_sub(len) { f.write_char('0')?; } } for digit in PowerOf2DigitIterable::::power_of_2_digits(&self.0, 3).rev() { f.write_char(char::from(digit_to_display_byte_lower(digit).unwrap()))?; } Ok(()) } } } #[cfg(feature = "test_build")] #[cfg(feature = "32_bit_limbs")] fn oz_fmt(f: &mut Formatter, x: Limb) -> Result { write!(f, "{x:08o}") } #[cfg(feature = "test_build")] #[cfg(not(feature = "32_bit_limbs"))] fn oz_fmt(f: &mut Formatter, x: Limb) -> Result { write!(f, "{x:016o}") } #[cfg(feature = "test_build")] impl Octal for NaturalAlt2 { fn fmt(&self, f: &mut Formatter) -> Result { match &self.0 { Natural(Small(x)) => Octal::fmt(x, f), Natural(Large(xs)) => { if f.alternate() { f.write_str("0o")?; } if let Some(width) = f.width() { let mut len = usize::exact_from(limbs_significant_bits(xs).div_round(3, Ceiling).0); if f.alternate() { len += 2; } for _ in 0..width.saturating_sub(len) { f.write_char('0')?; } } let mut triple_r = xs.len() % 3; if triple_r == 0 { triple_r = 3; } let mut result; let last_i = xs.len() - 1; const W_1_2: u64 = Limb::WIDTH >> 1; const W_1_4: u64 = Limb::WIDTH >> 2; const W_3_4: u64 = W_1_4 * 3; const MASK: Limb = (1 << W_3_4) - 1; match triple_r { 1 => { let x_2 = xs[last_i]; let y = x_2 >> W_3_4; if y == 0 { result = write!(f, "{:o}", x_2 & MASK); } else { write!(f, "{y:o}").unwrap(); result = oz_fmt(f, x_2 & MASK); } } 2 => { let x_1 = xs[last_i]; let x_2 = xs[last_i - 1]; let y = x_1 >> W_1_2; if y == 0 { write!(f, "{:o}", ((x_1 << W_1_4) & MASK) | (x_2 >> W_3_4)).unwrap(); } else { write!(f, "{y:o}").unwrap(); oz_fmt(f, ((x_1 << W_1_4) & MASK) | (x_2 >> W_3_4)).unwrap(); } result = oz_fmt(f, x_2 & MASK); } _ => { let x_0 = xs[last_i]; let x_1 = xs[last_i - 1]; let x_2 = xs[last_i - 2]; let y = x_0 >> W_1_4; if y == 0 { write!(f, "{:o}", ((x_0 << W_1_2) & MASK) | (x_1 >> W_1_2)).unwrap(); } else { write!(f, "{y:o}").unwrap(); oz_fmt(f, ((x_0 << W_1_2) & MASK) | (x_1 >> W_1_2)).unwrap(); } oz_fmt(f, ((x_1 << W_1_4) & MASK) | (x_2 >> W_3_4)).unwrap(); result = oz_fmt(f, x_2 & MASK); } } for mut chunk in &xs.iter().rev().skip(triple_r).chunks(3) { let x_0 = chunk.next().unwrap(); let x_1 = chunk.next().unwrap(); let x_2 = chunk.next().unwrap(); oz_fmt(f, x_0 >> W_1_4).unwrap(); oz_fmt(f, ((x_0 << W_1_2) & MASK) | (x_1 >> W_1_2)).unwrap(); oz_fmt(f, ((x_1 << W_1_4) & MASK) | (x_2 >> W_3_4)).unwrap(); result = oz_fmt(f, x_2 & MASK); } result } } } } impl Octal for Natural { /// Converts a [`Natural`] to an octal [`String`]. /// /// Using the `#` format flag prepends `"0o"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToOctalString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_octal_string(), "0"); /// assert_eq!(Natural::from(123u32).to_octal_string(), "173"); /// assert_eq!( /// Natural::from_str("1000000000000") /// .unwrap() /// .to_octal_string(), /// "16432451210000" /// ); /// assert_eq!(format!("{:07o}", Natural::from(123u32)), "0000173"); /// /// assert_eq!(format!("{:#o}", Natural::ZERO), "0o0"); /// assert_eq!(format!("{:#o}", Natural::from(123u32)), "0o173"); /// assert_eq!( /// format!("{:#o}", Natural::from_str("1000000000000").unwrap()), /// "0o16432451210000" /// ); /// assert_eq!(format!("{:#07o}", Natural::from(123u32)), "0o00173"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { match self { Self(Small(x)) => Octal::fmt(x, f), Self(Large(xs)) => { let mut digits = vec![0; usize::exact_from(limbs_significant_bits(xs).div_round(3, Ceiling).0)]; let mut limbs = xs.iter(); let mut remaining_bits = Limb::WIDTH; let mut limb = *limbs.next().unwrap(); for digit in digits.iter_mut().rev() { if remaining_bits >= 3 { *digit = digit_to_display_byte_lower(u8::wrapping_from(limb & 7)).unwrap(); remaining_bits -= 3; limb >>= 3; } else { match remaining_bits { 0 => { limb = *limbs.next().unwrap(); *digit = digit_to_display_byte_lower(u8::wrapping_from(limb & 7)) .unwrap(); remaining_bits = Limb::WIDTH - 3; limb >>= 3; } 1 => { let previous_limb = limb; limb = *limbs.next().unwrap_or(&0); *digit = digit_to_display_byte_lower(u8::wrapping_from( ((limb & 3) << 1) | previous_limb, )) .unwrap(); remaining_bits = Limb::WIDTH - 2; limb >>= 2; } _ => { let previous_limb = limb; limb = *limbs.next().unwrap_or(&0); *digit = digit_to_display_byte_lower(u8::wrapping_from( ((limb & 1) << 2) | previous_limb, )) .unwrap(); remaining_bits = Limb::WIDTH - 1; limb >>= 1; } } } } f.pad_integral(true, "0o", core::str::from_utf8(&digits).unwrap()) } } } } #[cfg(feature = "test_build")] impl LowerHex for NaturalAlt { fn fmt(&self, f: &mut Formatter) -> Result { if let Natural(Small(x)) = self.0 { LowerHex::fmt(&x, f) } else { if f.alternate() { f.write_str("0x")?; } if let Some(width) = f.width() { let mut len = usize::exact_from(self.0.significant_bits().shr_round(2, Ceiling).0); if f.alternate() { len += 2; } for _ in 0..width.saturating_sub(len) { f.write_char('0')?; } } for digit in PowerOf2DigitIterable::::power_of_2_digits(&self.0, 4).rev() { f.write_char(char::from(digit_to_display_byte_lower(digit).unwrap()))?; } Ok(()) } } } #[cfg(feature = "test_build")] impl LowerHex for NaturalAlt2 { fn fmt(&self, f: &mut Formatter) -> Result { match &self.0 { Natural(Small(x)) => LowerHex::fmt(x, f), Natural(Large(xs)) => { let (xs_last, xs_init) = xs.split_last().unwrap(); let width = if let Some(width) = f.width() { width.saturating_sub(xs_init.len() << Limb::LOG_WIDTH >> 2) } else { 0 }; let mut result = if f.alternate() { write!(f, "{xs_last:#0width$x}") } else { write!(f, "{xs_last:0width$x}") }; for x in xs_init.iter().rev() { #[cfg(feature = "32_bit_limbs")] { result = write!(f, "{x:08x}"); } #[cfg(not(feature = "32_bit_limbs"))] { result = write!(f, "{x:016x}"); } } result } } } } impl LowerHex for Natural { /// Converts a [`Natural`] to a hexadecimal [`String`] using lowercase characters. /// /// Using the `#` format flag prepends `"0x"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToLowerHexString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_lower_hex_string(), "0"); /// assert_eq!(Natural::from(123u32).to_lower_hex_string(), "7b"); /// assert_eq!( /// Natural::from_str("1000000000000") /// .unwrap() /// .to_lower_hex_string(), /// "e8d4a51000" /// ); /// assert_eq!(format!("{:07x}", Natural::from(123u32)), "000007b"); /// /// assert_eq!(format!("{:#x}", Natural::ZERO), "0x0"); /// assert_eq!(format!("{:#x}", Natural::from(123u32)), "0x7b"); /// assert_eq!( /// format!("{:#x}", Natural::from_str("1000000000000").unwrap()), /// "0xe8d4a51000" /// ); /// assert_eq!(format!("{:#07x}", Natural::from(123u32)), "0x0007b"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { match self { Self(Small(x)) => LowerHex::fmt(x, f), Self(Large(xs)) => { const DIGITS_PER_LIMB: u64 = Limb::WIDTH >> 2; let mut digits = vec![0; usize::exact_from(limbs_significant_bits(xs).shr_round(2, Ceiling).0)]; let mut limbs = xs.iter(); let mut limb = *limbs.next().unwrap(); let mut remaining_digits = DIGITS_PER_LIMB; for digit in digits.iter_mut().rev() { if remaining_digits == 0 { remaining_digits = DIGITS_PER_LIMB; limb = *limbs.next().unwrap(); } *digit = digit_to_display_byte_lower(u8::wrapping_from(limb & 15)).unwrap(); limb >>= 4; remaining_digits -= 1; } f.pad_integral(true, "0x", core::str::from_utf8(&digits).unwrap()) } } } } impl UpperHex for Natural { /// Converts a [`Natural`] to a hexadecimal [`String`] using uppercase characters. /// /// Using the `#` format flag prepends `"0x"` to the string. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use core::str::FromStr; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToUpperHexString; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.to_upper_hex_string(), "0"); /// assert_eq!(Natural::from(123u32).to_upper_hex_string(), "7B"); /// assert_eq!( /// Natural::from_str("1000000000000") /// .unwrap() /// .to_upper_hex_string(), /// "E8D4A51000" /// ); /// assert_eq!(format!("{:07X}", Natural::from(123u32)), "000007B"); /// /// assert_eq!(format!("{:#X}", Natural::ZERO), "0x0"); /// assert_eq!(format!("{:#X}", Natural::from(123u32)), "0x7B"); /// assert_eq!( /// format!("{:#X}", Natural::from_str("1000000000000").unwrap()), /// "0xE8D4A51000" /// ); /// assert_eq!(format!("{:#07X}", Natural::from(123u32)), "0x0007B"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { match self { Self(Small(x)) => UpperHex::fmt(x, f), Self(Large(xs)) => { const DIGITS_PER_LIMB: u64 = Limb::WIDTH >> 2; let mut digits = vec![0; usize::exact_from(limbs_significant_bits(xs).shr_round(2, Ceiling).0)]; let mut limbs = xs.iter(); let mut limb = *limbs.next().unwrap(); let mut remaining_digits = DIGITS_PER_LIMB; for digit in digits.iter_mut().rev() { if remaining_digits == 0 { remaining_digits = DIGITS_PER_LIMB; limb = *limbs.next().unwrap(); } *digit = digit_to_display_byte_upper(u8::wrapping_from(limb & 15)).unwrap(); limb >>= 4; remaining_digits -= 1; } f.pad_integral(true, "0x", core::str::from_utf8(&digits).unwrap()) } } } } ================================================ FILE: malachite-nz/src/natural/conversion/to_limbs.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::ops::Index; use core::slice; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; /// A double-ended iterator over the [limbs](crate#limbs) of a [`Natural`]. /// /// The forward order is ascending (least-significant first). The iterator does not iterate over any /// implicit leading zero limbs. /// /// This struct also supports retrieving limbs by index. This functionality is completely /// independent of the iterator's state. Indexing the implicit leading zero limbs is allowed. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct LimbIterator<'a> { pub(crate) n: &'a Natural, pub(crate) limb_count: usize, pub(crate) remaining: usize, // If `n` is nonzero, this index initially points to the least-significant limb, and is // incremented by next(). pub(crate) i: u64, // If `n` is nonzero, this index initially points to the most-significant limb, and is // decremented by next_back(). pub(crate) j: u64, } impl Iterator for LimbIterator<'_> { type Item = Limb; /// A function to iterate through the [limbs](crate#limbs) of a [`Natural`] in ascending order /// (least-significant first). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::ZERO.limbs().next(), None); /// /// // 10^12 = 232 * 2^32 + 3567587328 /// let trillion = Natural::from(10u32).pow(12); /// let mut limbs = trillion.limbs(); /// assert_eq!(limbs.next(), Some(3567587328)); /// assert_eq!(limbs.next(), Some(232)); /// assert_eq!(limbs.next(), None); /// } /// ``` fn next(&mut self) -> Option { if self.remaining != 0 { let limb = match self.n { Natural(Small(small)) => *small, Natural(Large(limbs)) => limbs[usize::exact_from(self.i)], }; if self.i != self.j { self.i += 1; } self.remaining -= 1; Some(limb) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for LimbIterator<'_> { /// A function to iterate through the [limbs](crate#limbs) of a [`Natural`] in descending order /// (most-significant first). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::ZERO.limbs().next_back(), None); /// /// // 10^12 = 232 * 2^32 + 3567587328 /// let trillion = Natural::from(10u32).pow(12); /// let mut limbs = trillion.limbs(); /// assert_eq!(limbs.next_back(), Some(232)); /// assert_eq!(limbs.next_back(), Some(3567587328)); /// assert_eq!(limbs.next_back(), None); /// } /// ``` fn next_back(&mut self) -> Option { if self.remaining != 0 { let limb = match self.n { Natural(Small(small)) => *small, Natural(Large(limbs)) => limbs[usize::exact_from(self.j)], }; if self.j != self.i { self.j -= 1; } self.remaining -= 1; Some(limb) } else { None } } } impl ExactSizeIterator for LimbIterator<'_> {} impl Index for LimbIterator<'_> { type Output = Limb; /// A function to retrieve a [`Natural`]'s [limbs](crate#limbs) by index. /// /// The index is the power of $2^W$ of which the limbs is a coefficient, where $W$ is the width /// of a limb. Indexing at or above the limb count returns zeros. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert_eq!(Natural::ZERO.limbs()[0], 0); /// /// // 10^12 = 232 * 2^32 + 3567587328 /// let trillion = Natural::from(10u32).pow(12); /// let limbs = trillion.limbs(); /// assert_eq!(limbs[0], 3567587328); /// assert_eq!(limbs[1], 232); /// assert_eq!(limbs[2], 0); /// assert_eq!(limbs[100], 0); /// } /// ``` fn index(&self, index: usize) -> &Limb { if index >= self.limb_count { &0 } else { match self.n { Natural(Small(small)) => small, Natural(Large(limbs)) => limbs.index(index), } } } } impl LimbIterator<'_> { // TODO document and test #[allow(clippy::missing_const_for_fn)] pub fn most_significant(&self) -> Option { match self.n { Natural(Small(0)) => None, Natural(Small(small)) => Some(*small), Natural(Large(limbs)) => limbs.last().copied(), } } } impl Natural { /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that /// less-significant limbs have lower indices in the output vector. /// /// There are no trailing zero limbs. /// /// This function borrows the [`Natural`]. If taking ownership is possible instead, /// [`into_limbs_asc`](Self::into_limbs_asc) is more efficient. /// /// This function is more efficient than [`to_limbs_desc`](Self::to_limbs_desc). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.to_limbs_asc().is_empty()); /// assert_eq!(Natural::from(123u32).to_limbs_asc(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).to_limbs_asc(), /// &[3567587328, 232] /// ); /// } /// ``` pub fn to_limbs_asc(&self) -> Vec { match self { &Self::ZERO => Vec::new(), Self(Small(small)) => vec![*small], Self(Large(limbs)) => limbs.clone(), } } /// Returns the [limbs](crate#limbs) of a [`Natural`] in descending order, so that /// less-significant limbs have higher indices in the output vector. /// /// There are no leading zero limbs. /// /// This function borrows the [`Natural`]. If taking ownership is possible instead, /// [`into_limbs_desc`](Self::into_limbs_desc) is more efficient. /// /// This function is less efficient than [`to_limbs_asc`](Self::to_limbs_asc). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.to_limbs_desc().is_empty()); /// assert_eq!(Natural::from(123u32).to_limbs_desc(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).to_limbs_desc(), /// &[232, 3567587328] /// ); /// } /// ``` pub fn to_limbs_desc(&self) -> Vec { match self { &Self::ZERO => Vec::new(), Self(Small(small)) => vec![*small], Self(Large(limbs)) => limbs.iter().copied().rev().collect(), } } /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that /// less-significant limbs have lower indices in the output vector. /// /// There are no trailing zero limbs. /// /// This function takes ownership of the [`Natural`]. If it's necessary to borrow instead, use /// [`to_limbs_asc`](Self::to_limbs_asc). /// /// This function is more efficient than [`into_limbs_desc`](Self::into_limbs_desc). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.into_limbs_asc().is_empty()); /// assert_eq!(Natural::from(123u32).into_limbs_asc(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).into_limbs_asc(), /// &[3567587328, 232] /// ); /// } /// ``` pub fn into_limbs_asc(self) -> Vec { match self { Self::ZERO => Vec::new(), Self(Small(small)) => vec![small], Self(Large(limbs)) => limbs, } } /// Returns the [limbs](crate#limbs) of a [`Natural`], in descending order, so that /// less-significant limbs have higher indices in the output vector. /// /// There are no leading zero limbs. /// /// This function takes ownership of the [`Natural`]. If it's necessary to borrow instead, use /// [`to_limbs_desc`](Self::to_limbs_desc). /// /// This function is less efficient than [`into_limbs_asc`](Self::into_limbs_asc). /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.into_limbs_desc().is_empty()); /// assert_eq!(Natural::from(123u32).into_limbs_desc(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).into_limbs_desc(), /// &[232, 3567587328] /// ); /// } /// ``` pub fn into_limbs_desc(self) -> Vec { match self { Self::ZERO => Vec::new(), Self(Small(small)) => vec![small], Self(Large(mut limbs)) => { limbs.reverse(); limbs } } } /// Returns the [limbs](crate#limbs) of a [`Natural`], in ascending order, so that /// less-significant limbs have lower indices in the output slice. /// /// There are no trailing zero limbs. /// /// This function borrows the [`Natural`]. There is no descending order counterpoint, but /// [`to_limbs_desc`](Self::to_limbs_desc) may be used instead. /// /// This function is more efficient than [`to_limbs_asc`](Self::to_limbs_asc) because it borrows /// the underlying memory directly. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.as_limbs_asc().is_empty()); /// assert_eq!(Natural::from(123u32).as_limbs_asc(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).as_limbs_asc(), /// &[3567587328, 232] /// ); /// } /// ``` pub fn as_limbs_asc(&self) -> &[Limb] { match self { Self(Small(0)) => &[], Self(Small(small)) => slice::from_ref(small), Self(Large(limbs)) => limbs, } } /// Returns a double-ended iterator over the [limbs](crate#limbs) of a [`Natural`]. /// /// The forward order is ascending, so that less-significant limbs appear first. There are no /// trailing zero limbs going forward, or leading zeros going backward. /// /// If it's necessary to get a [`Vec`] of all the limbs, consider using /// [`to_limbs_asc`](Self::to_limbs_asc), [`to_limbs_desc`](Self::to_limbs_desc), /// [`into_limbs_asc`](Self::into_limbs_asc), or [`into_limbs_desc`](Self::into_limbs_desc) /// instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::integers::PrimitiveInt; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_nz::platform::Limb; /// /// if Limb::WIDTH == u32::WIDTH { /// assert!(Natural::ZERO.limbs().next().is_none()); /// assert_eq!(Natural::from(123u32).limbs().collect_vec(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).limbs().collect_vec(), /// &[3567587328, 232] /// ); /// /// assert!(Natural::ZERO.limbs().next_back().is_none()); /// assert_eq!(Natural::from(123u32).limbs().rev().collect_vec(), &[123]); /// // 10^12 = 232 * 2^32 + 3567587328 /// assert_eq!( /// Natural::from(10u32).pow(12).limbs().rev().collect_vec(), /// &[232, 3567587328] /// ); /// } /// ``` pub fn limbs(&self) -> LimbIterator<'_> { let limb_count = self.limb_count(); let limb_count_usize = usize::exact_from(limb_count); LimbIterator { n: self, limb_count: limb_count_usize, remaining: limb_count_usize, i: 0, j: limb_count.saturating_sub(1), } } } ================================================ FILE: malachite-nz/src/natural/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::basic::traits::{One, Zero}; /// Generates all [`Natural`]s in a finite interval. /// /// This `struct` is created by [`exhaustive_natural_range`] and /// [`exhaustive_natural_inclusive_range`]; see their documentation for more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExhaustiveNaturalRange { a: Natural, b: Natural, } impl Iterator for ExhaustiveNaturalRange { type Item = Natural; fn next(&mut self) -> Option { if self.a == self.b { None } else { let result = self.a.clone(); self.a += Natural::ONE; Some(result) } } } impl DoubleEndedIterator for ExhaustiveNaturalRange { fn next_back(&mut self) -> Option { if self.a == self.b { None } else { self.b -= Natural::ONE; Some(self.b.clone()) } } } /// Generates all [`Natural`]s greater than or equal to some [`Natural`], in ascending order. /// /// This `struct` is created by [`exhaustive_natural_range_to_infinity`]; see its documentation for /// more. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct ExhaustiveNaturalRangeToInfinity { a: Natural, } impl Iterator for ExhaustiveNaturalRangeToInfinity { type Item = Natural; fn next(&mut self) -> Option { let result = self.a.clone(); self.a += Natural::ONE; Some(result) } } /// Generates all [`Natural`]s in ascending order. /// /// The output is $(k)_{k=0}^{\infty}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the least-significant limb of the previously-generated value is /// `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::natural::exhaustive::exhaustive_naturals; /// /// assert_eq!( /// prefix_to_string(exhaustive_naturals(), 10), /// "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]" /// ); /// ``` #[inline] pub const fn exhaustive_naturals() -> ExhaustiveNaturalRangeToInfinity { exhaustive_natural_range_to_infinity(Natural::ZERO) } /// Generates all positive [`Natural`]s in ascending order. /// /// The output is $(k)_{k=1}^{\infty}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the least-significant limb of the previously-generated value is /// `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::natural::exhaustive::exhaustive_positive_naturals; /// /// assert_eq!( /// prefix_to_string(exhaustive_positive_naturals(), 10), /// "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_positive_naturals() -> ExhaustiveNaturalRangeToInfinity { exhaustive_natural_range_to_infinity(Natural::ONE) } /// Generates all [`Natural`]s in the half-open interval $[a, b)$, in ascending order. /// /// `a` must be less than or equal to `b`. If `a` and `b` are equal, the range is empty. To generate /// all [`Natural`]s in an infinite interval, use [`exhaustive_natural_range_to_infinity`]. /// /// The output is $(k)_{k=a}^{b-1}$. /// /// The output length is $b - a$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the least-significant limb of the previously-generated value is /// `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::exhaustive::exhaustive_natural_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// exhaustive_natural_range(Natural::from(5u32), Natural::from(10u32)) /// .collect_vec() /// .to_debug_string(), /// "[5, 6, 7, 8, 9]" /// ) /// ``` #[inline] pub fn exhaustive_natural_range(a: Natural, b: Natural) -> ExhaustiveNaturalRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); ExhaustiveNaturalRange { a, b } } /// Generates all [`Natural`]s in the closed interval $[a, b]$, in ascending order. /// /// `a` must be less than or equal to `b`. If `a` and `b` are equal, the range contains a single /// element. To generate all [`Natural`]s in an infinite interval, use /// [`exhaustive_natural_range_to_infinity`]. /// /// The output is $(k)_{k=a}^{b}$. /// /// The output length is $b - a + 1$. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the least-significant limb of the previously-generated value is /// `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Panics /// Panics if $a>b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::exhaustive::exhaustive_natural_inclusive_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// exhaustive_natural_inclusive_range(Natural::from(5u32), Natural::from(10u32)) /// .collect_vec() /// .to_debug_string(), /// "[5, 6, 7, 8, 9, 10]" /// ) /// ``` #[inline] pub fn exhaustive_natural_inclusive_range(a: Natural, b: Natural) -> ExhaustiveNaturalRange { assert!(a <= b, "a must be less than or equal to b. a: {a}, b: {b}"); ExhaustiveNaturalRange { a, b: b + Natural::ONE, } } /// Generates all [`Natural`]s greater than or equal to some number $a$, in ascending order. /// /// The output is $(k)_{k=a}^{\infty}$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(i)$ /// /// $M(i) = O(i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// Although the time and space complexities are worst-case linear, the worst case is very rare. If /// we exclude the cases where the least-significant limb of the previously-generated value is /// `Limb::MAX`, the worst case space and time complexities are constant. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::natural::exhaustive::exhaustive_natural_range_to_infinity; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_natural_range_to_infinity(Natural::from(5u32)), /// 10 /// ), /// "[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_natural_range_to_infinity(a: Natural) -> ExhaustiveNaturalRangeToInfinity { ExhaustiveNaturalRangeToInfinity { a } } ================================================ FILE: malachite-nz/src/natural/factorization/is_power.rs ================================================ // Copyright © 2026 William Youmans // // Uses code adopted from the FLINT Library. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{CheckedRoot, DivAssignMod, DivMod, GcdAssign}; use malachite_base::num::basic::traits::One; use malachite_base::num::factorization::traits::{ ExpressAsPower, Factor, IsPower, IsPrime, Primes, }; use malachite_base::num::logic::traits::SignificantBits; const PRIMES: [u32; 168] = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, ]; // Find ONE perfect power representation for a Natural (not necessarily the smallest base). // // This function does NOT recurse - it just checks if n can be expressed as some base^exp. fn get_perfect_power_natural(n: &Natural) -> Option<(Natural, u64)> { // Find largest power of 2 dividing n let mut pow_2 = n.trailing_zeros().unwrap(); // Two divides exactly once - not a perfect power if pow_2 == 1 { return None; } // If pow_2 is prime, just check if n is a perfect pow_2-th power if pow_2.is_prime() { return n.checked_root(pow_2).map(|root| (root, pow_2)); } // Divide out 2^pow_2 to get the odd part let mut q = n >> pow_2; // Factor out powers of small primes for &prime in PRIMES.iter().skip(1) { let prime = Natural::from(prime); let (new_q, r) = (&q).div_mod(&prime); if r == 0u32 { q = new_q; if q.div_assign_mod(&prime) != 0u32 { return None; // prime divides exactly once, reject } let mut pow_p = 2u64; loop { let (new_q, r) = (&q).div_mod(&prime); if r == 0 { q = new_q; pow_p += 1; } else { break; } } pow_2.gcd_assign(pow_p); if pow_2 == 1 { return None; // we have multiplicity 1 of some factor } // As soon as pow_2 becomes prime, stop factoring if q == 1u32 || pow_2.is_prime() { return n.checked_root(pow_2).map(|root| (root, pow_2)); } } } // After factoring, check remaining cases if pow_2 == 0 { // No factors found above; exhaustively check all prime exponents let bits = n.significant_bits(); for nth in u64::primes() { // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits) if nth > bits { return None; } if let Some(root) = n.checked_root(nth) { return Some((root, nth)); } } } else { // Found some factors; only check prime divisors of pow_2 for (nth, _) in pow_2.factor() { if let Some(root) = n.checked_root(nth) { return Some((root, nth)); } } } None } // Boolean check: is n a perfect power? // // Note: This function computes roots the same number of times as get_perfect_power_natural, but // discards the root values, only returning whether a perfect power representation exists. // // Left here in case we can find a way to optimize out root computations later. fn get_perfect_power_natural_bool(n: &Natural) -> bool { // Find largest power of 2 dividing n let mut pow_2 = n.trailing_zeros().unwrap(); // Two divides exactly once - not a perfect power if pow_2 == 1 { return false; } // If pow_2 is prime, check if n is a perfect pow_2-th power if pow_2.is_prime() { return n.checked_root(pow_2).is_some(); } // Divide out 2^pow_2 to get the odd part let mut q = n >> pow_2; // Factor out powers of small primes for &prime in PRIMES.iter().skip(1) { let prime = Natural::from(prime); let (new_q, r) = (&q).div_mod(&prime); if r == 0 { q = new_q; if q.div_assign_mod(&prime) != 0u32 { return false; // prime divides exactly once, reject } let mut pow_p = 2u64; loop { let (new_q, r) = (&q).div_mod(&prime); if r == 0 { q = new_q; pow_p += 1; } else { break; } } pow_2.gcd_assign(pow_p); if pow_2 == 1 { return false; // we have multiplicity 1 of some factor } // As soon as pow_2 becomes prime, stop factoring if q == Natural::ONE || pow_2.is_prime() { return n.checked_root(pow_2).is_some(); } } } // After factoring, check remaining cases if pow_2 == 0 { // No factors found above; exhaustively check all prime exponents let bits = n.significant_bits(); for nth in u64::primes() { // Terminate if exponent exceeds bit length (n ^ (1 / nth) < 2 for nth > bits) if nth > bits { return false; } if n.checked_root(nth).is_some() { return true; } } } else { // Found some factors; only check prime divisors of pow_2 for (nth, _) in pow_2.factor() { if n.checked_root(nth).is_some() { return true; } } } false } // Express Natural as a power with the smallest possible base // // Note: This function is only called for multi-limb numbers (Large variant). fn express_as_power_natural(n: &Natural) -> Option<(Natural, u64)> { // Get initial representation let (mut base, mut exp) = get_perfect_power_natural(n)?; // Continue until we have the smallest possible base while base > 3u32 { match get_perfect_power_natural(&base) { Some((base2, exp2)) => { base = base2; exp *= exp2; } None => break, } } Some((base, exp)) } // Is Natural a perfect power? // // Note: This function is only called for multi-limb numbers #[inline] fn is_power_natural(n: &Natural) -> bool { get_perfect_power_natural_bool(n) } impl ExpressAsPower for Natural { /// Expresses a [`Natural`] as a perfect power if possible. /// /// Returns `Some((root, exponent))` where `root ^ exponent = self` and `exponent > 1`, or /// `None` if the number cannot be expressed as a perfect power. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::ExpressAsPower; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(8u32).express_as_power(), /// Some((Natural::from(2u32), 3)) /// ); /// assert_eq!( /// Natural::from(16u32).express_as_power(), /// Some((Natural::from(2u32), 4)) /// ); /// assert_eq!(Natural::from(6u32).express_as_power(), None); /// ``` fn express_as_power(&self) -> Option<(Self, u64)> { match self { // use the single-limb express_as_power impl for primitive integers Self(Small(small)) => small .express_as_power() .map(|(root, exp)| (Self::from(root), exp)), Self(Large(_)) => express_as_power_natural(self), } } } impl IsPower for Natural { /// Determines whether a [`Natural`] is a perfect power. /// /// A perfect power is any number of the form $a^x$ where $x > 1$, with $a$ and $x$ both /// integers. In particular, 0 and 1 are considered perfect powers. /// /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsPower; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(0u32).is_power(), true); /// assert_eq!(Natural::from(1u32).is_power(), true); /// assert_eq!(Natural::from(4u32).is_power(), true); /// assert_eq!(Natural::from(6u32).is_power(), false); /// assert_eq!(Natural::from(8u32).is_power(), true); /// ``` fn is_power(&self) -> bool { match self { // use the single-limb is_power impl for primitive integers Self(Small(small)) => small.is_power(), Self(Large(_)) => is_power_natural(self), } } } ================================================ FILE: malachite-nz/src/natural/factorization/is_square.rs ================================================ // Copyright © 2026 William Youmans // // Uses code adopted from the GMP Library. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::sqrt::limbs_checked_sqrt; use crate::platform::Limb; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::traits::IsSquare; const MOD34_BITS: Limb = ((Limb::WIDTH as Limb) / 4) * 3; const MOD34_MASK: Limb = (1 << MOD34_BITS) - 1; // This is PERFSQR_MOD_BITS from mpn/perfsqr.h, GMP 6.3.0. Either 49 on 64 bit limb or 25 on 32 bit // limb. 2^48-1 = 3^2 * 5 * 7 * 13 * 17 * 97 ... 2^24-1 = 3^2 * 5 * 7 * 13 * 17 ... const SQR_MOD_BITS: Limb = MOD34_BITS + 1; const SQR_MOD_MASK: Limb = (1 << SQR_MOD_BITS) - 1; // From mpn/generic/mod_34lsub1.c const B1: Limb = (Limb::WIDTH as Limb) / 4; const B2: Limb = B1 * 2; const B3: Limb = B1 * 3; const M1: Limb = (1 << B1) - 1; const M2: Limb = (1 << B2) - 1; const M3: Limb = (1 << B3) - 1; const fn low0(n: Limb) -> Limb { n & M3 } const fn high0(n: Limb) -> Limb { n >> B3 } const fn low1(n: Limb) -> Limb { (n & M2) << B1 } const fn high1(n: Limb) -> Limb { n >> B2 } const fn low2(n: Limb) -> Limb { (n & M1) << B2 } const fn high2(n: Limb) -> Limb { n >> B1 } const fn parts0(n: Limb) -> Limb { low0(n) + high0(n) } const fn parts1(n: Limb) -> Limb { low1(n) + high1(n) } const fn parts2(n: Limb) -> Limb { low2(n) + high2(n) } // This is mpn_mod_34lsub1 from mpn/generic/mod_34lsub1.c, GMP 6.3.0. // // Calculate a remainder from `limbs` divided by 2^(Limb::WIDTH*3/4)-1. The remainder is not fully // reduced, it's any limb value congruent to `limbs` modulo that divisor. // // Check gen-psqr.c. mpn_mod_34lsub1 preferred over mpn_mod_1 (plus a PERFSQR_PP modulus) with 32 // and 64 bit limb. pub(crate) fn mod_34lsub1(limbs: &[Limb]) -> Limb { // Process in chunks of 3, chunks lets us cleanly handle remainder let (sums, carries) = limbs.chunks(3).fold( ([Limb::ZERO; 3], [Limb::ZERO; 3]), |(mut sums, mut carries), chunk| { for (i, &limb) in chunk.iter().enumerate() { let (sum, overflow) = sums[i].overflowing_add(limb); sums[i] = sum; if overflow { carries[i] += 1; } } (sums, carries) }, ); parts0(sums[0]) + parts1(sums[1]) + parts2(sums[2]) + parts1(carries[0]) + parts2(carries[1]) + parts0(carries[2]) } // reduce mod 2^(WIDTH*3/4) - 1 and ensure result is in [0, modulus) fn perfsqr_mod_34(limbs: &[Limb]) -> Limb { let r = mod_34lsub1(limbs); (r & MOD34_MASK) + (r >> MOD34_BITS) } const fn perfsqr_mod_idx(r: Limb, d: Limb, inv: Limb) -> Limb { assert!(r <= SQR_MOD_MASK); assert!(inv.wrapping_mul(d) & SQR_MOD_MASK == 1); assert!(Limb::MAX / d >= SQR_MOD_MASK); let q = r.wrapping_mul(inv) & SQR_MOD_MASK; assert!(r == (q.wrapping_mul(d) & SQR_MOD_MASK)); q.wrapping_mul(d) >> SQR_MOD_BITS } // Single limb. Check precomputed bitmasks to see if remainder is a quadratic residue fn perfsqr_mod_1(r: Limb, d: Limb, inv: Limb, mask: Limb) -> bool { // CNST_LIMB(0x202021202020213), assert!(d <= Limb::WIDTH as Limb); let idx = perfsqr_mod_idx(r, d, inv); if (mask >> idx) & 1 == 0 { // non-square return false; } true } // Double limb. Check precomputed bitmasks to see if remainder is a quadratic residue fn perfsqr_mod_2(r: Limb, d: Limb, inv: Limb, mhi: Limb, mlo: Limb) -> bool { assert!(d <= 2 * Limb::WIDTH as Limb); let mut idx = perfsqr_mod_idx(r, d, inv); let m = if idx < Limb::WIDTH as Limb { mlo } else { mhi }; idx %= Limb::WIDTH as Limb; if (m >> idx) & 1 == 0 { // non-square return false; } true } // This test identifies 97.81% as non-squares. Grand total sq_res_0x100 and PERFSQR_MOD_TEST, 99.62% // non-squares. #[cfg(not(feature = "32_bit_limbs"))] fn perfsqr_mod_test(limbs: &[Limb]) -> bool { let r = perfsqr_mod_34(limbs); perfsqr_mod_2(r, 91, 0xfd2fd2fd2fd3, 0x2191240, 0x8850a206953820e1) // 69.23% && perfsqr_mod_2(r, 85, 0xfcfcfcfcfcfd, 0x82158, 0x10b48c4b4206a105) // 68.24% && perfsqr_mod_1(r, 9, 0xe38e38e38e39, 0x93) // 55.56% && perfsqr_mod_2(r, 97, 0xfd5c5f02a3a1, 0x1eb628b47, 0x6067981b8b451b5f) // 49.48% } // This test identifies 95.66% as non-squares. Grand total sq_res_0x100 and PERFSQR_MOD_TEST, 99.25% // non-squares. #[cfg(feature = "32_bit_limbs")] fn perfsqr_mod_test(limbs: &[Limb]) -> bool { let r = perfsqr_mod_34(limbs); perfsqr_mod_2(r, 45, 0xfa4fa5, 0x920, 0x1a442481) // 73.33% && perfsqr_mod_1(r, 17, 0xf0f0f1, 0x1a317) // 47.06 % && perfsqr_mod_1(r, 13, 0xec4ec5, 0x9e5) // 46.15 % && perfsqr_mod_1(r, 7, 0xdb6db7, 0x69) // 42.86 % } // This is sq_res0x100 from mpn/perfsqr.h when generated for 64 bit limb, GMP 6.3.0. Non-zero bit // indicates a quadratic residue mod 0x100. This test identifies 82.81% as non-squares (212/256). #[cfg(not(feature = "32_bit_limbs"))] const SQR_MOD256: [u64; 4] = [0x202021202030213, 0x202021202020213, 0x202021202030212, 0x202021202020212]; // This is sq_res0x100 from mpn/perfsqr.h when generated for 32 bit limb, GMP 6.3.0. Non-zero bit // indicates a quadratic residue mod 0x100. This test identifies 82.81% as non-squares (212/256). #[cfg(feature = "32_bit_limbs")] const SQR_MOD256: [u32; 8] = [0x2030213, 0x2020212, 0x2020213, 0x2020212, 0x2030212, 0x2020212, 0x2020212, 0x2020212]; fn limbs_is_square(limbs: &[Limb]) -> bool { assert!(!limbs.is_empty()); let idx = limbs[0] % 0x100; // mod 256 // The first test excludes 212/256 (82.8%) of the perfect square candidates in O(1) time. // // This just checks the particular bit in the bitmask SQR_MOD256_U64 encoding where the input // can be a perfect square mod 256. if (SQR_MOD256[usize::exact_from(idx >> Limb::LOG_WIDTH)] >> (idx & const { Limb::WIDTH_MASK as Limb })) & 1 == 0 { return false; } // The second test uses mpn_mod_34lsub1 to detect non-squares according to their residues modulo // small primes (or powers of primes). See mpn/perfsqr.h, GMP 6.3.0. if !perfsqr_mod_test(limbs) { return false; } // For the third and last test, we finally compute the square root, to make sure we've really // got a perfect square. limbs_checked_sqrt(limbs).is_some() } impl IsSquare for Natural { /// Determine whether a [`Natural`] is a perfect square. Rules out > 99% of non-squares in /// $O(1)$ time using quadratic residue tests, then falls back to computing the square root. The /// [`Natural`] is taken by reference. /// /// $f(x) = (\exists b \in \Z : b^2 = x)$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// # Examples /// ``` /// use malachite_base::num::factorization::traits::IsSquare; /// use malachite_nz::natural::Natural; /// /// let x = Natural::from(12345u64); /// let mut y = &x * &x; /// /// assert!((&y).is_square()); /// /// y += Natural::from(1u64); /// assert!(!(&y).is_square()); /// ``` fn is_square(&self) -> bool { match self { // use the FLINT n_is_square impl for primitive integers TODO: is the FLINT n_is_square // better than the GMP algorithm in this file for word size integers? Self(Small(small)) => small.is_square(), Self(Large(limbs)) => limbs_is_square(limbs), } } } ================================================ FILE: malachite-nz/src/natural/factorization/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`IsPower`](malachite_base::num::factorization::traits::IsPower) and /// [`ExpressAsPower`](malachite_base::num::factorization::traits::ExpressAsPower), traits for /// testing if a number is a perfect power and, if it is, expressing it as such. pub mod is_power; /// An implementation of [`IsSquare`](malachite_base::num::factorization::traits::IsSquare), a trait /// for testing if a number if a perfect square. pub mod is_square; /// An implementation of [`Primes`](malachite_base::num::factorization::traits::Primes), a trait for /// generating prime numbers. pub mod primes; #[doc(hidden)] pub mod remove_power; ================================================ FILE: malachite-nz/src/natural/factorization/primes.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::SaturatingFrom; use malachite_base::num::factorization::primes::{PrimesIterator, PrimesLessThanIterator}; use malachite_base::num::factorization::traits::Primes; /// An iterator over that generates all prime [`Natural`]s less than a given value. /// /// This `struct` is created by [`Natural::primes_less_than`] and /// [`Natural::primes_less_than_or_equal_to`]; see their documentation for more. #[derive(Clone, Debug)] pub struct NaturalPrimesLessThanIterator(PrimesLessThanIterator); impl Iterator for NaturalPrimesLessThanIterator { type Item = Natural; #[inline] fn next(&mut self) -> Option { self.0.next().map(Natural::from) } } /// An iterator over that generates all prime [`Natural`]s. /// /// This `struct` is created by [`Natural::primes`]; see its documentation for more. #[derive(Clone, Debug)] pub struct NaturalPrimesIterator(PrimesIterator); impl Iterator for NaturalPrimesIterator { type Item = Natural; #[inline] fn next(&mut self) -> Option { self.0.next().map(Natural::from) } } impl Primes for Natural { type I = NaturalPrimesIterator; type LI = NaturalPrimesLessThanIterator; /// Returns an iterator that generates all primes less than a given value. /// /// The iterator produced by `primes_less_than(n)` generates the same primes as the iterator /// produced by `primes().take_while(|&p| p < n)`, but the latter would be slower because it /// doesn't know in advance how large its prime sieve should be, and might have to create larger /// and larger prime sieves. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Primes; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::primes_less_than(&Natural::from(10u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7]" /// ); /// assert_eq!( /// Natural::primes_less_than(&Natural::from(11u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7]" /// ); /// assert_eq!( /// Natural::primes_less_than(&Natural::from(100u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, \ /// 83, 89, 97]" /// ); /// ``` #[inline] fn primes_less_than(n: &Self) -> NaturalPrimesLessThanIterator { NaturalPrimesLessThanIterator(u64::primes_less_than(&u64::saturating_from(n))) } /// Returns an iterator that generates all primes less than or equal to a given value. /// /// The iterator produced by `primes_less_than_or_equal_to(n)` generates the same primes as the /// iterator produced by `primes().take_while(|&p| p <= n)`, but the latter would be slower /// because it doesn't know in advance how large its prime sieve should be, and might have to /// create larger and larger prime sieves. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::factorization::traits::Primes; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::primes_less_than_or_equal_to(&Natural::from(10u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7]" /// ); /// assert_eq!( /// Natural::primes_less_than_or_equal_to(&Natural::from(11u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7, 11]" /// ); /// assert_eq!( /// Natural::primes_less_than_or_equal_to(&Natural::from(100u32)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, \ /// 83, 89, 97]" /// ); /// ``` #[inline] fn primes_less_than_or_equal_to(n: &Self) -> NaturalPrimesLessThanIterator { NaturalPrimesLessThanIterator(u64::primes_less_than_or_equal_to(&u64::saturating_from(n))) } /// Returns all [`Natural`] primes. /// /// # Worst-case complexity (amortized) /// $T(i) = O(\log \log i)$ /// /// $M(i) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration index. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_base::num::factorization::traits::Primes; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::primes() /// .take_while(|p| u8::convertible_from(p)) /// .collect_vec() /// .to_debug_string(), /// "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, \ /// 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, \ /// 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251]" /// ); /// ``` #[inline] fn primes() -> NaturalPrimesIterator { NaturalPrimesIterator(u64::primes()) } } ================================================ FILE: malachite-nz/src/natural/factorization/remove_power.rs ================================================ // Copyright © 2026 William Youmans // // Uses code adopted from the FLINT Library. // // 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 crate::natural::arithmetic::div_exact::limbs_modular_div_mod_wrap; use crate::natural::arithmetic::neg::limbs_neg_in_place; use crate::natural::arithmetic::square::{limbs_square_to_out, limbs_square_to_out_scratch_len}; use crate::natural::comparison::cmp::limbs_cmp_same_length; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::Equal; use core::mem::swap; use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_test_zero; // Remove the largest power of V from U that doesn't exceed the given cap // // This is `mpn_remove` from GMP 6.3.0. #[doc(hidden)] pub fn limbs_remove( wp: &mut Vec, // Output: U / V^k up: &[Limb], // Input number U vp: &[Limb], // Divisor V (must be odd) cap: usize, // Maximum power to attempt ) -> usize { let un = up.len(); let vn = vp.len(); assert!(un > 0); assert!(vn > 0); assert!(vp[0].odd(), "V must be odd for 2-adic division"); assert!(vn > 1 || vp[0] > 1, "V must be > 1 to avoid infinite loop"); // Temporary work buffers let mut qp = vec![0; un + 1]; let mut qp2 = vec![0; un + 1]; let mut tp = vec![0; (un + 1 + vn) / 2]; // Copy input into quotient buffer qp[..un].copy_from_slice(up); let mut qn = un; // Store the powers of V let mut pwpsn = Vec::with_capacity(Limb::WIDTH as usize); let mut pwpsp_offsets = Vec::with_capacity(Limb::WIDTH as usize); // All generated powers of V are stored here let mut powers_storage = Vec::new(); let mut current_power_is_vp = true; // true if current power is vp, false if in powers_storage let mut current_power_offset = 0; // offset in powers_storage if current_power_is_vp is false let mut pn = vn; let mut npowers = 0; while qn >= pn { qp[qn] = 0; if current_power_is_vp { // Use original vp directly limbs_modular_div_mod_wrap(&mut qp2[..=qn - pn], &mut tp[..pn], &qp[..qn], &vp[..pn]); if !slice_test_zero(&tp[..pn]) && limbs_cmp_same_length(&tp[..pn], &vp[..pn]) != Equal { break; // cannot divide } } else { // Access the power from storage without creating a conflicting borrow let power_slice = &powers_storage[current_power_offset..current_power_offset + pn]; limbs_modular_div_mod_wrap(&mut qp2[..=qn - pn], &mut tp[..pn], &qp[..qn], power_slice); if !slice_test_zero(&tp[..pn]) && limbs_cmp_same_length(&tp[..pn], power_slice) != Equal { break; // cannot divide } } swap(&mut qp, &mut qp2); qn -= pn; limbs_neg_in_place(&mut qp[..=qn]); if qp[qn] != 0 { qn += 1; } // record power pwpsp_offsets.push(if current_power_is_vp { usize::MAX } else { current_power_offset }); pwpsn.push(pn); npowers += 1; if ((2usize << npowers) - 1) > cap { break; } let nn = 2 * pn - 1; if nn > qn { break; } // allocate powers_storage on first use if npowers == 1 { powers_storage = vec![0; qn + Limb::WIDTH as usize]; } // compute square of current power into powers_storage let np_offset = if npowers == 1 { 0 } else { powers_storage.len() }; let np_end = np_offset + 2 * pn; powers_storage.resize(np_end, 0); let mut scratch = vec![0; limbs_square_to_out_scratch_len(pn)]; if current_power_is_vp { limbs_square_to_out( &mut powers_storage[np_offset..np_end], &vp[..pn], &mut scratch, ); } else { // Square the current power from powers_storage into a new location // // need to be careful about overlapping borrows // // we can use split_at_mut to get non-overlapping mutable slices let src_end = current_power_offset + pn; if src_end <= np_offset { // Source and destination don't overlap - safe to borrow both let (src_part, dst_part) = powers_storage.split_at_mut(np_offset); let src = &src_part[current_power_offset..src_end]; limbs_square_to_out(&mut dst_part[..2 * pn], src, &mut scratch); } else { // Fallback: copy source data to avoid overlapping borrows // // This should rarely happen with our offset calculation let src_data: Vec = powers_storage[current_power_offset..src_end].to_vec(); limbs_square_to_out( &mut powers_storage[np_offset..np_end], &src_data, &mut scratch, ); } } pn = nn; if powers_storage[np_offset + nn] != 0 { pn += 1; } current_power_is_vp = false; current_power_offset = np_offset; } let mut pwr = (1usize << npowers) - 1; for i in (0..npowers).rev() { let pn = pwpsn[i]; if qn < pn { continue; } if pwr + (1usize << i) > cap { continue; } let power_slice = if pwpsp_offsets[i] == usize::MAX { &vp[..pn] // Use original vp } else { let offset = pwpsp_offsets[i]; &powers_storage[offset..offset + pn] }; qp[qn] = 0; limbs_modular_div_mod_wrap( &mut qp2[..=(qn - pn)], &mut tp[..pn], &qp[..qn], power_slice, ); if !slice_test_zero(&tp[..pn]) && limbs_cmp_same_length(&tp[..pn], power_slice) != Equal { continue; } swap(&mut qp, &mut qp2); qn -= pn; limbs_neg_in_place(&mut qp[..=qn]); if qp[qn] != 0 { qn += 1; } pwr += 1usize << i; } wp.clear(); wp.extend_from_slice(&qp[..qn]); pwr } ================================================ FILE: malachite-nz/src/natural/logic/and.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::cmp::Ordering::*; use core::mem::swap; use core::ops::{BitAnd, BitAndAssign}; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::slices::slice_set_zero; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // bitwise and of the `Natural` and a `Limb`. The slice cannot be empty. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_const_test! {limbs_and_limb(xs: &[Limb], y: Limb) -> Limb { xs[0] & y }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the bitwise and of the `Natural`s. The length of the result is the length // of the shorter input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res` is returned and both // inputs are non-negative. pub_test! {limbs_and(xs: &[Limb], ys: &[Limb]) -> Vec { xs.iter().zip(ys.iter()).map(|(x, y)| x & y).collect() }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise and of the `Natural`s to a specified slice. The // output slice must be at least as long as the length of one of the input slices. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `out` is too short. // // This is equivalent to `mpn_and_n` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_and_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); for (out, (&x, &y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { *out = x & y; } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise and of the `Natural`s to a specified slice. The output slice must be at // least as long as the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are non-negative. pub_test! {limbs_and_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { assert!(out.len() >= xs_len); limbs_and_same_length_to_out(out, &xs[..ys_len], ys); slice_set_zero(&mut out[ys_len..xs_len]); } else { assert!(out.len() >= ys_len); limbs_and_same_length_to_out(out, xs, &ys[..xs_len]); slice_set_zero(&mut out[xs_len..ys_len]); } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise and of the `Natural`s to the first (left) slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_and_n` from `gmp-impl.h`, GMP 6.2.1, where `rp == up`. pub_test! {limbs_slice_and_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) { assert_eq!(xs.len(), ys.len()); for (x, &y) in xs.iter_mut().zip(ys.iter()) { *x &= y; } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise and of the `Natural`s to the first (left) slice. If the second slice is // shorter than the first, then some of the most-significant bits of the first slice should become // zero. Rather than setting them to zero, this function optionally returns the length of the // significant part of the slice. The caller can decide whether to zero the rest. If `None` is // returned, the entire slice remains significant. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1` and both inputs // are non-negative. pub_test! {limbs_slice_and_in_place_left(xs: &mut [Limb], ys: &[Limb]) -> Option { let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys.len()) { Equal => { limbs_slice_and_same_length_in_place_left(xs, ys); None } Greater => { limbs_slice_and_same_length_in_place_left(&mut xs[..ys_len], ys); Some(ys_len) } Less => { limbs_slice_and_same_length_in_place_left(xs, &ys[..xs_len]); None } } }} // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise and of the `Natural`s to the `Vec`. If the slice is // shorter than the `Vec`, then some of the most-significant bits of the `Vec` should become zero. // Rather than setting them to zero, this function truncates the `Vec`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where `res == op1` and both inputs // are non-negative and have the same length, and `res` is truncated afterwards to remove the // `max(0, xs.len() - ys.len())` trailing zero limbs. pub_test! {limbs_vec_and_in_place_left(xs: &mut Vec, ys: &[Limb]) { if let Some(truncate_size) = limbs_slice_and_in_place_left(xs, ys) { xs.truncate(truncate_size); } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, takes the // limbs of the bitwise and of the `Natural`s and writes them to the shorter slice (or the first // one, if they are equally long). If the function writes to the first slice, it returns `false`; // otherwise, it returns `true`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_and` from `mpz/and.c`, GMP 6.2.1, where both inputs are non-negative // and the result is written to the shorter input slice. pub_test! {limbs_and_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys_len) { Equal => { limbs_slice_and_same_length_in_place_left(xs, ys); false } Less => { limbs_slice_and_same_length_in_place_left(xs, &ys[..xs_len]); false } Greater => { limbs_slice_and_same_length_in_place_left(ys, &xs[..ys_len]); true } } }} impl Natural { fn and_limb(self, other: Limb) -> Limb { Limb::wrapping_from(&self) & other } fn and_limb_ref(&self, other: Limb) -> Limb { Limb::wrapping_from(self) & other } fn and_assign_limb(&mut self, other: Limb) { *self = Self(Small(self.and_limb_ref(other))); } } impl BitAnd for Natural { type Output = Self; /// Takes the bitwise and of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) & Natural::from(456u32), 72); /// assert_eq!( /// Natural::from(10u32).pow(12) & (Natural::from(10u32).pow(12) - Natural::ONE), /// 999999995904u64 /// ); /// ``` #[inline] fn bitand(mut self, other: Self) -> Self { self &= other; self } } impl<'a> BitAnd<&'a Self> for Natural { type Output = Self; /// Takes the bitwise and of two [`Natural`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) & &Natural::from(456u32), 72); /// assert_eq!( /// Natural::from(10u32).pow(12) & &(Natural::from(10u32).pow(12) - Natural::ONE), /// 999999995904u64 /// ); /// ``` #[inline] fn bitand(mut self, other: &'a Self) -> Self { self &= other; self } } impl BitAnd for &Natural { type Output = Natural; /// Takes the bitwise and of two [`Natural`]s, taking the first by reference and the seocnd by /// value. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) & Natural::from(456u32), 72); /// assert_eq!( /// &Natural::from(10u32).pow(12) & (Natural::from(10u32).pow(12) - Natural::ONE), /// 999999995904u64 /// ); /// ``` #[inline] fn bitand(self, mut other: Natural) -> Natural { other &= self; other } } impl BitAnd<&Natural> for &Natural { type Output = Natural; /// Takes the bitwise and of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) & &Natural::from(456u32), 72); /// assert_eq!( /// &Natural::from(10u32).pow(12) & &(Natural::from(10u32).pow(12) - Natural::ONE), /// 999999995904u64 /// ); /// ``` fn bitand(self, other: &Natural) -> Natural { match (self, other) { (x, &Natural(Small(y))) => Natural(Small(x.and_limb_ref(y))), (&Natural(Small(x)), y) => Natural(Small(y.and_limb_ref(x))), (Natural(Large(xs)), Natural(Large(ys))) => { Natural::from_owned_limbs_asc(limbs_and(xs, ys)) } } } } impl BitAndAssign for Natural { /// Bitwise-ands a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. /// /// $$ /// x \gets x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(u32::MAX); /// x &= Natural::from(0xf0ffffffu32); /// x &= Natural::from(0xfff0_ffffu32); /// x &= Natural::from(0xfffff0ffu32); /// x &= Natural::from(0xfffffff0u32); /// assert_eq!(x, 0xf0f0_f0f0u32); /// ``` fn bitand_assign(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.and_assign_limb(*y), (Self(Small(x)), _) => *x = other.and_limb(*x), (Self(Large(xs)), Self(Large(ys))) => { if limbs_and_in_place_either(xs, ys) { swap(xs, ys); } self.trim(); } } } } impl<'a> BitAndAssign<&'a Self> for Natural { /// Bitwise-ands a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. /// /// $$ /// x \gets x \wedge y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(u32::MAX); /// x &= &Natural::from(0xf0ffffffu32); /// x &= &Natural::from(0xfff0_ffffu32); /// x &= &Natural::from(0xfffff0ffu32); /// x &= &Natural::from(0xfffffff0u32); /// assert_eq!(x, 0xf0f0_f0f0u32); /// ``` fn bitand_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.and_assign_limb(*y), (Self(Small(x)), _) => *x = other.and_limb_ref(*x), (Self(Large(xs)), Self(Large(ys))) => { limbs_vec_and_in_place_left(xs, ys); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/logic/bit_access.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1995, 1997, 1999, 2000, 2001, 2002, 2012 Free Software Foundation, // Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::BitAccess; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, gets a bit of // the `Natural` at a specified index. Sufficiently high indices will return `false`. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_tstbit` from `mpz/tstbit.c`, GMP 6.2.1, where the input is // non-negative. pub_crate_test! {limbs_get_bit(xs: &[Limb], index: u64) -> bool { xs.get(bit_to_limb_count_floor(index)) .is_some_and(|x| x.get_bit(index & Limb::WIDTH_MASK)) }} fn limbs_set_bit_helper(xs: &mut [Limb], index: u64, limb_index: usize) { xs[limb_index].set_bit(index & Limb::WIDTH_MASK); } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, sets a bit of // the `Natural` at a specified index to `true`. Indices that are outside the bounds of the slice // will cause a panic. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `index >= xs.len() * Limb::WIDTH`. // // This is equivalent to `mpz_setbit` from `mpz/setbit.c`, GMP 6.2.1, where `d` is non-negative and // `bit_idx` small enough that no additional memory needs to be given to `d`. pub_crate_test! {limbs_slice_set_bit(xs: &mut [Limb], index: u64) { limbs_set_bit_helper(xs, index, bit_to_limb_count_floor(index)); }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, sets a bit of // the `Natural` at a specified index to `true`. Sufficiently high indices will increase the length // of the limbs vector. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `index`. // // This is equivalent to `mpz_setbit` from `mpz/setbit.c`, GMP 6.2.1, where `d` is non-negative. pub_test! {limbs_vec_set_bit(xs: &mut Vec, index: u64) { let small_index = bit_to_limb_count_floor(index); if small_index >= xs.len() { xs.resize(small_index + 1, 0); } limbs_set_bit_helper(xs, index, small_index); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, sets a bit of // the `Natural` at a specified index to `false`. Indices that are outside the bounds of the slice // will result in no action being taken, since there are infinitely many leading zeros. // // # Worst-case complexity // Constant time and additional memory. // // This is equivalent to `mpz_clrbit` from `mpz/clrbit.c`, GMP 6.2.1, where `d` is non-negative. pub_crate_test! {limbs_clear_bit(xs: &mut [Limb], index: u64) { let small_index = bit_to_limb_count_floor(index); if small_index < xs.len() { xs[small_index].clear_bit(index & Limb::WIDTH_MASK); } }} /// Provides functions for accessing and modifying the $i$th bit of a [`Natural`], or the /// coefficient of $2^i$ in its binary expansion. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.assign_bit(2, true); /// x.assign_bit(5, true); /// x.assign_bit(6, true); /// assert_eq!(x, 100); /// x.assign_bit(2, false); /// x.assign_bit(5, false); /// x.assign_bit(6, false); /// assert_eq!(x, 0); /// /// let mut x = Natural::ZERO; /// x.flip_bit(10); /// assert_eq!(x, 1024); /// x.flip_bit(10); /// assert_eq!(x, 0); /// ``` impl BitAccess for Natural { /// Determines whether the $i$th bit of a [`Natural`], or the coefficient of $2^i$ in its binary /// expansion, is 0 or 1. /// /// `false` means 0 and `true` means 1. Getting bits beyond the [`Natural`]'s width is allowed; /// those bits are `false`. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Then $f(n, j) = (b_j = 1)$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32).get_bit(2), false); /// assert_eq!(Natural::from(123u32).get_bit(3), true); /// assert_eq!(Natural::from(123u32).get_bit(100), false); /// assert_eq!(Natural::from(10u32).pow(12).get_bit(12), true); /// assert_eq!(Natural::from(10u32).pow(12).get_bit(100), false); /// ``` fn get_bit(&self, index: u64) -> bool { match self { Self(Small(small)) => small.get_bit(index), Self(Large(limbs)) => limbs_get_bit(limbs, index), } } /// Sets the $i$th bit of a [`Natural`], or the coefficient of $2^i$ in its binary expansion, to /// 1. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Then /// $$ /// n \gets \\begin{cases} /// n + 2^j & \text{if} \\quad b_j = 0, \\\\ /// n & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `index`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x.set_bit(2); /// x.set_bit(5); /// x.set_bit(6); /// assert_eq!(x, 100); /// ``` fn set_bit(&mut self, index: u64) { match self { Self(Small(small)) => { if index < Limb::WIDTH { let mut modified = *small; modified.set_bit(index); *small = modified; } else { let mut limbs = vec![*small]; limbs_vec_set_bit(&mut limbs, index); *self = Self(Large(limbs)); } } Self(Large(limbs)) => { limbs_vec_set_bit(limbs, index); } } } /// Sets the $i$th bit of a [`Natural`], or the coefficient of $2^i$ in its binary expansion, to /// 0. /// /// Clearing bits beyond the [`Natural`]'s width is allowed; since those bits are already /// `false`, clearing them does nothing. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Then /// $$ /// n \gets \\begin{cases} /// n - 2^j & \text{if} \\quad b_j = 1, \\\\ /// n & \text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `index`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitAccess; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::from(0x7fu32); /// x.clear_bit(0); /// x.clear_bit(1); /// x.clear_bit(3); /// x.clear_bit(4); /// assert_eq!(x, 100); /// ``` fn clear_bit(&mut self, index: u64) { match self { Self(Small(small)) => small.clear_bit(index), Self(Large(limbs)) => { limbs_clear_bit(limbs, index); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/logic/bit_block_access.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::arithmetic::mod_power_of_2::limbs_vec_mod_power_of_2_in_place; use crate::natural::arithmetic::shl::limbs_slice_shl_in_place; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::natural::logic::not::limbs_not_in_place; use crate::natural::{Natural, bit_to_limb_count_ceiling, bit_to_limb_count_floor}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::ModPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitBlockAccess, LeadingZeros}; use malachite_base::slices::slice_set_zero; use malachite_base::vecs::vec_delete_left; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs obtained by taking a slice of bits beginning at index `start` of the input slice and ending // at index `end - 1`. `start` must be less than or equal to `end`, but apart from that there are no // restrictions on the index values. If they index beyond the physical size of the input limbs, the // function interprets them as pointing to `false` bits. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `start > end`. pub_crate_test! {limbs_slice_get_bits(xs: &[Limb], start: u64, end: u64) -> Vec { assert!(start <= end); let small_start = bit_to_limb_count_floor(start); let len = xs.len(); if small_start >= len { return Vec::new(); } let small_end = bit_to_limb_count_floor(end) + 1; let mut out = (if small_end >= len { &xs[small_start..] } else { &xs[small_start..small_end] }) .to_vec(); let offset = start & Limb::WIDTH_MASK; if offset != 0 { limbs_slice_shr_in_place(&mut out, offset); } limbs_vec_mod_power_of_2_in_place(&mut out, end - start); out }} // Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs obtained by taking a slice of bits beginning at index `start` of the input slice and ending // at index `end - 1`. `start` must be less than or equal to `end`, but apart from that there are no // restrictions on the index values. If they index beyond the physical size of the input limbs, the // function interprets them as pointing to `false` bits. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `start > end`. pub_test! {limbs_vec_get_bits(mut xs: Vec, start: u64, end: u64) -> Vec { assert!(start <= end); let small_start = bit_to_limb_count_floor(start); if small_start >= xs.len() { return Vec::new(); } limbs_vec_mod_power_of_2_in_place(&mut xs, end); vec_delete_left(&mut xs, small_start); let offset = start & Limb::WIDTH_MASK; if offset != 0 { limbs_slice_shr_in_place(&mut xs, offset); } xs }} // Copy values from `ys` into `xs`. // // - If `ys` has the same length as `xs`, the usual copy is performed. // - If `ys` is longer than `xs`, the first `xs.len()` limbs of `ys` are copied. // - If `ys` is shorter than `xs`, `ys` is copied and the remaining bits of `xs` are filled with // zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. fn copy_from_diff_len_slice(xs: &mut [Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len <= ys_len { xs.copy_from_slice(&ys[..xs_len]); } else { let (xs_lo, xs_hi) = xs.split_at_mut(ys_len); xs_lo.copy_from_slice(ys); slice_set_zero(xs_hi); } } pub(crate) fn limbs_assign_bits_helper( xs: &mut Vec, start: u64, end: u64, mut bits: &[Limb], invert: bool, ) { let small_start = bit_to_limb_count_floor(start); let small_end = bit_to_limb_count_floor(end - 1) + 1; let width = bit_to_limb_count_ceiling(end - start); if width < bits.len() { bits = &bits[..width]; } let start_remainder = start & Limb::WIDTH_MASK; let end_remainder = end & Limb::WIDTH_MASK; if small_end > xs.len() { // Possible inefficiency here: we might write many zeros only to delete them later. xs.resize(small_end, 0); } let out = &mut xs[small_start..small_end]; assert!(!out.is_empty()); let original_first = out[0]; let original_last = *out.last().unwrap(); copy_from_diff_len_slice(out, bits); if invert { limbs_not_in_place(out); } if start_remainder != 0 { limbs_slice_shl_in_place(out, start_remainder); out[0] |= original_first.mod_power_of_2(start_remainder); } if end_remainder != 0 { out.last_mut().unwrap().assign_bits( end_remainder, Limb::WIDTH, &(original_last >> end_remainder), ); } } // Writes the limbs of `bits` into the limbs of `xs`, starting at bit `start` of `xs` (inclusive) // and ending at bit `end` of `xs` (exclusive). The bit indices do not need to be aligned with any // limb boundaries. If `bits` has more than `end` - `start` bits, only the first `end` - `start` // bits are written. If `bits` has fewer than `end` - `start` bits, the remaining written bits are // zero. `xs` may be extended to accommodate the new bits. `start` must be smaller than `end`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `end`. // // # Panics // Panics if `start >= end`. pub_test! {limbs_assign_bits(xs: &mut Vec, start: u64, end: u64, bits: &[Limb]) { assert!(start < end); limbs_assign_bits_helper(xs, start, end, bits, false); }} impl BitBlockAccess for Natural { type Bits = Self; /// Extracts a block of adjacent bits from a [`Natural`], taking the [`Natural`] by reference. /// /// The first index is `start` and last index is `end - 1`. /// /// Let $n$ be `self`, and let $p$ and $q$ be `start` and `end`, respectively. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits(16, 48), /// 0xef011234u32 /// ); /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits(4, 16), /// 0x567u32 /// ); /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits(0, 100), /// 0xabcdef0112345678u64 /// ); /// assert_eq!(Natural::from(0xabcdef0112345678u64).get_bits(10, 10), 0); /// ``` fn get_bits(&self, start: u64, end: u64) -> Self { match self { Self(Small(small)) => Self(Small(small.get_bits(start, end))), Self(Large(limbs)) => { Self::from_owned_limbs_asc(limbs_slice_get_bits(limbs, start, end)) } } } /// Extracts a block of adjacent bits from a [`Natural`], taking the [`Natural`] by value. /// /// The first index is `start` and last index is `end - 1`. /// /// Let $n$ be `self`, and let $p$ and $q$ be `start` and `end`, respectively. /// /// Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Then /// $$ /// f(n, p, q) = \sum_{i=p}^{q-1} 2^{b_{i-p}}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits_owned(16, 48), /// 0xef011234u32 /// ); /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits_owned(4, 16), /// 0x567u32 /// ); /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits_owned(0, 100), /// 0xabcdef0112345678u64 /// ); /// assert_eq!( /// Natural::from(0xabcdef0112345678u64).get_bits_owned(10, 10), /// 0 /// ); /// ``` fn get_bits_owned(self, start: u64, end: u64) -> Self { match self { Self(Small(small)) => Self(Small(small.get_bits(start, end))), Self(Large(limbs)) => Self::from_owned_limbs_asc(limbs_vec_get_bits(limbs, start, end)), } } /// Replaces a block of adjacent bits in a [`Natural`] with other bits. /// /// The least-significant `end - start` bits of `bits` are assigned to bits `start` through `end /// - 1`, inclusive, of `self`. /// /// Let $n$ be `self` and let $m$ be `bits`, and let $p$ and $q$ be `start` and `end`, /// respectively. /// /// If `bits` has fewer bits than `end - start`, the high bits are interpreted as 0. Let /// $$ /// n = \sum_{i=0}^\infty 2^{b_i}, /// $$ /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the rest are /// 0. Let /// $$ /// m = \sum_{i=0}^k 2^{d_i}, /// $$ /// where for all $i$, $d_i\in \\{0, 1\\}$. Also, let $p, q \in \mathbb{N}$, and let $W$ be /// `max(self.significant_bits(), end + 1)`. /// /// Then /// $$ /// n \gets \sum_{i=0}^{W-1} 2^{c_i}, /// $$ /// where /// $$ /// \\{c_0, c_1, c_2, \ldots, c_ {W-1}\\} = /// \\{b_0, b_1, b_2, \ldots, b_{p-1}, d_0, d_1, \ldots, d_{p-q-1}, b_q, \ldots, /// b_ {W-1}\\}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `end`. /// /// # Panics /// Panics if `start > end`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitBlockAccess; /// use malachite_nz::natural::Natural; /// /// let mut n = Natural::from(123u32); /// n.assign_bits(5, 7, &Natural::from(456u32)); /// assert_eq!(n, 27); /// /// let mut n = Natural::from(123u32); /// n.assign_bits(64, 128, &Natural::from(456u32)); /// assert_eq!(n.to_string(), "8411715297611555537019"); /// /// let mut n = Natural::from(123u32); /// n.assign_bits(80, 100, &Natural::from(456u32)); /// assert_eq!(n.to_string(), "551270173744270903666016379"); /// ``` fn assign_bits(&mut self, start: u64, end: u64, bits: &Self) { if start == end { return; } if let Self(Small(small_self)) = self && let Self(Small(small_bits)) = bits { let bits_width = end - start; let small_bits = small_bits.mod_power_of_2(bits_width); if small_bits == 0 || LeadingZeros::leading_zeros(small_bits) >= start { small_self.assign_bits(start, end, &small_bits); return; } } let limbs = self.promote_in_place(); match bits { Self(Small(small_bits)) => limbs_assign_bits(limbs, start, end, &[*small_bits]), Self(Large(bits_limbs)) => limbs_assign_bits(limbs, start, end, bits_limbs), } self.trim(); } } ================================================ FILE: malachite-nz/src/natural/logic/bit_convertible.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::natural::arithmetic::shr::limbs_slice_shr_in_place; use crate::platform::Limb; use alloc::vec::Vec; use itertools::Itertools; use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::{BitAccess, BitConvertible}; impl BitConvertible for Natural { /// Returns a [`Vec`] containing the bits of a [`Natural`] in ascending order: least- to /// most-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, it ends with `true`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::ZERO.to_bits_asc().is_empty()); /// // 105 = 1101001b /// assert_eq!( /// Natural::from(105u32).to_bits_asc(), /// &[true, false, false, true, false, true, true] /// ); /// ``` fn to_bits_asc(&self) -> Vec { let mut bits = Vec::new(); if *self == 0 { return bits; } let limbs = self.limbs(); let last_index = usize::exact_from(self.limb_count()) - 1; let mut last = limbs[last_index]; for limb in limbs.take(last_index) { for i in 0..Limb::WIDTH { bits.push(limb.get_bit(i)); } } while last != 0 { bits.push(last.odd()); last >>= 1; } bits } /// Returns a [`Vec`] containing the bits of a [`Natural`] in descending order: most- to /// least-significant. /// /// If the number is 0, the [`Vec`] is empty; otherwise, it begins with `true`. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::ZERO.to_bits_desc().is_empty()); /// // 105 = 1101001b /// assert_eq!( /// Natural::from(105u32).to_bits_desc(), /// &[true, true, false, true, false, false, true] /// ); /// ``` fn to_bits_desc(&self) -> Vec { let mut bits = self.to_bits_asc(); bits.reverse(); bits } /// Converts an iterator of bits into a [`Natural`]. The bits should be in ascending order /// (least- to most-significant). /// /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. /// /// # Examples /// ``` /// use core::iter::empty; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from_bits_asc(empty()), 0); /// // 105 = 1101001b /// assert_eq!( /// Natural::from_bits_asc( /// [true, false, false, true, false, true, true] /// .iter() /// .cloned() /// ), /// 105 /// ); /// ``` fn from_bits_asc>(xs: I) -> Self { Self::from_owned_limbs_asc( xs.chunks(usize::wrapping_from(Limb::WIDTH)) .into_iter() .map(Limb::from_bits_asc) .collect(), ) } /// Converts an iterator of bits into a [`Natural`]. The bits should be in descending order /// (most- to least-significant). /// /// $$ /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\], /// $$ /// where braces denote the Iverson bracket, which converts a bit to 0 or 1. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`. /// /// # Examples /// ``` /// use core::iter::empty; /// use malachite_base::num::logic::traits::BitConvertible; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from_bits_desc(empty()), 0); /// // 105 = 1101001b /// assert_eq!( /// Natural::from_bits_desc( /// [true, true, false, true, false, false, true] /// .iter() /// .cloned() /// ), /// 105 /// ); /// ``` fn from_bits_desc>(xs: I) -> Self { let mut out = Vec::new(); let mut last_width = 0; for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) { let mut x = 0; let mut i = 0; for bit in chunk { x <<= 1; if bit { x |= 1; } i += 1; } last_width = i; out.push(x); } match out.len() { 0 => Self::ZERO, 1 => Self::from(out[0]), _ => { out.reverse(); if last_width != Limb::WIDTH { let out_0 = out[0]; out[0] = 0; limbs_slice_shr_in_place(&mut out, Limb::WIDTH - last_width); out[0] |= out_0; } Self::from_owned_limbs_asc(out) } } } } ================================================ FILE: malachite-nz/src/natural/logic/bit_iterable.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::natural::conversion::to_limbs::LimbIterator; use crate::platform::Limb; use core::ops::Index; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, BitIterable, SignificantBits}; /// A double-ended iterator over the bits of a [`Natural`]. /// /// The forward order is ascending (least-significant first). /// /// This `struct` is created by [`BitIterable::bits`]; see its documentation for more. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct NaturalBitIterator<'a> { pub(crate) significant_bits: u64, pub(crate) limbs: LimbIterator<'a>, remaining: usize, indices_are_in_same_limb: bool, current_limb_forward: Limb, current_limb_back: Limb, // If `n` is nonzero, this mask initially points to the least-significant bit, and is left- // shifted by next(). i_mask: Limb, // If `n` is nonzero, this mask initially points to the most-significant nonzero bit, and is // right-shifted by next_back(). j_mask: Limb, } impl Iterator for NaturalBitIterator<'_> { type Item = bool; fn next(&mut self) -> Option { if self.remaining != 0 { let bit = self.current_limb_forward & self.i_mask != 0; self.i_mask <<= 1; if self.i_mask == 0 { self.i_mask = 1; if let Some(next) = self.limbs.next() { self.current_limb_forward = next; } else { self.current_limb_forward = self.current_limb_back; self.indices_are_in_same_limb = true; } } self.remaining -= 1; Some(bit) } else { None } } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl DoubleEndedIterator for NaturalBitIterator<'_> { fn next_back(&mut self) -> Option { if self.remaining != 0 { let bit = self.current_limb_back & self.j_mask != 0; self.j_mask >>= 1; if self.j_mask == 0 { self.j_mask = Limb::power_of_2(Limb::WIDTH - 1); if let Some(next_back) = self.limbs.next_back() { self.current_limb_back = next_back; } else { self.current_limb_back = self.current_limb_forward; self.indices_are_in_same_limb = true; } } self.remaining -= 1; Some(bit) } else { None } } } impl ExactSizeIterator for NaturalBitIterator<'_> {} impl Index for NaturalBitIterator<'_> { type Output = bool; /// A function to retrieve a [`Natural`]'s bits by index. /// /// The index is the power of 2 of which the bit is a coefficient. Indexing at or above the /// significant bit count returns `false` bits. /// /// This is equivalent to [`get_bit`](malachite_base::num::logic::traits::BitAccess::get_bit). /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitIterable; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.bits()[0], false); /// /// // 105 = 1101001b /// let n = Natural::from(105u32); /// let bits = n.bits(); /// assert_eq!(bits[0], true); /// assert_eq!(bits[1], false); /// assert_eq!(bits[2], false); /// assert_eq!(bits[3], true); /// assert_eq!(bits[4], false); /// assert_eq!(bits[5], true); /// assert_eq!(bits[6], true); /// assert_eq!(bits[7], false); /// assert_eq!(bits[100], false); /// ``` fn index(&self, index: u64) -> &bool { if self.limbs.n.get_bit(index) { &true } else { &false } } } impl<'a> BitIterable for &'a Natural { type BitIterator = NaturalBitIterator<'a>; /// Returns a double-ended iterator over the bits of a [`Natural`]. /// /// The forward order is ascending, so that less significant bits appear first. There are no /// trailing false bits going forward, or leading falses going backward. /// /// If it's necessary to get a [`Vec`] of all the bits, consider using /// [`to_bits_asc`](malachite_base::num::logic::traits::BitConvertible::to_bits_asc) or /// [`to_bits_desc`](malachite_base::num::logic::traits::BitConvertible::to_bits_desc) instead. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::BitIterable; /// use malachite_nz::natural::Natural; /// /// assert!(Natural::ZERO.bits().next().is_none()); /// // 105 = 1101001b /// assert_eq!( /// Natural::from(105u32).bits().collect::>(), /// &[true, false, false, true, false, true, true] /// ); /// /// assert!(Natural::ZERO.bits().next_back().is_none()); /// // 105 = 1101001b /// assert_eq!( /// Natural::from(105u32).bits().rev().collect::>(), /// &[true, true, false, true, false, false, true] /// ); /// ``` fn bits(self) -> NaturalBitIterator<'a> { let significant_bits = self.significant_bits(); let remainder = significant_bits & Limb::WIDTH_MASK; let mut bits = NaturalBitIterator { significant_bits, limbs: self.limbs(), remaining: usize::exact_from(significant_bits), indices_are_in_same_limb: significant_bits <= Limb::WIDTH, current_limb_forward: 0, current_limb_back: 0, i_mask: 1, j_mask: if remainder != 0 { Limb::power_of_2(remainder - 1) } else { Limb::power_of_2(Limb::WIDTH - 1) }, }; if let Some(next) = bits.limbs.next() { bits.current_limb_forward = next; } if let Some(next_back) = bits.limbs.next_back() { bits.current_limb_back = next_back; } else { bits.current_limb_back = bits.current_limb_forward; } bits } } ================================================ FILE: malachite-nz/src/natural/logic/bit_scan.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000-2002, 2004, 2012, 2015 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count}; use crate::platform::Limb; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitScan, TrailingZeros}; use malachite_base::slices::slice_leading_zeros; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, finds the // lowest index greater than or equal to `start` at which the `Natural` has a `false` bit. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_scan0` from `mpn/generic/scan0.c`, GMP 6.2.1. pub_crate_test! {limbs_index_of_next_false_bit(xs: &[Limb], start: u64) -> u64 { let starting_index = bit_to_limb_count_floor(start); if starting_index >= xs.len() { return start; } if let Some(result) = xs[starting_index].index_of_next_false_bit(start & Limb::WIDTH_MASK) && result != Limb::WIDTH { return limb_to_bit_count(starting_index) + result; } if starting_index == xs.len() - 1 { return limb_to_bit_count(xs.len()); } let false_index = starting_index + 1 + xs[starting_index + 1..] .iter() .take_while(|&&y| y == Limb::MAX) .count(); let mut result_offset = limb_to_bit_count(false_index); if false_index != xs.len() { result_offset += TrailingZeros::trailing_zeros(!xs[false_index]); } result_offset }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, finds the // lowest index greater than or equal to `start` at which the `Natural` has a `true` bit. If the // starting index is too large and there are no more `true` bits above it, `None` is returned. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_scan1` from `mpn/generic/scan1.c`, GMP 6.2.1. pub_crate_test! {limbs_index_of_next_true_bit(xs: &[Limb], start: u64) -> Option { let starting_index = bit_to_limb_count_floor(start); if starting_index >= xs.len() { None } else if let Some(result) = xs[starting_index].index_of_next_true_bit(start & Limb::WIDTH_MASK) { Some(limb_to_bit_count(starting_index) + result) } else if starting_index == xs.len() - 1 { None } else { let true_index = starting_index + 1 + slice_leading_zeros(&xs[starting_index + 1..]); if true_index == xs.len() { None } else { let result_offset = limb_to_bit_count(true_index); Some( result_offset .checked_add(TrailingZeros::trailing_zeros(xs[true_index])) .unwrap(), ) } } }} impl BitScan for &Natural { /// Given a [`Natural`] and a starting index, searches the [`Natural`] for the smallest index of /// a `false` bit that is greater than or equal to the starting index. /// /// Since every [`Natural`] has an implicit prefix of infinitely-many zeros, this function /// always returns a value. /// /// Starting beyond the [`Natural`]'s width is allowed; the result is the starting index. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitScan; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(0), /// Some(0) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(20), /// Some(20) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(31), /// Some(31) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(32), /// Some(34) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(33), /// Some(34) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(34), /// Some(34) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(35), /// Some(36) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_false_bit(100), /// Some(100) /// ); /// ``` fn index_of_next_false_bit(self, start: u64) -> Option { match self { Natural(Small(small)) => small.index_of_next_false_bit(start), Natural(Large(limbs)) => Some(limbs_index_of_next_false_bit(limbs, start)), } } /// Given a [`Natural`] and a starting index, searches the [`Natural`] for the smallest index of /// a `true` bit that is greater than or equal to the starting index. /// /// If the starting index is greater than or equal to the [`Natural`]'s width, the result is /// `None` since there are no `true` bits past that point. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::BitScan; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(0), /// Some(32) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(20), /// Some(32) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(31), /// Some(32) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(32), /// Some(32) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(33), /// Some(33) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(34), /// Some(35) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(35), /// Some(35) /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(36), /// None /// ); /// assert_eq!( /// Natural::from(0xb00000000u64).index_of_next_true_bit(100), /// None /// ); /// ``` fn index_of_next_true_bit(self, start: u64) -> Option { match self { Natural(Small(small)) => small.index_of_next_true_bit(start), Natural(Large(limbs)) => limbs_index_of_next_true_bit(limbs, start), } } } ================================================ FILE: malachite-nz/src/natural/logic/count_ones.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::logic::traits::CountOnes; // Interpreting a slice of `Limb`s, as the limbs (in ascending order) of a `Natural`, counts the // number of ones in the binary expansion of the `Natural`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. pub_crate_test! {limbs_count_ones(xs: &[Limb]) -> u64 { xs.iter().map(|&x| CountOnes::count_ones(x)).sum() }} impl CountOnes for &Natural { /// Counts the number of ones in the binary expansion of a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::CountOnes; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.count_ones(), 0); /// // 105 = 1101001b /// assert_eq!(Natural::from(105u32).count_ones(), 4); /// // 10^12 = 1110100011010100101001010001000000000000b /// assert_eq!(Natural::from(10u32).pow(12).count_ones(), 13); /// ``` fn count_ones(self) -> u64 { match self { Natural(Small(small)) => CountOnes::count_ones(*small), Natural(Large(limbs)) => limbs_count_ones(limbs), } } } ================================================ FILE: malachite-nz/src/natural/logic/hamming_distance.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1994, 1996, 2001, 2002, 2009-2011 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::logic::count_ones::limbs_count_ones; use crate::platform::Limb; use core::cmp::Ordering::*; use malachite_base::num::logic::traits::HammingDistance; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, returns the // Hamming distance between that `Natural` and a `Limb`. Both have infinitely many implicit leading // zeros. `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_hamming_distance_limb(xs: &[Limb], y: Limb) -> u64 { xs[0].hamming_distance(y) + limbs_count_ones(&xs[1..]) }} // Interpreting two equal-length slices of `Limb`s as the limbs of `Natural`s in ascending order, // returns the Hamming distance between them. Both have infinitely many implicit leading zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpz_hamdist` from `mpz/hamdist.c`, GMP 6.2.1, where both arguments are // non-negative and have the same length. pub_crate_test! {limbs_hamming_distance_same_length(xs: &[Limb], ys: &[Limb]) -> u64 { assert_eq!(xs.len(), ys.len()); xs.iter() .zip(ys.iter()) .map(|(x, &y)| x.hamming_distance(y)) .sum() }} // Interpreting two slices of `Limb`s as the limbs of `Natural`s in ascending order, returns the // Hamming distance between them. Both have infinitely many implicit leading zeros. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_hamdist` from `mpz/hamdist.c`, GMP 6.2.1, where both arguments are // non-negative. pub_test! {limbs_hamming_distance(xs: &[Limb], ys: &[Limb]) -> u64 { let xs_len = xs.len(); let ys_len = ys.len(); match xs_len.cmp(&ys_len) { Equal => limbs_hamming_distance_same_length(xs, ys), Less => { limbs_hamming_distance_same_length(xs, &ys[..xs_len]) + limbs_count_ones(&ys[xs_len..]) } Greater => { limbs_hamming_distance_same_length(&xs[..ys_len], ys) + limbs_count_ones(&xs[ys_len..]) } } }} impl Natural { fn hamming_distance_limb(&self, other: Limb) -> u64 { match self { Self(Small(small)) => small.hamming_distance(other), Self(Large(limbs)) => limbs_hamming_distance_limb(limbs, other), } } } impl HammingDistance<&Natural> for &Natural { /// Determines the Hamming distance between two [`Natural]`s. /// /// Both [`Natural`]s have infinitely many implicit leading zeros. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_base::num::logic::traits::HammingDistance; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// Natural::from(123u32).hamming_distance(&Natural::from(123u32)), /// 0 /// ); /// // 105 = 1101001b, 123 = 1111011 /// assert_eq!( /// Natural::from(105u32).hamming_distance(&Natural::from(123u32)), /// 2 /// ); /// let n = Natural::ONE << 100u32; /// assert_eq!(n.hamming_distance(&(&n - Natural::ONE)), 101); /// ``` fn hamming_distance(self, other: &Natural) -> u64 { match (self, other) { (&Natural(Small(x)), _) => other.hamming_distance_limb(x), (_, &Natural(Small(y))) => self.hamming_distance_limb(y), (Natural(Large(xs)), Natural(Large(ys))) => limbs_hamming_distance(xs, ys), } } } ================================================ FILE: malachite-nz/src/natural/logic/low_mask.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, bit_to_limb_count_ceiling}; use crate::platform::Limb; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::ModPowerOf2Assign; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::LowMask; // Returns the limbs of a `Natural`, where the lowest `bits` bits are set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `bits`. pub_crate_test! {limbs_low_mask(bits: u64) -> Vec { let len = bit_to_limb_count_ceiling(bits); let remaining_bits = bits & Limb::WIDTH_MASK; let mut xs = vec![Limb::MAX; len]; if remaining_bits != 0 { xs.last_mut().unwrap().mod_power_of_2_assign(remaining_bits); } xs }} impl LowMask for Natural { /// Returns a [`Natural`] whose least significant $b$ bits are `true` and whose other bits are /// `false`. /// /// $f(b) = 2^b - 1$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::logic::traits::LowMask; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::low_mask(0), 0); /// assert_eq!(Natural::low_mask(3), 7); /// assert_eq!( /// Natural::low_mask(100).to_string(), /// "1267650600228229401496703205375" /// ); /// ``` fn low_mask(bits: u64) -> Self { if bits <= Limb::WIDTH { Self(Small(Limb::low_mask(bits))) } else { Self(Large(limbs_low_mask(bits))) } } } ================================================ FILE: malachite-nz/src/natural/logic/mod.rs ================================================ // Copyright © 2026 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 . /// Bitwise and of [`Natural`](super::Natural)s. pub mod and; /// An implementation of [`BitAccess`](malachite_base::num::logic::traits::BitAccess), a trait for /// getting and setting individual bits of a number. pub mod bit_access; /// An implementation of [`BitBlockAccess`](malachite_base::num::logic::traits::BitBlockAccess), a /// trait for getting and setting adjacent blocks of bits in a number. pub mod bit_block_access; /// An implementation of [`BitConvertible`](malachite_base::num::logic::traits::BitConvertible), a /// trait for extracting all bits from a number or constructing a number from bits. pub mod bit_convertible; /// An implementation of [`BitIterable`](malachite_base::num::logic::traits::BitIterable), a trait /// for producing a double-ended iterator over a number's bits. pub mod bit_iterable; /// An implementation of [`BitScan`](malachite_base::num::logic::traits::BitScan), a trait for /// finding the next `true` or `false` bit in a number after a provided index. pub mod bit_scan; /// An implementation of [`CountOnes`](malachite_base::num::logic::traits::CountOnes), a trait for /// counting the number of ones in the binary representation of a number. pub mod count_ones; /// An implementation of [`HammingDistance`](malachite_base::num::logic::traits::HammingDistance), a /// trait for computing the Hamming distance between two numbers. pub mod hamming_distance; /// An implementation of [`LowMask`](malachite_base::num::logic::traits::LowMask), a trait for /// generating a low bit mask (a number in which only the $k$ least-significant bits are 1). pub mod low_mask; /// Bitwise negation of [`Natural`](super::Natural)s. pub mod not; /// Bitwise or of [`Natural`](super::Natural)s. pub mod or; /// An implementation of [`SignificantBits`](malachite_base::num::logic::traits::SignificantBits), a /// trait for determining how many significant bits a number has. pub mod significant_bits; /// An implementation of [`TrailingZeros`](malachite_base::num::logic::traits::TrailingZeros), a /// trait for determining the number of zeros that a number ends with when written in binary. pub mod trailing_zeros; /// Bitwise xor of [`Natural`](super::Natural)s. pub mod xor; ================================================ FILE: malachite-nz/src/natural/logic/not.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright 1991, 1993, 1994, 1996, 2001, 2003, 2012, 2015 Free Software Foundation, Inc. // // 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 crate::integer::Integer; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::ops::Not; use malachite_base::num::logic::traits::NotAssign; // Returns the bitwise not of a slice of limbs. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_com` from `mpn/generic/com.c`, GMP 6.2.1, where `rp` is returned. pub_test! {limbs_not(xs: &[Limb]) -> Vec { xs.iter().map(|x| !x).collect() }} // Writes the bitwise not of a slice of limbs to the lowest `x.len()` limbs of `out`. For this to // work, `out` must be at least as long as `xs`. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_com` from `mpn/generic/com.c`, GMP 6.2.1, where `rp != up`. // // # Panics // Panics if `out` is shorter than `xs`. pub_crate_test! {limbs_not_to_out(out: &mut [Limb], xs: &[Limb]) { assert!(out.len() >= xs.len()); for (x, y) in out.iter_mut().zip(xs.iter()) { *x = !y; } }} // Takes the bitwise not of a slice of limbs in place. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_com` from `mpn/generic/com.c`, GMP 6.2.1, where `rp == up`. pub_crate_test! {limbs_not_in_place(xs: &mut [Limb]) { for x in &mut *xs { x.not_assign(); } }} impl Not for Natural { type Output = Integer; /// Returns the bitwise negation of a [`Natural`], taking it by value and returning an /// [`Integer`]. /// /// The [`Natural`] is bitwise-negated as if it were represented in two's complement. /// /// $$ /// f(n) = -n - 1. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(!Natural::ZERO, -1); /// assert_eq!(!Natural::from(123u32), -124); /// ``` fn not(self) -> Integer { Integer { sign: false, abs: self.add_limb(1), } } } impl Not for &Natural { type Output = Integer; /// Returns the bitwise negation of a [`Natural`], taking it by reference and returning an /// [`Integer`]. /// /// The [`Natural`] is bitwise-negated as if it were represented in two's complement. /// /// $$ /// f(n) = -n - 1. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(!&Natural::ZERO, -1); /// assert_eq!(!&Natural::from(123u32), -124); /// ``` fn not(self) -> Integer { Integer { sign: false, abs: self.add_limb_ref(1), } } } ================================================ FILE: malachite-nz/src/natural/logic/or.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::mem::swap; use core::ops::{BitOr, BitOrAssign}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the bitwise or of the `Natural` and a `Limb`. `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub fn limbs_or_limb(xs: &[Limb], y: Limb) -> Vec { let mut result = xs.to_vec(); limbs_or_limb_in_place(&mut result, y); result } // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the bitwise or of the `Natural` and a `Limb` to an output slice. The output slice must // be at least as long as the input slice. `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs` or if `xs` is empty. pub_test! {limbs_or_limb_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) { out[..xs.len()].copy_from_slice(xs); limbs_or_limb_in_place(out, y); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the bitwise or of the `Natural` and a `Limb` to the input slice. `xs` cannot be empty. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_or_limb_in_place(xs: &mut [Limb], y: Limb) { xs[0] |= y; }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, returns a `Vec` of the limbs of the bitwise or of the `Natural`s. The length of the // result is the length of one of the input slices. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_ior_n` from `gmp-impl.h`, GMP 6.2.1, where `rp` is returned. pub_test! {limbs_or_same_length(xs: &[Limb], ys: &[Limb]) -> Vec { assert_eq!(xs.len(), ys.len()); xs.iter().zip(ys.iter()).map(|(x, y)| x | y).collect() }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the bitwise or of the `Natural`s. The length of the result is the length of // the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res` is returned and both // inputs are non-negative. pub_test! {limbs_or(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let mut result; if xs_len >= ys_len { result = limbs_or_same_length(&xs[..ys_len], ys); result.extend_from_slice(&xs[ys_len..]); } else { result = limbs_or_same_length(xs, &ys[..xs_len]); result.extend_from_slice(&ys[xs_len..]); } result }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise or of the `Natural`s to an output slice. The output // must be at least as long as one of the input slices. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `out` is too short. // // This is equivalent to `mpn_ior_n` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_or_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); for (out_x, (x, y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { *out_x = x | y; } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise or of the `Natural`s to an output slice. The output must be at least as // long as the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are non-negative. pub_test! {limbs_or_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { assert!(out.len() >= xs_len); limbs_or_same_length_to_out(out, &xs[..ys_len], ys); out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); } else { assert!(out.len() >= ys_len); limbs_or_same_length_to_out(out, xs, &ys[..xs_len]); out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]); } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise or of the `Natural`s to the first (left) slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_ior_n` from `gmp-impl.h`, GMP 6.2.1, where `rp == up`. pub_test! {limbs_or_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) { assert_eq!(xs.len(), ys.len()); for (x, &y) in xs.iter_mut().zip(ys.iter()) { *x |= y; } }} // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise or of the `Natural`s to the `Vec`. If `ys` is longer // than `xs`, `xs` will be extended. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where `res == op1` and both inputs // are non-negative. pub_test! {limbs_or_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { limbs_or_same_length_in_place_left(&mut xs[..ys_len], ys); } else { limbs_or_same_length_in_place_left(xs, &ys[..xs_len]); xs.extend_from_slice(&ys[xs_len..]); } }} // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise or of the `Natural`s to the longer slice (or the first one, if they are // equally long). Returns a `bool` which is `false` when the output is to the first slice and `true` // when it's to the second slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_ior` from `mpz/ior.c`, GMP 6.2.1, where both inputs are non-negative // and the result is written to the longer input slice. pub_test! {limbs_or_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let right = xs_len < ys_len; if right { limbs_or_same_length_in_place_left(&mut ys[..xs_len], xs); } else { limbs_or_same_length_in_place_left(&mut xs[..ys_len], ys); } right }} impl Natural { #[inline] fn or_limb(mut self, other: Limb) -> Self { self.or_assign_limb(other); self } fn or_limb_ref(&self, other: Limb) -> Self { Self(match self { Self(Small(small)) => Small(small | other), Self(Large(limbs)) => Large(limbs_or_limb(limbs, other)), }) } fn or_assign_limb(&mut self, other: Limb) { match self { Self(Small(small)) => *small |= other, Self(Large(limbs)) => limbs_or_limb_in_place(limbs, other), } } } impl BitOr for Natural { type Output = Self; /// Takes the bitwise or of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) | Natural::from(456u32), 507); /// assert_eq!( /// Natural::from(10u32).pow(12) | (Natural::from(10u32).pow(12) - Natural::ONE), /// 1000000004095u64 /// ); /// ``` #[inline] fn bitor(mut self, other: Self) -> Self { self |= other; self } } impl<'a> BitOr<&'a Self> for Natural { type Output = Self; /// Takes the bitwise or of two [`Natural`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) | &Natural::from(456u32), 507); /// assert_eq!( /// Natural::from(10u32).pow(12) | &(Natural::from(10u32).pow(12) - Natural::ONE), /// 1000000004095u64 /// ); /// ``` #[inline] fn bitor(mut self, other: &'a Self) -> Self { self |= other; self } } impl BitOr for &Natural { type Output = Natural; /// Takes the bitwise or of two [`Natural`]s, taking the first by reference and the second by /// value. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) | Natural::from(456u32), 507); /// assert_eq!( /// &Natural::from(10u32).pow(12) | (Natural::from(10u32).pow(12) - Natural::ONE), /// 1000000004095u64 /// ); /// ``` #[inline] fn bitor(self, mut other: Natural) -> Natural { other |= self; other } } impl BitOr<&Natural> for &Natural { type Output = Natural; /// Takes the bitwise or of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = x \vee y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) | &Natural::from(456u32), 507); /// assert_eq!( /// &Natural::from(10u32).pow(12) | &(Natural::from(10u32).pow(12) - Natural::ONE), /// 1000000004095u64 /// ); /// ``` fn bitor(self, other: &Natural) -> Natural { match (self, other) { (x, &Natural(Small(y))) => x.or_limb_ref(y), (&Natural(Small(x)), y) => y.or_limb_ref(x), (Natural(Large(xs)), Natural(Large(ys))) => Natural(Large(limbs_or(xs, ys))), } } } impl BitOrAssign for Natural { /// Bitwise-ors a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x |= Natural::from(0x0000000fu32); /// x |= Natural::from(0x00000f00u32); /// x |= Natural::from(0x000f_0000u32); /// x |= Natural::from(0x0f000000u32); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitor_assign(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.or_assign_limb(*y), (Self(Small(x)), _) => *self = other.or_limb(*x), (Self(Large(xs)), Self(Large(ys))) => { if limbs_or_in_place_either(xs, ys) { swap(xs, ys); } } } } } impl<'a> BitOrAssign<&'a Self> for Natural { /// Bitwise-ors a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x |= &Natural::from(0x0000000fu32); /// x |= &Natural::from(0x00000f00u32); /// x |= &Natural::from(0x000f_0000u32); /// x |= &Natural::from(0x0f000000u32); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitor_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.or_assign_limb(*y), (Self(Small(x)), _) => *self = other.or_limb_ref(*x), (Self(Large(xs)), Self(Large(ys))) => { limbs_or_in_place_left(xs, ys); } } } } ================================================ FILE: malachite-nz/src/natural/logic/significant_bits.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993-1995, 2001, 2002 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::SignificantBits; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, returns the // smallest number of bits necessary to represent that `Natural`. 0 has zero significant bits. When // the `Natural` is nonzero, this is equal to 1 + floor(log2(`self`)). // // This function assumes that `xs` is nonempty and the last (most significant) limb is nonzero. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. // // This is equivalent to `mpz_sizeinbase` from `mpz/sizeinbase.c`, GMP 6.2.1, where `x` is // non-negative and `base` is 2. pub_crate_test! {limbs_significant_bits(xs: &[T]) -> u64 { ((u64::wrapping_from(xs.len()) - 1) << T::LOG_WIDTH) + xs.last().unwrap().significant_bits() }} impl SignificantBits for &Natural { /// Returns the number of significant bits of a [`Natural`]. /// /// $$ /// f(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \lfloor \log_2 n \rfloor + 1 & \text{if} \\quad n > 0. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::SignificantBits; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.significant_bits(), 0); /// assert_eq!(Natural::from(100u32).significant_bits(), 7); /// ``` fn significant_bits(self) -> u64 { match self { Natural(Small(small)) => small.significant_bits(), Natural(Large(limbs)) => limbs_significant_bits(limbs), } } } ================================================ FILE: malachite-nz/src/natural/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::{Natural, limb_to_bit_count}; use crate::platform::Limb; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::slices::slice_leading_zeros; // Interpreting a slice of `Limb`s as the limbs of a `Natural` in ascending order, returns the // number of trailing zeros in the binary expansion of a `Natural` (equivalently, the multiplicity // of 2 in its prime factorization). The limbs cannot be empty or all zero. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` only contains zeros. pub_crate_test! {limbs_trailing_zeros(xs: &[Limb]) -> u64 { let zeros = slice_leading_zeros(xs); let remaining_zeros = TrailingZeros::trailing_zeros(xs[zeros]); limb_to_bit_count(zeros)+ remaining_zeros }} impl Natural { /// Returns the number of trailing zeros in the binary expansion of a [`Natural`] (equivalently, /// the multiplicity of 2 in its prime factorization), or `None` is the [`Natural`] is 0. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::ZERO.trailing_zeros(), None); /// assert_eq!(Natural::from(3u32).trailing_zeros(), Some(0)); /// assert_eq!(Natural::from(72u32).trailing_zeros(), Some(3)); /// assert_eq!(Natural::from(100u32).trailing_zeros(), Some(2)); /// assert_eq!(Natural::from(10u32).pow(12).trailing_zeros(), Some(12)); /// ``` pub fn trailing_zeros(&self) -> Option { match self { &Self::ZERO => None, Self(Small(small)) => Some(TrailingZeros::trailing_zeros(*small)), Self(Large(limbs)) => Some(limbs_trailing_zeros(limbs)), } } } ================================================ FILE: malachite-nz/src/natural/logic/xor.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::platform::Limb; use alloc::vec::Vec; use core::mem::swap; use core::ops::{BitXor, BitXorAssign}; // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the // limbs of the bitwise xor of the `Natural` and a `Limb`. `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_xor_limb(xs: &[Limb], y: Limb) -> Vec { let mut result = xs.to_vec(); limbs_xor_limb_in_place(&mut result, y); result }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the bitwise xor of the `Natural` and a `Limb` to an output slice. The output slice must // be at least as long as the input slice. `xs` cannot be empty. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `out` is shorter than `xs` or if `xs` is empty. pub_test! {limbs_xor_limb_to_out(out: &mut [Limb], xs: &[Limb], y: Limb) { out[..xs.len()].copy_from_slice(xs); limbs_xor_limb_in_place(out, y); }} // Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the // limbs of the bitwise xor of the `Natural` and a `Limb` to the input slice. `xs` cannot be empty. // // # Worst-case complexity // Constant time and additional memory. // // # Panics // Panics if `xs` is empty. pub_test! {limbs_xor_limb_in_place(xs: &mut [Limb], y: Limb) { xs[0] ^= y; }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, returns a `Vec` of the limbs of the bitwise xor of the `Natural`s. The length of the // result is the length of one of the input slices. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // This is equivalent to `mpn_xor_n` from `gmp-impl.h`, GMP 6.2.1, where `rp` is returned. // // # Panics // Panics if `xs` and `ys` have different lengths. pub_test! {limbs_xor_same_length(xs: &[Limb], ys: &[Limb]) -> Vec { assert_eq!(xs.len(), ys.len()); xs.iter().zip(ys.iter()).map(|(x, y)| x ^ y).collect() }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, returns a // `Vec` of the limbs of the bitwise xor of the `Natural`s. The length of the result is the length // of the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res` is returned and both // inputs are non-negative. pub_test! {limbs_xor(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let mut result; if xs_len >= ys_len { result = limbs_xor_same_length(&xs[..ys_len], ys); result.extend_from_slice(&xs[ys_len..]); } else { result = limbs_xor_same_length(xs, &ys[..xs_len]); result.extend_from_slice(&ys[xs_len..]); } result }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise xor of the `Natural`s to an output slice. The output // must be at least as long as one of the input slices. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths or if `out` is too short. // // This is equivalent to `mpn_xor_n` from `gmp-impl.h`, GMP 6.2.1. pub_test! {limbs_xor_same_length_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let len = xs.len(); assert_eq!(len, ys.len()); assert!(out.len() >= len); for (z, (x, y)) in out.iter_mut().zip(xs.iter().zip(ys.iter())) { *z = x ^ y; } }} // Interpreting two slices of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise xor of the `Natural`s to an output slice. The output must be at least as // long as the longer input slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `max(xs.len(), ys.len())`. // // # Panics // Panics if `out` is too short. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are non-negative. pub_test! {limbs_xor_to_out(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { assert!(out.len() >= xs_len); limbs_xor_same_length_to_out(out, &xs[..ys_len], ys); out[ys_len..xs_len].copy_from_slice(&xs[ys_len..]); } else { assert!(out.len() >= ys_len); limbs_xor_same_length_to_out(out, xs, &ys[..xs_len]); out[xs_len..ys_len].copy_from_slice(&ys[xs_len..]); } }} // Interpreting two equal-length slices of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise xor of the `Natural`s to the first (left) slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`. // // # Panics // Panics if `xs` and `ys` have different lengths. // // This is equivalent to `mpn_xor_n` from `gmp-impl.h`, GMP 6.2.1, where `rp == up`. pub_test! {limbs_xor_same_length_in_place_left(xs: &mut [Limb], ys: &[Limb]) { assert_eq!(xs.len(), ys.len()); for (x, y) in xs.iter_mut().zip(ys.iter()) { *x ^= y; } }} // Interpreting a `Vec` of `Limb`s and a slice of `Limb`s as the limbs (in ascending order) of two // `Natural`s, writes the limbs of the bitwise xor of the `Natural`s to the `Vec`. If `ys` is longer // than `xs`, `xs` will be extended. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ys.len()`. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where `res == op1` and both inputs // are non-negative. #[doc(hidden)] pub fn limbs_xor_in_place_left(xs: &mut Vec, ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); if xs_len >= ys_len { limbs_xor_same_length_in_place_left(&mut xs[..ys_len], ys); } else { limbs_xor_same_length_in_place_left(xs, &ys[..xs_len]); xs.extend_from_slice(&ys[xs_len..]); } } // Interpreting two `Vec`s of `Limb`s as the limbs (in ascending order) of two `Natural`s, writes // the limbs of the bitwise xor of the `Natural`s to the longer slice (or the first one, if they are // equally long). Returns a `bool` which is `false` when the output is to the first slice and `true` // when it's to the second slice. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `min(xs.len(), ys.len())`. // // This is equivalent to `mpz_xor` from `mpz/xor.c`, GMP 6.2.1, where both inputs are non-negative // and the result is written to the longer input slice. #[doc(hidden)] pub fn limbs_xor_in_place_either(xs: &mut [Limb], ys: &mut [Limb]) -> bool { let xs_len = xs.len(); let ys_len = ys.len(); let right = xs_len < ys_len; if right { limbs_xor_same_length_in_place_left(&mut ys[..xs_len], xs); } else { limbs_xor_same_length_in_place_left(&mut xs[..ys_len], ys); } right } impl Natural { #[inline] fn xor_limb(mut self, other: Limb) -> Self { self.xor_assign_limb(other); self } fn xor_limb_ref(&self, other: Limb) -> Self { Self(match self { Self(Small(small)) => Small(small ^ other), Self(Large(limbs)) => Large(limbs_xor_limb(limbs, other)), }) } fn xor_assign_limb(&mut self, other: Limb) { match self { Self(Small(small)) => *small ^= other, Self(Large(limbs)) => limbs_xor_limb_in_place(limbs, other), } } } impl BitXor for Natural { type Output = Self; /// Takes the bitwise xor of two [`Natural`]s, taking both by value. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) ^ Natural::from(456u32), 435); /// assert_eq!( /// Natural::from(10u32).pow(12) ^ (Natural::from(10u32).pow(12) - Natural::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(mut self, other: Self) -> Self { self ^= other; self } } impl<'a> BitXor<&'a Self> for Natural { type Output = Self; /// Takes the bitwise xor of two [`Natural`]s, taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(Natural::from(123u32) ^ &Natural::from(456u32), 435); /// assert_eq!( /// Natural::from(10u32).pow(12) ^ &(Natural::from(10u32).pow(12) - Natural::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(mut self, other: &'a Self) -> Self { self ^= other; self } } impl BitXor for &Natural { type Output = Natural; /// Takes the bitwise xor of two [`Natural`]s, taking the first by reference and the second by /// value. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) ^ Natural::from(456u32), 435); /// assert_eq!( /// &Natural::from(10u32).pow(12) ^ (Natural::from(10u32).pow(12) - Natural::ONE), /// 8191 /// ); /// ``` #[inline] fn bitxor(self, mut other: Natural) -> Natural { other ^= self; other } } impl BitXor<&Natural> for &Natural { type Output = Natural; /// Takes the bitwise xor of two [`Natural`]s, taking both by reference. /// /// $$ /// f(x, y) = x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// /// assert_eq!(&Natural::from(123u32) ^ &Natural::from(456u32), 435); /// assert_eq!( /// &Natural::from(10u32).pow(12) ^ &(Natural::from(10u32).pow(12) - Natural::ONE), /// 8191 /// ); /// ``` fn bitxor(self, other: &Natural) -> Natural { match (self, other) { (x, &Natural(Small(y))) => x.xor_limb_ref(y), (&Natural(Small(x)), y) => y.xor_limb_ref(x), (Natural(Large(xs)), Natural(Large(ys))) => { Natural::from_owned_limbs_asc(limbs_xor(xs, ys)) } } } } impl BitXorAssign for Natural { /// Bitwise-xors a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by value. /// /// $$ /// x \gets x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x ^= Natural::from(0x0000000fu32); /// x ^= Natural::from(0x00000f00u32); /// x ^= Natural::from(0x000f_0000u32); /// x ^= Natural::from(0x0f000000u32); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitxor_assign(&mut self, mut other: Self) { match (&mut *self, &mut other) { (_, Self(Small(y))) => self.xor_assign_limb(*y), (Self(Small(x)), _) => *self = other.xor_limb(*x), (Self(Large(xs)), Self(Large(ys))) => { if limbs_xor_in_place_either(xs, ys) { swap(xs, ys); } self.trim(); } } } } impl<'a> BitXorAssign<&'a Self> for Natural { /// Bitwise-xors a [`Natural`] with another [`Natural`] in place, taking the [`Natural`] on the /// right-hand side by reference. /// /// $$ /// x \gets x \oplus y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// /// let mut x = Natural::ZERO; /// x |= Natural::from(0x0000000fu32); /// x |= Natural::from(0x00000f00u32); /// x |= Natural::from(0x000f_0000u32); /// x |= Natural::from(0x0f000000u32); /// assert_eq!(x, 0x0f0f_0f0f); /// ``` fn bitxor_assign(&mut self, other: &'a Self) { match (&mut *self, other) { (_, Self(Small(y))) => self.xor_assign_limb(*y), (Self(Small(x)), _) => *self = other.xor_limb_ref(*x), (Self(Large(xs)), Self(Large(ys))) => { limbs_xor_in_place_left(xs, ys); self.trim(); } } } } ================================================ FILE: malachite-nz/src/natural/mod.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::platform::Limb; use alloc::string::String; use alloc::vec::Vec; #[cfg(feature = "doc-images")] use embed_doc_image::embed_doc_image; use malachite_base::comparison::traits::Min; use malachite_base::named::Named; use malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, ShrRound}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::slices::slice_trailing_zeros; /// A natural (non-negative) integer. /// /// Any `Natural` small enough to fit into a [`Limb`](crate#limbs) is represented inline. Only /// `Natural`s outside this range incur the costs of heap-allocation. #[cfg_attr( feature = "doc-images", embed_doc_image("natural-mem-layout", "images/natural-mem-layout.svg") )] #[derive(Clone, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr( feature = "serde", serde(try_from = "SerdeNatural", into = "SerdeNatural") )] pub struct Natural(pub(crate) InnerNatural); // We want to limit the visibility of the `Small` and `Large` constructors to within this crate. To // do this, we wrap the `InnerNatural` enum in a struct that gets compiled away. #[derive(Clone, Eq, Hash, PartialEq)] pub(crate) enum InnerNatural { Small(Limb), Large(Vec), } #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] pub(crate) struct SerdeNatural(String); impl Natural { // If a `Natural` is `Large` but is small enough to be `Small`, make it `Small`. fn demote_if_small(&mut self) { if let Self(Large(limbs)) = self { match limbs.len() { 0 => *self = Self::ZERO, 1 => *self = Self(Small(limbs[0])), _ => {} } } } // If a `Natural` is `Small`, make it `Large`. Return a reference to the `Limb` vector. pub(crate) fn promote_in_place(&mut self) -> &mut Vec { if let Self(Small(x)) = self { *self = Self(Large(vec![*x])); } if let Self(Large(xs)) = self { xs } else { unreachable!(); } } pub(crate) fn trim(&mut self) { if let Self(Large(limbs)) = self { let trailing_zero_count = slice_trailing_zeros(limbs); if trailing_zero_count != 0 { let len = limbs.len(); limbs.truncate(len - trailing_zero_count); } } self.demote_if_small(); } // Returns true iff `self` is valid. To be valid, // // `self` can only be `Large` when it is at least $2^W$, and cannot have leading zero limbs. All // `Natural`s must be valid. #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { match self { Self(Small(_)) => true, Self(Large(xs)) => xs.len() > 1 && *xs.last().unwrap() != 0, } } } /// The constant 0. impl Zero for Natural { const ZERO: Self = Self(Small(0)); } /// The constant 1. impl One for Natural { const ONE: Self = Self(Small(1)); } /// The constant 2. impl Two for Natural { const TWO: Self = Self(Small(2)); } /// The minimum value of a [`Natural`], 0. impl Min for Natural { const MIN: Self = Self::ZERO; } #[cfg(feature = "float_helpers")] impl Natural { pub const HIGH_BIT: Self = Self(Small(1 << (Limb::WIDTH - 1))); } impl Default for Natural { /// The default value of a [`Natural`], 0. fn default() -> Self { Self::ZERO } } // Implements `Named` for `Natural`. impl_named!(Natural); #[doc(hidden)] #[inline] pub fn limb_to_bit_count(n: usize) -> u64 { u64::wrapping_from(n) .arithmetic_checked_shl(Limb::LOG_WIDTH) .unwrap() } #[doc(hidden)] #[inline] pub fn bit_to_limb_count_floor(n: u64) -> usize { usize::exact_from(n >> Limb::LOG_WIDTH) } #[doc(hidden)] #[inline] pub fn bit_to_limb_count_ceiling(n: u64) -> usize { usize::exact_from(n.shr_round(Limb::LOG_WIDTH, Ceiling).0) } #[doc(hidden)] pub const LIMB_HIGH_BIT: Limb = 1 << (Limb::WIDTH - 1); /// Traits for arithmetic. pub mod arithmetic; /// Traits for comparing [`Natural`]s for equality or order. pub mod comparison; /// Traits for converting to and from [`Natural`]s, converting to and from strings, and extracting /// digits. pub mod conversion; /// Iterators that generate [`Natural`]s without repetition. pub mod exhaustive; /// Traits for generating primes, primality testing, and factorization (TODO!) pub mod factorization; /// Traits for logic and bit manipulation. pub mod logic; #[cfg(feature = "random")] /// Iterators that generate [`Natural`]s randomly. pub mod random; ================================================ FILE: malachite-nz/src/natural/random/mod.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::natural::arithmetic::mod_power_of_2::limbs_slice_mod_power_of_2_in_place; use crate::natural::logic::bit_access::limbs_slice_set_bit; use itertools::Itertools; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, PowerOf2, RoundToMultipleOfPowerOf2, ShrRound, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::iterators::iterator_to_bit_chunks; use malachite_base::num::logic::traits::{BitAccess, LowMask, SignificantBits}; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_positive_unsigneds, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use malachite_base::num::random::striped::{StripedBitSource, get_striped_unsigned_vec}; use malachite_base::num::random::{RandomPrimitiveInts, random_primitive_ints}; use malachite_base::random::Seed; use malachite_base::rounding_modes::RoundingMode::*; /// Generates a random [`Natural`] with a given maximum bit length. /// /// The [`Natural`] is chosen uniformly from $[0, 2^b)$; [`Natural`]s with bit lengths smaller than /// the maximum may also be generated. /// /// $$ /// P(n) = \\begin{cases} /// \frac{1}{2^b} & \text{if} \\quad 0 \\leq n < 2^b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::get_random_natural_with_up_to_bits; /// /// assert_eq!( /// get_random_natural_with_up_to_bits(&mut random_primitive_ints(EXAMPLE_SEED), 100) /// .to_string(), /// "976558340558744279591984426865" /// ); /// ``` pub fn get_random_natural_with_up_to_bits(xs: &mut RandomPrimitiveInts, bits: u64) -> Natural { if bits == 0 { return Natural::ZERO; } #[cfg(feature = "32_bit_limbs")] let mut xs = iterator_to_bit_chunks( xs.take(usize::exact_from(bits.shr_round(u64::LOG_WIDTH, Ceiling).0)), u64::WIDTH, u32::WIDTH, ) .map(Option::unwrap) .collect_vec(); #[cfg(not(feature = "32_bit_limbs"))] let mut xs = xs .take(usize::exact_from(bits.shr_round(u64::LOG_WIDTH, Ceiling).0)) .collect_vec(); limbs_slice_mod_power_of_2_in_place(&mut xs, bits); Natural::from_owned_limbs_asc(xs) } /// Generates a random [`Natural`] with a given bit length. /// /// The [`Natural`] is 0 if $b$ is 0, or else chosen uniformly from $[2^{b-1}, 2^b)$. /// /// $$ /// P(n) = \\begin{cases} /// 1 & \text{if} \\quad b = n = 0, \\\\ /// \frac{1}{2^{b-1}} & \text{if} \\quad b \neq 0 \\ \text{and} \\ 2^{b-1} \leq n < 2^b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::get_random_natural_with_bits; /// /// assert_eq!( /// get_random_natural_with_bits(&mut random_primitive_ints(EXAMPLE_SEED), 100).to_string(), /// "976558340558744279591984426865" /// ); /// ``` pub fn get_random_natural_with_bits(xs: &mut RandomPrimitiveInts, bits: u64) -> Natural { if bits == 0 { return Natural::ZERO; } #[cfg(feature = "32_bit_limbs")] let mut xs = iterator_to_bit_chunks( xs.take(usize::exact_from(bits.shr_round(u64::LOG_WIDTH, Ceiling).0)), u64::WIDTH, u32::WIDTH, ) .map(Option::unwrap) .collect_vec(); #[cfg(not(feature = "32_bit_limbs"))] let mut xs = xs .take(usize::exact_from(bits.shr_round(u64::LOG_WIDTH, Ceiling).0)) .collect_vec(); limbs_slice_mod_power_of_2_in_place(&mut xs, bits); limbs_slice_set_bit(&mut xs, bits - 1); Natural::from_owned_limbs_asc(xs) } /// Generates a striped random [`Natural`] with a given maximum bit length. /// /// [`Natural`]s with bit lengths smaller than the maximum may also be generated. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::get_striped_random_natural_with_up_to_bits; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// // 0x3fffff80000ffc007ffe03ff8 /// assert_eq!( /// get_striped_random_natural_with_up_to_bits(&mut bit_source, 100).to_string(), /// "316912612278197474676665499640" /// ); /// ``` pub fn get_striped_random_natural_with_up_to_bits(xs: &mut StripedBitSource, bits: u64) -> Natural { if bits == 0 { Natural::ZERO } else { Natural::from_owned_limbs_asc(get_striped_unsigned_vec(xs, bits)) } } /// Generates a striped random [`Natural`] with a given bit length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `bits`. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::get_striped_random_natural_with_bits; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// // 0xbfffff80000ffc007ffe03ff8 /// assert_eq!( /// get_striped_random_natural_with_bits(&mut bit_source, 100).to_string(), /// "950737912392312175425017102328" /// ); /// ``` pub fn get_striped_random_natural_with_bits(xs: &mut StripedBitSource, bits: u64) -> Natural { if bits == 0 { Natural::ZERO } else { let mut xs = get_striped_unsigned_vec(xs, bits); limbs_slice_set_bit(&mut xs, bits - 1); Natural::from_owned_limbs_asc(xs) } } /// Generates random [`Natural`]s, given an iterator of random bit lengths. #[derive(Clone, Debug)] pub struct RandomNaturals> { bits: I, limbs: RandomPrimitiveInts, } impl> Iterator for RandomNaturals { type Item = Natural; fn next(&mut self) -> Option { Some(get_random_natural_with_bits( &mut self.limbs, self.bits.next().unwrap(), )) } } /// Generates random [`Natural`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 0. Then a [`Natural`] is /// chosen uniformly among all [`Natural`]s with that bit length. The resulting distribution /// resembles a Pareto distribution. It has no mean or higher-order statistics (unless $m < 1$, /// which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// \\frac{1}{m + 1} & \text{if} \\quad n = 0, \\\\ /// \\frac{2}{m+1} \\left ( \\frac{m}{2(m+1)} \\right ) ^ {\\lfloor \\log_2 n \\rfloor + 1} & /// \text{if} \\quad \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if after being reduced /// to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_naturals; /// /// assert_eq!( /// prefix_to_string(random_naturals(EXAMPLE_SEED, 32, 1), 10), /// "[20431208470830262, 2777240, 114, 12184833305054, 1121025855008623490210, \ /// 13478874522577592, 115311695, 7, 18, 54522366353, ...]" /// ) /// ``` pub fn random_naturals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomNaturals> { RandomNaturals { bits: geometric_random_unsigneds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates random positive [`Natural`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. Then a [`Natural`] is /// chosen uniformly among all [`Natural`]s with that bit length. The resulting distribution /// resembles a Pareto distribution. It has no mean or higher-order statistics (unless $m < 2$, /// which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n = 0, \\\\ /// \frac{1}{m} \left ( \frac{m-1}{2m} \right ) ^ {\lfloor \log_2 n \rfloor} & /// \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_positive_naturals; /// /// assert_eq!( /// prefix_to_string(random_positive_naturals(EXAMPLE_SEED, 32, 1), 10), /// "[22, 4, 178, 55845661150, 93254818, 7577967529619388, 8, 11316951483471, 11, \ /// 1005760138411689342464923704482, ...]" /// ) /// ``` pub fn random_positive_naturals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomNaturals> { RandomNaturals { bits: geometric_random_positive_unsigneds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), } } /// Generates striped random [`Natural`]s, given an iterator of random bit lengths. #[derive(Clone, Debug)] pub struct StripedRandomNaturals> { bits: I, bit_source: StripedBitSource, } impl> Iterator for StripedRandomNaturals { type Item = Natural; fn next(&mut self) -> Option { Some(get_striped_random_natural_with_bits( &mut self.bit_source, self.bits.next().unwrap(), )) } } /// Generates striped random [`Natural`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 0. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Natural`] is generated from the sequence. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or, if /// after being reduced to lowest terms, their sum is greater than or equal to $2^{64}$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::striped_random_naturals; /// /// assert_eq!( /// prefix_to_string(striped_random_naturals(EXAMPLE_SEED, 16, 1, 32, 1), 10), /// "[18014656207519744, 2228160, 64, 17592184995840, 1179440951012584587264, \ /// 9007749010526207, 67108864, 5, 24, 34359738879, ...]" /// ) /// ``` pub fn striped_random_naturals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomNaturals> { StripedRandomNaturals { bits: geometric_random_unsigneds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Generates striped random positive [`Natural`]s with a specified mean bit length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. A striped bit /// sequence with the given stripe parameter is generated and truncated at the bit length. The /// highest bit is forced to be 1, and the [`Natural`] is generated from the sequence. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::striped_random_positive_naturals; /// /// assert_eq!( /// prefix_to_string( /// striped_random_positive_naturals(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[16, 4, 128, 34391195648, 75493376, 9007199120523391, 8, 8796094070783, 8, \ /// 950737950171027935941967741439, ...]" /// ) /// ``` pub fn striped_random_positive_naturals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomNaturals> { StripedRandomNaturals { bits: geometric_random_positive_unsigneds( seed.fork("bits"), mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), } } /// Uniformly generates random [`Natural`]s less than a positive limit. #[derive(Clone, Debug)] pub struct RandomNaturalsLessThan { bits: u64, limit: Natural, limbs: RandomPrimitiveInts, } impl Iterator for RandomNaturalsLessThan { type Item = Natural; fn next(&mut self) -> Option { loop { let x = get_random_natural_with_up_to_bits(&mut self.limbs, self.bits); if x < self.limit { return Some(x); } } } } /// Uniformly generates random [`Natural`]s less than a positive `limit`. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{\\ell} & \text{if} \\quad x < \\ell, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// where $\ell$ is `limit`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `limit.significant_bits()`. /// /// # Panics /// Panics if `limit` is 0. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_naturals_less_than; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// random_naturals_less_than(EXAMPLE_SEED, Natural::from(10u32)), /// 10 /// ), /// "[1, 7, 5, 7, 9, 2, 8, 2, 4, 6, ...]" /// ) /// ``` pub fn random_naturals_less_than(seed: Seed, limit: Natural) -> RandomNaturalsLessThan { assert_ne!(limit, 0); RandomNaturalsLessThan { bits: limit.ceiling_log_base_2(), limit, limbs: random_primitive_ints(seed), } } /// Generates a random [`Natural`] less than a given limit. /// /// The [`Natural`] is chosen uniformly from $[0, \ell)$, where $\ell$ is the provided limit. /// /// $$ /// P(n) = \\begin{cases} /// 1/\ell & \text{if} 0\leq n<\ell, \\\\ /// 0 & \\text{otherwise}, /// \\end{cases} /// $$ /// where $\ell$ is `limit`. /// /// # Expected complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and `n` is `limit.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_base::num::random::random_primitive_ints; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::get_random_natural_less_than; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// get_random_natural_less_than( /// &mut random_primitive_ints(EXAMPLE_SEED), /// &Natural::from(10u32).pow(20) /// ) /// .to_string(), /// "27702062732568241671" /// ); /// ``` pub fn get_random_natural_less_than( limbs: &mut RandomPrimitiveInts, limit: &Natural, ) -> Natural { assert_ne!(*limit, 0); let bits = limit.ceiling_log_base_2(); loop { let x = get_random_natural_with_up_to_bits(limbs, bits); if x < *limit { return x; } } } /// Uniformly generates random [`Natural`]s in an interval. #[derive(Clone, Debug)] pub struct UniformRandomNaturalRange { xs: RandomNaturalsLessThan, a: Natural, } impl Iterator for UniformRandomNaturalRange { type Item = Natural; fn next(&mut self) -> Option { self.xs.next().map(|x| &self.a + x) } } /// Uniformly generates random [`Natural`]s in the half-open interval $[a, b)$. /// /// $a$ must be less than $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a} & \text{if} \\quad a \leq x < b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a \geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::uniform_random_natural_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// uniform_random_natural_range(EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32)), /// 10 /// ), /// "[97, 17, 94, 37, 56, 32, 96, 11, 17, 39, ...]" /// ) /// ``` pub fn uniform_random_natural_range( seed: Seed, a: Natural, b: Natural, ) -> UniformRandomNaturalRange { assert!(a < b); UniformRandomNaturalRange { xs: random_naturals_less_than(seed, b - &a), a, } } /// Uniformly generates random [`Natural`]s in the closed interval $[a, b]$. /// /// $a$ must be less than or equal to $b$. /// /// $$ /// P(x) = \\begin{cases} /// \frac{1}{b-a+1} & \text{if} \\quad a \leq x \leq b, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::uniform_random_natural_inclusive_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// uniform_random_natural_inclusive_range( /// EXAMPLE_SEED, /// Natural::from(10u32), /// Natural::from(99u32) /// ), /// 10 /// ), /// "[97, 17, 94, 37, 56, 32, 96, 11, 17, 39, ...]" /// ) /// ``` #[inline] pub fn uniform_random_natural_inclusive_range( seed: Seed, a: Natural, b: Natural, ) -> UniformRandomNaturalRange { assert!(a <= b); uniform_random_natural_range(seed, a, b + Natural::ONE) } /// Generates random [`Natural`]s greater than or equal to a lower bound. #[derive(Clone, Debug)] pub struct RandomNaturalRangeToInfinity { min_bits: u64, bits: GeometricRandomNaturalValues, limbs: RandomPrimitiveInts, min_bit_xs: UniformRandomNaturalRange, } impl Iterator for RandomNaturalRangeToInfinity { type Item = Natural; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.min_bits { self.min_bit_xs.next() } else { Some(get_random_natural_with_bits(&mut self.limbs, bits)) } } } /// Generates random [`Natural`]s greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the [`Natural`]s is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// Then a [`Natural`] is chosen uniformly among all [`Natural`]s with that bit length that are /// greater than or equal to $a$. The resulting distribution has no mean or higher-order statistics /// (unless $a < m < a + 1$, which is not typical). /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n < a, \\\\ /// \frac{1}{m+1} & \text{if} \\quad a = n = 0, \\\\ /// \frac{m}{(m+1)^2}\left ( \frac{m}{2(m+1)} \right )^\nu & /// \text{if} \\quad 0 = a < n, \\\\ /// \frac{1}{(2^{\nu + 1}-a)(m-\alpha)} & /// \text{if} \\quad 0 < a \\ \text{and} \\ \alpha = \nu, \\\\ /// \frac{\left ( 1 - \frac{1}{\alpha-m}\right )^{\nu-\alpha}}{2^\nu(m-\alpha)} & /// \text{if} \\quad 0 < a \\ \text{and} \\ \alpha < \nu, \\\\ /// \\end{cases} /// $$ /// where $\alpha = \lfloor \log_2 a \rfloor$ and $\nu = \lfloor \log_2 n \rfloor$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their ratio is less than /// or equal to $a$, or if they are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_natural_range_to_infinity; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(1000u32), 20, 1), /// 10 /// ), /// "[3254, 4248, 163506, 1189717027294, 5282, 12220, 60088, 1016911, 5772451, 5473099750562, \ /// ...]" /// ) /// ``` pub fn random_natural_range_to_infinity( seed: Seed, a: Natural, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomNaturalRangeToInfinity { let min_bits = a.significant_bits(); RandomNaturalRangeToInfinity { min_bits, bits: geometric_random_unsigned_inclusive_range( seed.fork("bits"), min_bits, u64::MAX, mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), min_bit_xs: uniform_random_natural_range( seed.fork("min_bit_xs"), a, Natural::power_of_2(min_bits), ), } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomNaturalRangeMultipleOrders { min_bits: u64, max_bits: u64, bits: GeometricRandomNaturalValues, limbs: RandomPrimitiveInts, min_bit_xs: UniformRandomNaturalRange, max_bit_xs: UniformRandomNaturalRange, } impl Iterator for RandomNaturalRangeMultipleOrders { type Item = Natural; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.min_bits { self.min_bit_xs.next() } else if bits == self.max_bits { self.max_bit_xs.next() } else { Some(get_random_natural_with_bits(&mut self.limbs, bits)) } } } /// Generates random [`Natural`]s in an interval. #[derive(Clone, Debug)] #[allow(clippy::large_enum_variant)] pub enum RandomNaturalRange { SingleOrder(UniformRandomNaturalRange), MultipleOrders(RandomNaturalRangeMultipleOrders), } impl Iterator for RandomNaturalRange { type Item = Natural; fn next(&mut self) -> Option { match self { Self::SingleOrder(xs) => xs.next(), Self::MultipleOrders(xs) => xs.next(), } } } /// Generates random [`Natural`]s in the half-open interval $[a, b)$. /// /// In general, the [`Natural`]s are not generated uniformly; for that, use /// [`uniform_random_natural_range`]. Instead, [`Natural`]s with smaller bit lengths are generated /// more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_bits_numerator / mean_bits_denominator`. It is not actually the mean bit length, though it /// approaches the mean bit length as $\log (b/a)$ approaches infinity. $m$ must be greater than /// $a$, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// Once a bit length is selected, the [`Natural`] is chosen uniformly from all [`Natural`]s with /// that bit length that are in $[a, b)$. /// /// To obtain the probability mass function, adjust $b$ and see [`random_natural_inclusive_range`]. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_bits_numerator + /// mean_bits_denominator`, and $m$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a \geq b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their /// ratio is less than or equal to $a$, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_natural_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// random_natural_range( /// EXAMPLE_SEED, /// Natural::from(1000u32), /// Natural::from(1000000000u32), /// 20, /// 1 /// ), /// 10 /// ), /// "[3254, 4248, 163506, 600542, 5282, 12220, 60088, 1016911, 5772451, 2792610, ...]" /// ) /// ``` #[inline] pub fn random_natural_range( seed: Seed, a: Natural, b: Natural, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomNaturalRange { assert!(a < b); random_natural_inclusive_range( seed, a, b - Natural::ONE, mean_bits_numerator, mean_bits_denominator, ) } /// Generates random [`Natural`]s in the closed interval $[a, b]$. /// /// In general, the [`Natural`]s are not generated uniformly; for that, use /// [`uniform_random_natural_inclusive_range`]. Instead, [`Natural`]s with smaller bit lengths are /// generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_bits_numerator / mean_bits_denominator`. It is not actually the mean bit length, though it /// approaches the mean bit length as $\log (b/a)$ approaches infinity. $m$ must be greater than /// $a$, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// Once a bit length is selected, the [`Natural`] is chosen uniformly from all [`Natural`]s with /// that bit length that are in $[a, b]$. /// /// $$ /// P(n) = \\begin{cases} /// 0 & \text{if} \\quad n < a \\ \text{or} \\ n > b, \\\\ /// 1 & \text{if} \\quad a = n = b = 0, \\\\ /// \frac{1}{b-a} & \text{if} \\quad 0 < a \\ \text{and} \\ \alpha = \beta, \\\\ /// \left \[ (m+1)\left ( 1-\left (\frac{m}{m+1}\right )^{\beta+2} \right ) \right \]^{-1} & /// \text{if} \\quad 0 = a = n < b \\\\ /// (2^{\alpha+1}-n)\left \[ (m-\alpha)\left ( 1+\frac{1}{\alpha-m}\right )^{\alpha-\nu}- /// (m-\alpha-1)\left ( 1+\frac{1}{\alpha-m}\right )^{\beta-\nu}\right \]^{-1} & /// \text{if} \\quad 0 < a \\ \text{and} \\ \alpha = \nu < \beta, \\\\ /// \frac{m^{\nu+1}(m+1)^{\beta-\nu}}{((m+1)^{\beta+2}-m^{\beta+2})(2^\beta-n+1)} & /// \text{if} \\quad 0 = a < n \\ \text{and} \\ \nu = \beta, \\\\ /// (n-2^\beta+1)\left \[ (m-\alpha)\left ( 1+\frac{1}{\alpha-m}\right )^{\alpha-\nu}- /// (m-\alpha-1)\left ( 1+\frac{1}{\alpha-m}\right )^{\beta-\nu}\right \]^{-1} & /// \text{if} \\quad 0 < a \\ \text{and} \\ \alpha < \nu = \beta, \\\\ /// \frac{m(m+1)^\beta \left ( \frac{m}{2(m+1)}\right )^\nu}{(m+1)^{\beta+2}-m^{\beta+2}} & /// \text{if} \\quad 0 = a < n \\ \text{and} \\ \nu < \beta, \\\\ /// 2^{-\nu}\left \[ (m-\alpha)\left ( 1+\frac{1}{\alpha-m}\right )^{\alpha-\nu}-(m-\alpha-1) /// \left ( 1+\frac{1}{\alpha-m}\right )^{\beta-\nu}\right \]^{-1} & /// \text{if} \\quad 0 < a \\ \text{and} \\ \alpha < \nu < \beta, /// \\end{cases} /// $$ /// where $\alpha = \lfloor \log_2 a \rfloor$, $\beta = \lfloor \log_2 b \rfloor$, and $\nu = /// \lfloor \log_2 n \rfloor$. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_bits_numerator + /// mean_bits_denominator`, and $m$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a > b$, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their ratio /// is less than or equal to $a$, or if they are too large and manipulating them leads to arithmetic /// overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::random_natural_inclusive_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// random_natural_inclusive_range( /// EXAMPLE_SEED, /// Natural::from(1000u32), /// Natural::from(1000000000u32), /// 20, /// 1 /// ), /// 10 /// ), /// "[3254, 4248, 163506, 600542, 5282, 12220, 60088, 1016911, 5772451, 2792610, ...]" /// ) /// ``` pub fn random_natural_inclusive_range( seed: Seed, a: Natural, b: Natural, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomNaturalRange { assert!(a <= b); let min_bits = a.significant_bits(); let max_bits = b.significant_bits(); if min_bits == max_bits { RandomNaturalRange::SingleOrder(uniform_random_natural_inclusive_range(seed, a, b)) } else { RandomNaturalRange::MultipleOrders(RandomNaturalRangeMultipleOrders { min_bits, max_bits, bits: geometric_random_unsigned_inclusive_range( seed.fork("bits"), min_bits, max_bits, mean_bits_numerator, mean_bits_denominator, ), limbs: random_primitive_ints(seed.fork("limbs")), min_bit_xs: uniform_random_natural_range( seed.fork("min_bit_xs"), a, Natural::power_of_2(min_bits), ), max_bit_xs: uniform_random_natural_inclusive_range( seed.fork("max_bit_xs"), Natural::power_of_2(max_bits - 1), b, ), }) } } #[inline] fn ranges_intersect(lo_0: &T, hi_0: &T, lo: &T, hi: &T) -> bool { lo <= hi_0 && lo_0 <= hi } /// Generates random striped [`Natural`]s from a range. #[derive(Clone, Debug)] pub struct StripedRandomNaturalInclusiveRange { a: Natural, b: Natural, lo_template: Natural, hi_template: Natural, next_bit: u64, bit_source: StripedBitSource, } impl Iterator for StripedRandomNaturalInclusiveRange { type Item = Natural; fn next(&mut self) -> Option { if self.next_bit == 0 { return Some(self.lo_template.clone()); } let mut lo_template = self.lo_template.clone(); let mut hi_template = self.hi_template.clone(); let mut first = true; let mut previous_forced = true; let mut previous_bit = lo_template.get_bit(self.next_bit); for next_bit in (0..self.next_bit).rev() { let false_possible; let true_possible; if first { false_possible = true; true_possible = true; lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); first = false; } else { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); false_possible = ranges_intersect(&lo_template, &hi_template, &self.a, &self.b); lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); true_possible = ranges_intersect(&lo_template, &hi_template, &self.a, &self.b); } assert!(false_possible || true_possible); let bit = if !false_possible { previous_forced = true; true } else if !true_possible { previous_forced = true; false } else { if previous_forced { self.bit_source.end_block(); self.bit_source.set_previous_bit(previous_bit); previous_forced = false; } self.bit_source.next().unwrap() }; if !bit { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); } previous_bit = bit; } Some(lo_template) } } /// Generates random striped [`Natural`]s in the range $[a, b)$. /// /// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$, which is /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean /// run length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a\geq b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::basic::traits::One; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::natural::random::striped_random_natural_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// striped_random_natural_range(EXAMPLE_SEED, Natural::ONE, Natural::from(7u32), 4, 1) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1, 1, 110, 1, 110, 10, 11, 11, 100, ...]" /// ); /// ``` #[inline] pub fn striped_random_natural_range( seed: Seed, a: Natural, b: Natural, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomNaturalInclusiveRange { assert!(a < b); striped_random_natural_inclusive_range( seed, a, b - Natural::ONE, mean_stripe_numerator, mean_stripe_denominator, ) } /// Generates random striped [`Natural`]s in the range $[a, b]$. /// /// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean /// run length. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator <= /// mean_stripe_denominator`, or if $a > b$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::basic::traits::One; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::natural::random::striped_random_natural_inclusive_range; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// striped_random_natural_inclusive_range( /// EXAMPLE_SEED, /// Natural::ONE, /// Natural::from(6u32), /// 4, /// 1 /// ) /// .map(|x| x.to_binary_string()), /// 10 /// ), /// "[1, 1, 1, 110, 1, 110, 10, 11, 11, 100, ...]" /// ); /// ``` pub fn striped_random_natural_inclusive_range( seed: Seed, a: Natural, b: Natural, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> StripedRandomNaturalInclusiveRange { assert!(a <= b); let diff_bits = (&a ^ &b).significant_bits(); let mask = Natural::low_mask(diff_bits); let lo_template = (&a).round_to_multiple_of_power_of_2(diff_bits, Floor).0; let hi_template = &lo_template | mask; StripedRandomNaturalInclusiveRange { a, b, lo_template, hi_template, next_bit: diff_bits, bit_source: StripedBitSource::new(seed, mean_stripe_numerator, mean_stripe_denominator), } } /// Generates a random striped [`Natural`] in the range $[a, b)$. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a\geq b$. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::natural::random::get_striped_random_natural_from_range; /// use malachite_nz::natural::Natural; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// assert_eq!( /// get_striped_random_natural_from_range( /// &mut bit_source, /// Natural::from(10000u32), /// Natural::from(20000u32) /// ) /// .to_binary_string(), /// "10011100111111" /// ); /// ``` #[inline] pub fn get_striped_random_natural_from_range( xs: &mut StripedBitSource, a: Natural, b: Natural, ) -> Natural { assert!(a < b); get_striped_random_natural_from_inclusive_range(xs, a, b - Natural::ONE) } /// Generates a random striped [`Natural`] in the range $[a, b]$. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `b.significant_bits()`. /// /// # Panics /// Panics if $a > b$. /// /// # Examples /// ``` /// use malachite_base::num::random::striped::StripedBitSource; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_base::strings::ToBinaryString; /// use malachite_nz::natural::random::get_striped_random_natural_from_inclusive_range; /// use malachite_nz::natural::Natural; /// /// let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 10, 1); /// assert_eq!( /// get_striped_random_natural_from_inclusive_range( /// &mut bit_source, /// Natural::from(10000u32), /// Natural::from(19999u32) /// ) /// .to_binary_string(), /// "10011100111111" /// ); /// ``` #[allow(clippy::needless_pass_by_value)] pub fn get_striped_random_natural_from_inclusive_range( xs: &mut StripedBitSource, a: Natural, b: Natural, ) -> Natural { assert!(a <= b); let diff_bits = (&a ^ &b).significant_bits(); let mask = Natural::low_mask(diff_bits); let lo_template = (&a).round_to_multiple_of_power_of_2(diff_bits, Floor).0; let hi_template = &lo_template | mask; if diff_bits == 0 { return lo_template; } let mut lo_template = lo_template.clone(); let mut hi_template = hi_template.clone(); let mut first = true; let mut previous_forced = true; let mut previous_bit = lo_template.get_bit(diff_bits); for next_bit in (0..diff_bits).rev() { let false_possible; let true_possible; if first { false_possible = true; true_possible = true; lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); first = false; } else { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); false_possible = ranges_intersect(&lo_template, &hi_template, &a, &b); lo_template.assign_bit(next_bit, true); hi_template.assign_bit(next_bit, true); true_possible = ranges_intersect(&lo_template, &hi_template, &a, &b); } assert!(false_possible || true_possible); let bit = if !false_possible { previous_forced = true; true } else if !true_possible { previous_forced = true; false } else { if previous_forced { xs.end_block(); xs.set_previous_bit(previous_bit); previous_forced = false; } xs.next().unwrap() }; if !bit { lo_template.assign_bit(next_bit, false); hi_template.assign_bit(next_bit, false); } previous_bit = bit; } lo_template } /// Generates striped random [`Natural`]s greater than or equal to a lower bound. #[derive(Clone, Debug)] pub struct StripedRandomNaturalRangeToInfinity { min_bits: u64, bits: GeometricRandomNaturalValues, bit_source: StripedBitSource, min_bit_xs: StripedRandomNaturalInclusiveRange, } impl Iterator for StripedRandomNaturalRangeToInfinity { type Item = Natural; fn next(&mut self) -> Option { let bits = self.bits.next().unwrap(); if bits == self.min_bits { self.min_bit_xs.next() } else { Some(get_striped_random_natural_with_bits( &mut self.bit_source, bits, )) } } } /// Generates striped random [`Natural`]s greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the [`Natural`]s is specified; it must be greater than the bit length /// of $a$. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The actual bit length is chosen from a geometric distribution with lower bound $a$ and mean $m$. /// The resulting distribution has no mean or higher-order statistics (unless $a < m < a + 1$, which /// is not typical). /// /// The [`Natural`]s are generated using a striped bit sequence with mean run length $m$ = /// `mean_stripe_numerator / mean_stripe_denominator`. /// /// Because the [`Natural`]s are constrained to be within a certain range, the actual mean run /// length will usually not be $m$. Nonetheless, setting a higher $m$ will result in a higher mean /// run length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n / m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `mean_precision_numerator`, and $m$ is /// `mean_precision_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if their /// ratio is less than or equal to $a$, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::random::striped_random_natural_range_to_infinity; /// use malachite_nz::natural::Natural; /// /// assert_eq!( /// prefix_to_string( /// striped_random_natural_range_to_infinity( /// EXAMPLE_SEED, /// Natural::from(1000u32), /// 20, /// 1, /// 14, /// 1 /// ), /// 10 /// ), /// "[8192, 14336, 16376, 1024, 1024, 1023, 2047, 245760, 8195, 131070, ...]" /// ) /// ``` pub fn striped_random_natural_range_to_infinity( seed: Seed, a: Natural, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomNaturalRangeToInfinity { let min_bits = a.significant_bits(); StripedRandomNaturalRangeToInfinity { min_bits, bits: geometric_random_unsigned_inclusive_range( seed.fork("bits"), min_bits, u64::MAX, mean_bits_numerator, mean_bits_denominator, ), bit_source: StripedBitSource::new( seed.fork("bit_source"), mean_stripe_numerator, mean_stripe_denominator, ), min_bit_xs: striped_random_natural_range( seed.fork("min_bit_xs"), a, Natural::power_of_2(min_bits), mean_stripe_numerator, mean_stripe_denominator, ), } } ================================================ FILE: malachite-nz/src/platform_32.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `bin2kk`, `bin2kkinv`, and `fac2bin` contributed to the GNU project by Torbjörn Granlund // and Marco Bodrato. // // Copyright © 2002, 2010-2018 Free Software Foundation, Inc. // // Uses code adopted from the GNU MPFR Library. // // Copyright © 2005-2022 Free Software Foundation, Inc. // // 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 . pub type Limb = u32; pub type HalfLimb = u16; pub type DoubleLimb = u64; pub type SignedLimb = i32; pub type SignedHalfLimb = i16; pub type SignedDoubleLimb = i64; pub type FloatWithLimbWidth = f32; pub(crate) const MAX_DIGITS_PER_LIMB: usize = 10; // TODO tune pub(crate) const AORSMUL_FASTER_2AORSLSH: bool = true; // TODO tune pub(crate) const AORSMUL_FASTER_3AORSLSH: bool = true; // TODO tune pub(crate) const AORSMUL_FASTER_AORS_AORSLSH: bool = true; // TODO tune pub(crate) const AORSMUL_FASTER_AORS_2AORSLSH: bool = true; // TODO tune pub(crate) const MUL_TOOM22_THRESHOLD: usize = 118; // TODO tune pub(crate) const MUL_TOOM33_THRESHOLD: usize = 101; // TODO tune pub(crate) const MUL_TOOM44_THRESHOLD: usize = 530; // TODO tune pub(crate) const MUL_TOOM6H_THRESHOLD: usize = 738; // TODO tune pub(crate) const MUL_TOOM8H_THRESHOLD: usize = 984; // TODO tune pub(crate) const MUL_TOOM32_TO_TOOM43_THRESHOLD: usize = 315; // TODO tune pub(crate) const MUL_TOOM32_TO_TOOM53_THRESHOLD: usize = 307; // TODO tune pub(crate) const MUL_TOOM42_TO_TOOM53_THRESHOLD: usize = 328; // TODO tune pub(crate) const MUL_TOOM42_TO_TOOM63_THRESHOLD: usize = 295; // TODO tune pub(crate) const MUL_FFT_THRESHOLD: usize = 5608; // TODO tune pub(crate) const DC_DIV_QR_THRESHOLD: usize = 7; // TODO tune pub(crate) const DC_DIVAPPR_Q_THRESHOLD: usize = 151; // TODO tune pub(crate) const MAYBE_DCP1_DIVAPPR: bool = true; // TODO tune pub(crate) const INV_NEWTON_THRESHOLD: usize = 618; // TODO tune pub(crate) const MU_DIV_QR_THRESHOLD: usize = 2243; // TODO tune pub(crate) const INV_MULMOD_BNM1_THRESHOLD: usize = 68; // TODO tune pub(crate) const MU_DIV_QR_SKEW_THRESHOLD: usize = 233; // TODO tune pub(crate) const MU_DIVAPPR_Q_THRESHOLD: usize = 2297; // TODO tune pub(crate) const FUDGE: usize = 261; // TODO tune pub(crate) const MULLO_BASECASE_THRESHOLD: usize = 0; // TODO tune pub(crate) const MULLO_DC_THRESHOLD: usize = 216; // TODO tune pub(crate) const MULLO_MUL_N_THRESHOLD: usize = 100000; // TODO tune pub(crate) const BINV_NEWTON_THRESHOLD: usize = 3264; // TODO tune pub(crate) const DC_BDIV_QR_THRESHOLD: usize = 329; // TODO tune pub(crate) const MU_BDIV_QR_THRESHOLD: usize = 50000; // TODO tune pub(crate) const DC_BDIV_Q_THRESHOLD: usize = 373; // TODO tune pub(crate) const MU_BDIV_Q_THRESHOLD: usize = 2390; // TODO tune pub(crate) const MOD_1_NORM_THRESHOLD: usize = 0; // TODO tune pub(crate) const MOD_1_UNNORM_THRESHOLD: usize = 0; // TODO tune pub(crate) const MOD_1_1P_METHOD: bool = true; // TODO tune pub(crate) const MOD_1N_TO_MOD_1_1_THRESHOLD: usize = 3; // TODO tune pub(crate) const MOD_1U_TO_MOD_1_1_THRESHOLD: usize = 3; // TODO tune pub(crate) const MOD_1_1_TO_MOD_1_2_THRESHOLD: usize = 15; // TODO tune pub(crate) const MOD_1_2_TO_MOD_1_4_THRESHOLD: usize = 43; // TODO tune pub(crate) const BMOD_1_TO_MOD_1_THRESHOLD: usize = 31; // TODO tune pub(crate) const SQR_BASECASE_THRESHOLD: usize = 0; // TODO tune #[doc(hidden)] pub const SQR_TOOM2_THRESHOLD: usize = 222; // TODO tune pub(crate) const SQR_TOOM3_THRESHOLD: usize = 205; // TODO tune pub(crate) const SQR_TOOM4_THRESHOLD: usize = 1170; // TODO tune pub(crate) const SQR_TOOM6_THRESHOLD: usize = 512; // TODO tune pub(crate) const SQR_TOOM8_THRESHOLD: usize = 644; // TODO tune pub(crate) const SQRLO_DC_THRESHOLD: usize = 460; // TODO tune pub(crate) const FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD: u64 = 12000; // TODO tune pub(crate) const MATRIX22_STRASSEN_THRESHOLD: usize = 50; // This section is created by digits_data.rs. // mp_bases[10] data, as literal values pub(crate) const MP_BASES_CHARS_PER_LIMB_10: usize = 9; pub(crate) const MP_BASES_BIG_BASE_10: Limb = 0x3b9aca00; pub(crate) const MP_BASES_BIG_BASE_INVERTED_10: Limb = 0x12e0be82; pub(crate) const MP_BASES_NORMALIZATION_STEPS_10: u64 = 2; // Format is (chars_per_limb, logb2, log2b, big_base, big_base_inverted) pub(crate) const BASES: [(usize, Limb, Limb, Limb, Limb); 257] = [ (0, 0, 0, 0, 0), // 0 (0, 0, 0, 0, 0), // 1 (32, 0xffffffff, 0x1fffffff, 0x1, 0x0), // 2 (20, 0xa1849cc1, 0x32b80347, 0xcfd41b91, 0x3b563c24), // 3 (16, 0x7fffffff, 0x3fffffff, 0x2, 0x0), // 4 (13, 0x6e40d1a4, 0x4a4d3c25, 0x48c27395, 0xc25c2684), // 5 (12, 0x6308c91b, 0x52b80347, 0x81bf1000, 0xf91bd1b6), // 6 (11, 0x5b3064eb, 0x59d5d9fd, 0x75db9c97, 0x1607a2cb), // 7 (10, 0x55555555, 0x5fffffff, 0x3, 0x0), // 8 (10, 0x50c24e60, 0x6570068e, 0xcfd41b91, 0x3b563c24), // 9 (9, 0x4d104d42, 0x6a4d3c25, 0x3b9aca00, 0x12e0be82), // 10 (9, 0x4a002707, 0x6eb3a9f0, 0x8c8b6d2b, 0xd24cde04), // 11 (8, 0x4768ce0d, 0x72b80347, 0x19a10000, 0x3fa39ab5), // 12 (8, 0x452e53e3, 0x766a008e, 0x309f1021, 0x50f8ac5f), // 13 (8, 0x433cfffb, 0x79d5d9fd, 0x57f6c100, 0x74843b1e), // 14 (8, 0x41867711, 0x7d053f6d, 0x98c29b81, 0xad0326c2), // 15 (8, 0x3fffffff, 0x7fffffff, 0x4, 0x0), // 16 (7, 0x3ea16afd, 0x82cc7edf, 0x18754571, 0x4ef0b6bd), // 17 (7, 0x3d64598d, 0x8570068e, 0x247dbc80, 0xc0fc48a1), // 18 (7, 0x3c43c230, 0x87ef05ae, 0x3547667b, 0x33838942), // 19 (7, 0x3b3b9a42, 0x8a4d3c25, 0x4c4b4000, 0xad7f29ab), // 20 (7, 0x3a4898f0, 0x8c8ddd44, 0x6b5a6e1d, 0x313c3d15), // 21 (7, 0x39680b13, 0x8eb3a9f0, 0x94ace180, 0xb8cca9e0), // 22 (7, 0x3897b2b7, 0x90c10500, 0xcaf18367, 0x42ed6de9), // 23 (6, 0x37d5aed1, 0x92b80347, 0xb640000, 0x67980e0b), // 24 (6, 0x372068d2, 0x949a784b, 0xe8d4a51, 0x19799812), // 25 (6, 0x3676867e, 0x966a008e, 0x1269ae40, 0xbce85396), // 26 (6, 0x35d6deeb, 0x982809d5, 0x17179149, 0x62c103a9), // 27 (6, 0x354071d6, 0x99d5d9fd, 0x1cb91000, 0x1d353d43), // 28 (6, 0x34b260c5, 0x9b74948f, 0x23744899, 0xce1decea), // 29 (6, 0x342be986, 0x9d053f6d, 0x2b73a840, 0x790fc511), // 30 (6, 0x33ac61b9, 0x9e88c6b3, 0x34e63b41, 0x35b865a0), // 31 (6, 0x33333333, 0x9fffffff, 0x5, 0x0), // 32 (6, 0x32bfd901, 0xa16bad37, 0x4cfa3cc1, 0xa9aed1b3), // 33 (6, 0x3251dcf6, 0xa2cc7edf, 0x5c13d840, 0x63dfc229), // 34 (6, 0x31e8d59f, 0xa4231623, 0x6d91b519, 0x2b0fee30), // 35 (6, 0x3184648d, 0xa570068e, 0x81bf1000, 0xf91bd1b6), // 36 (6, 0x312434e8, 0xa6b3d78b, 0x98ede0c9, 0xac89c3a9), // 37 (6, 0x30c7fa34, 0xa7ef05ae, 0xb3773e40, 0x6d2c32fe), // 38 (6, 0x306f6f4c, 0xa92203d5, 0xd1bbc4d1, 0x387907c9), // 39 (6, 0x301a557f, 0xaa4d3c25, 0xf4240000, 0xc6f7a0b), // 40 (5, 0x2fc873d1, 0xab7110e6, 0x6e7d349, 0x28928154), // 41 (5, 0x2f799652, 0xac8ddd44, 0x7ca30a0, 0x6e8629d), // 42 (5, 0x2f2d8d8f, 0xada3f5fb, 0x8c32bbb, 0xd373dca0), // 43 (5, 0x2ee42e16, 0xaeb3a9f0, 0x9d46c00, 0xa0b17895), // 44 (5, 0x2e9d5009, 0xafbd42b4, 0xaffacfd, 0x746811a5), // 45 (5, 0x2e58cec0, 0xb0c10500, 0xc46bee0, 0x4da6500f), // 46 (5, 0x2e168874, 0xb1bf311e, 0xdab86ef, 0x2ba23582), // 47 (5, 0x2dd65df7, 0xb2b80347, 0xf300000, 0xdb20a88), // 48 (5, 0x2d983275, 0xb3abb3fa, 0x10d63af1, 0xe68d5ce4), // 49 (5, 0x2d5beb38, 0xb49a784b, 0x12a05f20, 0xb7cdfd9d), // 50 (5, 0x2d216f79, 0xb5848226, 0x1490aae3, 0x8e583933), // 51 (5, 0x2ce8a82e, 0xb66a008e, 0x16a97400, 0x697cc3ea), // 52 (5, 0x2cb17fea, 0xb74b1fd6, 0x18ed2825, 0x48a5ca6c), // 53 (5, 0x2c7be2b0, 0xb82809d5, 0x1b5e4d60, 0x2b52db16), // 54 (5, 0x2c47bddb, 0xb900e615, 0x1dff8297, 0x111586a6), // 55 (5, 0x2c14fffc, 0xb9d5d9fd, 0x20d38000, 0xf31d2b36), // 56 (5, 0x2be398c3, 0xbaa708f5, 0x23dd1799, 0xc8d76d19), // 57 (5, 0x2bb378e7, 0xbb74948f, 0x271f35a0, 0xa2cb1eb4), // 58 (5, 0x2b849210, 0xbc3e9ca2, 0x2a9ce10b, 0x807c3ec3), // 59 (5, 0x2b56d6c7, 0xbd053f6d, 0x2e593c00, 0x617ec8bf), // 60 (5, 0x2b2a3a60, 0xbdc899ab, 0x3257844d, 0x45746cbe), // 61 (5, 0x2afeb0f1, 0xbe88c6b3, 0x369b13e0, 0x2c0aa273), // 62 (5, 0x2ad42f3c, 0xbf45e08b, 0x3b27613f, 0x14f90805), // 63 (5, 0x2aaaaaaa, 0xbfffffff, 0x6, 0x0), // 64 (5, 0x2a82193a, 0xc0b73cb4, 0x4528a141, 0xd9cf0829), // 65 (5, 0x2a5a7176, 0xc16bad37, 0x4aa51420, 0xb6fc4841), // 66 (5, 0x2a33aa6e, 0xc21d6713, 0x50794633, 0x973054cb), // 67 (5, 0x2a0dbbaa, 0xc2cc7edf, 0x56a94400, 0x7a1dbe4b), // 68 (5, 0x29e89d24, 0xc3790848, 0x5d393975, 0x5f7fcd7f), // 69 (5, 0x29c44740, 0xc4231623, 0x642d7260, 0x47196c84), // 70 (5, 0x29a0b2c7, 0xc4caba78, 0x6b8a5ae7, 0x30b43635), // 71 (5, 0x297dd8db, 0xc570068e, 0x73548000, 0x1c1fa5f6), // 72 (5, 0x295bb2f9, 0xc6130af4, 0x7b908fe9, 0x930634a), // 73 (5, 0x293a3aeb, 0xc6b3d78b, 0x84435aa0, 0xef7f4a3c), // 74 (5, 0x29196acc, 0xc7527b93, 0x8d71d25b, 0xcf5552d2), // 75 (5, 0x28f93cfb, 0xc7ef05ae, 0x97210c00, 0xb1a47c8e), // 76 (5, 0x28d9ac1b, 0xc88983ed, 0xa1563f9d, 0x9634b43e), // 77 (5, 0x28bab310, 0xc92203d5, 0xac16c8e0, 0x7cd3817d), // 78 (5, 0x289c4cf8, 0xc9b89267, 0xb768278f, 0x65536761), // 79 (5, 0x287e7529, 0xca4d3c25, 0xc3500000, 0x4f8b588e), // 80 (5, 0x28612730, 0xcae00d1c, 0xcfd41b91, 0x3b563c24), // 81 (5, 0x28445ec9, 0xcb7110e6, 0xdcfa6920, 0x28928154), // 82 (5, 0x282817e1, 0xcc0052b1, 0xeac8fd83, 0x1721bfb0), // 83 (5, 0x280c4e90, 0xcc8ddd44, 0xf9461400, 0x6e8629d), // 84 (4, 0x27f0ff1b, 0xcd19bb05, 0x31c84b1, 0x491cc17c), // 85 (4, 0x27d625ec, 0xcda3f5fb, 0x342ab10, 0x3a11d83b), // 86 (4, 0x27bbbf95, 0xce2c97d6, 0x36a2c21, 0x2be074cd), // 87 (4, 0x27a1c8c8, 0xceb3a9f0, 0x3931000, 0x1e7a02e7), // 88 (4, 0x27883e5e, 0xcf393550, 0x3bd5ee1, 0x11d10edd), // 89 (4, 0x276f1d4c, 0xcfbd42b4, 0x3e92110, 0x5d92c68), // 90 (4, 0x275662a8, 0xd03fda8b, 0x4165ef1, 0xf50dbfb2), // 91 (4, 0x273e0ba3, 0xd0c10500, 0x4452100, 0xdf9f1316), // 92 (4, 0x2726158c, 0xd140c9fa, 0x4756fd1, 0xcb52a684), // 93 (4, 0x270e7dc9, 0xd1bf311e, 0x4a75410, 0xb8163e97), // 94 (4, 0x26f741dd, 0xd23c41d4, 0x4dad681, 0xa5d8f269), // 95 (4, 0x26e05f5f, 0xd2b80347, 0x5100000, 0x948b0fcd), // 96 (4, 0x26c9d3fe, 0xd3327c6a, 0x546d981, 0x841e0215), // 97 (4, 0x26b39d7f, 0xd3abb3fa, 0x57f6c10, 0x74843b1e), // 98 (4, 0x269db9bc, 0xd423b07e, 0x5b9c0d1, 0x65b11e6e), // 99 (4, 0x268826a1, 0xd49a784b, 0x5f5e100, 0x5798ee23), // 100 (4, 0x2672e22d, 0xd5101187, 0x633d5f1, 0x4a30b99b), // 101 (4, 0x265dea72, 0xd5848226, 0x673a910, 0x3d6e4d94), // 102 (4, 0x26493d93, 0xd5f7cff4, 0x6b563e1, 0x314825b0), // 103 (4, 0x2634d9c2, 0xd66a008e, 0x6f91000, 0x25b55f2e), // 104 (4, 0x2620bd41, 0xd6db196a, 0x73eb721, 0x1aadaccb), // 105 (4, 0x260ce662, 0xd74b1fd6, 0x7866310, 0x10294ba2), // 106 (4, 0x25f95385, 0xd7ba18f9, 0x7d01db1, 0x620f8f6), // 107 (4, 0x25e60316, 0xd82809d5, 0x81bf100, 0xf91bd1b6), // 108 (4, 0x25d2f390, 0xd894f74b, 0x869e711, 0xe6d37b2a), // 109 (4, 0x25c02379, 0xd900e615, 0x8ba0a10, 0xd55cff6e), // 110 (4, 0x25ad9165, 0xd96bdad2, 0x90c6441, 0xc4ad2db2), // 111 (4, 0x259b3bf3, 0xd9d5d9fd, 0x9610000, 0xb4b985cf), // 112 (4, 0x258921cb, 0xda3ee7f3, 0x9b7e7c1, 0xa5782bef), // 113 (4, 0x257741a2, 0xdaa708f5, 0xa112610, 0x96dfdd2a), // 114 (4, 0x25659a37, 0xdb0e4126, 0xa6cc591, 0x88e7e509), // 115 (4, 0x25542a50, 0xdb74948f, 0xacad100, 0x7b8813d3), // 116 (4, 0x2542f0c2, 0xdbda071c, 0xb2b5331, 0x6eb8b595), // 117 (4, 0x2531ec64, 0xdc3e9ca2, 0xb8e5710, 0x627289db), // 118 (4, 0x25211c1c, 0xdca258dc, 0xbf3e7a1, 0x56aebc07), // 119 (4, 0x25107ed5, 0xdd053f6d, 0xc5c1000, 0x4b66dc33), // 120 (4, 0x25001383, 0xdd6753e0, 0xcc6db61, 0x4094d8a3), // 121 (4, 0x24efd921, 0xddc899ab, 0xd345510, 0x3632f7a5), // 122 (4, 0x24dfceb3, 0xde29142e, 0xda48871, 0x2c3bd1f0), // 123 (4, 0x24cff343, 0xde88c6b3, 0xe178100, 0x22aa4d5f), // 124 (4, 0x24c045e1, 0xdee7b471, 0xe8d4a51, 0x19799812), // 125 (4, 0x24b0c5a6, 0xdf45e08b, 0xf05f010, 0x10a523e5), // 126 (4, 0x24a171b0, 0xdfa34e11, 0xf817e01, 0x828a237), // 127 (4, 0x24924924, 0xdfffffff, 0x7, 0x0), // 128 (4, 0x24834b2c, 0xe05bf942, 0x10818201, 0xf04ec452), // 129 (4, 0x247476f9, 0xe0b73cb4, 0x11061010, 0xe136444a), // 130 (4, 0x2465cbc0, 0xe111cd1d, 0x118db651, 0xd2af9589), // 131 (4, 0x245748bc, 0xe16bad37, 0x12188100, 0xc4b42a83), // 132 (4, 0x2448ed2f, 0xe1c4dfab, 0x12a67c71, 0xb73dccf5), // 133 (4, 0x243ab85d, 0xe21d6713, 0x1337b510, 0xaa4698c5), // 134 (4, 0x242ca992, 0xe27545fb, 0x13cc3761, 0x9dc8f729), // 135 (4, 0x241ec01b, 0xe2cc7edf, 0x14641000, 0x91bf9a30), // 136 (4, 0x2410fb4d, 0xe323142d, 0x14ff4ba1, 0x86257887), // 137 (4, 0x24035a80, 0xe3790848, 0x159df710, 0x7af5c98c), // 138 (4, 0x23f5dd10, 0xe3ce5d82, 0x16401f31, 0x702c01a0), // 139 (4, 0x23e8825d, 0xe4231623, 0x16e5d100, 0x65c3ceb1), // 140 (4, 0x23db49cc, 0xe4773465, 0x178f1991, 0x5bb91502), // 141 (4, 0x23ce32c4, 0xe4caba78, 0x183c0610, 0x5207ec23), // 142 (4, 0x23c13cb3, 0xe51daa7e, 0x18eca3c1, 0x48ac9c19), // 143 (4, 0x23b46706, 0xe570068e, 0x19a10000, 0x3fa39ab5), // 144 (4, 0x23a7b132, 0xe5c1d0b5, 0x1a592841, 0x36e98912), // 145 (4, 0x239b1aac, 0xe6130af4, 0x1b152a10, 0x2e7b3140), // 146 (4, 0x238ea2ef, 0xe663b741, 0x1bd51311, 0x2655840b), // 147 (4, 0x23824976, 0xe6b3d78b, 0x1c98f100, 0x1e7596ea), // 148 (4, 0x23760dc3, 0xe7036db3, 0x1d60d1b1, 0x16d8a20d), // 149 (4, 0x2369ef58, 0xe7527b93, 0x1e2cc310, 0xf7bfe87), // 150 (4, 0x235dedbb, 0xe7a102f9, 0x1efcd321, 0x85d2492), // 151 (4, 0x23520874, 0xe7ef05ae, 0x1fd11000, 0x179a9f4), // 152 (4, 0x23463f10, 0xe83c856d, 0x20a987e1, 0xf59e80eb), // 153 (4, 0x233a911b, 0xe88983ed, 0x21864910, 0xe8b768db), // 154 (4, 0x232efe26, 0xe8d602d9, 0x226761f1, 0xdc39d6d5), // 155 (4, 0x232385c6, 0xe92203d5, 0x234ce100, 0xd021c5d1), // 156 (4, 0x2318278e, 0xe96d887e, 0x2436d4d1, 0xc46b5e37), // 157 (4, 0x230ce318, 0xe9b89267, 0x25254c10, 0xb912f39c), // 158 (4, 0x2301b7fd, 0xea03231d, 0x26185581, 0xae150294), // 159 (4, 0x22f6a5d9, 0xea4d3c25, 0x27100000, 0xa36e2eb1), // 160 (4, 0x22ebac4c, 0xea96defe, 0x280c5a81, 0x991b4094), // 161 (4, 0x22e0caf6, 0xeae00d1c, 0x290d7410, 0x8f19241e), // 162 (4, 0x22d60179, 0xeb28c7f2, 0x2a135bd1, 0x8564e6b7), // 163 (4, 0x22cb4f7a, 0xeb7110e6, 0x2b1e2100, 0x7bfbb5b4), // 164 (4, 0x22c0b4a1, 0xebb8e95d, 0x2c2dd2f1, 0x72dadcc8), // 165 (4, 0x22b63095, 0xec0052b1, 0x2d428110, 0x69ffc498), // 166 (4, 0x22abc300, 0xec474e39, 0x2e5c3ae1, 0x6167f154), // 167 (4, 0x22a16b90, 0xec8ddd44, 0x2f7b1000, 0x5911016e), // 168 (4, 0x229729f1, 0xecd4011c, 0x309f1021, 0x50f8ac5f), // 169 (4, 0x228cfdd4, 0xed19bb05, 0x31c84b10, 0x491cc17c), // 170 (4, 0x2282e6e9, 0xed5f0c3c, 0x32f6d0b1, 0x417b26d8), // 171 (4, 0x2278e4e3, 0xeda3f5fb, 0x342ab100, 0x3a11d83b), // 172 (4, 0x226ef777, 0xede87974, 0x3563fc11, 0x32dee622), // 173 (4, 0x22651e5a, 0xee2c97d6, 0x36a2c210, 0x2be074cd), // 174 (4, 0x225b5944, 0xee705249, 0x37e71341, 0x2514bb58), // 175 (4, 0x2251a7ee, 0xeeb3a9f0, 0x39310000, 0x1e7a02e7), // 176 (4, 0x22480a11, 0xeef69fea, 0x3a8098c1, 0x180ea5d0), // 177 (4, 0x223e7f69, 0xef393550, 0x3bd5ee10, 0x11d10edd), // 178 (4, 0x223507b4, 0xef7b6b39, 0x3d311091, 0xbbfb88e), // 179 (4, 0x222ba2af, 0xefbd42b4, 0x3e921100, 0x5d92c68), // 180 (4, 0x22225019, 0xeffebccd, 0x3ff90031, 0x1c024c), // 181 (4, 0x22190fb4, 0xf03fda8b, 0x4165ef10, 0xf50dbfb2), // 182 (4, 0x220fe141, 0xf0809cf2, 0x42d8eea1, 0xea30efa3), // 183 (4, 0x2206c483, 0xf0c10500, 0x44521000, 0xdf9f1316), // 184 (4, 0x21fdb93f, 0xf10113b1, 0x45d16461, 0xd555c0c9), // 185 (4, 0x21f4bf3a, 0xf140c9fa, 0x4756fd10, 0xcb52a684), // 186 (4, 0x21ebd639, 0xf18028cf, 0x48e2eb71, 0xc193881f), // 187 (4, 0x21e2fe06, 0xf1bf311e, 0x4a754100, 0xb8163e97), // 188 (4, 0x21da3667, 0xf1fde3d3, 0x4c0e0f51, 0xaed8b724), // 189 (4, 0x21d17f28, 0xf23c41d4, 0x4dad6810, 0xa5d8f269), // 190 (4, 0x21c8d811, 0xf27a4c05, 0x4f535d01, 0x9d15039d), // 191 (4, 0x21c040ef, 0xf2b80347, 0x51000000, 0x948b0fcd), // 192 (4, 0x21b7b98f, 0xf2f56875, 0x52b36301, 0x8c394d1d), // 193 (4, 0x21af41bc, 0xf3327c6a, 0x546d9810, 0x841e0215), // 194 (4, 0x21a6d947, 0xf36f3ffb, 0x562eb151, 0x7c3784f8), // 195 (4, 0x219e7ffd, 0xf3abb3fa, 0x57f6c100, 0x74843b1e), // 196 (4, 0x219635af, 0xf3e7d937, 0x59c5d971, 0x6d02985d), // 197 (4, 0x218dfa2e, 0xf423b07e, 0x5b9c0d10, 0x65b11e6e), // 198 (4, 0x2185cd4c, 0xf45f3a98, 0x5d796e61, 0x5e8e5c64), // 199 (4, 0x217daeda, 0xf49a784b, 0x5f5e1000, 0x5798ee23), // 200 (4, 0x21759eac, 0xf4d56a5b, 0x614a04a1, 0x50cf7bde), // 201 (4, 0x216d9c96, 0xf5101187, 0x633d5f10, 0x4a30b99b), // 202 (4, 0x2165a86e, 0xf54a6e8c, 0x65383231, 0x43bb66bd), // 203 (4, 0x215dc207, 0xf5848226, 0x673a9100, 0x3d6e4d94), // 204 (4, 0x2155e939, 0xf5be4d0c, 0x69448e91, 0x374842ee), // 205 (4, 0x214e1ddb, 0xf5f7cff4, 0x6b563e10, 0x314825b0), // 206 (4, 0x21465fc4, 0xf6310b8f, 0x6d6fb2c1, 0x2b6cde75), // 207 (4, 0x213eaecd, 0xf66a008e, 0x6f910000, 0x25b55f2e), // 208 (4, 0x21370ace, 0xf6a2af9e, 0x71ba3941, 0x2020a2c5), // 209 (4, 0x212f73a0, 0xf6db196a, 0x73eb7210, 0x1aadaccb), // 210 (4, 0x2127e920, 0xf7133e9b, 0x7624be11, 0x155b891f), // 211 (4, 0x21206b26, 0xf74b1fd6, 0x78663100, 0x10294ba2), // 212 (4, 0x2118f98f, 0xf782bdbf, 0x7aafdeb1, 0xb160fe9), // 213 (4, 0x21119436, 0xf7ba18f9, 0x7d01db10, 0x620f8f6), // 214 (4, 0x210a3af8, 0xf7f13221, 0x7f5c3a21, 0x14930ef), // 215 (4, 0x2102edb3, 0xf82809d5, 0x81bf1000, 0xf91bd1b6), // 216 (4, 0x20fbac44, 0xf85ea0b0, 0x842a70e1, 0xefdcb0c7), // 217 (4, 0x20f4768a, 0xf894f74b, 0x869e7110, 0xe6d37b2a), // 218 (4, 0x20ed4c62, 0xf8cb0e3b, 0x891b24f1, 0xddfeb94a), // 219 (4, 0x20e62dae, 0xf900e615, 0x8ba0a100, 0xd55cff6e), // 220 (4, 0x20df1a4b, 0xf9367f6d, 0x8e2ef9d1, 0xcceced50), // 221 (4, 0x20d8121c, 0xf96bdad2, 0x90c64410, 0xc4ad2db2), // 222 (4, 0x20d11500, 0xf9a0f8d3, 0x93669481, 0xbc9c75f9), // 223 (4, 0x20ca22d9, 0xf9d5d9fd, 0x96100000, 0xb4b985cf), // 224 (4, 0x20c33b88, 0xfa0a7eda, 0x98c29b81, 0xad0326c2), // 225 (4, 0x20bc5ef1, 0xfa3ee7f3, 0x9b7e7c10, 0xa5782bef), // 226 (4, 0x20b58cf5, 0xfa7315d0, 0x9e43b6d1, 0x9e1771a9), // 227 (4, 0x20aec579, 0xfaa708f5, 0xa1126100, 0x96dfdd2a), // 228 (4, 0x20a8085e, 0xfadac1e7, 0xa3ea8ff1, 0x8fd05c41), // 229 (4, 0x20a1558b, 0xfb0e4126, 0xa6cc5910, 0x88e7e509), // 230 (4, 0x209aace2, 0xfb418734, 0xa9b7d1e1, 0x8225759d), // 231 (4, 0x20940e49, 0xfb74948f, 0xacad1000, 0x7b8813d3), // 232 (4, 0x208d79a5, 0xfba769b3, 0xafac2921, 0x750eccf9), // 233 (4, 0x2086eedb, 0xfbda071c, 0xb2b53310, 0x6eb8b595), // 234 (4, 0x20806dd2, 0xfc0c6d44, 0xb5c843b1, 0x6884e923), // 235 (4, 0x2079f671, 0xfc3e9ca2, 0xb8e57100, 0x627289db), // 236 (4, 0x2073889d, 0xfc7095ae, 0xbc0cd111, 0x5c80c07b), // 237 (4, 0x206d243e, 0xfca258dc, 0xbf3e7a10, 0x56aebc07), // 238 (4, 0x2066c93c, 0xfcd3e6a0, 0xc27a8241, 0x50fbb19b), // 239 (4, 0x2060777e, 0xfd053f6d, 0xc5c10000, 0x4b66dc33), // 240 (4, 0x205a2eed, 0xfd3663b2, 0xc91209c1, 0x45ef7c7c), // 241 (4, 0x2053ef71, 0xfd6753e0, 0xcc6db610, 0x4094d8a3), // 242 (4, 0x204db8f3, 0xfd981064, 0xcfd41b91, 0x3b563c24), // 243 (4, 0x20478b5c, 0xfdc899ab, 0xd3455100, 0x3632f7a5), // 244 (4, 0x20416696, 0xfdf8f020, 0xd6c16d31, 0x312a60c3), // 245 (4, 0x203b4a8b, 0xfe29142e, 0xda488710, 0x2c3bd1f0), // 246 (4, 0x20353725, 0xfe59063c, 0xdddab5a1, 0x2766aa45), // 247 (4, 0x202f2c4e, 0xfe88c6b3, 0xe1781000, 0x22aa4d5f), // 248 (4, 0x202929f0, 0xfeb855f8, 0xe520ad61, 0x1e06233c), // 249 (4, 0x20232ff8, 0xfee7b471, 0xe8d4a510, 0x19799812), // 250 (4, 0x201d3e50, 0xff16e281, 0xec940e71, 0x15041c33), // 251 (4, 0x201754e5, 0xff45e08b, 0xf05f0100, 0x10a523e5), // 252 (4, 0x201173a1, 0xff74aef0, 0xf4359451, 0xc5c2749), // 253 (4, 0x200b9a71, 0xffa34e11, 0xf817e010, 0x828a237), // 254 (4, 0x2005c942, 0xffd1be4c, 0xfc05fc01, 0x40a1423), // 255 (4, 0x1fffffff, 0xffffffff, 0x8, 0x0), // 256 ]; // This section is created by factorial_data.rs. // This is equivalent to `__gmp_oddfac_table` in `mpn/comb_tables.c`, GMP 6.2.1, which is the // combination of `ONE_LIMB_ODD_FACTORIAL_TABLE` and `ONE_LIMB_ODD_FACTORIAL_EXTTABLE` in // `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_FACTORIAL_TABLE: [Limb; 35] = [ 0x1, 0x1, 0x1, 0x3, 0x3, 0xf, 0x2d, 0x13b, 0x13b, 0xb13, 0x375f, 0x26115, 0x7233f, 0x5cca33, 0x2898765, 0x260eeeeb, 0x260eeeeb, 0x86fddd9b, 0xbeecca73, 0x2b930689, 0xd9df20ad, 0xdf4dae31, 0x98567c1b, 0xafc5266d, 0xf4f7347, 0x7ec241ef, 0x6fdd5923, 0xcc5866b1, 0x966aced7, 0xa196e5b, 0x977d7755, 0x5831734b, 0x5831734b, 0x5e5fdcab, 0x445da75b, ]; // This is equivalent to `ODD_FACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_TABLE_LIMIT: usize = 16; // This is equivalent to `ODD_FACTORIAL_EXTTABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_EXTTABLE_LIMIT: usize = 34; // This is equivalent to `ODD_FACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_TABLE_MAX: Limb = 0x260eeeeb; // This is equivalent to `__gmp_odd2fac_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE: [Limb; 10] = [0x1, 0x3, 0xf, 0x69, 0x3b1, 0x289b, 0x20fdf, 0x1eee11, 0x20dcf21, 0x27065f73]; // This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_DOUBLEFACTORIAL_TABLE_LIMIT: usize = 19; // This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_DOUBLEFACTORIAL_TABLE_MAX: Limb = 0x27065f73; // This is equivalent to `__gmp_limbroots_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `NTH_ROOT_NUMB_MASK_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const NTH_ROOT_NUMB_MASK_TABLE: [Limb; 8] = [Limb::MAX, 0xffff, 0x659, 0xff, 0x54, 0x28, 0x17, 0xf]; // This is equivalent to `ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE: [Limb; 31] = [ 0x1, 0xaaaaaaab, 0xaaaaaaab, 0xeeeeeeef, 0xa4fa4fa5, 0xf2ff2ff3, 0xf2ff2ff3, 0x53e3771b, 0xdd93e49f, 0xfcdee63d, 0x544a4cbf, 0x7ca340fb, 0xa417526d, 0xd7bd49c3, 0xd7bd49c3, 0x85294093, 0xf259eabb, 0xd6dc4fb9, 0x915f4325, 0x131cead1, 0xea76fe13, 0x633cd365, 0x21144677, 0x200b0d0f, 0x8c4f9e8b, 0x21a42251, 0xe03c04e7, 0x600211d3, 0x4aaacdfd, 0x33f4fe63, 0x33f4fe63, ]; pub(crate) const ODD_CENTRAL_BINOMIAL_OFFSET: usize = 8; // This table contains binomial(2k, k) / 2 ^ t. // // This is equivalent to `bin2kk` in `mpz/bin_uiui.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE: [Limb; 11] = [ 0x1923, 0x2f7b, 0xb46d, 0x15873, 0xa50c7, 0x13d66b, 0x4c842f, 0x93ee7d, 0x11e9e123, 0x22c60053, 0x873ae4d1, ]; pub(crate) const ODD_CENTRAL_BINOMIAL_TABLE_LIMIT: usize = 18; // This table contains the inverses of elements in the previous table. // // This is equivalent to `bin2kkinv` in `mpz/bin_uiui.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE: [Limb; 11] = [ 0x16a2de8b, 0x847457b3, 0xfa6f7565, 0xf0e50cbb, 0xdca370f7, 0x9bb12643, 0xdc8342cf, 0x4ebf7ad5, 0x86ab568b, 0x265843db, 0x8633f431, ]; // This table contains the values t in the formula binomial(2k, k) / 2 ^ t. // // This is equivalent to `fac2bin` in `mpz/bin_uiui.c`, GMP 6.2.1, and `CENTRAL_BINOMIAL_2FAC_TABLE` // from `fac_table.h`, GMP 6.2.1. pub(crate) const CENTRAL_BINOMIAL_2FAC_TABLE: [u64; 11] = [1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2]; // https://oeis.org/A005187, skipping the initial 0 // // This is equivalent to `__gmp_fac2cnt_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `TABLE_2N_MINUS_POPC_2N` from `fac_table.h`, GMP 6.2.1. pub(crate) const TABLE_2N_MINUS_POPC_2N: [u8; 24] = [1, 3, 4, 7, 8, 10, 11, 15, 16, 18, 19, 22, 23, 25, 26, 31, 32, 34, 35, 38, 39, 41, 42, 46]; pub(crate) const TABLE_LIMIT_2N_MINUS_POPC_2N: u64 = 49; // end of auto-generated code ================================================ FILE: malachite-nz/src/platform_64.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `bin2kk`, `bin2kkinv`, and `fac2bin` contributed to the GNU project by Torbjörn Granlund // and Marco Bodrato. // // Copyright © 2002, 2010-2018 Free Software Foundation, Inc. // // Uses code adopted from the GNU MPFR Library. // // Copyright © 2005-2022 Free Software Foundation, Inc. // // 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 . pub type Limb = u64; pub type HalfLimb = u32; pub type DoubleLimb = u128; pub type SignedLimb = i64; pub type SignedHalfLimb = i32; pub type SignedDoubleLimb = i128; pub type FloatWithLimbWidth = f64; pub(crate) const MAX_DIGITS_PER_LIMB: usize = 20; pub(crate) const AORSMUL_FASTER_2AORSLSH: bool = true; pub(crate) const AORSMUL_FASTER_3AORSLSH: bool = true; pub(crate) const AORSMUL_FASTER_AORS_AORSLSH: bool = true; pub(crate) const AORSMUL_FASTER_AORS_2AORSLSH: bool = true; pub(crate) const MUL_TOOM22_THRESHOLD: usize = 20; pub(crate) const MUL_TOOM33_THRESHOLD: usize = 39; pub(crate) const MUL_TOOM44_THRESHOLD: usize = 340; // unclear when 44 is better than 33 pub(crate) const MUL_TOOM6H_THRESHOLD: usize = 345; pub(crate) const MUL_TOOM8H_THRESHOLD: usize = 640; pub(crate) const MUL_TOOM32_TO_TOOM43_THRESHOLD: usize = 60; pub(crate) const MUL_TOOM32_TO_TOOM53_THRESHOLD: usize = 300; pub(crate) const MUL_TOOM42_TO_TOOM53_THRESHOLD: usize = 600; pub(crate) const MUL_TOOM42_TO_TOOM63_THRESHOLD: usize = 103; pub(crate) const MUL_FFT_THRESHOLD: usize = 1500; pub(crate) const DC_DIV_QR_THRESHOLD: usize = 85; pub(crate) const DC_DIVAPPR_Q_THRESHOLD: usize = 211; pub(crate) const MAYBE_DCP1_DIVAPPR: bool = true; pub(crate) const INV_NEWTON_THRESHOLD: usize = 789; pub(crate) const MU_DIV_QR_THRESHOLD: usize = 2094; pub(crate) const INV_MULMOD_BNM1_THRESHOLD: usize = 62; pub(crate) const MU_DIV_QR_SKEW_THRESHOLD: usize = 231; pub(crate) const MU_DIVAPPR_Q_THRESHOLD: usize = 2965; pub(crate) const FUDGE: usize = 311; pub(crate) const MULLO_BASECASE_THRESHOLD: usize = 1; pub(crate) const MULLO_DC_THRESHOLD: usize = 56; pub(crate) const MULLO_MUL_N_THRESHOLD: usize = 10806; pub(crate) const BINV_NEWTON_THRESHOLD: usize = 2211; pub(crate) const DC_BDIV_QR_THRESHOLD: usize = 211; pub(crate) const MU_BDIV_QR_THRESHOLD: usize = 7547; pub(crate) const DC_BDIV_Q_THRESHOLD: usize = 211; pub(crate) const MU_BDIV_Q_THRESHOLD: usize = 1998; pub(crate) const MOD_1_NORM_THRESHOLD: usize = 0; pub(crate) const MOD_1_UNNORM_THRESHOLD: usize = 0; pub(crate) const MOD_1_1P_METHOD: bool = false; pub(crate) const MOD_1N_TO_MOD_1_1_THRESHOLD: usize = 3; pub(crate) const MOD_1U_TO_MOD_1_1_THRESHOLD: usize = 0; pub(crate) const MOD_1_1_TO_MOD_1_2_THRESHOLD: usize = 6; pub(crate) const MOD_1_2_TO_MOD_1_4_THRESHOLD: usize = 26; pub(crate) const BMOD_1_TO_MOD_1_THRESHOLD: usize = 100000000; pub(crate) const SQR_BASECASE_THRESHOLD: usize = 0; pub(crate) const SQR_TOOM2_THRESHOLD: usize = 43; pub(crate) const SQR_TOOM3_THRESHOLD: usize = 390; pub(crate) const SQR_TOOM4_THRESHOLD: usize = 1090; pub(crate) const SQR_TOOM6_THRESHOLD: usize = 336; pub(crate) const SQR_TOOM8_THRESHOLD: usize = 837; pub(crate) const SQRLO_DC_THRESHOLD: usize = 389; pub(crate) const FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD: u64 = 6500; pub(crate) const MATRIX22_STRASSEN_THRESHOLD: usize = 30; // This section is created by digits_data.rs. // mp_bases[10] data, as literal values pub(crate) const MP_BASES_CHARS_PER_LIMB_10: usize = 19; pub(crate) const MP_BASES_BIG_BASE_10: Limb = 0x8ac7230489e80000; pub(crate) const MP_BASES_BIG_BASE_INVERTED_10: Limb = 0xd83c94fb6d2ac34a; pub(crate) const MP_BASES_NORMALIZATION_STEPS_10: u64 = 0; // Format is (chars_per_limb, logb2, log2b, big_base, big_base_inverted) pub(crate) const BASES: [(usize, Limb, Limb, Limb, Limb); 257] = [ (0, 0, 0, 0, 0), // 0 (0, 0, 0, 0, 0), // 1 (64, 0xffffffffffffffff, 0x1fffffffffffffff, 0x1, 0x0), // 2 ( 40, 0xa1849cc1a9a9e94e, 0x32b803473f7ad0f3, 0xa8b8b452291fe821, 0x846d550e37b5063d, ), // 3 (32, 0x7fffffffffffffff, 0x3fffffffffffffff, 0x2, 0x0), // 4 ( 27, 0x6e40d1a4143dcb94, 0x4a4d3c25e68dc57f, 0x6765c793fa10079d, 0x3ce9a36f23c0fc90, ), // 5 ( 24, 0x6308c91b702a7cf4, 0x52b803473f7ad0f3, 0x41c21cb8e1000000, 0xf24f62335024a295, ), // 6 ( 22, 0x5b3064eb3aa6d388, 0x59d5d9fd5010b366, 0x3642798750226111, 0x2df495ccaa57147b, ), // 7 (21, 0x5555555555555555, 0x5fffffffffffffff, 0x3, 0x0), // 8 ( 20, 0x50c24e60d4d4f4a7, 0x6570068e7ef5a1e7, 0xa8b8b452291fe821, 0x846d550e37b5063d, ), // 9 ( 19, 0x4d104d427de7fbcc, 0x6a4d3c25e68dc57f, 0x8ac7230489e80000, 0xd83c94fb6d2ac34a, ), // 10 ( 18, 0x4a00270775914e88, 0x6eb3a9f01975077f, 0x4d28cb56c33fa539, 0xa8adf7ae45e7577b, ), // 11 ( 17, 0x4768ce0d05818e12, 0x72b803473f7ad0f3, 0x1eca170c00000000, 0xa10c2bec5da8f8f, ), // 12 ( 17, 0x452e53e365907bda, 0x766a008e4788cbcd, 0x780c7372621bd74d, 0x10f4becafe412ec3, ), // 13 ( 16, 0x433cfffb4b5aae55, 0x79d5d9fd5010b366, 0x1e39a5057d810000, 0xf08480f672b4e86, ), // 14 ( 16, 0x41867711b4f85355, 0x7d053f6d26089673, 0x5b27ac993df97701, 0x6779c7f90dc42f48, ), // 15 (16, 0x3fffffffffffffff, 0x7fffffffffffffff, 0x4, 0x0), // 16 ( 15, 0x3ea16afd58b10966, 0x82cc7edf592262cf, 0x27b95e997e21d9f1, 0x9c71e11bab279323, ), // 17 ( 15, 0x3d64598d154dc4de, 0x8570068e7ef5a1e7, 0x5da0e1e53c5c8000, 0x5dfaa697ec6f6a1c, ), // 18 ( 15, 0x3c43c23018bb5563, 0x87ef05ae409a0288, 0xd2ae3299c1c4aedb, 0x3711783f6be7e9ec, ), // 19 ( 14, 0x3b3b9a42873069c7, 0x8a4d3c25e68dc57f, 0x16bcc41e90000000, 0x6849b86a12b9b01e, ), // 20 ( 14, 0x3a4898f06cf41ac9, 0x8c8ddd448f8b845a, 0x2d04b7fdd9c0ef49, 0x6bf097ba5ca5e239, ), // 21 ( 14, 0x39680b13582e7c18, 0x8eb3a9f01975077f, 0x5658597bcaa24000, 0x7b8015c8d7af8f08, ), // 22 ( 14, 0x3897b2b751ae561a, 0x90c10500d63aa658, 0xa0e2073737609371, 0x975a24b3a3151b38, ), // 23 ( 13, 0x37d5aed131f19c98, 0x92b803473f7ad0f3, 0xc29e98000000000, 0x50bd367972689db1, ), // 24 ( 13, 0x372068d20a1ee5ca, 0x949a784bcd1b8afe, 0x14adf4b7320334b9, 0x8c240c4aecb13bb5, ), // 25 ( 13, 0x3676867e5d60de29, 0x966a008e4788cbcd, 0x226ed36478bfa000, 0xdbd2e56854e118c9, ), // 26 ( 13, 0x35d6deeb388df86f, 0x982809d5be7072db, 0x383d9170b85ff80b, 0x2351ffcaa9c7c4ae, ), // 27 ( 13, 0x354071d61c77fa2e, 0x99d5d9fd5010b366, 0x5a3c23e39c000000, 0x6b24188ca33b0636, ), // 28 ( 13, 0x34b260c5671b18ac, 0x9b74948f5532da4b, 0x8e65137388122bcd, 0xcc3dceaf2b8ba99d, ), // 29 ( 13, 0x342be986572b45cc, 0x9d053f6d26089673, 0xdd41bb36d259e000, 0x2832e835c6c7d6b6, ), // 30 ( 12, 0x33ac61b998fbbdf2, 0x9e88c6b3626a72aa, 0xaee5720ee830681, 0x76b6aa272e1873c5, ), // 31 (12, 0x3333333333333333, 0x9fffffffffffffff, 0x5, 0x0), // 32 ( 12, 0x32bfd90114c12861, 0xa16bad3758efd873, 0x172588ad4f5f0981, 0x61eaf5d402c7bf4f, ), // 33 ( 12, 0x3251dcf6169e45f2, 0xa2cc7edf592262cf, 0x211e44f7d02c1000, 0xeeb658123ffb27ec, ), // 34 ( 12, 0x31e8d59f180dc630, 0xa4231623369e78e5, 0x2ee56725f06e5c71, 0x5d5e3762e6fdf509, ), // 35 ( 12, 0x3184648db8153e7a, 0xa570068e7ef5a1e7, 0x41c21cb8e1000000, 0xf24f62335024a295, ), // 36 ( 12, 0x312434e89c35dacd, 0xa6b3d78b6d3b24fb, 0x5b5b57f8a98a5dd1, 0x66ae7831762efb6f, ), // 37 ( 12, 0x30c7fa349460a541, 0xa7ef05ae409a0288, 0x7dcff8986ea31000, 0x47388865a00f544, ), // 38 ( 12, 0x306f6f4c8432bc6d, 0xa92203d587039cc1, 0xabd4211662a6b2a1, 0x7d673c33a123b54c, ), // 39 ( 12, 0x301a557ffbfdd252, 0xaa4d3c25e68dc57f, 0xe8d4a51000000000, 0x19799812dea11197, ), // 40 ( 11, 0x2fc873d1fda55f3b, 0xab7110e6ce866f2b, 0x7a32956ad081b79, 0xc27e62e0686feae, ), // 41 ( 11, 0x2f799652a4e6dc49, 0xac8ddd448f8b845a, 0x9f49aaff0e86800, 0x9b6e7507064ce7c7, ), // 42 ( 11, 0x2f2d8d8f64460aad, 0xada3f5fb9c415052, 0xce583bb812d37b3, 0x3d9ac2bf66cfed94, ), // 43 ( 11, 0x2ee42e164e8f53a4, 0xaeb3a9f01975077f, 0x109b79a654c00000, 0xed46bc50ce59712a, ), // 44 ( 11, 0x2e9d500984041dbd, 0xafbd42b465836767, 0x1543beff214c8b95, 0x813d97e2c89b8d46, ), // 45 ( 11, 0x2e58cec05a6a8144, 0xb0c10500d63aa658, 0x1b149a79459a3800, 0x2e81751956af8083, ), // 46 ( 11, 0x2e1688743ef9104c, 0xb1bf311e95d00de3, 0x224edfb5434a830f, 0xdd8e0a95e30c0988, ), // 47 ( 11, 0x2dd65df7a583598f, 0xb2b803473f7ad0f3, 0x2b3fb00000000000, 0x7ad4dd48a0b5b167, ), // 48 ( 11, 0x2d9832759d5369c4, 0xb3abb3faa02166cc, 0x3642798750226111, 0x2df495ccaa57147b, ), // 49 ( 11, 0x2d5beb38dcd1394c, 0xb49a784bcd1b8afe, 0x43c33c1937564800, 0xe392010175ee5962, ), // 50 ( 11, 0x2d216f7943e2ba6a, 0xb5848226989d33c3, 0x54411b2441c3cd8b, 0x84eaf11b2fe7738e, ), // 51 ( 11, 0x2ce8a82efbb3ff2c, 0xb66a008e4788cbcd, 0x6851455acd400000, 0x3a1e3971e008995d, ), // 52 ( 11, 0x2cb17fea7ad7e332, 0xb74b1fd64e0753c6, 0x80a23b117c8feb6d, 0xfd7a462344ffce25, ), // 53 ( 11, 0x2c7be2b0cfa1ba50, 0xb82809d5be7072db, 0x9dff7d32d5dc1800, 0x9eca40b40ebcef8a, ), // 54 ( 11, 0x2c47bddba92d7463, 0xb900e6160002ccfe, 0xc155af6faeffe6a7, 0x52fa161a4a48e43d, ), // 55 ( 11, 0x2c14fffcaa8b131e, 0xb9d5d9fd5010b366, 0xebb7392e00000000, 0x1607a2cbacf930c1, ), // 56 ( 10, 0x2be398c3a38be053, 0xbaa708f58014d37c, 0x50633659656d971, 0x97a014f8e3be55f1, ), // 57 ( 10, 0x2bb378e758451068, 0xbb74948f5532da4b, 0x5fa8624c7fba400, 0x568df8b76cbf212c, ), // 58 ( 10, 0x2b8492108be5e5f7, 0xbc3e9ca2e1a05533, 0x717d9faa73c5679, 0x20ba7c4b4e6ef492, ), // 59 ( 10, 0x2b56d6c70d55481b, 0xbd053f6d26089673, 0x86430aac6100000, 0xe81ee46b9ef492f5, ), // 60 ( 10, 0x2b2a3a608c72ddd5, 0xbdc899ab3ff56c5e, 0x9e64d9944b57f29, 0x9dc0d10d51940416, ), // 61 ( 10, 0x2afeb0f1060c7e41, 0xbe88c6b3626a72aa, 0xba5ca5392cb0400, 0x5fa8ed2f450272a5, ), // 62 ( 10, 0x2ad42f3c9aca595c, 0xbf45e08bcf06554e, 0xdab2ce1d022cd81, 0x2ba9eb8c5e04e641, ), // 63 (10, 0x2aaaaaaaaaaaaaaa, 0xbfffffffffffffff, 0x6, 0x0), // 64 ( 10, 0x2a82193a13425883, 0xc0b73cb42e16914c, 0x12aeed5fd3e2d281, 0xb67759cc00287bf1, ), // 65 ( 10, 0x2a5a717672f66450, 0xc16bad3758efd873, 0x15c3da1572d50400, 0x78621feeb7f4ed33, ), // 66 ( 10, 0x2a33aa6e56d9c71c, 0xc21d6713f453f356, 0x194c05534f75ee29, 0x43d55b5f72943bc0, ), // 67 ( 10, 0x2a0dbbaa3bdfcea4, 0xc2cc7edf592262cf, 0x1d56299ada100000, 0x173decb64d1d4409, ), // 68 ( 10, 0x29e89d244eb4bfaf, 0xc379084815b5774c, 0x21f2a089a4ff4f79, 0xe29fb54fd6b6074f, ), // 69 ( 10, 0x29c44740d7db51e6, 0xc4231623369e78e5, 0x2733896c68d9a400, 0xa1f1f5c210d54e62, ), // 70 ( 10, 0x29a0b2c743b14d74, 0xc4caba789e2b8687, 0x2d2cf2c33b533c71, 0x6aac7f9bfafd57b2, ), // 71 ( 10, 0x297dd8dbb7c22a2d, 0xc570068e7ef5a1e7, 0x33f506e440000000, 0x3b563c2478b72ee2, ), // 72 ( 10, 0x295bb2f9285c8c1b, 0xc6130af40bc0ecbf, 0x3ba43bec1d062211, 0x12b536b574e92d1b, ), // 73 ( 10, 0x293a3aebe2be1c92, 0xc6b3d78b6d3b24fb, 0x4455872d8fd4e400, 0xdf86c03020404fa5, ), // 74 ( 10, 0x29196acc815ebd9f, 0xc7527b930c965bf2, 0x4e2694539f2f6c59, 0xa34adf02234eea8e, ), // 75 ( 10, 0x28f93cfb40f5c22a, 0xc7ef05ae409a0288, 0x5938006c18900000, 0x6f46eb8574eb59dd, ), // 76 ( 10, 0x28d9ac1badc64117, 0xc88983ed6985bae5, 0x65ad9912474aa649, 0x42459b481df47cec, ), // 77 ( 10, 0x28bab310a196b478, 0xc92203d587039cc1, 0x73ae9ff4241ec400, 0x1b424b95d80ca505, ), // 78 ( 10, 0x289c4cf88b774469, 0xc9b892675266f66c, 0x836612ee9c4ce1e1, 0xf2c1b982203a0dac, ), // 79 ( 10, 0x287e7529fb244e91, 0xca4d3c25e68dc57f, 0x9502f90000000000, 0xb7cdfd9d7bdbab7d, ), // 80 ( 10, 0x286127306a6a7a53, 0xcae00d1cfdeb43cf, 0xa8b8b452291fe821, 0x846d550e37b5063d, ), // 81 ( 10, 0x28445ec93f792b1e, 0xcb7110e6ce866f2b, 0xbebf59a07dab4400, 0x57931eeaf85cf64f, ), // 82 ( 10, 0x282817e1038950fa, 0xcc0052b18b0e2a19, 0xd7540d4093bc3109, 0x305a944507c82f47, ), // 83 ( 10, 0x280c4e90c9ab1f45, 0xcc8ddd448f8b845a, 0xf2b96616f1900000, 0xe007ccc9c22781a, ), // 84 ( 9, 0x27f0ff1bc1ee87cd, 0xcd19bb053fb0284e, 0x336de62af2bca35, 0x3e92c42e000eeed4, ), // 85 ( 9, 0x27d625ecf571c340, 0xcda3f5fb9c415052, 0x39235ec33d49600, 0x1ebe59130db2795e, ), // 86 ( 9, 0x27bbbf95282fcd45, 0xce2c97d694adab3f, 0x3f674e539585a17, 0x268859e90f51b89, ), // 87 ( 9, 0x27a1c8c8ddaf84da, 0xceb3a9f01975077f, 0x4645b6958000000, 0xd24cde0463108cfa, ), // 88 ( 9, 0x27883e5e7df3f518, 0xcf393550f3aa6906, 0x4dcb74afbc49c19, 0xa536009f37adc383, ), // 89 ( 9, 0x276f1d4c9847e90e, 0xcfbd42b465836767, 0x56064e1d18d9a00, 0x7cea06ce1c9ace10, ), // 90 ( 9, 0x275662a841b30191, 0xd03fda8b97997f33, 0x5f04fe2cd8a39fb, 0x58db032e72e8ba43, ), // 91 ( 9, 0x273e0ba38d15a47b, 0xd0c10500d63aa658, 0x68d74421f5c0000, 0x388cc17cae105447, ), // 92 ( 9, 0x2726158c1b13cf03, 0xd140c9faa1e5439e, 0x738df1f6ab4827d, 0x1b92672857620ce0, ), // 93 ( 9, 0x270e7dc9c01d8e9b, 0xd1bf311e95d00de3, 0x7f3afbc9cfb5e00, 0x18c6a9575c2ade4, ), // 94 ( 9, 0x26f741dd3f070d61, 0xd23c41d42727c808, 0x8bf187fba88f35f, 0xd44da7da8e44b24f, ), // 95 ( 9, 0x26e05f5f16c2159e, 0xd2b803473f7ad0f3, 0x99c600000000000, 0xaa2f78f1b4cc6794, ), // 96 ( 9, 0x26c9d3fe61e80598, 0xd3327c6ab49ca6c8, 0xa8ce21eb6531361, 0x843c067d091ee4cc, ), // 97 ( 9, 0x26b39d7fc6ddab08, 0xd3abb3faa02166cc, 0xb92112c1a0b6200, 0x62005e1e913356e3, ), // 98 ( 9, 0x269db9bc7772a5cc, 0xd423b07e986aa967, 0xcad7718b8747c43, 0x4316eed01dedd518, ), // 99 ( 9, 0x268826a13ef3fde6, 0xd49a784bcd1b8afe, 0xde0b6b3a7640000, 0x2725dd1d243aba0e, ), // 100 ( 9, 0x2672e22d9dbdbd9f, 0xd510118708a8f8dd, 0xf2d8cf5fe6d74c5, 0xddd9057c24cb54f, ), // 101 ( 9, 0x265dea72f169cc99, 0xd5848226989d33c3, 0x1095d25bfa712600, 0xedeee175a736d2a1, ), // 102 ( 9, 0x26493d93a8cb2514, 0xd5f7cff41e09aeb8, 0x121b7c4c3698faa7, 0xc4699f3df8b6b328, ), // 103 ( 9, 0x2634d9c282f3ef82, 0xd66a008e4788cbcd, 0x13c09e8d68000000, 0x9ebbe7d859cb5a7c, ), // 104 ( 9, 0x2620bd41d8933adc, 0xd6db196a761949d9, 0x15876ccb0b709ca9, 0x7c828b9887eb2179, ), // 105 ( 9, 0x260ce662ef04088a, 0xd74b1fd64e0753c6, 0x17723c2976da2a00, 0x5d652ab99001adcf, ), // 106 ( 9, 0x25f95385547353fd, 0xd7ba18f93502e409, 0x198384e9c259048b, 0x4114f1754e5d7b32, ), // 107 ( 9, 0x25e60316448db8e1, 0xd82809d5be7072db, 0x1bbde41dfeec0000, 0x274b7c902f7e0188, ), // 108 ( 9, 0x25d2f390152f74f5, 0xd894f74b06ef8b40, 0x1e241d6e3337910d, 0xfc9e0fbb32e210c, ), // 109 ( 9, 0x25c02379aa9ad043, 0xd900e6160002ccfe, 0x20b91cee9901ee00, 0xf4afa3e594f8ea1f, ), // 110 ( 9, 0x25ad9165f2c18907, 0xd96bdad2acb5f5ef, 0x237ff9079863dfef, 0xcd85c32e9e4437b0, ), // 111 ( 9, 0x259b3bf36735c90c, 0xd9d5d9fd5010b366, 0x267bf47000000000, 0xa9bbb147e0dd92a8, ), // 112 ( 9, 0x258921cb955e7693, 0xda3ee7f38e181ed0, 0x29b08039fbeda7f1, 0x8900447b70e8eb82, ), // 113 ( 9, 0x257741a2ac9170af, 0xdaa708f58014d37c, 0x2d213df34f65f200, 0x6b0a92adaad5848a, ), // 114 ( 9, 0x25659a3711bc827d, 0xdb0e4126bcc86bd7, 0x30d201d957a7c2d3, 0x4f990ad8740f0ee5, ), // 115 ( 9, 0x25542a50f84b9c39, 0xdb74948f5532da4b, 0x34c6d52160f40000, 0x3670a9663a8d3610, ), // 116 ( 9, 0x2542f0c20000377d, 0xdbda071cc67e6db5, 0x3903f855d8f4c755, 0x1f5c44188057be3c, ), // 117 ( 9, 0x2531ec64d772bd64, 0xdc3e9ca2e1a05533, 0x3d8de5c8ec59b600, 0xa2bea956c4e4977, ), // 118 ( 9, 0x25211c1ce2fb5a6e, 0xdca258dca9331635, 0x4269541d1ff01337, 0xed68b23033c3637e, ), // 119 ( 9, 0x25107ed5e7c3ec3b, 0xdd053f6d26089673, 0x479b38e478000000, 0xc99cf624e50549c5, ), // 120 ( 9, 0x25001383bac8a744, 0xdd6753e032ea0efe, 0x4d28cb56c33fa539, 0xa8adf7ae45e7577b, ), // 121 ( 9, 0x24efd921f390bce3, 0xddc899ab3ff56c5e, 0x5317871fa13aba00, 0x8a5bc740b1c113e5, ), // 122 ( 9, 0x24dfceb3a26bb203, 0xde29142e0e01401f, 0x596d2f44de9fa71b, 0x6e6c7efb81cfbb9b, ), // 123 ( 9, 0x24cff3430a0341a7, 0xde88c6b3626a72aa, 0x602fd125c47c0000, 0x54aba5c5cada5f10, ), // 124 ( 9, 0x24c045e15c149931, 0xdee7b471b3a9507d, 0x6765c793fa10079d, 0x3ce9a36f23c0fc90, ), // 125 ( 9, 0x24b0c5a679267ae2, 0xdf45e08bcf06554e, 0x6f15be069b847e00, 0x26fb43de2c8cd2a8, ), // 126 ( 9, 0x24a171b0b31461c8, 0xdfa34e1177c23362, 0x7746b3e82a77047f, 0x12b94793db8486a1, ), // 127 (9, 0x2492492492492492, 0xdfffffffffffffff, 0x7, 0x0), // 128 ( 9, 0x24834b2c9d85cdfe, 0xe05bf942dbbc2145, 0x894953f7ea890481, 0xdd5deca404c0156d, ), // 129 ( 9, 0x247476f924137501, 0xe0b73cb42e16914c, 0x932abffea4848200, 0xbd51373330291de0, ), // 130 ( 9, 0x2465cbc00a40cec0, 0xe111cd1d5133412e, 0x9dacb687d3d6a163, 0x9fa4025d66f23085, ), // 131 ( 9, 0x245748bc980e0427, 0xe16bad3758efd873, 0xa8d8102a44840000, 0x842530ee2db4949d, ), // 132 ( 9, 0x2448ed2f49eb0633, 0xe1c4dfab90aab5ef, 0xb4b60f9d140541e5, 0x6aa7f2766b03dc25, ), // 133 ( 9, 0x243ab85da36e3167, 0xe21d6713f453f356, 0xc15065d4856e4600, 0x53035ba7ebf32e8d, ), // 134 ( 9, 0x242ca99203ea8c18, 0xe27545fba4fe385a, 0xceb1363f396d23c7, 0x3d12091fc9fb4914, ), // 135 ( 9, 0x241ec01b7cce4ea0, 0xe2cc7edf592262cf, 0xdce31b2488000000, 0x28b1cb81b1ef1849, ), // 136 ( 9, 0x2410fb4da9b3b0fc, 0xe323142dc8c66b55, 0xebf12a24bca135c9, 0x15c35be67ae3e2c9, ), // 137 ( 9, 0x24035a808a0f315e, 0xe379084815b5774c, 0xfbe6f8dbf88f4a00, 0x42a17bd09be1ff0, ), // 138 ( 8, 0x23f5dd105c67ab9d, 0xe3ce5d822ff4b643, 0x1ef156c084ce761, 0x8bf461f03cf0bbf, ), // 139 ( 8, 0x23e8825d7b05abb1, 0xe4231623369e78e5, 0x20c4e3b94a10000, 0xf3fbb43f68a32d05, ), // 140 ( 8, 0x23db49cc3a0866fe, 0xe4773465d54aded7, 0x22b0695a08ba421, 0xd84f44c48564dc19, ), // 141 ( 8, 0x23ce32c4c6cfb9f5, 0xe4caba789e2b8687, 0x24b4f35d7a4c100, 0xbe58ebcce7956abe, ), // 142 ( 8, 0x23c13cb308ab6ab7, 0xe51daa7e60fdd34c, 0x26d397284975781, 0xa5fac463c7c134b7, ), // 143 ( 8, 0x23b4670682c0c709, 0xe570068e7ef5a1e7, 0x290d74100000000, 0x8f19241e28c7d757, ), // 144 ( 8, 0x23a7b13237187c8b, 0xe5c1d0b53bc09fca, 0x2b63b3a37866081, 0x799a6d046c0ae1ae, ), // 145 ( 8, 0x239b1aac8ac74728, 0xe6130af40bc0ecbf, 0x2dd789f4d894100, 0x6566e37d746a9e40, ), // 146 ( 8, 0x238ea2ef2b24c379, 0xe663b741df9c37c0, 0x306a35e51b58721, 0x526887dbfb5f788f, ), // 147 ( 8, 0x23824976f4045a26, 0xe6b3d78b6d3b24fb, 0x331d01712e10000, 0x408af3382b8efd3d, ), // 148 ( 8, 0x23760dc3d6e4d729, 0xe7036db376537b90, 0x35f14200a827c61, 0x2fbb374806ec05f1, ), // 149 ( 8, 0x2369ef58c30bd43e, 0xe7527b930c965bf2, 0x38e858b62216100, 0x1fe7c0f0afce87fe, ), // 150 ( 8, 0x235dedbb8e82aa1c, 0xe7a102f9d39a9331, 0x3c03b2c13176a41, 0x11003d517540d32e, ), // 151 ( 8, 0x23520874dfeb1ffd, 0xe7ef05ae409a0288, 0x3f44c9b21000000, 0x2f5810f98eff0dc, ), // 152 ( 8, 0x23463f1019228dd7, 0xe83c856dd81804b7, 0x42ad23cef3113c1, 0xeb72e35e7840d910, ), // 153 ( 8, 0x233a911b42aa9b3c, 0xe88983ed6985bae5, 0x463e546b19a2100, 0xd27de19593dc3614, ), // 154 ( 8, 0x232efe26f7cf33f9, 0xe8d602d948f83829, 0x49f9fc3f96684e1, 0xbaf391fd3e5e6fc2, ), // 155 ( 8, 0x232385c65381b485, 0xe92203d587039cc1, 0x4de1c9c5dc10000, 0xa4bd38c55228c81d, ), // 156 ( 8, 0x2318278edde1b39b, 0xe96d887e26cd57b7, 0x51f77994116d2a1, 0x8fc5a8de8e1de782, ), // 157 ( 8, 0x230ce3187a6c2be9, 0xe9b892675266f66c, 0x563cd6bb3398100, 0x7bf9265bea9d3a3b, ), // 158 ( 8, 0x2301b7fd56ca21bb, 0xea03231d8d8224ba, 0x5ab3bb270beeb01, 0x69454b325983dccd, ), // 159 ( 8, 0x22f6a5d9da38341c, 0xea4d3c25e68dc57f, 0x5f5e10000000000, 0x5798ee2308c39df9, ), // 160 ( 8, 0x22ebac4c9580d89f, 0xea96defe264b59be, 0x643dce0ec16f501, 0x46e40ba0fa66a753, ), // 161 ( 8, 0x22e0caf633834beb, 0xeae00d1cfdeb43cf, 0x6954fe21e3e8100, 0x3717b0870b0db3a7, ), // 162 ( 8, 0x22d601796a418886, 0xeb28c7f233bdd372, 0x6ea5b9755f440a1, 0x2825e6775d11cdeb, ), // 163 ( 8, 0x22cb4f7aec6fd8b4, 0xeb7110e6ce866f2b, 0x74322a1c0410000, 0x1a01a1c09d1b4dac, ), // 164 ( 8, 0x22c0b4a15b80d83e, 0xebb8e95d3f7d9df2, 0x79fc8b6ae8a46e1, 0xc9eb0a8bebc8f3e, ), // 165 ( 8, 0x22b630953a28f77a, 0xec0052b18b0e2a19, 0x80072a66d512100, 0xffe357ff59e6a004, ), // 166 ( 8, 0x22abc300df54ca7c, 0xec474e39705912d2, 0x86546633b42b9c1, 0xe7dfd1be05fa61a8, ), // 167 ( 8, 0x22a16b90698da5d2, 0xec8ddd448f8b845a, 0x8ce6b0861000000, 0xd11ed6fc78f760e5, ), // 168 ( 8, 0x229729f1b2c83ded, 0xecd4011c8f11979a, 0x93c08e16a022441, 0xbb8db609dd29ebfe, ), // 169 ( 8, 0x228cfdd444992f78, 0xed19bb053fb0284e, 0x9ae49717f026100, 0xa71aec8d1813d532, ), // 170 ( 8, 0x2282e6e94ccb8588, 0xed5f0c3cbf8fa470, 0xa25577ae24c1a61, 0x93b612a9f20fbc02, ), // 171 ( 8, 0x2278e4e392557ecf, 0xeda3f5fb9c415052, 0xaa15f068e610000, 0x814fc7b19a67d317, ), // 172 ( 8, 0x226ef7776aa7fd29, 0xede87974f3c81855, 0xb228d6bf7577921, 0x6fd9a03f2e0a4b7c, ), // 173 ( 8, 0x22651e5aaf5532d0, 0xee2c97d694adab3f, 0xba91158ef5c4100, 0x5f4615a38d0d316e, ), // 174 ( 8, 0x225b5944b40b4694, 0xee7052491d2c3e64, 0xc351ad9aec0b681, 0x4f8876863479a286, ), // 175 ( 8, 0x2251a7ee3cdfcca5, 0xeeb3a9f01975077f, 0xcc6db6100000000, 0x4094d8a3041b60eb, ), // 176 ( 8, 0x22480a1174e913d9, 0xeef69fea211b2627, 0xd5e85d09025c181, 0x32600b8ed883a09b, ), // 177 ( 8, 0x223e7f69e522683c, 0xef393550f3aa6906, 0xdfc4e816401c100, 0x24df8c6eb4b6d1f1, ), // 178 ( 8, 0x223507b46b988abe, 0xef7b6b399471103e, 0xea06b4c72947221, 0x18097a8ee151acef, ), // 179 ( 8, 0x222ba2af32dbbb9e, 0xefbd42b465836767, 0xf4b139365210000, 0xbd48cc8ec1cd8e3, ), // 180 ( 8, 0x22225019a9b4d16c, 0xeffebccd41ffcd5c, 0xffc80497d520961, 0x3807a8d67485fb, ), // 181 ( 8, 0x22190fb47b1af172, 0xf03fda8b97997f33, 0x10b4ebfca1dee100, 0xea5768860b62e8d8, ), // 182 ( 8, 0x220fe14186679801, 0xf0809cf27f703d52, 0x117492de921fc141, 0xd54faf5b635c5005, ), // 183 ( 8, 0x2206c483d7c6b786, 0xf0c10500d63aa658, 0x123bb2ce41000000, 0xc14a56233a377926, ), // 184 ( 8, 0x21fdb93fa0e0ccc5, 0xf10113b153c8ea7b, 0x130a8b6157bdecc1, 0xae39a88db7cd329f, ), // 185 ( 8, 0x21f4bf3a31bcdcaa, 0xf140c9faa1e5439e, 0x13e15dede0e8a100, 0x9c10bde69efa7ab6, ), // 186 ( 8, 0x21ebd639f1d86584, 0xf18028cf72976a4e, 0x14c06d941c0ca7e1, 0x8ac36c42a2836497, ), // 187 ( 8, 0x21e2fe06597361a6, 0xf1bf311e95d00de3, 0x15a7ff487a810000, 0x7a463c8b84f5ef67, ), // 188 ( 8, 0x21da3667eb0e8ccb, 0xf1fde3d30e812642, 0x169859ddc5c697a1, 0x6a8e5f5ad090fd4b, ), // 189 ( 8, 0x21d17f282d1a300e, 0xf23c41d42727c808, 0x1791c60f6fed0100, 0x5b91a2943596fc56, ), // 190 ( 8, 0x21c8d811a3d3c9e1, 0xf27a4c0585cbf805, 0x18948e8c0e6fba01, 0x4d4667b1c468e8f0, ), // 191 ( 8, 0x21c040efcb50f858, 0xf2b803473f7ad0f3, 0x19a1000000000000, 0x3fa39ab547994daf, ), // 192 ( 8, 0x21b7b98f11b61c1a, 0xf2f56875eb3f2614, 0x1ab769203dafc601, 0x32a0a9b2faee1e2a, ), // 193 ( 8, 0x21af41bcd19739ba, 0xf3327c6ab49ca6c8, 0x1bd81ab557f30100, 0x26357ceac0e96962, ), // 194 ( 8, 0x21a6d9474c81adf0, 0xf36f3ffb6d916240, 0x1d0367a69fed1ba1, 0x1a5a6f65caa5859e, ), // 195 ( 8, 0x219e7ffda5ad572a, 0xf3abb3faa02166cc, 0x1e39a5057d810000, 0xf08480f672b4e86, ), // 196 ( 8, 0x219635afdcd3e46d, 0xf3e7d9379f70166a, 0x1f7b2a18f29ac3e1, 0x4383340615612ca, ), // 197 ( 8, 0x218dfa2ec92d0643, 0xf423b07e986aa967, 0x20c850694c2aa100, 0xf3c77969ee4be5a2, ), // 198 ( 8, 0x2185cd4c148e4ae2, 0xf45f3a98a20738a4, 0x222173cc014980c1, 0xe00993cc187c5ec9, ), // 199 ( 8, 0x217daeda36ad7a5c, 0xf49a784bcd1b8afe, 0x2386f26fc1000000, 0xcd2b297d889bc2b6, ), // 200 ( 8, 0x21759eac708452fe, 0xf4d56a5b33cec44a, 0x24f92ce8af296d41, 0xbb214d5064862b22, ), // 201 ( 8, 0x216d9c96c7d490d4, 0xf510118708a8f8dd, 0x2678863cd0ece100, 0xa9e1a7ca7ea10e20, ), // 202 ( 8, 0x2165a86e02cb358c, 0xf54a6e8ca5438db1, 0x280563f0a9472d61, 0x99626e72b39ea0cf, ), // 203 ( 8, 0x215dc207a3c20fdf, 0xf5848226989d33c3, 0x29a02e1406210000, 0x899a5ba9c13fafd9, ), // 204 ( 8, 0x2155e939e51e8b37, 0xf5be4d0cb51434aa, 0x2b494f4efe6d2e21, 0x7a80a705391e96ff, ), // 205 ( 8, 0x214e1ddbb54cd933, 0xf5f7cff41e09aeb8, 0x2d0134ef21cbc100, 0x6c0cfe23de23042a, ), // 206 ( 8, 0x21465fc4b2d68f98, 0xf6310b8f55304840, 0x2ec84ef4da2ef581, 0x5e377df359c944dd, ), // 207 ( 8, 0x213eaecd2893dd60, 0xf66a008e4788cbcd, 0x309f102100000000, 0x50f8ac5fc8f53985, ), // 208 ( 8, 0x21370ace09f681c6, 0xf6a2af9e5a0f0a08, 0x3285ee02a1420281, 0x44497266278e35b7, ), // 209 ( 8, 0x212f73a0ef6db7cb, 0xf6db196a761949d9, 0x347d6104fc324100, 0x382316831f7ee175, ), // 210 ( 8, 0x2127e92012e25004, 0xf7133e9b156c7be5, 0x3685e47dade53d21, 0x2c7f377833b8946e, ), // 211 ( 8, 0x21206b264c4a39a7, 0xf74b1fd64e0753c6, 0x389ff6bb15610000, 0x2157c761ab4163ef, ), // 212 ( 8, 0x2118f98f0e52c28f, 0xf782bdbfdda6577b, 0x3acc1912ebb57661, 0x16a7071803cc49a9, ), // 213 ( 8, 0x211194366320dc66, 0xf7ba18f93502e409, 0x3d0acff111946100, 0xc6781d80f8224fc, ), // 214 ( 8, 0x210a3af8e926bb78, 0xf7f1322182cf15d1, 0x3f5ca2e692eaf841, 0x294092d370a900b, ), // 215 ( 8, 0x2102edb3d00e29a6, 0xf82809d5be7072db, 0x41c21cb8e1000000, 0xf24f62335024a295, ), // 216 ( 8, 0x20fbac44d5b6edc2, 0xf85ea0b0b27b2610, 0x443bcb714399a5c1, 0xe03b98f103fad6d2, ), // 217 ( 8, 0x20f4768a4348ad08, 0xf894f74b06ef8b40, 0x46ca406c81af2100, 0xcee3d32cad2a9049, ), // 218 ( 8, 0x20ed4c62ea57b1f0, 0xf8cb0e3b4b3bbdb3, 0x496e106ac22aaae1, 0xbe3f9df9277fdada, ), // 219 ( 8, 0x20e62dae221c087a, 0xf900e6160002ccfe, 0x4c27d39fa5410000, 0xae46f0d94c05e933, ), // 220 ( 8, 0x20df1a4bc4ba6525, 0xf9367f6da0ab2e9c, 0x4ef825c296e43ca1, 0x9ef2280fb437a33d, ), // 221 ( 8, 0x20d8121c2c9e506e, 0xf96bdad2acb5f5ef, 0x51dfa61f5ad88100, 0x9039ff426d3f284b, ), // 222 ( 8, 0x20d1150031e51549, 0xf9a0f8d3b0e04fde, 0x54def7a6d2f16901, 0x82178c6d6b51f8f4, ), // 223 ( 8, 0x20ca22d927d8f54d, 0xf9d5d9fd5010b366, 0x57f6c10000000000, 0x74843b1ee4c1e053, ), // 224 ( 8, 0x20c33b88da7c29aa, 0xfa0a7eda4c112ce6, 0x5b27ac993df97701, 0x6779c7f90dc42f48, ), // 225 ( 8, 0x20bc5ef18c233bdf, 0xfa3ee7f38e181ed0, 0x5e7268b9bbdf8100, 0x5af23c74f9ad9fe9, ), // 226 ( 8, 0x20b58cf5f31e4526, 0xfa7315d02f20c7bd, 0x61d7a7932ff3d6a1, 0x4ee7eae2acdc617e, ), // 227 ( 8, 0x20aec5793770a74d, 0xfaa708f58014d37c, 0x65581f53c8c10000, 0x43556aa2ac262a0b, ), // 228 ( 8, 0x20a8085ef096d530, 0xfadac1e711c832d1, 0x68f48a385b8320e1, 0x3835949593b8ddd1, ), // 229 ( 8, 0x20a1558b2359c4b1, 0xfb0e4126bcc86bd7, 0x6cada69ed07c2100, 0x2d837fbe78458762, ), // 230 ( 8, 0x209aace23fafa72e, 0xfb418734a9008bd9, 0x70843718cdbf27c1, 0x233a7e150a54a555, ), // 231 ( 8, 0x20940e491ea988d7, 0xfb74948f5532da4b, 0x7479027ea1000000, 0x19561984a50ff8fe, ), // 232 ( 8, 0x208d79a5006d7a47, 0xfba769b39e49640e, 0x788cd40268f39641, 0xfd211159fe3490f, ), // 233 ( 8, 0x2086eedb8a3cead3, 0xfbda071cc67e6db5, 0x7cc07b437ecf6100, 0x6aa563e655033e3, ), // 234 ( 8, 0x20806dd2c486dcc6, 0xfc0c6d447c5dd362, 0x8114cc6220762061, 0xfbb614b3f2d3b14c, ), // 235 ( 8, 0x2079f67119059fae, 0xfc3e9ca2e1a05533, 0x858aa0135be10000, 0xeac0f8837fb05773, ), // 236 ( 8, 0x2073889d50e7bf63, 0xfc7095ae91e1c760, 0x8a22d3b53c54c321, 0xda6e4c10e8615ca5, ), // 237 ( 8, 0x206d243e9303d929, 0xfca258dca9331635, 0x8ede496339f34100, 0xcab755a8d01fa67f, ), // 238 ( 8, 0x2066c93c62170aa8, 0xfcd3e6a0ca8906c2, 0x93bde80aec3a1481, 0xbb95a9ae71aa3e0c, ), // 239 ( 8, 0x2060777e9b0db0f6, 0xfd053f6d26089673, 0x98c29b8100000000, 0xad0326c296b4f529, ), // 240 ( 8, 0x205a2eed73563032, 0xfd3663b27f31d529, 0x9ded549671832381, 0x9ef9f21eed31b7c1, ), // 241 ( 8, 0x2053ef71773d7e6a, 0xfd6753e032ea0efe, 0xa33f092e0b1ac100, 0x91747422be14b0b2, ), // 242 ( 8, 0x204db8f388552ea9, 0xfd9810643d6614c3, 0xa8b8b452291fe821, 0x846d550e37b5063d, ), // 243 ( 8, 0x20478b5cdbe2bb2f, 0xfdc899ab3ff56c5e, 0xae5b564ac3a10000, 0x77df79e9a96c06f6, ), // 244 ( 8, 0x20416696f957cfbf, 0xfdf8f02086af2c4b, 0xb427f4b3be74c361, 0x6bc6019636c7d0c2, ), // 245 ( 8, 0x203b4a8bb8d356e7, 0xfe29142e0e01401f, 0xba1f9a938041e100, 0x601c4205aebd9e47, ), // 246 ( 8, 0x2035372541ab0f0d, 0xfe59063c8822ce56, 0xc0435871d1110f41, 0x54ddc59756f05016, ), // 247 ( 8, 0x202f2c4e08fd6dcc, 0xfe88c6b3626a72aa, 0xc694446f01000000, 0x4a0648979c838c18, ), // 248 ( 8, 0x202929f0d04b99e9, 0xfeb855f8ca88fb0d, 0xcd137a5b57ac3ec1, 0x3f91b6e0bb3a053d, ), // 249 ( 8, 0x20232ff8a41b45eb, 0xfee7b471b3a9507d, 0xd3c21bcecceda100, 0x357c299a88ea76a5, ), // 250 ( 8, 0x201d3e50daa036db, 0xff16e281db76303b, 0xdaa150410b788de1, 0x2bc1e517aecc56e3, ), // 251 ( 8, 0x201754e5126d446d, 0xff45e08bcf06554e, 0xe1b24521be010000, 0x225f56ceb3da9f5d, ), // 252 ( 8, 0x201173a1312ca135, 0xff74aef0efafadd7, 0xe8f62df12777c1a1, 0x1951136d53ad63ac, ), // 253 ( 8, 0x200b9a71625f3b13, 0xffa34e1177c23362, 0xf06e445906fc0100, 0x1093d504b3cd7d93, ), // 254 ( 8, 0x2005c94216230568, 0xffd1be4c7f2af942, 0xf81bc845c81bf801, 0x824794d1ec1814f, ), // 255 (8, 0x1fffffffffffffff, 0xffffffffffffffff, 0x8, 0x0), // 256 ]; // This section is created by factorial_data.rs. // This is equivalent to `__gmp_oddfac_table` in `mpn/comb_tables.c`, GMP 6.2.1, which is the // combination of `ONE_LIMB_ODD_FACTORIAL_TABLE` and `ONE_LIMB_ODD_FACTORIAL_EXTTABLE` in // `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_FACTORIAL_TABLE: [Limb; 68] = [ 0x1, 0x1, 0x1, 0x3, 0x3, 0xf, 0x2d, 0x13b, 0x13b, 0xb13, 0x375f, 0x26115, 0x7233f, 0x5cca33, 0x2898765, 0x260eeeeb, 0x260eeeeb, 0x286fddd9b, 0x16beecca73, 0x1b02b930689, 0x870d9df20ad, 0xb141df4dae31, 0x79dd498567c1b, 0xaf2e19afc5266d, 0x20d8a4d0f4f7347, 0x335281867ec241ef, 0x9b3093d46fdd5923, 0x5e1f9767cc5866b1, 0x92dd23d6966aced7, 0xa30d0f4f0a196e5b, 0x8dc3e5a1977d7755, 0x2ab8ce915831734b, 0x2ab8ce915831734b, 0x81d2a0bc5e5fdcab, 0x9efcac82445da75b, 0xbc8b95cf58cde171, 0xa0e8444a1f3cecf9, 0x4191deb683ce3ffd, 0xddd3878bc84ebfc7, 0xcb39a64b83ff3751, 0xf8203f7993fc1495, 0xbd2a2a78b35f4bdd, 0x84757be6b6d13921, 0x3fbbcfc0b524988b, 0xbd11ed47c8928df9, 0x3c26b59e41c2f4c5, 0x677a5137e883fdb3, 0xff74e943b03b93dd, 0xfe5ebbcb10b2bb97, 0xb021f1de3235e7e7, 0x33509eb2e743a58f, 0x390f9da41279fb7d, 0xe5cb0154f031c559, 0x93074695ba4ddb6d, 0x81c471caa636247f, 0xe1347289b5a1d749, 0x286f21c3f76ce2ff, 0xbe84a2173e8ac7, 0x1595065ca215b88b, 0xf95877595b018809, 0x9c2efe3c5516f887, 0x373294604679382b, 0xaf1ff7a888adcd35, 0x18ddf279a2c5800b, 0x18ddf279a2c5800b, 0x505a90e2542582cb, 0x5bacad2cd8d5dc2b, 0xfe3152bcbff89f41, ]; // This is equivalent to `ODD_FACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_TABLE_LIMIT: usize = 25; // This is equivalent to `ODD_FACTORIAL_EXTTABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_EXTTABLE_LIMIT: usize = 67; // This is equivalent to `ODD_FACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_FACTORIAL_TABLE_MAX: Limb = 0x335281867ec241ef; // This is equivalent to `__gmp_odd2fac_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE: [Limb; 17] = [ 0x1, 0x3, 0xf, 0x69, 0x3b1, 0x289b, 0x20fdf, 0x1eee11, 0x20dcf21, 0x27065f73, 0x33385d46f, 0x49a10615f9, 0x730b9982551, 0xc223930bef8b, 0x15fe07a85a22bf, 0x2a9c2ed62ea3521, 0x57e22099c030d941, ]; // This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_LIMIT` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_DOUBLEFACTORIAL_TABLE_LIMIT: usize = 33; // This is equivalent to `ODD_DOUBLEFACTORIAL_TABLE_MAX` in `fac_table.h`, GMP 6.2.1. pub(crate) const ODD_DOUBLEFACTORIAL_TABLE_MAX: Limb = 0x57e22099c030d941; // This is equivalent to `__gmp_limbroots_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `NTH_ROOT_NUMB_MASK_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const NTH_ROOT_NUMB_MASK_TABLE: [Limb; 8] = [Limb::MAX, 0xffffffff, 0x285145, 0xffff, 0x1bdb, 0x659, 0x235, 0xff]; // This is equivalent to `ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE: [Limb; 64] = [ 0x1, 0xaaaaaaaaaaaaaaab, 0xaaaaaaaaaaaaaaab, 0xeeeeeeeeeeeeeeef, 0x4fa4fa4fa4fa4fa5, 0x2ff2ff2ff2ff2ff3, 0x2ff2ff2ff2ff2ff3, 0x938cc70553e3771b, 0xb71c27cddd93e49f, 0xb38e3229fcdee63d, 0xe684bb63544a4cbf, 0xc2f684917ca340fb, 0xf747c9cba417526d, 0xbb26eb51d7bd49c3, 0xbb26eb51d7bd49c3, 0xb0a7efb985294093, 0xbe4b8c69f259eabb, 0x6854d17ed6dc4fb9, 0xe1aa904c915f4325, 0x3b8206df131cead1, 0x79c6009fea76fe13, 0xd8c5d381633cd365, 0x4841f12b21144677, 0x4a91ff68200b0d0f, 0x8f9513a58c4f9e8b, 0x2b3e690621a42251, 0x4f520f00e03c04e7, 0x2edf84ee600211d3, 0xadcaa2764aaacdfd, 0x161f4f9033f4fe63, 0x161f4f9033f4fe63, 0xbada2932ea4d3e03, 0xcec189f3efaa30d3, 0xf7475bb68330bf91, 0x37eb7bf7d5b01549, 0x46b35660a4e91555, 0xa567c12d81f151f7, 0x4c724007bb2071b1, 0xf4a0cce58a016bd, 0xfa21068e66106475, 0x244ab72b5a318ae1, 0x366ce67e080d0f23, 0xd666fdae5dd2a449, 0xd740ddd0acc06a0d, 0xb050bbbb28e6f97b, 0x70b003fe890a5c75, 0xd03aabff83037427, 0x13ec4ca72c783bd7, 0x90282c06afdbd96f, 0x4414ddb9db4a95d5, 0xa2c68735ae6832e9, 0xbf72d71455676665, 0xa8469fab6b759b7f, 0xc1e55b56e606caf9, 0x40455630fc4a1cff, 0x120a7b0046d16f7, 0xa7c3553b08faef23, 0x9f0bfd1b08d48639, 0xa433ffce9a304d37, 0xa22ad1d53915c683, 0xcb6cbc723ba5dd1d, 0x547fb1b8ab9d0ba3, 0x547fb1b8ab9d0ba3, 0x8f15a826498852e3, ]; pub(crate) const ODD_CENTRAL_BINOMIAL_OFFSET: usize = 13; // This table contains binomial(2k, k) / 2 ^ t. // // This is equivalent to `bin2kk` in `mpz/bin_uiui.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE: [Limb; 23] = [ 0x13d66b, 0x4c842f, 0x93ee7d, 0x11e9e123, 0x22c60053, 0x873ae4d1, 0x10757bd97, 0x80612c6cd, 0xfaa556bc1, 0x3d3cc24821, 0x77cfeb6bbb, 0x7550ebd97c7, 0xe5f08695caf, 0x386120ffce11, 0x6eabb28dd6df, 0x3658e31c82a8f, 0x6ad2050312783, 0x1a42902a5af0bf, 0x33ac44f881661d, 0xcb764f927d82123, 0x190c23fa46b93983, 0x62b7609e25caf1b9, 0xc29cb72925ef2cff, ]; pub(crate) const ODD_CENTRAL_BINOMIAL_TABLE_LIMIT: usize = 35; // This table contains the inverses of elements in the previous table. // // This is equivalent to `bin2kkinv` in `mpz/bin_uiui.c`, GMP 6.2.1, and // `ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE` from `fac_table.h`, GMP 6.2.1. pub(crate) const ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE: [Limb; 23] = [ 0x61e5bd199bb12643, 0x78321494dc8342cf, 0x4fd348704ebf7ad5, 0x7e722ba086ab568b, 0xa5fcc124265843db, 0x89c4a6b18633f431, 0x4daa2c15f8ce9227, 0x801c618ca9be9605, 0x32dc192f948a441, 0xd02b90c2bf3be1, 0xd897e8c1749aa173, 0x54a234fc01fef9f7, 0x83ff2ab4d1ff7a4f, 0xa427f1c9b304e2f1, 0x9c14595d1793651f, 0x883a71c607a7b46f, 0xd089863c54bc9f2b, 0x9022f6bce5d07f3f, 0xbec207e218768c35, 0x9d70cb4cbb4f168b, 0x3c3d3403828a9d2b, 0x7672df58c56bc489, 0x1e66ca55d727d2ff, ]; // This table contains the values t in the formula binomial(2k, k) / 2 ^ t. // // This is equivalent to `fac2bin` in `mpz/bin_uiui.c`, GMP 6.2.1, and `CENTRAL_BINOMIAL_2FAC_TABLE` // from `fac_table.h`, GMP 6.2.1. pub(crate) const CENTRAL_BINOMIAL_2FAC_TABLE: [u64; 23] = [3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3]; // https://oeis.org/A005187, skipping the initial 0 // // This is equivalent to `__gmp_fac2cnt_table` in `mpn/comb_tables.c`, GMP 6.2.1, and // `TABLE_2N_MINUS_POPC_2N` from `fac_table.h`, GMP 6.2.1. pub(crate) const TABLE_2N_MINUS_POPC_2N: [u8; 40] = [ 1, 3, 4, 7, 8, 10, 11, 15, 16, 18, 19, 22, 23, 25, 26, 31, 32, 34, 35, 38, 39, 41, 42, 46, 47, 49, 50, 53, 54, 56, 57, 63, 64, 66, 67, 70, 71, 73, 74, 78, ]; pub(crate) const TABLE_LIMIT_2N_MINUS_POPC_2N: u64 = 81; // Use these tables to match FLINT for debugging // ``` // pub(crate) const FFT_TAB: [[u8; 2]; 5] = [[3, 3], [3, 2], [2, 1], [2, 1], [0, 0]]; // pub(crate) const MULMOD_TAB: [u8; 15] = [4, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 2, 2, 1, 1]; // ``` ================================================ FILE: malachite-nz/src/test_util/bench/bucketers.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::platform::Limb; use crate::test_util::natural::arithmetic::gcd::OwnedHalfGcdMatrix; use malachite_base::max; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rational_sequences::RationalSequence; use malachite_base::test_util::bench::bucketers::Bucketer; use std::cmp::{max, min}; pub fn natural_bucketer(var_name: &str) -> Bucketer<'_, Natural> { Bucketer { bucketing_function: &|x| usize::exact_from(x), bucketing_label: var_name.to_string(), } } pub fn natural_bit_bucketer(var_name: &str) -> Bucketer<'_, Natural> { Bucketer { bucketing_function: &|x| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_natural_max_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, Natural)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_natural_min_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, Natural)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(min(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("min({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_natural_max_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Natural, Natural))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_natural_min_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Natural, Natural))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(min(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("min({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_natural_bit_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, u64)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn pair_natural_bit_i64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, i64)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.unsigned_abs())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.unsigned_abs())"), } } pub fn triple_natural_bit_i64_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Natural, i64, u64)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn quadruple_1_2_3_natural_bit_i64_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Natural, i64, u64, T)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn pair_integer_bit_i64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, i64)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.unsigned_abs())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.unsigned_abs())"), } } pub fn pair_integer_bit_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, u64)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn pair_2_pair_integer_bit_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Integer, u64))> { Bucketer { bucketing_function: &|(_, (x, y))| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn triple_integer_bit_i64_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Integer, i64, u64)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn quadruple_1_2_3_integer_bit_i64_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Integer, i64, u64, T)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn triple_3_pair_natural_max_bit_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Natural, Natural))> { Bucketer { bucketing_function: &|(_, _, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_3_pair_natural_min_bit_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Natural, Natural))> { Bucketer { bucketing_function: &|(_, _, (x, y))| { usize::exact_from(min(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("min({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_1_natural_bit_bucketer(var_name: &str) -> Bucketer<'_, (Natural, T)> { Bucketer { bucketing_function: &|(x, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_natural_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, Natural)> { Bucketer { bucketing_function: &|(_, x)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_1_natural_bit_bucketer(var_name: &str) -> Bucketer<'_, (Natural, T, U)> { Bucketer { bucketing_function: &|(x, _, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_natural_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, U, Natural)> { Bucketer { bucketing_function: &|(_, _, x)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_pair_1_natural_bit_bucketer( var_name: &str, ) -> Bucketer<'_, (T, U, (Natural, V))> { Bucketer { bucketing_function: &|(_, _, (x, _))| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_pair_1_natural_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, (Natural, U))> { Bucketer { bucketing_function: &|(_, (x, _))| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_natural_max_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Natural, Natural, Natural)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits())" ), } } pub fn integer_bit_bucketer(var_name: &str) -> Bucketer<'_, Integer> { Bucketer { bucketing_function: &|x| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_1_integer_bit_bucketer(var_name: &str) -> Bucketer<'_, (Integer, T)> { Bucketer { bucketing_function: &|(x, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_integer_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, Integer)> { Bucketer { bucketing_function: &|(_, x)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_integer_max_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, Integer)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_integer_max_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Integer, Integer, Integer)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits())" ), } } pub fn triple_1_2_natural_max_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, Natural, T)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_triple_1_2_natural_max_bit_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Natural, Natural, U))> { Bucketer { bucketing_function: &|(_, (x, y, _))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_1_2_integer_max_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, Integer, T)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_triple_1_2_integer_max_bit_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Integer, Integer, U))> { Bucketer { bucketing_function: &|(_, (x, y, _))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_integer_max_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Integer, Integer))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn integer_natural_max_bit_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, Natural)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_1_integer_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, (Integer, U))> { Bucketer { bucketing_function: &|(_, (x, _))| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_integer_natural_max_bit_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, (Integer, Natural))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_1_integer_bit_bucketer(var_name: &str) -> Bucketer<'_, (Integer, T, U)> { Bucketer { bucketing_function: &|(x, _, _)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_integer_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, U, Integer)> { Bucketer { bucketing_function: &|(_, _, x)| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_pair_1_integer_bit_bucketer( var_name: &str, ) -> Bucketer<'_, (T, U, (Integer, V))> { Bucketer { bucketing_function: &|(_, _, (x, _))| usize::exact_from(x.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_pair_integer_max_bit_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Integer, Integer))> { Bucketer { bucketing_function: &|(_, _, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn natural_bit_ratio_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, Natural)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(x.significant_bits() / y.significant_bits()) }, bucketing_label: format!("{x_name}.significant_bits() / {y_name}.significant_bits()"), } } pub fn pair_1_vec_len_times_pair_2_natural_bits_bucketer<'a, T>( xs_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Vec, Natural)> { Bucketer { bucketing_function: &|(xs, y)| { xs.len() .checked_mul(usize::exact_from(y.significant_bits())) .unwrap() }, bucketing_label: format!("{xs_name}.len() * {y_name}.significant_bits()"), } } pub fn pair_1_vec_len_times_pair_2_bucketer<'a, T, U: Copy>( xs_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Vec, U)> where usize: ExactFrom, { Bucketer { bucketing_function: &|&(ref xs, y)| xs.len().checked_mul(usize::exact_from(y)).unwrap(), bucketing_label: format!("{xs_name}.len() * {y_name}"), } } pub fn natural_deserialize_bucketer<'a>() -> Bucketer<'a, (String, String, String)> { Bucketer { bucketing_function: &|(_, _, s)| { let n: Natural = serde_json::from_str(s).unwrap(); usize::exact_from(n.significant_bits()) }, bucketing_label: "n.significant_bits()".to_string(), } } pub fn integer_deserialize_bucketer<'a>() -> Bucketer<'a, (String, String, String)> { Bucketer { bucketing_function: &|(_, _, s)| { let n: Integer = serde_json::from_str(s).unwrap(); usize::exact_from(n.significant_bits()) }, bucketing_label: "n.significant_bits()".to_string(), } } pub fn triple_1_3_prod_natural_bits_bucketer<'a, T>( xs_name: &'a str, zs_name: &'a str, ) -> Bucketer<'a, (Natural, T, Natural)> { Bucketer { bucketing_function: &|(x, _, z)| { usize::exact_from(x.significant_bits()) .checked_mul(usize::exact_from(z.significant_bits())) .unwrap() }, bucketing_label: format!("{xs_name}.significant_bits() * {zs_name}.significant_bits()"), } } pub fn triple_3_triple_1_3_prod_natural_bits_bucketer<'a, T, U, V>( xs_name: &'a str, zs_name: &'a str, ) -> Bucketer<'a, (T, U, (Natural, V, Natural))> { Bucketer { bucketing_function: &|(_, _, (x, _, z))| { usize::exact_from(x.significant_bits()) .checked_mul(usize::exact_from(z.significant_bits())) .unwrap() }, bucketing_label: format!("{xs_name}.significant_bits() * {zs_name}.significant_bits()"), } } pub fn pair_1_half_gcd_matrix_bucketer(m_name: &str) -> Bucketer<'_, (OwnedHalfGcdMatrix, T)> { Bucketer { bucketing_function: &|(m, _)| m.s, bucketing_label: m_name.to_string(), } } pub fn triple_1_half_gcd_matrix_bucketer( m_name: &str, ) -> Bucketer<'_, (OwnedHalfGcdMatrix, T, U)> { Bucketer { bucketing_function: &|(m, _, _)| m.s, bucketing_label: m_name.to_string(), } } #[allow(clippy::type_complexity)] pub fn limbs_matrix_2_2_mul_bucketer<'a>() -> Bucketer< 'a, ( Vec, Vec, Vec, Vec, usize, Vec, Vec, Vec, Vec, ), > { Bucketer { bucketing_function: &|(_, _, _, _, xs_len, ys00, _, _, _)| max(*xs_len, ys00.len()), bucketing_label: "max(xs_len, ys_len)".to_string(), } } pub fn triple_3_pair_1_integer_bits_times_pair_2_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Integer, u64))> { Bucketer { bucketing_function: &|&(_, _, (ref x, y))| usize::exact_from(x.significant_bits() * y), bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn triple_1_2_natural_bit_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Natural, u64, T)> { Bucketer { bucketing_function: &|(x, y, _)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn triple_1_2_integer_bit_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Integer, u64, T)> { Bucketer { bucketing_function: &|(x, y, _)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn limbs_div_to_out_balancing_bucketer<'a>() -> Bucketer<'a, (Vec, Vec, Vec)> { Bucketer { bucketing_function: &|(_, ns, ds)| max(2, (ds.len() << 1).saturating_sub(ns.len())), bucketing_label: "max(2, 2 * ds.len() - ns.len())".to_string(), } } #[allow(clippy::type_complexity)] pub fn limbs_div_mod_extra_bucketer<'a>() -> Bucketer<'a, (Vec, usize, Vec, Limb, Limb, u64)> { Bucketer { bucketing_function: &|(_, fraction_len, ns, _, _, _)| ns.len() + fraction_len, bucketing_label: "ns.len() + fraction_len".to_string(), } } #[allow(clippy::type_complexity)] pub fn limbs_div_mod_barrett_product_bucketer<'a>() -> Bucketer<'a, (Vec, Vec, Vec, Vec, usize, usize)> { Bucketer { bucketing_function: &|(_, _, _, _, _, i_len)| i_len << 1, bucketing_label: "2 * i_len".to_string(), } } #[allow(clippy::type_complexity)] pub fn limbs_div_mod_barrett_helper_bucketer<'a>() -> Bucketer<'a, (Vec, Vec, Vec, Vec)> { Bucketer { bucketing_function: &|(_, _, ns, ds)| (ds.len() << 1).saturating_sub(ns.len()), bucketing_label: "max(0, 2 * ds.len() - ns.len())".to_string(), } } pub fn limb_pair_significant_bits_bucketer(var_name: &str) -> Bucketer<'_, (Limb, Limb)> { Bucketer { bucketing_function: &|&(hi, lo)| usize::exact_from(limbs_significant_bits(&[lo, hi])), bucketing_label: format!("{var_name}.significant_bits()"), } } #[allow(clippy::type_complexity)] pub fn limbs_mod_mul_two_limbs_bucketer<'a>() -> Bucketer<'a, (Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { Bucketer { bucketing_function: &|&(x_1, x_0, y_1, y_0, _, _, _, _, _)| { usize::exact_from(max( limbs_significant_bits(&[x_0, x_1]), limbs_significant_bits(&[y_0, y_1]), )) }, bucketing_label: "m.significant_bits()".to_string(), } } pub fn limbs_mod_limb_small_unnormalized_bucketer<'a>() -> Bucketer<'a, (Vec, Limb)> { Bucketer { bucketing_function: &|(ns, d)| { if *ns.last().unwrap() < *d { ns.len() - 1 } else { ns.len() } }, bucketing_label: "adjusted ns.len()".to_string(), } } pub fn rational_from_power_of_2_digits_bucketer<'a>() -> Bucketer<'a, (u64, Vec, RationalSequence)> { Bucketer { bucketing_function: &|(log_base, xs, ys)| { usize::exact_from(*log_base) * max(xs.len(), ys.component_len()) }, bucketing_label: "log_base * max(before_point.len(), after_point.component_len})" .to_string(), } } pub fn rational_from_digits_bucketer<'a>() -> Bucketer<'a, (Natural, Vec, RationalSequence)> { Bucketer { bucketing_function: &|(base, xs, ys)| { usize::exact_from(base.significant_bits()) * max(xs.len(), ys.component_len()) }, bucketing_label: "base.significant_bits() * max(before_point.len(), after_point.component_len})" .to_string(), } } pub fn vec_integer_sum_bits_bucketer<'a>() -> Bucketer<'a, Vec> { Bucketer { bucketing_function: &|xs| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn vec_natural_sum_bits_bucketer<'a>() -> Bucketer<'a, Vec> { Bucketer { bucketing_function: &|xs| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn pair_1_vec_natural_sum_bits_bucketer<'a, T>() -> Bucketer<'a, (Vec, T)> { Bucketer { bucketing_function: &|(xs, _)| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn triple_3_vec_integer_sum_bits_bucketer<'a, T, U>() -> Bucketer<'a, (T, U, Vec)> { Bucketer { bucketing_function: &|(_, _, xs)| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn triple_3_vec_natural_sum_bits_bucketer<'a, T, U>() -> Bucketer<'a, (T, U, Vec)> { Bucketer { bucketing_function: &|(_, _, xs)| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } ================================================ FILE: malachite-nz/src/test_util/bench/mod.rs ================================================ // Copyright © 2026 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 . pub mod bucketers; ================================================ FILE: malachite-nz/src/test_util/common/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; #[cfg(not(feature = "32_bit_limbs"))] use crate::platform::Limb; use malachite_base::num::arithmetic::traits::Sign as SignTrait; #[cfg(not(feature = "32_bit_limbs"))] use malachite_base::num::conversion::traits::VecFromOtherTypeSlice; use num::bigint::Sign; use num::{BigInt, BigUint}; use rug::integer::Order; use std::cmp::Ordering::*; #[cfg(feature = "32_bit_limbs")] impl From<&BigUint> for Natural { #[inline] fn from(n: &BigUint) -> Self { Self::from_owned_limbs_asc(n.to_u32_digits()) } } #[cfg(not(feature = "32_bit_limbs"))] impl From<&BigUint> for Natural { #[inline] fn from(n: &BigUint) -> Self { Self::from_owned_limbs_asc(Limb::vec_from_other_type_slice(&n.to_u32_digits())) } } #[cfg(feature = "32_bit_limbs")] impl From<&Natural> for BigUint { #[inline] fn from(n: &Natural) -> Self { Self::new(n.to_limbs_asc()) } } #[cfg(not(feature = "32_bit_limbs"))] impl From<&Natural> for BigUint { #[inline] fn from(n: &Natural) -> Self { Self::new(u32::vec_from_other_type_slice(n.as_limbs_asc())) } } #[cfg(feature = "32_bit_limbs")] impl From<&Natural> for BigInt { #[inline] fn from(n: &Natural) -> Self { Self::from_biguint( if *n == 0 { Sign::NoSign } else { Sign::Plus }, BigUint::new(n.to_limbs_asc()), ) } } #[cfg(not(feature = "32_bit_limbs"))] impl From<&Natural> for BigInt { #[inline] fn from(n: &Natural) -> Self { Self::from_biguint( if *n == 0 { Sign::NoSign } else { Sign::Plus }, BigUint::new(u32::vec_from_other_type_slice(n.as_limbs_asc())), ) } } impl TryFrom<&rug::Integer> for Natural { type Error = (); #[inline] fn try_from(n: &rug::Integer) -> Result { if *n >= 0 { Ok(Self::from_owned_limbs_asc(n.to_digits(Order::Lsf))) } else { Err(()) } } } impl From<&Natural> for rug::Integer { #[inline] fn from(n: &Natural) -> Self { Self::from_digits(n.as_limbs_asc(), Order::Lsf) } } impl From<&BigInt> for Integer { #[inline] fn from(n: &BigInt) -> Self { Self::from_sign_and_abs(n.sign() != Sign::Minus, Natural::from(n.magnitude())) } } impl From<&Integer> for BigInt { #[inline] fn from(n: &Integer) -> Self { let sign = match n.sign() { Less => Sign::Minus, Equal => Sign::NoSign, Greater => Sign::Plus, }; Self::from_biguint(sign, BigUint::from(n.unsigned_abs_ref())) } } impl From<&rug::Integer> for Integer { #[inline] fn from(n: &rug::Integer) -> Self { Self::from_sign_and_abs( *n >= 0, Natural::from_owned_limbs_asc(n.to_digits(Order::Lsf)), ) } } impl From<&Integer> for rug::Integer { #[inline] fn from(n: &Integer) -> Self { let out = Self::from(n.unsigned_abs_ref()); if *n >= 0 { out } else { -out } } } ================================================ FILE: malachite-nz/src/test_util/extra_variadic/mod.rs ================================================ // Copyright © 2026 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 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::logic::traits::SignificantBits; use malachite_base::random::Seed; use malachite_base::tuples::random::next_helper; use malachite_base::{ custom_tuples, exhaustive_tuples_1_input, random_custom_tuples, random_tuples, }; use std::cmp::max; use std::marker::PhantomData; #[allow(clippy::missing_const_for_fn)] fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { (a.unwrap(), b.unwrap(), c.unwrap()) } #[allow(clippy::missing_const_for_fn)] fn unwrap_quadruple( (a, b, c, d): (Option, Option, Option, Option), ) -> (X, Y, Z, W) { (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap()) } #[allow(clippy::missing_const_for_fn)] fn unwrap_quintuple( (a, b, c, d, e): (Option, Option, Option, Option, Option), ) -> (X, Y, Z, W, V) { (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap(), e.unwrap()) } 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)), ExhaustiveSextuples1Input, exhaustive_sextuples_1_input, exhaustive_sextuples_from_single, (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] ); 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]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXXXY, (X, X, X, Y), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xxxy, exhaustive_quadruples_xxxy_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [1, output_type_xs_1], [2, output_type_xs_2]], [Y, J, ys, ys_done, [3, output_type_ys_3]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYXZ, (X, Y, X, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyxz, exhaustive_quadruples_xyxz_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [2, output_type_xs_2]], [Y, J, ys, ys_done, [1, output_type_ys_1]], [Z, K, zs, zs_done, [3, output_type_zs_3]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYYX, (X, Y, Y, X), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyyx, exhaustive_quadruples_xyyx_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0], [3, output_type_xs_3]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]] ); custom_tuples!( (pub(crate)), ExhaustiveQuadruplesXYYZ, (X, Y, Y, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xyyz, exhaustive_quadruples_xyyz_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2]], [Z, K, zs, zs_done, [3, output_type_zs_3]] ); custom_tuples!( (pub(crate)), ExhaustiveQuintuplesXYYYZ, (X, Y, Y, Y, Z), (None, None, None, None, None), unwrap_quintuple, exhaustive_quintuples_xyyyz, exhaustive_quintuples_xyyyz_custom_output, [X, I, xs, xs_done, [0, output_type_xs_0]], [Y, J, ys, ys_done, [1, output_type_ys_1], [2, output_type_ys_2], [3, output_type_ys_3]], [Z, K, zs, zs_done, [4, output_type_zs_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_tuples!( (pub(crate)), RandomQuadruples, RandomQuadruplesFromSingle, random_quadruples, random_quadruples_from_single, (I::Item, I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen] ); random_tuples!( (pub(crate)), RandomSextuples, RandomSextuplesFromSingle, random_sextuples, random_sextuples_from_single, (I::Item, I::Item, I::Item, I::Item, I::Item, I::Item), [0, X, I, xs, xs_gen], [1, Y, J, ys, ys_gen], [2, Z, K, zs, zs_gen], [3, W, L, ws, ws_gen], [4, V, M, vs, vs_gen], [5, U, N, us, us_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_custom_tuples!( (pub(crate)), RandomTriplesXYY, (X, Y, Y), random_triples_xyy, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXXXY, (X, X, X, Y), random_quadruples_xxxy, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1], [x_2, x_2]], [Y, J, ys, ys_gen, [y_3, y_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYXZ, (X, Y, X, Z), random_quadruples_xyxz, [X, I, xs, xs_gen, [x_0, x_0], [x_2, y_1]], [Y, J, ys, ys_gen, [y_1, x_2]], [Z, K, zs, zs_gen, [z_3, z_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYYX, (X, Y, Y, X), random_quadruples_xyyx, [X, I, xs, xs_gen, [x_0, x_0], [x_3, y_1]], [Y, J, ys, ys_gen, [y_1, y_2], [y_2, x_3]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXYYZ, (X, Y, Y, Z), random_quadruples_xyyz, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]], [Z, K, zs, zs_gen, [z_3, z_3]] ); random_custom_tuples!( (pub(crate)), RandomQuintuplesXYYYZ, (X, Y, Y, Y, Z), random_quintuples_xyyyz, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2], [y_3, y_3]], [Z, K, zs, zs_gen, [z_4, z_4]] ); ================================================ FILE: malachite-nz/src/test_util/generators/common.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::test_util::generators::common::It; use num::{BigInt, BigUint}; pub fn natural_nrm(xs: It) -> It<(BigUint, rug::Integer, Natural)> { Box::new(xs.map(|x| (BigUint::from(&x), rug::Integer::from(&x), x))) } pub fn natural_rm(xs: It) -> It<(rug::Integer, Natural)> { Box::new(xs.map(|x| (rug::Integer::from(&x), x))) } #[allow(clippy::type_complexity)] pub fn natural_pair_nrm( ps: It<(Natural, Natural)>, ) -> It<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Box::new(ps.map(|(x, y)| { ( (BigUint::from(&x), BigUint::from(&y)), (rug::Integer::from(&x), rug::Integer::from(&y)), (x, y), ) })) } pub fn natural_pair_rm( ps: It<(Natural, Natural)>, ) -> It<((rug::Integer, rug::Integer), (Natural, Natural))> { Box::new(ps.map(|(x, y)| ((rug::Integer::from(&x), rug::Integer::from(&y)), (x, y)))) } pub fn natural_pair_nm(ps: It<(Natural, Natural)>) -> It<((BigUint, BigUint), (Natural, Natural))> { Box::new(ps.map(|(x, y)| ((BigUint::from(&x), BigUint::from(&y)), (x, y)))) } pub fn natural_pair_1_rm( ps: It<(Natural, T)>, ) -> It<((rug::Integer, T), (Natural, T))> { Box::new(ps.map(|(x, y)| ((rug::Integer::from(&x), y.clone()), (x, y)))) } pub fn natural_pair_1_nm( ps: It<(Natural, T)>, ) -> It<((BigUint, T), (Natural, T))> { Box::new(ps.map(|(x, y)| ((BigUint::from(&x), y.clone()), (x, y)))) } #[allow(clippy::type_complexity)] pub fn natural_pair_1_nrm( ps: It<(Natural, T)>, ) -> It<((BigUint, T), (rug::Integer, T), (Natural, T))> { Box::new(ps.map(|(x, y)| { ( (BigUint::from(&x), y.clone()), (rug::Integer::from(&x), y.clone()), (x, y), ) })) } #[allow(clippy::type_complexity)] pub fn natural_triple_nrm( ts: It<(Natural, Natural, Natural)>, ) -> It<( (BigUint, BigUint, BigUint), (rug::Integer, rug::Integer, rug::Integer), (Natural, Natural, Natural), )> { Box::new(ts.map(|(x, y, z)| { ( (BigUint::from(&x), BigUint::from(&y), BigUint::from(&z)), ( rug::Integer::from(&x), rug::Integer::from(&y), rug::Integer::from(&z), ), (x, y, z), ) })) } #[allow(clippy::type_complexity)] pub fn natural_triple_rm( ts: It<(Natural, Natural, Natural)>, ) -> It<( (rug::Integer, rug::Integer, rug::Integer), (Natural, Natural, Natural), )> { Box::new(ts.map(|(x, y, z)| { ( ( rug::Integer::from(&x), rug::Integer::from(&y), rug::Integer::from(&z), ), (x, y, z), ) })) } #[allow(clippy::type_complexity)] pub fn natural_triple_1_rm( ts: It<(Natural, T, U)>, ) -> It<((rug::Integer, T, U), (Natural, T, U))> { Box::new(ts.map(|(x, y, z)| ((rug::Integer::from(&x), y.clone(), z.clone()), (x, y, z)))) } pub fn integer_rm(xs: It) -> It<(rug::Integer, Integer)> { Box::new(xs.map(|x| (rug::Integer::from(&x), x))) } pub fn integer_nrm(xs: It) -> It<(BigInt, rug::Integer, Integer)> { Box::new(xs.map(|x| (BigInt::from(&x), rug::Integer::from(&x), x))) } pub fn integer_pair_rm( ps: It<(Integer, Integer)>, ) -> It<((rug::Integer, rug::Integer), (Integer, Integer))> { Box::new(ps.map(|(x, y)| ((rug::Integer::from(&x), rug::Integer::from(&y)), (x, y)))) } #[allow(clippy::type_complexity)] pub fn integer_pair_nrm( ps: It<(Integer, Integer)>, ) -> It<( (BigInt, BigInt), (rug::Integer, rug::Integer), (Integer, Integer), )> { Box::new(ps.map(|(x, y)| { ( (BigInt::from(&x), BigInt::from(&y)), (rug::Integer::from(&x), rug::Integer::from(&y)), (x, y), ) })) } pub fn integer_pair_nm(ps: It<(Integer, Integer)>) -> It<((BigInt, BigInt), (Integer, Integer))> { Box::new(ps.map(|(x, y)| ((BigInt::from(&x), BigInt::from(&y)), (x, y)))) } pub fn integer_pair_1_rm( ps: It<(Integer, T)>, ) -> It<((rug::Integer, T), (Integer, T))> { Box::new(ps.map(|(x, y)| ((rug::Integer::from(&x), y.clone()), (x, y)))) } #[allow(clippy::type_complexity)] pub fn integer_pair_1_nrm( ps: It<(Integer, T)>, ) -> It<((BigInt, T), (rug::Integer, T), (Integer, T))> { Box::new(ps.map(|(x, y)| { ( (BigInt::from(&x), y.clone()), (rug::Integer::from(&x), y.clone()), (x, y), ) })) } #[allow(clippy::type_complexity)] pub fn integer_triple_1_rm( ts: It<(Integer, T, U)>, ) -> It<((rug::Integer, T, U), (Integer, T, U))> { Box::new(ts.map(|(x, y, z)| ((rug::Integer::from(&x), y.clone(), z.clone()), (x, y, z)))) } pub fn integer_natural_pair_rm( ps: It<(Integer, Natural)>, ) -> It<((rug::Integer, rug::Integer), (Integer, Natural))> { Box::new(ps.map(|(x, y)| ((rug::Integer::from(&x), rug::Integer::from(&y)), (x, y)))) } #[allow(clippy::type_complexity)] pub fn integer_integer_natural_triple_rm( ts: It<(Integer, Integer, Natural)>, ) -> It<( (rug::Integer, rug::Integer, rug::Integer), (Integer, Integer, Natural), )> { Box::new(ts.map(|(x, y, z)| { ( ( rug::Integer::from(&x), rug::Integer::from(&y), rug::Integer::from(&z), ), (x, y, z), ) })) } #[allow(clippy::type_complexity)] pub fn natural_natural_triple_1_2_rm( ts: It<(Natural, Natural, T)>, ) -> It<((rug::Integer, rug::Integer, T), (Natural, Natural, T))> { Box::new(ts.map(|(x, y, z)| { ( (rug::Integer::from(&x), rug::Integer::from(&y), z.clone()), (x, y, z), ) })) } #[allow(clippy::type_complexity)] pub fn integer_integer_triple_1_2_rm( ts: It<(Integer, Integer, T)>, ) -> It<((rug::Integer, rug::Integer, T), (Integer, Integer, T))> { Box::new(ts.map(|(x, y, z)| { ( (rug::Integer::from(&x), rug::Integer::from(&y), z.clone()), (x, y, z), ) })) } pub fn integer_vec_nrm( xss: It>, ) -> It<(Vec, Vec, Vec)> { Box::new(xss.map(|xs| { ( xs.iter().map(BigInt::from).collect(), xs.iter().map(rug::Integer::from).collect(), xs, ) })) } pub fn natural_vec_nrm( xss: It>, ) -> It<(Vec, Vec, Vec)> { Box::new(xss.map(|xs| { ( xs.iter().map(BigUint::from).collect(), xs.iter().map(rug::Integer::from).collect(), xs, ) })) } ================================================ FILE: malachite-nz/src/test_util/generators/exhaustive.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::exhaustive::{ exhaustive_integers, exhaustive_natural_integers, exhaustive_negative_integers, exhaustive_nonzero_integers, }; use crate::integer::logic::bit_access::limbs_vec_clear_bit_neg; use crate::natural::Natural; use crate::natural::arithmetic::add::{limbs_vec_add_in_place_left, limbs_vec_add_limb_in_place}; use crate::natural::arithmetic::binomial_coefficient::{ BIN_GOETGHELUCK_THRESHOLD, BIN_UIUI_RECURSIVE_SMALLDC, }; use crate::natural::arithmetic::div_exact::{ limbs_modular_invert_limb, limbs_modular_invert_scratch_len, }; use crate::natural::arithmetic::div_mod::{ limbs_div_mod_barrett_is_len, limbs_div_mod_barrett_scratch_len, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::eq_mod::{ limbs_eq_limb_mod_limb, limbs_eq_limb_mod_ref_ref, limbs_eq_mod_limb_ref_ref, limbs_eq_mod_ref_ref_ref, }; use crate::natural::arithmetic::gcd::half_gcd::HalfGcdMatrix1; use crate::natural::arithmetic::mod_mul::limbs_precompute_mod_mul_two_limbs; use crate::natural::arithmetic::mod_power_of_2::limbs_slice_mod_power_of_2_in_place; use crate::natural::arithmetic::mod_power_of_2_square::SQRLO_DC_THRESHOLD_LIMIT; use crate::natural::arithmetic::mul::limb::{ limbs_slice_mul_limb_in_place, limbs_vec_mul_limb_in_place, }; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::mul::mul_mod::limbs_mul_mod_base_pow_n_minus_1_next_size; use crate::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h_input_sizes_valid, limbs_mul_greater_to_out_toom_8h_input_sizes_valid, limbs_mul_greater_to_out_toom_22_input_sizes_valid, limbs_mul_greater_to_out_toom_32_input_sizes_valid, limbs_mul_greater_to_out_toom_33_input_sizes_valid, limbs_mul_greater_to_out_toom_42_input_sizes_valid, limbs_mul_greater_to_out_toom_43_input_sizes_valid, limbs_mul_greater_to_out_toom_44_input_sizes_valid, limbs_mul_greater_to_out_toom_52_input_sizes_valid, limbs_mul_greater_to_out_toom_53_input_sizes_valid, limbs_mul_greater_to_out_toom_54_input_sizes_valid, limbs_mul_greater_to_out_toom_62_input_sizes_valid, limbs_mul_greater_to_out_toom_63_input_sizes_valid, }; use crate::natural::arithmetic::square::{ limbs_square_to_out_toom_3_input_size_valid, limbs_square_to_out_toom_4_input_size_valid, limbs_square_to_out_toom_6_input_size_valid, limbs_square_to_out_toom_8_input_size_valid, }; use crate::natural::arithmetic::sub::{limbs_sub_greater_in_place_left, limbs_sub_limb_in_place}; use crate::natural::comparison::cmp::limbs_cmp; use crate::natural::conversion::digits::general_digits::{ GET_STR_PRECOMPUTE_THRESHOLD, limbs_digit_count, limbs_per_digit_in_base, }; use crate::natural::exhaustive::{ ExhaustiveNaturalRange, exhaustive_natural_range, exhaustive_natural_range_to_infinity, exhaustive_naturals, exhaustive_positive_naturals, }; use crate::natural::logic::significant_bits::limbs_significant_bits; use crate::platform::{ DoubleLimb, Limb, ODD_CENTRAL_BINOMIAL_OFFSET, ODD_CENTRAL_BINOMIAL_TABLE_LIMIT, ODD_FACTORIAL_EXTTABLE_LIMIT, ODD_FACTORIAL_TABLE_LIMIT, SQR_TOOM2_THRESHOLD, }; use crate::test_util::extra_variadic::{ exhaustive_quadruples_from_single, exhaustive_quadruples_xxxy, exhaustive_quadruples_xxxy_custom_output, exhaustive_quadruples_xyxz, exhaustive_quadruples_xyyx, exhaustive_quadruples_xyyz, exhaustive_quintuples_xyyyz, exhaustive_sextuples_from_single, exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, exhaustive_triples_xyx, }; use crate::test_util::generators::{factors_of_limb_max, limbs_odd_factorial_valid}; use crate::test_util::natural::arithmetic::gcd::{OwnedHalfGcdMatrix, half_gcd_matrix_create}; use itertools::Itertools; use malachite_base::bools::exhaustive::{ExhaustiveBools, exhaustive_bools}; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::iterators::iter_windows; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, CoprimeWith, DivRound, DivisibleBy, DivisibleByPowerOf2, EqMod, EqModPowerOf2, Parity, PowerOf2, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::exhaustive::exhaustive_to_sci_options; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, SaturatingFrom, ToSci, WrappingFrom, }; use malachite_base::num::exhaustive::{ PrimitiveIntIncreasingRange, exhaustive_natural_signeds, exhaustive_positive_primitive_ints, exhaustive_primitive_floats, exhaustive_signeds, exhaustive_unsigneds, primitive_int_increasing_inclusive_range, primitive_int_increasing_range, }; use malachite_base::num::factorization::prime_sieve::n_to_bit; use malachite_base::num::iterators::{bit_distributor_sequence, ruler_sequence}; use malachite_base::num::logic::traits::{ BitAccess, BitConvertible, LeadingZeros, SignificantBits, }; use malachite_base::rational_sequences::RationalSequence; use malachite_base::rational_sequences::exhaustive::exhaustive_rational_sequences; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::slices::slice_trailing_zeros; use malachite_base::test_util::generators::common::{ It, permute_1_3_2, permute_2_1, reshape_1_2_to_3, reshape_1_3_to_4, reshape_2_1_to_3, reshape_2_2_to_4, }; use malachite_base::test_util::generators::exhaustive::{ UnsignedVecPairLenGenerator1, UnsignedVecPairLenGenerator2, UnsignedVecQuadrupleLenGenerator1, UnsignedVecTripleLenGenerator1, UnsignedVecTripleXYYLenGenerator, exhaustive_unsigned_pair_gen_var_20, exhaustive_unsigned_pair_gen_var_24, exhaustive_unsigned_vec_unsigned_pair_gen_var_17, }; use malachite_base::test_util::generators::{ exhaustive_pairs_big_small, exhaustive_pairs_big_tiny, }; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairsYsGenerator, exhaustive_dependent_pairs, exhaustive_ordered_unique_pairs, exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_triples, exhaustive_triples_custom_output, exhaustive_triples_xyy, exhaustive_triples_xyy_custom_output, lex_pairs, }; use malachite_base::vecs::exhaustive::{ ExhaustiveVecs, LexFixedLengthVecsFromSingle, exhaustive_vecs, exhaustive_vecs_fixed_length_from_single, exhaustive_vecs_length_range, exhaustive_vecs_min_length, lex_vecs_fixed_length_from_single, }; use num::{BigInt, BigUint}; use std::cmp::{Ordering::*, max}; use std::iter::once; use std::marker::PhantomData; use std::ops::{Shl, Shr}; // -- Integer -- pub fn exhaustive_integer_gen() -> It { Box::new(exhaustive_integers()) } pub fn exhaustive_integer_gen_var_1() -> It where Natural: TryFrom, { Box::new( once(Integer::ZERO).chain( lex_pairs( exhaustive_positive_float_naturals::(0), exhaustive_bools(), ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ), ) } pub fn exhaustive_integer_gen_var_2 ConvertibleFrom<&'a Natural> + PrimitiveFloat>() -> It { Box::new( lex_pairs(exhaustive_natural_gen_var_4::(), exhaustive_bools()) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn exhaustive_integer_gen_var_3() -> It where Natural: TryFrom, { Box::new( lex_pairs(exhaustive_natural_gen_var_5::(), exhaustive_bools()) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn exhaustive_integer_gen_var_4() -> It { Box::new(exhaustive_natural_integers()) } pub fn exhaustive_integer_gen_var_5() -> It where Integer: From, { Box::new(exhaustive_unsigneds::().map(Integer::from)) } pub fn exhaustive_integer_gen_var_6() -> It where Integer: From, { Box::new(exhaustive_natural_signeds::().map(Integer::from)) } pub fn exhaustive_integer_gen_var_7() -> It { Box::new(exhaustive_negative_integers()) } pub fn exhaustive_integer_gen_var_8() -> It { Box::new(exhaustive_nonzero_integers()) } pub fn exhaustive_integer_gen_var_9() -> It { Box::new(exhaustive_natural_integers().map(|n| (n << 1u32) | Integer::ONE)) } // -- (Integer, Integer) -- pub fn exhaustive_integer_pair_gen() -> It<(Integer, Integer)> { Box::new(exhaustive_pairs_from_single(exhaustive_integers())) } pub fn exhaustive_integer_pair_gen_var_1() -> It<(Integer, Integer)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_nonzero_integers(), )) } pub fn exhaustive_integer_pair_gen_var_2() -> It<(Integer, Integer)> { Box::new( exhaustive_pairs(exhaustive_integers(), exhaustive_nonzero_integers()) .map(|(x, y)| (x * &y, y)), ) } pub fn exhaustive_integer_pair_gen_var_3() -> It<(Integer, Integer)> { Box::new( exhaustive_pairs(exhaustive_integers(), exhaustive_nonzero_integers()) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn exhaustive_integer_pair_gen_var_4() -> It<(Integer, Integer)> { Box::new( exhaustive_pairs(exhaustive_integers(), exhaustive_natural_integers()) .map(|(a, n)| (a, (n << 1u32) | Integer::ONE)), ) } pub fn exhaustive_integer_pair_gen_var_5() -> It<(Integer, Integer)> { Box::new( exhaustive_pairs_from_single(exhaustive_integers()) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn exhaustive_integer_pair_gen_var_6() -> It<(Integer, Integer)> { Box::new( exhaustive_pairs_from_single( exhaustive_natural_integers().map(|n| (n << 1u32) | Integer::ONE), ) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn exhaustive_integer_pair_gen_var_7() -> It<(Integer, Integer)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_integers(), exhaustive_unsigneds::().map(Integer::from), )) } // -- (Integer, Integer, Integer) -- pub fn exhaustive_integer_triple_gen() -> It<(Integer, Integer, Integer)> { Box::new(exhaustive_triples_from_single(exhaustive_integers())) } pub fn exhaustive_integer_triple_gen_var_1() -> It<(Integer, Integer, Integer)> { Box::new(exhaustive_triples_from_single(exhaustive_natural_integers())) } pub fn exhaustive_integer_triple_gen_var_2() -> It<(Integer, Integer, Integer)> { Box::new( exhaustive_triples_xxy(exhaustive_integers(), exhaustive_natural_integers()) .map(|(a, b, n)| (a, b, (n << 1u32) | Integer::ONE)), ) } pub fn exhaustive_integer_triple_gen_var_3() -> It<(Integer, Integer, Integer)> { Box::new( exhaustive_triples_xyy(exhaustive_integers(), exhaustive_natural_integers()) .map(|(a, m, n)| (a, (m << 1u32) | Integer::ONE, (n << 1u32) | Integer::ONE)), ) } // -- (Integer, Integer, Integer, PrimitiveUnsigned) -- pub fn exhaustive_integer_integer_integer_unsigned_quadruple_gen_var_1() -> It<(Integer, Integer, Integer, T)> { Box::new(exhaustive_quadruples_xxxy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (Integer, Integer, Natural) -- pub fn exhaustive_integer_integer_natural_triple_gen() -> It<(Integer, Integer, Natural)> { Box::new(exhaustive_triples_xxy( exhaustive_integers(), exhaustive_naturals(), )) } pub fn exhaustive_integer_integer_natural_triple_gen_var_1() -> It<(Integer, Integer, Natural)> { Box::new( exhaustive_triples_xxy(exhaustive_integers(), exhaustive_naturals()) .map(|(x, y, m)| (x * Integer::from(&m) + &y, y, m)), ) } pub fn exhaustive_integer_integer_natural_triple_gen_var_2() -> It<(Integer, Integer, Natural)> { Box::new( exhaustive_triples_xxy(exhaustive_integers(), exhaustive_naturals()) .filter(|(x, y, m)| !x.eq_mod(y, m)), ) } // -- (Integer, Integer, PrimitiveFloat) -- pub fn exhaustive_integer_integer_primitive_float_triple_gen() -> It<(Integer, Integer, T)> { Box::new(exhaustive_triples_xxy( exhaustive_integers(), exhaustive_primitive_floats(), )) } // -- (Integer, Integer, PrimitiveSigned) -- pub fn exhaustive_integer_integer_signed_triple_gen() -> It<(Integer, Integer, T)> { Box::new(exhaustive_triples_xxy( exhaustive_integers(), exhaustive_signeds::(), )) } // -- (Integer, Integer, PrimitiveUnsigned) -- pub fn exhaustive_integer_integer_unsigned_triple_gen() -> It<(Integer, Integer, T)> { Box::new(exhaustive_triples_xxy( exhaustive_integers(), exhaustive_unsigneds::(), )) } pub fn exhaustive_integer_integer_unsigned_triple_gen_var_1() -> It<(Integer, Integer, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_integer_integer_unsigned_triple_gen_var_2() -> It<(Integer, Integer, T)> where Integer: Shl, { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn exhaustive_integer_integer_unsigned_triple_gen_var_3() -> It<(Integer, Integer, T)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } // -- (Integer, Integer, RoundingMode) -- pub fn exhaustive_integer_integer_rounding_mode_triple_gen_var_1() -> It<(Integer, Integer, RoundingMode)> { Box::new( exhaustive_triples( exhaustive_integers(), exhaustive_nonzero_integers(), exhaustive_rounding_modes(), ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub(crate) fn round_to_multiple_integer_filter_map( x: Integer, y: Integer, rm: RoundingMode, ) -> Option<(Integer, Integer, RoundingMode)> { if x == y { Some((x, y, rm)) } else if y == 0 { if rm == Down || rm == if x >= 0 { Floor } else { Ceiling } || rm == Nearest { Some((x, y, rm)) } else { None } } else if rm == Exact { Some((x * &y, y, rm)) } else { Some((x, y, rm)) } } pub fn exhaustive_integer_integer_rounding_mode_triple_gen_var_2() -> It<(Integer, Integer, RoundingMode)> { Box::new( exhaustive_triples( exhaustive_integers(), exhaustive_nonzero_integers(), exhaustive_rounding_modes(), ) .filter_map(|(x, y, rm)| round_to_multiple_integer_filter_map(x, y, rm)), ) } // -- (Integer, Natural) -- pub fn exhaustive_integer_natural_pair_gen() -> It<(Integer, Natural)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_naturals(), )) } // -- (Integer, Natural, Natural) -- pub fn exhaustive_integer_natural_natural_triple_gen() -> It<(Integer, Natural, Natural)> { Box::new(exhaustive_triples_xyy( exhaustive_integers(), exhaustive_naturals(), )) } // -- (Integer, PrimitiveFloat) -- pub fn exhaustive_integer_primitive_float_pair_gen() -> It<(Integer, T)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_primitive_floats(), )) } // -- (Integer, PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_integer_primitive_float_primitive_float_triple_gen() -> It<(Integer, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_integers(), exhaustive_primitive_floats(), )) } // -- (Integer, PrimitiveSigned) -- pub fn exhaustive_integer_signed_pair_gen() -> It<(Integer, T)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_signeds(), )) } pub fn exhaustive_integer_signed_pair_gen_var_1() -> It<(Integer, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_integers(), exhaustive_signeds(), )) } // -- (Integer, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_integer_signed_signed_triple_gen() -> It<(Integer, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_integers(), exhaustive_signeds::(), )) } // -- (Integer, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_integer_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(Integer, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_integers(), exhaustive_signeds::(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Integer, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_integer_signed_rounding_mode_triple_gen_var_1() -> It<(Integer, T, RoundingMode)> where Integer: Shr, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_integers(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .map(|((n, i), rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn exhaustive_integer_signed_rounding_mode_triple_gen_var_2() -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_integers(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .map(|((n, i), rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Integer, PrimitiveUnsigned) -- pub fn exhaustive_integer_unsigned_pair_gen() -> It<(Integer, T)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_unsigneds(), )) } pub fn exhaustive_integer_unsigned_pair_gen_var_1() -> It<(Integer, T)> { Box::new(lex_pairs( exhaustive_integers(), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )) } pub fn exhaustive_integer_unsigned_pair_gen_var_2() -> It<(Integer, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_integers(), exhaustive_unsigneds(), )) } pub fn exhaustive_integer_unsigned_pair_gen_var_3() -> It<(Integer, T)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_natural_integers(), exhaustive_positive_primitive_ints(), ) .interleave(exhaustive_pairs_big_tiny( exhaustive_negative_integers(), exhaustive_unsigneds::() .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)), )), ) } struct IntegerDivisibleByP2PairsGenerator; impl ExhaustiveDependentPairsYsGenerator> for IntegerDivisibleByP2PairsGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It { let pow = *pow; if pow == 0 { Box::new(exhaustive_integers()) } else { Box::new(exhaustive_integers().map(move |k| k << pow)) } } } pub fn exhaustive_integer_unsigned_pair_gen_var_4() -> It<(Integer, T)> { permute_2_1(Box::new( exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), IntegerDivisibleByP2PairsGenerator, ) .map(|(x, y)| (T::exact_from(x), y)), )) } pub fn exhaustive_integer_unsigned_pair_gen_var_5() -> It<(Integer, T)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_integers(), exhaustive_unsigneds::()) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn exhaustive_integer_unsigned_pair_gen_var_6() -> It<(Integer, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_integers(), exhaustive_positive_primitive_ints(), )) } // -- (Integer, PrimitiveUnsigned, bool) -- pub fn exhaustive_integer_unsigned_bool_triple_gen_var_1() -> It<(Integer, T, bool)> { Box::new(exhaustive_triples_custom_output( exhaustive_integers(), exhaustive_unsigneds(), exhaustive_bools(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), )) } // -- (Integer, PrimitiveUnsigned, Natural) -- pub fn exhaustive_integer_unsigned_natural_triple_gen() -> It<(Integer, T, Natural)> { Box::new(exhaustive_triples( exhaustive_integers(), exhaustive_unsigneds(), exhaustive_naturals(), )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned) -- type T1 = It<(Integer, T, T)>; pub fn exhaustive_integer_unsigned_unsigned_triple_gen() -> T1 { Box::new(exhaustive_triples_xyy( exhaustive_integers(), exhaustive_unsigneds::(), )) } pub fn exhaustive_integer_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Integer, T, U)> { permute_1_3_2(reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_integers(), exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )))) } pub fn exhaustive_integer_unsigned_unsigned_triple_gen_var_2() -> It<(Integer, T, T)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(x, y, z)| y.checked_add(z).map(|new_z| (x, y, new_z))), ) } pub fn exhaustive_integer_unsigned_unsigned_triple_gen_var_3() -> It<(Integer, T, T)> { Box::new(exhaustive_triples_xyy_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn exhaustive_integer_unsigned_unsigned_natural_quadruple_gen_var_1() -> It<(Integer, T, T, Natural)> { Box::new( exhaustive_quadruples_xyyz( exhaustive_integers(), exhaustive_unsigneds::(), exhaustive_naturals(), ) .filter(|(_, y, z, _)| y < z), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_integer_unsigned_rounding_mode_triple_gen_var_1() -> It<(Integer, u64, RoundingMode)> { Box::new( exhaustive_triples_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), exhaustive_rounding_modes(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .map(|(n, u, rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } pub fn exhaustive_integer_unsigned_rounding_mode_triple_gen_var_2() -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_integers(), exhaustive_unsigneds::()), exhaustive_rounding_modes(), ) .map(|((n, u), rm)| (if rm == Exact { n << u } else { n }, u, rm)), ) } // vars 3 and 4 are in malachite-float. pub fn exhaustive_integer_unsigned_rounding_mode_triple_gen_var_5() -> It<(Integer, T, RoundingMode)> { Box::new(exhaustive_triples_custom_output( exhaustive_integers(), exhaustive_unsigneds::(), exhaustive_rounding_modes(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Integer, RoundingMode) -- pub fn exhaustive_integer_rounding_mode_pair_gen() -> It<(Integer, RoundingMode)> { Box::new(lex_pairs( exhaustive_integers(), exhaustive_rounding_modes(), )) } pub fn exhaustive_integer_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat, >() -> It<(Integer, RoundingMode)> { Box::new( lex_pairs(exhaustive_integers(), exhaustive_rounding_modes()) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn exhaustive_integer_rounding_mode_pair_gen_var_2() -> It<(Integer, RoundingMode)> { Box::new(lex_pairs( exhaustive_nonzero_integers(), exhaustive_rounding_modes(), )) } // -- (Integer, ToSciOptions) -- pub fn exhaustive_integer_to_sci_options_pair_gen() -> It<(Integer, ToSciOptions)> { Box::new(exhaustive_pairs( exhaustive_integers(), exhaustive_to_sci_options(), )) } pub fn exhaustive_integer_to_sci_options_pair_gen_var_1() -> It<(Integer, ToSciOptions)> { Box::new( exhaustive_pairs(exhaustive_integers(), exhaustive_to_sci_options()) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (Integer, Vec) -- struct IntegerBoolVecPairGenerator1; impl ExhaustiveDependentPairsYsGenerator< Integer, Vec, LexFixedLengthVecsFromSingle, > for IntegerBoolVecPairGenerator1 { #[inline] fn get_ys(&self, x: &Integer) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single( u64::exact_from(x.to_twos_complement_limbs_asc().len()), exhaustive_bools(), ) } } pub fn exhaustive_integer_bool_vec_pair_gen_var_1() -> It<(Integer, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_integers(), IntegerBoolVecPairGenerator1, )) } struct IntegerBoolVecPairGenerator2; impl ExhaustiveDependentPairsYsGenerator< Integer, Vec, LexFixedLengthVecsFromSingle, > for IntegerBoolVecPairGenerator2 { #[inline] fn get_ys(&self, x: &Integer) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single( u64::exact_from(x.to_bits_asc().len()), exhaustive_bools(), ) } } pub fn exhaustive_integer_bool_vec_pair_gen_var_2() -> It<(Integer, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_integers(), IntegerBoolVecPairGenerator2, )) } // -- Natural -- pub fn exhaustive_natural_gen() -> It { Box::new(exhaustive_naturals()) } pub fn exhaustive_natural_gen_var_1() -> It { Box::new(exhaustive_natural_range_to_infinity(Natural::TWO)) } pub fn exhaustive_natural_gen_var_2() -> It { Box::new(exhaustive_positive_naturals()) } struct ExhaustivePositiveFloatNaturals { phantom: PhantomData<*const T>, done: bool, exponent: i64, limit: u64, mantissa: u64, max_finite: Natural, } impl Iterator for ExhaustivePositiveFloatNaturals where Natural: TryFrom, { type Item = Natural; fn next(&mut self) -> Option { if self.done { None } else { let n: Natural = ExactFrom::exact_from(self.mantissa); let n = n << self.exponent; if n == self.max_finite { self.done = true; } else { self.mantissa += 1; if self.mantissa == self.limit { self.mantissa >>= 1; self.exponent += 1; self.limit = u64::power_of_2(T::MANTISSA_WIDTH + 1); } } Some(n) } } } fn exhaustive_positive_float_naturals( start_exponent: i64, ) -> ExhaustivePositiveFloatNaturals where Natural: TryFrom, { ExhaustivePositiveFloatNaturals { phantom: PhantomData, done: false, exponent: start_exponent, limit: u64::power_of_2(T::MANTISSA_WIDTH + 1), mantissa: if start_exponent == 0 { 1 } else { u64::power_of_2(T::MANTISSA_WIDTH) }, max_finite: Natural::exact_from(T::MAX_FINITE), } } pub fn exhaustive_natural_gen_var_3() -> It where Natural: TryFrom, { Box::new(once(Natural::ZERO).chain(exhaustive_positive_float_naturals::(0))) } pub fn exhaustive_natural_gen_var_4 ConvertibleFrom<&'a Natural> + PrimitiveFloat>() -> It { Box::new( exhaustive_natural_range_to_infinity( Natural::power_of_2(T::MANTISSA_WIDTH + 1) | Natural::ONE, ) .filter(|n| !T::convertible_from(n)), ) } pub fn exhaustive_natural_gen_var_5() -> It where Natural: TryFrom, { Box::new( iter_windows(2, exhaustive_positive_float_naturals::(1)).filter_map(|xs| { let mut xs = xs.into_iter(); let a = xs.next().unwrap(); let diff = xs.next().unwrap() - &a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn exhaustive_natural_gen_var_6() -> It where Natural: From, { Box::new(exhaustive_unsigneds::().map(Natural::from)) } pub fn exhaustive_natural_gen_var_7() -> It where Natural: ExactFrom, { Box::new(exhaustive_natural_signeds::().map(Natural::exact_from)) } pub fn exhaustive_natural_gen_var_8() -> It { Box::new(exhaustive_naturals().map(|n| (n << 1u32) | Natural::ONE)) } // -- (Natural, bool) -- pub fn exhaustive_natural_bool_pair_gen() -> It<(Natural, bool)> { Box::new(lex_pairs(exhaustive_naturals(), exhaustive_bools())) } // -- (Natural, Integer, Natural) -- pub fn exhaustive_natural_integer_natural_triple_gen() -> It<(Natural, Integer, Natural)> { Box::new(exhaustive_triples_xyx( exhaustive_naturals(), exhaustive_integers(), )) } // -- (Natural, Natural) -- pub fn exhaustive_natural_pair_gen() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs_from_single(exhaustive_naturals())) } pub fn exhaustive_natural_pair_gen_var_1() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs( exhaustive_natural_range_to_infinity(Natural::power_of_2(Limb::WIDTH)), exhaustive_natural_range_to_infinity(Natural::TWO), )) } pub fn exhaustive_natural_pair_gen_var_2() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_natural_range_to_infinity(Natural::TWO), )) } pub fn exhaustive_natural_pair_gen_var_3() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs( exhaustive_positive_naturals(), exhaustive_natural_range_to_infinity(Natural::TWO), )) } pub fn exhaustive_natural_pair_gen_var_4() -> It<(Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()) .map(|(x, y, z)| (x * &y, y * z)) .unique(), ) } pub fn exhaustive_natural_pair_gen_var_5() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_positive_naturals(), )) } pub fn exhaustive_natural_pair_gen_var_6() -> It<(Natural, Natural)> { Box::new( exhaustive_pairs(exhaustive_naturals(), exhaustive_positive_naturals()) .map(|(x, y)| (x * &y, y)), ) } pub fn exhaustive_natural_pair_gen_var_7() -> It<(Natural, Natural)> { Box::new( exhaustive_pairs(exhaustive_naturals(), exhaustive_positive_naturals()) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn exhaustive_natural_pair_gen_var_8() -> It<(Natural, Natural)> { Box::new(exhaustive_ordered_unique_pairs(exhaustive_naturals())) } pub fn exhaustive_natural_pair_gen_var_9() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs_from_single(exhaustive_positive_naturals())) } pub fn exhaustive_natural_pair_gen_var_10() -> It<(Natural, Natural)> { // TODO Box::new(exhaustive_pairs_from_single(exhaustive_naturals()).filter(|(x, y)| x >= y)) } pub fn exhaustive_natural_pair_gen_var_11() -> It<(Natural, Natural)> { Box::new(exhaustive_ordered_unique_pairs( exhaustive_positive_naturals(), )) } pub fn exhaustive_natural_pair_gen_var_12() -> It<(Natural, Natural)> { Box::new( exhaustive_pairs_from_single(exhaustive_naturals()) .map(|(a, n)| (a, (n << 1u32) | Natural::ONE)), ) } pub fn exhaustive_natural_pair_gen_var_13() -> It<(Natural, Natural)> { Box::new( exhaustive_pairs_from_single(exhaustive_naturals().map(|n| (n << 1u32) | Natural::ONE)) .filter(|(x, y)| x.coprime_with(y)), ) } pub fn exhaustive_natural_pair_gen_var_14() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs_from_single(exhaustive_naturals()).filter(|(x, y)| x.coprime_with(y))) } pub fn exhaustive_natural_pair_gen_var_15() -> It<(Natural, Natural)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), exhaustive_unsigneds::().map(Natural::from), )) } // -- (Natural, Natural, bool) -- pub fn exhaustive_natural_natural_bool_triple_gen_var_1() -> It<(Natural, Natural, bool)> { reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs(exhaustive_naturals(), exhaustive_positive_naturals()), exhaustive_bools(), ))) } // -- (Natural, Natural, Natural) -- pub fn exhaustive_natural_triple_gen() -> It<(Natural, Natural, Natural)> { Box::new(exhaustive_triples_from_single(exhaustive_naturals())) } pub fn exhaustive_natural_triple_gen_var_1() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()).map(|(x, y, m)| (x * &m + &y, y, m)), ) } pub fn exhaustive_natural_triple_gen_var_2() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()).filter(|(x, y, m)| !x.eq_mod(y, m)), ) } pub fn exhaustive_natural_triple_gen_var_3() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()).map(|(x, y, z)| { let z = max(&x, &y) + z + Natural::ONE; (x, y, z) }), ) } pub fn exhaustive_natural_triple_gen_var_4() -> It<(Natural, Natural, Natural)> { Box::new(exhaustive_triples_xxy( exhaustive_naturals(), exhaustive_positive_naturals(), )) } pub fn exhaustive_natural_triple_gen_var_5() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()).map(|(x, y, mut z)| { z += &x; z += Natural::ONE; (x, y, z) }), ) } pub fn exhaustive_natural_triple_gen_var_6() -> It<(Natural, Natural, Natural)> { Box::new(exhaustive_triples_from_single( exhaustive_positive_naturals(), )) } pub fn exhaustive_natural_triple_gen_var_7() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()).map(|(x, y, z)| (x + &y * &z, y, z)), ) } pub fn exhaustive_natural_triple_gen_var_8() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()) .map(|(a, b, n)| (a, b, (n << 1u32) | Natural::ONE)), ) } pub fn exhaustive_natural_triple_gen_var_9() -> It<(Natural, Natural, Natural)> { Box::new( exhaustive_triples_from_single(exhaustive_naturals()) .map(|(a, m, n)| (a, (m << 1u32) | Natural::ONE, (n << 1u32) | Natural::ONE)), ) } // -- (Natural, Natural, Natural, Natural) -- pub fn exhaustive_natural_quadruple_gen_var_1() -> It<(Natural, Natural, Natural, Natural)> { Box::new( exhaustive_quadruples_from_single(exhaustive_naturals()).map(|(x, y, z, w)| { let w = max!(&x, &y, &z) + w + Natural::ONE; (x, y, z, w) }), ) } pub fn exhaustive_natural_quadruple_gen_var_2() -> It<(Natural, Natural, Natural, Natural)> { Box::new( exhaustive_quadruples_from_single(exhaustive_naturals()).map(|(x, y, z, mut w)| { w += max!(&x, &y); w += Natural::ONE; (x, y, z, w) }), ) } pub fn exhaustive_natural_quadruple_gen_var_3() -> It<(Natural, Natural, Natural, Natural)> { Box::new( exhaustive_quadruples_from_single(exhaustive_naturals()).map(|(x, y, z, mut w)| { w += &x; w += Natural::ONE; (x, y, z, w) }), ) } // -- (Natural, Natural, Natural, PrimitiveUnsigned) -- pub fn exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_1() -> It<(Natural, Natural, Natural, T)> { Box::new(exhaustive_quadruples_xxxy_custom_output( exhaustive_naturals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_2() -> It<(Natural, Natural, Natural, u64)> { Box::new( exhaustive_quadruples_xxxy(exhaustive_naturals(), exhaustive_unsigneds::()).map( |(x, y, z, mut m)| { m += max!( x.significant_bits(), y.significant_bits(), z.significant_bits() ); (x, y, z, m) }, ), ) } pub fn exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_3() -> It<(Natural, Natural, Natural, u64)> { Box::new( exhaustive_quadruples_xxxy(exhaustive_naturals(), exhaustive_unsigneds::()).map( |(x, y, z, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, z, m) }, ), ) } pub fn exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_4() -> It<(Natural, Natural, Natural, u64)> { Box::new( exhaustive_quadruples_xxxy(exhaustive_naturals(), exhaustive_unsigneds::()).map( |(x, y, z, mut m)| { m += x.significant_bits(); (x, y, z, m) }, ), ) } // -- (Natural, Natural, PrimitiveFloat) -- pub fn exhaustive_natural_natural_primitive_float_triple_gen() -> It<(Natural, Natural, T)> { Box::new(exhaustive_triples_xxy( exhaustive_naturals(), exhaustive_primitive_floats(), )) } // -- (Natural, Natural, PrimitiveSigned) -- pub fn exhaustive_natural_natural_signed_triple_gen() -> It<(Natural, Natural, T)> { Box::new(exhaustive_triples_xxy( exhaustive_naturals(), exhaustive_signeds::(), )) } pub fn exhaustive_natural_natural_signed_triple_gen_var_1() -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs_big_small( exhaustive_ordered_unique_pairs(exhaustive_naturals()), exhaustive_signeds(), ))) } // -- (Natural, Natural, PrimitiveUnsigned) -- pub fn exhaustive_natural_natural_unsigned_triple_gen() -> It<(Natural, Natural, T)> { Box::new(exhaustive_triples_xxy( exhaustive_naturals(), exhaustive_unsigneds::(), )) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_1() -> It<(Natural, Natural, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_naturals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_2() -> It<(Natural, Natural, T)> where Natural: Shl, { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_naturals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_3() -> It<(Natural, Natural, T)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_naturals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_4() -> It<(Natural, Natural, u64)> { Box::new( exhaustive_triples_xxy(exhaustive_naturals(), exhaustive_unsigneds::()).map( |(x, y, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, m) }, ), ) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_5() -> It<(Natural, Natural, u64)> { Box::new( exhaustive_triples_xxy(exhaustive_naturals(), exhaustive_unsigneds::()).map( |(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }, ), ) } pub fn exhaustive_natural_natural_unsigned_triple_gen_var_6() -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(exhaustive_pairs_big_small( exhaustive_ordered_unique_pairs(exhaustive_naturals()), exhaustive_unsigneds(), ))) } // -- (Natural, Natural, RoundingMode) -- pub fn exhaustive_natural_natural_rounding_mode_triple_gen_var_1() -> It<(Natural, Natural, RoundingMode)> { Box::new( exhaustive_triples( exhaustive_naturals(), exhaustive_positive_naturals(), exhaustive_rounding_modes(), ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub(crate) fn round_to_multiple_natural_filter_map( x: Natural, y: Natural, rm: RoundingMode, ) -> Option<(Natural, Natural, RoundingMode)> { if x == y { Some((x, y, rm)) } else if y == 0 { if rm == Down || rm == Floor || rm == Nearest { Some((x, y, rm)) } else { None } } else if rm == Exact { Some((x * &y, y, rm)) } else { Some((x, y, rm)) } } pub fn exhaustive_natural_natural_rounding_mode_triple_gen_var_2() -> It<(Natural, Natural, RoundingMode)> { Box::new( exhaustive_triples( exhaustive_naturals(), exhaustive_positive_naturals(), exhaustive_rounding_modes(), ) .filter_map(|(x, y, rm)| round_to_multiple_natural_filter_map(x, y, rm)), ) } // -- (Natural, PrimitiveFloat) -- pub fn exhaustive_natural_primitive_float_pair_gen() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_primitive_floats(), )) } // -- (Natural, PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_natural_primitive_float_primitive_float_triple_gen() -> It<(Natural, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_naturals(), exhaustive_primitive_floats(), )) } // -- (Natural, PrimitiveInt) -- pub fn exhaustive_natural_primitive_int_pair_gen_var_1< T: PrimitiveInt + SaturatingFrom, U: PrimitiveInt, >() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), primitive_int_increasing_inclusive_range(T::TWO, T::saturating_from(U::MAX)), )) } pub fn exhaustive_natural_primitive_int_pair_gen_var_2() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), primitive_int_increasing_inclusive_range(T::TWO, T::MAX), )) } pub fn exhaustive_natural_primitive_int_pair_gen_var_3() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_natural_primitive_int_pair_gen_var_4() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_naturals(), exhaustive_positive_primitive_ints(), )) } // -- (Natural, PrimitiveInt, PrimitiveUnsigned) -- pub fn exhaustive_natural_primitive_int_unsigned_triple_gen_var_3< T: PrimitiveInt, U: PrimitiveUnsigned, >() -> It<(Natural, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_naturals(), exhaustive_positive_primitive_ints(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Natural, PrimitiveSigned) -- pub fn exhaustive_natural_signed_pair_gen() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_signeds(), )) } pub fn exhaustive_natural_signed_pair_gen_var_1() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_natural_signeds(), )) } pub fn exhaustive_natural_signed_pair_gen_var_2() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), exhaustive_signeds(), )) } pub fn exhaustive_natural_signed_pair_gen_var_3() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_positive_naturals(), exhaustive_signeds(), )) } struct NaturalBitsMultipleOfLimbBitsGenerator; impl ExhaustiveDependentPairsYsGenerator> for NaturalBitsMultipleOfLimbBitsGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It { let p = Natural::power_of_2(pow << Limb::LOG_WIDTH); Box::new(exhaustive_natural_range(&p >> 1u32, p)) } } pub fn exhaustive_natural_signed_pair_gen_var_4() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_dependent_pairs( ruler_sequence(), exhaustive_positive_primitive_ints(), NaturalBitsMultipleOfLimbBitsGenerator, ) .map(|p| p.1), exhaustive_signeds(), )) } // -- (Natural, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_natural_signed_signed_triple_gen() -> It<(Natural, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_naturals(), exhaustive_signeds::(), )) } // -- (Natural, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_natural_signed_unsigned_triple_gen_var_1() -> It<(Natural, T, u64)> { Box::new( exhaustive_triples_custom_output( exhaustive_naturals(), exhaustive_signeds::(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } pub fn exhaustive_natural_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(Natural, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_naturals(), exhaustive_signeds::(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Natural, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_natural_signed_rounding_mode_triple_gen_var_1() -> It<(Natural, T, RoundingMode)> where Natural: Shr, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_naturals(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .map(|((n, i), rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn exhaustive_natural_signed_rounding_mode_triple_gen_var_2() -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_naturals(), exhaustive_signeds::()), exhaustive_rounding_modes(), ) .map(|((n, i), rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Natural, PrimitiveUnsigned) -- pub fn exhaustive_natural_unsigned_pair_gen() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_unsigneds(), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_1() -> It<(Natural, T)> { Box::new(lex_pairs( exhaustive_naturals(), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_2() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), exhaustive_unsigneds(), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_3() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_natural_range_to_infinity(Natural::TWO), exhaustive_unsigneds(), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_4() -> It<(Natural, u64)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_naturals(), primitive_int_increasing_inclusive_range(1, T::WIDTH), )) } struct NaturalDivisibleByP2PairsGenerator; impl ExhaustiveDependentPairsYsGenerator> for NaturalDivisibleByP2PairsGenerator { #[inline] fn get_ys(&self, pow: &u64) -> It { let pow = *pow; if pow == 0 { Box::new(exhaustive_naturals()) } else { Box::new(exhaustive_naturals().map(move |k| k << pow)) } } } pub fn exhaustive_natural_unsigned_pair_gen_var_5() -> It<(Natural, T)> { permute_2_1(Box::new( exhaustive_dependent_pairs( ruler_sequence(), exhaustive_unsigneds(), NaturalDivisibleByP2PairsGenerator, ) .map(|(x, y)| (T::exact_from(x), y)), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_6() -> It<(Natural, T)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_unsigneds::()) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn exhaustive_natural_unsigned_pair_gen_var_7() -> It<(Natural, u64)> { Box::new( exhaustive_pairs(exhaustive_naturals(), exhaustive_unsigneds::()).map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } pub fn exhaustive_natural_unsigned_pair_gen_var_8() -> It<(Natural, T)> { Box::new(exhaustive_pairs( exhaustive_positive_naturals(), exhaustive_unsigneds(), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_9() -> It<(Natural, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_naturals(), exhaustive_unsigneds(), )) } pub fn exhaustive_natural_unsigned_pair_gen_var_10() -> It<(Natural, u64)> { Box::new( exhaustive_pairs( exhaustive_positive_naturals(), exhaustive_unsigneds::(), ) .map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } // -- (Natural, PrimitiveUnsigned, bool) -- pub fn exhaustive_natural_unsigned_bool_triple_gen_var_1() -> It<(Natural, T, bool)> { Box::new(exhaustive_triples_custom_output( exhaustive_naturals(), exhaustive_unsigneds(), exhaustive_bools(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), )) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned) -- type T2 = It<(Natural, T, T)>; pub fn exhaustive_natural_unsigned_unsigned_triple_gen() -> T2 { Box::new(exhaustive_triples_xyy( exhaustive_naturals(), exhaustive_unsigneds::(), )) } pub fn exhaustive_natural_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Natural, T, U)> { permute_1_3_2(reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::TWO, T::from(36u8)), )))) } pub fn exhaustive_natural_unsigned_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveInt, >() -> It<(Natural, u64, T)> { permute_1_3_2(reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(1, U::WIDTH), )))) } pub fn exhaustive_natural_unsigned_unsigned_triple_gen_var_3() -> It<(Natural, T, T)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_naturals(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter_map(|(x, y, z): (Natural, T, T)| y.checked_add(z).map(|new_z| (x, y, new_z))), ) } pub fn exhaustive_natural_unsigned_unsigned_triple_gen_var_4() -> It<(Natural, T, T)> { Box::new(exhaustive_triples_xyy_custom_output( exhaustive_naturals(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } pub fn exhaustive_natural_unsigned_unsigned_triple_gen_var_5() -> It<(Natural, T, u64)> { Box::new( exhaustive_triples_custom_output( exhaustive_naturals(), exhaustive_unsigneds::(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn exhaustive_natural_unsigned_unsigned_natural_quadruple_gen_var_1() -> It<(Natural, T, T, Natural)> { Box::new( exhaustive_quadruples_xyyx(exhaustive_naturals(), exhaustive_unsigneds()) .filter(|(_, y, z, _)| y < z), ) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- pub fn exhaustive_natural_unsigned_rounding_mode_triple_gen_var_1() -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( lex_pairs( exhaustive_pairs_big_small(exhaustive_naturals(), exhaustive_unsigneds()), exhaustive_rounding_modes(), ) .map(|((n, u), rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } // var 2 is in malachite-float // -- (Natural, PrimitiveUnsigned, Vec) -- struct NaturalUnsignedBoolVecPairGenerator; impl ExhaustiveDependentPairsYsGenerator< (Natural, u64), Vec, LexFixedLengthVecsFromSingle, > for NaturalUnsignedBoolVecPairGenerator { #[inline] fn get_ys(&self, p: &(Natural, u64)) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single( p.0.significant_bits().div_round(p.1, Up).0, exhaustive_bools(), ) } } pub fn exhaustive_natural_unsigned_bool_vec_triple_gen_var_1() -> It<(Natural, u64, Vec)> { reshape_2_1_to_3(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_big_tiny(exhaustive_naturals(), exhaustive_positive_primitive_ints()), NaturalUnsignedBoolVecPairGenerator, ))) } pub fn exhaustive_natural_unsigned_bool_vec_triple_gen_var_2() -> It<(Natural, u64, Vec)> { reshape_2_1_to_3(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), lex_pairs( exhaustive_naturals(), primitive_int_increasing_inclusive_range(1, T::WIDTH), ), NaturalUnsignedBoolVecPairGenerator, ))) } // -- (Natural, RoundingMode) -- pub fn exhaustive_natural_rounding_mode_pair_gen() -> It<(Natural, RoundingMode)> { Box::new(lex_pairs( exhaustive_naturals(), exhaustive_rounding_modes(), )) } pub fn exhaustive_natural_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >() -> It<(Natural, RoundingMode)> { Box::new( lex_pairs(exhaustive_naturals(), exhaustive_rounding_modes()) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn exhaustive_natural_rounding_mode_pair_gen_var_2() -> It<(Natural, RoundingMode)> { Box::new(lex_pairs( exhaustive_positive_naturals(), exhaustive_rounding_modes(), )) } // -- (Natural, ToSciOptions) -- pub fn exhaustive_natural_to_sci_options_pair_gen() -> It<(Natural, ToSciOptions)> { Box::new(exhaustive_pairs( exhaustive_naturals(), exhaustive_to_sci_options(), )) } pub fn exhaustive_natural_to_sci_options_pair_gen_var_1() -> It<(Natural, ToSciOptions)> { Box::new( exhaustive_pairs(exhaustive_naturals(), exhaustive_to_sci_options()) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (Natural, Vec) -- struct NaturalBoolVecPairGenerator1; impl ExhaustiveDependentPairsYsGenerator< Natural, Vec, LexFixedLengthVecsFromSingle, > for NaturalBoolVecPairGenerator1 { #[inline] fn get_ys(&self, x: &Natural) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single(x.limb_count(), exhaustive_bools()) } } pub fn exhaustive_natural_bool_vec_pair_gen_var_1() -> It<(Natural, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_naturals(), NaturalBoolVecPairGenerator1, )) } struct NaturalBoolVecPairGenerator2; impl ExhaustiveDependentPairsYsGenerator< Natural, Vec, LexFixedLengthVecsFromSingle, > for NaturalBoolVecPairGenerator2 { #[inline] fn get_ys(&self, x: &Natural) -> LexFixedLengthVecsFromSingle { lex_vecs_fixed_length_from_single(x.significant_bits(), exhaustive_bools()) } } pub fn exhaustive_natural_bool_vec_pair_gen_var_2() -> It<(Natural, Vec)> { Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_naturals(), NaturalBoolVecPairGenerator2, )) } // -- (PrimitiveUnsigned, bool) pub fn exhaustive_unsigned_bool_pair_gen_var_1() -> It<(usize, bool)> { Box::new( lex_pairs(exhaustive_unsigneds(), exhaustive_bools()) .filter(|&(n, b)| limbs_odd_factorial_valid(n, b)), ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 31 are in malachite-base. pub fn exhaustive_unsigned_pair_gen_var_32() -> It<(T, T)> { // TODO Box::new( exhaustive_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range( T::exact_from(ODD_FACTORIAL_TABLE_LIMIT + 1), T::MAX, ), ) .filter(|&(n, k)| n >= k), ) } pub fn exhaustive_unsigned_pair_gen_var_33() -> It<(T, T)> { // TODO Box::new( exhaustive_pairs( exhaustive_unsigneds(), primitive_int_increasing_inclusive_range( T::TWO, T::wrapping_from(ODD_FACTORIAL_TABLE_LIMIT), ), ) .filter(|&(n, k)| n >= k), ) } pub fn exhaustive_unsigned_pair_gen_var_34() -> It<(T, T)> { Box::new( exhaustive_pairs( primitive_int_increasing_inclusive_range( T::from(4u8), T::wrapping_from(ODD_FACTORIAL_EXTTABLE_LIMIT), ), primitive_int_increasing_inclusive_range( T::TWO, T::wrapping_from(ODD_FACTORIAL_EXTTABLE_LIMIT - 2), ), ) .filter(|&(n, k)| n >= k + T::TWO), ) } pub fn exhaustive_unsigned_pair_gen_var_35() -> It<(T, T)> { Box::new( exhaustive_pairs( primitive_int_increasing_inclusive_range( T::wrapping_from((ODD_CENTRAL_BINOMIAL_OFFSET << 1) + 1), T::MAX, ), primitive_int_increasing_inclusive_range( T::wrapping_from((ODD_CENTRAL_BINOMIAL_OFFSET << 1) - 1), T::wrapping_from( (if BIN_UIUI_RECURSIVE_SMALLDC { ODD_CENTRAL_BINOMIAL_TABLE_LIMIT } else { ODD_FACTORIAL_TABLE_LIMIT }) << 1, ), ), ) .filter(|&(n, k)| n >= k + T::TWO), ) } #[allow(clippy::useless_conversion)] pub fn exhaustive_unsigned_pair_gen_var_36() -> It<(Limb, Limb)> { Box::new( exhaustive_pairs( primitive_int_increasing_inclusive_range( Limb::wrapping_from(BIN_GOETGHELUCK_THRESHOLD) << 1, Limb::MAX, ), primitive_int_increasing_inclusive_range( Limb::wrapping_from(BIN_GOETGHELUCK_THRESHOLD), Limb::MAX, ), ) .filter(|&(n, k)| { n >= k + 5 && k > (n >> 4) && n_to_bit(u64::from(n - k)) < n_to_bit(u64::from(n)) && k <= n - k }), ) } // -- (PrimitiveUnsigned * 6) -- // var 1 is in malachite-base. pub fn exhaustive_unsigned_sextuple_gen_var_2() -> It<(Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( exhaustive_pairs( exhaustive_pairs( exhaustive_unsigned_pair_gen_var_20(), exhaustive_unsigned_pair_gen_var_24(), ) .filter(|&((n_2, n_1), (d_1, d_0))| n_2 < d_1 || n_2 == d_1 && n_1 < d_0), exhaustive_unsigneds(), ) .map(|(((n_2, n_1), (d_1, d_0)), n_0)| { ( n_2, n_1, n_0, d_1, d_0, limbs_two_limb_inverse_helper(d_1, d_0), ) }), ) } // -- (String, String, String) -- pub fn exhaustive_string_triple_gen_var_1() -> It<(String, String, String)> { Box::new(exhaustive_naturals().map(|x| { ( serde_json::to_string(&BigUint::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) })) } pub fn exhaustive_string_triple_gen_var_2() -> It<(String, String, String)> { Box::new(exhaustive_integers().map(|x| { ( serde_json::to_string(&BigInt::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) })) } // var 3 is in malachite-q. // -- Vec -- pub fn exhaustive_integer_vec_gen() -> It> { Box::new(exhaustive_vecs(exhaustive_integers())) } // -- Vec -- pub fn exhaustive_natural_vec_gen() -> It> { Box::new(exhaustive_vecs(exhaustive_naturals())) } // -- (Vec, Integer) pub fn exhaustive_natural_vec_integer_pair_gen_var_1() -> It<(Vec, Integer)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_positive_naturals()), exhaustive_integers(), )) } // -- (Vec, Natural) struct ValidDigitsGenerator; impl ExhaustiveDependentPairsYsGenerator, It>> for ValidDigitsGenerator { #[inline] fn get_ys(&self, base: &Natural) -> It> { Box::new(exhaustive_vecs(exhaustive_natural_range( Natural::ZERO, base.clone(), ))) } } pub fn exhaustive_natural_vec_natural_pair_gen_var_1() -> It<(Vec, Natural)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_natural_range_to_infinity(Natural::power_of_2(Limb::WIDTH)), ValidDigitsGenerator, ))) } pub fn exhaustive_natural_vec_natural_pair_gen_var_2() -> It<(Vec, Natural)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_natural_range_to_infinity(Natural::TWO), ValidDigitsGenerator, ))) } pub fn exhaustive_natural_vec_natural_pair_gen_var_3() -> It<(Vec, Natural)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_naturals()), exhaustive_natural_range_to_infinity(Natural::power_of_2(Limb::WIDTH)), )) } pub fn exhaustive_natural_vec_natural_pair_gen_var_4() -> It<(Vec, Natural)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_naturals()), exhaustive_natural_range_to_infinity(Natural::TWO), )) } // -- (Vec, PrimitiveInt) -- pub fn exhaustive_natural_vec_primitive_int_pair_gen_var_1() -> It<(Vec, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_naturals()), exhaustive_positive_primitive_ints(), )) } // -- (Vec, u64) -- struct PowerOf2DigitsGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, Vec, ExhaustiveVecs, ExhaustiveNaturalRange>, > for PowerOf2DigitsGenerator { #[inline] fn get_ys( &self, &log_base: &u64, ) -> ExhaustiveVecs, ExhaustiveNaturalRange> { exhaustive_vecs(exhaustive_natural_range( Natural::ZERO, Natural::power_of_2(log_base), )) } } pub fn exhaustive_natural_vec_unsigned_pair_gen_var_1() -> It<(Vec, u64)> { permute_2_1(Box::new(exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), primitive_int_increasing_inclusive_range(1, u64::MAX), PowerOf2DigitsGenerator, ))) } // -- Vec // vars 1 through 4 are in malachite-base. pub fn exhaustive_unsigned_vec_gen_var_5() -> It> { Box::new( exhaustive_vecs_min_length(1, exhaustive_unsigneds()).map(|mut xs| { limbs_vec_mul_limb_in_place(&mut xs, 3); xs }), ) } // var 6 is in malachite-base // -- (Vec, PrimitiveUnsigned) // vars 1 through 3 are in malachite-base pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_4< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveInt, >() -> It<(Vec, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(T::TWO, T::saturating_from(U::MAX)), )) } // vars 5 through 17 are in malachite-base pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_18() -> It<(Vec, u64)> { Box::new( exhaustive_unsigned_vec_unsigned_pair_gen_var_17().filter(|(xs, index)| { let mut mut_xs = xs.clone(); limbs_vec_clear_bit_neg(&mut mut_xs, *index); mut_xs.len() == xs.len() }), ) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_19() -> It<(Vec, Limb)> { Box::new( exhaustive_pairs( exhaustive_vecs_min_length(1, exhaustive_unsigneds()), exhaustive_positive_primitive_ints(), ) .map(|(mut xs, y)| { limbs_vec_mul_limb_in_place(&mut xs, y); (xs, y) }), ) } pub fn exhaustive_unsigned_vec_unsigned_pair_gen_var_20() -> It<(Vec, u64)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()), exhaustive_unsigneds(), ) .filter_map(|(mut xs, mut pow)| { let xs_last = xs.last_mut().unwrap(); *xs_last = xs_last.checked_add(1)?; pow += limbs_significant_bits_helper(&xs); Some((xs, pow)) }), ) } // var 21 is in malachite-base. // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) // vars 1 through 5 are in malachite-base pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_6() -> It<(Vec, Limb, Limb)> { Box::new( exhaustive_triples_xyy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ) .filter(|(m, x, y)| { !Integer::from(Natural::from(*x)).eq_mod(-Natural::from(*y), Natural::from_limbs_asc(m)) }), ) } // vars 7 through 8 are in malachite-base. pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_9() -> It<(Vec, Limb, Limb)> { Box::new(exhaustive_triples( exhaustive_vecs(exhaustive_unsigneds()), factors_of_limb_max().into_iter(), exhaustive_unsigneds(), )) } // var 10 is in malachite-base. pub(crate) fn map_helper_3(t: (Vec, Limb, Limb)) -> (Vec, Limb, Limb) { let (mut xs, y, m) = t; let carry = limbs_slice_mul_limb_in_place(&mut xs, m); if carry != 0 { xs.push(carry); } else if *xs.last().unwrap() == 0 { xs.pop(); } limbs_vec_add_limb_in_place(&mut xs, y); (xs, y, m) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_11() -> It<(Vec, Limb, Limb)> { Box::new( exhaustive_triples( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ) .map(map_helper_3), ) } pub(crate) fn filter_helper_6(t: &(Vec, Limb, Limb)) -> bool { let (xs, y, m) = t; !limbs_eq_limb_mod_limb(xs, *y, *m) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_12() -> It<(Vec, Limb, Limb)> { Box::new( exhaustive_triples( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ) .filter(filter_helper_6), ) } // var 13 is in malachite-base. pub(crate) fn limbs_significant_bits_helper(xs: &[Limb]) -> u64 { let trailing_zeros = usize::exact_from(slice_trailing_zeros(xs)); if trailing_zeros == xs.len() { 0 } else { limbs_significant_bits(&xs[..xs.len() - trailing_zeros]) } } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_14() -> It<(Vec, T, u64)> { Box::new( exhaustive_triples_custom_output( exhaustive_vecs(exhaustive_unsigneds::()), exhaustive_unsigneds::(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_15() -> It<(Vec, T, u64)> { Box::new( exhaustive_triples_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()), exhaustive_unsigneds::(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_16() -> It<(Vec, T, u64)> { Box::new( exhaustive_triples_custom_output( exhaustive_vecs(exhaustive_unsigneds::()), exhaustive_unsigneds::(), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); if pow == 0 { pow = 1; } (xs, y, pow) }), ) } // -- (Vec, PrimitiveUnsigned, Vec) struct ValidLengthsGenerator; impl ExhaustiveDependentPairsYsGenerator<(Vec, u64), Vec, It>> for ValidLengthsGenerator { #[inline] fn get_ys(&self, p: &(Vec, u64)) -> It> { Box::new(exhaustive_vecs_min_length( limbs_digit_count(&p.0, p.1), exhaustive_unsigneds(), )) } } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1() -> It<(Vec, u64, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_big_tiny( exhaustive_vecs(exhaustive_unsigneds()), (3u64..256).filter(|&b| !b.is_power_of_two()), ), ValidLengthsGenerator, ) .map(|((xs, base), out)| (out, base, xs)), ) } pub(crate) fn filter_map_helper_1( t: (Vec, Limb, Vec), ) -> Option<(Vec, Limb, Vec)> { let (xs, y, m) = t; let mut product_limbs = if xs.is_empty() { Vec::new() } else { limbs_mul(&xs, &m) }; if product_limbs.last() == Some(&0) { product_limbs.pop(); } if limbs_sub_limb_in_place(&mut product_limbs, y) || *product_limbs.last().unwrap() == 0 { None } else { Some((product_limbs, y, m)) } } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2() -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ))) .filter_map(filter_map_helper_1), ) } pub(crate) fn filter_helper_1(t: &(Vec, Limb, Vec)) -> bool { let (xs, y, m) = t; !Integer::from(Natural::from_limbs_asc(xs)) .eq_mod(-Natural::from(*y), Natural::from_limbs_asc(m)) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3() -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ))) .filter(filter_helper_1), ) } pub(crate) fn map_helper_1(t: (Vec, Limb, Vec)) -> (Vec, Limb, Vec) { let (xs, y, m) = t; let mut product_limbs = if xs.is_empty() { Vec::new() } else { limbs_mul(&xs, &m) }; if product_limbs.last() == Some(&0) { product_limbs.pop(); } limbs_vec_add_limb_in_place(&mut product_limbs, y); (product_limbs, y, m) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4() -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ))) .map(map_helper_1), ) } pub(crate) fn filter_helper_4(t: &(Vec, Limb, Vec)) -> bool { let (xs, y, m) = t; !limbs_eq_limb_mod_ref_ref(xs, *y, m) } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5() -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ))) .filter(filter_helper_4), ) } // -- (Vec, PrimitiveUnsigned, Vec, PrimitiveUnsigned) -- struct ValidLengthsBasecaseGenerator { min_out_len: usize, } impl ExhaustiveDependentPairsYsGenerator, It>> for ValidLengthsBasecaseGenerator { #[inline] fn get_ys(&self, &len: &usize) -> It> { Box::new(exhaustive_vecs_min_length( u64::exact_from(if len == 0 { self.min_out_len } else { len }), exhaustive_unsigneds(), )) } } struct BasecaseDigitsInputGenerator; impl ExhaustiveDependentPairsYsGenerator<(Vec, u64), (Vec, usize), It<(Vec, usize)>> for BasecaseDigitsInputGenerator { #[inline] fn get_ys(&self, p: &(Vec, u64)) -> It<(Vec, usize)> { let min_out_len = usize::exact_from(limbs_digit_count(&p.0, p.1)); permute_2_1(Box::new(exhaustive_dependent_pairs( ruler_sequence(), once(0).chain(primitive_int_increasing_inclusive_range( min_out_len, usize::MAX, )), ValidLengthsBasecaseGenerator { min_out_len }, ))) } } pub fn exhaustive_unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1< T: PrimitiveUnsigned, >() -> It<(Vec, usize, Vec, u64)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_big_tiny( exhaustive_vecs_length_range( 0, u64::wrapping_from(GET_STR_PRECOMPUTE_THRESHOLD), exhaustive_unsigneds(), ), (3u64..256).filter(|&b| !b.is_power_of_two()), ), BasecaseDigitsInputGenerator, ) .map(|((xs, base), (out, len))| (out, len, xs, base)), ) } // -- (Vec, Vec) -- // vars 1 through 10 are in malachite-base. pub(crate) fn gcd_input_filter(xs: &[Limb], ys: &[Limb]) -> bool { *xs.last().unwrap() != 0 && *ys.last().unwrap() != 0 && limbs_cmp(xs, ys) != Less && (xs[0].odd() || ys[0].odd()) } pub fn exhaustive_unsigned_vec_pair_gen_var_11() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator2, ) .map(|p| p.1) .filter(|(xs, ys)| gcd_input_filter(xs, ys)), ) } // vars 12 through 13 are in malachite-base. pub fn exhaustive_unsigned_vec_pair_gen_var_14() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .filter_map(|(_, (out, mut xs))| { limbs_vec_mul_limb_in_place(&mut xs, 3); if out.len() >= xs.len() { Some((out, xs)) } else { None } }), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_15() -> It<(Vec, Vec)> { Box::new( exhaustive_pairs_from_single(exhaustive_vecs_min_length(2, exhaustive_unsigneds())) .filter_map(|(ns, ds)| { if *ds.last().unwrap() == 0 { return None; } let mut new_ns = limbs_mul(&ns, &ds); if *new_ns.last().unwrap() == 0 { new_ns.pop(); } Some((new_ns, ds)) }), ) } // vars 16 through 17 are in malachite-nz. pub fn exhaustive_unsigned_vec_pair_gen_var_18() -> It<(Vec, Vec)> { Box::new( exhaustive_pairs_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()).filter_map(|mut xs| { let x_last = xs.last_mut().unwrap(); if *x_last == Limb::MAX { None } else { *x_last += 1; Some(xs) } }), ) .filter_map(|(ns, ds)| { let mut ns = limbs_mul(&ns, &ds); if *ns.last().unwrap() == 0 { ns.pop(); } if *ns.last().unwrap() == 0 { None } else { Some((ns, ds)) } }), ) } // vars 19 through 21 are in malachite-nz. pub fn exhaustive_unsigned_vec_pair_gen_var_22() -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs( primitive_int_increasing_inclusive_range(1, u64::MAX), primitive_int_increasing_inclusive_range( 1, u64::exact_from(SQRLO_DC_THRESHOLD_LIMIT), ), ) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } fn exhaustive_square_helper bool>( valid: &'static F, min_x: u64, ) -> It<(Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map( move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }, ), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_pair_gen_var_23() -> It<(Vec, Vec)> { exhaustive_square_helper(&|x| x <= SQR_TOOM2_THRESHOLD, 1) } pub fn exhaustive_unsigned_vec_pair_gen_var_24() -> It<(Vec, Vec)> { exhaustive_square_helper(&|_| true, 2) } pub fn exhaustive_unsigned_vec_pair_gen_var_25() -> It<(Vec, Vec)> { exhaustive_square_helper(&limbs_square_to_out_toom_3_input_size_valid, 3) } pub fn exhaustive_unsigned_vec_pair_gen_var_26() -> It<(Vec, Vec)> { exhaustive_square_helper(&limbs_square_to_out_toom_4_input_size_valid, 4) } pub fn exhaustive_unsigned_vec_pair_gen_var_27() -> It<(Vec, Vec)> { exhaustive_square_helper(&|x| x == 7 || x == 8 || x > 9, 7) } pub fn exhaustive_unsigned_vec_pair_gen_var_28() -> It<(Vec, Vec)> { exhaustive_square_helper(&limbs_square_to_out_toom_6_input_size_valid, 18) } pub fn exhaustive_unsigned_vec_pair_gen_var_29() -> It<(Vec, Vec)> { exhaustive_square_helper(&limbs_square_to_out_toom_8_input_size_valid, 40) } // vars 32 to 33 are in malachite-base. // -- (Vec, Vec, PrimitiveUnsigned) -- struct ValidDigitsGenerator1 { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator<(u64, usize), (Vec, Vec), It<(Vec, Vec)>> for ValidDigitsGenerator1 { #[inline] fn get_ys(&self, p: &(u64, usize)) -> It<(Vec, Vec)> { Box::new(exhaustive_pairs( exhaustive_vecs_fixed_length_from_single( u64::wrapping_from(p.1), primitive_int_increasing_range(T::ZERO, T::wrapping_from(p.0)), ), exhaustive_vecs_min_length(limbs_per_digit_in_base(p.1, p.0), exhaustive_unsigneds()), )) } } // var 1 is in malachite-base pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_big_tiny( (3u64..256).filter(|&b| !b.is_power_of_two()), exhaustive_positive_primitive_ints(), ), ValidDigitsGenerator1 { phantom: PhantomData, }, ) .map(|((base, _), (xs, out))| (out, xs, base)), ) } struct ValidDigitsGenerator2 { phantom: PhantomData<(T, U)>, } impl ExhaustiveDependentPairsYsGenerator<(u64, usize), (Vec, Vec), It<(Vec, Vec)>> for ValidDigitsGenerator2 { #[inline] fn get_ys(&self, p: &(u64, usize)) -> It<(Vec, Vec)> { Box::new(exhaustive_pairs( exhaustive_vecs_fixed_length_from_single( u64::wrapping_from(p.1), exhaustive_unsigneds(), ), exhaustive_vecs_min_length(limbs_per_digit_in_base(p.1, p.0), exhaustive_unsigneds()), )) } } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_big_tiny( (3u64..256).filter(|&b| !b.is_power_of_two()), exhaustive_positive_primitive_ints(), ), ValidDigitsGenerator2 { phantom: PhantomData, }, ) .map(|((base, _), (xs, out))| (out, xs, base)), ) } // vars 4 through 6 are in malachite-base. pub(crate) fn filter_map_helper_2( t: (Vec, Vec, Limb), ) -> Option<(Vec, Vec, Limb)> { let (xs, ys, m) = t; let mut product_limbs = xs; if !product_limbs.is_empty() { limbs_vec_mul_limb_in_place(&mut product_limbs, m); }; if product_limbs.last() == Some(&0) { product_limbs.pop(); } if product_limbs.len() < ys.len() || limbs_sub_greater_in_place_left(&mut product_limbs, &ys) || *product_limbs.last().unwrap() == 0 { None } else { Some((product_limbs, ys, m)) } } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ) .filter_map(filter_map_helper_2), ) } pub(crate) fn filter_helper_2(t: &(Vec, Vec, Limb)) -> bool { let (xs, ys, m) = t; !Integer::from(Natural::from_limbs_asc(xs)) .eq_mod(-Natural::from_limbs_asc(ys), Natural::from(*m)) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ) .filter(filter_helper_2), ) } // vars 9 through 13 are in malachite-base. pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(primitive_int_increasing_inclusive_range(1, u64::MAX)) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ), exhaustive_positive_primitive_ints(), ) .filter_map(|((_, (out, mut xs)), y)| { limbs_vec_mul_limb_in_place(&mut xs, y); if out.len() >= xs.len() { Some((out, xs, y)) } else { None } }), ) } pub(crate) fn map_helper_2(t: (Vec, Vec, Limb)) -> (Vec, Vec, Limb) { let (mut xs, ys, m) = t; limbs_vec_mul_limb_in_place(&mut xs, m); if xs.last() == Some(&0) { xs.pop(); } limbs_vec_add_in_place_left(&mut xs, &ys); (xs, ys, m) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_15() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ) .map(map_helper_2), ) } pub(crate) fn filter_helper_5(t: &(Vec, Vec, Limb)) -> bool { let (xs, ys, m) = t; !limbs_eq_mod_limb_ref_ref(xs, ys, *m) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_16() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_triples_xxy( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), exhaustive_positive_primitive_ints(), ) .filter(filter_helper_5), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17() -> It<(Vec, Vec, Limb)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map( |(mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; if n_len > d_init_len { Some((n_len, d_init_len)) } else { None } }, ), UnsignedVecPairLenGenerator1, ), primitive_int_increasing_inclusive_range(Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX), ) .map(|((_, (n, mut d_init)), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (n, d_init, inverse) }), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_vecs(exhaustive_unsigneds::()), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_unsigneds()).filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ), exhaustive_unsigneds(), ) .map(|((_, (xs, ys)), mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()).filter_map(|mut xs| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(1)?; Some(xs) }), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21() -> It<(Vec, Vec, u64)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()), exhaustive_unsigneds(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter_map(|(mut xs, mut es, pow)| { let last_e = es.last_mut().unwrap(); *last_e = last_e.checked_add(1)?; if es == [1] { return None; } limbs_slice_mod_power_of_2_in_place(&mut xs, pow); if *xs.last().unwrap() == 0 { None } else { Some((xs, es, pow)) } }) .unique(), ) } // -- (Vec, Vec, Vec) -- // vars 1 through 3 are in malachite-base fn exhaustive_mul_helper bool>( valid: &'static F, min_x: u64, min_y: u64, ) -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( move |(o, x, y)| { let x = x.checked_add(min_x)?; let y = y.checked_add(min_y)?; if valid(usize::exact_from(x), usize::exact_from(y)) { let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_4() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_22_input_sizes_valid, 2, 2) } pub fn exhaustive_unsigned_vec_triple_gen_var_5() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_32_input_sizes_valid, 6, 4) } pub fn exhaustive_unsigned_vec_triple_gen_var_6() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_33_input_sizes_valid, 3, 3) } pub fn exhaustive_unsigned_vec_triple_gen_var_7() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_42_input_sizes_valid, 4, 2) } pub fn exhaustive_unsigned_vec_triple_gen_var_8() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_43_input_sizes_valid, 11, 8) } pub fn exhaustive_unsigned_vec_triple_gen_var_9() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_44_input_sizes_valid, 4, 4) } pub fn exhaustive_unsigned_vec_triple_gen_var_10() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_52_input_sizes_valid, 14, 5) } pub fn exhaustive_unsigned_vec_triple_gen_var_11() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_53_input_sizes_valid, 5, 3) } pub fn exhaustive_unsigned_vec_triple_gen_var_12() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_54_input_sizes_valid, 14, 11) } pub fn exhaustive_unsigned_vec_triple_gen_var_13() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_62_input_sizes_valid, 6, 2) } pub fn exhaustive_unsigned_vec_triple_gen_var_14() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_63_input_sizes_valid, 17, 9) } pub fn exhaustive_unsigned_vec_triple_gen_var_15() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42, 42) } pub fn exhaustive_unsigned_vec_triple_gen_var_16() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper(&limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86, 86) } fn exhaustive_mul_same_length_helper bool>( valid: &'static F, min_x: u64, ) -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds::()).filter_map( move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux, ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }, ), UnsignedVecTripleXYYLenGenerator, ) .map(|p| p.1), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_18() -> It<(Vec, Vec, Vec)> { exhaustive_mul_same_length_helper(&limbs_mul_greater_to_out_toom_33_input_sizes_valid, 5) } pub fn exhaustive_unsigned_vec_triple_gen_var_19() -> It<(Vec, Vec, Vec)> { exhaustive_mul_same_length_helper(&limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42) } pub fn exhaustive_unsigned_vec_triple_gen_var_20() -> It<(Vec, Vec, Vec)> { exhaustive_mul_same_length_helper(&limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86) } pub fn exhaustive_unsigned_vec_triple_gen_var_22() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper( &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_32_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_43_input_sizes_valid(xs_len, ys_len) }, 11, 8, ) } pub fn exhaustive_unsigned_vec_triple_gen_var_23() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper( &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_42_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_53_input_sizes_valid(xs_len, ys_len) }, 5, 3, ) } // vars 24 through 36 are in malachite-base pub(crate) fn filter_map_helper_3( t: (Vec, Vec, Vec), ) -> Option<(Vec, Vec, Vec)> { let (xs, ys, m) = t; let mut product_limbs = if xs.is_empty() { Vec::new() } else { limbs_mul(&xs, &m) }; if product_limbs.last() == Some(&0) { product_limbs.pop(); } if product_limbs.len() < ys.len() || limbs_sub_greater_in_place_left(&mut product_limbs, &ys) || *product_limbs.last().unwrap() == 0 { None } else { Some((product_limbs, ys, m)) } } pub fn exhaustive_unsigned_vec_triple_gen_var_37() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_triples_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), ) .filter_map(filter_map_helper_3), ) } pub(crate) fn filter_helper_3(t: &(Vec, Vec, Vec)) -> bool { let (xs, ys, m) = t; !Integer::from(Natural::from_limbs_asc(xs)) .eq_mod(-Natural::from_limbs_asc(ys), Natural::from_limbs_asc(m)) } pub fn exhaustive_unsigned_vec_triple_gen_var_38() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_triples_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(filter_helper_3), ) } // vars 39 through 41 are in malachite-base. pub fn exhaustive_unsigned_vec_triple_gen_var_42() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(2)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_inclusive_range(Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX), ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_43() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len > d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_inclusive_range(Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX), ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_44() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len { Some((q_len, n_len, d_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d))| { if *d.last().unwrap() != 0 { Some((q, n, d)) } else { None } }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_45() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len && n_len < (d_len - 1) << 1 { Some((q_len, n_len, d_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d))| { if *d.last().unwrap() != 0 { Some((q, n, d)) } else { None } }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_46() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), UnsignedVecTripleLenGenerator1, ) .filter_map( |(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].odd() { Some((q, n, d)) } else { None } }, ), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_47() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(1, u64::MAX)) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), UnsignedVecTripleLenGenerator1, ) .filter_map( |(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].odd() { Some((q, n, d)) } else { None } }, ), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_48() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(1, u64::MAX)) .filter_map(|(q_len, n_len, d_len)| { if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if *d.last().unwrap() == 0 { return None; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() + d.len() >= new_n.len() + 1 { Some((q, new_n, d)) } else { None } }), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_49() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(1, u64::MAX)) .filter_map(|(q_len, n_len, mut d_len)| { d_len = d_len.checked_add(1)?; if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if *d.last().unwrap() == 0 { return None; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() > new_n.len() - d.len() { Some((q, n, d)) } else { None } }), ) } // vars 50 through 53 are in malachite-base. pub(crate) fn limbs_eq_mod_map( xs: &[Limb], ys: Vec, m: Vec, ) -> (Vec, Vec, Vec) { let mut product_limbs = if xs.is_empty() { Vec::new() } else { limbs_mul(xs, &m) }; if product_limbs.last() == Some(&0) { product_limbs.pop(); } limbs_vec_add_in_place_left(&mut product_limbs, &ys); (product_limbs, ys, m) } pub fn exhaustive_unsigned_vec_triple_gen_var_54() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_triples_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), ) .map(|(xs, ys, m)| limbs_eq_mod_map(&xs, ys, m)), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_55() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_triples_from_single( exhaustive_vecs_min_length(2, exhaustive_unsigneds()) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(|(xs, ys, m)| !limbs_eq_mod_ref_ref_ref(xs, ys, m)), ) } pub fn exhaustive_unsigned_vec_triple_gen_var_56() -> It<(Vec, Vec, Vec)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_unsigneds()).filter_map( |(q_len, n_len): (u64, u64)| { Some((q_len.checked_add(n_len)?, n_len.checked_add(2)?)) }, ), UnsignedVecPairLenGenerator1, ), exhaustive_pairs( primitive_int_increasing_inclusive_range( Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, ), exhaustive_unsigneds(), ), ) .map(|((_, (q, n)), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // var 57 is in malachite-base. pub fn exhaustive_unsigned_vec_triple_gen_var_58() -> It<(Vec, Vec, Vec)> { exhaustive_mul_helper( &|x, y| { limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) && limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) }, 7, 7, ) } // var 59 is in malachite-base. // -- (Vec * 4) -- #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_1() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map(|(_, (q, r, n, d))| { if *d.last().unwrap() != 0 { Some((q, r, n, d)) } else { None } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_2() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(2)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map( |(_, (q, r, n, d)): (_, (Vec, Vec, Vec, Vec))| { if d[0].odd() { Some((q, r, n, d)) } else { None } }, ), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_3() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(4)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map( #[allow(clippy::type_complexity)] |(_, (q, r, n, d)): (_, (Vec, Vec, Vec, Vec))| { if d[0].odd() { Some((q, r, n, d)) } else { None } }, ), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_4() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len && (d_len << 1) > n_len + 1 { Some((q_len, r_len, n_len, d_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map(|(_, (q, r, n, d))| { if *d.last().unwrap() != 0 { Some((q, r, n, d)) } else { None } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_5() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(3)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len > d_len && q_len + d_len >= n_len { Some((q_len, r_len, n_len, d_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map( #[allow(clippy::type_complexity)] |(_, (q, r, n, mut d)): (_, (Vec, Vec, Vec, Vec))| { let d_last = d.last_mut().unwrap(); if d_last.get_highest_bit() { None } else { d_last.set_bit(Limb::WIDTH - 1); Some((q, r, n, d)) } }, ), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_6() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_quadruples_from_single(exhaustive_unsigneds::()).filter_map( |(out_len, mut b_len, e_len, mut m_len)| { b_len = b_len.checked_add(1)?; m_len = m_len.checked_add(1)?; if out_len >= m_len { Some((out_len, b_len, e_len, m_len)) } else { None } }, ), UnsignedVecQuadrupleLenGenerator1, ) .filter_map( #[allow(clippy::type_complexity)] |(_, (out, bs, es, ms)): (_, (Vec, Vec, Vec, Vec))| { if (es.len() > 1 || es.len() == 1 && es[0] > 1) && *bs.last().unwrap() != 0 && *es.last().unwrap() != 0 && *ms.last().unwrap() != 0 { Some((out, bs, es, ms)) } else { None } }, ), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_unsigned_vec_quadruple_gen_var_7() -> It<(Vec, Vec, Vec, Vec)> { Box::new( exhaustive_unsigned_vec_quadruple_gen_var_6().filter_map(|(out, bs, es, mut ms)| { let m = &mut ms[0]; *m = m.arithmetic_checked_shl(1)?; *m |= 1; Some((out, bs, es, ms)) }), ) } // -- large types -- // vars 1 through 4 are in malachite-base fn exhaustive_half_gcd_matrices_with_size(s: usize, n: usize) -> It { assert_ne!(n, 0); assert!(n <= s); Box::new( exhaustive_quadruples_from_single(exhaustive_vecs_fixed_length_from_single( u64::exact_from(n), exhaustive_unsigneds(), )) .map(move |(mut m00, m01, m10, m11)| { m00.resize(s << 2, 0); m00[s..s + n].copy_from_slice(&m01); m00[s << 1..(s << 1) + n].copy_from_slice(&m10); m00[s * 3..s * 3 + n].copy_from_slice(&m11); half_gcd_matrix_create(s, n, m00) }), ) } struct HalfGcdMatrixGenerator; impl ExhaustiveDependentPairsYsGenerator<(usize, usize), OwnedHalfGcdMatrix, It> for HalfGcdMatrixGenerator { #[inline] fn get_ys(&self, t: &(usize, usize)) -> It { let &(n, s) = t; exhaustive_half_gcd_matrices_with_size(s, n) } } fn exhaustive_half_gcd_matrices() -> It { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_ordered_unique_pairs(exhaustive_positive_primitive_ints()), HalfGcdMatrixGenerator, ) .map(|p| p.1), ) } struct HalfGcdMatrixAndVecGenerator; impl ExhaustiveDependentPairsYsGenerator< (usize, usize, usize), (OwnedHalfGcdMatrix, Vec, u8), It<(OwnedHalfGcdMatrix, Vec, u8)>, > for HalfGcdMatrixAndVecGenerator { #[inline] fn get_ys(&self, t: &(usize, usize, usize)) -> It<(OwnedHalfGcdMatrix, Vec, u8)> { let &(qs_len, m_n, m_s) = t; reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs( exhaustive_half_gcd_matrices_with_size(m_s, m_n), exhaustive_vecs_fixed_length_from_single( u64::exact_from(qs_len), exhaustive_unsigneds(), ), ), 0..=1, ))) } } pub fn exhaustive_large_type_gen_var_5() -> It<(OwnedHalfGcdMatrix, Vec, u8)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let qs_len = x.checked_add(1)?; let m_n = qs_len.checked_add(y)?; let m_s_1 = m_n.checked_add(qs_len)?.checked_add(z)?; let m_s_2 = m_n.checked_add(2)?.checked_add(z)?; Some((qs_len, m_n, max(m_s_1, m_s_2))) }, ), HalfGcdMatrixAndVecGenerator, ) .map(|p| p.1), ) } fn exhaustive_half_gcd_matrices_1() -> It { Box::new( exhaustive_quadruples_from_single(exhaustive_unsigneds()).map(|(m00, m01, m10, m11)| { HalfGcdMatrix1 { data: [[m00, m01], [m10, m11]], } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_6() -> It<(HalfGcdMatrix1, Vec, Vec, Vec)> { reshape_1_3_to_4(Box::new(exhaustive_pairs( exhaustive_half_gcd_matrices_1(), exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(x, y, z)| { let xs_len = x; let ys_len = x.checked_add(1)?.checked_add(y)?; let out_len = x.checked_add(1)?.checked_add(z)?; Some((out_len, xs_len, ys_len)) }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), ))) } pub fn exhaustive_large_type_gen_var_7() -> It<(OwnedHalfGcdMatrix, HalfGcdMatrix1)> { Box::new(exhaustive_pairs( exhaustive_half_gcd_matrices(), exhaustive_quadruples_from_single(primitive_int_increasing_range( 0, Limb::power_of_2(Limb::WIDTH - 1), )) .map(|(m00, m01, m10, m11)| HalfGcdMatrix1 { data: [[m00, m01], [m10, m11]], }), )) } struct MatrixMul22Generator; pub(crate) type T8 = ( Vec, Vec, Vec, Vec, usize, Vec, Vec, Vec, Vec, ); impl ExhaustiveDependentPairsYsGenerator<(u64, u64), T8, It> for MatrixMul22Generator { #[inline] fn get_ys(&self, p: &(u64, u64)) -> It { let &(ys_len, xs_len) = p; Box::new( exhaustive_pairs( exhaustive_quadruples_from_single(exhaustive_vecs_fixed_length_from_single( ys_len + xs_len + 1, exhaustive_unsigneds(), )), exhaustive_quadruples_from_single(exhaustive_vecs_fixed_length_from_single( ys_len, exhaustive_unsigneds(), )), ) .map( move |((xs00, xs01, xs10, xs11), (ys00, ys01, ys10, ys11))| { ( xs00, xs01, xs10, xs11, usize::exact_from(xs_len), ys00, ys01, ys10, ys11, ) }, ), ) } } pub fn exhaustive_large_type_gen_var_8() -> It { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), ), exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()), MatrixMul22Generator, ) .map(|p| p.1), ) } // var 9 is in malachite-base. pub fn exhaustive_large_type_gen_var_10() -> It<(Vec, Vec, Limb, Limb)> { reshape_2_2_to_4(Box::new(exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_pairs_from_single(exhaustive_positive_primitive_ints()) .filter(|(x, y)| x >= y), UnsignedVecPairLenGenerator1, ) .map(|p| p.1), exhaustive_pairs(factors_of_limb_max().into_iter(), exhaustive_unsigneds()), ))) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_11() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_inclusive_range(Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX), ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_12() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_pairs( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_unsigneds::()).filter_map( |(mut q_len, mut n_len, mut d_init_len)| { q_len = q_len.checked_add(3)?; n_len = n_len.checked_add(9)?; d_init_len = d_init_len.checked_add(5)?; let d_len = d_init_len + 1; if n_len >= d_len + 3 && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .map(|p| p.1), primitive_int_increasing_inclusive_range(Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX), ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_13() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_triples_from_single(exhaustive_positive_primitive_ints()) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].even() { None } else { let inverse = limbs_modular_invert_limb(d[0]).wrapping_neg(); Some((q, n, d, inverse)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_14() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(exhaustive_positive_primitive_ints::()).filter_map( |(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }, ), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].even() { None } else { let inverse = limbs_modular_invert_limb(d[0]).wrapping_neg(); Some((q, n, d, inverse)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_15() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter_map(|(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].even() { None } else { let inverse = limbs_modular_invert_limb(d[0]).wrapping_neg(); Some((q, n, d, inverse)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_16() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_dependent_pairs( bit_distributor_sequence( BitDistributorOutputType::tiny(), BitDistributorOutputType::normal(1), ), // TODO exhaustive_triples_from_single(primitive_int_increasing_inclusive_range(2, u64::MAX)) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), UnsignedVecTripleLenGenerator1, ) .filter_map(|(_, (q, n, d)): (_, (Vec, Vec, Vec))| { if d[0].even() { None } else { let inverse = limbs_modular_invert_limb(d[0]).wrapping_neg(); Some((q, n, d, inverse)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_17() -> It<(Vec, Vec, Vec, Limb)> { Box::new( exhaustive_vecs_min_length(1, exhaustive_unsigneds::()).filter_map(|d| { if d[0].even() { None } else { let inverse = limbs_modular_invert_limb(d[0]).wrapping_neg(); let is = vec![0; d.len()]; let scratch = vec![0; limbs_modular_invert_scratch_len(d.len())]; Some((is, scratch, d, inverse)) } }), ) } pub fn exhaustive_large_type_gen_var_18() -> It<(Vec, usize, Limb, Limb, u64)> { Box::new( exhaustive_triples( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ) .filter_map(|(ns, fraction_len, d)| { if ns.len() <= fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((ns, fraction_len, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_19() -> It<(Vec, usize, Vec, Limb, Limb, u64)> { Box::new( exhaustive_quadruples_xyxz( exhaustive_vecs(exhaustive_unsigneds()), exhaustive_unsigneds(), exhaustive_positive_primitive_ints(), ) .filter_map(|(out, fraction_len, ns, d)| { if ns.is_empty() || out.len() < ns.len() + fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((out, fraction_len, ns, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_20() -> It<(Vec, Vec, Vec, Vec, usize, usize)> { Box::new( exhaustive_quintuples_xyyyz( exhaustive_vecs_min_length(2, exhaustive_unsigneds()), exhaustive_vecs(exhaustive_unsigneds()), primitive_int_increasing_inclusive_range(3, u32::MAX), ) .filter_map(|(ds, mut scratch, mut qs, mut rs_hi, n_len)| { let n_len = usize::wrapping_from(n_len); let d_len = ds.len(); if n_len < d_len { return None; } let i_len = limbs_div_mod_barrett_is_len(n_len - d_len, d_len); if i_len == 0 || qs.len() < i_len { return None; } qs.truncate(i_len); if rs_hi.len() < i_len { return None; } rs_hi.truncate(i_len); let scratch_len = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); let x = limbs_div_mod_barrett_scratch_len(n_len, d_len); if x < i_len { return None; } let actual_scratch_len = x - i_len; if actual_scratch_len < d_len + i_len { return None; } if scratch.len() < actual_scratch_len { return None; } scratch.truncate(actual_scratch_len); Some((scratch, ds, qs, rs_hi, scratch_len, i_len)) }), ) } #[allow(clippy::type_complexity)] pub(crate) fn large_type_filter_map_1( s: (Limb, Limb, Limb, Limb, Limb, Limb), ) -> Option<(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { let (x_1, x_0, y_1, y_0, m_1, m_0) = s; if m_1 == 0 || m_1 == 1 && m_0 == 0 || x_1 > m_1 || y_1 > m_1 || x_1 == m_1 && x_0 > m_0 || y_1 == m_1 && y_0 > m_0 { None } else { let (inv_2, inv_1, inv_0) = limbs_precompute_mod_mul_two_limbs(m_1, m_0); Some((x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0)) } } #[allow(clippy::type_complexity)] pub fn exhaustive_large_type_gen_var_21() -> It<(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( exhaustive_sextuples_from_single(exhaustive_unsigneds()) .filter_map(large_type_filter_map_1), ) } // var 22 is in malachite-base. struct RationalFromPowerOf2DigitsGenerator; impl ExhaustiveDependentPairsYsGenerator< u64, (Vec, RationalSequence), It<(Vec, RationalSequence)>, > for RationalFromPowerOf2DigitsGenerator { #[inline] fn get_ys(&self, log_base: &u64) -> It<(Vec, RationalSequence)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_natural_range( Natural::ZERO, Natural::power_of_2(*log_base), )), exhaustive_rational_sequences(exhaustive_natural_range( Natural::ZERO, Natural::power_of_2(*log_base), )), )) } } pub fn exhaustive_large_type_gen_var_23() -> It<(u64, Vec, RationalSequence)> { reshape_1_2_to_3(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_positive_primitive_ints(), RationalFromPowerOf2DigitsGenerator, ))) } pub fn exhaustive_large_type_gen_var_24() -> It<(Vec, RationalSequence)> { RationalFromPowerOf2DigitsGenerator.get_ys(&1) } struct RationalFromDigitsGenerator; impl ExhaustiveDependentPairsYsGenerator< Natural, (Vec, RationalSequence), It<(Vec, RationalSequence)>, > for RationalFromDigitsGenerator { #[inline] fn get_ys(&self, base: &Natural) -> It<(Vec, RationalSequence)> { Box::new(exhaustive_pairs( exhaustive_vecs(exhaustive_natural_range(Natural::ZERO, base.clone())), exhaustive_rational_sequences(exhaustive_natural_range(Natural::ZERO, base.clone())), )) } } pub fn exhaustive_large_type_gen_var_25() -> It<(Natural, Vec, RationalSequence)> { reshape_1_2_to_3(Box::new(exhaustive_dependent_pairs( ruler_sequence(), exhaustive_natural_range_to_infinity(Natural::TWO), RationalFromDigitsGenerator, ))) } pub fn exhaustive_large_type_gen_var_26() -> It<(Vec, RationalSequence)> { RationalFromDigitsGenerator.get_ys(&Natural::from(10u32)) } ================================================ FILE: malachite-nz/src/test_util/generators/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use crate::natural::arithmetic::factorial::FAC_DSC_THRESHOLD; use crate::natural::arithmetic::gcd::half_gcd::HalfGcdMatrix1; use crate::platform::{Limb, ODD_DOUBLEFACTORIAL_TABLE_LIMIT}; use crate::test_util::generators::common::{ integer_integer_natural_triple_rm, integer_integer_triple_1_2_rm, integer_natural_pair_rm, integer_nrm, integer_pair_1_nrm, integer_pair_1_rm, integer_pair_nm, integer_pair_nrm, integer_pair_rm, integer_rm, integer_triple_1_rm, integer_vec_nrm, natural_natural_triple_1_2_rm, natural_nrm, natural_pair_1_nm, natural_pair_1_nrm, natural_pair_1_rm, natural_pair_nm, natural_pair_nrm, natural_pair_rm, natural_rm, natural_triple_1_rm, natural_triple_nrm, natural_triple_rm, natural_vec_nrm, }; use crate::test_util::generators::exhaustive::*; use crate::test_util::generators::random::*; use crate::test_util::generators::special_random::*; use crate::test_util::natural::arithmetic::gcd::OwnedHalfGcdMatrix; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::generators::common::Generator; use malachite_base::vecs::exhaustive::lex_ordered_unique_vecs; use num::{BigInt, BigUint}; use std::ops::{Shl, Shr}; // -- Integer -- pub fn integer_gen() -> Generator { Generator::new( &exhaustive_integer_gen, &random_integer_gen, &special_random_integer_gen, ) } pub fn integer_gen_rm() -> Generator<(rug::Integer, Integer)> { Generator::new( &|| integer_rm(exhaustive_integer_gen()), &|config| integer_rm(random_integer_gen(config)), &|config| integer_rm(special_random_integer_gen(config)), ) } pub fn integer_gen_nrm() -> Generator<(BigInt, rug::Integer, Integer)> { Generator::new( &|| integer_nrm(exhaustive_integer_gen()), &|config| integer_nrm(random_integer_gen(config)), &|config| integer_nrm(special_random_integer_gen(config)), ) } // All `Integer`s that are exactly equal to a floating point value of type `T`. pub fn integer_gen_var_1() -> Generator where Natural: TryFrom, { Generator::new( &exhaustive_integer_gen_var_1::, &random_integer_gen_var_1::, &special_random_integer_gen_var_1::, ) } // All `Integer`s that are not equal to any floating point value of type `T`. pub fn integer_gen_var_2 ConvertibleFrom<&'a Natural> + PrimitiveFloat>() -> Generator { Generator::new( &exhaustive_integer_gen_var_2::, &random_integer_gen_var_2::, &special_random_integer_gen_var_8::, ) } // All `Integer`s that are exactly between two adjacent floats of type `T`. pub fn integer_gen_var_3 ExactFrom<&'a Natural> + PrimitiveFloat>() -> Generator where Natural: TryFrom, { Generator::new( &exhaustive_integer_gen_var_3::, &random_integer_gen_var_3::, &special_random_integer_gen_var_2::, ) } // All `Integer`s that are natural (non-negative). pub fn integer_gen_var_4() -> Generator { Generator::new( &exhaustive_integer_gen_var_4, &random_integer_gen_var_4, &special_random_integer_gen_var_3, ) } pub fn integer_gen_var_4_rm() -> Generator<(rug::Integer, Integer)> { Generator::new( &|| integer_rm(exhaustive_integer_gen_var_4()), &|config| integer_rm(random_integer_gen_var_4(config)), &|config| integer_rm(special_random_integer_gen_var_3(config)), ) } pub fn integer_gen_var_4_nrm() -> Generator<(BigInt, rug::Integer, Integer)> { Generator::new( &|| integer_nrm(exhaustive_integer_gen_var_4()), &|config| integer_nrm(random_integer_gen_var_4(config)), &|config| integer_nrm(special_random_integer_gen_var_3(config)), ) } // All `Integer`s that are exactly equal to an unsigned value of type `T`. pub fn integer_gen_var_5() -> Generator where Integer: From, { Generator::new( &exhaustive_integer_gen_var_5::, &random_integer_gen_var_5::, &special_random_integer_gen_var_4::, ) } // All `Integer`s that are exactly equal to a signed value of type `T`. pub fn integer_gen_var_6() -> Generator where Integer: From, { Generator::new( &exhaustive_integer_gen_var_6::, &random_integer_gen_var_5::, &special_random_integer_gen_var_5::, ) } // All `Integer`s that are negative. pub fn integer_gen_var_7() -> Generator { Generator::new( &exhaustive_integer_gen_var_7, &random_integer_gen_var_6, &special_random_integer_gen_var_6, ) } // All `Integer`s that are nonzero. pub fn integer_gen_var_8() -> Generator { Generator::new( &exhaustive_integer_gen_var_8, &random_integer_gen_var_7, &special_random_integer_gen_var_7, ) } // All odd positive `Integer`s. pub fn integer_gen_var_9() -> Generator { Generator::new( &exhaustive_integer_gen_var_9, &random_integer_gen_var_8, &special_random_integer_gen_var_9, ) } // -- (Integer, Integer) -- pub fn integer_pair_gen() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen, &random_integer_pair_gen, &special_random_integer_pair_gen, ) } pub fn integer_pair_gen_rm() -> Generator<((rug::Integer, rug::Integer), (Integer, Integer))> { Generator::new( &|| integer_pair_rm(exhaustive_integer_pair_gen()), &|config| integer_pair_rm(random_integer_pair_gen(config)), &|config| integer_pair_rm(special_random_integer_pair_gen(config)), ) } #[allow(clippy::type_complexity)] pub fn integer_pair_gen_nrm() -> Generator<( (BigInt, BigInt), (rug::Integer, rug::Integer), (Integer, Integer), )> { Generator::new( &|| integer_pair_nrm(exhaustive_integer_pair_gen()), &|config| integer_pair_nrm(random_integer_pair_gen(config)), &|config| integer_pair_nrm(special_random_integer_pair_gen(config)), ) } pub fn integer_pair_gen_nm() -> Generator<((BigInt, BigInt), (Integer, Integer))> { Generator::new( &|| integer_pair_nm(exhaustive_integer_pair_gen()), &|config| integer_pair_nm(random_integer_pair_gen(config)), &|config| integer_pair_nm(special_random_integer_pair_gen(config)), ) } // All pairs of `Integer`s where the second `Integer` is nonzero. pub fn integer_pair_gen_var_1() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_1, &random_integer_pair_gen_var_1, &special_random_integer_pair_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn integer_pair_gen_var_1_nrm() -> Generator<( (BigInt, BigInt), (rug::Integer, rug::Integer), (Integer, Integer), )> { Generator::new( &|| integer_pair_nrm(exhaustive_integer_pair_gen_var_1()), &|config| integer_pair_nrm(random_integer_pair_gen_var_1(config)), &|config| integer_pair_nrm(special_random_integer_pair_gen_var_1(config)), ) } pub fn integer_pair_gen_var_1_rm() -> Generator<((rug::Integer, rug::Integer), (Integer, Integer))> { Generator::new( &|| integer_pair_rm(exhaustive_integer_pair_gen_var_1()), &|config| integer_pair_rm(random_integer_pair_gen_var_1(config)), &|config| integer_pair_rm(special_random_integer_pair_gen_var_1(config)), ) } // All pairs of `Integer`s where the first `Integer` is divisible by the second, and the second is // nonzero. pub fn integer_pair_gen_var_2() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_2, &random_integer_pair_gen_var_2, &special_random_integer_pair_gen_var_2, ) } #[allow(clippy::type_complexity)] pub fn integer_pair_gen_var_2_nrm() -> Generator<( (BigInt, BigInt), (rug::Integer, rug::Integer), (Integer, Integer), )> { Generator::new( &|| integer_pair_nrm(exhaustive_integer_pair_gen_var_2()), &|config| integer_pair_nrm(random_integer_pair_gen_var_2(config)), &|config| integer_pair_nrm(special_random_integer_pair_gen_var_2(config)), ) } // All pairs of `Integer`s where the first `Integer` is not divisible by the second, and the second // is nonzero. pub fn integer_pair_gen_var_3() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_3, &random_integer_pair_gen_var_3, &special_random_integer_pair_gen_var_3, ) } // All pairs of `Integer`s where the second `Integer` is positive and odd. pub fn integer_pair_gen_var_4() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_4, &random_integer_pair_gen_var_4, &special_random_integer_pair_gen_var_4, ) } pub fn integer_pair_gen_var_4_rm() -> Generator<((rug::Integer, rug::Integer), (Integer, Integer))> { Generator::new( &|| integer_pair_rm(exhaustive_integer_pair_gen_var_4()), &|config| integer_pair_rm(random_integer_pair_gen_var_4(config)), &|config| integer_pair_rm(special_random_integer_pair_gen_var_4(config)), ) } // All coprime pairs of `Integer`s. pub fn integer_pair_gen_var_5() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_5, &random_integer_pair_gen_var_5, &special_random_integer_pair_gen_var_5, ) } // All coprime pairs of odd positive `Integer`s. pub fn integer_pair_gen_var_6() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_6, &random_integer_pair_gen_var_6, &special_random_integer_pair_gen_var_6, ) } // All pairs of `Integer`s where the second `Integer` is small and non-negative. pub fn integer_pair_gen_var_7() -> Generator<(Integer, Integer)> { Generator::new( &exhaustive_integer_pair_gen_var_7, &random_integer_pair_gen_var_7, &special_random_integer_pair_gen_var_7, ) } pub fn integer_pair_gen_var_7_rm() -> Generator<((rug::Integer, u32), (Integer, Integer))> { Generator::new( &|| { Box::new( exhaustive_integer_pair_gen_var_7() .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, &|config| { Box::new( random_integer_pair_gen_var_7(config) .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, &|config| { Box::new( special_random_integer_pair_gen_var_7(config) .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, ) } // -- (Integer, Integer, Integer) -- pub fn integer_triple_gen() -> Generator<(Integer, Integer, Integer)> { Generator::new( &exhaustive_integer_triple_gen, &random_integer_triple_gen, &special_random_integer_triple_gen, ) } // All triples of natural (non-negative) `Integer`s. pub fn integer_triple_gen_var_1() -> Generator<(Integer, Integer, Integer)> { Generator::new( &exhaustive_integer_triple_gen_var_1, &random_integer_triple_gen_var_1, &special_random_integer_triple_gen_var_1, ) } // All triples of `Integer`s where the third `Integer` is positive and odd. pub fn integer_triple_gen_var_2() -> Generator<(Integer, Integer, Integer)> { Generator::new( &exhaustive_integer_triple_gen_var_2, &random_integer_triple_gen_var_2, &special_random_integer_triple_gen_var_2, ) } // All triples of `Integer`s where the second and third `Integer`s are positive and odd. pub fn integer_triple_gen_var_3() -> Generator<(Integer, Integer, Integer)> { Generator::new( &exhaustive_integer_triple_gen_var_3, &random_integer_triple_gen_var_3, &special_random_integer_triple_gen_var_3, ) } // -- (Integer, Integer, Integer, PrimitiveUnsigned) -- // All `(Integer, Integer, Integer, T)` where `T` is unsigned and small. pub fn integer_integer_integer_unsigned_quadruple_gen_var_1() -> Generator<(Integer, Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_integer_unsigned_quadruple_gen_var_1, &random_integer_integer_integer_unsigned_quadruple_gen_var_1, &special_random_integer_integer_integer_unsigned_quadruple_gen_var_1, ) } // -- (Integer, Integer, Natural) -- pub fn integer_integer_natural_triple_gen() -> Generator<(Integer, Integer, Natural)> { Generator::new( &exhaustive_integer_integer_natural_triple_gen, &random_integer_integer_natural_triple_gen, &special_random_integer_integer_natural_triple_gen, ) } #[allow(clippy::type_complexity)] pub fn integer_integer_natural_triple_gen_rm() -> Generator<( (rug::Integer, rug::Integer, rug::Integer), (Integer, Integer, Natural), )> { Generator::new( &|| integer_integer_natural_triple_rm(exhaustive_integer_integer_natural_triple_gen()), &|config| { integer_integer_natural_triple_rm(random_integer_integer_natural_triple_gen(config)) }, &|config| { integer_integer_natural_triple_rm(special_random_integer_integer_natural_triple_gen( config, )) }, ) } // All `(Integer, Integer, Natural)` triples where the first `Integer` is equal to the second mod // the `Natural`. pub fn integer_integer_natural_triple_gen_var_1() -> Generator<(Integer, Integer, Natural)> { Generator::new( &exhaustive_integer_integer_natural_triple_gen_var_1, &random_integer_integer_natural_triple_gen_var_1, &special_random_integer_integer_natural_triple_gen_var_1, ) } // All `(Integer, Integer, Natural)` triples where the first `Integer` is not equal to the second // mod the `Natural`. pub fn integer_integer_natural_triple_gen_var_2() -> Generator<(Integer, Integer, Natural)> { Generator::new( &exhaustive_integer_integer_natural_triple_gen_var_2, &random_integer_integer_natural_triple_gen_var_2, &special_random_integer_integer_natural_triple_gen_var_2, ) } // -- (Integer, Integer, PrimitiveFloat) -- pub fn integer_integer_primitive_float_triple_gen() -> Generator<(Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_primitive_float_triple_gen, &random_integer_integer_primitive_float_triple_gen, &special_random_integer_integer_primitive_float_triple_gen, ) } // -- (Integer, Integer, PrimitiveSigned) -- pub fn integer_integer_signed_triple_gen() -> Generator<(Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_signed_triple_gen, &random_integer_integer_primitive_int_triple_gen, &special_random_integer_integer_signed_triple_gen, ) } // -- (Integer, Integer, PrimitiveUnsigned) -- pub fn integer_integer_unsigned_triple_gen() -> Generator<(Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_unsigned_triple_gen, &random_integer_integer_primitive_int_triple_gen, &special_random_integer_integer_unsigned_triple_gen, ) } // All `(Integer, Integer, T)` where `T` is unsigned and small. pub fn integer_integer_unsigned_triple_gen_var_1() -> Generator<(Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_unsigned_triple_gen_var_1, &random_integer_integer_unsigned_triple_gen_var_1, &special_random_integer_integer_unsigned_triple_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn integer_integer_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Integer, rug::Integer, T), (Integer, Integer, T))> { Generator::new( &|| integer_integer_triple_1_2_rm(exhaustive_integer_integer_unsigned_triple_gen_var_1()), &|config| { integer_integer_triple_1_2_rm(random_integer_integer_unsigned_triple_gen_var_1(config)) }, &|config| { integer_integer_triple_1_2_rm(special_random_integer_integer_unsigned_triple_gen_var_1( config, )) }, ) } // All `(Integer, Integer, T)` where `T` is unsigned and small, and the `Integer`s are equal mod 2 // to the power of the `T`. pub fn integer_integer_unsigned_triple_gen_var_2() -> Generator<(Integer, Integer, T)> where Integer: Shl, { Generator::new( &exhaustive_integer_integer_unsigned_triple_gen_var_2, &random_integer_integer_unsigned_triple_gen_var_2, &special_random_integer_integer_unsigned_triple_gen_var_2, ) } // All `(Integer, Integer, T)` where `T` is unsigned and small, and the `Integer`s are not equal mod // 2 to the power of the `T`. pub fn integer_integer_unsigned_triple_gen_var_3() -> Generator<(Integer, Integer, T)> { Generator::new( &exhaustive_integer_integer_unsigned_triple_gen_var_3, &random_integer_integer_unsigned_triple_gen_var_3, &special_random_integer_integer_unsigned_triple_gen_var_3, ) } // -- (Integer, Integer, RoundingMode) -- // All `(Integer, Integer, RoundingMode)` triples where the second `Integer` is positive and if the // `RoundingMode` is `Exact`, the first `Integer` is divisible by the second. pub fn integer_integer_rounding_mode_triple_gen_var_1() -> Generator<(Integer, Integer, RoundingMode)> { Generator::new( &exhaustive_integer_integer_rounding_mode_triple_gen_var_1, &random_integer_integer_rounding_mode_triple_gen_var_1, &special_random_integer_integer_rounding_mode_triple_gen_var_1, ) } // All `(Integer, Integer, RoundingMode)` triples that are a valid input to // `Integer::round_to_multiple`. pub fn integer_integer_rounding_mode_triple_gen_var_2() -> Generator<(Integer, Integer, RoundingMode)> { Generator::new( &exhaustive_integer_integer_rounding_mode_triple_gen_var_2, &random_integer_integer_rounding_mode_triple_gen_var_2, &special_random_integer_integer_rounding_mode_triple_gen_var_2, ) } // -- (Integer, Natural) -- pub fn integer_natural_pair_gen() -> Generator<(Integer, Natural)> { Generator::new( &exhaustive_integer_natural_pair_gen, &random_integer_natural_pair_gen, &special_random_integer_natural_pair_gen, ) } type T1 = Generator<((rug::Integer, rug::Integer), (Integer, Natural))>; pub fn integer_natural_pair_gen_rm() -> T1 { Generator::new( &|| integer_natural_pair_rm(exhaustive_integer_natural_pair_gen()), &|config| integer_natural_pair_rm(random_integer_natural_pair_gen(config)), &|config| integer_natural_pair_rm(special_random_integer_natural_pair_gen(config)), ) } // -- (Integer, Natural, Natural) -- pub fn integer_natural_natural_triple_gen() -> Generator<(Integer, Natural, Natural)> { Generator::new( &exhaustive_integer_natural_natural_triple_gen, &random_integer_natural_natural_triple_gen, &special_random_integer_natural_natural_triple_gen, ) } // -- (Integer, PrimitiveFloat) -- pub fn integer_primitive_float_pair_gen() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_primitive_float_pair_gen, &random_integer_primitive_float_pair_gen, &special_random_integer_primitive_float_pair_gen, ) } pub fn integer_primitive_float_pair_gen_rm() -> Generator<((rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_rm(exhaustive_integer_primitive_float_pair_gen()), &|config| integer_pair_1_rm(random_integer_primitive_float_pair_gen(config)), &|config| integer_pair_1_rm(special_random_integer_primitive_float_pair_gen(config)), ) } // -- (Integer, PrimitiveFloat, PrimitiveFloat) -- pub fn integer_primitive_float_primitive_float_triple_gen() -> Generator<(Integer, T, T)> { Generator::new( &exhaustive_integer_primitive_float_primitive_float_triple_gen, &random_integer_primitive_float_primitive_float_triple_gen, &special_random_integer_primitive_float_primitive_float_triple_gen, ) } // -- (Integer, PrimitiveSigned) -- pub fn integer_signed_pair_gen() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_signed_pair_gen, &random_integer_primitive_int_pair_gen, &special_random_integer_signed_pair_gen, ) } pub fn integer_signed_pair_gen_rm() -> Generator<((rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_rm(exhaustive_integer_signed_pair_gen()), &|config| integer_pair_1_rm(random_integer_primitive_int_pair_gen(config)), &|config| integer_pair_1_rm(special_random_integer_signed_pair_gen(config)), ) } // All `(Integer, T)` where `T` is signed and small. pub fn integer_signed_pair_gen_var_1() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_signed_pair_gen_var_1, &random_integer_signed_pair_gen_var_1, &special_random_integer_signed_pair_gen_var_1, ) } pub fn integer_signed_pair_gen_var_1_rm() -> Generator<((rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_rm(exhaustive_integer_signed_pair_gen_var_1()), &|config| integer_pair_1_rm(random_integer_signed_pair_gen_var_1(config)), &|config| integer_pair_1_rm(special_random_integer_signed_pair_gen_var_1(config)), ) } // -- (Integer, PrimitiveSigned, PrimitiveSigned) -- pub fn integer_signed_signed_triple_gen() -> Generator<(Integer, T, T)> { Generator::new( &exhaustive_integer_signed_signed_triple_gen, &random_integer_primitive_int_primitive_int_triple_gen, &special_random_integer_signed_signed_triple_gen, ) } // -- (Integer, PrimitiveSigned, PrimitiveUnsigned) -- // All `(Integer, T, U)` where `T` is signed and small and `U` is unsigned, small, and positive. pub fn integer_signed_unsigned_triple_gen_var_1() -> Generator<(Integer, T, U)> { Generator::new( &exhaustive_integer_signed_unsigned_triple_gen_var_1, &random_integer_signed_unsigned_triple_gen_var_1, &special_random_integer_signed_unsigned_triple_gen_var_1, ) } // -- (Integer, PrimitiveSigned, RoundingMode) -- // All `(Integer, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Integer::shl_round`. pub fn integer_signed_rounding_mode_triple_gen_var_1() -> Generator<(Integer, T, RoundingMode)> where Integer: Shr, { Generator::new( &exhaustive_integer_signed_rounding_mode_triple_gen_var_1, &random_integer_signed_rounding_mode_triple_gen_var_1, &special_random_integer_signed_rounding_mode_triple_gen_var_1, ) } // All `(Integer, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Integer::shr_round`. pub fn integer_signed_rounding_mode_triple_gen_var_2() -> Generator<(Integer, T, RoundingMode)> where Integer: Shl, { Generator::new( &exhaustive_integer_signed_rounding_mode_triple_gen_var_2, &random_integer_signed_rounding_mode_triple_gen_var_2, &special_random_integer_signed_rounding_mode_triple_gen_var_2, ) } // -- (Integer, PrimitiveUnsigned) -- pub fn integer_unsigned_pair_gen() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen, &random_integer_primitive_int_pair_gen, &special_random_integer_unsigned_pair_gen, ) } pub fn integer_unsigned_pair_gen_rm() -> Generator<((rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_rm(exhaustive_integer_unsigned_pair_gen()), &|config| integer_pair_1_rm(random_integer_primitive_int_pair_gen(config)), &|config| integer_pair_1_rm(special_random_integer_unsigned_pair_gen(config)), ) } #[allow(clippy::type_complexity)] pub fn integer_unsigned_pair_gen_nrm() -> Generator<((BigInt, T), (rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_nrm(exhaustive_integer_unsigned_pair_gen()), &|config| integer_pair_1_nrm(random_integer_primitive_int_pair_gen(config)), &|config| integer_pair_1_nrm(special_random_integer_unsigned_pair_gen(config)), ) } // All `(Integer, T)` where `T` is unsigned and between 2 and 36, inclusive. pub fn integer_unsigned_pair_gen_var_1() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_1, &random_integer_unsigned_pair_gen_var_1, &special_random_integer_unsigned_pair_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn integer_unsigned_pair_gen_var_1_nrm() -> Generator<((BigInt, T), (rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_nrm(exhaustive_integer_unsigned_pair_gen_var_1()), &|config| integer_pair_1_nrm(random_integer_unsigned_pair_gen_var_1(config)), &|config| integer_pair_1_nrm(special_random_integer_unsigned_pair_gen_var_1(config)), ) } // All `(Integer, T)` where `T` is unsigned and small. pub fn integer_unsigned_pair_gen_var_2() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_2, &random_integer_unsigned_pair_gen_var_2, &special_random_integer_unsigned_pair_gen_var_2, ) } pub fn integer_unsigned_pair_gen_var_2_rm() -> Generator<((rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_rm(exhaustive_integer_unsigned_pair_gen_var_2()), &|config| integer_pair_1_rm(random_integer_unsigned_pair_gen_var_2(config)), &|config| integer_pair_1_rm(special_random_integer_unsigned_pair_gen_var_2(config)), ) } #[allow(clippy::type_complexity)] pub fn integer_unsigned_pair_gen_var_2_nrm() -> Generator<((BigInt, T), (rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_nrm(exhaustive_integer_unsigned_pair_gen_var_2()), &|config| integer_pair_1_nrm(random_integer_unsigned_pair_gen_var_2(config)), &|config| integer_pair_1_nrm(special_random_integer_unsigned_pair_gen_var_2(config)), ) } // All `(Integer, T)` where `T` is unsigned, small, and positive, and either the `Integer` is // non-negative or the `T` is odd. pub fn integer_unsigned_pair_gen_var_3() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_3, &random_integer_unsigned_pair_gen_var_3, &special_random_integer_unsigned_pair_gen_var_3, ) } #[allow(clippy::type_complexity)] pub fn integer_unsigned_pair_gen_var_3_nrm() -> Generator<((BigInt, T), (rug::Integer, T), (Integer, T))> { Generator::new( &|| integer_pair_1_nrm(exhaustive_integer_unsigned_pair_gen_var_3()), &|config| integer_pair_1_nrm(random_integer_unsigned_pair_gen_var_3(config)), &|config| integer_pair_1_nrm(special_random_integer_unsigned_pair_gen_var_3(config)), ) } // All `(Integer, u64)`s where the `T` is unsigned and small, and the `Integer` is divisible by 2 to // the power of the `T`. pub fn integer_unsigned_pair_gen_var_4() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_4, &random_integer_unsigned_pair_gen_var_4, &special_random_integer_unsigned_pair_gen_var_4, ) } // All `(Integer, u64)`s where the `T` is unsigned and small, and the `Integer` is not divisible by // 2 to the power of the `T`. pub fn integer_unsigned_pair_gen_var_5() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_5, &random_integer_unsigned_pair_gen_var_5, &special_random_integer_unsigned_pair_gen_var_5, ) } // All `(Integer, T)` where `T` is unsigned, positive, and small. pub fn integer_unsigned_pair_gen_var_6() -> Generator<(Integer, T)> { Generator::new( &exhaustive_integer_unsigned_pair_gen_var_6, &random_integer_unsigned_pair_gen_var_6, &special_random_integer_unsigned_pair_gen_var_6, ) } // -- (Integer, PrimitiveUnsigned, bool) -- // All `(Integer, T, bool)` where `T` is unsigned and small. pub fn integer_unsigned_bool_triple_gen_var_1() -> Generator<(Integer, T, bool)> { Generator::new( &exhaustive_integer_unsigned_bool_triple_gen_var_1, &random_integer_unsigned_bool_triple_gen_var_1, &special_random_integer_unsigned_bool_triple_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn integer_unsigned_bool_triple_gen_var_1_rm() -> Generator<((rug::Integer, T, bool), (Integer, T, bool))> { Generator::new( &|| integer_triple_1_rm(exhaustive_integer_unsigned_bool_triple_gen_var_1()), &|config| integer_triple_1_rm(random_integer_unsigned_bool_triple_gen_var_1(config)), &|config| { integer_triple_1_rm(special_random_integer_unsigned_bool_triple_gen_var_1( config, )) }, ) } // -- (Integer, PrimitiveUnsigned, Natural) -- pub fn integer_unsigned_natural_triple_gen() -> Generator<(Integer, T, Natural)> { Generator::new( &exhaustive_integer_unsigned_natural_triple_gen, &random_integer_primitive_int_natural_triple_gen, &special_random_integer_unsigned_natural_triple_gen, ) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn integer_unsigned_unsigned_triple_gen() -> Generator<(Integer, T, T)> { Generator::new( &exhaustive_integer_unsigned_unsigned_triple_gen, &random_integer_primitive_int_primitive_int_triple_gen, &special_random_integer_unsigned_unsigned_triple_gen, ) } // All `(Integer, T, U)` where `T` and `U` are unsigned, the `T` is between 2 and 36, inclusive, and // the `U` is small. pub fn integer_unsigned_unsigned_triple_gen_var_1() -> Generator<(Integer, T, U)> { Generator::new( &exhaustive_integer_unsigned_unsigned_triple_gen_var_1, &random_integer_unsigned_unsigned_triple_gen_var_1, &special_random_integer_unsigned_unsigned_triple_gen_var_1, ) } // All `(Integer, T, T)` where `T` is unsigned, both `T`s are small, and the first `T` is less than // or equal to the second. pub fn integer_unsigned_unsigned_triple_gen_var_2() -> Generator<(Integer, T, T)> { Generator::new( &exhaustive_integer_unsigned_unsigned_triple_gen_var_2, &random_integer_unsigned_unsigned_triple_gen_var_2, &special_random_integer_unsigned_unsigned_triple_gen_var_2, ) } // All `(Integer, T, T)` where `T` is unsigned and both `T`s are small. pub fn integer_unsigned_unsigned_triple_gen_var_3() -> Generator<(Integer, T, T)> { Generator::new( &exhaustive_integer_unsigned_unsigned_triple_gen_var_3, &random_integer_unsigned_unsigned_triple_gen_var_3, &special_random_integer_unsigned_unsigned_triple_gen_var_3, ) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- // All `(Integer, T, T, Natural)` where `T` is unsigned and the first `T` is smaller than the // second. pub fn integer_unsigned_unsigned_natural_quadruple_gen_var_1() -> Generator<(Integer, T, T, Natural)> { Generator::new( &exhaustive_integer_unsigned_unsigned_natural_quadruple_gen_var_1, &random_integer_unsigned_unsigned_natural_triple_gen_var_1, &special_random_integer_unsigned_unsigned_natural_quadruple_gen_var_1, ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- // All `(Integer, u64, RoundingMode)` where the triple is a valid input to // `Integer::round_to_multiple_of_power_of_2`. pub fn integer_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(Integer, u64, RoundingMode)> { Generator::new( &exhaustive_integer_unsigned_rounding_mode_triple_gen_var_1, &random_integer_unsigned_rounding_mode_triple_gen_var_1, &special_random_integer_unsigned_rounding_mode_triple_gen_var_1, ) } // All `(Integer, T, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `Integer::shr_round`. pub fn integer_unsigned_rounding_mode_triple_gen_var_2() -> Generator<(Integer, T, RoundingMode)> where Integer: Shl, { Generator::new( &exhaustive_integer_unsigned_rounding_mode_triple_gen_var_2, &random_integer_unsigned_rounding_mode_triple_gen_var_2, &special_random_integer_unsigned_rounding_mode_triple_gen_var_2, ) } // vars 3 and 4 are in malachite-float // All `(Integer, T, RoundingMode)` where the `T` is small and unsigned. pub fn integer_unsigned_rounding_mode_triple_gen_var_5() -> Generator<(Integer, T, RoundingMode)> { Generator::new( &exhaustive_integer_unsigned_rounding_mode_triple_gen_var_5, &random_integer_unsigned_rounding_mode_triple_gen_var_5, &special_random_integer_unsigned_rounding_mode_triple_gen_var_5, ) } // -- (Integer, RoundingMode) -- pub fn integer_rounding_mode_pair_gen() -> Generator<(Integer, RoundingMode)> { Generator::new( &exhaustive_integer_rounding_mode_pair_gen, &random_integer_rounding_mode_pair_gen, &special_random_integer_rounding_mode_pair_gen, ) } // All `(Integer, RoundingMode)` pairs that are valid inputs to `T::rounding_from`. pub fn integer_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat, >() -> Generator<(Integer, RoundingMode)> { Generator::new( &exhaustive_integer_rounding_mode_pair_gen_var_1::, &random_integer_rounding_mode_pair_gen_var_1::, &special_random_integer_rounding_mode_pair_gen_var_1::, ) } // All `(Integer, RoundingMode)` pairs where the `Integer` is nonzero. pub fn integer_rounding_mode_pair_gen_var_2() -> Generator<(Integer, RoundingMode)> { Generator::new( &exhaustive_integer_rounding_mode_pair_gen_var_2, &random_integer_rounding_mode_pair_gen_var_2, &special_random_integer_rounding_mode_pair_gen_var_2, ) } // -- (Integer, ToSciOptions) -- pub fn integer_to_sci_options_pair_gen() -> Generator<(Integer, ToSciOptions)> { Generator::new( &exhaustive_integer_to_sci_options_pair_gen, &random_integer_to_sci_options_pair_gen, &special_random_integer_to_sci_options_pair_gen, ) } // All `(Integer, ToSciOptions)` pairs where the `Integer` can be formatted using the options. pub fn integer_to_sci_options_pair_gen_var_1() -> Generator<(Integer, ToSciOptions)> { Generator::new( &exhaustive_integer_to_sci_options_pair_gen_var_1, &random_integer_to_sci_options_pair_gen_var_1, &special_random_integer_to_sci_options_pair_gen_var_1, ) } // -- (Integer, Vec) -- // All `(Integer, Vec)` pairs where the length of the `Vec` is the twos' complement limb count // of the `Integer`, including sign extension limbs if necessary. pub fn integer_bool_vec_pair_gen_var_1() -> Generator<(Integer, Vec)> { Generator::new( &exhaustive_integer_bool_vec_pair_gen_var_1, &random_integer_bool_vec_pair_gen_var_1, &special_random_integer_bool_vec_pair_gen_var_1, ) } // All `(Integer, Vec)` pairs where the length of the `Vec` is the twos' complement bit count // of the `Integer`, including sign extension bits if necessary. pub fn integer_bool_vec_pair_gen_var_2() -> Generator<(Integer, Vec)> { Generator::new( &exhaustive_integer_bool_vec_pair_gen_var_2, &random_integer_bool_vec_pair_gen_var_2, &special_random_integer_bool_vec_pair_gen_var_2, ) } // -- Natural -- pub fn natural_gen() -> Generator { Generator::new( &exhaustive_natural_gen, &random_natural_gen, &special_random_natural_gen, ) } pub fn natural_gen_rm() -> Generator<(rug::Integer, Natural)> { Generator::new( &|| natural_rm(exhaustive_natural_gen()), &|config| natural_rm(random_natural_gen(config)), &|config| natural_rm(special_random_natural_gen(config)), ) } pub fn natural_gen_nrm() -> Generator<(BigUint, rug::Integer, Natural)> { Generator::new( &|| natural_nrm(exhaustive_natural_gen()), &|config| natural_nrm(random_natural_gen(config)), &|config| natural_nrm(special_random_natural_gen(config)), ) } // All `Natural`s greater than or equal to 2. pub fn natural_gen_var_1() -> Generator { Generator::new( &exhaustive_natural_gen_var_1, &random_natural_gen_var_1, &special_random_natural_gen_var_6, ) } // All positive `Natural`s. pub fn natural_gen_var_2() -> Generator { Generator::new( &exhaustive_natural_gen_var_2, &random_natural_gen_var_2, &special_random_natural_gen_var_1, ) } // All `Natural`s that are exactly equal to a floating point value of type `T`. pub fn natural_gen_var_3() -> Generator where Natural: TryFrom, { Generator::new( &exhaustive_natural_gen_var_3::, &random_natural_gen_var_3::, &special_random_natural_gen_var_2::, ) } // All `Natural`s that are not equal to any floating point value of type `T`. pub fn natural_gen_var_4 ConvertibleFrom<&'a Natural> + PrimitiveFloat>() -> Generator { Generator::new( &exhaustive_natural_gen_var_4::, &random_natural_gen_var_4::, &special_random_natural_gen_var_7::, ) } type GN = Generator; // All `Natural`s that are exactly between two adjacent floats of type `T`. pub fn natural_gen_var_5 ExactFrom<&'a Natural> + PrimitiveFloat>() -> GN where Natural: TryFrom, { Generator::new( &exhaustive_natural_gen_var_5::, &random_natural_gen_var_5::, &special_random_natural_gen_var_3::, ) } // All `Natural`s that are exactly equal to an unsigned value of type `T`. pub fn natural_gen_var_6() -> Generator where Natural: From, { Generator::new( &exhaustive_natural_gen_var_6::, &random_natural_gen_var_6::, &special_random_natural_gen_var_4::, ) } // All `Natural`s that are exactly equal to a signed value of type `T`. pub fn natural_gen_var_7() -> Generator where Natural: ExactFrom, { Generator::new( &exhaustive_natural_gen_var_7::, &random_natural_gen_var_7::, &special_random_natural_gen_var_5::, ) } // All odd `Natural`s. pub fn natural_gen_var_8() -> Generator { Generator::new( &exhaustive_natural_gen_var_8, &random_natural_gen_var_8, &special_random_natural_gen_var_8, ) } // All small `Natural`s. pub fn natural_gen_var_9() -> Generator { Generator::new_no_special(&exhaustive_natural_gen, &random_natural_gen_var_9) } // -- (Natural, bool) -- pub fn natural_bool_pair_gen() -> Generator<(Natural, bool)> { Generator::new( &exhaustive_natural_bool_pair_gen, &random_natural_bool_pair_gen, &special_random_natural_bool_pair_gen, ) } // -- (Natural, Integer, Natural) -- pub fn natural_integer_natural_triple_gen() -> Generator<(Natural, Integer, Natural)> { Generator::new( &exhaustive_natural_integer_natural_triple_gen, &random_natural_integer_natural_triple_gen, &special_random_natural_integer_natural_triple_gen, ) } // -- (Natural, Natural) -- pub fn natural_pair_gen() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen, &random_natural_pair_gen, &special_random_natural_pair_gen, ) } #[allow(clippy::type_complexity)] pub fn natural_pair_gen_nrm() -> Generator<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Generator::new( &|| natural_pair_nrm(exhaustive_natural_pair_gen()), &|config| natural_pair_nrm(random_natural_pair_gen(config)), &|config| natural_pair_nrm(special_random_natural_pair_gen(config)), ) } pub fn natural_pair_gen_rm() -> Generator<((rug::Integer, rug::Integer), (Natural, Natural))> { Generator::new( &|| natural_pair_rm(exhaustive_natural_pair_gen()), &|config| natural_pair_rm(random_natural_pair_gen(config)), &|config| natural_pair_rm(special_random_natural_pair_gen(config)), ) } pub fn natural_pair_gen_nm() -> Generator<((BigUint, BigUint), (Natural, Natural))> { Generator::new( &|| natural_pair_nm(exhaustive_natural_pair_gen()), &|config| natural_pair_nm(random_natural_pair_gen(config)), &|config| natural_pair_nm(special_random_natural_pair_gen(config)), ) } // All pairs of `Natural`s where the first `Natural` is large (at least 2^`Limb::WIDTH`) and the // second is at least 2. pub fn natural_pair_gen_var_1() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_1, &random_natural_pair_gen_var_1, &special_random_natural_pair_gen_var_10, ) } // All pairs of `Natural`s where the second `Natural` is at least 2. pub fn natural_pair_gen_var_2() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_2, &random_natural_pair_gen_var_2, &special_random_natural_pair_gen_var_1, ) } // All pairs of `Natural`s where the first `Natural` is positive and the second is at least 2. pub fn natural_pair_gen_var_3() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_3, &random_natural_pair_gen_var_3, &special_random_natural_pair_gen_var_2, ) } // All pairs of `Natural`s that tend to have large GCDs. pub fn natural_pair_gen_var_4() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_4, &random_natural_pair_gen_var_4, &special_random_natural_pair_gen_var_3, ) } #[allow(clippy::type_complexity)] pub fn natural_pair_gen_var_4_nrm() -> Generator<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Generator::new( &|| natural_pair_nrm(exhaustive_natural_pair_gen_var_4()), &|config| natural_pair_nrm(random_natural_pair_gen_var_4(config)), &|config| natural_pair_nrm(special_random_natural_pair_gen_var_3(config)), ) } // All pairs of `Natural`s where the second `Natural` is positive. pub fn natural_pair_gen_var_5() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_5, &random_natural_pair_gen_var_5, &special_random_natural_pair_gen_var_4, ) } pub fn natural_pair_gen_var_5_rm() -> Generator<((rug::Integer, rug::Integer), (Natural, Natural))> { Generator::new( &|| natural_pair_rm(exhaustive_natural_pair_gen_var_5()), &|config| natural_pair_rm(random_natural_pair_gen_var_5(config)), &|config| natural_pair_rm(special_random_natural_pair_gen_var_4(config)), ) } #[allow(clippy::type_complexity)] pub fn natural_pair_gen_var_5_nrm() -> Generator<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Generator::new( &|| natural_pair_nrm(exhaustive_natural_pair_gen_var_5()), &|config| natural_pair_nrm(random_natural_pair_gen_var_5(config)), &|config| natural_pair_nrm(special_random_natural_pair_gen_var_4(config)), ) } // All pairs of `Natural`s where the first `Natural` is divisible by the second, and the second is // positive. pub fn natural_pair_gen_var_6() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_6, &random_natural_pair_gen_var_6, &special_random_natural_pair_gen_var_5, ) } #[allow(clippy::type_complexity)] pub fn natural_pair_gen_var_6_nrm() -> Generator<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Generator::new( &|| natural_pair_nrm(exhaustive_natural_pair_gen_var_6()), &|config| natural_pair_nrm(random_natural_pair_gen_var_6(config)), &|config| natural_pair_nrm(special_random_natural_pair_gen_var_5(config)), ) } // All pairs of `Natural`s where the first `Natural` is not divisible by the second, and the second // is positive. pub fn natural_pair_gen_var_7() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_7, &random_natural_pair_gen_var_7, &special_random_natural_pair_gen_var_6, ) } // All pairs of `Natural`s where the first is smaller than the second. pub fn natural_pair_gen_var_8() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_8, &random_natural_pair_gen_var_8, &special_random_natural_pair_gen_var_7, ) } // All pairs of positive `Natural`s. pub fn natural_pair_gen_var_9() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_9, &random_natural_pair_gen_var_9, &special_random_natural_pair_gen_var_8, ) } // All pairs of `Natural`s where the first is greater than or equal to the second. pub fn natural_pair_gen_var_10() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_10, &random_natural_pair_gen_var_10, &special_random_natural_pair_gen_var_9, ) } pub fn natural_pair_gen_var_10_rm() -> Generator<((rug::Integer, rug::Integer), (Natural, Natural))> { Generator::new( &|| natural_pair_rm(exhaustive_natural_pair_gen_var_10()), &|config| natural_pair_rm(random_natural_pair_gen_var_10(config)), &|config| natural_pair_rm(special_random_natural_pair_gen_var_9(config)), ) } pub fn natural_pair_gen_var_10_nrm() -> Generator<( (BigUint, BigUint), (rug::Integer, rug::Integer), (Natural, Natural), )> { Generator::new( &|| natural_pair_nrm(exhaustive_natural_pair_gen_var_10()), &|config| natural_pair_nrm(random_natural_pair_gen_var_10(config)), &|config| natural_pair_nrm(special_random_natural_pair_gen_var_9(config)), ) } // All pairs of positive `Natural`s where the first is smaller than the second. pub fn natural_pair_gen_var_11() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_11, &random_natural_pair_gen_var_11, &special_random_natural_pair_gen_var_11, ) } // All pairs of `Natural`s where the second `Natural` is odd. pub fn natural_pair_gen_var_12() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_12, &random_natural_pair_gen_var_12, &special_random_natural_pair_gen_var_12, ) } pub fn natural_pair_gen_var_12_rm() -> Generator<((rug::Integer, rug::Integer), (Natural, Natural))> { Generator::new( &|| natural_pair_rm(exhaustive_natural_pair_gen_var_12()), &|config| natural_pair_rm(random_natural_pair_gen_var_12(config)), &|config| natural_pair_rm(special_random_natural_pair_gen_var_12(config)), ) } // All coprime pairs of odd `Natural`s. pub fn natural_pair_gen_var_13() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_13, &random_natural_pair_gen_var_13, &special_random_natural_pair_gen_var_13, ) } // All coprime pairs of `Natural`s. pub fn natural_pair_gen_var_14() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_14, &random_natural_pair_gen_var_14, &special_random_natural_pair_gen_var_14, ) } // All pairs of `Natural`s where the second `Natural` is small. pub fn natural_pair_gen_var_15() -> Generator<(Natural, Natural)> { Generator::new( &exhaustive_natural_pair_gen_var_15, &random_natural_pair_gen_var_15, &special_random_natural_pair_gen_var_15, ) } pub fn natural_pair_gen_var_15_rm() -> Generator<((rug::Integer, u32), (Natural, Natural))> { Generator::new( &|| { Box::new( exhaustive_natural_pair_gen_var_15() .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, &|config| { Box::new( random_natural_pair_gen_var_15(config) .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, &|config| { Box::new( special_random_natural_pair_gen_var_15(config) .map(|(x, y)| ((rug::Integer::from(&x), u32::exact_from(&y)), (x, y))), ) }, ) } // -- (Natural, Natural, bool) -- // All `(Natural, Natural, bool)` where the second `Natural` is positive. pub fn natural_natural_bool_triple_gen_var_1() -> Generator<(Natural, Natural, bool)> { Generator::new( &exhaustive_natural_natural_bool_triple_gen_var_1, &random_natural_natural_bool_triple_gen_var_1, &special_random_natural_natural_bool_triple_gen_var_1, ) } // -- (Natural, Natural, Natural) -- pub fn natural_triple_gen() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen, &random_natural_triple_gen, &special_random_natural_triple_gen, ) } #[allow(clippy::type_complexity)] pub fn natural_triple_gen_rm() -> Generator<( (rug::Integer, rug::Integer, rug::Integer), (Natural, Natural, Natural), )> { Generator::new( &|| natural_triple_rm(exhaustive_natural_triple_gen()), &|config| natural_triple_rm(random_natural_triple_gen(config)), &|config| natural_triple_rm(special_random_natural_triple_gen(config)), ) } // All triples of `Natural` where the first is equal to the second mod the third. pub fn natural_triple_gen_var_1() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_1, &random_natural_triple_gen_var_1, &special_random_natural_triple_gen_var_1, ) } // All triples of `Natural` where the first is not equal to the second mod the third. pub fn natural_triple_gen_var_2() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_2, &random_natural_triple_gen_var_2, &special_random_natural_triple_gen_var_2, ) } // All triples of `Natural` where the first and second elements each are less than the third. pub fn natural_triple_gen_var_3() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_3, &random_natural_triple_gen_var_3, &special_random_natural_triple_gen_var_3, ) } // All triples of `Natural` where the third `Natural` is positive. pub fn natural_triple_gen_var_4() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_4, &random_natural_triple_gen_var_4, &special_random_natural_triple_gen_var_4, ) } // All triples of `Natural` where the first element is less than the third. pub fn natural_triple_gen_var_5() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_5, &random_natural_triple_gen_var_5, &special_random_natural_triple_gen_var_5, ) } #[allow(clippy::type_complexity)] pub fn natural_triple_gen_var_5_nrm() -> Generator<( (BigUint, BigUint, BigUint), (rug::Integer, rug::Integer, rug::Integer), (Natural, Natural, Natural), )> { Generator::new( &|| natural_triple_nrm(exhaustive_natural_triple_gen_var_5()), &|config| natural_triple_nrm(random_natural_triple_gen_var_5(config)), &|config| natural_triple_nrm(special_random_natural_triple_gen_var_5(config)), ) } // All triples of positive `Natural`s. pub fn natural_triple_gen_var_6() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_6, &random_natural_triple_gen_var_6, &special_random_natural_triple_gen_var_6, ) } // All triples of `Natural`s where the first is greater than or equal to the product of the second // and third. pub fn natural_triple_gen_var_7() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_7, &random_natural_triple_gen_var_7, &special_random_natural_triple_gen_var_7, ) } // All triples of `Natural`s where the third `Natural` is odd. pub fn natural_triple_gen_var_8() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_8, &random_natural_triple_gen_var_8, &special_random_natural_triple_gen_var_8, ) } // All triples of `Natural`s where the second and third `Natural`s are odd. pub fn natural_triple_gen_var_9() -> Generator<(Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_triple_gen_var_9, &random_natural_triple_gen_var_9, &special_random_natural_triple_gen_var_9, ) } // -- (Natural, Natural, Natural, Natural) -- // All quadruples of `Natural` where the first three elements are each less than the fourth. pub fn natural_quadruple_gen_var_1() -> Generator<(Natural, Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_quadruple_gen_var_1, &random_natural_quadruple_gen_var_1, &special_random_natural_quadruple_gen_var_1, ) } // All quadruples of `Natural` where the first two elements are each smaller than the fourth. pub fn natural_quadruple_gen_var_2() -> Generator<(Natural, Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_quadruple_gen_var_2, &random_natural_quadruple_gen_var_2, &special_random_natural_quadruple_gen_var_2, ) } // All quadruples of `Natural` where the first element is less than the fourth. pub fn natural_quadruple_gen_var_3() -> Generator<(Natural, Natural, Natural, Natural)> { Generator::new( &exhaustive_natural_quadruple_gen_var_3, &random_natural_quadruple_gen_var_3, &special_random_natural_quadruple_gen_var_3, ) } // -- (Natural, Natural, Natural, PrimitiveUnsigned) -- // All `(Natural, Natural, Natural, T)` where `T` is unsigned and small. pub fn natural_natural_natural_unsigned_quadruple_gen_var_1() -> Generator<(Natural, Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_1, &random_natural_natural_natural_unsigned_quadruple_gen_var_1, &special_random_natural_natural_natural_unsigned_quadruple_gen_var_1, ) } // All `(Natural, Natural, Natural, u64)` where all `Natural`s are less than 2 to the power of the // `u64`. pub fn natural_natural_natural_unsigned_quadruple_gen_var_2() -> Generator<(Natural, Natural, Natural, u64)> { Generator::new( &exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_2, &random_natural_natural_natural_unsigned_quadruple_gen_var_2, &special_random_natural_natural_natural_unsigned_quadruple_gen_var_2, ) } // All `(Natural, Natural, Natural, u64)` where the first two `Natural`s are less than 2 to the // power of the `u64`. pub fn natural_natural_natural_unsigned_quadruple_gen_var_3() -> Generator<(Natural, Natural, Natural, u64)> { Generator::new( &exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_3, &random_natural_natural_natural_unsigned_quadruple_gen_var_3, &special_random_natural_natural_natural_unsigned_quadruple_gen_var_3, ) } // All `(Natural, Natural, Natural, u64)` where the first `Natural` is less than 2 to the power of // the `u64`. pub fn natural_natural_natural_unsigned_quadruple_gen_var_4() -> Generator<(Natural, Natural, Natural, u64)> { Generator::new( &exhaustive_natural_natural_natural_unsigned_quadruple_gen_var_4, &random_natural_natural_natural_unsigned_quadruple_gen_var_4, &special_random_natural_natural_natural_unsigned_quadruple_gen_var_4, ) } // -- (Natural, Natural, PrimitiveFloat) -- pub fn natural_natural_primitive_float_triple_gen() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_primitive_float_triple_gen, &random_natural_natural_primitive_float_triple_gen, &special_random_natural_natural_primitive_float_triple_gen, ) } // -- (Natural, Natural, PrimitiveSigned) -- pub fn natural_natural_signed_triple_gen() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_signed_triple_gen, &random_natural_natural_primitive_int_triple_gen, &special_random_natural_natural_signed_triple_gen, ) } // All `(Natural, Natural, T)` where the `T` is signed and small, and the first `Natural` is smaller // than the second. pub fn natural_natural_signed_triple_gen_var_1() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_signed_triple_gen_var_1, &random_natural_natural_signed_triple_gen_var_1, &special_random_natural_natural_signed_triple_gen_var_1, ) } // -- (Natural, Natural, PrimitiveUnsigned) -- pub fn natural_natural_unsigned_triple_gen() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen, &random_natural_natural_primitive_int_triple_gen, &special_random_natural_natural_unsigned_triple_gen, ) } // All `(Natural, Natural, T)` where `T` is unsigned and small. pub fn natural_natural_unsigned_triple_gen_var_1() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_1, &random_natural_natural_unsigned_triple_gen_var_1, &special_random_natural_natural_unsigned_triple_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn natural_natural_unsigned_triple_gen_var_1_rm() -> Generator<((rug::Integer, rug::Integer, T), (Natural, Natural, T))> { Generator::new( &|| natural_natural_triple_1_2_rm(exhaustive_natural_natural_unsigned_triple_gen_var_1()), &|config| { natural_natural_triple_1_2_rm(random_natural_natural_unsigned_triple_gen_var_1(config)) }, &|config| { natural_natural_triple_1_2_rm(special_random_natural_natural_unsigned_triple_gen_var_1( config, )) }, ) } // All `(Natural, Natural, T)` where `T` is unsigned and small, and the `Natural`s are equal mod 2 // to the power of the `T`. pub fn natural_natural_unsigned_triple_gen_var_2() -> Generator<(Natural, Natural, T)> where Natural: Shl, { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_2, &random_natural_natural_unsigned_triple_gen_var_2, &special_random_natural_natural_unsigned_triple_gen_var_2, ) } // All `(Natural, Natural, T)` where `T` is unsigned and small, and the `Natural`s are not equal mod // 2 to the power of the `T`. pub fn natural_natural_unsigned_triple_gen_var_3() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_3, &random_natural_natural_unsigned_triple_gen_var_3, &special_random_natural_natural_unsigned_triple_gen_var_3, ) } // All `(Natural, Natural, u64)` where both `Natural`s are less than 2 to the power of the `u64`. pub fn natural_natural_unsigned_triple_gen_var_4() -> Generator<(Natural, Natural, u64)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_4, &random_natural_natural_unsigned_triple_gen_var_4, &special_random_natural_natural_unsigned_triple_gen_var_4, ) } // All `(Natural, Natural, u64)` where the first `Natural` is less than 2 to the power of the `u64`. pub fn natural_natural_unsigned_triple_gen_var_5() -> Generator<(Natural, Natural, u64)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_5, &random_natural_natural_unsigned_triple_gen_var_5, &special_random_natural_natural_unsigned_triple_gen_var_5, ) } // All `(Natural, Natural, T)` where the `T` is unsigned and small, and the first `Natural` is // smaller than the second. pub fn natural_natural_unsigned_triple_gen_var_6() -> Generator<(Natural, Natural, T)> { Generator::new( &exhaustive_natural_natural_unsigned_triple_gen_var_6, &random_natural_natural_unsigned_triple_gen_var_6, &special_random_natural_natural_unsigned_triple_gen_var_6, ) } // -- (Natural, Natural, RoundingMode) -- // All `(Natural, Natural, RoundingMode)` triples where the second `Natural` is positive and if the // `RoundingMode` is `Exact`, the first `Natural` is divisible by the second. pub fn natural_natural_rounding_mode_triple_gen_var_1() -> Generator<(Natural, Natural, RoundingMode)> { Generator::new( &exhaustive_natural_natural_rounding_mode_triple_gen_var_1, &random_natural_natural_rounding_mode_triple_gen_var_1, &special_random_natural_natural_rounding_mode_triple_gen_var_1, ) } // All `(Natural, Natural, RoundingMode)` triples that are a valid input to // `Natural::round_to_multiple`. pub fn natural_natural_rounding_mode_triple_gen_var_2() -> Generator<(Natural, Natural, RoundingMode)> { Generator::new( &exhaustive_natural_natural_rounding_mode_triple_gen_var_2, &random_natural_natural_rounding_mode_triple_gen_var_2, &special_random_natural_natural_rounding_mode_triple_gen_var_2, ) } // -- (Natural, PrimitiveFloat) -- pub fn natural_primitive_float_pair_gen() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_primitive_float_pair_gen, &random_natural_primitive_float_pair_gen, &special_random_natural_primitive_float_pair_gen, ) } pub fn natural_primitive_float_pair_gen_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_primitive_float_pair_gen()), &|config| natural_pair_1_rm(random_natural_primitive_float_pair_gen(config)), &|config| natural_pair_1_rm(special_random_natural_primitive_float_pair_gen(config)), ) } // -- (Natural, PrimitiveFloat, PrimitiveFloat) -- pub fn natural_primitive_float_primitive_float_triple_gen() -> Generator<(Natural, T, T)> { Generator::new( &exhaustive_natural_primitive_float_primitive_float_triple_gen, &random_natural_primitive_float_primitive_float_triple_gen, &special_random_natural_primitive_float_primitive_float_triple_gen, ) } // -- (Natural, PrimitiveSigned) -- pub fn natural_signed_pair_gen() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_signed_pair_gen, &random_natural_primitive_int_pair_gen, &special_random_natural_signed_pair_gen, ) } pub fn natural_signed_pair_gen_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_signed_pair_gen()), &|config| natural_pair_1_rm(random_natural_primitive_int_pair_gen(config)), &|config| natural_pair_1_rm(special_random_natural_signed_pair_gen(config)), ) } // All pairs of `Natural` and signed `T`, where the `T` is natural (non-negative). pub fn natural_signed_pair_gen_var_1() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_signed_pair_gen_var_1, &random_natural_signed_pair_gen_var_1, &special_random_natural_signed_pair_gen_var_1, ) } // All `(Natural, T)` where `T` is signed and small. pub fn natural_signed_pair_gen_var_2() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_signed_pair_gen_var_2, &random_natural_signed_pair_gen_var_2, &special_random_natural_signed_pair_gen_var_2, ) } pub fn natural_signed_pair_gen_var_2_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_signed_pair_gen_var_2()), &|config| natural_pair_1_rm(random_natural_signed_pair_gen_var_2(config)), &|config| natural_pair_1_rm(special_random_natural_signed_pair_gen_var_2(config)), ) } // All `(Natural, T)` where `T` is signed and the `Natural` is positive. pub fn natural_signed_pair_gen_var_3() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_signed_pair_gen_var_3, &random_natural_primitive_int_pair_gen_var_1, &special_random_natural_signed_pair_gen_var_3, ) } // All `(Natural, T)` where `T` is signed and small, the `Natural` is positive, and the `Natural`s // bit length is a multiple of the limb bit length. pub fn natural_signed_pair_gen_var_4() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_signed_pair_gen_var_4, &random_natural_signed_pair_gen_var_3, &special_random_natural_signed_pair_gen_var_4, ) } // -- (Natural, PrimitiveSigned, PrimitiveSigned) -- pub fn natural_signed_signed_triple_gen() -> Generator<(Natural, T, T)> { Generator::new( &exhaustive_natural_signed_signed_triple_gen, &random_natural_primitive_int_primitive_int_triple_gen, &special_random_natural_signed_signed_triple_gen, ) } // -- (Natural, PrimitiveSigned, PrimitiveUnsigned) -- type T2 = Generator<(Natural, T, u64)>; // All `(Natural, T, u64)` where the `Natural` is less than 2 to the power of the `u64`, and the `T` // is small and signed. pub fn natural_signed_unsigned_triple_gen_var_1() -> T2 { Generator::new( &exhaustive_natural_signed_unsigned_triple_gen_var_1, &random_natural_signed_unsigned_triple_gen_var_1, &special_random_natural_signed_unsigned_triple_gen_var_1, ) } // All `(Natural, T, U)` where `T` is signed and small and `U` is unsigned, small, and positive. pub fn natural_signed_unsigned_triple_gen_var_2() -> Generator<(Natural, T, U)> { Generator::new( &exhaustive_natural_signed_unsigned_triple_gen_var_2, &random_natural_signed_unsigned_triple_gen_var_2, &special_random_natural_signed_unsigned_triple_gen_var_2, ) } // -- (Natural, PrimitiveSigned, RoundingMode) -- // All `(Natural, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Natural::shl_round`. pub fn natural_signed_rounding_mode_triple_gen_var_1() -> Generator<(Natural, T, RoundingMode)> where Natural: Shr, { Generator::new( &exhaustive_natural_signed_rounding_mode_triple_gen_var_1, &random_natural_signed_rounding_mode_triple_gen_var_1, &special_random_natural_signed_rounding_mode_triple_gen_var_1, ) } // All `(Natural, T, RoundingMode)` where `T` is signed and the triple is a valid input to // `Natural::shr_round`. pub fn natural_signed_rounding_mode_triple_gen_var_2() -> Generator<(Natural, T, RoundingMode)> where Natural: Shl, { Generator::new( &exhaustive_natural_signed_rounding_mode_triple_gen_var_2, &random_natural_signed_rounding_mode_triple_gen_var_2, &special_random_natural_signed_rounding_mode_triple_gen_var_2, ) } // -- (Natural, PrimitiveUnsigned) -- pub fn natural_unsigned_pair_gen() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen, &random_natural_primitive_int_pair_gen, &special_random_natural_unsigned_pair_gen, ) } pub fn natural_unsigned_pair_gen_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_unsigned_pair_gen()), &|config| natural_pair_1_rm(random_natural_primitive_int_pair_gen(config)), &|config| natural_pair_1_rm(special_random_natural_unsigned_pair_gen(config)), ) } #[allow(clippy::type_complexity)] pub fn natural_unsigned_pair_gen_nrm() -> Generator<((BigUint, T), (rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_nrm(exhaustive_natural_unsigned_pair_gen()), &|config| natural_pair_1_nrm(random_natural_primitive_int_pair_gen(config)), &|config| natural_pair_1_nrm(special_random_natural_unsigned_pair_gen(config)), ) } // All `(Natural, T)` where `T` is unsigned and the `T` is at least 2 and at most `U::MAX`. pub fn natural_unsigned_pair_gen_var_1< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveInt, >() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_primitive_int_pair_gen_var_1::, &random_natural_unsigned_pair_gen_var_1::, &special_random_natural_unsigned_pair_gen_var_1::, ) } // All `(Natural, T)` where `T` is unsigned and the `T` is at least 2. pub fn natural_unsigned_pair_gen_var_2() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_primitive_int_pair_gen_var_2, &random_natural_unsigned_pair_gen_var_2, &special_random_natural_unsigned_pair_gen_var_2, ) } // All `(Natural, T)` where `T` is unsigned and between 2 and 36, inclusive. pub fn natural_unsigned_pair_gen_var_3() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_1, &random_natural_unsigned_pair_gen_var_3, &special_random_natural_unsigned_pair_gen_var_3, ) } #[allow(clippy::type_complexity)] pub fn natural_unsigned_pair_gen_var_3_nrm() -> Generator<((BigUint, T), (rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_nrm(exhaustive_natural_unsigned_pair_gen_var_1()), &|config| natural_pair_1_nrm(random_natural_unsigned_pair_gen_var_3(config)), &|config| natural_pair_1_nrm(special_random_natural_unsigned_pair_gen_var_3(config)), ) } // All `(Natural, T)` where `T` is unsigned and small. pub fn natural_unsigned_pair_gen_var_4() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_2, &random_natural_unsigned_pair_gen_var_4, &special_random_natural_unsigned_pair_gen_var_4, ) } pub fn natural_unsigned_pair_gen_var_4_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_unsigned_pair_gen_var_2()), &|config| natural_pair_1_rm(random_natural_unsigned_pair_gen_var_4(config)), &|config| natural_pair_1_rm(special_random_natural_unsigned_pair_gen_var_4(config)), ) } pub fn natural_unsigned_pair_gen_var_4_nm() -> Generator<((BigUint, T), (Natural, T))> { Generator::new( &|| natural_pair_1_nm(exhaustive_natural_unsigned_pair_gen_var_2()), &|config| natural_pair_1_nm(random_natural_unsigned_pair_gen_var_4(config)), &|config| natural_pair_1_nm(special_random_natural_unsigned_pair_gen_var_4(config)), ) } #[allow(clippy::type_complexity)] pub fn natural_unsigned_pair_gen_var_4_nrm() -> Generator<((BigUint, T), (rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_nrm(exhaustive_natural_unsigned_pair_gen_var_2()), &|config| natural_pair_1_nrm(random_natural_unsigned_pair_gen_var_4(config)), &|config| natural_pair_1_nrm(special_random_natural_unsigned_pair_gen_var_4(config)), ) } // All `(Natural, T)` where the `Natural` is at least 2 and the `T` is unsigned and small. pub fn natural_unsigned_pair_gen_var_5() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_3, &random_natural_unsigned_pair_gen_var_5, &special_random_natural_unsigned_pair_gen_var_12, ) } // All `(Natural, T)`, where the `T` is between 1 and `T::WIDTH`, inclusive. pub fn natural_unsigned_pair_gen_var_6() -> Generator<(Natural, u64)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_4::, &random_natural_unsigned_pair_gen_var_6::, &special_random_natural_unsigned_pair_gen_var_5::, ) } // All `(Natural, T)` where the `T` is unsigned, positive, and small. pub fn natural_unsigned_pair_gen_var_7() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_primitive_int_pair_gen_var_3, &random_natural_unsigned_pair_gen_var_7, &special_random_natural_unsigned_pair_gen_var_6, ) } pub fn natural_unsigned_pair_gen_var_7_rm() -> Generator<((rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_rm(exhaustive_natural_primitive_int_pair_gen_var_3()), &|config| natural_pair_1_rm(random_natural_unsigned_pair_gen_var_7(config)), &|config| natural_pair_1_rm(special_random_natural_unsigned_pair_gen_var_6(config)), ) } #[allow(clippy::type_complexity)] pub fn natural_unsigned_pair_gen_var_7_nrm() -> Generator<((BigUint, T), (rug::Integer, T), (Natural, T))> { Generator::new( &|| natural_pair_1_nrm(exhaustive_natural_primitive_int_pair_gen_var_3()), &|config| natural_pair_1_nrm(random_natural_unsigned_pair_gen_var_7(config)), &|config| natural_pair_1_nrm(special_random_natural_unsigned_pair_gen_var_6(config)), ) } // All `(Natural, T)` where the `Natural` is positive and the `T` is unsigned, positive, and small. pub fn natural_unsigned_pair_gen_var_8() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_primitive_int_pair_gen_var_4, &random_natural_unsigned_pair_gen_var_8, &special_random_natural_unsigned_pair_gen_var_7, ) } // All `(Natural, u64)`s where the `T` is unsigned and small, and the `Natural` is divisible by 2 to // the power of the `T`. pub fn natural_unsigned_pair_gen_var_9() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_5, &random_natural_unsigned_pair_gen_var_9, &special_random_natural_unsigned_pair_gen_var_8, ) } // All `(Natural, u64)`s where the `T` is unsigned and small, and the `Natural` is not divisible by // 2 to the power of the `T`. pub fn natural_unsigned_pair_gen_var_10() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_6, &random_natural_unsigned_pair_gen_var_10, &special_random_natural_unsigned_pair_gen_var_9, ) } // All `(Natural, u64)` where the `Natural` is less than 2 to the power of the `u64`. pub fn natural_unsigned_pair_gen_var_11() -> Generator<(Natural, u64)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_7, &random_natural_unsigned_pair_gen_var_11, &special_random_natural_unsigned_pair_gen_var_10, ) } // All `(Natural, T)` where the `Natural` is positive and the `T` is unsigned. pub fn natural_unsigned_pair_gen_var_12() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_8, &random_natural_primitive_int_pair_gen_var_1, &special_random_natural_unsigned_pair_gen_var_11, ) } // All `(Natural, T)` where the `Natural` is positive and the `T` is unsigned and small. pub fn natural_unsigned_pair_gen_var_13() -> Generator<(Natural, T)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_9, &random_natural_unsigned_pair_gen_var_12, &special_random_natural_unsigned_pair_gen_var_13, ) } // All `(Natural, u64)` where the `Natural` is nonzero and less than 2 to the power of the `u64`. pub fn natural_unsigned_pair_gen_var_14() -> Generator<(Natural, u64)> { Generator::new( &exhaustive_natural_unsigned_pair_gen_var_10, &random_natural_unsigned_pair_gen_var_13, &special_random_natural_unsigned_pair_gen_var_14, ) } // -- (Natural, PrimitiveUnsigned, bool) -- // All `(Natural, T, bool)` where `T` is unsigned and small. pub fn natural_unsigned_bool_triple_gen_var_1() -> Generator<(Natural, T, bool)> { Generator::new( &exhaustive_natural_unsigned_bool_triple_gen_var_1, &random_natural_unsigned_bool_triple_gen_var_1, &special_random_natural_unsigned_bool_triple_gen_var_1, ) } #[allow(clippy::type_complexity)] pub fn natural_unsigned_bool_triple_gen_var_1_rm() -> Generator<((rug::Integer, T, bool), (Natural, T, bool))> { Generator::new( &|| natural_triple_1_rm(exhaustive_natural_unsigned_bool_triple_gen_var_1()), &|config| natural_triple_1_rm(random_natural_unsigned_bool_triple_gen_var_1(config)), &|config| { natural_triple_1_rm(special_random_natural_unsigned_bool_triple_gen_var_1( config, )) }, ) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn natural_unsigned_unsigned_triple_gen() -> Generator<(Natural, T, T)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen, &random_natural_primitive_int_primitive_int_triple_gen, &special_random_natural_unsigned_unsigned_triple_gen, ) } // All `(Natural, T, U)` where `T` and `U` are unsigned, the `T` is between 2 and 36, inclusive, and // the `U` is small. pub fn natural_unsigned_unsigned_triple_gen_var_1() -> Generator<(Natural, T, U)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen_var_1, &random_natural_unsigned_unsigned_triple_gen_var_1, &special_random_natural_unsigned_unsigned_triple_gen_var_1, ) } // All `(Natural, u64, T)` where `T` is unsigned, `U` is a primitive int, the `u64` is between 1 and // `U::WIDTH`, inclusive, and the `T` is small. pub fn natural_unsigned_unsigned_triple_gen_var_2() -> Generator<(Natural, u64, T)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen_var_2::, &random_natural_unsigned_unsigned_triple_gen_var_2::, &special_random_natural_unsigned_unsigned_triple_gen_var_2::, ) } // All `(Natural, T, U)` where `T` and `U` are unsigned, the `T` and the `U` are small, and the `T` // is positive. pub fn natural_unsigned_unsigned_triple_gen_var_3() -> Generator<(Natural, T, U)> { Generator::new( &exhaustive_natural_primitive_int_unsigned_triple_gen_var_3, &random_natural_unsigned_unsigned_triple_gen_var_3, &special_random_natural_unsigned_unsigned_triple_gen_var_3, ) } // All `(Natural, T, T)` where `T` is unsigned, both `T`s are small, and the first `T` is less than // or equal to the second. pub fn natural_unsigned_unsigned_triple_gen_var_4() -> Generator<(Natural, T, T)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen_var_3, &random_natural_unsigned_unsigned_triple_gen_var_4, &special_random_natural_unsigned_unsigned_triple_gen_var_4, ) } // All `(Natural, T, T)` where `T` is unsigned and both `T`s are small. pub fn natural_unsigned_unsigned_triple_gen_var_5() -> Generator<(Natural, T, T)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen_var_4, &random_natural_unsigned_unsigned_triple_gen_var_5, &special_random_natural_unsigned_unsigned_triple_gen_var_5, ) } // All `(Natural, T, u64)` where the `Natural` is less than 2 to the power of the `u64`, and the `T` // is small and unsigned. pub fn natural_unsigned_unsigned_triple_gen_var_6() -> Generator<(Natural, T, u64)> { Generator::new( &exhaustive_natural_unsigned_unsigned_triple_gen_var_5, &random_natural_unsigned_unsigned_triple_gen_var_6, &special_random_natural_unsigned_unsigned_triple_gen_var_6, ) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- // All `(Natural, T, T, Natural)` where `T` is unsigned and the first `T` is smaller than the // second. pub fn natural_unsigned_unsigned_natural_quadruple_gen_var_1() -> Generator<(Natural, T, T, Natural)> { Generator::new( &exhaustive_natural_unsigned_unsigned_natural_quadruple_gen_var_1, &random_natural_unsigned_unsigned_natural_triple_gen_var_1, &special_random_natural_unsigned_unsigned_natural_quadruple_gen_var_1, ) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- // All `(Natural, T, RoundingMode)` where `T` is unsigned and the triple is a valid input to // `Natural::shr_round`. pub fn natural_unsigned_rounding_mode_triple_gen_var_1() -> Generator<(Natural, T, RoundingMode)> where Natural: Shl, { Generator::new( &exhaustive_natural_unsigned_rounding_mode_triple_gen_var_1, &random_natural_unsigned_rounding_mode_triple_gen_var_1, &special_random_natural_unsigned_rounding_mode_triple_gen_var_1, ) } // var 2 is in malachite-float // -- (Natural, PrimitiveUnsigned, Vec) -- // All `(Natural, u64, Vec)` where the `u64` is small and the `Vec` has as many elements // as the `Natural` has digits when expessed in base 2 to the power of the `u64`. pub fn natural_unsigned_bool_vec_triple_gen_var_1() -> Generator<(Natural, u64, Vec)> { Generator::new( &exhaustive_natural_unsigned_bool_vec_triple_gen_var_1, &random_natural_unsigned_bool_vec_triple_gen_var_1, &special_random_natural_unsigned_bool_vec_triple_gen_var_1, ) } // All `(Natural, u64, Vec)` where the `u64` is between 1 and `T::WIDTH`, inclusive, and the // `Vec` has as many elements as the `Natural` has digits when expessed in base 2 to the power // of the `u64`. pub fn natural_unsigned_bool_vec_triple_gen_var_2() -> Generator<(Natural, u64, Vec)> { Generator::new( &exhaustive_natural_unsigned_bool_vec_triple_gen_var_2::, &random_natural_unsigned_bool_vec_triple_gen_var_2::, &special_random_natural_unsigned_bool_vec_triple_gen_var_2::, ) } // -- (Natural, RoundingMode) -- pub fn natural_rounding_mode_pair_gen() -> Generator<(Natural, RoundingMode)> { Generator::new( &exhaustive_natural_rounding_mode_pair_gen, &random_natural_rounding_mode_pair_gen, &special_random_natural_rounding_mode_pair_gen, ) } // All `(Natural, RoundingMode)` pairs that are valid inputs to `T::rounding_from`. pub fn natural_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >() -> Generator<(Natural, RoundingMode)> { Generator::new( &exhaustive_natural_rounding_mode_pair_gen_var_1::, &random_natural_rounding_mode_pair_gen_var_1::, &special_random_natural_rounding_mode_pair_gen_var_1::, ) } // All `(Natural, RoundingMode)` pairs where the `Natural` is positive. pub fn natural_rounding_mode_pair_gen_var_2() -> Generator<(Natural, RoundingMode)> { Generator::new( &exhaustive_natural_rounding_mode_pair_gen_var_2, &random_natural_rounding_mode_pair_gen_var_2, &special_random_natural_rounding_mode_pair_gen_var_2, ) } // -- (Natural, ToSciOptions) -- pub fn natural_to_sci_options_pair_gen() -> Generator<(Natural, ToSciOptions)> { Generator::new( &exhaustive_natural_to_sci_options_pair_gen, &random_natural_to_sci_options_pair_gen, &special_random_natural_to_sci_options_pair_gen, ) } // All `(Natural, ToSciOptions)` pairs where the `Natural` can be formatted using the options. pub fn natural_to_sci_options_pair_gen_var_1() -> Generator<(Natural, ToSciOptions)> { Generator::new( &exhaustive_natural_to_sci_options_pair_gen_var_1, &random_natural_to_sci_options_pair_gen_var_1, &special_random_natural_to_sci_options_pair_gen_var_1, ) } // -- (Natural, Vec) -- // All `(Natural, Vec)` pairs where the length of the `Vec` is the number of limbs of the // `Natural`. pub fn natural_bool_vec_pair_gen_var_1() -> Generator<(Natural, Vec)> { Generator::new( &exhaustive_natural_bool_vec_pair_gen_var_1, &random_natural_bool_vec_pair_gen_var_1, &special_random_natural_bool_vec_pair_gen_var_1, ) } // All `(Natural, Vec)` pairs where the length of the `Vec` is the number of significant bits // of the `Natural`. pub fn natural_bool_vec_pair_gen_var_2() -> Generator<(Natural, Vec)> { Generator::new( &exhaustive_natural_bool_vec_pair_gen_var_2, &random_natural_bool_vec_pair_gen_var_2, &special_random_natural_bool_vec_pair_gen_var_2, ) } // -- (PrimitiveUnsigned, bool) -- #[allow(clippy::redundant_comparisons)] pub(crate) const fn limbs_odd_factorial_valid(n: usize, b: bool) -> bool { !b || n > ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 && n >= FAC_DSC_THRESHOLD } // All `(T, u63>)` that are valid arguments to `limbs_odd_factorial`. pub fn unsigned_bool_pair_gen_var_1() -> Generator<(usize, bool)> { Generator::new_no_special( &exhaustive_unsigned_bool_pair_gen_var_1, &random_unsigned_bool_pair_gen_var_1, ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 44 are in malachite-base // All `(T, T)` where `T` is unsigned, both `T`s are small, the first `T` is greater than or equal // to the second, and both are greater than `ODD_FACTORIAL_TABLE_LIMIT`. pub fn unsigned_pair_gen_var_45() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_32, &random_unsigned_pair_gen_var_33, ) } // All `(T, T)` where `T` is unsigned, both `T`s are small, the first `T` is greater than or equal // to the second, and the second is at least 2 and no greater than `ODD_FACTORIAL_TABLE_LIMIT`. pub fn unsigned_pair_gen_var_46() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_33, &random_unsigned_pair_gen_var_34, ) } // All `(T, T)` where `T` is unsigned, both `T`s are small, the first `T` is at least 2 more than // the second, the second is at least 2, and the first is no greater than // `ODD_FACTORIAL_EXTTABLE_LIMIT`. pub fn unsigned_pair_gen_var_47() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_34, &random_unsigned_pair_gen_var_35, ) } // All `(T, T)` where `T` is unsigned, both `T`s are small, the first `T` is greater than or equal // to the second, and both are greater than `ODD_FACTORIAL_TABLE_LIMIT`. pub fn unsigned_pair_gen_var_48() -> Generator<(T, T)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_35, &random_unsigned_pair_gen_var_36, ) } // All `(Limb, Limb)` that are valid inputs to `limbs_binomial_coefficient_limb_limb_goetgheluck`. pub fn unsigned_pair_gen_var_49() -> Generator<(Limb, Limb)> { Generator::new_no_special( &exhaustive_unsigned_pair_gen_var_36, &random_unsigned_pair_gen_var_37, ) } // var 50 is in malachite-base // -- (PrimitiveUnsigned * 6) -- // var 2 is in malachite-base. // All sextuples of unsigneds that are valid inputs to `limbs_div_mod_three_limb_by_two_limb`. pub fn unsigned_sextuple_gen_var_2() -> Generator<(Limb, Limb, Limb, Limb, Limb, Limb)> { Generator::new( &exhaustive_unsigned_sextuple_gen_var_2, &random_unsigned_sextuple_gen_var_1, &special_random_unsigned_sextuple_gen_var_2, ) } // -- (String, String, String) -- // All triples of `String`s corresponding to the serialization of a `num::BigUint`, a // `rug::Integer`, and a `Natural`, respectively, into a string. The three numbers have the same // value. pub fn string_triple_gen_var_1() -> Generator<(String, String, String)> { Generator::new( &exhaustive_string_triple_gen_var_1, &random_string_triple_gen_var_1, &special_random_string_triple_gen_var_1, ) } // All triples of `String`s corresponding to the serialization of a `num::BigInt`, a `rug::Integer`, // and an `Integer`, respectively, into a string. The three numbers have the same value. pub fn string_triple_gen_var_2() -> Generator<(String, String, String)> { Generator::new( &exhaustive_string_triple_gen_var_2, &random_string_triple_gen_var_2, &special_random_string_triple_gen_var_2, ) } // var 3 is in malachite-q. // -- Vec -- pub fn integer_vec_gen() -> Generator> { Generator::new( &exhaustive_integer_vec_gen, &random_integer_vec_gen, &special_random_integer_vec_gen, ) } pub fn integer_vec_gen_nrm() -> Generator<(Vec, Vec, Vec)> { Generator::new( &|| integer_vec_nrm(exhaustive_integer_vec_gen()), &|config| integer_vec_nrm(random_integer_vec_gen(config)), &|config| integer_vec_nrm(special_random_integer_vec_gen(config)), ) } // -- Vec -- pub fn natural_vec_gen() -> Generator> { Generator::new( &exhaustive_natural_vec_gen, &random_natural_vec_gen, &special_random_natural_vec_gen, ) } pub fn natural_vec_gen_nrm() -> Generator<(Vec, Vec, Vec)> { Generator::new( &|| natural_vec_nrm(exhaustive_natural_vec_gen()), &|config| natural_vec_nrm(random_natural_vec_gen(config)), &|config| natural_vec_nrm(special_random_natural_vec_gen(config)), ) } // -- (Vec, Integer) -- // All `(Vec, Integer)` where the `Natural`s are positive. pub fn natural_vec_integer_pair_gen_var_1() -> Generator<(Vec, Integer)> { Generator::new( &exhaustive_natural_vec_integer_pair_gen_var_1, &random_natural_vec_integer_pair_gen_var_1, &special_random_natural_vec_integer_pair_gen_var_1, ) } // -- (Vec, Natural) -- // All `(Vec, Natural)` where the second element of the pair is `Large` and every element // of the `Vec` is smaller than that second element. pub fn natural_vec_natural_pair_gen_var_1() -> Generator<(Vec, Natural)> { Generator::new( &exhaustive_natural_vec_natural_pair_gen_var_1, &random_natural_vec_natural_pair_gen_var_1, &special_random_natural_vec_natural_pair_gen_var_3, ) } // All `(Vec, Natural)` where the second element of the pair is at least 2, and every // element of the `Vec` is smaller than the second element of the pair. pub fn natural_vec_natural_pair_gen_var_2() -> Generator<(Vec, Natural)> { Generator::new( &exhaustive_natural_vec_natural_pair_gen_var_2, &random_natural_vec_natural_pair_gen_var_2, &striped_random_natural_vec_natural_pair_gen_var_4, ) } // All `(Vec, Natural)` where the second element of the pair is `Large`. pub fn natural_vec_natural_pair_gen_var_3() -> Generator<(Vec, Natural)> { Generator::new( &exhaustive_natural_vec_natural_pair_gen_var_3, &random_natural_vec_natural_pair_gen_var_3, &special_random_natural_vec_natural_pair_gen_var_1, ) } // All `(Vec, Natural)` where the second element of the pair is at least 2. pub fn natural_vec_natural_pair_gen_var_4() -> Generator<(Vec, Natural)> { Generator::new( &exhaustive_natural_vec_natural_pair_gen_var_4, &random_natural_vec_natural_pair_gen_var_4, &special_random_natural_vec_natural_pair_gen_var_2, ) } // -- (Vec, PrimitiveUnsigned) -- // All `(Vec, u64)`, where the `u64` is positive and each `Natural` in the `Vec` is less // than 2 to the power of the `u64`. pub fn natural_vec_unsigned_pair_gen_var_1() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_natural_vec_unsigned_pair_gen_var_1, &random_natural_vec_unsigned_pair_gen_var_1, &special_random_natural_vec_unsigned_pair_gen_var_1, ) } // All `(Vec, T)`, where the `T` is small and positive. pub fn natural_vec_unsigned_pair_gen_var_2() -> Generator<(Vec, T)> { Generator::new( &exhaustive_natural_vec_primitive_int_pair_gen_var_1, &random_natural_vec_unsigned_pair_gen_var_2, &special_random_natural_vec_unsigned_pair_gen_var_2, ) } // -- Vec -- // vars 1 through 4 are in malachite-base. // All `Vec` that are nonempty and represent a `Natural` divisible by 3. pub fn unsigned_vec_gen_var_5() -> Generator> { Generator::new( &exhaustive_unsigned_vec_gen_var_5, &random_unsigned_vec_gen_var_1, &special_random_unsigned_vec_gen_var_5, ) } // var 6 is in malachite-base. // -- (Vec, PrimitiveUnsigned) -- // vars 1 through 3 are in malachite-base // All `(Vec, T>)` where `T` is unsigned, the `Vec` has at least two elements, and the `T` is // greater than 1 and exactly convertible to the unsigned type `U`. pub fn unsigned_vec_unsigned_pair_gen_var_4< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, >() -> Generator<(Vec, T)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_4::, &random_unsigned_vec_unsigned_pair_gen_var_8::, &special_random_unsigned_vec_unsigned_pair_gen_var_4::, ) } // vars 5 through 20 are in malachite-base // All `(Vec, u64)` where the `u64` is small and `limbs_slice_clear_bit_neg` applied to the // `Vec` and `u64` doesn't panic. pub fn unsigned_vec_unsigned_pair_gen_var_21() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_18, &random_unsigned_vec_unsigned_pair_gen_var_9, &special_random_unsigned_vec_unsigned_pair_gen_var_18, ) } // vars 22 through 28 are in malachite-base. // All `(Vec, Limb)` where the `Vec` is nonempty and represents a `Natural` divisible by the // `Limb`, and the `Limb` is positive. pub fn unsigned_vec_unsigned_pair_gen_var_29() -> Generator<(Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_19, &random_unsigned_vec_unsigned_pair_gen_var_10, &special_random_unsigned_vec_unsigned_pair_gen_var_26, ) } // All `(Vec, u64)` where the `u64` is small, the `Vec` ends with a nonzero element, and the // number of significant bits of the `Vec` is less than or equal to the `u64`. pub fn unsigned_vec_unsigned_pair_gen_var_30() -> Generator<(Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_pair_gen_var_20, &random_unsigned_vec_unsigned_pair_gen_var_11, &special_random_unsigned_vec_unsigned_pair_gen_var_27, ) } // vars 31 through 32 are in malachite-base. // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 5 are in malachite-base // All `(Vec, Limb, Limb)`s where both `Limb`s are positive, the `Vec` contains at least two // elements, its last element is nonzero, and the first `Limb` is not equal to the second `Limb` mod // the `Natural` represented by the `Vec`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_6() -> Generator<(Vec, Limb, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_6, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_1, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_6, ) } // vars 7 through 8 are in malachite-base. // All `(Vec, Limb, Limb)`s where the first `Limb` is a factor of `Limb::MAX`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_9() -> Generator<(Vec, Limb, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_9, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_2, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_9, ) } // var 10 is in malachite-base. // All triples of `(Vec, Limb, Limb)` that are valid inputs to `limbs_eq_limb_mod_limb`, such // that `limbs_eq_limb_mod_limb` would return `true`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_11() -> Generator<(Vec, Limb, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_11, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_4, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_11, ) } // All triples of `(Vec, Limb, Limb)` that are valid inputs to `limbs_eq_limb_mod_limb`, such // that `limbs_eq_limb_mod_limb` would return `false`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_12() -> Generator<(Vec, Limb, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_12, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_5, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_12, ) } // var 13 is in malachite-base. // All `(Vec, T, u64)` where `T` is unsigned, the `u64` is small, and the number of // significant bits of both the `Vec` and the `Limb` are less than or equal to the `u64`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_14() -> Generator<(Vec, T, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_14, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_6, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_14, ) } // All `(Vec, T, u64)` where `T` is unsigned, the `Vec` is nonempty, the `u64` is small, and // the number of significant bits of both the `Vec` and the `Limb` are less than or equal to the // `u64`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_15() -> Generator<(Vec, T, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_15, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_7, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_14, ) } // All `(Vec, T, u64)` where `T` is unsigned, the `u64` is small and positive, and the number // of significant bits of both the `Vec` and the `Limb` are less than or equal to the `u64`. pub fn unsigned_vec_unsigned_unsigned_triple_gen_var_16() -> Generator<(Vec, T, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_triple_gen_var_16, &random_unsigned_vec_unsigned_unsigned_triple_gen_var_8, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_16, ) } // -- (Vec, PrimitiveUnsigned, Vec) -- // All `(Vec, u64, Vec)` that are valid inputs to `limbs_to_digits_small_base`. pub fn unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1() -> Generator<(Vec, u64, Vec)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1, ) } // All triples of `(Vec, Limb, Vec)` that are valid inputs to // `limbs_pos_eq_neg_limb_mod`, such that `limbs_pos_eq_neg_limb_mod` would return `true`. pub fn unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2() -> Generator<(Vec, Limb, Vec)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2, ) } // All triples of `(Vec, Limb, Vec)` that are valid inputs to // `limbs_pos_eq_neg_limb_mod`, such that `limbs_pos_eq_neg_limb_mod` would return `false`. pub fn unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3() -> Generator<(Vec, Limb, Vec)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3, ) } // All triples of `(Vec, Limb, Vec)` that are valid inputs to `limbs_eq_limb_mod`, such // that `limbs_eq_limb_mod` would return `true`. pub fn unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4() -> Generator<(Vec, Limb, Vec)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4, ) } // All triples of `(Vec, Limb, Vec)` that are valid inputs to `limbs_eq_limb_mod`, such // that `limbs_eq_limb_mod` would return `false`. pub fn unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5() -> Generator<(Vec, Limb, Vec)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5, ) } // -- (Vec, PrimitiveUnsigned, Vec, PrimitiveUnsigned) -- // All `(Vec, usize, Vec, u64)` that are valid inputs to // `limbs_to_digits_small_base_basecase`. pub fn unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1() -> Generator<(Vec, usize, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1, &random_primitive_int_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1, &special_random_unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1, ) } // -- (Vec, Vec) -- // vars 1 through 9 are in malachite-base. // All `(Vec, Vec)` where each `Vec` has length at least 2 and ends in a nonzero value, // the first `Vec` represents an integer at least as large as the second, and the first elements of // each `Vec` are not both even. pub fn unsigned_vec_pair_gen_var_10() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_11, &random_primitive_int_vec_pair_gen_var_9, &special_random_unsigned_vec_pair_gen_var_11, ) } // vars 11 through 12 are in malachite-base. // All `(Vec, Vec)` where the first `Vec` is at least as long as the second and the // second `Vec` is nonempty and represents a `Natural` divisible by 3. pub fn unsigned_vec_pair_gen_var_13() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_14, &random_unsigned_vec_pair_gen_var_3, &special_random_unsigned_vec_pair_gen_var_14, ) } // All `(Vec, Vec)` that are valid inputs to `limbs_div_exact`. pub fn unsigned_vec_pair_gen_var_14() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_15, &random_unsigned_vec_pair_gen_var_4, &special_random_unsigned_vec_pair_gen_var_15, ) } // vars 15 through 16 are in malachite-base. // All `(Vec, Vec)` that are valid inputs to `limbs_div_exact` and `limbs_divisible_by`. pub fn unsigned_vec_pair_gen_var_17() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_18, &random_primitive_int_vec_pair_gen_var_14, &special_random_unsigned_vec_pair_gen_var_18, ) } // vars 18 through 20 are in malachite-base. // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_low_basecase`. pub fn unsigned_vec_pair_gen_var_21() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_22, &random_primitive_int_vec_pair_gen_var_16, &special_random_unsigned_vec_pair_gen_var_22, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_basecase`. pub fn unsigned_vec_pair_gen_var_22() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_23, &random_primitive_int_vec_pair_gen_var_17, &special_random_unsigned_vec_pair_gen_var_23, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_toom_2`. pub fn unsigned_vec_pair_gen_var_23() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_24, &random_primitive_int_vec_pair_gen_var_18, &special_random_unsigned_vec_pair_gen_var_24, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_toom_3`. pub fn unsigned_vec_pair_gen_var_24() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_25, &random_primitive_int_vec_pair_gen_var_19, &special_random_unsigned_vec_pair_gen_var_25, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_toom_4`. pub fn unsigned_vec_pair_gen_var_25() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_26, &random_primitive_int_vec_pair_gen_var_20, &special_random_unsigned_vec_pair_gen_var_26, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to both // `limbs_square_to_out_toom_3` and `limbs_square_to_out_toom_4`. pub fn unsigned_vec_pair_gen_var_26() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_27, &random_primitive_int_vec_pair_gen_var_21, &special_random_unsigned_vec_pair_gen_var_27, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_toom_6`. pub fn unsigned_vec_pair_gen_var_27() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_28, &random_primitive_int_vec_pair_gen_var_22, &special_random_unsigned_vec_pair_gen_var_28, ) } // All `(Vec, Vec)` where `T` is unsigned and `out` and `xs` are valid inputs to // `limbs_square_to_out_toom_8`. pub fn unsigned_vec_pair_gen_var_28() -> Generator<(Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_pair_gen_var_29, &random_primitive_int_vec_pair_gen_var_23, &special_random_unsigned_vec_pair_gen_var_29, ) } // vars 31 to 32 are in malachite-base. // -- (Vec, Vec, PrimitiveUnsigned) -- // var 1 is in malachite-base // All `(Vec, Vec, u64)` that are valid, `Some`-returning inputs to // `limbs_from_digits_small_base_basecase`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2, &random_primitive_int_vec_unsigned_vec_unsigned_triple_gen_var_1, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2, ) } // All `(Vec, Vec, u64)` that are inputs to `limbs_from_digits_small_base_basecase`, // regardless of whether they return `Some` or `None`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3, &random_primitive_int_vec_unsigned_vec_unsigned_triple_gen_var_2, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3, ) } // vars 4 through 6 are in malachite-base. // All triples of `(Vec, Vec, Limb)` that are valid inputs to // `limbs_pos_eq_neg_mod_limb`, such that `limbs_pos_eq_neg_mod_limb` would return `true`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7, ) } // All triples of `(Vec, Vec, Limb)` that are valid inputs to // `limbs_pos_eq_neg_mod_limb`, such that `limbs_pos_eq_neg_mod_limb` would return `false`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8, ) } // vars 9 through 13 are in malachite-base. // All `(Vec, Vec, T)` where `T` is unsigned and positive, the first `Vec` is at least as long // as the second, and the second `Vec` is nonempty and represents a `Natural` divisible by the // `Limb`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, &special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14, ) } // All triples of `(Vec, Vec, Limb)` that are valid inputs to `limbs_eq_limb_mod`, such // that `limbs_eq_limb_mod` would return `true`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_15() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_15, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_15, ) } // All triples of `(Vec, Vec, Limb)` that are valid inputs to `limbs_eq_limb_mod`, such // that `limbs_eq_limb_mod` would return `false`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_16() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_16, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_16, ) } // All `(Vec, Vec, Limb)` that are valid inputs to `limbs_mod_schoolbook`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17() -> Generator<(Vec, Vec, Limb)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17, &random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7, &special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_17, ) } // All `(Vec, Vec, u64)` where the `u64` is small and the number of significant bits of // both `Vec`s are less than or equal to the `u64`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_7, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_18, ) } // All `(Vec, Vec, u64)` where the `u64` is small, the first `Vec` is at least as long // as the second, and the number of significant bits of both `Vec`s are less than or equal to the // `u64`. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_8, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_19, ) } // All `(Vec, Vec, u64)` where the `u64` is small, the number of significant bits of // both `Vec`s are less than or equal to the `u64`, and both `Vec`s end with a nonzero value. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_9, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_20, ) } // All `(Vec, Vec, u64)` that are valid inputs to `limbs_mod_power_of_2_pow`, and where // the `u64` is small. pub fn unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21() -> Generator<(Vec, Vec, u64)> { Generator::new( &exhaustive_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21, &random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_10, &special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_21, ) } // vars 22 through 23 are in malachite-base. // -- (Vec, Vec, Vec -- // vars 1 through 3 are in malachite-base // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_22`. pub fn unsigned_vec_triple_gen_var_4() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_4, &random_primitive_int_vec_triple_gen_var_4, &special_random_unsigned_vec_triple_gen_var_4, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_32`. pub fn unsigned_vec_triple_gen_var_5() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_5, &random_primitive_int_vec_triple_gen_var_5, &special_random_unsigned_vec_triple_gen_var_5, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_33`. pub fn unsigned_vec_triple_gen_var_6() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_6, &random_primitive_int_vec_triple_gen_var_6, &special_random_unsigned_vec_triple_gen_var_6, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_42`. pub fn unsigned_vec_triple_gen_var_7() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_7, &random_primitive_int_vec_triple_gen_var_7, &special_random_unsigned_vec_triple_gen_var_7, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_43`. pub fn unsigned_vec_triple_gen_var_8() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_8, &random_primitive_int_vec_triple_gen_var_8, &special_random_unsigned_vec_triple_gen_var_8, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_44`. pub fn unsigned_vec_triple_gen_var_9() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_9, &random_primitive_int_vec_triple_gen_var_9, &special_random_unsigned_vec_triple_gen_var_9, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_52`. pub fn unsigned_vec_triple_gen_var_10() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_10, &random_primitive_int_vec_triple_gen_var_10, &special_random_unsigned_vec_triple_gen_var_10, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_53`. pub fn unsigned_vec_triple_gen_var_11() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_11, &random_primitive_int_vec_triple_gen_var_11, &special_random_unsigned_vec_triple_gen_var_11, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_54`. pub fn unsigned_vec_triple_gen_var_12() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_12, &random_primitive_int_vec_triple_gen_var_12, &special_random_unsigned_vec_triple_gen_var_12, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_62`. pub fn unsigned_vec_triple_gen_var_13() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_13, &random_primitive_int_vec_triple_gen_var_13, &special_random_unsigned_vec_triple_gen_var_13, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_63`. pub fn unsigned_vec_triple_gen_var_14() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_14, &random_primitive_int_vec_triple_gen_var_14, &special_random_unsigned_vec_triple_gen_var_14, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_6h`. pub fn unsigned_vec_triple_gen_var_15() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_15, &random_primitive_int_vec_triple_gen_var_15, &special_random_unsigned_vec_triple_gen_var_15, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_8h`. pub fn unsigned_vec_triple_gen_var_16() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_16, &random_primitive_int_vec_triple_gen_var_16, &special_random_unsigned_vec_triple_gen_var_16, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_33`, and // where the second and third `Vec`s have the same length. pub fn unsigned_vec_triple_gen_var_18() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_18, &random_primitive_int_vec_triple_gen_var_18, &special_random_unsigned_vec_triple_gen_var_18, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_6h`, and // where the second and third `Vec`s have the same length. pub fn unsigned_vec_triple_gen_var_19() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_19, &random_primitive_int_vec_triple_gen_var_19, &special_random_unsigned_vec_triple_gen_var_19, ) } // All `(Vec, Vec, Vec)` that are valid inputs to `limbs_mul_greater_to_out_toom_8h`, and // where the second and third `Vec`s have the same length. pub fn unsigned_vec_triple_gen_var_20() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_20, &random_primitive_int_vec_triple_gen_var_20, &special_random_unsigned_vec_triple_gen_var_20, ) } // All `(Vec, Vec, Vec)` that are valid inputs to both `limbs_mul_greater_to_out_toom_32` // and `limbs_mul_greater_to_out_toom_43`. pub fn unsigned_vec_triple_gen_var_22() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_22, &random_primitive_int_vec_triple_gen_var_22, &special_random_unsigned_vec_triple_gen_var_22, ) } // All `(Vec, Vec, Vec)` that are valid inputs to both `limbs_mul_greater_to_out_toom_42` // and `limbs_mul_greater_to_out_toom_53`. pub fn unsigned_vec_triple_gen_var_23() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_23, &random_primitive_int_vec_triple_gen_var_23, &special_random_unsigned_vec_triple_gen_var_23, ) } // vars 24 through 36 are in malachite-base // All triples of `Vec` that meet the preconditions for `limbs_eq_mod`, where the `Natural` // represented by the first `Vec` is equal to the negative of `Natural` represented by the second // `Vec` mod the `Natural` represented by the third `Vec`. pub fn unsigned_vec_triple_gen_var_37() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_37, &random_primitive_int_vec_triple_gen_var_36, &special_random_unsigned_vec_triple_gen_var_37, ) } // All triples of `Vec` that meet the preconditions for `limbs_eq_mod`, where the `Natural` // represented by the first `Vec` is not equal to the negative of `Natural` represented by the // second `Vec` mod the `Natural` represented by the third `Vec`. pub fn unsigned_vec_triple_gen_var_38() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_38, &random_primitive_int_vec_triple_gen_var_37, &special_random_unsigned_vec_triple_gen_var_38, ) } // vars 39 through 41 are in malachite-base. // All triples of `Vec` that are valid inputs to `limbs_div_barrett_approx`. pub fn unsigned_vec_triple_gen_var_42() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_42, &random_unsigned_vec_triple_gen_var_1, &special_random_unsigned_vec_triple_gen_var_42, ) } // All triples of `Vec` that are valid inputs to `limbs_div_barrett`. pub fn unsigned_vec_triple_gen_var_43() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_43, &random_unsigned_vec_triple_gen_var_2, &special_random_unsigned_vec_triple_gen_var_43, ) } // All triples of `Vec` that are valid inputs to `limbs_div_to_out`. pub fn unsigned_vec_triple_gen_var_44() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_44, &random_unsigned_vec_triple_gen_var_3, &special_random_unsigned_vec_triple_gen_var_44, ) } // All triples of `Vec` that are valid inputs to `limbs_div_to_out` and both the balanced and // unbalanced div helper functions. pub fn unsigned_vec_triple_gen_var_45() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_45, &random_unsigned_vec_triple_gen_var_4, &special_random_unsigned_vec_triple_gen_var_45, ) } // All triples of `Vec` that are valid inputs to `limbs_modular_div_barrett`. pub fn unsigned_vec_triple_gen_var_46() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_46, &random_unsigned_vec_triple_gen_var_5, &special_random_unsigned_vec_triple_gen_var_46, ) } // All triples of `Vec` that are valid inputs to `limbs_modular_div`. pub fn unsigned_vec_triple_gen_var_47() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_47, &random_unsigned_vec_triple_gen_var_6, &special_random_unsigned_vec_triple_gen_var_47, ) } // All triples of `Vec` that are valid inputs to `limbs_div_exact_to_out`. pub fn unsigned_vec_triple_gen_var_48() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_48, &random_unsigned_vec_triple_gen_var_7, &special_random_unsigned_vec_triple_gen_var_48, ) } // All triples of `Vec` that are valid inputs to both `limbs_div_to_out` and // `limbs_div_exact_to_out`. pub fn unsigned_vec_triple_gen_var_49() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_49, &random_unsigned_vec_triple_gen_var_8, &special_random_unsigned_vec_triple_gen_var_49, ) } // vars 50 through 53 are in malachite-base. // All triples of `Vec` that are valid inputs to `limbs_eq_mod`, such that `limbs_eq_mod` // would return `true`. pub fn unsigned_vec_triple_gen_var_54() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_54, &random_unsigned_vec_triple_gen_var_11, &special_random_unsigned_vec_triple_gen_var_54, ) } // All triples of `Vec` that are valid inputs to `limbs_eq_mod`, such that `limbs_eq_mod` // would return `false`. pub fn unsigned_vec_triple_gen_var_55() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_55, &random_unsigned_vec_triple_gen_var_12, &special_random_unsigned_vec_triple_gen_var_55, ) } // All triples of `Vec` that are valid inputs to `limbs_div_mod_by_two_limb_normalized`. pub fn unsigned_vec_triple_gen_var_56() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_56, &random_unsigned_vec_triple_gen_var_13, &special_random_unsigned_vec_triple_gen_var_56, ) } // var 57 is in malachite-base. // All `(Vec, Vec, Vec)` that are valid inputs to both `limbs_mul_greater_to_out_toom_33` // and `limbs_mul_greater_to_out_toom_33`. pub fn unsigned_vec_triple_gen_var_58() -> Generator<(Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_triple_gen_var_58, &random_primitive_int_vec_triple_gen_var_45, &special_random_unsigned_vec_triple_gen_var_58, ) } // var 59 is in malachite-base. // -- (Vec * 4) -- // All quadruples of `Vec` that are valid inputs to `limbs_div_mod_to_out`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_1() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_1, &random_unsigned_vec_quadruple_gen_var_1, &special_random_unsigned_vec_quadruple_gen_var_1, ) } // All quadruples of `Vec` that are valid inputs to `limbs_modular_div_mod_barrett`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_2() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_2, &random_unsigned_vec_quadruple_gen_var_2, &special_random_unsigned_vec_quadruple_gen_var_2, ) } // All quadruples of `Vec` that are valid inputs to `limbs_modular_div_mod_barrett`, and the // first, second and third `Vec`s would meet the preconditions of // `limbs_modular_div_mod_divide_and_conquer`, given the correct `inverse`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_3() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_3, &random_unsigned_vec_quadruple_gen_var_3, &special_random_unsigned_vec_quadruple_gen_var_3, ) } // All quadruples of `Vec` that meet certain preconditions that enable comparing the // performance of two kinds of Barrett division. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_4() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_4, &random_unsigned_vec_quadruple_gen_var_4, &special_random_unsigned_vec_quadruple_gen_var_4, ) } // All quadruples of `Vec` that are valid inputs to `limbs_div_mod_barrett`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_5() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_5, &random_unsigned_vec_quadruple_gen_var_5, &special_random_unsigned_vec_quadruple_gen_var_5, ) } // All quadruples of `Vec` that are valid inputs to `limbs_mod_pow`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_6() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_6, &random_unsigned_vec_quadruple_gen_var_6, &special_random_unsigned_vec_quadruple_gen_var_6, ) } // All quadruples of `Vec` that are valid inputs to `limbs_mod_pow_odd`. #[allow(clippy::type_complexity)] pub fn unsigned_vec_quadruple_gen_var_7() -> Generator<(Vec, Vec, Vec, Vec)> { Generator::new( &exhaustive_unsigned_vec_quadruple_gen_var_7, &random_unsigned_vec_quadruple_gen_var_7, &special_random_unsigned_vec_quadruple_gen_var_7, ) } // -- large types -- // vars 1 through 4 are in malachite-base // All `(HalfGcdMatrix, Vec, u8)` that are valid inputs to `HalfGcdMatrix::update_q`. pub fn large_type_gen_var_5() -> Generator<(OwnedHalfGcdMatrix, Vec, u8)> { Generator::new( &exhaustive_large_type_gen_var_5, &random_large_type_gen_var_5, &special_random_large_type_gen_var_5, ) } // All `(HalfGcdMatrix1, Vec, Vec, Vec)` that are valid inputs to // `HalfGcdMatrix1::mul_vector`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_6() -> Generator<(HalfGcdMatrix1, Vec, Vec, Vec)> { Generator::new( &exhaustive_large_type_gen_var_6, &random_large_type_gen_var_6, &special_random_large_type_gen_var_6, ) } // All `(HalfGcdMatrix, HalfGcdMatrix1)` that are valid inputs to `HalfGcdMatrix::mul_matrix_1`. pub fn large_type_gen_var_7() -> Generator<(OwnedHalfGcdMatrix, HalfGcdMatrix1)> { Generator::new( &exhaustive_large_type_gen_var_7, &random_large_type_gen_var_7, &special_random_large_type_gen_var_7, ) } // All valid inputs to `limbs_matrix_mul_2_2`. pub fn large_type_gen_var_8() -> Generator { Generator::new( &exhaustive_large_type_gen_var_8, &random_large_type_gen_var_8, &special_random_large_type_gen_var_8, ) } // var 9 is in malachite-base. #[cfg(feature = "32_bit_limbs")] const PRIME_FACTORS_OF_LIMB_MAX: &[Limb] = &[3, 5, 17, 257, 65_537]; #[cfg(not(feature = "32_bit_limbs"))] const PRIME_FACTORS_OF_LIMB_MAX: &[Limb] = &[3, 5, 17, 257, 641, 65_537, 6_700_417]; pub(crate) fn factors_of_limb_max() -> Vec { lex_ordered_unique_vecs(PRIME_FACTORS_OF_LIMB_MAX.iter()) .map(|pfs| pfs.into_iter().product()) .collect() } // All `(Vec, Vec, Limb, Limb)` where the first `Vec` is at least as long as the second, // and the first `Limb` is a divisor of `Limb::MAX`. pub fn large_type_gen_var_10() -> Generator<(Vec, Vec, Limb, Limb)> { Generator::new( &exhaustive_large_type_gen_var_10, &random_large_type_gen_var_10, &special_random_large_type_gen_var_10, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_div_mod_schoolbook`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_11() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_11, &random_large_type_gen_var_11, &special_random_large_type_gen_var_11, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_div_mod_divide_and_conquer`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_12() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_12, &random_large_type_gen_var_12, &special_random_large_type_gen_var_12, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_modular_div_schoolbook`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_13() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_13, &random_large_type_gen_var_13, &special_random_large_type_gen_var_13, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_modular_div_mod_schoolbook`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_14() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_14, &random_large_type_gen_var_14, &special_random_large_type_gen_var_14, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_modular_div_mod_divide_and_conquer`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_15() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_15, &random_large_type_gen_var_15, &special_random_large_type_gen_var_15, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_modular_div_divide_and_conquer`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_16() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_16, &random_large_type_gen_var_16, &special_random_large_type_gen_var_16, ) } // All `(Vec, Vec, Vec, Limb)` that are valid inputs to // `limbs_modular_invert_small`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_17() -> Generator<(Vec, Vec, Vec, Limb)> { Generator::new( &exhaustive_large_type_gen_var_17, &random_large_type_gen_var_17, &special_random_large_type_gen_var_17, ) } // All `(Vec, usize, Limb, Limb, u64)` that are valid inputs to // `limbs_div_mod_extra_in_place`. pub fn large_type_gen_var_18() -> Generator<(Vec, usize, Limb, Limb, u64)> { Generator::new( &exhaustive_large_type_gen_var_18, &random_large_type_gen_var_18, &special_random_large_type_gen_var_18, ) } // All `(Vec, usize, Vec, Limb, Limb, u64)` that are valid inputs to // `limbs_div_mod_extra`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_19() -> Generator<(Vec, usize, Vec, Limb, Limb, u64)> { Generator::new( &exhaustive_large_type_gen_var_19, &random_large_type_gen_var_19, &special_random_large_type_gen_var_19, ) } // All `(Vec, Vec, Vec, Vec, usize, usize)` that are valid inputs to // `limbs_div_barrett_large_product`. #[allow(clippy::type_complexity)] pub fn large_type_gen_var_20() -> Generator<(Vec, Vec, Vec, Vec, usize, usize)> { Generator::new( &exhaustive_large_type_gen_var_20, &random_large_type_gen_var_20, &special_random_large_type_gen_var_20, ) } #[allow(clippy::type_complexity)] /// All nonuples of `Limb`s that are valid inputs to `limbs_mod_mul_two_limbs`. pub fn large_type_gen_var_21() -> Generator<(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { Generator::new( &exhaustive_large_type_gen_var_21, &random_large_type_gen_var_21, &special_random_large_type_gen_var_21, ) } // var 22 is in malachite-base. /// All `(u64, Vec, RationalSequence)` that are valid inputs to /// `Rational::from_power_of_2_digits`. pub fn large_type_gen_var_23() -> Generator<(u64, Vec, RationalSequence)> { Generator::new( &exhaustive_large_type_gen_var_23, &random_large_type_gen_var_23, &special_random_large_type_gen_var_23, ) } /// All `(Vec, RationalSequence)` that are valid inputs to /// `Rational::from_power_of_2_digits` with `log_base` == 1. pub fn large_type_gen_var_24() -> Generator<(Vec, RationalSequence)> { Generator::new_no_special( &exhaustive_large_type_gen_var_24, &random_large_type_gen_var_24, ) } /// All `(u64, Vec, RationalSequence)` that are valid inputs to /// `Rational::from_digits`. pub fn large_type_gen_var_25() -> Generator<(Natural, Vec, RationalSequence)> { Generator::new( &exhaustive_large_type_gen_var_25, &random_large_type_gen_var_25, &special_random_large_type_gen_var_24, ) } /// All `(Vec, RationalSequence)` that are valid inputs to `Rational::from_digits` /// with `base` == 10. pub fn large_type_gen_var_26() -> Generator<(Vec, RationalSequence)> { Generator::new_no_special( &exhaustive_large_type_gen_var_26, &random_large_type_gen_var_26, ) } // var 27 is in malachite-base. pub mod common; pub mod exhaustive; pub mod random; pub mod special_random; ================================================ FILE: malachite-nz/src/test_util/generators/random.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::logic::bit_access::limbs_vec_clear_bit_neg; use crate::integer::random::{ RandomIntegers, random_integers, random_natural_integers, random_negative_integers, random_nonzero_integers, }; use crate::natural::Natural; use crate::natural::arithmetic::binomial_coefficient::BIN_GOETGHELUCK_THRESHOLD; use crate::natural::arithmetic::binomial_coefficient::BIN_UIUI_RECURSIVE_SMALLDC; use crate::natural::arithmetic::div_exact::{ limbs_modular_invert_limb, limbs_modular_invert_scratch_len, }; use crate::natural::arithmetic::div_mod::{ limbs_div_mod_barrett_is_len, limbs_div_mod_barrett_scratch_len, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::eq_mod::limbs_eq_mod_ref_ref_ref; use crate::natural::arithmetic::gcd::half_gcd::HalfGcdMatrix1; use crate::natural::arithmetic::mod_power_of_2::limbs_slice_mod_power_of_2_in_place; use crate::natural::arithmetic::mod_power_of_2_square::SQRLO_DC_THRESHOLD_LIMIT; use crate::natural::arithmetic::mul::limb::limbs_vec_mul_limb_in_place; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::mul::mul_mod::limbs_mul_mod_base_pow_n_minus_1_next_size; use crate::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h_input_sizes_valid, limbs_mul_greater_to_out_toom_8h_input_sizes_valid, limbs_mul_greater_to_out_toom_22_input_sizes_valid, limbs_mul_greater_to_out_toom_32_input_sizes_valid, limbs_mul_greater_to_out_toom_33_input_sizes_valid, limbs_mul_greater_to_out_toom_42_input_sizes_valid, limbs_mul_greater_to_out_toom_43_input_sizes_valid, limbs_mul_greater_to_out_toom_44_input_sizes_valid, limbs_mul_greater_to_out_toom_52_input_sizes_valid, limbs_mul_greater_to_out_toom_53_input_sizes_valid, limbs_mul_greater_to_out_toom_54_input_sizes_valid, limbs_mul_greater_to_out_toom_62_input_sizes_valid, limbs_mul_greater_to_out_toom_63_input_sizes_valid, }; use crate::natural::arithmetic::square::{ limbs_square_to_out_toom_3_input_size_valid, limbs_square_to_out_toom_4_input_size_valid, limbs_square_to_out_toom_6_input_size_valid, limbs_square_to_out_toom_8_input_size_valid, }; use crate::natural::conversion::digits::general_digits::{ GET_STR_PRECOMPUTE_THRESHOLD, limbs_digit_count, limbs_per_digit_in_base, }; use crate::natural::random::{ RandomNaturalRangeToInfinity, RandomNaturals, RandomNaturalsLessThan, get_random_natural_with_bits, get_random_natural_with_up_to_bits, random_natural_range_to_infinity, random_naturals, random_naturals_less_than, random_positive_naturals, }; use crate::platform::{ DoubleLimb, Limb, ODD_CENTRAL_BINOMIAL_OFFSET, ODD_CENTRAL_BINOMIAL_TABLE_LIMIT, ODD_FACTORIAL_EXTTABLE_LIMIT, ODD_FACTORIAL_TABLE_LIMIT, SQR_TOOM2_THRESHOLD, }; use crate::test_util::extra_variadic::{ random_quadruples_from_single, random_quadruples_xxxy, random_quadruples_xyxz, random_quadruples_xyyx, random_quadruples_xyyz, random_quintuples_xyyyz, random_sextuples_from_single, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyx, random_triples_xyy, }; use crate::test_util::generators::exhaustive::{ filter_helper_1, filter_helper_2, filter_helper_3, filter_helper_4, filter_helper_5, filter_helper_6, filter_map_helper_1, filter_map_helper_2, filter_map_helper_3, gcd_input_filter, large_type_filter_map_1, limbs_eq_mod_map, limbs_significant_bits_helper, map_helper_1, map_helper_2, map_helper_3, round_to_multiple_integer_filter_map, round_to_multiple_natural_filter_map, }; use crate::test_util::generators::{T8, factors_of_limb_max, limbs_odd_factorial_valid}; use crate::test_util::natural::arithmetic::gcd::{OwnedHalfGcdMatrix, half_gcd_matrix_create}; use itertools::Itertools; use malachite_base::bools::random::{RandomBools, random_bools}; use malachite_base::iterators::with_special_value; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, CeilingLogBase2, CoprimeWith, DivRound, DivisibleBy, DivisibleByPowerOf2, EqMod, EqModPowerOf2, Parity, PowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::random::random_to_sci_options; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, SaturatingFrom, ToSci, WrappingFrom, }; use malachite_base::num::factorization::prime_sieve::n_to_bit; use malachite_base::num::logic::traits::{ BitAccess, BitConvertible, LeadingZeros, SignificantBits, }; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, GeometricRandomSigneds, geometric_random_positive_unsigneds, geometric_random_signed_range, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use malachite_base::num::random::{ RandomPrimitiveInts, RandomUnsignedBitChunks, RandomUnsignedRange, RandomUnsignedsLessThan, VariableRangeGenerator, random_natural_signeds, random_positive_unsigneds, random_primitive_ints, random_unsigned_bit_chunks, random_unsigned_inclusive_range, random_unsigneds_less_than, special_random_primitive_floats, }; use malachite_base::options::random::{RandomOptions, random_options}; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{ GenConfig, It, permute_1_3_2, reshape_1_3_to_4, reshape_2_1_to_3, reshape_2_2_to_4, }; use malachite_base::test_util::generators::random::{ PrimitiveIntVecPairLenGenerator1, PrimitiveIntVecPairLenGenerator2, PrimitiveIntVecQuadrupleLenGenerator1, PrimitiveIntVecTripleLenGenerator1, PrimitiveIntVecTripleXYYLenGenerator, get_two_highest, random_primitive_int_vec_unsigned_pair_gen_var_10, }; use malachite_base::tuples::random::{ random_ordered_unique_pairs, random_pairs, random_pairs_from_single, }; use malachite_base::unions::Union2; use malachite_base::unions::random::random_union2s; use malachite_base::vecs::random::{ RandomVecs, random_vecs, random_vecs_length_range, random_vecs_min_length, }; use malachite_base::vecs::{RandomValuesFromVec, random_values_from_vec}; use num::{BigInt, BigUint}; use std::cmp::{Ordering::*, max}; use std::collections::HashMap; use std::marker::PhantomData; use std::ops::{Shl, Shr}; // -- Integer -- pub fn random_integer_gen(config: &GenConfig) -> It { Box::new(random_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_integer_gen_var_1(config: &GenConfig) -> It { Box::new(with_special_value( EXAMPLE_SEED, Integer::ZERO, 1, 100, &|seed| { random_pairs( seed, &|seed_2| { random_positive_float_naturals::( seed_2, 0, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)) }, )) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_integer_gen_var_2(config: &GenConfig) -> It where for<'a> T: ConvertibleFrom<&'a Natural>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_natural_range_to_infinity( seed, Natural::power_of_2(T::MANTISSA_WIDTH + 1) | Natural::ONE, config.get_or("mean_bits_n", Limb::WIDTH << 1), config.get_or("mean_bits_d", 1), ) .filter(|n| !T::convertible_from(n)) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn random_integer_gen_var_3 ExactFrom<&'a Natural> + PrimitiveFloat>( config: &GenConfig, ) -> It where Natural: ExactFrom, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_float_naturals::( seed, 1, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) .filter_map(|a| { let b = Natural::exact_from(T::exact_from(&a).next_higher()); let diff = b - &a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn random_integer_gen_var_4(config: &GenConfig) -> It { Box::new(random_natural_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_integer_gen_var_5(_config: &GenConfig) -> It where Integer: From, { Box::new(random_primitive_ints(EXAMPLE_SEED).map(Integer::from)) } pub fn random_integer_gen_var_6(config: &GenConfig) -> It { Box::new(random_negative_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_integer_gen_var_7(config: &GenConfig) -> It { Box::new(random_nonzero_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_integer_gen_var_8(config: &GenConfig) -> It { Box::new( random_natural_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Integer::ONE), ) } // -- (Integer, Integer) -- pub fn random_integer_pair_gen(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs_from_single(random_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_integer_pair_gen_var_1(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_integer_pair_gen_var_2(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y)| (x * &y, y)), ) } pub fn random_integer_pair_gen_var_3(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn random_integer_pair_gen_var_4(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, n)| (a, (n << 1u32) | Integer::ONE)), ) } pub fn random_integer_pair_gen_var_5(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs_from_single(random_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn random_integer_pair_gen_var_6(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs_from_single( random_natural_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Integer::ONE), ) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn random_integer_pair_gen_var_7(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Integer::from) }, )) } // -- (Integer, Integer, Integer) -- pub fn random_integer_triple_gen(config: &GenConfig) -> It<(Integer, Integer, Integer)> { Box::new(random_triples_from_single(random_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_integer_triple_gen_var_1(config: &GenConfig) -> It<(Integer, Integer, Integer)> { Box::new(random_triples_from_single(random_natural_integers( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_integer_triple_gen_var_2(config: &GenConfig) -> It<(Integer, Integer, Integer)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, b, n)| (a, b, (n << 1u32) | Integer::ONE)), ) } pub fn random_integer_triple_gen_var_3(config: &GenConfig) -> It<(Integer, Integer, Integer)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, m, n)| (a, (m << 1u32) | Integer::ONE, (n << 1u32) | Integer::ONE)), ) } // -- (Integer, Integer, Integer, PrimitiveUnsigned) -- pub fn random_integer_integer_integer_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, Integer, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, Integer, Natural) -- pub fn random_integer_integer_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_integer_integer_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y, m)| (x * Integer::from(&m) + &y, y, m)), ) } pub fn random_integer_integer_natural_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y, m)| !x.eq_mod(y, m)), ) } // -- (Integer, Integer, PrimitiveFloat) -- pub fn random_integer_integer_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Integer, Integer, PrimitiveInt) -- pub fn random_integer_integer_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Integer, Integer, PrimitiveUnsigned) -- pub fn random_integer_integer_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_integer_integer_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, T)> where Integer: Shl, { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn random_integer_integer_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } // -- (Integer, Integer, RoundingMode) -- pub fn random_integer_integer_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub fn random_integer_integer_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_integer_filter_map(x, y, rm)), ) } // -- (Integer, Natural) -- pub fn random_integer_natural_pair_gen(config: &GenConfig) -> It<(Integer, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, Natural, Natural) -- pub fn random_integer_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, PrimitiveFloat) -- pub fn random_integer_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Integer, PrimitiveFloat, PrimitiveFloat) -- pub fn random_integer_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Integer, PrimitiveInt) -- pub fn random_integer_primitive_int_pair_gen( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Integer, PrimitiveInt, Natural) -- pub fn random_integer_primitive_int_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, T, Natural)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, PrimitiveInt, PrimitiveInt) -- pub fn random_integer_primitive_int_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Integer, PrimitiveSigned) -- pub fn random_integer_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_integer_signed_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveSigned, RoundingMode) -- pub fn random_integer_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shr, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn random_integer_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Integer, PrimitiveUnsigned) -- pub fn random_integer_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), )) } pub fn random_integer_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_integer_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { random_natural_integers( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { random_negative_integers( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn random_integer_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn random_integer_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn random_integer_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveUnsigned, bool) -- pub fn random_integer_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_bools, )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_integer_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Integer, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn random_integer_unsigned_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn random_integer_unsigned_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn random_integer_unsigned_unsigned_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, T, Natural)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- pub fn random_integer_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } pub fn random_integer_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| (if rm == Exact { n << u } else { n }, u, rm)), ) } // vars 3 and 4 are in malachite-float. pub fn random_integer_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // -- (Integer, RoundingMode) -- pub fn random_integer_rounding_mode_pair_gen(config: &GenConfig) -> It<(Integer, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn random_integer_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Integer, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn random_integer_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Integer, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_nonzero_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } // -- (Integer, ToSciOptions) -- pub fn random_integer_to_sci_options_pair_gen(config: &GenConfig) -> It<(Integer, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn random_integer_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // --(Integer, Vec) -- struct IntegerBoolVecPairGenerator1 { xs: RandomIntegers>, bs: RandomBools, } impl Iterator for IntegerBoolVecPairGenerator1 { type Item = (Integer, Vec); fn next(&mut self) -> Option<(Integer, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs) .take(x.to_twos_complement_limbs_asc().len()) .collect(); Some((x, bs)) } } pub fn random_integer_bool_vec_pair_gen_var_1(config: &GenConfig) -> It<(Integer, Vec)> { Box::new(IntegerBoolVecPairGenerator1 { xs: random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } struct IntegerBoolVecPairGenerator2 { xs: RandomIntegers>, bs: RandomBools, } impl Iterator for IntegerBoolVecPairGenerator2 { type Item = (Integer, Vec); fn next(&mut self) -> Option<(Integer, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs).take(x.to_bits_asc().len()).collect(); Some((x, bs)) } } pub fn random_integer_bool_vec_pair_gen_var_2(config: &GenConfig) -> It<(Integer, Vec)> { Box::new(IntegerBoolVecPairGenerator2 { xs: random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- Natural -- pub fn random_natural_gen(config: &GenConfig) -> It { Box::new(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_natural_gen_var_1(config: &GenConfig) -> It { Box::new(random_natural_range_to_infinity( EXAMPLE_SEED, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_natural_gen_var_2(config: &GenConfig) -> It { Box::new(random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } struct RandomPositiveFloatNaturals { exponents: GeometricRandomSignedRange, ranges: VariableRangeGenerator, phantom: PhantomData, } impl Iterator for RandomPositiveFloatNaturals { type Item = Natural; fn next(&mut self) -> Option { let exponent = self.exponents.next().unwrap(); let a = if exponent == 0 { 1 } else { u64::power_of_2(T::MANTISSA_WIDTH) }; let mantissa = self .ranges .next_in_range(a, u64::power_of_2(T::MANTISSA_WIDTH + 1)); Some(Natural::from(mantissa) << exponent) } } fn random_positive_float_naturals( seed: Seed, start_exponent: i64, mean_exponent_numerator: u64, mean_exponent_denominator: u64, ) -> RandomPositiveFloatNaturals { RandomPositiveFloatNaturals { exponents: geometric_random_signed_range( seed.fork("exponents"), start_exponent, i64::power_of_2(T::EXPONENT_WIDTH - 1) - i64::wrapping_from(T::MANTISSA_WIDTH) - 1, mean_exponent_numerator, mean_exponent_denominator, ), ranges: VariableRangeGenerator::new(seed.fork("mantissas")), phantom: PhantomData, } } pub fn random_natural_gen_var_3(config: &GenConfig) -> It { Box::new(with_special_value( EXAMPLE_SEED, Natural::ZERO, 1, 100, &|seed| { random_positive_float_naturals::( seed, 0, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) }, )) } #[allow(clippy::type_repetition_in_bounds)] pub fn random_natural_gen_var_4(config: &GenConfig) -> It where for<'a> T: ConvertibleFrom<&'a Natural>, { Box::new( random_natural_range_to_infinity( EXAMPLE_SEED, Natural::power_of_2(T::MANTISSA_WIDTH + 1) | Natural::ONE, config.get_or("mean_bits_n", Limb::WIDTH << 1), config.get_or("mean_bits_d", 1), ) .filter(|n| !T::convertible_from(n)), ) } pub fn random_natural_gen_var_5 ExactFrom<&'a Natural> + PrimitiveFloat>( config: &GenConfig, ) -> It where Natural: ExactFrom, { Box::new( random_positive_float_naturals::( EXAMPLE_SEED, 1, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), ) .filter_map(|a| { let b = Natural::exact_from(T::exact_from(&a).next_higher()); let diff = b - &a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn random_natural_gen_var_6(_config: &GenConfig) -> It where Natural: From, { Box::new(random_primitive_ints(EXAMPLE_SEED).map(Natural::from)) } pub fn random_natural_gen_var_7(_config: &GenConfig) -> It where Natural: ExactFrom, { Box::new(random_natural_signeds(EXAMPLE_SEED).map(Natural::exact_from)) } pub fn random_natural_gen_var_8(config: &GenConfig) -> It { Box::new( random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Natural::ONE), ) } pub fn random_natural_gen_var_9(config: &GenConfig) -> It { Box::new( geometric_random_unsigneds::( EXAMPLE_SEED, config.get_or("mean_n", 64), config.get_or("mean_d", 1), ) .map(Natural::from), ) } // -- (Natural, bool) -- pub fn random_natural_bool_pair_gen(config: &GenConfig) -> It<(Natural, bool)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_bools, )) } // -- (Natural, Integer, Natural) -- pub fn random_natural_integer_natural_triple_gen( config: &GenConfig, ) -> It<(Natural, Integer, Natural)> { Box::new(random_triples_xyx( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Natural, Natural) -- pub fn random_natural_pair_gen(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_pair_gen_var_1(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_natural_range_to_infinity( seed, Natural::power_of_2(Limb::WIDTH), config.get_or("mean_bits_n", 64 + Limb::WIDTH), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_natural_pair_gen_var_2(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_natural_pair_gen_var_3(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_natural_pair_gen_var_4(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| (x * &y, y * z)), ) } pub fn random_natural_pair_gen_var_5(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_natural_pair_gen_var_6(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y)| (x * &y, y)), ) } pub fn random_natural_pair_gen_var_7(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn random_natural_pair_gen_var_8(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_ordered_unique_pairs(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_pair_gen_var_9(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs_from_single(random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_pair_gen_var_10(config: &GenConfig) -> It<(Natural, Natural)> { // TODO Box::new( random_pairs_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x >= y), ) } pub fn random_natural_pair_gen_var_11(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_ordered_unique_pairs(random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_pair_gen_var_12(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, n)| (a, (n << 1u32) | Natural::ONE)), ) } pub fn random_natural_pair_gen_var_13(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single( random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Natural::ONE), ) .filter(|(x, y)| x.coprime_with(y)), ) } pub fn random_natural_pair_gen_var_14(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x.coprime_with(y)), ) } pub fn random_natural_pair_gen_var_15(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from) }, )) } // -- (Natural, Natural, bool) -- pub fn random_natural_natural_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_bools, )) } // -- (Natural, Natural, Natural) -- pub fn random_natural_triple_gen(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_triple_gen_var_1(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, m)| (x * &m + &y, y, m)), ) } pub fn random_natural_triple_gen_var_2(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y, m)| !x.eq_mod(y, m)), ) } pub fn random_natural_triple_gen_var_3(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| { let z = max(&x, &y) + z + Natural::ONE; (x, y, z) }), ) } pub fn random_natural_triple_gen_var_4(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_natural_triple_gen_var_5(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, mut z)| { z += &x; z += Natural::ONE; (x, y, z) }), ) } pub fn random_natural_triple_gen_var_6(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_from_single(random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_natural_triple_gen_var_7(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| (x + &y * &z, y, z)), ) } pub fn random_natural_triple_gen_var_8(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, b, n)| (a, b, (n << 1u32) | Natural::ONE)), ) } pub fn random_natural_triple_gen_var_9(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, m, n)| (a, (m << 1u32) | Natural::ONE, (n << 1u32) | Natural::ONE)), ) } // -- (Natural, Natural, Natural, Natural) -- pub fn random_natural_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter_map(|(x, y, z, w)| { let ranking = [(&x, 0), (&y, 1), (&z, 2), (&w, 3)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, w, x), 1 => (x, z, w, y), 2 => (x, y, w, z), _ => (x, y, z, w), }) } }), ) } pub fn random_natural_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z, mut w)| { w += max!(&x, &y); w += Natural::ONE; (x, y, z, w) }), ) } pub fn random_natural_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(random_naturals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z, mut w)| { w += &x; w += Natural::ONE; (x, y, z, w) }), ) } // -- (Natural, Natural, Natural, PrimitiveUnsigned) -- pub fn random_natural_natural_natural_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, Natural, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_natural_natural_unsigned_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += max!( x.significant_bits(), y.significant_bits(), z.significant_bits() ); (x, y, z, m) }), ) } pub fn random_natural_natural_natural_unsigned_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, z, m) }), ) } pub fn random_natural_natural_natural_unsigned_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += x.significant_bits(); (x, y, z, m) }), ) } // -- (Natural, Natural, PrimitiveFloat) -- pub fn random_natural_natural_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Natural, Natural, PrimitiveInt) -- pub fn random_natural_natural_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Natural, Natural, PrimitiveSigned) -- pub fn random_natural_natural_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_ordered_unique_pairs(random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ))) } // -- (Natural, Natural, PrimitiveUnsigned) -- pub fn random_natural_natural_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_natural_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, T)> where Natural: Shl, { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn random_natural_natural_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } pub fn random_natural_natural_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Natural, Natural, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, m) }), ) } pub fn random_natural_natural_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Natural, Natural, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } pub fn random_natural_natural_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_ordered_unique_pairs(random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ))) } // -- (Natural, Natural, RoundingMode) -- pub fn random_natural_natural_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub fn random_natural_natural_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_natural_filter_map(x, y, rm)), ) } // -- (Natural, PrimitiveFloat) -- pub fn random_natural_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Natural, PrimitiveFloat, PrimitiveFloat) -- pub fn random_natural_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Natural, PrimitiveInt) -- pub fn random_natural_primitive_int_pair_gen( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } pub fn random_natural_primitive_int_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Natural, PrimitiveInt, PrimitiveInt) -- pub fn random_natural_primitive_int_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Natural, PrimitiveSigned) -- pub fn random_natural_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_natural_signeds, )) } pub fn random_natural_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } struct NaturalBitsMultipleOfLimbBitsGenerator { limbs: RandomPrimitiveInts, limb_counts: GeometricRandomNaturalValues, } impl Iterator for NaturalBitsMultipleOfLimbBitsGenerator { type Item = Natural; fn next(&mut self) -> Option { Some(get_random_natural_with_bits( &mut self.limbs, self.limb_counts.next().unwrap() << Limb::LOG_WIDTH, )) } } pub fn random_natural_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| NaturalBitsMultipleOfLimbBitsGenerator { limbs: random_primitive_ints(seed.fork("limbs")), limb_counts: geometric_random_positive_unsigneds( seed.fork("limb_counts"), config.get_or("mean_small_n", 2), config.get_or("mean_small_d", 1), ), }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Natural, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_natural_signed_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } pub fn random_natural_signed_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Natural, PrimitiveSigned, RoundingMode) -- pub fn random_natural_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shr, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn random_natural_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Natural, PrimitiveUnsigned) -- pub fn random_natural_unsigned_pair_gen_var_1< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::saturating_from(U::MAX)), )) } pub fn random_natural_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::MAX), )) } pub fn random_natural_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), )) } pub fn random_natural_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Natural, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, 1, T::WIDTH), )) } pub fn random_natural_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(Natural, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn random_natural_unsigned_pair_gen_var_10( config: &GenConfig, ) -> It<(Natural, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn random_natural_unsigned_pair_gen_var_11(config: &GenConfig) -> It<(Natural, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } pub fn random_natural_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_pair_gen_var_13(config: &GenConfig) -> It<(Natural, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } // -- (Natural, PrimitiveUnsigned, bool) -- pub fn random_natural_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_bools, )) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_natural_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::from(36u8)), &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn random_natural_unsigned_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, u64, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, 1, U::WIDTH), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z)| if y <= z { (x, y, z) } else { (x, z, y) }), ) } pub fn random_natural_unsigned_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_natural_unsigned_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Natural, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn random_natural_unsigned_unsigned_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, T, Natural)> { Box::new( random_quadruples_xyyx::<_, _, T, _>( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- pub fn random_natural_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } // var 2 is in malachite-float // --(Natural, PrimitiveUnsigned, Vec) -- struct NaturalUnsignedBoolVecTripleGenerator { xs: RandomNaturals>, log_bases: It, bs: RandomBools, } impl Iterator for NaturalUnsignedBoolVecTripleGenerator { type Item = (Natural, u64, Vec); fn next(&mut self) -> Option<(Natural, u64, Vec)> { let x = self.xs.next().unwrap(); let log_base = self.log_bases.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from( x.significant_bits().div_round(log_base, Ceiling).0, )) .collect(); Some((x, log_base, bs)) } } pub fn random_natural_unsigned_bool_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, u64, Vec)> { Box::new(NaturalUnsignedBoolVecTripleGenerator { xs: random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), log_bases: Box::new(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), )), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } pub fn random_natural_unsigned_bool_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, u64, Vec)> { Box::new(NaturalUnsignedBoolVecTripleGenerator { xs: random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), log_bases: Box::new(random_unsigned_inclusive_range( EXAMPLE_SEED.fork("log_bases"), 1, T::WIDTH, )), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- (Natural, RoundingMode) -- pub fn random_natural_rounding_mode_pair_gen(config: &GenConfig) -> It<(Natural, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn random_natural_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Natural, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn random_natural_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } // -- (Natural, ToSciOptions) -- pub fn random_natural_to_sci_options_pair_gen(config: &GenConfig) -> It<(Natural, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn random_natural_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // --(Natural, Vec) -- struct NaturalBoolVecPairGenerator1 { xs: RandomNaturals>, bs: RandomBools, } impl Iterator for NaturalBoolVecPairGenerator1 { type Item = (Natural, Vec); fn next(&mut self) -> Option<(Natural, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from(x.limb_count())) .collect(); Some((x, bs)) } } pub fn random_natural_bool_vec_pair_gen_var_1(config: &GenConfig) -> It<(Natural, Vec)> { Box::new(NaturalBoolVecPairGenerator1 { xs: random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } struct NaturalBoolVecPairGenerator2 { xs: RandomNaturals>, bs: RandomBools, } impl Iterator for NaturalBoolVecPairGenerator2 { type Item = (Natural, Vec); fn next(&mut self) -> Option<(Natural, Vec)> { let x = self.xs.next().unwrap(); let bs = (&mut self.bs) .take(usize::exact_from(x.significant_bits())) .collect(); Some((x, bs)) } } pub fn random_natural_bool_vec_pair_gen_var_2(config: &GenConfig) -> It<(Natural, Vec)> { Box::new(NaturalBoolVecPairGenerator2 { xs: random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } // -- (Vec, bool) -- pub fn random_unsigned_bool_pair_gen_var_1(config: &GenConfig) -> It<(usize, bool)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_n", 16), config.get_or("mean_d", 1), ) }, &random_bools, ) .filter(|&(n, b)| limbs_odd_factorial_valid(n, b)), ) } // -- (PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 32 are in malachite-base pub fn random_unsigned_pair_gen_var_33(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::exact_from(ODD_FACTORIAL_TABLE_LIMIT + 1), T::MAX, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(n, k)| n >= k), ) } pub fn random_unsigned_pair_gen_var_34(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::TWO, T::wrapping_from(ODD_FACTORIAL_TABLE_LIMIT), config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(n, k)| n >= k), ) } pub fn random_unsigned_pair_gen_var_35(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::from(4u8), T::wrapping_from(ODD_FACTORIAL_EXTTABLE_LIMIT), config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::TWO, T::wrapping_from(ODD_FACTORIAL_EXTTABLE_LIMIT - 2), config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(n, k)| n >= k + T::TWO), ) } pub fn random_unsigned_pair_gen_var_36(config: &GenConfig) -> It<(T, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::wrapping_from((ODD_CENTRAL_BINOMIAL_OFFSET << 1) + 1), T::MAX, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, T::wrapping_from((ODD_CENTRAL_BINOMIAL_OFFSET << 1) - 1), T::wrapping_from(if BIN_UIUI_RECURSIVE_SMALLDC { ODD_CENTRAL_BINOMIAL_TABLE_LIMIT } else { ODD_FACTORIAL_TABLE_LIMIT }) << 1, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(n, k)| n >= k + T::TWO), ) } pub fn random_unsigned_pair_gen_var_37(config: &GenConfig) -> It<(Limb, Limb)> { Box::new( random_pairs_from_single(geometric_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), )) .filter_map(|(mut n, mut k)| { n += u64::wrapping_from(BIN_GOETGHELUCK_THRESHOLD) << 1; k += u64::wrapping_from(BIN_GOETGHELUCK_THRESHOLD); if n >= k + 5 && k > (n >> 4) && n_to_bit(n - k) < n_to_bit(n) && k <= n - k { Some((Limb::exact_from(n), Limb::exact_from(k))) } else { None } }), ) } // var 38 is in malachite-base. // -- (PrimitiveUnsigned * 6) -- pub fn random_unsigned_sextuple_gen_var_1( _config: &GenConfig, ) -> It<(Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| random_pairs_from_single(random_primitive_ints(seed_2)), &|seed_2| { random_pairs( seed_2, &|seed_3| { random_unsigned_inclusive_range( seed_3, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, ) }, &random_primitive_ints, ) }, ) .filter(|&((n_2, n_1), (d_1, d_0))| n_2 < d_1 || n_2 == d_1 && n_1 < d_0) }, &random_primitive_ints, ) .map(|(((n_2, n_1), (d_1, d_0)), n_0)| { ( n_2, n_1, n_0, d_1, d_0, limbs_two_limb_inverse_helper(d_1, d_0), ) }), ) } // -- (String, String, String) -- pub fn random_string_triple_gen_var_1(config: &GenConfig) -> It<(String, String, String)> { Box::new( random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigUint::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } pub fn random_string_triple_gen_var_2(config: &GenConfig) -> It<(String, String, String)> { Box::new( random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigInt::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } // -- Vec -- pub fn random_integer_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } // -- Vec -- pub fn random_natural_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } // -- (Vec, Integer> -- pub fn random_natural_vec_integer_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { random_positive_naturals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Vec, Natural> -- struct LargeDigitsRandomGenerator { bases: RandomNaturalRangeToInfinity, digit_counts: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, } impl Iterator for LargeDigitsRandomGenerator { type Item = (Vec, Natural); fn next(&mut self) -> Option<(Vec, Natural)> { let base = self.bases.next().unwrap(); let bits = base.ceiling_log_base_2(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { loop { let x = get_random_natural_with_up_to_bits(&mut self.xs, bits); if x < base { digits.push(x); break; } } } Some((digits, base)) } } pub fn random_natural_vec_natural_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(LargeDigitsRandomGenerator { bases: random_natural_range_to_infinity( EXAMPLE_SEED.fork("bases"), Natural::power_of_2(Limb::WIDTH), Limb::WIDTH + 4, 1, ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_natural_vec_natural_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(LargeDigitsRandomGenerator { bases: random_natural_range_to_infinity( EXAMPLE_SEED.fork("bases"), Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_natural_vec_natural_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { random_naturals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::power_of_2(Limb::WIDTH), Limb::WIDTH + 4, 1, ) }, )) } pub fn random_natural_vec_natural_pair_gen_var_4( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { random_naturals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Vec, PrimitiveUnsigned) -- struct PowerOf2DigitsGenerator { log_bases: GeometricRandomNaturalValues, digit_counts: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, } impl Iterator for PowerOf2DigitsGenerator { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { digits.push(get_random_natural_with_up_to_bits(&mut self.xs, log_base)); } Some((digits, log_base)) } } pub fn random_natural_vec_unsigned_pair_gen_var_1(config: &GenConfig) -> It<(Vec, u64)> { Box::new(PowerOf2DigitsGenerator { log_bases: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_count"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_natural_vec_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { random_naturals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Vec, PrimitiveUnsigned, Vec) -- struct DigitsRandomGenerator { bases: RandomValuesFromVec, xss: RandomVecs, RandomPrimitiveInts>, outs: RandomPrimitiveInts, } impl Iterator for DigitsRandomGenerator { type Item = (Vec, u64, Vec); fn next(&mut self) -> Option<(Vec, u64, Vec)> { let base = self.bases.next().unwrap(); let xs = self.xss.next().unwrap(); let out_len = usize::exact_from(limbs_digit_count(&xs, base)); let out = (&mut self.outs).take(out_len).collect(); Some((out, base, xs)) } } // -- (Vec, PrimitiveUnsigned, Vec, PrimitiveUnsigned) -- struct BasecaseDigitsRandomGenerator { bases: RandomValuesFromVec, xss: RandomVecs, RandomPrimitiveInts>, excess_lens: RandomOptions>, excess_out_lens: GeometricRandomNaturalValues, outs: RandomPrimitiveInts, } impl Iterator for BasecaseDigitsRandomGenerator { type Item = (Vec, usize, Vec, u64); fn next(&mut self) -> Option<(Vec, usize, Vec, u64)> { let base = self.bases.next().unwrap(); let xs = self.xss.next().unwrap(); let min_out_len = usize::exact_from(limbs_digit_count(&xs, base)); let excess_out_len = self.excess_out_lens.next().unwrap(); let (len, out_len) = if let Some(excess) = self.excess_lens.next().unwrap() { (min_out_len + excess, min_out_len + excess + excess_out_len) } else { (0, min_out_len + excess_out_len) }; let out = (&mut self.outs).take(out_len).collect(); Some((out, len, xs, base)) } } pub fn random_primitive_int_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1< T: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, usize, Vec, u64)> { Box::new(BasecaseDigitsRandomGenerator { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), xss: random_vecs_length_range( EXAMPLE_SEED.fork("xss"), 0, u64::exact_from(GET_STR_PRECOMPUTE_THRESHOLD), &random_primitive_ints, ), excess_lens: random_options( EXAMPLE_SEED.fork("excess_lens"), config.get_or("zero_len_prob_n", 1), config.get_or("zero_len_prob_d", 5), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ) }, ), excess_out_lens: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_out_lens"), config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ), outs: random_primitive_ints(EXAMPLE_SEED.fork("outs")), }) } // -- (Vec, Vec) -- // vars 1 through 8 are in malachite-base. pub fn random_primitive_int_vec_pair_gen_var_9(config: &GenConfig) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator2 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints::(EXAMPLE_SEED.fork("xs")), } .filter(|(xs, ys)| gcd_input_filter(xs, ys)), ) } // vars 10 through 13 are in malachite-base. pub fn random_primitive_int_vec_pair_gen_var_14(config: &GenConfig) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let x_last = xs.last_mut().unwrap(); if *x_last == Limb::MAX { None } else { *x_last += 1; Some(xs) } }), ) .filter_map(|(ns, ds)| { let mut ns = limbs_mul(&ns, &ds); if *ns.last().unwrap() == 0 { ns.pop(); } if *ns.last().unwrap() == 0 { None } else { Some((ns, ds)) } }), ) } // var 15 is in malachite-base. pub fn random_primitive_int_vec_pair_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs( EXAMPLE_SEED.fork("lengths"), &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, SQRLO_DC_THRESHOLD_LIMIT, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, ) .filter(|(x, y)| x >= y), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } fn random_square_helper bool>( config: &GenConfig, valid: &'static F, min_x: usize, ) -> It<(Vec, Vec)> { Box::new(PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_pair_gen_var_17( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &|x| x <= SQR_TOOM2_THRESHOLD, 1) } pub fn random_primitive_int_vec_pair_gen_var_18( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &|_| true, 2) } pub fn random_primitive_int_vec_pair_gen_var_19( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &limbs_square_to_out_toom_3_input_size_valid, 3) } pub fn random_primitive_int_vec_pair_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &limbs_square_to_out_toom_4_input_size_valid, 4) } pub fn random_primitive_int_vec_pair_gen_var_21( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &|x| x == 7 || x == 8 || x > 9, 7) } pub fn random_primitive_int_vec_pair_gen_var_22( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &limbs_square_to_out_toom_6_input_size_valid, 18) } pub fn random_primitive_int_vec_pair_gen_var_23( config: &GenConfig, ) -> It<(Vec, Vec)> { random_square_helper(config, &limbs_square_to_out_toom_8_input_size_valid, 40) } // vars 26 to 27 are in malachite-base. // -- (Vec, Vec, Vec) -- // vars 1 through 3 are in malachite-base fn random_mul_helper bool>( config: &GenConfig, valid: &'static F, min_x: usize, min_y: usize, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x, y)| { let x = x.checked_add(min_x)?; let y = y.checked_add(min_y)?; if valid(usize::exact_from(x), usize::exact_from(y)) { let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_22_input_sizes_valid, 2, 2, ) } pub fn random_primitive_int_vec_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_32_input_sizes_valid, 6, 4, ) } pub fn random_primitive_int_vec_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_33_input_sizes_valid, 3, 3, ) } pub fn random_primitive_int_vec_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_42_input_sizes_valid, 4, 2, ) } pub fn random_primitive_int_vec_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_43_input_sizes_valid, 11, 8, ) } pub fn random_primitive_int_vec_triple_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_44_input_sizes_valid, 4, 4, ) } pub fn random_primitive_int_vec_triple_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_52_input_sizes_valid, 14, 5, ) } pub fn random_primitive_int_vec_triple_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_53_input_sizes_valid, 5, 3, ) } pub fn random_primitive_int_vec_triple_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_54_input_sizes_valid, 14, 11, ) } pub fn random_primitive_int_vec_triple_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_62_input_sizes_valid, 6, 2, ) } pub fn random_primitive_int_vec_triple_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_63_input_sizes_valid, 17, 9, ) } pub fn random_primitive_int_vec_triple_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42, 42, ) } pub fn random_primitive_int_vec_triple_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86, 86, ) } fn random_mul_same_length_helper bool>( config: &GenConfig, valid: &'static F, min_x: usize, ) -> It<(Vec, Vec, Vec)> { Box::new(PrimitiveIntVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux, ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } pub fn random_primitive_int_vec_triple_gen_var_18( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_33_input_sizes_valid, 5, ) } pub fn random_primitive_int_vec_triple_gen_var_19( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42, ) } pub fn random_primitive_int_vec_triple_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86, ) } pub fn random_primitive_int_vec_triple_gen_var_22( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_32_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_43_input_sizes_valid(xs_len, ys_len) }, 11, 8, ) } pub fn random_primitive_int_vec_triple_gen_var_23( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_42_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_53_input_sizes_valid(xs_len, ys_len) }, 5, 3, ) } // vars 24 through 35 are in malachite-base pub fn random_primitive_int_vec_triple_gen_var_36( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter_map(filter_map_helper_3), ) } pub fn random_primitive_int_vec_triple_gen_var_37( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(filter_helper_3), ) } // var 39 through 44 are in malachite-base. pub fn random_primitive_int_vec_triple_gen_var_45( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { random_mul_helper( config, &|x, y| { limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) && limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) }, 7, 7, ) } // var 46 is in malachite-base. // -- (Vec, Vec, PrimitiveUnsigned) -- struct BasecaseDigitsRandomGenerator1 { bases: RandomValuesFromVec, digit_counts: GeometricRandomNaturalValues, base_to_digits: HashMap>, excess_limb_counts: GeometricRandomNaturalValues, outs: RandomPrimitiveInts, } impl Iterator for BasecaseDigitsRandomGenerator1 { type Item = (Vec, Vec, u64); fn next(&mut self) -> Option<(Vec, Vec, u64)> { let base = self.bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let ds = self.base_to_digits.entry(base).or_insert_with(move || { random_unsigneds_less_than(EXAMPLE_SEED.fork(&base.to_string()), T::wrapping_from(base)) }); let digits = ds.take(digit_count).collect(); let min_limb_count = limbs_per_digit_in_base(digit_count, base); let out = (&mut self.outs) .take(usize::exact_from(min_limb_count) + self.excess_limb_counts.next().unwrap()) .collect(); Some((out, digits, base)) } } pub fn random_primitive_int_vec_unsigned_vec_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new(BasecaseDigitsRandomGenerator1 { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), digit_counts: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), excess_limb_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_limb_count"), config.get_or("excess_limb_count_n", 4), config.get_or("excess_limb_count_d", 1), ), outs: random_primitive_ints(EXAMPLE_SEED.fork("outs")), base_to_digits: HashMap::new(), }) } struct BasecaseDigitsRandomGenerator2 { bases: RandomValuesFromVec, digit_counts: GeometricRandomNaturalValues, base_to_digits: HashMap>, excess_limb_counts: GeometricRandomNaturalValues, outs: RandomPrimitiveInts, } impl Iterator for BasecaseDigitsRandomGenerator2 { type Item = (Vec, Vec, u64); fn next(&mut self) -> Option<(Vec, Vec, u64)> { let base = self.bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let ds = self .base_to_digits .entry(base) .or_insert_with(move || random_primitive_ints(EXAMPLE_SEED.fork(&base.to_string()))); let digits = ds.take(digit_count).collect(); let min_limb_count = limbs_per_digit_in_base(digit_count, base); let out = (&mut self.outs) .take(usize::exact_from(min_limb_count) + self.excess_limb_counts.next().unwrap()) .collect(); Some((out, digits, base)) } } pub fn random_primitive_int_vec_unsigned_vec_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new(BasecaseDigitsRandomGenerator2 { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), digit_counts: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), excess_limb_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_limb_count"), config.get_or("excess_limb_count_n", 4), config.get_or("excess_limb_count_d", 1), ), outs: random_primitive_ints(EXAMPLE_SEED.fork("outs")), base_to_digits: HashMap::new(), }) } // -- Vec -- pub fn random_unsigned_vec_gen_var_1(config: &GenConfig) -> It> { Box::new( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .map(|mut xs| { limbs_vec_mul_limb_in_place(&mut xs, 3); xs }), ) } // -- (Vec, PrimitiveUnsigned) -- // vars 1 through 7 are in malachite-base pub fn random_unsigned_vec_unsigned_pair_gen_var_8< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, T::TWO, T::saturating_from(U::MAX)), )) } pub fn random_unsigned_vec_unsigned_pair_gen_var_9(config: &GenConfig) -> It<(Vec, u64)> { Box::new( random_primitive_int_vec_unsigned_pair_gen_var_10(config).filter(|(xs, index)| { let mut mut_xs = xs.clone(); limbs_vec_clear_bit_neg(&mut mut_xs, *index); mut_xs.len() == xs.len() }), ) } pub fn random_unsigned_vec_unsigned_pair_gen_var_10(config: &GenConfig) -> It<(Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_positive_unsigneds, ) .map(|(mut xs, y)| { limbs_vec_mul_limb_in_place(&mut xs, y); (xs, y) }), ) } pub fn random_unsigned_vec_unsigned_pair_gen_var_11(config: &GenConfig) -> It<(Vec, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(mut xs, mut pow)| { let xs_last = xs.last_mut().unwrap(); *xs_last = xs_last.checked_add(1)?; pow += limbs_significant_bits_helper(&xs); Some((xs, pow)) }), ) } // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ) .filter(|(m, x, y)| { !Integer::from(Natural::from(*x)).eq_mod(-Natural::from(*y), Natural::from_limbs_asc(m)) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_values_from_vec(seed, factors_of_limb_max()), &random_primitive_ints, )) } // var 3 is in malachite-base. pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_primitive_ints, &random_positive_unsigneds, ) .map(map_helper_3), ) } pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_primitive_ints, &random_positive_unsigneds, ) .filter(filter_helper_6), ) } pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &random_primitive_ints::, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); if pow == 0 { pow = 1; } (xs, y, pow) }), ) } // -- (Vec, PrimitiveUnsigned, Vec) -- pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, u64, Vec)> { Box::new(DigitsRandomGenerator { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), xss: random_vecs( EXAMPLE_SEED.fork("xss"), &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), outs: random_primitive_ints(EXAMPLE_SEED.fork("bytes")), }) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ))) .filter_map(filter_map_helper_1), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ))) .filter(filter_helper_1), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ))) .map(map_helper_1), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ))) .filter(filter_helper_4), ) } // -- (Vec, Vec) -- // vars 1 through 2 are in malachite-base. pub fn random_unsigned_vec_pair_gen_var_3(config: &GenConfig) -> It<(Vec, Vec)> { Box::new( PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter_map(|(out, mut xs)| { limbs_vec_mul_limb_in_place(&mut xs, 3); if out.len() >= xs.len() { Some((out, xs)) } else { None } }), ) } pub fn random_unsigned_vec_pair_gen_var_4(config: &GenConfig) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single(random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(ns, mut ds)| { let d_last = ds.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_ns = limbs_mul(&ns, &ds); if *new_ns.last().unwrap() == 0 { new_ns.pop(); } (new_ns, ds) }), ) } // var 5 is in malachite-base. // -- (Vec, Vec, PrimitiveUnsigned) -- // var 1 is in malachite-base. pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ) .filter_map(filter_map_helper_2), ) } pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ) .filter(filter_helper_2), ) } pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( seed.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }, &random_positive_unsigneds, ) .filter_map(|((out, mut xs), y)| { limbs_vec_mul_limb_in_place(&mut xs, y); if out.len() >= xs.len() { Some((out, xs, y)) } else { None } }), ) } pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ) .map(map_helper_2), ) } pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &random_positive_unsigneds, ) .filter(filter_helper_5), ) } pub fn random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; if n_len > d_init_len { Some((n_len, d_init_len)) } else { None } }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_unsigned_inclusive_range(seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX) }, ) .map(|((n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (n, d_init, inverse) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|((xs, ys), mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(1)?; Some(xs) }) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 1, &random_primitive_ints::, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 4), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(mut xs, mut es, pow)| { let last_e = es.last_mut().unwrap(); *last_e = last_e.checked_add(1)?; if es == [1] { return None; } limbs_slice_mod_power_of_2_in_place(&mut xs, pow); if *xs.last().unwrap() == 0 { None } else { Some((xs, es, pow)) } }), ) } // -- (Vec, Vec, Vec) -- pub fn random_unsigned_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(2)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_unsigned_inclusive_range(seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn random_unsigned_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len > d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_unsigned_inclusive_range(seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn random_unsigned_vec_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(_, _, d)| *d.last().unwrap() != 0), ) } pub fn random_unsigned_vec_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len && n_len < (d_len - 1) << 1 { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(_, _, d)| *d.last().unwrap() != 0), ) } pub fn random_unsigned_vec_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single( geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), ) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; (q, n, d) }), ) } pub fn random_unsigned_vec_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single( geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), ) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; (q, n, d) }), ) } pub fn random_unsigned_vec_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single( geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), ) .filter_map(|(q_len, n_len, d_len)| { if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter_map(|(q, n, mut d): (Vec, Vec, Vec)| { let d_last = d.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() + d.len() >= new_n.len() + 1 { Some((q, new_n, d)) } else { None } }), ) } pub fn random_unsigned_vec_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single( geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), ) .filter_map(|(q_len, n_len, mut d_len)| { d_len = d_len.checked_add(1)?; if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter_map(|(q, n, mut d): (Vec, Vec, Vec)| { let d_last = d.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() > new_n.len() - d.len() { Some((q, n, d)) } else { None } }), ) } // vars 9 through 10 are in malachite-base. pub fn random_unsigned_vec_triple_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .map(|(xs, ys, m)| limbs_eq_mod_map(&xs, ys, m)), ) } pub fn random_unsigned_vec_triple_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( random_vecs_min_length( EXAMPLE_SEED, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(|(xs, ys, m)| !limbs_eq_mod_ref_ref_ref(xs, ys, m)), ) } pub fn random_unsigned_vec_triple_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len): (usize, usize)| { Some((q_len.checked_add(n_len)?, n_len.checked_add(2)?)) }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_pairs( seed, &|seed_2| { random_unsigned_inclusive_range( seed_2, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, ) }, &random_primitive_ints, ) }, ) .map(|((q, n), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // -- (Vec * 4) -- #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, r, mut d)| { let last_d = d.last_mut().unwrap(); if *last_d == 0 { *last_d = 1; } (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(2)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, r, mut d)| { d[0] |= 1; (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(4)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, r, mut d)| { d[0] |= 1; (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len && (d_len << 1) > n_len + 1 { Some((q_len, r_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, r, mut d)| { let last_d = d.last_mut().unwrap(); if *last_d == 0 { *last_d = 1; } (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(3)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len > d_len && q_len + d_len >= n_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map( |(q, n, r, mut d): (Vec, Vec, Vec, Vec)| { d.last_mut().unwrap().set_bit(Limb::WIDTH - 1); (q, n, r, d) }, ), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( PrimitiveIntVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(out_len, mut b_len, e_len, mut m_len)| { b_len = b_len.checked_add(1)?; m_len = m_len.checked_add(1)?; if out_len >= m_len { Some((out_len, b_len, e_len, m_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .filter(|(_, bs, es, ms)| { (es.len() > 1 || es.len() == 1 && es[0] > 1) && *bs.last().unwrap() != 0 && *es.last().unwrap() != 0 && *ms.last().unwrap() != 0 }), ) } #[allow(clippy::type_complexity)] pub fn random_unsigned_vec_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( random_unsigned_vec_quadruple_gen_var_6(config).map(|(out, bs, es, mut ms)| { ms[0] |= 1; (out, bs, es, ms) }), ) } // -- large types -- // vars 1 through 4 are in malachite-base fn random_half_gcd_matrix( s: usize, n: usize, xs: &mut RandomPrimitiveInts, ) -> OwnedHalfGcdMatrix { assert!(s >= n); let mut m00 = xs.take(n).collect_vec(); let m01 = xs.take(n).collect_vec(); let m10 = xs.take(n).collect_vec(); let m11 = xs.take(n).collect_vec(); m00.resize(s << 2, 0); m00[s..s + n].copy_from_slice(&m01); m00[s << 1..(s << 1) + n].copy_from_slice(&m10); m00[s * 3..s * 3 + n].copy_from_slice(&m11); half_gcd_matrix_create(s, n, m00) } struct HalfGcdMatrixAndVecGenerator { sizes: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, bs: RandomBools, } impl Iterator for HalfGcdMatrixAndVecGenerator { type Item = (OwnedHalfGcdMatrix, Vec, u8); fn next(&mut self) -> Option { loop { let x = self.sizes.next().unwrap(); let qs_len = x.checked_add(1); let qs_len = if let Some(qs_len) = qs_len { qs_len } else { continue; }; let y = self.sizes.next().unwrap(); let m_n = qs_len.checked_add(y); let m_n = if let Some(m_n) = m_n { m_n } else { continue }; let z = self.sizes.next().unwrap(); let m_s = m_n.checked_add(z); let m_s = if let Some(m_s) = m_s { m_s } else { continue }; let m_s_1 = m_s.checked_add(2); let m_s_1 = if let Some(m_s_1) = m_s_1 { m_s_1 } else { continue; }; let m_s_2 = m_s.checked_add(qs_len); let m_s_2 = if let Some(m_s_2) = m_s_2 { m_s_2 } else { continue; }; let m_s = max(m_s_1, m_s_2); let m = random_half_gcd_matrix(m_s, m_n, &mut self.xs); let qs = (&mut self.xs).take(qs_len).collect_vec(); let column = u8::from(self.bs.next().unwrap()); return Some((m, qs, column)); } } } pub fn random_large_type_gen_var_5(config: &GenConfig) -> It<(OwnedHalfGcdMatrix, Vec, u8)> { Box::new(HalfGcdMatrixAndVecGenerator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_6( config: &GenConfig, ) -> It<(HalfGcdMatrix1, Vec, Vec, Vec)> { reshape_1_3_to_4(Box::new( random_quadruples_from_single(random_primitive_ints(EXAMPLE_SEED.fork("m"))) .map(|(m00, m01, m10, m11)| HalfGcdMatrix1 { data: [[m00, m01], [m10, m11]], }) .zip(PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let xs_len = x; let ys_len = x.checked_add(1)?.checked_add(y)?; let out_len = x.checked_add(1)?.checked_add(z)?; Some((out_len, xs_len, ys_len)) }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }), )) } struct HalfGcdMatrixAndHalfGcdMatrix1Generator { sizes: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, small_xs: RandomUnsignedBitChunks, } impl Iterator for HalfGcdMatrixAndHalfGcdMatrix1Generator { type Item = (OwnedHalfGcdMatrix, HalfGcdMatrix1); fn next(&mut self) -> Option { loop { let x = self.sizes.next().unwrap(); let n = x.checked_add(1); let n = if let Some(n) = n { n } else { continue }; let y = self.sizes.next().unwrap(); let s = n.checked_add(y); let s = if let Some(s) = s { s } else { continue }; let s = s.checked_add(1); let s = if let Some(s) = s { s } else { continue }; let m = random_half_gcd_matrix(s, n, &mut self.xs); let m_1 = HalfGcdMatrix1 { data: [ [self.small_xs.next().unwrap(), self.small_xs.next().unwrap()], [self.small_xs.next().unwrap(), self.small_xs.next().unwrap()], ], }; return Some((m, m_1)); } } } pub fn random_large_type_gen_var_7(config: &GenConfig) -> It<(OwnedHalfGcdMatrix, HalfGcdMatrix1)> { Box::new(HalfGcdMatrixAndHalfGcdMatrix1Generator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), small_xs: random_unsigned_bit_chunks(EXAMPLE_SEED.fork("small_xs"), Limb::WIDTH - 1), }) } struct MatrixMul22Generator { sizes: GeometricRandomNaturalValues, xs: RandomPrimitiveInts, } impl Iterator for MatrixMul22Generator { type Item = T8; fn next(&mut self) -> Option { let ys_len = self.sizes.next().unwrap(); let xs_len = self.sizes.next().unwrap(); let sum = ys_len + xs_len + 1; Some(( (&mut self.xs).take(sum).collect_vec(), (&mut self.xs).take(sum).collect_vec(), (&mut self.xs).take(sum).collect_vec(), (&mut self.xs).take(sum).collect_vec(), xs_len, (&mut self.xs).take(ys_len).collect_vec(), (&mut self.xs).take(ys_len).collect_vec(), (&mut self.xs).take(ys_len).collect_vec(), (&mut self.xs).take(ys_len).collect_vec(), )) } } pub fn random_large_type_gen_var_8(config: &GenConfig) -> It { Box::new(MatrixMul22Generator { sizes: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), }) } // var 9 is in malachite-base. pub fn random_large_type_gen_var_10(config: &GenConfig) -> It<(Vec, Vec, Limb, Limb)> { reshape_2_2_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_pairs( seed, &|seed_2| random_values_from_vec(seed_2, factors_of_limb_max()), &random_primitive_ints, ) }, ))) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_unsigned_inclusive_range(seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_init_len)| { q_len = q_len.checked_add(3)?; n_len = n_len.checked_add(9)?; d_init_len = d_init_len.checked_add(5)?; let d_len = d_init_len + 1; if n_len >= d_len + 3 && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), xs: random_primitive_ints(seed.fork("xs")), }, &|seed| { random_unsigned_inclusive_range(seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( PrimitiveIntVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, usize::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), xs: random_primitive_ints(EXAMPLE_SEED.fork("xs")), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_17( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( random_vecs_min_length( EXAMPLE_SEED, 1, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .map(|mut d| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); let is = vec![0; d.len()]; let scratch = vec![0; limbs_modular_invert_scratch_len(d.len())]; (is, scratch, d, inverse) }), ) } pub fn random_large_type_gen_var_18(config: &GenConfig) -> It<(Vec, usize, Limb, Limb, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_positive_unsigneds, ) .filter_map(|(ns, fraction_len, d)| { if ns.len() <= fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((ns, fraction_len, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_19( config: &GenConfig, ) -> It<(Vec, usize, Vec, Limb, Limb, u64)> { Box::new( random_quadruples_xyxz( EXAMPLE_SEED, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_positive_unsigneds, ) .filter_map(|(out, fraction_len, ns, d)| { if ns.is_empty() || out.len() < ns.len() + fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((out, fraction_len, ns, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec, usize, usize)> { Box::new( random_quintuples_xyyyz( EXAMPLE_SEED, &|seed| { random_vecs_min_length( seed, 2, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { random_vecs( seed, &random_primitive_ints, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 3, u32::MAX, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(ds, mut scratch, mut qs, mut rs_hi, n_len)| { let n_len = usize::wrapping_from(n_len); let d_len = ds.len(); if n_len < d_len { return None; } let i_len = limbs_div_mod_barrett_is_len(n_len - d_len, d_len); if i_len == 0 || qs.len() < i_len { return None; } qs.truncate(i_len); if rs_hi.len() < i_len { return None; } rs_hi.truncate(i_len); let scratch_len = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); let x = limbs_div_mod_barrett_scratch_len(n_len, d_len); if x < i_len { return None; } let actual_scratch_len = x - i_len; if actual_scratch_len < d_len + i_len { return None; } if scratch.len() < actual_scratch_len { return None; } scratch.truncate(actual_scratch_len); Some((scratch, ds, qs, rs_hi, scratch_len, i_len)) }), ) } #[allow(clippy::type_complexity)] pub fn random_large_type_gen_var_21( _config: &GenConfig, ) -> It<(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( random_sextuples_from_single(random_primitive_ints(EXAMPLE_SEED)) .filter_map(large_type_filter_map_1), ) } // var 22 is in malachite-base. struct RationalFromPowerOf2DigitsGenerator { log_bases: GeometricRandomNaturalValues, sizes: GeometricRandomNaturalValues, xs_map: HashMap, } impl Iterator for RationalFromPowerOf2DigitsGenerator { type Item = (u64, Vec, RationalSequence); fn next(&mut self) -> Option<(u64, Vec, RationalSequence)> { let log_base = self.log_bases.next().unwrap(); let xs = self.xs_map.entry(log_base).or_insert_with(|| { let seed = EXAMPLE_SEED.fork(&log_base.to_string()); random_naturals_less_than(seed, Natural::power_of_2(log_base)) }); let before_point = xs.take(self.sizes.next().unwrap()).collect(); let non_repeating = xs.take(self.sizes.next().unwrap()).collect(); let repeating = xs.take(self.sizes.next().unwrap()).collect(); Some(( log_base, before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn random_large_type_gen_var_23( config: &GenConfig, ) -> It<(u64, Vec, RationalSequence)> { Box::new(RationalFromPowerOf2DigitsGenerator { log_bases: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs_map: HashMap::new(), }) } struct RationalFromPowerOf2DigitsBinaryGenerator { sizes: GeometricRandomNaturalValues, bits: RandomBools, } impl Iterator for RationalFromPowerOf2DigitsBinaryGenerator { type Item = (Vec, RationalSequence); fn next(&mut self) -> Option<(Vec, RationalSequence)> { let before_point = (&mut self.bits) .map(Natural::from) .take(self.sizes.next().unwrap()) .collect(); let non_repeating = (&mut self.bits) .map(Natural::from) .take(self.sizes.next().unwrap()) .collect(); let repeating = (&mut self.bits) .map(Natural::from) .take(self.sizes.next().unwrap()) .collect(); Some(( before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn random_large_type_gen_var_24( config: &GenConfig, ) -> It<(Vec, RationalSequence)> { Box::new(RationalFromPowerOf2DigitsBinaryGenerator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), bits: random_bools(EXAMPLE_SEED.fork("bits")), }) } struct RationalFromDigitsGenerator { bases: RandomNaturalRangeToInfinity, sizes: GeometricRandomNaturalValues, xs_map: HashMap, } impl Iterator for RationalFromDigitsGenerator { type Item = (Natural, Vec, RationalSequence); fn next(&mut self) -> Option<(Natural, Vec, RationalSequence)> { let base = self.bases.next().unwrap(); let xs = self.xs_map.entry(base.clone()).or_insert_with(|| { let seed = EXAMPLE_SEED.fork(&base.to_string()); random_naturals_less_than(seed, base.clone()) }); let before_point = xs.take(self.sizes.next().unwrap()).collect(); let non_repeating = xs.take(self.sizes.next().unwrap()).collect(); let repeating = xs.take(self.sizes.next().unwrap()).collect(); Some(( base, before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn random_large_type_gen_var_25( config: &GenConfig, ) -> It<(Natural, Vec, RationalSequence)> { Box::new(RationalFromDigitsGenerator { bases: random_natural_range_to_infinity( EXAMPLE_SEED, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs_map: HashMap::new(), }) } struct RationalFromDigitsDecimalGenerator { sizes: GeometricRandomNaturalValues, digits: RandomNaturalsLessThan, } impl Iterator for RationalFromDigitsDecimalGenerator { type Item = (Vec, RationalSequence); fn next(&mut self) -> Option<(Vec, RationalSequence)> { let before_point = (&mut self.digits) .take(self.sizes.next().unwrap()) .collect(); let non_repeating = (&mut self.digits) .take(self.sizes.next().unwrap()) .collect(); let repeating = (&mut self.digits) .take(self.sizes.next().unwrap()) .collect(); Some(( before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn random_large_type_gen_var_26( config: &GenConfig, ) -> It<(Vec, RationalSequence)> { Box::new(RationalFromDigitsDecimalGenerator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), digits: random_naturals_less_than(EXAMPLE_SEED.fork("digits"), Natural::from(10u32)), }) } ================================================ FILE: malachite-nz/src/test_util/generators/special_random.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::integer::logic::bit_access::limbs_vec_clear_bit_neg; use crate::integer::random::{ StripedRandomIntegers, striped_random_integers, striped_random_natural_integers, striped_random_negative_integers, striped_random_nonzero_integers, }; use crate::natural::arithmetic::div_exact::{ limbs_modular_invert_limb, limbs_modular_invert_scratch_len, }; use crate::natural::arithmetic::div_mod::{ limbs_div_mod_barrett_is_len, limbs_div_mod_barrett_scratch_len, limbs_invert_limb, limbs_two_limb_inverse_helper, }; use crate::natural::arithmetic::eq_mod::limbs_eq_mod_ref_ref_ref; use crate::natural::arithmetic::gcd::half_gcd::HalfGcdMatrix1; use crate::natural::arithmetic::mod_power_of_2::limbs_slice_mod_power_of_2_in_place; use crate::natural::arithmetic::mod_power_of_2_square::SQRLO_DC_THRESHOLD_LIMIT; use crate::natural::arithmetic::mul::limb::limbs_vec_mul_limb_in_place; use crate::natural::arithmetic::mul::limbs_mul; use crate::natural::arithmetic::mul::mul_mod::limbs_mul_mod_base_pow_n_minus_1_next_size; use crate::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h_input_sizes_valid, limbs_mul_greater_to_out_toom_8h_input_sizes_valid, limbs_mul_greater_to_out_toom_22_input_sizes_valid, limbs_mul_greater_to_out_toom_32_input_sizes_valid, limbs_mul_greater_to_out_toom_33_input_sizes_valid, limbs_mul_greater_to_out_toom_42_input_sizes_valid, limbs_mul_greater_to_out_toom_43_input_sizes_valid, limbs_mul_greater_to_out_toom_44_input_sizes_valid, limbs_mul_greater_to_out_toom_52_input_sizes_valid, limbs_mul_greater_to_out_toom_53_input_sizes_valid, limbs_mul_greater_to_out_toom_54_input_sizes_valid, limbs_mul_greater_to_out_toom_62_input_sizes_valid, limbs_mul_greater_to_out_toom_63_input_sizes_valid, }; use crate::natural::arithmetic::square::{ limbs_square_to_out_toom_3_input_size_valid, limbs_square_to_out_toom_4_input_size_valid, limbs_square_to_out_toom_6_input_size_valid, limbs_square_to_out_toom_8_input_size_valid, }; use crate::natural::conversion::digits::general_digits::{ GET_STR_PRECOMPUTE_THRESHOLD, limbs_digit_count, limbs_per_digit_in_base, }; use crate::natural::random::{ StripedRandomNaturalInclusiveRange, StripedRandomNaturalRangeToInfinity, StripedRandomNaturals, get_striped_random_natural_with_bits, get_striped_random_natural_with_up_to_bits, striped_random_natural_range, striped_random_natural_range_to_infinity, striped_random_naturals, striped_random_positive_naturals, }; use crate::natural::{Natural, limb_to_bit_count}; use crate::platform::{DoubleLimb, Limb, SQR_TOOM2_THRESHOLD}; use crate::test_util::extra_variadic::{ random_quadruples_from_single, random_quadruples_xxxy, random_quadruples_xyxz, random_quadruples_xyyx, random_quadruples_xyyz, random_quintuples_xyyyz, random_sextuples_from_single, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyx, random_triples_xyy, }; use crate::test_util::generators::exhaustive::{ filter_helper_1, filter_helper_2, filter_helper_3, filter_helper_4, filter_helper_5, filter_helper_6, filter_map_helper_1, filter_map_helper_2, filter_map_helper_3, gcd_input_filter, large_type_filter_map_1, limbs_eq_mod_map, limbs_significant_bits_helper, map_helper_1, map_helper_2, map_helper_3, round_to_multiple_integer_filter_map, round_to_multiple_natural_filter_map, }; use crate::test_util::generators::{T8, factors_of_limb_max}; use crate::test_util::natural::arithmetic::gcd::{OwnedHalfGcdMatrix, half_gcd_matrix_create}; use malachite_base::bools::random::{RandomBools, random_bools}; use malachite_base::iterators::with_special_value; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, CeilingLogBase2, CoprimeWith, DivRound, DivisibleBy, DivisibleByPowerOf2, EqMod, EqModPowerOf2, Parity, PowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::random::random_to_sci_options; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, SaturatingFrom, ToSci, WrappingFrom, }; use malachite_base::num::logic::traits::{ BitAccess, BitConvertible, LeadingZeros, SignificantBits, }; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, GeometricRandomSignedRange, GeometricRandomSigneds, geometric_random_positive_unsigneds, geometric_random_signed_range, geometric_random_signeds, geometric_random_unsigned_inclusive_range, geometric_random_unsigneds, }; use malachite_base::num::random::striped::{ StripedBitSource, StripedRandomUnsignedBitChunks, StripedRandomUnsignedVecs, get_striped_bool_vec, get_striped_unsigned_vec, striped_random_natural_signeds, striped_random_positive_unsigneds, striped_random_signeds, striped_random_unsigned_bit_chunks, striped_random_unsigned_inclusive_range, striped_random_unsigned_vecs, striped_random_unsigned_vecs_length_range, striped_random_unsigned_vecs_min_length, striped_random_unsigneds, }; use malachite_base::num::random::{ RandomUnsignedRange, RandomUnsignedsLessThan, random_primitive_floats, random_unsigneds_less_than, }; use malachite_base::options::random::{RandomOptions, random_options}; use malachite_base::random::{EXAMPLE_SEED, Seed}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{ GenConfig, It, permute_1_3_2, reshape_1_3_to_4, reshape_2_1_to_3, reshape_2_2_to_4, }; use malachite_base::test_util::generators::random::get_two_highest; use malachite_base::test_util::generators::special_random::{ UnsignedVecPairLenGenerator1, UnsignedVecPairLenGenerator2, UnsignedVecQuadrupleLenGenerator1, UnsignedVecTripleLenGenerator1, UnsignedVecTripleXYYLenGenerator, special_random_unsigned_vec_unsigned_pair_gen_var_17, }; use malachite_base::tuples::random::{ random_ordered_unique_pairs, random_pairs, random_pairs_from_single, }; use malachite_base::unions::Union2; use malachite_base::unions::random::random_union2s; use malachite_base::vecs::random::random_vecs; use malachite_base::vecs::{RandomValuesFromVec, random_values_from_vec}; use num::{BigInt, BigUint}; use std::cmp::{Ordering::*, max}; use std::collections::HashMap; use std::marker::PhantomData; use std::ops::{Shl, Shr}; // -- Integer -- pub fn special_random_integer_gen(config: &GenConfig) -> It { Box::new(striped_random_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_integer_gen_var_1(config: &GenConfig) -> It { Box::new(with_special_value( EXAMPLE_SEED, Integer::ZERO, 1, 100, &|seed| { random_pairs( seed, &|seed_2| { special_random_positive_float_naturals::( seed_2, 0, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)) }, )) } pub fn special_random_integer_gen_var_2 ExactFrom<&'a Natural> + PrimitiveFloat>( config: &GenConfig, ) -> It where Natural: ExactFrom, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { special_random_positive_float_naturals::( seed, 1, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) .filter_map(|a| { let b = Natural::exact_from(T::exact_from(&a).next_higher()); let diff = b - &a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn special_random_integer_gen_var_3(config: &GenConfig) -> It { Box::new(striped_random_natural_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_integer_gen_var_4(config: &GenConfig) -> It where Integer: From, { Box::new( striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(Integer::from), ) } pub fn special_random_integer_gen_var_5(config: &GenConfig) -> It where Integer: From, { Box::new( striped_random_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(Integer::from), ) } pub fn special_random_integer_gen_var_6(config: &GenConfig) -> It { Box::new(striped_random_negative_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_integer_gen_var_7(config: &GenConfig) -> It { Box::new(striped_random_nonzero_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_integer_gen_var_8(config: &GenConfig) -> It where for<'a> T: ConvertibleFrom<&'a Natural>, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::power_of_2(T::MANTISSA_WIDTH + 1) | Natural::ONE, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", Limb::WIDTH << 1), config.get_or("mean_bits_d", 1), ) .filter(|n| !T::convertible_from(n)) }, &random_bools, ) .map(|(n, b)| Integer::from_sign_and_abs(b, n)), ) } pub fn special_random_integer_gen_var_9(config: &GenConfig) -> It { Box::new( striped_random_natural_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Integer::ONE), ) } // -- (Integer, Integer) -- pub fn special_random_integer_pair_gen(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs_from_single(striped_random_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_integer_pair_gen_var_1(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_integer_pair_gen_var_2(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y)| (x * &y, y)), ) } pub fn special_random_integer_pair_gen_var_3(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn special_random_integer_pair_gen_var_4(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, n)| (a, (n << 1u32) | Integer::ONE)), ) } pub fn special_random_integer_pair_gen_var_5(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs_from_single(striped_random_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn special_random_integer_pair_gen_var_6(config: &GenConfig) -> It<(Integer, Integer)> { Box::new( random_pairs_from_single( striped_random_natural_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Integer::ONE), ) .filter(|(x, y)| x.unsigned_abs_ref().coprime_with(y.unsigned_abs_ref())), ) } pub fn special_random_integer_pair_gen_var_7(config: &GenConfig) -> It<(Integer, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Integer::from) }, )) } // -- (Integer, Integer, Integer) -- pub fn special_random_integer_triple_gen(config: &GenConfig) -> It<(Integer, Integer, Integer)> { Box::new(random_triples_from_single(striped_random_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_integer_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, Integer)> { Box::new(random_triples_from_single(striped_random_natural_integers( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_integer_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, Integer)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, b, n)| (a, b, (n << 1u32) | Integer::ONE)), ) } pub fn special_random_integer_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, Integer, Integer)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(a, m, n)| (a, (m << 1u32) | Integer::ONE, (n << 1u32) | Integer::ONE)), ) } // -- (Integer, Integer, Integer, PrimitiveUnsigned) -- pub fn special_random_integer_integer_integer_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, Integer, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, Integer, Natural) -- pub fn special_random_integer_integer_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_integer_integer_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y, m)| (x * Integer::from(&m) + &y, y, m)), ) } pub fn special_random_integer_integer_natural_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, Natural)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y, m)| !x.eq_mod(y, m)), ) } // -- (Integer, Integer, PrimitiveFloat) -- pub fn special_random_integer_integer_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Integer, Integer, PrimitiveSigned) -- pub fn special_random_integer_integer_signed_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Integer, Integer, PrimitiveUnsigned) -- pub fn special_random_integer_integer_unsigned_triple_gen( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_integer_integer_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_integer_integer_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, T)> where Integer: Shl, { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn special_random_integer_integer_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, Integer, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } // -- (Integer, Integer, RoundingMode) -- pub fn special_random_integer_integer_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, Integer, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub fn special_random_integer_integer_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, Integer, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_integer_filter_map(x, y, rm)), ) } // -- (Integer, Natural) -- pub fn special_random_integer_natural_pair_gen(config: &GenConfig) -> It<(Integer, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, Natural, Natural) -- pub fn special_random_integer_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, PrimitiveFloat) -- pub fn special_random_integer_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Integer, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_integer_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Integer, PrimitiveSigned) -- pub fn special_random_integer_signed_pair_gen( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_integer_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveSigned, PrimitiveSigned) --- pub fn special_random_integer_signed_signed_triple_gen( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Integer, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_integer_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Integer, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveSigned, RoundingMode) -- pub fn special_random_integer_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shr, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn special_random_integer_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Integer, PrimitiveUnsigned) -- pub fn special_random_integer_unsigned_pair_gen( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_integer_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_bits_n", T::WIDTH >> 1), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_integer_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_integer_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_natural_integers( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_negative_integers( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_integer_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed_2| { striped_random_integers( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn special_random_integer_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Integer, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn special_random_integer_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Integer, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveUnsigned, bool) -- pub fn special_random_integer_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, T, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_bools, )) } // -- (Integer, PrimitiveUnsigned, Natural) -- pub fn special_random_integer_unsigned_natural_triple_gen( config: &GenConfig, ) -> It<(Integer, T, Natural)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_integer_unsigned_unsigned_triple_gen( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_integer_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Integer, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_bits_n", T::WIDTH >> 1), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_integer_unsigned_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn special_random_integer_unsigned_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Integer, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Integer, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn special_random_integer_unsigned_unsigned_natural_quadruple_gen_var_1< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Integer, T, T, Natural)> { Box::new( random_quadruples_xyyz( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // -- (Integer, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_integer_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Integer, u64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } pub fn special_random_integer_unsigned_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> where Integer: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| (if rm == Exact { n << u } else { n }, u, rm)), ) } // vars 4 and 5 are in malachite-float. pub fn special_random_integer_unsigned_rounding_mode_triple_gen_var_5( config: &GenConfig, ) -> It<(Integer, T, RoundingMode)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, )) } // -- (Integer, RoundingMode) -- pub fn special_random_integer_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(Integer, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_integer_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Integer> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Integer, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn special_random_integer_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Integer, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } // -- (Integer, ToSciOptions) -- pub fn special_random_integer_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(Integer, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn special_random_integer_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // --(Integer, Vec) -- struct IntegerBoolVecPairGenerator1 { xs: StripedRandomIntegers>, striped_bit_source: StripedBitSource, } impl Iterator for IntegerBoolVecPairGenerator1 { type Item = (Integer, Vec); fn next(&mut self) -> Option<(Integer, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec( &mut self.striped_bit_source, u64::exact_from(x.to_twos_complement_limbs_asc().len()), ); Some((x, bs)) } } pub fn special_random_integer_bool_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(Integer, Vec)> { Box::new(IntegerBoolVecPairGenerator1 { xs: striped_random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } struct IntegerBoolVecPairGenerator2 { xs: StripedRandomIntegers>, striped_bit_source: StripedBitSource, } impl Iterator for IntegerBoolVecPairGenerator2 { type Item = (Integer, Vec); fn next(&mut self) -> Option<(Integer, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec( &mut self.striped_bit_source, u64::exact_from(x.to_bits_asc().len()), ); Some((x, bs)) } } pub fn special_random_integer_bool_vec_pair_gen_var_2( config: &GenConfig, ) -> It<(Integer, Vec)> { Box::new(IntegerBoolVecPairGenerator2 { xs: striped_random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } // -- Natural -- pub fn special_random_natural_gen(config: &GenConfig) -> It { Box::new(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_natural_gen_var_1(config: &GenConfig) -> It { Box::new(striped_random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } struct SpecialRandomPositiveFloatNaturals { exponents: GeometricRandomSignedRange, mantissas: StripedRandomUnsignedBitChunks, phantom: PhantomData, } impl Iterator for SpecialRandomPositiveFloatNaturals { type Item = Natural; fn next(&mut self) -> Option { let exponent = self.exponents.next().unwrap(); let mut mantissa = self.mantissas.next().unwrap(); if exponent != 0 { mantissa.set_bit(T::MANTISSA_WIDTH); } else if mantissa == 0 { mantissa = 1; } Some(Natural::from(mantissa) << exponent) } } fn special_random_positive_float_naturals( seed: Seed, start_exponent: i64, mean_exponent_numerator: u64, mean_exponent_denominator: u64, mean_stripe_numerator: u64, mean_stripe_denominator: u64, ) -> SpecialRandomPositiveFloatNaturals { SpecialRandomPositiveFloatNaturals { exponents: geometric_random_signed_range( seed.fork("exponents"), start_exponent, i64::power_of_2(T::EXPONENT_WIDTH - 1) - i64::wrapping_from(T::MANTISSA_WIDTH) - 1, mean_exponent_numerator, mean_exponent_denominator, ), mantissas: striped_random_unsigned_bit_chunks( seed.fork("mantissas"), T::MANTISSA_WIDTH + 1, mean_stripe_numerator, mean_stripe_denominator, ), phantom: PhantomData, } } pub fn special_random_natural_gen_var_2(config: &GenConfig) -> It { Box::new(with_special_value( EXAMPLE_SEED, Natural::ZERO, 1, 100, &|seed| { special_random_positive_float_naturals::( seed, 0, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_gen_var_3 ExactFrom<&'a Natural> + PrimitiveFloat>( config: &GenConfig, ) -> It where Natural: ExactFrom, { Box::new( special_random_positive_float_naturals::( EXAMPLE_SEED, 1, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("mean_stripe_n", 16), config.get_or("mean_stripe_d", 1), ) .filter_map(|a| { let b = Natural::exact_from(T::exact_from(&a).next_higher()); let diff = b - &a; if diff.even() { // This happens almost always Some(a + (diff >> 1)) } else { None } }), ) } pub fn special_random_natural_gen_var_4(config: &GenConfig) -> It where Natural: From, { Box::new( striped_random_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(Natural::from), ) } pub fn special_random_natural_gen_var_5(config: &GenConfig) -> It where Natural: ExactFrom, { Box::new( striped_random_natural_signeds( EXAMPLE_SEED, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) .map(Natural::exact_from), ) } pub fn special_random_natural_gen_var_6(config: &GenConfig) -> It { Box::new(striped_random_natural_range_to_infinity( EXAMPLE_SEED, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } #[allow(clippy::type_repetition_in_bounds)] pub fn special_random_natural_gen_var_7(config: &GenConfig) -> It where for<'a> T: ConvertibleFrom<&'a Natural>, { Box::new( striped_random_natural_range_to_infinity( EXAMPLE_SEED, Natural::power_of_2(T::MANTISSA_WIDTH + 1) | Natural::ONE, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", Limb::WIDTH << 1), config.get_or("mean_bits_d", 1), ) .filter(|n| !T::convertible_from(n)), ) } pub fn special_random_natural_gen_var_8(config: &GenConfig) -> It { Box::new( striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Natural::ONE), ) } // -- (Natural, bool) -- pub fn special_random_natural_bool_pair_gen(config: &GenConfig) -> It<(Natural, bool)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_bools, )) } // -- (Natural, Integer, Natural) -- pub fn special_random_natural_integer_natural_triple_gen( config: &GenConfig, ) -> It<(Natural, Integer, Natural)> { Box::new(random_triples_xyx( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Natural, Natural) -- pub fn special_random_natural_pair_gen(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_natural_pair_gen_var_1(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_natural_pair_gen_var_2(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_natural_pair_gen_var_3(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| (x * &y, y * z)), ) } pub fn special_random_natural_pair_gen_var_4(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_natural_pair_gen_var_5(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .map(|(x, y)| (x * &y, y)), ) } pub fn special_random_natural_pair_gen_var_6(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by(y)), ) } pub fn special_random_natural_pair_gen_var_7(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_ordered_unique_pairs(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_natural_pair_gen_var_8(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs_from_single(striped_random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_natural_pair_gen_var_9(config: &GenConfig) -> It<(Natural, Natural)> { // TODO Box::new( random_pairs_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x >= y), ) } pub fn special_random_natural_pair_gen_var_10(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::power_of_2(Limb::WIDTH), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64 + Limb::WIDTH), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_natural_pair_gen_var_11(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_ordered_unique_pairs( striped_random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), )) } pub fn special_random_natural_pair_gen_var_12(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, n)| (a, (n << 1u32) | Natural::ONE)), ) } pub fn special_random_natural_pair_gen_var_13(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single( striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|n| (n << 1u32) | Natural::ONE), ) .filter(|(x, y)| x.coprime_with(y)), ) } pub fn special_random_natural_pair_gen_var_14(config: &GenConfig) -> It<(Natural, Natural)> { Box::new( random_pairs_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y)| x.coprime_with(y)), ) } pub fn special_random_natural_pair_gen_var_15(config: &GenConfig) -> It<(Natural, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from) }, )) } // -- (Natural, Natural, bool) -- pub fn special_random_natural_natural_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_bools, )) } // -- (Natural, Natural, Natural) -- pub fn special_random_natural_triple_gen(config: &GenConfig) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, m)| (x * &m + &y, y, m)), ) } pub fn special_random_natural_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter(|(x, y, m)| !x.eq_mod(y, m)), ) } pub fn special_random_natural_triple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| { let z = max(&x, &y) + z + Natural::ONE; (x, y, z) }), ) } pub fn special_random_natural_triple_gen_var_4( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_natural_triple_gen_var_5( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, mut z)| { z += &x; z += Natural::ONE; (x, y, z) }), ) } pub fn special_random_natural_triple_gen_var_6( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new(random_triples_from_single( striped_random_positive_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), )) } pub fn special_random_natural_triple_gen_var_7( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| (x + &y * &z, y, z)), ) } pub fn special_random_natural_triple_gen_var_8( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, b, n)| (a, b, (n << 1u32) | Natural::ONE)), ) } pub fn special_random_natural_triple_gen_var_9( config: &GenConfig, ) -> It<(Natural, Natural, Natural)> { Box::new( random_triples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(a, m, n)| (a, (m << 1u32) | Natural::ONE, (n << 1u32) | Natural::ONE)), ) } // -- (Natural, Natural, Natural, Natural) -- pub fn special_random_natural_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .filter_map(|(x, y, z, w)| { let ranking = [(&x, 0), (&y, 1), (&z, 2), (&w, 3)]; let (hi, next_hi) = get_two_highest(&ranking); if hi.0 == next_hi.0 { None } else { Some(match hi.1 { 0 => (y, z, w, x), 1 => (x, z, w, y), 2 => (x, y, w, z), _ => (x, y, z, w), }) } }), ) } pub fn special_random_natural_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z, mut w)| { w += max!(&x, &y); w += Natural::ONE; (x, y, z, w) }), ) } pub fn special_random_natural_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, Natural, Natural)> { Box::new( random_quadruples_from_single(striped_random_naturals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z, mut w)| { w += &x; w += Natural::ONE; (x, y, z, w) }), ) } // -- (Natural, Natural, Natural, PrimitiveUnsigned) -- pub fn special_random_natural_natural_natural_unsigned_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, Natural, T)> { Box::new(random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_natural_natural_unsigned_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += max!( x.significant_bits(), y.significant_bits(), z.significant_bits() ); (x, y, z, m) }), ) } pub fn special_random_natural_natural_natural_unsigned_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, z, m) }), ) } pub fn special_random_natural_natural_natural_unsigned_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Natural, Natural, Natural, u64)> { Box::new( random_quadruples_xxxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, z, mut m)| { m += x.significant_bits(); (x, y, z, m) }), ) } // -- (Natural, Natural, PrimitiveFloat) -- pub fn special_random_natural_natural_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Natural, Natural, PrimitiveUnsigned) -- pub fn special_random_natural_natural_unsigned_triple_gen( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Natural, Natural, PrimitiveSigned) -- pub fn special_random_natural_natural_signed_triple_gen( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_natural_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_ordered_unique_pairs(striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ))) } // -- (Natural, Natural, PrimitiveUnsigned) -- pub fn special_random_natural_natural_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_natural_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, T)> where Natural: Shl, { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, pow)| ((x << pow) + &y, y, pow)), ) } pub fn special_random_natural_natural_unsigned_triple_gen_var_3( config: &GenConfig, ) -> It<(Natural, Natural, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|&(ref x, ref y, pow)| !x.eq_mod_power_of_2(y, pow.exact_into())), ) } pub fn special_random_natural_natural_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Natural, Natural, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += max(x.significant_bits(), y.significant_bits()); (x, y, m) }), ) } pub fn special_random_natural_natural_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Natural, Natural, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } pub fn special_random_natural_natural_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Natural, Natural, T)> { reshape_2_1_to_3(Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_ordered_unique_pairs(striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ))) } // -- (Natural, Natural, RoundingMode) -- pub fn special_random_natural_natural_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, Natural, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .map(|(x, y, rm)| { if rm == Exact { (x * &y, y, rm) } else { (x, y, rm) } }), ) } pub fn special_random_natural_natural_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, Natural, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter_map(|(x, y, rm)| round_to_multiple_natural_filter_map(x, y, rm)), ) } // -- (Natural, PrimitiveFloat) -- pub fn special_random_natural_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Natural, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_natural_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Natural, PrimitiveSigned) -- pub fn special_random_natural_signed_pair_gen( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } struct NaturalBitsMultipleOfLimbBitsGenerator { bit_source: StripedBitSource, limb_counts: GeometricRandomNaturalValues, } impl Iterator for NaturalBitsMultipleOfLimbBitsGenerator { type Item = Natural; fn next(&mut self) -> Option { Some(get_striped_random_natural_with_bits( &mut self.bit_source, self.limb_counts.next().unwrap() << Limb::LOG_WIDTH, )) } } pub fn special_random_natural_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| NaturalBitsMultipleOfLimbBitsGenerator { bit_source: StripedBitSource::new( seed.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), limb_counts: geometric_random_positive_unsigneds( seed.fork("limb_counts"), config.get_or("mean_small_n", 2), config.get_or("mean_small_d", 1), ), }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Natural, PrimitiveSigned, PrimitiveSigned) --- pub fn special_random_natural_signed_signed_triple_gen( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } // -- (Natural, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_natural_signed_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } pub fn special_random_natural_signed_unsigned_triple_gen_var_2< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Natural, PrimitiveSigned, RoundingMode) -- pub fn special_random_natural_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shr, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i < T::ZERO && rm == Exact { n >> i } else { n }, i, rm, ) }), ) } pub fn special_random_natural_signed_rounding_mode_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .map(|(n, i, rm)| { ( if i > T::ZERO && rm == Exact { n << i } else { n }, i, rm, ) }), ) } // -- (Natural, PrimitiveUnsigned) -- pub fn special_random_natural_unsigned_pair_gen( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_1< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::saturating_from(U::MAX), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::MAX, config.get_or("mean_stripe_n", T::WIDTH), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_stripe_n", T::WIDTH), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Natural, u64)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 1, T::WIDTH, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(Natural, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed_2| { striped_random_naturals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .map(|(mut x, y)| { x.round_to_multiple_of_power_of_2_assign(y.exact_into(), Down); (x, y) }), ) } pub fn special_random_natural_unsigned_pair_gen_var_9( config: &GenConfig, ) -> It<(Natural, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds::( seed, config.get_or("mean_small_n", 32), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y)| !x.divisible_by_power_of_2(y.exact_into())), ) } pub fn special_random_natural_unsigned_pair_gen_var_10(config: &GenConfig) -> It<(Natural, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } pub fn special_random_natural_unsigned_pair_gen_var_11( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_12( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_13( config: &GenConfig, ) -> It<(Natural, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_natural_unsigned_pair_gen_var_14(config: &GenConfig) -> It<(Natural, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, mut m)| { m += x.significant_bits(); (x, m) }), ) } // -- (Natural, PrimitiveUnsigned, bool) -- pub fn special_random_natural_unsigned_bool_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, bool)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_bools, )) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned) --- pub fn special_random_natural_unsigned_unsigned_triple_gen( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_1< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::from(36u8), config.get_or("mean_stripe_n", T::WIDTH), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveInt, >( config: &GenConfig, ) -> It<(Natural, u64, T)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 1, U::WIDTH, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_4( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, z)| if y <= z { (xs, y, z) } else { (xs, z, y) }), ) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_5( config: &GenConfig, ) -> It<(Natural, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, )) } pub fn special_random_natural_unsigned_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Natural, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .map(|(x, y, mut m)| { m += x.significant_bits(); (x, y, m) }), ) } // -- (Natural, PrimitiveUnsigned, PrimitiveUnsigned, Natural) -- pub fn special_random_natural_unsigned_unsigned_natural_quadruple_gen_var_1< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Natural, T, T, Natural)> { Box::new( random_quadruples_xyyx::<_, _, T, _>( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(x, y, z, w)| match y.cmp(&z) { Less => Some((x, y, z, w)), Greater => Some((x, z, y, w)), Equal => None, }), ) } // -- (Natural, PrimitiveUnsigned, RoundingMode) -- pub fn special_random_natural_unsigned_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, T, RoundingMode)> where Natural: Shl, { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ) }, &random_rounding_modes, ) .map(|(n, u, rm)| { if rm == Exact { (n << u, u, rm) } else { (n, u, rm) } }), ) } // var 2 is in malachite-float // --(Natural, PrimitiveUnsigned, Vec) -- struct NaturalUnsignedBoolVecTripleGenerator { xs: StripedRandomNaturals>, log_bases: It, striped_bit_source: StripedBitSource, } impl Iterator for NaturalUnsignedBoolVecTripleGenerator { type Item = (Natural, u64, Vec); fn next(&mut self) -> Option<(Natural, u64, Vec)> { let x = self.xs.next().unwrap(); let log_base = self.log_bases.next().unwrap(); let bs = get_striped_bool_vec( &mut self.striped_bit_source, x.significant_bits().div_round(log_base, Ceiling).0, ); Some((x, log_base, bs)) } } pub fn special_random_natural_unsigned_bool_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Natural, u64, Vec)> { Box::new(NaturalUnsignedBoolVecTripleGenerator { xs: striped_random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), log_bases: Box::new(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), )), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_natural_unsigned_bool_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Natural, u64, Vec)> { Box::new(NaturalUnsignedBoolVecTripleGenerator { xs: striped_random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), log_bases: Box::new(striped_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("log_bases"), 1, T::WIDTH, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), )), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } // -- (Natural, RoundingMode) -- pub fn special_random_natural_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(Natural, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_natural_rounding_mode_pair_gen_var_1< T: for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Natural, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|&(ref n, rm)| rm != Exact || T::convertible_from(n)), ) } pub fn special_random_natural_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_naturals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } // -- (Natural, ToSciOptions) -- pub fn special_random_natural_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(Natural, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn special_random_natural_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- (Natural, Vec) -- struct NaturalBoolVecPairGenerator1 { xs: StripedRandomNaturals>, striped_bit_source: StripedBitSource, } impl Iterator for NaturalBoolVecPairGenerator1 { type Item = (Natural, Vec); fn next(&mut self) -> Option<(Natural, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec(&mut self.striped_bit_source, x.limb_count()); Some((x, bs)) } } pub fn special_random_natural_bool_vec_pair_gen_var_1( config: &GenConfig, ) -> It<(Natural, Vec)> { Box::new(NaturalBoolVecPairGenerator1 { xs: striped_random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } struct NaturalBoolVecPairGenerator2 { xs: StripedRandomNaturals>, striped_bit_source: StripedBitSource, } impl Iterator for NaturalBoolVecPairGenerator2 { type Item = (Natural, Vec); fn next(&mut self) -> Option<(Natural, Vec)> { let x = self.xs.next().unwrap(); let bs = get_striped_bool_vec(&mut self.striped_bit_source, x.significant_bits()); Some((x, bs)) } } pub fn special_random_natural_bool_vec_pair_gen_var_2( config: &GenConfig, ) -> It<(Natural, Vec)> { Box::new(NaturalBoolVecPairGenerator2 { xs: striped_random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), }) } // -- (PrimitiveUnsigned * 6) -- // var 1 is in malachite-base. pub fn special_random_unsigned_sextuple_gen_var_2( config: &GenConfig, ) -> It<(Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { random_pairs_from_single(striped_random_unsigneds( seed_2, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) }, &|seed_2| { random_pairs( seed_2, &|seed_3| { striped_random_unsigned_inclusive_range( seed_3, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed_3| { striped_random_unsigneds( seed_3, config.get_or("mean_unsigned_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_unsigned_stripe_d", 1), ) }, ) }, ) .filter(|&((n_2, n_1), (d_1, d_0))| n_2 < d_1 || n_2 == d_1 && n_1 < d_0) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|(((n_2, n_1), (d_1, d_0)), n_0)| { ( n_2, n_1, n_0, d_1, d_0, limbs_two_limb_inverse_helper(d_1, d_0), ) }), ) } // -- (String, String, String) -- pub fn special_random_string_triple_gen_var_1(config: &GenConfig) -> It<(String, String, String)> { Box::new( striped_random_naturals( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigUint::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } pub fn special_random_string_triple_gen_var_2(config: &GenConfig) -> It<(String, String, String)> { Box::new( striped_random_integers( EXAMPLE_SEED.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigInt::from(&x)).unwrap(), serde_json::to_string(&rug::Integer::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } // -- Vec -- pub fn special_random_integer_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } // -- Vec -- pub fn special_random_natural_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } // -- (Vec, Integer) -- pub fn special_random_natural_vec_integer_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { striped_random_positive_naturals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), ) }, &|seed| { striped_random_integers( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Vec, Natural) -- pub fn special_random_natural_vec_natural_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { striped_random_naturals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::power_of_2(Limb::WIDTH), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH + 4, 1, ) }, )) } pub fn special_random_natural_vec_natural_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { striped_random_naturals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } struct LargeDigitsRandomGenerator { bases: StripedRandomNaturalRangeToInfinity, digit_counts: GeometricRandomNaturalValues, bit_source: StripedBitSource, } impl Iterator for LargeDigitsRandomGenerator { type Item = (Vec, Natural); fn next(&mut self) -> Option<(Vec, Natural)> { let base = self.bases.next().unwrap(); let bits = base.ceiling_log_base_2(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { loop { let x = get_striped_random_natural_with_up_to_bits(&mut self.bit_source, bits); if x < base { digits.push(x); break; } } } Some((digits, base)) } } pub fn special_random_natural_vec_natural_pair_gen_var_3( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(LargeDigitsRandomGenerator { bases: striped_random_natural_range_to_infinity( EXAMPLE_SEED.fork("bases"), Natural::power_of_2(Limb::WIDTH), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), Limb::WIDTH + 4, 1, ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), }) } pub fn striped_random_natural_vec_natural_pair_gen_var_4( config: &GenConfig, ) -> It<(Vec, Natural)> { Box::new(LargeDigitsRandomGenerator { bases: striped_random_natural_range_to_infinity( EXAMPLE_SEED.fork("bases"), Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), }) } // -- (Vec, PrimitiveUnsigned) -- struct PowerOf2DigitsGenerator { log_bases: GeometricRandomNaturalValues, digit_counts: GeometricRandomNaturalValues, bit_source: StripedBitSource, } impl Iterator for PowerOf2DigitsGenerator { type Item = (Vec, u64); fn next(&mut self) -> Option<(Vec, u64)> { let log_base = self.log_bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mut digits = Vec::with_capacity(digit_count); for _ in 0..digit_count { digits.push(get_striped_random_natural_with_up_to_bits( &mut self.bit_source, log_base, )); } Some((digits, log_base)) } } pub fn special_random_natural_vec_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new(PowerOf2DigitsGenerator { log_bases: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), digit_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("digit_count"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_natural_vec_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_vecs( seed, &|seed_2| { striped_random_naturals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- Vec -- // vars 1 through 4 are in malachite-base. pub fn special_random_unsigned_vec_gen_var_5(config: &GenConfig) -> It> { Box::new( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .map(|mut xs| { limbs_vec_mul_limb_in_place(&mut xs, 3); xs }), ) } // var 6 is in malachite-base. // -- (Vec, PrimitiveUnsigned) -- // vars 1 through 3 are in malachite-base pub fn special_random_unsigned_vec_unsigned_pair_gen_var_4< T: PrimitiveUnsigned + SaturatingFrom, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 6), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, T::TWO, T::saturating_from(U::MAX), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // vars 5 through 17 are in malachite-base. pub fn special_random_unsigned_vec_unsigned_pair_gen_var_18( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new( special_random_unsigned_vec_unsigned_pair_gen_var_17(config).filter(|(xs, index)| { let mut mut_xs = xs.clone(); limbs_vec_clear_bit_neg(&mut mut_xs, *index); mut_xs.len() == xs.len() }), ) } // vars 19 through 25 are in malachite-base. pub fn special_random_unsigned_vec_unsigned_pair_gen_var_26( config: &GenConfig, ) -> It<(Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(|(mut xs, y)| { limbs_vec_mul_limb_in_place(&mut xs, y); (xs, y) }), ) } pub fn special_random_unsigned_vec_unsigned_pair_gen_var_27( config: &GenConfig, ) -> It<(Vec, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_unsigned_n", 4), config.get_or("mean_small_unsigned_d", 1), ) }, ) .filter_map(|(mut xs, mut pow)| { let xs_last = xs.last_mut().unwrap(); *xs_last = xs_last.checked_add(1)?; pow += limbs_significant_bits_helper(&xs); Some((xs, pow)) }), ) } // var 28 is in malachite-base. // -- (Vec, PrimitiveUnsigned, PrimitiveUnsigned) -- // vars 1 through 5 are in malachite-base pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(|(m, x, y)| { !Integer::from(Natural::from(*x)).eq_mod(-Natural::from(*y), Natural::from_limbs_asc(m)) }), ) } // vars 7 through 8 are in malachite-base. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_9( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| random_values_from_vec(seed, factors_of_limb_max()), &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, )) } // var 10 is in malachite-base. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_11( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(map_helper_3), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_12( config: &GenConfig, ) -> It<(Vec, Limb, Limb)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(filter_helper_6), ) } // var 13 is in malachite-base. pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_14( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_15( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); (xs, y, pow) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_16( config: &GenConfig, ) -> It<(Vec, T, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", T::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigneds::( seed, config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, y, mut pow)| { pow += max(limbs_significant_bits_helper(&xs), y.significant_bits()); if pow == 0 { pow = 1; } (xs, y, pow) }), ) } // -- (Vec, PrimitiveUnsigned, Vec) -- struct DigitsSpecialRandomGenerator { bases: RandomValuesFromVec, xss: StripedRandomUnsignedVecs>, bit_source: StripedBitSource, phantom: PhantomData<*const T>, } impl Iterator for DigitsSpecialRandomGenerator { type Item = (Vec, u64, Vec); fn next(&mut self) -> Option<(Vec, u64, Vec)> { let base = self.bases.next().unwrap(); let xs = self.xss.next().unwrap(); let out_len = usize::exact_from(limbs_digit_count(&xs, base)); let out = get_striped_unsigned_vec( &mut self.bit_source, u64::exact_from(out_len) << T::LOG_WIDTH, ); Some((out, base, xs)) } } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1( config: &GenConfig, ) -> It<(Vec, u64, Vec)> { Box::new(DigitsSpecialRandomGenerator { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), xss: striped_random_unsigned_vecs( EXAMPLE_SEED.fork("xss"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), phantom: PhantomData, }) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) .filter_map(filter_map_helper_1), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) .filter(filter_helper_1), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) .map(map_helper_1), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Limb, Vec)> { Box::new( permute_1_3_2(Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ))) .filter(filter_helper_4), ) } // -- (Vec, PrimitiveUnsigned, Vec, PrimitiveUnsigned) -- struct BasecaseDigitsSpecialRandomGenerator { bases: RandomValuesFromVec, xss: StripedRandomUnsignedVecs>, excess_lens: RandomOptions>, excess_out_lens: GeometricRandomNaturalValues, bit_source: StripedBitSource, phantom: PhantomData<*const T>, } impl Iterator for BasecaseDigitsSpecialRandomGenerator { type Item = (Vec, usize, Vec, u64); fn next(&mut self) -> Option<(Vec, usize, Vec, u64)> { let base = self.bases.next().unwrap(); let xs = self.xss.next().unwrap(); let min_out_len = usize::exact_from(limbs_digit_count(&xs, base)); let excess_out_len = self.excess_out_lens.next().unwrap(); let (len, out_len) = if let Some(excess) = self.excess_lens.next().unwrap() { (min_out_len + excess, min_out_len + excess + excess_out_len) } else { (0, min_out_len + excess_out_len) }; let out = get_striped_unsigned_vec( &mut self.bit_source, u64::exact_from(out_len) << T::LOG_WIDTH, ); Some((out, len, xs, base)) } } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1< T: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, usize, Vec, u64)> { Box::new(BasecaseDigitsSpecialRandomGenerator { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), xss: striped_random_unsigned_vecs_length_range( EXAMPLE_SEED.fork("xss"), 0, u64::exact_from(GET_STR_PRECOMPUTE_THRESHOLD), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), excess_lens: random_options( EXAMPLE_SEED.fork("excess_lens"), config.get_or("zero_len_prob_n", 1), config.get_or("zero_len_prob_d", 5), &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ) }, ), excess_out_lens: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_out_lens"), config.get_or("mean_excess_len_n", 4), config.get_or("mean_excess_len_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), phantom: PhantomData, }) } // -- (Vec, Vec) -- // vars 1 through 10 are in malachite-base. pub fn special_random_unsigned_vec_pair_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator2 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(xs, ys)| gcd_input_filter(xs, ys)), ) } // vars 12 through 13 are in malachite-base. pub fn special_random_unsigned_vec_pair_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter_map(|(out, mut xs)| { limbs_vec_mul_limb_in_place(&mut xs, 3); if out.len() >= xs.len() { Some((out, xs)) } else { None } }), ) } pub fn special_random_unsigned_vec_pair_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single(striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(ns, mut ds)| { let d_last = ds.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_ns = limbs_mul(&ns, &ds); if *new_ns.last().unwrap() == 0 { new_ns.pop(); } (new_ns, ds) }), ) } // vars 16 through 17 are in malachite-base. pub fn special_random_unsigned_vec_pair_gen_var_18( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new( random_pairs_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let x_last = xs.last_mut().unwrap(); if *x_last == Limb::MAX { None } else { *x_last += 1; Some(xs) } }), ) .filter_map(|(ns, ds)| { let mut ns = limbs_mul(&ns, &ds); if *ns.last().unwrap() == 0 { ns.pop(); } if *ns.last().unwrap() == 0 { None } else { Some((ns, ds)) } }), ) } // vars 19 through 21 are in malachite-base. pub fn special_random_unsigned_vec_pair_gen_var_22( config: &GenConfig, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs( EXAMPLE_SEED.fork("lengths"), &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 1, u64::exact_from(SQRLO_DC_THRESHOLD_LIMIT), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, ) .filter(|(x, y)| x >= y), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } fn special_random_square_helper bool>( config: &GenConfig, valid: &'static F, min_x: u64, ) -> It<(Vec, Vec)> { Box::new(UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_pair_gen_var_23( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &|x| x <= SQR_TOOM2_THRESHOLD, 1) } pub fn special_random_unsigned_vec_pair_gen_var_24( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &|_| true, 2) } pub fn special_random_unsigned_vec_pair_gen_var_25( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &limbs_square_to_out_toom_3_input_size_valid, 3) } pub fn special_random_unsigned_vec_pair_gen_var_26( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &limbs_square_to_out_toom_4_input_size_valid, 4) } pub fn special_random_unsigned_vec_pair_gen_var_27( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &|x| x == 7 || x == 8 || x > 9, 7) } pub fn special_random_unsigned_vec_pair_gen_var_28( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &limbs_square_to_out_toom_6_input_size_valid, 18) } pub fn special_random_unsigned_vec_pair_gen_var_29( config: &GenConfig, ) -> It<(Vec, Vec)> { special_random_square_helper(config, &limbs_square_to_out_toom_8_input_size_valid, 40) } // vars 32 to 33 are in malachite-base. // -- (Vec, Vec, PrimitiveUnsigned) -- // var 1 is in malachite-base struct BasecaseDigitsSpecialRandomGenerator1 { bases: RandomValuesFromVec, digit_counts: GeometricRandomNaturalValues, base_to_digits: HashMap>, excess_limb_counts: GeometricRandomNaturalValues, bit_source: StripedBitSource, phantom: PhantomData<*const U>, } impl Iterator for BasecaseDigitsSpecialRandomGenerator1 { type Item = (Vec, Vec, u64); fn next(&mut self) -> Option<(Vec, Vec, u64)> { let base = self.bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let ds = self.base_to_digits.entry(base).or_insert_with(move || { random_unsigneds_less_than(EXAMPLE_SEED.fork(&base.to_string()), T::wrapping_from(base)) }); let digits = ds.take(digit_count).collect(); let min_limb_count = limbs_per_digit_in_base(digit_count, base); let out = get_striped_unsigned_vec( &mut self.bit_source, (min_limb_count + self.excess_limb_counts.next().unwrap()) << U::LOG_WIDTH, ); Some((out, digits, base)) } } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new(BasecaseDigitsSpecialRandomGenerator1 { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), digit_counts: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), excess_limb_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_limb_count"), config.get_or("mean_excess_limb_count_n", 4), config.get_or("mean_excess_limb_count_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), base_to_digits: HashMap::new(), phantom: PhantomData, }) } struct BasecaseDigitsSpecialRandomGenerator2 { bases: RandomValuesFromVec, digit_counts: GeometricRandomNaturalValues, base_to_digits: HashMap>, excess_limb_counts: GeometricRandomNaturalValues, bit_source: StripedBitSource, mean_stripe_n: u64, mean_stripe_d: u64, phantom: PhantomData<*const U>, } impl Iterator for BasecaseDigitsSpecialRandomGenerator2 { type Item = (Vec, Vec, u64); fn next(&mut self) -> Option<(Vec, Vec, u64)> { let base = self.bases.next().unwrap(); let digit_count = self.digit_counts.next().unwrap(); let mean_stripe_n = self.mean_stripe_n; let mean_stripe_d = self.mean_stripe_d; let ds = self.base_to_digits.entry(base).or_insert_with(move || { striped_random_unsigneds( EXAMPLE_SEED.fork(&base.to_string()), mean_stripe_n, mean_stripe_d, ) }); let digits = ds.take(digit_count).collect(); let min_limb_count = limbs_per_digit_in_base(digit_count, base); let out = get_striped_unsigned_vec( &mut self.bit_source, (min_limb_count + self.excess_limb_counts.next().unwrap()) << U::LOG_WIDTH, ); Some((out, digits, base)) } } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3< T: PrimitiveUnsigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new(BasecaseDigitsSpecialRandomGenerator2 { bases: random_values_from_vec( EXAMPLE_SEED.fork("bases"), (3u64..256).filter(|&b| !b.is_power_of_two()).collect(), ), digit_counts: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("digit_counts"), config.get_or("mean_digit_count_n", 4), config.get_or("mean_digit_count_d", 1), ), excess_limb_counts: geometric_random_unsigneds( EXAMPLE_SEED.fork("excess_limb_count"), config.get_or("mean_excess_limb_count_n", 4), config.get_or("mean_excess_limb_count_d", 1), ), bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("bit_source"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ), base_to_digits: HashMap::new(), mean_stripe_n: config.get_or("mean_stripe_n", 32), mean_stripe_d: config.get_or("mean_stripe_d", 1), phantom: PhantomData, }) } // vars 4 through 6 are in malachite-base. pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(filter_map_helper_2), ) } pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(filter_helper_2), ) } // vars 9 through 13 are in malachite-base. pub fn special_random_unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigned_inclusive_range( seed.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|((out, mut xs), y)| { limbs_vec_mul_limb_in_place(&mut xs, y); if out.len() >= xs.len() { Some((out, xs, y)) } else { None } }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .map(map_helper_2), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter(filter_helper_5), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_vec_triple_gen_var_17( config: &GenConfig, ) -> It<(Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; if n_len > d_init_len { Some((n_len, d_init_len)) } else { None } }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_inclusive_range( seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|((n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (n, d_init, inverse) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_18( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs::( seed, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_19( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|((xs, ys), mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter_map(|mut xs| { let last_x = xs.last_mut().unwrap(); *last_x = last_x.checked_add(1)?; Some(xs) }) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .map(|(xs, ys, mut pow)| { pow += max( limbs_significant_bits_helper(&xs), limbs_significant_bits_helper(&ys), ); (xs, ys, pow) }), ) } pub fn special_random_unsigned_vec_unsigned_unsigned_triple_gen_var_21( config: &GenConfig, ) -> It<(Vec, Vec, u64)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length::( seed, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("small_unsigned_mean_n", 4), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter_map(|(mut xs, mut es, pow)| { let last_e = es.last_mut().unwrap(); *last_e = last_e.checked_add(1)?; if es == [1] { return None; } limbs_slice_mod_power_of_2_in_place(&mut xs, pow); if *xs.last().unwrap() == 0 { None } else { Some((xs, es, pow)) } }), ) } // var 22 is in malachite-base. // -- (Vec, Vec, Vec) -- // vars 1 through 3 are in malachite-base fn special_random_mul_helper bool>( config: &GenConfig, valid: &'static F, min_x: u64, min_y: u64, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x, y)| { let x = x.checked_add(min_x)?; let y = y.checked_add(min_y)?; if valid(usize::exact_from(x), usize::exact_from(y)) { let o = x.checked_add(y)?.checked_add(o)?; Some((o, x, y)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_22_input_sizes_valid, 2, 2, ) } pub fn special_random_unsigned_vec_triple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_32_input_sizes_valid, 6, 4, ) } pub fn special_random_unsigned_vec_triple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_33_input_sizes_valid, 3, 3, ) } pub fn special_random_unsigned_vec_triple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_42_input_sizes_valid, 4, 2, ) } pub fn special_random_unsigned_vec_triple_gen_var_8( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_43_input_sizes_valid, 11, 8, ) } pub fn special_random_unsigned_vec_triple_gen_var_9( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_44_input_sizes_valid, 4, 4, ) } pub fn special_random_unsigned_vec_triple_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_52_input_sizes_valid, 14, 5, ) } pub fn special_random_unsigned_vec_triple_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_53_input_sizes_valid, 5, 3, ) } pub fn special_random_unsigned_vec_triple_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_54_input_sizes_valid, 14, 11, ) } pub fn special_random_unsigned_vec_triple_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_62_input_sizes_valid, 6, 2, ) } pub fn special_random_unsigned_vec_triple_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_63_input_sizes_valid, 17, 9, ) } pub fn special_random_unsigned_vec_triple_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42, 42, ) } pub fn special_random_unsigned_vec_triple_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86, 86, ) } fn special_random_mul_same_length_helper bool>( config: &GenConfig, valid: &'static F, min_x: u64, ) -> It<(Vec, Vec, Vec)> { Box::new(UnsignedVecTripleXYYLenGenerator { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(move |(o, x)| { let x = x.checked_add(min_x)?; let ux = usize::exact_from(x); if valid(ux, ux) { let o = x.arithmetic_checked_shl(1u64)?.checked_add(o)?; Some((o, x)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", T::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } pub fn special_random_unsigned_vec_triple_gen_var_18( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_33_input_sizes_valid, 5, ) } pub fn special_random_unsigned_vec_triple_gen_var_19( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_6h_input_sizes_valid, 42, ) } pub fn special_random_unsigned_vec_triple_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_same_length_helper( config, &limbs_mul_greater_to_out_toom_8h_input_sizes_valid, 86, ) } pub fn special_random_unsigned_vec_triple_gen_var_22( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_32_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_43_input_sizes_valid(xs_len, ys_len) }, 11, 8, ) } pub fn special_random_unsigned_vec_triple_gen_var_23( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &|xs_len, ys_len| { limbs_mul_greater_to_out_toom_42_input_sizes_valid(xs_len, ys_len) && limbs_mul_greater_to_out_toom_53_input_sizes_valid(xs_len, ys_len) }, 5, 3, ) } // vars 24 through 36 are in malachite-base pub fn special_random_unsigned_vec_triple_gen_var_37( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter_map(filter_map_helper_3), ) } pub fn special_random_unsigned_vec_triple_gen_var_38( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(filter_helper_3), ) } // vars 39 through 41 is in malachite-base. pub fn special_random_unsigned_vec_triple_gen_var_42( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(2)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_inclusive_range( seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_43( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(1)?; let d_len = d_init_len + 1; if n_len > d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_inclusive_range( seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); (q, n, d_init) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_44( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(_, _, d)| *d.last().unwrap() != 0), ) } pub fn special_random_unsigned_vec_triple_gen_var_45( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if n_len >= d_len && q_len > n_len - d_len && n_len < (d_len - 1) << 1 { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(_, _, d)| *d.last().unwrap() != 0), ) } pub fn special_random_unsigned_vec_triple_gen_var_46( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; (q, n, d) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_47( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len, d_len)| { if q_len >= n_len && n_len >= d_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; (q, n, d) }), ) } pub fn special_random_unsigned_vec_triple_gen_var_48( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len, d_len)| { if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter_map(|(q, n, mut d)| { let d_last = d.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() + d.len() >= new_n.len() + 1 { Some((q, new_n, d)) } else { None } }), ) } pub fn special_random_unsigned_vec_triple_gen_var_49( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range::( EXAMPLE_SEED.fork("lengths"), 1, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len, mut d_len)| { d_len = d_len.checked_add(1)?; if q_len + 1 >= n_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter_map(|(q, n, mut d)| { let d_last = d.last_mut().unwrap(); if *d_last == 0 { *d_last = 1; } let mut new_n = limbs_mul(&n, &d); if *new_n.last().unwrap() == 0 { new_n.pop(); } if q.len() > new_n.len() - d.len() { Some((q, n, d)) } else { None } }), ) } // vars 50 through 53 are in malachite-base. pub fn special_random_unsigned_vec_triple_gen_var_54( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .map(|(xs, ys, m)| limbs_eq_mod_map(&xs, ys, m)), ) } pub fn special_random_unsigned_vec_triple_gen_var_55( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_triples_from_single( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .filter(|xs| *xs.last().unwrap() != 0), ) .filter(|(xs, ys, m)| !limbs_eq_mod_ref_ref_ref(xs, ys, m)), ) } pub fn special_random_unsigned_vec_triple_gen_var_56( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, n_len): (u64, u64)| { Some((q_len.checked_add(n_len)?, n_len.checked_add(2)?)) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_unsigned_inclusive_range( seed_2, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, &|seed_2| { striped_random_positive_unsigneds( seed_2, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, ) .map(|((q, n), (d_1, d_0))| (q, n, vec![d_0, d_1])), ) } // var 57 is in malachite-base. pub fn special_random_unsigned_vec_triple_gen_var_58( config: &GenConfig, ) -> It<(Vec, Vec, Vec)> { special_random_mul_helper( config, &|x, y| { limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) && limbs_mul_greater_to_out_toom_44_input_sizes_valid(x, y) }, 7, 7, ) } // var 59 is in malachite-base. // -- (Vec * 4) -- #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, r, mut d)| { let last_d = d.last_mut().unwrap(); if *last_d == 0 { *last_d = 1; } (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_2( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(2)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, r, mut d)| { d[0] |= 1; (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_3( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(4)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(4)?; d_len = d_len.checked_add(2)?; if n_len >= d_len + 2 && q_len >= n_len - d_len && r_len >= d_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, r, mut d)| { d[0] |= 1; (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_4( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(2)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len >= d_len && q_len > n_len - d_len && (d_len << 1) > n_len + 1 { Some((q_len, r_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, r, mut d)| { let last_d = d.last_mut().unwrap(); if *last_d == 0 { *last_d = 1; } (q, n, r, d) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_5( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut r_len, mut n_len, mut d_len)| { q_len = q_len.checked_add(1)?; r_len = r_len.checked_add(2)?; n_len = n_len.checked_add(3)?; d_len = d_len.checked_add(2)?; if r_len >= d_len && n_len > d_len && q_len + d_len >= n_len { Some((q_len, r_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map( |(q, n, r, mut d): (Vec, Vec, Vec, Vec)| { d.last_mut().unwrap().set_bit(Limb::WIDTH - 1); (q, n, r, d) }, ), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_6( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new( UnsignedVecQuadrupleLenGenerator1 { phantom: PhantomData, lengths: random_quadruples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(out_len, mut b_len, e_len, mut m_len)| { b_len = b_len.checked_add(1)?; m_len = m_len.checked_add(1)?; if out_len >= m_len { Some((out_len, b_len, e_len, m_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .filter(|(_, bs, es, ms)| { (es.len() > 1 || es.len() == 1 && es[0] > 1) && *bs.last().unwrap() != 0 && *es.last().unwrap() != 0 && *ms.last().unwrap() != 0 }), ) } #[allow(clippy::type_complexity)] pub fn special_random_unsigned_vec_quadruple_gen_var_7( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec)> { Box::new(special_random_unsigned_vec_quadruple_gen_var_6(config).map( |(out, bs, es, mut ms)| { ms[0] |= 1; (out, bs, es, ms) }, )) } // -- large types -- // vars 1 through 4 are in malachite-base fn special_random_half_gcd_matrix( s: usize, n: usize, bit_source: &mut StripedBitSource, ) -> OwnedHalfGcdMatrix { assert!(n <= s); let bits = limb_to_bit_count(n); let mut m00 = get_striped_unsigned_vec(bit_source, bits); let m01 = get_striped_unsigned_vec(bit_source, bits); let m10 = get_striped_unsigned_vec(bit_source, bits); let m11 = get_striped_unsigned_vec(bit_source, bits); m00.resize(s << 2, 0); m00[s..s + n].copy_from_slice(&m01); m00[s << 1..(s << 1) + n].copy_from_slice(&m10); m00[s * 3..s * 3 + n].copy_from_slice(&m11); half_gcd_matrix_create(s, n, m00) } struct HalfGcdMatrixAndVecGenerator { sizes: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, bs: RandomBools, } impl Iterator for HalfGcdMatrixAndVecGenerator { type Item = (OwnedHalfGcdMatrix, Vec, u8); fn next(&mut self) -> Option { loop { let x = self.sizes.next().unwrap(); let qs_len = x.checked_add(1); let qs_len = if let Some(qs_len) = qs_len { qs_len } else { continue; }; let y = self.sizes.next().unwrap(); let m_n = qs_len.checked_add(y); let m_n = if let Some(m_n) = m_n { m_n } else { continue }; let z = self.sizes.next().unwrap(); let m_s = m_n.checked_add(z); let m_s = if let Some(m_s) = m_s { m_s } else { continue }; let m_s_1 = m_s.checked_add(2); let m_s_1 = if let Some(m_s_1) = m_s_1 { m_s_1 } else { continue; }; let m_s_2 = m_s.checked_add(qs_len); let m_s_2 = if let Some(m_s_2) = m_s_2 { m_s_2 } else { continue; }; let m_s = max(m_s_1, m_s_2); let m = special_random_half_gcd_matrix(m_s, m_n, &mut self.striped_bit_source); let qs = get_striped_unsigned_vec(&mut self.striped_bit_source, limb_to_bit_count(qs_len)); let column = u8::from(self.bs.next().unwrap()); return Some((m, qs, column)); } } } pub fn special_random_large_type_gen_var_5( config: &GenConfig, ) -> It<(OwnedHalfGcdMatrix, Vec, u8)> { Box::new(HalfGcdMatrixAndVecGenerator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ), bs: random_bools(EXAMPLE_SEED.fork("bs")), }) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_6( config: &GenConfig, ) -> It<(HalfGcdMatrix1, Vec, Vec, Vec)> { reshape_1_3_to_4(Box::new( random_quadruples_from_single(striped_random_unsigneds( EXAMPLE_SEED.fork("m"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .map(|(m00, m01, m10, m11)| HalfGcdMatrix1 { data: [[m00, m01], [m10, m11]], }) .zip(UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(x, y, z)| { let xs_len = x; let ys_len = x.checked_add(1)?.checked_add(y)?; let out_len = x.checked_add(1)?.checked_add(z)?; Some((out_len, xs_len, ys_len)) }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }), )) } struct HalfGcdMatrixAndHalfGcdMatrix1Generator { sizes: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, bit_chunks: StripedRandomUnsignedBitChunks, } impl Iterator for HalfGcdMatrixAndHalfGcdMatrix1Generator { type Item = (OwnedHalfGcdMatrix, HalfGcdMatrix1); fn next(&mut self) -> Option { loop { let x = self.sizes.next().unwrap(); let n = x.checked_add(1); let n = if let Some(n) = n { n } else { continue }; let y = self.sizes.next().unwrap(); let s = n.checked_add(y); let s = if let Some(s) = s { s } else { continue }; let s = s.checked_add(1); let s = if let Some(s) = s { s } else { continue }; let m = special_random_half_gcd_matrix(s, n, &mut self.striped_bit_source); let m_1 = HalfGcdMatrix1 { data: [ [self.bit_chunks.next().unwrap(), self.bit_chunks.next().unwrap()], [self.bit_chunks.next().unwrap(), self.bit_chunks.next().unwrap()], ], }; return Some((m, m_1)); } } } pub fn special_random_large_type_gen_var_7( config: &GenConfig, ) -> It<(OwnedHalfGcdMatrix, HalfGcdMatrix1)> { Box::new(HalfGcdMatrixAndHalfGcdMatrix1Generator { sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), bit_chunks: striped_random_unsigned_bit_chunks( EXAMPLE_SEED.fork("bit_chunks"), Limb::WIDTH - 1, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } struct MatrixMul22Generator { sizes: GeometricRandomNaturalValues, striped_bit_source: StripedBitSource, } impl Iterator for MatrixMul22Generator { type Item = T8; fn next(&mut self) -> Option { let ys_len = self.sizes.next().unwrap(); let xs_len = self.sizes.next().unwrap(); let sum_bits = (ys_len + xs_len + 1) << Limb::LOG_WIDTH; let ys_bits = ys_len << Limb::LOG_WIDTH; Some(( get_striped_unsigned_vec(&mut self.striped_bit_source, sum_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, sum_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, sum_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, sum_bits), usize::exact_from(xs_len), get_striped_unsigned_vec(&mut self.striped_bit_source, ys_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, ys_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, ys_bits), get_striped_unsigned_vec(&mut self.striped_bit_source, ys_bits), )) } } pub fn special_random_large_type_gen_var_8(config: &GenConfig) -> It { Box::new(MatrixMul22Generator { sizes: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }) } // var 9 is in malachite-base. pub fn special_random_large_type_gen_var_10( config: &GenConfig, ) -> It<(Vec, Vec, Limb, Limb)> { reshape_2_2_to_4(Box::new(random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecPairLenGenerator1 { phantom: PhantomData, lengths: random_pairs_from_single(geometric_random_positive_unsigneds( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .map(|(x, y)| if x >= y { (x, y) } else { (y, x) }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { random_pairs( seed, &|seed_2| random_values_from_vec(seed_2, factors_of_limb_max()), &|seed_2| { striped_random_unsigneds( seed_2, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) }, ))) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_11( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(q_len, mut n_len, mut d_init_len)| { n_len = n_len.checked_add(3)?; d_init_len = d_init_len.checked_add(2)?; let d_len = d_init_len + 1; if n_len >= d_len && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_inclusive_range( seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_12( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigneds::( seed.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, mut d_init_len)| { q_len = q_len.checked_add(3)?; n_len = n_len.checked_add(9)?; d_init_len = d_init_len.checked_add(5)?; let d_len = d_init_len + 1; if n_len >= d_len + 3 && q_len >= n_len - d_len { Some((q_len, n_len, d_init_len)) } else { None } }), striped_bit_source: StripedBitSource::new( seed.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), }, &|seed| { striped_random_unsigned_inclusive_range( seed, Limb::power_of_2(Limb::WIDTH - 1), Limb::MAX, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, ) .map(|((q, n, mut d_init), d_last)| { d_init.push(d_last); let inverse = limbs_two_limb_inverse_helper(d_init[d_init.len() - 1], d_init[d_init.len() - 2]); (q, n, d_init, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_13( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_14( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("lengths"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_15( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter_map(|(mut q_len, mut n_len, d_len)| { q_len = q_len.checked_add(1)?; n_len = n_len.checked_add(1)?; if q_len >= n_len && n_len > d_len { Some((q_len, n_len, d_len)) } else { None } }), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_16( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( UnsignedVecTripleLenGenerator1 { phantom: PhantomData, lengths: random_triples_from_single(geometric_random_unsigned_inclusive_range( EXAMPLE_SEED.fork("lengths"), 2, u64::MAX, config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), )) .filter(|&(q_len, n_len, d_len)| q_len >= n_len && n_len >= d_len), striped_bit_source: StripedBitSource::new( EXAMPLE_SEED.fork("striped_bit_source"), config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ), } .map(|(q, n, mut d)| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); (q, n, d, inverse) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_17( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Limb)> { Box::new( striped_random_unsigned_vecs_min_length( EXAMPLE_SEED, 1, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) .map(|mut d| { d[0] |= 1; let inverse = limbs_modular_invert_limb::(d[0]).wrapping_neg(); let is = vec![0; d.len()]; let scratch = vec![0; limbs_modular_invert_scratch_len(d.len())]; (is, scratch, d, inverse) }), ) } pub fn special_random_large_type_gen_var_18( config: &GenConfig, ) -> It<(Vec, usize, Limb, Limb, u64)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(ns, fraction_len, d)| { if ns.len() <= fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((ns, fraction_len, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_19( config: &GenConfig, ) -> It<(Vec, usize, Vec, Limb, Limb, u64)> { Box::new( random_quadruples_xyxz( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { striped_random_positive_unsigneds( seed, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), ) }, ) .filter_map(|(out, fraction_len, ns, d)| { if ns.is_empty() || out.len() < ns.len() + fraction_len { None } else { let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); Some((out, fraction_len, ns, d, d_inv, shift)) } }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_20( config: &GenConfig, ) -> It<(Vec, Vec, Vec, Vec, usize, usize)> { Box::new( random_quintuples_xyyyz( EXAMPLE_SEED, &|seed| { striped_random_unsigned_vecs_min_length( seed, 2, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { striped_random_unsigned_vecs( seed, config.get_or("mean_stripe_n", Limb::WIDTH << 1), config.get_or("mean_stripe_d", 1), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ) }, &|seed| { geometric_random_unsigned_inclusive_range( seed, 3, u32::MAX, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter_map(|(ds, mut scratch, mut qs, mut rs_hi, n_len)| { let n_len = usize::wrapping_from(n_len); let d_len = ds.len(); if n_len < d_len { return None; } let i_len = limbs_div_mod_barrett_is_len(n_len - d_len, d_len); if i_len == 0 || qs.len() < i_len { return None; } qs.truncate(i_len); if rs_hi.len() < i_len { return None; } rs_hi.truncate(i_len); let scratch_len = limbs_mul_mod_base_pow_n_minus_1_next_size(d_len + 1); let x = limbs_div_mod_barrett_scratch_len(n_len, d_len); if x < i_len { return None; } let actual_scratch_len = x - i_len; if actual_scratch_len < d_len + i_len { return None; } if scratch.len() < actual_scratch_len { return None; } scratch.truncate(actual_scratch_len); Some((scratch, ds, qs, rs_hi, scratch_len, i_len)) }), ) } #[allow(clippy::type_complexity)] pub fn special_random_large_type_gen_var_21( config: &GenConfig, ) -> It<(Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb, Limb)> { Box::new( random_sextuples_from_single(striped_random_positive_unsigneds( EXAMPLE_SEED, config.get_or("mean_stripe_n", Limb::WIDTH >> 1), config.get_or("mean_stripe_d", 1), )) .filter_map(large_type_filter_map_1), ) } // var 22 is in malachite-base. struct RationalFromPowerOf2DigitsGenerator { mean_stripe_n: u64, mean_stripe_d: u64, log_bases: GeometricRandomNaturalValues, sizes: GeometricRandomNaturalValues, xs_map: HashMap, } impl Iterator for RationalFromPowerOf2DigitsGenerator { type Item = (u64, Vec, RationalSequence); fn next(&mut self) -> Option<(u64, Vec, RationalSequence)> { let log_base = self.log_bases.next().unwrap(); let mean_stripe_n = self.mean_stripe_n; let mean_stripe_d = self.mean_stripe_d; let xs = self.xs_map.entry(log_base).or_insert_with(|| { let seed = EXAMPLE_SEED.fork(&log_base.to_string()); striped_random_natural_range( seed, Natural::ZERO, Natural::power_of_2(log_base), mean_stripe_n, mean_stripe_d, ) }); let before_point = xs.take(self.sizes.next().unwrap()).collect(); let non_repeating = xs.take(self.sizes.next().unwrap()).collect(); let repeating = xs.take(self.sizes.next().unwrap()).collect(); Some(( log_base, before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn special_random_large_type_gen_var_23( config: &GenConfig, ) -> It<(u64, Vec, RationalSequence)> { Box::new(RationalFromPowerOf2DigitsGenerator { mean_stripe_n: config.get_or("mean_stripe_n", 32), mean_stripe_d: config.get_or("mean_stripe_d", 1), log_bases: geometric_random_positive_unsigneds( EXAMPLE_SEED.fork("log_bases"), config.get_or("mean_log_base_n", 4), config.get_or("mean_log_base_d", 1), ), sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs_map: HashMap::new(), }) } struct RationalFromDigitsGenerator { mean_stripe_n: u64, mean_stripe_d: u64, bases: StripedRandomNaturalRangeToInfinity, sizes: GeometricRandomNaturalValues, xs_map: HashMap, } impl Iterator for RationalFromDigitsGenerator { type Item = (Natural, Vec, RationalSequence); fn next(&mut self) -> Option<(Natural, Vec, RationalSequence)> { let base = self.bases.next().unwrap(); let mean_stripe_n = self.mean_stripe_n; let mean_stripe_d = self.mean_stripe_d; let xs = self.xs_map.entry(base.clone()).or_insert_with(|| { let seed = EXAMPLE_SEED.fork(&base.to_string()); striped_random_natural_range( seed, Natural::ZERO, base.clone(), mean_stripe_n, mean_stripe_d, ) }); let before_point = xs.take(self.sizes.next().unwrap()).collect(); let non_repeating = xs.take(self.sizes.next().unwrap()).collect(); let repeating = xs.take(self.sizes.next().unwrap()).collect(); Some(( base, before_point, RationalSequence::from_vecs(non_repeating, repeating), )) } } pub fn special_random_large_type_gen_var_24( config: &GenConfig, ) -> It<(Natural, Vec, RationalSequence)> { Box::new(RationalFromDigitsGenerator { mean_stripe_n: config.get_or("mean_stripe_n", 32), mean_stripe_d: config.get_or("mean_stripe_d", 1), bases: striped_random_natural_range_to_infinity( EXAMPLE_SEED, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ), sizes: geometric_random_unsigneds( EXAMPLE_SEED.fork("sizes"), config.get_or("mean_length_n", 4), config.get_or("mean_length_d", 1), ), xs_map: HashMap::new(), }) } ================================================ FILE: malachite-nz/src/test_util/integer/arithmetic/add.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::basic::traits::Zero; pub fn integer_sum_alt>(xs: I) -> Integer { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { let mut s = x; for _ in 0..i.trailing_zeros() { s += stack.pop().unwrap(); } stack.push(s); } let mut s = Integer::ZERO; for x in stack { s += x; } s } ================================================ FILE: malachite-nz/src/test_util/integer/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 num::{BigInt, Integer, Zero}; pub fn num_divisible_by(x: &BigInt, y: &BigInt) -> bool { *x == BigInt::zero() || *y != BigInt::zero() && x.is_multiple_of(y) } ================================================ FILE: malachite-nz/src/test_util/integer/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . pub mod add; pub mod divisible_by; pub mod mul; pub mod sign; ================================================ FILE: malachite-nz/src/test_util/integer/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::basic::traits::{One, Zero}; pub fn integer_product_naive>(xs: I) -> Integer { let mut p = Integer::ONE; for x in xs { if x == 0 { return Integer::ZERO; } p *= x; } p } ================================================ FILE: malachite-nz/src/test_util/integer/arithmetic/sign.rs ================================================ // Copyright © 2026 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 num::BigInt; use num::bigint::Sign; use std::cmp::Ordering::{self, *}; pub fn num_sign(x: &BigInt) -> Ordering { match x.sign() { Sign::NoSign => Equal, Sign::Plus => Greater, Sign::Minus => Less, } } ================================================ FILE: malachite-nz/src/test_util/integer/comparison/mod.rs ================================================ // Copyright © 2026 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 . pub mod partial_cmp_primitive_int; pub mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/test_util/integer/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 num::BigInt; use std::cmp::Ordering; pub fn num_partial_cmp_primitive(x: &BigInt, u: T) -> Option where BigInt: From, { x.partial_cmp(&BigInt::from(u)) } ================================================ FILE: malachite-nz/src/test_util/integer/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 num::BigInt; pub fn num_partial_eq_primitive(x: &BigInt, i: T) -> bool where BigInt: From, { *x == BigInt::from(i) } ================================================ FILE: malachite-nz/src/test_util/integer/conversion/mod.rs ================================================ // Copyright © 2026 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 . pub mod to_twos_complement_limbs; ================================================ FILE: malachite-nz/src/test_util/integer/conversion/to_twos_complement_limbs.rs ================================================ // Copyright © 2026 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 crate::natural::arithmetic::sub::limbs_sub_limb_in_place; use crate::natural::logic::not::limbs_not_in_place; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::WrappingNegAssign; pub fn limbs_twos_complement_in_place_alt_1(limbs: &mut [Limb]) -> bool { let i = limbs.iter().copied().take_while(|&x| x == 0).count(); let len = limbs.len(); if i == len { return true; } limbs[i].wrapping_neg_assign(); let j = i + 1; if j != len { limbs_not_in_place(&mut limbs[j..]); } false } pub fn limbs_twos_complement_in_place_alt_2(limbs: &mut [Limb]) -> bool { let carry = limbs_sub_limb_in_place(limbs, 1); limbs_not_in_place(limbs); carry } ================================================ FILE: malachite-nz/src/test_util/integer/logic/and.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::test_util::integer::logic::{integer_op_bits, integer_op_limbs}; pub fn integer_and_alt_1(x: &Integer, y: &Integer) -> Integer { integer_op_bits(&|a, b| a && b, x, y) } pub fn integer_and_alt_2(x: &Integer, y: &Integer) -> Integer { integer_op_limbs(&|a, b| a & b, x, y) } ================================================ FILE: malachite-nz/src/test_util/integer/logic/checked_count_ones.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::{BitIterable, CountOnes}; pub fn integer_checked_count_ones_alt_1(n: &Integer) -> Option { if *n >= 0 { Some(u64::wrapping_from(n.bits().filter(|&b| b).count())) } else { None } } pub fn integer_checked_count_ones_alt_2(n: &Integer) -> Option { if *n >= 0 { Some(n.twos_complement_limbs().map(CountOnes::count_ones).sum()) } else { None } } ================================================ FILE: malachite-nz/src/test_util/integer/logic/checked_count_zeros.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::{BitIterable, CountZeros}; pub fn integer_checked_count_zeros_alt_1(n: &Integer) -> Option { if *n < 0 { Some(u64::wrapping_from(n.bits().filter(|&b| !b).count())) } else { None } } pub fn integer_checked_count_zeros_alt_2(n: &Integer) -> Option { if *n < 0 { Some(n.twos_complement_limbs().map(CountZeros::count_zeros).sum()) } else { None } } ================================================ FILE: malachite-nz/src/test_util/integer/logic/checked_hamming_distance.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::platform::Limb; use malachite_base::num::logic::traits::{BitIterable, HammingDistance}; use std::iter::repeat; pub fn integer_checked_hamming_distance_alt_1(x: &Integer, y: &Integer) -> Option { let negative = *x < 0; if negative != (*y < 0) { return None; } let bit_zip: Box> = if x.bits().count() >= y.bits().count() { Box::new(x.bits().zip(y.bits().chain(repeat(negative)))) } else { Box::new(x.bits().chain(repeat(negative)).zip(y.bits())) }; let mut distance = 0u64; for (b, c) in bit_zip { if b != c { distance += 1; } } Some(distance) } pub fn rug_checked_hamming_distance(x: &rug::Integer, y: &rug::Integer) -> Option { x.hamming_dist(y).map(u64::from) } pub fn integer_checked_hamming_distance_alt_2(x: &Integer, y: &Integer) -> Option { if (*x < 0) != (*y < 0) { return None; } let extension = if *x < 0 { Limb::MAX } else { 0 }; let limb_zip: Box> = if x.twos_complement_limbs().count() >= y.twos_complement_limbs().count() { Box::new( x.twos_complement_limbs() .zip(y.twos_complement_limbs().chain(repeat(extension))), ) } else { Box::new( x.twos_complement_limbs() .chain(repeat(extension)) .zip(y.twos_complement_limbs()), ) }; let mut distance = 0u64; for (x, y) in limb_zip { distance += x.hamming_distance(y); } Some(distance) } ================================================ FILE: malachite-nz/src/test_util/integer/logic/from_bits.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use itertools::Itertools; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; pub fn from_bits_asc_naive>(bits: I) -> Integer { let bits = bits.collect_vec(); if bits.is_empty() { return Integer::ZERO; } let mut n; if *bits.last().unwrap() { n = Integer::NEGATIVE_ONE; for i in bits .iter() .enumerate() .filter_map(|(i, &bit)| if bit { None } else { Some(u64::exact_from(i)) }) { n.clear_bit(i); } } else { n = Integer::ZERO; for i in bits .iter() .enumerate() .filter_map(|(i, &bit)| if bit { Some(u64::exact_from(i)) } else { None }) { n.set_bit(i); } }; n } pub fn from_bits_desc_naive>(bits: I) -> Integer { let bits = bits.collect_vec(); if bits.is_empty() { return Integer::ZERO; } let mut n; if bits[0] { n = Integer::NEGATIVE_ONE; for i in bits.iter().rev().enumerate().filter_map(|(i, &bit)| { if bit { None } else { Some(u64::exact_from(i)) } }) { n.clear_bit(i); } } else { n = Integer::ZERO; for i in bits.iter().rev().enumerate().filter_map(|(i, &bit)| { if bit { Some(u64::exact_from(i)) } else { None } }) { n.set_bit(i); } }; n } ================================================ FILE: malachite-nz/src/test_util/integer/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitIterable, SignificantBits}; pub fn integer_index_of_next_false_bit_alt(n: &Integer, u: u64) -> Option { if u >= n.significant_bits() { if *n >= 0 { Some(u) } else { None } } else { for (i, bit) in n.bits().enumerate().skip(usize::exact_from(u)) { if !bit { return Some(u64::exact_from(i)); } } None } } ================================================ FILE: malachite-nz/src/test_util/integer/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitIterable, SignificantBits}; pub fn integer_index_of_next_true_bit_alt(n: &Integer, u: u64) -> Option { if u >= n.significant_bits() { if *n >= 0 { None } else { Some(u) } } else { for (i, bit) in n.bits().enumerate().skip(usize::exact_from(u)) { if bit { return Some(u64::exact_from(i)); } } None } } ================================================ FILE: malachite-nz/src/test_util/integer/logic/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::platform::Limb; use malachite_base::num::logic::traits::{BitConvertible, BitIterable}; use std::iter::repeat; pub fn integer_op_bits(bit_fn: &dyn Fn(bool, bool) -> bool, x: &Integer, y: &Integer) -> Integer { let x_negative = *x < 0; let y_negative = *y < 0; let bit_zip: Box> = if x.bits().count() >= y.bits().count() { Box::new(x.bits().zip(y.bits().chain(repeat(y_negative)))) } else { Box::new(x.bits().chain(repeat(x_negative)).zip(y.bits())) }; Integer::from_bits_asc(bit_zip.map(|(b, c)| bit_fn(b, c))) } pub fn integer_op_limbs(limb_fn: &dyn Fn(Limb, Limb) -> Limb, x: &Integer, y: &Integer) -> Integer { let x_extension = if *x < 0 { Limb::MAX } else { 0 }; let y_extension = if *y < 0 { Limb::MAX } else { 0 }; let limb_zip: Box> = if x.twos_complement_limbs().count() >= y.twos_complement_limbs().count() { Box::new( x.twos_complement_limbs() .zip(y.twos_complement_limbs().chain(repeat(y_extension))), ) } else { Box::new( x.twos_complement_limbs() .chain(repeat(x_extension)) .zip(y.twos_complement_limbs()), ) }; let mut limbs = Vec::new(); for (x, y) in limb_zip { limbs.push(limb_fn(x, y)); } Integer::from_owned_twos_complement_limbs_asc(limbs) } pub mod and; pub mod checked_count_ones; pub mod checked_count_zeros; pub mod checked_hamming_distance; pub mod from_bits; pub mod index_of_next_false_bit; pub mod index_of_next_true_bit; pub mod or; pub mod to_bits; pub mod trailing_zeros; pub mod xor; ================================================ FILE: malachite-nz/src/test_util/integer/logic/or.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::test_util::integer::logic::{integer_op_bits, integer_op_limbs}; pub fn integer_or_alt_1(x: &Integer, y: &Integer) -> Integer { integer_op_bits(&|a, b| a || b, x, y) } pub fn integer_or_alt_2(x: &Integer, y: &Integer) -> Integer { integer_op_limbs(&|a, b| a | b, x, y) } ================================================ FILE: malachite-nz/src/test_util/integer/logic/to_bits.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; pub fn to_bits_asc_naive(n: &Integer) -> Vec { let mut bits = Vec::new(); if *n == 0 { return bits; } for i in 0..n.significant_bits() { bits.push(n.get_bit(i)); } let last_bit = *bits.last().unwrap(); if last_bit != (*n < 0) { bits.push(!last_bit); } bits } pub fn to_bits_desc_naive(n: &Integer) -> Vec { let mut bits = Vec::new(); if *n == 0 { return bits; } let significant_bits = n.significant_bits(); let last_bit = n.get_bit(significant_bits - 1); if last_bit != (*n < 0) { bits.push(!last_bit); } for i in (0..significant_bits).rev() { bits.push(n.get_bit(i)); } bits } ================================================ FILE: malachite-nz/src/test_util/integer/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::BitIterable; pub fn integer_trailing_zeros_alt(n: &Integer) -> Option { if *n == 0 { None } else { Some(u64::wrapping_from(n.bits().take_while(|&b| !b).count())) } } ================================================ FILE: malachite-nz/src/test_util/integer/logic/xor.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::test_util::integer::logic::{integer_op_bits, integer_op_limbs}; pub fn integer_xor_alt_1(x: &Integer, y: &Integer) -> Integer { integer_op_bits(&|a, b| a ^ b, x, y) } pub fn integer_xor_alt_2(x: &Integer, y: &Integer) -> Integer { integer_op_limbs(&|a, b| a ^ b, x, y) } ================================================ FILE: malachite-nz/src/test_util/integer/mod.rs ================================================ // Copyright © 2026 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 . pub mod arithmetic; pub mod comparison; pub mod conversion; pub mod logic; pub mod random; ================================================ FILE: malachite-nz/src/test_util/integer/random/mod.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::itertools::Itertools; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{MomentStats, moment_stats}; pub fn random_integers_helper_helper>( xs: I, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { let actual_values = xs .clone() .map(|x| Integer::to_string(&x)) .take(20) .collect_vec(); let actual_values = actual_values.iter().map(String::as_str).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .into_iter() .map(|(x, freq)| (x.to_string(), freq)) .collect_vec(); let actual_common_values = actual_common_values .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.clone().take(1000000)); let (median_lo, median_hi) = ( median_lo.to_string(), median_hi.map(|x| Integer::to_string(&x)), ); let actual_sample_median = (median_lo.as_str(), median_hi.as_deref()); let actual_sample_moment_stats = moment_stats(xs.take(1000000).map(|x| f64::rounding_from(&x, Nearest).0)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), actual_sample_median, actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats ) ); } ================================================ FILE: malachite-nz/src/test_util/mod.rs ================================================ // Copyright © 2026 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 . pub mod bench; pub mod common; pub mod extra_variadic; pub mod generators; pub mod integer; pub mod natural; ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/add.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::basic::traits::Zero; pub fn natural_sum_alt>(xs: I) -> Natural { let mut stack = Vec::new(); for (i, x) in xs.enumerate().map(|(i, x)| (i + 1, x)) { let mut s = x; for _ in 0..i.trailing_zeros() { s += stack.pop().unwrap(); } stack.push(s); } let mut s = Natural::ZERO; for x in stack { s += x; } s } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::natural::arithmetic::div_round::double_cmp; use crate::natural::exhaustive::exhaustive_natural_inclusive_range; use malachite_base::num::arithmetic::traits::{DivExact, Factorial, Gcd, Parity}; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use std::cmp::Ordering::*; pub fn binomial_coefficient_naive_1(n: Natural, mut k: Natural) -> Natural { if k > n { return Natural::ZERO; } if k == 0u32 || n == k { return Natural::ONE; } if double_cmp(&k, &n) == Greater { k = &n - &k; } let k_u64 = u64::exact_from(&k); exhaustive_natural_inclusive_range(&n - k + Natural::ONE, n) .product::() .div_exact(Natural::factorial(k_u64)) } pub fn binomial_coefficient_naive_2(n: Natural, mut k: Natural) -> Natural { if k > n { return Natural::ZERO; } if k == 0u32 || n == k { return Natural::ONE; } if double_cmp(&k, &n) == Greater { k = &n - &k; } if k == 1u32 { n } else if k == 2u32 { (&n >> 1) * (if n.even() { n - Natural::ONE } else { n }) } else { let mut product = n - &k + Natural::ONE; let mut numerator = product.clone(); for i in exhaustive_natural_inclusive_range(Natural::TWO, k) { numerator += Natural::ONE; let gcd = (&numerator).gcd(&i); product /= i.div_exact(&gcd); product *= (&numerator).div_exact(gcd); } product } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/checked_sub.rs ================================================ // Copyright © 2026 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 std::ops::Sub; pub fn checked_sub(x: T, y: T) -> Option<::Output> { if x >= y { Some(x - y) } else { None } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/div.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_div_qr_1n_pi1` contributed to the GNU project by Niels Möller. // // `mpn_div_qr_1` contributed to the GNU project by Niels Möller and Torbjörn Granlund. // // Copyright © 1991, 1993, 1994, 1996, 1998-2000, 2002, 2003, 2013 Free Software Foundation, // Inc. // // 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 crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::div::div_by_preinversion; use crate::natural::arithmetic::div_mod::{div_mod_by_preinversion, limbs_invert_limb}; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{ OverflowingAddAssign, WrappingAddAssign, WrappingSubAssign, XMulYToZZ, }; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`, where `qp == up`, but not computing the remainder. fn limbs_div_limb_normalized_in_place(ns: &mut [Limb], ns_high: Limb, d: Limb, d_inv: Limb) { let len = ns.len(); if len == 1 { ns[0] = div_by_preinversion(ns_high, ns[0], d, d_inv); return; } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let (mut q_high, mut q_low) = Limb::x_mul_y_to_zz(d_inv, ns_high); q_high.wrapping_add_assign(ns_high); let second_highest_limb = ns[len - 1]; ns[len - 1] = q_high; let (sum, mut big_carry) = DoubleLimb::join_halves(second_highest_limb, ns[len - 2]) .overflowing_add(DoubleLimb::from(power_of_2) * DoubleLimb::from(ns_high)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for j in (0..len - 2).rev() { let (t, r) = Limb::x_mul_y_to_zz(sum_high, d_inv); let mut q = DoubleLimb::from(sum_high) + DoubleLimb::from(t) + DoubleLimb::from(q_low); q_low = r; if big_carry { q.wrapping_add_assign(DoubleLimb::join_halves(1, d_inv)); if sum_low.overflowing_add_assign(power_of_2) { sum_low.wrapping_sub_assign(d); q.wrapping_add_assign(1); } } let q_higher; (q_higher, ns[j + 1]) = q.split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut ns[j + 2..], q_higher)); let sum; (sum, big_carry) = DoubleLimb::join_halves(sum_low, ns[j]) .overflowing_add(DoubleLimb::from(sum_high) * DoubleLimb::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); } let mut q_high = 0; if big_carry { q_high += 1; sum_high.wrapping_sub_assign(d); } if sum_high >= d { q_high += 1; sum_high.wrapping_sub_assign(d); } let t = div_by_preinversion(sum_high, sum_low, d, d_inv); let (q_high, q_low) = DoubleLimb::join_halves(q_high, q_low) .wrapping_add(DoubleLimb::from(t)) .split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut ns[1..], q_high)); ns[0] = q_low; } // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`, but not computing the remainder. fn limbs_div_limb_normalized_to_out( out: &mut [Limb], ns: &[Limb], ns_high: Limb, d: Limb, d_inv: Limb, ) { let len = ns.len(); if len == 1 { out[0] = div_by_preinversion(ns_high, ns[0], d, d_inv); return; } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let (mut q_high, mut q_low) = Limb::x_mul_y_to_zz(d_inv, ns_high); q_high.wrapping_add_assign(ns_high); out[len - 1] = q_high; let (sum, mut big_carry) = DoubleLimb::join_halves(ns[len - 1], ns[len - 2]) .overflowing_add(DoubleLimb::from(power_of_2) * DoubleLimb::from(ns_high)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for j in (0..len - 2).rev() { let (t, r) = Limb::x_mul_y_to_zz(sum_high, d_inv); let mut q = DoubleLimb::from(sum_high) + DoubleLimb::from(t) + DoubleLimb::from(q_low); q_low = r; if big_carry { q.wrapping_add_assign(DoubleLimb::join_halves(1, d_inv)); if sum_low.overflowing_add_assign(power_of_2) { sum_low.wrapping_sub_assign(d); q.wrapping_add_assign(1); } } let q_higher; (q_higher, out[j + 1]) = q.split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut out[j + 2..], q_higher)); let sum; (sum, big_carry) = DoubleLimb::join_halves(sum_low, ns[j]) .overflowing_add(DoubleLimb::from(sum_high) * DoubleLimb::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); } let mut q_high = 0; if big_carry { q_high += 1; sum_high.wrapping_sub_assign(d); } if sum_high >= d { q_high += 1; sum_high.wrapping_sub_assign(d); } let t = div_by_preinversion(sum_high, sum_low, d, d_inv); (q_high, out[0]) = DoubleLimb::join_halves(q_high, q_low) .wrapping_add(DoubleLimb::from(t)) .split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut out[1..], q_high)); } // This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, but not computing // the remainder. Experiments show that this is always slower than `limbs_div_limb_to_out`. pub fn limbs_div_limb_to_out_alt(out: &mut [Limb], ns: &[Limb], d: Limb) { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); assert!(out.len() >= len); let len_minus_1 = len - 1; let mut highest_limb = ns[len_minus_1]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { let adjust = highest_limb >= d; if adjust { highest_limb -= d; } out[len_minus_1] = Limb::from(adjust); let d_inv = limbs_invert_limb::(d); limbs_div_limb_normalized_to_out(out, &ns[..len_minus_1], highest_limb, d, d_inv); } else { let d = d << bits; let ns_high = limbs_shl_to_out(out, ns, bits); let d_inv = limbs_invert_limb::(d); let r; (out[len_minus_1], r) = div_mod_by_preinversion(ns_high, out[len_minus_1], d, d_inv); limbs_div_limb_normalized_in_place(&mut out[..len_minus_1], r, d, d_inv); } } // This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, where `qp == up`, // but not computing the remainder. Experiments show that this is always slower than // `limbs_div_limb_in_place`. pub fn limbs_div_limb_in_place_alt(ns: &mut [Limb], d: Limb) { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let len_minus_1 = len - 1; let mut highest_limb = ns[len_minus_1]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { let adjust = highest_limb >= d; if adjust { highest_limb -= d; } ns[len_minus_1] = Limb::from(adjust); let d_inv = limbs_invert_limb::(d); limbs_div_limb_normalized_in_place(&mut ns[..len_minus_1], highest_limb, d, d_inv); } else { let d = d << bits; let ns_high = limbs_slice_shl_in_place(ns, bits); let d_inv = limbs_invert_limb::(d); let r; (ns[len_minus_1], r) = div_mod_by_preinversion(ns_high, ns[len_minus_1], d, d_inv); limbs_div_limb_normalized_in_place(&mut ns[..len_minus_1], r, d, d_inv); } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/div_exact.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::div_exact::MAX_OVER_3; use crate::platform::Limb; use malachite_base::num::arithmetic::traits::{WrappingMulAssign, WrappingSubAssign}; use malachite_base::num::basic::integers::PrimitiveInt; // This is equivalent to `MODLIMB_INVERSE_3` from `gmp-impl.h`, GMP 6.2.1. const MODLIMB_INVERSE_3: Limb = (MAX_OVER_3 << 1) | 1; const CEIL_MAX_OVER_3: Limb = MAX_OVER_3 + 1; const CEIL_2_MAX_OVER_3: Limb = ((Limb::MAX >> 1) / 3 + 1) | (1 << (Limb::WIDTH - 1)); /// Benchmarks show that this algorithm is always worse than the default. /// /// This is equivalent to `mpn_divexact_by3c` from `mpn/generic/diveby3.c`, GMP 6.2.1, with /// `DIVEXACT_BY3_METHOD == 1`, no carry-in, and no return value. pub fn limbs_div_exact_3_to_out_alt(out: &mut [Limb], ns: &[Limb]) { let len = ns.len(); assert_ne!(len, 0); assert!(out.len() >= len); let (ns_last, ns_init) = ns.split_last().unwrap(); let (out_last, out_init) = out[..len].split_last_mut().unwrap(); let mut big_carry = 0; for (out_q, n) in out_init.iter_mut().zip(ns_init.iter()) { let (diff, carry) = n.overflowing_sub(big_carry); big_carry = Limb::from(carry); let q = diff.wrapping_mul(MODLIMB_INVERSE_3); *out_q = q; if q >= CEIL_MAX_OVER_3 { big_carry += 1; if q >= CEIL_2_MAX_OVER_3 { big_carry += 1; } } } *out_last = ns_last .wrapping_sub(big_carry) .wrapping_mul(MODLIMB_INVERSE_3); } /// Benchmarks show that this algorithm is always worse than the default. /// /// This is equivalent to `mpn_divexact_by3c` from `mpn/generic/diveby3.c`, GMP 6.2.1, with /// `DIVEXACT_BY3_METHOD == 1`, no carry-in, and no return value, where `rp == up`. pub fn limbs_div_exact_3_in_place_alt(ns: &mut [Limb]) { let len = ns.len(); assert_ne!(len, 0); let (ns_last, ns_init) = ns.split_last_mut().unwrap(); let mut big_carry = 0; for n in &mut *ns_init { let (diff, carry) = n.overflowing_sub(big_carry); big_carry = Limb::from(carry); let q = diff.wrapping_mul(MODLIMB_INVERSE_3); *n = q; if q >= CEIL_MAX_OVER_3 { big_carry += 1; if q >= CEIL_2_MAX_OVER_3 { big_carry += 1; } } } ns_last.wrapping_sub_assign(big_carry); ns_last.wrapping_mul_assign(MODLIMB_INVERSE_3); } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/div_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // `mpn_div_qr_1n_pi1` contributed to the GNU project by Niels Möller // // `mpn_div_qr_1` contributed to the GNU project by Niels Möller and Torbjörn Granlund // // Copyright © 1991, 1993, 1994, 1996, 1998-2000, 2002, 2003, 2013 Free Software Foundation, // Inc. // // 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 crate::natural::arithmetic::add::limbs_slice_add_limb_in_place; use crate::natural::arithmetic::div_mod::{div_mod_by_preinversion, limbs_invert_limb}; use crate::natural::arithmetic::shl::{limbs_shl_to_out, limbs_slice_shl_in_place}; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{ DivRem, OverflowingAddAssign, WrappingAddAssign, WrappingSubAssign, XMulYToZZ, }; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; pub fn rug_ceiling_div_neg_mod(x: rug::Integer, y: rug::Integer) -> (rug::Integer, rug::Integer) { let (quotient, remainder) = x.div_rem_ceil(y); (quotient, -remainder) } pub fn limbs_div_limb_to_out_mod_naive(out: &mut [Limb], xs: &[Limb], d: Limb) -> Limb { assert!(out.len() >= xs.len()); let d = DoubleLimb::from(d); let mut upper = 0; for (out_limb, &in_limb) in out.iter_mut().zip(xs.iter()).rev() { let (q, r) = DoubleLimb::join_halves(upper, in_limb).div_rem(d); *out_limb = q.lower_half(); upper = r.lower_half(); } upper } pub fn limbs_div_limb_in_place_mod_naive(xs: &mut [Limb], d: Limb) -> Limb { let d = DoubleLimb::from(d); let mut upper = 0; for limb in xs.iter_mut().rev() { let (q, r) = DoubleLimb::join_halves(upper, *limb).div_rem(d); *limb = q.lower_half(); upper = r.lower_half(); } upper } // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`, where `qp == up`. fn limbs_div_limb_normalized_in_place_mod( ns: &mut [Limb], ns_high: Limb, d: Limb, d_inv: Limb, ) -> Limb { let len = ns.len(); if len == 1 { let r; (ns[0], r) = div_mod_by_preinversion(ns_high, ns[0], d, d_inv); return r; } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let (mut q_high, mut q_low) = Limb::x_mul_y_to_zz(d_inv, ns_high); q_high.wrapping_add_assign(ns_high); let ns_2nd_to_last = ns[len - 1]; ns[len - 1] = q_high; let (sum, mut big_carry) = DoubleLimb::join_halves(ns_2nd_to_last, ns[len - 2]) .overflowing_add(DoubleLimb::from(power_of_2) * DoubleLimb::from(ns_high)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for j in (0..len - 2).rev() { let (t, r) = Limb::x_mul_y_to_zz(sum_high, d_inv); let mut q = DoubleLimb::from(sum_high) + DoubleLimb::from(t) + DoubleLimb::from(q_low); q_low = r; if big_carry { q.wrapping_add_assign(DoubleLimb::join_halves(1, d_inv)); if sum_low.overflowing_add_assign(power_of_2) { sum_low.wrapping_sub_assign(d); q.wrapping_add_assign(1); } } let (q_higher, q_high) = q.split_in_half(); ns[j + 1] = q_high; assert!(!limbs_slice_add_limb_in_place(&mut ns[j + 2..], q_higher)); let (sum, carry) = DoubleLimb::join_halves(sum_low, ns[j]) .overflowing_add(DoubleLimb::from(sum_high) * DoubleLimb::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); big_carry = carry; } let mut q_high = 0; if big_carry { q_high += 1; sum_high.wrapping_sub_assign(d); } if sum_high >= d { q_high += 1; sum_high.wrapping_sub_assign(d); } let (t, r) = div_mod_by_preinversion(sum_high, sum_low, d, d_inv); let (q_high, q_low) = DoubleLimb::join_halves(q_high, q_low) .wrapping_add(DoubleLimb::from(t)) .split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut ns[1..], q_high)); ns[0] = q_low; r } // The high bit of `d` must be set. // // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(n)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_div_qr_1n_pi1` from `mpn/generic/div_qr_1n_pi1.c`, GMP 6.2.1, with // `DIV_QR_1N_METHOD == 2`. fn limbs_div_limb_normalized_to_out_mod( out: &mut [Limb], ns: &[Limb], n_last: Limb, d: Limb, d_inv: Limb, ) -> Limb { let len = ns.len(); if len == 1 { let (q, r) = div_mod_by_preinversion(n_last, ns[0], d, d_inv); out[0] = q; return r; } let power_of_2 = d.wrapping_neg().wrapping_mul(d_inv); let (mut q_high, mut q_low) = Limb::x_mul_y_to_zz(d_inv, n_last); q_high.wrapping_add_assign(n_last); out[len - 1] = q_high; let (sum, mut big_carry) = DoubleLimb::join_halves(ns[len - 1], ns[len - 2]) .overflowing_add(DoubleLimb::from(power_of_2) * DoubleLimb::from(n_last)); let (mut sum_high, mut sum_low) = sum.split_in_half(); for j in (0..len - 2).rev() { let (t, r) = Limb::x_mul_y_to_zz(sum_high, d_inv); let mut q = DoubleLimb::from(sum_high) + DoubleLimb::from(t) + DoubleLimb::from(q_low); q_low = r; if big_carry { q.wrapping_add_assign(DoubleLimb::join_halves(1, d_inv)); let (sum, carry) = sum_low.overflowing_add(power_of_2); sum_low = sum; if carry { sum_low.wrapping_sub_assign(d); q.wrapping_add_assign(1); } } let (q_higher, q_high) = q.split_in_half(); out[j + 1] = q_high; assert!(!limbs_slice_add_limb_in_place(&mut out[j + 2..], q_higher)); let (sum, carry) = DoubleLimb::join_halves(sum_low, ns[j]) .overflowing_add(DoubleLimb::from(sum_high) * DoubleLimb::from(power_of_2)); sum_high = sum.upper_half(); sum_low = sum.lower_half(); big_carry = carry; } let mut q_high = 0; if big_carry { q_high += 1; sum_high.wrapping_sub_assign(d); } if sum_high >= d { q_high += 1; sum_high.wrapping_sub_assign(d); } let (t, r) = div_mod_by_preinversion(sum_high, sum_low, d, d_inv); let (q_high, q_low) = DoubleLimb::join_halves(q_high, q_low) .wrapping_add(DoubleLimb::from(t)) .split_in_half(); assert!(!limbs_slice_add_limb_in_place(&mut out[1..], q_high)); out[0] = q_low; r } /// This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, where `len > 1`. /// Experiments show that this is always slower than `limbs_div_limb_to_out_mod`. pub fn limbs_div_limb_to_out_mod_alt(out: &mut [Limb], ns: &[Limb], d: Limb) -> Limb { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let out = &mut out[..len]; assert!(out.len() >= len); let (ns_last, ns_init) = ns.split_last().unwrap(); let mut ns_last = *ns_last; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { let (out_last, out_init) = out.split_last_mut().unwrap(); *out_last = if ns_last >= d { ns_last -= d; 1 } else { 0 }; let d_inv = limbs_invert_limb::(d); limbs_div_limb_normalized_to_out_mod(out_init, ns_init, ns_last, d, d_inv) } else { let d = d << bits; let ns_last = limbs_shl_to_out(out, ns, bits); let d_inv = limbs_invert_limb::(d); let (out_last, out_init) = out.split_last_mut().unwrap(); let (q, r) = div_mod_by_preinversion(ns_last, *out_last, d, d_inv); *out_last = q; limbs_div_limb_normalized_in_place_mod(out_init, r, d, d_inv) >> bits } } /// This is equivalent to `mpn_div_qr_1` from `mpn/generic/div_qr_1.c`, GMP 6.2.1, where `qp == up` /// and `len > 1`. Experiments show that this is always slower than `limbs_div_limb_in_place_mod`. pub fn limbs_div_limb_in_place_mod_alt(ns: &mut [Limb], d: Limb) -> Limb { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let len_minus_1 = len - 1; let mut ns_last = ns[len_minus_1]; let bits = LeadingZeros::leading_zeros(d); if bits == 0 { ns[len_minus_1] = if ns_last >= d { ns_last -= d; 1 } else { 0 }; let d_inv = limbs_invert_limb::(d); limbs_div_limb_normalized_in_place_mod(&mut ns[..len_minus_1], ns_last, d, d_inv) } else { let d = d << bits; let ns_last = limbs_slice_shl_in_place(ns, bits); let d_inv = limbs_invert_limb::(d); let (q, r) = div_mod_by_preinversion(ns_last, ns[len_minus_1], d, d_inv); ns[len_minus_1] = q; limbs_div_limb_normalized_in_place_mod(&mut ns[..len_minus_1], r, d, d_inv) >> bits } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000-2002 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::divisible_by::limbs_divisible_by_limb; use crate::natural::arithmetic::mod_op::limbs_mod_limb; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use num::{BigUint, Integer, Zero}; pub fn num_divisible_by(x: &BigUint, y: &BigUint) -> bool { *x == BigUint::zero() || *y != BigUint::zero() && x.is_multiple_of(y) } /// Benchmarks show that this is never faster than just calling `limbs_divisible_by_limb`. /// /// ns.len() must be greater than 1; divisor must be nonzero. /// /// This is equivalent to `mpz_divisible_ui_p` from `mpz/divis_ui.c`, GMP 6.2.1, where `a` is /// non-negative. #[allow(clippy::absurd_extreme_comparisons)] pub fn combined_limbs_divisible_by_limb(ns: &[Limb], d: Limb) -> bool { if ns.len() <= BMOD_1_TO_MOD_1_THRESHOLD { limbs_divisible_by_limb(ns, d) } else { limbs_mod_limb::(ns, d) == 0 } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 2000-2002, 2012 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::divisible_by::{ limbs_divisible_by_limb, limbs_divisible_by_val_ref, }; use crate::natural::arithmetic::eq_mod::limbs_eq_limb_mod_limb; use crate::natural::arithmetic::mod_op::{limbs_mod, limbs_mod_limb}; use crate::natural::arithmetic::sub::{limbs_sub, limbs_sub_limb}; use crate::natural::comparison::cmp::limbs_cmp; use crate::platform::{BMOD_1_TO_MOD_1_THRESHOLD, DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::slices::slice_trailing_zeros; use std::cmp::Ordering::*; pub fn limbs_eq_limb_mod_naive_1(xs: &[Limb], y: Limb, ms: &[Limb]) -> bool { assert!(xs.len() > 1); assert!(ms.len() > 1); let mut xs_mod = if xs.len() >= ms.len() { limbs_mod(xs, ms) } else { xs.to_vec() }; xs_mod.truncate(xs_mod.len() - slice_trailing_zeros(&xs_mod)); xs_mod == [y] } pub fn limbs_eq_limb_mod_naive_2(xs: &[Limb], y: Limb, ms: &[Limb]) -> bool { let mut diff = limbs_sub_limb(xs, y).0; diff.truncate(diff.len() - slice_trailing_zeros(&diff)); diff.len() >= ms.len() && limbs_divisible_by_val_ref(&mut diff, ms) } pub fn limbs_eq_mod_limb_naive_1(xs: &[Limb], ys: &[Limb], ms: Limb) -> bool { assert!(xs.len() > 1); assert!(ys.len() > 1); limbs_mod_limb::(xs, ms) == limbs_mod_limb::(ys, ms) } pub fn limbs_eq_mod_limb_naive_2(xs: &[Limb], ys: &[Limb], ms: Limb) -> bool { if xs == ys { return true; } let mut diff = if limbs_cmp(xs, ys) >= Equal { limbs_sub(xs, ys) } else { limbs_sub(ys, xs) } .0; diff.truncate(diff.len() - slice_trailing_zeros(&diff)); if diff.len() == 1 { diff[0].divisible_by(ms) } else { limbs_divisible_by_limb(&diff, ms) } } pub fn limbs_eq_mod_naive_1(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { let mut xs_mod = if xs.len() >= ms.len() { limbs_mod(xs, ms) } else { xs.to_vec() }; let mut ys_mod = if ys.len() >= ms.len() { limbs_mod(ys, ms) } else { ys.to_vec() }; xs_mod.truncate(xs_mod.len() - slice_trailing_zeros(&xs_mod)); ys_mod.truncate(ys_mod.len() - slice_trailing_zeros(&ys_mod)); limbs_cmp(&xs_mod, &ys_mod) == Equal } pub fn limbs_eq_mod_naive_2(xs: &[Limb], ys: &[Limb], ms: &[Limb]) -> bool { if xs == ys { return true; } let mut diff = if limbs_cmp(xs, ys) >= Equal { limbs_sub(xs, ys) } else { limbs_sub(ys, xs) } .0; diff.truncate(diff.len() - slice_trailing_zeros(&diff)); diff.len() >= ms.len() && limbs_divisible_by_val_ref(&mut diff, ms) } /// Benchmarks show that this is never faster than just calling `limbs_eq_limb_mod_limb`. /// /// xs.len() must be greater than 1; m must be nonzero. /// /// This is equivalent to `mpz_congruent_ui_p` from `mpz/cong_ui.c`, GMP 6.2.1, where `a` is /// non-negative. pub fn combined_limbs_eq_limb_mod_limb(xs: &[Limb], y: Limb, m: Limb) -> bool { if xs.len() < BMOD_1_TO_MOD_1_THRESHOLD { limbs_mod_limb::(xs, m) == y % m } else { limbs_eq_limb_mod_limb(xs, y, m) } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{DivExact, DivMod, DivRound, NegAssign}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::rounding_modes::RoundingMode::*; use std::mem::swap; pub fn extended_gcd_euclidean_natural( mut a: Natural, mut b: Natural, ) -> (Natural, Integer, Integer) { let mut stack = Vec::new(); let gcd; let mut x; let mut y; loop { if a == 0u32 && b == 0u32 { (gcd, x, y) = (a, Integer::ZERO, Integer::ZERO); break; } else if a == b || a == 0u32 { (gcd, x, y) = (b, Integer::ZERO, Integer::ONE); break; } let (q, r) = (&b).div_mod(&a); stack.push(q); swap(&mut a, &mut b); a = r; } for q in stack.into_iter().rev() { swap(&mut x, &mut y); x -= Integer::from(q) * &y; } (gcd, x, y) } // This is equivalent to `n_xgcd` from `ulong_extras/xgcd.c`, FLINT 2.7.1, extended to `Natural`s // and with an adjustment to find the minimal cofactors. pub fn extended_gcd_binary_natural(mut a: Natural, mut b: Natural) -> (Natural, Integer, Integer) { if a == 0u32 && b == 0u32 { return (Natural::ZERO, Integer::ZERO, Integer::ZERO); } else if a == b || a == 0u32 { return (b, Integer::ZERO, Integer::ONE); } else if b == 0u32 { return (a, Integer::ONE, Integer::ZERO); } let mut swapped = false; if a < b { swap(&mut a, &mut b); swapped = true; } let mut u1 = Integer::ONE; let mut v2 = Integer::ONE; let mut u2 = Integer::ZERO; let mut v1 = Integer::ZERO; let mut u3 = a.clone(); let mut v3 = b.clone(); let mut d; let mut t2; let mut t1; while v3 != 0u32 { d = &u3 - &v3; if u3 < (&v3 << 2) { if d < v3 { // quot = 1 t2 = v2.clone(); t1 = u2.clone(); u2 -= u1; u2.neg_assign(); u1 = t1; u3 = v3; v2 -= v1; v2.neg_assign(); v1 = t2; v3 = d; } else if d < (&v3 << 1) { // quot = 2 t1 = u2.clone(); u2 = u1 - (&u2 << 1); u1 = t1; u3 = v3; t2 = v2.clone(); v2 = v1 - (v2 << 1); v1 = t2; v3 = d - &u3; } else { // quot = 3 t1 = u2.clone(); u2 = u1 - Integer::from(3u32) * &u2; u1 = t1; u3 = v3; t2 = v2.clone(); v2 = v1 - Integer::from(3u32) * &v2; v1 = t2; v3 = d - (&u3 << 1); } } else { let (quot, rem) = u3.div_mod(&v3); let quot = Integer::from(quot); t1 = u2.clone(); u2 = u1 - " * &u2; u1 = t1; u3 = v3.clone(); t2 = v2.clone(); v2 = v1 - quot * &v2; v1 = t2; v3 = rem; } } // The cofactors at this point are not necessarily minimal, so we may need to adjust. let gcd = u3; let mut x = u1; let mut y = v1; let two_limit_a = Integer::from(a.div_exact(&gcd)); let two_limit_b = Integer::from(b.div_exact(&gcd)); let limit_b = &two_limit_b >> 1u32; if x > limit_b { let k = (&x - limit_b).div_round(&two_limit_b, Ceiling).0; x -= two_limit_b * &k; y += two_limit_a * k; } if swapped { swap(&mut x, &mut y); } (gcd, x, y) } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::SaturatingSubAssign; use malachite_base::num::basic::traits::One; pub fn factorial_naive(mut n: u64) -> Natural { let mut f = Natural::ONE; while n != 0 { f *= Natural::from(n); n -= 1; } f } pub fn double_factorial_naive(mut n: u64) -> Natural { let mut f = Natural::ONE; while n != 0 { f *= Natural::from(n); n.saturating_sub_assign(2); } f } pub fn multifactorial_naive(mut n: u64, m: u64) -> Natural { assert_ne!(m, 0); let mut f = Natural::ONE; while n != 0 { f *= Natural::from(n); n.saturating_sub_assign(m); } f } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/gcd.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1996, 1998, 2000-2004, 2008, 2012, 2019 Free Software Foundation, Inc. // // 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 crate::natural::Natural; use crate::natural::arithmetic::gcd::half_gcd::{ HalfGcdMatrix, HalfGcdMatrix1, limbs_half_gcd_matrix_mul_matrix_1, limbs_half_gcd_matrix_update_q, }; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{DivMod, Parity, XXSubYYToZZ}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{JoinHalves, SplitInHalf}; use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::slices::slice_test_zero; pub fn gcd_euclidean_nz(x: Natural, y: Natural) -> Natural { if y == 0 { x } else { let r = x % &y; gcd_euclidean_nz(y, r) } } // recursive implementation overflows stack, so using a loop instead pub fn gcd_binary_nz(mut x: Natural, mut y: Natural) -> Natural { let mut twos = 0; loop { if x == y { return x << twos; } else if x == 0 { return y << twos; } else if y == 0 { return x << twos; } else if x.even() { x >>= 1; if y.even() { y >>= 1; twos += 1; } } else if y.even() { y >>= 1; } else if x > y { x -= &y; x >>= 1; } else { y -= &x; y >>= 1; } } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct OwnedHalfGcdMatrix { pub data: Vec, pub s: usize, pub two_s: usize, pub three_s: usize, pub n: usize, } #[allow(clippy::missing_const_for_fn)] fn from_owned(m: &mut OwnedHalfGcdMatrix) -> HalfGcdMatrix<'_> { HalfGcdMatrix { s: m.s, two_s: m.two_s, three_s: m.three_s, n: m.n, data: &mut m.data, } } impl OwnedHalfGcdMatrix { pub fn init(n: usize, mut p: Vec) -> Self { let m = HalfGcdMatrix::init(n, &mut p); Self { s: m.s, two_s: m.two_s, three_s: m.three_s, n: m.n, data: p, } } pub const fn update_q_scratch_len(&self, qs_len: usize) -> usize { self.n + qs_len } pub fn mul_matrix_1(&mut self, m_1: &HalfGcdMatrix1, scratch: &mut [Limb]) { let mut om = from_owned(self); limbs_half_gcd_matrix_mul_matrix_1(&mut om, m_1, scratch); self.n = om.n; } pub fn update_q(&mut self, qs: &[Limb], column: u8, scratch: &mut [Limb]) { let mut om = from_owned(self); limbs_half_gcd_matrix_update_q(&mut om, qs, column, scratch); self.n = om.n; } pub fn get(&self, row: u8, column: u8) -> &[Limb] { match (row, column) { (0, 0) => &self.data[..self.s], (0, 1) => &self.data[self.s..self.two_s], (1, 0) => &self.data[self.two_s..self.three_s], (1, 1) => &self.data[self.three_s..], _ => panic!(), } } } pub fn half_gcd_matrix_create(s: usize, n: usize, data: Vec) -> OwnedHalfGcdMatrix { assert!(n <= s); assert_eq!(data.len(), s << 2); OwnedHalfGcdMatrix { data, s, two_s: s << 1, three_s: s * 3, n, } } pub fn half_gcd_matrix_to_naturals(m: &OwnedHalfGcdMatrix) -> (Natural, Natural, Natural, Natural) { let n = m.n; ( Natural::from_limbs_asc(&m.get(0, 0)[..n]), Natural::from_limbs_asc(&m.get(0, 1)[..n]), Natural::from_limbs_asc(&m.get(1, 0)[..n]), Natural::from_limbs_asc(&m.get(1, 1)[..n]), ) } pub fn half_gcd_matrix_1_to_naturals(m_1: &HalfGcdMatrix1) -> (Natural, Natural, Natural, Natural) { ( Natural::from(m_1.data[0][0]), Natural::from(m_1.data[0][1]), Natural::from(m_1.data[1][0]), Natural::from(m_1.data[1][1]), ) } pub fn half_gcd_matrix_create_string(m: &HalfGcdMatrix) -> String { format!("half_gcd_matrix_create({}, {}, vec!{:?})", m.s, m.n, m.data) } pub fn half_gcd_matrix_all_elements_nonzero(m: &HalfGcdMatrix) -> bool { for i in 0..2 { for j in 0..2 { if slice_test_zero(m.get(i, j)) { return false; } } } true } /// This is equivalent to `div2` from `mpn/generic/hgcd2.c`, GMP 6.2.1, where `HGCD2_DIV2_METHOD == /// 2`. pub fn limbs_gcd_div_alt( mut n1: Limb, mut n0: Limb, mut d1: Limb, mut d0: Limb, ) -> (Limb, Limb, Limb) { let mut q = 0; let n_zeros = LeadingZeros::leading_zeros(n1); let mut d_zeros = LeadingZeros::leading_zeros(d1); assert!(d_zeros >= n_zeros); d_zeros -= n_zeros; d1 = (d1 << d_zeros) + (d0 >> 1 >> (Limb::WIDTH - 1 - d_zeros)); d0 <<= d_zeros; for _ in 0..=d_zeros { q <<= 1; if n1 == d1 && n0 >= d0 || n1 != d1 && n1 > d1 { q |= 1; (n1, n0) = Limb::xx_sub_yy_to_zz(n1, n0, d1, d0); } d0 = (d1 << (Limb::WIDTH - 1)) | (d0 >> 1); d1 >>= 1; } (q, n1, n0) } pub fn limbs_gcd_div_naive(n1: Limb, n0: Limb, d1: Limb, d0: Limb) -> (Limb, Limb, Limb) { let (q, r) = DoubleLimb::join_halves(n1, n0).div_mod(DoubleLimb::join_halves(d1, d0)); let (q1, q0) = q.split_in_half(); assert_eq!(q1, 0); let (r1, r0) = r.split_in_half(); (q0, r1, r0) } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModPowerOf2, NegAssign, Parity}; use malachite_base::num::conversion::traits::WrappingInto; use malachite_base::num::logic::traits::BitAccess; use std::mem::swap; pub fn jacobi_symbol_simple(mut a: Natural, mut n: Natural) -> i8 { assert_ne!(n, 0u32); assert!(n.odd()); a %= &n; let mut t = 1i8; while a != 0u32 { while a.even() { a >>= 1u32; let r: u8 = (&(&n).mod_power_of_2(3)).wrapping_into(); if r == 3 || r == 5 { t.neg_assign(); } } swap(&mut a, &mut n); if a.get_bit(1) && n.get_bit(1) { t.neg_assign(); } a %= &n; } if n == 1u32 { t } else { 0 } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ CeilingLogBasePowerOf2, CheckedLogBase2, CheckedLogBasePowerOf2, FloorLogBasePowerOf2, Square, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use std::cmp::Ordering::*; pub fn floor_log_base_naive(x: &Natural, base: &Natural) -> u64 { assert_ne!(*x, 0); assert!(*base > 1); let mut result = 0; let mut p = Natural::ONE; // loop always executes at least once while p <= *x { result += 1; p *= base; } result - 1 } pub fn ceiling_log_base_naive(x: &Natural, base: &Natural) -> u64 { assert_ne!(*x, 0); assert!(*base > 1); let mut result = 0; let mut p = Natural::ONE; while p < *x { result += 1; p *= base; } result } pub fn checked_log_base_naive(x: &Natural, base: &Natural) -> Option { assert_ne!(*x, 0); assert!(*base > 1); let mut result = 0; let mut p = Natural::ONE; while p < *x { result += 1; p *= base; } if p == *x { Some(result) } else { None } } fn log_by_squaring_helper(x: &Natural, base: &Natural) -> (u64, bool) { assert_ne!(*x, 0); assert!(*base > 1); if *x == 1 { return (0, true); } else if x < base { return (0, false); } let x_bits = x.significant_bits(); let mut powers = vec![base.clone()]; for i in 0.. { let power = &powers[i]; if ((power.significant_bits() - 1) << 1) | 1 > x_bits { break; } let next_power = power.square(); powers.push(next_power); } // At this point, `powers[i]` is `base ^ (2 ^ i)` let mut log = 0; let mut test_power = Natural::ONE; for (i, power) in powers.into_iter().enumerate().rev() { let new_test_power = &test_power * power; match new_test_power.cmp(x) { Equal => { log.set_bit(u64::exact_from(i)); return (log, true); } Less => { test_power = new_test_power; log.set_bit(u64::exact_from(i)); } _ => {} } } (log, false) } pub fn floor_log_base_by_squaring(x: &Natural, base: &Natural) -> u64 { if let Some(log_base) = base.checked_log_base_2() { return x.floor_log_base_power_of_2(log_base); } log_by_squaring_helper(x, base).0 } pub fn ceiling_log_base_by_squaring(x: &Natural, base: &Natural) -> u64 { if let Some(log_base) = base.checked_log_base_2() { return x.ceiling_log_base_power_of_2(log_base); } let (log, exact) = log_by_squaring_helper(x, base); if exact { log } else { log + 1 } } pub fn checked_log_base_by_squaring(x: &Natural, base: &Natural) -> Option { if let Some(log_base) = base.checked_log_base_2() { return x.checked_log_base_power_of_2(log_base); } let (log, exact) = log_by_squaring_helper(x, base); if exact { Some(log) } else { None } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::basic::traits::{One, Zero}; pub fn ceiling_log_base_power_of_2_naive_nz(x: &Natural, pow: u64) -> u64 { assert_ne!(*x, Natural::ZERO); assert_ne!(pow, 0); let mut result = 0; let mut p = Natural::ONE; while p < *x { result += 1; p <<= pow; } result } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . pub mod add; pub mod binomial_coefficient; pub mod checked_sub; pub mod div; pub mod div_exact; pub mod div_mod; pub mod divisible_by; pub mod eq_mod; pub mod extended_gcd; pub mod factorial; pub mod gcd; pub mod kronecker_symbol; pub mod log_base; pub mod log_base_power_of_2; pub mod mod_inverse; pub mod mod_mul; pub mod mod_op; pub mod mod_pow; pub mod mod_power_of_2_pow; pub mod mod_power_of_2_square; pub mod mul; pub mod neg; pub mod pow; pub mod primorial; pub mod root; pub mod sqrt; pub mod square; pub mod sub; ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 crate::integer::Integer; use crate::natural::InnerNatural::Small; use crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ExtendedGcd, ModInverse}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; fn mod_inverse_simple_helper(x: Natural, m: Natural) -> Option { let (gcd, _, inverse) = (&m).extended_gcd(x); if gcd == 1u32 { Some(Natural::exact_from(if inverse < 0u32 { inverse + Integer::from(m) } else { inverse })) } else { None } } pub fn mod_inverse_simple(n: Natural, m: Natural) -> Option { assert_ne!(n, 0u32); assert!(n < m); match (n, m) { (x @ Natural::ONE, _) => Some(x), (Natural(Small(x)), Natural(Small(y))) => x.mod_inverse(y).map(Natural::from), (a, b) => mod_inverse_simple_helper(a, b), } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ExactFrom, JoinHalves, SplitInHalf}; pub fn limbs_precompute_mod_mul_two_limbs_alt(m_1: Limb, m_0: Limb) -> (Limb, Limb, Limb) { let out_limbs = (Natural::power_of_2(Limb::WIDTH << 2) / Natural::from(DoubleLimb::join_halves(m_1, m_0))) .into_limbs_asc(); assert_eq!(out_limbs.len(), 3); (out_limbs[2], out_limbs[1], out_limbs[0]) } /// m_1 cannot be zero, and we cannot have m_1 == 1 and m_0 == 0. Both [x_0, x_1] and [y_0, y_1] /// must be less than [m_0, m_1]. pub fn limbs_mod_mul_two_limbs_naive( x_1: Limb, x_0: Limb, y_1: Limb, y_0: Limb, m_1: Limb, m_0: Limb, ) -> (Limb, Limb) { DoubleLimb::exact_from( &(Natural::from(DoubleLimb::join_halves(x_1, x_0)) * Natural::from(DoubleLimb::join_halves(y_1, y_0)) % Natural::from(DoubleLimb::join_halves(m_1, m_0))), ) .split_in_half() } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_op.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1993, 1994, 1996, 1998-2000, 2002, 2003 Free Software Foundation, Inc. // // 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 crate::natural::arithmetic::div_mod::limbs_invert_limb; use crate::natural::arithmetic::mod_op::mod_by_preinversion; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::LeadingZeros; use rug::ops::RemRounding; pub fn rug_neg_mod(x: rug::Integer, y: rug::Integer) -> rug::Integer { -x.rem_ceil(y) } // # Worst-case complexity // $T(n) = O(n)$ // // $M(n) = O(1)$ // // where $T$ is time, $M$ is additional memory, and $n$ is `ns.len()`. // // This is equivalent to `mpn_divrem_1` from `mpn/generic/divrem_1.c`, GMP 6.2.1, where `qxn == 0` // and `un > 1`, but not computing the quotient. pub fn limbs_mod_limb_alt_3(ns: &[Limb], d: Limb) -> Limb { assert_ne!(d, 0); let len = ns.len(); assert!(len > 1); let bits = LeadingZeros::leading_zeros(d); let (ns_last, ns_init) = ns.split_last().unwrap(); if bits == 0 { // High quotient limb is 0 or 1, skip a divide step. let mut r = *ns_last; if r >= d { r -= d; } // Multiply-by-inverse, divisor already normalized. let d_inv = limbs_invert_limb::(d); for n in ns_init.iter().rev() { r = mod_by_preinversion::(r, *n, d, d_inv); } r } else { // Skip a division if high < divisor (high quotient 0). Testing here before normalizing will // still skip as often as possible. let (ns, mut r) = if *ns_last < d { (ns_init, *ns_last) } else { (ns, 0) }; let d = d << bits; r <<= bits; let d_inv = limbs_invert_limb::(d); let (ns_last, ns_init) = ns.split_last().unwrap(); let mut previous_n = *ns_last; let cobits = Limb::WIDTH - bits; r |= previous_n >> cobits; for &n in ns_init.iter().rev() { let shifted_n = (previous_n << bits) | (n >> cobits); r = mod_by_preinversion::(r, shifted_n, d, d_inv); previous_n = n; } mod_by_preinversion::(r, previous_n << bits, d, d_inv) >> bits } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::ModMulAssign; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::BitIterable; pub fn simple_binary_mod_pow(x: &Natural, exp: &Natural, m: &Natural) -> Natural { if *m == 1 { return Natural::ZERO; } let mut out = Natural::ONE; for bit in exp.bits().rev() { out.mod_mul_assign(out.clone(), m); if bit { out.mod_mul_assign(x, m); } } out } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{ModPowerOf2MulAssign, ModPowerOf2SquareAssign}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::BitIterable; pub fn simple_binary_mod_power_of_2_pow(x: &Natural, exp: &Natural, pow: u64) -> Natural { if pow == 0 { return Natural::ZERO; } let mut out = Natural::ONE; for bit in exp.bits().rev() { out.mod_power_of_2_square_assign(pow); if bit { out.mod_power_of_2_mul_assign(x, pow); } } out } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mod_power_of_2_square::limbs_square_diagonal_shl_add; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::{Square, WrappingSquare}; use malachite_base::num::conversion::traits::SplitInHalf; pub fn limbs_square_low_basecase_unrestricted(out: &mut [Limb], xs: &[Limb]) { let n = xs.len(); let out = &mut out[..n]; assert_ne!(n, 0); let xs_0 = xs[0]; match n { 1 => out[0] = xs_0.wrapping_square(), 2 => { let p_hi; (p_hi, out[0]) = DoubleLimb::from(xs_0).square().split_in_half(); out[1] = (xs_0.wrapping_mul(xs[1]) << 1).wrapping_add(p_hi); } _ => { let mut scratch = vec![0; n - 1]; limbs_mul_limb_to_out::(&mut scratch, &xs[1..], xs_0); for i in 1.. { let two_i = i << 1; if two_i >= n - 1 { break; } limbs_slice_add_mul_limb_same_length_in_place_left( &mut scratch[two_i..], &xs[i + 1..n - i], xs[i], ); } limbs_square_diagonal_shl_add(out, &mut scratch, xs); } } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::natural::InnerNatural::{Large, Small}; use crate::natural::Natural; use crate::natural::arithmetic::add::limbs_slice_add_greater_in_place_left; use crate::natural::arithmetic::div_exact::limbs_div_exact_limb_to_out; use crate::natural::arithmetic::mod_op::limbs_mod_limb; use crate::natural::arithmetic::mul::fft::{ CRTData, Context, FFTContext, MAX_NPROFILES, MPN_CTX_NCRTS, MPN_CTX_TWO_POWER_TAB_SIZE, MPNToFFTFunc, ModData, SD_FFT_CTX_W2TAB_INIT, SerializedCRTData, SerializedContext, SerializedFFTContext, VEC_SZ, crt_data_find_bn_bound, f64_mulmod, f64_reduce_0n_to_pmhn, f64_reduce_pm1n_to_pmhn, f64x4_mul_add, mpn_mul_default_mpn_ctx, }; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h, limbs_mul_greater_to_out_toom_8h, limbs_mul_greater_to_out_toom_22, limbs_mul_greater_to_out_toom_32, limbs_mul_greater_to_out_toom_33, limbs_mul_greater_to_out_toom_42, limbs_mul_greater_to_out_toom_43, limbs_mul_greater_to_out_toom_44, limbs_mul_greater_to_out_toom_53, limbs_mul_greater_to_out_toom_63, }; use crate::natural::arithmetic::mul::{ FFT_MUL_THRESHOLD, limbs_mul_greater_to_out_basecase, limbs_mul_greater_to_out_scratch_len, toom44_ok, }; use crate::platform::{ Limb, MUL_FFT_THRESHOLD, MUL_TOOM6H_THRESHOLD, MUL_TOOM8H_THRESHOLD, MUL_TOOM22_THRESHOLD, MUL_TOOM32_TO_TOOM43_THRESHOLD, MUL_TOOM32_TO_TOOM53_THRESHOLD, MUL_TOOM33_THRESHOLD, MUL_TOOM42_TO_TOOM53_THRESHOLD, MUL_TOOM42_TO_TOOM63_THRESHOLD, MUL_TOOM44_THRESHOLD, }; use libm::scalbn; use malachite_base::num::arithmetic::traits::{ DivRound, ModPow, PowerOf2, XMulYToZZ, XXDivModYToQR, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::factorization::traits::{IsPrime, PrimitiveRootPrime}; use malachite_base::num::logic::traits::{LeadingZeros, SignificantBits, TrailingZeros}; use malachite_base::rounding_modes::RoundingMode::*; use wide::f64x4; // In GMP this is hardcoded to 500 pub const MUL_BASECASE_MAX_UN: usize = 500; // We must have 1 < ys.len() < MUL_TOOM22_THRESHOLD < MUL_BASECASE_MAX_UN < xs.len(). fn limbs_mul_greater_to_out_basecase_mem_opt_helper(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(ys_len > 1); assert!(ys_len < MUL_TOOM22_THRESHOLD); assert!(MUL_TOOM22_THRESHOLD < MUL_BASECASE_MAX_UN); assert!(xs_len > MUL_BASECASE_MAX_UN); let mut triangle_buffer = [0; MUL_TOOM22_THRESHOLD]; let mut offset = 0; for chunk in xs.chunks(MUL_BASECASE_MAX_UN) { let out = &mut out[offset..]; if chunk.len() >= ys_len { limbs_mul_greater_to_out_basecase(out, chunk, ys); } else { limbs_mul_greater_to_out_basecase(out, ys, chunk); } if offset != 0 { limbs_slice_add_greater_in_place_left(out, &triangle_buffer[..ys_len]); } offset += MUL_BASECASE_MAX_UN; if offset < xs_len { triangle_buffer[..ys_len] .copy_from_slice(&out[MUL_BASECASE_MAX_UN..MUL_BASECASE_MAX_UN + ys_len]); } } } /// A version of `limbs_mul_greater_to_out_basecase` that attempts to be more efficient by /// increasing cache locality. It is currently not measurably better than ordinary basecase. pub fn limbs_mul_greater_to_out_basecase_mem_opt(out: &mut [Limb], xs: &[Limb], ys: &[Limb]) { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); if ys_len > 1 && ys_len < MUL_TOOM22_THRESHOLD && xs.len() > MUL_BASECASE_MAX_UN { limbs_mul_greater_to_out_basecase_mem_opt_helper(out, xs, ys); } else { limbs_mul_greater_to_out_basecase(out, xs, ys); } } pub fn limbs_product_naive(out: &mut [Limb], factors: &[Limb]) -> usize { let mut n = Natural::ONE; for &f in factors { n *= Natural::from(f); } let xs = n.into_limbs_asc(); let size = xs.len(); out[..size].copy_from_slice(&xs); size } pub fn natural_product_naive>(xs: I) -> Natural { let mut p = Natural::ONE; for x in xs { if x == 0 { return Natural::ZERO; } p *= x; } p } impl CRTData { // This is crt_data_init from fft_small.h, FLINT 3.3.0-dev, returning CRTData. fn new(prime: u64, coeff_len: usize, nprimes: usize) -> Self { Self { prime, coeff_len, nprimes, data: vec![0; nprimes * coeff_len + coeff_len + nprimes], } } // This is crt_data_co_prime_red from fft_small.h, FLINT 3.3.0-dev, writing a value. #[inline] fn co_prime_red_write(&mut self, i: usize, val: u64) { assert!(i < self.nprimes); self.data[self.nprimes * self.coeff_len + self.coeff_len + i] = val; } // This is crt_data_co_prime from fft_small.h, FLINT 3.3.0-dev, writing a value. #[inline] fn co_prime_write(&mut self, i: usize, val: u64) { assert!(i < self.nprimes); self.data[i * self.coeff_len] = val; } // return mpn of length C->coeff_len // // This is crt_data_prod_primes from fft_small.h, FLINT 3.3.0-dev. #[inline] fn prod_primes(&mut self) -> &mut [u64] { &mut self.data[self.nprimes * self.coeff_len..] } fn serialize(self) -> SerializedCRTData { SerializedCRTData { prime: self.prime, coeff_len: self.coeff_len, nprimes: self.nprimes, } } } const D_BITS: i32 = 53; // This is fft_small_mulmod_satisfies_bounds from fft_small/mulmod_statisfies_bounds.c, FLINT // 3.3.0-dev. fn fft_small_mulmod_satisfies_bounds(nn: u64) -> bool { let n = nn as f64; let ninv = 1.0 / n; let t1 = n.mul_add(ninv, -1.0).abs(); // epsilon ~= t1 / n good enough let n1bits = i32::exact_from(nn.significant_bits()); let n2hi = u64::x_mul_y_to_zz(nn, nn).0; assert_ne!(n2hi, 0); let n2bits = i32::exact_from(u64::WIDTH + n2hi.significant_bits()); // for |a*b| < 2*n^2 // // |h*n_inv| < 2*n, so rounding in mul(h, ninv) at least B bits after the . let b = D_BITS - n1bits - 1; assert!(b >= 2); let diff = n2bits - D_BITS; let p = 2.0 * n * t1; let limit2 = p + scalbn(ninv, diff) + 0.5 + scalbn(1.0, -b - 1); // for |a * b| < 4 * n ^ 2 let limit4 = 2.0 * p + scalbn(ninv, diff + 1) + 0.5 + scalbn(1.0, -b); // fudge the limits 1 and 3/2 because the above is double arithmetic limit2 < 0.99 && limit4 < 1.49 } // This is nmod_init from nmod.h, FLINT 3.3.0-dev, but returning `mod`. fn nmod_init(n: u64) -> ModData { let norm = LeadingZeros::leading_zeros(n); let shifted = n << norm; let ninv = u64::xx_div_mod_y_to_qr(!shifted, u64::MAX, shifted).0; ModData { n, ninv, norm } } // This is next_fft_number from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn next_fft_number(p: u64) -> u64 { let bits = p.significant_bits(); let l = TrailingZeros::trailing_zeros(p - 1); let q = p - u64::power_of_2(l + 1); if bits < 15 { panic!(); } else if q.significant_bits() == bits { q } else { assert!(l >= 5); u64::power_of_2(bits) - u64::power_of_2(l - 1) + 1 } } // This is sd_fft_ctx_init_prime from fft_small/sd_fft_ctx.c, FLINT 3.3.0-dev, returning q. fn sd_fft_ctx_init_prime(pp: u64) -> FFTContext { assert!( fft_small_mulmod_satisfies_bounds(pp), "FFT prime {pp} does not satisfy bounds for arithmetic" ); let mut q = FFTContext::default(); q.p = pp as f64; q.pinv = 1.0 / q.p; q.mod_data = nmod_init(pp); q.primitive_root = pp.primitive_root_prime(); let n = q.p; let ninv = q.pinv; // fill wtab to a depth of SD_FFT_CTX_W2TAB_INIT: 2 ^ (SD_FFT_CTX_W2TAB_INIT - 1) entries: 1, // e(1 / 4), e(1 / 8), e(3 / 8), ... // // Q->w2tab[j] is itself a table of length 2 ^ (j - 1) containing 2 ^ (j + 1) st roots of // unity. q.w2tab_backing = vec![0.0; 1 << 12]; q.w2tab_backing[0] = 1.0; let mut l = 1; for k in 1..SD_FFT_CTX_W2TAB_INIT { let w = f64_reduce_0n_to_pmhn!( q.primitive_root .mod_pow((q.mod_data.n - 1) >> (k + 1), q.mod_data.n) as f64, n ); q.w2tab_offsets[k as usize] = l; let (w_lo, w_hi) = q.w2tab_backing.split_at_mut(l); for (hi, &lo) in w_hi.iter_mut().zip(w_lo.iter()) { *hi = f64_reduce_pm1n_to_pmhn!(f64_mulmod!(lo, w, n, ninv), n); } l <<= 1; } q.w2tab_depth = SD_FFT_CTX_W2TAB_INIT; q } // fill x[i] = 2 ^ i mod p for 0 <= i < len // // This is fill_slow_two_pow_tab from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn fill_slow_two_pow_tab(xs: &mut [f64], p: f64, pinv: f64) { let mut t = 1.0; let (xs_head, xs_tail) = xs.split_first_mut().unwrap(); *xs_head = t; for x in xs_tail { let q = (t * (2.0 * pinv)).round_ties_even(); t = fma!(-q, p, t + t); *x = t; } } // fill in d[i * nvs + k / VEC_SZ][k % VEC_SZ] = 2 ^ i mod Rffts[k].p for 0 <= k < VEC_SZ * nvs and // 0 <= i < len. // // This is fill_vec_two_pow_tab from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn fill_vec_two_pow_tab(xs: &mut [f64x4], rffts: &mut [FFTContext], len: usize, nvs: usize) { let mut ps = vec![f64x4::ZERO; nvs << 1]; for l in 0..nvs { let r = &rffts[l << 2..]; let p = &mut ps[l << 1..]; p[0] = f64x4::new([r[0].p, r[1].p, r[2].p, r[3].p]); p[1] = f64x4::new([r[0].pinv, r[1].pinv, r[2].pinv, r[3].pinv]) * f64x4::splat(2.0); } for x in xs.iter_mut().take(nvs) { *x = f64x4::ONE; } let mut k = 0; for _ in 1..len { for l in 0..nvs { let xs = &mut xs[k + l..]; let t = xs[0]; let p = &ps[l << 1..]; xs[nvs] = f64x4_mul_add!(-(t * p[1]).round(), p[0], t * f64x4::splat(2.0)); } k += nvs; } } // TODO make macro // // This is PUSH_PROFILE from fft_small/mpn_mul.c, FLINT 3.3.0-dev. fn push_profile(r: &mut Context, np: usize, bits: u64) { let i = r.profiles_size; r.profiles[i].np = np; r.profiles[i].bits = bits; r.profiles[i].bn_bound = crt_data_find_bn_bound(&r.crts[np - 1], bits); r.profiles[i].to_ffts = Some(MPNToFFTFunc { np, bits }); r.profiles_size = i + 1; } const DEFAULT_PRIME: u64 = 0x0003f00000000001; // This is mpn_ctx_init from fft_small/mpn_mul.c, FLINT 3.3.0-dev, returning the context. pub fn initialize_context() -> Context { let mut p = DEFAULT_PRIME; let mut r = Context::default(); for i in 0..MPN_CTX_NCRTS { if i > 0 { p = next_fft_number(p); } while !p.is_prime() { p = next_fft_number(p); } r.ffts[i] = sd_fft_ctx_init_prime(p); if i == 0 { r.crts[0] = CRTData::new(p, 1, 1); r.crts[0].co_prime_red_write(0, 1); r.crts[0].co_prime_write(0, 1); r.crts[0].prod_primes()[0] = p; } else { let mut len = r.crts[i - 1].coeff_len; let mut t = vec![0; (len + 2) << 1]; let (t, tt) = t.split_at_mut(len + 2); t[len + 1] = 0; t[len] = limbs_mul_limb_to_out::(t, &r.crts[i - 1].prod_primes()[..len], p); // leave enough room for (product of primes)*(number of primes) len += 2; limbs_mul_limb_to_out::(tt, &t[..len], u64::wrapping_from(i) + 1); while tt[len - 1] == 0 { len -= 1; } r.crts[i] = CRTData::new(p, len, i + 1); // set product of primes r.crts[i].prod_primes()[..len].copy_from_slice(&t[..len]); // set cofactors for pi in 0..=i { let prime = r.crts[pi].prime; let cofac = r.crts[i].co_prime(pi); limbs_div_exact_limb_to_out::(cofac, &t[..len], prime); let d = limbs_mod_limb::(&cofac[..len], prime); r.crts[i].co_prime_red_write(pi, d); } } } // powers of two for slow mod { let len = MPN_CTX_TWO_POWER_TAB_SIZE; let x = vec![0.0; len * MPN_CTX_NCRTS]; r.slow_two_pow_backing = x; let mut offset = 0; for i in 0..MPN_CTX_NCRTS { r.slow_two_pow_offsets[i] = offset; fill_slow_two_pow_tab( &mut r.slow_two_pow_backing[offset..offset + len], r.ffts[i].p, r.ffts[i].pinv, ); offset += len; } } // powers of two for fast mod { let len = MPN_CTX_TWO_POWER_TAB_SIZE; let max_nvs = MPN_CTX_NCRTS.div_round(VEC_SZ, Ceiling).0; let x = vec![f64x4::ZERO; max_nvs * (max_nvs + 1) / 2 * len]; r.vec_two_pow_tab_backing = x; let mut offset = 0; for nvs in 1..=max_nvs { r.vec_two_pow_tab_offsets[nvs - 1] = offset; fill_vec_two_pow_tab( &mut r.vec_two_pow_tab_backing[offset..], &mut r.ffts, len, nvs, ); offset += nvs * len; } } r.profiles_size = 0; push_profile(&mut r, 4, 84); push_profile(&mut r, 4, 88); push_profile(&mut r, 4, 92); push_profile(&mut r, 5, 112); push_profile(&mut r, 5, 116); push_profile(&mut r, 5, 120); push_profile(&mut r, 6, 136); push_profile(&mut r, 6, 140); push_profile(&mut r, 6, 144); push_profile(&mut r, 7, 160); push_profile(&mut r, 7, 164); push_profile(&mut r, 7, 168); push_profile(&mut r, 8, 184); push_profile(&mut r, 8, 188); push_profile(&mut r, 8, 192); assert!(r.profiles_size <= MAX_NPROFILES); r } impl FFTContext { fn serialize(self) -> SerializedFFTContext { let mut w2tab_backing = [0; 4096]; for (o, x) in w2tab_backing.iter_mut().zip(self.w2tab_backing.into_iter()) { *o = x.to_bits(); } SerializedFFTContext { p: self.p.to_bits(), pinv: self.pinv.to_bits(), mod_data: self.mod_data, primitive_root: self.primitive_root, w2tab_depth: self.w2tab_depth, w2tab_backing, w2tab_offsets: self.w2tab_offsets, } } } impl Context { pub_crate_test! {serialize(self) -> SerializedContext { let mut crts_data_0 = [0; 3]; let mut crts_data_1 = [0; 8]; let mut crts_data_2 = [0; 15]; let mut crts_data_3 = [0; 24]; let mut crts_data_4 = [0; 29]; let mut crts_data_5 = [0; 41]; let mut crts_data_6 = [0; 55]; let mut crts_data_7 = [0; 71]; crts_data_0.copy_from_slice(&self.crts[0].data); crts_data_1.copy_from_slice(&self.crts[1].data); crts_data_2.copy_from_slice(&self.crts[2].data); crts_data_3.copy_from_slice(&self.crts[3].data); crts_data_4.copy_from_slice(&self.crts[4].data); crts_data_5.copy_from_slice(&self.crts[5].data); crts_data_6.copy_from_slice(&self.crts[6].data); crts_data_7.copy_from_slice(&self.crts[7].data); let mut vec_two_pow_tab_backing = [[0; 4]; 768]; for (o, f) in vec_two_pow_tab_backing .iter_mut() .zip(self.vec_two_pow_tab_backing.into_iter()) { let [f0, f1, f2, f3] = f.to_array(); *o = [f0.to_bits(), f1.to_bits(), f2.to_bits(), f3.to_bits()]; } let mut slow_two_pow_backing = [0; 1 << 11]; for (o, x) in slow_two_pow_backing .iter_mut() .zip(self.slow_two_pow_backing.into_iter()) { *o = x.to_bits(); } let [f0, f1, f2, f3, f4, f5, f6, f7] = self.ffts; let [c0, c1, c2, c3, c4, c5, c6, c7] = self.crts; SerializedContext { ffts: [ f0.serialize(), f1.serialize(), f2.serialize(), f3.serialize(), f4.serialize(), f5.serialize(), f6.serialize(), f7.serialize(), ], crts: [ c0.serialize(), c1.serialize(), c2.serialize(), c3.serialize(), c4.serialize(), c5.serialize(), c6.serialize(), c7.serialize(), ], crts_data_0, crts_data_1, crts_data_2, crts_data_3, crts_data_4, crts_data_5, crts_data_6, crts_data_7, vec_two_pow_tab_backing, vec_two_pow_tab_offsets: self.vec_two_pow_tab_offsets, slow_two_pow_backing, slow_two_pow_offsets: self.slow_two_pow_offsets, profiles: self.profiles, profiles_size: self.profiles_size, buffer_alloc: self.buffer_alloc, } }} } fn limbs_mul_same_length_to_out_slow( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) { let len = xs.len(); assert_eq!(ys.len(), len); assert_ne!(len, 0); if len < MUL_TOOM22_THRESHOLD { limbs_mul_greater_to_out_basecase(out, xs, ys); } else if len < MUL_TOOM33_THRESHOLD { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if len < MUL_TOOM44_THRESHOLD { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else if len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } else if len < FFT_MUL_THRESHOLD { limbs_mul_greater_to_out_toom_8h(out, xs, ys, scratch); } else { mpn_mul_default_mpn_ctx(out, xs, ys, true); } } fn limbs_mul_greater_to_out_old_slow( out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb], ) -> Limb { let xs_len = xs.len(); let ys_len = ys.len(); assert!(xs_len >= ys_len); assert_ne!(ys_len, 0); assert!(out.len() >= xs_len + ys_len); if ys_len < MUL_TOOM22_THRESHOLD { // Plain schoolbook multiplication. Unless xs_len is very large, or else if // `limbs_mul_same_length_to_out` applies, perform basecase multiply directly. limbs_mul_greater_to_out_basecase(out, xs, ys); } else if ys_len < MUL_TOOM33_THRESHOLD { if xs_len >= 3 * ys_len { let two_ys_len = ys_len << 1; let three_ys_len = two_ys_len + ys_len; let four_ys_len = two_ys_len << 1; let (scratch, mul_scratch) = scratch.split_at_mut(four_ys_len); limbs_mul_greater_to_out_toom_42(out, &xs[..two_ys_len], ys, mul_scratch); let mut xs = &xs[two_ys_len..]; let mut out_offset = two_ys_len; while xs.len() >= three_ys_len { let out = &mut out[out_offset..]; let (xs_lo, xs_hi) = xs.split_at(two_ys_len); limbs_mul_greater_to_out_toom_42(scratch, xs_lo, ys, mul_scratch); let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..three_ys_len].copy_from_slice(&scratch_hi[..two_ys_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); xs = xs_hi; out_offset += two_ys_len; } let xs_len = xs.len(); let out = &mut out[out_offset..]; // ys_len <= xs_len < 3 * ys_len let four_xs_len = xs_len << 2; if four_xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22(scratch, xs, ys, mul_scratch); } else if four_xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32(scratch, xs, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_42(scratch, xs, ys, mul_scratch); } let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..ys_len + xs_len].copy_from_slice(&scratch_hi[..xs_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); } else if 4 * xs_len < 5 * ys_len { limbs_mul_greater_to_out_toom_22(out, xs, ys, scratch); } else if 4 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } } else if (xs_len + ys_len) >> 1 < MUL_FFT_THRESHOLD || 3 * ys_len < MUL_FFT_THRESHOLD { // Handle the largest operands that are not in the FFT range. The 2nd condition makes very // unbalanced operands avoid the FFT code (except perhaps as coefficient products of the // Toom code). if ys_len < MUL_TOOM44_THRESHOLD || !toom44_ok(xs_len, ys_len) { // Use ToomX3 variants if xs_len << 1 >= 5 * ys_len { let two_ys_len = ys_len << 1; let four_ys_len = two_ys_len << 1; let (scratch, mul_scratch) = scratch.split_at_mut(four_ys_len); let (xs_lo, mut xs) = xs.split_at(two_ys_len); if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs_lo, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_63(out, xs_lo, ys, mul_scratch); } let mut out_offset = two_ys_len; // xs_len >= 2.5 * ys_len while xs.len() << 1 >= 5 * ys_len { let out = &mut out[out_offset..]; let (xs_lo, xs_hi) = xs.split_at(two_ys_len); if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(scratch, xs_lo, ys, mul_scratch); } else { limbs_mul_greater_to_out_toom_63(scratch, xs_lo, ys, mul_scratch); } let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..ys_len + two_ys_len].copy_from_slice(&scratch_hi[..two_ys_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); xs = xs_hi; out_offset += two_ys_len; } let xs_len = xs.len(); let out = &mut out[out_offset..]; // ys_len / 2 <= xs_len < 2.5 * ys_len limbs_mul_to_out_slow(scratch, xs, ys, mul_scratch); let (scratch_lo, scratch_hi) = scratch.split_at(ys_len); out[ys_len..xs_len + ys_len].copy_from_slice(&scratch_hi[..xs_len]); assert!(!limbs_slice_add_greater_in_place_left(out, scratch_lo)); } else if 6 * xs_len < 7 * ys_len { limbs_mul_greater_to_out_toom_33(out, xs, ys, scratch); } else if xs_len << 1 < 3 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM43_THRESHOLD { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_43(out, xs, ys, scratch); } } else if 6 * xs_len < 11 * ys_len { if xs_len << 2 < 7 * ys_len { if ys_len < MUL_TOOM32_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_32(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_53(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM42_TO_TOOM53_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_53(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM42_TO_TOOM63_THRESHOLD { limbs_mul_greater_to_out_toom_42(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_63(out, xs, ys, scratch); } } else if ys_len < MUL_TOOM6H_THRESHOLD { limbs_mul_greater_to_out_toom_44(out, xs, ys, scratch); } else if ys_len < MUL_TOOM8H_THRESHOLD { limbs_mul_greater_to_out_toom_6h(out, xs, ys, scratch); } else { limbs_mul_greater_to_out_toom_8h(out, xs, ys, scratch); } } else { mpn_mul_default_mpn_ctx(out, xs, ys, true); } out[xs_len + ys_len - 1] } fn limbs_mul_greater_to_out_slow( r: &mut [Limb], x: &[Limb], y: &[Limb], scratch: &mut [Limb], ) -> Limb { let xs_len = x.len(); let ys_len = y.len(); assert!(xs_len >= ys_len); if xs_len == ys_len { limbs_mul_same_length_to_out_slow(r, x, y, scratch); } else if ys_len < FFT_MUL_THRESHOLD { let mut scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; limbs_mul_greater_to_out_old_slow(r, x, y, &mut scratch); } else { mpn_mul_default_mpn_ctx(r, x, y, true); } r[xs_len + ys_len - 1] } fn limbs_mul_greater_slow_fft(xs: &[Limb], ys: &[Limb]) -> Vec { let xs_len = xs.len(); let ys_len = ys.len(); let out_len = xs_len + ys_len; let mut scratch = vec![0; out_len + limbs_mul_greater_to_out_scratch_len(xs_len, ys_len)]; let (out, mul_scratch) = scratch.split_at_mut(out_len); limbs_mul_greater_to_out_slow(out, xs, ys, mul_scratch); scratch.truncate(out_len); scratch.shrink_to_fit(); scratch } fn limbs_mul_to_out_slow(out: &mut [Limb], xs: &[Limb], ys: &[Limb], scratch: &mut [Limb]) -> Limb { if xs.len() >= ys.len() { limbs_mul_greater_to_out_slow(out, xs, ys, scratch) } else { limbs_mul_greater_to_out_slow(out, ys, xs, scratch) } } pub fn mul_slow_fft(x: &Natural, y: &Natural) -> Natural { match (x, y) { (Natural(Small(x)), y) => y.mul_limb_ref(*x), (x, Natural(Small(y))) => x.mul_limb_ref(*y), (Natural(Large(xs)), Natural(Large(ys))) => { let big_limbs = if xs.len() >= ys.len() { limbs_mul_greater_slow_fft(xs, ys) } else { limbs_mul_greater_slow_fft(ys, xs) }; Natural::from_owned_limbs_asc(big_limbs) } } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/neg.rs ================================================ // Copyright © 2026 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 num::{BigInt, BigUint}; pub fn neg_num(u: BigUint) -> BigInt { -BigInt::from(u) } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/pow.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::SquareAssign; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::BitIterable; pub fn natural_pow_naive(n: &Natural, exp: u64) -> Natural { let mut result = Natural::ONE; for _ in 0..exp { result *= n; } result } pub fn natural_pow_simple_binary(n: &Natural, exp: u64) -> Natural { let mut result = Natural::ONE; for bit in exp.bits().rev() { result.square_assign(); if bit { result *= n; } } result } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::traits::Primes; pub fn primorial_naive(n: u64) -> Natural { Natural::primes_less_than_or_equal_to(&Natural::from(n)).product() } pub fn product_of_first_n_primes_naive(n: u64) -> Natural { Natural::primes().take(usize::exact_from(n)).product() } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/root.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::test_util::natural::arithmetic::sqrt::floor_inverse_binary; use malachite_base::num::arithmetic::traits::{DivRound, Pow, PowerOf2}; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; pub fn floor_root_binary(x: &Natural, exp: u64) -> Natural { if exp == 0 { panic!("Cannot take 0th root"); } else if exp == 1 || x < &Natural::TWO { x.clone() } else { let p = Natural::power_of_2(x.significant_bits().div_round(exp, Ceiling).0); floor_inverse_binary(|x| x.pow(exp), x, &p >> 1, p) } } pub fn ceiling_root_binary(x: &Natural, exp: u64) -> Natural { let floor_root = floor_root_binary(x, exp); if &(&floor_root).pow(exp) == x { floor_root } else { floor_root + Natural::ONE } } pub fn checked_root_binary(x: &Natural, exp: u64) -> Option { let floor_root = floor_root_binary(x, exp); if &(&floor_root).pow(exp) == x { Some(floor_root) } else { None } } pub fn root_rem_binary(x: &Natural, exp: u64) -> (Natural, Natural) { let floor_root = floor_root_binary(x, exp); let rem = x - (&floor_root).pow(exp); (floor_root, rem) } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::arithmetic::traits::{PowerOf2, ShrRound, Square}; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use std::cmp::Ordering::*; pub(crate) fn floor_inverse_binary Natural>( f: F, x: &Natural, mut low: Natural, mut high: Natural, ) -> Natural { loop { if high <= low { return low; } let mid = (&low + &high).shr_round(1, Ceiling).0; match f(&mid).cmp(x) { Equal => return mid, Less => low = mid, Greater => high = mid - Natural::ONE, } } } pub fn floor_sqrt_binary(x: &Natural) -> Natural { if x < &Natural::TWO { x.clone() } else { let p = Natural::power_of_2(x.significant_bits().shr_round(1, Ceiling).0); floor_inverse_binary(|x| x.square(), x, &p >> 1, p) } } pub fn ceiling_sqrt_binary(x: &Natural) -> Natural { let floor_sqrt = floor_sqrt_binary(x); if &(&floor_sqrt).square() == x { floor_sqrt } else { floor_sqrt + Natural::ONE } } pub fn checked_sqrt_binary(x: &Natural) -> Option { let floor_sqrt = floor_sqrt_binary(x); if &(&floor_sqrt).square() == x { Some(floor_sqrt) } else { None } } pub fn sqrt_rem_binary(x: &Natural) -> (Natural, Natural) { let floor_sqrt = floor_sqrt_binary(x); let rem = x - (&floor_sqrt).square(); (floor_sqrt, rem) } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::natural::arithmetic::add_mul::limbs_slice_add_mul_limb_same_length_in_place_left; use crate::natural::arithmetic::mul::limb::limbs_mul_limb_to_out; use crate::natural::arithmetic::square::limbs_square_diagonal_add_shl_1; use crate::platform::{DoubleLimb, Limb}; use malachite_base::num::arithmetic::traits::Square; use malachite_base::num::conversion::traits::SplitInHalf; pub fn limbs_square_to_out_basecase_unrestricted(out: &mut [Limb], xs: &[Limb]) { let n = xs.len(); let (xs_head, xs_tail) = xs.split_first().unwrap(); (out[1], out[0]) = DoubleLimb::from(*xs_head).square().split_in_half(); if n > 1 { let two_n = n << 1; let mut scratch = vec![0; two_n - 2]; let (scratch_last, scratch_init) = scratch[..n].split_last_mut().unwrap(); *scratch_last = limbs_mul_limb_to_out::(scratch_init, xs_tail, *xs_head); for i in 1..n - 1 { let (scratch_last, scratch_init) = scratch[i..][i..n].split_last_mut().unwrap(); let (xs_head, xs_tail) = xs[i..].split_first().unwrap(); *scratch_last = limbs_slice_add_mul_limb_same_length_in_place_left(scratch_init, xs_tail, *xs_head); } limbs_square_diagonal_add_shl_1(&mut out[..two_n], &mut scratch, xs); } } ================================================ FILE: malachite-nz/src/test_util/natural/arithmetic/sub.rs ================================================ // Copyright © 2026 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 crate::natural::arithmetic::sub::limbs_sub_same_length_in_place_left; use crate::platform::Limb; pub fn limbs_sub_same_length_in_place_with_overlap_naive( xs: &mut [Limb], right_start: usize, ) -> bool { let left_end = xs.len() - right_start; let mut x = xs[..left_end].to_vec(); let borrow = limbs_sub_same_length_in_place_left(&mut x, &xs[right_start..]); xs[..left_end].copy_from_slice(&x); borrow } // Given two slices `xs` and `ys`, computes the difference between the `Natural`s whose limbs are // `&xs[xs.len() - ys.len()..]` and `&ys`, and writes the limbs of the result to `&xs[..ys.len()]`. pub fn limbs_sub_same_length_to_out_with_overlap_naive(xs: &mut [Limb], ys: &[Limb]) -> bool { let y_len = ys.len(); let mut x = xs[xs.len() - y_len..].to_vec(); let borrow = limbs_sub_same_length_in_place_left(&mut x, ys); xs[..y_len].copy_from_slice(&x); borrow } ================================================ FILE: malachite-nz/src/test_util/natural/comparison/cmp.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::logic::traits::SignificantBits; use std::cmp::Ordering::{self, *}; pub fn natural_cmp_normalized_naive(x: &Natural, y: &Natural) -> Ordering { let x_bits = x.significant_bits(); let y_bits = y.significant_bits(); match x_bits.cmp(&y_bits) { Equal => x.cmp(y), Less => (x << (y_bits - x_bits)).cmp(y), Greater => x.cmp(&(y << (x_bits - y_bits))), } } ================================================ FILE: malachite-nz/src/test_util/natural/comparison/mod.rs ================================================ // Copyright © 2026 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 . pub mod cmp; pub mod partial_cmp_primitive_int; pub mod partial_eq_primitive_int; ================================================ FILE: malachite-nz/src/test_util/natural/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 num::BigUint; use std::cmp::Ordering; pub fn num_partial_cmp_unsigned(x: &BigUint, u: T) -> Option where BigUint: From, { x.partial_cmp(&BigUint::from(u)) } ================================================ FILE: malachite-nz/src/test_util/natural/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 num::BigUint; pub fn num_partial_eq_unsigned(x: &BigUint, u: T) -> bool where BigUint: From, { *x == BigUint::from(u) } ================================================ FILE: malachite-nz/src/test_util/natural/conversion/mod.rs ================================================ // Copyright © 2026 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 . pub mod string; ================================================ FILE: malachite-nz/src/test_util/natural/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::basic::traits::Zero; pub fn from_string_base_naive(small_base: u8, s: &str) -> Option { let mut x = Natural::ZERO; let base = Natural::from(small_base); for c in s.chars() { x *= &base; x += Natural::from(c.to_digit(u32::from(small_base))?); } Some(x) } ================================================ FILE: malachite-nz/src/test_util/natural/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . pub mod from_string; pub mod to_string; ================================================ FILE: malachite-nz/src/test_util/natural/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::conversion::string::to_string::digit_to_display_byte_lower; use malachite_base::num::conversion::traits::WrappingFrom; pub fn to_string_base_naive(x: &Natural, base: u8) -> String { assert!((2..=36).contains(&base), "base out of range"); let base = Limb::from(base); if *x == 0 { "0".to_string() } else { let mut x = x.clone(); let mut cs = Vec::new(); while x != 0 { cs.push(char::from( digit_to_display_byte_lower(u8::wrapping_from(x.div_assign_mod_limb(base))) .unwrap(), )); } cs.into_iter().rev().collect() } } ================================================ FILE: malachite-nz/src/test_util/natural/logic/and.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::test_util::natural::logic::{natural_op_bits, natural_op_limbs}; pub fn natural_and_alt_1(x: &Natural, y: &Natural) -> Natural { natural_op_bits(&|a, b| a && b, x, y) } pub fn natural_and_alt_2(x: &Natural, y: &Natural) -> Natural { natural_op_limbs(&|a, b| a & b, x, y) } ================================================ FILE: malachite-nz/src/test_util/natural/logic/count_ones.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitIterable, CountOnes}; pub fn natural_count_ones_alt_1(n: &Natural) -> u64 { u64::exact_from(n.bits().filter(|&b| b).count()) } pub fn natural_count_ones_alt_2(n: &Natural) -> u64 { n.limbs().map(CountOnes::count_ones).sum() } ================================================ FILE: malachite-nz/src/test_util/natural/logic/from_bits.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use itertools::Itertools; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; pub fn from_bits_asc_naive>(bits: I) -> Natural { let mut n = Natural::ZERO; for i in bits.enumerate().filter_map(|(index, bit)| { if bit { Some(u64::exact_from(index)) } else { None } }) { n.set_bit(i); } n } pub fn from_bits_desc_naive>(bits: I) -> Natural { let bits = bits.collect_vec(); let mut n = Natural::ZERO; for i in bits.iter().rev().enumerate().filter_map(|(index, &bit)| { if bit { Some(u64::exact_from(index)) } else { None } }) { n.set_bit(i); } n } ================================================ FILE: malachite-nz/src/test_util/natural/logic/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use num::{BigUint, One, Zero}; pub fn num_get_bit(x: &BigUint, index: u64) -> bool { x & (BigUint::one() << usize::exact_from(index)) != BigUint::zero() } ================================================ FILE: malachite-nz/src/test_util/natural/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::logic::traits::{BitIterable, HammingDistance, SignificantBits}; use std::iter::repeat; pub fn natural_hamming_distance_alt_1(x: &Natural, y: &Natural) -> u64 { let bit_zip: Box> = if x.significant_bits() >= y.significant_bits() { Box::new(x.bits().zip(y.bits().chain(repeat(false)))) } else { Box::new(x.bits().chain(repeat(false)).zip(y.bits())) }; let mut distance = 0u64; for (b, c) in bit_zip { if b != c { distance += 1; } } distance } pub fn natural_hamming_distance_alt_2(x: &Natural, y: &Natural) -> u64 { let limb_zip: Box> = if x.limb_count() >= y.limb_count() { Box::new(x.limbs().zip(y.limbs().chain(repeat(0)))) } else { Box::new(x.limbs().chain(repeat(0)).zip(y.limbs())) }; let mut distance = 0u64; for (x, y) in limb_zip { distance += x.hamming_distance(y); } distance } pub fn rug_hamming_distance(x: &rug::Integer, y: &rug::Integer) -> u64 { u64::from(x.hamming_dist(y).unwrap()) } ================================================ FILE: malachite-nz/src/test_util/natural/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::BitIterable; use std::iter::repeat; pub fn natural_index_of_next_false_bit_alt(n: &Natural, u: u64) -> Option { for (i, bit) in n .bits() .chain(repeat(false)) .enumerate() .skip(usize::exact_from(u)) { if !bit { return Some(u64::wrapping_from(i)); } } unreachable!(); } ================================================ FILE: malachite-nz/src/test_util/natural/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::num::logic::traits::BitIterable; pub fn natural_index_of_next_true_bit_alt(n: &Natural, u: u64) -> Option { for (i, bit) in n.bits().enumerate().skip(usize::exact_from(u)) { if bit { return Some(u64::wrapping_from(i)); } } None } ================================================ FILE: malachite-nz/src/test_util/natural/logic/mod.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::platform::Limb; use malachite_base::num::logic::traits::{BitConvertible, BitIterable, SignificantBits}; use std::iter::repeat; pub fn natural_op_bits(bit_fn: &dyn Fn(bool, bool) -> bool, x: &Natural, y: &Natural) -> Natural { let bit_zip: Box> = if x.significant_bits() >= y.significant_bits() { Box::new(x.bits().zip(y.bits().chain(repeat(false)))) } else { Box::new(x.bits().chain(repeat(false)).zip(y.bits())) }; Natural::from_bits_asc(bit_zip.map(|(b, c)| bit_fn(b, c))) } pub fn natural_op_limbs(limb_fn: &dyn Fn(Limb, Limb) -> Limb, x: &Natural, y: &Natural) -> Natural { let limb_zip: Box> = if x.limb_count() >= y.limb_count() { Box::new(x.limbs().zip(y.limbs().chain(repeat(0)))) } else { Box::new(x.limbs().chain(repeat(0)).zip(y.limbs())) }; let mut and_limbs = Vec::new(); for (x, y) in limb_zip { and_limbs.push(limb_fn(x, y)); } Natural::from_owned_limbs_asc(and_limbs) } pub mod and; pub mod count_ones; pub mod from_bits; pub mod get_bit; pub mod hamming_distance; pub mod index_of_next_false_bit; pub mod index_of_next_true_bit; pub mod or; pub mod set_bit; pub mod to_bits; pub mod trailing_zeros; pub mod xor; ================================================ FILE: malachite-nz/src/test_util/natural/logic/or.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::test_util::natural::logic::{natural_op_bits, natural_op_limbs}; pub fn natural_or_alt_1(x: &Natural, y: &Natural) -> Natural { natural_op_bits(&|a, b| a || b, x, y) } pub fn natural_or_alt_2(x: &Natural, y: &Natural) -> Natural { natural_op_limbs(&|a, b| a | b, x, y) } ================================================ FILE: malachite-nz/src/test_util/natural/logic/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use num::{BigUint, One}; pub fn num_set_bit(x: &mut BigUint, index: u64) { *x = x.clone() | (BigUint::one() << usize::exact_from(index)); } ================================================ FILE: malachite-nz/src/test_util/natural/logic/to_bits.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; pub fn to_bits_asc_naive(n: &Natural) -> Vec { let mut bits = Vec::new(); for i in 0..n.significant_bits() { bits.push(n.get_bit(i)); } bits } pub fn to_bits_desc_naive(n: &Natural) -> Vec { let mut bits = Vec::new(); for i in (0..n.significant_bits()).rev() { bits.push(n.get_bit(i)); } bits } ================================================ FILE: malachite-nz/src/test_util/natural/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::BitIterable; pub fn natural_trailing_zeros_alt(n: &Natural) -> Option { if *n == 0 { None } else { Some(u64::wrapping_from(n.bits().take_while(|&b| !b).count())) } } ================================================ FILE: malachite-nz/src/test_util/natural/logic/xor.rs ================================================ // Copyright © 2026 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 crate::natural::Natural; use crate::test_util::natural::logic::{natural_op_bits, natural_op_limbs}; pub fn natural_xor_alt_1(x: &Natural, y: &Natural) -> Natural { natural_op_bits(&|a, b| a ^ b, x, y) } pub fn natural_xor_alt_2(x: &Natural, y: &Natural) -> Natural { natural_op_limbs(&|a, b| a ^ b, x, y) } ================================================ FILE: malachite-nz/src/test_util/natural/mod.rs ================================================ // Copyright © 2026 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 . pub mod arithmetic; pub mod comparison; pub mod conversion; pub mod logic; pub mod random; ================================================ FILE: malachite-nz/src/test_util/natural/random/mod.rs ================================================ // Copyright © 2026 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 crate::itertools::Itertools; use crate::natural::Natural; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{MomentStats, moment_stats}; pub fn random_naturals_helper_helper>( xs: I, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { let actual_values = xs .clone() .map(|x| Natural::to_string(&x)) .take(20) .collect_vec(); let actual_values = actual_values.iter().map(String::as_str).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .into_iter() .map(|(x, freq)| (x.to_string(), freq)) .collect_vec(); let actual_common_values = actual_common_values .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.clone().take(1000000)); let (median_lo, median_hi) = ( median_lo.to_string(), median_hi.map(|x| Natural::to_string(&x)), ); let actual_sample_median = (median_lo.as_str(), median_hi.as_deref()); let actual_sample_moment_stats = moment_stats(xs.take(1000000).map(|x| f64::rounding_from(&x, Nearest).0)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), actual_sample_median, actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats ) ); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign, DivAssignMod, UnsignedAbs}; use malachite_base::num::basic::traits::Two; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{SignedDoubleLimb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, integer_integer_natural_triple_gen}; use num::{BigInt, Signed}; use std::str::FromStr; #[test] fn test_abs() { let test = |s, out| { let n = Integer::from_str(s).unwrap(); let abs = n.clone().abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); let abs = (&n).abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); assert_eq!(BigInt::from_str(s).unwrap().abs().to_string(), out); assert_eq!(rug::Integer::from_str(s).unwrap().abs().to_string(), out); let abs = n.clone().unsigned_abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); let abs = (&n).unsigned_abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); let x = n.clone(); let abs = x.unsigned_abs_ref(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); let mut x = n; x.abs_assign(); assert!(abs.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "0"); test("123", "123"); test("-123", "123"); test("1000000000000", "1000000000000"); test("-1000000000000", "1000000000000"); test("3000000000", "3000000000"); test("-3000000000", "3000000000"); test("-2147483648", "2147483648"); let mut n = Integer::from(-123); let remainder = n.mutate_unsigned_abs(|x| x.div_assign_mod(Natural::TWO)); assert_eq!(n, -61); assert_eq!(remainder, 1); let mut n = Integer::from(-123); n.mutate_unsigned_abs(|x| *x >>= 10); assert_eq!(n, 0); } #[test] fn abs_properties() { integer_gen().test_properties(|x| { let abs = x.clone().abs(); assert!(abs.is_valid()); assert_eq!(Integer::from(&BigInt::from(&x).abs()), abs); assert_eq!(Integer::from(&rug::Integer::from(&x).abs()), abs); let abs_alt = (&x).abs(); assert!(abs_alt.is_valid()); assert_eq!(abs_alt, abs); let mut abs_alt = x.clone(); abs_alt.abs_assign(); assert!(abs_alt.is_valid()); assert_eq!(abs_alt, abs); assert!(abs >= 0); assert_eq!(abs == x, x >= 0); assert_eq!((&abs).abs(), abs); let abs_alt = x.clone().unsigned_abs(); assert!(abs_alt.is_valid()); assert_eq!(Ok(abs_alt), (&abs).try_into()); let abs_alt = (&x).unsigned_abs(); assert!(abs_alt.is_valid()); assert_eq!(Ok(&abs_alt), abs.try_into().as_ref()); let internal_abs = x.unsigned_abs_ref(); assert!(internal_abs.is_valid()); assert_eq!(*internal_abs, abs_alt); }); signed_gen::().test_properties(|i| { assert_eq!( Integer::from(i).abs(), Integer::from(SignedDoubleLimb::from(i).abs()) ); }); } #[test] fn mutate_unsigned_abs_properties() { integer_integer_natural_triple_gen().test_properties(|(mut n, out, new_abs)| { let out_2 = out.clone(); let new_abs_2 = new_abs.clone(); assert_eq!( n.mutate_unsigned_abs(|x| { *x = new_abs; out }), out_2 ); assert!(n.is_valid()); assert_eq!(n.abs(), new_abs_2); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsDiff, AbsDiffAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen, integer_triple_gen}; use std::str::FromStr; #[test] fn test_abs_diff_integer() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n.abs_diff_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.abs_diff_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("456", "123", "333"); test("1000000000000", "123", "999999999877"); test("123", "1000000000000", "999999999877"); test("12345678987654321", "314159265358979", "12031519722295342"); test("4294967296", "1", "4294967295"); test("4294967295", "4294967295", "0"); test("4294967296", "4294967295", "1"); test("4294967296", "4294967296", "0"); test("4294967295", "4294967296", "1"); test("18446744073709551616", "1", "18446744073709551615"); test("18446744073709551615", "18446744073709551615", "0"); test("18446744073709551616", "18446744073709551615", "1"); test("18446744073709551615", "18446744073709551616", "1"); test("70734740290631708", "282942734368", "70734457347897340"); test("282942734368", "70734740290631708", "70734457347897340"); test("0", "-123", "123"); test("456", "-123", "579"); test("1000000000000", "-123", "1000000000123"); test("123", "-1000000000000", "1000000000123"); test("12345678987654321", "-314159265358979", "12659838253013300"); test("4294967296", "-1", "4294967297"); test("4294967295", "-4294967295", "8589934590"); test("4294967296", "-4294967295", "8589934591"); test("4294967296", "-4294967296", "8589934592"); test("4294967295", "-4294967296", "8589934591"); test("18446744073709551616", "-1", "18446744073709551617"); test( "18446744073709551615", "-18446744073709551615", "36893488147419103230", ); test( "18446744073709551616", "-18446744073709551615", "36893488147419103231", ); test( "18446744073709551615", "-18446744073709551616", "36893488147419103231", ); test("70734740290631708", "-282942734368", "70735023233366076"); test("282942734368", "-70734740290631708", "70735023233366076"); test("-123", "0", "123"); test("-456", "123", "579"); test("-1000000000000", "123", "1000000000123"); test("-123", "1000000000000", "1000000000123"); test("-12345678987654321", "314159265358979", "12659838253013300"); test("-4294967296", "1", "4294967297"); test("-4294967295", "4294967295", "8589934590"); test("-4294967296", "4294967295", "8589934591"); test("-4294967296", "4294967296", "8589934592"); test("-4294967295", "4294967296", "8589934591"); test("-18446744073709551616", "1", "18446744073709551617"); test( "-18446744073709551615", "18446744073709551615", "36893488147419103230", ); test( "-18446744073709551616", "18446744073709551615", "36893488147419103231", ); test( "-18446744073709551615", "18446744073709551616", "36893488147419103231", ); test("-70734740290631708", "282942734368", "70735023233366076"); test("-282942734368", "70734740290631708", "70735023233366076"); test("-456", "-123", "333"); test("-1000000000000", "-123", "999999999877"); test("-123", "-1000000000000", "999999999877"); test( "-12345678987654321", "-314159265358979", "12031519722295342", ); test("-4294967296", "-1", "4294967295"); test("-4294967295", "-4294967295", "0"); test("-4294967296", "-4294967295", "1"); test("-4294967296", "-4294967296", "0"); test("-4294967295", "-4294967296", "1"); test("-18446744073709551616", "-1", "18446744073709551615"); test("-18446744073709551615", "-18446744073709551615", "0"); test("-18446744073709551616", "-18446744073709551615", "1"); test("-18446744073709551615", "-18446744073709551616", "1"); test("-70734740290631708", "-282942734368", "70734457347897340"); test("-282942734368", "-70734740290631708", "70734457347897340"); } #[test] fn abs_diff_properties() { integer_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.abs_diff_assign(&y); assert!(mut_x.is_valid()); let diff = mut_x; let mut mut_x = x.clone(); mut_x.abs_diff_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let diff_alt = x.clone().abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = x.clone().abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); assert_eq!((&x - &y).abs(), diff); assert_eq!((&y).abs_diff(&x), diff); assert_eq!((-&x).abs_diff(-&y), diff); assert_eq!(diff == 0, x == y); }); integer_gen().test_properties(|x| { assert_eq!((&x).abs_diff(Integer::ZERO), (&x).abs()); assert_eq!((&x).abs_diff(&x), 0); assert_eq!(Integer::ZERO.abs_diff(&x), x.abs()); }); integer_triple_gen().test_properties(|(x, y, z)| { assert!((&x).abs_diff(&z) <= x.abs_diff(&y) + y.abs_diff(z)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(x.abs_diff(y), Integer::from(x).abs_diff(Integer::from(y))); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::signed_pair_gen; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{SignedDoubleLimb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, integer_vec_gen, natural_pair_gen, natural_vec_gen, }; use malachite_nz::test_util::integer::arithmetic::add::integer_sum_alt; use num::BigInt; use std::iter::{Sum, once}; use std::str::FromStr; #[test] fn test_add() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n += v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n += &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigInt::from_str(s).unwrap() + BigInt::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() + rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "579"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("12345678987654321", "314159265358979", "12659838253013300"); test("0", "-123", "-123"); test("123", "-123", "0"); test("123", "-456", "-333"); test("1000000000000", "-123", "999999999877"); test("123", "-1000000000000", "-999999999877"); test("12345678987654321", "-314159265358979", "12031519722295342"); } #[test] fn test_sum() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let sum = Integer::sum(xs.iter().cloned()); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); let sum_alt = Integer::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = integer_sum_alt(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }; test("[]", "0"); test("[10]", "10"); test("[6, -2]", "4"); test("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "55"); test("[123456, -789012, 345678, -9012345]", "-9332223"); } #[test] fn add_properties() { integer_pair_gen().test_properties(|(x, y)| { let sum_val_val = x.clone() + y.clone(); let sum_val_ref = x.clone() + &y; let sum_ref_val = &x + y.clone(); let sum = &x + &y; assert!(sum_val_val.is_valid()); assert!(sum_val_ref.is_valid()); assert!(sum_ref_val.is_valid()); assert!(sum.is_valid()); assert_eq!(sum_val_val, sum); assert_eq!(sum_val_ref, sum); assert_eq!(sum_ref_val, sum); let mut mut_x = x.clone(); mut_x += y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x += &y; assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x += rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), sum); assert_eq!(Integer::from(&(BigInt::from(&x) + BigInt::from(&y))), sum); assert_eq!( Integer::from(&(rug::Integer::from(&x) + rug::Integer::from(&y))), sum ); assert_eq!(&y + &x, sum); assert_eq!(&sum - &x, y); assert_eq!(sum - y, x); }); integer_gen().test_properties(|ref x| { assert_eq!(x + Integer::ZERO, *x); assert_eq!(Integer::ZERO + x, *x); assert_eq!(x + x, x << 1); assert_eq!(x + (-x), 0); }); integer_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x + &y) + &z, x + (y + z)); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(&x + &y, Integer::from(x) + Integer::from(y)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(SignedDoubleLimb::from(x) + SignedDoubleLimb::from(y)), Integer::from(x) + Integer::from(y) ); }); } #[test] fn sum_properties() { integer_vec_gen().test_properties(|xs| { let sum = Integer::sum(xs.iter().cloned()); assert!(sum.is_valid()); let sum_alt = Integer::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = integer_sum_alt(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }); integer_gen().test_properties(|x| { assert_eq!(Integer::sum(once(&x)), x); assert_eq!(Integer::sum(once(x.clone())), x); }); integer_pair_gen().test_properties(|(x, y)| { let sum = &x + &y; assert_eq!(Integer::sum([&x, &y].into_iter()), sum); assert_eq!(Integer::sum([x, y].into_iter()), sum); }); natural_vec_gen().test_properties(|xs| { assert_eq!( Integer::sum(xs.iter().map(Integer::from)), Integer::from(Natural::sum(xs.into_iter())) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign, CheckedAddMul}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::test_util::generators::{signed_triple_gen, signed_triple_gen_var_1}; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_triple_gen, }; use std::str::FromStr; #[test] fn test_add_mul() { let test = |r, s, t, out| { let u = Integer::from_str(r).unwrap(); let v = Integer::from_str(s).unwrap(); let w = Integer::from_str(t).unwrap(); let mut a = u.clone(); a.add_mul_assign(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = (&u).add_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); }; test("0", "0", "0", "0"); test("0", "0", "123", "0"); test("123", "0", "5", "123"); test("123", "5", "1", "128"); test("123", "5", "100", "623"); test("10", "3", "4", "22"); test("1000000000000", "0", "123", "1000000000000"); test("1000000000000", "1", "123", "1000000000123"); test("1000000000000", "123", "1", "1000000000123"); test("1000000000000", "123", "100", "1000000012300"); test("1000000000000", "100", "123", "1000000012300"); test("1000000000000", "65536", "65536", "1004294967296"); test("1000000000000", "1000000000000", "0", "1000000000000"); test("1000000000000", "1000000000000", "1", "2000000000000"); test("1000000000000", "1000000000000", "100", "101000000000000"); test("0", "1000000000000", "100", "100000000000000"); test( "1000000000000", "65536", "1000000000000", "65537000000000000", ); test( "1000000000000", "1000000000000", "1000000000000", "1000000000001000000000000", ); test( "0", "1000000000000", "1000000000000", "1000000000000000000000000", ); test("123", "-5", "-1", "128"); test("123", "-5", "-100", "623"); test("10", "-3", "-4", "22"); test("1000000000000", "-1", "-123", "1000000000123"); test("1000000000000", "-123", "-1", "1000000000123"); test("1000000000000", "-123", "-100", "1000000012300"); test("1000000000000", "-100", "-123", "1000000012300"); test("1000000000000", "-65536", "-65536", "1004294967296"); test("1000000000000", "-1000000000000", "-1", "2000000000000"); test("1000000000000", "-1000000000000", "-100", "101000000000000"); test("0", "-1000000000000", "-100", "100000000000000"); test( "1000000000000", "-65536", "-1000000000000", "65537000000000000", ); test( "1000000000000", "-1000000000000", "-1000000000000", "1000000000001000000000000", ); test( "0", "-1000000000000", "-1000000000000", "1000000000000000000000000", ); test("0", "0", "-123", "0"); test("123", "0", "-5", "123"); test("123", "-5", "1", "118"); test("123", "5", "-1", "118"); test("123", "-5", "100", "-377"); test("123", "5", "-100", "-377"); test("10", "-3", "4", "-2"); test("10", "3", "-4", "-2"); test("15", "-3", "4", "3"); test("15", "3", "-4", "3"); test("1000000000000", "0", "-123", "1000000000000"); test("1000000000000", "-1", "123", "999999999877"); test("1000000000000", "1", "-123", "999999999877"); test("1000000000000", "-123", "1", "999999999877"); test("1000000000000", "123", "-1", "999999999877"); test("1000000000000", "-123", "100", "999999987700"); test("1000000000000", "123", "-100", "999999987700"); test("1000000000000", "-100", "123", "999999987700"); test("1000000000000", "100", "-123", "999999987700"); test("1000000000000", "-65536", "65536", "995705032704"); test("1000000000000", "65536", "-65536", "995705032704"); test("1000000000000", "-1000000000000", "0", "1000000000000"); test("1000000000000", "-1000000000000", "1", "0"); test("1000000000000", "1000000000000", "-1", "0"); test("1000000000000", "-1000000000000", "100", "-99000000000000"); test("1000000000000", "1000000000000", "-100", "-99000000000000"); test("0", "-1000000000000", "100", "-100000000000000"); test("4294967296", "-1", "1", "4294967295"); test("4294967296", "1", "-1", "4294967295"); test("3902609153", "-88817093856604", "1", "-88813191247451"); test("3902609153", "88817093856604", "-1", "-88813191247451"); test("-123", "0", "5", "-123"); test("-123", "-5", "1", "-128"); test("-123", "-5", "100", "-623"); test("-10", "-3", "4", "-22"); test("-1000000000000", "0", "123", "-1000000000000"); test("-1000000000000", "-1", "123", "-1000000000123"); test("-1000000000000", "-123", "1", "-1000000000123"); test("-1000000000000", "-123", "100", "-1000000012300"); test("-1000000000000", "-100", "123", "-1000000012300"); test("-1000000000000", "-65536", "65536", "-1004294967296"); test("-1000000000000", "-1000000000000", "0", "-1000000000000"); test("-1000000000000", "-1000000000000", "1", "-2000000000000"); test( "-1000000000000", "-1000000000000", "100", "-101000000000000", ); test( "-1000000000000", "-65536", "1000000000000", "-65537000000000000", ); test( "-1000000000000", "-1000000000000", "1000000000000", "-1000000000001000000000000", ); test( "0", "-1000000000000", "1000000000000", "-1000000000000000000000000", ); test("-123", "5", "-1", "-128"); test("-123", "5", "-100", "-623"); test("-10", "3", "-4", "-22"); test("-1000000000000", "1", "-123", "-1000000000123"); test("-1000000000000", "123", "-1", "-1000000000123"); test("-1000000000000", "123", "-100", "-1000000012300"); test("-1000000000000", "100", "-123", "-1000000012300"); test("-1000000000000", "65536", "-65536", "-1004294967296"); test("-1000000000000", "1000000000000", "-1", "-2000000000000"); test( "-1000000000000", "1000000000000", "-100", "-101000000000000", ); test( "-1000000000000", "65536", "-1000000000000", "-65537000000000000", ); test( "-1000000000000", "1000000000000", "-1000000000000", "-1000000000001000000000000", ); test("-123", "0", "-5", "-123"); test("-123", "5", "1", "-118"); test("-123", "-5", "-1", "-118"); test("-123", "5", "100", "377"); test("-123", "-5", "-100", "377"); test("-10", "3", "4", "2"); test("-10", "-3", "-4", "2"); test("-15", "3", "4", "-3"); test("-15", "-3", "-4", "-3"); test("-1000000000000", "0", "-123", "-1000000000000"); test("-1000000000000", "1", "123", "-999999999877"); test("-1000000000000", "-1", "-123", "-999999999877"); test("-1000000000000", "123", "1", "-999999999877"); test("-1000000000000", "-123", "-1", "-999999999877"); test("-1000000000000", "123", "100", "-999999987700"); test("-1000000000000", "-123", "-100", "-999999987700"); test("-1000000000000", "100", "123", "-999999987700"); test("-1000000000000", "-100", "-123", "-999999987700"); test("-1000000000000", "65536", "65536", "-995705032704"); test("-1000000000000", "-65536", "-65536", "-995705032704"); test("-1000000000000", "1000000000000", "0", "-1000000000000"); test("-1000000000000", "1000000000000", "1", "0"); test("-1000000000000", "-1000000000000", "-1", "0"); test("-1000000000000", "1000000000000", "100", "99000000000000"); test("-1000000000000", "-1000000000000", "-100", "99000000000000"); test("-4294967296", "1", "1", "-4294967295"); test("-4294967296", "-1", "-1", "-4294967295"); test("-3902609153", "88817093856604", "1", "88813191247451"); test("-3902609153", "-88817093856604", "-1", "88813191247451"); test( "1000000000000000000000000", "-1000000000000", "1000000000000", "0", ); test( "-4", "-24227802588", "-14313318194700", "346780247600420147883596", ); } #[test] fn add_mul_properties() { integer_triple_gen().test_properties(|(a, b, c)| { let mut mut_a = a.clone(); mut_a.add_mul_assign(b.clone(), c.clone()); assert!(mut_a.is_valid()); let result = mut_a; let mut mut_a = a.clone(); mut_a.add_mul_assign(b.clone(), &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.add_mul_assign(&b, c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.add_mul_assign(&b, &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let result_alt = a.clone().add_mul(b.clone(), c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(b.clone(), &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(&b, c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = (&a).add_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let a = &a; let b = &b; let c = &c; assert_eq!(a + b * c, result); assert_eq!(a.add_mul(c, b), result); assert_eq!(a.add_mul(&(-b), &(-c)), result); assert_eq!((-a).add_mul(&(-b), c), -&result); assert_eq!((-a).add_mul(b, -c), -result); }); integer_gen().test_properties(|a| { let a = &a; assert_eq!(a.add_mul(a, &Integer::NEGATIVE_ONE), 0); assert_eq!(a.add_mul(&(-a), &Integer::ONE), 0); }); integer_pair_gen().test_properties(|(a, b)| { let a = &a; let b = &b; assert_eq!(a.add_mul(&Integer::ZERO, b), *a); assert_eq!(a.add_mul(&Integer::ONE, b), a + b); assert_eq!(Integer::ZERO.add_mul(a, b), a * b); assert_eq!(a.add_mul(b, &Integer::ZERO), *a); assert_eq!(a.add_mul(b, &Integer::ONE), a + b); assert_eq!((a * b).add_mul(-a, b), 0); assert_eq!((a * b).add_mul(a, -b), 0); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!( (&x).add_mul(&y, &z), Integer::from(x).add_mul(Integer::from(y), Integer::from(z)) ); }); signed_triple_gen_var_1::().test_properties(|(x, y, z)| { assert_eq!( x.add_mul(y, z), Integer::from(x).add_mul(Integer::from(y), Integer::from(z)) ); }); signed_triple_gen::().test_properties(|(x, y, z)| { let result = Integer::from(x).add_mul(Integer::from(y), Integer::from(z)); assert_eq!( x.checked_add_mul(y, z).is_some(), SignedLimb::convertible_from(&result) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{BinomialCoefficient, NegAssign, Parity}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::signed_pair_gen_var_12; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, integer_gen_var_4, integer_pair_gen_var_7}; use std::str::FromStr; #[test] fn test_binomial_coefficient() { fn test(n: &str, k: &str, out: &str) { let n = Integer::from_str(n).unwrap(); let k = Integer::from_str(k).unwrap(); let b = Integer::binomial_coefficient(n.clone(), k.clone()); assert!(b.is_valid()); assert_eq!(b.to_string(), out); let b_alt = Integer::binomial_coefficient(&n, &k); assert!(b_alt.is_valid()); assert_eq!(b_alt, b); assert_eq!( rug::Integer::from(&n) .binomial(u32::exact_from(&k)) .to_string(), out, ); } test("0", "0", "1"); test("1", "0", "1"); test("1", "1", "1"); test("2", "0", "1"); test("2", "1", "2"); test("2", "2", "1"); test("3", "0", "1"); test("3", "1", "3"); test("3", "2", "3"); test("3", "3", "1"); test("4", "0", "1"); test("4", "1", "4"); test("4", "2", "6"); test("4", "3", "4"); test("4", "4", "1"); test("1", "2", "0"); test("10", "5", "252"); test("100", "50", "100891344545564193334812497256"); test("-1", "0", "1"); test("-1", "1", "-1"); test("-2", "0", "1"); test("-2", "1", "-2"); test("-2", "2", "3"); test("-3", "0", "1"); test("-3", "1", "-3"); test("-3", "2", "6"); test("-3", "3", "-10"); test("-1", "2", "1"); test("-10", "5", "-2002"); test("-80", "50", "1828256793482238093393785743858493760"); test("-128", "1", "-128"); test("-2", "127", "-128"); } #[test] fn binomial_coefficient_properties() { integer_pair_gen_var_7().test_properties(|(n, k)| { let b = Integer::binomial_coefficient(n.clone(), k.clone()); assert!(b.is_valid()); let b_alt = Integer::binomial_coefficient(&n, &k); assert!(b_alt.is_valid()); assert_eq!(b, b_alt); assert_eq!( Integer::from(&rug::Integer::from(&n).binomial(u32::exact_from(&k))), b ); assert_eq!(b == 0, n >= 0 && n < k); if n >= k { assert_eq!(Integer::binomial_coefficient(&n, &(&n - &k)), b); } if k != 0u32 { let c = Integer::binomial_coefficient(&(&n - Integer::ONE), &k); assert_eq!( c + Integer::binomial_coefficient(&n - Integer::ONE, &k - Integer::ONE), b ); } let mut b_alt = Integer::binomial_coefficient(&((&n - Integer::ONE) + &k), &k); if k.odd() { b_alt.neg_assign(); } assert_eq!(Integer::binomial_coefficient(-n, k), b_alt); }); integer_gen().test_properties(|n| { assert_eq!(Integer::binomial_coefficient(&n, &Integer::ONE), n); assert_eq!(Integer::binomial_coefficient(n, Integer::ZERO), 1); }); integer_gen_var_4().test_properties(|n| { assert_eq!(Integer::binomial_coefficient(&n, &n), 1u32); if n != 0 { assert_eq!(Integer::binomial_coefficient(&n, &(&n - Integer::ONE)), n); assert_eq!(Integer::binomial_coefficient(Integer::ZERO, n), 0); } }); signed_pair_gen_var_12::().test_properties(|(n, k)| { assert_eq!( Integer::binomial_coefficient(Integer::from(n), Integer::from(k)), SignedLimb::binomial_coefficient(n, k) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedDiv, DivRem}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_pair_gen_var_4; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_8, integer_pair_gen, integer_pair_gen_var_1, integer_pair_gen_var_2, natural_pair_gen_var_5, }; use num::BigInt; use std::str::FromStr; #[test] fn test_div() { let test = |s, t, quotient| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); x /= v.clone(); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); x /= &v; assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let q = u.clone() / v.clone(); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.clone() / &v; assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = &u / v.clone(); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = &u / &v; assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = BigInt::from_str(s).unwrap() / &BigInt::from_str(t).unwrap(); assert_eq!(q.to_string(), quotient); let q = rug::Integer::from_str(s).unwrap() / rug::Integer::from_str(t).unwrap(); assert_eq!(q.to_string(), quotient); let q = u.div_rem(v).0; assert_eq!(q.to_string(), quotient); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "1"); test("123", "1", "123"); test("123", "123", "1"); test("123", "456", "0"); test("456", "123", "3"); test("4294967295", "1", "4294967295"); test("4294967295", "4294967295", "1"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "3", "333333333333"); test("1000000000000", "123", "8130081300"); test("1000000000000", "4294967295", "232"); test( "1000000000000000000000000", "1", "1000000000000000000000000", ); test("1000000000000000000000000", "3", "333333333333333333333333"); test("1000000000000000000000000", "123", "8130081300813008130081"); test("1000000000000000000000000", "4294967295", "232830643708079"); test("1000000000000000000000000", "1234567890987", "810000006723"); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290113", ); test("3768477692975601", "11447376614057827956", "0"); test("3356605361737854", "3081095617839357", "1"); test("1098730198198174614195", "953382298040157850476", "1"); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", ); test("0", "1000000000000000000000000", "0"); test("123", "1000000000000000000000000", "0"); test( "915607705283450388306561139234228660872677067256472842161753852459689688332903348325308112\ 7923093090598913", "11669177832462215441614364516705357863717491965951", "784637716923245892498679555408392159158150581185689944063", ); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "-1"); test("123", "-1", "-123"); test("123", "-123", "-1"); test("123", "-456", "0"); test("456", "-123", "-3"); test("4294967295", "-1", "-4294967295"); test("4294967295", "-4294967295", "-1"); test("1000000000000", "-1", "-1000000000000"); test("1000000000000", "-3", "-333333333333"); test("1000000000000", "-123", "-8130081300"); test("1000000000000", "-4294967295", "-232"); test( "1000000000000000000000000", "-1", "-1000000000000000000000000", ); test( "1000000000000000000000000", "-3", "-333333333333333333333333", ); test( "1000000000000000000000000", "-123", "-8130081300813008130081", ); test( "1000000000000000000000000", "-4294967295", "-232830643708079", ); test( "1000000000000000000000000", "-1234567890987", "-810000006723", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", ); test( "253640751230376270397812803167", "-2669936877441", "-94998781946290113", ); test("3768477692975601", "-11447376614057827956", "0"); test("3356605361737854", "-3081095617839357", "-1"); test("1098730198198174614195", "-953382298040157850476", "-1"); test( "69738658860594537152875081748", "-69738658860594537152875081748", "-1", ); test( "1000000000000000000000000", "-1000000000000000000000000", "-1", ); test("0", "-1000000000000000000000000", "0"); test("123", "-1000000000000000000000000", "0"); test( "915607705283450388306561139234228660872677067256472842161753852459689688332903348325308112\ 7923093090598913", "-11669177832462215441614364516705357863717491965951", "-784637716923245892498679555408392159158150581185689944063", ); test("-1", "1", "-1"); test("-123", "1", "-123"); test("-123", "123", "-1"); test("-123", "456", "0"); test("-456", "123", "-3"); test("-4294967295", "1", "-4294967295"); test("-4294967295", "4294967295", "-1"); test("-1000000000000", "1", "-1000000000000"); test("-1000000000000", "3", "-333333333333"); test("-1000000000000", "123", "-8130081300"); test("-1000000000000", "4294967295", "-232"); test( "-1000000000000000000000000", "1", "-1000000000000000000000000", ); test( "-1000000000000000000000000", "3", "-333333333333333333333333", ); test( "-1000000000000000000000000", "123", "-8130081300813008130081", ); test( "-1000000000000000000000000", "4294967295", "-232830643708079", ); test( "-1000000000000000000000000", "1234567890987", "-810000006723", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", ); test( "-253640751230376270397812803167", "2669936877441", "-94998781946290113", ); test("-3768477692975601", "11447376614057827956", "0"); test("-3356605361737854", "3081095617839357", "-1"); test("-1098730198198174614195", "953382298040157850476", "-1"); test( "-69738658860594537152875081748", "69738658860594537152875081748", "-1", ); test( "-1000000000000000000000000", "1000000000000000000000000", "-1", ); test("-123", "1000000000000000000000000", "0"); test( "-91560770528345038830656113923422866087267706725647284216175385245968968833290334832530811\ 27923093090598913", "11669177832462215441614364516705357863717491965951", "-784637716923245892498679555408392159158150581185689944063", ); test("-1", "-1", "1"); test("-123", "-1", "123"); test("-123", "-123", "1"); test("-123", "-456", "0"); test("-456", "-123", "3"); test("-4294967295", "-1", "4294967295"); test("-4294967295", "-4294967295", "1"); test("-1000000000000", "-1", "1000000000000"); test("-1000000000000", "-3", "333333333333"); test("-1000000000000", "-123", "8130081300"); test("-1000000000000", "-4294967295", "232"); test( "-1000000000000000000000000", "-1", "1000000000000000000000000", ); test( "-1000000000000000000000000", "-3", "333333333333333333333333", ); test( "-1000000000000000000000000", "-123", "8130081300813008130081", ); test( "-1000000000000000000000000", "-4294967295", "232830643708079", ); test( "-1000000000000000000000000", "-1234567890987", "810000006723", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", ); test( "-253640751230376270397812803167", "-2669936877441", "94998781946290113", ); test("-3768477692975601", "-11447376614057827956", "0"); test("-3356605361737854", "-3081095617839357", "1"); test("-1098730198198174614195", "-953382298040157850476", "1"); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "1", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "1", ); test("-123", "-1000000000000000000000000", "0"); test( "-91560770528345038830656113923422866087267706725647284216175385245968968833290334832530811\ 27923093090598913", "-11669177832462215441614364516705357863717491965951", "784637716923245892498679555408392159158150581185689944063", ); } #[test] #[should_panic] fn div_assign_fail() { let mut x = Integer::from(10); x /= Integer::ZERO; } #[test] #[should_panic] fn div_assign_ref_fail() { let mut x = Integer::from(10); x /= &Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_fail() { Integer::from(10) / Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_val_ref_fail() { Integer::from(10) / &Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_ref_val_fail() { &Integer::from(10) / Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_ref_ref_fail() { &Integer::from(10) / &Integer::ZERO; } #[test] fn test_checked_div() { let test = |s, t, quotient| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let q = u.clone().checked_div(v.clone()); assert!(q.as_ref().is_none_or(Integer::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = u.clone().checked_div(&v); assert!(q.as_ref().is_none_or(Integer::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = (&u).checked_div(v.clone()); assert!(q.as_ref().is_none_or(Integer::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = (&u).checked_div(&v); assert!(q.as_ref().is_none_or(Integer::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = BigInt::from_str(s) .unwrap() .checked_div(&BigInt::from_str(t).unwrap()); assert_eq!(q.to_debug_string(), quotient); }; test("0", "1", "Some(0)"); test("0", "123", "Some(0)"); test("1", "1", "Some(1)"); test("123", "1", "Some(123)"); test("123", "123", "Some(1)"); test("123", "456", "Some(0)"); test("456", "123", "Some(3)"); test("4294967295", "1", "Some(4294967295)"); test("4294967295", "4294967295", "Some(1)"); test("1000000000000", "1", "Some(1000000000000)"); test("1000000000000", "3", "Some(333333333333)"); test("1000000000000", "123", "Some(8130081300)"); test("1000000000000", "4294967295", "Some(232)"); test("0", "-1", "Some(0)"); test("0", "-123", "Some(0)"); test("1", "-1", "Some(-1)"); test("123", "-1", "Some(-123)"); test("123", "-123", "Some(-1)"); test("123", "-456", "Some(0)"); test("456", "-123", "Some(-3)"); test("4294967295", "-1", "Some(-4294967295)"); test("4294967295", "-4294967295", "Some(-1)"); test("1000000000000", "-1", "Some(-1000000000000)"); test("1000000000000", "-3", "Some(-333333333333)"); test("1000000000000", "-123", "Some(-8130081300)"); test("1000000000000", "-4294967295", "Some(-232)"); test("-1", "1", "Some(-1)"); test("-123", "1", "Some(-123)"); test("-123", "123", "Some(-1)"); test("-123", "456", "Some(0)"); test("-456", "123", "Some(-3)"); test("-4294967295", "1", "Some(-4294967295)"); test("-4294967295", "4294967295", "Some(-1)"); test("-1000000000000", "1", "Some(-1000000000000)"); test("-1000000000000", "3", "Some(-333333333333)"); test("-1000000000000", "123", "Some(-8130081300)"); test("-1000000000000", "4294967295", "Some(-232)"); test("-1", "-1", "Some(1)"); test("-123", "-1", "Some(123)"); test("-123", "-123", "Some(1)"); test("-123", "-456", "Some(0)"); test("-456", "-123", "Some(3)"); test("-4294967295", "-1", "Some(4294967295)"); test("-4294967295", "-4294967295", "Some(1)"); test("-1000000000000", "-1", "Some(1000000000000)"); test("-1000000000000", "-3", "Some(333333333333)"); test("-1000000000000", "-123", "Some(8130081300)"); test("-1000000000000", "-4294967295", "Some(232)"); test("0", "0", "None"); test("1", "0", "None"); test("123", "0", "None"); test("1000000000000000000000000", "0", "None"); test("-1", "0", "None"); test("-123", "0", "None"); test("-1000000000000000000000000", "0", "None"); } fn div_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); mut_x /= &y; assert!(mut_x.is_valid()); let q = mut_x; let mut mut_x = x.clone(); mut_x /= y.clone(); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = &x / &y; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = &x / y.clone(); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone() / &y; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone() / y.clone(); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = (&x).div_rem(&y).0; assert_eq!(q_alt, q); let num_q = BigInt::from(&x) / &BigInt::from(&y); assert_eq!(Integer::from(&num_q), q); let rug_q = rug::Integer::from(&x) / rug::Integer::from(&y); assert_eq!(Integer::from(&rug_q), q); let remainder = &x - &q * &y; assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder > 0) == (x > 0)); assert_eq!(&q * &y + remainder, x); assert_eq!((-&x) / &y, -&q); assert_eq!(x / (-y), -q); } #[allow(clippy::eq_op)] #[test] fn div_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1().test_properties_with_config(&config, |(x, y)| { div_properties_helper(x, y); }); integer_pair_gen_var_2().test_properties_with_config(&config, |(x, y)| { div_properties_helper(x, y); }); integer_gen().test_properties(|x| { assert_eq!(&x / Integer::ONE, x); assert_eq!(&x / Integer::NEGATIVE_ONE, -x); }); integer_gen_var_8().test_properties(|x| { assert_eq!(Integer::ZERO / &x, 0); if x > Integer::ONE { assert_eq!(Integer::ONE / &x, 0); } assert_eq!(&x / Integer::ONE, x); assert_eq!(&x / Integer::NEGATIVE_ONE, -&x); assert_eq!(&x / &x, 1); assert_eq!(&x / -&x, -1); }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) / Integer::from(&y), x / y); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!(Integer::from(x) / Integer::from(y), x / y); }); } #[test] fn checked_div_properties() { integer_pair_gen().test_properties(|(x, y)| { let quotient_val_val = x.clone().checked_div(y.clone()); let quotient_val_ref = x.clone().checked_div(&y); let quotient_ref_val = (&x).checked_div(y.clone()); let quotient = (&x).checked_div(&y); assert!(quotient_val_val.as_ref().is_none_or(Integer::is_valid)); assert!(quotient_val_ref.as_ref().is_none_or(Integer::is_valid)); assert!(quotient_ref_val.as_ref().is_none_or(Integer::is_valid)); assert!(quotient.as_ref().is_none_or(Integer::is_valid)); assert_eq!(quotient_val_val, quotient); assert_eq!(quotient_val_ref, quotient); assert_eq!(quotient_ref_val, quotient); if y != 0u32 { assert_eq!(quotient, Some(&x / &y)); } assert_eq!( BigInt::from(&x) .checked_div(&BigInt::from(&y)) .map(|n| Integer::from(&n)), quotient ); }); integer_gen().test_properties(|ref x| { assert_eq!(x.checked_div(Integer::ZERO), None); assert_eq!(x.checked_div(Integer::ONE), Some(x.clone())); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(Integer::ZERO.checked_div(x), Some(Integer::ZERO)); if *x > Integer::ONE { assert_eq!(Integer::ONE.checked_div(x), Some(Integer::ZERO)); } assert_eq!(x.checked_div(x), Some(Integer::ONE)); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign, DivRound}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_pair_gen_var_3; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_8, integer_pair_gen_var_2, natural_pair_gen_var_6, }; use std::str::FromStr; #[test] fn test_div_exact() { let test = |s, t, quotient| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); x.div_exact_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); x.div_exact_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let q = u.clone().div_exact(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.clone().div_exact(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = (&u).div_exact(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = (&u).div_exact(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.div_round(v, Exact).0; assert_eq!(q.to_string(), quotient); let q = rug::Integer::from_str(s) .unwrap() .div_exact(&rug::Integer::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); }; test("0", "123", "0"); test("123", "1", "123"); test("123", "123", "1"); test("56088", "123", "456"); test("0", "1000000000000", "0"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "1000000000000", "1"); test("123000000000000", "1000000000000", "123"); test("123000000000000", "123", "1000000000000"); test("121932631112635269000000", "123456789000", "987654321000"); test("8589934590", "4294967295", "2"); test("18446744065119617025", "4294967295", "4294967295"); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", "577397114388109712462006371470162814529304445639807296878809567953200969820156259914159240\ 9106139481288193067515284601342023565222679498917484131095648263181800618990427694244342686\ 4412105186059052689237237088193855584354278755933606296018800151986520872701706693002473648\ 4330061421236425747083307907706860804054565348593527605104495080560663025897787060638154303\ 7631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", ); test("0", "-123", "0"); test("123", "-1", "-123"); test("123", "-123", "-1"); test("56088", "-123", "-456"); test("0", "-1000000000000", "0"); test("1000000000000", "-1", "-1000000000000"); test("1000000000000", "-1000000000000", "-1"); test("123000000000000", "-1000000000000", "-123"); test("123000000000000", "-123", "-1000000000000"); test("121932631112635269000000", "-123456789000", "-987654321000"); test("8589934590", "-4294967295", "-2"); test("18446744065119617025", "-4294967295", "-4294967295"); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099789", "-57739711438810971246200637147016281452930444563980729687880956795320096982015625991415924\ 0910613948128819306751528460134202356522267949891748413109564826318180061899042769424434268\ 6441210518605905268923723708819385558435427875593360629601880015198652087270170669300247364\ 8433006142123642574708330790770686080405456534859352760510449508056066302589778706063815430\ 37631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", ); test("-123", "1", "-123"); test("-123", "123", "-1"); test("-56088", "123", "-456"); test("-1000000000000", "1", "-1000000000000"); test("-1000000000000", "1000000000000", "-1"); test("-123000000000000", "1000000000000", "-123"); test("-123000000000000", "123", "-1000000000000"); test("-121932631112635269000000", "123456789000", "-987654321000"); test("-8589934590", "4294967295", "-2"); test("-18446744065119617025", "4294967295", "-4294967295"); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", "-57739711438810971246200637147016281452930444563980729687880956795320096982015625991415924\ 0910613948128819306751528460134202356522267949891748413109564826318180061899042769424434268\ 6441210518605905268923723708819385558435427875593360629601880015198652087270170669300247364\ 8433006142123642574708330790770686080405456534859352760510449508056066302589778706063815430\ 37631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", ); test("-123", "-1", "123"); test("-123", "-123", "1"); test("-56088", "-123", "456"); test("-1000000000000", "-1", "1000000000000"); test("-1000000000000", "-1000000000000", "1"); test("-123000000000000", "-1000000000000", "123"); test("-123000000000000", "-123", "1000000000000"); test("-121932631112635269000000", "-123456789000", "987654321000"); test("-8589934590", "-4294967295", "2"); test("-18446744065119617025", "-4294967295", "4294967295"); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099789", "577397114388109712462006371470162814529304445639807296878809567953200969820156259914159240\ 9106139481288193067515284601342023565222679498917484131095648263181800618990427694244342686\ 4412105186059052689237237088193855584354278755933606296018800151986520872701706693002473648\ 4330061421236425747083307907706860804054565348593527605104495080560663025897787060638154303\ 7631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", ); } #[test] #[should_panic] fn div_exact_assign_fail() { let mut n = Integer::from(10); n.div_exact_assign(Integer::ZERO); } #[test] #[should_panic] fn div_exact_assign_ref_fail() { let mut n = Integer::from(10); n.div_exact_assign(&Integer::ZERO); } #[test] #[should_panic] fn div_exact_fail() { Integer::from(10).div_exact(Integer::ZERO); } #[test] #[should_panic] fn div_exact_val_ref_fail() { Integer::from(10).div_exact(&Integer::ZERO); } #[test] #[should_panic] fn div_exact_ref_val_fail() { (&Integer::from(10)).div_exact(Integer::ZERO); } #[test] #[should_panic] fn div_exact_ref_ref_fail() { (&Integer::from(10)).div_exact(&Integer::ZERO); } #[test] fn div_exact_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_2().test_properties_with_config(&config, |(x, y)| { let mut mut_x = x.clone(); mut_x.div_exact_assign(&y); assert!(mut_x.is_valid()); let q = mut_x; let mut mut_x = x.clone(); mut_x.div_exact_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, q); let q_alt = (&x).div_exact(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = (&x).div_exact(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone().div_exact(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone().div_exact(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = (&x).div_round(&y, Exact).0; assert_eq!(q_alt, q); assert_eq!( Integer::from(&rug::Integer::from(&x).div_exact(&rug::Integer::from(&y))), q ); assert_eq!(&q * &y, x); assert_eq!((-&x).div_exact(&y), -&q); assert_eq!(x.div_exact(-y), -q); }); integer_gen().test_properties(|n| { let n = &n; assert_eq!(n.div_exact(Integer::ONE), *n); assert_eq!(n.div_exact(Integer::NEGATIVE_ONE), -n); }); integer_gen_var_8().test_properties(|n| { let n = &n; assert_eq!(Integer::ZERO.div_exact(n), 0); assert_eq!(n.div_exact(n), 1); }); natural_pair_gen_var_6().test_properties(|(x, y)| { assert_eq!( Integer::from(&x).div_exact(Integer::from(&y)), x.div_exact(y) ); }); signed_pair_gen_var_3::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).div_exact(Integer::from(y)), x.div_exact(y)); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivAssignMod, CeilingDivMod, CeilingDivNegMod, CeilingMod, DivAssignMod, DivAssignRem, DivMod, DivRem, DivRound, Mod, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_pair_gen_var_4; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_8, integer_pair_gen_var_1, integer_pair_gen_var_2, natural_pair_gen_var_5, }; use num::{BigInt, Integer as NumInteger}; use std::str::FromStr; #[test] fn test_div_mod() { let test = |s, t, quotient, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); let r = x.div_assign_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.div_assign_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = BigInt::from_str(s) .unwrap() .div_mod_floor(&BigInt::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = rug::Integer::from_str(s) .unwrap() .div_rem_floor(rug::Integer::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = ((&u).div_round(&v, Floor).0, u.mod_op(v)); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0", "0"); test("0", "123", "0", "0"); test("1", "1", "1", "0"); test("123", "1", "123", "0"); test("123", "123", "1", "0"); test("123", "456", "0", "123"); test("456", "123", "3", "87"); test("4294967295", "1", "4294967295", "0"); test("4294967295", "4294967295", "1", "0"); test("1000000000000", "1", "1000000000000", "0"); test("1000000000000", "3", "333333333333", "1"); test("1000000000000", "123", "8130081300", "100"); test("1000000000000", "4294967295", "232", "3567587560"); test( "1000000000000000000000000", "1", "1000000000000000000000000", "0", ); test( "1000000000000000000000000", "3", "333333333333333333333333", "1", ); test( "1000000000000000000000000", "123", "8130081300813008130081", "37", ); test( "1000000000000000000000000", "4294967295", "232830643708079", "3167723695", ); test( "1000000000000000000000000", "1234567890987", "810000006723", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290113", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "0", "3768477692975601", ); test( "3356605361737854", "3081095617839357", "1", "275509743898497", ); test( "1098730198198174614195", "953382298040157850476", "1", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test("123", "1000000000000000000000000", "0", "123"); test("0", "-1", "0", "0"); test("0", "-123", "0", "0"); test("1", "-1", "-1", "0"); test("123", "-1", "-123", "0"); test("123", "-123", "-1", "0"); test("123", "-456", "-1", "-333"); test("456", "-123", "-4", "-36"); test("4294967295", "-1", "-4294967295", "0"); test("4294967295", "-4294967295", "-1", "0"); test("1000000000000", "-1", "-1000000000000", "0"); test("1000000000000", "-3", "-333333333334", "-2"); test("1000000000000", "-123", "-8130081301", "-23"); test("1000000000000", "-4294967295", "-233", "-727379735"); test( "1000000000000000000000000", "-1", "-1000000000000000000000000", "0", ); test( "1000000000000000000000000", "-3", "-333333333333333333333334", "-2", ); test( "1000000000000000000000000", "-123", "-8130081300813008130082", "-86", ); test( "1000000000000000000000000", "-4294967295", "-232830643708080", "-1127243600", ); test( "1000000000000000000000000", "-1234567890987", "-810000006724", "-704498996588", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018655", "-454912836989613466895606299668358255", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253980", "-278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "-2669936877441", "-94998781946290114", "-1149635115107", ); test( "3768477692975601", "-11447376614057827956", "-1", "-11443608136364852355", ); test( "3356605361737854", "-3081095617839357", "-2", "-2805585873940860", ); test( "1098730198198174614195", "-953382298040157850476", "-2", "-808034397882141086757", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "-1", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "-1", "0", ); test("0", "-1000000000000000000000000", "0", "0"); test( "123", "-1000000000000000000000000", "-1", "-999999999999999999999877", ); test("-1", "1", "-1", "0"); test("-123", "1", "-123", "0"); test("-123", "123", "-1", "0"); test("-123", "456", "-1", "333"); test("-456", "123", "-4", "36"); test("-4294967295", "-1", "4294967295", "0"); test("-4294967295", "4294967295", "-1", "0"); test("-1000000000000", "1", "-1000000000000", "0"); test("-1000000000000", "3", "-333333333334", "2"); test("-1000000000000", "123", "-8130081301", "23"); test("-1000000000000", "4294967295", "-233", "727379735"); test( "-1000000000000000000000000", "1", "-1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "3", "-333333333333333333333334", "2", ); test( "-1000000000000000000000000", "123", "-8130081300813008130082", "86", ); test( "-1000000000000000000000000", "4294967295", "-232830643708080", "1127243600", ); test( "-1000000000000000000000000", "1234567890987", "-810000006724", "704498996588", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018655", "454912836989613466895606299668358255", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253980", "278232688309211835744673381771890580480", ); test( "-253640751230376270397812803167", "2669936877441", "-94998781946290114", "1149635115107", ); test( "-3768477692975601", "11447376614057827956", "-1", "11443608136364852355", ); test( "-3356605361737854", "3081095617839357", "-2", "2805585873940860", ); test( "-1098730198198174614195", "953382298040157850476", "-2", "808034397882141086757", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "-1", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "-1", "0", ); test( "-123", "1000000000000000000000000", "-1", "999999999999999999999877", ); test("-1", "-1", "1", "0"); test("-123", "-1", "123", "0"); test("-123", "-123", "1", "0"); test("-123", "-456", "0", "-123"); test("-456", "-123", "3", "-87"); test("-4294967295", "-1", "4294967295", "0"); test("-4294967295", "-4294967295", "1", "0"); test("-1000000000000", "-1", "1000000000000", "0"); test("-1000000000000", "-3", "333333333333", "-1"); test("-1000000000000", "-123", "8130081300", "-100"); test("-1000000000000", "-4294967295", "232", "-3567587560"); test( "-1000000000000000000000000", "-1", "1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "-3", "333333333333333333333333", "-1", ); test( "-1000000000000000000000000", "-123", "8130081300813008130081", "-37", ); test( "-1000000000000000000000000", "-4294967295", "232830643708079", "-3167723695", ); test( "-1000000000000000000000000", "-1234567890987", "810000006723", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "-2669936877441", "94998781946290113", "-1520301762334", ); test( "-3768477692975601", "-11447376614057827956", "0", "-3768477692975601", ); test( "-3356605361737854", "-3081095617839357", "1", "-275509743898497", ); test( "-1098730198198174614195", "-953382298040157850476", "1", "-145347900158016763719", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "1", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "1", "0", ); test("-123", "-1000000000000000000000000", "0", "-123"); } #[test] #[should_panic] fn div_assign_mod_fail() { Integer::from(10).div_assign_mod(Integer::ZERO); } #[test] #[should_panic] fn div_assign_mod_ref_fail() { Integer::from(10).div_assign_mod(&Integer::ZERO); } #[test] #[should_panic] fn div_mod_fail() { Integer::from(10).div_mod(Integer::ZERO); } #[test] #[should_panic] fn div_mod_val_ref_fail() { Integer::from(10).div_mod(&Integer::ZERO); } #[test] #[should_panic] fn div_mod_ref_val_fail() { (&Integer::from(10)).div_mod(Integer::ZERO); } #[test] #[should_panic] fn div_mod_ref_ref_fail() { (&Integer::from(10)).div_mod(&Integer::ZERO); } #[test] fn test_div_rem() { let test = |s, t, quotient, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); let r = x.div_assign_rem(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.div_assign_rem(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().div_rem(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().div_rem(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_rem(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_rem(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = BigInt::from_str(s) .unwrap() .div_rem(&BigInt::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = rug::Integer::from_str(s) .unwrap() .div_rem(rug::Integer::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = (u.clone() / v.clone(), u % v); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0", "0"); test("0", "123", "0", "0"); test("1", "1", "1", "0"); test("123", "1", "123", "0"); test("123", "123", "1", "0"); test("123", "456", "0", "123"); test("456", "123", "3", "87"); test("4294967295", "1", "4294967295", "0"); test("4294967295", "4294967295", "1", "0"); test("1000000000000", "1", "1000000000000", "0"); test("1000000000000", "3", "333333333333", "1"); test("1000000000000", "123", "8130081300", "100"); test("1000000000000", "4294967295", "232", "3567587560"); test( "1000000000000000000000000", "1", "1000000000000000000000000", "0", ); test( "1000000000000000000000000", "3", "333333333333333333333333", "1", ); test( "1000000000000000000000000", "123", "8130081300813008130081", "37", ); test( "1000000000000000000000000", "4294967295", "232830643708079", "3167723695", ); test( "1000000000000000000000000", "1234567890987", "810000006723", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290113", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "0", "3768477692975601", ); test( "3356605361737854", "3081095617839357", "1", "275509743898497", ); test( "1098730198198174614195", "953382298040157850476", "1", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test("123", "1000000000000000000000000", "0", "123"); test("0", "-1", "0", "0"); test("0", "-123", "0", "0"); test("1", "-1", "-1", "0"); test("123", "-1", "-123", "0"); test("123", "-123", "-1", "0"); test("123", "-456", "0", "123"); test("456", "-123", "-3", "87"); test("4294967295", "-1", "-4294967295", "0"); test("4294967295", "-4294967295", "-1", "0"); test("1000000000000", "-1", "-1000000000000", "0"); test("1000000000000", "-3", "-333333333333", "1"); test("1000000000000", "-123", "-8130081300", "100"); test("1000000000000", "-4294967295", "-232", "3567587560"); test( "1000000000000000000000000", "-1", "-1000000000000000000000000", "0", ); test( "1000000000000000000000000", "-3", "-333333333333333333333333", "1", ); test( "1000000000000000000000000", "-123", "-8130081300813008130081", "37", ); test( "1000000000000000000000000", "-4294967295", "-232830643708079", "3167723695", ); test( "1000000000000000000000000", "-1234567890987", "-810000006723", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "-2669936877441", "-94998781946290113", "1520301762334", ); test( "3768477692975601", "-11447376614057827956", "0", "3768477692975601", ); test( "3356605361737854", "-3081095617839357", "-1", "275509743898497", ); test( "1098730198198174614195", "-953382298040157850476", "-1", "145347900158016763719", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "-1", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "-1", "0", ); test("0", "-1000000000000000000000000", "0", "0"); test("123", "-1000000000000000000000000", "0", "123"); test("-1", "1", "-1", "0"); test("-123", "1", "-123", "0"); test("-123", "123", "-1", "0"); test("-123", "456", "0", "-123"); test("-456", "123", "-3", "-87"); test("-4294967295", "1", "-4294967295", "0"); test("-4294967295", "4294967295", "-1", "0"); test("-1000000000000", "1", "-1000000000000", "0"); test("-1000000000000", "3", "-333333333333", "-1"); test("-1000000000000", "123", "-8130081300", "-100"); test("-1000000000000", "4294967295", "-232", "-3567587560"); test( "-1000000000000000000000000", "1", "-1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "3", "-333333333333333333333333", "-1", ); test( "-1000000000000000000000000", "123", "-8130081300813008130081", "-37", ); test( "-1000000000000000000000000", "4294967295", "-232830643708079", "-3167723695", ); test( "-1000000000000000000000000", "1234567890987", "-810000006723", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "2669936877441", "-94998781946290113", "-1520301762334", ); test( "-3768477692975601", "11447376614057827956", "0", "-3768477692975601", ); test( "-3356605361737854", "3081095617839357", "-1", "-275509743898497", ); test( "-1098730198198174614195", "953382298040157850476", "-1", "-145347900158016763719", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "-1", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "-1", "0", ); test("-123", "1000000000000000000000000", "0", "-123"); test("-1", "-1", "1", "0"); test("-123", "-1", "123", "0"); test("-123", "-123", "1", "0"); test("-123", "-456", "0", "-123"); test("-456", "-123", "3", "-87"); test("-4294967295", "-1", "4294967295", "0"); test("-4294967295", "-4294967295", "1", "0"); test("-1000000000000", "-1", "1000000000000", "0"); test("-1000000000000", "-3", "333333333333", "-1"); test("-1000000000000", "-123", "8130081300", "-100"); test("-1000000000000", "-4294967295", "232", "-3567587560"); test( "-1000000000000000000000000", "-1", "1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "-3", "333333333333333333333333", "-1", ); test( "-1000000000000000000000000", "-123", "8130081300813008130081", "-37", ); test( "-1000000000000000000000000", "-4294967295", "232830643708079", "-3167723695", ); test( "-1000000000000000000000000", "-1234567890987", "810000006723", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "-2669936877441", "94998781946290113", "-1520301762334", ); test( "-3768477692975601", "-11447376614057827956", "0", "-3768477692975601", ); test( "-3356605361737854", "-3081095617839357", "1", "-275509743898497", ); test( "-1098730198198174614195", "-953382298040157850476", "1", "-145347900158016763719", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "1", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "1", "0", ); test("-123", "-1000000000000000000000000", "0", "-123"); } #[test] #[should_panic] fn div_assign_rem_fail() { Integer::from(10).div_assign_rem(Integer::ZERO); } #[test] #[should_panic] fn div_assign_rem_ref_fail() { Integer::from(10).div_assign_rem(&Integer::ZERO); } #[test] #[should_panic] fn div_rem_fail() { Integer::from(10).div_rem(Integer::ZERO); } #[test] #[should_panic] fn div_rem_val_ref_fail() { Integer::from(10).div_rem(&Integer::ZERO); } #[test] #[should_panic] fn div_rem_ref_val_fail() { (&Integer::from(10)).div_rem(Integer::ZERO); } #[test] #[should_panic] fn div_rem_ref_ref_fail() { (&Integer::from(10)).div_rem(&Integer::ZERO); } #[test] fn test_ceiling_div_mod() { let test = |s, t, quotient, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); let r = x.ceiling_div_assign_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.ceiling_div_assign_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().ceiling_div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().ceiling_div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).ceiling_div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).ceiling_div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = rug::Integer::from_str(s) .unwrap() .div_rem_ceil(rug::Integer::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = (u.clone().div_round(v.clone(), Ceiling).0, u.ceiling_mod(v)); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0", "0"); test("0", "123", "0", "0"); test("1", "1", "1", "0"); test("123", "1", "123", "0"); test("123", "123", "1", "0"); test("123", "456", "1", "-333"); test("456", "123", "4", "-36"); test("4294967295", "1", "4294967295", "0"); test("4294967295", "4294967295", "1", "0"); test("1000000000000", "1", "1000000000000", "0"); test("1000000000000", "3", "333333333334", "-2"); test("1000000000000", "123", "8130081301", "-23"); test("1000000000000", "4294967295", "233", "-727379735"); test( "1000000000000000000000000", "1", "1000000000000000000000000", "0", ); test( "1000000000000000000000000", "3", "333333333333333333333334", "-2", ); test( "1000000000000000000000000", "123", "8130081300813008130082", "-86", ); test( "1000000000000000000000000", "4294967295", "232830643708080", "-1127243600", ); test( "1000000000000000000000000", "1234567890987", "810000006724", "-704498996588", ); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018655", "-454912836989613466895606299668358255", ); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253980", "-278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290114", "-1149635115107", ); test( "3768477692975601", "11447376614057827956", "1", "-11443608136364852355", ); test( "3356605361737854", "3081095617839357", "2", "-2805585873940860", ); test( "1098730198198174614195", "953382298040157850476", "2", "-808034397882141086757", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test( "123", "1000000000000000000000000", "1", "-999999999999999999999877", ); test("0", "-1", "0", "0"); test("0", "-123", "0", "0"); test("1", "-1", "-1", "0"); test("123", "-1", "-123", "0"); test("123", "-123", "-1", "0"); test("123", "-456", "0", "123"); test("456", "-123", "-3", "87"); test("4294967295", "-1", "-4294967295", "0"); test("4294967295", "-4294967295", "-1", "0"); test("1000000000000", "-1", "-1000000000000", "0"); test("1000000000000", "-3", "-333333333333", "1"); test("1000000000000", "-123", "-8130081300", "100"); test("1000000000000", "-4294967295", "-232", "3567587560"); test( "1000000000000000000000000", "-1", "-1000000000000000000000000", "0", ); test( "1000000000000000000000000", "-3", "-333333333333333333333333", "1", ); test( "1000000000000000000000000", "-123", "-8130081300813008130081", "37", ); test( "1000000000000000000000000", "-4294967295", "-232830643708079", "3167723695", ); test( "1000000000000000000000000", "-1234567890987", "-810000006723", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "-2669936877441", "-94998781946290113", "1520301762334", ); test( "3768477692975601", "-11447376614057827956", "0", "3768477692975601", ); test( "3356605361737854", "-3081095617839357", "-1", "275509743898497", ); test( "1098730198198174614195", "-953382298040157850476", "-1", "145347900158016763719", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "-1", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "-1", "0", ); test("0", "-1000000000000000000000000", "0", "0"); test("123", "-1000000000000000000000000", "0", "123"); test("-1", "1", "-1", "0"); test("-123", "1", "-123", "0"); test("-123", "123", "-1", "0"); test("-123", "456", "0", "-123"); test("-456", "123", "-3", "-87"); test("-4294967295", "1", "-4294967295", "0"); test("-4294967295", "4294967295", "-1", "0"); test("-1000000000000", "1", "-1000000000000", "0"); test("-1000000000000", "3", "-333333333333", "-1"); test("-1000000000000", "123", "-8130081300", "-100"); test("-1000000000000", "4294967295", "-232", "-3567587560"); test( "-1000000000000000000000000", "1", "-1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "3", "-333333333333333333333333", "-1", ); test( "-1000000000000000000000000", "123", "-8130081300813008130081", "-37", ); test( "-1000000000000000000000000", "4294967295", "-232830643708079", "-3167723695", ); test( "-1000000000000000000000000", "1234567890987", "-810000006723", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-810000006723000055638900467181273922269593923137018654", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-3164062526261718967339454949926851258865601262253979", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "2669936877441", "-94998781946290113", "-1520301762334", ); test( "-3768477692975601", "11447376614057827956", "0", "-3768477692975601", ); test( "-3356605361737854", "3081095617839357", "-1", "-275509743898497", ); test( "-1098730198198174614195", "953382298040157850476", "-1", "-145347900158016763719", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "-1", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "-1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test("-123", "1000000000000000000000000", "0", "-123"); test("-1", "-1", "1", "0"); test("-123", "-1", "123", "0"); test("-123", "-123", "1", "0"); test("-123", "-456", "1", "333"); test("-456", "-123", "4", "36"); test("-4294967295", "-1", "4294967295", "0"); test("-4294967295", "-4294967295", "1", "0"); test("-1000000000000", "-1", "1000000000000", "0"); test("-1000000000000", "-3", "333333333334", "2"); test("-1000000000000", "-123", "8130081301", "23"); test("-1000000000000", "-4294967295", "233", "727379735"); test( "-1000000000000000000000000", "-1", "1000000000000000000000000", "0", ); test( "-1000000000000000000000000", "-3", "333333333333333333333334", "2", ); test( "-1000000000000000000000000", "-123", "8130081300813008130082", "86", ); test( "-1000000000000000000000000", "-4294967295", "232830643708080", "1127243600", ); test( "-1000000000000000000000000", "-1234567890987", "810000006724", "704498996588", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018655", "454912836989613466895606299668358255", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253980", "278232688309211835744673381771890580480", ); test( "-253640751230376270397812803167", "-2669936877441", "94998781946290114", "1149635115107", ); test( "-3768477692975601", "-11447376614057827956", "1", "11443608136364852355", ); test( "-3356605361737854", "-3081095617839357", "2", "2805585873940860", ); test( "-1098730198198174614195", "-953382298040157850476", "2", "808034397882141086757", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "1", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "1", "0", ); test("0", "-1000000000000000000000000", "0", "0"); test( "-123", "-1000000000000000000000000", "1", "999999999999999999999877", ); } #[test] #[should_panic] fn ceiling_div_assign_mod_fail() { Integer::from(10).ceiling_div_assign_mod(Integer::ZERO); } #[test] #[should_panic] fn ceiling_div_assign_mod_ref_fail() { Integer::from(10).ceiling_div_assign_mod(&Integer::ZERO); } #[test] #[should_panic] fn ceiling_div_mod_fail() { Integer::from(10).ceiling_div_mod(Integer::ZERO); } #[test] #[should_panic] fn ceiling_div_mod_val_ref_fail() { Integer::from(10).ceiling_div_mod(&Integer::ZERO); } #[test] #[should_panic] fn ceiling_div_mod_ref_val_fail() { (&Integer::from(10)).ceiling_div_mod(Integer::ZERO); } #[test] #[should_panic] fn ceiling_div_mod_ref_ref_fail() { (&Integer::from(10)).ceiling_div_mod(&Integer::ZERO); } fn div_mod_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); let r = mut_x.div_assign_mod(&y); assert!(mut_x.is_valid()); assert!(r.is_valid()); let q = mut_x; let mut mut_x = x.clone(); let r_alt = mut_x.div_assign_mod(y.clone()); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = ((&x).div_round(&y, Floor).0, (&x).mod_op(&y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let (num_q, num_r) = BigInt::from(&x).div_mod_floor(&BigInt::from(&y)); assert_eq!(Integer::from(&num_q), q); assert_eq!(Integer::from(&num_r), r); let (rug_q, rug_r) = rug::Integer::from(&x).div_rem_floor(rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_q), q); assert_eq!(Integer::from(&rug_r), r); assert!(r.lt_abs(&y)); assert!(r == 0 || (r > 0) == (y > 0)); assert_eq!(q * &y + r, x); let (neg_q, neg_r) = (-&x).div_mod(&y); assert_eq!((&x).ceiling_div_mod(&y), (-neg_q, -neg_r)); let (neg_q, r) = (&x).div_mod(-&y); assert_eq!(x.ceiling_div_mod(y), (-neg_q, r)); } #[test] fn div_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| div_mod_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| div_mod_properties_helper(x, y)); integer_gen().test_properties(|x| { let (q, r) = (&x).div_mod(Integer::ONE); assert_eq!(q, x); assert_eq!(r, 0); let (q, r) = (&x).div_mod(Integer::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x.div_mod(Integer::ONE), (x.clone(), Integer::ZERO)); assert_eq!(x.div_mod(Integer::NEGATIVE_ONE), (-x, Integer::ZERO)); assert_eq!(x.div_mod(x), (Integer::ONE, Integer::ZERO)); assert_eq!(x.div_mod(-x), (Integer::NEGATIVE_ONE, Integer::ZERO)); assert_eq!(Integer::ZERO.div_mod(x), (Integer::ZERO, Integer::ZERO)); if *x > 1 { assert_eq!(Integer::ONE.div_mod(x), (Integer::ZERO, Integer::ONE)); assert_eq!( Integer::NEGATIVE_ONE.div_mod(x), (Integer::NEGATIVE_ONE, x - Integer::ONE) ); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { let (q, r) = (&x).div_mod(&y); assert_eq!( Integer::from(x).div_mod(Integer::from(y)), (Integer::from(q), Integer::from(r)) ); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { let (q, r) = x.div_mod(y); assert_eq!( Integer::from(x).div_mod(Integer::from(y)), (Integer::from(q), Integer::from(r)) ); }); } fn div_rem_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); let r = mut_x.div_assign_rem(&y); assert!(mut_x.is_valid()); assert!(r.is_valid()); let q = mut_x; let mut q_alt = x.clone(); let r_alt = q_alt.div_assign_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_rem(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_rem(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x / &y, &x % &y); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let (num_q, num_r) = BigInt::from(&x).div_rem(&BigInt::from(&y)); assert_eq!(Integer::from(&num_q), q); assert_eq!(Integer::from(&num_r), r); let (rug_q, rug_r) = rug::Integer::from(&x).div_rem(rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_q), q); assert_eq!(Integer::from(&rug_r), r); assert!(r.lt_abs(&y)); assert!(r == 0 || (r > 0) == (x > 0)); assert_eq!(&q * &y + &r, x); assert_eq!((-&x).div_rem(&y), (-&q, -&r)); assert_eq!(x.div_rem(-y), (-q, r)); } #[test] fn div_rem_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| div_rem_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| div_rem_properties_helper(x, y)); integer_gen().test_properties(|x| { let (q, r) = (&x).div_rem(Integer::ONE); assert_eq!(q, x); assert_eq!(r, 0); let (q, r) = (&x).div_rem(Integer::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x.div_rem(Integer::ONE), (x.clone(), Integer::ZERO)); assert_eq!(x.div_rem(Integer::NEGATIVE_ONE), (-x, Integer::ZERO)); assert_eq!(x.div_rem(x), (Integer::ONE, Integer::ZERO)); assert_eq!(x.div_rem(-x), (Integer::NEGATIVE_ONE, Integer::ZERO)); assert_eq!(Integer::ZERO.div_rem(x), (Integer::ZERO, Integer::ZERO)); if *x > 1 { assert_eq!(Integer::ONE.div_rem(x), (Integer::ZERO, Integer::ONE)); assert_eq!( Integer::NEGATIVE_ONE.div_rem(x), (Integer::ZERO, Integer::NEGATIVE_ONE) ); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { let (q, r) = (&x).div_rem(&y); assert_eq!( Integer::from(x).div_rem(Integer::from(y)), (Integer::from(q), Integer::from(r)) ); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { let (q, r) = x.div_rem(y); assert_eq!( Integer::from(x).div_rem(Integer::from(y)), (Integer::from(q), Integer::from(r)) ); }); } fn ceiling_div_mod_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); let r = mut_x.ceiling_div_assign_mod(&y); assert!(mut_x.is_valid()); assert!(r.is_valid()); let q = mut_x; let mut mut_x = x.clone(); let r_alt = mut_x.ceiling_div_assign_mod(y.clone()); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).ceiling_div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).ceiling_div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().ceiling_div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().ceiling_div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = ((&x).div_round(&y, Ceiling).0, (&x).ceiling_mod(&y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let (rug_q, rug_r) = rug::Integer::from(&x).div_rem_ceil(rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_q), q); assert_eq!(Integer::from(&rug_r), r); assert!(r.lt_abs(&y)); assert!(r == 0 || (r > 0) != (y > 0)); assert_eq!(q * &y + r, x); let (neg_q, neg_r) = (-&x).ceiling_div_mod(&y); assert_eq!((&x).div_mod(&y), (-neg_q, -neg_r)); let (neg_q, r) = (&x).ceiling_div_mod(-&y); assert_eq!(x.div_mod(y), (-neg_q, r)); } #[test] fn ceiling_div_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| ceiling_div_mod_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| ceiling_div_mod_properties_helper(x, y)); integer_gen().test_properties(|x| { let (q, r) = (&x).ceiling_div_mod(Integer::ONE); assert_eq!(q, x); assert_eq!(r, 0); let (q, r) = (&x).ceiling_div_mod(Integer::NEGATIVE_ONE); assert_eq!(q, -x); assert_eq!(r, 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x.ceiling_div_mod(Integer::ONE), (x.clone(), Integer::ZERO)); assert_eq!( x.ceiling_div_mod(Integer::NEGATIVE_ONE), (-x, Integer::ZERO) ); assert_eq!(x.ceiling_div_mod(x), (Integer::ONE, Integer::ZERO)); assert_eq!( x.ceiling_div_mod(-x), (Integer::NEGATIVE_ONE, Integer::ZERO) ); assert_eq!( Integer::ZERO.ceiling_div_mod(x), (Integer::ZERO, Integer::ZERO) ); }); natural_pair_gen_var_5().test_properties(|(x, y)| { let (q, r) = (&x).ceiling_div_neg_mod(&y); assert_eq!( Integer::from(x).ceiling_div_mod(Integer::from(y)), (Integer::from(q), -r) ); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { let (q, r) = x.ceiling_div_mod(y); assert_eq!( Integer::from(x).ceiling_div_mod(Integer::from(y)), (Integer::from(q), Integer::from(r)) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivRound, DivRoundAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_signed_rounding_mode_triple_gen_var_1; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_integer_rounding_mode_triple_gen_var_1, integer_pair_gen_var_1, integer_pair_gen_var_3, integer_rounding_mode_pair_gen, integer_rounding_mode_pair_gen_var_2, natural_natural_rounding_mode_triple_gen_var_1, }; use num::{BigInt, Integer as NumInteger}; use rug::ops::DivRounding; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_div_round() { let test = |s, t, rm, quotient, o| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); assert_eq!(x.div_round_assign(v.clone(), rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let mut x = u.clone(); assert_eq!(x.div_round_assign(&v, rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let (q, o_alt) = u.clone().div_round(v.clone(), rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = u.clone().div_round(&v, rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = (&u).div_round(v.clone(), rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = (&u).div_round(&v, rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); match rm { Down => { assert_eq!( rug::Integer::from_str(s) .unwrap() .div_trunc(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } Floor => { assert_eq!( BigInt::from_str(s) .unwrap() .div_floor(&BigInt::from_str(t).unwrap()) .to_string(), quotient ); assert_eq!( rug::Integer::from_str(s) .unwrap() .div_floor(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } Ceiling => { assert_eq!( rug::Integer::from_str(s) .unwrap() .div_ceil(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } _ => {} } }; test("0", "1", Down, "0", Equal); test("0", "1", Floor, "0", Equal); test("0", "1", Up, "0", Equal); test("0", "1", Ceiling, "0", Equal); test("0", "1", Nearest, "0", Equal); test("0", "1", Exact, "0", Equal); test("0", "123", Down, "0", Equal); test("0", "123", Floor, "0", Equal); test("0", "123", Up, "0", Equal); test("0", "123", Ceiling, "0", Equal); test("0", "123", Nearest, "0", Equal); test("0", "123", Exact, "0", Equal); test("1", "1", Down, "1", Equal); test("1", "1", Floor, "1", Equal); test("1", "1", Up, "1", Equal); test("1", "1", Ceiling, "1", Equal); test("1", "1", Nearest, "1", Equal); test("1", "1", Exact, "1", Equal); test("123", "1", Down, "123", Equal); test("123", "1", Floor, "123", Equal); test("123", "1", Up, "123", Equal); test("123", "1", Ceiling, "123", Equal); test("123", "1", Nearest, "123", Equal); test("123", "1", Exact, "123", Equal); test("123", "2", Down, "61", Less); test("123", "2", Floor, "61", Less); test("123", "2", Up, "62", Greater); test("123", "2", Ceiling, "62", Greater); test("123", "2", Nearest, "62", Greater); test("125", "2", Down, "62", Less); test("125", "2", Floor, "62", Less); test("125", "2", Up, "63", Greater); test("125", "2", Ceiling, "63", Greater); test("125", "2", Nearest, "62", Less); test("123", "123", Down, "1", Equal); test("123", "123", Floor, "1", Equal); test("123", "123", Up, "1", Equal); test("123", "123", Ceiling, "1", Equal); test("123", "123", Nearest, "1", Equal); test("123", "123", Exact, "1", Equal); test("123", "456", Down, "0", Less); test("123", "456", Floor, "0", Less); test("123", "456", Up, "1", Greater); test("123", "456", Ceiling, "1", Greater); test("123", "456", Nearest, "0", Less); test("1000000000000", "1", Down, "1000000000000", Equal); test("1000000000000", "1", Floor, "1000000000000", Equal); test("1000000000000", "1", Up, "1000000000000", Equal); test("1000000000000", "1", Ceiling, "1000000000000", Equal); test("1000000000000", "1", Nearest, "1000000000000", Equal); test("1000000000000", "1", Exact, "1000000000000", Equal); test("1000000000000", "3", Down, "333333333333", Less); test("1000000000000", "3", Floor, "333333333333", Less); test("1000000000000", "3", Up, "333333333334", Greater); test("1000000000000", "3", Ceiling, "333333333334", Greater); test("1000000000000", "3", Nearest, "333333333333", Less); test("999999999999", "2", Down, "499999999999", Less); test("999999999999", "2", Floor, "499999999999", Less); test("999999999999", "2", Up, "500000000000", Greater); test("999999999999", "2", Ceiling, "500000000000", Greater); test("999999999999", "2", Nearest, "500000000000", Greater); test("1000000000001", "2", Down, "500000000000", Less); test("1000000000001", "2", Floor, "500000000000", Less); test("1000000000001", "2", Up, "500000000001", Greater); test("1000000000001", "2", Ceiling, "500000000001", Greater); test("1000000000001", "2", Nearest, "500000000000", Less); test( "1000000000000000000000000", "4294967295", Down, "232830643708079", Less, ); test( "1000000000000000000000000", "4294967295", Floor, "232830643708079", Less, ); test( "1000000000000000000000000", "4294967295", Up, "232830643708080", Greater, ); test( "1000000000000000000000000", "4294967295", Ceiling, "232830643708080", Greater, ); test( "1000000000000000000000000", "4294967295", Nearest, "232830643708080", Greater, ); test( "1000000000000000000000000", "1000000000000", Down, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Floor, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Up, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Ceiling, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Nearest, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Exact, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000001", Down, "999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Floor, "999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Up, "1000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Ceiling, "1000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Nearest, "999999999999", Less, ); test( "2999999999999999999999999", "2000000000000000000000000", Nearest, "1", Less, ); test( "3000000000000000000000000", "2000000000000000000000000", Nearest, "2", Greater, ); test( "3000000000000000000000001", "2000000000000000000000000", Nearest, "2", Greater, ); test("0", "-1", Down, "0", Equal); test("0", "-1", Floor, "0", Equal); test("0", "-1", Up, "0", Equal); test("0", "-1", Ceiling, "0", Equal); test("0", "-1", Nearest, "0", Equal); test("0", "-1", Exact, "0", Equal); test("0", "-123", Down, "0", Equal); test("0", "-123", Floor, "0", Equal); test("0", "-123", Up, "0", Equal); test("0", "-123", Ceiling, "0", Equal); test("0", "-123", Nearest, "0", Equal); test("0", "-123", Exact, "0", Equal); test("1", "-1", Down, "-1", Equal); test("1", "-1", Floor, "-1", Equal); test("1", "-1", Up, "-1", Equal); test("1", "-1", Ceiling, "-1", Equal); test("1", "-1", Nearest, "-1", Equal); test("1", "-1", Exact, "-1", Equal); test("123", "-1", Down, "-123", Equal); test("123", "-1", Floor, "-123", Equal); test("123", "-1", Up, "-123", Equal); test("123", "-1", Ceiling, "-123", Equal); test("123", "-1", Nearest, "-123", Equal); test("123", "-1", Exact, "-123", Equal); test("123", "-2", Down, "-61", Greater); test("123", "-2", Floor, "-62", Less); test("123", "-2", Up, "-62", Less); test("123", "-2", Ceiling, "-61", Greater); test("123", "-2", Nearest, "-62", Less); test("125", "-2", Down, "-62", Greater); test("125", "-2", Floor, "-63", Less); test("125", "-2", Up, "-63", Less); test("125", "-2", Ceiling, "-62", Greater); test("125", "-2", Nearest, "-62", Greater); test("123", "-123", Down, "-1", Equal); test("123", "-123", Floor, "-1", Equal); test("123", "-123", Up, "-1", Equal); test("123", "-123", Ceiling, "-1", Equal); test("123", "-123", Nearest, "-1", Equal); test("123", "-123", Exact, "-1", Equal); test("123", "-456", Down, "0", Greater); test("123", "-456", Floor, "-1", Less); test("123", "-456", Up, "-1", Less); test("123", "-456", Ceiling, "0", Greater); test("123", "-456", Nearest, "0", Greater); test("1000000000000", "-1", Down, "-1000000000000", Equal); test("1000000000000", "-1", Floor, "-1000000000000", Equal); test("1000000000000", "-1", Up, "-1000000000000", Equal); test("1000000000000", "-1", Ceiling, "-1000000000000", Equal); test("1000000000000", "-1", Nearest, "-1000000000000", Equal); test("1000000000000", "-1", Exact, "-1000000000000", Equal); test("1000000000000", "-3", Down, "-333333333333", Greater); test("1000000000000", "-3", Floor, "-333333333334", Less); test("1000000000000", "-3", Up, "-333333333334", Less); test("1000000000000", "-3", Ceiling, "-333333333333", Greater); test("1000000000000", "-3", Nearest, "-333333333333", Greater); test("999999999999", "-2", Down, "-499999999999", Greater); test("999999999999", "-2", Floor, "-500000000000", Less); test("999999999999", "-2", Up, "-500000000000", Less); test("999999999999", "-2", Ceiling, "-499999999999", Greater); test("999999999999", "-2", Nearest, "-500000000000", Less); test("1000000000001", "-2", Down, "-500000000000", Greater); test("1000000000001", "-2", Floor, "-500000000001", Less); test("1000000000001", "-2", Up, "-500000000001", Less); test("1000000000001", "-2", Ceiling, "-500000000000", Greater); test("1000000000001", "-2", Nearest, "-500000000000", Greater); test( "1000000000000000000000000", "-4294967295", Down, "-232830643708079", Greater, ); test( "1000000000000000000000000", "-4294967295", Floor, "-232830643708080", Less, ); test( "1000000000000000000000000", "-4294967295", Up, "-232830643708080", Less, ); test( "1000000000000000000000000", "-4294967295", Ceiling, "-232830643708079", Greater, ); test( "1000000000000000000000000", "-4294967295", Nearest, "-232830643708080", Less, ); test( "1000000000000000000000000", "-1000000000000", Down, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Floor, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Up, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Ceiling, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Nearest, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Exact, "-1000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000001", Down, "-999999999999", Greater, ); test( "1000000000000000000000000", "-1000000000001", Floor, "-1000000000000", Less, ); test( "1000000000000000000000000", "-1000000000001", Up, "-1000000000000", Less, ); test( "1000000000000000000000000", "-1000000000001", Ceiling, "-999999999999", Greater, ); test( "1000000000000000000000000", "-1000000000001", Nearest, "-999999999999", Greater, ); test( "2999999999999999999999999", "-2000000000000000000000000", Nearest, "-1", Greater, ); test( "3000000000000000000000000", "-2000000000000000000000000", Nearest, "-2", Less, ); test( "3000000000000000000000001", "-2000000000000000000000000", Nearest, "-2", Less, ); test("-1", "1", Down, "-1", Equal); test("-1", "1", Floor, "-1", Equal); test("-1", "1", Up, "-1", Equal); test("-1", "1", Ceiling, "-1", Equal); test("-1", "1", Nearest, "-1", Equal); test("-1", "1", Exact, "-1", Equal); test("-123", "1", Down, "-123", Equal); test("-123", "1", Floor, "-123", Equal); test("-123", "1", Up, "-123", Equal); test("-123", "1", Ceiling, "-123", Equal); test("-123", "1", Nearest, "-123", Equal); test("-123", "1", Exact, "-123", Equal); test("-123", "2", Down, "-61", Greater); test("-123", "2", Floor, "-62", Less); test("-123", "2", Up, "-62", Less); test("-123", "2", Ceiling, "-61", Greater); test("-123", "2", Nearest, "-62", Less); test("-125", "2", Down, "-62", Greater); test("-125", "2", Floor, "-63", Less); test("-125", "2", Up, "-63", Less); test("-125", "2", Ceiling, "-62", Greater); test("-125", "2", Nearest, "-62", Greater); test("-123", "123", Down, "-1", Equal); test("-123", "123", Floor, "-1", Equal); test("-123", "123", Up, "-1", Equal); test("-123", "123", Ceiling, "-1", Equal); test("-123", "123", Nearest, "-1", Equal); test("-123", "123", Exact, "-1", Equal); test("-123", "456", Down, "0", Greater); test("-123", "456", Floor, "-1", Less); test("-123", "456", Up, "-1", Less); test("-123", "456", Ceiling, "0", Greater); test("-123", "456", Nearest, "0", Greater); test("-1000000000000", "1", Down, "-1000000000000", Equal); test("-1000000000000", "1", Floor, "-1000000000000", Equal); test("-1000000000000", "1", Up, "-1000000000000", Equal); test("-1000000000000", "1", Ceiling, "-1000000000000", Equal); test("-1000000000000", "1", Nearest, "-1000000000000", Equal); test("-1000000000000", "1", Exact, "-1000000000000", Equal); test("-1000000000000", "3", Down, "-333333333333", Greater); test("-1000000000000", "3", Floor, "-333333333334", Less); test("-1000000000000", "3", Up, "-333333333334", Less); test("-1000000000000", "3", Ceiling, "-333333333333", Greater); test("-1000000000000", "3", Nearest, "-333333333333", Greater); test("-999999999999", "2", Down, "-499999999999", Greater); test("-999999999999", "2", Floor, "-500000000000", Less); test("-999999999999", "2", Up, "-500000000000", Less); test("-999999999999", "2", Ceiling, "-499999999999", Greater); test("-999999999999", "2", Nearest, "-500000000000", Less); test("-1000000000001", "2", Down, "-500000000000", Greater); test("-1000000000001", "2", Floor, "-500000000001", Less); test("-1000000000001", "2", Up, "-500000000001", Less); test("-1000000000001", "2", Ceiling, "-500000000000", Greater); test("-1000000000001", "2", Nearest, "-500000000000", Greater); test( "-1000000000000000000000000", "4294967295", Down, "-232830643708079", Greater, ); test( "-1000000000000000000000000", "4294967295", Floor, "-232830643708080", Less, ); test( "-1000000000000000000000000", "4294967295", Up, "-232830643708080", Less, ); test( "-1000000000000000000000000", "4294967295", Ceiling, "-232830643708079", Greater, ); test( "-1000000000000000000000000", "4294967295", Nearest, "-232830643708080", Less, ); test( "-1000000000000000000000000", "1000000000000", Down, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Floor, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Up, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Ceiling, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Nearest, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Exact, "-1000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000001", Down, "-999999999999", Greater, ); test( "-1000000000000000000000000", "1000000000001", Floor, "-1000000000000", Less, ); test( "-1000000000000000000000000", "1000000000001", Up, "-1000000000000", Less, ); test( "-1000000000000000000000000", "1000000000001", Ceiling, "-999999999999", Greater, ); test( "-1000000000000000000000000", "1000000000001", Nearest, "-999999999999", Greater, ); test( "-2999999999999999999999999", "2000000000000000000000000", Nearest, "-1", Greater, ); test( "-3000000000000000000000000", "2000000000000000000000000", Nearest, "-2", Less, ); test( "-3000000000000000000000001", "2000000000000000000000000", Nearest, "-2", Less, ); test("-1", "-1", Down, "1", Equal); test("-1", "-1", Floor, "1", Equal); test("-1", "-1", Up, "1", Equal); test("-1", "-1", Ceiling, "1", Equal); test("-1", "-1", Nearest, "1", Equal); test("-1", "-1", Exact, "1", Equal); test("-123", "-1", Down, "123", Equal); test("-123", "-1", Floor, "123", Equal); test("-123", "-1", Up, "123", Equal); test("-123", "-1", Ceiling, "123", Equal); test("-123", "-1", Nearest, "123", Equal); test("-123", "-1", Exact, "123", Equal); test("-123", "-2", Down, "61", Less); test("-123", "-2", Floor, "61", Less); test("-123", "-2", Up, "62", Greater); test("-123", "-2", Ceiling, "62", Greater); test("-123", "-2", Nearest, "62", Greater); test("-125", "-2", Down, "62", Less); test("-125", "-2", Floor, "62", Less); test("-125", "-2", Up, "63", Greater); test("-125", "-2", Ceiling, "63", Greater); test("-125", "-2", Nearest, "62", Less); test("-123", "-123", Down, "1", Equal); test("-123", "-123", Floor, "1", Equal); test("-123", "-123", Up, "1", Equal); test("-123", "-123", Ceiling, "1", Equal); test("-123", "-123", Nearest, "1", Equal); test("-123", "-123", Exact, "1", Equal); test("-123", "-456", Down, "0", Less); test("-123", "-456", Floor, "0", Less); test("-123", "-456", Up, "1", Greater); test("-123", "-456", Ceiling, "1", Greater); test("-123", "-456", Nearest, "0", Less); test("-1000000000000", "-1", Down, "1000000000000", Equal); test("-1000000000000", "-1", Floor, "1000000000000", Equal); test("-1000000000000", "-1", Up, "1000000000000", Equal); test("-1000000000000", "-1", Ceiling, "1000000000000", Equal); test("-1000000000000", "-1", Nearest, "1000000000000", Equal); test("-1000000000000", "-1", Exact, "1000000000000", Equal); test("-1000000000000", "-3", Down, "333333333333", Less); test("-1000000000000", "-3", Floor, "333333333333", Less); test("-1000000000000", "-3", Up, "333333333334", Greater); test("-1000000000000", "-3", Ceiling, "333333333334", Greater); test("-1000000000000", "-3", Nearest, "333333333333", Less); test("-999999999999", "-2", Down, "499999999999", Less); test("-999999999999", "-2", Floor, "499999999999", Less); test("-999999999999", "-2", Up, "500000000000", Greater); test("-999999999999", "-2", Ceiling, "500000000000", Greater); test("-999999999999", "-2", Nearest, "500000000000", Greater); test("-1000000000001", "-2", Down, "500000000000", Less); test("-1000000000001", "-2", Floor, "500000000000", Less); test("-1000000000001", "-2", Up, "500000000001", Greater); test("-1000000000001", "-2", Ceiling, "500000000001", Greater); test("-1000000000001", "-2", Nearest, "500000000000", Less); test( "-1000000000000000000000000", "-4294967295", Down, "232830643708079", Less, ); test( "-1000000000000000000000000", "-4294967295", Floor, "232830643708079", Less, ); test( "-1000000000000000000000000", "-4294967295", Up, "232830643708080", Greater, ); test( "-1000000000000000000000000", "-4294967295", Ceiling, "232830643708080", Greater, ); test( "-1000000000000000000000000", "-4294967295", Nearest, "232830643708080", Greater, ); test( "-1000000000000000000000000", "-1000000000000", Down, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Floor, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Up, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Ceiling, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Nearest, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Exact, "1000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000001", Down, "999999999999", Less, ); test( "-1000000000000000000000000", "-1000000000001", Floor, "999999999999", Less, ); test( "-1000000000000000000000000", "-1000000000001", Up, "1000000000000", Greater, ); test( "-1000000000000000000000000", "-1000000000001", Ceiling, "1000000000000", Greater, ); test( "-1000000000000000000000000", "-1000000000001", Nearest, "999999999999", Less, ); test( "-2999999999999999999999999", "-2000000000000000000000000", Nearest, "1", Less, ); test( "-3000000000000000000000000", "-2000000000000000000000000", Nearest, "2", Greater, ); test( "-3000000000000000000000001", "-2000000000000000000000000", Nearest, "2", Greater, ); } #[test] #[should_panic] fn div_round_assign_fail_1() { let mut n = Integer::from(10); n.div_round_assign(Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_assign_fail_2() { let mut n = Integer::from(10); n.div_round_assign(Integer::from(3), Exact); } #[test] #[should_panic] fn div_round_assign_ref_fail_1() { let mut n = Integer::from(10); n.div_round_assign(&Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_assign_ref_fail_2() { let mut n = Integer::from(10); n.div_round_assign(&Integer::from(3), Exact); } #[test] #[should_panic] fn div_round_fail_1() { Integer::from(10).div_round(Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_fail_2() { Integer::from(10).div_round(Integer::from(3), Exact); } #[test] #[should_panic] fn div_round_val_ref_fail_1() { Integer::from(10).div_round(&Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_val_ref_fail_2() { Integer::from(10).div_round(&Integer::from(3), Exact); } #[test] #[should_panic] fn div_round_ref_val_fail_1() { (&Integer::from(10)).div_round(Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_ref_val_fail_2() { (&Integer::from(10)).div_round(Integer::from(3), Exact); } #[test] #[should_panic] fn div_round_ref_ref_fail_1() { (&Integer::from(10)).div_round(&Integer::ZERO, Floor); } #[test] #[should_panic] fn div_round_ref_ref_fail_2() { (&Integer::from(10)).div_round(&Integer::from(3), Exact); } #[test] fn div_round_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_integer_rounding_mode_triple_gen_var_1().test_properties_with_config( &config, |(x, y, rm)| { let mut mut_n = x.clone(); let o = mut_n.div_round_assign(&y, rm); assert!(mut_n.is_valid()); let q = mut_n; let mut mut_n = x.clone(); assert_eq!(mut_n.div_round_assign(y.clone(), rm), o); assert!(mut_n.is_valid()); assert_eq!(mut_n, q); let (q_alt, o_alt) = (&x).div_round(&y, rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = (&x).div_round(y.clone(), rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = x.clone().div_round(&y, rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = x.clone().div_round(y.clone(), rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); assert!(q.le_abs(&x)); let (q_alt, o_alt) = (-&x).div_round(&y, -rm); assert_eq!(-q_alt, q); assert_eq!(o_alt, o.reverse()); let (q_alt, o_alt) = (&x).div_round(-&y, -rm); assert_eq!(-q_alt, q); assert_eq!(o_alt, o.reverse()); assert_eq!((q * &y).cmp(&x), if y >= 0 { o } else { o.reverse() }); match ((x >= 0) == (y >= 0), rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }, ); integer_pair_gen_var_1().test_properties(|(x, y)| { let left_multiplied = &x * &y; let xo = (x.clone(), Equal); assert_eq!((&left_multiplied).div_round(&y, Down), xo); assert_eq!((&left_multiplied).div_round(&y, Up), xo); assert_eq!((&left_multiplied).div_round(&y, Floor), xo); assert_eq!((&left_multiplied).div_round(&y, Ceiling), xo); assert_eq!((&left_multiplied).div_round(&y, Nearest), xo); assert_eq!((&left_multiplied).div_round(&y, Exact), xo); assert_eq!( Integer::from(&rug::Integer::from(&x).div_trunc(rug::Integer::from(&y))), (&x).div_round(&y, Down).0 ); assert_eq!( Integer::from(&BigInt::from(&x).div_floor(&BigInt::from(&y))), (&x).div_round(&y, Floor).0 ); assert_eq!( Integer::from(&rug::Integer::from(&x).div_floor(rug::Integer::from(&y))), (&x).div_round(&y, Floor).0 ); assert_eq!( Integer::from(&rug::Integer::from(&x).div_ceil(rug::Integer::from(&y))), x.div_round(y, Ceiling).0 ); }); integer_pair_gen_var_3().test_properties(|(x, y)| { let down = (&x).div_round(&y, Down); let up = if (x >= 0) == (y >= 0) { (&down.0 + Integer::ONE, Greater) } else { (&down.0 - Integer::ONE, Less) }; let floor = (&x).div_round(&y, Floor); let ceiling = (&floor.0 + Integer::ONE, Greater); assert_eq!((&x).div_round(&y, Up), up); assert_eq!((&x).div_round(&y, Ceiling), ceiling); let nearest = x.div_round(y, Nearest); assert!(nearest == down || nearest == up); }); integer_rounding_mode_pair_gen().test_properties(|(x, rm)| { assert_eq!((&x).div_round(Integer::ONE, rm), (x.clone(), Equal)); assert_eq!((&x).div_round(Integer::NEGATIVE_ONE, rm), (-x, Equal)); }); integer_rounding_mode_pair_gen_var_2().test_properties(|(ref x, rm)| { assert_eq!(Integer::ZERO.div_round(x, rm), (Integer::ZERO, Equal)); assert_eq!(x.div_round(x, rm), (Integer::ONE, Equal)); assert_eq!(x.div_round(-x, rm), (Integer::NEGATIVE_ONE, Equal)); assert_eq!((-x).div_round(x, rm), (Integer::NEGATIVE_ONE, Equal)); }); natural_natural_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { let (q, o) = (&x).div_round(&y, rm); assert_eq!( Integer::from(x).div_round(Integer::from(y), rm), (Integer::from(q), o) ); }); signed_signed_rounding_mode_triple_gen_var_1::().test_properties(|(x, y, rm)| { let (q, o) = x.div_round(y, rm); assert_eq!( Integer::from(x).div_round(Integer::from(y), rm), (Integer::from(q), o) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_8, integer_pair_gen, integer_pair_gen_var_2, integer_pair_gen_var_3, natural_pair_gen, }; use malachite_nz::test_util::integer::arithmetic::divisible_by::num_divisible_by; use num::BigInt; use std::str::FromStr; #[test] fn test_divisible_by() { let test = |s, t, divisible| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.clone().divisible_by(v.clone()), divisible); assert_eq!(u.clone().divisible_by(&v), divisible); assert_eq!((&u).divisible_by(v.clone()), divisible); assert_eq!((&u).divisible_by(&v), divisible); assert_eq!(u == 0 || v != 0 && u % v == 0, divisible); assert_eq!( num_divisible_by(&BigInt::from_str(s).unwrap(), &BigInt::from_str(t).unwrap()), divisible ); assert_eq!( rug::Integer::from_str(s) .unwrap() .is_divisible(&rug::Integer::from_str(t).unwrap()), divisible ); }; test("0", "0", true); test("1", "0", false); test("1000000000000", "0", false); test("0", "1", true); test("0", "123", true); test("1", "1", true); test("123", "1", true); test("123", "123", true); test("123", "456", false); test("456", "123", false); test("369", "123", true); test("4294967295", "1", true); test("4294967295", "4294967295", true); test("1000000000000", "1", true); test("1000000000000", "3", false); test("1000000000002", "3", true); test("1000000000000", "123", false); test("1000000000000", "4294967295", false); test("1000000000000000000000000", "1", true); test("1000000000000000000000000", "3", false); test("1000000000000000000000002", "3", true); test("1000000000000000000000000", "123", false); test("1000000000000000000000000", "4294967295", false); test("1000000000000000000000000", "1000000000000", true); test("1000000000000000000000000", "1000000000001", false); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", true, ); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099788", false, ); test("0", "-1", true); test("0", "-123", true); test("1", "-1", true); test("123", "-1", true); test("123", "-123", true); test("123", "-456", false); test("456", "-123", false); test("369", "-123", true); test("4294967295", "-1", true); test("4294967295", "-4294967295", true); test("1000000000000", "-1", true); test("1000000000000", "-3", false); test("1000000000002", "-3", true); test("1000000000000", "-123", false); test("1000000000000", "-4294967295", false); test("1000000000000000000000000", "-1", true); test("1000000000000000000000000", "-3", false); test("1000000000000000000000002", "-3", true); test("1000000000000000000000000", "-123", false); test("1000000000000000000000000", "-4294967295", false); test("1000000000000000000000000", "-1000000000000", true); test("1000000000000000000000000", "-1000000000001", false); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099789", true, ); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099788", false, ); test("-1", "0", false); test("-1000000000000", "0", false); test("-1", "1", true); test("-123", "1", true); test("-123", "123", true); test("-123", "456", false); test("-456", "123", false); test("-369", "123", true); test("-4294967295", "1", true); test("-4294967295", "4294967295", true); test("-1000000000000", "1", true); test("-1000000000000", "3", false); test("-1000000000002", "3", true); test("-1000000000000", "123", false); test("-1000000000000", "4294967295", false); test("-1000000000000000000000000", "1", true); test("-1000000000000000000000000", "3", false); test("-1000000000000000000000002", "3", true); test("-1000000000000000000000000", "123", false); test("-1000000000000000000000000", "4294967295", false); test("-1000000000000000000000000", "1000000000000", true); test("-1000000000000000000000000", "1000000000001", false); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", true, ); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099788", false, ); test("-1", "-1", true); test("-123", "-1", true); test("-123", "-123", true); test("-123", "-456", false); test("-456", "-123", false); test("-369", "-123", true); test("-4294967295", "-1", true); test("-4294967295", "-4294967295", true); test("-1000000000000", "-1", true); test("-1000000000000", "-3", false); test("-1000000000002", "-3", true); test("-1000000000000", "-123", false); test("-1000000000000", "-4294967295", false); test("-1000000000000000000000000", "-1", true); test("-1000000000000000000000000", "-3", false); test("-1000000000000000000000002", "-3", true); test("-1000000000000000000000000", "-123", false); test("-1000000000000000000000000", "-4294967295", false); test("-1000000000000000000000000", "-1000000000000", true); test("-1000000000000000000000000", "-1000000000001", false); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099789", true, ); test( "-85167390638832534155095794307111191155780003684512955609936093881325960865026707945673997\ 8115695995227540918591177133606739237724591829175426900075118671527941456047488257049908299\ 0491312297889746397086083361625118924209880487666436844160872789514123895317920452925678027\ 7597810520028602516194421271297705634312768260197519167321745960256763360219826256892100808\ 1944855667091257528737125119080085592631176887680837517744653024363521274834692165422458986\ 1062517042681252582968986240751551041944533547263190561023591522603284832387406712887238529\ 1373073927546722736469219522612950133888704971058693114130935719034106453236601312328010609\ 8646815162879794545517964986689039448179963983254097809173637948296452222906447816773031749\ 0819410850670448075039505406703250253039214769072591939993068314351077164686993152712334065\ 0054764979233156891346041593972211130527058870153140449004003430210210108369170655037628865\ 5266738289939079249411893137923743207131654331337979221879437117652968461408510941832896381\ 7060143276727041922971949080953977653567193804161853619694137064794533640190145092141382316\ 3405999170707783410783087675682188065142974818640102076011385949818563813372616528648174101\ 4907990633728659922633550842446636931629444200404044052858958223971704265454174534805015725\ 23448224036804997350851153108395928780441635856", "-14750227965563656560025035845269405189398018669695853517400995652385572010732263815974936\ 8080821747949474430587689097259577148476973385751452961609619939409285830226599826048341601\ 6576390452204426400593828107256814088351371325554864304425008611048361721593563653380924810\ 2692659078914207980563844549476017755177663674783001449501248974399040735523228684207141892\ 2992135840957348090162448797731978275542273083446867343807680553295282140602439900681439016\ 6694982753079697108601126786460781490631333452551810222191964304044026732368834188903586437\ 6137724664457908815322266967227141431524031843984372003980899388641087496934099664501079567\ 0213351871698766886593652982743738804219008430900536956471739072625759490261936518009750957\ 6624018903777061930820690641412868685634995095262397002303944032370164345741148566677635444\ 8186307133288106956593939073729500658176632828099788", false, ); } #[test] fn divisible_by_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen().test_properties_with_config(&config, |(x, y)| { let divisible = (&x).divisible_by(&y); assert_eq!((&x).divisible_by(y.clone()), divisible); assert_eq!(x.clone().divisible_by(&y), divisible); assert_eq!(x.clone().divisible_by(y.clone()), divisible); assert_eq!(x == 0 || y != 0 && &x % &y == 0, divisible); assert_eq!((-&x).divisible_by(&y), divisible); assert_eq!((&x).divisible_by(-&y), divisible); assert_eq!( num_divisible_by(&BigInt::from(&x), &BigInt::from(&y)), divisible ); assert_eq!( rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y)), divisible ); }); integer_pair_gen_var_2().test_properties(|(x, y)| { assert!((&x).divisible_by(&y)); assert!(x == 0 || y != 0 && &x % &y == 0); assert!(num_divisible_by(&BigInt::from(&x), &BigInt::from(&y))); assert!(rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y))); }); integer_pair_gen_var_3().test_properties(|(x, y)| { assert!(!(&x).divisible_by(&y)); assert!(x != 0 && (y == 0 || &x % &y != 0)); assert!(!num_divisible_by(&BigInt::from(&x), &BigInt::from(&y))); assert!(!rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y))); }); integer_gen().test_properties(|n| { assert!((&n).divisible_by(Integer::ONE)); assert!(n.divisible_by(Integer::NEGATIVE_ONE)); }); integer_gen_var_8().test_properties(|n| { assert!(!(&n).divisible_by(Integer::ZERO)); assert!(Integer::ZERO.divisible_by(&n)); if n > 1 { assert!(!Integer::ONE.divisible_by(&n)); } assert!((&n).divisible_by(&n)); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!( Integer::from(&x).divisible_by(Integer::from(&y)), x.divisible_by(y) ); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(x).divisible_by(Integer::from(y)), x.divisible_by(y) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_unsigned_pair_gen_var_1, unsigned_gen}; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_4, integer_unsigned_pair_gen_var_5, natural_unsigned_pair_gen_var_4, }; use std::str::FromStr; #[test] fn test_divisible_by_power_of_2() { let test = |n, pow, out| { assert_eq!( Integer::from_str(n).unwrap().divisible_by_power_of_2(pow), out ); assert_eq!( rug::Integer::from_str(n) .unwrap() .is_divisible_2pow(u32::exact_from(pow)), out ); }; test("0", 0, true); test("0", 10, true); test("0", 100, true); test("123", 0, true); test("123", 1, false); test("-123", 0, true); test("-123", 1, false); test("1000000000000", 0, true); test("1000000000000", 12, true); test("1000000000000", 13, false); test("-1000000000000", 0, true); test("-1000000000000", 12, true); test("-1000000000000", 13, false); test("4294967295", 0, true); test("4294967295", 1, false); test("-4294967295", 0, true); test("-4294967295", 1, false); test("4294967296", 0, true); test("4294967296", 32, true); test("4294967296", 33, false); test("-4294967296", 0, true); test("-4294967296", 32, true); test("-4294967296", 33, false); test("18446744073709551615", 0, true); test("18446744073709551615", 1, false); test("-18446744073709551615", 0, true); test("-18446744073709551615", 1, false); test("18446744073709551616", 0, true); test("18446744073709551616", 64, true); test("18446744073709551616", 65, false); test("-18446744073709551616", 0, true); test("-18446744073709551616", 64, true); test("-18446744073709551616", 65, false); } #[test] fn divisible_by_power_of_2_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(x, pow)| { let divisible = x.divisible_by_power_of_2(pow); assert_eq!( rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow)), divisible ); if x != 0 { assert_eq!(x.trailing_zeros().unwrap() >= pow, divisible); } assert_eq!((-&x).divisible_by_power_of_2(pow), divisible); assert!((&x << pow).divisible_by_power_of_2(pow)); assert_eq!(&x >> pow << pow == x, divisible); }); integer_unsigned_pair_gen_var_4().test_properties(|(x, pow)| { assert!(x.divisible_by_power_of_2(pow)); assert!(rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow))); if x != 0 { assert!(x.trailing_zeros().unwrap() >= pow); } assert!((-&x).divisible_by_power_of_2(pow)); assert_eq!(&x >> pow << pow, x); }); integer_unsigned_pair_gen_var_5().test_properties(|(x, pow)| { assert!(!x.divisible_by_power_of_2(pow)); assert!(!rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow))); if x != 0 { assert!(x.trailing_zeros().unwrap() < pow); } assert!(!(-&x).divisible_by_power_of_2(pow)); assert_ne!(&x >> pow << pow, x); }); integer_gen().test_properties(|x| { assert!(x.divisible_by_power_of_2(0)); }); unsigned_gen().test_properties(|pow| { assert!(Integer::ZERO.divisible_by_power_of_2(pow)); }); natural_unsigned_pair_gen_var_4().test_properties(|(x, pow)| { assert_eq!( x.divisible_by_power_of_2(pow), Integer::from(x).divisible_by_power_of_2(pow) ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(x, pow)| { assert_eq!( x.divisible_by_power_of_2(pow), Integer::from(x).divisible_by_power_of_2(pow) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, EqMod, Mod, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_triple_gen, unsigned_vec_triple_gen_var_36, unsigned_vec_unsigned_unsigned_triple_gen_var_5, unsigned_vec_unsigned_unsigned_triple_gen_var_7, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, }; use malachite_nz::integer::Integer; use malachite_nz::integer::arithmetic::eq_mod::{ limbs_eq_neg_limb_mod_limb, limbs_pos_eq_neg_limb_mod, limbs_pos_eq_neg_limb_mod_ref, limbs_pos_eq_neg_mod, limbs_pos_eq_neg_mod_limb, limbs_pos_eq_neg_mod_ref, limbs_pos_limb_eq_neg_limb_mod, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_integer_natural_triple_gen, integer_integer_natural_triple_gen_var_1, integer_integer_natural_triple_gen_var_2, integer_natural_pair_gen, integer_pair_gen, natural_triple_gen, unsigned_vec_triple_gen_var_37, unsigned_vec_triple_gen_var_38, unsigned_vec_unsigned_unsigned_triple_gen_var_6, unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2, unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_neg_limb_mod_limb() { let test = |xs: &[Limb], y: Limb, m: Limb, equal: bool| { assert_eq!(limbs_eq_neg_limb_mod_limb(xs, y, m), equal); }; test(&[6, 7], 4, 2, true); test(&[7, 7], 4, 2, false); test(&[6, 7], 3, 2, false); test(&[7, 7], 3, 2, true); test(&[2, 2], 6, 13, true); test(&[100, 101, 102], 1232, 10, true); test(&[100, 101, 102], 1233, 10, false); test(&[123, 456], 153, 789, true); test(&[123, 456], 1000, 789, false); test(&[u32::MAX, u32::MAX], 101, 2, true); test(&[u32::MAX, u32::MAX], 100, 2, false); test(&[u32::MAX, u32::MAX], 111, 3, true); test(&[u32::MAX, u32::MAX], 110, 3, false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_neg_limb_mod_limb_fail() { limbs_eq_neg_limb_mod_limb(&[10], 10, 15); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_limb_eq_neg_limb_mod() { let test = |x: Limb, y: Limb, ms: &[Limb], equal: bool| { assert_eq!(limbs_pos_limb_eq_neg_limb_mod(x, y, ms), equal); let x = Integer::from(x); let y = -Natural::from(y); let m = Natural::from_limbs_asc(ms); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }; test(1, 1, &[1, 1], false); test(1, 1, &[2, 1], false); test(1, 1, &[1, 0, 1], false); test(u32::MAX, u32::MAX, &[u32::MAX - 1, 1], true); test(u32::MAX, u32::MAX, &[u32::MAX - 1, 1, 2], false); test(u32::MAX, u32::MAX, &[u32::MAX - 1, 2], false); test(0xabcddbca, 0x641fefdf, &[0xfedcba9, 1], true); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_eq_neg_limb_mod() { let test = |xs: &[Limb], y: Limb, ms: &[Limb], equal: bool| { let mut mut_ms = ms.to_vec(); assert_eq!(limbs_pos_eq_neg_limb_mod(xs, y, &mut mut_ms), equal); assert_eq!(limbs_pos_eq_neg_limb_mod_ref(xs, y, ms), equal); let x = Integer::from(Natural::from_limbs_asc(xs)); let y = -Natural::from(y); let m = Natural::from_limbs_asc(ms); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }; // - !xs[0].wrapping_neg().eq_mod_power_of_2(y, u64::from(twos)) test(&[1, 2], 2, &[2, 1], false); // - xs[0].wrapping_neg().eq_mod_power_of_2(y, u64::from(twos)) // - m_len == 2 && m_0 != 0 // - m_1 < 1 << twos // - x_len < BMOD_1_TO_MOD_1_THRESHOLD test(&[2, 2], 2, &[2, 1], true); // - m_1 >= 1 << twos test(&[0, 1], 1, &[1, 1], true); // - m_len > 2 || m_0 == 0 test(&[0, 1], 1, &[1, 0, 1], false); // - x_len >= BMOD_1_TO_MOD_1_THRESHOLD // - y < m_0 test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], 2, &[2, 1], false, ); // - limbs_pos_eq_neg_limb_mod_helper, y >= m_0 test( &[ 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 4294967294, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294836223, 65535, 0, 0, 8192, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294959103, 4095, ], u32::MAX, &[4294959104, 4095], true, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_fail_1() { limbs_pos_eq_neg_limb_mod(&[1], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_fail_2() { limbs_pos_eq_neg_limb_mod(&[1, 1], 1, &mut [1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_fail_3() { limbs_pos_eq_neg_limb_mod(&[1, 0], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_fail_4() { limbs_pos_eq_neg_limb_mod(&[1, 1], 0, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_fail_5() { limbs_pos_eq_neg_limb_mod(&[1, 1], 1, &mut [1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_ref_fail_1() { limbs_pos_eq_neg_limb_mod_ref(&[1], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_ref_fail_2() { limbs_pos_eq_neg_limb_mod_ref(&[1, 1], 1, &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_ref_fail_3() { limbs_pos_eq_neg_limb_mod_ref(&[1, 0], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_ref_fail_4() { limbs_pos_eq_neg_limb_mod_ref(&[1, 1], 0, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_limb_mod_ref_fail_5() { limbs_pos_eq_neg_limb_mod_ref(&[1, 1], 1, &[1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_eq_neg_mod_limb() { let test = |xs: &[Limb], ys: &[Limb], m: Limb, equal: bool| { assert_eq!(limbs_pos_eq_neg_mod_limb(xs, ys, m), equal); let x = Integer::from(Natural::from_limbs_asc(xs)); let y = -Natural::from_limbs_asc(ys); let m = Natural::from(m); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }; // - xs[0].wrapping_neg().eq_mod_power_of_2(ys[0], u64::from(m.trailing_zeros())) in // limbs_pos_eq_mod_neg_limb_greater test(&[0, 1], &[0, 1], 1, true); test(&[0, 1], &[0, 1], 2, true); test(&[0, 1], &[6, 1], 2, true); // - !xs[0].wrapping_neg().eq_mod_power_of_2(ys[0], u64::from(m.trailing_zeros())) in // limbs_pos_eq_mod_neg_limb_greater test(&[0, 1], &[7, 1], 2, false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_limb_fail_1() { limbs_pos_eq_neg_mod_limb(&[1], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_limb_fail_2() { limbs_pos_eq_neg_mod_limb(&[1, 1], &[4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_limb_fail_3() { limbs_pos_eq_neg_mod_limb(&[1, 0], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_limb_fail_4() { limbs_pos_eq_neg_mod_limb(&[1, 1], &[3, 0], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_limb_fail_5() { limbs_pos_eq_neg_mod_limb(&[1, 1], &[3, 4], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_eq_neg_mod() { let test = |xs: &[Limb], ys: &[Limb], ms: &[Limb], equal: bool| { let mut mut_ms = ms.to_vec(); assert_eq!(limbs_pos_eq_neg_mod(xs, ys, &mut mut_ms), equal); assert_eq!(limbs_pos_eq_neg_mod_ref(xs, ys, ms), equal); let x = Integer::from(Natural::from_limbs_asc(xs)); let y = -Natural::from_limbs_asc(ys); let m = Natural::from_limbs_asc(ms); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }; // - !xs[0].wrapping_neg().eq_mod_power_of_2(ys[0], u64::from(ms[0].trailing_zeros())) in // limbs_pos_eq_neg_mod_greater test(&[1, 2], &[3, 4], &[0, 1], false); test(&[0, 0, 1], &[0, 1], &[1, 1], true); // - xs[0].wrapping_neg().eq_mod_power_of_2(ys[0], u64::from(ms[0].trailing_zeros())) in // limbs_pos_eq_neg_mod_greater test( &[ 936369948, 322455623, 3632895046, 978349680, 17000327, 2833388987, 2719643819, 4166701038, ], &[ 2342728269, 2320695303, 2977562202, 4108534583, 1505907268, 3739165110, 101046064, 1901445664, ], &[602975281, 3649288173, 1789153785, 3864060421, 3382875975, 610141130], false, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_1() { limbs_pos_eq_neg_mod(&[1], &[1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_2() { limbs_pos_eq_neg_mod(&[1, 1, 1], &[1], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_3() { limbs_pos_eq_neg_mod(&[1, 1, 1], &[1, 0, 3], &mut [7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_4() { limbs_pos_eq_neg_mod(&[1, 1, 0], &[1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_5() { limbs_pos_eq_neg_mod(&[1, 1, 1], &[1, 0, 0], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_fail_6() { limbs_pos_eq_neg_mod(&[1, 1, 1], &[1, 0, 3], &mut [7, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_1() { limbs_pos_eq_neg_mod_ref(&[1], &[1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_2() { limbs_pos_eq_neg_mod_ref(&[1, 1, 1], &[1], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_3() { limbs_pos_eq_neg_mod_ref(&[1, 1, 1], &[1, 0, 3], &[7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_4() { limbs_pos_eq_neg_mod_ref(&[1, 1, 0], &[1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_5() { limbs_pos_eq_neg_mod_ref(&[1, 1, 1], &[1, 0, 0], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_eq_neg_mod_ref_fail_6() { limbs_pos_eq_neg_mod_ref(&[1, 1, 1], &[1, 0, 3], &[7, 0]); } #[test] fn test_eq_mod() { let test = |r, s, t, out| { let u = Integer::from_str(r).unwrap(); let v = Integer::from_str(s).unwrap(); let w = Natural::from_str(t).unwrap(); assert_eq!(u.clone().eq_mod(v.clone(), w.clone()), out); assert_eq!(u.clone().eq_mod(v.clone(), &w), out); assert_eq!(u.clone().eq_mod(&v, w.clone()), out); assert_eq!(u.clone().eq_mod(&v, &w), out); assert_eq!((&u).eq_mod(v.clone(), w.clone()), out); assert_eq!((&u).eq_mod(v.clone(), &w), out); assert_eq!((&u).eq_mod(&v, w.clone()), out); assert_eq!((&u).eq_mod(&v, &w), out); assert_eq!(v.eq_mod(u, w), out); assert_eq!( rug::Integer::from_str(r).unwrap().is_congruent( &rug::Integer::from_str(s).unwrap(), &rug::Integer::from_str(t).unwrap() ), out ); }; test("0", "0", "0", true); test("0", "1", "0", false); test("57", "57", "0", true); test("57", "58", "0", false); test("1000000000000", "57", "0", false); test("0", "256", "256", true); test("0", "256", "512", false); test("13", "23", "10", true); test("13", "24", "10", false); test("13", "21", "1", true); test("13", "21", "2", true); test("13", "21", "4", true); test("13", "21", "8", true); test("13", "21", "16", false); test("13", "21", "3", false); test("1000000000001", "1", "4096", true); test("1000000000001", "1", "8192", false); test("12345678987654321", "321", "1000", true); test("12345678987654321", "322", "1000", false); test("1234", "1234", "1000000000000", true); test("1234", "1235", "1000000000000", false); test("1000000001234", "1000000002234", "1000", true); test("1000000001234", "1000000002235", "1000", false); test("1000000001234", "1234", "1000000000000", true); test("1000000001234", "1235", "1000000000000", false); test("1000000001234", "5000000001234", "1000000000000", true); test("1000000001234", "5000000001235", "1000000000000", false); test("0", "-1", "0", false); test("57", "-57", "0", false); test("57", "-58", "0", false); test("1000000000000", "-57", "0", false); test("0", "-256", "256", true); test("0", "-256", "512", false); test("13", "-27", "10", true); test("13", "-28", "10", false); test("29", "-27", "1", true); test("29", "-27", "2", true); test("29", "-27", "4", true); test("29", "-27", "8", true); test("29", "-27", "16", false); test("29", "-27", "3", false); test("999999999999", "-1", "4096", true); test("999999999999", "-1", "8192", false); test("12345678987654321", "-679", "1000", true); test("12345678987654321", "-680", "1000", false); test("1000000001234", "-999999999766", "1000", true); test("1000000001234", "-999999999767", "1000", false); test("1000000001234", "-999999998766", "1000000000000", true); test("1000000001234", "-999999998767", "1000000000000", false); test("-1", "0", "0", false); test("-57", "57", "0", false); test("-57", "58", "0", false); test("-1000000000000", "57", "0", false); test("-256", "0", "256", true); test("-256", "0", "512", false); test("-13", "27", "10", true); test("-13", "28", "10", false); test("-29", "27", "1", true); test("-29", "27", "2", true); test("-29", "27", "4", true); test("-29", "27", "8", true); test("-29", "27", "16", false); test("-29", "27", "3", false); test("-999999999999", "1", "4096", true); test("-999999999999", "1", "8192", false); test("-12345678987654321", "679", "1000", true); test("-12345678987654321", "680", "1000", false); test("-1000000001234", "999999999766", "1000", true); test("-1000000001234", "999999999767", "1000", false); test("-1000000001234", "999999998766", "1000000000000", true); test("-1000000001234", "999999998767", "1000000000000", false); test("-57", "-57", "0", true); test("-57", "-58", "0", false); test("-1000000000000", "-57", "0", false); test("-13", "-23", "10", true); test("-13", "-24", "10", false); test("-13", "-21", "1", true); test("-13", "-21", "2", true); test("-13", "-21", "4", true); test("-13", "-21", "8", true); test("-13", "-21", "16", false); test("-13", "-21", "3", false); test("-1000000000001", "-1", "4096", true); test("-1000000000001", "-1", "8192", false); test("-12345678987654321", "-321", "1000", true); test("-12345678987654321", "-322", "1000", false); test("-1234", "-1234", "1000000000000", true); test("-1234", "-1235", "1000000000000", false); test("-1000000001234", "-1000000002234", "1000", true); test("-1000000001234", "-1000000002235", "1000", false); test("-1000000001234", "-1234", "1000000000000", true); test("-1000000001234", "-1235", "1000000000000", false); test("-1000000001234", "-5000000001234", "1000000000000", true); test("-1000000001234", "-5000000001235", "1000000000000", false); } #[test] fn limbs_eq_neg_limb_mod_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_7().test_properties_with_config( &config, |(xs, y, m)| { let equal = limbs_eq_neg_limb_mod_limb(&xs, y, m); assert_eq!( (-Natural::from_owned_limbs_asc(xs)).eq_mod(Integer::from(y), Natural::from(m)), equal ); }, ); } #[test] fn limbs_pos_limb_eq_neg_limb_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_5().test_properties_with_config( &config, |(ms, x, y)| { let equal = limbs_pos_limb_eq_neg_limb_mod(x, y, &ms); let x = Integer::from(x); let y = -Natural::from(y); let m = Natural::from_owned_limbs_asc(ms); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }, ); unsigned_vec_unsigned_unsigned_triple_gen_var_6().test_properties_with_config( &config, |(ms, x, y)| { assert!(!limbs_pos_limb_eq_neg_limb_mod(x, y, &ms)); let x = Integer::from(x); let y = -Natural::from(y); let m = Natural::from_owned_limbs_asc(ms); assert!(!(&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x != y && (m == 0 || (&x).mod_op(&m) != (&y).mod_op(&m))); assert!(!(x - y).divisible_by(m)); }, ); } #[test] fn limbs_pos_eq_neg_limb_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().test_properties_with_config( &config, |(xs, mut ms, y)| { let equal = limbs_pos_eq_neg_limb_mod_ref(&xs, y, &ms); let m = Natural::from_limbs_asc(&ms); assert_eq!(limbs_pos_eq_neg_limb_mod(&xs, y, &mut ms), equal); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from(y); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }, ); unsigned_vec_unsigned_unsigned_vec_triple_gen_var_2().test_properties_with_config( &config, |(xs, y, mut ms)| { assert!(limbs_pos_eq_neg_limb_mod_ref(&xs, y, &ms)); let m = Natural::from_limbs_asc(&ms); assert!(limbs_pos_eq_neg_limb_mod(&xs, y, &mut ms)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from(y); assert!((&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m)); assert!((x - y).divisible_by(m)); }, ); unsigned_vec_unsigned_unsigned_vec_triple_gen_var_3().test_properties_with_config( &config, |(xs, y, mut ms)| { assert!(!limbs_pos_eq_neg_limb_mod_ref(&xs, y, &ms)); let m = Natural::from_limbs_asc(&ms); assert!(!limbs_pos_eq_neg_limb_mod(&xs, y, &mut ms)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from(y); assert!(!(&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x != y && (m == 0 || (&x).mod_op(&m) != (&y).mod_op(&m))); assert!(!(x - y).divisible_by(m)); }, ); } #[test] fn limbs_pos_eq_neg_mod_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().test_properties_with_config( &config, |(xs, ys, m)| { let equal = limbs_pos_eq_neg_mod_limb(&xs, &ys, m); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); let m = Natural::from(m); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_7().test_properties_with_config( &config, |(xs, ys, m)| { assert!(limbs_pos_eq_neg_mod_limb(&xs, &ys, m)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); let m = Natural::from(m); assert!((&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m)); assert!((x - y).divisible_by(m)); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_8().test_properties_with_config( &config, |(xs, ys, m)| { assert!(!limbs_pos_eq_neg_mod_limb(&xs, &ys, m)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); let m = Natural::from(m); assert!(!(&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x != y && (m == 0 || (&x).mod_op(&m) != (&y).mod_op(&m))); assert!(!(x - y).divisible_by(m)); }, ); } #[test] fn limbs_pos_eq_neg_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_36().test_properties_with_config(&config, |(xs, ys, mut ms)| { let equal = limbs_pos_eq_neg_mod_ref(&xs, &ys, &ms); let m = Natural::from_limbs_asc(&ms); assert_eq!(limbs_pos_eq_neg_mod(&xs, &ys, &mut ms), equal); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); assert_eq!((&x).eq_mod(&y, &m), equal); let m = Integer::from(m); assert_eq!( x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m), equal ); assert_eq!((x - y).divisible_by(m), equal); }); unsigned_vec_triple_gen_var_37().test_properties_with_config(&config, |(xs, ys, mut ms)| { assert!(limbs_pos_eq_neg_mod_ref(&xs, &ys, &ms)); let m = Natural::from_limbs_asc(&ms); assert!(limbs_pos_eq_neg_mod(&xs, &ys, &mut ms)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); assert!((&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x == y || m != 0 && (&x).mod_op(&m) == (&y).mod_op(&m)); assert!((x - y).divisible_by(m)); }); unsigned_vec_triple_gen_var_38().test_properties_with_config(&config, |(xs, ys, mut ms)| { assert!(!limbs_pos_eq_neg_mod_ref(&xs, &ys, &ms)); let m = Natural::from_limbs_asc(&ms); assert!(!limbs_pos_eq_neg_mod(&xs, &ys, &mut ms)); let x = Integer::from(Natural::from_owned_limbs_asc(xs)); let y = -Natural::from_owned_limbs_asc(ys); assert!(!(&x).eq_mod(&y, &m)); let m = Integer::from(m); assert!(x != y && (m == 0 || (&x).mod_op(&m) != (&y).mod_op(&m))); assert!(!(x - y).divisible_by(m)); }); } #[test] fn eq_mod_properties() { integer_integer_natural_triple_gen().test_properties(|(x, y, m)| { let equal = (&x).eq_mod(&y, &m); assert_eq!((&y).eq_mod(&x, &m), equal); assert_eq!((&x).eq_mod(&y, m.clone()), equal); assert_eq!((&x).eq_mod(y.clone(), &m), equal); assert_eq!((&x).eq_mod(y.clone(), m.clone()), equal); assert_eq!(x.clone().eq_mod(&y, &m), equal); assert_eq!(x.clone().eq_mod(&y, m.clone()), equal); assert_eq!(x.clone().eq_mod(y.clone(), &m), equal); assert_eq!(x.clone().eq_mod(y.clone(), m.clone()), equal); assert_eq!((-&x).eq_mod(-&y, &m), equal); assert_eq!((&x - &y).divisible_by(Integer::from(&m)), equal); assert_eq!((&y - &x).divisible_by(Integer::from(&m)), equal); assert_eq!( rug::Integer::from(&x).is_congruent(&rug::Integer::from(&y), &rug::Integer::from(&m)), equal ); }); integer_integer_natural_triple_gen_var_1().test_properties(|(ref x, ref y, ref m)| { assert!(x.eq_mod(y, m)); assert!(y.eq_mod(x, m)); assert!(rug::Integer::from(x).is_congruent(&rug::Integer::from(y), &rug::Integer::from(m))); }); integer_integer_natural_triple_gen_var_2().test_properties(|(ref x, ref y, ref m)| { assert!(!x.eq_mod(y, m)); assert!(!y.eq_mod(x, m)); assert!( !rug::Integer::from(x).is_congruent(&rug::Integer::from(y), &rug::Integer::from(m)) ); }); integer_pair_gen().test_properties(|(x, y)| { assert!((&x).eq_mod(&y, Natural::ONE)); assert_eq!((&x).eq_mod(&y, Natural::ZERO), x == y); }); integer_natural_pair_gen().test_properties(|(x, m)| { assert_eq!( (&x).eq_mod(Integer::ZERO, &m), (&x).divisible_by(Integer::from(&m)) ); assert!((&x).eq_mod(&x, m)); }); natural_triple_gen().test_properties(|(x, y, m)| { assert_eq!( Integer::from(&x).eq_mod(Integer::from(&y), &m), x.eq_mod(y, m) ); }); signed_triple_gen::().test_properties(|(x, y, m)| { assert_eq!( Integer::from(x).eq_mod(Integer::from(y), Integer::from(m).unsigned_abs()), x.eq_mod(y, m) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, EqModPowerOf2, ModPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_signed_unsigned_triple_gen_var_2, unsigned_vec_unsigned_unsigned_triple_gen_var_8, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, }; use malachite_nz::integer::Integer; use malachite_nz::integer::arithmetic::eq_mod_power_of_2::{ limbs_eq_mod_power_of_2_neg_limb, limbs_eq_mod_power_of_2_neg_pos, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_integer_integer_unsigned_quadruple_gen_var_1, integer_integer_unsigned_triple_gen_var_1, integer_integer_unsigned_triple_gen_var_2, integer_integer_unsigned_triple_gen_var_3, integer_pair_gen, integer_unsigned_pair_gen_var_2, natural_natural_unsigned_triple_gen_var_1, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_mod_power_of_2_neg_limb() { let test = |xs, y, pow, out| { assert_eq!(limbs_eq_mod_power_of_2_neg_limb(xs, y, pow), out); }; let width = Limb::WIDTH; test(&[1, 1], 3, 0, true); test(&[1, 1], 3, 1, true); test(&[1, 1], 3, 2, true); test(&[1, 1], 3, 3, false); test(&[1, 1], u32::MAX, 0, true); test(&[1, 1], u32::MAX, 1, true); test(&[1, 1], u32::MAX, width, true); test(&[1, 1], u32::MAX, width + 1, true); test(&[1, 2], u32::MAX, width + 1, false); test(&[1, u32::MAX, u32::MAX], u32::MAX, width + 1, true); test(&[1, u32::MAX, u32::MAX], u32::MAX, 2 * width, true); test(&[1, u32::MAX, u32::MAX], u32::MAX, 3 * width - 1, true); test(&[1, u32::MAX, u32::MAX], u32::MAX, 3 * width, true); test(&[1, u32::MAX, u32::MAX], u32::MAX, 3 * width + 1, false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_mod_power_of_2_neg_pos() { let test = |xs, ys, pow, out| { assert_eq!(limbs_eq_mod_power_of_2_neg_pos(xs, ys, pow), out); }; test(&[0b1111011, 0b111001000], &[0b10101], 4, true); test(&[0b1111011, 0b111001000], &[0b10101], 5, false); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b1111], 35, true, ); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b1111], 36, false, ); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b1111], 100, false, ); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b10111], 37, true, ); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b10111], 38, false, ); test( &[0b1111011, 0b111001000], &[0b11111111111111111111111110000101, 0b10111], 100, false, ); test( &[0xabcdabcd, 0x12341234], &[0x54325433, 0xedcbedcb], 64, true, ); test(&[0xabcdabcd, 0x12341234], &[0, 0xedcbedcb], 64, false); test( &[0xabcdabcd, 0x12341234], &[0x54325433, 0xedcbedcb], 65, false, ); test( &[0xabcdabcd, 0x12341234], &[0x54325433, 0xedcbedcb], 128, false, ); test(&[0, 0, 0x12341234], &[0, 0, 0x1234edcc], 80, true); test( &[0x54325433, 0xedcbedcb], &[0xabcdabcd, 0x12341234], 64, true, ); test(&[0, 0xedcbedcb], &[0xabcdabcd, 0x12341234], 64, false); test( &[0x54325433, 0xedcbedcb], &[0xabcdabcd, 0x12341234], 65, false, ); test( &[0x54325433, 0xedcbedcb], &[0xabcdabcd, 0x12341234], 128, false, ); test(&[0, 0, 0x1234edcc], &[0, 0, 0x12341234], 80, true); } #[test] fn test_eq_mod_power_of_2() { let test = |x, y, pow, out| { assert_eq!( Integer::from_str(x) .unwrap() .eq_mod_power_of_2(&Integer::from_str(y).unwrap(), pow), out ); #[cfg(feature = "32_bit_limbs")] assert_eq!( rug::Integer::from_str(x) .unwrap() .is_congruent_2pow(&rug::Integer::from_str(y).unwrap(), Limb::exact_from(pow)), out ); }; test("0", "256", 8, true); test("0", "256", 9, false); test("13", "21", 0, true); test("13", "21", 1, true); test("13", "21", 2, true); test("13", "21", 3, true); test("13", "21", 4, false); test("13", "21", 100, false); test("1000000000001", "1", 12, true); test("1000000000001", "1", 13, false); test("4294967295", "4294967295", 32, true); test("281474976710672", "844424930131984", 49, true); test("281474976710672", "844424930131984", 50, false); test("0", "-256", 8, true); test("0", "-256", 9, false); test("-13", "27", 0, true); test("-13", "27", 1, true); test("-13", "27", 2, true); test("-13", "27", 3, true); test("-13", "27", 4, false); test("-13", "27", 100, false); test("13", "-27", 0, true); test("13", "-27", 1, true); test("13", "-27", 2, true); test("13", "-27", 3, true); test("13", "-27", 4, false); test("13", "-27", 100, false); test("-1000000000001", "4095", 13, true); test("-1000000000001", "4095", 14, false); test("1000000000001", "-4095", 13, true); test("1000000000001", "-4095", 14, false); test("4294967295", "-1", 32, true); test("-1", "4294967295", 32, true); test("-13", "-21", 0, true); test("-13", "-21", 1, true); test("-13", "-21", 2, true); test("-13", "-21", 3, true); test("-13", "-21", 4, false); test("-13", "-21", 100, false); test("-1000000000001", "-1", 12, true); test("-1000000000001", "-1", 13, false); test("-4294967295", "-4294967295", 32, true); test("-281474976710672", "-844424930131984", 49, true); test("-281474976710672", "-844424930131984", 50, false); test("1311693408901639117", "-17135050664807912499", 64, true); test("1311693408901639117", "-17135050663395328000", 64, false); test("1311693408901639117", "-17135050664807912499", 65, false); test("1311693408901639117", "-17135050664807912499", 128, false); test( "5633680281231555440641310720", "-5634717283396403096794955776", 80, true, ); test("-1311693408901639117", "17135050664807912499", 64, true); test("-1311693408901639117", "17135050663395328000", 64, false); test("-1311693408901639117", "17135050664807912499", 65, false); test("-1311693408901639117", "17135050664807912499", 128, false); test( "-5633680281231555440641310720", "5634717283396403096794955776", 80, true, ); test("18446744073709541007", "-10609", 64, true); test("18446744073709541007", "-10609", 65, false); test("79228162514264337589248972431", "-4294977905", 96, true); test("79228162514264337589248972431", "-4294977905", 97, false); } #[test] fn limbs_eq_mod_power_of_2_neg_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_8().test_properties_with_config( &config, |(xs, y, pow)| { assert_eq!( limbs_eq_mod_power_of_2_neg_limb(&xs, y, pow), (-Natural::from_owned_limbs_asc(xs)).eq_mod_power_of_2(&Integer::from(y), pow) ); }, ); } #[test] fn limbs_eq_mod_power_of_2_neg_pos_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9().test_properties_with_config( &config, |(xs, ys, pow)| { assert_eq!( limbs_eq_mod_power_of_2_neg_pos(&xs, &ys, pow), (-Natural::from_owned_limbs_asc(xs)) .eq_mod_power_of_2(&Integer::from(Natural::from_owned_limbs_asc(ys)), pow) ); }, ); } #[test] fn eq_mod_power_of_2_properties() { integer_integer_unsigned_triple_gen_var_1().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(&y, pow); #[cfg(feature = "32_bit_limbs")] assert_eq!( rug::Integer::from(&x) .is_congruent_2pow(&rug::Integer::from(&y), Limb::exact_from(pow)), eq_mod_power_of_2 ); assert_eq!(y.eq_mod_power_of_2(&x, pow), eq_mod_power_of_2); assert_eq!( x.mod_power_of_2(pow) == y.mod_power_of_2(pow), eq_mod_power_of_2, ); }); integer_integer_unsigned_triple_gen_var_2().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(&y, pow), "{x} {y} {pow}"); #[cfg(feature = "32_bit_limbs")] assert!( rug::Integer::from(&x) .is_congruent_2pow(&rug::Integer::from(&y), Limb::exact_from(pow)) ); assert!(y.eq_mod_power_of_2(&x, pow)); assert_eq!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); integer_integer_unsigned_triple_gen_var_3().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(&y, pow)); #[cfg(feature = "32_bit_limbs")] assert!( !rug::Integer::from(&x) .is_congruent_2pow(&rug::Integer::from(&y), Limb::exact_from(pow)) ); assert!(!y.eq_mod_power_of_2(&x, pow)); assert_ne!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); integer_unsigned_pair_gen_var_2().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(&n, pow)); assert_eq!( n.eq_mod_power_of_2(&Integer::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( Integer::ZERO.eq_mod_power_of_2(&n, pow), n.divisible_by_power_of_2(pow) ); }); integer_integer_integer_unsigned_quadruple_gen_var_1().test_properties(|(x, y, z, pow)| { if x.eq_mod_power_of_2(&y, pow) && y.eq_mod_power_of_2(&z, pow) { assert!(x.eq_mod_power_of_2(&z, pow)); } }); integer_pair_gen().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(&y, 0)); }); natural_natural_unsigned_triple_gen_var_1().test_properties(|(x, y, pow)| { assert_eq!( x.eq_mod_power_of_2(&y, pow), Integer::from(x).eq_mod_power_of_2(&Integer::from(y), pow), ); }); signed_signed_unsigned_triple_gen_var_2::().test_properties(|(x, y, pow)| { assert_eq!( x.eq_mod_power_of_2(y, pow), Integer::from(x).eq_mod_power_of_2(&Integer::from(y), pow), ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, ExtendedGcd, Gcd}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen}; use num::BigInt; use num::Integer as NumInteger; use std::cmp::min; use std::str::FromStr; #[test] fn test_extended_gcd() { let test = |s, t, gcd, x, y| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let result = u.clone().extended_gcd(v.clone()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = (&u).extended_gcd(v.clone()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = u.clone().extended_gcd(&v); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = (&u).extended_gcd(&v); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); if u != 0u32 || v != 0u32 { let result = BigInt::from_str(s) .unwrap() .extended_gcd(&BigInt::from_str(t).unwrap()); assert_eq!(result.gcd.to_string(), gcd); assert_eq!(result.x.to_string(), x); assert_eq!(result.y.to_string(), y); } let result = rug::Integer::from_str(s) .unwrap() .extended_gcd(rug::Integer::from_str(t).unwrap(), rug::Integer::new()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); }; test("0", "0", "0", "0", "0"); test("0", "1", "1", "0", "1"); test("0", "-1", "1", "0", "-1"); test("1", "0", "1", "1", "0"); test("-1", "0", "1", "-1", "0"); test("1", "1", "1", "0", "1"); test("1", "-1", "1", "0", "-1"); test("-1", "1", "1", "0", "1"); test("-1", "-1", "1", "0", "-1"); test("0", "6", "6", "0", "1"); test("0", "-6", "6", "0", "-1"); test("6", "0", "6", "1", "0"); test("-6", "0", "6", "-1", "0"); test("1", "6", "1", "1", "0"); test("1", "-6", "1", "1", "0"); test("-1", "6", "1", "-1", "0"); test("-1", "-6", "1", "-1", "0"); test("6", "1", "1", "0", "1"); test("6", "-1", "1", "0", "-1"); test("-6", "1", "1", "0", "1"); test("-6", "-1", "1", "0", "-1"); test("6", "6", "6", "0", "1"); test("6", "-6", "6", "0", "-1"); test("-6", "6", "6", "0", "1"); test("-6", "-6", "6", "0", "-1"); test("8", "12", "4", "-1", "1"); test("54", "24", "6", "1", "-2"); test("42", "56", "14", "-1", "1"); test("48", "18", "6", "-1", "3"); test("3", "5", "1", "2", "-1"); test("12", "90", "6", "-7", "1"); test("240", "46", "2", "-9", "47"); test("240", "-46", "2", "-9", "-47"); test("-240", "46", "2", "9", "47"); test("-240", "-46", "2", "9", "-47"); test("-128", "-128", "128", "0", "-1"); test("0", "-128", "128", "0", "-1"); test("-128", "0", "128", "-1", "0"); test("12", "60", "12", "1", "0"); test("-12", "60", "12", "-1", "0"); test("12", "-60", "12", "1", "0"); test("-12", "-60", "12", "-1", "0"); test("60", "12", "12", "0", "1"); test("-60", "12", "12", "0", "1"); test("60", "-12", "12", "0", "-1"); test("-60", "-12", "12", "0", "-1"); test( "12345678987654321", "98765432123456789", "1", "1777777788", "-222222223", ); test( "12345678987654321", "-98765432123456789", "1", "1777777788", "222222223", ); test( "-12345678987654321", "98765432123456789", "1", "-1777777788", "-222222223", ); test( "-12345678987654321", "-98765432123456789", "1", "-1777777788", "222222223", ); test( "12345678987654321", "98765432123456827", "37", "-577153682403132", "72144210138067", ); test( "12345678987654321", "-98765432123456827", "37", "-577153682403132", "-72144210138067", ); test( "-12345678987654321", "98765432123456827", "37", "577153682403132", "72144210138067", ); test( "-12345678987654321", "-98765432123456827", "37", "577153682403132", "-72144210138067", ); } #[test] fn extended_gcd_properties() { integer_pair_gen().test_properties(|(a, b): (Integer, Integer)| { let result_val_val = a.clone().extended_gcd(b.clone()); let result_val_ref = a.clone().extended_gcd(&b); let result_ref_val = (&a).extended_gcd(b.clone()); let result = (&a).extended_gcd(&b); assert!(result_val_val.0.is_valid()); assert!(result_val_val.1.is_valid()); assert!(result_val_val.2.is_valid()); assert!(result_val_ref.0.is_valid()); assert!(result_val_ref.1.is_valid()); assert!(result_val_ref.2.is_valid()); assert!(result_ref_val.0.is_valid()); assert!(result_ref_val.1.is_valid()); assert!(result_ref_val.2.is_valid()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let (gcd, x, y) = result; if a != 0u32 || b != 0u32 { let num_result = BigInt::from(&a).extended_gcd(&BigInt::from(&b)); assert_eq!(Integer::from(&num_result.gcd), gcd); assert_eq!(Integer::from(&num_result.x), x); assert_eq!(Integer::from(&num_result.y), y); } let (rug_gcd, rug_x, rug_y) = rug::Integer::from(&a).extended_gcd(rug::Integer::from(&b), rug::Integer::new()); assert_eq!(Natural::exact_from(&rug_gcd), gcd); assert_eq!(Integer::from(&rug_x), x); assert_eq!(Integer::from(&rug_y), y); assert_eq!(a.unsigned_abs_ref().gcd(b.unsigned_abs_ref()), gcd); assert_eq!(&a * &x + &b * &y, Integer::from(&gcd)); // uniqueness if a != 0u32 && b != 0u32 && &gcd != min(a.unsigned_abs_ref(), b.unsigned_abs_ref()) { assert!(x.le_abs(&((&b).div_exact(Integer::from(&gcd)) >> 1u32))); assert!(y.le_abs(&((&a).div_exact(Integer::from(&gcd)) >> 1u32))); } let reverse = (&b).extended_gcd(&a); if a == b { assert_eq!(reverse, (gcd, x, y)); } else if a == -b { assert_eq!(reverse, (gcd, x, -y)); } else { assert_eq!(reverse, (gcd, y, x)); } }); integer_gen().test_properties(|x| { if x != 0u32 { let result = (&x).extended_gcd(&x); assert_eq!(result.0, *x.unsigned_abs_ref()); assert_eq!(result.1, 0u32); assert_eq!(result.2, if x >= 0u32 { 1i32 } else { -1i32 }); let result = (&x).extended_gcd(-&x); assert_eq!(result.0, *x.unsigned_abs_ref()); assert_eq!(result.1, 0u32); assert_eq!(result.2, if x < 0u32 { 1i32 } else { -1i32 }); let result = (&x).extended_gcd(Integer::ZERO); assert_eq!(result.0, *x.unsigned_abs_ref()); assert_eq!(result.1, if x >= 0u32 { 1i32 } else { -1i32 }); assert_eq!(result.2, 0u32); let result = Integer::ZERO.extended_gcd(&x); assert_eq!(result.0, *x.unsigned_abs_ref()); assert_eq!(result.1, 0u32); assert_eq!(result.2, if x >= 0u32 { 1i32 } else { -1i32 }); } if *x.unsigned_abs_ref() != 1u32 { assert_eq!( Integer::ONE.extended_gcd(&x), (Natural::ONE, Integer::ONE, Integer::ZERO) ); } assert_eq!( x.extended_gcd(Integer::ONE), (Natural::ONE, Integer::ZERO, Integer::ONE) ); }); signed_pair_gen::().test_properties(|(a, b)| { let (u_gcd, u_x, u_y) = a.extended_gcd(b); let (gcd, x, y) = Integer::from(a).extended_gcd(Integer::from(b)); assert_eq!(gcd, u_gcd); assert_eq!(x, u_x); assert_eq!(y, u_y); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, CoprimeWith, JacobiSymbol, KroneckerSymbol, LegendreSymbol, ModPowerOf2, Sign, }; use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::WrappingInto; use malachite_base::test_util::generators::{ large_type_gen_var_27, signed_pair_gen, signed_pair_gen_var_8, }; use malachite_nz::integer::Integer; use malachite_nz::integer::arithmetic::kronecker_symbol::limbs_kronecker_symbol; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_9, integer_pair_gen, integer_pair_gen_var_4, integer_pair_gen_var_5, integer_pair_gen_var_6, integer_triple_gen, integer_triple_gen_var_2, integer_triple_gen_var_3, }; use std::borrow::Cow; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_limbs_kronecker_symbol() { fn test(x_sign: bool, xs: &[Limb], y_sign: bool, ys: &[Limb], s: i8) { let x = Integer::from_sign_and_abs(x_sign, Natural::from_limbs_asc(xs)); let y = Integer::from_sign_and_abs(y_sign, Natural::from_limbs_asc(ys)); assert_eq!((&x).kronecker_symbol(&y), s); assert_eq!(limbs_kronecker_symbol(x_sign, xs, y_sign, ys), s); } #[cfg(not(feature = "32_bit_limbs"))] { // - ys_len != 0 // - xs_len != 0 // - (x_lo | y_lo).odd() // - y_sign // - ys_len <= 1 || y_twos == 0 first time // - x_sign // - xs_len >= ys_len // - ys_len == 1 // - y_lo == 1 test(true, &[1], true, &[1], 1); // - ys_len == 0 test(false, &[], false, &[], 0); // - xs_len == 0 test(false, &[], false, &[1], 1); // - !y_sign // - !x_sign test(false, &[1], false, &[1], -1); // - y_lo != 1 // - xs_len <= 1 test(false, &[1], false, &[3], 1); // - (x_lo | y_lo).even() test(false, &[2], false, &[2], 0); // - xs_len < ys_len // - ys_len <= 1 || y_twos == 0 second time test(false, &[1], false, &[1, 1], -1); // - xs_len > 1 // - xs.len() < BMOD_1_TO_MOD_1_THRESHOLD test(false, &[3], false, &[1, 1], 1); // - ys_len != 1 // - xs_len < ys_len << 1 // - xs_len <= ys_len // - y_twos == 0 test(false, &[1, 1], false, &[1, 1], 0); // - ys_len > 1 && y_twos != 0 first time // - ys_len == 2 && b1 >> y_twos == 0 first time test(false, &[1], false, &[2, 1], -1); // - ys_len != 2 || b1 >> y_twos != 0 first time test(false, &[1], false, &[2, 2], -1); // - xs_len > ys_len test(false, &[1, 1], false, &[1, 0, 1], -1); // - y_twos != 0 test(false, &[1, 1], false, &[2, 2], 0); // - ys_len > 1 && y_twos != 0 second time // - ys_len == 2 && b1 >> y_twos == 0 second time test(false, &[2, 1], false, &[1, 0, 1], -1); } #[cfg(feature = "32_bit_limbs")] { // - xs_len >= ys_len << 1 test( true, &[ 809415104, 1710169977, 881476190, 1104012799, 1326347481, 682701285, 3321863945, 1051939994, 3108635835, 1895680941, 2854018447, 4014565990, 3427834973, ], false, &[1909529931, 430037021], 1, ); // - ys_len != 2 || b1 >> y_twos != 0 second time test( false, &[3810500016, 962414993, 1954977047], false, &[ 2965238473, 2597078462, 113721090, 1560538966, 3708600302, 1747115778, 2509295310, 3964059579, 1937003961, 3783443612, 1437850759, 686587963, 1405672406, ], 1, ); // - xs.len() >= BMOD_1_TO_MOD_1_THRESHOLD test( true, &[95723951], true, &[ 3104822486, 256665209, 1106870463, 2021763401, 3319578375, 3716316846, 413568526, 2889388423, 2677034801, 1809274412, 609675151, 2287549814, 2615809925, 2139281936, 2621623930, 2423765969, 2490520154, 276871549, 2835834558, 3643930811, 2346794500, 1716153848, 2882325673, 197745775, 1455312056, 2481758015, 1539562182, 1248381418, 643884751, 3963005283, 3999713854, 570674748, 1646619329, 4056981682, 2746165076, 2757679283, 1546323574, 3282851400, 1861976181, 2431917382, 1727042394, 490254435, 3636744381, 1560042014, 704706907, 4231077753, 3265644143, 25380599, 1231870002, 1477457950, 4289279025, 1339161480, 2290594253, 2530008576, ], 1, ); } } #[test] fn test_legendre_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Integer::from_str(u).unwrap(); let n = Integer::from_str(v).unwrap(); assert_eq!(a.clone().legendre_symbol(n.clone()), s); assert_eq!(a.clone().legendre_symbol(&n), s); assert_eq!((&a).legendre_symbol(n.clone()), s); assert_eq!((&a).legendre_symbol(&n), s); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!((&a).jacobi_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .legendre(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "3", 0); test("1", "3", 1); test("2", "3", -1); test("0", "5", 0); test("1", "5", 1); test("2", "5", -1); test("3", "5", -1); test("4", "5", 1); test("0", "7", 0); test("1", "7", 1); test("2", "7", 1); test("3", "7", -1); test("4", "7", 1); test("5", "7", -1); test("6", "7", -1); test("7", "7", 0); test("8", "7", 1); test("9", "7", 1); test("10", "7", -1); test("11", "7", 1); test("12", "7", -1); test("13", "7", -1); test("-7", "7", 0); test("-6", "7", 1); test("-5", "7", 1); test("-4", "7", -1); test("-3", "7", 1); test("-2", "7", -1); test("-1", "7", -1); test("1001", "9907", -1); test("10908", "9907", -1); test("-8906", "9907", -1); } #[test] fn legendre_symbol_fail() { assert_panic!(Integer::ONE.legendre_symbol(Integer::TWO)); assert_panic!(Integer::ONE.legendre_symbol(&Integer::TWO)); assert_panic!((&Integer::ONE).legendre_symbol(Integer::TWO)); assert_panic!((&Integer::ONE).legendre_symbol(&Integer::TWO)); assert_panic!(Integer::ONE.legendre_symbol(Integer::NEGATIVE_ONE)); assert_panic!(Integer::ONE.legendre_symbol(&Integer::NEGATIVE_ONE)); assert_panic!((&Integer::ONE).legendre_symbol(Integer::NEGATIVE_ONE)); assert_panic!((&Integer::ONE).legendre_symbol(&Integer::NEGATIVE_ONE)); } #[test] fn test_jacobi_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Integer::from_str(u).unwrap(); let n = Integer::from_str(v).unwrap(); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!((&a).jacobi_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .jacobi(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "1", 1); test("0", "9", 0); test("1", "9", 1); test("2", "9", 1); test("3", "9", 0); test("4", "9", 1); test("5", "9", 1); test("6", "9", 0); test("7", "9", 1); test("8", "9", 1); test("9", "9", 0); test("10", "9", 1); test("11", "9", 1); test("12", "9", 0); test("13", "9", 1); test("14", "9", 1); test("15", "9", 0); test("16", "9", 1); test("17", "9", 1); test("-9", "9", 0); test("-8", "9", 1); test("-7", "9", 1); test("-6", "9", 0); test("-5", "9", 1); test("-4", "9", 1); test("-3", "9", 0); test("-2", "9", 1); test("-1", "9", 1); } #[test] fn jacobi_symbol_fail() { assert_panic!(Integer::ONE.jacobi_symbol(Integer::TWO)); assert_panic!(Integer::ONE.jacobi_symbol(&Integer::TWO)); assert_panic!((&Integer::ONE).jacobi_symbol(Integer::TWO)); assert_panic!((&Integer::ONE).jacobi_symbol(&Integer::TWO)); assert_panic!(Integer::ONE.jacobi_symbol(Integer::NEGATIVE_ONE)); assert_panic!(Integer::ONE.jacobi_symbol(&Integer::NEGATIVE_ONE)); assert_panic!((&Integer::ONE).jacobi_symbol(Integer::NEGATIVE_ONE)); assert_panic!((&Integer::ONE).jacobi_symbol(&Integer::NEGATIVE_ONE)); } // Odd n is already tested in test_jacobi_symbol, so here we just test even n #[test] fn test_kronecker_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Integer::from_str(u).unwrap(); let n = Integer::from_str(v).unwrap(); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .kronecker(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "2", 0); test("1", "2", 1); test("2", "2", 0); test("3", "2", -1); test("4", "2", 0); test("5", "2", -1); test("6", "2", 0); test("7", "2", 1); test("0", "4", 0); test("1", "4", 1); test("2", "4", 0); test("3", "4", 1); test("0", "6", 0); test("1", "6", 1); test("2", "6", 0); test("3", "6", 0); test("4", "6", 0); test("5", "6", 1); test("6", "6", 0); test("7", "6", 1); test("8", "6", 0); test("9", "6", 0); test("10", "6", 0); test("11", "6", 1); test("12", "6", 0); test("13", "6", -1); test("14", "6", 0); test("15", "6", 0); test("16", "6", 0); test("17", "6", -1); test("18", "6", 0); test("19", "6", -1); test("20", "6", 0); test("21", "6", 0); test("22", "6", 0); test("23", "6", -1); test("-1", "2", 1); test("-2", "2", 0); test("-3", "2", -1); test("-4", "2", 0); test("-5", "2", -1); test("-6", "2", 0); test("-7", "2", 1); test("-1", "4", 1); test("-2", "4", 0); test("-3", "4", 1); test("-1", "6", -1); test("-2", "6", 0); test("-3", "6", 0); test("-4", "6", 0); test("-5", "6", -1); test("-6", "6", 0); test("-7", "6", -1); test("-8", "6", 0); test("-9", "6", 0); test("-10", "6", 0); test("-11", "6", -1); test("-12", "6", 0); test("-13", "6", 1); test("-14", "6", 0); test("-15", "6", 0); test("-16", "6", 0); test("-17", "6", 1); test("-18", "6", 0); test("-19", "6", 1); test("-20", "6", 0); test("-21", "6", 0); test("-22", "6", 0); test("-23", "6", 1); test("0", "-2", 0); test("1", "-2", 1); test("2", "-2", 0); test("3", "-2", -1); test("4", "-2", 0); test("5", "-2", -1); test("6", "-2", 0); test("7", "-2", 1); test("0", "-4", 0); test("1", "-4", 1); test("2", "-4", 0); test("3", "-4", 1); test("0", "-6", 0); test("1", "-6", 1); test("2", "-6", 0); test("3", "-6", 0); test("4", "-6", 0); test("5", "-6", 1); test("6", "-6", 0); test("7", "-6", 1); test("8", "-6", 0); test("9", "-6", 0); test("10", "-6", 0); test("11", "-6", 1); test("12", "-6", 0); test("13", "-6", -1); test("14", "-6", 0); test("15", "-6", 0); test("16", "-6", 0); test("17", "-6", -1); test("18", "-6", 0); test("19", "-6", -1); test("20", "-6", 0); test("21", "-6", 0); test("22", "-6", 0); test("23", "-6", -1); test("-1", "-2", -1); test("-2", "-2", 0); test("-3", "-2", 1); test("-4", "-2", 0); test("-5", "-2", 1); test("-6", "-2", 0); test("-7", "-2", -1); test("-1", "-4", -1); test("-2", "-4", 0); test("-3", "-4", -1); test("-1", "-6", 1); test("-2", "-6", 0); test("-3", "-6", 0); test("-4", "-6", 0); test("-5", "-6", 1); test("-6", "-6", 0); test("-7", "-6", 1); test("-8", "-6", 0); test("-9", "-6", 0); test("-10", "-6", 0); test("-11", "-6", 1); test("-12", "-6", 0); test("-13", "-6", -1); test("-14", "-6", 0); test("-15", "-6", 0); test("-16", "-6", 0); test("-17", "-6", -1); test("-18", "-6", 0); test("-19", "-6", -1); test("-20", "-6", 0); test("-21", "-6", 0); test("-22", "-6", 0); test("-23", "-6", -1); test("1001", "-9908", -1); test("10909", "-9908", -1); test("-8907", "-9908", 1); } #[test] fn limbs_kronecker_symbol_properties() { large_type_gen_var_27().test_properties(|(x_sign, xs, y_sign, ys)| { let x = Integer::from_sign_and_abs(x_sign, Natural::from_limbs_asc(&xs)); let y = Integer::from_sign_and_abs(y_sign, Natural::from_limbs_asc(&ys)); let s = (&x).kronecker_symbol(&y); assert_eq!(limbs_kronecker_symbol(x_sign, &xs, y_sign, &ys), s); }); } #[test] fn jacobi_symbol_properties() { integer_pair_gen_var_4().test_properties(|(a, n)| { let s = (&a).jacobi_symbol(&n); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); // Legendre should only be called on prime n, but it still works for non-prime odd n and we // can't currently test primality anyway. assert_eq!((&a).legendre_symbol(&n), s); assert_eq!((&a).legendre_symbol(n.clone()), s); assert_eq!(a.clone().legendre_symbol(&n), s); assert_eq!(a.clone().legendre_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!( rug::Integer::from(&a).jacobi(&rug::Integer::from(&n)), i32::from(s) ); assert!(s.le_abs(&1i8)); assert_eq!((&a + &n).jacobi_symbol(&n), s); assert_eq!((&a - &n).jacobi_symbol(&n), s); assert_eq!( s != 0, a.unsigned_abs_ref().coprime_with(n.unsigned_abs_ref()) ); let n_mod_8: u8 = (&(&n).mod_power_of_2(3)).wrapping_into(); assert_eq!( (&a << 1u32).jacobi_symbol(&n), if n_mod_8 == 1 || n_mod_8 == 7 { s } else { -s } ); let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); assert_eq!((-a).jacobi_symbol(n), if n_mod_4 == 1 { s } else { -s }); }); integer_pair_gen_var_6().test_properties(|(m, n)| { let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); let m_mod_4: u8 = (&(&m).mod_power_of_2(2)).wrapping_into(); assert_eq!( (&m).jacobi_symbol(&n) * n.jacobi_symbol(m), if n_mod_4 == 1 || m_mod_4 == 1 { 1 } else { -1 } ); }); integer_triple_gen_var_2().test_properties(|(a, b, n)| { assert_eq!( (&a * &b).jacobi_symbol(&n), a.jacobi_symbol(&n) * b.jacobi_symbol(n) ); }); integer_triple_gen_var_3().test_properties(|(a, m, n)| { assert_eq!( (&a).jacobi_symbol(&m * &n), (&a).jacobi_symbol(m) * a.jacobi_symbol(n) ); }); integer_gen_var_9().test_properties(|n| { if n != 1u32 { assert_eq!(Integer::ZERO.jacobi_symbol(&n), 0); assert_eq!((&n).jacobi_symbol(&n), 0); } assert_eq!(Integer::ONE.jacobi_symbol(&n), 1); assert_eq!((&n).jacobi_symbol(Integer::ONE), 1); let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); assert_eq!( Integer::NEGATIVE_ONE.jacobi_symbol(&n), if n_mod_4 == 1 { 1 } else { -1 } ); let n_mod_8: u8 = (&(&n).mod_power_of_2(3)).wrapping_into(); assert_eq!( Integer::TWO.jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { 1 } else { -1 } ); }); signed_pair_gen_var_8::().test_properties(|(x, y)| { assert_eq!( Integer::from(x).jacobi_symbol(Integer::from(y)), x.jacobi_symbol(y) ); }); } #[test] fn kronecker_symbol_properties() { integer_pair_gen().test_properties(|(a, n)| { let s = (&a).kronecker_symbol(&n); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!( rug::Integer::from(&a).kronecker(&rug::Integer::from(&n)), i32::from(s) ); assert!(s.le_abs(&1i8)); assert_eq!( s != 0, a.unsigned_abs_ref().coprime_with(n.unsigned_abs_ref()) ); let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); if n_mod_4 == 2 { let four_n = &n << 2u32; let b = &a + &four_n; if n > 0u32 || a.sign() == b.sign() { assert_eq!(b.kronecker_symbol(&n), s); } let b = &a - four_n; if n > 0u32 || a.sign() == b.sign() { assert_eq!(b.kronecker_symbol(&n), s); } } else { let b = &a + &n; if n > 0u32 || a.sign() == b.sign() { assert_eq!(b.kronecker_symbol(&n), s); } let b = &a - &n; if n > 0u32 || a.sign() == b.sign() { assert_eq!(b.kronecker_symbol(&n), s); } } let a_mod_4: u8 = (&(&a).mod_power_of_2(2)).wrapping_into(); if a != 0u32 && a_mod_4 != 3 { let abs_a = (&a).abs(); if a_mod_4 == 2 { let four_abs_a = abs_a << 2u32; assert_eq!((&a).kronecker_symbol(&n + &four_abs_a), s); assert_eq!((&a).kronecker_symbol(&n - four_abs_a), s); } else { assert_eq!((&a).kronecker_symbol(&n + &abs_a), s); assert_eq!((&a).kronecker_symbol(&n - abs_a), s); } } let m = a; let m_odd = if m == 0u32 { Integer::ONE } else { &m >> m.trailing_zeros().unwrap() }; let m_odd_mod_4: u8 = (&(&m_odd).mod_power_of_2(2)).wrapping_into(); let m_star = if m_odd_mod_4 == 1 { Cow::Borrowed(&m) } else { Cow::Owned(-&m) }; assert_eq!( m_star.as_ref().kronecker_symbol(&n), n.kronecker_symbol(m.abs()) ); }); integer_triple_gen().test_properties(|(x, y, z)| { if !(z == -1i32 && (x == 0u32 && y < 0u32 || x < 0u32 && y == 0u32)) { assert_eq!( (&x * &y).kronecker_symbol(&z), (&x).kronecker_symbol(&z) * (&y).kronecker_symbol(&z) ); } let y_odd_mod_4: u8 = if y == 0u32 { 0 } else { (&(&y >> y.trailing_zeros().unwrap()).mod_power_of_2(2)).wrapping_into() }; let z_odd_mod_4: u8 = if z == 0u32 { 0 } else { (&(&z >> z.trailing_zeros().unwrap()).mod_power_of_2(2)).wrapping_into() }; if !(x == -1i32 && (y == 0u32 && z_odd_mod_4 == 3 || y_odd_mod_4 == 3 && z == 0u32)) { assert_eq!( (&x).kronecker_symbol(&y * &z), (&x).kronecker_symbol(y) * x.kronecker_symbol(z) ); } }); integer_pair_gen_var_5().test_properties(|(m, n)| { let n_odd = if n == 0u32 { Integer::ONE } else { &n >> n.trailing_zeros().unwrap() }; let m_odd = if m == 0u32 { Integer::ONE } else { &m >> m.trailing_zeros().unwrap() }; let n_odd_mod_4: u8 = (&n_odd.mod_power_of_2(2)).wrapping_into(); let m_odd_mod_4: u8 = (&m_odd.mod_power_of_2(2)).wrapping_into(); let p = if n_odd_mod_4 == 1 || m_odd_mod_4 == 1 { 1 } else { -1 }; assert_eq!( (&m).kronecker_symbol(&n) * (&n).kronecker_symbol(&m), if m < 0u32 && n < 0u32 { -p } else { p } ); assert_eq!((&m).kronecker_symbol(&n) * n.kronecker_symbol(m.abs()), p); }); integer_gen().test_properties(|n| { if n != 1u32 && n != -1i32 { assert_eq!(Integer::ZERO.kronecker_symbol(&n), 0); assert_eq!((&n).kronecker_symbol(&n), 0); } assert_eq!(Integer::ONE.kronecker_symbol(&n), 1); assert_eq!((&n).kronecker_symbol(Integer::ONE), 1); let n_odd = if n == 0u32 { Integer::ONE } else { &n >> n.trailing_zeros().unwrap() }; let n_odd_mod_4: u8 = (&n_odd.mod_power_of_2(2)).wrapping_into(); assert_eq!( Integer::NEGATIVE_ONE.kronecker_symbol(&n), if n_odd_mod_4 == 1 { 1 } else { -1 } ); assert_eq!( (&n).kronecker_symbol(Integer::NEGATIVE_ONE), if n >= 0u32 { 1 } else { -1 } ); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(x).kronecker_symbol(Integer::from(y)), x.kronecker_symbol(y) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivMod, CeilingMod, CeilingModAssign, DivMod, DivRem, Mod, ModAssign, NegMod, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::signed_pair_gen_var_4; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_8, integer_pair_gen_var_1, integer_pair_gen_var_2, natural_pair_gen_var_5, }; use num::{BigInt, Integer as NumInteger}; use rug::ops::RemRounding; use std::str::FromStr; #[test] fn test_mod() { let test = |s, t, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); x.mod_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = BigInt::from_str(s) .unwrap() .mod_floor(&BigInt::from_str(t).unwrap()); assert_eq!(r.to_string(), remainder); let r = rug::Integer::from_str(s) .unwrap() .rem_floor(rug::Integer::from_str(t).unwrap()); assert_eq!(r.to_string(), remainder); assert_eq!(u.div_mod(v).1.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "123"); test("456", "123", "87"); test("4294967295", "4294967295", "0"); test("4294967295", "4294967295", "0"); test("1000000000000", "1", "0"); test("1000000000000", "3", "1"); test("1000000000000", "123", "100"); test("1000000000000", "4294967295", "3567587560"); test("1000000000000000000000000", "1", "0"); test("1000000000000000000000000", "3", "1"); test("1000000000000000000000000", "123", "37"); test("1000000000000000000000000", "4294967295", "3167723695"); test("1000000000000000000000000", "1234567890987", "530068894399"); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "3768477692975601", ); test("3356605361737854", "3081095617839357", "275509743898497"); test( "1098730198198174614195", "953382298040157850476", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test("123", "1000000000000000000000000", "123"); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "-333"); test("456", "-123", "-36"); test("4294967295", "-1", "0"); test("4294967295", "-4294967295", "0"); test("1000000000000", "-1", "0"); test("1000000000000", "-3", "-2"); test("1000000000000", "-123", "-23"); test("1000000000000", "-4294967295", "-727379735"); test("1000000000000000000000000", "-1", "0"); test("1000000000000000000000000", "-3", "-2"); test("1000000000000000000000000", "-123", "-86"); test("1000000000000000000000000", "-4294967295", "-1127243600"); test( "1000000000000000000000000", "-1234567890987", "-704498996588", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "-454912836989613466895606299668358255", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "-278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "-2669936877441", "-1149635115107", ); test( "3768477692975601", "-11447376614057827956", "-11443608136364852355", ); test("3356605361737854", "-3081095617839357", "-2805585873940860"); test( "1098730198198174614195", "-953382298040157850476", "-808034397882141086757", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "0", ); test("0", "-1000000000000000000000000", "0"); test( "123", "-1000000000000000000000000", "-999999999999999999999877", ); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "333"); test("-456", "123", "36"); test("-4294967295", "-1", "0"); test("-4294967295", "4294967295", "0"); test("-1000000000000", "1", "0"); test("-1000000000000", "3", "2"); test("-1000000000000", "123", "23"); test("-1000000000000", "4294967295", "727379735"); test("-1000000000000000000000000", "1", "0"); test("-1000000000000000000000000", "3", "2"); test("-1000000000000000000000000", "123", "86"); test("-1000000000000000000000000", "4294967295", "1127243600"); test( "-1000000000000000000000000", "1234567890987", "704498996588", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "454912836989613466895606299668358255", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "278232688309211835744673381771890580480", ); test( "-253640751230376270397812803167", "2669936877441", "1149635115107", ); test( "-3768477692975601", "11447376614057827956", "11443608136364852355", ); test("-3356605361737854", "3081095617839357", "2805585873940860"); test( "-1098730198198174614195", "953382298040157850476", "808034397882141086757", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "0", ); test( "-123", "1000000000000000000000000", "999999999999999999999877", ); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "-123"); test("-456", "-123", "-87"); test("-4294967295", "-1", "0"); test("-4294967295", "-4294967295", "0"); test("-1000000000000", "-1", "0"); test("-1000000000000", "-3", "-1"); test("-1000000000000", "-123", "-100"); test("-1000000000000", "-4294967295", "-3567587560"); test("-1000000000000000000000000", "-1", "0"); test("-1000000000000000000000000", "-3", "-1"); test("-1000000000000000000000000", "-123", "-37"); test("-1000000000000000000000000", "-4294967295", "-3167723695"); test( "-1000000000000000000000000", "-1234567890987", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "-2669936877441", "-1520301762334", ); test( "-3768477692975601", "-11447376614057827956", "-3768477692975601", ); test("-3356605361737854", "-3081095617839357", "-275509743898497"); test( "-1098730198198174614195", "-953382298040157850476", "-145347900158016763719", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "0", ); test("-123", "-1000000000000000000000000", "-123"); } #[test] #[should_panic] fn mod_assign_fail() { Integer::from(10).mod_assign(Integer::ZERO); } #[test] #[should_panic] fn mod_assign_ref_fail() { Integer::from(10).mod_assign(&Integer::ZERO); } #[test] #[should_panic] fn mod_fail() { Integer::from(10).mod_op(Integer::ZERO); } #[test] #[should_panic] fn mod_val_ref_fail() { Integer::from(10).mod_op(&Integer::ZERO); } #[test] #[should_panic] fn mod_ref_val_fail() { (&Integer::from(10)).mod_op(Integer::ZERO); } #[test] #[should_panic] fn mod_ref_ref_fail() { (&Integer::from(10)).mod_op(&Integer::ZERO); } #[test] fn test_rem() { let test = |s, t, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); x %= v.clone(); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x %= &v; assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone() % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone() % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = BigInt::from_str(s).unwrap() % &BigInt::from_str(t).unwrap(); assert_eq!(r.to_string(), remainder); let r = rug::Integer::from_str(s).unwrap() % rug::Integer::from_str(t).unwrap(); assert_eq!(r.to_string(), remainder); assert_eq!(u.div_rem(v).1.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "123"); test("456", "123", "87"); test("4294967295", "1", "0"); test("4294967295", "4294967295", "0"); test("1000000000000", "1", "0"); test("1000000000000", "3", "1"); test("1000000000000", "123", "100"); test("1000000000000", "4294967295", "3567587560"); test("1000000000000000000000000", "1", "0"); test("1000000000000000000000000", "3", "1"); test("1000000000000000000000000", "123", "37"); test("1000000000000000000000000", "4294967295", "3167723695"); test("1000000000000000000000000", "1234567890987", "530068894399"); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "3768477692975601", ); test("3356605361737854", "3081095617839357", "275509743898497"); test( "1098730198198174614195", "953382298040157850476", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test("123", "1000000000000000000000000", "123"); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "123"); test("456", "-123", "87"); test("4294967295", "-1", "0"); test("4294967295", "-4294967295", "0"); test("1000000000000", "-1", "0"); test("1000000000000", "-3", "1"); test("1000000000000", "-123", "100"); test("1000000000000", "-4294967295", "3567587560"); test("1000000000000000000000000", "-1", "0"); test("1000000000000000000000000", "-3", "1"); test("1000000000000000000000000", "-123", "37"); test("1000000000000000000000000", "-4294967295", "3167723695"); test( "1000000000000000000000000", "-1234567890987", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "-2669936877441", "1520301762334", ); test( "3768477692975601", "-11447376614057827956", "3768477692975601", ); test("3356605361737854", "-3081095617839357", "275509743898497"); test( "1098730198198174614195", "-953382298040157850476", "145347900158016763719", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "0", ); test("0", "-1000000000000000000000000", "0"); test("123", "-1000000000000000000000000", "123"); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "-123"); test("-456", "123", "-87"); test("-4294967295", "1", "0"); test("-4294967295", "4294967295", "0"); test("-1000000000000", "1", "0"); test("-1000000000000", "3", "-1"); test("-1000000000000", "123", "-100"); test("-1000000000000", "4294967295", "-3567587560"); test("-1000000000000000000000000", "1", "0"); test("-1000000000000000000000000", "3", "-1"); test("-1000000000000000000000000", "123", "-37"); test("-1000000000000000000000000", "4294967295", "-3167723695"); test( "-1000000000000000000000000", "1234567890987", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "2669936877441", "-1520301762334", ); test( "-3768477692975601", "11447376614057827956", "-3768477692975601", ); test("-3356605361737854", "3081095617839357", "-275509743898497"); test( "-1098730198198174614195", "953382298040157850476", "-145347900158016763719", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "0", ); test("-123", "1000000000000000000000000", "-123"); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "-123"); test("-456", "-123", "-87"); test("-4294967295", "-1", "0"); test("-4294967295", "-4294967295", "0"); test("-1000000000000", "-1", "0"); test("-1000000000000", "-3", "-1"); test("-1000000000000", "-123", "-100"); test("-1000000000000", "-4294967295", "-3567587560"); test("-1000000000000000000000000", "-1", "0"); test("-1000000000000000000000000", "-3", "-1"); test("-1000000000000000000000000", "-123", "-37"); test("-1000000000000000000000000", "-4294967295", "-3167723695"); test( "-1000000000000000000000000", "-1234567890987", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "-2669936877441", "-1520301762334", ); test( "-3768477692975601", "-11447376614057827956", "-3768477692975601", ); test("-3356605361737854", "-3081095617839357", "-275509743898497"); test( "-1098730198198174614195", "-953382298040157850476", "-145347900158016763719", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "0", ); test("-123", "-1000000000000000000000000", "-123"); } #[test] #[should_panic] fn rem_assign_fail() { let mut x = Integer::from(10); x %= Integer::ZERO; } #[test] #[should_panic] fn rem_assign_ref_fail() { let mut x = Integer::from(10); x %= &Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_fail() { Integer::from(10) % Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_val_ref_fail() { Integer::from(10) % &Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_val_fail() { &Integer::from(10) % Integer::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_ref_fail() { &Integer::from(10) % &Integer::ZERO; } #[test] fn test_ceiling_mod() { let test = |s, t, remainder| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut x = u.clone(); x.ceiling_mod_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.ceiling_mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().ceiling_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().ceiling_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).ceiling_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).ceiling_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = rug::Integer::from_str(s) .unwrap() .rem_ceil(rug::Integer::from_str(t).unwrap()); assert_eq!(r.to_string(), remainder); assert_eq!(u.ceiling_div_mod(v).1.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "-333"); test("456", "123", "-36"); test("4294967295", "1", "0"); test("4294967295", "4294967295", "0"); test("1000000000000", "1", "0"); test("1000000000000", "3", "-2"); test("1000000000000", "123", "-23"); test("1000000000000", "4294967295", "-727379735"); test("1000000000000000000000000", "1", "0"); test("1000000000000000000000000", "3", "-2"); test("1000000000000000000000000", "123", "-86"); test("1000000000000000000000000", "4294967295", "-1127243600"); test( "1000000000000000000000000", "1234567890987", "-704498996588", ); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-454912836989613466895606299668358255", ); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "2669936877441", "-1149635115107", ); test( "3768477692975601", "11447376614057827956", "-11443608136364852355", ); test("3356605361737854", "3081095617839357", "-2805585873940860"); test( "1098730198198174614195", "953382298040157850476", "-808034397882141086757", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test( "123", "1000000000000000000000000", "-999999999999999999999877", ); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "123"); test("456", "-123", "87"); test("4294967295", "-1", "0"); test("4294967295", "-4294967295", "0"); test("1000000000000", "-1", "0"); test("1000000000000", "-3", "1"); test("1000000000000", "-123", "100"); test("1000000000000", "-4294967295", "3567587560"); test("1000000000000000000000000", "-1", "0"); test("1000000000000000000000000", "-3", "1"); test("1000000000000000000000000", "-123", "37"); test("1000000000000000000000000", "-4294967295", "3167723695"); test( "1000000000000000000000000", "-1234567890987", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-1234567890987654321234567890987654321", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "-316049380092839506236049380092839506176", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "-2669936877441", "1520301762334", ); test( "3768477692975601", "-11447376614057827956", "3768477692975601", ); test("3356605361737854", "-3081095617839357", "275509743898497"); test( "1098730198198174614195", "-953382298040157850476", "145347900158016763719", ); test( "69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "-1000000000000000000000000", "0", ); test("0", "-1000000000000000000000000", "0"); test("123", "-1000000000000000000000000", "123"); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "-123"); test("-456", "123", "-87"); test("-4294967295", "1", "0"); test("-4294967295", "4294967295", "0"); test("-1000000000000", "1", "0"); test("-1000000000000", "3", "-1"); test("-1000000000000", "123", "-100"); test("-1000000000000", "4294967295", "-3567587560"); test("-1000000000000000000000000", "1", "0"); test("-1000000000000000000000000", "3", "-1"); test("-1000000000000000000000000", "123", "-37"); test("-1000000000000000000000000", "4294967295", "-3167723695"); test( "-1000000000000000000000000", "1234567890987", "-530068894399", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "-779655053998040854338961591319296066", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "-37816691783627670491375998320948925696", ); test( "-253640751230376270397812803167", "2669936877441", "-1520301762334", ); test( "-3768477692975601", "11447376614057827956", "-3768477692975601", ); test("-3356605361737854", "3081095617839357", "-275509743898497"); test( "-1098730198198174614195", "953382298040157850476", "-145347900158016763719", ); test( "-69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test("-123", "1000000000000000000000000", "-123"); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "333"); test("-456", "-123", "36"); test("-4294967295", "-1", "0"); test("-4294967295", "-4294967295", "0"); test("-1000000000000", "-1", "0"); test("-1000000000000", "-3", "2"); test("-1000000000000", "-123", "23"); test("-1000000000000", "-4294967295", "727379735"); test("-1000000000000000000000000", "-1", "0"); test("-1000000000000000000000000", "-3", "2"); test("-1000000000000000000000000", "-123", "86"); test("-1000000000000000000000000", "-4294967295", "1127243600"); test( "-1000000000000000000000000", "-1234567890987", "704498996588", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-1234567890987654321234567890987654321", "454912836989613466895606299668358255", ); test( "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "-316049380092839506236049380092839506176", "278232688309211835744673381771890580480", ); test( "-253640751230376270397812803167", "-2669936877441", "1149635115107", ); test( "-3768477692975601", "-11447376614057827956", "11443608136364852355", ); test("-3356605361737854", "-3081095617839357", "2805585873940860"); test( "-1098730198198174614195", "-953382298040157850476", "808034397882141086757", ); test( "-69738658860594537152875081748", "-69738658860594537152875081748", "0", ); test( "-1000000000000000000000000", "-1000000000000000000000000", "0", ); test("0", "-1000000000000000000000000", "0"); test( "-123", "-1000000000000000000000000", "999999999999999999999877", ); } #[test] #[should_panic] fn ceiling_mod_assign_fail() { Integer::from(10).ceiling_mod_assign(Integer::ZERO); } #[test] #[should_panic] fn ceiling_mod_assign_ref_fail() { Integer::from(10).ceiling_mod_assign(&Integer::ZERO); } #[test] #[should_panic] fn ceiling_mod_fail() { Integer::from(10).ceiling_mod(Integer::ZERO); } #[test] #[should_panic] fn ceiling_mod_val_ref_fail() { Integer::from(10).ceiling_mod(&Integer::ZERO); } #[test] #[should_panic] fn ceiling_mod_ref_val_fail() { (&Integer::from(10)).ceiling_mod(Integer::ZERO); } #[test] #[should_panic] fn ceiling_mod_ref_ref_fail() { (&Integer::from(10)).ceiling_mod(&Integer::ZERO); } fn mod_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); mut_x.mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x.mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); assert_eq!((&x).div_mod(&y).1, remainder); let num_remainder = BigInt::from(&x).mod_floor(&BigInt::from(&y)); assert_eq!(Integer::from(&num_remainder), remainder); let rug_remainder = rug::Integer::from(&x).rem_floor(rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_remainder), remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder > 0) == (y > 0)); assert_eq!((-&x).mod_op(&y), -(&x).ceiling_mod(&y)); assert_eq!((&x).mod_op(-&y), x.ceiling_mod(y)); } #[test] fn mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| mod_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| mod_properties_helper(x, y)); integer_gen().test_properties(|x| { assert_eq!((&x).mod_op(Integer::ONE), 0); assert_eq!(x.mod_op(Integer::NEGATIVE_ONE), 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x.mod_op(Integer::ONE), 0); assert_eq!(x.mod_op(Integer::NEGATIVE_ONE), 0); assert_eq!(x.mod_op(x), 0); assert_eq!(x.mod_op(-x), 0); assert_eq!(Integer::ZERO.mod_op(x), 0); if *x > 1 { assert_eq!(Integer::ONE.mod_op(x), 1); assert_eq!(Integer::NEGATIVE_ONE.mod_op(x), x - Integer::ONE); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).mod_op(Integer::from(&y)), x.mod_op(y)); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).mod_op(Integer::from(y)), x.mod_op(y)); }); } fn rem_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); mut_x %= &y; assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x %= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, remainder); let remainder_alt = &x % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = &x % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); assert_eq!((&x).div_rem(&y).1, remainder); let num_remainder = BigInt::from(&x) % &BigInt::from(&y); assert_eq!(Integer::from(&num_remainder), remainder); let rug_remainder = rug::Integer::from(&x) % rug::Integer::from(&y); assert_eq!(Integer::from(&rug_remainder), remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder > 0) == (x > 0)); assert_eq!((-&x) % &y, -&remainder); assert_eq!(x % (-y), remainder); } #[test] fn rem_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| rem_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| rem_properties_helper(x, y)); integer_gen().test_properties(|x| { assert_eq!(&x % Integer::ONE, 0); assert_eq!(x % Integer::NEGATIVE_ONE, 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x % Integer::ONE, 0); assert_eq!(x % Integer::NEGATIVE_ONE, 0); assert_eq!(x % x, 0); assert_eq!(x % -x, 0); assert_eq!(Integer::ZERO % x, 0); if *x > 1 { assert_eq!(Integer::ONE % x, 1); assert_eq!(Integer::NEGATIVE_ONE % x, -1); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) % Integer::from(&y), x % y); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!(Integer::from(x) % Integer::from(y), x % y); }); } fn ceiling_mod_properties_helper(x: Integer, y: Integer) { let mut mut_x = x.clone(); mut_x.ceiling_mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x.ceiling_mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).ceiling_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).ceiling_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().ceiling_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().ceiling_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); assert_eq!((&x).ceiling_div_mod(&y).1, remainder); let rug_remainder = rug::Integer::from(&x).rem_ceil(rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_remainder), remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder >= 0) != (y > 0)); assert_eq!((-&x).ceiling_mod(&y), -(&x).mod_op(&y)); assert_eq!((&x).ceiling_mod(-&y), x.mod_op(y)); } #[test] fn ceiling_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); integer_pair_gen_var_1() .test_properties_with_config(&config, |(x, y)| ceiling_mod_properties_helper(x, y)); integer_pair_gen_var_2() .test_properties_with_config(&config, |(x, y)| ceiling_mod_properties_helper(x, y)); integer_gen().test_properties(|x| { assert_eq!((&x).ceiling_mod(Integer::ONE), 0); assert_eq!(x.ceiling_mod(Integer::NEGATIVE_ONE), 0); }); integer_gen_var_8().test_properties(|ref x| { assert_eq!(x.ceiling_mod(Integer::ONE), 0); assert_eq!(x.ceiling_mod(Integer::NEGATIVE_ONE), 0); assert_eq!(x.ceiling_mod(x), 0); assert_eq!(x.ceiling_mod(-x), 0); assert_eq!(Integer::ZERO.ceiling_mod(x), 0); }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!( Integer::from(&x).ceiling_mod(Integer::from(&y)), -x.neg_mod(y) ); }); signed_pair_gen_var_4::().test_properties(|(x, y)| { assert_eq!( Integer::from(x).ceiling_mod(Integer::from(y)), x.ceiling_mod(y) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, CeilingModPowerOf2, CeilingModPowerOf2Assign, DivisibleByPowerOf2, ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2, PowerOf2, RemPowerOf2, RemPowerOf2Assign, ShrRound, Sign, }; use malachite_base::num::basic::traits::Zero; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, signed_unsigned_pair_gen_var_10, signed_unsigned_pair_gen_var_11, unsigned_gen, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_unsigned_triple_gen_var_1, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_4, integer_unsigned_pair_gen_var_5, integer_unsigned_unsigned_triple_gen_var_3, natural_unsigned_pair_gen_var_4, }; use std::cmp::min; use std::str::FromStr; #[test] fn test_mod_power_of_2() { let test = |s, v: u64, out| { let u = Integer::from_str(s).unwrap(); let mut n = u.clone(); n.mod_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 0, "0"); test("2", 1, "0"); test("260", 8, "4"); test("1611", 4, "11"); test("123", 100, "123"); test("1000000000000", 0, "0"); test("1000000000000", 12, "0"); test("1000000000001", 12, "1"); test("999999999999", 12, "4095"); test("1000000000000", 15, "4096"); test("1000000000000", 100, "1000000000000"); test("1000000000000000000000000", 40, "1020608380928"); test("1000000000000000000000000", 64, "2003764205206896640"); test("2147483647", 30, "1073741823"); test("2147483647", 31, "2147483647"); test("2147483647", 32, "2147483647"); test("2147483648", 30, "0"); test("2147483648", 31, "0"); test("2147483648", 32, "2147483648"); test("2147483649", 30, "1"); test("2147483649", 31, "1"); test("2147483649", 32, "2147483649"); test("4294967295", 31, "2147483647"); test("4294967295", 32, "4294967295"); test("4294967295", 33, "4294967295"); test("4294967296", 31, "0"); test("4294967296", 32, "0"); test("4294967296", 33, "4294967296"); test("4294967297", 31, "1"); test("4294967297", 32, "1"); test("4294967297", 33, "4294967297"); test("-2", 1, "0"); test("-260", 8, "252"); test("-1611", 4, "5"); test("-123", 100, "1267650600228229401496703205253"); test("-1000000000000", 0, "0"); test("-1000000000000", 12, "0"); test("-1000000000001", 12, "4095"); test("-999999999999", 12, "1"); test("-1000000000000", 15, "28672"); test("-1000000000000", 100, "1267650600228229400496703205376"); test("-1000000000000000000000000", 40, "78903246848"); test("-1000000000000000000000000", 64, "16442979868502654976"); test("-2147483647", 30, "1"); test("-2147483647", 31, "1"); test("-2147483647", 32, "2147483649"); test("-2147483648", 30, "0"); test("-2147483648", 31, "0"); test("-2147483648", 32, "2147483648"); test("-2147483649", 30, "1073741823"); test("-2147483649", 31, "2147483647"); test("-2147483649", 32, "2147483647"); test("-4294967295", 31, "1"); test("-4294967295", 32, "1"); test("-4294967295", 33, "4294967297"); test("-4294967296", 31, "0"); test("-4294967296", 32, "0"); test("-4294967296", 33, "4294967296"); test("-4294967297", 31, "2147483647"); test("-4294967297", 32, "4294967295"); test("-4294967297", 33, "4294967295"); } #[test] fn test_rem_power_of_2() { let test = |s, v: u64, out| { let u = Integer::from_str(s).unwrap(); let mut n = u.clone(); n.rem_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().rem_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).rem_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 0, "0"); test("2", 1, "0"); test("260", 8, "4"); test("1611", 4, "11"); test("123", 100, "123"); test("1000000000000", 0, "0"); test("1000000000000", 12, "0"); test("1000000000001", 12, "1"); test("999999999999", 12, "4095"); test("1000000000000", 15, "4096"); test("1000000000000", 100, "1000000000000"); test("1000000000000000000000000", 40, "1020608380928"); test("1000000000000000000000000", 64, "2003764205206896640"); test("2147483647", 30, "1073741823"); test("2147483647", 31, "2147483647"); test("2147483647", 32, "2147483647"); test("2147483648", 30, "0"); test("2147483648", 31, "0"); test("2147483648", 32, "2147483648"); test("2147483649", 30, "1"); test("2147483649", 31, "1"); test("2147483649", 32, "2147483649"); test("4294967295", 31, "2147483647"); test("4294967295", 32, "4294967295"); test("4294967295", 33, "4294967295"); test("4294967296", 31, "0"); test("4294967296", 32, "0"); test("4294967296", 33, "4294967296"); test("4294967297", 31, "1"); test("4294967297", 32, "1"); test("4294967297", 33, "4294967297"); test("-2", 1, "0"); test("-260", 8, "-4"); test("-1611", 4, "-11"); test("-123", 100, "-123"); test("-1000000000000", 0, "0"); test("-1000000000000", 12, "0"); test("-1000000000001", 12, "-1"); test("-999999999999", 12, "-4095"); test("-1000000000000", 15, "-4096"); test("-1000000000000", 100, "-1000000000000"); test("-1000000000000000000000000", 40, "-1020608380928"); test("-1000000000000000000000000", 64, "-2003764205206896640"); test("-2147483647", 30, "-1073741823"); test("-2147483647", 31, "-2147483647"); test("-2147483647", 32, "-2147483647"); test("-2147483648", 30, "0"); test("-2147483648", 31, "0"); test("-2147483648", 32, "-2147483648"); test("-2147483649", 30, "-1"); test("-2147483649", 31, "-1"); test("-2147483649", 32, "-2147483649"); test("-4294967295", 31, "-2147483647"); test("-4294967295", 32, "-4294967295"); test("-4294967295", 33, "-4294967295"); test("-4294967296", 31, "0"); test("-4294967296", 32, "0"); test("-4294967296", 33, "-4294967296"); test("-4294967297", 31, "-1"); test("-4294967297", 32, "-1"); test("-4294967297", 33, "-4294967297"); } #[test] fn test_ceiling_mod_power_of_2() { let test = |s, v: u64, out| { let u = Integer::from_str(s).unwrap(); let mut n = u.clone(); n.ceiling_mod_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().ceiling_mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).ceiling_mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 0, "0"); test("2", 1, "0"); test("260", 8, "-252"); test("1611", 4, "-5"); test("123", 100, "-1267650600228229401496703205253"); test("1000000000000", 0, "0"); test("1000000000000", 12, "0"); test("1000000000001", 12, "-4095"); test("999999999999", 12, "-1"); test("1000000000000", 15, "-28672"); test("1000000000000", 100, "-1267650600228229400496703205376"); test("1000000000000000000000000", 40, "-78903246848"); test("1000000000000000000000000", 64, "-16442979868502654976"); test("2147483647", 30, "-1"); test("2147483647", 31, "-1"); test("2147483647", 32, "-2147483649"); test("2147483648", 30, "0"); test("2147483648", 31, "0"); test("2147483648", 32, "-2147483648"); test("2147483649", 30, "-1073741823"); test("2147483649", 31, "-2147483647"); test("2147483649", 32, "-2147483647"); test("4294967295", 31, "-1"); test("4294967295", 32, "-1"); test("4294967295", 33, "-4294967297"); test("4294967296", 31, "0"); test("4294967296", 32, "0"); test("4294967296", 33, "-4294967296"); test("4294967297", 31, "-2147483647"); test("4294967297", 32, "-4294967295"); test("4294967297", 33, "-4294967295"); test("-2", 1, "0"); test("-260", 8, "-4"); test("-1611", 4, "-11"); test("-123", 100, "-123"); test("-1000000000000", 0, "0"); test("-1000000000000", 12, "0"); test("-1000000000001", 12, "-1"); test("-999999999999", 12, "-4095"); test("-1000000000000", 15, "-4096"); test("-1000000000000", 100, "-1000000000000"); test("-1000000000000000000000000", 40, "-1020608380928"); test("-1000000000000000000000000", 64, "-2003764205206896640"); test("-2147483647", 30, "-1073741823"); test("-2147483647", 31, "-2147483647"); test("-2147483647", 32, "-2147483647"); test("-2147483648", 30, "0"); test("-2147483648", 31, "0"); test("-2147483648", 32, "-2147483648"); test("-2147483649", 30, "-1"); test("-2147483649", 31, "-1"); test("-2147483649", 32, "-2147483649"); test("-4294967295", 31, "-2147483647"); test("-4294967295", 32, "-4294967295"); test("-4294967295", 33, "-4294967295"); test("-4294967296", 31, "0"); test("-4294967296", 32, "0"); test("-4294967296", 33, "-4294967296"); test("-4294967297", 31, "-1"); test("-4294967297", 32, "-1"); test("-4294967297", 33, "-4294967297"); } #[test] fn mod_power_of_2_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n.mod_power_of_2_assign(u); assert!(mut_n.is_valid()); let result = mut_n; let result_alt = (&n).mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!((&n >> u << u) + &result, n); assert!(result < Natural::power_of_2(u)); assert_eq!(result == 0, n.divisible_by_power_of_2(u)); assert_eq!((&result).mod_power_of_2(u), result); assert_eq!(n & Integer::low_mask(u), result); }); integer_integer_unsigned_triple_gen_var_1().test_properties(|(ref x, ref y, u)| { let xm = Integer::from(x.mod_power_of_2(u)); let ym = Integer::from(y.mod_power_of_2(u)); assert_eq!((x + y).mod_power_of_2(u), (&xm + &ym).mod_power_of_2(u)); assert_eq!((x - y).mod_power_of_2(u), (&xm - &ym).mod_power_of_2(u)); assert_eq!((x * y).mod_power_of_2(u), (xm * ym).mod_power_of_2(u)); }); integer_unsigned_pair_gen_var_4().test_properties(|(n, u)| { assert_eq!(n.mod_power_of_2(u), 0); }); integer_unsigned_pair_gen_var_5().test_properties(|(n, u)| { assert_ne!((&n).mod_power_of_2(u), 0); assert_eq!( Integer::from((&n).mod_power_of_2(u)) - n.ceiling_mod_power_of_2(u), Natural::power_of_2(u) ); }); integer_unsigned_unsigned_triple_gen_var_3().test_properties(|(n, u, v)| { assert_eq!( (&n).mod_power_of_2(u).mod_power_of_2(v), n.mod_power_of_2(min(u, v)) ); }); signed_unsigned_pair_gen_var_10::().test_properties(|(i, pow)| { assert_eq!(i.mod_power_of_2(pow), Integer::from(i).mod_power_of_2(pow)); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, pow)| { assert_eq!( (&n).mod_power_of_2(pow), Integer::from(n).mod_power_of_2(pow) ); }); integer_gen().test_properties(|n| { assert_eq!(n.mod_power_of_2(0), 0); }); unsigned_gen().test_properties(|u| { assert_eq!(Integer::ZERO.mod_power_of_2(u), 0); }); } #[test] fn rem_power_of_2_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n.rem_power_of_2_assign(u); assert!(mut_n.is_valid()); let result = mut_n; let result_alt = (&n).rem_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().rem_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert!(result.le_abs(&n)); assert_eq!((((&n).shr_round(u, Down).0 << u) + &result), n); assert!(result.lt_abs(&Natural::power_of_2(u))); assert_eq!(result == 0, (&n).divisible_by_power_of_2(u)); assert_eq!((&result).rem_power_of_2(u), result); assert_eq!(n.abs().mod_power_of_2(u), result.abs()); }); integer_unsigned_pair_gen_var_4().test_properties(|(n, u)| { assert_eq!(n.rem_power_of_2(u), 0); }); integer_unsigned_pair_gen_var_5().test_properties(|(n, u)| { assert_ne!((&n).rem_power_of_2(u), 0); assert_eq!((&n).rem_power_of_2(u).sign(), n.sign()); }); integer_unsigned_unsigned_triple_gen_var_3().test_properties(|(n, u, v)| { assert_eq!( (&n).rem_power_of_2(u).rem_power_of_2(v), n.rem_power_of_2(min(u, v)) ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(i, pow)| { assert_eq!(i.rem_power_of_2(pow), Integer::from(i).rem_power_of_2(pow)); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, pow)| { assert_eq!( (&n).rem_power_of_2(pow), Integer::from(n).rem_power_of_2(pow) ); }); integer_gen().test_properties(|n| { assert_eq!(n.rem_power_of_2(0), 0); }); unsigned_gen().test_properties(|u| { assert_eq!(Integer::ZERO.rem_power_of_2(u), 0); }); } #[test] fn ceiling_mod_power_of_2_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n.ceiling_mod_power_of_2_assign(u); assert!(mut_n.is_valid()); let result = mut_n; let result_alt = (&n).ceiling_mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().ceiling_mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!((((&n).shr_round(u, Ceiling).0 << u) + &result), n); assert!(result <= 0); assert!(-&result <= Natural::power_of_2(u)); assert_eq!(result == 0, (&n).divisible_by_power_of_2(u)); assert_eq!((-n).mod_power_of_2(u), -result); }); integer_integer_unsigned_triple_gen_var_1().test_properties(|(ref x, ref y, u)| { let xm = Integer::from(x.mod_power_of_2(u)); let ym = Integer::from(y.mod_power_of_2(u)); assert_eq!( (x + y).ceiling_mod_power_of_2(u), (&xm + &ym).ceiling_mod_power_of_2(u) ); assert_eq!( (x - y).ceiling_mod_power_of_2(u), (&xm - &ym).ceiling_mod_power_of_2(u) ); assert_eq!( (x * y).ceiling_mod_power_of_2(u), (xm * ym).ceiling_mod_power_of_2(u) ); }); integer_unsigned_pair_gen_var_4().test_properties(|(n, u)| { assert_eq!(n.ceiling_mod_power_of_2(u), 0); }); integer_unsigned_pair_gen_var_5().test_properties(|(n, u)| { assert_ne!(n.ceiling_mod_power_of_2(u), 0); }); signed_unsigned_pair_gen_var_11::().test_properties(|(i, pow)| { assert_eq!( i.ceiling_mod_power_of_2(pow), Integer::from(i).ceiling_mod_power_of_2(pow) ); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, pow)| { assert_eq!( -(&n).neg_mod_power_of_2(pow), Integer::from(n).ceiling_mod_power_of_2(pow) ); }); integer_gen().test_properties(|n| { assert_eq!(n.ceiling_mod_power_of_2(0), 0); }); unsigned_gen().test_properties(|u| { assert_eq!(Integer::ZERO.ceiling_mod_power_of_2(u), 0); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase2, DivMod, PowerOf2, Square, UnsignedAbs, }; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::test_util::generators::signed_pair_gen; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{SignedDoubleLimb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, integer_vec_gen, natural_pair_gen, natural_vec_gen, }; use malachite_nz::test_util::integer::arithmetic::mul::integer_product_naive; use num::BigInt; use std::iter::{Product, once}; use std::str::FromStr; #[test] fn test_mul() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n *= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n *= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigInt::from_str(s).unwrap() * BigInt::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() * rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "0"); test("0", "-123", "0"); test("123", "0", "0"); test("-123", "0", "0"); test("1", "123", "123"); test("1", "-123", "-123"); test("-1", "123", "-123"); test("-1", "-123", "123"); test("123", "1", "123"); test("123", "-1", "-123"); test("-123", "1", "-123"); test("-123", "-1", "123"); test("123", "456", "56088"); test("123", "-456", "-56088"); test("-123", "456", "-56088"); test("-123", "-456", "56088"); test("0", "1000000000000", "0"); test("0", "-1000000000000", "0"); test("1000000000000", "0", "0"); test("-1000000000000", "0", "0"); test("1", "1000000000000", "1000000000000"); test("1", "-1000000000000", "-1000000000000"); test("-1", "1000000000000", "-1000000000000"); test("-1", "-1000000000000", "1000000000000"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "-1", "-1000000000000"); test("-1000000000000", "1", "-1000000000000"); test("-1000000000000", "-1", "1000000000000"); test("1000000000000", "123", "123000000000000"); test("1000000000000", "-123", "-123000000000000"); test("-1000000000000", "123", "-123000000000000"); test("-1000000000000", "-123", "123000000000000"); test("123", "1000000000000", "123000000000000"); test("123", "-1000000000000", "-123000000000000"); test("-123", "1000000000000", "-123000000000000"); test("-123", "-1000000000000", "123000000000000"); test("123456789000", "987654321000", "121932631112635269000000"); test("123456789000", "-987654321000", "-121932631112635269000000"); test("-123456789000", "987654321000", "-121932631112635269000000"); test("-123456789000", "-987654321000", "121932631112635269000000"); test("4294967295", "2", "8589934590"); test("4294967295", "-2", "-8589934590"); test("-4294967295", "2", "-8589934590"); test("-4294967295", "-2", "8589934590"); test("4294967295", "4294967295", "18446744065119617025"); test("4294967295", "-4294967295", "-18446744065119617025"); test("-4294967295", "4294967295", "-18446744065119617025"); test("-4294967295", "-4294967295", "18446744065119617025"); test("18446744073709551615", "2", "36893488147419103230"); test("18446744073709551615", "-2", "-36893488147419103230"); test("-18446744073709551615", "2", "-36893488147419103230"); test("-18446744073709551615", "-2", "36893488147419103230"); let large_power_of_2 = Integer::power_of_2(100_000) * Integer::power_of_2(100_000); assert!(large_power_of_2.is_valid()); assert_eq!( large_power_of_2.unsigned_abs().checked_log_base_2(), Some(200_000) ); } #[test] fn test_product() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let product = Integer::product(xs.iter().cloned()); assert!(product.is_valid()); assert_eq!(product.to_string(), out); let product_alt = Integer::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = integer_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }; test("[]", "1"); test("[10]", "10"); test("[6, -2]", "-12"); test("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "0"); test("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "3628800"); test( "[123456, -789012, 345678, -9012345]", "303462729062737285547520", ); } #[test] fn mul_properties() { integer_pair_gen().test_properties(|(x, y)| { let product_val_val = x.clone() * y.clone(); let product_val_ref = x.clone() * &y; let product_ref_val = &x * y.clone(); let product = &x * &y; assert!(product_val_val.is_valid()); assert!(product_val_ref.is_valid()); assert!(product_ref_val.is_valid()); assert!(product.is_valid()); assert_eq!(product_val_val, product); assert_eq!(product_val_ref, product); assert_eq!(product_ref_val, product); let mut mut_x = x.clone(); mut_x *= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x *= &y; assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x *= rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), product); assert_eq!( Integer::from(&(BigInt::from(&x) * BigInt::from(&y))), product ); assert_eq!( Integer::from(&(rug::Integer::from(&x) * rug::Integer::from(&y))), product ); assert_eq!(&y * &x, product); if x != 0 { let (q, r) = (&product).div_mod(&x); assert_eq!(q, y); assert_eq!(r, 0); } if y != 0 { let (q, r) = (&product).div_mod(&y); assert_eq!(q, x); assert_eq!(r, 0); } assert_eq!(-&x * &y, -&product); assert_eq!(x * -y, -product); }); integer_gen().test_properties(|ref x| { assert_eq!(x * Integer::ZERO, 0); assert_eq!(Integer::ZERO * x, 0); assert_eq!(x * Integer::ONE, *x); assert_eq!(Integer::ONE * x, *x); assert_eq!(x * Integer::NEGATIVE_ONE, -x); assert_eq!(Integer::NEGATIVE_ONE * x, -x); assert_eq!(x * x, x.square()); }); integer_triple_gen().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x * y) * z, x * (y * z)); assert_eq!(x * (y + z), x * y + x * z); assert_eq!((x + y) * z, x * z + y * z); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(&x * &y, Integer::from(x) * Integer::from(y)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(SignedDoubleLimb::from(x) * SignedDoubleLimb::from(y)), Integer::from(x) * Integer::from(y) ); }); } #[test] fn product_properties() { integer_vec_gen().test_properties(|xs| { let product = Integer::product(xs.iter().cloned()); assert!(product.is_valid()); let product_alt = Integer::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = integer_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }); integer_gen().test_properties(|x| { assert_eq!(Integer::product(once(&x)), x); assert_eq!(Integer::product(once(x.clone())), x); }); integer_pair_gen().test_properties(|(x, y)| { let product = &x * &y; assert_eq!(Integer::product([&x, &y].into_iter()), product); assert_eq!(Integer::product([x, y].into_iter()), product); }); natural_vec_gen().test_properties(|xs| { assert_eq!( Integer::product(xs.iter().map(Integer::from)), Integer::from(Natural::product(xs.into_iter())) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::{SignedDoubleLimb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, natural_gen}; use num::BigInt; use std::str::FromStr; #[test] fn test_neg() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); let neg = -u.clone(); assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); let neg = -&u; assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); assert_eq!((-BigInt::from_str(s).unwrap()).to_string(), out); assert_eq!((-rug::Integer::from_str(s).unwrap()).to_string(), out); let mut x = u; x.neg_assign(); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "0"); test("123", "-123"); test("-123", "123"); test("1000000000000", "-1000000000000"); test("-1000000000000", "1000000000000"); test("-2147483648", "2147483648"); test("2147483648", "-2147483648"); } #[test] fn neg_properties() { integer_gen().test_properties(|x| { let negative = -x.clone(); assert!(negative.is_valid()); assert!(negative.is_valid()); let negative_alt = -&x; assert!(negative_alt.is_valid()); assert_eq!(negative_alt, negative); assert_eq!(Integer::from(&-BigInt::from(&x)), negative); assert_eq!(Integer::from(&-rug::Integer::from(&x)), negative); assert_eq!(negative == x, x == 0); assert_eq!(-&negative, x); assert_eq!(x + negative, 0); }); signed_gen::().test_properties(|x| { assert_eq!(Integer::from(-SignedDoubleLimb::from(x)), -Integer::from(x)); }); natural_gen().test_properties(|x| { assert_eq!(-&x, -Integer::from(x)); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, DivisibleByPowerOf2, Parity}; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::integer_gen; use std::str::FromStr; #[test] fn test_even() { let test = |n, out| { assert_eq!(Integer::from_str(n).unwrap().even(), out); }; test("0", true); test("1", false); test("2", true); test("3", false); test("123", false); test("1000000000000", true); test("1000000000001", false); test("-1", false); test("-2", true); test("-3", false); test("-123", false); test("-1000000000000", true); test("-1000000000001", false); } #[test] fn test_odd() { let test = |n, out| { assert_eq!(Integer::from_str(n).unwrap().odd(), out); }; test("0", false); test("1", true); test("2", false); test("3", true); test("123", true); test("1000000000000", false); test("1000000000001", true); test("-1", true); test("-2", false); test("-3", true); test("-123", true); test("-1000000000000", false); test("-1000000000001", true); } #[test] fn even_properties() { integer_gen().test_properties(|ref x| { let even = x.even(); assert_eq!(!x.odd(), even); assert_eq!(x.divisible_by(Integer::TWO), even); assert_eq!(x.divisible_by_power_of_2(1), even); assert_eq!((x + Integer::ONE).odd(), even); assert_eq!((x - Integer::ONE).odd(), even); assert_eq!((-x).even(), even); }); signed_gen::().test_properties(|i| { assert_eq!(i.even(), Integer::from(i).even()); }); } #[test] fn odd_properties() { integer_gen().test_properties(|ref x| { let odd = x.odd(); assert_eq!(!x.even(), odd); assert_eq!(!x.divisible_by(Integer::TWO), odd); assert_eq!(!(x).divisible_by_power_of_2(1), odd); assert_eq!((x + Integer::ONE).even(), odd); assert_eq!((x - Integer::ONE).even(), odd); assert_eq!((-x).odd(), odd); }); signed_gen::().test_properties(|i| { assert_eq!(i.odd(), Integer::from(i).odd()); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedRoot, Parity, Pow, PowAssign, PowerOf2, Square, }; use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_unsigned_pair_gen_var_15, unsigned_gen_var_5}; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_unsigned_triple_gen_var_1, integer_unsigned_pair_gen_var_2, integer_unsigned_unsigned_triple_gen_var_3, natural_unsigned_pair_gen_var_4, }; use num::BigInt; use num::traits::Pow as NumPow; use rug::ops::Pow as RugPow; use std::str::FromStr; #[test] fn test_pow() { let test = |s, exp, out| { let u = Integer::from_str(s).unwrap(); let mut x = u.clone(); x.pow_assign(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = u.clone().pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = (&u).pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = BigInt::from_str(s).unwrap().pow(exp); assert_eq!(x.to_string(), out); let x = rug::Integer::from_str(s).unwrap().pow(u32::exact_from(exp)); assert_eq!(x.to_string(), out); }; test("0", 0, "1"); test("1", 0, "1"); test("2", 0, "1"); test("1000", 0, "1"); test("1000000000000", 0, "1"); test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("1000", 1, "1000"); test("1000000000000", 1, "1000000000000"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "4"); test("3", 2, "9"); test("1000", 2, "1000000"); test("1000000000000", 2, "1000000000000000000000000"); test( "123", 456, "992500687720988567008314620574696326372959408198869005198162988813828671047493990779211286\ 6142614463805542423693627187249280035274164990211814381967260156999810012079049675951763646\ 5445895625741609866209900500198407153244604778968016963028050310261417615914468729918240685\ 4878786176459769390634643579861657117309763994785076492286863414669671679101266533421349427\ 4485146389992748709248661097714611276356710167264595313219648143933987301708814041466127119\ 8500333255713096142335151414630651683065518784081203678487703002802082091236603519026256880\ 6244996817813872275740354848312715156831237421490955692604636096559777009388445806119312464\ 9516620869554031369814001163802732256625268978083813635182879531427216211122223117090171561\ 2355701347552371530013693855379834865667060014643302459100429783653966913783002290784283455\ 6282833554705299329560514844771293338811599302127586876027950885792304316616960102321873904\ 36601614145603241902386663442520160735566561", ); test( "123", 457, "122077584589681593742022698330687648143874007208460887639374047624100926538841760865842988\ 2535541579048081718114316144031661444338722293796053168981972999310976631485723110142066928\ 5249845161966218013543817761524404079849086387813066086452450188162154366757479653779943604\ 3150090699704551635048061160322983825429100971358564408551284200004369616529455783610825979\ 5761673005969108091237585315018897186991875350573545223526016721703880438110184127100333635\ 7415540990452710825507223623999570157017058810441988052453987469344656097222102232840229596\ 3168134608591106289916063646342463964290242202843387550190370239876852572154778834152675433\ 1890544366955145858487122143147736067564908084304309077127494182365547593968033443402091102\ 0319751265748941698191684344211719688477048381801126202469352863389437930395309281766466865\ 0422788527228751817535943325906869080673826714161693185751437958952453430943886092585590490\ 23701998539909198753993559603429979770474687003", ); test( "10", 100, "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000", ); test( "10", 101, "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", ); test("2", 100, "1267650600228229401496703205376"); test( "12345678987654321", 5, "286797196211272153445658333952148540084053148773966942500383143133144940612575601", ); test( "12345678987654321", 6, "354070611898367606555445954656918550154832595750628623501854823341167403514406003590115726\ 6821921", ); test("-1", 0, "1"); test("-2", 0, "1"); test("-1000", 0, "1"); test("-1000000000000", 0, "1"); test("-1", 1, "-1"); test("-2", 1, "-2"); test("-1000", 1, "-1000"); test("-1000000000000", 1, "-1000000000000"); test("-1", 2, "1"); test("-2", 2, "4"); test("-3", 2, "9"); test("-1000", 2, "1000000"); test("-1000000000000", 2, "1000000000000000000000000"); test( "-123", 456, "992500687720988567008314620574696326372959408198869005198162988813828671047493990779211286\ 6142614463805542423693627187249280035274164990211814381967260156999810012079049675951763646\ 5445895625741609866209900500198407153244604778968016963028050310261417615914468729918240685\ 4878786176459769390634643579861657117309763994785076492286863414669671679101266533421349427\ 4485146389992748709248661097714611276356710167264595313219648143933987301708814041466127119\ 8500333255713096142335151414630651683065518784081203678487703002802082091236603519026256880\ 6244996817813872275740354848312715156831237421490955692604636096559777009388445806119312464\ 9516620869554031369814001163802732256625268978083813635182879531427216211122223117090171561\ 2355701347552371530013693855379834865667060014643302459100429783653966913783002290784283455\ 6282833554705299329560514844771293338811599302127586876027950885792304316616960102321873904\ 36601614145603241902386663442520160735566561", ); test( "-123", 457, "-12207758458968159374202269833068764814387400720846088763937404762410092653884176086584298\ 8253554157904808171811431614403166144433872229379605316898197299931097663148572311014206692\ 8524984516196621801354381776152440407984908638781306608645245018816215436675747965377994360\ 4315009069970455163504806116032298382542910097135856440855128420000436961652945578361082597\ 9576167300596910809123758531501889718699187535057354522352601672170388043811018412710033363\ 5741554099045271082550722362399957015701705881044198805245398746934465609722210223284022959\ 6316813460859110628991606364634246396429024220284338755019037023987685257215477883415267543\ 3189054436695514585848712214314773606756490808430430907712749418236554759396803344340209110\ 2031975126574894169819168434421171968847704838180112620246935286338943793039530928176646686\ 5042278852722875181753594332590686908067382671416169318575143795895245343094388609258559049\ 023701998539909198753993559603429979770474687003", ); test( "-10", 100, "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000", ); test( "-10", 101, "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000", ); test("-2", 100, "1267650600228229401496703205376"); test( "-12345678987654321", 5, "-286797196211272153445658333952148540084053148773966942500383143133144940612575601", ); test( "-12345678987654321", 6, "354070611898367606555445954656918550154832595750628623501854823341167403514406003590115726\ 6821921", ); } #[test] fn pow_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(x, exp)| { let power = (&x).pow(exp); assert!(power.is_valid()); let power_alt = x.clone().pow(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let mut power_alt = x.clone(); power_alt.pow_assign(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let power_of_neg = (-&x).pow(exp); if exp.even() { assert_eq!(power_of_neg, power); } else { assert_eq!(power_of_neg, -&power); } if exp > 0 && (x >= 0 || exp.odd()) { assert_eq!((&power).checked_root(exp).as_ref(), Some(&x)); } assert_eq!(Integer::from(&BigInt::from(&x).pow(exp)), power); assert_eq!( Integer::from(&rug::Integer::from(&x).pow(u32::exact_from(exp))), power ); }); integer_gen().test_properties(|x| { assert_eq!((&x).pow(0), 1); assert_eq!((&x).pow(1), x); assert_eq!((&x).pow(2), x.square()); }); unsigned_gen_var_5().test_properties(|exp| { assert_eq!(Integer::ZERO.pow(exp), u64::from(exp == 0)); assert_eq!(Integer::ONE.pow(exp), 1); assert_eq!(Integer::TWO.pow(exp), Integer::power_of_2(exp)); assert_eq!( Integer::NEGATIVE_ONE.pow(exp), if exp.even() { 1 } else { -1 } ); }); integer_integer_unsigned_triple_gen_var_1().test_properties(|(x, y, exp)| { assert_eq!((&x * &y).pow(exp), x.pow(exp) * y.pow(exp)); }); integer_unsigned_unsigned_triple_gen_var_3().test_properties(|(x, e, f)| { assert_eq!((&x).pow(e + f), (&x).pow(e) * (&x).pow(f)); assert_eq!((&x).pow(e * f), x.pow(e).pow(f)); }); natural_unsigned_pair_gen_var_4().test_properties(|(x, exp)| { assert_eq!((&x).pow(exp), Integer::from(x).pow(exp)); }); signed_unsigned_pair_gen_var_15::().test_properties(|(x, exp)| { assert_eq!(Pow::pow(x, exp), Integer::from(x).pow(exp)); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, LowMask}; use malachite_base::test_util::generators::{unsigned_gen_var_5, unsigned_gen_var_16}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; #[test] fn test_power_of_2() { let test = |pow, out| assert_eq!(Integer::power_of_2(pow).to_string(), out); test(0, "1"); test(1, "2"); test(2, "4"); test(3, "8"); test(32, "4294967296"); test(100, "1267650600228229401496703205376"); } #[test] fn power_of_2_properties() { unsigned_gen_var_5().test_properties(|pow| { let n = Integer::power_of_2(pow); assert!(n.is_valid()); assert_eq!(n, Integer::ONE << pow); assert_eq!(n, Integer::low_mask(pow) + Integer::ONE); assert_eq!(Natural::exact_from(&n), Natural::power_of_2(pow)); let mut n = n; n.clear_bit(pow); assert_eq!(n, 0); }); unsigned_gen_var_16::().test_properties(|pow| { assert_eq!(SignedLimb::power_of_2(pow), Integer::power_of_2(pow)); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CeilingSqrt, CheckedRoot, CheckedSqrt, FloorRoot, FloorRootAssign, FloorSqrt, Parity, Pow, }; use malachite_base::num::basic::traits::{NegativeOne, One}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen, signed_unsigned_pair_gen_var_18}; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_4, integer_unsigned_pair_gen_var_3, natural_gen, natural_unsigned_pair_gen_var_7, }; use num::BigInt; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_floor_root() { let test = |s, exp, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.clone().floor_root(exp).to_string(), out); assert_eq!((&n).floor_root(exp).to_string(), out); let mut n = n; n.floor_root_assign(exp); assert_eq!(n.to_string(), out); }; test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("100", 1, "100"); test("0", 2, "0"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "1"); test("3", 2, "1"); test("4", 2, "2"); test("5", 2, "2"); test("0", 3, "0"); test("1", 3, "1"); test("2", 3, "1"); test("7", 3, "1"); test("8", 3, "2"); test("9", 3, "2"); test("10", 2, "3"); test("100", 2, "10"); test("100", 3, "4"); test("1000000000", 2, "31622"); test("1000000000", 3, "1000"); test("1000000000", 4, "177"); test("1000000000", 5, "63"); test("1000000000", 6, "31"); test("1000000000", 7, "19"); test("1000000000", 8, "13"); test("1000000000", 9, "10"); test("1000000000", 10, "7"); test("-1", 1, "-1"); test("-2", 1, "-2"); test("-100", 1, "-100"); test("-1", 3, "-1"); test("-2", 3, "-2"); test("-7", 3, "-2"); test("-8", 3, "-2"); test("-9", 3, "-3"); test("-100", 3, "-5"); test("-1000000000", 3, "-1000"); test("-1000000000", 5, "-64"); test("-1000000000", 7, "-20"); test("-1000000000", 9, "-10"); } #[test] fn floor_root_fail() { assert_panic!(Integer::ONE.floor_root(0)); assert_panic!(Integer::NEGATIVE_ONE.floor_root(0)); assert_panic!(Integer::NEGATIVE_ONE.floor_root(2)); assert_panic!(Integer::NEGATIVE_ONE.floor_root(4)); assert_panic!(Integer::NEGATIVE_ONE.floor_root(100)); } #[test] fn floor_root_ref_fail() { assert_panic!((&Integer::ONE).floor_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).floor_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).floor_root(2)); assert_panic!((&Integer::NEGATIVE_ONE).floor_root(4)); assert_panic!((&Integer::NEGATIVE_ONE).floor_root(100)); } #[test] fn floor_root_assign_fail() { assert_panic!({ let mut x = Integer::ONE; x.floor_root_assign(0); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.floor_root_assign(0); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.floor_root_assign(2); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.floor_root_assign(4); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.floor_root_assign(100); }); } #[test] fn test_ceiling_root() { let test = |s, exp, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.clone().ceiling_root(exp).to_string(), out); assert_eq!((&n).ceiling_root(exp).to_string(), out); let mut n = n; n.ceiling_root_assign(exp); assert_eq!(n.to_string(), out); }; test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("100", 1, "100"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "2"); test("3", 2, "2"); test("4", 2, "2"); test("5", 2, "3"); test("0", 3, "0"); test("1", 3, "1"); test("2", 3, "2"); test("7", 3, "2"); test("8", 3, "2"); test("9", 3, "3"); test("10", 2, "4"); test("100", 2, "10"); test("100", 3, "5"); test("1000000000", 2, "31623"); test("1000000000", 3, "1000"); test("1000000000", 4, "178"); test("1000000000", 5, "64"); test("1000000000", 6, "32"); test("1000000000", 7, "20"); test("1000000000", 8, "14"); test("1000000000", 9, "10"); test("1000000000", 10, "8"); test("-1", 1, "-1"); test("-2", 1, "-2"); test("-100", 1, "-100"); test("-1", 3, "-1"); test("-2", 3, "-1"); test("-7", 3, "-1"); test("-8", 3, "-2"); test("-9", 3, "-2"); test("-100", 3, "-4"); test("-1000000000", 3, "-1000"); test("-1000000000", 5, "-63"); test("-1000000000", 7, "-19"); test("-1000000000", 9, "-10"); } #[test] fn ceiling_root_fail() { assert_panic!(Integer::ONE.ceiling_root(0)); assert_panic!(Integer::NEGATIVE_ONE.ceiling_root(0)); assert_panic!(Integer::NEGATIVE_ONE.ceiling_root(2)); assert_panic!(Integer::NEGATIVE_ONE.ceiling_root(4)); assert_panic!(Integer::NEGATIVE_ONE.ceiling_root(100)); } #[test] fn ceiling_root_ref_fail() { assert_panic!((&Integer::ONE).ceiling_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).ceiling_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).ceiling_root(2)); assert_panic!((&Integer::NEGATIVE_ONE).ceiling_root(4)); assert_panic!((&Integer::NEGATIVE_ONE).ceiling_root(100)); } #[test] fn ceiling_root_assign_fail() { assert_panic!({ let mut x = Integer::ONE; x.ceiling_root_assign(0); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.ceiling_root_assign(0); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.ceiling_root_assign(2); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.ceiling_root_assign(4); }); assert_panic!({ let mut x = Integer::NEGATIVE_ONE; x.ceiling_root_assign(100); }); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_checked_root() { let test = |s, exp, out: Option<&str>| { let n = Integer::from_str(s).unwrap(); let out = out.map(|s| s.to_string()); assert_eq!(n.clone().checked_root(exp).map(|x| x.to_string()), out); assert_eq!((&n).checked_root(exp).map(|x| x.to_string()), out); }; test("0", 1, Some("0")); test("1", 1, Some("1")); test("2", 1, Some("2")); test("100", 1, Some("100")); test("0", 2, Some("0")); test("1", 2, Some("1")); test("2", 2, None); test("3", 2, None); test("4", 2, Some("2")); test("5", 2, None); test("0", 3, Some("0")); test("1", 3, Some("1")); test("2", 3, None); test("7", 3, None); test("8", 3, Some("2")); test("9", 3, None); test("10", 2, None); test("100", 2, Some("10")); test("100", 3, None); test("1000000000", 2, None); test("1000000000", 3, Some("1000")); test("1000000000", 4, None); test("1000000000", 5, None); test("1000000000", 6, None); test("1000000000", 7, None); test("1000000000", 8, None); test("1000000000", 9, Some("10")); test("1000000000", 10, None); test("-1", 1, Some("-1")); test("-2", 1, Some("-2")); test("-100", 1, Some("-100")); test("-1", 3, Some("-1")); test("-2", 3, None); test("-7", 3, None); test("-8", 3, Some("-2")); test("-9", 3, None); test("-100", 3, None); test("-1000000000", 3, Some("-1000")); test("-1000000000", 5, None); test("-1000000000", 7, None); test("-1000000000", 9, Some("-10")); } #[test] fn checked_root_fail() { assert_panic!(Integer::ONE.checked_root(0)); assert_panic!(Integer::NEGATIVE_ONE.checked_root(0)); assert_panic!(Integer::NEGATIVE_ONE.checked_root(2)); assert_panic!(Integer::NEGATIVE_ONE.checked_root(4)); assert_panic!(Integer::NEGATIVE_ONE.checked_root(100)); } #[test] fn checked_root_ref_fail() { assert_panic!((&Integer::ONE).checked_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).checked_root(0)); assert_panic!((&Integer::NEGATIVE_ONE).checked_root(2)); assert_panic!((&Integer::NEGATIVE_ONE).checked_root(4)); assert_panic!((&Integer::NEGATIVE_ONE).checked_root(100)); } #[test] fn floor_cbrt_properties() { integer_gen().test_properties(|n| { let cbrt = n.clone().floor_root(3); assert!(cbrt.is_valid()); let cbrt_alt = (&n).floor_root(3); assert!(cbrt_alt.is_valid()); assert_eq!(cbrt_alt, cbrt); let mut n_alt = n.clone(); n_alt.floor_root_assign(3); assert!(cbrt_alt.is_valid()); assert_eq!(n_alt, cbrt); if n >= 0 { assert_eq!(Integer::from(&BigInt::from(&n).nth_root(3)), cbrt); assert_eq!(Integer::from(&rug::Integer::from(&n).root(3)), cbrt); } let cube = (&cbrt).pow(3); let ceiling_cbrt = (&n).ceiling_root(3); if cube == n { assert_eq!(ceiling_cbrt, cbrt); } else { assert_eq!(ceiling_cbrt, &cbrt + Integer::ONE); } assert!(cube <= n); assert!((&cbrt + Integer::ONE).pow(3) > n); assert_eq!(-(-n).ceiling_root(3), cbrt); }); natural_gen().test_properties(|n| { assert_eq!((&n).floor_root(3), Integer::from(n).floor_root(3)); }); signed_gen::().test_properties(|i| { assert_eq!(i.floor_root(3), Integer::from(i).floor_root(3)); }); } #[test] fn ceiling_cbrt_properties() { integer_gen().test_properties(|n| { let cbrt = n.clone().ceiling_root(3); assert!(cbrt.is_valid()); let cbrt_alt = (&n).ceiling_root(3); assert!(cbrt_alt.is_valid()); assert_eq!(cbrt_alt, cbrt); let mut n_alt = n.clone(); n_alt.ceiling_root_assign(3); assert!(cbrt_alt.is_valid()); assert_eq!(n_alt, cbrt); if n < 0 { assert_eq!(Integer::from(&BigInt::from(&n).nth_root(3)), cbrt); assert_eq!(Integer::from(&rug::Integer::from(&n).root(3)), cbrt); } let cube = (&cbrt).pow(3); let floor_cbrt = (&n).floor_root(3); if cube == n { assert_eq!(floor_cbrt, cbrt); } else { assert_eq!(floor_cbrt, &cbrt - Integer::ONE); } assert!(cube >= n); if n != 0 { assert!((&cbrt - Integer::ONE).pow(3) < n); } assert_eq!(-(-n).floor_root(3), cbrt); }); natural_gen().test_properties(|n| { assert_eq!((&n).ceiling_root(3), Integer::from(n).ceiling_root(3)); }); signed_gen::().test_properties(|i| { assert_eq!(i.ceiling_root(3), Integer::from(i).ceiling_root(3)); }); } #[test] fn checked_cbrt_properties() { integer_gen().test_properties(|n| { let cbrt = n.clone().checked_root(3); assert!(cbrt.as_ref().is_none_or(Integer::is_valid)); let cbrt_alt = (&n).checked_root(3); assert!(cbrt_alt.as_ref().is_none_or(Integer::is_valid)); assert_eq!(cbrt_alt, cbrt); if let Some(cbrt) = cbrt { assert_eq!((&cbrt).pow(3), n); assert_eq!((&n).floor_root(3), cbrt); assert_eq!(n.ceiling_root(3), cbrt); } }); natural_gen().test_properties(|n| { assert_eq!( (&n).checked_root(3).map(Integer::from), Integer::from(n).checked_root(3) ); }); signed_gen::().test_properties(|i| { assert_eq!( i.checked_root(3).map(Integer::from), Integer::from(i).checked_root(3) ); }); } #[test] fn floor_root_properties() { integer_unsigned_pair_gen_var_3().test_properties(|(n, exp)| { let root = n.clone().floor_root(exp); assert!(root.is_valid()); let root_alt = (&n).floor_root(exp); assert!(root_alt.is_valid()); assert_eq!(root_alt, root); let mut n_alt = n.clone(); n_alt.floor_root_assign(exp); assert!(root_alt.is_valid()); assert_eq!(n_alt, root); if n >= 0 { assert_eq!( Integer::from(&BigInt::from(&n).nth_root(u32::exact_from(exp))), root ); assert_eq!( Integer::from(&rug::Integer::from(&n).root(u32::exact_from(exp))), root ); } let pow = (&root).pow(exp); let ceiling_root = (&n).ceiling_root(exp); if pow == n { assert_eq!(ceiling_root, root); } else { assert_eq!(ceiling_root, &root + Integer::ONE); } assert!(pow <= n); assert!((&root + Integer::ONE).pow(exp) > n); if exp.odd() { assert_eq!(-(-n).ceiling_root(exp), root); } }); integer_gen().test_properties(|n| { assert_eq!((&n).floor_root(1), n); }); integer_gen_var_4().test_properties(|n| { assert_eq!((&n).floor_root(2), (&n).floor_sqrt()); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { assert_eq!((&n).floor_root(exp), Integer::from(n).floor_root(exp)); }); signed_unsigned_pair_gen_var_18::().test_properties(|(i, exp)| { assert_eq!(i.floor_root(exp), Integer::from(i).floor_root(exp)); }); } #[test] fn ceiling_root_properties() { integer_unsigned_pair_gen_var_3().test_properties(|(n, exp)| { let root = n.clone().ceiling_root(exp); assert!(root.is_valid()); let root_alt = (&n).ceiling_root(exp); assert!(root_alt.is_valid()); assert_eq!(root_alt, root); let mut n_alt = n.clone(); n_alt.ceiling_root_assign(exp); assert!(root_alt.is_valid()); assert_eq!(n_alt, root); if n < 0 { assert_eq!( Integer::from(&BigInt::from(&n).nth_root(u32::exact_from(exp))), root ); assert_eq!( Integer::from(&rug::Integer::from(&n).root(u32::exact_from(exp))), root ); } let pow = (&root).pow(exp); let floor_root = (&n).floor_root(exp); if pow == n { assert_eq!(floor_root, root); } else { assert_eq!(floor_root, &root - Integer::ONE); } assert!(pow >= n); if n != 0 { assert!((&root - Integer::ONE).pow(exp) < n); } if exp.odd() { assert_eq!(-(-n).floor_root(exp), root); } }); integer_gen().test_properties(|n| { assert_eq!((&n).ceiling_root(1), n); }); integer_gen_var_4().test_properties(|n| { assert_eq!((&n).ceiling_root(2), (&n).ceiling_sqrt()); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { assert_eq!((&n).ceiling_root(exp), Integer::from(n).ceiling_root(exp)); }); signed_unsigned_pair_gen_var_18::().test_properties(|(i, exp)| { assert_eq!(i.ceiling_root(exp), Integer::from(i).ceiling_root(exp)); }); } #[test] fn checked_root_properties() { integer_unsigned_pair_gen_var_3().test_properties(|(n, exp)| { let root = n.clone().checked_root(exp); assert!(root.as_ref().is_none_or(Integer::is_valid)); let root_alt = (&n).checked_root(exp); assert!(root_alt.as_ref().is_none_or(Integer::is_valid)); assert_eq!(root_alt, root); if let Some(root) = root { assert_eq!((&root).pow(exp), n); assert_eq!((&n).floor_root(exp), root); assert_eq!(n.ceiling_root(exp), root); } }); integer_gen().test_properties(|n| { assert_eq!((&n).checked_root(1), Some(n)); }); integer_gen_var_4().test_properties(|n| { assert_eq!((&n).checked_root(2), (&n).checked_sqrt()); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { assert_eq!( (&n).checked_root(exp).map(Integer::from), Integer::from(n).checked_root(exp) ); }); signed_unsigned_pair_gen_var_18::().test_properties(|(i, exp)| { assert_eq!( i.checked_root(exp).map(Integer::from), Integer::from(i).checked_root(exp) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, DivRound, DivisibleBy, Parity, RoundToMultiple, RoundToMultipleAssign, }; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::signed_signed_rounding_mode_triple_gen_var_2; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_integer_rounding_mode_triple_gen_var_2, integer_pair_gen_var_1, integer_pair_gen_var_3, integer_rounding_mode_pair_gen, natural_natural_rounding_mode_triple_gen_var_2, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_round_to_multiple() { let test = |s, t, rm, multiple, o| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); assert_eq!(n.round_to_multiple_assign(v.clone(), rm), o); assert_eq!(n.to_string(), multiple); assert!(n.is_valid()); let mut n = u.clone(); assert_eq!(n.round_to_multiple_assign(&v, rm), o); assert_eq!(n.to_string(), multiple); assert!(n.is_valid()); let (r, o_alt) = u.clone().round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), multiple); assert_eq!(o_alt, o); let (r, o_alt) = u.clone().round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), multiple); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), multiple); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), multiple); assert_eq!(o_alt, o); }; test("0", "1", Down, "0", Equal); test("0", "1", Floor, "0", Equal); test("0", "1", Up, "0", Equal); test("0", "1", Ceiling, "0", Equal); test("0", "1", Nearest, "0", Equal); test("0", "1", Exact, "0", Equal); test("0", "123", Down, "0", Equal); test("0", "123", Floor, "0", Equal); test("0", "123", Up, "0", Equal); test("0", "123", Ceiling, "0", Equal); test("0", "123", Nearest, "0", Equal); test("0", "123", Exact, "0", Equal); test("1", "1", Down, "1", Equal); test("1", "1", Floor, "1", Equal); test("1", "1", Up, "1", Equal); test("1", "1", Ceiling, "1", Equal); test("1", "1", Nearest, "1", Equal); test("1", "1", Exact, "1", Equal); test("123", "1", Down, "123", Equal); test("123", "1", Floor, "123", Equal); test("123", "1", Up, "123", Equal); test("123", "1", Ceiling, "123", Equal); test("123", "1", Nearest, "123", Equal); test("123", "1", Exact, "123", Equal); test("123", "2", Down, "122", Less); test("123", "2", Floor, "122", Less); test("123", "2", Up, "124", Greater); test("123", "2", Ceiling, "124", Greater); test("123", "2", Nearest, "124", Greater); test("125", "2", Down, "124", Less); test("125", "2", Floor, "124", Less); test("125", "2", Up, "126", Greater); test("125", "2", Ceiling, "126", Greater); test("125", "2", Nearest, "124", Less); test("123", "123", Down, "123", Equal); test("123", "123", Floor, "123", Equal); test("123", "123", Up, "123", Equal); test("123", "123", Ceiling, "123", Equal); test("123", "123", Nearest, "123", Equal); test("123", "123", Exact, "123", Equal); test("123", "456", Down, "0", Less); test("123", "456", Floor, "0", Less); test("123", "456", Up, "456", Greater); test("123", "456", Ceiling, "456", Greater); test("123", "456", Nearest, "0", Less); test("1000000000000", "1", Down, "1000000000000", Equal); test("1000000000000", "1", Floor, "1000000000000", Equal); test("1000000000000", "1", Up, "1000000000000", Equal); test("1000000000000", "1", Ceiling, "1000000000000", Equal); test("1000000000000", "1", Nearest, "1000000000000", Equal); test("1000000000000", "1", Exact, "1000000000000", Equal); test("1000000000000", "3", Down, "999999999999", Less); test("1000000000000", "3", Floor, "999999999999", Less); test("1000000000000", "3", Up, "1000000000002", Greater); test("1000000000000", "3", Ceiling, "1000000000002", Greater); test("1000000000000", "3", Nearest, "999999999999", Less); test("999999999999", "2", Down, "999999999998", Less); test("999999999999", "2", Floor, "999999999998", Less); test("999999999999", "2", Up, "1000000000000", Greater); test("999999999999", "2", Ceiling, "1000000000000", Greater); test("999999999999", "2", Nearest, "1000000000000", Greater); test("1000000000001", "2", Down, "1000000000000", Less); test("1000000000001", "2", Floor, "1000000000000", Less); test("1000000000001", "2", Up, "1000000000002", Greater); test("1000000000001", "2", Ceiling, "1000000000002", Greater); test("1000000000001", "2", Nearest, "1000000000000", Less); test( "1000000000000000000000000", "4294967295", Down, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "4294967295", Floor, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "4294967295", Up, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "4294967295", Ceiling, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "4294967295", Nearest, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "1000000000000", Down, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Floor, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Up, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Ceiling, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Nearest, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Exact, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000001", Down, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Floor, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Up, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Ceiling, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Nearest, "999999999999999999999999", Less, ); test( "2999999999999999999999999", "2000000000000000000000000", Nearest, "2000000000000000000000000", Less, ); test( "3000000000000000000000000", "2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test( "3000000000000000000000001", "2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test("0", "-1", Down, "0", Equal); test("0", "-1", Floor, "0", Equal); test("0", "-1", Up, "0", Equal); test("0", "-1", Ceiling, "0", Equal); test("0", "-1", Nearest, "0", Equal); test("0", "-1", Exact, "0", Equal); test("0", "-123", Down, "0", Equal); test("0", "-123", Floor, "0", Equal); test("0", "-123", Up, "0", Equal); test("0", "-123", Ceiling, "0", Equal); test("0", "-123", Nearest, "0", Equal); test("0", "-123", Exact, "0", Equal); test("1", "-1", Down, "1", Equal); test("1", "-1", Floor, "1", Equal); test("1", "-1", Up, "1", Equal); test("1", "-1", Ceiling, "1", Equal); test("1", "-1", Nearest, "1", Equal); test("1", "-1", Exact, "1", Equal); test("123", "-1", Down, "123", Equal); test("123", "-1", Floor, "123", Equal); test("123", "-1", Up, "123", Equal); test("123", "-1", Ceiling, "123", Equal); test("123", "-1", Nearest, "123", Equal); test("123", "-1", Exact, "123", Equal); test("123", "-2", Down, "122", Less); test("123", "-2", Floor, "122", Less); test("123", "-2", Up, "124", Greater); test("123", "-2", Ceiling, "124", Greater); test("123", "-2", Nearest, "124", Greater); test("125", "-2", Down, "124", Less); test("125", "-2", Floor, "124", Less); test("125", "-2", Up, "126", Greater); test("125", "-2", Ceiling, "126", Greater); test("125", "-2", Nearest, "124", Less); test("123", "-123", Down, "123", Equal); test("123", "-123", Floor, "123", Equal); test("123", "-123", Up, "123", Equal); test("123", "-123", Ceiling, "123", Equal); test("123", "-123", Nearest, "123", Equal); test("123", "-123", Exact, "123", Equal); test("123", "-456", Down, "0", Less); test("123", "-456", Floor, "0", Less); test("123", "-456", Up, "456", Greater); test("123", "-456", Ceiling, "456", Greater); test("123", "-456", Nearest, "0", Less); test("1000000000000", "-1", Down, "1000000000000", Equal); test("1000000000000", "-1", Floor, "1000000000000", Equal); test("1000000000000", "-1", Up, "1000000000000", Equal); test("1000000000000", "-1", Ceiling, "1000000000000", Equal); test("1000000000000", "-1", Nearest, "1000000000000", Equal); test("1000000000000", "-1", Exact, "1000000000000", Equal); test("1000000000000", "-3", Down, "999999999999", Less); test("1000000000000", "-3", Floor, "999999999999", Less); test("1000000000000", "-3", Up, "1000000000002", Greater); test("1000000000000", "-3", Ceiling, "1000000000002", Greater); test("1000000000000", "-3", Nearest, "999999999999", Less); test("999999999999", "-2", Down, "999999999998", Less); test("999999999999", "-2", Floor, "999999999998", Less); test("999999999999", "-2", Up, "1000000000000", Greater); test("999999999999", "-2", Ceiling, "1000000000000", Greater); test("999999999999", "-2", Nearest, "1000000000000", Greater); test("1000000000001", "-2", Down, "1000000000000", Less); test("1000000000001", "-2", Floor, "1000000000000", Less); test("1000000000001", "-2", Up, "1000000000002", Greater); test("1000000000001", "-2", Ceiling, "1000000000002", Greater); test("1000000000001", "-2", Nearest, "1000000000000", Less); test( "1000000000000000000000000", "-4294967295", Down, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "-4294967295", Floor, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "-4294967295", Up, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "-4294967295", Ceiling, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "-4294967295", Nearest, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "-1000000000000", Down, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Floor, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Up, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Ceiling, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Nearest, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000000", Exact, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "-1000000000001", Down, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "-1000000000001", Floor, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "-1000000000001", Up, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "-1000000000001", Ceiling, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "-1000000000001", Nearest, "999999999999999999999999", Less, ); test( "2999999999999999999999999", "-2000000000000000000000000", Nearest, "2000000000000000000000000", Less, ); test( "3000000000000000000000000", "-2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test( "3000000000000000000000001", "-2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test("-1", "1", Down, "-1", Equal); test("-1", "1", Floor, "-1", Equal); test("-1", "1", Up, "-1", Equal); test("-1", "1", Ceiling, "-1", Equal); test("-1", "1", Nearest, "-1", Equal); test("-1", "1", Exact, "-1", Equal); test("-123", "1", Down, "-123", Equal); test("-123", "1", Floor, "-123", Equal); test("-123", "1", Up, "-123", Equal); test("-123", "1", Ceiling, "-123", Equal); test("-123", "1", Nearest, "-123", Equal); test("-123", "1", Exact, "-123", Equal); test("-123", "2", Down, "-122", Greater); test("-123", "2", Floor, "-124", Less); test("-123", "2", Up, "-124", Less); test("-123", "2", Ceiling, "-122", Greater); test("-123", "2", Nearest, "-124", Less); test("-125", "2", Down, "-124", Greater); test("-125", "2", Floor, "-126", Less); test("-125", "2", Up, "-126", Less); test("-125", "2", Ceiling, "-124", Greater); test("-125", "2", Nearest, "-124", Greater); test("-123", "123", Down, "-123", Equal); test("-123", "123", Floor, "-123", Equal); test("-123", "123", Up, "-123", Equal); test("-123", "123", Ceiling, "-123", Equal); test("-123", "123", Nearest, "-123", Equal); test("-123", "123", Exact, "-123", Equal); test("-123", "456", Down, "0", Greater); test("-123", "456", Floor, "-456", Less); test("-123", "456", Up, "-456", Less); test("-123", "456", Ceiling, "0", Greater); test("-123", "456", Nearest, "0", Greater); test("-1000000000000", "1", Down, "-1000000000000", Equal); test("-1000000000000", "1", Floor, "-1000000000000", Equal); test("-1000000000000", "1", Up, "-1000000000000", Equal); test("-1000000000000", "1", Ceiling, "-1000000000000", Equal); test("-1000000000000", "1", Nearest, "-1000000000000", Equal); test("-1000000000000", "1", Exact, "-1000000000000", Equal); test("-1000000000000", "3", Down, "-999999999999", Greater); test("-1000000000000", "3", Floor, "-1000000000002", Less); test("-1000000000000", "3", Up, "-1000000000002", Less); test("-1000000000000", "3", Ceiling, "-999999999999", Greater); test("-1000000000000", "3", Nearest, "-999999999999", Greater); test("-999999999999", "2", Down, "-999999999998", Greater); test("-999999999999", "2", Floor, "-1000000000000", Less); test("-999999999999", "2", Up, "-1000000000000", Less); test("-999999999999", "2", Ceiling, "-999999999998", Greater); test("-999999999999", "2", Nearest, "-1000000000000", Less); test("-1000000000001", "2", Down, "-1000000000000", Greater); test("-1000000000001", "2", Floor, "-1000000000002", Less); test("-1000000000001", "2", Up, "-1000000000002", Less); test("-1000000000001", "2", Ceiling, "-1000000000000", Greater); test("-1000000000001", "2", Nearest, "-1000000000000", Greater); test( "-1000000000000000000000000", "4294967295", Down, "-999999999999996832276305", Greater, ); test( "-1000000000000000000000000", "4294967295", Floor, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "4294967295", Up, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "4294967295", Ceiling, "-999999999999996832276305", Greater, ); test( "-1000000000000000000000000", "4294967295", Nearest, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "1000000000000", Down, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Floor, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Up, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Ceiling, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Nearest, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000000", Exact, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "1000000000001", Down, "-999999999999999999999999", Greater, ); test( "-1000000000000000000000000", "1000000000001", Floor, "-1000000000001000000000000", Less, ); test( "-1000000000000000000000000", "1000000000001", Up, "-1000000000001000000000000", Less, ); test( "-1000000000000000000000000", "1000000000001", Ceiling, "-999999999999999999999999", Greater, ); test( "-1000000000000000000000000", "1000000000001", Nearest, "-999999999999999999999999", Greater, ); test( "-2999999999999999999999999", "2000000000000000000000000", Nearest, "-2000000000000000000000000", Greater, ); test( "-3000000000000000000000000", "2000000000000000000000000", Nearest, "-4000000000000000000000000", Less, ); test( "-3000000000000000000000001", "2000000000000000000000000", Nearest, "-4000000000000000000000000", Less, ); test("-1", "-1", Down, "-1", Equal); test("-1", "-1", Floor, "-1", Equal); test("-1", "-1", Up, "-1", Equal); test("-1", "-1", Ceiling, "-1", Equal); test("-1", "-1", Nearest, "-1", Equal); test("-1", "-1", Exact, "-1", Equal); test("-123", "-1", Down, "-123", Equal); test("-123", "-1", Floor, "-123", Equal); test("-123", "-1", Up, "-123", Equal); test("-123", "-1", Ceiling, "-123", Equal); test("-123", "-1", Nearest, "-123", Equal); test("-123", "-1", Exact, "-123", Equal); test("-123", "-2", Down, "-122", Greater); test("-123", "-2", Floor, "-124", Less); test("-123", "-2", Up, "-124", Less); test("-123", "-2", Ceiling, "-122", Greater); test("-123", "-2", Nearest, "-124", Less); test("-125", "-2", Down, "-124", Greater); test("-125", "-2", Floor, "-126", Less); test("-125", "-2", Up, "-126", Less); test("-125", "-2", Ceiling, "-124", Greater); test("-125", "-2", Nearest, "-124", Greater); test("-123", "-123", Down, "-123", Equal); test("-123", "-123", Floor, "-123", Equal); test("-123", "-123", Up, "-123", Equal); test("-123", "-123", Ceiling, "-123", Equal); test("-123", "-123", Nearest, "-123", Equal); test("-123", "-123", Exact, "-123", Equal); test("-123", "-456", Down, "0", Greater); test("-123", "-456", Floor, "-456", Less); test("-123", "-456", Up, "-456", Less); test("-123", "-456", Ceiling, "0", Greater); test("-123", "-456", Nearest, "0", Greater); test("-1000000000000", "-1", Down, "-1000000000000", Equal); test("-1000000000000", "-1", Floor, "-1000000000000", Equal); test("-1000000000000", "-1", Up, "-1000000000000", Equal); test("-1000000000000", "-1", Ceiling, "-1000000000000", Equal); test("-1000000000000", "-1", Nearest, "-1000000000000", Equal); test("-1000000000000", "-1", Exact, "-1000000000000", Equal); test("-1000000000000", "-3", Down, "-999999999999", Greater); test("-1000000000000", "-3", Floor, "-1000000000002", Less); test("-1000000000000", "-3", Up, "-1000000000002", Less); test("-1000000000000", "-3", Ceiling, "-999999999999", Greater); test("-1000000000000", "-3", Nearest, "-999999999999", Greater); test("-999999999999", "-2", Down, "-999999999998", Greater); test("-999999999999", "-2", Floor, "-1000000000000", Less); test("-999999999999", "-2", Up, "-1000000000000", Less); test("-999999999999", "-2", Ceiling, "-999999999998", Greater); test("-999999999999", "-2", Nearest, "-1000000000000", Less); test("-1000000000001", "-2", Down, "-1000000000000", Greater); test("-1000000000001", "-2", Floor, "-1000000000002", Less); test("-1000000000001", "-2", Up, "-1000000000002", Less); test("-1000000000001", "-2", Ceiling, "-1000000000000", Greater); test("-1000000000001", "-2", Nearest, "-1000000000000", Greater); test( "-1000000000000000000000000", "-4294967295", Down, "-999999999999996832276305", Greater, ); test( "-1000000000000000000000000", "-4294967295", Floor, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "-4294967295", Up, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "-4294967295", Ceiling, "-999999999999996832276305", Greater, ); test( "-1000000000000000000000000", "-4294967295", Nearest, "-1000000000000001127243600", Less, ); test( "-1000000000000000000000000", "-1000000000000", Down, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Floor, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Up, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Ceiling, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Nearest, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000000", Exact, "-1000000000000000000000000", Equal, ); test( "-1000000000000000000000000", "-1000000000001", Down, "-999999999999999999999999", Greater, ); test( "-1000000000000000000000000", "-1000000000001", Floor, "-1000000000001000000000000", Less, ); test( "-1000000000000000000000000", "-1000000000001", Up, "-1000000000001000000000000", Less, ); test( "-1000000000000000000000000", "-1000000000001", Ceiling, "-999999999999999999999999", Greater, ); test( "-1000000000000000000000000", "-1000000000001", Nearest, "-999999999999999999999999", Greater, ); test( "-2999999999999999999999999", "-2000000000000000000000000", Nearest, "-2000000000000000000000000", Greater, ); test( "-3000000000000000000000000", "-2000000000000000000000000", Nearest, "-4000000000000000000000000", Less, ); test( "-3000000000000000000000001", "-2000000000000000000000000", Nearest, "-4000000000000000000000000", Less, ); test("0", "0", Floor, "0", Equal); test("0", "0", Ceiling, "0", Equal); test("0", "0", Down, "0", Equal); test("0", "0", Up, "0", Equal); test("0", "0", Nearest, "0", Equal); test("0", "0", Exact, "0", Equal); test("2", "0", Floor, "0", Less); test("2", "0", Down, "0", Less); test("2", "0", Nearest, "0", Less); test("-2", "0", Ceiling, "0", Greater); test("-2", "0", Down, "0", Greater); test("-2", "0", Nearest, "0", Greater); } #[test] #[should_panic] fn round_to_multiple_assign_fail_1() { let mut n = Integer::from(10); n.round_to_multiple_assign(Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_fail_2() { let mut n = Integer::from(10); n.round_to_multiple_assign(Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_fail_3() { let mut n = Integer::from(10); n.round_to_multiple_assign(Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_fail_4() { let mut n = Integer::from(10); n.round_to_multiple_assign(Integer::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_1() { let mut n = Integer::from(10); n.round_to_multiple_assign(&Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_2() { let mut n = Integer::from(10); n.round_to_multiple_assign(&Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_3() { let mut n = Integer::from(10); n.round_to_multiple_assign(&Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_4() { let mut n = Integer::from(10); n.round_to_multiple_assign(&Integer::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_fail_1() { Integer::from(10).round_to_multiple(Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_fail_2() { Integer::from(10).round_to_multiple(Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_fail_3() { Integer::from(10).round_to_multiple(Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_fail_4() { Integer::from(10).round_to_multiple(Integer::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_1() { Integer::from(10).round_to_multiple(&Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_2() { Integer::from(10).round_to_multiple(&Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_3() { Integer::from(10).round_to_multiple(&Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_4() { Integer::from(10).round_to_multiple(&Integer::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_1() { (&Integer::from(10)).round_to_multiple(Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_2() { (&Integer::from(10)).round_to_multiple(Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_3() { (&Integer::from(10)).round_to_multiple(Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_4() { (&Integer::from(10)).round_to_multiple(Integer::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_1() { (&Integer::from(10)).round_to_multiple(&Integer::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_2() { (&Integer::from(10)).round_to_multiple(&Integer::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_3() { (&Integer::from(10)).round_to_multiple(&Integer::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_4() { (&Integer::from(10)).round_to_multiple(&Integer::ZERO, Exact); } #[test] fn round_to_multiple_properties() { integer_integer_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { let mut mut_n = x.clone(); let o = mut_n.round_to_multiple_assign(&y, rm); assert!(mut_n.is_valid()); let r = mut_n; let mut mut_n = x.clone(); assert_eq!(mut_n.round_to_multiple_assign(y.clone(), rm), o); assert!(mut_n.is_valid()); assert_eq!(mut_n, r); let (r_alt, o_alt) = (&x).round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (&x).round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (-&x).round_to_multiple(&y, -rm); assert_eq!(-r_alt, r); assert_eq!(o_alt.reverse(), o); let (r_alt, o_alt) = (&x).round_to_multiple(-&y, rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); assert!((&r).divisible_by(&y)); assert_eq!(r.cmp(&x), o); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if y == 0 { assert_eq!(r, 0); assert_eq!(o, Equal); } else { assert!((&r - &x).le_abs(&y)); match rm { Floor => assert!(r <= x), Ceiling => assert!(r >= x), Down => assert!(r.le_abs(&x)), Up => assert!(r.ge_abs(&x)), Exact => assert_eq!(r, x), Nearest => { let closest; let second_closest; if r <= x { closest = &x - &r; second_closest = &r + (&y).abs() - &x; } else { closest = &r - &x; second_closest = x + (&y).abs() - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!(r.div_round(y, Exact).0.even()); } } } } }); integer_pair_gen_var_1().test_properties(|(x, y)| { let product = x * &y; let po = (product.clone(), Equal); assert_eq!((&product).round_to_multiple(&y, Down), po); assert_eq!((&product).round_to_multiple(&y, Up), po); assert_eq!((&product).round_to_multiple(&y, Floor), po); assert_eq!((&product).round_to_multiple(&y, Ceiling), po); assert_eq!((&product).round_to_multiple(&y, Nearest), po); assert_eq!((&product).round_to_multiple(&y, Exact), po); }); integer_pair_gen_var_3().test_properties(|(x, y)| { let down = (&x).round_to_multiple(&y, Down); assert_eq!(down.1, if x >= 0 { Less } else { Greater }); let up = if x >= 0 { (&down.0 + (&y).abs(), Greater) } else { (&down.0 - (&y).abs(), Less) }; let floor = (&x).round_to_multiple(&y, Floor); assert_eq!(floor.1, Less); let ceiling = (&floor.0 + (&y).abs(), Greater); assert_eq!((&x).round_to_multiple(&y, Up), up); assert_eq!((&x).round_to_multiple(&y, Ceiling), ceiling); let nearest = x.round_to_multiple(y, Nearest); assert!(nearest == down || nearest == up); }); integer_rounding_mode_pair_gen().test_properties(|(ref x, rm)| { let xo = (x.clone(), Equal); assert_eq!(x.round_to_multiple(Integer::ONE, rm), xo); assert_eq!(x.round_to_multiple(Integer::NEGATIVE_ONE, rm), xo); assert_eq!( Integer::ZERO.round_to_multiple(x, rm), (Integer::ZERO, Equal) ); assert_eq!(x.round_to_multiple(x, rm), xo); assert_eq!(x.round_to_multiple(-x, rm), xo); assert_eq!((-x).round_to_multiple(x, rm), (-x, Equal)); }); natural_natural_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { let (n, no) = (&x).round_to_multiple(&y, rm); let (i, io) = Integer::from(&x).round_to_multiple(Integer::from(&y), rm); assert_eq!(n, i); assert_eq!(no, io); }); signed_signed_rounding_mode_triple_gen_var_2::().test_properties( |(x, y, rm)| { let (n, no) = x.round_to_multiple(y, rm); let (i, io) = Integer::from(x).round_to_multiple(Integer::from(y), rm); assert_eq!(n, i); assert_eq!(no, io); }, ); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, DivisibleByPowerOf2, PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, ShrRound, }; use malachite_base::num::basic::traits::Zero; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::logic::traits::BitAccess; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::signed_unsigned_rounding_mode_triple_gen_var_1; use malachite_base::test_util::generators::unsigned_rounding_mode_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_rounding_mode_pair_gen, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_5, integer_unsigned_rounding_mode_triple_gen_var_1, natural_unsigned_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_round_to_multiple_of_power_of_2() { let test = |s, v: u64, rm: RoundingMode, out, o| { let u = Integer::from_str(s).unwrap(); let mut n = u.clone(); assert_eq!(n.round_to_multiple_of_power_of_2_assign(v, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = u.shr_round(v, rm); assert_eq!((n << v).to_string(), out); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "244", Less); test("245", 1, Up, "246", Greater); test("245", 1, Floor, "244", Less); test("245", 1, Ceiling, "246", Greater); test("245", 1, Nearest, "244", Less); test("246", 1, Down, "246", Equal); test("246", 1, Up, "246", Equal); test("246", 1, Floor, "246", Equal); test("246", 1, Ceiling, "246", Equal); test("246", 1, Nearest, "246", Equal); test("246", 1, Exact, "246", Equal); test("247", 1, Down, "246", Less); test("247", 1, Up, "248", Greater); test("247", 1, Floor, "246", Less); test("247", 1, Ceiling, "248", Greater); test("247", 1, Nearest, "248", Greater); test("491", 2, Down, "488", Less); test("491", 2, Up, "492", Greater); test("491", 2, Floor, "488", Less); test("491", 2, Ceiling, "492", Greater); test("491", 2, Nearest, "492", Greater); test("492", 2, Down, "492", Equal); test("492", 2, Up, "492", Equal); test("492", 2, Floor, "492", Equal); test("492", 2, Ceiling, "492", Equal); test("492", 2, Nearest, "492", Equal); test("492", 2, Exact, "492", Equal); test("493", 2, Down, "492", Less); test("493", 2, Up, "496", Greater); test("493", 2, Floor, "492", Less); test("493", 2, Ceiling, "496", Greater); test("493", 2, Nearest, "492", Less); test("4127195135", 25, Down, "4093640704", Less); test("4127195135", 25, Up, "4127195136", Greater); test("4127195135", 25, Floor, "4093640704", Less); test("4127195135", 25, Ceiling, "4127195136", Greater); test("4127195135", 25, Nearest, "4127195136", Greater); test("4127195136", 25, Down, "4127195136", Equal); test("4127195136", 25, Up, "4127195136", Equal); test("4127195136", 25, Floor, "4127195136", Equal); test("4127195136", 25, Ceiling, "4127195136", Equal); test("4127195136", 25, Nearest, "4127195136", Equal); test("4127195136", 25, Exact, "4127195136", Equal); test("4127195137", 25, Down, "4127195136", Less); test("4127195137", 25, Up, "4160749568", Greater); test("4127195137", 25, Floor, "4127195136", Less); test("4127195137", 25, Ceiling, "4160749568", Greater); test("4127195137", 25, Nearest, "4127195136", Less); test("8254390271", 26, Down, "8187281408", Less); test("8254390271", 26, Up, "8254390272", Greater); test("8254390271", 26, Floor, "8187281408", Less); test("8254390271", 26, Ceiling, "8254390272", Greater); test("8254390271", 26, Nearest, "8254390272", Greater); test("8254390272", 26, Down, "8254390272", Equal); test("8254390272", 26, Up, "8254390272", Equal); test("8254390272", 26, Floor, "8254390272", Equal); test("8254390272", 26, Ceiling, "8254390272", Equal); test("8254390272", 26, Nearest, "8254390272", Equal); test("8254390272", 26, Exact, "8254390272", Equal); test("8254390273", 26, Down, "8254390272", Less); test("8254390273", 26, Up, "8321499136", Greater); test("8254390273", 26, Floor, "8254390272", Less); test("8254390273", 26, Ceiling, "8321499136", Greater); test("8254390273", 26, Nearest, "8254390272", Less); test( "155921023828072216384094494261247", 100, Down, "154653373227843986982597791055872", Less, ); test( "155921023828072216384094494261247", 100, Up, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261247", 100, Floor, "154653373227843986982597791055872", Less, ); test( "155921023828072216384094494261247", 100, Ceiling, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261248", 100, Down, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Up, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Floor, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261249", 100, Down, "155921023828072216384094494261248", Less, ); test( "155921023828072216384094494261249", 100, Up, "157188674428300445785591197466624", Greater, ); test( "155921023828072216384094494261249", 100, Floor, "155921023828072216384094494261248", Less, ); test( "155921023828072216384094494261249", 100, Ceiling, "157188674428300445785591197466624", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "155921023828072216384094494261248", Less, ); test("4294967295", 1, Down, "4294967294", Less); test("4294967295", 1, Up, "4294967296", Greater); test("4294967295", 1, Floor, "4294967294", Less); test("4294967295", 1, Ceiling, "4294967296", Greater); test("4294967295", 1, Nearest, "4294967296", Greater); test("4294967296", 1, Down, "4294967296", Equal); test("4294967296", 1, Up, "4294967296", Equal); test("4294967296", 1, Floor, "4294967296", Equal); test("4294967296", 1, Ceiling, "4294967296", Equal); test("4294967296", 1, Nearest, "4294967296", Equal); test("4294967296", 1, Exact, "4294967296", Equal); test("4294967297", 1, Down, "4294967296", Less); test("4294967297", 1, Up, "4294967298", Greater); test("4294967297", 1, Floor, "4294967296", Less); test("4294967297", 1, Ceiling, "4294967298", Greater); test("4294967297", 1, Nearest, "4294967296", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "7999999999992", Less); test("7999999999999", 3, Up, "8000000000000", Greater); test("7999999999999", 3, Floor, "7999999999992", Less); test("7999999999999", 3, Ceiling, "8000000000000", Greater); test("7999999999999", 3, Nearest, "8000000000000", Greater); test("8000000000000", 3, Down, "8000000000000", Equal); test("8000000000000", 3, Up, "8000000000000", Equal); test("8000000000000", 3, Floor, "8000000000000", Equal); test("8000000000000", 3, Ceiling, "8000000000000", Equal); test("8000000000000", 3, Nearest, "8000000000000", Equal); test("8000000000000", 3, Exact, "8000000000000", Equal); test("8000000000001", 3, Down, "8000000000000", Less); test("8000000000001", 3, Up, "8000000000008", Greater); test("8000000000001", 3, Floor, "8000000000000", Less); test("8000000000001", 3, Ceiling, "8000000000008", Greater); test("8000000000001", 3, Nearest, "8000000000000", Less); test( "16777216000000000000", 24, Down, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Up, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Floor, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Ceiling, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Nearest, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Exact, "16777216000000000000", Equal, ); test( "33554432000000000000", 25, Down, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Up, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Floor, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Ceiling, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Nearest, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Exact, "33554432000000000000", Equal, ); test( "2147483648000000000000", 31, Down, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Up, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Floor, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Ceiling, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Exact, "2147483648000000000000", Equal, ); test( "4294967296000000000000", 32, Down, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Up, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Floor, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Ceiling, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Exact, "4294967296000000000000", Equal, ); test( "8589934592000000000000", 33, Down, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Up, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Floor, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Ceiling, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Exact, "8589934592000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Down, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1267650600228229401496703205376000000000000", Equal, ); test("1000000000000", 10, Down, "1000000000000", Equal); test("1000000000000", 10, Up, "1000000000000", Equal); test("1000000000000", 10, Floor, "1000000000000", Equal); test("1000000000000", 10, Ceiling, "1000000000000", Equal); test("1000000000000", 10, Nearest, "1000000000000", Equal); test("1000000000000", 10, Exact, "1000000000000", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "4722366482869645213696", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "4722366482869645213696", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "2147483648", Less); test("4294967295", 31, Up, "4294967296", Greater); test("4294967295", 31, Floor, "2147483648", Less); test("4294967295", 31, Ceiling, "4294967296", Greater); test("4294967295", 31, Nearest, "4294967296", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "4294967296", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "4294967296", Greater); test("4294967295", 32, Nearest, "4294967296", Greater); test("4294967296", 32, Down, "4294967296", Equal); test("4294967296", 32, Up, "4294967296", Equal); test("4294967296", 32, Floor, "4294967296", Equal); test("4294967296", 32, Ceiling, "4294967296", Equal); test("4294967296", 32, Nearest, "4294967296", Equal); test("4294967296", 32, Exact, "4294967296", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "8589934592", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "8589934592", Greater); test("4294967296", 33, Nearest, "0", Less); test("-123", 0, Down, "-123", Equal); test("-123", 0, Up, "-123", Equal); test("-123", 0, Floor, "-123", Equal); test("-123", 0, Ceiling, "-123", Equal); test("-123", 0, Nearest, "-123", Equal); test("-123", 0, Exact, "-123", Equal); test("-245", 1, Down, "-244", Greater); test("-245", 1, Up, "-246", Less); test("-245", 1, Floor, "-246", Less); test("-245", 1, Ceiling, "-244", Greater); test("-245", 1, Nearest, "-244", Greater); test("-246", 1, Down, "-246", Equal); test("-246", 1, Up, "-246", Equal); test("-246", 1, Floor, "-246", Equal); test("-246", 1, Ceiling, "-246", Equal); test("-246", 1, Nearest, "-246", Equal); test("-246", 1, Exact, "-246", Equal); test("-247", 1, Down, "-246", Greater); test("-247", 1, Up, "-248", Less); test("-247", 1, Floor, "-248", Less); test("-247", 1, Ceiling, "-246", Greater); test("-247", 1, Nearest, "-248", Less); test("-491", 2, Down, "-488", Greater); test("-491", 2, Up, "-492", Less); test("-491", 2, Floor, "-492", Less); test("-491", 2, Ceiling, "-488", Greater); test("-491", 2, Nearest, "-492", Less); test("-492", 2, Down, "-492", Equal); test("-492", 2, Up, "-492", Equal); test("-492", 2, Floor, "-492", Equal); test("-492", 2, Ceiling, "-492", Equal); test("-492", 2, Nearest, "-492", Equal); test("-492", 2, Exact, "-492", Equal); test("-493", 2, Down, "-492", Greater); test("-493", 2, Up, "-496", Less); test("-493", 2, Floor, "-496", Less); test("-493", 2, Ceiling, "-492", Greater); test("-493", 2, Nearest, "-492", Greater); test("-4127195135", 25, Down, "-4093640704", Greater); test("-4127195135", 25, Up, "-4127195136", Less); test("-4127195135", 25, Floor, "-4127195136", Less); test("-4127195135", 25, Ceiling, "-4093640704", Greater); test("-4127195135", 25, Nearest, "-4127195136", Less); test("-4127195136", 25, Down, "-4127195136", Equal); test("-4127195136", 25, Up, "-4127195136", Equal); test("-4127195136", 25, Floor, "-4127195136", Equal); test("-4127195136", 25, Ceiling, "-4127195136", Equal); test("-4127195136", 25, Nearest, "-4127195136", Equal); test("-4127195136", 25, Exact, "-4127195136", Equal); test("-4127195137", 25, Down, "-4127195136", Greater); test("-4127195137", 25, Up, "-4160749568", Less); test("-4127195137", 25, Floor, "-4160749568", Less); test("-4127195137", 25, Ceiling, "-4127195136", Greater); test("-4127195137", 25, Nearest, "-4127195136", Greater); test("-8254390271", 26, Down, "-8187281408", Greater); test("-8254390271", 26, Up, "-8254390272", Less); test("-8254390271", 26, Floor, "-8254390272", Less); test("-8254390271", 26, Ceiling, "-8187281408", Greater); test("-8254390271", 26, Nearest, "-8254390272", Less); test("-8254390272", 26, Down, "-8254390272", Equal); test("-8254390272", 26, Up, "-8254390272", Equal); test("-8254390272", 26, Floor, "-8254390272", Equal); test("-8254390272", 26, Ceiling, "-8254390272", Equal); test("-8254390272", 26, Nearest, "-8254390272", Equal); test("-8254390272", 26, Exact, "-8254390272", Equal); test("-8254390273", 26, Down, "-8254390272", Greater); test("-8254390273", 26, Up, "-8321499136", Less); test("-8254390273", 26, Floor, "-8321499136", Less); test("-8254390273", 26, Ceiling, "-8254390272", Greater); test("-8254390273", 26, Nearest, "-8254390272", Greater); test( "-155921023828072216384094494261247", 100, Down, "-154653373227843986982597791055872", Greater, ); test( "-155921023828072216384094494261247", 100, Up, "-155921023828072216384094494261248", Less, ); test( "-155921023828072216384094494261247", 100, Floor, "-155921023828072216384094494261248", Less, ); test( "-155921023828072216384094494261247", 100, Ceiling, "-154653373227843986982597791055872", Greater, ); test( "-155921023828072216384094494261247", 100, Nearest, "-155921023828072216384094494261248", Less, ); test( "-155921023828072216384094494261248", 100, Down, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261248", 100, Up, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261248", 100, Floor, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261248", 100, Ceiling, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261248", 100, Nearest, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261248", 100, Exact, "-155921023828072216384094494261248", Equal, ); test( "-155921023828072216384094494261249", 100, Down, "-155921023828072216384094494261248", Greater, ); test( "-155921023828072216384094494261249", 100, Up, "-157188674428300445785591197466624", Less, ); test( "-155921023828072216384094494261249", 100, Floor, "-157188674428300445785591197466624", Less, ); test( "-155921023828072216384094494261249", 100, Ceiling, "-155921023828072216384094494261248", Greater, ); test( "-155921023828072216384094494261249", 100, Nearest, "-155921023828072216384094494261248", Greater, ); test("-4294967295", 1, Down, "-4294967294", Greater); test("-4294967295", 1, Up, "-4294967296", Less); test("-4294967295", 1, Floor, "-4294967296", Less); test("-4294967295", 1, Ceiling, "-4294967294", Greater); test("-4294967295", 1, Nearest, "-4294967296", Less); test("-4294967296", 1, Down, "-4294967296", Equal); test("-4294967296", 1, Up, "-4294967296", Equal); test("-4294967296", 1, Floor, "-4294967296", Equal); test("-4294967296", 1, Ceiling, "-4294967296", Equal); test("-4294967296", 1, Nearest, "-4294967296", Equal); test("-4294967296", 1, Exact, "-4294967296", Equal); test("-4294967297", 1, Down, "-4294967296", Greater); test("-4294967297", 1, Up, "-4294967298", Less); test("-4294967297", 1, Floor, "-4294967298", Less); test("-4294967297", 1, Ceiling, "-4294967296", Greater); test("-4294967297", 1, Nearest, "-4294967296", Greater); test("-1000000000000", 0, Down, "-1000000000000", Equal); test("-1000000000000", 0, Up, "-1000000000000", Equal); test("-1000000000000", 0, Floor, "-1000000000000", Equal); test("-1000000000000", 0, Ceiling, "-1000000000000", Equal); test("-1000000000000", 0, Nearest, "-1000000000000", Equal); test("-1000000000000", 0, Exact, "-1000000000000", Equal); test("-7999999999999", 3, Down, "-7999999999992", Greater); test("-7999999999999", 3, Up, "-8000000000000", Less); test("-7999999999999", 3, Floor, "-8000000000000", Less); test("-7999999999999", 3, Ceiling, "-7999999999992", Greater); test("-7999999999999", 3, Nearest, "-8000000000000", Less); test("-8000000000000", 3, Down, "-8000000000000", Equal); test("-8000000000000", 3, Up, "-8000000000000", Equal); test("-8000000000000", 3, Floor, "-8000000000000", Equal); test("-8000000000000", 3, Ceiling, "-8000000000000", Equal); test("-8000000000000", 3, Nearest, "-8000000000000", Equal); test("-8000000000000", 3, Exact, "-8000000000000", Equal); test("-8000000000001", 3, Down, "-8000000000000", Greater); test("-8000000000001", 3, Up, "-8000000000008", Less); test("-8000000000001", 3, Floor, "-8000000000008", Less); test("-8000000000001", 3, Ceiling, "-8000000000000", Greater); test("-8000000000001", 3, Nearest, "-8000000000000", Greater); test( "-16777216000000000000", 24, Down, "-16777216000000000000", Equal, ); test( "-16777216000000000000", 24, Up, "-16777216000000000000", Equal, ); test( "-16777216000000000000", 24, Floor, "-16777216000000000000", Equal, ); test( "-16777216000000000000", 24, Ceiling, "-16777216000000000000", Equal, ); test( "-16777216000000000000", 24, Nearest, "-16777216000000000000", Equal, ); test( "-16777216000000000000", 24, Exact, "-16777216000000000000", Equal, ); test( "-33554432000000000000", 25, Down, "-33554432000000000000", Equal, ); test( "-33554432000000000000", 25, Up, "-33554432000000000000", Equal, ); test( "-33554432000000000000", 25, Floor, "-33554432000000000000", Equal, ); test( "-33554432000000000000", 25, Ceiling, "-33554432000000000000", Equal, ); test( "-33554432000000000000", 25, Nearest, "-33554432000000000000", Equal, ); test( "-33554432000000000000", 25, Exact, "-33554432000000000000", Equal, ); test( "-2147483648000000000000", 31, Down, "-2147483648000000000000", Equal, ); test( "-2147483648000000000000", 31, Up, "-2147483648000000000000", Equal, ); test( "-2147483648000000000000", 31, Floor, "-2147483648000000000000", Equal, ); test( "-2147483648000000000000", 31, Ceiling, "-2147483648000000000000", Equal, ); test( "-2147483648000000000000", 31, Nearest, "-2147483648000000000000", Equal, ); test( "-2147483648000000000000", 31, Exact, "-2147483648000000000000", Equal, ); test( "-4294967296000000000000", 32, Down, "-4294967296000000000000", Equal, ); test( "-4294967296000000000000", 32, Up, "-4294967296000000000000", Equal, ); test( "-4294967296000000000000", 32, Floor, "-4294967296000000000000", Equal, ); test( "-4294967296000000000000", 32, Ceiling, "-4294967296000000000000", Equal, ); test( "-4294967296000000000000", 32, Nearest, "-4294967296000000000000", Equal, ); test( "-4294967296000000000000", 32, Exact, "-4294967296000000000000", Equal, ); test( "-8589934592000000000000", 33, Down, "-8589934592000000000000", Equal, ); test( "-8589934592000000000000", 33, Up, "-8589934592000000000000", Equal, ); test( "-8589934592000000000000", 33, Floor, "-8589934592000000000000", Equal, ); test( "-8589934592000000000000", 33, Ceiling, "-8589934592000000000000", Equal, ); test( "-8589934592000000000000", 33, Nearest, "-8589934592000000000000", Equal, ); test( "-8589934592000000000000", 33, Exact, "-8589934592000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Down, "-1267650600228229401496703205376000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Up, "-1267650600228229401496703205376000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Floor, "-1267650600228229401496703205376000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Ceiling, "-1267650600228229401496703205376000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Nearest, "-1267650600228229401496703205376000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Exact, "-1267650600228229401496703205376000000000000", Equal, ); test("-1000000000000", 10, Down, "-1000000000000", Equal); test("-1000000000000", 10, Up, "-1000000000000", Equal); test("-1000000000000", 10, Floor, "-1000000000000", Equal); test("-1000000000000", 10, Ceiling, "-1000000000000", Equal); test("-1000000000000", 10, Nearest, "-1000000000000", Equal); test("-1000000000000", 10, Exact, "-1000000000000", Equal); test("-980657949", 72, Down, "0", Greater); test("-980657949", 72, Up, "-4722366482869645213696", Less); test("-980657949", 72, Floor, "-4722366482869645213696", Less); test("-980657949", 72, Ceiling, "0", Greater); test("-980657949", 72, Nearest, "0", Greater); test("-4294967295", 31, Down, "-2147483648", Greater); test("-4294967295", 31, Up, "-4294967296", Less); test("-4294967295", 31, Floor, "-4294967296", Less); test("-4294967295", 31, Ceiling, "-2147483648", Greater); test("-4294967295", 31, Nearest, "-4294967296", Less); test("-4294967295", 32, Down, "0", Greater); test("-4294967295", 32, Up, "-4294967296", Less); test("-4294967295", 32, Floor, "-4294967296", Less); test("-4294967295", 32, Ceiling, "0", Greater); test("-4294967295", 32, Nearest, "-4294967296", Less); test("-4294967296", 32, Down, "-4294967296", Equal); test("-4294967296", 32, Up, "-4294967296", Equal); test("-4294967296", 32, Floor, "-4294967296", Equal); test("-4294967296", 32, Ceiling, "-4294967296", Equal); test("-4294967296", 32, Nearest, "-4294967296", Equal); test("-4294967296", 32, Exact, "-4294967296", Equal); test("-4294967296", 33, Down, "0", Greater); test("-4294967296", 33, Up, "-8589934592", Less); test("-4294967296", 33, Floor, "-8589934592", Less); test("-4294967296", 33, Ceiling, "0", Greater); test("-4294967296", 33, Nearest, "0", Greater); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_1() { Integer::from(-123).round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_2() { Integer::from(-123).round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_3() { Integer::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_4() { Integer::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_1() { Integer::from(-123).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_2() { Integer::from(-123).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_3() { Integer::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_4() { Integer::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_1() { (&Integer::from(-123)).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_2() { (&Integer::from(-123)).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_3() { (&Integer::from_str("-1000000000001").unwrap()).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_4() { (&Integer::from_str("-1000000000001").unwrap()).round_to_multiple_of_power_of_2(100, Exact); } #[test] fn round_to_multiple_of_power_of_2_properties() { integer_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, pow, rm)| { let (r, o) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert!(r.is_valid()); let (r_alt, o_alt) = n.clone().round_to_multiple_of_power_of_2(pow, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let mut mut_n = n.clone(); assert_eq!(mut_n.round_to_multiple_of_power_of_2_assign(pow, rm), o); assert!(mut_n.is_valid()); assert_eq!(mut_n, r); assert!(r.divisible_by_power_of_2(pow)); assert_eq!(r.cmp(&n), o); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } let (r_alt, o_alt) = (&n).shr_round(pow, rm); assert_eq!(r_alt << pow, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (-&n).round_to_multiple_of_power_of_2(pow, -rm); assert_eq!(-r_alt, r); assert_eq!(o_alt.reverse(), o); assert!((&r - &n).abs() <= Integer::power_of_2(pow)); let (r_alt, o_alt) = (&n).round_to_multiple(Integer::power_of_2(pow), rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); match rm { Floor => assert!(r <= n), Ceiling => assert!(r >= n), Down => assert!(r.le_abs(&n)), Up => assert!(r.ge_abs(&n)), Exact => assert_eq!(r, n), Nearest => { let k = Integer::power_of_2(pow); let closest; let second_closest; if r <= n { closest = &n - &r; second_closest = &r + k - n; } else { closest = &r - &n; second_closest = n + k - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!(!r.get_bit(pow)); } } } }); integer_unsigned_pair_gen_var_2().test_properties(|(n, pow)| { let shifted: Integer = n << pow; let so = (shifted.clone(), Equal); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Down), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Up), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Floor), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Ceiling), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Nearest), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Exact), so); }); integer_unsigned_pair_gen_var_5().test_properties(|(n, pow)| { let floor = (&n).round_to_multiple_of_power_of_2(pow, Floor); assert_eq!(floor.1, Less); let ceiling = (&floor.0 + Integer::power_of_2(pow), Greater); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Ceiling), ceiling); if n >= 0 { assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Up), ceiling); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Down), floor); } else { assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Up), floor); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Down), ceiling); } let nearest = n.round_to_multiple_of_power_of_2(pow, Nearest); assert!(nearest == ceiling || nearest == floor); }); integer_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).round_to_multiple_of_power_of_2(0, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen().test_properties(|(pow, rm)| { assert_eq!( Integer::ZERO.round_to_multiple_of_power_of_2(pow, rm), (Integer::ZERO, Equal) ); }); natural_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, pow, rm)| { let (r, o) = Integer::from(&n).round_to_multiple_of_power_of_2(pow, rm); let (r_alt, o_alt) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); }); signed_unsigned_rounding_mode_triple_gen_var_1::().test_properties( |(n, pow, rm)| { let (r, o) = Integer::from(n).round_to_multiple_of_power_of_2(pow, rm); let (r_alt, o_alt) = n.round_to_multiple_of_power_of_2(pow, rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); }, ); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2, ShlRound, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{signed_gen, unsigned_gen_var_5}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_gen, integer_signed_pair_gen_var_1, integer_unsigned_pair_gen_var_2, natural_signed_pair_gen_var_2, natural_unsigned_pair_gen_var_4, }; use num::BigInt; use rug; use std::ops::{Shl, ShlAssign, Shr}; use std::str::FromStr; fn test_shl_unsigned_helper(f: F) where Integer: Shl + ShlAssign, for<'a> &'a Integer: Shl, { let test = |s, v: u8, out| { let u = Integer::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("2147483648", 1, "4294967296"); test("1000000000000", 0, "1000000000000"); test("1000000000000", 3, "8000000000000"); test("1000000000000", 24, "16777216000000000000"); test("1000000000000", 25, "33554432000000000000"); test("1000000000000", 31, "2147483648000000000000"); test("1000000000000", 32, "4294967296000000000000"); test("1000000000000", 33, "8589934592000000000000"); test( "1000000000000", 100, "1267650600228229401496703205376000000000000", ); test("-123", 0, "-123"); test("-123", 1, "-246"); test("-123", 2, "-492"); test("-123", 25, "-4127195136"); test("-123", 26, "-8254390272"); test("-123", 100, "-155921023828072216384094494261248"); test("-2147483648", 1, "-4294967296"); test("-1000000000000", 0, "-1000000000000"); test("-1000000000000", 3, "-8000000000000"); test("-1000000000000", 24, "-16777216000000000000"); test("-1000000000000", 25, "-33554432000000000000"); test("-1000000000000", 31, "-2147483648000000000000"); test("-1000000000000", 32, "-4294967296000000000000"); test("-1000000000000", 33, "-8589934592000000000000"); test( "-1000000000000", 100, "-1267650600228229401496703205376000000000000", ); } #[test] fn test_shl_unsigned() { test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|u, v, out| { let mut n = rug::Integer::from_str(u).unwrap(); n <<= v; assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() << v; assert_eq!(n.to_string(), out); let n = BigInt::from_str(u).unwrap() << usize::exact_from(v); assert_eq!(n.to_string(), out); let n = &BigInt::from_str(u).unwrap() << usize::exact_from(v); assert_eq!(n.to_string(), out); }); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); } fn test_shl_signed_helper(f: F) where Integer: Shl + ShlAssign, for<'a> &'a Integer: Shl, { let test = |s, v: i8, out| { let u = Integer::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("0", 10, "0"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("2147483648", 1, "4294967296"); test("1000000000000", 3, "8000000000000"); test("1000000000000", 24, "16777216000000000000"); test("1000000000000", 25, "33554432000000000000"); test("1000000000000", 31, "2147483648000000000000"); test("1000000000000", 32, "4294967296000000000000"); test("1000000000000", 33, "8589934592000000000000"); test( "1000000000000", 100, "1267650600228229401496703205376000000000000", ); test("-123", 1, "-246"); test("-123", 2, "-492"); test("-123", 25, "-4127195136"); test("-123", 26, "-8254390272"); test("-123", 100, "-155921023828072216384094494261248"); test("-2147483648", 1, "-4294967296"); test("-1000000000000", 3, "-8000000000000"); test("-1000000000000", 24, "-16777216000000000000"); test("-1000000000000", 25, "-33554432000000000000"); test("-1000000000000", 31, "-2147483648000000000000"); test("-1000000000000", 32, "-4294967296000000000000"); test("-1000000000000", 33, "-8589934592000000000000"); test( "-1000000000000", 100, "-1267650600228229401496703205376000000000000", ); test("123", 0, "123"); test("245", -1, "122"); test("246", -1, "123"); test("247", -1, "123"); test("491", -2, "122"); test("492", -2, "123"); test("493", -2, "123"); test("4127195135", -25, "122"); test("4127195136", -25, "123"); test("4127195137", -25, "123"); test("8254390271", -26, "122"); test("8254390272", -26, "123"); test("8254390273", -26, "123"); test("155921023828072216384094494261247", -100, "122"); test("155921023828072216384094494261248", -100, "123"); test("155921023828072216384094494261249", -100, "123"); test("4294967295", -1, "2147483647"); test("4294967296", -1, "2147483648"); test("4294967297", -1, "2147483648"); test("1000000000000", 0, "1000000000000"); test("7999999999999", -3, "999999999999"); test("8000000000000", -3, "1000000000000"); test("8000000000001", -3, "1000000000000"); test("16777216000000000000", -24, "1000000000000"); test("33554432000000000000", -25, "1000000000000"); test("2147483648000000000000", -31, "1000000000000"); test("4294967296000000000000", -32, "1000000000000"); test("8589934592000000000000", -33, "1000000000000"); test( "1267650600228229401496703205376000000000000", -100, "1000000000000", ); test("1000000000000", -10, "976562500"); test("980657949", -72, "0"); test("4294967295", -31, "1"); test("4294967295", -32, "0"); test("4294967296", -32, "1"); test("4294967296", -33, "0"); test("-123", 0, "-123"); test("-245", -1, "-123"); test("-246", -1, "-123"); test("-247", -1, "-124"); test("-491", -2, "-123"); test("-492", -2, "-123"); test("-493", -2, "-124"); test("-4127195135", -25, "-123"); test("-4127195136", -25, "-123"); test("-4127195137", -25, "-124"); test("-8254390271", -26, "-123"); test("-8254390272", -26, "-123"); test("-8254390273", -26, "-124"); test("-155921023828072216384094494261247", -100, "-123"); test("-155921023828072216384094494261248", -100, "-123"); test("-155921023828072216384094494261249", -100, "-124"); test("-4294967295", -1, "-2147483648"); test("-4294967296", -1, "-2147483648"); test("-4294967297", -1, "-2147483649"); test("-1000000000000", 0, "-1000000000000"); test("-7999999999999", -3, "-1000000000000"); test("-8000000000000", -3, "-1000000000000"); test("-8000000000001", -3, "-1000000000001"); test("-16777216000000000000", -24, "-1000000000000"); test("-33554432000000000000", -25, "-1000000000000"); test("-2147483648000000000000", -31, "-1000000000000"); test("-4294967296000000000000", -32, "-1000000000000"); test("-8589934592000000000000", -33, "-1000000000000"); test( "-1267650600228229401496703205376000000000000", -100, "-1000000000000", ); test("-1000000000000", -10, "-976562500"); test("-980657949", -72, "-1"); test("-4294967295", -31, "-2"); test("-4294967295", -32, "-1"); test("-4294967296", -32, "-1"); test("-4294967296", -33, "-1"); } #[test] fn test_shl_signed() { test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|i, j, out| { let mut n = rug::Integer::from_str(i).unwrap(); n <<= j; assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(i).unwrap() << j; assert_eq!(n.to_string(), out); }); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); } fn shl_properties_helper_unsigned() where Integer: Shl + ShlAssign + Shr, for<'a> &'a Integer: Shl, for<'a> &'a Natural: Shl, u64: TryFrom, { integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n <<= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!((&n << u).ge_abs(&n)); assert_eq!(-&n << u, -(&n << u)); assert_eq!(&n << u, &n * Integer::power_of_2(u64::exact_from(u))); assert_eq!(&n << u >> u, n); }); integer_gen().test_properties(|n| { assert_eq!(&n << T::ZERO, n); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(Integer::ZERO << u, 0); assert!(Natural::exact_from(Integer::ONE << u).is_power_of_2()); }); natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { assert_eq!(&n << u, Integer::from(n) << u); }); } fn shl_properties_helper_signed() where Integer: Shl + ShlAssign, for<'a> &'a Integer: Shl + Shl<::Output, Output = Integer> + ShlRound, for<'a> &'a Natural: Shl, { integer_signed_pair_gen_var_1::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n <<= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n).shl_round(i, Floor).0, shifted); if i >= T::ZERO { assert_eq!(&n << i.unsigned_abs(), shifted); } }); integer_gen().test_properties(|n| { assert_eq!(&n << T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Integer::ZERO << i, 0); }); natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { assert_eq!(&n << i, Integer::from(n) << i); }); } #[test] fn shl_properties() { apply_fn_to_unsigneds!(shl_properties_helper_unsigned); apply_fn_to_signeds!(shl_properties_helper_signed); integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let shifted = &n << u; let mut rug_n = rug::Integer::from(&n); rug_n <<= u; assert_eq!(Integer::from(&rug_n), shifted); assert_eq!( Integer::from(&(&BigInt::from(&n) << usize::exact_from(u))), shifted ); assert_eq!( Integer::from(&(BigInt::from(&n) << usize::exact_from(u))), shifted ); assert_eq!(Integer::from(&(rug::Integer::from(&n) << u)), shifted); }); integer_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = &n << i; let mut rug_n = rug::Integer::from(&n); rug_n <<= i; assert_eq!(Integer::from(&rug_n), shifted); assert_eq!(Integer::from(&(rug::Integer::from(&n) << i)), shifted); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShl, DivisibleByPowerOf2, ShlRound, ShlRoundAssign, UnsignedAbs, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_signed_rounding_mode_triple_gen_var_4, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_rounding_mode_pair_gen, integer_signed_rounding_mode_triple_gen_var_1, natural_signed_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::ops::Shr; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_shl_round_signed_helper { ($t:ident) => { let test = |i, j: $t, rm: RoundingMode, out, o| { let u = Integer::from_str(i).unwrap(); let mut n = u.clone(); assert_eq!(n.shl_round_assign(j, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shl_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shl_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 10, Exact, "0", Equal); test("123", 1, Exact, "246", Equal); test("123", 2, Exact, "492", Equal); test("123", 25, Exact, "4127195136", Equal); test("123", 26, Exact, "8254390272", Equal); test( "123", 100, Exact, "155921023828072216384094494261248", Equal, ); test("2147483648", 1, Exact, "4294967296", Equal); test("1000000000000", 3, Exact, "8000000000000", Equal); test("1000000000000", 24, Exact, "16777216000000000000", Equal); test("1000000000000", 25, Exact, "33554432000000000000", Equal); test("1000000000000", 31, Exact, "2147483648000000000000", Equal); test("1000000000000", 32, Exact, "4294967296000000000000", Equal); test("1000000000000", 33, Exact, "8589934592000000000000", Equal); test( "1000000000000", 100, Exact, "1267650600228229401496703205376000000000000", Equal, ); test("-123", 1, Exact, "-246", Equal); test("-123", 2, Exact, "-492", Equal); test("-123", 25, Exact, "-4127195136", Equal); test("-123", 26, Exact, "-8254390272", Equal); test( "-123", 100, Exact, "-155921023828072216384094494261248", Equal, ); test("-2147483648", 1, Exact, "-4294967296", Equal); test("-1000000000000", 3, Exact, "-8000000000000", Equal); test("-1000000000000", 24, Exact, "-16777216000000000000", Equal); test("-1000000000000", 25, Exact, "-33554432000000000000", Equal); test( "-1000000000000", 31, Exact, "-2147483648000000000000", Equal, ); test( "-1000000000000", 32, Exact, "-4294967296000000000000", Equal, ); test( "-1000000000000", 33, Exact, "-8589934592000000000000", Equal, ); test( "-1000000000000", 100, Exact, "-1267650600228229401496703205376000000000000", Equal, ); test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", -10, Down, "0", Equal); test("0", -10, Up, "0", Equal); test("0", -10, Floor, "0", Equal); test("0", -10, Ceiling, "0", Equal); test("0", -10, Nearest, "0", Equal); test("0", -10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", -1, Down, "122", Less); test("245", -1, Up, "123", Greater); test("245", -1, Floor, "122", Less); test("245", -1, Ceiling, "123", Greater); test("245", -1, Nearest, "122", Less); test("246", -1, Down, "123", Equal); test("246", -1, Up, "123", Equal); test("246", -1, Floor, "123", Equal); test("246", -1, Ceiling, "123", Equal); test("246", -1, Nearest, "123", Equal); test("246", -1, Exact, "123", Equal); test("247", -1, Down, "123", Less); test("247", -1, Up, "124", Greater); test("247", -1, Floor, "123", Less); test("247", -1, Ceiling, "124", Greater); test("247", -1, Nearest, "124", Greater); test("491", -2, Down, "122", Less); test("491", -2, Up, "123", Greater); test("491", -2, Floor, "122", Less); test("491", -2, Ceiling, "123", Greater); test("491", -2, Nearest, "123", Greater); test("492", -2, Down, "123", Equal); test("492", -2, Up, "123", Equal); test("492", -2, Floor, "123", Equal); test("492", -2, Ceiling, "123", Equal); test("492", -2, Nearest, "123", Equal); test("492", -2, Exact, "123", Equal); test("493", -2, Down, "123", Less); test("493", -2, Up, "124", Greater); test("493", -2, Floor, "123", Less); test("493", -2, Ceiling, "124", Greater); test("493", -2, Nearest, "123", Less); test("4127195135", -25, Down, "122", Less); test("4127195135", -25, Up, "123", Greater); test("4127195135", -25, Floor, "122", Less); test("4127195135", -25, Ceiling, "123", Greater); test("4127195135", -25, Nearest, "123", Greater); test("4127195136", -25, Down, "123", Equal); test("4127195136", -25, Up, "123", Equal); test("4127195136", -25, Floor, "123", Equal); test("4127195136", -25, Ceiling, "123", Equal); test("4127195136", -25, Nearest, "123", Equal); test("4127195136", -25, Exact, "123", Equal); test("4127195137", -25, Down, "123", Less); test("4127195137", -25, Up, "124", Greater); test("4127195137", -25, Floor, "123", Less); test("4127195137", -25, Ceiling, "124", Greater); test("4127195137", -25, Nearest, "123", Less); test("8254390271", -26, Down, "122", Less); test("8254390271", -26, Up, "123", Greater); test("8254390271", -26, Floor, "122", Less); test("8254390271", -26, Ceiling, "123", Greater); test("8254390271", -26, Nearest, "123", Greater); test("8254390272", -26, Down, "123", Equal); test("8254390272", -26, Up, "123", Equal); test("8254390272", -26, Floor, "123", Equal); test("8254390272", -26, Ceiling, "123", Equal); test("8254390272", -26, Nearest, "123", Equal); test("8254390272", -26, Exact, "123", Equal); test("8254390273", -26, Down, "123", Less); test("8254390273", -26, Up, "124", Greater); test("8254390273", -26, Floor, "123", Less); test("8254390273", -26, Ceiling, "124", Greater); test("8254390273", -26, Nearest, "123", Less); test("155921023828072216384094494261247", -100, Down, "122", Less); test( "155921023828072216384094494261247", -100, Up, "123", Greater, ); test( "155921023828072216384094494261247", -100, Floor, "122", Less, ); test( "155921023828072216384094494261247", -100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", -100, Nearest, "123", Greater, ); test( "155921023828072216384094494261248", -100, Down, "123", Equal, ); test("155921023828072216384094494261248", -100, Up, "123", Equal); test( "155921023828072216384094494261248", -100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", -100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", -100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", -100, Exact, "123", Equal, ); test("155921023828072216384094494261249", -100, Down, "123", Less); test( "155921023828072216384094494261249", -100, Up, "124", Greater, ); test( "155921023828072216384094494261249", -100, Floor, "123", Less, ); test( "155921023828072216384094494261249", -100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", -100, Nearest, "123", Less, ); test("4294967295", -1, Down, "2147483647", Less); test("4294967295", -1, Up, "2147483648", Greater); test("4294967295", -1, Floor, "2147483647", Less); test("4294967295", -1, Ceiling, "2147483648", Greater); test("4294967295", -1, Nearest, "2147483648", Greater); test("4294967296", -1, Down, "2147483648", Equal); test("4294967296", -1, Up, "2147483648", Equal); test("4294967296", -1, Floor, "2147483648", Equal); test("4294967296", -1, Ceiling, "2147483648", Equal); test("4294967296", -1, Nearest, "2147483648", Equal); test("4294967296", -1, Exact, "2147483648", Equal); test("4294967297", -1, Down, "2147483648", Less); test("4294967297", -1, Up, "2147483649", Greater); test("4294967297", -1, Floor, "2147483648", Less); test("4294967297", -1, Ceiling, "2147483649", Greater); test("4294967297", -1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", -3, Down, "999999999999", Less); test("7999999999999", -3, Up, "1000000000000", Greater); test("7999999999999", -3, Floor, "999999999999", Less); test("7999999999999", -3, Ceiling, "1000000000000", Greater); test("7999999999999", -3, Nearest, "1000000000000", Greater); test("8000000000000", -3, Down, "1000000000000", Equal); test("8000000000000", -3, Up, "1000000000000", Equal); test("8000000000000", -3, Floor, "1000000000000", Equal); test("8000000000000", -3, Ceiling, "1000000000000", Equal); test("8000000000000", -3, Nearest, "1000000000000", Equal); test("8000000000000", -3, Exact, "1000000000000", Equal); test("8000000000001", -3, Down, "1000000000000", Less); test("8000000000001", -3, Up, "1000000000001", Greater); test("8000000000001", -3, Floor, "1000000000000", Less); test("8000000000001", -3, Ceiling, "1000000000001", Greater); test("8000000000001", -3, Nearest, "1000000000000", Less); test("16777216000000000000", -24, Down, "1000000000000", Equal); test("16777216000000000000", -24, Up, "1000000000000", Equal); test("16777216000000000000", -24, Floor, "1000000000000", Equal); test("16777216000000000000", -24, Ceiling, "1000000000000", Equal); test("16777216000000000000", -24, Nearest, "1000000000000", Equal); test("16777216000000000000", -24, Exact, "1000000000000", Equal); test("33554432000000000000", -25, Down, "1000000000000", Equal); test("33554432000000000000", -25, Up, "1000000000000", Equal); test("33554432000000000000", -25, Floor, "1000000000000", Equal); test("33554432000000000000", -25, Ceiling, "1000000000000", Equal); test("33554432000000000000", -25, Nearest, "1000000000000", Equal); test("33554432000000000000", -25, Exact, "1000000000000", Equal); test("2147483648000000000000", -31, Down, "1000000000000", Equal); test("2147483648000000000000", -31, Up, "1000000000000", Equal); test("2147483648000000000000", -31, Floor, "1000000000000", Equal); test( "2147483648000000000000", -31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", -31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", -31, Exact, "1000000000000", Equal); test("4294967296000000000000", -32, Down, "1000000000000", Equal); test("4294967296000000000000", -32, Up, "1000000000000", Equal); test("4294967296000000000000", -32, Floor, "1000000000000", Equal); test( "4294967296000000000000", -32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", -32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", -32, Exact, "1000000000000", Equal); test("8589934592000000000000", -33, Down, "1000000000000", Equal); test("8589934592000000000000", -33, Up, "1000000000000", Equal); test("8589934592000000000000", -33, Floor, "1000000000000", Equal); test( "8589934592000000000000", -33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", -33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", -33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", -100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Exact, "1000000000000", Equal, ); test("1000000000000", -10, Down, "976562500", Equal); test("1000000000000", -10, Up, "976562500", Equal); test("1000000000000", -10, Floor, "976562500", Equal); test("1000000000000", -10, Ceiling, "976562500", Equal); test("1000000000000", -10, Nearest, "976562500", Equal); test("1000000000000", -10, Exact, "976562500", Equal); test("980657949", -72, Down, "0", Less); test("980657949", -72, Up, "1", Greater); test("980657949", -72, Floor, "0", Less); test("980657949", -72, Ceiling, "1", Greater); test("980657949", -72, Nearest, "0", Less); test("4294967295", -31, Down, "1", Less); test("4294967295", -31, Up, "2", Greater); test("4294967295", -31, Floor, "1", Less); test("4294967295", -31, Ceiling, "2", Greater); test("4294967295", -31, Nearest, "2", Greater); test("4294967295", -32, Down, "0", Less); test("4294967295", -32, Up, "1", Greater); test("4294967295", -32, Floor, "0", Less); test("4294967295", -32, Ceiling, "1", Greater); test("4294967295", -32, Nearest, "1", Greater); test("4294967296", -32, Down, "1", Equal); test("4294967296", -32, Up, "1", Equal); test("4294967296", -32, Floor, "1", Equal); test("4294967296", -32, Ceiling, "1", Equal); test("4294967296", -32, Nearest, "1", Equal); test("4294967296", -32, Exact, "1", Equal); test("4294967296", -33, Down, "0", Less); test("4294967296", -33, Up, "1", Greater); test("4294967296", -33, Floor, "0", Less); test("4294967296", -33, Ceiling, "1", Greater); test("4294967296", -33, Nearest, "0", Less); test("-123", 0, Down, "-123", Equal); test("-123", 0, Up, "-123", Equal); test("-123", 0, Floor, "-123", Equal); test("-123", 0, Ceiling, "-123", Equal); test("-123", 0, Nearest, "-123", Equal); test("-123", 0, Exact, "-123", Equal); test("-245", -1, Down, "-122", Greater); test("-245", -1, Up, "-123", Less); test("-245", -1, Floor, "-123", Less); test("-245", -1, Ceiling, "-122", Greater); test("-245", -1, Nearest, "-122", Greater); test("-246", -1, Down, "-123", Equal); test("-246", -1, Up, "-123", Equal); test("-246", -1, Floor, "-123", Equal); test("-246", -1, Ceiling, "-123", Equal); test("-246", -1, Nearest, "-123", Equal); test("-246", -1, Exact, "-123", Equal); test("-247", -1, Down, "-123", Greater); test("-247", -1, Up, "-124", Less); test("-247", -1, Floor, "-124", Less); test("-247", -1, Ceiling, "-123", Greater); test("-247", -1, Nearest, "-124", Less); test("-491", -2, Down, "-122", Greater); test("-491", -2, Up, "-123", Less); test("-491", -2, Floor, "-123", Less); test("-491", -2, Ceiling, "-122", Greater); test("-491", -2, Nearest, "-123", Less); test("-492", -2, Down, "-123", Equal); test("-492", -2, Up, "-123", Equal); test("-492", -2, Floor, "-123", Equal); test("-492", -2, Ceiling, "-123", Equal); test("-492", -2, Nearest, "-123", Equal); test("-492", -2, Exact, "-123", Equal); test("-493", -2, Down, "-123", Greater); test("-493", -2, Up, "-124", Less); test("-493", -2, Floor, "-124", Less); test("-493", -2, Ceiling, "-123", Greater); test("-493", -2, Nearest, "-123", Greater); test("-4127195135", -25, Down, "-122", Greater); test("-4127195135", -25, Up, "-123", Less); test("-4127195135", -25, Floor, "-123", Less); test("-4127195135", -25, Ceiling, "-122", Greater); test("-4127195135", -25, Nearest, "-123", Less); test("-4127195136", -25, Down, "-123", Equal); test("-4127195136", -25, Up, "-123", Equal); test("-4127195136", -25, Floor, "-123", Equal); test("-4127195136", -25, Ceiling, "-123", Equal); test("-4127195136", -25, Nearest, "-123", Equal); test("-4127195136", -25, Exact, "-123", Equal); test("-4127195137", -25, Down, "-123", Greater); test("-4127195137", -25, Up, "-124", Less); test("-4127195137", -25, Floor, "-124", Less); test("-4127195137", -25, Ceiling, "-123", Greater); test("-4127195137", -25, Nearest, "-123", Greater); test("-8254390271", -26, Down, "-122", Greater); test("-8254390271", -26, Up, "-123", Less); test("-8254390271", -26, Floor, "-123", Less); test("-8254390271", -26, Ceiling, "-122", Greater); test("-8254390271", -26, Nearest, "-123", Less); test("-8254390272", -26, Down, "-123", Equal); test("-8254390272", -26, Up, "-123", Equal); test("-8254390272", -26, Floor, "-123", Equal); test("-8254390272", -26, Ceiling, "-123", Equal); test("-8254390272", -26, Nearest, "-123", Equal); test("-8254390272", -26, Exact, "-123", Equal); test("-8254390273", -26, Down, "-123", Greater); test("-8254390273", -26, Up, "-124", Less); test("-8254390273", -26, Floor, "-124", Less); test("-8254390273", -26, Ceiling, "-123", Greater); test("-8254390273", -26, Nearest, "-123", Greater); test( "-155921023828072216384094494261247", -100, Down, "-122", Greater, ); test("-155921023828072216384094494261247", -100, Up, "-123", Less); test( "-155921023828072216384094494261247", -100, Floor, "-123", Less, ); test( "-155921023828072216384094494261247", -100, Ceiling, "-122", Greater, ); test( "-155921023828072216384094494261247", -100, Nearest, "-123", Less, ); test( "-155921023828072216384094494261248", -100, Down, "-123", Equal, ); test( "-155921023828072216384094494261248", -100, Up, "-123", Equal, ); test( "-155921023828072216384094494261248", -100, Floor, "-123", Equal, ); test( "-155921023828072216384094494261248", -100, Ceiling, "-123", Equal, ); test( "-155921023828072216384094494261248", -100, Nearest, "-123", Equal, ); test( "-155921023828072216384094494261248", -100, Exact, "-123", Equal, ); test( "-155921023828072216384094494261249", -100, Down, "-123", Greater, ); test("-155921023828072216384094494261249", -100, Up, "-124", Less); test( "-155921023828072216384094494261249", -100, Floor, "-124", Less, ); test( "-155921023828072216384094494261249", -100, Ceiling, "-123", Greater, ); test( "-155921023828072216384094494261249", -100, Nearest, "-123", Greater, ); test("-4294967295", -1, Down, "-2147483647", Greater); test("-4294967295", -1, Up, "-2147483648", Less); test("-4294967295", -1, Floor, "-2147483648", Less); test("-4294967295", -1, Ceiling, "-2147483647", Greater); test("-4294967295", -1, Nearest, "-2147483648", Less); test("-4294967296", -1, Down, "-2147483648", Equal); test("-4294967296", -1, Up, "-2147483648", Equal); test("-4294967296", -1, Floor, "-2147483648", Equal); test("-4294967296", -1, Ceiling, "-2147483648", Equal); test("-4294967296", -1, Nearest, "-2147483648", Equal); test("-4294967296", -1, Exact, "-2147483648", Equal); test("-4294967297", -1, Down, "-2147483648", Greater); test("-4294967297", -1, Up, "-2147483649", Less); test("-4294967297", -1, Floor, "-2147483649", Less); test("-4294967297", -1, Ceiling, "-2147483648", Greater); test("-4294967297", -1, Nearest, "-2147483648", Greater); test("-1000000000000", 0, Down, "-1000000000000", Equal); test("-1000000000000", 0, Up, "-1000000000000", Equal); test("-1000000000000", 0, Floor, "-1000000000000", Equal); test("-1000000000000", 0, Ceiling, "-1000000000000", Equal); test("-1000000000000", 0, Nearest, "-1000000000000", Equal); test("-1000000000000", 0, Exact, "-1000000000000", Equal); test("-7999999999999", -3, Down, "-999999999999", Greater); test("-7999999999999", -3, Up, "-1000000000000", Less); test("-7999999999999", -3, Floor, "-1000000000000", Less); test("-7999999999999", -3, Ceiling, "-999999999999", Greater); test("-7999999999999", -3, Nearest, "-1000000000000", Less); test("-8000000000000", -3, Down, "-1000000000000", Equal); test("-8000000000000", -3, Up, "-1000000000000", Equal); test("-8000000000000", -3, Floor, "-1000000000000", Equal); test("-8000000000000", -3, Ceiling, "-1000000000000", Equal); test("-8000000000000", -3, Nearest, "-1000000000000", Equal); test("-8000000000000", -3, Exact, "-1000000000000", Equal); test("-8000000000001", -3, Down, "-1000000000000", Greater); test("-8000000000001", -3, Up, "-1000000000001", Less); test("-8000000000001", -3, Floor, "-1000000000001", Less); test("-8000000000001", -3, Ceiling, "-1000000000000", Greater); test("-8000000000001", -3, Nearest, "-1000000000000", Greater); test("-16777216000000000000", -24, Down, "-1000000000000", Equal); test("-16777216000000000000", -24, Up, "-1000000000000", Equal); test("-16777216000000000000", -24, Floor, "-1000000000000", Equal); test( "-16777216000000000000", -24, Ceiling, "-1000000000000", Equal, ); test( "-16777216000000000000", -24, Nearest, "-1000000000000", Equal, ); test("-16777216000000000000", -24, Exact, "-1000000000000", Equal); test("-33554432000000000000", -25, Down, "-1000000000000", Equal); test("-33554432000000000000", -25, Up, "-1000000000000", Equal); test("-33554432000000000000", -25, Floor, "-1000000000000", Equal); test( "-33554432000000000000", -25, Ceiling, "-1000000000000", Equal, ); test( "-33554432000000000000", -25, Nearest, "-1000000000000", Equal, ); test("-33554432000000000000", -25, Exact, "-1000000000000", Equal); test( "-2147483648000000000000", -31, Down, "-1000000000000", Equal, ); test("-2147483648000000000000", -31, Up, "-1000000000000", Equal); test( "-2147483648000000000000", -31, Floor, "-1000000000000", Equal, ); test( "-2147483648000000000000", -31, Ceiling, "-1000000000000", Equal, ); test( "-2147483648000000000000", -31, Nearest, "-1000000000000", Equal, ); test( "-2147483648000000000000", -31, Exact, "-1000000000000", Equal, ); test( "-4294967296000000000000", -32, Down, "-1000000000000", Equal, ); test("-4294967296000000000000", -32, Up, "-1000000000000", Equal); test( "-4294967296000000000000", -32, Floor, "-1000000000000", Equal, ); test( "-4294967296000000000000", -32, Ceiling, "-1000000000000", Equal, ); test( "-4294967296000000000000", -32, Nearest, "-1000000000000", Equal, ); test( "-4294967296000000000000", -32, Exact, "-1000000000000", Equal, ); test( "-8589934592000000000000", -33, Down, "-1000000000000", Equal, ); test("-8589934592000000000000", -33, Up, "-1000000000000", Equal); test( "-8589934592000000000000", -33, Floor, "-1000000000000", Equal, ); test( "-8589934592000000000000", -33, Ceiling, "-1000000000000", Equal, ); test( "-8589934592000000000000", -33, Nearest, "-1000000000000", Equal, ); test( "-8589934592000000000000", -33, Exact, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Down, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Up, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Floor, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Ceiling, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Nearest, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", -100, Exact, "-1000000000000", Equal, ); test("-1000000000000", -10, Down, "-976562500", Equal); test("-1000000000000", -10, Up, "-976562500", Equal); test("-1000000000000", -10, Floor, "-976562500", Equal); test("-1000000000000", -10, Ceiling, "-976562500", Equal); test("-1000000000000", -10, Nearest, "-976562500", Equal); test("-1000000000000", -10, Exact, "-976562500", Equal); test("-980657949", -72, Down, "0", Greater); test("-980657949", -72, Up, "-1", Less); test("-980657949", -72, Floor, "-1", Less); test("-980657949", -72, Ceiling, "0", Greater); test("-980657949", -72, Nearest, "0", Greater); test("-4294967295", -31, Down, "-1", Greater); test("-4294967295", -31, Up, "-2", Less); test("-4294967295", -31, Floor, "-2", Less); test("-4294967295", -31, Ceiling, "-1", Greater); test("-4294967295", -31, Nearest, "-2", Less); test("-4294967295", -32, Down, "0", Greater); test("-4294967295", -32, Up, "-1", Less); test("-4294967295", -32, Floor, "-1", Less); test("-4294967295", -32, Ceiling, "0", Greater); test("-4294967295", -32, Nearest, "-1", Less); test("-4294967296", -32, Down, "-1", Equal); test("-4294967296", -32, Up, "-1", Equal); test("-4294967296", -32, Floor, "-1", Equal); test("-4294967296", -32, Ceiling, "-1", Equal); test("-4294967296", -32, Nearest, "-1", Equal); test("-4294967296", -32, Exact, "-1", Equal); test("-4294967296", -33, Down, "0", Greater); test("-4294967296", -33, Up, "-1", Less); test("-4294967296", -33, Floor, "-1", Less); test("-4294967296", -33, Ceiling, "0", Greater); test("-4294967296", -33, Nearest, "0", Greater); }; } #[test] fn test_shl_round_signed() { apply_to_signeds!(test_shl_round_signed_helper); } macro_rules! shl_round_signed_fail_helper { ($t:ident) => { assert_panic!(Integer::from(-123).shl_round_assign($t::NEGATIVE_ONE, Exact)); assert_panic!(Integer::from(-123).shl_round_assign($t::exact_from(-100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shl_round_assign($t::NEGATIVE_ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shl_round_assign($t::exact_from(-100), Exact) ); assert_panic!(Integer::from(-123).shl_round($t::NEGATIVE_ONE, Exact)); assert_panic!(Integer::from(-123).shl_round($t::exact_from(-100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shl_round($t::NEGATIVE_ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shl_round($t::exact_from(-100), Exact) ); assert_panic!((&Integer::from(-123)).shl_round($t::NEGATIVE_ONE, Exact)); assert_panic!((&Integer::from(-123)).shl_round($t::exact_from(-100), Exact)); assert_panic!( (&Integer::from_str("-1000000000001").unwrap()).shl_round($t::NEGATIVE_ONE, Exact) ); assert_panic!( (&Integer::from_str("-1000000000001").unwrap()).shl_round($t::exact_from(-100), Exact) ); }; } #[test] fn shl_round_signed_fail() { apply_to_signeds!(shl_round_signed_fail_helper); } fn shl_round_properties_helper() where Integer: ShlRound + ShlRoundAssign + Shr, for<'a> &'a Integer: ShlRound, Natural: Shr, for<'a> &'a Natural: ShlRound, SignedLimb: ArithmeticCheckedShl + ShlRound, u64: TryFrom<::Output>, { integer_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { let mut mut_n = n.clone(); let o = mut_n.shl_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = (-&n).shl_round(i, -rm); assert_eq!(-shifted_alt, shifted); assert_eq!(o_alt, o.reverse()); assert_eq!( i >= T::ZERO || n.divisible_by_power_of_2(u64::exact_from(i.unsigned_abs())), o == Equal ); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if i < T::ZERO { assert_eq!((shifted >> i).cmp(&n), o); } }); integer_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shl_round(T::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(Integer::ZERO.shl_round(i, rm), (Integer::ZERO, Equal)); }); natural_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { let (s, o) = (&n).shl_round(i, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shl_round(i, rm)); }); signed_signed_rounding_mode_triple_gen_var_4::().test_properties( |(n, i, rm)| { if n.arithmetic_checked_shl(i).is_some() { let (s, o) = n.shl_round(i, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shl_round(i, rm)); } }, ); } #[test] fn shl_round_properties() { apply_fn_to_signeds!(shl_round_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ShrRound, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_1, unsigned_gen, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_signed_pair_gen_var_1, integer_unsigned_pair_gen_var_2, integer_unsigned_unsigned_triple_gen_var_3, natural_signed_pair_gen_var_2, natural_unsigned_pair_gen_var_4, }; use num::BigInt; use std::ops::{Shr, ShrAssign}; use std::str::FromStr; fn test_shr_unsigned_helper(f: F) where Integer: Shr + ShrAssign, for<'a> &'a Integer: Shr, { let test = |s, v: u8, out| { let u = Integer::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("245", 1, "122"); test("246", 1, "123"); test("247", 1, "123"); test("491", 2, "122"); test("492", 2, "123"); test("493", 2, "123"); test("4127195135", 25, "122"); test("4127195136", 25, "123"); test("4127195137", 25, "123"); test("8254390271", 26, "122"); test("8254390272", 26, "123"); test("8254390273", 26, "123"); test("155921023828072216384094494261247", 100, "122"); test("155921023828072216384094494261248", 100, "123"); test("155921023828072216384094494261249", 100, "123"); test("4294967295", 1, "2147483647"); test("4294967296", 1, "2147483648"); test("4294967297", 1, "2147483648"); test("1000000000000", 0, "1000000000000"); test("7999999999999", 3, "999999999999"); test("8000000000000", 3, "1000000000000"); test("8000000000001", 3, "1000000000000"); test("16777216000000000000", 24, "1000000000000"); test("33554432000000000000", 25, "1000000000000"); test("2147483648000000000000", 31, "1000000000000"); test("4294967296000000000000", 32, "1000000000000"); test("8589934592000000000000", 33, "1000000000000"); test( "1267650600228229401496703205376000000000000", 100, "1000000000000", ); test("1000000000000", 10, "976562500"); test("980657949", 72, "0"); test("4294967295", 31, "1"); test("4294967295", 32, "0"); test("4294967296", 32, "1"); test("4294967296", 33, "0"); test("-123", 0, "-123"); test("-245", 1, "-123"); test("-246", 1, "-123"); test("-247", 1, "-124"); test("-491", 2, "-123"); test("-492", 2, "-123"); test("-493", 2, "-124"); test("-4127195135", 25, "-123"); test("-4127195136", 25, "-123"); test("-4127195137", 25, "-124"); test("-8254390271", 26, "-123"); test("-8254390272", 26, "-123"); test("-8254390273", 26, "-124"); test("-155921023828072216384094494261247", 100, "-123"); test("-155921023828072216384094494261248", 100, "-123"); test("-155921023828072216384094494261249", 100, "-124"); test("-4294967295", 1, "-2147483648"); test("-4294967296", 1, "-2147483648"); test("-4294967297", 1, "-2147483649"); test("-1000000000000", 0, "-1000000000000"); test("-7999999999999", 3, "-1000000000000"); test("-8000000000000", 3, "-1000000000000"); test("-8000000000001", 3, "-1000000000001"); test("-16777216000000000000", 24, "-1000000000000"); test("-33554432000000000000", 25, "-1000000000000"); test("-2147483648000000000000", 31, "-1000000000000"); test("-4294967296000000000000", 32, "-1000000000000"); test("-8589934592000000000000", 33, "-1000000000000"); test( "-1267650600228229401496703205376000000000000", 100, "-1000000000000", ); test("-1000000000000", 10, "-976562500"); test("-980657949", 72, "-1"); test("-4294967295", 31, "-2"); test("-4294967295", 32, "-1"); test("-4294967296", 32, "-1"); test("-4294967296", 33, "-1"); } #[test] fn test_shr_unsigned() { test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|u, v, out| { let mut n = rug::Integer::from_str(u).unwrap(); n >>= v; assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() >> v; assert_eq!(n.to_string(), out); }); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); } fn test_shr_signed_helper(f: F) where Integer: Shr + ShrAssign, for<'a> &'a Integer: Shr, { let test = |s, v: i8, out| { let u = Integer::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("245", 1, "122"); test("246", 1, "123"); test("247", 1, "123"); test("491", 2, "122"); test("492", 2, "123"); test("493", 2, "123"); test("4127195135", 25, "122"); test("4127195136", 25, "123"); test("4127195137", 25, "123"); test("8254390271", 26, "122"); test("8254390272", 26, "123"); test("8254390273", 26, "123"); test("155921023828072216384094494261247", 100, "122"); test("155921023828072216384094494261248", 100, "123"); test("155921023828072216384094494261249", 100, "123"); test("4294967295", 1, "2147483647"); test("4294967296", 1, "2147483648"); test("4294967297", 1, "2147483648"); test("1000000000000", 0, "1000000000000"); test("7999999999999", 3, "999999999999"); test("8000000000000", 3, "1000000000000"); test("8000000000001", 3, "1000000000000"); test("16777216000000000000", 24, "1000000000000"); test("33554432000000000000", 25, "1000000000000"); test("2147483648000000000000", 31, "1000000000000"); test("4294967296000000000000", 32, "1000000000000"); test("8589934592000000000000", 33, "1000000000000"); test( "1267650600228229401496703205376000000000000", 100, "1000000000000", ); test("1000000000000", 10, "976562500"); test("980657949", 72, "0"); test("4294967295", 31, "1"); test("4294967295", 32, "0"); test("4294967296", 32, "1"); test("4294967296", 33, "0"); test("-123", 0, "-123"); test("-245", 1, "-123"); test("-246", 1, "-123"); test("-247", 1, "-124"); test("-491", 2, "-123"); test("-492", 2, "-123"); test("-493", 2, "-124"); test("-4127195135", 25, "-123"); test("-4127195136", 25, "-123"); test("-4127195137", 25, "-124"); test("-8254390271", 26, "-123"); test("-8254390272", 26, "-123"); test("-8254390273", 26, "-124"); test("-155921023828072216384094494261247", 100, "-123"); test("-155921023828072216384094494261248", 100, "-123"); test("-155921023828072216384094494261249", 100, "-124"); test("-4294967295", 1, "-2147483648"); test("-4294967296", 1, "-2147483648"); test("-4294967297", 1, "-2147483649"); test("-1000000000000", 0, "-1000000000000"); test("-7999999999999", 3, "-1000000000000"); test("-8000000000000", 3, "-1000000000000"); test("-8000000000001", 3, "-1000000000001"); test("-16777216000000000000", 24, "-1000000000000"); test("-33554432000000000000", 25, "-1000000000000"); test("-2147483648000000000000", 31, "-1000000000000"); test("-4294967296000000000000", 32, "-1000000000000"); test("-8589934592000000000000", 33, "-1000000000000"); test( "-1267650600228229401496703205376000000000000", 100, "-1000000000000", ); test("-1000000000000", 10, "-976562500"); test("-980657949", 72, "-1"); test("-4294967295", 31, "-2"); test("-4294967295", 32, "-1"); test("-4294967296", 32, "-1"); test("-4294967296", 33, "-1"); test("0", -10, "0"); test("123", -1, "246"); test("123", -2, "492"); test("123", -25, "4127195136"); test("123", -26, "8254390272"); test("123", -100, "155921023828072216384094494261248"); test("2147483648", -1, "4294967296"); test("1000000000000", -3, "8000000000000"); test("1000000000000", -24, "16777216000000000000"); test("1000000000000", -25, "33554432000000000000"); test("1000000000000", -31, "2147483648000000000000"); test("1000000000000", -32, "4294967296000000000000"); test("1000000000000", -33, "8589934592000000000000"); test( "1000000000000", -100, "1267650600228229401496703205376000000000000", ); test("-123", -1, "-246"); test("-123", -2, "-492"); test("-123", -25, "-4127195136"); test("-123", -26, "-8254390272"); test("-123", -100, "-155921023828072216384094494261248"); test("-2147483648", -1, "-4294967296"); test("-1000000000000", -3, "-8000000000000"); test("-1000000000000", -24, "-16777216000000000000"); test("-1000000000000", -25, "-33554432000000000000"); test("-1000000000000", -31, "-2147483648000000000000"); test("-1000000000000", -32, "-4294967296000000000000"); test("-1000000000000", -33, "-8589934592000000000000"); test( "-1000000000000", -100, "-1267650600228229401496703205376000000000000", ); } #[test] fn test_shr_signed() { test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|u, v, out| { let mut n = rug::Integer::from_str(u).unwrap(); n >>= v; assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() >> v; assert_eq!(n.to_string(), out); }); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); } fn shr_properties_helper_unsigned() where Integer: ShrAssign + Shr, for<'a> &'a Integer: Shr + ShrRound, for<'a> &'a Natural: Shr, SignedLimb: Shr, { integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n >>= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!(shifted.le_abs(&n)); assert_eq!((&n).shr_round(u, Floor).0, shifted); }); integer_unsigned_unsigned_triple_gen_var_3::().test_properties(|(n, u, v)| { if let Some(sum) = u.checked_add(v) { assert_eq!(&n >> u >> v, n >> sum); } }); integer_gen().test_properties(|n| { assert_eq!(&n >> T::ZERO, n); }); unsigned_gen::().test_properties(|u| { assert_eq!(Integer::ZERO >> u, 0); }); natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { assert_eq!(&n >> u, Integer::from(n) >> u); }); signed_unsigned_pair_gen_var_1::().test_properties(|(i, j)| { if let Some(sum) = j.checked_add(T::exact_from(SignedLimb::WIDTH)) { let shifted = Integer::from(i) >> sum; if i >= 0 { assert_eq!(shifted, 0); } else { assert_eq!(shifted, -1); } } if j < T::exact_from(SignedLimb::WIDTH) { assert_eq!(i >> j, Integer::from(i) >> j); } }); } #[allow(clippy::trait_duplication_in_bounds)] fn shr_properties_helper_signed() where Integer: ShrAssign + Shr + Shr<::Output, Output = Integer>, for<'a> &'a Integer: Shr + ShrRound, for<'a> &'a Natural: Shr, { integer_signed_pair_gen_var_1::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n >>= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> i; assert_eq!(shifted_alt, shifted); assert!(shifted_alt.is_valid()); let shifted_alt = n.clone() >> i; assert_eq!(shifted_alt, shifted); assert!(shifted_alt.is_valid()); assert_eq!((&n).shr_round(i, Floor).0, shifted); if i >= T::ZERO { assert_eq!(n >> i.unsigned_abs(), shifted); } }); integer_gen().test_properties(|n| { assert_eq!(&n >> T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Integer::ZERO >> i, 0); }); natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { assert_eq!(&n >> i, Integer::from(n) >> i); }); } #[test] fn shr_properties() { apply_fn_to_unsigneds!(shr_properties_helper_unsigned); apply_fn_to_signeds!(shr_properties_helper_signed); integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let shifted = &n >> u; let mut rug_n = rug::Integer::from(&n); rug_n >>= u; assert_eq!(Integer::from(&rug_n), shifted); assert_eq!(Integer::from(&(rug::Integer::from(&n) >> u)), shifted); assert_eq!( Integer::from(&(&BigInt::from(&n) >> usize::exact_from(u))), shifted ); assert_eq!( Integer::from(&(BigInt::from(&n) >> usize::exact_from(u))), shifted ); }); integer_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = &n >> i; let mut rug_n = rug::Integer::from(&n); rug_n >>= i; assert_eq!(Integer::from(&rug_n), shifted); assert_eq!(Integer::from(&(rug::Integer::from(&n) >> i)), shifted); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShr, DivRound, DivisibleByPowerOf2, ShrRound, ShrRoundAssign, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, signed_signed_rounding_mode_triple_gen_var_3, signed_unsigned_rounding_mode_triple_gen_var_2, unsigned_rounding_mode_pair_gen, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_rounding_mode_pair_gen, integer_signed_rounding_mode_triple_gen_var_2, integer_unsigned_pair_gen_var_2, integer_unsigned_pair_gen_var_5, integer_unsigned_rounding_mode_triple_gen_var_2, natural_signed_rounding_mode_triple_gen_var_2, natural_unsigned_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::ops::Shl; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_shr_round_unsigned_helper { ($t:ident) => { let test = |u, v: $t, rm: RoundingMode, out, o| { let u = Integer::from_str(u).unwrap(); let mut n = u.clone(); assert_eq!(n.shr_round_assign(v, rm), o, "{} {} {:?}", u, v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "122", Less); test("245", 1, Up, "123", Greater); test("245", 1, Floor, "122", Less); test("245", 1, Ceiling, "123", Greater); test("245", 1, Nearest, "122", Less); test("246", 1, Down, "123", Equal); test("246", 1, Up, "123", Equal); test("246", 1, Floor, "123", Equal); test("246", 1, Ceiling, "123", Equal); test("246", 1, Nearest, "123", Equal); test("246", 1, Exact, "123", Equal); test("247", 1, Down, "123", Less); test("247", 1, Up, "124", Greater); test("247", 1, Floor, "123", Less); test("247", 1, Ceiling, "124", Greater); test("247", 1, Nearest, "124", Greater); test("491", 2, Down, "122", Less); test("491", 2, Up, "123", Greater); test("491", 2, Floor, "122", Less); test("491", 2, Ceiling, "123", Greater); test("491", 2, Nearest, "123", Greater); test("492", 2, Down, "123", Equal); test("492", 2, Up, "123", Equal); test("492", 2, Floor, "123", Equal); test("492", 2, Ceiling, "123", Equal); test("492", 2, Nearest, "123", Equal); test("492", 2, Exact, "123", Equal); test("493", 2, Down, "123", Less); test("493", 2, Up, "124", Greater); test("493", 2, Floor, "123", Less); test("493", 2, Ceiling, "124", Greater); test("493", 2, Nearest, "123", Less); test("4127195135", 25, Down, "122", Less); test("4127195135", 25, Up, "123", Greater); test("4127195135", 25, Floor, "122", Less); test("4127195135", 25, Ceiling, "123", Greater); test("4127195135", 25, Nearest, "123", Greater); test("4127195136", 25, Down, "123", Equal); test("4127195136", 25, Up, "123", Equal); test("4127195136", 25, Floor, "123", Equal); test("4127195136", 25, Ceiling, "123", Equal); test("4127195136", 25, Nearest, "123", Equal); test("4127195136", 25, Exact, "123", Equal); test("4127195137", 25, Down, "123", Less); test("4127195137", 25, Up, "124", Greater); test("4127195137", 25, Floor, "123", Less); test("4127195137", 25, Ceiling, "124", Greater); test("4127195137", 25, Nearest, "123", Less); test("8254390271", 26, Down, "122", Less); test("8254390271", 26, Up, "123", Greater); test("8254390271", 26, Floor, "122", Less); test("8254390271", 26, Ceiling, "123", Greater); test("8254390271", 26, Nearest, "123", Greater); test("8254390272", 26, Down, "123", Equal); test("8254390272", 26, Up, "123", Equal); test("8254390272", 26, Floor, "123", Equal); test("8254390272", 26, Ceiling, "123", Equal); test("8254390272", 26, Nearest, "123", Equal); test("8254390272", 26, Exact, "123", Equal); test("8254390273", 26, Down, "123", Less); test("8254390273", 26, Up, "124", Greater); test("8254390273", 26, Floor, "123", Less); test("8254390273", 26, Ceiling, "124", Greater); test("8254390273", 26, Nearest, "123", Less); test("155921023828072216384094494261247", 100, Down, "122", Less); test("155921023828072216384094494261247", 100, Up, "123", Greater); test("155921023828072216384094494261247", 100, Floor, "122", Less); test( "155921023828072216384094494261247", 100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "123", Greater, ); test("155921023828072216384094494261248", 100, Down, "123", Equal); test("155921023828072216384094494261248", 100, Up, "123", Equal); test( "155921023828072216384094494261248", 100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "123", Equal, ); test("155921023828072216384094494261249", 100, Down, "123", Less); test("155921023828072216384094494261249", 100, Up, "124", Greater); test("155921023828072216384094494261249", 100, Floor, "123", Less); test( "155921023828072216384094494261249", 100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "123", Less, ); test("4294967295", 1, Down, "2147483647", Less); test("4294967295", 1, Up, "2147483648", Greater); test("4294967295", 1, Floor, "2147483647", Less); test("4294967295", 1, Ceiling, "2147483648", Greater); test("4294967295", 1, Nearest, "2147483648", Greater); test("4294967296", 1, Down, "2147483648", Equal); test("4294967296", 1, Up, "2147483648", Equal); test("4294967296", 1, Floor, "2147483648", Equal); test("4294967296", 1, Ceiling, "2147483648", Equal); test("4294967296", 1, Nearest, "2147483648", Equal); test("4294967296", 1, Exact, "2147483648", Equal); test("4294967297", 1, Down, "2147483648", Less); test("4294967297", 1, Up, "2147483649", Greater); test("4294967297", 1, Floor, "2147483648", Less); test("4294967297", 1, Ceiling, "2147483649", Greater); test("4294967297", 1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "999999999999", Less); test("7999999999999", 3, Up, "1000000000000", Greater); test("7999999999999", 3, Floor, "999999999999", Less); test("7999999999999", 3, Ceiling, "1000000000000", Greater); test("7999999999999", 3, Nearest, "1000000000000", Greater); test("8000000000000", 3, Down, "1000000000000", Equal); test("8000000000000", 3, Up, "1000000000000", Equal); test("8000000000000", 3, Floor, "1000000000000", Equal); test("8000000000000", 3, Ceiling, "1000000000000", Equal); test("8000000000000", 3, Nearest, "1000000000000", Equal); test("8000000000000", 3, Exact, "1000000000000", Equal); test("8000000000001", 3, Down, "1000000000000", Less); test("8000000000001", 3, Up, "1000000000001", Greater); test("8000000000001", 3, Floor, "1000000000000", Less); test("8000000000001", 3, Ceiling, "1000000000001", Greater); test("8000000000001", 3, Nearest, "1000000000000", Less); test("16777216000000000000", 24, Down, "1000000000000", Equal); test("16777216000000000000", 24, Up, "1000000000000", Equal); test("16777216000000000000", 24, Floor, "1000000000000", Equal); test("16777216000000000000", 24, Ceiling, "1000000000000", Equal); test("16777216000000000000", 24, Nearest, "1000000000000", Equal); test("16777216000000000000", 24, Exact, "1000000000000", Equal); test("33554432000000000000", 25, Down, "1000000000000", Equal); test("33554432000000000000", 25, Up, "1000000000000", Equal); test("33554432000000000000", 25, Floor, "1000000000000", Equal); test("33554432000000000000", 25, Ceiling, "1000000000000", Equal); test("33554432000000000000", 25, Nearest, "1000000000000", Equal); test("33554432000000000000", 25, Exact, "1000000000000", Equal); test("2147483648000000000000", 31, Down, "1000000000000", Equal); test("2147483648000000000000", 31, Up, "1000000000000", Equal); test("2147483648000000000000", 31, Floor, "1000000000000", Equal); test( "2147483648000000000000", 31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", 31, Exact, "1000000000000", Equal); test("4294967296000000000000", 32, Down, "1000000000000", Equal); test("4294967296000000000000", 32, Up, "1000000000000", Equal); test("4294967296000000000000", 32, Floor, "1000000000000", Equal); test( "4294967296000000000000", 32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", 32, Exact, "1000000000000", Equal); test("8589934592000000000000", 33, Down, "1000000000000", Equal); test("8589934592000000000000", 33, Up, "1000000000000", Equal); test("8589934592000000000000", 33, Floor, "1000000000000", Equal); test( "8589934592000000000000", 33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", 33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", 100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1000000000000", Equal, ); test("1000000000000", 10, Down, "976562500", Equal); test("1000000000000", 10, Up, "976562500", Equal); test("1000000000000", 10, Floor, "976562500", Equal); test("1000000000000", 10, Ceiling, "976562500", Equal); test("1000000000000", 10, Nearest, "976562500", Equal); test("1000000000000", 10, Exact, "976562500", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "1", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "1", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "1", Less); test("4294967295", 31, Up, "2", Greater); test("4294967295", 31, Floor, "1", Less); test("4294967295", 31, Ceiling, "2", Greater); test("4294967295", 31, Nearest, "2", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "1", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "1", Greater); test("4294967295", 32, Nearest, "1", Greater); test("4294967296", 32, Down, "1", Equal); test("4294967296", 32, Up, "1", Equal); test("4294967296", 32, Floor, "1", Equal); test("4294967296", 32, Ceiling, "1", Equal); test("4294967296", 32, Nearest, "1", Equal); test("4294967296", 32, Exact, "1", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "1", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "1", Greater); test("4294967296", 33, Nearest, "0", Less); test("-123", 0, Down, "-123", Equal); test("-123", 0, Up, "-123", Equal); test("-123", 0, Floor, "-123", Equal); test("-123", 0, Ceiling, "-123", Equal); test("-123", 0, Nearest, "-123", Equal); test("-123", 0, Exact, "-123", Equal); test("-245", 1, Down, "-122", Greater); test("-245", 1, Up, "-123", Less); test("-245", 1, Floor, "-123", Less); test("-245", 1, Ceiling, "-122", Greater); test("-245", 1, Nearest, "-122", Greater); test("-246", 1, Down, "-123", Equal); test("-246", 1, Up, "-123", Equal); test("-246", 1, Floor, "-123", Equal); test("-246", 1, Ceiling, "-123", Equal); test("-246", 1, Nearest, "-123", Equal); test("-246", 1, Exact, "-123", Equal); test("-247", 1, Down, "-123", Greater); test("-247", 1, Up, "-124", Less); test("-247", 1, Floor, "-124", Less); test("-247", 1, Ceiling, "-123", Greater); test("-247", 1, Nearest, "-124", Less); test("-491", 2, Down, "-122", Greater); test("-491", 2, Up, "-123", Less); test("-491", 2, Floor, "-123", Less); test("-491", 2, Ceiling, "-122", Greater); test("-491", 2, Nearest, "-123", Less); test("-492", 2, Down, "-123", Equal); test("-492", 2, Up, "-123", Equal); test("-492", 2, Floor, "-123", Equal); test("-492", 2, Ceiling, "-123", Equal); test("-492", 2, Nearest, "-123", Equal); test("-492", 2, Exact, "-123", Equal); test("-493", 2, Down, "-123", Greater); test("-493", 2, Up, "-124", Less); test("-493", 2, Floor, "-124", Less); test("-493", 2, Ceiling, "-123", Greater); test("-493", 2, Nearest, "-123", Greater); test("-4127195135", 25, Down, "-122", Greater); test("-4127195135", 25, Up, "-123", Less); test("-4127195135", 25, Floor, "-123", Less); test("-4127195135", 25, Ceiling, "-122", Greater); test("-4127195135", 25, Nearest, "-123", Less); test("-4127195136", 25, Down, "-123", Equal); test("-4127195136", 25, Up, "-123", Equal); test("-4127195136", 25, Floor, "-123", Equal); test("-4127195136", 25, Ceiling, "-123", Equal); test("-4127195136", 25, Nearest, "-123", Equal); test("-4127195136", 25, Exact, "-123", Equal); test("-4127195137", 25, Down, "-123", Greater); test("-4127195137", 25, Up, "-124", Less); test("-4127195137", 25, Floor, "-124", Less); test("-4127195137", 25, Ceiling, "-123", Greater); test("-4127195137", 25, Nearest, "-123", Greater); test("-8254390271", 26, Down, "-122", Greater); test("-8254390271", 26, Up, "-123", Less); test("-8254390271", 26, Floor, "-123", Less); test("-8254390271", 26, Ceiling, "-122", Greater); test("-8254390271", 26, Nearest, "-123", Less); test("-8254390272", 26, Down, "-123", Equal); test("-8254390272", 26, Up, "-123", Equal); test("-8254390272", 26, Floor, "-123", Equal); test("-8254390272", 26, Ceiling, "-123", Equal); test("-8254390272", 26, Nearest, "-123", Equal); test("-8254390272", 26, Exact, "-123", Equal); test("-8254390273", 26, Down, "-123", Greater); test("-8254390273", 26, Up, "-124", Less); test("-8254390273", 26, Floor, "-124", Less); test("-8254390273", 26, Ceiling, "-123", Greater); test("-8254390273", 26, Nearest, "-123", Greater); test( "-155921023828072216384094494261247", 100, Down, "-122", Greater, ); test("-155921023828072216384094494261247", 100, Up, "-123", Less); test( "-155921023828072216384094494261247", 100, Floor, "-123", Less, ); test( "-155921023828072216384094494261247", 100, Ceiling, "-122", Greater, ); test( "-155921023828072216384094494261247", 100, Nearest, "-123", Less, ); test( "-155921023828072216384094494261248", 100, Down, "-123", Equal, ); test("-155921023828072216384094494261248", 100, Up, "-123", Equal); test( "-155921023828072216384094494261248", 100, Floor, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Ceiling, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Nearest, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Exact, "-123", Equal, ); test( "-155921023828072216384094494261249", 100, Down, "-123", Greater, ); test("-155921023828072216384094494261249", 100, Up, "-124", Less); test( "-155921023828072216384094494261249", 100, Floor, "-124", Less, ); test( "-155921023828072216384094494261249", 100, Ceiling, "-123", Greater, ); test( "-155921023828072216384094494261249", 100, Nearest, "-123", Greater, ); test("-4294967295", 1, Down, "-2147483647", Greater); test("-4294967295", 1, Up, "-2147483648", Less); test("-4294967295", 1, Floor, "-2147483648", Less); test("-4294967295", 1, Ceiling, "-2147483647", Greater); test("-4294967295", 1, Nearest, "-2147483648", Less); test("-4294967296", 1, Down, "-2147483648", Equal); test("-4294967296", 1, Up, "-2147483648", Equal); test("-4294967296", 1, Floor, "-2147483648", Equal); test("-4294967296", 1, Ceiling, "-2147483648", Equal); test("-4294967296", 1, Nearest, "-2147483648", Equal); test("-4294967296", 1, Exact, "-2147483648", Equal); test("-4294967297", 1, Down, "-2147483648", Greater); test("-4294967297", 1, Up, "-2147483649", Less); test("-4294967297", 1, Floor, "-2147483649", Less); test("-4294967297", 1, Ceiling, "-2147483648", Greater); test("-4294967297", 1, Nearest, "-2147483648", Greater); test("-1000000000000", 0, Down, "-1000000000000", Equal); test("-1000000000000", 0, Up, "-1000000000000", Equal); test("-1000000000000", 0, Floor, "-1000000000000", Equal); test("-1000000000000", 0, Ceiling, "-1000000000000", Equal); test("-1000000000000", 0, Nearest, "-1000000000000", Equal); test("-1000000000000", 0, Exact, "-1000000000000", Equal); test("-7999999999999", 3, Down, "-999999999999", Greater); test("-7999999999999", 3, Up, "-1000000000000", Less); test("-7999999999999", 3, Floor, "-1000000000000", Less); test("-7999999999999", 3, Ceiling, "-999999999999", Greater); test("-7999999999999", 3, Nearest, "-1000000000000", Less); test("-8000000000000", 3, Down, "-1000000000000", Equal); test("-8000000000000", 3, Up, "-1000000000000", Equal); test("-8000000000000", 3, Floor, "-1000000000000", Equal); test("-8000000000000", 3, Ceiling, "-1000000000000", Equal); test("-8000000000000", 3, Nearest, "-1000000000000", Equal); test("-8000000000000", 3, Exact, "-1000000000000", Equal); test("-8000000000001", 3, Down, "-1000000000000", Greater); test("-8000000000001", 3, Up, "-1000000000001", Less); test("-8000000000001", 3, Floor, "-1000000000001", Less); test("-8000000000001", 3, Ceiling, "-1000000000000", Greater); test("-8000000000001", 3, Nearest, "-1000000000000", Greater); test("-16777216000000000000", 24, Down, "-1000000000000", Equal); test("-16777216000000000000", 24, Up, "-1000000000000", Equal); test("-16777216000000000000", 24, Floor, "-1000000000000", Equal); test( "-16777216000000000000", 24, Ceiling, "-1000000000000", Equal, ); test( "-16777216000000000000", 24, Nearest, "-1000000000000", Equal, ); test("-16777216000000000000", 24, Exact, "-1000000000000", Equal); test("-33554432000000000000", 25, Down, "-1000000000000", Equal); test("-33554432000000000000", 25, Up, "-1000000000000", Equal); test("-33554432000000000000", 25, Floor, "-1000000000000", Equal); test( "-33554432000000000000", 25, Ceiling, "-1000000000000", Equal, ); test( "-33554432000000000000", 25, Nearest, "-1000000000000", Equal, ); test("-33554432000000000000", 25, Exact, "-1000000000000", Equal); test("-2147483648000000000000", 31, Down, "-1000000000000", Equal); test("-2147483648000000000000", 31, Up, "-1000000000000", Equal); test( "-2147483648000000000000", 31, Floor, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Ceiling, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Nearest, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Exact, "-1000000000000", Equal, ); test("-4294967296000000000000", 32, Down, "-1000000000000", Equal); test("-4294967296000000000000", 32, Up, "-1000000000000", Equal); test( "-4294967296000000000000", 32, Floor, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Ceiling, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Nearest, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Exact, "-1000000000000", Equal, ); test("-8589934592000000000000", 33, Down, "-1000000000000", Equal); test("-8589934592000000000000", 33, Up, "-1000000000000", Equal); test( "-8589934592000000000000", 33, Floor, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Ceiling, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Nearest, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Exact, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Down, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Up, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Floor, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Ceiling, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Nearest, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Exact, "-1000000000000", Equal, ); test("-1000000000000", 10, Down, "-976562500", Equal); test("-1000000000000", 10, Up, "-976562500", Equal); test("-1000000000000", 10, Floor, "-976562500", Equal); test("-1000000000000", 10, Ceiling, "-976562500", Equal); test("-1000000000000", 10, Nearest, "-976562500", Equal); test("-1000000000000", 10, Exact, "-976562500", Equal); test("-980657949", 72, Down, "0", Greater); test("-980657949", 72, Up, "-1", Less); test("-980657949", 72, Floor, "-1", Less); test("-980657949", 72, Ceiling, "0", Greater); test("-980657949", 72, Nearest, "0", Greater); test("-4294967295", 31, Down, "-1", Greater); test("-4294967295", 31, Up, "-2", Less); test("-4294967295", 31, Floor, "-2", Less); test("-4294967295", 31, Ceiling, "-1", Greater); test("-4294967295", 31, Nearest, "-2", Less); test("-4294967295", 32, Down, "0", Greater); test("-4294967295", 32, Up, "-1", Less); test("-4294967295", 32, Floor, "-1", Less); test("-4294967295", 32, Ceiling, "0", Greater); test("-4294967295", 32, Nearest, "-1", Less); test("-4294967296", 32, Down, "-1", Equal); test("-4294967296", 32, Up, "-1", Equal); test("-4294967296", 32, Floor, "-1", Equal); test("-4294967296", 32, Ceiling, "-1", Equal); test("-4294967296", 32, Nearest, "-1", Equal); test("-4294967296", 32, Exact, "-1", Equal); test("-4294967296", 33, Down, "0", Greater); test("-4294967296", 33, Up, "-1", Less); test("-4294967296", 33, Floor, "-1", Less); test("-4294967296", 33, Ceiling, "0", Greater); test("-4294967296", 33, Nearest, "0", Greater); }; } #[test] fn test_shr_round_unsigned() { apply_to_unsigneds!(test_shr_round_unsigned_helper); } macro_rules! shr_round_unsigned_fail_helper { ($t:ident) => { assert_panic!(Integer::from(-123).shr_round_assign($t::ONE, Exact)); assert_panic!(Integer::from(-123).shr_round_assign($t::exact_from(100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round_assign($t::ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round_assign($t::exact_from(100), Exact) ); assert_panic!(Integer::from(-123).shr_round($t::ONE, Exact)); assert_panic!(Integer::from(-123).shr_round($t::exact_from(100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round($t::ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round($t::exact_from(100), Exact) ); assert_panic!((&Integer::from(-123)).shr_round($t::ONE, Exact)); assert_panic!((&Integer::from(-123)).shr_round($t::exact_from(100), Exact)); assert_panic!((&Integer::from_str("-1000000000001").unwrap()).shr_round($t::ONE, Exact)); assert_panic!( (&Integer::from_str("-1000000000001").unwrap()).shr_round($t::exact_from(100), Exact) ); }; } #[test] fn shr_round_unsigned_fail() { apply_to_unsigneds!(shr_round_unsigned_fail_helper); } macro_rules! test_shr_round_signed_helper { ($t:ident) => { let test = |i, j: $t, rm: RoundingMode, out, o| { let u = Integer::from_str(i).unwrap(); let mut n = u.clone(); assert_eq!(n.shr_round_assign(j, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shr_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shr_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "122", Less); test("245", 1, Up, "123", Greater); test("245", 1, Floor, "122", Less); test("245", 1, Ceiling, "123", Greater); test("245", 1, Nearest, "122", Less); test("246", 1, Down, "123", Equal); test("246", 1, Up, "123", Equal); test("246", 1, Floor, "123", Equal); test("246", 1, Ceiling, "123", Equal); test("246", 1, Nearest, "123", Equal); test("246", 1, Exact, "123", Equal); test("247", 1, Down, "123", Less); test("247", 1, Up, "124", Greater); test("247", 1, Floor, "123", Less); test("247", 1, Ceiling, "124", Greater); test("247", 1, Nearest, "124", Greater); test("491", 2, Down, "122", Less); test("491", 2, Up, "123", Greater); test("491", 2, Floor, "122", Less); test("491", 2, Ceiling, "123", Greater); test("491", 2, Nearest, "123", Greater); test("492", 2, Down, "123", Equal); test("492", 2, Up, "123", Equal); test("492", 2, Floor, "123", Equal); test("492", 2, Ceiling, "123", Equal); test("492", 2, Nearest, "123", Equal); test("492", 2, Exact, "123", Equal); test("493", 2, Down, "123", Less); test("493", 2, Up, "124", Greater); test("493", 2, Floor, "123", Less); test("493", 2, Ceiling, "124", Greater); test("493", 2, Nearest, "123", Less); test("4127195135", 25, Down, "122", Less); test("4127195135", 25, Up, "123", Greater); test("4127195135", 25, Floor, "122", Less); test("4127195135", 25, Ceiling, "123", Greater); test("4127195135", 25, Nearest, "123", Greater); test("4127195136", 25, Down, "123", Equal); test("4127195136", 25, Up, "123", Equal); test("4127195136", 25, Floor, "123", Equal); test("4127195136", 25, Ceiling, "123", Equal); test("4127195136", 25, Nearest, "123", Equal); test("4127195136", 25, Exact, "123", Equal); test("4127195137", 25, Down, "123", Less); test("4127195137", 25, Up, "124", Greater); test("4127195137", 25, Floor, "123", Less); test("4127195137", 25, Ceiling, "124", Greater); test("4127195137", 25, Nearest, "123", Less); test("8254390271", 26, Down, "122", Less); test("8254390271", 26, Up, "123", Greater); test("8254390271", 26, Floor, "122", Less); test("8254390271", 26, Ceiling, "123", Greater); test("8254390271", 26, Nearest, "123", Greater); test("8254390272", 26, Down, "123", Equal); test("8254390272", 26, Up, "123", Equal); test("8254390272", 26, Floor, "123", Equal); test("8254390272", 26, Ceiling, "123", Equal); test("8254390272", 26, Nearest, "123", Equal); test("8254390272", 26, Exact, "123", Equal); test("8254390273", 26, Down, "123", Less); test("8254390273", 26, Up, "124", Greater); test("8254390273", 26, Floor, "123", Less); test("8254390273", 26, Ceiling, "124", Greater); test("8254390273", 26, Nearest, "123", Less); test("155921023828072216384094494261247", 100, Down, "122", Less); test("155921023828072216384094494261247", 100, Up, "123", Greater); test("155921023828072216384094494261247", 100, Floor, "122", Less); test( "155921023828072216384094494261247", 100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "123", Greater, ); test("155921023828072216384094494261248", 100, Down, "123", Equal); test("155921023828072216384094494261248", 100, Up, "123", Equal); test( "155921023828072216384094494261248", 100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "123", Equal, ); test("155921023828072216384094494261249", 100, Down, "123", Less); test("155921023828072216384094494261249", 100, Up, "124", Greater); test("155921023828072216384094494261249", 100, Floor, "123", Less); test( "155921023828072216384094494261249", 100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "123", Less, ); test("4294967295", 1, Down, "2147483647", Less); test("4294967295", 1, Up, "2147483648", Greater); test("4294967295", 1, Floor, "2147483647", Less); test("4294967295", 1, Ceiling, "2147483648", Greater); test("4294967295", 1, Nearest, "2147483648", Greater); test("4294967296", 1, Down, "2147483648", Equal); test("4294967296", 1, Up, "2147483648", Equal); test("4294967296", 1, Floor, "2147483648", Equal); test("4294967296", 1, Ceiling, "2147483648", Equal); test("4294967296", 1, Nearest, "2147483648", Equal); test("4294967296", 1, Exact, "2147483648", Equal); test("4294967297", 1, Down, "2147483648", Less); test("4294967297", 1, Up, "2147483649", Greater); test("4294967297", 1, Floor, "2147483648", Less); test("4294967297", 1, Ceiling, "2147483649", Greater); test("4294967297", 1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "999999999999", Less); test("7999999999999", 3, Up, "1000000000000", Greater); test("7999999999999", 3, Floor, "999999999999", Less); test("7999999999999", 3, Ceiling, "1000000000000", Greater); test("7999999999999", 3, Nearest, "1000000000000", Greater); test("8000000000000", 3, Down, "1000000000000", Equal); test("8000000000000", 3, Up, "1000000000000", Equal); test("8000000000000", 3, Floor, "1000000000000", Equal); test("8000000000000", 3, Ceiling, "1000000000000", Equal); test("8000000000000", 3, Nearest, "1000000000000", Equal); test("8000000000000", 3, Exact, "1000000000000", Equal); test("8000000000001", 3, Down, "1000000000000", Less); test("8000000000001", 3, Up, "1000000000001", Greater); test("8000000000001", 3, Floor, "1000000000000", Less); test("8000000000001", 3, Ceiling, "1000000000001", Greater); test("8000000000001", 3, Nearest, "1000000000000", Less); test("16777216000000000000", 24, Down, "1000000000000", Equal); test("16777216000000000000", 24, Up, "1000000000000", Equal); test("16777216000000000000", 24, Floor, "1000000000000", Equal); test("16777216000000000000", 24, Ceiling, "1000000000000", Equal); test("16777216000000000000", 24, Nearest, "1000000000000", Equal); test("16777216000000000000", 24, Exact, "1000000000000", Equal); test("33554432000000000000", 25, Down, "1000000000000", Equal); test("33554432000000000000", 25, Up, "1000000000000", Equal); test("33554432000000000000", 25, Floor, "1000000000000", Equal); test("33554432000000000000", 25, Ceiling, "1000000000000", Equal); test("33554432000000000000", 25, Nearest, "1000000000000", Equal); test("33554432000000000000", 25, Exact, "1000000000000", Equal); test("2147483648000000000000", 31, Down, "1000000000000", Equal); test("2147483648000000000000", 31, Up, "1000000000000", Equal); test("2147483648000000000000", 31, Floor, "1000000000000", Equal); test( "2147483648000000000000", 31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", 31, Exact, "1000000000000", Equal); test("4294967296000000000000", 32, Down, "1000000000000", Equal); test("4294967296000000000000", 32, Up, "1000000000000", Equal); test("4294967296000000000000", 32, Floor, "1000000000000", Equal); test( "4294967296000000000000", 32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", 32, Exact, "1000000000000", Equal); test("8589934592000000000000", 33, Down, "1000000000000", Equal); test("8589934592000000000000", 33, Up, "1000000000000", Equal); test("8589934592000000000000", 33, Floor, "1000000000000", Equal); test( "8589934592000000000000", 33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", 33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", 100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1000000000000", Equal, ); test("1000000000000", 10, Down, "976562500", Equal); test("1000000000000", 10, Up, "976562500", Equal); test("1000000000000", 10, Floor, "976562500", Equal); test("1000000000000", 10, Ceiling, "976562500", Equal); test("1000000000000", 10, Nearest, "976562500", Equal); test("1000000000000", 10, Exact, "976562500", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "1", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "1", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "1", Less); test("4294967295", 31, Up, "2", Greater); test("4294967295", 31, Floor, "1", Less); test("4294967295", 31, Ceiling, "2", Greater); test("4294967295", 31, Nearest, "2", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "1", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "1", Greater); test("4294967295", 32, Nearest, "1", Greater); test("4294967296", 32, Down, "1", Equal); test("4294967296", 32, Up, "1", Equal); test("4294967296", 32, Floor, "1", Equal); test("4294967296", 32, Ceiling, "1", Equal); test("4294967296", 32, Nearest, "1", Equal); test("4294967296", 32, Exact, "1", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "1", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "1", Greater); test("4294967296", 33, Nearest, "0", Less); test("-123", 0, Down, "-123", Equal); test("-123", 0, Up, "-123", Equal); test("-123", 0, Floor, "-123", Equal); test("-123", 0, Ceiling, "-123", Equal); test("-123", 0, Nearest, "-123", Equal); test("-123", 0, Exact, "-123", Equal); test("-245", 1, Down, "-122", Greater); test("-245", 1, Up, "-123", Less); test("-245", 1, Floor, "-123", Less); test("-245", 1, Ceiling, "-122", Greater); test("-245", 1, Nearest, "-122", Greater); test("-246", 1, Down, "-123", Equal); test("-246", 1, Up, "-123", Equal); test("-246", 1, Floor, "-123", Equal); test("-246", 1, Ceiling, "-123", Equal); test("-246", 1, Nearest, "-123", Equal); test("-246", 1, Exact, "-123", Equal); test("-247", 1, Down, "-123", Greater); test("-247", 1, Up, "-124", Less); test("-247", 1, Floor, "-124", Less); test("-247", 1, Ceiling, "-123", Greater); test("-247", 1, Nearest, "-124", Less); test("-491", 2, Down, "-122", Greater); test("-491", 2, Up, "-123", Less); test("-491", 2, Floor, "-123", Less); test("-491", 2, Ceiling, "-122", Greater); test("-491", 2, Nearest, "-123", Less); test("-492", 2, Down, "-123", Equal); test("-492", 2, Up, "-123", Equal); test("-492", 2, Floor, "-123", Equal); test("-492", 2, Ceiling, "-123", Equal); test("-492", 2, Nearest, "-123", Equal); test("-492", 2, Exact, "-123", Equal); test("-493", 2, Down, "-123", Greater); test("-493", 2, Up, "-124", Less); test("-493", 2, Floor, "-124", Less); test("-493", 2, Ceiling, "-123", Greater); test("-493", 2, Nearest, "-123", Greater); test("-4127195135", 25, Down, "-122", Greater); test("-4127195135", 25, Up, "-123", Less); test("-4127195135", 25, Floor, "-123", Less); test("-4127195135", 25, Ceiling, "-122", Greater); test("-4127195135", 25, Nearest, "-123", Less); test("-4127195136", 25, Down, "-123", Equal); test("-4127195136", 25, Up, "-123", Equal); test("-4127195136", 25, Floor, "-123", Equal); test("-4127195136", 25, Ceiling, "-123", Equal); test("-4127195136", 25, Nearest, "-123", Equal); test("-4127195136", 25, Exact, "-123", Equal); test("-4127195137", 25, Down, "-123", Greater); test("-4127195137", 25, Up, "-124", Less); test("-4127195137", 25, Floor, "-124", Less); test("-4127195137", 25, Ceiling, "-123", Greater); test("-4127195137", 25, Nearest, "-123", Greater); test("-8254390271", 26, Down, "-122", Greater); test("-8254390271", 26, Up, "-123", Less); test("-8254390271", 26, Floor, "-123", Less); test("-8254390271", 26, Ceiling, "-122", Greater); test("-8254390271", 26, Nearest, "-123", Less); test("-8254390272", 26, Down, "-123", Equal); test("-8254390272", 26, Up, "-123", Equal); test("-8254390272", 26, Floor, "-123", Equal); test("-8254390272", 26, Ceiling, "-123", Equal); test("-8254390272", 26, Nearest, "-123", Equal); test("-8254390272", 26, Exact, "-123", Equal); test("-8254390273", 26, Down, "-123", Greater); test("-8254390273", 26, Up, "-124", Less); test("-8254390273", 26, Floor, "-124", Less); test("-8254390273", 26, Ceiling, "-123", Greater); test("-8254390273", 26, Nearest, "-123", Greater); test( "-155921023828072216384094494261247", 100, Down, "-122", Greater, ); test("-155921023828072216384094494261247", 100, Up, "-123", Less); test( "-155921023828072216384094494261247", 100, Floor, "-123", Less, ); test( "-155921023828072216384094494261247", 100, Ceiling, "-122", Greater, ); test( "-155921023828072216384094494261247", 100, Nearest, "-123", Less, ); test( "-155921023828072216384094494261248", 100, Down, "-123", Equal, ); test("-155921023828072216384094494261248", 100, Up, "-123", Equal); test( "-155921023828072216384094494261248", 100, Floor, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Ceiling, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Nearest, "-123", Equal, ); test( "-155921023828072216384094494261248", 100, Exact, "-123", Equal, ); test( "-155921023828072216384094494261249", 100, Down, "-123", Greater, ); test("-155921023828072216384094494261249", 100, Up, "-124", Less); test( "-155921023828072216384094494261249", 100, Floor, "-124", Less, ); test( "-155921023828072216384094494261249", 100, Ceiling, "-123", Greater, ); test( "-155921023828072216384094494261249", 100, Nearest, "-123", Greater, ); test("-4294967295", 1, Down, "-2147483647", Greater); test("-4294967295", 1, Up, "-2147483648", Less); test("-4294967295", 1, Floor, "-2147483648", Less); test("-4294967295", 1, Ceiling, "-2147483647", Greater); test("-4294967295", 1, Nearest, "-2147483648", Less); test("-4294967296", 1, Down, "-2147483648", Equal); test("-4294967296", 1, Up, "-2147483648", Equal); test("-4294967296", 1, Floor, "-2147483648", Equal); test("-4294967296", 1, Ceiling, "-2147483648", Equal); test("-4294967296", 1, Nearest, "-2147483648", Equal); test("-4294967296", 1, Exact, "-2147483648", Equal); test("-4294967297", 1, Down, "-2147483648", Greater); test("-4294967297", 1, Up, "-2147483649", Less); test("-4294967297", 1, Floor, "-2147483649", Less); test("-4294967297", 1, Ceiling, "-2147483648", Greater); test("-4294967297", 1, Nearest, "-2147483648", Greater); test("-1000000000000", 0, Down, "-1000000000000", Equal); test("-1000000000000", 0, Up, "-1000000000000", Equal); test("-1000000000000", 0, Floor, "-1000000000000", Equal); test("-1000000000000", 0, Ceiling, "-1000000000000", Equal); test("-1000000000000", 0, Nearest, "-1000000000000", Equal); test("-1000000000000", 0, Exact, "-1000000000000", Equal); test("-7999999999999", 3, Down, "-999999999999", Greater); test("-7999999999999", 3, Up, "-1000000000000", Less); test("-7999999999999", 3, Floor, "-1000000000000", Less); test("-7999999999999", 3, Ceiling, "-999999999999", Greater); test("-7999999999999", 3, Nearest, "-1000000000000", Less); test("-8000000000000", 3, Down, "-1000000000000", Equal); test("-8000000000000", 3, Up, "-1000000000000", Equal); test("-8000000000000", 3, Floor, "-1000000000000", Equal); test("-8000000000000", 3, Ceiling, "-1000000000000", Equal); test("-8000000000000", 3, Nearest, "-1000000000000", Equal); test("-8000000000000", 3, Exact, "-1000000000000", Equal); test("-8000000000001", 3, Down, "-1000000000000", Greater); test("-8000000000001", 3, Up, "-1000000000001", Less); test("-8000000000001", 3, Floor, "-1000000000001", Less); test("-8000000000001", 3, Ceiling, "-1000000000000", Greater); test("-8000000000001", 3, Nearest, "-1000000000000", Greater); test("-16777216000000000000", 24, Down, "-1000000000000", Equal); test("-16777216000000000000", 24, Up, "-1000000000000", Equal); test("-16777216000000000000", 24, Floor, "-1000000000000", Equal); test( "-16777216000000000000", 24, Ceiling, "-1000000000000", Equal, ); test( "-16777216000000000000", 24, Nearest, "-1000000000000", Equal, ); test("-16777216000000000000", 24, Exact, "-1000000000000", Equal); test("-33554432000000000000", 25, Down, "-1000000000000", Equal); test("-33554432000000000000", 25, Up, "-1000000000000", Equal); test("-33554432000000000000", 25, Floor, "-1000000000000", Equal); test( "-33554432000000000000", 25, Ceiling, "-1000000000000", Equal, ); test( "-33554432000000000000", 25, Nearest, "-1000000000000", Equal, ); test("-33554432000000000000", 25, Exact, "-1000000000000", Equal); test("-2147483648000000000000", 31, Down, "-1000000000000", Equal); test("-2147483648000000000000", 31, Up, "-1000000000000", Equal); test( "-2147483648000000000000", 31, Floor, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Ceiling, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Nearest, "-1000000000000", Equal, ); test( "-2147483648000000000000", 31, Exact, "-1000000000000", Equal, ); test("-4294967296000000000000", 32, Down, "-1000000000000", Equal); test("-4294967296000000000000", 32, Up, "-1000000000000", Equal); test( "-4294967296000000000000", 32, Floor, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Ceiling, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Nearest, "-1000000000000", Equal, ); test( "-4294967296000000000000", 32, Exact, "-1000000000000", Equal, ); test("-8589934592000000000000", 33, Down, "-1000000000000", Equal); test("-8589934592000000000000", 33, Up, "-1000000000000", Equal); test( "-8589934592000000000000", 33, Floor, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Ceiling, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Nearest, "-1000000000000", Equal, ); test( "-8589934592000000000000", 33, Exact, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Down, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Up, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Floor, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Ceiling, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Nearest, "-1000000000000", Equal, ); test( "-1267650600228229401496703205376000000000000", 100, Exact, "-1000000000000", Equal, ); test("-1000000000000", 10, Down, "-976562500", Equal); test("-1000000000000", 10, Up, "-976562500", Equal); test("-1000000000000", 10, Floor, "-976562500", Equal); test("-1000000000000", 10, Ceiling, "-976562500", Equal); test("-1000000000000", 10, Nearest, "-976562500", Equal); test("-1000000000000", 10, Exact, "-976562500", Equal); test("-980657949", 72, Down, "0", Greater); test("-980657949", 72, Up, "-1", Less); test("-980657949", 72, Floor, "-1", Less); test("-980657949", 72, Ceiling, "0", Greater); test("-980657949", 72, Nearest, "0", Greater); test("-4294967295", 31, Down, "-1", Greater); test("-4294967295", 31, Up, "-2", Less); test("-4294967295", 31, Floor, "-2", Less); test("-4294967295", 31, Ceiling, "-1", Greater); test("-4294967295", 31, Nearest, "-2", Less); test("-4294967295", 32, Down, "0", Greater); test("-4294967295", 32, Up, "-1", Less); test("-4294967295", 32, Floor, "-1", Less); test("-4294967295", 32, Ceiling, "0", Greater); test("-4294967295", 32, Nearest, "-1", Less); test("-4294967296", 32, Down, "-1", Equal); test("-4294967296", 32, Up, "-1", Equal); test("-4294967296", 32, Floor, "-1", Equal); test("-4294967296", 32, Ceiling, "-1", Equal); test("-4294967296", 32, Nearest, "-1", Equal); test("-4294967296", 32, Exact, "-1", Equal); test("-4294967296", 33, Down, "0", Greater); test("-4294967296", 33, Up, "-1", Less); test("-4294967296", 33, Floor, "-1", Less); test("-4294967296", 33, Ceiling, "0", Greater); test("-4294967296", 33, Nearest, "0", Greater); test("0", -10, Exact, "0", Equal); test("123", -1, Exact, "246", Equal); test("123", -2, Exact, "492", Equal); test("123", -25, Exact, "4127195136", Equal); test("123", -26, Exact, "8254390272", Equal); test( "123", -100, Exact, "155921023828072216384094494261248", Equal, ); test("2147483648", -1, Exact, "4294967296", Equal); test("1000000000000", -3, Exact, "8000000000000", Equal); test("1000000000000", -24, Exact, "16777216000000000000", Equal); test("1000000000000", -25, Exact, "33554432000000000000", Equal); test("1000000000000", -31, Exact, "2147483648000000000000", Equal); test("1000000000000", -32, Exact, "4294967296000000000000", Equal); test("1000000000000", -33, Exact, "8589934592000000000000", Equal); test( "1000000000000", -100, Exact, "1267650600228229401496703205376000000000000", Equal, ); test("-123", -1, Exact, "-246", Equal); test("-123", -2, Exact, "-492", Equal); test("-123", -25, Exact, "-4127195136", Equal); test("-123", -26, Exact, "-8254390272", Equal); test( "-123", -100, Exact, "-155921023828072216384094494261248", Equal, ); test("-2147483648", -1, Exact, "-4294967296", Equal); test("-1000000000000", -3, Exact, "-8000000000000", Equal); test("-1000000000000", -24, Exact, "-16777216000000000000", Equal); test("-1000000000000", -25, Exact, "-33554432000000000000", Equal); test( "-1000000000000", -31, Exact, "-2147483648000000000000", Equal, ); test( "-1000000000000", -32, Exact, "-4294967296000000000000", Equal, ); test( "-1000000000000", -33, Exact, "-8589934592000000000000", Equal, ); test( "-1000000000000", -100, Exact, "-1267650600228229401496703205376000000000000", Equal, ); }; } #[test] fn test_shr_round_signed() { apply_to_signeds!(test_shr_round_signed_helper); } macro_rules! shr_round_signed_fail_helper { ($t:ident) => { assert_panic!(Integer::from(-123).shr_round_assign($t::ONE, Exact)); assert_panic!(Integer::from(-123).shr_round_assign($t::exact_from(100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round_assign($t::ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round_assign($t::exact_from(100), Exact) ); assert_panic!(Integer::from(-123).shr_round($t::ONE, Exact)); assert_panic!(Integer::from(-123).shr_round($t::exact_from(100), Exact)); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round($t::ONE, Exact) ); assert_panic!( Integer::from_str("-1000000000001") .unwrap() .shr_round($t::exact_from(100), Exact) ); assert_panic!((&Integer::from(-123)).shr_round($t::ONE, Exact)); assert_panic!((&Integer::from(-123)).shr_round($t::exact_from(100), Exact)); assert_panic!((&Integer::from_str("-1000000000001").unwrap()).shr_round($t::ONE, Exact)); assert_panic!( (&Integer::from_str("-1000000000001").unwrap()).shr_round($t::exact_from(100), Exact) ); }; } #[test] fn shr_round_signed_fail() { apply_to_signeds!(shr_round_signed_fail_helper); } fn shr_round_properties_helper_unsigned() where Integer: Shl + ShrRound + ShrRoundAssign, for<'a> &'a Integer: Shl + ShrRound, Natural: Shl, for<'a> &'a Natural: ShrRound, SignedLimb: ShrRound, { integer_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(n, u, rm)| { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(u, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); assert!(shifted.le_abs(&n)); let (s_alt, o_alt) = (-&n).shr_round(u, -rm); assert_eq!(-s_alt, shifted); assert_eq!(o_alt, o.reverse()); assert_eq!((&n).div_round(Integer::ONE << u, rm), (shifted.clone(), o)); assert_eq!(n.divisible_by_power_of_2(u.exact_into()), o == Equal); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } assert_eq!((shifted << u).cmp(&n), o); }); integer_unsigned_pair_gen_var_2::().test_properties(|(n, u)| { let left_shifted = &n << u; let no = (n, Equal); assert_eq!((&left_shifted).shr_round(u, Down), no); assert_eq!((&left_shifted).shr_round(u, Up), no); assert_eq!((&left_shifted).shr_round(u, Floor), no); assert_eq!((&left_shifted).shr_round(u, Ceiling), no); assert_eq!((&left_shifted).shr_round(u, Nearest), no); assert_eq!((&left_shifted).shr_round(u, Exact), no); }); integer_unsigned_pair_gen_var_5::().test_properties(|(n, u)| { let floor = (&n).shr_round(u, Floor); assert_eq!(floor.1, Less); let ceiling = (&floor.0 + Integer::ONE, Greater); assert_eq!((&n).shr_round(u, Ceiling), ceiling); if n >= 0 { assert_eq!((&n).shr_round(u, Up), ceiling); assert_eq!((&n).shr_round(u, Down), floor); } else { assert_eq!((&n).shr_round(u, Up), floor); assert_eq!((&n).shr_round(u, Down), ceiling); } let nearest = n.shr_round(u, Nearest); assert!(nearest == floor || nearest == ceiling); }); integer_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shr_round(T::ZERO, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { assert_eq!(Integer::ZERO.shr_round(u, rm), (Integer::ZERO, Equal)); }); natural_unsigned_rounding_mode_triple_gen_var_1::().test_properties(|(n, u, rm)| { let (s, o) = (&n).shr_round(u, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shr_round(u, rm)); }); signed_unsigned_rounding_mode_triple_gen_var_2::().test_properties( |(n, u, rm)| { let (s, o) = n.shr_round(u, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shr_round(u, rm)); }, ); } fn shr_round_properties_helper_signed() where Integer: Shl + ShrRound + ShrRoundAssign, for<'a> &'a Integer: ShrRound, Natural: Shl, for<'a> &'a Natural: ShrRound, SignedLimb: ArithmeticCheckedShr + ShrRound, { integer_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (s, o_alt) = (-&n).shr_round(i, -rm); assert_eq!(-s, shifted); assert_eq!(o_alt, o.reverse()); assert_eq!( i <= T::ZERO || n.divisible_by_power_of_2(i.exact_into()), o == Equal ); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if i >= T::ZERO { assert_eq!((shifted << i).cmp(&n), o); } }); integer_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shr_round(T::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(Integer::ZERO.shr_round(i, rm), (Integer::ZERO, Equal)); }); natural_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { let (s, o) = (&n).shr_round(i, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shr_round(i, rm)); }); signed_signed_rounding_mode_triple_gen_var_3::().test_properties( |(n, i, rm)| { if n.arithmetic_checked_shr(i).is_some() { let (s, o) = n.shr_round(i, rm); assert_eq!((Integer::from(s), o), Integer::from(n).shr_round(i, rm)); } }, ); } #[test] fn shr_round_properties() { apply_fn_to_unsigneds!(shr_round_properties_helper_unsigned); apply_fn_to_signeds!(shr_round_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::arithmetic::sign::num_sign; use num::BigInt; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_sign() { let test = |s, out| { assert_eq!(Integer::from_str(s).unwrap().sign(), out); assert_eq!(num_sign(&BigInt::from_str(s).unwrap()), out); assert_eq!(rug::Integer::from_str(s).unwrap().cmp0(), out); }; test("0", Equal); test("123", Greater); test("-123", Less); test("1000000000000", Greater); test("-1000000000000", Less); } #[test] fn sign_properties() { integer_gen().test_properties(|n| { let sign = n.sign(); assert_eq!(rug::Integer::from(&n).cmp0(), sign); assert_eq!(num_sign(&BigInt::from(&n)), sign); assert_eq!(n.partial_cmp(&0), Some(sign)); assert_eq!((-n).sign(), sign.reverse()); }); signed_gen::().test_properties(|i| { assert_eq!(Integer::from(i).sign(), i.sign()); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingSqrt, CeilingSqrtAssign, CheckedRoot, CheckedSqrt, FloorRoot, FloorSqrt, FloorSqrtAssign, Square, }; use malachite_base::num::basic::traits::{NegativeOne, One}; use malachite_base::test_util::generators::signed_gen_var_2; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen_var_4, natural_gen}; use num::BigInt; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_floor_sqrt() { let test = |s, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.clone().floor_sqrt().to_string(), out); assert_eq!((&n).floor_sqrt().to_string(), out); let mut n = n; n.floor_sqrt_assign(); assert_eq!(n.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "1"); test("3", "1"); test("4", "2"); test("5", "2"); test("10", "3"); test("100", "10"); test("1000000000", "31622"); test("152415765279683", "12345677"); test("152415765279684", "12345678"); test("152415765279685", "12345678"); test( "10000000000000000000000000000000000000000", "100000000000000000000", ); test( "100000000000000000000000000000000000000000", "316227766016837933199", ); } #[test] pub fn floor_sqrt_fail() { assert_panic!(Integer::NEGATIVE_ONE.floor_sqrt()); } #[test] fn test_ceiling_sqrt() { let test = |s, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.clone().ceiling_sqrt().to_string(), out); assert_eq!((&n).ceiling_sqrt().to_string(), out); let mut n = n; n.ceiling_sqrt_assign(); assert_eq!(n.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "2"); test("3", "2"); test("4", "2"); test("5", "3"); test("10", "4"); test("100", "10"); test("1000000000", "31623"); test("152415765279683", "12345678"); test("152415765279684", "12345678"); test("152415765279685", "12345679"); test( "10000000000000000000000000000000000000000", "100000000000000000000", ); test( "100000000000000000000000000000000000000000", "316227766016837933200", ); } #[test] pub fn ceiling_sqrt_fail() { assert_panic!(Integer::NEGATIVE_ONE.ceiling_sqrt()); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_checked_sqrt() { let test = |s, out: Option<&str>| { let n = Integer::from_str(s).unwrap(); let out = out.map(|s| s.to_string()); assert_eq!(n.clone().checked_sqrt().map(|x| x.to_string()), out); assert_eq!((&n).checked_sqrt().map(|x| x.to_string()), out); }; test("0", Some("0")); test("1", Some("1")); test("2", None); test("3", None); test("4", Some("2")); test("5", None); test("10", None); test("100", Some("10")); test("1000000000", None); test("152415765279683", None); test("152415765279684", Some("12345678")); test("152415765279685", None); test( "10000000000000000000000000000000000000000", Some("100000000000000000000"), ); test("100000000000000000000000000000000000000000", None); } #[test] pub fn checked_sqrt_fail() { assert_panic!(Integer::NEGATIVE_ONE.checked_sqrt()); } #[test] fn floor_sqrt_properties() { integer_gen_var_4().test_properties(|n| { let sqrt = n.clone().floor_sqrt(); assert_eq!((&n).floor_sqrt(), sqrt); let mut n_alt = n.clone(); n_alt.floor_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!((&n).floor_root(2), sqrt); assert_eq!(Integer::from(&BigInt::from(&n).sqrt()), sqrt); assert_eq!(Integer::from(&rug::Integer::from(&n).sqrt()), sqrt); let square = (&sqrt).square(); let ceiling_sqrt = (&n).ceiling_sqrt(); if square == n { assert_eq!(ceiling_sqrt, sqrt); } else { assert_eq!(ceiling_sqrt, &sqrt + Integer::ONE); } assert!(square <= n); assert!((sqrt + Integer::ONE).square() > n); }); natural_gen().test_properties(|n| { assert_eq!((&n).floor_sqrt(), Integer::from(n).floor_sqrt()); }); signed_gen_var_2::().test_properties(|i| { assert_eq!(i.floor_sqrt(), Integer::from(i).floor_sqrt()); }); } #[test] fn ceiling_sqrt_properties() { integer_gen_var_4().test_properties(|n| { let sqrt = n.clone().ceiling_sqrt(); assert_eq!((&n).ceiling_sqrt(), sqrt); let mut n_alt = n.clone(); n_alt.ceiling_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!((&n).ceiling_root(2), sqrt); let square = (&sqrt).square(); let floor_sqrt = (&n).floor_sqrt(); if square == n { assert_eq!(floor_sqrt, sqrt); } else { assert_eq!(floor_sqrt, &sqrt - Integer::ONE); } assert!(square >= n); if n != 0 { assert!((sqrt - Integer::ONE).square() < n); } }); natural_gen().test_properties(|n| { assert_eq!((&n).ceiling_sqrt(), Integer::from(n).ceiling_sqrt()); }); signed_gen_var_2::().test_properties(|i| { assert_eq!(i.ceiling_sqrt(), Integer::from(i).ceiling_sqrt()); }); } #[test] fn checked_sqrt_properties() { integer_gen_var_4().test_properties(|n| { let sqrt = n.clone().checked_sqrt(); assert_eq!((&n).checked_sqrt(), sqrt); assert_eq!((&n).checked_root(2), sqrt); if let Some(sqrt) = sqrt { assert_eq!((&sqrt).square(), n); assert_eq!((&n).floor_sqrt(), sqrt); assert_eq!(n.ceiling_sqrt(), sqrt); } }); natural_gen().test_properties(|n| { assert_eq!( (&n).checked_sqrt().map(Integer::from), Integer::from(n).checked_sqrt() ); }); signed_gen_var_2::().test_properties(|i| { assert_eq!( i.checked_sqrt().map(Integer::from), Integer::from(i).checked_sqrt() ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, CheckedSqrt, Square, SquareAssign}; use malachite_base::test_util::generators::signed_gen_var_10; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen, natural_gen}; use std::str::FromStr; #[test] fn test_square() { let test = |x, out| { let u = Integer::from_str(x).unwrap(); assert_eq!(u.clone().square().to_string(), out); assert_eq!((&u).square().to_string(), out); let mut x = u; x.square_assign(); assert_eq!(x.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "4"); test("3", "9"); test("10", "100"); test("123", "15129"); test("1000", "1000000"); test("123456789", "15241578750190521"); test("-1", "1"); test("-2", "4"); test("-3", "9"); test("-10", "100"); test("-123", "15129"); test("-1000", "1000000"); test("-123456789", "15241578750190521"); } #[test] fn square_properties() { integer_gen().test_properties(|x| { let square = (&x).square(); assert!(square.is_valid()); let mut mut_x = x.clone(); mut_x.square_assign(); assert!(mut_x.is_valid()); assert_eq!(mut_x, square); assert_eq!(&x * &x, square); assert_eq!((-&x).square(), square); assert!(square >= 0); assert!(square >= x); assert_eq!(square.checked_sqrt(), Some(x.abs())); }); integer_pair_gen().test_properties(|(x, y)| { let x_squared = (&x).square(); let y_squared = (&y).square(); let xy = &x * &y; assert_eq!((&x + &y).square(), &x_squared + &y_squared + (&xy << 1)); assert_eq!((&x - &y).square(), &x_squared + &y_squared - (&xy << 1)); assert_eq!(xy.square(), x_squared * y_squared); }); natural_gen().test_properties(|x| { assert_eq!((&x).square(), Integer::from(x).square()); }); signed_gen_var_10::().test_properties(|x| { assert_eq!(x.square(), Integer::from(x).square()); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::{SignedDoubleLimb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen, natural_pair_gen}; use num::BigInt; use rug; use std::str::FromStr; #[test] fn test_sub() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n -= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n -= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigInt::from_str(s).unwrap() - BigInt::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() - rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "-123", "123"); test("123", "0", "123"); test("123", "-456", "579"); test("1000000000000", "-123", "1000000000123"); test("123", "-1000000000000", "1000000000123"); test("12345678987654321", "-314159265358979", "12659838253013300"); test("0", "123", "-123"); test("123", "123", "0"); test("123", "456", "-333"); test("1000000000000", "123", "999999999877"); test("123", "1000000000000", "-999999999877"); test("12345678987654321", "314159265358979", "12031519722295342"); } #[allow(clippy::eq_op)] #[test] fn sub_properties() { integer_pair_gen().test_properties(|(x, y)| { let diff_val_val = x.clone() - y.clone(); let diff_val_ref = x.clone() - &y; let diff_ref_val = &x - y.clone(); let diff = &x - &y; assert!(diff_val_val.is_valid()); assert!(diff_val_ref.is_valid()); assert!(diff_ref_val.is_valid()); assert!(diff.is_valid()); assert_eq!(diff_val_val, diff); assert_eq!(diff_val_ref, diff); assert_eq!(diff_ref_val, diff); let mut mut_x = x.clone(); mut_x -= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = x.clone(); mut_x -= &y; assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = rug::Integer::from(&x); mut_x -= rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), diff); assert_eq!(Integer::from(&(BigInt::from(&x) - BigInt::from(&y))), diff); assert_eq!( Integer::from(&(rug::Integer::from(&x) - rug::Integer::from(&y))), diff ); assert_eq!(&y - &x, -&diff); assert_eq!(&diff + &y, x); assert_eq!(x - diff, y); }); integer_gen().test_properties(|ref x| { assert_eq!(x - Integer::ZERO, *x); assert_eq!(Integer::ZERO - x, -x); assert_eq!(x - -x, x << 1); assert_eq!(x - x, 0); }); natural_pair_gen().test_properties(|(x, y)| { if x >= y { assert_eq!(&x - &y, Integer::from(x) - Integer::from(y)); } else { assert_eq!(-(&y - &x), Integer::from(x) - Integer::from(y)); } }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(SignedDoubleLimb::from(x) - SignedDoubleLimb::from(y)), Integer::from(x) - Integer::from(y) ); }); } ================================================ FILE: malachite-nz/tests/integer/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedSubMul, SubMul, SubMulAssign, UnsignedAbs}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::test_util::generators::{ signed_triple_gen, signed_triple_gen_var_2, unsigned_vec_triple_gen_var_39, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, }; use malachite_nz::integer::Integer; use malachite_nz::integer::arithmetic::sub_mul::{ limbs_overflowing_sub_mul, limbs_overflowing_sub_mul_in_place_left, limbs_overflowing_sub_mul_limb, limbs_overflowing_sub_mul_limb_in_place_either, limbs_overflowing_sub_mul_limb_in_place_left, limbs_overflowing_sub_mul_limb_in_place_right, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen, integer_triple_gen}; use std::str::FromStr; #[test] fn test_limbs_overflowing_sub_mul_limb() { let test = |xs_before: &[Limb], ys_before: &[Limb], z: Limb, result: &[Limb], sign: bool| { let (result_alt, sign_alt) = limbs_overflowing_sub_mul_limb(xs_before, ys_before, z); assert_eq!(&result_alt, &result); assert_eq!(sign_alt, sign); let mut xs = xs_before.to_vec(); assert_eq!( limbs_overflowing_sub_mul_limb_in_place_left(&mut xs, ys_before, z), sign ); assert_eq!(xs, result); let mut ys = ys_before.to_vec(); assert_eq!( limbs_overflowing_sub_mul_limb_in_place_right(xs_before, &mut ys, z), sign ); assert_eq!(ys, result); }; #[cfg(feature = "32_bit_limbs")] { test(&[123, 456], &[123], 4, &[4294966927, 455, 0], true); test(&[123, 456], &[123], u32::MAX, &[246, 333, 0], true); test(&[123], &[123], 1, &[0, 0], true); test(&[123], &[123], 4, &[369, 0], false); test( &[123], &[123, 456], u32::MAX, &[4294967050, 4294966962, 455], false, ); test( &[8191], &[0, 4160749568], 1610678208, &[4294959105, 4294967295, 1560344513], false, ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[18446744073709551615], &[0, 18446744056529682432], 18446742974197923840, &[1, 18446744073709551615, 18446742957018055679], false, ); } } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_overflowing_sub_mul_limb_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], z: Limb, right: bool, xs_after: &[Limb], ys_after: &[Limb], sign| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!( limbs_overflowing_sub_mul_limb_in_place_either(&mut xs, &mut ys, z), (right, sign) ); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test( &[123, 456], &[123], 4, false, &[4294966927, 455, 0], &[123], true, ); test( &[123, 456], &[123], u32::MAX, false, &[246, 333, 0], &[123], true, ); test(&[123], &[123], 1, false, &[0, 0], &[123], true); test(&[123], &[123], 4, false, &[369, 0], &[123], false); test( &[123], &[123, 456], u32::MAX, true, &[123], &[4294967050, 4294966962, 455], false, ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_overflowing_sub_mul_and_limbs_overflowing_sub_mul_in_place_left() { let test = |xs_before: &[Limb], ys: &[Limb], zs: &[Limb], result: &[Limb], sign: bool| { let (result_alt, sign_alt) = limbs_overflowing_sub_mul(xs_before, ys, zs); assert_eq!(result_alt, result); assert_eq!(sign_alt, sign); let mut xs = xs_before.to_vec(); assert_eq!( limbs_overflowing_sub_mul_in_place_left(&mut xs, ys, zs), sign ); assert_eq!(xs, result); }; test( &[123, 456], &[123, 789], &[321, 654], &[39360, 333255, 516006], false, ); test( &[123, 456, 789, 987, 654], &[123, 789], &[321, 654], &[4294927936, 4294634040, 4294452078, 986, 654], true, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_overflowing_sub_mul_fail_1() { limbs_overflowing_sub_mul(&[10, 10], &[], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_overflowing_sub_mul_fail_2() { limbs_overflowing_sub_mul(&[10, 10], &[10, 10], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_overflowing_sub_mul_in_place_left_fail_1() { let mut xs = vec![10, 10]; limbs_overflowing_sub_mul_in_place_left(&mut xs, &[], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_overflowing_sub_mul_in_place_left_fail_2() { let mut xs = vec![10, 10]; limbs_overflowing_sub_mul_in_place_left(&mut xs, &[10, 10], &[]); } #[test] fn test_sub_mul() { let test = |r, s, t, out| { let u = Integer::from_str(r).unwrap(); let v = Integer::from_str(s).unwrap(); let w = Integer::from_str(t).unwrap(); let mut a = u.clone(); a.sub_mul_assign(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.sub_mul_assign(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.sub_mul_assign(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.sub_mul_assign(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().sub_mul(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().sub_mul(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().sub_mul(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().sub_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = (&u).sub_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); }; test("0", "0", "0", "0"); test("0", "0", "123", "0"); test("123", "0", "5", "123"); test("123", "-5", "1", "128"); test("123", "-5", "100", "623"); test("10", "-3", "4", "22"); test("1000000000000", "0", "123", "1000000000000"); test("1000000000000", "-1", "123", "1000000000123"); test("1000000000000", "-123", "1", "1000000000123"); test("1000000000000", "-123", "100", "1000000012300"); test("1000000000000", "-100", "123", "1000000012300"); test("1000000000000", "-65536", "65536", "1004294967296"); test("1000000000000", "-1000000000000", "0", "1000000000000"); test("1000000000000", "-1000000000000", "1", "2000000000000"); test("1000000000000", "-1000000000000", "100", "101000000000000"); test("0", "-1000000000000", "100", "100000000000000"); test( "1000000000000", "-65536", "1000000000000", "65537000000000000", ); test( "1000000000000", "-1000000000000", "1000000000000", "1000000000001000000000000", ); test( "0", "-1000000000000", "1000000000000", "1000000000000000000000000", ); test("123", "5", "-1", "128"); test("123", "5", "-100", "623"); test("10", "3", "-4", "22"); test("1000000000000", "1", "-123", "1000000000123"); test("1000000000000", "123", "-1", "1000000000123"); test("1000000000000", "123", "-100", "1000000012300"); test("1000000000000", "100", "-123", "1000000012300"); test("1000000000000", "65536", "-65536", "1004294967296"); test("1000000000000", "1000000000000", "-1", "2000000000000"); test("1000000000000", "1000000000000", "-100", "101000000000000"); test("0", "1000000000000", "-100", "100000000000000"); test( "1000000000000", "65536", "-1000000000000", "65537000000000000", ); test( "1000000000000", "1000000000000", "-1000000000000", "1000000000001000000000000", ); test( "0", "1000000000000", "-1000000000000", "1000000000000000000000000", ); test("0", "0", "-123", "0"); test("123", "0", "-5", "123"); test("123", "5", "1", "118"); test("123", "-5", "-1", "118"); test("123", "5", "100", "-377"); test("123", "-5", "-100", "-377"); test("10", "3", "4", "-2"); test("10", "-3", "-4", "-2"); test("15", "3", "4", "3"); test("15", "-3", "-4", "3"); test("1000000000000", "0", "-123", "1000000000000"); test("1000000000000", "1", "123", "999999999877"); test("1000000000000", "-1", "-123", "999999999877"); test("1000000000000", "123", "1", "999999999877"); test("1000000000000", "-123", "-1", "999999999877"); test("1000000000000", "123", "100", "999999987700"); test("1000000000000", "-123", "-100", "999999987700"); test("1000000000000", "100", "123", "999999987700"); test("1000000000000", "-100", "-123", "999999987700"); test("1000000000000", "65536", "65536", "995705032704"); test("1000000000000", "-65536", "-65536", "995705032704"); test("1000000000000", "1000000000000", "0", "1000000000000"); test("1000000000000", "1000000000000", "1", "0"); test("1000000000000", "-1000000000000", "-1", "0"); test("1000000000000", "1000000000000", "100", "-99000000000000"); test("1000000000000", "-1000000000000", "-100", "-99000000000000"); test("0", "1000000000000", "100", "-100000000000000"); test("4294967296", "1", "1", "4294967295"); test("4294967296", "-1", "-1", "4294967295"); test("3902609153", "88817093856604", "1", "-88813191247451"); test("3902609153", "-88817093856604", "-1", "-88813191247451"); test("-123", "0", "5", "-123"); test("-123", "5", "1", "-128"); test("-123", "5", "100", "-623"); test("-10", "3", "4", "-22"); test("-1000000000000", "0", "123", "-1000000000000"); test("-1000000000000", "1", "123", "-1000000000123"); test("-1000000000000", "123", "1", "-1000000000123"); test("-1000000000000", "123", "100", "-1000000012300"); test("-1000000000000", "100", "123", "-1000000012300"); test("-1000000000000", "65536", "65536", "-1004294967296"); test("-1000000000000", "1000000000000", "0", "-1000000000000"); test("-1000000000000", "1000000000000", "1", "-2000000000000"); test("-1000000000000", "1000000000000", "100", "-101000000000000"); test( "-1000000000000", "65536", "1000000000000", "-65537000000000000", ); test( "-1000000000000", "1000000000000", "1000000000000", "-1000000000001000000000000", ); test( "0", "1000000000000", "1000000000000", "-1000000000000000000000000", ); test("-123", "-5", "-1", "-128"); test("-123", "-5", "-100", "-623"); test("-10", "-3", "-4", "-22"); test("-1000000000000", "-1", "-123", "-1000000000123"); test("-1000000000000", "-123", "-1", "-1000000000123"); test("-1000000000000", "-123", "-100", "-1000000012300"); test("-1000000000000", "-100", "-123", "-1000000012300"); test("-1000000000000", "-65536", "-65536", "-1004294967296"); test("-1000000000000", "-1000000000000", "-1", "-2000000000000"); test( "-1000000000000", "-1000000000000", "-100", "-101000000000000", ); test( "-1000000000000", "-65536", "-1000000000000", "-65537000000000000", ); test( "-1000000000000", "-1000000000000", "-1000000000000", "-1000000000001000000000000", ); test("-123", "0", "-5", "-123"); test("-123", "-5", "1", "-118"); test("-123", "5", "-1", "-118"); test("-123", "-5", "100", "377"); test("-123", "5", "-100", "377"); test("-10", "-3", "4", "2"); test("-10", "3", "-4", "2"); test("-15", "-3", "4", "-3"); test("-15", "3", "-4", "-3"); test("-1000000000000", "0", "-123", "-1000000000000"); test("-1000000000000", "-1", "123", "-999999999877"); test("-1000000000000", "1", "-123", "-999999999877"); test("-1000000000000", "-123", "1", "-999999999877"); test("-1000000000000", "123", "-1", "-999999999877"); test("-1000000000000", "-123", "100", "-999999987700"); test("-1000000000000", "123", "-100", "-999999987700"); test("-1000000000000", "-100", "123", "-999999987700"); test("-1000000000000", "100", "-123", "-999999987700"); test("-1000000000000", "-65536", "65536", "-995705032704"); test("-1000000000000", "65536", "-65536", "-995705032704"); test("-1000000000000", "-1000000000000", "0", "-1000000000000"); test("-1000000000000", "-1000000000000", "1", "0"); test("-1000000000000", "1000000000000", "-1", "0"); test("-1000000000000", "-1000000000000", "100", "99000000000000"); test("-1000000000000", "1000000000000", "-100", "99000000000000"); test("-4294967296", "-1", "1", "-4294967295"); test("-4294967296", "1", "-1", "-4294967295"); test("-3902609153", "-88817093856604", "1", "88813191247451"); test("-3902609153", "88817093856604", "-1", "88813191247451"); test( "1000000000000000000000000", "1000000000000", "1000000000000", "0", ); test( "18446744073709551615", "340282366604025813406317257057592410112", "18446742974197923840", "-6277101355396255406250174417290596496345921599978512318465", ); } #[test] fn limbs_overflowing_sub_mul_limb_properties() { unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties(|(a, b, c)| { let (result, sign) = limbs_overflowing_sub_mul_limb(&a, &b, c); let expected_result = Integer::from(Natural::from_owned_limbs_asc(a)).sub_mul( Integer::from(Natural::from_owned_limbs_asc(b)), Integer::from(c), ); assert_eq!(sign, expected_result >= 0); assert_eq!( Natural::from_owned_limbs_asc(result), expected_result.unsigned_abs() ); }); } #[test] fn limbs_overflowing_sub_mul_limb_in_place_left_properties() { unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties(|(mut a, b, c)| { let a_old = a.clone(); let sign = limbs_overflowing_sub_mul_limb_in_place_left(&mut a, &b, c); let expected_result = Integer::from(Natural::from_owned_limbs_asc(a_old)).sub_mul( Integer::from(Natural::from_owned_limbs_asc(b)), Integer::from(c), ); assert_eq!(sign, expected_result >= 0); assert_eq!( Natural::from_owned_limbs_asc(a), expected_result.unsigned_abs(), ); }); } #[test] fn limbs_overflowing_sub_mul_limb_in_place_right_properties() { unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties(|(a, mut b, c)| { let b_old = b.clone(); let sign = limbs_overflowing_sub_mul_limb_in_place_right(&a, &mut b, c); let expected_result = Integer::from(Natural::from_owned_limbs_asc(a)).sub_mul( Integer::from(Natural::from_owned_limbs_asc(b_old)), Integer::from(c), ); assert_eq!(sign, expected_result >= 0); assert_eq!( Natural::from_owned_limbs_asc(b), expected_result.unsigned_abs() ); }); } #[test] fn limbs_overflowing_sub_mul_limb_in_place_either_properties() { unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties(|(mut a, mut b, c)| { let a_old = a.clone(); let b_old = b.clone(); let (right, sign) = limbs_overflowing_sub_mul_limb_in_place_either(&mut a, &mut b, c); let expected_result = Integer::from(Natural::from_limbs_asc(&a_old)).sub_mul( Integer::from(Natural::from_limbs_asc(&b_old)), Integer::from(c), ); let result = Natural::from_owned_limbs_asc(if right { assert_eq!(a_old, a); b } else { assert_eq!(b_old, b); a }); assert_eq!(sign, expected_result >= 0); assert_eq!(result, expected_result.unsigned_abs()); }); } #[test] fn limbs_overflowing_sub_mul_properties() { unsigned_vec_triple_gen_var_39().test_properties(|(a, b, c)| { let (result, sign) = limbs_overflowing_sub_mul(&a, &b, &c); let expected_result = Integer::from(Natural::from_owned_limbs_asc(a)).sub_mul( Integer::from(Natural::from_owned_limbs_asc(b)), Integer::from(Natural::from_owned_limbs_asc(c)), ); if expected_result != 0 { assert_eq!(sign, expected_result >= 0); } assert_eq!( Natural::from_owned_limbs_asc(result), expected_result.unsigned_abs() ); }); } #[test] fn limbs_overflowing_sub_mul_in_place_left_properties() { unsigned_vec_triple_gen_var_39().test_properties(|(mut a, b, c)| { let a_old = a.clone(); let sign = limbs_overflowing_sub_mul_in_place_left(&mut a, &b, &c); let expected_result = Integer::from(Natural::from_owned_limbs_asc(a_old)).sub_mul( Integer::from(Natural::from_owned_limbs_asc(b)), Integer::from(Natural::from_owned_limbs_asc(c)), ); if expected_result != 0 { assert_eq!(sign, expected_result >= 0); } assert_eq!( Natural::from_owned_limbs_asc(a), expected_result.unsigned_abs() ); }); } #[test] fn sub_mul_properties() { integer_triple_gen().test_properties(|(a, b, c)| { let mut mut_a = a.clone(); mut_a.sub_mul_assign(b.clone(), c.clone()); assert!(mut_a.is_valid()); let result = mut_a; let mut mut_a = a.clone(); mut_a.sub_mul_assign(b.clone(), &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.sub_mul_assign(&b, c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.sub_mul_assign(&b, &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let result_alt = a.clone().sub_mul(b.clone(), c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result = a.clone().sub_mul(b.clone(), &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result = a.clone().sub_mul(&b, c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result = a.clone().sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result = (&a).sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!(&a - &b * &c, result); assert_eq!((&a).sub_mul(&c, &b), result); assert_eq!((&a).sub_mul(&(-&b), &(-&c)), result); assert_eq!((-&a).sub_mul(&(-&b), &c), -&result); assert_eq!((-a).sub_mul(b, -c), -result); }); integer_gen().test_properties(|a| { assert_eq!((&a).sub_mul(&a, &Integer::ONE), 0); assert_eq!((&a).sub_mul(&(-&a), &Integer::NEGATIVE_ONE), 0); }); integer_pair_gen().test_properties(|(a, b)| { assert_eq!((&a).sub_mul(&Integer::ZERO, &b), a); assert_eq!((&a).sub_mul(&Integer::ONE, &b), &a - &b); assert_eq!(Integer::ZERO.sub_mul(&a, &b), -&a * &b); assert_eq!((&a).sub_mul(&b, &Integer::ZERO), a); assert_eq!((&a).sub_mul(&b, &Integer::ONE), &a - &b); assert_eq!((&a * &b).sub_mul(&a, &b), 0); assert_eq!((&a * &b).sub_mul(-a, -b), 0); }); signed_triple_gen_var_2::().test_properties(|(x, y, z)| { assert_eq!( x.sub_mul(y, z), Integer::from(x).sub_mul(Integer::from(y), Integer::from(z)) ); }); signed_triple_gen::().test_properties(|(x, y, z)| { let result = Integer::from(x).sub_mul(Integer::from(y), Integer::from(z)); assert_eq!( x.checked_sub_mul(y, z).is_some(), SignedLimb::convertible_from(&result) ); }); } ================================================ FILE: malachite-nz/tests/integer/basic/constants.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; use malachite_nz::integer::Integer; #[test] fn test_zero() { let zero = Integer::ZERO; assert!(zero.is_valid()); assert_eq!(zero, 0); assert_eq!(zero.to_string(), "0"); } #[test] fn test_one() { let one = Integer::ONE; assert!(one.is_valid()); assert_eq!(one, 1); assert_eq!(one.to_string(), "1"); } #[test] fn test_two() { let two = Integer::TWO; assert!(two.is_valid()); assert_eq!(two, 2); assert_eq!(two.to_string(), "2"); } #[test] fn test_negative_one() { let negative_one = Integer::NEGATIVE_ONE; assert!(negative_one.is_valid()); assert_eq!(negative_one, -1); assert_eq!(negative_one.to_string(), "-1"); } ================================================ FILE: malachite-nz/tests/integer/basic/default.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; #[test] fn test_default() { let default = Integer::default(); assert!(default.is_valid()); assert_eq!(default, 0); assert_eq!(default.to_string(), "0"); } ================================================ FILE: malachite-nz/tests/integer/basic/from_sign_and_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_bool_pair_gen, natural_gen}; use std::str::FromStr; #[test] fn test_from_sign_and_abs() { let test = |sign, abs, out| { let abs = Natural::from_str(abs).unwrap(); let x = Integer::from_sign_and_abs(sign, abs.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); let x = Integer::from_sign_and_abs_ref(sign, &abs); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(true, "0", "0"); test(false, "0", "0"); test(true, "123", "123"); test(false, "123", "-123"); test(true, "1000000000000", "1000000000000"); test(false, "1000000000000", "-1000000000000"); } #[test] fn from_sign_and_abs_properties() { natural_bool_pair_gen().test_properties(|(abs, sign)| { let x = Integer::from_sign_and_abs(sign, abs.clone()); assert!(x.is_valid()); let x_alt = Integer::from_sign_and_abs_ref(sign, &abs); assert!(x_alt.is_valid()); assert_eq!(x, x_alt); if abs != 0 { assert_eq!(x >= 0, sign); } assert_eq!(x.unsigned_abs(), abs); }); natural_gen() .test_properties(|abs| assert_eq!(Integer::from_sign_and_abs_ref(true, &abs), abs)); } ================================================ FILE: malachite-nz/tests/integer/basic/named.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_nz::integer::Integer; #[test] fn test_named() { assert_eq!(Integer::NAME, "Integer"); } ================================================ FILE: malachite-nz/tests/integer/basic/size.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use std::mem::size_of; #[test] fn test_size() { if size_of::() == 8 { assert_eq!(size_of::(), 32); } } ================================================ FILE: malachite-nz/tests/integer/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::test_cmp_helper; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use num::BigInt; use rug; use std::cmp::Ordering::*; #[test] fn test_ord() { let strings = &[ "-1000000000001", "-1000000000000", "-999999999999", "-123", "-2", "-1", "0", "1", "2", "123", "999999999999", "1000000000000", "1000000000001", ]; test_cmp_helper::(strings); test_cmp_helper::(strings); test_cmp_helper::(strings); } #[test] fn cmp_properties() { integer_pair_gen().test_properties(|(x, y)| { let ord = x.cmp(&y); assert_eq!(BigInt::from(&x).cmp(&BigInt::from(&y)), ord); assert_eq!(rug::Integer::from(&x).cmp(&rug::Integer::from(&y)), ord); assert_eq!(y.cmp(&x).reverse(), ord); assert_eq!(x == y, x.cmp(&y) == Equal); assert_eq!((-y).cmp(&-x), ord); }); integer_gen().test_properties(|x| { assert_eq!(x.cmp(&x), Equal); }); integer_triple_gen().test_properties(|(x, y, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).cmp(&Integer::from(&y)), x.cmp(&y)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).cmp(&Integer::from(y)), x.cmp(&y)); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::Zero; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::common::test_custom_cmp_helper; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use rug; use std::cmp::Ordering::*; #[test] fn test_ord_abs() { let strings = &["0", "1", "-2", "123", "-124", "999999999999", "-1000000000000", "1000000000001"]; test_custom_cmp_helper::(strings, OrdAbs::cmp_abs); test_custom_cmp_helper::(strings, rug::Integer::cmp_abs); } #[test] fn cmp_abs_properties() { integer_pair_gen().test_properties(|(x, y)| { let ord = x.cmp_abs(&y); assert_eq!((&x).abs().cmp(&(&y).abs()), ord); assert_eq!(rug::Integer::from(&x).cmp_abs(&rug::Integer::from(&y)), ord); assert_eq!((&x).abs().cmp(&(&y).abs()), ord); assert_eq!((-x).cmp_abs(&(-y)), ord); }); integer_gen().test_properties(|x| { assert_eq!(x.cmp_abs(&x), Equal); assert_eq!(x.cmp_abs(&-&x), Equal); assert!(x.ge_abs(&Integer::ZERO)); }); integer_triple_gen().test_properties(|(x, y, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).cmp_abs(&Integer::from(&y)), x.cmp(&y)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).cmp_abs(&Integer::from(y)), x.cmp_abs(&y)); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::test_eq_helper; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use num::BigInt; use rug; #[test] fn test_eq() { let strings = &["0", "1", "-1", "2", "-2", "123", "-123", "1000000000000", "-1000000000000"]; test_eq_helper::(strings); test_eq_helper::(strings); test_eq_helper::(strings); } #[allow(clippy::cmp_owned, clippy::eq_op)] #[test] fn eq_properties() { integer_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(BigInt::from(&x) == BigInt::from(&y), eq); assert_eq!(rug::Integer::from(&x) == rug::Integer::from(&y), eq); assert_eq!(y == x, eq); }); integer_gen().test_properties(|x| { assert_eq!(x, x); }); integer_triple_gen().test_properties(|(x, y, z)| { if x == y && y == z { assert_eq!(x, z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) == Integer::from(&y), x == y); assert_eq!(Integer::from(&x) == y, x == y); assert_eq!(x == Integer::from(&y), x == y); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x) == Integer::from(y), x == y); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{EqAbs, OrdAbs}; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use std::str::FromStr; #[test] fn test_eq_abs() { let test = |s, t, eq: bool| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == (&v).abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("123", "124", false); test("123", "122", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("1000000000000", "0", false); test("-123", "123", true); test("-123", "124", false); test("-123", "122", false); test("-1000000000000", "123", false); test("-123", "1000000000000", false); test("-1000000000000", "1000000000000", true); test("-1000000000000", "0", false); test("0", "-5", false); test("123", "-123", true); test("123", "-124", false); test("123", "-122", false); test("1000000000000", "-123", false); test("123", "-1000000000000", false); test("1000000000000", "-1000000000000", true); test("-123", "-123", true); test("-123", "-124", false); test("-123", "-122", false); test("-1000000000000", "-123", false); test("-123", "-1000000000000", false); test("-1000000000000", "-1000000000000", true); } #[allow(clippy::cmp_owned, clippy::eq_op)] #[test] fn eq_properties() { integer_pair_gen().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!((&x).abs() == (&y).abs(), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.cmp_abs(&y) == Equal, eq); assert_eq!(x.eq_abs(&-&y), eq); assert_eq!((-&x).eq_abs(&y), eq); assert_eq!((-x).eq_abs(&-y), eq); }); integer_gen().test_properties(|x| { assert!(x.eq_abs(&x)); }); integer_triple_gen().test_properties(|(x, y, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) == Integer::from(&y), x == y); assert_eq!(Integer::from(&x) == y, x == y); assert_eq!(x == Integer::from(&y), x == y); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).eq_abs(&Integer::from(y)), x.eq_abs(&y)); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_integer_natural_triple_gen, integer_natural_natural_triple_gen, integer_natural_pair_gen, natural_pair_gen, }; use std::str::FromStr; #[test] fn test_eq_abs_integer_natural() { let test = |s, t, eq: bool| { let u = Integer::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("123", "124", false); test("123", "122", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("1000000000000", "0", false); test("-123", "123", true); test("-123", "124", false); test("-123", "122", false); test("-1000000000000", "123", false); test("-123", "1000000000000", false); test("-1000000000000", "1000000000000", true); test("-1000000000000", "0", false); } #[test] fn eq_abs_natural_properties() { integer_natural_pair_gen().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!((&x).abs() == y, eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(x.eq_abs(&Integer::from(&y)), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!((-x).eq_abs(&y), eq); }); integer_integer_natural_triple_gen().test_properties(|(x, z, y)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); integer_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert_eq!(x, z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Integer::from(&y)), x == y); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_gen, integer_primitive_float_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_f32() { let test = |u, v: f32, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", -123.0, true); test("123", 5.0, false); test("123", -5.0, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f32::INFINITY, false); test("1", f32::NEGATIVE_INFINITY, false); test("1", f32::NAN, false); test("-123", 123.0, true); test("-123", -123.0, true); test("-123", 5.0, false); test("-123", -5.0, false); test("-1000000000000", 123.0, false); test("-1000000000000", -123.0, false); test("-1", 0.5, false); test("-1", -0.5, false); test("-1", f32::INFINITY, false); test("-1", f32::NEGATIVE_INFINITY, false); test("-1", f32::NAN, false); } #[test] fn test_eq_abs_f64() { let test = |u, v: f64, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", -123.0, true); test("123", 5.0, false); test("123", -5.0, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f64::INFINITY, false); test("1", f64::NEGATIVE_INFINITY, false); test("1", f64::NAN, false); test("-123", 123.0, true); test("-123", -123.0, true); test("-123", 5.0, false); test("-123", -5.0, false); test("-1000000000000", 123.0, false); test("-1000000000000", -123.0, false); test("-1", 0.5, false); test("-1", -0.5, false); test("-1", f64::INFINITY, false); test("-1", f64::NEGATIVE_INFINITY, false); test("-1", f64::NAN, false); } fn eq_abs_primitive_float_properties_helper< T: EqAbs + PartialEq + PrimitiveFloat, >() where Integer: EqAbs + PartialEq + PartialOrdAbs, { integer_primitive_float_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!((&x).abs() == y.abs(), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); integer_gen().test_properties(|n| { assert_ne!(n, T::NAN); assert_ne!(n, T::INFINITY); assert_ne!(n, T::NEGATIVE_INFINITY); }); } #[test] fn eq_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(eq_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_signed_pair_gen, integer_unsigned_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_u32() { let test = |u, v: u32, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 123, false); test("-123", 123, true); test("-123", 5, false); test("-1000000000000", 123, false); } #[test] fn test_eq_abs_u64() { let test = |u, v: u64, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-123", 123, true); test("-123", 5, false); test("-1000000000000", 1000000000000, true); test("-1000000000000", 1000000000001, false); test("-1000000000000000000000000", 1000000000000, false); } #[test] fn test_eq_abs_i32() { let test = |u, v: i32, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 123, false); test("-123", 123, true); test("-123", -123, true); test("-123", 5, false); test("-1000000000000", 123, false); } #[test] fn test_eq_abs_i64() { let test = |u, v: i64, eq: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-123", 123, true); test("-123", -123, true); test("-123", 5, false); test("-1000000000000", 1000000000000, true); test("-1000000000000", 1000000000001, false); test("-1000000000000000000000000", 1000000000000, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn eq_abs_primitive_int_properties_helper_unsigned< T: EqAbs + PartialEq + PrimitiveUnsigned, >() where Integer: EqAbs + From + PartialEq + PartialOrdAbs, { integer_unsigned_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == y, eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Integer::from(y)), x == y); }); } fn eq_abs_primitive_int_properties_helper_signed + PrimitiveSigned>() where Integer: EqAbs + From + TryFrom + PartialOrdAbs + PartialEq<::Output>, { integer_signed_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == y.unsigned_abs(), eq); assert_eq!( >::eq_abs(&x, &Integer::from(y)), eq ); assert_eq!(y.eq_abs(&x), eq); assert_eq!( >::eq_abs(&Integer::from(y), &x), eq ); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Integer::exact_from(x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Integer::exact_from(y)), x.eq_abs(&y)); }); } #[test] fn eq_abs_primitive_int_properties() { apply_fn_to_unsigneds!(eq_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(eq_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/integer/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::hash::hash; use malachite_nz::test_util::generators::integer_gen; #[test] fn hash_properties() { integer_gen().test_properties(|x| { assert_eq!(hash(&x), hash(&x.clone())); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 crate::malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::traits::Zero; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_natural_triple_gen, integer_natural_natural_triple_gen, integer_natural_pair_gen, natural_pair_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_integer_natural() { let test = |s, t, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Integer::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u).map(Ordering::reverse), cmp); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", "0", Some(Equal), false, false, true, true); test("0", "5", Some(Less), true, false, true, false); test("123", "123", Some(Equal), false, false, true, true); test("123", "124", Some(Less), true, false, true, false); test("123", "122", Some(Greater), false, true, false, true); test( "1000000000000", "123", Some(Greater), false, true, false, true, ); test("123", "1000000000000", Some(Less), true, false, true, false); test( "1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "0", Some(Greater), false, true, false, true, ); } #[test] fn partial_cmp_abs_natural_properties() { integer_natural_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp_abs(&y), cmp); assert_eq!(x.cmp_abs(&Integer::from(&y)), cmp.unwrap()); assert_eq!( Some(rug::Integer::from(&x).cmp_abs(&rug::Integer::from(&y))), cmp ); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); assert_eq!((-x).partial_cmp_abs(&y), cmp); }); integer_integer_natural_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); integer_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x < z); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x > z); } }); integer_gen().test_properties(|x| { assert!(x.ge_abs(&Natural::ZERO)); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Integer::from(&y)), Some(x.cmp(&y))); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_primitive_float_triple_gen, integer_primitive_float_pair_gen, integer_primitive_float_primitive_float_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_primitive_float() { let test = |u, v: f32, out: Option| { let u = Integer::from_str(u).unwrap(); let out_rev = out.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!((&u).abs().partial_cmp_abs(&v.abs()), out); assert_eq!(v.partial_cmp_abs(&u), out_rev); let v = f64::from(v); assert_eq!(u.partial_cmp_abs(&v), out); assert_eq!(v.partial_cmp_abs(&u), out_rev); }; test("5", f32::NAN, None); test("5", f32::INFINITY, Some(Less)); test("5", f32::NEGATIVE_INFINITY, Some(Less)); test("-5", f32::NAN, None); test("-5", f32::INFINITY, Some(Less)); test("-5", f32::NEGATIVE_INFINITY, Some(Less)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Less)); test("123", 123.0, Some(Equal)); test("123", 5.0, Some(Greater)); test("123", -123.0, Some(Equal)); test("-123", 123.0, Some(Equal)); test("-123", 5.0, Some(Greater)); test("-123", -123.0, Some(Equal)); test("1000000000000", 123.0, Some(Greater)); test("-1000000000000", 123.0, Some(Greater)); test("1208925819614629174706175", 1.2089258e24, Some(Less)); test("1208925819614629174706176", 1.2089258e24, Some(Equal)); test("1208925819614629174706177", 1.2089258e24, Some(Greater)); test("1208925819614629174706175", -1.2089258e24, Some(Less)); test("1208925819614629174706176", -1.2089258e24, Some(Equal)); test("1208925819614629174706177", -1.2089258e24, Some(Greater)); test("-1208925819614629174706175", 1.2089258e24, Some(Less)); test("-1208925819614629174706176", 1.2089258e24, Some(Equal)); test("-1208925819614629174706177", 1.2089258e24, Some(Greater)); test("-1208925819614629174706175", -1.2089258e24, Some(Less)); test("-1208925819614629174706176", -1.2089258e24, Some(Equal)); test("-1208925819614629174706177", -1.2089258e24, Some(Greater)); } fn partial_cmp_abs_primitive_float_properties_helper + PrimitiveFloat>() where Integer: PartialOrd + PartialOrdAbs, { integer_primitive_float_pair_gen::().test_properties(|(x, y)| { let cmp_abs = x.partial_cmp_abs(&y); let cmp_abs_rev = cmp_abs.map(Ordering::reverse); assert_eq!((&x).abs().partial_cmp_abs(&y.abs()), cmp_abs); assert_eq!(y.partial_cmp_abs(&x), cmp_abs_rev); assert_eq!((&x).abs().partial_cmp(&y.abs()), cmp_abs); assert_eq!(x.partial_cmp_abs(&-y), cmp_abs); }); integer_integer_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); integer_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u.lt_abs(&v)); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u.gt_abs(&v)); } }); integer_gen().test_properties(|x| { assert!(x.ge_abs(&T::ZERO)); assert!(x.lt_abs(&T::NEGATIVE_INFINITY)); assert!(x.lt_abs(&T::INFINITY)); }); } #[test] fn partial_cmp_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_signed_triple_gen, integer_integer_unsigned_triple_gen, integer_signed_pair_gen, integer_signed_signed_triple_gen, integer_unsigned_pair_gen, integer_unsigned_unsigned_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_u32() { let test = |s, v: u32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); } #[test] fn test_partial_cmp_abs_u64() { let test = |u, v: u64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", 1000000000001, Some(Less), true, false, true, false, ); } #[test] fn test_partial_cmp_abs_i32() { let test = |u, v: i32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.unsigned_abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("-123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("-123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test("-123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", -123, Some(Greater), false, true, false, true, ); } #[test] fn test_partial_cmp_abs_i64() { let test = |u, v: i64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Integer::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.unsigned_abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("-123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("-123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test("-123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", -123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", -1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", -1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "1000000000000", -1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", -1000000000001, Some(Less), true, false, true, false, ); } fn partial_cmp_abs_primitive_int_properties_helper_unsigned< T: PartialOrdAbs + PrimitiveUnsigned, >() where Integer: From + PartialOrdAbs + PartialOrd, { integer_unsigned_pair_gen::().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp(&y), cmp); assert_eq!(Some(x.cmp_abs(&Integer::from(y))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(y.partial_cmp_abs(&x), cmp_rev); assert_eq!(Some(Integer::from(y).cmp_abs(&x)), cmp_rev); assert_eq!((-x).partial_cmp_abs(&y), cmp); }); integer_integer_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); integer_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u < v); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u > v); } }); integer_gen().test_properties(|x| { assert!(x.ge_abs(&T::ZERO)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Integer::from(y)), Some(x.cmp(&y))); }); } fn partial_cmp_abs_primitive_int_properties_helper_signed< T: PartialOrdAbs + PartialOrd + PrimitiveSigned, >() where Integer: From + PartialOrdAbs + PartialOrd<::Output>, { integer_signed_pair_gen::().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp(&y.unsigned_abs()), cmp); assert_eq!(Some(x.cmp_abs(&Integer::from(y))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(y.partial_cmp_abs(&x), cmp_rev); assert_eq!(Some(Integer::from(y).cmp_abs(&x)), cmp_rev); assert_eq!((-&x).partial_cmp_abs(&y), cmp); if y != T::MIN { assert_eq!(x.partial_cmp_abs(&-y), cmp); assert_eq!((-x).partial_cmp_abs(&-y), cmp); } }); integer_integer_signed_triple_gen::().test_properties(|(n, m, i)| { if n.lt_abs(&i) && i.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&i) && i.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); integer_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i.lt_abs(&n) && n.lt_abs(&j) { assert!(i.lt_abs(&j)); } else if i.gt_abs(&n) && n.gt_abs(&j) { assert!(i.gt_abs(&j)); } }); integer_gen().test_properties(|x| { assert!(x.ge_abs(&T::ZERO)); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).partial_cmp_abs(&y), Some(x.cmp_abs(&y))); assert_eq!(x.partial_cmp_abs(&Integer::from(y)), Some(x.cmp_abs(&y))); }); } #[test] fn partial_cmp_abs_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_integer_natural_triple_gen, integer_natural_natural_triple_gen, integer_natural_pair_gen, natural_pair_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_natural() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u).map(Ordering::reverse), out); }; test("0", "0", Some(Equal)); test("0", "5", Some(Less)); test("123", "123", Some(Equal)); test("123", "124", Some(Less)); test("123", "122", Some(Greater)); test("1000000000000", "123", Some(Greater)); test("123", "1000000000000", Some(Less)); test("1000000000000", "1000000000000", Some(Equal)); test("-1000000000000", "1000000000000", Some(Less)); test("-1000000000000", "0", Some(Less)); } #[test] fn partial_cmp_natural_properties() { integer_natural_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp(&y); assert_eq!(x.cmp(&Integer::from(&y)), cmp.unwrap()); assert_eq!( rug::Integer::from(&x).partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); }); integer_integer_natural_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); integer_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Integer::from(&y)), Some(x.cmp(&y))); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_gen, integer_integer_primitive_float_triple_gen, integer_primitive_float_pair_gen, integer_primitive_float_primitive_float_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_primitive_float() { let test = |u, v: f32, out: Option| { let out_rev = out.map(Ordering::reverse); assert_eq!(Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Integer::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Integer::from_str(u).unwrap()), out_rev); let v = f64::from(v); assert_eq!(Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Integer::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Integer::from_str(u).unwrap()), out_rev); }; test("5", f32::NAN, None); test("5", f32::INFINITY, Some(Less)); test("5", f32::NEGATIVE_INFINITY, Some(Greater)); test("-5", f32::NAN, None); test("-5", f32::INFINITY, Some(Less)); test("-5", f32::NEGATIVE_INFINITY, Some(Greater)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Greater)); test("123", 123.0, Some(Equal)); test("123", 5.0, Some(Greater)); test("123", -123.0, Some(Greater)); test("-123", 123.0, Some(Less)); test("-123", 5.0, Some(Less)); test("-123", -123.0, Some(Equal)); test("1000000000000", 123.0, Some(Greater)); test("-1000000000000", 123.0, Some(Less)); test("1208925819614629174706175", 1.2089258e24, Some(Less)); test("1208925819614629174706176", 1.2089258e24, Some(Equal)); test("1208925819614629174706177", 1.2089258e24, Some(Greater)); test("1208925819614629174706175", -1.2089258e24, Some(Greater)); test("1208925819614629174706176", -1.2089258e24, Some(Greater)); test("1208925819614629174706177", -1.2089258e24, Some(Greater)); test("-1208925819614629174706175", 1.2089258e24, Some(Less)); test("-1208925819614629174706176", 1.2089258e24, Some(Less)); test("-1208925819614629174706177", 1.2089258e24, Some(Less)); test("-1208925819614629174706175", -1.2089258e24, Some(Greater)); test("-1208925819614629174706176", -1.2089258e24, Some(Equal)); test("-1208925819614629174706177", -1.2089258e24, Some(Less)); test("-117886223846050103296", -1.1788622e20, Some(Equal)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_float_properties_helper< T: PartialOrd + PartialOrd + PrimitiveFloat, >() where Integer: PartialOrd, rug::Integer: PartialOrd, { integer_primitive_float_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(rug::Integer::from(&n).partial_cmp(&u), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Integer::from(&n)), cmp_rev); }); integer_integer_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); integer_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); integer_gen().test_properties(|x| { assert!(x > T::NEGATIVE_INFINITY); assert!(x < T::INFINITY); }); } #[test] fn partial_cmp_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_integer_signed_triple_gen, integer_integer_unsigned_triple_gen, integer_signed_pair_gen, integer_signed_signed_triple_gen, integer_unsigned_pair_gen, integer_unsigned_unsigned_triple_gen, }; use malachite_nz::test_util::integer::comparison::partial_cmp_primitive_int::*; use num::BigInt; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_u32() { let test = |s, v: u32, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!( num_partial_cmp_primitive(&BigInt::from_str(s).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(s).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("-123", 123, Some(Less)); test("123", 124, Some(Less)); test("-123", 124, Some(Less)); test("123", 122, Some(Greater)); test("-123", 122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("-1000000000000", 123, Some(Less)); } #[test] fn test_partial_cmp_u64() { let test = |s, v: u64, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!( num_partial_cmp_primitive(&BigInt::from_str(s).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(s).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("-123", 123, Some(Less)); test("123", 124, Some(Less)); test("-123", 124, Some(Less)); test("123", 122, Some(Greater)); test("-123", 122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("1000000000000", 1000000000000, Some(Equal)); test("-1000000000000", 1000000000000, Some(Less)); test("1000000000000", 1000000000001, Some(Less)); test("-1000000000000", 1000000000001, Some(Less)); } #[test] fn test_partial_cmp_i32() { let test = |u, v: i32, out| { assert_eq!(Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( num_partial_cmp_primitive(&BigInt::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Integer::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("-123", 123, Some(Less)); test("-123", -123, Some(Equal)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("-123", 124, Some(Less)); test("-123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("-123", 122, Some(Less)); test("-123", -122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("-1000000000000", -123, Some(Less)); } #[test] fn test_partial_cmp_i64() { let test = |u, v: i64, out| { assert_eq!(Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( num_partial_cmp_primitive(&BigInt::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Integer::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("-123", 123, Some(Less)); test("-123", -123, Some(Equal)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("-123", 124, Some(Less)); test("-123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("-123", 122, Some(Less)); test("-123", -122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("-1000000000000", -123, Some(Less)); test("1000000000000", 1000000000000, Some(Equal)); test("1000000000000", -1000000000000, Some(Greater)); test("-1000000000000", 1000000000000, Some(Less)); test("-1000000000000", -1000000000000, Some(Equal)); test("1000000000000", 1000000000001, Some(Less)); test("1000000000000", -1000000000001, Some(Greater)); test("-1000000000000", 1000000000001, Some(Less)); test("-1000000000000", -1000000000001, Some(Greater)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_unsigned< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >() where BigInt: From, Integer: From + PartialOrd, rug::Integer: PartialOrd, { integer_unsigned_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(num_partial_cmp_primitive(&From::from(&n), u), cmp); assert_eq!(rug::Integer::from(&n).partial_cmp(&u), cmp); assert_eq!(Some(n.cmp(&Integer::from(u))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Integer::from(&n)), cmp_rev); assert_eq!(Some(Integer::from(u).cmp(&n)), cmp_rev); }); integer_integer_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); integer_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Integer::from(y)), Some(x.cmp(&y))); }); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_signed< T: PartialOrd + PartialOrd + PrimitiveSigned, >() where BigInt: From, Integer: From + PartialOrd, rug::Integer: PartialOrd, { integer_signed_pair_gen::().test_properties(|(n, i)| { let cmp = n.partial_cmp(&i); assert_eq!(num_partial_cmp_primitive(&From::from(&n), i), cmp); assert_eq!(rug::Integer::from(&n).partial_cmp(&i), cmp); assert_eq!(Some(n.cmp(&Integer::from(i))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp(&n), cmp_rev); assert_eq!(i.partial_cmp(&rug::Integer::from(&n)), cmp_rev); assert_eq!(Some(Integer::from(i).cmp(&n)), cmp_rev); }); integer_integer_signed_triple_gen::().test_properties(|(n, m, i)| { if n < i && i < m { assert_eq!(n.cmp(&m), Less); } else if n > i && i > m { assert_eq!(n.cmp(&m), Greater); } }); integer_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i < n && n < j { assert!(i < j); } else if i > n && n > j { assert!(i > j); } }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Integer::from(y)), Some(x.cmp(&y))); }); } #[test] fn partial_cmp_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{integer_natural_pair_gen, natural_pair_gen}; use rug; use std::str::FromStr; #[test] fn test_integer_partial_eq_natural() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!( rug::Integer::from_str(s).unwrap() == rug::Integer::from_str(t).unwrap(), out ); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("-123", "123", false); test("123", "5", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("-1000000000000", "1000000000000", false); } #[allow(clippy::cmp_owned)] #[test] fn partial_eq_natural_properties() { integer_natural_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(x == Integer::from(&y), eq); assert_eq!(rug::Integer::from(&x) == rug::Integer::from(&y), eq); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) == y, x == y); assert_eq!(x == Integer::from(&y), x == y); }); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_primitive_float_pair_gen, natural_primitive_float_pair_gen, }; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_partial_eq() { let test = |u, v: f32, out| { assert_eq!(Integer::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Integer::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); let v = f64::from(v); assert_eq!(Integer::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Integer::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("5", f32::NAN, false); test("5", f32::INFINITY, false); test("5", f32::NEGATIVE_INFINITY, false); test("-5", f32::NAN, false); test("-5", f32::INFINITY, false); test("-5", f32::NEGATIVE_INFINITY, false); test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", 5.0, false); test("123", -123.0, false); test("-123", 123.0, false); test("-123", 5.0, false); test("-123", -123.0, true); test("1000000000000", 123.0, false); test("-1000000000000", 123.0, false); test("1208925819614629174706175", 1.2089258e24, false); test("1208925819614629174706176", 1.2089258e24, true); test("1208925819614629174706177", 1.2089258e24, false); test("1208925819614629174706175", -1.2089258e24, false); test("1208925819614629174706176", -1.2089258e24, false); test("1208925819614629174706177", -1.2089258e24, false); test("-1208925819614629174706175", 1.2089258e24, false); test("-1208925819614629174706176", 1.2089258e24, false); test("-1208925819614629174706177", 1.2089258e24, false); test("-1208925819614629174706175", -1.2089258e24, false); test("-1208925819614629174706176", -1.2089258e24, true); test("-1208925819614629174706177", -1.2089258e24, false); } #[allow(clippy::cmp_owned, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_float_properties_helper< T: PartialEq + PartialEq + PartialEq + PrimitiveFloat, >() where Integer: PartialEq + PartialOrd, Natural: PartialEq, rug::Integer: PartialEq, { integer_primitive_float_pair_gen::().test_properties(|(n, f)| { let eq = n == f; assert_eq!(rug::Integer::from(&n) == f, eq); assert_eq!(f == n, eq); assert_eq!(f == rug::Integer::from(&n), eq); assert_eq!(n.partial_cmp(&f) == Some(Equal), eq); if eq { assert!(f.is_integer()); } }); natural_primitive_float_pair_gen::().test_properties(|(n, f)| { let i_n: Integer = From::from(&n); let eq = n == f; assert_eq!(i_n == f, eq); assert_eq!(f == n, eq); assert_eq!(f == i_n, eq); }); } #[test] fn partial_eq_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_eq_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{integer_signed_pair_gen, integer_unsigned_pair_gen}; use malachite_nz::test_util::integer::comparison::partial_eq_primitive_int::*; use num::BigInt; use rug; use std::str::FromStr; #[test] fn test_partial_eq_u32() { let test = |s, v: u32, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!( num_partial_eq_primitive(&BigInt::from_str(s).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Integer::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", 123, false); test("123", 5, false); test("-123", 5, false); test("1000000000000", 123, false); test("-1000000000000", 123, false); } #[test] fn test_partial_eq_u64() { let test = |s, v: u64, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!( num_partial_eq_primitive(&BigInt::from_str(s).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Integer::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", 123, false); test("123", 5, false); test("-123", 5, false); test("1000000000000", 1000000000000, true); test("-1000000000000", 1000000000000, false); test("1000000000000", 1000000000001, false); test("-1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-1000000000000000000000000", 1000000000000, false); } #[test] fn test_partial_eq_i32() { let test = |s, v: i32, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Integer::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Integer::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", -123, true); test("-123", 123, false); test("123", 5, false); test("-123", -5, false); test("1000000000000", 123, false); test("-1000000000000", -123, false); } #[test] fn test_partial_eq_i64() { let test = |s, v: i64, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Integer::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Integer::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", -123, true); test("-123", 123, false); test("123", 5, false); test("-123", -5, false); test("1000000000000", 1000000000000, true); test("-1000000000000", -1000000000000, true); test("1000000000000", 1000000000001, false); test("-1000000000000", -1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-1000000000000000000000000", -1000000000000, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_unsigned< T: PartialEq + PartialEq + PrimitiveUnsigned, >() where BigInt: From, Integer: From + PartialEq, rug::Integer: PartialEq, { integer_unsigned_pair_gen::().test_properties(|(n, u)| { let eq = n == u; assert_eq!(num_partial_eq_primitive(&From::from(&n), u), eq); assert_eq!(rug::Integer::from(&n) == u, eq); assert_eq!(&n == &Integer::from(u), eq); assert_eq!(u == n, eq); assert_eq!(u == rug::Integer::from(&n), eq); assert_eq!(&Integer::from(u) == &n, eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Integer::from(x) == y, x == y); assert_eq!(x == Integer::from(y), x == y); }); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_signed< T: PartialEq + PartialEq + PrimitiveSigned, >() where Integer: From + PartialEq, rug::Integer: PartialEq, { integer_signed_pair_gen::().test_properties(|(n, i)| { let eq = n == i; assert_eq!(rug::Integer::from(&n) == i, eq); assert_eq!(&n == &Integer::from(i), eq); assert_eq!(i == n, eq); assert_eq!(i == rug::Integer::from(&n), eq); assert_eq!(&Integer::from(i) == &n, eq); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Integer::from(x) == y, x == y); assert_eq!(x == Integer::from(y), x == y); }); } #[test] fn partial_eq_primitive_int_properties() { apply_fn_to_unsigneds!(partial_eq_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_eq_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/integer/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, integer_pair_gen}; use num::BigInt; use rug; use std::str::FromStr; #[test] #[allow(clippy::redundant_clone)] fn test_clone() { let test = |u| { let x = Integer::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); assert!(x.is_valid()); let x = BigInt::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); let x = rug::Integer::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); }; test("123"); test("1000000000000"); test("-123"); test("-1000000000000"); } #[test] fn test_clone_and_clone_from() { let test = |u, v| { let mut x = Integer::from_str(u).unwrap(); x.clone_from(&Integer::from_str(v).unwrap()); assert_eq!(x.to_string(), v); assert!(x.is_valid()); let mut x = BigInt::from_str(u).unwrap(); x.clone_from(&BigInt::from_str(v).unwrap()); assert_eq!(x.to_string(), v); let mut x = rug::Integer::from_str(u).unwrap(); x.clone_from(&rug::Integer::from_str(v).unwrap()); assert_eq!(x.to_string(), v); }; test("-123", "456"); test("-123", "1000000000000"); test("1000000000000", "-123"); test("1000000000000", "2000000000000"); } #[allow(clippy::redundant_clone)] #[test] fn clone_and_clone_from_properties() { integer_gen().test_properties(|x| { let mut_x = x.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, x); assert_eq!(Integer::from(&BigInt::from(&x).clone()), x); assert_eq!(Integer::from(&rug::Integer::from(&x).clone()), x); }); integer_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.clone_from(&y); assert!(mut_x.is_valid()); assert_eq!(mut_x, y); let mut num_x = BigInt::from(&x); num_x.clone_from(&BigInt::from(&y)); assert_eq!(Integer::from(&num_x), y); let mut rug_x = rug::Integer::from(&x); rug_x.clone_from(&rug::Integer::from(&y)); assert_eq!(Integer::from(&rug_x), y); }); signed_pair_gen::().test_properties(|(i, j)| { let x = Integer::from(i); let y = Integer::from(j); let mut mut_i = i; let mut mut_x = x.clone(); mut_i.clone_from(&j); mut_x.clone_from(&y); assert_eq!(mut_x, mut_i); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; #[test] fn test_from_bool() { let test = |b, s| { let n = Integer::from(b); assert!(n.is_valid()); assert_eq!(n.to_string(), s); }; test(false, "0"); test(true, "1"); } ================================================ FILE: malachite-nz/tests/integer/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use std::str::FromStr; #[test] fn test_from_natural() { let test = |s| { let u = Natural::from_str(s).unwrap(); let x = Integer::from(u.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), s); let x = Integer::from(&u); assert!(x.is_valid()); assert_eq!(x.to_string(), s); }; test("0"); test("123"); test("1000000000000"); test("4294967295"); test("4294967296"); } #[test] fn from_natural_properties() { natural_gen().test_properties(|x| { let integer_x = Integer::from(x.clone()); assert!(integer_x.is_valid()); assert_eq!(integer_x.to_string(), x.to_string()); let integer_x_alt = Integer::from(&x); assert!(integer_x_alt.is_valid()); assert_eq!(integer_x_alt, integer_x); assert_eq!(Natural::try_from(&integer_x).as_ref(), Ok(&x)); assert_eq!(Natural::try_from(integer_x), Ok(x)); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::from::SignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_5, primitive_float_gen_var_6, primitive_float_gen_var_7, primitive_float_gen_var_14, primitive_float_rounding_mode_pair_gen_var_2, primitive_float_rounding_mode_pair_gen_var_3, }; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use std::cmp::Ordering::*; #[test] fn test_rounding_from_f32() { let test = |f: f32, rm: RoundingMode, out, o_out| { let (x, o) = Integer::rounding_from(f, rm); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(o, o_out); }; test(0.0, Exact, "0", Equal); test(-0.0, Exact, "0", Equal); test(123.0, Exact, "123", Equal); test(-123.0, Exact, "-123", Equal); test(1.0e9, Exact, "1000000000", Equal); test(-1.0e9, Exact, "-1000000000", Equal); test(4294967295.0, Exact, "4294967296", Equal); test(-4294967295.0, Exact, "-4294967296", Equal); test(4294967296.0, Exact, "4294967296", Equal); test(-4294967296.0, Exact, "-4294967296", Equal); test(18446744073709551615.0, Exact, "18446744073709551616", Equal); test( -18446744073709551615.0, Exact, "-18446744073709551616", Equal, ); test(18446744073709551616.0, Exact, "18446744073709551616", Equal); test( -18446744073709551616.0, Exact, "-18446744073709551616", Equal, ); test(1.0e20, Exact, "100000002004087734272", Equal); test(-1.0e20, Exact, "-100000002004087734272", Equal); test(1.23e20, Exact, "122999999650278146048", Equal); test(-1.23e20, Exact, "-122999999650278146048", Equal); test(1.6777216e7, Exact, "16777216", Equal); test(-1.6777216e7, Exact, "-16777216", Equal); test(1.6777218e7, Exact, "16777218", Equal); test(-1.6777218e7, Exact, "-16777218", Equal); test(123.1, Floor, "123", Less); test(123.1, Down, "123", Less); test(123.1, Ceiling, "124", Greater); test(123.1, Up, "124", Greater); test(123.1, Nearest, "123", Less); test(-123.1, Floor, "-124", Less); test(-123.1, Down, "-123", Greater); test(-123.1, Ceiling, "-123", Greater); test(-123.1, Up, "-124", Less); test(-123.1, Nearest, "-123", Greater); test(123.9, Floor, "123", Less); test(123.9, Down, "123", Less); test(123.9, Ceiling, "124", Greater); test(123.9, Up, "124", Greater); test(123.9, Nearest, "124", Greater); test(-123.9, Floor, "-124", Less); test(-123.9, Down, "-123", Greater); test(-123.9, Ceiling, "-123", Greater); test(-123.9, Up, "-124", Less); test(-123.9, Nearest, "-124", Less); test(123.5, Nearest, "124", Greater); test(-123.5, Nearest, "-124", Less); test(124.5, Nearest, "124", Less); test(-124.5, Nearest, "-124", Greater); test(-0.99, Ceiling, "0", Greater); test(-0.99, Down, "0", Greater); test(-0.499, Nearest, "0", Greater); test(-0.5, Nearest, "0", Greater); test(-1.1788622e20, Exact, "-117886223846050103296", Equal); } #[test] #[should_panic] fn rounding_from_f32_fail_1() { Integer::rounding_from(f32::NAN, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_2() { Integer::rounding_from(f32::INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_3() { Integer::rounding_from(f32::NEGATIVE_INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_4() { Integer::rounding_from(123.1, Exact); } #[test] fn test_rounding_from_f64() { let test = |f: f64, rm: RoundingMode, out, o_out| { let (x, o) = Integer::rounding_from(f, rm); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(o, o_out); }; test(0.0, Exact, "0", Equal); test(-0.0, Exact, "0", Equal); test(123.0, Exact, "123", Equal); test(-123.0, Exact, "-123", Equal); test(1.0e9, Exact, "1000000000", Equal); test(-1.0e9, Exact, "-1000000000", Equal); test(4294967295.0, Exact, "4294967295", Equal); test(-4294967295.0, Exact, "-4294967295", Equal); test(4294967296.0, Exact, "4294967296", Equal); test(-4294967296.0, Exact, "-4294967296", Equal); test(18446744073709551615.0, Exact, "18446744073709551616", Equal); test( -18446744073709551615.0, Exact, "-18446744073709551616", Equal, ); test(18446744073709551616.0, Exact, "18446744073709551616", Equal); test( -18446744073709551616.0, Exact, "-18446744073709551616", Equal, ); test(1.0e20, Exact, "100000000000000000000", Equal); test(-1.0e20, Exact, "-100000000000000000000", Equal); test(1.23e20, Exact, "123000000000000000000", Equal); test(-1.23e20, Exact, "-123000000000000000000", Equal); test( 1.0e100, Exact, "100000000000000001590289110975991804683608085639452813897813275577478387721703810608134699\ 85856815104", Equal, ); test( -1.0e100, Exact, "-10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469\ 985856815104", Equal, ); test( 1.23e100, Exact, "123000000000000008366862950845375853795062237854139353014252897832358837028676639186389822\ 00322686976", Equal, ); test( -1.23e100, Exact, "-12300000000000000836686295084537585379506223785413935301425289783235883702867663918638982\ 200322686976", Equal, ); test(9.007199254740992e15, Exact, "9007199254740992", Equal); test(-9.007199254740992e15, Exact, "-9007199254740992", Equal); test(9.007199254740994e15, Exact, "9007199254740994", Equal); test(-9.007199254740994e15, Exact, "-9007199254740994", Equal); test(123.1, Floor, "123", Less); test(123.1, Down, "123", Less); test(123.1, Ceiling, "124", Greater); test(123.1, Up, "124", Greater); test(123.1, Nearest, "123", Less); test(-123.1, Floor, "-124", Less); test(-123.1, Down, "-123", Greater); test(-123.1, Ceiling, "-123", Greater); test(-123.1, Up, "-124", Less); test(-123.1, Nearest, "-123", Greater); test(123.9, Floor, "123", Less); test(123.9, Down, "123", Less); test(123.9, Ceiling, "124", Greater); test(123.9, Up, "124", Greater); test(123.9, Nearest, "124", Greater); test(-123.9, Floor, "-124", Less); test(-123.9, Down, "-123", Greater); test(-123.9, Ceiling, "-123", Greater); test(-123.9, Up, "-124", Less); test(-123.9, Nearest, "-124", Less); test(123.5, Nearest, "124", Greater); test(-123.5, Nearest, "-124", Less); test(124.5, Nearest, "124", Less); test(-124.5, Nearest, "-124", Greater); test(-0.99, Ceiling, "0", Greater); test(-0.99, Down, "0", Greater); test(-0.499, Nearest, "0", Greater); test(-0.5, Nearest, "0", Greater); } #[test] #[should_panic] fn rounding_from_f64_fail_1() { Integer::rounding_from(f64::NAN, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_2() { Integer::rounding_from(f64::INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_3() { Integer::rounding_from(f64::NEGATIVE_INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_4() { Integer::rounding_from(123.1, Exact); } #[test] fn test_try_from_f32() { let test = |f: f32, out| { let on = Integer::try_from(f); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test(f32::NAN, "Err(FloatInfiniteOrNan)"); test(f32::INFINITY, "Err(FloatInfiniteOrNan)"); test(f32::NEGATIVE_INFINITY, "Err(FloatInfiniteOrNan)"); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967296)"); test(-4294967295.0, "Ok(-4294967296)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000002004087734272)"); test(-1.0e20, "Ok(-100000002004087734272)"); test(1.23e20, "Ok(122999999650278146048)"); test(-1.23e20, "Ok(-122999999650278146048)"); test(123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(-123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(f32::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(-f32::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(f32::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(-f32::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(f32::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test( -f32::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)", ); test( f32::MAX_FINITE, "Ok(340282346638528859811704183484516925440)", ); test( -f32::MAX_FINITE, "Ok(-340282346638528859811704183484516925440)", ); } #[test] fn test_try_from_f64() { let test = |f: f64, out| { let on = Integer::try_from(f); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test(f64::NAN, "Err(FloatInfiniteOrNan)"); test(f64::INFINITY, "Err(FloatInfiniteOrNan)"); test(f64::NEGATIVE_INFINITY, "Err(FloatInfiniteOrNan)"); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967295)"); test(-4294967295.0, "Ok(-4294967295)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000000000000000000)"); test(-1.0e20, "Ok(-100000000000000000000)"); test(1.23e20, "Ok(123000000000000000000)"); test(-1.23e20, "Ok(-123000000000000000000)"); test( 1.0e100, "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ 469985856815104)", ); test( -1.0e100, "Ok(-1000000000000000015902891109759918046836080856394528138978132755774783877217038106081\ 3469985856815104)", ); test( 1.23e100, "Ok(12300000000000000836686295084537585379506223785413935301425289783235883702867663918638\ 982200322686976)", ); test( -1.23e100, "Ok(-1230000000000000083668629508453758537950622378541393530142528978323588370286766391863\ 8982200322686976)", ); test(123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(-123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(f64::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(-f64::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(f64::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(-f64::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(f64::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test( -f64::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)", ); test( f64::MAX_FINITE, "Ok(17976931348623157081452742373170435679807056752584499659891747680315726078002853876058\ 955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207\ 624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472\ 3168738177180919299881250404026184124858368)", ); test( -f64::MAX_FINITE, "Ok(-1797693134862315708145274237317043567980705675258449965989174768031572607800285387605\ 895586327668781715404589535143824642343213268894641827684675467035375169860499105765512820\ 762454900903893289440758685084551339423045832369032229481658085593321233482747978262041447\ 23168738177180919299881250404026184124858368)", ); } #[test] fn test_exact_from_f32() { let test = |f: f32, out| { let x = Integer::exact_from(f); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(0.0, "0"); test(-0.0, "0"); test(123.0, "123"); test(-123.0, "-123"); test(1.0e9, "1000000000"); test(-1.0e9, "-1000000000"); test(4294967295.0, "4294967296"); test(-4294967295.0, "-4294967296"); test(4294967296.0, "4294967296"); test(-4294967296.0, "-4294967296"); test(18446744073709551615.0, "18446744073709551616"); test(-18446744073709551615.0, "-18446744073709551616"); test(18446744073709551616.0, "18446744073709551616"); test(-18446744073709551616.0, "-18446744073709551616"); test(1.0e20, "100000002004087734272"); test(-1.0e20, "-100000002004087734272"); test(1.23e20, "122999999650278146048"); test(-1.23e20, "-122999999650278146048"); test(f32::MAX_FINITE, "340282346638528859811704183484516925440"); test(-f32::MAX_FINITE, "-340282346638528859811704183484516925440"); } #[test] #[should_panic] fn exact_from_f32_fail_1() { Integer::exact_from(f32::NAN); } #[test] #[should_panic] fn exact_from_f32_fail_2() { Integer::exact_from(f32::INFINITY); } #[test] #[should_panic] fn exact_from_f32_fail_3() { Integer::exact_from(f32::NEGATIVE_INFINITY); } #[test] #[should_panic] fn exact_from_f32_fail_4() { Integer::exact_from(123.1); } #[test] #[should_panic] fn exact_from_f32_fail_5() { Integer::exact_from(-123.1); } #[test] #[should_panic] fn exact_from_f32_fail_6() { Integer::exact_from(123.5); } #[test] #[should_panic] fn exact_from_f32_fail_7() { Integer::exact_from(-123.5); } #[test] #[should_panic] fn exact_from_f32_fail_8() { Integer::exact_from(124.5); } #[test] #[should_panic] fn exact_from_f32_fail_9() { Integer::exact_from(-124.5); } #[test] #[should_panic] fn exact_from_f32_fail_10() { Integer::exact_from(f32::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f32_fail_11() { Integer::exact_from(-f32::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f32_fail_12() { Integer::exact_from(f32::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f32_fail_13() { Integer::exact_from(-f32::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f32_fail_14() { Integer::exact_from(f32::MIN_POSITIVE_NORMAL); } #[test] #[should_panic] fn exact_from_f32_fail_15() { Integer::exact_from(-f32::MIN_POSITIVE_NORMAL); } #[test] fn test_exact_from_f64() { let test = |f: f64, out| { let x = Integer::exact_from(f); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(0.0, "0"); test(-0.0, "0"); test(123.0, "123"); test(-123.0, "-123"); test(1.0e9, "1000000000"); test(-1.0e9, "-1000000000"); test(4294967295.0, "4294967295"); test(-4294967295.0, "-4294967295"); test(4294967296.0, "4294967296"); test(-4294967296.0, "-4294967296"); test(18446744073709551615.0, "18446744073709551616"); test(-18446744073709551615.0, "-18446744073709551616"); test(18446744073709551616.0, "18446744073709551616"); test(-18446744073709551616.0, "-18446744073709551616"); test(1.0e20, "100000000000000000000"); test(-1.0e20, "-100000000000000000000"); test(1.23e20, "123000000000000000000"); test(-1.23e20, "-123000000000000000000"); test( 1.0e100, "100000000000000001590289110975991804683608085639452813897813275577478387721703810608134699\ 85856815104", ); test( -1.0e100, "-10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469\ 985856815104", ); test( 1.23e100, "123000000000000008366862950845375853795062237854139353014252897832358837028676639186389822\ 00322686976", ); test( -1.23e100, "-12300000000000000836686295084537585379506223785413935301425289783235883702867663918638982\ 200322686976", ); test( f64::MAX_FINITE, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", ); test( -f64::MAX_FINITE, "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", ); } #[test] #[should_panic] fn exact_from_f64_fail_1() { Integer::exact_from(f64::NAN); } #[test] #[should_panic] fn exact_from_f64_fail_2() { Integer::exact_from(f64::INFINITY); } #[test] #[should_panic] fn exact_from_f64_fail_3() { Integer::exact_from(f64::NEGATIVE_INFINITY); } #[test] #[should_panic] fn exact_from_f64_fail_4() { Integer::exact_from(123.1); } #[test] #[should_panic] fn exact_from_f64_fail_5() { Integer::exact_from(-123.1); } #[test] #[should_panic] fn exact_from_f64_fail_6() { Integer::exact_from(123.5); } #[test] #[should_panic] fn exact_from_f64_fail_7() { Integer::exact_from(-123.5); } #[test] #[should_panic] fn exact_from_f64_fail_8() { Integer::exact_from(124.5); } #[test] #[should_panic] fn exact_from_f64_fail_9() { Integer::exact_from(-124.5); } #[test] #[should_panic] fn exact_from_f64_fail_10() { Integer::exact_from(f64::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f64_fail_11() { Integer::exact_from(-f64::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f64_fail_12() { Integer::exact_from(f64::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f64_fail_13() { Integer::exact_from(-f64::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f64_fail_14() { Integer::exact_from(f64::MIN_POSITIVE_NORMAL); } #[test] #[should_panic] fn exact_from_f64_fail_15() { Integer::exact_from(-f64::MIN_POSITIVE_NORMAL); } #[test] fn test_convertible_from_f32() { let test = |f: f32, out| { assert_eq!(Integer::convertible_from(f), out); }; test(f32::NAN, false); test(f32::INFINITY, false); test(f32::NEGATIVE_INFINITY, false); test(0.0, true); test(-0.0, true); test(123.0, true); test(-123.0, true); test(1.0e9, true); test(-1.0e9, true); test(4294967295.0, true); test(-4294967295.0, true); test(4294967296.0, true); test(-4294967296.0, true); test(18446744073709551615.0, true); test(-18446744073709551615.0, true); test(18446744073709551616.0, true); test(-18446744073709551616.0, true); test(1.0e20, true); test(-1.0e20, true); test(1.23e20, true); test(-1.23e20, true); test(123.1, false); test(-123.1, false); test(123.5, false); test(-123.5, false); test(124.5, false); test(-124.5, false); test(f32::MIN_POSITIVE, false); test(-f32::MIN_POSITIVE, false); test(f32::MAX_SUBNORMAL, false); test(-f32::MAX_SUBNORMAL, false); test(f32::MIN_POSITIVE_NORMAL, false); test(-f32::MIN_POSITIVE_NORMAL, false); test(f32::MAX_FINITE, true); test(-f32::MAX_FINITE, true); } #[test] fn test_convertible_from_f64() { let test = |f: f64, out| { assert_eq!(Integer::convertible_from(f), out); }; test(f64::NAN, false); test(f64::INFINITY, false); test(f64::NEGATIVE_INFINITY, false); test(0.0, true); test(-0.0, true); test(123.0, true); test(-123.0, true); test(1.0e9, true); test(-1.0e9, true); test(4294967295.0, true); test(-4294967295.0, true); test(4294967296.0, true); test(-4294967296.0, true); test(18446744073709551615.0, true); test(-18446744073709551615.0, true); test(18446744073709551616.0, true); test(-18446744073709551616.0, true); test(1.0e20, true); test(-1.0e20, true); test(1.23e20, true); test(-1.23e20, true); test(1.0e100, true); test(-1.0e100, true); test(1.23e100, true); test(-1.23e100, true); test(123.1, false); test(-123.1, false); test(123.5, false); test(-123.5, false); test(124.5, false); test(-124.5, false); test(f64::MIN_POSITIVE, false); test(-f64::MIN_POSITIVE, false); test(f64::MAX_SUBNORMAL, false); test(-f64::MAX_SUBNORMAL, false); test(f64::MIN_POSITIVE_NORMAL, false); test(-f64::MIN_POSITIVE_NORMAL, false); test(f64::MAX_FINITE, true); test(-f64::MAX_FINITE, true); } fn rounding_from_float_properties_helper RoundingFrom<&'a Integer>>() where Integer: PartialEq + PartialOrd + RoundingFrom, SignedLimb: ConvertibleFrom + RoundingFrom, { primitive_float_rounding_mode_pair_gen_var_2::().test_properties(|(f, rm)| { let (n, o) = Integer::rounding_from(f, rm); assert!(n.is_valid()); let (n_alt, o_alt) = Integer::rounding_from(-f, -rm); assert_eq!(&n_alt, &-&n); assert_eq!(o_alt, o.reverse()); assert_eq!(n.partial_cmp(&f), Some(o)); match (f.is_sign_positive(), rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); primitive_float_gen_var_5::().test_properties(|f| { let no = Integer::rounding_from(f, Exact); assert!(no.0.is_valid()); assert_eq!(no.1, Equal); assert_eq!(no, Integer::rounding_from(f, Floor)); assert_eq!(no, Integer::rounding_from(f, Ceiling)); assert_eq!(no, Integer::rounding_from(f, Down)); assert_eq!(no, Integer::rounding_from(f, Up)); assert_eq!(no, Integer::rounding_from(f, Nearest)); assert_eq!(T::rounding_from(&no.0, Exact), (f, Equal)); }); primitive_float_gen_var_6::().test_properties(|f| { let n_floor = Integer::rounding_from(f, Floor); assert!(n_floor.0.is_valid()); assert_eq!(n_floor.1, Less); let n_ceiling = (&n_floor.0 + Integer::ONE, Greater); assert_eq!(n_ceiling, Integer::rounding_from(f, Ceiling)); if f >= T::ZERO { assert_eq!(n_floor, Integer::rounding_from(f, Down)); assert_eq!(n_ceiling, Integer::rounding_from(f, Up)); } else { assert_eq!(n_ceiling, Integer::rounding_from(f, Down)); assert_eq!(n_floor, Integer::rounding_from(f, Up)); } let n_nearest = Integer::rounding_from(f, Nearest); assert!(n_nearest == n_floor || n_nearest == n_ceiling); }); primitive_float_gen_var_7::().test_properties(|f| { let floor = Integer::rounding_from(f, Floor); assert_eq!(floor.1, Less); let ceiling = (&floor.0 + Integer::ONE, Greater); let nearest = Integer::rounding_from(f, Nearest); assert_eq!(nearest, if floor.0.even() { floor } else { ceiling }); }); let min: Integer = From::from(SignedLimb::MIN); let max: Integer = From::from(SignedLimb::MAX); primitive_float_rounding_mode_pair_gen_var_3::().test_properties( move |(f, rm)| { if f.is_finite() { let mut n = Integer::rounding_from(f, rm).0; if PartialOrd::::gt(&n, &max) { n = max.clone(); } if PartialOrd::::lt(&n, &min) { n = min.clone(); } assert_eq!(SignedLimb::rounding_from(f, rm).0, n); } }, ); } #[test] fn rounding_from_float_properties() { apply_fn_to_primitive_floats!(rounding_from_float_properties_helper); } fn try_from_float_properties_helper RoundingFrom<&'a Integer>>() where Integer: TryFrom + RoundingFrom, SignedLimb: TryFrom>, NiceFloat: TryFrom, { primitive_float_gen::().test_properties(|f| { let on = Integer::try_from(f); assert!(on.as_ref().map_or(true, Integer::is_valid)); assert_eq!(Integer::try_from(-f), on.map(|n| -n)); if let Ok(n) = SignedLimb::try_from(NiceFloat(f)) { assert_eq!(n, Integer::exact_from(f)); } }); primitive_float_gen_var_5::().test_properties(|f| { let n = Integer::exact_from(f); assert!(n.is_valid()); assert_eq!(n, Integer::rounding_from(f, Exact).0); assert_eq!(T::rounding_from(&n, Exact).0, f); }); primitive_float_gen_var_6::().test_properties(|f| { assert!(Integer::try_from(f).is_err()); }); primitive_float_gen_var_7::().test_properties(|f| { assert!(Integer::try_from(f).is_err()); }); primitive_float_gen_var_14::().test_properties(|f| { assert_eq!(SignedLimb::exact_from(NiceFloat(f)), Integer::exact_from(f)); }); } #[test] fn try_from_float_properties() { apply_fn_to_primitive_floats!(try_from_float_properties_helper); } fn convertible_from_float_properties_helper() where Integer: ConvertibleFrom, SignedLimb: ConvertibleFrom, { primitive_float_gen::().test_properties(|f| { let nc = Integer::convertible_from(f); if SignedLimb::convertible_from(f) { assert!(nc); } }); primitive_float_gen_var_5::().test_properties(|f| { assert!(Integer::convertible_from(f)); }); primitive_float_gen_var_6::().test_properties(|f| { assert!(!Integer::convertible_from(f)); }); primitive_float_gen_var_7::().test_properties(|f| { assert!(!Integer::convertible_from(f)); }); } #[test] fn convertible_from_float_properties() { apply_fn_to_primitive_floats!(convertible_from_float_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen, signed_gen_var_2, unsigned_gen}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use num::BigInt; use rug; #[test] fn test_from_u32() { let test = |u: u32, out| { let x = Integer::from(u); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(BigInt::from(u).to_string(), out); assert_eq!(rug::Integer::from(u).to_string(), out); #[cfg(feature = "32_bit_limbs")] { let x_alt = Integer::const_from_unsigned(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u32::MAX, "4294967295"); } #[test] fn test_from_u64() { let test = |u: u64, out| { let x = Integer::from(u); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(BigInt::from(u).to_string(), out); assert_eq!(rug::Integer::from(u).to_string(), out); #[cfg(not(feature = "32_bit_limbs"))] { let x_alt = Integer::const_from_unsigned(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u64::MAX, "18446744073709551615"); } #[test] fn test_from_i32() { let test = |i: i32, out| { let x = Integer::from(i); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(BigInt::from(i).to_string(), out); assert_eq!(rug::Integer::from(i).to_string(), out); #[cfg(feature = "32_bit_limbs")] { let x_alt = Integer::const_from_signed(i); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(-123, "-123"); test(i32::MIN, "-2147483648"); test(i32::MAX, "2147483647"); } #[test] fn test_from_i64() { let test = |i: i64, out| { let x = Integer::from(i); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(BigInt::from(i).to_string(), out); assert_eq!(rug::Integer::from(i).to_string(), out); #[cfg(not(feature = "32_bit_limbs"))] { let x_alt = Integer::const_from_signed(i); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(-123, "-123"); test(i64::MIN, "-9223372036854775808"); test(i64::MAX, "9223372036854775807"); } fn from_unsigned_properties_helper TryFrom<&'a Integer> + PrimitiveUnsigned>() where Integer: From, Natural: From, u128: TryFrom, { unsigned_gen::().test_properties(|u| { let n = Integer::from(u); assert!(n.is_valid()); assert_eq!(T::exact_from(&n), u); let alt_n: Integer = From::from(Natural::from(u)); assert_eq!(alt_n, n); let alt_n: Integer = From::from(u128::exact_from(u)); assert_eq!(alt_n, n); }); } fn from_signed_properties_helper TryFrom<&'a Integer> + PrimitiveSigned>() where Integer: From, Natural: TryFrom, i128: TryFrom, { signed_gen::().test_properties(|i| { let n = Integer::from(i); assert!(n.is_valid()); assert_eq!(T::exact_from(&n), i); let alt_n: Integer = From::from(i128::exact_from(i)); assert_eq!(alt_n, n); }); signed_gen_var_2::().test_properties(|i| { let n: Integer = From::from(Natural::exact_from(i)); assert_eq!(n, Integer::from(i)); }); } #[test] fn from_primitive_int_properties() { apply_fn_to_unsigneds!(from_unsigned_properties_helper); apply_fn_to_signeds!(from_signed_properties_helper); unsigned_gen::().test_properties(|u| { let n = Integer::from(u); assert_eq!(Integer::from(&BigInt::from(u)), n); assert_eq!(Integer::from(&rug::Integer::from(u)), n); #[cfg(feature = "32_bit_limbs")] { let n_alt = Integer::const_from_unsigned(u); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); unsigned_gen::().test_properties(|u| { let n = Integer::from(u); assert_eq!(Integer::from(&BigInt::from(u)), n); assert_eq!(Integer::from(&rug::Integer::from(u)), n); #[cfg(not(feature = "32_bit_limbs"))] { let n_alt = Integer::const_from_unsigned(u); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); signed_gen::().test_properties(|i| { let n = Integer::from(i); assert_eq!(Integer::from(&BigInt::from(i)), n); assert_eq!(Integer::from(&rug::Integer::from(i)), n); #[cfg(feature = "32_bit_limbs")] { let n_alt = Integer::const_from_signed(i); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); signed_gen::().test_properties(|i| { let n = Integer::from(i); assert_eq!(Integer::from(&BigInt::from(i)), n); assert_eq!(Integer::from(&rug::Integer::from(i)), n); #[cfg(not(feature = "32_bit_limbs"))] { let n_alt = Integer::const_from_signed(i); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); } ================================================ FILE: malachite-nz/tests/integer/conversion/from_twos_complement_limbs.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Sign; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_base::vecs::vec_delete_left; use malachite_nz::integer::Integer; use malachite_nz::platform::Limb; use std::cmp::Ordering::*; #[cfg(feature = "32_bit_limbs")] #[test] fn test_from_twos_complement_limbs_asc() { let test = |xs: &[Limb], out| { let x = Integer::from_twos_complement_limbs_asc(xs); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = Integer::from_owned_twos_complement_limbs_asc(xs.to_vec()); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(&[], "0"); test(&[0], "0"); test(&[0, 0, 0], "0"); test(&[123], "123"); test(&[123, 0], "123"); test(&[4294967173], "-123"); test(&[4294967173, u32::MAX], "-123"); test(&[3567587328, 232], "1000000000000"); test(&[727379968, 4294967063], "-1000000000000"); test(&[1, 2, 3, 4, 5], "1701411834921604967429270619762735448065"); test( &[u32::MAX, u32::MAX - 2, u32::MAX - 3, u32::MAX - 4, u32::MAX - 5], "-1701411834921604967429270619762735448065", ); test(&[u32::MAX, 0], "4294967295"); test(&[1, u32::MAX], "-4294967295"); test(&[0, 1], "4294967296"); test(&[0, u32::MAX], "-4294967296"); test(&[u32::MAX, u32::MAX, 0], "18446744073709551615"); test(&[1, 0, u32::MAX], "-18446744073709551615"); test(&[0, 0, 1], "18446744073709551616"); test(&[0, 0, u32::MAX], "-18446744073709551616"); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_from_twos_complement_limbs_desc() { let test = |xs: &[Limb], out| { let x = Integer::from_twos_complement_limbs_desc(xs); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = Integer::from_owned_twos_complement_limbs_desc(xs.to_vec()); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(&[], "0"); test(&[0], "0"); test(&[0, 0, 0], "0"); test(&[123], "123"); test(&[0, 123], "123"); test(&[4294967173], "-123"); test(&[u32::MAX, 4294967173], "-123"); test(&[232, 3567587328], "1000000000000"); test(&[4294967063, 727379968], "-1000000000000"); test(&[5, 4, 3, 2, 1], "1701411834921604967429270619762735448065"); test( &[u32::MAX - 5, u32::MAX - 4, u32::MAX - 3, u32::MAX - 2, u32::MAX], "-1701411834921604967429270619762735448065", ); test(&[0, u32::MAX], "4294967295"); test(&[u32::MAX, 1], "-4294967295"); test(&[1, 0], "4294967296"); test(&[u32::MAX, 0], "-4294967296"); test(&[0, u32::MAX, u32::MAX], "18446744073709551615"); test(&[u32::MAX, 0, 1], "-18446744073709551615"); test(&[1, 0, 0], "18446744073709551616"); test(&[u32::MAX, 0, 0], "-18446744073709551616"); } fn trim_be_limbs(xs: &mut Vec) { if xs.is_empty() { return; } if xs[0].get_highest_bit() { match xs.iter().position(|&limb| limb != Limb::MAX) { None => *xs = vec![Limb::MAX], Some(i) => { let i = if xs[i].get_highest_bit() { i } else { i - 1 }; vec_delete_left(xs, i); } } } else { match xs.iter().position(|&limb| limb != 0) { None => xs.clear(), Some(i) => { let i = if xs[i].get_highest_bit() { i - 1 } else { i }; vec_delete_left(xs, i); } } } } #[test] fn from_twos_complement_limbs_asc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let x = Integer::from_twos_complement_limbs_asc(&xs); assert_eq!(Integer::from_owned_twos_complement_limbs_asc(xs.clone()), x); let mut trimmed_xs = xs.iter().copied().rev().collect_vec(); trim_be_limbs(&mut trimmed_xs); trimmed_xs.reverse(); assert_eq!(x.to_twos_complement_limbs_asc(), trimmed_xs); assert_eq!( Integer::from_owned_twos_complement_limbs_desc(xs.iter().copied().rev().collect()), x ); if match x.sign() { Equal => xs.is_empty(), Greater => { let last = *xs.last().unwrap(); !last.get_highest_bit() && (last != 0 || xs[xs.len() - 2].get_highest_bit()) } Less => { let last = *xs.last().unwrap(); last.get_highest_bit() && (last != Limb::MAX || xs.len() <= 1 || !xs[xs.len() - 2].get_highest_bit()) } } { assert_eq!(x.to_twos_complement_limbs_asc(), xs); } }); } #[test] fn from_twos_complement_limbs_desc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let x = Integer::from_twos_complement_limbs_desc(&xs); assert_eq!( Integer::from_owned_twos_complement_limbs_desc(xs.clone()), x ); let mut trimmed_xs = xs.clone(); trim_be_limbs(&mut trimmed_xs); assert_eq!(x.to_twos_complement_limbs_desc(), trimmed_xs); assert_eq!( Integer::from_owned_twos_complement_limbs_asc(xs.iter().copied().rev().collect()), x ); if match x.sign() { Equal => xs.is_empty(), Greater => { let first = xs[0]; !first.get_highest_bit() && (first != 0 || xs[1].get_highest_bit()) } Less => { let first = xs[0]; first.get_highest_bit() && (first != Limb::MAX || xs.len() <= 1 || !xs[1].get_highest_bit()) } } { assert_eq!(x.to_twos_complement_limbs_desc(), xs); } }); } ================================================ FILE: malachite-nz/tests/integer/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::generators::common::GenConfig; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use std::str::FromStr; #[test] fn test_is_integer() { let test = |n, out| { assert_eq!(Integer::from_str(n).unwrap().is_integer(), out); }; test("0", true); test("1", true); test("100", true); test("-1", true); test("-100", true); } #[test] fn is_integer_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); integer_gen().test_properties_with_config(&config, |n| { assert!(n.is_integer()); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/natural_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::integer_gen; use std::str::FromStr; #[test] fn test_try_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); let on = Natural::try_from(u.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Natural::try_from(&u); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("0", "Ok(0)"); test("123", "Ok(123)"); test("-123", "Err(NaturalFromIntegerError)"); test("1000000000000", "Ok(1000000000000)"); test("-1000000000000", "Err(NaturalFromIntegerError)"); test("2147483647", "Ok(2147483647)"); test("2147483648", "Ok(2147483648)"); test("-2147483648", "Err(NaturalFromIntegerError)"); test("-2147483649", "Err(NaturalFromIntegerError)"); } #[test] fn test_exact_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); let n = Natural::exact_from(u.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::exact_from(&u); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0"); test("123", "123"); test("1000000000000", "1000000000000"); test("2147483647", "2147483647"); test("2147483648", "2147483648"); } #[test] #[should_panic] fn natural_exact_from_integer_fail_1() { Natural::exact_from(Integer::from_str("-123").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_fail_2() { Natural::exact_from(Integer::from_str("-1000000000000").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_fail_3() { Natural::exact_from(Integer::from_str("-2147483648").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_fail_4() { Natural::exact_from(Integer::from_str("-2147483649").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_ref_fail_1() { Natural::exact_from(&Integer::from_str("-123").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_ref_fail_2() { Natural::exact_from(&Integer::from_str("-1000000000000").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_ref_fail_3() { Natural::exact_from(&Integer::from_str("-2147483648").unwrap()); } #[test] #[should_panic] fn natural_exact_from_integer_ref_fail_4() { Natural::exact_from(&Integer::from_str("-2147483649").unwrap()); } #[test] fn test_saturating_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); let n = Natural::saturating_from(u.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::saturating_from(&u); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0"); test("123", "123"); test("-123", "0"); test("1000000000000", "1000000000000"); test("-1000000000000", "0"); test("2147483647", "2147483647"); test("2147483648", "2147483648"); test("-2147483648", "0"); test("-2147483649", "0"); } #[test] fn test_convertible_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(Natural::convertible_from(u.clone()), out); assert_eq!(Natural::convertible_from(&u), out); }; test("0", true); test("123", true); test("-123", false); test("1000000000000", true); test("-1000000000000", false); test("2147483647", true); test("2147483648", true); test("-2147483648", false); test("-2147483649", false); } #[test] fn try_from_integer_properties() { integer_gen().test_properties(|x| { let natural_x = Natural::try_from(x.clone()); assert!(natural_x.as_ref().map_or(true, Natural::is_valid)); let natural_x_alt = Natural::try_from(&x); assert!(natural_x_alt.as_ref().map_or(true, Natural::is_valid)); assert_eq!(natural_x, natural_x_alt); assert_eq!(natural_x.is_ok(), x >= 0); assert_eq!(natural_x.is_ok(), Natural::convertible_from(&x)); if let Ok(n) = natural_x { assert_eq!(n.to_string(), x.to_string()); assert_eq!(Natural::exact_from(&x), n); assert_eq!(Integer::from(&n), x); assert_eq!(Integer::from(n), x); } }); } #[test] fn saturating_from_integer_properties() { integer_gen().test_properties(|x| { let natural_x = Natural::saturating_from(x.clone()); assert!(natural_x.is_valid()); let natural_x_alt = Natural::saturating_from(&x); assert!(natural_x_alt.is_valid()); assert_eq!(natural_x, natural_x_alt); assert_eq!(natural_x == 0, x <= 0); assert!(natural_x >= x); assert_eq!(natural_x == x, Natural::convertible_from(x)); }); } #[test] fn convertible_from_integer_properties() { integer_gen().test_properties(|x| { let convertible = Natural::convertible_from(x.clone()); assert_eq!(Natural::convertible_from(&x), convertible); assert_eq!(convertible, x >= 0); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/primitive_float_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_7, signed_rounding_mode_pair_gen_var_4, }; use malachite_nz::integer::Integer; use malachite_nz::integer::conversion::primitive_float_from_integer::PrimitiveFloatFromIntegerError; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_1, integer_gen_var_2, integer_gen_var_3, integer_rounding_mode_pair_gen_var_1, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_f32_rounding_from_integer() { let test = |s: &str, rm: RoundingMode, out, o_out| { let u = Integer::from_str(s).unwrap(); let (x, o) = f32::rounding_from(&u, rm); assert_eq!(NiceFloat(x), NiceFloat(out)); assert_eq!(o, o_out); }; test("3", Exact, 3.0, Equal); test("-3", Exact, -3.0, Equal); test("123", Exact, 123.0, Equal); test("-123", Exact, -123.0, Equal); test("0", Exact, 0.0, Equal); test("1000000000", Exact, 1.0e9, Equal); test("-1000000000", Exact, -1.0e9, Equal); test("16777216", Exact, 1.6777216e7, Equal); test("-16777216", Exact, -1.6777216e7, Equal); test("16777218", Exact, 1.6777218e7, Equal); test("-16777218", Exact, -1.6777218e7, Equal); test("16777217", Floor, 1.6777216e7, Less); test("16777217", Down, 1.6777216e7, Less); test("16777217", Ceiling, 1.6777218e7, Greater); test("16777217", Up, 1.6777218e7, Greater); test("16777217", Nearest, 1.6777216e7, Less); test("-16777217", Floor, -1.6777218e7, Less); test("-16777217", Down, -1.6777216e7, Greater); test("-16777217", Ceiling, -1.6777216e7, Greater); test("-16777217", Up, -1.6777218e7, Less); test("-16777217", Nearest, -1.6777216e7, Greater); test("33554432", Exact, 3.3554432e7, Equal); test("-33554432", Exact, -3.3554432e7, Equal); test("33554436", Exact, 3.3554436e7, Equal); test("-33554436", Exact, -3.3554436e7, Equal); test("33554433", Floor, 3.3554432e7, Less); test("33554433", Down, 3.3554432e7, Less); test("33554433", Ceiling, 3.3554436e7, Greater); test("33554433", Up, 3.3554436e7, Greater); test("33554433", Nearest, 3.3554432e7, Less); test("-33554433", Floor, -3.3554436e7, Less); test("-33554433", Down, -3.3554432e7, Greater); test("-33554433", Ceiling, -3.3554432e7, Greater); test("-33554433", Up, -3.3554436e7, Less); test("-33554433", Nearest, -3.3554432e7, Greater); test("33554434", Nearest, 3.3554432e7, Less); test("-33554434", Nearest, -3.3554432e7, Greater); test("33554435", Nearest, 3.3554436e7, Greater); test("-33554435", Nearest, -3.3554436e7, Less); test( "340282346638528859811704183484516925439", Floor, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Down, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Ceiling, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Up, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Nearest, 3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925439", Floor, -3.4028235e38, Less, ); test( "-340282346638528859811704183484516925439", Down, -3.4028233e38, Greater, ); test( "-340282346638528859811704183484516925439", Ceiling, -3.4028233e38, Greater, ); test( "-340282346638528859811704183484516925439", Up, -3.4028235e38, Less, ); test( "-340282346638528859811704183484516925439", Nearest, -3.4028235e38, Less, ); test( "340282346638528859811704183484516925440", Exact, 3.4028235e38, Equal, ); test( "-340282346638528859811704183484516925440", Exact, -3.4028235e38, Equal, ); test( "340282346638528859811704183484516925441", Floor, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Down, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Nearest, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Ceiling, f32::INFINITY, Greater, ); test( "340282346638528859811704183484516925441", Up, f32::INFINITY, Greater, ); test( "-340282346638528859811704183484516925441", Floor, f32::NEGATIVE_INFINITY, Less, ); test( "-340282346638528859811704183484516925441", Down, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Nearest, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Ceiling, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Up, f32::NEGATIVE_INFINITY, Less, ); test( "10000000000000000000000000000000000000000000000000000", Floor, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Down, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Nearest, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Ceiling, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Up, f32::INFINITY, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Floor, f32::NEGATIVE_INFINITY, Less, ); test( "-10000000000000000000000000000000000000000000000000000", Down, -3.4028235e38, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Nearest, f32::NEGATIVE_INFINITY, Less, ); test( "-10000000000000000000000000000000000000000000000000000", Ceiling, -3.4028235e38, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Up, f32::NEGATIVE_INFINITY, Less, ); test("1125899873419263", Floor, 1.12589984e15, Less); test("1125899873419263", Down, 1.12589984e15, Less); test("1125899873419263", Ceiling, 1.1258999e15, Greater); test("1125899873419263", Up, 1.1258999e15, Greater); test("1125899873419263", Nearest, 1.1258999e15, Greater); test("-1125899873419263", Floor, -1.1258999e15, Less); test("-1125899873419263", Down, -1.12589984e15, Greater); test("-1125899873419263", Ceiling, -1.12589984e15, Greater); test("-1125899873419263", Up, -1.1258999e15, Less); test("-1125899873419263", Nearest, -1.1258999e15, Less); } #[test] #[should_panic] fn f32_rounding_from_integer_fail_1() { f32::rounding_from( &Integer::from_str("340282346638528859811704183484516925439").unwrap(), Exact, ); } #[test] #[should_panic] fn f32_rounding_from_integer_fail_2() { f32::rounding_from( &Integer::from_str("340282346638528859811704183484516925441").unwrap(), Exact, ); } #[test] #[should_panic] fn f32_rounding_from_integer_fail_3() { f32::rounding_from(&Integer::from_str("16777217").unwrap(), Exact); } #[test] #[should_panic] fn f32_rounding_from_integer_fail_4() { f32::rounding_from( &Integer::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), Exact, ); } #[test] fn test_f64_rounding_from_integer() { let test = |s: &str, rm: RoundingMode, out, o_out| { let u = Integer::from_str(s).unwrap(); let (x, o) = f64::rounding_from(&u, rm); assert_eq!(NiceFloat(x), NiceFloat(out)); assert_eq!(o, o_out); }; test("3", Exact, 3.0, Equal); test("-3", Exact, -3.0, Equal); test("123", Exact, 123.0, Equal); test("-123", Exact, -123.0, Equal); test("0", Exact, 0.0, Equal); test("100000000000000000000", Exact, 1.0e20, Equal); test("-100000000000000000000", Exact, -1.0e20, Equal); test("9007199254740992", Exact, 9.007199254740992e15, Equal); test("-9007199254740992", Exact, -9.007199254740992e15, Equal); test("9007199254740994", Exact, 9.007199254740994e15, Equal); test("-9007199254740994", Exact, -9.007199254740994e15, Equal); test("9007199254740993", Floor, 9.007199254740992e15, Less); test("9007199254740993", Down, 9.007199254740992e15, Less); test("9007199254740993", Ceiling, 9.007199254740994e15, Greater); test("9007199254740993", Up, 9.007199254740994e15, Greater); test("9007199254740993", Nearest, 9.007199254740992e15, Less); test("-9007199254740993", Floor, -9.007199254740994e15, Less); test("-9007199254740993", Down, -9.007199254740992e15, Greater); test("-9007199254740993", Ceiling, -9.007199254740992e15, Greater); test("-9007199254740993", Up, -9.007199254740994e15, Less); test("-9007199254740993", Nearest, -9.007199254740992e15, Greater); test("18014398509481984", Exact, 1.8014398509481984e16, Equal); test("-18014398509481984", Exact, -1.8014398509481984e16, Equal); test("18014398509481988", Exact, 1.8014398509481988e16, Equal); test("-18014398509481988", Exact, -1.8014398509481988e16, Equal); test("18014398509481985", Floor, 1.8014398509481984e16, Less); test("18014398509481985", Down, 1.8014398509481984e16, Less); test("18014398509481985", Ceiling, 1.8014398509481988e16, Greater); test("18014398509481985", Up, 1.8014398509481988e16, Greater); test("18014398509481985", Nearest, 1.8014398509481984e16, Less); test("-18014398509481985", Floor, -1.8014398509481988e16, Less); test("-18014398509481985", Down, -1.8014398509481984e16, Greater); test( "-18014398509481985", Ceiling, -1.8014398509481984e16, Greater, ); test("-18014398509481985", Up, -1.8014398509481988e16, Less); test( "-18014398509481985", Nearest, -1.8014398509481984e16, Greater, ); test("18014398509481986", Nearest, 1.8014398509481984e16, Less); test( "-18014398509481986", Nearest, -1.8014398509481984e16, Greater, ); test("18014398509481987", Nearest, 1.8014398509481988e16, Greater); test("-18014398509481987", Nearest, -1.8014398509481988e16, Less); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Floor, 1.7976931348623155e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Down, 1.7976931348623155e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Ceiling, 1.7976931348623157e308, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Up, 1.7976931348623157e308, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Nearest, 1.7976931348623157e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Floor, -1.7976931348623157e308, Less, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Down, -1.7976931348623155e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Ceiling, -1.7976931348623155e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Up, -1.7976931348623157e308, Less, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Nearest, -1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", Exact, 1.7976931348623157e308, Equal, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", Exact, -1.7976931348623157e308, Equal, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Floor, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Down, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Nearest, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Ceiling, f64::INFINITY, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Up, f64::INFINITY, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Floor, f64::NEGATIVE_INFINITY, Less, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Down, -1.7976931348623157e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Nearest, -1.7976931348623157e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Ceiling, -1.7976931348623157e308, Greater, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Up, f64::NEGATIVE_INFINITY, Less, ); } #[test] #[should_panic] fn f64_rounding_from_integer_fail_1() { f64::rounding_from(&Integer::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap(), Exact); } #[test] #[should_panic] fn f64_rounding_from_integer_fail_2() { f64::rounding_from(&Integer::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap(), Exact); } #[test] #[should_panic] fn f64_rounding_from_integer_fail_3() { f64::rounding_from(&Integer::from_str("9007199254740993").unwrap(), Exact); } #[test] fn test_f32_try_from_integer() { let test = |s: &str, out: Result| { let u = Integer::from_str(s).unwrap(); assert_eq!(f32::try_from(&u).map(NiceFloat), out.map(NiceFloat)); }; test("3", Ok(3.0)); test("-3", Ok(-3.0)); test("123", Ok(123.0)); test("-123", Ok(-123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("-1000000000", Ok(-1.0e9)); test("16777216", Ok(1.6777216e7)); test("-16777216", Ok(-1.6777216e7)); test("16777218", Ok(1.6777218e7)); test("-16777218", Ok(-1.6777218e7)); test("16777217", Err(PrimitiveFloatFromIntegerError)); test("-16777217", Err(PrimitiveFloatFromIntegerError)); test("33554432", Ok(3.3554432e7)); test("-33554432", Ok(-3.3554432e7)); test("33554436", Ok(3.3554436e7)); test("-33554436", Ok(-3.3554436e7)); test("33554433", Err(PrimitiveFloatFromIntegerError)); test("-33554433", Err(PrimitiveFloatFromIntegerError)); test("33554434", Err(PrimitiveFloatFromIntegerError)); test("-33554434", Err(PrimitiveFloatFromIntegerError)); test("33554435", Err(PrimitiveFloatFromIntegerError)); test("-33554435", Err(PrimitiveFloatFromIntegerError)); test( "340282346638528859811704183484516925439", Err(PrimitiveFloatFromIntegerError), ); test( "-340282346638528859811704183484516925439", Err(PrimitiveFloatFromIntegerError), ); test("340282346638528859811704183484516925440", Ok(3.4028235e38)); test( "-340282346638528859811704183484516925440", Ok(-3.4028235e38), ); test( "340282346638528859811704183484516925441", Err(PrimitiveFloatFromIntegerError), ); test( "-340282346638528859811704183484516925441", Err(PrimitiveFloatFromIntegerError), ); test( "10000000000000000000000000000000000000000000000000000", Err(PrimitiveFloatFromIntegerError), ); test( "-10000000000000000000000000000000000000000000000000000", Err(PrimitiveFloatFromIntegerError), ); } #[test] fn test_f64_try_from_integer() { let test = |s: &str, out: Result| { let u = Integer::from_str(s).unwrap(); assert_eq!(f64::try_from(&u).map(NiceFloat), out.map(NiceFloat)); }; test("3", Ok(3.0)); test("-3", Ok(-3.0)); test("123", Ok(123.0)); test("-123", Ok(-123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("-1000000000", Ok(-1.0e9)); test("9007199254740992", Ok(9.007199254740992e15)); test("-9007199254740992", Ok(-9.007199254740992e15)); test("9007199254740994", Ok(9.007199254740994e15)); test("-9007199254740994", Ok(-9.007199254740994e15)); test("9007199254740993", Err(PrimitiveFloatFromIntegerError)); test("-9007199254740993", Err(PrimitiveFloatFromIntegerError)); test("18014398509481984", Ok(1.8014398509481984e16)); test("-18014398509481984", Ok(-1.8014398509481984e16)); test("18014398509481988", Ok(1.8014398509481988e16)); test("-18014398509481988", Ok(-1.8014398509481988e16)); test("18014398509481985", Err(PrimitiveFloatFromIntegerError)); test("-18014398509481985", Err(PrimitiveFloatFromIntegerError)); test("18014398509481986", Err(PrimitiveFloatFromIntegerError)); test("-18014398509481986", Err(PrimitiveFloatFromIntegerError)); test("18014398509481987", Err(PrimitiveFloatFromIntegerError)); test("-18014398509481987", Err(PrimitiveFloatFromIntegerError)); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Err(PrimitiveFloatFromIntegerError), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Err(PrimitiveFloatFromIntegerError), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", Ok(1.7976931348623157e308), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", Ok(-1.7976931348623157e308), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Err(PrimitiveFloatFromIntegerError), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Err(PrimitiveFloatFromIntegerError), ); } #[test] fn test_f32_exact_from_integer() { let test = |s: &str, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(NiceFloat(f32::exact_from(&u)), NiceFloat(out)); }; test("3", 3.0); test("-3", -3.0); test("123", 123.0); test("-123", -123.0); test("0", 0.0); test("1000000000", 1.0e9); test("-1000000000", -1.0e9); test("16777216", 1.6777216e7); test("-16777216", -1.6777216e7); test("16777218", 1.6777218e7); test("-16777218", -1.6777218e7); test("33554432", 3.3554432e7); test("-33554432", -3.3554432e7); test("33554436", 3.3554436e7); test("-33554436", -3.3554436e7); test("340282346638528859811704183484516925440", 3.4028235e38); test("-340282346638528859811704183484516925440", -3.4028235e38); } #[test] #[should_panic] fn f32_exact_from_integer_fail_1() { f32::exact_from(&Integer::from_str("16777217").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_2() { f32::exact_from(&Integer::from_str("-16777217").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_3() { f32::exact_from(&Integer::from_str("33554433").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_4() { f32::exact_from(&Integer::from_str("-33554433").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_5() { f32::exact_from(&Integer::from_str("33554434").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_6() { f32::exact_from(&Integer::from_str("-33554434").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_7() { f32::exact_from(&Integer::from_str("33554435").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_8() { f32::exact_from(&Integer::from_str("-33554435").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_9() { f32::exact_from(&Integer::from_str("340282346638528859811704183484516925439").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_10() { f32::exact_from(&Integer::from_str("-340282346638528859811704183484516925439").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_11() { f32::exact_from(&Integer::from_str("340282346638528859811704183484516925441").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_12() { f32::exact_from(&Integer::from_str("-340282346638528859811704183484516925441").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_13() { f32::exact_from(&Integer::from_str("340282346638528859811704183484516925441").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_14() { f32::exact_from(&Integer::from_str("-340282346638528859811704183484516925441").unwrap()); } #[test] #[should_panic] fn f32_exact_from_integer_fail_15() { f32::exact_from( &Integer::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), ); } #[test] #[should_panic] fn f32_exact_from_integer_fail_16() { f32::exact_from( &Integer::from_str("-10000000000000000000000000000000000000000000000000000").unwrap(), ); } #[test] fn test_f64_exact_from_integer() { let test = |s: &str, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(NiceFloat(f64::exact_from(&u)), NiceFloat(out)); }; test("3", 3.0); test("-3", -3.0); test("123", 123.0); test("-123", -123.0); test("0", 0.0); test("1000000000", 1.0e9); test("-1000000000", -1.0e9); test("9007199254740992", 9.007199254740992e15); test("-9007199254740992", -9.007199254740992e15); test("9007199254740994", 9.007199254740994e15); test("-9007199254740994", -9.007199254740994e15); test("18014398509481984", 1.8014398509481984e16); test("-18014398509481984", -1.8014398509481984e16); test("18014398509481988", 1.8014398509481988e16); test("-18014398509481988", -1.8014398509481988e16); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", 1.7976931348623157e308, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", -1.7976931348623157e308, ); } #[test] #[should_panic] fn f64_exact_from_integer_fail_1() { f64::exact_from(&Integer::from_str("18014398509481983").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_2() { f64::exact_from(&Integer::from_str("-18014398509481983").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_3() { f64::exact_from(&Integer::from_str("18014398509481985").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_4() { f64::exact_from(&Integer::from_str("-18014398509481985").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_5() { f64::exact_from(&Integer::from_str("18014398509481986").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_6() { f64::exact_from(&Integer::from_str("-18014398509481986").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_7() { f64::exact_from(&Integer::from_str("18014398509481987").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_8() { f64::exact_from(&Integer::from_str("-18014398509481987").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_9() { f64::exact_from(&Integer::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_10() { f64::exact_from(&Integer::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_11() { f64::exact_from(&Integer::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap()); } #[test] #[should_panic] fn f64_exact_from_integer_fail_12() { f64::exact_from(&Integer::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369").unwrap()); } #[test] fn test_f32_convertible_from_integer() { let test = |s: &str, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(f32::convertible_from(&u), out); }; test("3", true); test("-3", true); test("123", true); test("-123", true); test("0", true); test("1000000000", true); test("-1000000000", true); test("16777216", true); test("-16777216", true); test("16777218", true); test("-16777218", true); test("16777217", false); test("-16777217", false); test("33554432", true); test("-33554432", true); test("33554436", true); test("-33554436", true); test("33554433", false); test("-33554433", false); test("33554434", false); test("-33554434", false); test("33554435", false); test("-33554435", false); test("340282346638528859811704183484516925439", false); test("-340282346638528859811704183484516925439", false); test("340282346638528859811704183484516925440", true); test("-340282346638528859811704183484516925440", true); test("340282346638528859811704183484516925441", false); test("-340282346638528859811704183484516925441", false); test( "10000000000000000000000000000000000000000000000000000", false, ); test( "-10000000000000000000000000000000000000000000000000000", false, ); } #[test] fn test_f64_convertible_from_integer() { let test = |s: &str, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(f64::convertible_from(&u), out); }; test("3", true); test("-3", true); test("123", true); test("-123", true); test("0", true); test("1000000000", true); test("-1000000000", true); test("9007199254740992", true); test("-9007199254740992", true); test("9007199254740994", true); test("-9007199254740994", true); test("9007199254740993", false); test("-9007199254740993", false); test("18014398509481984", true); test("-18014398509481984", true); test("18014398509481988", true); test("-18014398509481988", true); test("18014398509481985", false); test("-18014398509481985", false); test("18014398509481986", false); test("-18014398509481986", false); test("18014398509481987", false); test("-18014398509481987", false); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", false, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", false, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", true, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", true, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", false, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", false, ); } #[allow(clippy::trait_duplication_in_bounds)] fn float_rounding_from_integer_properties_helper< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Integer> + for<'a> ConvertibleFrom<&'a Natural> + PartialOrd + PrimitiveFloat + for<'a> RoundingFrom<&'a Integer>, >() where Integer: RoundingFrom, Natural: TryFrom, { integer_rounding_mode_pair_gen_var_1::().test_properties(|(n, rm)| { let (f, o) = T::rounding_from(&n, rm); let (f_alt, o_alt) = T::rounding_from(&-&n, -rm); assert_eq!(NiceFloat(f_alt), NiceFloat((-f).abs_negative_zero())); assert_eq!(o_alt, o.reverse()); assert_eq!(f.partial_cmp(&n), Some(o)); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); integer_gen_var_1::().test_properties(|n| { let (f, o) = T::rounding_from(&n, Exact); assert_eq!(o, Equal); let (f_alt, o) = T::rounding_from(&n, Floor); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); let (f_alt, o) = T::rounding_from(&n, Ceiling); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); let (f_alt, o) = T::rounding_from(&n, Down); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); let (f_alt, o) = T::rounding_from(&n, Up); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); let (f_alt, o) = T::rounding_from(&n, Nearest); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); let (n_alt, o) = Integer::rounding_from(f, Exact); assert_eq!(o, Equal); assert_eq!(n_alt, n); }); integer_gen_var_2::().test_properties(|n| { let f_below = T::rounding_from(&n, Floor); assert_eq!(f_below.1, Less); let f_above = (f_below.0.next_higher(), Greater); let f_below = (NiceFloat(f_below.0), f_below.1); let f_above = (NiceFloat(f_above.0), f_above.1); let (f, o) = T::rounding_from(&n, Ceiling); assert_eq!(f_above, (NiceFloat(f), o)); if n >= 0 { let (f_alt, o_alt) = T::rounding_from(&n, Down); assert_eq!((NiceFloat(f_alt), o_alt), f_below); let (f_alt, o_alt) = T::rounding_from(&n, Up); assert_eq!((NiceFloat(f_alt), o_alt), f_above); } else { let (f_alt, o_alt) = T::rounding_from(&n, Down); assert_eq!((NiceFloat(f_alt), o_alt), f_above); let (f_alt, o_alt) = T::rounding_from(&n, Up); assert_eq!((NiceFloat(f_alt), o_alt), f_below); } let f_nearest = T::rounding_from(&n, Nearest); let f_nearest = (NiceFloat(f_nearest.0), f_nearest.1); assert!(f_nearest == f_below || f_nearest == f_above); }); integer_gen_var_3::().test_properties(|n| { let floor = T::rounding_from(&n, Floor); let ceiling = (floor.0.next_higher(), Greater); let nearest = T::rounding_from(&n, Nearest); let floor = (NiceFloat(floor.0), floor.1); let ceiling = (NiceFloat(ceiling.0), ceiling.1); let nearest = (NiceFloat(nearest.0), nearest.1); assert_eq!( nearest, if floor.0.0.to_bits().even() { floor } else { ceiling } ); }); signed_rounding_mode_pair_gen_var_4::().test_properties(|(i, rm)| { let n: Integer = From::from(i); let (f, o) = T::rounding_from(i, rm); let (f_alt, o_alt) = T::rounding_from(&n, rm); assert_eq!(NiceFloat(f), NiceFloat(f_alt)); assert_eq!(o, o_alt); assert_eq!(f.partial_cmp(&n), Some(o)); }); } #[test] fn float_rounding_from_integer_properties() { apply_fn_to_primitive_floats!(float_rounding_from_integer_properties_helper); } #[allow(clippy::trait_duplication_in_bounds)] fn float_try_from_integer_properties_helper< T: for<'a> TryFrom<&'a Integer, Error = PrimitiveFloatFromIntegerError> + for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat + for<'a> RoundingFrom<&'a Integer>, >() where Integer: RoundingFrom, Natural: TryFrom, SignedLimb: RoundingFrom, NiceFloat: TryFrom, { integer_gen().test_properties(|n| { let of = T::try_from(&n); assert_eq!( T::try_from(&-n).map(NiceFloat), of.map(|f| NiceFloat((-f).abs_negative_zero())) ); }); integer_gen_var_1::().test_properties(|n| { let f = T::exact_from(&n); assert_eq!(NiceFloat(f), NiceFloat(T::rounding_from(&n, Exact).0)); assert_eq!(Integer::rounding_from(f, Exact).0, n); }); integer_gen_var_2::().test_properties(|n| { assert!(T::try_from(&n).is_err()); }); integer_gen_var_3::().test_properties(|n| { assert!(T::try_from(&n).is_err()); }); signed_gen::().test_properties(|i| { if let Ok(f) = NiceFloat::::try_from(i) { assert_eq!(f, NiceFloat(T::exact_from(&Integer::from(i)))); } }); signed_gen_var_7::().test_properties(|i| { assert_eq!( NiceFloat::::exact_from(i), NiceFloat(T::exact_from(&Integer::from(i))) ); }); } #[test] fn float_try_from_integer_properties() { apply_fn_to_primitive_floats!(float_try_from_integer_properties_helper); } #[allow(clippy::trait_duplication_in_bounds)] fn float_convertible_from_integer_properties_helper< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Integer> + for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >() where Natural: TryFrom, { integer_gen().test_properties(|n| { assert_eq!(T::convertible_from(&n), T::convertible_from(&-n)); }); integer_gen_var_1::().test_properties(|n| { assert!(T::convertible_from(&n)); }); integer_gen_var_2::().test_properties(|n| { assert!(!T::convertible_from(&n)); }); integer_gen_var_3::().test_properties(|n| { assert!(!T::convertible_from(&n)); }); signed_gen::().test_properties(|i| { let n: Integer = From::from(i); assert_eq!(T::convertible_from(i), T::convertible_from(&n)); }); } #[test] fn float_convertible_from_integer_properties() { apply_fn_to_primitive_floats!(float_convertible_from_integer_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/conversion/primitive_int_from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, OverflowingFrom, SaturatingFrom, WrappingFrom, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; use malachite_nz::integer::conversion::primitive_int_from_integer::SignedFromIntegerError; use malachite_nz::integer::conversion::primitive_int_from_integer::UnsignedFromIntegerError; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::integer_gen; use rug; use std::str::FromStr; #[test] fn test_u32_try_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::try_from(&u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .to_u32() .ok_or(UnsignedFromIntegerError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Err(UnsignedFromIntegerError)); test("4294967295", Ok(u32::MAX)); test("4294967296", Err(UnsignedFromIntegerError)); test("-123", Err(UnsignedFromIntegerError)); test("-1000000000000", Err(UnsignedFromIntegerError)); test("-4294967295", Err(UnsignedFromIntegerError)); test("-4294967296", Err(UnsignedFromIntegerError)); } #[test] fn test_u32_exact_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::exact_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_u32().unwrap(), out); }; test("0", 0); test("123", 123); test("4294967295", u32::MAX); } #[test] #[should_panic] fn u32_exact_from_integer_fail_1() { u32::exact_from(&Integer::from_str("1000000000000").unwrap()); } #[test] #[should_panic] fn u32_exact_from_integer_fail_2() { u32::exact_from(&Integer::from_str("4294967296").unwrap()); } #[test] #[should_panic] fn u32_exact_from_integer_fail_3() { u32::exact_from(&Integer::from_str("-123").unwrap()); } #[test] #[should_panic] fn u32_exact_from_integer_fail_4() { u32::exact_from(&Integer::from_str("-1000000000000").unwrap()); } #[test] #[should_panic] fn u32_exact_from_integer_fail_5() { u32::exact_from(&Integer::from_str("-4294967295").unwrap()); } #[test] #[should_panic] fn u32_exact_from_integer_fail_6() { u32::exact_from(&Integer::from_str("-4294967296").unwrap()); } #[test] fn test_u32_wrapping_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::wrapping_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_u32_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000", 3567587328); test("4294967296", 0); test("4294967297", 1); test("-123", 4294967173); test("-1000000000000", 727379968); test("-4294967296", 0); test("-4294967297", u32::MAX); } #[test] fn test_u32_saturating_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::saturating_from(&u), out); }; test("0", 0); test("123", 123); test("1000000000000", u32::MAX); test("4294967296", u32::MAX); test("4294967297", u32::MAX); test("-123", 0); test("-1000000000000", 0); test("-4294967296", 0); test("-4294967297", 0); } #[test] fn test_u32_overflowing_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::overflowing_from(&u), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000", (3567587328, true)); test("4294967296", (0, true)); test("4294967297", (1, true)); test("-123", (4294967173, true)); test("-1000000000000", (727379968, true)); test("-4294967296", (0, true)); test("-4294967297", (u32::MAX, true)); } #[test] fn test_u32_convertible_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u32::convertible_from(&u), out); }; test("0", true); test("123", true); test("1000000000000", false); test("4294967295", true); test("4294967296", false); test("-123", false); test("-1000000000000", false); test("-4294967295", false); test("-4294967296", false); } #[test] fn test_u64_try_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::try_from(&u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .to_u64() .ok_or(UnsignedFromIntegerError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Ok(1000000000000)); test("18446744073709551615", Ok(u64::MAX)); test("18446744073709551616", Err(UnsignedFromIntegerError)); test("-123", Err(UnsignedFromIntegerError)); test("-1000000000000", Err(UnsignedFromIntegerError)); test("-18446744073709551615", Err(UnsignedFromIntegerError)); test("-18446744073709551616", Err(UnsignedFromIntegerError)); } #[test] fn test_u64_exact_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::exact_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_u64().unwrap(), out); }; test("0", 0); test("123", 123); test("1000000000000", 1000000000000); test("18446744073709551615", u64::MAX); } #[test] #[should_panic] fn u64_exact_from_integer_fail_1() { u64::exact_from(&Integer::from_str("18446744073709551616").unwrap()); } #[test] #[should_panic] fn u64_exact_from_integer_fail_2() { u64::exact_from(&Integer::from_str("-123").unwrap()); } #[test] #[should_panic] fn u64_exact_from_integer_fail_3() { u64::exact_from(&Integer::from_str("-1000000000000").unwrap()); } #[test] #[should_panic] fn u64_exact_from_integer_fail_4() { u64::exact_from(&Integer::from_str("-18446744073709551615").unwrap()); } #[test] #[should_panic] fn u64_exact_from_integer_fail_5() { u64::exact_from(&Integer::from_str("-18446744073709551616").unwrap()); } #[test] fn test_u64_wrapping_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::wrapping_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_u64_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 2003764205206896640); test("18446744073709551616", 0); test("18446744073709551617", 1); test("-123", 18446744073709551493); test("-1000000000000000000000000", 16442979868502654976); test("-18446744073709551616", 0); test("-18446744073709551617", u64::MAX); } #[test] fn test_u64_saturating_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::saturating_from(&u), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", u64::MAX); test("18446744073709551616", u64::MAX); test("18446744073709551617", u64::MAX); test("-123", 0); test("-1000000000000000000000000", 0); test("-18446744073709551616", 0); test("-18446744073709551617", 0); } #[test] fn test_u64_overflowing_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::overflowing_from(&u), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000000000000000", (2003764205206896640, true)); test("18446744073709551616", (0, true)); test("18446744073709551617", (1, true)); test("-123", (18446744073709551493, true)); test("-1000000000000000000000000", (16442979868502654976, true)); test("-18446744073709551616", (0, true)); test("-18446744073709551617", (u64::MAX, true)); } #[test] fn test_u64_convertible_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u64::convertible_from(&u), out); }; test("0", true); test("123", true); test("1000000000000000000000000", false); test("18446744073709551615", true); test("18446744073709551616", false); test("-123", false); test("-1000000000000000000000000", false); test("-18446744073709551615", false); test("-18446744073709551616", false); } #[test] fn test_i32_try_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::try_from(&u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .to_i32() .ok_or(SignedFromIntegerError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Err(SignedFromIntegerError)); test("2147483647", Ok(i32::MAX)); test("2147483648", Err(SignedFromIntegerError)); test("-123", Ok(-123)); test("-1000000000000", Err(SignedFromIntegerError)); test("-2147483648", Ok(i32::MIN)); test("-2147483649", Err(SignedFromIntegerError)); } #[test] fn test_i32_exact_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::exact_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_i32().unwrap(), out); }; test("0", 0); test("123", 123); test("2147483647", i32::MAX); test("-123", -123); test("-2147483648", i32::MIN); } #[test] #[should_panic] fn i32_exact_from_integer_fail_1() { i32::exact_from(&Integer::from_str("1000000000000").unwrap()); } #[test] #[should_panic] fn i32_exact_from_integer_fail_2() { i32::exact_from(&Integer::from_str("2147483648").unwrap()); } #[test] #[should_panic] fn i32_exact_from_integer_fail_3() { i32::exact_from(&Integer::from_str("-1000000000000").unwrap()); } #[test] #[should_panic] fn i32_exact_from_integer_fail_4() { i32::exact_from(&Integer::from_str("-2147483649").unwrap()); } #[test] fn test_i32_wrapping_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::wrapping_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_i32_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000", -727379968); test("2147483648", -0x80000000); test("2147483649", -0x7fffffff); test("-123", -123); test("-1000000000000", 727379968); test("-2147483649", 0x7fffffff); test("-2147483650", 0x7ffffffe); } #[test] fn test_i32_saturating_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::saturating_from(&u), out); }; test("0", 0); test("123", 123); test("1000000000000", 0x7fffffff); test("2147483648", 0x7fffffff); test("2147483649", 0x7fffffff); test("-123", -123); test("-1000000000000", -0x80000000); test("-2147483648", -0x80000000); test("-2147483649", -0x80000000); } #[test] fn test_i32_overflowing_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::overflowing_from(&u), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000", (-727379968, true)); test("2147483648", (-0x80000000, true)); test("2147483649", (-0x7fffffff, true)); test("-123", (-123, false)); test("-1000000000000", (727379968, true)); test("-2147483649", (0x7fffffff, true)); test("-2147483650", (0x7ffffffe, true)); } #[test] fn test_i32_convertible_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i32::convertible_from(&u), out); }; test("0", true); test("123", true); test("1000000000000", false); test("2147483647", true); test("2147483648", false); test("-123", true); test("-1000000000000", false); test("-2147483648", true); test("-2147483649", false); } #[test] fn test_i64_try_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::try_from(&u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .to_i64() .ok_or(SignedFromIntegerError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000000000000000", Err(SignedFromIntegerError)); test("9223372036854775807", Ok(i64::MAX)); test("9223372036854775808", Err(SignedFromIntegerError)); test("-123", Ok(-123)); test("-1000000000000000000000000", Err(SignedFromIntegerError)); test("-9223372036854775808", Ok(i64::MIN)); test("-9223372036854775809", Err(SignedFromIntegerError)); } #[test] fn test_i64_exact_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::exact_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_i64().unwrap(), out); }; test("0", 0); test("123", 123); test("9223372036854775807", i64::MAX); test("-123", -123); test("-9223372036854775808", i64::MIN); } #[test] #[should_panic] fn i64_exact_from_integer_fail_1() { i64::exact_from(&Integer::from_str("1000000000000000000000000").unwrap()); } #[test] #[should_panic] fn i64_exact_from_integer_fail_2() { i64::exact_from(&Integer::from_str("9223372036854775808").unwrap()); } #[test] #[should_panic] fn i64_exact_from_integer_fail_3() { i64::exact_from(&Integer::from_str("-1000000000000000000000000").unwrap()); } #[test] #[should_panic] fn i64_exact_from_integer_fail_4() { i64::exact_from(&Integer::from_str("-9223372036854775809").unwrap()); } #[test] fn test_i64_wrapping_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::wrapping_from(&u), out); assert_eq!(rug::Integer::from_str(s).unwrap().to_i64_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 2003764205206896640); test("9223372036854775808", -0x8000000000000000); test("9223372036854775809", -0x7fffffffffffffff); test("-123", -123); test("-1000000000000000000000000", -2003764205206896640); test("-9223372036854775809", 0x7fffffffffffffff); test("-9223372036854775810", 0x7ffffffffffffffe); } #[test] fn test_i64_saturating_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::saturating_from(&u), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 0x7fffffffffffffff); test("9223372036854775808", 0x7fffffffffffffff); test("9223372036854775809", 0x7fffffffffffffff); test("-123", -123); test("-1000000000000000000000000", -0x8000000000000000); test("-9223372036854775808", -0x8000000000000000); test("-9223372036854775809", -0x8000000000000000); } #[test] fn test_i64_overflowing_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::overflowing_from(&u), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000000000000000", (2003764205206896640, true)); test("9223372036854775808", (-0x8000000000000000, true)); test("9223372036854775809", (-0x7fffffffffffffff, true)); test("-123", (-123, false)); test("-1000000000000000000000000", (-2003764205206896640, true)); test("-9223372036854775809", (0x7fffffffffffffff, true)); test("-9223372036854775810", (0x7ffffffffffffffe, true)); } #[test] fn test_i64_convertible_from_integer() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(i64::convertible_from(&u), out); }; test("0", true); test("123", true); test("1000000000000000000000000", false); test("9223372036854775807", true); test("9223372036854775808", false); test("-123", true); test("-1000000000000000000000000", false); test("-9223372036854775808", true); test("-9223372036854775809", false); } #[allow(clippy::trait_duplication_in_bounds)] fn unsigned_from_integer_properties_helper< T: for<'a> TryFrom<&'a Integer, Error = UnsignedFromIntegerError> + for<'a> TryFrom<&'a Natural> + for<'a> OverflowingFrom<&'a Integer> + PrimitiveUnsigned + for<'a> WrappingFrom<&'a Integer>, >() where Integer: From, { integer_gen().test_properties(|x| { let result = T::try_from(&x); if x >= 0 && x.significant_bits() <= T::WIDTH { assert_eq!(Integer::from(result.unwrap()), x); assert_eq!(result, Ok(T::wrapping_from(&x))); assert_eq!(result, Ok(T::exact_from(&x))); } else { assert!(result.is_err()); } assert_eq!(result.is_err(), T::overflowing_from(&x).1); let result = T::wrapping_from(&x); assert_eq!(result, T::exact_from(&(&x).mod_power_of_2(T::WIDTH))); }); } fn signed_from_integer_properties_helper< T: for<'a> TryFrom<&'a Integer, Error = SignedFromIntegerError> + for<'a> OverflowingFrom<&'a Integer> + PrimitiveSigned + for<'a> WrappingFrom<&'a Integer>, >() where Integer: From, { let min = -Integer::power_of_2(T::WIDTH - 1); integer_gen().test_properties(|x| { let result = T::try_from(&x); if x.significant_bits() < T::WIDTH || x == min { assert_eq!(Integer::from(result.unwrap()), x); assert_eq!(result, Ok(T::wrapping_from(&x))); assert_eq!(result, Ok(T::exact_from(&x))); } else { assert!(result.is_err()); } assert_eq!(result.is_err(), T::overflowing_from(&x).1); }); } fn primitive_int_from_integer_properties_helper< T: for<'a> ConvertibleFrom<&'a Integer> + for<'a> OverflowingFrom<&'a Integer> + PrimitiveInt + for<'a> SaturatingFrom<&'a Integer> + PartialEq + PartialOrdAbs + for<'a> WrappingFrom<&'a Integer>, >() where Integer: PartialOrd, { integer_gen().test_properties(|x| { let result = T::wrapping_from(&x); assert_eq!(result, T::overflowing_from(&x).0); let result = T::saturating_from(&x); assert!(result.le_abs(&x)); assert_eq!(result == x, T::convertible_from(&x)); let result = T::overflowing_from(&x); assert_eq!(result, (T::wrapping_from(&x), !T::convertible_from(&x))); let convertible = T::convertible_from(&x); assert_eq!(convertible, x >= T::MIN && x <= T::MAX); }); } #[test] fn primitive_int_from_integer_properties() { apply_fn_to_primitive_ints!(primitive_int_from_integer_properties_helper); apply_fn_to_unsigneds!(unsigned_from_integer_properties_helper); apply_fn_to_signeds!(signed_from_integer_properties_helper); } ================================================ FILE: malachite-nz/tests/integer/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{string_gen, string_gen_var_9}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use std::str::FromStr; #[test] fn test_serde() { let test = |n, out| { assert_eq!( serde_json::to_string(&Integer::from_str(n).unwrap()).unwrap(), out ); assert_eq!(serde_json::from_str::(out).unwrap().to_string(), n); }; test("0", "\"0x0\""); test("100", "\"0x64\""); test("1000000000000", "\"0xe8d4a51000\""); test("4294967295", "\"0xffffffff\""); test("4294967296", "\"0x100000000\""); test("18446744073709551615", "\"0xffffffffffffffff\""); test("18446744073709551616", "\"0x10000000000000000\""); test("1000000000000000000000000", "\"0xd3c21bcecceda1000000\""); test( "340282366920938463463374607431768211455", "\"0xffffffffffffffffffffffffffffffff\"", ); test( "340282366920938463463374607431768211456", "\"0x100000000000000000000000000000000\"", ); test("-100", "\"-0x64\""); test("-1000000000000", "\"-0xe8d4a51000\""); test("-4294967295", "\"-0xffffffff\""); test("-4294967296", "\"-0x100000000\""); test("-18446744073709551615", "\"-0xffffffffffffffff\""); test("-18446744073709551616", "\"-0x10000000000000000\""); test("-1000000000000000000000000", "\"-0xd3c21bcecceda1000000\""); test( "-340282366920938463463374607431768211455", "\"-0xffffffffffffffffffffffffffffffff\"", ); test( "-340282366920938463463374607431768211456", "\"-0x100000000000000000000000000000000\"", ); } #[test] fn serde_properties() { integer_gen().test_properties(|x| { let s = serde_json::to_string(&x).unwrap(); assert_eq!(serde_json::from_str::(&s).unwrap(), x); assert!(string_is_subset(&s, "\"-0123456789abcdefx")); }); string_gen().test_properties(|s| { let _n: Result = serde_json::from_str(&s); }); string_gen_var_9().test_properties(|s| { let _n: Integer = serde_json::from_str(&s).unwrap(); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::{FromSciString, ToStringBase}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use std::str::FromStr; #[test] pub fn test_from_sci_string() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Integer::from_str(s).unwrap()); assert_eq!(Integer::from_sci_string(s), out); assert_eq!( Integer::from_sci_string_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("-123", Some("-123")); test("-00123", Some("-123")); test("-123.00", Some("-123")); test("-123e0", Some("-123")); test("-12.3e1", Some("-123")); test("-1.23e2", Some("-123")); test("-1.23E2", Some("-123")); test("-1.23e+2", Some("-123")); test("-1.23E+2", Some("-123")); test("-.123e3", Some("-123")); test("-0.123e3", Some("-123")); test("-0.0123e4", Some("-123")); test("-1230e-1", Some("-123")); test("-12300e-2", Some("-123")); test("-12300E-2", Some("-123")); test("123.4", Some("123")); test("123.8", Some("124")); test("123.5", Some("124")); test("124.5", Some("124")); test("127.49", Some("127")); test("-123.4", Some("-123")); test("-123.8", Some("-124")); test("-123.5", Some("-124")); test("-124.5", Some("-124")); test("-127.49", Some("-127")); test("-127.5", Some("-128")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Integer::from_str(s).unwrap()); assert_eq!(Integer::from_sci_string_with_options(s, options), out); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Integer: From, { let out = out.map(Integer::from); assert_eq!(Integer::from_sci_string_with_options(s, options), out); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_i( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_i( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_i( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_i( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_i("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_i("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_i("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_rounding_mode(Down); test("123.4", options, Some("123")); options.set_rounding_mode(Floor); test("123.4", options, Some("123")); options.set_rounding_mode(Up); test("123.4", options, Some("124")); options.set_rounding_mode(Ceiling); test("123.4", options, Some("124")); options.set_rounding_mode(Nearest); test("123.4", options, Some("123")); options.set_rounding_mode(Exact); test("123.4", options, None); options.set_rounding_mode(Down); test("123.5", options, Some("123")); options.set_rounding_mode(Floor); test("123.5", options, Some("123")); options.set_rounding_mode(Up); test("123.5", options, Some("124")); options.set_rounding_mode(Ceiling); test("123.5", options, Some("124")); options.set_rounding_mode(Nearest); test("123.5", options, Some("124")); options.set_rounding_mode(Exact); test("123.5", options, None); options.set_rounding_mode(Down); test("0.4", options, Some("0")); options.set_rounding_mode(Floor); test("0.4", options, Some("0")); options.set_rounding_mode(Up); test("0.4", options, Some("1")); options.set_rounding_mode(Ceiling); test("0.4", options, Some("1")); options.set_rounding_mode(Nearest); test("0.4", options, Some("0")); options.set_rounding_mode(Exact); test("0.4", options, None); options.set_rounding_mode(Down); test("0.04", options, Some("0")); options.set_rounding_mode(Floor); test("0.04", options, Some("0")); options.set_rounding_mode(Up); test("0.04", options, Some("1")); options.set_rounding_mode(Ceiling); test("0.04", options, Some("1")); options.set_rounding_mode(Nearest); test("0.04", options, Some("0")); options.set_rounding_mode(Exact); test("0.04", options, None); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("1")); test("1.1", options, Some("2")); test("1.11", options, Some("2")); test("0.01", options, Some("0")); test("0.1", options, Some("0")); test("0.11", options, Some("1")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("1")); test("1.11", options, Some("1")); test("1.111", options, Some("1")); test("1.112", options, Some("2")); test("0.1", options, Some("0")); test("0.11", options, Some("0")); test("0.111", options, Some("0")); test("0.112", options, Some("1")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options = FromSciStringOptions::default(); options.set_rounding_mode(Exact); test("1.5", options, None); test("1.9999999999999999999999999999", options, None); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("-1e+5", options, Some("-32")); test("-1e5", options, Some("-32")); options.set_base(3); test("-1e+5", options, Some("-243")); test("-1e5", options, Some("-243")); options.set_base(4); test("-1e+5", options, Some("-1024")); test("-1e5", options, Some("-1024")); options.set_base(5); test("-1e+5", options, Some("-3125")); test("-1e5", options, Some("-3125")); options.set_base(8); test("-1e+5", options, Some("-32768")); test("-1e5", options, Some("-32768")); options.set_base(16); test("-1e+5", options, Some("-1048576")); test("-1e5", options, Some("-485")); options.set_base(32); test("-1e+5", options, Some("-33554432")); test("-1e5", options, Some("-1477")); options.set_base(36); test("-1e+5", options, Some("-60466176")); test("-1E+5", options, Some("-60466176")); test("-1e5", options, Some("-1805")); options.set_base(16); test("-ff", options, Some("-255")); test("-fF", options, Some("-255")); test("-Ff", options, Some("-255")); test("-FF", options, Some("-255")); options = FromSciStringOptions::default(); options.set_rounding_mode(Down); test("-123.4", options, Some("-123")); options.set_rounding_mode(Floor); test("-123.4", options, Some("-124")); options.set_rounding_mode(Up); test("-123.4", options, Some("-124")); options.set_rounding_mode(Ceiling); test("-123.4", options, Some("-123")); options.set_rounding_mode(Nearest); test("-123.4", options, Some("-123")); options.set_rounding_mode(Exact); test("-123.4", options, None); options.set_rounding_mode(Down); test("-123.5", options, Some("-123")); options.set_rounding_mode(Floor); test("-123.5", options, Some("-124")); options.set_rounding_mode(Up); test("-123.5", options, Some("-124")); options.set_rounding_mode(Ceiling); test("-123.5", options, Some("-123")); options.set_rounding_mode(Nearest); test("-123.5", options, Some("-124")); options.set_rounding_mode(Exact); test("-123.5", options, None); options.set_rounding_mode(Down); test("-0.4", options, Some("0")); options.set_rounding_mode(Floor); test("-0.4", options, Some("-1")); options.set_rounding_mode(Up); test("-0.4", options, Some("-1")); options.set_rounding_mode(Ceiling); test("-0.4", options, Some("0")); options.set_rounding_mode(Nearest); test("-0.4", options, Some("0")); options.set_rounding_mode(Exact); test("-0.4", options, None); options.set_rounding_mode(Down); test("-0.04", options, Some("0")); options.set_rounding_mode(Floor); test("-0.04", options, Some("-1")); options.set_rounding_mode(Up); test("-0.04", options, Some("-1")); options.set_rounding_mode(Ceiling); test("-0.04", options, Some("0")); options.set_rounding_mode(Nearest); test("-0.04", options, Some("0")); options.set_rounding_mode(Exact); test("-0.04", options, None); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("-1.01", options, Some("-1")); test("-1.1", options, Some("-2")); test("-1.11", options, Some("-2")); test("-0.01", options, Some("0")); test("-0.1", options, Some("0")); test("-0.11", options, Some("-1")); options.set_base(3); // 1/2 is 0.111... test("-1.1", options, Some("-1")); test("-1.11", options, Some("-1")); test("-1.111", options, Some("-1")); test("-1.112", options, Some("-2")); test("-0.1", options, Some("0")); test("-0.11", options, Some("0")); test("-0.111", options, Some("0")); test("-0.112", options, Some("-1")); options = FromSciStringOptions::default(); options.set_base(2); test("-2", options, None); test("-102", options, None); test("-12e4", options, None); test("-12e-4", options, None); test("-1.2", options, None); test("-0.2", options, None); test("-0.002", options, None); options = FromSciStringOptions::default(); options.set_rounding_mode(Exact); test("-1.5", options, None); test("-1.9999999999999999999999999999", options, None); } fn from_sci_string_helper(s: &str) { if let Some(x) = Integer::from_sci_string(s) { for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string(), s); } } #[test] fn from_sci_string_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_helper(&s); }); integer_gen().test_properties(|x| { assert_eq!(Integer::from_sci_string(&x.to_string()).unwrap(), x); }); } fn from_sci_string_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Integer::from_sci_string_with_options(s, options) { assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string_base(options.get_base()), s.to_lowercase()); } } #[test] fn from_sci_string_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ExactFrom, FromStringBase, ToStringBase}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::exhaustive::valid_digit_chars; use malachite_base::test_util::generators::{ signed_gen, signed_unsigned_pair_gen_var_5, string_gen, string_gen_var_4, unsigned_gen_var_11, unsigned_pair_gen_var_19, unsigned_string_pair_gen_var_2, unsigned_string_pair_gen_var_3, }; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use num::{BigInt, Num}; use rug; use std::collections::HashMap; use std::str::FromStr; #[test] fn test_from_str() { let test_ok = |s, n| { assert_eq!(Integer::from_str(s).unwrap().to_string(), n); assert_eq!(BigInt::from_str(s).unwrap().to_string(), n); assert_eq!(rug::Integer::from_str(s).unwrap().to_string(), n); }; test_ok("0", "0"); test_ok("+0", "0"); test_ok("-0", "0"); test_ok("123456", "123456"); test_ok("+123456", "123456"); test_ok("1000000000000000000000000", "1000000000000000000000000"); test_ok("-123456", "-123456"); test_ok("-1000000000000000000000000", "-1000000000000000000000000"); let test_err = |s, rug_err| { assert!(Integer::from_str(s).is_err()); assert!(BigInt::from_str(s).is_err()); let rn = rug::Integer::from_str(s); assert_eq!(rn.is_err() || rn.unwrap() < 0, rug_err); }; test_err("12A", true); test_err(" 10", false); test_err("1.0", true); test_err("$%^", true); test_err("", true); test_err("-", true); test_err("--0", true); test_err("-+0", true); test_err("+-0", true); test_err("++0", true); test_err("--1", true); test_err("-+1", true); test_err("+-1", true); test_err("++1", true); } #[test] fn from_str_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); string_gen().test_properties_with_config(&config, |s| { let trimmed = s.strip_prefix('-').unwrap_or(&s); let trimmed = trimmed.strip_prefix('+').unwrap_or(trimmed); assert_eq!( Integer::from_str(&s).is_ok(), !trimmed.is_empty() && trimmed.chars().all(|c| c.is_ascii_digit()), ); }); string_gen_var_4().test_properties(|s| { let n = Integer::from_str(&s).unwrap(); let abs_s = s.strip_prefix('-').unwrap_or(&s); let trimmed = abs_s.trim_start_matches('0'); let trimmed = if trimmed.is_empty() { "0".to_string() } else if s.starts_with('-') { "-".to_string() + trimmed } else { trimmed.to_string() }; assert_eq!(n.to_string(), trimmed); assert_eq!(n, Integer::from_string_base(10, &s).unwrap()); let mut with_zero = "0".to_string() + abs_s; if s.starts_with('-') { with_zero = "-".to_string() + &with_zero; } assert_eq!(Integer::from_str(&with_zero).unwrap(), n); assert_eq!(BigInt::from_str(&s).unwrap(), BigInt::from(&n)); assert_eq!(rug::Integer::from_str(&s).unwrap(), rug::Integer::from(&n)); }); unsigned_gen_var_11().test_properties(|u| { let zeros = vec![b'0'; u]; let zero_s = std::str::from_utf8(&zeros).unwrap(); assert_eq!(Integer::from_str(zero_s).unwrap(), 0); assert_eq!(Integer::from_str(&("-".to_string() + zero_s)).unwrap(), 0); }); signed_gen::().test_properties(|u| { let s = u.to_string(); assert_eq!( Integer::from_str(&s).unwrap(), Integer::from(SignedLimb::from_str(&s).unwrap()) ); }); } #[test] fn test_from_string_base() { let test_ok = |base, s, n| { assert_eq!(Integer::from_string_base(base, s).unwrap().to_string(), n); assert_eq!( BigInt::from_str_radix(s, u32::exact_from(base)) .unwrap() .to_string(), n ); assert_eq!( rug::Integer::from_str_radix(s, i32::exact_from(base)) .unwrap() .to_string(), n ); }; test_ok(2, "0", "0"); test_ok(10, "0", "0"); test_ok(2, "101", "5"); test_ok(10, "123456", "123456"); test_ok(16, "deadbeef", "3735928559"); test_ok(16, "DEADBEEF", "3735928559"); test_ok(16, "deAdBeEf", "3735928559"); test_ok(10, "1000000000000000000000000", "1000000000000000000000000"); test_ok(2, "1000000000000000000000000", "16777216"); test_ok( 36, "1000000000000000000000000", "22452257707354557240087211123792674816", ); test_ok(36, "helloworld", "1767707668033969"); test_ok(2, "-0", "0"); test_ok(10, "-0", "0"); test_ok(2, "-101", "-5"); test_ok(10, "-123456", "-123456"); test_ok(16, "-deadbeef", "-3735928559"); test_ok(16, "-DEADBEEF", "-3735928559"); test_ok(16, "-deAdBeEf", "-3735928559"); test_ok( 10, "-1000000000000000000000000", "-1000000000000000000000000", ); test_ok(2, "-1000000000000000000000000", "-16777216"); test_ok( 36, "-1000000000000000000000000", "-22452257707354557240087211123792674816", ); test_ok(36, "-helloworld", "-1767707668033969"); let test_err = |base, s, rug_err| { assert!(Integer::from_string_base(base, s).is_none()); assert!(BigInt::from_str_radix(s, u32::exact_from(base)).is_err()); assert_eq!( rug::Integer::from_str_radix(s, i32::exact_from(base)).is_err(), rug_err ); }; test_err(2, "123", true); test_err(10, "12A", true); test_err(35, " 10", false); test_err(35, "1.0", true); test_err(35, "$%^", true); test_err(35, "", true); test_err(35, "-", true); } #[test] fn from_string_base_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); let mut digit_map = HashMap::new(); unsigned_string_pair_gen_var_2().test_properties_with_config(&config, |(base, s)| { let abs_s = s.strip_prefix('-').unwrap_or(&s); let digits = digit_map .entry(base) .or_insert_with(|| valid_digit_chars(base)); assert_eq!( Integer::from_string_base(base, &s).is_some(), !abs_s.is_empty() && abs_s.chars().all(|c| digits.contains(&c)), ); }); unsigned_string_pair_gen_var_3().test_properties(|(base, s)| { let n = Integer::from_string_base(base, &s).unwrap(); let s_lo = s.to_lowercase(); let abs_s = s_lo.strip_prefix('-').unwrap_or(&s_lo); let trimmed = abs_s.trim_start_matches('0'); let trimmed = if trimmed.is_empty() { "0".to_string() } else if s.starts_with('-') { "-".to_string() + trimmed } else { trimmed.to_string() }; assert_eq!(n.to_string_base(base), trimmed); let mut with_zero = "0".to_string() + abs_s; if s.starts_with('-') { with_zero = "-".to_string() + &with_zero; } assert_eq!(Integer::from_string_base(base, &with_zero).unwrap(), n); assert_eq!( BigInt::from_str_radix(&s, u32::from(base)).unwrap(), BigInt::from(&n) ); assert_eq!( rug::Integer::from_str_radix(&s, i32::from(base)).unwrap(), rug::Integer::from(&n) ); }); unsigned_pair_gen_var_19().test_properties(|(u, base)| { let zeros = vec![b'0'; u]; let zero_s = std::str::from_utf8(&zeros).unwrap(); assert_eq!(Integer::from_string_base(base, zero_s).unwrap(), 0); assert_eq!( Integer::from_string_base(base, &("-".to_string() + zero_s)).unwrap(), 0 ); }); signed_unsigned_pair_gen_var_5::().test_properties(|(i, base)| { let s = i.to_string_base(base); assert_eq!( Integer::from_string_base(base, &s).unwrap(), Integer::from(SignedLimb::from_string_base(base, &s).unwrap()) ); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{FloorLogBase, Pow, PowerOf2, RoundToMultiple}; use malachite_base::num::conversion::string::options::{ FromSciStringOptions, SciSizeOptions, ToSciOptions, }; use malachite_base::num::conversion::traits::{FromSciString, ToSci}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{signed_gen, signed_to_sci_options_pair_gen_var_1}; use malachite_base::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, integer_to_sci_options_pair_gen_var_1}; use std::collections::HashMap; use std::str::FromStr; #[test] pub fn test_to_sci() { assert_eq!( Integer::power_of_2(1000000).to_sci().to_string(), "9.900656229295898e301029" ); assert_eq!( (-Integer::power_of_2(1000000)).to_sci().to_string(), "-9.900656229295898e301029" ); fn test_i(x: &Integer, out: &str) { assert_eq!(x.to_sci().to_string(), out); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), out ); } fn test(s: &str, out: &str) { test_i(&Integer::from_str(s).unwrap(), out); } test("0", "0"); test("1", "1"); test("10", "10"); test("100", "100"); test("1000", "1000"); test("10000", "10000"); test("100000", "100000"); test("1000000", "1000000"); test("10000000", "10000000"); test("100000000", "100000000"); test("1000000000", "1000000000"); test("10000000000", "10000000000"); test("100000000000", "100000000000"); test("1000000000000", "1000000000000"); test("10000000000000", "10000000000000"); test("100000000000000", "100000000000000"); test("1000000000000000", "1000000000000000"); test("10000000000000000", "1e16"); test("100000000000000000", "1e17"); test_i(&Integer::from(u64::MAX), "1.844674407370955e19"); test_i(&Integer::from(u128::MAX), "3.402823669209385e38"); test_i(&Integer::from(i64::MAX), "9.223372036854776e18"); test_i(&Integer::from(i128::MAX), "1.701411834604692e38"); test("999999999999999", "999999999999999"); test("9999999999999999", "9999999999999999"); test("99999999999999999", "1e17"); test("999999999999999999", "1e18"); test("-1", "-1"); test("-10", "-10"); test("-100", "-100"); test("-1000", "-1000"); test("-10000", "-10000"); test("-100000", "-100000"); test("-1000000", "-1000000"); test("-10000000", "-10000000"); test("-100000000", "-100000000"); test("-1000000000", "-1000000000"); test("-10000000000", "-10000000000"); test("-100000000000", "-100000000000"); test("-1000000000000", "-1000000000000"); test("-10000000000000", "-10000000000000"); test("-100000000000000", "-100000000000000"); test("-1000000000000000", "-1000000000000000"); test("-10000000000000000", "-1e16"); test("-100000000000000000", "-1e17"); test_i(&Integer::from(i64::MIN), "-9.223372036854776e18"); test_i(&Integer::from(i128::MIN), "-1.701411834604692e38"); } #[test] pub fn test_to_sci_with_options() { fn test_i(x: &Integer, options: ToSciOptions, out: &str) { assert_eq!(x.to_sci_with_options(options).to_string(), out); } fn test(s: &str, options: ToSciOptions, out: &str) { test_i(&Integer::from_str(s).unwrap(), options, out); } // For tests with the default options, see `test_to_sci` let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test("0", options, "0.000000000000000"); test("1", options, "1.000000000000000"); test("10", options, "10.00000000000000"); test("100", options, "100.0000000000000"); test("1000", options, "1000.000000000000"); test("10000", options, "10000.00000000000"); test("100000", options, "100000.0000000000"); test("1000000", options, "1000000.000000000"); test("10000000", options, "10000000.00000000"); test("100000000", options, "100000000.0000000"); test("1000000000", options, "1000000000.000000"); test("10000000000", options, "10000000000.00000"); test("100000000000", options, "100000000000.0000"); test("1000000000000", options, "1000000000000.000"); test("10000000000000", options, "10000000000000.00"); test("100000000000000", options, "100000000000000.0"); test("1000000000000000", options, "1000000000000000"); test("10000000000000000", options, "1.000000000000000e16"); test("100000000000000000", options, "1.000000000000000e17"); test_i(&Integer::from(u64::MAX), options, "1.844674407370955e19"); test_i(&Integer::from(u128::MAX), options, "3.402823669209385e38"); test("999999999999999", options, "999999999999999.0"); test("9999999999999999", options, "9999999999999999"); test("99999999999999999", options, "1.000000000000000e17"); test("999999999999999999", options, "1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test_i(&Integer::from(u128::MAX), options, "1e128"); options.set_base(3); test_i(&Integer::from(u128::MAX), options, "2.022011021210021e80"); options.set_base(4); test_i(&Integer::from(u128::MAX), options, "1e64"); options.set_base(5); test_i(&Integer::from(u128::MAX), options, "1.103111044120131e55"); options.set_base(8); test_i(&Integer::from(u128::MAX), options, "4e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test_i(&Integer::from(u128::MAX), options, "1e+32"); options.set_base(32); test_i(&Integer::from(u128::MAX), options, "8e+25"); options.set_base(36); test_i(&Integer::from(u128::MAX), options, "f.5lxx1zz5pnorynqe+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test_i(&Integer::from(u128::MAX), options, "2.022011021210021e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test_i(&Integer::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQe+24"); options.set_lowercase(); options.set_e_uppercase(); test_i(&Integer::from(u128::MAX), options, "f.5lxx1zz5pnorynqE+24"); options.set_uppercase(); test_i(&Integer::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test_i( &Integer::from(u128::MAX), options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", ); options.set_base(3); test_i( &Integer::from(u128::MAX), options, "202201102121002021012000211012011021221022212021111001022110211020010021100121010", ); options.set_base(4); test_i( &Integer::from(u128::MAX), options, "3333333333333333333333333333333333333333333333333333333333333333", ); options.set_base(5); test_i( &Integer::from(u128::MAX), options, "11031110441201303134210404233413032443021130230130231310", ); options.set_base(8); test_i( &Integer::from(u128::MAX), options, "3777777777777777777777777777777777777777777", ); options.set_base(16); test_i( &Integer::from(u128::MAX), options, "ffffffffffffffffffffffffffffffff", ); options.set_base(32); test_i( &Integer::from(u128::MAX), options, "7vvvvvvvvvvvvvvvvvvvvvvvvv", ); options.set_base(36); test_i( &Integer::from(u128::MAX), options, "f5lxx1zz5pnorynqglhzmsp33", ); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test("0", options, "0.000"); test("1", options, "1.000"); test("10", options, "10.00"); test("100", options, "100.0"); test("1000", options, "1000"); test("10000", options, "1.000e4"); test("9", options, "9.000"); test("99", options, "99.00"); test("999", options, "999.0"); test("9999", options, "9999"); test("99999", options, "1.000e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test("0", options, "0.00"); test("1", options, "1.00"); test("10", options, "10.00"); test("100", options, "100.00"); test("1000", options, "1000.00"); test("10000", options, "10000.00"); test("9", options, "9.00"); test("99", options, "99.00"); test("999", options, "999.00"); test("9999", options, "9999.00"); test("99999", options, "99999.00"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test("123", options, "1.2e2"); options.set_rounding_mode(Down); test("123", options, "1.2e2"); options.set_rounding_mode(Floor); test("123", options, "1.2e2"); options.set_rounding_mode(Up); test("123", options, "1.3e2"); options.set_rounding_mode(Ceiling); test("123", options, "1.3e2"); options.set_rounding_mode(Nearest); test("135", options, "1.4e2"); options.set_rounding_mode(Down); test("135", options, "1.3e2"); options.set_rounding_mode(Floor); test("135", options, "1.3e2"); options.set_rounding_mode(Up); test("135", options, "1.4e2"); options.set_rounding_mode(Ceiling); test("135", options, "1.4e2"); options.set_rounding_mode(Exact); test("140", options, "1.4e2"); options.set_rounding_mode(Nearest); test("999", options, "1e3"); options.set_rounding_mode(Down); test("999", options, "9.9e2"); options.set_rounding_mode(Floor); test("999", options, "9.9e2"); options.set_rounding_mode(Up); test("999", options, "1e3"); options.set_rounding_mode(Ceiling); test("999", options, "1e3"); let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test_i(&Integer::from(i64::MAX), options, "9.223372036854776e18"); test_i(&Integer::from(i128::MAX), options, "1.701411834604692e38"); test("-1", options, "-1.000000000000000"); test("-10", options, "-10.00000000000000"); test("-100", options, "-100.0000000000000"); test("-1000", options, "-1000.000000000000"); test("-10000", options, "-10000.00000000000"); test("-100000", options, "-100000.0000000000"); test("-1000000", options, "-1000000.000000000"); test("-10000000", options, "-10000000.00000000"); test("-100000000", options, "-100000000.0000000"); test("-1000000000", options, "-1000000000.000000"); test("-10000000000", options, "-10000000000.00000"); test("-100000000000", options, "-100000000000.0000"); test("-1000000000000", options, "-1000000000000.000"); test("-10000000000000", options, "-10000000000000.00"); test("-100000000000000", options, "-100000000000000.0"); test("-1000000000000000", options, "-1000000000000000"); test("-10000000000000000", options, "-1.000000000000000e16"); test("-100000000000000000", options, "-1.000000000000000e17"); test_i(&Integer::from(i64::MIN), options, "-9.223372036854776e18"); test_i(&Integer::from(i128::MIN), options, "-1.701411834604692e38"); test("-999999999999999", options, "-999999999999999.0"); test("-9999999999999999", options, "-9999999999999999"); test("-99999999999999999", options, "-1.000000000000000e17"); test("-999999999999999999", options, "-1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test_i(&Integer::from(i128::MAX), options, "1e127"); test_i(&Integer::from(i128::MIN), options, "-1e127"); options.set_base(3); test_i(&Integer::from(i128::MAX), options, "1.01100201022001e80"); test_i(&Integer::from(i128::MIN), options, "-1.01100201022001e80"); options.set_base(4); test_i(&Integer::from(i128::MAX), options, "2e63"); test_i(&Integer::from(i128::MIN), options, "-2e63"); options.set_base(5); test_i(&Integer::from(i128::MAX), options, "3.013030220323124e54"); test_i(&Integer::from(i128::MIN), options, "-3.013030220323124e54"); options.set_base(8); test_i(&Integer::from(i128::MAX), options, "2e42"); test_i(&Integer::from(i128::MIN), options, "-2e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test_i(&Integer::from(i128::MAX), options, "8e+31"); test_i(&Integer::from(i128::MIN), options, "-8e+31"); options.set_base(32); test_i(&Integer::from(i128::MAX), options, "4e+25"); test_i(&Integer::from(i128::MIN), options, "-4e+25"); options.set_base(36); test_i(&Integer::from(i128::MAX), options, "7.ksyyizzkutudzbve+24"); test_i(&Integer::from(i128::MIN), options, "-7.ksyyizzkutudzbve+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test_i(&Integer::from(i128::MAX), options, "1.01100201022001e+80"); test_i(&Integer::from(i128::MIN), options, "-1.01100201022001e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test_i(&Integer::from(i128::MAX), options, "7.KSYYIZZKUTUDZBVe+24"); test_i(&Integer::from(i128::MIN), options, "-7.KSYYIZZKUTUDZBVe+24"); options.set_lowercase(); options.set_e_uppercase(); test_i(&Integer::from(i128::MAX), options, "7.ksyyizzkutudzbvE+24"); test_i(&Integer::from(i128::MIN), options, "-7.ksyyizzkutudzbvE+24"); options.set_uppercase(); test_i(&Integer::from(i128::MAX), options, "7.KSYYIZZKUTUDZBVE+24"); test_i(&Integer::from(i128::MIN), options, "-7.KSYYIZZKUTUDZBVE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test_i( &Integer::from(i128::MAX), options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", ); test_i( &Integer::from(i128::MIN), options, "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", ); options.set_base(3); test_i( &Integer::from(i128::MAX), options, "101100201022001010121000102002120122110122221010202000122201220121120010200022001", ); test_i( &Integer::from(i128::MIN), options, "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", ); options.set_base(4); test_i( &Integer::from(i128::MAX), options, "1333333333333333333333333333333333333333333333333333333333333333", ); test_i( &Integer::from(i128::MIN), options, "-2000000000000000000000000000000000000000000000000000000000000000", ); options.set_base(5); test_i( &Integer::from(i128::MAX), options, "3013030220323124042102424341431241221233040112312340402", ); test_i( &Integer::from(i128::MIN), options, "-3013030220323124042102424341431241221233040112312340403", ); options.set_base(8); test_i( &Integer::from(i128::MAX), options, "1777777777777777777777777777777777777777777", ); test_i( &Integer::from(i128::MIN), options, "-2000000000000000000000000000000000000000000", ); options.set_base(16); test_i( &Integer::from(i128::MAX), options, "7fffffffffffffffffffffffffffffff", ); test_i( &Integer::from(i128::MIN), options, "-80000000000000000000000000000000", ); options.set_base(32); test_i( &Integer::from(i128::MAX), options, "3vvvvvvvvvvvvvvvvvvvvvvvvv", ); test_i( &Integer::from(i128::MIN), options, "-40000000000000000000000000", ); options.set_base(36); test_i( &Integer::from(i128::MAX), options, "7ksyyizzkutudzbv8aqztecjj", ); test_i( &Integer::from(i128::MIN), options, "-7ksyyizzkutudzbv8aqztecjk", ); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test("-1", options, "-1.000"); test("-10", options, "-10.00"); test("-100", options, "-100.0"); test("-1000", options, "-1000"); test("-10000", options, "-1.000e4"); test("-9", options, "-9.000"); test("-99", options, "-99.00"); test("-999", options, "-999.0"); test("-9999", options, "-9999"); test("-99999", options, "-1.000e5"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test("-1", options, "-1"); test("-10", options, "-1e1"); test("-100", options, "-1e2"); test("-1000", options, "-1e3"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-1e2"); test("-999", options, "-1e3"); test("-9999", options, "-1e4"); test("-99999", options, "-1e5"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-1e1"); test("-100", options, "-1e2"); test("-1000", options, "-1e3"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-1e2"); test("-999", options, "-1e3"); test("-9999", options, "-1e4"); test("-99999", options, "-1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test("-1", options, "-1.00"); test("-10", options, "-10.00"); test("-100", options, "-100.00"); test("-1000", options, "-1000.00"); test("-10000", options, "-10000.00"); test("-9", options, "-9.00"); test("-99", options, "-99.00"); test("-999", options, "-999.00"); test("-9999", options, "-9999.00"); test("-99999", options, "-99999.00"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test("-123", options, "-1.2e2"); options.set_rounding_mode(Down); test("-123", options, "-1.2e2"); options.set_rounding_mode(Floor); test("-123", options, "-1.3e2"); options.set_rounding_mode(Up); test("-123", options, "-1.3e2"); options.set_rounding_mode(Ceiling); test("-123", options, "-1.2e2"); options.set_rounding_mode(Nearest); test("-135", options, "-1.4e2"); options.set_rounding_mode(Down); test("-135", options, "-1.3e2"); options.set_rounding_mode(Floor); test("-135", options, "-1.4e2"); options.set_rounding_mode(Up); test("-135", options, "-1.4e2"); options.set_rounding_mode(Ceiling); test("-135", options, "-1.3e2"); options.set_rounding_mode(Exact); test("-140", options, "-1.4e2"); options.set_rounding_mode(Nearest); test("-999", options, "-1e3"); options.set_rounding_mode(Down); test("-999", options, "-9.9e2"); options.set_rounding_mode(Floor); test("-999", options, "-1e3"); options.set_rounding_mode(Up); test("-999", options, "-1e3"); options.set_rounding_mode(Ceiling); test("-999", options, "-9.9e2"); } #[should_panic] #[test] pub fn to_sci_with_options_fail() { let mut options = ToSciOptions::default(); options.set_rounding_mode(Exact); options.set_precision(2); Integer::from(123).to_sci_with_options(options).to_string(); } #[test] fn to_sci_properties() { let mut powers_of_10 = HashMap::new(); const TEN: Integer = Integer::const_from_unsigned(10); const U_TEN: Natural = Natural::const_from(10); let default_p = 16; integer_gen().test_properties(|x| { assert!(x.fmt_sci_valid(ToSciOptions::default())); let s = x.to_sci().to_string(); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), s ); assert!(string_is_subset(&s, DECIMAL_SCI_STRING_CHARS)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains('E')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); assert!(!s.contains("e-")); let x_from = Integer::from_sci_string(&s).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let log = x.unsigned_abs_ref().floor_log_base(&U_TEN); if log < default_p { assert_eq!(x_from, x); } else { let pow = powers_of_10 .entry(log - default_p + 1) .or_insert_with_key(|&p| (&TEN).pow(p)); assert_eq!(x.round_to_multiple(&*pow, Nearest).0, x_from); } } }); signed_gen::().test_properties(|x| { assert_eq!( x.to_sci().to_string(), Integer::from(x).to_sci().to_string() ); }); } #[test] fn to_sci_with_options_properties() { let mut powers = HashMap::new(); let mut chars = HashMap::new(); integer_to_sci_options_pair_gen_var_1().test_properties(|(x, options)| { assert!(x.fmt_sci_valid(options)); let s = x.to_sci_with_options(options).to_string(); let cs: &mut String = chars.entry(options.get_base()).or_insert_with_key(|&base| { let mut cs = "+-.0123456789".to_string(); if base > 10 { let limit = usize::from(base - 10); for c in ('a'..='z').take(limit) { cs.push(c); } for c in ('A'..='Z').take(limit) { cs.push(c); } } if base < 15 { cs.push('e'); cs.push('E'); } cs }); assert!(string_is_subset(&s, cs)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); assert!(!s.contains("e-")); assert!(!s.contains("E-")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 1); assert!(s.chars().filter(|&c| c == '+').count() <= 1); let mut from_options = FromSciStringOptions::default(); from_options.set_base(options.get_base()); let x_from = Integer::from_sci_string_with_options(&s, from_options).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let base = Integer::from(options.get_base()); let u_base = Natural::from(options.get_base()); let scale = match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => None, SciSizeOptions::Precision(p) => { let log = x.unsigned_abs_ref().floor_log_base(&u_base); if log >= p { Some(log - p + 1) } else { None } } }; if let Some(scale) = scale { let pow = powers .entry((base.clone(), scale)) .or_insert_with(|| base.pow(scale)); assert_eq!( x.round_to_multiple(&*pow, options.get_rounding_mode()).0, x_from ); } else { assert_eq!(x_from, x); } } }); signed_to_sci_options_pair_gen_var_1::().test_properties(|(x, options)| { assert_eq!( x.to_sci_with_options(options).to_string(), Integer::from(x).to_sci_with_options(options).to_string() ); }); } ================================================ FILE: malachite-nz/tests/integer/conversion/string/to_string.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::arithmetic::traits::SaturatingSubAssign; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::conversion::string::to_string::BaseFmtWrapper as BaseBaseFmtWrapper; use malachite_base::num::conversion::traits::{FromStringBase, ToStringBase}; use malachite_base::strings::{ ToBinaryString, ToDebugString, ToLowerHexString, ToOctalString, ToUpperHexString, string_is_subset, }; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_2, signed_unsigned_pair_gen_var_5, signed_unsigned_pair_gen_var_7, signed_unsigned_unsigned_triple_gen_var_3, unsigned_gen_var_8, unsigned_pair_gen_var_9, }; use malachite_nz::integer::Integer; use malachite_nz::natural::conversion::string::to_string::BaseFmtWrapper; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_gen, integer_unsigned_pair_gen_var_1, integer_unsigned_pair_gen_var_2, integer_unsigned_unsigned_triple_gen_var_1, }; use num::BigInt; use std::cmp::max; use std::panic::catch_unwind; use std::str::FromStr; fn test_padding(mut s: &str, mut s_padded: &str, mut width: usize) { assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); let negative = s.starts_with('-'); assert_eq!(s_padded.starts_with('-'), negative); if negative { s = &s[1..]; s_padded = &s_padded[1..]; width.saturating_sub_assign(1); } assert!(s_padded.ends_with(&s)); assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); if s.len() < width { let diff = s_padded.len() - s.len(); assert!(s_padded[..diff].chars().all(|c| c == '0')); assert_eq!(&s_padded[diff..], s); } } #[test] pub fn test_to_string() { fn test(u: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_string(), u); assert_eq!(x.to_debug_string(), u); assert_eq!(format!("{x:00}"), u); assert_eq!(format!("{x:00?}"), u); } test("0"); test("2"); test("123"); test("1000"); test("1000000"); test("1000000000000000"); test("-2"); test("-123"); test("-1000"); test("-1000000"); test("-1000000000000000"); fn test_width(u: &str, width: usize, out: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_string(); assert_eq!(format!("{x:0width$}"), out); assert_eq!(format!("{x:0width$?}"), out); test_padding(&s, out, width); } test_width("0", 0, "0"); test_width("0", 1, "0"); test_width("0", 2, "00"); test_width("0", 5, "00000"); test_width("1000000", 0, "1000000"); test_width("1000000", 1, "1000000"); test_width("1000000", 2, "1000000"); test_width("1000000", 3, "1000000"); test_width("1000000", 4, "1000000"); test_width("1000000", 5, "1000000"); test_width("1000000", 6, "1000000"); test_width("1000000", 7, "1000000"); test_width("1000000", 8, "01000000"); test_width("1000000", 10, "0001000000"); test_width("1000000000000000", 0, "1000000000000000"); test_width("1000000000000000", 1, "1000000000000000"); test_width("1000000000000000", 16, "1000000000000000"); test_width("1000000000000000", 20, "00001000000000000000"); test_width("-1000000", 0, "-1000000"); test_width("-1000000", 1, "-1000000"); test_width("-1000000", 2, "-1000000"); test_width("-1000000", 3, "-1000000"); test_width("-1000000", 4, "-1000000"); test_width("-1000000", 5, "-1000000"); test_width("-1000000", 6, "-1000000"); test_width("-1000000", 7, "-1000000"); test_width("-1000000", 8, "-1000000"); test_width("-1000000", 9, "-01000000"); test_width("-1000000", 10, "-001000000"); test_width("-1000000000000000", 0, "-1000000000000000"); test_width("-1000000000000000", 1, "-1000000000000000"); test_width("-1000000000000000", 16, "-1000000000000000"); test_width("-1000000000000000", 20, "-0001000000000000000"); } #[test] fn to_string_properties() { integer_gen().test_properties(|x| { let s = x.to_string(); assert_eq!(x.to_debug_string(), s); assert_eq!(x.to_string_base(10), s); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(BigInt::from(&x).to_string(), s); assert_eq!(rug::Integer::from(&x).to_string(), s); assert!(string_is_subset(&s, "-0123456789")); if x != 0 { assert!(!s.starts_with('0')); } }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { let s = x.to_string(); let s_padded = format!("{x:0width$}"); test_padding(&s, &s_padded, width); assert_eq!(format!("{x:0width$?}"), s_padded); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 10), width = width), s_padded ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(&x, 10), width = width), s_padded ); assert_eq!( format!("{:0width$}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$}", rug::Integer::from(&x), width = width), s_padded ); }); signed_gen::().test_properties(|x| { assert_eq!(Integer::from(x).to_string(), x.to_string()); }); signed_unsigned_pair_gen_var_5::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", Integer::from(x), width = width), format!("{x:0width$}") ); }); } #[test] pub fn test_to_binary_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_binary_string(), out); assert_eq!(format!("{x:00b}"), out); assert_eq!(format!("{x:#b}"), out_prefixed); } test("0", "0", "0b0"); test("2", "10", "0b10"); test("123", "1111011", "0b1111011"); test("1000", "1111101000", "0b1111101000"); test("1000000", "11110100001001000000", "0b11110100001001000000"); test( "1000000000000000", "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test("-2", "-10", "-0b10"); test("-123", "-1111011", "-0b1111011"); test("-1000", "-1111101000", "-0b1111101000"); test( "-1000000", "-11110100001001000000", "-0b11110100001001000000", ); test( "-1000000000000000", "-11100011010111111010100100110001101000000000000000", "-0b11100011010111111010100100110001101000000000000000", ); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_binary_string(); assert_eq!(format!("{x:0width$b}"), out); assert_eq!(format!("{x:#0width$b}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0b0"); test_width("0", 1, "0", "0b0"); test_width("0", 2, "00", "0b0"); test_width("0", 5, "00000", "0b000"); test_width("1000", 0, "1111101000", "0b1111101000"); test_width("1000", 1, "1111101000", "0b1111101000"); test_width("1000", 10, "1111101000", "0b1111101000"); test_width("1000", 12, "001111101000", "0b1111101000"); test_width("1000", 14, "00001111101000", "0b001111101000"); test_width( "1000000000000000", 0, "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 1, "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 52, "0011100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 54, "000011100011010111111010100100110001101000000000000000", "0b0011100011010111111010100100110001101000000000000000", ); test_width("-1000", 0, "-1111101000", "-0b1111101000"); test_width("-1000", 1, "-1111101000", "-0b1111101000"); test_width("-1000", 10, "-1111101000", "-0b1111101000"); test_width("-1000", 13, "-001111101000", "-0b1111101000"); test_width("-1000", 15, "-00001111101000", "-0b001111101000"); test_width( "-1000000000000000", 0, "-11100011010111111010100100110001101000000000000000", "-0b11100011010111111010100100110001101000000000000000", ); test_width( "-1000000000000000", 1, "-11100011010111111010100100110001101000000000000000", "-0b11100011010111111010100100110001101000000000000000", ); test_width( "-1000000000000000", 53, "-0011100011010111111010100100110001101000000000000000", "-0b11100011010111111010100100110001101000000000000000", ); test_width( "-1000000000000000", 55, "-000011100011010111111010100100110001101000000000000000", "-0b0011100011010111111010100100110001101000000000000000", ); } #[test] fn to_binary_string_properties() { integer_gen().test_properties(|x| { let s = x.to_binary_string(); let prefixed_s = if x < 0 { "-0b".to_owned() + &s[1..] } else { "0b".to_owned() + &s }; assert_eq!(format!("{x:#b}"), prefixed_s); assert_eq!(format!("{x:00b}"), s); assert_eq!(format!("{x:#00b}"), prefixed_s); assert_eq!(x.to_string_base(2), s); let num_x = BigInt::from(&x); assert_eq!(num_x.to_binary_string(), s); assert_eq!(format!("{num_x:#b}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_binary_string(), s); assert_eq!(format!("{rug_x:#b}"), prefixed_s); assert!(string_is_subset(&s, "-01")); if x != 0 { assert!(!s.starts_with('0')); } }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { let s = x.to_binary_string(); let s_padded = format!("{x:0width$b}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$b}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$b}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$b}"); assert_eq!( format!("{:#0width$b}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$b}", rug::Integer::from(&x), width = width), s_padded ); }); signed_gen_var_2::().test_properties(|x| { assert_eq!(Integer::from(x).to_binary_string(), x.to_binary_string()); assert_eq!(format!("{:#b}", Integer::from(x)), format!("{x:#b}")); }); signed_unsigned_pair_gen_var_7::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$b}", Integer::from(x), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$b}", Integer::from(x), width = width), format!("{x:#0width$b}") ); }); } #[test] pub fn test_to_octal_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_octal_string(), out); assert_eq!(format!("{x:00o}"), out); assert_eq!(format!("{x:#o}"), out_prefixed); } test("0", "0", "0o0"); test("2", "2", "0o2"); test("123", "173", "0o173"); test("1000", "1750", "0o1750"); test("1000000", "3641100", "0o3641100"); test( "1000000000000000", "34327724461500000", "0o34327724461500000", ); test("-2", "-2", "-0o2"); test("-123", "-173", "-0o173"); test("-1000", "-1750", "-0o1750"); test("-1000000", "-3641100", "-0o3641100"); test( "-1000000000000000", "-34327724461500000", "-0o34327724461500000", ); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_octal_string(); assert_eq!(format!("{x:0width$o}"), out); assert_eq!(format!("{x:#0width$o}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0o0"); test_width("0", 1, "0", "0o0"); test_width("0", 2, "00", "0o0"); test_width("0", 3, "000", "0o0"); test_width("0", 4, "0000", "0o00"); test_width("0", 5, "00000", "0o000"); test_width("1000", 0, "1750", "0o1750"); test_width("1000", 1, "1750", "0o1750"); test_width("1000", 4, "1750", "0o1750"); test_width("1000", 6, "001750", "0o1750"); test_width("1000", 8, "00001750", "0o001750"); test_width( "1000000000000000", 0, "34327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 1, "34327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 19, "0034327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 21, "000034327724461500000", "0o0034327724461500000", ); test_width("-1000", 0, "-1750", "-0o1750"); test_width("-1000", 1, "-1750", "-0o1750"); test_width("-1000", 4, "-1750", "-0o1750"); test_width("-1000", 7, "-001750", "-0o1750"); test_width("-1000", 9, "-00001750", "-0o001750"); test_width( "-1000000000000000", 0, "-34327724461500000", "-0o34327724461500000", ); test_width( "-1000000000000000", 1, "-34327724461500000", "-0o34327724461500000", ); test_width( "-1000000000000000", 20, "-0034327724461500000", "-0o34327724461500000", ); test_width( "-1000000000000000", 22, "-000034327724461500000", "-0o0034327724461500000", ); } #[test] fn to_octal_string_properties() { integer_gen().test_properties(|x| { let s = x.to_octal_string(); let prefixed_s = if x < 0 { "-0o".to_owned() + &s[1..] } else { "0o".to_owned() + &s }; assert_eq!(format!("{x:#o}"), prefixed_s); assert_eq!(format!("{x:00o}"), s); assert_eq!(format!("{x:#00o}"), prefixed_s); assert_eq!(x.to_string_base(8), s); let num_x = BigInt::from(&x); assert_eq!(num_x.to_octal_string(), s); assert_eq!(format!("{num_x:#o}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_octal_string(), s); assert_eq!(format!("{rug_x:#o}"), prefixed_s); assert!(string_is_subset(&s, "-01234567")); if x != 0 { assert!(!s.starts_with('0')); } }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { let s = x.to_octal_string(); let s_padded = format!("{x:0width$o}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$o}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$o}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$o}"); assert_eq!( format!("{:#0width$o}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$o}", rug::Integer::from(&x), width = width), s_padded ); }); signed_gen_var_2::().test_properties(|x| { assert_eq!(Integer::from(x).to_octal_string(), x.to_octal_string()); assert_eq!(format!("{:#o}", Integer::from(x)), format!("{x:#o}")); }); signed_unsigned_pair_gen_var_7::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$o}", Integer::from(x), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$o}", Integer::from(x), width = width), format!("{x:#0width$o}") ); }); } #[test] pub fn test_to_lower_hex_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_lower_hex_string(), out); assert_eq!(format!("{x:00x}"), out); assert_eq!(format!("{x:#x}"), out_prefixed); } test("0", "0", "0x0"); test("2", "2", "0x2"); test("123", "7b", "0x7b"); test("1000", "3e8", "0x3e8"); test("1000000", "f4240", "0xf4240"); test("1000000000000000", "38d7ea4c68000", "0x38d7ea4c68000"); test("-2", "-2", "-0x2"); test("-123", "-7b", "-0x7b"); test("-1000", "-3e8", "-0x3e8"); test("-1000000", "-f4240", "-0xf4240"); test("-1000000000000000", "-38d7ea4c68000", "-0x38d7ea4c68000"); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_lower_hex_string(); assert_eq!(format!("{x:0width$x}"), out); assert_eq!(format!("{x:#0width$x}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0x0"); test_width("0", 1, "0", "0x0"); test_width("0", 2, "00", "0x0"); test_width("0", 3, "000", "0x0"); test_width("0", 4, "0000", "0x00"); test_width("0", 5, "00000", "0x000"); test_width("1000", 0, "3e8", "0x3e8"); test_width("1000", 1, "3e8", "0x3e8"); test_width("1000", 3, "3e8", "0x3e8"); test_width("1000", 5, "003e8", "0x3e8"); test_width("1000", 7, "00003e8", "0x003e8"); test_width("1000000000000000", 0, "38d7ea4c68000", "0x38d7ea4c68000"); test_width("1000000000000000", 1, "38d7ea4c68000", "0x38d7ea4c68000"); test_width("1000000000000000", 15, "0038d7ea4c68000", "0x38d7ea4c68000"); test_width( "1000000000000000", 17, "000038d7ea4c68000", "0x0038d7ea4c68000", ); test_width("-1000", 0, "-3e8", "-0x3e8"); test_width("-1000", 1, "-3e8", "-0x3e8"); test_width("-1000", 3, "-3e8", "-0x3e8"); test_width("-1000", 6, "-003e8", "-0x3e8"); test_width("-1000", 8, "-00003e8", "-0x003e8"); test_width("-1000000000000000", 0, "-38d7ea4c68000", "-0x38d7ea4c68000"); test_width("-1000000000000000", 1, "-38d7ea4c68000", "-0x38d7ea4c68000"); test_width( "-1000000000000000", 16, "-0038d7ea4c68000", "-0x38d7ea4c68000", ); test_width( "-1000000000000000", 18, "-000038d7ea4c68000", "-0x0038d7ea4c68000", ); } #[test] pub fn test_to_upper_hex_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_upper_hex_string(), out); assert_eq!(format!("{x:00X}"), out); assert_eq!(format!("{x:#X}"), out_prefixed); } test("0", "0", "0x0"); test("2", "2", "0x2"); test("123", "7B", "0x7B"); test("1000", "3E8", "0x3E8"); test("1000000", "F4240", "0xF4240"); test("1000000000000000", "38D7EA4C68000", "0x38D7EA4C68000"); test("-2", "-2", "-0x2"); test("-123", "-7B", "-0x7B"); test("-1000", "-3E8", "-0x3E8"); test("-1000000", "-F4240", "-0xF4240"); test("-1000000000000000", "-38D7EA4C68000", "-0x38D7EA4C68000"); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_upper_hex_string(); assert_eq!(format!("{x:0width$X}"), out); assert_eq!(format!("{x:#0width$X}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0x0"); test_width("0", 1, "0", "0x0"); test_width("0", 2, "00", "0x0"); test_width("0", 3, "000", "0x0"); test_width("0", 4, "0000", "0x00"); test_width("0", 5, "00000", "0x000"); test_width("1000", 0, "3E8", "0x3E8"); test_width("1000", 1, "3E8", "0x3E8"); test_width("1000", 3, "3E8", "0x3E8"); test_width("1000", 5, "003E8", "0x3E8"); test_width("1000", 7, "00003E8", "0x003E8"); test_width("1000000000000000", 0, "38D7EA4C68000", "0x38D7EA4C68000"); test_width("1000000000000000", 1, "38D7EA4C68000", "0x38D7EA4C68000"); test_width("1000000000000000", 15, "0038D7EA4C68000", "0x38D7EA4C68000"); test_width( "1000000000000000", 17, "000038D7EA4C68000", "0x0038D7EA4C68000", ); test_width("-1000", 0, "-3E8", "-0x3E8"); test_width("-1000", 1, "-3E8", "-0x3E8"); test_width("-1000", 3, "-3E8", "-0x3E8"); test_width("-1000", 6, "-003E8", "-0x3E8"); test_width("-1000", 8, "-00003E8", "-0x003E8"); test_width("-1000000000000000", 0, "-38D7EA4C68000", "-0x38D7EA4C68000"); test_width("-1000000000000000", 1, "-38D7EA4C68000", "-0x38D7EA4C68000"); test_width( "-1000000000000000", 16, "-0038D7EA4C68000", "-0x38D7EA4C68000", ); test_width( "-1000000000000000", 18, "-000038D7EA4C68000", "-0x0038D7EA4C68000", ); } #[test] fn to_hex_string_properties() { integer_gen().test_properties(|x| { let s = x.to_lower_hex_string(); let prefixed_s = if x < 0 { "-0x".to_owned() + &s[1..] } else { "0x".to_owned() + &s }; assert_eq!(format!("{x:#x}"), prefixed_s); assert_eq!(x.to_upper_hex_string(), s.to_ascii_uppercase()); assert_eq!( format!("{x:#X}"), if x < 0 { "-0x".to_owned() + &s[1..].to_ascii_uppercase() } else { "0x".to_owned() + &s.to_ascii_uppercase() } ); assert_eq!(format!("{x:00x}"), s); assert_eq!(format!("{x:#00x}"), prefixed_s); assert_eq!(format!("{x:00X}"), s.to_ascii_uppercase()); assert_eq!( format!("{x:#00X}"), if x < 0 { "-0x".to_owned() + &s[1..].to_ascii_uppercase() } else { "0x".to_owned() + &s.to_ascii_uppercase() } ); assert_eq!(x.to_string_base(16), s); let num_x = BigInt::from(&x); assert_eq!(num_x.to_lower_hex_string(), s); assert_eq!(format!("{num_x:#x}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_lower_hex_string(), s); assert_eq!(format!("{rug_x:#x}"), prefixed_s); assert!(string_is_subset(&s, "-0123456789abcdef")); if x != 0 { assert!(!s.starts_with('0')); } }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { let s = x.to_lower_hex_string(); let s_padded = format!("{x:0width$x}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$x}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$x}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$x}"); assert_eq!( format!("{:#0width$x}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$x}", rug::Integer::from(&x), width = width), s_padded ); let s = x.to_upper_hex_string(); let s_padded_upper = format!("{x:0width$X}"); assert_eq!(s_padded_upper, format!("{x:0width$x}").to_ascii_uppercase()); let s_padded = s_padded_upper; test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$X}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$X}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$X}"); assert_eq!( format!("{:#0width$X}", BigInt::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$X}", rug::Integer::from(&x), width = width), s_padded ); }); signed_gen_var_2::().test_properties(|x| { assert_eq!( Integer::from(x).to_lower_hex_string(), x.to_lower_hex_string() ); assert_eq!( Integer::from(x).to_upper_hex_string(), x.to_upper_hex_string() ); assert_eq!(format!("{:#x}", Integer::from(x)), format!("{x:#x}")); assert_eq!(format!("{:#X}", Integer::from(x)), format!("{x:#X}")); }); signed_unsigned_pair_gen_var_7::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$x}", Integer::from(x), width = width), format!("{x:0width$x}") ); assert_eq!( format!("{:0width$X}", Integer::from(x), width = width), format!("{x:0width$X}") ); assert_eq!( format!("{:#0width$x}", Integer::from(x), width = width), format!("{x:#0width$x}") ); assert_eq!( format!("{:#0width$X}", Integer::from(x), width = width), format!("{x:#0width$X}") ); }); } #[test] pub fn test_to_string_base() { fn test(u: &str, base: u8, out: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_string_base(base), out); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, base)), out); } test("0", 2, "0"); test("0", 3, "0"); test("0", 10, "0"); test("0", 16, "0"); test("0", 17, "0"); test("2", 3, "2"); test("2", 10, "2"); test("2", 16, "2"); test("2", 17, "2"); test("123", 8, "173"); test("1000000", 10, "1000000"); test("1000000", 20, "65000"); test("1000000", 36, "lfls"); test("1000", 2, "1111101000"); test("1000", 3, "1101001"); test("1000", 4, "33220"); test("1000", 10, "1000"); test("1000", 20, "2a0"); test("1000", 36, "rs"); test( "1000000000000000", 2, "11100011010111111010100100110001101000000000000000", ); test("1000000000000000", 3, "11212010201001210101011021212001"); test("1000000000000000", 4, "3203113322210301220000000"); test("1000000000000000", 10, "1000000000000000"); test("1000000000000000", 20, "4hd2a0000000"); test("1000000000000000", 36, "9ugxnorjls"); test("-2", 3, "-2"); test("-2", 10, "-2"); test("-2", 16, "-2"); test("-2", 17, "-2"); test("-123", 8, "-173"); test("-1000000", 10, "-1000000"); test("-1000000", 20, "-65000"); test("-1000000", 36, "-lfls"); test("-1000", 2, "-1111101000"); test("-1000", 3, "-1101001"); test("-1000", 4, "-33220"); test("-1000", 10, "-1000"); test("-1000", 20, "-2a0"); test("-1000", 36, "-rs"); test( "-1000000000000000", 2, "-11100011010111111010100100110001101000000000000000", ); test("-1000000000000000", 3, "-11212010201001210101011021212001"); test("-1000000000000000", 4, "-3203113322210301220000000"); test("-1000000000000000", 10, "-1000000000000000"); test("-1000000000000000", 20, "-4hd2a0000000"); test("-1000000000000000", 36, "-9ugxnorjls"); fn test_width(u: &str, base: u8, width: usize, out: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_string_base(base); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, base), width = width), out ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(&x, base), width = width), out ); test_padding(&s, out, width); } test_width("0", 2, 0, "0"); test_width("0", 2, 1, "0"); test_width("0", 2, 2, "00"); test_width("0", 2, 5, "00000"); test_width("1000000", 36, 0, "lfls"); test_width("1000000", 36, 1, "lfls"); test_width("1000000", 36, 2, "lfls"); test_width("1000000", 36, 3, "lfls"); test_width("1000000", 36, 4, "lfls"); test_width("1000000", 36, 5, "0lfls"); test_width("1000000", 36, 6, "00lfls"); test_width("1000000000000000", 36, 0, "9ugxnorjls"); test_width("1000000000000000", 36, 1, "9ugxnorjls"); test_width("1000000000000000", 36, 10, "9ugxnorjls"); test_width("1000000000000000", 36, 11, "09ugxnorjls"); test_width("1000000000000000", 36, 20, "00000000009ugxnorjls"); test_width("-1000000", 36, 0, "-lfls"); test_width("-1000000", 36, 1, "-lfls"); test_width("-1000000", 36, 2, "-lfls"); test_width("-1000000", 36, 3, "-lfls"); test_width("-1000000", 36, 4, "-lfls"); test_width("-1000000", 36, 5, "-lfls"); test_width("-1000000", 36, 6, "-0lfls"); test_width("-1000000", 36, 7, "-00lfls"); test_width("-1000000000000000", 36, 0, "-9ugxnorjls"); test_width("-1000000000000000", 36, 1, "-9ugxnorjls"); test_width("-1000000000000000", 36, 10, "-9ugxnorjls"); test_width("-1000000000000000", 36, 11, "-9ugxnorjls"); test_width("-1000000000000000", 36, 12, "-09ugxnorjls"); test_width("-1000000000000000", 36, 21, "-00000000009ugxnorjls"); } #[test] fn to_string_base_fail() { assert_panic!(Integer::from(10).to_string_base(0)); assert_panic!(Integer::from(10).to_string_base(1)); assert_panic!(Integer::from(10).to_string_base(37)); assert_panic!(Integer::from(10).to_string_base(100)); assert_panic!(format!("{}", BaseFmtWrapper::new(&Integer::from(10), 0))); assert_panic!(format!("{}", BaseFmtWrapper::new(&Integer::from(10), 1))); assert_panic!(format!("{}", BaseFmtWrapper::new(&Integer::from(10), 37))); assert_panic!(format!("{}", BaseFmtWrapper::new(&Integer::from(10), 100))); } #[test] fn to_string_base_properties() { integer_unsigned_pair_gen_var_1().test_properties(|(x, base)| { let s = x.to_string_base(base); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(x.to_string_base_upper(base), s.to_uppercase()); assert_eq!(Integer::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s, "-0123456789abcdefghijklmnopqrstuvwxyz" )); if x != 0 { assert!(!s.starts_with('0')); } }); integer_gen().test_properties(|x| { assert_eq!(x.to_string_base(10), x.to_string()); assert_eq!(x.to_string_base(2), x.to_binary_string()); assert_eq!(x.to_string_base(8), x.to_octal_string()); assert_eq!(x.to_string_base(16), x.to_lower_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(Integer::ZERO.to_string_base(base), "0"); assert_eq!(Integer::ONE.to_string_base(base), "1"); assert_eq!(Integer::NEGATIVE_ONE.to_string_base(base), "-1"); assert_eq!(Integer::from(base).to_string_base(base), "10"); }); integer_unsigned_unsigned_triple_gen_var_1().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(&x, base); let s = x.to_string_base(base); let s_padded = format!("{fx:0width$}"); assert_eq!(format!("{fx:0width$?}"), s_padded); assert_eq!(Integer::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "-0123456789abcdefghijklmnopqrstuvwxyz" )); test_padding(&s, &s_padded, width); }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 16), width = width), format!("{x:0width$x}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:0width$}", BaseFmtWrapper::new(&Integer::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); signed_unsigned_unsigned_triple_gen_var_3::().test_properties( |(x, base, width)| { assert_eq!( format!( "{:0width$}", BaseFmtWrapper::new(&Integer::from(x), base), width = width ), format!( "{:0width$}", BaseBaseFmtWrapper::new(x, base), width = width ), ); }, ); } #[test] pub fn test_to_string_base_upper() { fn test(u: &str, base: u8, out: &str) { let x = Integer::from_str(u).unwrap(); assert_eq!(x.to_string_base_upper(base), out); assert_eq!(format!("{:#}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#00}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#00?}", BaseFmtWrapper::new(&x, base)), out); } test("0", 2, "0"); test("0", 3, "0"); test("0", 10, "0"); test("0", 16, "0"); test("0", 17, "0"); test("2", 3, "2"); test("2", 10, "2"); test("2", 16, "2"); test("2", 17, "2"); test("123", 8, "173"); test("1000000", 10, "1000000"); test("1000000", 20, "65000"); test("1000000", 36, "LFLS"); test("1000", 2, "1111101000"); test("1000", 3, "1101001"); test("1000", 4, "33220"); test("1000", 10, "1000"); test("1000", 20, "2A0"); test("1000", 36, "RS"); test( "1000000000000000", 2, "11100011010111111010100100110001101000000000000000", ); test("1000000000000000", 3, "11212010201001210101011021212001"); test("1000000000000000", 4, "3203113322210301220000000"); test("1000000000000000", 10, "1000000000000000"); test("1000000000000000", 20, "4HD2A0000000"); test("1000000000000000", 36, "9UGXNORJLS"); test("-2", 3, "-2"); test("-2", 10, "-2"); test("-2", 16, "-2"); test("-2", 17, "-2"); test("-123", 8, "-173"); test("-1000000", 10, "-1000000"); test("-1000000", 20, "-65000"); test("-1000000", 36, "-LFLS"); test("-1000", 2, "-1111101000"); test("-1000", 3, "-1101001"); test("-1000", 4, "-33220"); test("-1000", 10, "-1000"); test("-1000", 20, "-2A0"); test("-1000", 36, "-RS"); test( "-1000000000000000", 2, "-11100011010111111010100100110001101000000000000000", ); test("-1000000000000000", 3, "-11212010201001210101011021212001"); test("-1000000000000000", 4, "-3203113322210301220000000"); test("-1000000000000000", 10, "-1000000000000000"); test("-1000000000000000", 20, "-4HD2A0000000"); test("-1000000000000000", 36, "-9UGXNORJLS"); fn test_width(u: &str, base: u8, width: usize, out: &str) { let x = Integer::from_str(u).unwrap(); let s = x.to_string_base_upper(base); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, base), width = width), out ); assert_eq!( format!("{:#0width$?}", BaseFmtWrapper::new(&x, base), width = width), out ); test_padding(&s, out, width); } test_width("0", 2, 0, "0"); test_width("0", 2, 1, "0"); test_width("0", 2, 2, "00"); test_width("0", 2, 5, "00000"); test_width("1000000", 36, 0, "LFLS"); test_width("1000000", 36, 1, "LFLS"); test_width("1000000", 36, 2, "LFLS"); test_width("1000000", 36, 3, "LFLS"); test_width("1000000", 36, 4, "LFLS"); test_width("1000000", 36, 5, "0LFLS"); test_width("1000000", 36, 6, "00LFLS"); test_width("1000000000000000", 36, 0, "9UGXNORJLS"); test_width("1000000000000000", 36, 1, "9UGXNORJLS"); test_width("1000000000000000", 36, 10, "9UGXNORJLS"); test_width("1000000000000000", 36, 11, "09UGXNORJLS"); test_width("1000000000000000", 36, 20, "00000000009UGXNORJLS"); test_width("-1000000", 36, 0, "-LFLS"); test_width("-1000000", 36, 1, "-LFLS"); test_width("-1000000", 36, 2, "-LFLS"); test_width("-1000000", 36, 3, "-LFLS"); test_width("-1000000", 36, 4, "-LFLS"); test_width("-1000000", 36, 5, "-LFLS"); test_width("-1000000", 36, 6, "-0LFLS"); test_width("-1000000", 36, 7, "-00LFLS"); test_width("-1000000000000000", 36, 0, "-9UGXNORJLS"); test_width("-1000000000000000", 36, 1, "-9UGXNORJLS"); test_width("-1000000000000000", 36, 10, "-9UGXNORJLS"); test_width("-1000000000000000", 36, 11, "-9UGXNORJLS"); test_width("-1000000000000000", 36, 12, "-09UGXNORJLS"); test_width("-1000000000000000", 36, 21, "-00000000009UGXNORJLS"); } #[test] fn to_string_base_upper_fail() { assert_panic!(Integer::from(10).to_string_base_upper(0)); assert_panic!(Integer::from(10).to_string_base_upper(1)); assert_panic!(Integer::from(10).to_string_base_upper(37)); assert_panic!(Integer::from(10).to_string_base_upper(100)); assert_panic!(format!("{:#}", BaseFmtWrapper::new(&Integer::from(10), 0))); assert_panic!(format!("{:#}", BaseFmtWrapper::new(&Integer::from(10), 1))); assert_panic!(format!("{:#}", BaseFmtWrapper::new(&Integer::from(10), 37))); assert_panic!(format!( "{:#}", BaseFmtWrapper::new(&Integer::from(10), 100) )); } #[test] fn to_string_base_upper_properties() { integer_unsigned_pair_gen_var_1().test_properties(|(x, base)| { let s = x.to_string_base_upper(base); assert_eq!(format!("{:#}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:#00}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(x.to_string_base(base), s.to_lowercase()); assert_eq!(Integer::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s, "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); if x != 0 { assert!(!s.starts_with('0')); } }); integer_gen().test_properties(|x| { assert_eq!(x.to_string_base_upper(10), x.to_string()); assert_eq!(x.to_string_base_upper(2), x.to_binary_string()); assert_eq!(x.to_string_base_upper(8), x.to_octal_string()); assert_eq!(x.to_string_base_upper(16), x.to_upper_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(Integer::ZERO.to_string_base_upper(base), "0"); assert_eq!(Integer::ONE.to_string_base_upper(base), "1"); assert_eq!(Integer::NEGATIVE_ONE.to_string_base_upper(base), "-1"); assert_eq!(Integer::from(base).to_string_base_upper(base), "10"); }); integer_unsigned_unsigned_triple_gen_var_1().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(&x, base); let s = x.to_string_base_upper(base); let s_padded = format!("{fx:#0width$}"); assert_eq!(format!("{fx:#0width$?}"), s_padded); assert_eq!(Integer::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); test_padding(&s, &s_padded, width); }); integer_unsigned_pair_gen_var_2().test_properties(|(x, width)| { assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 16), width = width), format!("{x:0width$X}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:#0width$}", BaseFmtWrapper::new(&Integer::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); signed_unsigned_unsigned_triple_gen_var_3::().test_properties( |(x, base, width)| { assert_eq!( format!( "{:#0width$}", BaseFmtWrapper::new(&Integer::from(x), base), width = width ), format!( "{:#0width$}", BaseBaseFmtWrapper::new(x, base), width = width ), ); }, ); } ================================================ FILE: malachite-nz/tests/integer/conversion/to_twos_complement_limbs.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Sign; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_gen, unsigned_gen_var_5, unsigned_vec_gen, unsigned_vec_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::integer::conversion::to_twos_complement_limbs::*; use malachite_nz::natural::{LIMB_HIGH_BIT, Natural}; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_bool_vec_pair_gen_var_1, integer_gen, integer_unsigned_pair_gen_var_2, }; use malachite_nz::test_util::integer::conversion::to_twos_complement_limbs::{ limbs_twos_complement_in_place_alt_1, limbs_twos_complement_in_place_alt_2, }; use std::cmp::Ordering::*; #[cfg(feature = "32_bit_limbs")] use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_twos_complement() { let test = |xs: &[Limb], out: &[Limb]| { assert_eq!(limbs_twos_complement(xs), out); }; test(&[1, 2, 3], &[u32::MAX, 0xfffffffd, 0xfffffffc]); test(&[u32::MAX, 0xfffffffd, 0xfffffffc], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_maybe_sign_extend_non_negative_in_place() { let test = |xs: &[Limb], out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_maybe_sign_extend_non_negative_in_place(&mut mut_xs); assert_eq!(mut_xs, out); }; test(&[], &[]); test(&[1, 2, 3], &[1, 2, 3]); test(&[1, 2, u32::MAX], &[1, 2, u32::MAX, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_twos_complement_in_place() { let test = |xs: &[Limb], out: &[Limb], carry: bool| { let mut mut_xs = xs.to_vec(); assert_eq!(limbs_twos_complement_in_place(&mut mut_xs), carry); assert_eq!(mut_xs, out); let mut mut_xs = xs.to_vec(); assert_eq!(limbs_twos_complement_in_place_alt_1(&mut mut_xs), carry); assert_eq!(mut_xs, out); let mut mut_xs = xs.to_vec(); assert_eq!(limbs_twos_complement_in_place_alt_2(&mut mut_xs), carry); assert_eq!(mut_xs, out); }; test(&[], &[], true); test(&[1, 2, 3], &[u32::MAX, 0xfffffffd, 0xfffffffc], false); test(&[u32::MAX, 0xfffffffd, 0xfffffffc], &[1, 2, 3], false); test(&[0, 0, 0], &[0, 0, 0], true); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_twos_complement_and_maybe_sign_extend_negative_in_place() { let test = |xs: &[Limb], out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut mut_xs); assert_eq!(mut_xs, out); }; test(&[1, 2, 3], &[u32::MAX, 0xfffffffd, 0xfffffffc]); test(&[u32::MAX, 0xfffffffd, 0xfffffffc], &[1, 2, 3, u32::MAX]); test(&[0, u32::MAX], &[0, 1, u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_twos_complement_and_maybe_sign_extend_negative_in_place_fail() { let mut mut_xs = vec![0, 0, 0]; limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut mut_xs); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_twos_complement_limbs_asc() { let test = |s, out: &[Limb]| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.twos_complement_limbs().collect_vec(), out); assert_eq!(u.to_twos_complement_limbs_asc(), out); assert_eq!(u.into_twos_complement_limbs_asc(), out); }; test("0", &[]); test("123", &[123]); test("-123", &[4294967173]); test("1000000000000", &[3567587328, 232]); test("-1000000000000", &[727379968, 4294967063]); test("1701411834921604967429270619762735448065", &[1, 2, 3, 4, 5]); test( "-1701411834921604967429270619762735448065", &[u32::MAX, u32::MAX - 2, u32::MAX - 3, u32::MAX - 4, u32::MAX - 5], ); test("2147483647", &[2147483647]); test("-2147483647", &[2147483649]); test("2147483648", &[2147483648, 0]); test("-2147483648", &[2147483648]); test("2147483649", &[2147483649, 0]); test("-2147483649", &[2147483647, 4294967295]); test("4294967294", &[u32::MAX - 1, 0]); test("-4294967294", &[2, u32::MAX]); test("4294967295", &[u32::MAX, 0]); test("-4294967295", &[1, u32::MAX]); test("4294967296", &[0, 1]); test("-4294967296", &[0, u32::MAX]); test("18446744073709551615", &[u32::MAX, u32::MAX, 0]); test("-18446744073709551615", &[1, 0, u32::MAX]); test("18446744073709551616", &[0, 0, 1]); test("-18446744073709551616", &[0, 0, u32::MAX]); let n = Integer::from_str("-1701411834921604967429270619762735448065").unwrap(); let mut limbs = n.twos_complement_limbs(); assert_eq!(Some(u32::MAX), limbs.next()); assert_eq!(Some(u32::MAX - 5), limbs.next_back()); assert_eq!(Some(u32::MAX - 4), limbs.next_back()); assert_eq!(Some(u32::MAX - 2), limbs.next()); assert_eq!(Some(u32::MAX - 3), limbs.next()); assert_eq!(None, limbs.next()); assert_eq!(None, limbs.next_back()); let limbs = n.twos_complement_limbs(); assert_eq!(limbs.get_limb(0), u32::MAX); assert_eq!(limbs.get_limb(1), u32::MAX - 2); assert_eq!(limbs.get_limb(2), u32::MAX - 3); assert_eq!(limbs.get_limb(3), u32::MAX - 4); assert_eq!(limbs.get_limb(4), u32::MAX - 5); assert_eq!(limbs.get_limb(5), u32::MAX); let mut limbs = n.twos_complement_limbs(); assert_eq!(Some(u32::MAX), limbs.next()); assert_eq!(Some(u32::MAX - 2), limbs.next()); assert_eq!(Some(u32::MAX - 3), limbs.next()); assert_eq!(Some(u32::MAX - 5), limbs.next_back()); assert_eq!(Some(u32::MAX - 4), limbs.next_back()); assert_eq!(None, limbs.next()); assert_eq!(None, limbs.next_back()); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_twos_complement_limbs_desc() { let test = |s, out: &[Limb]| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.to_twos_complement_limbs_desc(), out); assert_eq!(u.into_twos_complement_limbs_desc(), out); }; test("0", &[]); test("123", &[123]); test("-123", &[4294967173]); test("1000000000000", &[232, 3567587328]); test("-1000000000000", &[4294967063, 727379968]); test("1701411834921604967429270619762735448065", &[5, 4, 3, 2, 1]); test( "-1701411834921604967429270619762735448065", &[u32::MAX - 5, u32::MAX - 4, u32::MAX - 3, u32::MAX - 2, u32::MAX], ); test("4294967295", &[0, u32::MAX]); test("-4294967295", &[u32::MAX, 1]); test("4294967296", &[1, 0]); test("-4294967296", &[u32::MAX, 0]); test("18446744073709551615", &[0, u32::MAX, u32::MAX]); test("-18446744073709551615", &[u32::MAX, 0, 1]); test("18446744073709551616", &[1, 0, 0]); test("-18446744073709551616", &[u32::MAX, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_twos_complement_limb_count() { let test = |n, out| { assert_eq!( Integer::from_str(n).unwrap().twos_complement_limb_count(), out ); }; test("0", 0); test("123", 1); test("-123", 1); test("1000000000000", 2); test("-1000000000000", 2); test("1701411834921604967429270619762735448065", 5); test("-1701411834921604967429270619762735448065", 5); test("2147483647", 1); test("-2147483647", 1); test("2147483648", 2); test("-2147483648", 1); test("2147483649", 2); test("-2147483649", 2); test("4294967294", 2); test("-4294967294", 2); test("4294967295", 2); test("-4294967295", 2); test("4294967296", 2); test("-4294967296", 2); test("18446744073709551615", 3); test("-18446744073709551615", 3); test("18446744073709551616", 3); test("-18446744073709551616", 3); } #[test] fn limbs_twos_complement_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_2().test_properties_with_config(&config, |xs| { let out_xs = limbs_twos_complement(&xs); if *xs.last().unwrap() != 0 && out_xs.last().unwrap().get_highest_bit() { let n = -Natural::from_limbs_asc(&xs); assert_eq!(n.to_twos_complement_limbs_asc(), out_xs); } }); } #[test] fn limbs_maybe_sign_extend_non_negative_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let mut mut_xs = xs.clone(); limbs_maybe_sign_extend_non_negative_in_place(&mut mut_xs); if !xs.is_empty() && *xs.last().unwrap() != 0 { let n = Integer::from(Natural::from_owned_limbs_asc(xs)); assert_eq!(n.to_twos_complement_limbs_asc(), mut_xs); } }); } #[test] fn limbs_twos_complement_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let mut mut_xs = xs.clone(); limbs_twos_complement_in_place(&mut mut_xs); let mut mut_xs_alt = xs.clone(); limbs_twos_complement_in_place_alt_1(&mut mut_xs_alt); assert_eq!(mut_xs_alt, mut_xs); let mut mut_xs_alt = xs.clone(); limbs_twos_complement_in_place_alt_2(&mut mut_xs_alt); assert_eq!(mut_xs_alt, mut_xs); if !xs.is_empty() && *xs.last().unwrap() != 0 && mut_xs.last().unwrap().get_highest_bit() { let n = -Natural::from_owned_limbs_asc(xs); assert_eq!(n.to_twos_complement_limbs_asc(), mut_xs); } }); } #[test] fn limbs_twos_complement_and_maybe_sign_extend_negative_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_2().test_properties_with_config(&config, |xs| { let mut mut_xs = xs.clone(); limbs_twos_complement_and_maybe_sign_extend_negative_in_place(&mut mut_xs); if !xs.is_empty() && *xs.last().unwrap() != 0 { let n = -Natural::from_owned_limbs_asc(xs); assert_eq!(n.to_twos_complement_limbs_asc(), mut_xs); } }); } #[test] fn to_twos_complement_limbs_asc_properties() { integer_gen().test_properties(|x| { let xs = x.to_twos_complement_limbs_asc(); assert_eq!(xs.len(), usize::exact_from(x.twos_complement_limb_count())); assert_eq!(x.clone().into_twos_complement_limbs_asc(), xs); assert_eq!(x.twos_complement_limbs().collect_vec(), xs); assert_eq!(Integer::from_twos_complement_limbs_asc(&xs), x); assert_eq!( x.to_twos_complement_limbs_desc(), xs.iter().copied().rev().collect_vec() ); match x.sign() { Equal => assert!(xs.is_empty()), Greater => { let last = *xs.last().unwrap(); assert!(!last.get_highest_bit()); if last == 0 { assert!(xs[xs.len() - 2].get_highest_bit()); } } Less => { let last = *xs.last().unwrap(); assert!(last.get_highest_bit()); if last == !0 && xs.len() > 1 { assert!(!xs[xs.len() - 2].get_highest_bit()); } } } }); } #[test] fn to_twos_complement_limbs_desc_properties() { integer_gen().test_properties(|x| { let xs = x.to_twos_complement_limbs_desc(); assert_eq!(xs.len(), usize::exact_from(x.twos_complement_limb_count())); assert_eq!(x.clone().into_twos_complement_limbs_desc(), xs); assert_eq!(x.twos_complement_limbs().rev().collect_vec(), xs); assert_eq!(Integer::from_twos_complement_limbs_desc(&xs), x); assert_eq!( x.to_twos_complement_limbs_asc(), xs.iter().copied().rev().collect_vec() ); match x.sign() { Equal => assert!(xs.is_empty()), Greater => { let first = xs[0]; assert!(!first.get_highest_bit()); if first == 0 { assert!(xs[1].get_highest_bit()); } } Less => { let first = xs[0]; assert!(first.get_highest_bit()); if first == !0 && xs.len() > 1 { assert!(!xs[1].get_highest_bit()); } } } }); } #[test] fn twos_complement_limbs_properties() { integer_bool_vec_pair_gen_var_1().test_properties(|(n, bs)| { let mut limbs = n.twos_complement_limbs(); let mut xs = Vec::new(); let mut i = 0; for b in bs { if b { xs.insert(i, limbs.next().unwrap()); i += 1; } else { xs.insert(i, limbs.next_back().unwrap()); } } assert!(limbs.next().is_none()); assert!(limbs.next_back().is_none()); assert_eq!(n.to_twos_complement_limbs_asc(), xs); }); integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { if u < n.unsigned_abs_ref().limb_count() { assert_eq!( n.twos_complement_limbs().get_limb(u), n.to_twos_complement_limbs_asc()[usize::exact_from(u)] ); } else { assert_eq!( n.twos_complement_limbs().get_limb(u), if n >= 0 { 0 } else { Limb::MAX } ); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(Integer::ZERO.twos_complement_limbs().get_limb(u), 0); }); } #[test] fn twos_complement_limb_count_properties() { integer_gen().test_properties(|x| { let n = x.twos_complement_limb_count(); assert_eq!( (x >= 0 && x < LIMB_HIGH_BIT) || (x < 0 && x >= -Integer::from(LIMB_HIGH_BIT)), n <= 1 ); }); signed_gen::().test_properties(|i| { assert!(Integer::from(i).twos_complement_limb_count() <= 1); }); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_integer_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integer_inclusive_range; fn expected_range_len(a: &Integer, b: &Integer) -> usize { match (*a >= 0, *b >= 0) { (false, false) => usize::exact_from(&-a) - usize::exact_from(&-b) + 1, (false, true) => usize::exact_from(&-a) + usize::exact_from(b) + 1, (true, false) => panic!(), (true, true) => usize::exact_from(b) - usize::exact_from(a) + 1, } } fn exhaustive_integer_inclusive_range_helper(a: &Integer, b: &Integer, values: &str) { let xs = exhaustive_integer_inclusive_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); assert_eq!( exhaustive_integer_inclusive_range(a.clone(), b.clone()).count(), expected_range_len(a, b) ); } fn exhaustive_integer_inclusive_range_rev_helper(a: Integer, b: Integer, rev_values: &str) { let len = expected_range_len(&a, &b); assert_eq!( exhaustive_integer_inclusive_range(a.clone(), b.clone()).count(), len ); let mut tail = exhaustive_integer_inclusive_range(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(tail.to_debug_string(), rev_values); } #[test] fn test_exhaustive_integer_inclusive_range() { exhaustive_integer_inclusive_range_helper(&Integer::ZERO, &Integer::ZERO, "[0]"); exhaustive_integer_inclusive_range_helper(&Integer::ZERO, &Integer::ONE, "[0, 1]"); exhaustive_integer_inclusive_range_helper( &Integer::ZERO, &Integer::from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", ); exhaustive_integer_inclusive_range_helper( &Integer::from(10), &Integer::from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]", ); exhaustive_integer_inclusive_range_helper( &Integer::from(-20), &Integer::from(-10), "[-10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20]", ); exhaustive_integer_inclusive_range_helper( &Integer::from(-100), &Integer::from(100), "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10]", ); exhaustive_integer_inclusive_range_rev_helper( Integer::from(-20), Integer::from(-10), "[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10]", ); exhaustive_integer_inclusive_range_rev_helper( Integer::from(-100), Integer::from(100), "[-100, 100, -99, 99, -98, 98, -97, 97, -96, 96, -95, 95, -94, 94, -93, 93, -92, 92, -91, \ 91]", ); } #[test] #[should_panic] fn exhaustive_integer_inclusive_range_fail() { exhaustive_integer_inclusive_range(Integer::ONE, Integer::ZERO); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_integer_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integer_range; fn expected_range_len(a: &Integer, b: &Integer) -> usize { match (*a >= 0, *b >= 0) { (false, false) => usize::exact_from(&-a) - usize::exact_from(&-b), (false, true) => usize::exact_from(&-a) + usize::exact_from(b), (true, false) => panic!(), (true, true) => usize::exact_from(b) - usize::exact_from(a), } } fn exhaustive_integer_range_helper(a: &Integer, b: &Integer, values: &str) { let xs = exhaustive_integer_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); assert_eq!( exhaustive_integer_range(a.clone(), b.clone()).count(), expected_range_len(a, b) ); } fn exhaustive_integer_range_rev_helper(a: Integer, b: Integer, rev_values: &str) { let len = expected_range_len(&a, &b); assert_eq!(exhaustive_integer_range(a.clone(), b.clone()).count(), len); let mut tail = exhaustive_integer_range(a, b) .skip(len.saturating_sub(20)) .collect_vec(); tail.reverse(); assert_eq!(tail.to_debug_string(), rev_values); } #[test] fn test_exhaustive_integer_range() { exhaustive_integer_range_helper(&Integer::ZERO, &Integer::ZERO, "[]"); exhaustive_integer_range_helper(&Integer::ZERO, &Integer::ONE, "[0]"); exhaustive_integer_range_helper( &Integer::ZERO, &Integer::from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", ); exhaustive_integer_range_helper( &Integer::from(10), &Integer::from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); exhaustive_integer_range_helper( &Integer::from(-20), &Integer::from(-10), "[-11, -12, -13, -14, -15, -16, -17, -18, -19, -20]", ); exhaustive_integer_range_helper( &Integer::from(-100), &Integer::from(100), "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10]", ); exhaustive_integer_range_rev_helper( Integer::from(-20), Integer::from(-10), "[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11]", ); exhaustive_integer_range_rev_helper( Integer::from(-100), Integer::from(100), "[-100, -99, 99, -98, 98, -97, 97, -96, 96, -95, 95, -94, 94, -93, 93, -92, 92, -91, 91, \ -90]", ); } #[test] #[should_panic] fn exhaustive_integer_range_fail() { exhaustive_integer_range(Integer::ONE, Integer::ZERO); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_integer_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integer_range_to_infinity; fn exhaustive_integer_range_to_infinity_helper(a: Integer, values: &str) { let xs = exhaustive_integer_range_to_infinity(a) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_integer_range_to_infinity() { exhaustive_integer_range_to_infinity_helper( Integer::ZERO, "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); exhaustive_integer_range_to_infinity_helper( Integer::from(5), "[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]", ); exhaustive_integer_range_to_infinity_helper( Integer::from(-5), "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14]", ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_integer_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integer_range_to_negative_infinity; fn exhaustive_integer_range_to_negative_infinity_helper(a: Integer, values: &str) { let xs = exhaustive_integer_range_to_negative_infinity(a) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_integer_range_to_negative_infinity() { exhaustive_integer_range_to_negative_infinity_helper( Integer::ZERO, "[0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19]", ); exhaustive_integer_range_to_negative_infinity_helper( Integer::from(-5), "[-5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, \ -23, -24]", ); exhaustive_integer_range_to_negative_infinity_helper( Integer::from(5), "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14]", ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_integers.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::integer::exhaustive::exhaustive_integers; #[test] fn test_exhaustive_integers() { assert_eq!( exhaustive_integers() .take(20) .collect_vec() .to_debug_string(), "[0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10]" ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_natural_integers.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::integer::exhaustive::exhaustive_natural_integers; #[test] fn test_exhaustive_natural_integers() { assert_eq!( exhaustive_natural_integers() .take(20) .collect_vec() .to_debug_string(), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]" ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_negative_integers.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::integer::exhaustive::exhaustive_negative_integers; #[test] fn test_exhaustive_negative_integers() { assert_eq!( exhaustive_negative_integers() .take(20) .collect_vec() .to_debug_string(), "[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, \ -20]" ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_nonzero_integers.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::integer::exhaustive::exhaustive_nonzero_integers; #[test] fn test_exhaustive_nonzero_integers() { assert_eq!( exhaustive_nonzero_integers() .take(20) .collect_vec() .to_debug_string(), "[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10]" ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/exhaustive_positive_integers.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::integer::exhaustive::exhaustive_positive_integers; #[test] fn test_exhaustive_positive_integers() { assert_eq!( exhaustive_positive_integers() .take(20) .collect_vec() .to_debug_string(), "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]" ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/integer_decreasing_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::integer_decreasing_range_to_negative_infinity; fn integer_decreasing_range_to_negative_infinity_helper(a: Integer, values: &str) { let xs = integer_decreasing_range_to_negative_infinity(a) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_integer_decreasing_range_to_negative_infinity() { integer_decreasing_range_to_negative_infinity_helper( Integer::ZERO, "[0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19]", ); integer_decreasing_range_to_negative_infinity_helper( Integer::from(10), "[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9]", ); integer_decreasing_range_to_negative_infinity_helper( Integer::from(-10), "[-10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, \ -27, -28, -29]", ); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/integer_increasing_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::integer_increasing_inclusive_range; fn expected_range_len(a: &Integer, b: &Integer) -> usize { match (*a >= 0, *b >= 0) { (false, false) => usize::exact_from(&-a) - usize::exact_from(&-b) + 1, (false, true) => usize::exact_from(&-a) + usize::exact_from(b) + 1, (true, false) => panic!(), (true, true) => usize::exact_from(b) - usize::exact_from(a) + 1, } } fn integer_increasing_inclusive_range_helper(a: Integer, b: Integer, values: &str) { let xs = integer_increasing_inclusive_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); let len = expected_range_len(&a, &b); assert_eq!( integer_increasing_inclusive_range(a.clone(), b.clone()).count(), len ); let mut init = integer_increasing_inclusive_range(a, b) .rev() .skip(len.saturating_sub(20)) .collect_vec(); init.reverse(); assert_eq!(xs, init.to_debug_string()); } #[test] fn test_integer_increasing_inclusive_range() { integer_increasing_inclusive_range_helper(Integer::ZERO, Integer::ZERO, "[0]"); integer_increasing_inclusive_range_helper(Integer::ZERO, Integer::ONE, "[0, 1]"); integer_increasing_inclusive_range_helper( Integer::ZERO, Integer::from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", ); integer_increasing_inclusive_range_helper( Integer::from(10), Integer::from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]", ); integer_increasing_inclusive_range_helper( Integer::from(-20), Integer::from(-10), "[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10]", ); integer_increasing_inclusive_range_helper( Integer::from(-100), Integer::from(100), "[-100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, \ -83, -82, -81]", ); } #[test] #[should_panic] fn integer_increasing_inclusive_range_fail() { integer_increasing_inclusive_range(Integer::ONE, Integer::ZERO); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/integer_increasing_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::integer_increasing_range; fn expected_range_len(a: &Integer, b: &Integer) -> usize { match (*a >= 0, *b >= 0) { (false, false) => usize::exact_from(&-a) - usize::exact_from(&-b), (false, true) => usize::exact_from(&-a) + usize::exact_from(b), (true, false) => panic!(), (true, true) => usize::exact_from(b) - usize::exact_from(a), } } fn integer_increasing_range_helper(a: Integer, b: Integer, values: &str) { let xs = integer_increasing_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); let len = expected_range_len(&a, &b); assert_eq!(integer_increasing_range(a.clone(), b.clone()).count(), len); let mut init = integer_increasing_range(a, b) .rev() .skip(len.saturating_sub(20)) .collect_vec(); init.reverse(); assert_eq!(xs, init.to_debug_string()); } #[test] fn test_integer_increasing_range() { integer_increasing_range_helper(Integer::ZERO, Integer::ZERO, "[]"); integer_increasing_range_helper(Integer::ZERO, Integer::ONE, "[0]"); integer_increasing_range_helper( Integer::ZERO, Integer::from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", ); integer_increasing_range_helper( Integer::from(10), Integer::from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); integer_increasing_range_helper( Integer::from(-20), Integer::from(-10), "[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11]", ); integer_increasing_range_helper( Integer::from(-100), Integer::from(100), "[-100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, \ -83, -82, -81]", ); } #[test] #[should_panic] fn integer_increasing_range_fail() { integer_increasing_range(Integer::ONE, Integer::ZERO); } ================================================ FILE: malachite-nz/tests/integer/exhaustive/integer_increasing_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::integer_increasing_range_to_infinity; fn integer_increasing_range_to_infinity_helper(a: Integer, values: &str) { let xs = integer_increasing_range_to_infinity(a) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_integer_increasing_range_to_infinity() { integer_increasing_range_to_infinity_helper( Integer::ZERO, "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); integer_increasing_range_to_infinity_helper( Integer::from(10), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]", ); integer_increasing_range_to_infinity_helper( Integer::from(-10), "[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", ); } ================================================ FILE: malachite-nz/tests/integer/logic/and.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_pair_gen, unsigned_vec_pair_gen_var_8, unsigned_vec_pair_gen_var_9, unsigned_vec_triple_gen_var_33, unsigned_vec_triple_gen_var_34, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::and::{ limbs_and_neg_neg, limbs_and_neg_neg_to_out, limbs_and_pos_neg, limbs_and_pos_neg_in_place_left, limbs_and_pos_neg_to_out, limbs_neg_and_limb_neg, limbs_neg_and_limb_neg_to_out, limbs_pos_and_limb_neg, limbs_pos_and_limb_neg_in_place, limbs_pos_and_limb_neg_to_out, limbs_slice_and_neg_neg_in_place_either, limbs_slice_and_neg_neg_in_place_left, limbs_slice_and_pos_neg_in_place_right, limbs_slice_neg_and_limb_neg_in_place, limbs_vec_and_neg_neg_in_place_either, limbs_vec_and_neg_neg_in_place_left, limbs_vec_and_pos_neg_in_place_right, limbs_vec_neg_and_limb_neg_in_place, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use malachite_nz::test_util::integer::logic::and::{integer_and_alt_1, integer_and_alt_2}; use rug; use std::cmp::{max, min}; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_and_limb_neg_and_limbs_pos_and_limb_neg_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_pos_and_limb_neg(xs, y), out); let mut xs = xs.to_vec(); limbs_pos_and_limb_neg_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 2, &[2, 7]); test(&[100, 101, 102], 10, &[0, 101, 102]); test(&[123, 456], 789, &[17, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_and_limb_neg_fail() { limbs_pos_and_limb_neg(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_and_limb_neg_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_pos_and_limb_neg_to_out(&mut out, xs, y); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[6, 7], 2, &[2, 7, 10, 10]); test(&[10, 10, 10, 10], &[100, 101, 102], 10, &[0, 101, 102, 10]); test(&[10, 10, 10, 10], &[123, 456], 789, &[17, 456, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_and_limb_neg_to_out_fail_1() { limbs_pos_and_limb_neg_to_out(&mut [], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_and_limb_neg_to_out_fail_2() { limbs_pos_and_limb_neg_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_and_limb_neg_in_place_fail() { limbs_pos_and_limb_neg_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_and_limb_neg_and_limbs_vec_neg_and_limb_neg_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_neg_and_limb_neg(xs, y), out); let mut xs = xs.to_vec(); limbs_vec_neg_and_limb_neg_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[0, 2], 3, &[0, 2]); test(&[1, 1], 3, &[0xfffffffd, 1]); test(&[u32::MAX - 1, 1], 1, &[0, 2]); test(&[u32::MAX - 1, u32::MAX], 1, &[0, 0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_and_limb_neg_fail() { limbs_neg_and_limb_neg(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_and_limb_neg_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_neg_and_limb_neg_to_out(&mut out, xs, y), carry); assert_eq!(out, out_after); }; test(&[0, 0], &[0, 2], 3, false, &[0, 2]); test(&[1, 2, 100], &[0, 2, 100], 3, false, &[0, 2, 100]); test(&[0, 0], &[1, 1], 3, false, &[0xfffffffd, 1]); test(&[0, 0], &[u32::MAX - 1, 1], 1, false, &[0, 2]); test(&[0, 0], &[u32::MAX - 1, u32::MAX], 1, true, &[0, 0]); test( &[1, 2, 100], &[u32::MAX - 1, u32::MAX], 1, true, &[0, 0, 100], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_and_limb_neg_to_out_fail_1() { limbs_neg_and_limb_neg_to_out(&mut [1, 2, 3], &[1, 2, 3, 4], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_and_limb_neg_to_out_fail_2() { limbs_neg_and_limb_neg_to_out(&mut [1, 2, 3], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_neg_and_limb_neg_in_place() { let test = |xs: &[Limb], y: Limb, carry, xs_after: &[Limb]| { let mut xs = xs.to_vec(); assert_eq!(limbs_slice_neg_and_limb_neg_in_place(&mut xs, y), carry); assert_eq!(xs, xs_after); }; test(&[0, 2], 3, false, &[0, 2]); test(&[1, 1], 3, false, &[0xfffffffd, 1]); test(&[u32::MAX - 1, 1], 1, false, &[0, 2]); test(&[u32::MAX - 1, u32::MAX], 1, true, &[0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_neg_and_limb_neg_in_place_fail() { limbs_slice_neg_and_limb_neg_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_neg_and_limb_neg_in_place_fail() { let mut xs = vec![]; limbs_vec_neg_and_limb_neg_in_place(&mut xs, 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_pos_neg() { let test = |xs, ys, out: &[Limb]| { assert_eq!(limbs_and_pos_neg(xs, ys), out); }; test(&[2], &[3], &[0]); test(&[1, 1, 1], &[1, 2, 3], &[1, 1, 0]); test(&[6, 7], &[1, 2, 3], &[6, 5]); test(&[1, 2, 3], &[6, 7], &[0, 0, 3]); test(&[100, 101, 102], &[102, 101, 100], &[0, 0, 2]); test(&[0, 0, 1], &[3], &[0, 0, 1]); test(&[3], &[0, 0, 1], &[]); test(&[0, 3, 3], &[0, 0, 3], &[0, 0, 1]); test(&[0, 0, 3], &[0, 3, 3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_fail_1() { limbs_and_pos_neg(&[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_fail_2() { limbs_and_pos_neg(&[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_pos_neg_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_and_pos_neg_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[2], &[3], &[10, 10, 10, 10], &[0, 10, 10, 10]); test(&[1, 1, 1], &[1, 2, 3], &[10, 10, 10, 10], &[1, 1, 0, 10]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], &[6, 5, 10, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], &[0, 0, 3, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], &[0, 0, 2, 10], ); test(&[0, 0, 1], &[3], &[10, 10, 10, 10], &[0, 0, 1, 10]); test(&[3], &[0, 0, 1], &[10, 10, 10, 10], &[0, 10, 10, 10]); test(&[0, 3, 3], &[0, 0, 3], &[10, 10, 10, 10], &[0, 0, 1, 10]); test(&[0, 0, 3], &[0, 3, 3], &[10, 10, 10, 10], &[0, 0, 0, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_to_out_fail_1() { let out = &mut [10, 10, 10, 10]; limbs_and_pos_neg_to_out(out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_to_out_fail_2() { let out = &mut [10, 10, 10, 10]; limbs_and_pos_neg_to_out(out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_to_out_fail_3() { let out = &mut [10]; limbs_and_pos_neg_to_out(out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_neg_in_place_left_and_limbs_vec_and_pos_neg_in_place_right() { let test = |xs: &[Limb], ys, out: &[Limb]| { { let mut mut_xs = xs.to_vec(); limbs_and_pos_neg_in_place_left(&mut mut_xs, ys); assert_eq!(mut_xs, out); } { let mut mut_ys = ys.to_vec(); limbs_vec_and_pos_neg_in_place_right(xs, &mut mut_ys); assert_eq!(mut_ys, out); } }; test(&[2], &[3], &[0]); test(&[1, 1, 1], &[1, 2, 3], &[1, 1, 0]); test(&[6, 7], &[1, 2, 3], &[6, 5]); test(&[1, 2, 3], &[6, 7], &[0, 0, 3]); test(&[100, 101, 102], &[102, 101, 100], &[0, 0, 2]); test(&[0, 0, 1], &[3], &[0, 0, 1]); test(&[3], &[0, 0, 1], &[0]); test(&[0, 3, 3], &[0, 0, 3], &[0, 0, 1]); test(&[0, 0, 3], &[0, 3, 3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_in_place_left_fail_1() { limbs_and_pos_neg_in_place_left(&mut [0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_pos_neg_in_place_left_fail_2() { limbs_and_pos_neg_in_place_left(&mut [3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_pos_neg_in_place_right_fail_1() { let mut ys = vec![3]; limbs_vec_and_pos_neg_in_place_right(&[0, 0, 0], &mut ys); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_pos_neg_in_place_right_fail_2() { let mut ys = vec![0, 0, 0]; limbs_vec_and_pos_neg_in_place_right(&[3], &mut ys); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_and_pos_neg_in_place_right() { let test = |xs, ys_before: &[Limb], ys_after: &[Limb]| { let mut ys = ys_before.to_vec(); limbs_slice_and_pos_neg_in_place_right(xs, &mut ys); assert_eq!(ys, ys_after); }; test(&[2], &[3], &[0]); test(&[1, 1, 1], &[1, 2, 3], &[1, 1, 0]); test(&[6, 7], &[1, 2, 3], &[6, 5, 3]); test(&[1, 2, 3], &[6, 7], &[0, 0]); test(&[100, 101, 102], &[102, 101, 100], &[0, 0, 2]); test(&[0, 0, 1], &[3], &[0]); test(&[3], &[0, 0, 1], &[0, 0, 0]); test(&[0, 3, 3], &[0, 0, 3], &[0, 0, 1]); test(&[0, 0, 3], &[0, 3, 3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_pos_neg_in_place_right_fail_1() { limbs_slice_and_pos_neg_in_place_right(&[0, 0, 0], &mut [3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_pos_neg_in_place_right_fail_2() { limbs_slice_and_pos_neg_in_place_right(&[3], &mut [0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_neg_neg_and_limbs_vec_and_neg_neg_in_place_left() { let test = |xs, ys, out: &[Limb]| { assert_eq!(limbs_and_neg_neg(xs, ys), out); let mut mut_xs = xs.to_vec(); limbs_vec_and_neg_neg_in_place_left(&mut mut_xs, ys); assert_eq!(mut_xs, out); }; test(&[2], &[3], &[4]); test(&[1, 1, 1], &[1, 2, 3], &[1, 3, 3]); test(&[6, 7], &[1, 2, 3], &[6, 7, 3]); test(&[1, 2, 3], &[6, 7], &[6, 7, 3]); test(&[100, 101, 102], &[102, 101, 100], &[104, 101, 102]); test(&[0, 0, 1], &[3], &[0, 0, 1]); test(&[3], &[0, 0, 1], &[0, 0, 1]); test(&[0, 3, 3], &[0, 0, 3], &[0, 0, 4]); test(&[0, 0, 3], &[0, 3, 3], &[0, 0, 4]); test(&[0, 2, 1], &[0, u32::MAX, u32::MAX], &[0, 0, 0, 1]); test(&[0, 2], &[0, u32::MAX, u32::MAX], &[0, 0, 0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_fail_1() { limbs_and_neg_neg(&[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_fail_2() { limbs_and_neg_neg(&[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_neg_neg_in_place_left_fail_1() { limbs_vec_and_neg_neg_in_place_left(&mut vec![0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_neg_neg_in_place_left_fail_2() { limbs_vec_and_neg_neg_in_place_left(&mut vec![3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_neg_neg_to_out() { let test = |xs, ys, out_before: &[Limb], b, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_and_neg_neg_to_out(&mut out, xs, ys), b); assert_eq!(out, out_after); }; test(&[2], &[3], &[10, 10, 10, 10], true, &[4, 10, 10, 10]); test( &[1, 1, 1], &[1, 2, 3], &[10, 10, 10, 10], true, &[1, 3, 3, 10], ); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], true, &[6, 7, 3, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], true, &[6, 7, 3, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], true, &[104, 101, 102, 10], ); test(&[0, 0, 1], &[3], &[10, 10, 10, 10], true, &[0, 0, 1, 10]); test(&[3], &[0, 0, 1], &[10, 10, 10, 10], true, &[0, 0, 1, 10]); test( &[0, 3, 3], &[0, 0, 3], &[10, 10, 10, 10], true, &[0, 0, 4, 10], ); test( &[0, 0, 3], &[0, 3, 3], &[10, 10, 10, 10], true, &[0, 0, 4, 10], ); test( &[0, 2], &[0, u32::MAX], &[10, 10, 10, 10], false, &[0, 0, 10, 10], ); test( &[0, 2, 1], &[0, u32::MAX, u32::MAX], &[10, 10, 10, 10], false, &[0, 0, 0, 10], ); test( &[0, 2], &[0, u32::MAX, u32::MAX], &[10, 10, 10, 10], false, &[0, 0, 0, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_to_out_fail_1() { let out = &mut [10, 10, 10, 10]; limbs_and_neg_neg_to_out(out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_to_out_fail_2() { let out = &mut [10, 10, 10, 10]; limbs_and_neg_neg_to_out(out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_to_out_fail_3() { let out = &mut [10, 10]; limbs_and_neg_neg_to_out(out, &[6, 7, 8], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_neg_neg_to_out_fail_4() { let out = &mut [10, 10]; limbs_and_neg_neg_to_out(out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_and_neg_neg_in_place_left() { let test = |xs_before: &[Limb], ys, b, xs_after: &[Limb]| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_slice_and_neg_neg_in_place_left(&mut xs, ys), b); assert_eq!(xs, xs_after); }; test(&[2], &[3], true, &[4]); test(&[1, 1, 1], &[1, 2, 3], true, &[1, 3, 3]); test(&[1, 2, 3], &[6, 7], true, &[6, 7, 3]); test(&[100, 101, 102], &[102, 101, 100], true, &[104, 101, 102]); test(&[0, 0, 1], &[3], true, &[0, 0, 1]); test(&[0, 3, 3], &[0, 0, 3], true, &[0, 0, 4]); test(&[0, 0, 3], &[0, 3, 3], true, &[0, 0, 4]); test(&[0, 2], &[0, u32::MAX], false, &[0, 0]); test(&[0, 2, 1], &[0, u32::MAX, u32::MAX], false, &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_neg_neg_in_place_left_fail_1() { limbs_slice_and_neg_neg_in_place_left(&mut [0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_neg_neg_in_place_left_fail_2() { limbs_slice_and_neg_neg_in_place_left(&mut [0, 0, 1], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_neg_neg_in_place_left_fail_3() { limbs_slice_and_neg_neg_in_place_left(&mut [6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_and_neg_neg_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], p, xs_after: &[Limb], ys_after: &[Limb]| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_slice_and_neg_neg_in_place_either(&mut xs, &mut ys), p); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[2], &[3], (false, true), &[4], &[3]); test( &[1, 1, 1], &[1, 2, 3], (false, true), &[1, 3, 3], &[1, 2, 3], ); test(&[1, 2, 3], &[6, 7], (false, true), &[6, 7, 3], &[6, 7]); test(&[6, 7], &[1, 2, 3], (true, true), &[6, 7], &[6, 7, 3]); test( &[100, 101, 102], &[102, 101, 100], (false, true), &[104, 101, 102], &[102, 101, 100], ); test(&[0, 0, 1], &[3], (false, true), &[0, 0, 1], &[3]); test(&[3], &[0, 0, 1], (true, true), &[3], &[0, 0, 1]); test( &[0, 3, 3], &[0, 0, 3], (false, true), &[0, 0, 4], &[0, 0, 3], ); test( &[0, 0, 3], &[0, 3, 3], (false, true), &[0, 0, 4], &[0, 3, 3], ); test( &[0, 2], &[0, u32::MAX], (false, false), &[0, 0], &[0, u32::MAX], ); test( &[0, 2, 1], &[0, u32::MAX, u32::MAX], (false, false), &[0, 0, 0], &[0, u32::MAX, u32::MAX], ); test( &[0, 2], &[0, u32::MAX, u32::MAX], (true, false), &[0, 2], &[0, 0, 0], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_neg_neg_in_place_either_fail_1() { limbs_slice_and_neg_neg_in_place_either(&mut [0, 0, 0], &mut [3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_neg_neg_in_place_either_fail_2() { limbs_slice_and_neg_neg_in_place_either(&mut [3], &mut [0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_and_neg_neg_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], b, xs_after: &[Limb], ys_after: &[Limb]| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_vec_and_neg_neg_in_place_either(&mut xs, &mut ys), b); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[2], &[3], false, &[4], &[3]); test(&[1, 1, 1], &[1, 2, 3], false, &[1, 3, 3], &[1, 2, 3]); test(&[1, 2, 3], &[6, 7], false, &[6, 7, 3], &[6, 7]); test(&[6, 7], &[1, 2, 3], true, &[6, 7], &[6, 7, 3]); test( &[100, 101, 102], &[102, 101, 100], false, &[104, 101, 102], &[102, 101, 100], ); test(&[0, 0, 1], &[3], false, &[0, 0, 1], &[3]); test(&[3], &[0, 0, 1], true, &[3], &[0, 0, 1]); test(&[0, 3, 3], &[0, 0, 3], false, &[0, 0, 4], &[0, 0, 3]); test(&[0, 0, 3], &[0, 3, 3], false, &[0, 0, 4], &[0, 3, 3]); test(&[0, 2], &[0, u32::MAX], false, &[0, 0, 1], &[0, u32::MAX]); test( &[0, 2, 1], &[0, u32::MAX, u32::MAX], false, &[0, 0, 0, 1], &[0, u32::MAX, u32::MAX], ); test( &[0, 2], &[0, u32::MAX, u32::MAX], true, &[0, 2], &[0, 0, 0, 1], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_neg_neg_in_place_either_fail_1() { limbs_vec_and_neg_neg_in_place_either(&mut vec![0, 0, 0], &mut vec![3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_and_neg_neg_in_place_either_fail_2() { limbs_vec_and_neg_neg_in_place_either(&mut vec![3], &mut vec![0, 0, 0]); } #[test] fn test_and() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n &= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n &= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() & v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u & v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() & &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u & &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(integer_and_alt_1(&u, &v).to_string(), out); assert_eq!(integer_and_alt_2(&u, &v).to_string(), out); let n = rug::Integer::from_str(s).unwrap() & rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "0"); test("123", "0", "0"); test("123", "456", "72"); test("1000000000000", "123", "0"); test("123", "1000000000000", "0"); test("1000000000000", "999999999999", "999999995904"); test("12345678987654321", "314159265358979", "312331665941633"); test("0", "-123", "0"); test("123", "-456", "56"); test("1000000000000", "-123", "1000000000000"); test("123", "-1000000000000", "0"); test("1000000000000", "-999999999999", "4096"); test("12345678987654321", "-314159265358979", "12033347321712689"); test("-123", "0", "0"); test("-123", "456", "384"); test("-1000000000000", "123", "0"); test("-123", "1000000000000", "1000000000000"); test("-1000000000000", "999999999999", "0"); test("-12345678987654321", "314159265358979", "1827599417347"); test("-123", "-456", "-512"); test("-1000000000000", "-123", "-1000000000000"); test("-123", "-1000000000000", "-1000000000000"); test("-1000000000000", "-999999999999", "-1000000000000"); test( "-12345678987654321", "-314159265358979", "-12347506587071667", ); test( "-18446744073708507135", "-9007061819981696", "-18446744073709551616", ); test("-18446744073708507135", "-4194176", "-18446744073709551616"); test("-4194176", "-18446744073708507135", "-18446744073709551616"); test( "3332140978726732268209104861552", "-478178031043645514337313657924474082957368", "2539024739207132029580719268160", ); test( "-478178031043645514337313657924474082957368", "3332140978726732268209104861552", "2539024739207132029580719268160", ); } #[test] fn limbs_pos_and_limb_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { let out = limbs_pos_and_limb_neg(&xs, y); let n = Integer::from(Natural::from_owned_limbs_asc(xs)) & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(out), Natural::exact_from(n)); }); } #[test] fn limbs_pos_and_limb_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_pos_and_limb_neg_to_out(&mut out, &xs, y); let len = xs.len(); let n = Integer::from(Natural::from_owned_limbs_asc(xs)) & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let mut out_alt = Natural::exact_from(n).into_limbs_asc(); out_alt.resize(len, 0); assert_eq!(out_alt, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_pos_and_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let mut n = Integer::from(Natural::from_limbs_asc(&xs)); limbs_pos_and_limb_neg_in_place(&mut xs, y); n &= Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(xs), Natural::exact_from(n)); }); } #[test] fn limbs_neg_and_limb_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(xs, y)| { let out = limbs_neg_and_limb_neg(&xs, y); let n = -Natural::from_owned_limbs_asc(xs) & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(out), Natural::exact_from(-n)); }); } #[test] fn limbs_neg_and_limb_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let carry = limbs_neg_and_limb_neg_to_out(&mut out, &xs, y); let len = xs.len(); let n = -Natural::from_owned_limbs_asc(xs) & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let mut out_alt = Natural::exact_from(-n).into_limbs_asc(); assert_eq!(carry, out_alt.len() == len + 1); out_alt.resize(len, 0); assert_eq!(out_alt, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_slice_neg_and_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_slice_neg_and_limb_neg_in_place(&mut xs, y); let n = -Natural::from_owned_limbs_asc(old_xs) & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let mut expected_xs = Natural::exact_from(-n).into_limbs_asc(); expected_xs.resize(xs.len(), 0); assert_eq!(xs, expected_xs); }); } #[test] fn limbs_vec_neg_and_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let n = Natural::from_limbs_asc(&xs); limbs_vec_neg_and_limb_neg_in_place(&mut xs, y); let n = -n & Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(xs), Natural::exact_from(-n)); }); } #[test] fn limbs_and_pos_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_and_pos_neg(&xs, &ys)), Integer::from(Natural::from_owned_limbs_asc(xs)) & -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_and_pos_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_33().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_and_pos_neg_to_out(&mut out, &xs, &ys); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Integer::from(Natural::from_owned_limbs_asc(xs)) & -Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_and_pos_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_and_pos_neg_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Integer::from(Natural::from_owned_limbs_asc(xs_old)) & -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_slice_and_pos_neg_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, mut ys)| { let ys_old = ys.clone(); limbs_slice_and_pos_neg_in_place_right(&xs, &mut ys); let len = min(xs.len(), ys.len()); let result = Integer::from(Natural::from_owned_limbs_asc(xs)) & -Natural::from_owned_limbs_asc(ys_old); let mut expected_ys = Natural::exact_from(result).into_limbs_asc(); expected_ys.resize(len, 0); assert_eq!(&ys[..len], expected_ys.as_slice()); }); } #[test] fn limbs_vec_and_pos_neg_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, mut ys)| { let ys_old = ys.clone(); limbs_vec_and_pos_neg_in_place_right(&xs, &mut ys); let len = xs.len(); let result = Integer::from(Natural::from_owned_limbs_asc(xs)) & -Natural::from_owned_limbs_asc(ys_old); let mut expected_limbs = Natural::exact_from(result).into_limbs_asc(); expected_limbs.resize(len, 0); ys.resize(len, 0); assert_eq!(ys, expected_limbs); }); } #[test] fn limbs_and_neg_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_and_neg_neg(&xs, &ys)), -Natural::from_owned_limbs_asc(xs) & -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_and_neg_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_34().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); let b = limbs_and_neg_neg_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); let result = Natural::exact_from( -(-Natural::from_owned_limbs_asc(xs) & -Natural::from_owned_limbs_asc(ys)), ); let mut expected_out = result.to_limbs_asc(); expected_out.resize(len, 0); assert_eq!(&out[..len], expected_out.as_slice()); assert_eq!(b, Natural::from_owned_limbs_asc(expected_out) == result); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_slice_and_neg_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_9().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); let b = limbs_slice_and_neg_neg_in_place_left(&mut xs, &ys); let len = xs_old.len(); let result = Natural::exact_from( -(-Natural::from_owned_limbs_asc(xs_old) & -Natural::from_owned_limbs_asc(ys)), ); let mut expected_xs = result.to_limbs_asc(); expected_xs.resize(len, 0); assert_eq!(xs, expected_xs.as_slice()); assert_eq!(b, Natural::from_owned_limbs_asc(expected_xs) == result); }); } #[test] fn limbs_vec_and_neg_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_vec_and_neg_neg_in_place_left(&mut xs, &ys); assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(xs_old) & -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_slice_and_neg_neg_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let (right, b) = limbs_slice_and_neg_neg_in_place_either(&mut xs, &mut ys); let len = max(xs_old.len(), ys_old.len()); let result = Natural::exact_from( -(-Natural::from_limbs_asc(&xs_old) & -Natural::from_limbs_asc(&ys_old)), ); let mut expected_limbs = result.to_limbs_asc(); expected_limbs.resize(len, 0); assert_eq!(b, Natural::from_limbs_asc(&expected_limbs) == result); if right { assert_eq!(ys, expected_limbs.as_slice()); assert_eq!(xs, xs_old); } else { assert_eq!(xs, expected_limbs.as_slice()); assert_eq!(ys, ys_old); } }); } #[test] fn limbs_vec_and_neg_neg_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_vec_and_neg_neg_in_place_either(&mut xs, &mut ys); let expected = -Natural::from_limbs_asc(&xs_old) & -Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(-Natural::from_owned_limbs_asc(ys), expected); } else { assert_eq!(-Natural::from_owned_limbs_asc(xs), expected); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn and_properties() { integer_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() & y.clone(); let result_val_ref = x.clone() & &y; let result_ref_val = &x & y.clone(); let result = &x & &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x &= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x &= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x &= rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), result); assert_eq!( Integer::from(&(rug::Integer::from(&x) & rug::Integer::from(&y))), result ); assert_eq!(integer_and_alt_1(&x, &y), result); assert_eq!(integer_and_alt_2(&x, &y), result); assert_eq!(&y & &x, result); assert_eq!(&result & &x, result); assert_eq!(&result & &y, result); assert_eq!(!(!x | !y), result); }); integer_gen().test_properties(|x| { assert_eq!(&x & Integer::ZERO, 0); assert_eq!(Integer::ZERO & &x, 0); assert_eq!(&x & &x, x); assert_eq!(&x & !&x, 0); }); integer_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x & &y) & &z, x & (y & z)); }); signed_pair_gen::().test_properties(|(i, j)| { assert_eq!(Integer::from(i) & Integer::from(j), i & j); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) & Integer::from(&y), x & y); }); } ================================================ FILE: malachite-nz/tests/integer/logic/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_unsigned_bool_triple_gen_var_1; use rug; use std::str::FromStr; #[test] fn test_assign_bit() { let test = |u, index, bit, out| { let mut n = Integer::from_str(u).unwrap(); n.assign_bit(index, bit); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = rug::Integer::from_str(u).unwrap(); n.set_bit(u32::exact_from(index), bit); assert_eq!(n.to_string(), out); }; test("0", 10, true, "1024"); test("100", 0, true, "101"); test("1000000000000", 10, true, "1000000001024"); test( "1000000000000", 100, true, "1267650600228229402496703205376", ); test("5", 100, true, "1267650600228229401496703205381"); test("0", 10, false, "0"); test("0", 100, false, "0"); test("1024", 10, false, "0"); test("101", 0, false, "100"); test("1000000001024", 10, false, "1000000000000"); test("1000000001024", 100, false, "1000000001024"); test( "1267650600228229402496703205376", 100, false, "1000000000000", ); test("1267650600228229401496703205381", 100, false, "5"); } #[test] fn assign_bit_properties() { integer_unsigned_bool_triple_gen_var_1().test_properties(|(n, index, bit)| { let mut mut_n = n.clone(); mut_n.assign_bit(index, bit); assert!(mut_n.is_valid()); let result = mut_n; let mut rug_n = rug::Integer::from(&n); rug_n.set_bit(u32::exact_from(index), bit); assert_eq!(Integer::from(&rug_n), result); }); } ================================================ FILE: malachite-nz/tests/integer/logic/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2Sub, NegModPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::{BitBlockAccess, LowMask, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::large_type_gen_var_4; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_block_access::limbs_neg_assign_bits; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_4, integer_gen_var_7, integer_unsigned_natural_triple_gen, integer_unsigned_unsigned_natural_quadruple_gen_var_1, natural_gen, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_natural_quadruple_gen_var_1, }; use std::str::FromStr; fn verify_limbs_neg_assign_bits(xs: &[Limb], start: u64, end: u64, bits: &[Limb], out: &[Limb]) { let old_n = -Natural::from_limbs_asc(xs); let mut n = old_n.clone(); let bits = Natural::from_limbs_asc(bits); n.assign_bits(start, end, &bits); let result = n; assert_eq!(-Natural::from_limbs_asc(out), result); let mut n = old_n; assign_bits_naive::(&mut n, start, end, &bits); assert_eq!(n, result); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_assign_bits() { let test = |xs: &[Limb], start: u64, end: u64, bits: &[Limb], out: &[Limb]| { let mut limbs = xs.to_vec(); limbs_neg_assign_bits(&mut limbs, start, end, bits); assert_eq!(limbs, out); verify_limbs_neg_assign_bits(xs, start, end, bits, out); }; test(&[1], 0, 1, &[1], &[1]); test(&[1], 1, 2, &[1], &[1]); test(&[1], 0, 1, &[0, 1], &[2]); test(&[123], 64, 128, &[456], &[123, 0, 4294966839, u32::MAX]); test(&[123], 80, 100, &[456], &[123, 0, 4265017344, 15]); test( &[123, 456], 80, 100, &[789, 321], &[123, 456, 4243193856, 15], ); test( &[1619367413, 294928230], 73, 89, &[4211621339, 3627566573, 1208090001, 4045783696, 2932656682, 177881999, 898588654], &[1619367413, 294928230, 25446400], ); test( &[1404969050, 495263765, 2378891263, 1299524786, 1654909014, 2724647948], 21, 32, &[ 3269073749, 1170977875, 2823122906, 144832001, 3738801070, 1107604886, 4260406413, 1766163855, 592730267, 484513503, 1204041536, 3664297641, ], &[2505973850, 495263765, 2378891263, 1299524786, 1654909014, 2724647948], ); test( &[ 4126931041, 1467617913, 1718397261, 904474857, 312429577, 2397873671, 3967827549, 3842236128, 3414636734, 1846949256, 1999024107, 424639176, ], 27, 77, &[977841009], &[ 1979447393, 4264409764, 1718403071, 904474857, 312429577, 2397873671, 3967827549, 3842236128, 3414636734, 1846949256, 1999024107, 424639176, ], ); test(&[123, 456], 0, 100, &[], &[0, 0, 0, 16]); } #[test] #[should_panic] fn limbs_neg_assign_bits_fail_1() { let mut xs = vec![123]; limbs_neg_assign_bits(&mut xs, 10, 5, &[456]); } #[test] #[should_panic] fn limbs_neg_assign_bits_fail_2() { let mut xs = vec![123]; limbs_neg_assign_bits(&mut xs, 10, 10, &[456]); } #[test] #[should_panic] fn limbs_neg_assign_bits_fail_3() { let mut xs = vec![]; limbs_neg_assign_bits(&mut xs, 10, 10, &[456]); } #[test] fn test_assign_bits() { let test = |s, start, end, t, out| { let u = Integer::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.assign_bits(start, end, &v); assert_eq!(n, Integer::from_str(out).unwrap()); let mut n = u; assign_bits_naive(&mut n, start, end, &v); assert_eq!(n, Integer::from_str(out).unwrap()); }; test("123", 10, 10, "456", "123"); test("123", 5, 7, "456", "27"); test("123", 64, 128, "456", "8411715297611555537019"); test("123", 80, 100, "456", "551270173744270903666016379"); test( "1000000000000", 80, 100, "456", "551270173744271903666016256", ); test( "456", 80, 100, "1000000000000", "401092572728463209067316249032", ); test( "1000000000000", 80, 100, "2000000000000", "802185145456926419134632497152", ); test("-123", 10, 10, "456", "-123"); test("-123", 5, 7, "456", "-123"); test( "-123", 64, 128, "456", "-340282366920938455033212565746503123067", ); test("-123", 80, 100, "456", "-1267098121128665515963862483067"); test( "-1000000000000", 80, 100, "456", "-1267098121128665516963862482944", ); test( "-456", 80, 100, "1000000000000", "-866556818573946577800212251080", ); test( "-1000000000000", 80, 100, "2000000000000", "-465464245845483369732896002048", ); test("-123", 0, 100, "0", "-1267650600228229401496703205376"); } #[test] #[should_panic] fn assign_bits_fail() { let mut n = Integer::from(123u32); n.assign_bits(10, 5, &Natural::from(456u32)); } #[test] fn limbs_assign_neg_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_4().test_properties_with_config(&config, |(xs_in, start, end, ref bits)| { let mut xs = xs_in.to_vec(); limbs_neg_assign_bits(&mut xs, start, end, bits); verify_limbs_neg_assign_bits(&xs_in, start, end, bits, &xs); }); } #[test] fn assign_bits_properties() { integer_unsigned_unsigned_natural_quadruple_gen_var_1().test_properties( |(n, start, end, bits)| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(start, end, &bits); let result = n; let mut n = old_n.clone(); assign_bits_naive(&mut n, start, end, &bits); assert_eq!(n, result); n.assign_bits(start, end, &bits); assert_eq!(n, result); let bits_width = end - start; assert_eq!(n.get_bits(start, end), (&bits).mod_power_of_2(bits_width)); let mut n = !old_n; let not_bits = bits .neg_mod_power_of_2(bits_width) .mod_power_of_2_sub(Natural::ONE, bits_width); n.assign_bits(start, end, ¬_bits); assert_eq!(!n, result); }, ); integer_unsigned_natural_triple_gen().test_properties(|(n, start, bits)| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(start, start, &bits); assert_eq!(n, old_n); }); natural_unsigned_pair_gen_var_4().test_properties(|(bits, start)| { let mut n = Integer::ZERO; n.assign_bits(start, start + bits.significant_bits(), &bits); assert_eq!(n, bits << start); }); integer_gen().test_properties(|n| { let old_n = n; let mut n = old_n.clone(); let significant_bits = old_n.significant_bits(); n.assign_bits( 0, significant_bits, &(&old_n).mod_power_of_2(significant_bits), ); assert_eq!(n, old_n); }); integer_gen_var_4().test_properties(|n| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(0, old_n.significant_bits(), &Natural::ZERO); assert_eq!(n, 0); }); integer_gen_var_7().test_properties(|n| { let old_n = n; let mut n = old_n.clone(); let significant_bits = old_n.significant_bits(); n.assign_bits(0, significant_bits, &Natural::low_mask(significant_bits)); assert_eq!(n, -1); }); natural_gen().test_properties(|n| { let old_n = n; let mut n = Integer::ZERO; n.assign_bits(0, old_n.significant_bits(), &old_n); assert_eq!(n, old_n); }); natural_unsigned_unsigned_natural_quadruple_gen_var_1().test_properties( |(n, start, end, bits)| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(start, end, &bits); let result = n; let mut n = Integer::from(old_n); n.assign_bits(start, end, &bits); assert_eq!(n, result); }, ); } ================================================ FILE: malachite-nz/tests/integer/logic/bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitConvertible, BitIterable, SignificantBits}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen_var_5}; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{ integer_bool_vec_pair_gen_var_2, integer_unsigned_pair_gen_var_2, }; #[test] fn test_bits() { let n = Integer::from(-105); let mut bits = n.bits(); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); assert_eq!(bits[0], true); assert_eq!(bits[1], true); assert_eq!(bits[2], true); assert_eq!(bits[3], false); assert_eq!(bits[4], true); assert_eq!(bits[5], false); assert_eq!(bits[6], false); assert_eq!(bits[7], true); assert_eq!(bits[8], true); let mut bits = n.bits(); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); } #[test] fn bits_properties() { integer_bool_vec_pair_gen_var_2().test_properties(|(n, bs)| { let mut bits = n.bits(); let mut bit_vec = Vec::new(); let mut i = 0; for b in bs { if b { bit_vec.insert(i, bits.next().unwrap()); i += 1; } else { bit_vec.insert(i, bits.next_back().unwrap()); } } assert!(bits.next().is_none()); assert!(bits.next_back().is_none()); assert_eq!(n.to_bits_asc(), bit_vec); }); integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { if u < n.significant_bits() { assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]); } else { assert_eq!(n.bits()[u], n < 0); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(Integer::ZERO.bits()[u], false); }); signed_gen::().test_properties(|i| { assert!(i.bits().eq(Integer::from(i).bits())); }); } ================================================ FILE: malachite-nz/tests/integer/logic/checked_count_ones.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::CountOnes; use malachite_base::test_util::generators::signed_gen_var_2; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::checked_count_ones::{ integer_checked_count_ones_alt_1, integer_checked_count_ones_alt_2, }; use std::str::FromStr; #[test] fn test_checked_count_ones() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.checked_count_ones(), out); assert_eq!(integer_checked_count_ones_alt_1(&u), out); assert_eq!(integer_checked_count_ones_alt_2(&u), out); }; test("0", Some(0)); test("105", Some(4)); test("-105", None); test("1000000000000", Some(13)); test("-1000000000000", None); test("4294967295", Some(32)); test("-4294967295", None); test("4294967296", Some(1)); test("-4294967296", None); test("18446744073709551615", Some(64)); test("-18446744073709551615", None); test("18446744073709551616", Some(1)); test("-18446744073709551616", None); } #[test] fn checked_count_ones_properties() { integer_gen().test_properties(|x| { let ones = x.checked_count_ones(); assert_eq!(integer_checked_count_ones_alt_1(&x), ones); assert_eq!(integer_checked_count_ones_alt_2(&x), ones); assert_eq!(ones == Some(0), x == 0); assert_eq!((!x).checked_count_zeros(), ones); }); signed_gen_var_2::().test_properties(|i| { assert_eq!( Integer::from(i).checked_count_ones(), Some(CountOnes::count_ones(i)) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/checked_count_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::CountZeros; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_gen_var_4, unsigned_vec_gen_var_2, unsigned_vec_gen_var_4, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::checked_count_zeros::limbs_count_zeros_neg; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::checked_count_zeros::{ integer_checked_count_zeros_alt_1, integer_checked_count_zeros_alt_2, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_count_zeros_neg() { let test = |xs, out| { assert_eq!(limbs_count_zeros_neg(xs), out); }; test(&[0, 1, 2], 33); test(&[1, u32::MAX], 32); } #[test] fn test_checked_count_zeros() { let test = |s, out| { let u = Integer::from_str(s).unwrap(); assert_eq!(u.checked_count_zeros(), out); assert_eq!(integer_checked_count_zeros_alt_1(&u), out); assert_eq!(integer_checked_count_zeros_alt_2(&u), out); }; test("0", None); test("105", None); test("-105", Some(3)); test("1000000000000", None); test("-1000000000000", Some(24)); test("4294967295", None); test("-4294967295", Some(31)); test("4294967296", None); test("-4294967296", Some(32)); test("18446744073709551615", None); test("-18446744073709551615", Some(63)); test("18446744073709551616", None); test("-18446744073709551616", Some(64)); } #[test] fn limbs_count_zeros_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_4().test_properties_with_config(&config, |xs| { limbs_count_zeros_neg(&xs); }); unsigned_vec_gen_var_2().test_properties_with_config(&config, |xs| { assert_eq!( Some(limbs_count_zeros_neg(&xs)), (-Natural::from_owned_limbs_asc(xs)).checked_count_zeros() ); }); } #[test] fn checked_count_zeros_properties() { integer_gen().test_properties(|x| { let zeros = x.checked_count_zeros(); assert_eq!(integer_checked_count_zeros_alt_1(&x), zeros); assert_eq!(integer_checked_count_zeros_alt_2(&x), zeros); assert_eq!((!x).checked_count_ones(), zeros); }); signed_gen_var_4::().test_properties(|i| { assert_eq!( Integer::from(i).checked_count_zeros(), Some(CountZeros::count_zeros(i)) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/checked_hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::logic::traits::{CheckedHammingDistance, HammingDistance}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_pair_gen, unsigned_vec_pair_gen_var_8, unsigned_vec_unsigned_pair_gen_var_19, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::checked_hamming_distance::{ limbs_hamming_distance_limb_neg, limbs_hamming_distance_neg, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen_var_1, natural_pair_gen, }; use malachite_nz::test_util::integer::logic::checked_hamming_distance::{ integer_checked_hamming_distance_alt_1, integer_checked_hamming_distance_alt_2, rug_checked_hamming_distance, }; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_hamming_distance_limb_neg() { let test = |xs, y, out| { assert_eq!(limbs_hamming_distance_limb_neg(xs, y), out); }; test(&[2], 2, 0); test(&[1, 1, 1], 1, 2); test(&[1, 1, 1], 2, 3); test(&[1, 2, 3], 3, 4); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_hamming_distance_limb_neg_fail() { limbs_hamming_distance_limb_neg(&[], 5); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_hamming_distance_neg() { let test = |xs, ys, out| { assert_eq!(limbs_hamming_distance_neg(xs, ys), out); }; test(&[2], &[3], 2); test(&[1, 1, 1], &[1, 2, 3], 3); test(&[1, 1, 1], &[1, 2, 3, 4], 4); test(&[1, 2, 3, 4], &[1, 1, 1], 4); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_hamming_distance_neg_fail_1() { limbs_hamming_distance_neg(&[0, 0], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_hamming_distance_neg_fail_2() { limbs_hamming_distance_neg(&[1, 2, 3], &[0, 0]); } #[test] fn test_checked_hamming_distance() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.checked_hamming_distance(&v), out); assert_eq!(integer_checked_hamming_distance_alt_1(&u, &v), out); assert_eq!(integer_checked_hamming_distance_alt_2(&u, &v), out); assert_eq!( rug_checked_hamming_distance( &rug::Integer::from_str(s).unwrap(), &rug::Integer::from_str(t).unwrap(), ), out ); }; test("105", "123", Some(2)); test("1000000000000", "0", Some(13)); test("4294967295", "0", Some(32)); test("4294967295", "4294967295", Some(0)); test("4294967295", "4294967296", Some(33)); test("1000000000000", "1000000000001", Some(1)); test("-105", "-123", Some(2)); test("-1000000000000", "-1", Some(24)); test("-4294967295", "-1", Some(31)); test("-4294967295", "-4294967295", Some(0)); test("-4294967295", "-4294967296", Some(1)); test("-1000000000000", "-1000000000001", Some(13)); test("-105", "123", None); test("-1000000000000", "0", None); test("-4294967295", "0", None); test("-4294967295", "4294967295", None); test("-4294967295", "4294967296", None); test("-1000000000000", "1000000000001", None); test("105", "-123", None); test("1000000000000", "-1", None); test("4294967295", "-1", None); test("4294967295", "-4294967295", None); test("4294967295", "-4294967296", None); test("1000000000000", "-1000000000001", None); } #[test] fn limbs_hamming_distance_limb_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_19().test_properties_with_config(&config, |(xs, y)| { assert_eq!( Some(limbs_hamming_distance_limb_neg(&xs, y)), (-Natural::from_owned_limbs_asc(xs)).checked_hamming_distance(&-Natural::from(y)), ); }); } #[test] fn limbs_hamming_distance_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( Some(limbs_hamming_distance_neg(&xs, &ys)), (-Natural::from_owned_limbs_asc(xs)) .checked_hamming_distance(&-Natural::from_owned_limbs_asc(ys)), ); }); } #[test] fn checked_hamming_distance_properties() { integer_pair_gen().test_properties(|(x, y)| { let distance = x.checked_hamming_distance(&y); assert_eq!( rug_checked_hamming_distance(&rug::Integer::from(&x), &rug::Integer::from(&y)), distance ); assert_eq!(y.checked_hamming_distance(&x), distance); assert_eq!(integer_checked_hamming_distance_alt_1(&x, &y), distance); assert_eq!(integer_checked_hamming_distance_alt_2(&x, &y), distance); assert_eq!(distance == Some(0), x == y); assert_eq!((&x ^ &y).checked_count_ones(), distance); assert_eq!((!x).checked_hamming_distance(&!y), distance); }); integer_triple_gen_var_1().test_properties(|(x, y, z)| { assert!( x.checked_hamming_distance(&z).unwrap() <= x.checked_hamming_distance(&y).unwrap() + y.checked_hamming_distance(&z).unwrap() ); let x = !x; let y = !y; let z = !z; assert!( x.checked_hamming_distance(&z).unwrap() <= x.checked_hamming_distance(&y).unwrap() + y.checked_hamming_distance(&z).unwrap() ); }); integer_gen().test_properties(|n| { assert_eq!(n.checked_hamming_distance(&n), Some(0)); assert_eq!( n.checked_hamming_distance(&Integer::ZERO), n.checked_count_ones() ); assert_eq!( n.checked_hamming_distance(&Integer::NEGATIVE_ONE), n.checked_count_zeros() ); assert_eq!( Integer::ZERO.checked_hamming_distance(&n), n.checked_count_ones() ); assert_eq!( Integer::NEGATIVE_ONE.checked_hamming_distance(&n), n.checked_count_zeros() ); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!( Some(x.hamming_distance(&y)), Integer::from(x).checked_hamming_distance(&Integer::from(y)), ); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!( Integer::from(x).checked_hamming_distance(&Integer::from(y)), x.checked_hamming_distance(y) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitAccess, NotAssign}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_access::{ limbs_slice_clear_bit_neg, limbs_vec_clear_bit_neg, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_21, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_clear_bit_neg() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_slice_clear_bit_neg(&mut mut_xs, index); assert_eq!(mut_xs, out); }; test(&[3, 2, 1], 0, &[4, 2, 1]); test(&[0, 0, 3], 32, &[0, 0, 3]); test(&[0, 3, 2, 1], 64, &[0, 3, 3, 1]); test(&[0, 0, 0xfffffffd], 64, &[0, 0, u32::MAX - 1]); test(&[0xfffffff7], 3, &[u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_clear_bit_fail_1() { let mut mut_xs = vec![0, 0, u32::MAX]; limbs_slice_clear_bit_neg(&mut mut_xs, 64); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_clear_bit_fail_2() { let mut mut_xs = vec![3, 2, 1]; limbs_slice_clear_bit_neg(&mut mut_xs, 100); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_clear_bit_neg() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_vec_clear_bit_neg(&mut mut_xs, index); assert_eq!(mut_xs, out); }; test(&[3, 2, 1], 0, &[4, 2, 1]); test(&[0, 0, 3], 32, &[0, 0, 3]); test(&[0, 3, 2, 1], 64, &[0, 3, 3, 1]); test(&[0, 0, 0xfffffffd], 64, &[0, 0, u32::MAX - 1]); test(&[0, 0, u32::MAX], 64, &[0, 0, 0, 1]); test(&[3, 2, 1], 100, &[3, 2, 1, 16]); test(&[0xfffffff7], 3, &[u32::MAX]); test(&[0xfffffff8], 3, &[0, 1]); } #[test] fn test_clear_bit() { let test = |u, index, out| { let mut n = Integer::from_str(u).unwrap(); n.clear_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 10, "0"); test("0", 100, "0"); test("1024", 10, "0"); test("101", 0, "100"); test("1000000001024", 10, "1000000000000"); test("1000000001024", 100, "1000000001024"); test("1267650600228229402496703205376", 100, "1000000000000"); test("1267650600228229401496703205381", 100, "5"); test("-1", 5, "-33"); test("-1", 100, "-1267650600228229401496703205377"); test("-31", 0, "-32"); test("-999999998976", 10, "-1000000000000"); test("-1000000000000", 100, "-1267650600228229402496703205376"); test("-18446744078004518912", 0, "-18446744078004518912"); test("-18446744078004518912", 32, "-18446744082299486208"); test("-18446744078004518912", 33, "-18446744086594453504"); test("-18446744078004518912", 64, "-18446744078004518912"); test("-18446744078004518912", 65, "-55340232225423622144"); test("-36893488143124135936", 32, "-36893488147419103232"); test("-4294967295", 0, "-4294967296"); test("-4294967287", 3, "-4294967295"); test("-4294967288", 3, "-4294967296"); } #[test] fn limbs_slice_clear_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_21().test_properties_with_config( &config, |(mut xs, index)| { let mut n = -Natural::from_limbs_asc(&xs); limbs_slice_clear_bit_neg(&mut xs, index); n.clear_bit(index); assert_eq!(-Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn limbs_vec_clear_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config( &config, |(mut xs, index)| { let mut n = -Natural::from_limbs_asc(&xs); limbs_vec_clear_bit_neg(&mut xs, index); n.clear_bit(index); assert_eq!(-Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn clear_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.clear_bit(index); assert!(mut_n.is_valid()); let result = mut_n; let mut mut_n = n.clone(); mut_n.assign_bit(index, false); assert_eq!(mut_n, result); assert_eq!(&n & !Integer::power_of_2(index), result); assert!(result <= n); if n.get_bit(index) { assert_ne!(result, n); let mut mut_result = result.clone(); mut_result.set_bit(index); assert_eq!(mut_result, n); } else { assert_eq!(result, n); } let mut mut_not_n = !n; mut_not_n.set_bit(index); mut_not_n.not_assign(); assert_eq!(mut_not_n, result); }); } ================================================ FILE: malachite-nz/tests/integer/logic/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use rug; use std::str::FromStr; #[test] fn test_flip_bit() { let test = |u, index, out| { let mut n = Integer::from_str(u).unwrap(); n.flip_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = rug::Integer::from_str(u).unwrap(); n.toggle_bit(u32::exact_from(index)); assert_eq!(n.to_string(), out); }; test("0", 10, "1024"); test("1024", 10, "0"); test("100", 0, "101"); test("101", 0, "100"); test("1000000000000", 10, "1000000001024"); test("1000000001024", 10, "1000000000000"); test("1000000000000", 100, "1267650600228229402496703205376"); test("1267650600228229402496703205376", 100, "1000000000000"); test("5", 100, "1267650600228229401496703205381"); test("1267650600228229401496703205381", 100, "5"); test("-4294967296", 0, "-4294967295"); test("-4294967295", 0, "-4294967296"); } #[test] fn flip_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.flip_bit(index); assert!(mut_n.is_valid()); let result = mut_n; assert_ne!(result, n); let mut rug_n = rug::Integer::from(&n); rug_n.toggle_bit(u32::exact_from(index)); assert_eq!(Integer::from(&rug_n), result); let mut mut_result = result.clone(); mut_result.flip_bit(index); assert_eq!(mut_result, n); assert_eq!(n ^ Integer::power_of_2(index), result); }); } ================================================ FILE: malachite-nz/tests/integer/logic/from_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::logic::traits::BitConvertible; use malachite_base::test_util::generators::bool_vec_gen; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_desc_alt, }; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::integer::logic::from_bits::{ from_bits_asc_naive, from_bits_desc_naive, }; #[test] fn test_from_bits_asc_and_from_bit_iterator_asc() { let test = |bits: &[bool], out| { let x = Integer::from_bits_asc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(&[], "0"); test(&[false], "0"); test(&[false, false, false], "0"); test(&[true, false], "1"); test(&[true], "-1"); test(&[true, true, true], "-1"); test(&[false, true, true, false], "6"); test(&[false, true, false, true], "-6"); test(&[true, false, false, true, false, true, true, false], "105"); test( &[true, false, false, true, false, true, true, false, false], "105", ); test( &[true, false, false, true, false, true, true, false, false, false], "105", ); test(&[true, true, true, false, true, false, false, true], "-105"); test( &[ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, false, ], "1000000000000", ); test( &[ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, false, false, ], "1000000000000", ); test( &[ false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, false, true, true, false, true, false, true, true, false, true, false, true, false, false, true, true, true, false, true, false, false, false, true, ], "-1000000000000", ); } #[test] fn test_from_bits_desc() { let test = |bits: &[bool], out| { let x = Integer::from_bits_desc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(&[], "0"); test(&[false], "0"); test(&[false, false, false], "0"); test(&[false, true], "1"); test(&[true], "-1"); test(&[true, true, true], "-1"); test(&[false, true, true, false], "6"); test(&[true, false, true, false], "-6"); test(&[false, true, true, false, true, false, false, true], "105"); test( &[false, false, true, true, false, true, false, false, true], "105", ); test( &[false, false, false, true, true, false, true, false, false, true], "105", ); test(&[true, false, false, true, false, true, true, true], "-105"); test( &[true, true, true, false, false, true, false, true, true, true], "-105", ); test( &[ false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], "1000000000000", ); test( &[ false, false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], "1000000000000", ); test( &[ true, false, false, false, true, false, true, true, true, false, false, true, false, true, false, true, true, false, true, false, true, true, false, true, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, ], "-1000000000000", ); } #[test] fn from_bits_asc_properties() { bool_vec_gen().test_properties(|bits| { let x = Integer::from_bits_asc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(from_bits_asc_naive(bits.iter().copied()), x); assert_eq!(from_bits_asc_alt::(bits.iter().copied()), x); assert_eq!(Integer::from_bits_desc(bits.iter().copied().rev()), x); assert_eq!(bits.iter().all(|b| !b), x == 0); if SignedLimb::convertible_from(&x) { assert_eq!(SignedLimb::from_bits_asc(bits.into_iter()), x); } }); } #[test] fn from_bits_desc_properties() { bool_vec_gen().test_properties(|bits| { let x = Integer::from_bits_desc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(from_bits_desc_naive(bits.iter().copied()), x); assert_eq!(from_bits_desc_alt::(bits.iter().copied()), x); assert_eq!(Integer::from_bits_asc(bits.iter().copied().rev()), x); assert_eq!(bits.iter().all(|b| !b), x == 0); if SignedLimb::convertible_from(&x) { assert_eq!(SignedLimb::from_bits_desc(bits.into_iter()), x); } }); } ================================================ FILE: malachite-nz/tests/integer/logic/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_vec_unsigned_pair_gen_var_18, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_access::limbs_get_bit_neg; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen_var_4, integer_unsigned_pair_gen_var_2}; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_get_bit_neg() { let test = |xs: &[Limb], index: u64, out: bool| { assert_eq!(limbs_get_bit_neg(xs, index), out); }; test(&[1], 0, true); test(&[1], 100, true); test(&[123], 2, true); test(&[123], 3, false); test(&[123], 100, true); test(&[0, 0b1011], 0, false); test(&[0, 0b1011], 32, true); test(&[0, 0b1011], 33, false); test(&[0, 0b1011], 34, true); test(&[0, 0b1011], 35, false); test(&[0, 0b1011], 100, true); test(&[1, 0b1011], 0, true); test(&[1, 0b1011], 32, false); test(&[1, 0b1011], 33, false); test(&[1, 0b1011], 34, true); test(&[1, 0b1011], 35, false); test(&[1, 0b1011], 100, true); } #[test] fn test_get_bit() { let test = |n, index, out| { assert_eq!(Integer::from_str(n).unwrap().get_bit(index), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .get_bit(u32::exact_from(index)), out ); }; test("0", 0, false); test("0", 100, false); test("123", 2, false); test("123", 3, true); test("123", 100, false); test("-123", 0, true); test("-123", 1, false); test("-123", 100, true); test("1000000000000", 12, true); test("1000000000000", 100, false); test("-1000000000000", 12, true); test("-1000000000000", 100, true); test("4294967295", 31, true); test("4294967295", 32, false); test("4294967296", 31, false); test("4294967296", 32, true); test("4294967296", 33, false); test("-4294967295", 0, true); test("-4294967295", 1, false); test("-4294967295", 31, false); test("-4294967295", 32, true); test("-4294967295", 33, true); test("-4294967296", 0, false); test("-4294967296", 31, false); test("-4294967296", 32, true); test("-4294967296", 33, true); } #[test] fn limbs_get_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(xs, index)| { assert_eq!( (-Natural::from_limbs_asc(&xs)).get_bit(index), limbs_get_bit_neg(&xs, index) ); }); } #[test] fn get_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, index)| { let bit = n.get_bit(index); assert_eq!(rug::Integer::from(&n).get_bit(u32::exact_from(index)), bit); assert_eq!(&n & Integer::power_of_2(index) != 0, bit); assert_eq!(!(!n).get_bit(index), bit); }); integer_gen_var_4().test_properties(|n| { let significant_bits = n.significant_bits(); assert!(!n.get_bit(significant_bits)); if n != 0 { assert!(n.get_bit(significant_bits - 1)); } }); signed_unsigned_pair_gen_var_1::().test_properties(|(i, index)| { assert_eq!(Integer::from(i).get_bit(index), i.get_bit(index)); }); } ================================================ FILE: malachite-nz/tests/integer/logic/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{BitBlockAccess, LowMask, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_unsigned_unsigned_triple_gen_var_2, unsigned_pair_gen_var_7, unsigned_triple_gen_var_20, unsigned_vec_unsigned_unsigned_triple_gen_var_4, }; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_block_access::{ limbs_neg_limb_get_bits, limbs_slice_neg_get_bits, limbs_vec_neg_get_bits, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_unsigned_pair_gen_var_2, integer_unsigned_unsigned_triple_gen_var_2, natural_unsigned_unsigned_triple_gen_var_4, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] fn verify_limbs_neg_limb_get_bits(x: Limb, start: u64, end: u64, out: &[Limb]) { let n = -Natural::from(x); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_limbs_asc(out), result); } #[cfg(feature = "32_bit_limbs")] fn verify_limbs_neg_get_bits(xs: &[Limb], start: u64, end: u64, out: &[Limb]) { let n = -Natural::from_limbs_asc(xs); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_limbs_asc(out), result); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_limb_get_bits() { let test = |x: Limb, start: u64, end: u64, out: &[Limb]| { assert_eq!(limbs_neg_limb_get_bits(x, start, end), out); verify_limbs_neg_limb_get_bits(x, start, end, out); }; // - trailing_zeros < end // - start >= Limb::WIDTH test(1, 40, 50, &[0x3ff]); // - start < Limb::WIDTH // - trailing_zeros < start test(0x12345678, 16, 48, &[0xffffedcb]); test(0x12345678, 4, 16, &[0xa98]); // - trailing_zeros >= start test(0x12345678, 0, 100, &[0xedcba988, u32::MAX, u32::MAX, 0xf]); test(0x12345678, 10, 10, &[]); // - trailing_zeros >= end test(0x80000000, 5, 10, &[]); } #[test] #[should_panic] fn limbs_neg_limb_get_bits_fail() { limbs_neg_limb_get_bits(123, 10, 5); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_neg_get_bits() { let test = |xs: &[Limb], start: u64, end: u64, out: &[Limb]| { assert_eq!(limbs_slice_neg_get_bits(xs, start, end), out); verify_limbs_neg_get_bits(xs, start, end, out); }; // - trailing_zeros < end // - limb_start >= len test(&[1], 40, 50, &[0x3ff]); // - limb_start < len // - limb_end >= len // - offset != 0 // - trailing_zeros < start test(&[0x12345678, 0xabcdef01], 16, 48, &[0x10feedcb]); // - limb_end < len test(&[0x12345678, 0xabcdef01], 4, 16, &[0xa98]); // - offset == 0 // - trailing_zeros >= start test( &[0x12345678, 0xabcdef01], 0, 100, &[0xedcba988, 0x543210fe, u32::MAX, 0xf], ); test(&[0x12345678, 0xabcdef01], 10, 10, &[]); // - trailing_zeros >= end test(&[0, 0x80000000], 5, 10, &[]); } #[test] #[should_panic] fn limbs_slice_neg_get_bits_fail() { limbs_slice_neg_get_bits(&[123], 10, 5); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_neg_get_bits() { let test = |xs: &[Limb], start: u64, end: u64, out: &[Limb]| { assert_eq!(limbs_vec_neg_get_bits(xs.to_vec(), start, end), out); verify_limbs_neg_get_bits(xs, start, end, out); }; test(&[1], 40, 50, &[0x3ff]); test(&[0x12345678, 0xabcdef01], 16, 48, &[0x10feedcb]); test(&[0x12345678, 0xabcdef01], 4, 16, &[0xa98]); test( &[0x12345678, 0xabcdef01], 0, 100, &[0xedcba988, 0x543210fe, u32::MAX, 0xf], ); test(&[0x12345678, 0xabcdef01], 10, 10, &[]); test(&[0, 0x80000000], 5, 10, &[]); } #[test] #[should_panic] fn limbs_vec_neg_get_bits_fail() { limbs_vec_neg_get_bits(vec![123], 10, 5); } #[test] fn test_get_bits() { let test = |s, start, end, out| { let u = Integer::from_str(s).unwrap(); let out = Natural::from_str(out).unwrap(); assert_eq!(u.get_bits(start, end), out); assert_eq!(u.clone().get_bits_owned(start, end), out); assert_eq!(get_bits_naive::(&u, start, end), out); }; test("12379813738590787192", 16, 48, "4009824820"); test("12379813738590787192", 4, 16, "1383"); test("12379813738590787192", 0, 100, "12379813738590787192"); test("12379813738590787192", 10, 10, "0"); test("-12379813738590787192", 16, 48, "285142475"); test("-12379813738590787192", 4, 16, "2712"); test( "-12379813738590787192", 0, 100, "1267650600215849587758112418184", ); test("-12379813738590787192", 10, 10, "0"); } #[test] #[should_panic] fn get_bits_fail() { Integer::from(123).get_bits(10, 5); } #[test] #[should_panic] fn get_bits_owned_fail() { Integer::from(123).get_bits_owned(10, 5); } #[test] fn limbs_neg_limb_get_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_triple_gen_var_20().test_properties_with_config(&config, |(x, start, end)| { let out = limbs_neg_limb_get_bits(x, start, end); let n = -Natural::from(x); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_owned_limbs_asc(out), result); }); } #[test] fn limbs_neg_get_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_4().test_properties_with_config( &config, |(xs, start, end)| { let out = limbs_slice_neg_get_bits(&xs, start, end); let n = -Natural::from_limbs_asc(&xs); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_owned_limbs_asc(out), result); let out = limbs_vec_neg_get_bits(xs.clone(), start, end); let n = -Natural::from_owned_limbs_asc(xs); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_owned_limbs_asc(out), result); }, ); } #[test] fn get_bit_properties() { integer_unsigned_unsigned_triple_gen_var_2().test_properties(|(n, start, end)| { let bits = n.get_bits(start, end); assert_eq!(n.clone().get_bits_owned(start, end), bits); assert_eq!(get_bits_naive::(&n, start, end), bits); let significant_bits = n.significant_bits(); assert_eq!( n.get_bits(start + significant_bits, end + significant_bits), if n >= 0 { Natural::ZERO } else { Natural::low_mask(end - start) } ); assert_eq!( (!&n).get_bits(start, end), Natural::low_mask(end - start) - &bits ); let mut mut_n = n.clone(); mut_n.assign_bits(start, end, &bits); assert_eq!(n, mut_n); }); integer_unsigned_pair_gen_var_2().test_properties(|(n, start)| { assert_eq!(n.get_bits(start, start), 0); }); unsigned_pair_gen_var_7().test_properties(|(start, end)| { assert_eq!(Integer::ZERO.get_bits(start, end), 0); }); natural_unsigned_unsigned_triple_gen_var_4().test_properties(|(n, start, end)| { assert_eq!( Integer::from(&n).get_bits(start, end), n.get_bits(start, end) ); }); signed_unsigned_unsigned_triple_gen_var_2::().test_properties( |(n, start, end)| { assert_eq!( Integer::from(n).get_bits(start, end), n.get_bits(start, end) ); }, ); } ================================================ FILE: malachite-nz/tests/integer/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, BitScan}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_vec_unsigned_pair_gen_var_20, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_scan::limbs_index_of_next_false_bit_neg; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_unsigned_pair_gen_var_2, natural_unsigned_pair_gen_var_4, }; use malachite_nz::test_util::integer::logic::index_of_next_false_bit::*; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_index_of_next_false_bit_neg() { let test = |xs, u, out| { assert_eq!(limbs_index_of_next_false_bit_neg(xs, u), out); }; test(&[1], 0, None); test(&[1], 100, None); test(&[0b100], 0, Some(0)); test(&[0b100], 1, Some(1)); test(&[0b100], 2, None); test(&[0b100], 3, None); test(&[0, 0b101], 0, Some(0)); test(&[0, 0b101], 20, Some(20)); test(&[0, 0b101], 31, Some(31)); test(&[0, 0b101], 32, Some(34)); test(&[0, 0b101], 33, Some(34)); test(&[0, 0b101], 34, Some(34)); test(&[0, 0b101], 35, None); test(&[0, 0b101], 100, None); test(&[0, 0, 0b101], 36, Some(36)); test(&[0, 0, 0b101], 64, Some(66)); test(&[0, 0, 0b101, 0b101], 96, Some(96)); test(&[0, 0, 0b101, 0b101], 97, Some(98)); } #[test] fn test_index_of_next_false_bit() { let test = |s, u, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.index_of_next_false_bit(u), out); assert_eq!(integer_index_of_next_false_bit_alt(&n, u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .find_zero(u32::exact_from(u)) .map(u64::from), out ); }; test("0", 0, Some(0)); test("0", 100, Some(100)); test("47244640256", 0, Some(0)); test("47244640256", 20, Some(20)); test("47244640256", 31, Some(31)); test("47244640256", 32, Some(34)); test("47244640256", 33, Some(34)); test("47244640256", 34, Some(34)); test("47244640256", 35, Some(36)); test("47244640256", 100, Some(100)); test("680564733841876926631601309731428237312", 64, Some(64)); test("680564733841876926631601309731428237312", 68, Some(129)); test("-21474836480", 0, Some(0)); test("-21474836480", 20, Some(20)); test("-21474836480", 31, Some(31)); test("-21474836480", 32, Some(34)); test("-21474836480", 33, Some(34)); test("-21474836480", 34, Some(34)); test("-21474836480", 35, None); test("-21474836480", 36, None); test("-21474836480", 100, None); test("-92233720368547758080", 36, Some(36)); test("-92233720368547758080", 64, Some(66)); test("-396140812663555408336267509760", 96, Some(96)); test("-396140812663555408336267509760", 97, Some(98)); } #[test] fn limbs_index_of_next_false_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, u)| { assert_eq!( limbs_index_of_next_false_bit_neg(&xs, u), (-Natural::from_owned_limbs_asc(xs)).index_of_next_false_bit(u) ); }); } #[test] fn index_of_next_false_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { let result = n.index_of_next_false_bit(u); assert_eq!(result, integer_index_of_next_false_bit_alt(&n, u)); assert_eq!( rug::Integer::from(&n) .find_zero(u32::exact_from(u)) .map(u64::from), result ); assert_eq!(result.is_some(), &n >> u != -1); if let Some(result) = result { assert!(result >= u); assert!(!n.get_bit(result)); assert_eq!(result == u, !n.get_bit(u)); } assert_eq!((!n).index_of_next_true_bit(u), result); }); integer_gen().test_properties(|n| { assert_eq!(n.index_of_next_false_bit(0), (!n).trailing_zeros()); }); unsigned_gen().test_properties(|u| { assert_eq!(Integer::ZERO.index_of_next_false_bit(u), Some(u)); assert_eq!(Integer::NEGATIVE_ONE.index_of_next_false_bit(u), None); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { assert_eq!( Integer::from(&n).index_of_next_false_bit(index), n.index_of_next_false_bit(index) ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(i, index)| { assert_eq!( Integer::from(i).index_of_next_false_bit(index), i.index_of_next_false_bit(index) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, BitScan}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, unsigned_gen, unsigned_vec_unsigned_pair_gen_var_20, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_scan::limbs_index_of_next_true_bit_neg; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_unsigned_pair_gen_var_2, natural_unsigned_pair_gen_var_4, }; use malachite_nz::test_util::integer::logic::index_of_next_true_bit::*; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_index_of_next_true_bit_neg() { let test = |xs, u, out| { assert_eq!(limbs_index_of_next_true_bit_neg(xs, u), out); }; test(&[1], 0, 0); test(&[1], 100, 100); test(&[0b100], 0, 2); test(&[0b100], 1, 2); test(&[0b100], 2, 2); test(&[0b100], 3, 3); test(&[0, 0b101], 0, 32); test(&[0, 0b101], 20, 32); test(&[0, 0b101], 31, 32); test(&[0, 0b101], 32, 32); test(&[0, 0b101], 33, 33); test(&[0, 0b101], 34, 35); test(&[0, 0b101], 35, 35); test(&[0, 0b101], 36, 36); test(&[0, 0b101], 100, 100); test(&[0, 0, 0b101], 64, 64); test(&[0, 0, 0b101], 66, 67); test(&[0, 0, 0b101, 0b101], 96, 97); test(&[0, 0, 0b101, 0b101], 98, 99); } #[test] fn test_index_of_next_true_bit() { let test = |s, u, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.index_of_next_true_bit(u), out); assert_eq!(integer_index_of_next_true_bit_alt(&n, u), out); assert_eq!( rug::Integer::from_str(s) .unwrap() .find_one(u32::exact_from(u)) .map(u64::from), out ); }; test("0", 0, None); test("0", 100, None); test("47244640256", 0, Some(32)); test("47244640256", 20, Some(32)); test("47244640256", 31, Some(32)); test("47244640256", 32, Some(32)); test("47244640256", 33, Some(33)); test("47244640256", 34, Some(35)); test("47244640256", 35, Some(35)); test("47244640256", 36, None); test("47244640256", 100, None); test("340282366925890223602069384504899796992", 91, Some(91)); test("340282366925890223602069384504899796992", 92, Some(128)); test("-21474836480", 0, Some(32)); test("-21474836480", 20, Some(32)); test("-21474836480", 31, Some(32)); test("-21474836480", 32, Some(32)); test("-21474836480", 33, Some(33)); test("-21474836480", 34, Some(35)); test("-21474836480", 35, Some(35)); test("-21474836480", 36, Some(36)); test("-21474836480", 100, Some(100)); test("-92233720368547758080", 64, Some(64)); test("-92233720368547758080", 66, Some(67)); test("-396140812663555408336267509760", 96, Some(97)); test("-396140812663555408336267509760", 98, Some(99)); } #[test] fn limbs_index_of_next_true_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, u)| { assert_eq!( Some(limbs_index_of_next_true_bit_neg(&xs, u)), (-Natural::from_owned_limbs_asc(xs)).index_of_next_true_bit(u) ); }); } #[test] fn index_of_next_true_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, u)| { let result = n.index_of_next_true_bit(u); assert_eq!(result, integer_index_of_next_true_bit_alt(&n, u)); assert_eq!( rug::Integer::from(&n) .find_one(u32::exact_from(u)) .map(u64::from), result ); assert_eq!(result.is_some(), &n >> u != 0); if let Some(result) = result { assert!(result >= u); assert!(n.get_bit(result)); assert_eq!(result == u, n.get_bit(u)); } assert_eq!((!n).index_of_next_false_bit(u), result); }); integer_gen().test_properties(|n| { assert_eq!(n.index_of_next_true_bit(0), n.trailing_zeros()); }); unsigned_gen().test_properties(|u| { assert_eq!(Integer::ZERO.index_of_next_true_bit(u), None); assert_eq!(Integer::NEGATIVE_ONE.index_of_next_true_bit(u), Some(u)); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { assert_eq!( Integer::from(&n).index_of_next_true_bit(index), n.index_of_next_true_bit(index) ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(i, index)| { assert_eq!( Integer::from(i).index_of_next_true_bit(index), i.index_of_next_true_bit(index) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitScan; use malachite_base::num::logic::traits::LowMask; use malachite_base::test_util::generators::{unsigned_gen_var_5, unsigned_gen_var_15}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::SignedLimb; #[test] fn test_low_mask() { let test = |bits, out| assert_eq!(Integer::low_mask(bits).to_string(), out); test(0, "0"); test(1, "1"); test(2, "3"); test(3, "7"); test(32, "4294967295"); test(100, "1267650600228229401496703205375"); } #[test] fn low_mask_properties() { unsigned_gen_var_5().test_properties(|bits| { let n = Integer::low_mask(bits); assert!(n.is_valid()); assert_eq!(n, Integer::power_of_2(bits) - Integer::ONE); assert_eq!(Natural::exact_from(&n), Natural::low_mask(bits)); assert_eq!(n.index_of_next_false_bit(0), Some(bits)); }); unsigned_gen_var_15::().test_properties(|bits| { assert_eq!(SignedLimb::low_mask(bits), Integer::low_mask(bits)); }); } ================================================ FILE: malachite-nz/tests/integer/logic/not.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::NotAssign; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::{integer_gen, natural_gen}; use rug; use std::str::FromStr; #[test] fn test_not() { let test = |s, out| { let n = Integer::from_str(s).unwrap(); let not = !n.clone(); assert!(not.is_valid()); assert_eq!(not.to_string(), out); let not = !&n; assert!(not.is_valid()); assert_eq!(not.to_string(), out); assert_eq!((!rug::Integer::from_str(s).unwrap()).to_string(), out); let mut x = n; x.not_assign(); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "-1"); test("123", "-124"); test("-123", "122"); test("1000000000000", "-1000000000001"); test("-1000000000000", "999999999999"); test("-2147483648", "2147483647"); test("2147483647", "-2147483648"); } #[test] fn not_properties() { integer_gen().test_properties(|x| { let not = !x.clone(); assert!(not.is_valid()); let rug_not = !rug::Integer::from(&x); assert_eq!(Integer::from(&rug_not), not); let not_alt = !&x; assert!(not_alt.is_valid()); assert_eq!(not_alt, not); let mut not_alt = x.clone(); not_alt.not_assign(); assert_eq!(not_alt, not); assert_ne!(not, x); assert_eq!(!¬, x); assert_eq!(x >= 0, not < 0); }); signed_gen::().test_properties(|i| { assert_eq!(!Integer::from(i), !i); }); natural_gen().test_properties(|x| { assert_eq!(!Integer::from(&x), !x); }); } ================================================ FILE: malachite-nz/tests/integer/logic/or.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_pair_gen, unsigned_vec_pair_gen_var_8, unsigned_vec_triple_gen_var_33, unsigned_vec_triple_gen_var_35, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::or::{ limbs_neg_or_limb, limbs_neg_or_limb_in_place, limbs_neg_or_limb_to_out, limbs_neg_or_neg_limb, limbs_or_neg_neg, limbs_or_neg_neg_in_place_either, limbs_or_neg_neg_to_out, limbs_or_pos_neg, limbs_or_pos_neg_in_place_right, limbs_or_pos_neg_to_out, limbs_pos_or_neg_limb, limbs_slice_or_neg_neg_in_place_left, limbs_slice_or_pos_neg_in_place_left, limbs_vec_or_neg_neg_in_place_left, limbs_vec_or_pos_neg_in_place_left, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use malachite_nz::test_util::integer::logic::or::{integer_or_alt_1, integer_or_alt_2}; use rug; use std::cmp::min; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_or_limb_and_limbs_neg_or_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_neg_or_limb(xs, y), out); let mut xs = xs.to_vec(); limbs_neg_or_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 0, &[6, 7]); test(&[6, 7], 2, &[6, 7]); test(&[100, 101, 102], 10, &[98, 101, 102]); test(&[123, 456], 789, &[107, 456]); test(&[0, 0, 456], 789, &[0xfffffceb, Limb::MAX, 455]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_or_limb_in_place_fail() { limbs_neg_or_limb_in_place(&mut [0, 0, 0], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_or_limb_fail() { limbs_neg_or_limb(&[0, 0, 0], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_or_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_neg_or_limb_to_out(&mut out, xs, y); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[6, 7], 0, &[6, 7, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, &[6, 7, 10, 10]); test(&[10, 10, 10, 10], &[100, 101, 102], 10, &[98, 101, 102, 10]); test(&[10, 10, 10, 10], &[123, 456], 789, &[107, 456, 10, 10]); test( &[10, 10, 10, 10], &[0, 0, 456], 789, &[0xfffffceb, Limb::MAX, 455, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_or_limb_to_out_fail_1() { limbs_neg_or_limb_to_out(&mut [10, 10], &[0, 0], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_or_limb_to_out_fail_2() { limbs_neg_or_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_or_neg_limb() { let test = |xs: &[Limb], y: Limb, out: Limb| { assert_eq!(limbs_pos_or_neg_limb(xs, y), out); }; test(&[6, 7], 3, 0xfffffff9); test(&[100, 101, 102], 10, 0xffffff92); test(&[0, 0, 1], 100, 0xffffff9c); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] const fn limbs_pos_or_neg_limb_fail() { limbs_pos_or_neg_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_or_neg_limb() { let test = |xs: &[Limb], y: Limb, out: Limb| { assert_eq!(limbs_neg_or_neg_limb(xs, y), out); }; test(&[6, 7], 3, 5); test(&[100, 101, 102], 10, 98); test(&[0, 0, 1], 100, 0xffffff9c); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] const fn limbs_neg_or_neg_limb_fail() { limbs_neg_or_neg_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_pos_neg_limbs_vec_or_pos_neg_in_place_left_and_limbs_or_pos_neg_in_place_right() { let test = |xs_before, ys_before, out| { assert_eq!(limbs_or_pos_neg(xs_before, ys_before), out); let mut xs = xs_before.to_vec(); limbs_vec_or_pos_neg_in_place_left(&mut xs, ys_before); assert_eq!(xs, out); let mut ys = ys_before.to_vec(); limbs_or_pos_neg_in_place_right(xs_before, &mut ys); assert_eq!(ys, out); }; test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 2, 2]); test(&[6, 7], &[1, 2, 3], vec![1, 0, 3]); test(&[1, 2, 3], &[6, 7], vec![5, 5]); test(&[100, 101, 102], &[102, 101, 100], vec![2, 0, 0]); test(&[0, 0, 1], &[3], vec![3]); test(&[3], &[0, 0, 1], vec![0xfffffffd, Limb::MAX, 0]); test(&[0, 3, 3], &[0, 0, 3], vec![0, 0xfffffffd, 0]); test(&[0, 0, 3], &[0, 3, 3], vec![0, 3, 0]); test(&[0, 3], &[0, 0, 3], vec![0, 0xfffffffd, 2]); test(&[0, 0, 3], &[0, 3], vec![0, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_fail_1() { limbs_or_pos_neg(&[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_fail_2() { limbs_or_pos_neg(&[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_pos_neg_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_or_pos_neg_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[2], &[3], &[10, 10, 10, 10], vec![1, 10, 10, 10]); test(&[1, 1, 1], &[1, 2, 3], &[10, 10, 10, 10], vec![1, 2, 2, 10]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], vec![1, 0, 3, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], vec![5, 5, 10, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![2, 0, 0, 10], ); test(&[0, 0, 1], &[3], &[10, 10, 10, 10], vec![3, 10, 10, 10]); test( &[3], &[0, 0, 1], &[10, 10, 10, 10], vec![0xfffffffd, Limb::MAX, 0, 10], ); test( &[0, 3, 3], &[0, 0, 3], &[10, 10, 10, 10], vec![0, 0xfffffffd, 0, 10], ); test(&[0, 0, 3], &[0, 3, 3], &[10, 10, 10, 10], vec![0, 3, 0, 10]); test( &[0, 3], &[0, 0, 3], &[10, 10, 10, 10], vec![0, 0xfffffffd, 2, 10], ); test(&[0, 0, 3], &[0, 3], &[10, 10, 10, 10], vec![0, 3, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_or_pos_neg_to_out(&mut out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_to_out_fail_2() { let mut out = vec![10, 10, 10, 10]; limbs_or_pos_neg_to_out(&mut out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_to_out_fail_3() { let mut out = vec![10]; limbs_or_pos_neg_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_or_pos_neg_in_place_left() { let test = |xs_before: &[Limb], ys, b, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_slice_or_pos_neg_in_place_left(&mut xs, ys), b); assert_eq!(xs, xs_after); }; test(&[2], &[3], false, vec![1]); test(&[1, 1, 1], &[1, 2, 3], false, vec![1, 2, 2]); test(&[6, 7], &[1, 2, 3], true, vec![1, 0]); test(&[1, 2, 3], &[6, 7], false, vec![5, 5, 0]); test(&[100, 101, 102], &[102, 101, 100], false, vec![2, 0, 0]); test(&[0, 0, 1], &[3], false, vec![3, 0, 0]); test(&[3], &[0, 0, 1], true, vec![0xfffffffd]); test(&[0, 3, 3], &[0, 0, 3], false, vec![0, 0xfffffffd, 0]); test(&[0, 0, 3], &[0, 3, 3], false, vec![0, 3, 0]); test(&[0, 3], &[0, 0, 3], true, vec![0, 0xfffffffd]); test(&[0, 0, 3], &[0, 3], false, vec![0, 3, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_or_pos_neg_in_place_left_fail_1() { limbs_slice_or_pos_neg_in_place_left(&mut [0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_or_pos_neg_in_place_left_fail_2() { limbs_slice_or_pos_neg_in_place_left(&mut [3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_or_pos_neg_in_place_left_fail_1() { limbs_vec_or_pos_neg_in_place_left(&mut vec![0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_or_pos_neg_in_place_left_fail_2() { limbs_vec_or_pos_neg_in_place_left(&mut vec![3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_in_place_right_fail_1() { limbs_or_pos_neg_in_place_right(&[0, 0, 0], &mut [3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_pos_neg_in_place_right_fail_2() { limbs_or_pos_neg_in_place_right(&[3], &mut [0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_neg_neg_and_limbs_vec_or_neg_neg_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_or_neg_neg(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_vec_or_neg_neg_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 0, 1]); test(&[6, 7], &[1, 2, 3], vec![1, 2]); test(&[1, 2, 3], &[6, 7], vec![1, 2]); test(&[100, 101, 102], &[102, 101, 100], vec![98, 101, 100]); test(&[0, 0, 1], &[3], vec![3]); test(&[3], &[0, 0, 1], vec![3]); test(&[0, 3, 3], &[0, 0, 3], vec![0, 3, 2]); test(&[0, 0, 3], &[0, 3, 3], vec![0, 3, 2]); test(&[0, 3], &[0, 0, 3], vec![0, 3]); test(&[0, 0, 3], &[0, 3], vec![0, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_fail_1() { limbs_or_neg_neg(&[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_fail_2() { limbs_or_neg_neg(&[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_neg_neg_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_or_neg_neg_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[2], &[3], &[10, 10, 10, 10], vec![1, 10, 10, 10]); test(&[1, 1, 1], &[1, 2, 3], &[10, 10, 10, 10], vec![1, 0, 1, 10]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], vec![1, 2, 10, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], vec![1, 2, 10, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![98, 101, 100, 10], ); test(&[0, 0, 1], &[3], &[10, 10, 10, 10], vec![3, 10, 10, 10]); test(&[3], &[0, 0, 1], &[10, 10, 10, 10], vec![3, 10, 10, 10]); test(&[0, 3, 3], &[0, 0, 3], &[10, 10, 10, 10], vec![0, 3, 2, 10]); test(&[0, 0, 3], &[0, 3, 3], &[10, 10, 10, 10], vec![0, 3, 2, 10]); test(&[0, 3], &[0, 0, 3], &[10, 10, 10, 10], vec![0, 3, 10, 10]); test(&[0, 0, 3], &[0, 3], &[10, 10, 10, 10], vec![0, 3, 10, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10], vec![1, 2]); test(&[6, 7], &[1, 2, 3], &[10, 10], vec![1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_or_neg_neg_to_out(&mut out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_to_out_fail_2() { let mut out = vec![10, 10, 10, 10]; limbs_or_neg_neg_to_out(&mut out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_to_out_fail_3() { let mut out = vec![10]; limbs_or_neg_neg_to_out(&mut out, &[6, 7, 8], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_or_neg_neg_in_place_left() { let test = |xs_before: &[Limb], ys, xs_after| { let mut xs = xs_before.to_vec(); limbs_slice_or_neg_neg_in_place_left(&mut xs, ys); assert_eq!(xs, xs_after); }; test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 0, 1]); test(&[6, 7], &[1, 2, 3], vec![1, 2]); test(&[1, 2, 3], &[6, 7], vec![1, 2, 0]); test(&[100, 101, 102], &[102, 101, 100], vec![98, 101, 100]); test(&[0, 0, 1], &[3], vec![3, 0, 0]); test(&[3], &[0, 0, 1], vec![3]); test(&[0, 3, 3], &[0, 0, 3], vec![0, 3, 2]); test(&[0, 0, 3], &[0, 3, 3], vec![0, 3, 2]); test(&[0, 3], &[0, 0, 3], vec![0, 3]); test(&[0, 0, 3], &[0, 3], vec![0, 3, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_or_neg_neg_in_place_left_fail_1() { limbs_slice_or_neg_neg_in_place_left(&mut [0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_or_neg_neg_in_place_left_fail_2() { limbs_slice_or_neg_neg_in_place_left(&mut [3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_or_neg_neg_in_place_left_fail_1() { limbs_vec_or_neg_neg_in_place_left(&mut vec![0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_or_neg_neg_in_place_left_fail_2() { limbs_vec_or_neg_neg_in_place_left(&mut vec![3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_neg_neg_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], b, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_or_neg_neg_in_place_either(&mut xs, &mut ys), b); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[2], &[3], false, vec![1], vec![3]); test(&[1, 1, 1], &[1, 2, 3], false, vec![1, 0, 1], vec![1, 2, 3]); test(&[1, 2, 3], &[6, 7], true, vec![1, 2, 3], vec![1, 2]); test(&[6, 7], &[1, 2, 3], false, vec![1, 2], vec![1, 2, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![98, 101, 100], vec![102, 101, 100], ); test(&[0, 0, 1], &[3], true, vec![0, 0, 1], vec![3]); test(&[3], &[0, 0, 1], false, vec![3], vec![0, 0, 1]); test(&[0, 3, 3], &[0, 0, 3], false, vec![0, 3, 2], vec![0, 0, 3]); test(&[0, 0, 3], &[0, 3, 3], false, vec![0, 3, 2], vec![0, 3, 3]); test(&[0, 3], &[0, 0, 3], false, vec![0, 3], vec![0, 0, 3]); test(&[0, 0, 3], &[0, 3], true, vec![0, 0, 3], vec![0, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_in_place_either_fail_1() { limbs_or_neg_neg_in_place_either(&mut [0, 0, 0], &mut [3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_neg_neg_in_place_either_fail_2() { limbs_or_neg_neg_in_place_either(&mut [3], &mut [0, 0, 0]); } #[test] fn test_or() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n |= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n |= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() | v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u | v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() | &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u | &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(integer_or_alt_1(&u, &v).to_string(), out); assert_eq!(integer_or_alt_2(&u, &v).to_string(), out); let n = rug::Integer::from_str(s).unwrap() | rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "507"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("1000000000000", "999999999999", "1000000004095"); test("12345678987654321", "314159265358979", "12347506587071667"); test("0", "-123", "-123"); test("123", "-456", "-389"); test("1000000000000", "-123", "-123"); test("123", "-1000000000000", "-999999999877"); test("1000000000000", "-999999999999", "-4095"); test("12345678987654321", "-314159265358979", "-1827599417347"); test("-123", "0", "-123"); test("-123", "456", "-51"); test("-1000000000000", "123", "-999999999877"); test("-123", "1000000000000", "-123"); test("-1000000000000", "999999999999", "-1"); test( "-12345678987654321", "314159265358979", "-12033347321712689", ); test("-123", "-456", "-67"); test("-1000000000000", "-123", "-123"); test("-123", "-1000000000000", "-123"); test("-1000000000000", "-999999999999", "-999999999999"); test("-12345678987654321", "-314159265358979", "-312331665941633"); test( "17561442137713604341197", "-533163900219836", "-75045493870643", ); test( "-18446744013580009457", "-18446673704965373937", "-18446673644835831793", ); test( "-18446673704965373937", "-18446744013580009457", "-18446673644835831793", ); test( "-324518553658389833295008601473024", "317057721155483154675232931839", "-324201495937234350140333368541185", ); test( "317057721155483154675232931839", "-324518553658389833295008601473024", "-324201495937234350140333368541185", ); test( "-324201495937234350140333368541185", "-324518553658389833295008601473024", "-324201495937234350140333368541185", ); test( "-324518553658389833295008601473024", "-324201495937234350140333368541185", "-324201495937234350140333368541185", ); test( "576458553284361984", "-10889035741470030830237691627457877114880", "-10889035741470030830237115168904592752896", ); test( "-26298808336", "170141183460469156173823577801560686592", "-26298808336", ); test( "-4363947867655", "-158453907176889445928738488320", "-4363947867655", ); } #[test] fn limbs_neg_or_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(xs, y)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_neg_or_limb(&xs, y)), -Natural::from_owned_limbs_asc(xs) | Integer::from(y) ); }); } #[test] fn limbs_neg_or_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_neg_or_limb_to_out(&mut out, &xs, y); let len = xs.len(); assert_eq!( -Natural::from_limbs_asc(&out[..len]), -Natural::from_owned_limbs_asc(xs) | Integer::from(y), ); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_neg_or_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_neg_or_limb_in_place(&mut xs, y); assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(old_xs) | Integer::from(y) ); }); } #[test] fn limbs_pos_or_neg_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(xs, y)| { assert_eq!( limbs_pos_or_neg_limb(&xs, y), -(Integer::from(Natural::from_owned_limbs_asc(xs)) | Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX])) ); }); } #[test] fn limbs_neg_or_neg_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(xs, y)| { assert_eq!( limbs_neg_or_neg_limb(&xs, y), -(-Natural::from_owned_limbs_asc(xs) | Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX])) ); }); } #[test] fn limbs_or_pos_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_or_pos_neg(&xs, &ys)), Integer::from(Natural::from_owned_limbs_asc(xs)) | -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_or_pos_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_33().test_properties_with_config(&config, |(mut out, ys, xs)| { let out_old = out.clone(); limbs_or_pos_neg_to_out(&mut out, &xs, &ys); let len = ys.len(); assert_eq!( -Natural::from_limbs_asc(&out[..len]), Integer::from(Natural::from_owned_limbs_asc(xs)) | -Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_slice_or_pos_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); if limbs_slice_or_pos_neg_in_place_left(&mut xs, &ys) { let mut out = Natural::exact_from( -(Integer::from(Natural::from_owned_limbs_asc(xs_old)) | -Natural::from_owned_limbs_asc(ys)), ) .to_limbs_asc(); out.resize(xs.len(), 0); assert_eq!(out, xs); } else { assert_eq!( -Natural::from_owned_limbs_asc(xs), Integer::from(Natural::from_owned_limbs_asc(xs_old)) | -Natural::from_owned_limbs_asc(ys) ); } }); } #[test] fn limbs_vec_or_pos_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_vec_or_pos_neg_in_place_left(&mut xs, &ys); assert_eq!( -Natural::from_owned_limbs_asc(xs), Integer::from(Natural::from_owned_limbs_asc(xs_old)) | -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_or_pos_neg_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, mut ys)| { let ys_old = ys.clone(); limbs_or_pos_neg_in_place_right(&xs, &mut ys); assert_eq!( -Natural::from_owned_limbs_asc(ys), Integer::from(Natural::from_owned_limbs_asc(xs)) | -Natural::from_owned_limbs_asc(ys_old) ); }); } #[test] fn limbs_or_neg_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_or_neg_neg(&xs, &ys)), -Natural::from_owned_limbs_asc(xs) | -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_or_neg_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_35().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_or_neg_neg_to_out(&mut out, &xs, &ys); let len = min(xs.len(), ys.len()); let result = Natural::exact_from( -(-Natural::from_owned_limbs_asc(xs) | -Natural::from_owned_limbs_asc(ys)), ); let mut expected_limbs = result.into_limbs_asc(); expected_limbs.resize(len, 0); assert_eq!(&out[..len], expected_limbs); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_slice_or_neg_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_slice_or_neg_neg_in_place_left(&mut xs, &ys); assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(xs_old) | -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_vec_or_neg_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_vec_or_neg_neg_in_place_left(&mut xs, &ys); assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(xs_old) | -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_or_neg_neg_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_or_neg_neg_in_place_either(&mut xs, &mut ys); let expected = -Natural::from_limbs_asc(&xs_old) | -Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(-Natural::from_owned_limbs_asc(ys), expected); } else { assert_eq!(-Natural::from_owned_limbs_asc(xs), expected); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn or_properties() { integer_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() | y.clone(); let result_val_ref = x.clone() | &y; let result_ref_val = &x | y.clone(); let result = &x | &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x |= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x |= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x |= rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), result); assert_eq!( Integer::from(&(rug::Integer::from(&x) | rug::Integer::from(&y))), result ); assert_eq!(integer_or_alt_1(&x, &y), result); assert_eq!(integer_or_alt_2(&x, &y), result); assert_eq!(&y | &x, result); assert_eq!(&result | &x, result); assert_eq!(&result | &y, result); assert_eq!(!(!x & !y), result); }); integer_gen().test_properties(|x| { assert_eq!(&x | Integer::ZERO, x); assert_eq!(Integer::ZERO | &x, x); assert_eq!(&x | Integer::NEGATIVE_ONE, -1); assert_eq!(Integer::NEGATIVE_ONE | &x, -1); assert_eq!(&x | &x, x); assert_eq!(&x | !&x, -1); }); integer_triple_gen().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x | y) | z, x | (y | z)); assert_eq!(x & (y | z), (x & y) | (x & z)); assert_eq!((x & y) | z, (x | z) & (y | z)); assert_eq!(x | (y & z), (x | y) & (x | z)); assert_eq!((x | y) & z, (x & z) | (y & z)); }); signed_pair_gen::().test_properties(|(i, j)| { assert_eq!(Integer::from(i) | Integer::from(j), i | j); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) | Integer::from(&y), x | y); }); } ================================================ FILE: malachite-nz/tests/integer/logic/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitAccess, NotAssign}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_unsigned_pair_gen_var_20; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_access::limbs_set_bit_neg; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_set_bit_neg() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_set_bit_neg(&mut mut_xs, index); assert_eq!(mut_xs, out); }; test(&[3, 2, 1], 100, &[3, 2, 1]); test(&[0, 0, 0b1101, 0b11], 96, &[0, 0, 0b1101, 0b10]); test(&[0, 0, 0b1101, 0b11], 66, &[0, 0, 0b1001, 0b11]); test(&[0, 0, 0b1100, 0b11], 64, &[0, 0, 0b1011, 0b11]); test(&[0, 0, 0b1101, 0b11], 32, &[0, u32::MAX, 0b1100, 0b11]); } #[test] fn test_set_bit() { let test = |u, index, out| { let mut n = Integer::from_str(u).unwrap(); n.set_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 10, "1024"); test("100", 0, "101"); test("1000000000000", 10, "1000000001024"); test("1000000000000", 100, "1267650600228229402496703205376"); test("5", 100, "1267650600228229401496703205381"); test("-1", 5, "-1"); test("-1", 100, "-1"); test("-33", 5, "-1"); test("-1267650600228229401496703205377", 100, "-1"); test("-32", 0, "-31"); test("-1000000000000", 10, "-999999998976"); test("-1000000000000", 100, "-1000000000000"); test("-1267650600228229402496703205376", 100, "-1000000000000"); test("-18446744078004518912", 0, "-18446744078004518911"); test("-18446744078004518912", 32, "-18446744078004518912"); test("-18446744078004518912", 33, "-18446744078004518912"); test("-18446744078004518912", 64, "-4294967296"); test("-18446744078004518912", 65, "-18446744078004518912"); test("-4294967296", 0, "-4294967295"); } #[test] fn limbs_set_bit_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config( &config, |(mut xs, index)| { let mut n = -Natural::from_limbs_asc(&xs); limbs_set_bit_neg(&mut xs, index); n.set_bit(index); assert_eq!(-Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn set_bit_properties() { integer_unsigned_pair_gen_var_2().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.set_bit(index); assert!(mut_n.is_valid()); let result = mut_n; let mut mut_n = n.clone(); mut_n.assign_bit(index, true); assert_eq!(mut_n, result); assert_eq!(&n | Integer::power_of_2(index), result); assert_ne!(result, 0); assert!(result >= n); if n.get_bit(index) { assert_eq!(result, n); } else { assert_ne!(result, n); let mut mut_result = result.clone(); mut_result.clear_bit(index); assert_eq!(mut_result, n); } let mut mut_not_n = !n; mut_not_n.clear_bit(index); mut_not_n.not_assign(); assert_eq!(mut_not_n, result); }); } ================================================ FILE: malachite-nz/tests/integer/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::signed_gen; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{integer_gen, natural_gen}; use num::BigInt; use rug; use std::str::FromStr; #[test] fn test_significant_bits() { let test = |n, out| { assert_eq!(Integer::from_str(n).unwrap().significant_bits(), out); assert_eq!(u64::wrapping_from(BigInt::from_str(n).unwrap().bits()), out); assert_eq!( u64::from(rug::Integer::from_str(n).unwrap().significant_bits()), out ); }; test("0", 0); test("100", 7); test("-100", 7); test("1000000000000", 40); test("-1000000000000", 40); } #[test] fn significant_bits_properties() { integer_gen().test_properties(|x| { let bits = x.significant_bits(); assert_eq!(u64::wrapping_from(BigInt::from(&x).bits()), bits); assert_eq!(u64::from(rug::Integer::from(&x).significant_bits()), bits); assert_eq!((-&x).significant_bits(), bits); let x_abs = x.abs(); assert_eq!(x_abs <= Limb::MAX, bits <= Limb::WIDTH); if x_abs != 0 { assert!(Natural::power_of_2(bits - 1) <= x_abs); assert!(x_abs < Natural::power_of_2(bits)); } }); natural_gen().test_properties(|n| { assert_eq!(Integer::from(&n).significant_bits(), n.significant_bits()); }); signed_gen::().test_properties(|i| { assert_eq!(Integer::from(i).significant_bits(), i.significant_bits()); }); } ================================================ FILE: malachite-nz/tests/integer/logic/to_bits.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{bool_vec_gen, bool_vec_gen_var_5, signed_gen}; use malachite_base::test_util::num::logic::bit_convertible::{to_bits_asc_alt, to_bits_desc_alt}; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::bit_convertible::{ bits_slice_to_twos_complement_bits_negative, bits_to_twos_complement_bits_non_negative, bits_vec_to_twos_complement_bits_negative, }; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::to_bits::{to_bits_asc_naive, to_bits_desc_naive}; use std::str::FromStr; #[test] fn test_bits_to_twos_complement_bits_non_negative() { let test = |bits: &[bool], out_bits: &[bool]| { let mut mut_bits = bits.to_vec(); bits_to_twos_complement_bits_non_negative(&mut mut_bits); assert_eq!(mut_bits, out_bits); }; test(&[], &[]); test(&[false, true, false], &[false, true, false]); test(&[true, false, true], &[true, false, true, false]); } #[test] fn test_bits_slice_to_twos_complement_bits_negative() { let test = |bits: &[bool], out_bits: &[bool], carry: bool| { let mut mut_bits = bits.to_vec(); assert_eq!( bits_slice_to_twos_complement_bits_negative(&mut mut_bits), carry ); assert_eq!(mut_bits, out_bits); }; test(&[], &[], true); test(&[true, false, true], &[true, true, false], false); test(&[false, false, false], &[false, false, false], true); } #[test] fn test_bits_vec_to_twos_complement_bits_negative() { let test = |bits: &[bool], out_bits: &[bool]| { let mut mut_bits = bits.to_vec(); bits_vec_to_twos_complement_bits_negative(&mut mut_bits); assert_eq!(mut_bits, out_bits); }; test(&[true, false, false], &[true, true, true]); test(&[true, false, true], &[true, true, false, true]); } #[test] #[should_panic] fn bits_vec_to_twos_complement_bits_negative_fail() { let mut mut_bits = vec![false, false]; bits_vec_to_twos_complement_bits_negative(&mut mut_bits); } #[test] fn test_to_bits_asc() { let test = |n, out| { let n = Integer::from_str(n).unwrap(); assert_eq!(n.bits().collect_vec(), out); assert_eq!(n.to_bits_asc(), out); assert_eq!(to_bits_asc_naive(&n), out); assert_eq!(to_bits_asc_alt(&n), out); }; test("0", vec![]); test("1", vec![true, false]); test("-1", vec![true]); test("6", vec![false, true, true, false]); test("-6", vec![false, true, false, true]); test( "105", vec![true, false, false, true, false, true, true, false], ); test( "-105", vec![true, true, true, false, true, false, false, true], ); test( "1000000000000", vec![ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, false, ], ); test( "-1000000000000", vec![ false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, false, true, true, false, true, false, true, true, false, true, false, true, false, false, true, true, true, false, true, false, false, false, true, ], ); test( "4294967295", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, ], ); test( "-4294967295", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "4294967296", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, ], ); test( "-4294967296", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "18446744073709551615", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, ], ); test( "-18446744073709551615", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "18446744073709551616", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, ], ); test( "-18446744073709551616", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "-10725406948920873257320529212268773241779870075", vec![ true, false, true, false, false, false, false, true, false, true, true, false, false, true, false, true, false, false, true, false, false, true, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, true, false, true, false, true, true, false, true, false, false, true, false, false, false, true, false, true, true, true, true, false, false, true, true, false, false, false, false, true, true, true, false, false, true, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, false, false, true, true, false, false, false, false, true, true, false, false, true, true, false, true, false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, false, true, true, false, true, true, false, false, true, true, true, false, true, true, true, false, true, false, false, true, true, true, false, false, false, false, true, true, true, true, true, false, false, false, false, true, ], ); } #[test] fn test_to_bits_desc() { let test = |n, out| { let n = Integer::from_str(n).unwrap(); assert_eq!(n.bits().rev().collect_vec(), out); assert_eq!(n.to_bits_desc(), out); assert_eq!(to_bits_desc_naive(&n), out); assert_eq!(to_bits_desc_alt(&n), out); }; test("0", vec![]); test("1", vec![false, true]); test("-1", vec![true]); test("6", vec![false, true, true, false]); test("-6", vec![true, false, true, false]); test( "105", vec![false, true, true, false, true, false, false, true], ); test( "-105", vec![true, false, false, true, false, true, true, true], ); test( "1000000000000", vec![ false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "-1000000000000", vec![ true, false, false, false, true, false, true, true, true, false, false, true, false, true, false, true, true, false, true, false, true, true, false, true, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "4294967295", vec![ false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "-4294967295", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "4294967296", vec![ false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "-4294967296", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "18446744073709551615", vec![ false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "-18446744073709551615", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "18446744073709551616", vec![ false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "-18446744073709551616", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); } #[test] fn bits_to_twos_complement_bits_non_negative_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); bool_vec_gen().test_properties_with_config(&config, |mut bits| { bits_to_twos_complement_bits_non_negative(&mut bits); }); } #[test] fn bits_slice_to_twos_complement_bits_negative_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); bool_vec_gen().test_properties_with_config(&config, |mut bits| { bits_slice_to_twos_complement_bits_negative(&mut bits); }); } #[test] fn bits_vec_to_twos_complement_bits_negative_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); bool_vec_gen_var_5().test_properties_with_config(&config, |mut bits| { bits_vec_to_twos_complement_bits_negative(&mut bits); }); } #[test] fn to_bits_asc_properties() { integer_gen().test_properties(|x| { let bits = x.to_bits_asc(); assert_eq!(to_bits_asc_naive(&x), bits); assert_eq!(to_bits_asc_alt(&x), bits); assert_eq!(x.bits().collect_vec(), bits); assert_eq!(Integer::from_bits_asc(bits.iter().copied()), x); if x != 0 { assert_eq!(*bits.last().unwrap(), x < 0); } let bit_len = bits.len(); if bit_len > 1 { assert_ne!(bits[bit_len - 1], bits[bit_len - 2]); } }); signed_gen::().test_properties(|i| { assert_eq!(i.to_bits_asc(), Integer::from(i).to_bits_asc()); }); } #[test] fn to_bits_desc_properties() { integer_gen().test_properties(|x| { let bits = x.to_bits_desc(); assert_eq!(to_bits_desc_naive(&x), bits); assert_eq!(to_bits_desc_alt(&x), bits); assert_eq!(x.bits().rev().collect_vec(), bits); assert_eq!(Integer::from_bits_desc(bits.iter().copied()), x); if x != 0 { assert_eq!(bits[0], x < 0); } if bits.len() > 1 { assert_ne!(bits[0], bits[1]); } }); signed_gen::().test_properties(|i| { assert_eq!(i.to_bits_desc(), Integer::from(i).to_bits_desc()); }); } ================================================ FILE: malachite-nz/tests/integer/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::logic::traits::TrailingZeros; use malachite_base::test_util::generators::signed_gen_var_6; use malachite_nz::integer::Integer; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::integer_gen; use malachite_nz::test_util::integer::logic::trailing_zeros::integer_trailing_zeros_alt; use std::str::FromStr; #[test] fn test_trailing_zeros() { let test = |s, out| { let n = Integer::from_str(s).unwrap(); assert_eq!(n.trailing_zeros(), out); assert_eq!(integer_trailing_zeros_alt(&n), out); }; test("0", None); test("123", Some(0)); test("-123", Some(0)); test("1000000000000", Some(12)); test("-1000000000000", Some(12)); test("4294967295", Some(0)); test("-4294967295", Some(0)); test("4294967296", Some(32)); test("-4294967296", Some(32)); test("18446744073709551615", Some(0)); test("-18446744073709551615", Some(0)); test("18446744073709551616", Some(64)); test("-18446744073709551616", Some(64)); } #[allow(clippy::cmp_owned, clippy::useless_conversion)] #[test] fn significant_bits_properties() { integer_gen().test_properties(|x| { let trailing_zeros = x.trailing_zeros(); assert_eq!(integer_trailing_zeros_alt(&x), trailing_zeros); assert_eq!(trailing_zeros.is_none(), x == 0); assert_eq!((-&x).trailing_zeros(), trailing_zeros); if x != 0 { let trailing_zeros = trailing_zeros.unwrap(); assert_ne!((!&x).trailing_zeros() == Some(0), trailing_zeros == 0); if trailing_zeros <= u64::from(Limb::MAX) { assert!((&x >> trailing_zeros).odd()); assert_eq!(&x >> trailing_zeros << trailing_zeros, x); } } }); signed_gen_var_6::().test_properties(|i| { assert_eq!( Integer::from(i).trailing_zeros(), Some(TrailingZeros::trailing_zeros(i)) ); }); } ================================================ FILE: malachite-nz/tests/integer/logic/xor.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_pair_gen, unsigned_vec_pair_gen_var_8, unsigned_vec_triple_gen_var_34, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_pair_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5, }; use malachite_nz::integer::Integer; use malachite_nz::integer::logic::xor::{ limbs_neg_xor_limb, limbs_neg_xor_limb_neg, limbs_neg_xor_limb_neg_in_place, limbs_neg_xor_limb_neg_to_out, limbs_neg_xor_limb_to_out, limbs_pos_xor_limb_neg, limbs_pos_xor_limb_neg_to_out, limbs_slice_neg_xor_limb_in_place, limbs_slice_pos_xor_limb_neg_in_place, limbs_vec_neg_xor_limb_in_place, limbs_vec_pos_xor_limb_neg_in_place, limbs_xor_neg_neg, limbs_xor_neg_neg_in_place_either, limbs_xor_neg_neg_in_place_left, limbs_xor_neg_neg_to_out, limbs_xor_pos_neg, limbs_xor_pos_neg_in_place_either, limbs_xor_pos_neg_in_place_left, limbs_xor_pos_neg_in_place_right, limbs_xor_pos_neg_to_out, }; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen, integer_triple_gen, natural_pair_gen, }; use malachite_nz::test_util::integer::logic::xor::{integer_xor_alt_1, integer_xor_alt_2}; use rug; use std::cmp::max; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_xor_limb_and_limbs_vec_neg_xor_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_neg_xor_limb(xs, y), out); let mut xs = xs.to_vec(); limbs_vec_neg_xor_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 0, &[6, 7]); test(&[6, 7], 2, &[8, 7]); test(&[100, 101, 102], 10, &[106, 101, 102]); test(&[123, 456], 789, &[880, 456]); test(&[Limb::MAX - 1, Limb::MAX, Limb::MAX], 2, &[0, 0, 0, 1]); test(&[0, 0, 0, 1], 2, &[Limb::MAX - 1, Limb::MAX, Limb::MAX, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_neg_xor_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { let mut xs = xs.to_vec(); limbs_slice_neg_xor_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 0, &[6, 7]); test(&[6, 7], 2, &[8, 7]); test(&[100, 101, 102], 10, &[106, 101, 102]); test(&[123, 456], 789, &[880, 456]); test(&[Limb::MAX - 1, Limb::MAX, Limb::MAX], 2, &[0, 0, 0]); test(&[0, 0, 0, 1], 2, &[Limb::MAX - 1, Limb::MAX, Limb::MAX, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_xor_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_neg_xor_limb_to_out(&mut out, xs, y), carry); assert_eq!(out, out_after); }; test(&[10, 10], &[1], Limb::MAX, true, &[0, 10]); test(&[10; 4], &[6, 7], 0, false, &[6, 7, 10, 10]); test(&[10; 4], &[6, 7], 2, false, &[8, 7, 10, 10]); test(&[10; 4], &[100, 101, 102], 10, false, &[106, 101, 102, 10]); test(&[10; 4], &[123, 456], 789, false, &[880, 456, 10, 10]); test( &[10; 4], &[Limb::MAX - 1, Limb::MAX, Limb::MAX], 2, true, &[0, 0, 0, 10], ); test( &[10; 4], &[0, 0, 0, 1], 2, false, &[Limb::MAX - 1, Limb::MAX, Limb::MAX, 0], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_xor_limb_to_out_fail() { limbs_neg_xor_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_xor_limb_neg_and_limbs_vec_pos_xor_limb_neg_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_pos_xor_limb_neg(xs, y), out); let mut xs = xs.to_vec(); limbs_vec_pos_xor_limb_neg_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[0, 2], 3, &[0xfffffffd, 2]); test(&[1, 2, 3], 4, &[0xfffffffb, 2, 3]); test(&[2, Limb::MAX], 2, &[0, 0, 1]); test(&[2, Limb::MAX, Limb::MAX], 2, &[0, 0, 0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_xor_limb_neg_fail() { limbs_pos_xor_limb_neg(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_pos_xor_limb_neg_in_place_fail() { let mut xs = vec![]; limbs_vec_pos_xor_limb_neg_in_place(&mut xs, 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pos_xor_limb_neg_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_pos_xor_limb_neg_to_out(&mut out, xs, y), carry); assert_eq!(out, out_after); }; test(&[0, 0], &[0, 2], 3, false, &[0xfffffffd, 2]); test(&[1, 2, 100], &[0, 2, 100], 3, false, &[0xfffffffd, 2, 100]); test(&[0, 0, 0], &[1, 2, 3], 4, false, &[0xfffffffb, 2, 3]); test(&[0, 0], &[2, Limb::MAX], 2, true, &[0, 0]); test(&[0, 0, 0], &[2, Limb::MAX, Limb::MAX], 2, true, &[0, 0, 0]); test( &[1, 2, 3, 100], &[2, Limb::MAX, Limb::MAX], 2, true, &[0, 0, 0, 100], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_xor_limb_neg_to_out_fail_1() { limbs_pos_xor_limb_neg_to_out(&mut [1, 2, 3], &[1, 2, 3, 4], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pos_xor_limb_neg_to_out_fail_2() { limbs_pos_xor_limb_neg_to_out(&mut [1, 2, 3], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_pos_xor_limb_neg_in_place() { let test = |xs_before: &[Limb], y: Limb, carry, xs_after: &[Limb]| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_slice_pos_xor_limb_neg_in_place(&mut xs, y), carry); assert_eq!(xs, xs_after); }; test(&[0, 2], 3, false, &[0xfffffffd, 2]); test(&[1, 2, 3], 4, false, &[0xfffffffb, 2, 3]); test(&[2, Limb::MAX], 2, true, &[0, 0]); test(&[2, Limb::MAX, Limb::MAX], 2, true, &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_pos_xor_limb_neg_in_place_fail() { limbs_slice_pos_xor_limb_neg_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_xor_limb_neg_and_limbs_neg_xor_limb_neg_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_neg_xor_limb_neg(xs, y), out); let mut xs = xs.to_vec(); limbs_neg_xor_limb_neg_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[0, 2], 3, &[3, 1]); test(&[6, 7], 2, &[0xfffffff8, 7]); test(&[1, 2, 3], 4, &[0xfffffffb, 2, 3]); test(&[100, 101, 102], 10, &[4294967190, 101, 102]); test(&[123, 456], 789, &[4294966416, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_xor_limb_neg_fail() { limbs_neg_xor_limb_neg(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_xor_limb_neg_in_place_fail() { limbs_neg_xor_limb_neg_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_xor_limb_neg_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_neg_xor_limb_neg_to_out(&mut out, xs, y); assert_eq!(out, out_after); }; test(&[10; 4], &[0, 2], 3, &[3, 1, 10, 10]); test(&[10; 4], &[6, 7], 2, &[0xfffffff8, 7, 10, 10]); test(&[10; 4], &[1, 2, 3], 4, &[0xfffffffb, 2, 3, 10]); test(&[10; 4], &[100, 101, 102], 10, &[4294967190, 101, 102, 10]); test(&[10; 4], &[123, 456], 789, &[4294966416, 456, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_xor_limb_neg_to_out_fail_1() { limbs_neg_xor_limb_neg_to_out(&mut [], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_neg_xor_limb_neg_to_out_fail_2() { limbs_neg_xor_limb_neg_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_pos_neg_limbs_xor_pos_neg_in_place_left_and_limbs_xor_pos_neg_in_place_right() { let test = |xs_before, ys_before, out| { assert_eq!(limbs_xor_pos_neg(xs_before, ys_before), out); let mut xs = xs_before.to_vec(); limbs_xor_pos_neg_in_place_left(&mut xs, ys_before); assert_eq!(xs, out); let mut ys = ys_before.to_vec(); limbs_xor_pos_neg_in_place_right(xs_before, &mut ys); assert_eq!(ys, out); }; test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![2, 3, 2]); test(&[6, 7], &[1, 2, 3], vec![7, 5, 3]); test(&[1, 2, 3], &[6, 7], vec![5, 5, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![2, 0, 2]); test(&[0, 0, 1], &[3], vec![3, 0, 1]); test(&[3], &[0, 0, 1], vec![0xfffffffd, Limb::MAX, 0]); test(&[0, 3, 3], &[0, 0, 3], vec![0, 0xfffffffd, 1]); test(&[0, 0, 3], &[0, 3, 3], vec![0, 3, 0]); test(&[0, 3], &[0, 0, 3], vec![0, 0xfffffffd, 2]); test(&[0, 0, 3], &[0, 3], vec![0, 3, 3]); test(&[0, 1], &[0, Limb::MAX, Limb::MAX], vec![0, 0, 0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_fail_1() { limbs_xor_pos_neg(&[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_fail_2() { limbs_xor_pos_neg(&[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_left_fail_1() { limbs_xor_pos_neg_in_place_left(&mut vec![0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_left_fail_2() { limbs_xor_pos_neg_in_place_left(&mut vec![3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_right_fail_1() { limbs_xor_pos_neg_in_place_right(&[0, 0, 0], &mut vec![3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_right_fail_2() { limbs_xor_pos_neg_in_place_right(&[3], &mut vec![0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_pos_neg_to_out() { let test = |xs, ys, out_before: &[Limb], out_after, carry| { let mut out = out_before.to_vec(); assert_eq!(limbs_xor_pos_neg_to_out(&mut out, xs, ys), carry); assert_eq!(out, out_after); }; test(&[2], &[3], &[10; 4], vec![1, 10, 10, 10], false); test(&[1, 1, 1], &[1, 2, 3], &[10; 4], vec![2, 3, 2, 10], false); test(&[6, 7], &[1, 2, 3], &[10; 4], vec![7, 5, 3, 10], false); test(&[1, 2, 3], &[6, 7], &[10; 4], vec![5, 5, 3, 10], false); test( &[100, 101, 102], &[102, 101, 100], &[10; 4], vec![2, 0, 2, 10], false, ); test(&[0, 0, 1], &[3], &[10; 4], vec![3, 0, 1, 10], false); test( &[3], &[0, 0, 1], &[10; 4], vec![0xfffffffd, Limb::MAX, 0, 10], false, ); test( &[0, 3, 3], &[0, 0, 3], &[10; 4], vec![0, 0xfffffffd, 1, 10], false, ); test(&[0, 0, 3], &[0, 3, 3], &[10; 4], vec![0, 3, 0, 10], false); test( &[0, 3], &[0, 0, 3], &[10; 4], vec![0, 0xfffffffd, 2, 10], false, ); test(&[0, 0, 3], &[0, 3], &[10; 4], vec![0, 3, 3, 10], false); test( &[0, 1], &[0, Limb::MAX, Limb::MAX], &[10; 4], vec![0, 0, 0, 10], true, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_to_out_fail_1() { let mut out = vec![10; 4]; limbs_xor_pos_neg_to_out(&mut out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_to_out_fail_2() { let mut out = vec![10; 4]; limbs_xor_pos_neg_to_out(&mut out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_to_out_fail_3() { let mut out = vec![10]; limbs_xor_pos_neg_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_pos_neg_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], b, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_xor_pos_neg_in_place_either(&mut xs, &mut ys), b); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[2], &[3], false, vec![1], vec![3]); test(&[1, 1, 1], &[1, 2, 3], false, vec![2, 3, 2], vec![1, 2, 3]); test(&[1, 2, 3], &[6, 7], false, vec![5, 5, 3], vec![6, 7]); test(&[6, 7], &[1, 2, 3], true, vec![6, 7], vec![7, 5, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![2, 0, 2], vec![102, 101, 100], ); test(&[0, 0, 1], &[3], false, vec![3, 0, 1], vec![3]); test( &[3], &[0, 0, 1], true, vec![3], vec![0xfffffffd, Limb::MAX, 0], ); test( &[0, 3, 3], &[0, 0, 3], false, vec![0, 0xfffffffd, 1], vec![0, 0, 3], ); test(&[0, 0, 3], &[0, 3, 3], false, vec![0, 3, 0], vec![0, 3, 3]); test( &[0, 3], &[0, 0, 3], true, vec![0, 3], vec![0, 0xfffffffd, 2], ); test(&[0, 0, 3], &[0, 3], false, vec![0, 3, 3], vec![0, 3]); test( &[1, 0, 0], &[Limb::MAX, Limb::MAX, Limb::MAX, Limb::MAX], true, vec![1, 0, 0], vec![0, 0, 0, 0, 1], ); test( &[0, 1], &[0, Limb::MAX, Limb::MAX], true, vec![0, 1], vec![0, 0, 0, 1], ); test( &[Limb::MAX, Limb::MAX, Limb::MAX, Limb::MAX], &[1, 0, 0], false, vec![0, 0, 0, 0, 1], vec![1, 0, 0], ); test( &[0, Limb::MAX, Limb::MAX], &[0, 1], false, vec![0, 0, 0, 1], vec![0, 1], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_either_fail_1() { limbs_xor_pos_neg_in_place_either(&mut vec![0, 0, 0], &mut vec![3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_pos_neg_in_place_either_fail_2() { limbs_xor_pos_neg_in_place_either(&mut vec![3], &mut vec![0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_neg_neg_and_limbs_xor_neg_neg_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_xor_neg_neg(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_xor_neg_neg_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[2], &[3], vec![3]); test(&[1, 1, 1], &[1, 2, 3], vec![0, 3, 2]); test(&[6, 7], &[1, 2, 3], vec![5, 5, 3]); test(&[1, 2, 3], &[6, 7], vec![5, 5, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![6, 0, 2]); test(&[0, 0, 1], &[3], vec![0xfffffffd, Limb::MAX, 0]); test(&[3], &[0, 0, 1], vec![0xfffffffd, Limb::MAX, 0]); test(&[0, 3, 3], &[0, 0, 3], vec![0, 0xfffffffd, 1]); test(&[0, 0, 3], &[0, 3, 3], vec![0, 0xfffffffd, 1]); test(&[0, 3], &[0, 0, 3], vec![0, 0xfffffffd, 2]); test(&[0, 0, 3], &[0, 3], vec![0, 0xfffffffd, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_in_place_left_fail_1() { limbs_xor_neg_neg_in_place_left(&mut vec![0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_in_place_left_fail_2() { limbs_xor_neg_neg_in_place_left(&mut vec![3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_neg_neg_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_xor_neg_neg_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[2], &[3], &[10; 4], vec![3, 10, 10, 10]); test(&[1, 1, 1], &[1, 2, 3], &[10; 4], vec![0, 3, 2, 10]); test(&[6, 7], &[1, 2, 3], &[10; 4], vec![5, 5, 3, 10]); test(&[1, 2, 3], &[6, 7], &[10; 4], vec![5, 5, 3, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10; 4], vec![6, 0, 2, 10], ); test( &[0, 0, 1], &[3], &[10; 4], vec![0xfffffffd, Limb::MAX, 0, 10], ); test( &[3], &[0, 0, 1], &[10; 4], vec![0xfffffffd, Limb::MAX, 0, 10], ); test(&[0, 3, 3], &[0, 0, 3], &[10; 4], vec![0, 0xfffffffd, 1, 10]); test(&[0, 0, 3], &[0, 3, 3], &[10; 4], vec![0, 0xfffffffd, 1, 10]); test(&[0, 3], &[0, 0, 3], &[10; 4], vec![0, 0xfffffffd, 2, 10]); test(&[0, 0, 3], &[0, 3], &[10; 4], vec![0, 0xfffffffd, 2, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_to_out_fail_1() { let mut out = vec![10; 4]; limbs_xor_neg_neg_to_out(&mut out, &[0, 0, 0], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_to_out_fail_2() { let mut out = vec![10; 4]; limbs_xor_neg_neg_to_out(&mut out, &[3], &[0, 0, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_to_out_fail_3() { let mut out = vec![10]; limbs_xor_neg_neg_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_neg_neg_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], b, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_xor_neg_neg_in_place_either(&mut xs, &mut ys), b); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[2], &[3], false, vec![3], vec![3]); test(&[1, 1, 1], &[1, 2, 3], false, vec![0, 3, 2], vec![1, 2, 3]); test(&[1, 2, 3], &[6, 7], false, vec![5, 5, 3], vec![6, 7]); test(&[6, 7], &[1, 2, 3], true, vec![6, 7], vec![5, 5, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![6, 0, 2], vec![102, 101, 100], ); test( &[0, 0, 1], &[3], false, vec![0xfffffffd, Limb::MAX, 0], vec![3], ); test( &[3], &[0, 0, 1], true, vec![3], vec![0xfffffffd, Limb::MAX, 0], ); test( &[0, 3, 3], &[0, 0, 3], false, vec![0, 0xfffffffd, 1], vec![0, 0, 3], ); test( &[0, 0, 3], &[0, 3, 3], false, vec![0, 0xfffffffd, 1], vec![0, 3, 3], ); test( &[0, 3], &[0, 0, 3], true, vec![0, 3], vec![0, 0xfffffffd, 2], ); test( &[0, 0, 3], &[0, 3], false, vec![0, 0xfffffffd, 2], vec![0, 3], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_in_place_either_fail_1() { limbs_xor_neg_neg_in_place_either(&mut [0, 0, 0], &mut [3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_neg_neg_in_place_either_fail_2() { limbs_xor_neg_neg_in_place_either(&mut [3], &mut [0, 0, 0]); } #[test] fn test_xor() { let test = |s, t, out| { let u = Integer::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); let mut n = u.clone(); n ^= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n ^= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() ^ v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u ^ v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() ^ &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u ^ &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(integer_xor_alt_1(&u, &v).to_string(), out); assert_eq!(integer_xor_alt_2(&u, &v).to_string(), out); let n = rug::Integer::from_str(s).unwrap() ^ rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "435"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("1000000000000", "999999999999", "8191"); test("12345678987654321", "314159265358979", "12035174921130034"); test("0", "-123", "-123"); test("123", "-456", "-445"); test("1000000000000", "-123", "-1000000000123"); test("123", "-1000000000000", "-999999999877"); test("1000000000000", "-999999999999", "-8191"); test( "12345678987654321", "-314159265358979", "-12035174921130036", ); test("-123", "0", "-123"); test("-123", "456", "-435"); test("-1000000000000", "123", "-999999999877"); test("-123", "1000000000000", "-1000000000123"); test("-1000000000000", "999999999999", "-1"); test( "-12345678987654321", "314159265358979", "-12035174921130036", ); test("-123", "-456", "445"); test("-1000000000000", "-123", "999999999877"); test("-123", "-1000000000000", "999999999877"); test("-1000000000000", "-999999999999", "1"); test( "-12345678987654321", "-314159265358979", "12035174921130034", ); test( "-58833344151816", "-163347918670491773353", "163347906017862822063", ); test( "-163347918670491773353", "-58833344151816", "163347906017862822063", ); test( "4722366342132156858368", "-35201550909443", "-4722366377333707767811", ); test( "-35201550909443", "4722366342132156858368", "-4722366377333707767811", ); test( "-26298808336", "170141183460469156173823577801560686592", "-170141183460469156173823577827859494928", ); test( "170141183460469156173823577801560686592", "-26298808336", "-170141183460469156173823577827859494928", ); test( "-19191697422411034898997120", "-748288838313422294120286634350663119087542623797248", "748288838313422294120286615158965696676507724800128", ); test( "-748288838313422294120286634350663119087542623797248", "-19191697422411034898997120", "748288838313422294120286615158965696676507724800128", ); test( "4294967296", "-79228162514264337589248983040", "-79228162514264337593543950336", ); test( "-79228162514264337589248983040", "4294967296", "-79228162514264337593543950336", ); } #[test] fn limbs_neg_or_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(xs, y)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_neg_xor_limb(&xs, y)), -Natural::from_owned_limbs_asc(xs) ^ Integer::from(y) ); }); } #[test] fn limbs_neg_xor_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let len = xs.len(); if limbs_neg_xor_limb_to_out(&mut out, &xs, y) { let mut result = Natural::exact_from(-(-Natural::from_owned_limbs_asc(xs) ^ Integer::from(y))) .to_limbs_asc(); result.resize(len, 0); assert_eq!(result, &out[..len]); } else { assert_eq!( -Natural::from_limbs_asc(&out[..len]), -Natural::from_owned_limbs_asc(xs) ^ Integer::from(y), ); } assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_slice_neg_xor_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); if limbs_slice_neg_xor_limb_in_place(&mut xs, y) { let xor = Integer::from(Natural::from_owned_limbs_asc(old_xs.clone())) ^ Integer::from(y); if xor <= 0 { let mut result = Natural::exact_from(-xor).to_limbs_asc(); result.resize(xs.len(), 0); assert_eq!(result, xs); } } else { assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(old_xs) ^ Integer::from(y) ); } }); } #[test] fn limbs_vec_neg_xor_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_vec_neg_xor_limb_in_place(&mut xs, y); assert_eq!( -Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(old_xs) ^ Integer::from(y) ); }); } #[test] fn limbs_pos_xor_limb_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { let out = limbs_pos_xor_limb_neg(&xs, y); let n = Integer::from(Natural::from_owned_limbs_asc(xs)) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(out), Natural::exact_from(-n)); }); } #[test] fn limbs_pos_xor_limb_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_pos_xor_limb_neg_to_out(&mut out, &xs, y); let len = xs.len(); let n = Integer::from(Natural::from_owned_limbs_asc(xs)) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let mut result = Natural::exact_from(-n).into_limbs_asc(); result.resize(len, 0); assert_eq!(result, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_slice_pos_xor_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let n = Integer::from(Natural::from_limbs_asc(&xs)) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let carry = limbs_slice_pos_xor_limb_neg_in_place(&mut xs, y); if carry { let result = Natural::exact_from(-n); let result = result.as_limbs_asc(); assert_eq!(xs, &result[..xs.len()]); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), Natural::exact_from(-n)); } }); } #[test] fn limbs_vec_pos_xor_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let n = Integer::from(Natural::from_limbs_asc(&xs)) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); limbs_vec_pos_xor_limb_neg_in_place(&mut xs, y); assert_eq!(Natural::from_owned_limbs_asc(xs), Natural::exact_from(-n)); }); } #[test] fn limbs_neg_xor_limb_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(xs, y)| { let out = limbs_neg_xor_limb_neg(&xs, y); let n = -Natural::from_owned_limbs_asc(xs) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); assert_eq!(Natural::from_owned_limbs_asc(out), Natural::exact_from(n)); }); } #[test] fn limbs_neg_xor_limb_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_5().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_neg_xor_limb_neg_to_out(&mut out, &xs, y); let len = xs.len(); let n = -Natural::from_owned_limbs_asc(xs) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); let mut limbs = Natural::exact_from(n).into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_neg_xor_limb_neg_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_18().test_properties_with_config(&config, |(mut xs, y)| { let n = -Natural::from_limbs_asc(&xs) ^ Integer::from_owned_twos_complement_limbs_asc(vec![y, Limb::MAX]); limbs_neg_xor_limb_neg_in_place(&mut xs, y); let mut expected_limbs = Natural::exact_from(n).into_limbs_asc(); expected_limbs.resize(xs.len(), 0); assert_eq!(xs, expected_limbs); }); } #[test] fn limbs_xor_pos_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( -Natural::from_owned_limbs_asc(limbs_xor_pos_neg(&xs, &ys)), Integer::from(Natural::from_owned_limbs_asc(xs)) ^ -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_xor_pos_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_34().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); let carry = limbs_xor_pos_neg_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); let mut result = out[..len].to_vec(); if carry { result.push(1); } assert_eq!( -Natural::from_owned_limbs_asc(result), Integer::from(Natural::from_owned_limbs_asc(xs)) ^ -Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_xor_pos_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_xor_pos_neg_in_place_left(&mut xs, &ys); assert_eq!( -Natural::from_owned_limbs_asc(xs), Integer::from(Natural::from_owned_limbs_asc(xs_old)) ^ -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_xor_pos_neg_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, mut ys)| { let ys_old = ys.clone(); limbs_xor_pos_neg_in_place_right(&xs, &mut ys); assert_eq!( -Natural::from_owned_limbs_asc(ys), Integer::from(Natural::from_owned_limbs_asc(xs)) ^ -Natural::from_owned_limbs_asc(ys_old) ); }); } #[test] fn limbs_xor_pos_neg_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_xor_pos_neg_in_place_either(&mut xs, &mut ys); let expected = Integer::from(Natural::from_limbs_asc(&xs_old)) ^ -Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(-Natural::from_owned_limbs_asc(ys), expected); } else { assert_eq!(-Natural::from_owned_limbs_asc(xs), expected); assert_eq!(ys, ys_old); } }); } #[test] fn limbs_xor_neg_neg_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_xor_neg_neg(&xs, &ys)), -Natural::from_owned_limbs_asc(xs) ^ -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_xor_neg_neg_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_34().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_xor_neg_neg_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); let result = Natural::exact_from( -Natural::from_owned_limbs_asc(xs) ^ -Natural::from_owned_limbs_asc(ys), ); let mut expected = result.to_limbs_asc(); expected.resize(len, 0); assert_eq!(&out[..len], expected.as_slice()); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_xor_neg_neg_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_xor_neg_neg_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), -Natural::from_owned_limbs_asc(xs_old) ^ -Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_xor_neg_neg_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_8().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_xor_neg_neg_in_place_either(&mut xs, &mut ys); let expected = -Natural::from_limbs_asc(&xs_old) ^ -Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), expected); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), expected); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn xor_properties() { integer_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() ^ y.clone(); let result_val_ref = x.clone() ^ &y; let result_ref_val = &x ^ y.clone(); let result = &x ^ &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x ^= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x ^= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x ^= rug::Integer::from(&y); assert_eq!(Integer::from(&mut_x), result); assert_eq!( Integer::from(&(rug::Integer::from(&x) ^ rug::Integer::from(&y))), result ); assert_eq!(integer_xor_alt_1(&x, &y), result); assert_eq!(integer_xor_alt_2(&x, &y), result); assert_eq!(&y ^ &x, result); assert_eq!(&result ^ &x, y); assert_eq!(&result ^ &y, x); assert_eq!(!&x ^ !&y, result); assert_eq!(!(&x ^ !&y), result); assert_eq!(!(!x ^ y), result); }); integer_gen().test_properties(|ref x| { assert_eq!(x ^ Integer::ZERO, *x); assert_eq!(Integer::ZERO ^ x, *x); assert_eq!(x ^ Integer::NEGATIVE_ONE, !x); assert_eq!(Integer::NEGATIVE_ONE ^ x, !x); assert_eq!(x ^ x, 0); assert_eq!(x ^ !x, -1); assert_eq!(!x ^ x, -1); }); integer_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x ^ &y) ^ &z, x ^ (y ^ z)); }); signed_pair_gen::().test_properties(|(i, j)| { assert_eq!(Integer::from(i) ^ Integer::from(j), i ^ j); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Integer::from(&x) ^ Integer::from(&y), x ^ y); }); } ================================================ FILE: malachite-nz/tests/integer/random/get_random_integer_from_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; use malachite_base::num::random::{VariableRangeGenerator, random_primitive_ints}; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_random_integer_from_range_to_infinity; use std::str::FromStr; fn get_random_integer_from_range_to_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, out: &str, ) { let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); let xs = (0..10) .map(|_| { get_random_integer_from_range_to_infinity( &mut xs, &mut vrg, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_integer_from_range_to_infinity() { get_random_integer_from_range_to_infinity_helper("0", 1, 1, "[0, 1, 4, 1, 2, 1, 1, 0, 0, 0]"); get_random_integer_from_range_to_infinity_helper( "0", 10, 1, "[7, 7816, 428, 130, 1, 141, 10, 0, 4, 4483]", ); get_random_integer_from_range_to_infinity_helper( "0", 100, 1, "[5101205056696451696397798478058511, 1562796, 8799850658374624318722, \ 432133157539661383965541544934515144954635954990115469923269847259651409024994917000655083\ 9187394388518593842616549212512013, \ 279353891976332938189472063076409154515, 1660357170525, \ 143642188899218739960634489126387586224289351782452807884934768151051511265288490384892849\ 22660727526851378407, 86075361492, 353552745516847393429177033516378899307448925328642, \ 577340679116474858586805525866181088123189468507069123812855481357566943854]", ); get_random_integer_from_range_to_infinity_helper( "1000", 11, 1, "[1015, 1672, 6316, 1282, 3037, 1805, 1122, 1003, 1014, 1019]", ); get_random_integer_from_range_to_infinity_helper( "1000", 100, 1, "[1206982412795330974999926231143439, 457693356, 169360311075942561584386, \ 156864198081133600182484993110222733524619588763603298779764468364382591713280608608755884\ 131404116709444244598775565, 66677412650746398524862933431554022355, 26949124609373, \ 102746416386110194533593072869947149634954555999655687951279670456046799992002349096588693\ 3126118631, 22626063730900, 2792352557430693060292673664470974590025115014402, \ 68488724460300171666815845652220555564874106206890863873832895385292448366]", ); get_random_integer_from_range_to_infinity_helper( "-1000", 1, 1, "[-3, -2, -1, 1, 29, -3, 0, 0, -1, 0]", ); get_random_integer_from_range_to_infinity_helper( "-1000", 11, 1, "[-3, 136, -1, 2, -3, -731, 981996642, 764, 0, 1411]", ); get_random_integer_from_range_to_infinity_helper( "-1000", 100, 1, "[70671, 33609936868504473224, 3330, 6514514285313835997, \ 141387787476503121093422704441276431644102874620098798311586658867138567258580573643023899\ 16124485683507351766006393560845, 250798235515229707219, 136491265145933085529437, \ 303813780, 816375814318068602464139315741117, -237]", ); } #[test] #[should_panic] fn get_random_integer_from_range_to_infinity_fail_1() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, ); } #[test] #[should_panic] fn get_random_integer_from_range_to_infinity_fail_2() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, ); } #[test] #[should_panic] fn get_random_integer_from_range_to_infinity_fail_3() { get_random_integer_from_range_to_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::from(10u32).pow(100), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/get_random_integer_from_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; use malachite_base::num::random::{VariableRangeGenerator, random_primitive_ints}; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_random_integer_from_range_to_negative_infinity; use std::str::FromStr; fn get_random_integer_from_range_to_negative_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, out: &str, ) { let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); let xs = (0..10) .map(|_| { get_random_integer_from_range_to_negative_infinity( &mut xs, &mut vrg, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_integer_from_range_to_negative_infinity() { get_random_integer_from_range_to_negative_infinity_helper( "0", 1, 1, "[0, -1, -4, -1, -2, -1, -1, 0, 0, 0]", ); get_random_integer_from_range_to_negative_infinity_helper( "0", 10, 1, "[-7, -7816, -428, -130, -1, -141, -10, 0, -4, -4483]", ); get_random_integer_from_range_to_negative_infinity_helper( "0", 100, 1, "[-5101205056696451696397798478058511, -1562796, -8799850658374624318722, \ -43213315753966138396554154493451514495463595499011546992326984725965140902499491700065508\ 39187394388518593842616549212512013, -279353891976332938189472063076409154515, \ -1660357170525, \ -14364218889921873996063448912638758622428935178245280788493476815105151126528849038489284\ 922660727526851378407, -86075361492, \ -353552745516847393429177033516378899307448925328642, \ -577340679116474858586805525866181088123189468507069123812855481357566943854]", ); get_random_integer_from_range_to_negative_infinity_helper( "1000", 1, 1, "[-3, -2, -1, 1, 29, -3, 0, 0, -1, 0]", ); get_random_integer_from_range_to_negative_infinity_helper( "1000", 11, 1, "[-5135, -4, 108, -1, 3, -3, -3666351202, -1, -37251, 718]", ); get_random_integer_from_range_to_negative_infinity_helper( "1000", 100, 1, "[-2429686799, 648, -2730587924715692, 1, -4964076984094755832797, \ -829471522969346588791746968515146309473173680336193392475266233389518923764834, \ -89318048233905, -17177555, -451081617762069, -2086237]", ); get_random_integer_from_range_to_negative_infinity_helper( "-1000", 11, 1, "[-1008, -1672, -6316, -1282, -3037, -1805, -1122, -1020, -1009, -1004]", ); get_random_integer_from_range_to_negative_infinity_helper( "-1000", 100, 1, "[-1206982412795330974999926231143439, -457693356, -169360311075942561584386, \ -15686419808113360018248499311022273352461958876360329877976446836438259171328060860875588\ 4131404116709444244598775565, -66677412650746398524862933431554022355, -26949124609373, \ -10274641638611019453359307286994714963495455599965568795127967045604679999200234909658869\ 33126118631, -22626063730900, -2792352557430693060292673664470974590025115014402, \ -68488724460300171666815845652220555564874106206890863873832895385292448366]", ); } #[test] #[should_panic] fn get_random_integer_from_range_to_negative_infinity_fail_1() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, ); } #[test] #[should_panic] fn get_random_integer_from_range_to_negative_infinity_fail_2() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, ); } #[test] #[should_panic] fn get_random_integer_from_range_to_negative_infinity_fail_3() { get_random_integer_from_range_to_negative_infinity( &mut random_primitive_ints(EXAMPLE_SEED.fork("ints")), &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), -Integer::from(10u32).pow(100), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/get_striped_random_integer_from_inclusive_range.rs ================================================ // Copyright © 2026 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::num::random::VariableRangeGenerator; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_striped_random_integer_from_inclusive_range; use std::str::FromStr; fn get_striped_random_integer_from_inclusive_range_helper( m_numerator: u64, m_denominator: u64, a: &str, b: &str, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), m_numerator, m_denominator); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); let xs = (0..10) .map(|_| { get_striped_random_integer_from_inclusive_range( &mut bit_source, &mut vrg, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_integer_from_inclusive_range() { get_striped_random_integer_from_inclusive_range_helper( 2, 1, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_integer_from_inclusive_range_helper( 2, 1, "1950", "2019", "[2014, 1964, 2008, 1994, 1999, 1971, 1990, 1984, 2016, 2018]", ); get_striped_random_integer_from_inclusive_range_helper( 2, 1, "-10000", "9000", "[8458, 8998, 8818, -8899, -9414, 8703, 8540, 6141, 2042, 6456]", ); get_striped_random_integer_from_inclusive_range_helper( 2, 1, "-10000", "-1000", "[-8724, -9372, -8880, -9422, -8448, -9891, -8959, -8479, -1002, -4963]", ); get_striped_random_integer_from_inclusive_range_helper( 10, 1, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_integer_from_inclusive_range_helper( 10, 1, "1950", "2019", "[2016, 1987, 2019, 1951, 2019, 1951, 2019, 1951, 1950, 1950]", ); get_striped_random_integer_from_inclusive_range_helper( 10, 1, "-10000", "9000", "[8312, 8992, 8992, -10000, -2046, 8192, 0, 4095, 63, 2047]", ); get_striped_random_integer_from_inclusive_range_helper( 10, 1, "-10000", "-1000", "[-8432, -10000, -1023, -9999, -10000, -1016, -1000, -1007, -8192, -4095]", ); get_striped_random_integer_from_inclusive_range_helper( 11, 10, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_integer_from_inclusive_range_helper( 11, 10, "1950", "2019", "[1992, 1962, 2005, 2018, 1962, 2005, 2005, 2005, 1951, 2005]", ); get_striped_random_integer_from_inclusive_range_helper( 11, 10, "-10000", "9000", "[8634, 8874, 8362, -9557, -8877, 8874, 8533, 8362, 5461, 5333]", ); get_striped_random_integer_from_inclusive_range_helper( 11, 10, "-10000", "-1000", "[-9077, -9558, -8874, -9557, -8853, -9557, -8885, -8874, -5462, -2710]", ); } #[test] #[should_panic] fn get_striped_random_integer_from_inclusive_range_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); get_striped_random_integer_from_inclusive_range( &mut bit_source, &mut vrg, Integer::from(10u32), Integer::from(9u32), ); } ================================================ FILE: malachite-nz/tests/integer/random/get_striped_random_integer_from_range.rs ================================================ // Copyright © 2026 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::num::random::VariableRangeGenerator; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_striped_random_integer_from_range; use std::str::FromStr; fn get_striped_random_integer_from_range_helper( m_numerator: u64, m_denominator: u64, a: &str, b: &str, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), m_numerator, m_denominator); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); let xs = (0..10) .map(|_| { get_striped_random_integer_from_range( &mut bit_source, &mut vrg, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_integer_from_range() { get_striped_random_integer_from_range_helper(2, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_integer_from_range_helper( 2, 1, "1950", "2020", "[2014, 1964, 2008, 1994, 1999, 1971, 1990, 1984, 2016, 2018]", ); get_striped_random_integer_from_range_helper( 2, 1, "-10000", "9001", "[8458, 8998, 8818, -8899, -9414, 8703, 8540, 6141, 2042, 6456]", ); get_striped_random_integer_from_range_helper( 2, 1, "-10000", "-999", "[-8724, -9372, -8880, -9422, -8448, -9891, -8959, -8479, -1002, -4963]", ); get_striped_random_integer_from_range_helper(10, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_integer_from_range_helper( 10, 1, "1950", "2020", "[2016, 1987, 2019, 1951, 2019, 1951, 2019, 1951, 1950, 1950]", ); get_striped_random_integer_from_range_helper( 10, 1, "-10000", "9001", "[8312, 8992, 8992, -10000, -2046, 8192, 0, 4095, 63, 2047]", ); get_striped_random_integer_from_range_helper( 10, 1, "-10000", "-999", "[-8432, -10000, -1023, -9999, -10000, -1016, -1000, -1007, -8192, -4095]", ); get_striped_random_integer_from_range_helper( 11, 10, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_integer_from_range_helper( 11, 10, "1950", "2020", "[1992, 1962, 2005, 2018, 1962, 2005, 2005, 2005, 1951, 2005]", ); get_striped_random_integer_from_range_helper( 11, 10, "-10000", "9001", "[8634, 8874, 8362, -9557, -8877, 8874, 8533, 8362, 5461, 5333]", ); get_striped_random_integer_from_range_helper( 11, 10, "-10000", "-999", "[-9077, -9558, -8874, -9557, -8853, -9557, -8885, -8874, -5462, -2710]", ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vrg")); get_striped_random_integer_from_range( &mut bit_source, &mut vrg, Integer::from(10u32), Integer::from(9u32), ); } ================================================ FILE: malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_striped_random_integer_from_range_to_infinity; use std::str::FromStr; fn get_striped_random_integer_from_range_to_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, out: &str, ) { let mut bit_source = StripedBitSource::new( EXAMPLE_SEED.fork("bs"), mean_stripe_numerator, mean_stripe_denominator, ); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); let xs = (0..10) .map(|_| { get_striped_random_integer_from_range_to_infinity( &mut bit_source, &mut vrg, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_integer_from_range_to_infinity() { get_striped_random_integer_from_range_to_infinity_helper( "0", 10, 1, 1, 1, "[0, 1, 4, 1, 3, 1, 1, 0, 0, 0]", ); get_striped_random_integer_from_range_to_infinity_helper( "0", 10, 1, 10, 1, "[7, 4126, 511, 255, 1, 248, 15, 0, 7, 8191]", ); get_striped_random_integer_from_range_to_infinity_helper( "0", 10, 1, 100, 1, "[2920647185518839672075671782293383, 1048576, 4739083809502202445823, \ 528812496939392674605437340435408671558612951523319156054677508322810572932328766514425150\ 8429219658089743953085078238920703, 170472354644468060339516718901910044671, \ 1099511627776, \ 186415569962779171680854936542673085018277752582758046597588616311812447948859965258255723\ 66927316848155197439, 137436864511, 187077834941321271646236832607563322963774152898535, \ 897560034344005936431766292731307813053258931074478508157776167326430855104]", ); get_striped_random_integer_from_range_to_infinity_helper( "1000", 10, 1, 11, 1, "[1020, 2040, 4351, 1087, 4095, 1536, 2047, 1023, 1022, 1007]", ); get_striped_random_integer_from_range_to_infinity_helper( "1000", 10, 1, 100, 1, "[973535863568279311376735658835847, 268435456, 151115988660057280545023, \ 788041621480711912165160823578914479144879663560965225783543272513529599243438802396891675\ 96389234574457387517706367, 61144487963324812669777136988278751233, 35184372088704, \ 108958909782649556234624985077749301722270247350340375090485228690114398468811820627146895\ 0192652287, 34084862300097, 2922291218836765780501982453037225347447510761475, \ 113055782260031715275206575103088333621424376204588378848515940842185162750]", ); get_striped_random_integer_from_range_to_infinity_helper( "-1000", 10, 1, 1, 1, "[-3, -2, -1, 1, 17, -2, 0, 0, -1, 0]", ); get_striped_random_integer_from_range_to_infinity_helper( "-1000", 10, 1, 11, 1, "[-3, 188, -1, 3, -3, -512, 1073725455, 1023, 0, 2047]", ); get_striped_random_integer_from_range_to_infinity_helper( "-1000", 10, 1, 100, 1, "[130951, 19023203726501412800, 2055, 4629700416936738823, \ 206378257939585890650633610891897828407043084058691785319121408973257569307274994499096280\ 35369831199775792242011278409759, 295147869995014168352, 132373800004962371502079, \ 507510783, 1297559231579135076369342163583007, -128]", ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_infinity_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_infinity_fail_2() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_infinity_fail_3() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::from(10u32).pow(100), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/get_striped_random_integer_from_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Pow; use malachite_base::num::basic::traits::Zero; use malachite_base::num::random::VariableRangeGenerator; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_striped_random_integer_from_range_to_negative_infinity; use std::str::FromStr; fn get_striped_random_integer_from_range_to_negative_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, out: &str, ) { let mut bit_source = StripedBitSource::new( EXAMPLE_SEED.fork("bs"), mean_stripe_numerator, mean_stripe_denominator, ); let mut vrg = VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")); let xs = (0..10) .map(|_| { get_striped_random_integer_from_range_to_negative_infinity( &mut bit_source, &mut vrg, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_integer_from_range_to_negative_infinity() { get_striped_random_integer_from_range_to_negative_infinity_helper( "0", 10, 1, 1, 1, "[0, -1, -4, -1, -3, -1, -1, 0, 0, 0]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "0", 10, 1, 10, 1, "[-7, -4126, -511, -255, -1, -248, -15, 0, -7, -8191]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "0", 10, 1, 100, 1, "[-2920647185518839672075671782293383, -1048576, -4739083809502202445823, \ -52881249693939267460543734043540867155861295152331915605467750832281057293232876651442515\ 08429219658089743953085078238920703, -170472354644468060339516718901910044671, \ -1099511627776, -1864155699627791716808549365426730850182777525827580465975886163118124479\ 4885996525825572366927316848155197439, -137436864511, \ -187077834941321271646236832607563322963774152898535, \ -897560034344005936431766292731307813053258931074478508157776167326430855104]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "1000", 10, 1, 11, 1, "[-8071, -4, 127, -1, 3, -2, -2147484671, -1, -32775, 515]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "1000", 10, 1, 100, 1, "[-2151677831, 767, -2269323280383999, 1, -5008327044809161965583, \ -466786749337581235991134723080519000284817084727848060138773225560246511976448, \ -140672846790145, -29360131, -283605347598335, -2096896]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "-1000", 10, 1, 11, 1, "[-1020, -2040, -4351, -1087, -4095, -1536, -2047, -1023, -1022, -1007]", ); get_striped_random_integer_from_range_to_negative_infinity_helper( "-1000", 10, 1, 100, 1, "[-973535863568279311376735658835847, -268435456, -151115988660057280545023, \ -78804162148071191216516082357891447914487966356096522578354327251352959924343880239689167\ 596389234574457387517706367, -61144487963324812669777136988278751233, -35184372088704, \ -10895890978264955623462498507774930172227024735034037509048522869011439846881182062714689\ 50192652287, -34084862300097, -2922291218836765780501982453037225347447510761475, \ -113055782260031715275206575103088333621424376204588378848515940842185162750]", ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_negative_infinity_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_negative_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 1, 0, ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_negative_infinity_fail_2() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_negative_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), Integer::ZERO, 2, 0, ); } #[test] #[should_panic] fn get_striped_random_integer_from_range_to_negative_infinity_fail_3() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED.fork("bs"), 10, 1); get_striped_random_integer_from_range_to_negative_infinity( &mut bit_source, &mut VariableRangeGenerator::new(EXAMPLE_SEED.fork("vr")), -Integer::from(10).pow(100), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/get_uniform_random_integer_from_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_uniform_random_integer_from_inclusive_range; use std::str::FromStr; fn get_uniform_random_integer_from_inclusive_range_helper(a: &str, b: &str, out: &str) { let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); let xs = (0..10) .map(|_| { get_uniform_random_integer_from_inclusive_range( &mut xs, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_uniform_random_integer_from_inclusive_range() { get_uniform_random_integer_from_inclusive_range_helper( "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_uniform_random_integer_from_inclusive_range_helper( "1950", "2019", "[1965, 1958, 1994, 1952, 1963, 1953, 1999, 1971, 1970, 2011]", ); get_uniform_random_integer_from_inclusive_range_helper( "-10", "9", "[5, -2, 2, -8, 3, -8, -7, 4, 9, 7]", ); get_uniform_random_integer_from_inclusive_range_helper( "-10", "-1", "[-2, -8, -8, -7, -7, -9, -7, -5, -3, -6]", ); } #[test] #[should_panic] fn get_uniform_random_integer_from_inclusive_range_fail() { get_uniform_random_integer_from_inclusive_range( &mut random_primitive_ints(EXAMPLE_SEED), Integer::ONE, Integer::ZERO, ); } ================================================ FILE: malachite-nz/tests/integer/random/get_uniform_random_integer_from_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::integer::random::get_uniform_random_integer_from_range; use std::str::FromStr; fn get_uniform_random_integer_from_range_helper(a: &str, b: &str, out: &str) { let mut xs = random_primitive_ints(EXAMPLE_SEED.fork("ints")); let xs = (0..10) .map(|_| { get_uniform_random_integer_from_range( &mut xs, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_uniform_random_integer_from_range() { get_uniform_random_integer_from_range_helper("0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_uniform_random_integer_from_range_helper( "1950", "2020", "[1965, 1958, 1994, 1952, 1963, 1953, 1999, 1971, 1970, 2011]", ); get_uniform_random_integer_from_range_helper("-10", "10", "[5, -2, 2, -8, 3, -8, -7, 4, 9, 7]"); get_uniform_random_integer_from_range_helper( "-10", "0", "[-2, -8, -8, -7, -7, -9, -7, -5, -3, -6]", ); } #[test] #[should_panic] fn get_uniform_random_integer_from_range_fail() { get_uniform_random_integer_from_range( &mut random_primitive_ints(EXAMPLE_SEED), Integer::ZERO, Integer::ZERO, ); } ================================================ FILE: malachite-nz/tests/integer/random/random_integer_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integer_inclusive_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn random_integer_inclusive_range_helper( a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_integer_inclusive_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_integer_inclusive_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_inclusive_range_helper( "0", "0", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1", "0", "1", "-1", "-1", "-4", "-2", "-2", "-1", "-1", "0", "1", "2", "-4", "0", "1", "0", "0", "1", "0", ]; let common_values = &[ ("0", 284116), ("1", 189679), ("-1", 189332), ("-4", 84500), ("3", 63397), ("2", 63173), ("-3", 62961), ("-2", 62842), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.3356830000000005), standard_deviation: NiceFloat(1.8054398863225456), skewness: NiceFloat(-0.35221934475763134), excess_kurtosis: NiceFloat(-0.2458978296075136), }; random_integer_inclusive_range_helper( "-4", "3", 2, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1023", "1022", "1023", "1023", "1023", "1022", "1023", "1024", "1024", "1025", "1025", "1022", "1023", "1023", "1023", "1022", "1025", "1024", "1024", "1024", ]; let common_values = &[("1023", 300404), ("1022", 299811), ("1025", 200144), ("1024", 199641)]; let sample_median = ("1023", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1023.3001179999817), standard_deviation: NiceFloat(1.0999810889439465), skewness: NiceFloat(0.2889412070926685), excess_kurtosis: NiceFloat(-1.2389995110068848), }; random_integer_inclusive_range_helper( "1022", "1025", 12, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1023", "-1023", "-1023", "-1023", "-1023", "-1023", "-1023", "-1025", "-1024", "-1025", "-1024", "-1023", "-1023", "-1023", "-1023", "-1023", "-1025", "-1026", "-1024", "-1024", ]; let common_values = &[("-1023", 600215), ("-1024", 133294), ("-1026", 133261), ("-1025", 133230)]; let sample_median = ("-1023", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1023.7995370000281), standard_deviation: NiceFloat(1.1073864781257785), skewness: NiceFloat(-0.990171399672332), excess_kurtosis: NiceFloat(-0.5751529612720772), }; random_integer_inclusive_range_helper( "-1026", "-1023", 12, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "152", "1", "0", "-62", "5282", "0", "28", "-4", "-79", "-11", "2", "1", "-1", "82", "-1", "696", "-6", "-39", "1421", ]; let common_values = &[ ("0", 118542), ("1", 95287), ("-1", 95269), ("-3", 38248), ("3", 38202), ("2", 38150), ("-2", 38078), ("-4", 15429), ("7", 15423), ("-5", 15382), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(130.2935679999988), standard_deviation: NiceFloat(901.4375229872913), skewness: NiceFloat(7.858028656993447), excess_kurtosis: NiceFloat(67.9560213744922), }; random_integer_inclusive_range_helper( "-1000", "9999", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_integer_inclusive_range_fail_1() { random_integer_inclusive_range(EXAMPLE_SEED, Integer::from(-100), Integer::from(-10), 1, 0); } #[test] #[should_panic] fn random_integer_inclusive_range_fail_2() { random_integer_inclusive_range(EXAMPLE_SEED, Integer::from(-100), Integer::from(-10), 4, 1); } #[test] #[should_panic] fn random_integer_inclusive_range_fail_3() { random_integer_inclusive_range(EXAMPLE_SEED, Integer::from(-9), Integer::from(-10), 10, 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_integer_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integer_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn random_integer_range_helper( a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_integer_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_integer_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_helper( "0", "1", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1", "0", "1", "-1", "-1", "-4", "-2", "-2", "-1", "-1", "0", "1", "2", "-4", "0", "1", "0", "0", "1", "0", ]; let common_values = &[ ("0", 284116), ("1", 189679), ("-1", 189332), ("-4", 84500), ("3", 63397), ("2", 63173), ("-3", 62961), ("-2", 62842), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.3356830000000005), standard_deviation: NiceFloat(1.8054398863225456), skewness: NiceFloat(-0.35221934475763134), excess_kurtosis: NiceFloat(-0.2458978296075136), }; random_integer_range_helper( "-4", "4", 2, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1023", "1022", "1023", "1023", "1023", "1022", "1023", "1024", "1024", "1025", "1025", "1022", "1023", "1023", "1023", "1022", "1025", "1024", "1024", "1024", ]; let common_values = &[("1023", 300404), ("1022", 299811), ("1025", 200144), ("1024", 199641)]; let sample_median = ("1023", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1023.3001179999817), standard_deviation: NiceFloat(1.0999810889439465), skewness: NiceFloat(0.2889412070926685), excess_kurtosis: NiceFloat(-1.2389995110068848), }; random_integer_range_helper( "1022", "1026", 12, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1023", "-1023", "-1023", "-1023", "-1023", "-1023", "-1023", "-1025", "-1024", "-1025", "-1024", "-1023", "-1023", "-1023", "-1023", "-1023", "-1025", "-1026", "-1024", "-1024", ]; let common_values = &[("-1023", 600215), ("-1024", 133294), ("-1026", 133261), ("-1025", 133230)]; let sample_median = ("-1023", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1023.7995370000281), standard_deviation: NiceFloat(1.1073864781257785), skewness: NiceFloat(-0.990171399672332), excess_kurtosis: NiceFloat(-0.5751529612720772), }; random_integer_range_helper( "-1026", "-1022", 12, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "152", "1", "0", "-62", "5282", "0", "28", "-4", "-79", "-11", "2", "1", "-1", "82", "-1", "696", "-6", "-39", "1421", ]; let common_values = &[ ("0", 118542), ("1", 95287), ("-1", 95269), ("-3", 38248), ("3", 38202), ("2", 38150), ("-2", 38078), ("-4", 15429), ("7", 15423), ("-5", 15382), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(130.2935679999988), standard_deviation: NiceFloat(901.4375229872913), skewness: NiceFloat(7.858028656993447), excess_kurtosis: NiceFloat(67.9560213744922), }; random_integer_range_helper( "-1000", "10000", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_integer_range_fail_1() { random_integer_range(EXAMPLE_SEED, Integer::from(-100), Integer::from(-10), 1, 0); } #[test] #[should_panic] fn random_integer_range_fail_2() { random_integer_range(EXAMPLE_SEED, Integer::from(-100), Integer::from(-10), 4, 1); } #[test] #[should_panic] fn random_integer_range_fail_3() { random_integer_range(EXAMPLE_SEED, Integer::from(-9), Integer::from(-10), 10, 1); } #[test] #[should_panic] fn random_integer_range_fail_4() { random_integer_range(EXAMPLE_SEED, Integer::from(10), Integer::from(10), 10, 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_integer_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integer_range_to_infinity; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn random_integer_range_to_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_integer_range_to_infinity( EXAMPLE_SEED, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_integer_range_to_infinity() { let values = &[ "0", "14", "0", "8", "2", "6", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("2", 62676), ("3", 62465), ("7", 15819), ("5", 15781), ("6", 15694), ("4", 15518), ("13", 3945), ("8", 3895), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.289019000000012), standard_deviation: NiceFloat(811.503067487901), skewness: NiceFloat(791.581366511165), excess_kurtosis: NiceFloat(717047.0759703598), }; random_integer_range_to_infinity_helper( "0", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "20431208470830262", "2777240", "114", "12184833305054", "1121025855008623490210", "13478874522577592", "115311695", "7", "18", "54522366353", "2183264193236231773387459", "824", "18558864232439549193912", "15", "110989", "453270", "4307150", "45388024541", "47", "3345913274", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14233), ("2", 14194), ("7", 6984), ("6", 6980), ("4", 6964), ("5", 6929), ("10", 3479), ("15", 3431), ]; let sample_median = ("3201388", Some("3201522")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.480305129633914e129), standard_deviation: NiceFloat(2.4803051296331898e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_infinity_helper( "0", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "11", "182", "12", "152", "50", "94", "18", "11", "13", "15", "14", "13", "28", "24", "13", "13", "31", "19", "12", "13", ]; let common_values = &[ ("13", 83637), ("11", 83622), ("15", 83440), ("14", 83364), ("10", 83305), ("12", 82880), ("20", 15837), ("31", 15785), ("19", 15779), ("18", 15776), ]; let sample_median = ("15", None); let sample_moment_stats = MomentStats { mean: NiceFloat(128.81076899999977), standard_deviation: NiceFloat(15255.606035258177), skewness: NiceFloat(845.8189997295934), excess_kurtosis: NiceFloat(789803.2243471228), }; random_integer_range_to_infinity_helper( "10", 5, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "118", "56", "1714", "55845661150", "93254818", "822568088563644", "120", "871591019599", "99", "1171796531603249384284396706", "3570371", "76271186", "69092967935443594634663005648041578296", "110", "39", "25543539470733", "317538101910", "206", "14906804826461850333", "95450125556931311", ]; let common_values = &[ ("13", 5882), ("14", 5840), ("12", 5734), ("15", 5645), ("11", 5644), ("10", 5642), ("18", 2148), ("27", 2143), ("19", 2134), ("23", 2134), ]; let sample_median = ("7289020", Some("7289286")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8276128186777812e120), standard_deviation: NiceFloat(1.8276117282901724e123), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_infinity_helper( "10", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "-2", "-6", "0", "0", "-1", "-2", "-2", "2", "0", "0", "-1", "-7", "-2", "5", "0", "1", "1", "1", "-2", ]; let common_values = &[ ("0", 340125), ("-1", 170288), ("1", 170110), ("3", 42793), ("2", 42482), ("-2", 42480), ("-3", 42401), ("7", 10842), ("-6", 10756), ("-5", 10753), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(4.031789999999887), standard_deviation: NiceFloat(549.0621114688183), skewness: NiceFloat(481.1013689046789), excess_kurtosis: NiceFloat(256425.40976596656), }; random_integer_range_to_infinity_helper( "-10", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "89270", "69403499476962893258904", "62", "59700386", "45674428", "696", "0", "-3", "3235", "7330", "-5", "15043", "11858", "2541784888", "7007928", "1518", "23", "909", "60054", "1", ]; let common_values = &[ ("0", 27154), ("1", 26497), ("-1", 26298), ("-2", 12852), ("2", 12781), ("3", 12707), ("-3", 12664), ("-8", 8085), ("-10", 8066), ("-9", 7928), ]; let sample_median = ("293781", Some("293783")); let sample_moment_stats = MomentStats { mean: NiceFloat(6.04296612240715e153), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_infinity_helper( "-10", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1032867295426", "15476566285494", "1005058503561", "11872468885656", "3085108281010", "7786786793950", "1848070042786", "1008384510771", "1035939113223", "1034091049134", "1097997002237", "1066780473347", "1232902614972", "2160500927160", "1039676158979", "1075044604283", "1421346833487", "2100488049827", "1090935342918", "1033099299962", ]; let common_values = &[ ("1012318490312", 2), ("1020804407546", 2), ("1040579317197", 2), ("1041361099759", 2), ("1099357770481", 2), ("1000000358874", 1), ("1000000635467", 1), ("1000000743391", 1), ("1000001041678", 1), ("1000001124568", 1), ]; let sample_median = ("1099468717392", Some("1099468761569")); let sample_moment_stats = MomentStats { mean: NiceFloat(9002084314682.418), standard_deviation: NiceFloat(1175305974058995.2), skewness: NiceFloat(894.6662459454856), excess_kurtosis: NiceFloat(856946.924578041), }; random_integer_range_to_infinity_helper( "1000000000000", 41, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2282426752182", "3076375863448", "33871433858738", "193926771358011304414", "683117911635193788", "95918191752968866622136", "5399022933155", "2679643424229893512354", "7585953905347", "17738519421136481929559726434799186", "70600001019637432", "77299482847566318", "332646018266965594347466935183659688140188647", "4856563742926", "1110539913949", "8169120771017371179759", "142409202767618812372", "3612730358681", "468787385712310874935747551", "9607440468294695468459788", ]; let common_values = &[ ("1000006091267", 1), ("1000006483280", 1), ("1000008421992", 1), ("1000009071089", 1), ("1000011436758", 1), ("1000013492649", 1), ("1000014387323", 1), ("1000020641917", 1), ("1000020859147", 1), ("1000020971497", 1), ]; let sample_median = ("70366472614875784", Some("70368772587252716")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0984547559553134e113), standard_deviation: NiceFloat(1.098369190533207e116), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_infinity_helper( "1000000000000", 64, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "-2", "-6", "0", "0", "-1", "-2", "-2", "2", "0", "0", "-1", "-7", "-2", "5", "0", "1", "1", "1", "-2", ]; let common_values = &[ ("0", 332922), ("-1", 166652), ("1", 166524), ("3", 42164), ("2", 41585), ("-3", 41436), ("-2", 41400), ("5", 10546), ("4", 10540), ("-6", 10475), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.4130599999999974), standard_deviation: NiceFloat(777.5605240878597), skewness: NiceFloat(-244.83259806631784), excess_kurtosis: NiceFloat(225482.22529172004), }; random_integer_range_to_infinity_helper( "-1000000000000", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "89270", "69403499476962893258904", "62", "0", "61363647650", "-956", "120", "99407", "-5283", "-171170", "-346513", "-15043", "119462940242", "6836752184", "-1720", "-30", "-999", "-45453", "-54", "78", ]; let common_values = &[ ("0", 17993), ("1", 17632), ("-1", 17419), ("-2", 8480), ("-3", 8468), ("3", 8420), ("2", 8265), ("6", 4225), ("4", 4223), ("-4", 4199), ]; let sample_median = ("24", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.2795558914963709e155), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_infinity_helper( "-1000000000000", 32, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_integer_range_to_infinity_fail_1() { random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(10), 1, 0); } #[test] #[should_panic] fn random_integer_range_to_infinity_fail_2() { random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(10), 4, 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_integer_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integer_range_to_negative_infinity; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn random_integer_range_to_negative_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_integer_range_to_negative_infinity( EXAMPLE_SEED, Integer::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_integer_range_to_negative_infinity() { let values = &[ "0", "-14", "0", "-8", "-2", "-6", "-1", "0", "0", "0", "0", "0", "-1", "-1", "0", "0", "-1", "-1", "0", "0", ]; let common_values = &[ ("0", 500248), ("-1", 249491), ("-2", 62676), ("-3", 62465), ("-7", 15819), ("-5", 15781), ("-6", 15694), ("-4", 15518), ("-13", 3945), ("-8", 3895), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.289019000000012), standard_deviation: NiceFloat(811.503067487901), skewness: NiceFloat(-791.581366511165), excess_kurtosis: NiceFloat(717047.0759703598), }; random_integer_range_to_negative_infinity_helper( "0", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-20431208470830262", "-2777240", "-114", "-12184833305054", "-1121025855008623490210", "-13478874522577592", "-115311695", "-7", "-18", "-54522366353", "-2183264193236231773387459", "-824", "-18558864232439549193912", "-15", "-110989", "-453270", "-4307150", "-45388024541", "-47", "-3345913274", ]; let common_values = &[ ("0", 30467), ("-1", 29379), ("-3", 14233), ("-2", 14194), ("-7", 6984), ("-6", 6980), ("-4", 6964), ("-5", 6929), ("-10", 3479), ("-15", 3431), ]; let sample_median = ("-3201522", Some("-3201388")); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.480305129633914e129), standard_deviation: NiceFloat(2.4803051296331898e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_negative_infinity_helper( "0", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "-24", "-2", "-1", "-1", "-8124", "-2", "-321835205711", "-99", "-10", "-145", "-1", "-814468690", "-20280", "-120", "1", "-2023", "10", "-909", "-10902", ]; let common_values = &[ ("0", 116331), ("1", 97337), ("-1", 96828), ("-3", 40657), ("2", 40328), ("-2", 40302), ("3", 40199), ("10", 18790), ("9", 18745), ("8", 18603), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-324066858236836.2), standard_deviation: NiceFloat(2.1808471647947933e17), skewness: NiceFloat(-782.8568751691934), excess_kurtosis: NiceFloat(641629.0527568299), }; random_integer_range_to_negative_infinity_helper( "10", 5, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-2", "-69403499476962893258904", "-62", "-61363647650", "-64671510460", "0", "0", "-120", "-79", "-5283", "-171170", "-346513", "-15043", "-76271186", "-260083512", "-1720", "-1518", "1", "-3", "-49022969236123561123418405268118", ]; let common_values = &[ ("0", 27157), ("1", 26618), ("-1", 26439), ("-2", 12828), ("3", 12822), ("-3", 12808), ("2", 12788), ("10", 8081), ("9", 8077), ("8", 8044), ]; let sample_median = ("-276826", Some("-276824")); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.7536910581415426e155), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_negative_infinity_helper( "10", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-13", "-182", "-13", "-152", "-50", "-94", "-18", "-14", "-12", "-10", "-11", "-15", "-28", "-24", "-15", "-13", "-31", "-19", "-15", "-11", ]; let common_values = &[ ("-13", 83731), ("-10", 83540), ("-12", 83478), ("-14", 83457), ("-11", 83187), ("-15", 82855), ("-20", 15837), ("-31", 15785), ("-19", 15779), ("-18", 15776), ]; let sample_median = ("-15", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-128.80925900000398), standard_deviation: NiceFloat(15255.606046679814), skewness: NiceFloat(-845.8189981268482), excess_kurtosis: NiceFloat(789803.2223167756), }; random_integer_range_to_negative_infinity_helper( "-10", 5, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-118", "-56", "-1714", "-55845661150", "-93254818", "-822568088563644", "-120", "-871591019599", "-99", "-1171796531603249384284396706", "-3570371", "-76271186", "-69092967935443594634663005648041578296", "-110", "-39", "-25543539470733", "-317538101910", "-206", "-14906804826461850333", "-95450125556931311", ]; let common_values = &[ ("-13", 5852), ("-12", 5824), ("-14", 5824), ("-11", 5734), ("-10", 5589), ("-15", 5564), ("-18", 2148), ("-27", 2143), ("-19", 2134), ("-23", 2134), ]; let sample_median = ("-7289286", Some("-7289020")); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.8276128186777812e120), standard_deviation: NiceFloat(1.8276117282901724e123), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_negative_infinity_helper( "-10", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "-2", "-6", "0", "0", "-1", "-2", "-2", "2", "0", "0", "-1", "-7", "-2", "5", "0", "1", "1", "1", "-2", ]; let common_values = &[ ("0", 332922), ("-1", 166652), ("1", 166524), ("3", 42164), ("2", 41585), ("-3", 41436), ("-2", 41400), ("5", 10546), ("4", 10540), ("-6", 10475), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.4130599999999974), standard_deviation: NiceFloat(777.5605240878597), skewness: NiceFloat(-244.83259806631784), excess_kurtosis: NiceFloat(225482.22529172004), }; random_integer_range_to_negative_infinity_helper( "1000000000000", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "89270", "18359148696", "-50", "-1189717027294", "-61363647650", "956", "0", "120", "99407", "5283", "-171170", "-346513", "-15043", "-119462940242", "6836752184", "1720", "-30", "-999", "-45453", "-54", ]; let common_values = &[ ("0", 18088), ("1", 17624), ("-1", 17275), ("3", 8602), ("2", 8437), ("-3", 8322), ("-2", 8240), ("7", 4233), ("-6", 4129), ("-4", 4119), ]; let sample_median = ("-24", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.821612894174129e142), standard_deviation: NiceFloat(8.821611690087554e145), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_negative_infinity_helper( "1000000000000", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1098860169725", "-15476566285494", "-1039756450654", "-11872468885656", "-3085108281010", "-7786786793950", "-1848070042786", "-1001655869084", "-1066875920613", "-1005653510487", "-1039550426984", "-1016104838230", "-1232902614972", "-2160500927160", "-1077775969857", "-1032850377710", "-1421346833487", "-2100488049827", "-1095947428690", "-1014665028606", ]; let common_values = &[ ("-1002769937332", 2), ("-1073874696438", 2), ("-1000000188909", 1), ("-1000000496682", 1), ("-1000000510433", 1), ("-1000000739585", 1), ("-1000001292527", 1), ("-1000001626249", 1), ("-1000002315263", 1), ("-1000002353491", 1), ]; let sample_median = ("-1099462180132", Some("-1099461808833")); let sample_moment_stats = MomentStats { mean: NiceFloat(-9002075457674.271), standard_deviation: NiceFloat(1175305974119130.0), skewness: NiceFloat(-894.6662458308058), excess_kurtosis: NiceFloat(856946.9244296869), }; random_integer_range_to_negative_infinity_helper( "-1000000000000", 41, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-2282426752182", "-3076375863448", "-33871433858738", "-193926771358011304414", "-683117911635193788", "-95918191752968866622136", "-5399022933155", "-2679643424229893512354", "-7585953905347", "-17738519421136481929559726434799186", "-70600001019637432", "-77299482847566318", "-332646018266965594347466935183659688140188647", "-4856563742926", "-1110539913949", "-8169120771017371179759", "-142409202767618812372", "-3612730358681", "-468787385712310874935747551", "-9607440468294695468459788", ]; let common_values = &[ ("-1000001292527", 1), ("-1000003874527", 1), ("-1000008544047", 1), ("-1000010938009", 1), ("-1000029445751", 1), ("-1000041463842", 1), ("-1000043700145", 1), ("-1000044447812", 1), ("-1000047340863", 1), ("-1000049992535", 1), ]; let sample_median = ("-70368772587252716", Some("-70366472614875784")); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0984547559553134e113), standard_deviation: NiceFloat(1.098369190533207e116), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integer_range_to_negative_infinity_helper( "-1000000000000", 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_integer_range_to_negative_infinity_fail_1() { random_integer_range_to_negative_infinity(EXAMPLE_SEED, Integer::from(-10), 1, 0); } #[test] #[should_panic] fn random_integer_range_to_negative_infinity_fail_2() { random_integer_range_to_negative_infinity(EXAMPLE_SEED, Integer::from(-10), 4, 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::random_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn random_integers_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_integers(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_integers() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[ ("0", 969830), ("1", 14858), ("-1", 14856), ("-3", 128), ("-2", 122), ("3", 101), ("2", 98), ("7", 2), ("-4", 2), ("5", 1), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.00012800000000000482), standard_deviation: NiceFloat(0.18133950617561467), skewness: NiceFloat(-0.11594058747329855), excess_kurtosis: NiceFloat(53.17726403139359), }; random_integers_helper( 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "2", "-2", "-6", "0", "0", "-1", "-2", "-2", "2", "0", "0", "-1", "-7", "-2", "5", "0", "1", "1", "1", "-2", ]; let common_values = &[ ("0", 332922), ("-1", 166652), ("1", 166524), ("3", 42164), ("2", 41585), ("-3", 41436), ("-2", 41400), ("5", 10546), ("4", 10540), ("-6", 10475), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.4130599999999974), standard_deviation: NiceFloat(777.5605240878597), skewness: NiceFloat(-244.83259806631784), excess_kurtosis: NiceFloat(225482.22529172004), }; random_integers_helper( 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "89270", "69403499476962893258904", "62", "-1848070042786", "-64671510460", "-696", "0", "-79", "70819", "7330", "215441", "-424643", "-11858", "-84146163512", "-7212822200", "1518", "23", "-909", "-60054", "-46", ]; let common_values = &[ ("0", 15405), ("1", 15074), ("-1", 14891), ("-2", 7292), ("2", 7217), ("-3", 7168), ("3", 7120), ("5", 3593), ("-6", 3558), ("-7", 3542), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0417062616580636e155), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integers_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "15542", "204354108892664954266560767940941860034994328", "5282", "-323516", "-400812728", "-248570628312176883893327", "5606382754", "-63523217", "-15024295498724618356672330435", "25408382788335305673841323624499957642146385720", "70153184455655", "331577334953510974497668975717692627852954604565929960256566094891153641703901536975584071\ 2936487655650300919339856269", "-2179070834703641056854463566957970466590674233219693760530182904389383", "-5826316", "-8647284", "-1", "43088412843029635753589496830104451113312", "18608", "-3946823889925", "-114916707179919722397", ]; let common_values = &[ ("0", 7696), ("-1", 7685), ("1", 7575), ("-3", 3800), ("-2", 3773), ("3", 3717), ("2", 3679), ("7", 1889), ("6", 1862), ("-5", 1862), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.4757098576025357e248), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_integers_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_integers_fail_1() { random_integers(EXAMPLE_SEED, 0, 1); } #[test] #[should_panic] fn random_integers_fail_2() { random_integers(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_integers_fail_3() { random_integers(EXAMPLE_SEED, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_natural_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::random_natural_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn random_natural_integers_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_natural_integers(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_natural_integers() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[ ("0", 984681), ("1", 15077), ("2", 121), ("3", 116), ("6", 2), ("4", 1), ("5", 1), ("7", 1), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.015695000000000257), standard_deviation: NiceFloat(0.12853281096935348), skewness: NiceFloat(9.11690327111834), excess_kurtosis: NiceFloat(110.73931175909136), }; random_natural_integers_helper( 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "0", "14", "0", "8", "2", "6", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("2", 62676), ("3", 62465), ("7", 15819), ("5", 15781), ("6", 15694), ("4", 15518), ("13", 3945), ("8", 3895), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.289019000000012), standard_deviation: NiceFloat(811.503067487901), skewness: NiceFloat(791.581366511165), excess_kurtosis: NiceFloat(717047.0759703598), }; random_natural_integers_helper( 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "20431208470830262", "2777240", "114", "12184833305054", "1121025855008623490210", "13478874522577592", "115311695", "7", "18", "54522366353", "2183264193236231773387459", "824", "18558864232439549193912", "15", "110989", "453270", "4307150", "45388024541", "47", "3345913274", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14233), ("2", 14194), ("7", 6984), ("6", 6980), ("4", 6964), ("5", 6929), ("10", 3479), ("15", 3431), ]; let sample_median = ("3201388", Some("3201522")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.480305129633914e129), standard_deviation: NiceFloat(2.4803051296331898e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_integers_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1049807948069596877906281043152861735368289016372406", "1388880088667859422", "26145954", "3731388", "1470862095575962348216", "99", "1", "835275153", "3892061391890507266755", "925334710331614885833504493368", "221414670923422190", "11239", "254772031885", "1351005164080654998", "9136414433496904064275246960259217614", "1775", "5562", "8137327159764", "19744859531291384657393101375027010425831988999", "2078424122508695", ]; let common_values = &[ ("0", 15386), ("1", 15062), ("2", 7592), ("3", 7459), ("4", 3719), ("5", 3707), ("6", 3685), ("7", 3508), ("12", 1906), ("11", 1865), ]; let sample_median = ("15157534309527", Some("15157859817105")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8099447055615434e263), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_integers_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_natural_integers_fail_1() { random_natural_integers(EXAMPLE_SEED, 0, 1); } #[test] #[should_panic] fn random_natural_integers_fail_2() { random_natural_integers(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_natural_integers_fail_3() { random_natural_integers(EXAMPLE_SEED, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/integer/random/random_negative_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::random_negative_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn random_negative_integers_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_negative_integers(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_negative_integers() { // mean bits = 65/64 let values = &["-1"; 20]; let common_values = &[ ("-1", 984681), ("-3", 7622), ("-2", 7455), ("-5", 73), ("-6", 66), ("-7", 54), ("-4", 44), ("-8", 2), ("-10", 2), ("-14", 1), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.023822000000005), standard_deviation: NiceFloat(0.20727410662829246), skewness: NiceFloat(-10.72004433095801), excess_kurtosis: NiceFloat(159.60627558337237), }; random_negative_integers_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-1", "-24", "-1", "-30", "-6", "-12", "-2", "-1", "-1", "-1", "-1", "-1", "-2", "-2", "-1", "-1", "-3", "-3", "-1", "-1", ]; let common_values = &[ ("-1", 500248), ("-3", 124972), ("-2", 124519), ("-7", 31554), ("-5", 31346), ("-6", 31198), ("-4", 31043), ("-12", 8033), ("-11", 7959), ("-10", 7935), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-15.68562000000007), standard_deviation: NiceFloat(2088.3045530403606), skewness: NiceFloat(-877.2889258611025), excess_kurtosis: NiceFloat(832799.3689336807), }; random_negative_integers_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-22", "-4", "-178", "-55845661150", "-93254818", "-7577967529619388", "-8", "-11316951483471", "-11", "-1005760138411689342464923704482", "-948931", "-42716754", "-81013760999253680590984897748479904878392", "-23", "-5", "-488225822927510", "-1558028859598", "-29", "-200127331174844881647", "-4058622214797175252", ]; let common_values = &[ ("-1", 31094), ("-2", 15260), ("-3", 15185), ("-4", 7586), ("-5", 7376), ("-7", 7346), ("-6", 7258), ("-10", 3631), ("-14", 3607), ("-11", 3605), ]; let sample_median = ("-3799067", Some("-3799061")); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.312362311300544e130), standard_deviation: NiceFloat(2.3122865276852406e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_integers_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-1030304779202860497815440824491190", "-886085025458", "-207326", "-83590267817164982586207812646050", "-142592182196136038718074156629812683467448", "-486577913627642327503939268330036386", "-5557920650918595", "-82", "-3896", "-259694111319673990840", "-38511521798151392412656616617957654586378660839", "-637134", "-2330568192653124764618470467652346596061", "-2516", "-512663303", "-39317568409", "-18536901993439", "-4959577657266999117207", "-628", "-42485719907732979", ]; let common_values = &[ ("-1", 15720), ("-2", 7718), ("-3", 7584), ("-6", 3790), ("-4", 3739), ("-7", 3704), ("-5", 3673), ("-9", 1918), ("-11", 1916), ("-10", 1904), ]; let sample_median = ("-18438360920148", Some("-18436851140261")); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.519478531998525e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_integers_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_negative_integers_fail_1() { random_negative_integers(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_negative_integers_fail_2() { random_negative_integers(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/random_nonzero_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::random_nonzero_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn random_nonzero_integers_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_nonzero_integers(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_nonzero_integers() { // mean bits = 65/64 let values = &[ "1", "1", "1", "-1", "-1", "-1", "1", "-1", "-1", "1", "1", "1", "-1", "-1", "-1", "-1", "1", "1", "-1", "-1", ]; let common_values = &[ ("1", 492842), ("-1", 491818), ("2", 3836), ("3", 3803), ("-2", 3744), ("-3", 3718), ("6", 39), ("5", 33), ("-6", 32), ("-5", 31), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.001516999999999985), standard_deviation: NiceFloat(1.0444624404988267), skewness: NiceFloat(-0.00031392947248860435), excess_kurtosis: NiceFloat(-1.2267327517337354), }; random_nonzero_integers_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "6", "1", "6", "-14", "-1", "-1", "1", "-1", "-3", "6", "5", "7", "-1", "-1", "-2", "-14", "1", "5", "-14", "-1", ]; let common_values = &[ ("1", 249934), ("-1", 249480), ("3", 62818), ("-3", 62545), ("2", 62282), ("-2", 62281), ("-7", 15874), ("7", 15794), ("6", 15750), ("-5", 15696), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.677845999999954), standard_deviation: NiceFloat(1282.3370760759833), skewness: NiceFloat(271.563399149848), excess_kurtosis: NiceFloat(320730.53239180415), }; random_nonzero_integers_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "6", "373973144", "46887963477285686350042496363292819122", "-93254818", "-126908", "-4471675267836600", "1860142159", "-118004986915853475", "-98", "346513", "18250435", "511570", "-7230971744056", "-28344", "-1006", "-1", "45", "53968471397952150", "-1", "-5655261", ]; let common_values = &[ ("1", 15709), ("-1", 15677), ("-3", 7735), ("3", 7574), ("-2", 7514), ("2", 7484), ("-7", 3755), ("7", 3713), ("4", 3712), ("5", 3676), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.1307602130166568e111), standard_deviation: NiceFloat(2.1307597326341758e114), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_integers_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "121396406", "28091526743610625648357683081915367485486380400402584", "674", "-503972648740684226424764", "-261225431937620249973589071", "-1744034", "1", "-96963", "-33563594322", "1085240", "221961187000", "104563169774", "-799255527", "-32987221556354134413", "-8799240150400653965518", "-940783", "954", "16689620", "-392696864519", "-31641", ]; let common_values = &[ ("1", 7878), ("-1", 7830), ("-3", 3920), ("-2", 3913), ("3", 3882), ("2", 3809), ("-7", 1974), ("4", 1950), ("-6", 1939), ("-4", 1892), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_integers_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_nonzero_integers_fail_1() { random_nonzero_integers(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_nonzero_integers_fail_2() { random_nonzero_integers(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/random_positive_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::random_positive_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn random_positive_integers_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( random_positive_integers(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_positive_integers() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 984681), ("3", 7622), ("2", 7455), ("5", 73), ("6", 66), ("7", 54), ("4", 44), ("8", 2), ("10", 2), ("14", 1), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.023822000000005), standard_deviation: NiceFloat(0.20727410662829246), skewness: NiceFloat(10.72004433095801), excess_kurtosis: NiceFloat(159.60627558337237), }; random_positive_integers_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1", "24", "1", "30", "6", "12", "2", "1", "1", "1", "1", "1", "2", "2", "1", "1", "3", "3", "1", "1", ]; let common_values = &[ ("1", 500248), ("3", 124972), ("2", 124519), ("7", 31554), ("5", 31346), ("6", 31198), ("4", 31043), ("12", 8033), ("11", 7959), ("10", 7935), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(15.68562000000007), standard_deviation: NiceFloat(2088.3045530403606), skewness: NiceFloat(877.2889258611025), excess_kurtosis: NiceFloat(832799.3689336807), }; random_positive_integers_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "22", "4", "178", "55845661150", "93254818", "7577967529619388", "8", "11316951483471", "11", "1005760138411689342464923704482", "948931", "42716754", "81013760999253680590984897748479904878392", "23", "5", "488225822927510", "1558028859598", "29", "200127331174844881647", "4058622214797175252", ]; let common_values = &[ ("1", 31094), ("2", 15260), ("3", 15185), ("4", 7586), ("5", 7376), ("7", 7346), ("6", 7258), ("10", 3631), ("14", 3607), ("11", 3605), ]; let sample_median = ("3799061", Some("3799067")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.312362311300544e130), standard_deviation: NiceFloat(2.3122865276852406e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_integers_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1030304779202860497815440824491190", "886085025458", "207326", "83590267817164982586207812646050", "142592182196136038718074156629812683467448", "486577913627642327503939268330036386", "5557920650918595", "82", "3896", "259694111319673990840", "38511521798151392412656616617957654586378660839", "637134", "2330568192653124764618470467652346596061", "2516", "512663303", "39317568409", "18536901993439", "4959577657266999117207", "628", "42485719907732979", ]; let common_values = &[ ("1", 15720), ("2", 7718), ("3", 7584), ("6", 3790), ("4", 3739), ("7", 3704), ("5", 3673), ("9", 1918), ("11", 1916), ("10", 1904), ]; let sample_median = ("18436851140261", Some("18438360920148")); let sample_moment_stats = MomentStats { mean: NiceFloat(5.519478531998525e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_integers_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_positive_integers_fail_1() { random_positive_integers(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_positive_integers_fail_2() { random_positive_integers(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_integer_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integer_inclusive_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn striped_random_integer_inclusive_range_helper( a: &str, b: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_integer_inclusive_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), mean_stripe_numerator, mean_stripe_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_integer_inclusive_range() { let values = &[ "1990", "1991", "1991", "2006", "1996", "1991", "2020", "1991", "1990", "2014", "1990", "2020", "1991", "1990", "2020", "1991", "2015", "2020", "2016", "2016", ]; let common_values = &[ ("1990", 141061), ("1991", 140282), ("2016", 140025), ("2021", 125104), ("2020", 124770), ("2017", 47126), ("2019", 46880), ("1999", 39864), ("2015", 39502), ("2018", 15866), ]; let sample_median = ("2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(-0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_integer_inclusive_range_helper( "1990", "2021", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1990", "-1991", "-1991", "-2006", "-1996", "-1991", "-2020", "-1991", "-1990", "-2014", "-1990", "-2020", "-1991", "-1990", "-2020", "-1991", "-2015", "-2020", "-2016", "-2016", ]; let common_values = &[ ("-1990", 141061), ("-1991", 140282), ("-2016", 140025), ("-2021", 125104), ("-2020", 124770), ("-2017", 47126), ("-2019", 46880), ("-1999", 39864), ("-2015", 39502), ("-2018", 15866), ]; let sample_median = ("-2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_integer_inclusive_range_helper( "-2021", "-1990", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1792", "-1766", "1551", "111", "-1567", "16", "1985", "142", "1935", "992", "3", "-510", "1984", "-624", "-30", "-1542", "-1", "-2017", "-1927", "-7", ]; let common_values = &[ ("1990", 29612), ("1984", 22443), ("-1", 19100), ("-2016", 16609), ("-2021", 14942), ("-2020", 14868), ("0", 13951), ("1985", 7476), ("1987", 7411), ("1988", 7362), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.049800999999855), standard_deviation: NiceFloat(1269.7724478413352), skewness: NiceFloat(-0.007894098306828256), excess_kurtosis: NiceFloat(-1.0358454536315198), }; striped_random_integer_inclusive_range_helper( "-2021", "1990", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_integer_inclusive_range_fail_1() { striped_random_integer_inclusive_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(100u32), 1, 0, ); } #[test] #[should_panic] fn striped_random_integer_inclusive_range_fail_2() { striped_random_integer_inclusive_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(100u32), 1, 1, ); } #[test] #[should_panic] fn striped_random_integer_inclusive_range_fail_3() { striped_random_integer_inclusive_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(9u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_integer_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integer_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn striped_random_integer_range_helper( a: &str, b: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_integer_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), mean_stripe_numerator, mean_stripe_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_integer_range() { let values = &[ "1990", "1991", "1991", "2006", "1996", "1991", "2020", "1991", "1990", "2014", "1990", "2020", "1991", "1990", "2020", "1991", "2015", "2020", "2016", "2016", ]; let common_values = &[ ("1990", 141061), ("1991", 140282), ("2016", 140025), ("2021", 125104), ("2020", 124770), ("2017", 47126), ("2019", 46880), ("1999", 39864), ("2015", 39502), ("2018", 15866), ]; let sample_median = ("2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(-0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_integer_range_helper( "1990", "2022", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1990", "-1991", "-1991", "-2006", "-1996", "-1991", "-2020", "-1991", "-1990", "-2014", "-1990", "-2020", "-1991", "-1990", "-2020", "-1991", "-2015", "-2020", "-2016", "-2016", ]; let common_values = &[ ("-1990", 141061), ("-1991", 140282), ("-2016", 140025), ("-2021", 125104), ("-2020", 124770), ("-2017", 47126), ("-2019", 46880), ("-1999", 39864), ("-2015", 39502), ("-2018", 15866), ]; let sample_median = ("-2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_integer_range_helper( "-2021", "-1989", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1792", "-1766", "1551", "111", "-1567", "16", "1985", "142", "1935", "992", "3", "-510", "1984", "-624", "-30", "-1542", "-1", "-2017", "-1927", "-7", ]; let common_values = &[ ("1990", 29612), ("1984", 22443), ("-1", 19100), ("-2016", 16609), ("-2021", 14942), ("-2020", 14868), ("0", 13951), ("1985", 7476), ("1987", 7411), ("1988", 7362), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.049800999999855), standard_deviation: NiceFloat(1269.7724478413352), skewness: NiceFloat(-0.007894098306828256), excess_kurtosis: NiceFloat(-1.0358454536315198), }; striped_random_integer_range_helper( "-2021", "1991", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_integer_range_fail_1() { striped_random_integer_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(100u32), 1, 0, ); } #[test] #[should_panic] fn striped_random_integer_range_fail_2() { striped_random_integer_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(100u32), 1, 1, ); } #[test] #[should_panic] fn striped_random_integer_range_fail_3() { striped_random_integer_range( EXAMPLE_SEED, Integer::from(10u32), Integer::from(9u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_integer_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integer_range_to_infinity; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn striped_random_integer_range_to_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_integer_range_to_infinity( EXAMPLE_SEED, Integer::from_str(a).unwrap(), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_integer_range_to_infinity() { let values = &[ "2", "4", "128", "1124203576", "4", "15", "32", "751", "6400", "8376024595", "3", "60", "1", "1", "65045535", "6", "0", "7", "73608", "719661083353407616", ]; let common_values = &[ ("0", 90859), ("1", 82901), ("3", 37653), ("2", 37438), ("7", 25786), ("4", 25681), ("8", 17394), ("15", 17328), ("16", 12055), ("31", 11982), ]; let sample_median = ("71", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.068551928510147e34), standard_deviation: NiceFloat(6.914607365781463e37), skewness: NiceFloat(958.8924868378492), excess_kurtosis: NiceFloat(939262.8054862365), }; striped_random_integer_range_to_infinity_helper( "0", 4, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "8192", "8312", "15614", "1984", "1568", "1021", "1791", "260174", "9855", "98176", "1519", "2591", "3616", "8176", "1796", "8167", "262616", "4069", "12062", "1072", ]; let common_values = &[ ("1023", 31964), ("1007", 28139), ("1000", 28045), ("1008", 10625), ("1022", 10572), ("1016", 10499), ("1020", 10300), ("1004", 9705), ("1006", 9498), ("1003", 9422), ]; let sample_median = ("4159", None); let sample_moment_stats = MomentStats { mean: NiceFloat(54201665904379.625), standard_deviation: NiceFloat(2.6365321443458296e16), skewness: NiceFloat(608.9470987335318), excess_kurtosis: NiceFloat(388228.1677811064), }; striped_random_integer_range_to_infinity_helper( "1000", 4, 1, 14, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "8192", "2", "1084", "18871288", "-192", "519", "8", "16769337", "-408", "-65", "-11", "388992", "8", "0", "-188", "0", "67044287", "3297545015170", "-57", "4", ]; let common_values = &[ ("0", 58215), ("-1", 53215), ("1", 52942), ("3", 24172), ("-3", 24170), ("-2", 24102), ("2", 24042), ("7", 16555), ("-7", 16514), ("4", 16507), ]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5127815180423845e54), standard_deviation: NiceFloat(1.512781518042442e57), skewness: NiceFloat(999.9984999993533), excess_kurtosis: NiceFloat(999995.0000009801), }; striped_random_integer_range_to_infinity_helper( "-1000", 4, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_integer_range_to_infinity_fail_1() { striped_random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(100u32), 1, 0, 10, 1); } #[test] #[should_panic] fn striped_random_integer_range_to_infinity_fail_2() { striped_random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(100u32), 1, 1, 10, 1); } #[test] #[should_panic] fn striped_random_integer_range_to_infinity_fail_3() { striped_random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(100u32), 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_integer_range_to_infinity_fail_4() { striped_random_integer_range_to_infinity(EXAMPLE_SEED, Integer::from(100u32), 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_integer_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integer_range_to_negative_infinity; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn striped_random_integer_range_to_negative_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_integer_range_to_negative_infinity( EXAMPLE_SEED, Integer::from_str(a).unwrap(), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_integer_range_to_negative_infinity() { let values = &[ "-2", "-4", "-128", "-1124203576", "-4", "-15", "-32", "-751", "-6400", "-8376024595", "-3", "-60", "-1", "-1", "-65045535", "-6", "0", "-7", "-73608", "-719661083353407616", ]; let common_values = &[ ("0", 90859), ("-1", 82901), ("-3", 37653), ("-2", 37438), ("-7", 25786), ("-4", 25681), ("-8", 17394), ("-15", 17328), ("-16", 12055), ("-31", 11982), ]; let sample_median = ("-71", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.068551928510147e34), standard_deviation: NiceFloat(6.914607365781463e37), skewness: NiceFloat(-958.8924868378492), excess_kurtosis: NiceFloat(939262.8054862365), }; striped_random_integer_range_to_negative_infinity_helper( "0", 4, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "4", "2", "-1024", "-270182996582056056", "-263128", "798", "-15", "-16744652", "479", "68", "11", "-1072708599", "-10", "0", "240", "0", "-34521100", "-4385034796639", "-60", "-7", ]; let common_values = &[ ("0", 58400), ("1", 53191), ("-1", 53081), ("-3", 24269), ("3", 24150), ("2", 24142), ("-2", 23864), ("7", 16659), ("4", 16517), ("-4", 16397), ]; let sample_median = ("-3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.9240865426395e50), standard_deviation: NiceFloat(3.92408654263964e53), skewness: NiceFloat(-999.9984999993759), excess_kurtosis: NiceFloat(999995.0000009785), }; striped_random_integer_range_to_negative_infinity_helper( "1000", 4, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-8192", "-8312", "-15614", "-1984", "-1568", "-1009", "-1791", "-260174", "-9855", "-98176", "-1519", "-2591", "-3616", "-8176", "-1796", "-8167", "-262616", "-4069", "-12062", "-1072", ]; let common_values = &[ ("-1023", 31892), ("-1007", 28274), ("-1000", 28157), ("-1008", 10740), ("-1022", 10689), ("-1016", 10551), ("-1020", 10510), ("-1001", 9498), ("-1004", 9330), ("-1006", 9302), ]; let sample_median = ("-4159", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-54201665904379.41), standard_deviation: NiceFloat(2.6365321443458296e16), skewness: NiceFloat(-608.9470987335318), excess_kurtosis: NiceFloat(388228.1677811064), }; striped_random_integer_range_to_negative_infinity_helper( "-1000", 4, 1, 14, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_integer_range_to_negative_infinity_fail_1() { striped_random_integer_range_to_negative_infinity( EXAMPLE_SEED, Integer::from(100), 1, 0, 10, 1, ); } #[test] #[should_panic] fn striped_random_integer_range_to_negative_infinity_fail_2() { striped_random_integer_range_to_negative_infinity( EXAMPLE_SEED, Integer::from(100), 1, 1, 10, 1, ); } #[test] #[should_panic] fn striped_random_integer_range_to_negative_infinity_fail_3() { striped_random_integer_range_to_negative_infinity(EXAMPLE_SEED, Integer::from(100), 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_integer_range_to_negative_infinity_fail_4() { striped_random_integer_range_to_negative_infinity( EXAMPLE_SEED, Integer::from(-100), 4, 1, 2, 3, ); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::striped_random_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn striped_random_integers_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_integers( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_integers() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[ ("0", 969830), ("1", 14858), ("-1", 14856), ("-3", 135), ("2", 115), ("-2", 115), ("3", 84), ("-7", 3), ("4", 2), ("7", 1), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.00016100000000001123), standard_deviation: NiceFloat(0.18124295000911678), skewness: NiceFloat(-0.332760005499994), excess_kurtosis: NiceFloat(53.997755862907425), }; striped_random_integers_helper( 4, 1, 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "2", "-2", "-4", "0", "0", "-1", "-2", "-3", "2", "0", "0", "-1", "-4", "-3", "7", "0", "1", "1", "1", "-3", ]; let common_values = &[ ("0", 332922), ("-1", 166652), ("1", 166524), ("2", 42176), ("3", 41573), ("-2", 41508), ("-3", 41328), ("4", 15789), ("-7", 15751), ("7", 15560), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.8722809999999835), standard_deviation: NiceFloat(809.560511708087), skewness: NiceFloat(-339.00725481029485), excess_kurtosis: NiceFloat(238310.7740951809), }; striped_random_integers_helper( 4, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "65536", "75521006248971741167616", "32", "-2199023255520", "-68719468544", "-527", "0", "-112", "131071", "4152", "262143", "-262145", "-8192", "-137405429760", "-4294967296", "1219", "16", "-1023", "-32768", "-32", ]; let common_values = &[ ("0", 15405), ("1", 15074), ("-1", 14891), ("-3", 7324), ("2", 7197), ("3", 7140), ("-2", 7136), ("7", 6709), ("-7", 6675), ("-4", 6660), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.1248652082766593e155), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_integers_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "8192", "178427569518544464724715670468776264076361728", "8176", "-262144", "-268435456", "-226655146685469074391039", "4294967296", "-67108863", "-19807040628566083848630173696", "45671926166590716193865150952632647489410830335", "43978334404607", "252172839656924666985926477663676528888687738185461429445660194859797887186474365257113263\ 9068666062843684114535546880", "-1728806579227565766676057273846916536097145074328900789155504620306432", "-4194304", "-16777215", "-1", "43556142803623322374103370143943282917375", "31742", "-4123168604160", "-129703669268270284799", ]; let common_values = &[ ("0", 7696), ("-1", 7685), ("1", 7575), ("-2", 3831), ("-3", 3742), ("3", 3735), ("2", 3661), ("-4", 3643), ("7", 3615), ("4", 3570), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.346385398054525e248), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_integers_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_integers_fail_1() { striped_random_integers(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_integers_fail_2() { striped_random_integers(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_integers_fail_3() { striped_random_integers(EXAMPLE_SEED, 4, 1, 0, 1); } #[test] #[should_panic] fn striped_random_integers_fail_4() { striped_random_integers(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_integers_fail_5() { striped_random_integers(EXAMPLE_SEED, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_natural_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::striped_random_natural_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn striped_random_natural_integers_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_natural_integers( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_natural_integers() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[("0", 984681), ("1", 15077), ("3", 120), ("2", 117), ("4", 3), ("5", 1), ("7", 1)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.015695000000000875), standard_deviation: NiceFloat(0.12845498618458842), skewness: NiceFloat(9.02636021695415), excess_kurtosis: NiceFloat(104.38317092740806), }; striped_random_natural_integers_helper( 4, 1, 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "0", "8", "0", "8", "2", "4", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("3", 62636), ("2", 62505), ("4", 23595), ("7", 23447), ("8", 8713), ("15", 8690), ("6", 7938), ("5", 7832), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.16843100000002), standard_deviation: NiceFloat(782.5565010647151), skewness: NiceFloat(800.2073401417995), excess_kurtosis: NiceFloat(728738.7203924827), }; striped_random_natural_integers_helper( 4, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "18014656207519744", "2228160", "64", "17592184995840", "1179440951012584587264", "9007749010526207", "67108864", "5", "24", "34359738879", "2417851639228158863474687", "512", "9444737328601429442560", "8", "131071", "524032", "8388607", "34359738368", "60", "2147741695", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14232), ("2", 14195), ("4", 13131), ("7", 13019), ("8", 11921), ("15", 11751), ("31", 10682), ("16", 10555), ]; let sample_median = ("3670016", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.459178425232889e129), standard_deviation: NiceFloat(1.459178425232619e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_natural_integers_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1473193827441715154886135497317777215948837626052608", "1152921504606846976", "16777216", "4128768", "1180591620717412351744", "127", "1", "1073741823", "4722366482869645209600", "1267650600226049676594364547199", "288230376151711743", "8192", "274869520368", "1152921504606846976", "5317074242107007699768820031345917967", "1024", "8191", "4398046511104", "11417981541647679048466288345891489974790914528", "2251799813685247", ]; let common_values = &[ ("0", 15386), ("1", 15062), ("2", 7584), ("3", 7467), ("4", 7110), ("7", 7017), ("8", 6866), ("15", 6763), ("31", 6505), ("16", 6460), ]; let sample_median = ("17592169267200", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.6414828903095017e263), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_natural_integers_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_natural_integers_fail_1() { striped_random_natural_integers(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_natural_integers_fail_2() { striped_random_natural_integers(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_natural_integers_fail_3() { striped_random_natural_integers(EXAMPLE_SEED, 4, 1, 0, 1); } #[test] #[should_panic] fn striped_random_natural_integers_fail_4() { striped_random_natural_integers(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_natural_integers_fail_5() { striped_random_natural_integers(EXAMPLE_SEED, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_negative_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::striped_random_negative_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn striped_random_negative_integers_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_negative_integers( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_negative_integers() { // mean bits = 65/64 let values = &["-1"; 20]; let common_values = &[ ("-1", 984681), ("-3", 7637), ("-2", 7440), ("-4", 97), ("-7", 78), ("-5", 33), ("-6", 29), ("-11", 2), ("-8", 1), ("-9", 1), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.023796999999977), standard_deviation: NiceFloat(0.20691241046333197), skewness: NiceFloat(-10.752762867801868), excess_kurtosis: NiceFloat(162.40220891738076), }; striped_random_negative_integers_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-1", "-16", "-1", "-16", "-4", "-15", "-2", "-1", "-1", "-1", "-1", "-1", "-2", "-2", "-1", "-1", "-3", "-2", "-1", "-1", ]; let common_values = &[ ("-1", 500248), ("-2", 124818), ("-3", 124673), ("-7", 47032), ("-4", 46853), ("-8", 17749), ("-15", 17612), ("-5", 15660), ("-6", 15596), ("-16", 6518), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-15.773014000000762), standard_deviation: NiceFloat(2128.8810534178506), skewness: NiceFloat(-884.8410850537254), excess_kurtosis: NiceFloat(843254.2507640689), }; striped_random_negative_integers_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-16", "-4", "-128", "-34391195648", "-75493376", "-9007199120523391", "-8", "-8796094070783", "-8", "-950737950171027935941967741439", "-1040391", "-33554432", "-84390026996392738938916902643112875376640", "-30", "-7", "-554153860399104", "-2199023255551", "-16", "-220784470296873664512", "-4611685966886694919", ]; let common_values = &[ ("-1", 31094), ("-3", 15250), ("-2", 15195), ("-7", 13890), ("-4", 13880), ("-8", 12601), ("-15", 12519), ("-31", 11397), ("-16", 11237), ("-63", 10225), ]; let sample_median = ("-4194272", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.1641486095650758e130), standard_deviation: NiceFloat(1.1640776313097e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_integers_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-649037107316853596555600210165760", "-822486237184", "-196608", "-141976867225561692967630759002112", "-174223242635524708377374895198005052307456", "-664594824829454142366461086851399679", "-4503599627370496", "-127", "-2048", "-147574233996470517759", "-45660775794157599311165096735019350831520546815", "-1048320", "-1361212544433490269424560431578983940096", "-3968", "-536870911", "-34359738368", "-35184372088831", "-9297159013149614014464", "-768", "-72040001986101247", ]; let common_values = &[ ("-1", 15720), ("-2", 7656), ("-3", 7646), ("-7", 7219), ("-4", 7199), ("-8", 7122), ("-15", 6934), ("-31", 6799), ("-16", 6750), ("-63", 6456), ]; let sample_median = ("-17592186044416", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.796251092974677e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_integers_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_negative_integers_fail_1() { striped_random_negative_integers(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_negative_integers_fail_2() { striped_random_negative_integers(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_negative_integers_fail_3() { striped_random_negative_integers(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_negative_integers_fail_4() { striped_random_negative_integers(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_nonzero_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::striped_random_nonzero_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn striped_random_nonzero_integers_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_nonzero_integers( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_nonzero_integers() { // mean bits = 65/64 let values = &[ "1", "1", "1", "-1", "-1", "-1", "1", "-1", "-1", "1", "1", "1", "-1", "-1", "-1", "-1", "1", "1", "-1", "-1", ]; let common_values = &[ ("1", 492842), ("-1", 491818), ("2", 3848), ("3", 3791), ("-3", 3753), ("-2", 3709), ("7", 50), ("4", 49), ("-4", 41), ("-7", 36), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0015040000000000353), standard_deviation: NiceFloat(1.0443710206123127), skewness: NiceFloat(0.0008346150701385402), excess_kurtosis: NiceFloat(-1.2794877665824687), }; striped_random_nonzero_integers_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "4", "1", "4", "-8", "-1", "-1", "1", "-1", "-2", "7", "7", "6", "-1", "-1", "-3", "-14", "1", "4", "-8", "-1", ]; let common_values = &[ ("1", 249934), ("-1", 249480), ("3", 62605), ("-3", 62544), ("2", 62495), ("-2", 62282), ("4", 23545), ("-7", 23428), ("7", 23343), ("-4", 23304), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.9232179999999961), standard_deviation: NiceFloat(942.1853934867996), skewness: NiceFloat(-30.544317259845204), excess_kurtosis: NiceFloat(179726.72807613286), }; striped_random_nonzero_integers_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "4", "268435456", "84405977732342160290572740160760316144", "-133169152", "-131064", "-2251834173421823", "1577058304", "-126100789566374399", "-76", "270335", "33554431", "262144", "-4398046511104", "-20352", "-1023", "-1", "63", "72057589742960640", "-1", "-8388607", ]; let common_values = &[ ("1", 15709), ("-1", 15677), ("-3", 7646), ("-2", 7603), ("3", 7564), ("2", 7494), ("4", 6925), ("7", 6916), ("-7", 6903), ("-4", 6802), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.5217288846207e111), standard_deviation: NiceFloat(2.5217283396166554e114), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_integers_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "67108864", "47890485651710580317658107747553101683567604294221824", "512", "-311675034947891977256960", "-309485009821345068724780928", "-1179647", "1", "-131071", "-17179869184", "1056767", "273820942303", "137438952504", "-536870912", "-36749372959343247360", "-4722366482869645217791", "-786432", "1023", "8388608", "-274911460352", "-24575", ]; let common_values = &[ ("1", 7878), ("-1", 7830), ("-3", 3940), ("-2", 3893), ("2", 3885), ("3", 3806), ("4", 3707), ("-7", 3694), ("-4", 3689), ("7", 3608), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(f64::NAN), standard_deviation: NiceFloat(f64::NAN), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_integers_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_nonzero_integers_fail_1() { striped_random_nonzero_integers(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_nonzero_integers_fail_2() { striped_random_nonzero_integers(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_nonzero_integers_fail_3() { striped_random_nonzero_integers(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_nonzero_integers_fail_4() { striped_random_nonzero_integers(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/striped_random_positive_integers.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::random::striped_random_positive_integers; use malachite_nz::test_util::integer::random::random_integers_helper_helper; fn striped_random_positive_integers_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( striped_random_positive_integers( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_positive_integers() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 984681), ("3", 7637), ("2", 7440), ("4", 97), ("7", 78), ("5", 33), ("6", 29), ("11", 2), ("8", 1), ("9", 1), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.023796999999977), standard_deviation: NiceFloat(0.20691241046333197), skewness: NiceFloat(10.752762867801868), excess_kurtosis: NiceFloat(162.40220891738076), }; striped_random_positive_integers_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1", "16", "1", "16", "4", "15", "2", "1", "1", "1", "1", "1", "2", "2", "1", "1", "3", "2", "1", "1", ]; let common_values = &[ ("1", 500248), ("2", 124818), ("3", 124673), ("7", 47032), ("4", 46853), ("8", 17749), ("15", 17612), ("5", 15660), ("6", 15596), ("16", 6518), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(15.773014000000762), standard_deviation: NiceFloat(2128.8810534178506), skewness: NiceFloat(884.8410850537254), excess_kurtosis: NiceFloat(843254.2507640689), }; striped_random_positive_integers_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "16", "4", "128", "34391195648", "75493376", "9007199120523391", "8", "8796094070783", "8", "950737950171027935941967741439", "1040391", "33554432", "84390026996392738938916902643112875376640", "30", "7", "554153860399104", "2199023255551", "16", "220784470296873664512", "4611685966886694919", ]; let common_values = &[ ("1", 31094), ("3", 15250), ("2", 15195), ("7", 13890), ("4", 13880), ("8", 12601), ("15", 12519), ("31", 11397), ("16", 11237), ("63", 10225), ]; let sample_median = ("4194272", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.1641486095650758e130), standard_deviation: NiceFloat(1.1640776313097e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_integers_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "649037107316853596555600210165760", "822486237184", "196608", "141976867225561692967630759002112", "174223242635524708377374895198005052307456", "664594824829454142366461086851399679", "4503599627370496", "127", "2048", "147574233996470517759", "45660775794157599311165096735019350831520546815", "1048320", "1361212544433490269424560431578983940096", "3968", "536870911", "34359738368", "35184372088831", "9297159013149614014464", "768", "72040001986101247", ]; let common_values = &[ ("1", 15720), ("2", 7656), ("3", 7646), ("7", 7219), ("4", 7199), ("8", 7122), ("15", 6934), ("31", 6799), ("16", 6750), ("63", 6456), ]; let sample_median = ("17592186044416", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.796251092974677e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_integers_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_positive_integers_fail_1() { striped_random_positive_integers(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_positive_integers_fail_2() { striped_random_positive_integers(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_positive_integers_fail_3() { striped_random_positive_integers(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_positive_integers_fail_4() { striped_random_positive_integers(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/integer/random/uniform_random_integer_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::uniform_random_integer_inclusive_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn uniform_random_integer_inclusive_range_helper( a: &str, b: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( uniform_random_integer_inclusive_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_uniform_random_integer_inclusive_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; uniform_random_integer_inclusive_range_helper( "0", "0", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-3", "3", "1", "1", "3", "-3", "-2", "-4", "-2", "-1", "0", "-1", "2", "1", "2", "2", "-1", "-3", "-1", "3", ]; let common_values = &[ ("-2", 125739), ("-1", 125293), ("2", 125220), ("3", 125016), ("-4", 124976), ("1", 124665), ("-3", 124627), ("0", 124464), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5004029999999962), standard_deviation: NiceFloat(2.291244004332587), skewness: NiceFloat(0.0011305808123400524), excess_kurtosis: NiceFloat(-1.2381429974564255), }; uniform_random_integer_inclusive_range_helper( "-4", "3", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1023", "1025", "1023", "1023", "1025", "1023", "1024", "1022", "1024", "1025", "1022", "1025", "1024", "1023", "1024", "1024", "1025", "1023", "1025", "1025", ]; let common_values = &[("1024", 250959), ("1025", 250309), ("1022", 249440), ("1023", 249292)]; let sample_median = ("1024", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1023.5021369999873), standard_deviation: NiceFloat(1.1178079811513417), skewness: NiceFloat(-0.003486279405775989), excess_kurtosis: NiceFloat(-1.3594690811608392), }; uniform_random_integer_inclusive_range_helper( "1022", "1025", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1025", "-1023", "-1025", "-1025", "-1023", "-1025", "-1024", "-1026", "-1024", "-1023", "-1026", "-1023", "-1024", "-1025", "-1024", "-1024", "-1023", "-1025", "-1023", "-1023", ]; let common_values = &[("-1024", 250959), ("-1023", 250309), ("-1026", 249440), ("-1025", 249292)]; let sample_median = ("-1024", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1024.4978629999973), standard_deviation: NiceFloat(1.1178079811512938), skewness: NiceFloat(-0.0034862794057047334), excess_kurtosis: NiceFloat(-1.3594690811609873), }; uniform_random_integer_inclusive_range_helper( "-1026", "-1023", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "7279", "1141", "3725", "8735", "8576", "4611", "-916", "5299", "2421", "2094", "8430", "-253", "5785", "1183", "9525", "1201", "3280", "3065", "6206", "8542", ]; let common_values = &[ ("3214", 127), ("7954", 126), ("2592", 125), ("6885", 125), ("7656", 125), ("2344", 124), ("6392", 124), ("4426", 123), ("-312", 122), ("1519", 122), ]; let sample_median = ("4509", None); let sample_moment_stats = MomentStats { mean: NiceFloat(4503.707855999995), standard_deviation: NiceFloat(3172.2131846202396), skewness: NiceFloat(-0.0021819995553274013), excess_kurtosis: NiceFloat(-1.196969134950911), }; uniform_random_integer_inclusive_range_helper( "-1000", "9999", values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn uniform_random_integer_inclusive_range_fail() { uniform_random_integer_inclusive_range(EXAMPLE_SEED, Integer::from(-9), Integer::from(-10)); } ================================================ FILE: malachite-nz/tests/integer/random/uniform_random_integer_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::integer::Integer; use malachite_nz::integer::random::uniform_random_integer_range; use malachite_nz::test_util::integer::random::random_integers_helper_helper; use std::str::FromStr; fn uniform_random_integer_range_helper( a: &str, b: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_integers_helper_helper( uniform_random_integer_range( EXAMPLE_SEED, Integer::from_str(a).unwrap(), Integer::from_str(b).unwrap(), ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_uniform_random_integer_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; uniform_random_integer_range_helper( "0", "1", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-3", "3", "1", "1", "3", "-3", "-2", "-4", "-2", "-1", "0", "-1", "2", "1", "2", "2", "-1", "-3", "-1", "3", ]; let common_values = &[ ("-2", 125739), ("-1", 125293), ("2", 125220), ("3", 125016), ("-4", 124976), ("1", 124665), ("-3", 124627), ("0", 124464), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5004029999999962), standard_deviation: NiceFloat(2.291244004332587), skewness: NiceFloat(0.0011305808123400524), excess_kurtosis: NiceFloat(-1.2381429974564255), }; uniform_random_integer_range_helper( "-4", "4", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1023", "1025", "1023", "1023", "1025", "1023", "1024", "1022", "1024", "1025", "1022", "1025", "1024", "1023", "1024", "1024", "1025", "1023", "1025", "1025", ]; let common_values = &[("1024", 250959), ("1025", 250309), ("1022", 249440), ("1023", 249292)]; let sample_median = ("1024", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1023.5021369999873), standard_deviation: NiceFloat(1.1178079811513417), skewness: NiceFloat(-0.003486279405775989), excess_kurtosis: NiceFloat(-1.3594690811608392), }; uniform_random_integer_range_helper( "1022", "1026", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-1025", "-1023", "-1025", "-1025", "-1023", "-1025", "-1024", "-1026", "-1024", "-1023", "-1026", "-1023", "-1024", "-1025", "-1024", "-1024", "-1023", "-1025", "-1023", "-1023", ]; let common_values = &[("-1024", 250959), ("-1023", 250309), ("-1026", 249440), ("-1025", 249292)]; let sample_median = ("-1024", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1024.4978629999973), standard_deviation: NiceFloat(1.1178079811512938), skewness: NiceFloat(-0.0034862794057047334), excess_kurtosis: NiceFloat(-1.3594690811609873), }; uniform_random_integer_range_helper( "-1026", "-1022", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "7279", "1141", "3725", "8735", "8576", "4611", "-916", "5299", "2421", "2094", "8430", "-253", "5785", "1183", "9525", "1201", "3280", "3065", "6206", "8542", ]; let common_values = &[ ("3214", 127), ("7954", 126), ("2592", 125), ("6885", 125), ("7656", 125), ("2344", 124), ("6392", 124), ("4426", 123), ("-312", 122), ("1519", 122), ]; let sample_median = ("4509", None); let sample_moment_stats = MomentStats { mean: NiceFloat(4503.707855999995), standard_deviation: NiceFloat(3172.2131846202396), skewness: NiceFloat(-0.0021819995553274013), excess_kurtosis: NiceFloat(-1.196969134950911), }; uniform_random_integer_range_helper( "-1000", "10000", values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn uniform_random_integer_range_fail_1() { uniform_random_integer_range(EXAMPLE_SEED, Integer::from(-9), Integer::from(-10)); } #[test] #[should_panic] fn uniform_random_integer_range_fail_2() { uniform_random_integer_range(EXAMPLE_SEED, Integer::from(-10), Integer::from(-10)); } ================================================ FILE: malachite-nz/tests/lib.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::bool_assert_comparison, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::excessive_precision, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::float_cmp, clippy::type_complexity, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::option_if_let_else, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::trivially_copy_pass_by_ref )] extern crate itertools; #[macro_use] extern crate malachite_base; extern crate malachite_nz; extern crate num; extern crate rug; pub mod integer { pub mod arithmetic { pub mod abs; pub mod abs_diff; pub mod add; pub mod add_mul; pub mod binomial_coefficient; pub mod div; pub mod div_exact; pub mod div_mod; pub mod div_round; pub mod divisible_by; pub mod divisible_by_power_of_2; pub mod eq_mod; pub mod eq_mod_power_of_2; pub mod extended_gcd; pub mod kronecker_symbol; pub mod mod_op; pub mod mod_power_of_2; pub mod mul; pub mod neg; pub mod parity; pub mod pow; pub mod power_of_2; pub mod root; pub mod round_to_multiple; pub mod round_to_multiple_of_power_of_2; pub mod shl; pub mod shl_round; pub mod shr; pub mod shr_round; pub mod sign; pub mod sqrt; pub mod square; pub mod sub; pub mod sub_mul; } pub mod basic { pub mod constants; pub mod default; pub mod from_sign_and_abs; pub mod named; pub mod size; } pub mod comparison { pub mod cmp; pub mod cmp_abs; pub mod eq; pub mod eq_abs; pub mod eq_abs_natural; pub mod eq_abs_primitive_float; pub mod eq_abs_primitive_int; pub mod hash; pub mod partial_cmp_abs_natural; pub mod partial_cmp_abs_primitive_float; pub mod partial_cmp_abs_primitive_int; pub mod partial_cmp_natural; pub mod partial_cmp_primitive_float; pub mod partial_cmp_primitive_int; pub mod partial_eq_natural; pub mod partial_eq_primitive_float; pub mod partial_eq_primitive_int; } pub mod conversion { pub mod clone; pub mod from_bool; pub mod from_natural; pub mod from_primitive_float; pub mod from_primitive_int; pub mod from_twos_complement_limbs; pub mod is_integer; pub mod natural_from_integer; pub mod primitive_float_from_integer; pub mod primitive_int_from_integer; #[cfg(feature = "serde")] pub mod serde; pub mod string { pub mod from_sci_string; pub mod from_string; pub mod to_sci; pub mod to_string; } pub mod to_twos_complement_limbs; } pub mod exhaustive { pub mod exhaustive_integer_inclusive_range; pub mod exhaustive_integer_range; pub mod exhaustive_integer_range_to_infinity; pub mod exhaustive_integer_range_to_negative_infinity; pub mod exhaustive_integers; pub mod exhaustive_natural_integers; pub mod exhaustive_negative_integers; pub mod exhaustive_nonzero_integers; pub mod exhaustive_positive_integers; pub mod integer_decreasing_range_to_negative_infinity; pub mod integer_increasing_inclusive_range; pub mod integer_increasing_range; pub mod integer_increasing_range_to_infinity; } pub mod logic { pub mod and; pub mod assign_bit; pub mod assign_bits; pub mod bits; pub mod checked_count_ones; pub mod checked_count_zeros; pub mod checked_hamming_distance; pub mod clear_bit; pub mod flip_bit; pub mod from_bits; pub mod get_bit; pub mod get_bits; pub mod index_of_next_false_bit; pub mod index_of_next_true_bit; pub mod low_mask; pub mod not; pub mod or; pub mod set_bit; pub mod significant_bits; pub mod to_bits; pub mod trailing_zeros; pub mod xor; } pub mod random { pub mod get_random_integer_from_range_to_infinity; pub mod get_random_integer_from_range_to_negative_infinity; pub mod get_striped_random_integer_from_inclusive_range; pub mod get_striped_random_integer_from_range; pub mod get_striped_random_integer_from_range_to_infinity; pub mod get_striped_random_integer_from_range_to_negative_infinity; pub mod get_uniform_random_integer_from_inclusive_range; pub mod get_uniform_random_integer_from_range; pub mod random_integer_inclusive_range; pub mod random_integer_range; pub mod random_integer_range_to_infinity; pub mod random_integer_range_to_negative_infinity; pub mod random_integers; pub mod random_natural_integers; pub mod random_negative_integers; pub mod random_nonzero_integers; pub mod random_positive_integers; pub mod striped_random_integer_inclusive_range; pub mod striped_random_integer_range; pub mod striped_random_integer_range_to_infinity; pub mod striped_random_integer_range_to_negative_infinity; pub mod striped_random_integers; pub mod striped_random_natural_integers; pub mod striped_random_negative_integers; pub mod striped_random_nonzero_integers; pub mod striped_random_positive_integers; pub mod uniform_random_integer_inclusive_range; pub mod uniform_random_integer_range; } } pub mod natural { pub mod arithmetic { pub mod abs_diff; pub mod add; pub mod add_mul; pub mod binomial_coefficient; pub mod checked_sub; pub mod checked_sub_mul; pub mod coprime_with; pub mod div; pub mod div_exact; pub mod div_mod; pub mod div_round; pub mod divisible_by; pub mod divisible_by_power_of_2; pub mod eq_mod; pub mod eq_mod_power_of_2; pub mod extended_gcd; pub mod factorial; pub mod gcd; pub mod is_power_of_2; pub mod kronecker_symbol; pub mod lcm; pub mod log_base; pub mod log_base_2; pub mod log_base_power_of_2; pub mod mod_add; pub mod mod_inverse; pub mod mod_is_reduced; pub mod mod_mul; pub mod mod_neg; pub mod mod_op; pub mod mod_pow; // end pub mod mod_power_of_2; pub mod mod_power_of_2_add; pub mod mod_power_of_2_inverse; pub mod mod_power_of_2_is_reduced; pub mod mod_power_of_2_mul; pub mod mod_power_of_2_neg; pub mod mod_power_of_2_pow; pub mod mod_power_of_2_shl; pub mod mod_power_of_2_shr; pub mod mod_power_of_2_square; pub mod mod_power_of_2_sub; pub mod mod_shl; pub mod mod_shr; pub mod mod_square; pub mod mod_sub; pub mod mul; pub mod neg; pub mod next_power_of_2; pub mod parity; pub mod pow; pub mod power_of_2; pub mod primorial; pub mod root; pub mod round_to_multiple; pub mod round_to_multiple_of_power_of_2; pub mod saturating_sub; pub mod saturating_sub_mul; pub mod shl; pub mod shl_round; pub mod shr; pub mod shr_round; pub mod sign; pub mod sqrt; pub mod square; pub mod sub; pub mod sub_mul; } pub mod basic { pub mod constants; pub mod default; pub mod named; pub mod size; } pub mod comparison { pub mod cmp; pub mod eq; pub mod eq_abs_primitive_float; pub mod eq_abs_primitive_int; pub mod hash; pub mod partial_cmp_abs_primitive_float; pub mod partial_cmp_abs_primitive_int; pub mod partial_cmp_primitive_float; pub mod partial_cmp_primitive_int; pub mod partial_eq_primitive_float; pub mod partial_eq_primitive_int; } pub mod conversion { pub mod clone; pub mod digits { pub mod from_digits; pub mod from_power_of_2_digits; pub mod power_of_2_digits; pub mod to_digits; pub mod to_power_of_2_digits; } pub mod from_bool; pub mod from_limbs; pub mod from_primitive_float; pub mod from_primitive_int; pub mod is_integer; pub mod mantissa_and_exponent { pub mod integer_mantissa_and_exponent; pub mod sci_mantissa_and_exponent; } pub mod primitive_float_from_natural; pub mod primitive_int_from_natural; #[cfg(feature = "serde")] pub mod serde; pub mod string { pub mod from_sci_string; pub mod from_string; pub mod to_sci; pub mod to_string; } pub mod to_limbs; } pub mod exhaustive { pub mod exhaustive_natural_inclusive_range; pub mod exhaustive_natural_range; pub mod exhaustive_natural_range_to_infinity; pub mod exhaustive_naturals; pub mod exhaustive_positive_naturals; } pub mod factorization { pub mod is_power; pub mod is_square; pub mod primes; } pub mod logic { pub mod and; pub mod assign_bit; pub mod assign_bits; pub mod bits; pub mod clear_bit; pub mod count_ones; pub mod flip_bit; pub mod from_bits; pub mod get_bit; pub mod get_bits; pub mod hamming_distance; pub mod index_of_next_false_bit; pub mod index_of_next_true_bit; pub mod limb_count; pub mod low_mask; pub mod not; pub mod or; pub mod set_bit; pub mod significant_bits; pub mod to_bits; pub mod trailing_zeros; pub mod xor; } pub mod random { pub mod get_random_natural_less_than; pub mod get_random_natural_with_bits; pub mod get_random_natural_with_up_to_bits; pub mod get_striped_random_natural_from_inclusive_range; pub mod get_striped_random_natural_from_range; pub mod get_striped_random_natural_with_bits; pub mod get_striped_random_natural_with_up_to_bits; pub mod random_natural_inclusive_range; pub mod random_natural_range; pub mod random_natural_range_to_infinity; pub mod random_naturals; pub mod random_naturals_less_than; pub mod random_positive_naturals; pub mod striped_random_natural_inclusive_range; pub mod striped_random_natural_range; pub mod striped_random_natural_range_to_infinity; pub mod striped_random_naturals; pub mod striped_random_positive_naturals; pub mod uniform_random_natural_inclusive_range; pub mod uniform_random_natural_range; } } ================================================ FILE: malachite-nz/tests/natural/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsDiff, AbsDiffAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use std::str::FromStr; #[test] fn test_abs_diff_natural() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.abs_diff_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.abs_diff_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("456", "123", "333"); test("1000000000000", "123", "999999999877"); test("123", "1000000000000", "999999999877"); test("12345678987654321", "314159265358979", "12031519722295342"); test("4294967296", "1", "4294967295"); test("4294967295", "4294967295", "0"); test("4294967296", "4294967295", "1"); test("4294967296", "4294967296", "0"); test("4294967295", "4294967296", "1"); test("18446744073709551616", "1", "18446744073709551615"); test("18446744073709551615", "18446744073709551615", "0"); test("18446744073709551616", "18446744073709551615", "1"); test("18446744073709551615", "18446744073709551616", "1"); test("70734740290631708", "282942734368", "70734457347897340"); test("282942734368", "70734740290631708", "70734457347897340"); } #[test] fn abs_diff_properties() { natural_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.abs_diff_assign(&y); assert!(mut_x.is_valid()); let diff = mut_x; let mut mut_x = x.clone(); mut_x.abs_diff_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let diff_alt = x.clone().abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = x.clone().abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); assert_eq!((Integer::from(&x) - Integer::from(&y)).abs(), diff); assert_eq!((&y).abs_diff(&x), diff); assert_eq!(diff == 0, x == y); }); natural_gen().test_properties(|x| { assert_eq!((&x).abs_diff(Natural::ZERO), x); assert_eq!((&x).abs_diff(&x), 0); assert_eq!(Natural::ZERO.abs_diff(&x), x); }); natural_triple_gen().test_properties(|(x, y, z)| { assert!((&x).abs_diff(&z) <= x.abs_diff(&y) + y.abs_diff(z)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(x.abs_diff(y), Natural::from(x).abs_diff(Natural::from(y))); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ large_type_gen_var_9, unsigned_pair_gen_var_27, unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_triple_gen_var_40, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_bool_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11, }; use malachite_base::vecs::vec_from_str; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::add::{ limbs_add, limbs_add_greater, limbs_add_greater_to_out, limbs_add_limb, limbs_add_limb_to_out, limbs_add_same_length_to_out, limbs_add_same_length_with_carry_in_in_place_left, limbs_add_same_length_with_carry_in_to_out, limbs_add_to_out, limbs_add_to_out_aliased, limbs_slice_add_greater_in_place_left, limbs_slice_add_in_place_either, limbs_slice_add_limb_in_place, limbs_slice_add_same_length_in_place_left, limbs_vec_add_in_place_either, limbs_vec_add_in_place_left, limbs_vec_add_limb_in_place, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ natural_gen, natural_pair_gen, natural_triple_gen, natural_vec_gen, }; use malachite_nz::test_util::natural::arithmetic::add::natural_sum_alt; use num::BigUint; use rug; use std::cmp::max; use std::iter::{Sum, once}; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_limb() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_add_limb(xs, y), out); }; test(&[], 0, &[]); test(&[], 5, &[5]); test(&[6, 7], 2, &[8, 7]); test(&[100, 101, 102], 10, &[110, 101, 102]); test(&[123, 456], 789, &[912, 456]); test(&[u32::MAX, 5], 2, &[1, 6]); test(&[u32::MAX], 2, &[1, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry: bool, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_add_limb_to_out(&mut out, xs, y), carry); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[], 0, false, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[], 5, true, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, false, &[8, 7, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, false, &[110, 101, 102, 10], ); test( &[10, 10, 10, 10], &[123, 456], 789, false, &[912, 456, 10, 10], ); test(&[10, 10, 10, 10], &[u32::MAX, 5], 2, false, &[1, 6, 10, 10]); test(&[10, 10, 10, 10], &[u32::MAX], 2, true, &[1, 10, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_limb_to_out_fail() { limbs_add_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_limb_in_place() { let test = |xs: &[Limb], y: Limb, carry: bool, out: &[Limb]| { let mut xs = xs.to_vec(); assert_eq!(limbs_slice_add_limb_in_place(&mut xs, y), carry); assert_eq!(xs, out); }; test(&[], 0, false, &[]); test(&[], 5, true, &[]); test(&[6, 7], 2, false, &[8, 7]); test(&[100, 101, 102], 10, false, &[110, 101, 102]); test(&[123, 456], 789, false, &[912, 456]); test(&[u32::MAX, 5], 2, false, &[1, 6]); test(&[u32::MAX], 2, true, &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_add_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { let mut xs = xs.to_vec(); limbs_vec_add_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 2, &[8, 7]); test(&[100, 101, 102], 10, &[110, 101, 102]); test(&[123, 456], 789, &[912, 456]); test(&[u32::MAX, 5], 2, &[1, 6]); test(&[u32::MAX], 2, &[1, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_add_limb_in_place_fail() { limbs_vec_add_limb_in_place(&mut vec![], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_greater() { let test = |xs, ys, out| { assert_eq!(limbs_add_greater(xs, ys), out); }; test(&[], &[], vec![]); test(&[2], &[], vec![2]); test(&[2], &[3], vec![5]); test(&[1, 1, 1], &[1, 2, 3], vec![2, 3, 4]); test(&[1, 2, 3], &[6, 7], vec![7, 9, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![202, 202, 202]); test(&[u32::MAX, 3], &[1], vec![0, 4]); test(&[u32::MAX], &[1], vec![0, 1]); test(&[1], &[u32::MAX], vec![0, 1]); test(&[u32::MAX], &[u32::MAX], vec![u32::MAX - 1, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn test_limbs_add_greater_fail() { limbs_add_greater(&[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_and_limbs_vec_add_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_add(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_vec_add_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[], &[], vec![]); test(&[2], &[], vec![2]); test(&[], &[2], vec![2]); test(&[2], &[3], vec![5]); test(&[1, 1, 1], &[1, 2, 3], vec![2, 3, 4]); test(&[6, 7], &[1, 2, 3], vec![7, 9, 3]); test(&[1, 2, 3], &[6, 7], vec![7, 9, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![202, 202, 202]); test(&[u32::MAX, 3], &[1], vec![0, 4]); test(&[1], &[u32::MAX, 3], vec![0, 4]); test(&[u32::MAX], &[1], vec![0, 1]); test(&[1], &[u32::MAX], vec![0, 1]); test(&[u32::MAX], &[u32::MAX], vec![u32::MAX - 1, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_greater_to_out() { let test = |xs, ys, out_before: &[Limb], carry, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_add_greater_to_out(&mut out, xs, ys), carry); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], false, vec![0, 0]); test(&[2], &[], &[0, 0], false, vec![2, 0]); test(&[2], &[3], &[0, 0], false, vec![5, 0]); test( &[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], false, vec![2, 3, 4, 5], ); test(&[1, 2, 3], &[6, 7], &[0, 0, 0], false, vec![7, 9, 3]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], false, vec![202, 202, 202, 10], ); test( &[u32::MAX, 3], &[1], &[10, 10, 10, 10], false, vec![0, 4, 10, 10], ); test( &[u32::MAX], &[1], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[1], &[u32::MAX], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[u32::MAX], &[u32::MAX], &[10, 10, 10, 10], true, vec![u32::MAX - 1, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_greater_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_add_greater_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_greater_to_out_fail_2() { let mut out = vec![10]; limbs_add_greater_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_same_length_to_out() { let test = |xs, ys, out_before: &[Limb], carry, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_add_same_length_to_out(&mut out, xs, ys), carry); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], false, vec![0, 0]); test(&[2], &[3], &[0, 0], false, vec![5, 0]); test( &[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], false, vec![2, 3, 4, 5], ); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], false, vec![202, 202, 202, 10], ); test( &[u32::MAX], &[1], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[1], &[u32::MAX], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[u32::MAX], &[u32::MAX], &[10, 10, 10, 10], true, vec![u32::MAX - 1, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_same_length_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_add_same_length_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_same_length_to_out_fail_2() { let mut out = vec![10]; limbs_add_same_length_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_to_out() { let test = |xs, ys, out_before: &[Limb], carry, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_add_to_out(&mut out, xs, ys), carry); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], false, vec![0, 0]); test(&[2], &[], &[0, 0], false, vec![2, 0]); test(&[], &[2], &[0, 0], false, vec![2, 0]); test(&[2], &[3], &[0, 0], false, vec![5, 0]); test( &[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], false, vec![2, 3, 4, 5], ); test(&[6, 7], &[1, 2, 3], &[0, 0, 0], false, vec![7, 9, 3]); test(&[1, 2, 3], &[6, 7], &[0, 0, 0], false, vec![7, 9, 3]); test( &[6, 7], &[1, 2, 3], &[10, 10, 10, 10], false, vec![7, 9, 3, 10], ); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], false, vec![202, 202, 202, 10], ); test( &[u32::MAX, 3], &[1], &[10, 10, 10, 10], false, vec![0, 4, 10, 10], ); test( &[1], &[u32::MAX, 3], &[10, 10, 10, 10], false, vec![0, 4, 10, 10], ); test( &[u32::MAX], &[1], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[1], &[u32::MAX], &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[u32::MAX], &[u32::MAX], &[10, 10, 10, 10], true, vec![u32::MAX - 1, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_to_out_fail() { let mut out = vec![10, 10]; limbs_add_to_out(&mut out, &[6, 7, 8], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_to_out_aliased() { let test = |xs_before: &[Limb], in_size, ys: &[Limb], carry, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_add_to_out_aliased(&mut xs, in_size, ys), carry); assert_eq!(xs, xs_after); }; test(&[], 0, &[], false, vec![]); test(&[1, 2, 3], 0, &[4, 5], false, vec![4, 5, 3]); test(&[1, 2, 3], 1, &[4, 5], false, vec![5, 5, 3]); test(&[1, 2, 3], 2, &[4, 5], false, vec![5, 7, 3]); test(&[1, 1, 3], 1, &[u32::MAX, 5], false, vec![0, 6, 3]); test(&[1, 1, 3], 1, &[u32::MAX], true, vec![0, 1, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_to_out_aliased_fail_1() { let mut out = vec![6, 7]; limbs_add_to_out_aliased(&mut out, 1, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_to_out_aliased_fail_2() { let mut out = vec![6, 7, 8, 9]; limbs_add_to_out_aliased(&mut out, 4, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_same_length_in_place_left() { let test = |xs_before: &[Limb], ys, carry, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_slice_add_same_length_in_place_left(&mut xs, ys), carry ); assert_eq!(xs, xs_after); }; test(&[], &[], false, vec![]); test(&[2], &[3], false, vec![5]); test(&[1, 1, 1], &[1, 2, 3], false, vec![2, 3, 4]); test( &[100, 101, 102], &[102, 101, 100], false, vec![202, 202, 202], ); test(&[u32::MAX], &[1], true, vec![0]); test(&[1], &[u32::MAX], true, vec![0]); test(&[u32::MAX], &[u32::MAX], true, vec![u32::MAX - 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_add_same_length_in_place_left_fail() { let mut out = vec![6, 7]; limbs_slice_add_same_length_in_place_left::(&mut out, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_greater_in_place_left() { let test = |xs_before: &[Limb], ys, carry, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_slice_add_greater_in_place_left(&mut xs, ys), carry); assert_eq!(xs, xs_after); }; test(&[], &[], false, vec![]); test(&[2], &[], false, vec![2]); test(&[2], &[3], false, vec![5]); test(&[1, 1, 1], &[1, 2, 3], false, vec![2, 3, 4]); test(&[1, 2, 3], &[6, 7], false, vec![7, 9, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![202, 202, 202], ); test(&[u32::MAX, 3], &[1], false, vec![0, 4]); test(&[u32::MAX], &[1], true, vec![0]); test(&[1], &[u32::MAX], true, vec![0]); test(&[u32::MAX], &[u32::MAX], true, vec![u32::MAX - 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_add_greater_in_place_left_fail() { let mut out = vec![6, 7]; limbs_slice_add_greater_in_place_left(&mut out, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], right, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_slice_add_in_place_either(&mut xs, &mut ys), right); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], (false, false), vec![], vec![]); test(&[2], &[], (false, false), vec![2], vec![]); test(&[], &[2], (true, false), vec![], vec![2]); test(&[2], &[3], (false, false), vec![5], vec![3]); test(&[6, 7], &[1, 2], (false, false), vec![7, 9], vec![1, 2]); test( &[6, 7], &[1, 2, 3], (true, false), vec![6, 7], vec![7, 9, 3], ); test( &[1, 2, 3], &[6, 7], (false, false), vec![7, 9, 3], vec![6, 7], ); test(&[], &[1, 2, 3], (true, false), vec![], vec![1, 2, 3]); test(&[1, 2, 3], &[], (false, false), vec![1, 2, 3], vec![]); test( &[1, 1, 1], &[1, 2, 3], (false, false), vec![2, 3, 4], vec![1, 2, 3], ); test( &[100, 101, 102], &[102, 101, 100], (false, false), vec![202, 202, 202], vec![102, 101, 100], ); test(&[u32::MAX, 3], &[1], (false, false), vec![0, 4], vec![1]); test(&[1], &[u32::MAX, 3], (true, false), vec![1], vec![0, 4]); test(&[u32::MAX], &[1], (false, true), vec![0], vec![1]); test(&[1], &[u32::MAX], (false, true), vec![0], vec![u32::MAX]); test( &[u32::MAX], &[u32::MAX], (false, true), vec![u32::MAX - 1], vec![u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_add_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], right, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_vec_add_in_place_either(&mut xs, &mut ys), right); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![], vec![]); test(&[2], &[], false, vec![2], vec![]); test(&[], &[2], true, vec![], vec![2]); test(&[2], &[3], false, vec![5], vec![3]); test(&[6, 7], &[1, 2], false, vec![7, 9], vec![1, 2]); test(&[6, 7], &[1, 2, 3], true, vec![6, 7], vec![7, 9, 3]); test(&[1, 2, 3], &[6, 7], false, vec![7, 9, 3], vec![6, 7]); test(&[], &[1, 2, 3], true, vec![], vec![1, 2, 3]); test(&[1, 2, 3], &[], false, vec![1, 2, 3], vec![]); test(&[1, 1, 1], &[1, 2, 3], false, vec![2, 3, 4], vec![1, 2, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![202, 202, 202], vec![102, 101, 100], ); test(&[u32::MAX, 3], &[1], false, vec![0, 4], vec![1]); test(&[1], &[u32::MAX, 3], true, vec![1], vec![0, 4]); test(&[u32::MAX], &[1], false, vec![0, 1], vec![1]); test(&[1], &[u32::MAX], false, vec![0, 1], vec![u32::MAX]); test( &[u32::MAX], &[u32::MAX], false, vec![u32::MAX - 1, 1], vec![u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_same_length_with_carry_in_to_out() { let test = |xs, ys, carry_in, out_before: &[Limb], carry, out_after| { let mut out = out_before.to_vec(); assert_eq!( limbs_add_same_length_with_carry_in_to_out(&mut out, xs, ys, carry_in), carry ); assert_eq!(out, out_after); }; test(&[], &[], false, &[0, 0], false, vec![0, 0]); test(&[], &[], true, &[0, 0], true, vec![0, 0]); test(&[2], &[3], false, &[0, 0], false, vec![5, 0]); test(&[2], &[3], true, &[0, 0], false, vec![6, 0]); test( &[1, 1, 1], &[1, 2, 3], false, &[5, 5, 5, 5], false, vec![2, 3, 4, 5], ); test( &[1, 1, 1], &[1, 2, 3], true, &[5, 5, 5, 5], false, vec![3, 3, 4, 5], ); test( &[100, 101, 102], &[102, 101, 100], false, &[10, 10, 10, 10], false, vec![202, 202, 202, 10], ); test( &[u32::MAX], &[1], false, &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[u32::MAX], &[1], true, &[10, 10, 10, 10], true, vec![1, 10, 10, 10], ); test( &[u32::MAX - 1], &[1], true, &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[1], &[u32::MAX], false, &[10, 10, 10, 10], true, vec![0, 10, 10, 10], ); test( &[u32::MAX], &[u32::MAX], false, &[10, 10, 10, 10], true, vec![u32::MAX - 1, 10, 10, 10], ); test( &[u32::MAX], &[u32::MAX], true, &[10, 10, 10, 10], true, vec![u32::MAX, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_same_length_with_carry_in_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_add_same_length_with_carry_in_to_out(&mut out, &[6, 7], &[1, 2, 3], false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_same_length_with_carry_in_to_out_fail_2() { let mut out = vec![10]; limbs_add_same_length_with_carry_in_to_out(&mut out, &[6, 7], &[1, 2], false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_same_length_with_carry_in_in_place_left() { let test = |xs_before: &[Limb], ys, carry_in, carry, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_add_same_length_with_carry_in_in_place_left(&mut xs, ys, carry_in), carry ); assert_eq!(xs, xs_after); }; test(&[], &[], false, false, vec![]); test(&[], &[], true, true, vec![]); test(&[2], &[3], false, false, vec![5]); test(&[2], &[3], true, false, vec![6]); test(&[1, 1, 1], &[1, 2, 3], false, false, vec![2, 3, 4]); test( &[100, 101, 102], &[102, 101, 100], false, false, vec![202, 202, 202], ); test(&[u32::MAX], &[1], false, true, vec![0]); test(&[u32::MAX], &[1], true, true, vec![1]); test(&[u32::MAX - 1], &[1], true, true, vec![0]); test(&[1], &[u32::MAX], false, true, vec![0]); test(&[u32::MAX], &[u32::MAX], false, true, vec![u32::MAX - 1]); test(&[u32::MAX], &[u32::MAX], true, true, vec![u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_same_length_with_carry_in_in_place_left_fail() { let mut out = vec![6, 7]; limbs_add_same_length_with_carry_in_in_place_left(&mut out, &[1, 2, 3], false); } #[test] fn test_add() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n += v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n += &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigUint::from_str(s).unwrap() + BigUint::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() + rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "579"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("12345678987654321", "314159265358979", "12659838253013300"); test( "1000000000000", "1000000000000000000000000", "1000000000001000000000000", ); test( "157489031134308824401228232926", "2350262829889206551114184866", "159839293964198030952342417792", ); } #[test] fn test_sum() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let sum = Natural::sum(xs.iter().cloned()); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); let sum_alt = Natural::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = natural_sum_alt(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }; test("[]", "0"); test("[10]", "10"); test("[6, 2]", "8"); test("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "55"); test("[123456, 789012, 345678, 9012345]", "10270491"); } #[test] fn limbs_add_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(xs, y)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_add_limb(&xs, y)), Natural::from_owned_limbs_asc(xs) + Natural::from(y) ); }); } #[test] fn limbs_add_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let carry = limbs_add_limb_to_out(&mut out, &xs, y); let len = xs.len(); let n = Natural::from_owned_limbs_asc(xs) + Natural::from(y); let mut xs = n.into_limbs_asc(); assert_eq!(carry, xs.len() == len + 1); xs.resize(len, 0); assert_eq!(xs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_slice_add_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(mut xs, y)| { let n = Natural::from_limbs_asc(&xs) + Natural::from(y); let carry = limbs_slice_add_limb_in_place(&mut xs, y); let mut expected_xs = n.into_limbs_asc(); assert_eq!(carry, expected_xs.len() == xs.len() + 1); expected_xs.resize(xs.len(), 0); assert_eq!(xs, expected_xs); }); } #[test] fn limbs_vec_add_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let n = Natural::from_limbs_asc(&xs) + Natural::from(y); limbs_vec_add_limb_in_place(&mut xs, y); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }); } fn limbs_add_helper(f: &dyn Fn(&[Limb], &[Limb]) -> Vec, xs: Vec, ys: Vec) { assert_eq!( Natural::from_owned_limbs_asc(f(&xs, &ys)), Natural::from_owned_limbs_asc(xs) + Natural::from_owned_limbs_asc(ys) ); } #[test] fn limbs_add_greater_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_1().test_properties_with_config(&config, |(xs, ys)| { limbs_add_helper(&limbs_add_greater, xs, ys); }); } #[test] fn limbs_add_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(xs, ys)| { limbs_add_helper(&limbs_add, xs, ys); }); } fn limbs_add_to_out_helper( f: &mut dyn FnMut(&mut [Limb], &[Limb], &[Limb]) -> bool, out_len: &dyn Fn(usize, usize) -> usize, mut out: Vec, xs: Vec, ys: Vec, ) { let old_out = out.clone(); let carry = f(&mut out, &xs, &ys); let len = out_len(xs.len(), ys.len()); let n = Natural::from_owned_limbs_asc(xs) + Natural::from_owned_limbs_asc(ys); let mut xs = n.into_limbs_asc(); assert_eq!(carry, xs.len() == len + 1); xs.resize(len, 0); assert_eq!(xs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); } #[test] fn limbs_add_greater_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_40().test_properties_with_config(&config, |(out, xs, ys)| { limbs_add_to_out_helper( &mut limbs_add_greater_to_out, &|xs_len, _| xs_len, out, xs, ys, ); }); } #[test] fn limbs_add_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_31().test_properties_with_config(&config, |(out, xs, ys)| { limbs_add_to_out_helper( &mut limbs_add_same_length_to_out, &|xs_len, _| xs_len, out, xs, ys, ); }); } #[test] fn limbs_add_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_32().test_properties_with_config(&config, |(out, xs, ys)| { limbs_add_to_out_helper(&mut limbs_add_to_out, &max, out, xs, ys); }); } #[test] fn limbs_add_to_out_aliased_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_11().test_properties_with_config( &config, |(mut xs, ys, xs_len)| { let xs_old = xs.clone(); let carry = limbs_add_to_out_aliased(&mut xs, xs_len, &ys); let ys_len = ys.len(); let n = Natural::from_limbs_asc(&xs_old[..xs_len]) + Natural::from_owned_limbs_asc(ys); let mut ns = n.into_limbs_asc(); if ns.len() < ys_len { ns.resize(ys_len, 0); } assert_eq!( Natural::from_limbs_asc(&xs[..ys_len]), Natural::from_limbs_asc(&ns[..ys_len]), ); if carry { assert_eq!(ns.len(), ys_len + 1); assert_eq!(*ns.last().unwrap(), 1); } else { assert_eq!(ns.len(), ys_len); } assert_eq!(&xs[ys_len..], &xs_old[ys_len..]); }, ); } fn limbs_slice_add_in_place_left_helper( f: &mut dyn FnMut(&mut [Limb], &[Limb]) -> bool, xs: &mut [Limb], ys: &[Limb], ) { let n = Natural::from_limbs_asc(xs) + Natural::from_limbs_asc(ys); let carry = f(xs, ys); let len = xs.len(); let mut ns = n.into_limbs_asc(); assert_eq!(carry, ns.len() == len + 1); ns.resize(len, 0); assert_eq!(ns, xs); } #[test] fn limbs_slice_add_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(mut xs, ys)| { limbs_slice_add_in_place_left_helper( &mut limbs_slice_add_same_length_in_place_left, &mut xs, &ys, ); }); } #[test] fn limbs_slice_add_greater_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_1().test_properties_with_config(&config, |(mut xs, ys)| { limbs_slice_add_in_place_left_helper( &mut limbs_slice_add_greater_in_place_left, &mut xs, &ys, ); }); } #[test] fn limbs_vec_add_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_vec_add_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) + Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_slice_add_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let (right, b) = limbs_slice_add_in_place_either(&mut xs, &mut ys); let len = max(xs_old.len(), ys_old.len()); let result = Natural::from_limbs_asc(&xs_old) + Natural::from_limbs_asc(&ys_old); let mut expected_out = result.to_limbs_asc(); expected_out.resize(len, 0); assert_eq!(!b, Natural::from_limbs_asc(&expected_out) == result); if right { assert_eq!(ys, expected_out.as_slice()); assert_eq!(xs, xs_old); } else { assert_eq!(xs, expected_out.as_slice()); assert_eq!(ys, ys_old); } }); } #[test] fn limbs_vec_add_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_vec_add_in_place_either(&mut xs, &mut ys); let n = Natural::from_limbs_asc(&xs_old) + Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }); } #[test] fn limbs_add_same_length_with_carry_in_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_9().test_properties_with_config(&config, |(out, xs, ys, carry_in)| { let mut out = out.to_vec(); let old_out = out.clone(); let carry = limbs_add_same_length_with_carry_in_to_out(&mut out, &xs, &ys, carry_in); let len = xs.len(); let mut n = Natural::from_owned_limbs_asc(xs) + Natural::from_owned_limbs_asc(ys); if carry_in { n += Natural::ONE; } let mut ns = n.into_limbs_asc(); assert_eq!(carry, ns.len() == len + 1); ns.resize(len, 0); assert_eq!(ns, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }); } #[test] fn limbs_add_same_length_with_carry_in_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_bool_triple_gen_var_1().test_properties_with_config( &config, |(mut xs, ys, carry_in)| { let xs_old = xs.clone(); let carry = limbs_add_same_length_with_carry_in_in_place_left(&mut xs, &ys, carry_in); let mut n = Natural::from_owned_limbs_asc(xs_old) + Natural::from_owned_limbs_asc(ys); if carry_in { n += Natural::ONE; } let len = xs.len(); let mut ns = n.into_limbs_asc(); assert_eq!(carry, ns.len() == len + 1); ns.resize(len, 0); assert_eq!(ns, xs); }, ); } #[test] fn add_properties() { natural_pair_gen().test_properties(|(x, y)| { let sum_val_val = x.clone() + y.clone(); let sum_val_ref = x.clone() + &y; let sum_ref_val = &x + y.clone(); let sum = &x + &y; assert!(sum_val_val.is_valid()); assert!(sum_val_ref.is_valid()); assert!(sum_ref_val.is_valid()); assert!(sum.is_valid()); assert_eq!(sum_val_val, sum); assert_eq!(sum_val_ref, sum); assert_eq!(sum_ref_val, sum); let mut mut_x = x.clone(); mut_x += y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x += &y; assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x += rug::Integer::from(&y); assert_eq!(Natural::exact_from(&mut_x), sum); assert_eq!(Natural::from(&(BigUint::from(&x) + BigUint::from(&y))), sum); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) + rug::Integer::from(&y))), sum ); assert_eq!(&y + &x, sum); assert_eq!(&sum - &x, y); assert_eq!(&sum - &y, x); assert!(sum >= x); assert!(sum >= y); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x + &y) + &z, x + (y + z)); }); natural_gen().test_properties(|x| { assert_eq!(&x + Natural::ZERO, x); assert_eq!(Natural::ZERO + &x, x); assert_eq!(&x + &x, x << 1); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( DoubleLimb::from(x) + DoubleLimb::from(y), Natural::from(x) + Natural::from(y) ); }); } #[test] fn sum_properties() { natural_vec_gen().test_properties(|xs| { let sum = Natural::sum(xs.iter().cloned()); assert!(sum.is_valid()); let sum_alt = Natural::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = natural_sum_alt(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }); natural_gen().test_properties(|x| { assert_eq!(Natural::sum(once(&x)), x); assert_eq!(Natural::sum(once(x.clone())), x); }); natural_pair_gen().test_properties(|(x, y)| { let sum = &x + &y; assert_eq!(Natural::sum([&x, &y].into_iter()), sum); assert_eq!(Natural::sum([x, y].into_iter()), sum); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/add_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AddMul, AddMulAssign, CheckedAddMul}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_1, unsigned_triple_gen_var_19, unsigned_vec_triple_gen_var_41, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::add_mul::{ limbs_add_mul, limbs_add_mul_in_place_left, limbs_add_mul_limb, limbs_slice_add_mul_limb_same_length_in_place_left, limbs_slice_add_mul_limb_same_length_in_place_right, limbs_vec_add_mul_limb_in_place_either, limbs_vec_add_mul_limb_in_place_left, limbs_vec_add_mul_limb_in_place_right, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_pair_gen, natural_triple_gen}; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_mul_limb() { let test = |xs_before: &[Limb], ys_before: &[Limb], z: Limb, result: &[Limb]| { assert_eq!(limbs_add_mul_limb(xs_before, ys_before, z), result); let mut xs = xs_before.to_vec(); limbs_vec_add_mul_limb_in_place_left(&mut xs, ys_before, z); assert_eq!(xs, result); let mut ys = ys_before.to_vec(); limbs_vec_add_mul_limb_in_place_right(xs_before, &mut ys, z); assert_eq!(ys, result); }; test(&[123, 456], &[123], 4, &[615, 456]); test(&[123, 456], &[123], u32::MAX, &[0, 579]); test(&[123], &[0, 123], 4, &[123, 492]); test(&[123, 456], &[0, 123], u32::MAX, &[123, 333, 123]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_mul_limb_same_length_in_place_left() { let test = |xs_before: &[Limb], ys: &[Limb], z: Limb, xs_after: &[Limb], carry: Limb| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_slice_add_mul_limb_same_length_in_place_left(&mut xs, ys, z), carry ); assert_eq!(xs, xs_after); }; test(&[123], &[123], 4, &[615], 0); test(&[123], &[123], u32::MAX, &[0], 123); test(&[123, 0], &[0, 123], 4, &[123, 492], 0); test(&[123, 456], &[0, 123], u32::MAX, &[123, 333], 123); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_add_mul_limb_same_length_in_place_left_fail() { limbs_slice_add_mul_limb_same_length_in_place_left(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_add_mul_limb_same_length_in_place_right() { let test = |xs: &[Limb], ys_before: &[Limb], z: Limb, ys_after: &[Limb], carry: Limb| { let mut ys = ys_before.to_vec(); assert_eq!( limbs_slice_add_mul_limb_same_length_in_place_right(xs, &mut ys, z), carry ); assert_eq!(ys, ys_after); }; test(&[123, 456], &[123, 0], 4, &[615, 456], 0); test(&[123, 456], &[123, 0], u32::MAX, &[0, 579], 0); test(&[123, 0], &[0, 123], 4, &[123, 492], 0); test(&[123, 456], &[0, 123], u32::MAX, &[123, 333], 123); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_add_mul_limb_same_length_in_place_right_fail() { limbs_slice_add_mul_limb_same_length_in_place_right(&[10, 10], &mut [10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_add_mul_limb_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], z: Limb, right: bool, xs_after: &[Limb], ys_after: &[Limb]| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!( limbs_vec_add_mul_limb_in_place_either(&mut xs, &mut ys, z), right ); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[123, 456], &[123], 4, false, &[615, 456], &[123]); test( &[123, 456], &[123, 0], u32::MAX, false, &[0, 579], &[123, 0], ); test(&[123], &[0, 123], 4, true, &[123], &[123, 492]); test( &[123, 456], &[0, 123], u32::MAX, false, &[123, 333, 123], &[0, 123], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_add_mul_and_limbs_add_mul_in_place_left() { let test = |xs_before: &[Limb], ys: &[Limb], zs: &[Limb], result: &[Limb]| { assert_eq!(limbs_add_mul(xs_before, ys, zs), result); let mut xs = xs_before.to_vec(); limbs_add_mul_in_place_left(&mut xs, ys, zs); assert_eq!(xs, result); }; test( &[123, 456], &[123, 789], &[321, 654], &[39606, 334167, 516006], ); test( &[123, 456, 789, 987, 654], &[123, 789], &[321, 654], &[39606, 334167, 516795, 987, 654], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_mul_fail_1() { limbs_add_mul(&[10, 10], &[], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_mul_fail_2() { limbs_add_mul(&[10, 10], &[10, 10], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_mul_in_place_left_fail_1() { let mut xs = vec![10, 10]; limbs_add_mul_in_place_left(&mut xs, &[], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_add_mul_in_place_left_fail_2() { let mut xs = vec![10, 10]; limbs_add_mul_in_place_left(&mut xs, &[10, 10], &[]); } #[test] fn test_add_mul() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let w = Natural::from_str(t).unwrap(); let mut a = u.clone(); a.add_mul_assign(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let mut a = u.clone(); a.add_mul_assign(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(v.clone(), w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(v.clone(), &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(&v, w.clone()); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = u.clone().add_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); let a = (&u).add_mul(&v, &w); assert_eq!(a.to_string(), out); assert!(a.is_valid()); }; test("0", "0", "0", "0"); test("0", "0", "123", "0"); test("123", "0", "5", "123"); test("123", "5", "1", "128"); test("123", "5", "100", "623"); test("10", "3", "4", "22"); test("1000000000000", "0", "123", "1000000000000"); test("1000000000000", "1", "123", "1000000000123"); test("1000000000000", "123", "1", "1000000000123"); test("1000000000000", "123", "100", "1000000012300"); test("1000000000000", "100", "123", "1000000012300"); test("1000000000000", "65536", "65536", "1004294967296"); test("1000000000000", "1000000000000", "0", "1000000000000"); test("1000000000000", "1000000000000", "1", "2000000000000"); test("1000000000000", "1000000000000", "100", "101000000000000"); test("0", "1000000000000", "100", "100000000000000"); test( "1000000000000", "65536", "1000000000000", "65537000000000000", ); test( "1000000000000", "1000000000000", "1000000000000", "1000000000001000000000000", ); test( "0", "1000000000000", "1000000000000", "1000000000000000000000000", ); test( "18446744073583722494", "2", "4033876984", "18446744081651476462", ); } #[test] fn limbs_add_mul_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties_with_config( &config, |(a, b, c)| { assert_eq!( limbs_add_mul_limb(&a, &b, c), Natural::from_owned_limbs_asc(a) .add_mul(Natural::from_owned_limbs_asc(b), Natural::from(c)) .into_limbs_asc() ); }, ); } #[test] fn limbs_slice_add_mul_limb_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(a, b, c)| { let a_old = a; let mut a = a_old.to_vec(); let carry = limbs_slice_add_mul_limb_same_length_in_place_left(&mut a, &b, c); let len = b.len(); let mut result = a[..len].to_vec(); result.push(carry); assert_eq!( Natural::from_owned_limbs_asc(result), Natural::from_limbs_asc(&a_old[..len]) .add_mul(Natural::from_owned_limbs_asc(b), Natural::from(c)) ); assert_eq!(&a[len..], &a_old[len..]); }, ); } #[test] fn limbs_slice_add_mul_limb_same_length_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(a, mut b, c)| { let b_old = b.clone(); let carry = limbs_slice_add_mul_limb_same_length_in_place_right(&a, &mut b, c); b.push(carry); assert_eq!( Natural::from_owned_limbs_asc(b), Natural::from_owned_limbs_asc(a) .add_mul(Natural::from_owned_limbs_asc(b_old), Natural::from(c)) ); }, ); } #[test] fn limbs_vec_add_mul_limb_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties_with_config( &config, |(mut a, b, c)| { let a_old = a.clone(); limbs_vec_add_mul_limb_in_place_left(&mut a, &b, c); assert_eq!( a, Natural::from_owned_limbs_asc(a_old) .add_mul(Natural::from_owned_limbs_asc(b), Natural::from(c)) .into_limbs_asc() ); }, ); } #[test] fn limbs_vec_add_mul_limb_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties_with_config( &config, |(a, mut b, c)| { let b_old = b.clone(); limbs_vec_add_mul_limb_in_place_right(&a, &mut b, c); assert_eq!( b, Natural::from_owned_limbs_asc(a) .add_mul(Natural::from_owned_limbs_asc(b_old), Natural::from(c)) .into_limbs_asc() ); }, ); } #[test] fn limbs_vec_add_mul_limb_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_10().test_properties_with_config( &config, |(mut a, mut b, c)| { let a_old = a.clone(); let b_old = b.clone(); let result = if limbs_vec_add_mul_limb_in_place_either(&mut a, &mut b, c) { assert_eq!(a_old, a); b } else { assert_eq!(b_old, b); a }; assert_eq!( result, Natural::from_owned_limbs_asc(a_old) .add_mul(Natural::from_owned_limbs_asc(b_old), Natural::from(c)) .into_limbs_asc() ); }, ); } #[test] fn limbs_add_mul_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_41().test_properties_with_config(&config, |(a, b, c)| { assert_eq!( limbs_add_mul(&a, &b, &c), Natural::from_owned_limbs_asc(a) .add_mul( Natural::from_owned_limbs_asc(b), Natural::from_owned_limbs_asc(c) ) .into_limbs_asc() ); }); } #[test] fn limbs_add_mul_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_41().test_properties_with_config(&config, |(mut a, b, c)| { let a_old = a.clone(); limbs_add_mul_in_place_left(&mut a, &b, &c); assert_eq!( a, Natural::from_owned_limbs_asc(a_old) .add_mul( Natural::from_owned_limbs_asc(b), Natural::from_owned_limbs_asc(c) ) .into_limbs_asc() ); }); } #[test] fn add_mul_properties() { natural_triple_gen().test_properties(|(a, b, c)| { let mut mut_a = a.clone(); mut_a.add_mul_assign(b.clone(), c.clone()); assert!(mut_a.is_valid()); let result = mut_a; let mut mut_a = a.clone(); mut_a.add_mul_assign(b.clone(), &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.add_mul_assign(&b, c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.add_mul_assign(&b, &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let result_alt = a.clone().add_mul(b.clone(), c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(b.clone(), &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(&b, c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().add_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = (&a).add_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!(&a + &b * &c, result); assert_eq!(a.add_mul(c, b), result); }); natural_pair_gen().test_properties(|(a, b)| { let a = &a; let b = &b; assert_eq!(a.add_mul(&Natural::ZERO, b), *a); assert_eq!(a.add_mul(&Natural::ONE, b), a + b); assert_eq!(Natural::ZERO.add_mul(a, b), a * b); assert_eq!(a.add_mul(b, &Natural::ZERO), *a); assert_eq!(a.add_mul(b, &Natural::ONE), a + b); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { let result = Natural::from(x).add_mul(Natural::from(y), Natural::from(z)); assert_eq!( x.checked_add_mul(y, z).is_some(), Limb::convertible_from(&result) ); }); unsigned_triple_gen_var_1::().test_properties(|(x, y, z)| { assert_eq!( x.add_mul(y, z), Natural::from(x).add_mul(Natural::from(y), Natural::from(z)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/binomial_coefficient.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{BinomialCoefficient, DivExact, Gcd}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_pair_gen_var_28, unsigned_pair_gen_var_44}; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::binomial_coefficient::*; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_2, natural_pair_gen_var_15, unsigned_pair_gen_var_45, unsigned_pair_gen_var_46, unsigned_pair_gen_var_47, unsigned_pair_gen_var_48, unsigned_pair_gen_var_49, }; use malachite_nz::test_util::natural::arithmetic::binomial_coefficient::*; use std::str::FromStr; #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_binomial_coefficient_limb_limb_bdiv() { fn test(n: Limb, k: Limb, out: &[Limb]) { let xs = limbs_binomial_coefficient_limb_limb_bdiv(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!(xs, out); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } // - k_max == 0 // - ones == 0 test(26, 26, &[1]); // - ones != 0 test(69, 32, &[10356137869959167254, 2]); // - k_max != 0 test( 364, 227, &[ 13299750156278230008, 15204945566537371181, 1343180567794975186, 14635289525631461779, 10747969514869510295, 9942168, ], ); test( 1000, 500, &[ 2548782591045708352, 2287006466848960994, 434054286371261995, 9307092176803372215, 1234012513444138811, 6453284806000209963, 9510906063553676151, 16379477204911690877, 4813923858496575229, 4008028500528486217, 13325564105666315328, 7088459241230905245, 10525434632971158032, 12617275459030976558, 17868910957880245731, 27735200797, ], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_binomial_coefficient_limb_limb_small_k() { fn test(n: Limb, k: Limb, out: &[Limb]) { let xs = limbs_binomial_coefficient_limb_limb_small_k(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!(xs, out); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } // - nmax >= k test(2, 2, &[1]); // - nmax < k // - numfac == 0 // - shift != 0 in limbs_hensel_div_limb test(9, 9, &[1]); // - numfac != 0 test(17, 17, &[1]); // - shift == 0 in limbs_hensel_div_limb test(836, 7, &[55217369185858880]); test( 1000, 25, &[4493608106319329376, 18354803010869864610, 140006850684], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_binomial_coefficient_limb_limb_basecase() { fn test(n: Limb, k: Limb, out: Limb) { assert_eq!(limbs_binomial_coefficient_limb_limb_basecase(n, k), out); assert_eq!( Natural::from(out), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } test(10, 5, 252); test(67, 65, 2211); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer() { fn test(n: Limb, k: Limb, out: &[Limb]) { let xs = limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!(xs, out); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } // - !BIN_UIUI_RECURSIVE_SMALLDC || hk <= ODD_FACTORIAL_TABLE_LIMIT as Limb // - n <= ODD_FACTORIAL_EXTTABLE_LIMIT as Limb test(27, 25, &[351]); // - n > ODD_FACTORIAL_EXTTABLE_LIMIT as Limb // - !BIN_UIUI_RECURSIVE_SMALLDC || k <= ODD_FACTORIAL_TABLE_LIMIT as Limb test( 10000, 25, &[12769553919776416000, 9951314237341865820, 6910797670090152703, 99667982199316897], ); // - BIN_UIUI_RECURSIVE_SMALLDC && hk > ODD_FACTORIAL_TABLE_LIMIT as Limb test(54, 52, &[1431]); // - BIN_UIUI_RECURSIVE_SMALLDC && k > ODD_FACTORIAL_TABLE_LIMIT as Limb test(93, 51, &[10325892988062052036, 28774313]); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_binomial_coefficient_limb_limb_goetgheluck() { fn test(n: Limb, k: Limb, out: &[Limb]) { let xs = limbs_binomial_coefficient_limb_limb_goetgheluck(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!(xs, out); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } // - prod <= max_prod first time // - ma < mb first time // - a >= prime first time // - ma >= mb first time // - a < prime first time // - sieve[index] & mask == 0 first time // - prod <= max_prod second time // - ma >= mb second time // - a >= prime second time // - ma < mb second time // - a < prime second time // - i <= max_i first time // - sieve[index] & mask != 0 first time // - i > max_i first time // - sieve[index] & mask != 0 second time // - i <= max_i second time // - sieve[index] & mask == 0 second time // - n % prime < k % prime // - prod <= max_prod third time // - n % prime >= k % prime // - prod > max_prod third time // - i > max_i second time // - sieve[index] & mask != 0 third time // - i <= max_i third time // - sieve[index] & mask == 0 third time // - prod <= max_prod fourth time // - prod > max_prod fourth time // - i > max_i third time // - j != 0 test( 1024, 512, &[ 9401457825549664838, 2721813090096631178, 14255346604713632433, 3580037932091556548, 1754384789820018233, 2635023193750144437, 11050518185659523387, 12964790596359511527, 1445883973524779011, 12061501847736594246, 3370187743259284348, 6342914377781736300, 5825027960880516300, 13264895533447765242, 4401514467996618027, 459836855626902435, ], ); // - prod > max_prod second time test( 1045, 519, &[ 5718966217258963792, 18109692964617656624, 12203044925148468153, 12014411658199454757, 12073183713056964826, 10217774024310452016, 5834695290287326173, 15738609591983585192, 1510425106975833791, 1194950807760887936, 13372185138508722787, 1955712450906595670, 3886453007529083390, 2635264355471572346, 11248337219650472692, 12482562081008645864, 50551, ], ); } #[test] fn test_binomial_coefficient_limb_limb() { fn test(n: Limb, k: Limb, out: &str) { let x = binomial_coefficient_limb_limb(n, k); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!( x, Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); } // - n >= k // - k == 0 test(0, 0, "1"); test(1, 0, "1"); test(1, 1, "1"); test(2, 0, "1"); // - k == 1 test(2, 1, "2"); test(2, 2, "1"); test(3, 0, "1"); test(3, 1, "3"); test(3, 2, "3"); test(3, 3, "1"); test(4, 0, "1"); test(4, 1, "4"); // - using limbs_binomial_coefficient_limb_limb_basecase test(4, 2, "6"); test(4, 3, "4"); test(4, 4, "1"); // - n < k test(1, 2, "0"); test(10, 5, "252"); // - using limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer test(100, 50, "100891344545564193334812497256"); // - using limbs_binomial_coefficient_limb_limb_small_k test(68, 2, "2278"); // - using limbs_binomial_coefficient_limb_limb_bdiv test( 557, 270, "12303897123684661862136414153519313173927533052423815769743887086897271613639625388778793\ 435582088957595545453390198975003546712921290727359277922023155427564241544480", ); // - using limbs_binomial_coefficient_limb_limb_goetgheluck test( 1520, 604, "75854072694680390545636184213535932745981366536099293315554162782484973010323284519943551\ 805370379122919525568608395918396659326939152960648811048376751248471027979484001171948494\ 104610240152756095326405688057789446682785317328585217327221577095099162137370467209392535\ 545646923979679739966748638562974802230089647823656716367175837356234669272446104178944990\ 64852838291828963125461234805108096610500907519032849968173861190511519206171866000", ); } #[test] fn test_binomial_coefficient() { fn test(n: &str, k: &str, out: &str) { let n = Natural::from_str(n).unwrap(); let k = Natural::from_str(k).unwrap(); let b = Natural::binomial_coefficient(n.clone(), k.clone()); assert!(b.is_valid()); assert_eq!(b.to_string(), out); let b_alt = Natural::binomial_coefficient(&n, &k); assert!(b_alt.is_valid()); assert_eq!(b_alt, b); assert_eq!(binomial_coefficient_naive_1(n.clone(), k.clone()), b); assert_eq!(binomial_coefficient_naive_2(n.clone(), k.clone()), b); if let Ok(k) = u32::try_from(&k) { assert_eq!(rug::Integer::from(&n).binomial(k).to_string(), out); } } // - k <= n // - k == 0 || n == k test("0", "0", "1"); test("1", "0", "1"); test("1", "1", "1"); test("2", "0", "1"); // - k != 0 && n != k // - double_cmp(&k, &n) != Greater // - k < 2 in binomial_coefficient_helper test("2", "1", "2"); test("2", "2", "1"); test("3", "0", "1"); test("3", "1", "3"); // - double_cmp(&k, &n) == Greater test("3", "2", "3"); test("3", "3", "1"); test("4", "0", "1"); test("4", "1", "4"); // - k >= 2 && Limb::convertible_from(&n) in binomial_coefficient_helper test("4", "2", "6"); test("4", "3", "4"); test("4", "4", "1"); // - k > n test("1", "2", "0"); test("10", "5", "252"); test("100", "50", "100891344545564193334812497256"); // - k >= 2 && !Limb::convertible_from(&n) in binomial_coefficient_helper // - k.even() first time in binomial_coefficient_raising_factorial_4 // - k <= Limb::power_of_2(Limb::WIDTH >> 1) in binomial_coefficient_hmul_nbnpk // - k.odd() second time in binomial_coefficient_raising_factorial_4 // - r == 0 first time in binomial_coefficient_raising_factorial_4 // - k != 0 in binomial_coefficient_raising_factorial_4 // - r != 0 second time in binomial_coefficient_raising_factorial_4 // - k > 1 in binomial_coefficient_raising_factorial_4 // - k - lk < 5 in binomial_coefficient_raising_factorial_4_rec // - k <= lk in binomial_coefficient_raising_factorial_4_rec test( "1000000000000000000000000", "10", "27557319223985890652556079144620811287477954168595679012345679012345418595679012345679012\ 347422646604938271604938264183063271604938271604958214285714285714285714253397817460317460\ 3174603457499999999999999999999900000000000000000000000", ); test( "1000000000000000000000000", "999999999999999999999990", "27557319223985890652556079144620811287477954168595679012345679012345418595679012345679012\ 347422646604938271604938264183063271604938271604958214285714285714285714253397817460317460\ 3174603457499999999999999999999900000000000000000000000", ); // - k.odd() first time in binomial_coefficient_raising_factorial_4 // - k.even() second time in binomial_coefficient_raising_factorial_4 // - k - lk >= 5 in binomial_coefficient_raising_factorial_4_rec // - k > lk in binomial_coefficient_raising_factorial_4_rec test( "25694718637547264792682404365646", "77", "24892107841828531181241909544492918596306121771031452631201178559919761115634737951594564\ 134356322099422004184733720911624149235259560430254876738408767931226785921407370175095156\ 586781390423037037354806763474907080465964805824615654538038771653753950919821491697271091\ 377714045381616063058884296191134488706691089783145326802624153519283791876914093506515827\ 833506442633078910514277387531336146210345320293586400210472321425351318080461247076886974\ 768698454873923739768679830132931625134235003968808918478243378730618857978191369012739961\ 051581373447851611688649593583701011088238159758896124868328792895820245726080012240623605\ 641788102744035650422323176408348710487482498610290424711478789115694916288138443827673675\ 370569473426454096853986388197987217558182898826734752119147506194959212385238127156463909\ 327557739453207008435734881763952972072877981513820560067736400661554297872808149726929774\ 009647173110901034073815261251706646282610156215143897705316902472221999807813890716324389\ 059130071475748736042259427029862564233394643788711602637944768761312353268539463729212269\ 415045191305842571853121600306112590657683014528748487348383916892187205977769846675553991\ 678198468541000193638965662990392249005490587691945513633072925439584423085568573063324438\ 190079886080774771402863370193790234632425970224213478091984184852108551225355019635354056\ 486480357281956498614205484617578531125055573838944472215270078882558231706258591409870228\ 048336579336293173152190873375502722426036746069862292026870602177622921149409743274336566\ 057103504313000613515998137450390738545271211718490829689241758733404923221326412878356941\ 435514837492022527605671586407700532750514057135146338845230795592073866772571401329026443\ 608142817184754893131076291570078101560304351288697491914877440785372806706691123696040114\ 923681774613230825471864285137036389227443209862850919338428947675401504411181949854055775\ 200409538150678687818266389944970852915636139634528094736089467929779413965463990220175083\ 710210323999501861734841899661962324188839025051105910476408529885881803658183792799548436\ 079055522933471249257212221461038082674897327598629096995991431788007725162706786103836085\ 868101229756394404428127938624116484159208824390263198961814488490969603019941815506011834\ 656564995524746083712970354462072408140254406415763673750", ); test( "18446744073709551615", "158", "55895522534362171876679545770571780830932656730029153560869974856994653843802569288729672\ 382637511859126481647849454205948292497053990755261689981054438192648753626841630309709195\ 818046531987560211901650810864524918303657683264406997638322847538595795406557688836851113\ 964170617643288481686744802130922248594817017440419821564431902277641567516581995890812918\ 486722065525008580823765669188839888456062057395467503086550870415427259131515369395143321\ 954047801400987772358011644373722286582971360737319736278747048729130702410986775490918876\ 230529996180462561974695082885810128945711270133861913341366432968582985806434359568905664\ 514713947374000003710986140313054418069500150430587294188316434107034410813333644810868109\ 517010015342588756758001231909300692391419214678692034627983296534319977780017419329875838\ 305344927801449612412534953383999840286057067187077005869924788433675067369851522793235730\ 315737008337149771567919123016352557348492008964898963676372074751843928582292062287972645\ 002479275926607204375396328813893195279046674831290420168619360957160719607118724011337751\ 884687312078496400868136122166666403111874431469083483195561561046860576791948708097239448\ 707700121141752690164054210305897535632910540849799510508361519672108494930297513957744916\ 541405888702155034069578507345846043015833055785496095916102636242742597283956473922401079\ 208727407330832207583179935719542716898842632948842003593449284004534387840878675132405353\ 545617559957750742653148569486728382115360807684946620305181043444563683398002670423056641\ 556205884154456331403885923859681242657192316862584038348512448080592213086456602118302523\ 497600139305650208731488402477762993305561030251065134570006992415665014910718509829224625\ 872159298105076966017786257520264468203354024508924179560925218008493771963278229045367865\ 887776645263717204778132848971659200666442585918134220062630814282240784092582922877337752\ 874525729691815214017623817845517096588696914035779725717257987350294068144824840587807588\ 357158318464027597598240198947245829267827323307370357782705746909925183438673236245050493\ 849326967187419243980545566285650601408510053072445047817977219500403018557783113306208827\ 167431080889349651649509675460140965485298062146167041924877070444810030309666624075227137\ 218638063690047219457567724110789914580071868854478163169581354672185562960327685598076336\ 690378854689193418551369074938423269725145368510358579999339101382841905493888240214883154\ 842774151093965701354532381623493383136070753785526556095815078903379059184394232509103407\ 445242908548214164343171473652463157048465973199937898538847219544675249899299702767453227\ 701439662328156741963625896736861699341091781695881895814781993228295591405890355373308533\ 69629590890184209436859538990383412624370182464931679935821512705", ); test( "18446744073709551615", "67", "17975145518991061179479323219129935574158608347154628002363871092506776489199109934521955\ 123099550607217011648682834882233989613437897676528916878068374745801854526845695228287766\ 789754958180819896635236168923015045618525205927314379144644668574770271895365790241559003\ 144822843889333362041474551859621080410036652606791515505353369554207762483251871851266970\ 526017855527470363796741702469836770390720021847155096242244011610914819823947147149757369\ 963787213725621805262787399500529025447928970023245860150872609280717916258813202603295120\ 573904776695107485006469437484809405204869700461623288629055326810940902543920025198724784\ 512861425829561074459250975049818414179892103155718839794288796334197669645772310664090067\ 383176579762499437658976815731335276585886004562625663405112281286580831287539250796636410\ 499555980578478064777424504455782233056592703195498279137626891735967240326084691333116555\ 048351036083482033114827059239588624846987544228990882068278651916209911673445783701818463\ 605412513547801208468857612548719031059286380708408871334262084700310978668806235603467446\ 875803132012584698568224321090559637699882304716272182566747176011138741513605154927341734\ 8337767036988850446297726975", ); // - r == 0 second time in binomial_coefficient_raising_factorial_4 test( "64794141400349148426125344064038245668210", "256", "66031965476204798455146874331523684080813362175686018331031515911090977873910155832605365\ 024088507121468974811846414037841974044761919328109003377289871853511171575036733766570594\ 891453274802950544969704784506297953600869073325018040500075322154584368142810932546171082\ 852158395260664371405927007989709292505767982485700717462755039001448808389259756963264278\ 906088556027912417831893433509962336148107621718179651346831471790176401806766480380429889\ 091161537666615007387280496039863931909142998822738027792169782639238146079132322198094998\ 802486850137067671945865080411439029612107336301348639088595876320707598941419394424283157\ 143766976110612717751687095427384089847206769596670568078428576165333416386232441693390109\ 663643281983434582393770222667816544269262132334616225677948861772526297326474869185995248\ 147223996638098457580467492870356321781996013113726822987288450823900111773163205636973304\ 380289800405883789689472988397794249318636225811197198716377966054543346740613593561974377\ 093009085172518201919751004048922207546914508128933773326960672960593784186495358724918479\ 796985664038589538200615872665489843329713567750689491887312970295325573546986255121402411\ 084560066792113137699614374211253083694137958737734257446884558418163050219974644457688081\ 676873402993322999032939870868467432529157509565329259639753569836216746833599315763759693\ 829765447474480250973648293550957370797807649367827793436798113040510064141170940749382465\ 206220269485857516368112061908007860073237682581918967583093557269558058823518949817468789\ 084216644967899755535494281973068520476114970926637305610945283948226717762805241122575066\ 678103015124110768502924767744781460648409786391934340118093908438148276389461167601820750\ 057069093773693074665652175457980958723759516515717047910383569619901407819068208673474699\ 453686471361006890630023875323558303493400544302118291489329274887331045875348205800862710\ 175052394281227458757959196016039413945472225266077758335879434496501644524406760148503536\ 777844536674510188616914664398525551534555340932552542038044113796537414101079613456296985\ 563991419519025675361727124584048105966929210844853432544846497675490471504969416848715119\ 092439521396484249151715675927492341087857671196859845186304379535276682803519065353324314\ 753738064545044955708632071615933033701914916065271501916712011810342168742156422262920787\ 990320364401380933898662355120884340792786670753109271316345859012462545725984191058886315\ 780390631728366246215522172383402706101501675956766022277331224839584378620731356043496863\ 785541271891585740098376406528987886519218563576267816719725054923546357372040525223848949\ 127753974390320001547914359669712714875205242660997027993020756142973623600187114692661037\ 463223091304396021296078235892866862323792231314445721295667474988263893282253274196685780\ 474772501116806432261201824061161163113862619883103396549652499049127008949545703101415021\ 959323424435960397307451027052471053244276197436645437020963781472397247593591077373074717\ 094053719991571689422435129889293085327836165576103011597448058754151829033639997737893083\ 842550015423824149716583089263434540508738377195408947652432376611378742646557728539254326\ 476152890041397510536077837901277246692068153800616280367894133910883810668466983308213587\ 221482938745562008958936847061728216788782564518434418288722461230400118273167234421901949\ 895714204179305818559684033777442551682966339667887715092224700434706792933312052909488102\ 079842621982456264706730931310278553720716127067281236666033604620046598324107408026680346\ 412372599646940552339198684588489969280418636356788664147669690402699465461172213740285470\ 809128728317682820264186890847420093051962425795653283884719000382298889430710471760502027\ 229103999961325795946767445375287269359953381217519871307479690576346343309759003193210071\ 556418039142564126112040263001368700411929992559256249934586198220607434498304226202009811\ 851202657216426523574148350721115772654468971702946249623853433692813341850096864575825766\ 875327019841615467863988595861381027218305979988212099705711032765590105239080603592671851\ 263007878964971854611940675180372780784561628267671888044540380421481565399877355853257247\ 904912714553488274268173076162924936684919527723389714147069548613898253656186458224176096\ 650679656664121232090301986651148027643907951818914611914284611587891731441594791289668499\ 732443965790127087948406108626423198713173029654246468017240080444863841518378912082628643\ 724261542806751229219083492033570837867883135531192455131856234586805554416472640371021449\ 626153219324461765285594058845200904698148046455373363116514572144638111797423237086355564\ 247860048288380294928679328053911481495367259163199843147875393924983826306330183640755507\ 721631146048737226709507724059249592648982425588036008000118061247531554850396149937729527\ 930090878598591797914711906297196260037210666173426412078722356587377867788754800643764289\ 349492930056977738160467345399517207696550782762419615728732412876581046942100815806171450\ 348045418018196938450493961876960731452162424045420483182667480966924113555262743123695828\ 842908617606474347446639604774874895056539625426950012998315670654871344246635345053749863\ 496640365576291398308932572744385646669612244790159569747800709995170292663386348773622916\ 561134395120135530744456556349965822317543312742948102629799123576739818344673647025657695\ 985344238813907956117069517497661033396357007152583146264519158459022423403393518704274469\ 555988017487304952556931240339272093145564884487180943346829587730987339974521536847163156\ 576792360583613136094081709906550031136279843694368596413923678731949271836013710356271449\ 750444414580685902236336967295155735991873355394004365947388684449125129801766071721100317\ 754267126693147225832067659102896333959362151819898227685846445795875977111413552941797422\ 553933826223370170202722743530536102426573846057258556374829036318491118228532586723711507\ 306175083430903562551070805871091783816943579841868012387755648345966129650056499655937025\ 786637878092663953415315273277401554564452187856322467035501932551411544392181881298986961\ 977669220229531562675556039911519639525744745226708275593777931260713611128737604054948983\ 139973224611064054789667235394810524925200258714854048451678007812968231907618644701400069\ 416728442304285423001695542417198763520331552551177941831892213963517136796389994665927604\ 459301587378625571860379754039201572427152553572980209384382435194093360849052249292611790\ 503999041541116237688173853723809560117304453500860053652419055303646548732887211219816022\ 640151501792454343959659164109351416330947070094808894238884111531377647551954029108954865\ 820855989915402340973344448073147690851869968726931741577360043521731876511950237869229333\ 859602928143413880913510506371294577002903467954358083654964723356629201256978479953248587\ 837494474562791991946166010566508192581355676686351165394433654073840991635192074086973572\ 163621004682262040173522080229706241781899722662323148146556857674870483185715528972858490\ 341376734230716934752618524152956020461673836080774036785780214798629565634422775934543353\ 476894063593324705839019506068594012535084480289279779876445412055235366951246546684773766\ 212435536276729263154137776171656339214503240937372959067826975944390909279310279488186009\ 284938438825832468869538671600734260099608765379746524963643065452430188106594098479755797\ 093870460951873974971714697637666625870945820997332659684169379272678395704589081533814498\ 140005779826762539275887677973897726706795887769141977524446776813526719526578593420736712\ 954032634210661657840530040608510833332863779404436297002475234120661252662270361338493492\ 578189610080628765357649189060318248893668432942439239400104110762226338091351054740301228\ 267114030372038914676357083876933841022019867273340907399707064313910406654589321612531521\ 602233355695432124690159097553479392454292250308539955098369447489417568755029977263235806\ 737535494742497503685663730366012718441966449290261821980738958389669746636037465845741790\ 748315986037312254641500834573322524472364659503566291792471608054787771836144999713040748\ 466357834461871406015310449476989294914019751283337432367578854283638114561957941268079431\ 890173027032456336882142230048504806653501455520488580583506078652051408716252946680955540\ 372281906409585858036827184877008395810459992480127401354027016126387228520620234335154464\ 821713911693946238556003001085542056042701510153072679687977939864130493222714210229201112\ 642263071677946070197883792071982433883297230356359448021422941875047191241501644623057173\ 683380213277548600830552213704456922714478433917536416960698247481747286784162314893055284\ 885473180947515913242742950779558619216152807571397814191898554257601274089785855209288639\ 494478547781184010543598204017553457188090206965615937213419385871077837956771570536756086\ 174306711357612692470993367865237583867552293229085658581609124490438092837633181262633832\ 224797483199978752769003102249388926725978940121151544263886670246958179931376644535033670\ 467812416073434198259354970151012012393996634623039876371855129029695663871190598266249780\ 985956108718263661078782256910771187915990947315908329250697737849898883453664118270530637\ 992646293212166265938379652583376259988885243320020604733922599818302151475423517827259313\ 745572427630024541315969730421839521723099984520094706630448404321113193582564213335655774\ 981763101020538995438787319788215596029041832485363544281092101855739567987099076742200167\ 364424955142913668223754444009608547667377068092022968659294922490236070017253740709080640\ 315292979235034789700250605885981133239085270171689650328229691156105945528843937717117926\ 974279215959289065294575953759240127500933613923927450217241389655578977813273562315693668\ 620610689781058230089093580999028877435087490580246008336904216212775259586405528318199698\ 927003543457809044748027664785695692314604437532737114872376072006455841723036100877964792\ 160706943287071568418614565943721712313708341206571425251067669284456587123688846181674686\ 565863767558687263852890202721039246395025", ); // - r != 0 first time in binomial_coefficient_raising_factorial_4 test( "525899105584115331831822389398654378975439821235847075538334479459976804361", "39", "63916028057105686233224647128326757355318526278850191265753818300077123506148592771686251\ 843871031286613741578697393929955287964794759564768972837142349342808068645976054243890830\ 335431299980007761289437669633253213451826328048705819152063003640688010892927140146765994\ 354038412675123498589995067406959494949003877187335117608898667586172913313268407045309326\ 477759661775566817269791782958981335897762329413676812249676003924448031057465002588047731\ 852626643205542869258383826751237297401033366907927123119420545541506268940498743697330488\ 751030122065781855695143246866312361451074604659115580225953639683092992548231210545034231\ 285233852021142144210530482766055167812957716779323951011087624228337943053231819759016008\ 625315621642894259660510209185578346141448798234857352488051062830286245538065408386075147\ 891775165871474412122232335872318403542887945441629517772432566332148611895718898507734193\ 765122244095887688382558927354124421602429208358235005847747779165375960977523729969144623\ 942428302069692001442132909094843144966416850972408319273833346995290959884209879178506231\ 148534376246222578564697565675661378959062018141850826958907520091990573403348600298989654\ 015323124079115828761962218496431800939709402415702347227440683769932960611846922227191597\ 870575184258217562373579180321454906142789445372655817629764513368590547268810214608619866\ 197718738244504054960382041108971143812515663988260257731991609483301668915756882792269602\ 669162926415723894743233548358640390458315117002551455170242787151998722348149039656347608\ 551565127458440090648316733044596038381441744468926633398369489669625808759994489694980764\ 526999955110732774112122334751376885411610502128309282739439676195629420963063203373174208\ 091590129280478685913083169673141792020290565109251623524461277589125997756234920480123074\ 209844165277719752489744793568781301978159825605932386339370565204645057536772220679746768\ 569224291055005731953230004831223439059300914798178296528394239043745002141250499403742249\ 183874569695076545083105825050171871111881712648095404574108051786690297924470700238074897\ 792414511177305601932558389549730072609925691552289753566425338003950881601294728845880132\ 500287043788618527834331584961373617001959960073108393488866008662550518286185355757098004\ 407731116008477326366253892028653451448990656804004447051045116046286082144417019317955065\ 059880762228310370726650525371685367667341518793755754089895626603855406071794521713173191\ 730870597842233077363902687264007764576583562429780462716550361987547856866479132368207653\ 806647693143188635189378544081798845519519486948493126898293329214413593802057692320667583\ 766380661973838437256232890788063096146364826652367871270984406087292750139629458354387512\ 791101502903444068723989625533851827638409364499043290472310636212447688058605971032119472\ 5991269626624579699378058679358476375414026678029422929039835277325354971910400", ); // - k == 0 in binomial_coefficient_raising_factorial_4 test( "55186653679569007523486527767687421937059940360080261894526453", "3", "28012439529730582769980703531255137397476701127318927388432337037639370308404590341026789\ 244616713573401635136679393282116959418116580481496576838954049642935186063159197881085428\ 921826", ); // - k <= 1 in binomial_coefficient_raising_factorial_4 test( "821407847938765300653812701638851178", "5", "31161115310790267810728647115818905409309919004871253034511265989952209125820211890996722\ 13934942403111281665464675315630857236685237472673845588842782932266933122933085560371660", ); fn test_large(n: &str, k: &str) { let n = Natural::from_str(n).unwrap(); let k = Natural::from_str(k).unwrap(); let b = Natural::binomial_coefficient(n.clone(), k.clone()); assert!(b.is_valid()); let b_alt = Natural::binomial_coefficient(&n, &k); assert!(b_alt.is_valid()); assert_eq!(b_alt, b); assert_eq!(binomial_coefficient_naive_2(n.clone(), k.clone()), b); if let Ok(k) = u32::try_from(&k) { assert_eq!(Natural::exact_from(&rug::Integer::from(&n).binomial(k)), b); } } // - k > Limb::power_of_2(Limb::WIDTH >> 1) in binomial_coefficient_hmul_nbnpk test_large("4294967296", "131076"); } #[test] fn limbs_binomial_coefficient_limb_limb_bdiv_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_45().test_properties_with_config(&config, |(n, k)| { let xs = limbs_binomial_coefficient_limb_limb_bdiv(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); }); } #[test] fn limbs_binomial_coefficient_limb_limb_small_k_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_46().test_properties_with_config(&config, |(n, k)| { let xs = limbs_binomial_coefficient_limb_limb_small_k(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); }); } #[test] fn limbs_binomial_coefficient_limb_limb_basecase_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_47().test_properties_with_config(&config, |(n, k)| { assert_eq!( Natural::from(limbs_binomial_coefficient_limb_limb_basecase(n, k)), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); }); } #[test] fn limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_48().test_properties_with_config(&config, |(n, k)| { let xs = limbs_binomial_coefficient_limb_limb_small_k_divide_and_conquer(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)) ); }); } #[test] fn limbs_binomial_coefficient_limb_limb_goetgheluck_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_49().test_properties_with_config(&config, |(n, k)| { let xs = limbs_binomial_coefficient_limb_limb_goetgheluck(n, k); assert_ne!(*xs.last().unwrap(), 0); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::binomial_coefficient(Natural::from(n), Natural::from(k)), ); }); } #[test] fn binomial_coefficient_limb_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_small_n", 256); unsigned_pair_gen_var_28().test_properties_with_config(&config, |(n, k)| { let x = binomial_coefficient_limb_limb(n, k); assert!(x.is_valid()); assert_eq!( x, Natural::binomial_coefficient(Natural::from(n), Natural::from(k)), ); }); } #[test] fn binomial_coefficient_properties() { natural_pair_gen_var_15().test_properties(|(n, k)| { let b = Natural::binomial_coefficient(n.clone(), k.clone()); assert!(b.is_valid()); let b_alt = Natural::binomial_coefficient(&n, &k); assert!(b_alt.is_valid()); assert_eq!(b, b_alt); assert_eq!(binomial_coefficient_naive_1(n.clone(), k.clone()), b); assert_eq!(binomial_coefficient_naive_2(n.clone(), k.clone()), b); assert_eq!( Natural::exact_from(&rug::Integer::from(&n).binomial(u32::exact_from(&k))), b ); assert_eq!(b == 0u32, n < k); if n >= k { assert_eq!(Natural::binomial_coefficient(&n, &(&n - &k)), b); } if n != 0u32 && k != 0u32 { let c = Natural::binomial_coefficient(&n - Natural::ONE, &k - Natural::ONE); assert_eq!( Natural::binomial_coefficient(&(&n - Natural::ONE), &k) + &c, b ); let gcd = (&n).gcd(&k); assert_eq!(c.div_exact(k.div_exact(&gcd)) * n.div_exact(gcd), b); } }); natural_gen().test_properties(|n| { assert_eq!(Natural::binomial_coefficient(&n, &Natural::ZERO), 1u32); assert_eq!(Natural::binomial_coefficient(&n, &Natural::ONE), n); }); natural_gen_var_2().test_properties(|n| { assert_eq!(Natural::binomial_coefficient(&n, &n), 1u32); assert_eq!(Natural::binomial_coefficient(&n, &(&n - Natural::ONE)), n); assert_eq!(Natural::binomial_coefficient(Natural::ZERO, n), 0u32); }); unsigned_pair_gen_var_44::().test_properties(|(n, k)| { assert_eq!( Natural::binomial_coefficient(Natural::from(n), Natural::from(k)), Limb::binomial_coefficient(n, k) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/checked_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedSub; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use malachite_nz::test_util::natural::arithmetic::checked_sub::checked_sub; use num::BigUint; use rug; use std::str::FromStr; #[test] fn test_checked_sub_natural() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let on = u.clone().checked_sub(v.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = u.clone().checked_sub(&v); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = (&u).checked_sub(v.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = (&u).checked_sub(&v); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = checked_sub(BigUint::from_str(s).unwrap(), BigUint::from_str(t).unwrap()) .map(|x| Natural::from(&x)); assert_eq!(on.to_debug_string(), out); let on = checked_sub( rug::Integer::from_str(s).unwrap(), rug::Integer::from_str(t).unwrap(), ); assert_eq!(on.to_debug_string(), out); }; test("0", "0", "Some(0)"); test("0", "123", "None"); test("123", "0", "Some(123)"); test("456", "123", "Some(333)"); test("1000000000000", "123", "Some(999999999877)"); test("123", "1000000000000", "None"); test( "12345678987654321", "314159265358979", "Some(12031519722295342)", ); test("4294967296", "1", "Some(4294967295)"); test("4294967295", "4294967295", "Some(0)"); test("4294967296", "4294967295", "Some(1)"); test("4294967296", "4294967296", "Some(0)"); test("4294967295", "4294967296", "None"); test("18446744073709551616", "1", "Some(18446744073709551615)"); test("18446744073709551615", "18446744073709551615", "Some(0)"); test("18446744073709551616", "18446744073709551615", "Some(1)"); test("18446744073709551615", "18446744073709551616", "None"); test( "70734740290631708", "282942734368", "Some(70734457347897340)", ); test("282942734368", "70734740290631708", "None"); } #[test] fn checked_sub_properties() { natural_pair_gen().test_properties(|(x, y)| { let diff = if x >= y { let mut mut_x = x.clone(); mut_x -= &y; assert!(mut_x.is_valid()); let diff = mut_x; let mut rug_x = rug::Integer::from(&x); rug_x -= rug::Integer::from(&y); assert_eq!(Natural::exact_from(&rug_x), diff); Some(diff) } else { None }; let diff_alt = x.clone().checked_sub(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.as_ref().is_none_or(Natural::is_valid)); let diff_alt = x.clone().checked_sub(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.as_ref().is_none_or(Natural::is_valid)); let diff_alt = (&x).checked_sub(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.as_ref().is_none_or(Natural::is_valid)); let diff_alt = (&x).checked_sub(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.as_ref().is_none_or(Natural::is_valid)); let reverse_diff = (&y).checked_sub(&x); assert_eq!(reverse_diff.is_some(), x == y || diff.is_none()); assert_eq!( checked_sub(BigUint::from(&x), BigUint::from(&y)).map(|x| Natural::from(&x)), diff ); assert_eq!( checked_sub(rug::Integer::from(&x), rug::Integer::from(&y)) .map(|x| Natural::exact_from(&x)), diff ); if let Some(diff) = diff { assert!(diff <= x); assert_eq!(diff + &y, x); } }); natural_gen().test_properties(|x| { assert_eq!((&x).checked_sub(Natural::ZERO).as_ref(), Some(&x)); assert_eq!((&x).checked_sub(&x), Some(Natural::ZERO)); if x != 0 { assert!((Natural::ZERO.checked_sub(x)).is_none()); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( x.checked_sub(y).map(Natural::from), Natural::from(x).checked_sub(Natural::from(y)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/checked_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedSub, CheckedSubMul}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::unsigned_triple_gen_var_19; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use std::str::FromStr; #[test] fn test_checked_sub_mul() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let w = Natural::from_str(t).unwrap(); let on = u.clone().checked_sub_mul(v.clone(), w.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = u.clone().checked_sub_mul(v.clone(), &w); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = u.clone().checked_sub_mul(&v, w.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = u.clone().checked_sub_mul(&v, &w); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); let on = (&u).checked_sub_mul(&v, &w); assert_eq!(on.to_debug_string(), out); assert!(on.is_none_or(|n| n.is_valid())); }; test("0", "0", "0", "Some(0)"); test("0", "0", "123", "Some(0)"); test("123", "0", "5", "Some(123)"); test("123", "5", "1", "Some(118)"); test("123", "5", "100", "None"); test("10", "3", "4", "None"); test("15", "3", "4", "Some(3)"); test("1000000000000", "0", "123", "Some(1000000000000)"); test("1000000000000", "1", "123", "Some(999999999877)"); test("1000000000000", "123", "1", "Some(999999999877)"); test("1000000000000", "123", "100", "Some(999999987700)"); test("1000000000000", "100", "123", "Some(999999987700)"); test("1000000000000", "65536", "65536", "Some(995705032704)"); test("1000000000000", "1000000000000", "0", "Some(1000000000000)"); test("1000000000000", "1000000000000", "1", "Some(0)"); test("1000000000000", "1000000000000", "100", "None"); test("0", "1000000000000", "100", "None"); test("4294967296", "1", "1", "Some(4294967295)"); test("3902609153", "88817093856604", "1", "None"); } #[test] fn checked_sub_properties() { natural_triple_gen().test_properties(|(a, b, c)| { let result = (&a).checked_sub_mul(&b, &c); assert!(result.as_ref().is_none_or(Natural::is_valid)); let result_alt = a.clone().checked_sub_mul(&b, &c); assert!(result_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_alt, result); let result_alt = a.clone().checked_sub_mul(&b, c.clone()); assert!(result_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_alt, result); let result_alt = a.clone().checked_sub_mul(b.clone(), &c); assert!(result_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_alt, result); let result_alt = a.clone().checked_sub_mul(b.clone(), c.clone()); assert!(result_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_alt, result); assert_eq!(a.checked_sub(b * c), result); }); natural_gen().test_properties(|n| { assert_eq!((&n).checked_sub_mul(&n, &Natural::ONE), Some(Natural::ZERO)); }); natural_pair_gen().test_properties(|(a, b)| { assert_eq!((&a).checked_sub_mul(&Natural::ZERO, &b).as_ref(), Some(&a)); assert_eq!((&a).checked_sub_mul(&b, &Natural::ZERO).as_ref(), Some(&a)); assert_eq!( (&a).checked_sub_mul(&Natural::ONE, &b), (&a).checked_sub(&b) ); assert_eq!((&a).checked_sub_mul(&b, &Natural::ONE), a.checked_sub(b)); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert_eq!( x.checked_sub_mul(y, z).map(Natural::from), Natural::from(x).checked_sub_mul(Natural::from(y), Natural::from(z)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/coprime_with.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CoprimeWith, Gcd}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::coprime_with::{ coprime_with_check_2, coprime_with_check_2_3, coprime_with_check_2_3_5, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use std::str::FromStr; #[test] fn test_coprime_with() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.clone().coprime_with(v.clone()), out); assert_eq!((&u).coprime_with(v.clone()), out); assert_eq!(u.clone().coprime_with(&v), out); assert_eq!((&u).coprime_with(&v), out); }; test("0", "0", false); test("0", "6", false); test("6", "0", false); test("1", "6", true); test("6", "1", true); test("8", "12", false); test("54", "24", false); test("42", "56", false); test("48", "18", false); test("3", "5", true); test("12", "60", false); test("12", "90", false); test("12345678987654321", "98765432123456789", true); test("12345678987654321", "98765432123456827", false); } #[test] fn coprime_with_properties() { natural_pair_gen().test_properties(|(x, y)| { let c = (&x).coprime_with(&y); assert_eq!(x.clone().coprime_with(y.clone()), c); assert_eq!(x.clone().coprime_with(&y), c); assert_eq!((&x).coprime_with(y.clone()), c); assert_eq!((&x).gcd(&y) == 1, c); assert_eq!(coprime_with_check_2(x.clone(), y.clone()), c); assert_eq!(coprime_with_check_2_3(x.clone(), y.clone()), c); assert_eq!(coprime_with_check_2_3_5(x.clone(), y.clone()), c); assert_eq!(y.coprime_with(x), c); }); natural_gen().test_properties(|x| { assert_eq!((&x).coprime_with(&x), x == 1); assert!((&x).coprime_with(Natural::ONE)); assert_eq!((&x).coprime_with(Natural::ZERO), x == 1); let y = &x + Natural::ONE; assert!(x.coprime_with(y)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( Natural::from(x).coprime_with(Natural::from(y)), x.coprime_with(y) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedDiv, DivMod}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_12, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::div::{ limbs_div, limbs_div_barrett, limbs_div_barrett_approx, limbs_div_barrett_approx_scratch_len, limbs_div_barrett_scratch_len, limbs_div_divide_and_conquer, limbs_div_divide_and_conquer_approx, limbs_div_divisor_of_limb_max_with_carry_in_place, limbs_div_divisor_of_limb_max_with_carry_to_out, limbs_div_schoolbook, limbs_div_schoolbook_approx, limbs_div_to_out, limbs_div_to_out_ref_ref, limbs_div_to_out_ref_val, limbs_div_to_out_val_ref, }; use malachite_nz::natural::arithmetic::div::{ limbs_div_limb, limbs_div_limb_in_place, limbs_div_limb_to_out, }; use malachite_nz::natural::arithmetic::div_mod::limbs_two_limb_inverse_helper; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ large_type_gen_var_10, large_type_gen_var_11, large_type_gen_var_12, natural_gen, natural_gen_var_2, natural_pair_gen, natural_pair_gen_var_5, natural_pair_gen_var_6, unsigned_vec_triple_gen_var_42, unsigned_vec_triple_gen_var_43, unsigned_vec_triple_gen_var_44, unsigned_vec_unsigned_unsigned_triple_gen_var_9, }; use malachite_nz::test_util::natural::arithmetic::div::{ limbs_div_limb_in_place_alt, limbs_div_limb_to_out_alt, }; use num::BigUint; use num::CheckedDiv as NumCheckedDiv; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_limb_and_limbs_div_limb_in_place() { let test = |ns: &[Limb], d: Limb, q: &[Limb]| { assert_eq!(limbs_div_limb(ns, d), q); let mut ns = ns.to_vec(); let ns_old = ns.clone(); limbs_div_limb_in_place(&mut ns, d); assert_eq!(ns, q); let mut ns = ns_old; limbs_div_limb_in_place_alt(&mut ns, d); assert_eq!(ns, q); }; test(&[0, 0], 2, &[0, 0]); test(&[6, 7], 1, &[6, 7]); test(&[6, 7], 2, &[0x80000003, 3]); test(&[100, 101, 102], 10, &[1288490198, 858993469, 10]); test(&[123, 456], 789, &[2482262467, 0]); test(&[u32::MAX, u32::MAX], 2, &[u32::MAX, 0x7fffffff]); test(&[u32::MAX, u32::MAX], 3, &[0x55555555, 0x55555555]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_fail_1() { limbs_div_limb(&[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_fail_2() { limbs_div_limb(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_in_place_fail_1() { limbs_div_limb_in_place(&mut [10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_in_place_fail_2() { limbs_div_limb_in_place(&mut [10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_limb_to_out() { let test = |out_before: &[Limb], ns: &[Limb], d: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_div_limb_to_out(&mut out, ns, d); assert_eq!(out, out_after); let mut out = out_before.to_vec(); limbs_div_limb_to_out_alt(&mut out, ns, d); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[0, 0], 2, &[0, 0, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 1, &[6, 7, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, &[0x80000003, 3, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, &[1288490198, 858993469, 10, 10], ); test( &[10, 10, 10, 10], &[123, 456], 789, &[2482262467, 0, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 2, &[u32::MAX, 0x7fffffff, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 3, &[0x55555555, 0x55555555, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_fail_1() { limbs_div_limb_to_out(&mut [10], &[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_fail_2() { limbs_div_limb_to_out(&mut [10, 10], &[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_fail_3() { limbs_div_limb_to_out(&mut [10], &[10, 10], 10); } fn verify_limbs_div(qs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let expected_q = &n / &d; let base_q_len = ns.len() - ds.len(); let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); assert_eq!(q, expected_q); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); let r = n - q * &d; assert!(r < d); } #[test] fn test_limbs_div_schoolbook() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); assert_eq!(limbs_div_schoolbook(&mut qs, &mut ns, ds, d_inv), q_highest); assert_eq!(qs, qs_out); verify_limbs_div(qs_in, ns_in, ds, q_highest, &qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len < d_len_m_1 // - !highest_q first time // - !(!flag || n_1 < Limb::try_from(d_len).unwrap()) test(&[10], &[1, 2, 3], &[3, 4, 0x80000000], false, &[10]); // - q_len >= d_len_m_1 // - !(n_1 == d_1 && ns[d_len_s_m_1] == d_2) // - !carry first time // - d_len_s >= 2 // - !(!flag || n_1 >= d_1) first time // - !carry second time // - !(!flag || n_1 >= d_1) second time test( &[10, 10, 10, 10], &[1, 2, 3, 4, 5, 6], &[3, 4, 0x80000000], false, &[4294967207, 9, 12, 10], ); // - !flag || n_1 < Limb::try_from(d_len).unwrap() // - !highest_q second time // - q_len != 0 // - limbs_sub_limb_in_place(ns_hi, limbs_sub_mul_limb_same_length_in_place_left(ns_lo, qs, // ds[i])) fourth time // - n_1 == 0 third time test(&[10], &[0, 0, 0, 1], &[1, 0, 0x80000000], false, &[1]); // - q_len == 0 second time test(&[10], &[0; 3], &[0, 0, 0x80000000], false, &[10]); // - *ns_last >= carry test(&[10; 3], &[0; 5], &[0, 0, 0x80000000], false, &[0, 0, 10]); // - n_1 != 0 third time test( &[10; 2], &[0, 0, 1, 1], &[1, 0, 0x80000000], false, &[2, 10], ); // - highest_q first time test( &[10, 10], &[ 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, ], &[ 1430162564, 1873089879, 3090281851, 2861182896, 2502166555, 2486624904, 960387080, 3073064701, ], true, &[10, 10], ); // - !flag || n_1 >= d_1 second time // - n_1 == carry second time test( &[10; 2], &[0, 0, 1, 0, 1], &[0, 1, 0x80000000], false, &[u32::MAX, 1], ); // - carry second time test( &[10; 2], &[0, 0, 0, 0, 1], &[1, 0, 0x80000000], false, &[u32::MAX, 1], ); // - *ns_last < carry // - n_1 != 0 first time // - highest_q second time // - !carry third time test( &[10; 20], &[ 4294966784, 16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffff00, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xf0000000, 16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2540339372, ], true, &[ 2788498651, 3973284986, 2817551825, 2648982666, 1871496085, 1183691368, 1920086634, 2156916676, 2580901671, 858626385, 3833802894, 4255330726, 3612427555, 2966560147, 10, 10, 10, 10, 10, 10, ], ); // - carry third time // - n_1 != 0 second time test( &[10; 8], &[ 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, 63, 0, 0, 0, 0, 4294966784, u32::MAX, 255, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2874223232, ], true, &[ 3459164144, 2642691284, 1062969477, 1392962372, 1677352416, 1850494842, 2123025524, 10, ], ); // - !flag || n_1 >= d_1 first time // - n_1 == carry first time test( &[10; 10], &[ 0, 0, 0, 0, 0, 0xfffffff8, u32::MAX, 0xfffff, 0, 0, 0xffff0000, u32::MAX, 0x1fffff, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fffff, 0, 0, 0, 0, u32::MAX, 3500471700, ], true, &[ 1188137339, 3726116623, 2078060623, u32::MAX, 2498443049, 1067076977, 2528078370, 1716103827, 974820792, 10, ], ); // - n_1 == 0 first time test( &[10; 20], &[ 0, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffff00, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7ffffff, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3828608089, ], true, &[ 2643432265, 2230909280, 3987412564, 1770201633, 2297365160, 1655451772, 3061719465, 182613124, 3034480808, 3038313569, 3464266718, 249914758, 4270196816, 4141866692, 91710029, 4264403435, 2579237268, 67618125, 523165989, 10, ], ); // - n_1 != carry first time // - flag && n_1 < carry first time test( &[10; 73], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xf0000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4024661822, ], true, &[ 201450768, 518871072, 3015445987, 3944509552, 208835829, 3460787832, 1884898895, 2547198435, 186469778, 3505271765, 1840399470, 2685063887, 2953363253, 1530364228, 3130405732, 893752596, 3868726834, 4151054974, 2514125465, 3161927869, 2354681787, 1962216954, 2851892627, 2800023632, 4197573593, 3243049600, 922941226, 2202547330, 3061793011, 1583790204, 3045500683, 440439528, 2631483812, 1993907261, 2362030668, 4006507490, u32::MAX - 1, 2180774078, 372389172, 842953352, 3854387892, 1420082779, 4086327226, 1481011735, 2795106458, 2092419963, 1299755146, 3455955436, 2935373316, 2973368959, 208681747, 1883779895, 599992803, 1583705426, 4184839928, 352155351, 1499776059, 3341886577, 2973508834, 452082451, 98512703, 1051917695, 3372026069, 2092419965, 1233174284, 2711177091, 1249466612, 3854527767, 1663483483, 2301060034, 1932936627, 288459805, 10, ], ); // - carry first time test( &[10; 45], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294967279, u32::MAX, u32::MAX, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0xffffff00, u32::MAX, u32::MAX, u32::MAX, ], &[0xffff0000, u32::MAX, 16383, 3221225472, u32::MAX, u32::MAX, 2953571387], true, &[ 1344119085, 4210855069, 928035132, 841350331, 528284037, 1219359454, 3548354897, 1057752790, 3847832303, 1950615424, 782270048, 1691663352, 2130612726, 2986797999, 2134900501, 367200458, 366133304, 4140157070, 1119890783, 2133610345, 309344350, 1553079209, 39974261, 4150943609, 1565848679, 3244273595, 2309629507, 3647061699, 1476447016, 2423314465, 988904489, 3076842837, 370106892, 2669774090, 81048948, 2207992586, u32::MAX, 2794855737, 2919419242, 2509602689, 685991398, 3934508174, 2079332445, 1950605148, 10, ], ); // - n_1 != carry second time // - flag && n_1 < carry second time test( &[10; 10], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3833725436, ], true, &[ u32::MAX - 1, 150659924, 1536731131, 3027101341, 827397342, 835599031, 2855838328, 1016945560, 516734631, 10, ], ); // - !(flag && n_1 < carry) first time test( &[0; 3], &[ 0xffff0000, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294965248, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, 8191, ], &[ 0xffff0000, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 255, 0, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[u32::MAX, u32::MAX, 8191], ); // - q_len == 0 first time test( &[0], &[0, 0, 0x80000000], &[0, 0x80000000, 0x80000000], false, &[0], ); } #[cfg(not(feature = "32_bit_limbs"))] { // - !limbs_sub_limb_in_place(ns_hi, limbs_sub_mul_limb_same_length_in_place_left(ns_lo, qs, // ds[i])) fourth time test( &[10], &[0, 0, 1, 1], &[0, 1, 0x8000000000000000], false, &[2], ); // - n_1 == d_1 && ns[d_len_s_m_1] == d_2 // - !(flag && n_1 < carry) second time test( &[10; 518], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], true, &[ u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); test( &[10; 3], &[ 0x20000000, 4503599090491408, 31664835368329200, 18410716373991817215, 18157950747604419646, 2301339547025015295, ], &[18446744073172680704, 18442240474082189295, 18410716376202215423], false, &[u64::MAX, 0, 2305843009213431808], ); } } #[test] #[should_panic] fn limbs_div_schoolbook_fail_1() { let ds = &[3, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_fail_2() { let ds = &[3, 4, 5, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_fail_3() { let ds = &[3, 4, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook(&mut [10], &mut [1, 2, 3, 4, 5], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_fail_4() { let ds = &[3, 4, 5]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_divide_and_conquer() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); assert_eq!( limbs_div_divide_and_conquer(&mut qs, ns, ds, d_inv), q_highest ); assert_eq!(qs, qs_out); verify_limbs_div(qs_in, ns, ds, q_highest, &qs); }; { // - *scratch_2_head != 0 test( &[10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], false, &[4294967057, 15, 18, 10], ); // - *scratch_2_head == 0 // - !(highest_q && limbs_slice_add_same_length_in_place_left(&mut scratch_init[q_len..], // ds) || limbs_cmp_same_length(scratch_init, ns) == Greater) test( &[10; 3], &[0; 9], &[0, 0, 0, 0, 0, 0x80000000], false, &[0, 0, 0], ); test( &[10; 3], &[0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 0, 0x80000000], false, &[0, 0, 2], ); // - highest_q && limbs_slice_add_same_length_in_place_left(&mut scratch_init[q_len..], ds) // || limbs_cmp_same_length(scratch_init, ns) == Greater test( &[10; 3], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], &[0, 0, 0, 1, 0, 0, 0, 0x80000000], false, &[1, 0, 0], ); } } #[test] #[should_panic] fn limbs_div_divide_and_conquer_fail_1() { let ds = &[3, 4, 5, 6, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer(&mut [10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_fail_2() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer(&mut [10; 4], &[1, 2, 3, 4, 5, 6, 7, 8], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_fail_3() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer(&mut [10, 10], &[1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_fail_4() { let ds = &[3, 4, 5, 6, 7, 8]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer(&mut [10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } fn verify_limbs_div_approx( qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns_in); let d = Natural::from_limbs_asc(ds); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns_in.len() - ds.len(); let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); let q_is_one_too_large = q != expected_q; if q_is_one_too_large { assert_eq!(q, expected_q + Natural::ONE); assert_eq!((q - Natural::ONE) * &d + expected_r, n); } else { assert_eq!(q * &d + expected_r, n); } assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); } #[test] fn test_limbs_div_barrett() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; assert_eq!(limbs_div_barrett(&mut qs, ns, ds, &mut scratch), q_highest); assert_eq!(qs, qs_out); verify_limbs_div(qs_in, ns, ds, q_highest, &qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len < d_len // - ghost_limb // - *scratch_2_head <= 6 // - !highest_q third time // - !(highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..], ds) || // limbs_cmp_same_length(&mut rs, ns) == Greater) test(&[10; 3], &[1, 2, 3], &[0, 0x80000000], false, &[6, 10, 10]); test(&[10; 3], &[1, 2, 3], &[3, 0x80000000], false, &[6, 10, 10]); // - q_len >= d_len // - !highest_q first time // - !_limbs_div_barrett_approx(&mut scratch_2, &mut rs, ds, scratch) // - *scratch_2_head > 4 test( &[10; 3], &[1, 2, 3, 4], &[0, 0x80000000], false, &[6, 8, 10], ); test( &[10; 3], &[1, 2, 3, 4], &[3, 0x80000000], false, &[5, 8, 10], ); // - *scratch_2_head > 6 test(&[10; 3], &[0, 0, 1], &[0, 0x80000001], false, &[1, 10, 10]); // - !ghost_limb test( &[10; 3], &[0, 0, 0, 0], &[0, 0, 0x80000000], false, &[0, 10, 10], ); // - highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..], ds) || // limbs_cmp_same_length(&mut rs, ns) == Greater // - !limbs_sub_limb_to_out(qs, &tp[1..q_len + 1], 1) second time test(&[10; 3], &[0, 0, 1], &[1, 0x80000000], false, &[1, 10, 10]); // - *scratch_2_head <= 4 // - !highest_q second time // - !(highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..d_len], ds) || // limbs_cmp_same_length(&rs[..n_len], ns) == Greater) test( &[10; 3], &[0, 0, 0, 0], &[0, 0x80000000], false, &[0, 0, 10], ); // - highest_q && limbs_slice_add_same_length_in_place_left(&mut rs[q_len..d_len], ds) || // limbs_cmp_same_length(&rs[..n_len], ns) == Greater // - !limbs_sub_limb_to_out(qs, &tp[1..q_len + 1], 1) first time test( &[10; 3], &[0, 0, 1, 0], &[1, 0x80000000], false, &[1, 0, 10], ); // - highest_q first time test( &[10; 337], &[ 2119562458, 822658147, 3797927043, 3236945010, 3998585665, 1799547707, 694717600, 81695911, 596552600, 1030767834, 2420116557, 2879241862, 4265568378, 644932084, 525117944, 1830433723, 3385005819, 1023897437, 3938627008, 3218345466, 471356423, 1008605584, 192751188, 2084112099, 2804133613, 3079231960, 3746102582, 3887941757, 2403297368, 3093735039, 2439864684, 2473555841, 2532233722, 2609655906, 3449112520, 2817574574, 1129609143, 821518979, 991339292, 2760112178, 890698714, 990807460, 2521797827, 3797612523, 1500537907, 3973412117, 2699035435, 2317986252, 2861160946, 2101011897, 1732640676, 3352339942, 3286471253, 1371519955, 1379608062, 2699834414, 3261360638, 226259522, 1897478770, 2788528264, 2309134747, 4024965405, 3976506219, 1035727997, 3131955545, 3667438412, 384232858, 2419576220, 793788636, 334784748, 3765760253, 1098631674, 1499085537, 2112219622, 1421552393, 1432628811, 643517209, 3632058889, 1632079643, 2223695587, 1476932543, 1960156116, 3436427017, 2201635037, 3182693886, 1548942116, 3157649082, 980646399, 831953531, 2763454966, 3961226196, 3582012549, 3882861773, 3003921500, 1404369615, 4000431109, 969558169, 660750652, 4122382799, 2357249946, 3678033512, 1327191217, 2116553842, 22168676, 1216607516, 2222670817, 4212062746, 3066154963, 4179712741, 406795945, 2599414815, 3647640166, 4071465241, 883313541, 1105574450, 866562291, 372730105, 970111908, 749995626, 1253456197, 2374658843, 3555086224, 3636919504, 488985805, 2204950393, 1262942086, 3204402881, 4275635994, 2310416697, 4135349793, 1226698657, 1188086923, 3222723934, 1042266586, 4047620517, 3948968819, 4123810886, 1610456917, 556933362, 4197028761, 59668868, 2993790244, 854419727, 933448524, 897309660, 3037260848, 1562257062, 4083457628, 981822256, 295330752, 3711901403, 1052560139, 3617703336, 262191843, 1142114318, 3848091155, 2086394563, 469188180, 3855914481, 154128290, 2738524940, 1460255288, 1285831461, 534017408, 3101261674, 118239159, 1944080872, 4203935546, 2653496603, 3202103001, 4264655348, 3809947358, 331166910, 4277075817, 1031408102, 866321189, 356095977, 1058770275, 3617580770, 2573338110, 1315597113, 1752964646, 2179362239, 2449996072, 1745253117, 85067425, 347176893, 240744367, 123940072, 3568364276, 1405760257, 2210945376, 2261469245, 2772215200, 746282058, 568635214, 1171903297, 1744293446, 1789334502, 1459265780, 2293069614, 319891368, 1979148180, 627405437, 1184813190, 3346831763, 1106015952, 940476403, 1182911489, 1469568725, 2364938114, 1157432499, 2372887700, 1043172544, 2250011461, 2085295087, 604304964, 340825308, 2422766482, 2410385883, 791761071, 2733359762, 1681282344, 1354240087, 1139722734, 1143256298, 2677141676, 664248460, 1670722978, 3073187653, 4102786625, 2618886769, 2531436405, 3579964409, 3950031759, 2248680433, 984112565, 3136159147, 3101912984, 1099692243, 2145841930, 1116532125, 4172191260, 1659871196, 1924994861, 3162922129, 2658827997, 1059354695, 486907692, 3395508395, 295826664, 2173667478, 3774792204, 1393285442, 1481797518, 3124974926, 3444355559, 76091140, 368283108, 4144769582, 1548649424, 2500545816, 2934156349, 324366676, 3648212298, 4072218004, 2165091138, 1096979546, 1763071718, 1899235026, 803276905, 1146994263, 2575402634, 2199211565, 757588391, 2673498553, 81023164, 439773287, 3406088797, 2333068608, 4043446581, 360179846, 2767375326, 69621430, 1199860390, 2642727874, 2693185292, 3218919242, 2999720961, 1196125438, 1368472471, 992806312, 3414591657, 1991386017, 1806201055, 3597622657, 998040031, 901561537, 3420061213, 1598740651, 3883097859, 2560593523, 2144383095, 2844056757, 689661366, 4046234614, 792024425, 2086938139, 1867234422, 1449908164, 4144743168, 1158803667, 2979094734, 1636380917, 2507967837, 1146823800, 4089295245, 3701313701, 3893526214, 1323911033, 3620380011, 3952758387, 3265334125, 2820495010, 2855022691, 1720959672, 825537074, 1695132633, 4264601047, 3483737293, 3618271080, 2259345874, 806986786, 3597560543, 3609564742, 3752395175, 1910432839, 2910423130, 2748643710, 2345098346, 3595323045, 1619954943, 4250836093, 2316914206, 3801483715, 3657868704, ], &[ 3231068322, 2952358964, 2649323214, 3829109446, 3277451762, 1929830117, 128637820, 2648688236, 3506019657, ], true, &[ 1863226650, 1957700928, 2397867988, 3361691958, 4165763036, 2541448103, 3330236317, 390820454, 3199800095, 1741385769, 489727642, 3156882136, 3364833247, 2137995472, 49695877, 3008476841, 2862420416, 3492919918, 3413332847, 336822005, 1172092721, 3834063622, 387233639, 4033191572, 825059607, 1739762995, 2020314499, 3839219267, 693092469, 33950982, 1177221008, 3244207164, 2680526838, 4242912184, 2481840017, 3724363464, 1448349630, 2835676977, 2435088559, 2020244573, 2206043073, 1215858002, 3357751071, 3401291562, 3486448975, 1614914078, 3741841610, 3754003433, 545275396, 696866963, 2296823190, 2173589284, 3887309169, 2170555018, 2354335949, 1942858008, 2275759948, 238261999, 3409767723, 4050603972, 3841360830, 479906857, 3816482700, 3132890483, 1442647186, 2664711624, 3255895001, 2304652118, 490441941, 1384930190, 3781000441, 1197124175, 3673914796, 3264625683, 2934430644, 4012652010, 645313445, 1342417027, 4259899126, 127557767, 1863840635, 4240034833, 3380128902, 1721040466, 258484486, 2943320471, 4080044726, 1184529896, 50392490, 99485071, 2656469171, 394602583, 3236432821, 829680970, 4180640632, 216345893, 794871810, 776950374, 188852287, 2768051863, 1478264409, 3116222344, 2035264630, 3540143745, 3312627463, 1243839690, 4283661964, 2255627632, 2493155473, 3422881207, 672998229, 1330645402, 805858947, 3157155303, 2449760637, 541100830, 3959355989, 2578797546, 1805505456, 1105314669, 4044058628, 3236890928, 2881753558, 2935150784, 3619155497, 1247576722, 1057473446, 2602148123, 2591947096, 3098219463, 203480759, 3190196698, 1560456418, 1737612953, 1525519966, 1833713546, 2974486003, 3554849856, 1570515568, 3538788251, 3534319124, 3133957142, 2947537950, 1328568927, 2472554746, 3121690099, 3058658055, 2512921696, 4268236616, 507933028, 1384977378, 2914276309, 2170658818, 2676773599, 1344588011, 1406282402, 4240165134, 1774763910, 3592097532, 323634811, 4493032, 2026844160, 4259889667, 1561456992, 1745963453, 3318810240, 2613669069, 3295340381, 3322882413, 1172726818, 2542871057, 889925562, 2512140586, 1002695611, 3804029809, 510918143, 2428502323, 1435737298, 2312478558, 800761403, 822185524, 2215463403, 2284293602, 1855687935, 3929793519, 3135842877, 397151223, 819010071, 3143846345, 616813752, 2964423320, 2479441994, 2399498982, 3731231486, 1268178985, 637959829, 1437260196, 1762640607, 2763892037, 3152346415, 130897174, 150170711, 3043757213, 3263747790, 2268840104, 3897286925, 539186347, 2052996062, 427292218, 4071153750, 2387542695, 1403176825, 3054171069, 612471588, 1215312135, 1616958897, 1846418285, 1376844475, 1228696609, 534770698, 3860539144, 3746082038, 3223899771, 2595640187, 243793487, 698835349, 2226712063, 4113186925, 2899418198, 1544475879, 1323263527, 3387040179, 3921953055, 1816962743, 3835265005, 512922592, 4131079192, 3966796549, 586497526, 3324562547, 4163601002, 2280208374, 1649440850, 2888163653, 1932515002, 2915989787, 1835707588, 661236253, 1521623480, 1468090177, 62176243, 1761654778, 654002630, 3078945097, 2118465419, 622606572, 1872263161, 371147127, 2407796135, 1691024627, 1530874911, 2999266525, 3959644478, 2593752318, 673127524, 2516817005, 1435234490, 2950535738, 3814456529, 2728341971, 1618690437, 2649703585, 1797683058, 2532611783, 3170196918, 1687541847, 3276477161, 3728293877, 1601226381, 2623169918, 4277737387, 972038484, 3652503133, 1692819095, 4166924696, 679045210, 2147824742, 1754890006, 3603422769, 760272390, 2805004613, 1482946566, 2730421710, 638284193, 1248071107, 1757322486, 2253794113, 446496343, 3072090920, 2265361578, 1244157949, 703538048, 36778122, 2938030723, 4284977264, 1670946207, 3674544567, 3705855800, 1533888849, 2783879966, 1509595576, 2692068678, 4286514245, 931483302, 2846849819, 3750140783, 1937245748, 1537653123, 482103265, 2110925496, 3832643610, 1721135933, 1078480349, 2178800517, 768852883, 1630173117, 854612116, 4050668505, 3460165548, 3293238206, 4141790935, 764767464, 3763613607, 3433771841, 2639622, 654168294, 186019120, ], ); // - highest_q third time test( &[10; 37], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4261412864, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967168, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3621246934, ], true, &[ 2097542169, 2497074010, 3595786574, 3396020653, 699180723, 799063684, 1, 2097542169, 2497074010, 3595786574, 3396020653, 699180723, 799063684, 1, 2097542169, 2497074010, 3595786574, 3396020653, 699180723, 799063684, 1, 2097542169, 2497074010, 3595786574, 3396020653, 699180723, 799063684, 1, 2097542169, 2497074010, 3595786574, 3396020653, 699180723, 799063684, 10, 10, 10, ], ); // - limbs_sub_greater_to_out 2 in limbs_div_barrett test( &[10; 69], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967288, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 8191, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4261412864, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], ); // - !limbs_div_barrett_approx test( &[10; 8], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[0, 0, 0, 0, 0, 0, 0, 2147483648], true, &[u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 3], &[0, 0, 1], &[0, 0x8000000000000001], false, &[1, 10, 10], ); test( &[10; 1201], &[ 18295077001300582982, 11318972173113518719, 9127519662193085094, 11186232593046463828, 9967574749124910412, 9534668194866541873, 17538998692236597692, 8856351994537314708, 15915919282507021309, 4395337101052053871, 4573109461445904651, 7471333999959771232, 15168214583465292846, 10112694665499997517, 7468171880957946669, 6921645588354592946, 13601816639536924709, 15354213944627759328, 2741837546898925109, 2808068836502997863, 11740258706413798883, 12018890889885101893, 14950676973818139848, 11571325165054093751, 15673140488076698056, 111792651078725003, 8462112369261970769, 3506632968581684254, 14492060158927869608, 9683679100633315103, 8518299955708236612, 4652093220482746517, 7043533562034634565, 12167203625017475462, 7117384414390535484, 3466429710589950813, 17042769017553443224, 9042817094280175152, 16844111334058787904, 3229027329268312555, 13434137902318146452, 10307081978533698950, 16225670675216025408, 2520628227212852899, 18240849581864299900, 1488578585703911609, 12729292459179553524, 10245967895896970359, 13339552018102535488, 3997937496978780356, 7658709074265624500, 1435708185782215934, 6431277357886612239, 3790371881169902395, 6784416241349450757, 17724596047816212568, 11815611058096852874, 18130171813954955659, 1024780128434872289, 17963095905370618004, 122805984702922462, 4151944930379965325, 17442615003616391312, 4994655809588385430, 3040428539445301559, 17832402824141992191, 10165853977855724270, 2335376537564192245, 16821936144912130606, 1159886974868740222, 12541069017485894294, 7837219358605440583, 16446400756537961003, 126465459086606815, 2083531762113796389, 8624382957529422405, 11784929789278735279, 11213379749377196194, 560319428396345164, 15149217973310924334, 15463814793141030032, 198092507050200273, 8610639264260168818, 261903620794761859, 11988086720959071107, 17592070826426022758, 3768394046587852857, 17166555261248835248, 14963038520790234947, 2241578438524899796, 12189060128627683066, 2262926845306353696, 13779828760616581286, 2541235484167862316, 12643925053624024515, 17496648690832865541, 3985970119983125736, 3095952870801231592, 11840830080834210856, 1592987240002085723, 10982564110995200636, 4643989547154306181, 10428500092848201987, 6198871498072261125, 7023308239893005307, 1842762842799324585, 14071338712339983613, 226982182212975753, 10132117640523152816, 13755737565472281731, 11632719781566051232, 15601465236759733965, 7426599477609205946, 4611356292343480284, 8631478323050143434, 11591955075248152245, 14677238670216581539, 8164238761098476942, 13987621157141456718, 3767319467475575547, 12012052271989395919, 8337005502962563778, 1906268936538377685, 3174524835537599456, 429665364769606677, 4394657478224842134, 13121187501762162553, 14381551623920212050, 8629282374304273880, 13263190906733112908, 5218608522481599043, 12107632235830044399, 17543485324435588445, 5588590375237119557, 653390775866146799, 17771172514225072483, 7528918736871248090, 282399778929005580, 2605980929215962661, 12146324033914854229, 11592565716384131105, 18151666657326444699, 4388203927026263831, 7341614458621896439, 8894653933329611005, 13805725287465815477, 1961833582231565395, 7660480270814575592, 7471493328104234933, 15044319201246839910, 4576661672063304734, 13536449736957685091, 11860387989360659066, 14764867249962166936, 13360409447124464240, 14221155626952092001, 17398349115650451905, 3184465599333245836, 15707751954179380044, 12562479861627119924, 88057213942976, 1597598702141447884, 1261772823635792000, 15958552215247247021, 12793055150726238784, 11200918639832307722, 5597941261295916139, 4315031833738259815, 6902838082588292746, 12728989104884069511, 16918323087316778932, 13511521151542209585, 553843237172766561, 5043573603672626571, 17723320900855236842, 9608995393314215645, 3240943499004890750, 2656790654801382241, 1676457890700011962, 1762227695284006379, 7552785576552937293, 12811313200785996585, 9898873674914761859, 17367249174383145486, 6558113706220556681, 13049161836673606453, 518571717053573108, 15162122533925516408, 11258823008709425295, 2435504881057972054, 14963790284869753122, 17872120991620222840, 829886456078946400, 3111042046099960191, 12008856441265505258, 2885441178087651466, 13689155834809427488, 1131420088641124682, 4614200008200617537, 6047126292996169487, 10306766196213210408, 15363972403137500863, 4835120368572137311, 6423191714064598283, 13652834984059479335, 16393177507860580647, 235892475830229813, 6409760052867575115, 1550734354829621988, 13575662851619075640, 718363601454148431, 7618105344726885101, 13870052170163128170, 17099086237059090191, 9396086948840999204, 2193052566012551739, 10987190533735767295, 15342771743918665873, 1551527591660837277, 2481113648650332471, 12526575541699553066, 17267384064568181119, 17289295549595612856, 2664460126537239716, 6877918636888277820, 16082383248389501517, 14351409001844089162, 8263128092015238423, 17346851708062879652, 311521651703256488, 3981059575604853696, 6313669348188551640, 18099378411031449694, 15968996741727654128, 9159799405918354972, 9462164989236485935, 3684393721233135450, 17937865489600192328, 1638517822102130933, 17395422161525252689, 3473709908567621234, 9193281964841491478, 10331967326496158302, 16798696233976578557, 7807831077297910192, 12652762876222409301, 4869797982244064640, 17701222287597080443, 14198439585207683091, 15865499320981581597, 10334047464234401983, 3015211655799314399, 2424108494719176484, 5856301803897821467, 6554732345079263181, 15122890791522644819, 10545203438810108056, 9012473640708669972, 1610970557833154315, 16035943676789150718, 2896323099257548494, 15155422639005018579, 2259843538120092351, 10245098502137432793, 2520646283097234470, 18012393436345512168, 7561203372316264305, 7653799543413918665, 2140030530743770178, 9857665885574564324, 7489977190124210547, 9998927813057387755, 2762046115540595154, 13701876953526406973, 9166149367362906555, 15040003763080700518, 15420365130894777610, 2514077990148227892, 8504504167644069065, 17726177341910187592, 2449744483621879771, 1723730756025983988, 14406403103456534844, 1454650873709405887, 18385141654478933772, 5577491305370650404, 4566210906549652321, 12646617965385778707, 2552078226205003325, 12355063666203300427, 12178902896368926706, 15006718947903716117, 16372728326443816683, 10180279671730724459, 17731483716821982507, 17200000119948045535, 16335525811156407438, 6875979274642807833, 15168986439371917908, 15864186564710033224, 8479084522424050164, 15994651879769538679, 17760497144399786164, 18426614975808400224, 14704575934872194992, 15181888226941380306, 11721908889511702187, 102617178928138881, 7447495721105104237, 7954810306378822535, 16998786374321127605, 8090790070484230870, 16289196329372215488, 7526820476636601578, 12572297496289928774, 113628864092045691, 6250550022217214406, 4360142915129731393, 6501796933114606792, 11802403139188476967, 3519002220471562974, 12904839411442007974, 17836996140509983390, 10274485582719436243, 1702862600039034598, 14513867867040307158, 7487625572871740440, 547811069452644988, 14936715197880499253, 13562114970675542784, 17390100354796730187, 2650648508100345126, 2284358746933974591, 15679445219134526756, 10812943946121458631, 3086162675176072976, 18390684768949838073, 6075230822143172142, 6982548968812756053, 10592236207809317452, 4646507818793863055, 12915347565287279717, 13659140852008443728, 3573929783088736212, 8525440095045701760, 744607937041376677, 14783015896444558651, 15131086952103884713, 5411002486960761278, 2088437290856887643, 17144271151733343032, 13301554666552663294, 7896467561063988444, 18211131252066266807, 18314706540585938015, 10366120178981009524, 17459923192069900601, 4447456409081943565, 18283667669702090783, 9450771365947353345, 4378436544916016463, 18212457741993594328, 15198669923619110391, 1879444567544117559, 13563147379710886746, 7674325133378880705, 3334816774600195478, 17381122289894552650, 8606404348019304750, 11293315989134833536, 9316500947082049857, 1266335121593205314, 13354728313128860089, 16404400110998945357, 12189461827482124995, 8571799438986557328, 16924412540155584500, 4066705394775144307, 8244708734889461660, 8298262041269740098, 8485079550935558613, 10390420936585250554, 8032986327114538781, 16386580215630153737, 1596782152296894307, 11436174552386854673, 12281350017506362626, 1201023713565731644, 11354800184560792809, 6244435089778753535, 14781899671263994812, 13453856532164887543, 5205173379729650294, 6758121452061198317, 15199577981158799457, 5097188591555664044, 17892257447678225776, 13090788927117929247, 14729055239625004209, 4325309995714780542, 13696424036200737757, 1273472536475971315, 2493602685304131114, 14343892393575517386, 17316017497393506890, 7414572135952091508, 14030461927641410000, 5832918032885817891, 5502576889680878828, 6923748617342471812, 871116026416752255, 10966491112110866938, 2678875367438552346, 880767707416234664, 13418969124074860064, 14901114133194346006, 13532936137684711970, 13210870719065554599, 5680454822125667478, 18160829213663155836, 371611573974742026, 5989253166049701849, 14180420379914515920, 15377609392846358665, 4353627738587754452, 3173054206132556029, 7895498175890703618, 3080756330636658459, 3760068566220710837, 6677805614130848551, 15143994173468972043, 2776883010742953966, 7672039583834722626, 14012333824083176377, 7996303528193834674, 11897965609914054208, 5088662930442171136, 9775050840076636067, 155290985412698044, 7446050331902513644, 3182373073764824464, 6333622418059827492, 3381171406223616986, 6279035658057293263, 12457015290254566192, 9997746010079880598, 6365931066892340107, 985007383843617635, 17683099066034169719, 11690122858292360173, 12820337681274901203, 10119776165009632402, 8025360517304244421, 5799209647953164975, 11923243886776383739, 4434382877035266302, 6892316876790904772, 13311686201719400688, 13070055340969362249, 1389161348064595575, 17317825074198166229, 12352407812302110965, 4357096373749880928, 15322947805519342504, 3393459926528754710, 309259942348373780, 15221863408129710293, 2184432377148992552, 5599867762682684625, 11692237690560353533, 15617277716526144374, 16352998506828635464, 10683295287531537932, 10174768335502056341, 9757436149722611038, 2152351494881547919, 3149777722784977852, 8102543602996006449, 11216609622075916890, 3579652612346447740, 16460137215641926135, 11507203873319504418, 16154205860053489440, 2632057472745483271, 17753479868310580515, 14766406055562904631, 8264678782999986871, 17190366735089617123, 14132490063308838582, 5611885333274300040, 7809615541777044817, 500715652367171775, 9987493264173996320, 841374560193562207, 6977580041132397357, 15755392832835879990, 2396663158056304844, 6954661831316013111, 17813876156953598887, 8398019579977679371, 15855357483987489279, 3812760582326753081, 17273631953943528844, 9938856188329661065, 15819226062126522823, 15903684874086185036, 17013855101741324873, 16945130082273335779, 12554320244359036189, 13649309719081627643, 8623047233379225403, 4386984048641888911, 10553868952837364802, 2287715920316141389, 5449632814028619034, 14866255022956570263, 11741122206403462638, 16053480635563219127, 5950910649550286503, 15674410143609173241, 18052239445521828504, 17771738773780736596, 7982624156303669042, 3523750006668789187, 11709430973580071492, 2896965446277645340, 8080432872087262526, 6780281993621524078, 684058261883760969, 15989257244423388836, 11589699367052272611, 10104208263881413964, 17189453506869451477, 13916361665060626203, 2853202431249762367, 17209296028258297770, 8683507465402308661, 9645802663683152169, 10358479223375842731, 7829663615722911275, 16814895244990924256, 9450557997282764467, 975077777946948005, 9552034374331587062, 16463119689405074774, 17510823549036664049, 2497156003024501849, 8569401863532688038, 10049279418614386291, 3587742668108530158, 6893073803871002466, 8435788430991711447, 6027317537544203617, 7287819136806388073, 8022714784833611325, 7097275444704143170, 9012025202589703553, 9157332853571289532, 1993744974767457280, 1465502656822405877, 9131312205000720858, 10325876690137477079, 6169134302635077705, 8374996558291634468, 560822697555683025, 1908237605140107852, 3071760787762132773, 5175055607701420190, 16301592270910662010, 13309210291635015714, 17042047666169332328, 9526937776970478108, 12098704706218455302, 13970362276996674357, 6796229436389522906, 15062885882848544518, 16920623441880575261, 14229647915216500624, 8741798560844117715, 4980134414764225717, 11277891936160048605, 8669128257761758831, 11639866248680237811, 14320586036388102785, 8445229725159674642, 3733656198588769556, 2734841737258647101, 3180524601127048731, 2450617332784964412, 11426278631729088077, 6103545629653703721, 16596235424879528709, 3083400506423704996, 3326973352265933113, 8829291997519615573, 10934832120864112438, 2237208881368262020, 5487788679486358745, 6433752820775880003, 17592485008402930155, 897116185036299103, 4177675527876951143, 8991005262989032861, 12499756317966457681, 8950539096741137700, 2847881219307650887, 15077888665364050191, 18223594192550309314, 13486903824928920160, 388063271439952358, 10319980883121211184, 7635019531196725850, 2427615724424514210, 7729266079341799689, 6404444267730632702, 5433617192107305037, 4076855819327886411, 13570092861836669774, 17637230595629666135, 3763591644356069904, 16581684393851086944, 12542913026947120792, 900710323095653438, 10736895612395941051, 2621023630214846484, 7378502763289664634, 13474732295031584723, 3104494731822189089, 8271151412175201324, 12279765059279079874, 6577258368503226128, 6763279491725722121, 11416038652636887266, 13192060800396327604, 16237708051063768614, 7089146474910269889, 15563073315367269087, 3957364145608674590, 5323058129820270810, 4109735477541683587, 12355852476209988798, 15985687144714610011, 12621726154507263107, 14640375261881059191, 16363974953655857698, 4850702814848069062, 15272503445030894973, 16921342410168262313, 7428955369032396232, 14045654759586398366, 1824179654748832763, 13065290435644832773, 6620750261665502627, 3710427655103863956, 1481622391321253962, 15738776155042427147, 5393243462308065801, 2548893674570156490, 15446175308782730745, 13099052830471814150, 16025011191599670127, 2890048025568963952, 15911511151530752849, 13361640240769822063, 12104304782171432594, 961887753450176109, 15685615589765989640, 17189497989928671280, 2831942924382855480, 4480390308058866189, 15123214478066113546, 5319876220060588766, 7554565254690703099, 15333258353184365603, 11213391410117524311, 15593488040195587753, 593648809612765970, 12555350446961062819, 6229267335263745809, 14015166800911232090, 13026142996056874252, 18183116121398427318, 15181376709750626113, 1401960981421676957, 4293598990318865637, 530920581688032599, 6940659528892404741, 16442234548874017487, 11187943673940954369, 5477084646686373295, 6381208324537451874, 8061144699238466390, 8077766508626903071, 6753688433578836015, 15372709739771454415, 14767218468779016882, 1215884787035963826, 14382870766506391926, 2777669072491465441, 4979926579396211735, 1768278590436478191, 15494549597590347998, 13355843170158138770, 9534590495526626915, 11105540785007109613, 14720148350689650025, 6017193011436405301, 16984479834548076496, 16271637870678307585, 12326183850782128718, 6046566507616322174, 10855966808284447862, 14486143464576348956, 11338497252460063850, 5183772359646668332, 18243138296691918952, 13528809746451616015, 14990329438970768590, 5382414247629766136, 17839632985912233567, 6536591723065785846, 15159440725656239912, 13722780980393210799, 15379786009638462213, 13680360627088226980, 157894015409385528, 5177681992682638634, 17291176910176600814, 13010475027988538353, 1220715812992048990, 3158791389064101642, 17418153569888323944, 14192277962237157065, 13201221044060083557, 17197741701763036713, 1169866928588403159, 11475502076729221523, 17842351657425532858, 8719597950895866531, 13655118154496174216, 9324866581514290928, 6471362086641457443, 1120540713350762121, 17250869044224608119, 10278304262960546351, 830716653181086159, 528668968156165816, 17461167627153646098, 2954445364658355279, 4279374933577208791, 5125629313701256673, 13688234303349159556, 6162791048326647760, 4085886762736458043, 12797243781587979166, 4186645783941093387, 5286754311331113809, 12228267120751123127, 13244227501124911724, 5790695027871396694, 1179783746683833033, 547187269099730162, 3784522572642818792, 18032448183921975913, 12457662158631096805, 15315319400702151227, 17578423625750785029, 16343351208792817827, 12441408408284563210, 7954314853731713656, 2984276352836570732, 13395574438985641870, 2307482872375012455, 12980078936529177252, 10700284809642803759, 13865447514364266827, 18230467246784513159, 10014640149449599139, 5878477546561163101, 4136028674985152176, 13271285149376627150, 16149599021017368823, 12810144100834492972, 10361575929298677228, 2536873008009811981, 10725873242024230485, 6497018066462413733, 12672985826259352756, 12621580784482696405, 3208673605123299314, 12964686779683735787, 11198928388252299700, 9267110518317968851, 14949846318732066452, 9541744713692425692, 15941076237518505589, 3430239862814579319, 10612575443053695979, 13849997225041110710, 10812240591348788214, 6393517327149796800, 3773291149649696828, 11772973342821893348, 15336626839762886687, 9577966728657848673, 12885121901356197298, 17815545299295776530, 6220765473251078270, 2771097797711300301, 16970067356480780400, 1504708658327185321, 6907611344237613843, 4075093039543471236, 13083035552238343340, 14250200630765174185, 9672767310783428470, 11849400399424996986, 7035900738271398225, 16082635402379245761, 16050998072774064345, 12233157773887550741, 9123081242185639205, 10491848564263417153, 8146725764960278312, 15575340461645603858, 4148874142333973054, 2993956721277198006, 7451409165297669404, 11313922544892113187, 3194232630201899744, 636408375757237004, 13608592959958520180, 1602275071834536905, 17095805362986103383, 273804608848916383, 7791458085242420416, 4108672307826744184, 15366005913747176151, 1911777325643792089, 7650198163620616024, 5464577924945397455, 11373225807219821179, 11803062818149301122, 16590458695267155990, 5042461121399527303, 17546193017727636334, 6044754748618261501, 18027283631246224402, 5490643452609947204, 10676364643909038013, 11630248788877483715, 13656452259036871197, 10354144198163268775, 15527017933877727076, 7934356641322781866, 4029898516517466246, 18052926818605623623, 3540286841764757111, 4634551231653920631, 14122057670778455103, 6502701997202257971, 6891458055552018817, 15456790929915692095, 4755257324171297175, 16716123507389519228, 3651613652886160497, 726970425978162241, 1404697533390673853, 18337661318309196519, 11286275631912876508, 16956255978892411559, 7232996886210695519, 7015333597196144681, 2767625396637754039, 5012454424073998044, 4313194875364346824, 10862594252285252036, 1780047608637690763, 6465610838655107636, 14797199105868765000, 14892726918517585944, 12886955176299933454, 12555896806127357876, 1579402751470265132, 10039610188105182645, 13021770347030669513, 13884058132948290753, 6203460449771372271, 17680930315624648890, 1135636070221202481, 5887167508778361325, 6692888760348109187, 16471454437283076325, 6790413570336457138, 4747413456280934549, 12256524938413768175, 15683900003187016699, 7658943070244016799, 9373611225821015637, 3097782436024673554, 3715948327301456793, 16620556575387636951, 1144786186914086248, 2571220709130887133, 17221925829597224845, 14639715549529666265, 2377686026891085475, 6175736503910047094, 16254346102373555209, 2091619280012452304, 2977400894759148074, 16973091263321852037, 18362768537728015363, 1991299393262221799, 2234896163405550283, 18058593386109307972, 10550027282767151380, 16780239965370137213, 799009131584013840, 10449833190601914997, 5403901802819318335, 3399172224735334606, 2288410999716774322, 5500021116082973302, 4679603412526091068, 17393554539674064705, 9796061166459144993, 9467440242924277380, 11232005203975958356, 5489824429056622584, 16693157940463512280, 15406446911191459754, 4194365386979719807, 5203380675405663527, 4845608829713153827, 12287647978288669912, 15124365454705698450, 13535980942912919723, 8131237757227102165, 3174196792035455626, 5866637449648808112, 16572436768235757709, 4014543717417567164, 10648229607518736806, 11124454154979311706, 1769806716148969845, 487436280093944655, 8499791320565867237, 15961111617996045786, 5068322564632937925, 15412395235178437129, 11967627266106331118, 8045493101565796203, 13046639311331048399, 15060301207111006451, 14565561077561594206, 4358177937116176854, 11754827048597359847, 13428566207941409974, 4886280109612433539, 1622891182969078648, 5631762445567547687, 1001237725533401134, 1757759663273866730, 16057243644130790443, 1499729696211089292, 11828414361895128981, 14654309635396524180, 11291463832641202452, 14519357404633231926, 10577140847149996567, 3792719835563443387, 15142788729413823525, 9678889469185452465, 8297094875949379007, 15382627216272468711, 15925819828335300195, 14660243428068176769, 6234311288201569973, 3098696262152872404, 16414024924130435474, 7632710397177488243, 3027219954282024629, 13613605315723845518, 4728284780117539918, 1526596142713039913, 13362185372491310310, 3646060091216202899, 7134750524336139051, 10748226811567148106, 6061127651723295538, 1977080743741376721, 8247273669544854710, 11303352485877072729, 3212027501425168508, 3372242849830936750, 15122856257096582829, 3657320729410695570, 1079822070530945640, 3637761676173672044, 12937343848915788544, 14571852791540951516, 14342466430585531102, 11728929959200744262, 9616215636394561656, 11219596255947364400, 8537080980244641448, 5536712989388435927, 3631171822217372772, 17865529156187152852, 5037311271195656389, 16487502805572224194, 2147708277645688540, 5001570498819337775, 7470084541514784017, 17492697990745102157, 8070931416656058009, 6060950086595339669, 15013400715742283111, 2306746444225502304, 8409359804202256945, 164372999763571994, 17018131853777354259, 12208035939150177086, 15378350496540915492, 14788480835646558098, 10222082122641529550, 9826197618153251703, 11243600916118905460, 11580887407889731032, 1393539571585322510, 9935346143997187837, 7496342550492044399, 13651431762540088188, 18099050770585698965, 7529498299621559528, 15208919353243962747, 3726212045576545652, 4678887453978995265, 14257385919526698171, 12560466975991464998, 1916602273852958082, 1580725334554883931, 4225567785880728522, 11435782961353548865, 9711420123575671266, 12525556123102287402, 2646005433774867481, 13608235394975640398, 13551601168317309842, 16238098975271138187, 6304934077364865470, 9171945380172233284, 12494391509484808505, 8265808003325748972, 4965580429357067406, 2338192348119283399, 1178551921476923378, 17792386313089099560, 9283481247039557200, 18034555261167084807, 940432788242421418, 157287264000433134, 8930392502298325360, 14945125834809509178, 12014926331118784945, 16300522776195850517, 3339639261621971347, 11241360985958214479, 16436926344603140983, 10678188202681436261, 15790390608679380109, 3932414003149456454, 5930062229915467643, 4450937096561861235, 6454095283937419925, 9191309540370341069, 2369208882454404157, 12058336702238473519, 6689133296485718676, 10352121632476532849, 3457908119433474049, 8564209740315103396, 4484492680807237072, 6272029608511724469, 14111360500805747905, 3426639800371632037, 9193459114578112726, 7715081428105427735, 11741225476850793322, 5763876427542620399, 10485104516843146360, 13517901123362979253, 10971040515178626597, 10880433648809156464, 10463748994258517642, 6039895771661000246, 18291078422235189340, 13108581522989000527, 15970781344230536695, 14450809554308819328, 16634698737197679715, 10907837400337288081, 4981117528505172335, 6575031804504949146, 7418118826254061112, 5934085700009751031, 6506575199869110637, 6840822251681248761, 11392304369263274998, 5878363293290930458, 3935353596127878330, 13113298309412464813, 13481516285263684897, 9985427214718546766, 6516008243224711903, 7181072207395196982, 3447347579103428171, 7443665624167886719, 12843482800554270558, 1283805457628563062, 17578575987130403567, 8648960510881174810, 16654535114846652064, 16246000708166950031, 9421890536303267950, 2811797585537180207, 5221682992061150871, 8701033693885846524, 510866220487737298, 11014183458125585795, 7331136142244744171, 13347933694384243576, 2971027367826241163, 16895278402964612481, 10343481409259870382, 7637469477289176903, 14515774696379459873, 10726339387643525816, 788506778946106429, 2659740016403876425, 16299202570325799651, 10641347864823085647, 18351117229710313282, 11988134638402872271, 9778312471146927353, 7381217128978919856, 11060274181369112531, 7495561798963235349, 9055395298714390718, 16303796496309697333, 8572341055391067730, 10552681108574337704, 778603576632844717, 9200061608692138973, 13379830264581686143, 3558681711903189493, 15333709760058518468, 2592042142960702928, 407067581456916025, 5641562894408640944, 12630685466004633336, 1951314561801616023, 5079140706956976391, 3970999389200166383, 334899398117822722, 8719953466943676049, 14359186121933838308, 8823579651924661407, 1813976296212826001, 7289919441079088958, 6752583945603678883, 11125294819942902844, 9024544902550020287, 16347203117320623082, 16956773689825861850, 16095935035076959663, 5891276384953676887, 15268407330104588524, 8413928464863914833, 8490251354332486177, 6927106640650584013, 12126731995366926678, 3751336702350408676, 5401550620951546719, 6931736049013788628, 12580678497648710244, 14038988011959255031, 6324030753850964685, 10493602541721624812, 2109892633617514458, 12146451675883836768, 13274122909086796977, 9754756986068039363, 14495908277997962154, 9466734708284504026, 4844085276275930177, 9796561850244140319, 1799849561951724621, 12358897468285161083, 12177695598696402808, 7332427622266662258, 6479138013230677807, 2934293921862361841, 10101747402348634287, 17392449178621812522, 9076304922506319918, 11821100168915316422, 2496048241232164281, 3879748422895069655, 16704268052335595321, 17390288111943870483, 7693888478144629575, 76425240623418453, 16567047119010034390, 11413373222405397265, 16470449866739367455, 11214274131174610225, 3101065760151847228, 6960224778085176498, 13808140043074427665, 6407627460027904108, 15896802775139636956, 7832538022931244434, 2921401371982230107, 5173908476677176511, 10421805820757738988, 6810895721424324269, 9500975479118470651, 2857351951424190284, 12823190925726244119, 1508820218642005789, 8299638370676388531, 16716319887270456308, 49159138387135609, 13569342532624466720, 13810905518194621132, 15814726715984180641, 9733273584351206251, 2143427140149969534, 5005663583690258770, 9498096902345501346, 8059179870401817189, 2748099509860782482, 13393750936162889414, 8594871683329714285, 9350309329045037166, 7894115690084420630, 16786514420046861964, 976749382737801867, 10467038807753661049, 9339621677902021989, 402089271605444461, 4137928429977667667, 11168137397964197909, 17118114157506933041, 2466794684933887081, 2381322333528956568, 16060736976005604675, 7659572533258347452, 2456177646632167396, 5581133606107460922, 9386681170001289422, 856367678035725915, 15662913305262005104, 10182759715493794272, 6309878850057832646, 7310497159043440161, 8801096542582865405, 17603162305339672061, 12464396493690551414, 905835578866578233, 6335283537487112756, 18062909181584849860, 18164643260343932115, 9611673889224211203, 11167605540010764967, 5235785776664953431, 15827229396414291668, 15930079830521734622, 10729843207836263675, 13661546405175006477, 16135164248800319186, 17460395396731193202, 14180726883841571695, 15960200487338673589, 8706962802097008830, 2160987916800110300, 1051526548572672844, 9819378916385658549, 5286507605709789239, 13469546533879771266, 9307969742012845248, 15615676059776785223, 13678628123654222573, 4894676242232977237, 12463254721383166913, 16203870605982620330, 16023651922098038612, 7232852316950853131, 8962741390064610435, 11073871852691286666, 1951976192995013845, 981262607320358571, 16888050122965370896, 4344384252438731372, 7412522378253499740, 883175500149730679, 9464224172069098591, 10275279734394232097, 15403548203346787052, 9763124462913973107, 2389315153739146729, 13323697104831839684, 5987579865535399885, 6129762999102774797, 4347951805136348101, 2506188997686408591, 2557923537528328465, 1907502054327326877, 11348447673182547440, 214394370899217588, 1795825157652904688, 1079543763001874644, 7616884667306755371, 14035899738904279037, 13603064082194411970, 4656663014321257673, 2516633233356574316, 13157932564393540150, 11846837651284282888, 16495943766392305895, 11420100349017187526, 10171218756873499208, 6391422370224144667, 3018292857029467592, 3106481628843315850, 6825790880621561776, 12921691493010642236, 17141277638143731380, 4485397080913431269, 13546956797638434094, 17912330572903817378, 8490274475095362840, 13555954280504902543, 14027241222269053491, 10885497045528349179, 12019189578091440959, 8524809140594718081, 6729564987712259454, 10294149345473347404, 14564176145614125180, 10959232484424234147, 13881154219512878890, 11303202608031861845, 9393772422743641450, 6070458610875812307, 16959999555618324305, 10001897689126693737, 11648110147126966600, 11854195848867487269, 1069111130614492919, 14992756999092303050, 14546869344145489447, 8058351440331963307, 4274232524574392202, 11464289163923391246, 8692996261929543956, 4508468249049018651, 14423278340286421655, 2564508301584730834, 3859045330752750621, 2394646001476710533, 15538310772728613959, 7119012861567026172, 14080676356760895921, 10481316516476920127, 8953956652625819960, 15120007614681010256, 1707764772247280369, 9418183698843915873, 8035252867217811158, 11608754122523476680, 9711175522978321729, 4843904770403152351, 13087602715200118413, 6994836269212372197, 17825214555151605811, 2967734810424283243, 2387363035965899020, 17972801638857345955, 14678563586097685754, 18332850447185985724, 4802373133882822931, 10249883805776628591, 9771191734968311898, 12071190072567592143, 9199739750044147248, 6156417751384074752, 9945419763243948060, 16852715112241242836, 15498848488019829937, 8209154894812848656, 7605360745335808686, 5813615285131032978, 63204830640610456, 13528270312138672012, 13283862845967502043, 8050305155218750215, 14674596502349757008, 8358424196888559720, 1146973740112715424, 14964963965589838478, 841757193400499440, 14177680650235797891, 7631715193722403025, 5034141147376399263, 283111841854752856, 14927674423006354942, 16964047188773151732, 6398259345736930740, 16580537252867656103, 12301527733370425637, 12833132833691646344, 17033427146698681927, 16008951791940190108, 17980249132360677006, 16067599779005199581, 2081457686236108956, 5812601273257050732, 17866101689516824721, 2684839860280649088, 854604419444537598, 8905025564636441116, 7217301761354685473, 13930846346011985462, 2228185093512258877, 2196889361780157388, 7373358985538640633, 4616035087050111997, 12541255008421421213, 6023231021806580561, 5345892880580177162, 15954974730435085918, 1459920705275321361, 10512201752571642839, 18058356709377865891, 4833344764102103195, 2509346903506136425, 14446963374952835244, 17897676329582789951, 1678081788586355622, 5572980068705774721, 2292511766532018507, 12515574856517533810, 3533113919323294510, 15790765656655812990, 1229927139455551951, 9079999555500778355, 10714091306623367583, 16702898494447597729, 7175066789028512513, 16316215516083409859, 1335614351511752127, 8120563109037646837, 15529472665463557381, 4320685394030925984, ], &[ 1672628060742854697, 15282246281150199895, 1805861883825941289, 13054368594875028248, 2171479929375595351, 9116298011409447511, 17306888266286748641, 5746239585631076601, 9725142985408265462, 8496940287015097744, 18226505622247538366, 6266780941044650332, 6156048087444894443, 4538057600114721383, 97265789122852680, 6274289580297275262, 5228875786412768441, 16242628134361946493, 11190536716838148054, 14999253618380186569, 9431412228781264525, 3720693557798279014, 16573669939083720392, 6740694555820849051, 6524091096770490079, 3096562044087457385, 3445205792069137773, 5879395926345036068, 11823228934954636111, 12371688555199950549, 17297616112085246932, 2555509880373782106, 16223058021752764878, 14999422229046575663, 4862802819963101806, 17693697449754524004, 7451546626575486923, 16834189484925343792, 16509933831486099241, 12631184257434523805, 17806422081175828224, 9024323842858863304, 6033612708074245541, 14283589057587996336, 10842466583038220693, 17663757149762543208, 17032131808306205091, 4374016337917105366, 6505220788410699133, 5673566217968186629, 5932755409025155247, 4554145012174950408, 17529903423737764658, 3815725265250996100, 768030762409375364, 8101111540473986421, 514131312877508602, 8467511376623331898, 831718339007207491, 2504859423595920845, 11166837695738109823, 14373206768305383478, 9082192462384414967, 14242379354001692723, 12416775352244640482, 13103976180057994274, 6653815487356775730, 4540712387053805867, 14570815029195900562, 13110042734243091237, 3689426930956949722, 12593196976319748335, 5082154213541346557, 8069143451694814354, 589978278622072544, 10926961016815911289, 13766140955627543742, 4586220875755960736, 16112246436712502875, 9204941109851770944, 5473914245681242802, 3218880288053733024, 9536533824552638136, 10077047347011578942, 14182303267298662466, 6026715993374312806, 10378524287074681936, 2296780928121215418, 15754749815480350917, 3330943091954471356, 1126865601328103283, 8951889275386466113, 7986378594472968517, 793002098840792529, 15105672122567239393, 14635720719820726943, 7943655256838356552, 12835998967580492470, 756113536611343794, 13521679712064841769, 6920694928381100485, 3963584378724408976, 18168458596975089512, 6246280487083928698, 15693439960182266662, 2204976266736113349, 17357508962507938891, 11151653946273121871, 1703605549588045403, 16733783926869844505, 11316772557004760630, 18286184542860447926, 17671746225554970780, 7808746917349768325, 11269882956337693194, 12921611154439887602, 16678620045935729497, 16402009986336505442, 12847458604081538511, 17755399026300991951, 12686461068405877203, 14423738039750236538, 4909229580701064002, 1469887314647249417, 13190369397487996719, 10548255880673058721, 10653993017413970889, 15707594908377821293, 7185571374210148494, 16675774579122291136, 6388065414982007363, 3817450123651794334, 8635533889608537216, 6098638948365389616, 14307458322530931176, 13765784114239575219, 14446745783912954054, 3962804757561248904, 1162536535886696571, 8949170256816840738, 7643084825050542991, 16599216336031476997, 17192262166429815739, 10667971872031883844, 3121128640608730652, 10144016131343139900, 16895209624213388514, 1069213517692929905, 11337495802967652212, 5324596461543864795, 8246685063522286472, 18440915663687455364, 2785075444444891667, 14642175687044056076, 7806683982223990578, 18188589122349697120, 17807393819655286371, 9986742896841182780, 11733628547230256252, 9608069068769719469, 2782483964663700175, 4481784645254463219, 16640245285459980455, 7081071197660003592, 4682789333184064646, 8699027495672091249, 2042623593099711310, 9915351267439399830, 4529441913968349798, 17688669638726001150, 6969233181109699557, 15041947273170766194, 17013037482566716685, 4028641208180307500, 9766684953326663168, 16660710246722520539, 9300789760989405814, 4619559511775411121, 11220958186525568895, 195220445631146614, 8797196939793783080, 18091207242784278021, 14238252978432062697, 14862253422759731673, 12947632302042479882, 15790153148656404089, 1463807601685839210, 6696548515759888327, 5142603015218451719, 9851870076797225221, 339341363302195257, 7704429898409730537, 11167176554577895085, 15752522708113359648, 15301031230056608579, 2313150267472026543, 10140513040040392042, 3537463966687096726, 15456908874173546317, 7973357052931918856, 7110133225280554584, 1404650061415360805, 12060443895006083838, 11121710524180835999, 17692677335419631161, 10345142843647975813, 11682157366762073463, 2218847055822344923, 10934859963273441522, 12441186660408656103, 822437026043744899, 2681004617288037103, 17757286544288847237, 8711785011821989019, 2785025474986163397, 2215183106863227830, 8059198739628780880, 571580723319871982, 16197606749028159993, 14831503691581153694, 11539851268300258899, 524105877649968839, 17416266841947817353, 5495778589153513323, 968960604106612398, 16678615353805682898, 11700287878212831351, 3622606565047473052, 2647340224033760611, 6871533508415095757, 2659198863719376934, 6931677157599383205, 5055354256113794098, 336562919103163745, 2361059542672889740, 825783562725949018, 11642185020259800092, 10047872728458598237, 13504093553221294687, 8602424918317817259, 15282984454184248861, 852452176859461039, 10050340329117425330, 2701111594842630681, 3380516875107345403, 4136143889811526300, 6268876047837425795, 2559786284511206847, 17755488665395878481, 8001355533630793116, 14726003870570175656, 9103515680317108232, 8435167688649445195, 14978151287514534341, 8379493954467012982, 6052576543057882900, 15389754048954564920, 12385734689115419153, 17777831557332306413, 9900279278045930351, 1206609987039670425, 13611112101506709706, 12762535112248529447, 817294020497817885, 10754700156031583495, 15389439159096743524, 14162879890232853094, 5117425864944557608, 8604962998164750142, 13790816172204909738, 4104758843285603165, 17930520683724082981, 8414454756264175755, 10449954739296855658, 15479563286299626029, 303808843612780921, 1389720105318403852, 785817621113818440, 11448825792535874711, 9736582039937653322, 12920595361026137481, 16699975623529765391, 13749646219160470884, 11401244124325218336, 16282041074080967643, 6553330957169095078, 2534460029969182943, 15346714113583882829, 10322797870140362419, 8170525298094874241, 8993837346481500013, 1592337973614036797, 4112707017760094378, 3653698431433437788, 1164503220725896682, 4192689923903726560, 8728431104977525460, 6286869906994648159, 15043778140439653995, 5615728271150547979, 1988572003934603512, 15135378657876422165, 315512758477949858, 16216116870274501948, 12504723790971753070, 1535348898544488365, 10095860684622701491, 9132371123926938392, 10120783865748871929, 5051411488306545858, 15543678014917206393, 15426909057079235480, 9504015675463012967, 3066901079497505204, 6081911170465869341, 11137007540202157563, 7450248916723605240, 16986119260853423951, 7578352278837776349, 6751429673444952435, 13612365479873100530, 7696425067114400131, 201953216397633927, 10830451601162376941, 5745264538351074871, 3879748506573515769, 13854134445751736268, 12219208888937467580, 5358318705731611099, 10986820887645881138, 5254734320802095761, 17981689768158240665, 4420729817422648815, 18361425798056776288, 8540074679155734254, 1731667252659743593, 6152889871893755218, 15217521953228771511, 3567899098692038741, 5389619645758200151, 4691008339827948826, 10713279365488347571, 9745954968251366598, 7302191498672369955, 12626782502849516545, 14447293561102751675, 6734094488616523594, 5731330022735521614, 1465319249901885331, 8689750081955043230, 12950959544528179017, 8224104597108932838, 13301534995263852143, 5645122690858278324, 17908106229077733178, 323203859917688448, 12815293733143521854, 8031863434623615415, 15599896533075140903, 486382747533668075, 2557885075871780373, 5639961122845008175, 10393998329050866773, 15322005771165766426, 15578096382762093684, 14721580303503888873, 8331810764551543605, 14134080240781873816, 5292301859290420205, 12934613667998296598, 12759300614679833510, 11836905953852898472, 10400210724390354576, 7895575850616655288, 329940446534439796, 6948421725680731847, 10383034077753168858, 14251858051847196147, 13417478805898580488, 15666356095993822967, 2649890612422460352, 3960290467905564799, 11604699241357916870, 2707032916751066910, 17162029134544454899, 3462167755608084681, 7708163267151599835, 6060118632496715447, 14659850067472343295, 916231975382177286, 7887196957456909593, 16212896135104729851, 18388686047231092271, 15188059656466677817, 10159359915532738686, 12209557326012167892, 17104166537381148968, 8549912606942034263, 8608254283565330385, 12199789530349117525, 17653984748958090856, 13236243855027491135, 7285865740076703400, 15313657680519880233, 9809529301268841750, 8322107960211428865, 5703942948802254530, 14812716998355005471, 15136016082127517829, 7281927702421102653, 15373636513805545688, 10377353955277252153, 2710606888135973500, 483290790823167088, 16941949237955644494, 13114672411012065693, 16718085808501163359, 15292113884889789796, 7981991935175106680, 16723904260851495386, 4634513538107365365, 18324378641217720117, 18227662801481578598, 5444832827920199100, 12893849341139616412, 11696684010633795560, 12371761519158834548, 5017297642292910863, 18115726883313877717, 18182028244204009400, 623586467022528940, 12093052177881141597, 12472931752552395239, 8322821403753201296, 9468858393454090922, ], false, &[ 5918120123986948981, 12214866885969252723, 11609253883777433902, 5635355260056282089, 15175771283313717007, 15492577498145701934, 17281089998867972767, 6586417628634894478, 12935717257603408407, 213518157147993568, 17634550085774545221, 7802961645411480687, 15474328354975317828, 3030764988654892480, 8848149603966882371, 676892117606100777, 4196049354216097590, 1119069746820091103, 13781529735879690406, 16275626026273391927, 8300205860701261916, 7767984337518977035, 5352931226469408832, 12549815516668122057, 11497059402098551468, 12238303176301966941, 17906048896221344372, 11541304749033810082, 1087347036356063215, 10445124749889523059, 2108226265832637935, 18326684922164242899, 17591839094119199053, 9649362351718252143, 5419877371634754910, 7985315133687996015, 4380072020580579165, 16785985274039491915, 17906401277998543325, 16110490995638091421, 3199491816914838798, 16213219991928431786, 9326535095032375619, 15738134700481029737, 60761202193356037, 14526584003657596983, 9717506275850427639, 8872353450872566613, 17495997723658103586, 3896491297225969939, 15875376698593105408, 9826018841003362522, 8152616341657954338, 14943012924993107558, 7125340071924826005, 4761034333897027607, 7251331321451036206, 4747806146235227299, 6726751761629566068, 18178470774825318512, 18189114841849876379, 17717832995746573676, 2573674198725968785, 5853505062283210675, 14828791922576430704, 17468100460396300527, 16548721553868826459, 9927275635269960578, 3174270457173750382, 11071224255186651932, 15278979303406616879, 9257778059115798365, 14655545247523251097, 13790831768475677442, 6071172380973927546, 14653522655958546738, 1283852078171252640, 17755439659741780817, 7042497028732297491, 5214827328478127328, 8543642755744863764, 8612011501311255315, 6185713519471448847, 10532050115036338934, 4085362692096841984, 16722145437751649336, 9095286107166596594, 13057785857928532741, 6724302268334378235, 16685648673426979898, 8043212514589919457, 4407985707410781908, 4857378688754564057, 13943718795425872569, 471792017916165335, 5215960704545918835, 8898677740944188434, 16192547849590163757, 10927045263666149554, 16012942497443086833, 17856824427949500892, 5311983919389056447, 9076063431281448739, 2785828113680086598, 15110707091558662212, 6583010959630797697, 1419528267250785056, 9595683664056411195, 3249323284298806238, 9595933966715778670, 1500902293448815881, 5874310265457777380, 5285481081074725330, 3692318632564707737, 434746415289817737, 3244704509795678589, 5607528670277715164, 6168231075304184647, 17820359109262978732, 15921865578115170464, 6560400307775181833, 18092176022757937173, 2416917950725208618, 5068383455535678979, 10996164899950125555, 2534117342435778418, 9652711066484768908, 13461915503471780054, 8411049298262654215, 11627045183374435993, 597713380029364712, 9914424860026353436, 6398417476997644577, 913522648047558044, 5233560422688152729, 12269904588172515957, 2915109300865307211, 7061777415895646538, 14428707789216354297, 1790994874131700041, 8134975277497787768, 12979580903727579988, 11615590867637744738, 7000312698420541142, 9784693912853241529, 10944442549740283787, 82531176080969023, 14959951731803161969, 6668176410821069021, 4719500064486095694, 5759785414559226561, 4970363591469849595, 3243428337539320431, 3156898109989998209, 4247164185502339328, 8388168007257316831, 8981232323059064529, 16860198432014849988, 3539236745546337501, 17719922367578025346, 17210626294345726472, 8625129527773205281, 15568690990583000906, 16537720024170832632, 11081163673779633734, 14597737748843479829, 12286199535506665388, 7151442784245909806, 5044864980114186877, 4391689371296961006, 6540168485548659477, 2857514210130326707, 6969210128397296294, 185414187382782164, 9788252758640228255, 11134472910826455196, 9826829185177748458, 10391037584385454968, 9612702489136097624, 15745785329372206817, 11985385919699457287, 4647950731727578599, 13474308436818096670, 7407581385161850827, 17049401430832148706, 11185615615288710943, 11340197387195283249, 9085306227945895799, 13048191724100099668, 8222075024390640547, 14981122579864582841, 10723365510805850325, 15882294117621079731, 17224307861706260858, 404752946419267157, 17455653606541202378, 11149932181201234911, 17174493378281359115, 5742746808088101191, 6857975670321360348, 9488183194120086577, 850756444942468501, 18251138242152971676, 5028044743228145865, 1709652293836541825, 9336246950855990417, 12104001557578243874, 7518552932181414217, 10953659187130713754, 8640278306963064150, 3527996602952080033, 9724416208794871557, 9818471899845617626, 2259597663894735920, 17196044757056583541, 2638888046578257240, 6998509470199156531, 9192353130659837733, 567984143948249890, 9591497398626468338, 16399018889425267172, 11561115484479883223, 13399243786692529429, 146294187886053462, 7961591237166713768, 8208718803163953456, 1484938287860582687, 15046852652421580156, 7169416232431254009, 5292287501892714727, 16630324861460976422, 12475975871299584278, 13525399861247607934, 1565336724846468707, 7276508501752242104, 11859012083360705479, 555007877916338240, 14880605908455542248, 2705807160288146830, 14145160047055578292, 9866403983350364712, 1195459380772174685, 11139370143037652187, 11437022067401833240, 13682486855606152975, 3430673715799609998, 8489219321033686862, 14395916737962056100, 14198819344492488794, 4725627873940009758, 4377130471348839898, 132810124294572633, 10250911241920381171, 9212291520499301135, 14290126791732174693, 709484470312549752, 13655949074890812034, 16390659273052951496, 1962161044085964851, 6592951073267309884, 16635386023505459542, 7521725279768638651, 10702292265780209953, 17508035731310744307, 4849314369727221433, 3518368935757575829, 928772043789904943, 13066503627704932241, 9170835921766657120, 1720438369363860482, 9653343145255079951, 10806927358101847561, 11860406035049881649, 1974385665395717679, 15975482787244401193, 3619432381005082811, 9877997566644094001, 17053881395186060130, 10589869650671333670, 11664760554418654295, 7590280596977495719, 10856366592484551548, 2631368840539712836, 2839899387286337113, 8524146102427533222, 4990365012618727902, 7151891648819983069, 11375481945550229603, 8858696180128338237, 16384521973744224932, 17139452207328725464, 13252654993803597499, 13434282302115861786, 14150706912775302393, 10948307646609458445, 17388420540008093188, 6587864291894884444, 7978190567474696593, 7928967279204444076, 15049296655976922413, 289738567977993423, 6897438000403266124, 5964433949215867587, 16648009539233406755, 12752972348654131733, 2033455762505189299, 11364966258849937493, 16482570007448457618, 11388428709157868651, 7266585693081119187, 2599499958067785647, 1720925230213021349, 17626323535654061769, 6663193598469739489, 12671248167045283050, 12140673778531699982, 12103201664484858035, 8004547753695309336, 6455154238957765328, 8593204946748750727, 10957963623834878235, 17888461227536598973, 17735403436793241827, 4585025702858048319, 9246263998993338794, 9799856693447240374, 13046824397398954407, 3257704574039398043, 16475559398714306923, 16151216692843310157, 7492987706459570361, 8794687054736704078, 14498750737487053007, 6499114153875831088, 10344627650758003261, 3933547531509449109, 9252017834015356297, 10431927836410739631, 5636096958617681173, 17723724381959311922, 821040401146944398, 8509491285814488607, 7142450219324257681, 2899499047459777930, 12095042099304891630, 9090217037821987593, 3737560355775916991, 4433293248592466046, 2579586186392778687, 5627778192418388032, 18000377780513451714, 2643121727684540272, 13573819511864552202, 4784246152290536627, 9420370852195292962, 712263826591202499, 15491886233585377779, 9323035863279061117, 11045154527883042924, 7385229880856543696, 6977873611490450039, 13639543508335080037, 13478048328899736023, 18039135682054740779, 11521064013981520637, 12102327419513222106, 9272869873740159480, 12775276724893510766, 5753913366937783318, 2967349222422898380, 450790676996347594, 14991588921019202960, 4473124084109094254, 5276806381726757488, 572213956369142365, 978390961725309052, 11077194266341939697, 9301606295378325073, 6640701743743293068, 12862661643802294986, 11875074059347396257, 2662510629463159961, 7518896084004916711, 5633197821304310891, 13694031055503341476, 2390793653044825173, 1748645157989562610, 12795800048419142659, 13894628843525927844, 2254756627497371142, 17588489135795917364, 5359793907722886073, 14093783225507224946, 12953198522788916163, 13706816417396184408, 17931918665360327727, 3692987813274069977, 6331195597561897082, 10168077267706641283, 9760779913234776768, 2948160909961149051, 17652740296610148356, 12899526691779881821, 4089363416315714602, 15800160433756171036, 4150896140209606169, 4332987844457554832, 1726137208556197778, 2230907531048364518, 8037395526181922358, 11903227707490817951, 13247419964627176543, 9656311595299555081, 11824744075533270637, 5618559869312497469, 5589143266997450557, 18379067610860048886, 11371445493433813486, 12614852294401999528, 15893311235480705385, 13552674216984930943, 6331861843109662222, 562000957286283961, 15993421123194766567, 17787868659905745587, 884898535478444829, 2284336629817602343, 13188445592703944671, 262346945748782371, 16087606565809361134, 4452167838802852067, 17502476454970888321, 8180837608229621001, 6395585225706196871, 11859771797007351562, 14699457447367466778, 17084204551310758507, 7715446538566999362, 14709025739137466139, 14530757131065554612, 14780426661345509038, 45918674395986635, 14144922841238297945, 3642101397043170323, 12593107591216122208, 2107492802032040706, 3969864990100431674, 10726651770322104822, 17773265383948264351, 16680071697289316333, 12864952677492720002, 12349506660379881743, 12343351742867596309, 12895930201825086535, 12401346848400595318, 8155690734768845822, 11075739107507568490, 14443945014748180431, 4606806037355291818, 8618009589158556699, 4962909705265320474, 7936513201613120511, 6885820758344807063, 10401668492364333375, 16727888475202594818, 4154014773292175466, 13161203947882521396, 13919019307994819468, 9598301910556281548, 13615929950270046529, 9814294142614670228, 388842039453995229, 3868906497764221215, 11133917243382513385, 14431233794630116013, 13866552635857099237, 1446694260333969170, 12634186166034145163, 5583369938899602777, 5137033854197759276, 14066215613504391619, 3724105431075335405, 634452116543180599, 16701028791920674351, 14689441581249693370, 11300117837769921445, 5709070571093483362, 17979686883221884345, 4523042923981658057, 1775748550754504259, 16344644718339597549, 17392052235242169852, 12785196418644852357, 18211451905528726650, 2708064947215446363, 8380100165657891871, 7137253101551661869, 8142616943154617917, 17803746564213147436, 153826372692538928, 5723793786021725861, 10196131183953359834, 5523825472161035798, 18267865405460736489, 3283468354748984180, 10604208998484587574, 7393144798381468009, 14384823378526431848, 17875404430476094447, 12734512376384491761, 12434256692947114698, 17275896681161726464, 3991517411918578920, 3341256985625706194, 12875923317501906784, 11553174191068953395, 9402911263274348037, 7889147691441176281, 2938433861208318833, 16835317070524419869, 15311222124964640322, 13191386070347279526, 2797120364879623301, 4825023507822429466, 850800332384380026, 12566471159773669108, 10641916485819690941, 4533772051636675323, 13280511685797693290, 1555062755988987659, 3239647128855404245, 6726066500947499377, 6007423757732386662, 4149243922709316723, 5132586553438157005, 15792321766139519460, 15816926954768067972, 7294118112451354585, 17286958838591009277, 4907287824228034499, 4053237279580028055, 15243191806135344763, 15160933191318572834, 9399541646460123387, 10512247032240862385, 1549392404477822056, 1553664084033256717, 8299938816978050250, 4506406752176376101, 392106422304255528, 14325256251728416026, 9605320355454775897, 149289209445211694, 14196672746036566731, 16390833843583709204, 7306529835380864755, 1609617294884241186, 4376392608007191042, 4686172428942509254, 9226100890114720864, 4817469637170691996, 11063190997882783988, 16818806293969511167, 16753414946544024233, 11652469874726823984, 10410834301724561610, 4496419155373466708, 14860760715530123421, 17116153223846910169, 7192050227650381565, 17378669812287708918, 225986433549199368, 8470401363462512715, 10770868581319043866, 9466901035622012241, 6699024375729741712, 409036602332432525, 5386757448559243618, 8963450891011896500, 8673144181466249760, 873094291187559664, 12664083699094549676, 5775559671211518891, 11686008504688202631, 15839718905540698056, 13266083552259617867, 16629163912909716168, 12951596193960803465, 16680382695263717715, 5312112430010155237, 183580306753984010, 4620614350630898330, 146368985100561751, 8680242838971693339, 16334891003809230168, 8296044009054807136, 11068535921992539488, 13459068409989801398, 16330227018753527806, 12310150645922723889, 16470777689868351201, 13885354582351631115, 10781416202037656061, 14844375805930616264, 8719638653924890264, 9466966915302767475, 16902517274689764268, 7637295587685318358, 10083082213122260465, 8181103359836753090, 16962684553940361626, 7837156732091767324, 269176569842339446, 7278095361680012780, 3942758955593007702, 4528968938190179194, 6704240607075070331, 3303432731279722312, 2158648768224700327, 14688749631211044587, 11272001457898253785, 2068777615217221600, 7354581415030465360, 4115757448706765204, 9845224061747124764, 3689237284770699729, 18290464418127999238, 7852077070988627012, 7863151332492806125, 251628885737301978, 18042357620611449193, 14116593607800996151, 8096141927089169364, 12647877985059926597, 8418401584195560472, 18060685288941472824, 12955326448341608928, 17257701815289013872, 12412692797833535892, 7581020805942464303, 1793728477510701265, 1440048947029875831, 4001344949088306175, 4930448054167731848, 18351422903276209040, 14203523087498470015, 4333543995517392762, 2404299597925046684, 8665180504038796043, 4824446420399647636, 10289758138518593816, 3607452937085742574, 5784430632374580381, 13224009883109730301, 10433302833369492081, 8563330309308426093, 977134692355658252, 868639596313947660, 11114845570806284756, 10553568804667187456, 828402278919864619, 8940626136465663544, 1412605768723256370, 9626895483501195170, 16359088278152878811, 3692614001269046240, 14789154216532717572, 4036942485790633503, 1049261082210626671, 16218938044785968460, 85530679118254297, 13099694691696048080, 3076142799126365810, 16178437464286841227, 12056596164270992336, 13502907218061644868, 3588068196299944250, 6887727249443337211, 1859310871727038082, 13661391178199592998, 13954271532839623639, 10390958586703587961, 10379888160727024239, 4052888005851455694, 7904956370427672392, 8519981488846994043, 15332926568151370053, 1191060154732214298, 16959635090494556484, 11069336977744897600, 17227745386405237665, 8089827037565392855, 13503095650871818986, 16377926887996418472, 18093036631333756750, 12555984050040346394, 7227273171888696040, 13299375693247766378, 17475709327332183680, 15615295930257614429, 410338853684361107, 8259500083186530998, 2735443689396556788, 15142914652661121453, 2197321929993766794, 17346858321220349784, 6402361562826954211, 17682894801076100405, 10016553667127190501, 13036488928964213107, 12660139296995183874, 17212334112539182701, 11367734776084342977, 8665742805841735408, 16025336783181331773, 5117698047398356429, 12735740150828193823, 1081804134485276729, 7842045440217572578, 6019238819083806569, 8727766917839869670, 17543657322565662173, 14412106950578331252, 14543869151173063856, 7943364918570979252, 14084805295748537131, 13111098905227599465, 11202865977925716420, 5996820135817652995, 11571287622023775421, 5373524677929215301, 17153815447258968833, 10046961949080008556, 14846860571176635442, 10338928091935313530, 2940317764326823227, 1776405787535180450, 625809269984863503, 17769559239543673204, 3118489222192938565, 13250086689910946329, 15923099038962390019, 10822567853940674338, 6978627730782203076, 2595174935535264194, 9243536850072179353, 3406470433637984371, 3073959449450317144, 15861711889629424487, 11928324792455649636, 13550524272193533110, 15780700931447669545, 10131935114090648897, 5340317636333714216, 15339343608558820412, 13396278126027078678, 12344841862313043381, 12566090228569145515, 4467783437523316260, 17567821697166775078, 9779110602238335971, 11793438626400388253, 2497240398513373223, 10605325543162108671, 15082988041680062339, 5183965453682540694, 6434074123110416631, 11620219770967033588, 6206234705311197318, 9042208974224880901, 9727369898804305283, 4647900181451243158, 9318060116894502304, 5257285210765950994, 13361487866051577136, 3441585901560937350, 2240964027883718235, 10026719207153507368, 17290246452243511459, 14480168376982470724, 7629280450957209642, 14474347826383962832, 11317012819726516750, 2962115003543065613, 12162772852283897343, 7157384874230657509, 6851750854456963926, 15390047842623433503, 5489411047155759331, 6332140231414210853, 11095975516180329805, 13859585413297997655, 1668754947299094584, 7358928682129827290, 2766327988455105348, 16708694722996588875, 2768953098861172595, 6914880772284915541, 16557166180686635628, 3693170667429108001, 16072312986624846808, 9896456787099841815, 17615200765944957338, 4199047158638921808, 8630520885961961356, 12027685245286153560, 7891368337618414637, 6404928949401724730, 18116758261578934492, 894858370047540031, 2921629729181210457, 7745289541745323639, 11350346089330756111, 10152653266983330591, 14798328937825324211, 8949208387022094213, 17787392503905898329, 12486460963965989428, 651591352658579316, 1237562200852981434, 16003240939391023959, 6420739448387256570, 4823415470543283046, 7174592656453798147, 11424373324798981360, 737331696961998974, 4118748058691239361, 14616473443770035549, 17650444454043907647, 17711200809424400157, 5091501578910147488, 15550101363878126041, 4566810755429043240, 11107983018581197120, 13554292788177360136, 3365373296985431135, 15610147292789460654, 3564088093422756616, 10817889322783172996, 16159632643279358168, 8597419859706760838, 11079829268996560033, 17269507137857304393, 9947618800967513663, 462576820491406287, 841015303753696179, 15512002278736704978, 3374877754464709299, 1154757937962396227, 9537134004482849819, 10128571182745135555, 3704274043469819984, 15034886915357192640, 916221862035256124, 17425598900953186568, 3947379328146942835, 3660680652792309828, 5007284878115686577, 7522847462384788182, 10571799915899197168, 8013565820738950446, 3966675855215748889, 129692155915043627, 5691183223879520601, 12139669617779071047, 11814058524451360978, 6775079055986650672, 16825782776226623043, 5104813292662071339, 1450815249446379483, 13853175235386092441, 6694335922759190067, 7218434162566164191, 17430813386582913632, 8498332674216771915, 17615391640730478338, 241596204271102644, 2570852601221578960, 4599802214241276374, 10438837029660804288, 5157548795688936967, 3798153122426926247, 2692303022775628041, 1447520878810147944, 5855192377386493733, 6514581604771681776, 1473660589499588222, 18307281621256799329, 11125509395109998281, 2435145631387070987, 1285271838144216244, 4541083490208481993, 15565142710078764855, 13071820190366239674, 10807442981250235320, 16852181421674849736, 794202264952966952, 14267784245260213795, 13928008029423527207, 18135353902736935922, 2114431837901815099, 6130665714725128892, 14739842984474439614, 7454369312678179513, 15910289572447146154, 9146362349279587472, 4658814649895066035, 4852338178188865614, 2192949132388551398, 716457667898608901, 2399899887449189428, 13124730724498682787, 1984867750527727115, 3299889278515997731, 8195306963169862777, 14475785604327151063, 12724460465724812829, 6758639346286631138, 15913784793216142830, 13171932495254154817, 3538643548410335706, 12168540036106852345, 16425314134821469021, 331063747268359873, 18155850216697850278, 211510699789398426, 7935466970847300822, 12229125293409986487, 8734112355949291277, 10071615545797653112, 1793864989578041612, 11752738563545219357, 2554337087062880546, 6784160661654190401, 685578570200418652, 2732494065060693551, 7703734784123999976, 11477040429265293999, 17381175706019390228, 14837293364696097009, 4833703890663686653, 2761757739428920605, 9412696259424618339, 18336993413001201202, 5392220203502617737, 12132875900848494122, 5897666419764808427, 10107214772704578306, 5834665481992921890, 2244306519766258831, 5820675501905835926, 13895182007484584312, 9733080033395096503, 17951749141696177588, 7852600446374176592, 642107575067795990, 16064679065784673939, 6040352419222121316, 16970428073606505636, 433090259886128885, 1549830981278788516, 3028881619520159752, 12587143878061487305, 7306602487976240524, 6069082702714594855, 8317005307998462740, 11586696275428727811, 10124520395695439236, 2195436795699758658, 14913315324971455554, 5466516946326216931, 1717042106502750014, 17693487700744112539, 17312324646637390229, 12185008789555994527, 9030058640985830041, 10443142281726880983, 15264441814628501960, 4146653965712179952, 8027211328596986571, 8811720185546566650, 5690186672540385493, 251818496025458043, 10345253390016854955, 7346199546033069539, 13632205746357973720, 14506822790046125209, 12522294874687963723, 12449500355426750184, 16764643529091852379, 2638044797938755324, 18319874071056096586, 14888037590772700254, 6416648884059549407, 3741778762412317117, 3440707741509585117, 6047470481787558630, 2492811946256114988, 17943897517735339646, 16834876807347850875, 11693943181588820350, 9934491754613191232, 7118638609538842310, 6721145656345173892, 7927663645875889614, 4114384607638700718, 11775393055826824993, 12784890791525439800, 2959297838067480856, 9238429361931549659, 15825672608139947803, 3094848335709726824, 8091746658688215399, 7128309512560006037, 3784265539610231208, 17653881331317683086, 13833532758351825783, 3974699445166882529, 18126794112732677537, 3900550060852543519, 17913516784410626641, 14238655509846810037, 17818640735092102056, 14112661809980388763, 16347084184144786237, 7317578804055819219, 15985432390504555226, 16103870553153834573, 3533821776202300649, 8924951458298615732, 11378896973645739060, 8417337589693233698, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); } } #[test] #[should_panic] fn limbs_div_barrett_fail_1() { let ns = &[1, 2, 3]; let ds = &[0x80000000]; let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_barrett(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_fail_2() { let ns = &[1, 2]; let ds = &[0, 0x80000000]; let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_barrett(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_fail_3() { let ns = &[1, 2, 3]; let ds = &[0, 1]; let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_barrett(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_fail_4() { let ns = &[1, 2, 3, 4]; let ds = &[0, 0x80000000]; let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_barrett(&mut [10], ns, ds, &mut scratch); } #[test] fn test_limbs_div_schoolbook_approx() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); assert_eq!( limbs_div_schoolbook_approx(&mut qs, &mut ns, ds, d_inv), q_highest ); assert_eq!(qs, qs_out); assert_eq!(ns, ns_out); verify_limbs_div_approx(qs_in, ns_in, ds, q_highest, &qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len + 1 < d_len // - !highest_q test( &[10], &[1, 2, 3], &[3, 4, 0x80000000], false, &[10], &[1, 2, 3], ); // - !(!flag || n_1 >= d_1) second time test(&[0], &[0; 4], &[0, 0, 0x80000000], false, &[0], &[0; 4]); // - q_len + 1 >= d_len // - !(!flag || n_1 >= d_1) first time // - !carry second time test( &[0, 0], &[0; 5], &[0, 0, 0x80000000], false, &[0, 0], &[0; 5], ); // - highest_q test( &[ 2694350779, 1945458005, 4130424186, 4267238024, 2588565427, 561074857, 3031728663, 2495857464, 1122008234, 2280094424, ], &[ 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, ], &[ 1430162564, 1873089879, 3090281851, 2861182896, 2502166555, 2486624904, 960387080, 3073064701, ], true, &[ 2694350779, 1945458005, 4130424186, 4267238024, 2588565427, 561074857, 3031728663, 2495857464, 1122008234, 2280094424, ], &[ 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 1188988289, ], ); // - !(n_1 == d_1 && ns[j] == d_0) // - !carry first time test( &[ 2678906106, 1133029551, 3498992572, 3960506675, 2156562886, 2180928089, 4027866586, 3363079195, 2699625088, 10633112, 1776348429, 2657266039, 366882369, 3755249663, 1513004482, 385462618, 1235118123, ], &[ 1454965277, 156018042, 1386304234, 3933017003, 1840527397, 4169420651, 3343338814, 1487329926, 3897306601, 3401241545, 3117994664, 2264466925, 3843062712, 3688462745, 2751679318, 2963108470, 1519717633, 1232770303, ], &[3907037329, 1526550202, 2796269294, 2117183522, 529127946, 3581684574], false, &[ 804693922, 2514269410, 4036020089, 2186548072, 2508423987, 4057814367, 1906755998, 3240890878, 892733317, 778428899, 2723150360, 1478273149, 366882369, 3755249663, 1513004482, 385462618, 1235118123, ], &[ 1454965277, 156018042, 1386304234, 3933017003, 3311017948, 2590855881, 4216998583, 2363684544, 3240958306, 2015516746, 4229646813, 3042340787, 3637479002, 2452334854, 2707761200, 1588607308, 1519717633, 1232770303, ], ); // - n_1 == d_1 && ns[j] == d_0 // - !flag || n_1 >= d_1 first time // - n_1 == carry test( &[10, 10, 10, 10], &[0, 0, 0, 1, 4, 0x80000000], &[3, 4, 0x80000000], false, &[0xfffffffc, u32::MAX, u32::MAX, 10], &[0, 19, 0, 0x7ffffffe, 0x80000000, 0x80000000], ); // - carry first time test( &[10, 10, 10, 10, 10], &[0, 0, 0, 0, 0, 3], &[3, 0, 0x80000000], false, &[u32::MAX, u32::MAX, 5, 10, 10], &[0, 3, 2147483630, u32::MAX, 0, 3], ); // - !flag || n_1 >= d_1 second time // - !(flag && n_1 < carry) test( &[10, 10, 10, 10], &[0, 0, 0, 3, u32::MAX, 0x80000000], &[3, 4, u32::MAX, 0x80000000], false, &[u32::MAX, u32::MAX, 10, 10], &[0, 0, 3, 0x80000000, 0x80000000, 0x80000000], ); // - carry second time test( &[10; 4], &[0, 0, 0, 0, 0, 0, 1, 0], &[0, 1, 0, 0x80000000], false, &[u32::MAX, u32::MAX, 1, 0], &[0, 0, 1, 0x7ffffffe, u32::MAX, 0, 1, 0], ); // - n_1 != carry // - !flag || n_1 >= carry first time test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 0x4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294705152, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 0x4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294705152, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 186, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX, 7, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); // - limbs_div_schoolbook_approx, flag && n_1 < carry test( &[10; 115], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147450880, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2147516415, ], false, &[ 4980658, 4718518, 4456378, 4194238, 3932098, 3669958, 3407818, 3145678, 2883538, 2621398, 2359258, 2097118, 1834978, 1572838, 1310698, 1048558, 786418, 524278, 262138, 4294967294, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 4294836225, 10, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 40271144, 2621513, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 131071, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147450880, ], ); // - !flag || n_1 >= carry second time test( &[10; 24], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 32767, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2147483648, ], false, &[ 4294967294, 2147483648, 1073741823, 3758096384, 268435455, 4160749568, 67108863, 4261412864, 16777215, 4286578688, 4194303, 4292870144, 1048575, 4294443008, 262143, 4294836224, 65535, 0, 0, 0, 0, 0, 0, 0, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2863267831, 61449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 32767, 0, 0, 0, 0, 0, 0, 0, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 13716243670146164789, 10080982542333195561, 6537250227633874413, 12999253343990893001, 12265098574469062516, 10364481473864190262, 3369535821171388227, 10993808308731343874, 2872517547503231658, 12291082106617508077, 9131160905399738920, 6775211851169928012, 8910327134129798117, 14142305268873431891, 7124925848807234985, 2155988926103471984, 10449767567966035946, 9346026815749340730, 1047855496984265723, 8616868492917905090, 6520418679719901901, 7627787833874912128, 16237358816885147630, 18338579662632174061, 13533819409691495819, 8877538849543441757, 1515670908092000385, 11038667469728451796, 1811062388681013211, ], &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 4451260977376821357, 18241701617364042056, 6169989192350218482, 15071965537117101028, 13509168527678537782, 12224278653171635329, 16077066393714953826, 1433938684868066489, 13014970036232570373, 899282336249563956, 3089487642230339536, 3787737519477527148, 16667686214395942740, 8787122953224574943, 7841835218775877827, 9693303502025838409, 16122224776459879427, 144327425397945219, ], &[ 2350654041004706911, 7834348511584604247, 12756796070221345724, 3842923787777653903, 12373799197090248752, 9712029403347085570, 1426676505264168302, 10586232903332693517, 8387833601131974459, 6290888746273553243, 9503969704425173615, ], false, &[ 89235393247566392, 5198286616477507104, 15671556528191444298, 6642842185819876016, 1703950202232719208, 6620591674460885314, 9897211438557358662, 12382449603707212210, 13586842887558233290, 11884313943008627054, 3205830138969300059, 4257812936318957065, 11084100237971796628, 13937343901544333624, 11743372027422931451, 280132530083052382, 10449767567966035946, 9346026815749340730, 1047855496984265723, 8616868492917905090, 6520418679719901901, 7627787833874912128, 16237358816885147630, 18338579662632174061, 13533819409691495819, 8877538849543441757, 1515670908092000385, 11038667469728451796, 1811062388681013211, ], &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 10156380351246372681, 9009005527785483288, 4330767427200269309, 11409205475757922767, 12430752173702915207, 11990819624778098799, 4145020291153594556, 7099200056207569977, 3510167930325480168, 4731667122118327121, 10720310942075546738, 5799804483118787221, 17268037247251138479, 13305947798457087249, 1405091439325174594, 13072181651983436371, 16122224776459879427, 144327425397945219, ], ); } } #[test] #[should_panic] fn limbs_div_schoolbook_approx_fail_1() { let ds = &[3, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook_approx(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_approx_fail_2() { let ds = &[3, 4, 5, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook_approx(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_approx_fail_3() { let ds = &[3, 4, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook_approx(&mut [10], &mut [1, 2, 3, 4, 5], ds, d_inv); } #[test] #[should_panic] fn limbs_div_schoolbook_approx_fail_4() { let ds = &[3, 4, 5]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_schoolbook_approx(&mut [10], &mut [1, 2, 3], ds, d_inv); } #[test] fn test_limbs_div_divide_and_conquer_approx() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); assert_eq!( limbs_div_divide_and_conquer_approx(&mut qs, &mut ns, ds, d_inv), q_highest ); assert_eq!(qs, qs_out); verify_limbs_div_approx(qs_in, ns_in, ds, q_highest, &qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len < d_len // - q_len < DC_DIVAPPR_Q_THRESHOLD test( &[10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], false, &[4294967057, 15, 18, 10], ); // - q_len >= d_len // - q_len_mod_d_len != 1 // - q_len_mod_d_len == 2 // - q_len_mod_d_len != d_len // - hi < DC_DIV_QR_THRESHOLD in limbs_div_divide_and_conquer_approx_helper // - carry != 0 in limbs_div_divide_and_conquer_approx_helper // - lo < DC_DIVAPPR_Q_THRESHOLD in limbs_div_divide_and_conquer_approx_helper test( &[ 1745715367, 3242831492, 2189664406, 3695710048, 3400938664, 2983493477, 3450434346, 3015863128, 3052023755, 2151651529, 1044116780, 1095733406, 3716653807, 297398212, ], &[ 3142115855, 4096457822, 1432901702, 1952216623, 2397263357, 1868450777, 1021098076, 367053436, 1889683424, 1528567953, 3087804116, 689228227, 2409781986, 2752631639, 2960393344, 2301774469, 4157044152, 730723095, 338324989, 783259147, 1430926216, 364208092, 2781791540, 805329298, 3841626209, 3970169746, 287294352, ], &[ 1650097037, 2785533476, 2062924184, 1202017958, 802671467, 2646041574, 1723210259, 3842076078, 3483645026, 3596926305, 1708140396, 44589295, 3278888837, ], false, &[ 3307700692, 2732374665, 3119369275, 1963618313, 3967275780, 1010403672, 2386237047, 1636315044, 2452324979, 2121986305, 4198504803, 1202996215, 3246857339, 376322562, ], ); // - 2 < q_len_mod_d_len < DC_DIV_QR_THRESHOLD test( &[ 2955158159, 1759170654, 241992668, 2980193182, 840605220, 1045835548, 3208341497, 2808694346, 3017377112, 355832894, 950019940, 696314608, 1276063535, 1858415265, 60277520, 2139543466, ], &[ 3731075771, 2226257702, 854739192, 2333168376, 3831123162, 672459584, 2105255949, 3941486408, 3063931623, 3785513419, 2454733900, 2814451407, 149252521, 3850018836, 2493517320, 445200997, 3777868852, 753763226, 4021231089, 1034604267, 2132847427, 3137530222, ], &[ 270591029, 2232658820, 2961791111, 2169611462, 3306811456, 395960943, 1347788049, 792089960, 2698153968, 3485969429, ], false, &[ 1488408081, 248978519, 2376028816, 407178103, 178475908, 1057954502, 1272791110, 1537402746, 43900650, 1842311580, 1675506505, 3865664908, 1276063535, 1858415265, 60277520, 2139543466, ], ); // - carry != 0 test( &[ 3168925666, 1401331420, 1768122255, 956650685, 3125577762, 275145267, 4000912215, 2182857050, 353954436, 2524534987, 1528525099, 1007392140, 2880118216, 2063897965, 1760572146, 1006590899, ], &[ 3431345542, 1730498888, 4138696524, 681428010, 2575604395, 915393966, 2674130562, 2622706300, 1008959988, 202234291, 1715673957, 4288131207, 3157817283, 1254299717, 1844271939, 2429564694, 1102891971, 4218541309, 2925340256, 2466247404, 3527404620, 1380334293, 3436079542, 200877067, 3607253971, ], &[ 878527761, 3297204326, 2726502278, 1631019758, 1065904878, 1800983432, 346615437, 143744864, 473085159, 3630485760, ], false, &[ 181883802, 1500895548, 839791393, 3438225757, 1702652997, 2997889672, 398115167, 3761202175, 3544971480, 1688702060, 207943299, 1616875104, 3637603520, 3111391940, 4267483432, 1006590899, ], ); // - highest_q second time test( &[ 2437003791, 645401979, 1378969963, 3859694962, 1591396376, 1173467855, 1717394161, 2958783214, 3972116836, 3930714191, ], &[ 844935929, 1399477695, 2543116912, 837902568, 1404832613, 3601679936, 681919524, 1510676120, 4054159774, 3802723255, 3285008709, 2781902552, 2079211469, 3135384488, 3124225549, ], &[4097164548, 2480021577, 1254500038, 3382139236, 615831817, 2805966013, 2977211920], true, &[ 3611312107, 839029826, 3955154288, 3446643589, 690412234, 2545148908, 2572472581, 212083904, 3972116836, 3930714191, ], ); // - q_len_mod_d_len == 1 // - !(n_2 == d_1 && n_1 == d_0) test( &[ 4235270104, 498278423, 1233560634, 4293074805, 853780813, 1015040797, 3070872633, 2324941085, 3436613312, 2914604270, 3125537558, 1989275393, 2102765265, ], &[ 2411131391, 1285978457, 4193249971, 1729912476, 3951338248, 4289840260, 894016416, 2906952374, 3455712241, 1463845617, 1727541890, 1481030343, 1658748062, 1143697602, 3292965673, 2291275076, 3088692422, 2745736668, 4049914342, 1746048268, 398577563, 1528894241, ], &[ 2173999991, 2272873400, 2390524858, 1701140046, 320303811, 2196647430, 90814602, 3168314224, 2071538040, 267268559, 2660563785, ], false, &[ 3525126782, 1512399222, 2720117630, 206486370, 3387391711, 3483623607, 1368424417, 1794379685, 2200464811, 3921564486, 2468104993, 1989275393, 2102765265, ], ); // - q_len >= d_len test( &[ 2046213120, 118064180, 676462636, 192405947, 987595058, 3117257430, 2648701979, 3334098139, 2300211432, 238540576, 1839171291, 3761260665, 1016976338, 464138847, 2985769256, 4173218084, 198170535, 2181413355, ], &[ 3268984709, 3890178895, 3714425009, 922229459, 124979838, 1582051975, 1533234197, 1439049575, 1664144928, 3333243233, 508818207, 1681704030, 573822729, 1791263995, 978387652, 2703189437, 2825974585, 854916987, 2566023663, 1086830792, 2353550490, 2091798094, 2573588469, 1760161870, ], &[ 4063752152, 180981500, 1829379233, 4014641527, 2812579451, 2652403028, 1486280954, 2616093248, ], false, &[ 918482979, 147806120, 3245881243, 1658946288, 1766790068, 1379341579, 3971780904, 1671161699, 2162749536, 1257881574, 3103952931, 1923216828, 1012333274, 3304761773, 243084170, 2889743198, 198170535, 2181413355, ], ); // - highest_q first time test( &[ 2272242430, 2854406627, 1305900137, 1975858742, 4025222745, 212032770, 698550929, 632227880, 3284689006, 780673660, 395497962, 765997120, 2856842543, 2158993022, 20701243, 2016479159, 934398704, 1923839427, ], &[ 2079043963, 3911491338, 447442849, 3956113252, 1222080016, 639120617, 2598755724, 1080730341, 102550561, 3677835688, 4245198487, 1565695097, 2098176177, 3974320562, 1241514653, 856068310, 4158641647, 2053124989, 4149048308, 3508898669, 1748966969, 1026687354, 3392457811, 3901741824, 3279053517, 763547094, 1818065987, 2992419410, 2814961974, 3367454332, 1015324186, 3391900712, ], &[ 2456150337, 1126994408, 3067336229, 1544722288, 1285201687, 384279509, 1392445337, 548923399, 2471923537, 3222966094, 168537260, 3352071531, 2060967172, 2867808805, 1744855395, 2564913121, ], true, &[ 902145632, 1230897285, 1461544881, 3921469470, 3447138679, 4291295264, 3805913658, 2179953362, 3669599647, 3982542142, 3582166894, 852760370, 3665299175, 3877964992, 3092149152, 1384797257, 934398704, 1923839427, ], ); // - q_len_mod_d_len >= DC_DIV_QR_THRESHOLD // - hi < DC_DIV_QR_THRESHOLD in limbs_div_divide_and_conquer_approx_helper test( &[ 2108009976, 2838126990, 827008974, 4157613011, 3782799311, 839921672, 879731301, 1926496935, 3712149888, 2363043408, 3863476261, 1703718215, 499165670, 2993223230, 4279694017, 2976095205, 2193242813, 3593708162, 586354096, 296757650, 242624274, 199363552, 2802933005, 2759687879, 3925865458, 4217980786, 621040829, 4008464542, 3795907109, 270168250, 3625538473, 759155103, 3959828159, 1835721901, 1818377089, 114690984, 2967220963, 2377698568, 2241245638, 2252300906, 3116551983, 3644576818, 2608501946, 2181270779, 1815210824, 1268283136, 484429506, 1180516809, 559610343, 2543044915, 3719740023, 558939794, 3989231279, 1089033996, 3509826828, 3545449066, 3353643945, 2822587915, 2300900020, 309191900, 2371088678, 1169317833, 2688462322, 704882387, 1429447898, 2514029776, 1955158460, 3862686818, 1584130288, 482000750, 4224830364, 2104097699, 1183456674, 2270729014, 2607655660, 2966545947, 2931252595, 759652385, 3970839358, 2487392344, 1507124762, 758697388, 3840603988, 1293583672, 252424514, 646352064, 1756992845, 2309291248, 3392597937, 2946557682, 3659552460, 1720311830, 3395887210, 2674135679, 3196424053, 2895118562, 1256983146, 2482795730, 1922474903, 2105232035, 3692384401, 2891711374, 3496171341, 515080177, 4073860792, 2051799135, 2279442367, 3258846627, 70977295, 1937954703, 2800340027, 1760719187, 646417623, 3158839049, 3176203007, 213391749, 869819866, 3906922929, 1586646665, 1614123406, 3687984980, 1177302158, 272342927, 1441818617, 2083855650, 1541781406, 3311904586, 106907162, 4108429222, 662974012, 4140594255, 1984524179, 3259771450, 3863443649, 3307256449, 3597197635, 3771753969, 3551628070, 3550518548, 2546464879, 3812123817, 2299164636, 2258249267, 815945886, 3725185601, 738801212, 3862546442, 207778311, 1535617953, 2150997157, 729581295, 143725958, 1410055499, 4204574368, 2185442793, 3653861199, 1767186378, 3537808267, 1766021033, 2239408696, 1986025224, 3625288948, 4046347844, 2490523057, 3491861717, 1312039469, 597857291, 206880668, 1812928615, 3684502664, 3820772609, 1327777451, 1237379465, 764273090, 3594853086, 2859643842, 1243019386, 3444655918, 1596721727, 2221238575, 2483346164, 2064518283, 2282844430, 1960424205, 4028198846, 2342293800, 1645322170, 3508868511, 2376856302, 1764497492, 2461899059, 3430260828, 1083983032, 1448541077, 2081767380, 1131293272, 2121152826, 4212689224, 2039367869, 2193844060, 1864700761, 1182989130, 1481869846, 969270162, 3997775597, 1483663077, 394034269, 1586435653, 2281434261, 1937512315, 836935557, 59742568, 1854699653, 2116629465, 328821302, 1999851100, 604863759, 556389113, 2057620108, 1992554416, 427465103, 813735424, 487055225, 402647361, 3006998394, 2146302389, 2308517156, 1063328348, 2382344201, 2665908320, 481118926, 2376219143, 1164055989, 128362737, 2711666601, 1898018298, 2928344090, 3862251511, 749517272, 2790599579, 3506539103, 2592038317, 1682088920, 1332639030, 3053921374, 3066891587, 242466377, 3536065834, 2016487096, 1321862427, 2409873623, 3088797737, 2840818323, 2052021858, 4079299898, 452968540, 3880575723, 2680668784, 1502544423, 1619882634, 1068420458, 3236073318, 1740351058, 1183565882, 2761799103, 246817911, 2967032269, 4003972840, 969974269, 3193561842, 1002645557, 2347161653, 4272895273, 1522072178, 972383725, 3026624523, 434293193, 2855690795, 2455822196, 2413168892, 2999634230, 784531194, 249556803, 2559695464, 3131798530, 668810109, 2114036394, 2861740558, 370716909, 2126014070, 3913884200, 1577476936, 855642956, 2074597201, 3461659621, 3292762038, 2153122643, 1658901071, 1562860969, 501980289, 1611843440, 2433026108, 3791871978, ], &[ 2325147333, 1406197332, 1502532645, 137754493, 1488912421, 1014222449, 1678300831, 2078887154, 2311629707, 3855402290, 1904906031, 1350026944, 314061674, 919972212, 1429252796, 544807358, 2607111216, 3001219316, 160533550, 2875169678, 1402474615, 3234840532, 1662112023, 1943050521, 4132256985, 2915369430, 699620367, 59590583, 2461837586, 3986106860, 2659659366, 3589796255, 4168995860, 2337625655, 4292546333, 1793085295, 2647770730, 2871508164, 2660729400, 3630964395, 3874212033, 1240042620, 1713051992, 2105061240, 968807145, 3026819276, 2442427316, 2718248469, 2572140009, 1793916894, 2112926236, 1058005225, 1528978151, 98430379, 3348888463, 2121431457, 3545708238, 3975070402, 764453596, 192861224, 2698588322, 1493819664, 2502294971, 3139295505, 1318649192, 1552623529, 2989328476, 1592829691, 1175278450, 182489613, 1858350437, 2440903999, 1622786339, 162763913, 4106583944, 609833788, 1344925844, 3910333895, 1369398307, 51929280, 2214052160, 78601532, 642016948, 3966440550, 4161875340, 3764174238, 2944905670, 832634369, 2082700552, 3444794582, 962611192, 38510846, 2733538376, 2141542785, 621670923, 3130866640, 1666281368, 3628581169, 3965100367, 2889091703, 762371524, 3752935086, 656901001, 2374421435, 3084212494, 1186140919, 3420046356, 775236355, 1337865306, 2051118555, 713071112, 1946850844, 1427068060, 3949026319, 3075128554, 438166063, 3975561046, 858907746, 26964870, 3843362808, 1461820702, 3090970200, 1037540471, 289966660, 2768763862, 50890120, 580189324, 2911422550, 3684738914, 2025034397, 414622319, 2287243961, 3268939669, 3547523099, 4011963324, 1768695320, 1859343614, 2123856143, 4141054481, 765801396, 359993985, 3668605792, 3613648266, 1778728280, 2547397231, 2456061149, 2562918666, 2903450513, 1994190773, 99234624, 3722083920, 4262323306, 202219441, 4201857695, 3988878636, 1533308334, 401400520, 1069756554, 2457773969, 2892388936, 3423117995, 1944069442, 492036629, 3426800580, 2282483359, 4006366620, 1695364515, 2555180845, 1669287836, 349290429, 778467450, 2020203604, 2218159817, 1450404019, 1278304750, 2412695340, 1592154884, 3868182043, 2240370481, 3859902860, 1008825116, 412233394, 2475457637, 3664379433, 4204584226, 2750684469, 4113507475, 2916584959, 285955744, 739598569, 18278051, 3768126932, 2181905109, 2612988076, 1827656088, 1160380415, 4160443718, 1846086671, 3050604645, 2547108010, 2828666778, 3252702258, 3885923576, 2331974758, 730724707, 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, 3428792463, 2896462048, 2985885576, 1819460734, 21206096, 3560441846, 987100555, 2844904275, 84854892, 1268249628, 3963306788, 3338670067, 2504599089, 65588657, 321493327, 4249673617, 4150876068, 721566898, 2186945060, 922948272, 1502464627, 1426914435, 2906888275, 3454987739, 2609132626, 2073366782, 1058809001, 1226951003, 2624503637, 282722778, 1407178266, 3304346308, 3613017687, 2397594777, 161128076, 1938083248, 3042822216, 3958145306, 1431161184, 4147630074, 1744618540, 3729847703, 2366216428, 2101731625, 2812677939, 3587016062, 1626785569, 3117017254, 3720581461, 4254564252, 2400911475, 750362271, 3062375802, 2182368701, 268751862, 2682134876, 274793576, 2417658182, 2321240923, 4200603818, 1349142841, 4066976957, 1043247680, 679021323, 2933095037, 1621487581, 225868669, 1030678959, 1236344244, 972640788, 1784301152, 578117349, 3509551550, 214420003, 3786992737, 802372148, 3562194086, 2187046946, 3600373521, 4275090943, 2120016813, 4177241875, 3185774231, 2397692077, 1015362399, 2178889151, 3433916223, 1688082118, 1971242178, 236388706, 3802829765, 521309115, 2299816689, 3207614143, 1053195464, 3584561145, 1178690670, 2940812254, 3321982035, 2754825123, 3073598062, 202404806, 547895545, 1188944547, 1056841779, 529463805, 204665384, 850370055, 2063320161, 3724100092, 1180272690, 1398467003, 2814052449, 1311768018, 659771105, 3226477227, 4230080238, 2134344405, 1461172705, 2728018383, 1816821358, 3231137250, 2012377728, 2206916761, 3121807673, 3037967028, 3653505029, 4164239058, 1337501466, 2487452346, 428839025, 3321493092, 2920064796, 2750126813, 3635762100, 2659829309, 1992243088, 2359420187, 861816585, 4182313312, 1389528266, 2890138969, 2195001695, 576635805, 1974585967, 851480113, 1896534852, 3143828462, 4276040597, 3921135859, 2394233682, 2692972118, 2103941456, 3931376544, 3790764632, 2278428793, 3381340311, 3516241824, 2923157557, 1276268033, 3471729699, 2370137091, 2637023305, 4027814477, 3711009696, 3667995314, 459819000, 1002878772, 2658190707, 1189561796, 1831813150, 2874008201, ], &[ 1703326352, 1625259628, 3642322228, 911402341, 2158835226, 939248485, 3607511108, 2863853568, 1611642161, 1312857772, 1839433327, 567060478, 3139863681, 3642698184, 3744632443, 712538472, 2692932947, 576185818, 156934113, 518107105, 2803035863, 2284220097, 3447382922, 2400125006, 3565062840, 160044186, 3644393084, 4196433258, 3391883838, 1115703759, 2380388002, 962895870, 4001772616, 2311278419, 2620271020, 3047789793, 3229254302, 3182628087, 2718480927, 2872538422, 1963990826, 2856537226, 1729736384, 372544200, 1482170753, 3370665422, 305555060, 4060802437, 1456459795, 2848113958, 1036273297, 3245835346, 3355862097, 3242734427, 3313897419, 4230036415, 1425594704, 2428756491, 420147714, 3218149930, 1791217142, 2881741659, 3231612869, 845372829, 1635665046, 1525482197, 3779462557, 2279005731, 626908159, 2963734610, 215448882, 2517668355, 3294128769, 1167990371, 2344651228, 2882002195, 3350056381, 3749638142, 476010196, 2304276366, 1088082897, 1927672185, 3316329053, 1174989749, 1101596429, 3054511229, 1685228241, 2301284206, 2526016461, 684171580, 3869889559, 2606492401, 2114658735, 1419214215, 2779052449, 2594333668, 2225446358, 1211258458, 4029343999, 2816277230, 4098142949, 1987363952, 2732004911, 2516355975, 2365350298, 1747416524, 3951513077, 3526462790, ], false, &[ 1303670916, 3965736473, 654490008, 3337248200, 112312312, 2506678400, 713192736, 901474194, 2359721047, 1133557120, 3068598661, 3136858413, 4095957211, 3057328754, 1900588230, 1315930687, 3273808327, 2821746043, 4255148500, 3072995291, 1472014781, 922081554, 1759317078, 149072645, 2712091402, 2134310281, 708105323, 3703209145, 2071594694, 8111834, 3766831226, 2182956891, 2525476614, 1478202223, 4199311113, 3813148212, 316780911, 1396844257, 2321402831, 1151134318, 848673799, 735789140, 1092813310, 738412079, 1895091662, 2947844274, 31103395, 2559694049, 1194304023, 3260126654, 1118043028, 1552558623, 3016599055, 1053142289, 446041643, 2615854004, 2105823819, 3769707039, 2784177611, 9564629, 580911617, 1979035813, 1479556681, 2599744262, 3097426153, 4195176293, 3497554127, 3484306250, 2114827319, 2314051712, 1210812068, 4158781103, 478301760, 2027533091, 1682020897, 129914624, 2066167843, 3989890251, 1378700448, 170057876, 3992582209, 1541347967, 3421610776, 697014638, 2834243941, 3504973679, 630519426, 1551901326, 3092678418, 1136389639, 1806538485, 2208151411, 1598302001, 4041410193, 3574334276, 2340664244, 1624426425, 1200740723, 2912910258, 671197404, 2272603994, 909857936, 792804858, 3083891114, 3143045405, 2389563439, 115312858, 1445242760, 2065820105, 256586994, 1432132569, 1549619424, 2631865338, 1674212272, 2599765330, 3713129178, 1590556325, 3610491293, 709987753, 3230113618, 1606099993, 3453954266, 3501213811, 3278809492, 3770342657, 1534951916, 1366321311, 3149479124, 3987513652, 2108936446, 1162972378, 279205823, 3711325879, 2278557694, 2305274058, 3709507652, 3805940202, 3778288085, 1061153771, 491180471, 479623642, 2960728114, 553156023, 1863065855, 2253455830, 14222934, 2488687289, 3378176628, 1136227234, 3805644784, 3175842224, 463501844, 2100687360, 2025076951, 4064921772, 1000043802, 2482142143, 1463585061, 1044328896, 3966669663, 1023595412, 2689537057, 685044345, 2599439954, 3302022962, 2669841238, 3358991646, 351579450, 2303934592, 2098132645, 2239011851, 1623838039, 790570033, 2288992150, 2252675624, 2479618080, 3624986625, 2129338944, 3796999988, 465518072, 620957443, 1836556967, 2894771224, 2904933718, 287211723, 1386209013, 2288387719, 162551270, 370319691, 2924564913, 2947669880, 3390862854, 1797811, 3097227838, 2245950593, 1664498395, 3380635348, 3536484871, 1217287925, 3149066538, 154911037, 1960867817, 4238493382, 1991791660, 509572665, 3386968719, 3880405816, 2335816696, 2519967410, 3482574698, 1501302597, 2415671279, 715902305, 1920401004, 3735445496, 1792155851, 2110622431, 3695395614, 3311496726, 4035668560, 187609524, 3743601469, 2990357125, 3084998227, 767424914, 1388627321, 1381810466, 3799640235, 1423360242, 3375037167, 979951340, 3463933333, 387599460, 229837304, 1394766077, 1068156038, 1135935924, 86516134, 142150630, 448211640, 3205606056, 1420159909, 4203558153, 2816235778, 4188064475, 1490981561, 2934083684, 2693435736, 1351552613, 962789901, 1071201732, 3244341475, 1855681940, 4210620238, 2129345127, 2909949483, 3992748944, 3928807766, 2014533910, 3099391001, 3112195816, 4009296318, 1247610431, 1474512546, 2530880557, 3597268331, 764359883, 4198267775, 1228639730, 736768887, 396797847, 799410613, 582496441, 2658423343, 1643853660, 1258585041, 3767032705, 3709454541, 892807168, 1443895160, 3500326521, 784531194, 249556803, 2559695464, 3131798530, 668810109, 2114036394, 2861740558, 370716909, 2126014070, 3913884200, 1577476936, 855642956, 2074597201, 3461659621, 3292762038, 2153122643, 1658901071, 1562860969, 501980289, 1611843440, 2433026108, 3791871978, ], ); // - q_len >= DC_DIVAPPR_Q_THRESHOLD test( &[ 1253234102, 1407423154, 1496099965, 1695523232, 4087895045, 3633064637, 1918073940, 1994089224, 2894393019, 3803250781, 3557289532, 855915119, 825886212, 2854426287, 3305239731, 1558916547, 14680883, 2283482810, 1975429241, 3696056256, 1225143894, 401826166, 1805660989, 1715696159, 3407333066, 671337274, 3930782284, 615690969, 1799309743, 3261619710, 2139755586, 1418298860, 1130149390, 2049944334, 3646689909, 3742182516, 3450706114, 1620481751, 911179844, 2537827243, 1863349000, 2588289405, 1379393302, 290595733, 3551967170, 597631845, 3116406696, 418522057, 3052889123, 3602625940, 282818149, 870470676, 2360142740, 122311196, 1285732945, 3338688058, 2358904627, 1717417860, 1010819896, 1162692117, 745279285, 2988897615, 3882583107, 1500499444, 868916372, 1937848809, 1694462512, 3596830383, 3102959500, 2042575803, 1732232437, 2619341801, 1399365095, 1742239855, 3363053286, 2955047192, 2536114731, 797861027, 3390102223, 1284755330, 1346331125, 3841540834, 224493549, 3323242612, 1489837409, 424629037, 2887418470, 2691856116, 51264601, 1998453260, 3606432589, 270475934, 1351120072, 13779558, 1467138526, 1834087227, 4205762576, 1570218025, 3941564310, 1908199096, 4049815285, 3522198110, 1100468986, 2461406603, 2479269826, 536560408, 3804672262, 4126365829, 495636874, 1441896026, 1313080761, 3619143141, 3430175499, 1671147767, 461789206, 1605289369, 3711914422, 3538203337, 2188319161, 3278799759, 3020736936, 3471537210, 399986340, 1968814758, 969264551, 3530350534, 1969502380, 147661179, 3137298512, 1364101497, 1404388912, 1303215423, 2286919520, 3249572742, 3330831913, 3586493901, 3162077775, 2991387015, 3706115087, 169578752, 1159180539, 3934133734, 558035602, 2925779959, 4063767692, 2885217884, 2752907569, 1140725464, 749603258, 672416514, 1032385258, 3864779512, 3712562196, 3208066496, 2643074326, 3543548657, 3720627664, 632092389, 1636851426, 594140763, 69489824, 2777250607, 2306083065, 3916911258, 3141155998, 1993475481, 68784498, 1770067486, 1998044447, 2520569326, 1992263322, 3101331801, 140848189, 3764741027, 1978515439, 2361982733, 3127443736, 2897381492, 1302677523, 887097058, 1952041780, 783608822, 1097624715, 99755829, 536819342, 2899797741, 3314381803, 4190434837, 928227057, 3989607704, 3914272902, 3196195572, 1073079639, 3400734903, 3946657062, 3174732283, 2855002505, 1996931952, 2245019261, 2712989234, 1251678454, 578021470, 933525407, 1735185706, 3242693894, 757877465, 1570544476, 4054554610, 4232789, 1769248079, 3386476948, 1651095046, 1722645365, 3742083849, 249564447, 260470985, 926270254, 1849290911, 936613977, 2807355918, 799601174, 2973430993, 3630517123, 1010630102, 1596332202, 3693726207, 2696180764, 256508517, 2935861013, 2617574366, 2142295104, 1294973507, 4038702029, 3944607195, 3841990618, 98499149, 876432870, 2276059480, 2682515232, 633274451, 3670159674, 2039570585, 3672264107, 3435333464, 722344600, 590278704, 3403124564, 2414477570, 3921713319, 2561609021, 966607910, 3391894575, 1125597344, 1769874536, 1258228103, 1862948975, 3973133769, 2533256421, 88292560, 2813190491, 3533833187, 413327252, 3841705126, 2608177858, 3676328284, 2614193419, 2483046806, 692717429, 3846808159, 379277707, 1669205079, 4233020303, 1294972508, 3928564917, 2407908590, 744791264, 3255079725, 3753322493, 472420344, 1166843119, 2467000669, 4140405991, 623716212, 1139273119, 3354207202, 2025876056, 1890550355, 3308875843, 4187315065, 568191796, 1415565133, 2687244643, 2241676607, 2580202219, 1708640561, 390914458, 3510831086, 1856289438, 1473240478, 2516164037, 56978641, 4018676274, 948004161, 2713281743, 1119094116, 1836707971, 65506862, 2266057879, 3850031360, 2402902235, 1355795078, 3048720123, 3936358528, 764696513, 3500940987, 3117850578, 3798438683, 4211733833, 972363431, 1880167313, 253714622, 76302969, 2144921929, 594588250, 3419391407, 110436200, 3019984992, 1696068166, 1311459144, 383767145, 4278876264, 1806767552, 478592754, 3307398109, 2106194092, 1374406895, 512715289, 2870580756, 1992431788, 63343676, 697633985, 890054481, 1959129172, 2577805590, 2764027866, 2020028848, 3876787343, ], &[ 861890943, 516245383, 733102822, 3373234349, 110977034, 4271239715, 1739646310, 3430038451, 2971068856, 1353792561, 273988221, 3727621506, 1880644317, 1169807252, 2221765190, 645570626, 1827088960, 1940915885, 4161457279, 3100425720, 996251533, 95565099, 1073046961, 2253764580, 2391616729, 3098700232, 106646536, 853783579, 1589281984, 1966496578, 2971444515, 4208062631, 3919529557, 3375641417, 1678790027, 3548362465, 4197401264, 4152189205, 2578742796, 2352527389, 1289840774, 383594740, 604487604, 3605617314, 1576995811, 2410149432, 990820085, 2546262411, 2154758716, 618380381, 2206847289, 3469453827, 1341806652, 1019433523, 152426111, 2749431433, 3607895359, 3011391435, 1478694163, 851990590, 1027992752, 1059272616, 3480493466, 1488043252, 1392852266, 3113620249, 4146237371, 2130545233, 3935615262, 1894052325, 3086808567, 1407836003, 3747705872, 2582628925, 4262889138, 874765444, 2961363842, 680545553, 2488989749, 3345785826, 952704427, 4098093425, 2516922879, 211154154, 1759131069, 1700311172, 2393378850, 189990019, 3378862840, 1411934279, 4058568121, 2905294981, 3913230880, 3855904011, 1536608211, 4114811350, 387292488, 691407511, 2360232735, 1725740094, 50400678, 3408982759, 2861477438, 2945536307, 3193284782, 2711749342, 658984109, 343184872, 1067289865, 2232608224, 4027855946, 3835625791, 3914871156, 3647728511, 2766962294, 1158831068, 1928020015, 1802324187, 1465396891, 2797410329, 3693678708, 1474899877, 1451659497, 2793780175, 3408416157, 698362941, 1638711078, 2942583266, 3345553229, 3337125778, 3898736345, 3233933201, 2121187878, 1375122421, 216315377, 285271552, 153543683, 3787450620, 18426473, 2074179790, 3707951065, 4276245641, 3503168626, 1741007520, 46035775, 1938996412, 2285217270, 1291171645, 4224874181, 602464202, 1803057980, 3577626393, 355587957, 3077316668, 2374221701, 2965264159, 1074621373, 4162088640, 2550826771, 2808953809, 1252092668, 3357187794, 476206830, 3584460445, 4065428738, 633814711, 2880883917, 3884516376, 1513164555, 3300578942, 1670837060, 1132213662, 3351202257, 2610012791, 3257259539, 3160483911, 2266079247, 868822128, 4250370567, 1331943301, 1945818535, 1393345318, 2060415706, 908741824, 4156794744, 2564813613, 905212060, 3218738129, 3262255881, 2263542766, 1227381935, 3663658012, 2226973450, 4231561520, 2818168164, 2670361969, 3318293987, 725644295, 4019758576, 998642393, 495827676, 3734906270, 549931550, 3628965188, 3223395992, 3590294271, 449855696, 1500765851, 2275616292, 2735068879, 2797134520, 2639621186, 4044997105, 3174110149, 13220550, 3092556343, 1435605571, 3386705521, 3831842284, 3500054590, 812912044, 2329469982, 1723309995, 2307452017, 3303104792, 309903689, 2189249934, 3636229896, 1168371322, 2203364016, 56316585, 1507047047, 3978350651, 1287006021, 4136822779, 1754090185, 2908593163, 1172296646, 1218980475, 2947600132, 2403727272, 1587640760, 1122215884, 54808095, 1625907344, 3722900656, 845603689, 1328648304, 1556638437, 3283968864, 3011502249, 112044910, 3596114169, 1850965401, 272070320, 1659402803, 3430852231, 4069438789, 2244303862, 651616701, 2182731301, 636443810, 1069166894, 1406346119, 749190002, 1954541375, 1807738880, 1450920040, 3158039132, 825986184, 4212536016, 1808707022, 2850318233, 429694363, 4071098452, 1248651330, 2275666509, 838162196, 1424879694, 776592838, 2740483790, 1284163517, 1280694131, 1134770642, 2077202374, 1206292163, 1284319127, 4184450872, 562093874, 952059065, 2799693572, 565666121, 156186725, 2849625182, 1184911783, 1502520806, 633585326, 3853907607, 2739083441, 1951262688, 103314579, 3831503747, 2993941865, 2470035934, 1778816965, 3674359762, 2878370279, 1350386433, 2408142731, 3015205620, 3043051127, 1655111158, 3773182311, 3910770118, 2947352886, 3356936393, 2844618418, 3298179444, 1279762744, 2973165223, 1721543619, 4040357913, 2673457267, 2733636953, 3004389294, 2106808579, 466071136, 2720455489, 900027010, 3351752905, 386568249, 3758644029, 66397961, 2459306698, 2672898173, 1655443171, 3369301491, 1855362811, 1446321007, 2158536501, 1872565755, 3914900675, 1397039644, 13190889, 514173561, 931870314, 594435363, 1526203696, 2400586492, 2299132127, 2876601263, 565427241, 1381196042, 2872681002, 3103160824, 405911440, 954740851, 675181390, 2686349099, 4136963415, 4220549550, 2370055970, 3163147061, 4154464526, 3976152950, 3281076036, 2145465814, 1952261737, 850385895, 4035222541, 4292853188, 187378739, 146395110, 3997223188, 2808707041, 983334910, 2236221581, 1884459573, 2703940487, 4077202970, 3803155817, 1872492268, 2837348007, 3074452453, 479001365, 3913048191, 3515475086, 4132420828, 3086255747, 4198950954, 3294929815, 811732388, 2548414145, 1396214061, 2394099307, 4068762174, 526147562, 1076045316, 1123992450, 3733570622, 4220579043, 889069266, 2894360531, 1971615205, 2766482958, 4265953201, 2973723720, 3986781638, 529293577, 1884138947, 510069540, 1743552552, 812713578, ], &[ 2625866541, 2810579078, 3501644219, 2416714925, 1291740196, 3660307741, 2609642196, 2505392144, 1722898427, 1674316556, 1432469984, 4097335408, 3108223053, 1374639232, 1851930259, 893716755, 2663933335, 1737930775, 3657985359, 3660388910, 2695083669, 3386383098, 267519188, 3888348035, 1835595210, 2613536126, 4114884836, 2142604605, 8565287, 1755951705, 4130425802, 2850158056, 2234922350, 1949213237, 2449412937, 1402509673, 3986161632, 1988171673, 4272507706, 3260139743, 1807943254, 2734619085, 740216746, 446923648, 1965334425, 3397454741, 809048263, 494222614, 1484571594, 3636917813, 1079987980, 3243842717, 3971186898, 338155234, 863804008, 1792493616, 2522062802, 3816014339, 2741664304, 222474042, 154928734, 2936845361, 1353872451, 3808072940, 334383012, 1793621170, 2698841688, 3751625796, 3312001535, 1308411945, 2231283256, 3335332368, 2732745501, 2266806470, 383612527, 3711228074, 2478058102, 2078994051, 975470800, 4179961686, 2605205960, 4060526006, 2648539390, 992385227, 1710490965, 385423846, 824778193, 2349766631, 1760192209, 489319807, 2127640163, 339639147, 2672582271, 1527261122, 3929636146, 3273385907, 51468511, 4261991464, 1868351312, 413372128, 1083615978, 2931924886, 3886667243, 2763475974, 2738582447, 2397672301, 2259776571, 2115277994, 2148277873, 2696639925, 1519841204, 811678952, 628203566, 2552032086, 4011447443, 3160851596, 258941070, 1535778333, 4063703767, 1926535070, 303663750, 2997548738, 1835822843, 2093980860, 1428491141, 3798948389, 462487877, 2937763495, 3558060512, 87869235, 3064605488, 295532817, 92123524, 2923122754, 569558082, 310878410, 2667249293, 1502523772, 700589809, 402354610, 1860279993, 748794047, 3648640215, 3110702404, 2258574876, 2773396367, 3517237080, 2990861341, 331348076, 1212514551, 962158293, 1191845582, 2112876079, 2501772177, 2831655935, 3995296179, 3011183472, 4288287857, 3132719253, 1897663845, 2153050331, 3461291371, 57799706, 461541578, 1483239302, 28451101, 895953744, 3368918207, 2594694002, 1268319513, 973441686, 3311571754, 2019274316, 4123248452, 1446014889, 1417571585, 615477194, 2194462687, 1708163105, 3293326615, 3383426484, 606654074, 1070117839, 630146344, 2571257218, 3961968468, 1929710282, 1868034367, 403216466, 3088416046, 449849638, 443975756, 1551823500, 3682150448, 3283842757, 4232686157, 4164057310, 2186087032, 2166995410, 3181021883, 3318208525, 2768887999, 2877385605, 469197960, 363931824, 752117713, 3980786726, 4244751154, 3858512024, 4033177219, 3536702242, 3001143104, 1049662321, 4154276130, 2710845384, 1882050975, 2307442635, 2303006043, 1063921606, 92351540, 1383930617, 3560089905, 2221914576, 3599852592, 2796496568, 2234040425, 3492209128, 469541171, 919249352, 4275860868, 3002397499, ], false, &[ 3585575447, 3122160444, 2645674960, 4091549360, 626365202, 1144617016, 3462810264, 127827394, 3154238169, 3508098827, 4065321164, 2627720920, 3399886577, 3188051673, 1639089029, 2016161381, 1581970985, 237731508, 3479558677, 1944880307, 2562503556, 1795700699, 2609445006, 1116190050, 1146777337, 1200401433, 1157695328, 350844679, 3282708071, 2845229536, 459139289, 3375883464, 2424175740, 3193435758, 432712800, 3851580195, 993388507, 3458606683, 3233513818, 1868436357, 1353535090, 1991321983, 1598253594, 3580022384, 1800608735, 3030838485, 1479344427, 2146117321, 3615628302, 1468724143, 2513216309, 2478400520, 1881309170, 3573465816, 191069649, 2319303987, 36912024, 1056835502, 4085803346, 2567638548, 3614176540, 1774136604, 2502728501, 2178987690, 2079375302, 2975418245, 761382377, 3364876440, 3617579499, 1451615440, 3143305641, 2435105671, 2844406164, 1247246351, 894541250, 3633445851, 214286649, 1891108578, 2579284088, 307573789, 3098902942, 2276329990, 3682940322, 2840709312, 3778212298, 2325451725, 3477808517, 31838273, 2670981675, 2270297375, 465284332, 2697844185, 2622424439, 4051875556, 814914907, 2448623943, 1299744713, 1873124502, 2036773577, 3689282510, 975141741, 1207881273, 2818435693, 3863231130, 3098155233, 3073113139, 1724416932, 774815313, 3984444108, 1380084993, 825030359, 1705088193, 124122371, 3659155851, 2518826336, 528672560, 2665679696, 1402818456, 782001915, 871778931, 2353626471, 685023982, 1884443856, 4156627926, 64651699, 1586126662, 1522765556, 3831765770, 3303426700, 2833111857, 928056991, 1307034056, 3386313127, 3415959770, 3498516705, 1932766589, 2313751714, 366206234, 3192561873, 2943917337, 1140687467, 1640175340, 3542041198, 2895665827, 154126416, 650854034, 2789160074, 352460908, 1351655152, 1980048568, 2172281721, 3543770557, 2365332223, 35300985, 1050292927, 1349692310, 270125821, 2579494270, 3106522063, 4229421146, 471231049, 13349434, 2438602373, 1915124258, 2193214542, 3087834620, 276889911, 2493806637, 2402232776, 556133444, 1874277037, 1783512114, 1442646686, 949037422, 4233276648, 1359566262, 564784663, 939635477, 1679428216, 2650897503, 1481863691, 1162596971, 1097624715, 99755829, 536819342, 2899797741, 3314381803, 4190434837, 928227057, 3989607704, 3914272902, 3196195572, 1073079639, 3400734903, 3946657062, 3174732283, 2855002505, 1996931952, 2245019261, 2712989234, 1251678454, 578021470, 933525407, 1735185706, 3242693894, 757877465, 1570544476, 4054554610, 4232789, 1769248079, 3386476948, 1651095046, 1722645365, 3742083849, 249564447, 260470985, 926270254, 1849290911, 936613977, 2807355918, 799601174, 2973430993, 3630517123, 1010630102, 1596332202, 3693726207, 2696180764, 256508517, 2935861013, 2617574366, 2142295104, 1294973507, 4038702029, 3944607195, 3841990618, 98499149, 876432870, 2276059480, 2682515232, 633274451, 3670159674, 2039570585, 3672264107, 3435333464, 722344600, 590278704, 3403124564, 2414477570, 3921713319, 2561609021, 966607910, 3391894575, 1125597344, 1769874536, 1258228103, 1862948975, 3973133769, 2533256421, 88292560, 2813190491, 3533833187, 413327252, 3841705126, 2608177858, 3676328284, 2614193419, 2483046806, 692717429, 3846808159, 379277707, 1669205079, 4233020303, 1294972508, 3928564917, 2407908590, 744791264, 3255079725, 3753322493, 472420344, 1166843119, 2467000669, 4140405991, 623716212, 1139273119, 3354207202, 2025876056, 1890550355, 3308875843, 4187315065, 568191796, 1415565133, 2687244643, 2241676607, 2580202219, 1708640561, 390914458, 3510831086, 1856289438, 1473240478, 2516164037, 56978641, 4018676274, 948004161, 2713281743, 1119094116, 1836707971, 65506862, 2266057879, 3850031360, 2402902235, 1355795078, 3048720123, 3936358528, 764696513, 3500940987, 3117850578, 3798438683, 4211733833, 972363431, 1880167313, 253714622, 76302969, 2144921929, 594588250, 3419391407, 110436200, 3019984992, 1696068166, 1311459144, 383767145, 4278876264, 1806767552, 478592754, 3307398109, 2106194092, 1374406895, 512715289, 2870580756, 1992431788, 63343676, 697633985, 890054481, 1959129172, 2577805590, 2764027866, 2020028848, 3876787343, ], ); // - highest_q in limbs_div_divide_and_conquer_approx_helper test( &[ 2317066713, 3734873775, 217584598, 4283181214, 1987296898, 2029964730, 2841877055, 215692782, 869134407, 874390362, 2208433375, 645289786, 1962123143, 1210019992, 392208793, 479186599, 1403346326, 3121890550, 21351539, 1792046631, 1830759088, 3009702825, 2064264407, 1425980591, 2915380046, 2661484230, 272407717, 4286945194, 649139597, 3925921591, 1081687841, 2923866665, 563140201, 1426204510, 3994415326, 2030662828, 2060697960, 3056670310, 1609787794, 792934567, 2717771124, 4164322768, 3913458892, 2759459876, 4091351278, 1717819380, 1097243558, 2147464721, 1228826351, 3209546368, 1237764046, 1059356034, 2760411795, 3026477323, 624675850, 3763684075, 3540407970, 1913722572, 262369959, 2180102174, 3425380260, 1174673633, 158169541, 2382293449, 812030319, 3239921986, 484642353, 2919528753, 1658419979, 366878628, 1718980142, 799549350, 4285110305, 2715036325, 2455015536, 3032041112, 2735249018, 3310370605, 1181357276, 146624587, 3299107633, 1004501470, 3484807107, 1748985025, 1773700707, 1386223716, 4087630817, 750649422, 3611015842, 3444400533, 3725662389, 1109727693, 3037130634, 624478673, 633583116, 2378434635, 2687240280, 2673870544, 324343858, 731297615, 3614185356, 495482604, 715462793, 3367457094, 2135162069, 2612684285, 1189448323, 3887861594, 1345391741, 3430076735, 1913449259, 4268745212, 3848733916, 1785626124, 3506024858, 1223431612, 3120693480, 3802248189, 2144116453, 557985986, 2604607267, 1018386624, 2418517078, 2442250784, 3582497470, 654976641, 2599906378, 2211771862, 4102664307, 836270496, 4128006488, 2260892, 277275779, 535619372, 1868873131, 749436370, 1849951520, 783534973, 2957791640, 1636965908, 1156916684, 3732442514, 2251346101, 2723065991, 3717891339, 2525911896, 3076617154, 3265371035, 3292658676, 409114969, 4086635237, 3264336755, 2836953044, 3037161740, 3543275191, 585786355, 3087011769, 2185871252, 2541194926, 2224439978, 3412364477, 1350015989, 1311332023, 758561683, 4108017253, 4204509134, 4157141131, 1893317202, 1224082165, 880878665, 1834575916, 2572831131, 2631286660, 2578509166, 2240326536, 2609750355, 2798227847, 1197386254, 807604908, 1802810117, 2881797181, 3334708065, 3583310868, 3599155312, 183678286, 3236382667, 4125313765, 239427309, 3653131096, 494732271, 3893107141, 1018082495, 1979944519, 4044560358, 4179896605, 3780149973, 3875190427, 3114449657, 3457335347, 2339734261, 2616033966, 1329204235, 1248786560, 3467382161, 3028029914, 2536952877, 194748555, 241512194, 3260227272, 2858189566, 3881365161, 36968705, 581216076, 4188186728, 2833747030, 1972266392, 1374287701, 3058853674, 4101868185, 3030432843, 3731159238, 3617181750, 1742674464, 3668849596, 412040791, 406334378, 502702971, 2540238946, 2391871283, 1851296773, 2979189987, 199738981, 3379464313, 2875483565, 2404227424, 2501388469, 2789274764, 2515008836, 3408871507, 4145552682, 2991097752, 2338096504, 2325133139, 2082275255, 2834180247, 537432099, 1257296228, 3446712843, 39458827, 2174956861, 3039757037, 4157335831, 733488951, 2064219555, 1158696763, 1747438019, 1904327490, 2069625042, 3220261644, 2535390409, 1866459831, 3174902084, 3763763466, 711704437, 3941981941, 3947689731, 545125868, 199321616, 195433751, 587082201, 1623079028, 3583449493, 4189372053, 656157970, 4065268173, 2321947633, 4117128060, 1042761195, 543619922, 4200179141, 2194761475, 878960867, 3598234187, 3791350851, 346665711, 1360737771, 1930187385, 2405900037, 3062309031, 2085261831, 707121842, 3173108868, 503413591, 73514434, ], &[ 1172385474, 2722128840, 3229943889, 318467582, 1270391003, 1178663423, 1974716983, 3282704963, 3178774681, 3202829277, 3946239996, 2183661896, 756303666, 3877972989, 4251016295, 3386638802, 4082864246, 2928113767, 1526526769, 2729531320, 933752600, 3559448071, 3782798998, 249483043, 1511243361, 3564728022, 1594495334, 71444771, 3603995676, 816918005, 1243632828, 1550377419, 1008068857, 2948396814, 2093904319, 2147043689, 2566638926, 1425327657, 1162199945, 2960758893, 4198224, 2356436749, 3424929725, 1080768275, 209858098, 113302786, 3443677754, 3549677964, 3154318213, 3154103315, 1582401507, 3617714568, 2767982074, 3761726254, 683939930, 192236320, 1080891479, 1143174553, 2075266572, 1844075493, 3593156363, 1292478494, 1945353284, 1251725895, 142445996, 3777493501, 3614227130, 2589877580, 1660324871, 652913311, 2513923073, 104713426, 2880864765, 717044714, 2176657233, 3162919827, 1461924303, 1335307283, 1089899112, 1463447432, 4286236462, 538631465, 1843988250, 978544087, 215501900, 93216142, 2947050139, 2693646353, 4213675869, 3765139921, 320058937, 1970573977, 43732280, 1873575176, 1055975473, 3361081513, 4080049587, 2593310713, 2546627943, 348433615, 2711034081, 1213059756, 3994279311, 2969515716, 3962824055, 498958294, 3283335149, 2727270461, 967722336, 1011867961, 3277768890, 1239567734, 2615827582, 3138350967, 1983810667, 1258771837, 156352868, 3459871732, 3838966901, 1926475715, 2906860513, 2265591974, 739992556, 4097548896, 4063110249, 2614816895, 3485800367, 2745680040, 1081661573, 739066934, 1373973331, 1210644481, 2279017196, 1005551928, 2040599086, 2689171110, 2107331398, 4229586067, 3246733336, 1653467821, 3803759079, 1396785958, 744631377, 2218132207, 655573009, 2223316795, 2924583188, 3561375837, 949662445, 1302891749, 1031980062, 864295262, 2438572862, 1504001412, 933269347, 1253638591, 1534271622, 2530288971, 3587024017, 4130814425, 2573905811, 2785603748, 3552056080, 4244335838, 1333943369, 2283588299, 2119292262, 1681201617, 3442164059, 1894009073, 2739198217, 1409299279, 3436643841, 1088847721, 837995626, 1423764787, 3020531343, 4051404125, 618735582, 2571970479, 3106734771, 2404302700, 1055667736, 397025181, 252340965, 1296678038, 512661010, 963140047, 1161844858, 3862111880, 964139113, 3914454392, 2517045255, 3547177225, 2645896340, 2943432060, 4173143499, 48482790, 1022192902, 500159282, 3637285006, 1101744863, 2363750224, 312625286, 3984163509, 3118100618, 2790609658, 2907841435, 1239943712, 2072088288, 159276689, 3267720981, 2856806276, 102734665, 3390376688, 3378951761, 975939361, 454652442, 1925083628, 2151124106, 1307480526, 3774198893, 3018272285, 272747408, 1016277798, 3605470575, 531634579, 2961498249, 821488395, 3558633824, 2912444276, 1657117175, 2153161136, 1884360710, 721291427, 1531829639, 4115435659, 4254348147, 1506441630, 4046066015, 556451623, 3337814584, 1018537690, 555628783, 1620746271, 2482837019, 3679282774, 2426930864, 2632326440, 2327928883, 2353267828, 3481986297, 2112160697, 1022061657, 758309560, 2644660892, 907838024, 1498392732, 528384055, 1202823703, 1890604888, 1949099119, 3063001275, 685428701, 1780107085, 2619180751, 2954672471, 2283259797, 1374458453, 1565978557, 1093442961, 3891637052, 780517054, 503083440, 1375890406, 1386889110, 4237816737, 249672267, 828386282, 1163719531, 132139434, 391942771, 1096514028, 3006936950, 2283483449, 1662382851, 3602503245, 4242261323, 2784647410, 2828350825, 1288023746, 1017072535, 2006783410, 122598670, 1977168703, 4075238695, 1691129759, 2007296448, 1519044036, 1701991670, 1153128956, 1512900449, 1261204616, 2927982361, 1657752895, 139288437, 140564828, 100283802, 3070382516, 4089107340, 191147528, 1712401819, 391845701, 1540517289, 1700899625, 1477882518, 755000874, 480418626, 588196749, 400809532, 2485933533, 2888628826, 332783138, 3009527268, 3784829804, 2922060404, 2516820570, 2217403977, 2521013993, 2614722986, 3779307621, 317006621, 1733129556, 1267545638, 3033328419, 2185074347, 2126485254, 1990828725, 1034359217, 3945891523, 3588995366, 246414315, 2407783722, 1985580187, 2106721825, 35659189, 204134384, 203035567, 2650819784, 3097513541, 195622280, 620515605, 2016439173, 304017649, 1791577127, 1576105034, 3535138410, 3637374201, 3626803115, 1214754525, 1611339531, 1762283227, 2759574029, 32271764, 2702968983, 1516226210, 160223584, 3507738999, 146234417, 2990154579, 1436112035, 1948173615, 3890958043, 1222277581, 1349923980, 506218124, 1577016965, 3229129980, 3912753236, 233704342, 1219563141, 429930162, 2006881030, 3328217266, 3101601662, 3008827607, 3114439162, 4169647780, 2658687412, 2809028243, 297647962, 1609437431, 3358143193, 1716156248, 1612652130, 2723039108, 2877712792, 227416933, 3655452320, 3809918775, 3758975241, 2625261551, 1044900207, 2767833802, 749765276, 1997143904, 536279565, 1568228199, 764519151, 4215912350, 263962810, 319470773, 3810995202, 3465177349, 1243659365, 864064918, 4136562751, 3062846208, 708743160, 2187738105, 3898834484, 2200754536, 4539814, 1789419448, 105721213, 2944213866, 1486345112, 32430882, 253601522, 3408074780, 2992349041, 2451728307, 226661140, 2460239549, 2100724593, 3852012222, 743449851, 2967418295, 605498674, 2055548507, 1922946771, 2632283075, 4086716584, 623236339, 3410294246, 4133057483, 2812524059, 1205446946, 3043927830, 3482614376, 1275680906, 3676217583, 513988754, 893728600, 1999049758, 598451747, 3593194658, 609427399, 2673100544, 910865729, 3116238253, 736726549, 3362221872, 1013768942, 718438609, 2217341124, 3587867839, 2300483002, 1946981080, 3920103403, 2292895303, 3117736693, 877577485, 2187888016, 1368957453, 4283009664, 1076391253, 1397877819, 2980178183, 3968837715, 867743243, 4043356977, 2946375050, 26361492, 3432852562, 1912980855, 130799130, 4033884077, 3349537042, 3182198745, 2179478628, 4252455628, 825955887, 93466691, 2196075887, 1784475710, 946546654, 3933870986, 2244605733, 3490402086, 4030429100, 3023300148, 1745265920, 4112142076, 2903907125, 2758734523, 3896908867, 2564201959, 26549320, 1274768945, 2576126997, 3923164846, 3736091709, 370046710, 514332769, 4121086903, 2972568269, 4088911695, 803020494, 3034337812, 317708135, 1334283383, 881113661, 1695276900, 3766800569, 2061275833, 1227611332, 121744019, 2173946227, 2389688567, 192367735, 3892792894, 2172535825, 117291679, 1935828849, 2721596143, 823956503, 1586432341, 2448062771, 4054304197, 864073076, 4252759593, 1258481746, 4285979432, 1026798711, 2713633766, 114893615, 3134616441, 2817271874, 666109477, 3691375086, 2759951811, 448361256, 1541295802, 3882571749, 2284391955, 1326400031, 2777223186, 885169913, 2782624297, 3537147598, 1692556532, 776208409, 3241275549, 1904954149, 2405119603, 3819789804, ], &[ 225066005, 745131552, 2942567538, 4258778781, 1967392927, 3741613691, 1890932195, 1506277386, 1146302728, 3715076457, 3577274198, 3953573097, 2085422530, 661098011, 4236873637, 2930925760, 3967583938, 2852055099, 355730378, 512021169, 2505846300, 2749910007, 1454559275, 2553714326, 1536856909, 733797684, 656941700, 370199490, 1949020029, 4091629764, 3452778818, 3434279798, 240547993, 381305151, 534633119, 3783352536, 1551443097, 2973034337, 2180000100, 2053656589, 3320616670, 1724644295, 589237508, 2241024734, 412948466, 3347181025, 1812386780, 1524837382, 3656593545, 501624455, 3029327470, 273718066, 2666953466, 324438884, 2852820080, 120020650, 3393646374, 2619314651, 3733169374, 3756112094, 1302185220, 3677713422, 2747067315, 2815017712, 1868682331, 1943529649, 1563990165, 319757768, 2031825250, 2139207520, 2978578108, 1560356796, 3699549338, 2916893113, 101966731, 1585835576, 2998190164, 3967243725, 3959463829, 498949725, 3348011234, 3761007557, 302477959, 3992592959, 2447724633, 2460308753, 1858976258, 3525120157, 384425177, 2978081316, 607592077, 401773917, 1748638062, 4245512962, 1117346825, 2328817272, 847205838, 3491495030, 470052326, 1893860493, 2076576843, 2289319719, 1260754313, 4064542122, 1206836886, 523542952, 894395755, 3043786155, 2337338009, 2752103377, 3251660619, 2215772339, 3015482729, 2593131420, 3786996532, 3672453772, 651643275, 1988656237, 3347623451, 356296282, 2406730821, 3093333932, 2660898588, 81938635, 3783019719, 383826519, 2681656944, 3399824694, 3552203202, 3981865110, 1183621457, 146668152, 3118763304, 1958273303, 2057041878, 1183522949, 2882248106, 230586931, 680070970, 263636248, 2634241968, 677653887, 4023567727, 3777994047, 1592901741, 2761934715, 910715025, 1512493458, 165009600, 3565664162, 1187297321, 2558161419, 2468839453, 887950197, 220662954, 1244941671, 3095343373, 2063342669, 2090489239, 2010099484, 1948084319, 1365644807, 1235644818, 2588736961, 1564371721, 411294152, 3045805520, 1843591393, 3688879242, 2388718380, 2305780976, 3853250176, 1061462164, 3916091720, 1198491889, 3197591330, 1096143292, 2118906933, 1635799180, 1176220582, 2501989740, 801999335, 2705462373, 1003645809, 2186975253, 1064745016, 1555323605, 4095122662, 1852179202, 3337474276, 2971325331, 529480360, 4181951721, 1632451986, 1921251025, 2187957901, 1550157150, 1055194859, 1178754848, 2551455843, 4253040930, 72428672, 2433250913, 3380996315, 868858299, 2205090193, 2621190489, 1284715782, 1308118202, 628595114, 2783487525, 3396644559, 3453264010, 1070669284, 1383523038, 3993112084, 1712356129, 373012427, 126203575, 2392499470, 607718265, 2253959369, 1040951361, 2590357607, 2175608952, 2297182602, 4276086375, 1607963583, 1082087029, 3529235816, 326427724, 3716684434, 1901298488, 37770472, 3247695701, 1067103258, 3117586492, 1266520999, 1168926910, 2626033388, 630871070, 4243084776, 188878698, 3514192446, 1923550427, 206270544, 1634209660, 3863690423, 2574699027, 4168121673, 1449879463, 4224275977, 2227130200, 1884692906, 606301209, 1210083889, 3640641606, 2504768822, 3610799696, 2178748368, 1708820271, 1819469384, 2802870165, 2246886931, 3567016595, 3555599583, 1348994237, 3790873838, 3926636967, 1088645573, 3438253657, 3323650855, 828010249, 618829949, 1504599310, 1908275663, 4270232696, 4036146227, 1856897469, 2998994751, 2752368926, 870328089, 338595046, 3616029110, 296696765, 1403260870, 1830786965, 1227812187, 2223459989, 3589209104, 2051289912, 3318866022, 4094335795, 3787444415, 1234353630, 3808781435, 387466633, 3211872777, 4202021032, 639324231, 1976675272, 2193056063, 3199669188, ], true, &[ 3923579889, 1687605753, 3377794191, 3322208449, 1203553350, 2154425101, 1359863697, 3023444870, 776353376, 592836194, 2511309652, 3922934431, 4150213939, 858418424, 2956152570, 488137268, 931462870, 1642630985, 3149845100, 3318171957, 538998706, 5191729, 2137745225, 2297747699, 1984407713, 643246259, 2253618591, 523932289, 191175769, 3642012130, 3400043084, 1707948340, 2992423698, 81890223, 2378233131, 3079312226, 1066946509, 803135022, 1994948858, 4041732309, 1337312336, 2966488667, 3428464355, 2737588983, 4228360315, 2146901404, 3059157811, 2476369890, 75140925, 3251604233, 2881152809, 802794015, 3378093993, 96836131, 3099865764, 811380027, 133901715, 1047457206, 3609305681, 1771180437, 2461319522, 3515701714, 1066513666, 1659070392, 3086795089, 3716662526, 559065127, 3237292382, 3631218434, 3795187732, 704836609, 3786271895, 4061286432, 405232026, 3609248662, 3980760947, 3571087184, 1847154731, 2094552306, 814159853, 4260485048, 3149179255, 912325889, 3689884426, 4138663955, 14357881, 2050778168, 3912490158, 1861501789, 814905489, 3254286948, 2032825464, 3271543587, 2219425366, 4225852701, 1857868075, 1298372166, 1102499025, 3574133387, 3812312663, 448380962, 3807290049, 4209544034, 2256927203, 412478498, 1228300916, 2401082596, 350244424, 3441586361, 3136422715, 945678990, 2116172969, 301198401, 3322856984, 3407592301, 188389305, 2628435530, 597331343, 433647333, 3063380936, 3817880039, 2901586764, 3507352615, 2352939145, 3490273512, 4090562787, 1802676852, 514644644, 4124694011, 3639332010, 1115134207, 227756304, 3818731261, 4222040109, 2430937604, 2156693403, 2184651107, 3551740749, 2132540830, 1150238882, 1052043654, 571348510, 3172318934, 3673669988, 692769159, 210233084, 2958517959, 2297993342, 3316672837, 3302014323, 354145219, 2484852144, 3683759209, 3408466568, 2978225356, 4097994925, 2538336670, 1392418428, 2899544976, 457988587, 3773763501, 2012444919, 150975722, 2234422639, 1822822763, 551692314, 1014406649, 3374930924, 1240545416, 2294327444, 3432793083, 1000394478, 2103969650, 1395783166, 4085383479, 1542514796, 194271393, 145341362, 3655868181, 633459061, 328054273, 3431726030, 3557285056, 2901104858, 2052553042, 1042550372, 343075862, 4115125230, 3906797654, 1301043752, 2559925980, 1623793157, 628627946, 1884173596, 1228259826, 2621415081, 2785923512, 4270141343, 315667031, 282856266, 429519802, 3536348488, 2322956754, 3194951300, 1510744177, 3616915522, 3309727286, 517266630, 1119984084, 4026073305, 2238785198, 732618834, 3368263738, 4087015376, 2697003280, 994552013, 4290467065, 2365091630, 59691114, 169931479, 1498618224, 2382537145, 310192470, 900458915, 275936028, 3655907299, 1961047155, 943058038, 2333911425, 1578159189, 1847055172, 2659538736, 1993399472, 2491904542, 1070133929, 2666142065, 2803306446, 284508539, 2535344546, 798366741, 899869216, 282425661, 1522885207, 1934768011, 1935282035, 1783703650, 763335394, 1114825113, 4001525101, 3326921253, 1057031491, 231338938, 505911721, 3073700058, 3881013726, 2622491116, 2434260580, 2104610402, 77048668, 3840229888, 539240724, 272637566, 3598686634, 832397853, 3941981941, 3947689731, 545125868, 199321616, 195433751, 587082201, 1623079028, 3583449493, 4189372053, 656157970, 4065268173, 2321947633, 4117128060, 1042761195, 543619922, 4200179141, 2194761475, 878960867, 3598234187, 3791350851, 346665711, 1360737771, 1930187385, 2405900037, 3062309031, 2085261831, 707121842, 3173108868, 503413591, 73514434, ], ); // - lo >= DC_DIVAPPR_Q_THRESHOLD in limbs_div_divide_and_conquer_approx_helper test( &[ 3852468748, 3866732619, 592701608, 3778254743, 1280491238, 2834833773, 550923334, 1479705073, 498349312, 767409174, 42211279, 2128147526, 2926662909, 141411040, 1065100366, 1527285446, 2874448851, 3117914313, 1218471999, 4280625327, 2037562894, 1609603468, 3241376868, 1996556629, 3588969003, 1318580268, 3687594860, 1362481322, 2944468172, 1695770272, 3083883725, 2377648522, 2496254008, 749263050, 2770685897, 3512231732, 3023316399, 3384859643, 1220306495, 391138498, 804657736, 44216427, 1931816623, 339239167, 2662606581, 2648352860, 1235726472, 1626990950, 3004127325, 1053956347, 808327756, 1442399511, 4286364870, 31595646, 2379491886, 1328294899, 816658097, 3205321744, 3963029596, 2572812025, 87366995, 3217997432, 1508641500, 1825064063, 1941897747, 1436358378, 3017514874, 941910582, 3588117902, 135801271, 2867936354, 2658316194, 407580200, 665652508, 1146163780, 3147022746, 3669479157, 3697518011, 3942322922, 3433464004, 147802483, 1146857432, 73698519, 3370749655, 1389534220, 589317299, 177267891, 2688250309, 2128670608, 1265200580, 2019760989, 1150930096, 2585252733, 15447323, 3088238466, 1783728664, 2811524431, 3891707403, 4029016169, 2907528558, 1270616768, 166893059, 1545869782, 4275310588, 2441090079, 2829901749, 3736960597, 3941382642, 2821131110, 564991139, 3126664226, 1998382701, 1328551552, 1210689595, 2996963417, 1557893584, 43742716, 876455611, 1677218718, 729180347, 315949329, 1732639163, 1821348164, 151672496, 1329099718, 974261301, 850419612, 1856037997, 2615159114, 3710750197, 4091633114, 2586774188, 2588577112, 1339558569, 1735462778, 1262938743, 1891014212, 3269098922, 1992796362, 2808355044, 3874652326, 2745283316, 1735823559, 3407614800, 370629516, 1152369319, 881914057, 470647543, 3939410385, 2852748779, 853680636, 3231204925, 296778651, 3315599780, 970480725, 1570957625, 3243621138, 4081630171, 2137632035, 488321574, 3274673411, 996742709, 1121917553, 684178420, 2611815203, 1398907392, 3313511725, 2114905089, 530433742, 1501425765, 3354176655, 3515249223, 3432236694, 2338559491, 3638772717, 3253118328, 1594238823, 3094732444, 354679189, 1860678321, 86892394, 826940850, 1314179547, 3978569567, 1699444163, 3462511739, 2591772690, 3726539491, 728424834, 2932676784, 311068414, 2129104220, 1026553636, 2242765511, 1733810815, 1138330866, 3652398326, 3074523173, 3839981206, 1015663483, 722242539, 3272711437, 2982099959, 1938802295, 3022788284, 12930779, 878443915, 2907693541, 1979049428, 593163227, 3823442786, 3215213583, 3695525644, 1119636738, 3212997654, 3027851617, 1144485880, 164747928, 2781230452, 1258345532, 2869324653, 3068929942, 1028739729, 3380289029, 2295840170, 3545102314, 2855402743, 1772822517, 724460983, 2228954158, 3208333919, 2821114010, 3148029409, 4068546439, 833494094, 2960251966, 160156911, 1983852913, 2791477758, 3697190934, 153093720, 104144622, 2441461309, 3159646380, 1733652873, 1562477414, 2555472454, 208737200, 2703626976, 3180538910, 2592414545, 3416739924, 3356130918, 4069598606, 1949794549, 1771742849, 3756687965, 1452093924, 2443380777, 1591957147, 1211239165, 1876128705, 4247423793, 398751752, 2564049252, 3016849411, 379369954, 1500293555, 1436202725, 3000709783, 2380370269, 1733644538, 1525628809, 13455701, 3296626657, 521910174, 2364967601, 1781968745, 1399663633, 3043350501, 1368246629, 2392664448, 1283732518, 785313394, 3034454976, 695088212, 1511797594, 1863608029, 299100351, 2597420190, 989884842, 2042620176, 1636899254, 2378486752, 402706413, 681449111, 3318018166, 1613374280, 2127967446, 289891229, 191268175, 2824016875, 1141385569, 1160748059, 2298038638, 2273363044, 1083067452, 2227633073, 3411833901, 2501670656, 1136686475, 449786314, 1206095141, 1428680228, 373851423, 1065715962, 3842120141, 1446849052, 142137120, 2503522334, 2890167721, 489029335, 2904499752, 3583810486, 141821369, 3975802804, 3139899326, 3360723646, 1325094173, 1458543621, 3135728890, 1722244101, 546577431, 2431082502, 2423442975, 3716191600, 4106127568, 1535072638, 3490647587, 690007845, 123509837, 3008940800, 2522129913, 509564148, 3464677431, 2734250447, 2521445361, 2724421404, 1464248423, 4286188561, 2041779154, 2040896472, 951622461, 2742066946, 3643978111, 3702076160, 3277267213, 3516427880, 3288032742, 1694027041, 3062496840, 1755611164, 2144317315, 1840150810, 3659412421, 269788590, 1685549590, 138245102, 3801925635, 2810327973, 3857961937, 3773132978, 2859864128, 1937028826, 1803313773, 1721171315, 3641809479, 561594878, 3883288939, 1615573909, 3567576946, 53427597, 3447054169, 924172132, 289810649, 3166741000, 991317667, 72203781, 985172668, 3013352759, 2107570161, 3250293704, 4114482787, 1050030772, 1057622762, 3438626748, 2519260970, 159154610, 888655185, 471817829, 470991380, 2525869562, 257437760, 665926900, 2709862184, 3205674228, 1381649365, 1803460892, 4134101678, 2543649326, 1209534353, 1226459212, 3664518300, 2168714963, 3110951542, 2920091469, 280549216, 3763064171, 3139277729, 2961240010, 3997887886, 2249335682, 4125195068, 2179174964, 4200864330, 1948058108, 1468274578, 2376503735, 1402764211, 3508183492, 568398904, 3916597152, 1316008321, 3354808565, 243276170, 383567360, 3854059575, 3533629121, 450497668, 1613229695, 1579942631, 1479512959, 1708803214, 166236912, 3371361562, 1178374935, 3631449184, 1044231267, 43160759, 2872462763, 386332526, 1454108301, 463466433, 2881621607, 1902397631, 3675190003, 3262456635, 3682680678, 3921732891, 1604135368, 3949662129, 3129246190, 1954536251, 1538666313, 2274928374, 1650180856, 3652524428, 1821056613, 911456961, 840333318, 764118487, 2652399697, 2580502346, 2438391701, 2513677855, 2640798083, 2778108413, 3625988619, 3121963132, 2016358782, 2026634297, 2454141008, 3719526468, 2069512197, 595695222, 1372551058, 2654832919, 1312895472, 3449972978, 1039886392, 1219309116, 2158257939, 161673294, 1466523266, ], &[ 1228082563, 3958970957, 2292561045, 1680572099, 795956301, 3199900361, 2775759977, 470071915, 418570831, 1211920274, 3653536884, 1024252286, 2421732290, 2695210567, 602247103, 4076240601, 547232254, 3118467901, 373262705, 2538006674, 3879907903, 484206954, 2539623040, 4205486376, 1910552745, 3038212402, 2654312301, 3586427708, 954791645, 2348064693, 1497313290, 2715388363, 3338088407, 2319307053, 1080519064, 4159525507, 1284211779, 4015474700, 3753400642, 388134024, 2776075876, 552537674, 1195536084, 1000211139, 3608292187, 456221898, 2979823937, 3666331215, 3448143527, 752704015, 3181775208, 1221668864, 3658472905, 2038458530, 2182904194, 1539979012, 1086813538, 1185254470, 810158065, 3448748698, 4194931499, 1623694312, 298685602, 2265178291, 1937541694, 1775046588, 1544843229, 1529059357, 649269555, 2357792903, 2571831955, 176354978, 1299551755, 830143712, 1015814111, 776566019, 2627651913, 3960393788, 1268944216, 3414991379, 3922712735, 2519760646, 1906700144, 2590958602, 353821006, 2218545353, 1375841084, 2092401658, 1639008622, 4082695593, 2141419111, 3236669066, 1724206670, 419369846, 2835126061, 3041510267, 153991327, 2126200895, 3461262411, 191209011, 1342692414, 154698036, 563023945, 1510300314, 2248068391, 3846972081, 1992059708, 2646433655, 1714730200, 2303707509, 3981692650, 3517398169, 2281282719, 2519619923, 4271369978, 293814410, 438829639, 3337765624, 622782672, 944352733, 3715313213, 531335520, 113528832, 2419325895, 2984041163, 878536167, 3214930707, 2146787348, 4917714, 3257269189, 2452274107, 2672157272, 1585645759, 2131367341, 3585828795, 1333843792, 3923459029, 694088371, 1013702168, 1741059100, 3997989379, 542853888, 1761645159, 406716499, 1694374453, 1624534824, 3459630459, 802104445, 128207303, 144400385, 476582731, 3051345902, 1368383669, 1166299002, 2707219053, 4004021138, 2679504095, 2592982338, 1033724773, 1157182117, 711981576, 42503937, 2924924484, 3595784172, 3595204272, 2994216676, 4221872019, 3722581147, 3333988566, 1523164764, 1080358318, 1413433846, 3738351350, 977402259, 1992977980, 1559146947, 3211129812, 2160246550, 2367537106, 446281713, 2153747232, 397871847, 3366573642, 2055448941, 41153636, 754933361, 2993598965, 3306066874, 3631977724, 3123479847, 2585741316, 2994078662, 2509626417, 4066762390, 4211900185, 3742567686, 3545119766, 949327829, 1947239775, 1596917691, 2428932126, 1055142932, 562149283, 3199507769, 2908430793, 814804964, 398782122, 1053511625, 2957145782, 4214499480, 2538107930, 3510188017, 3044050202, 1179016763, 3073719558, 1010197763, 2365480195, 796718852, 2056040043, 872695428, 645007655, 3691376745, 104700630, 2649843250, 4122935255, 642238345, 2295983257, 348265112, 2773179245, 898141051, 2579996826, 2612225547, 3972451489, 2646202581, 3681992299, 181022653, 1485802997, 2440387741, 2520682234, 51353550, 114076802, 51940680, 2817210994, 452896124, 3254045803, 2864556183, 81661781, 237542081, 1973800766, 3657654720, 2530129707, 403307022, 68172699, 332554330, 1181024212, 811837036, 3695906025, 1961935526, 3608053891, 3566607807, 1505243326, 3952431950, 2229199298, 1258499123, 3907526592, 1202974947, 4257231754, 383365712, 2370787478, 3966045621, 3709646864, 341562985, 2306743433, 3087453648, 1119686719, 3010178775, 1966960488, 4005245264, 742100958, 1841989955, 4073161558, 1387924175, 3136835241, 4153208836, 172275833, 118390136, 3068417534, 3427994941, 1186924296, 3531763845, 1587276588, 2491453930, 3092663154, 186325597, 3735008023, 2520603222, 141263570, 2586779772, 1097287985, 1184074419, 2231683844, 1006316112, 4242375661, 3021145139, 2474020608, 3059475910, 4077499345, 2682549550, 899267458, 2939020861, 212132728, 4070534479, 899246172, 3206389107, 738644506, 1196824568, 4135770345, 665964490, 3404106178, 2800460425, 370991796, 6173656, 989425002, 738558511, 1186448823, 1117986518, 3268400991, 694618816, 743869433, 1081820528, 1169090980, 2808795201, 2626416762, 1852742088, 3500519845, 1862566642, 2528685207, 38532995, 3254975580, 2293790115, 278388535, 4214498933, 3355793258, 2429295061, 3055950106, 1916510220, 408474308, 1993547223, 3283433638, 2876081292, 3535523705, 2101519467, 4222280709, 1877650206, 1362736623, 1125507149, 2753028888, 2871670444, 3984235984, 2837413105, 2740068704, 2501544770, 2062713945, 1827003918, 3387715121, 3978334051, 164380626, 911533483, 3159921130, 3896040725, 2453247705, 1732359707, 97075111, 1167974376, 1292533086, 3978529628, 1173190459, 1180474283, 4027781835, 1819164482, 1138188719, 2554004670, 2238689551, 2719133108, 827123216, 3402746862, 364981183, 1215495008, 3697503228, 2459473144, 794939056, 2850414988, 3880571940, 3446126388, 387496900, 4012258040, 233036233, 1295469109, 2236990087, 289904073, 1533599469, 1786729109, 3155911485, 1361493542, 1709668750, 2979939253, 899656352, 2488414909, 2345651638, 857006573, 2499927665, 3004854698, 2767508418, 3057934317, 2570296632, 2340731830, 1704320439, 2217465736, 483270163, 433273029, 3463124152, 2858495981, 2293137585, 3765138357, 2050975825, 1062202999, 2389813229, 327867315, 3524908521, 1060359725, 2437188567, 4037791947, 265987565, 2531318664, 3789582609, 1036190383, 359313632, 343266182, 3818075324, 1483429641, 3251308104, 2231865653, 2088816062, 1363097078, 2619396780, 3922946100, 2087714470, 2714841575, 313007644, 3053385186, 31524825, 420269932, 2184870970, 2633967376, 2976557270, 3907847269, 1704768911, 845456817, 3013183512, 673429122, 1088006999, 4254909288, 3477532731, 2633706423, 30604022, 381299887, 124029095, 2146491520, 810411389, 1842896686, 1189234944, 490339649, 1115698075, 3923320995, 2822835404, 2863188964, 2041216097, 3722786391, 1411085302, 643395602, 1892259907, 1276564050, 92834220, 2113523130, 3750780619, 413882810, 4162989, 2342682023, 2496728931, 3765633586, 1201219647, 1509483486, 1571999425, 2150766213, 4078947670, 1554603889, 2829344380, 915004628, 2209136503, 1860939599, 1336190314, 3883277228, 3526987435, 1959059220, 2644428109, 4106090871, 917923267, 1544296685, 710190597, 1252330700, 445060090, 3748836645, 2225146599, 1869685424, 2948785336, 396398905, 4121416478, 120806631, 76766006, 2336284840, 2353857164, 631928490, 2358081096, 2401392404, 1781483930, 3507012756, 114196273, 761825995, 1747713254, 3582101597, 748625738, 2646455218, 2905499938, 3230684494, 3213162530, 12062405, 2034846069, 2240074509, 3895726666, 1559793991, 401560906, 1188895923, 3908766043, 3080529735, 1723996093, 3234235196, 1524383480, 3006010429, 1021800042, 2598013312, 2404289459, 359714242, 2353150857, 3214159696, 71259951, 3244867195, 1475212366, 1519569068, 396867142, 1704063457, 1255619835, 1809747439, 2455947434, 2914124280, 490937656, 1909042102, 2425011492, 1653816077, 1744426598, 3540268790, 1266922070, 3157358103, 764478931, 143507967, 4138193217, 1618357750, 4064415341, 915914627, 379606079, 1684722693, 731091210, 3441411920, 904319643, 4101866043, 1130761207, 2746556498, 2962076734, 2459719176, 4014414287, 2306516630, 3241923533, 893098894, 155104880, 2462450145, 3698302787, 2611896162, 3483738489, 1960417753, 3190054039, 3176206866, 2149242647, 241842249, 3791458236, 266968864, 653002708, 3295229436, 720704829, 668777771, 2920041289, 1616327007, 2614675119, 3120745852, 3703698323, 642045983, 664497190, 4138076932, 416801804, 3836460143, 2512697726, 1321118683, 3790475422, 2372618883, 3906311778, 3636945722, 93045717, 3245150294, 2203703812, 2876544088, 1482347470, 536620593, 3055935093, 3219276551, 1736510361, 2882369741, 227297457, 2287462988, 1314417701, 2698591585, 3562176889, 1108866670, 986625362, 3935882051, 2153826689, 4088091186, 2094026213, 2614688936, 4293577301, 4053305951, 4075217449, 3960924855, 347332803, 1968625524, 114389475, 430194382, 3252648209, 4018348764, 1840000995, 1589897244, 258799598, 1737020958, 1683355155, 1473302633, 1904664311, 4282826162, 1231154140, 4030919851, 1206926359, 3663795445, 2379135003, 303432555, 355307489, 1769635102, 2552468836, 3490641321, 3099203148, 528813020, 3258352325, 1295334678, 3143722334, 1978938927, 286181973, 2742706533, 1605086426, 1943464059, 2101290175, 2169564592, 2507578488, 3835864045, 101762307, 2100748227, 3058433907, 3335629628, 2214316788, 1268535268, 402136621, 1768704361, 1113090330, 3771703632, 3647202551, 2716086257, 1380543566, 888137953, 3154815844, 1427117965, 4171112788, 1823391124, 1935813073, 3498407768, 2295745053, 3209451097, 3427436731, 1760982025, 1197278449, 540450594, 3647987196, 3703306058, 1018206619, 2476714098, 3182222236, 2163415625, 1564991911, 377612233, 1240138195, 438211, 2660780499, 3842090366, 2254892076, 770175200, 24158863, 2695586572, 1592642609, 6566621, 3696323406, 545103586, 1539983422, 2835737393, 3243834056, 1307518947, 1449819027, 3732497678, 361142215, 560917662, 1000073399, 2993529240, 2447753259, 277468387, 2097588385, 2296579141, 3491393176, 593689188, 3981379323, 1199729884, 3155291067, 3484678877, 3241832730, 700414265, 1991308981, 4120895059, 1897048619, 3149808222, 439364012, 344761676, 3062212838, 1283609663, 4033828278, 1778135949, 2420787257, 893368411, 602240535, 1331176104, 3252174301, 2911796787, 3606169310, 3656396589, 3672036583, 2975308991, 3008310252, 1216481017, 3571455814, 917390807, 3398014016, 3881198175, 3246069043, 2018429161, 2473741365, 115107297, 3264952157, 2580209049, 36273546, 3206338009, 305508401, 1376925433, 2056571909, 1019775170, 2706062024, 2901924304, 2190222733, 2740737267, 21015048, 1250529961, 4189046693, 1010891679, 1852727754, 2130616276, 548460973, 1990672906, 1047266283, 1377617303, 2745241728, 3579697777, 4061895368, 2785622772, 2769532205, 3150425811, 210098228, 799917387, 3243975475, 3585288930, 2961830047, 3048068800, 3653640841, 3600794853, 2717549000, 2701285348, 3943817837, 1093998117, 2069876461, ], &[ 1904169149, 2631229056, 3049906843, 1882970882, 1342610636, 348735230, 2030868119, 308972916, 3291280440, 1713067370, 798189929, 267083738, 1426325271, 1400323459, 4220917798, 2838399613, 2788016416, 1808463064, 3797033758, 4019522812, 2732377100, 2865589386, 1858695675, 791228146, 3278919839, 1007346809, 2152870094, 4143135690, 2156969365, 276568681, 768119249, 3720025676, 3691488609, 2122964639, 1090037461, 1573203071, 1029758226, 512965488, 1081406960, 3875174920, 4202135603, 1561629768, 144375534, 824852270, 2139340951, 2521611777, 617945581, 1174393067, 83560822, 3171084584, 2743715748, 57600123, 2500345583, 509310341, 1466707920, 3965654944, 1780152208, 2543890327, 3951358979, 4064884222, 1148693723, 731908693, 2303119198, 2162132555, 3899764661, 4062906460, 2910202154, 3507799436, 3049585561, 1547101764, 2240591447, 538691646, 3327231079, 4101167722, 3558467927, 632232393, 3069596916, 792109379, 1443377440, 4063660922, 2403295483, 3242450069, 2054813912, 3224639109, 2116127467, 3510867445, 4131878961, 554538806, 763384993, 4028933429, 784809516, 2188214742, 1245086980, 232165771, 3893787601, 1616832299, 3354660858, 3756152253, 695071424, 3616331020, 3728930728, 2300889664, 1134765807, 2568071856, 2230185436, 1313073173, 3090697900, 2811549719, 2626884644, 3174004164, 3418927780, 1459400962, 1170992180, 700259624, 2882894395, 3735934167, 64057275, 4285443281, 3858505044, 3530830770, 3881898558, 1248666153, 4057784557, 825094518, 3954584560, 1379703941, 456663582, 1936817375, 2100203590, 2269578911, 1927092754, 2056845231, 64996052, 3180336408, 3382367590, 1579799629, 369271331, 3393685503, 1678462084, 3580453071, 3344059212, 2603016988, 1704438831, 2960085271, 3944849185, 1984458477, 3159618129, 1356105311, 3061973253, 1169634390, 1581525372, 2092399029, 3856589897, 2747272433, 129370532, 3259112907, 2392093327, 4224720237, 2467960903, 3012864179, 657311189, 792107047, 3702308235, 2589079343, 1977762240, 2054656079, 365049703, 1136316952, 1766336156, 1574143327, 1448002399, 1545340743, 3343582998, 4266810491, 885565293, 1012325697, 4265244667, 4164478481, 3171829328, 3052840557, 1524972073, 3381586754, 3989036728, 1081734627, 3737298307, 1869630638, 3072103206, 3329790326, 3520758799, 163463995, 3179586285, 2504600081, 2392849343, 2696495366, 77291649, 1524994513, 4129364215, 2589017064, 563995388, 2948622336, 3478580619, 1302885151, 1885238682, 3399987677, 3819885284, 291981185, 2438308465, 1131073201, 2094997380, 4030538680, 2493835385, 781324886, 780626834, 788047573, 3251459753, 589598543, 530167431, 691366057, 2997152103, 1895699987, 2067335840, 911810562, 3044146727, 1981642612, 2744164616, 1268584352, 4091929647, 739635330, 2535146835, 1232134198, 2821166834, 2694137328, 1845150759, 4145746520, 1570842207, 1877662863, 2624263192, 822008531, 544782319, 313703935, 2549594582, 1507198513, 1165274204, 3706172942, 1025658022, 1367415969, 3754039309, 4187050684, 1116191986, 1599395850, 4255758850, 3627566792, 2013052489, 3678795519, 2570182055, 3933838202, 2878788816, 245983387, 3805875941, 156152490, 2288310229, 213932492, 2816431456, 3032792377, 4098973047, 1987668121, 2178466333, 3171514186, 1824097633, 2477633111, 905563455, 2561821790, 1164919073, 3346223498, 85587270, 388762173, 2830714978, 587416024, 118417479, 985918121, 2869840425, 1942696561, 1447188301, 1252144775, 1754507324, 2995197874, 348722845, 1994558236, 3180590158, 3621098260, 2808142053, 664847652, 2216211159, 1812881783, 3652176793, 1818451392, 1492863756, 4248433045, 1393154835, 2899742381, 1639554680, 3891616188, 1401178839, 155094399, 3335589331, 3242149447, 1506620207, 4025305548, 1378564899, 2250748936, 3892206821, 2999250953, 2404072212, 1227092115, 3842156829, 1175300589, 1366215256, 3655797370, 555970590, 2216476284, 356175930, 2316653842, 3511159891, 3242198801, 3709284219, 3992609721, 131038128, 561182178, 2366328214, 2169412954, 1843648386, 1596245006, 590747798, 29988297, 1032233337, 4148540805, 4287292895, 1784151615, 775442479, 3254055272, 1319462308, 1998762911, 462052502, 3240867011, 1529884215, 2445458752, 687926411, 320372384, 1993875140, 1103187463, 1101261370, 434642811, 3921005377, 476413110, 4114908941, 399340969, 550419121, 2138268102, 1961648534, 2475107221, 812733153, 1013882638, 804382040, 597969578, 3969389037, 1681594804, 3597283127, 3246865960, 2618922824, 2412709123, 2883379189, 2268836289, 4041631960, 3932960611, 2819242006, 3434298940, 1965495785, 1801489474, 2483685757, 525486136, 3103413787, 2524236016, 3297675542, 4250105246, 2163911845, 868191034, 768077954, 1251877129, 2082725352, 2563716501, 324144134, 2949337083, 629793518, 3585348714, 2283159799, 1662388577, 3211992651, 1893003272, 367507404, 597480849, 3530706203, 2180056290, 3040505611, 3393423843, 962401948, 1880350816, 1059318370, 2185874635, 834999744, 976189277, 2214236591, 1042067189, 3972166345, 3379537993, 4180308634, 1894580429, 2768917877, 2304053036, 1074132791, 1172385654, 3558332507, 4118553815, 1144817158, 1932880741, 139994662, 2006231438, 1878531442, 1451662501, 190676819, 2374814207, 2111662756, 2422642399, 1219123380, 1437107644, 3325772043, 803974620, 599430876, 2919848672, 1661638336, 1841139086, 1961142950, 3330180086, 844957898, 2211184671, 1097521602, 488948427, 3209202495, 3087475496, 2505815200, 1915071794, 989106472, 3460765890, 1592714830, 1577504527, 544612468, 527148798, 3186590344, 2423036586, ], false, &[ 1274629765, 3141211094, 3066783437, 3586463614, 3484042397, 3524692172, 1849759418, 639170343, 4042051785, 1786641195, 2781936314, 598559471, 4206822552, 3076839520, 3426707763, 2541903555, 3985517971, 2924425523, 805503712, 2235352830, 2985073687, 1986582861, 708824890, 508981633, 2929420962, 2821655200, 1435071022, 2815105969, 3064101020, 669540051, 64719297, 2298557985, 2663556386, 2872778448, 1920581662, 3964906867, 3545183326, 3734685799, 965493690, 2511488644, 1289889793, 2716496762, 1482707283, 1243240515, 1600220728, 3386832682, 1230771057, 1851371335, 962673373, 3303433511, 2971821380, 465715438, 1476479395, 4210224292, 3326701593, 262885511, 2623286176, 2785619040, 3631756223, 2689408595, 895184011, 3039724640, 3256518757, 3157339284, 2736033980, 2623616149, 2262942125, 4066660566, 2010739028, 294414070, 468536368, 39081857, 488790327, 2978306577, 4076063380, 164990706, 1769246328, 2404180723, 1910734795, 1212674812, 3651413973, 4107687624, 3562008089, 2495538965, 1060913944, 700681324, 2213076011, 956710321, 3766900265, 1201745400, 1689241027, 2023383937, 3309067962, 4290293260, 3262071778, 867200275, 3722256414, 2704572302, 798356854, 4060154398, 2192265925, 1631346682, 3841392362, 364742914, 1350896170, 3826205664, 1387850479, 2438144424, 1722720699, 3355734439, 281374639, 4294332167, 2848655781, 2650822950, 52206106, 1267368119, 3786144635, 3997971973, 3766740222, 157940553, 874086492, 567057084, 1468392762, 1319013026, 1763094857, 1258351011, 4219111833, 2069011861, 1508267766, 1742493547, 3709667481, 244137977, 3867904379, 2749217489, 1901868294, 3141009904, 1334349455, 318703881, 790854628, 2456409186, 2729035424, 2140696710, 3057979010, 1943182218, 446440787, 3044060750, 3377747126, 2650171384, 2030143427, 68841182, 3417107910, 1982395041, 213127592, 4263826627, 3810676045, 2815565679, 4215729650, 2424656131, 2427868488, 3538613128, 2004058276, 3156863142, 3493891883, 1282367517, 4021690990, 3880291659, 3234626473, 733983061, 3094727704, 2181100156, 2419795021, 261213792, 1806943490, 2451407303, 2727992941, 3870486736, 2318523062, 160305854, 3405051241, 3671726857, 3273962892, 3354100289, 2703913540, 304014061, 2416130602, 1740666524, 1270481586, 829357964, 3389415821, 1783014510, 3440915536, 2186635473, 1638518047, 2861195291, 1925018981, 267706283, 1852657873, 3918895473, 3639936236, 1540281136, 3992865037, 1795928884, 535725314, 2620251512, 3768070603, 342868542, 2807296004, 1944907465, 766931863, 507809586, 1382623024, 3748022748, 809199766, 2606119767, 440758364, 808682457, 1891522267, 2798966179, 1932040027, 3544577672, 1613760857, 2497954981, 3761568437, 2673674694, 2267348907, 2169995118, 1082902734, 1924288552, 2560273581, 1328627426, 500474681, 2740807968, 1058091958, 4193976709, 2145630875, 2850935242, 3475556484, 1444110200, 2094948501, 3669224179, 3527535779, 1309727297, 3043349576, 2800927336, 798778876, 2615924118, 1736199098, 4167626369, 3609129416, 3696542059, 2660961906, 3709573368, 2742620902, 2002154977, 1840222458, 678539421, 391765530, 3711225631, 2336471984, 808858486, 2107964482, 2120664214, 3475065201, 3782915227, 2313935531, 1140567569, 1920486212, 469939343, 4127720462, 1046677730, 3365009246, 2650242485, 79281379, 3069462836, 1131058884, 1346966266, 2182389628, 3425864155, 487991612, 4274615916, 3585882986, 3882253255, 3299152123, 3923136894, 4158963676, 1993380396, 3025592126, 3697510913, 26996074, 1666693894, 4128726650, 1349974160, 1162680197, 1002804513, 2192715135, 3733784449, 1296058713, 756389024, 985468845, 1910174731, 3512126196, 2889051038, 896547684, 1052365249, 1712208218, 2895783918, 4015271697, 4194906302, 1607592000, 488260174, 1247101503, 2635736706, 101416663, 502456820, 3004088397, 2217260735, 3689763077, 2750526303, 2814008209, 4290490637, 459845084, 194661656, 3298271035, 499760349, 1457282007, 1720527994, 283878558, 114686420, 207781028, 2101242696, 2475285413, 4066549966, 3571095625, 1456774526, 1957825881, 644287366, 859324850, 2429216562, 4069493991, 978462144, 4019464424, 269773692, 4086951598, 3169184115, 3840130624, 997907757, 3420447554, 999500052, 2700308046, 53871682, 1856963, 1188612325, 3393695655, 2729360995, 4101441780, 3357241810, 3598434336, 1257477782, 953991428, 4060500318, 1564349166, 1626434500, 1259685422, 4087690819, 3327437017, 1630386771, 3761712654, 226730056, 3668971305, 2810327973, 3857961937, 3773132978, 2859864128, 1937028826, 1803313773, 1721171315, 3641809479, 561594878, 3883288939, 1615573909, 3567576946, 53427597, 3447054169, 924172132, 289810649, 3166741000, 991317667, 72203781, 985172668, 3013352759, 2107570161, 3250293704, 4114482787, 1050030772, 1057622762, 3438626748, 2519260970, 159154610, 888655185, 471817829, 470991380, 2525869562, 257437760, 665926900, 2709862184, 3205674228, 1381649365, 1803460892, 4134101678, 2543649326, 1209534353, 1226459212, 3664518300, 2168714963, 3110951542, 2920091469, 280549216, 3763064171, 3139277729, 2961240010, 3997887886, 2249335682, 4125195068, 2179174964, 4200864330, 1948058108, 1468274578, 2376503735, 1402764211, 3508183492, 568398904, 3916597152, 1316008321, 3354808565, 243276170, 383567360, 3854059575, 3533629121, 450497668, 1613229695, 1579942631, 1479512959, 1708803214, 166236912, 3371361562, 1178374935, 3631449184, 1044231267, 43160759, 2872462763, 386332526, 1454108301, 463466433, 2881621607, 1902397631, 3675190003, 3262456635, 3682680678, 3921732891, 1604135368, 3949662129, 3129246190, 1954536251, 1538666313, 2274928374, 1650180856, 3652524428, 1821056613, 911456961, 840333318, 764118487, 2652399697, 2580502346, 2438391701, 2513677855, 2640798083, 2778108413, 3625988619, 3121963132, 2016358782, 2026634297, 2454141008, 3719526468, 2069512197, 595695222, 1372551058, 2654832919, 1312895472, 3449972978, 1039886392, 1219309116, 2158257939, 161673294, 1466523266, ], ); test( &[10; 6], &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], &[3, 4, 5, 6, 7, 0x80000000], false, &[3614, 4294966768, 4294967005, 19, 22, 10], ); // - q_lo test( &[0; 338], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3221225472, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], true, &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3fffff, 0, 0, 0, 0, 0, 0, 0, 3221225472, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); // - n_2 == d_1 && n_1 == d_0 test( &[0; 780], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xf0000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4261412864, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ 0, 0, 0, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3fffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0x10000, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4293918719, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffff00, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4261412864, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294967167, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294950912, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], ); // - carry // - !limbs_slice_add_same_length_in_place_left(&mut ns_hi[..a], &ds[..a]) // - q != 0 test( &[10; 10], &[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 1, 0, 0x80000000], false, &[0, 0, 0xfffffffc, u32::MAX, u32::MAX, 1, 10, 10, 10, 10], ); // - limbs_slice_add_same_length_in_place_left(&mut ns_hi[..a], &ds[..a]) test( &[10; 197], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4290772991, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 131071, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 131071, 10, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 1976632771194112527, 521304770361505402, 6547459063177486272, 16111887222588973398, 11964828684918293857, 9728747614510340318, 4267206348672680192, 10832398719275582210, 14900216064213533822, 6380760676681064593, 2849541272450836814, 18142033108417998751, 5641128336349728868, 2535172385342350806, 15911904441417898191, 9084408705773921949, 15744864820799189887, 4463837653601785361, 2987490935632187606, 11223238737559450353, 5105094309856727876, 1009868354752173181, 13484596105692600309, 238858926646454289, 1059132889701728020, 15279567309856499035, 517773561239225477, 13637839145813400305, 7302869346647374900, 1151876675162026587, 9504208398199632979, 8612638565635453711, 2164322139068363749, 15512475459854984520, 6875534824714840095, 16955948007577516702, 6471458936191368235, 10654427325707436522, 15337657345435735346, 15231031327469377800, 16046593431914105744, 8712679690677372756, 15831996438112202870, 14225387673292899684, 17347546671830406364, 7848557880774740728, 15226813436071672038, 14096480347669118219, 16389437176481235757, 7980211852778477130, 16446026267287953606, 7958418492797069881, 2213403156236979508, 8758841210279886543, 5431207818821342199, 10995901604046539947, 18335471104239998694, 13564698255420469178, 5867947764049999258, 1175284037301014819, 12349712146059439945, 6688979957099199180, 15522195128263747693, 11640494562411680106, 15737920193718148078, 3117055011815888766, 13625786892636999921, 12946533130762629275, 2401319620356150536, 15224229761057707791, 9402116507951822726, 17081785103310854839, 18332791217613728290, 400494137558561035, 12279775278166901330, 3814281798348375735, 16512813422954004929, 15443554440158194522, 9668157500068914212, 6053490056859889986, 803053277491258716, 13646927161616864743, 12206129576276588469, 8174515000911774339, 3036848877312472711, 11063940183681869708, 6310270877191259165, 9386179633193645060, 9559132660384619200, 8951064714492945869, 14166616301229473652, 13071629188826572782, 11853790173693535149, 209636673262143030, 10441446179239151884, 10420612973148232000, 11908054025560012662, 10909003530238644740, 5352309958024461387, 6231231241710103495, 5817566191981122394, 9966557507113270738, 2526734084799877406, 7119546382209824917, 11004099504334912785, 17101894178044846313, 17623127824006159278, 8521084772968581318, 13811386822752437212, 3432971939926452639, 9600964573924347046, 17748647615012039077, 13689755186761681519, 16574316982652951580, 16782416719434018360, 16144163416834277717, 2756565693629327141, 8059306003700661181, 16267666526611427826, 11909795646086424444, 943806121593842977, 13457826244859784108, 7239747548483360443, 16749825534693166168, 14426083390114861929, 17648467062688582919, 15758353298227492958, 8404753209561230712, 17152753483008477565, 1709121095849985814, 9192526565401365977, 5811560381076741655, 7570776248350537723, 10727029289681698856, 10402933617834546815, 8318965057148775598, 13169231870647857793, 12802647644833789786, 3875248944583119534, 12821268270102906356, 6572470769294941231, 647608152449604156, 1871144685026941083, 4032548946127357216, 16395335442808140376, 6736436429481567066, 1079601411786263878, 2504995255059825437, 6763393428021343788, 7715029394801749110, 11780543684841254832, 1383809532223095584, 14972882189077591253, 7800448071104479686, 789117789337480564, 14240769726663499540, 11053104839957580124, 14698906095810695206, 11960947912669574992, 12154539497540266947, 14003595352222612163, 9605483083077043861, 1678324429116079639, 18410093395270606595, 17901794159659874459, 4555659564807476615, 5907892309603612114, 6524803775567674587, 341147093193233779, 12996396640449564521, 6720226112934991484, 2388493664120597295, 4290799651574648025, 15852556922046266402, 2246578851767626469, 2920616190359978, 1995918845898424965, 10100917236583320084, 7326568532476915731, 15216155190727196226, 12275242131304351295, 5999272749153860391, 16885847068579318746, 2394902793719864009, 5326879392776369400, 15621103453348562573, 316702208555392711, 11540860887565649468, 18366619672720535993, 12809248756928885140, 7645410389657248491, 14015340112675676632, 2512410450534100064, 879480154877772022, 11649289287186823201, 3763895355294089425, 6070847093240149275, 1985095235894032224, 6801453453040268360, 2577579383099711197, 402372101655687448, 5644686065835595838, 2514710250566535253, 1911966914948814254, 3687058531887005876, 7434246748483727789, 14122808689973017488, 17766089471795036547, 6666390546144059621, 9594245591763828251, 10442127131744522659, 12010358916814662429, 11623966019504805712, 12883088750499797281, 15648374317449757761, 7443275395944491151, 2162931565418953025, 13144859518518203320, 14371376174232659599, 14565951115370759763, 7113822803057100738, 791629390390021149, 17035680947686192637, 16117534524053580299, 16569219763811788776, 12157015834931780538, 10769346653748666149, 1546686602678137333, 13300226369383179632, 6100259704952035034, 3072644701407984585, 4030070721794724661, 4784297440480155258, 8207888015979310860, 7318324394866297710, 1188255145714469504, 7497067679833095894, 831722367483141911, 3342006775070786183, 915228369324832271, 12214752361799071858, 7220077330608179732, 13269901002361366384, 13156705894018513856, 14069485524218015587, 16856376646412467543, 5458014833622408772, 16052033690985477131, 3853276807297699899, 4361733283329901315, 17976611431135375864, 7827211709974023187, 2672179408451719014, 13336920158316088067, 13989361937721365460, 17089134261482111299, 717462569675369116, 2677140142520744762, 12527274888132316130, 16020437139419307993, 5109175831372656675, 6967613605928103302, 10707316610802880961, 3751977410812504643, 3338250566945759407, 5483469392473217290, 17852350745219193880, 4273571006338555810, 14355529799772896463, 9097946801457959042, 6170305947438052682, 3686031910837362999, 13659812758484650695, 1078072280470978659, 10977423862490226031, 8329312879062820322, 4304430845375483198, 11670535966145436284, 9843819566701342756, 5423791105551635377, 15484617895300773730, 11737838788253883653, 17352638972287011361, 6417215765954491552, 5210838541415799099, 14459766465462519223, 11293780554786569855, 3913456812295604968, 10038604499286389380, 83285032545623676, 532455486041684132, 10447557457915823565, 13091470210751298878, 12472561867327718392, 14986754996345557860, 13353714167702784729, 14933692721559793075, 4392496650147061013, 14233597247368097070, 13776324136360206128, 2519461559911558060, 13447307564192855696, 17414679919154962748, ], &[ 13564422861878112234, 3275713182933072863, 9034480898755624920, 2219243711863369707, 1414795403602489063, 15894568837862895798, 5479009852840249103, 13548176561971981614, 7335026045847382779, 8888321385565889284, 1374250446640957676, 884800927779782031, 8670348570372777926, 13918154801540915789, 10563048209614776992, 13969791730415477716, 3452835315790744420, 7707311332988117775, 4057795468009662220, 503791220336896693, 11739899866722757790, 11508632709875839378, 2046257727824251571, 14147378955881967537, 7621816326428068081, 11992669611664635262, 4065021093573908389, 10481004349510473318, 10475301724256756509, 2524130821276975109, 8593134939742261716, 15623538309287845872, 12317584420983773918, 13199980610882090215, 13443389318588629073, 803739730193348834, 17830865805659102381, 11251151180776149719, 5892904253365508433, 17425282708969635181, 7064424708573252994, 11602656136970912939, 9321057698061643115, 11015344462881106465, 10461212970348321643, 14132875754655537304, 15753277783360549383, 12320964235023516733, 15957290977412221921, 15001559471941651986, 14955046884332716974, 10073992907091554325, 4815480386394792639, 2369717258966377146, 9248685362922918367, 11146342741382934626, 10126995575484511675, 10836902283955631137, 18212311536097636051, 4203660351079577016, 7620879273947445884, 3547199160053636344, 322234022833908928, 13570629391930072285, 14555015649158595870, 5365173841640051462, 18270551664241964745, 16860982171375384296, 1073487768765270579, 533079099712269200, 18402112985722301945, 5434269089519901126, 13639392734635113987, 8006521979690287885, 1545872313913044683, 15377554075787870730, 751964771297808412, 10798750359921054639, 11281008050931496235, 173570012084088260, 3794273797618100167, 7040606489685125833, 2026261595126825272, 4120208834527743861, 539222748500084412, 79750673604550443, 17475108564705202581, 7592139295506453445, 5023893374592386852, 2824914523935320076, 3238624402000298552, 14131756234617118206, 8788539332133441603, 12952024446070112298, 10155295021066454828, 3941570600498808512, 6414922728964194522, 4076629519262102829, 7536766196851355087, 6915125713337987783, 4580280718549432890, 10168080122054976212, 15909510579919558189, 14519226511270844173, 2083762604858883168, 13387991133148007718, 16840836457014280191, 13080359029893923590, 11503510372644227919, 7953484793188318118, 9854115240624462348, 5335772307682974862, 4936183703810019894, 15994627285462031439, 10709370317657097612, 16199196738320076993, 14938272361213950876, 15253370694640585418, 10690065705918307042, 9549292542903499984, 8643187064435534254, 11624928373665837384, 8023398739766654926, 17499066444790402375, 9801044615559621440, 14552811277630127749, 13492161609355707245, 9655752034551803175, 1755722784425137866, 11625636701478868329, 3624227495361674626, 16165268009822921837, 8092810235043787525, 5788572199295079813, 6854648148487456329, 14456461148456692547, 14310121083997049160, 7059162200334339773, 14727298439147858639, 2177197582567289597, 6545559818086725189, 10527371808810639250, 4564586802867503950, 2652020551780949632, 6405684903154669518, 1737731788352731098, 3469893625756210544, 15065635631347129418, 13174028003011531358, 15454741792218022113, 14370595360570179099, 18037934040444240682, 2964154747013421979, 13884952913031178416, 597641522633545753, 13985314547491780345, 8360203218690496165, 11794669667587913233, 8996326275940748604, 14117671113926503561, 11301961759403099265, 6700188071922378791, 15385674866154542642, 8468030983307924915, 7377911706704156399, 2604656541341801794, 4418057625951919598, 2110519074747192474, 6101102874337817025, 17886250954206311063, 15712345996698736982, 10487961467211158758, 7074394084984481200, 9751971849704663337, 7679893214057488711, 945225664530152672, 1245168954077749403, 9513611114031241898, 10766452668861159380, 10755131449239090448, 16388278488885030616, 2817843987791967489, 11763453497935146995, 1092574082244810895, 1941447274495784860, 13572786039056178918, 15061182291913076311, 6679943993103806154, 15408371401907582553, 177747470770242167, 15593976009786423347, 7461104255684909887, 5044076910420087327, 17630612657815416743, 15051698319468276092, 14951988637957301647, 954336914910981662, 10967373098940345847, 2121680414874388243, 6976201562796491998, 6607602757564910564, 2432806802785175299, 11440086710224789398, 2224788034891182999, 5665602195014987730, 3821334059850073126, 8765713375749646572, 933515038511209109, 9433768612524189229, 2467805208666126785, 14871840927317419092, 5154749137613554029, 14265822875736809648, 14610870159067374513, 12698797236213924014, 9569606658962541579, 16162107306292390178, 12212893918580781835, 4614977216445016679, 1352141803214945397, 7426333917406258422, 14520946858416385440, 12446204685829260164, 2067433179439046305, 10861419565872522342, 15042750574419434699, 8969751642165063673, 2375359711870752032, 8547092847092151309, 3254399133444460923, 6176880426174028076, 1267184736498266698, 6443556206710696839, 5582660421956028475, 2003441447753754180, 14408039201078176692, 9878715208788868318, 3156012596211387511, 2621328682710618956, 1343996423359983728, 1659922365403643436, 9104705095152231651, 161254471946633022, 17082420100696680164, 12948458999893309534, 169193814558716113, 11181197557527273709, 6214014612630290060, 4852610222569086650, 4759907655510719027, 16416424951651935524, 977804021685057099, 11673776803881765160, 4922236924628996318, 17921361428612029549, 9649330011870916482, 620643376032400196, 6391102220914894427, 1331509376533438689, 14618159860008486331, 2457140428084980479, 14239221334508169296, 4552842402472365258, 13656369860726864138, 15616197149307562605, 4979886663474976519, 3721352528085365632, 10207378704552161011, 14450395034610232613, 4394727065169978678, 6225996635016717724, 10125465703568602374, 12627017260126529357, 6034795013566274191, 14507135436863373853, 670092389362258666, 16892179404337461285, 17907525342655368510, 6388033394429406697, 14608221204689506984, 9725811389591747512, 15841826865041066838, 12726453974670314753, 5294708137059751589, 12939898091011681833, 17545561031992221346, 12940997953067270813, 8668645445261571392, 17465976365740637310, 3297459757903247617, 5595819579374915626, 4255310297204286682, 13444083690317354200, 13079687451729978985, 17936788196509077492, 4731803836376614325, 8488258826257443557, 15872298653522164970, 6136303961972758860, 8203587474223770207, 6640840421159816678, 5369017699494121011, 13476518943592512132, 18148180997156310554, 16551428108902177352, 10607422095455667650, 18070526307796619350, 592194588928348733, 9500655832933342555, 15906694991065813017, 5672170756115546545, 5164713544570924308, 9654099190010511616, 15467930191553249033, 15324226386462646310, 11654051669492811942, 3845504882613220875, 17995014637765041183, 8451419834021139432, 4831660661140974858, 1270713005767677247, 2854249945191704862, 11336191586387214070, 6230352080584748033, 9904554377773225787, 13646007744312337579, 12876135209922183651, 5590478105512035067, 16683787122041782881, 2912257455736462263, 1161124723702057201, 14599086761545813923, 13759995150092530098, 1187669969167762513, 2025210147021211292, 8404792573797774696, 6043699170259360346, 8567182735917474580, 11673587056707375436, 13729589792471955572, 6040294236876235718, 14118883879821257022, 1472762515001555634, 5772607514220590032, 12005167700240721094, 2562574981556592924, 4322916215476956068, 2931397736166450113, 1981334131663903720, 14008950785795439721, 2258367698152396200, 3193592957432138332, 18147159661113326998, 7636102688703700127, 2455873680142820545, 13327423214878219110, 12145648468670490988, 177980942656438245, 7435164945754514167, 14611156817208949574, 9482801842425137904, 17579649951803679316, 4395194171697397116, 2246099311908860608, 2326078108126869227, 11810587602203652970, 16265527186229236462, 4210697026328134418, 15046104816787660106, 5661711221409653164, 13045157006959773220, 6999069520359938726, 5808420710659641279, 15787347158818842535, 2851830421850001378, 5525485631561271262, 711754543881977867, 9906329062827899634, 13595975648907914352, 15095498981812294732, 14827890138173702931, 10114436220688049709, 7728356353192609902, 11254468346316497641, 15153773712001763014, 10207835043420703649, 8801897675976972272, 2550825610727592889, 4806829881527541342, ], &[ 1408954216269482756, 17495363275392015072, 7569538419880562930, 3159444535690624422, 10539713616310108624, 12287759471187878632, 10762226695213450386, 13702928698805429873, 9308039037015276334, 2693272575243867415, 4495731759682297278, 17957718702553480973, 1695225019270301796, 12538720478819195709, 7355696648235750501, 14609468359145504152, 17713212205059712263, 7067761757765748297, 4455678910009476432, 14940946772952633580, 7353223946372247705, 1966704175929577612, 17788828899639927690, 5873642145421053485, 9432511011769375502, 8011456734513040486, 18383517818628757190, 14804344175107599111, 14453706668928035575, 212174636863869640, 18318201713407159667, 15868508625313800988, 794570724775389143, 6890250104153732120, 13215618552493662151, 15355712080025289288, 14989269405365678703, 3440332781177776817, 1547041711400466409, 16949408083533983339, 942645885575525869, 3593963961417655151, 4158508676658397508, 13468348757333127520, 11862936891535571513, 4377454676311890507, 13780065204467937543, 15803361323352221769, 953489208716892192, 17364437917524369478, 11384216985369504647, 3360175615399279011, 7215910295314039412, 4449007827158713949, 8690290001027040683, 772293093052269703, 6926666182768252467, 7985255216129545232, 6665284360882852586, 15207741179893001845, 15703767897436764321, 7914253539478783255, 5903013543557664007, 4774214457440373599, 14080179030683024826, 9434035144822929636, 5367813517486193633, 3304878828952757511, 10243535705902406930, 1884627861659715947, 4978189310017102374, 1216698964122740709, 15100941079818973803, 1749141348527036567, 8743320843818547513, 9958778070878908244, 7858295599866849905, 15078222426471283656, 7336868524011917281, 10555852968409722407, 6944256015177961916, 17387864131687949624, 632732732269768198, 16900672962472231809, 13484064257890193159, 4044769021954392546, 15294554445007953309, 330214884931606053, 8773227351193839544, 9933428285510948540, 2903959890557503867, 6265719520493470019, 14025203023893391008, 11647283945890530059, 13249598051183746227, 2074546550971361923, 12247825023511227150, 2784768583222188866, 6407637641382682182, 9752576266849520115, 15195951757710781232, 13752087641373844065, 15476511142100387305, 14236723356162907578, 10822337465577716429, 12814664143156135314, 10894509357772940167, 12457195754516214135, ], false, &[ 13415846491005578619, 13584292933077885365, 441953663009890135, 7210335717300495676, 13057964354000775464, 10292169585687982086, 12251907425151490553, 7386686741811236397, 291437469999876541, 1843506473757893895, 1231339981456887992, 7336311449497199296, 7176633324357201366, 658513238018005674, 3117977571063681035, 2261787922928337152, 4069182574784670800, 4786347950692670036, 955338065659184695, 17893231513983993127, 15970449235194675852, 18222079201306580439, 7381385984359606163, 13894071053001480008, 17968185102194547794, 9652567975385349040, 4579378768094593374, 2929413774035294909, 4858585721157204024, 432346869077563062, 16632527599028610709, 2969760407998231671, 8723191162795424532, 2205885763249224226, 4090893610978417832, 727335411538814681, 692739901795118471, 16185752384798441976, 9407352218349207860, 15954006133480937416, 16002700437312273924, 1803166211419435125, 16572732079534009876, 10103383220489568096, 14055635057552795086, 6204301430393608593, 16304361060342210151, 1077463458077785016, 846584174947782921, 14549143985217156839, 4794451719446030954, 15070589344871049989, 11768766648218861349, 193778540633917339, 2069627918507475641, 17004474480886564748, 6387833454863576557, 7403048767127663654, 6361857152378524096, 14590329534696373089, 3264224706753004828, 15794673518624161617, 8471728032197957118, 11123707683472607781, 5926672570922373756, 8353224757488864005, 3920855214133136556, 4088762124331852387, 1351340558126331083, 1064663312281497792, 6722208927949900059, 8191142535859454935, 13932575231193375718, 13250838834435891833, 2482941775014508642, 6361967846756283686, 12230741962057003367, 5322339673572617872, 2461502783752535986, 15456869581410217577, 13516762109813035487, 17722517240817407655, 12006022535464060948, 7693156444704391120, 589139607677986600, 10992862276542439592, 15638442660969354281, 6302046879465388504, 18186347373545845422, 17661768623582090594, 11182202442217703360, 10323032349274612161, 351359225361309232, 17208481651320700686, 7762799900361196225, 18130637050502143037, 3527936976222881348, 7787458878406549730, 9785865244475232340, 9313322536748638436, 6628693715403354820, 8155584772586242242, 4298548228131846405, 6216995875383402160, 8745213713616642956, 6205924554981340524, 539046468165950413, 9024163979699199629, 7137709973749463062, 4302338034003647906, 13829701518024075554, 3020599208667394924, 2771484371923677669, 1332418334924131169, 15030111211658663300, 8687405539746619117, 3255425958083223853, 17607580850311952887, 6117457031153941598, 9667238428907972490, 16866165930381488058, 9279876560625206616, 7219817020774185353, 15408311020361635593, 10627051636551065581, 15435960991076989754, 2125427069228602466, 14834800748267676770, 8338000901565415696, 9843107756445251924, 11726258180166518722, 13216133507413853832, 9548542073000115784, 4477904860207934342, 11559138083775928810, 14261941916295954455, 2935454921278307407, 14578760607502424030, 1741904848044422540, 10910867960823424013, 16471597397244360629, 5831225248121651892, 12850983616913099920, 4576475941872797279, 10819576084838658923, 9911449990461349025, 8071318423647144806, 12934895766920841548, 1934332324237869529, 1138130330895714883, 7749002603757035655, 6467404987016890639, 11255316830064030538, 3018235715458169811, 15201809744582983527, 16342498733210722843, 7708152387679592258, 9492172974580805134, 5866422978520553541, 16455719455662584469, 13731761368830060542, 18292973038079145164, 9007521683809498606, 11536176422926297746, 17069970006150149865, 2103718123709857344, 9551485804718272266, 12273976131107017479, 1653874358479460972, 10193109839436245173, 17209319149808494347, 2304536837571895652, 6062765286861083817, 4897491367356012054, 10921490709194148600, 7489492882796549046, 15346457168511978884, 15415284042926257534, 3288025229571018975, 5490937743897191968, 12030244067941846502, 6649465014690650122, 13043829245604474765, 16104656800587069133, 15901113890052229676, 3837090179127712297, 2184801241947831767, 14724333584011117924, 18042748113599866974, 15635242211549384225, 11210521843889130992, 9474616548314628408, 7072588307383545068, 7764739347402168434, 6456269087620448997, 13468842728337937173, 10407803768686058347, 58702129805853206, 9751180010069185513, 6064452714620219927, 13392800693556694325, 18372122025912817085, 7516403896475345556, 336160785595278081, 16607869224650226242, 4883984113455670464, 7621647467206333443, 7975633505870931502, 10173870707804084376, 15734058126402681870, 13198172970791238175, 6074102067907439304, 7289841954562682843, 16642477840387047386, 17735102900144975086, 4380312697910692464, 17348779887199611248, 3519767210720195345, 3200318167890176110, 8763164776273977859, 6372373083461058525, 7012561740996573104, 16229141474971594905, 1111767702608658668, 10378536678592366267, 9247600318566456250, 17456358751309498336, 8398075459962870518, 398315841023187114, 10277410686246662542, 218781901157848211, 618572494658903822, 3804414506632334467, 17482725095963661462, 11945563631700693151, 11377949134930807832, 11388696917522764394, 12397282866398662460, 17984588793337249647, 11852155346818929323, 6282040579217154095, 5865043035453987718, 12490608990412245333, 8662459463589993440, 9703534627155947683, 9083465368456889169, 17385583284480619421, 12619315429611258952, 4780803560699965289, 9760114025973133776, 6710382011811335688, 4756178837305619434, 11338794508489062066, 5806084365129173257, 5858402760317423580, 16972385428332971155, 7980041598360573257, 17539414382812231878, 2807108495977968496, 12347721638665260177, 2657388420803290454, 18291179742275985307, 17290651979906283695, 18248938193230918423, 9700793153607985827, 1581581530211316863, 421641550279827055, 3550734485990309734, 8838675277867213091, 2325841972611425748, 12896051317905757266, 2634241676839630629, 9793375243415420023, 4956535453535085870, 1394001153426732084, 12161423949049475376, 3204414789776213360, 3766999954663739543, 2885444883803065223, 17796581505208708505, 7118003311319221436, 11737838788253883653, 17352638972287011361, 6417215765954491552, 5210838541415799099, 14459766465462519223, 11293780554786569855, 3913456812295604968, 10038604499286389380, 83285032545623676, 532455486041684132, 10447557457915823565, 13091470210751298878, 12472561867327718392, 14986754996345557860, 13353714167702784729, 14933692721559793075, 4392496650147061013, 14233597247368097070, 13776324136360206128, 2519461559911558060, 13447307564192855696, 17414679919154962748, ], ); test( &[ 3218961335417250355, 17081672491164411676, 3707650621435880034, 12226464081058805510, 16651181251520783855, 13640009159697172462, 4751991872429123135, 3148650123879180586, 1277783667166791164, 8130851378765417486, 5973994279255982458, 9850645253643520175, 7138807895287208194, 15375995502112115974, 3398898578710810979, 17572162751360544244, 8819660083286717264, 69135776031233389, 9998360095371859020, 1528928997031509791, 12805160204156629031, 8189615704171780683, 2467675461409164019, 782953727844991423, 6355321416294201810, 3548418573913501932, 1385195069445654350, 13512602943141297700, 3524217759662463436, 15981277851376785202, 12068598413178807016, 18233498041601520144, ], &[ 18165976559003511263, 9223225080462702306, 8750698670891994416, 10120417502780222451, 7032717053294267869, 7737301656727013632, 18225658593706260392, 7369113716849300883, 6897596754170972342, 12718107066356504381, 9547303833255868241, 7363473626086637667, 1289803166471838781, 11172671997578955149, 11576917227142009738, 4808558430339823806, 14087513123418218680, 8335805388080937297, 6817204158716710723, 6461426422998966208, 1365262330733891893, 9676053381450021925, 13152204186994838090, 13956491013462127564, 2322954839434490857, 6310077930127744700, 4095927283220333117, 9197971078622697427, 16090563028856198822, 11899164972605215873, 7553212707478476751, 1757047503535568327, 14107358592894281225, ], &[ 2828382444363234501, 14019650302598222399, 7149153771500111721, 5808789510078375243, 11746020933581287784, 13963712573526024090, 7948303882471336756, 1363675852130084180, 6084755510768204882, 1350344795057047203, 9774965847686534495, 3240922473188564283, 15530555198365657320, 9503969704425173615, ], true, &[ 3405376264873912531, 12732472809437054653, 130818493222944537, 1430180103580323943, 11834290994594767473, 16311544963273773940, 14852866940109114958, 11049173384187452405, 17390023561952283067, 8415736510262004193, 7352370979091376738, 10787900486113600253, 15465246806979411530, 12013049514342915482, 15910934446693912634, 13226375350164320552, 12041814675416282230, 17264487603347577556, 8934954480948017545, 1528928997031509791, 12805160204156629031, 8189615704171780683, 2467675461409164019, 782953727844991423, 6355321416294201810, 3548418573913501932, 1385195069445654350, 13512602943141297700, 3524217759662463436, 15981277851376785202, 12068598413178807016, 18233498041601520144, ], ); } } #[test] #[should_panic] fn limbs_div_divide_and_conquer_approx_fail_1() { let ds = &[3, 4, 5, 6, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer_approx(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_approx_fail_2() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer_approx(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_approx_fail_3() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer_approx(&mut [10, 10], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } #[test] #[should_panic] fn limbs_div_divide_and_conquer_approx_fail_4() { let ds = &[3, 4, 5, 6, 7, 8]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_divide_and_conquer_approx(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } fn verify_limbs_div_approx_2( qs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns.len() - ds.len(); let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); let q_is_too_large = q != expected_q; if q_is_too_large { assert!(q > expected_q); assert!(q - &expected_q <= 4); assert_eq!(expected_q * &d + expected_r, n); } else { assert_eq!(q * &d + expected_r, n); } assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); } #[test] fn test_limbs_div_barrett_approx() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; assert_eq!( limbs_div_barrett_approx(&mut qs, ns, ds, &mut scratch), q_highest ); assert_eq!(qs, qs_out); verify_limbs_div_approx_2(qs_in, ns, ds, q_highest, &qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len + 1 < d_len // - d_len_s == i_len // - !highest_q first time in limbs_div_barrett_approx_preinverted // - q_len == 0 first time in limbs_div_barrett_approx_preinverted test(&[10; 3], &[1, 2], &[0, 0x80000000], false, &[10, 10, 10]); // - q_len + 1 >= d_len // - d_len_s != i_len // - !limbs_add_limb_to_out(scratch_2, &ds[d_len_s - n..], 1) // - q_len != 0 first time in limbs_div_barrett_approx_preinverted // - i_len == chunk_len in limbs_div_barrett_approx_preinverted // - q_len == 0 second time in limbs_div_barrett_approx_preinverted // - !(limbs_slice_add_limb_in_place(qs, 3) || carry) in // limbs_div_barrett_approx_preinverted test(&[10; 3], &[1, 2, 3], &[0, 0x80000000], false, &[8, 10, 10]); test(&[10; 3], &[1, 2, 3], &[3, 0x80000000], false, &[8, 10, 10]); // - q_len != 0 second time in limbs_div_barrett_approx_preinverted // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_div_barrett_approx_preinverted // - n != 0 in limbs_div_barrett_approx_preinverted // - limbs_cmp_same_length(rs, ds) == Less // - i_len != chunk_len in limbs_div_barrett_approx_preinverted test( &[10; 100], &[ 1940112928, 3379564708, 4199340399, 1881321211, 3929726949, 459862695, 1350630556, 2137584308, 1243785894, 983397001, 140271427, 1266031183, 3559919295, 702977622, 3883080853, 1830599918, 3030922777, 2650241556, 2807154392, 2218698435, 1904442293, 2992923456, 1481791037, 4079300846, 2680084216, 656285791, 3396057405, 272065717, 766725345, 1681255263, 1707458816, 1535744308, 3830462997, 1607479268, 3475252676, 933054715, 4058518411, 1139150315, 1176656025, 2657461768, 3149905151, 2833828072, 1407836276, 189062495, 3008111084, 3911286362, 3969377587, 520858887, 1921886086, 2410034665, 1853865087, 1218625232, 3157059817, 1933332942, 1324005415, 2613648167, 575584498, 1622716448, 2776523679, 1406325147, 1675354862, 559193409, 3342355233, 2906475403, 692112491, 30493944, 2020871018, 3990740411, 1951624334, 522929143, 339689612, 1674309350, 1834377980, 548522470, 1069818460, 3188037910, 3867849691, 141774569, 2470564281, 821388456, 4277724930, 3388680598, 3502532015, 3274512650, 734688334, 1114445519, 4090718315, 3618580673, 2579392987, 1832470019, 497126331, 752679886, 3640533944, 1359185510, 2078361523, 766787155, 3847437498, 1508816472, 3627438612, 1634541191, 742795696, 2960390854, 3550088312, 3226573591, 2822842868, 3362189143, 3928024536, 2437449313, 2184757656, 3728018796, 3935919847, 948513362, 2073970870, 135663041, 2352180020, 74067810, 2805347538, 2583013940, 2822521171, 3940279282, 1038996723, 1890047439, 511776527, 3353284478, 2377633924, 1797661892, 1357303377, 2035070964, 1462275246, 529813385, 240201619, 2189253653, 736920794, ], &[ 543800634, 2770754899, 3204213496, 689485059, 1826336873, 1076055628, 4272024858, 559589670, 2749860031, 1191446963, 568428784, 3084221767, 2956512443, 3015109082, 4142890122, 1553810981, 1616811544, 2640988818, 4239702102, 3215569246, 4002923809, 2144877501, 1973532991, 4210632120, 245033969, 3777546533, 2341963108, 3264590407, 2911498298, 3029909661, 3030243778, 3822448105, 3778161582, 4002513281, 405410583, 2595147981, 1384025271, 2688968055, 1208777176, 1722256783, 1319267870, 3011578504, 2249499744, 1245802205, 2315940873, 1685775875, 3654277152, 3113432869, 924331621, 1024360203, 3411941166, 1488722938, 14894550, 2976848938, 1792408550, 1006468168, 758547548, 2693569089, 268361906, 3490575936, 2248882501, 3137929560, 2509320863, 2201587434, 926371577, 1243694325, 1112023631, 2791032478, 4081106682, 3051719441, ], false, &[ 2057668, 2838783492, 4112571934, 2985797927, 3502010766, 249276105, 2839050469, 4137353790, 2017993048, 1573570544, 2879477808, 2277205117, 3638192330, 748457752, 3491012018, 1271254053, 513425262, 1211823879, 867012819, 2598440433, 1263651369, 2021347718, 4249300861, 2804939275, 2973559875, 4064802504, 1895088151, 3564064077, 4027716297, 3914830075, 1990115176, 1854504344, 4070846044, 9890028, 3874191625, 3177041731, 3239277327, 1987223315, 3008019786, 2383741649, 1213911302, 1443565130, 976567504, 3330200204, 1895735680, 141240306, 4207639562, 4048459734, 2216965594, 4199097617, 2357661853, 3838741723, 3334878567, 3391363083, 1245835070, 263088765, 3602928895, 211195285, 1878503011, 3634753202, 1476824331, 2380710600, 1037136857, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - n == 0 in limbs_div_barrett_approx_preinverted // - r != 0 in limbs_div_barrett_approx_preinverted test( &[10; 28], &[ 1289672612, 59863601, 2751157317, 2012015018, 753744884, 727617566, 1322732201, 3978203284, 2280484600, 3096956045, 3846897372, 4039916165, 3268087487, 2544740714, 3583698031, 3555712249, 1472500374, 3434100279, 100408066, 1521129569, 3806609799, 552198579, 2644816287, 1159339267, 3543498888, 171157498, 3510108197, 1568117536, 1428232726, 2356104756, 64268959, 1999542893, 1166391479, 4277110967, 3494387915, ], &[2774518906, 1389562763, 2693574400, 665477625, 1306831105, 2326033317, 2701983394], true, &[ 1959935944, 2176722772, 2263227298, 52031251, 3734871887, 3327523565, 110124788, 3702612244, 3495588882, 1155949119, 2274365757, 1700149681, 157693893, 1287343110, 1404704510, 3815550465, 1225032011, 1088256607, 2172622843, 4270557118, 3435679666, 4256455092, 679164912, 4183948729, 591513024, 2958428852, 959546540, 1259575285, ], ); // - limbs_slice_add_limb_in_place in limbs_div_barrett_approx_helper test( &[10; 1], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 524287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483648, ], true, &[u32::MAX], ); // - limbs_add_limb_to_out in limbs_div_barrett_approx_helper test( &[10; 119], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { // - highest_q first time in limbs_div_barrett_approx_preinverted // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_div_barrett_approx_preinverted // - limbs_cmp_same_length(rs, ds) >= Equal test( &[10; 100], &[ 2117335661666050915, 12541399304153348003, 946298540148951811, 3706040940807058638, 8245328193712015182, 2995778607291858486, 9642363239685223935, 6402096640921797670, 11712805591752250715, 3201293761729543527, 2067868456322875388, 14022668248311848844, 4632052274282811479, 14328717146754990094, 14774171516395200100, 3932090441073088420, 257112211266950213, 8641538702124596212, 3125093651287853737, 17086253003900284664, 13301324934271401692, 17351307810524827327, 10929578147013387375, 15271667824914109078, 14749348389589883650, 6533201755640185223, 2371674840347488671, 4979324240277110920, 735115859885293605, 6735013534832335382, 10119392873034328735, 8587971333550618807, 18370051728122323147, 9585925514203520684, 10610241536420552110, 5468885590163205010, 9820231198117134549, 11691363752858795073, 17305814922233352619, 859726499782635315, 191600792977201905, 6645113919639439987, 10186139014514132915, 13892914247169168407, 6236711305574503596, 11144904233279320413, 974401940116314268, 626033050094744466, 2363222200699405972, 5179961716326453662, 1671413606631599949, 16140149794420865699, 4525104777442472653, 15677954115433676863, 2638708390995098468, 11988738016208980482, 9157465979869425297, 13700136748402110667, 12843998927271872117, 8172056912358636191, 11114503332573068878, 12203499984806198697, 18293693840507282811, 2347317225764209541, 7620549999680469515, 266221208971070149, 7404318409115354801, 11821070343886468455, 16743495774393393347, 10903651574167871901, 8120955791898229966, 6256918112663531036, 4642094091398991189, 17666442779793022150, 6979752362584161816, 738088006020097171, 119461506395194534, 2707265934504496803, 3596152365672913357, 14919229675768492176, 15711892957093044137, 4388966441873938872, 7245386709333796615, 977953205631793823, 5781210341467685855, 5753014960288580146, 15207218610262659062, 4952531357988639834, 15654095960314850064, 16211757785947051034, 1847823176222065635, 13267820071825624266, 7825351897308816877, 2314230949902785215, 13036201409691464885, 6084371089556728596, 4297442532874624612, 532433185229873311, 3442779195445707888, 2185935771567302024, 13911571822971487392, 6709028122157209948, 8941147419783910451, 10057960523899590670, 3902932452596575823, 18330616827289950879, 16003030155941114765, 14460484829934394726, 3301932590566986553, 2576945510271437558, 338533333586368208, 17133311687376929054, 15155994049404735760, 9946561124819597870, 983339636912873569, 7933316580780536493, 10915381430875882064, 12068808550152064359, 1144295877076351834, 6170469241760056335, 1371470265702819753, 8726850576136926792, 10647848489928733096, 8768829048069168648, 13771635456188648954, 17554939941431219329, 9462385985825033541, 748159237152854524, 14199895651244313572, 9044210482484213648, 3880401870711113518, 1694971440240542063, 13547801197479934494, ], &[ 6673567349177488920, 11342960606651398230, 13810764753596302625, 9212178722694740287, 18084527251132181489, 16224438820695147876, 14021309035811827770, 13013362906859690434, 16417289605410335662, 17190663644106068759, 11146075708059454647, 11549029857422506456, 7397036559618436638, 12934631186266104928, 5350679730075628553, 7240352255165061152, 13372092351570783845, 4399593574620862254, 6394016331529930198, 12785468835634740198, 4322747866783581276, 11568791147039875250, 14991909491573471557, 13477304839860990623, 9455746029240930041, 5341626453207818831, 11987393219164946170, 4239560960510469879, 1182652798618482486, 3574433530016984198, 14570885001650188449, 16721218276523736662, 17582595396154395868, 10645279465349745085, 8467600286036697431, 1335601409485137284, 5427053117344459552, 3050086815044747081, 16544140034308828175, 16944072159927844572, 1776035917115670079, 6854263689321209087, 1395326973393056556, 13328497288435313800, 9104953879994634550, 13847967313738589938, 2043265995513605223, 13193995464379134227, 5009710316527156329, 14279264770257730496, 10408308917163910844, 5580572910800173671, 3609059974654018173, 8878539685629369010, 15620596077589725028, 3646029498286920979, 16172850651808491619, 15245408082837971190, 4561308773951735888, 11261441942590830857, 14221474405402406790, 2504490064796610713, 17165895347857529984, 12091565718300353127, 14873026879861808494, 7208276890744094311, 13958391986410864884, 8096376858901544433, 18161016816080485352, 9946585096298233506, ], true, &[ 7142549011416014880, 14684691169135507473, 1822120729679146161, 11841933122038769821, 4526355225639296177, 8468787586279727777, 15714230407431964682, 18333537779008451159, 16040493219692071303, 2049960712985714117, 18060699260844232006, 11436218371188111964, 18247749997104652519, 10208028585116703246, 6519062707001442120, 8663593385407998358, 9429327332580418592, 11147294715178482267, 12622325713357218079, 9917628001464406797, 8948638694752077597, 413202514200140930, 13469381266876650437, 10995920589784133757, 10156568832733545237, 7515628739788185693, 3313803886141758450, 16133860033309869788, 13595249790827433309, 1761826376674293671, 9950121844277925507, 7711011638364466454, 12239101884168908635, 9962222649144848616, 9495651849838993161, 10726943428780681871, 3103236698633674082, 18053635426183322245, 14277576247420605289, 17591792639916063380, 11239385027227950840, 4103032036605369386, 266316975199678275, 4262765348359631356, 5507126713842059802, 8339639832375105582, 9642119792134182293, 485127249403759007, 3452585660397695342, 17804977833202015222, 1531864037104263565, 12597964144177527097, 2015301325553239081, 1705158706504614015, 3632321048208706170, 2599148812642503905, 18033201044296677048, 10122148881615284352, 12336433997173007311, 8939795914080226824, 9195323771605999386, 1966840646595138765, 6678745632744258779, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); } } #[test] #[should_panic] fn limbs_div_barrett_approx_fail_1() { let ns = &[1, 2]; let ds = &[0x80000000]; let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; limbs_div_barrett_approx(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_approx_fail_2() { let ns = &[1]; let ds = &[0, 0x80000000]; let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; limbs_div_barrett_approx(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_approx_fail_3() { let ns = &[1, 2]; let ds = &[0, 1]; let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; limbs_div_barrett_approx(&mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_barrett_approx_fail_4() { let ns = &[1, 2, 3, 4]; let ds = &[0, 0x80000000]; let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; limbs_div_barrett_approx(&mut [10], ns, ds, &mut scratch); } fn verify_limbs_div_2(qs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let expected_q = &n / &d; let base_q_len = ns.len() - ds.len() + 1; let q = Natural::from_limbs_asc(&qs_out[..base_q_len]); assert_eq!(q, expected_q); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); let r = n - q * &d; assert!(r < d); } #[test] fn test_limbs_div() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); limbs_div_to_out_ref_ref(&mut qs, ns, ds); assert_eq!(qs, qs_out); verify_limbs_div_2(qs_in, ns, ds, qs_out); let mut qs = qs_in.to_vec(); let mut ns_cloned = ns.to_vec(); let mut ds_cloned = ds.to_vec(); limbs_div_to_out(&mut qs, &mut ns_cloned, &mut ds_cloned); assert_eq!(qs, qs_out); let mut qs = qs_in.to_vec(); let mut ns_cloned = ns.to_vec(); limbs_div_to_out_val_ref(&mut qs, &mut ns_cloned, ds); assert_eq!(qs, qs_out); let mut qs = qs_in.to_vec(); let mut ds_cloned = ds.to_vec(); limbs_div_to_out_ref_val(&mut qs, ns, &mut ds_cloned); assert_eq!(qs, qs_out); let qs = limbs_div(ns, ds); let qs: &[Limb] = &qs; assert_eq!(&qs_out[..qs.len()], qs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len + FUDGE >= d_len // - bits != 0 in limbs_div_to_out_unbalanced // - bits != 0 and two-limb division in limbs_div_to_out_unbalanced // - carry == 0 in limbs_div_to_out_unbalanced test(&[10; 4], &[1, 2], &[3, 4], &[0, 10, 10, 10]); test( &[10; 4], &[1, 2, 3, 4], &[5, 6], &[2624702236, 2863311530, 0, 10], ); // - bits == 0 in limbs_div_to_out_unbalanced // - bits == 0 and schoolbook division in limbs_div_to_out_unbalanced test( &[10; 256], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3221225472, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3221225472, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], ); // - bits != 0 and schoolbook division in limbs_div_to_out_unbalanced test(&[10; 3], &[0; 3], &[0, 0, 1], &[0, 10, 10]); // - carry != 0 and !highest_q in limbs_div_to_out_unbalanced test(&[10; 3], &[0, 0, 2], &[0, 1], &[0, 2, 10]); // - q_len + FUDGE < d_len // - bits != 0 in limbs_div_to_out_balanced // - bits != 0 and schoolbook division in limbs_div_to_out_balanced // - carry == 0 in limbs_div_to_out_balanced // - *scratch_2_head > 4 in limbs_div_to_out_balanced test( &[10; 3], &[ 2004133373, 2208332663, 2302126873, 2101318142, 1556208712, 845422188, 1055855393, 3791075321, 2255139682, 1837642188, 3011157525, 2408855870, 3298400249, 965057055, 1159107131, 881492493, ], &[ 1319347431, 2633328929, 1132813012, 2337676551, 3505724291, 3258373855, 2627638070, 4109307798, 2791039276, 3812830525, 922865115, 1132868227, 50383791, 3208398854, 737302397, ], &[839942670, 1, 10], ); // - bits != 0 and two-limb division in limbs_div_to_out_balanced // - carry != 0 and !highest_q in limbs_div_to_out_balanced test( &[10; 3], &[ 2004133373, 2208332663, 2302126873, 2101318142, 1556208712, 845422188, 1055855393, 3791075321, 2255139682, 1837642188, 3011157525, 2408855870, 3298400249, 965057055, 1159107131, ], &[ 1319347431, 2633328929, 1132813012, 2337676551, 3505724291, 3258373855, 2627638070, 4109307798, 2791039276, 3812830525, 922865115, 1132868227, 50383791, 3208398854, 737302397, ], &[1, 10, 10], ); // - bits == 0 and two-limb division in limbs_div_to_out_unbalanced test( &[10; 233], &[ 1120072065, 20030636, 2023698558, 3410014045, 1693005413, 3940821177, 4061897489, 3904598150, 1239781075, 2248531977, 1084346740, 3406083359, 715154118, 3499417710, 3315749667, 3834314996, 3974469907, 2814389907, 3511455607, 3248220325, 909379929, 1899385878, 877989498, 598994477, 3240673535, 2330636314, 306792275, 1197844499, 516880032, 2699904331, 945876341, 4162862896, 2209400052, 1190718041, 1558127761, 743003038, 846606641, 167779957, 442248369, 4254081958, 378292991, 2269632031, 2106325614, 2903467429, 2325283078, 3655634793, 2243956483, 48899184, 1510394527, 1220327074, 1986122738, 2771000282, 3801992586, 3807619027, 471210965, 240054629, 4138891889, 507966513, 2608584883, 3695585074, 1142049536, 1815447345, 878847029, 2425512616, 3404280273, 1809800602, 2708940436, 2746635100, 4246404208, 2039835981, 4031917112, 1996943450, 2580411493, 1129753117, 1562335482, 3454161890, 1304546076, 266633008, 2243463006, 1495416944, 3194149979, 1187229392, 2598096522, 2717656416, 1723138812, 321773293, 3528634550, 4012356064, 361342150, 1407382791, 281788878, 387885890, 2614365524, 3674715918, 3735628736, 4055198582, 3441555171, 2873512886, 881773623, 2426850436, 308355156, 4092323473, 976626532, 3349954092, 3198525613, 1279820517, 1618078850, 1918325121, 535344811, 988051597, 837895483, 3080823321, 2284227193, 3889421868, 4104768675, 3163480219, 3024832314, 2949487671, 3104325999, 4157724952, 4168869313, 721690106, 3562272836, 4007453971, 550776419, 1766890521, 3691651042, 2002769424, 3017703356, 622145868, 984506967, 872390633, 1401216125, 2631526378, 3112269305, 432369818, 193905809, 1155233014, 752554312, 145186046, 92244317, 3561426112, 1231358008, 454785216, 3928879637, 3214356742, 1926040456, 2162944696, 54812965, 2689940083, 3697347877, 2642017440, 1597744969, 861917368, 3358318171, 1108217254, 1094946939, 4142346894, 3219881738, 3673252603, 3653156321, 1364144882, 942313725, 1035715400, 2330944680, 1224099910, 3349983481, 356524863, 3275906855, 3285206514, 4248893603, 4088970118, 89006304, 23030721, 3809886990, 2867877807, 2930760156, 2433798057, 3852621687, 3592557226, 3512908344, 1565719632, 2354066426, 478797990, 1152699515, 318340209, 760174225, 1631571749, 2271463377, 650468891, 507504586, 2693229321, 3120669668, 2544094891, 3144973242, 3636388382, 1159049189, 1889357596, 1384924984, 43707224, 3718061345, 2543662513, 3729944648, 2644670969, 1377639119, 168824066, 2584279623, 4277720720, 1318206723, 1379145863, 3963963461, 4034653496, 3968013334, 2828714546, 1851135170, 1939714189, 3010931551, 226867970, 3933697914, 3421927438, 966963996, 1035716399, 790589571, 1188590505, 555295916, 3048626203, 3577474856, 155510811, 3536545976, 239763597, 2799111567, 3792587555, 4190649328, 3101199245, ], &[3290181794, 4048330047], &[ 3781336300, 393098052, 601926039, 4290235837, 2822961350, 3264010853, 1395348986, 1532724636, 1479458209, 2803797702, 2248954690, 1109326360, 868524296, 1622203818, 2233229102, 3747990662, 555588899, 2749663474, 3197509055, 630575671, 4105739578, 350883605, 3884847782, 2399406878, 1709869907, 4200326701, 4079556706, 1296998956, 1096350538, 524761973, 1629603733, 506636222, 2285887205, 2231667772, 4010753639, 917205307, 45978573, 2604387874, 3703883391, 956577030, 301635887, 1366863825, 653575304, 4002452771, 1532839774, 365525468, 1207266883, 46605181, 3549725346, 1181348714, 1401721152, 3079539285, 904310818, 1291426703, 3423900075, 3724908664, 918900181, 492461520, 2051740414, 861850244, 1441070167, 2409123056, 1923594929, 2592176152, 762526381, 2608436860, 179967203, 947743965, 3152260497, 3795355036, 3128372461, 334341652, 2852670346, 525231164, 2707537479, 423546146, 422356576, 2514936736, 1508996402, 2866854016, 2529118278, 1616687498, 3248910372, 3424501529, 3509076680, 4206763914, 2036548848, 4062752651, 4244007332, 2701189385, 1278945872, 1938315563, 341487762, 2245251522, 2614982710, 3077916256, 291100198, 3611957075, 1995518592, 154652263, 1532772306, 248498549, 3231944766, 628801303, 3344272527, 1065639153, 1987158587, 1479356917, 2988956252, 4046958565, 2209065419, 477730056, 2336652721, 1037902218, 2563735377, 4101524640, 3496286466, 893815781, 370165241, 111642164, 1658058879, 322898205, 2985501252, 4080369932, 313430011, 2711111000, 1181601656, 555256727, 554722327, 2969317428, 2537636036, 969866577, 3100268542, 861181567, 2766358890, 3556106295, 2319452091, 2276583134, 3694687721, 2683079950, 3602799233, 3315957548, 1156121233, 2466768002, 351756246, 1311063094, 607227992, 2577239074, 3348786927, 3556673019, 1603335686, 2933024191, 2025259240, 1495478557, 2032170560, 2121476735, 3193544299, 4119114109, 2928661241, 448576207, 1614958740, 345202029, 2600582520, 2742644459, 92765692, 1372450470, 3781561695, 1568934205, 145316051, 4006568817, 3666572039, 3335574604, 4261359692, 281814983, 2392237710, 1491546468, 2408177492, 3815015525, 1277308779, 3604474102, 796103227, 3177970999, 2372049172, 1292258380, 2260556904, 4006251044, 3037386650, 3097581743, 272132478, 1428294116, 1610143768, 3421139539, 1124007750, 2568811011, 899340979, 2888377028, 148246615, 621225076, 1635442139, 179184538, 2565113048, 524982498, 1477029769, 2443496661, 4238972150, 2111945492, 1826948655, 1631527737, 3293499896, 1592525336, 1072822530, 398987024, 1403041752, 1154120498, 183009602, 1860553280, 3833836549, 639383491, 2747751428, 1967745750, 985697863, 4102756978, 3010429932, 2426159954, 1632866751, 2325250581, 1085491035, 2626066600, 1004650627, 734034293, 2634237232, 3290134248, 0, ], ); // - bits == 0 in limbs_div_to_out_balanced // - bits == 0 and two-limb division in limbs_div_to_out_balanced test( &[10; 3], &[ 2974709165, 1408789605, 3865174329, 1359597196, 2297806425, 1241510613, 3227134452, 325500099, 3798589956, 748039492, ], &[ 322054190, 2721366349, 534065582, 4284544993, 2403511175, 3934371253, 3610661048, 2543303641, 4119337658, 3350506258, ], &[0, 10, 10], ); // - bits == 0 and schoolbook division in limbs_div_to_out_balanced test( &[10; 5], &[ 2333679788, 2356666855, 2364697986, 2341519831, 2855670118, 1220356586, 3077887875, 2167847389, 1298352907, 2783063425, 343561812, 1466674656, 2828723164, 2244865405, 3261584816, 323262334, 2146252780, 2244363245, 1140774914, ], &[ 1638368212, 4269779221, 4096262691, 3276079354, 3835296926, 1228438544, 931207076, 3941619719, 577971296, 3365897754, 3952671229, 3635074066, 1819466191, 1077726049, 2724331936, ], &[985368501, 2737353193, 3370693165, 1798455938, 0], ); // - *scratch_2_head <= 4 in limbs_div_to_out_balanced // - !(r_len > n_len || limbs_cmp_same_length(ns, &rs[..n_len]) == Less) test( &[10; 3], &[ 0, 0, 4294443008, 7, 4286578688, u32::MAX, u32::MAX, 4294443071, u32::MAX, u32::MAX, 0xffffff, 0, 4294950912, ], &[ 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, ], &[4294950912, 0, 10], ); // - bits == 0 and divide-and-conquer division in limbs_div_to_out_balanced test( &[10; 265], &[ 506643067, 674201220, 4077605637, 870747493, 2507358273, 3724638469, 1035009974, 829046988, 3750301412, 3918208469, 3953784269, 1207127792, 4050829853, 461784483, 2383763199, 2285448897, 893186049, 2814159946, 583430210, 349181410, 3312529089, 3040593764, 3505574840, 2245473386, 499733927, 1870266859, 306858541, 2287239467, 3602186482, 2485354048, 3925520601, 1490580163, 3946071957, 831571085, 2671733075, 3492322751, 1693084970, 3703683238, 914345023, 1731822012, 971261566, 2899991322, 1415427842, 2792111536, 3754030226, 2536140100, 2809833781, 255220419, 1494036353, 1435449211, 3699505245, 3939949425, 3424663004, 1987816971, 872486514, 2304200621, 3672706956, 3098142146, 4028147917, 3126086923, 3431963845, 2505585471, 2599393784, 2703989391, 104322041, 31236914, 1102844188, 1685015561, 3414504334, 3166439653, 3856439354, 3774684706, 4074904284, 605442011, 812212716, 1996651776, 4084653341, 271581859, 2458893946, 1704814216, 3983060909, 1705321390, 2722920787, 1026280690, 3548307184, 2796854160, 2478471453, 2069980586, 2327202328, 3179332026, 2188958336, 2717879675, 130062885, 140536268, 2499125438, 3163111280, 4259661702, 2176278885, 422519228, 2482586299, 2904549185, 656169575, 2052350629, 1346745024, 2132509288, 3672720658, 1036389958, 1864007789, 4247227128, 3920036168, 1436562554, 4261984498, 3509215437, 583752676, 3145348403, 2267709494, 2846186667, 95392897, 3743233716, 2210401890, 333864866, 4114644153, 3030283850, 2885600773, 209380485, 753945396, 719327396, 1293498320, 881901364, 2799735404, 3880748109, 2227099476, 2045911493, 279042015, 1825819541, 1783146691, 2256898093, 2186071881, 3753747971, 3588523011, 33603847, 1513157507, 3499821617, 3738644542, 1415336880, 2770362204, 2060947257, 2730479597, 2685626774, 999367629, 3913677028, 1269070210, 71600754, 1301019431, 2216016590, 146670051, 2663607608, 3377525204, 3629426592, 3008812841, 3146776799, 2307984538, 3891637717, 2113643890, 191705646, 2335382191, 1140110911, 4020097332, 1669672424, 2764048323, 131913018, 3294340837, 1179938248, 3518525865, 2275430195, 3163615882, 1433056069, 3632771998, 945256067, 3112805135, 3793337, 2498643598, 196475979, 1234934305, 2303169144, 3075871960, 1459180144, 181561979, 3503884769, 2684065515, 830368038, 3013649837, 2204747214, 1403496840, 3859560760, 2859158714, 3625515328, 1724787311, 751869756, 1068392634, 3152945440, 166456628, 3912875927, 1276199042, 3180668929, 2654240450, 3838496263, 1978050764, 1330937637, 3052787309, 2179574058, 3771594804, 78717414, 2499543381, 2290126169, 3421184223, 3433039199, 3357845254, 2982215557, 486514084, 3948984473, 748257374, 980199615, 2114791508, 2263110875, 1438244139, 364374413, 1396459296, 3946812646, 3259529007, 1803026660, 4176094107, 3107042296, 3690348839, 3454595397, 2121594656, 576668497, 807899954, 1335323177, 4200325364, 2730879357, 3284030486, 3324267006, 27217584, 3455039500, 2034759734, 748477743, 1248615399, 1109976687, 476936469, 3606689372, 3993977007, 2258238141, 1642523191, 2086149347, 3137863504, 3174920716, 199510880, 1099331674, 704556250, 3389523009, 6232858, 4190352603, 2138785122, 3218278977, 1935766981, 1255344917, 1933434103, 4229596014, 3581553119, 2147449432, 208926434, 2037430803, 4143975728, 2356343321, 937192435, 1637432038, 661638621, 1801480924, 3779152128, 4243491821, 1667774376, 1715755489, 3661813139, 1605971891, 4030695606, 2961165054, 1368430397, 2222904896, 2817587025, 1714442303, 3822714979, 300305701, 1874484285, 2601340412, 2275789197, 2695461089, 2246464394, 1119579754, 1646098622, 3280004748, 33497272, 1940830933, 3780770129, 1587254032, 832573251, 1504418072, 4247592896, 317874907, 949850421, 2252881736, 3574316069, 3062236166, 1396410954, 3249498785, 3495392204, 540855070, 1908700137, 1469179505, 4199276220, 953657385, 3056452157, 2141569526, 2342475731, 3746376146, 3271677606, 2770490239, 2212992129, 1758619376, 1446549455, 409094501, 767129031, 3284625381, 1887741449, 1134874072, 2988924415, 1641550007, 856704035, 80648349, 1467185629, 2753807208, 1609415681, 4087676277, 3276525355, 1530490532, 3475014952, 1971819359, 2190766950, 2667577576, 2404497182, 4128259693, 2449514447, 4199089872, 2205116036, 4089987616, 457231895, 2931469481, 3147651033, 2352907189, 876540006, 3743945364, 1472931415, 1553806347, 917186799, 2698606847, 66937650, 3645382047, 853223241, 3225678178, 3306353588, 4116060170, 2590602281, 1017313973, 2613704632, 2155925964, 971128116, 2969595931, 2019050340, 3266635763, 2229237075, 2897700432, 692684809, 2884804723, 548672200, 4148599125, 2903660719, 3024254547, 3711620919, 3505267307, 3040630725, 2741747953, 1929597653, 2289604848, 1876399821, 416443208, 113684194, 2458701351, 1129214912, 2220498900, 2434385125, 383696859, 1361474230, 1163397052, 2669432319, 3058892712, 180222756, 651218593, 799737686, 149785061, 2171639569, 3195389488, 270082840, 119827887, 1410384095, 4066783084, 3263839471, 464165531, 3866096625, 2064936052, 221981930, 3625198339, 3424885311, 1071723748, 409527338, 1676479257, 3093122613, 3729266155, 1862387444, 1361519384, 1243604327, 1643472480, 611403222, 996523967, 4174256483, 2326506033, 2418590323, 3423410866, 1529787343, 4205549227, 3997545970, 2223326432, 380968195, 3506194936, 3910452712, 4038499509, 1845505874, 1017156422, 1929655910, 2711754908, 635288831, 2247734769, 3304323666, 2179819642, 206674737, 590233515, 1336492628, 3718075, 3613296921, 3550161900, 1864016712, 114106506, 2398669907, 2720528985, 3857377519, 3905792607, 3346298226, 462294071, 3119274864, 3972744498, 2110531614, 2149059199, 3948853307, 864424113, 2523103018, 405972168, 1017288780, 2875520328, 2155632746, 3241100405, 86049349, 2941679162, 3047748962, 2284186344, 3132866461, 2331447040, 1003213663, 1873981685, 3371337621, 3796896013, 4144448610, 2569252563, 2859304641, 1027973602, 3158196152, 4058699545, 2002924383, 3295505824, 695758308, 544681384, 3452307839, 1190734708, 4232023153, 451772934, 673919865, 2022672425, 3493426012, 1142609332, 477542383, 1304798841, 461115870, 3268103575, 2243523508, 606810814, 4235312469, 1885993181, 114475077, 757688489, 1965769398, 260629125, 2265559181, 2568323569, 4202738507, 422918034, 1258453131, 3552221985, 1666914845, 4063631552, 1893061685, 1362616670, 3828572660, 3003680479, 119501228, 2101943449, 1119123129, 2512417484, 4143796978, 4123615401, 867855104, 9080683, 2989272444, 4071914200, 3126419388, 897981380, 1843424411, 2958654429, 19279568, 3561481778, 3620717321, 1713789028, 3466124758, 2114531476, 3750356418, 99077566, 1592097168, 3827583318, 620525513, 290829475, 2167034573, 859199755, 859025849, 1856340069, 1742571592, 619057918, 448873046, 492980624, 4024378211, 2920022072, 1315190691, 220327298, 822905603, 862879897, 2816210126, 1919765070, 2058864462, 697509061, 1633189430, 2245037639, 1891169791, 1490604281, 2749203494, 2727100064, 3952743771, 745359287, 294665575, 481463143, 2908504060, 3264906873, 4291223436, 1078483712, 1974128727, 3336164436, 56705038, 3439879863, 2641239652, 915511148, ], &[ 275357812, 1380366134, 832237659, 2112384134, 3392548533, 2322411681, 3893212013, 4294409814, 4093767003, 825461980, 2478547269, 3404630461, 1971516824, 3442909527, 310968935, 3588187524, 1263584270, 1954425632, 710153676, 1490566985, 3851982772, 3813403663, 3945099227, 487964380, 413515585, 3154361919, 1595882626, 2396609791, 324874877, 1386033964, 3103282602, 2599529608, 2119912272, 1365578038, 3224231142, 4103857906, 475734936, 3828952167, 3071966456, 1450111251, 1166414077, 2218130537, 3324650407, 1559641024, 2423373264, 2283136700, 1299328382, 3345578599, 840299756, 3797238397, 2067196109, 3055917746, 3636953439, 9994084, 848907394, 3724334355, 3765535226, 4202522723, 3549598176, 2976719094, 1062012457, 3192129616, 2622008775, 4140808457, 3311195039, 2219962246, 583122033, 3484577945, 3996746462, 3163823232, 2815287028, 4187316839, 3462896421, 2231360878, 1678307748, 460684903, 3249941390, 2444083444, 1885084635, 1384447473, 4228441234, 2992602088, 4233710708, 3252082214, 3754932745, 974410439, 749693996, 4239737998, 881588329, 1689075190, 292144262, 1373806909, 960467260, 3106551077, 1249264314, 1210555633, 3882913567, 59286933, 1593160363, 1969806577, 33237994, 1192096261, 1570929611, 1291838216, 1453595934, 1481420023, 1722346701, 3005255028, 2671588519, 1129223015, 1988074467, 2499928090, 3504414178, 2670506578, 798157759, 3859749353, 3404813676, 3070374972, 1362004270, 388389672, 3227842930, 3141750652, 246994433, 3435384009, 2937163806, 1091298751, 3219724097, 1663604618, 1547894794, 2034927931, 2077403472, 1183979515, 1312517327, 1652629779, 2840629951, 1320559340, 3379399676, 1763411889, 2852175138, 1013263636, 910550154, 529178328, 1437740880, 1545534222, 2859835603, 2271712768, 1100624932, 108752761, 3521837118, 2043489286, 2482010929, 2526022944, 784503235, 3989653576, 514018710, 3703716272, 4124099812, 1390681784, 2537781805, 201204889, 971348667, 2307205686, 1760983313, 2268919139, 3109728863, 1931931512, 1811265792, 2492179233, 2839289978, 305552922, 2705812278, 487378575, 1148523689, 4211680716, 3055415169, 512649009, 1499343281, 2379775206, 3398729819, 2885867944, 1989458261, 3168583752, 3895436961, 435919341, 3229009848, 333401020, 2066985073, 1599311722, 2470446433, 2036229414, 3754646122, 1602078777, 349281148, 1872253564, 1044135153, 3952751023, 1908969406, 2526035592, 108266294, 1002947027, 3490519747, 1017767773, 1363582374, 4236936817, 1095422379, 1476035104, 3938596998, 1896398408, 4013241860, 284937761, 5850220, 2334057891, 2272377339, 3385837178, 2094910603, 172965460, 2993236410, 1631768055, 1408498310, 4196305218, 2858075969, 3162013919, 3250561599, 2819691478, 976316354, 2309193549, 3902122050, 2088052090, 89473947, 3770933220, 1285217956, 495480326, 2012241013, 1505071862, 2618825681, 148024106, 2211817594, 3486453451, 3547415938, 4170790841, 710399394, 2988742259, 3003999364, 282857121, 3004330911, 2445074578, 1614383715, 2436968214, 11188480, 2102332723, 1466315446, 3717470884, 2603285911, 908917900, 3806165173, 1397056453, 1461836583, 327667425, 1587556539, 1289291700, 446244259, 3478801927, 758862925, 336152650, 518856100, 804638637, 2976399236, 3191730168, 3165653830, 4116291332, 1180509997, 787973682, 1833860962, 1047583821, 156500875, 1287142618, 2903226831, 2477133296, 625749873, 3687467688, 1470807488, 821205035, 4228089759, 498323515, 59751723, 4138495950, 1453952672, 2570830070, 521547133, 3428749320, 2363485698, 1810803490, 525920316, 1605961985, 2230129511, 1733393350, 1424281608, 2365058430, 3533943852, 258572135, 209602549, 687169735, 746097119, 3883623461, 860878590, 899440424, 1064227214, 2191778986, 3556832513, 2171344159, 2484630726, 290049039, 2356156351, 740380975, 1960730095, 142059661, 4018594902, 3106881150, 930323391, 1255739479, 3337449057, 3148783500, 2253473087, 1071245161, 3447698853, 1197848740, 4060561204, 499397149, 2774518906, 1389562763, 2693574400, ], &[ 2892496898, 1447320150, 3590707186, 4252286087, 4099207609, 4105150739, 3969659377, 3877581106, 3844075082, 1119395228, 4111657348, 1989245533, 2625018871, 1435016728, 775322113, 2486746233, 411477946, 783741811, 294555322, 874068633, 3432359852, 2911163611, 1375769638, 3434130437, 985693369, 3510076962, 2092775723, 1201035228, 812940046, 388585821, 3460410142, 4102284201, 2588728415, 1834489811, 1860072658, 3206722627, 4070805677, 912012520, 1107950571, 2855449499, 2356110400, 1048165361, 786166069, 3139410711, 2376418896, 213462974, 2934906474, 4184813074, 2148116146, 2886707962, 1072776382, 2999802157, 3058489357, 2949636457, 1567339918, 2296903598, 1471627440, 3093553236, 2902773332, 220749635, 1005913375, 859636387, 1837155708, 2140012254, 1304301626, 4253207180, 2566725460, 1469242176, 3759058257, 3409005372, 1238566539, 1398646155, 974517148, 3314067407, 339946221, 924727838, 1957551537, 680280333, 1281468850, 2209761488, 3116305703, 1340386652, 1621222022, 2320551186, 862888096, 2491969066, 2767235914, 3271787837, 2762818305, 3533899432, 2143575776, 3910952894, 14685217, 3463875857, 2036855868, 4258306113, 1030748318, 524321052, 1852279535, 59479177, 3613680178, 3646237449, 1565986281, 2257075320, 2631569154, 2895149301, 1938268122, 65582006, 4031119479, 430394105, 3217907221, 543498480, 1033294445, 2556400020, 767171781, 50312859, 2780724798, 3203289606, 3870927927, 67083759, 2409696923, 3952601322, 3653157894, 923160622, 3398950378, 1555694690, 2244182109, 3619744924, 2568706263, 826771561, 640735316, 3641939139, 642767502, 950596306, 2695574621, 1644028223, 554000152, 486521532, 3326739594, 117306555, 1841260119, 3938389504, 300582682, 3953482514, 430139137, 455233320, 1037301049, 3615948425, 136331238, 2572752842, 3241874704, 2846529663, 1268666222, 425076421, 1387063258, 2890954385, 4096839497, 575163363, 2677416020, 1370013560, 2172542077, 268835184, 2720518386, 2313195126, 2520731985, 1428843145, 1120133039, 3270957840, 3315172136, 2870322488, 2870507039, 724984412, 3139237569, 952022623, 3933753186, 3828757670, 3909874303, 178407797, 3904699386, 1722471536, 1933503701, 2084550100, 714890658, 2573717352, 962347002, 2899589891, 680105427, 2737432908, 602384873, 3647759319, 885456319, 2557006269, 2747397933, 2991432384, 2531228735, 235505427, 3454054340, 324776205, 2920011061, 2039088389, 1071395333, 3752028462, 3264518328, 2221042825, 2520779553, 3023235163, 3336750037, 2776943124, 698637417, 213422247, 2253953770, 2289793400, 1099689581, 2183186023, 3600213851, 2987733376, 3240713853, 2532959736, 3990244023, 935412481, 4003796414, 4044202737, 2701294309, 2774001322, 1246813030, 3523205316, 2877272264, 2808629070, 3952617986, 575846345, 3887709830, 2303176257, 2448994062, 1814306890, 1125465602, 1437344932, 57018575, 2882004962, 257559391, 129924651, 8107674, 2641593151, 3225211500, 3751185810, 4152912940, 2352009510, 1449645454, 1216509365, 2388967059, 2711793416, 1284040889, 1645864028, 2051429244, 1605254461, 1917359262, 1805912147, 536698251, 1021142310, 3935443381, 2696660773, 1238552336, 3193475557, 1525093066, 1459803910, 0, ], ); // - bits != 0 and divide-and-conquer division in limbs_div_to_out_unbalanced test( &[10; 744], &[ 3587573856, 4227426142, 3896224682, 1468139892, 1853281713, 3230829722, 3544339255, 913969399, 3983606726, 181178735, 2741195255, 1539029618, 3261057660, 669185888, 26774344, 3042294054, 4000320681, 3616777430, 1701761628, 984410729, 4231348353, 2662674575, 1467572439, 2032481283, 1873156172, 115509983, 2937869423, 973418665, 1489589927, 1095121637, 506586746, 2535986948, 2719080072, 296096440, 1642945999, 2339337213, 988268530, 2303133076, 2256242938, 646154972, 1819375956, 2274317751, 3820060724, 742765560, 3675289356, 3771892301, 3075647720, 1818112062, 3031351147, 3419055185, 1772759499, 3049965965, 716650100, 3384724295, 3504962640, 3501988647, 4073738879, 817690323, 306125872, 4262005940, 2328708878, 2185547215, 3604829167, 1214715318, 405219872, 2470967999, 4165888706, 58640780, 3166122711, 1754011174, 823366021, 588855436, 539915357, 897646815, 4093176866, 1081711730, 282768489, 761405028, 3134899797, 3405740924, 322586217, 2056545290, 2437754480, 104247006, 1236818589, 2491440617, 181378199, 1163012610, 1325379332, 4200723192, 1263362307, 3234219355, 3292135414, 1507504036, 4161995531, 309710870, 3183147539, 982486451, 3492150688, 694819593, 2066057564, 1649903936, 1060155149, 1595975750, 2913835322, 1938985687, 3772153889, 3152752661, 1191763263, 3764287870, 3782997871, 81159186, 4157520234, 1723748366, 1221210497, 3568223039, 927507384, 4004363262, 1795793243, 3503626292, 2692130423, 1081516180, 3595063804, 849797265, 1035581542, 770759929, 2889095772, 2572036064, 3097409730, 2958492178, 2450749829, 2069709085, 2687054597, 3392070073, 3827943191, 2368917411, 3160758175, 1531480588, 2746326450, 3122359045, 1995296172, 310451197, 1100329853, 2141732304, 3562890277, 4172526924, 4143185198, 2397101926, 620168044, 828452963, 3271569899, 2726758945, 1647557222, 2748652901, 1029871186, 1773072595, 1311795717, 2792240418, 3100733307, 298902661, 2608361440, 642743765, 3026335712, 1586592828, 1251923561, 2152803283, 3359308047, 3979690761, 2548031009, 2148504694, 2514911217, 401310800, 1418125404, 2325652800, 716233458, 422262103, 376190943, 1713380879, 2534508846, 2080413009, 2690193951, 2909422387, 2435837201, 176977642, 224472737, 1590904934, 1664979624, 1748982641, 1284257790, 2779881254, 385265989, 1148527382, 800142050, 3595556318, 3950265146, 3931111523, 3399894595, 4200004994, 3727110364, 1510525540, 429323681, 2586345405, 3441619670, 94654169, 2266545045, 1451808026, 286040435, 364003484, 2106693078, 1916214330, 2622096560, 3504008387, 1867458297, 4209615436, 2899684845, 3149003214, 2731979274, 2481557740, 234269740, 1239420776, 2726912636, 1844267393, 1488044058, 1587005400, 145015793, 1637696129, 1990069464, 3053970062, 676336554, 625771493, 1492378707, 1231018082, 3059699722, 4113615249, 2967103567, 3335726303, 2137774253, 273460502, 1561489611, 1227429414, 778315897, 3061631993, 2437789514, 2566029814, 3017507824, 3219754602, 35255136, 1934306764, 1655248959, 3655963814, 2821596564, 1431977748, 3114012833, 3915822059, 343010167, 3704265251, 2691314567, 2602475242, 2459094882, 58857240, 2230690665, 1357656795, 3025543277, 3488674640, 408985076, 80729036, 246851391, 1419653386, 530010128, 3529087076, 3980421141, 4129023783, 1630771696, 2057278583, 2501545742, 790764428, 3984347668, 2562445985, 2262348292, 2515967925, 1103371818, 3735595401, 3210477145, 3387257181, 538884374, 2695206119, 4211749041, 1006274735, 2406061865, 2654644297, 1268724640, 2399689302, 157759259, 564853502, 865205768, 2174783618, 3167863384, 1770172407, 1906775255, 3171669377, 2455086709, 1355327864, 3351895167, 4184858376, 2699533565, 2939169294, 1702277740, 3447680482, 3322351998, 4248517760, 4100425921, 1169799041, 524849931, 1743345401, 3987645088, 3022177240, 3263737545, 3656340460, 239445170, 4089162190, 1208712978, 1453215235, 3390225374, 3337889603, 717395279, 1066458381, 2162685522, 4009460245, 2575879990, 2578471337, 4218103221, 3046325563, 1352991515, 1561949281, 3488911174, 295633326, 1993756395, 3677304657, 796898320, 45622345, 2999482773, 2078651788, 1552765091, 428170722, 1748054862, 4158222865, 1050292437, 249107, 2651086861, 1540178674, 1275557298, 651050585, 1895599156, 4150309716, 2064336046, 1021257319, 2422595446, 3116755258, 2756656575, 2328011578, 3632905157, 2576200202, 830418644, 2430246370, 3913080080, 2371749061, 2683067461, 3611558701, 1603392737, 796477803, 604567756, 1376069347, 1491246154, 2728262664, 4138498935, 3008562381, 1061547384, 285679033, 2358943172, 1884649492, 1783482693, 1010268161, 176114433, 794165875, 2362278477, 3903204233, 326754905, 1988607850, 3187254334, 1749797209, 2986661384, 1759716588, 3137467938, 4067743599, 1134210801, 3799848836, 1955405545, 3881788427, 3097574490, 3844756657, 3183850151, 2496328910, 1468671385, 2888878911, 2306353811, 1498824361, 4152891378, 1588217107, 79108222, 2883552792, 2390312777, 1587172303, 2070384343, 2265280181, 4013380367, 2742676878, 2654283484, 1471778694, 970959698, 1006151052, 1276307400, 2874101774, 3169092608, 244587925, 2402787407, 1635687252, 835856534, 321407542, 2307278464, 2272745321, 2574317642, 729437319, 1682288870, 1482920833, 776000268, 3908963888, 214874919, 4233311318, 1441385448, 2358127573, 2753681514, 467574656, 4139948165, 1538275035, 3244920878, 2576965792, 584068468, 3054546876, 2629688518, 4253271747, 3723872815, 1652066683, 990821089, 2335421805, 1989570928, 240486517, 2872315587, 3869991906, 3870517664, 1540804424, 397183643, 3750033565, 1433260634, 1506168711, 3616651625, 512028445, 3746712828, 3278592880, 2611514549, 1214563129, 1259227909, 1067976218, 3425169051, 741795595, 893688343, 2674408703, 3694908868, 2478153735, 2220661625, 1022546736, 3719214155, 3161293211, 4131981986, 1473264088, 1651777063, 1438502715, 290022167, 59234682, 3458968160, 2552001459, 3451530289, 3800073253, 717882913, 845719525, 1038699111, 3058303772, 1117505279, 3682430977, 2869037104, 2562493618, 960519305, 4147639705, 1817463351, 3166022129, 3200769866, 789666262, 2654485924, 3686362402, 2179867687, 3980226915, 3671542918, 1896992204, 1514962591, 815867715, 3924270086, 4262628477, 3977258034, 1340257907, 6618754, 2720861064, 778635062, 682181834, 2891943360, 3002120306, 3399643048, 3139375492, 865948953, 3273305779, 388881948, 3544744413, 3963050187, 3002594763, 3339669779, 2722426929, 1246819181, 2786076007, 708438365, 1013683719, 3027751127, 1766272571, 2839608714, 2866928644, 2107420563, 4035553421, 2376700546, 621608197, 1993043072, 2666011084, 2265522039, 3230507984, 2869423257, 1776134078, 2413254013, 3859414865, 193597892, 4255395370, 168637254, 3364100552, 3883433219, 3117797624, 2738841992, 3052596910, 3280507008, 2860095630, 4031447725, 3454885698, 1783630119, 3036202894, 3585701130, 4184585287, 1329572188, 2352399996, 3076023682, 2989927975, 320530428, 2081170907, 933271377, 2974966675, 3452895778, 2331110373, 995864819, 1177147317, 4084213472, 1179430541, 361665403, 2401303908, 3027157843, 2778759588, 1031442202, 542151276, 4259656091, 745358488, 2580062497, 2004998882, 2066508478, 341659477, 958017378, 2415007725, 211645068, 3630737942, 2670158596, 3544834081, 2043760261, 2149621570, 1287267516, 3353570061, 3758258174, 4171807709, 1363035595, 2692148345, 3728232161, 2672522097, 3234166892, 1337714504, 2475062988, 902334395, 3470019951, 1789926953, 39991566, 1071624731, 2480238280, 2010573056, 2975909089, 2685102208, 1752958961, 2957725128, 2441562510, 1615057382, 2739912075, 962437876, 1445592393, 750430353, 2848157371, 3515397641, 2140566969, 3080139371, 3564834440, 561913271, 1812943111, 1349101061, 1627550717, 3467766096, 194766042, 3125120919, 3021598191, 2389614341, 2536207717, 3687483968, 3746428277, 1304917109, 4262793424, 1046105397, 103309888, 2808595193, 1896772845, 2625389818, 1425524079, 4245371665, 1376995745, 1906643058, 4123808395, 4010921636, 3668036324, 538106732, 429893286, 1473862381, 692485290, 728791765, 4006267410, 2159349173, 1146991809, 1105326804, 855626330, 2350214961, 3945267379, 4182769713, 1218539569, 2795526933, 508156606, 1596052577, 4135932990, 4009064452, 3154371819, 1789912473, 3737225773, 2339289640, 382599364, 2822801808, 1231473766, 3195594892, 3686689017, 2674031129, 2724276086, 4112764261, 79570030, 1908454621, 270118882, 3204318684, 2240304382, 1923066108, 3669840087, 3114917464, 57715381, 3015749933, 3183317351, 2563719945, 2409212385, 2256893938, 718636813, 3965735223, 1345089653, 1264444, 2296052850, 1092210950, 3468764525, 3967443918, 788417425, 1924956491, 3656370968, 4266402294, 389687964, 3067575949, 3786278950, 4368934, 3414260125, 1500941491, 4197777812, 1901284905, 2548021755, 1986057606, 2732888210, 3872664452, 2787539702, 3264559111, 753549553, 1048190618, 2900005727, 1868077400, 1284542693, 3154799998, 395567255, 2005460208, 4005052806, 1893310835, 3217932531, 2607307407, 3917316670, 2028218244, 3745680211, 2397481422, 736482987, 1916844834, 3868328610, 938512555, 1559481864, 729544587, 3690980706, 1759014647, 2060717833, 2250640148, 3619925046, 2153794810, 4127168634, 3259374700, 2051907961, 3964686808, 3841055905, 4242264783, 2314742304, 2209077724, 2577227865, 1487635776, 1585379583, 3475070421, 1683734827, 3363053669, 3722095029, 3857335408, 2852846850, 456879372, 2473892714, 2928343667, 541075767, 3595876467, 1688710352, 2071331730, 1142047400, 1817453168, 96871997, 3927306877, 3090061646, 3474317652, 437148773, 439538568, 324686794, 772632617, 1424328970, 580538580, 3999279969, 2022469388, 2802303848, 1147488095, 2053949131, 3046702544, 3822972379, 2920233521, 4031279543, 2356245098, 2951036256, 3287235943, 2760424423, 140913700, 689952328, 3916658401, 1694797888, 82150998, 4075118605, 1967095926, 1704543314, 3154572744, 408071699, 844684417, 1174429103, 3583461805, 1015646627, 861970508, 1906905868, 2272773809, 879277860, 2980820537, 1917774935, 247497916, 2403283458, 553129122, 3303057196, 4005726052, 1808761740, 1909802116, 964057278, 1586240623, 3097009405, 2048123311, 2481968244, 3155267854, 555253647, 4027932249, 229358586, 1015669317, 4112551330, 351151415, 1331401879, 1749898409, 3352469407, 710145444, 2903798473, 2876271745, 692844392, 2354652850, 100021926, 4212629124, 2971597719, 2697935131, 445511347, 1636699871, 2524940444, 1303870696, 3634945394, 2398930906, 1337769794, 3955409228, 2657553814, 1455809030, 701994564, 374320080, 519334058, 71402463, 2995013099, 1573823285, 2419768029, 4108602983, 4266125692, 3514998795, 2367509976, 2654621106, 562141353, 3101668250, 2753822172, 406447740, 4132920329, 3645443797, 4221410098, 1000631411, 2319369935, 3987192941, 609889174, 569928846, 3471449767, 761399938, 2925981744, 3610481831, 364846710, 2579622933, 1755359875, 3327963251, 2230753636, 3897751713, 3685870953, 720576993, 4008645094, 2170973511, 3057371253, 2362087099, 2415801497, 3804893423, 874616900, 4188156090, 2114593709, 3626784402, 2090293821, 1178445498, 3501583487, 3787814639, 1160994150, 3773261324, 3438864014, 3474697300, 3232616282, 3082635737, 3290126053, 1041836645, 1497490946, 2116412677, 78748560, 2610841375, 406515051, 2540982558, 1278151559, 910145724, 2942229044, 1412896287, 2420692111, 2829066497, 2762072644, 883699073, 4146766932, 968581437, 2262117978, 4102625453, 753476188, ], &[ 4049869757, 1602523624, 1387514923, 225246600, 155172862, 3856617978, 2201641309, 1540516258, 34942771, 4041710783, 3460925118, 1016127034, 1143953610, 3427876200, 4178328442, 3374908315, 2087712114, 4171526185, 3514588648, 2986361397, 3768375872, 152142192, 1983892945, 2539876375, 1278133015, 3290367811, 3728704045, 2495609578, 3383634048, 550401536, 2958764367, 417726361, 3629290307, 3955082917, 3367571078, 1156977964, 2700212626, 3890522506, 1407330442, 2072012244, 292784856, 2848511017, 2011019434, 3729188240, 1314875514, 1752114201, 3480385261, 1532349465, 1252987479, 1748370879, 457308873, 2290488535, 4117600387, 1025979949, 4285742993, 3815216993, 1825262081, 665711516, 1319233702, 3390016806, 2279278230, 1335733129, 2732993747, 770076251, 2848793746, 893093476, 350727685, 49933264, 3771423699, 1804029403, 3544637522, 3176796760, 475781914, 777775753, 2152296620, 1317524444, 3941840558, 1662743930, 1905993615, 2485835810, 3925643251, 3071436009, 851721712, 1325046168, 3214018378, 1465803515, 2459667310, 2361559987, 2668552637, 2425633974, 3200812339, 2594448814, 4170435967, 1112582678, 3198704424, 4028094030, 2482710119, 2990475705, 708195759, 612294539, 2794828841, 2498141427, 3805184114, 3010938369, 1479667740, 660767380, 1641177565, 1782849661, 1915222559, 1626388136, 1816788637, 1338361170, 783877621, 4003339370, 1930607900, 1259399167, 3351643097, 1641708262, 967800396, 1800752717, 2198926109, 1163817943, 2710351254, 451351637, 1285647338, 865168955, 645286276, 2685132510, 1773153387, 4273868103, 2604563645, 4105767904, 2556376985, 158907213, 3579937882, 3059825408, 1920542835, 528717490, 1430681949, 616489338, 597761261, 3760865497, 963173252, 2915089223, 1441674715, 1717557648, 1819215517, 3449795284, 844168976, 1574237607, 758725457, 762624299, 533122182, 1201164787, 1968174784, 896982568, 3419630169, 2247559545, 3983311870, 3975342941, 1112833399, 2721518545, 2493587613, 3444837338, 3313000598, 751186769, 2970698395, 915811688, 1206259449, 1340427760, 3844346545, 3762393860, 543253569, 1197933603, 3734607133, 4037352821, 2263945478, 2831362781, 3363558852, 476952769, 1916745391, 208671986, 2395250976, 1549715018, 2746690542, 1219103496, 256305249, 358172450, 2072583005, 3916780941, 4158630723, 1190830416, 3779410961, 103078237, 413254256, 341045330, 1139999874, 92806975, 1388100212, 1158509802, 2339968162, 1347201015, 784082665, 1171121798, 1281820962, 528442543, ], &[ 1082720091, 3476817859, 1893722246, 3080882169, 3417947745, 3340276454, 3885894760, 1942705317, 675159075, 2356580166, 2812410352, 1542004962, 2479082003, 1559105673, 1430407422, 3754123073, 3434749261, 3438277207, 3184426987, 2481219277, 3201501212, 2336166635, 3118471262, 4257588863, 1129103696, 2036867994, 1362270000, 2205796804, 1619465560, 1334326802, 1654568402, 748744581, 529239522, 352036781, 4164399267, 339969597, 3948817065, 4118696507, 3167307180, 3299871862, 992173657, 3312501436, 4234856346, 1472448261, 454903616, 2135585012, 1182478660, 3108573415, 289552136, 3656397512, 471369369, 621698889, 3506241896, 3050415504, 635379448, 309369370, 3135812778, 709795745, 3156857644, 1981234127, 777872572, 2069114566, 4227271663, 1642023978, 4255257763, 4251585692, 4102236891, 61692500, 3829081047, 2974587843, 3417120535, 3759026709, 543679528, 610505883, 2224107411, 952038760, 1845841012, 2091165188, 2319077898, 813461061, 4130723132, 819025288, 308176462, 1882359754, 1123046783, 351488317, 1740084483, 4031432934, 866128405, 3761028110, 153341699, 1557409832, 3958654248, 9848396, 1343150951, 1655256005, 3758327652, 714608206, 2476402679, 2222813494, 249341289, 20217846, 3718322691, 1309897917, 1956873127, 3780340503, 3187273275, 2997743448, 2763864945, 1015229074, 1035154014, 4111197216, 4129892876, 2463400739, 2137142214, 2932334703, 1212478961, 1404771156, 2403376672, 1666383249, 2101966267, 2787146653, 3409236902, 382073169, 8092902, 3172754632, 2362871022, 174894239, 2851299514, 4035565821, 1576086690, 1863466767, 2147230465, 4012739188, 2573883505, 3496112107, 1561836070, 2714989398, 518249309, 585535272, 1083806803, 2432909736, 417453124, 3662025813, 3862714644, 2982211872, 3413054134, 278502998, 1933231828, 1756355548, 4175286263, 1635691203, 1696182335, 3722603401, 3499515010, 2780239369, 2967447083, 3938392642, 1039437781, 156713901, 202025882, 3388635620, 4085640754, 2766466060, 3257237392, 1610632422, 2659484643, 759134140, 2468303426, 3485429206, 391268866, 3602129409, 466642453, 2027942747, 753837398, 2159887674, 1699077410, 3385420601, 2097219048, 1939536260, 4216211838, 1310649129, 3770773042, 2367698780, 2182982254, 105876687, 389319130, 956327995, 1042519322, 3560831866, 2584066309, 2359741951, 3525689940, 2936794464, 4165100291, 464352315, 1510693553, 1019366466, 1339175695, 2900331968, 1808660155, 3444379929, 844617472, 594684582, 2551754663, 4184241459, 2541557677, 1600387746, 3461253021, 20795987, 2007859697, 2294435372, 2967012275, 427466509, 3926685990, 2687323981, 58620064, 463567707, 2009818918, 2587127815, 335237443, 548349111, 2327100548, 3527232221, 963188157, 2846759149, 2508857384, 2785887779, 1911224250, 499633849, 339500132, 1698755389, 3785332522, 1951026064, 1157235411, 2385637652, 70752751, 3581109807, 1000717338, 367332589, 852120579, 1720305388, 2396130011, 2325323294, 3159509753, 2304229465, 3412995226, 1302807073, 1047169090, 103900265, 388968533, 1642951622, 2119771731, 3904510666, 3214555812, 2090353527, 3439045026, 414952145, 1990923465, 2145341503, 3376393463, 1768247381, 2500689220, 3437741376, 2952550055, 202503815, 3117369798, 3572610192, 3057469623, 3868128130, 2897590216, 1333004082, 3846323733, 1145656956, 2957222763, 1612732059, 636089096, 280438137, 4133371531, 2415302446, 3343573484, 450368029, 4013078578, 1776076354, 4055087576, 2875505329, 956580657, 1284100217, 484412750, 3403238717, 114812192, 3141957869, 1923373041, 4267447588, 1848508027, 3578399081, 3602314328, 2015600160, 3169258369, 4225283, 3215758323, 535488666, 2299743753, 2598839590, 2251925973, 3424293163, 1583565986, 822791938, 499972304, 3526253756, 3187560030, 839910754, 2473717205, 2920751658, 281393009, 1675618188, 279356115, 3737356546, 2987221453, 2784535811, 1716035779, 2728300709, 295755590, 79028394, 2321443009, 3334571157, 2092798399, 776878210, 3880589251, 3000121191, 895584305, 1972715675, 3933866443, 2459940020, 2535432427, 3442732987, 1351280251, 2705869134, 4056756488, 642205063, 1335417345, 2925570768, 3272930570, 1215315775, 2270360900, 3920083766, 1800417946, 2267749997, 4044783727, 1769884599, 2859569555, 3317860539, 616401729, 639899592, 656298035, 1728919003, 4078302028, 666745393, 1560472966, 3582178280, 30041205, 1445208285, 1831729364, 3833375730, 2031873203, 110189422, 4001884424, 1172085689, 434283494, 365118314, 2974799471, 2419990253, 2254345440, 3303650744, 379954120, 2872690320, 2813488227, 2931609524, 750879352, 3553708007, 3932935565, 2268402810, 4181556412, 2645378729, 3996572258, 1392500829, 2476571256, 2592516278, 2941009392, 3567442876, 3295525458, 2364649002, 1107394009, 3085546406, 3546490308, 3980163356, 3563024751, 1632689827, 2857550583, 2854525629, 2769744068, 3179245702, 114619536, 1503846887, 3983245950, 4053448614, 3804164557, 483691484, 4154677001, 3343013834, 3198409629, 2196007920, 2814767401, 2583091893, 622358751, 1909097055, 4275650466, 2408839673, 975842192, 1807945419, 530334006, 2193239360, 3573576815, 3375828028, 343495318, 4289026005, 1962467408, 347337978, 3396953980, 884291722, 1137165202, 220827107, 779266710, 2344445455, 34856979, 1143045482, 56767308, 1578363872, 3731201669, 3706120565, 3337776817, 4289277255, 1854266966, 983344215, 1966863762, 367660085, 2557629697, 926188478, 3333617884, 3810871127, 349652103, 217155142, 1688170224, 3319067823, 2885726973, 134399180, 5674764, 3973054562, 2273408331, 3833933899, 3417440443, 1041778853, 1946826410, 3801686902, 1531220405, 1393391045, 331387982, 3898611911, 268525782, 3769634949, 3016559037, 2445833730, 678007929, 1519682189, 746295463, 499000954, 1304839962, 2069998292, 572428575, 980128037, 1245074429, 3558109310, 2997264588, 658214766, 883463509, 3369353012, 1297551772, 2110922247, 2798156905, 955238199, 1636058159, 4078945672, 1404295386, 3413374279, 1206293582, 2450940328, 3853860296, 568231531, 3871379428, 801397097, 3548192318, 2198482100, 1425818836, 2226232328, 2217750444, 1674221667, 575304554, 339577605, 1944985402, 3285623423, 137164688, 2194970053, 3895173964, 2206988857, 560190101, 4150633681, 2529897699, 2877680493, 2138142714, 3624049789, 4259353316, 1917725116, 253374220, 1961669318, 524948489, 3660413785, 2459743863, 609305506, 4234617120, 1880171213, 2231312825, 3930360917, 3757082546, 1598330816, 2275523468, 2537954969, 2648376719, 3949938840, 1179324615, 2638061103, 1420005740, 162992051, 2259945784, 1691781876, 2035325287, 3681767229, 1864052113, 4098159425, 2904470037, 2739041791, 3653434846, 25187402, 743386308, 1617431581, 1955566361, 1609808798, 612646080, 749092400, 3476155485, 372463231, 2400385265, 2448935262, 2868736303, 44050485, 1811513622, 244185373, 1058010832, 3236838304, 1696379775, 1374320342, 893033010, 2184044974, 2103383697, 3678814304, 3707318863, 2232216478, 2121008938, 3391204665, 114653376, 3539615664, 693415359, 3948513646, 2472340375, 2689595350, 2911666831, 2862380219, 2277904386, 3052644532, 3620922554, 1583320802, 989453708, 2848948202, 2802447076, 314144584, 1963582024, 3054383355, 3230565030, 3198370807, 3232305102, 3533915944, 1159220898, 3409956546, 739193900, 279482209, 2395025280, 3213913189, 3465386197, 4007322480, 1185701264, 882190169, 301180834, 3985404529, 775008128, 1929920973, 498148924, 1653387516, 32770831, 84662291, 1070233280, 420774040, 1845466025, 2660849065, 892513130, 1220251223, 3462048171, 3639870150, 279428221, 2277386828, 1042423213, 49732010, 2156548934, 2306505697, 1610786467, 2412885409, 514239305, 3502348066, 3662528922, 3523842425, 499321566, 1558826766, 1025787712, 750835728, 2151253987, 2771548076, 1874413816, 1770687295, 242014543, 2896631433, 4270012022, 4154175689, 358416847, 62726299, 2459979834, 3959988277, 3138565580, 2632517010, 3757121807, 982781859, 3866772115, 1940202687, 143199844, 3711383957, 3192090943, 192177309, 3414164907, 2772999412, 3345422423, 3632869399, 298443741, 1301417999, 3779042088, 3129617922, 2534671226, 3888890090, 3440629680, 860078030, 3705887480, 1118604355, 1986962149, 2134492511, 4252575925, 1247103708, 2063043343, 4018417608, 1435800387, 3604051252, 2382645558, 65332182, 359897542, 1245864255, 1609404488, 3987595397, 3239425334, 187261326, 4123855750, 1200175240, 2149408423, 3981447331, 4266532762, 2991803305, 904593361, 2972818330, 1285040552, 432629695, 3318003843, 1422945986, 903546290, 4170273900, 2167679655, 3927128491, 369901225, 3823643528, 3070820575, 153246247, 3566780970, 3775810437, 100362394, 3451770819, 2165886441, 3421082619, 2757100947, 3862770948, 991992674, 2507717612, 1238760013, 1566046550, 3362507120, 3516476868, 591759613, 3252699908, 3659831623, 102934758, 1522937224, 2690593629, 4166523866, 2815574307, 1262613047, 3171249524, 859033927, 2026114441, 321675781, 4067069202, 1828982470, 1, ], ); // - bits != 0 and divide-and-conquer division in limbs_div_to_out_balanced test( &[10; 276], &[ 108635137, 53042175, 2495789053, 166626339, 2790541996, 3399648116, 704235903, 1987319994, 3846313422, 3704598543, 3690196699, 3215164091, 1591950078, 4084137444, 3535469973, 369348781, 3853840741, 38365848, 2204958899, 420812105, 2779552010, 1548769452, 685824244, 2413919731, 3001005256, 1844653400, 2702666282, 953246091, 1180609303, 1728187391, 3376808367, 922212062, 2555240, 3091442748, 2779003823, 1730350709, 3884150184, 1912296588, 1381602302, 1132745285, 2605509609, 907722107, 764554269, 3991449945, 3268497606, 652777597, 3569835073, 3292533280, 1757212806, 4083008115, 1567249607, 2029822077, 1300690097, 542854515, 2421776641, 1792015269, 3385254138, 3324421134, 3135185624, 2936968278, 3252736384, 272507607, 2728141594, 4200848223, 3001744645, 1397661269, 3892465560, 2335547432, 3245101563, 1241760367, 93951076, 2656438422, 1056867098, 3937300802, 2762984593, 3306503534, 1748156730, 1129525575, 654008385, 439540212, 2194484000, 3773978123, 3104733633, 3072629324, 1956867429, 3192898033, 520613936, 2701719680, 3263467682, 4152521012, 821868901, 857419957, 794567744, 1966964158, 1188525445, 25386574, 4072516363, 2420189258, 506921989, 4093279187, 45547769, 513061404, 243072258, 3189135266, 3207683448, 3842162034, 1133520520, 175840391, 3746219860, 744587725, 660570869, 4002101132, 522243467, 2303217069, 1674769460, 3791198176, 3339780616, 3458756479, 1979186301, 896682364, 2308144330, 1378320625, 4274094804, 586903390, 2523245831, 395299569, 1187786606, 2283803123, 4267141178, 2219595837, 1128697087, 1857876110, 1318499953, 3165428382, 1575816218, 956482234, 18588216, 3132721083, 47556415, 81611970, 3910123222, 423589575, 1101413252, 3606836170, 1942712759, 3189437565, 1988019498, 2092781681, 4236534903, 790511562, 4060480297, 3105894710, 2764365449, 1397438933, 1196278536, 2058315951, 2838695613, 4281268824, 3826944690, 1181288743, 369591812, 1309874942, 3790984071, 288341904, 1563879876, 165797805, 858735816, 2072353128, 685737219, 361047486, 4066070935, 747362930, 2075612928, 247842391, 3759957561, 4008727703, 3301939318, 2461349415, 1220733209, 3976094938, 4150525547, 950524413, 615359333, 3819351887, 604594973, 967650734, 3412914931, 940128704, 3084501448, 3552914752, 1468579018, 3375888808, 272090024, 2102430932, 2231900023, 407815192, 3133923502, 808329364, 1437980982, 2714133004, 2541977126, 1644097574, 1605051578, 900680606, 1233529861, 1285360886, 262211605, 3340000454, 3059934898, 261179603, 1359321373, 2785008571, 1696998009, 4208277335, 1632076295, 1780238612, 1096677031, 2326184831, 1755582758, 1271079634, 3473819079, 3524297696, 2971249360, 304707349, 1752064216, 3406003757, 2298730120, 3470434630, 1822263204, 3897394658, 1744777112, 1474862410, 2619263924, 1883564355, 245003326, 2772487730, 1684833147, 3384787730, 3432821829, 1659957487, 4143280212, 2945269934, 2715460396, 3109905612, 2183811774, 423754031, 2103134812, 1722483377, 1623977444, 4207250751, 474534834, 2675551745, 1065671136, 3814366580, 3372473612, 922981250, 1210468465, 535527770, 590607480, 2860431542, 509048194, 3860804971, 3161644296, 1119093457, 2017558623, 3882518387, 2116262688, 1592400489, 1330477596, 1812541649, 3066693344, 1681733293, 2837523711, 3962139488, 2400483346, 684544040, 618138932, 23933358, 337472067, 4255565569, 3863904974, 1571272948, 3063467317, 3199661373, 2892202115, 3466650924, 2813788238, 199916841, 6302159, 3020774987, 2959649954, 3051172815, 385827752, 3500074887, 1998588949, 740187474, 1537085728, 4040744226, 169795027, 1388002404, 448995184, 209159058, 2041030169, 3989416757, 2372340142, 610343086, 3895834685, 3130822270, 2937770030, 354183502, 142181574, 2610105359, 2678801631, 3035570967, 3617741371, 3969553519, 1367705229, 2107582010, 3358994616, 3893272782, 661536642, 41261552, 4179523599, 3717595615, 2660616505, 364657719, 1591424432, 2930227288, 1470954796, 2176631849, 1725166260, 2686775012, 818766763, 1889939384, 3037885089, 3635001611, 4198592608, 1743285046, 2898224735, 1659026011, 318231763, 4236634945, 2813628609, 1962109336, 1610396960, 3016705702, 3623307415, 3832212453, 4249700382, 941544661, 720165462, 4093658500, 3453816013, 2079181823, 523275463, 3269528702, 3019887295, 3811204518, 159775628, 1722773106, 1469942260, 3026312336, 1636680124, 676646879, 1243866643, 3046790125, 3838163884, 456070987, 3400235386, 3209376427, 2052709404, 2975905060, 3314477136, 63144045, 1485059871, 162201390, 186441332, 612262739, 828760782, 3475105064, 2824483050, 780082694, 2214596670, 79854651, 3785529118, 3362875978, 2019456835, 3664773598, 2128455541, 1830176771, 3131136264, 385070469, 2166122015, 4242832149, 1871374367, 2866877895, 565736311, 3669481600, 3732705160, 920034463, 1676220645, 3589606699, 2654716480, 1934326920, 2849139664, 3961632132, 3838830143, 3776089649, 3421594363, 3482840282, 2537104160, 3010338838, 2165340101, 1892478832, 2700868158, 1092691010, 2008876123, 752365533, 628818795, 3526690309, 1565204, 3539771692, 3129225931, 3999602879, 843176653, 1303696065, 2008779360, 3311453295, 1156870995, 3738053906, 359090986, 3637794830, 205702249, 3331669407, 3910416238, 3925253071, 3900326738, 1156846221, 567150051, 379723012, 3421075741, 2064258650, 2895443535, 753490073, 948868209, 3567651732, 3728641104, 1287032959, 710808071, 1107267370, 515160531, 1433094102, 3871178973, 3077300132, 2340844017, 1955407235, 1314652042, 3168268098, 2448320270, 2400447335, 3294295438, 1015553266, 2155337410, 1202973291, 26721975, 748351815, 3704104726, 493250895, 4196736012, 260103997, 1216172054, 1878845953, 2517690048, 2952150363, 2853405105, 3643402580, 173602363, 34441180, 4232560859, 3432794922, 1140120890, 3906522401, 1592024957, 4187088827, 3565666595, 2036898614, 1513649673, 89930944, 2373451644, 570806865, 2966068116, 216216149, 901919588, 2525422962, 926283525, 2020466305, 4176067636, 2062906224, 2749700324, 3770003319, 4243016358, 1536893669, 1734422817, 1903034843, 2140137740, 2133960349, 2127799686, 3826582112, 219489448, 508455455, 400134475, 2681095601, 1225367969, 1189240142, 3928151903, 2223436694, 188587138, 2759880580, 2159086089, 139714886, 4230028328, 2668106965, 197527044, 1076021583, 365687428, 2429361726, 987702546, 479721329, 370553881, 330849794, 1208154538, 511352639, 1347185232, 3309753618, 2165973922, 2714839722, 1566744459, 1258272726, 4003842107, 1592609821, 1602879458, 598396180, 1691880384, 1805556651, 951428589, 1382102411, 3352671230, 3650598499, 3958924995, 3934211043, 1708901267, 2214291603, 3062058779, 3334192431, 794991697, 1238615391, 1385289547, 3821895409, 36111771, 1154601572, 3442859590, 72901265, 204664637, 3567057924, 1929964733, 3447462776, 1857620277, 1670547089, 3282928074, 1385001633, 905180163, 3027069579, 1563462544, 3261712196, 2691524721, 2887321824, 532509125, 1250479582, 1736964157, 1752056130, 2411795965, 2530177666, 1944298739, 4021827042, 235488471, 49513017, 364455717, 3051752647, 2541367373, 4025312306, 758560501, 2532590036, 2497355449, 2645291172, 4094509748, 2811604062, 3938869461, 2314766426, 3949981315, 3113301191, 3961932201, 3642942123, 4042045976, 1080625720, 749107450, 2408837571, 773510366, 408327874, 4043794032, 2751095877, 4253356392, 1852579882, 2930909909, 22950574, 2455166107, 1518997069, 3502877484, 3466955328, 2495681100, 1416465050, 2781446012, 3974552369, 3963181882, 4031801829, 971448688, 3324460697, 3468632379, 596003274, 2001813586, 494254023, 3111644337, 1214103910, 2547242619, 345292455, 1171889494, 2523157824, 2004995962, 2793293234, 3357565902, 3618900967, 1122158351, 1840000495, 3714974862, 2372340013, 3036104311, 1987619821, 1915784172, 187130136, 1032034929, 764058777, 1324555408, 4258631431, 2565322815, 3622146170, 446425747, 663948352, 3473130059, 3081160831, 881843540, 2045224772, 2479557013, 3352503836, 1209737991, 3178334862, 1649664345, 3898477658, 2455734938, 2058141628, 1165813520, 3499004048, 1363642302, 1673253013, 950040890, 859882680, 3358702534, 2831246639, 3154009927, 3886020609, 4260600294, 4292328051, 2154852829, 3071909756, 3083791599, 2780514384, 2089946486, 440735136, 2840096690, 3847114327, 4107780595, 1507811167, 319613030, 771404322, 3267312644, 343171187, 416166006, 400367691, 354408782, 3664160643, 306037219, 2628548851, 2490873938, 147038682, 2557865570, 1918482947, 1550632444, 1104237513, 2381980505, 1257779567, 3978083093, 4188937519, 1450461940, 3573655366, 4007222924, 899058972, 2762018299, 2973671862, 613016156, 3453147112, 3958949304, 248065424, 750535902, 2025904997, 2542540928, 3631746189, 1474696231, 3349867745, 1645065489, 1753887057, 62923614, 3355303085, 1757052497, 4111601366, 4122660071, 3488098722, 968401720, 2418687776, 3889098632, 1507574874, 1788573805, 930165776, 2563485754, 2283929886, 361900473, 3829676677, 2920155840, 2690982721, 2647324946, 933444487, 1982178922, 2334110536, 2878917031, 3486781662, 1761730411, 3024808673, 3873242498, 3895635845, 1874483821, 1898379794, 4172331028, 3759742822, 339224592, 336709787, 1768365716, 3768045522, 1226451429, 2705764626, 2090014839, 2715498023, 15765857, 262371622, 1364974277, 3278122087, 1085595683, 2097096706, 4084807931, 342124999, 3362503915, 102138122, 222464351, 2367255609, 329998946, 1654125618, 1397194509, 2342407041, 4218981334, 3043210002, 1820580167, 3532477643, 3698803212, 2459696610, 3760108330, 590088894, 2109406971, 2851337682, 1821297729, 3479206596, 3141773016, 1887780855, 3345901315, 3465462131, 1285191121, 3092915327, 141461573, 2073757501, 878536688, 1772007905, 1193942688, 1553571015, 2179016361, 3232910452, 897070601, 2148852628, 4215017747, 571464735, 3364559156, 4279542294, 3759036030, 2656683267, 1707236123, 1356967673, 2580245428, 1451203266, 2299603042, 3068898426, 1148383426, 950626083, 3457385021, 2591070383, 3181532137, 3347056243, 1495266049, 2210488892, 720796437, 1413487507, 3065309505, 3696802085, 2734150063, 3600467301, 2529953774, 2679381445, 4233323864, 1085096641, 1587182738, 4041255127, 891185711, 2340666116, 671752008, 4136178412, 379067213, 2916836063, 3982716045, 745125821, 3190060915, 2728700228, 4248229826, 822059760, 2434419301, 2390321192, 1529594228, 2455438975, 1623635782, 3927813233, 3131415702, 2632189134, 2093836398, 4098626915, 1127324299, 2709110703, 1267984800, 2156759432, 947735481, 2766133233, 4227965085, 531828395, 3790033202, 3790793152, 2975006665, 1116356882, 2644453515, 2771505868, 3490730292, 2557842446, 3338652340, 837555851, 582834001, 3882158027, 384350213, 708918872, 3173032166, 14955604, 3415856040, 3404370362, 3759099429, 2374207480, 1534379322, 2698542736, 2164045979, 660913601, 3556971203, 1616608268, 1829936346, 3109981160, 697542468, 740461237, 1422792083, 3962800663, 3066960795, 1173757342, 769744240, 3750815337, 3814517080, 385190612, 2953064964, 1871983583, 1649509432, 1554161863, 3185361908, 2106975424, 1538113731, 2523454661, 143645610, 718612279, 1723847182, 747395397, 2882688996, 2021890066, 1030716023, 1995073902, 4105305241, 2127982715, 1690451116, 1956139100, 530256795, 3558366590, 2724310482, 2341665586, 250870045, 3391930252, 3942088647, 3976895259, 112642770, 3730114995, 1371701615, 3644536213, 2026852217, 1200740294, 2038780887, 648265626, 1535440607, 782951933, 824579667, 3601202459, 2314910152, 4263436566, 442006573, 1248351448, 3167704183, 3934018759, 3957471958, 2504687739, 3253599456, 389758313, 3342046926, 278999028, 2652455147, 3325515388, 2176380480, 1129683162, 3997989394, 3620086114, 2746229755, 290677810, 1466119856, 1528967320, 1110833004, 135210629, 4036023385, 82033834, 420677558, 1964407130, 2702828444, 3920237543, 930065859, 2455503717, 544391994, 38795400, 3389365984, 2189324221, 3653325550, 2984928969, 985994309, 4212011784, 433292705, 3993514299, 272538953, 84416207, 3750907699, 4166502555, 3618032189, 1236823026, 4151994611, 2505418422, 1513527578, 1564158364, 2400104436, 2118135017, 497726437, 3029863178, 3946017842, 4023841770, 299480378, 3182449534, 3212382324, 3197008823, ], &[ 4002709364, 963399356, 2782341067, 3945310775, 1640289005, 3723750838, 1254211967, 2304588540, 3174496786, 2728509707, 255821323, 110353438, 3720272848, 2229377273, 2152240593, 1976405605, 3700189945, 1261817945, 962162212, 2968380111, 734133596, 725489232, 1719612084, 3884866627, 28057341, 3961915971, 1325614652, 65176638, 3323056153, 1428210708, 2748040079, 943478886, 2463128528, 1179615866, 819519877, 745909987, 2928403710, 428934326, 1802933992, 265877181, 784539883, 3368469872, 2186856195, 267183160, 711926800, 1784916336, 3062621903, 41142608, 1185902375, 3289485275, 2769494454, 845407692, 420641321, 1822514821, 1468465938, 3143456289, 1922484069, 4035995228, 3823561491, 3573485374, 1462883391, 949414736, 1205197438, 1545720767, 4004962418, 901935939, 1176411707, 3934655491, 1247692219, 3372976809, 648846849, 561624310, 4213429112, 388574078, 3876368507, 2459110297, 3629548833, 2842464979, 755880226, 109802803, 410812363, 1884761319, 4167310741, 1416731661, 4162069084, 3695932529, 2935063704, 1097793995, 2124836831, 724360417, 3061931520, 3339903277, 3019747519, 303387593, 3800465715, 4021351514, 2617312748, 2101558562, 212720952, 2948123341, 2761073207, 3424660022, 1745409052, 743791614, 3820519067, 3495466566, 855725038, 3341655828, 3835113615, 1270021592, 1093683126, 366232505, 2382273294, 687690291, 2407217871, 3126999218, 2489109394, 2399521074, 1912270761, 1547900176, 112668330, 2418271838, 164643, 788458686, 1283051461, 502966828, 2822195605, 3290495578, 1940639423, 1104706107, 334853171, 3663855161, 3267632296, 1384333597, 2439397119, 360160344, 913951997, 3699617663, 2223491591, 4152571511, 4127552387, 2384896323, 2719106630, 1968080578, 3047590289, 1349230865, 2632158056, 417315676, 4047908012, 2058515124, 3962573168, 435657190, 3869063277, 1129208107, 371028160, 2341806620, 1837536116, 4062395278, 760408526, 489855682, 1341968057, 3582061385, 567307943, 1459157484, 2793270460, 3765006265, 316630926, 3312280213, 3038146737, 1954778145, 1255537680, 1872487321, 3078336, 1786349493, 2936757034, 3157582052, 656659566, 638195606, 2761830593, 796052712, 1835931537, 3594050559, 2825844970, 1783476497, 1587070264, 582928447, 349530572, 3521756034, 3849814263, 3898598710, 1487612894, 3546940589, 3702560901, 2571834495, 2432615017, 151334837, 1929191978, 456717814, 1822026775, 2905791667, 2187809681, 3085861483, 2527039138, 1461502989, 1674065300, 1427963173, 3931324821, 3503894366, 770079370, 2646944748, 192300986, 1063095706, 3173456208, 3863439598, 3538143515, 1736463922, 2524154399, 2134152316, 2565447595, 2642170528, 3536538194, 1250655424, 359773845, 3664161865, 879705815, 1474928595, 2536605270, 1911087921, 2962799796, 4010905032, 2793477763, 1959425433, 3713879004, 136714178, 1724676493, 867784003, 3212103591, 453276555, 1061978135, 1967464120, 3591583971, 1101672396, 1057025284, 2241955674, 442433290, 2456783152, 793285251, 1178449650, 684670303, 1866273007, 1391022401, 3083722623, 2493222535, 1189326604, 1199252550, 3969981178, 4060147906, 525899569, 24010191, 765321740, 2761772368, 3377909206, 1331140315, 3875549784, 4212148483, 2588352295, 1569174674, 1936659977, 626141956, 2533524762, 239859149, 3534146265, 2997682745, 71238037, 2732432587, 3908540462, 477053537, 1471594724, 2867685233, 3586191718, 1273507649, 1161961515, 2329077270, 2132699100, 2632998553, 1299594849, 1554941646, 3548827963, 3889378581, 467940077, 4211088672, 3371367836, 1620737016, 2233519964, 2624185462, 843840626, 2427990702, 3297260629, 786361707, 1646501219, 2205482711, 1032553750, 3122751558, 4227854173, 3810881375, 423778347, 2970196049, 2431725362, 2079714185, 1671048359, 372886771, 3881108825, 1517433910, 980297672, 460700981, 1452459198, 1527418894, 1426505982, 3181114286, 1351932282, 2092103967, 2878978239, 2422613736, 1750361767, 3327673906, 3090894970, 3102624891, 2501611324, 2723100867, 3663964999, 852336624, 4080907747, 3496497293, 865887813, 929644307, 2488175940, 838516249, 244558558, 3755455496, 3162262069, 696753816, 1156821200, 2717965945, 2023685211, 742596168, 4023287277, 869919872, 809477569, 2011079194, 3221489136, 4266255834, 2419594884, 3939612855, 1706366855, 2428360994, 716879901, 3297635122, 1769572686, 2873365745, 3831233968, 1661441467, 3919563787, 1226247329, 155760684, 2127556453, 3650610530, 3912925100, 3397709082, 2605399534, 844200203, 1218697875, 3747822377, 1899143697, 1732546786, 2288016347, 359886996, 3307751257, 2007742513, 2748636623, 3533690902, 871243358, 3464803523, 4180212238, 3640833128, 1577830398, 1892628035, 2306472556, 2996392130, 3006231684, 2296266179, 3151580099, 3594248718, 298545948, 3539272117, 2749678939, 1874404025, 2584227634, 2959840975, 4165861727, 959382651, 1009550827, 649210999, 3468285293, 3791505115, 3177835926, 1574975458, 3712971814, 2268845891, 3027469655, 2612516945, 2767217349, 3437723210, 361909048, 174803142, 1801608370, 2683396447, 4123855575, 3743115358, 855097355, 389967654, 3466849183, 62496602, 1570756383, 2619549118, 2702719459, 3205603560, 3517585951, 1001571916, 3914648094, 586411011, 2203219545, 1991805170, 291462253, 2626091906, 2500429699, 3658425250, 591275011, 3457521561, 1909516648, 1016647432, 1214423814, 545389916, 2274937717, 4186397493, 2838711218, 2407104593, 3341370919, 2071188669, 1056326847, 279675352, 3143136760, 663034604, 2337665064, 1068045341, 3288706086, 1599970362, 1807582654, 3478852750, 3645690411, 634626702, 3016872041, 4009908955, 1006051491, 2719021150, 1908698847, 1974558407, 1045151170, 81414730, 1422867232, 4197239354, 1591983466, 1874189107, 3882070116, 471160619, 3538033652, 1325575575, 3542883207, 2157625989, 3201577383, 609577155, 1394935989, 3283862577, 898081363, 1638703961, 2459812069, 2143849566, 1692845986, 191429412, 1947558163, 2654605920, 362944274, 652627228, 3005443786, 1907584792, 2260991562, 2033179708, 517601169, 1610423429, 3396730858, 3421003047, 2978082438, 1862441924, 3826508713, 1263943479, 2041961479, 3942582480, 2128168260, 47267024, 4126534310, 3346534361, 3387023656, 2882502992, 851762018, 2559987094, 633154678, 2834924154, 68763504, 2517021392, 1787244558, 476241955, 1869261127, 451025182, 1484615367, 1293374777, 849824408, 125615889, 34383294, 709860222, 3029061471, 1782241004, 2502486226, 3289755139, 1884331971, 3585604373, 708130179, 3812432338, 3121673423, 336729898, 3212815979, 1331640570, 368808354, 3927992910, 2583344309, 1604683896, 2377675664, 1432049895, 2336708810, 1233966810, 106712876, 1665259905, 4193964217, 192648794, 1498181023, 947378957, 2402512259, 1416057697, 1026447453, 3945411820, 3451452905, 3553837717, 3947305034, 902601876, 3942899828, 3516283811, 262422749, 2638031869, 712288220, 199462641, 3599010749, 3787584036, 1126365450, 4070880751, 3865411772, 1658495826, 3570711854, 1735726921, 119145303, 3163130848, 1291336833, 2146796315, 1896458910, 3507258381, 3730474410, 647902664, 119220376, 2833167618, 2741203329, 249470903, 71327613, 1931728642, 2604757487, 1117219288, 711428972, 3428460616, 322366467, 3243077053, 3378897681, 1403843932, 1991989918, 2413012613, 1365744141, 492078564, 2676610402, 3773231972, 1970922906, 2318388358, 1112949420, 3487096476, 2360170040, 3943418017, 3228760458, 3122193412, 3638387262, 1016961461, 2409174780, 1643889695, 3848556024, 3685824617, 3512748976, 3284143746, 748779869, 2874184074, 1232281025, 4144896530, 1069350420, 286933366, 416090620, 2657050801, 3108410259, 4063672733, 2336832052, 4393947, 1331069304, 1668926341, 3265202467, 169918063, 1585538827, 1657996381, 1427959009, 2747423595, 433894126, 2042216201, 426611464, 2098273364, 2681925510, 2347419442, 759472315, 358883472, 3566573061, 566399128, 1133339458, 3913483015, 1985356395, 2890868444, 306415199, 1693603799, 815436612, 4239331360, 2080083468, 2674607028, 308976991, 562939988, 142614472, 2751524972, 2580927221, 4040617817, 2258237186, 2077092459, 1424533819, 1818261836, 2255477956, 2463113859, 3917783, 3196888747, 1250369919, 2128811027, 4135988753, 2855121231, 2751603541, 1748944916, 606818116, 891282707, 1280813224, 3409874308, 890595934, 3601429200, 671048320, 3885753853, 2067382323, 3518602897, 4104376817, 3947164920, 2066705712, 3805972909, 2493699797, 2966924389, 701802948, 2781603469, 971061938, 1383226196, 3438743891, 755681190, 3291987780, 2657031748, 2157421567, 2518108674, 3181389973, 225606787, 3198444098, 651201578, 4077819767, 462870400, 1659941395, 3260365109, 591607061, 3304541751, 3964864687, 3949358441, 156533293, 798441780, 3281785939, 1484494452, 1302095638, 251493387, 4009163885, 2395098738, 2328212887, 496298918, 516574034, 2964917507, 76965044, 3856691333, 864137593, 2447187657, 4258071311, 3755646436, 4248910684, 2663150304, 1237165667, ], &[ 1984473199, 3256227249, 2455176569, 2099166325, 4149291216, 3802329550, 4268938044, 841307730, 1835702977, 1996082126, 3547567838, 773843704, 4016216621, 2681973928, 2642638628, 756126484, 3711891528, 3333768427, 3023107041, 329078158, 3831084881, 2250143469, 2740854484, 2065364093, 16475968, 1789063882, 90562755, 2395829638, 105502248, 2464984171, 352362049, 1671925562, 1672656429, 3912672783, 2976521985, 1857535053, 912101373, 3599178263, 1475622388, 1679421724, 912451536, 1544347804, 3409297610, 2780624831, 2956890227, 2759200533, 1377434234, 737077784, 3725690282, 3427153748, 1794622970, 939859254, 2855863085, 647722556, 354344551, 3826763791, 1345727351, 288135440, 1036229247, 695718102, 815041410, 2006432724, 28242562, 1749929211, 875993743, 3126551415, 837166301, 3481584796, 3204894742, 540424284, 2500473276, 2033531364, 3658774875, 1170881648, 1587377703, 3303215635, 2382459946, 4261489817, 3503640610, 2312174189, 2085919298, 876781300, 3523968595, 3794900435, 551562034, 277917899, 4049545585, 1148488459, 3049249256, 3028547737, 385184461, 2327045056, 326335295, 1526099772, 4222288321, 3335089988, 3223345238, 3867286782, 814275510, 4052015149, 1619520353, 1451459556, 1906956921, 3352694287, 1890686648, 4263536151, 3670741827, 3921992654, 2432133033, 3137493217, 587639161, 305609045, 3928594642, 1789779366, 151593889, 3742404497, 2236095179, 1327594808, 168249194, 3856434419, 1196489310, 3396059561, 647915695, 3822118736, 3541416683, 1851262272, 3995631059, 3428808225, 4186414337, 2490990084, 2116008544, 3650220767, 1396560346, 907120910, 1909963938, 4088722647, 3467954950, 4004624286, 1977459563, 3110163371, 4093373364, 619921165, 3816233891, 1937989728, 3624382539, 2436122875, 544743061, 1173132218, 2928770999, 1155101491, 439835796, 978535833, 2767377467, 2446840779, 3121046201, 1239790209, 1427805909, 3673596610, 3945221930, 1197651601, 1456742497, 177427399, 1394121276, 372545580, 1590879370, 1356252877, 2819023735, 2147545641, 3662283870, 4040887354, 3677669405, 1738433639, 291377486, 55300961, 4286101333, 3829985898, 2667081711, 1422260840, 1198139136, 4157283455, 3655872630, 1182240668, 2228451189, 1436090123, 289825845, 4160160212, 1255112200, 3852671276, 291873274, 3097152433, 1700751971, 1521673523, 769906108, 100191651, 909759186, 3738396514, 63815917, 3764078995, 4283954803, 3644348060, 1146825084, 3992578663, 1098803369, 4234257585, 2499204008, 2806310476, 1805565067, 2148657240, 3603959232, 1973450338, 304954722, 187699076, 2886666068, 1565668459, 3119264127, 526428678, 3519310907, 4144387005, 2133914899, 367483308, 438788794, 2018175717, 152755342, 2289694022, 1623257904, 3632662641, 1438654875, 1957740844, 3866415111, 4036225294, 1540930636, 777575895, 1164306998, 905593419, 176596270, 1964891555, 435285470, 427518217, 341067847, 1226878934, 3817779176, 655247797, 1445754505, 3726676144, 2254233196, 1355909097, 3364332039, 3448860423, 4203238266, 3244898179, 2238989099, 2550902008, 20701893, 2266649866, 2508429693, 2270048684, 1797834837, 2026596902, 379667603, 2096274613, 976774677, 2606058996, 225173995, 3819162877, 1852526611, 2880769412, 1907061042, 1871814156, 1625893023, 1164237684, 405483535, 4277482961, 2315260153, 1956694410, 2508860583, 2, ], ); // - bits == 0 and divide-and-conquer division in limbs_div_to_out_unbalanced test( &[10; 166], &[ 1459165216, 3821473485, 1527833631, 534557042, 2641251684, 3809609559, 3061112419, 3967227446, 874369607, 3357113542, 172837185, 3063799945, 809083967, 2114991304, 3652585499, 3870981027, 260839090, 86387882, 3506805298, 3586414637, 1219151546, 1074937346, 1869327638, 417941536, 3278188390, 2755475894, 732985043, 3207584010, 452875381, 1770638312, 2520936487, 429394218, 59073091, 2715600775, 2347478058, 2065207972, 333851993, 2020557144, 2988851968, 3434603645, 3867986743, 620458350, 4176081514, 687997565, 2000470173, 207628264, 2939063980, 2887037244, 88858000, 1979351616, 2144759905, 226043352, 2991906207, 2099593474, 388908813, 605491614, 917110966, 1440029715, 1265986065, 1353710372, 150747576, 4066821351, 2601543228, 3022790779, 2756513327, 2301300942, 4180697886, 536617044, 1792525146, 302356039, 2248737864, 1440314786, 2943873916, 194486140, 2460944396, 2163386634, 663134844, 1064843562, 683691518, 1346625839, 1429039926, 905082151, 1043984157, 3973238222, 3954748148, 600018136, 45112318, 3802284763, 599423421, 1288822021, 2339077887, 2053244537, 2215861254, 3570045286, 1668889163, 3129765729, 1881187635, 2099320920, 1455508634, 3101359109, 2133360041, 4219848842, 3274735980, 1661020165, 1959002083, 2476803683, 2995302951, 3007969525, 2952785468, 2735292483, 1339083985, 1425599321, 963296461, 3835062683, 3441026991, 1009908781, 785678562, 362135934, 221588933, 2902273739, 3436714793, 672263420, 391421925, 3562850020, 1167915739, 1235366482, 3241596463, 839741578, 1600792632, 1356868232, 1717207350, 1486509543, 609703091, 1813709463, 1754127387, 103270828, 2294491827, 1977478773, 3581233061, 2076865607, 1233918144, 468952816, 3796007953, 765537507, 1015431726, 1729447629, 4075863441, 1166265824, 1653283772, 2675507303, 1805466182, 2868049045, 393643708, 2395539658, 1405125898, 3106988834, 1449875350, 1921850832, 1103068145, 3501885274, 2708895753, 433758320, 3993837559, 3767611255, 312060882, 3998790645, 877231469, 2138719115, 4142414870, 1018473073, 533189076, 3104708022, 1178372066, 2975216060, 3907507630, 975237132, 386309107, 902266006, 2644385081, 1477475340, 1858200689, 3285099777, 1132271153, 2053580658, 1125376417, 874041446, 712345397, 1140230609, 538666680, 881721324, 1111893069, 2501306270, 2274122960, 1357144116, 2166627910, 577081103, 1122655088, 392081015, 596573533, 3113340265, 3964396084, 1011820872, 1620966576, 2716227347, 4149946487, 1583709456, 61899924, 4263575338, 2401528621, 3509028054, 3666511577, 397386472, 969124122, 4008000629, 2718198502, 1418318388, 2934063395, 2647641395, 1145485096, 2200369228, 1989216706, 2963238435, 1926386286, 2830877782, 545778532, 1945014519, 1638724297, 622208887, 1112164416, 2022531771, 2867462821, 599490439, 1876923470, 950997193, 1684774054, 3263116384, 859638073, 1516033581, 3344695361, 1785593437, 598067909, 2850637811, 2288401518, 1795058327, 4095583229, 1222559443, 737107737, 651134240, 7438464, 747824109, 3730428362, 2416724451, 2565046767, 2620912429, 2561442128, 2361206033, 3310915724, 858282568, 2272790867, 659862547, 461019210, 268119566, 1687038156, 1409316883, 2126896112, 1753824368, 2573165648, 3765733919, 1487774113, 2831055305, 21121671, 1366044190, 3078238855, 4195255404, 1496590230, 1626222644, 3171354920, 1518148632, 2538776379, 1154154541, 1870543847, 2084780047, 603891666, 524384754, 604772818, 2926191905, 3313865705, 2210821711, 3918703550, 1119015865, 1362962604, 1749827365, 2045857758, 2562923004, 1460944271, 3737144414, 3632123919, 2354988860, 2895025884, 3090512056, 3436396245, 3344468871, 136152018, 3202810570, 2877125824, 3677060161, 747702260, 2458095411, 1835835611, 1903565435, 1773042151, 1229867663, 1051182633, 1551699740, 46990108, ], &[ 2983822400, 1175377136, 4004483281, 2235564407, 1822513467, 381114796, 280652026, 2967591791, 3307355161, 2377064394, 385476518, 822689029, 4246167127, 11318802, 2302723623, 935991327, 3629372113, 2655890047, 2427850107, 3493543220, 1199218706, 18464511, 3419074626, 131354313, 1681481125, 1916223295, 3786572616, 4255559076, 2934355035, 1723151624, 3248974311, 3738736372, 1475008151, 786397519, 2078941349, 3511637043, 626529836, 3727302624, 3446417866, 1056699846, 1674449049, 3597285965, 2085431198, 1104070989, 2845556388, 3561365655, 3725037602, 1844214597, 938693814, 3351033209, 2761175913, 4231374306, 1596758609, 839842001, 1569016951, 2417309445, 1330306602, 1051752810, 136987586, 4191267361, 12875184, 3448410984, 1907451325, 2277059171, 4081014716, 1109678253, 3098651582, 2013701166, 3694814849, 2213240606, 915706703, 466995892, 2849324974, 4088671183, 3041537520, 256167934, 2378660697, 3026916, 3420187595, 3019264354, 2517539357, 3190771438, 3964084208, 464800745, 2158354996, 2997461723, 1586829196, 626753654, 1190341385, 32972831, 4211614888, 3666851480, 4151894977, 3598196315, 2868568182, 3468849454, 1834890649, 3931331938, 1665539267, 344411925, 2706253979, 4175115668, 3417292439, 2920916773, 1978420139, 2431824169, 986409380, 1888406655, 3938963826, 1560180445, 3202323406, 1414927418, 4029028281, 3561590815, 3654051825, 2798678208, 317536782, 2586849954, 3375941666, 2815670947, 2163397988, 2274010858, 3353427146, 3194776320, 1018812088, 248020252, 2984616735, 2264657095, 883506886, 1203774994, 3281598423, 4002133977, 2951591465, 1380559214, 313180293, 2977296703, 943333173, 196114172, 4050138623, 716791187, 3081577264, 2452658991, 1506085116, 96780562, 3815905806, 894431824, 2606307520, 4085987609, 286762580, 3059401150, ], &[ 2808057994, 3606496776, 1638284867, 2965092528, 3070561729, 3046780593, 2492165002, 2058133462, 1411482622, 1386159493, 1930973158, 2741344048, 991334618, 23694448, 3645114681, 2489826892, 2652335165, 300868672, 2296390812, 1038735413, 1402107292, 3134939101, 495678723, 1934871653, 2094500280, 2973473339, 930416921, 1063911356, 1613559983, 607236505, 3394770573, 1595743960, 2977461902, 3135858186, 3804985197, 2427992839, 40481157, 1194866742, 2665355479, 1208298331, 264923797, 1533531928, 589823565, 1623330987, 1821021081, 3936785116, 1670988047, 812003305, 186281380, 2006301434, 1859818525, 2519784381, 502212272, 4074421773, 1011623398, 2394120437, 1749077131, 358348440, 3091437650, 2632724490, 750658123, 940819777, 1564325991, 3192289990, 1922442690, 2098791607, 1410727269, 3997475748, 2046568633, 2328724701, 594683983, 2946935672, 250929021, 3546617499, 3147415082, 2862801627, 1752972798, 1777319581, 1049723832, 2195152639, 3483521471, 1734219330, 2576240512, 2409422582, 2679948137, 3770401512, 1061673858, 1725420873, 718139354, 233062852, 2768861085, 4124913273, 3554269730, 2872541430, 4278481571, 768499669, 4277599530, 3185103338, 1954279181, 3422846001, 98074718, 551096407, 3681600913, 2349433618, 3210489357, 2742261282, 4049115855, 914605405, 3971655743, 62350404, 3980249028, 823758998, 3662208770, 3596057304, 1896028596, 1563432047, 3924435289, 1454939129, 1062311879, 1403923520, 56670001, 3483882506, 1501725860, 976633875, 2995625644, 3931841873, 211374720, 1454175215, 3629938299, 2471336363, 4025409672, 91025627, 421183437, 2654995201, 1631399822, 552933189, 3700683612, 3350958380, 2564370593, 3463421537, 3068013499, 2815245398, 1236034626, 2411769049, 3471729333, 1807804732, 3870076218, 3233217373, 2623595623, 3235588553, 1211586912, 106513608, 1606540242, 735139009, 3646406666, 1157995439, 990423165, 1032637281, 3009147147, 3249314474, 1109145355, 2938339245, 1916419568, 824070112, 65967478, 0, ], ); // - bits == 0 and Barrett division in limbs_div_to_out_unbalanced test( &[10; 1770], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 461373439, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967024, u32::MAX, 4294945791, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffff, 0, 54525952, 0, 402653184, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 44, 0, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, 4287102975, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4026531839, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 6, 0, 16, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 18431, 0, 0, 0, 0, 0, 0x2000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4232052736, u32::MAX, 1610612735, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 2816, 0, 0, 0, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7340031, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff9, u32::MAX, 4294967103, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 1310720, 0, 0, 0, 0, 4294443008, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2818572287, 0, 0, 0, 0, 0, 0, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963968, u32::MAX, 4294918143, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffff, 0, 603979776, 0, 0, 0, 0, 0xf0000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 239, 0, 0, 0, 0, 0, 0x100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4293394432, u32::MAX, 4286578687, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3fffffff, 0, 0, 64, 0, 0, 0, 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 81919, 0, 0, 0, 0, 0, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3556769792, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 127, 0, 0x7000, 0, 0, 0, 0, 4294950912, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 25165823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967216, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffff, 0, 12582912, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fffffff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294930432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffffff, 0, 0x40000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2047, 0, 196608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0x4000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294639616, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffffff, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff4, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfff00000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x800000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], ); // - bits != 0 and Barrett division in limbs_div_to_out_balanced test( &[10; 1401], &[123; 2800], &[456; 1410], &[ 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 3842865475, 1356305461, 226050910, 3616814565, 2034458192, 2486560013, 1130254551, 904203641, 1582356372, 1158510915, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - bits == 0 and Barrett division in limbs_div_to_out_balanced let mut ds = vec![0; 1409]; ds.push(u32::MAX); test( &[10; 1401], &[123; 2800], &ds, &[ 170970, 170847, 170724, 170601, 170478, 170355, 170232, 170109, 169986, 169863, 169740, 169617, 169494, 169371, 169248, 169125, 169002, 168879, 168756, 168633, 168510, 168387, 168264, 168141, 168018, 167895, 167772, 167649, 167526, 167403, 167280, 167157, 167034, 166911, 166788, 166665, 166542, 166419, 166296, 166173, 166050, 165927, 165804, 165681, 165558, 165435, 165312, 165189, 165066, 164943, 164820, 164697, 164574, 164451, 164328, 164205, 164082, 163959, 163836, 163713, 163590, 163467, 163344, 163221, 163098, 162975, 162852, 162729, 162606, 162483, 162360, 162237, 162114, 161991, 161868, 161745, 161622, 161499, 161376, 161253, 161130, 161007, 160884, 160761, 160638, 160515, 160392, 160269, 160146, 160023, 159900, 159777, 159654, 159531, 159408, 159285, 159162, 159039, 158916, 158793, 158670, 158547, 158424, 158301, 158178, 158055, 157932, 157809, 157686, 157563, 157440, 157317, 157194, 157071, 156948, 156825, 156702, 156579, 156456, 156333, 156210, 156087, 155964, 155841, 155718, 155595, 155472, 155349, 155226, 155103, 154980, 154857, 154734, 154611, 154488, 154365, 154242, 154119, 153996, 153873, 153750, 153627, 153504, 153381, 153258, 153135, 153012, 152889, 152766, 152643, 152520, 152397, 152274, 152151, 152028, 151905, 151782, 151659, 151536, 151413, 151290, 151167, 151044, 150921, 150798, 150675, 150552, 150429, 150306, 150183, 150060, 149937, 149814, 149691, 149568, 149445, 149322, 149199, 149076, 148953, 148830, 148707, 148584, 148461, 148338, 148215, 148092, 147969, 147846, 147723, 147600, 147477, 147354, 147231, 147108, 146985, 146862, 146739, 146616, 146493, 146370, 146247, 146124, 146001, 145878, 145755, 145632, 145509, 145386, 145263, 145140, 145017, 144894, 144771, 144648, 144525, 144402, 144279, 144156, 144033, 143910, 143787, 143664, 143541, 143418, 143295, 143172, 143049, 142926, 142803, 142680, 142557, 142434, 142311, 142188, 142065, 141942, 141819, 141696, 141573, 141450, 141327, 141204, 141081, 140958, 140835, 140712, 140589, 140466, 140343, 140220, 140097, 139974, 139851, 139728, 139605, 139482, 139359, 139236, 139113, 138990, 138867, 138744, 138621, 138498, 138375, 138252, 138129, 138006, 137883, 137760, 137637, 137514, 137391, 137268, 137145, 137022, 136899, 136776, 136653, 136530, 136407, 136284, 136161, 136038, 135915, 135792, 135669, 135546, 135423, 135300, 135177, 135054, 134931, 134808, 134685, 134562, 134439, 134316, 134193, 134070, 133947, 133824, 133701, 133578, 133455, 133332, 133209, 133086, 132963, 132840, 132717, 132594, 132471, 132348, 132225, 132102, 131979, 131856, 131733, 131610, 131487, 131364, 131241, 131118, 130995, 130872, 130749, 130626, 130503, 130380, 130257, 130134, 130011, 129888, 129765, 129642, 129519, 129396, 129273, 129150, 129027, 128904, 128781, 128658, 128535, 128412, 128289, 128166, 128043, 127920, 127797, 127674, 127551, 127428, 127305, 127182, 127059, 126936, 126813, 126690, 126567, 126444, 126321, 126198, 126075, 125952, 125829, 125706, 125583, 125460, 125337, 125214, 125091, 124968, 124845, 124722, 124599, 124476, 124353, 124230, 124107, 123984, 123861, 123738, 123615, 123492, 123369, 123246, 123123, 123000, 122877, 122754, 122631, 122508, 122385, 122262, 122139, 122016, 121893, 121770, 121647, 121524, 121401, 121278, 121155, 121032, 120909, 120786, 120663, 120540, 120417, 120294, 120171, 120048, 119925, 119802, 119679, 119556, 119433, 119310, 119187, 119064, 118941, 118818, 118695, 118572, 118449, 118326, 118203, 118080, 117957, 117834, 117711, 117588, 117465, 117342, 117219, 117096, 116973, 116850, 116727, 116604, 116481, 116358, 116235, 116112, 115989, 115866, 115743, 115620, 115497, 115374, 115251, 115128, 115005, 114882, 114759, 114636, 114513, 114390, 114267, 114144, 114021, 113898, 113775, 113652, 113529, 113406, 113283, 113160, 113037, 112914, 112791, 112668, 112545, 112422, 112299, 112176, 112053, 111930, 111807, 111684, 111561, 111438, 111315, 111192, 111069, 110946, 110823, 110700, 110577, 110454, 110331, 110208, 110085, 109962, 109839, 109716, 109593, 109470, 109347, 109224, 109101, 108978, 108855, 108732, 108609, 108486, 108363, 108240, 108117, 107994, 107871, 107748, 107625, 107502, 107379, 107256, 107133, 107010, 106887, 106764, 106641, 106518, 106395, 106272, 106149, 106026, 105903, 105780, 105657, 105534, 105411, 105288, 105165, 105042, 104919, 104796, 104673, 104550, 104427, 104304, 104181, 104058, 103935, 103812, 103689, 103566, 103443, 103320, 103197, 103074, 102951, 102828, 102705, 102582, 102459, 102336, 102213, 102090, 101967, 101844, 101721, 101598, 101475, 101352, 101229, 101106, 100983, 100860, 100737, 100614, 100491, 100368, 100245, 100122, 99999, 99876, 99753, 99630, 99507, 99384, 99261, 99138, 99015, 98892, 98769, 98646, 98523, 98400, 98277, 98154, 98031, 97908, 97785, 97662, 97539, 97416, 97293, 97170, 97047, 96924, 96801, 96678, 96555, 96432, 96309, 96186, 96063, 95940, 95817, 95694, 95571, 95448, 95325, 95202, 95079, 94956, 94833, 94710, 94587, 94464, 94341, 94218, 94095, 93972, 93849, 93726, 93603, 93480, 93357, 93234, 93111, 92988, 92865, 92742, 92619, 92496, 92373, 92250, 92127, 92004, 91881, 91758, 91635, 91512, 91389, 91266, 91143, 91020, 90897, 90774, 90651, 90528, 90405, 90282, 90159, 90036, 89913, 89790, 89667, 89544, 89421, 89298, 89175, 89052, 88929, 88806, 88683, 88560, 88437, 88314, 88191, 88068, 87945, 87822, 87699, 87576, 87453, 87330, 87207, 87084, 86961, 86838, 86715, 86592, 86469, 86346, 86223, 86100, 85977, 85854, 85731, 85608, 85485, 85362, 85239, 85116, 84993, 84870, 84747, 84624, 84501, 84378, 84255, 84132, 84009, 83886, 83763, 83640, 83517, 83394, 83271, 83148, 83025, 82902, 82779, 82656, 82533, 82410, 82287, 82164, 82041, 81918, 81795, 81672, 81549, 81426, 81303, 81180, 81057, 80934, 80811, 80688, 80565, 80442, 80319, 80196, 80073, 79950, 79827, 79704, 79581, 79458, 79335, 79212, 79089, 78966, 78843, 78720, 78597, 78474, 78351, 78228, 78105, 77982, 77859, 77736, 77613, 77490, 77367, 77244, 77121, 76998, 76875, 76752, 76629, 76506, 76383, 76260, 76137, 76014, 75891, 75768, 75645, 75522, 75399, 75276, 75153, 75030, 74907, 74784, 74661, 74538, 74415, 74292, 74169, 74046, 73923, 73800, 73677, 73554, 73431, 73308, 73185, 73062, 72939, 72816, 72693, 72570, 72447, 72324, 72201, 72078, 71955, 71832, 71709, 71586, 71463, 71340, 71217, 71094, 70971, 70848, 70725, 70602, 70479, 70356, 70233, 70110, 69987, 69864, 69741, 69618, 69495, 69372, 69249, 69126, 69003, 68880, 68757, 68634, 68511, 68388, 68265, 68142, 68019, 67896, 67773, 67650, 67527, 67404, 67281, 67158, 67035, 66912, 66789, 66666, 66543, 66420, 66297, 66174, 66051, 65928, 65805, 65682, 65559, 65436, 65313, 65190, 65067, 64944, 64821, 64698, 64575, 64452, 64329, 64206, 64083, 63960, 63837, 63714, 63591, 63468, 63345, 63222, 63099, 62976, 62853, 62730, 62607, 62484, 62361, 62238, 62115, 61992, 61869, 61746, 61623, 61500, 61377, 61254, 61131, 61008, 60885, 60762, 60639, 60516, 60393, 60270, 60147, 60024, 59901, 59778, 59655, 59532, 59409, 59286, 59163, 59040, 58917, 58794, 58671, 58548, 58425, 58302, 58179, 58056, 57933, 57810, 57687, 57564, 57441, 57318, 57195, 57072, 56949, 56826, 56703, 56580, 56457, 56334, 56211, 56088, 55965, 55842, 55719, 55596, 55473, 55350, 55227, 55104, 54981, 54858, 54735, 54612, 54489, 54366, 54243, 54120, 53997, 53874, 53751, 53628, 53505, 53382, 53259, 53136, 53013, 52890, 52767, 52644, 52521, 52398, 52275, 52152, 52029, 51906, 51783, 51660, 51537, 51414, 51291, 51168, 51045, 50922, 50799, 50676, 50553, 50430, 50307, 50184, 50061, 49938, 49815, 49692, 49569, 49446, 49323, 49200, 49077, 48954, 48831, 48708, 48585, 48462, 48339, 48216, 48093, 47970, 47847, 47724, 47601, 47478, 47355, 47232, 47109, 46986, 46863, 46740, 46617, 46494, 46371, 46248, 46125, 46002, 45879, 45756, 45633, 45510, 45387, 45264, 45141, 45018, 44895, 44772, 44649, 44526, 44403, 44280, 44157, 44034, 43911, 43788, 43665, 43542, 43419, 43296, 43173, 43050, 42927, 42804, 42681, 42558, 42435, 42312, 42189, 42066, 41943, 41820, 41697, 41574, 41451, 41328, 41205, 41082, 40959, 40836, 40713, 40590, 40467, 40344, 40221, 40098, 39975, 39852, 39729, 39606, 39483, 39360, 39237, 39114, 38991, 38868, 38745, 38622, 38499, 38376, 38253, 38130, 38007, 37884, 37761, 37638, 37515, 37392, 37269, 37146, 37023, 36900, 36777, 36654, 36531, 36408, 36285, 36162, 36039, 35916, 35793, 35670, 35547, 35424, 35301, 35178, 35055, 34932, 34809, 34686, 34563, 34440, 34317, 34194, 34071, 33948, 33825, 33702, 33579, 33456, 33333, 33210, 33087, 32964, 32841, 32718, 32595, 32472, 32349, 32226, 32103, 31980, 31857, 31734, 31611, 31488, 31365, 31242, 31119, 30996, 30873, 30750, 30627, 30504, 30381, 30258, 30135, 30012, 29889, 29766, 29643, 29520, 29397, 29274, 29151, 29028, 28905, 28782, 28659, 28536, 28413, 28290, 28167, 28044, 27921, 27798, 27675, 27552, 27429, 27306, 27183, 27060, 26937, 26814, 26691, 26568, 26445, 26322, 26199, 26076, 25953, 25830, 25707, 25584, 25461, 25338, 25215, 25092, 24969, 24846, 24723, 24600, 24477, 24354, 24231, 24108, 23985, 23862, 23739, 23616, 23493, 23370, 23247, 23124, 23001, 22878, 22755, 22632, 22509, 22386, 22263, 22140, 22017, 21894, 21771, 21648, 21525, 21402, 21279, 21156, 21033, 20910, 20787, 20664, 20541, 20418, 20295, 20172, 20049, 19926, 19803, 19680, 19557, 19434, 19311, 19188, 19065, 18942, 18819, 18696, 18573, 18450, 18327, 18204, 18081, 17958, 17835, 17712, 17589, 17466, 17343, 17220, 17097, 16974, 16851, 16728, 16605, 16482, 16359, 16236, 16113, 15990, 15867, 15744, 15621, 15498, 15375, 15252, 15129, 15006, 14883, 14760, 14637, 14514, 14391, 14268, 14145, 14022, 13899, 13776, 13653, 13530, 13407, 13284, 13161, 13038, 12915, 12792, 12669, 12546, 12423, 12300, 12177, 12054, 11931, 11808, 11685, 11562, 11439, 11316, 11193, 11070, 10947, 10824, 10701, 10578, 10455, 10332, 10209, 10086, 9963, 9840, 9717, 9594, 9471, 9348, 9225, 9102, 8979, 8856, 8733, 8610, 8487, 8364, 8241, 8118, 7995, 7872, 7749, 7626, 7503, 7380, 7257, 7134, 7011, 6888, 6765, 6642, 6519, 6396, 6273, 6150, 6027, 5904, 5781, 5658, 5535, 5412, 5289, 5166, 5043, 4920, 4797, 4674, 4551, 4428, 4305, 4182, 4059, 3936, 3813, 3690, 3567, 3444, 3321, 3198, 3075, 2952, 2829, 2706, 2583, 2460, 2337, 2214, 2091, 1968, 1845, 1722, 1599, 1476, 1353, 1230, 1107, 984, 861, 738, 615, 492, 369, 246, 123, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - bits != 0 and Barrett division in limbs_div_to_out_unbalanced test( &[10; 1770], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 461373439, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967024, u32::MAX, 4294945791, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffff, 0, 54525952, 0, 402653184, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 44, 0, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, 4287102975, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4026531839, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 6, 0, 16, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 18431, 0, 0, 0, 0, 0, 0x2000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4232052736, u32::MAX, 1610612735, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 2816, 0, 0, 0, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7340031, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff9, u32::MAX, 4294967103, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 1310720, 0, 0, 0, 0, 4294443008, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2818572287, 0, 0, 0, 0, 0, 0, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963968, u32::MAX, 4294918143, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffff, 0, 603979776, 0, 0, 0, 0, 0xf0000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 239, 0, 0, 0, 0, 0, 0x100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4293394432, u32::MAX, 4286578687, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3fffffff, 0, 0, 64, 0, 0, 0, 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 81919, 0, 0, 0, 0, 0, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3556769792, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 127, 0, 0x7000, 0, 0, 0, 0, 4294950912, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 25165823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967216, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffff, 0, 12582912, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fffffff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294930432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1ffffff, 0, 0x40000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2047, 0, 196608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0, 0x4000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294639616, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x1fffffff, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff4, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfff00000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x800000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 519], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], ); // - r_len > n_len || limbs_cmp_same_length(ns, &rs[..n_len]) == Less in // limbs_div_to_out_balanced test( &[10; 5], &[ 0, 0, 0, 0, 0, 0, 0, 18446744073709535232, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, 0xfffffff, 0, 0, 18446744073709550592, u64::MAX, 0x1ffffffff, 0, 0, 0, 18446744073709551488, u64::MAX, u64::MAX, u64::MAX, ], &[127, 0, 0, 0, 1], ); test( &[10; 4], &[ 18446463148488654849, 280925229285374, 16285016218270955520, 37348968499195, 18437754466102935552, 4286578943, ], &[280925220896767, 18446744073701163008, 34292631551], &[u64::MAX, 0, 2305843009213431808, 0], ); } } #[test] #[should_panic] fn limbs_div_fail_1() { limbs_div(&[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_div_fail_2() { limbs_div(&[1], &[4, 5]); } #[test] #[should_panic] fn limbs_div_fail_3() { limbs_div(&[1, 2, 3], &[4, 0]); } #[test] #[should_panic] fn limbs_div_to_out_fail_1() { limbs_div_to_out(&mut [10; 4], &mut [1, 2, 3], &mut [4]); } #[test] #[should_panic] fn limbs_div_to_out_fail_2() { limbs_div_to_out(&mut [10; 4], &mut [1], &mut [4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_fail_3() { limbs_div_to_out(&mut [10], &mut [1, 2, 3, 4], &mut [4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_fail_4() { limbs_div_to_out(&mut [10; 4], &mut [1, 2, 3], &mut [4, 0]); } #[test] #[should_panic] fn limbs_div_to_out_val_ref_fail_1() { limbs_div_to_out_val_ref(&mut [10; 4], &mut [1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_div_to_out_val_ref_fail_2() { limbs_div_to_out_val_ref(&mut [10; 4], &mut [1], &[4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_val_ref_fail_3() { limbs_div_to_out_val_ref(&mut [10], &mut [1, 2, 3, 4], &[4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_val_ref_fail_4() { limbs_div_to_out_val_ref(&mut [10; 4], &mut [1, 2, 3], &[4, 0]); } #[test] #[should_panic] fn limbs_div_to_out_ref_val_fail_1() { limbs_div_to_out_ref_val(&mut [10; 4], &[1, 2, 3], &mut [4]); } #[test] #[should_panic] fn limbs_div_to_out_ref_val_fail_2() { limbs_div_to_out_ref_val(&mut [10; 4], &[1], &mut [4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_ref_val_fail_3() { limbs_div_to_out_ref_val(&mut [10], &[1, 2, 3, 4], &mut [4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_ref_val_fail_4() { limbs_div_to_out_ref_val(&mut [10; 4], &[1, 2, 3], &mut [4, 0]); } #[test] #[should_panic] fn limbs_div_to_out_ref_ref_fail_1() { limbs_div_to_out_ref_ref(&mut [10; 4], &[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_div_to_out_ref_ref_fail_2() { limbs_div_to_out_ref_ref(&mut [10; 4], &[1], &[4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_ref_ref_fail_3() { limbs_div_to_out_ref_ref(&mut [10], &[1, 2, 3, 4], &[4, 5]); } #[test] #[should_panic] fn limbs_div_to_out_ref_ref_fail_4() { limbs_div_to_out_ref_ref(&mut [10; 4], &[1, 2, 3], &[4, 0]); } #[test] fn test_div() { let test = |s, t, quotient| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); x /= v.clone(); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); x /= &v; assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let q = u.clone() / v.clone(); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.clone() / &v; assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = &u / v.clone(); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = &u / &v; assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = BigUint::from_str(s).unwrap() / &BigUint::from_str(t).unwrap(); assert_eq!(q.to_string(), quotient); let q = rug::Integer::from_str(s).unwrap() / rug::Integer::from_str(t).unwrap(); assert_eq!(q.to_string(), quotient); let q = u.div_mod(v).0; assert_eq!(q.to_string(), quotient); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "1"); test("123", "1", "123"); test("123", "123", "1"); test("123", "456", "0"); test("456", "123", "3"); test("4294967295", "1", "4294967295"); test("4294967295", "4294967295", "1"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "3", "333333333333"); test("1000000000000", "123", "8130081300"); test("1000000000000", "4294967295", "232"); test( "1000000000000000000000000", "1", "1000000000000000000000000", ); test("1000000000000000000000000", "3", "333333333333333333333333"); test("1000000000000000000000000", "123", "8130081300813008130081"); test("1000000000000000000000000", "4294967295", "232830643708079"); test("1000000000000000000000000", "1234567890987", "810000006723"); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290113", ); test("3768477692975601", "11447376614057827956", "0"); test("3356605361737854", "3081095617839357", "1"); test("1098730198198174614195", "953382298040157850476", "1"); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", ); test("0", "1000000000000000000000000", "0"); test("123", "1000000000000000000000000", "0"); test( "915607705283450388306561139234228660872677067256472842161753852459689688332903348325308112\ 7923093090598913", "11669177832462215441614364516705357863717491965951", "784637716923245892498679555408392159158150581185689944063", ); } #[test] #[should_panic] fn div_assign_fail_1() { let mut x = Natural::from(10u32); x /= Natural::ZERO; } #[test] #[should_panic] fn div_assign_fail_2() { let mut x = Natural::ZERO; x /= Natural::ZERO; } #[test] #[should_panic] fn div_assign_ref_fail_1() { let mut x = Natural::from(10u32); x /= &Natural::ZERO; } #[test] #[should_panic] fn div_assign_ref_fail_2() { let mut x = Natural::ZERO; x /= &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_fail_1() { Natural::from(10u32) / Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn div_fail_2() { Natural::ZERO / Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_val_ref_fail_1() { Natural::from(10u32) / &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn div_val_ref_fail_2() { Natural::ZERO / &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_ref_val_fail_1() { &Natural::from(10u32) / Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn div_ref_val_fail_2() { &Natural::ZERO / Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn div_ref_ref_fail_1() { &Natural::from(10u32) / &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] fn div_ref_ref_fail_2() { &Natural::ZERO / &Natural::ZERO; } #[test] fn test_checked_div() { let test = |s, t, quotient| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let q = u.clone().checked_div(v.clone()); assert!(q.as_ref().is_none_or(Natural::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = u.clone().checked_div(&v); assert!(q.as_ref().is_none_or(Natural::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = (&u).checked_div(v.clone()); assert!(q.as_ref().is_none_or(Natural::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = (&u).checked_div(&v); assert!(q.as_ref().is_none_or(Natural::is_valid)); assert_eq!(q.to_debug_string(), quotient); let q = BigUint::from_str(s) .unwrap() .checked_div(&BigUint::from_str(t).unwrap()); assert_eq!(q.to_debug_string(), quotient); }; test("0", "1", "Some(0)"); test("0", "123", "Some(0)"); test("1", "1", "Some(1)"); test("123", "1", "Some(123)"); test("123", "123", "Some(1)"); test("123", "456", "Some(0)"); test("456", "123", "Some(3)"); test("4294967295", "1", "Some(4294967295)"); test("4294967295", "4294967295", "Some(1)"); test("1000000000000", "1", "Some(1000000000000)"); test("1000000000000", "3", "Some(333333333333)"); test("1000000000000", "123", "Some(8130081300)"); test("1000000000000", "4294967295", "Some(232)"); test("0", "0", "None"); test("1", "0", "None"); test("123", "0", "None"); test("1000000000000000000000000", "0", "None"); } #[test] fn limbs_div_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_div_limb_in_place(&mut xs, y); let out = xs.clone(); let q = Natural::from_limbs_asc(&old_xs) / Natural::from(y); assert_eq!(Natural::from_owned_limbs_asc(xs), q); let mut xs = old_xs.clone(); limbs_div_limb_in_place_alt(&mut xs, y); assert_eq!(xs, out); assert_eq!(Natural::from_owned_limbs_asc(limbs_div_limb(&old_xs, y)), q); }); } #[test] fn limbs_div_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_div_limb_to_out(&mut out, &xs, y); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_limbs_asc(&xs) / Natural::from(y) ); assert_eq!(&out[len..], &old_out[len..]); let mut out_alt = old_out; limbs_div_limb_to_out_alt(&mut out_alt, &xs, y); assert_eq!(out, out_alt); }, ); } #[test] fn limbs_div_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_div_limb_in_place(&mut xs, y); let out = xs.clone(); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_limbs_asc(&old_xs) / Natural::from(y) ); let mut xs = old_xs; limbs_div_limb_in_place_alt(&mut xs, y); assert_eq!(xs, out); }); } #[test] fn limbs_div_divisor_of_limb_max_with_carry_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_10().test_properties_with_config( &config, |(mut out, xs, divisor, carry)| { // TODO figure out what to test limbs_div_divisor_of_limb_max_with_carry_to_out::( &mut out, &xs, divisor, carry, ); }, ); } #[test] fn limbs_div_divisor_of_limb_max_with_carry_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_9().test_properties_with_config( &config, |(mut xs, divisor, carry)| { // TODO figure out what to test limbs_div_divisor_of_limb_max_with_carry_in_place(&mut xs, divisor, carry); }, ); } #[test] fn limbs_div_schoolbook_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_11().test_properties_with_config(&config, |(qs_in, ns_in, ds, inverse)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_schoolbook(&mut qs, &mut ns, &ds, inverse); verify_limbs_div(&qs_in, &ns_in, &ds, q_highest, &qs); }); } #[test] fn limbs_div_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_12().test_properties_with_config(&config, |(qs_in, ns, ds, inverse)| { let mut qs = qs_in.clone(); let q_highest = limbs_div_divide_and_conquer(&mut qs, &ns, &ds, inverse); verify_limbs_div(&qs_in, &ns, &ds, q_highest, &qs); }); } #[test] fn limbs_div_barrett_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_43().test_properties_with_config(&config, |(qs_in, ns, ds)| { let mut qs = qs_in.clone(); let mut scratch = vec![0; limbs_div_barrett_scratch_len(ns.len(), ds.len())]; let q_highest = limbs_div_barrett(&mut qs, &ns, &ds, &mut scratch); verify_limbs_div(&qs_in, &ns, &ds, q_highest, &qs); }); } #[test] fn limbs_div_schoolbook_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_11().test_properties_with_config(&config, |(qs_in, ns_in, ds, inverse)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_schoolbook_approx(&mut qs, &mut ns, &ds, inverse); verify_limbs_div_approx(&qs_in, &ns_in, &ds, q_highest, &qs); }); } #[test] fn limbs_div_divide_and_conquer_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); large_type_gen_var_12().test_properties_with_config(&config, |(qs_in, ns_in, ds, inverse)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_divide_and_conquer_approx(&mut qs, &mut ns, &ds, inverse); verify_limbs_div_approx(&qs_in, &ns_in, &ds, q_highest, &qs); }); } #[test] fn limbs_div_barrett_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_42().test_properties_with_config(&config, |(qs_in, ns, ds)| { let mut qs = qs_in.clone(); let mut scratch = vec![0; limbs_div_barrett_approx_scratch_len(ns.len(), ds.len())]; let q_highest = limbs_div_barrett_approx(&mut qs, &ns, &ds, &mut scratch); verify_limbs_div_approx_2(&qs_in, &ns, &ds, q_highest, &qs); }); } #[test] fn limbs_div_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_44().test_properties_with_config(&config, |(qs_in, ns, ds)| { let mut qs = qs_in.clone(); limbs_div_to_out_ref_ref(&mut qs, &ns, &ds); verify_limbs_div_2(&qs_in, &ns, &ds, &qs); let qs_out = qs; let mut qs = qs_in.clone(); let mut ns_cloned = ns.clone(); let mut ds_cloned = ds.clone(); limbs_div_to_out(&mut qs, &mut ns_cloned, &mut ds_cloned); assert_eq!(qs, qs_out); let mut qs = qs_in.clone(); let mut ns_cloned = ns.clone(); limbs_div_to_out_val_ref(&mut qs, &mut ns_cloned, &ds); assert_eq!(qs, qs_out); let mut qs = qs_in; let mut ds_cloned = ds.clone(); limbs_div_to_out_ref_val(&mut qs, &ns, &mut ds_cloned); assert_eq!(qs, qs_out); let qs = limbs_div(&ns, &ds); let qs: &[Limb] = &qs; assert_eq!(&qs_out[..qs.len()], qs); }); } // It would be a little confusing to only pass y by value #[allow(clippy::needless_pass_by_value)] fn div_properties_helper(x: Natural, y: Natural) { let mut mut_x = x.clone(); mut_x /= &y; assert!(mut_x.is_valid()); let q = mut_x; let mut mut_x = x.clone(); mut_x /= y.clone(); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = &x / &y; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = &x / y.clone(); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone() / &y; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone() / y.clone(); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!((&x).checked_div(&y).unwrap(), q); let q_alt = (&x).div_mod(&y).0; assert_eq!(q_alt, q); let num_q = BigUint::from(&x) / &BigUint::from(&y); assert_eq!(Natural::from(&num_q), q); let rug_q = rug::Integer::from(&x) / rug::Integer::from(&y); assert_eq!(Natural::exact_from(&rug_q), q); let r = &x - &q * &y; assert!(r < y); assert_eq!(q * y + r, x); } #[allow(clippy::eq_op)] #[test] fn div_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); natural_pair_gen_var_5().test_properties_with_config(&config, |(x, y)| { div_properties_helper(x, y); }); natural_pair_gen_var_6().test_properties_with_config(&config, |(x, y)| { div_properties_helper(x, y); }); natural_gen().test_properties(|n| { assert_eq!(&n / Natural::ONE, n); }); natural_gen_var_2().test_properties(|n| { assert_eq!(&n / &n, 1); assert_eq!(Natural::ZERO / &n, Natural::ZERO); if n > 1 { assert_eq!(Natural::ONE / n, Natural::ZERO); } }); unsigned_pair_gen_var_12::() .test_properties(|(x, y)| assert_eq!(Natural::from(x) / Natural::from(y), x / y)); } #[test] fn checked_div_properties() { natural_pair_gen().test_properties(|(x, y)| { let quotient_val_val = x.clone().checked_div(y.clone()); let quotient_val_ref = x.clone().checked_div(&y); let quotient_ref_val = (&x).checked_div(y.clone()); let quotient = (&x).checked_div(&y); assert!(quotient_val_val.as_ref().is_none_or(Natural::is_valid)); assert!(quotient_val_ref.as_ref().is_none_or(Natural::is_valid)); assert!(quotient_ref_val.as_ref().is_none_or(Natural::is_valid)); assert!(quotient.as_ref().is_none_or(Natural::is_valid)); assert_eq!(quotient_val_val, quotient); assert_eq!(quotient_val_ref, quotient); assert_eq!(quotient_ref_val, quotient); if y != 0u32 { assert_eq!(quotient, Some(&x / &y)); } assert_eq!( BigUint::from(&x) .checked_div(&BigUint::from(&y)) .map(|n| Natural::from(&n)), quotient ); }); natural_gen().test_properties(|ref x| { assert_eq!(x.checked_div(Natural::ZERO), None); assert_eq!(x.checked_div(Natural::ONE), Some(x.clone())); }); natural_gen_var_2().test_properties(|ref x| { assert_eq!(Natural::ZERO.checked_div(x), Some(Natural::ZERO)); assert_eq!(Natural::ONE.checked_div(x), Some(Natural::from(*x == 1u32))); assert_eq!(x.checked_div(x), Some(Natural::ONE)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/div_exact.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ DivExact, DivExactAssign, DivMod, DivRound, EqModPowerOf2, ModPowerOf2, ModPowerOf2Neg, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::common::rle_decode; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_22, unsigned_pair_gen_var_11, unsigned_vec_pair_gen_var_12, }; use malachite_nz::integer::Integer; use malachite_nz::natural::arithmetic::div_exact::{ limbs_div_exact, limbs_div_exact_3, limbs_div_exact_3_in_place, limbs_div_exact_3_to_out, limbs_div_exact_limb, limbs_div_exact_limb_in_place, limbs_div_exact_limb_in_place_no_special_3, limbs_div_exact_limb_no_special_3, limbs_div_exact_limb_to_out, limbs_div_exact_limb_to_out_no_special_3, limbs_div_exact_to_out, limbs_div_exact_to_out_ref_ref, limbs_div_exact_to_out_ref_val, limbs_div_exact_to_out_val_ref, limbs_modular_div, limbs_modular_div_barrett, limbs_modular_div_barrett_scratch_len, limbs_modular_div_divide_and_conquer, limbs_modular_div_mod_barrett, limbs_modular_div_mod_barrett_scratch_len, limbs_modular_div_mod_divide_and_conquer, limbs_modular_div_mod_schoolbook, limbs_modular_div_ref, limbs_modular_div_ref_scratch_len, limbs_modular_div_schoolbook, limbs_modular_div_schoolbook_in_place, limbs_modular_div_scratch_len, limbs_modular_invert, limbs_modular_invert_limb, limbs_modular_invert_scratch_len, test_invert_limb_table, }; use malachite_nz::natural::{Natural, limb_to_bit_count}; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ large_type_gen_var_13, large_type_gen_var_14, large_type_gen_var_15, large_type_gen_var_16, natural_gen, natural_gen_var_2, natural_pair_gen_var_6, unsigned_vec_gen_var_5, unsigned_vec_pair_gen_var_13, unsigned_vec_quadruple_gen_var_2, unsigned_vec_triple_gen_var_46, unsigned_vec_triple_gen_var_47, unsigned_vec_triple_gen_var_48, unsigned_vec_unsigned_pair_gen_var_29, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14, }; use malachite_nz::test_util::natural::arithmetic::div_exact::{ limbs_div_exact_3_in_place_alt, limbs_div_exact_3_to_out_alt, }; use std::str::FromStr; #[test] fn test_test_invert_limb_table() { test_invert_limb_table(); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_invert_limb() { let test = |x, inverse| { assert_eq!(limbs_modular_invert_limb(x), inverse); }; test(1, 1); test(3, 2863311531); test(5, 3435973837); test(7, 3067833783); test(123, 3945782963); test(1000000001, 2211001857); test(0x7fffffff, 0x7fffffff); test(2863311531, 3); test(u32::MAX, u32::MAX); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_invert_limb_fail_1() { limbs_modular_invert_limb::(0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_invert_limb_fail_2() { limbs_modular_invert_limb::(2); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_exact_limb_and_limbs_div_exact_limb_in_place() { let test = |ns: &[Limb], d: Limb, q: &[Limb]| { let ns_old = ns; assert_eq!(limbs_div_exact_limb(ns_old, d), q); let mut ns = ns_old.to_vec(); limbs_div_exact_limb_in_place(&mut ns, d); assert_eq!(ns, q); assert_eq!(limbs_div_exact_limb_no_special_3(ns_old, d), q); let mut ns = ns_old.to_vec(); limbs_div_exact_limb_in_place_no_special_3(&mut ns, d); assert_eq!(ns, q); }; test(&[0], 2, &[0]); test(&[6], 2, &[3]); test(&[0, 0], 2, &[0, 0]); test(&[6, 7], 1, &[6, 7]); test(&[6, 7], 2, &[0x80000003, 3]); test(&[92, 101, 102], 10, &[1288490198, 858993469, 10]); test(&[4294966783, 455], 789, &[2482262467, 0]); test(&[u32::MAX - 1, u32::MAX], 2, &[u32::MAX, 0x7fffffff]); test(&[u32::MAX, u32::MAX], 3, &[0x55555555, 0x55555555]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_fail_1() { limbs_div_exact_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_fail_2() { limbs_div_exact_limb(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_in_place_fail_1() { limbs_div_exact_limb_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_in_place_fail_2() { limbs_div_exact_limb_in_place(&mut [10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_exact_limb_to_out() { let test = |out_before: &[Limb], ns: &[Limb], d: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_div_exact_limb_to_out::(&mut out, ns, d); assert_eq!(out, out_after); let mut out = out_before.to_vec(); limbs_div_exact_limb_to_out_no_special_3::(&mut out, ns, d); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[0], 2, &[0, 10, 10, 10]); test(&[10, 10, 10, 10], &[6], 2, &[3, 10, 10, 10]); test(&[10, 10, 10, 10], &[0, 0], 2, &[0, 0, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 1, &[6, 7, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, &[0x80000003, 3, 10, 10]); test( &[10, 10, 10, 10], &[92, 101, 102], 10, &[1288490198, 858993469, 10, 10], ); test( &[10, 10, 10, 10], &[4294966783, 455], 789, &[2482262467, 0, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX - 1, u32::MAX], 2, &[u32::MAX, 0x7fffffff, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 3, &[0x55555555, 0x55555555, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_to_out_fail_1() { limbs_div_exact_limb_to_out::(&mut [10, 10], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_to_out_fail_2() { limbs_div_exact_limb_to_out::(&mut [10, 10], &[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_limb_to_out_fail_3() { limbs_div_exact_limb_to_out::(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_exact_3_and_limbs_div_exact_3_in_place() { let test = |ns: &[Limb], q: &[Limb]| { let old_ns = ns; assert_eq!(limbs_div_exact_3(ns), q); assert_eq!(limbs_div_exact_limb(ns, 3), q); let mut ns = old_ns.to_vec(); limbs_div_exact_3_in_place(&mut ns); assert_eq!(ns, q); let mut ns = old_ns.to_vec(); limbs_div_exact_3_in_place_alt(&mut ns); assert_eq!(ns, q); let mut ns = old_ns.to_vec(); limbs_div_exact_limb_in_place(&mut ns, 3); assert_eq!(ns, q); }; test(&[0], &[0]); test(&[6], &[2]); test(&[0, 0], &[0, 0]); test(&[8, 7], &[1431655768, 2]); test(&[100, 101, 102], &[2863311564, 33, 34]); test(&[u32::MAX, u32::MAX], &[0x55555555, 0x55555555]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_3_fail() { limbs_div_exact_3(&[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_3_in_place_fail() { limbs_div_exact_3_in_place(&mut []); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_exact_3_to_out() { let test = |out_before: &[Limb], xs: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_div_exact_3_to_out::(&mut out, xs); assert_eq!(out, out_after); let mut out = out_before.to_vec(); limbs_div_exact_3_to_out_alt(&mut out, xs); assert_eq!(out, out_after); let mut out = out_before.to_vec(); limbs_div_exact_limb_to_out::(&mut out, xs, 3); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[0], &[0, 10, 10, 10]); test(&[10, 10, 10, 10], &[6], &[2, 10, 10, 10]); test(&[10, 10, 10, 10], &[0, 0], &[0, 0, 10, 10]); test(&[10, 10, 10, 10], &[8, 7], &[1431655768, 2, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], &[2863311564, 33, 34, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], &[0x55555555, 0x55555555, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_3_to_out_fail_1() { limbs_div_exact_3_to_out::(&mut [10, 10], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_3_to_out_fail_2() { limbs_div_exact_3_to_out::(&mut [10], &[10, 10]); } fn verify_limbs_modular_invert(ds: &[Limb], is: &[Limb]) { let d = Natural::from_limbs_asc(ds); let i = Natural::from_limbs_asc(is); let pow = limb_to_bit_count(ds.len()); assert!((d * i).eq_mod_power_of_2(&Natural::ONE, pow)); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_invert() { let test = |is_in: &[Limb], ds: &[Limb], is_out: &[Limb]| { let n = ds.len(); let mut is = is_in.to_vec(); let mut scratch = vec![0; limbs_modular_invert_scratch_len(n)]; limbs_modular_invert(&mut is, ds, &mut scratch); assert_eq!(&is[..n], is_out); verify_limbs_modular_invert(ds, is_out); }; // - rn < DC_BDIV_Q_THRESHOLD test(&[10; 3], &[1], &[1]); test(&[10; 3], &[3], &[2863311531]); test(&[10; 3], &[5], &[3435973837]); test(&[10; 3], &[7], &[3067833783]); test(&[10; 3], &[1, 1, 1], &[1, u32::MAX, u32::MAX]); test(&[10; 4], &[1, 2, 3, 4], &[1, u32::MAX - 1, 0, 0]); test(&[10; 4], &[1, 0, 0, 0], &[1, 0, 0, 0]); test(&[10; 4], &[u32::MAX; 4], &[u32::MAX; 4]); // - rn >= DC_BDIV_Q_THRESHOLD test( &[10; 162], &[ 3228372949, 511037199, 1766844847, 2482988267, 1469636570, 157644737, 1548533671, 1988920387, 949768135, 3990423112, 2320976801, 2511643497, 3093682328, 3428374192, 1438878145, 2361210316, 3906032124, 2138110309, 1599933050, 3823943671, 2259360130, 823468722, 3291657189, 1273080994, 1300170623, 1148822796, 467501062, 3149282203, 94789064, 4211146202, 938886545, 537979797, 2587941131, 108323731, 2067107670, 105331677, 1935250512, 1452284826, 1800549345, 723680431, 2794168985, 904704921, 3016862976, 1287705882, 4132038308, 624608496, 1997184254, 448598152, 1820893106, 195416787, 651904977, 2955157364, 94342663, 437349382, 377636621, 3709576977, 1757632127, 4278237941, 34068629, 2454145994, 4156002276, 3961922656, 2767617077, 3288237973, 4240277740, 1356471757, 9181081, 1636990395, 1662834396, 626816820, 2875878941, 921881987, 2158368015, 840508787, 3305037379, 3711054769, 1268398179, 3896061030, 1052597619, 2040268853, 3162123944, 1619537254, 4260249983, 788774918, 323831598, 70896907, 791692982, 1081190864, 2374371095, 1425732171, 2496438238, 4066183598, 2164924109, 3370833658, 4001560838, 1910191661, 4219785120, 451095085, 3421655677, 2108533585, 3424568374, 2891875753, 3180562301, 954785991, 2447015474, 3930894331, 715625138, 2543510489, 360538720, 3774920082, 2598943309, 2345969301, 1201240332, 3131955258, 115485203, 1731266015, 3565733667, 3708968152, 3343319896, 4164543588, 958613110, 460381838, 508487067, 79603149, 4226757805, 2221491775, 793628682, 2721231001, 1503226493, 3320680646, 536612991, 1986939605, 3925890122, 953289772, 453639997, 3182429348, 3743006936, 4003692116, 1964545970, 4050648413, 4076626036, 416351025, 1696831244, 3133590002, 1111664786, 2906324009, 1439094475, 2214055485, 2798705323, 435684851, 3596001227, 3036344489, 3889898941, 1065048513, 4016594719, 4180638855, 3698313403, 2650988185, 407962531, 3005112678, 4110843613, 1265856698, ], &[ 991539581, 170886811, 1946164502, 4138638160, 4166973165, 3436035151, 3104724201, 1844757770, 2340741284, 3474459530, 2913154637, 1985603183, 1490032629, 404439462, 2516898868, 4063787328, 2068346028, 3562917355, 3607751063, 4085533551, 3185010719, 4194162665, 3987252641, 3919902763, 1349071027, 3498237178, 1424577630, 2755258000, 1356884618, 432658210, 1133331071, 1971536170, 609062776, 2584940413, 503389674, 833096403, 2005416443, 873663129, 600036946, 1888391296, 3845065736, 2778213007, 3174588960, 860483363, 3214125890, 241195760, 4142060378, 3524395685, 2521966985, 3548302474, 4280709033, 1127351847, 3384545423, 1156416795, 2964727747, 2348926815, 3088158836, 914441803, 741513463, 43888624, 3905516593, 2467124760, 57532003, 2507495445, 3391285900, 917840688, 1449210608, 83470763, 2386746834, 518977089, 2745927519, 1466192189, 1209060587, 1707570892, 1673078302, 921540600, 3312933158, 503196443, 2601292096, 584811553, 315531478, 2613557634, 1029661810, 1565433701, 2749963283, 797016668, 2524006881, 4144613766, 342648943, 3634335756, 2886479078, 3729634162, 2446396883, 2646833057, 3809228466, 1241062391, 1771218854, 1859001695, 181499665, 2243910284, 3135305341, 1144637960, 377778783, 462714009, 1503150032, 2671008870, 2934075825, 1452005121, 869697216, 2087204075, 3565024128, 3030614795, 4198797483, 4039346519, 601848748, 4060938550, 2096365943, 2015345784, 2227066926, 2589779098, 2064017544, 3930785044, 572495510, 1372658164, 2267700924, 3842986739, 1865979088, 727501730, 3530720452, 2082196229, 744666215, 1657468106, 1799434953, 1390303492, 713826320, 92635671, 3263118136, 4104386251, 2272448841, 2859245350, 3739570419, 2388112539, 2973693102, 2566815653, 909557454, 3719121807, 4178393753, 2424198070, 1957898281, 1984544495, 1408061170, 3310277440, 1794952171, 452701329, 3882836884, 3298396236, 3967258537, 162517223, 3293672996, 764489620, 714009670, 31373948, ], ); // - rn >= BINV_NEWTON_THRESHOLD // - rn < d_len test( &[10; 1539], &[ 2598813973, 1904197782, 1215006787, 2930851058, 147918011, 1108782873, 2193711651, 927233146, 4123817534, 3041706771, 2553964352, 2170557862, 2838589053, 2708835560, 2407955329, 1653207324, 2470552742, 3357058396, 1072990020, 1514783799, 1734243804, 1048851304, 3193592152, 1383793603, 2063694499, 3485786208, 990960024, 3569185429, 1155708496, 1416333121, 623402323, 3585705881, 2928088588, 4117621841, 3292316347, 2217241313, 1950216441, 1391040412, 2926386224, 3240560579, 3973468920, 2847202482, 2728825575, 2388048350, 3463506691, 3707514927, 865702555, 681215612, 2250616248, 1724513618, 364443494, 318451745, 1623887866, 1280032334, 35195442, 3837277484, 3573894817, 1602810477, 2072874171, 3800895590, 4253419440, 3499691102, 3587932863, 3517441378, 514856216, 1648457744, 1474005402, 700069688, 1803098596, 378514692, 3068261379, 3834605983, 93188389, 516236732, 2468656032, 4095977127, 3706578522, 3452719188, 1052956630, 813640425, 3047313546, 754584849, 3584789926, 347367947, 1332536470, 94171148, 626270691, 665836088, 426974652, 749957497, 1566095325, 3066600838, 4106843490, 318006871, 162882344, 3632111614, 720131390, 2147721707, 2217002633, 2466031857, 1087787961, 753159680, 366300446, 3082468114, 3984408901, 4057095635, 851983865, 4150513631, 1165194321, 2055798628, 2975996128, 2693369845, 3726562839, 3482086133, 4069043610, 1448967233, 700979569, 1698695640, 2318799208, 3684286306, 4092668018, 3628416641, 584456626, 1679287620, 1813093480, 177926224, 998082621, 3120492909, 1996199168, 3491975384, 3147828383, 2087111449, 381360867, 1127916110, 3472685226, 3293954452, 490729044, 3264678372, 1277191068, 4239255920, 2343436004, 2451796708, 1844810428, 2031787164, 3768550378, 3743966167, 2637191163, 3978079759, 4158883864, 1561267833, 539304561, 3435817790, 277956235, 4028949085, 2643928548, 2755470882, 3796376394, 194519280, 98463778, 3179299980, 2447702226, 150057260, 3463931601, 906456277, 990239469, 512339370, 2261507614, 2826877099, 3855453279, 2271503686, 841719073, 1591142177, 2651714174, 3361609137, 3279250024, 3326254458, 333896144, 3528172547, 3941409760, 1558812882, 3841874000, 3172301956, 4257828380, 4114850067, 2182891616, 2046840523, 1555755083, 2209766728, 2332501890, 607500373, 4124706810, 1713777506, 2341598661, 2284959418, 2746608689, 867377978, 336903700, 2503448208, 701980251, 2377952035, 614377477, 4284955660, 3814775340, 74129761, 1280559390, 2313692692, 1849232614, 2933185433, 1636271207, 630083065, 433420841, 471362220, 4210050941, 406797277, 582028044, 528813510, 2576049278, 540310007, 2789529550, 3534664845, 3236430259, 1506736021, 1977751182, 2006662671, 3679126532, 3806292929, 322589328, 2243078958, 2178902647, 2189720772, 3791358339, 1508304160, 1013509043, 3587377598, 3623382349, 1086144534, 1599008554, 1093927956, 2876914186, 543927302, 2219667262, 3853928343, 2487266159, 2613372592, 3550686437, 3716813778, 961453654, 2039051889, 4283100852, 3145660844, 1250225831, 198998794, 3726057928, 2284062625, 2219120593, 2244278486, 3790941761, 4203700163, 3879487839, 2965718505, 2863698764, 63056401, 475617471, 399914031, 459648012, 3133447831, 3412742746, 1512219896, 402842103, 4119870394, 2231397283, 1516833787, 1104380754, 128232714, 296865691, 1663298638, 716369560, 2904885147, 4237273250, 343946912, 2604094031, 217784841, 1162604926, 1345215097, 1426555576, 3614102008, 3943750939, 1639058309, 3296139198, 1330339563, 426593850, 1532081057, 1300177557, 1482433791, 812987015, 3232993095, 1037853411, 645052957, 2928052694, 1226934622, 2336175954, 1920836876, 2517428765, 3726338359, 4041660846, 2092081260, 3380258824, 1697518166, 3349439761, 743024530, 1795639086, 1779094250, 503268222, 3554837208, 2986098469, 2762697287, 232864157, 3768291070, 2983947152, 1577288457, 1050740564, 834028049, 1274280907, 3769464765, 1910494593, 2197778112, 2813074316, 2881147492, 1559228213, 1461309572, 1700587844, 2988103759, 1717431083, 951586291, 1707887130, 985013185, 3532658879, 2597699341, 1911327175, 3080664111, 3484272917, 794091071, 2311407322, 342113645, 1768703425, 2382063884, 3831832486, 3217975952, 3451120056, 3035392294, 136312738, 1699608380, 700762772, 3631031559, 1846450824, 1131124755, 1046357323, 2552828340, 2598371768, 795498120, 3174589062, 3838467339, 2334795665, 3324675939, 3403942196, 2075108646, 4259667163, 545251542, 749294402, 3324014447, 1729518387, 3551096145, 1758729590, 2379344936, 2455329109, 1757426268, 1706226190, 902425986, 2432676044, 2039145952, 410402636, 1639537846, 1305863342, 256740017, 3207555620, 3925040779, 668173470, 1141011911, 4212893794, 1581027147, 363670779, 2004465281, 1138726957, 645471449, 3585049231, 2777598154, 2922780411, 2222055902, 3815639175, 429697628, 4000303790, 3545345324, 3542109929, 509705074, 3722614775, 1753809005, 1973665455, 3780943261, 2494678174, 2641931684, 3388813526, 3347201186, 619828405, 2625911693, 3122659421, 3479474745, 3245356132, 1832479544, 3308783684, 1963028441, 640786937, 1641844190, 211570630, 1733515651, 2171524601, 3396267685, 3914881000, 996687218, 1617466047, 3343054134, 1737892381, 3544966831, 3416864496, 107959379, 2249494870, 793869312, 3685840230, 1757287133, 1655716303, 4226516527, 2538565645, 278467613, 2644886589, 2699974905, 1984329139, 1005957589, 789155264, 3666799939, 1611583926, 809907316, 3452803056, 1107204019, 2209104411, 1462179962, 2853352142, 3225410978, 2108213590, 4192481899, 1912371245, 1171525154, 3712460427, 2560727022, 1086797266, 952026066, 685685805, 1936296543, 3499184244, 196202245, 3078070455, 2171291372, 2730765878, 1573851700, 2931331934, 2847177501, 3478529515, 2313080814, 1556316903, 1559216686, 3130885922, 1862119430, 3274978261, 206968409, 2624567354, 1978029702, 4063454216, 2415324407, 1518621963, 747943965, 1111109939, 4070402813, 3113587512, 898431887, 316373197, 3046639257, 173632841, 3798588025, 1794547053, 272903937, 863380298, 2774736392, 2777149271, 3206794646, 32657715, 1025716581, 1615425071, 3173842612, 2073903119, 2153824733, 2329799226, 2341967952, 473768936, 3486256934, 2848218304, 2428724257, 3159637305, 2126501230, 765243196, 3425509759, 1131263732, 2515711177, 3855554546, 1023477320, 787209967, 336492935, 2359162223, 1128313353, 2209616384, 389804749, 535230248, 2210531774, 3227122449, 1267072928, 675693308, 1385601874, 1416098547, 4192675028, 2716632450, 4177948782, 13560634, 3703614488, 3901742123, 2270254077, 3759771486, 581228935, 3949774462, 3458012976, 4163726158, 1602955605, 3047124020, 1612897320, 2437308530, 2370536309, 1561087937, 2116794827, 1579558066, 431023695, 689842616, 2342172842, 4203138565, 2160272314, 4192374041, 3675193896, 1455954294, 3940635994, 4025127357, 4027321239, 1155472117, 1928138697, 1875048682, 4087308487, 4291614860, 1175537429, 3503698743, 2187471558, 2673330725, 2702107217, 2763809959, 2274134903, 1077148334, 2166895545, 1831099412, 3296218829, 2076626325, 1104984380, 1764164194, 3056784327, 1988083103, 3849746178, 3460231757, 3983590507, 1641801163, 1321487487, 2277192156, 1700397327, 4163993314, 118570737, 2510013157, 342313019, 328214482, 1456063300, 3771950632, 1226087686, 2343733178, 1108934200, 3650307976, 118441436, 3857631518, 1808729865, 2826187782, 2596972674, 1966611164, 988201436, 3909729734, 2034457184, 3137580128, 437202273, 1431097330, 2630459633, 2423317302, 1422128850, 3011012632, 3611423092, 3531891566, 1592039994, 734168534, 3492902008, 947200226, 1735249159, 3526990689, 1725556774, 1693403463, 3317454666, 2042191731, 3608995702, 497650714, 628421679, 2465885637, 4008542175, 68576338, 1372104957, 1927020046, 3573635655, 3090117252, 1774561696, 3603424898, 55089895, 2060875413, 116850528, 183816573, 478639013, 3736973628, 3606174188, 3086193394, 2548388100, 2591332019, 3032618195, 469584388, 1770142568, 205800329, 174943950, 260521576, 2114953066, 3428041459, 860714084, 1560598053, 2885505481, 3365355923, 2821218095, 814424502, 94258256, 2857874640, 3213633690, 239445181, 1741311155, 70754202, 469749979, 469377271, 634558134, 1314018935, 2663122712, 3425107874, 616125297, 1220520411, 363320242, 1717903421, 2177377494, 2683338356, 210565640, 3061448891, 1561105018, 3639722552, 2586119577, 264509957, 1416442444, 572448512, 3316197518, 4101471127, 1909662580, 3289492851, 702940172, 1747588119, 3288795988, 1441233966, 678854386, 2604723913, 373703246, 2055937039, 1124872113, 1294098600, 4165350921, 347872377, 4149215174, 3215450946, 3307233717, 3600358822, 2659616884, 552889201, 1684681790, 1821948043, 2909781107, 917768879, 2259947602, 2019396153, 3413299181, 603749894, 2467542574, 4017401393, 2519998741, 1106606352, 2283516402, 4262893045, 931507531, 257221572, 1471379658, 4223521274, 2958168654, 1643148068, 537294061, 3213657938, 3835022365, 3594404173, 777970857, 1918635217, 1702205904, 1047564373, 67547546, 3019489110, 483595975, 4130252917, 3081408781, 436773586, 1982914868, 3527757249, 1553562987, 4080227164, 822023069, 1427193014, 2565421648, 3942884687, 586018307, 1138884595, 2613035769, 486310535, 233458001, 106898418, 170926111, 3212999317, 3194995097, 827548055, 1783632131, 1458445783, 4273893842, 4169283956, 3425898311, 1900133873, 2830934989, 3597188167, 60014629, 2917912426, 3137954804, 1361341056, 4180775481, 946784052, 4199341441, 976101959, 1662997785, 1179237245, 372119531, 2815699743, 2114995295, 3901740963, 3080952004, 938243235, 1717858705, 1880470411, 3714648015, 2698621435, 4276694893, 327245390, 2823511048, 1178264505, 2316760826, 1757942990, 1568677829, 1199580238, 3100459677, 1386893348, 1600406349, 3128791813, 874040538, 2965907285, 8663319, 2919597841, 1169807363, 2130724711, 2817929643, 2594603073, 975728895, 3248945863, 1506505714, 8259384, 2395186489, 64139190, 254403781, 3179528072, 3318835559, 872874473, 3221533853, 1278142055, 2865063695, 2096015856, 3893588672, 1650965167, 852689473, 2456343381, 2227877463, 3533995396, 2567915364, 3260019114, 3354960043, 317493973, 4088542285, 603804423, 3133721086, 2455680365, 2501599681, 2371144161, 4224001882, 3900064951, 2295679614, 483545534, 500738921, 259183629, 2958675979, 3886544014, 3382548497, 1341558649, 764676712, 2686742281, 3585367009, 2470017030, 280649561, 504360831, 3177630390, 691028027, 3630869823, 1850039925, 693186712, 2234334464, 3019783104, 1258253876, 2759186239, 2705660533, 1535024585, 16228098, 3597194253, 3856258376, 2530800309, 1756061934, 3703461702, 1458672824, 3009579190, 325542092, 974024523, 937809905, 180338019, 728257472, 1334683442, 1531729599, 4257819380, 3701291761, 2423233504, 3786098144, 776062663, 3861731850, 3717496633, 2918219359, 2369401162, 1963105504, 2673826226, 3238671093, 568083438, 4121947082, 3892853652, 1632686679, 2302193583, 3211408318, 1938993158, 4122064270, 311269184, 2105346675, 1581174365, 2485158976, 2443260070, 1986431168, 1124848188, 1841087451, 2704521996, 1214274421, 3662035084, 2837679678, 4043497550, 552208260, 1644975825, 1950150273, 4027848966, 4079004873, 647675052, 223752470, 637576072, 949880156, 2749078102, 2043391316, 1008133, 253411434, 3799679907, 238227057, 2495985662, 1475105846, 2961884606, 652180469, 1691635637, 1430944868, 15398684, 2278485165, 3795142783, 2981896799, 1330890913, 2239691223, 407470744, 3702570774, 1624292191, 3703366632, 2187395861, 2415878960, 2303069741, 1369122706, 2750340520, 4035673151, 1425244662, 25186311, 123582970, 2490005251, 936607532, 4115073120, 2730391719, 2823090688, 396451377, 2182998280, 1365726601, 4033770954, 3047868289, 2336389408, 688454315, 1299725781, 3304644284, 4238176839, 3914620151, 3029466942, 3172492309, 1190474536, 569450335, 320580314, 4004925139, 2557991799, 1493351038, 949583033, 3275441062, 1311907795, 106222620, 396788468, 3186456628, 517037899, 2177653619, 370023265, 532558109, 3182151426, 954367771, 2865591818, 600183719, 2521622949, 3079560626, 1906789399, 1612708432, 1801660151, 3565921772, 2688352000, 1101243899, 888006794, 2233649225, 2671500356, 1504445832, 1199168343, 2043022343, 1250919220, 1374956710, 1107550604, 957179006, 3319703903, 4110453611, 3311143947, 2774029776, 1456730624, 1014119593, 3012545941, 1650066434, 3431589287, 3624715486, 1072097915, 3568695028, 478299405, 362822053, 2632030958, 955747917, 2974153651, 2880247593, 2837857407, 1533402093, 1550331006, 3833005459, 111580345, 1694562098, 2731241196, 2659074758, 1347615125, 3711588514, 1514710939, 3788474419, 3668780501, 3266213391, 4081085519, 1196081228, 1049947080, 1820720234, 3100382458, 2198468097, 3708538645, 1035729054, 1784655621, 507574130, 2908640623, 3615200865, 1223546227, 3675568182, 1661330896, 1399689373, 1323389692, 2981922901, 4156332999, 1902241850, 1428680890, 3049572611, 4253261231, 2148214199, 1998921071, 3899443086, 1478235253, 3791927172, 1483896530, 3565485437, 915921912, 2258155251, 3426051958, 3307670857, 3029363090, 3673788309, 4082838999, 624603732, 573907442, 3116664857, 3586999255, 557493850, 1739716128, 2397076308, 2312498391, 767640384, 2119706819, 2637314051, 1070866648, 664107404, 616236779, 3020748367, 4122128780, 2009706384, 3245363034, 429196441, 4195520565, 4209198410, 2158211364, 3659713923, 3985561806, 1747634790, 4115935838, 2827667115, 3073689925, 1621229363, 2774950774, 2538390550, 3506768465, 718261358, 564823729, 380006788, 897186389, 3414352487, 1032216622, 1469922191, 2196317056, 2239269473, 3654751282, 613015420, 4098167098, 1281134924, 849099531, 2523299715, 3904840545, 1997547696, 1158713208, 1289444182, 757815917, 899581875, 3622748533, 3063686656, 2979790776, 1553609204, 355408616, 3897614956, 3680334470, 25191644, 355655308, 111682127, 4053312775, 2921335050, 2200671456, 472639194, 1374183459, 2738441274, 1596829615, 959522853, 1993763998, 1832301144, 2263515976, 993190648, 4045308024, 2213735364, 4061773476, 2596920312, 1929252967, 3935609312, 982934883, 3154772065, 4254233108, 1244999206, 765237459, 2528318166, 1563389556, 2293797399, 3495759008, 48504250, 3182637462, 3138309477, 2147232621, 4810076, 3999234780, 2279064264, 2264522982, 3079929466, 1524222187, 1598294545, 2049273389, 2729549735, 2116985451, 2637892533, 1094214870, 2711414546, 418295062, 98357556, 296649589, 2636445209, 4030461397, 3073508440, 4062358649, 1293566861, 1534697481, 1343281639, 3078259374, 386875427, 1145986442, 1790533181, 2987076845, 237202537, 2194958623, 935119723, 1921262864, 943957815, 2336181341, 2723699978, 1638860845, 2630349960, 431757538, 4152375793, 3473513084, 2603606861, 4176464622, 3978369596, 981482293, 929741839, 2111696471, 571254437, 1419237733, 901791748, 3340393111, 221970895, 2605197016, 22565479, 1000841034, 2192399670, 1207300847, 356824298, 3009617459, 2651652098, 2420275852, 1631602976, 575809994, 2928806259, 2831092106, 2629452482, 2842897182, 1909556662, 2496151886, 3385330607, 957152776, 2804092840, 3551246686, 2730894896, 2027253611, 2531182020, 2258110944, 1391264743, 3902230517, 3835546712, 3424753892, 1147410244, 3448482025, 319341118, 1798380053, 2742193162, 2106010955, 3267048655, 3886107336, 3334600393, 3772435523, 3985863328, 2950255062, 1012493134, 3954831363, 325018235, 2523597002, 2454925521, 2861802043, 4209313262, 3868234463, 1685691511, 2786322255, 4244960817, 1991229419, 4239301712, 576152977, 1652411241, 1589394460, 521549473, 266587858, 961791319, 1146831103, 3469211532, 3501779101, 2312218475, 2321025269, 1346459216, 472196028, 3771324053, 1495430908, 463405457, 1940232183, 3937148918, 1156878514, 2831556660, 1644483662, 1787817713, 2339616130, 3815974485, 2298018558, 71674109, 2675299410, 960845405, 3569711116, 1673611570, 1769369631, 1437416980, 4174063039, 2062712084, 2133844948, 196794643, 1935768058, 1831573341, 1418980930, 3294487604, 3544538744, 2334730191, 3988003806, 2274350901, 2023027498, 3447859831, 1671781771, 4023665101, 1455029189, 2419433622, 2943475311, 4198568768, 1395089836, 1092520718, 2430238564, 437551709, 4097009390, 3375079636, 4154198223, 92070792, 974607811, 3873908092, 3374473679, 638725898, 1249915990, 1085664087, 3927733894, 1217984426, 1825247311, 2107887775, 170602951, 1075337232, 1842870533, 3647067870, 2444592832, 3013106942, 1161476947, 3743427689, 1263482478, 69206560, 833594813, 3842989721, 337909675, 3392484922, 370017251, 27594915, 2126835633, 1736323108, 1893331695, 1468455680, 1075562062, 455344215, 969605531, 294398875, 883453327, 3994410499, 1964955910, 1983678849, 556499140, 2199399388, 1506753515, 2562511167, 573514453, 1452183180, 3758124304, 2276736219, 3962356320, 160602272, 2732947819, 1312555719, 808517807, 1646633687, 4057383018, 1177836167, 2724613618, 724351202, 3082498407, 3292565482, 2024078169, 2339554384, 3963173875, 2223760730, 2562066565, 2193608401, 1812209945, 1665831972, 1039920028, 3410644888, 3314911306, 2847575459, 2005962667, 2392982038, 2769384144, 1673231309, 2605033025, 3097232789, 525491643, 1088675733, 389231889, 4053722369, 1394160319, 920345783, 1695188025, 1313259843, 2855284945, 1128781302, 1711293636, 2436253183, 2702553100, 2342544037, 2382554808, 1645824427, 700888148, 3820471891, 2062002896, 1600256482, 3523617235, 3825142862, 4016136295, 3838255962, 2953276340, 394106186, 956179026, 3512260850, 3001113638, 1645204518, 555542490, 409962126, 479780262, 4202384502, 549252742, 1340551826, 190095025, 2842856010, 446626748, 2565781573, 2172050474, 85422525, 151000070, 2413238086, 224534468, 4102988065, 3524737259, 784974768, 3778660388, 2573449273, 956921977, 1416256526, 3821996527, 1297167173, 2183926071, 2745200336, 1745460864, 399929970, 3271657494, 1058524185, 3138265217, 3822962039, 796872545, 555781465, 3355863387, 4265560398, 2445094472, 546611744, 958064176, 2278895404, 2100057835, 789578969, 387055963, 1153298400, 4065547056, 3688020091, 783181103, 1789734962, 1466117990, 1740574947, 1632230912, 4155788342, 1714025679, 3862124914, 2247239755, 3047057899, 3610673443, 1450313039, 3533121399, 1564221183, 4056883174, 319992191, 598075724, 2438292429, 901314271, 2157273664, 435275402, 1774735757, 177332560, 3010394026, 3827445200, 2002098740, 1897812156, 454287770, 2829500771, 3286056227, 1498747083, 3402858410, 58581019, 1048766033, 1640106396, 3774636176, 1228719792, 1768725616, 3094025701, 3705595233, 2943515149, ], &[ 3303507517, 1737467916, 767592771, 4237693101, 2944498355, 2305367062, 2912464955, 2039632714, 957753136, 3932250327, 2923226395, 758588986, 3276864736, 4129542782, 3701423701, 1834120826, 1304646722, 2700953412, 4016654202, 1446197632, 4233056281, 2795834408, 2358334260, 4031834794, 1761430989, 1322974963, 1041373666, 2212100552, 2426361770, 4261631544, 3079923997, 556209919, 2565829294, 1158111010, 1485991528, 4015229549, 3673606504, 611864921, 976174193, 806940030, 2732222596, 2259057471, 2443961478, 4098098138, 644289655, 180553484, 4059537703, 708282117, 1433746242, 1823452813, 685407883, 2203888447, 3826783627, 2594937784, 3968973728, 3226845414, 2669006681, 531830322, 453908823, 3201286311, 919570600, 1858088761, 407253743, 1432230279, 3303340419, 3210731060, 1388706247, 551779110, 351497524, 3064709178, 2129368300, 1872141157, 2752241851, 2688864462, 597028566, 3593773250, 2480760169, 1493938468, 320489468, 1206910552, 2899495800, 1583265563, 2935858872, 126264340, 2083066625, 2827628121, 3109648374, 3916360359, 389087236, 3766699281, 1333824469, 1218761052, 2129210405, 2527568435, 3858191140, 3930233522, 1058437374, 1654914995, 911091073, 1037669921, 2949223555, 2606346852, 1104967551, 701746540, 416874025, 683350868, 335950780, 486101025, 3696781531, 434131711, 3081485031, 4277564240, 2555479895, 3850726160, 3227325468, 553377665, 199290481, 3982285635, 3468419008, 3392035752, 1966268427, 1873702317, 2940911086, 2914228436, 1708633307, 662031149, 621794577, 2395698305, 2735240556, 1414089965, 3294650435, 479604329, 2426263958, 847381928, 873722272, 1110653081, 1951740102, 2731402038, 2556525098, 2219924857, 1852070957, 2449841178, 1210250294, 3699155577, 1784858631, 243884741, 2161178521, 2410975312, 2681491929, 437235103, 1281548845, 3357384194, 549196434, 4067561207, 3450283139, 3652169421, 1874377644, 169053482, 1420061127, 395406675, 3332510954, 3856194671, 3006496664, 809601906, 1922764991, 3111985626, 3390014784, 3048045015, 2051558581, 2703813358, 3808996437, 3570075083, 3505603444, 35527898, 3996784836, 4168425592, 1946706469, 856358712, 3661547641, 141395264, 3094553658, 629697921, 3847603586, 2560897876, 2555855191, 1405066228, 896493515, 3694348082, 3454533550, 885932680, 3723805569, 493727984, 2574262444, 610088096, 503058120, 2172357146, 2481205990, 3987005657, 3085722243, 2250687621, 1050336745, 3740028373, 3019114451, 1642616645, 1137174523, 354355265, 1455093279, 304460919, 4116447569, 2981853747, 856638318, 3109624356, 3591169837, 4193437247, 443242328, 1666463852, 2097829509, 2208974333, 1422720757, 3349658507, 2452053895, 2569932614, 47797786, 3752698672, 2215739699, 1652083417, 3346170449, 585897335, 2075209213, 3518121114, 378885805, 3744168278, 3903962084, 1064225611, 4197819881, 1867701541, 1058875078, 1828480385, 35105056, 2154079979, 4006209278, 3153027209, 3695601551, 3461064991, 3223410438, 3090214664, 4250727661, 167290560, 3088602589, 1392761792, 4016528315, 2899219207, 2196701677, 1154503712, 810711706, 3932982426, 2420112400, 3293415319, 4134821524, 3493789883, 3329390364, 3047733519, 1049261264, 3282299496, 482643201, 1333502492, 3412458538, 3505648168, 1030433939, 3681403988, 4159258448, 821956, 3965405477, 3688327, 2218271368, 3431171763, 2674850379, 2269778883, 596405244, 2839693344, 4146102065, 3215467606, 1891293404, 973749441, 3640452446, 2709562759, 459831821, 460230179, 2910252183, 2014822547, 3590552255, 2390315678, 1031487459, 1213313670, 2511201602, 1511763753, 3969704570, 2909506049, 1760818720, 1110188569, 154546279, 577049207, 1753565754, 4085487615, 3287577161, 2028144074, 4111187020, 3004119870, 900037962, 2806754372, 748875551, 2620104615, 2513455401, 1585914851, 239727281, 2605810930, 416537433, 2166996582, 1965459949, 758058785, 1510362220, 1824837142, 3097689711, 3896639991, 4187903962, 372233538, 4010166025, 1907205494, 3036010338, 1576810188, 3371537329, 2895423119, 3461187657, 1440946377, 2483629064, 2639054882, 2819542476, 1677376583, 3628809647, 1237686175, 3985351720, 2642412817, 4013664855, 2065613802, 817459407, 2876445270, 3076582045, 1810603735, 1174549530, 4260651012, 1973700727, 2194803557, 2360115398, 3069422632, 1295376632, 1002159587, 4162264900, 963230566, 193817342, 2402613170, 275479630, 116160077, 2599851335, 159870465, 211768251, 4017718175, 931115106, 1004170356, 2730898374, 932870994, 1082826978, 2961790318, 3424432922, 1300198410, 2280596007, 2164752687, 2135660458, 2665413409, 378731924, 3146959946, 1447131084, 624620351, 1626838440, 3569823375, 787344599, 398683074, 2909969062, 1166082222, 2222839820, 3445152909, 241015893, 3204685501, 1212401564, 4123206390, 1295604587, 1098987770, 3308585450, 3613934791, 1755566651, 3657857779, 1263036827, 3678216851, 2402921074, 3493820436, 1704692066, 403162744, 3170124922, 3563160884, 3160828389, 464965432, 1118230114, 988354534, 356341207, 3849468154, 686849000, 1566884214, 240572604, 3063337879, 731356349, 820769259, 941504045, 2706839108, 2723874282, 278246299, 3880298064, 4262421502, 256437639, 1773319540, 153110521, 565549233, 1853553593, 4289762574, 4098151149, 3144524222, 4144088665, 2052608329, 1464290562, 2110534105, 1113619720, 2516886130, 2842359662, 436774705, 2771156018, 1683247173, 3108637805, 2436817839, 4127310701, 3910938906, 2062961202, 3341755081, 3583281049, 3534420977, 996954658, 4115691732, 1529857101, 519089315, 1800475325, 2866891326, 3674269922, 4258687645, 1222536664, 119098982, 3470430550, 2133110377, 10231145, 2797637322, 1573837132, 2948970055, 44978960, 4025694418, 3346973726, 1067376893, 2502195176, 14223176, 2185770650, 2887537518, 15571252, 2033910005, 63833522, 787872402, 3088869854, 940048320, 409417410, 1084110155, 601749701, 914916762, 524011526, 846030561, 4258519014, 2487948410, 3192173244, 3091400971, 3644666631, 532480229, 2780924927, 604543953, 756270658, 2063413786, 61217573, 780610452, 955642466, 737073209, 97297839, 4258953485, 2857641388, 304710700, 3918409840, 2194881876, 196515060, 1845737739, 80004705, 3864082477, 2417895713, 1575272517, 2071122658, 4181848470, 699244129, 2719978593, 3969766361, 3331919022, 1806356115, 1674881762, 3140317527, 1020055538, 928717808, 3657371453, 3576271656, 1661098282, 2787948393, 1612552028, 3154905497, 1703392561, 843717976, 1621287936, 964546377, 3549430129, 712295080, 2234282678, 4200849568, 2117828027, 1392560869, 1138816605, 1628721368, 1719186629, 499638295, 2276446667, 2040220810, 4170119435, 3098091505, 3464708059, 2446105454, 823802794, 561105361, 2956734110, 85242489, 3594780155, 577528063, 3814286772, 3517308917, 1542560009, 903130712, 3610028360, 1094281534, 428913785, 2017125716, 4147179238, 2416543280, 2299224901, 3094092893, 690981050, 1074080982, 3806304984, 42870724, 661112767, 951312097, 993899402, 1421924279, 3477956487, 2620630825, 421567847, 1135313615, 1871766543, 2089515143, 3125551624, 2893389248, 1822212994, 608096287, 1209599323, 1729308570, 3183687973, 4188910249, 4113106401, 3467805891, 421479009, 2067824783, 1123275745, 3372672466, 1299403729, 2597804990, 4109910992, 3549093152, 1334873992, 2837764304, 217816190, 2798635274, 1928429025, 3532349620, 1432073554, 894604604, 1320754530, 2946314029, 1689416007, 4088210274, 3660222258, 1778465861, 2089083512, 2489444834, 3020220872, 2955906475, 530018361, 3604331239, 266271770, 1093367251, 2425988385, 756441106, 3810449360, 166826417, 4128383674, 2193768558, 1695641441, 4163952927, 3844926416, 3179839754, 1485072550, 1035240603, 2716609076, 4025246794, 1340294165, 3056622704, 1486949742, 582340579, 1925519282, 1050735048, 33509855, 2342941070, 2747830341, 1845018013, 2064583117, 350099328, 937043595, 1618308339, 1824995534, 1246976548, 2566004874, 3546659674, 659106533, 2844260619, 3911232451, 1416070938, 2388309597, 316855261, 1695213219, 856692567, 50305942, 3668671854, 155369786, 2137812662, 4211140628, 1042632363, 287846104, 2375035513, 1607313275, 4018768752, 2592097421, 741212831, 2408601799, 903321756, 3509061462, 3142569462, 4087971745, 3019038954, 1803053183, 2257944916, 1390909767, 2836222866, 371214087, 3682888114, 2241578583, 3605759723, 963603499, 1055335598, 3601870947, 4058606066, 377849537, 1843635487, 1835087927, 3393215451, 17492256, 3372299656, 3413139881, 4264793180, 1928965951, 4021643980, 2269905143, 545062409, 1389035345, 948398528, 271536224, 3504014149, 567335901, 3413496753, 3071719597, 1445310729, 1770797777, 1267315070, 2207614182, 3493277503, 4282532855, 2107955232, 133857837, 2087779634, 4056521208, 818046024, 1890865855, 2126495054, 697548852, 3485729598, 1695030614, 893769923, 184087075, 1500071319, 2080614980, 2480313210, 3450043314, 1064086870, 2786617720, 4034347698, 681412032, 2428347460, 3253322495, 3604525345, 1428905795, 4035094721, 2101041634, 4183013229, 1705836765, 1682316444, 1879660152, 656187483, 3706455747, 2213541704, 669373128, 1529444811, 2814804687, 908625065, 2227416512, 2001006578, 607169088, 3393837756, 2682839326, 1093822620, 2249228026, 741792013, 3650948262, 2073718838, 2268511569, 1643477360, 2804865813, 3375407338, 1318291972, 1414889752, 2869309697, 1958772002, 4162044589, 344252635, 3226572534, 3577208303, 1959437424, 899330854, 3892405212, 1622822546, 1644013310, 1300136815, 2640337368, 2069864152, 1596350405, 3843745327, 1256171531, 870418775, 2393395126, 3876818506, 3944780828, 4008626102, 3127368256, 3426341771, 2086853545, 3827677693, 313614572, 3669266463, 4080954414, 1707330242, 2963410257, 3437453487, 2794195219, 3099230302, 726769739, 2044701195, 1129715603, 1793697677, 2760059361, 2331714255, 2589913453, 4127324884, 2881798920, 3400611219, 2052671160, 3546649304, 2164589537, 2812204213, 3337755588, 3983060148, 1899178107, 776922408, 4182115872, 444866608, 1399651129, 3474508713, 2842510671, 3402478835, 1423128980, 4178402672, 3172508430, 804756202, 1597189857, 1958174560, 3392832851, 1197650976, 3772223860, 2054821761, 4011804750, 474742851, 1329523696, 4032274332, 2454461926, 638843849, 2072449514, 764758175, 3934751812, 4075369298, 3142015673, 3394043201, 1535751977, 1846529809, 959593533, 2235839818, 2814770736, 247085892, 2629667206, 2957898589, 3933947035, 1295728615, 3586572901, 4038985747, 1129159296, 1855469111, 1271614337, 1507173551, 332723961, 1156816569, 1294330789, 4122256011, 299955786, 3523281781, 2491532525, 1960595579, 1730519156, 499071642, 1575886120, 2620965123, 3289148909, 1154711404, 1451719777, 2628469322, 1901725555, 823453464, 3761287780, 2261972333, 3596389504, 3137670793, 82630428, 3159699693, 837229231, 344117878, 2381467908, 726572177, 304723155, 3208229621, 1458659872, 1794857529, 3755652400, 2395146944, 4102358516, 3277747506, 1818040372, 3936695066, 2397713693, 1708618418, 1728140834, 1261714327, 1581655946, 2071676586, 1202217464, 1344775033, 4250653297, 2492875948, 1126916876, 2945410447, 2941087697, 2560380036, 2546735705, 3178023445, 626886956, 484882355, 3357302024, 4057372957, 2081549406, 3896175417, 2686162101, 1986295486, 1621237422, 3568031348, 4006200466, 1442461868, 3844879388, 3501884160, 4038570281, 4208037469, 183139977, 999125999, 530710734, 2507567639, 3058017326, 4201561530, 2864542147, 2696523106, 2969212130, 2678586192, 844065498, 2655259915, 1258788749, 2827607705, 2237733350, 3783297719, 2313239370, 950226942, 1280595939, 1196906959, 1606546303, 1844760556, 228764146, 744772053, 1358152164, 1193261600, 2565492365, 1225744635, 4233301881, 2253145769, 1602119788, 1365069640, 52910185, 2636770690, 3298764603, 1878144899, 4262332977, 3649154366, 3690806265, 231714913, 2913226838, 1554707381, 2963669507, 2049539773, 1775985343, 3627719803, 433359314, 3418531436, 793315695, 913341557, 2380241821, 348855994, 234181973, 3722537381, 3525843118, 1275331720, 2537849571, 2827984585, 1565515383, 642373946, 1576289295, 2688247425, 3614474901, 1917731824, 2884918146, 1646964474, 2383030418, 2488801475, 1560749769, 139516483, 1142139281, 3459274279, 2863576242, 2828722138, 717484310, 1564480623, 3172598637, 2368201724, 2247871922, 419758505, 3015961787, 3098012702, 1041261606, 984280115, 2438811327, 2578749598, 978582878, 968817491, 2965070269, 2780764697, 792560930, 4229722212, 4114038484, 817420493, 3041070967, 3191549455, 56820468, 186749905, 784610516, 1729092057, 1935036496, 3745217089, 631003694, 3845500664, 1776171936, 2105858365, 1027041956, 1638191578, 3198133424, 3040033996, 3224025446, 2046726489, 3326226799, 4261577923, 778164631, 4272446112, 967648331, 4223690387, 394608816, 2849103815, 1132525868, 4239388057, 3710951992, 582192848, 1372476599, 1228786127, 444221576, 1576598378, 4000181362, 2210214319, 3226877228, 3921989392, 3841275639, 1917309689, 2860911813, 4290305048, 1796377659, 3485206273, 2654605026, 1122524178, 3609458012, 1733743381, 2869375618, 3606400920, 2485406505, 617720548, 497728528, 3826929977, 788489471, 1188098828, 3383811959, 836335995, 104474735, 994749139, 523424077, 1334471135, 3246261832, 579729621, 539626281, 1917656426, 3649706685, 407844197, 3736652416, 449727051, 2451735689, 854611863, 3476911840, 973228334, 374181454, 174850286, 4178627179, 3564929895, 1321454916, 3996342532, 3051609408, 3899526499, 1406247157, 803997219, 3125646376, 1606457001, 1405170718, 208843195, 1067743855, 2152262286, 3179865614, 3639249079, 3035981075, 2732174588, 351444382, 2864637808, 1006363319, 3244329910, 405573136, 562447830, 2108083668, 396995391, 326716392, 3263476213, 46276814, 1326176087, 1851003306, 2516298844, 3058805571, 2774935984, 1856888260, 2568955433, 3218178509, 649282170, 2256866690, 3674417033, 1111304414, 2088271619, 3238685708, 1574098232, 4183705418, 1987306144, 1189150097, 1378845891, 3654818831, 386424237, 515382663, 1197128686, 2542968522, 3887585643, 73911371, 4058793301, 1696639371, 2561358933, 2221990016, 727444672, 1973624906, 3853875864, 174963610, 2695490643, 1066818493, 150873363, 3952837259, 2936691596, 3233597847, 2506388918, 3711816965, 2536068963, 2311484662, 1093886392, 2704991380, 4059725080, 1625573608, 2471671232, 1763939042, 2734410153, 4028854994, 2952269163, 1527756733, 3902245417, 803045644, 1140158788, 3552349570, 235707516, 415130691, 1269910803, 2620435440, 2226985943, 534205480, 2823709851, 4167053910, 3680035619, 2757219390, 253917945, 3675657485, 761900957, 921345945, 3266224194, 3148826681, 1686290818, 1647986984, 495687313, 977442969, 519576012, 2062617190, 2755583385, 2380042959, 3142598908, 2437799893, 2426856697, 3052553836, 1753471289, 3915929071, 181022453, 2017995427, 2796049960, 1358824868, 2906668276, 3538494963, 1500035161, 65877569, 3786619137, 2956889923, 2470576554, 1511345314, 2266296788, 2066914712, 94664780, 4203735289, 4281330982, 2763817600, 2319245226, 944042376, 3922820514, 3935434053, 3397738753, 243208651, 4248331561, 1105500069, 2967638830, 1029380469, 1099175028, 3684769174, 970577857, 824995756, 2937133428, 1925916100, 859262581, 1913695947, 99275310, 848678738, 1204388593, 2545149594, 4025381218, 2655396831, 4274996806, 785850435, 2813888154, 2491029176, 729818073, 3512685438, 2347032890, 236189106, 1548333126, 4226775910, 3531794275, 2605168049, 2258187662, 3684015953, 898250663, 3771349383, 4093644918, 1624210803, 4281075128, 3093735055, 1291164275, 4037665805, 400599276, 1273249058, 2375386975, 3439029906, 3333739393, 21660248, 1230861454, 4062325366, 4236459577, 114385419, 3486611078, 2042004563, 1720831514, 2860273565, 1626594640, 1874700160, 2999308559, 3363764551, 3500763507, 2853826537, 2479469741, 1210500932, 2562869107, 880924171, 3384557003, 4168144997, 1148570091, 3116312623, 3172212634, 3567662417, 2642768241, 2015203625, 322037435, 4195745331, 482368754, 3667466677, 4219023014, 1434757526, 2822946590, 1936561533, 2947351890, 76179171, 2209227842, 2435463017, 276550749, 3368341828, 4262885294, 527655253, 3745940749, 947007746, 3600866533, 4084045218, 3905637169, 702492342, 3383700150, 1661174941, 1763804378, 961484162, 439776914, 257725152, 2840617852, 2635835773, 2403444459, 2908195944, 2902712886, 3595015469, 1460138072, 457118198, 2120525120, 2083051232, 2885301328, 3622650790, 400659000, 184135173, 1137972313, 759714739, 1306898817, 2898422672, 1499186793, 2809562653, 1117081917, 3344337520, 1802186651, 3627008548, 3860814929, 3728070085, 2991502661, 1782981707, 2477289364, 3565582296, 4061650811, 1579851913, 3689665892, 75184626, 2690145835, 1228774440, 781089767, 3218967841, 4064814684, 3163493596, 2809482905, 208507155, 3756966102, 1779229104, 3680138867, 1751377038, 2598643358, 741546321, 1303997493, 1306096237, 3769872893, 3911517876, 1315212882, 2839259600, 1408676647, 4129419272, 26525771, 1163846026, 4159566079, 3195690749, 3064298320, 2468791883, 2538731242, 3488224592, 840135976, 493847318, 3680037513, 4066665187, 1669269859, 29113490, 3642824198, 2180773838, 3705727774, 3741660915, 2916119284, 4126524803, 2531904672, 3689890848, 3760318626, 2463539219, 2074029166, 3481349310, 834750020, 3864728871, 2085171104, 1481087706, 385893521, 1753696318, 262108731, 3110985970, 3185711468, 3592333917, 4001141364, 1777140007, 1668227551, 3014458968, 3982753649, 216294504, 3414213843, 553573571, 4237875195, 1780838673, 2208517053, 1405463181, 3074428565, 443193338, 3142617921, 426182091, 3549357900, 3829054100, 3730720095, 3556916232, 3050819311, 395210557, 3290215021, 1925989323, 1278915506, 2074504769, 788246561, 4036378728, 2546297900, 3576484297, 881981653, 3844099771, 1100647287, 3275806264, 1545433580, 2973403693, 2010768484, 58589600, 2055927634, 900275269, 1772160551, 3642278816, 759464205, 3337186197, 2884437454, 1815406779, 1826092146, 1703588272, 91001350, 785570260, 4114370752, 2690000574, 4090829518, 3792473390, 2886081610, 712723937, 3835538037, 4094897515, 2015334309, 3367660714, 1368192432, 1580207087, 2030632060, 1542088491, 1685523972, 4182209840, 1673405540, 4001729368, 595538569, 1903475145, 3297819296, 946281001, 1202436672, 4111768072, 412627407, 1029652681, 2792765909, 2040861363, 2987136935, 22966596, 3410302892, 3001821942, 1981338581, 3480779498, 1173591145, 4071007940, 1927554934, 1430729301, 2103178216, 3055596527, 3263660591, 4266315882, 3008856523, 1661503737, 2281231147, 4261532350, 2177588068, 1785850443, 62425813, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_invert_fail_1() { limbs_modular_invert(&mut [10; 3], &[], &mut [10; 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_invert_fail_2() { let ds = &[1, 2, 3]; let mut scratch = vec![0; limbs_modular_invert_scratch_len(ds.len())]; limbs_modular_invert(&mut [10; 2], ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_invert_fail_3() { let ds = &[4, 5]; let mut scratch = vec![0; limbs_modular_invert_scratch_len(ds.len())]; limbs_modular_invert(&mut [10; 3], ds, &mut scratch); } fn verify_limbs_modular_div_mod(ns: &[Limb], ds: &[Limb], borrow: bool, qs: &[Limb], rs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let q = Natural::from_limbs_asc(qs); let r = Natural::from_limbs_asc(rs); let n_len = ns.len(); let d_len = ds.len(); let q_len = n_len - d_len; let qd = q * d; assert_eq!(n < qd, borrow); assert!(qd.eq_mod_power_of_2(&n, limb_to_bit_count(q_len))); let expected_r = (Integer::from(n) - Integer::from(qd)) .mod_power_of_2(limb_to_bit_count(n_len)) >> limb_to_bit_count(q_len); assert_eq!(expected_r, r); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_div_mod_schoolbook() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], borrow, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let inverse = limbs_modular_invert_limb(ds[0]).wrapping_neg(); assert_eq!( limbs_modular_div_mod_schoolbook(&mut qs, &mut ns, ds, inverse), borrow ); let q_len = ns.len() - ds.len(); assert_eq!(&qs[..q_len], qs_out); assert_eq!(&ns[q_len..], ns_out); verify_limbs_modular_div_mod(ns_in, ds, borrow, qs_out, ns_out); }; // - lowest_q && limbs_slice_add_limb_in_place(&mut qs[q_diff..], 1) test(&[10; 3], &[0, 0, 0], &[1, 2], false, &[0], &[0, 0]); // - !(lowest_q && limbs_slice_add_limb_in_place(&mut qs[q_diff..], 1)) test(&[10; 3], &[1, 2, 3], &[1, 2], false, &[1], &[0, 3]); test( &[10; 3], &[1, 2, 3], &[5, 6], true, &[3435973837], &[858993456, u32::MAX - 1], ); test(&[10; 3], &[1, 2, 3, 4], &[1, 2, 3], false, &[1], &[0, 0, 4]); test( &[10; 3], &[1, 2, 3, 4], &[1, u32::MAX, 3], false, &[1], &[3, u32::MAX, 3], ); test(&[10; 3], &[0, 1], &[1], false, &[0], &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_schoolbook_fail_1() { limbs_modular_div_mod_schoolbook(&mut [10; 3], &mut [1, 2, 3], &[], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_schoolbook_fail_2() { let ds = &[1, 2, 3]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_schoolbook_fail_3() { let ds = &[1, 2]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(&mut [], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_schoolbook_fail_4() { let ds = &[4, 5]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_schoolbook(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_div_mod_divide_and_conquer() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], borrow, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let inverse = limbs_modular_invert_limb(ds[0]).wrapping_neg(); assert_eq!( limbs_modular_div_mod_divide_and_conquer(&mut qs, &mut ns, ds, inverse), borrow ); let q_len = ns.len() - ds.len(); assert_eq!(&qs[..q_len], qs_out); assert_eq!(&ns[q_len..], ns_out); verify_limbs_modular_div_mod(ns_in, ds, borrow, qs_out, ns_out); }; // - q_len <= d_len // - q_len < DC_BDIV_QR_THRESHOLD // - q_len != d_len test(&[10; 3], &[0, 0, 0], &[1, 2], false, &[0], &[0, 0]); test(&[10; 3], &[1, 2, 3], &[1, 2], false, &[1], &[0, 3]); test( &[10; 3], &[1, 2, 3], &[5, 6], true, &[3435973837], &[858993456, u32::MAX - 1], ); test(&[10; 3], &[1, 2, 3, 4], &[1, 2, 3], false, &[1], &[0, 0, 4]); test( &[10; 3], &[1, 2, 3, 4], &[1, u32::MAX, 3], false, &[1], &[3, u32::MAX, 3], ); // - q_len == d_len test(&[10; 4], &[0; 4], &[1, 0], false, &[0, 0], &[0, 0]); // - q_len > d_len // - q_len_mod_d_len < DC_BDIV_QR_THRESHOLD // - q_len_mod_d_len != d_len // - lo < DC_BDIV_QR_THRESHOLD in limbs_modular_div_mod_divide_and_conquer_helper // - hi < DC_BDIV_QR_THRESHOLD in limbs_modular_div_mod_divide_and_conquer_helper test(&[10; 5], &[0; 5], &[1, 0], false, &[0, 0, 0], &[0, 0]); test( &[10; 4], &[1, 2, 3, 4], &[5, 6], true, &[3435973837, 3607772528], &[4123168602, u32::MAX - 1], ); test( &[10; 5], &[1, 2, 3, 4, 5], &[7, 8, 9], false, &[3067833783, 175304787], &[1051828726, 2717224210, 4], ); // - q_len_mod_d_len == d_len test( &[10; 6], &[1, 2, 3, 4, 5, 6], &[7, 8], false, &[3067833783, 175304787, 3481052211, 2770888938], &[3602692266, 0], ); // - q_len >= DC_BDIV_QR_THRESHOLD test( &[10; 111], &[ 238690007, 851362023, 2059930942, 863267985, 3076614342, 3047275605, 1421974480, 393459707, 388753961, 1307811244, 1724185886, 1342073382, 3451829757, 511726014, 460409053, 863948559, 755242682, 1610976003, 1095233439, 3983048866, 3486643678, 1487854845, 1830823553, 2167088595, 2000609352, 3778875209, 1877274219, 3295032048, 1477159538, 2048839778, 1451455912, 2109980052, 1750913495, 391343357, 3276142698, 2641970441, 1571798863, 2401599044, 1467594428, 2128234517, 3438746006, 227485655, 15222216, 256928874, 3095411638, 111550405, 2230139158, 531435393, 1299420097, 783687022, 3432104224, 1656185186, 3410451479, 1448536986, 1411134389, 3874476101, 2765514254, 2128294132, 3954579563, 2329369626, 3269515791, 3855344744, 1503334643, 1671855141, 3162383277, 1731111055, 3777334519, 1174367318, 1945392580, 966689109, 97441364, 1465255424, 1616147497, 1637231485, 1811763876, 2884209513, 3019238075, 1328651869, 840247524, 344122022, 795760234, 289967503, 616630287, 675829910, 2847875873, 2811380606, 2236228680, 4067593481, 2980091801, 2832971103, 2491091113, 1521816576, 4075571575, 2543360203, 935927249, 573194417, 1822073845, 1839465906, 3275095514, ], &[ 2515301847, 3904775757, 133728302, 3903482605, 3523183307, 1531057916, 1011111105, 1204888196, 587552558, 2259844136, 2514432920, 3885615695, 1529240459, 2527102686, 1527502935, 3607833032, 3108651811, 1015333242, 2650209133, 499583440, 2106087248, 3218570602, 187468843, 2524810763, 3875472062, 3825849708, 2963555251, 2365237686, 2035410556, 3853326592, 2366649615, 757846500, 2808712542, 1010450631, 2537107077, 415304475, 2322781433, 1747200466, 3029815769, 2722060855, 3586580760, 2610036947, 2383069225, 1479189021, 3488202013, 3088351671, 2313154907, 1103886425, 3716175621, 1172908513, ], false, &[ 3119021825, 2664508330, 2031628331, 478764351, 1877838675, 14612131, 652799697, 1178144318, 581220955, 1647659598, 1352407033, 2397453730, 3102518439, 248362411, 760583238, 3183702428, 3503543471, 1633363102, 700510731, 2278494661, 3883161292, 2875693392, 778768718, 1830608772, 4092108024, 1084731936, 2636788137, 1618403943, 2120905188, 1304331644, 3129515489, 1701146314, 2248764147, 4096904357, 4179132986, 1285739406, 4084818677, 3908907080, 2892808133, 3130632865, 1541722253, 754313201, 49163159, 4048683373, 1840022468, 3666703478, 149207896, 1807686489, 529174445, ], &[ 222246482, 233545700, 3332794578, 1998197261, 3881642604, 2334420680, 457729581, 1028684141, 1820939861, 393050552, 3364087427, 980919077, 215964517, 2941392816, 735903426, 707494399, 1663858662, 1254976633, 2324830169, 279707711, 2388586745, 1736265304, 1292267389, 1204103850, 1444415893, 646068967, 361893912, 1168453387, 4162569836, 37496928, 2388108126, 4045054107, 479165313, 2859008180, 3729669518, 790583185, 1990610890, 653432721, 4260517455, 1533264118, 4071210056, 1925491571, 2468006372, 1418208775, 3998441757, 2911027604, 1743255069, 4051022203, 3853317804, 3130583770, ], ); // - q_len_mod_d_len >= DC_BDIV_QR_THRESHOLD test( &[10; 172], &[ 119338358, 2430782482, 2540297421, 188973918, 3420087589, 1543598052, 1550450700, 3792047461, 889269407, 501191530, 2576798720, 2543454220, 3210031718, 485123386, 106926418, 550954803, 939577053, 4245574922, 3198319089, 3116005666, 2750993558, 1870348975, 1975807411, 1781898658, 487257459, 1417798881, 2833805593, 3259853663, 1497754962, 686849710, 2609757048, 3718757183, 57671149, 3248634542, 3521889134, 4157073590, 177642810, 2320627206, 3417728001, 301744109, 1374315478, 1156075184, 2442293407, 1057610827, 1297359181, 1747109539, 2141404099, 4281881065, 138386125, 3063455685, 3257890728, 3858193084, 3304890228, 238881307, 3445664438, 1185407578, 2888653737, 993706894, 1967766053, 127412966, 2403399672, 1285486798, 908290107, 1510442679, 4206401596, 3276759710, 11374285, 3959337953, 2236839585, 1565413293, 2800534730, 3519885942, 3614906874, 2633795417, 3347806654, 569358328, 2189946218, 1203262343, 2746982062, 62980684, 2586441066, 3124531637, 2381648646, 105584535, 2941906813, 4638308, 3536520384, 446015359, 345521288, 2337847433, 1716341197, 3434262596, 327360947, 2195093682, 1901891799, 2053064947, 1866727148, 1933602442, 1896991511, 2434864863, 2509221232, 4146560978, 1738009642, 1186271375, 1991440446, 388280769, 169881608, 3374872656, 4866502, 1578994123, 3894433257, 1685621086, 3090617712, 2446643244, 1027311466, 2913067733, 415217914, 206402492, 3701056394, 1797709466, 3451818053, 648910037, 1949755852, 3049709007, 1611096612, 271402178, 2578204568, 481131710, 1944796007, 2365170803, 32134309, 3750170475, 1864104146, 3460592883, 1303514890, 1133731290, 3830118297, 591382459, 3363797689, 3707044033, 3781009395, 1183270231, 3773122255, 3243748324, 3121647216, 3297073440, ], &[ 1049478211, 680469795, 747349000, 2496192539, 3157275628, 2809929985, 1340573873, 2369546793, 2965031816, 1069643167, 3522649492, 82508657, 3745222809, 2653443896, 2691224863, 3638169243, 2790760129, 4050384292, 1236545914, 17769303, 3123357666, 3308586064, 230925596, 2288243675, 526850016, 3478799166, 1359885289, 375398501, 1996193928, 224867464, 3724522919, 3776621157, 1721777221, 1941498131, 1319934893, 335479091, 1206826435, 1008537741, 2525891651, 3027900562, 4088218789, 1755627645, 2151342900, 1492538444, 3337655012, 1349454, 757064511, 1793808978, 1243123906, ], false, &[ 3523610706, 4095718486, 1445432431, 1673437541, 4020367945, 3745015492, 3016399130, 2189565108, 2158132813, 1848828598, 2472767424, 878094830, 2680402548, 1260943793, 2476928489, 1177867634, 1646518182, 2946352334, 2967411271, 795570707, 2492588175, 1099595857, 2363747444, 2197221897, 2821893422, 2883961834, 3448280420, 786023016, 2349590684, 2639964406, 1547208182, 3946067756, 3185616768, 3182946836, 2191883192, 714873272, 792265815, 933013306, 2758420490, 3469512009, 2749660816, 1740114201, 1648303579, 1226176719, 4026247645, 894127522, 574096753, 1891430834, 2973532085, 944441129, 1683821712, 681573051, 3596769123, 1196189501, 2202034777, 1230292795, 3495428083, 3349595990, 3089151840, 3902324247, 1824847451, 783543484, 3845016445, 1815687272, 3454243, 2400067141, 2812607721, 1192925916, 2545803688, 4259913124, 2525790266, 1603659073, 2954188152, 3220648056, 4024945180, 1854165635, 2161271037, 517485723, 3238095654, 89843703, 3273382586, 3798028954, 1204973927, 2456421551, 1909094133, 2001850210, 3332598500, 2971871953, 2353788999, 1241071170, 422153499, 3611758239, 1771812426, 1704380646, 2934602124, 2834187644, 518477462, ], &[ 266027871, 609493494, 1199784782, 1682700206, 4164056974, 2244647064, 14359526, 1914376228, 1643693158, 449364942, 41001758, 2790190796, 1578020376, 30923228, 2290083886, 793751679, 3951462642, 4187532857, 4144262715, 2260802306, 203413221, 3707574023, 576327919, 33186882, 2830664220, 3895250804, 3878634772, 2739709544, 1332976664, 1238738498, 2733771934, 2370719463, 1598734028, 1315681082, 1037147578, 3551458133, 3406603032, 2882741411, 196631076, 833893415, 1307502306, 2956084628, 3466863337, 682644819, 4092006006, 1963236296, 154386710, 1982810036, 3147006703, ], ); // - lo >= DC_BDIV_QR_THRESHOLD in limbs_modular_div_mod_divide_and_conquer_helper // - hi >= DC_BDIV_QR_THRESHOLD in limbs_modular_div_mod_divide_and_conquer_helper test( &[10; 704], &[ 4185751770, 949164274, 3900519725, 1754790124, 2927570383, 1610053170, 3366859463, 1066429707, 3501570618, 2367440639, 2328634068, 3704221588, 2322372141, 3380520853, 4189820685, 485163788, 2195405920, 3117134592, 3277704486, 3921062791, 4106797055, 3045508412, 661029638, 2678369724, 1467681615, 1851814983, 2960522150, 2294339994, 489626124, 1242331300, 3385810062, 1149294828, 4088074806, 3724039365, 3770424399, 2493469584, 806372748, 3771669403, 1111232705, 3478087568, 4029774748, 3551452116, 3110587082, 2488974879, 47749858, 2223367929, 873250000, 2012398807, 1861118382, 2706639555, 2880844104, 1868093092, 3743135694, 4074318903, 2930806087, 2281983526, 1378855744, 3388340416, 3195092613, 3141388671, 3385803629, 2248154961, 716647719, 408786065, 4189607626, 2706804476, 392451433, 843831220, 2117893506, 3763769755, 2423989357, 1884254215, 4268634885, 1347756990, 4289680773, 1595972140, 1860322889, 3365907154, 654256963, 3331834702, 3229143368, 1643589278, 3268087485, 3428966374, 3734153935, 506918314, 2193830653, 1524006905, 2233546309, 2451094754, 983474066, 1062775683, 1398440782, 617471652, 233856640, 1491439739, 194893774, 404597210, 3349886938, 807897566, 1268209008, 3507741641, 434756682, 3067317419, 1955402334, 3598337478, 4236902625, 3345914967, 2108259867, 4199783792, 3533374250, 690146057, 2735070107, 3232842523, 3628050608, 139149260, 1670944793, 3256209787, 3411654393, 1946511496, 2082461349, 2746160530, 1671886353, 2094620437, 1492520252, 3287026452, 1499589769, 2631443030, 4265952385, 1560009101, 1665017895, 3582256582, 583800370, 1971617104, 1393694131, 1717803931, 2118915823, 606443859, 76766530, 1028659200, 3222396398, 491393514, 2650674330, 1420523709, 990196161, 4164467322, 955609751, 3658315631, 3108133206, 2441918819, 119215334, 1647135728, 1151329712, 2270557882, 2839636265, 1788114480, 953442631, 220077499, 3739679968, 289913489, 153493659, 2215060199, 654989994, 2506760104, 3263600596, 2504124177, 3901175056, 3815693428, 4062899928, 656080429, 1691317505, 2738892449, 2218799091, 254384726, 3472889999, 452028418, 2323167132, 3160160509, 2790465254, 3506704767, 920776279, 1555295659, 2088038090, 3587541031, 704460377, 41385058, 117178999, 3630755471, 2068346931, 1737173706, 943790911, 1174415673, 2975257119, 4104946893, 563605415, 3504496607, 3460311420, 3481281138, 2065638799, 222198878, 693087774, 2553540537, 3515067895, 493992216, 2675820307, 1624273500, 537035998, 1538452403, 227298276, 566431973, 3341420291, 2663602752, 849190806, 517998830, 674919319, 1319125805, 3230314450, 889723668, 3312911398, 2040926687, 1551018220, 217350907, 1190271637, 2196470418, 582739501, 574580675, 627521985, 3462620295, 1826546772, 1200183559, 2511667565, 3321520722, 1760501936, 3401858303, 2056315825, 2956669134, 591282350, 2228097677, 3953970187, 3763033846, 3981289762, 2843535951, 4035523339, 1074508115, 3233409639, 314820046, 1519729781, 1729078105, 4201604342, 3380921403, 2184949152, 2897857848, 212321156, 481361797, 3780255393, 2528871308, 2219779174, 3502413298, 2433932491, 2088433048, 1119465465, 553056530, 2681509152, 1990025128, 4113937421, 757723844, 4065055099, 1438167045, 1714067756, 295039437, 3553014346, 1500257339, 121711495, 1299814419, 1481787451, 466462561, 3450349124, 3354633040, 4197116852, 2300067620, 2300312798, 734816444, 668372087, 610325644, 1820480332, 312923552, 1371828336, 386480792, 3231465004, 2119854347, 2503795939, 37544982, 2127724350, 3977310867, 906274532, 3014798043, 1163507806, 39393504, 3203870929, 2603325424, 601940205, 1446813021, 4008328844, 1129836361, 2242436794, 1108252363, 710998579, 3822246787, 4245857572, 227662739, 3162273355, 2718012967, 512837928, 1146047591, 1624412382, 4172642116, 2479791213, 2246659717, 2115301250, 144504796, 3097248580, 1488044443, 3235358299, 310016185, 727752929, 3403555569, 1034814907, 572097587, 1799465727, 3315327068, 1904601168, 1060041227, 95653066, 3179621384, 2784606474, 3635929233, 3002198637, ], &[ 925120207, 4225173411, 773590203, 2705088909, 760018119, 3560986781, 3276778645, 569879745, 275063826, 3553444079, 3591608936, 938243104, 3604596571, 1820901407, 4022554834, 1440792481, 574650989, 3656262710, 4150032702, 1559596409, 3960538469, 1809314494, 2152378256, 825148860, 2074258358, 2059483645, 3119970833, 3052492792, 1083432735, 2994856903, 3287600147, 2502703055, 1752688956, 4149576868, 1709984301, 3235915685, 487122947, 437538202, 3178502734, 1263854855, 135705911, 2843982074, 4164166971, 4100829511, 3031022541, 3201076966, 1805387578, 1826440600, 557213027, 2792934052, 2243352750, 1801883920, 3301321918, 469048417, 2725138727, 2947700289, 1913798124, 574678647, 2000040094, 2336849657, 3912194680, 1616490328, 2363261019, 3380210359, 2784609072, 835985245, 1062319853, 2519822447, 4185407058, 3253459482, 3240288702, 3425190358, 3392304118, 3339858917, 227057671, 2117867538, 1238503500, 1783611406, 1671436072, 4020871006, 3708283179, 1814419869, 2809845213, 402675383, 700520900, 4021715245, 3864091313, 1886661387, 2898624118, 2266154557, 1538350152, 4205425742, 2641391768, 3508390452, 202172288, 2270033614, 787751496, 4225843194, 2087465714, 718749793, 4160365132, 121686135, 3232242907, 1290170166, 2696610438, 2043913461, 2304403306, ], false, &[ 4221978630, 1973199499, 4118761517, 1280124308, 1169734844, 4186771056, 1549813668, 2075241811, 3420909216, 3907043806, 2541993804, 282548280, 1975129143, 3336674855, 4090776129, 2428071752, 3676342369, 3454430534, 316538936, 243907370, 2971927846, 251436476, 2221794683, 2822328444, 528428056, 1993265952, 3040794479, 4050913221, 2509817742, 2793009366, 3346235129, 4179770275, 1329386656, 3069305579, 422911051, 232216774, 3312143191, 81270597, 779322188, 1011095209, 1055038871, 1975842925, 1732790895, 733239904, 1557320335, 1710699531, 4221175046, 721245441, 2600219287, 1818367711, 1883945801, 1722730504, 3667715777, 3514130820, 2079744029, 4097159692, 8702783, 1634848318, 4003868364, 3189174634, 154328123, 3136083300, 1256793950, 3908958390, 3995938868, 3505295673, 15682981, 1733079452, 2199765868, 1399865418, 3931463027, 216129100, 1771409837, 4170117419, 2889309579, 1323366430, 3037738897, 3024721374, 3698031352, 1843487639, 2640258708, 2514361590, 67538017, 3752890769, 2377631023, 1117874819, 2034201383, 3233935115, 186520404, 1781753373, 2159589499, 1457819895, 1955947342, 3294618852, 2583537479, 1780703679, 1295362239, 4288927730, 3528770822, 290885828, 1022721043, 2379556752, 249111996, 1042924458, 3285072303, 1799654769, 341780256, 2011707698, 4011728901, 4131230694, 243833190, 3438825130, 732870287, 3977999178, 1964878050, 1772633237, 3427011489, 4149075167, 3147152113, 4186542306, 3008212122, 2269822538, 2457396003, 2899887041, 3084745386, 2805864858, 2636345155, 2806159180, 1448641497, 1724536998, 3602736476, 670315274, 821858587, 3976166693, 1431302113, 994517893, 3205096696, 734083218, 684810460, 871706632, 1619463495, 1943812284, 3232191634, 1688008439, 959671513, 861714098, 3632682856, 4008579961, 1713155910, 621038709, 2171689707, 16974992, 1322572013, 3716365836, 1503115330, 3655753010, 3148139022, 862756091, 2477797665, 1345732090, 2351929785, 4244479677, 3338662555, 590731935, 3482514189, 1766212776, 1514121012, 3065000224, 1126651654, 3402553599, 4032051831, 2997384063, 1732308544, 1185658163, 505658742, 12068286, 191037370, 3820036984, 1808669698, 4025106072, 1258717124, 2996770408, 104941276, 3293831485, 3303505858, 1959694112, 2104003029, 513795826, 682626035, 1611502331, 165846820, 3906438907, 2655225469, 1304471424, 2263663116, 2896749335, 2359126350, 2213606484, 1429710281, 2842535444, 2328001305, 1030529844, 72684272, 3885232193, 4190971495, 1802226099, 3077502465, 1399196074, 15975559, 1608426341, 2824610166, 3242678682, 97752959, 1141976170, 2545270306, 2934382174, 1423201353, 4009237774, 989437497, 3792380846, 2436069063, 101138334, 3054205179, 476518326, 45092653, 1388468856, 622609810, 3089605077, 273759253, 2522262643, ], &[ 1326262193, 4033304858, 3860284891, 3270761392, 301590389, 3160950768, 2103051311, 421308210, 339700217, 2084975913, 4010857750, 3321647285, 2893234504, 3337934258, 2470197482, 3426298259, 3795587565, 2533784226, 1029322143, 2753534641, 1002751731, 1383277453, 1739180040, 4179121877, 686043541, 3404602754, 2524149226, 1961421140, 739626289, 50422302, 4167603214, 890939538, 544526709, 333127915, 1031745192, 2528526981, 2519624435, 2088255264, 2561443326, 3976592858, 1904453814, 37801928, 2483368030, 3723552401, 479916426, 2605772934, 4101701491, 2731241841, 516350289, 1540979081, 2317342783, 3699898529, 2962115900, 618662503, 360824901, 2483974833, 3444107029, 23562940, 1137290279, 793246641, 3743331916, 1726283098, 3569199524, 898653133, 4096842332, 1438551593, 32970915, 3426974921, 444732961, 724921875, 1414708840, 1717003917, 1924528246, 4171817847, 3372667246, 3830123695, 927406351, 2027580181, 1664983727, 2533132252, 1161370976, 2395800918, 1493087279, 3712645656, 216022641, 405129823, 437352819, 2790439088, 3977337552, 1902827120, 3057912539, 3003163486, 3875702633, 3752739451, 987987508, 2784338852, 840729416, 101169395, 3198958489, 4287799304, 1745316888, 3524003193, 1226093819, 3034997281, 714903529, 1035449811, 1648914672, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_divide_and_conquer_fail_1() { limbs_modular_div_mod_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], &[], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_divide_and_conquer_fail_2() { let ds = &[1, 2, 3]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_divide_and_conquer_fail_3() { let ds = &[1, 2]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(&mut [], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_divide_and_conquer_fail_4() { let ds = &[4, 5]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_mod_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[test] fn test_limbs_modular_div_mod_barrett() { let test = |qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], borrow, qs_out: &[Limb], rs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut rs = rs_in.to_vec(); let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; assert_eq!( limbs_modular_div_mod_barrett(&mut qs, &mut rs, ns, ds, &mut scratch), borrow ); let q_len = ns.len() - ds.len(); assert_eq!(&qs[..q_len], qs_out); assert_eq!(&rs[..ds.len()], rs_out); verify_limbs_modular_div_mod(ns, ds, borrow, qs_out, rs_out); }; #[cfg(feature = "32_bit_limbs")] { // - in limbs_modular_div_mod_barrett_balanced // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_mod_barrett_balanced // - q_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_mod_barrett_balanced // - carry in limbs_modular_div_mod_barrett_balanced test( &[10; 3], &[10; 3], &[0, 0, 0, 0], &[1, 2], false, &[0, 0], &[0, 0], ); test( &[10; 3], &[10; 3], &[1, 2, 3, 4], &[1, 2], false, &[1, 0], &[3, 4], ); test( &[10; 3], &[10; 3], &[1, 2, 3, 4], &[5, 6], true, &[3435973837, 3607772528], &[4123168602, u32::MAX - 1], ); test( &[10; 3], &[10; 3], &[1, 2, 3, 4, 5], &[1, 2, 3], false, &[1, 0], &[0, 4, 5], ); test( &[10; 3], &[10; 3], &[1, 2, 3, 4, 5], &[1, u32::MAX, 3], false, &[1, 3], &[2, 0xfffffff8, 4], ); // - in limbs_modular_div_mod_barrett_unbalanced // - q_len_s > i_len in limbs_modular_div_mod_barrett_unbalanced // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_unbalanced // - d_len == i_len in limbs_modular_div_mod_barrett_unbalanced // - q_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_unbalanced // - d_len != q_len_s in limbs_modular_div_mod_barrett_unbalanced // - !carry second time in limbs_modular_div_mod_barrett_unbalanced test( &[10; 3], &[10; 3], &[1, 2, 3, 4, 5], &[7, 8], true, &[3067833783, 175304787, 3481052211], &[2216353382, u32::MAX - 1], ); // - d_len == q_len_s in limbs_modular_div_mod_barrett_unbalanced test( &[10; 4], &[10; 3], &[1, 2, 3, 4, 5, 6], &[7, 8], false, &[3067833783, 175304787, 3481052211, 2770888938], &[3602692266, 0], ); // - d_len != i_len in limbs_modular_div_mod_barrett_unbalanced // - !carry first time in limbs_modular_div_mod_barrett_unbalanced test( &[10; 25], &[10; 19], &[ 1055350223, 3049382586, 4211404571, 3876314835, 4079443157, 4038320272, 788805966, 3784408476, 1246213405, 2888182970, 2261017929, 1076053788, 2501863035, 4127455271, 4275509120, 2405873407, 595189898, 734988773, 472621924, 2174894187, 3899735108, 215445128, 1522826922, 2013231118, 2572793610, 3364892170, 1420194578, 2506221487, 667648088, 810748791, 2612101093, 2650289028, 4056901105, 2431350237, 37519423, 2017228158, 1313697295, 2715710214, 1734284446, 2882471675, 3715454439, 1236125406, 1443396768, 2933508364, ], &[ 3663635511, 3774569147, 1456029034, 545218027, 3883722449, 4256811234, 4280475551, 446268340, 1439707019, 3006588287, 3015676595, 2251279938, 3776675540, 112585308, 2726538330, 1425601246, 1583649315, 3604979549, 1473232315, ], false, &[ 170063657, 2165570113, 2907518307, 1430243918, 2140749125, 3558893223, 2847072687, 4090009629, 4254439605, 2409969231, 3425274081, 4131046019, 2116325398, 2254079976, 4252966135, 2463907465, 580945345, 1823337423, 2340467621, 2110070789, 2620914623, 3150901076, 1253645171, 1967019766, 2932062934, ], &[ 2089766457, 292821147, 3117586049, 1036271118, 2574097064, 1232271710, 1288296201, 2511496451, 3125977553, 2778795769, 2999224452, 1311965009, 225728039, 1754024341, 1242425483, 2864810952, 1157382204, 2754439417, 1927770818, ], ); // - carry second time in limbs_modular_div_mod_barrett_unbalanced test( &[10; 113], &[10; 7], &[ 1780785185, 786171578, 3157515628, 1592442002, 3380766160, 2287562230, 715389251, 248693343, 1917127407, 3734172511, 318221247, 353404054, 770901771, 1185388775, 1026227030, 2159266648, 4115835732, 3372528053, 3300094046, 4237524737, 3734961305, 3971742075, 2838379294, 4275415020, 3696524563, 4195057627, 1748644269, 3938177066, 3720834606, 3725787789, 2343496907, 2973877655, 710152359, 3397267742, 2968876692, 2888566080, 4065287679, 2995290545, 355522630, 1240165026, 2600807130, 468290838, 38477660, 2658554572, 2915670343, 1795675394, 278501959, 1137682730, 3997261853, 34007068, 4160869696, 531258143, 1374216847, 1723957411, 277507095, 2287214710, 508149326, 2515464872, 1732728407, 258712591, 2285022762, 2447676003, 1262780680, 1199002631, 1579465944, 1049912517, 2621415467, 3593350728, 962641356, 1344046504, 137232829, 638490247, 3421265303, 2727821003, 2855549593, 827801261, 2202020535, 2322971763, 360280234, 840962056, 2736221025, 1257442332, 2541827007, 3410395173, 1257508164, 315829993, 2860519251, 3307878515, 1942955455, 1060223758, 1834897098, 2073690721, 43780026, 1410663879, 614961912, 2120543497, 2242462397, 2715797106, 2037137824, 1831803889, 30458973, 707478969, 1483765857, 206823596, 726188538, 4064151055, 1331924582, 2159077308, 299368864, 644097902, 1927782610, 1274113091, 780909329, 3276588176, 2622376275, 1944908892, 1548718985, 1478198552, 167729486, 2805305447, ], &[2712529337, 3550254038, 912173613, 3471575420, 1584706027, 4183294179, 2032726108], false, &[ 2145811881, 2853684621, 164754117, 3675200822, 3263953060, 540174416, 540344644, 3117220624, 74272150, 2433930443, 2738006052, 2816255289, 2203418744, 911786820, 3177797500, 1226409737, 3793898412, 403951736, 2441100417, 2633166493, 3446817232, 345329148, 3098851660, 941805631, 3993664945, 1275632198, 508337323, 839461454, 1530627916, 271645050, 1670009911, 3116428377, 3731487849, 2293244083, 917189423, 1772472525, 3599863118, 187105349, 2474067907, 2795120425, 630120186, 3544350690, 3629527923, 759676403, 199697033, 729268782, 314351667, 1979650537, 528328059, 1369356989, 4006685949, 3314502758, 3919641191, 1499885293, 1421775739, 4058709376, 549255670, 2433522610, 194681592, 1941767539, 3859348464, 2757354972, 2081397265, 1728594419, 1355471243, 605531861, 3102620513, 2633037944, 2567352331, 2289344558, 1636097668, 2472013149, 1966694756, 3680045927, 3351623316, 3953479661, 1034435973, 2559556196, 2727941371, 996730585, 3729767953, 2471327060, 4216682881, 1386133884, 3545016228, 2025097022, 2150272500, 2943616975, 4160651382, 4095528727, 3654689124, 2442799685, 2211976583, 3869553045, 169899811, 1764168626, 2153322769, 2927176214, 3196475524, 1798404841, 220326463, 216721343, 2602454439, 1608608695, 2299642725, 685786805, 2299002959, 3664589029, 1143480179, 1493337062, 3847260732, 2243223380, 1914898063, ], &[2336930396, 3906180555, 3405422945, 1687575114, 2055613801, 3816276157, 1899020713], ); // - carry first time in limbs_modular_div_mod_barrett_unbalanced test( &[10; 210], &[10; 19], &[ 2957922040, 870247152, 910873828, 2706667305, 2006892424, 1634563813, 287970711, 1133803930, 961388798, 2714428017, 4030274882, 3138804883, 547887122, 1780655515, 2754780720, 2058686138, 2291641774, 1741543525, 2246044650, 933209107, 4004027900, 3379557691, 266017900, 2676189357, 1591355793, 3361078936, 2211217877, 2921128900, 1828179459, 1074012967, 43100052, 2836201490, 1311232425, 4155464115, 1757143636, 1277755008, 1485841251, 3152888554, 583586772, 3806098743, 782964212, 3226263583, 1162123370, 3059562578, 2860980942, 479696604, 2270702751, 75758186, 2277793459, 2408711142, 2815967312, 232354809, 1421580147, 108234715, 3286460793, 841443270, 1825464019, 3954173086, 4046395553, 1749247097, 1093808724, 3438517259, 359669614, 601658924, 1342170297, 1428604227, 182377350, 2587642660, 4286173557, 1885226635, 3025582699, 3966955161, 1368652640, 1973817988, 672984222, 1170853285, 4036364126, 2637166249, 2697845360, 3566541779, 376105455, 3942586561, 2215680833, 2746461408, 2651245592, 760249496, 3897056740, 2058897545, 1283445246, 3868587627, 2438849073, 4047410037, 3367521161, 675390171, 775086206, 3438960005, 144798590, 3473698909, 836037579, 2050195295, 2470811574, 1614292177, 357128906, 2374914894, 979884995, 1299595291, 3731376453, 1227867350, 3881033174, 3084409704, 409188904, 4138760620, 4274774539, 1698773036, 3894254462, 3016352503, 1333890087, 2095418435, 3153732455, 2176884950, 3593733835, 3605051893, 3005410021, 3887509669, 1018183006, 2630850017, 2235284844, 98727747, 3537572449, 1659151250, 1804358600, 886148381, 3364035538, 3284706688, 3368127755, 613336882, 2099319807, 2400145286, 2228643956, 2297667468, 3984708746, 1630727280, 1283416474, 2286105322, 1331586489, 375863143, 2336260394, 379345862, 1592268783, 421930024, 791870237, 34696659, 2830390144, 1045783073, 2327165333, 3737840283, 4280928327, 1608634581, 821500409, 2477616696, 748075940, 2898867500, 2810718701, 680766084, 1706513434, 2559362270, 2907012739, 557079510, 761670334, 2936564915, 2799140450, 263855902, 83724051, 3113029528, 710433489, 63647540, 2392860382, 2849685609, 2191113984, 3344692166, 3650051957, 1283783144, 679051425, 1874499366, 2982158115, 2233164876, 1068193514, 169526123, 124050420, 2254129164, 3129272672, 3748280701, 2962809382, 2925481293, 3971297350, 343974506, 1952488808, 298193824, 3111608248, 3842844698, 1134548982, 2796565349, 439974096, 661703453, 1670489521, 1331486799, 3296145757, 3970474581, 3498762865, 838199092, 3353634107, 1628665432, 439108122, 3585259826, 3022889712, 1940250559, 79233496, 1912286078, 4232848205, 2352720259, 952267727, 1536903505, 39209222, 3912743975, 3928334222, 2718037985, 1489352573, 2765707939, 598657491, ], &[ 4281128173, 3027906753, 2001755931, 2775065157, 1187751336, 596325169, 2779056912, 170261384, 831473261, 3013867871, 518058824, 3100518656, 3459929010, 2119404241, 1145055308, 743036299, 35681442, 2984784309, 2394592752, ], false, &[ 3545195480, 2830193270, 335420053, 794287831, 2741916634, 2863209122, 3474537493, 756302532, 2390999417, 4294477763, 1189935988, 1859141045, 2587320393, 948338846, 4082107915, 2964828974, 2707598527, 3327111998, 3063462536, 2651416679, 905396265, 2388020551, 593710429, 449874296, 2226775585, 7979097, 1540449503, 3250233597, 1312158539, 1991615641, 335908038, 3520510682, 2746466872, 914186511, 1932273631, 861083548, 3035810408, 2344742126, 659982098, 2860585760, 2634369596, 2813832754, 3952630841, 2075380109, 309440464, 1523149574, 3192186814, 999974815, 2341598038, 3017399438, 862035203, 4054680737, 2201990712, 397181202, 1647559963, 1267523856, 1199238444, 3731680308, 3790641117, 709354153, 2258539734, 1749483122, 2853840203, 1578892991, 2727550048, 2884219240, 3732650659, 2280125842, 2227946823, 2743139282, 150244596, 3009923444, 4262641312, 2587401277, 1068934326, 2162268682, 500752745, 2478246253, 657149362, 727272162, 1138165722, 3053293624, 622175917, 1883556266, 995622659, 3180371798, 2641139734, 636602958, 3974225725, 643270566, 3594175694, 1815151046, 181929979, 634258268, 1988561038, 1406268435, 1255929703, 2047200162, 327297893, 2089111137, 2465221310, 1515525444, 2651009463, 1627761087, 2816949718, 371898069, 3623581394, 2408374459, 852283718, 743629996, 1406343073, 1288623951, 1390517443, 3612531871, 1908188719, 20588564, 1991288974, 2134681310, 3976054820, 2112398386, 2742074585, 2223277780, 2566567369, 4161267340, 3521909307, 2707583513, 771440763, 2374943346, 3684262675, 3129700156, 1702004952, 3829866647, 2745914165, 544083442, 3125630973, 3396214384, 3490241400, 3855124301, 1918091363, 2827032159, 1870456944, 3090227886, 3351449380, 3758213391, 1013018528, 2291181284, 3221497475, 880874956, 4157883302, 3310385525, 1659149070, 1344782497, 1930681950, 237809822, 665463528, 2594721127, 3171089793, 17771920, 3012888524, 986806237, 1721541891, 203322900, 2850993174, 2812942792, 3291016822, 793893217, 3551981739, 3725150196, 3904109269, 908950595, 3445210635, 1732434801, 136778475, 4020163671, 2911572158, 2619712085, 695817951, 2564865838, 2683591409, 4128013969, 204856464, 3938011158, 472034484, 2799987675, 4277430554, 1053828060, 2996826767, 1330644500, 1181151222, 787673069, 1532990849, 432834735, 4011003718, 248480909, 3771359672, 316592679, 2847657270, 634291083, 1350943800, 1122137552, 489179352, 3994078723, 852486950, 2165215099, 624250642, 3818338360, 4277937938, 3825066593, 1697585856, 845743932, ], &[ 1692999357, 2954880473, 990817610, 3627848867, 604557740, 926149699, 3727741567, 705168250, 257141873, 2721173810, 2517358846, 2668361786, 1527518030, 3882089664, 221121460, 921437873, 2477571204, 1545760534, 127126010, ], ); // - carry in limbs_modular_div_mod_barrett_balanced test( &[10; 6], &[10; 8], &[ 1374494479, 2192068018, 2880324652, 42688047, 1794508871, 4043622026, 2888818532, 3570449488, 135909991, 1834703233, 99771521, 2930887574, 605577774, 1011468183, ], &[ 2460992677, 1140036614, 1658868868, 366747528, 1860201147, 2709920888, 1959763964, 1863179050, ], true, &[776020643, 407209981, 1979624516, 357370108, 1022326398, 2383287252], &[ 2671332979, 918397726, 698873472, 823603187, 3540180412, 56598308, 2177764749, 4272553129, ], ); // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_unbalanced // - d_len + i_len > mul_size in limbs_modular_div_mod_barrett_unbalanced // - q_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_unbalanced // - d_len + q_len_s > mul_size in limbs_modular_div_mod_barrett_unbalanced test( &[10; 139], &[10; 84], &[ 2646628784, 618896692, 3398943402, 3264540707, 1504960063, 3906164607, 570941654, 3580995164, 1443736701, 3590824971, 3860070111, 2945656477, 4251307330, 2402685539, 1846137259, 1189307444, 3386646133, 136368423, 249459846, 784663226, 4146072344, 2595677890, 733424230, 3453504236, 88571396, 749579536, 918695180, 1666773246, 4177391250, 4175984066, 2859904653, 3320165100, 314964734, 1227587574, 2960770677, 2399848571, 430617262, 138749172, 3397335244, 100239326, 1527324818, 3102878375, 3902410462, 3147053920, 2748042023, 2424421132, 1052940357, 986705203, 3463928015, 2137344177, 1023713259, 1900812309, 1091750798, 1033535614, 1704349724, 1274392095, 4220281689, 2312523638, 2550288105, 1603152422, 2468778401, 2362990259, 1771954100, 2226726386, 2256260198, 1919957004, 3125206342, 1705043648, 275322946, 1578653828, 3244824726, 568760497, 2157867085, 3722151892, 982962005, 2605569069, 3011932580, 555973834, 3850227878, 1840125026, 859902026, 3226837879, 803396279, 4091669116, 3502825211, 2705549345, 2355778569, 2472138162, 2501828872, 1716056509, 2461082272, 3407718600, 2048730354, 2754501598, 81705455, 2613874586, 3616438498, 743457455, 866447928, 1549437857, 2823907456, 216297612, 4292914429, 4033666199, 449146474, 3154061115, 452155000, 160006622, 658415472, 480293619, 2568541254, 523346876, 1123518434, 782900648, 4045385592, 969181715, 2603815504, 1562047677, 413762781, 164584514, 3971139354, 389543933, 3094350891, 3173761159, 3798939769, 3469659030, 2945777042, 2994242422, 3136151730, 2486286949, 2988445086, 1260050525, 1171382725, 1867967284, 302235847, 1042890122, 3608326628, 2275778352, 1767146951, 2944622700, 2789083247, 4141708171, 1551586595, 3621216040, 2781452047, 1405040348, 1672588153, 14666875, 2647122819, 3187518016, 2279001686, 1938063779, 1875081978, 4251256078, 2572448523, 3800192906, 1289906739, 2632255896, 2152286481, 3897576094, 1708421957, 4073852972, 3476212556, 1875655706, 3865408865, 1201794786, 4216156085, 1050577862, 472506848, 2553269926, 840961926, 2090709561, 2675996462, 2446149597, 833756615, 1758241617, 2274654294, 2386883401, 449558962, 1197625280, 3018484457, 1526642077, 2525115961, 1104794510, 4179539512, 2334981542, 1704190014, 4245163918, 821915893, 2958170015, 709350427, 728990040, 1687853788, 786779220, 3852055852, 1751071670, 3041460477, 352348239, 1868210536, 3695502625, 830421334, 235096442, 19032492, 3460387365, 2186466609, 161794199, 2560621452, 1382113822, 606335634, 2333561107, 1707370336, 2209093163, 2998828734, 917854441, 1572665439, 1169967127, 912392167, 3799501844, 3071223299, 3987504849, 3355880904, 567811128, 949461215, ], &[ 175531285, 78228064, 2801564496, 304265049, 891912354, 3315401569, 1026356408, 3942470248, 2223627569, 408866608, 2002970320, 4044159622, 3481083399, 1214787196, 4080970297, 855215497, 2843678654, 1991914207, 835424234, 3258509780, 1749412212, 3777869951, 1129376847, 3137205020, 1400979858, 3150368514, 3165530001, 2207061983, 1161753389, 803214774, 3625753632, 590750112, 259965773, 1326162274, 2653188614, 26451591, 1562785702, 1235742790, 3331276450, 9510804, 4278241988, 3727506800, 2781712221, 543113252, 380099502, 710412699, 905024784, 187278197, 587009259, 1508184302, 2414129863, 4152465703, 2161022364, 4124396813, 2190629393, 906688385, 102547773, 3659658175, 1420753856, 3400522400, 3636743612, 1520808959, 4198488051, 2115490366, 1371548286, 1292662256, 1069684821, 2485205762, 3559685229, 2961412573, 847483721, 410608408, 3530014382, 413744145, 1193871608, 3152782990, 1690455930, 233301503, 547904857, 2335968082, 845227807, 2094174869, 2149532553, 2291269465, ], true, &[ 2546777840, 2081991539, 2509769500, 1875915406, 1905948192, 602689312, 3268538198, 613162535, 1767316190, 3835834564, 2622706926, 3323532817, 374980976, 3111700826, 936860640, 2413052605, 2407595201, 278465408, 3314744140, 4091514460, 2110199799, 117453367, 1530925758, 309474103, 1279578725, 70909593, 1326551758, 2779708349, 3712869410, 1897725706, 705261972, 1824847489, 1691398432, 3209177026, 1020273962, 1167724900, 2567174051, 4116130680, 3208103429, 760573618, 782808697, 2745346818, 2496095329, 2811545307, 3946467709, 2483594659, 959341815, 4137660153, 997566470, 1730965450, 4089641998, 4267066391, 2858661809, 600039749, 1399987501, 506879518, 1186751467, 302620911, 2812551403, 3007055905, 303564811, 4286826331, 788916190, 2719882990, 4258512233, 1028190872, 1114024691, 3514649924, 3727249082, 841848367, 3084474590, 1059371415, 2166678521, 1581100579, 2950580743, 1574625618, 1082144357, 2521093167, 1048084761, 31290854, 2524741152, 808554579, 3189810605, 2992968319, 243265975, 603472290, 2860489763, 2101153718, 2034388432, 3710181854, 111490823, 1160951531, 1727109115, 746190508, 1539058660, 2839040461, 859789905, 1109658141, 2693429224, 364552289, 3793037740, 2280420170, 2901284656, 1614139914, 2372237091, 3487857543, 3345177295, 3288910636, 1737015121, 2590600286, 724573974, 197769707, 3550689133, 2635427825, 2347968548, 3296511750, 2601097680, 1138768331, 4046279289, 2437184198, 938543525, 1764278559, 1965551605, 514794004, 2192820822, 206655186, 3857560265, 1879744272, 1999335571, 3017015326, 3516909563, 421663640, 3063628317, 60413188, 359364666, 2997260220, 3206275809, 1623244265, 2111620703, ], &[ 3415280693, 292226959, 592874699, 3763036729, 1688416787, 1967588907, 1135297545, 300526407, 488749755, 1494683603, 3165003011, 4282144535, 2476794373, 1988031229, 913525083, 454665488, 4180669379, 3576137622, 467981361, 2124275570, 3315398077, 2017816700, 2870440357, 2701664661, 2420523946, 2114772415, 3454473078, 3959609658, 1750896866, 3529048766, 2526439800, 734193874, 3225577122, 1983738086, 1618614567, 4019248755, 1615177076, 1150622424, 2861553604, 317586884, 2084839958, 109391139, 4199849234, 407061349, 413639713, 161276082, 1826515215, 462920784, 2166692927, 1121252881, 2339049969, 3097449182, 1750060809, 1304728762, 2057029243, 4030798175, 3626590369, 3782070983, 103174900, 2174112267, 3202455482, 1120937734, 162805295, 2459403827, 1438730035, 1398853228, 3980589931, 411009274, 295760150, 835365008, 2046227916, 2834161547, 3061448231, 1463103212, 2485431474, 3580658208, 2859008315, 864196777, 1789864771, 1239143610, 84264026, 1385174506, 806629248, 4117925861, ], ); // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_balanced // - d_len + i_len > mul_size in limbs_modular_div_mod_barrett_balanced // - q_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in // limbs_modular_div_mod_barrett_balanced // - d_len + q_len_s > mul_size in limbs_modular_div_mod_barrett_balanced test( &[10; 101], &[10; 102], &[ 359503822, 930755077, 1384939963, 726523519, 735855137, 4230638458, 2518447149, 3461004289, 1461342994, 3713880403, 1117118383, 2325203080, 2382674090, 2102380477, 2949789537, 2703453484, 86306444, 2133711224, 4243514322, 2016200957, 2466844919, 2791971265, 1678349265, 503608099, 3435266102, 4137444085, 937001532, 485586778, 2181285770, 4154702612, 3835162797, 4047003407, 3104468273, 2789877216, 2555048214, 312826773, 2193261799, 1490099020, 995118624, 4053513367, 342560776, 1032986831, 1842962421, 1301135762, 1524809911, 902292378, 1239258361, 88884962, 1144616285, 1492178819, 420992757, 519709698, 2442073331, 1884369937, 26045701, 1835589285, 2189835185, 2439987082, 3707057329, 2082610449, 999299935, 1541780167, 1690776984, 112340575, 1698317092, 1643561123, 3408357912, 3288699838, 2673112056, 2870952889, 3681616841, 2531108070, 1640007944, 506062406, 3401691507, 3344023372, 853239077, 4105040843, 2886461869, 3452820566, 1667819286, 3128286539, 2625300568, 1756006991, 3341301070, 1308108861, 1414362786, 2458021424, 9934651, 3098138015, 3107892925, 2498445889, 3830361110, 379544259, 2568097985, 2246190918, 2856152801, 384822350, 1724512815, 3991713640, 3817037833, 3722412510, 2895114053, 2728589301, 19358989, 3717195474, 1165862612, 2362092950, 828816743, 2052326574, 2217965628, 2673072144, 324120214, 1340520493, 3213377932, 3674602689, 1059080299, 824464261, 2585132071, 1440667471, 392712257, 3280116872, 2202169969, 398134473, 1073083450, 2311392108, 3823195150, 3284957997, 2227733574, 1303704641, 1615356863, 3190573039, 2485032610, 3180590299, 2042457445, 308852594, 690284549, 3598835432, 511022704, 3497853857, 659940084, 1641894511, 783187155, 2292526793, 562512416, 1637241073, 1083958605, 4163240058, 604721442, 3780983693, 2998951985, 2603228801, 463730318, 1015654434, 2651982477, 4118206282, 512096013, 1080397248, 101189089, 2863689109, 354738858, 1787339697, 2232290920, 534759005, 2119002163, 3794431325, 232343840, 2486173117, 68089103, 2140825959, 2555962430, 2890402101, 2413815707, 1672311294, 2499213554, 3468248781, 871538482, 2596129344, 531624012, 2504774829, 1221872721, 1208930227, 3557575767, 3709013124, 1698819786, 4123261656, 4065987239, 1688610525, 1294770319, 2785995745, 4198307858, 2777810428, 2269402709, 3351492035, 1694111420, 3998731057, 2900253048, 1205651103, 396770736, 696872604, 1384642173, 3321829462, 289627277, ], &[ 2278424439, 3077751259, 1304585622, 1987828284, 3483676582, 456771916, 1922279346, 2709541120, 2656843747, 12978767, 316240098, 3536722689, 548385414, 724002627, 2476881616, 2166507279, 202171725, 1147560006, 1880112538, 1756777728, 1508901890, 1237270434, 2343198647, 2028182871, 1956050418, 3185234762, 2726786236, 1226215383, 3283321503, 3550779054, 3962623185, 2233581072, 3685362689, 2523061304, 3432992352, 856774698, 642855332, 1539603917, 3436254526, 3438316948, 3678354762, 2885957136, 638778530, 3855571391, 738420174, 1718985865, 3616901246, 1722694230, 1556281305, 3363415828, 3883725652, 1233902038, 492256678, 810883596, 2933458617, 2930892677, 3831374672, 3234208811, 4293259190, 2352386302, 3873041439, 997918588, 2424427679, 2782564963, 1728191643, 3952822243, 238626071, 1035613084, 542308994, 2994827340, 1113278284, 841529778, 4170703109, 3414455081, 896207174, 1979954113, 2035511039, 85618777, 2727640652, 1344449047, 3337583835, 3623474070, 3820508255, 635242386, 1085332469, 711665582, 1681624716, 2455915902, 2126072253, 2798572817, 1776815147, 453484, 3038980850, 1347504630, 372275114, 403210354, 3868566120, 3631747289, 3548627910, 3178868797, 3753938571, 150270533, ], false, &[ 3465160226, 1253419105, 3124808467, 751085507, 3110124395, 407173395, 2437959899, 4040430705, 2411492979, 2914523482, 3840204125, 319435997, 3999044619, 4145842866, 3512313567, 1166909167, 2317449476, 3701079118, 126559811, 90896448, 1455026859, 2191225041, 3229561661, 1343784046, 2969703260, 2878543582, 273951576, 4116117584, 781734515, 1973696951, 3647673909, 1542403693, 2180800305, 617680099, 300639543, 1558155610, 1182878845, 3865689017, 1416306973, 198512632, 2832322478, 3504115888, 1419290744, 3178356971, 3900449515, 199561130, 64886902, 3940732115, 3447589634, 1832464907, 1574927461, 435919088, 4113254992, 3460547477, 513876119, 1205361386, 3044966276, 2248267594, 3776615277, 3623228612, 3932766400, 1166892513, 291542906, 218374345, 4239344438, 2778233019, 1936059236, 1477081525, 1164400965, 3635983219, 4153675354, 3092149950, 937401074, 1818500930, 3870615142, 85247866, 3236546484, 3254512410, 3962391971, 2922578976, 95454893, 3077617251, 1113587582, 2603242994, 1807246933, 2202312525, 1989071615, 2769213474, 3776552472, 3043026852, 1891888557, 3886288480, 2532140003, 2035601305, 2317402048, 606214956, 4160105394, 3090211730, 1733339611, 926487350, 965806220, ], &[ 3221267380, 424988678, 3461740599, 99497455, 420198800, 867051773, 2503641458, 2356910464, 401890558, 3995226265, 1173135914, 569117494, 4292931100, 2799167928, 2695949014, 899794022, 3039093573, 892570103, 1937446217, 2096306730, 3092703233, 541614723, 1040631696, 3029761757, 2957844148, 1645807647, 291224988, 2152250183, 1826147730, 3034872166, 3287666699, 1640543162, 3730948302, 1919958117, 1401704167, 1823651835, 2352158907, 1673084692, 4217391492, 2392397767, 1316530687, 1884365084, 1664508764, 1242497742, 1700540913, 3262218786, 1465845111, 1581184944, 4138608221, 3316745971, 4068716277, 1099430011, 3708438587, 2390739279, 2810494457, 2750115918, 1906243889, 3659100604, 3033098071, 4226373414, 3983457187, 609871527, 3791925678, 404663530, 1206366873, 3160414140, 388713457, 2942486656, 2004345881, 3595245692, 2542300575, 2795641800, 2424368091, 424084901, 3116448977, 3602081167, 4024353039, 1210988544, 3034081293, 957423016, 1582447550, 3269802842, 1711116416, 3752601257, 296665184, 437398155, 285377319, 623507510, 1699111470, 132189609, 500420363, 3184770686, 2323445041, 2548878469, 2747066033, 3915257708, 3792192004, 1406510909, 2945427566, 210394923, 1847865361, 255836050, ], ); // - d_len + i_len <= mul_size in limbs_modular_div_mod_barrett_balanced // - d_len + q_len_s <= mul_size in limbs_modular_div_mod_barrett_balanced test( &[10; 90], &[10; 1294], &rle_decode(&[ (0, 60), (4294966784, 1), (u32::MAX, 246), (65535, 1), (0, 295), (3221225472, 1), (u32::MAX, 35), (31, 1), (0, 181), (4294967292, 1), (u32::MAX, 64), (7, 1), (0, 20), (4293918720, 1), (u32::MAX, 143), (4095, 1), (0, 225), (4292870144, 1), (u32::MAX, 106), ]), &rle_decode(&[ (u32::MAX, 558), (31, 1), (0, 72), (4294967288, 1), (u32::MAX, 110), (127, 1), (0, 435), (4261412864, 1), (u32::MAX, 115), ]), false, &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &rle_decode(&[ (0, 217), (65536, 1), (0, 295), (3221225472, 1), (u32::MAX, 14), (4294950911, 1), (u32::MAX, 20), (31, 1), (0, 51), (4096, 1), (0, 110), (4294901760, 1), (u32::MAX, 18), (4294967291, 1), (u32::MAX, 64), (7, 1), (0, 20), (4293918720, 1), (u32::MAX, 143), (4095, 1), (0, 187), (4, 1), (0, 37), (4292870144, 1), (u32::MAX, 76), (4294966783, 1), (u32::MAX, 29), ]), ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 595], &[10; 731], &rle_decode(&[ (u64::MAX, 51), (9007199254740991, 1), (0, 346), (18446603336221196288, 1), (u64::MAX, 39), (127, 1), (0, 170), (18446743798831644672, 1), (u64::MAX, 380), (8191, 1), (0, 224), (18446744073709551488, 1), (u64::MAX, 110), ]), &rle_decode(&[ (u64::MAX, 183), (1048575, 1), (0, 4), (18446744071562067968, 1), (u64::MAX, 206), (134217727, 1), (0, 130), (18446744072635809792, 1), (u64::MAX, 204), ]), false, &rle_decode(&[ (1, 1), (0, 50), (18437736874454810624, 1), (u64::MAX, 131), (1048575, 1), (0, 4), (18446744071562067968, 1), (u64::MAX, 46), (18446744073709551103, 1), (u64::MAX, 4), (1048575, 1), (0, 125), (1099511627776, 1), (0, 4), (18442240474082181120, 1), (u64::MAX, 4), (4611686018427387903, 1), (0, 18), (134217728, 1), (0, 2), (140737488355328, 1), (0, 19), (18446744073172680704, 1), (u64::MAX, 4), (2199023255551, 1), (0, 4), (18444492273895866368, 1), (u64::MAX, 9), (18446744073709551487, 1), (u64::MAX, 8), (18446744073709486079, 1), (u64::MAX, 78), (18446744072635809791, 1), (u64::MAX, 22), (1152921504606846975, 1), (0, 5), (18446744073709551232, 1), (u64::MAX, 4), (786431, 1), (0, 4), (18446744073172680704, 1), (u64::MAX, 12), (281474977234943, 1), (0, 3), (8, 1), (17870283321406128128, 1), (u64::MAX, 3), (18446744073709535231, 1), (u64::MAX, 7), ]), &rle_decode(&[ (1, 1), (0, 5), (562949953421312, 1), (0, 4), (14987979559889010688, 1), (u64::MAX, 2), (18446743798831644671, 1), (u64::MAX, 2), (383, 1), (0, 4), (18446744073709289472, 1), (u64::MAX, 3), (134217727, 1), (0, 4), (18446743798831644672, 1), (u64::MAX, 3), (137438953471, 1), (0, 4), (18446462598732840960, 1), (u64::MAX, 73), (2251799813685247, 1), (0, 4), (13835058055282163712, 1), (u64::MAX, 16), (18446744073709551614, 1), (u64::MAX, 1), (18446744073709486079, 1), (u64::MAX, 4), (536870911, 1), (0, 4), (18446742424442109952, 1), (u64::MAX, 4), (2251799813685247, 1), (0, 4), (17293822569102704640, 1), (u64::MAX, 7), (18446742974197923839, 1), (18446744073709551591, 1), (u64::MAX, 2), (18446744073701163007, 1), (2251799813685247, 1), (98304, 1), (0, 2), (34359738368, 1), (0, 1), (18446744073608888320, 1), (u64::MAX, 2), (18446708889337462783, 1), (u64::MAX, 2), (18446744073708503039, 1), (u64::MAX, 3), (9007199254740991, 1), (2147483648, 1), (0, 6), (18428729675200069632, 1), (u64::MAX, 3), (18446744073709550591, 1), (u64::MAX, 18), (72057594037927935, 1), (0, 5), (18446744073709551600, 1), (u64::MAX, 4), (16383, 1), (0, 8), (17179869184, 1), (0, 8), (8796093022208, 1), (0, 50), (64, 1), (0, 4), (18446744073709289472, 1), (u64::MAX, 4), (268435455, 1), (0, 10), (18446744073708503040, 1), (u64::MAX, 4), (2147483647, 1), (0, 1), (288230376151711744, 1), (0, 3), (8192, 1), (0, 18), (17870283321406128128, 1), (18446744073701163007, 1), (u64::MAX, 4), (51539607679, 1), (0, 4), (18446638520593154048, 1), (u64::MAX, 4), (72057594037927935, 1), (0, 3), (18446743936270598144, 1), (u64::MAX, 1), (511, 1), (0, 4), (18446744073708503040, 1), (u64::MAX, 1), (18446603336221196287, 1), (18446744073709549567, 1), (u64::MAX, 2), (18446744072635809791, 1), (u64::MAX, 1), (4194303, 1), (0, 2), (2199023255552, 1), (0, 7), (18446744073575342080, 1), (u64::MAX, 61), (17293822569102704639, 1), (u64::MAX, 23), (67108863, 1), (0, 4), (18446743661392691200, 1), (u64::MAX, 4), (844424930131967, 1), (0, 4), (17870283321406128128, 1), (u64::MAX, 5), (18446742974197923839, 1), (u64::MAX, 4), (4503599627370495, 1), (0, 1), (562949953421312, 1), (16384, 1), (0, 1), (13835058055282163712, 1), (8589934591, 1), (0, 1), (18446744073675997184, 1), (u64::MAX, 2), (18446726481523507199, 1), (u64::MAX, 7), (1073741823, 1), (0, 4), (18446744073575333888, 1), (u64::MAX, 2), (18446603336221196287, 1), (u64::MAX, 19), (536870911, 1), (0, 4), (18446741874686296064, 1), (u64::MAX, 4), (2251799813685247, 1), (0, 9), (128, 1), (0, 8), (65536, 1), (0, 36), (18446744073709551488, 1), (u64::MAX, 41), (1073741823, 1), (0, 22), (17293822569102704640, 1), (u64::MAX, 5), (383, 1), (0, 4), (18446744073708765184, 1), (u64::MAX, 4), (536870911, 1), (0, 12), (18446462598732316672, 1), (u64::MAX, 3), (18446744073709551607, 1), (576460752303423487, 1), (0, 3), (16384, 1), (0, 7), ]), ); } } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_barrett_fail_1() { let ns = &[1, 2, 3]; let ds = &[3]; let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_mod_barrett(&mut [10; 3], &mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_barrett_fail_2() { let ns = &[1, 2, 3]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_mod_barrett(&mut [10; 3], &mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_barrett_fail_3() { let ns = &[1, 2, 3, 4]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_mod_barrett(&mut [10], &mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_barrett_fail_4() { let ns = &[1, 2, 3, 4]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_mod_barrett(&mut [10; 3], &mut [10], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_mod_barrett_fail_5() { let ns = &[1, 2, 3, 4]; let ds = &[4, 5]; let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_mod_barrett(&mut [10; 3], &mut [10; 3], ns, ds, &mut scratch); } fn verify_limbs_modular_div(ns: &[Limb], ds: &[Limb], qs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let q = Natural::from_limbs_asc(qs); assert_eq!((q * d).mod_power_of_2(limb_to_bit_count(ns.len())), n); } fn verify_limbs_modular_div_neg(ns: &[Limb], ds: &[Limb], qs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let q = Natural::from_limbs_asc(qs); let p = limb_to_bit_count(ns.len()); assert_eq!((q * d).mod_power_of_2(p).mod_power_of_2_neg(p), n); } #[test] fn test_limbs_modular_div_schoolbook() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let inverse = limbs_modular_invert_limb(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(&mut qs, &mut ns, ds, inverse); assert_eq!(&qs[..ns.len()], qs_out); verify_limbs_modular_div_neg(ns_in, ds, qs_out); let mut ns = ns_in.to_vec(); limbs_modular_div_schoolbook_in_place(&mut ns, ds, inverse); assert_eq!(ns, qs_out); }; #[cfg(feature = "32_bit_limbs")] { test(&[10; 3], &[0, 0, 0], &[1, 2], &[0, 0, 0]); test( &[10; 3], &[1, 2, 3], &[1, 2], &[u32::MAX, u32::MAX, 0xfffffffc], ); test( &[10; 3], &[1, 2, 3], &[3], &[1431655765, u32::MAX, 0xfffffffe], ); test(&[10; 3], &[1, 2, 3], &[u32::MAX], &[1, 3, 6]); test( &[10; 3], &[1, 2, 3], &[5, 6], &[858993459, 687194767, 893353197], ); test( &[10; 3], &[1, 2, 3], &[1, 2, 3], &[u32::MAX, u32::MAX, u32::MAX], ); test( &[10; 3], &[1, 2, 3], &[1, u32::MAX, 3], &[u32::MAX, 0xfffffffc, 0xfffffffd], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 3], &[1, 2, 3], &[1, 2], &[u64::MAX, u64::MAX, 0xfffffffffffffffc], ); } } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_fail_1() { limbs_modular_div_schoolbook(&mut [10; 3], &mut [1, 2, 3], &[], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_fail_2() { let ds = &[1, 2, 3, 4]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_fail_3() { let ds = &[1, 2]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(&mut [10, 10], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_fail_4() { let ds = &[4, 5]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_in_place_fail_1() { limbs_modular_div_schoolbook_in_place(&mut [1, 2, 3], &[], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_in_place_fail_2() { let ds = &[1, 2, 3, 4]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook_in_place(&mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_schoolbook_in_place_fail_3() { let ds = &[4, 5]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_schoolbook_in_place(&mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_div_divide_and_conquer() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, ds, inverse); assert_eq!(&qs[..ns.len()], qs_out); verify_limbs_modular_div(ns_in, ds, qs_out); }; // - q_len > d_len first time // - q_len < DC_BDIV_QR_THRESHOLD first time // - q_len != d_len test(&[10; 3], &[0, 0, 0], &[1, 2], &[0, 0, 0]); test(&[10; 3], &[1, 2, 3], &[1, 2], &[1, 0, 3]); test( &[10; 3], &[1, 2, 3], &[5, 6], &[3435973837, 3607772528, 3401614098], ); // - q_len <= d_len // - q_len < DC_BDIV_QR_THRESHOLD second time test(&[10; 3], &[1, 2, 3], &[1, 2, 3], &[1, 0, 0]); test(&[10; 3], &[1, 2, 3], &[1, u32::MAX, 3], &[1, 3, 2]); // - q_len == d_len test( &[10; 4], &[1, 2, 3, 4], &[5, 6], &[3435973837, 3607772528, 3401614098, 2790010755], ); // - q_len > d_len second time test( &[10; 5], &[1, 2, 3, 4, 5], &[7, 8], &[3067833783, 175304787, 3481052211, 2770888938, 2968937350], ); // - q_len >= DC_BDIV_QR_THRESHOLD first time test( &[10; 101], &[ 2614433502, 201952551, 1985699938, 3737156448, 1826834370, 390646530, 3862902767, 3701087729, 3240671658, 1498939256, 405421884, 2500498977, 543951667, 3836845972, 114681939, 1915271357, 1549193218, 2855181942, 1722136441, 2766310271, 47656978, 3837638424, 4016489648, 3574908855, 271673898, 401895301, 1488021015, 2138694572, 2044000169, 958933265, 3144481463, 2779079775, 1326886023, 2406822210, 3541050174, 2770735565, 2480957566, 2243398174, 2238068283, 311009614, 1882015784, 1325726230, 997031698, 1581908377, 2605721422, 3189028102, 272460210, 490645275, 2254115078, 1729448452, 3279102284, 4891191, 3182892978, 4279769790, 76488030, 2146767575, 3135871036, 2565128600, 1134722432, 4021959710, 2443099174, 3511788218, 3402507407, 3887545637, 1602118380, 3373080814, 913482070, 2525212842, 458807656, 2191742476, 189120803, 1571244040, 2065986906, 3536519990, 1106920062, 249073982, 3953429556, 70634017, 2295215236, 1095935313, 3576698687, 4150987084, 3091466601, 2659048520, 2421964497, 478008822, 4183767176, 3019500765, 472981990, 4237993573, 2387724271, 2897482399, 2735157706, 3951571091, 1100488960, 772381751, 3385833448, 243788259, 2673522310, 2507994216, 422336110, ], &[ 1465267273, 74481649, 4134700379, 1230170156, 365676293, 3483084975, 1197662581, 2640006295, 4011823868, 3248823520, 3487252378, 2404109212, 1035566706, 2348272566, 1563713437, 926167746, 4275574143, 2618001622, 3006090084, 758724212, 2363503275, 2777706618, 36668516, 1573638162, 826631123, 1003261600, 3834425037, 3917704239, 380020162, 1200612060, 4053700768, 4029551185, 1269962948, 3135204397, 1191219015, 2005782900, 600631609, 2788434518, 160830671, 1865310436, 2821311021, 1359155705, 390596229, 173852699, 2808888002, 845149215, 4091564759, 2997755999, 3196096033, 2442709791, 2497943703, ], &[ 2268505070, 3175859475, 3142537387, 3900159731, 1159682617, 4189328550, 3907703309, 1212735193, 532303389, 2766948169, 2016978110, 2967794961, 2774851624, 3217650683, 2925509985, 3764969541, 958893059, 3417020824, 1954191584, 3562512044, 2446134389, 2177043907, 2722738527, 1056354433, 163366464, 2100641128, 2795771616, 981138683, 2004843724, 421545248, 931541656, 2667221997, 1053518296, 3427347852, 943193977, 1693724312, 497384180, 1592766692, 3814767396, 496551406, 761630525, 122738561, 2053011267, 3134192635, 3959716126, 756419570, 4291525522, 52995454, 2355566740, 1535344262, 3457101895, 1561710520, 629646311, 1264617650, 1304911374, 3953997387, 101220699, 606111922, 3169531883, 119225490, 2099572326, 3662568011, 2701978464, 2354203828, 3024227856, 812859784, 3907484219, 895862916, 2367636279, 3049608863, 3534493707, 303599528, 235895898, 3152156937, 3282734021, 2504903737, 3347451841, 105947633, 2602282968, 2091238035, 1697885061, 2125538933, 1538362896, 3260245263, 4185444552, 1173878884, 860722873, 4135695975, 3027742222, 4045316121, 684087923, 2221029460, 2175787664, 4254578535, 1093169950, 3230867467, 1521099406, 1031502141, 3310189672, 2767979128, 3491264110, ], ); // - n >= DC_BDIV_Q_THRESHOLD in limbs_modular_div_divide_and_conquer_helper // - lo < hi in limbs_modular_div_divide_and_conquer_helper test( &[10; 369], &[ 926256687, 2852364395, 3370590143, 2584805050, 1597100583, 529558289, 126580396, 4262060268, 1358185452, 3688826498, 2880947234, 2448955814, 2642826080, 1444415359, 2262174529, 4252876126, 1546829518, 1026350339, 461104688, 3572581738, 1379301297, 1469000044, 1232904583, 1130621172, 3414532348, 2076979854, 415474734, 138424304, 2741622037, 1356956847, 3700037198, 3056382371, 4003358430, 4114290085, 2632329664, 2757229707, 942973054, 2844466602, 2536850025, 1562205098, 2369019562, 479441879, 1133122146, 3033404131, 799055770, 2801165147, 333840674, 1266456054, 3826844211, 2394399329, 1580344224, 4208515641, 3938843492, 2943006000, 3095897464, 3657696853, 1895017685, 1174400257, 856895147, 2769847676, 2637358396, 4211838346, 2677238745, 3116142044, 2687432725, 1110573568, 933169252, 2112520496, 1203633399, 706652780, 1876380535, 947010911, 2311376766, 3912635689, 3738597172, 2407075297, 1150178856, 332957826, 2061573893, 1936087771, 2146544892, 3812143813, 4006647140, 1808470881, 3639090995, 3102762721, 3422984617, 3555513955, 3249465976, 4102963672, 1077718033, 2477507069, 1259888894, 1319895809, 2840602832, 488930783, 280413795, 1714984325, 906714553, 4044121361, 2834701307, 353693245, 630667692, 714081891, 689252325, 2538920747, 1229220355, 1965412395, 2366311709, 3490987487, 4244144248, 3004878982, 1934198881, 3439419469, 584060055, 3763445399, 1754985895, 3426861913, 3852827741, 2905990235, 591028154, 3955620274, 2446523634, 2269181228, 2155869554, 2785380931, 1067038528, 4226586573, 938767979, 3463341351, 729920782, 3672068894, 3277213230, 3829428878, 78609376, 2725264455, 1334526325, 3852128883, 83033112, 3171538426, 212483737, 1705821676, 4130869601, 985721852, 4137618486, 3647946653, 2078761135, 2033567134, 922945141, 2842773827, 2731090851, 3725966427, 346163520, 620359799, 2807835138, 4251526149, 3329030547, 1785319896, 1412060986, 112477766, 2463195081, 2269604331, 1667556850, 3069673827, 2451159887, 3531154947, 859465533, 797558571, 2402685684, 1938998432, 3367592143, 1855629490, 415564883, 1771525305, 2108262482, 878332057, 3591804465, 742811660, 2001773684, 869241071, 3406728833, 4240156422, 1145567809, 1952848548, 1700151067, 95712656, 1166986301, 2821041275, 1639679488, 836739412, 159195524, 2990285642, 1385013141, 4175880469, 612922039, 172085215, 403018883, 954336314, 686090551, 1892450280, 3747619613, 4144413437, 2234712194, 2339662600, 2244879528, 1753875098, 1838725682, 3357280280, 2192624967, 91122545, 4248769883, 3595273608, 1004650549, 3206549498, 3722330732, 2319766803, 3308299148, 3660385401, 1984746697, 2537428039, 837529793, 3423459313, 3380318451, 3600361999, 1289811131, 2814141705, 1934106458, 1264409971, 2339500232, 2513439371, 628923995, 161098739, 97046111, 528398469, 1351706370, 2700997745, 3433492154, 3705626784, 2281353606, 2351376214, 78178014, 4256447668, 2755024441, 1600945286, 2135856519, 2332322194, 1336372796, 924574937, 3984145695, 806549767, 1455952508, 1602006824, 1992184377, 175977061, 2976584306, 1501249388, 3211774572, 2177299115, 2436808205, 1296153861, 1528208726, 2086869059, 4256091310, 3359280803, 3794379308, 2845006300, 3370727254, 4191386263, 3868923083, 4024786060, 3356572949, 1309623451, 3404587756, 799637471, 2539690724, 3538256419, 1789660732, 993651510, 868809315, 4070903506, 3500550366, 3537383550, 3000705462, 2011729323, 1276336091, 3715263489, 3856442137, 3078455161, 2394585974, 1731395403, 209285071, 4286415453, 3634201569, 2714865379, 3923934404, 1590322431, 2827746455, 4104930505, 1849053889, 1110373541, 2098826577, 3752273612, 1449873597, 1543844883, 3523617712, 4278529692, 3074073157, 32217677, 2222114104, 1507299609, 4254234641, 619965639, 52325523, 2586116737, 3828937288, 841926627, 3927959971, 1429216471, 4078179238, 4166937366, 964935962, 846542155, 3665864344, 1340829030, 3980686425, 1463832311, 2710331305, 4041927928, 287911129, 1092730462, 1712349041, 332408781, 721925455, 3228519043, 2399858087, 1126502586, 1239406845, 1890441075, 3602881664, 1720394596, 1136141449, 2550451241, 2108470819, 2381224270, 196743147, 2289453443, 3352746316, 1442822225, 195272465, 1977411238, 619069892, 1120443118, 2367263780, 2339580211, 3244857684, 413188862, 3648382353, 1866426486, 3275669837, 714860356, 2503398064, 3520234361, 2602261672, 142956137, 3457786845, 1647737711, 3596429731, 98035229, 2134549817, ], &[ 288812247, 1867980581, 1784848883, 3719376405, 891732341, 4042694263, 2315971843, 4173934812, 3724384121, 3438649023, 817688419, 3717708150, 392002651, 1406301870, 3000223143, 3208696401, 3333344771, 2069472443, 2868745797, 2276970520, 4200672618, 4286576728, 3178657413, 2709499760, 3528379042, 37056359, 713896147, 1464335286, 999714577, 4261103320, 2842057702, 532870143, 318250036, 454191633, 3585978181, 3853346096, 232386666, 4153228123, 3001669262, 2644858239, 1372523035, 1638844646, 221021648, 2633701374, 3889749815, 3749206185, 2682504994, 1691062985, 1564838714, 2021047227, 3653939067, 375766416, 1676298932, 1632585265, 1987642618, 3216589770, 2139352178, 3531691061, 3135733087, 2974439634, 3240759359, 1441918073, 2963546690, 956474789, 1010096752, 3295505885, 1556487598, 2763009589, 2181664193, 3830580006, 567013630, 1792629848, 3395572099, 3047782274, 849031602, 3372175233, 1238500612, 3602622896, 1224295906, 514205489, 615596822, 3650298487, 3835144940, 4230075746, 3563666002, 2171604008, 3860998558, 4030801816, 1966076533, 534702268, 4096165465, 118025721, 3217620626, 1281269306, 2026131743, 1083491983, 2634322198, 1319079531, 384610271, 343671134, 1924283281, 4110082962, 1035723460, 7922039, 1864294974, 3433501319, 612818706, 2074478411, 430050897, 347224817, 3689916278, 431159468, 2396947295, 2216850314, 2873958193, 1052280319, 3807224736, 3366982378, 445016867, 801857639, 2770754059, 2166713172, 2421080783, 4293281425, 3315144969, 832988729, 3203751531, 60602646, 3435936620, 2013384606, 3375674785, 506953530, 4135169500, 2547839556, 1670695010, 2532819097, 1595078260, 1906874739, 4140805961, 909986610, 1450206000, 2416600358, 78210121, 2461045671, 3017469740, 1248552863, 2491666236, 3529749845, 1306097619, 609634854, 1618830814, ], &[ 2153621097, 2032975874, 1092283530, 2105499851, 2772147020, 797232604, 4197023255, 2316448335, 231339989, 790127543, 2827859807, 3740953002, 2953654149, 4028925052, 890100763, 944013012, 3074009738, 2799155639, 1581696516, 421616097, 2763522161, 460382413, 3452929191, 1491944014, 1268408485, 3706732519, 987986692, 1185168616, 312846948, 1736211677, 4257673428, 3728427015, 3445998410, 2787875431, 2693980376, 2270279443, 1915043797, 4081500771, 22182374, 2602808921, 4089111581, 316485891, 1787500084, 2286785318, 1422270801, 799485298, 870038934, 2055189464, 3431348353, 2777540456, 426645251, 1311005497, 3234663366, 540942104, 1278767054, 3141018165, 3997602571, 3885692388, 2906279738, 1880065873, 701408818, 1624620668, 2502792336, 27895058, 3449141668, 731396337, 2025748336, 3252039671, 2316581185, 1576067456, 959043581, 4043904286, 3885331851, 1432462822, 3531781850, 3866289759, 1120305997, 421733220, 2095656685, 306908537, 1829908494, 3026950391, 2753364951, 2446351196, 3811823100, 2096821518, 2024511440, 1827913918, 540355707, 1677071333, 2189975772, 1140077230, 2361607088, 3292807914, 1616778383, 1428264564, 4185564524, 4078951710, 3050933070, 1900914292, 1656040826, 4169852007, 3654163666, 459884159, 1142386374, 2092770650, 4093216198, 3297930392, 1585102456, 2240909415, 2977419294, 1424884171, 3131984332, 3677770202, 1103210323, 3732259374, 3405359572, 1239187170, 1233825656, 1171077559, 3166656449, 3557574007, 2517986752, 298018080, 64725485, 3157564402, 1895722919, 3711770814, 2165944903, 4108826234, 39205698, 3297059852, 2709772591, 3472388897, 1795079771, 1014084034, 1690969319, 188496797, 362199350, 1538080346, 3295087220, 3035112492, 860797619, 2138464630, 893193827, 3209353152, 1892791880, 3956061449, 2582762448, 123764390, 3853335455, 1109119369, 2810579875, 2557150328, 194723070, 1511406773, 308580645, 1506805209, 3800717643, 1154701911, 3327639678, 1742392333, 383847505, 808485729, 1107933974, 1843546476, 3160127489, 461019178, 2758534633, 3136176283, 4161349001, 1122667843, 529002233, 1756067056, 610266011, 868502089, 1924153935, 3733910978, 2089140891, 2010741130, 1699263293, 1974321295, 2337744872, 2401421411, 152242715, 1841948095, 4080892494, 3557450617, 1648335241, 1739529953, 1965700723, 4159737024, 1826643625, 2624044999, 2662463178, 1453688703, 2373328295, 1284900613, 166103125, 2950850796, 224937865, 2363667655, 1395721930, 1038140390, 2227351547, 4027728456, 2456853028, 3392407547, 3558026617, 1022960493, 324320014, 1741363959, 665626647, 1989801844, 1039225187, 2749242260, 2891585679, 413980454, 1421911978, 542423805, 1198826717, 3829692439, 2424493878, 1743568705, 3904138435, 957436945, 3380949485, 3874828753, 3764048544, 2784271009, 3709257819, 2420168014, 2258006234, 1818204898, 4293192208, 1516897791, 4231562984, 1087919881, 3298788303, 409554742, 363790612, 1163362152, 1851768229, 3036249655, 1304207802, 2757649751, 1345091600, 3980437826, 845106654, 1191417084, 789417113, 3069537799, 4128120253, 1724644264, 1850762321, 440075901, 3081463549, 3296565609, 880610907, 3604815503, 825119004, 662787316, 2065720314, 1905930059, 3158622573, 2441285185, 609976312, 3214173289, 1972737948, 1856923900, 3881955749, 147509891, 13256522, 480264715, 2304077206, 4079499728, 1733454240, 683301825, 2067789682, 357755971, 4064960581, 880616108, 2567161687, 2143724680, 295233846, 885328588, 3528678059, 2821762581, 438733817, 1651128958, 266078579, 389905061, 451514054, 1632102041, 3121845303, 1370227908, 2165682378, 4205795758, 3678759448, 3760360877, 3616397292, 3496735510, 2181567729, 1760479516, 2226441722, 1169335764, 1685289328, 3980766219, 584449244, 1198456230, 3262408896, 3506319243, 3461775774, 3985269650, 4207509002, 2496174343, 4246361431, 2525595216, 505792351, 694109202, 2532334608, 177977694, 3590514888, 1386331403, 3322919897, 3677035627, 1748970524, 2355331384, 2803452306, 1684779748, 431295285, 2720257929, 1349292466, 196319200, 721926885, 2699941953, 2509363172, 2856348470, 971658703, 3158854173, 648569495, 806886112, 894065939, 1809981633, 2207773884, 2422134450, 2395969450, 154939100, 2258690857, 1558269103, 3746056343, 3625500344, 1655744570, 3783968316, 2684172985, 1026377946, 2668609092, 3087350250, 1696799137, 4172271775, 2172265355, 1009592900, 3751494892, 1102570367, 728659538, 896138123, 62660027, 2953563063, 2225405012, ], ); // - lo == hi in limbs_modular_div_divide_and_conquer_helper test( &[10; 130], &[ 3959967020, 604241247, 1023896993, 1094415464, 1559137023, 2965982948, 2156029102, 1706771649, 894030132, 45266116, 3024397174, 2788172395, 890061141, 3642398662, 2446922996, 2040815673, 4240388236, 3527485030, 2696135743, 1863211571, 4250621960, 2587213674, 4041734617, 3833321094, 3255910635, 1391342501, 405445752, 1166990562, 3729755900, 3449768038, 3995921119, 41398076, 589125403, 1408294985, 2526515658, 979087391, 1829542521, 2584013937, 86635251, 3289463217, 1129003160, 4215486047, 2533366306, 2464115291, 3785087535, 2492911607, 1526230004, 1102360497, 3665011293, 2884421895, 324933681, 708889365, 377966516, 1925322820, 2718776900, 3007014420, 2694491006, 64698980, 2283839644, 3204232940, 897214742, 3983354864, 1516406610, 4133557944, 2175029320, 609379471, 564247587, 683039961, 1804280416, 4145184207, 4080873242, 3101363732, 4184296551, 3096748957, 1158225507, 2896147906, 1844344520, 2528253875, 2002410714, 265589879, 3121801985, 3170049206, 1924743552, 3357216142, 1965153305, 4252960808, 2092345429, 2837817119, 4284431393, 4293590240, 654671346, 442937916, 1896790019, 691824410, 525764843, 1906879578, 1441648208, 101533739, 1634254350, 3353889676, 3656414560, 1273785308, 3544127466, 3459937121, 870751892, 1042879338, 266055738, 1555417213, 1241879745, 1883960373, 1942927191, 1838179445, 1068713063, 2025583273, 531467322, 1876253978, 3303292405, 414426425, 1511200112, 4106411687, 3527482414, 1961626864, 2704598906, 3866316252, 3265850188, 3581763702, 1084651282, 3286715315, 3240494590, 2037895289, ], &[ 831013375, 20762440, 1023050464, 2893474254, 1340969251, 2523392356, 3059428058, 4273516901, 733612744, 2348114766, 527881926, 1821776884, 342733126, 533682011, 3273669965, 3813354237, 730319485, 3494597442, 3842303180, 2653483407, 1439592834, 1040222095, 4178562882, 3903858398, 1448880503, 453957758, 2591332887, 1627251265, 3845154845, 2189626142, 2509689197, 1600458471, 2116253912, 567231261, 4265711834, 4030352409, 1804529170, 4286478946, 2730794561, 4214016930, 265468824, 1147813206, 1770605310, 3394893197, 1654160857, 531943003, 32521814, 4040486896, 1507001215, 3704501969, 651705156, 969516949, 24702145, 1664997108, 421558584, 372837233, 1254072677, 531592109, 3829378883, 2113868005, 960337326, 3547746167, 1987930996, 3779916457, 3178987148, 2246813569, 111988945, 2002604914, 923221962, 1220517471, 3875731717, 456825253, 4034876422, 444954392, 2767163540, 2138086216, 2109913076, 4089697693, 1989588591, 1122017014, 722640034, 2406717790, 980978606, 3956008296, 1092718561, 396048014, 3434190160, 3721687760, 980653819, 2134907925, 1119974854, 3412876362, 3043790819, 185604051, 2832132094, 3655349262, 2911925829, 377462795, 2359250992, 3598561591, 1539340059, 4033418662, 2214700100, 3039512018, 3007111049, 4215728089, 2804550486, 3578434606, 227455404, 265376688, 2221211195, 1024077580, 4234081405, 2702795924, 1578634809, 696069720, 1613277316, 1828976876, 1070942553, 2681872839, 2525247432, 352687185, ], &[ 2214746836, 963790571, 514240474, 3287959011, 3633281888, 331145186, 2070936355, 1275814903, 649598638, 4048580142, 703307156, 1012761762, 1604206100, 3671704900, 1413149070, 1684128911, 3864334051, 3517749930, 404335570, 3003402025, 300542403, 3126191669, 3699252803, 1439364308, 4192415949, 1299197928, 1611984161, 2452019244, 1490517426, 3629863277, 2995875193, 4190690602, 3357095237, 2125051168, 2745878491, 133070914, 2983910851, 2032579934, 3884117502, 2707418796, 147936035, 2807568299, 463241876, 2904771792, 974710149, 1446026448, 1012503772, 1241584448, 1218926543, 22512568, 3540164426, 3704594926, 1675610321, 4283065258, 1692490953, 1496989584, 1037241778, 2303280516, 3682225212, 1739214044, 602765408, 4279069132, 4056574424, 1288231393, 2447355568, 1822142590, 2659661918, 520518691, 877252364, 1172314748, 2143580045, 2927546685, 1702611733, 3329775201, 265548959, 2886036575, 982951504, 1898736712, 1808101939, 1001715132, 988772812, 3415931945, 3156345141, 2590276172, 1147813273, 1551504667, 4036713818, 2703846994, 3378891303, 3501124044, 3973617807, 2147277907, 1948408686, 3297628811, 4200352081, 73680938, 2715396127, 809994587, 819313279, 2649935820, 3358862368, 3764689552, 1229451982, 3158810723, 1613280893, 2296459508, 3037083750, 2496650271, 814520391, 1890901501, 2263419075, 880319244, 571981604, 4091474119, 4150388764, 3742405101, 2249427916, 4175082452, 1674645979, 71011260, 2431119031, 1958098093, 3007232024, 389827510, 355733904, 3385289187, 3022974738, 3499817070, 70324044, 1955894168, ], ); // - q_len >= DC_BDIV_QR_THRESHOLD second time test( &[10; 136], &[ 1635505187, 367942507, 585747625, 3259895362, 2551559511, 2891390854, 210701094, 253381911, 741016565, 1562764630, 647253529, 995079955, 1415112766, 1121555269, 3264386894, 1432983665, 3084492729, 4197513843, 2107932479, 911748961, 1669179905, 3062572274, 160542021, 1653853504, 3878824697, 4044369261, 1986777757, 3535266551, 1866910827, 4275901664, 354208268, 1288584384, 2863182224, 1221901169, 1253657528, 592130239, 3568722156, 2486101902, 483424561, 1575660483, 720736121, 1101685031, 2565922629, 196632433, 1033148213, 969310472, 1995520702, 3260631554, 1562557993, 45802047, 949951688, 3295028866, 2613836943, 4061881640, 2210607847, 14248080, 1604642540, 3576146202, 1838134557, 4181752638, 2414843751, 3325579689, 2902708971, 2230053926, 1716268270, 3844071486, 3423382254, 2254614074, 234521767, 3030206003, 660556467, 4001187396, 3773254173, 2953162211, 943562247, 2352566705, 3238995051, 2513628232, 1645194089, 4221434207, 298778061, 1395231701, 3223314097, 3370303237, 1905903471, 1408845004, 3916893951, 3646732666, 162038877, 1235325374, 1651995328, 4159903692, 716366148, 2592723919, 2588428010, 2841918047, 2236491801, 1439600422, 268691456, 2330191766, 371571121, 2510936837, 1992243115, 888863283, 68281559, 2527602368, 113695533, 2735585253, 1909150691, 1102365183, 1743094105, 2335719272, 958887136, 4011105869, 2588799839, 630693297, 1764561812, 4102816119, 1751306966, 3347952786, 2985949642, 2087233415, 4171910514, 4184815114, 2269683542, 2467143008, 2240451464, 3865437579, 205000839, 537874053, 1119318572, 169965588, 2947313176, 862816324, 3987040697, 1222400428, ], &[ 3139654297, 2963323009, 2614026787, 2578421476, 2191104461, 2624045036, 3640460632, 1417210598, 3126930163, 1027257221, 460590703, 4066457807, 3459488871, 576203252, 1688476041, 2466961360, 1837547601, 376220531, 4141413316, 1803893809, 1761371554, 3478953436, 130868688, 3859844778, 2980999350, 3309259618, 1059925822, 2182828747, 2005291310, 4234145897, 1408307661, 3344594438, 3438553526, 2363099253, 2188599822, 3464723571, 1041189464, 1746045537, 1958228487, 3752307692, 303751983, 1642664874, 131752811, 1640394963, 2637801305, 3516563951, 1933714212, 1737019176, 2450206053, 503586131, 126392718, 2688144827, 1242477456, 2295392334, 466349000, 2569462004, 1318597067, 1300781532, 1655398676, 2050075490, 3903849354, 3120503464, 171096473, 29581654, 3447431964, 832547958, 3444142819, 3539975343, 4114704783, 521462868, 251982313, 1371581103, 3750111566, 2076014585, 988831298, 3885431509, 2528566949, 1332909323, 41017395, 250182185, 190467400, 477317824, 3346975325, 1469734194, 3287617291, 1797244834, 3716306921, 3132805196, 4130477334, 931614979, 4159691979, 2278615012, 3033894917, 953086932, 887198557, 3075690000, 189881536, 2562655208, 2340948573, 1756155681, 1434962210, 1786798745, 2696354320, 466230606, 265495223, 3772572252, 4060091719, 4091929587, 2602735823, 3377510257, 285339272, 1093341111, 1082532166, 1615653819, 2657481369, 1946488895, 3281845888, 8959603, 969779240, 3948725158, 3119648217, 4059928239, 2639117089, 715898173, 3730038209, 2531002727, 656254619, 4082370365, 4254910891, 2266367871, 2845947517, 91542353, 988318600, 2012804020, 2917139165, 2687206014, ], &[ 344182299, 3565607671, 1425615408, 3688127580, 932395430, 2078412097, 712144307, 2579135290, 1670334397, 3526571898, 527889915, 1847317444, 3706898982, 1670379914, 3028965264, 1454573587, 1233674887, 1842735039, 673704170, 2755491011, 3144215569, 2844132685, 3976352845, 3704439681, 2871494744, 563225203, 477319433, 2394374187, 3361238262, 4097585783, 2091409235, 2989027616, 251393985, 2038664131, 1900105723, 2726074037, 3903048322, 601506890, 4227623429, 3732979811, 2904090093, 3911663358, 694119437, 2312158283, 3761860359, 1226110613, 2077730233, 2543223326, 3098049773, 3187544264, 3680092572, 3815125216, 1990113409, 382920264, 3200154083, 970587848, 1032771863, 1792989867, 408437052, 2035811594, 2495259018, 423722523, 3044771958, 1864896105, 2129868689, 188726050, 1810624947, 1128856008, 504663759, 221476670, 3718864116, 2197791369, 288158522, 1522677473, 4187008757, 3299027054, 3045833372, 1408455415, 2175274137, 54848700, 3470586256, 2721864863, 3804754388, 1239548951, 3301368160, 982306786, 3770156486, 3880485126, 2829505820, 2147636394, 2199815955, 3505488481, 1942842807, 1772747693, 4108779241, 2096541274, 930806315, 421709313, 3631892223, 1621500079, 1514788551, 2479798345, 4264484840, 4155460021, 258059056, 2718683630, 3598111667, 3304295306, 3429094861, 516349540, 2653253840, 1683537378, 3529770422, 112780533, 2171129104, 167784124, 2755669738, 3293537875, 3629382442, 614431521, 657960320, 376396606, 4098436288, 822064619, 226101057, 1630664330, 10604005, 2512924628, 3388389178, 3002235032, 485512099, 1009076950, 1391753479, 286560938, 1910351313, 2438028481, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_divide_and_conquer_fail_1() { let ds = &[4]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_divide_and_conquer_fail_2() { let ds = &[1, 2, 3, 4]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_divide_and_conquer_fail_3() { let ds = &[1, 2]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut [10, 10], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_divide_and_conquer_fail_4() { let ds = &[4, 5]; let inverse = limbs_modular_invert_limb::(ds[0]).wrapping_neg(); limbs_modular_div_divide_and_conquer(&mut [10; 3], &mut [1, 2, 3], ds, inverse); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_div_barrett() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let n = ns.len(); let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(n, ds.len())]; limbs_modular_div_barrett(&mut qs, ns, ds, &mut scratch); assert_eq!(&qs[..n], qs_out); assert_eq!(&qs[n..], &qs_in[n..]); verify_limbs_modular_div(ns, ds, qs_out); }; // - in limbs_modular_div_barrett_same_length // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_barrett_same_length test(&[10; 3], &[0, 0], &[1, 2], &[0, 0]); test(&[10; 3], &[1, 2], &[1, 1], &[1, 1]); test(&[10; 3], &[1, 2], &[1, 2], &[1, 0]); test(&[10; 3], &[1, 2], &[5, 6], &[3435973837, 3607772528]); // - in limbs_modular_div_barrett_greater // - !carry second time in limbs_modular_div_barrett_greater test(&[10; 4], &[1, 2, 3, 4], &[1, 2, 3], &[1, 0, 0, 4]); test( &[10; 4], &[1, 2, 3, 4], &[1, u32::MAX, 3], &[1, 3, 2, 0xfffffffa], ); // - q_len > i_len in limbs_modular_div_barrett_greater // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_barrett_greater // - d_len == i_len in limbs_modular_div_barrett_greater test( &[10; 5], &[1, 2, 3, 4, 5], &[7, 8], &[3067833783, 175304787, 3481052211, 2770888938, 2968937350], ); // - d_len != i_len in limbs_modular_div_barrett_greater // - !carry first time in limbs_modular_div_barrett_greater test( &[10; 17], &[ 0, 0xfffffff0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 0, 0, 4294836224, u32::MAX, 0x7ffff, 0, 0xfffffffc, u32::MAX, ], &[u32::MAX, 0xffff, 4294959104, u32::MAX, 2047, 4294966784, u32::MAX], &[ 0, 16, 0x100000, 4294836224, 15, 1074823164, 4294565887, 2684338192, 2282854407, 605372416, 3137181202, 4166294690, 3073446262, 77886964, 3052808264, 3411277657, 901277614, ], ); // - carry first time in limbs_modular_div_barrett_greater test( &[10; 98], &[ 1642495634, 526967555, 2241173042, 3209550984, 1676167598, 1610173536, 3438803694, 1164362544, 2678449286, 780912452, 2768403743, 2060815434, 3972640317, 2520341055, 592620591, 1203487883, 983093889, 890767242, 57706568, 4116094675, 884607251, 2877607316, 1277464658, 1436231943, 3566448321, 320221382, 3788109081, 1244065662, 1675904837, 2386486007, 3956992595, 319964407, 202742052, 3806969795, 1515593820, 3744019160, 2090003288, 3532996659, 1561167831, 1602116916, 624040306, 162765508, 3520901959, 2560212238, 1836753736, 4193390434, 2748131373, 2815896923, 2183843856, 717268028, 4057685405, 1038000620, 3031926158, 1351486738, 3081828692, 716238242, 2133401994, 4055809448, 2426834827, 42249556, 1437875081, 2953322847, 3372525974, 807912434, 3231438580, 1532794318, 2545826975, 3083637183, 581139768, 2339238221, 1475394016, 3592198406, 2002134106, 444657767, 2223944228, 1052336361, 284385712, 2716809682, 457871403, 257228149, 53492436, 3918756724, 902759153, 2804665433, 3072525061, 1179183759, 1583887668, 2221275350, 3084717885, 3234652545, 2379337844, 3543607479, 1728198647, 1630260072, 2895054954, 2533669171, 1060868412, 547908407, ], &[ 14618623, 1746469986, 3422287375, 4133184481, 1570537644, 4262126259, 2806378130, 3961348569, 2005535219, 3128034624, 2629791421, 2581513752, 3943557466, 4294487356, 2073524094, 2453727247, 3583353645, 1921128531, 3406066844, 1698548606, 1946999159, ], &[ 2734842222, 2285689435, 3313291574, 144014201, 4220859605, 2950326491, 2357784357, 1586509685, 2832228486, 1607316550, 280781708, 4284905083, 511390653, 1180279956, 1018877648, 2593613350, 2120941422, 3139501780, 905043699, 3767548899, 580952750, 2178827242, 2551200564, 983629603, 884994054, 211841976, 2433402391, 1021212454, 819127040, 1904972730, 3433697954, 3446961599, 2967793385, 184760660, 4258736086, 2575421315, 3702982944, 1090206528, 738361131, 1464668514, 536747506, 1728476312, 836227767, 3720425025, 1632791665, 3046719088, 3289636949, 4151602118, 3854618415, 3416186138, 83311182, 2337871634, 3256616827, 250345345, 4152926648, 1505633136, 1983549218, 3590016829, 2141100866, 3890424583, 3192188136, 3779057143, 3508994270, 4056653461, 4016652469, 573993530, 498142680, 2568576590, 3123744761, 893793360, 3037437361, 2515586057, 1419850307, 2367351324, 2046622935, 822851473, 550435958, 1715769219, 386202898, 2986510451, 1685332339, 1548081751, 2846757228, 2600333304, 3154407368, 2550424293, 1762563946, 251045310, 2158430157, 2056859408, 1057424536, 2450050482, 2554796526, 3366193628, 4244612028, 1102253197, 3744549054, 521836615, ], ); // - carry second time in limbs_modular_div_barrett_greater test( &[10; 37], &[ 2935526596, 3034554327, 1814238638, 2697925306, 3829736681, 2739165479, 724626090, 604324966, 4252490674, 2065896555, 3890359639, 4148922800, 3007022887, 846622959, 2009383236, 1908685339, 1526530451, 2415388932, 338610665, 3714252276, 2553761603, 3643634643, 496773116, 3423491766, 1075245675, 217851812, 3421283768, 206430974, 1384123998, 1106562315, 3884178146, 2393734976, 3612774482, 3699430895, 1007237140, 4205715447, 842811847, ], &[ 205703789, 2117899933, 1318971308, 3978644775, 3407016997, 1105357630, 1976230147, 4259422827, 1569463276, 1189711442, 3449406972, 1341407674, 423077568, 1572740530, 3866269574, ], &[ 3183291732, 3833024062, 3586222897, 2197803151, 1007086642, 544727792, 1794027376, 3492679295, 555612395, 977509785, 2253915713, 1050562685, 3689706953, 91679594, 965381603, 1030563531, 506556705, 1163731842, 1782685644, 1032462892, 838184086, 2712070683, 101254061, 2126604889, 1455324808, 4284267836, 3246890330, 2786100847, 4292354129, 3612163869, 4255169090, 1705817867, 2385139426, 3288783439, 280839878, 1415086525, 3673678347, ], ); // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_barrett_same_length // - n_len + i_len > mul_size in limbs_modular_div_barrett_same_length test( &[10; 69], &[ 2082197907, 3463552973, 3033841621, 3293308755, 1318302421, 924962436, 4055211147, 3066037067, 189854397, 360674525, 270528549, 1824708088, 1848896300, 2009286050, 1723092285, 1962202393, 1691706400, 1228277495, 2169116062, 1340789312, 2688811811, 2948615768, 3930757643, 232970699, 1674295859, 2771170263, 29024924, 4025863949, 2350200807, 1685576833, 1697147461, 3283768071, 1970079668, 2868576138, 4067067287, 2755619479, 1433554174, 570418866, 4193378147, 56846214, 4010333403, 99500968, 594166316, 2103126565, 3797481093, 1835813191, 3717816485, 1427301989, 2602454977, 2725793563, 4164737951, 1352512745, 3416783056, 1623413593, 3064676881, 1724024701, 130815055, 1736837714, 2687511206, 1192745823, 63300791, 2476521677, 2332269618, 139603363, 1232593938, 2211955807, 1536891080, 1717467933, 803195014, ], &[ 571177489, 4171067636, 130205627, 385002762, 3710389308, 2495334077, 2555702128, 3776766701, 2374702786, 4018024315, 3321371413, 1939382625, 1735826724, 2610501056, 959471237, 3348497660, 3584321092, 3397401589, 1458021574, 3693295416, 1782750542, 2587986675, 1266401498, 4096921279, 1864600357, 3704089229, 3712721011, 2510009154, 1625100953, 2753044802, 3523244715, 2048819457, 1999850617, 1841193902, 1889118279, 2552563105, 37156074, 382481471, 4065787580, 572345799, 140984432, 4192479401, 1924809764, 1459787400, 2966035238, 819250523, 1301397292, 2037545391, 1858919076, 1830995686, 1796776602, 1566339969, 2002295704, 3651240066, 2475237044, 904307699, 3991071672, 1874129794, 4232916985, 755030924, 3876937220, 3359171346, 2215460812, 1717512044, 3462640226, 1416735647, 2825930507, 1273943241, 1501109004, ], &[ 3324824931, 3285501135, 2080039886, 1363439285, 4216289514, 170135702, 3339034566, 3206256933, 2049361690, 3880142493, 2355736055, 3496015895, 269070856, 3612458995, 3874254584, 2792128956, 3736657578, 2652084650, 3367020175, 1255915505, 1207914599, 3301647744, 3872751597, 1044752670, 4048018730, 1158138599, 46279244, 374848909, 3803666978, 1097388174, 4125010214, 3492963129, 3793628443, 1566031349, 1950072987, 3983338264, 2373811991, 3106070941, 3871479066, 2857657266, 1820484444, 1815087675, 3736927857, 3638157771, 1043782805, 1853270968, 2202072929, 2227928131, 1445478612, 4065556003, 1988319175, 1719054009, 2654397327, 263746738, 1572373639, 349867437, 3114446163, 1211887713, 951929852, 2733483965, 4117156940, 2770305201, 3589296114, 83156101, 1563034919, 1982884392, 689027156, 3848414016, 2735835897, ], ); // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_modular_div_barrett_greater // - d_len + i_len > mul_size in limbs_modular_div_barrett_greater test( &[10; 369], &[ 926256687, 2852364395, 3370590143, 2584805050, 1597100583, 529558289, 126580396, 4262060268, 1358185452, 3688826498, 2880947234, 2448955814, 2642826080, 1444415359, 2262174529, 4252876126, 1546829518, 1026350339, 461104688, 3572581738, 1379301297, 1469000044, 1232904583, 1130621172, 3414532348, 2076979854, 415474734, 138424304, 2741622037, 1356956847, 3700037198, 3056382371, 4003358430, 4114290085, 2632329664, 2757229707, 942973054, 2844466602, 2536850025, 1562205098, 2369019562, 479441879, 1133122146, 3033404131, 799055770, 2801165147, 333840674, 1266456054, 3826844211, 2394399329, 1580344224, 4208515641, 3938843492, 2943006000, 3095897464, 3657696853, 1895017685, 1174400257, 856895147, 2769847676, 2637358396, 4211838346, 2677238745, 3116142044, 2687432725, 1110573568, 933169252, 2112520496, 1203633399, 706652780, 1876380535, 947010911, 2311376766, 3912635689, 3738597172, 2407075297, 1150178856, 332957826, 2061573893, 1936087771, 2146544892, 3812143813, 4006647140, 1808470881, 3639090995, 3102762721, 3422984617, 3555513955, 3249465976, 4102963672, 1077718033, 2477507069, 1259888894, 1319895809, 2840602832, 488930783, 280413795, 1714984325, 906714553, 4044121361, 2834701307, 353693245, 630667692, 714081891, 689252325, 2538920747, 1229220355, 1965412395, 2366311709, 3490987487, 4244144248, 3004878982, 1934198881, 3439419469, 584060055, 3763445399, 1754985895, 3426861913, 3852827741, 2905990235, 591028154, 3955620274, 2446523634, 2269181228, 2155869554, 2785380931, 1067038528, 4226586573, 938767979, 3463341351, 729920782, 3672068894, 3277213230, 3829428878, 78609376, 2725264455, 1334526325, 3852128883, 83033112, 3171538426, 212483737, 1705821676, 4130869601, 985721852, 4137618486, 3647946653, 2078761135, 2033567134, 922945141, 2842773827, 2731090851, 3725966427, 346163520, 620359799, 2807835138, 4251526149, 3329030547, 1785319896, 1412060986, 112477766, 2463195081, 2269604331, 1667556850, 3069673827, 2451159887, 3531154947, 859465533, 797558571, 2402685684, 1938998432, 3367592143, 1855629490, 415564883, 1771525305, 2108262482, 878332057, 3591804465, 742811660, 2001773684, 869241071, 3406728833, 4240156422, 1145567809, 1952848548, 1700151067, 95712656, 1166986301, 2821041275, 1639679488, 836739412, 159195524, 2990285642, 1385013141, 4175880469, 612922039, 172085215, 403018883, 954336314, 686090551, 1892450280, 3747619613, 4144413437, 2234712194, 2339662600, 2244879528, 1753875098, 1838725682, 3357280280, 2192624967, 91122545, 4248769883, 3595273608, 1004650549, 3206549498, 3722330732, 2319766803, 3308299148, 3660385401, 1984746697, 2537428039, 837529793, 3423459313, 3380318451, 3600361999, 1289811131, 2814141705, 1934106458, 1264409971, 2339500232, 2513439371, 628923995, 161098739, 97046111, 528398469, 1351706370, 2700997745, 3433492154, 3705626784, 2281353606, 2351376214, 78178014, 4256447668, 2755024441, 1600945286, 2135856519, 2332322194, 1336372796, 924574937, 3984145695, 806549767, 1455952508, 1602006824, 1992184377, 175977061, 2976584306, 1501249388, 3211774572, 2177299115, 2436808205, 1296153861, 1528208726, 2086869059, 4256091310, 3359280803, 3794379308, 2845006300, 3370727254, 4191386263, 3868923083, 4024786060, 3356572949, 1309623451, 3404587756, 799637471, 2539690724, 3538256419, 1789660732, 993651510, 868809315, 4070903506, 3500550366, 3537383550, 3000705462, 2011729323, 1276336091, 3715263489, 3856442137, 3078455161, 2394585974, 1731395403, 209285071, 4286415453, 3634201569, 2714865379, 3923934404, 1590322431, 2827746455, 4104930505, 1849053889, 1110373541, 2098826577, 3752273612, 1449873597, 1543844883, 3523617712, 4278529692, 3074073157, 32217677, 2222114104, 1507299609, 4254234641, 619965639, 52325523, 2586116737, 3828937288, 841926627, 3927959971, 1429216471, 4078179238, 4166937366, 964935962, 846542155, 3665864344, 1340829030, 3980686425, 1463832311, 2710331305, 4041927928, 287911129, 1092730462, 1712349041, 332408781, 721925455, 3228519043, 2399858087, 1126502586, 1239406845, 1890441075, 3602881664, 1720394596, 1136141449, 2550451241, 2108470819, 2381224270, 196743147, 2289453443, 3352746316, 1442822225, 195272465, 1977411238, 619069892, 1120443118, 2367263780, 2339580211, 3244857684, 413188862, 3648382353, 1866426486, 3275669837, 714860356, 2503398064, 3520234361, 2602261672, 142956137, 3457786845, 1647737711, 3596429731, 98035229, 2134549817, ], &[ 288812247, 1867980581, 1784848883, 3719376405, 891732341, 4042694263, 2315971843, 4173934812, 3724384121, 3438649023, 817688419, 3717708150, 392002651, 1406301870, 3000223143, 3208696401, 3333344771, 2069472443, 2868745797, 2276970520, 4200672618, 4286576728, 3178657413, 2709499760, 3528379042, 37056359, 713896147, 1464335286, 999714577, 4261103320, 2842057702, 532870143, 318250036, 454191633, 3585978181, 3853346096, 232386666, 4153228123, 3001669262, 2644858239, 1372523035, 1638844646, 221021648, 2633701374, 3889749815, 3749206185, 2682504994, 1691062985, 1564838714, 2021047227, 3653939067, 375766416, 1676298932, 1632585265, 1987642618, 3216589770, 2139352178, 3531691061, 3135733087, 2974439634, 3240759359, 1441918073, 2963546690, 956474789, 1010096752, 3295505885, 1556487598, 2763009589, 2181664193, 3830580006, 567013630, 1792629848, 3395572099, 3047782274, 849031602, 3372175233, 1238500612, 3602622896, 1224295906, 514205489, 615596822, 3650298487, 3835144940, 4230075746, 3563666002, 2171604008, 3860998558, 4030801816, 1966076533, 534702268, 4096165465, 118025721, 3217620626, 1281269306, 2026131743, 1083491983, 2634322198, 1319079531, 384610271, 343671134, 1924283281, 4110082962, 1035723460, 7922039, 1864294974, 3433501319, 612818706, 2074478411, 430050897, 347224817, 3689916278, 431159468, 2396947295, 2216850314, 2873958193, 1052280319, 3807224736, 3366982378, 445016867, 801857639, 2770754059, 2166713172, 2421080783, 4293281425, 3315144969, 832988729, 3203751531, 60602646, 3435936620, 2013384606, 3375674785, 506953530, 4135169500, 2547839556, 1670695010, 2532819097, 1595078260, 1906874739, 4140805961, 909986610, 1450206000, 2416600358, 78210121, 2461045671, 3017469740, 1248552863, 2491666236, 3529749845, 1306097619, 609634854, 1618830814, ], &[ 2153621097, 2032975874, 1092283530, 2105499851, 2772147020, 797232604, 4197023255, 2316448335, 231339989, 790127543, 2827859807, 3740953002, 2953654149, 4028925052, 890100763, 944013012, 3074009738, 2799155639, 1581696516, 421616097, 2763522161, 460382413, 3452929191, 1491944014, 1268408485, 3706732519, 987986692, 1185168616, 312846948, 1736211677, 4257673428, 3728427015, 3445998410, 2787875431, 2693980376, 2270279443, 1915043797, 4081500771, 22182374, 2602808921, 4089111581, 316485891, 1787500084, 2286785318, 1422270801, 799485298, 870038934, 2055189464, 3431348353, 2777540456, 426645251, 1311005497, 3234663366, 540942104, 1278767054, 3141018165, 3997602571, 3885692388, 2906279738, 1880065873, 701408818, 1624620668, 2502792336, 27895058, 3449141668, 731396337, 2025748336, 3252039671, 2316581185, 1576067456, 959043581, 4043904286, 3885331851, 1432462822, 3531781850, 3866289759, 1120305997, 421733220, 2095656685, 306908537, 1829908494, 3026950391, 2753364951, 2446351196, 3811823100, 2096821518, 2024511440, 1827913918, 540355707, 1677071333, 2189975772, 1140077230, 2361607088, 3292807914, 1616778383, 1428264564, 4185564524, 4078951710, 3050933070, 1900914292, 1656040826, 4169852007, 3654163666, 459884159, 1142386374, 2092770650, 4093216198, 3297930392, 1585102456, 2240909415, 2977419294, 1424884171, 3131984332, 3677770202, 1103210323, 3732259374, 3405359572, 1239187170, 1233825656, 1171077559, 3166656449, 3557574007, 2517986752, 298018080, 64725485, 3157564402, 1895722919, 3711770814, 2165944903, 4108826234, 39205698, 3297059852, 2709772591, 3472388897, 1795079771, 1014084034, 1690969319, 188496797, 362199350, 1538080346, 3295087220, 3035112492, 860797619, 2138464630, 893193827, 3209353152, 1892791880, 3956061449, 2582762448, 123764390, 3853335455, 1109119369, 2810579875, 2557150328, 194723070, 1511406773, 308580645, 1506805209, 3800717643, 1154701911, 3327639678, 1742392333, 383847505, 808485729, 1107933974, 1843546476, 3160127489, 461019178, 2758534633, 3136176283, 4161349001, 1122667843, 529002233, 1756067056, 610266011, 868502089, 1924153935, 3733910978, 2089140891, 2010741130, 1699263293, 1974321295, 2337744872, 2401421411, 152242715, 1841948095, 4080892494, 3557450617, 1648335241, 1739529953, 1965700723, 4159737024, 1826643625, 2624044999, 2662463178, 1453688703, 2373328295, 1284900613, 166103125, 2950850796, 224937865, 2363667655, 1395721930, 1038140390, 2227351547, 4027728456, 2456853028, 3392407547, 3558026617, 1022960493, 324320014, 1741363959, 665626647, 1989801844, 1039225187, 2749242260, 2891585679, 413980454, 1421911978, 542423805, 1198826717, 3829692439, 2424493878, 1743568705, 3904138435, 957436945, 3380949485, 3874828753, 3764048544, 2784271009, 3709257819, 2420168014, 2258006234, 1818204898, 4293192208, 1516897791, 4231562984, 1087919881, 3298788303, 409554742, 363790612, 1163362152, 1851768229, 3036249655, 1304207802, 2757649751, 1345091600, 3980437826, 845106654, 1191417084, 789417113, 3069537799, 4128120253, 1724644264, 1850762321, 440075901, 3081463549, 3296565609, 880610907, 3604815503, 825119004, 662787316, 2065720314, 1905930059, 3158622573, 2441285185, 609976312, 3214173289, 1972737948, 1856923900, 3881955749, 147509891, 13256522, 480264715, 2304077206, 4079499728, 1733454240, 683301825, 2067789682, 357755971, 4064960581, 880616108, 2567161687, 2143724680, 295233846, 885328588, 3528678059, 2821762581, 438733817, 1651128958, 266078579, 389905061, 451514054, 1632102041, 3121845303, 1370227908, 2165682378, 4205795758, 3678759448, 3760360877, 3616397292, 3496735510, 2181567729, 1760479516, 2226441722, 1169335764, 1685289328, 3980766219, 584449244, 1198456230, 3262408896, 3506319243, 3461775774, 3985269650, 4207509002, 2496174343, 4246361431, 2525595216, 505792351, 694109202, 2532334608, 177977694, 3590514888, 1386331403, 3322919897, 3677035627, 1748970524, 2355331384, 2803452306, 1684779748, 431295285, 2720257929, 1349292466, 196319200, 721926885, 2699941953, 2509363172, 2856348470, 971658703, 3158854173, 648569495, 806886112, 894065939, 1809981633, 2207773884, 2422134450, 2395969450, 154939100, 2258690857, 1558269103, 3746056343, 3625500344, 1655744570, 3783968316, 2684172985, 1026377946, 2668609092, 3087350250, 1696799137, 4172271775, 2172265355, 1009592900, 3751494892, 1102570367, 728659538, 896138123, 62660027, 2953563063, 2225405012, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_barrett_fail_1() { let ns = &[1, 2]; let ds = &[3]; let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_barrett_fail_2() { let ns = &[1]; let ds = &[1]; let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_barrett_fail_3() { let ns = &[1, 2]; let ds = &[1, 2, 3]; let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_barrett_fail_4() { let ns = &[1, 2, 3, 4]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_barrett_fail_5() { let ns = &[1, 2, 3, 4]; let ds = &[4, 5]; let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_modular_div() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let n = ns.len(); let mut scratch = vec![0; limbs_modular_div_scratch_len(n, ds.len())]; let mut mut_ns = ns.to_vec(); limbs_modular_div(&mut qs, &mut mut_ns, ds, &mut scratch); assert_eq!(&qs[..n], qs_out); let mut qs = qs_in.to_vec(); let n = ns.len(); let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(n, ds.len())]; limbs_modular_div_ref(&mut qs, ns, ds, &mut scratch); assert_eq!(&qs[..n], qs_out); verify_limbs_modular_div(ns, ds, qs_out); }; // - schoolbook branch test(&[10; 3], &[0, 0], &[1, 2], &[0, 0]); test(&[10; 3], &[1, 2, 3], &[3], &[2863311531, 0, 1]); test( &[10; 3], &[1, 2, 3], &[u32::MAX], &[u32::MAX, 0xfffffffc, 0xfffffff9], ); test(&[10; 3], &[1, 2], &[1, 1], &[1, 1]); test(&[10; 3], &[1, 2], &[1, 2], &[1, 0]); test(&[10; 3], &[1, 2], &[5, 6], &[3435973837, 3607772528]); test(&[10; 4], &[1, 2, 3, 4], &[1, 2, 3], &[1, 0, 0, 4]); test( &[10; 4], &[1, 2, 3, 4], &[1, u32::MAX, 3], &[1, 3, 2, 0xfffffffa], ); // - divide-and-conquer branch test( &[10; 940], &[ 1617001812, 406941400, 4290122623, 1353643808, 3101415473, 2776366000, 1481378761, 1754925789, 2932070541, 2268599150, 3665046852, 1854806905, 1473093751, 1310246577, 1085278892, 3448341300, 664884543, 894931028, 2986635139, 2227836107, 657956320, 2780373025, 723708052, 3678557934, 205944971, 3639109391, 1410682902, 273368655, 137589532, 2752044605, 212717727, 3792430292, 3119625350, 3784798586, 2990465174, 4284837080, 1139179612, 1590711001, 1736757382, 3899481945, 3054534962, 3715303406, 2871448595, 2613719261, 3519175216, 1742061049, 687836540, 3035159189, 2430146491, 3643811245, 1449733326, 909516982, 4131451057, 3824921017, 1370422021, 2664108177, 2259517283, 1110019077, 2291074089, 3844959301, 2341419713, 1983390487, 2379479711, 3103336479, 3631463561, 4141601545, 3984814009, 2847757328, 925199080, 2677150178, 3932146626, 2585985618, 3097165312, 624553107, 3497399511, 2463155636, 1025776088, 3972587430, 1776770640, 1070718417, 1149088515, 4112473641, 225083923, 3371457763, 2377652798, 2195213316, 3230992135, 2084781295, 2695452223, 2117879824, 920852431, 3418533408, 4371131, 2567093115, 3561201955, 3500513345, 1532361440, 2619974821, 1999143525, 1723126370, 2374780155, 3680488284, 328733252, 1032411542, 1853229941, 2293678997, 3094028501, 2057689466, 732918339, 449235695, 2135519188, 2885118676, 1010648119, 2686289702, 3794769615, 3150457436, 896104974, 1933155926, 3334021940, 944686456, 2364306114, 4136346953, 4200045016, 1969878091, 2569970022, 685844738, 2612152187, 860994125, 3220153414, 2803393155, 981612648, 3042964600, 1071555038, 2816042187, 3876557086, 3346011246, 1146392271, 2817040744, 1510282841, 325681574, 1630649453, 3288209101, 2072179016, 2821749271, 529631819, 4008039627, 3123605697, 3327357221, 1207815414, 2982053815, 4147131056, 1931822734, 353985760, 2963142283, 1073494612, 2091657110, 3979899238, 1802218645, 3796622263, 3071022976, 733595921, 2814034738, 2643673522, 4145539201, 906706184, 1357361031, 2806820925, 924346897, 4024033817, 4170035271, 751396103, 427807833, 1293458142, 825562756, 749911432, 2455906530, 2373035821, 2035314458, 523324040, 74749282, 1449696708, 1969230914, 1493171573, 1513766478, 4210281190, 1335461048, 707211493, 3186784150, 2467802616, 2058950664, 3722342212, 2509828536, 3802882999, 2600271262, 2092219856, 4157404778, 3400786142, 155585754, 652633073, 822626032, 3523591903, 1459099206, 2649574877, 4113736981, 1830792451, 2727586932, 1760483902, 241823374, 2715302907, 2576249518, 3361586004, 726705922, 3486441743, 16464902, 240807763, 1358538485, 4039078491, 1424904458, 2071547645, 3899722875, 3750426231, 2344735245, 1643746205, 491168785, 1384963465, 1750451847, 4078035388, 1770764243, 4052515472, 3241294450, 4243264539, 3310019665, 2887029156, 714075326, 1226997201, 3444729396, 2832779460, 622387501, 3969455295, 2045396250, 393223708, 226908064, 4072524790, 714484882, 1907609400, 3766575797, 478121983, 60272670, 898422298, 32593466, 2569174567, 391827066, 4035751597, 1908938867, 173327883, 2048138818, 230061596, 1242368902, 969448935, 1350957584, 1329847677, 1861496005, 381477284, 2549500005, 44785600, 873742504, 2067021143, 2991092988, 3548588862, 2442888192, 1877980812, 2914948150, 1098468146, 675021252, 3550660795, 705365138, 874024736, 17542161, 2817527888, 3629705143, 3195425797, 2175349263, 759180483, 625046999, 323114189, 2947844301, 3753994875, 2150414476, 3280636325, 148566019, 3393964028, 3188177781, 3019549329, 543709989, 2636840844, 1091743439, 2478470416, 2011975001, 1970347299, 2912238231, 715625754, 820695691, 3922781318, 3776236498, 3442057982, 921595229, 1441760440, 161150259, 1641485394, 1541289533, 3922947949, 3843619638, 3081238601, 3722091136, 1118176273, 621876688, 3997694905, 2566254497, 1508842638, 2833152011, 2269341704, 3805097671, 1910097409, 1778233534, 2629818400, 1928875119, 3415886257, 3654500721, 1162300191, 2855569689, 2679374632, 3480632355, 1697167619, 1916977851, 522312972, 3598627948, 1453501632, 1251971247, 1389213373, 807549034, 3088783989, 3417566420, 2280710564, 3403195199, 2495855004, 932408531, 2331161525, 3778497616, 16187086, 3485533486, 3495411373, 1786709186, 316453771, 1948970731, 2299432775, 3933979962, 4095089804, 379650624, 3914831055, 441554897, 2871518068, 3616069049, 1511616572, 3359750356, 4204007612, 2372585636, 3447071366, 2322506117, 272845013, 2251768829, 219574446, 805900066, 1562309083, 2747023165, 625123816, 3084319726, 1766945764, 730018360, 2396297375, 3185454773, 30578559, 2118564330, 2970233977, 3864914812, 3673919355, 387910790, 3961065920, 1279254859, 606858626, 3226772313, 3128243714, 3607492460, 1703562315, 2007811259, 2317297443, 3003813959, 3582624750, 2460028613, 4007959672, 3387473962, 2321603229, 2634383176, 1530063181, 653942855, 777144175, 3383143429, 2938927788, 152348935, 1627498490, 339085549, 1090554742, 566713397, 2625208878, 3313094379, 3682455164, 825072458, 3450039589, 825880309, 236573086, 225561664, 1245435637, 1331746952, 1353578371, 1858571383, 1507506405, 4248940778, 625956529, 3841763541, 1935501192, 113898702, 1717500961, 1803749553, 3698863369, 922793844, 3945374015, 4243233523, 4250348340, 3804428707, 375844143, 3217202690, 2958736927, 2390653610, 3913327699, 1445233502, 2564009562, 1981762528, 4082411483, 3027869173, 1427382679, 1184126161, 818177569, 3869201961, 3896288494, 2991466485, 3711933803, 569576015, 1555955484, 2471128165, 1976033094, 2785392947, 2319149042, 4011978677, 2965267321, 4102225036, 3477006125, 647674513, 2105038091, 1803927615, 783856168, 1324871043, 3615993255, 3431877321, 3971793725, 3934927792, 2179674064, 1248922540, 743817474, 1502564707, 803921101, 459529729, 3792678523, 2146248483, 4130547052, 3605002956, 3012317918, 4064731802, 4197909109, 4084469190, 1701485661, 3117730821, 972406826, 3210336796, 2256307987, 3848993871, 2176735158, 3781051143, 2680104892, 3305191212, 1603519343, 602901276, 1617518529, 2454120969, 1268075759, 498226963, 260513853, 1438206225, 3423412289, 2731106726, 234808220, 688404693, 1622003954, 1671415587, 4289391631, 2811620618, 1159840463, 856151253, 3940102962, 4048700229, 426530845, 2638052743, 3885492985, 806562813, 2558031618, 2366389147, 826787397, 1423193924, 819474847, 1921929046, 1831867082, 3600381551, 2477872533, 1029143458, 769714702, 2814119928, 4191052015, 1167365455, 2457269908, 975781406, 2087117506, 69469836, 1923853303, 1135113139, 2334628021, 663459911, 3006299219, 538724612, 3334068941, 2700983994, 1073161914, 3486899373, 1634133651, 1157990333, 1503694793, 1267044873, 2540754456, 1496511112, 781068794, 3561760800, 3895331222, 2500281154, 3412563576, 2764489218, 3868392337, 1074848405, 1646812850, 2199258432, 4258601309, 661369302, 874915103, 2014299592, 1949788135, 24892497, 680092321, 146288879, 3655059587, 1166284415, 1703237926, 4235856968, 2990205786, 3631372211, 1168518819, 1358761778, 2444279125, 2533070212, 2255837372, 3511526532, 3043738970, 1234663270, 2988008723, 4269697291, 4118872953, 910125556, 3167731674, 4285191140, 2460574472, 3150156454, 1702113899, 313167013, 3377687638, 3851000034, 2336152121, 3957198339, 1488999987, 3934439945, 654432127, 2247512052, 2811676271, 3497130291, 450665617, 2913226868, 1369911749, 1685617502, 3084648045, 1382681328, 3265795904, 35118333, 2698123229, 3632834581, 1779152731, 2940643214, 3013389545, 134571045, 3077109637, 4216881108, 3149045213, 4287730821, 3037477329, 1627490387, 1543881990, 375058941, 507557878, 2540666574, 2631980166, 487254845, 4018184736, 834259987, 493887543, 3678837714, 4006335571, 2894197190, 444039706, 2250255290, 3658855260, 2692485260, 3067208848, 177991403, 3168488251, 3931497670, 1064352145, 3704612442, 763514580, 2667497882, 2999748217, 1495439415, 231547898, 355122902, 3257752995, 2277957568, 3110120058, 857628464, 2568037394, 142755211, 815281764, 2367800630, 1224636898, 2080180449, 1355348312, 3289292906, 2297669780, 1847374168, 2276368440, 3819739502, 1791466417, 1102305871, 2354766268, 1338112610, 3463874583, 2021767462, 1066043808, 2309743709, 2571990210, 3315672796, 2398059936, 365056733, 3447539115, 3746732720, 3008661963, 3862798665, 2308467583, 1665116459, 1280978829, 3527882851, 3761190132, 671769688, 266901941, 3154667402, 1038908368, 2515820906, 1271818580, 2962093088, 3773575104, 2517853396, 4061725672, 3523770889, 2033488750, 2429531509, 2971035542, 4238011901, 1000531442, 1416882400, 678786363, 1019864239, 2751310982, 442339976, 55517395, 82583326, 1942516957, 3947856921, 722940461, 728206370, 1744336133, 2287954803, 292238920, 3911418046, 2155661057, 4159957990, 887247601, 556462431, 1016030816, 1512907682, 3069626937, 1472354633, 3141549111, 2016546891, 2821933580, 2770752073, 563151583, 221583615, 289067957, 3908737670, 2004753320, 3931101403, 883429785, 3689435720, 2987821650, 28050592, 2735311860, 3265507995, 2758493314, 2655530609, 2545294868, 2470465036, 1271710983, 545536994, 1327776999, 141840027, 1138841565, 1781544782, 3199919479, 681382208, 1245717786, 2930809728, 3280849083, 3956551507, 3355385777, 355999081, 2179057718, 882649569, 1825265258, 1442192351, 3389922361, 1461142241, 1668273192, 1024455283, 1363451707, 3165776423, 1708618405, 3593748137, 553996297, 2695393796, 1317090480, 2473638063, 3722258345, 2520027887, 2083034437, 1575395416, 3095210370, 3995459958, 3484130891, 803033008, 9632350, 3554497809, 3029973822, 706965453, 2956683625, 3768697729, 2368889001, 3579687116, 1507088502, 44440509, 3722401618, 10979986, 1440335280, 360127666, 3537309717, 2881783860, 821182819, 2620792872, 1352001982, 4178426943, 4092532482, 2378352391, 2593011994, 1487230079, 1280656126, 2550113868, 292018470, 3077472516, 3307900686, 3895849291, 1947913132, 636104659, 231356996, 3069426222, 1616111446, 535734499, 4152792010, 3810588916, 594013155, 3342644263, 3876779199, 2365417389, 2541878010, 631827463, 899645198, 1215887929, 2257594209, 3558848715, 3595018839, 2467717482, 368943385, 202032628, 353961970, 189404791, 2740031059, 1445247256, 3111695158, 2430510723, 1636469966, 3085197240, 393496208, 1147559660, 3854034067, 144621988, 901901079, 1157982037, 3309406483, 881900034, 1419066224, 2147885124, 1202171837, 4028375088, 344523185, 4281695498, 2098200318, 4285280344, 830500235, 2819516821, 2402660095, 3347692646, 429942249, 118042706, 2413131752, 1801992999, 1419387777, 917304148, 2405971626, 2514112112, 1486885522, 3561350045, 1391269566, 2312342833, 2165644886, 3237357298, 529810310, 533161912, 573572810, 2388955822, 1839462779, 3595785519, 502068002, 1370445852, 2940004806, 3127248122, 402923598, 942165049, 1322781936, 2267106055, 963050643, 2271136014, 593519182, 997148741, 1007096690, 2862595233, 2455777215, 87788237, 2537341695, 213203205, 3618812433, 934598945, 2019611411, 152516526, 2045476718, 4203041946, 1700636518, 2634288824, 957703279, 438300965, 752868345, 1741551695, 3299805511, 2787468423, 3915443541, 1822431092, 4184623349, 470943777, 3306758738, 2378813334, 887946583, 3895139974, 3274730894, 1775157124, 1716784797, 3766822546, 515029397, 366876429, 3967551838, 2567429723, 1242834401, 3586292863, ], &[ 3316717475, 3755784115, 621265671, 2021086862, 474517724, 1164498167, 2627801958, 2170528742, 3104726388, 2515033406, 1702293156, 20581773, 1429119997, 2801585517, 3698032538, 596509909, 4238480986, 3843806649, 3322888890, 2861086342, 2626735834, 3405303428, 1508735314, 2650558814, 76337057, 1202565180, 2949817513, 3758629286, 1042329346, 3168950269, 883013312, 3720930735, 2244494029, 489190350, 4140126449, 2460687698, 888181262, 1751014525, 1555755626, 2244055025, 763172867, 3257618646, 345848605, 3619012015, 2273117624, 135239042, 1894337682, 2498817131, 351760917, 1230693073, 3288131984, 3614737212, 1133719825, 185344371, 2675805123, 1402914899, 3191767840, 3841311369, 2430249603, 3911615234, 2851144250, 2899717103, 2663597034, 1253013791, 851947363, 3119663958, 3884604595, 2250953966, 2832866738, 1236465462, 223567620, 1066146269, 3608374122, 1320851988, 3253186631, 2553947674, 1872191801, 516096295, 1195634624, 1449552529, 3856722883, 885977930, 3490641956, 2826234306, 3220379648, 3128438151, 1512748001, 655293586, 3885072026, 2836395257, 2848550792, 2316139958, 4224898232, 2632024198, 3603593725, 2166290957, 1571114837, 2145825902, 2043443301, 1891374967, 2046538548, 2488717199, 458651019, 2154445315, 2592455849, 3266747300, 98563372, 1904966481, 3676400896, 1716053111, 4206308204, 2658208676, 8001594, 1703645106, 2813029027, 894823261, 3726692608, 2449116480, 816030429, 3707476830, 1383662560, 2226126219, 3497705382, 1561989294, 2785389389, 3599384314, 2861958972, 26104257, 2618018317, 3938629738, 2008094819, 2901123170, 2341058897, 4197167100, 1303127374, 2903445052, 2658544205, 4149209641, 3128590068, 2172777857, 4127535687, 1057764004, 1621064811, 2989221344, 1862232212, 2949761869, 2620726474, 1750641652, 791265704, 2280902366, 3677859617, 1079043155, 1923182939, 2931362944, 123886216, 3043646978, 2297249701, 1035980818, 647873384, 2322301058, 2888236714, 2426466965, 3992010422, 910268721, 985368295, 1204228737, 3853108154, 2009215835, 893158799, 3476709186, 1783358605, 2497820589, 1805443650, 3969566710, 275487805, 3039957375, 514336764, 894146804, 2205031305, 2510265732, 1422658886, 227958265, 2068145443, 3893567490, 1543534282, 3541044587, 4205612325, 72081868, 3715915655, 3036960423, 419507608, 227127645, 434408508, 892436563, 162488684, 2166806308, 2727867269, 4081733001, 1736363129, 1586322132, 1569504753, 3585166014, 3409177960, 729399842, 600955707, 620409951, 4035728663, 3310125212, 4007687135, 1985227096, 198425200, 2174110521, 3681529070, 3128924487, 3475835290, 3105816703, 1645162765, 1329687130, 1438822241, 138742218, 545756349, 1589117794, 2874541073, 3226347249, 4238593852, 3175238090, 722760824, 2131293683, 359116635, 298494439, 1088923288, 1968400526, 425105133, 1003272490, 3419770934, 2286548114, 4069139264, 2021547095, 4252514166, 739676914, 1252440864, 2954914141, 891635266, 2569821890, 2274156960, 110747191, 10901206, 1932982168, 3445500258, 3634603074, 2076728168, 3765573833, 1087331828, 1830739116, 3074239474, 3109493948, 2614390121, 4096514773, 675737774, 1507210057, 3191779296, 487432240, 2260865324, 2080515432, 2883102503, 3886146031, 2630370868, 4277699658, 2892800514, 2200233033, 4132407774, 1674322414, 2982982405, 233528548, 1992281682, 4010179274, 132362763, 3820134833, 940222260, 1630667207, 3398377275, 59636590, 4159603377, 2127038731, 3535020648, 2726744939, 4053613473, 2694809533, 706296318, 3338739441, 3842009520, 2042421975, 318380771, 2862807993, 2988149892, 3967129325, 1725278138, 1137034794, 471477310, 2744784585, 3460424855, 1534357877, 3129901970, 2959751571, 981310577, 1151686479, 3917168837, 973476963, 1657796170, 57914437, 592921187, 458153097, 1933428006, 3953517828, 3462305086, 4127665091, 3416337136, 162732228, 1898167698, 1748974110, 1940432124, 4123185775, 3630680071, 582967365, 2778696182, 1253667008, 3496303486, 4269467104, 2724664452, 1077655402, 2678165119, 3253518851, 2109204349, 1050417512, 303542903, 1843757381, 2118812266, ], &[ 760607388, 1277184530, 2981799216, 2484283466, 1845234507, 4067960649, 1724479507, 83819652, 3545040829, 3052531934, 420422484, 3643672428, 1349470285, 4056685047, 2832938505, 1491007438, 178763876, 1111495297, 631150561, 3047444289, 1566356971, 2488845930, 425164460, 1595773856, 3837001561, 484465035, 2820607142, 3804528360, 2674871824, 3186224219, 4087693654, 2920476376, 8588869, 558775, 3389974041, 2969506917, 2965452016, 3676587727, 210868935, 1114006350, 2218193233, 1556179958, 148150696, 2219106491, 1462994960, 1292243663, 321251749, 2464568116, 253403500, 3875750499, 2872190504, 163483092, 3519534673, 805076316, 2163404152, 615601509, 767178352, 1619091211, 1814614561, 1067405571, 1717163796, 3946244485, 3024690426, 2792967083, 1807679765, 431637400, 322732386, 2839911024, 3368845765, 1517033346, 2660595988, 2750276183, 4061009359, 1623680793, 757894942, 3706877533, 2218116650, 2293451319, 569823489, 698352566, 3510886798, 2554837373, 4086146958, 1954697554, 573960878, 2250331646, 303856091, 2708174687, 4046135943, 1693832138, 3593561197, 3446967787, 2952095018, 2269948291, 1381823220, 3412641037, 1102668748, 621987569, 1535069601, 767621348, 2590901967, 3254158348, 3515706407, 733878453, 346561487, 989792827, 991774293, 2178089063, 3612432705, 1736330716, 4220679880, 4097313986, 214252218, 399876886, 590654784, 1772229036, 768989885, 944426986, 26251316, 461731150, 2081388689, 3083458623, 706415427, 1827828472, 3899769203, 4083585540, 4247342897, 1726610250, 973927807, 2871216474, 3494935804, 2158506902, 1905985267, 3353223634, 3173570788, 1690463510, 382352574, 2134842019, 3565559088, 249151518, 3370936016, 2396613398, 3417046586, 3594305304, 3140493812, 1254379168, 698764737, 2933504786, 1640097237, 3137847969, 147779617, 2340800809, 3271699801, 123654759, 4243613971, 4091038901, 226197826, 2843561677, 452274519, 1696592386, 510445282, 3118679881, 85905218, 4025631594, 2028469208, 509528611, 1040836081, 2397186849, 1562223848, 2694595611, 3893476920, 2309600022, 2399768696, 296649436, 2674754660, 3089905235, 1453504612, 2462730671, 3620829868, 2445109014, 1608966704, 4064616054, 1895591320, 4020983935, 2194700822, 810629206, 2473380931, 3571447370, 3670144438, 2241547653, 1600037379, 1312769092, 4288987007, 2180603515, 2032431482, 3155930440, 2347081206, 1170375513, 804187424, 1588865075, 1003883189, 1403312026, 2521589509, 3447772884, 176190746, 2770328111, 1376304849, 3302569355, 2706302415, 771852514, 2551687698, 2864197933, 647550216, 2115432876, 906064237, 572464402, 3003545732, 864303856, 389881224, 2127293745, 1745696468, 2876423177, 434301283, 2411003884, 1459296715, 4116191604, 4123400655, 514083733, 3501677069, 560842328, 3484783459, 3147137690, 98562603, 1227984143, 3656369715, 1790748622, 207681062, 1858085765, 3042917557, 15051061, 2662004930, 3234896654, 2201418512, 2261075821, 2414525847, 2115659173, 1538531010, 3426973282, 1850436548, 3108645332, 3468490861, 103560194, 3847474391, 2304980299, 646430594, 3231078594, 939320799, 21325968, 297361623, 4235174350, 3627466917, 2483242091, 4046019218, 2574344522, 3739169162, 2592019430, 288825870, 4090930955, 4137250565, 3891494555, 3120605826, 2196869924, 3174597170, 1613629883, 685507332, 1534687890, 908779827, 3295054006, 3756384184, 2861186142, 1659095103, 1717981410, 1263584044, 1519352335, 2462230874, 2507408901, 1017299565, 1783063087, 585746985, 3964830516, 3699440600, 3536055582, 2697252588, 2469673820, 962878683, 4263311381, 3667261985, 3070169507, 2743455086, 1717498452, 1115060528, 3846008407, 2601161942, 1892836847, 2163612072, 759958512, 3415397520, 1318661582, 988342975, 1319302705, 2265404538, 1889584918, 1549178474, 3271275522, 2877014458, 290716992, 1767870320, 3388946514, 13220617, 3925060219, 884929420, 3247704764, 2619847907, 3003460125, 522300420, 1485636618, 3423826468, 4173033596, 9068662, 1399499354, 3671771326, 1257731400, 2320092093, 1591017631, 599804719, 155451276, 1685145394, 1704457903, 547504407, 515106096, 3101264871, 1006089811, 1373639639, 3788559554, 74017985, 1232649413, 780153206, 1697467997, 2186106110, 3727566152, 1581072277, 3430739907, 1111233986, 34667293, 1405231508, 1228646292, 1721533476, 476892877, 3639232096, 812825459, 82472797, 2919035606, 1949528088, 1351453055, 2062781753, 3793110056, 2099220542, 1317878085, 3082007409, 3316362678, 3051185694, 3814721763, 4123576632, 299554338, 1863096302, 151300891, 1996738407, 741596005, 1115878980, 609896904, 1128474784, 3757075843, 2332323233, 4185436105, 2320459296, 3864402168, 1830711645, 4274682854, 3920215426, 3480904315, 1735518575, 1450876856, 4150198541, 2232155899, 3944834006, 2497911169, 2383598128, 2094445320, 1342532472, 1789279465, 1000444294, 11639007, 1290432806, 4207854768, 3606748345, 1655667625, 1766854649, 440958770, 778291729, 2589089910, 3630396169, 3916516125, 1115783505, 1808920531, 1936074214, 1379602123, 2109970892, 672050079, 3681625243, 880229580, 1226430335, 2376783696, 4021974970, 3642478776, 1316164236, 4224587460, 3674694076, 1609544635, 3597979777, 1507369018, 2871382803, 2147895845, 46634184, 3128655439, 2042987970, 1565373672, 3820697495, 1861755004, 3965634071, 192091812, 1714797038, 1913602383, 1284821271, 535686584, 95183224, 2099444647, 3918351823, 2323427836, 3425011013, 4034948283, 830062458, 3077755706, 2664361966, 3369633219, 685190299, 3773862621, 3479436350, 2166056948, 1165446941, 597447203, 449505020, 1407500224, 2595439346, 4163318436, 2061079625, 328423701, 1694015638, 1739710589, 2700176438, 3868944325, 1880345981, 126900733, 4252410326, 1210883987, 2952395303, 2472131703, 2919687101, 1151019281, 2923524835, 744738035, 1495025615, 864881767, 3672741575, 3952364434, 1561011577, 1661355866, 579464773, 430715700, 3967156099, 3638535987, 3314993313, 39754630, 3015258697, 3965969076, 1226994342, 333446910, 1554778231, 1872069078, 3265886307, 3661167969, 2545225482, 86455596, 4170100560, 1688415942, 1011498191, 1731003257, 3624902119, 2939526631, 3035198743, 1225561695, 172905320, 779745656, 3939303614, 1180230735, 2279433297, 2623909995, 2744984397, 2464197534, 1263906486, 3664838213, 826505934, 3484580218, 2811919655, 2439097791, 742011920, 3984794087, 305740292, 4085693322, 1641069773, 2623476948, 1391797660, 2004149167, 3244285446, 1000729643, 537058827, 2761876864, 3370814500, 1632812628, 2024768271, 10435691, 1808177540, 3508999569, 4285869266, 3955904362, 999801692, 2701282598, 3234606559, 1828569180, 2238113468, 2835896689, 398984954, 628112193, 3250276768, 3848427074, 4046507569, 1227584178, 3624650311, 1983600411, 2035997048, 3406710114, 876143052, 3576865031, 1808241372, 47133236, 2032404345, 1238579946, 2439947599, 1090627887, 3162552029, 3743711685, 2946905539, 2462606049, 1934095111, 2581983028, 2108794193, 537838758, 4276183193, 4118403780, 86207174, 241654991, 980261680, 1783811780, 3182293354, 2600347842, 3815684348, 2736014977, 1734720333, 4292465690, 296762674, 1299907137, 2710350606, 2474176175, 4143658256, 3614357927, 3668497288, 1388238213, 4039173642, 4262328310, 2046246019, 11867698, 1389032783, 3383689984, 203861277, 1983217572, 66262335, 2302573608, 2106760160, 676069123, 1923174580, 781475291, 740922128, 1145598272, 1863497642, 4017642908, 1433452599, 2335232697, 2252173876, 2622261950, 558873943, 1782242773, 4277857496, 2736476832, 4066356669, 2928683215, 630971298, 1950508576, 1217075937, 657092636, 3655489968, 3906055628, 2142188310, 3431799034, 1433370594, 3460735328, 844557915, 1205870649, 1403166550, 664366810, 699119677, 2418845509, 2981098211, 1120979748, 3155458151, 1505569454, 1404478419, 3580055806, 298814169, 883897064, 1829019390, 1951530736, 450098305, 1015728621, 1355065591, 957492909, 2448099162, 1099299552, 3160642001, 40991601, 2335441865, 1242957033, 744421734, 1288340852, 838608359, 3740535760, 2237946750, 3362970437, 1146604084, 3552223768, 2000474849, 3302747771, 3289090092, 1179750911, 299925783, 417958743, 3758178331, 3103400639, 510077191, 2978242633, 4234232170, 2462645467, 3759250684, 2930664089, 1112129962, 2041179483, 538852775, 1881748154, 3282982596, 692481925, 2461480040, 1321990335, 2603998961, 891524618, 2762291355, 1602130552, 3063842230, 1512104437, 1311990640, 1124520432, 1943880370, 1383543514, 659628275, 1498309472, 3514392205, 1588156795, 1101447212, 234163485, 1550295807, 2222040367, 2338297355, 3634753617, 251867854, 637824295, 3385282073, 2717908232, 3780668880, 3282410375, 12579023, 3519277677, 3981301653, 2289038755, 522494362, 2949573042, 786166898, 1057696288, 329580624, 3463380191, 2483531405, 700795614, 2675217847, 3326945763, 1078245300, 1966168086, 4106783828, 513839480, 452541817, 992723496, 2322276273, 1610065747, 262720733, 1456710625, 2076208126, 1528480920, 2344925742, 3245103726, 3530526281, 1227544700, 3828557800, 202954188, 844439261, 4143421330, 858722987, 791357449, 3651495542, 2338484477, 628819270, 2867425597, 512142937, 1740596275, 1958985288, 2954923600, 2724470424, 239279551, 3549834366, 4273847436, 4205746302, 1617654892, 4055107588, 3345065763, 3918815107, 3690347759, 2780847799, 704192022, 577918201, 2047971125, 199715340, 2815715011, 4100422521, 304495953, 3524335327, 3863026147, 1090602107, 55579725, 801128139, 1204054409, 750920527, 3494787127, 1695780971, 3713381555, 3067697193, 3857711920, 4229533126, 1848429928, 2930893519, 3245738664, 2770202715, 3311103276, 3239813930, 215046932, 768437545, 3361501036, 668953535, 2523450946, 3426827629, 4294907906, 3567391972, 2118111054, 3636801154, 235010253, 506820626, 4082694685, 1020596576, 4286162559, 93467349, 2864513902, 1787418532, 841111654, 3988531733, 1803513923, 2454566170, 2924727696, 2008920947, 3384148494, 1392082716, 197522545, 1809534525, 2067947619, 1915304315, 1794320741, 3658475265, 2477556156, 3466391692, 759597459, 3446403109, 4175986942, 2016300498, 3285587019, 3805614518, 3359773927, 3758992970, 2082537230, 4170722751, 1924400162, 3120097767, 1817189766, 4215519640, 1640964039, 3460451146, 553294147, 3993022590, 936189736, 3289831433, 2746878752, 218269093, 3641264302, 3746904227, 127062817, 3607266633, 3906014892, 3583438340, 1711866360, 1769540234, 8808456, 692035790, 3582940716, 2726467727, 1377561547, 355273557, 2147522454, 1648952034, 3996367145, 3973855422, 791111697, 504755645, 3306755904, 3160971610, 1420009713, 292333945, 1246559702, 502418547, 2839194844, 1755323582, 3824720395, 280335533, 2486741893, 3748085109, 1510237367, 913162122, 1367015807, 2150739469, 431332632, 2458778103, 468839323, 631541365, 3621249238, 2195421604, 2309648614, 1907083220, 1785404891, 1376379485, 1304676200, 1670817555, 1112332257, 2685812955, 3507402533, 2655556228, 3969960616, 901856719, 2257719427, 4169793859, 3281921750, 20313081, 605538211, 3389947560, 1288421142, 601129353, 2630934375, 1090529584, 3541228947, 2135095396, 2428588788, 1720926402, 1972699444, 1936465090, 4196883041, 1513169082, 1306967955, 3516168954, 2504390827, 3238431030, 936930168, 3824872735, 519589764, 3699706696, 2222441744, 2342278743, 3084957176, 4290410350, 1778787953, 3015190990, 2716506129, ], ); // - Barrett branch test( &[10; 1659], &[ 890276236, 341226799, 792588053, 367901941, 3412384327, 710303656, 2007116218, 1732149551, 2749665392, 2733077788, 1892910904, 3903262213, 3368335519, 980935858, 449583968, 1960964070, 82417675, 2300807023, 737772447, 2848196409, 2168358691, 2864360576, 177909817, 2598798571, 1444232680, 2011304558, 436734343, 2531093317, 1833818035, 2701704151, 4079761960, 2060337785, 3666406285, 2332405305, 1694319899, 2756923912, 2596868778, 3353801212, 2319197408, 949456643, 3210673236, 1574562999, 1402290323, 875914832, 1808447500, 1400287402, 1870271379, 3193561790, 2631625063, 422393142, 454330683, 1399511891, 887928993, 1982772955, 4249787009, 1042550992, 1845718215, 1923499583, 2405586067, 3603194566, 2924605215, 694963825, 1949261922, 395815473, 2098120598, 2155391008, 3001875867, 2497152933, 2157055549, 1494381162, 2624433809, 445187226, 1230608566, 2984284721, 1836275894, 3306237100, 1841513512, 2710642428, 973820593, 514673088, 3144609082, 3051871892, 3428549981, 1521009477, 3865181386, 3006578727, 4266792118, 1296136965, 2663669369, 2707104363, 1525098552, 3096200455, 83349968, 440117228, 2452613966, 1926577488, 404744979, 1730348753, 1281414650, 2753590879, 2501408984, 2436683689, 4018005907, 3151813017, 774894936, 928812960, 1406876714, 1300626258, 3795254718, 572793086, 504939191, 1858924532, 3208327188, 2458888708, 2209857693, 3635862246, 4015896456, 2424475729, 2407841828, 1838875522, 2698758219, 900362220, 3297883135, 2319766547, 3926911411, 2683221001, 635164605, 1978063173, 1554445660, 4039067308, 3534363633, 228909859, 2698728084, 1446768153, 3078533766, 1803252867, 810281015, 1437865883, 3136549314, 2523233981, 1635904205, 2841910210, 2673459917, 302753536, 3721460164, 4235982205, 2610290684, 3241605472, 3116643475, 1191081198, 2046254645, 101183106, 1647792738, 1559541261, 3806071610, 1461177358, 3272653778, 1407647063, 2448211251, 4228622147, 3316552027, 2359816329, 1591928596, 2248518657, 1224679111, 3354288039, 3472204054, 941606258, 1209690115, 322676832, 2932831862, 2003163428, 3206276298, 993107033, 2629921131, 3427077956, 4115430705, 18758505, 3427417332, 2001126401, 2108037391, 3665577171, 1863775255, 943945131, 1612515047, 4135299880, 3120161330, 280157154, 2453614374, 314225268, 3156105086, 1108918989, 164492394, 3228445085, 159609226, 3542796998, 3908606313, 737372698, 4020386652, 1541117308, 4079987109, 831583516, 710011798, 2517260657, 1502443551, 3947743604, 2630448337, 3713488594, 2045169924, 4240999995, 1008865782, 4189193897, 1658576435, 2238907645, 1755810942, 797651323, 2137409038, 1033636473, 4124730937, 3073837451, 109594062, 2690701355, 4034943218, 1405033142, 1440037662, 1082006809, 3569043007, 3728191023, 3761504320, 4122286843, 2321793213, 1900629490, 2311374908, 3129571201, 3976202280, 1676045885, 544386369, 2901355594, 3307278941, 2444850863, 774358865, 1135879223, 4061259975, 2102938029, 3898096702, 3670762822, 2514569341, 3882503461, 1631374873, 2849583118, 3325748020, 2953632965, 3236697735, 93102960, 765161636, 3854704169, 1573342719, 1310401001, 2041585538, 3684168483, 1596820840, 3244422616, 3149564815, 3111579294, 2543256788, 285031977, 1116476069, 1854107100, 2993132022, 2237783497, 1121738400, 1873498161, 3906059657, 2868037945, 2128298315, 2461778166, 2519976634, 1169495678, 145517031, 1089544388, 3496922453, 3858416589, 3577132981, 819516733, 360815306, 3662368821, 1541910226, 2826451779, 1275644110, 1972056710, 1036339248, 3879421912, 168837530, 2778017004, 508177746, 1418725768, 2362803078, 1537678007, 4273641757, 1157309391, 2027675884, 2766447468, 1140619111, 280217396, 1977767061, 3847572985, 563089282, 2707116985, 565542300, 3133606843, 1550118329, 4226756370, 1602547683, 2474372184, 2817100937, 2304466412, 3401474958, 1765460555, 514706751, 2958558266, 2788304434, 728359185, 3110910343, 2268078075, 2011266928, 1833177040, 3411609757, 2509364835, 2276646789, 3090785310, 410706208, 3982922454, 396138284, 1225183095, 2653156018, 1198560357, 1081851637, 4266095252, 200467546, 2084872625, 3819726737, 1842926566, 2137414674, 3780793518, 3803338949, 2618440541, 3079036479, 1098784392, 2442578090, 3632573226, 2172339623, 2589618514, 3908085439, 2879837004, 4287758566, 2751698111, 2126731652, 2825624276, 2248293625, 2459102047, 727371099, 1762220065, 2035848579, 2684644913, 1138174417, 1607470803, 1910213315, 3392274014, 2122238927, 799528170, 3993036983, 3276585428, 3696900606, 3376656588, 3273677417, 3728672429, 2897266369, 1209435480, 3668943597, 554740320, 1910520674, 2755821121, 2815354947, 628678360, 1972408136, 2959168464, 2823142531, 2826638433, 2423863843, 1087171516, 3879922452, 1945794416, 3539137213, 2491723621, 2326706944, 1055221317, 1132982204, 3700164345, 2874108055, 4229375434, 2069834207, 242639877, 1033996106, 3133990269, 2480736852, 3972172611, 207742724, 3310273273, 3175731064, 3581837682, 76902028, 4245157123, 4269031394, 2490069025, 2999666665, 504120169, 191809390, 167412924, 555218984, 1496941280, 2093783841, 3208530629, 3145850049, 3933461123, 2175208309, 365172205, 2462688963, 3453497377, 1555304950, 4025179114, 2083241909, 168967519, 4078676060, 4042564952, 2524740606, 910140135, 2191946661, 36949303, 2750127471, 3088746837, 1513675215, 2555879390, 718186264, 2118995763, 2901874435, 2945636440, 2863577556, 2968054349, 2987445655, 1391389309, 3362068597, 420379086, 3549925062, 2452687361, 1408886777, 2462121091, 3799278878, 3322044177, 4293985015, 1286609586, 2785058305, 4274674252, 2778156482, 3910962810, 4068513623, 1564413978, 1181250931, 3988825528, 2788859022, 2134808366, 2286009824, 191534000, 673284258, 943092112, 3792387654, 1636364244, 1258619608, 2687335657, 2373558306, 1780255272, 192951187, 431701677, 3304549528, 1704199693, 314302815, 1733754456, 2651178366, 262110118, 2490882199, 3280711290, 3787049925, 328986136, 1023802009, 1956694362, 2484923034, 2727330053, 2638100006, 92690660, 3896101961, 1028256658, 3988282321, 2110531875, 1842222098, 2787896255, 3395969716, 990977104, 2139528143, 1832975942, 4160298612, 2285171947, 1418666556, 222644271, 919581311, 862681678, 2923905104, 1799774966, 2815043367, 2781755775, 1331093883, 669689278, 2966365455, 3173764511, 2239898981, 2363266499, 2640372661, 2127456692, 2279796862, 1776783331, 2548834983, 472218271, 2900695473, 1495706076, 2657343542, 209220262, 275069056, 3271376502, 3733744095, 3534782378, 2464305853, 4233994418, 1155007782, 1180251759, 1970459014, 2342844621, 59653648, 2748740588, 2766398852, 3832978838, 242101716, 1386468541, 1326666089, 3173296092, 2837432655, 3998816786, 3710871416, 679295186, 2135255711, 1894408962, 2653191387, 3752231861, 2630930863, 487033484, 1492980844, 3038367576, 4293864058, 2543786315, 3417240532, 2205003924, 1597945938, 1509635773, 4283299822, 3442672823, 4165828898, 396431869, 648731431, 38097411, 522913513, 957583354, 4279028565, 2596119340, 2064412533, 3862275959, 3172491786, 2807778054, 1802160322, 2786925709, 608133700, 156702572, 3651500279, 2104603013, 2661177081, 618430078, 2315385783, 299901731, 2422105030, 2329676657, 716074660, 1732980457, 1214771864, 1586076972, 1803988277, 3707411655, 2659362119, 2373571795, 770730047, 3785576910, 735242862, 2539172759, 2203837147, 1488005025, 1384867732, 3789824993, 1122099741, 552382082, 1506769429, 4044090493, 1748889897, 4206809578, 781459036, 3672028809, 2541707199, 840152057, 238216856, 801669583, 908070471, 3215820340, 277209814, 2800868730, 2623960742, 1086085297, 1126632972, 4142066460, 1949273163, 2523144053, 2629334386, 3335675532, 4057941621, 1205937990, 1082630648, 1878674537, 1256320064, 1727330605, 2529007873, 4276070038, 2148176144, 2447857920, 3472917547, 1158643513, 2671603905, 2829575595, 3450336191, 982424809, 882567930, 323789646, 3200918344, 2216686077, 3009541444, 2571083160, 1006292466, 437753632, 3278939834, 3355173103, 3481349388, 857243294, 2364943880, 3808395135, 3214225862, 3777869070, 3565105852, 2808230263, 221823914, 2758813582, 2925915811, 414573289, 2532719232, 2409558681, 270315198, 2558439626, 615075030, 4089479722, 3494552549, 2115205628, 74023539, 2750188165, 1839125170, 583459154, 3761181274, 2329244963, 1691231890, 507167187, 4046741250, 1026250436, 902121215, 2344634879, 2988992123, 2984781046, 3518129686, 1917222692, 1968401639, 2543696192, 3620784874, 4204784824, 983090664, 2003341457, 3457430091, 1995667040, 2478215910, 1213924330, 902607969, 1674777804, 4280126343, 2726668253, 2097919452, 3522418576, 33515971, 1894400520, 3029857368, 150356335, 4243001247, 673978253, 2719146244, 2090227855, 4192329224, 2236320436, 2148835059, 3185966796, 941447358, 779143957, 2545384906, 340222909, 1163954627, 3190577527, 864905744, 3107306228, 910249975, 2948352628, 147585477, 959446574, 3474262008, 4035464440, 1309641572, 1843324139, 594300461, 1004840213, 2224007255, 3852374975, 4120257334, 2723207946, 2794257458, 1545266608, 1321887969, 2165623498, 4123085504, 1017498034, 2385703284, 1909037055, 543047021, 3878828835, 3447407518, 1606126047, 1695313677, 836832112, 3506770595, 2603100919, 3453043698, 199938105, 3434291843, 3309362210, 3420539779, 3881672999, 3941526979, 1892491834, 1578793338, 2517226952, 2402834890, 5862131, 40700601, 3714441463, 729961232, 1925856845, 3468241001, 3115568092, 1631854454, 1701899766, 3027256253, 2894901269, 1124111614, 389357030, 3985153554, 552236945, 2703725197, 3429926834, 2037737468, 2457575384, 3768369718, 1501137909, 1925317821, 2657749431, 3797990637, 4187234508, 327539080, 794903321, 2319399609, 2762815786, 976015557, 1691624096, 3787965011, 1187388905, 2626212695, 3807450271, 3591385293, 1093027360, 2171140441, 1152487697, 3182952906, 2771269699, 1234596937, 2271936819, 603050394, 3263289503, 3560700020, 2800995941, 1196053050, 2414391090, 1881373224, 1884483033, 2568796666, 3824541190, 3858390730, 2040352321, 718151978, 1377901177, 1597261066, 2356591213, 2419086272, 2844721838, 2553373958, 3487777061, 4036573915, 3960541066, 646040800, 4243906341, 2572505351, 1801145995, 664327833, 676356931, 2958233650, 3981016651, 481021340, 418338722, 3399065823, 3030397492, 150785760, 1176367446, 2939257689, 32665451, 2951976791, 311905711, 1897102562, 3243398501, 1748429176, 1746479862, 343846941, 2781004348, 2171670176, 309744191, 2415354772, 1041777746, 2288489926, 4248954013, 1910365690, 1113007596, 3208904334, 323062080, 584001309, 30088757, 3210313377, 810170431, 1442786337, 854351100, 904966376, 768074292, 1149027717, 3752792280, 3857132892, 2279768216, 3349859712, 282292503, 56581336, 2391268817, 2947375479, 1126824647, 4105649938, 3962247540, 519562385, 1963761442, 395588526, 2431054442, 950162585, 1570376756, 2250607225, 2673908656, 2527346059, 288669023, 575810459, 2786581872, 3735760778, 4200489389, 680967503, 1713328630, 1930270331, 2425215981, 3980660137, 4014429658, 2192587396, 3942840373, 1564337241, 327120779, 4156973813, 3880803765, 3540049821, 1863580480, 3375736133, 4036504068, 1785184442, 1955521254, 1453896460, 1053996688, 1978861082, 548425572, 302301885, 1991013158, 22073650, 3921072009, 1928162922, 1082841772, 327037462, 1044813693, 2938349910, 995698425, 332894183, 1388488396, 3872091479, 4029340893, 3277696405, 775391931, 1016127394, 2545485682, 2073876466, 1128541985, 1496426020, 80233992, 1338981471, 3354539036, 3085869246, 1640435947, 3318556546, 3284845655, 2946418668, 3047158280, 2003184416, 159404031, 2086225997, 3708415056, 820845255, 2941403694, 1894980986, 4054398500, 354127917, 1759927817, 461854099, 2756970748, 102702694, 1301323588, 2833690096, 1511747665, 2593308423, 1879972490, 1838875158, 2618211449, 1797209275, 120683822, 1883611437, 4202360723, 4128014501, 3211136205, 1088772951, 1828585088, 2938812583, 2284221739, 3823561623, 4077006488, 1029205999, 3672550742, 343538454, 3044781643, 1237692065, 2928228237, 1830634178, 275610581, 3774294394, 3361331648, 2196692892, 3255359432, 2329150995, 1274593100, 1328237401, 1721689163, 1552282513, 3159830746, 3644636753, 1105036069, 355771027, 1576347151, 944409757, 448354212, 1354862379, 339109623, 3510474598, 3466751984, 20825450, 3821901448, 2057496944, 2943845147, 3219926439, 1333132401, 183117509, 3498530864, 2182448771, 3426279410, 1665731931, 1510911964, 1196289032, 2580562014, 1929195017, 2594768969, 809172016, 2653623722, 2512680195, 217752055, 1721337598, 2483986094, 2361703097, 2370506525, 1987764412, 517621644, 693022222, 4199398517, 373355871, 3352107025, 2338083298, 159801450, 1797870121, 2860144576, 3939907735, 3514862832, 431143617, 1623844364, 1508889091, 2387069842, 1972468120, 736883904, 1753611344, 1661123641, 2409352944, 461880992, 2038512497, 3457487084, 3961958981, 801429985, 2972366430, 3338662267, 3327375019, 2105332644, 998675685, 691868141, 870966463, 1279549664, 3134690576, 3190301255, 1631564609, 1367483321, 2646565011, 634484526, 2537380840, 2213333282, 472168933, 3498162369, 4174275366, 1543944344, 3557960735, 1147270417, 3787417027, 214242757, 3877605781, 1792046194, 1247989220, 4226299524, 2026490398, 2743362165, 3282533732, 1766662214, 3166276549, 3016180603, 2258391278, 3962452054, 168300410, 2111946937, 713217908, 945581724, 3974119689, 3587010488, 2181601474, 246735659, 2543921339, 2723353212, 1467436138, 3185503405, 3831196899, 158015188, 490283336, 2084333291, 2741425836, 655722571, 2045963231, 4174037980, 2501752755, 148738138, 1307383368, 3787063365, 721414861, 367804370, 3580824327, 4086466283, 1279991485, 2037844627, 3544424029, 843306486, 2062910422, 2484907808, 2564538263, 2558157768, 3736247186, 2359778109, 2792113263, 2653179154, 1171565785, 970085568, 2755189942, 2462193088, 2187804183, 1622505599, 757911218, 3544379371, 4084601374, 2831197190, 1128632808, 1911943420, 1064662251, 617203970, 3185110184, 3872537015, 2663673571, 1598938612, 2021095595, 1230226206, 3352634834, 3243340070, 3521473899, 947764553, 1063048833, 332597817, 1892887725, 885809381, 1232744110, 488758874, 1219451925, 3879973077, 3087466985, 1317009576, 4096728294, 1647182459, 2603742762, 3671645026, 2351436637, 2208571110, 772272953, 2835855429, 3069601842, 3507496189, 956062404, 1530390718, 3749254585, 2207726706, 3111772294, 1060767761, 711759067, 2176543833, 2198489800, 808754055, 2305333083, 3151555404, 2509458656, 2135135534, 3230952171, 2571117847, 2341460893, 479051995, 1768657443, 1460137774, 2415002930, 3360777084, 1122116253, 303290829, 3416566333, 4216166260, 1908146236, 645774129, 2687866494, 3150948846, 3002877577, 1584197209, 1906233324, 2943774631, 1302474040, 123233115, 3070944438, 4059478095, 966454883, 1124649660, 459555946, 1739202231, 220401749, 569942371, 3571881666, 3770440911, 932409766, 2318445287, 414753024, 1238020551, 1107839477, 659942128, 3483946741, 465817183, 3283253432, 3332782561, 930288386, 1502477361, 289384294, 2672225570, 656751994, 1938557826, 4263515785, 3846686615, 1977835682, 3782978161, 3841096638, 2100335863, 1466976524, 905037512, 3998859595, 2647592476, 1315412287, 2608076472, 2106055663, 3021269968, 3874586748, 3153686736, 3797040333, 3195133207, 1058452397, 471283566, 3289919590, 2491009200, 274949631, 1247099012, 4029069224, 2905208231, 2179210118, 3711788704, 3755257973, 2928888484, 1052560560, 2967164700, 1635564638, 2408974105, 2650877150, 152761664, 3778129977, 6898243, 3642738916, 2085555548, 4208692126, 3516476673, 3689736495, 4284496225, 2331191533, 55304992, 3822559904, 2239314561, 371351603, 1372721940, 2935911010, 2081736209, 3779840280, 1714652721, 3411278140, 2654198957, 4262940016, 713862676, 3977788884, 1302513367, 1393129292, 3633035689, 2006841374, 3188426778, 506706704, 4019796909, 2697310122, 2678256017, 4001202363, 4268990548, 1518149683, 4051379891, 2122891199, 1746178525, 1962304081, 3865021362, 1312381895, 4177647623, 2434495123, 696907907, 482662266, 540053306, 2380506995, 3725670235, 2171452643, 3435152939, 4096541777, 3503333448, 3691060485, 1944004703, 898436730, 121854915, 1588868274, 2860886605, 1300182839, 1693834903, 3031447227, 3217167554, 2922628107, 4114756146, 2079196834, 2684932909, 363311866, 668991145, 1327347517, 2469568598, 1913706668, 268108277, 577243285, 1477909197, 1398721081, 4010189391, 2691034717, 1036016821, 1810355639, 274912831, 1795119756, 1368326430, 2579557677, 913700763, 1609695519, 2382496942, 1044984785, 303066142, 1822891534, 3029842660, 4197043641, 584103984, 1997889445, 3604603832, 3119992851, 2675724476, 4061366219, 2925184984, 2195814396, 429034966, 1102290544, 3100888502, 3392886272, 630724501, 315124612, 2110860880, 3375452806, 1360073167, 1663964263, 3704594026, 2156765374, 2209318060, 305106236, 3229984531, 3679679759, 412339952, 3408237957, 4272496758, 1831873985, 888956855, 2879515229, 2865192273, 757175501, 1423828575, 1369325109, 100316687, 3388465856, 2777010920, 1042158042, 1817540433, 1115141275, 2632434501, 4015855401, 4118763832, 942872566, 1619453899, 3946427286, 541394029, 1528755909, 2036673964, 1456023963, 4059819153, 4121822726, 2025464163, 3230339097, 68415417, 18265310, 1132496724, 2754635682, 385314119, 1567156044, 940632399, 1831395946, 2469397928, 541250595, 74019926, 2039901080, 773704780, 590385326, 3107133266, 2143056697, 3257519203, 3995912435, 2208286868, 1856405930, 1700973893, 1653979838, 2024515776, 3218710950, 1084145854, 1317505497, 3590817427, 123061081, 2076656022, 4077554585, 2879482171, 2950794060, 3734348393, 722767161, 3691545699, 1644306454, 333687306, 2241964536, 3060788682, 2453668285, 1189757337, 1263877652, 569206760, 3846943302, 4010117854, 4059584053, 4044950226, 3638405845, 3879375082, 2049939648, 1496362390, 1682303551, 2612201683, 3043389670, 1640230718, 4052525226, 917568678, 863698076, 993517383, 3674253221, 744083165, 2026633641, 1428745764, 3316111420, 296209737, 825439661, 1138886542, 4238983059, 1093858251, 623018211, 509903369, 3954989263, 2875469802, 3163782305, 2068031367, 2440167512, 1590471250, 2577400899, 1401443658, 438753386, 973022558, 490459931, 4153136453, 2638113298, 1725729658, 1657506325, 4041198040, 3744818426, 1877561769, 4134538451, 3997643962, 3278471793, 2418908581, 356962783, 3224136760, 2919949586, 3613171265, 97663361, 3097697220, 3489004921, 2697784225, 4279173863, 3772958071, 3905886590, 1711013393, 2126838688, 990698143, 3920056751, 3588492473, 2098301822, 1854964825, 1664184868, 3795158895, 151603425, 3531429187, 3490656748, 1113504873, 1471018271, 4168869499, 4008256495, 2171869942, 609135193, 2986518561, 1725952510, 1976303843, 2274910761, 242274490, 3473272380, 3970326612, 2167449820, 1194973795, 3783506867, 348209623, 3135533248, 3532222693, 3344736663, 214520997, 1636130783, 2067796675, 2369417375, 2235358466, 86178644, 2779810734, 4214159539, 3218271482, 3985230716, 2329504243, 147581458, 1474992222, 1674107989, 3428339487, 2770470340, 1986697826, 2655128050, 2876733066, 1471032373, 911683545, 2090594993, 3437186916, 3308018952, 533482761, 1086927954, 3676694935, 3342609410, 1508797862, 2500353221, 3720936876, 2701068861, 642689761, 3643678624, 290806518, 83395626, 1535005732, 2747794047, 3570146930, 914908213, 1337975084, 1497808741, 260949154, 4207131444, 593904854, 3888947157, 195239383, 3774140559, 2853428653, 3136732762, 1248240658, 2234958820, 3762975745, 1162679573, 272129118, 296868072, 3334585892, 2918794318, 1694070693, 2492485295, 2683814086, 298872871, 817942615, 1004532076, 2606294117, 4046765057, 2233192255, 3661649470, 2238986852, 1062091508, 2399311242, 2885215834, 1798967492, 2531479104, 4074434116, 2111742327, 2896836169, 3250431, 1770836879, 2620395921, 501323762, 1835526774, 2803163141, 1991155504, 2143149513, 1934058381, 1289076816, 2032493823, 3585211537, 2907068377, ], &[ 1957536939, 2704233779, 913359386, 2607986801, 2446464778, 489495221, 1977138138, 199874920, 2066813840, 4078462749, 1016088557, 337324630, 3990125130, 2305453367, 3378159386, 3362499975, 1892329456, 421235551, 960087932, 2138732375, 1747069721, 2966299538, 3497725227, 788194103, 2620925095, 3992734827, 2347614949, 1192266871, 2152140927, 2595902702, 1509482398, 787254206, 2484597728, 1789728733, 1226715026, 114480829, 987023760, 3496800953, 256020284, 1894092757, 47387107, 2176522500, 2135704654, 994057186, 2546241901, 4122251778, 3491731236, 384111784, 1236832234, 3662603701, 2609281585, 1219883919, 2008118687, 2326006512, 2338027654, 2332414668, 2538669365, 2958308350, 3306252952, 4097401440, 245412822, 1134218707, 3076680142, 926168655, 451578268, 1698122066, 514466774, 1794890875, 2253188253, 3860209307, 4125975400, 1233713256, 1331554757, 4108025645, 636835921, 1849327003, 393004812, 2558555361, 1692156580, 3582970009, 914267920, 2658172248, 4012245606, 854232321, 1471576996, 3492333793, 2913754320, 2051701466, 1005511236, 3371062639, 3296185640, 2678783225, 3650455045, 4263496163, 3495211840, 160882721, 3272734255, 3363410960, 1673492685, 2227170400, 1101828895, 1119793884, 1457840656, 2222657767, 3828794092, 4237803786, 1329436877, 2830186178, 3860284552, 1337378154, 2783161843, 470651568, 1823782186, 497979415, 2298463213, 3726533213, 2304335399, 3374908291, 3136539039, 1011793524, 1434135959, 3546472177, 3334783571, 226156373, 1932074218, 631985614, 1079925731, 3769906884, 4019194278, 3109451869, 1778729352, 3135074288, 3585179302, 536686269, 269921815, 75736971, 1251776355, 3758315612, 1656722319, 3842105657, 309256249, 3658053371, 1366755718, 2879694669, 216747845, 1138851530, 180246577, 2017139089, 1955595458, 1039824550, 3194217029, 1733371216, 1506550177, 526780059, 1134528034, 384391871, 984118045, 3841118292, 1290155172, 3325719027, 2046692404, 549115234, 1571136961, 2903831138, 4237164623, 3384940491, 444561690, 1887009067, 3032883562, 528649308, 3526917838, 861967137, 849430599, 1174292170, 3363871839, 3164890264, 4139898798, 2515068538, 2817798053, 1985333569, 3628916450, 4104808900, 834622482, 2376137274, 570637315, 265226452, 2900200945, 3714687255, 2191892020, 1444354629, 2162094270, 1794298889, 1027492948, 3254523420, 3973688556, 70444914, 4247183201, 2558259799, 1382220873, 363937698, 1293687680, 2257401251, 1821850058, 2709286660, 3142574973, 3132883088, 3836062384, 2080511414, 2488073709, 3338281745, 158637847, 1975561389, 3788657841, 2878593484, 3932639038, 2471341193, 2976486658, 4177193258, 3207728388, 3451499189, 1036976564, 4174152173, 1200214586, 1593901807, 1598813685, 3572817953, 381665761, 23270196, 1802671154, 3457511367, 3684670008, 4141234293, 4257731307, 1636422959, 740772838, 1988075395, 3741682939, 91025578, 3019507910, 1239453327, 15530035, 1805537881, 3030234017, 2850226774, 647324122, 367062563, 997518198, 694008483, 317521938, 1160123804, 725289606, 1178038187, 1241619590, 3354084342, 2764339200, 624229820, 212334275, 395480330, 1367723402, 3193328333, 492787846, 2912412117, 769721138, 1070730529, 448893800, 735046630, 3751288669, 2414740806, 2618411130, 405231076, 2516857660, 464468370, 3258011579, 1477182041, 493720224, 2850809713, 3137078323, 3502041365, 3173963137, 2479519371, 167431223, 3658737457, 3772800354, 1986032427, 1987941758, 3573465175, 326371902, 3433869641, 1504044245, 2797511645, 2359717369, 3995931882, 1634803252, 4253137604, 4268085428, 3040903829, 2277724443, 128782128, 875783256, 479424864, 528909344, 3760571120, 3390001080, 3322552131, 2303766273, 2363235433, 1521779839, 71576180, 1476909520, 2716820223, 3668085110, 2404806181, 3808398898, 551144165, 396216221, 3351190698, 2567267783, 4253613190, 436775, 1500218837, 1017116170, 4018991981, 2949611141, 2820025183, 1026140859, 1421949338, 3652746241, 4092056796, 812077816, 400306669, 3639988628, 3886839943, 1895304730, 426912903, 2799536256, 648522878, 3154874866, 2278734966, 2267078837, 3248002806, 2570845216, 1716635426, 3324742113, 2710305693, 2354409016, 209044596, 1052107641, 1275041956, 2683489172, 2218781510, 3218932590, 367423450, 1139521118, 484065443, 2774672726, 2199688060, 2595994858, 2766781330, 4010728155, 2471938607, 2443485677, 2512646557, 1783786440, 2586521152, 1293511168, 2754786394, 843414384, 2733670928, 2673211126, 1831548704, 1507579292, 300108435, 4168221860, 3056060813, 1074051129, 2443218252, 2786872412, 1521579909, 3002145596, 1038629976, 333719208, 398037698, 2327562199, 3906306578, 3860291999, 2708215457, 2994740784, 2444084751, 2051054286, 3721504053, 13639901, 3131442928, 1665891362, 1004981560, 2672093967, 3849433595, 3693322361, 4157500107, 3275912258, 939706674, 2775110135, 2772877030, 3937484334, 240094954, 268854799, 358769959, 3879082861, 990116332, 3844458806, 3358517002, 157654009, 1888197277, 3767715560, 1992005094, 3000885357, 712308948, 97474400, 1032741665, 1474808743, 1698678514, 931537527, 1916486634, 2878260947, 3727228108, 2313492286, 3285497655, 3206730275, 4284678508, 2506474477, 1389954169, 3751888822, 194362906, 2064318045, 4133690442, 2808582010, 2677686297, 3050279294, 2468404997, 1830004272, 2685594794, 477597531, 3289330681, 2143814392, 3874622902, 3298844876, 2487277301, 3988787333, 3041371803, 4049441073, 3767569736, 2542990054, 2425662849, 1897157558, 1338068625, 3204808408, 2152753507, 3746300240, 2482331983, 3385302403, 2758234439, 2759085438, 508998065, 1223433126, 2394383885, 132654029, 2315880048, 4098029485, 4024894935, 7497695, 1562536823, 3137935348, 3016914619, 2109764983, 1252720630, 145849589, 4083512962, 2437495916, 1112513401, 1406756818, 1950408622, 446872130, 2562784674, 179413856, 1514287693, 3292189406, 2906659889, 713923011, 3611402990, 1483192135, 624362594, 1716375666, 2598996983, 3400508352, 532608647, 1064107478, 3678086402, 2971527569, 373188058, 159485586, 1268240989, 3237585490, 3168342804, 3260235693, 1044471752, 1794355961, 2708027181, 2350414048, 2578105119, 1701986224, 3287958641, 3731989517, 2550833186, 1464424680, 1492730967, 788230494, 1536847815, 3539582664, 2684847209, 3275242595, 1175102357, 812199218, 2945417844, 1324851034, 3657118239, 2080012874, 2073911306, 348871803, 1385046650, 2256273117, 1079410594, 2685229619, 2682847322, 2114480861, 646191989, 2203899983, 3969414867, 3538537702, 4068013123, 3232826610, 596198863, 1046306571, 2865628166, 68987600, 2100190548, 3315046820, 3490220594, 1096067081, 2941419727, 2558046885, 591489912, 3477689804, 133164194, 2648378976, 1672712559, 503765043, 472903689, 2389245110, 576018363, 3148922955, 4125524011, 3286180064, 4030404254, 2604010162, 2997085129, 89056299, 1807554852, 3269841668, 549895196, 260687385, 3579375620, 187060840, 1942595893, 603206835, 3855746037, 591224213, 2177212211, 1725264, 3682481866, 1603335098, 2633406770, 2503221238, 3962816132, 1570827695, 2441815283, 2775443721, 2831622813, 331378838, 2661613345, 1859324001, 1681417767, 4071306777, 3407361880, 3630093367, 4191434377, 1636246728, 669176351, 673352253, 3293415547, 2884409096, 14264168, 3758461627, 1716070268, 3988243278, 1362878027, 3980519306, 536008192, 2678505899, 1811539102, 342405744, 1073242768, 3131459191, 3387892829, 270841706, 1918541045, 492555376, 4112571650, 90351315, 2276388252, 3010748516, 3067881057, 2416288684, 2671243984, 1733673053, 438278887, 3784801996, 1744631357, 948419911, 327397862, 862996580, 3011920294, 116939684, 2556778847, 3517559828, 3829460311, 4187696223, 1136268214, 4227182561, 417640562, 947119687, 1552494427, 3914862791, 3660625720, 3269794901, 3983761435, 1080024760, 3542497606, 734720422, 2130766530, 2052008789, 866179302, 3356984656, 3353059419, 3601785550, 1473338460, 3554981181, 3284807202, 2537178131, 2660558883, 1407764537, 2536942750, 1111424643, 197150902, 1986360943, 570578003, 3230731629, 2880732002, 718229319, 2216239393, 2151519911, 3213233733, 140516899, 2705306189, 2099103478, 3400320424, 557688725, 1668843985, 873992190, 4038504679, 2235288434, 3929442420, 1798837796, 1541815340, 866720679, 912630678, 3653176164, 4183404997, 3783207140, 236751523, 4213981998, 2366690759, 3322048028, 1620537970, 150683096, 1696323966, 2488037541, 955353889, 3126250139, 2098113031, 996224862, 379286788, 1454980629, 1330626720, 3254326109, 114141156, 505833530, 776857882, 3230818694, 1513550233, 2944138982, 1138399014, 1232351884, 3762710836, 2726900776, 1754189655, 3929691897, 517294527, 1584785665, 3428100574, 493061896, 191275086, 3371640283, 3691097600, 660743997, 454351402, 2693537492, 224441543, 4083242290, 2042419433, 1749405749, 3326121761, 1143000188, 528164385, 2093408728, 547444310, 742328728, 385453463, 1855621240, 693597263, 821097697, 3359254510, 3784781596, 3737350790, 1858752558, 3289952948, 3844337741, 3017718436, 747204738, 2068341572, 1829338054, 2656623131, 2621869237, 188997883, 894051007, 2539316328, 720156732, 2857142692, 479986318, 2311943223, 3461090848, 763159324, 1341957518, 3254977494, 344988894, 2995353987, 359814922, 3943690309, 4114837915, 4183023494, 1015984176, 2054910037, 88581401, 2304385752, 936890838, 1910665193, 2253192878, 2257283900, 3264567353, 3384051258, 2436405862, 3219870836, 739980663, 2626205881, 3700440528, 4116751635, 123261973, 97170430, 2912685809, 1847392507, 1227630879, 4041294564, 1594273654, 4133439523, 2273557482, 1852654860, 3619550719, 1702837553, 28059816, 102772606, 4220040474, 2282708544, 3048829450, 1198037965, 3799925281, 3345026858, 3972819307, 3424778198, 3055538572, 3844967902, 3860665646, 3364107827, 3065192652, 313761936, 179089842, 1653844636, 1935859587, 4030697757, 941748694, 2581107832, 2215407717, 266072062, 151136699, 3862901759, 1913706201, 3703579696, 3175598851, 3518922721, 1540670487, 1481796449, 2350248159, 1161169395, 1551024445, 2596829351, 908720646, 510631697, 643247275, 7860017, 1436230977, 1642294503, 3987759281, 3697987608, 1884149375, 2628751463, 3704486074, 1467870985, 1033168865, 4152476956, 649602304, 513167376, 826712542, 850605344, 3235955410, 2269970645, 2692348528, 4086685012, 635138347, 3779838044, 3121512906, 3227378207, 1054819334, 31747484, 458159784, 4199967375, 1288741089, 1261908606, 1322196907, 66488517, 3887579746, 1119580071, 3520963022, 3373216749, 223764043, 2861161993, 747227972, 3482785674, 1405771917, 719369505, 1673984799, 276079513, 2508081261, 2515431484, 2922924126, 3597246716, 647895476, 3793428410, 3425572118, 1074297825, 821559348, 2839542545, 1897144802, 3613259736, 1808031746, 1281519681, 3896118069, 4131591488, 296155402, 638550355, 3052325442, 125220535, 450621007, 2279487792, 3201319320, 3970196322, 1300822796, 1592875148, 459824311, 3555860014, 37468205, 163861297, 2887286569, 1605580982, 2267025263, 852924927, 823513980, 2749888610, 2890486427, 1975455355, 4260140080, 2388308835, 2751260543, 2054257325, 898019685, 3076718156, 2748642166, 4107558681, 726356635, 2409380553, 4133858015, 2137846929, 1533796622, 3343476816, 2995477096, 1906524432, 2463273274, 2821225323, 3240034000, 284966169, 1623621895, 155403754, 3702407866, 2384829979, 3527853746, 3965422206, 3695468695, 4111056268, 2851499724, 2096098281, 2589036318, 2328285109, 342249683, 1491530029, 1120943322, 2993943428, 961500646, 3834036750, 1407279773, 2159771508, 2949114548, 1257703137, 112753236, 2687765617, 3264480915, 541858082, 1905233079, 3741673276, 1506206568, 948437457, 2072091462, 435343542, 1826721485, 3026216742, 1899272380, 2381726103, 2386973389, 3851959892, 676110207, 1429488429, 2456962149, 3434188217, 1759358419, 2012996724, 3832387879, 1306928055, 3879599379, 1855514535, 1278340174, 3895170905, 4036851839, 1736502179, 902593028, 3041896318, 1088656605, 2205253218, 1400012130, 2261287720, 175467724, 2113685409, 2927396005, 2790930243, 1527781896, 1808475280, 462065438, 3808277088, 1996854314, 1227914704, 2532981454, 2751135197, 832474648, 278376997, 179999604, 3454837790, 4189477161, 3925404576, 724347681, 326641044, 545292031, 4132073668, 714677745, 3376764287, 4156659605, 1767724141, 1293260683, 3611915310, 2602914479, 705091580, 3795953319, 104155240, 2107810007, 102476149, 2478337301, 2728764462, 2324210661, 1662625823, 19728436, 919970704, 408330796, 226002873, 1224941092, 3253024461, 703084167, 1686344642, 2710447096, 3741823793, 1800137048, 1728578459, 4073670765, 2856520839, 2518678794, 2111509220, 3046036386, 66768381, 3409265781, 2031838848, 4139578175, 1919099167, 3614877420, 689717715, 3410494541, 659505257, 4116537698, 2258414617, 2602261611, 4243664763, 1148504559, 3060144650, 1821973517, 943353725, 2656223194, 2921874644, 737103001, 2682285832, 3365075677, 504157948, 2117504770, 1091988882, 138431492, 3089878442, 1947915975, 2861908225, 625375400, 3456663917, 2919653950, 3589858184, 3706889141, 2982313688, 2375816280, 2734870666, 4188096235, 3604422039, 983639961, 3301762066, 3181745837, 2721926640, 3199024837, 1310138874, 1579083497, 2259444203, 3729344966, 3342523607, 3034522197, 3782108897, 1886708695, 3226663577, 2702137984, 2606528335, 1872012482, 1786733392, 3448253761, 808696129, 3961046824, 746729737, 2209996950, 249014846, 1666060137, 3026499663, 1078708282, 370739583, 68889615, 526951028, 3065574510, 263587921, 691750675, 2941031793, 234389378, 3121098346, 552746304, 1240292787, 2749223196, 2911200879, 3575079143, 2387877722, 56226183, 2234703068, 4280011272, 2242365487, 2018017386, 3120559877, 3029127512, 76026914, 3177333864, 3005037212, 779649575, 3013183545, 2164743696, 931414036, 59423493, 1275368408, 1414803373, 3990230148, 2088594422, 1188225634, 2944724829, 1746820395, 1685910229, 834306437, 1493402276, 2360893322, 3553642704, 29771524, 1090675414, 3011165295, 1063371514, 3940303196, 2577763706, 2185407339, 2491344105, 780054209, 3253655957, 1491625412, 1765967954, 2859073426, 3732521455, 1293856115, 1892088133, 148995653, 1484716015, 1889017950, 1269166526, 2838492749, 2418409421, 2209869646, 2522045468, 168513861, 3804997079, 1587811051, 1897846173, 2879779511, 3528031017, 2591223604, 3214640965, 3550383759, 2783793874, 2203740552, 3118026720, 2574427919, 3540330003, 3341696766, 3490004383, 3920451780, 2209488555, 1498679604, 331789812, 2435056342, 3810073792, 1163725363, 4006114636, 1560879500, 1837741532, 2185704910, 2798311217, 2991940915, 568480613, 2866397512, 3023365481, 970163083, 4289563056, 2270448642, 1850438485, 3664911059, 3605978328, 1336002490, 1355682756, 351606621, 3586308334, 1102330800, 3090559563, 2148719826, 3215451182, 2702159478, 1432967778, 3401990268, 2400799759, 2484974007, 1353690636, 2753559176, 2640489981, 1036931712, 1903649253, 964220241, 2773991379, 2133175336, 583322695, 2199489502, 3631891337, 1813009747, 456084772, 2320697906, 2974016610, 1520270050, 896145014, 2080304689, 1976066498, 2839737822, 1549783855, 4179969968, 1104386050, 837388826, 3165878801, 814640192, 3604179832, 2665037610, 3822828834, 2216452945, 2276503837, 634164486, 1412890410, 3261612008, 563171960, 3566738474, 2754595658, 681116053, 3118865924, 177463739, 139480302, 281558431, 1690126124, 1897842373, 152100710, 1389253223, 656498764, 465779469, 1700329794, 1161598335, 4182855549, 2896065503, 1169161019, 988049753, 141540097, 3920962023, 1414463815, 2649582854, 1247190586, 2345836198, 2096301443, 1735443990, 2410187529, 3110145792, 4259098967, 3496419344, 1323096534, 2280524624, 2704688879, 814213923, 2999267246, 3391489910, 3302983115, 105712882, 1051466424, 1317340325, 2155365832, 3664348767, 41875693, 2574817994, 2417654542, 2345990960, 3248572524, 2232341334, 2323122825, 3467411353, 2464771648, 3558780344, 2048000656, 2550689605, 3832657853, 588816494, 1928072148, 882779546, 2585956826, 4115174858, 2041950439, 3851200700, 3492163676, 2564516100, 4026987647, 2862754352, 11739424, 3152433432, 3038183071, 86904302, 4194617361, 1533432622, 2267744820, 1709636676, 2268808549, 306348255, 378915346, 3839473038, 3466138943, 1889711851, 4243725138, 2040287089, 2711698315, 2512890389, 1443237091, 1788173191, 3483735845, 187126422, 3972604184, 87146887, 1114058116, 3401707008, 1786906060, 1113751464, 3806893326, 752642051, 3083541814, 2468915599, 2445639645, 3885031785, 104242888, 3874118728, 2821368929, 2069280853, 2465759541, 76153213, 2243998971, 60618079, 432802985, 3403462072, 3617268113, 86582391, 978301034, 3106717053, 879484256, 4191758913, 3233938947, 1333422465, 4259870922, 878234880, 3752118900, 3493144181, 2923150231, 2387653130, 362351294, 3725228020, 446282046, 864505264, 819646991, 2142174716, 757107765, 3054689800, 980736009, 3781683590, 3228301270, 733658545, 44816498, 3764513000, 2648527937, 1175301170, 689878689, 3284446800, 582872017, 4081139934, 772717500, 2468163649, 1154957469, 1063689275, 2686616245, 3968673572, 1552104858, 3208534258, 3719381547, 4293124814, 4185971596, 2822157478, 2226770657, 2722172771, 3204920070, 3153368659, 3957403777, 3340401452, 358170452, 86873248, 3073864777, 1901787488, 1868606477, 3135506861, 2969520380, 612214934, 2360443633, 2158036096, 384976614, 1988412094, 2588500257, 2526449435, 4235741613, 440052124, 972557488, 1421976670, 1592981311, 1190795166, 123857612, 1450909778, 279599536, 97553494, 2356966581, 2886183120, 675956446, 1305595169, 1205008613, 3157245850, 1388240997, 2108861482, 2163666121, 3918485200, 2326199955, 3683465789, 3756179104, 1328336284, 703189534, 3141697951, 912546716, 3380018405, 2873689339, 1066530264, 272975397, 132319529, 2540398225, 3521502371, 2761283016, 2471199096, 3521041929, 756789292, 2527658902, 2755972832, 1885214085, 2175187093, 2258837609, 2586448274, 2964587075, 2168070343, 755385185, 2820998539, 3455906021, 1853441295, 498516020, 4189729152, 3555989654, 2264955912, 2663747569, 754868430, 234525495, 3316740819, 1374506476, 3843025136, 3711134757, 2912660137, 1250443668, 2288121539, 1768013429, 659068459, 1033379830, 3479740778, 900522158, 1758840019, 1292039331, 692167145, 3562019492, 3793770736, 450238625, 3629428994, 291785463, 1925186703, 125661517, 2883876802, 324456772, ], &[ 838935716, 2203587819, 915639214, 3753735741, 3643959629, 380366065, 2800082357, 479609169, 3344910139, 939862102, 341732586, 2006110852, 3452170213, 3812660487, 1864783975, 1318854193, 3422317845, 1427228514, 4149153373, 2684083624, 1074989654, 4073983073, 763800714, 4006319696, 119085884, 60830173, 991131160, 3219809387, 3231928830, 2959951027, 2787097517, 921471246, 453915876, 3731898283, 3251142762, 2579466369, 27120149, 2385740750, 1273661758, 3509690455, 3723885200, 4216400843, 3843558280, 78594259, 3230699712, 3825953413, 1142802181, 3138293244, 2095371158, 2351682776, 2501576120, 1676985000, 2623958874, 4227586876, 1860325172, 2090337755, 4281181325, 2213517873, 496143888, 2773301631, 3322452819, 737280293, 940258553, 320919084, 1595155948, 755694675, 3627876063, 3556466666, 2945032739, 4212566832, 2489967318, 612979803, 2998019149, 791094903, 2331887068, 3848194214, 1669109803, 586836653, 17421765, 4174252863, 2502645698, 1463986066, 33539085, 1789626263, 3342962255, 3824519205, 2026068357, 2765446594, 844159180, 3508825346, 1134575466, 1545918988, 3138211047, 2308850390, 1340320302, 1500877398, 4234310467, 1983405401, 1030999951, 2800668723, 4229219814, 3909258449, 3342207809, 3096542283, 1526382630, 456900343, 1292423164, 2023977467, 3452242468, 697297984, 2512301505, 1854858696, 2453945880, 475365007, 3487108263, 727126356, 3257286385, 514172720, 2342933557, 2456659886, 4293261548, 2045491426, 3978264522, 96991830, 728236868, 3356414658, 858180648, 3186522835, 315467595, 3025301039, 1022091990, 832213724, 1625707968, 1952252164, 1626399404, 2286098955, 1957714754, 935464737, 344352942, 2655128088, 2455096079, 3508589253, 1323890983, 18543456, 1120234679, 2368630283, 3464013570, 414956029, 1608237042, 3123061407, 3048565223, 1337447413, 2725081489, 3544363169, 3162272209, 1757543970, 3268970159, 2449039760, 3153678826, 666593731, 2303670329, 4257224320, 977258122, 428570155, 782781929, 3018115039, 453083041, 2998000053, 3874611711, 244856874, 2209589064, 365052855, 2255276114, 4268430165, 2172011676, 2202715955, 1929862469, 2117294128, 3787626628, 2347621422, 788538718, 690792725, 2069984822, 2567516370, 2156040001, 2753711351, 4233613434, 4029666569, 3098679112, 4024517832, 2132477759, 1327869411, 659072182, 2909455412, 3730675471, 679967738, 182649740, 194375197, 3841653420, 4027960673, 175135837, 1660264436, 3644680859, 4007751387, 2899873733, 3767998718, 1048209090, 1751066328, 4286847948, 135738204, 2614043038, 1982088957, 758427538, 3475803304, 2870686136, 4094121733, 1912601923, 2108805517, 47636847, 230717174, 1648662744, 3198815387, 919877866, 3677274799, 599980511, 3198454352, 962418282, 2571908668, 1214590864, 3203010561, 1973877631, 4097190280, 980645781, 730416487, 1042657050, 3749371087, 2876213668, 1057105900, 452303833, 936771815, 2711618145, 3682803011, 4148511396, 2871128258, 1670210392, 363675039, 1226232864, 2545473472, 2847607537, 706216472, 668367486, 3335248515, 684311493, 1922073430, 2173646273, 1758431003, 553691538, 2135670731, 4237772697, 1307471006, 1673244127, 475473888, 1489978871, 3151848780, 3727938421, 2510602424, 1534771587, 1514732764, 3961802829, 1749640392, 3073492043, 4184684257, 2678493181, 1016148119, 162968394, 1542225613, 3314073214, 742431147, 2655829423, 2077968934, 3307840731, 3166378296, 3380012342, 1628856437, 2492930090, 1125050986, 3917568307, 2081901207, 1910847527, 2713093801, 1095695739, 2968092789, 3472722113, 377271708, 1040508736, 948060390, 2161675070, 385186644, 4184834501, 1657036626, 2397219251, 2440643845, 440875536, 2390881422, 1456820922, 2584489112, 3663536575, 3123816215, 2449538096, 3006681818, 2608705815, 4192739282, 1380673229, 3059394456, 1566510861, 2531146664, 1359283390, 2012589430, 4200074946, 3098609836, 4006992613, 4077565448, 1974438847, 1221683442, 1719050478, 3161792955, 2578040126, 3061737012, 367079059, 3046588169, 1563359926, 2224001306, 2791171902, 2289618085, 3388295848, 3287189754, 2674283012, 2056956826, 3968642769, 3774531757, 3562296786, 3475855578, 618682730, 3174665899, 4290008806, 1008009435, 1700412634, 2902015788, 2972205524, 2584006496, 4087976424, 678816164, 2093048627, 2385841515, 846482516, 1762625699, 4062395767, 1067045848, 4162678883, 3600728522, 1571165888, 3489010385, 787541038, 1248805154, 2599773530, 115140567, 2919051278, 3369387442, 4107879124, 2428887338, 994007703, 2665777337, 3130672163, 982959104, 2698714317, 1460766600, 1821697637, 3330816250, 2095057996, 830788453, 3990976194, 1800223602, 2026811060, 2393136879, 1189765438, 1109812562, 3311727428, 3224449942, 4237200199, 3873080150, 2683760941, 4088732835, 614500558, 711266360, 2147434665, 3808624639, 3034313567, 1059395674, 1561883669, 103784012, 2032335571, 2800686028, 609480554, 1769603386, 4151398145, 2185648870, 1739535600, 1586519522, 572991424, 1068733442, 2619062803, 4041514271, 1086033525, 11857992, 3192078073, 1344195581, 1238380717, 4077237295, 3875651208, 292286543, 619476155, 2161959405, 1203958830, 4290561761, 3693181580, 3900343517, 2797356182, 4084172378, 261394861, 769278713, 4199742495, 2309375370, 3346948261, 3750248064, 2567542765, 3972013578, 3992801407, 3056612552, 554436073, 2730615770, 1231284851, 2255256795, 1587098949, 1645198162, 2603125261, 1127388761, 860864076, 3375951570, 2228774088, 1597961976, 412935124, 2173190974, 1415442621, 3815450429, 4044940139, 1867706821, 1053298761, 2092988724, 738251343, 2294030391, 1030772826, 3106409390, 2170123922, 1863396860, 690798362, 3794558912, 3566843628, 121083434, 994730387, 574163581, 2016938790, 2148010580, 197642070, 2380205705, 3769045477, 1675706118, 4120416559, 3559669638, 376897093, 1128063177, 74421326, 761413501, 3392222006, 1321099529, 47433813, 2130311331, 1584264183, 4078065031, 4056472694, 1048381830, 2103467739, 1824423056, 2776327151, 434780346, 4017942257, 2398098907, 3022379282, 21450696, 2803414267, 3336384729, 3655253595, 2013481291, 629727070, 304283403, 3969058801, 343107726, 3930196577, 1050996951, 1696216281, 4113049883, 2063680700, 3299802318, 2169413090, 599831066, 265205477, 86598633, 1318950976, 2817019822, 3523559767, 1192997804, 967006658, 2618135270, 652785590, 1396546377, 85541097, 1498343279, 1545058670, 1004723554, 3231552447, 628138355, 4033681503, 2114084638, 3662581523, 2278439544, 3504753352, 1762732636, 1199413890, 2921045813, 2558711012, 849244440, 3149132172, 2553108318, 1232917889, 3271342783, 3248249426, 1731072265, 2957986492, 1684696396, 3968320398, 2537362303, 2030936713, 1234679023, 4192065531, 4222971816, 3064892308, 2590492328, 288251267, 2550089391, 879932618, 784103313, 3344367287, 676675271, 2000590552, 3777064239, 3282963152, 860961137, 689785050, 3572163643, 2233769790, 4104660183, 855938732, 2821571786, 2808753272, 1281740498, 969712731, 474012755, 4001231436, 3985764292, 2862143307, 994442730, 1243356938, 1775451246, 722781566, 3131106180, 3339337915, 2271184254, 1079900234, 2744647618, 1638963938, 4263302376, 3563278731, 1946093388, 1809549982, 2256560928, 2960989550, 1799848335, 3793311156, 4262135533, 2448031337, 319777785, 1925667888, 2774876369, 2635247551, 2921425304, 1354802634, 2456898309, 1860471049, 2869265862, 3082305168, 3898824849, 3125463798, 4212194039, 1623533549, 1173751565, 2496120567, 50014129, 13149499, 4167145366, 1955034137, 1636727570, 404325094, 1751899763, 3718846670, 2966030995, 3631249081, 850012394, 3102446697, 2042206947, 2248313443, 2785796194, 2751107788, 3825364911, 839857966, 3593553796, 2978187162, 1963772991, 2535947700, 3591089575, 972097984, 3139361936, 1671749808, 2397938437, 3496814669, 1899924710, 750821353, 2796989722, 3330933794, 741406274, 4044115699, 1664390021, 828823849, 4263496205, 809061833, 1366595084, 1030792229, 1836547249, 3859902111, 1449813785, 658840733, 2048685768, 4124870169, 2673685491, 2426733455, 2333311310, 3492090101, 1992837915, 11511403, 2540925625, 2852742586, 2179960638, 2931055419, 3659567067, 1933074409, 649207452, 4276721791, 4191972082, 539633860, 17233553, 1594779948, 4215033555, 181714143, 685754269, 1956851130, 589401843, 3102481839, 497723403, 952363536, 3336958173, 375851460, 3769041100, 2814705111, 503471929, 434207586, 4273458948, 3293647658, 2353814912, 2821137839, 2876582042, 160572601, 1201368925, 60357568, 139088744, 721227061, 2623980501, 3943799534, 3041058274, 2977612913, 3291630599, 349175514, 3961677955, 3235620723, 2972138888, 2079236907, 3547729544, 3780005092, 1440555729, 2438143802, 4201044301, 2714313685, 3486585540, 2800950188, 1801147672, 3703751487, 2461295830, 380678753, 3708873777, 40573490, 2437248324, 198586160, 669549162, 720284965, 2019671626, 1452819480, 495221607, 816889749, 3963879039, 2755252053, 1699095522, 1122700669, 292682575, 2542299989, 32521186, 2188233807, 2468163267, 292904686, 3223433980, 2703281150, 1173144272, 3313052362, 3356734471, 2695828969, 460370984, 3371854267, 351372515, 544848035, 665581896, 405416947, 1277394067, 1797975604, 937658179, 794722376, 8125493, 3456647328, 1780985597, 3741333943, 3296469654, 1660046360, 2306936782, 3661850759, 4080591659, 2501854245, 1384493589, 3663701959, 1729039559, 900961315, 1098594423, 2562550163, 1148027253, 3616002981, 334019448, 2850279078, 4060960913, 1287642279, 3376572244, 2534805166, 1377930878, 3804442725, 1383027131, 2082023911, 1793040924, 348666885, 2304696682, 256389582, 3478053630, 698728310, 2037905177, 3976969740, 3230702660, 1299868963, 2833628697, 2930863988, 2357656502, 1343551287, 2011573652, 3097268490, 3399030503, 209755840, 537294183, 3998427081, 1076591702, 1263890468, 1782599039, 3780229996, 1024431710, 2833602231, 3777979580, 4078024794, 872524254, 352227412, 1351273981, 852004662, 1161960014, 1906524671, 204792238, 2663768241, 4072664750, 3414324694, 286128037, 1110040325, 900463961, 963252168, 341367983, 3248675265, 1219574682, 408882044, 4029283861, 2041191997, 2273854782, 3408304833, 2242938048, 3436897597, 2980462347, 2514777114, 2857882805, 461470076, 3109832332, 3200488424, 4074902801, 3969927253, 729904888, 4152956776, 689265400, 3124361813, 2969684080, 1117396653, 2927468191, 4173382674, 4220933905, 2013331272, 1607793854, 3861336002, 1873865360, 16258643, 2300509732, 3479887951, 2336999346, 159459282, 3950452492, 3929460924, 705609132, 526429974, 676661281, 3888522264, 1774544613, 3921273959, 157436604, 4006393372, 3620960941, 1816027785, 976626829, 1147734086, 4071348376, 2542528107, 962473538, 1088491988, 1609404762, 914564813, 1410211333, 3779344617, 4175461012, 824484826, 2980214363, 3955476205, 3424635742, 740023698, 1869598491, 649848532, 486101202, 2723887281, 2776425384, 682654951, 48707499, 3215265093, 2091228948, 3882341515, 2914449810, 4145012253, 2500281477, 1192252445, 2720083567, 3606499354, 2308681139, 3417499332, 2673063768, 2245530872, 1594809199, 2961185232, 2154329832, 3212262766, 2884845477, 3476290762, 2814732863, 2643163160, 1881713506, 2949244325, 4196436484, 2317791900, 4235123047, 1093953049, 5453429, 3068787991, 3345927257, 1386287281, 1495554810, 3092636873, 1484259532, 3600514898, 2957555206, 3348133074, 2055353028, 681494686, 377599951, 812642228, 1988902688, 2634311151, 1839068105, 3616435588, 444035475, 3061487513, 55224199, 2434767613, 2830319279, 473221113, 2719964944, 2466794715, 4145309788, 1222340136, 173399292, 2934551672, 1337072089, 208573081, 3208261196, 460363797, 2972654949, 4049253252, 3382433428, 3953728176, 3042257654, 1441354805, 871221561, 1750912796, 3684367914, 969056696, 1128407825, 1312971320, 350151817, 1913948880, 162760467, 2927001962, 271548687, 4233867754, 4187064028, 1752223315, 3566855814, 3098906749, 940415226, 1450714578, 2089508179, 685807392, 1094880779, 3618434588, 1852947202, 317434962, 1659500546, 3597259289, 2888477399, 2671081767, 2440146053, 2035849436, 3156792370, 4265496433, 1525348048, 2545566909, 1778313912, 2782108361, 2017683243, 1447595289, 4213477653, 356590757, 3887333316, 1375294643, 166093975, 3646164777, 2470748042, 2344217837, 1900424442, 3867136564, 3763279553, 3894629246, 1025417778, 4274768880, 3262354653, 1368425302, 108316157, 1343309487, 2548223206, 3292698474, 2074720811, 2415701834, 2319728429, 4253222152, 1823863126, 671442975, 2815690234, 166017875, 4133918798, 2341656544, 1195071311, 3591080201, 2727319421, 323604173, 3467106257, 1807836963, 3351025639, 2903513081, 1902463642, 2877952685, 2401135475, 1661402701, 179177133, 2157408987, 3104539005, 1187176474, 216324254, 3682100936, 47318979, 4266538909, 1364880663, 3089835665, 2974326632, 136715739, 21460991, 875857069, 3634182054, 3507421393, 2816493641, 2428086359, 2677298183, 4144250643, 3067655705, 2047511728, 581965183, 3555378151, 3320505513, 1784970183, 3537100678, 2661089461, 1915923033, 4016714600, 780795784, 660039721, 1585895448, 4267382956, 788816746, 441129301, 2642236828, 3236397688, 4098671167, 417254115, 1512419440, 2595207623, 714330442, 1793107412, 1915812662, 1065761790, 559987752, 2473228903, 2857904446, 176611125, 1056992200, 3785703632, 1081171201, 352847890, 1749283439, 2145600786, 2611374980, 2819729772, 1330960860, 237844587, 1927429738, 63223319, 3015994684, 3325055109, 1399511661, 2815713002, 2466135290, 681412319, 3776472186, 2316275012, 3463722640, 845546679, 3470095507, 141194431, 4021588401, 723350993, 3043631697, 3504648579, 2019448585, 3063288730, 581965108, 4096321988, 2137034574, 295040412, 445386599, 3257986313, 716955156, 1644931397, 55457860, 252470757, 670110185, 1740055863, 2418200077, 2304754384, 3105055645, 23205783, 1131503062, 216403393, 2353961029, 3130064620, 3993811637, 1483619628, 649295085, 1095042730, 2656243769, 1223292028, 582240413, 1206780397, 2973061534, 4292796836, 3537057693, 4187363592, 491905630, 179086816, 1772613819, 2747068600, 1832416612, 1180763400, 818642060, 36609327, 1658217467, 2050606159, 3032666431, 3767423337, 1111353105, 1522267728, 1631984380, 3190473602, 3680487263, 734566855, 2353333066, 986328581, 3681689264, 1595897310, 3335184558, 2507600517, 2490029559, 2745986115, 4181623162, 3432004504, 2145423842, 2367982528, 2806960322, 3076340209, 505849942, 533374703, 1257745383, 644213956, 2962046646, 2201943625, 237256910, 3874792384, 983086135, 1654746256, 3220085267, 3164213233, 1962620300, 3406864224, 284885940, 2339029442, 1267505911, 3660344615, 3917330963, 3551145561, 3488278296, 1907092122, 2980179347, 54406137, 1998418578, 1902516963, 2207644610, 3941412978, 1623928004, 485916323, 3615926304, 523041942, 115202452, 2022521528, 1490106543, 1835947191, 4260360619, 1424916687, 2528887699, 3933621604, 3297208940, 2162596225, 1222503210, 2136147383, 2425841507, 3933152399, 4238982603, 2877219680, 3629789132, 3074841443, 3440850273, 521778548, 197924155, 209664882, 4244045891, 4041802190, 213808, 1061287415, 4109828330, 3118408869, 628642373, 537513117, 534884706, 3291471519, 3166304457, 1868482021, 459148534, 1009990526, 2380010357, 890059218, 604931398, 3306919535, 2774345113, 820980298, 2438859282, 2852945605, 3422427217, 3698390489, 3313390587, 3080508268, 2767314620, 3842719809, 3355496804, 2278214546, 1228854785, 3963672337, 3480498117, 1185458174, 254331697, 4075265013, 1893263033, 1251932761, 2009544780, 559074272, 253120496, 1936501741, 1726021337, 4053670081, 2881809588, 2485095543, 1685412297, 3542536640, 2366264687, 637664695, 1837220786, 354783458, 2949531247, 2469565699, 974572166, 3336819772, 1219492409, 2302227018, 3368888008, 1441596117, 4139261093, 3992023496, 2186276726, 1337085007, 1297128349, 3345717969, 1502084009, 4279269575, 746110129, 357443087, 1184174039, 3510875879, 3851501689, 2612516856, 603491753, 797427139, 852360679, 1117907315, 1427571936, 817235609, 3158982462, 259347609, 1788586925, 1148039424, 3368411210, 1634605211, 400804429, 936765965, 1742182939, 1903805118, 1538100182, 2176265557, 2662759467, 984261631, 4020913363, 1487175843, 2947614836, 1900701443, 4060998848, 4029580532, 2688679851, 1811723482, 1453238253, 3787617091, 2282686689, 3993782144, 21304404, 507557860, 2944490999, 182972447, 3174956974, 869715075, 3277689659, 1814259483, 4163075289, 3873534736, 462031943, 3153254355, 1301198786, 3943710461, 3909340915, 504180560, 2041140274, 3440956310, 3656453113, 3273349780, 3481111110, 3576620931, 2732393968, 3946434431, 659377962, 677158288, 670305147, 974547443, 310689727, 94218257, 1724518031, 1905703897, 1286333546, 2751245199, 5571896, 3457747128, 2179848102, 3894181682, 4124381231, 3410266880, 709398455, 187319059, 3511629688, 3559400976, 2489398231, 600737488, 3595918510, 3798083973, 4026752984, 4210193948, 68891514, 3947247567, 3107252542, 1170883420, 1834752658, 2941121513, 3841122236, 2470855721, 182150380, 3416558885, 1477637651, 995210324, 588847561, 2552679828, 64224740, 961985977, 1427921858, 3494336204, 1146890788, 3705393264, 3874804387, 49839043, 1196485418, 4243424919, 215134702, 1706006595, 423982823, 710751734, 346438174, 2785074971, 3048570439, 3828658776, 443370961, 4028150602, 942994137, 720074843, 1909180916, 647304255, 1473324775, 1036517605, 440850580, 3455287996, 2297168269, 2592528575, 323504231, 292579127, 649004565, 281112587, 2639333091, 2098301904, 2778751588, 2025098146, 1805301626, 1552474374, 3081073479, 4079139025, 919447806, 2132238174, 3776363222, 1050273203, 2654179515, 31684454, 55205341, 2546554914, 1088968049, 1402421698, 3682384666, 1553165183, 115328209, 3405269619, 2255597873, 1379651895, 2310622780, 1996922494, 1033698934, 3481464610, 1795184151, 152194312, 1061361554, 1284312248, 1338186205, 4098514812, 2874751651, 2866358430, 412769457, 2483498856, 4198676447, 71720962, 3683175370, 3989356764, 2846917228, 921604934, 1635603564, 2971093080, 742806196, 2398879483, 3298081490, 4237003774, 2380113868, 1568001623, 2624936612, 3176752214, 2867181933, 1917549358, 4044310480, 1307704115, 3767119746, 4201150796, 1450449070, 744907957, 1114261347, 2636959698, 117707599, 1450886244, 2336471832, 1236404162, 2912700530, 3665684179, 3640387930, 2966734192, 3208997144, 1270408976, 308398801, 2329948514, 343477117, 2365820358, 3697864380, 16124765, 968064396, 551610086, 3261227824, 3845306004, 2839278865, 1710063436, 529765606, 2590339389, 2232645965, 2220674716, 4175021164, 1253655722, 1585348878, 3251476604, 3936991537, 190532800, 4099120852, 1806314545, 530090133, 461441516, 3941506885, 3666450612, 3737219241, 1320249304, 2052469119, 2016428234, 3789822793, 3096501122, 1858994377, 3384814016, 3282125914, 27976241, 4138503041, 4076911591, 2610665395, 992528352, 1507678034, 3833126488, 3471104910, 876024133, 4017994422, 3413457336, 534460630, 4014654886, 4064894491, 2863983481, 92546398, 1436623597, 2255152241, 1523252476, 3763913562, 2628132090, 1984279468, 2113001554, 2108275221, 1060884588, 2747717543, 1986766057, 1622949311, 2332772870, 3332840810, 2524006752, 336521846, 4071972450, 324329553, 3149454512, 187149260, 2031485001, 3480471856, 2265780046, 3792798369, 3177913371, 2347210476, 4081333345, 4046146024, 2917080827, 590638612, 270185333, 2805124246, 460831443, 3496962886, 4271837334, 988718092, 1152316522, 3942609672, 3794345353, 1149696567, 1402909182, 494716490, 1245651130, 1943182059, 1599846823, 3504994553, 1535906884, 1749731330, 1919915129, 3952459270, 1846223130, 602074928, 1536114851, 4291196323, 2411210106, 646156071, 636908156, 390344456, 3173016861, 1180977247, 1710702402, 2756888285, 747439941, 4092116022, 4113279650, 3090618475, 396445650, 3996355793, 3860756326, 3383911526, 2918629863, 564066118, 1331988394, 3762172819, 4160630094, 845911615, 4045163162, 2379948201, 4071794973, 3679892002, 1449801312, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_fail_1() { let ns = &mut [1, 2]; let ds = &[]; let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_fail_2() { let ns = &mut []; let ds = &[]; let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_fail_3() { let ns = &mut [1, 2]; let ds = &[1, 2, 3]; let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_fail_4() { let ns = &mut [1, 2, 3, 4]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_fail_5() { let ns = &mut [1, 2, 3, 4]; let ds = &[4, 5]; let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_ref_fail_1() { let ns = &[1, 2]; let ds = &[]; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_ref_fail_2() { let ns = &[]; let ds = &[]; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_ref_fail_3() { let ns = &[1, 2]; let ds = &[1, 2, 3]; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_ref_fail_4() { let ns = &[1, 2, 3, 4]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut [10; 3], ns, ds, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_modular_div_ref_fail_5() { let ns = &[1, 2, 3, 4]; let ds = &[4, 5]; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut [10; 3], ns, ds, &mut scratch); } fn verify_limbs_div_exact(ns: &[Limb], ds: &[Limb], qs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let expected_q = Natural::from_limbs_asc(qs); let (q, r) = n.div_mod(d); assert_eq!(q, expected_q); assert_eq!(r, 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_exact() { let test = |qs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut mut_ns = ns.to_vec(); let mut mut_ds = ds.to_vec(); limbs_div_exact_to_out(&mut qs, &mut mut_ns, &mut mut_ds); let q_len = ns.len() - ds.len() + 1; assert_eq!(&qs[..q_len], qs_out); let mut qs = qs_in.to_vec(); let mut mut_ns = ns.to_vec(); limbs_div_exact_to_out_val_ref(&mut qs, &mut mut_ns, ds); let q_len = ns.len() - ds.len() + 1; assert_eq!(&qs[..q_len], qs_out); let mut qs = qs_in.to_vec(); let mut mut_ds = ds.to_vec(); limbs_div_exact_to_out_ref_val(&mut qs, ns, &mut mut_ds); let q_len = ns.len() - ds.len() + 1; assert_eq!(&qs[..q_len], qs_out); let mut qs = qs_in.to_vec(); limbs_div_exact_to_out_ref_ref(&mut qs, ns, ds); let q_len = ns.len() - ds.len() + 1; assert_eq!(&qs[..q_len], qs_out); let qs = limbs_div_exact(ns, ds); let qs: &[Limb] = &qs; assert_eq!(&qs_out[..qs.len()], qs); verify_limbs_div_exact(ns, ds, qs_out); }; // - d_len == 1 test(&[10; 3], &[6], &[2], &[3]); // - leading_zero_limbs == 0 // - d_len != 1 // - shift == 0 // - d_len <= q_len test(&[5; 8], &[1, 3, 6, 5, 3], &[1; 3], &[1, 2, 3]); // - d_len > q_len test(&[0; 5], &[6, 19, 32, 21], &[1, 2, 3], &[6, 7]); // - shift != 0 test(&[0; 5], &[6, 19, 32, 21], &[6, 7], &[1, 2, 3]); test( &[10; 7], &[10200, 20402, 30605, 20402, 10200], &[100, 101, 102], &[102, 101, 100], ); test(&[10; 3], &[u32::MAX], &[u32::MAX], &[1]); test(&[10; 4], &[1, u32::MAX - 1], &[u32::MAX], &[u32::MAX, 0]); test( &[10; 6], &[1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], &[u32::MAX; 3], &[u32::MAX, u32::MAX, u32::MAX, 0], ); // - leading_zero_limbs != 0 test( &[0; 5], &[0, 0, 0, 6, 19, 32, 21], &[0, 0, 1, 2, 3], &[0, 6, 7], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_fail_1() { limbs_div_exact(&[6, 19, 32, 21], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_fail_2() { limbs_div_exact(&[6, 19, 32, 21], &[1, 2, 3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_fail_3() { limbs_div_exact(&[6, 19, 32, 21], &[1, 2, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_fail_1() { limbs_div_exact_to_out(&mut [10; 5], &mut [6, 19, 32, 21], &mut []); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_fail_2() { limbs_div_exact_to_out(&mut [10; 5], &mut [6, 19, 32, 21], &mut [1, 2, 3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_fail_3() { limbs_div_exact_to_out(&mut [10; 5], &mut [6, 19, 32, 21], &mut [1, 2, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_fail_4() { limbs_div_exact_to_out(&mut [10], &mut [6, 19, 32, 21], &mut [1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_val_ref_fail_1() { limbs_div_exact_to_out_val_ref(&mut [10; 5], &mut [6, 19, 32, 21], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_val_ref_fail_2() { limbs_div_exact_to_out_val_ref(&mut [10; 5], &mut [6, 19, 32, 21], &[1, 2, 3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_val_ref_fail_3() { limbs_div_exact_to_out_val_ref(&mut [10; 5], &mut [6, 19, 32, 21], &[1, 2, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_val_ref_fail_4() { limbs_div_exact_to_out_val_ref(&mut [10], &mut [6, 19, 32, 21], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_val_fail_1() { limbs_div_exact_to_out_ref_val(&mut [10; 5], &[6, 19, 32, 21], &mut []); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_val_fail_2() { limbs_div_exact_to_out_ref_val(&mut [10; 5], &[6, 19, 32, 21], &mut [1, 2, 3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_val_fail_3() { limbs_div_exact_to_out_ref_val(&mut [10; 5], &[6, 19, 32, 21], &mut [1, 2, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_val_fail_4() { limbs_div_exact_to_out_ref_val(&mut [10], &[6, 19, 32, 21], &mut [1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_ref_fail_1() { limbs_div_exact_to_out_ref_ref(&mut [10; 5], &[6, 19, 32, 21], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_ref_fail_2() { limbs_div_exact_to_out_ref_ref(&mut [10; 5], &[6, 19, 32, 21], &[1, 2, 3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_ref_fail_3() { limbs_div_exact_to_out_ref_ref(&mut [10; 5], &[6, 19, 32, 21], &[1, 2, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_exact_to_out_ref_ref_fail_4() { limbs_div_exact_to_out_ref_ref(&mut [10], &[6, 19, 32, 21], &[1, 2, 3]); } #[test] fn test_div_exact() { let test = |s, t, quotient| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); x.div_exact_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); x.div_exact_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let q = u.clone().div_exact(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.clone().div_exact(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = (&u).div_exact(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = (&u).div_exact(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); let q = u.div_round(v, Exact).0; assert_eq!(q.to_string(), quotient); let q = rug::Integer::from_str(s) .unwrap() .div_exact(&rug::Integer::from_str(t).unwrap()); assert_eq!(q.to_string(), quotient); }; test("0", "123", "0"); test("123", "1", "123"); test("123", "123", "1"); test("56088", "123", "456"); test("0", "1000000000000", "0"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "1000000000000", "1"); test("123000000000000", "1000000000000", "123"); test("123000000000000", "123", "1000000000000"); test("121932631112635269000000", "123456789000", "987654321000"); test("8589934590", "4294967295", "2"); test("18446744065119617025", "4294967295", "4294967295"); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", "577397114388109712462006371470162814529304445639807296878809567953200969820156259914159240\ 9106139481288193067515284601342023565222679498917484131095648263181800618990427694244342686\ 4412105186059052689237237088193855584354278755933606296018800151986520872701706693002473648\ 4330061421236425747083307907706860804054565348593527605104495080560663025897787060638154303\ 7631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", ); } #[test] #[should_panic] fn div_exact_assign_fail() { let mut n = Natural::from(10u32); n.div_exact_assign(Natural::ZERO); } #[test] #[should_panic] fn div_exact_assign_ref_fail() { let mut n = Natural::from(10u32); n.div_exact_assign(&Natural::ZERO); } #[test] #[should_panic] fn div_exact_fail() { Natural::from(10u32).div_exact(Natural::ZERO); } #[test] #[should_panic] fn div_exact_val_ref_fail() { Natural::from(10u32).div_exact(&Natural::ZERO); } #[test] #[should_panic] fn div_exact_ref_val_fail() { (&Natural::from(10u32)).div_exact(Natural::ZERO); } #[test] #[should_panic] fn div_exact_ref_ref_fail() { (&Natural::from(10u32)).div_exact(&Natural::ZERO); } #[test] fn limbs_modular_invert_limb_properties() { unsigned_gen_var_22().test_properties(|x| { let inverse = limbs_modular_invert_limb::(x); assert_eq!(x.wrapping_mul(inverse), 1); assert_eq!(limbs_modular_invert_limb::(inverse), x); }); } #[test] fn limbs_div_exact_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_29().test_properties_with_config(&config, |(xs, y)| { let expected_result = Natural::from_limbs_asc(&xs).div_exact(Natural::from(y)); assert_eq!( Natural::from_owned_limbs_asc(limbs_div_exact_limb(&xs, y)), expected_result ); assert_eq!( Natural::from_owned_limbs_asc(limbs_div_exact_limb_no_special_3(&xs, y)), expected_result ); }); } #[test] fn limbs_div_exact_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_14().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_div_exact_limb_to_out::(&mut out, &xs, y); let len = xs.len(); let expected_result = Natural::from_limbs_asc(&xs).div_exact(Natural::from(y)); assert_eq!(Natural::from_limbs_asc(&out[..len]), expected_result); assert_eq!(&out[len..], &old_out[len..]); let mut out = old_out.to_vec(); limbs_div_exact_limb_to_out_no_special_3::(&mut out, &xs, y); let len = xs.len(); let expected_result = Natural::from_owned_limbs_asc(xs).div_exact(Natural::from(y)); assert_eq!(Natural::from_limbs_asc(&out[..len]), expected_result); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_div_exact_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_29().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_div_exact_limb_in_place(&mut xs, y); let expected_result = Natural::from_limbs_asc(&old_xs).div_exact(Natural::from(y)); assert_eq!(Natural::from_owned_limbs_asc(xs), expected_result); let mut xs = old_xs.to_vec(); limbs_div_exact_limb_in_place_no_special_3(&mut xs, y); let expected_result = Natural::from_owned_limbs_asc(old_xs).div_exact(Natural::from(y)); assert_eq!(Natural::from_owned_limbs_asc(xs), expected_result); }); } #[test] fn limbs_div_exact_3_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_5().test_properties_with_config(&config, |xs| { let q_limbs = Natural::from_owned_limbs_asc(limbs_div_exact_3(&xs)); assert_eq!( Natural::from_owned_limbs_asc(limbs_div_exact_limb(&xs, 3)), q_limbs, ); assert_eq!( Natural::from_owned_limbs_asc(xs).div_exact(Natural::from(3u32)), q_limbs ); }); } #[test] fn limbs_div_exact_3_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_13().test_properties_with_config(&config, |(mut out, xs)| { let old_out = out.clone(); limbs_div_exact_3_to_out::(&mut out, &xs); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_limbs_asc(&xs).div_exact(Natural::from(3u32)) ); assert_eq!(&out[len..], &old_out[len..]); let mut out_alt = old_out.clone(); limbs_div_exact_limb_to_out::(&mut out_alt, &xs, 3); assert_eq!(out_alt, out); let mut out_alt = old_out; limbs_div_exact_3_to_out_alt(&mut out_alt, &xs); assert_eq!(out_alt, out); }); } #[test] fn limbs_div_exact_3_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_5().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); limbs_div_exact_3_in_place(&mut xs); assert_eq!( Natural::from_limbs_asc(&xs), Natural::from_limbs_asc(&old_xs).div_exact(Natural::from(3u32)) ); let mut xs_alt = old_xs.to_vec(); limbs_div_exact_limb_in_place(&mut xs_alt, 3); assert_eq!(xs_alt, xs); let mut xs_alt = old_xs.to_vec(); limbs_div_exact_3_in_place_alt(&mut xs_alt); assert_eq!(xs_alt, xs); }); } #[test] fn limbs_modular_invert_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_12().test_properties_with_config(&config, |(mut is, ds)| { let n = ds.len(); let mut scratch = vec![0; limbs_modular_invert_scratch_len(n)]; limbs_modular_invert(&mut is, &ds, &mut scratch); verify_limbs_modular_invert(&ds, &is[..n]); }); } #[test] fn limbs_modular_div_mod_schoolbook_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_14().test_properties_with_config( &config, |(mut qs, mut ns, ds, inverse)| { let ns_old = ns.clone(); let borrow = limbs_modular_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse); let q_len = ns.len() - ds.len(); verify_limbs_modular_div_mod(&ns_old, &ds, borrow, &qs[..q_len], &ns[q_len..]); }, ); } #[test] fn limbs_modular_div_mod_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); large_type_gen_var_15().test_properties_with_config( &config, |(mut qs, mut ns, ds, inverse)| { let ns_old = ns.clone(); let borrow = limbs_modular_div_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); let q_len = ns.len() - ds.len(); verify_limbs_modular_div_mod(&ns_old, &ds, borrow, &qs[..q_len], &ns[q_len..]); }, ); } #[test] fn limbs_modular_div_mod_barrett_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_2().test_properties_with_config( &config, |(mut qs, mut rs, ns, ds)| { let mut scratch = vec![0; limbs_modular_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let borrow = limbs_modular_div_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); let q_len = ns.len() - ds.len(); verify_limbs_modular_div_mod(&ns, &ds, borrow, &qs[..q_len], &rs[..ds.len()]); }, ); } #[test] fn limbs_modular_div_schoolbook_properties() { large_type_gen_var_13().test_properties(|(mut qs, mut ns, ds, inverse)| { let ns_old = ns.clone(); limbs_modular_div_schoolbook(&mut qs, &mut ns, &ds, inverse); verify_limbs_modular_div_neg(&ns_old, &ds, &qs); let mut ns = ns_old.to_vec(); limbs_modular_div_schoolbook_in_place(&mut ns, &ds, inverse); assert_eq!(ns, &qs[..ns.len()]); }); } #[test] fn limbs_modular_div_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); large_type_gen_var_16().test_properties_with_config( &config, |(mut qs, mut ns, ds, inverse)| { let ns_old = ns.clone(); limbs_modular_div_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); verify_limbs_modular_div(&ns_old, &ds, &qs); }, ); } #[test] fn limbs_modular_div_barrett_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_46().test_properties_with_config(&config, |(mut qs, ns, ds)| { let mut scratch = vec![0; limbs_modular_div_barrett_scratch_len(ns.len(), ds.len())]; limbs_modular_div_barrett(&mut qs, &ns, &ds, &mut scratch); verify_limbs_modular_div(&ns, &ds, &qs[..ns.len()]); }); } #[test] fn limbs_modular_div_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_47().test_properties_with_config( &config, |(mut qs, mut ns, ds)| { let qs_old = qs.clone(); let ns_old = ns.clone(); let mut scratch = vec![0; limbs_modular_div_scratch_len(ns.len(), ds.len())]; limbs_modular_div(&mut qs, &mut ns, &ds, &mut scratch); let result = qs; let mut qs = qs_old.to_vec(); let ns = ns_old; let mut scratch = vec![0; limbs_modular_div_ref_scratch_len(ns.len(), ds.len())]; limbs_modular_div_ref(&mut qs, &ns, &ds, &mut scratch); assert_eq!(qs, result); verify_limbs_modular_div(&ns, &ds, &qs[..ns.len()]); }, ); } #[test] fn limbs_div_exact_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_48().test_properties_with_config( &config, |(mut qs, mut ns, mut ds)| { let qs_old = qs.clone(); let ns_old = ns.clone(); let ds_old = ds.clone(); limbs_div_exact_to_out(&mut qs, &mut ns, &mut ds); let result = qs; let mut qs = qs_old.to_vec(); let mut ns = ns_old.to_vec(); let mut ds = ds_old.to_vec(); limbs_div_exact_to_out_val_ref(&mut qs, &mut ns, &ds); assert_eq!(qs, result); let mut qs = qs_old.to_vec(); let ns = ns_old; limbs_div_exact_to_out_ref_val(&mut qs, &ns, &mut ds); assert_eq!(qs, result); let mut qs = qs_old.to_vec(); let ds = ds_old; limbs_div_exact_to_out_ref_ref(&mut qs, &ns, &ds); assert_eq!(qs, result); let q_len = ns.len() - ds.len() + 1; let qs = limbs_div_exact(&ns, &ds); assert_eq!(qs, &result[..q_len]); verify_limbs_div_exact(&ns, &ds, &qs[..q_len]); }, ); } #[test] fn div_exact_properties() { natural_pair_gen_var_6().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.div_exact_assign(&y); assert!(mut_x.is_valid()); let q = mut_x; let mut mut_x = x.clone(); mut_x.div_exact_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, q); let q_alt = (&x).div_exact(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = (&x).div_exact(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone().div_exact(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = x.clone().div_exact(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); let q_alt = (&x).div_round(&y, Exact).0; assert_eq!(q_alt, q); assert_eq!( Natural::exact_from(&rug::Integer::from(&x).div_exact(&rug::Integer::from(&y))), q ); assert_eq!(q * y, x); }); natural_gen().test_properties(|n| { assert_eq!((&n).div_exact(Natural::ONE), n); }); natural_gen_var_2().test_properties(|n| { assert_eq!(Natural::ZERO.div_exact(&n), 0); assert_eq!((&n).div_exact(&n), 1); }); unsigned_pair_gen_var_11::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).div_exact(Natural::from(y)), x.div_exact(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/div_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivAssignNegMod, CeilingDivNegMod, DivAssignMod, DivAssignRem, DivMod, DivRem, DivRound, NegMod, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, JoinHalves}; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_12, unsigned_pair_gen_var_12, unsigned_pair_gen_var_35, unsigned_vec_pair_gen_var_11, unsigned_vec_triple_gen_var_50, unsigned_vec_triple_gen_var_51, unsigned_vec_triple_gen_var_53, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13, }; use malachite_nz::natural::arithmetic::div_mod::{ limbs_div_limb_in_place_mod, limbs_div_limb_mod, limbs_div_limb_to_out_mod, limbs_div_mod, limbs_div_mod_barrett, limbs_div_mod_barrett_scratch_len, limbs_div_mod_by_two_limb_normalized, limbs_div_mod_divide_and_conquer, limbs_div_mod_extra, limbs_div_mod_extra_in_place, limbs_div_mod_schoolbook, limbs_div_mod_three_limb_by_two_limb, limbs_div_mod_to_out, limbs_invert_approx, limbs_invert_basecase_approx, limbs_invert_limb, limbs_invert_newton_approx, limbs_two_limb_inverse_helper, }; use malachite_nz::natural::{Natural, limb_to_bit_count}; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ large_type_gen_var_11, large_type_gen_var_12, large_type_gen_var_18, large_type_gen_var_19, natural_gen, natural_gen_var_2, natural_pair_gen_var_5, natural_pair_gen_var_6, unsigned_sextuple_gen_var_2, unsigned_vec_quadruple_gen_var_1, unsigned_vec_quadruple_gen_var_5, }; use malachite_nz::test_util::natural::arithmetic::div_mod::{ limbs_div_limb_in_place_mod_alt, limbs_div_limb_in_place_mod_naive, limbs_div_limb_to_out_mod_alt, limbs_div_limb_to_out_mod_naive, rug_ceiling_div_neg_mod, }; use num::{BigUint, Integer}; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_invert_limb() { let test = |x: Limb, inv: Limb| { assert_eq!(limbs_invert_limb::(x), inv); }; test(0x80000000, u32::MAX); test(0x80000001, 0xfffffffc); test(0x80000002, 0xfffffff8); test(0x89abcdef, 0xdc08767e); test(0xfffffffd, 3); test(u32::MAX - 1, 2); test(u32::MAX, 1); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_limb_mod_and_limbs_div_limb_in_place_mod() { let test = |ns: &[Limb], d: Limb, q: Vec, r: Limb| { let (q_alt, r_alt) = limbs_div_limb_mod(ns, d); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let old_ns = ns; let mut ns = old_ns.to_vec(); assert_eq!(limbs_div_limb_in_place_mod(&mut ns, d), r); assert_eq!(ns, q); let mut ns = old_ns.to_vec(); assert_eq!(limbs_div_limb_in_place_mod_alt(&mut ns, d), r); assert_eq!(ns, q); let mut ns = old_ns.to_vec(); assert_eq!(limbs_div_limb_in_place_mod_naive(&mut ns, d), r); assert_eq!(ns, q); }; test(&[0, 0], 2, vec![0, 0], 0); test(&[6, 7], 1, vec![6, 7], 0); test(&[6, 7], 2, vec![0x80000003, 3], 0); test(&[100, 101, 102], 10, vec![1288490198, 858993469, 10], 8); test(&[123, 456], 789, vec![2482262467, 0], 636); test(&[u32::MAX, u32::MAX], 2, vec![u32::MAX, 0x7fffffff], 1); test(&[u32::MAX, u32::MAX], 3, vec![0x55555555, 0x55555555], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_mod_fail_1() { limbs_div_limb_mod(&[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_mod_fail_2() { limbs_div_limb_mod(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_in_place_mod_fail_1() { limbs_div_limb_in_place_mod(&mut [10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_in_place_mod_fail_2() { limbs_div_limb_in_place_mod(&mut [10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_limb_to_out_mod() { let test = |out_before: &[Limb], ns: &[Limb], d: Limb, r: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_div_limb_to_out_mod(&mut out, ns, d), r); assert_eq!(out, out_after); let mut out = out_before.to_vec(); assert_eq!(limbs_div_limb_to_out_mod_alt(&mut out, ns, d), r); assert_eq!(out, out_after); let mut out = out_before.to_vec(); assert_eq!(limbs_div_limb_to_out_mod_naive(&mut out, ns, d), r); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[0, 0], 2, 0, &[0, 0, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 1, 0, &[6, 7, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, 0, &[0x80000003, 3, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, 8, &[1288490198, 858993469, 10, 10], ); test( &[10, 10, 10, 10], &[123, 456], 789, 636, &[2482262467, 0, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 2, 1, &[u32::MAX, 0x7fffffff, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 3, 0, &[0x55555555, 0x55555555, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_mod_fail_1() { limbs_div_limb_to_out_mod(&mut [10], &[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_mod_fail_2() { limbs_div_limb_to_out_mod(&mut [10, 10], &[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_limb_to_out_mod_fail_3() { limbs_div_limb_to_out_mod(&mut [10], &[10, 10], 10); } fn verify_limbs_div_mod_extra( original_out: &[Limb], fraction_len: usize, ns: &[Limb], d: Limb, out: &[Limb], r: Limb, ) { let out_len = ns.len() + fraction_len; let mut extended_ns = vec![0; out_len]; extended_ns[fraction_len..].copy_from_slice(ns); let n = Natural::from_owned_limbs_asc(extended_ns); let d = Natural::from(d); let (expected_q, expected_r) = (&n).div_mod(&d); let q = Natural::from_limbs_asc(&out[..out_len]); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert_eq!(&out[out_len..], &original_out[out_len..]); assert!(r < d); assert_eq!(q * d + Natural::from(r), n); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_mod_extra() { let test = |out_before: &[Limb], fraction_len: usize, ns: &[Limb], d: Limb, r: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); assert_eq!( limbs_div_mod_extra(&mut out, fraction_len, ns, d, d_inv, shift), r ); assert_eq!(out, out_after); verify_limbs_div_mod_extra(out_before, fraction_len, ns, d, &out, r); }; // - shift != 0 // - ns_last >= d // - !ns.is_empty() test(&[10, 10, 10, 10], 0, &[123], 7, 4, &[17, 10, 10, 10]); test( &[10, 10, 10, 10], 1, &[123], 7, 2, &[2454267026, 17, 10, 10], ); test( &[10, 10, 10, 10], 0, &[123, 456], 7, 1, &[613566774, 65, 10, 10], ); test( &[10, 10, 10, 10], 1, &[123, 456], 7, 4, &[613566756, 613566774, 65, 10], ); // - ns_last < d // - ns.is_empty() test(&[10; 3], 0, &[1], 2, 1, &[0, 10, 10]); test(&[10; 4], 0, &[0, 1], 2, 0, &[0x80000000, 0, 10, 10]); // - shift == 0 test( &[10; 10], 6, &[1494880112, 1342788885], 3459538423, 503849941, &[ 3112466029, 4165884652, 3488895153, 1476752580, 2095685273, 2437515973, 1667053127, 0, 10, 10, ], ); test( &[10; 3], 0, &[3702397177], 3086378613, 616018564, &[1, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_fail_1() { let d = 7; let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); limbs_div_mod_extra(&mut [10; 2], 1, &[123, 456], d, d_inv, shift); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_fail_2() { limbs_div_mod_extra(&mut [10; 4], 1, &[123, 456], 0, 0, 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_fail_3() { let d = 7; let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); limbs_div_mod_extra(&mut [10; 4], 1, &[], d, d_inv, shift); } fn verify_limbs_div_mod_extra_in_place( original_ns: &[Limb], fraction_len: usize, d: Limb, ns: &[Limb], r: Limb, ) { let mut extended_ns = vec![0; ns.len()]; extended_ns[fraction_len..].copy_from_slice(&original_ns[fraction_len..]); let n = Natural::from_owned_limbs_asc(extended_ns); let d = Natural::from(d); let (expected_q, expected_r) = (&n).div_mod(&d); let q = Natural::from_limbs_asc(ns); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert!(r < d); assert_eq!(q * d + Natural::from(r), n); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_mod_extra_in_place() { let test = |ns_before: &[Limb], fraction_len: usize, d: Limb, r: Limb, ns_after: &[Limb]| { let mut ns = ns_before.to_vec(); let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); assert_eq!( limbs_div_mod_extra_in_place(&mut ns, fraction_len, d, d_inv, shift), r ); assert_eq!(ns, ns_after); verify_limbs_div_mod_extra_in_place(ns_before, fraction_len, d, &ns, r); }; // - shift != 0 // - ns_last >= d // - !ns.is_empty() test(&[123], 0, 7, 4, &[17]); test(&[10, 123], 1, 7, 2, &[2454267026, 17]); test(&[123, 456], 0, 7, 1, &[613566774, 65]); test(&[10, 123, 456], 1, 7, 4, &[613566756, 613566774, 65]); // - ns_last < d // - ns.is_empty() test(&[1], 0, 2, 1, &[0]); test(&[0, 1], 0, 2, 0, &[0x80000000, 0]); // - shift == 0 test( &[10, 10, 10, 10, 10, 10, 1494880112, 1342788885], 6, 3459538423, 503849941, &[3112466029, 4165884652, 3488895153, 1476752580, 2095685273, 2437515973, 1667053127, 0], ); test(&[3702397177], 0, 3086378613, 616018564, &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_in_place_fail_1() { limbs_div_mod_extra_in_place(&mut [0, 123, 456], 1, 0, 0, 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_in_place_fail_2() { let d = 7; let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); limbs_div_mod_extra_in_place(&mut [], 0, d, d_inv, shift); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_div_mod_extra_in_place_fail_3() { let d = 7; let shift = LeadingZeros::leading_zeros(d); let d_inv = limbs_invert_limb::(d << shift); limbs_div_mod_extra_in_place(&mut [123, 456], 2, d, d_inv, shift); } fn verify_limbs_two_limb_inverse_helper(hi: Limb, lo: Limb, result: Limb) { let b = Natural::power_of_2(Limb::WIDTH); let b_cubed_minus_1 = Natural::low_mask(Limb::WIDTH * 3); let x = Natural::from(DoubleLimb::join_halves(hi, lo)); let expected_result = &b_cubed_minus_1 / &x - &b; assert_eq!(result, expected_result); assert!(b_cubed_minus_1 - (Natural::from(result) + b) * &x < x); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_two_limb_inverse_helper() { let test = |hi, lo, result| { assert_eq!(limbs_two_limb_inverse_helper(hi, lo), result); verify_limbs_two_limb_inverse_helper(hi, lo, result); }; // - hi_product >= lo // - hi_product >= lo_product_hi test(0x80000000, 0, u32::MAX); test(0x80000000, 123, u32::MAX); test(0x80000123, 1, 0xfffffb74); test(u32::MAX, 0, 1); // - hi_product < lo test(u32::MAX, 123, 0); test(0xfffff123, 1, 0xedd); test(u32::MAX, u32::MAX, 0); // - hi_product < lo_product_hi // - !(hi_product > hi || hi_product == hi && lo_product_lo >= lo) test(0x80000001, 3, 0xfffffffb); // - hi_product > hi || hi_product == hi && lo_product_lo >= lo test(2325651385, 3907343530, 3636893938); } #[test] #[should_panic] fn limbs_two_limb_inverse_helper_fail() { limbs_two_limb_inverse_helper(0, 10); } fn verify_limbs_div_mod_three_limb_by_two_limb( n_2: Limb, n_1: Limb, n_0: Limb, d_1: Limb, d_0: Limb, q: Limb, r: DoubleLimb, ) { let n = Natural::from_owned_limbs_asc(vec![n_0, n_1, n_2]); let d = Natural::from(DoubleLimb::join_halves(d_1, d_0)); let r = Natural::from(r); assert_eq!((&n).div_mod(&d), (Natural::from(q), r.clone())); assert!(r < d); assert_eq!(Natural::from(q) * d + r, n); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_mod_three_limb_by_two_limb() { let test = |n_2, n_1, n_0, d_1, d_0, q, r| { assert_eq!( limbs_div_mod_three_limb_by_two_limb( n_2, n_1, n_0, d_1, d_0, limbs_two_limb_inverse_helper(d_1, d_0) ), (q, r) ); verify_limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, q, r); }; // - r < d // - r.upper_half() >= q_0 test(1, 2, 3, 0x80000004, 5, 1, 0x7ffffffdfffffffe); test(2, 0x40000000, 4, 0x80000000, 0, 4, 0x4000000000000004); // - r >= d // - r.upper_half() < q_0 test( 1614123406, 3687984980, 2695202596, 2258238141, 1642523191, 3069918587, 274277675918877623, ); } fn verify_limbs_div_mod_by_two_limb_normalized( qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb], ns_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns_in); let d = Natural::from_limbs_asc(ds); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns_in.len() - 2; let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); let r = Natural::from_limbs_asc(&ns_out[..2]); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); assert_eq!(&ns_in[2..], &ns_out[2..]); assert!(r < d); assert_eq!(q * d + r, n); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_mod_by_two_limb_normalized() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds, q_highest, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); assert_eq!( limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, ds), q_highest ); assert_eq!(qs, qs_out); assert_eq!(ns, ns_out); verify_limbs_div_mod_by_two_limb_normalized(qs_in, ns_in, ds, q_highest, &qs, &ns); }; // - !highest_q test(&[10], &[1, 2], &[3, 0x80000000], false, &[10], &[1, 2]); test( &[10, 10, 10, 10], &[1, 2, 3, 4, 5], &[3, 0x80000000], false, &[4294967241, 7, 10, 10], &[166, 2147483626, 3, 4, 5], ); // - highest_q test( &[0, 0], &[4142767597, 2922703399, 3921445909], &[2952867570, 2530544119], true, &[2360708771, 0], &[3037232599, 1218898013, 3921445909], ); } #[test] #[should_panic] fn limbs_div_mod_by_two_limb_normalized_fail_1() { limbs_div_mod_by_two_limb_normalized(&mut [10], &mut [1, 2], &[3, 4]); } #[test] #[should_panic] fn limbs_div_mod_by_two_limb_normalized_fail_2() { limbs_div_mod_by_two_limb_normalized(&mut [10], &mut [1, 2], &[3, 0x80000000, 4]); } #[test] #[should_panic] fn limbs_div_mod_by_two_limb_normalized_fail_3() { limbs_div_mod_by_two_limb_normalized(&mut [10], &mut [1, 2, 3, 4], &[3, 0x80000000]); } fn verify_limbs_div_mod_1( qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb], ns_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns_in); let d = Natural::from_limbs_asc(ds); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns_in.len() - ds.len(); let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); let r = Natural::from_limbs_asc(&ns_out[..ds.len()]); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); assert!(r < d); assert_eq!(q * d + r, n); } #[test] fn test_limbs_div_mod_schoolbook() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); assert_eq!( limbs_div_mod_schoolbook(&mut qs, &mut ns, ds, inv), q_highest ); assert_eq!(qs, qs_out); assert_eq!(ns, ns_out); verify_limbs_div_mod_1(qs_in, ns_in, ds, q_highest, &qs, &ns); }; #[cfg(feature = "32_bit_limbs")] { // - !highest_q test( &[10], &[1, 2, 3], &[3, 4, 0x80000000], false, &[10], &[1, 2, 3], ); // - !(n_1 == d_1 && ns[i - 1] == d_0) // - !carry test( &[10, 10, 10, 10], &[1, 2, 3, 4, 5, 6], &[3, 4, 0x80000000], false, &[4294967207, 9, 12, 10], &[268, 328, 2147483575, 4294967251, 5, 6], ); // - carry test( &[10], &[0, 0, 0, 1], &[1, 0, 0x80000000], false, &[1], &[u32::MAX, u32::MAX, 0x7fffffff, 1], ); // - highest_q test( &[10; 10], &[ 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, ], &[ 1430162564, 1873089879, 3090281851, 2861182896, 2502166555, 2486624904, 960387080, 3073064701, ], true, &[10, 10, 10, 10, 10, 10, 10, 10, 10, 10], &[ 1030827391, 3064551024, 3176366775, 3772761918, 2268243711, 29902504, 2510544116, 1188988289, ], ); // - n_1 == d_1 && ns[i - 1] == d_0 test( &[10; 8], &[ 0, 0x4000000, 0xfffff000, 63, 4294443008, u32::MAX, u32::MAX, 8388575, 4294836224, 0x3fffffff, ], &[33554304, 4294443008, u32::MAX], false, &[0, 4294443008, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3fffffff, 10], &[ 0, 0, 0, 4294443072, 0xfff00000, u32::MAX, u32::MAX, u32::MAX, 4294836224, 0x3fffffff, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 17], &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 4451260977376821357, 18241701617364042056, 6169989192350218482, 15071965537117101028, 13509168527678537782, 12224278653171635329, 16077066393714953826, 1433938684868066489, 13014970036232570373, 899282336249563956, 3089487642230339536, 3787737519477527148, 16667686214395942740, 8787122953224574943, 7841835218775877827, 9693303502025838409, 16122224776459879427, 144327425397945219, ], &[ 2350654041004706911, 7834348511584604247, 12756796070221345724, 3842923787777653903, 12373799197090248752, 9712029403347085570, 1426676505264168302, 10586232903332693517, 8387833601131974459, 6290888746273553243, 9503969704425173615, ], false, &[ 89235393247566392, 5198286616477507104, 15671556528191444298, 6642842185819876016, 1703950202232719208, 6620591674460885314, 9897211438557358662, 12382449603707212210, 13586842887558233290, 11884313943008627054, 3205830138969300059, 4257812936318957065, 11084100237971796628, 13937343901544333624, 11743372027422931451, 280132530083052382, 10, ], &[ 12688955427180652274, 7641660693922643933, 8789985477567049482, 5698832637416200787, 14684840547760545685, 2822100467869581421, 3557573565928866957, 4409631974409684922, 16994214656621423610, 4513108841166793667, 9009005527785483287, 4330767427200269309, 11409205475757922767, 12430752173702915207, 11990819624778098799, 4145020291153594556, 7099200056207569977, 3510167930325480168, 4731667122118327121, 10720310942075546738, 5799804483118787221, 17268037247251138479, 13305947798457087249, 1405091439325174594, 13072181651983436371, 16122224776459879427, 144327425397945219, ], ); } } #[test] #[should_panic] fn limbs_div_mod_schoolbook_fail_1() { let ds = &[3, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_schoolbook(&mut [10], &mut [1, 2, 3], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_schoolbook_fail_2() { let ds = &[3, 4, 5, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_schoolbook(&mut [10], &mut [1, 2, 3], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_schoolbook_fail_3() { let ds = &[3, 4, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_schoolbook(&mut [10], &mut [1, 2, 3, 4, 5], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_schoolbook_fail_4() { let ds = &[3, 4, 5]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_schoolbook(&mut [10], &mut [1, 2, 3], ds, inv); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_div_mod_divide_and_conquer() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let ds_len = ds.len(); let inv = limbs_two_limb_inverse_helper(ds[ds_len - 1], ds[ds_len - 2]); assert_eq!( limbs_div_mod_divide_and_conquer(&mut qs, &mut ns, ds, inv), q_highest ); assert_eq!(qs, qs_out); assert_eq!(&ns[..ds_len], ns_out); verify_limbs_div_mod_1(qs_in, ns_in, ds, q_highest, &qs, &ns); }; // - q_len <= d_len // - q_len < DC_DIV_QR_THRESHOLD // - m != 0 test( &[10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], false, &[4294967057, 15, 18, 10], &[718, 910, 1080, 1286, 1492, 2147483434], ); // - carry != 0 second time test( &[0; 3], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], &[0, 0, 0, 0, 1, 0, 0, 0x80000000], false, &[1, 0, 0], &[0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, 0x7fffffff], ); // - highest_q third time test( &[ 1341443830, 680228019, 2358294753, 4240552485, 4220791420, 3445360969, 1267691556, 3340881424, 992535572, 1421700486, 4136881179, ], &[ 342694080, 2041952014, 1126110022, 386493367, 2712278177, 1646877232, 868323005, 1128141558, 2508964077, 2270408768, 413397861, 276293957, 2413870149, 3904853505, 1276303079, 2556190902, 3967785388, 2803311564, 1963309088, 2281251697, 108392083, 3821172642, 2048710986, 445614759, 2901896991, 3601903082, 1748962330, 658337341, 3756770944, 2926642090, 7482898, 2241569433, 3381544088, 3275875595, 3036252835, 2075586864, 1267727773, 221607050, 3946214050, 921175728, 655433083, 3594825352, 1857831165, 3460211778, 2710641188, 1271591399, 263125866, 3619333728, 1041602820, 3231202083, 259949419, 4156557841, 3419638674, 3270070813, 2084018311, 2951772182, 860428573, 1138531819, 71044931, 3406637788, 3662652535, 3741808197, 86584983, 1543795459, 160951322, 1039367499, 2428548772, 3604743617, 1138310711, 2881638514, 2899388867, 3501166651, 161644747, 2395978477, 2682256494, 3417971200, 624066885, 1772236754, 48275686, 3979745914, 2458268763, 2470110876, 3143857674, 3359279240, 46246098, 2912257532, 2916568936, ], &[ 4267671814, 3181376526, 4204274026, 2772982826, 171341955, 3239339748, 83269891, 2325049318, 746305994, 1290717192, 1805639230, 1856363646, 3445599715, 1388597950, 2699498310, 246990054, 1396771726, 265087723, 3372840761, 3260397695, 2010115470, 2211074582, 1883962263, 256363687, 4012920099, 2367091978, 1485341992, 1836339208, 1434180757, 2616877872, 1145425491, 1261399773, 3926766027, 3115015865, 1741783714, 3802513218, 4081750672, 3856503286, 2137512595, 1192985123, 1863041957, 700637154, 2503934926, 2021744810, 157763047, 453501781, 1898727251, 3741166728, 105996483, 3390681922, 1127471458, 4229032301, 254843851, 2729237155, 1707011850, 1756734415, 1864969309, 96539023, 220456923, 3061776324, 1741151628, 1199010536, 2099212259, 3095715999, 1369052975, 2575251120, 1821995904, 4169452262, 3299830336, 666854626, 3647011057, 3965571435, 1551218489, 726151433, 1730753749, 750433250, 2084548637, 475638490, 3209308986, 1536371286, 3458731894, 451976715, 1463077982, 2401462738, ], true, &[ 4074815036, 3472841870, 921256965, 4240552485, 4220791420, 3445360969, 1267691556, 3340881424, 992535572, 1421700486, 4136881179, ], &[ 50882392, 3543059939, 2606418187, 171797978, 3702339267, 3400795540, 1675838746, 3131956910, 3246773095, 2366066134, 1942572319, 200951604, 2751524401, 2229461380, 953596498, 2149080321, 992246008, 2665146762, 3598754770, 101403369, 2364937647, 3687287854, 3518388658, 3773344884, 2952272227, 2179289728, 3985568008, 2985468384, 1733586261, 4006520661, 592636589, 1738983882, 3771432433, 334405279, 30528997, 3353300809, 3694124666, 1257341879, 1142716002, 3178475445, 1431232435, 2733787829, 2350134046, 162973337, 604966704, 1355497537, 2006066960, 1053669332, 2166548589, 1297102232, 878976420, 1030095675, 3202690801, 955256572, 1487108550, 2945568597, 3875785235, 1390419282, 1216776596, 786261001, 3784540042, 1845909951, 1777517834, 12237310, 475982412, 3059699536, 4125207911, 2924612871, 3238196381, 2479221661, 1483884124, 433754513, 447002430, 2684532044, 3494064078, 619277683, 2680056541, 538552294, 1984267024, 700348592, 1278341418, 1614761367, 3944408375, 1269851701, ], ); // - hi < DC_DIV_QR_THRESHOLD in limbs_div_mod_divide_and_conquer_helper // - carry != 0 first time in limbs_div_mod_divide_and_conquer_helper // - lo < DC_DIV_QR_THRESHOLD in limbs_div_mod_divide_and_conquer_helper // - carry != 0 second time in limbs_div_mod_divide_and_conquer_helper // - q_len > d_len // - q_len_mod_d_len == 1 // - 2 < q_len_mod_d_len < DC_DIV_QR_THRESHOLD // - q_len_mod_d_len != d_len // - highest_q second time // - carry != 0 first time test( &[ 3656551823, 3383257247, 550091805, 1932339117, 3279901067, 2864941409, 3440756420, 466783416, 651341619, 2318022162, 1201487629, 3064175522, 2345469826, 3581748650, 2606599593, 3742095121, ], &[ 3689695988, 3117118992, 1237207334, 1180101208, 2947083336, 2827697081, 221923985, 2507264800, 619323315, 1516562901, 3186068769, 1013769776, 1271582351, 1669896397, 2497959088, 3504047880, 4212568439, 1608150067, 4150555892, 374787916, 889323122, 3833122938, 4262272989, ], &[ 3226059476, 722714803, 1915993039, 2160412527, 1484228011, 1715426198, 1611850737, 3097214810, ], true, &[ 3948774568, 277233294, 951139522, 4214130560, 3551225641, 3386184722, 1565143611, 2922369553, 2764255027, 5466750, 2823931470, 3552636955, 545484857, 803194457, 1615608566, 3742095121, ], &[ 1074470868, 2174113464, 1715956530, 3963027838, 1871758691, 1809783936, 3173233408, 1926929270, ], ); // - hi >= DC_DIV_QR_THRESHOLD in limbs_div_mod_divide_and_conquer_helper // - lo >= DC_DIV_QR_THRESHOLD in limbs_div_mod_divide_and_conquer_helper // - q_len_mod_d_len >= DC_DIV_QR_THRESHOLD test( &[ 2108009976, 2838126990, 827008974, 4157613011, 3782799311, 839921672, 879731301, 1926496935, 3712149888, 2363043408, 3863476261, 1703718215, 499165670, 2993223230, 4279694017, 2976095205, 2193242813, 3593708162, 586354096, 296757650, 242624274, 199363552, 2802933005, 2759687879, 3925865458, 4217980786, 621040829, 4008464542, 3795907109, 270168250, 3625538473, 759155103, 3959828159, 1835721901, 1818377089, 114690984, 2967220963, 2377698568, 2241245638, 2252300906, 3116551983, 3644576818, 2608501946, 2181270779, 1815210824, 1268283136, 484429506, 1180516809, 559610343, 2543044915, 3719740023, 558939794, 3989231279, 1089033996, 3509826828, 3545449066, 3353643945, 2822587915, 2300900020, 309191900, 2371088678, 1169317833, 2688462322, 704882387, 1429447898, 2514029776, 1955158460, 3862686818, 1584130288, 482000750, 4224830364, 2104097699, 1183456674, 2270729014, 2607655660, 2966545947, 2931252595, 759652385, 3970839358, 2487392344, 1507124762, 758697388, 3840603988, 1293583672, 252424514, 646352064, 1756992845, 2309291248, 3392597937, 2946557682, 3659552460, 1720311830, 3395887210, 2674135679, 3196424053, 2895118562, 1256983146, 2482795730, 1922474903, 2105232035, 3692384401, 2891711374, 3496171341, 515080177, 4073860792, 2051799135, 2279442367, 3258846627, 70977295, 1937954703, 2800340027, 1760719187, 646417623, 3158839049, 3176203007, 213391749, 869819866, 3906922929, 1586646665, 1614123406, 3687984980, 1177302158, 272342927, 1441818617, 2083855650, 1541781406, 3311904586, 106907162, 4108429222, 662974012, 4140594255, 1984524179, 3259771450, 3863443649, 3307256449, 3597197635, 3771753969, 3551628070, 3550518548, 2546464879, 3812123817, 2299164636, 2258249267, 815945886, 3725185601, 738801212, 3862546442, 207778311, 1535617953, 2150997157, 729581295, 143725958, 1410055499, 4204574368, 2185442793, 3653861199, 1767186378, 3537808267, 1766021033, 2239408696, 1986025224, 3625288948, 4046347844, 2490523057, 3491861717, 1312039469, 597857291, 206880668, 1812928615, 3684502664, 3820772609, 1327777451, 1237379465, 764273090, 3594853086, 2859643842, 1243019386, 3444655918, 1596721727, 2221238575, 2483346164, 2064518283, 2282844430, 1960424205, 4028198846, 2342293800, 1645322170, 3508868511, 2376856302, 1764497492, 2461899059, 3430260828, 1083983032, 1448541077, 2081767380, 1131293272, 2121152826, 4212689224, 2039367869, 2193844060, 1864700761, 1182989130, 1481869846, 969270162, 3997775597, 1483663077, 394034269, 1586435653, 2281434261, 1937512315, 836935557, 59742568, 1854699653, 2116629465, 328821302, 1999851100, 604863759, 556389113, 2057620108, 1992554416, 427465103, 813735424, 487055225, 402647361, 3006998394, 2146302389, 2308517156, 1063328348, 2382344201, 2665908320, 481118926, 2376219143, 1164055989, 128362737, 2711666601, 1898018298, 2928344090, 3862251511, 749517272, 2790599579, 3506539103, 2592038317, 1682088920, 1332639030, 3053921374, 3066891587, 242466377, 3536065834, 2016487096, 1321862427, 2409873623, 3088797737, 2840818323, 2052021858, 4079299898, 452968540, 3880575723, 2680668784, 1502544423, 1619882634, 1068420458, 3236073318, 1740351058, 1183565882, 2761799103, 246817911, 2967032269, 4003972840, 969974269, 3193561842, 1002645557, 2347161653, 4272895273, 1522072178, 972383725, 3026624523, 434293193, 2855690795, 2455822196, 2413168892, 2999634230, 784531194, 249556803, 2559695464, 3131798530, 668810109, 2114036394, 2861740558, 370716909, 2126014070, 3913884200, 1577476936, 855642956, 2074597201, 3461659621, 3292762038, 2153122643, 1658901071, 1562860969, 501980289, 1611843440, 2433026108, 3791871978, ], &[ 2325147333, 1406197332, 1502532645, 137754493, 1488912421, 1014222449, 1678300831, 2078887154, 2311629707, 3855402290, 1904906031, 1350026944, 314061674, 919972212, 1429252796, 544807358, 2607111216, 3001219316, 160533550, 2875169678, 1402474615, 3234840532, 1662112023, 1943050521, 4132256985, 2915369430, 699620367, 59590583, 2461837586, 3986106860, 2659659366, 3589796255, 4168995860, 2337625655, 4292546333, 1793085295, 2647770730, 2871508164, 2660729400, 3630964395, 3874212033, 1240042620, 1713051992, 2105061240, 968807145, 3026819276, 2442427316, 2718248469, 2572140009, 1793916894, 2112926236, 1058005225, 1528978151, 98430379, 3348888463, 2121431457, 3545708238, 3975070402, 764453596, 192861224, 2698588322, 1493819664, 2502294971, 3139295505, 1318649192, 1552623529, 2989328476, 1592829691, 1175278450, 182489613, 1858350437, 2440903999, 1622786339, 162763913, 4106583944, 609833788, 1344925844, 3910333895, 1369398307, 51929280, 2214052160, 78601532, 642016948, 3966440550, 4161875340, 3764174238, 2944905670, 832634369, 2082700552, 3444794582, 962611192, 38510846, 2733538376, 2141542785, 621670923, 3130866640, 1666281368, 3628581169, 3965100367, 2889091703, 762371524, 3752935086, 656901001, 2374421435, 3084212494, 1186140919, 3420046356, 775236355, 1337865306, 2051118555, 713071112, 1946850844, 1427068060, 3949026319, 3075128554, 438166063, 3975561046, 858907746, 26964870, 3843362808, 1461820702, 3090970200, 1037540471, 289966660, 2768763862, 50890120, 580189324, 2911422550, 3684738914, 2025034397, 414622319, 2287243961, 3268939669, 3547523099, 4011963324, 1768695320, 1859343614, 2123856143, 4141054481, 765801396, 359993985, 3668605792, 3613648266, 1778728280, 2547397231, 2456061149, 2562918666, 2903450513, 1994190773, 99234624, 3722083920, 4262323306, 202219441, 4201857695, 3988878636, 1533308334, 401400520, 1069756554, 2457773969, 2892388936, 3423117995, 1944069442, 492036629, 3426800580, 2282483359, 4006366620, 1695364515, 2555180845, 1669287836, 349290429, 778467450, 2020203604, 2218159817, 1450404019, 1278304750, 2412695340, 1592154884, 3868182043, 2240370481, 3859902860, 1008825116, 412233394, 2475457637, 3664379433, 4204584226, 2750684469, 4113507475, 2916584959, 285955744, 739598569, 18278051, 3768126932, 2181905109, 2612988076, 1827656088, 1160380415, 4160443718, 1846086671, 3050604645, 2547108010, 2828666778, 3252702258, 3885923576, 2331974758, 730724707, 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, 3428792463, 2896462048, 2985885576, 1819460734, 21206096, 3560441846, 987100555, 2844904275, 84854892, 1268249628, 3963306788, 3338670067, 2504599089, 65588657, 321493327, 4249673617, 4150876068, 721566898, 2186945060, 922948272, 1502464627, 1426914435, 2906888275, 3454987739, 2609132626, 2073366782, 1058809001, 1226951003, 2624503637, 282722778, 1407178266, 3304346308, 3613017687, 2397594777, 161128076, 1938083248, 3042822216, 3958145306, 1431161184, 4147630074, 1744618540, 3729847703, 2366216428, 2101731625, 2812677939, 3587016062, 1626785569, 3117017254, 3720581461, 4254564252, 2400911475, 750362271, 3062375802, 2182368701, 268751862, 2682134876, 274793576, 2417658182, 2321240923, 4200603818, 1349142841, 4066976957, 1043247680, 679021323, 2933095037, 1621487581, 225868669, 1030678959, 1236344244, 972640788, 1784301152, 578117349, 3509551550, 214420003, 3786992737, 802372148, 3562194086, 2187046946, 3600373521, 4275090943, 2120016813, 4177241875, 3185774231, 2397692077, 1015362399, 2178889151, 3433916223, 1688082118, 1971242178, 236388706, 3802829765, 521309115, 2299816689, 3207614143, 1053195464, 3584561145, 1178690670, 2940812254, 3321982035, 2754825123, 3073598062, 202404806, 547895545, 1188944547, 1056841779, 529463805, 204665384, 850370055, 2063320161, 3724100092, 1180272690, 1398467003, 2814052449, 1311768018, 659771105, 3226477227, 4230080238, 2134344405, 1461172705, 2728018383, 1816821358, 3231137250, 2012377728, 2206916761, 3121807673, 3037967028, 3653505029, 4164239058, 1337501466, 2487452346, 428839025, 3321493092, 2920064796, 2750126813, 3635762100, 2659829309, 1992243088, 2359420187, 861816585, 4182313312, 1389528266, 2890138969, 2195001695, 576635805, 1974585967, 851480113, 1896534852, 3143828462, 4276040597, 3921135859, 2394233682, 2692972118, 2103941456, 3931376544, 3790764632, 2278428793, 3381340311, 3516241824, 2923157557, 1276268033, 3471729699, 2370137091, 2637023305, 4027814477, 3711009696, 3667995314, 459819000, 1002878772, 2658190707, 1189561796, 1831813150, 2874008201, ], &[ 1703326352, 1625259628, 3642322228, 911402341, 2158835226, 939248485, 3607511108, 2863853568, 1611642161, 1312857772, 1839433327, 567060478, 3139863681, 3642698184, 3744632443, 712538472, 2692932947, 576185818, 156934113, 518107105, 2803035863, 2284220097, 3447382922, 2400125006, 3565062840, 160044186, 3644393084, 4196433258, 3391883838, 1115703759, 2380388002, 962895870, 4001772616, 2311278419, 2620271020, 3047789793, 3229254302, 3182628087, 2718480927, 2872538422, 1963990826, 2856537226, 1729736384, 372544200, 1482170753, 3370665422, 305555060, 4060802437, 1456459795, 2848113958, 1036273297, 3245835346, 3355862097, 3242734427, 3313897419, 4230036415, 1425594704, 2428756491, 420147714, 3218149930, 1791217142, 2881741659, 3231612869, 845372829, 1635665046, 1525482197, 3779462557, 2279005731, 626908159, 2963734610, 215448882, 2517668355, 3294128769, 1167990371, 2344651228, 2882002195, 3350056381, 3749638142, 476010196, 2304276366, 1088082897, 1927672185, 3316329053, 1174989749, 1101596429, 3054511229, 1685228241, 2301284206, 2526016461, 684171580, 3869889559, 2606492401, 2114658735, 1419214215, 2779052449, 2594333668, 2225446358, 1211258458, 4029343999, 2816277230, 4098142949, 1987363952, 2732004911, 2516355975, 2365350298, 1747416524, 3951513077, 3526462790, ], false, &[ 1303670916, 3965736473, 654490008, 3337248200, 112312312, 2506678400, 713192736, 901474194, 2359721047, 1133557120, 3068598661, 3136858413, 4095957211, 3057328754, 1900588230, 1315930687, 3273808327, 2821746043, 4255148500, 3072995291, 1472014781, 922081554, 1759317078, 149072645, 2712091402, 2134310281, 708105323, 3703209145, 2071594694, 8111834, 3766831226, 2182956891, 2525476614, 1478202223, 4199311113, 3813148212, 316780911, 1396844257, 2321402831, 1151134318, 848673799, 735789140, 1092813310, 738412079, 1895091662, 2947844274, 31103395, 2559694049, 1194304023, 3260126654, 1118043028, 1552558623, 3016599055, 1053142289, 446041643, 2615854004, 2105823819, 3769707039, 2784177611, 9564629, 580911617, 1979035813, 1479556681, 2599744262, 3097426153, 4195176293, 3497554127, 3484306250, 2114827319, 2314051712, 1210812068, 4158781103, 478301760, 2027533091, 1682020897, 129914624, 2066167843, 3989890251, 1378700448, 170057876, 3992582209, 1541347967, 3421610776, 697014638, 2834243941, 3504973679, 630519426, 1551901326, 3092678418, 1136389639, 1806538485, 2208151411, 1598302001, 4041410193, 3574334276, 2340664244, 1624426425, 1200740723, 2912910258, 671197404, 2272603994, 909857936, 792804858, 3083891114, 3143045405, 2389563439, 115312858, 1445242760, 2065820105, 256586994, 1432132569, 1549619424, 2631865338, 1674212272, 2599765330, 3713129178, 1590556325, 3610491293, 709987753, 3230113618, 1606099993, 3453954266, 3501213811, 3278809492, 3770342657, 1534951916, 1366321311, 3149479124, 3987513652, 2108936446, 1162972378, 279205823, 3711325879, 2278557694, 2305274058, 3709507652, 3805940202, 3778288085, 1061153771, 491180471, 479623642, 2960728114, 553156023, 1863065855, 2253455830, 14222934, 2488687289, 3378176628, 1136227234, 3805644784, 3175842224, 463501844, 2100687360, 2025076951, 4064921772, 1000043802, 2482142143, 1463585061, 1044328896, 3966669663, 1023595412, 2689537057, 685044345, 2599439954, 3302022962, 2669841238, 3358991646, 351579450, 2303934592, 2098132645, 2239011851, 1623838039, 790570033, 2288992150, 2252675624, 2479618080, 3624986625, 2129338944, 3796999988, 465518072, 620957443, 1836556967, 2894771224, 2904933718, 287211723, 1386209013, 2288387719, 162551270, 370319691, 2924564913, 2947669880, 3390862854, 1797811, 3097227838, 2245950593, 1664498395, 3380635348, 3536484871, 1217287925, 3149066538, 154911037, 1960867817, 4238493382, 1991791660, 509572665, 3386968719, 3880405816, 2335816696, 2519967410, 3482574698, 1501302597, 2415671279, 715902305, 1920401004, 3735445496, 1792155851, 2110622431, 3695395614, 3311496726, 4035668560, 187609524, 3743601469, 2990357125, 3084998227, 767424914, 1388627321, 1381810466, 3799640235, 1423360242, 3375037167, 979951340, 3463933333, 387599460, 229837304, 1394766077, 1068156038, 1135935924, 86516134, 142150630, 448211640, 3205606056, 1420159909, 4203558153, 2816235778, 4188064475, 1490981561, 2934083684, 2693435736, 1351552613, 962789901, 1071201732, 3244341475, 1855681940, 4210620238, 2129345127, 2909949483, 3992748944, 3928807766, 2014533910, 3099391001, 3112195816, 4009296318, 1247610431, 1474512546, 2530880557, 3597268331, 764359883, 4198267775, 1228639730, 736768887, 396797847, 799410613, 582496441, 2658423343, 1643853660, 1258585041, 3767032705, 3709454541, 892807168, 1443895160, 3500326521, 784531194, 249556803, 2559695464, 3131798530, 668810109, 2114036394, 2861740558, 370716909, 2126014070, 3913884200, 1577476936, 855642956, 2074597201, 3461659621, 3292762038, 2153122643, 1658901071, 1562860969, 501980289, 1611843440, 2433026108, 3791871978, ], &[ 1707334789, 979340170, 3926273349, 2029694660, 686358037, 1260123629, 689471236, 4127009836, 1697317324, 3024229658, 3968952300, 2265029759, 733830093, 2234057965, 799627406, 1641742523, 2511563041, 678204198, 60484965, 1732955108, 1348641815, 1389334445, 3762643904, 3914179461, 4076462931, 3234877741, 2806715190, 3058911852, 3068848122, 80861952, 660210165, 2035863667, 3882844515, 2652987274, 207029959, 4170201248, 1224653886, 3554890284, 323203565, 969583090, 2280910221, 2548241625, 2048045350, 3691775573, 3750377304, 2623340073, 1726676400, 2551234664, 3420452119, 1785849707, 3581615935, 3521097022, 4008380099, 4200557552, 3795120169, 488463511, 3784467967, 2462685342, 1684084055, 1072125823, 765304928, 2900468163, 3209242917, 399160769, 3897765190, 3241572534, 1027203705, 4127226109, 154941175, 1755153596, 4225252328, 1209101989, 2906888698, 1481930532, 2884731435, 2416462752, 553651049, 2247421040, 3347507436, 1936621186, 3156059073, 4059864280, 3191940359, 3872902453, 783002816, 3711047515, 1471051688, 357992570, 1061754510, 3765779801, 4106840335, 3213049794, 1824410844, 2555550067, 1066295382, 3248869963, 4006861446, 3297772017, 3418388327, 2284151457, 766215224, 1091253635, 2070830666, 1435103841, 1408352671, 338399542, 2946293497, 412804347, ], ); // - q_len >= DC_DIV_QR_THRESHOLD test( &[ 3333140561, 2349469031, 666934289, 3646788197, 3373340607, 3062489357, 1781577064, 3971231072, 2027939726, 18149756, 461121573, 1026270057, 4154481498, 3854995191, 2829169318, 2604923553, 1399568275, 4214150257, 1269657447, 527209086, 559827800, 1978807620, 1942748659, 3544969161, 760896836, 694370989, 3323597771, 1950755821, 1740588707, 2716546795, 1636681281, 131422512, 2683077565, 4107286368, 3475458482, 1406752921, 2741526831, 625075474, 1356017187, 660778033, 4078598031, 2127023485, 1900179860, 2413773277, 2442990944, 850894581, 1061627184, 2255197913, 490496693, 400007380, 3092474488, 1228905086, 1949288324, 1866222251, 4084867584, 219026194, 1513678816, 2415719293, 671740632, 2331463444, 1649508273, 622524186, 36198287, 385821590, 3891184984, 3888867762, 823766845, 871168771, 4220135146, 3182319759, 3811051122, 2244319794, 1994956782, 3515960993, 3523512148, 4142104035, 11404747, 3407068856, 2661473296, 1343912700, 1278923149, 1319603671, 3928437020, 2678906106, 1133029551, 3498992572, 3960506675, 2156562886, 2180928089, 4027866586, 3363079195, 2699625088, 10633112, 1776348429, 2657266039, 366882369, 3755249663, 1513004482, 385462618, 1235118123, 2498536948, 2963795538, 373052379, 4211662453, 1125414031, 3132282357, 2555861787, 3949045845, 2694335672, 335933961, 2882374566, 3487775198, 1816750435, 3017829161, 964613564, 159555703, 1822850997, 2275865751, 4158541302, 2501990511, 3721844651, 2781838144, 1795741626, 377630941, 2137086277, 150771080, 3410699853, 2181744662, 3165518125, 156617039, 3099687100, 2159351188, 340108091, 2408725718, 1639869303, 1752843886, 1941447467, 2157946488, 1515895552, 3624132653, 3556726921, 2697391196, 3650363912, 2596921683, 3641623430, 3884964637, 4229700714, 1936259996, 3765315225, 4087511128, 746291101, 1752759843, 699518598, 2102672534, 2335948897, 4138231225, 3162828440, 2881768368, 1254885146, 2977691172, 2250072411, 2614007259, 2771551612, 776074685, 3162839614, 1471012556, 523323297, 1856466918, 4090405884, 813410161, 100155385, 1084252628, 1599609446, 139407955, 4121369443, 1963225032, 2735275753, 100107317, 1064061529, 50786861, 1654370440, 3334472166, 1385803654, 3881645932, 3538258401, 1238925138, 1307191791, 2439918414, 1853442725, 3584719283, 2139830944, 1008033673, 2159214266, 1728151904, 2054140804, 2246372905, 1296034828, 732486414, 4197166746, 2149038695, 2421556216, 2209917678, 2053724924, 3695308867, 2810551805, 3486105675, 979515789, 2065617241, 3321246575, 4275036932, 3028497318, 1883398852, 1301060583, 2486427309, 592113155, 2482121819, 53211642, 3067158128, 2316354328, 2457370797, 1766767168, 4130364650, 1394191393, 893956183, 3188688185, 1875859783, 3686866863, 3294062742, 2146834313, 2406586432, 1574602180, 3208002016, 1067708846, 1620126309, 593911816, 1573785767, 2208656217, 4037191927, 3437397556, 425721135, 3749387007, 407468749, 4203518167, 557223936, 3186718435, 3473504989, 2673679280, 1478635903, 4172750097, 1469776418, 2542136327, 941914936, 3438581078, 3116581940, 3479694655, 159558945, 3809792710, 2458053073, 945749848, 3386290936, 950397544, 148027778, 275178526, 1664599931, 2000347485, 3312866545, 4123761723, 2408292910, 4050298, 4225958969, 2745635153, 1877283873, 90573827, 3031684040, 2275034810, 476532317, 4006527249, 2818283214, 661127690, 2880950746, 3285389422, 965419004, 1273458580, 1611437669, 4165036259, 503131762, 337440890, 1274837150, 3486913543, 1110808141, 3573281492, 3543428578, 4165550725, 79661970, 1465954224, 4160343768, 3753977684, 849800837, 1568284940, 1214508489, 777072754, 3766232553, 4163385462, 3428999259, 906027128, 4231567110, 1070253805, 2975789822, 1794042990, 2937404746, 3315145973, 3978541255, 191961431, 2940436214, 614874984, 868388988, 4078685796, 2613877234, 3380127687, 2664922311, 3262235038, 741871774, 1144269180, 4258950699, 3668553647, 3162392321, 927199539, 557637561, 1114912670, 84346866, 4241634616, 592125931, 1914166161, 1225886409, 722682712, 2163011354, 2585075265, 2786722853, 1993844439, 3433052694, 3718814733, 3881165856, 1749980152, 2115861966, 3664836486, 1644814678, 603487648, 821270634, 3041437740, 925329308, 414275079, 3675481275, 583965775, 3319812843, 270816609, 1752806861, 3191564196, 3197116565, 2440000620, 4074382088, 3346183865, 176525856, 3011091744, 746158938, 1522027948, 930706422, 2574400675, 4141639266, 758742087, 1418306156, 493509688, 4102390641, 3757183059, 2174506350, 3715933078, 3450125642, 1345548124, 3845070193, 1563795423, 1304049315, 2604880108, 1998271877, 4078353958, 966179722, 3401781407, 1708183977, 3890171386, 698646214, 604975097, 4189977050, 1847675543, 2745048720, 1585177380, 3886892753, 2534712423, 1830125662, 796996186, 3789574770, 2219095884, 38427113, 3653683439, 1791769536, 3941686320, 2991883118, 1081207663, 3863639548, 3017351034, 741393256, 2333573607, 2783158305, 2015776314, 3034707152, 1871224010, 1795881414, 928539629, 3211747317, 461147496, 1512738445, 1178891684, 2603472964, 1694950214, 3121022285, 91788635, 2303571910, 3259041724, 1240577113, 827064078, 3847765430, 1254285617, 2609289648, 82835530, 2235563901, 2939680484, 3327268666, 3659752183, 1783109461, 2828509671, 3804296197, 406800911, 2037292519, 941994402, 3350211940, 4004870359, 1105941782, 2367553097, 2440982990, 1468367, 2369391483, 3613174135, 2337161925, 2600055725, 1612773644, 1037201309, 919122459, 1114016493, 670586694, 594109706, 113464329, 4093636009, 307208587, 3876235186, 3370598978, 934478190, 2843794891, ], &[ 2368917411, 3160758175, 1531480588, 2746326450, 3122359045, 1995296172, 310451197, 1100329853, 2141732304, 3562890277, 4172526924, 4143185198, 2397101926, 620168044, 828452963, 3271569899, 2726758945, 1647557222, 2748652901, 1029871186, 1773072595, 1311795717, 2792240418, 3100733307, 298902661, 2608361440, 642743765, 3026335712, 1586592828, 1251923561, 2152803283, 3359308047, 3979690761, 2548031009, 2148504694, 2514911217, 401310800, 1418125404, 2325652800, 716233458, 422262103, 376190943, 1713380879, 2534508846, 2080413009, 2690193951, 2909422387, 2435837201, 176977642, 224472737, 1590904934, 1664979624, 1748982641, 1284257790, 2779881254, 385265989, 1148527382, 800142050, 3595556318, 3950265146, 3931111523, 3399894595, 4200004994, 3727110364, 1510525540, 429323681, 2586345405, 3441619670, 94654169, 2266545045, 1451808026, 286040435, 364003484, 2106693078, 1916214330, 2622096560, 3504008387, 1867458297, 4209615436, 2899684845, 3149003214, 2731979274, 2481557740, 234269740, 1239420776, 2726912636, 1844267393, 1488044058, 1587005400, 145015793, 1637696129, 1990069464, 3053970062, 676336554, 625771493, 1492378707, 1231018082, 3059699722, 4113615249, 2967103567, 3335726303, 2137774253, 273460502, 1561489611, 1227429414, 778315897, 3061631993, 2437789514, 2566029814, 3017507824, 3219754602, 35255136, 1934306764, 1655248959, 3655963814, 2821596564, 1431977748, 3114012833, 3915822059, 343010167, 3704265251, 2691314567, 2602475242, 2459094882, 58857240, 2230690665, 1357656795, 3025543277, 3488674640, 408985076, 80729036, 246851391, 1419653386, 530010128, 3529087076, 3980421141, 4129023783, 1630771696, 2057278583, 2501545742, 790764428, 3984347668, 2562445985, 2262348292, 2515967925, 1103371818, 3735595401, 3210477145, 3387257181, 538884374, 2695206119, 4211749041, 1006274735, 2406061865, 2654644297, 1268724640, 2399689302, 157759259, 564853502, 865205768, 2174783618, 3167863384, 1770172407, 1906775255, 3171669377, 2455086709, 1355327864, 3351895167, 4184858376, 2699533565, 2939169294, 1702277740, 3447680482, 3322351998, 4248517760, 4100425921, 1169799041, 524849931, 1743345401, 3987645088, 3022177240, 3263737545, 3656340460, 239445170, 4089162190, 1208712978, 1453215235, 3390225374, 3337889603, 717395279, 1066458381, 2162685522, 4009460245, 2575879990, 2578471337, 4218103221, 3046325563, 1352991515, 1561949281, 3488911174, 295633326, 1993756395, 3677304657, 796898320, 45622345, 2999482773, 2078651788, 1552765091, 428170722, 1748054862, 4158222865, 1050292437, 249107, 2651086861, 1540178674, 1275557298, 651050585, 1895599156, 4150309716, 2064336046, 1021257319, 2422595446, 3116755258, 2756656575, 2328011578, 3632905157, 2576200202, 830418644, 2430246370, 3913080080, 2371749061, 2683067461, 3611558701, 1603392737, 796477803, 604567756, 1376069347, 1491246154, 2728262664, 4138498935, 3008562381, 1061547384, 285679033, 2358943172, 1884649492, 1783482693, 1010268161, 176114433, 794165875, 2362278477, 3903204233, 326754905, 1988607850, 3187254334, 1749797209, 2986661384, 1759716588, 3137467938, 4067743599, 1134210801, 3799848836, 1955405545, 3881788427, 3097574490, 3844756657, 3183850151, 2496328910, 1468671385, 2888878911, 2306353811, 1498824361, 4152891378, 1588217107, 79108222, 2883552792, 2390312777, 1587172303, 2070384343, 2265280181, 4013380367, 2742676878, 2654283484, 1471778694, 970959698, 1006151052, 1276307400, 2874101774, 3169092608, 244587925, 2402787407, 1635687252, 835856534, 321407542, 2307278464, 2272745321, 2574317642, 729437319, 1682288870, 1482920833, 776000268, 3908963888, 214874919, 4233311318, 1441385448, 2358127573, 2753681514, 467574656, 4139948165, 1538275035, 3244920878, 2576965792, 584068468, 3054546876, 2629688518, 4253271747, 3723872815, 1652066683, 990821089, 2335421805, 1989570928, 240486517, 2872315587, 3869991906, 3870517664, 1540804424, 397183643, 3750033565, 1433260634, 1506168711, 3616651625, 512028445, 3746712828, 3278592880, 2611514549, 1214563129, 1259227909, 1067976218, 3425169051, 741795595, 893688343, 2674408703, 3694908868, 2478153735, 2220661625, 1022546736, 3719214155, 3161293211, 4131981986, 1473264088, 1651777063, 1438502715, 290022167, 59234682, 3458968160, 2552001459, 3451530289, 3800073253, 717882913, 845719525, 1038699111, 3058303772, 1117505279, 3682430977, 2869037104, 2562493618, 960519305, 4147639705, 1817463351, 3166022129, 3200769866, 789666262, 2654485924, 3686362402, 2179867687, 3980226915, 3671542918, 1896992204, 1514962591, 815867715, 3924270086, 4262628477, 3977258034, ], &[ 491933121, 4095154087, 1190388341, 2123387578, 3299683037, 3840239224, 3891252433, 3823858915, 548023871, 3189021809, 130119335, 1406023029, 1691542279, 2101470388, 367145009, 521045073, 1370995123, 202251222, 2377400220, 3656022509, 2413445446, 3583191945, 150872893, 1253881977, 3664619565, 661519973, 672952411, 1111416155, 2582282747, 2253466637, 3993637585, 1023965093, 4055175549, 1721196160, 4271105372, 1844335262, 794907961, 3970777280, 1279126024, 3389187110, 6388771, 3557792034, 2503975364, 1216157736, 4081863507, 1212796362, 22717034, 3517296783, 3126258972, 454147562, 4182968994, 685295412, 2996150679, 840677609, 2775806132, 2555856748, 2855553012, 2971949846, 3057579317, 954558068, 1251032539, 2673204563, 697957636, 1312479140, 2686740988, 2005131101, 664387193, 2169938189, 4081160067, 3469684725, 123152292, 2899902365, 1142266692, 2066860665, 647803613, 3574778631, 1302596512, 678200322, 3509569151, 849744577, 1521760114, 3195673981, 111241164, 623461570, 3571445453, 200189218, 4138515602, 665845464, 4184871542, 1353865395, 2913489035, 3076207781, 2549062531, 3446687793, 685940105, 1430268106, 2488363196, 1172253595, 4151501269, 3292280286, 2025935004, 3388911026, 1080796771, 3386986959, 4175562557, 2440556214, 9871988, 5488492, 4179517076, 908443542, 364965294, 2303037125, 369102673, 1570100894, 3615415741, 3133015360, 2623933135, 211314818, 3377760249, 2285528104, 3096807957, 3213907502, 3633343924, 2065769028, 300167487, 1745300631, 1943126607, 1065862406, 2422304458, 523765517, 57630113, 520436682, 581485167, 527613705, 1677813796, 2698743484, 2448718551, 1681977324, 4183961145, 333724319, 2667028740, 3403027352, 1499647517, 2965583197, 1090547876, 1536215624, 3407325498, 1392474450, 3354142052, 3326326224, 1138672330, 1577104875, 235932133, 3877789753, 1822119722, 305251772, 3802044423, 608489509, 2727503310, 865373313, 3763994776, 3206318655, 88097048, 4241064408, 1171067683, 4250936686, 729121178, 763857558, 450636528, 2096197907, 1427186250, 1251064262, 3036762405, 2966424923, 880639864, 1995310474, 2023015792, 4198637421, 3996151657, 3070092174, 331733799, 2680348059, 2601390369, 92920881, 600583651, 1323663334, 4258529164, 2493258032, 3313489774, 2050494797, 1494880112, 1342788885, 2493538385, 1096813856, 27701253, 2762164402, 3934044073, 2289089808, 721323988, 2246162231, 2514451824, 3095057964, 1921436785, 2847276160, 1369952734, 4246781184, 3442030977, 3930627222, 614706399, 3051396564, 3044240928, 3450585985, 2120836933, 3006035710, 178202067, 736149219, 623937260, 1958379885, 3104814268, 3269365015, 914726129, 2951180538, 3940965189, 1869582492, 2599100173, 1009213592, 1410445689, 1179880005, 3583285938, 1921636631, 434725812, 735782942, 2548761027, 3733379485, 3466163816, 2455801926, 1673952134, 2422059957, 4005305357, 2795894062, 3245947918, 4171997564, 2269244989, 1975479474, 2449387935, 2550893401, 4033149, 3723976428, 3871853952, 3210178057, 2062131312, 1434821634, 1130065536, 4276609753, 41976415, 968125282, 853099726, 3675357389, 3545982836, 1237895428, 88970686, 4259275077, ], false, &[ 2046945960, 1873732058, 883136475, 2335087597, 1091742925, 3913267466, 1586245016, 4163559950, 1402352044, 2528046476, 1941819469, 2309605638, 3377063311, 3151818591, 494038776, 3426549387, 3253079763, 124752778, 4008075289, 327167526, 1965527166, 717131100, 1676230023, 3836503956, 3686584911, 550652113, 589790309, 2877365586, 2824639624, 3138038419, 3640799592, 585603054, 1414821912, 3869326513, 3124646127, 813686461, 180141293, 2274287537, 3375883484, 3539423998, 2876480809, 1880629606, 2803556469, 687655801, 393062928, 524210967, 2366097978, 2175763640, 3159336997, 790281459, 3247341866, 170318031, 1506555227, 246985421, 2165448534, 4166633223, 3351234404, 3976060563, 3925058943, 398933467, 3413453047, 3215824401, 2764818555, 2281679666, 2124899687, 3988046369, 3496024103, 1898489528, 3748055383, 1888289090, 3518616015, 2878886670, 1858863206, 1865431124, 2320246513, 1797214962, 3620561150, 3636061735, 1288494915, 1503932934, 333549760, 2000535203, 2963961099, 151292676, 4071971672, 2869808036, 801933070, 1423471894, 477371428, 3645363638, 2586777443, 3381283382, 3165264014, 1496932333, 2011004150, 558029532, 1103521912, 3099006002, 2922027532, 2250375874, 869652089, 386060205, 514086971, 679438817, 2922028193, 3519808732, 1083788073, 2102488620, 2723526073, 3287730376, 3961054192, 1086172650, 3775096139, 3273358074, 3471776285, 4280446341, 1945339479, 3318103287, 2895065752, 4010586984, 3721844651, 2781838144, 1795741626, 377630941, 2137086277, 150771080, 3410699853, 2181744662, 3165518125, 156617039, 3099687100, 2159351188, 340108091, 2408725718, 1639869303, 1752843886, 1941447467, 2157946488, 1515895552, 3624132653, 3556726921, 2697391196, 3650363912, 2596921683, 3641623430, 3884964637, 4229700714, 1936259996, 3765315225, 4087511128, 746291101, 1752759843, 699518598, 2102672534, 2335948897, 4138231225, 3162828440, 2881768368, 1254885146, 2977691172, 2250072411, 2614007259, 2771551612, 776074685, 3162839614, 1471012556, 523323297, 1856466918, 4090405884, 813410161, 100155385, 1084252628, 1599609446, 139407955, 4121369443, 1963225032, 2735275753, 100107317, 1064061529, 50786861, 1654370440, 3334472166, 1385803654, 3881645932, 3538258401, 1238925138, 1307191791, 2439918414, 1853442725, 3584719283, 2139830944, 1008033673, 2159214266, 1728151904, 2054140804, 2246372905, 1296034828, 732486414, 4197166746, 2149038695, 2421556216, 2209917678, 2053724924, 3695308867, 2810551805, 3486105675, 979515789, 2065617241, 3321246575, 4275036932, 3028497318, 1883398852, 1301060583, 2486427309, 592113155, 2482121819, 53211642, 3067158128, 2316354328, 2457370797, 1766767168, 4130364650, 1394191393, 893956183, 3188688185, 1875859783, 3686866863, 3294062742, 2146834313, 2406586432, 1574602180, 3208002016, 1067708846, 1620126309, 593911816, 1573785767, 2208656217, 4037191927, 3437397556, 425721135, 3749387007, 407468749, 4203518167, 557223936, 3186718435, 3473504989, 2673679280, 1478635903, 4172750097, 1469776418, 2542136327, 941914936, 3438581078, 3116581940, 3479694655, 159558945, 3809792710, 2458053073, 945749848, 3386290936, 950397544, 148027778, 275178526, 1664599931, 2000347485, 3312866545, 4123761723, 2408292910, 4050298, 4225958969, 2745635153, 1877283873, 90573827, 3031684040, 2275034810, 476532317, 4006527249, 2818283214, 661127690, 2880950746, 3285389422, 965419004, 1273458580, 1611437669, 4165036259, 503131762, 337440890, 1274837150, 3486913543, 1110808141, 3573281492, 3543428578, 4165550725, 79661970, 1465954224, 4160343768, 3753977684, 849800837, 1568284940, 1214508489, 777072754, 3766232553, 4163385462, 3428999259, 906027128, 4231567110, 1070253805, 2975789822, 1794042990, 2937404746, 3315145973, 3978541255, 191961431, 2940436214, 614874984, 868388988, 4078685796, 2613877234, 3380127687, 2664922311, 3262235038, 741871774, 1144269180, 4258950699, 3668553647, 3162392321, 927199539, 557637561, 1114912670, 84346866, 4241634616, 592125931, 1914166161, 1225886409, 722682712, 2163011354, 2585075265, 2786722853, 1993844439, 3433052694, 3718814733, 3881165856, 1749980152, 2115861966, 3664836486, 1644814678, 603487648, 821270634, 3041437740, 925329308, 414275079, 3675481275, 583965775, 3319812843, 270816609, 1752806861, 3191564196, 3197116565, 2440000620, 4074382088, 3346183865, 176525856, 3011091744, 746158938, 1522027948, 930706422, 2574400675, 4141639266, 758742087, 1418306156, 493509688, 4102390641, 3757183059, 2174506350, 3715933078, 3450125642, 1345548124, 3845070193, 1563795423, 1304049315, 2604880108, 1998271877, 4078353958, 966179722, 3401781407, 1708183977, 3890171386, 698646214, 604975097, 4189977050, 1847675543, 2745048720, 1585177380, 3886892753, 2534712423, 1830125662, 796996186, 3789574770, 2219095884, 38427113, 3653683439, 1791769536, 3941686320, 2991883118, 1081207663, 3863639548, 3017351034, 741393256, 2333573607, 2783158305, 2015776314, 3034707152, 1871224010, 1795881414, 928539629, 3211747317, 461147496, 1512738445, 1178891684, 2603472964, 1694950214, 3121022285, 91788635, 2303571910, 3259041724, 1240577113, 827064078, 3847765430, 1254285617, 2609289648, 82835530, 2235563901, 2939680484, 3327268666, 3659752183, 1783109461, 2828509671, 3804296197, 406800911, 2037292519, 941994402, 3350211940, 4004870359, 1105941782, 2367553097, 2440982990, 1468367, 2369391483, 3613174135, 2337161925, 2600055725, 1612773644, 1037201309, 919122459, 1114016493, 670586694, 594109706, 113464329, 4093636009, 307208587, 3876235186, 3370598978, 934478190, 2843794891, ], &[ 3428605691, 3747865452, 3179948115, 2350061225, 568002466, 1150456745, 398797276, 1289784855, 1713342581, 1243415582, 2262476431, 2640854581, 2126611553, 279688048, 1750838292, 4147801215, 1090003542, 3022523567, 193306367, 3095010320, 4106129220, 2615828356, 2229875117, 1066352114, 1628397898, 370050060, 4157038478, 3551524420, 3356007005, 71309641, 801692593, 3448737794, 2187893878, 3694205688, 3993669226, 1704384353, 437976508, 281233142, 3685881986, 557022935, 2623696682, 3473835466, 2373703925, 4102552649, 3005124737, 1604665678, 2894612216, 113726438, 326916434, 2354584210, 2207672568, 1272863868, 1643657755, 453968751, 3873638645, 2388412558, 2026577065, 3555348237, 2342844423, 564662317, 3301275728, 2205414701, 1980322846, 2111846734, 3351655044, 3986317737, 3746472405, 4065813457, 3783710419, 2063617629, 3337397526, 396000532, 1367889075, 3493608147, 3502046919, 4063752078, 2026966957, 1730343114, 1889308216, 2064908820, 1350757250, 953211432, 3171180512, 3683852864, 2865517189, 9728788, 4075807873, 230559850, 3447666295, 3875782338, 2964025959, 3279832060, 1701408562, 1524777719, 2018628821, 877683542, 2894422993, 2842238026, 2368190181, 2574790540, 3301078931, 519264490, 2640226714, 1382986517, 2712031077, 1268830384, 2018243821, 1374899410, 1932087493, 4236194373, 2079152365, 1069353434, 2794047491, 3019576051, 1360117274, 3615353679, 3816194597, 563906666, 1827758233, 3391740972, 4039283822, 474920421, 602146150, 3520459365, 2217822485, 1815675107, 1257332805, 101198736, 3156910259, 1281759597, 2577040428, 1316988841, 790502779, 2183328888, 3514409721, 3117638288, 2751392867, 625199304, 4183171081, 810287943, 199775540, 2896399552, 1276626819, 3536203521, 3977249862, 1553852925, 1596788767, 4199876212, 4164476281, 1700598937, 4111801568, 897035781, 3318378574, 4049506305, 2522517679, 2296942227, 91515126, 2738354614, 3444113221, 776723413, 2322159108, 258188842, 4014626824, 2677530556, 2630906411, 2348643583, 2619411399, 1783064149, 3684137491, 4249816060, 2342260236, 4186117248, 3931377058, 283592002, 2818946531, 2155019855, 1212182985, 937681548, 520081464, 1686760025, 4003314294, 120323668, 3282730481, 1331500167, 2103184161, 453960707, 3079516933, 4193898972, 279508919, 2459211929, 4262295127, 1413249938, 2652447340, 1521334653, 3641279725, 1047788888, 2569690437, 3517124875, 527659101, 950373677, 562851515, 3518587604, 2668894245, 2265163836, 2975852422, 3168107907, 3219343979, 3364338005, 4122186542, 3517854206, 626303838, 201513242, 4042863292, 4203206994, 154681851, 1046188872, 1014035958, 1565481708, 783475007, 1419399714, 1439418252, 3671223860, 338436030, 2221870804, 275182251, 790279697, 3288665213, 3033639795, 2320556485, 1648356934, 326278183, 429784181, 104482651, 1051376296, 3823684587, 3057907898, 4214146560, 2770254088, 2132180852, 515232230, 3723417512, 3994583184, 1170935740, 565152109, 1486190861, 2906472005, 3154973145, 1571950735, 1391459913, 2972445791, 1670706254, 2522911431, 2665886703, 2875123532, 623767904, 1291947264, 3935970871, 2500309617, 3931020115, 3436644927, 3672390796, 2307254280, ], ); // - q_len_mod_d_len == 1 // - !(n_2 == d_1 && n_1 == d_0) test( &[ 386353625, 2283334827, 253851108, 4279287864, 2561872983, 1000131216, 216965099, 1733322743, 3814906874, 520558483, 2573981410, 3011109093, 1361665859, 2981910167, 2501833654, 2673979284, 2696912361, 797890797, 97183495, 2324611911, 3471887001, 1013155374, 524729310, 3971281568, 2873934524, 1076401482, 1645093822, 423739674, 3400177353, 3716049850, 2858905860, 3351077705, 1478568656, 3370413874, 3966773377, 1660817988, 3770638166, 698194415, 92466505, 399941585, 3301477423, 2578917060, 3012966571, 1915213695, 3062576400, 2979801504, 3838450560, 975685759, 3154985631, 1986911427, 3559636850, 2134674515, 3128102806, 1097660929, 1212690783, 3611467219, 1232001761, 904465835, 671601217, 2829397960, 3910014855, 2035732477, 3262086074, 3077756473, 1064556527, 3095006074, 436186642, 3844079107, 2798261317, 3470373096, 218408908, 4184804463, 2826021777, 1939569756, 1452808097, 1149547097, 316749819, 1631475409, 4023391942, 513096309, 3730431754, 3391919570, 4153138767, 1328779762, 3015228258, 2487205968, 213982794, 1927310263, 897606115, ], &[ 133654450, 371159391, 40768202, 2113895976, 2732923987, 3215138425, 2391931662, 2672734577, 195120416, 939150931, 1941696822, 2919872876, 2564539452, 3080820908, 2846583634, 3349568397, 3465385329, 3550405793, 1724556069, 151917586, 3772273289, 4156003461, 2380288065, 356475766, 4123619567, 1619017859, 3739529130, 490749645, 267879469, 2890847693, 3854244893, 3384266657, 115723042, 103663103, 267682519, 965965574, 1841386548, 2476428873, 6965648, 3347378817, 4174270937, 911558590, 1958087705, 1467103561, 1925556384, 607664404, 2051263137, 3092553737, 3239342455, 1360744647, 331798903, 938411111, 3063265275, 4144610940, 624250586, ], &[ 3712980585, 4273305215, 2588121912, 1482202110, 247010829, 2649827458, 2673293530, 50266420, 3870816552, ], false, &[ 362121003, 2089507514, 1304606762, 1263278756, 358438501, 2269424948, 3806457519, 1279073058, 2059434869, 1815692099, 652038027, 526160281, 1238911451, 1042947643, 2960978573, 3022105016, 2649279744, 1198671551, 2684187685, 1000492760, 431499902, 183857299, 3280835037, 1246895529, 2318725685, 2267164315, 979921718, 3857707914, 3760109217, 2715707691, 1406885970, 2988297028, 209159729, 4186884247, 1096787060, 1637274376, 3553955911, 204938738, 2626213055, 3882415239, 2634475536, 1602083916, 1366306436, 671584326, 4002679807, 692653815, 3838450560, 975685759, 3154985631, 1986911427, 3559636850, 2134674515, 3128102806, 1097660929, 1212690783, 3611467219, 1232001761, 904465835, 671601217, 2829397960, 3910014855, 2035732477, 3262086074, 3077756473, 1064556527, 3095006074, 436186642, 3844079107, 2798261317, 3470373096, 218408908, 4184804463, 2826021777, 1939569756, 1452808097, 1149547097, 316749819, 1631475409, 4023391942, 513096309, 3730431754, 3391919570, 4153138767, 1328779762, 3015228258, 2487205968, 213982794, 1927310263, 897606115, ], &[ 3140142351, 3638334268, 927590030, 3257445174, 190628332, 423978494, 2125526010, 2335881748, 2011775260, ], ); // - q_len_mod_d_len == 2 test( &[ 3451729766, 1173985848, 93029266, 2489920009, 3973680219, 780152687, 1953113811, 856318718, 3314090115, 2569865885, 10849561, 743853677, 1946859719, 3063924404, 3352045106, 101532091, 429420318, 3158186124, 1342100634, 1680882573, 4042659776, 565667221, 989688746, 4541446, 834463803, 3523014310, 3432977627, 1818084880, 3544409611, 1926948225, 3663387900, 1035293697, 285923430, 3096314023, 664014848, 2054069437, 3124990832, 115905130, 1379323203, 2244054884, 2012040660, 1620087465, 1907788850, 132467852, 3020885577, 238576412, 567018667, 3426013542, 3145012002, 2070201540, 1421424259, 2074360440, 810615969, 153078550, 825376847, 2436604908, 1365021492, 288298963, 3753461462, 4215347696, 514661745, 3484458912, 4247537127, 1579462876, 3865189996, 1018915575, 2974009562, 3501816358, 2821759336, 2722697353, 517866351, 632193686, 1959130106, 2570573609, 3726681184, 1695074321, 1803440017, 268435105, 2059636298, 1870796488, 3616705235, 779907146, 3840642834, 3690603635, 889240128, 4220497978, 1506894274, 3744062951, 3031958651, 4062058444, 2309758423, 1411665710, 1638698058, 1784343146, 373693019, 3239595939, 1656022725, 1985062241, 2188775097, 395478226, 2732514978, 2804731752, 4294707867, 2796289890, 4286815139, 2694259304, 3400027223, 2866208426, 712658287, 3005677674, 3799280383, 333964254, 426632823, 1071506508, 424615774, 1216913008, 1528084851, 2440789637, 8647650, 1482353199, 1079815951, 1741478231, 335212928, 3230225069, 812456049, 1107265661, 309740350, 39813940, 1038050523, 3708554333, 2276389162, 3145208114, 286364489, 2078653938, 2343246544, 761958231, 2400118006, 2820784413, 91083352, 868359282, 2976918690, 1899156995, 2927253740, 2971404198, 955553520, 2163090892, 1779162381, 3706789234, 1427323973, 2892945053, 3765307938, 1888304940, 4281185143, 4063224403, 3895821018, 292451283, 1315405597, 1278053061, 2659048964, 1651475603, 2464063324, 2470117886, 885060568, 2223396118, 983203622, 2153273837, 909540554, 11662729, 1290088356, 3558268851, 2470462290, 3816443571, 1219777270, 1663771088, 2059674235, 3741754207, 918293007, 1170814255, 2592844500, 34078497, 868179007, 2916133370, 224466504, 1457353443, 743181292, 2045016399, 4268051489, 2582113750, 108054210, 1045580699, 1021681246, 4287699909, 2442965928, 2358040249, 2188665290, 2493816549, 1868457202, 1538714165, 3141445884, 1886427078, 2413842865, 3754082182, 1242353411, 837326189, 1891378866, 2004934119, 2718308820, 1293740965, 3706050263, 660923758, 4037329521, 1659464686, 3767070633, 2733667846, 1303579884, 720201259, 4178102594, 1521257108, 3676354960, 2861869547, 1694835235, 1663377877, 1033893232, 1788049008, 2131980496, 1380320795, 1706971693, 1547085187, 4249747381, 4022331904, 3773862935, 186851005, 1122661765, 2869769810, 714482846, 122240297, 1990969517, 1505355345, 1418846887, 2157766299, 3944099174, 752193837, 2717991695, 3106584127, 2176113460, 2424010054, 2202537322, 735567917, 2635174646, 57167007, 1501943516, 3981020168, 2264071537, 1811387936, 3230232665, 2056500724, 2470649052, 298208196, 361093257, 837772742, ], &[ 3759203346, 4116788486, 472182301, 1657732406, 1379670583, 1302865697, 694415200, 281678172, 1654699562, 3014506006, 1741431230, 3860463155, 1145719988, 3566676616, 2320845102, 2321995000, 536415919, 2387437419, 3567575351, 89009414, 1112333426, 3147195251, 3149954561, 1503279897, 3064049622, 172526224, 3226367243, 4252316042, 2985921401, 3319920602, 2971463135, 662010514, 2716903751, 3114900209, 4294888231, 2302528059, 2985636330, 4227410510, 523042380, 1128527265, 2237860860, 2902190407, 2028066064, 43980114, 85965472, 1423570354, 370469915, 2799642260, 678694776, 4007712353, 1236341524, 2105667795, 1513858354, 3031596159, 3550734930, 4152331215, 778814882, 736616127, 1334786757, 193672910, 4005017476, 49451649, 274162308, 193472860, 3849716547, 1147344616, 3779102036, 636364760, 49841072, 4203872775, 2917594088, 2516158563, 1718950767, 2409600701, 4112139783, 968713133, 2367692503, 1383637739, 1447827357, 70112330, 1597216524, 1036612170, 47442040, 3535655506, 3217988958, 1524147015, 1542229372, 4278993048, 1177373055, 2455939135, 3977288741, 2323766505, 2631150922, 2494146789, 1766908673, 2014027584, 3170299898, 2200469205, 447095672, 3553741345, 1471247393, 1705231371, 3597764506, 2179927417, 2057038135, 2877684583, 4157842671, 3988568107, 136943619, 1758053719, 133243005, 1316787143, 3912460869, 3007503154, 673776671, 2300353234, 2544200665, 1154464703, 2377559298, 2085288775, 570803259, 1718587627, 1887771341, 2141823671, 812587685, 473768462, 3537328856, 2051785610, 1867482529, 386483431, 2102139021, 3579998391, 1082229057, 4197498026, 2004997074, ], &[3960768807, 1512612890, 3846503597, 4289005374, 3202073567, 4260281911, 4219386150], false, &[ 3383011450, 2938966556, 422368941, 3441497106, 3409423652, 2305567488, 3562827580, 1338876308, 1099736044, 1201047259, 1743369967, 1491174234, 287230448, 3116597437, 1643175661, 4211676401, 601814058, 2723977393, 3228175296, 3419496235, 2059811269, 2947984775, 469809020, 251557204, 3013739023, 3166260707, 517974662, 920653259, 3867055574, 34801513, 4073639353, 766741992, 3966323891, 2226406520, 2341832923, 2682492751, 1942828791, 1732324839, 3967931993, 929680784, 1485027211, 2843893078, 430780969, 4066926931, 3159632662, 3397052086, 2311817261, 2992832593, 1564064832, 3020792541, 1056579269, 3627023013, 1422659846, 3325045886, 345931608, 1290807491, 3973995577, 3750219800, 350963107, 4053409628, 4058696363, 3668673317, 1418277077, 2159286564, 1868951430, 1399034844, 2585316317, 3592102683, 4163508856, 4075983119, 78320926, 2811875443, 4059965405, 1357445571, 2986007740, 326981837, 3415489538, 2531041805, 234199714, 3488607804, 1688036115, 744596707, 3014071644, 2766006369, 2628073818, 654781813, 4265430858, 4287622569, 2665792473, 4154810693, 2848091329, 755306763, 1245738903, 3190845925, 604185632, 294919488, 4045732560, 3602930508, 1226696054, 2425992356, 2138768869, 1417531642, 3016312849, 1435667556, 3658864646, 277170454, 1681853564, 2140619166, 76500316, 3095347477, 473108630, 4089067082, 1142664387, 709297371, 1129824116, 1641660886, 4174467937, 869296342, 332188854, 3873253978, 2646933540, 331422365, 2123872788, 1908091634, 1952247202, 3839276275, 3725920254, 2040912245, 1038050523, 3708554333, 2276389162, 3145208114, 286364489, 2078653938, 2343246544, 761958231, 2400118006, 2820784413, 91083352, 868359282, 2976918690, 1899156995, 2927253740, 2971404198, 955553520, 2163090892, 1779162381, 3706789234, 1427323973, 2892945053, 3765307938, 1888304940, 4281185143, 4063224403, 3895821018, 292451283, 1315405597, 1278053061, 2659048964, 1651475603, 2464063324, 2470117886, 885060568, 2223396118, 983203622, 2153273837, 909540554, 11662729, 1290088356, 3558268851, 2470462290, 3816443571, 1219777270, 1663771088, 2059674235, 3741754207, 918293007, 1170814255, 2592844500, 34078497, 868179007, 2916133370, 224466504, 1457353443, 743181292, 2045016399, 4268051489, 2582113750, 108054210, 1045580699, 1021681246, 4287699909, 2442965928, 2358040249, 2188665290, 2493816549, 1868457202, 1538714165, 3141445884, 1886427078, 2413842865, 3754082182, 1242353411, 837326189, 1891378866, 2004934119, 2718308820, 1293740965, 3706050263, 660923758, 4037329521, 1659464686, 3767070633, 2733667846, 1303579884, 720201259, 4178102594, 1521257108, 3676354960, 2861869547, 1694835235, 1663377877, 1033893232, 1788049008, 2131980496, 1380320795, 1706971693, 1547085187, 4249747381, 4022331904, 3773862935, 186851005, 1122661765, 2869769810, 714482846, 122240297, 1990969517, 1505355345, 1418846887, 2157766299, 3944099174, 752193837, 2717991695, 3106584127, 2176113460, 2424010054, 2202537322, 735567917, 2635174646, 57167007, 1501943516, 3981020168, 2264071537, 1811387936, 3230232665, 2056500724, 2470649052, 298208196, 361093257, 837772742, ], &[1749675900, 83311145, 2319870768, 2301367900, 1271820700, 747192890, 2232034578], ); // - highest_q first time test( &[ 1444823481, 1895962470, 1145820971, 951685031, 1619286897, 645659681, 3225126137, 1237595037, 528204561, 3332610202, 2935828481, 3511627759, 3794280700, 504366468, 2867551534, 432130908, 1682537913, 2112976328, 291513836, 2849031909, 3326433036, 1925364297, 3779561553, 487877982, 435659240, 1540143453, 3711236017, 1440132082, 825660149, 1624471959, 1941539144, ], &[ 110690520, 2114031203, 436730283, 2624140005, 3364550071, 806172129, 2495686202, 3508099340, 1915440069, 3196245075, 3757278096, 786923263, 1820433641, 3283619351, 2326488762, 119217121, 3545365539, 3063896557, 1866040341, 3325517573, 713948948, 2863092530, 2356199798, 3131342786, 4122497749, 3637172320, 2586791774, 2794104974, 1738360752, 1591954820, 2633103962, 398797289, 30804220, 2682142316, 1858898375, 2406882215, 999588447, 645011646, 3469603876, 3657151690, 2477958807, 286833025, 1802487901, 2709688493, 2318425877, 3516543869, ], &[ 3866576925, 1873138890, 1768109056, 2705255084, 4241776445, 658244374, 286815054, 153522406, 2020517918, 87408861, 541283899, 2327698817, 696800449, 1357243166, 2373189783, ], true, &[ 4258888914, 1485342244, 864808754, 1855573169, 2779156179, 2884098865, 3015216190, 233158379, 2131022258, 2947161299, 1457166139, 936993560, 1814334647, 2085655570, 1964344103, 3265126561, 2194874867, 2958220463, 1400730387, 3516776467, 3089823491, 3793414649, 3469628691, 1982433652, 3254747018, 787956375, 1101033526, 351690326, 3218501609, 2653245227, 2069227013, ], &[ 1748815118, 2402822363, 2091637344, 2074482742, 2316188658, 2370992052, 3607116276, 2077769165, 1723590682, 2807481888, 338472032, 1807369086, 4009280963, 3941733223, 1094544382, ], ); // - carry test( &[0; 7], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 1, 0, 0x80000000], false, &[7, 0, 0, 0xfffffffc, u32::MAX, u32::MAX, 1], &[0, 0, 0, 0xfffffff9, u32::MAX, 0x7fffffff], ); // - highest_q in limbs_div_mod_divide_and_conquer_helper test( &[ 2516900350, 3628420684, 45459239, 1513614219, 989392388, 453507217, 1512254264, 2426221826, 1233076550, 244898124, 2764583004, 3329101881, 1699874673, 3208045667, 2210327365, 948719692, 29636434, 309163724, 626642377, 3476255186, 2213282765, 3561515942, 4189534597, 950518908, 139348404, 1259661856, 694161725, 2634491186, 3727710582, 788362676, 3045474119, 4091304988, 2805201294, 3987583308, 1169494314, 1793738933, 1926962859, 143323906, 3767356737, 2736821279, 3155234958, 369913573, 2104538395, 1964464892, 120182245, 1607533355, 3512159772, 428709975, 3273911427, 1151542509, 2860816013, 1136173381, 662332459, 3578077057, 3243603823, 818341966, 1912641848, 3483224197, 605429894, 746864868, 3712846888, 2818736253, 462940792, 3732576280, 1660947800, 1011233610, 843846147, 2308498613, 1878649446, 1442264468, 2962205673, 2832862233, 1244894861, 1156622958, 1582973750, 1574948490, 3846938629, 935089728, 1705244040, 4043433438, 3114254174, 1062986960, 3905677705, 1930766407, 1354562200, 955778452, 2932639939, 249007379, 3763599833, 32702674, 3759419411, 4281057196, 1688108074, 3861261668, 444663411, 2875533494, 971084229, 1671724356, 681694042, 1336342690, 3989885039, 3351736702, 3656186109, 2518436399, 3272921467, 235621572, 641659042, 2119882595, 1983842751, 1488017726, 3187465143, 2506358055, 3348535321, 999852594, 4293611527, 1073384603, 250481194, 4148825621, 3839501948, 3818994640, 1414056232, 2701465891, 499495991, 1361504858, 1308748876, 1650859371, 3722040369, 223548436, 2431095012, 3829963049, 367284736, 451104830, 3192609374, 959276880, 2266256342, 4176815348, 3580491737, 674113379, 4084740134, 883805748, 892822580, 2297912891, 2348080766, 3777075710, 2743249275, 1929349295, 2464988855, 1327032420, 1398791640, 2085211945, 889984414, 883598216, 1429348413, 154972877, 3622910749, 1670306325, 2187005411, 651154286, 2688016708, 1041316505, 2776658464, 161390395, 3846865057, 3267383835, 1010302540, 3607316170, 1418199870, 3954492322, 922710287, 1323651551, 2431904946, 3054195005, 902509698, 1670133092, 1092971517, 1075109776, ], &[ 1426636939, 2291732338, 3067548371, 1958595483, 4265832187, 1189668824, 2839754982, 3301139255, 530760593, 3029188645, 1298922175, 1055363550, 2070850046, 992858009, 1206997984, 1510007185, 2204463849, 2600547912, 3402640587, 372285673, 54684613, 211924658, 2690037178, 1114469505, 374316665, 319939537, 1363579227, 25099128, 2808696886, 2318162131, 1283473588, 4173665536, 1302236115, 2981103428, 364658024, 3500679214, 73401477, 2399140443, 2401409782, 974668784, 3260945138, 700031094, 619920306, 2267288646, 225106679, 2520705554, 760523499, 2971006600, 2155228491, 967349835, 2899641188, 2567983244, 1086821788, 208644014, 2327565301, 3873773388, 1254243651, 3371628757, 1486945462, 3153661571, 3596439034, 3448680976, 2884772533, 2113693162, 3571562346, 3271064301, 2352298427, 2624271304, 2147301202, 1628031526, 2268489536, 2460058239, 3824853526, 1114448457, 1711950597, 2805133745, 3886047152, 1482425544, 3015333985, 1726209429, 1945238011, 2536476005, 1974758758, 3373425305, 2797746190, 1649833243, 2549697741, 2772403629, 1276934258, 1197267921, 480328120, 3145095762, 647795990, 605209910, 1896440782, 2021024361, 4280085434, 384535302, 228210377, 1342562609, 550195641, 304643910, 803682708, 2640613597, 214734489, 3610647775, 3787633026, 3169459037, 2718345417, 1486978425, 4213419405, 2452166506, 2369416903, 2146131022, 3632701374, 857903632, 2077812289, 2633196639, 1727541399, 1445819648, 1663740433, 2573746586, 150961985, 2843003920, 2121435332, 503235641, 2162411412, 2641993335, 2306838455, 3013627797, 187911601, 2832638744, 3245525711, 4114681913, 4248626985, 892023341, 4180070411, 462293938, 2339665566, 886499165, 2680618581, 1275413281, 1653569893, 3506841220, 805196234, 2798162194, 2468871331, 3396930973, 2515921922, 897743120, 2034157178, 2373161268, 3355723218, 3914014661, 994426990, 2992401161, 2581503631, 697892172, 82419160, 2053001658, 3320533046, 3791389127, 1839288008, 270908689, 1413534997, 429338594, 997502210, 3103236226, 2401510054, 2663896427, 3727426794, 2724686279, 3944143754, ], &[ 3845376373, 2532376922, 273377135, 3677509657, 2349096840, 865593650, 3913447585, 3605798835, 2383627001, 256434907, 1598943794, 582857664, 2095029213, 493203050, 4072709797, 2373943493, 3435129133, 3493851471, 1582101091, 2328189763, 853133742, 2400321806, 3544763029, 3255311766, 2487877428, 2345846021, 3540974504, 1867377852, 2499885368, 3386759756, 3964579463, 3290899719, 2797957335, 2863338106, 3380325251, 1361967176, 2820693326, 1270065483, 2316076985, 20080038, 2796142674, 1493193006, 3582143536, 1315905237, 884491638, 2352205614, 3522766470, 1928358187, 1698951621, 4079830723, 3210021170, 3465329392, 3919799352, 4222905913, 255999498, 707431500, 4259794201, 604859264, 3884712299, 2790776367, 3466495862, 1352500875, 1421557254, 3449668508, 339288181, 2600471637, 2364459698, 1593691125, 3908068568, 1590428078, 3967743945, 361284513, 1947639764, 2146594709, 698658216, 2934691142, 3852641925, 2677524346, 3136105113, 3755616420, 393422782, 4055467971, 836734774, 1342622278, 1842869702, 3646198604, 3250586544, 1155965487, 3143510276, 264136749, 764849704, 2833843864, 3628999351, 1603529516, 3414178524, 2241268229, 1653241000, 3792840587, ], true, &[ 3369583400, 1798959332, 2489167563, 2461009697, 1361288842, 1654052513, 3133509548, 2052390470, 2454818186, 91621325, 3151880750, 1899967999, 2316081396, 3597413959, 4267146135, 1546768645, 474411717, 1597284556, 2105139892, 4124114432, 3190771802, 3793203026, 3276311936, 2880323996, 1248675214, 83340366, 3739848429, 2035483515, 2728839161, 2427538604, 1330706703, 3030714454, 1781130352, 2866672350, 1381956557, 989054476, 1246309158, 3420842543, 2855783980, 2430281813, 846960251, 2085811611, 1851093062, 1216231642, 2046747009, 771854370, 301562071, 2564992655, 13210966, 3346332460, 602343193, 4038323773, 3846528060, 3292787443, 2312570709, 772642248, 3361839528, 2269167700, 4111218264, 1417638867, 3914782282, 3574321715, 2749659194, 3611340496, 3547422042, 662840159, 4181609060, 2617950548, 3566455037, 4058070983, 3770037022, 2124212778, 1485396640, 423608280, 171333896, 1574948490, 3846938629, 935089728, 1705244040, 4043433438, 3114254174, 1062986960, 3905677705, 1930766407, 1354562200, 955778452, 2932639939, 249007379, 3763599833, 32702674, 3759419411, 4281057196, 1688108074, 3861261668, 444663411, 2875533494, 971084229, 1671724356, 681694042, 1336342690, 3989885039, 3351736702, 3656186109, 2518436399, 3272921467, 235621572, 641659042, 2119882595, 1983842751, 1488017726, 3187465143, 2506358055, 3348535321, 999852594, 4293611527, 1073384603, 250481194, 4148825621, 3839501948, 3818994640, 1414056232, 2701465891, 499495991, 1361504858, 1308748876, 1650859371, 3722040369, 223548436, 2431095012, 3829963049, 367284736, 451104830, 3192609374, 959276880, 2266256342, 4176815348, 3580491737, 674113379, 4084740134, 883805748, 892822580, 2297912891, 2348080766, 3777075710, 2743249275, 1929349295, 2464988855, 1327032420, 1398791640, 2085211945, 889984414, 883598216, 1429348413, 154972877, 3622910749, 1670306325, 2187005411, 651154286, 2688016708, 1041316505, 2776658464, 161390395, 3846865057, 3267383835, 1010302540, 3607316170, 1418199870, 3954492322, 922710287, 1323651551, 2431904946, 3054195005, 902509698, 1670133092, 1092971517, 1075109776, ], &[ 2033854275, 3346500754, 1026391195, 2931755468, 4132970223, 507488150, 3787819697, 4267307150, 2229023955, 3535124792, 2115982537, 3261552465, 1403786253, 4168838966, 2905077003, 3343366362, 4058434477, 3051762274, 2754465216, 2139644668, 2121257326, 147231635, 1411313351, 1942773925, 1518792733, 4026871852, 1608765600, 2674641821, 3388658059, 4045496133, 4161170911, 1328400056, 1288717066, 741487928, 2130937044, 3073981280, 486422437, 2174741216, 4004413829, 1284627600, 1179437164, 1177246499, 2634583310, 2950709339, 3500520165, 502702338, 3556716680, 3168781392, 201139498, 1773610178, 1336109110, 75169920, 4261358748, 3946913462, 1177416531, 1904421971, 529501654, 760059661, 2718436151, 1695275660, 769729199, 1160292778, 1476806846, 913674448, 1863234151, 2549859956, 2693241338, 2672780028, 1641057282, 3939169714, 1414934690, 318354912, 300864018, 400872379, 1081977009, 3047385148, 3103660917, 175274494, 1331622900, 1558233166, 3851938640, 205628404, 992837552, 615234521, 3588694980, 848421132, 513268312, 468730797, 1030322804, 1991013271, 1629772980, 3351179781, 2259742484, 957712992, 1217297297, 2285959262, 947300257, 3115413281, ], ); // - q_lo && limbs_sub_same_length_in_place_left(&mut ns_lo[lo..], ds_lo) test( &[0; 91], &[ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffff000, 4294959103, u32::MAX, u32::MAX, u32::MAX, 0, 0x1000000, 0, 0, 0, 0xfff00000, 0xfffff, 0, 0x1000000, 0, u32::MAX - 1, u32::MAX, 4294965247, u32::MAX, u32::MAX, 4294967279, u32::MAX, u32::MAX, 0x7fffff, 1, u32::MAX, 4160782335, 4294443007, 532479, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4160749631, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 4294709248, u32::MAX, u32::MAX, 2151677951, 16383, 4294950912, u32::MAX, u32::MAX, 0x7ffffff, 0, 0, 0xfffffff8, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0xfffffffd, u32::MAX, u32::MAX, u32::MAX, 4294966783, 16383, 8192, 0x4000, 0, 0x4000000, 4294966784, 511, 0, 4227858432, 4290772991, u32::MAX, u32::MAX, 4265607135, 4290772991, u32::MAX, u32::MAX, u32::MAX, 7, 0, 32, 0, 16, 0, u32::MAX - 1, 0x10001, 0, 4292870144, 4294950911, 4294836223, u32::MAX, 4026531839, u32::MAX, u32::MAX, u32::MAX, 0x1000003, 0xff000000, u32::MAX, u32::MAX, 0xfffffff, 32, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294443007, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, ], &[ 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 0, 0, 0, 0, 0xff000000, u32::MAX, u32::MAX, u32::MAX, 0xfffff, 0xfff00000, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 0, 0x80000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, ], &[0; 47], ); test( &[10; 151], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 131071, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[ 0, 1, 4096, 0, 4227825664, u32::MAX, u32::MAX, u32::MAX, 131071, 0, 0, 1, 4096, 0, 4227825664, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4227825664, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4227825664, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 4096, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[u32::MAX, 0, 4096, 0, 4227825664, u32::MAX, u32::MAX, u32::MAX, 131071, 0], ); } #[test] #[should_panic] fn limbs_div_mod_divide_and_conquer_fail_1() { let ds = &[3, 4, 5, 6, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_divide_and_conquer_fail_2() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_divide_and_conquer_fail_3() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_divide_and_conquer(&mut [10, 10], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, inv); } #[test] #[should_panic] fn limbs_div_mod_divide_and_conquer_fail_4() { let ds = &[3, 4, 5, 6, 7, 8]; let inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_div_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, inv); } fn verify_limbs_invert_approx( is_in: &[Limb], ds: &[Limb], result_definitely_exact: bool, is_out: &[Limb], ) { let d = Natural::from_limbs_asc(ds); let n = ds.len(); let bits = limb_to_bit_count(n); let product = Natural::power_of_2(bits << 1); // TODO compare to limbs_invert let mut expected_i = (&product - Natural::ONE) / &d; let offset = Natural::power_of_2(bits); expected_i -= &offset; let i = Natural::from_limbs_asc(&is_out[..n]); let x = (&i + &offset) * &d; let result_exact = i == expected_i; if result_definitely_exact { assert!(result_exact); } let y = if result_exact { assert_eq!(i, expected_i); (i + offset + Natural::ONE) * d } else { assert_eq!(&i + Natural::ONE, expected_i); (i + offset + Natural::TWO) * d }; assert!(x < product); assert!(product <= y); assert_eq!(&is_in[n..], &is_out[n..]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_invert_basecase_approx() { let test = |is_in: &[Limb], ds: &[Limb], result_definitely_exact, is_out: &[Limb]| { let mut is = is_in.to_vec(); let mut scratch = vec![0; is_in.len() << 1]; assert_eq!( limbs_invert_basecase_approx(&mut is, ds, &mut scratch), result_definitely_exact ); assert_eq!(is, is_out); verify_limbs_invert_approx(is_in, ds, result_definitely_exact, &is); }; // - d_len == 1 test(&[10; 3], &[0x80000000], true, &[u32::MAX, 10, 10]); // - d_len == 2 test(&[10; 3], &[0, 0x80000000], true, &[u32::MAX, u32::MAX, 10]); // - d_len > 2 // - !MAYBE_DCP1_DIVAPPR || d_len < DC_DIVAPPR_Q_THRESHOLD test( &[10; 3], &[1, 2, 0x80000000], false, &[0xfffffffb, 0xfffffff7, u32::MAX], ); // - !(!MAYBE_DCP1_DIVAPPR || d_len < DC_DIVAPPR_Q_THRESHOLD) let mut ds = vec![123; 175]; ds.push(0x80000000); test( &[10; 176], &ds, false, &[ 2468656776, 458964117, 2715468315, 1790012879, 3522999749, 4214715874, 561506786, 3302400720, 534918344, 1263272887, 3075782921, 2067555491, 746647830, 518406956, 2268770356, 199166681, 585200343, 2568074090, 496918528, 707408551, 2864167181, 2697486675, 365965986, 566676423, 4243405542, 2529073250, 1738952834, 695156794, 4116132056, 240876219, 2603129425, 2192004736, 1342688443, 2964614325, 4249182840, 2414593720, 2593965601, 2916418334, 2637652497, 994042154, 3834346320, 2159029599, 988365118, 3644217481, 1407533479, 654358021, 2493606292, 4023096448, 1141066521, 983459780, 3892764635, 2438657556, 46466645, 374378413, 979049107, 3284790741, 3990074329, 928205488, 3007997859, 3046358137, 2915845116, 628001258, 3465083935, 4236663285, 474535350, 2027435145, 3567992797, 4283770508, 2324985479, 376140225, 777742614, 1991983228, 354120270, 1512293869, 1872844204, 2864777182, 1662657829, 3120313116, 1367744326, 3903740266, 1092780358, 4056570813, 2945196325, 187533600, 931587688, 2394937291, 1507441207, 345576625, 1601524905, 476504330, 1269949561, 3390313417, 881580197, 1002436463, 2217811800, 685849999, 185823896, 1272490189, 3967659522, 3205992619, 2860215323, 3472978514, 1224636072, 305126296, 1759643037, 3515215216, 4075133951, 1224421257, 774076486, 3594767960, 1443121990, 2854565002, 2031006704, 3471036315, 2258092726, 3015513815, 1591867662, 2298829418, 2586837892, 4173923545, 3288784297, 1655027454, 674268161, 118227690, 4135574019, 3420877922, 3419101194, 2933141174, 801148518, 2138817011, 4265486539, 2610068278, 3432736337, 4263393041, 3163494866, 1217674034, 638081175, 1411840480, 38063796, 989590891, 457807629, 1412034828, 1103809621, 2233526783, 1436248111, 1917272861, 1485988800, 1517198661, 126869, 2315908856, 3274287261, 3670331343, 473008784, 1471036169, 231026838, 3870905408, 2284494418, 3904415704, 3550806025, 1919076393, 1355185851, 1830925510, 1032027683, 3523514211, 219638593, 1697572843, 1874144044, 3230672849, 2851366658, 4206129317, 4265556027, 241571, 120540, 4294966804, 4294966803, u32::MAX, ], ); } #[test] #[should_panic] fn limbs_invert_basecase_approx_fail_1() { limbs_invert_basecase_approx(&mut [10; 3], &[1], &mut [10, 10]); } #[test] #[should_panic] fn limbs_invert_basecase_approx_fail_2() { limbs_invert_basecase_approx(&mut [10; 3], &[1, 0x80000000], &mut [10; 3]); } #[test] #[should_panic] fn limbs_invert_basecase_approx_fail_3() { limbs_invert_basecase_approx(&mut [10; 3], &[], &mut [10; 3]); } #[test] #[should_panic] fn limbs_invert_basecase_approx_fail_4() { limbs_invert_basecase_approx(&mut [10; 1], &[1, 0x80000000], &mut [10; 4]); } #[test] fn test_limbs_invert_newton_approx() { let test = |is_in: &[Limb], ds: &[Limb], result_definitely_exact: bool, is_out: &[Limb]| { let mut is = is_in.to_vec(); let mut scratch = vec![0; is_in.len() << 1]; assert_eq!( limbs_invert_newton_approx(&mut is, ds, &mut scratch), result_definitely_exact ); assert_eq!(is, is_out); verify_limbs_invert_approx(is_in, ds, result_definitely_exact, is_out); }; #[cfg(feature = "32_bit_limbs")] { // - d_len < INV_MULMOD_BNM1_THRESHOLD // - condition // - scratch[d_len] >= 2 // - scratch_hi[0] == Limb::MAX test( &[10; 6], &[1, 2, 3, 4, 0x80000000], true, &[187, 120, 0xfffffff4, 4294967279, u32::MAX, 10], ); // - scratch_hi[0] != Limb::MAX test( &[10; 5], &[0, 0, 0, 0, 0x80000000], false, &[u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX], ); // - scratch[d_len] < 2 // - carry != 2 || limbs_sub_same_length_in_place_left(scratch_lo, ds_hi) // - limbs_cmp_same_length(scratch_lo, ds_hi_lo) == Greater test( &[10; 14], &[ 299802232, 2821120521, 3181086016, 891739326, 736497831, 3980709285, 3375818113, 818447231, 2663163337, 699303808, 3766306416, 1006926545, 2441137698, 2544067966, ], true, &[ 229224643, 1806820748, 815670549, 204407994, 3185958944, 3971027994, 2329129898, 1099516923, 4253768807, 1256057898, 821933298, 3636132439, 2794702458, 2955917631, ], ); // - limbs_cmp_same_length(scratch_lo, ds_hi_lo) != Greater test( &[10; 17], &[ 1333179288, 1649693138, 1336899365, 4171117151, 3070030019, 3225196885, 4108439079, 3954646297, 638063024, 4277538414, 3277457249, 211212338, 1364200948, 4280413500, 4293399504, 2216765967, 2874951670, ], true, &[ 3443915210, 2295603218, 2419744057, 2759520395, 1944568016, 862757513, 374771378, 2859328789, 3506872242, 2421673342, 2468885898, 3005107568, 562470030, 1627801097, 2440421683, 35821881, 2121399373, ], ); // - carry == 2 && !limbs_sub_same_length_in_place_left(scratch_lo, ds_hi) test( &[10; 386], &[ 4139195837, 2812339247, 712806962, 1626328903, 2947517926, 2755997282, 2347019211, 3654990401, 2055029559, 2047178043, 738069620, 2149818033, 309630864, 294595925, 984043983, 951236822, 3743724193, 376648825, 1593339365, 227563185, 1874134978, 2807943566, 2192306383, 2417491485, 3316512293, 297138568, 2944100909, 2810082512, 665119620, 3864239577, 3520109855, 3002981822, 2546622683, 1756025151, 1423319454, 599853088, 460530389, 705981334, 552539618, 3941502084, 3349709634, 3660369568, 4191516275, 1528800983, 2348924921, 536392452, 3446783547, 4055134021, 3504562733, 2929958411, 901778770, 4237963198, 259318031, 1332469925, 397810510, 2137922926, 2519380736, 2577896406, 1043505431, 785332849, 2822966324, 4191916739, 3770327065, 3847462252, 3402720200, 251432210, 1578533442, 1712937183, 923979930, 280220794, 3293380821, 58676675, 1844830895, 1423620414, 4194849677, 2680873227, 2987401408, 3054997563, 3873823475, 3253516897, 3108585700, 1036642260, 3701470592, 3361442680, 3546225277, 2218739223, 564155191, 702047302, 1856675496, 4272520963, 3616818204, 3227622340, 7791852, 1610528696, 3522462693, 2296449042, 1081049555, 3405408505, 3147562914, 1940148078, 1129402371, 1876701550, 836206182, 1223716477, 1698320293, 2529561505, 564212319, 2789696380, 443251042, 2823939041, 3786276490, 4195951187, 3667489226, 971532893, 2743600172, 3037330715, 4224128528, 2995464410, 3050205287, 3794514069, 3133644716, 856691943, 4201452292, 348501153, 1203620471, 1838400383, 3827770633, 2962797354, 3177076525, 845486999, 3837777196, 20436524, 4276721373, 1755330325, 2585578623, 1854317259, 959489662, 1160837498, 3571761559, 3163627715, 2901883906, 2062957005, 3360581687, 1107261099, 228566566, 2557814383, 3508583772, 3839775630, 1987907537, 3937116357, 4075557942, 1464892113, 135879982, 601922490, 4155196105, 2081104107, 839459275, 557861287, 880140789, 1056812723, 2199617957, 3317528481, 2087992298, 958637907, 921274851, 3154866102, 264017075, 877303542, 3865752723, 3807776374, 1302371900, 1869052069, 811485110, 140041357, 2676834656, 4125536053, 171179365, 3771700498, 3425440532, 3227264309, 1543154128, 2694625489, 3220336965, 2749044579, 709181621, 2938548554, 4119990906, 2253937157, 2107618938, 1207222516, 1683811680, 4221953072, 2171761912, 2361269244, 1218314377, 987928344, 960497416, 4031250239, 1639847512, 3905432218, 2367546610, 57458558, 3770185025, 3589850319, 287603777, 924162991, 4243441755, 28593432, 2234223762, 1214198168, 2213332087, 3246012885, 529821154, 1596080010, 2256716924, 2362237023, 1879143372, 799154828, 2678703189, 1929808701, 4081552632, 3350711293, 1794596388, 1913506378, 2737040879, 198149267, 1887090525, 2083508083, 4031867527, 836150409, 1487419119, 3649006840, 1344342026, 3117129602, 3286034010, 531726714, 3818493634, 2688829452, 3432248157, 3806552324, 3379192093, 398164062, 4196498468, 1734011552, 3599517541, 241509852, 3872917131, 1538621009, 2828040157, 1983017593, 1489296752, 1386698908, 156979201, 1922448841, 4076360550, 1664424704, 1927752777, 123651960, 3939944267, 3005604, 3709073637, 2967489805, 2852961368, 1801607632, 3956884953, 454504210, 748001653, 3508419959, 2390033624, 4237480745, 1883803406, 59501653, 488021688, 3997215744, 144013454, 4156138229, 3207190384, 167672785, 256377941, 3785838836, 3977721847, 3392462430, 4056881256, 3422674218, 1637604924, 3061791480, 3075439268, 2345796777, 3039548956, 3679830975, 4100519548, 4223820878, 1246251349, 2789094988, 1261279528, 4128764694, 1552408181, 166251596, 2264884840, 806042015, 1273344257, 1858140664, 1995440463, 3254742107, 175101411, 1875902902, 4071806551, 786127358, 2299796383, 1344001864, 4174715279, 1521370160, 2176319001, 1345743938, 2456867417, 3171076699, 3897764891, 2772973782, 514961974, 3464245463, 1978612418, 292121862, 3636736076, 2272659407, 2274331899, 2772880215, 1604910771, 2954725178, 123316598, 545555686, 1505282294, 4191700344, 1093499729, 3833383026, 694388959, 2893900278, 3764927679, 4192192353, 3782397072, 133448517, 509945324, 2954071581, 722765544, 1180635727, 285984716, 2936179119, 967121404, 2905768257, 491288904, 600135579, 3439065503, 14264794, 483956926, 686531157, 3363035798, 3905972150, 150791166, 2723784356, 3266626182, 1371155093, 250336761, 679758430, 2220669843, 1371404999, 4205993408, 537317422, 3612437196, 1870187644, 503652613, 899335706, 1295444931, 858056159, 3581382201, 2982334041, 600961969, 1040115528, 3630194218, 3183659540, 4266985633, 3006565428, 1121854128, 4106907361, 44957935, 1229739423, 2382159630, 2285266310, ], true, &[ 1760088770, 4080526177, 2608023608, 2694893566, 3004066830, 2214237510, 2072514982, 3451962427, 3485197532, 1515079746, 943350838, 4214976192, 2981850513, 1937549988, 1829233582, 632967491, 3914179126, 2456791403, 3628658525, 2007162807, 1521235463, 948161520, 3827351402, 2205307930, 1303273516, 2090403955, 3125120326, 2973550249, 2163659402, 170314532, 2876229226, 494968470, 3718668508, 3650935973, 107817707, 2532423658, 285835761, 2250301255, 139168257, 2806883602, 578805866, 3326219151, 1901602970, 2556068326, 2844199513, 2698479894, 3728787046, 3617123572, 2737802465, 2919596304, 2536928839, 2842472828, 1114232765, 175110451, 2394784754, 1073221182, 1632800088, 1157318295, 1717474331, 946089681, 3106197206, 615168037, 418892634, 501982827, 2986457953, 1893146468, 2870765383, 2995035310, 2573692899, 3477374183, 2071198427, 408851767, 3229401245, 2377739259, 1928791437, 578119252, 2254241267, 78652380, 2481343171, 2555454369, 243482381, 3700865683, 2995183706, 2488100778, 58054772, 3942346233, 2473745660, 1701522923, 493462489, 2470313146, 1819837247, 2330284930, 3142712167, 3950226677, 4007462473, 949452561, 172944267, 1691823870, 2219435104, 3533670123, 4033487402, 2444553587, 636683551, 47678947, 1065529762, 3263050320, 2092343545, 2519888675, 702264901, 4018827207, 3006140979, 818479576, 3732144508, 1702177720, 3844143349, 836374747, 1688156611, 1269107088, 1920184236, 3443692773, 2073861277, 891840490, 2064863720, 1253640243, 2497953103, 2358358733, 3466359679, 3365482312, 3043490905, 3493002877, 2370987911, 2125398795, 2298093147, 3168989499, 37076949, 1291478294, 1505564872, 3116600055, 2110018206, 4029514678, 1008993328, 2147039657, 1901430028, 2950027853, 2946649371, 4134547468, 3226580242, 67002805, 2061914186, 3435506795, 3305296188, 3118926502, 295938263, 3154848702, 1589297569, 1009644335, 1975002616, 494351062, 177792213, 892936667, 1985856724, 663011930, 2023064427, 3079345397, 2280115487, 4203733211, 3138908774, 3421884238, 3191420860, 764158096, 2603879287, 498589969, 4170367159, 2819475894, 1727077689, 1873104274, 915049813, 3805534647, 176482024, 403322181, 3368346834, 727193433, 900646796, 3136999543, 1613355909, 3820352029, 471439511, 3471432766, 2597114568, 2009837938, 2097632715, 389166167, 1520996840, 2344734085, 512633468, 3658635856, 3326549414, 541537802, 3175329594, 1115521890, 3735752302, 533040624, 56216564, 1874766932, 1607160247, 3369156252, 1450323938, 1142635331, 4207543509, 435950743, 481361367, 3824656441, 125520431, 3292911980, 1675469381, 2431218394, 511182588, 3479222912, 589490204, 3553506996, 3661709471, 2316618654, 3550373878, 637631474, 3286110763, 244959945, 2755104673, 808873559, 1203129909, 1782570471, 1686763662, 4191962546, 2412523467, 1421588889, 723752795, 1565383987, 1318771925, 2220007547, 735466750, 230658922, 2961374421, 3695325463, 332357800, 2802182630, 1730542835, 2333489502, 2835283919, 2570040420, 1616532567, 3720529315, 4255972038, 829762005, 3700718193, 548891081, 4072462181, 2065133636, 1848015799, 3443807950, 2405066408, 3915008762, 1771214599, 2430422722, 1128497450, 3442687835, 470675323, 555235400, 3286905630, 2352651205, 432555847, 1420447424, 4040437919, 338923254, 2725984822, 2023735825, 1460042409, 1908406675, 227654190, 1604523408, 3244243921, 133688164, 3064060274, 825400946, 2986602176, 515391607, 3051097076, 300579920, 315609812, 2442041976, 3222865686, 118218402, 64228258, 3425231024, 1070030503, 3353054629, 1626756792, 1818031100, 2401051982, 1526192477, 3602675682, 4033108418, 591128181, 3633475386, 3157206335, 4104216, 4025784094, 4266193286, 3001126208, 1337250415, 849416722, 3366284510, 2345597524, 2989746743, 2720174096, 1786442541, 3985055947, 4203001741, 3820341370, 471657766, 2355959089, 230906874, 1276534260, 2537678103, 811570777, 2584355518, 485370897, 387761024, 1152564004, 3275183056, 53471703, 3659550427, 2979266253, 2595802853, 826532396, 204030308, 4056457437, 3759821833, 554940888, 3898319353, 3448792241, 43692421, 3180294571, 3458984544, 3685975113, 2826822888, 1945528754, 1535708884, 3885432471, 3758699446, 1165404565, 2794772054, 3117403039, 1044526214, 2907540110, 633050460, 2831691446, 2669183055, 1559434402, 664522226, 458177657, 1420820322, 1119080846, 977395351, 1701334796, 3891507914, 3557298907, 1340368221, 4100667588, 2864910492, 1990253606, 3528312622, 322862997, 3522066321, 257961239, 4264277879, 2930887517, 1076405866, 1366357571, 2601454765, 1784972437, 1588243763, 991217823, 620712910, 2406746141, 2860518703, 3892074672, 3777065266, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { // - d_len >= INV_MULMOD_BNM1_THRESHOLD // - !condition test( &[0; 892], &[ 996305544975114981, 12929066524383774152, 16956610067055251962, 13012122099231548957, 14395689158572846177, 7935429077563080059, 17542764935243101497, 18413828249925519615, 17271321257298840331, 406766324155888956, 14818331828215117974, 8187386216945380849, 16792638575276899182, 6540004189057298818, 465689003663102769, 11974785539062893556, 11523099967255714584, 14591636912283935445, 4871757987380755363, 9308130069290886865, 10612219179153523310, 5420071244571425562, 12724302122592532888, 5173545157589181140, 1429324130148847596, 18414282026575416657, 1721766939064217260, 185288146264311331, 8027581238524003859, 12629121378225318691, 5422022678890177669, 6300007666394297907, 13771277516427401556, 4461063943424152501, 5814271695863693557, 9833762282568603070, 5534898830643720899, 11414581203473717153, 13252208296859650317, 6070377927034194834, 468982118171070321, 15569817073538385644, 8515954578625472255, 17703147536676285546, 2713926565223832109, 16501613896332875878, 12360649233716580846, 6951122318765494287, 1255018572838364315, 5022530899188934293, 14471021290055621346, 3965972119993826976, 10914640319991729939, 4671893019190076511, 8132288757883741990, 7379730619550447967, 7082846353163966035, 7749284037330602929, 17090786448482076935, 3623093583024522445, 6775174256836032571, 5932859643874401763, 9263718069255818484, 11941172789559596258, 7505495305758940713, 8374557854631657796, 5030384219708396008, 3609081759463861677, 2444176790044307758, 12883357531875110193, 2545675590276006076, 1091049428613676247, 3001645527995991696, 9613284625002680960, 13486970893816936976, 11564610387350917328, 7838720830134816136, 3368189672511472263, 16407993343222005051, 3965440550685537978, 4708478243468404768, 1875742626798710446, 109477476572266497, 9185060711428219960, 2062557879153655855, 15504010890019002364, 1436468774610332740, 470895386030379118, 11192666441535176072, 7094623340817246353, 16041820192281853667, 5048179711756437977, 1908765243120848557, 10810219542319634593, 15971282719319513661, 8395180060853137311, 17415231760777435363, 10489441496511966940, 3213813993411776195, 13309643264471443871, 14152370013037392509, 9805694808649718454, 2991106746654603900, 2279780759950444362, 13989789024965052794, 11942900996372546394, 15051646099368945987, 7583267444740224154, 5192555551306992142, 13216959612015226558, 14397593124921798192, 4374707725758052604, 15529039788482882168, 16475619415913302762, 2649655538625316107, 11899566009797061232, 16892018353302708322, 12364166218684092426, 10372683350152669575, 5328477050361662527, 10949313792626687170, 11924230090558408019, 636095257275314085, 10210914536395617961, 6515368615710817299, 17001040330117317563, 4519581466335837391, 12514298524110577503, 1744739741016504912, 9689951195577973993, 2774540351629210180, 7646006525601223889, 7530479442266342421, 10538917317906671989, 6031253606146099659, 4606167752034374890, 17763804757970320617, 6871166461842469695, 3069238346134678776, 6898492556629873366, 18330913680324098797, 11469514731644700404, 541525751461369940, 18096353837092553451, 16390355202675291281, 11980660197830118439, 15349236833293249382, 1901608480726107605, 10754477505423276549, 1780265741680781169, 6204486525934807168, 2675596223932028138, 1082656654749778403, 15313246555910578407, 16597928615331243076, 9259667019969423039, 13966308744186245944, 3711817850123753976, 10380302371138242940, 1102076039759449071, 1796134829015781040, 8320143967311972799, 12603759772660781109, 9343508021191710450, 11833581848018650785, 5036078561764059265, 14477046704375156568, 17958581882146395247, 6312863763728381603, 5890775652924120757, 3024100139720533291, 15594980805126031556, 9929023026443104564, 6003618257535256748, 10584762467178432077, 8070692469310128137, 3448506857138757663, 12067250229870443464, 8289617863280099780, 7705347156484755083, 8239333463449775936, 12953560490361273923, 7863343728067574413, 15499170354027597711, 16789849673988523596, 193554686279189480, 9324166766841362509, 17865442848307712220, 4017570072096420828, 359910874540192895, 14283136222667718022, 15545842610688758167, 9161703351540143861, 10856046010222875891, 270665191423043189, 15816860058997167317, 10604344774996324885, 3421439666836669232, 15362489920565158049, 901986887674190509, 8102011985696643347, 9831189590417175739, 7694208525827500802, 17761503253302918415, 16843825659097088549, 15968418888658984723, 13213298841864639514, 10768746828601368994, 15843374988242905966, 10372481985078119452, 7145529267057724453, 588445411774656377, 6907651744680403237, 13729433346623178186, 7466282812151723072, 2397976897839660773, 3595288154116844222, 3771046205661211665, 18292138992930644589, 5076094080207419189, 16955129624357257007, 3929215337030354093, 11057894513779502294, 11863471976993485758, 9408615240131003867, 2448439901554368107, 7669176413900589628, 13955883899642443946, 3559761514651432863, 5999853120304570098, 2807928142993089395, 6880972979489023884, 8540438276045396759, 13336393887543928327, 14948024915319356336, 754486632845103448, 16252590658474672770, 11838852632524903679, 16841746824793599992, 4866584459095974245, 13046184814853980498, 8710985684981006226, 2355658489901240093, 17682251256218590491, 12738885399031396318, 3641463259326479601, 11573802402437143897, 4785854649163125380, 17654700608592820265, 7689738254866306083, 3911334929659733907, 3805687817679677472, 3372180752527728873, 12516023017017683246, 6541569134387572029, 14932792460356112158, 274079842264421275, 14741476297422044947, 7640237864595124592, 7990415001403780690, 14485175485850127358, 15701126719940798119, 7497786401585040464, 2046586308065249596, 4234230752844127257, 3490034085431124756, 7410205974894450493, 13594277608316567296, 13163068385450899386, 6911330603633557461, 4165273348787835236, 13196815825235476993, 15409229411685315073, 4238586327560550200, 4274172509763128574, 8233070080684386642, 1152981557203525396, 2258263369774438742, 16860590243592954334, 10642146327347114407, 16394076595581895042, 3547145813374894294, 7303429257652622247, 4599869911214805642, 1470127264048118954, 6553553520469198052, 624221776008514758, 16024993613079197687, 12072685851575104500, 4289561477780298769, 14522030035108027997, 10025959010474970695, 4338629041423254482, 12668451231751642706, 7041673834301289685, 1101300709714299914, 15830324192849592102, 6361267392222383309, 12743724653827284764, 13913765213720067888, 12472686594479717483, 17041667280903689118, 12612588174971368395, 4625038945277105759, 4288983616264520473, 13257170061268337928, 15378358854815534796, 1307879339751355693, 9045256242044980161, 13066137780318064542, 17483698129188252816, 5537781126683250458, 15814088167067959984, 17124111106622331645, 2228813159198082553, 12771677329276373795, 7473600359686104579, 10172401847101693206, 8817322474066906889, 10002046533039894942, 18350636570159627372, 2608194133937884904, 16496103406635747044, 3203166370447920771, 1416097169966651887, 860034031549905008, 15435212006888252138, 4982756044520683355, 14527835149012332766, 15648655845991912781, 15220061209366144565, 10713592116389348982, 11856331444132914701, 13011883287657858557, 18375660967945668491, 7611177834315648116, 11475292136381607303, 12142625427672665818, 1644376245508948388, 14986147846200059747, 10358191212479538383, 2124663276626493099, 15025396046176607689, 7566356641233415240, 3834259550197202335, 7422439917941038432, 14335746041650957139, 11010643115481291768, 16639917992723217687, 3400935192914355446, 6526469202356090658, 2911450085827434145, 2592450403666061908, 6573976403851247795, 4285219873414520276, 15329532146725863869, 6799347789229688901, 6639341479260471078, 5137054100466749121, 5102420602612942914, 12454937665202983967, 12962650067948965377, 17483657740097839287, 12223498331603994543, 14079145217780475833, 3310333423646124225, 8148231670879135605, 9541038636961784750, 11089617618703446533, 3560209342825276058, 2574634823119268479, 2588311243176990131, 15013509191556503430, 15455072885984268053, 13986137485131324765, 5720067926322634989, 320358790111393789, 15410939285136639329, 15697272961739331244, 1355846111750777085, 2546959351276906905, 14534695021313396715, 12100942362109396400, 1909839808518887758, 15057164163203198957, 10816292376571145141, 17932667027515587541, 8894763284691124395, 17376767493810914651, 1054656077023869452, 8186894411081110112, 4918609723063820894, 10472223930221187526, 8210872174259857628, 8260857529094096436, 11707883934354468821, 7798711246011152830, 12313898141945763999, 4092899057830195664, 12768752632246510730, 7011904089799177666, 18269846218072729005, 4472126139715717850, 7263280326862818361, 4617033187864299345, 16062484525314928005, 7764862313171817272, 5507098054488704246, 15417948890339509732, 3199184308759380889, 12873647785813929264, 15851634423390314715, 3379562369756927370, 2914796073219663247, 9453518290639493724, 10389507097848983202, 6987583823829734148, 5644521590882572085, 16385036288302112854, 14202037992186130818, 1662729350231436066, 16086866498209553899, 11668110277201388817, 2581723866463834707, 14466562150912612524, 18444381539786477861, 11792751584642451686, 644172128540161319, 15714856399314491326, 6336413224068482580, 15648040294508822482, 3581892413107868745, 2087860646799841458, 12928312782299116049, 4630539989871908829, 6915603518697601787, 14918733616941773093, 15087665207194981362, 613969264471068110, 3544544803540968193, 5220360717428049381, 3375260723217895506, 16778447987047186697, 11894812810172861433, 14542979312432827779, 13561316753657099179, 1968473618327458185, 5456934299993876358, 7469735400543018284, 7068657239043349097, 9254040800524479410, 5214107275553666760, 5001330682797736624, 17026132790954295091, 10969354337912897232, 869351389198733586, 9574587810937905907, 6923373747285449001, 12719903474522918771, 12250857818862900982, 2153256573644871951, 13709729097688338391, 2899377834668376960, 6841869401787596550, 10339715141881541659, 718655127116157511, 13741406681906111321, 15392288868670671619, 17545786767738322758, 11089794771839702758, 219094231550242583, 9674358307241496741, 4002620491443309348, 8012290324302967070, 8714326673970415123, 12380264119087982419, 11108551912665576265, 3708955946231240253, 11607264285750874901, 4216424611300123940, 8256067698160491644, 7506994298913059376, 11501100133000306066, 7549037119651533111, 5112970978157051505, 13518442004335850902, 7350008695599366666, 9542638447580599221, 2158188779042279647, 1604170908932337076, 6391929341437538244, 10779746559124306734, 12656450449103176181, 10121044395803332310, 11651522650180060700, 16328514328541821784, 10523761782294701174, 1822303728984452144, 7260452386953933551, 12204494523152059466, 17100382786462731446, 12548225060484474439, 11326872465335361323, 5596285187831113760, 5909751003547848587, 992306619579834385, 2228664329259510492, 15196270917670055982, 2131889695890586742, 9819776790840463517, 1473593931814601068, 14939513955417919643, 7685117665289355354, 6724244559482510387, 101460542568704969, 7352190705745517803, 2150669404455836808, 455126870518119052, 11553577781469330615, 10384536636375637150, 14364597940339752635, 2495319672618636831, 8180783418013670444, 3773765470722916252, 10227754258298095569, 4811293038656815364, 2304664986814074602, 2418992918773594204, 6388448639180737685, 6893696275605311774, 13851958766811817366, 4793074330182947851, 4813793152033309122, 1098414269347239038, 11751908186279088029, 15167430159498163699, 10528686090760108130, 17120804521852235295, 5538072916971524268, 18284870874128074659, 224523015148941267, 14496093443691170173, 5490655299006793623, 11584315652765207551, 3229579698633170375, 5527375504543907996, 6239324650299686862, 2232148196848710005, 9031256656667465794, 40023723987633148, 14627741678268078967, 11950626749898431344, 14785414395108523186, 870832948163923646, 13004928204786500706, 11732704426571300600, 907514934656616373, 11587740830029349245, 7583505136677874861, 2623787766244261370, 10256163025245964672, 7257287909572091733, 4812915812660879618, 3468364439026649335, 6604147596013682093, 16816894664989923710, 3964120271755066308, 6086548275463043980, 10447117175471304144, 12856607441078849807, 10592398111690221432, 14269275707379118835, 4396127772639422927, 10489721798852691549, 6681412646421684356, 12490106130106455109, 3624408102113036819, 17246634770535451304, 73750230380742720, 3858795004528971618, 18037249274864620640, 9013680198221453825, 11909298583725721915, 7512555591920604211, 17449244834240874515, 7793591661081767445, 16652407448095073621, 11804971167281860328, 16410605854679152138, 1713343542446776550, 16483548344281970818, 4628627981197409087, 9083762764219706193, 17065951854876058290, 11490185594933330698, 9891012968004512035, 368256788081374064, 470621950908252, 17956316299265730194, 8221822257224301188, 6380872247545425488, 9031471961851140451, 17956391258409007260, 13017604911584754606, 9245778199486992293, 8056793204522970093, 2531655295742236851, 16039488662052065607, 4695551407385442957, 16581782264738209135, 9457268466305801158, 2502271077174158302, 836797013558343943, 1224523470498102285, 374165187087964522, 10212314508075547184, 7669093970332858967, 9176723313583927295, 8839526249801396044, 9460240515540152245, 526138750665184089, 6908994573320912372, 12176043050383940227, 8431292525679019707, 7800865258551716648, 2930208417676545581, 12001139080437682925, 2848294057310329443, 3495763019164815081, 13998099468531902475, 2334207795701343601, 1265352082029868252, 5352951968929077427, 11045950825318827473, 17705541510574119706, 10388016860076689091, 6188336841660552180, 3874842388902329486, 3586889024655840994, 7577730940669490050, 3828324032996703471, 7382564057518691083, 18020764642442034007, 3255848346667024023, 913981917700616307, 6544220161742236189, 628453794376152858, 5273139986123145851, 12804359385937816703, 15490118777013724970, 5004956137979193113, 11537600208633214816, 6041778305931749161, 18021165191120757752, 4439552721639804321, 9445924893904633163, 6333608419766441318, 6265966168082228187, 5090746176805509189, 12079779788101746835, 3405057163683809716, 18176431495575685240, 5416316679824315388, 5666993498240944478, 9396996717121195736, 15077940112899068312, 15769845674133811095, 4172092555141541227, 10535661541737621064, 10760049649331328984, 9044328015087752668, 4208484814661836163, 4524519455413453106, 8416163180819044235, 76133776812564214, 8938397440798861336, 7699462000599225384, 9542247023407697767, 1397476485288102889, 12838783590422826565, 11111769246893411506, 17719085637529819037, 18350048131892648764, 647133208572620551, 3545832683987398107, 17392149180006432089, 4645454948531556636, 4638633830898005179, 15832113029610700219, 12312766094616504216, 11054531676785061901, 12882000175930708962, 17065292675540451547, 7348135285662513163, 10368855461513742486, 17213692472848349009, 5448237816391429929, 17475251701204191843, 12352004908893419844, 4421019229248084817, 5233890583141520327, 15415498665325430242, 8699482400205838797, 11081065321342975843, 13692414560354688711, 2057100631763259620, 1768191442150902149, 12463118341434320148, 14697940362261450576, 7225350934202123472, 9180626944525820669, 14817691250517499688, 9524098384486815580, 4894140555324164954, 2309262794362375113, 8645740617004046828, 16829903653299752341, 4278553392732422821, 16174995535301769275, 7274361875865992211, 5483861345936568593, 16555617280692737205, 2106788877369503099, 6355572984153420404, 15413046204382700864, 15184587830187202860, 17638950466015943646, 10142359495639047596, 2852278080143788489, 14902051473257283997, 12684082230048932446, 5127878269602498356, 1458833335160283623, 18343902965575788886, 15956410439937236477, 10143815431586875695, 8519328419973108156, 9379288137799805556, 11116700304696206296, 3269635235146511468, 7446145908658980471, 8423421258962502269, 2960959498368537205, 8029834119982365442, 12951331847284209016, 13335373530776006943, 2051038411438343086, 14988843915712852160, 11070472159205332532, 2405233098821133668, 12872299485466251244, 4146849588411590424, 8652997027024585292, 9417874732592565535, 2771366489480367357, 16381568131097774387, 1160190173665475303, 12142110843989704382, 17157977103678150822, 12240974252728213375, 8005232037362794911, 62748564819661432, 15562900352067429326, 13819933941831285726, 8700733640462543781, 17417693392111317966, 11195518897113567806, 8656545261572504126, 2665140739762930045, 2523114891549547532, 15947075740878853027, 16617762624958355772, 9189411410511795645, 9417682881040880723, 1220008371097876826, 4473435335583972063, 12416336276688398745, 9439155074539900208, 17599514971068491442, 1382978212068751289, 12012964446858847311, 13059411911626363940, 9000605160655962560, 18444429515577739106, 1678358883660355393, 5074103451266196440, 1108189786283239561, 10612698979413855931, 4989895863474068758, 653620819971957060, 12060263383072344947, 15076531277958824549, 10597595939754188762, 15724450558403473627, 16382650125476798913, 8738893762787150302, 9733212779214420390, 5558001311635500417, 2720376062751869999, 2936217033743496825, 3059230718610361194, 5589670835881847684, 12297086381101763222, 12830838307506907529, 7727866232017902927, 16978583538503170044, 5646531489086592542, 5696883024644775459, 1778382958859079024, 9219341275099378906, 17593963150311257769, 198176573650528594, 10425519151629874209, 13457055667833759545, 17213583299444020650, 14862117423842849302, 16906392281688863338, 4290302946266596427, 13505570400341984024, 2056510386911305907, 11571082458161054292, 7566281435617775832, 10210241606684674096, 10697498687651578080, 4947318501826974509, 5861434792576988890, 9869040491958929661, 5532013052186573089, 12416594018569715230, 10820734898252214278, 8537468997207455166, 439343392893541672, 14734630723072977466, 9898041261033982210, 17393034157801306127, 13758525217758656857, 2713096067589327874, 12442874178280670969, 14498768890161377807, 161967360889456606, 11930601082339405958, 11362787206913160786, 12545070484550723467, 14815095129086834610, 8605787829002095856, 12923597973881209899, 10587151577465292584, 14183134664818382968, 5172374334040473114, 9364926097792520560, 6171919845492918332, 4386231931762251578, 2155663571428617218, 7765511219465701910, 12061535530010910259, 16100330205655290696, 9974384126080194942, 9674175848724908032, 1687977953933677553, 2052842863240418404, 18296704913226861337, 4023434438910601547, 9899743965354682742, 5310198234766113901, 5162456985274720081, 8646509974119784542, 6113717383160009894, 6014191554047499022, 8484348411248636487, 2876047496375093909, 6660788054730924011, 1664197372146636482, 2820993293910648101, 11665512417100144808, 6502457677692154814, 2170150732610996776, 15522116097990839236, 15440086643427998964, 3675113412536301313, 8316358419658521853, 189389437052919038, 6981753429704993440, 12802645856607643857, 7243825699014665843, 12796799374814419834, 8068467907492367066, 16310382387876189712, 1486061732225930791, 382533986053029739, 16359148449656380800, 17246074348224240328, 11700746273206874174, ], true, &[ 15498103360604201801, 14680681220073716272, 2597755073189185031, 3031720638800363592, 1920406924732488878, 10671706282978043129, 6228787134876346903, 379886459615822925, 13395893364837647375, 2539271575052356599, 5822821431547583252, 11653751705603753257, 12529814421763290515, 16725786429659625136, 8733808577647898400, 16438345524314195560, 13777363959694830441, 14778407189296268050, 7947204033657518709, 12198601215715000710, 14004671183850272040, 2889674051614386577, 10853297240118727311, 6550855388784511682, 10594647619939535751, 16524423461967409279, 994846650169701593, 4039993035738174198, 7455026353542067531, 13807909686230087400, 16619061172485859478, 1546401888779565694, 9690928310204887436, 5454239242551327618, 3786919253240050536, 2972332442098923930, 1865268881810449860, 8339549666946765074, 13006352754592757965, 1714792330552067567, 6220026947940415121, 4048069131584252803, 17688504380133199508, 17216109827709949817, 11949387591167859998, 6855711313153816508, 17917442589402729465, 8600885059137106442, 14888743631958063001, 9431744630167571473, 8272246627545091450, 17341832173311952535, 5160662201476171772, 15038444760033175970, 14039296666679545981, 2263167394422146208, 8446862552035629888, 4853953753265406906, 6685969515208740927, 8256430291108630658, 10896747900245806123, 14368162519606825238, 7786764717051573685, 5370546488631029142, 15582578406703215017, 9494185062826522189, 6363441093260940599, 16190691295942052876, 12724998683972539048, 2102181153200211977, 879764964453554414, 3347396463829460164, 1027339669743783444, 17583129106206895304, 282387697705284642, 17110710405896291662, 11498688457889144764, 6965355384393768126, 13278709567767772146, 4819923293192931680, 1170338567469074232, 763615589049737121, 2348050584087482620, 14097296695204456959, 6384334913949883710, 6028544760791927713, 8187545488055362231, 7063217129888877167, 13479644449093004187, 11992733912376194292, 7409310591773283984, 13031150744286911622, 9332879416429877896, 2001884409427827782, 15203114628217631180, 14017477444722883946, 7610351877068962234, 9319846690308621869, 7203395294399241513, 1778452692808043374, 12850855729587627891, 1360166033214989666, 13959275740256150433, 1843781989277689675, 13164190414140016883, 3081307608579392680, 8221511042828430700, 10565795978869754992, 855511478939793280, 17555024393632391969, 4676606444126992994, 16536255467354733310, 7706482596057768719, 7982435643880136195, 2343558441420595688, 8038073847992125590, 6532371125691312796, 3497211664997370445, 17060901251779314901, 8091433945761175425, 16183609030655920635, 16134243026506678734, 9180668788515171706, 18003960143664339508, 13887735155279069367, 2659683821455572987, 1331603854454319596, 16082403620038202501, 369464106971055547, 16311050942660421666, 2994870778517660556, 11130168214536899193, 3300406311663170456, 1075089886256539971, 9012950151532917276, 641757861159507369, 15966286426551108727, 1226877989263316310, 17112637329270715265, 17323663008089158231, 10026469426888150267, 524479246512834180, 10905694386442894721, 3672252371967730615, 15037399789406973858, 12269806864516545683, 10761709967947971245, 13105266188161840706, 17338364687856820797, 16100433027433167590, 14337016682458810045, 3332196670791019099, 5195803899392128754, 12941547540344482902, 9032161337701862144, 5119058081849308896, 9293401341523949372, 2355093473782322052, 15065206658334786999, 6783932346331470797, 2282237337525993718, 12116195797686921304, 12268793128461513563, 10265900513243166078, 2970086998765846777, 5285800515582961715, 12385459780641615157, 5601921082969230188, 5739224955818992148, 5974530395831456872, 11711584111803267702, 15646178135498987414, 12157670326998106818, 7791656942816786940, 14344848147208564924, 8700884833629903231, 18177769559740364464, 18382136005865921159, 222823780357781604, 497948724088869099, 9863620480969751318, 16308985429832874022, 1368611891476963920, 8858581712296235685, 1793308458534327344, 7396111023030682916, 3895507615963378822, 14177713440849561511, 14508402349077922893, 361323830993616269, 2825345270910018629, 3016833259740851983, 14483705479778190024, 3191843655544259254, 17070318950017119283, 2247769061143051061, 10292893110800209725, 11180590473858949296, 491608769894573367, 4091862619508686394, 3622150583759937322, 9568595877746213070, 479214495394894017, 13004153549418065685, 11861044287632377914, 5905426964527919438, 15015303818527343634, 9416264667829720601, 16081900471086526579, 9098802851390736358, 7391232700349409101, 13667214033814761539, 12794230344463343073, 10563713604936057218, 10052294573876784373, 7759412720896564264, 9366854730557707997, 2352461940723137072, 11608039586815592966, 6223890086918678767, 16955768079151639030, 13958082335128634418, 6355109232855010962, 1203057641719310190, 11741473200072129728, 5883089625042104026, 697399775759770323, 7003550520208088794, 15639267143578516315, 5207168854484713319, 15549927463564155687, 16813194272724195518, 3203632921993014264, 2659632200539494052, 3200887485387849503, 3016394023706511246, 1685176993209004988, 4998042426381070680, 12308396269304618142, 10440905572279671571, 7289258316425236560, 11420492019403843671, 3435739014286885023, 1183580578914549974, 12391022286588593670, 14444662377984361207, 3027667768274959200, 10234843522693820701, 8137024801098838373, 2175956518454571415, 6512856431774372320, 17425077298837902611, 15619030842709663170, 4328733858250197414, 17049066271793844563, 16740818455336098686, 12803231563237450023, 14343207585545120929, 40565370554270873, 12269808301108907911, 14237854148444748363, 10889535537041659002, 5359832735901121412, 2280455121926342381, 3698460136651532460, 15500853660111634993, 4832455315374609219, 11551934315514307960, 15059280723596882650, 11460904528728722381, 9970203721365112078, 13412504833312966786, 2206569743519066169, 9674034118822376378, 1759760896325455600, 10687307483631403928, 132216754299839087, 15289917908856362717, 1309517963883189412, 18384862652234479475, 14945947123806962003, 6882615358601571684, 16513199887693192411, 17124752213270846694, 7283515403266723292, 12670977044098443396, 14485430674802409203, 1442934611356195090, 2021608864368655648, 10147644583900548957, 7371857896328825503, 2026947477675445350, 16313500187754293138, 8719670043093194236, 9933635014681005842, 822035763478980397, 2335471145280263358, 6109201632743197420, 6557042951458164883, 18289983318532010507, 9986031355445219324, 15882873198924587879, 1098360009929048631, 7417842524061545043, 11644845667626684475, 12942727688395215899, 581290207332301664, 8125070223816106784, 11423720844597916472, 10762562165784879144, 18174238106661068956, 9781731830317872009, 14559997564850144831, 15072792132406040717, 6428710680341821974, 8638270714640158948, 4747635406887618639, 8166831520970770757, 16942363651143481863, 79838347512847759, 6797482772873510007, 8323313311501674325, 17315123295476467077, 17834823603692454763, 10308328726247533052, 12030775355448257403, 2824788998758389510, 14109078089313897312, 11641130520145898166, 5636888963936541037, 18167395440091628041, 13372321523258588071, 4953410089393985196, 16105978672566938901, 10601583498278860290, 422348575551778984, 15238612832267589376, 1558937784171631375, 4331786449779679969, 15337418327813603463, 3313623259710416722, 17208498059429816255, 11251165400370815573, 17196498271703547709, 4097082694964734509, 7556946433095242856, 6347844528857916723, 4396355829072866852, 15635886121326888262, 7946520529777546618, 17096795895172408901, 9111548767024605867, 16907865654057151888, 5359925595440508025, 14237051989030130933, 17920964492648856901, 9862823344875030309, 7831769621036765714, 15021371912684571004, 13219589878808411721, 3953374146380746931, 12281692872760829769, 17693057212120612558, 5241268511066516428, 4584240683173043100, 11307963236856502036, 7464986033622734170, 11524680505188643482, 17257089978727055496, 18059877653952752717, 15575226900606154880, 3221287664925276003, 12861272282032425661, 17679280856858968683, 3805991681496902676, 11826697782075950609, 11798316213508884820, 7256245301505607009, 1942097151423080080, 16676392041435466123, 3541826565176409368, 13666275375614477812, 13646853539556393482, 12122709830935888872, 5785269903265304048, 5868625090434118091, 3864460472305508684, 8895862569614586345, 12252663534383898572, 10626162454630951434, 7883969995276923964, 17478887037876608342, 6525728841689878159, 17336841599087317704, 11085223335146350423, 1222123164560134901, 5595334910355692295, 7363771988069998591, 9010542397617207628, 8434654566307931545, 11206543728876967867, 15587365405946669727, 2320942588082952209, 15311261788951755580, 2614614644094425585, 16217798751029591830, 10309196366595871818, 14539656466339188474, 10003084092804057729, 17222779654871765458, 7744845468535171480, 771418309849778572, 11853058894145105205, 7897815886550766898, 5556587033994696457, 5714513807268881046, 17023601577918379389, 7803604781873663765, 9673291697515318071, 751122971760046241, 12388950643138021462, 6504250773221959796, 2900483328540996047, 16094938562348725597, 13572318981601654924, 776133591684824066, 17428665954631228492, 8871325163368356380, 6583256885218221021, 1423625032359763948, 8622740667699315995, 15406519135004097712, 9334369631470070512, 561254366250448269, 2451227769609519941, 8184551011516832687, 14941775554735050609, 2759039806353480037, 11925431361731619347, 10618650992098344834, 5791425757755968063, 11660536948841586794, 2857507999616493872, 5825182218810570134, 17584369622325436663, 794055755026372106, 12883797727322545150, 18063953891303933291, 1790841919243736465, 5922286747060715395, 13635166140759297450, 12934485298710265323, 11510394440285739488, 12653058381697761786, 3520206312932507527, 4915681338581827651, 14909516590488540050, 8456908206610978485, 2644237539946939762, 6968908545546543585, 17353040957162817288, 228004544586749645, 13386917106721017370, 2184106151122208429, 16467989441911105753, 10601823028219711509, 18167950260390545512, 8277286857156019519, 13563912571686595957, 15582544648763444728, 9860615950719022688, 3933595180193208944, 12737069340933819752, 2548892651686437285, 3303413609438162579, 17777198402933062639, 5612657840907832552, 10097325046301879419, 13502797453096229412, 16293091837583275620, 10149785319153721053, 10917494345308567085, 8633251221833283482, 15738850746404276595, 6752312563210507217, 7135284369428244819, 13321936134618682416, 11186187484044006385, 15467255718596759448, 4015680278938498487, 8912017791951568885, 17369296825929516384, 11139067090598960686, 13891662388974658401, 3024082309075874431, 10424315222954594810, 14513618925484751860, 7276364549692054193, 11034452333610388814, 9789225329773407471, 12095760644845543832, 3633636993638476391, 15639450070030165345, 14131121496387047030, 1997628424286182611, 4886205421027198894, 2281507686083878983, 14449854216333401840, 11502216356832663403, 13217816854604559250, 13361208817170243759, 3141182044294776671, 943014545321951171, 9633879085127205937, 16989828445793452648, 11835207147831430092, 7872611687915144993, 4049881848896294199, 3290792016280792924, 16059058124944821524, 18117071023279943008, 2165714551511825906, 4833662604885929274, 10526578162287941048, 13206778162496184746, 3896743010069301483, 16460014844475236489, 15154725474972641298, 14345270766528744663, 17402402453289603334, 3288718495566280780, 8993733837232386155, 3833085535083527294, 7847978509748787883, 7972924047649057079, 12473398711254555491, 15731808600224711384, 3182304439100627450, 2222507844556822292, 12748274553933993123, 3732391409121408330, 5896704990342262438, 10476090783680276673, 7391366085325406250, 9360823097004384536, 1522113286895808467, 12026598040119338948, 12893282189675353714, 1548700654335322520, 11308375302858097618, 6607303211456996260, 12621767746489750095, 16790296314382286229, 4205006354245204458, 6862768412190121175, 6199274374008955620, 6149173056349597341, 4671022687150055483, 2339406038313386086, 2580712663495884399, 5155064204644202167, 10701280261854167679, 2003705784272479623, 891800345438178258, 2015157615957402424, 14734603996366190682, 2500055061464995368, 7565076598722386219, 797833630650518729, 8246811997609042702, 307274411518370206, 15392638891124529583, 8133595059008797235, 2133482744567035368, 6768583867520736798, 13870757981396451531, 3905284165590317986, 3725077298590384134, 11913658005747634296, 16413425521993511734, 16928435840770689079, 15158417916852732700, 15078403577663587115, 3604841662928070482, 8779579673678636779, 1844972348783550177, 1955688372597214830, 10648724934575366934, 7678993761009537627, 6073617291696587360, 3615200825975967408, 16371640817143729595, 16928482556305122249, 12990694152278275704, 5640259820302602755, 4989122819964029214, 7590422812313190613, 15721317340593136631, 14456366058538546421, 6859291583171100475, 17730064557195549303, 12219353466802479223, 11213809090707058129, 6321450736904845757, 16151341499792188358, 4253083896566756937, 1178914272955904563, 13890560466563563173, 17998034639207894616, 15698739872825380840, 7704370348197248021, 14688093845995269729, 10994178222689427725, 15202615776454662278, 2397376818002250319, 16152831963735085706, 1343705646975602069, 9971858951327064782, 13758691325336329519, 17302762426880499898, 8807701590488219892, 6199420116262704967, 9664416484578619747, 10236591429744542118, 4423424052098369685, 17610466725009345131, 18294628161039087585, 16968894997210109518, 10551385103597485203, 9947281806024743977, 14758108212921747826, 10549325689211416175, 6587235771698546584, 14966278167349758870, 5528693664081443227, 11949914318271519709, 8016488460872121417, 2207215439863076393, 8975573544109811696, 684661245008108269, 9509929980012046821, 3032917475263357561, 2266490715697348333, 8183312483725612477, 240525392577752196, 15478661834874363472, 3470245043229935761, 2464525278395619404, 11110278275554344534, 4908085575640720862, 15064778674958610402, 4828835356862930951, 6202584064584953358, 10295563005485174947, 3163276082607976067, 14049639598239105180, 3650233217585203620, 12608886534768827942, 3981905877343315598, 39468275061822561, 17591426002006430904, 7594517119640797959, 14880567798374375908, 4017486827885574448, 13737692776882788427, 6158794355989980812, 383745276846808810, 5108235151843952780, 6581178451981594031, 11451128845105388295, 698564733531409693, 13590491791704146886, 10352604600393091731, 6213449185937997650, 4348280587322608966, 959194844934412287, 15484062908308664344, 7387861422874591620, 17667235454770559565, 2440272288352768767, 15313076085483229881, 4394939461270873554, 1628152315473173420, 1415402097762366967, 15346329547611571068, 11311158606059373217, 2366068387763653832, 15827874528350068510, 13478669408398828575, 5936593674063517567, 10584447941392540523, 1317442477979981269, 8979238841918884811, 5240407513739116940, 12227540356097433044, 11331718208669401235, 11393510971894295226, 478480586582623369, 2028112196418916108, 16944217440280198338, 9814942465102597148, 3183401114378360681, 7794238633501499150, 6535042020255030123, 16258670974723154594, 2212968344770363453, 5719260649695922910, 4606011453115746425, 18085523271336811794, 17023461305362306011, 4247443272385203825, 6453251596576818368, 18153292782216062723, 5969466175493841801, 6321027330911253733, 10620114383079958080, 11515725563710830976, 4682443894174103379, 9005330096592740147, 11358291404660090303, 15135083403206933818, 6370715174201910549, 6105822410739604100, 8316207692961349510, 8259189295390750903, 2909742184369137309, 931815393357021144, 3709546617072645818, 1586929876111184413, 3725106404003481751, 17989670899755090663, 16491755486151566843, 18235557335072238517, 16819814180993789265, 3041428806510990731, 6865566553245145098, 5559130936912499682, 7868492591048735877, 516631801965947304, 12161391763229603010, 2099765767202237253, 11018187982047213443, 1806434721568654790, 14516670445144859820, 14996026277919828161, 1979400560260923097, 530899540924426437, 1544520666424388930, 12533232064152026916, 10636267691556545099, 11484747390613915689, 11975226862445058044, 18241416109577265729, 17650249201626190339, 5761319483108090030, 9726766041568799984, 18315404984942763135, 17485602863250344984, 7542671955399167106, 14167359599732935525, 14822899150603891301, 11294686994492532553, 4045981924741516243, 6288727179049989333, 6271716940971079785, 5997800943644820668, 12705895494256190348, 18325566440733423026, 15268015809894548522, 13529897842266058970, 18331490128621572171, 10350274989230142044, 7235025897971980354, 16944603767727061155, 17046851593613065508, 16086819789503268069, 2290872333130971056, 11984271223439423839, 1968822742298832180, 9083741104320807061, 3490731051051179842, 6072547544689161806, 40892107681695834, 8194227897552725559, 2721703120818905136, 9182734210123626257, 10113312346515496162, 1627809854903310227, 4186406494017506284, 10256817089933617761, 2890871166679209745, 9992704421054257501, 13713795077083289625, 3497800266051164878, 577588120720483057, 7743155312369684850, 647582273058879352, 11847425330561165923, 7451614373862558947, 787695141116308299, 7020373641750093706, 18434370843004147346, 16766305512676347566, 11415044418032097316, 482952101064757562, 18365897665965731898, 6881852757206457367, 13295203415856753793, 4499519949012683341, 17639942290890472204, 2755065488659651945, 9099541245887106039, 8663706628944419889, 17311177494160805304, 3306401809449207660, 2992016527983769757, 6087225719072057672, 6533774652927754545, 18039943409631383264, 1540245282770191318, 15277302707208554957, 17334457161902221476, 10845441929461561460, 11846394699980441664, 9115621611590602269, 2922854986832564065, 17451398518651662455, 1624359634333743178, 14135939137800853431, 5650014301091287122, 1008856784246308033, 16575426331385040544, 11769760111485998379, 18047362944033116891, 4430274753462093265, 10745539796374847916, 10143880086904985637, 11789608990060323996, 9802343997665591732, 5669534112895101423, 16251907517385954967, 6261903170633780259, 8303151037984901826, 13675205335362018011, 4667052050829987784, 5394729392207077204, 3621809308351225757, 17881301996012426281, 18399425005085138360, 11784479206713797182, 10851557031496270555, 18242614516595162924, 3073485463193110742, 13919662806477670818, 15467987962430305736, 17976204998667974976, 8621215111631964342, 7126454543525487791, 12434044822613840789, 17437950370500401683, 8791748056601765148, 7578617491717957648, 17385069130528753926, 9612850688404007777, 8114351499558902046, 2647542888905057502, 4835591961742843525, 5890936468602936453, 13302065294648475030, 14976820931424228464, 3279343125067124808, 10626838744682430018, 12709395681192284704, 7430874177645136330, 18115853546653664013, 371015040294693882, 15943602063165443616, 14943822821811562326, 7804830422267751664, 14895692916762302315, 12698274826067610241, 4758182647740913674, 4888906871671527431, 1572622354970534142, 9250392132777844371, 12615538942854370319, 6020495506206849796, 13058788715426468132, 14422825795723441575, 3943209974410467764, 12768876895569234627, 10635363936797354481, ], ); } } #[test] #[should_panic] fn limbs_invert_newton_approx_fail_1() { limbs_invert_newton_approx(&mut [10; 6], &[1, 2, 3, 4, 5], &mut [10; 10]); } #[test] #[should_panic] fn limbs_invert_newton_approx_fail_2() { limbs_invert_newton_approx(&mut [10; 6], &[1, 2, 3, 4, 0x80000000], &mut [10; 8]); } #[test] #[should_panic] fn limbs_invert_newton_approx_fail_3() { limbs_invert_newton_approx(&mut [10; 6], &[1, 2, 3, 0x80000000], &mut [10; 10]); } #[test] #[should_panic] fn limbs_invert_newton_approx_fail_4() { limbs_invert_newton_approx(&mut [10; 4], &[1, 2, 3, 4, 0x80000000], &mut [10; 10]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_invert_approx() { let test = |is_in: &[Limb], ds: &[Limb], result_definitely_exact, is_out: &[Limb]| { let mut is = is_in.to_vec(); let mut scratch = vec![0; is_in.len() << 1]; assert_eq!( limbs_invert_approx(&mut is, ds, &mut scratch), result_definitely_exact, ); assert_eq!(is, is_out); verify_limbs_invert_approx(is_in, ds, result_definitely_exact, &is); }; // - ds.len() < INV_NEWTON_THRESHOLD test(&[10; 3], &[0x80000000], true, &[u32::MAX, 10, 10]); // - ds.len() >= INV_NEWTON_THRESHOLD let mut ds = vec![123; 175]; ds.push(0x80000000); test( &[10; 176], &ds, false, &[ 2468656776, 458964117, 2715468315, 1790012879, 3522999749, 4214715874, 561506786, 3302400720, 534918344, 1263272887, 3075782921, 2067555491, 746647830, 518406956, 2268770356, 199166681, 585200343, 2568074090, 496918528, 707408551, 2864167181, 2697486675, 365965986, 566676423, 4243405542, 2529073250, 1738952834, 695156794, 4116132056, 240876219, 2603129425, 2192004736, 1342688443, 2964614325, 4249182840, 2414593720, 2593965601, 2916418334, 2637652497, 994042154, 3834346320, 2159029599, 988365118, 3644217481, 1407533479, 654358021, 2493606292, 4023096448, 1141066521, 983459780, 3892764635, 2438657556, 46466645, 374378413, 979049107, 3284790741, 3990074329, 928205488, 3007997859, 3046358137, 2915845116, 628001258, 3465083935, 4236663285, 474535350, 2027435145, 3567992797, 4283770508, 2324985479, 376140225, 777742614, 1991983228, 354120270, 1512293869, 1872844204, 2864777182, 1662657829, 3120313116, 1367744326, 3903740266, 1092780358, 4056570813, 2945196325, 187533600, 931587688, 2394937291, 1507441207, 345576625, 1601524905, 476504330, 1269949561, 3390313417, 881580197, 1002436463, 2217811800, 685849999, 185823896, 1272490189, 3967659522, 3205992619, 2860215323, 3472978514, 1224636072, 305126296, 1759643037, 3515215216, 4075133951, 1224421257, 774076486, 3594767960, 1443121990, 2854565002, 2031006704, 3471036315, 2258092726, 3015513815, 1591867662, 2298829418, 2586837892, 4173923545, 3288784297, 1655027454, 674268161, 118227690, 4135574019, 3420877922, 3419101194, 2933141174, 801148518, 2138817011, 4265486539, 2610068278, 3432736337, 4263393041, 3163494866, 1217674034, 638081175, 1411840480, 38063796, 989590891, 457807629, 1412034828, 1103809621, 2233526783, 1436248111, 1917272861, 1485988800, 1517198661, 126869, 2315908856, 3274287261, 3670331343, 473008784, 1471036169, 231026838, 3870905408, 2284494418, 3904415704, 3550806025, 1919076393, 1355185851, 1830925510, 1032027683, 3523514211, 219638593, 1697572843, 1874144044, 3230672849, 2851366658, 4206129317, 4265556027, 241571, 120540, 4294966804, 4294966803, u32::MAX, ], ); } #[test] #[should_panic] fn limbs_invert_approx_fail_1() { limbs_invert_approx(&mut [10; 3], &[1], &mut [10, 10]); } #[test] #[should_panic] fn limbs_invert_approx_fail_2() { limbs_invert_approx(&mut [10; 3], &[1, 0x80000000], &mut [10; 3]); } #[test] #[should_panic] fn limbs_invert_approx_fail_3() { limbs_invert_approx(&mut [10; 3], &[], &mut [10; 3]); } #[test] #[should_panic] fn limbs_invert_approx_fail_4() { limbs_invert_approx(&mut [10; 1], &[1, 0x80000000], &mut [10; 4]); } fn verify_limbs_div_mod_2( qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest: bool, qs_out: &[Limb], rs_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let d_len = ds.len(); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns.len() - d_len; let mut qs = qs_out[..base_q_len].to_vec(); if q_highest { qs.push(1); } let q = Natural::from_owned_limbs_asc(qs); let r = Natural::from_limbs_asc(&rs_out[..d_len]); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); assert_eq!(&rs_in[d_len..], &rs_out[d_len..]); assert!(r < d); assert_eq!(q * d + r, n); } #[test] fn test_limbs_div_mod_barrett() { let test = |qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], q_highest, qs_out: &[Limb], rs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut rs = rs_in.to_vec(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; assert_eq!( limbs_div_mod_barrett(&mut qs, &mut rs, ns, ds, &mut scratch), q_highest, ); assert_eq!(qs, qs_out); assert_eq!(rs, rs_out); verify_limbs_div_mod_2(qs_in, rs_in, ns, ds, q_highest, &qs, &rs); }; #[cfg(feature = "32_bit_limbs")] { // - q_len + MU_DIV_QR_SKEW_THRESHOLD >= d_len // - d_len != i_len in limbs_div_mod_barrett_helper // - !limbs_add_limb_to_out(scratch, &ds[d_len - i_len_plus_1..], 1) in // limbs_div_mod_barrett_helper // - !highest_q in limbs_div_mod_barrett_preinverted // - i_len == chunk_len in limbs_div_mod_barrett_preinverted // - i_len < MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_div_mod_barrett_preinverted // - n > 0 in limbs_div_mod_barrett_preinverted // - limbs_cmp_same_length(ns_hi, ds) >= Equal in limbs_div_mod_barrett_preinverted test( &[10, 10], &[10, 10, 10], &[1, 2, 3], &[1, 0x80000000], false, &[6, 10], &[0xfffffffb, 1, 10], ); // - highest_q in limbs_div_mod_barrett_preinverted // - i_len >= MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD in limbs_div_mod_barrett_preinverted // - d_len_plus_i_len > scratch_len in limbs_div_barrett_large_product // - i_len != chunk_len in limbs_div_mod_barrett_preinverted // - limbs_cmp_same_length(ns_hi, ds) == Less in limbs_div_mod_barrett_preinverted test( &[ 3347432287, 667250836, 2974407817, 429996943, 2750501459, 981155607, 2784121354, 3415523349, 1074478768, 1820977205, 231390348, 1372589414, 2069009514, 2430571486, 1857553253, 1536218533, 3666738280, 3477095993, 1509486443, 3092180985, 1588218081, 2448257324, 672729993, 2374023188, 2913701567, 2541072953, 762935357, 1333399576, 2676378567, 2962748936, 744662462, 1379794240, 2290146289, 4080012384, 2739115667, 701035190, 4208500661, 2190862255, 3061320303, 3853993751, 2324138270, 2878407932, 3552024846, 3816909905, 3815506441, 1255343574, 1901570312, 91219029, 1399539132, 3118241152, 3325617992, 2881339798, 2520199899, 3667594206, 1853889834, 866669545, 4104229459, 2070282300, 1484152931, 3098893530, 358952500, 2164190448, 4138312509, 727032566, 2750086730, 3119399990, 1390731909, ], &[ 1037101017, 1727794380, 1490452070, 1098486148, 4011045557, 2946764072, 697788893, 2534857680, 3261736561, 2991036431, 3203952375, 678147993, 1718071908, 1324397528, 3227412704, 2808109049, 2498489092, 1483895999, 1974627636, 774482390, 1844543122, 3947438938, 1357670917, 3021715202, 2044056785, 26339702, 2002972036, 2442219903, 3581261805, 291932047, 3070844846, 1561991523, 2591235485, 4062653222, 432295028, 3024980126, 3174836607, 1645982854, 968272899, 3101889669, 3996099656, 1637081358, 2998072999, 2235890151, 553838585, 1688691976, 4092350095, 2065416776, 3709647283, 1072755910, 2385936305, 2615766642, 136864038, 757727106, 2199116578, 2066024664, 3784388877, 896467499, 298040025, 315565009, 4174702765, 3225704704, 23210826, 2346706257, 1990744556, 2040289114, 1584842987, 1498510914, 2668413122, 2503096531, 2005961409, 2272795985, 394426800, 2285275525, 2471642108, 2784697818, 1258928804, 151106578, 3449120105, 169880528, 3307735530, 1735274873, 1875100806, 2033402873, 1707359177, 2748179285, 3611534985, 3379681783, 1722155183, 1210860589, 1583939074, 1413313200, 1958033089, 1382323587, 3321046184, 2567768608, 2706224116, 1925292443, 486456966, 33556563, 4003036360, 624876701, 2847313485, 3451353450, 3432337713, 1567344163, 2879538252, 624051431, 1206504435, 3713613381, 1062990555, 498008949, 1798769609, 3937669287, 4147083150, 2479873449, 1454286408, 665997230, 331654711, 1482116196, 2545259161, 1591656626, 904758973, 1600224317, 3734588228, 2386781283, 4212676921, 1479533912, 2157734799, 3588439224, ], &[ 3380102021, 2452922302, 1962966574, 3357220828, 3890634007, 1037328979, 1799391942, 1004666291, 3982464365, 4257152024, 187444313, 3439720141, 1266693503, 724678963, 3437259008, 1572104078, 4039559445, 3285865736, 3569601379, 1308348984, 1718729371, 284719758, 444404442, 4151851178, 2692003849, 1055982587, 4035467383, 3921915216, 3487944745, 1817447325, 1542763265, 3937726417, 2223825009, 1394339428, 1214099970, 4192217805, 3753293552, 3811191236, 706896668, 1075933013, 3658129436, 156288657, 1259909922, 1889374713, 2941065257, 81950085, 649933990, 3336906952, 2183193381, 1175410937, 2580459452, 3904196981, 2723001189, 1789637716, 2009908016, 3170700121, 18873175, 2237687603, 1424198121, 980763182, 1043721413, 1070004656, 3240828354, 1874904174, 1859325685, 914946875, 3171367435, 891888508, 94557928, 2528939804, 1026794028, 412407977, 1504097351, 2321903212, 4049474173, 2376576188, 2102495452, 1976457360, 2692728936, 3130170922, 2123163736, 3537525633, 1557920518, 2628772698, 453031939, 451448604, 2142259, 3310964267, 2745320950, 2734144127, 3699687158, 784837860, 1503636827, 811700689, 582299446, 2429787592, 1210273821, 2702547973, 2699574096, 3370153605, 1236597584, 1088015704, 2939670102, 165924895, 18853284, 3700200624, 3220442711, 2965715000, 1488424876, 3464105223, 217616508, 315230760, 1429465794, 1372241659, 4248780864, 767395681, 4105247821, 1532652179, 2100932260, 2674903482, 484464190, 3609058420, 1471559178, 4122200129, 4198439348, 1623393770, 4254969136, 2270601790, 4239377868, 588832613, 2695326914, 1952240370, 2369526722, 669955508, 1561380904, 1661607015, 491163324, 4063133286, 339180970, 1218080293, 2858927543, 2211268294, 4242441810, 4166777931, 459461625, 2722830085, 1984526624, 2371328931, 3795073119, 313183280, 3291949415, 1843511154, 809173981, 3006056205, 3286577997, 74654418, 3553288229, 2169290280, 151023939, 1586116459, 3040308252, 4142315068, 2646953656, 4225002928, 4051564438, 1032308582, 4166856711, ], &[ 2427812263, 4051563058, 1632406385, 3107965286, 2723923069, 1032718410, 1300669246, 1686783039, 2900234860, 381961320, 3860838802, 3653570244, 1848772343, 2404802446, 17732494, 2990806772, 1910668969, 3421521828, 1829199569, 2997918403, 3557175274, 3519619382, 740250212, 998547797, 140767728, 1892932539, 668118324, 497299250, 937663333, 2612689662, 4010699478, 389960621, 3786256383, 1395295829, 1276717484, 1869006600, 2093853956, 1555847120, 101097965, 231988325, 1792259822, 29327628, 408838665, 3646864419, 2451151869, 3859710466, 2245716151, 2883931737, 1198282734, 2659505911, 354206954, 3482662941, 3212522494, 4106878300, 1901956875, 645864641, 1078147214, 1797412778, 3856838800, 2428567766, 662568175, 698243503, 4146493635, 150220967, 3723014797, 1944885174, 2282033009, 3395489773, 473095209, 3085161317, 2999589203, 3878818308, 1223719023, 352990164, 249223561, 4143029861, 2622703186, 796827870, 1054862138, 677020780, 1289629518, 3449239587, 3541454564, 3311081075, 583050818, 491332673, 1997521794, 627632367, 2864835203, 2880916227, 233376741, 1067584403, 2454677969, 4048829167, 2955413920, 651548741, 1667224967, 659069317, 4019573675, 3305249558, 3965166031, 2657374006, 1899323245, 2478966232, 2865170658, 819362488, 2414458118, 203150817, 3555808793, 3366944226, ], true, &[ 318412713, 166261607, 2009115186, 2592695300, 909481568, 921495628, 1252820069, 2134562168, 1472790817, 1608088310, 689541000, 69370609, 2685209974, 3562066729, 55850493, 1884247907, 2876898529, 3115161272, 2620296992, 3497928383, 4079349604, 2838452936, 3352297661, 3503798900, 2830174901, 2750509727, 1984400813, 797374166, 112488353, 4244342514, 2411618910, 4209213781, 3477038403, 2142115980, 1949259992, 1303854388, 2073509204, 1462419537, 1282719064, 770376429, 874669429, 674943385, 4182481942, 2641210646, 1249878403, 721250586, 3561964927, 4189270923, 2494976587, 1232128515, 2160491104, 2258727309, 3620010609, 252515683, 3388122763, 4155289792, 1020390516, 2070282300, 1484152931, 3098893530, 358952500, 2164190448, 4138312509, 727032566, 2750086730, 3119399990, 1390731909, ], &[ 2882761542, 785407498, 1124133487, 572386909, 1169675686, 3567625455, 4199715839, 3851396630, 3274146684, 3477301663, 3302596192, 1480559142, 100842294, 3530609196, 4086393700, 1190308308, 4263459677, 1142007717, 2247036858, 4120633014, 2294603452, 2399429000, 2624162280, 1454610696, 270143073, 3957844361, 3046891288, 1549007386, 233535161, 3109659080, 209449866, 498073310, 2626910641, 195499996, 3976787267, 3922992490, 349292363, 3307104635, 365992265, 4190381097, 3755383481, 2478897620, 1546723896, 4001998632, 1128630761, 2676599750, 2475921888, 3233603626, 1483504432, 2551193799, 3557144097, 313815765, 1349744193, 1374844288, 2400211342, 2986607421, 3195157472, 1299836347, 1861689827, 742292964, 2823852296, 448143737, 1667945403, 633976860, 2902355589, 2157443145, 243118113, 2840619921, 2919500120, 2742747945, 845926917, 220468159, 1355718767, 2330428847, 3717678284, 1787470596, 2523167223, 2214932965, 2055827539, 27888400, 2211687684, 526284755, 994343204, 904008663, 487598580, 2347713123, 3532282785, 3549720901, 2459046510, 338578128, 1168895967, 3291681132, 3787087696, 1555047248, 894667165, 1085939503, 4100902874, 309142266, 1088553857, 2096128611, 1104848719, 3907470805, 3414980158, 3260046959, 2704772147, 288217831, 1781865616, 179692408, 1428188291, 2562193479, 1062990555, 498008949, 1798769609, 3937669287, 4147083150, 2479873449, 1454286408, 665997230, 331654711, 1482116196, 2545259161, 1591656626, 904758973, 1600224317, 3734588228, 2386781283, 4212676921, 1479533912, 2157734799, 3588439224, ], ); // - r != 0 in limbs_div_mod_barrett_preinverted test( &mut [10, 10], &mut [10, 10], &[0, 0, 0, 1], &[1, 0x80000000], false, &[u32::MAX, 1], &[1, 0x7ffffffe], ); // - d_len == i_len in limbs_div_mod_barrett_helper // - n == 0 in limbs_div_mod_barrett_preinverted test( &mut [10; 3], &mut [10, 10], &[0; 5], &[0, 0x80000000], false, &[0, 0, 0], &[0, 0], ); // - q_len + MU_DIV_QR_SKEW_THRESHOLD < d_len // - !highest_q in limbs_div_mod_barrett_large_helper // - !_limbs_sub_same_length_with_borrow_in_in_place_left(rs_hi, scratch_hi, // limbs_sub_same_length_to_out(rs_lo, ns_lo, scratch_lo)) in // limbs_div_mod_barrett_large_helper test( &mut [10; 125], &mut [10; 405], &[ 2824467771, 3299124311, 2818671068, 3680778570, 981687343, 2406693669, 659467593, 2993414243, 45406089, 1478779191, 1711786852, 1750419133, 2909274013, 511107722, 3561218251, 1136025710, 993075881, 3516743656, 2114794292, 1997914, 3812643652, 2505455342, 1465178283, 1978590884, 2983823507, 1628362808, 1695987706, 2508198478, 518693670, 835288758, 1012607974, 749782274, 577737644, 2333209317, 4167594129, 2270730042, 3116080031, 2989072664, 3700594452, 2080277190, 1740782490, 2022893854, 2980102855, 751636825, 3922671264, 3391149880, 614930929, 120867901, 2567507861, 1524427749, 2580678371, 2199894921, 1776614185, 1166041925, 1079838738, 110556090, 2831653230, 2555307604, 1415160216, 250952335, 1727168666, 4114643415, 3895205129, 692242739, 1888273350, 3407947612, 2500185766, 2392325992, 454908683, 1510488259, 627605677, 2579656597, 503296566, 732883994, 1804534661, 1024632105, 2582676903, 2186193446, 2035546222, 1537608294, 2871563506, 1842379464, 4285710796, 1145782664, 2168389602, 2821015070, 3799000303, 1910989354, 2712163170, 2373188937, 94374379, 745462864, 1273218817, 599427865, 3025428597, 4170147632, 654664457, 999597566, 1301587861, 785951171, 1404519917, 226625774, 114784173, 1303174335, 1991080402, 953508169, 2955695351, 4272100018, 4152229685, 505603829, 1367830508, 275280730, 1743334800, 136640107, 543638242, 2867205034, 3205072197, 122133232, 2907110177, 2577983454, 4044792269, 1426164254, 3391219052, 4077004042, 60445643, 361888880, 1370511290, 4140611, 1545574856, 337863511, 2696753299, 882513095, 2220102704, 4040224968, 3895008884, 3144563393, 2298197836, 2781817257, 1704369652, 3931316078, 315544063, 3497851423, 3664143565, 952326443, 3938628137, 2331019960, ], &[ 3222658839, 1719980949, 49002116, 576454969, 2480526346, 4090562449, 3826526799, 1957153338, 2225171960, 2687643162, 708981609, 3176715792, 2962973059, 2652817195, 1197341180, 2939993186, 3554367730, 1570613844, 2536409086, 499280456, 3247067732, 1595825640, 2368929206, 663346056, 3132360609, 1474802683, 2339072148, 2202454503, 3728785029, 3203437738, 904057293, 3413710811, 2642403758, 3344563036, 4027597111, 1888090288, 1863907782, 2464957062, 2688706102, 569142547, 397802070, 245946780, 3489512252, 2617239243, 779718731, 179625066, 4023449096, 3996006819, 953561942, 1127504598, 1992436862, 3073123794, 1835220635, 3142367806, 3159289192, 1927251431, 2830198394, 910503635, 2897643083, 2932878381, 1507827586, 3067247947, 885528755, 2017570727, 3134837176, 499511463, 1535166690, 1643153113, 2968177930, 3952804609, 3989699184, 256167900, 567717900, 3896800262, 2310644620, 2351013373, 1964719080, 1905779649, 3311747907, 1340733718, 2870734940, 3144732377, 1107086597, 3017452910, 32224803, 2995638379, 1782145516, 3064028223, 405412838, 4063680301, 3415165225, 1788170832, 3805938672, 1902801261, 2231309030, 1810036873, 3470233158, 2413346472, 3530489706, 110880408, 887205258, 3604865827, 2857625992, 3018122209, 2631997677, 1125977084, 2461114861, 2161802286, 273825728, 2086061888, 541221199, 1806844610, 1376732414, 3802142465, 3535151037, 2954021790, 2116798495, 3735046347, 1186632354, 2833281426, 3457883657, 3962766016, 13814577, 1650009216, 4147309188, 2302630822, 3980940746, 4258997501, ], false, &[ 914514400, 3342502906, 521760868, 1049115929, 3824837806, 2763332026, 79145590, 2361118660, 3694174875, 582606291, 2236610090, 245694427, 1561619352, 186706776, 239856728, 3342500541, 3049919767, 2350706825, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 671156763, 3522970087, 1803674928, 705095332, 2537912304, 2452859779, 3450873050, 2679364048, 3526396093, 4177976105, 266611217, 1151557614, 2132817166, 3877142811, 507210298, 2972523503, 3073806840, 3566048488, 880991998, 3345680417, 3235170656, 2403723979, 1313154315, 2771932402, 1330267204, 3414255915, 1179382708, 3233207082, 2503609750, 249317411, 2632726993, 130324620, 2032071659, 3005726146, 3875282024, 887247870, 1998016163, 4254819443, 3740865454, 3553274754, 2446121384, 3275444724, 233325872, 539446483, 1087952312, 1835245616, 3627109091, 2510529404, 185630261, 3706778570, 3098183261, 1931085512, 798171652, 3040444481, 1161846676, 1038636293, 3421904104, 2901743603, 300733872, 3719079820, 3468813384, 2881344572, 2125343174, 1936937822, 598427076, 1712995528, 4084208860, 3733468538, 1669487237, 1385196430, 4053752992, 3005943092, 2525935674, 282240792, 4279794411, 4125983631, 2329629976, 2704369810, 1464421682, 1313908108, 1226002425, 1808406752, 3275768064, 3175836384, 931684775, 589156533, 3002460872, 2667576199, 1619914000, 3662683434, 3389418364, 772131109, 3768421507, 3396906380, 2736076174, 2900071166, 538472464, 373492649, 1143475222, 591038056, 3736209846, 856338986, 232250025, 3427987228, 159577157, 485970599, 624042727, 2427226926, 758605639, 309500365, 1623348751, 4085018849, 1073894303, 3272403714, 3990448709, 1089031712, 1648217954, 1406121363, 1462876615, 1399073841, 3264088864, 3357032142, 1754184006, 598504776, 2188603491, 1888083714, 2827226198, 3414026126, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - highest_q in limbs_div_mod_barrett_large_helper test( &[10; 115], &[10; 1254], &[ 2401497277, 3741262706, 691871239, 1949640889, 266070694, 3295242537, 3037066187, 3875417448, 1358853731, 4158125741, 737486219, 2625351318, 2205206855, 501024225, 2060376077, 1953521053, 3762056723, 163485007, 769999701, 2385831686, 2388009068, 3120433785, 609866149, 1014929431, 4255522153, 3908104955, 1296186549, 1400337892, 2481196402, 1530226708, 1736756203, 4267671814, 3181376526, 4204274026, 2772982826, 171341955, 3239339748, 83269891, 2325049318, 746305994, 1290717192, 1805639230, 1856363646, 3445599715, 1388597950, 2699498310, 246990054, 1396771726, 265087723, 3372840761, 3260397695, 2010115470, 2211074582, 1883962263, 256363687, 4012920099, 2367091978, 1485341992, 1836339208, 1434180757, 2616877872, 1145425491, 1261399773, 3926766027, 3115015865, 1741783714, 3802513218, 4081750672, 3856503286, 2137512595, 1192985123, 1863041957, 700637154, 2503934926, 2021744810, 157763047, 453501781, 1898727251, 3741166728, 105996483, 3390681922, 1127471458, 4229032301, 254843851, 2729237155, 1707011850, 1756734415, 1864969309, 96539023, 220456923, 3061776324, 1741151628, 1199010536, 2099212259, 3095715999, 1369052975, 2575251120, 1821995904, 4169452262, 3299830336, 666854626, 3647011057, 3965571435, 1551218489, 726151433, 1730753749, 750433250, 2084548637, 475638490, 3209308986, 1536371286, 3458731894, 451976715, 1463077982, 3275775647, 1176722184, 946473888, 295088963, 1154092407, 103838303, 3743650178, 4149308777, 1617840168, 3465913339, 4133656500, 186966677, 1624567957, 3264214229, 1285455678, 3951367256, 1685500601, 2890483019, 3692192743, 503129144, 3972113270, 2472468030, 3386552094, 520995657, 318761291, 3652507947, 876136924, 451086694, 2855321222, 557040372, 805677163, 2526778273, 2320694361, 1256424719, 1952008095, 4056766614, 4133706458, 3948099450, 343436346, 4192911370, 284826582, 674589589, 2186532130, 3868256489, 3551620239, 3301954255, 1174676675, 603478538, 275555563, 2405977791, 1847784099, 896249737, 2255526478, 1787445221, 239988612, 1297053793, 4022115314, 3399153034, 1717528213, 1660404772, 3074772866, 2806710693, 1643510791, 3184377187, 1540838982, 134943412, 4022881239, 1840380980, 3861497294, 2510066751, 1433230269, 2045075002, 2415627101, 1223566402, 3367143819, 612631145, 1154322627, 3247079704, 1778868389, 272795417, 933297265, 3458460741, 1389431679, 2907745644, 2086192882, 2684128325, 2650239535, 1784197442, 3949401651, 1783533373, 4288056634, 888203755, 437001866, 1407050668, 3135687315, 3463879635, 1702062054, 1204976730, 4177166610, 739673691, 2277342971, 3478834440, 4081300483, 914246861, 2121339885, 1961961557, 92095006, 2260302382, 2461228008, 3993959318, 2950464602, 1950783601, 1224172324, 2576903297, 576707684, 4125788986, 2560012161, 1956729376, 1629575657, 4036954933, 300086502, 4022406600, 3237472700, 1646970397, 2062807673, 1759249491, 1956866526, 2025198625, 1297980907, 2709447351, 3977405586, 3105592010, 4167079730, 2234262082, 3282437095, 3492171389, ], &[ 414354569, 1366704839, 3104154714, 3052961192, 1917209478, 527538773, 96279538, 131392026, 2197344782, 2544900655, 3721689046, 1511768113, 2703760155, 1445726112, 1858496576, 1575565932, 3793123807, 1385830602, 411844037, 2236175811, 573323765, 2565409615, 2461667516, 3785284514, 4260465727, 3052818977, 1895970970, 3792821387, 4109605593, 1615504561, 3239716852, 1706559703, 3187779838, 3278892149, 3231274931, 4198044737, 1513165468, 245082668, 1270047387, 3396787938, 1940745611, 3740768753, 2072323188, 285189880, 644016853, 3495689253, 1168360917, 2400702434, 984958722, 222994595, 3006232190, 2064852513, 2152929014, 1163603446, 3191172136, 1835493220, 3277922296, 3636603619, 1531000264, 3057499684, 3823394467, 2647235938, 1717867123, 499456838, 4094707383, 2454454468, 3671059285, 3201191048, 2439390676, 3022007460, 4061878398, 4243531226, 3389689292, 558186288, 3777835601, 3123712634, 3503180938, 3691679764, 1701324443, 835309072, 3906212426, 4049064285, 1768153688, 2228746280, 3594304220, 2961136397, 213262897, 80889120, 4109164941, 1704207190, 149603550, 4140450876, 835389387, 2885880052, 439529491, 1516869648, 2050960198, 926155485, 475035022, 1187115633, 894340078, 343754206, 3955497730, 1344991704, 598758584, 4056958135, 2153619389, 2541228501, 3084209032, 689848357, 1722405264, 3359713626, 1572612273, 740065643, 1582253391, 4070651569, 1908850964, 495396647, 4057999777, 3077955309, 4157175191, 2258556901, 2113839, 3880102604, 2790333280, 2943303426, 3912791781, 4284145483, 1840413180, 3097912758, 1064553745, 1126983800, 2256085399, 2448922218, 981100464, 266358012, 1971087790, 1988527723, 237308225, 1936681335, 4258331432, 1348277821, 529864588, 2497818319, 4244738664, 564460927, 1832999941, 65438986, 1185234412, 1316363591, 1608606945, 1000964619, 1732529786, 527797972, 150140396, 2156815817, 4220448391, 1051855867, 4280728484, 1058663428, 4250194724, 1036504424, 3657621656, 189944192, 57605355, 3072751931, 752978294, 1461890065, 2724185615, 141061473, 1466705961, 304569847, 2188875717, 617186800, 3058558545, 1591798676, 88078245, 623288082, 132838333, 1534710499, 2200810995, 2857112538, 3863089059, 3060974440, 16773497, 1918012630, 3327340967, 3661341852, 2395761457, 1535964139, 746843178, 4060399981, 4287382590, 1336021602, 1599090737, 1174816250, 481099617, 918021470, 1173582832, 1368734491, 888221269, 510154884, 1262941262, 2567813829, 1077623012, 2261930141, 2307570205, 2069365574, 3586190102, 1698424580, 615530592, 4037104804, 1283475105, 4214495193, 3288288012, 3585802470, 261207221, 3506861813, 1536248070, 3151134123, 645179327, 490399820, 2479385864, 3709733877, 396138285, 2627168580, 4028642442, 2012757271, 1884810033, 4051927252, 2652348818, 2069059332, 2416554871, 28369250, 1321756354, 3314148643, 2588326180, 3141604522, 1974534297, 4170320959, 2683069809, 1278314467, 312763173, 1481522722, 2846196729, ], true, &[ 2089919886, 3662797229, 1688302765, 1220493490, 974788570, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 3521949631, 142488398, 2558755806, 546733190, 2792635139, 1330279357, 3430917364, 206259042, 1647608238, 3662226174, 2677354502, 501681320, 3339919968, 736768019, 4258570929, 4202792087, 1651152858, 415339868, 1437647081, 1371825040, 1535867295, 1113678172, 4268196599, 2619516870, 4117420686, 2491883937, 1711537149, 3681498741, 487272454, 3249094136, 2833249206, 1984417080, 608254353, 2280645468, 3395986408, 3532393236, 285299266, 249977069, 1222542802, 1102282847, 2598354195, 439643199, 2126654464, 607909799, 2936741523, 3763227596, 4235714917, 1698786602, 1862433691, 2965568505, 2196568398, 3068583313, 2467355500, 2575639252, 3699104542, 1440347634, 2202871610, 1085633678, 2985993155, 1566387171, 2653399887, 3340197769, 2614511546, 565555655, 4058797643, 1841325854, 671657716, 560998985, 334170781, 85067287, 1935383603, 3452109092, 3454188157, 154367468, 3636444053, 3436201211, 2489786062, 1247734460, 4255062573, 1485745449, 2725636745, 3754874076, 4135899179, 2423709040, 392644331, 2072210265, 339068725, 3933463273, 4288485419, 4212008073, 3733609991, 4120877958, 1466616375, 2958829060, 83050688, 4089523843, 2719660596, 3345635470, 4218331277, 176804352, 2942885054, 1103429906, 1232548981, 3336211973, 2320933704, 2354076844, 2529582693, 3959342251, 1769056129, 3021361560, 1001511651, 766365010, 303546733, 2838329868, 696771802, 2198903959, 3831700812, 4192525926, 2867372730, 3200189248, 2637281548, 3606733360, 2672897488, 2624221199, 1766256987, 3059086417, 3482969658, 2697305862, 415920845, 1575345078, 931452186, 2064246173, 3556532318, 1127897667, 4176776745, 1103206019, 759429637, 3840446634, 2669415208, 4098858695, 3968696636, 474286523, 3603742455, 3683233930, 3910949095, 1016216353, 1693878242, 2936976170, 2258461087, 1543964790, 1257134506, 2705742284, 619723369, 2313052342, 1916338183, 3578695856, 2388468521, 1417556272, 2630850792, 2327790132, 3594026023, 1659979016, 477242076, 1948563308, 2803059042, 2392360966, 2007275313, 272222339, 264018609, 1147760126, 4131679216, 833601075, 1429546506, 3426172207, 1125974375, 3584187622, 1582857679, 1084294484, 2193982331, 3084073169, 892928835, 2823566821, 3544239939, 172135078, 2430777811, 1620416268, 1792703584, 2899867927, 3974701277, 1890638601, 3367278100, 4278027820, 3171315428, 3696212814, 1038269559, 2729624661, 173005716, 3652244541, 724827867, 3530325019, 2203073321, 2587791340, 1909841295, 1412031121, 1429200221, 3614105795, 3265396657, 1362525000, 1906071103, 1060149404, 2733619757, 2675449568, 3414488370, 210765135, 2800530139, 3014478492, 3230858260, 3409460781, 3411785589, 2543986390, 3934724152, 3235965806, 2053739672, 4085596199, 1563589410, 2817526968, 4048637993, 3055675422, 2173262993, 2970495556, 514198452, 1591956633, 3852865086, 124440700, 1002712372, 596340824, 3999538417, 117476573, 2037586050, 3291573274, 1511567035, 1614566437, 3821078763, 961133253, 2796121934, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - limbs_div_mod_barrett_helper, limbs_add_limb_to_out test( &[10; 9], &[10; 167], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 33554431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 67108863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294965248, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967294, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[0, 0, 0, 4294965248, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 10], &[ u32::MAX, u32::MAX, u32::MAX, 4294965247, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33554432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 255, 0, 0, 0, 3758096384, 67108863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 10, ], ); // - limbs_div_mod_barrett_large_helper, limbs_sub_same_length_with_borrow_in_in_place_left test( &[10; 2], &[10; 452], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, 1023, 0, 0, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 134217727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1048575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190080, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483648, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294959104, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 33554431, 0, 0, 0, 4026531840, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2097151, 4278190080, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], false, &[u32::MAX, 10], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2145386496, 2147483647, 1024, 0, 0, 4294963200, u32::MAX, u32::MAX, 16383, 4294950912, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4292870143, 2097151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134217728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 4294967280, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294959103, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294959103, 8191, 0, 0, 0, 0, 33554432, 4261412864, u32::MAX, u32::MAX, 4026531839, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1048576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190080, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2097152, 4276092928, 16777215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966272, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 10, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 9467139676469209549, 590281264913108801, 2444597864339828042, 14864081623018167053, 17247631583397892818, 14553244820490552393, 12829855212365838534, 3531466761266135925, 11372171159031384620, 5870847048926628622, 9193240591510160396, 4025304033900694645, 17261252553070218810, 1960954339685170046, 9689788042403522315, 6777781555383721706, 564338697137211139, 2236230241770389317, 7260612298284603217, 7551831827404764167, 14240930170717885933, 5403113159439788814, 11890192816726889700, 4571074562843162754, 6585174915018781919, 16820621164336832115, 2906428786044704407, 14549789283221663094, 8574533295629171239, 2554371108614275803, 12102140726062325305, 5927759880327312421, 1947106727211751169, 4243634376196439953, 3958901784387088795, 11997496505606868854, 8614259227764305665, 2851316343853334425, 7360014330841540867, 12833167596911644967, 16420023392297553774, 448987443751486030, 1127916262354476550, 998365641524414747, 771182118275428982, 3644906482543632509, 12008471662501141232, 6735530311778854203, 14937996347189247818, 10310266533399488799, 14173112110010990829, 10048196983951682150, 7660343487007291390, 5442254482173747309, 11894682918116055490, 555474340707057713, 5454210195350763050, 6335921756850263208, 11125242160747149811, 5950900297278200050, 4972887779003626968, 15099558014605218082, 8070946285642924813, 5661924633602804698, 4017981546647826153, 3298784914124356106, 1048634509662954303, ], &[ 1601810336850541391, 6414377018375174391, 919960012376992260, 7432535796251013733, 14687204344100976419, 4239980047441451729, 3419961342059496953, 16241811836659790563, 582511433240649668, 246415310737356671, 4213289580820322712, 6570486144808547472, 649071692625916450, 16246395526862594705, 5418002168615819323, 8787804720479728592, 16606257073152622475, 1410262373214068670, 2846556520446018460, 12702224195603835801, 14824788470038136235, 8070823597295684045, 10064047777457825217, 12473928276513608352, 4502242984490214594, 8213242804638977717, 11407293275124988149, 15303970978422100227, 5734015081210218763, 6780255848655226189, 5308681743121306497, 3590094480707706491, 924657275311967241, 13313245703725306506, 13755314570936606477, 1722612846595274627, 11310713460998976321, 17860713973992950196, 4832972642835413575, 6159638888337886550, 16436259186156623772, 8219825892743153908, 12825816757113080127, 17576561025816321316, 16426316569762062979, 7041069634919241163, 14958139263401063299, 8541928253694453091, 14623281385826596559, 5881920493887697974, 2856125878289959548, 13138961086309035424, 1445182795958550281, 989371283719803801, 14414401959190662319, 12694741659414145902, 4944169755440522083, 4850330269090259826, 7263731888738583042, 3847985956261979907, 10886313908655224591, 16884924304355496352, 17434369248195376612, 9624045826924140661, 9440358242723121635, 44413621672380228, 14501853932445164832, 4412509400967439905, 4059150452772511000, 14121559478607349396, 6939247432141568945, 9144772592231287902, 9035665952014395555, 14897716038428818227, 15076823799682351749, 16277606343067785741, 1901372957955104636, 9089098420745572372, 7424125507905187829, 12368330388186365917, 12778631331588513256, 7648700244963873530, 3776028467270636181, 16107369772612157292, 9046543866366629415, 13251838453492673272, 2975138303374961664, 2462966081502544324, 814917744063498594, 13005222969141014201, 5026855542811222762, 2382391535955253463, 5899528506680208740, 13336141787604226636, 2972106516856532181, 14045206722662122716, 13361481863470745757, 1303122885509130861, 2127042842590220699, 6185514996199626930, 16622745329653187578, 1256533115604594696, 11243434057073050028, 9066405370642929758, 4552716624777987017, 1128092841571320177, 3756894170446405064, 3328979948330012406, 15049042231988504879, 3530903968533512703, 17905884378428276079, 3713606437359152813, 9370125751473669209, 10012381228375856292, 6916709082927033810, 17606888822444197359, 10818646898854586102, 9927520028322801489, 17015575684851383261, 15287563104761130407, 4246630569287612899, 6737522138244324583, 16956805675707509108, 10507692348129622148, 1144006384258648355, 4260138925314579646, 14508270375905482517, 3559046762122289814, 15199903498605585717, 16432575538338639756, ], &[ 5592822181652430458, 17506309594623475426, 14050063092843436505, 7714948654849123602, 12960251261153655218, 12293354553127881932, 18236552269356335752, 8116592444680865353, 5788148289215893900, 8971586422059718981, 7830225577778842728, 16542468928391674395, 7685364916096821326, 10621040870461365797, 13017786142160529410, 15623634767986429431, 3570280230795725028, 5462496964935066825, 13096782281304038571, 1028538565298248606, 1306240401949593430, 9752885768751332733, 16834186448734276157, 7637206024963845142, 14347989823115406647, 11694534965309339857, 17506164867360865472, 18226657528377127028, 17113377911080849277, 12836900580850373696, 7624296086468816307, 3241150049341673184, 11432625191496196476, 7201112746916642381, 14159401858377741999, 13042389876849434472, 6539044773109830458, 5626612565019858620, 16855355146181557220, 2896027096805100269, 1749121842377065409, 14486576285464434664, 13003134176160772443, 4520736241988979615, 14386190542886985088, 5203873393963986621, 2767011034432552285, 6993214728799607735, 16219726698174042484, 12883752315794694947, 4638588568194864850, 13671093412063473486, 16507766724668892429, 508640878850638089, 10821378407060575406, 7345992160360704865, 10043908069076742056, 18320857698273010360, 2218460838923946432, 12515547441597943704, 8373193888106171069, 11138535537637434655, 2449630875466873477, 8767699022869197665, 6446940169111329267, 12481583138381941451, 18405856492243480913, 8856983257605794349, 11977198292403090397, 4992072464455161558, 1429124422280954077, 16695629052720642207, 15320583853113777709, 9270873446273846783, 9544568698292818385, 16150036388405871492, 4707553634577955164, 12819651092171657742, 6194167822526464289, 3302239600303656809, 13520149877311082646, 3658928982143500918, 6938149248133961941, 3561482775788486836, 11608588618646326460, 9312042305619109305, 7752033026671842884, 17638989744464665362, 11720586895422616384, 17488161719714908794, 14359533380966089634, 9112047402314539693, 9045007769242360827, 14039981061261051366, 12161985564133395359, 12552005864162233454, 13987473146854769743, 18218863257920884509, 527093394921779615, 10809320813728048297, 9176568449151735783, 16181777654712188911, 3708863559833042684, 15705373009786311560, 12044345266545331965, 15745097802473032619, 3448641903062070968, 7079863925626111888, 10936059842602692227, 3949990826310278419, 8781569794504977516, 2710649351206510739, 8045244454460377457, 16793164706992819994, 14171071447733414359, 6442975288102390424, 13408292761208182437, 18190891873633561623, 14416452326133420106, 11467995109126255854, 10355921853391241663, 3362337025912778005, 12828210017750944427, 6724529289281531448, 17910365619735459537, 18061583666579344364, 7385510916096038449, 14735084634699542626, 2983574817812405387, 1160726944282883582, 2119364765206141036, 6464791768964988391, 8824016806539484116, 8270030586906660422, 15002907845345901548, 5776511587881140498, 8026215921305305807, 4715947225014261487, 1386404302622265399, 155879991043344208, 7029054386547293524, 11220489073691424833, 2733588115435171341, 5063187558440228172, 14208382232307280669, 3376720278729662133, 14690710213721258877, 11094816467682244196, 13929756812886477086, 14698847015580325706, 15992372099283576304, 5818288394714584003, 5038324365106419021, 506432342213631013, 7781480413773762085, 2275557418573742756, 8703301345083257514, 11424227525030059244, 8529590924998378026, 5577211436885609271, 16859602499387351883, 5848360527348246100, 2118117857825986323, 3178709503818913442, 14068618324826971348, 7820101807986528976, 16849757836429474618, ], &[ 10900792384749518304, 1752565570529908396, 3402229115647561238, 2472381872242532960, 15748089475115162936, 1958855681762413475, 12100416912810779188, 12256578057348862042, 6556831077371185734, 15914846823057329492, 17346954154793811255, 17566187606614467459, 1433606366066775495, 9089332045922722756, 10056944581186126460, 5324425019386643029, 5281765195814058625, 1449711238109407238, 5903959110668039125, 3336955200427408551, 751494194154096512, 15350321905800137137, 12407374450431165353, 8705815621686854350, 18038286270431178148, 11671842546699641930, 9343865367071815679, 13401838367914321671, 18365991333043790435, 17428290065100096976, 6040216493892400727, 4224515713015397505, 16578741590625036060, 11835373548777581169, 18413478850867685366, 8453265724386285209, 5394500720474148965, 1927463313122594080, 4177838821929605731, 10680620304882583021, 180005403771618203, 2256408572502279608, 11718426532525535626, 14260315287467647015, 4035759666841010016, 16259497729863184485, 7772704202422133476, 6815813069474359325, 11207378575459431371, 18308033894506293455, 9875145231436590806, 15354934628544213986, 761822562304640527, 7391550101325083295, 4023926600201752832, 922969942182092752, 12110946035817932140, 16574399923422896843, 7087993004495856759, 8299428112066197874, 4589434828506762129, 13978205413565566735, 15675366647238478172, 7819770375827015142, 6823625407675143456, 2042269662440457350, 11521115322912473140, 13703874674141705702, 1295561690992462505, 12464082489717915012, 11378922861990148970, 2076282285705918066, 1390689690731346588, 13670979351308531000, 12980996477862222169, 10496970808504864546, 14015388605987660396, 4171129107047347396, 1656857204469415571, 17492457435753920912, 10132937897450237781, 5065601177732655021, 17498367701449356268, 9552937910825811119, 6213399497134928078, 12865519292113075754, 8548871019474664332, 12973212090641168109, 3018095992673320728, 4102580256148037725, 11411505815957245048, 8044142604358855954, 6163064685377006161, 7676133172626151339, 15177331097378985405, 923128391789363540, 8405355494789853124, 8409013636286216842, 17519952046647436442, 12690425880634822079, 7295927951214020420, 5103171252065286692, 4531269626482776566, 17509133779966482098, 16771567673323510549, 9940518318209913958, 2566490491730418524, 4997841530198583881, 11759671980624847072, 12804335234851198898, ], true, &[ 564820221219774034, 4488711358679422475, 10020082426042197380, 17225157352286806558, 5780768250525361575, 1970180556702143116, 5857604197270789289, 4060596445048742789, 4197799076012455571, 7044577438443748571, 9865458079653433267, 16329626967551115891, 4152461199188161627, 13000775528850398936, 7619420622350160180, 14900279174214956337, 1704825421557733731, 47372161928033978, 3056759021249434255, 16034528189533406528, 6435981853629992716, 7347416955208902363, 7867885339734871956, 16003312811447303393, 11973054691848315139, 4061237791967812067, 2991418391396596002, 4703879799196538602, 7912263594713072930, 10103623638174366026, 10329033596439147117, 17155789472068722424, 811379340807249314, 16011199724895161224, 3304315874218574570, 8105141063347209779, 2750621792338662113, 11379790872842995450, 3804288408313301542, 2401920265819467507, 8046761544384349111, 14485522278750006278, 13468921503494590590, 345391242184932873, 13063364294012052475, 9333826905573469899, 194256409910599419, 14732838482552366259, 1399589143134623506, 3979386708177190104, 8831973874140082077, 17265655065442874316, 12810778560618597071, 3646538182485961898, 10947011750214431344, 709929350993015196, 5828094472112746203, 6335921756850263208, 11125242160747149811, 5950900297278200050, 4972887779003626968, 15099558014605218082, 8070946285642924813, 5661924633602804698, 4017981546647826153, 3298784914124356106, 1048634509662954303, ], &[ 11770973102809246906, 5654064914644075203, 14154195031168297145, 3196816914765589663, 13269534898382935070, 6602763211194544985, 16018516851544910792, 3180625223944165224, 5350941027330432714, 6398743157953739295, 1906167046060045935, 3556291732895289080, 17581917949159063577, 11917842024560925369, 5513291200181693371, 2805207190711928628, 10488935147153720707, 9353681503295456349, 11923702266366452872, 16445534228693736707, 1321572029020662220, 2088179387423767363, 2940575338916006997, 5660751381096282465, 9379032325552965866, 6155754375040762615, 17757845483758379498, 4791726927249442785, 2271154604380575561, 2810516188026226067, 17085166475121940699, 99572451658953140, 5696266492111718158, 10862208603440047636, 17394577092287756526, 8594037627948854376, 15384378431083587966, 8688372331869182594, 6898185140759317855, 9871173932216986045, 12528452101456458662, 13557460938391962098, 4450262203153213242, 9384263431241833822, 9013347668307504163, 11311595079831956259, 936915772753461789, 8433063029106192581, 16896552532247465449, 436920621494623275, 17030913520242164150, 9892849888317096483, 10846215292694646349, 8237341484379572099, 16094501558496758251, 1945916543779639318, 18090461816104963907, 4146339453090156488, 16829166437621172993, 3078631608488886297, 4439257821416126689, 7705380192038328855, 3538871580337510846, 13746211561839200096, 11905905983562326697, 13358208869614303744, 5843566918809605864, 9427926296554685300, 14598289187890400060, 11008519655031485653, 8593121017807548632, 9396415039249055836, 6268435325877250293, 17232661262414298575, 72834733148045272, 10210620080322964005, 4785045324389620807, 12743978039683515133, 1532018623508178307, 1626858325392940984, 14509988664710915642, 11484970178386722683, 9637331423956040786, 16727570268905595418, 17007646468471636895, 11784309337440826435, 8264087540904628249, 5386650781848750246, 2634849477861627672, 13571530405202238935, 957020390364360749, 10551951282480361215, 5860903308359481633, 7956790956638521305, 8737258119314118945, 12342128112549159916, 16715653993533680030, 16954242660912593528, 2489318600286989195, 7710331526401780284, 14799339212986303952, 15607538409164651487, 16839239842720015730, 12565794445330275268, 11582072386774199841, 7158773820903321984, 1329934199003039189, 6297267245832566486, 6153026408185751289, 3259942857823462030, 17905884378428276079, 3713606437359152813, 9370125751473669209, 10012381228375856292, 6916709082927033810, 17606888822444197359, 10818646898854586102, 9927520028322801489, 17015575684851383261, 15287563104761130407, 4246630569287612899, 6737522138244324583, 16956805675707509108, 10507692348129622148, 1144006384258648355, 4260138925314579646, 14508270375905482517, 3559046762122289814, 15199903498605585717, 16432575538338639756, ], ); test( &[0], &[0, 0], &[0, 0, 1], &[0, 0x8000000000000000], false, &[2], &[0, 0], ); } } #[test] #[should_panic] fn limbs_div_mod_barrett_fail_1() { let ns = &[1, 2, 3]; let ds = &[0x80000000]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_mod_barrett_fail_2() { let ns = &[1, 2]; let ds = &[1, 0x80000000]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_mod_barrett_fail_3() { let ns = &[1, 2, 3, 4]; let ds = &[1, 0x80000000]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_mod_barrett(&mut [10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_div_mod_barrett_fail_4() { let ns = &[1, 2, 3]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_div_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } fn verify_limbs_div_mod_3( qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb], rs_out: &[Limb], ) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let d_len = ds.len(); let (expected_q, expected_r) = (&n).div_mod(&d); let base_q_len = ns.len() - d_len + 1; let qs = qs_out[..base_q_len].to_vec(); let q = Natural::from_owned_limbs_asc(qs); let r = Natural::from_limbs_asc(&rs_out[..d_len]); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert_eq!(&qs_in[base_q_len..], &qs_out[base_q_len..]); assert_eq!(&rs_in[d_len..], &rs_out[d_len..]); assert!(r < d); assert_eq!(q * d + r, n); } #[test] fn test_limbs_div_mod() { let test = |qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], qs_out: &[Limb], rs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut rs = rs_in.to_vec(); limbs_div_mod_to_out(&mut qs, &mut rs, ns, ds); assert_eq!(qs, qs_out); assert_eq!(rs, rs_out); let (qs, rs) = limbs_div_mod(ns, ds); let d_len = ds.len(); let qs_limit = ns.len() - d_len + 1; assert_eq!(qs, &qs_out[..qs_limit]); assert_eq!(&qs_in[qs_limit..], &qs_out[qs_limit..]); let rs_limit = d_len; assert_eq!(rs, &rs_out[..rs_limit]); assert_eq!(&rs_in[rs_limit..], &rs_out[rs_limit..]); verify_limbs_div_mod_3(qs_in, rs_in, ns, ds, qs_out, rs_out); }; #[cfg(feature = "32_bit_limbs")] { let test_only_verify = |qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb]| { let mut qs = qs_in.to_vec(); let mut rs = rs_in.to_vec(); limbs_div_mod_to_out(&mut qs, &mut rs, ns, ds); let qs_out_alt = qs; let rs_out_alt = rs; let (qs, rs) = limbs_div_mod(ns, ds); let d_len = ds.len(); let qs_limit = ns.len() - d_len + 1; let mut qs_out = qs_in.to_vec(); qs_out[..qs_limit].copy_from_slice(&qs); let rs_limit = d_len; let mut rs_out = rs_in.to_vec(); rs_out[..rs_limit].copy_from_slice(&rs); assert_eq!(qs_out, qs_out_alt); assert_eq!(rs_out, rs_out_alt); verify_limbs_div_mod_3(qs_in, rs_in, ns, ds, &qs_out, &rs_out); }; // - d_len == 2 // - bits != 0 in limbs_div_mod_by_two_limb // - carry == 0 in limbs_div_mod_by_two_limb test( &[10; 4], &[10; 4], &[1, 2], &[3, 4], &[0, 10, 10, 10], &[1, 2, 10, 10], ); test( &[10; 4], &[10; 4], &[1, 2, 3], &[4, 5], &[2576980377, 0, 10, 10], &[2576980381, 2, 10, 10], ); // - bits == 0 in limbs_div_mod_by_two_limb test( &[10; 4], &[10; 4], &[1, 2, 3], &[4, 0x80000000], &[6, 0, 10, 10], &[4294967273, 1, 10, 10], ); // - adjusted_n_len < 2 * d_len // - q_len == 0 in limbs_div_mod_balanced test(&[10], &[10; 3], &[0; 3], &[0, 0, 1], &[0], &[0; 3]); // - _q_len > 0 in limbs_div_mod_balanced // - adjust in limbs_div_mod_balanced // - q_len == 0 in limbs_div_mod_balanced // - i_len >= 2 in limbs_div_mod_balanced // - ns_shifted[q_len - 1] >= (DoubleLimb::from(x) * DoubleLimb::from(qs[q_len - // 1])).upper_half() in limbs_div_mod_balanced // - bits != 0 limbs_div_mod_balanced // - q_len == r_len in limbs_div_mod_balanced // - do_extra_cleanup in limbs_div_mod_balanced // - !quotient_too_large in limbs_div_mod_balanced test(&[10], &[10; 3], &[0, 0, 1], &[0, 0, 1], &[1], &[0; 3]); // - !adjust in limbs_div_mod_balanced test(&[10, 10], &[10; 3], &[0; 4], &[0, 0, 1], &[0, 0], &[0; 3]); // - quotient_too_large in limbs_div_mod_balanced test(&[10], &[10; 3], &[0, 0, 1], &[0, 1, 1], &[0], &[0, 0, 1]); // - bits != 0 in limbs_div_mod_unbalanced // - bits != 0 and Schoolbook condition in limbs_div_mod_unbalanced test( &[10; 264], &[10; 30], &[ 3099176493, 2686179191, 2963763290, 1498905807, 2459138342, 883505904, 186294937, 1240988195, 1152000807, 3485254691, 3058980612, 4051918579, 84687528, 3474110821, 825051253, 2495113655, 4269053297, 531158278, 2131423786, 735959410, 1116746011, 2099249419, 427789428, 2182383446, 3493666451, 2086611578, 2349523902, 1865831092, 104597580, 720145483, 1653677313, 2449086005, 1225118075, 1458687427, 2284889737, 1178000580, 1204354477, 1109887135, 2302764777, 1833071533, 2749496868, 3989183692, 3112262804, 2143914125, 71393498, 3686808425, 568295620, 856601035, 205234115, 617861388, 102368116, 561132401, 733711249, 2931194848, 1371887453, 2942553563, 977874680, 3567773306, 2225947571, 668306082, 3150218776, 3697051793, 4272816685, 2926797142, 2177250555, 2840203688, 51052169, 1663516163, 3085068676, 471736374, 3127282104, 1358199856, 250868071, 54398826, 2107868776, 1621910930, 1677400830, 20889047, 4180454819, 908186988, 1625301399, 817226551, 4039437379, 261787419, 1484678288, 1183594253, 3154399910, 888455895, 1713982625, 2925178936, 2076694919, 2288237521, 620657938, 2457761902, 2906110636, 649773865, 1387981473, 1600821385, 3512543520, 2803028516, 1584293468, 1443490691, 2589741655, 3170284085, 1902835632, 1603116322, 2850443356, 60694796, 779743237, 4006039758, 3272304347, 2442366350, 3601524312, 720808564, 3291979084, 1675880280, 4139440559, 3672978467, 3938651783, 3257918674, 2077369764, 3027135446, 3940308694, 2533432781, 4105883289, 626796131, 608794713, 810463080, 2363401530, 2800065942, 2679046183, 4063827982, 2327835929, 522607612, 1660561124, 817356463, 2984129158, 146372510, 4293731514, 2558750639, 3948304613, 1448810261, 826590770, 2423032883, 1050524737, 2770168039, 265887860, 3353243705, 2674401993, 1496121248, 2053790031, 1863298286, 1068977659, 2875518960, 4137037281, 2888534695, 473250405, 3368783492, 3797281057, 132028186, 316202261, 381223941, 3366394660, 425124513, 4083952857, 2301832392, 3321645917, 509444341, 361894284, 3976042471, 2957832871, 250836826, 1408114735, 1614725824, 4214313885, 4081964203, 2663894263, 145380453, 2329325761, 2055092903, 126874014, 1000460254, 3910319503, 2561073113, 4231784000, 1042785346, 3511487116, 1270832223, 3456586087, 1210528079, 4119713948, 3299598065, 4178946856, 1623358249, 1001721969, 3964704699, 4133343553, 2193492316, 407893767, 2484237727, 3782842008, 2959959832, 449539588, 2978317444, 4008576738, 3478248618, 98697842, 3986898689, 1622966191, 3594042026, 3280563264, 270713233, 3999415188, 401848066, 623805281, 1710411200, 1801291443, 640646012, 2283134929, 1043531051, ], &[ 3120245340, 1558358768, 2311090615, 3377497278, 2047683134, 1453801550, 1974940808, 1545066418, 2840151982, 2463969682, 2025473894, 697610529, 906262319, ], &[ 3603474202, 23640019, 2133576502, 3778379659, 883962915, 1866519837, 1888919496, 2545522706, 1473641504, 1017307414, 1207107908, 43613763, 2001107652, 1295816376, 3276720994, 750683734, 862054731, 2423105118, 647184565, 82749472, 3134905644, 3469243304, 3869523273, 2200822282, 2271529456, 1805512365, 576197860, 1881352922, 2694444088, 700188823, 4014261501, 998600230, 3921476919, 3042342458, 1113168589, 1849643027, 272533119, 3745240014, 846408292, 2765600200, 337759056, 1580016038, 958561971, 2320387143, 2022805900, 1706525297, 2849929806, 2816448769, 4287480228, 531300416, 3987101730, 2194947684, 1539543472, 2563500078, 250905437, 2906546975, 3420715312, 1399943972, 2573547036, 2517309835, 3506368432, 609682764, 2647408356, 3234556565, 4224842927, 440117919, 2582391054, 3173478111, 1215556799, 1989776959, 1675806417, 3878920467, 243984561, 272254140, 815747813, 2471627048, 531500590, 126500733, 3476535401, 1877907075, 2939545031, 4041939245, 626658366, 2742940646, 3814661399, 3153036624, 2080267727, 412913879, 709446334, 1928720530, 3215012198, 1340243607, 4170012693, 1863453653, 1692829830, 3479433296, 1015591610, 2369310060, 1289466663, 1652392162, 348688115, 2813901666, 1381977739, 3968353944, 3449363379, 1249293688, 2453835214, 750904326, 577039386, 3965310144, 1188022514, 552527181, 2964971453, 1145764708, 4147965668, 632850159, 2337487248, 3382593879, 3632939001, 2658993791, 2820040018, 1556252114, 397274557, 490831003, 1052830763, 1914107101, 1353387689, 2482075969, 976484162, 2282876383, 4269190628, 139809131, 1188730299, 1650745941, 2014147322, 1678125742, 223161009, 123908503, 1950841716, 576079068, 3330988019, 932533018, 1319346982, 1356010466, 1972839391, 3937944592, 2091834184, 3610099681, 3420417182, 182310440, 651615236, 1741788918, 873416547, 99212541, 4107741571, 15809533, 2996576548, 1121127050, 2786591053, 2205830989, 3933647253, 3009211397, 2474199526, 616438769, 217585320, 626425556, 2196061289, 2231311076, 2237166829, 683712700, 1232727911, 2782798599, 2626930217, 3593762186, 2432346581, 1165370034, 134611782, 343289563, 4182953926, 3066331256, 1857734341, 132757904, 2635310959, 1313863984, 2215899094, 2574941352, 2348626035, 2950919138, 181796835, 3322669423, 3336363510, 767753600, 5374509, 3674971984, 1030279018, 550713284, 1341338555, 3995296635, 1696197965, 1833947598, 4208080450, 377211595, 1040418139, 1967465586, 998434750, 2027799751, 650545326, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 4239744213, 626950715, 3916878897, 2974637695, 488695410, 1094975104, 2496621051, 205419221, 4192241096, 3583664917, 511224033, 2016541230, 718692763, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - carry != 0 in limbs_div_mod_by_two_limb test( &[10; 148], &[10; 215], &[ 59488434, 3053025912, 3197673861, 28499967, 919132002, 3254889605, 3510992086, 4155414397, 1401076337, 3663475665, 3859836963, 838452584, 1714061888, 756807500, 721664913, 2122189093, 190377396, 772161692, 337532878, 2801246946, 3347165247, 504261973, 4207433768, 3203836949, 1637702776, 3950126612, 3575550053, 630469114, 2468674532, 3237190898, 2699368075, 2126693510, 2005217541, 990977199, 211751826, 4095342386, 2390539499, 553381774, 1202910267, 3124334908, 3631027545, 3118560130, 3505258080, 2533393565, 3897399802, 1644233433, 2966724466, 1228506720, 4266980301, 1975806255, 3087455989, 430105567, 2496389669, 2559019944, 1343075842, 515604272, 2623722375, 3549762134, 3517683279, 3564893038, 3816995397, 21727446, 2930818039, 2672793843, 1589653728, 2917937865, 665591277, 1222288512, 1197537333, 2425822187, 3647080994, 3180811677, 3800694132, 4006852228, 1392314914, 1823809919, 3315974102, 2004045597, 2557007205, 532899885, 1088861606, 3969820933, 711573681, 3744617855, 3618206965, 3834838995, 601286347, 1494520421, 2007503431, 3672534190, 3437739925, 3075991743, 1108097829, 438830502, 854842946, 798336207, 2497251014, 985928236, 1930130581, 260199427, 3446617597, ], &[4005818469, 1809723722], &[ 3451340519, 1823569360, 2748474762, 2379400860, 128212466, 361580627, 4041171442, 914389241, 3615201878, 3760016986, 2510499050, 3863385767, 36040042, 2251851610, 3210062577, 3672600394, 1663820028, 3073274096, 204666796, 2644054989, 1349439868, 1510081385, 286811203, 2996214643, 52859440, 3057966118, 2864727410, 1423659659, 1075210206, 3609454422, 3252263523, 2843960331, 927166023, 951309132, 672342687, 3596154210, 3997816532, 417627069, 1674501808, 3480074829, 2081711134, 3258035904, 1912656239, 2929955725, 1760162477, 3439128620, 3247428686, 2554948803, 1823534619, 2390298418, 153525011, 2577068170, 2912027555, 3356439173, 2878222520, 3673969868, 1465531030, 2707072452, 840674665, 2018453620, 3959489183, 853967262, 3462469779, 4149541196, 2692208503, 130843211, 2074716794, 2092443671, 3814231863, 3497057086, 3471416493, 1131939280, 2342388876, 299693157, 3210385182, 2920296477, 565691872, 868167224, 3148093393, 1215844287, 3565781208, 3578206636, 1537052552, 2438538598, 1664889116, 1383231686, 4042617071, 1777130014, 4179189376, 1391393677, 3822307038, 597944414, 2695354041, 2634181099, 2054915922, 810822072, 2370856623, 1541755236, 3884794992, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 1137651599, 55996911, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - bits == 0 in limbs_div_mod_balanced // - q_len == 2 in limbs_div_mod_balanced test( &[10; 373], &[10; 178], &[ 3300759985, 47489222, 1596412201, 3681499224, 721942549, 2798268772, 1725678834, 1018213306, 278963757, 2162182910, 4238919550, 1480123217, 3550714331, 2714414047, 1584331762, 3790545549, 2452172382, 3823866136, 3793112677, ], &[ 2532879920, 749327979, 378994598, 3512427187, 1768486327, 874381062, 3750599339, 1824619676, 4102262081, 3872688397, 4080392661, 1233784995, 3967512105, 536874, 1334357500, 533131065, 3802334171, 2688028352, ], &[ 1765718367, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 687097313, 233246948, 2670005176, 2918696316, 2059690051, 3559547370, 982825692, 2828616847, 3397764024, 1640472335, 1827782800, 239756415, 4169556349, 1129911247, 2514993175, 2469589340, 3137350801, 1512435665, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - q_len > 2 in limbs_div_mod_balanced // - q_len < DC_DIV_QR_THRESHOLD in limbs_div_mod_balanced test( &[10; 4], &[10; 6], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], &[4294967057, 15, 18, 0], &[718, 910, 1080, 1286, 1492, 2147483434], ); // - i_len < 2 in limbs_div_mod_balanced // - i_len_alt > 0 in limbs_div_mod_balanced test( &[10; 3], &[10; 4], &[0, 0, 0, 3, u32::MAX, 0x80000000], &[3, 4, u32::MAX, 0x80000000], &[u32::MAX, u32::MAX, 0], &[3, 4, 0xfffffffc, 0x7fffffff], ); // - i_len_alt == 0 in limbs_div_mod_balanced // - !do_extra_cleanup in limbs_div_mod_balanced test( &[10; 10], &[10; 10], &[500160962, 3482059973, 3833374734, 2382534866, 7345183], &[1962915382, 2761901894, 931109938], &[4192427024, 33881415, 0, 10, 10, 10, 10, 10, 10, 10], &[3497463394, 501014622, 297308821, 10, 10, 10, 10, 10, 10, 10], ); // - ns_shifted[q_len - 1] < (DoubleLimb::from(x) * DoubleLimb::from(qs[q_len - // 1])).upper_half() in limbs_div_mod_balanced // - carry in limbs_div_mod_balanced // - q_len != rn in limbs_div_mod_balanced test( &[10; 25], &[10; 20], &[ 3406830026, 653096149, 665840651, 3475733215, 2990001405, 3962996135, 1125790437, 510807273, 2268497988, 3801098676, 4251717337, 4009243500, 3093915781, 2221063229, 1145961534, 1520950302, 4156341537, 4051749345, 1887697916, 2938053362, 1317017771, 2551451381, 1165783725, 1692722530, ], &[ 757200076, 1850648953, 1310285965, 43796838, 2811750593, 2350568971, 1162649579, 3588922014, 843685186, 327689313, 822131258, 632127361, 4287259347, 855554137, 2978907761, 2140676852, ], &[ 1485327588, 946067489, 2418948212, 1981289301, 1964021912, 3125032408, 3497971833, 3396209894, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 1472562202, 467285767, 3874015352, 3774608073, 3547803297, 3252310888, 379016022, 3915526178, 172347662, 1424794357, 2354655682, 1763403834, 1622341466, 1527845266, 321699454, 1968063162, 10, 10, 10, 10, ], ); // - carry in limbs_div_mod_balanced test( &[10, 10], &[10; 3], &[3156053040, 2869923590, 2300216426, 1369503], &[177914576, 1102898054, 1547778], &[3800268463, 0], &[0, 0, 0], ); // - divide-and-conquer condition in limbs_div_mod_unbalanced // - bits != 0 and divide-and-conquer condition in limbs_div_mod_unbalanced test( &[10; 674], &[10; 255], &[ 4077004042, 60445643, 361888880, 1370511290, 4140611, 1545574856, 337863511, 2696753299, 882513095, 2220102704, 4040224968, 3895008884, 3144563393, 2298197836, 2781817257, 1704369652, 3931316078, 315544063, 3497851423, 3664143565, 952326443, 3938628137, 2331019960, 3709840874, 886597817, 2718223965, 2271519236, 1069952925, 2973484971, 694036791, 3948658826, 1091836994, 3976014345, 2590014773, 1030558914, 3050284515, 4064531951, 227487465, 1614818201, 2853653798, 312516670, 1131265287, 1079324522, 2790732553, 2857570668, 2459258033, 3676592728, 1861660079, 3846516218, 2487383610, 820186200, 670229005, 795815915, 4236865449, 388462685, 3530199852, 4067109237, 228011739, 3243897206, 2102622551, 3066279582, 2307396469, 3918457987, 3177100158, 1165801255, 3470877002, 730654273, 225744395, 303984647, 71923315, 2631641933, 642193977, 214491076, 4083126324, 1300818039, 3145270519, 3071074628, 533164498, 2260983885, 2398373112, 2291850622, 2549903002, 2876921663, 2087750942, 3012568578, 2072377257, 2300996389, 1724754966, 3663537905, 2452259556, 681943280, 495483009, 1806854180, 2022877157, 3545541285, 3155213185, 1520127898, 881038528, 2682219847, 2061051159, 4091777429, 2973569703, 2243163157, 3812478845, 2868568231, 538252316, 915738068, 3645567840, 557499318, 586868707, 334386881, 1009292772, 9683309, 1394382805, 1469121902, 3538152891, 192398621, 3298083372, 291538032, 454155529, 3467440904, 107593274, 2581455983, 4068643130, 1289926312, 2620830750, 3599696168, 845286964, 93649777, 211929373, 405469122, 2046160625, 4269019707, 3153165259, 3273675158, 740768718, 1724953971, 4107531497, 3669145824, 2308427932, 4057339865, 30691770, 4215434099, 2209368084, 3410096812, 3930010459, 4058257897, 1401228000, 3205298856, 919645629, 1080800085, 3531478127, 4244298042, 1920158944, 4150416695, 2942997287, 621554087, 2193963845, 3535984780, 1948458592, 1237268195, 4059838770, 4178023707, 2225635923, 1078133440, 1904752780, 1129557671, 2721601376, 3991770285, 2491529378, 2424674576, 4164361438, 1566434777, 3112804218, 2185237562, 2557399204, 967876237, 2243639679, 2436745635, 2376273731, 3848434966, 1970386149, 294413738, 1420657192, 694358663, 647017168, 4094657777, 3013362236, 590143693, 2285757920, 2393504081, 116938458, 891518480, 696284131, 2710811430, 3317562620, 1647436225, 1605219555, 3358343198, 2183786684, 1105785201, 248367120, 1398964063, 3309346508, 3273593185, 2032930327, 2675472140, 557577078, 692086759, 1588022257, 1734092444, 927029618, 3696557822, 3370092072, 2151067302, 2650483754, 3670460764, 2763985465, 1126450086, 3029345718, 1504895755, 3694166108, 578785502, 294874178, 110079616, 1327583117, 2661938072, 2345632606, 3722933355, 656745495, 671269721, 2346516327, 1169529001, 4238866211, 949351039, 3500460463, 4199863511, 2082398726, 1281275042, 2560151133, 1138051905, 468589983, 727511715, 2554428159, 2014177155, 3346720979, 1317583392, 1714879892, 4249909774, 2158352329, 3040382616, 964600510, 319055149, 890296957, 2071841867, 2811829970, 3945344817, 4075668231, 1336582250, 1632615222, 2996499016, 1247703908, 2161089989, 1757474064, 1957983140, 2427088146, 3819098678, 1414774317, 1685786700, 2842967660, 2434489739, 2748571761, 2393986575, 585646425, 733271380, 4096908487, 866235842, 1811304066, 2337315068, 4064326552, 2517677609, 595634311, 929413085, 2556167349, 2814648343, 3447175234, 4171314821, 3354462286, 2190450759, 3693163187, 817168953, 753817804, 2679932775, 2584000650, 511478235, 2858863655, 2320104001, 2367392444, 1724096919, 1152655320, 3131579385, 2076635048, 3557452129, 3931367674, 1011051727, 3910860016, 3742755232, 3977120817, 178461096, 1938068862, 1480470517, 2997286985, 196403685, 3581556360, 3800228840, 2583177118, 3801520456, 1254931401, 3392702841, 1046934176, 412728369, 2864978525, 970771733, 672204372, 1528132877, 2673063996, 740759188, 1840165684, 1821213771, 3111387733, 2386566079, 2682984985, 808050061, 4160818440, 1656303941, 2884647798, 3997066586, 3727980283, 4181671626, 2736389654, 1808865173, 1642983278, 875419327, 3960909969, 3751011271, 2807559080, 1535615269, 2321637137, 2745054513, 3020092780, 1359015906, 2466514344, 591997660, 2754906030, 3487658632, 3722637404, 1613546148, 915678357, 1842708127, 701921987, 1207101857, 1974760740, 2410755764, 3324705651, 3105821672, 335929431, 1887715703, 4035171395, 2815003797, 3632947325, 3664189665, 2211203246, 1473602679, 3802261181, 3699100807, 3964975584, 2757250875, 3240191191, 3824907808, 1582581356, 116402974, 2321914135, 933007824, 136161346, 2857937718, 1044097090, 477414473, 3966936277, 21169877, 2518410639, 1938987054, 4164953085, 3287593768, 96004465, 3316812094, 2635456314, 2931969475, 3535012794, 3954299175, 4188146823, 1054040153, 4020697192, 3043463112, 487456176, 1536604607, 2191156801, 2869189759, 650124563, 54254415, 910946976, 3240585021, 4240104628, 989174439, 3235043341, 607641178, 2910679971, 4072297259, 2664931864, 2560203429, 3992282762, 480443057, 3944140064, 1601223002, 3984987075, 3894479377, 1082591102, 2444518988, 2566734417, 1272094512, 2581007089, 3838472665, 2810473520, 1590808097, 143027202, 1667662742, 3686892725, 228309572, 4091365295, 1107025920, 938240502, 567559985, 2237721627, 1939039548, 3053102548, 3379831217, 3536253061, 1586694963, 931323468, 593457460, 1981974171, 443146100, 11888347, 2403661012, 2646485528, 528884126, 1040587284, 2828170682, 512577110, 3534338212, 1642316111, 124785841, ], &[ 3924577409, 3801138880, 2554871927, 1797946680, 1773117295, 3509783608, 281892096, 2358224613, 4217828194, 1339769957, 439570060, 3151617679, 1384372613, 4141908033, 3034076248, 201556707, 1940999750, 1134129834, 1062995144, 3653931665, 1653789920, 2219526834, 849219893, 3448402897, 890163003, 378127096, 3324725657, 2858888153, 4101277783, 1736762052, 4083759525, 1398269743, 946713296, 1332088349, 1241448676, 820326205, 1554372778, 2902257209, 2531752530, 593903741, 283370156, 1184475111, 4048000423, 3262885223, 3065903568, 2181798675, 970937186, 2831985588, 3318099557, 125775489, 2602810229, 1265835529, 370295842, 3885440035, 332195328, 803805465, 2339766805, 3074827324, 176637217, 2717782694, 3228882886, 2079180306, 1985828369, 1451458086, 2647399511, 653380804, 2816232893, 580123271, 1284828784, 1488365849, 3992136885, 1712696753, 3200712671, 4019248351, 2502831049, 3353947366, 3805407296, 3975182552, 1255379188, 3079539536, 2754826248, 2654365805, 1932758080, 2018940849, 3987435655, 2107608701, 1979416324, 2553264951, 2332482333, 3854067399, 7383141, 2032883058, 209316404, 1509786266, 891329562, 2446773803, 981357189, 289424276, 1563495883, 1124421740, 4019623418, 229810471, 1293459273, 685378813, 763089605, 543868756, 4294383498, 4256223402, 3521141578, 1300426165, 4203249157, 2446225842, 3483103616, 2930204118, 3459214772, 2242535858, 2845721016, 2523036196, 1191008269, 1438983871, 1990994626, 1369473842, 3325530252, 2436280648, 3247037040, 1827745637, 1440370214, 565710731, 918521819, 3174181412, 2021188910, 1292274207, 3161583133, 1940037031, 1320244184, 1944735324, 1624924970, 1914256377, 1558283566, 1557557944, 819014915, 3477749819, 2317549528, 1815788616, 3410581584, 865672422, 3902451420, 47231850, 2052078859, 2128580726, 2861615294, 2875806926, 2504678981, 2922243612, 2567002225, 3176460060, 3501319351, 256937154, 986867411, 2877370533, 3829593455, 169449010, 1762966206, 126552381, 3303194639, 437611604, 2065984359, 215674808, 2549495983, 226202732, 19733282, 265226462, 732006741, 2011526642, 2592527346, 3141322109, 980881336, 4085884669, 2038689570, 3704380296, 1688979285, 1869912321, 1472588169, 3395855158, 2409096192, 2603014340, 2571643809, 1244430574, 2331499515, 234553812, 3949996932, 1906820531, 1849149876, 4204335779, 1113287279, 1165814564, 3834491692, 3992932111, 1545656810, 1251393152, ], &[ 1794394879, 681672307, 1749784971, 3875852290, 2605775875, 3830937493, 1776664153, 2164658304, 3052389122, 121103990, 2532311556, 2668274136, 1883610764, 747104693, 408690547, 2248739723, 259855129, 2934993883, 2176924250, 1485355327, 1127644750, 856342931, 303483764, 5142053, 651773086, 625244098, 2731424936, 2350150371, 112631240, 1275290840, 4277356426, 3524679625, 242960953, 38072741, 2625824106, 3378716297, 2200097651, 3700674881, 2915988853, 596256955, 3040402748, 3720241079, 1756922775, 3093790065, 1609216017, 3777740724, 3784972477, 1832540396, 3490124554, 1020072047, 4238953885, 2842509290, 1000994976, 1809915247, 2550234689, 278010821, 2286612383, 3355766530, 3432337462, 2193122316, 1639147782, 3225990501, 208759694, 998787272, 1642795010, 1560281600, 2893662837, 3412088625, 1789543945, 134279791, 138110696, 3588552537, 3112564659, 3163154447, 877493420, 3664273345, 2755762243, 1258332153, 471466382, 304823311, 4211933030, 2150727708, 2218469374, 2393674811, 1501890427, 196739488, 341729196, 1105616285, 1176146479, 2705538889, 3565383221, 2299341008, 1060768503, 3218783689, 1009846994, 3473661394, 397249216, 13506754, 3621623374, 3497151661, 2898512014, 3630774848, 1935370085, 4267120880, 4135899051, 1799409148, 3505276358, 269078904, 2454901039, 25026941, 3541071795, 320224295, 25570166, 3637410887, 3066266074, 1551849913, 3855206886, 646778908, 3499920598, 1807392173, 2974658193, 3899170154, 2028217657, 223895356, 2694366517, 2696487317, 1259241092, 1452450347, 2872701257, 1465266387, 1227664185, 1852988079, 3265840174, 1314955140, 4073824270, 3212823909, 218445285, 1520746645, 4031847794, 3149615466, 1274808703, 370944499, 1824664178, 2735686429, 266060777, 3448762326, 53610860, 2123530021, 4143115834, 3225521174, 4010735833, 2635569855, 986902780, 122656384, 1339558267, 1284193679, 2736231797, 2963307804, 1626189148, 1233185099, 4139608947, 464077508, 4046285469, 2555743157, 3580743777, 3735247525, 4127955544, 4010576069, 1345310021, 3320552976, 3399711244, 3850568096, 1644768234, 2092743449, 1307520618, 3326695560, 649696140, 702848925, 138141565, 644912687, 2425292401, 1411631036, 3440461177, 3328837680, 2755185884, 2989552286, 2790272888, 3664124418, 3269945962, 2604287363, 1618340662, 3679959200, 4050805993, 1339789151, 3336692676, 2115818874, 2085307949, 2292717793, 3240684688, 2542744650, 2126759311, 399221966, 123686284, 4172595169, 3670712777, 2379819943, 3438823735, 3774292021, 506637095, 1055885463, 25709264, 3995986987, 742675655, 349888342, 3977445313, 3680517912, 4131805201, 3892493076, 2099913466, 1704689141, 578202598, 982472653, 3353811282, 3106111697, 2102812484, 1381551617, 1645348055, 3743699078, 4026522120, 1465113716, 2586289393, 2164999569, 748805860, 2837286220, 1641999730, 4171579513, 3835462317, 3732455291, 876396979, 3868206280, 2846621181, 3305441853, 3080114558, 1862673159, 2378144974, 3952061855, 1185723458, 3653385196, 1985735779, 847725020, 3859801001, 1049156371, 1895793200, 1830383465, 746355981, 281226425, 692646446, 2574915700, 1101022556, 3422609839, 428283554, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 1301325451, 2202463531, 827674839, 2990077551, 3515177881, 1362651403, 481136630, 3397298241, 3518449263, 76128572, 4225087952, 1094548681, 282440964, 1243437992, 2536206935, 1312305087, 2350135248, 1191467757, 772049416, 1651785710, 13757971, 4177684085, 4225218737, 3829973687, 4224488792, 835349925, 807373018, 2003072240, 1998180420, 1893011542, 2772647530, 1845722545, 3927750947, 1582656468, 3929302887, 2309901890, 2219253077, 74452907, 3721812597, 3102504646, 1837697683, 4169869788, 1109227870, 1893389948, 1637025892, 401123956, 2362840033, 3249816285, 1331916977, 11330013, 1790389738, 4046514714, 4242300773, 386281183, 4154390602, 2907471583, 596332521, 1031920105, 1416982457, 936732589, 620289351, 2021344934, 4134683536, 254271151, 3153428294, 2775130118, 767392350, 1524517878, 1803212363, 1935475282, 476597337, 1665283842, 385826494, 1418089792, 1583155781, 904332458, 2167494919, 4213977373, 2749948942, 1366862995, 974249813, 2151831423, 2426239456, 4154619782, 1909704093, 82889380, 1836307000, 1860128761, 2497608852, 302875545, 2512570768, 3465381901, 3664521586, 2113690348, 3208498261, 211553098, 1122435807, 3989762258, 1790955068, 1274985561, 801567833, 206607829, 1945509947, 2689438654, 630881630, 3166357111, 950757161, 2525660644, 2782583030, 2082925684, 4017471838, 2770389652, 3152723497, 2730012549, 375610667, 331640140, 3189394626, 1169047456, 1269402316, 366259196, 659129976, 1835642575, 1109092533, 1409510258, 1055228915, 3865844484, 1951513725, 1561115766, 1535328235, 566121235, 1218990885, 2397023975, 110038834, 410651474, 2293988363, 1341825237, 3049031992, 1068909343, 3433095008, 226980250, 234888265, 3753182189, 712474545, 3392300015, 358854770, 2053632965, 2314494072, 3270641699, 1763895670, 4027033942, 3610557903, 1952033954, 3311300088, 2108677074, 2293958755, 649449413, 1137877459, 1632674803, 3368118971, 4027363661, 3533599056, 4112294692, 1992613374, 2157460184, 2344709644, 3126961604, 3915648450, 163946806, 3452706048, 3278493797, 3569418312, 619110361, 1791108219, 53432167, 1675611199, 3468608269, 3380246190, 3977636639, 2303818017, 2959386722, 4259696814, 2826759181, 1786462977, 974733518, 2879253522, 3102475706, 2731858652, 2537398244, 2096104946, 3000514581, 821433471, 3175348116, 2836803346, 3386301193, 400757797, 3528093517, 689295706, 494008951, 3664544857, 1053036864, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - DC_DIV_QR_THRESHOLD <= q_len < MU_DIV_QR_THRESHOLD in limbs_div_mod_unbalanced test( &[10; 62], &[10; 1098], &[ 1563750116, 2761722522, 2234492700, 664378669, 2289696554, 166287485, 476834844, 2920420087, 2528304999, 1938173917, 3950825207, 4243596790, 2986888741, 3513584208, 1621935302, 3010962100, 97331004, 3497602837, 3156993605, 4246943277, 3773399914, 1791046376, 1330596670, 2066725731, 3080890361, 1411737887, 1547876370, 3080590448, 1532248923, 1435492412, 3448185497, 1125870178, 3236487585, 411921826, 2813696973, 3217407722, 3223519146, 3065092232, 2369951103, 2509352358, 926337125, 3014682136, 2966028824, 1505359010, 1713762975, 4092602064, 637732943, 1302647295, 2902550792, 889992967, 3865589903, 1419953312, 9792449, 3415320263, 564771153, 1688162383, 2484779041, 309493832, 218454065, 3482805065, 3854968150, 917520015, 394395502, 1316087688, 4013170326, 3611139371, 3969996396, 845435642, 1250928392, 3564637530, 3534519817, 4193257039, 1210838207, 1018604374, 1039438522, 3241956599, 283401613, 3791643370, 2495704071, 2807365421, 66163757, 3720427495, 929326153, 1056427022, 2224017890, 3983649303, 3242577483, 2252715700, 3763817420, 3945056819, 2536219802, 2347365037, 1332467980, 932313386, 1344905435, 1546705437, 2064541576, 1511380419, 3830839286, 1360902083, 3503290266, 3917441903, 1833414880, 3943874358, 1755117544, 2923194969, 2839238526, 1436154878, 2022570233, 2627252135, 514344885, 3629007310, 2734265902, 3693108522, 3208247898, 2234133971, 1972552128, 2954899309, 2020593517, 2046949131, 3731357545, 1937584680, 3590346900, 3944796673, 1847972007, 2243279972, 659814707, 354026232, 3897554349, 2861167827, 616720453, 3566033773, 667580062, 2925065641, 1209421025, 2590558623, 4061392256, 1200913167, 951116272, 3677973046, 3503505276, 3890324717, 588682794, 1822470598, 3062466072, 1622960923, 2217967478, 1671943310, 3797078111, 306673750, 416365363, 1127402537, 4051830565, 1295357578, 3597600014, 3944475003, 289083572, 792152829, 1866204223, 154676033, 1521441452, 3508161103, 925444108, 1492828246, 661274700, 3234551268, 2848116256, 2684114954, 1278505794, 1135004416, 1528837298, 903435517, 897822285, 1306717602, 1475128383, 1820901356, 1682104357, 2694156349, 1295051939, 3518824442, 250688398, 2216356021, 3513738778, 1822646861, 2230691522, 3766112863, 615919379, 1974329303, 1351423644, 2477642991, 1213629777, 1378792281, 2617577340, 2140073178, 2191340227, 2566413020, ], &[ 3993985187, 418743558, 1313360511, 1682822200, 2190606963, 1153956890, 2732042229, 1286070126, 662863720, 4186279397, 540453600, 3865675059, 1267823400, 3515598059, 2652841176, 1202274130, 1747727592, 4024332644, 1774850346, 681999022, 3602470822, 2758087563, 1879963947, 3431635945, 246837220, 425774791, 1105979956, 2942553343, 1698889280, 2350552370, 3068812671, 3185616175, 3088938498, 878065968, 4173406915, 3359260462, 3381157370, 170884832, 4229318755, 2494013993, 1549083413, 4140845217, 4084551031, 3363271174, 234069829, 579586268, 409399673, 3823445787, 644521777, 2518846537, 536802144, 2920279334, 18872050, 1166062818, 330384075, 567479240, 242105288, 2256634487, 2099809688, 3182064703, 3455323968, 3796049588, 913224553, 1273986744, 1216752331, 3471953608, 4141617369, 113668956, 2271813874, 3836046471, 1442113087, 1985184453, 1605355495, 4002876308, 3555195054, 1327862010, 2467826608, 2786784068, 2229364499, 4162880057, 2362120653, 2428764072, 3253302211, 4041072194, 3342725375, 5091414, 4236090390, 645428080, 2998645452, 2029624491, 56740124, 2165228859, 3087533984, 1636492749, 2209776976, 3692581237, 607934780, 2356087899, 844604833, 3795358717, 1191407440, 2348446542, 2260870238, 3095317646, 2239633241, 1510395276, 1414456297, 1992793921, 2093060671, 3555947012, 2097207883, 2341507439, 1797902178, 3894103463, 589765482, 4279776370, 1462654158, 1306903445, 2072601153, 2881422521, 41492691, 12234573, 1317588012, 460035424, 2087095783, 1325294692, 639610198, 163158835, 583584804, 2753511772, 3964488699, 2486983401, 2238895215, 1588375790, 2681620680, 4165955199, ], &[ 191160977, 1213228253, 1438665503, 2959833037, 428771185, 3495423600, 919673997, 3884278974, 2821606108, 3332861208, 2205644743, 3483267644, 3604026186, 2215417553, 2139152976, 746332817, 1763682853, 1100669552, 495776985, 2816532175, 2063832600, 3128459671, 3849765047, 1543117375, 4168563146, 912783864, 700345848, 4172185590, 3008292117, 4097449922, 3103811732, 3816126299, 2071211439, 2427293197, 1964661455, 1195541057, 490289276, 795794482, 314985500, 672557932, 539503340, 2302303785, 1102570205, 3216815566, 2112797258, 2783671087, 1390099077, 3312724493, 908130100, 1220098318, 1193663953, 1149221829, 819778349, 3289614534, 865016664, 2219777967, 589857044, 2513517779, 639503753, 2645890189, 0, 10, ], &[ 847465617, 4013314980, 3846912964, 910246757, 2972404216, 2762134840, 1953196515, 4029750073, 4055861164, 1261155057, 4100430088, 2785511074, 497236120, 1367918422, 3738577206, 736241263, 650868678, 2349520844, 3387563635, 741561301, 2423229549, 2724745547, 894805326, 2982356553, 4201925489, 3718492797, 3268940283, 1316855216, 535979702, 1867135512, 2894454664, 1953954059, 3331547089, 3629484636, 809197002, 3453878941, 2710176999, 2236099000, 2474407754, 508610082, 3021250908, 950343151, 2347617926, 3116087366, 387686701, 1840236979, 608794169, 80987566, 2929948001, 3099591933, 1498594442, 976518465, 2412591727, 4182908032, 3079365048, 2450010282, 2281968581, 2243779001, 309401913, 3783895152, 2093682035, 2006514294, 2836109544, 964684103, 1645279117, 3042605589, 3518893342, 3753614018, 3245078642, 976146102, 470909372, 417907929, 584991811, 4141480919, 3596625836, 3530716922, 1149488478, 595234233, 353336372, 638993563, 341110766, 984515266, 1262652725, 843520981, 594906936, 3922870845, 2571018879, 2329734185, 4233366705, 2923004114, 168356226, 666545721, 3625364230, 2627653737, 2717371138, 3344260869, 893744508, 407453169, 1376334915, 1670800848, 320471216, 2114539766, 1671037181, 886024377, 1940914459, 1457430737, 1427559259, 3091470472, 2856003945, 2098123517, 1418768818, 2088924969, 3884270171, 233325771, 2475658630, 3306400235, 1042747488, 2251057616, 288186037, 1069520858, 1716749834, 2851756715, 3107695069, 4055132959, 1800778936, 1250813397, 4225902318, 3898227912, 2436303557, 4099682647, 4014271299, 2579688947, 2474049743, 1793988451, 1750223744, 2886556309, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - bits == 0 and divide-and-conquer condition in limbs_div_mod_unbalanced test( &[10; 320], &[10; 915], &[ 685114319, 3257424506, 414393229, 2860628494, 121479429, 2579870766, 1597023839, 2474392621, 3223958133, 1457435159, 3048194581, 3047568591, 328216793, 3688729284, 1474966660, 3229714080, 1674178552, 3622356479, 2813923308, 420491140, 1181947036, 2552013519, 2545590339, 977030817, 1410754865, 418734423, 3219708398, 3814271579, 856825330, 886986018, 2340527841, 1574000724, 1326246490, 2345646501, 3649082184, 1757236341, 3333117097, 4191792834, 771549916, 4014890173, 1767239699, 1537408864, 860021926, 3301854273, 2439584990, 3450574632, 2067936331, 2217599411, 1936116337, 3184038132, 3501118169, 1312763670, 1815889084, 4185547518, 1921708290, 4252193163, 733366199, 1748333822, 3613571030, 2021878401, 674325326, 1834274504, 1974211381, 2155793730, 666543182, 3988638747, 719903603, 4243752700, 3417033998, 578937389, 1954345891, 438767411, 1067012960, 2140679028, 2616731558, 3608791372, 234168266, 115663374, 37715525, 3155431063, 1484074906, 2987669067, 1980354536, 201618151, 2443603378, 442745319, 2757914412, 1266139308, 4142086597, 1989465976, 3517367864, 1441253229, 1295109068, 2757883716, 1533532909, 4121897334, 3324479034, 33282683, 1821922930, 1002968212, 762196862, 13770263, 826603273, 4072569825, 780821896, 788706413, 2104768306, 1607373740, 341951230, 1675442736, 3679554432, 4040499065, 571466582, 467434507, 1883560688, 3831540337, 740943368, 2376257013, 1304728970, 917813781, 3342830532, 3374539547, 1366263565, 1830393744, 3801219913, 3174561984, 3973286677, 1398849159, 369072692, 656722452, 2994544393, 2007585192, 3393313477, 2976738602, 1184554260, 1566038994, 826752733, 477094709, 3837269061, 2769881480, 2709841643, 2163313442, 1223013930, 2855285371, 472880962, 695734454, 3106659328, 336220721, 2424316775, 1005851508, 3997249632, 3813922059, 4109122372, 1011074885, 44571353, 3135429322, 2678006854, 1812501650, 531726754, 684688016, 82728273, 2816638159, 2837354685, 3655899911, 36796549, 4088908020, 1199108102, 2363335387, 2702162409, 1359179115, 4038752961, 4132030616, 3472925013, 918360670, 1612076468, 1617334280, 3399902835, 1794719516, 1364930290, 3884047381, 1715844217, 2543581627, 1948226880, 3734808909, 1123962649, 6885664, 4055662667, 2036545059, 1825684950, 626135857, 3682021373, 2923868404, 1141437069, 301320286, 2038697946, 4203441370, 2625080149, 2416510088, 3453059660, 2196830401, 1003239496, 766384828, 1454135529, 3753927217, 289196672, 3027589815, 386319177, 4286570851, 34998813, 2808034465, 654631613, 2919774640, 3980646343, 3390105294, 3876707444, 342623382, 3063311246, 2951194817, 2409427609, 277380170, 1128962197, 512899487, 1130696384, 337608154, 4248250968, 2538526153, 408791364, 1355901969, 930023605, 619907788, 1270155017, 2669635170, ], &[ 933436633, 2314417619, 1779862136, 2339830299, 3359221691, 1983848875, 2097698892, 1645402710, 49190984, 3806363526, 2374325643, 638588450, 3467828663, 2693267297, 3081019625, 2568134532, 3644457728, 2630819968, 707790566, 1984505565, 3749563552, 3700374589, 2579510542, 4246015133, 1527325532, 3034605869, 2134963426, 3613350443, 2082268909, 3145097012, 497158738, 1750605816, 1683654362, 1392048080, 2595287102, 1859642116, 3880370994, 773829956, 2727575776, 868421082, 910865307, 4010486592, 72360528, 2330397412, 2764112435, 2833247271, 1236763483, 1139702723, 3454679019, 3138128998, 3268622050, 3622582141, 1726130545, 2831795892, 391680447, 1964919870, 2937963749, 260385042, 1893950828, 1182888075, 3460030123, 2590897592, 3391091057, 3700415037, 1619162545, 1524016666, 1313243906, 3716478858, 1054838129, 1929422210, 4093970820, 1243478860, 3650034984, 3598628391, 99479112, 2103638976, 3422493162, 3133671222, 3540259323, 1874029880, 1634209319, 2379655185, 1946213151, 2520479253, ], &[ 3601647142, 1198081127, 2017909663, 2850560144, 2525189596, 3322651433, 1196731903, 2005963472, 2134066324, 2610149081, 450546169, 188828597, 1723795042, 2336113352, 3907052140, 3494836209, 715365512, 1993048254, 1925488994, 823976428, 2233248290, 2422705001, 3872792781, 2414526209, 1756149349, 1280574399, 1755135863, 1247153316, 1728175244, 1243737647, 2892353496, 4039291447, 2822417936, 1802319071, 2421598944, 3822986016, 1165555397, 2706895746, 3653134185, 3710916752, 2131271858, 1948052061, 263095829, 3665120472, 3941304005, 2412990560, 214802237, 2000697426, 2019125997, 4285690497, 458482240, 3763367750, 3740974398, 18717988, 2994310518, 31139573, 2962856782, 2635167300, 1374305995, 1904881724, 594198221, 3362552684, 4265460501, 274321353, 561861394, 1648066133, 2292362828, 3514463789, 3295772513, 2531715202, 3705228042, 3001079609, 3079883010, 3054352160, 2260450577, 4705408, 1098764342, 3839802990, 2734256, 1555041092, 1134828750, 3567598995, 192771362, 2717018386, 662391953, 2584453057, 2585537103, 2576027868, 1668324201, 3624757426, 460065697, 1929435817, 3408543056, 2538334724, 3248763392, 549345600, 386006368, 3558580119, 3062181549, 1775062641, 2633004162, 2187541778, 4022833250, 2741897083, 3947772701, 679751089, 158802595, 285267524, 328299044, 3021797568, 2510593713, 2545541570, 1206900374, 1414348252, 4082633309, 274916917, 477912774, 1556311254, 3077433173, 2797875659, 3143263862, 465042590, 2147512274, 3300509342, 3506297514, 2410981614, 2358295490, 3388832427, 667531680, 2815589176, 4196689902, 1375855277, 3423352186, 1308972370, 3156982991, 3705393539, 756586648, 1240095514, 4216114488, 559069171, 2307911019, 636721718, 223194289, 1878543863, 53769785, 1002080984, 368614887, 254165863, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], &[ 4135839129, 3082159379, 2808741151, 2746492478, 1317271925, 1590248590, 1871245480, 883232624, 3985674442, 3997584338, 2338792001, 1776575346, 2531584902, 261625854, 3578066182, 2058830353, 684820033, 3683099826, 1776182826, 2182228087, 919424929, 4095708279, 1423878550, 172604911, 255380658, 4104949687, 3178922494, 1444103543, 1691042525, 1011488353, 3955571774, 2253259467, 3143874569, 377143694, 2390377782, 1070304427, 1715840158, 2972468795, 455414172, 3300053546, 2552753048, 3276730351, 1581696761, 1405031742, 2503564946, 1980393840, 2686153828, 3279538716, 1074513470, 2389426005, 592338809, 348493719, 3669366843, 2086362650, 1888752201, 1485850549, 3098846363, 839653456, 2380177511, 1732519385, 1998829691, 3296699081, 2705709135, 2848494034, 4155180828, 1425421469, 3752183557, 2319259329, 2757221818, 1921158733, 3302049214, 1696454223, 3356952349, 3100878977, 324054921, 2131412976, 1078305944, 698318350, 4151030129, 2259288990, 762849915, 3134288938, 4090864118, 1223661238, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - Barrett condition in limbs_div_mod_unbalanced // - bits == 0 in Barrett condition in limbs_div_mod_unbalanced test( &[10; 1459], &[10; 1458], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 1699768805, 1493014143, 2592376845, 190926105, 542951397, 3841252648, 1343830055, 2073311615, 2471501748, 1744126095, 4269392231, 3721081862, 3530443208, 1084284148, 467429630, 306942799, 1316059964, 2458728017, 4217570360, 2624704102, 3521450981, 2608224726, 3040435965, 2267671055, 471534848, 3629410298, 1363200167, 203206966, 3414918917, 3335382360, 1913622484, 1218762755, 3956682428, 1037359525, 5531615, 3407338094, 3864111971, 3057551672, 1048359741, 3074041931, 1285559492, 2147056083, 4091000908, 3900432305, 3556431023, 1451794634, 2393864263, 2505694122, 2968009980, 1048797969, 1048151529, 817832869, 2521994756, 2426006163, 3275649087, 941801312, 1575422758, 361314564, 722834359, 4247301247, 2186131251, 3429599060, 2212966801, 1219957676, 1702525945, 940680423, 333505183, 2493537355, 354760063, 274436852, 1639243309, 2924727204, 4285739645, 4001422648, 105606253, 3112142556, 3975066309, 409404932, 3040839303, 4022137216, 276092852, 3345019055, 1650156126, 169273103, 1920493641, 197903490, 4009771827, 838073342, 3939112618, 3406907996, 4120898973, 2720730518, 2834644027, 3448317034, 3673080760, 1810888516, 2181591183, 2952080694, 3794819074, 676604950, 3118739900, 606918192, 1316167449, 2730639798, 1815557579, 1808982050, 2109827633, 1671035061, 7558450, 1554665087, 520056416, 4218246290, 1161585267, 1878255675, 2486870832, 2088887262, 1303298097, 164712340, 2377403159, 525890592, 3347413040, 1697811557, 3373912443, 1800652721, 1430587466, 630390988, 1443110580, 572173114, 3006613569, 163802577, 3661300485, 2066285319, 3197778371, 1266266830, 3617690296, 4233259050, 3805452611, 2682754452, 1121170085, 4239996815, 2574739406, 3293943958, 589250712, 694935820, 2394149134, 3507180662, 2403010680, 1341157799, 688040930, 1064943055, 1576175762, 2748814503, 3365706670, 2331616371, 3891308187, 3625939659, 834228833, 2747861390, 4238259694, 2400594789, 1064448439, 1457694712, 2503273199, 848323770, 3879018391, 419366498, 2787183492, 1572178433, 1143352485, 4132728989, 3611364165, 2042218208, 4202715626, 4222254124, 3573214358, 2530238089, 3214459960, 199438106, 1990033748, 3797350881, 2039620692, 2196170141, 2867974320, 218349677, 2334991902, 2199173454, 2635928703, 1960733130, 3298739914, 1745262170, 2022670546, 1773942006, 4022957449, 3487536364, 4203797706, 321674131, 2963478216, 482717037, 423207073, 2529853593, 115650857, 1559406958, 2515253401, 4253176221, 1494891359, 54215779, 145831030, 2534290332, 722379383, 3288965822, 3478280697, 114345927, 438460383, 4120362834, 3417392370, 3871144709, 2774707897, 2662801524, 3802201761, 1044223137, 817062608, 964570171, 2627601973, 2648686193, 2728498120, 1589690733, 3285610776, 295629246, 3995872256, 2573726546, 231960020, 4274030532, 3444536058, 3882840099, 2252235022, 3959235737, 3485371602, 1365773288, 33313646, 1392617408, 1844121885, 993486158, 821274239, 2676605019, 3812510576, 3432776114, 495146668, 216967234, 3172737228, 3417198461, 1629229154, 1821830950, 1340735610, 3211463144, 3560398150, 1050123642, 874441227, 3169516221, 2783241998, 99843330, 1175436161, 2825581162, 3259620982, 3350111857, 1606464613, 1911911079, 4127551535, 3229370127, 3828823712, 2744685123, 2859704702, 1106636072, 369804135, 2989745290, 2768260583, 3275220193, 1104864623, 2290350054, 1049972093, 1592992521, 3598788064, 3350912109, 2954408081, 4230173468, 2901042813, 1614811380, 1930643862, 4235254046, 3520012632, 1160373738, 3249852125, 923106635, 2511906301, 2055083218, 3193170540, 843255473, 3274357481, 1069334404, 2160558830, 1247811861, 1960090087, 1260505746, 273679994, 628898405, 3731946987, 3821611375, 1479367897, 406962212, 1951524671, 151905808, 2697376333, 2827375721, 3738186384, 2398267382, 1189552516, 3271847863, 3695955312, 839640611, 391563549, 2851226168, 533382637, 4005632192, 779063015, 972248299, 4160069328, 1551848869, 2901173293, 1788886403, 7742522, 1152154246, 3162815742, 3933026131, 2093435260, 293643707, 537139803, 166837469, 1353454767, 647497063, 3056417780, 4130500121, 2563320691, 3004161478, 4266673072, 1525376895, 2692236203, 612090721, 3803502732, 1472545930, 1285255741, 3563385061, 354899818, 3985901869, 1077755288, 3764626839, 1736779714, 1388617683, 373259603, 406803142, 2250511459, 3661744930, 1712371282, 3755716304, 1001652736, 1437790589, 2722214878, 3509431789, 1045623456, 1477384299, 1529044191, 3485492831, 777726776, 3111945645, 87325680, 3674053827, 3777562490, 2467629264, 3920974102, 1118313420, 518650065, 2779852693, 3938004723, 351444334, 2301762313, 1696242659, 915234550, 3426770333, 2623516555, 2367502869, 1764681654, 3012087599, 2970366387, 1214823325, 1416807413, 1002068525, 902786108, 4219021066, 3685197343, 627261248, 275319515, 1048180581, 184895903, 4054317442, 1164782510, 2969271356, 448119019, 3225650628, 3586253056, 13844949, 4265695528, 3156376136, 2094798072, 857381027, 2996376430, 2313835774, 421527113, 577824604, 2027011737, 1936987926, 1716119129, 2495416975, 1566342556, 1974265475, 100699876, 3818621196, 864167162, 264481383, 2779691848, 2519054856, 356904428, 1425193402, 2029146838, 3791198981, 1181286580, 2106244436, 4074963191, 1156817098, 2002193018, 584536494, 1252244761, 3576951572, 2017920970, 1604293290, 3010503460, 1201492606, 1555982397, 2556964369, 3428819809, 4168489079, 4171058202, 404720822, 2480856269, 1813722898, 2093837710, 3164853594, 3430042720, 2545385245, 1253945679, 2067139932, 1049755734, 4162345450, 1330690410, 2567802121, 3494789533, 4027320953, 1359086506, 697144652, 2171860846, 1885681379, 3200348033, 779514913, 3892431243, 3292022849, 3206367229, 141294896, 1247341423, 1286221471, 2030904879, 133272354, 1441910339, 3982161305, 2696309947, 3801057775, 4053369379, 3233631762, 3173498696, 19486328, 3282282805, 2117833655, 416934200, 2476837107, 3550654071, 835595228, 2784887835, 1849982594, 1215825494, 120169702, 3628150453, 813273996, 3164608875, 2585886019, 3468354974, 2529654702, 3937155612, 2948360421, 3839784361, 3626976122, 3884938510, 2182665318, 1984077334, 3592802345, 974314095, 2658877268, 3320515471, 3220348329, 2057524489, 3330170042, 1859432638, 180803537, 1712128971, 2278567221, 2233418239, 2029256422, 183505236, 1671411329, 207176584, 2036148357, 2313901094, 3988184694, 2436690588, 211724920, 3032356297, 3340214696, 117345076, 1500403818, 1365050888, 2323945197, 2919933846, 3023641486, 599606728, 3628676259, 1581385213, 1427038937, 807104522, 3978940995, 3629484758, 47151915, 1224789415, 2759574529, 2839954032, 1315873434, 3168847820, 1610459325, 3726598118, 896590825, 2419742875, 3430079217, 3778931934, 3687222980, 332999836, 1043316180, 4189864653, 685607150, 3695627010, 196835870, 3941428183, 676485145, 986494888, 1049128467, 1888162207, 2801108003, 2947315222, 1894059346, 454711531, 3589935315, 1803051198, 3655137369, 983821858, 3081875497, 3803393764, 2428490033, 1679378736, 246071720, 1483050983, 1382043974, 895942294, 2442009263, 68111122, 1626094364, 1007851423, 4064984075, 1533309302, 3360582064, 2740180933, 883885210, 2989133634, 678055765, 2661431250, 92559696, 1032783565, 22899740, 2361882691, 2393385114, 992907787, 3373832203, 343145453, 1165167516, 290287284, 1707286378, 634939907, 1875541381, 1297012104, 3157634640, 1929967474, 1519414443, 3881762803, 2681995819, 1775206192, 2755218098, 3910825543, 1860602393, 1832806570, 415596447, 2186155905, 2791826564, 1816344456, 4023525966, 243382839, 748453584, 512556810, 3922005623, 1061467548, 276741166, 2229273612, 1738207771, 4128865796, 1984054190, 1324502121, 2297662740, 1222235249, 3182342363, 1665477641, 2147473685, 2421806673, 2322492629, 3459362839, 293710623, 3706578807, 1598383617, 3666283079, 1011133678, 2189483475, 938644636, 847088475, 195518118, 544927250, 1332819612, 2366720962, 3995717811, 1985243513, 948001598, 634366393, 3212334449, 4000960249, 3974258285, 4013403482, 418753555, 1101654041, 1090819318, 1675158019, 3683152713, 1204756106, 3841987860, 2260147808, 102023094, 238154404, 533560693, 4086126380, 642534617, 1632145671, 1006291121, 1435987078, 1313038313, 4186175328, 843360286, 1839639056, 1353648132, 2221125136, 3732368512, 3339185832, 662563454, 2744469998, 1331973650, 1343096038, 3251304725, 3601378173, 3422205067, 172706680, 908147887, 3728762498, 3795011129, 3044217576, 67031330, 2499472547, 4147725229, 2529069049, 3741434149, 4201254595, 3779595001, 42489268, 2053548825, 985282652, 3980674776, 3248961215, 3376433654, 38182659, 2602101994, 1925777855, 806407427, 2317267910, 1380652265, 3701097444, 1220848862, 2025812459, 3482791264, 1753046753, 598143651, 2616070898, 2479609320, 1868138196, 945178683, 3832269010, 2314371642, 2400732781, 2048750780, 54093670, 327716566, 3334970102, 28861124, 4118278855, 3714357594, 541833330, 2000911880, 2666752754, 499968133, 1548730866, 1814521338, 2487369228, 1138644653, 739248636, 126190040, 3978033791, 1817304821, 1225794794, 2871919793, 940731169, 504076316, 995594649, 3329757458, 2846947354, 3891292748, 3959049218, 2127628616, 810346662, 2271875593, 3880247584, 1164066271, 1750445267, 338639562, 1699074958, 959302743, 2956590033, 867798509, 627451437, 3510106002, 2473252158, 1509206912, 3352377241, 3802665519, 2147957812, 56184472, 1718654148, 3672624374, 3511414009, 2682054173, 3922316656, 2414259176, 1496250883, 3967344788, 3214918603, 1624761599, 2724006253, 978208159, 1113357772, 3487098045, 4270740839, 633061828, 2261921853, 3462914738, 1530768806, 1364864048, 2876294873, 2510835104, 4242821662, 2474987381, 3633586220, 979932165, 4155189874, 2525154569, 1335483880, 639760624, 1660790427, 2226690500, 4135706134, 150618757, 593063255, 3258479253, 3728374085, 3007800944, 3679685736, 694904689, 102552353, 1428747995, 1176285881, 641509845, 3270509599, 272169854, 3047261598, 1287492008, 3351279172, 2404469180, 459751592, 1333387953, 735177161, 215716037, 536597459, 3665567562, 822815388, 3602692316, 3168229037, 1054147108, 4146505577, 1580773238, 1088501561, 3629868530, 2978204283, 3610240644, 2223237525, 3153209697, 448561701, 895234984, 1592358205, 57857782, 851682344, 4181525201, 1988009551, 3651424110, 3655716749, 3787661870, 2925252014, 3708997912, 3309060091, 4188222270, 1673276025, 2192528846, 958274526, 1258766035, 3525801758, 1215614889, 3051826051, 2354974337, 1541657893, 1271755575, 496264166, 2626820052, 936952045, 3785181421, 1294902361, 1958901697, 1604821791, 218282718, 2246953449, 538193118, 1919817946, 1243076425, 799521120, 279827487, 2722496365, 4019574708, 990869332, 2181585056, 2705356597, 610157367, 4119248513, 3343890269, 3121261960, 4085000780, 1022014736, 4240976369, 2817889889, 4075894073, 560049242, 373205120, 334714162, 1892034277, 51733004, 1776487312, 1265439929, 529285398, 2048981213, 1833004632, 827301005, 1648393113, 4281016481, 2048185380, 784315559, 3245679058, 3513265995, 1369181664, 4269143782, 113931975, 1398194472, 540409306, 216516009, 2627890586, 3694809441, 2573974797, 1396611872, 2646365320, 988053471, 84792061, 963667070, 2114579379, 3564371585, 3893773169, 4197725787, 2378021272, 3273607654, 1738197474, 2402812179, 1278628015, 2317178895, 3160300732, 603898477, 1287079046, 392763347, 445875312, 318139180, 1903469143, 3585413276, 885483094, 1674549044, 3911672420, 1575430246, 1867282418, 2115410448, 4189894183, 3512999498, 2833930381, 4284803257, 2594863293, 3053172089, 442647755, 2456733276, 3207156565, 1248598530, 3135346976, 2511563725, 2761431370, 3552853409, 3064928230, 1668127734, 2151818142, 1573413967, 2528903432, 2255579949, 4086541389, 1008056620, 651544198, 4099217330, 2147059795, 4189054906, 3160158060, 3084688966, 1829066970, 366751766, 1086760266, 1823021570, 3035776668, 3725549438, 303569416, 1637955291, 3070457854, 2756834184, 1117066585, 2815830458, 1229154243, 978732541, 3666377420, 2646214554, 3084488532, 2757010866, 1756160517, 2475577838, 467860047, 3125348085, 990351000, 3303850398, 1120462919, 1920695807, 2980611720, 142863055, 2378648555, 2707355873, 3519612422, 3266835497, 2512195477, 1941306513, 365527762, 592954943, 2552580189, 2606501901, 1933724422, 2729691276, 28289820, 3017728757, 3650961916, 3696374759, 4228636665, 1241471494, 3355869165, 1455843481, 2403725149, 829901760, 2618851388, 2623034964, 2752098284, 962418521, 964160519, 1174284358, 2043907493, 848741317, 2520932535, 53649688, 4228750878, 3694987632, 2694050164, 1097113047, 1221352269, 3997202409, 2858697527, 2874569664, 82995009, 2474870382, 608319794, 2793235942, 1762763510, 593568738, 4140942494, 3399850155, 3632742015, 1495257590, 1987803076, 3040781503, 4185563847, 2095097137, 2984180367, 2385825018, 276655462, 2186224265, 242785858, 25971964, 960934651, 4259630073, 2869516035, 1099452330, 1108772812, 2208212843, 138327599, 3047969124, 2406962821, 3234115454, 2013090243, 1253595634, 379537518, 966627542, 2289594467, 3820588844, 3307962615, 2251395356, 1086612191, 2411787092, 716861072, 488537062, 4279016079, 1024670198, 3162868375, 2993498248, 318817475, 1204805151, 2917216152, 202544687, 4055006202, 2166902046, 777932120, 1954248209, 1436706075, 392807099, 3560992122, 3690436481, 4086456539, 1672219993, 718561908, 1329443408, 41759831, 3830929272, 468558885, 2850993192, 1203438200, 173099196, 3100895691, 3212371819, 2727223413, 265778175, 1306749738, 1945372531, 3409735664, 1829111612, 73857789, 1967847248, 111126146, 1941085939, 2157306354, 932967688, 1524770100, 3562820290, 1815865396, 618928660, 1954521715, 2791055048, 1472833149, 2745012885, 2590581857, 764068138, 3810864565, 2068720839, 423731968, 2781829173, 671016197, 3626671545, 578830019, 2263629204, 3196999908, 979097653, 3960854009, 2652280123, 2014180777, 3212225669, 1901793582, 791028866, 1535961645, 3425925260, 1728220859, 906987059, 1320441954, 103740087, 138471919, 2751991892, 3763793139, 1930252328, 2302777807, 4166228863, 1898736904, 2679190175, 1902812084, 3494412200, 2003091421, 647088593, 1275527793, 1571337951, 1296166873, 952173553, 3873665860, 2863399704, 1687749991, 1019315430, 262989750, 1995806398, 3977438566, 3065387570, 194327737, 2433254350, 3852864758, 3086016127, 1848276257, 872733825, 4293282833, 3839899541, 1287823073, 2617969813, 1718468275, 640897626, 2796238324, 2471345611, 3038580905, 1824539690, 2178312422, 3642675324, 4168141874, 4093223514, 1058804935, 1645178046, 3320651392, 2520046692, 1724703883, 821899232, 481110608, 2492775734, 922020621, 2923405792, 3392950548, 76237439, 3904683294, 256504571, 727968315, 59423766, 3078236506, 2465675774, 2942973709, 2930861254, 2455418902, 2986403934, 3056400696, 3599867309, 595501194, 2042151651, 2763604081, 65000450, 398696589, 3026108404, 4199385741, 3349995311, 129915120, 2486649758, 775313272, 2784093349, 1582665104, 2775814261, 1584569957, 2195691054, 2575677337, 3244017237, 2457054839, 3897157261, 3195991591, 2030342150, 3727062402, 3706029571, 1179068874, 94821848, 2230566710, 3669075264, 2425831169, 2438414276, 1720898289, 138216286, 3807634131, 346144588, 1780209932, 694722911, 297024116, 2795490416, 1836169972, 2915769303, 591959219, 2377921602, 4158591575, 1182337705, 231710027, 2274507465, 2241869617, 300827881, 4150367209, 3585840019, 4167111741, 1023965277, 1674153048, 887595527, 1601672948, 1765479313, 4065509701, 3915091640, 1297871355, 3479625154, 2831036720, 3785201761, 1221164796, 1647627464, 2551945655, 1768755122, 2079192478, 347747455, 4045445050, 2954562195, 3495749867, 2264323612, 3116421719, 2118887029, 432847575, 3976298717, 30083877, 78749340, 2656872748, 3171516677, 944561854, 202462342, 339834758, 1199920281, 488096540, 3380838041, 3470160182, 1755758102, 803450485, 738480354, 357618351, 8551902, 812925594, 3218358491, 2918846080, 3174772578, 822290689, 51990462, 3350891640, 2729296982, 2723805763, 3540769319, 1145905142, 1754039404, 4289454572, 4153901476, 1336760032, 2717506348, 2938254966, 1476941276, 3458786809, 2378593502, 1537570700, 476723401, 1207306095, 1092996894, 1187377294, 3666979500, 3948059620, 4150681293, 719413909, 1118296918, 3753268822, 905882560, 1638884713, 1259563753, 1063300422, 1502884288, 2285369399, 1874551590, 2040785043, 1775679918, 1144757520, 3854262168, 3821097323, 282903083, 197139966, 976017372, 3684024526, 3746169537, 108937132, 2444167905, 3366454633, 1002555971, 3961863482, 1693512346, 4219424106, 2731825813, 2173055658, 3589347522, 1180897582, 349307065, 132252171, 1286185962, 2906205536, 2843606103, 27822898, 2481699072, 2948630201, 1774092707, 1171123309, 3404061713, 2905420837, 2351973006, 3971568799, 3248015376, 2297549471, 2624549152, 2864086950, 2757145051, 284981704, 4116824485, 786416861, 455364234, 810567289, 1304615212, 2127708286, 3066389895, 3906659140, 1621009466, 4060905456, 2498550541, 2021095657, 189923381, 3015918335, 394513300, 395082750, 1997152191, 3900214471, 2076041515, 2762331608, 3059576182, 634566583, 2077367009, 239466771, 3512081528, 3492757347, 1343506243, 144657866, 1186993011, 2942254420, 3813487876, 640076454, 3107898063, 4057144155, 2951251839, 4059833593, 2265248880, 2051308911, 3838642653, 1427962716, 1138966813, 1697969541, 3885404282, 2547515947, 2006341172, 1338884621, 3673075887, 2250647769, 2303605646, 4029999904, 2015620651, 429025216, 4230380695, 3438741639, ], &[ 4140022839, 1332918634, 385973856, 729517205, 4200666083, 3186247306, 2216473287, 3967994940, 3549880551, 2351334526, 2534881763, 2681541703, 2415670560, 1563911606, 1997982500, 1605736458, 1167308742, 3790043183, 1281410972, 4023693410, 2615885090, 4061771357, 831983168, 1009160127, 63254496, 1067286614, 3975642271, 3217740495, 1975825580, 854854016, 1915702280, 3908074524, 285492350, 1679287901, 1104416954, 3695854744, 3144705003, 390542060, 1273889374, 3084930693, 4021045456, 3870124465, 1499147739, 3994210128, 3405516906, 3623362998, 3181013060, 1438540318, 4272229535, 306800092, 1181814571, 3620542147, 3869706343, 2217038651, 3688188000, 3236239747, 2170551399, 3953686852, 198893646, 182904951, 2546842722, 1735943345, 1114476981, 405616403, 3534536074, 2023951294, 1480810150, 3151805839, 382753314, 3801503696, 2647293617, 3687313025, 3690190955, 3611357942, 311999520, 1479537441, 1417453958, 432157481, 3078614193, 3775508939, 64222726, 3924944108, 2439554192, 3257110815, 1419675816, 1340749298, 453811150, 1561302035, 1676196487, 1180208338, 3665601239, 1668250078, 2824874050, 623744389, 2632051421, 2939514497, 2726660986, 3692620466, 342565691, 900445430, 1837938808, 3156072699, 1435577065, 848877849, 3301087391, 2965859650, 1031009120, 2161708655, 140555963, 2153100207, 4212548871, 2619127334, 3918882470, 1432982383, 3390781349, 3716882367, 4184486270, 2277586036, 470252938, 4112802036, 1170864674, 583933362, 3436794416, 2375532943, 49632807, 3418743752, 3474436229, 3170120487, 2315065091, 3188088177, 590943243, 3782256578, 1083050403, 786791806, 967853931, 1985229455, 2650153654, 1329623293, 2081902975, 2953142527, 1454174427, 956392778, 2653248919, 2825319626, 2568111104, 2273785507, 2681572985, 2942580495, 1582788144, 774169635, 3400727324, 4131339023, 3522701030, 319714447, 458707788, 3752893403, 2443453767, 2781969719, 3372652584, 2121224611, 2434396226, 3653609151, 1787303898, 3116390348, 1921974414, 1712268671, 2949516740, 1622664220, 161136625, 497442963, 3317256575, 2957603271, 986452621, 3805208504, 2188469415, 140689727, 1797077961, 2162618915, 3322199776, 3924576551, 944631509, 2240768158, 2759297442, 1749164955, 3082686335, 3003330954, 1180096875, 2313197002, 1149750323, 3900540274, 1995494972, 2408692703, 2046549780, 411448793, 255559985, 3477747740, 3894106684, 4213478926, 3984564898, 2712600956, 3287187119, 816891367, 2106294719, 1106097934, 2910176802, 2608974151, 3469858998, 2100827559, 1199787244, 3568298, 591666042, 328113877, 3372271726, 3376926821, 2110192502, 2024579892, 2139201149, 1247359283, 2768125945, 2549569459, 2612808458, 2318203790, 130370887, 4254847480, 4001483865, 3878364734, 3541076697, 2506919390, 3651245283, 3792308185, 411720929, 3304656118, 1031630616, 2882095508, 2575128889, 1941130594, 3620512291, 1584273173, 298857748, 1816941748, 2999070534, 3251147932, 1387106514, 3520710326, 1393970408, 2451356112, 159701226, 2454829360, 3908203803, 2096649839, 3785552552, 2810782392, 3683175936, 2049748560, 2728594433, 3807332520, 3378848389, 879276013, 806429365, 2062382159, 685759815, 4103606920, 3837126864, 4044942116, 1361913605, 3538745256, 4260118682, 1468436403, 3266698300, 2298805804, 3550824836, 2931275954, 1201599658, 3732266565, 3356136327, 3721347742, 1028089391, 470390407, 838305008, 1154116269, 2955121230, 1969987690, 96777497, 2525384567, 3280604030, 2954089608, 2870616682, 383452739, 2851853443, 4247435667, 1968078656, 2157562040, 2298288548, 2057507768, 3694060404, 1371214831, 691452969, 3349919462, 3931314405, 2996280220, 2073252676, 3500529769, 3308852650, 4013710550, 2128361215, 4120449957, 2644175204, 2771183255, 3881988169, 4057679961, 3263153248, 1702685317, 317599410, 767790225, 40124243, 1722383190, 1975688792, 4175872056, 3846629460, 2643060200, 4204702999, 3742204598, 1998112415, 3570363511, 625953345, 1899666414, 4202545026, 3330022508, 959584356, 4092102387, 2602888631, 1180144128, 2154538601, 1195848017, 2998497271, 1397107840, 3412220808, 465149695, 2877827512, 248680930, 4060793970, 127179801, 3479407908, 1039497650, 1589401135, 1785006420, 4270265648, 3759909234, 433296685, 2364021432, 2489444512, 829658611, 2658111199, 3782549974, 1011476712, 4211023677, 1914407156, 3639480936, 1313292962, 72715740, 3746156019, 154708522, 3703285093, 507957038, 1196454422, 4164637758, 3835084902, 1974263654, 4097488680, 1017286328, 2381514791, 3008685528, 797211770, 2421604636, 2469811051, 2448855528, 3200879216, 150917686, 1386549503, 951269912, 884416859, 3270671738, 4173496604, 2352492574, 2312459813, 1381728090, 2225432681, 2624147380, 1753378914, 3784057767, 1849246765, 2097893023, 1813860006, 1309569046, 261246408, 1352760534, 655383919, 822735207, 2080963562, 785386674, 962647863, 3855351034, 163148442, 1638002593, 2361285757, 2942885144, 3801953893, 2050867773, 3719126889, 611516050, 241996878, 2359976268, 3116112772, 525763893, 3795367885, 1899100059, 1826668521, 3968490725, 1184477065, 376409549, 746651808, 2755958490, 690064601, 1335602324, 2315651118, 1798021213, 3057146144, 361981243, 3683370219, 3495845024, 4229047082, 3665386898, 2448070295, 2103815950, 2282815628, 2728867302, 1675855376, 4246790452, 3451647092, 2752025505, 3696059121, 1776536840, 2501328953, 108497888, 1674323829, 524525402, 2031653211, 3739008218, 842744685, 1787133262, 571129007, 1522748508, 2869008999, 3669532986, 3107783215, 1087834784, 909862848, 3671334552, 1604234750, 1868039767, 3277936848, 3892010410, 3604408115, 804539188, 2593245850, 1848873611, 1717694352, 50916242, 2543833083, 3321591984, 3860808446, 973275623, 1426440356, 878204766, 2518066829, 3609815944, 1178130909, 3463022868, 1259354393, 660781485, 696960611, 294179566, 2623547513, 4025779112, 4289956495, 1716509851, 4255486421, 1742423706, 181083582, 1576335154, 2400595517, 3017395276, 3510949481, 1775378365, 2675541160, 4181947126, 458529395, 69232536, 67987398, 2855644109, 1641330784, 506233303, 2545017731, 3604602302, 2316102379, 4021957608, 1362988002, 589652170, 3287129679, 646961616, 2741167343, 1059694828, 1294695889, 3286103374, 3610609446, 1880809887, 1000550267, 2311288273, 2150509497, 2387358122, 1755230652, 1623678481, 660120160, 2362168609, 4284517997, 855059721, 1701363080, 2654809044, 2751921880, 3540973385, 635986452, 4005249717, 1433280704, 3916647210, 3042341804, 2761453879, 2077007662, 3296723936, 3466880283, 2491001159, 2109091000, 4073525474, 2496408082, 729984271, 4039357488, 2111341421, 2499441761, 3659919241, 1137617785, 1194350142, 3319664610, 2841053011, 3485613539, 3898686580, 2337910268, 529215038, 3933384825, 3048164724, 3392190075, 1198986188, 201875403, 3776454656, 3574314726, 508211398, 2990122727, 3462663039, 1258115643, 2862943783, 3952621480, 626721278, 354658674, 266436877, 2279900047, 4140177395, 3611401140, 720994657, 2619255647, 755150209, 1673688098, 1267362287, 1821789133, 510222616, 3931771335, 2041130289, 1196341210, 3372955715, 4045256105, 1539159220, 2187027664, 1289255586, 2507529354, 246384965, 101778058, 1336141232, 2030836804, 3555070947, 2540732193, 2281068220, 1082424123, 1850093489, 3769741173, 602125081, 3757503918, 604811852, 1052381749, 189435693, 3642461764, 1573464316, 2296426935, 2340526263, 1459850834, 2751113293, 4273708006, 3295958131, 3610793060, 2618547711, 2886178254, 3168984730, 3896008389, 2910684641, 1920019587, 1667878611, 1691252955, 3994472380, 2977338229, 2576984626, 1351501113, 3282383656, 1895943533, 3499135774, 1923355202, 960512068, 2164140475, 1409823362, 90738535, 863701612, 2347007954, 748064492, 191656587, 2411360951, 895287351, 3599283834, 3869423593, 996172278, 1343958987, 4204232129, 862186651, 4240883199, 3892297078, 3426320726, 3826202456, 1691966729, 2680477006, 1151773552, 3420034107, 478329790, 2776338319, 85306325, 301696000, 4020575783, 1047443936, 2434816967, 844360331, 1358522767, 3451833642, 277400701, 3790214849, 1600773312, 1374401216, 3587961434, 2218115041, 554687844, 1455373089, 2415557558, 4185944221, 3644298685, 813130403, 1803175896, 2141326869, 1993778480, 3229151677, 4022953349, 1250408313, 726142251, 4052078854, 1572753212, 3088327523, 734957233, 4140608595, 799532378, 3130800248, 3179102660, 1290963726, 3671626909, 2258829788, 1103104173, 2115377976, 2247341092, 1301956403, 1833471854, 3662831447, 1344786344, 2540851541, 554976441, 3985164853, 1538266468, 2085479071, 3369085596, 2283036863, 1880236792, 3210743188, 1521915907, 3358852380, 3074581226, 1752478027, 714306799, 3302922277, 2597012016, 4130751078, 4214555128, 2628587553, 1531096623, 199872584, 955170151, 669657590, 1894747756, 1734152212, 1353348674, 2319549030, 3289364904, 648833538, 1850063548, 2741510265, 878914348, 1757164095, 1912901164, 97276445, 1411832265, 838060298, 1610234873, 2723117095, 2609845475, 2259244006, 1261890709, 2844142420, 1147885155, 3369135375, 1613476195, 3417049767, 2537355294, 2053515427, 1399515658, 145763359, 2482971113, 991709643, 2138676150, 1818872095, 1302171429, 1568090509, 3275531750, 1497380322, 945407229, 1822760862, 4228040908, 1940517075, 230246089, 3963321737, 1138094364, 3400867993, 2181433825, 3305102925, 511506388, 3528785436, 2879653029, 1926046085, 4143670679, 1150191731, 285291427, 2685918049, 312767991, 4231911307, 1880157802, 2096745103, 590684735, 2432966875, 2116020629, 630495259, 2253830476, 1313727939, 2791912760, 2351981765, 3251513736, 2599152303, 2660227829, 124307715, 3135200655, 2482790133, 2271101300, 1989104610, 3073191272, 2152082822, 1971138214, 1045327, 659102103, 2885552100, 2565948175, 777943450, 2675195962, 348776090, 2995731289, 3758589532, 4025556286, 257655013, 1730311656, 3698180322, 2241973994, 568561445, 1188334933, 1946887145, 859125395, 3482471605, 550147837, 2058651912, 405932042, 3893823580, 1614629224, 3412449577, 651241210, 3061461973, 574810638, 71361216, 4020596156, 2396933510, 2356436008, 1248054342, 200369296, 3712728011, 4011870981, 4266142254, 2720800691, 4069057194, 2501639775, 2484471739, 434977093, 797544023, 2570613282, 3886296071, 1015700927, 4290596355, 859758311, 1174682680, 1562063833, 1324565576, 3332475453, 4073935411, 2176440226, 53930109, 1686994234, 3678627525, 3373660623, 747493144, 535648778, 3674317346, 1305675282, 1150814201, 2803793911, 2512646071, 771940597, 3647355999, 3368179321, 4058511426, 1217012830, 1798535844, 1737906025, 3999269518, 3424818174, 2089527288, 2639547497, 695593140, 663988481, 2419596334, 3462868145, 3475802818, 1753477635, 2527218844, 3145557245, 3911980182, 1533706830, 2097434290, 183240521, 3788929990, 1779682324, 3724458093, 3073497049, 3465759597, 1474943606, 1573286105, 2475506690, 3461534603, 4152775580, 3631550490, 1699689806, 3829642010, 1282316060, 2662021448, 472675346, 669363918, 2371875811, 1146052026, 1118224828, 2861361748, 2015009562, 2878512978, 2442465428, 3219237043, 83434832, 3214067809, 3404145170, 871844412, 2343292833, 2897770929, 2293007334, 513785118, 1366807188, 169985021, 1530708725, 463131517, 1546654520, 1088914309, 44472394, 3008593345, 2694951514, 2232781270, 436583961, 2935635715, 231976418, 741587681, 3448976579, 236186582, 4252390528, 472879255, 3229739022, 538200076, 1762392842, 1710301339, 56783367, 1961703833, 1674101533, 3944799467, 1107734217, 426021150, 450787910, 1135363928, 1422694911, 793598682, 3381976482, 3932766847, 1292864939, 1678995521, 2190978815, 2431912766, 911135553, 2831351577, 325868757, 802420541, 3983523312, 2559890678, 3857026632, 1885246049, 3146727643, 2765128037, 1589823584, 3065411923, 872021375, 3311812203, 881521209, 747137786, 1000063898, 4179502904, 886971834, 4080397638, 3665528562, 2249307047, 2450795045, 1536473676, 850174262, 3788478504, 150976104, 200295633, 2153651630, 2249578122, 3985317910, 1064906261, 1022848907, 4220566724, 3216656807, 870116043, 3758680505, 3705749884, 1139091108, 464338309, 180190377, 3552869299, 152240175, 3980504246, 4271460058, 3106014727, 2149379356, 1183751575, 1040186257, 3494088390, 3752192162, 2582668840, 2597589280, 4007048334, 1778752844, 99620680, 2641234020, 3386178446, 506319377, 3103448882, 1147167957, 377320373, 2497010457, 1000662354, 2868328072, 922615819, 3970174196, 1461002909, 3753696352, 593319197, 1532590741, 1875289108, 138731777, 499151617, 4032772524, 3122220215, 851080138, 262060487, 2672031422, 1097448973, 3189786243, 1797858651, 4244888125, 3819604663, 4081313171, 1832908389, 2377912868, 1847228618, 3104197710, 1112047092, 899391336, 25843412, 3238157180, 927329896, 3835265149, 4131266143, 3837840238, 4065666327, 2386113761, 1064968537, 2141571934, 4050080197, 989947624, 3228918065, 442069281, 1556500487, 308551397, 4271798672, 1012927931, 1974219749, 1471451147, 1122581592, 2557944616, 2776424641, 1726474870, 724419567, 2407585803, 399430939, 3202481237, 853574375, 4169880447, 2035965381, 3159142693, 4087427281, 4204744473, 2474028992, 3798061448, 3191976206, 3120499674, 3479294815, 1733377752, 3657201267, 1480888860, 2961598821, 411586368, 865110282, 2341972482, 2344688435, 2421214281, 1570048415, 2896452877, 1277537301, 2283577309, 751577431, 449046766, 2378532630, 2595133499, 1063829692, 4188088082, 461333493, 1908087872, 2658523609, 3569418974, 1070871225, 2357598817, 4292134786, 3476191658, 2805937374, 403338560, 1212974003, 924302178, 625202418, 1459471363, 655272954, 545977887, 3925403669, 3905429650, 202344993, 1022243223, 3519555225, 3995996715, 3495955340, 1531262614, 805883967, 552365643, 824579115, 352329222, 2214775478, 1141873437, 4176338150, 2431351884, 3821463016, 2241018444, 1830341716, 4281293374, 2632577683, 104553534, 4228525818, 81311374, 1416321600, 868978934, 1556952824, 2506428984, 1605875665, 1028001984, 2071100053, 883637341, 3497247423, 2859438818, 2035817804, 1655619706, 2876228696, 903008988, 45752216, 3179847931, 1654196760, 4191521402, 68775206, 2067177360, 1755767049, 3568557060, 4239419860, 3514957631, 3471866719, 311987081, 403749913, 1261293110, 446382351, 1483679335, 2692556303, 146604582, 865795316, 1833151165, 870688614, 2467816272, 2449912450, 3430026814, 3055553592, 2460877343, 4117618048, 2400028590, 1902522093, 1090459846, 1037099175, 3719648076, 3190107914, 2683135016, 1231028497, 4027483771, 924307969, 801053376, 954497527, 3347069242, 886000463, 453530242, 972468416, 3035618670, 1594272021, 2700569422, 3793393799, 1518016174, 2625828448, 1984364244, 2136657614, 3775705358, 676668216, 4036059109, 3871682951, 1295429007, 290889627, 4110067154, 3565163083, 189319471, 2176690992, 1368068628, 2861883430, 297404302, 1555651386, 4283682929, 2078440612, 1530250824, 1007971128, 3074660650, 2724633898, 3129535048, 375590183, 3617921628, 3123163094, 2604938584, 3091482218, 1578248319, 1804580725, 3030194226, 2158090275, 2223882595, 2836244064, 1162211541, 4144942976, 3721042806, 1647757766, 1447025305, 1118891857, 1563361770, 2309821167, 2387329512, 855463165, 769472501, 1489521344, 3369561939, 2274906295, 2125752596, 1787159736, 199924260, 1780938880, 3649141711, 2340757833, 699166103, 1746203973, 818394345, 1125628807, 2542356884, 4150623740, 1888868286, 3745774934, 2128521740, 1918735504, 4064631087, 3564585770, 723018111, 207533877, 1133081391, 3880643558, 3976896917, 1841086146, 2888834682, 1737374656, 1703611383, 2012913400, 694766250, 3861321783, 2516192867, 3761835775, 3343643163, 590603614, 1385290112, 2700600120, 207214751, 2371677819, 1210343671, 1728112455, 3720216384, 3903650715, 3561837883, 3177305787, 2355775836, 3068608053, 1887582056, 4190357576, 3910654511, 88819933, 2306809855, 1332041550, 1050789271, 3469446146, 2488469708, 1416544857, 1425028521, 2747872322, 3129490163, 2564654546, 1587932947, 4261106204, 1620978021, 2257130639, 2819418418, 52714980, 3418522356, 40167526, 4134923373, 2539755532, 3064981812, 3387538608, 1012034832, 4241330628, 2329203924, 1099862144, 292732436, 2017940373, 2397577521, 1582076519, 2960516164, 2006032264, 858932757, 1391187597, 1373080359, 1172877124, 4241912676, 4134947311, 2367655641, 2375764648, 2393945667, 1825712583, 1906250637, 502204827, 1233539319, 4013594888, 1959712448, 2552663179, 4227809025, 486479310, 1975104978, 2896563986, 551237600, 1194609747, 3075900028, 3061335793, 2728762768, 2955419238, 3589869325, 1888973202, 852008308, 1917501497, 1625287585, 298893075, 2076272664, 1843055430, 263190501, 4148349679, 905113736, 57762247, 2231089523, 2125301642, 807837564, 2834619161, 3845495969, 591906810, 1100346851, 699291254, 1715817360, 2427638743, 3840867316, 3932350493, 3412282614, 3694900426, 2807704524, 1066636475, 3438115659, 3355131770, 3341962062, 3262708171, 1232960254, 1869251006, 3525364421, 1547705609, 1528968807, 3767707767, 3237184893, 1556181875, 1960589866, 2668826245, 197638116, 3510004367, 1498061377, 414050101, 1868279989, 273436188, 2937861546, 225967853, 4178355034, 1653778860, 302857263, 4291922353, 3060239340, 1653754556, 2992964514, 235006151, 638877560, 3373103168, 2014692868, 3132811322, 2993012887, 2015301852, 4036277177, 3788322771, 1042860784, 2268227965, 25586980, 2307365481, 172888216, 4196345828, 579281005, 618139269, 4217291893, 2306625190, 2693052733, 2154636683, 2948735822, 2120515448, 1279430119, 726555353, 1213908688, 803633496, 2302786543, 3417413164, 3876465323, 1796216538, 1069420612, 1, ], &[ 1988498380, 3050132581, 84001963, 3445692001, 2734783387, 1774219496, 2162032114, 770345120, 3457703796, 3559428633, 4257360364, 1090466591, 3567817053, 2497380424, 3534691541, 1279435419, 2742018051, 2205075879, 641106, 1754923528, 58973331, 1715000559, 1117715270, 2272741525, 2115935795, 1483835360, 1296235, 1796957756, 3968651424, 152068196, 176938861, 570875261, 3336099773, 1193842175, 3048757774, 764666488, 3843941623, 1548464729, 1897867882, 2878929765, 448571520, 2406065734, 3568376411, 108079736, 153179622, 376615879, 462260105, 973865240, 3413391101, 2811718165, 3572533591, 3909460695, 3134008033, 3897396582, 1040616570, 2998174467, 4068999806, 2523162074, 948788147, 2600716643, 3959424266, 2966714, 526886335, 3296693425, 2243375988, 4143935802, 1111766991, 1144066805, 2311007495, 1010976381, 845073483, 1135483459, 3990880342, 294797346, 2679966602, 2533930988, 1664564718, 268281267, 2092673357, 469524764, 3945653712, 326073803, 2694037849, 3507600917, 3290201609, 121045908, 22654279, 1505718612, 551101589, 2556674091, 3163892929, 1910818775, 3418844366, 3372741206, 130020156, 715267628, 4274925122, 1048026555, 2835427841, 3505581892, 1602295761, 2414351668, 1553499591, 4229635398, 2519192505, 2021787900, 2301738189, 2691817702, 5305850, 1565221152, 3538706617, 3057801765, 2874943612, 3131932103, 2612726193, 1166707551, 2820888127, 3160538692, 3124232750, 481384322, 2617755783, 3630694751, 1672329146, 3497041986, 441500257, 1563794131, 666530710, 1149258814, 4274365529, 169180791, 4187510295, 2714548495, 3562799169, 2904591043, 1774457729, 800521106, 1411048330, 2663300606, 22655328, 3774883767, 3819965706, 3800295936, 3668492475, 1379825015, 4213938165, 1132023495, 3760304231, 2917225913, 189390673, 1938798483, 3140766517, 2153396970, 1928404388, 2785977327, 934591575, 2405323840, 3637359453, 981340132, 242310679, 981811654, 2288564752, 2987925303, 4031514738, 197635692, 2859303437, 2533609681, 1151769485, 2644644277, 2635940433, 3366453887, 4277743333, 929550085, 40133408, 1833321431, 2429701519, 1464545187, 3066929948, 3904082769, 373116082, 2430829492, 2571513045, 3885018135, 603068030, 1172828581, 4065558289, 1163895893, 2468059427, 1548489900, 1717402470, 4016751470, 1013738008, 1034029588, 3482329597, 3435207029, 1673410325, 397717038, 1500823297, 1911172810, 1420629560, 3358784452, 1312197637, 1152173034, 367120884, 384630941, 3440282377, 2522765605, 1597847376, 2683717257, 2561199311, 639683785, 3817861808, 463544224, 3991704969, 3376721583, 105154089, 1533594425, 335823085, 1107739913, 1452695631, 954081147, 1472744072, 109401385, 3210541127, 1847806577, 327707567, 2422910059, 2867854042, 1286261864, 2777291397, 2491134001, 1866376440, 1442628329, 1148774257, 327348168, 796722022, 1651402005, 2839518531, 707220227, 442580375, 614584592, 4054371638, 313021875, 3191805300, 2207878775, 3933190445, 2035546077, 381129617, 3161098198, 1019615010, 2743759521, 1458405016, 1891243747, 3502084250, 951344904, 2669441803, 966435550, 1450947158, 2445618755, 2629179958, 1786188217, 1157343233, 512400759, 3058846955, 1691540553, 3902487730, 53457416, 827127510, 109080803, 2065162700, 2595989450, 514516885, 3571421189, 1946474067, 3695201586, 529285628, 2120794437, 1831163308, 1518439076, 3361874260, 3805558145, 2288973775, 2352901588, 4206307376, 1343461937, 1115914255, 241429811, 2386351727, 3283851422, 1570726296, 4171557460, 2197857248, 3493510408, 2254067927, 3407035296, 1925479341, 3186474620, 953208782, 715061374, 1181448968, 1220358590, 1370257748, 2925654278, 3323438388, 1322650109, 3766704524, 3870430557, 3257441173, 2439781482, 1554488089, 800150735, 1514175574, 3153400949, 1583649143, 1280421056, 3882604400, 2181270798, 2782475677, 3148486479, 4071326639, 1764147111, 3505719068, 1862656169, 1261162987, 2211270974, 3217710591, 2927566184, 4232715549, 3582658271, 1363726747, 3233373581, 3022128605, 3193686951, 1851291940, 2618042857, 2848579530, 4293396464, 1928252986, 528145280, 300907511, 3891802439, 1267856769, 1165928777, 4227625628, 540012700, 469250948, 966533455, 2875072197, 2230103081, 2000106078, 3086794985, 4244235827, 3081744548, 3713073740, 2925851679, 2315339278, 2558156736, 3723155058, 3227292432, 2941681952, 4041413976, 2097513703, 3042683335, 3624088138, 3936977773, 2820887559, 1664662915, 2334141648, 4092839529, 274159708, 4055649255, 3512716978, 1365039076, 3916570667, 2158939813, 403036637, 942532489, 378445989, 2167306547, 753402418, 1193358264, 3877024670, 3743152347, 116435136, 1948333248, 569098908, 2922999784, 917671206, 2718173867, 1010784137, 1804409345, 2242631895, 3989814639, 2044343096, 723486672, 1841507274, 2333301606, 4260854855, 2763867469, 2805327422, 2351089720, 1719837442, 4008440919, 16200186, 1228294632, 3833322142, 151876299, 3340352893, 647820547, 3228338641, 3940895065, 1697980005, 2505263582, 77077868, 1311758352, 2346165371, 2652028800, 3480066477, 1481299332, 2948248752, 501377681, 3276784059, 4102724530, 1207318829, 2947644680, 3069480791, 1116349810, 3395241135, 3570300879, 3836110678, 23881082, 2523984619, 86893874, 2919930037, 3241130876, 3697730978, 1459589531, 486161579, 3036213671, 2106273230, 391770200, 1135761788, 3542580424, 2902564186, 4169447111, 1908429065, 498329772, 2010302804, 1930725702, 1614128757, 1901201146, 2340750074, 2621544559, 1554979341, 2490973900, 3039157328, 2525878574, 2064002895, 2981842962, 513591182, 48663763, 346106995, 1067873617, 1664056855, 3497080122, 2640223678, 4006771320, 1595836468, 2008498009, 1036368219, 238997308, 168075897, 876079826, 2934854956, 1075263443, 3803042525, 2802898866, 2169905202, 3377165843, 2465797619, 1978983742, 2322310751, 1590628498, 1459551643, 4156365433, 3054380889, 1819890111, 2928185712, 2553214234, 3066671630, 3394771139, 1734126526, 247246953, 3320484300, 579355057, 1177404814, 1327413352, 2035170753, 1052379386, 3339678481, 2430828601, 3360847369, 2961791848, 484983472, 3181472945, 3105431626, 1283580906, 3703197182, 1961222326, 3649286491, 2664156595, 2335129028, 230491131, 468504878, 3710487036, 3159611165, 3544126878, 1088644958, 2961497435, 2785759884, 1537524580, 563225344, 2114093362, 4212602497, 1169631938, 2088081811, 4006629680, 3089709789, 3749609771, 1969435408, 1786420402, 3870446123, 2169555554, 1571013574, 506991779, 2174983408, 2376333115, 1813451470, 2875689985, 2056697043, 2022446139, 828430986, 710475734, 785980495, 505758805, 3139780897, 3708680832, 3390307357, 2434318195, 330093210, 3019701899, 3546042185, 202048370, 3017694172, 3813711930, 1950710894, 2336832114, 3123649938, 3799964456, 1278675670, 1776925346, 23381263, 909581672, 3084101661, 1592521095, 3095643203, 1245783006, 917301336, 1175072489, 1493603974, 537178477, 3098462691, 848961674, 4083634813, 485866548, 2460787176, 1957075662, 1653349530, 193311723, 1510554197, 615759127, 3054909658, 3810118423, 3275067767, 2822189856, 1822027915, 641453111, 3902949794, 1707895715, 187255999, 1547540130, 3996925138, 3744594623, 279929032, 2815355330, 1197018567, 334914949, 104288985, 152451615, 2257137946, 495821725, 3891425071, 2698902656, 4248123041, 3994796663, 2283493355, 1792145295, 771358160, 57983054, 2699162282, 3252719646, 901108453, 21411013, 1214186627, 3971974103, 4284646962, 505661368, 2014789373, 709655680, 4019528811, 3456428712, 3896941342, 25228952, 3267679573, 2554048052, 1140488725, 796840032, 1008803984, 1769445882, 450164846, 183418978, 1557823191, 2205206958, 2186287277, 4041341207, 2277585274, 2647704834, 3299210809, 465486816, 81165601, 3688958209, 4134919427, 308497409, 1670228519, 1054621084, 3997139209, 642331675, 877436795, 3750152836, 2099953927, 2407318768, 4064392686, 3499776748, 2890558934, 4257002037, 409497686, 1871363314, 3488166608, 368834184, 683374402, 3315975032, 3919319927, 1636872711, 3746724350, 411713899, 3127168268, 1541472093, 481068370, 3914726958, 3809187727, 1019234471, 4257529799, 1795024406, 2169201644, 180192691, 3146544995, 3086567728, 1371853848, 3442647104, 1956649571, 3221872492, 2599010979, 3825880037, 129532942, 1962882180, 2981643769, 501519665, 1104150124, 3577388513, 530338682, 2379351921, 476796974, 2079075205, 523122306, 4175790511, 1769173929, 3684943051, 203952644, 2367960727, 2956929713, 724249999, 3868724734, 3128867062, 788369620, 183457300, 4030548412, 320471199, 818557389, 3673114423, 3427092352, 965641427, 4165737446, 546271097, 3179039741, 1968478116, 233505213, 3523513681, 3185397073, 1639252860, 192368536, 2476919576, 1286359266, 3468793964, 3927932569, 1554017778, 381977140, 2630912557, 3248408028, 1380148387, 434027229, 3679247941, 2320186711, 4049616334, 1306803801, 3657216807, 4072237788, 2409653033, 16652557, 777239076, 3435314631, 953899982, 375200832, 3240441496, 1403201300, 3463532889, 2152357282, 1492290956, 1756116611, 2979347831, 157726282, 597994889, 3571510881, 4022595441, 3689069225, 3371053456, 1105664287, 381184864, 3760869170, 2128986335, 4138730626, 2108903255, 3330167716, 1193420433, 4081108869, 2371248791, 2008259868, 329286806, 834934063, 1587339743, 3835392552, 3027794970, 2946227510, 2759445311, 4153403869, 3246082301, 2169502676, 4274409702, 1618245891, 3538641406, 2440237498, 291928949, 1309678695, 2248858018, 1259269551, 3062553916, 2375747923, 929738114, 3593316299, 395934754, 1240422334, 403599738, 3596058407, 4199195184, 708535732, 1045565478, 2985960024, 2935035441, 1902361158, 1360356647, 655818324, 1464367881, 1402852252, 1605910196, 1553177831, 2270937291, 3867336542, 1242299751, 4201495317, 1894193944, 2952284338, 2983597634, 3331327699, 2688007694, 1534358324, 151501193, 874435351, 113820939, 3053243228, 2461547215, 3493411866, 2931307581, 243458129, 2419713971, 2259098050, 4153522826, 1347753364, 789286836, 3723853308, 282228699, 31083181, 212832201, 3992535406, 3841973318, 3150180785, 966530634, 1983757001, 4224102508, 4103842551, 2315916292, 797697662, 915301841, 727577536, 3413485655, 917582931, 843507358, 1529131982, 1843003612, 3002449886, 346610535, 991891575, 2565267970, 3912371508, 2710618386, 2330075864, 2735484155, 2546043717, 3241769509, 2210455214, 4169254026, 1482724431, 674379398, 565771066, 3142137141, 515638418, 939683105, 1345730468, 2404207571, 249108973, 1883806778, 2156914196, 1564711040, 3370156804, 1857590348, 1147780810, 3733908955, 2181248732, 1904993207, 3694175594, 619779923, 3491824168, 3612713452, 1216174279, 663457690, 4014509322, 2569761593, 14109664, 1828397087, 2936522368, 4158885908, 657033012, 3173212007, 472151655, 684251460, 4075235611, 4224354174, 1004777987, 505536516, 1454022092, 824505586, 3067613896, 2235424889, 3665322087, 3481517352, 2363451123, 2771040650, 3235122422, 1154036889, 969497501, 2563704447, 3797108, 1395020021, 2762840789, 1908946824, 3014468569, 925225402, 1138335619, 3624023401, 14380823, 2839985590, 1786726385, 2046596657, 862236402, 214661254, 79111383, 1583211853, 1641485501, 2710635102, 4088715922, 3860998541, 1323605849, 3597942622, 1491675000, 1599602967, 3388494990, 3354632479, 2528582795, 215618636, 394082738, 1141528681, 1784788922, 1221028471, 3234711669, 904205099, 1676230442, 3127792899, 3994795553, 2452526892, 2165805680, 1335373003, 192721187, 4240993835, 3133423197, 1689272558, 3673814847, 1422539041, 3736049673, 1833170900, 282944559, 2338828666, 2779222702, 3327509347, 103394172, 3158363803, 1906876457, 2941521396, 4107834947, 3417951529, 880661309, 2072508295, 589009441, 1335393037, 4277398556, 2493403024, 3409655003, 3109850219, 1180552996, 2381399690, 2298638016, 3501746890, 846617313, 2905524779, 2707401285, 2041915730, 2296396459, 1041902038, 889847207, 1989421094, 1389388870, 3827587250, 1783862700, 3828138938, 1868614698, 4248902541, 3581264817, 3916285777, 1776264454, 2214767964, 2937276417, 1736659895, 1395637227, 280854206, 226975266, 3550562380, 1121092319, 159004679, 3748222278, 1260252989, 1422903228, 3336410666, 194417341, 2723594163, 2281242077, 1784282179, 1034680840, 1402111826, 335654645, 294940873, 2853511062, 378984905, 2532157416, 2195182123, 3873081897, 1625154299, 260395831, 3540310196, 4273320806, 2622305394, 2711543735, 200100618, 3414809217, 2926348222, 1329786033, 4245332557, 3574371092, 2777917577, 321179615, 3642895588, 1496048120, 797710555, 3671936109, 2438718323, 45015662, 2137354414, 874208938, 3450439142, 1916685905, 1662667234, 2856738964, 3829688032, 3404462996, 2848035045, 2061762938, 1260861712, 3010572066, 3394836279, 2342878342, 1271875691, 4111464444, 2126598368, 2380694046, 2430271490, 1145499017, 3787409979, 1555528697, 3376084869, 642452482, 2589187231, 1081315770, 2087941360, 3364823763, 3805619618, 486395332, 908395706, 2499268457, 2420556587, 474512813, 2481646657, 3492741661, 1968018988, 1074530387, 2014914730, 2803826225, 3220982875, 1438277839, 2775829138, 1528403642, 3794191286, 2608342366, 410785526, 2637600256, 3490750019, 1440381245, 814635701, 2260916755, 2650730282, 415890751, 2524080685, 3474570208, 2446217936, 2397550701, 231181743, 736834280, 1383997656, 1496783958, 623278112, 1645711091, 2659144562, 2936379758, 424018844, 1549465529, 2669736270, 1664977313, 1523334854, 193915346, 917134660, 1861003559, 2211424692, 3594457673, 521847126, 2663400187, 3341032570, 1640978768, 3374727890, 2984430165, 3295971473, 3727310438, 4148801904, 2931771022, 3471915299, 3774018978, 243266066, 719450229, 786371556, 1967721517, 3662692002, 2660462613, 3406551440, 3689369626, 4170908863, 927580754, 1492537107, 1444056133, 934562830, 964303678, 1533941876, 4122966823, 3705199737, 1112924448, 95199848, 343531614, 594658489, 808416147, 2905432520, 3584653211, 1387698320, 3110254075, 179755886, 2585492770, 826193502, 633023598, 1166009098, 1290016012, 672935203, 442560997, 2496163987, 4194310358, 522918013, 4222433924, 1620670288, 1584642952, 1110116518, 2050444989, 3738181405, 2449666200, 1322361471, 3346873860, 1704204055, 2765918523, 1681401174, 1734783149, 2990922980, 2845873797, 2655480068, 1134013632, 627992748, 2305459149, 890878648, 3702690433, 2308583593, 1647897272, 3079544696, 2470471677, 4040208261, 2073585273, 1793034905, 1713771355, 2220715251, 2553773388, 1442482611, 3113497415, 2768408881, 1270025121, 1399831313, 1630862433, 3377364946, 1442504714, 2789927137, 3191151633, 2578873407, 208337033, 3096561372, 3943415949, 3118056636, 1664092654, 533371474, 1132049460, 1378502069, 1205939688, 2646775436, 873517579, 3647947118, 4249353240, 1234899426, 3562671303, 1028908207, 3806236229, 2688126461, 2379248861, 4273316716, 1028554767, 960050373, 34458263, 2497415615, 2000699114, 1654490516, 3970420809, 430138864, 2839090700, 2992085491, 2048751357, 747829112, 2102051019, 2747342438, 3939874657, 204736053, 132477025, 2895769009, 4049016784, 4006488678, 3010059929, 3869487365, 820665998, 3637576575, 1400083196, 3176270933, 1580718861, 1862589245, 3687231820, 2811111046, 288642712, 2708675068, 3659920550, 1043267703, 2675211709, 2471783225, 3908671780, 1796097076, 3884725302, 2618455344, 2727437605, 3198512809, 77833978, 4002905580, 2475905855, 4285041054, 1379496519, 2810710199, 3524329171, 2422823286, 3888601537, 1921960588, 4141779429, 3945205304, 2680621131, 4186120628, 1952951538, 2875169441, 3303243339, 574383361, 2010030917, 3924461786, 1497240891, 3972138842, 3082719894, 700821923, 1225799274, 39941891, 1579154501, 2895091775, 2026419054, 3180814760, 1239600240, 3443816247, 4103641786, 1778116375, 1356356349, 3003002432, 2464906412, 3106084532, 620250446, 2199567717, 4285388064, 1443224417, 1183702872, 2361871288, 2889920918, 151923059, 3665604400, 902272748, 3673929087, 777413599, 2880183228, 3116820884, 12649513, 2151951398, 2517689255, 2603024997, 1540902312, 413276528, 463295145, 1270795006, 3197387059, 1235198896, 1591251569, 1536841283, 183104831, 1099570929, 4157586543, 4245916264, 1187513801, 2725120513, 2263045835, 3616676335, 1441932591, 859970322, 1785738074, 2632201495, 3074325275, 3739260875, 3210655551, 3115242275, 2776972168, 1857654859, 3388697322, 816121986, 4034608581, 3645370625, 3901309336, 3655082618, 694485749, 2189293828, 4003306605, 2104718709, 2248125819, 1242466666, 3425122185, 2526773969, 1997783773, 3366295660, 3638946293, 236310604, 3074020533, 1544508523, 2720105666, 4275312048, 2125511485, 2928099726, 3115904574, 1659470574, 2302631502, 2782437446, 3351759933, 3997936888, 2966997408, 3158966556, 2819300721, 1647111112, 3003598038, 2858959466, 2179510155, 2584211049, 2202151208, 3064305858, 898246753, 1503685985, 3011437597, 3645693595, 2240988222, 3440343576, 4238868402, 3504605984, 693969911, 37266154, 53849195, 240646457, 1676768678, 3078948456, 353299888, 3398599422, 1225876435, 3474721352, 2919885255, 1645273187, 1329251097, 63136291, 3744051145, 3578975497, 743346836, 2992151082, 2097992510, 2029339826, 1064760489, 4287623009, 690583934, 2137261889, 2523731672, 2989051237, 3080671706, 891097198, 705467787, 3974619780, 2507988307, 3580098689, 2900468355, 2065761093, 1093422169, 3699292714, 3679511724, 1376356943, 190833907, 1757023356, 2392875706, 1341718208, 3312756053, 1335629721, 3842952633, 1585023162, 3483717351, 1166983906, 3797224124, 2704194560, 3663191348, 1943345575, 2900370013, 98538425, 2337184175, 665720157, 3985681094, 1514818198, ], ); // - bits != 0 and Barrett condition in limbs_div_mod_unbalanced test_only_verify(&[10; 19901], &[10; 100], &[123; 20000], &[123; 100]); // - limbs_div_mod_balanced, q_len >= MU_DIV_QR_THRESHOLD test( &[10; 2283], &[10; 2648], &[ 3352941598, 3865259069, 4100372468, 1153884783, 3551739464, 59160376, 542012042, 2236793144, 552149400, 3785998871, 2245653521, 2409739829, 2573999247, 3383580072, 3537839900, 1800846733, 3935526498, 361012784, 2531357419, 3553113631, 2410557200, 583408141, 3768359305, 3429382207, 653740782, 2770578614, 547505820, 3799199419, 579588554, 2311425149, 389629528, 1207262435, 2369107295, 3706674098, 3539705585, 1291978910, 48205553, 3769782509, 116475615, 3232605021, 2340006404, 3412987383, 1384309659, 2215239759, 1942462745, 2588181253, 2684650591, 1257320673, 4277802941, 958808384, 606057277, 3147308225, 770499239, 1471078323, 1270490723, 1467056681, 1895212705, 2201929338, 2102169879, 3620413218, 635666763, 569457881, 3894059482, 2680054308, 3602399856, 4134893864, 4290529946, 2930760993, 4047561930, 2289637023, 3542709032, 192324913, 2131616688, 1889179343, 2830556125, 2071197973, 2105996730, 949597522, 897750365, 70094343, 3723815252, 2416305558, 1343266059, 3370097189, 806498684, 206432944, 3041278862, 1744541256, 224141755, 3110999564, 3362772841, 2421877055, 1717381634, 348336738, 2637922202, 2392853940, 3292333937, 2201713794, 2114914809, 1121818844, 1870800821, 3147561780, 3324016521, 1200997507, 1342809995, 850923048, 3583522625, 2731648896, 2594584541, 3890526868, 2599265209, 2411009154, 1774254374, 532444790, 2622092896, 3509086892, 2563255478, 3507174912, 3134562215, 3573536461, 3803846265, 778670720, 2230332276, 1697423243, 85700226, 969711479, 3505043587, 3297200562, 3609467049, 3662693589, 1818999322, 4028100981, 4171049232, 2406321492, 2679681856, 857327639, 3423532043, 1257720770, 3090300222, 188156280, 3651878387, 2836134823, 3082809968, 3017209674, 2994744466, 2209427910, 2161073841, 2518334235, 2747949904, 1514181761, 2963843535, 270222615, 4096734680, 2099374675, 1696553128, 1926409097, 3454305722, 1118607235, 2127714518, 4097359941, 1136116769, 1071932743, 2900390949, 442288212, 3866263192, 717449078, 909539744, 3089568997, 1780473113, 4109927051, 2885887984, 2499567691, 2657115664, 1600427383, 3916185142, 1159449752, 3516682650, 2230663677, 3808047887, 3311279083, 1113070132, 2694645626, 2405191541, 102053937, 1253521286, 4264380542, 395088166, 4244788789, 737121534, 1533918350, 1421656021, 1823064241, 4285578303, 1145239996, 1373063198, 1447479413, 3110566560, 2228989155, 2568955150, 3091730457, 2167077931, 1000704813, 1365724058, 1622364628, 2600037337, 497840569, 1286515240, 1963466706, 3435274784, 1444436503, 3072121470, 3528252416, 3499581434, 1487555088, 2939147354, 1884571487, 568110034, 1867883974, 3613945741, 2941248381, 3062867723, 1051501799, 1341244124, 2776237803, 1573493621, 4261946497, 1174438344, 3969798321, 3102138455, 727003024, 2176697125, 410088182, 1687162110, 334286567, 476511714, 1268317677, 1366540862, 971968086, 2138545348, 314951050, 2549414696, 565905760, 752921380, 752912976, 919710852, 1747578544, 637407331, 895745615, 3928514299, 236178919, 2099477779, 2964313723, 3735673656, 2936293548, 1281316406, 2181151134, 3376904737, 3557977206, 1928051613, 2852078038, 1824332746, 512024805, 1603493621, 2435305148, 2144349581, 1331930562, 3278175766, 1538591372, 351100581, 3662257053, 3132051881, 4014279503, 3747909981, 829713073, 210609157, 3696228065, 1740580647, 4134052799, 755637464, 795323419, 2849194170, 821499939, 3879325297, 3763047250, 943359378, 411631726, 4062170203, 268447990, 41972768, 2368084446, 2195089954, 485925597, 3124084755, 3180106404, 4183765083, 1541224878, 675908427, 2052803359, 249079602, 3524972440, 2170545402, 3446583891, 3710920834, 1942843298, 1218812510, 1382515762, 2725872755, 999055630, 3177157328, 3721528640, 1836334439, 2344692655, 834120671, 3024104186, 1076667078, 1133950510, 4188852844, 580162168, 1918097294, 1770073085, 590997459, 1210599652, 1632475170, 3051890039, 42749444, 4269218580, 2222311225, 883198162, 1888411854, 4183890545, 3246570683, 195442368, 196037051, 974729437, 1342078148, 32826947, 3572916171, 864015929, 295109535, 2224357476, 1361921758, 298048697, 726601358, 2826594017, 554358481, 966095240, 1972650035, 2817068489, 1969200190, 2467562829, 2081888672, 2831836860, 1790053370, 1806900511, 248405477, 4212079279, 2050637813, 3530389869, 3211759308, 1819585111, 3529543975, 41959328, 1229293924, 2778327079, 3410107750, 1442913286, 2637085780, 3883716744, 4045095498, 2205587602, 4281963295, 2631929941, 3285243142, 1613783652, 2182382436, 285809098, 1288018550, 1703517393, 2680782178, 4260228630, 2930513450, 1616109485, 773198330, 4287295895, 1236258458, 461840545, 2803605868, 3156784273, 3166478490, 1801557871, 2904634333, 3502927223, 3070532647, 2198772324, 381276809, 2943658000, 2148911850, 1426315320, 1005257343, 4276366730, 2202788903, 2161973870, 3609320518, 1461876661, 3668805867, 2080797435, 1225245034, 3735216484, 870533159, 3529202324, 358216445, 1990249735, 3407662275, 1313139948, 1381815569, 1818671019, 1762902291, 1548317770, 2642568638, 3157152070, 962148359, 3249314108, 3285001996, 234560851, 2533219266, 1450736514, 2328971594, 2147646886, 2911182861, 289496119, 3820875108, 1613803218, 240307579, 428421238, 1219773262, 1375112614, 268056704, 842341040, 408523626, 847433923, 107050208, 86686181, 2890182805, 1583672238, 2043054348, 2975392387, 729830685, 2449742790, 4196893844, 2272991634, 447829360, 904418846, 3769077942, 1428195213, 3927252138, 4021669144, 2881630524, 323590000, 210792473, 194270793, 3020394847, 765483391, 349124164, 2615178332, 3314188419, 3822943107, 2988433008, 908388966, 1922979134, 982324796, 3165493043, 2849765788, 842972206, 3591780767, 1395976813, 3228082170, 2792837035, 3191784579, 2660042933, 1748797889, 1321422746, 3145111502, 3141814433, 3652370786, 591050983, 3494741231, 3350752369, 1421763191, 3132442705, 558545178, 975892805, 341911030, 656356144, 2286165340, 450346669, 637140221, 89072045, 402213236, 1975885020, 3285218084, 2193991887, 2011954846, 2606898818, 3436080580, 2926281199, 55934162, 817769705, 287501970, 3676724976, 1175741578, 4073198053, 2495889009, 3073551599, 3155339747, 3969770190, 299485369, 3168323564, 580294856, 2875848326, 809536699, 656115601, 2114309196, 1654373062, 3712639373, 3130293194, 2807928548, 2954498836, 240485275, 3113332823, 3086822109, 1702151749, 3175011934, 4181496971, 836977696, 3745555232, 2371262786, 2867226506, 720581270, 3045708244, 1733608256, 3465966605, 3677990793, 2314229597, 698448638, 2489820843, 1526372643, 2027666288, 1707567327, 2734820117, 771109161, 2417603233, 2694932721, 452911264, 661420216, 1631366353, 4011280330, 3480917150, 2392724203, 770895055, 605594002, 3677652265, 1070596605, 1695550370, 1520192671, 3480373122, 3550693150, 1315349952, 416034556, 3771261849, 4194856143, 2851623790, 2299561959, 1875357982, 3295047991, 2579162284, 476437292, 2621344047, 1994816148, 3905959610, 71550537, 117252386, 304043394, 1873648084, 4239350106, 3199297662, 3310636359, 2954431106, 792209675, 3870777325, 1853576687, 3581538525, 433574806, 2860924556, 3390621376, 2368554871, 627364129, 1574995609, 1142271456, 1569717699, 4094936125, 2944660699, 43018112, 2512847729, 2019324938, 3901821844, 3420172849, 151080197, 4016039285, 592588830, 3906756109, 4224187012, 301712264, 1658594148, 2249329290, 1292403150, 813304860, 4088931985, 1585941827, 390195485, 969134553, 429346518, 568274453, 3605800519, 1487806472, 2714928861, 1045313889, 2638728579, 388915952, 270137007, 3010641250, 4034539301, 2350307082, 265782436, 2132362406, 3998149319, 2667174578, 3076526276, 1383452424, 3003910302, 3125664737, 3778790933, 4217219395, 1379756451, 3479313901, 2060882141, 2023484131, 1770391098, 1902931577, 1138972185, 1452977171, 2976115132, 3054397980, 2628446996, 201510624, 1412377429, 3907225543, 2304879017, 2142288120, 1086991753, 2232923429, 1479196079, 3572928742, 3543916016, 386405050, 719851631, 1870310482, 2962941579, 1883689338, 2676428384, 325734318, 285783456, 733481369, 2288445534, 2693091674, 2379843793, 205284521, 1884435247, 852671716, 2325353908, 4124913230, 392937477, 327089835, 3062247560, 916672747, 4156917521, 3082343686, 2693674622, 3446490976, 3436686617, 247823536, 1859601916, 1162033593, 1057243325, 744353288, 3435250176, 1935338485, 3028907291, 3961675510, 303110937, 4007030239, 3605372969, 103872478, 3052027611, 1081381736, 3561624671, 2918477489, 3971020070, 363648285, 3183344665, 31806155, 232323427, 4017720528, 1954445749, 2050700022, 4205157578, 512705308, 381960300, 1731331282, 83759392, 2828421050, 2274470436, 494185741, 3400884913, 3811076252, 123814107, 2965005277, 1477118286, 3339701951, 1091278307, 1116337920, 1418768144, 1581978167, 2613621202, 1223672049, 181842720, 2767416127, 875394740, 1142663941, 1729589357, 3090510457, 2184462714, 2428219712, 4214716589, 4247769652, 611414190, 1045261582, 3393575974, 171426311, 3441038236, 3066029567, 1498812939, 1839959393, 2321762739, 3099316323, 67890600, 3996080557, 3993720333, 62433539, 1468624962, 1788898782, 1972996857, 4174341914, 3280590419, 2244731930, 3556666805, 691033915, 3208212556, 830813083, 1560342479, 1134321379, 2813257340, 2482755860, 2646521539, 3584723926, 3446624641, 3625856671, 673792232, 2939933598, 1991301800, 1276891074, 3316991229, 3394991590, 2609715024, 1018617151, 1031310709, 1932593857, 4237137128, 901129393, 3082376671, 1433662587, 400269957, 3727171113, 330909419, 736956423, 4168039731, 808990789, 3150079653, 239610305, 1359468908, 3231418820, 1068230593, 1979002685, 2592886371, 640867886, 3044611728, 3787517458, 1024767066, 3213575946, 2698388841, 347657989, 4221105184, 1779863053, 1046341482, 1812302311, 3656596638, 1724800455, 3703046924, 751974902, 4122226429, 3738981746, 3671275895, 502862348, 417110769, 1973326978, 3615811973, 638559911, 1155883350, 2422515487, 2718728830, 1481097457, 1479175209, 824381311, 1858110581, 2364677028, 2080382672, 1505406194, 3993956365, 2715420718, 271231652, 2941588080, 1950700302, 3846220322, 1419598607, 62770719, 2939727949, 1569073417, 602595177, 1245626305, 3359798055, 1703355349, 3690743168, 178363954, 2908127350, 3466799309, 4163361670, 787973888, 4008520220, 774913405, 2342214829, 746086478, 3001029718, 1878022140, 2782622440, 3392054168, 1257667320, 565538943, 94004702, 2025355884, 2968981941, 4000193667, 4168608420, 1155851325, 4224702393, 556865462, 1461683187, 3158342266, 1166073416, 1273699263, 2554565259, 2702271939, 492522911, 579919413, 3885103462, 556735539, 3432964532, 698421864, 2225260692, 2545013724, 691191564, 1289731157, 1780213562, 2296279347, 460468173, 3952053879, 1920067027, 3167597200, 3699004523, 2153401532, 3210453855, 1125886564, 4225393243, 512562002, 2855351059, 3052922695, 3345993204, 3607746483, 3548799028, 2875625551, 1900275389, 3331125610, 224989674, 3527083381, 256805087, 2060275194, 3926180491, 2519363257, 3651109823, 3366742327, 1975034105, 1369971546, 4291565104, 2283529341, 2975378004, 194061946, 2811908685, 195122659, 30698277, 3264261714, 3143157243, 288763231, 2440056066, 2038814389, 444224631, 2238280221, 1503289660, 1334078583, 3724601449, 3300355959, 430546443, 4089192701, 57041070, 4196017516, 1508165596, 2889497246, 3745130267, 2182795017, 3574952253, 2808300879, 1111081240, 2553888706, 2673754047, 2591543351, 90021410, 2953439372, 3797444432, 556661921, 4131718258, 3617100594, 3934689382, 332330933, 3005860472, 1591919565, 2055730929, 635280917, 4111376974, 1023831659, 435448232, 2726078206, 77158690, 2153293015, 3369430400, 3630029124, 1133297771, 4267564846, 263729482, 3205345537, 1981047493, 2365111109, 2389382724, 3463942123, 1252789836, 1631188759, 3931403155, 1089070145, 343485369, 2482907957, 39564190, 3278898721, 363035113, 1536288420, 170308081, 3629240119, 9963, 3045711510, 2913470241, 4291636337, 1529754056, 262759009, 817271712, 1607080688, 737593827, 786413904, 3615013534, 487306804, 531158814, 3769512541, 1916818391, 4225331905, 2263017901, 3640159446, 3910329829, 3054168261, 781668891, 185410657, 1131242667, 2313538067, 16617931, 3088923134, 2285596567, 97320018, 2296939715, 3108674784, 3300398814, 3751582111, 881235571, 2889009763, 3491919944, 3263323399, 3347337487, 2427854010, 2812041675, 3539673368, 198495814, 1164322846, 4048000025, 3739084371, 3734085769, 3235510699, 926485538, 957553562, 3176108272, 622844963, 3094460156, 4074719719, 2870619664, 1930018982, 3808075326, 666404853, 2705852762, 619691053, 4221033144, 217503338, 2498645430, 1957980210, 2710477511, 1441331060, 1453965392, 1218329146, 3234626249, 2734978851, 420187145, 3875048836, 4109064695, 2023449386, 3705316294, 3734226228, 1678173088, 2355852399, 2545273442, 1660679545, 1047346445, 2851483434, 2385495686, 1845313467, 1434170548, 1876684260, 2864173169, 2858434057, 1606312665, 1404069374, 1409272983, 1501865176, 2629801523, 1156531379, 1966173113, 982374943, 2780186025, 51018911, 1670745883, 3433098563, 2796786690, 2521705837, 2349895698, 3414672511, 1189601967, 2691663763, 2003563011, 3170083221, 446706685, 2905548069, 2473452500, 2672119163, 1938341073, 1963072058, 3308540972, 2512499996, 3890193954, 3190271472, 1294547060, 154292633, 1145441043, 951556529, 1982588182, 2644881742, 1346657469, 1639969796, 3344053522, 1134687904, 603093703, 936617365, 2509419533, 680100671, 3656867476, 844884523, 1426442225, 1247488423, 1442787747, 4038072298, 560676042, 3167315140, 1367214747, 3536486947, 2853294519, 1136378567, 4026892739, 3443804471, 3243823117, 3189117970, 3844359512, 3716938307, 540784417, 2981956124, 1720572142, 3834798996, 3204329258, 3524043696, 891709759, 2358715990, 2249911045, 3497271760, 1870817405, 1453778751, 179255677, 2275729572, 1720686084, 2198280122, 587446621, 3277712905, 2994960400, 2828218934, 2978053083, 1152064605, 1863664141, 3416092329, 3147585282, 2404365896, 2520923621, 4144562663, 3306225086, 2030220496, 3587351850, 4122478346, 2659218421, 708542702, 2920393449, 2724650275, 75837497, 2495363342, 323083023, 4113859057, 1224677188, 3523705698, 181614693, 1464538763, 2447172354, 14093408, 325546099, 675680947, 3772468734, 345460982, 3224933462, 354558048, 449647873, 3016480523, 999347881, 2244728783, 3607973886, 1243947858, 2867395630, 1677541562, 4148542415, 862425012, 1470826913, 1052156219, 1728527766, 3578908356, 613335170, 2846084569, 1561352258, 291274331, 3704626207, 2762818579, 3245081919, 1343250043, 1615662229, 2531097670, 219127971, 2938579671, 3018648863, 3648602704, 721153328, 3110227800, 174697874, 643678501, 2670530392, 3158908975, 2804952646, 2356598803, 2050807595, 107662147, 1685361536, 1308533998, 1201813904, 2765954423, 1339748516, 3870256564, 2218776576, 854059437, 3907628986, 3886388047, 1688308435, 201296086, 3766085655, 2036555838, 3481613745, 948797408, 623304414, 1696856886, 1141726531, 3305871632, 2059599793, 908357061, 831275983, 849593710, 534797383, 793513545, 2370402315, 2777618690, 2628626407, 1757921480, 1691753018, 1285901466, 3426285239, 1331079772, 4146654863, 4024544110, 2979788510, 368467125, 24345681, 3073350707, 2969826896, 3884548140, 1799669248, 303853872, 207913625, 2141350731, 4138734403, 2939418084, 2306193173, 1408426023, 53245159, 225958934, 3592303602, 2276071422, 3558775671, 3798844796, 2812825104, 1149309307, 1671473834, 3741733619, 3464120030, 816392559, 2544850933, 3324452198, 2766215433, 2754927401, 136530698, 1546386029, 1670932675, 658949286, 170713198, 1210990734, 3743021444, 535276301, 1626462684, 1738421569, 2230576599, 3137963179, 1069299320, 455706470, 2580258203, 1360344399, 2862263047, 1370723388, 2792952777, 3846954515, 4209499685, 2927081264, 1204584971, 2379333741, 558569530, 1853212826, 3391360408, 1040513901, 1559770267, 876307615, 2824088, 1726280519, 644171358, 2706107769, 1680502933, 3489334226, 3424452901, 1495977214, 2224502270, 3728096365, 544320834, 4204260145, 2679681016, 820042458, 2850750985, 309319576, 1824964053, 1698100227, 3367290062, 361573975, 92583228, 2004326206, 493109001, 19484891, 3513638673, 2024772169, 4182578488, 3969090556, 88306186, 2631515405, 541817465, 3963902259, 994021943, 2974115977, 2296327675, 586210092, 1897225015, 4176474579, 2151973839, 2337213554, 2187117024, 2420055192, 3210640273, 2324839717, 1368233728, 288508901, 4085658026, 2082314040, 3764593412, 3125476362, 1600660512, 2149788730, 2427665180, 2997014598, 2154927292, 3917694996, 1539578838, 2368889526, 2995386165, 3409788340, 2886433974, 305855824, 3257718445, 261611974, 4227264599, 989750356, 1040361259, 4210137765, 2025815163, 2075444018, 583224675, 1301409366, 952488236, 864737326, 778670543, 8355060, 2923623421, 570431183, 2146789689, 1321011113, 247566633, 3943346875, 3696321262, 3176959573, 116528996, 13668972, 3406819072, 1902636191, 3113341004, 983724362, 3272488923, 4030017163, 835027824, 2238285483, 2548203205, 853361272, 3602065527, 1893771807, 3292565667, 340846533, 1750230819, 42266476, 718060706, 1584722703, 2580995200, 3686307554, 42260378, 1141531492, 791080198, 274869305, 4239725097, 3419290367, 634711851, 997215417, 1544807754, 2078245666, 4238725987, 1172084063, 573057941, 3811717672, 1862508866, 2392223776, 2246649095, 1911826635, 3716573075, 4256209707, 3522457949, 1340206478, 2517529807, 2221194466, 798990140, 759140438, 2674366145, 1344189665, 72595386, 723597581, 3593659419, 335376232, 2753787811, 4017574301, 2990058171, 3225943710, 1953159124, 3613021838, 1905719752, 1955073033, 2340717037, 2676910034, 3772473222, 3296466198, 3389933517, 2434303156, 1827448545, 1094002802, 3686776366, 3309239944, 1401087443, 260302646, 3203194394, 2134171894, 719448679, 1930627162, 3244219325, 3378404381, 3812681251, 2441318219, 2554633492, 1638940565, 3656938790, 3303253879, 828306443, 3638677120, 1326652936, 338801470, 2089611888, 2182150992, 3959668269, 3276592769, 3232487203, 2699698479, 3711459231, 1260821803, 1941766867, 4251289643, 2593320982, 4208132401, 3268186492, 1107538016, 2560397818, 1455893406, 772798556, 2010059348, 1412329555, 2751622179, 3345879875, 981350120, 4220854172, 2570887849, 2604765825, 4152631207, 1280682784, 3587177396, 3678567847, 710852020, 4067970368, 852353955, 3615534147, 2639984158, 4167767411, 2761837378, 1513673525, 694793254, 1894362672, 3263805017, 2976737806, 2775946012, 1564642610, 550950721, 3276449658, 1159035543, 2521734550, 2336608068, 2877139214, 2245730435, 3068431322, 4272866276, 274664347, 3097556962, 3342326698, 3870423352, 1062641621, 3999456880, 1663122741, 2137008455, 1150577129, 278182406, 584570470, 413288288, 953893357, 1619838786, 954237462, 2030868600, 3341078837, 1505588254, 996685690, 3838869263, 1899435389, 2717743049, 3274864849, 3237346116, 2342164642, 139415908, 543879245, 281171972, 2551065661, 2525750051, 104753154, 3488693617, 2239811298, 3907183760, 1861147359, 2237652376, 821384415, 2556443506, 923807176, 1114497964, 1688435037, 418913733, 3780821965, 855870812, 382500784, 3672042270, 3987791218, 240406871, 3177312849, 2339645894, 3663387343, 1718477391, 609427853, 47138600, 1392173474, 3322084900, 165330900, 191665056, 3375525145, 1887282863, 3045589263, 340365534, 3681803191, 3761997474, 3100098094, 3217118214, 1203379379, 1450361464, 457167927, 1523878470, 682498098, 877912245, 3964961947, 3161518987, 1518633749, 3120873652, 2576970448, 3300695214, 2791936052, 2714172087, 2724523327, 2456178494, 3245773223, 3724143762, 1011922455, 2468133615, 1328520608, 4243852002, 3530232048, 3958621534, 2186530782, 3190800545, 421915440, 3732105573, 894766418, 3912473160, 1873602277, 3818847891, 2911857216, 4022363100, 2455241114, 2315909413, 4188396625, 1322637246, 2354013201, 3533097733, 3150407740, 3447711566, 4171141781, 3043204910, 3805211328, 3849054297, 1738944382, 960458108, 4100056853, 1452230905, 3671771463, 793342064, 2052502384, 126345260, 4266351554, 2739791171, 2564099162, 2054176940, 4104860610, 2880824279, 1824609945, 2290885592, 2080132465, 3293516142, 3225255226, 1903846973, 249770957, 3607270679, 2039840265, 1484740747, 2799626769, 232574972, 3198581021, 3408176098, 2283476893, 1378712722, 2267853117, 3801697208, 4042881095, 214208749, 61544914, 723875937, 2544717728, 3107244281, 1942406924, 2204315142, 194788263, 2081604187, 1429321846, 3818022117, 2227370780, 35034435, 3300785703, 1916258515, 3792740919, 341949768, 1510985228, 935888111, 2831355401, 1172367405, 2779293526, 381002684, 1203468318, 791299579, 3228453447, 2164274465, 1578115502, 2644529284, 340751106, 116209844, 2355694636, 2729630500, 3450921193, 4212016059, 804469812, 2549255576, 1849673577, 2728107038, 299357951, 297926966, 1885179687, 1460468723, 1061492634, 2653222691, 2880953738, 394617822, 2279747967, 3993584895, 3177779497, 3847988196, 1617034158, 561325326, 3691960099, 655631397, 3717838062, 783893013, 2851649543, 2631344086, 3916534255, 4239514467, 1949848383, 3484594726, 1770224734, 3906314793, 4005839418, 4207121646, 2201510217, 528220266, 614751096, 351840326, 1436422606, 3907682814, 3423937400, 4097091480, 132496980, 1854199064, 378621641, 58135356, 768061170, 261902503, 3235989531, 3944366822, 2897288002, 76638955, 1608646444, 888012857, 2965667012, 1070852076, 2826174185, 826355269, 461939309, 2089015901, 913565948, 297310628, 1453100438, 351883424, 3277154215, 232696739, 373302545, 254462392, 1382840549, 2396260914, 395629689, 3690272782, 347837558, 3442928069, 565974422, 3199867881, 1394223081, 1414226204, 411776212, 366110497, 2215785507, 3336617752, 1389191042, 3230116820, 2286308091, 1103652934, 3278839516, 3987773259, 2751916818, 3426671738, 52390424, 3788159002, 336944991, 2490094935, 852597407, 806843902, 1247443822, 2022880264, 2704535770, 4119940159, 3352245584, 614580992, 22768085, 3281732273, 3360660161, 3184765773, 2103780889, 1975453788, 1520016309, 3642758446, 2329500419, 301513139, 818876954, 4020148877, 783951920, 2289116618, 2759423270, 3546488753, 3471283776, 1350688833, 3882816801, 110527762, 731506281, 3875805926, 361558987, 2733293446, 4149112272, 2738842435, 3457365282, 1911203461, 3791694111, 1986738012, 1121816344, 332259749, 2539780233, 1500659471, 1583130056, 712133978, 1118188024, 1648568355, 1769554028, 3303786687, 2270603708, 822978229, 3963942206, 3944801693, 950968052, 1427806001, 1761238700, 927940075, 3972749169, 207889573, 3360276654, 3703034669, 2752232151, 1355645600, 3309499666, 2234034742, 3333706992, 3679565790, 77914175, 330403612, 3453596334, 3459410678, 175508592, 3753692883, 373965805, 3840567680, 1424343310, 1202542810, 3690575999, 3214807968, 918808778, 709316579, 1472859715, 2605553991, 1502769065, 2626246324, 826592139, 1164837467, 2821720060, 2611020842, 4187248140, 3363390475, 2799120749, 3670536960, 2795389205, 707717410, 2060782639, 1982852844, 4060378888, 1138561015, 3906784820, 2931775722, 908740949, 2432273836, 498592088, 1637289171, 2159879590, 4047017466, 3660792958, 2115652508, 1209950895, 2345077512, 2128606337, 3052623652, 2014505870, 2055498585, 4179829578, 3728976993, 275050537, 2552939213, 620323796, 3714857310, 62090404, 2682354799, 181021002, 3494582794, 600379307, 3560414895, 1350459482, 3565826612, 524507499, 1413687814, 1405059824, 2383744607, 3387756791, 2559380951, 3351617500, 3677287602, 348058713, 3224158492, 3746961259, 3757007545, 316694990, 1967943132, 1845094737, 2029405643, 4226275584, 994479209, 1270994116, 1958491610, 4132050946, 3967659388, 3029819959, 2977591836, 151469162, 2398127247, 1593561927, 3507232654, 241564748, 1740951350, 386885364, 2933913818, 1720957320, 87561347, 1723480837, 3552803561, 3556853653, 2031086874, 491826579, 2079567355, 2169699209, 3044943289, 4056924672, 2307645608, 3537713376, 2908104019, 3177159128, 929013201, 433566853, 1352264950, 2480483252, 776517141, 1309218572, 1434953184, 3391313612, 2741185955, 3363829478, 1675086390, 972223600, 2744479033, 3266794923, 35658808, 1579045646, 873399878, 389478288, 1382367939, 3653633542, 3233170189, 620600047, 984251838, 3024949168, 2365493295, 3895194616, 4057529727, 1430697808, 596632735, 515576435, 3485088618, 1561260468, 2326132425, 1441097513, 2650789119, 2657744738, 2044628817, 420984447, 1799231880, 2547017352, 2745434926, 1298092765, 485912325, 4050696110, 2449075835, 492836822, 3202477568, 1240801219, 3646284028, 1647715380, 3149177250, 2943417567, 1413539007, 980840595, 1125336194, 3751306352, 2855978526, 494149037, 2867775588, 4113812967, 1263704367, 2910496580, 1593721994, 1085528744, 2264130185, 83269382, 1115238432, 2604100592, 2577869874, 4196698412, 2704878249, 3617944011, 1349932536, 978828117, 99862233, 449450281, 2396577116, 3678387947, 4259742516, 1322631672, 1915561686, 1264795767, 2769207380, 804413524, 1232505337, 1220009724, 1294287873, 2855456734, 3927255440, 2712197443, 2491275022, 2240407480, 2761036179, 1837202003, 1106888468, 1417477688, 915296319, 2039342274, 2733613182, 462637863, 2840649864, 3100484828, 2719672892, 151906935, 2261319585, 2656759829, 1519948884, 719129572, 1682072090, 2781457991, 1350068632, 3274154190, 2109173442, 1908724382, 2419052419, 2028679234, 3203173989, 2590495456, 1989273280, 531511733, 3566448108, 3462338174, 4277911603, 22298737, 1524273119, 2709336519, 938092901, 295799642, 902385642, 2137236380, 2789233877, 3682007324, 3625684954, 3614857056, 202468198, 1226661917, 3159277477, 3560648153, 3819621278, 540332999, 2944854747, 2409193978, 374804764, 1336405091, 3018475595, 213078133, 3384614741, 3290633661, 3332242057, 3224858586, 3203591826, 1245392207, 2580283994, 2701486219, 2384381770, 3098276020, 3123910700, 4085709500, 4128158718, 603139521, 1135525058, 3857642684, 1410378644, 78359003, 3406390922, 4092337337, 3213773240, 4197894447, 1942316430, 1258637305, 4239250867, 3475475336, 2655363530, 3739419561, 3143231964, 3957503737, 4047803818, 434992995, 2450348156, 2837933497, 51567125, 3207610947, 3292696078, 3101011969, 3766828611, 3055435588, 2877370050, 226359606, 3392837464, 193077577, 3311782725, 3894789730, 3316160046, 951206256, 555159409, 3162879474, 472431400, 570576174, 753157825, 4105008110, 1211132986, 318543594, 3685357622, 773996108, 3754567744, 1249414550, 275208091, 721342432, 3031780362, 3383028662, 2217171095, 3427901388, 3933669498, 109992127, 1145753994, 1494149615, 3600238607, 3201504597, 580777735, 618124048, 242104221, 129496845, 410772906, 2537408883, 2754275686, 2639107980, 725841242, 2443820926, 1893265753, 3447797702, 2933959901, 3214099889, 934279127, 65128819, 3272362684, 2552082822, 2090528760, 2559891538, 118281105, 2672518703, 2096202720, 3273414364, 2037459504, 3370827896, 1699701315, 1606070586, 2904479552, 3315003695, 2820748303, 1793140491, 2962952508, 2710637011, 2678335574, 3590547790, 882661210, 277613712, 1784245098, 2779933225, 2310988284, 1408095043, 1622616915, 1839606749, 2605774208, 2254855010, 2957400503, 4242380003, 2773759547, 972422801, 967128554, 2340551928, 1861158625, 2404129215, 3647330257, 1574228621, 3419433492, 2124217412, 240959784, 1320622909, 1747700367, 2755288827, 1824869076, 407182857, 336533520, 736075625, 1196548381, 3239474159, 3048296225, 483742895, 2994857359, 3209699333, 1469442024, 923109824, 1382969239, 3174660371, 3212452354, 1807036900, 3961861384, 571414940, 3034500868, 2064945562, 1884621518, 4273342775, 3337870380, 772881427, 487872381, 1460921875, 167725087, 1193045309, 3438378745, 206582715, 733951678, 3780148814, 2296573340, 2888500099, 793860351, 985954389, 2244404490, 1686378278, 1286463227, 504058677, 2940924721, 3628549544, 2298279082, 4074139272, 3318550839, 2078691953, 3904311006, 2751358613, 3134421831, 3689866939, 471611259, 3585450053, 53341630, 1433114211, 4137751343, 3233461668, 3138867815, 1669897675, 301150150, 73141700, 1222677780, 1821445642, 2626124657, 3869544082, 2466140961, 1867437858, 2283701970, 2364920272, 3852084637, 2567337268, 3683422908, 2747924360, 3880780234, 1860180562, 3714959304, 4123133298, 2021423060, 2077485881, 225646782, 2336847691, 1461822489, 130273718, 2894035181, 1084935869, 3834746928, 2778596117, 1594764681, 700265718, 1902646838, 1363673254, 4114066892, 1859912045, 435194699, 2491267954, 1053346475, 2418313825, 184677741, 2294122112, 4244326950, 1517107134, 3572119836, 2968484987, 3666330450, 3979403703, 2036049749, 2719225873, 3938641674, 617427440, 815463497, 575728460, 3291828497, 1043374761, 604294591, 3619555499, 194736919, 2546021062, 1050882061, 3837091824, 555004663, 1668443581, 1907761109, 1777339140, 154502652, 1192574008, 2967586359, 1956114947, 1059598381, 1680712924, 2611921118, 1170015973, 1798997495, 362951246, 3172658646, 3632419746, 1334773961, 3976403025, 1604507134, 4057780710, 2463567881, 621884418, 434643179, 2303536415, 1378521501, 182935114, 4226457937, 1861600714, 3698888173, 710367560, 2290293929, 1660299298, 1003266145, 1614223266, 3903798180, 1421639545, 3329173822, 1980085434, 2610822457, 2296634936, 3837413666, 152461017, 4072600229, 3860162625, 1102141974, 1707290459, 3416778051, 2826572991, 224792111, 620251130, 4001879930, 3041187018, 2257061408, 2953988237, 1050117564, 1566680723, 3569348398, 3895084389, 2279563192, 4145303386, 3865963395, 917194771, 1529108810, 1483738511, 1364174636, 2884583785, 1890244693, 958296239, 3472389716, 1186326098, 2140878101, 3783117706, 991645649, 3444958227, 1241410709, 2300684342, 585778329, 2121441728, 200352242, 3554821900, 3515050051, 1013367459, 4150105309, 3592078139, 4074451175, 587413402, 3265599719, 2529856805, 4244056558, 4072403842, 3104615316, 2805257814, 390680494, 1879691966, 2588945355, 935618168, 3813809475, 3315398574, 3636679403, 29389301, 956420692, 2461914496, 4107004684, 2723760888, 3936011913, 2024331212, 2450012726, 302988290, 2741245539, 489985017, 168854395, 4145632475, 3348641173, 3483375137, 2267242998, 3821788835, 1500990181, 1102216180, 2522627710, 3739104751, 3968030494, 4150934004, 489690835, 260506722, 1113595250, 825720166, 4271989921, 1692626437, 756162517, 3018843962, 1009961164, 776249663, 1457130315, 2499776103, 388172068, 1401931394, 627698688, 287314572, 269662701, 3149013861, 1642206188, 1180957409, 371610907, 2393570134, 2964591267, 2480333347, 3025831710, 3717481964, 231048978, 194179706, 587444409, 2010083858, 980770207, 1026370399, 1179743068, 2792643637, 4132609170, 49332703, 1412722994, 3016115316, 529076589, 1972709189, 128813830, 1532167613, 646111429, 2038237049, 2552100089, 1852245650, 2121119349, 4050924288, 1001258012, 3002257343, 1006242596, 4197333726, 3785607155, 1899057351, 209150997, 2943164961, 271141033, 308133959, 1598574082, 946544384, 3049246031, 3136618323, 2964435656, 2378700241, 2878579386, 2797948570, 575272375, 3675742452, 4044544470, 3518398596, 340879154, 1751409701, 2003106873, 2680471427, 3034973115, 404982343, 1648254750, 3438446325, 326496853, 414296402, 2298977583, 2033290810, 1517186933, 696398609, 434702008, 1636984193, 3182749650, 3067231181, 821004408, 491225538, 2694332105, 3634010658, 523231120, 1261908927, 1630854003, 1338318556, 2787957072, 1884258157, 4003603151, 3068923237, 3204155879, 1508622908, 1215621040, 4259301989, 3430911876, 4080344501, 2599578809, 1912454190, 767417636, 4012455246, 2151245570, 974420560, 2719564908, 3280911801, 4241226322, 3777914170, 536905698, 835045394, 1911481927, 3620312534, 2942899656, 3760905009, 2074926029, 4176746017, 2469508557, 1929255162, 1657639950, 2716801832, 22336494, 1195357815, 1422585254, 1874307911, 3198517022, 223354754, 3323948180, 3209547520, 1190171800, 394784888, 1640980643, 630307724, 2036676005, 287039132, 3251918809, 1030982007, 4246784801, 1244050735, 3074276551, 1250819685, 3809668227, 104238959, 2670846655, 1533972167, 3067023947, 2415515608, 917603302, 592440565, 611377455, 1299190767, 1939156996, 1788934393, 3186649882, 3681837145, 2083672672, 1196126620, 1806064279, 1806838116, 4240579640, 739999337, 1098091142, 1664190189, 2991224025, 1923902267, 3945259600, 2658937590, 3726575401, 1230419543, 764707230, 3549313932, 3642424943, 1172885982, 1789374295, 2360482756, 2780394134, 2473472446, 3209657800, 2099441302, 343054463, 1459528931, 1021394506, 1816423506, 1601401383, 3064233088, 3259222355, 823671598, 3534219776, 3057131487, 4112592391, 2783467128, 3868566268, 702854391, 265064015, 344847057, 588017928, 2234898225, 1072515401, 3858512687, 3172259969, 2790437958, 2812769030, 2651544961, 2859171487, 4071197034, 3260715658, 3653780825, 960634056, 1279190064, 3663377179, 1328571309, 237244914, 663195520, 1121502200, 1386985313, 2964079428, 990137762, 3677208200, 562536179, 522373400, 2577496881, 2954694441, 2901335475, 1678665494, 3580889300, 137429613, 583855456, 2768859992, 1684983888, 887775211, 3667114619, 4013712371, 466790664, 3399994087, 1172332809, 2809459941, 623322023, 1753469431, 1675051448, 498176279, 2207442562, 4016251328, 3185194281, 2600040851, 4270582732, 1723627381, 1631498182, 3960806710, 2190355785, 2137601052, 2278263342, 2066183413, 3859845987, 2932413281, 4138343518, 4135936067, 1789261648, 3051029009, 40477262, 325390641, 3536676044, 1511190721, 2002391507, 2334607786, 3872900627, 2558273463, 2249944299, 306737834, 3077116541, 3436927049, 2837294326, 3939848585, 1817825412, 3689962232, 3874263331, 2528990281, 4020542608, 87030143, 2888357544, 2386482209, 2430768040, 208306461, 10322350, 1326860706, 3769524590, 2648363096, 4288581473, 714713903, 1505322989, 2287854817, 1900232455, 717665487, 2206697255, 3320079515, 238263521, 3779932000, 4291033226, 1135011350, 1549279832, 3468014233, 3779721960, 3664469845, 665493332, 765366809, 1006405486, 3594166055, 561989023, 882671877, 2264533342, 3140063933, 406699684, 4246323920, 2339167001, 1783144553, 2086830194, 792259729, 2055752400, 1503053078, 3772837246, 4206234055, 1820416778, 109615414, 4101436885, 1735287569, 754370562, 262726395, 1566536381, 2291152860, 656632823, 3795882518, 3102217658, 665395103, 1608144010, 1445439113, 900539898, 3853476929, 2401562096, 1380339985, 2652722097, 514817454, 2508510877, 2242620781, 3092675696, 2176715756, 751784508, 3829100853, 929922339, 3976876619, 428408992, 3103972711, 3091047489, 3499654318, 730418292, 3976731332, 720471960, 3321231524, 3822050235, 3006219256, 4128715548, 1901210946, 1904321687, 2347804532, 2441708401, 644662079, 2642956374, 1202342572, 487559801, 2541351849, 3506127277, 3748411961, 1020813277, 2204234834, 2668314131, 3540550786, 3156593674, 689247699, 183287391, 3623291437, 3096141502, 1122829497, 2830342673, 1277696873, 523256736, 3580548409, 412193661, 3390072822, 1910577718, 4000272642, 3157003401, 3120575397, 3347285717, 1105801291, 3526168444, 2277601066, 4126289064, 3603202161, 3714461246, 637329241, 1506073901, 140763919, 159059625, 570372100, 310655276, 4274054126, 652820072, 2665232536, 3249851629, 1215359787, 2325162303, 2513932058, 3352242508, 2859049505, 1484882680, 4235526646, 2025797853, 164609077, 1438493508, 3761009218, 3665206095, 1595187746, 1062512728, 956546028, 3846483422, 3574864413, 2743831638, 1475164144, 2011784204, 2110784939, 2358003518, 3759373203, 4256674738, 1436800746, 1411553200, 2774888497, 425035555, 1915114919, 448640415, 4163842478, 1189142075, 2598603359, 2150021519, 475551616, 4043651335, 2879473669, 2633187236, 2307941991, 168392305, 2351213187, 7536760, 1570396346, 3287927468, 2942827206, 4208388387, 3851127056, 1750219284, 3767183313, 3893440254, 928449456, 472638248, 50253946, 1304140612, 2794306168, 308727834, 2870656027, 189076424, 1746584410, 3959695155, 3279489516, 3039347640, 3096646029, 2748502756, 3324587967, 3261840469, 3057046585, 2727997697, 1104035019, 1280696830, 3477204367, 1297971334, 750607414, 2433365552, 2601518004, 11258684, 1040704941, 3715818873, 2158787114, 7016446, 2925548686, 622135942, 1619542473, 286908419, 718362729, 121666472, 3119289134, 3087945776, 861582939, 425296970, 1263438729, 4065557937, 3959986517, 4134693254, 1925794123, 193437418, 3476905956, 1511712377, 3238874232, 3312526937, 1773669437, 1585186417, 627240956, 1936130968, 1481159394, 4283758747, 2641584867, 2666928986, 3452821649, 4178531521, 1822700059, 3415376573, 3881394922, 1692296803, 382840841, 4000638979, 1899699449, 3696396074, 2530736870, 1339745766, 1620430034, 2696251887, 907474405, 122959529, 2311046870, 2707913370, 2068155025, 871578813, 3199933316, 4109893644, 3364535059, 2689483583, 2733315419, 2816581989, 493597647, 4233326794, 2707337061, 2466491155, 461645590, 3394920046, 2364034700, 2927025934, 3561869025, 1766019166, 1087480153, 3423282059, 2131323526, 443966965, 1322332697, 1188782069, 2328104863, 101502730, 559580730, 292683787, 4260616850, 106658508, 2316309568, 2434308741, 2540198387, 3872202391, 1683466445, 361864473, 1073947479, 92799404, 1093412917, 1797622721, 2090746539, 2283241835, 2132221790, 683313217, 2605586840, 272071431, 778910196, 1178669312, 3122370980, 2530336330, 3970158473, 2490258456, 2190693705, 596284947, 1765600807, 3350342078, 2794589150, 2635443956, 807439784, 3903077782, 3945796325, 942763420, 2713046382, 1698713811, 1317857903, 1110525719, 3495131608, 3223505065, 946629392, 2972584044, 506707999, 94736771, 3765880923, 652903571, 1540406962, 749211644, 3014228203, 3518499041, 3422675143, 570554490, 376540369, 3468500338, 2654381732, 1082043102, 547740010, 1376776268, 2368736622, 2340164956, 3274206213, 1585675606, 2526948269, 3685826888, 1303281228, 4233726619, 3077043885, 946095382, 1772054857, 3629314636, 3668407285, 1679245410, 3015824845, 3419133504, 1772118397, 3869309009, 3116086793, 2476315498, 2727156416, 2073358304, 2493520250, 3184598335, 3426023846, 2535765177, 1350497350, 3842761924, 193088781, 3549291691, 2898323987, 528541515, 3931652212, 2628035505, 3220688025, 1327873644, 2630505529, 2645555986, 683371565, 94682890, 3088159400, 666832937, 1170664070, 2982432118, 1240862344, 1541705759, 3848566925, 470074324, 3299004854, 2806142952, 739137245, 2220277210, 3177719291, 2655324779, 123152485, 811519781, 201013561, 3301124472, 1329382140, 41951119, 620138375, 2546585592, 625899600, 3326495333, 4213033328, 3082520072, 2891613782, 459582846, 2097858672, 717773013, 361515587, 2355289195, 1151755260, 1300970819, 1575593593, 252818119, 1942833848, 3291967541, 664516403, 1757721427, 617231947, 3341602112, 2134171110, 2655152316, 4171063368, 2266853692, 2249705420, 4229017828, 3808551569, 1022164534, 2764922040, 1186169196, 480930826, 3626411618, 191179196, 3084727732, 2279466761, 4262348380, 3415268683, 2678080982, 4222640244, 3707472424, 397923840, 475207557, 1315511880, 1883992100, 898749016, 1879798163, 2017024751, 4062544133, 806475517, 3051502018, 3708841910, 2096099031, 2472482157, 1257669380, 4098373733, 3753948004, 1449830867, 1906256745, 545503177, 1730793521, 1951534912, 1016204794, 3644912944, 2756593845, 1084912829, 2782536566, 3940309671, 4041993642, 3625686158, 3342172669, 3350618388, 1432134919, 3394172396, 452736283, 3746356467, 1206978644, 1071262458, 3418727601, 3753580695, 1155910123, 3621981229, 974633491, 4270218948, 139365450, 1903294135, 4213872458, 2609351473, 1806785011, 4061492016, 1658876611, 1725649895, 4238767421, 992865751, 2011385765, 111748306, 2649459396, 221192812, 4156176160, 536764228, 2796826913, 1239184361, 2672911755, 3006728942, 2027502333, 163000014, 829865457, 2838930988, 1890078144, 464268512, 2194804859, 3938455874, 1014614635, 1776352812, 4242636730, 250288235, 399096520, 591848475, 3913262575, 3472268179, 4154557375, 3758335140, 1187320829, 1385358369, 2785309889, 3598306971, 2407716186, 3628617916, 4288509869, 3267216806, 1856454511, 2928214947, 83101206, 3202050500, 965501838, 1912359870, 632876507, 1208660227, 778560438, 2876747643, 3513939362, 3961376920, 4110658869, 3126278195, 364426099, 3234695768, 2990525857, 796682824, 1791220715, 405843908, 124880551, 1855027244, 3746450180, 191162010, 4082012263, 1581699691, 2764243440, 277355349, 963430298, 3566230933, 38625380, 768212651, 1512496904, 1874854932, 2450757328, 2786594782, 1412558861, 1395849717, 2747218492, 3495543061, 1846920941, 1898677827, 2422832755, 3921580192, 107001262, 2741893884, 2313862769, 1259354486, 1588034006, 2331911183, 3195037905, 2648622432, 2978006124, 2561556210, 343248328, 4270266947, 3123864518, 228539497, 2407750681, 883695218, 2745594856, 2247519066, 4231094, 3581492796, 1675476648, 3620672884, 705741717, 21140076, 3982005817, 2694829480, 279149408, 4168326852, 316910772, 3383945497, 107689253, 1930173490, 896093152, 2913961684, 3725633499, 3050991063, 1315775057, 2197755799, 1142448087, 3961882716, 2593319623, 3492417047, 2019475096, 3414459666, 748384462, 499802845, 3126485939, 2047865095, 2560586698, 365444713, 2028626826, 3873328802, 74720391, 1993493319, 3232526894, 3721087504, 1967755320, 668632378, 1664543524, 1468291947, 2952440865, 1254499682, 704856107, 3454907905, 1964686149, 2452514339, 2293075687, 2004179645, 4015953950, 2947022984, 1173640303, 3314346410, 4272848163, 1425734659, 189190656, 786794043, 3946370116, 3085382345, 195301679, 4033242297, 1514196051, 3136636993, 4124105667, 1194214926, 489226345, 4080514545, 137488511, 4103330635, 1341258892, 1995718006, 202036240, 2939663429, 2187110372, 1576986644, 2100184388, 257157287, 1505449570, 3072904390, 523897480, 3619460547, 380563300, 669924233, 3918009837, 3169238035, 4209189486, 1240386377, 3643960492, 4267039098, 1045161394, 619826520, 3227734068, 425851327, 1814371668, 2114793343, 851360717, 1089263423, 1146150256, 3569229004, 2947755440, 326298952, 2159409889, 1578326684, 1453272682, 2251621847, 448102574, 623114003, 2807384207, 4212076107, 932326520, 2090364258, 3399577451, 4004091583, 952313228, 2574159231, 1854395394, 2705398428, 28644137, 302699461, 2929946845, 2052869589, 1470767307, 1144233294, 3039104974, 1656359271, 3353995119, 1755814610, 374073025, 1415373730, 1263008081, 276443594, 2844698199, 936296608, 52983486, 1213318387, 3037986992, 1150786479, 2177266424, 4187211253, 667257572, 100299652, 1701434678, 2229094793, 2589354623, 3277721085, 2778825478, 3059387080, 2015082842, 4084788098, 2105734286, 4117727535, 1077417510, 1280959967, 3207427510, 3001681767, 2287516411, 807245294, 943791596, 3567936516, 1175510623, 970953875, 1603914526, 3736436896, 3132876687, 1911058141, 1902151321, 2882818778, 2129022628, 4147170175, 1665613532, 1339380240, 1295409124, 2519006226, 1589066702, 3555085149, 2567876837, 4073965037, 1105941413, 3390819744, 184772468, 2876844310, 3055730007, 1867650446, 2066626685, 2382337144, 3731581159, 694748949, 4037311148, 3311787740, 2400074253, 2611534780, 3949492046, 3768082359, 3715389991, 1821116255, 619535405, 3526020385, 981623321, 451820079, 4037309001, 318196631, 2851710377, 2693083957, 510705188, 3309245549, 2952849981, 1195988301, 408775548, 3399824599, 2652897529, 3888595751, 249737658, 2553914719, 3085382480, 3761350827, 275315172, 3214461141, 2902235262, 519532287, 297992837, 3160553840, 335649192, 1512852903, 1903834058, 799630905, 2367526032, 441909661, 840254872, 2131794245, 1764935775, 1927169311, 3463226678, 1472402236, 1767217158, 3205167853, 3927785614, 3573286096, 3753099950, 2228929210, 1659221107, 2746211993, 810190361, 949046192, 3192506604, 4088392527, 2847106980, 2936788348, 4156916135, 795573075, 3496252351, 3678494, 1220639620, 1190792577, 2327376947, 238604068, 1443497716, 1284955950, 2598236634, 2746974481, 1397718164, 4007286832, 1962880570, 501731990, 1536158589, 2703567548, 4033741310, 1043951332, 2178030208, 502382330, 397014065, 3437941627, 2102353911, 3105472874, 133677020, 2501316468, 3498041685, 1233221581, 598304446, 1256058298, 856556625, 1668346687, 1834508098, 414982247, 968825298, 728571643, 3066334051, 205267651, 642009878, 2938411293, 3400735822, 1111934622, 304392877, 2678708182, 177181264, 1984975730, 1969199060, 1244467610, 1654243204, 3654035062, 3366916456, 3737272025, 2650746504, 2185763245, 1889212024, 4246389927, 3390547957, 1332135365, 296506871, 4177217258, 2700794658, 2242564412, 836397977, 1676121129, 422154043, 216339390, 3750079775, 2310419665, 511516103, 1739906592, 799210035, 3712311464, 1455592792, 3349937262, 1598562662, 2486265409, 519166017, 1297435763, 1392763799, 2022600061, 510735474, 2478097195, 506759619, 796379426, 399080223, 666623180, 1124185019, 892437879, 485826853, 1656496716, 2938611183, 4178286512, 2439599863, 1598034092, 3269993250, 3450031166, 475866618, 1806759119, 2393680802, 1970747471, 2099713240, 3875517845, 1207984196, 2516007974, 3965473493, 3948490816, 2119377154, 1839612738, 879208677, 246542905, 2630201999, 2928517000, 1097588026, 2965830207, 498130572, 1798823308, 1795905178, 187806215, 1287988379, 2031912144, 646835032, 2767499591, 1124794926, 2577129465, 3037704214, 2639841971, 919973961, 2033290775, 2885700032, 3520462836, 765528422, 446633427, 3123360363, 2298081977, 1390131662, 4230413914, 1902215370, 3616013845, 2260513001, 3747377440, 2817779138, 3264575558, 826783367, 1292120871, 1208887850, 265679868, 3872810982, 2675698014, 4061565567, 4152710054, 110655396, 780958816, 2763524359, 3633986695, 2010942553, 160739946, 3619904389, 2947803112, 179114010, 3738984586, 4013670177, 1088797110, 1276754564, 2440296283, 2399071424, 434487060, 1560826919, 4157071910, 2976509345, 2893695026, 768343063, 3824495669, 2655391168, 1167184615, 1621514532, 3975881006, 836459681, 3885571349, 508166775, 214823162, 2276274638, 4195487102, 1195690824, 188782154, 29205793, 4136541674, 3381782951, 3561011302, 2915898541, 581308861, 2514950412, 2711252254, 3661076924, 1554606681, 1729955597, 2723146055, 200346906, 1552082335, 410639853, 1691198816, 1384831443, 877670880, 1170630543, 982426045, 1450261819, 3227495855, 666934888, 2420401338, 2087666752, 1563061416, 1657331301, 3553602125, 3056899951, 869589327, 139857133, 3767113610, 1303974605, 1723201762, 263844574, 2503243858, 358826296, 4173491333, 3687643809, 1625871493, 4198946919, 624894510, 3700331886, 3329004524, 799770921, 2298483872, 2335302132, 252126903, 2666987340, 2847670745, 2812544104, 512934167, 4280220084, 3224849468, 2219609098, 3179622399, 1764701927, 378248121, 4261315889, 1025924236, 1196055308, 946511871, 1660111110, 4193689984, 3547572682, 1714485709, 3208296103, 1879031614, 3993387879, 74759326, 2535726908, 20781750, 3772441705, 3140626384, 4022054925, 3132004834, 4128133333, 555857086, 219631928, 4066401226, 2364736568, 2372067565, 3238914984, 1096667213, 689491983, 2785309740, 1587072461, 3410938009, 2847008597, 3514882839, 1910022341, 1653248734, 1499301492, 384557449, 2844135017, 3322424352, 2468876483, 1801577798, 396633331, 2182190443, 1629994414, 2959059506, 3964895515, 1761306860, 1805894432, 3922729773, 2411151815, 889157855, 1026886856, 4026036674, 193965600, 1570181022, 633532461, 177300986, 3371224064, 1748120023, 1761340469, 401130679, 2744459475, 2720260552, 1908778372, 286268774, 1859399551, 2795691203, 649400262, 3721810747, 1895622116, 1270653455, 2482668703, 1928217432, 3870565217, 3195815102, 1002226446, 2319234940, 1849617444, 241443443, 1960134849, 3257532571, 2122442138, 3357237384, 1091603714, 1400399574, 2764930769, 3639652992, 1075992067, 3354008606, 3674434180, 1269912324, 3480210695, 2694195272, 3120019549, 4204414893, 3115582945, 62860, 3100959926, 869419887, 1501173206, 989959599, 4194175791, 1874919226, 4132268124, 941227636, 1117180576, 2798307927, 674257397, 867344324, 747456843, 2751244875, 2885134775, 3838427931, 1873728410, 611603176, 2959150253, 2181196683, 1710737373, 3705891697, 3034486028, 725440065, 1923636551, 4151354804, 2346141321, 2707306865, 74049846, 1541018327, 1790958807, 3077570591, 1139993470, 2417568601, 4004865519, 1041577893, 3235167060, 3254089701, 2570838319, 2475603200, 3859647482, 2993708386, 143247127, 3734661089, 826230775, 4116635923, 199135364, 588292673, 824443751, 568341079, 1016456619, 1604002702, 1772195110, 3964951887, 1493560899, 2866906460, 2936090282, 946222747, 525981003, 2325353316, 2886265911, 4179416306, 3370849462, 1893142846, 2681054547, 3735197589, 3776524206, 1296370394, 4238698717, 2003830728, 3887946826, 2829434435, 1875801233, 3277229923, 4123505719, 774917414, 3564778974, 1353262063, 1276224511, 1774196274, 2512537568, 208846945, 483611843, 1566083971, 2070150886, 738949232, 4244252079, 1367631629, 4274810101, 4148053121, 2262045233, 1323571644, 3874729248, 20229007, 1930672366, 2535449036, 2724644158, 2337868550, 1980878450, 3084405876, 351999056, 2331600327, 803554490, 3414519030, 3508616719, 1312233895, 1276476199, 741671465, 2052571533, 784575034, 3477049444, 1778569772, 4002036361, 1117181350, 2042796171, 1211457669, 4052197160, 185043729, 2924935303, 3596780754, 3912420895, 3627811273, 1985659887, 3753611409, 2047663715, 3318805362, 149285966, 3179895001, 1237672670, 1985820626, 1298372520, 4284591011, 341224454, 454999791, 3750564549, 4107533271, 213131740, 4012841780, 603326064, 3017166441, 279885978, 1915229757, 1348159257, 1548745560, 2981789576, 4749968, 3020261054, 2037208068, 117001672, 815291934, 317905993, 465148647, 3623981244, 190010148, 1709761935, 2835947327, 3517022470, 2178243690, 2497438014, 1876568825, 641590597, 288338736, 1164573506, 2218432212, 3072549385, 2808266324, 4204926341, 3781762011, 3181513185, 4246729183, 3028889447, 3479420370, 1293238383, 3671370466, 357540249, 544681902, 1619466883, 2095482859, 2351601097, 1294354403, 3924412452, 3509201400, 394596275, 2000769208, 936155928, 2980604496, 903974142, 2430419875, 4100610868, 1228760002, 3303634223, 2793866830, 751125932, 951956482, 280266344, 2891935450, 1873629086, 5570516, 3354888472, 149771485, 338307762, 2822577121, 1237324803, 3342007852, 3441674541, 3974115083, 2186803670, 3504599397, 3344339108, 3913996367, 2303206643, 2511334168, 3254784413, 1378993575, 2422186725, 2959643285, 4212948275, 788681136, 4207545241, 2851838191, 2114800129, 933612608, 2319524742, 1877560809, 4206760104, 1731687165, 171699922, 3463277658, 2795199671, 3866480958, 622763825, 3094649971, 1423332786, 2717336129, 558587665, 2491633038, 2364130945, 3360297817, 716787448, 2782951458, 1575189363, 226384805, 1089938862, 2914472892, 2706981436, 3863385624, 2637979099, 3616845051, 2684045904, 1905176309, 2846718196, 3558902951, 3891946352, 1254905803, 269913489, 1082165285, 1833207584, 4115780246, 434319330, 1742079497, 647885839, 2863394952, 3038238702, 413347594, 1719976258, 4034848482, 2328176830, 1613364718, 3940789192, 3739394322, 2362355131, 115437714, 3583561637, 3840825890, 2914519890, 1212102726, 3481009106, 736166974, 718171257, 2199668000, 357589147, 1280278871, 1491363454, 955868050, 789879528, 2698794649, 1915436774, 1686943875, 1758449247, 1150886369, 2922900881, 208227464, 1143826808, 4191332816, 2696921387, 3692310240, 76470987, 3289165344, 623567006, 4188640667, 2864843705, 796242042, 1597539994, 34970604, 962193696, 2654314888, 2896643079, 972723042, 1891747952, 1034976782, 2949023272, 2341526400, 1742458173, 2052910327, 2072192599, 2793782047, 3358992152, 3911277496, 1831587768, 1243577120, 4249315708, 2013672927, 2547035442, 941512412, 360581387, 185821450, 1761992495, 1628978782, 3866270262, 1939713190, 2410442029, 1842360003, 100022960, 3489472548, 2137169704, 3508042620, 717338936, 1716080536, 4174165314, 1779870772, 4188693983, 2720756617, 4132300777, 3257213784, 782058413, 1875126093, 1095563746, 1715694327, 2066141725, 1846928857, 3429251073, 2122502370, 2298283254, 3089071457, 4031218271, 1134630355, 2385033542, 456362630, 1957570996, 1042213984, 703226120, 265051185, 4023801258, 3225097623, 831815050, 2355101173, 3982484216, 3634887390, 2443592608, 1362657087, 3987480592, 1452761837, 1326430527, 25981182, 2573055937, 1095878064, 3985298805, 3302487006, 1202505595, 390727865, 1826073018, 1989386218, 1898055969, 3392648337, 727907640, 1593813478, 3211587452, 3210864466, 3762668884, 2902234025, 1292462085, 1742646865, 1549756508, 675034357, 3053829169, 1471227718, 3124180515, 1807018783, 2453567817, 3992883600, 2268519457, 2035724962, 1436456489, 4264737023, 708223934, 3028559606, 501587643, 2707807431, 325077208, 2416334023, 3694645865, 1685743923, 604273842, 2649984654, 2845588843, 2933252684, 2730336951, 3580925423, 814225121, 3366268425, 1770717149, 1486401167, 3804277507, 1456752174, 6337974, 2409833340, 1617313876, 225498760, 1983179608, 3402609150, 744149761, 9987060, 3366937625, 3438474150, 4063360667, 3385409664, 3769624981, 4072601314, 3280258332, 298354566, 4056036825, 1561486207, 3007704270, 1662043103, 3892618780, 1804001291, 562253753, 4067841977, 2995255243, 80526741, 3057512084, 475203264, 2986752586, 3957883503, 1802853615, 311819332, 2837767349, 2388888673, 3277341280, 966408880, 2072943634, 539516418, 79462313, 2004099787, 2453102486, 603261020, 207424431, 2855582760, 2902494889, 741106176, 2468329430, 861181190, 282067858, 3684697365, 2623982006, 3801013044, 1168619526, 3894563665, 1944151972, 484249400, 2065256884, 1354519084, 3787011034, 1665285189, 2185133696, 633574470, 1522160849, 3190731137, 3963083576, 1769923208, 2261196778, 1079503357, 1414231568, 2141083825, 3772913971, 2048406301, 1513088102, 3812670713, 3248749895, 674551953, 3112555045, 3285597033, 189516445, 917663541, 1185071584, 2241980593, 2147308254, 3090205461, 3246618291, 290677042, 2461014414, 208431436, 290062660, 1228872528, 1963818101, 2419660283, 957129217, 135746754, 1315404499, 2924407396, 2700594564, 4124385669, 1690270299, 1360970740, 3034185919, 1285708700, 3277837412, 2891370147, 2083671223, 1244859227, 3629315723, 3331276912, 3100624908, 1692720362, 4162739079, 1171668716, 1019917260, 2960968382, 4239429154, 330832212, 2492679465, 3914351164, 2808889733, 3618854112, 3006959176, 883348238, 1728184215, 749952887, 2053405316, 207244847, 667629088, 3103931639, 3209824599, 4184808738, 117315862, 2026537671, 1562413553, 51345937, 3030421576, 813196369, 1177468730, 1399926526, 3101004500, 718483271, 1666840428, 1341570325, 2878342532, 358644994, 1438403479, 1036501667, 2791104898, 3825098773, 1174900477, 1564073696, 1006841031, 1226328839, 3800714361, 955435755, 1441308303, 2803693950, 3007187706, 3856940286, 1018239338, 1888688014, 1004758210, 332259430, 2579813580, 190823703, 295727938, 3560564104, 4073975972, 1195227660, 2044024465, 1483690487, 1910935996, 2323731591, 744962529, 2081905760, 1333818677, 1904243684, 1957392189, 812731343, 3589031064, 1160013846, 420235851, 3194898584, 3216802636, 3774331753, 3140756417, 1101314431, 3839920531, 3137953037, 542091325, 585982585, 67002391, 574032484, 1082814026, 982927169, 3343037305, 2499327969, 1014383634, 2128207535, 3143311258, 811145884, 1733742038, 1401919609, 2347405339, 1688793501, 130901125, 1385522776, 1610371130, 1332586336, 1524228264, 564391738, 981401281, 196991208, 3182621051, 3793780661, 4081937694, 1011590214, 1557984820, 1386727610, 1596730208, 44173985, 1294188761, 2868988806, 694733848, 1105838051, 1058473773, 345764388, 3923435382, 413963178, 2348630075, 384455613, 1557846890, 3572852130, 227635462, 1553781408, 3368144363, 3190344882, 2500047004, 389502182, 1951032182, 1025162499, 2375933612, 822062590, 375772173, 466764721, 2209593473, 513776010, 1807603230, 1905631247, 2102145812, 1878880833, 261887521, 728430148, 3553454410, 3877709566, 2747867557, 2339647168, 3102826569, 3883347586, 390581341, 2881151029, 1633488411, 2816794805, 2192621063, 543414115, 3832288603, 332599431, 2623361470, 212358006, 4240266170, 684331595, 3519558920, 2607974922, 4281769784, 1880377186, 3258299025, 780109431, 2460011815, 3306081571, 3682519163, 690153507, 2663605533, 1316874873, 435432769, 1844774748, 3579784610, 3192012120, 3816514493, 1486578621, 1711039154, 3024371827, 3961681035, 1833846744, 502498483, 4197209668, 1250998235, 2332362239, 273574790, 3414542188, 3757096517, 21687122, 4149375708, 2775774025, 3885486699, 3764828482, 3169684879, 1117267736, 563210996, 3358060713, 184906203, 260230243, 1407818763, 2566183894, 1022937550, 1704423600, 3768409750, 1675234354, 3205910089, 3849094279, 2775898525, 4171610541, 3027555101, 1995615707, 2875301755, 3119844309, 454813608, 2090164325, 1635654480, 3286845309, 838176838, 700409389, 1759207814, 3708137884, 1734213966, 2458469923, 1120465439, 2280792603, 251883086, 3307893883, 1147090770, 2478925252, 1571333237, 2110931086, 3071393123, 3639019776, 1527571161, 116756486, 4154212295, 4071193782, 160866177, 3822684608, 2812877367, 1187661933, 813375893, 4274355110, 3563648184, 95719798, 2321509863, 1705316827, 2624456109, 3729011434, 1980377637, 81244603, 3643221080, 2327782863, 2796726383, 1095348620, 694915451, 3869647965, 2102740931, 478028556, 4176353850, 1624886689, 1810087026, 3469284847, 279474143, 2654551468, 1650083553, 3786269063, 3975583314, 2715946934, 2176813425, 3911871341, 3162842812, 2484168385, 3039170731, 218808232, 2431971182, 1440889340, 259578859, 2693612833, 3234083238, 2456743001, 4251021668, 3086139771, 2655006781, 2585623969, 1517231877, 2905797824, 2564746181, 3228165387, 3837985644, 1990176697, 1156148007, 2314574003, 2513356051, 3161514242, 395936304, 85293272, 2959851853, 2699879800, 3388798371, 971502522, 25055937, 3578505718, 2265183946, 195596295, 314183619, 325141022, 2254229711, 3167471176, 991640389, 124907210, 1027834766, 306444940, 1237553404, 2020281085, 3652504468, 4166735853, 1579142390, 989985405, 1127757650, 3729807159, 2928562908, 474945706, 2481405227, 2572235402, 1318027793, 2375964164, 2182156758, 1147762477, 312894346, 722913909, 2048214621, 2526350014, 3878110937, 3763322101, 3802543443, 1971787277, 3836674074, 1019754041, 1229366887, 2095273765, 3240112698, 893657076, 1649975247, 1961083610, 4128219362, 3651979629, 560387431, 2272018206, 3455417001, 3591835175, 2202299987, 3219733860, 511772453, 932647786, 2934565812, 2620296847, 1412673738, 432452030, 2699068520, 3290349229, 1260200576, 2387873837, 1020650889, 2896929722, 46043276, 3175381592, 3640150750, 3359402253, 36379711, 2766622628, 1554648268, 423799075, 762803372, 1518772429, 3767916634, 2349860008, 3999813858, 4146982465, 3598588618, 42286784, 2318972122, 158301187, 1413340234, 2569385797, 2986790265, 1601097767, 3186903402, 1492083499, 2186589123, 3007389491, 3890657249, 526248321, 4163624347, 442866336, 1628632908, 3473974029, 3187528117, 785940226, 578554732, 3156675263, 385881021, 4069927986, 2627409796, 2493786632, 1220112150, 2494935162, 3940544959, ], &[ 3863301396, 4107573608, 769303631, 3610738414, 830788656, 4093448067, 3961045012, 32998969, 2051223797, 3423229921, 1904051975, 3173276200, 1228524945, 3991474867, 2558817552, 2412845289, 2693892487, 2807867297, 2840990073, 3357897643, 4077724130, 4256256142, 3215370719, 961574649, 2783373145, 2888444892, 2290228211, 2438375496, 2172850779, 1371470591, 2145309256, 1373633064, 4127606380, 3237788058, 4161678101, 3117205711, 3367678015, 1835932588, 103170075, 2086719399, 3635268234, 1075092783, 2322705303, 1181088871, 2119517037, 1941053194, 2426223899, 1223640157, 2806178916, 1837938782, 3474314935, 1094340946, 1519955632, 2393278998, 2573377932, 1478044003, 1551179941, 1707547400, 836897832, 1100557452, 4127181141, 883244422, 1924787802, 4265368319, 1084411345, 416214779, 3210503977, 270111460, 570730254, 2856794581, 2308577544, 1601765064, 1555967971, 922066792, 2413427606, 2872234780, 2604193566, 3388171005, 1570309289, 2294854396, 2658009782, 2591918480, 3522202025, 231757146, 4204857543, 3547860361, 1464338574, 3046135352, 2156639880, 4202540070, 2025826159, 3098079937, 1936927235, 2324543615, 4118634899, 2173483850, 2792340068, 1873251935, 1329676397, 4043896491, 2309336419, 980209872, 2777302910, 3606217402, 3661029657, 3300621321, 1682483184, 1403461142, 1223784743, 989364098, 4013393779, 3101723344, 3920771322, 3654398113, 659304100, 2541187212, 866322486, 3272793365, 539079315, 691963245, 1257923717, 2386692694, 2687779700, 4058653147, 3991344999, 897061149, 2324025121, 2967160685, 786657051, 2252177489, 980079755, 3131679746, 3324117860, 4055735401, 3845118353, 2451175052, 184232145, 624678568, 2101388835, 4142018772, 2748564864, 2176101753, 290591054, 2465352612, 1359620450, 3705457053, 1692771801, 3882450774, 3055204792, 888363043, 574687565, 1207688631, 2763529019, 568213190, 3846386580, 547028270, 695643805, 3592508514, 3670105804, 2822171601, 869109705, 1004643975, 2589161100, 1630131925, 3278288666, 2691788554, 2121899712, 2397877521, 1435285741, 2269606420, 4256438690, 753043674, 3171716037, 41205438, 3121289912, 1323558351, 1361648638, 851327672, 3104712715, 4004974077, 1301613261, 2833338776, 3359514548, 1454336368, 2759103629, 1960046482, 1092082457, 1499734131, 811024496, 3572058602, 680905751, 300633989, 2424260077, 3501914344, 563961991, 1037919651, 3916889833, 1787252091, 2894072139, 1402432736, 1292040125, 682437315, 2969913946, 314458596, 1751517864, 3350980225, 1439799227, 1636821554, 3406541220, 1219732804, 3202430109, 1914037453, 563664320, 3367122241, 2515249318, 4047342823, 2606550211, 2167198989, 1523186563, 452794059, 1346414345, 3332356711, 1383558530, 2011404918, 2878045272, 3235959584, 2338004003, 3703022278, 976253964, 3367441096, 1031350937, 3245197722, 1599344278, 3041157247, 2825168448, 256034927, 3591345113, 3217325239, 3017793609, 848837066, 2474357857, 1438488646, 3582043621, 3167628029, 3875878184, 750243293, 2350679755, 3998775646, 638861873, 2526770107, 2769525670, 738597950, 1994625812, 3723039945, 2937249595, 3756565658, 3171285120, 1791315722, 62587833, 1395408127, 3693836917, 2738507457, 2306644854, 1474880765, 1160674040, 2845323575, 420810975, 1899118535, 1598631145, 1287542219, 208660872, 2670540827, 4285356488, 3940367467, 2553544428, 3288950243, 2385345193, 1834621976, 2731668575, 826787064, 4129914940, 3098181877, 1647015619, 487963810, 3621584170, 2941528453, 1404599035, 4123744367, 3242445801, 639956074, 1576331544, 3989605601, 262974392, 149652296, 771649267, 2863404594, 212076261, 430647394, 2620118033, 134762381, 3200455716, 1300726789, 2837061400, 630227810, 876215174, 4066609908, 1702081865, 2811686994, 3651804679, 4104022340, 3509034466, 505886247, 2823492341, 3718178477, 2350711654, 1091894884, 991761658, 2416007280, 3262724307, 2788106539, 213178296, 96331913, 2488727943, 318433030, 1284078995, 599654997, 3374493799, 2383380175, 1921627781, 2006909313, 3722858815, 1216826854, 2917401357, 1676843856, 389470213, 334298917, 1965856677, 749841577, 3683568719, 708694228, 337850258, 3111094818, 2782798319, 4005027416, 581456353, 611481801, 1294462617, 29883974, 492092705, 1519669277, 3859693035, 1889037872, 1031737207, 2578726208, 1972815393, 188943053, 1485570324, 526754497, 2470561029, 1220023327, 4210753221, 3493817654, 133559404, 3002705638, 2498655424, 3860497340, 3331608996, 1405034307, 2629878850, 476987772, 3610433569, 1023762843, 658844517, 3090909301, 907135177, 1408007749, 3914369905, 508522333, 3316282642, 1050991069, 4208430570, 3612474296, 3203199646, 3816629579, 2319236875, 479063253, 1512092787, 929610795, 2715987221, 1270125585, 1011146594, 2342272581, 130885952, 3412056503, 4187759189, 882073708, 4183872848, 172107317, 2957726207, 3280137581, 336758918, 1225340863, 2980372021, 727900139, 83467744, 3112049220, 3022765871, 3092091329, 3429841070, 2481778911, 1228662170, 796434253, 3799895828, 4245142305, 4060814107, 32186386, 2762465842, 3106581250, 1879981484, 1044873406, 4245445901, 515382924, 2067565497, 889935212, 1897047746, 1837757206, 101552593, 2684290698, 137909205, 879061337, 1558061909, 2653072754, 4247712148, 951006500, 1219781407, 1073570653, 2696083564, 621148580, 176025161, 3955431920, 2229129171, 3584030730, 1983508788, 3708181991, 2786434403, 1254465085, 846041455, 1592631656, 1522495938, 1934663236, 3068611723, 320091931, 2587695487, 3191009209, 29787986, 468991587, 1595518822, 3373815179, 2308734497, 1843368977, 942275147, 1148248505, 4234927039, 2416737763, 433582485, 1730443177, 15151120, 1912575096, 1589875286, 3467980504, 2102706272, 4064622680, 3321081735, 1278382005, 3743042633, 4094549164, 2003156479, 878239104, 788871490, 3911621039, 2585364529, 3842385316, 3707497759, 4257004160, 108649445, 3177789050, 1363721622, 2898922735, 1467428903, 2019157527, 4024265210, 163512519, 124230527, 2015871258, 4147623411, 1276959372, 3521852578, 3832954702, 223998324, 3663355248, 1866084068, 1034709049, 1357099318, 3064263741, 2772852849, 1112354774, 229271352, 375671972, 3577874614, 1456769098, 2514337878, 2958441448, 2521768862, 2332946402, 1306522363, 2051612216, 1798549572, 2328587715, 250374248, 1181282837, 2401502703, 2561171171, 167987730, 4291774408, 1297255113, 377921436, 896506850, 2666513068, 2215986608, 2417034530, 4103536478, 2650538608, 153287877, 2013466969, 4283997596, 3235129347, 1597613202, 3775501616, 940975219, 3651296726, 3935519507, 1711331252, 1382619450, 98804289, 2828250792, 1113234481, 879722963, 4181357652, 335298543, 298230884, 2842345357, 2897108219, 2131811279, 1610217235, 2935752175, 1980703969, 96565072, 2285804804, 3441818431, 4027097405, 1453644439, 1404165497, 2137407333, 4133788414, 2012339193, 2914917166, 1212496804, 863513903, 3641661674, 2344878371, 1624332397, 3193401691, 3589187922, 3492743685, 1074343035, 3549688503, 1235879378, 272458456, 1530905055, 633600272, 952169022, 694842255, 2924520177, 3733576543, 3412038548, 3355971570, 3319754603, 35156185, 2711361786, 1908801108, 2007786947, 1471019471, 682257175, 3452454141, 4086992517, 619063037, 3527436755, 873637727, 2540048683, 4216590989, 2517973204, 856413582, 3410373161, 3976252825, 1076697656, 4084517409, 3558844395, 1708431648, 4121221409, 500433207, 69169381, 3518331925, 1903010337, 2945573052, 1916961424, 2296550276, 1473104968, 570605625, 2970669612, 2930435606, 1407290785, 1362262639, 1643553808, 1379331415, 814987507, 3738591405, 868048552, 609381189, 3044266817, 1073709216, 2273520370, 4174096914, 3211778166, 1775963388, 4195045652, 3903545039, 27421359, 2831518698, 2264275203, 3825390392, 991249490, 2033327389, 3437683812, 3589994222, 2095797327, 2693270490, 2446965435, 3532382189, 4225020538, 2438827018, 3599722660, 2059526307, 916675930, 4032044649, 3832545177, 4265752161, 2025270161, 1700180813, 2724405129, 894375853, 2158154452, 1992158364, 1104234105, 4095063140, 549680132, 295278223, 3399425354, 502455385, 925070896, 25265139, 3138056117, 2485080362, 3122750407, 2110469673, 2519059530, 2245336963, 386180475, 103198797, 189274207, 3711966958, 1497301749, 2091705140, 2998746394, 3197222872, 1586189053, 2434615335, 865658181, 410299428, 283623349, 2593258180, 3319619642, 111650022, 3054665890, 3379592188, 362888191, 1774728950, 698157433, 1196199247, 231783178, 3854883494, 944662656, 2849527466, 18761251, 757793978, 3575863519, 1522566520, 935676887, 2205620771, 848824700, 487422055, 3045852915, 2821647442, 942847641, 2420057003, 4122422133, 3221662523, 3948174115, 1511012575, 2712620547, 154277939, 1260340613, 764036546, 1258666603, 2736493060, 2398218922, 332369172, 3321255431, 3735363230, 3130335168, 1471863620, 2350818699, 1666699401, 263809178, 225879205, 3475801107, 41747506, 1281025890, 2613054861, 1941686229, 2161424264, 998469013, 1567825824, 2708371812, 4234191147, 1416171194, 893931380, 965714073, 595159859, 2094181000, 1274027425, 3400425068, 960344775, 2934909672, 552371896, 3250358914, 2867135600, 714318092, 3437291998, 1218637856, 2592190957, 3215592510, 1154397448, 92253472, 729368671, 1238758682, 876266136, 2532748595, 3277383450, 2002640396, 1096082385, 3097263866, 3774645444, 143160707, 820702860, 2963502810, 2295329126, 1738773598, 1662291270, 2109612228, 2254641499, 82516534, 3161744187, 3679464233, 1358033344, 2995955069, 3624029481, 2392653637, 163541126, 103712334, 304309084, 84468238, 2162950986, 4246306060, 262053879, 894859385, 1440182788, 3032139842, 3204874529, 900031376, 4267138270, 1841498413, 3989603237, 381201084, 52369466, 3293766866, 3539091133, 2826516997, 451466955, 1474183607, 1650264638, 55944005, 922622657, 1648352125, 2905899264, 2376709984, 494615258, 2094380542, 1818828149, 633848924, 217595087, 2514129298, 2686868725, 1334881256, 945657314, 3287435007, 2934095457, 3252504849, 2198733907, 3325659469, 3651948905, 2792934808, 3967802298, 2660224790, 2498216702, 2191920241, 1388358405, 1762131463, 3930963570, 2634828966, 157650978, 3583842536, 3242164879, 3088432937, 1681039203, 3521823186, 2711390389, 537666406, 376858519, 3748935340, 4140298933, 3491468466, 712574481, 2722290823, 3829138812, 4159064276, 2077023449, 927927769, 2794552777, 478084560, 3993993319, 2103681826, 1287040024, 3438112843, 946795562, 3787267183, 1066818694, 3032121002, 2604020549, 768054703, 2506165286, 1915485245, 3059742383, 2693940456, 1983217549, 2556130441, 3043340405, 2402731290, 1100667933, 804329802, 442779347, 559541894, 1528504026, 2430094040, 380854895, 1924878482, 1122304788, 72444675, 3969057890, 714896496, 1494340534, 597259814, 3447834580, 2159188321, 1818909926, 3314125974, 4200637638, 2442370766, 343066112, 2918772200, 1301372507, 1469386163, 2329124057, 1063769022, 1976395812, 1172302345, 3034217238, 2565781187, 1333195768, 1802803443, 3542179279, 2595530300, 1298867338, 2131992457, 4008141933, 3551156725, 1910959429, 926841893, 722213632, 3001255255, 2877951087, 951003498, 1850325282, 961774018, 2564886523, 3851438777, 894949398, 256796330, 1959581786, 2633182213, 347574201, 1192307709, 3562336091, 4219631762, 3241567097, 2990515345, 2420064232, 2970262593, 1461569831, 959873136, 339106858, 1193176040, 958105449, 73335412, 414655367, 2703505850, 3523782649, 1836045931, 2238239231, 622571598, 2306296237, 2739009399, 2235729403, 4049021645, 1139357889, 3707063481, 3027045705, 2536246044, 3463101979, 164310463, 3068187810, 3712847292, 1194203136, 315781630, 3635235621, 3210331632, 3843708250, 1994373266, 1594553425, 774598913, 4048276724, 789636282, 3215162174, 2262339544, 1305015749, 4007832380, 599420190, 2326564224, 2581496076, 1490199678, 2345840465, 2587986101, 2223352107, 899040275, 2032648532, 492046170, 2775769948, 4025191184, 2066154698, 3282686682, 1947023303, 877230065, 2379757900, 1421079241, 1472867997, 1256546466, 2015075685, 564334856, 1596942756, 2067271158, 1525094696, 933563085, 2736916537, 1289719444, 2825124575, 538020056, 1948821945, 3347107101, 2079729373, 1572505804, 3433209293, 1344499437, 3949051563, 3232199037, 3082371535, 1331266164, 107382829, 600011905, 2444019204, 588880467, 3129757140, 464629376, 849856979, 423898800, 88832098, 1081264490, 984244991, 2741490369, 302293134, 264947875, 3559707631, 3163924576, 3570999744, 3669081938, 2295906825, 2650299087, 1113300657, 905751103, 500693370, 2100014668, 3986098399, 1812213805, 2493587511, 950742301, 3760594111, 1988198331, 1873596690, 2635981672, 869076633, 2899275440, 909196488, 426688577, 1424894512, 2514329532, 1429386171, 1601662235, 698006110, 3413993105, 2770364726, 2118460870, 2739235711, 985371284, 1878394461, 2601294175, 682033607, 3495222984, 3705210174, 363192243, 2726571167, 128884760, 1240146787, 3016436128, 3416184840, 3975805871, 1867343818, 367917036, 2840825415, 3109229134, 86399602, 29168346, 643436421, 855684886, 2698919498, 2573030045, 1310289643, 2632411665, 3280803400, 3031393328, 2706966620, 757184666, 1870090363, 1089529774, 405908185, 3185354428, 2211285265, 3069886124, 1833781576, 4109099359, 2041763376, 1412307932, 1108344823, 2934287361, 3748982678, 997317374, 4034047498, 1589982531, 4000312659, 961015296, 3096991478, 1531557499, 3851171859, 3915206184, 3845090477, 360397185, 3650820078, 2671471668, 3582096970, 98103656, 293910129, 688011927, 2301307999, 891574533, 1096467904, 1772826405, 2251911696, 257754158, 3595310014, 3071881112, 330145073, 2003841156, 3503655584, 2500095275, 2581430324, 3750572141, 2399342110, 793019159, 2908904187, 3048524529, 3121098597, 2426325849, 3141829183, 730031729, 631358017, 2816312406, 2140259643, 2705520489, 249478212, 3810678698, 112873024, 1316257435, 3829349326, 512530284, 1791055446, 977334578, 2132878588, 885903211, 1036930474, 3730775044, 1701720120, 2244244496, 1471396055, 4218527872, 2282408914, 2863265592, 2524710962, 3681247194, 1021315023, 1936348533, 763047529, 1864565264, 4056081562, 1341771220, 3280140661, 470866172, 491650059, 833461558, 3663381328, 3131958008, 3888395947, 190302498, 3369220408, 3194531411, 4268320815, 641711829, 4145336402, 3637433757, 3916511879, 2178833411, 3528637090, 921304408, 848707877, 74460658, 4156338096, 3758212244, 4041754743, 3783679569, 2464912581, 389100529, 2749390487, 1272451842, 1982831993, 3205451183, 3611482027, 2856507974, 3045919911, 787026444, 3326213299, 3742042988, 1179040305, 1079935839, 1099752002, 2208759695, 3321518120, 625037743, 1196410750, 2539925852, 3637757870, 4076045265, 2521116350, 257980137, 1792560058, 4080511201, 2295460214, 3430291767, 2341109458, 2373054528, 2964565865, 448201628, 2789539343, 3122329385, 1041274565, 1354785628, 1790951895, 3835101816, 2927123449, 1699998449, 822436141, 442731999, 253622870, 2051004295, 2119605933, 788752772, 3859931127, 3342223111, 1766122016, 2442973203, 684168317, 1723020245, 154195179, 3840290724, 197981657, 3225996975, 1370627218, 1351642439, 3678888257, 2134899360, 1190824919, 2672793161, 2594374637, 4003067381, 3768518618, 983310739, 756053185, 740998700, 170333885, 353078645, 3235856060, 1175961245, 3465368919, 2715457241, 25728426, 1205273122, 1007876083, 2046909066, 3387646551, 300617592, 2304621094, 1783616228, 4108300103, 586016796, 3730618599, 3601593992, 1497117442, 1382687044, 856047991, 3446843207, 2718610562, 1648426450, 316212126, 3770040316, 4085290555, 3839828266, 1824200161, 1558151259, 2451017528, 4144269623, 1926063180, 3430941798, 3283263584, 3623728522, 1321248896, 2213285073, 1427594731, 2251376848, 3156851965, 3184709111, 3145527411, 3930726181, 3730945673, 846201422, 731360758, 4265684973, 1939059752, 2176908121, 4194865292, 4067633000, 2038583049, 3475282686, 1326107151, 498945469, 3441081476, 2360019237, 1877755648, 2980984493, 937159856, 1765157866, 3158122715, 2419599545, 686694843, 3369792550, 1593995909, 3205417509, 972506778, 1749567615, 2334033091, 3965294821, 510805665, 1753849516, 249859705, 2412460463, 2378513928, 2986924333, 2985311978, 1103056985, 1321159371, 3294519955, 929620231, 4106207278, 4270651331, 3587554722, 2548230974, 1382890621, 3583771152, 3542820493, 1248566046, 1451098024, 2031079077, 2958317520, 408683181, 1322401171, 739053183, 2763421668, 2050043200, 2027533054, 3479908048, 1846767499, 937808196, 4080393047, 618895890, 345507295, 3836887679, 3486959977, 673180241, 2986760251, 609039359, 3790679251, 2816013571, 3674501891, 2510023654, 2140217074, 1918529247, 1295289994, 2852923944, 2968882596, 2374994285, 2339464893, 3530889069, 2047732915, 1888856899, 2303610, 1266797804, 2451766648, 2651393253, 4200986449, 1305014630, 2017208592, 1878532929, 2601631173, 3905586154, 3600492846, 3185555607, 3685032847, 2313651900, 2203112200, 2821359262, 3290447334, 2051909399, 2681200978, 2681643754, 2030516748, 2198940390, 560748330, 3035412164, 2222960210, 928429057, 1269561797, 1103973285, 3614653856, 2885465202, 2451268620, 3178535744, 3816260981, 2989224422, 1462753367, 2867544236, 3638993558, 2857844328, 871331601, 3290183874, 3357526835, 258572105, 74152014, 712442772, 1849061379, 2049304441, 1088152569, 2456861437, 4193739116, 903105013, 991152330, 3610977022, 3586484046, 2744021039, 2290293141, 265948355, 3393021731, 3823630150, 3404747914, 1260993824, 1021536000, 1793676912, 1445707769, 548650645, 2471023129, 1722482397, 1598031653, 1594850289, 3998091782, 2583735047, 4112635463, 4234758004, 61638741, 3499059311, 4255669520, 15597809, 4087916888, 3362090556, 613317221, 3135646367, 3745275152, 4183259686, 3005121894, 507799850, 718271315, 1030377735, 2148053708, 2062123531, 3453548255, 4131065481, 3413716172, 1106611811, 2253913656, 1217267302, 3521325090, 3202345697, 121303188, 2221607947, 200493459, 1536064549, 3701264585, 902459672, 2821419562, 3071361031, 1740183748, 2204817065, 2794368953, 2538416643, 1337013619, 1616927622, 3369284587, 306231805, 2471779547, 3343914379, 611812604, 3026990327, 1335972784, 2378840193, 139258552, 3711256482, 1887306531, 1842343803, 490997472, 1573143855, 2397027602, 114182794, 4008507325, 383983854, 3474881466, 1166904981, 1175073889, 1110485910, 3196990699, 4043619493, 805814251, 3373120547, 3788327425, 1533909416, 122434679, 3233582914, 295171787, 3657217515, 1578609722, 1948311121, 3999105875, 926524223, 1716729206, 2647249755, 1295295684, 1398742476, 1293649163, 3301318792, 1249107492, 3524708489, 900623614, 370317173, 3023227877, 2970370655, 438972951, 1453396240, 1074644125, 3045346916, 3937515917, 3535500112, 15511707, 21092320, 1808975979, 1836053162, 1131843404, 3321948476, 3302484273, 1327089406, 1414697348, 3320224015, 3616020523, 2344106677, 3914949717, 1612099005, 3159929782, 3472685206, 822813935, 1667292129, 976813491, 524378253, 1423919370, 1608169807, 273400699, 4009308334, 2421399647, 2280736582, 2766712283, 880839455, 2987899032, 2225630634, 2180172035, 2543875929, 2519364125, 3173433087, 1374125784, 3773143786, 874684944, 2053073738, 2343241744, 1895902701, 2366578082, 3825280261, 3757786236, 487512505, 1439635617, 1938815713, 2765729372, 3899164654, 3939832878, 4093082626, 1667022796, 3717556594, 3576843936, 499863677, 309936726, 3673342852, 1506381090, 3981017018, 133430156, 2132647863, 3475909759, 3665468568, 1623556555, 1085940983, 1366059584, 3025235319, 2970652374, 918600524, 2658744166, 2146092500, 2559792540, 3027296124, 3707023583, 739669772, 2930461897, 4224273847, 662889673, 1789566189, 2115222049, 2306045628, 1477918479, 3477961272, 2200326274, 2369335807, 2494565418, 1530641215, 1856911599, 1275429767, 866170004, 2745000546, 472242075, 1148993577, 798297321, 55095409, 2748938057, 929342181, 3387367510, 2828846404, 3637875254, 3732596202, 1557186170, 3381990740, 3426821093, 2834907694, 3939509161, 256757454, 3493347492, 1430037675, 724227592, 3233425142, 4193858302, 3143893061, 1935755610, 3752077517, 371021776, 1488573226, 3656803611, 1397487558, 114178560, 4143176526, 2827786662, 699057361, 3618652178, 3599020362, 883404904, 4076765018, 2869084935, 3430236310, 1142749989, 858868390, 2586327245, 3689072619, 3252574271, 3363933552, 3954232405, 2841098694, 1982066393, 2919650679, 972054529, 4263034065, 4202926574, 368921376, 2413687507, 1964998417, 1988513324, 1398922010, 672186161, 2525728596, 823408642, 350612408, 535241906, 4193747053, 3792454954, 4256440194, 946622562, 2670085778, 1489269745, 1957616797, 4145373127, 1921334332, 1154509428, 655312838, 338018742, 1492255818, 2530469964, 1474144450, 2544683314, 3920946287, 2107625122, 3071888029, 1093629422, 3957291155, 730207247, 687256411, 3258444139, 3382358863, 3665785701, 2294231690, 2744545482, 318434024, 1834441139, 3028059443, 1871862592, 1485031020, 2593743370, 697263431, 2210865421, 886961312, 2439951771, 898199987, 3761197168, 124724274, 2825616292, 2116702434, 1827284511, 1436381597, 1143344478, 2186418061, 2883101965, 378396187, 202806650, 3493016233, 3939805873, 3409895940, 3163956514, 3373046225, 2392603855, 2395190604, 3887042662, 966537920, 1465769860, 3846762642, 1449184266, 3361962069, 1673370925, 2958808530, 2121780302, 1683265706, 3285605311, 3961408003, 1543405091, 3037678236, 2408131699, 1787522757, 532868180, 3660710907, 737195751, 2579810447, 96617884, 2062138541, 2841404191, 1126197758, 772281033, 2192259642, 4125174714, 1587858335, 2227253460, 3228097564, 3808342348, 1930401381, 1718652876, 2762016003, 1896072752, 346749331, 3331590536, 2680437094, 1358381816, 1219099791, 2113769757, 514300773, 1510306590, 2620476138, 4192783798, 1375258173, 1517398070, 930184940, 3398516162, 2751947685, 1774049194, 3212098936, 1853827081, 1551809481, 4006909361, 4078910330, 1093611256, 3546035934, 3855068033, 858010820, 2321366198, 258458600, 3514203269, 1963201552, 1421264067, 1283367171, 441633157, 1845368475, 3362267277, 1133521382, 3051588901, 3331080283, 226988630, 2950015695, 1136423795, 27821883, 3776906112, 1472027322, 3101124287, 680641770, 1610005117, 4267303048, 2779573177, 145212881, 787862669, 2540284848, 2542323265, 3107232433, 2803967209, 1022688977, 2623452425, 3494748854, 111839415, 3449508061, 2614845097, 4279526745, 449560047, 382457375, 3060479998, 2948798581, 3774205704, 293384035, 1606331620, 4042994563, 565887987, 1141791257, 2033992531, 824325187, 3271632932, 3344669331, 205920938, 517437389, 3974257596, 1307157514, 3477428627, 2698403329, 3240285673, 1192057106, 1071891060, 3673531594, 923453309, 3687423291, 2724369809, 2003024538, 3800279676, 2094946084, 497354294, 1824040717, 2958898075, 2581987757, 4122751267, 1424305065, 1354551820, 4236177572, 1793895565, 4030145142, 3660321673, 2018007866, 4213196204, 1668717301, 2070438973, 3539891506, 3346804175, 1928891907, 530432338, 1978654608, 55791536, 3348858146, 154895971, 292221119, 2987688682, 1164399118, 2430342431, 2428527198, 2496113248, 454730991, 1971063328, 1258681134, 1813932199, 210407227, 3340111973, 1084627479, 1064216514, 4064722485, 2215309052, 2993288075, 3146502847, 1831511244, 2280232151, 1590405456, 2200667755, 1628965450, 2761404145, 3717575260, 3798572094, 493632921, 255074552, 2384177829, 2778689435, 659238302, 2327047407, 832728694, 3100546768, 81046048, 2887377108, 578242373, 2799531209, 1295083006, 3419337072, 1345094121, 3216919515, 2343387385, 4153152162, 2161067647, 1022049107, 119048368, 3916106008, 565831742, 2794988440, 800430879, 2447084785, 453855289, 4132400296, 2669036842, 296861197, 2202167592, 661965250, 909220018, 1527898574, 2667058573, 588621789, 1998764042, 372858612, 1477125875, 2647615554, 1983954649, 2388809988, 2016597037, 1089073774, 3433137953, 815616715, 551673059, 894250325, 1559189236, 18389714, 4228703818, 517820013, 2111620514, 2544469443, 389336009, 4175846461, 1243110116, 4108914066, 1211738389, 793931364, 1801248621, 472881962, 2841706465, 1274000666, 2209746053, 2475239540, 275807348, 3274559590, 278907706, 215711806, 461479011, 35786016, 2256077091, 3898546316, 2586194294, 2834624674, 3854613059, 349247533, 3330821143, 2484986035, 1118490626, 109596634, 1102082878, 3639363802, 4123644328, 583993094, 950048702, 3739148555, 989914794, 1878111588, 1705085869, 1515179520, 71552189, 2889476532, 289469054, 3359213779, 998546497, 1617722977, 4210818802, 2212383714, 42057675, 1064166190, 3128172126, 2743461504, 2779205797, 3839262319, 2645572700, 4040270163, 1638247754, 4271726795, 470879176, 3889433544, 3751756626, 2995468452, 2585565812, 999116819, 3508547190, 2161381426, 1016925093, 1000171248, 1494314082, 4022087643, 1102083259, 4009453582, 4186192569, 3212042270, 2178496725, 1460473606, 4018333955, 2005109618, 4283613923, 2169746853, 2524549630, 3509522975, 720025572, 3624177652, 1590493281, 56530035, 1056103439, 3171190085, 2733026440, 2459096713, 2043383257, 3089026843, 159409060, 1417617528, 680269607, 3936036271, 3533484516, 436828291, 1110616994, 1409703119, 3293167841, 3330632855, 1806501600, 665466700, 2138584065, 1134927945, 2636023322, 902992604, 1467516266, 3163905998, 2748534143, 3338909086, 2773650360, 2351882854, 2618618051, 1307786697, 1329236348, 2960590099, 2274451740, 2016354728, 2239789753, 3033989968, 1384792327, 922785320, 92821760, 438784782, 3757769042, 567367146, 1003466644, 1726035240, 2262967263, 2726288557, 4095316988, 4477560, 4043153559, 3917834466, 2042703909, 3964168936, 2533496967, 565827498, 3044782857, 1426618089, 50646973, 2813326961, 3628087749, 2907344581, 2537993920, 3598160970, 1028651184, 1717080965, 3269360889, 570217843, 4186276351, 1082213825, 926440426, 2070827707, 3294185079, 2449173840, 86727007, 1435055586, 3065557879, 2351425539, 1286878886, 3818639923, 4286969439, 3271121683, 2981208936, 471223863, 1362601479, 3999136827, 2947233786, 2942179272, 4165102641, 1585257917, 3601973938, 3372610933, 4045268939, 3936571497, 2375540043, 1711605304, 2745105944, 60319076, 846801314, 3244316989, 3280757716, 3106180603, 1876680557, 2199367803, 2589208677, 721055873, 922630059, 1548218484, 2646172490, 2856162971, 861677714, 2013479067, 4125064047, 3135259174, 1987391034, 1612240980, 3901607644, 1989084918, 4064704523, 1617603086, 3624548836, 4228236160, 951778179, 2258253293, 2844302721, 221571638, 45481005, 4115699132, 1497796421, 4267752533, 891937890, 1035077096, 2209048878, 2922535041, 3098592820, 4042474064, 1697703755, 2399789403, 424377247, 2260587022, 2193368797, 600282097, 2742041813, 1336804874, 2650658716, 2970310817, 4045380756, 2688502007, 3926497235, 1096372043, 1338172683, 1237644267, 2798132618, 4214417948, 350223564, 2294825555, 4042231686, 257708548, 677230641, 1925625022, 4241883500, 2695106980, 3028571259, 2887580741, 1180867256, 954435786, 1057867101, 1558741430, 3348329056, 866764562, 3344476407, 1111689088, 187045741, 2391307551, 2959008045, 3948691948, 1319187960, 675359019, 2984386771, 1840667056, 488976976, 2325589449, 3007129454, 408435318, 3694608179, 2542389000, 3687602293, 1123412948, 1374633563, 2112015185, 2546930077, 2404921048, 1414947884, 404979651, 3135158757, 1510573459, 1710196771, 2713693744, 1070462689, 1213959292, 2534266780, 661012500, 1874896877, 3271767429, 3275230980, 4264750161, 3572375081, 1579194793, 1742321855, 1961359715, 1488092333, 2831928507, 2798998762, 3843198441, 3176393593, 3214277128, 2393328325, 3566395385, 2774611529, 1428232834, 2110323330, 791378925, 216120541, 3861236968, 231370989, 2639794499, 624599731, 1219997589, 3787521330, 604314725, 3461276607, 4050374542, 3642233765, 194872120, 189897179, 3261758346, 469130126, 3340624526, 968498604, 355999757, 3837862051, 3904146415, 2873860611, 869804381, 299440640, 3520424116, 467765288, 1174495386, 3568117911, 3678085175, 1146375992, 2008699612, 2353114304, 1071351122, 2303361684, 862351484, 1648692826, 1224344365, 4272397711, 4083818503, 513078016, 4124881085, 1496441405, 4009634631, 2028357190, 2064925965, 130259652, 4158281641, 3339267074, 2346473402, 3040620475, 302567288, 2098529576, 2557666596, 3815840311, 683165531, 2914308335, 4044834414, 4252332010, 3278908623, 769564314, 3697741763, 2167955348, 3203861471, 2126706587, 2456367636, 3772712294, 2092879871, 863396039, 508902802, 2793550452, 2693435437, 1391736628, 1157153689, 1409894468, 807646877, 271880092, 2088023280, 827665392, 1435968155, 529346767, 3332013609, 1707352770, 1166889197, 3084999870, 2984300978, 2396541821, 780406104, 4069234239, 1386380802, 3372735777, 3654121391, 2926997272, 3418571197, 481723726, 156396805, 3225545154, 136794862, 1845380077, 1434076416, 2469706378, 1818524696, 1020300445, 3961599464, 1347758807, 1580244193, 3105582525, 4224693377, 85103854, 221740682, 583809331, 1876617658, 190405249, 434449658, 1905985766, 1004630479, 534307076, 3645762882, 1516085517, 1235003680, 1311064464, 892154476, 3004766628, 1015993206, 249377204, 3871066261, 2893118754, 2466150031, 2139448418, 4269228198, 512105997, 2790471018, 3932220953, 1659370949, 81403428, 356737648, 4153182358, 3806788782, 2102548424, 3227939175, 3000515829, 1141241618, 856180425, 1217257095, 291825148, 29808179, 946834904, 2727274069, 2659003572, 2778333831, 170117914, 2900631470, 1650666906, 3004242406, 3422959408, 4060912839, 114575898, 1842399219, 962270342, 3676883280, 2930727789, 3839654913, 2161690357, 680073756, 1898043108, 3687931421, 3644299988, 2354196541, 2450591233, 3155696561, 2851736135, 200426970, 3098061401, 1143058922, 2859561130, 191439515, 2380738368, 3453524409, 243865967, 4204885436, 1854308264, 2651192364, 215699541, 3667750969, 92453718, 2870815953, 2350285294, 2860516750, 180810177, 3523383186, 132903803, 2874303329, 1836934344, 1769424123, 2074849407, 2436859811, 796104248, 3837530147, 2693412114, 865664534, 274559048, 3156205156, 3318629936, 725125344, 927243554, 3507933982, 2771564181, 511265012, 2360434429, 790740438, 67312079, 2232773510, 4159603181, 2666116581, 911742448, 2773650983, 1537336504, 1123767928, 1245244759, 755395243, 2230363192, 2311150865, 1310905897, 3635633537, 915322772, 3309277755, 4102148078, 2737064941, 116557272, 3395885355, 3492962591, 2154943050, 4283933288, 1187022256, 2337945824, 2140138623, 1243490701, 1664618771, 2723135057, 477750234, 519210867, 990489192, 2010998441, 2405731553, 2328924508, 1027928316, 1471509675, 448099363, 2464256239, 3912226872, 2086652210, 3206856094, 7300210, 1998193697, 943722522, 254166499, 2111943630, 1127624858, 4001349711, 3044456286, 1531676981, 3763383233, 523495565, 625810415, 4285822939, 1882476395, 295164493, 3251126307, 264629432, 3058573006, 4222655455, 4193922449, 1947989063, 1625940097, 965463176, 1540545082, 4269802379, 3096278327, 1917287030, 811928072, 2021954213, 3352534952, 2069143641, 1011142292, 2013199459, 1983584044, 3378795515, 1073003188, 3542525645, 4256818813, 2893719471, 3997051418, 2019353119, 3254985548, 3031865, 313156230, 1875615965, 3520020372, 2398543168, 269701833, 3585027713, 2172521845, 2365672940, 1148380788, 1918167676, 4244569795, 2283551383, 727538472, 1530708679, 2512271941, 2142650333, 4236443712, 2249548500, 66575576, 3430978190, 4160214541, 2373906807, 4038023459, 3358632548, 3594956519, 1035453391, 4145796024, 1156514907, 1246913527, 2241586732, 3979448944, 4224967589, 92230190, 3201011336, 786008427, 909198170, 2192884584, 1418258734, 2169216084, 3388716292, 3273421687, 2807726209, 3178922474, 1243431685, 1921275148, 2464361452, 1596390320, 776990882, 1812414638, 437620977, 12213113, 4179461440, 498724925, 1371593337, 2419938007, 3418848663, 3084795577, 2099025380, 450764221, 3933062083, 2894530307, ], &[ 169261212, 97019657, 2010098423, 3060596318, 2200430153, 2869077638, 3698742283, 630687593, 1344435198, 14077903, 384687684, 536665320, 33712500, 1110160663, 1132275258, 755052985, 3538444513, 2168204486, 1431872026, 2944859263, 151411172, 2055104382, 2850392235, 3204051758, 432306835, 811337238, 2814548049, 2643221792, 4046346365, 3018313224, 1385088585, 2725111255, 3634261412, 2210377846, 1304209844, 3231053663, 931121572, 3651371093, 2734237688, 1736817020, 1266539929, 2040761720, 580656351, 672494919, 1095514416, 1562672852, 4036170315, 2378771331, 3846827522, 752910893, 130805753, 1015401095, 2737607490, 4133741161, 410356140, 2533339641, 2271585092, 2961265479, 2637760446, 2158261474, 680899708, 163993353, 2997711760, 4215808749, 3723292800, 2192481625, 2556236735, 3085843169, 3092082759, 2465630516, 3247488074, 1705364646, 814558461, 3702622021, 241980441, 4140873510, 3885766880, 4012271283, 3999222517, 148661894, 1282933302, 1770982817, 3186160246, 1901652026, 4066201988, 2160372795, 3268508049, 1795046973, 866721742, 2075628922, 2807956783, 3295312433, 1999667844, 1333068683, 1149723459, 72589844, 1092560851, 4282555118, 3510140080, 522259828, 3385050651, 1937511732, 761458722, 1293935175, 2214664794, 10242119, 3063498224, 4222607771, 642844662, 1351241302, 1536474598, 4122373319, 3737795066, 2617562249, 2974564444, 3058044388, 2028712828, 1829321567, 2548853558, 2574521694, 3312702962, 1865006140, 1501367075, 456299067, 2942841642, 4196219184, 3498196346, 2569794425, 3802868405, 356077732, 3430096358, 1630488232, 1667012225, 1212294536, 538718198, 1407896138, 3172899401, 4248307113, 2864880507, 2852924732, 1281650298, 3789759257, 2435025122, 2392372329, 1516476552, 3800421041, 4033823692, 1936348564, 1434124331, 3273281793, 3592180633, 3962067590, 4287698149, 1519025535, 3563650753, 481915643, 196362100, 1760975324, 387341865, 4218232910, 223829427, 3264588279, 2066845936, 1898648367, 1048579696, 2407743538, 688452394, 1749433021, 1355601447, 820585203, 1020713467, 4173935621, 3483593644, 487816899, 93580477, 2944973103, 2300781257, 3103447323, 2951726120, 1970055032, 3830054424, 2489896194, 1046031109, 2245455797, 1867332719, 3150097735, 487517766, 2966736739, 4061236172, 2438285500, 1032477139, 364267316, 2952150398, 858946610, 1472690045, 920469949, 2209121191, 864450987, 3106150723, 2969726486, 2845130450, 1849358041, 3005036358, 4235423404, 97347937, 175921091, 1348170234, 770199516, 365087161, 991425113, 1533529912, 3818277147, 709418670, 4199014005, 1109879416, 3319928498, 757645463, 258144610, 2336236633, 650087839, 147117363, 812176287, 3720773532, 36900249, 2987629201, 720304279, 2467854235, 3815514608, 1066410164, 2802842865, 2173716894, 1982188941, 1128651664, 3558904900, 4058483597, 3270204162, 1330681110, 758186224, 2172595164, 1448125003, 2173830084, 3215033023, 1851182505, 2713002256, 3835030966, 2229814851, 2233929591, 2244641624, 1171786638, 1378913849, 1556728648, 2949947972, 4074487734, 1505921507, 748234195, 3600080354, 2028262296, 1470704954, 3470426878, 3122530841, 2410213039, 3408701679, 2501278564, 2084471422, 4258561313, 69281285, 77000318, 2036112677, 3928311555, 4243023562, 4014794170, 2383505475, 3292068789, 2907501855, 3311234451, 1145983385, 3319882794, 3653205285, 3725028918, 3729871024, 1390021708, 4222789914, 218974342, 3821348650, 1368295153, 1279495709, 4278066442, 3297583909, 1821526324, 2973731013, 1041979214, 489278942, 2124166216, 3405155013, 2219346020, 1318848327, 1829360017, 4134292239, 1354535698, 3077327835, 3264258673, 2012426550, 4177109126, 601960462, 3163195869, 1445745889, 898171740, 827204772, 2258489433, 2062776641, 1021468635, 2390809492, 534241200, 1797102980, 1845684576, 2118715856, 72319402, 413085624, 4008263605, 632503759, 1686868824, 1754787516, 4294687573, 2013002089, 803099033, 1273543325, 4245916534, 3037861929, 2991538180, 1799210280, 3000981395, 499844317, 2877414269, 2329779164, 4220434292, 562828242, 2741213468, 1944223012, 1861372602, 819033522, 2681839553, 828991290, 928793250, 2344560370, 673594463, 3751423502, 3807439725, 3979850161, 3547495108, 3707143288, 1858125101, 4142196157, 2373721462, 1518142446, 1548054547, 442881448, 1738298750, 453949092, 1970124231, 3424857338, 1820967071, 1736209613, 1091836295, 2809423605, 3481631497, 133425586, 4015083333, 1984612975, 923514530, 655227462, 2775293769, 2712696699, 828247566, 3829922109, 3871571738, 675598020, 555032496, 923212291, 639720389, 2919964342, 4004944983, 2217510339, 1925954172, 2418913014, 589615454, 435489824, 2245278741, 3491912204, 3342199322, 4013531036, 3426342754, 678591516, 4258986026, 1682355128, 788886889, 2218536681, 1317056760, 750073663, 1793777336, 518564031, 3108963423, 1523426771, 1198654802, 2719985938, 521075618, 745829783, 2389591028, 3716963027, 2238978453, 403983408, 3781517404, 1836423104, 2198030139, 2302949603, 4173024897, 392102066, 930721646, 1094357046, 3808728794, 2852832081, 2314321478, 150826424, 711452896, 647663402, 3016271507, 213728995, 4127389886, 3720742331, 874266103, 712172019, 1315187042, 729949129, 2284688094, 1817849857, 2709846568, 3092049463, 1161688426, 56968775, 2489474475, 1404650164, 263784267, 908154757, 4290307608, 1375864071, 2725649740, 1247176526, 3679406490, 4236673427, 413662550, 3792331497, 479205991, 2852263799, 1042720125, 3950417785, 1001301598, 4015555465, 334867024, 4253731418, 764002502, 1119482483, 980052531, 1558968415, 116027612, 3045193528, 216886097, 3377362470, 452394673, 2745755946, 3996292608, 2672041571, 1369242942, 3549593046, 217715905, 1091134633, 1780559106, 2338755733, 811628867, 314006903, 655439900, 1803434434, 2061142553, 1119728935, 3070087224, 2533572837, 1408968356, 2424595522, 2737313431, 1127783352, 2637282584, 641318539, 2988938943, 1101438454, 354997500, 1532790146, 1946117468, 1260866996, 3198198219, 10975301, 3918093929, 2825812082, 538313674, 1768430706, 3738638001, 2667074884, 3358956925, 2410322745, 1076744040, 375884360, 3751703965, 3161863052, 1457146467, 3832520550, 3233502144, 3669902726, 245281689, 980364295, 3800611124, 3491342490, 579797343, 4250558994, 4153483609, 4258531200, 572001069, 453700369, 579285386, 1726550780, 677036467, 864962793, 4131217567, 2169450313, 3795432981, 3369719591, 1347751707, 2987508248, 589435126, 849216358, 80245949, 3523392244, 1329490478, 2846195592, 1283476607, 3988324775, 1226554934, 2524758910, 4115217052, 264772855, 846505996, 1974293917, 3071402363, 171606341, 80617760, 1218055661, 4202796081, 1431247412, 1205540953, 1035047106, 1562320516, 3549999782, 1724161454, 1280483311, 2462179501, 604829659, 768655290, 1447536294, 144890904, 1718444137, 253182878, 2781922595, 2107474328, 3912782422, 2132300849, 252022782, 4071842247, 536916710, 2410520005, 865716811, 4217017985, 3405855693, 489680629, 4018805509, 1851896495, 3292625358, 864499941, 3240462025, 2075476643, 938753688, 3665130887, 4050325243, 2454104972, 1298917629, 1343787954, 4100160453, 1768484371, 1266082612, 238720905, 3180785770, 867009796, 2035104678, 3520470624, 559830721, 1459820613, 1707305731, 2269616662, 1576379671, 3903748424, 1436765334, 3048417647, 2253458581, 3416118525, 1271698793, 3601159380, 3271921040, 2369386936, 1192728003, 1122107959, 706191870, 3978806926, 2539808936, 2998649492, 2864374813, 668066219, 2640264057, 1281805203, 598078394, 1301198855, 2947966501, 2555954897, 1999895199, 3567728711, 2965019228, 2511728126, 2956114261, 2995201734, 4123471616, 457926115, 2385329272, 4012223776, 3469911190, 3267267247, 432918904, 2419068123, 3755513135, 2791185744, 758833690, 3119576271, 112374229, 3625202266, 315354366, 1568978273, 1708623705, 2064937453, 1124067903, 513216095, 3600324289, 1796860007, 1650966402, 2904683505, 1536173911, 1194264833, 513210391, 3723175142, 735565798, 1834230448, 2261021807, 3908447305, 1057830830, 2776652319, 856596767, 2408743106, 3248755512, 3799111617, 1459677314, 3511723346, 499123179, 2708042922, 3492700205, 305184657, 1157916233, 3495088020, 2259888881, 1084374759, 500610066, 564964925, 4131273965, 4039883025, 3168377277, 254683919, 72093362, 1633531730, 1268664506, 1996711604, 3890322048, 3880828363, 3683271754, 2649717281, 658488513, 3017375859, 3323992513, 1910609388, 2895184148, 2111754597, 4005561580, 3122346347, 2993430208, 1199752820, 3108668091, 4218258049, 2822905539, 691305232, 2961667717, 1592996194, 2452161541, 50809045, 3557234166, 4011426161, 4041745783, 3204617417, 647976586, 1613272265, 891115055, 879063893, 3810802553, 3324904075, 988210689, 3334787768, 3235291491, 1406547399, 1509369724, 2678898670, 996757247, 621865039, 1415546535, 1635533836, 785967648, 3519780499, 2306303512, 2608109709, 359246803, 794297329, 1984469432, 860434555, 4188210328, 3560452183, 3324289086, 1341545766, 3210361014, 1550450120, 1999237534, 3419330139, 2052886381, 1713799546, 3838907316, 1300491982, 2376293684, 4058197568, 3717833550, 917200668, 237670602, 3700755001, 1177316153, 1660105335, 260378933, 3544708874, 2760016197, 174001204, 3662445679, 236165327, 2352314383, 3876396412, 2842836038, 680492466, 2660856178, 1251120958, 2853698773, 456537263, 898086106, 2998300997, 377764496, 1543994003, 2189371744, 1255653737, 4002649460, 2687989728, 2526120649, 2771515626, 603147406, 1301287096, 2424823104, 4141553409, 2594874275, 2043054687, 169776785, 4218374604, 3662370269, 2905747555, 1746018134, 357240197, 502016893, 1474347041, 219646155, 483088078, 3514453507, 3217126533, 2412744587, 1413706460, 3659693851, 2763885745, 3512330896, 3369579836, 987519219, 1511534086, 2988205816, 2061616536, 3145760504, 1795367921, 1255779803, 2379607545, 410665900, 1407996847, 3494698253, 2200535289, 615174944, 275789962, 2965302786, 747758065, 399661, 664465050, 967613913, 125247217, 2794499891, 2702820795, 125088830, 2440619784, 291501124, 1302832003, 4097601407, 3942447907, 4190666347, 238558373, 2615163708, 650543751, 583615336, 274528855, 1116046575, 1191854544, 500294666, 178065110, 1136050609, 847527472, 2214527390, 1376266014, 536073983, 1549513725, 49053874, 3854314141, 665952982, 3072097827, 3377813806, 2214813699, 3972044240, 706712408, 1694621635, 1547391041, 508243162, 1582084361, 3109229183, 2354675221, 2691073826, 247654849, 3300964107, 920809617, 355328468, 1689727187, 2482106376, 3398454675, 4214185480, 1920179926, 3602682077, 2103634868, 465683507, 1949801248, 3203673832, 3614462347, 2628322849, 3412024211, 3058963268, 739635165, 168941792, 1084170381, 3020427408, 3027788526, 2767887509, 2350507515, 3794342601, 2701457973, 756909326, 2148742735, 4276521984, 372610377, 3595171701, 1430047080, 778291005, 4051284928, 3770991142, 4020832961, 876293685, 4204224949, 3328204949, 97989228, 1597721355, 1310541270, 1187240092, 362259278, 1473083151, 3673028806, 2288833254, 818795041, 2550563052, 11964728, 329354443, 269689053, 2202758728, 640290438, 2319494670, 2820841677, 1991707137, 4003582526, 1987274151, 685337695, 3389490388, 47364191, 2019974308, 1796560073, 2242052145, 132168074, 3664740900, 361328363, 312012382, 3787517201, 2134021202, 4221983070, 3092531591, 4015482354, 2383783835, 2935132128, 1073105385, 1051702314, 188642192, 1840755701, 2194015262, 2970833720, 3418173712, 2252291293, 896755811, 651041213, 2225339647, 3799501024, 3424383062, 418261680, 219007048, 686407479, 336359847, 815174575, 2476150653, 395070317, 112893476, 3236677850, 3043491435, 4141851912, 1741291050, 1447570359, 4060099803, 2025408789, 730965869, 421345011, 1940000014, 3939429382, 955964946, 771910038, 423132332, 3928015638, 3828592830, 3062230638, 299535389, 2287150162, 2665328140, 1340823063, 1797607489, 441789856, 921536914, 1038801198, 3684047183, 1436606597, 3683958696, 2132905377, 2812354533, 710326258, 2053698821, 4157794269, 3865258382, 3434923942, 352173601, 3698116441, 61131962, 1831719345, 4924961, 1843981357, 700878228, 3450757256, 2056793283, 999928739, 4282817569, 842381781, 3597643631, 1773109621, 3736994722, 1006105110, 1984548595, 1549955286, 2252538952, 2134791896, 816830151, 2573239801, 1318436425, 1215534200, 584845949, 1503621472, 2135150542, 1205539732, 3946745009, 3379992771, 2693969248, 3372345019, 2830977120, 1615941834, 1665464385, 3189732495, 2091398892, 1420883664, 3478609997, 3624116279, 2008982698, 3436952257, 3091084695, 2110787732, 773082120, 3133624299, 2225398192, 4086665432, 2754332922, 498589840, 1032159204, 3615509977, 483862860, 413051959, 3147549436, 203215668, 864863242, 2260028710, 1792523541, 1886034938, 4117866346, 3907544391, 1792457196, 2413537412, 1123222281, 1881205239, 338064304, 1854384474, 3567492850, 1936538538, 4003096252, 1552683498, 4245128768, 439398918, 4170165755, 4159254873, 2096750598, 2291173747, 402334911, 2054654988, 2484919497, 3081708303, 3279239445, 108764284, 1057932939, 3308339365, 2207596480, 1449496569, 1696511884, 1834486206, 3308019401, 322787272, 294989059, 3308250023, 2710211918, 935435567, 74574252, 3918706572, 995180801, 2743621566, 2564939789, 2233249899, 3800182678, 3356656333, 3735865703, 119633377, 2083925509, 2463491366, 3923690669, 1079463335, 3057356162, 967864883, 3852737202, 1231024601, 1966227476, 1364301520, 3559098941, 2224735562, 2140723583, 2954206392, 2792110922, 1612283936, 4116236064, 3975950903, 1906705634, 3397946250, 3425584528, 933399048, 2654489483, 2465523840, 265969028, 3944317432, 726011247, 4165272642, 3707806595, 1980231873, 3916598482, 2208019315, 1055848462, 1396382428, 3565198447, 2259626619, 1629781689, 641856706, 1567056255, 4157261705, 3272229411, 2887326518, 4112471500, 3407005857, 2165760760, 2245192644, 2387432860, 2948884081, 1894578563, 4051596444, 4264496837, 1037225999, 406391535, 3697484571, 987529602, 828660915, 3322759290, 3336752646, 232274025, 1425642089, 790855420, 559144975, 531066167, 4111730690, 3535290287, 2382110606, 4012402298, 1708817394, 3887552584, 256426575, 3468310594, 1318238511, 410028308, 3076830889, 3142568555, 617939456, 268991245, 2600800869, 3068613261, 4159995171, 1629469694, 3607924061, 1126466101, 2409909797, 2602008720, 1676826993, 101555029, 1543891625, 1425841171, 1381575655, 3157322434, 1502237687, 1765553298, 2196226984, 2144309744, 1920733185, 2417117835, 7914446, 824040601, 3658371011, 3764653611, 3882418008, 3131863018, 3734042302, 3886679853, 2046795709, 2102441413, 774651843, 3153107599, 3441128733, 1816520377, 1550198216, 296013733, 4204605434, 1702162229, 4225881387, 836166567, 2965646145, 166521501, 271613715, 1191068489, 3073239720, 2533295935, 305967434, 2025841195, 578863608, 1347597556, 790549374, 836951743, 1016821465, 2546000514, 3963969693, 3758198764, 3154272861, 3997249588, 3488724105, 2694683883, 1672107026, 846981198, 3208072415, 592509645, 2825113079, 929097667, 4017105126, 721112884, 529877910, 1957406684, 3590512653, 2256381674, 1326953526, 4145690793, 299038714, 312037364, 929796369, 4076045375, 232059136, 48191462, 2609783390, 2793032740, 570795792, 2196568883, 2379554324, 53898640, 2778733606, 1650134377, 1356622380, 1413120072, 1497564725, 3121339218, 2339710583, 729121036, 1226260959, 310416282, 1068015305, 2988960158, 1087871955, 3901334475, 382701389, 3419394711, 1197193940, 1145893534, 4213285962, 2358861326, 3998800674, 2393159007, 3284066750, 3802242851, 1313120318, 1363843377, 1864600319, 63244244, 4008207492, 25997534, 1096534622, 2512363231, 2822756078, 1502763806, 4160151918, 1229692802, 2027837957, 2682155120, 3622762160, 2350798073, 3364105528, 2242135190, 2198683774, 3004743957, 341703900, 2063637675, 1872726597, 369384611, 1228961924, 1174849959, 3429920072, 388013006, 3711844897, 3458411733, 558446990, 881810677, 1612852481, 2341850382, 2615440366, 2756996485, 69608033, 2051792699, 879427566, 860445240, 2799693963, 1529796847, 2693841749, 2241425469, 3509318038, 2310074766, 3970361365, 4137984377, 2640268429, 1179754608, 987219549, 4018070677, 997817346, 639088040, 1490544586, 4291233088, 3379985752, 934787373, 2545981495, 1791682456, 1831741597, 674344163, 3222780829, 807041479, 3982102682, 4194907534, 2382110434, 1305255837, 602454212, 1959169268, 3491589095, 4274490818, 1407854427, 4285073354, 3181358931, 1413064917, 1136150007, 1567762961, 2613870921, 1915481443, 39052775, 1638846611, 1514008892, 3881142793, 1681639953, 851015338, 2913922957, 3768834738, 2690174502, 3822191500, 2710964289, 2884125750, 953870770, 81197866, 877172811, 2824832010, 879150580, 1996758685, 32277063, 3986128633, 3479151959, 4227758436, 1856386632, 1937580142, 2006837739, 1272263848, 58649929, 364183573, 2651849529, 514447392, 2336954024, 700118423, 3608261942, 530454875, 4232722227, 3245016835, 3107778289, 1294145943, 2322823463, 3200734771, 3997000237, 1394603080, 1521731730, 2099402018, 4076865358, 2952642380, 1998818851, 1113503600, 1304568624, 156004729, 2524292645, 2196657034, 838089549, 852921142, 318774773, 535471800, 3303288655, 11720307, 3920050060, 1828240211, 524002979, 3048477395, 3534464096, 3963965163, 965647042, 1254821357, 1076701084, 2092634935, 2227885879, 2211769441, 4149106576, 108232835, 1044586194, 907173178, 33459410, 1802126318, 2254795011, 2504657317, 2646373524, 1874357148, 3605965029, 1140229111, 683774180, 1809530666, 1065795157, 1426067459, 579103711, 2163604958, 508216473, 1358516833, 1857560558, 2375569242, 2924422020, 2493986279, 729547351, 54833281, 3560718296, 2168295149, 2812939376, 3488876993, 4293921905, 106256919, 3235972461, 571493829, 2879800589, 3939771200, 3173435794, 1528411227, 2644147095, 3099154467, 3780711788, 3974962776, 3038048098, 3815481320, 856676641, 2816739527, 2163011160, 2429846008, 2574499461, 119664881, 199459917, 3413283247, 768994425, 2761139109, 287075146, 2513460954, 3946445315, 3896813683, 341660798, 3771058010, 1948705192, 1023508457, 2862084803, 1760749154, 1666275298, 1181277511, 2612599583, 3323548077, 1187252244, 775332124, 3631948959, 1634443470, 2542063810, 4141442087, 3558732104, 2216948373, 2165466142, 409718746, 4038251685, 2652525312, 3147566726, 939782543, 634685444, 4171370098, 1242056880, 1509271389, 447023005, 63439402, 753908776, 4007669178, 3612271563, 2941872224, 2339268139, 3167669951, 3980741106, 3989254815, 1392085272, 2825617612, 956934399, 693542348, 388806851, 2961997752, 3537162743, 165236021, 3568156596, 2285015214, 1348352477, 265706007, 2902421909, 3911380709, 456741743, 2843416287, 381948901, 1723053624, 3637546635, 488437141, 2056924346, 3245456457, 3348178830, 907978865, 3949328523, 3105952503, 2583910709, 1005480091, 2592364506, 4212210190, 1616794263, 3063505007, 592323106, 1258310856, 3641811727, 3350224634, 309905898, 4040991440, 980414012, 177467055, 217549578, 2392128580, 296868908, 1084522467, 2436484542, 1317628251, 898381082, 1111060884, 3948408286, 2371873032, 2226259852, 4058234570, 2076955067, 2121848190, 3826134000, 1986232314, 3499478289, 1151387495, 787568209, 1612098354, 726090716, 3069387528, 3976962630, 11690122, 1514834375, 2808050579, 1071588017, 2715771085, 437010571, 2212330428, 1453821701, 3145667973, 1767906839, 3146700047, 4258425268, 3254514728, 3407434515, 4223362441, 2099546808, 830143900, 697083215, 2751907755, 1322473957, 900523897, 2264299413, 1819302867, 806605230, 2799217353, 4141245107, 2305511413, 2796286940, 1505198926, 4225291875, 3419813095, 371941609, 894282352, 3479699537, 2884117847, 248087943, 1920569071, 2946559495, 712099571, 322392405, 3179639943, 1574300690, 2867358013, 2572247714, 2563009176, 2358102551, 3259794641, 3054031241, 565630085, 599078879, 862629306, 1222169625, 2841254325, 2978934915, 1803471284, 622464338, 1354864342, 1901488888, 3205841023, 2319170073, 2904669324, 726542457, 1875424943, 4281642921, 2733515426, 3395862316, 3074062952, 4007451622, 3514683310, 1293909285, 1564336286, 2757910036, 3740249853, 2635743866, 1699257190, 855262188, 2797562313, 2308409571, 2253291408, 3845709526, 3154706518, 1770564626, 2996626195, 1879190681, 2386507312, 1705385750, 1368311878, 3107016242, 3053769309, 1152662782, 3526989793, 1902149904, 1902713811, 1304553510, 2290942581, 994180644, 56936189, 599820797, 628353940, 2338146967, 2227276356, 3246471204, 2978741305, 321966222, 734612620, 904416002, 1929536581, 1325321823, 2240235157, 3921782780, 2377955413, 1963840910, 1390622328, 2216413136, 1687027811, 569207696, 652619399, 4260710017, 2551934365, 128469616, 3999651830, 1649824406, 2553389567, 3992265912, 867004062, 3467311621, 3883161582, 3171530997, 4135113186, 2525098373, 4127647431, 1239629070, 1752753702, 2554081705, 478672844, 1252671738, 401028269, 981568864, 1532744660, 2664413649, 3073701514, 328844958, 2280704902, 2820551746, 554581755, 2039689489, 3587864476, 3575114490, 886087913, 231160170, 1237051234, 1485907068, 3678959111, 772097566, 1428405353, 4048938898, 3109482280, 1435032640, 1835231833, 232340095, 1426343085, 3667550549, 3131273021, 595482068, 2141954646, 1432221631, 1746392369, 3843312686, 34950246, 2816690285, 1045968443, 38087956, 1588670084, 234385795, 1180629994, 373759660, 3873059192, 3277260485, 1750965294, 2851237408, 2070340801, 1298152607, 1791737110, 3240276593, 2371282968, 295305820, 3105367956, 1030783254, 2361722325, 1010613854, 1695440553, 2311171792, 2219950094, 2774978735, 2694247550, 110928242, 2747578028, 255588253, 890925956, 251245116, 2392813905, 2414578306, 900686275, 648109093, 3359108729, 9572800, 3154921879, 2936477949, 2806878192, 1570137434, 1047231293, 2966514714, 1969235114, 3821617637, 535808314, 97656562, 4198277832, 1089921216, 3395530343, 1137276020, 1830819579, 758187601, 773887976, 3831934509, 1923796236, 1341680867, 913019441, 3965990038, 3759247519, 3440863001, 529202042, 3075812116, 1166356691, 4278485955, 1794714579, 1193119096, 3961305347, 2229650504, 2297510904, 270375426, 2793019230, 304714534, 1585992009, 445066303, 884042704, 91232658, 1662385806, 4264570167, 3095721922, 978954050, 3444729637, 3666872358, 1511495455, 4122290371, 2375985997, 2310836319, 1572001398, 1452824364, 815272928, 360989272, 1472815262, 1183233980, 2693925021, 3070992885, 428567726, 1923132646, 870680902, 61334733, 4271169929, 1202450261, 3874156717, 3615524040, 445431985, 3669093913, 1422476991, 311965702, 1417684717, 1234301513, 1340738181, 2539564284, 1741389949, 532861019, 397460158, 1025691229, 348704568, 757498655, 1082072963, 2211584104, 4248378436, 581118102, 280058941, 2711609473, 1283305525, 1157715406, 4231811513, 2418383425, 1647805755, 3089074013, 4043454068, 2851114191, 3362588837, 48533473, 1297952280, 2283341403, 3894166150, 2375381028, 3154331156, 3834699351, 2961474424, 3395077458, 2479986544, 4021481315, 1360350208, 4027622151, 1889459682, 822951371, 2773824837, 2622968707, 1216338372, 1436799036, 228980341, 260550308, 3290695384, 1179830564, 713457843, 1961397091, 3022066718, 60400459, 710482200, 1326388333, 866098456, 988957043, 594546317, 112224322, 1686309163, 2673427515, 1480561387, 3719778253, 189373921, 740479302, 753019699, 2546788894, 1928428757, 3753951145, 1111306054, 1674018696, 1374154164, 66028805, 1169871060, 2942556110, 3383298011, 3948130716, 520357725, 3601036029, 2809274873, 1404107262, 2239311886, 2205203007, 1747688431, 1305067003, 2495767700, 3435341083, 744065202, 2893661505, 3631471766, 1348058193, 3290931841, 1783052691, 3545333754, 2885010405, 3015101869, 1816466873, 445215974, 55469969, 708427338, 2670076660, 2749713334, 600727729, 1015194815, 7563398, 3314338860, 626668465, 463724106, 843782950, 1440417991, 2606259873, 1072028034, 2814019719, 1373997202, 2666900010, 4176313376, 1576887401, 1887901460, 618965715, 3928901268, 2756253242, 908674445, 2783555991, 3145253475, 671884197, 2798251670, 610439611, 2479534986, 3193743292, 3016810470, 4116360208, 330168713, 1143619883, 2702848180, 3323979924, 251520862, 3080153930, 2721102100, 3645026600, 574398990, 2681106313, 2664633763, 3589752630, 1589507214, 4031662545, 1422801893, 677504516, 4032699133, 2580409667, 689884803, 4207215400, 2242741325, 1700880086, 18943211, 1186581791, 900206253, 2336736788, 79204608, 539780241, 636226674, 375779182, 4069215835, 1908716833, 379009447, 3605914215, 1522568903, 4040671234, 2120018121, 2114864129, 1357210322, 2711209295, 2241517755, 2299541072, 1003731941, 1285293545, 2895160814, 3448925696, 3014223150, 1986102505, 918021216, 1895559974, 2968756830, 1782617764, 3842402057, 506957063, 2794128870, 2723929084, 1790694617, 3819994108, 1796867407, 2348433259, 1855143178, 3340341657, 639892717, 2673209190, 1411690552, 79209238, 3485688689, 411330608, 1097436549, 3022819216, 3328590415, 2498382669, 2688145691, 2333608262, 2206781451, 1615021580, 3535503209, 188493173, 851224538, 2629538998, 3538694915, 3195915323, 2470454372, 2836404795, 3037684755, 2029634947, 2480471703, 4256103912, 1677074447, 3285177667, 2202069462, 3664482806, 133405527, 1619292952, 1179718513, 2810618561, 4147162567, 1990145900, 1418108687, 2801415083, 2141121066, 3043945114, 3424083024, 1845146157, 4014278960, 2690703066, 505360624, 1732127460, 562124320, 3526601753, 955179947, 3591457224, 679719161, 297241111, 4108320331, 864134418, 1333562459, 70858138, 2853172817, 1219721500, 1025014572, 3300750566, 2211754460, 991410483, 938799966, 2410403222, 442916956, 3350691005, 808760, 4130790737, 2746612085, 3276621096, 2647227164, 681856395, 1257288473, 1413712379, 1522258369, 3118343404, 2489706870, 1471908966, 2844043282, 1124423147, 3066981623, 594250653, 67819044, 526822929, 777003105, 50825748, 75903841, 1594424835, 793251734, 2458067235, 491807081, 3381117014, 1465584653, 2882491124, 3410605180, 827689385, 2357158234, 3863254832, 1910156500, 478425738, 434763393, 3130649408, 1557159391, 3192315391, 3648822439, 3820808146, 1252113848, 1395689995, 4291373887, 1333204702, 1522583226, 3077867787, 2132184325, 26511430, 2845341536, 2936737873, 1963433591, 584753689, 237431516, 1522453220, 86696668, 2754619137, 795919532, 2240162667, 2266874211, 597113619, 387562260, 2495984678, 3176140312, 3613000869, 3002833403, 2881801810, 1354059370, 472516870, 299801435, 1094226210, 3036033414, 3597911882, 1663838219, 4174262658, 3860098876, 177331920, 2980423231, 2241317010, 2236131872, 4009575873, 205213156, 2801357992, 1761279322, 291587360, 2857705814, 3265468724, 1333694034, 3153113696, 1981765837, 4180801648, 3177874603, 3419835662, 1422518551, 234578164, 3035560631, 2977642177, 2826017116, 693022312, 4002892189, 1984270335, 3966818281, 1449559836, 1580743741, 1221247885, 49265144, 237645723, 3688431518, 2644307901, 4247118948, 3711144286, 747817992, 608833440, 1520829247, 3824111021, 678228162, 810382036, 3825158806, 3989772169, 1237886049, 3067089131, 932255296, 3253516486, 3066949529, 2358323679, 1883424307, 3579121260, 326865116, 1470953433, 2483136260, 4202451688, 3199596490, 2860013262, 749139668, 3240279399, 3174098421, 1172311557, 2001947608, 3298861893, 3498198144, 2132465324, 1381243268, 72984231, 2119259388, 853533695, 1552099388, 1, ], &[ 1048607726, 142412324, 3250800312, 1077166691, 3553793686, 4228441628, 3203079399, 1202791260, 799001727, 1030363239, 1081996306, 2584161993, 3105539669, 2513998685, 4130331711, 3550728490, 1554513655, 4178882888, 781786346, 2080285035, 2740757392, 539616476, 1486958112, 3986698615, 1921400669, 1147589945, 2901977179, 3882011895, 3184378754, 2895226410, 690455662, 1190546349, 2220742959, 2051575810, 540146951, 539062650, 2310850033, 1556710312, 2279375644, 3357053280, 1676861190, 131504401, 2967730434, 82164296, 3149325066, 3482489407, 817143551, 2015288431, 3228437308, 905767502, 3933983825, 2027435163, 1570365157, 3561664566, 3300012446, 3405843634, 2537652810, 1460717190, 1544462148, 529475468, 484660801, 2529788802, 4294022942, 2334555233, 872784994, 3455279604, 1035665898, 2101483995, 2171449070, 246721522, 2400142253, 4238880814, 819242783, 2258413710, 705995468, 271390846, 402766610, 3816209662, 2234701477, 2452466394, 4213942774, 3278770703, 3998052049, 439764839, 309852143, 3929931316, 1550731629, 2868770243, 2431523761, 488401131, 1370587819, 2557822445, 716319861, 2599351696, 2796412436, 3147432724, 2520879833, 144393128, 698522794, 2546333916, 627318794, 4246242694, 1220884539, 3346273775, 1071300069, 1601718155, 3760578403, 1426969773, 1627940230, 3747385244, 962484480, 1164046906, 2606826923, 1240876116, 1623862569, 2100011929, 1743793088, 995602808, 2769415714, 1252942287, 714554977, 2031164465, 2276588141, 3728901018, 122946257, 1858841224, 770012953, 1293680777, 1650616396, 788795923, 2897629253, 398117719, 1274119920, 2903266721, 1229746351, 1962723219, 3497182756, 2689318549, 1514884124, 428587693, 2594122257, 2255868181, 1213534981, 473438460, 3259926899, 784898828, 1740586706, 2493427182, 604737398, 2545731397, 661514446, 152703462, 4226882176, 2763904320, 3169889376, 3526208587, 3107915060, 3226820443, 4186456471, 3018794099, 523425582, 447127557, 3315536887, 2638060561, 4253140999, 2778958816, 136563180, 889096332, 2156297749, 2633584027, 1709332969, 3628824594, 2213804574, 1109051684, 3946712344, 1562010546, 732978546, 1769212829, 541807011, 2330452140, 1259982384, 4244981534, 1446677613, 1494947962, 1886609176, 1890798392, 1278248805, 2089372606, 1464145854, 243399923, 4211737502, 1818727317, 2988620475, 967898340, 1580663464, 2153157677, 1925889642, 3632162291, 141271097, 386524308, 2500718963, 482731158, 2062686924, 219086577, 3285135277, 629410216, 897503263, 3908515354, 1620444287, 2430031229, 934361166, 1796358719, 4124248671, 638890537, 1432980354, 3148696701, 67367302, 2623937754, 2612868021, 80761026, 1141232637, 3269660781, 1889586531, 3256841450, 2670581455, 3744999014, 2431354450, 2059640453, 1149532609, 3217977165, 4063910813, 2038505080, 477944338, 3867820883, 2041535667, 149604452, 2179375611, 153526327, 131491024, 280454069, 2548076235, 406520943, 2273013398, 1610586692, 136533182, 2579763983, 3505264999, 649562207, 2152208510, 4109589512, 913916439, 2770616731, 1104198273, 1202831344, 1255751355, 3447468228, 665264080, 477725270, 2692532968, 1870693866, 3851762774, 997405540, 2042036508, 3726396028, 1379580311, 2439697975, 345704789, 242944825, 1137146938, 988466318, 3882464952, 3107721748, 17414629, 1662467057, 1280533760, 812371865, 1883212013, 2434696745, 1223107282, 3596170173, 565858852, 536542408, 2433577281, 3132259324, 927119620, 1882095984, 2261424849, 2564496532, 806455696, 2635858001, 1840281829, 1429686119, 3246338601, 836772651, 1360857075, 2774016575, 4122295000, 1246981145, 3699426177, 4097010166, 2362501646, 3279563, 2709151847, 671939434, 2540411298, 1237267379, 1533499075, 1029636334, 3329917063, 3015797724, 241909419, 2435929696, 2196157828, 376150999, 2758243214, 609760865, 3449122098, 1743972313, 4091850250, 671738770, 2364789363, 1916675262, 304618359, 4119966810, 2850975933, 165283783, 686409432, 719782946, 3511536373, 3395113947, 3984649666, 1785678028, 265739219, 887986970, 2855120100, 3564162829, 268532078, 4139618232, 2400629035, 3035579533, 1697435623, 255084169, 1464704590, 1969412123, 1474218865, 1068169710, 1486590349, 3981484600, 574030985, 2187701187, 1896404752, 4221469159, 3433453595, 1136439656, 328113653, 2084810857, 509246959, 3940661151, 3802993380, 2825285631, 3972592023, 193253710, 1105971629, 1023278470, 2506284183, 705358340, 3886603586, 1357318457, 1425410849, 2872776361, 255660592, 1313207097, 3156112223, 2830882366, 694005909, 2906618499, 2520527692, 1449611271, 1849318233, 725033292, 2446520944, 2915986673, 2763045905, 2877683241, 1026458781, 615272660, 187420409, 943610851, 1812634652, 2273048325, 98138901, 2725026118, 2967557799, 3270136886, 2059346281, 322818454, 2229832363, 1421907280, 1790203450, 3309886466, 2218371394, 1723058643, 141062552, 2848609617, 3178614253, 3697309878, 2621643540, 3453793862, 4098981072, 1509842023, 669644032, 1780348545, 1347261194, 1942473489, 3177185986, 2974907342, 2498656520, 863579786, 534304671, 658990181, 3867449603, 2592395109, 2899904485, 24363917, 2582826966, 3202040405, 4276755802, 333639144, 1055214722, 2593914648, 4006021860, 1862629360, 1984390962, 941140443, 1975514676, 1444701897, 2077986133, 1321299657, 240670064, 1907831864, 3548899199, 3417333093, 93616467, 4042521537, 669172764, 1509883566, 1410028566, 2465323811, 1548825994, 3883910619, 3234661467, 3105117973, 4114740676, 3200175759, 2178246178, 633150960, 3955508938, 3460166584, 2110457566, 3753290715, 2770574241, 2049063426, 573027729, 4156077678, 1407126170, 216038396, 2102970600, 3194950401, 4017319979, 1291946975, 2300933104, 2099048635, 894312712, 1934513279, 2557556618, 3248883960, 260082879, 3059635004, 3069327264, 1714535246, 1831216556, 414921881, 3289293516, 944181322, 3925790739, 3359968475, 1846968300, 2609486679, 1850019504, 1944960161, 3750774956, 2296180799, 2486016936, 2570802263, 3691641463, 3848645994, 2487460912, 3997753905, 3027763387, 3960275222, 840918160, 743404502, 1575447943, 1886521982, 882571777, 3530937658, 2589305705, 2678878307, 1307010984, 1256181931, 55466926, 2188902026, 2395613978, 2514869503, 2982962505, 2054026528, 2157945040, 39790067, 2647728191, 570680119, 3483166779, 3446354771, 1333593377, 2251539900, 3433452892, 2268781405, 1187783236, 3432951380, 1296750451, 1842142891, 911250979, 2905313019, 247454604, 4158769786, 1283681216, 1339246742, 2404495800, 1902364864, 3144630274, 2371884247, 1665809985, 3444104202, 385659994, 657155685, 2255995967, 1905981216, 2736009248, 1428368476, 2624996710, 1145643837, 2786210682, 3485069535, 2999714050, 1002675335, 4174976414, 1248658090, 880109681, 3070247226, 66466048, 3111549103, 292579238, 339279340, 2344203213, 2176303622, 3906973220, 2905978660, 2190987192, 2594302473, 3664921655, 2097010421, 3960926873, 2179851435, 36046787, 3494331530, 1138328290, 100401628, 2319700689, 2151407026, 3811406180, 3438415433, 2827821485, 3243639281, 3556903243, 636198560, 4273411963, 3842446478, 4050639786, 2854770013, 1403448237, 1556407557, 3221360095, 1567961792, 37915355, 3857273364, 759462610, 1596782015, 3997591545, 2208738987, 3029977760, 248859738, 1283529230, 1415005957, 1972668381, 1136025839, 165926394, 427559678, 2587400498, 2049663228, 567766412, 3161812322, 2435932699, 2668793445, 1531281830, 3565406590, 3664348935, 2265420009, 3929560982, 142270226, 3509595350, 2352645495, 2905368949, 1049755192, 888023262, 2438967112, 4254921568, 3319930823, 3984992816, 2765963407, 2806247137, 178106618, 3411420675, 1286002529, 2982691785, 2873859269, 3369594395, 4167720102, 4143525238, 3717603632, 3191223634, 28203420, 775269803, 412179788, 1962047866, 1813776568, 733160490, 1545749793, 4068549595, 2389240832, 378753614, 4104045591, 3657852010, 874025036, 4056508979, 2951515898, 1124709994, 3783222963, 1012308188, 2229271510, 2219096628, 2458020702, 3621530574, 1080427507, 1517056900, 301884898, 1290494301, 4123182810, 4189508696, 3988834325, 3689801913, 513395950, 1744594764, 3290355805, 2403507478, 482652462, 2821811425, 993426434, 1014456377, 904787565, 440111472, 3902930297, 4142551056, 1591497191, 286221577, 2152371786, 996720255, 3895520923, 3985861127, 3251025271, 2700743537, 3239439576, 2969935613, 1691240642, 1493465575, 1053359537, 2355791459, 3910993255, 2403970629, 1187413316, 4240222384, 1371714172, 3965808637, 746046851, 1242409855, 1595856627, 3182235189, 2115649167, 3417666039, 2827475911, 3419665752, 2224557620, 1207076402, 2188810252, 2013649922, 1578650227, 3675331676, 1746814009, 994279655, 979461807, 2150039433, 1488417808, 410096171, 3115127198, 4205833441, 3149429906, 2331868780, 3732482276, 1317599654, 708995455, 3471263525, 2203689020, 3813526622, 57733901, 3221347386, 1875131483, 1871230123, 3503204429, 279302990, 1008515956, 2958288963, 3997438534, 2218418435, 3325971377, 1036477492, 1667373986, 2935447535, 3272214732, 1916937801, 3411973075, 190188148, 3259518452, 2744957335, 987959381, 2926241446, 4028119966, 2659487306, 2364177521, 1707356830, 924143357, 3495026759, 3224492066, 820998238, 521377600, 409920327, 3022575390, 3408451909, 2446120177, 253505828, 3013593681, 751866448, 459847293, 4151089466, 2734658906, 3628614093, 1204026156, 3836104854, 133921563, 1906374634, 13937476, 493403406, 900335320, 26546070, 1285100637, 854607887, 4109641695, 1398374294, 227160874, 799394835, 1021062743, 1106469748, 17498306, 1228416509, 941032865, 682571704, 2464984044, 2082388629, 1494996330, 3394857640, 244442806, 1377332949, 1391098255, 49637159, 571188827, 3707911702, 1723324451, 1643372792, 1140473043, 866463091, 653154991, 1297445690, 573376538, 3981781235, 3696912668, 565267791, 4185635602, 3480070858, 4050228235, 893269043, 2925165903, 3337269632, 1840579081, 2457286075, 744856935, 287770719, 2668837353, 991298351, 1967208622, 2418132114, 908335335, 890083308, 23221927, 2853213933, 807614974, 218855713, 1501222052, 2494434864, 3153286947, 2002393426, 1937810340, 2196991305, 1201314450, 3995545220, 2109262516, 2587798229, 1522992967, 3290897323, 2844799547, 2362679901, 2499652853, 236409787, 1821770534, 1385634971, 780550390, 1992356749, 361422561, 1911938329, 985103802, 2446932867, 1781316431, 2862433888, 1710440644, 1630007296, 3895088584, 2584069445, 4109526636, 1215052693, 1879156818, 2454307146, 2104746099, 4224392284, 286611992, 1778618995, 2141695259, 2711187183, 4257553041, 647228281, 1295156827, 1552913077, 213807527, 2252596158, 2051124395, 1241226424, 1140277576, 131906315, 1277450464, 3948826599, 1266865951, 2478887003, 2605897720, 1991636367, 2192624302, 1280448240, 194619382, 2005700446, 2926770241, 753480478, 603647115, 3213709892, 882887847, 1895753586, 1815651065, 2481200593, 2083558189, 3700353603, 3991937366, 619042791, 2825773803, 1041174867, 3851789531, 3214460859, 1140471650, 3196668456, 322856926, 1460664681, 2638812276, 3663403397, 398669302, 1037797389, 552494379, 2219226623, 1705521916, 27946460, 280394090, 3773459630, 1253024509, 2879489206, 1767188167, 916184538, 1199740381, 4263858782, 3986775882, 3044707269, 611283348, 1526180610, 195582791, 1730668165, 3073839585, 907890001, 2481144221, 3782885147, 217960406, 3054908023, 1837860495, 3848079760, 2917706776, 3944231881, 3086946659, 1791437342, 3605338932, 1949911356, 3711518847, 3125234193, 1241545832, 333629901, 1042934573, 2394347103, 2851879566, 1778541946, 2808769668, 3248943939, 2073787511, 247734098, 3837843645, 2171779606, 2141888351, 2575430218, 2166342642, 3714912603, 3024488117, 2290054554, 3394256909, 3083054909, 584692472, 4063088234, 2746953830, 3850784297, 3335013306, 3364320672, 1128684862, 4001742473, 1536088780, 4198240687, 1581849589, 2423268362, 3246412217, 1454863643, 1108610164, 3878934470, 38892282, 245169604, 1274726846, 3803493626, 1744937663, 103002740, 502054946, 1892247461, 2623709034, 3995377274, 3044743413, 3996081168, 772081511, 2286981943, 3068018767, 3983416027, 3641407152, 2757340837, 1836414225, 3244876917, 3573033415, 4138495962, 3311045110, 295783324, 173431332, 3611538103, 2361066151, 3015722298, 1343609822, 1282836993, 588785015, 1551804562, 120847676, 2210229385, 575857299, 4149396254, 885356301, 597576777, 3931353525, 1785590947, 1472332500, 2741133655, 3562427458, 2362380834, 2479477684, 4236191078, 1767966538, 4178971734, 2932483246, 2958030392, 4101226876, 3921481958, 633626263, 1769237825, 3533263201, 2143256898, 2215605389, 2895081471, 1728913742, 1805410928, 2970038245, 2463197162, 4200176957, 1564826577, 3267987851, 614250648, 3900292330, 1769065434, 4232208574, 3592015556, 144180881, 2509343022, 2439166937, 852496649, 826798105, 3564967947, 2918197096, 4059790058, 2255368011, 3523829294, 3319959687, 4156223144, 1133583449, 3454229874, 1557011911, 3458427548, 4230055622, 4190826337, 17883382, 124954346, 40987641, 3563510070, 1941316727, 1359068976, 2550479444, 627239665, 3063146127, 3351478702, 2504515151, 1068440347, 916246986, 720364258, 3947921413, 1150872866, 1875253368, 3832839852, 2778439355, 3289279511, 2889088515, 1856943409, 2903940647, 184310325, 3217001628, 319129082, 749624857, 1832240983, 2640398028, 860496046, 3522090122, 323134571, 3153179517, 3065488900, 1184373041, 3532771604, 2401547734, 3152768461, 1782533689, 234187710, 424333209, 722591632, 3763004948, 4153495192, 1728824235, 348843722, 308766489, 2093510996, 850299604, 4217675914, 2195899127, 256544001, 3226528914, 2962551672, 1328234458, 2986580052, 3233545816, 180971160, 419014901, 3912253012, 637008115, 1205945402, 1503804357, 4012660565, 4156469030, 2582083821, 199488563, 458440108, 2849662824, 2704948215, 795518706, 1000777821, 2004820266, 2822441063, 3764807805, 2681140792, 1491528833, 400635370, 3401974306, 1862815705, 2561957438, 2983350168, 3904191142, 146855111, 3927193381, 2731433733, 673747148, 3253050213, 4239533938, 4046300384, 63718730, 394253960, 28039621, 1200917690, 3116360994, 2676755349, 4241904784, 3959007578, 4031049777, 3202945405, 4122030991, 137424116, 1142687397, 338198709, 1594649019, 2508774575, 3211820212, 3002454781, 1566031505, 1916162942, 681747305, 200923992, 3809405102, 3721492621, 1786753592, 3227675559, 1213303313, 2346133839, 4242483508, 1977660151, 3145905223, 3492890380, 2021133693, 181054296, 4282292922, 1199764816, 2333541081, 4259709876, 769347186, 2399481048, 2778284357, 3762399931, 2234414972, 1839810677, 102290666, 4240663622, 2902993370, 2184365004, 3243124072, 3955281908, 2765439260, 2135672711, 2989999631, 3787014518, 614587906, 933777560, 3348884554, 3804856256, 2711182813, 1170529113, 368238835, 1773069460, 4229876441, 2594105862, 1075367781, 2216618737, 3125174865, 318524823, 1020662435, 2523775978, 3750101384, 3948363519, 3304724022, 664366799, 84875872, 4137905023, 4216040944, 771707291, 3135286886, 1079340376, 141842777, 1111481799, 1532734553, 1980818988, 3722270308, 1566396676, 1019009, 717064453, 3372969819, 506661632, 2063798179, 2423583087, 2656391525, 1630100941, 2479950284, 3657991172, 2371699826, 4199252741, 2521889397, 3324104671, 443020662, 2271816278, 3749381900, 554658420, 2887078027, 1375538749, 2337582266, 756385786, 1104904157, 628107957, 3929401682, 2450090419, 157294829, 1993439139, 220713980, 3472905742, 3113447906, 467991303, 3249685152, 1191502788, 1643194722, 66946652, 3325985891, 3655086037, 589852547, 4114108739, 3474857286, 2212167498, 518108528, 1061202903, 1834419839, 3515790230, 432023349, 1792804209, 1376908486, 2799134354, 407169155, 3760230799, 31952730, 4237093098, 559932983, 338621103, 2777797418, 1176552774, 1043376225, 40393076, 1543484797, 2835954021, 4280169740, 2726285215, 678780856, 2234240248, 4106921813, 3468591277, 2347844488, 1286704498, 693550934, 636005574, 562601422, 3806801557, 518760153, 805523449, 1807233646, 2340277386, 1764245323, 3893899160, 732166191, 1519923334, 2287823447, 1847983638, 2757449629, 1627605149, 3249509794, 1248043307, 16594694, 680804929, 4087351011, 1788938681, 3636487025, 801119410, 3000953659, 191016393, 564779703, 2567794023, 4235935246, 130144285, 1612660013, 400272330, 1080646757, 3775916055, 960046260, 1380362532, 3441542350, 3252871445, 2045998548, 1475566564, 1155903948, 1551712446, 3407113964, 1992638852, 1950218946, 1565489847, 2819274347, 1167904963, 4156357668, 3889678881, 861634597, 1177972497, 3769153896, 1764256941, 2735480696, 3045090663, 506102454, 2207236307, 4179160848, 736180119, 1105109838, 1816897482, 3650337200, 3399862146, 3877657330, 807392854, 1903312622, 876336464, 60413064, 2629999006, 4052780402, 3804059563, 3805986115, 2325037255, 236398700, 2898403681, 193636779, 2977069801, 666013355, 47616353, 749954976, 4048172198, 2782182603, 366812230, 1865894290, 2548867210, 3803685394, 4266343191, 805883814, 3771810872, 2276556842, 2489193099, 1813625903, 2150529688, 1552801160, 2887420624, 1604048554, 2450479040, 3827176094, 1896156795, 2478871586, 118817859, 1361329827, 2990876811, 505801955, 2238407528, 2761195506, 750435627, 2441696264, 4186437002, 672360518, 3949971889, 3634836549, 777538567, 2152384322, 1347995475, 966537071, 2192031274, 454113577, 1831918275, 72945292, 2134532522, 806000481, 3391255587, 2601288989, 2375000414, 1984718442, 2766094083, 2871392044, 2908879884, 3206209067, 2495491120, 695154173, 2275211574, 2648325390, 2042875058, 4184470059, 205717683, 2549735036, 4142739910, 3226096901, 784305247, 2643409298, 3940551169, 799181258, 2278468111, 1262890692, 1810968035, 4230881612, 4010863801, 1310173617, 1877791166, 3392974657, 3310629609, 1294111179, 1691717910, 2243195728, 201100405, 1860817865, 3992517629, 2110903561, 1072241403, 2490794850, 2657190577, 491600738, 2738950799, 721276717, 4115495505, 1249753963, 733586712, 3785610108, 3531709114, 1092285370, 2483693547, 2377719792, 2530971004, 654112433, 1370215652, 3194499974, 971522642, 4288355310, 4153013974, 1073702593, 1588497013, 3931168881, 2297644577, 1971171469, 3526077049, 653418467, 1184518933, 3903410468, 1431385791, 2135588004, 3746548756, 1300360760, 2983521883, 3680677366, 1114764921, 2067504244, 4037354341, 1328353836, 3681470518, 1296904099, 897792099, 3889325469, 1620581231, 1057101059, 2623957214, 1416465790, 2321249288, 600221944, 745706052, 2884744632, 725459359, 2151136086, 1022690555, 2101534544, 4235991561, 2526289534, 4090433148, 3414669915, 994816426, 3364509792, 1685851067, 916262427, 2653730670, 4107563285, 492616131, 4213854692, 2383881706, 4072301786, 2768754227, 268515465, 315313193, 836553593, 2730985350, 2073139965, 2398076251, 558256342, 1788344547, 2984051379, 4109409395, 3614988625, 1956541383, 1880479368, 3202603508, 1425106476, 2480560240, 304989404, 4139136237, 307799893, 2298991754, 114036851, 1259328780, 4262189101, 2653754063, 1502449452, 3375251268, 2192199048, 3791883037, 2668934777, 1425476067, 4049800425, 1668283262, 2667327420, 2933151991, 4019716343, 2330828453, 3498211009, 3769685326, 3264444082, 2991844381, 2321900855, 117851441, 842442946, 2118410931, 3143493727, 2344874932, 3816911655, 4211335525, 3674661885, 1221645719, 4096136746, 3067959751, 3886517668, 474527889, 13436509, 556504311, 2037544501, 768123789, 3109215060, 2111841029, 4066422103, 2509393756, 2613607688, 1934939639, 804143648, 979630044, 3032976830, 1789262393, 3800185863, 1684588922, 2856996817, 3980253276, 3747721886, 2040009573, 3786938617, 4184189589, 2909473305, 4005326975, 169151147, 3555459784, 1680052614, 357068529, 3902867798, 4134705630, 2460264703, 3446281088, 2506686175, 2140253907, 2524031008, 3748672241, 2637079427, 596462645, 1756428494, 4079242605, 2154048804, 583321194, 3323589816, 435553745, 985041064, 2207815591, 1541521937, 3977646346, 1466656860, 1701122017, 370668095, 856054136, 983678454, 1869763666, 2906502004, 3590037337, 3674457348, 4190173453, 840012341, 3173978322, 2071940589, 3907580805, 1066268792, 624296315, 1619840813, 4184498156, 2417585810, 313712078, 2648134631, 3458957331, 25928886, 1616655447, 1597586003, 2422906806, 3753518055, 1382145270, 2264934263, 693781264, 1245009193, 208844628, 1626364957, 1570465417, 2904762226, 2704404565, 2698439442, 838859405, 681405606, 3270592794, 114323964, 463704433, 3008664129, 112133631, 2466737566, 99913252, 3107521111, 2967401892, 3610987977, 2746833516, 278618614, 24782692, 4186221509, 184204380, 1132823616, 2205467018, 1963448884, 1793230230, 3245502016, 2062710723, 3289617322, 2424440484, 2687983608, 3112733899, 3238195835, 2191413483, 2942981831, 2468923457, 109598858, 1921003506, 1867451786, 2069725403, 1789618297, 1332853677, 1255099134, 1845389783, 1380514769, 221106554, 1417110717, 4271433429, 2613671844, 4283741954, 1039802998, 3530487181, 2813442650, 2933398011, 4213197108, 4038929941, 146649145, 1889293476, 2479307454, 2210098336, 3439692794, 1655802607, 4247139691, 1694322066, 1779056134, 34699089, 3358014766, 3795933745, 1652860608, 1013413276, 3660600634, 554286455, 377171445, 3694311441, 1362736640, 2317624482, 2105488535, 3907800383, 2739752543, 659143664, 1266278408, 14379155, 2842357425, 3578153666, 1210028003, 2292709595, 2461065183, 1060627985, 1916482582, 2047777944, 374805563, 2855466869, 2243765299, 88602660, 1309015120, 1794831005, 3217210436, 575982793, 146096222, 4183228001, 50568213, 1080395281, 3719456079, 4174019042, 2836192500, 1028264017, 1563161897, 3153715814, 20965921, 1786764091, 2068658040, 334984384, 672639999, 1795028197, 3479475131, 2410760560, 717812557, 2347632908, 1700901001, 3001721233, 3310592578, 16086271, 3774008122, 3689378213, 1885471476, 2901220836, 1715551356, 1893280548, 3286583788, 553079801, 2351975790, 490104937, 4090146754, 634172285, 256165689, 2147466137, 2413755525, 4149288700, 1840031596, 588585345, 933371499, 151941262, 2291598029, 1558175109, 2205961485, 3279743313, 662618489, 928026255, 2315088032, 2393177614, 1975851571, 251169825, 2844282749, 1577745923, 3717002386, 1306224863, 3095824220, 100258507, 1043298283, 762332010, 3662156511, 324729017, 3173025242, 3018005111, 226292042, 3693510184, 1551950805, 4270336845, 414941324, 59765929, 1409167125, 628242312, 504567837, 2654788266, 1503480310, 3757851583, 3647297321, 618810458, 298766937, 145543352, 972529625, 4006011378, 3902655343, 1704213062, 4277457734, 584553954, 369288135, 2377121631, 1596097246, 3974978658, 216680729, 3946882169, 3632432957, 202232795, 3398084585, 3713222132, 1288467794, 1142439074, 2360536800, 4151455478, 1088521481, 1195327196, 1602839012, 2953796466, 1815602329, 3514635026, 1774774321, 2374040735, 1925157728, 2332391415, 1234977504, 1381581253, 903985422, 971877975, 1392602998, 454395919, 2045134551, 316284213, 2190742535, 2783640915, 3239126304, 3543417906, 149651663, 2439212212, 476510431, 106147908, 1640247147, 3589889334, 1703804993, 4113626973, 1918936481, 1562421946, 1146941118, 3775194923, 418383335, 3871173886, 4179550043, 405447285, 1012425284, 2303549182, 2892019780, 2729667706, 4078173312, 2470025705, 1324397742, 2828838965, 2935720150, 2238693574, 867355806, 2193601218, 3280892195, 2247553430, 3448996084, 1655942402, 3680936068, 67725183, 3204263936, 3043409732, 3955540766, 415375390, 1755128377, 2528734418, 1792464404, 3184424158, 643865569, 1862465812, 2090335917, 2707692972, 1217649324, 3993780143, 3619942265, 3501265789, 2221019617, 56988249, 3012876501, 392522600, 2001797432, 1047913195, 1537292461, 2680755293, 428657196, 3198027984, 4204053927, 2454206119, 2689406141, 4005981783, 2006813447, 324015368, 1364194912, 2619685538, 2444093870, 3849270705, 1627584507, 816114131, 1219945742, 2158042708, 1023080013, 3749899796, 217196112, 2556865648, 1040004967, 3669140364, 2162023748, 2793508972, 685969446, 3839946268, 4095529400, 1044010880, 236277423, 2028710759, 3540673645, 1266224279, 395323073, 3682742496, 1996225489, 426996724, 500059552, 3026743941, 1686345089, 1811167335, 4133545193, 577693922, 1681085597, 2863808567, 1972726650, 791532555, 3060621312, 1042840997, 4186315276, 2615862938, 3318562748, 3816578039, 3857359734, 3632212033, 2247534109, 2184530934, 2472630317, 1558485216, 859102614, 2048162191, 825356872, 359544751, 3403239469, 674674212, 1957563770, 1296318164, 1266552461, 2160687728, 3335753693, 3432986702, 1230729674, 4159438343, 2912873721, 3848793786, 991531769, 3058585677, 52710525, 697741785, 785232610, 3294858478, 3011485669, 3475026752, 2238609462, 577017207, 1478684897, 629526962, 3367047382, 408605384, 3419371293, 3731500720, 2411014418, 1074468417, 2147325269, 387968308, 1878764768, 2912609159, 3000669691, 2205894515, 1726031277, 3862581587, 654428449, 1435491333, 1982567117, 883646517, 1213287163, 422593417, 3148866580, 440528113, 2604566415, 960194632, 1054708709, 2281968814, 2178014147, 119455690, 2805298477, 2276632809, 3157907488, 3604132410, 1300852807, 964851233, 483630605, 634097080, 3815600057, 359410053, 1801332993, 3396608815, 2035465575, 3693605339, 2260082808, 3768318407, 456831610, 1784896347, 1993961602, 3367680195, 2925998416, 1692304064, 4017997519, 988139663, 1172195776, 677056045, 2996742609, 1817105632, 2206587093, 1339440427, 3115619024, 2137452547, 2583411781, 531984158, 2972052723, 1119548166, 2552741930, 1740178731, 3414605445, 2304800008, 843429176, 1687215212, 2348034820, 3585915064, 2116619858, 2939781180, 12638302, 2015346190, 3310257159, 3812182659, 1929038994, 392010725, 2816962432, 365845012, 1966332800, 2331495590, 3282664549, 1565343709, 720795201, 274820494, 2573327352, 834206249, 2120328806, 2122466443, 3552259992, 319200107, 1887946580, 3275565177, 2214525605, 738814547, 928993058, 3139215937, 89284281, 3595637762, 1784520615, 1659233101, 1538260873, 2962979310, 3313688954, 2626898666, 3733084731, 770537802, 533232722, 2624520459, 2254466625, 2000199242, 2850289393, 3581680978, 1306543443, 2731694315, 4214864861, 987449903, 1337556927, 971618652, 562554112, 933714896, 3365336106, 3022295433, 2393633675, 426316712, 1945028387, 1347027978, 2736909937, 2134829411, 73979674, 55019955, 2012450470, 2348886159, 3424147355, 2447440437, 3161600497, 3157707664, 4219238506, 2297279601, 2411947365, 1714194929, 2466112961, 1223895820, 1852439360, 2900645877, 2372468244, 2993491906, 4140450304, 3289653733, 78074619, 1860352651, 2471757345, 1742864175, 2860681391, 283215926, 2730553569, 3695205783, 2508794543, 2898776688, 2440433292, 369374088, 2520129209, 1297447417, 4085044427, 454499846, 3776430362, 4048231919, 2078269113, 447150081, 502285383, 1290765738, 666955917, 1496143525, 3095658311, 1004015786, 3902083656, 608537333, 2570742756, 894957982, 2920024516, 2030269977, 4168722532, 2901933123, 2799872620, 2444444753, 3445465651, 826603018, 446153324, 3203157537, 2506406304, 223810067, 759136959, 2868603029, 4122642584, 715786506, 339816921, 3558811374, 246428935, 655313389, 1964431859, 3727543494, 4131082215, 3514937976, 389882274, 2108836808, 686658518, 247041449, 1580425893, 3619334465, 38297597, 2623967825, 256196002, 950708889, 1604756990, 2284090906, 2764905572, 3243572005, 91323796, 2372081166, 971118391, 3223082462, 3657959176, 3916088510, 876198567, 532411151, 1245822880, 2967282993, 3683945008, 2604865059, 1312816639, 1526063192, 3709858508, 541160516, 887438549, 1605566680, 316061163, 2717518136, 3202624914, 4286142265, 37932352, 2280000189, 3574083833, 616660103, 186007304, 3579480040, 4172855165, 3061121219, 2664433865, 582225734, 1498440115, 954466500, 1740424462, 3094153782, 1187633960, 2178324759, 3721660768, 1980280304, 3918075453, 2854136894, 3035212071, 369889928, 3318180449, 3880555344, 1741811985, 3111529874, 4063756931, 3492254213, 1485092366, 3763735860, 2363926030, 2981956449, 2849831138, 2025730596, 3905485701, 470980499, 962666217, 3549434234, 2940438956, 1300471200, 335327941, 130508638, 3084917853, 3243225177, 4225033895, 1685117220, 1103258167, 310727863, 3731698514, 110353031, 2677159441, 262645976, 69502397, 4142500369, 44273624, 2561626371, 4055984328, 2458564605, 1160926149, 2336828638, 3658545338, 2209496238, 2501847046, 4149648788, 1804898244, 3203259142, 995640966, 4111713010, 4256965601, 889096426, 2046359378, 2387978410, 4130716718, 2095157696, 1961147811, 1960183532, 164838879, 3444405849, 626148875, 2952415260, 1533519138, 4277482566, 1223727646, 1200427663, 4017440522, 2188055283, 1634298257, 3459215521, 492491429, 596752184, 3072588207, 3843332436, 773938296, 2593034010, 1097064791, 1915293085, 2209596761, 4254557865, 1433887599, 2099572369, 3884213536, 2359656999, 3115513575, 3851397787, 1765911954, 3275173333, 1722769015, 3454767171, 3918573616, 216313730, 3949302453, 3200254389, 229916177, 1121204461, 1330735176, 1717289746, 3668412925, 1644023445, 2283088904, 3557171827, 3056900036, 1778244577, 3595924212, 872667586, 1197158642, 3234491598, 172146091, 2014705894, 33279590, 571001578, 1948965857, 3009595051, 1556760510, 453148385, 1675972822, 366761520, 798807211, 1232401108, 3040172477, 2170351532, 3569675569, 2417102923, 1019261436, 2683810943, 2344308389, 3194319863, 2577226907, 3703945667, 3111376847, 1317654146, 2148638525, 996159628, 844072733, 307958944, 105943548, 2007781657, 1588114, 2750589103, 1746465119, 4239391159, 129209852, 4127384176, 3908370239, 3051559082, 300427753, 1527209534, 441877589, 3777172921, 3682277937, 2578951337, 952723401, 1638973752, 657222197, 950982327, 765295671, 3922241689, 3339076687, 1140001630, 1375537922, 1377470415, 400397279, 2079788604, 2709952526, 2379097212, 896580422, 3779262114, 1279325572, 4266133362, 879053306, 2465184182, 3704483987, 4247230526, 2678554635, 1492996125, 3718393868, 1621062588, 2593729831, 3561472420, 3167586565, 4199345398, 2367889564, 2725438277, 4029056280, 57956979, 2113392763, 1834941097, 725273836, 3435290245, 1221495376, 3829652832, 3742636942, 357848024, 3791413177, 3966631496, 2287469375, 3008002390, 1748658003, 3237163429, 1159572541, 4048446324, 508643870, 2672687864, 1607401925, 1147147667, 2055873100, 2662684175, 114519117, 2740281092, 1088299689, 3656675431, 3317348295, 2239055466, 2786446378, 2177806798, 4081920224, 4036375509, 1379076356, 475411811, 3480425274, 3096540510, 1246069411, 2552543737, 3691125098, 3708761388, 647070382, 3654474345, 895508246, 3821094606, 685711293, 3433236794, 280551223, 2253092286, 465155427, 51156263, 3598662025, 779787368, 4008704214, 1285583345, 4024712339, 3656160558, 1874433302, 1646839208, 844610019, 1878842109, 3645139659, 946453509, 1461659014, 91586562, 3498886254, 3283439756, 3971699775, 2305270524, 4201973861, 2289308009, 1198674110, 1918349466, 195525652, 2140360410, 1721981151, 2408926798, 1425931703, 1217754763, 1219341160, 781018523, 692209302, 1091974787, 496031969, 3730567525, 2722454404, 2962379865, 3238697411, 380426314, 198771613, 3672237099, 1881647940, 400688324, 3086010163, 3001448434, 85789128, 3786848369, 1282699876, 3111531037, 1466042151, 404041098, 2846201024, 265539915, 3126668874, 3510276810, 594380959, 2471268617, 3517102299, 3207314782, 1103070659, 1412524949, 100266650, 331188293, 1432143322, 3556739414, 1568633613, 2607329227, 2205653840, 1127637801, 2157182903, 1977783564, 2579631731, 1807013737, 362289356, 4245038233, 2412483343, 2562775465, 1025258397, 1322639906, 4078999618, 2646473383, 3694773355, 1504919321, 2785506462, 2052914740, 2141266707, 878037524, 3969401813, 3566092309, 3888635284, 2553979069, 4209191456, 2295889100, 666961337, 4037948352, 4250228512, 1973928677, 826541289, 2635094545, 10, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { // - d_len > 2 // - adjusted_n_len >= 2 * d_len // - bits == 0 in limbs_div_mod_unbalanced // - Schoolbook condition in limbs_div_mod_unbalanced // - bits == 0 and Schoolbook condition in limbs_div_mod_unbalanced test( &[10; 17], &[10; 17], &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 4451260977376821357, 18241701617364042056, 6169989192350218482, 15071965537117101028, 13509168527678537782, 12224278653171635329, 16077066393714953826, 1433938684868066489, 13014970036232570373, 899282336249563956, 3089487642230339536, 3787737519477527148, 16667686214395942740, 8787122953224574943, 7841835218775877827, 9693303502025838409, 16122224776459879427, 144327425397945219, ], &[ 2350654041004706911, 7834348511584604247, 12756796070221345724, 3842923787777653903, 12373799197090248752, 9712029403347085570, 1426676505264168302, 10586232903332693517, 8387833601131974459, 6290888746273553243, 9503969704425173615, ], &[ 89235393247566392, 5198286616477507104, 15671556528191444298, 6642842185819876016, 1703950202232719208, 6620591674460885314, 9897211438557358662, 12382449603707212210, 13586842887558233290, 11884313943008627054, 3205830138969300059, 4257812936318957065, 11084100237971796628, 13937343901544333624, 11743372027422931451, 280132530083052382, 0, ], &[ 12688955427180652274, 7641660693922643933, 8789985477567049482, 5698832637416200787, 14684840547760545685, 2822100467869581421, 3557573565928866957, 4409631974409684922, 16994214656621423610, 4513108841166793667, 9009005527785483287, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 3], &[10; 23], &[ 748159237152854524, 14199895651244313572, 9044210482484213648, 3880401870711113518, 1694971440240542063, 13547801197479934494, 5244069077418598572, 17329479401291658084, 12613311850003558282, 5618071535926791206, 16954511293879569524, 8600749590433482901, 11708546551548237376, 10879843710159659952, 9101678715417935644, 12126242459863584426, 17259866272884195621, 4418382641453775715, 542305129955142216, 6563442437678466173, 12794875758080454756, 7461769876910639905, 17925257245127463276, 5137728719899113924, 12905981752247605071, ], &[ 2654882163556630563, 2047318842992691178, 17944530594807555614, 17278864523505748498, 1160166728089482341, 18368953657130322418, 3937719995815345698, 12007028340444721520, 1496744539933999053, 1476923054783110845, 6551619938265612084, 16801911333947266527, 13986495313155597995, 6571595571877061463, 10140569634762389822, 16210530410764331582, 15172903143228403872, 5831780706385794192, 12288937301416472500, 16224579586702000460, 14545605105156691376, 8614987803254853144, 16629891239728134900, ], &[17831022488782895576, 14315989140983049585, 0], &[ 18140975738986113396, 16765596268029991308, 14497740378349400824, 8834432760455669008, 2081502095596466916, 16785570606386467383, 5299348241512211807, 17503170383548190207, 16775442261989831354, 8131705923782084593, 266320274487676679, 6602256474512308593, 2102043233085822823, 11614561527212258722, 17915538208051341722, 5710195504177465517, 2094480568485157388, 14339014023087152780, 6947889352398323832, 10985139413433625547, 12373170520775701923, 9198039438688117621, 15475638737141339650, ], ); test( &[10; 60], &[10; 56], &[ 14660214196707223375, 14265972253040120215, 15506320303100465818, 17085621003033826581, 11203337550022453944, 15493204961705835371, 5803021083410871755, 8112917457002746745, 12663484193891261040, 1721048899893287199, 8062187621610464306, 13431761655884620090, 7331427712144411262, 3626934647030185267, 13231383914073320042, 11637171044660683638, 15189928975258171045, 941827519265124224, 2992792486091076914, 2044203374633195985, 8310380355675814732, 1677894573715118386, 1863631713396879617, 13750903464355877990, 13561054993991137710, 6643134394212488277, 9782189322903525535, 7987880548748269544, 17396502810230452231, 9355336424066456608, 6974435047841500624, 4695995454788932008, 9790410161672155866, 7324176676989916049, 14873447357313289350, 17933513319573948354, 16221633809094225356, 1119296061370324791, 13659405622992751643, 10536448431317839371, 15771892335411705715, 6450515195565208913, 12583173873673842188, 8943105588740166659, 16781237121411387206, 7355272525679995848, 8924936502454129260, 9464007023044637842, 2392086820925613645, 6952992660961663836, 15709161892606831425, 15961199354349516091, 8170938350051511007, 10106337242460916657, 4519632767875399815, 13966478644099829332, 18146666299243951179, 18001892575388798951, 17442461326088111501, 12996149925790510613, 15125238000270787220, 13458137050174539117, 7565676737178758148, 7820895745333505106, 18391820881894926862, 17227107494212736312, 16170524482788524562, 18292226432698054709, 16409124153431213414, 2622798522164114141, 2030148142272451724, 12631034221630749586, 12521714531249855181, 4869764655816857917, 18312880399388298885, 1881841240505020002, 16686085102712131293, 1638984612454565124, 5980766772519196081, 14473546029553426533, 2610255570241349719, 4121823778233332328, 15196027812344512481, 17634932614139407184, 14566629132274047837, 6629067916649366603, 39453246491293667, 4118307938296638515, 176389639877922730, 2385844666265721927, 14424300909552701177, 2596064544694255252, 9262830285738421829, 8366979142044016136, 12451088247268499723, 16456341544263224076, 405434591376297036, 5989071471671786526, 17922319711997177283, 12402685985480014221, 11440567647536028583, 17109382986734751589, 1165111999013207871, 9042409351611763515, 335396288523389342, 6889397323074150916, 13998858741906849976, 15927944587197048898, 10995067153735213576, 13255077995174337515, 11985913648073551062, 16606199253171990948, 16615211378568935152, 13000672060735124358, ], &[ 6726150808576237754, 9590776370558469124, 4613857594775205869, 5605914158178321857, 12627075307783464761, 456502911636413728, 6201419543988208076, 12457367465345491402, 9194484469177303126, 14469237774454463326, 8872571916644400618, 10371861714649740250, 9551882050917532587, 1418647961867356190, 11742587182398063873, 11015016132415914044, 8777839015232205587, 11080046461630228193, 13740325869131645472, 17716201322003396844, 2184375889136968144, 2744007897878529583, 10107840174031679018, 6807210551800087042, 3927845063936277496, 4657264236265855475, 18202437017170404187, 5332422779150911238, 15515262280249200267, 248667350560422394, 3473467338029486524, 5450666559053310869, 9114347711968955703, 1001965327187909086, 9391480248060184246, 9069754537718985217, 6108113375902101471, 615335597740998377, 7341924484422171664, 7557688311245960406, 10629369615492290302, 6551022068682485711, 13009629572214277263, 9801266711191462998, 12475469715378400041, 16817728089246511388, 5318131496704799888, 14034696640350324685, 173195053797772988, 9465580662794117123, 9395502290798332505, 172507413604644051, 13462235362634225088, 9267822876689174860, 12978933587961252639, ], &[ 12372756710207599663, 9737052986771636298, 16735862446672978006, 1139195382411501599, 4025384807176208306, 10128156782936698507, 7100085357301525578, 10639782880668134749, 3972383448210895518, 16316091826865092258, 14638110565144662169, 17027377005940147919, 1984424298563015784, 10943215534705396352, 4761407742818533080, 536799158643182373, 3577912885973196462, 8426618872156874849, 13718975316423099691, 9890119685862829437, 1661366149680121631, 18221664832966866708, 1501909944594354041, 15664453277583965124, 3204453056814894230, 11234664797845870989, 865170089562739167, 15036893469165510103, 9555056751383235767, 10793253279766963078, 10975966662822330260, 6344197561810800775, 10052816891387114632, 5489737378772055553, 3577007843046523907, 5025363426761413084, 11669827237042875622, 15298941946562692234, 5287362685718508737, 14167437013528222514, 108442285706035530, 12321077902001896155, 4987860952577552150, 4822344167562733502, 5046873607058225743, 15023457088946801127, 10073890866526654379, 9395914048369797781, 12331509678230261831, 4207910636930067124, 13640015182632895728, 16512336849198622133, 750194286339711619, 3343827571253159031, 1179021970615059386, 9309853498190567264, 8323638524074867625, 2319424490723820181, 30896532530597901, 1, ], &[ 16979197013852036393, 4534519222829727882, 5127955051936920534, 5669732551578654322, 13787946500638697314, 2666880029397285003, 18286001525339884787, 3747928243980886079, 5670276194023029484, 15201258611907138387, 6046915833599742673, 13282924752646783062, 18026143804639821221, 10186643213552896189, 17209309200088910354, 13215180252119768256, 1246399679408038126, 4186715523775575401, 16756959752065842207, 6600048850655585015, 4543693866439677976, 15594233518271892275, 15247811862837572166, 6322126320582019533, 649809830609098083, 5229876751712742127, 17719948521867410031, 10737539927122287433, 12476905306147178753, 1539850235988803702, 13572545877865905325, 11163694899331373883, 7882148214994127637, 8164419266634080608, 5782587821804107698, 12155391719814216620, 8020222143449740150, 8489927257914490530, 15688922762526028920, 207673185831465902, 13825819490340731785, 14207999229863934400, 10163751595898713958, 17777080404153962435, 17016927136773389232, 3820023214020965653, 1892439588667561762, 16909683715900311832, 11919385779232783009, 11201007117990222527, 8700983269916503928, 5034192113764375450, 12790439085134048151, 17790018876931315900, 5953092655978688336, 10, ], ); test( &[0; 2672], &[0; 1031], &[ 18285600144381611747, 2607658718107379546, 9747604544742966856, 2960103437306950033, 11333576199308712527, 14238003202284088532, 16265332193148604979, 1379942304307770309, 16938783330207677640, 2745252988447228002, 6791234087903673829, 12518174636027607009, 15674280970395865818, 13974288954585950791, 14841204964098561443, 8748517132169388864, 17525897240098709564, 16349048229068678114, 17968982428715890523, 9358013674764648602, 5199229606169954727, 422943872008603371, 9250194632016078797, 10021555560097390790, 2684614891063859627, 7440654004485895845, 15497536988658560429, 16091759101488274182, 7624403524401510649, 10159556756468762769, 2567573898157529790, 15609657766585643253, 16236943306986434793, 5890548198293774422, 17362921261219419202, 2808858681174890249, 6640440299319480962, 4326748503634915406, 11456055721778818238, 10707187402450482341, 10505948868316563545, 18366980076276187881, 15068095720303300745, 4952650647951470154, 15911634980226720120, 10740745397838202379, 3200127162032008025, 3763543940730164508, 3723483274937556495, 17871783614248259146, 8786059543177366813, 13050056601003380055, 5623281846050325544, 8511114651096961385, 10891975825673952044, 16080052858418260073, 7171941023859325850, 2503165103241590389, 11967819128596062687, 17746426492658731021, 1524291256148953421, 2076038155471824980, 5880985691677435840, 4713693495653829540, 8577899432290161344, 11976146392187565938, 2529575305527670284, 3765314673643814808, 7234028569335439232, 12375682646064399341, 7101569992574162906, 11098657045492285566, 1153652218824818047, 1210454437960036069, 2694638310421669121, 7870059579873173861, 3508868899875540240, 13609981818610730741, 10703439073683625892, 13071420953159015459, 13716502475013538938, 10634244764110852465, 16403497596959564382, 15306415780193612609, 17601327182445704540, 18298349615021078405, 18111916165749794999, 7537294468737253688, 7386987937618099419, 10775482015504178918, 8525379645714838775, 8788609183023289620, 895207535126054757, 17118106622782691546, 16749800484842219686, 10933310771357651927, 17045784651422893806, 10055875188754575183, 9519498699655590213, 17322601174638910336, 12118730165352641482, 5930728976613565641, 17159697904528121051, 15309680603600886131, 2354852814839706361, 1866864355164982520, 14799678913936204761, 114516480202556771, 13374320542339641716, 17948849241297689882, 11937303202723535389, 8708253685264852524, 14784022410383824926, 15741150074911773529, 4751508515383369506, 6753819133127024063, 7615256392835158829, 14330334546462075477, 5916715905113385520, 16699087896061936717, 2161501163497237132, 7657705954734728178, 13842299391403386537, 6172027960597539813, 5307601271781038790, 4555363624168980660, 8897561972602250232, 492135721000809790, 196374542645899516, 14990889098212601995, 6381940097804056460, 7088456247368733765, 174918913838309902, 14001140535865588809, 16643163063827173806, 1238954875765713073, 13202778059857945377, 13892311264186089515, 13771970066908683469, 14995846051430041367, 17421145547571170005, 10821698378431695436, 5316647583697276386, 14051654090444941132, 18388943018780729150, 11259779711269878259, 8742581111664031470, 8889827116461862655, 17319531559654594882, 6500455467003400955, 3959184730122082747, 4054561166041887982, 17316966724931034861, 1607293446195331113, 1556357414629043861, 11011377910730701009, 13217502480646592162, 5556764467305459566, 12021589498137324260, 531690648537094954, 1038223775874752655, 10112707642670009067, 16909364180557997068, 13549292338140530580, 14089674983696767092, 14960833416043686252, 3361732906192010803, 15411952217752187419, 475547270098839964, 8227352829235176532, 4333410121135356569, 16974375358381043398, 7462799035629267008, 3961814110661375506, 3191195952723002366, 15267463856820101363, 2682345599906528119, 9202835087842166762, 5753494002443879006, 13496926465554347490, 15537050413782275199, 4005699994847427717, 13011783168070790177, 16932430119108925312, 10469912374234875027, 5996081763274312546, 13299322992254047535, 13566444816251120959, 13441242515242491906, 6531470165275421029, 6998803913624387519, 5190923639408924125, 1301326112306077751, 2724835656803633652, 14868270067404848561, 16428689823791581153, 6363562758622431773, 5795421246045082577, 13738077193279334339, 17818084837848061577, 7409215264364848571, 2893214122000373991, 4066741278513513286, 6208913273098798518, 5323770029909018782, 5551337708190405618, 10281953507639521630, 7674048265312145606, 13913805095945202464, 11645578449852204207, 5216827728522108969, 18149089235876418482, 4193193659542496963, 4384037638695340997, 6264405355262516799, 5923041840648053673, 18445416708501282570, 1449616427668184913, 17814282379016188485, 11394546105942760801, 514272123860845956, 5487867953647208460, 9765982880054791980, 15269612196572547812, 6933672683776753268, 10897766962490536850, 7963503740124897799, 1249067770622312125, 8521634516253063564, 15047118858576393194, 3052485574284313450, 15762145598668916146, 18313105704770544279, 6541634279146063106, 3775400747866844137, 16496810669859720010, 8379319521731425820, 10800415684660017782, 6142541123129235279, 8861768666560539302, 15721050291326133652, 11134786092605171040, 13017548541999335364, 16909509841464459084, 8484654924270783553, 15005512331960977142, 4074672441814183738, 4078543398182843194, 6773998236248908357, 631977413504183184, 9491750397437496755, 3377999220825657249, 3346615552296940898, 17604589720878522247, 5769086022977878966, 17347842858220401404, 11931418629108149400, 14490915772427782374, 11545152969051431084, 18194530049847403452, 14802318193842666424, 16217304261948074309, 1412773250833563909, 7479345161017490691, 14305628603682480019, 14047111540339531390, 2202019933845371318, 213291111871207451, 9537101822050445095, 360483935799398585, 15821799940301882413, 13587044781648265473, 11158232757574497759, 12493764616797894572, 12454593638118113923, 16175783796857016626, 11972175061436709392, 14628387199635430458, 5253379621963585234, 6809274079261887574, 1124840670828961539, 5990829238947221675, 16084193379498378212, 6869638953004510310, 17906409028525617365, 2739791577758847487, 480131078003075884, 16023370915391221306, 15817682603522356534, 12423449398808644199, 14130320721960901031, 7934273914237433979, 786249691033407308, 318299827682676802, 17097143809787660310, 17521193394806881361, 8643211685837497345, 1204030043754228035, 2676537878172957478, 1780844249865247048, 1857038044392024228, 15537174113724189402, 15216184620024948614, 18295257315773355758, 5049495368122551869, 511689711728309335, 16940513174832634299, 12104504465679211266, 15914220570778735059, 6279446781938212962, 601029894044123455, 17804281207827746870, 433540216199633732, 7944481812184613751, 3853777775611712418, 12126936213601232312, 7065913778676807607, 43238211455364752, 8192260579196809431, 8266744677261407642, 4334793912650253838, 12956232517663155469, 5369404211871099568, 3235414488456415006, 12567595135095181283, 13364037675200086203, 2815554933029326376, 6185051196142844265, 16989212187178652008, 3878956585408701458, 708958585074504373, 16920922562467588927, 18249699025766906652, 18027337540317897651, 2618966708286475266, 1113776870378384593, 5988471205905783011, 11449408349082147321, 6427498821108845882, 8757628250113942992, 3713195263318788838, 601232850676293890, 9498794059653193118, 6534298968814526870, 12486527138072517297, 15783607638066166551, 17817123635789116996, 1248377855370621035, 11141540237607695650, 11310946791190236066, 12846390650128150341, 15186900836698527641, 3867690890119912186, 4589172752928224161, 18406516299291763072, 11413251654981660385, 16024801440525265600, 4278405775100889986, 8755603474239908996, 3160069975842943114, 9906744402561181341, 9965035381218832722, 6752543667701180453, 9346639648731189767, 10661232594877011901, 14936909082854570803, 1969452932415658459, 1696145335740060250, 18164995195644723626, 5001142711409868759, 502680569449519136, 3022117952710893422, 10177903082752941255, 15652975217635236869, 2966845407346038740, 475611270044318476, 16066077773226714888, 15255919358962415817, 11732084421089027684, 4677384405854396649, 4610350216539332701, 10328878907789481841, 6555568935797623159, 3017832515483377819, 14707077320201566872, 12590581217649731730, 3161603588075729925, 2563665003397527163, 5979170469664323613, 5626012705821413010, 14527466196441398570, 9288633927607394750, 14475257195709120279, 11865264300717431518, 17136126069177251144, 1473429666850111981, 7510246272136643144, 18310164183004169194, 3593138027022744772, 6350576143506118040, 12773591294872180021, 4700465661075210908, 18143542497507479548, 7719757932210686713, 4338121025681527358, 15571485830471842974, 16406722845577898376, 5721314859539898709, 6589287198671761501, 9745964795756887415, 10659452091068591333, 6690465060747950210, 728586915321808599, 8500603684008829799, 6301121250492508617, 1984503548524816268, 18268190305907234300, 7454276134026583117, 8547492859943863047, 9499474055416732782, 300834181303701699, 6423420221300563233, 10906772834067949181, 12139236772746843296, 15479617127388528892, 7255634393137870745, 422813312578980582, 1148428423488055078, 2405372466822606988, 18202859592780650711, 15123472874738759666, 2160560009262204586, 1220679802754985663, 8755041458565252857, 10511683773218681884, 3102123453859609904, 2170460789136594842, 10540612896965819281, 11507452270722296921, 3888033478974547053, 2913172211662715309, 5819754293645132724, 5417423241393498910, 1121133064615112577, 8899735394209007976, 17939515994389118968, 3057735335191827376, 6167592388365551096, 7859032161115089000, 16392857948131842701, 9672772119042623246, 6861392074297507574, 10079830057029967718, 1610021695530123734, 11499290474395739628, 18357287834621605730, 7842767805813604560, 17595414094496571456, 7727166516961623663, 5489874195960679366, 16978517381214022058, 11807176188692933608, 15778362166265505627, 12826269652469979971, 7799517220815997172, 6941343467007860979, 14716681029145080878, 5685272761645196256, 13841850638623453280, 18117357664247936176, 11360524534267913074, 18408319184374782489, 7834872787814949745, 16527576874764684677, 16576008924894848236, 12304125447826256834, 18301056937365686021, 4783517752793787963, 2014695633627143026, 8288284640512774782, 14976342552024779031, 2436344641520555003, 13990286257760881060, 18118120610252892651, 8432102189510702685, 9013208900764457155, 15956895100219663594, 11965405775699735022, 11479704069694999185, 1315304162999565265, 7619720903122481473, 10798255112249544769, 9067939483463584201, 8242338589636256000, 11595456341434427053, 14057071507676286987, 13492895734414905617, 8167664880787891961, 13065353170057145433, 1390434145929843432, 15097573448811012551, 10002618775785350116, 13037941058513405166, 10812662834979031696, 7926490047107184245, 5399553758270644040, 15603376937288512903, 3817798784005377844, 12622533130989118638, 12217900933744511855, 11495811053435066455, 17088770095627295990, 6282760152901843934, 11339571359698956951, 10010250182369906159, 11956984034096448616, 230656938835165573, 155123462325204273, 16323688331673735090, 12405389233556129322, 16866268093283320126, 8076215192615100819, 17788391733691877517, 13738263070347903116, 17514698963264490076, 14361153193344045623, 10697613194968260318, 398797896589607036, 11354436663860273814, 3988804407101251650, 11718246560466989132, 10607955713165345856, 12293428353299936422, 2774193885283164233, 12111880818145942696, 5269109320979566091, 17700804638146972952, 13483325589659749714, 7018249448187819229, 16605502462498173206, 14334331196281817568, 17997264741331536966, 16942067749941194095, 18326105716816079857, 2873713554755956975, 89972251875212547, 11011206003344840167, 16263607631557095555, 3956845690962774124, 15843733851407790844, 4532327333478987933, 14523922448792187179, 671512032483507444, 9051952980308527779, 5771887136664598504, 7318486125138347367, 2056863287621362849, 5319340499967729915, 6771692072764865726, 4993497900077789612, 14846578576184294087, 8749976795074478239, 13944161778625889141, 13939659589211557709, 8674498121103871446, 13858955528517010167, 6854968788299690525, 9785571842093558996, 6616581398547260916, 11173134838307567854, 15020736287331849950, 213678875278769463, 8136043007787109258, 963815884865140222, 14383997603758711218, 2441395136452256841, 2285295004115032555, 14143394511135418137, 15622142144369079201, 16493347221813991820, 17474381401274268608, 936058552355041089, 12942246561895670820, 10317584384347004208, 11782536454405046773, 12350945172113506786, 7391214981076111463, 7073023377646396731, 4011509139909188128, 2257833537102580311, 7274600296374037369, 2769150843750451970, 9102426399850639067, 8214223108585585549, 11637757222275081002, 9169116734789273638, 13195915003973211388, 5475411329499291917, 5086118280372242975, 17718728186337638844, 16105088227769019766, 6209815346219807551, 2881314910093736440, 12490322405428340882, 12004395323760866113, 9968698365927837252, 17316938449682856319, 15625883316417529399, 12226632472013770838, 14161693092908388449, 17778030898846793856, 13976693691407275877, 3477953777282076567, 13740936608896808297, 17180555612721269478, 13416907629329031924, 5869124347540464645, 13384341358033251916, 14313718444333031397, 3376219002404246289, 339811206717616611, 2616093060711965335, 8204344482414301835, 9186789611379643507, 14338727533336579685, 12784860191396059227, 10489777731949698480, 14621154301243573986, 13692422118348399108, 3784610479458294357, 7735714461152647872, 12931998015666009092, 12887123618479150667, 4005389619579094200, 12949896351841026182, 4274952326880371758, 2252542616091249178, 11223191016227664360, 12276921256190460942, 9311103011248164424, 14618190821987444804, 16794211813689377361, 17066759525543500866, 7695930135720339816, 15636206560014700744, 7080595571863441999, 16002741097850788650, 7266069110373243930, 18266417640341330095, 12863061635472560818, 2804143153090216476, 5360410260257436881, 10259005860191386447, 3129239898744374569, 5704118451966324874, 2617683975038617110, 1419008983250810424, 18176995508939903574, 3428325565738056333, 15807295691769067887, 17098475885649833094, 435386771621069983, 3749240361804507548, 3484935049619675621, 14151734623085313892, 7107401439542109862, 9140252282652202082, 17139755393802157327, 1840890360164731160, 13945742659422648167, 2993927710006218010, 5123393630446195909, 12126601606897174993, 3757237441333108331, 13430475145736272456, 141286591810884028, 13716994059020442018, 16256272733681835404, 13021661888272553737, 10938682475722641190, 16670594791610413108, 7581768967654565510, 7258449528404661741, 16972464178815325271, 13103916238623071625, 14383222643604888683, 9134614536502072501, 4484749605592970811, 7617523826265603571, 286970167644433897, 17350844883213337166, 9372418001867268906, 11036524012081184976, 14599471605351296864, 14353873970303354160, 13804851709719425521, 12542207662034387249, 5455404902951618435, 18208534021141654431, 10760289922882806669, 10594303509090562894, 10523612649331418075, 10175165805141093468, 3845925331470243881, 9968712325133293994, 12632170237051093440, 14407500129795275129, 7039838041956792694, 8486437057635491253, 12990896208114377714, 2169038646525679305, 17731701498975515823, 12645000352324144895, 6940383608615873690, 17112601588170442293, 9898015000882658910, 14088035355956248952, 507013420654526970, 16055894587901325067, 17646639921892423762, 9750921155184562446, 854792204257329267, 1907596925043325411, 13186585073232938657, 17324756184357468589, 13215141704644982246, 9990033614756242368, 10703741257062175210, 17316690423805264994, 10087888281338300084, 1089239266776577821, 12176439490507890322, 12695856964012192215, 11884436036930363286, 16729977556989227363, 10923433806234038450, 12992592892604117864, 1268144030942582108, 10300209358150898566, 7832544414491392865, 6657397193574515418, 17331856360490769436, 6685863352121534775, 4872607912521754323, 13925034245904306548, 15794800294630432773, 4150702655832044776, 1922931668614047821, 12163445688451808604, 6814128619400384333, 1631984743731389500, 3778862171994919347, 15454466802087055901, 9264991358295251267, 9936918682375797148, 18157798989566244240, 5581635369737696387, 4479378944085838523, 1634001250673190201, 9492710507275012642, 9234172590874940829, 8783494515876021547, 10628896245581316049, 9175567334027325902, 18216027702703135409, 11634672812751315604, 5707660447334077643, 10202156378293455124, 13892983828551272913, 9908193203293924452, 17571530454157193212, 15072879288037447844, 127116006100922087, 11771185510908260613, 2445074823174851909, 10670868476525820983, 7425728342067716996, 2985971528087667631, 7395252277468977294, 2997333798387301672, 17435969755936090886, 2284549800776567351, 1549552636061955968, 2562232096971944509, 18175473291905577073, 2694680735549112623, 1791226765063856042, 6639691018975209776, 14450608736185529781, 776581885259523327, 481545710834071552, 17904221072369375896, 7658678246624118033, 14858939803632465766, 16638621759785444057, 7852705140401778814, 15504288742303235325, 16123480377693163548, 17580674642691781753, 2060059788952429927, 8044488423463356775, 12159915697800522747, 9979462535316088472, 11464540989399692426, 9723421225194612320, 6449580914984939699, 9406550367550615810, 5311403373873226147, 3066770575413693918, 633416401733094941, 11712977725629062725, 4883265930195070560, 16189146570612520152, 1698905934763835706, 950927367170890858, 8829376333788190736, 7907286046365739950, 3164878452294289455, 10511755255842705560, 2924155429164172446, 16124299828159551950, 6010099555943764977, 12724759932455911822, 8127212736140639283, 10128696763620279450, 18035084640302368027, 8781918799260800755, 14441294204200284647, 1927193541320801341, 17060847707989835700, 8195209044950545498, 4420757359342589946, 3727277256040667922, 385534260624886499, 3266025280223616765, 8307518494652840749, 10628505726158916146, 12481632216062021685, 8443059664409740255, 17083655987996225144, 730490563149619104, 16115455384269067104, 2382469211629823819, 15299473012699513736, 2545726390341274697, 9566636451267734313, 17404798143522728759, 12853265630229752228, 2172148070178466503, 11003520300346660378, 1134402141777052949, 11771658227786580781, 12088790715698048033, 17088312113295353834, 9858438140481896937, 4732279313243969474, 9302577460868509370, 10413475674288905591, 13021872760990946904, 9638439145954399186, 2342341335564065825, 18026701375952328694, 5788988813536004381, 6112690485750689530, 12277817288452946380, 7006316162927315897, 12091459534025657274, 2152473017451714429, 7117646493299604201, 1591263581497951670, 12905706257967317715, 9739330975167177950, 14245120246238342654, 5445126088677322792, 8475451974915724213, 16532703318231814798, 11346158079313546034, 2587775018559680831, 16042335036595321112, 2783584919636232962, 9477074304137314302, 6679970828349102077, 14914134423793746235, 8835496380779847657, 13649036745393349622, 11800533244055495841, 10329924636422821002, 12857463828194064326, 376873602561854006, 13991526512239117933, 4244930150917248420, 9377193637737929560, 13470983451570137106, 13709193869228195237, 873834737899882109, 17298475531540644799, 5157431525573101837, 15694890039292357223, 7263973093257735703, 12810611197004081294, 17159179774131359627, 16320123751204284184, 6659167957772819702, 3559977382115542403, 12297726256906381994, 10545494770323931829, 14423760345131502963, 11951650428815262297, 3552160721881779344, 3921553500551057972, 8827773853996085356, 13035185276040540279, 2431229196115555640, 8867095302754162942, 5824531700307273486, 17795693614810306555, 5327408766240893952, 16204495625665346776, 4520750388436708886, 16011790401268552431, 13186223796877430470, 5894651091707364204, 7349710328825984565, 12990495590567591633, 15789659485048909512, 8110395238510363562, 7157879492847706094, 1855521204456327951, 9387090323123631218, 6983791028671987424, 17264360937175821593, 8964335962673307125, 4438686713691513133, 4609268036048721815, 13573223706586323329, 4370839728814507274, 7190667190262397984, 10585250032143309718, 5262324401338557970, 18436298550586124762, 615281048933821162, 7892081066718287534, 4153026337684348988, 1998277297931299322, 9570951836837442866, 4214601792245837204, 12544321637650748092, 9861635514343412559, 5163007832201827055, 8357508302373244198, 14941521234529596324, 3025149840692592346, 1565659965409485275, 8113415648323406877, 18047137088865383715, 4761751436090139639, 410742697284005702, 8123281234742203725, 2300465198396824513, 7573276443955885792, 18354607580020177721, 13826724636992006395, 8759796250561912860, 15446866439938431144, 6466830870344794620, 7248618897690538684, 10968843377874574640, 4538534083565844065, 10463149345079834509, 7862094636026465434, 9363380870281847317, 17750231516234915849, 10605066658889662478, 8651524573226517322, 18099624785064356749, 9012260115980472797, 5112736631921184699, 16433387801586396924, 11364983784749187252, 4592720300056375272, 17400478621152089229, 9960304372235946193, 6810543488590694603, 9421463587360187007, 11110051932845796606, 15820198248392525417, 17370225890188484838, 5511348958827419764, 2047354351196049067, 8842128025677787612, 2546794526658883557, 9990966093285021784, 10968573027006701235, 8153649946073344163, 3435896373516278367, 8854351008479838087, 15172945879518770400, 16101272223167010392, 6080119325930559085, 18336117387797080742, 11495477657407490192, 13799378353686928991, 814519040394412554, 4055424121543431351, 17971320561372651, 3045424347018335501, 9144749175919467258, 17693139582687085722, 15549618811805620741, 10042978303090035766, 11250820672049577391, 14650606162160854310, 681053092156505443, 1467784211081816986, 14292070206822113207, 3356550259250142987, 8897529911380186072, 15774124171111764637, 3608035896189707114, 14945841364780812283, 13638982384303383036, 5615554819198447325, 6604755778043315386, 13154764512915240378, 15781224930202608619, 5254282127938948208, 15314350610960881010, 127785624547347482, 553562291991422824, 2665385793464509946, 11960374868185251273, 11044390920977985650, 4524189753866435423, 11922516208188195244, 7322728958220573958, 4566122595518047958, 9257927878541886507, 11778087706650674305, 12675707724087743775, 14040780876086782366, 10310608200410344735, 14747492163773576994, 14763717547881637874, 4519119406094329744, 5416745750548195790, 8698677371585009606, 10540691781438295688, 7621321253979898000, 12870309033904607776, 8766530226422390333, 14410571192410377800, 5017391940288233504, 8156621488957733235, 5701635921482105032, 8697544584237000467, 14463840701596743299, 1132393248669674482, 17783802461705335925, 3379973927717106230, 170233915427480249, 7721198001501959996, 5984888435057942981, 11741252369856674270, 2667584213579254971, 12391311788904160680, 6403858222659082204, 1706835705335237525, 6951651160442697621, 3395001754770416725, 16336009550495654242, 1588611969581977597, 3369833199693136814, 16679631221398536370, 17143410383401198876, 10718378066292328788, 5098802788047763943, 5003995899412543356, 7797753734199884695, 9804992578690571817, 852561252664521182, 676543942240459737, 12047623372899199507, 12688884395525848756, 2909502726897081899, 6031120528123066491, 10187664230696218588, 1634984456433807424, 13461263282968829173, 562535253767547543, 3262317265760851658, 10159933570831396212, 9610081805557490182, 10645180788472548796, 3825134762043109512, 11454131642474959474, 9401675919629678678, 14450914272139752267, 7874801920832590192, 18054728540681521894, 15303403280502540543, 15467520708986418749, 7705766485597949742, 204013254901132813, 13967733294005655167, 4001477583895779972, 5972807400755250985, 1217989087590450380, 10862887725324735466, 1706534929358469389, 13264418588578493513, 10626892394654962607, 2832066031146486501, 6506140673085843042, 14326905332890415966, 4447185119806812807, 10289677945299645724, 4459612687423833871, 10867968914888905042, 6485974059834599556, 14142727197114410913, 8587964753565667799, 8972765350531032618, 2292328948393940314, 935062418987300570, 6736600688398044784, 7931198222933701097, 12299736294122528410, 14482610418638535345, 14434918807907278467, 2439305975663118437, 4480608229958318339, 3952066067287563861, 14258451016047506475, 1231074371015334625, 10331248234059926878, 748201218435577445, 17462982229802307244, 15686869687340151573, 17053063210448785862, 3599854718778131864, 9301737618251045483, 7627446349617553731, 12835054936982245416, 6336754664191040283, 5870029311999289016, 6027766907695007223, 4082089270941640253, 10932978191544782698, 858542788191451824, 18173438258887704458, 15950175591359254382, 10496438189070905854, 3761196574957125185, 8070795822731288097, 14333885717356195593, 12907535393235068762, 1300746091836895017, 16095775835363872226, 5221409894943186677, 10801943559441670680, 2226518879270450694, 14144518871296969095, 8329328663632421754, 14151247548153947290, 7005388744793033852, 3731783672032466610, 5642923046890143070, 2243566518435928649, 17827722312011386647, 3288494091174335807, 12802408479052688767, 3941775622555625432, 13974527790491109973, 7184506709498460272, 11905130726430415767, 12898188848602614942, 3336329541205892765, 16740350675338109671, 335449286526469870, 16670399530115701446, 3370759555155341636, 13153054802454960430, 17020347152181004363, 16005180766456295251, 16035747705790056677, 1904525470716808389, 1362939978621142721, 14268989953945718594, 3131759537359596393, 12623877369046640758, 16034480904634718634, 7205849095551422163, 18352760423874563428, 9294184574071126998, 4855176006968938932, 13740659884417148386, 9678792914697707031, 17346691148499799327, 3661296281536466662, 1858171995289042067, 18199380542019467146, 18435270579529426778, 8792805062170870691, 2216926146372155391, 3336698928747087340, 15361162057883195491, 2230334966886787987, 6790919905652555693, 9523654540872868833, 2373039885555601800, 4493652711092482273, 4848735304745253118, 4615650132005261688, 7011332091469251441, 15051588471309214410, 16436499359483898767, 5534529923924019676, 8031782014972324826, 9587715117105518067, 5201232572863714631, 6949484852216655045, 11242297859309211887, 5445327566402416511, 11759527029723480062, 7401655792007047741, 12981437329323060492, 16627917972301844941, 16086064209851186236, 18317605428363897776, 5479987106722795675, 470044962552825995, 3263508437049006276, 8532199872517472836, 179963713893634086, 14750710828805195780, 8566890372208465530, 457434420254160615, 9026428119711082888, 5051697286542220522, 4066845298260571291, 15266943848838025449, 7790231715639606132, 18047039423184779192, 7097787949459808218, 12326346119319424869, 14895758855340221400, 270818421368673258, 10953991395430365501, 10722834322274726220, 7175276538034253286, 12293270138776886211, 10868230614957475384, 15568806031450505970, 2173332627995000239, 14888402241228040414, 18405500854031799916, 9396217995786697609, 8638079772902395024, 8700301862255582170, 16669714149683986916, 11791960995856983997, 6941956874526614041, 471913500417437253, 12645657659237731696, 7344954555441957686, 8576764504255171238, 17045229481365431866, 10710908163870404781, 11301570355963434173, 5971177578976838887, 115032958122130333, 16996195561179864691, 5303610406571283411, 1557215249726500571, 429079935597742432, 6007572072647948719, 8793841786368287656, 209772504980789061, 12514491936429933001, 7014555801251009174, 5854792368971550756, 867919854085761466, 11854155159921686895, 13142074624110571417, 7907850875814485970, 16861742288872511551, 1208590626489658408, 8601279929820923503, 2258924690462246171, 9585184984627008623, 5315828210383196353, 1297805663260559339, 7398320505542428444, 17073967214624996598, 17704120650146094638, 1299385581680024947, 1443489762904405882, 13518221354231615324, 9070126881206870042, 993730884724745294, 14081041013869681380, 8359943552596347499, 6866696380166200245, 3837542845849508667, 14602652064433499913, 14314340020057352466, 8839559535694012406, 14227230979046046062, 10298228782846904508, 13298718693240900028, 13909155817605919274, 8780642200132615642, 9412091595152829592, 6822145839018577251, 8785978531052338151, 4948528066049804851, 1172628369060862431, 5666685907911162463, 14153629140204265152, 10500845530057771412, 14608765724027887761, 5087095504941752721, 8701919577673940506, 17137520717957261114, 9199637801040704714, 7095886304415555902, 15925336741311965253, 13077337771490692636, 145710441006655783, 13157185292334340173, 13407008567503772150, 14215960022966892561, 11985156240556559472, 17945288516894513884, 14097688271959790972, 15505832877271523166, 5843174730859038007, 16205337090179264073, 17606308108912062454, 669419080191010051, 15851467430769620452, 4936909049694472990, 9426661750545745060, 15134074240235574428, 7927257239677744604, 13865931916371651548, 9055694221969554578, 18105938911030359772, 17344312477772739728, 7984780979580024449, 17946659128143746086, 3659014353178730517, 10881946920507249755, 9643240829875041416, 9979006042478131099, 3624673912637648606, 10183097162206305022, 14705929380474025749, 8560872261129163553, 8542571307034562924, 2849336599501641328, 1427173016960915063, 10561422500956348533, 13953646915815013961, 14711009426065697276, 17629582482698947067, 5068672373293663589, 10328236305608973133, 11390625625852214740, 16171676010227409920, 12007752012156277746, 8787339600696104751, 17147558071877953304, 6243146155416198819, 16781815705425825152, 9276534213532622927, 5681999116735330218, 16852010554258505062, 1705868855435043353, 14818213196970587370, 9256091199810743680, 10438037318676504268, 16794099631419865392, 9815261792343983998, 8286783569926236889, 337573434858179240, 16820096306284770618, 15966431763494632363, 6481208570789422743, 8429344246220730373, 27262454150324780, 9516508385964067765, 12876008564654096078, 4071754764426708210, 11593726207040321843, 10464906996437266409, 17795281436982488931, 7949644313068982658, 7004988298640898067, 12037768710549869791, 16790409316897618369, 7084103797769437957, 2419445775321185382, 8074279743518467644, 8069323749479463736, 17160974715554385442, 6446198417065372686, 909199233418090118, 17988046405451941411, 15619199660230837101, 8540771809211736979, 15004059727603767665, 9970067037279458294, 18037810830226270966, 7395784361237814976, 441608911830412969, 15193617525949907726, 8329750585903900376, 9232838481221040709, 13862722871242295122, 2651785001097390772, 13513885689469842635, 2916635381190975954, 14673366675350976320, 16796162449704211211, 15311238965453782301, 17048079530325153354, 6357896971279650981, 6912501188214061635, 15767706566209693421, 4950547784710662682, 6818275469676220067, 6311416403137682772, 14192827820659451230, 5519753761822532883, 6327790738344616319, 1571492847028444517, 519836968001291628, 8880684714326015791, 4414274058554177288, 6693694082558848552, 9180328506312734588, 11851754793034588133, 17892308745832908148, 12122989628255788470, 9813496966285232956, 10955347908495147392, 7570827623140202413, 12207236341183232786, 4777412212063025006, 12385252236023114447, 9508166476039999651, 114906234504385867, 9207258060511755437, 9210800729712345963, 5771423404639548192, 15194614200877751860, 4338352328776016735, 2610599495858282641, 16733979028371628176, 1929910361255473211, 14137591116693762330, 11276030669834631098, 8384908437274376663, 9932945040858512861, 6671057894832572720, 15600691762738444868, 1090424207156031951, 7633234269493162481, 1452672955493924651, 8042177265524791320, 5918487395429243286, 6071477929355428400, 8446553879294519239, 17238305490194970122, 8987047329207310489, 12398791106166157316, 15174911221193868718, 16946345338721827201, 10949948458544444544, 17318691300002579588, 3998415180681624527, 12750967780890975278, 288347833998723232, 16095212211245790724, 7822321122528030405, 1109063169170634828, 4652215944166612902, 16803163450585461189, 2776655336762420387, 15642000619067002463, 2018031858324511467, 11237756472829950832, 17565143038179107620, 16281738469740252935, 17600775725533342946, 14750124410220606835, 12883103971220877489, 15936542280450981255, 9714323865324229767, 1469778854158587075, 9593652974682074282, 11762461414294133530, 1404229929827068795, 16503900992928085410, 14684251465993475323, 17706137844161464268, 3909560365123413776, 9861484314350641439, 12009083324415037686, 18169123171153377641, 2393555352820887974, 12841835092045423984, 5564097118032313065, 12777929502410633133, 5078336225337553091, 8694020844593690446, 11388328638584884970, 13970084235020262491, 829772823417380360, 8286179729255644084, 957139202750627952, 3221879212666198953, 7645002751366998370, 16715354970243034507, 18304845819423800855, 9447343833119941047, 15163436489241423867, 2479924668890227186, 7818020209349584296, 10580682200967646169, 13911404593504958709, 8718275660345998055, 10124290490841409455, 7651303722187917624, 8976889705380896709, 11163660337280624646, 10388784795451265724, 3541771203499561964, 6075152751154669243, 2218667547472367527, 3995516111323252367, 11180655997089000245, 5073383660790586917, 13458152992621454755, 11676714551890338118, 1494799466123513971, 7327872328474238339, 2389581909384645325, 16687753253842922782, 11699615151482669193, 14774804959571915475, 947896829667145566, 10573954710522391072, 7072571908216975157, 1921454675444217366, 11232731567954977537, 14840397076140631292, 5060980672779376677, 12975040048834693618, 10752224255692434704, 1306885046650589222, 1930876755170305305, 8739276995254053408, 17062175909187112484, 13994219820475631601, 15241051299228638903, 13189674117437271785, 3224946313788614445, 2946953495584212148, 12515092889993340415, 8549243107224308830, 6555967774604787675, 17074340742411084655, 15860252206376208136, 2452901849982359121, 1217176756850333549, 15260442969744536089, 15266619117940483626, 3092040621234773226, 8592622982489602359, 17268283100249965729, 9118863795573669565, 5004589504450812591, 6062182260926951061, 17997691517876082652, 4684918577412859882, 15422706458772273904, 10373853167444581181, 9008368442714488639, 3624691764843327336, 1028359463583846893, 859230892908817598, 4558109131236939269, 9197636145007824268, 3397702897203024845, 17645318682095346025, 297912191657103235, 16707811002284900618, 9544713268645707384, 18174588433767285273, 14115044574398526220, 9550382630286578375, 5669098498675234593, 1419240760313025600, 2624357144105750680, 1883325833631791743, 12465653732071455581, 14016850785680848114, 10853862374929837476, 9213307118918963573, 17446748283231651532, 6944359057113621208, 4376214699313790455, 4272171302826636053, 1361571807732899930, 15928311517924806859, 10979193193168197302, 14315748858106823250, 11415251230794226377, 14341688199410222112, 13372316746789815573, 12205797915700991132, 12054245058919264469, 7420566807537884143, 5432588773028217373, 6350587654471565537, 6531829368743229731, 2207976572300046135, 12703622166413274712, 18356491416550058865, 11743861089192075323, 9975481076082250423, 5270519543247843824, 16596875614345327407, 264970638689993857, 12731851329939038802, 4100374548344342900, 11696626303514932259, 5795347109604371486, 4018536166291403802, 11605839014492166891, 4046122976220313619, 7173051512574373511, 10760222355399775007, 2397452537849365173, 7000689557970901078, 3508218483424754056, 11249130935335670874, 15485017380487364008, 14838383309738250533, 1654265944033471910, 6550408986795246586, 11574017534658799615, 4938545842279886871, 6987608227293293739, 8490763818451756454, 15553940026252549950, 6498239556873819401, 8894315085699368208, 1767452481216158212, 17391068041642225358, 12099770647562592260, 3232275359468560052, 9875417733360604587, 7344425724555447442, 18431729052975636742, 2951164042491135904, 15903903429564563858, 17834292681718510486, 4198460729209826867, 18283343945753908147, 13114879247072451198, 6308546439134988873, 8448793227573510403, 12883523838880467178, 12608354838733343984, 12284418193790956340, 3099459343498815410, 3160460005758859474, 17209423043124247155, 10299954565801063517, 17312198705527288316, 1159079074290265282, 13803764368072178660, 12357928111570535493, 9319226950413258817, 7861389264222959398, 4208357822974886032, 4724453996000826506, 9219506857747054473, 16650755835313196333, 4602357483273387357, 8421668150799174361, 12464268335381289971, 16842331782835636444, 2164847798539863920, 11848181286892607238, 8483204622866252940, 5177013341061819166, 6794893916803855304, 830729528874930746, 10838023688403983614, 2936119661394195602, 16749442537019148931, 6282125361565649956, 12522652324110588825, 706946363036865451, 287377191870510960, 4079038197618045672, 65600267963984525, 15852196146124192732, 7791496333170096323, 1197307315361468886, 12564376588501612052, 18287064409980818748, 16513413097113895910, 13772586176619885924, 17412579692431697526, 9943582674770693553, 18017460763820483721, 12774668415999817484, 17419661422487800791, 8542296650831811427, 11030794367359113173, 3091992835617551759, 6647390664467556203, 4760797422569339325, 15821430759187595540, 15905919720868415262, 6964495470980486330, 11481098497210815485, 13606157196874073055, 2545548939497776096, 17492549168216383449, 976625893298873591, 3307888858281262315, 4406331424039826265, 7251492960589745703, 1462803411594068207, 14615947077492017745, 14477853980032711958, 6580067844089943084, 8164600499091902269, 4672103301095852237, 355042099720565535, 11026766258596173656, 9849960052517135155, 16725670149953992537, 15683028676578831515, 10104782290810509683, 4905343590849641899, 17726532108833531580, 13910286230069122723, 9139857611408342006, 4873918044036171351, 5211230260928194081, 4862798578450111352, 8040863435679951765, 9157211979753234216, 5969001182224545740, 14666007377730777715, 746412171062253704, 5788296420214704699, 16052313287704740168, 15016980204491105152, 128634126176999080, 12474550947728802418, 17798334047543705551, 16546317352521543345, 5935130659172645630, 9017751516052971809, 8734332868677069231, 4489180421214586024, 10852153455030219222, 9452853792027507, 7518566350390737179, 226398539584556263, 11348207575144575782, 11286381051277848898, 2699324198517442237, 5176288375717881953, 7814733078102607208, 2870574509136744908, 13870395192961519685, 16224938596653908092, 1164830155402073602, 6289706313355675934, 10093838410108560175, 2551691589709651401, 15882696485463451559, 3395731646324122865, 12473003610421288231, 7149619960361615882, 9872807622306918213, 6663012576266477470, 17016549792515115205, 7914178572800158023, 17014701567637435932, 14346020259284370257, 5074365976986728463, 4760168726990175515, 9895948792206852207, 18273255159788978236, 15744547484672365588, 16864050091650583468, 7152138044891906219, 3133231435713995056, 14654289506261133725, 14216037513719362689, 6883938067921952514, 13637751749205284541, 3930907102025842836, 7818503413066881742, 16512268473175446131, 13618638131220285482, 3526560852689406895, 16317348279030286281, 5781706287563855208, 16877706843053345782, 9787389520151320440, 1672625892740702444, 17775094144895143457, 7284734471708236532, 6265912061217026214, 16428427284586036469, 7239300285490611080, 12257099262814629130, 1443098110450745157, 7111333716613874437, 10912463389630114261, 16046472632120791101, 11071308475967108461, 15827031925467657247, 8451701545861351835, 2032718007638091987, 9275305708809424137, 10133532607349132521, 62031173551766505, 1069668934694816298, 10021315903394494037, 18062320514241791111, 16614273374620642998, 3874528406029009574, 11609554407744278526, 6664429329059042685, 2466789265733227250, 13791862987730476433, 3100076428479694646, 1940573727807547478, 1717992312877296193, 3858278897688455120, 2708391244967786582, 5897077897033357390, 13903090124093303714, 5210172753029188249, 7461814148277300830, 9825991953137124992, 8749849231144845954, 15733619176610014569, 2536045915051793710, 2795322555877650589, 15164137179922407098, 11311210084140344802, 10571285191092929225, 4809833504711226607, 15053596169163492600, 12405664553095020547, 16471715640263755395, 3828351876877550724, 8499888452131579133, 5279727535149011805, 788643833745941437, 11012285726544455006, 15140257364221864448, 1834285009459528474, 6667182475201903438, 15294024395589453460, 10526482467856757788, 11877982762793807927, 16230316864465358123, 15723393603594181628, 18424513935220466565, 2247141586434891619, 9561372576131838874, 8725104655684175177, 4143398848385382705, 15142179196637056843, 17330386941741492571, 8185673125837710067, 14939737481973173962, 10478395787666924945, 2774689508274990026, 12451742284278860222, 10819437460867617255, 13731567691766219490, 2010973683387239919, 9908150371329956596, 5142510757399393995, 8739166923706997151, 16903649040425907246, 6887419514989237100, 1875697363324020800, 16410802797521308346, 135862499096678312, 1002710565280860416, 5506348106905501784, 11368287034717703998, 12947266586015982813, 5318254909926585664, 9296468205284792595, 8004814724160061752, 366393468717204226, 10790734687437783398, 4968864942084278227, 15798662312565535644, 1358717464422009379, 12888686466434430386, 370520483338984073, 9184642588343372758, 9427179068402613262, 10546786545869440465, 12655417731444306355, 9241957630409402290, 821497951821470195, 3197970711092278947, 2184424336239199737, 5106022623290447939, 16287048031456496603, 14037056338746814782, 7474000199931218562, 12188148167023924203, 4192028392289466906, 7847291769851591899, 3599561900723047299, 851922034760320751, 13587138821847499752, 15960408996225570897, 3252001517847791314, 794174927197992513, 13500786923616416327, 10492520307372562282, 17778963725733766896, 9940193524688369200, 7839429243680619309, 11152685327758330011, 4793514629906514769, 12571317405831554973, 14236764890442489777, 14285226682975878252, 4752465601541667238, 7069073862761309134, 18297621617638524964, 16921089529724869008, 15310629395363439387, 13959904965987734388, 5530325767118220975, 955257971161171732, 9249687876412175486, 6437014646360143974, 1355675591008680076, 14363814817404705228, 11444699168208672882, 16890344077647521215, 13663194688247169944, 9311758702620596945, 9111333905244008262, 3739308534752587737, 10082399017494306243, 14502104680453962352, 3240447658814963588, 1945616413338215240, 12702436196323839746, 15056103164643567233, 14232906369316952845, 8850081479512611348, 78742167026295742, 10346207199790592003, 8330318603106182342, 7555172829812303483, 9135554534047252825, 2213978715965424041, 14487841485121669529, 14201073224315526620, 12002576656710628646, 9216161229854384642, 15287364979646883311, 4707577895128497224, 14025232799632084648, 5317706395334588893, 1489525665074354154, 9157439364142092486, 7033808256892914411, 2856904746309353752, 11315255790030198921, 12167475608624586287, 14898366696798509538, 9918128939648387398, 15155651994814693417, 7300960472494546400, 2127526231515960912, 8923406206829661118, 16210393114988425815, 6582813395371196199, 15621762854392338472, 3789550044424910854, 16988798023618902953, 16490593537106458722, 14139545158028230044, 9923635478455782946, 8897217280317716469, 8453814653444266828, 7491325054712040563, 12316700761490127631, 3768457975900229126, 3000037930881673503, 16933057766750635435, 15031174928418481583, 3019987484089942716, 18385609936539305759, 17538768527945166806, 5447221007766299602, 4022798439534764827, 17074805847175217989, 9477194110020170032, 10200259846152838876, 6455055232471034376, 5679758327656142352, 7374147007380920949, 10200477410022066193, 2678287199491553725, 5011120062607229052, 7214257460239674372, 9631753064650306646, 1151983673963114572, 2455508156322019163, 13344796472161923955, 17003695385004214505, 11166307372098954131, 2221946328882472137, 7061489614039858629, 3790971501091116413, 7833733804721228481, 193935756315502298, 10256338066976304411, 6065749049589877362, 10736472690437134411, 10155365416269683464, 8189737882773858983, 13671211115390707327, 9578025336797949473, 4003423028251739147, 4500512304316856151, 16693811644887033093, 7707767344560596984, 5599541458797859603, 11592325835943024402, 13355669588132489385, 15932001697488084536, 9870357379952328535, 18310499762741838752, 16196774945614723862, 15790487345250753382, 11990590655367464148, 6718674416650039299, 14857329469228715563, 15423479737409206383, 17779878703537243863, 2210183662909405344, 2815540909030329829, 5940765014986549489, 16884893974961992656, 4351638805125702042, 17084353252120736247, 5724252085645496824, 17794301429798973952, 7949129492433028333, 17290229503720706399, 12839841549866653659, 14863383260888850679, 15788917858243172461, 12477975711782044218, 12362210923589911101, 12864920132785914749, 10860162458674426789, 15634366676531407135, 6076026769874036504, 12186624835981223643, 477838969646790588, 10209086843687255723, 4453597694185557465, 9792638779490749472, 8664773568287178159, 18322711946104316656, 5061590004040013161, 11611936838758532137, 3299611430381151917, 3978890638406515286, 5081581149863744934, 6181936955807580784, 3372188069238850634, 17854265102071578827, 1268076978660794505, 4722477313014336378, 5471980643922086499, 16788648796682094709, 13328529160256523927, 17816434316065398701, 4038311782651024619, 8255869964978262613, 8890037824421975027, 7319879894513022697, 15914698902244750946, 8857389029776818687, 441863541258666465, 3208037884158506723, 6113734693574039276, 264986606662698668, 1166237501799711319, 1823307447602740420, 5025672756710206999, 18278689422657324853, 4594507497487291210, 1280886041213346013, 11896598892872950706, 5576693076164380614, 10907097907235031727, 317196941106545936, 10598515286008372146, 10232665246931238263, 16641631582624438065, 1996845757059763068, 8450189738658666487, 16874433980334624325, 11462456373743157203, 17922058749640783486, 10312126789368172997, 13340565145612845891, 2211332034685909397, 6280821632118062402, 11495261020831147497, 7525751008510944548, 16481618138878161375, 17687291635686050126, 4726039693402439590, 6224312974372200845, 177270674822437819, 12844674102136119940, 2765095317735756740, 6375785787962152345, 4765877337254522185, 5699318866607950771, 7726266014961936643, 10439969907866586583, 11215604933445164846, 11144874084048847665, 16677507722859793772, 14926605406115980653, 11021418173114133993, 18143508384673173911, 17869384978881128193, 539841771736061948, 813906843235746774, 2120916504386756315, 17563694758070096975, 5807011249822640473, 12074412278826937750, 10494691749052118094, 4034710777981084065, 12945928140391853828, 13460531663356368909, 9805968628270501084, 8389235258735557083, 4653641631812286778, 8961436573446073348, 6695344158613046716, 16832827001219019801, 5227374831316662089, 5088308882683339576, 3279167959625059741, 10436103497832123501, 2797296687506317311, 18305760283738580632, 3531912382829235411, 8745021258521548248, 2062796519113317445, 7005506890190360164, 15260828944473012523, 11736618288708934540, 15523033936060000556, 9071328583193116055, 2949954518191771020, 9219149478710608069, 1788704922178497999, 3917123331723493156, 8283987826876682192, 3926515941902592230, 4576777655155350003, 2895291773949819710, 5409491793062473762, 7827016058731337158, 2360244091777092634, 17765210336693396066, 15413391993237156529, 9542656815625824892, 9430563399204843121, 11559365450247449510, 15796909749180552904, 62820771556683371, 17275496805851130274, 6527142162623953967, 4324187305635963626, 8775772925418898915, 4283973075245351015, 8846184539722500106, 2860502690824226817, 1240652940592194, 15064048316358894661, 15864254034666279286, 4098943802367114793, 2956682521101031793, 1877556925464957894, 9589792900125026809, 12161426439049578986, 6435540582736037161, 10575856639119978060, 14751225739652781433, 3642975302329400055, 10213336036038833464, 7137807512192531866, 15715238576819145647, 17891816262406767004, 2885759842806217828, 10001842985502100171, 16889965688337087910, 7192241521508241891, 12459052609846245573, 16045056395445218777, 14263408894637697194, 6319194484923808205, 6887168986137924562, 4723017923445345268, 8785445940747788332, 2221153194351157100, 4112058037714640844, 16624774310058492682, 18155682498135649179, 4932684590312312624, 6466580926084050461, 13095557293811313234, 5629819270691955218, 6705036397567572049, 15096504303120814344, 17813708390329054153, 2867801270346878637, 4428369643259246081, 14356128800268363075, 2105538175211522946, 8157169805154179676, 13281934124532911335, 721993975496515367, 9731311970803693633, 17408383560695508306, 3661032291356469843, 17118601234529144108, 14173384340046827967, 13956269658151533336, 14193288209519401944, 10854924829501094491, 9362722838007437994, 13139075107441548779, 53888779219483732, 9991228977857148506, 11866192603390104699, 1903043806364214756, 14664090553522048890, 94655028324146279, 5944941626254245313, 3067815658183085252, 10088835779690593635, 12586879497500128294, 17338285387265829132, 13546679410630118150, 4684155179104389445, 17373141188216408963, 10683275227724384825, 11727464505463619204, 16890013009763926299, 12256558554118856945, 1692369148468240661, 14260594858617396870, 8079067481737035693, 17302479952759473929, 3465288033646104738, 7033532051975356541, 5750806504528053243, 16142598027708695045, 3763071556050151375, 747332911728793689, 7125512446937882000, 1711762381076986594, 15200743445044769163, 567070148436076824, 11150986733649743405, 1751542514779667937, 14904426643112052682, 16243812463903474525, 4313436371286419450, 18281797249258270726, 13863976627696030069, 12604750965802575212, 10295616727116267978, 7795942372543067322, 6713137871239810667, 13830865828728404463, 11139257890131452244, 2759969414377994154, 151123411588221984, 1548247161690787301, 16234894685549118874, 13392592243844300663, 4341718471344294648, 7137644906875460827, 5416631993939117377, 11693386548832817142, 11851058952064231493, 9690204938813699131, 68528268163302809, 13565043622050152230, 7983220844142817842, 6794808910151851013, 2118666482985725107, 7247597207626321306, 16937693375274789158, 10616884815388828659, 11696015248644704721, 3352478958667054947, 3225871086863590754, 180230908445925268, 6654741577584823985, 11710009687907650028, 628457965752902770, 1735690146666342885, 16556237906505825388, 12440271636242780312, 8713058872068144699, 8975441040195700002, 10850963832660773043, 86339822673122508, 4000323666157343936, 12142567722725546249, 3374710818178624781, 6392232680788016964, 12790199390015157427, 4671003891873822839, 4452182512321524727, 3905095889403963026, 16726139916064776463, 3453332349452466770, 16221710379420353742, 4632551944540970365, 8387501246722919769, 9326344266173346561, 14810846036626389828, 7283658938651037849, 5813262143148998917, 11727805907650385268, 9857096480403873519, 6356324418997451940, 4218579215729792881, 10470999063206203293, 622196070040738252, 17021144211023071215, 272053703337182123, 1450758744433386057, 8397337301039096971, 1756739264090010567, 14804942979114893233, 12762190712783408010, 4486114271404551982, 13538690353341899530, 6182493449368831960, 2768435790455158079, 8491588540734758297, 5001428683933385935, 16861055012236061995, 10578636081126268849, 14449779720168257980, 9370646703732609468, 476896208068404545, 11604128769892258429, 3178840918267575500, 3407583825966649895, 17913378662961900390, 1138652617523020638, 4702124733398535376, 16197108716716127538, 16852598869081929632, 5020614776073585872, 1188708373797737364, 13456434315549496452, 3798071449732352219, 6593816705053129140, 8463318160472344568, 10114730768365942765, 2093191144313711189, 12720945689550243678, 17481264965133664645, 17640221870440170657, 3490097599238691289, 3624992904734580452, 5383687377060455481, 10776924742527744182, 15746021472289883888, 17925392760128571522, 12689005861958409137, 5231100489367895272, 14007286820825332338, 2397858260918981403, 3320067181759583430, 18227252228223404573, 18011328143837002368, 4798104660333169602, 10865877383638846865, 3767167656736085179, 13252620599128939387, 6636747284560413010, 13514887050922862847, 422456370340431886, 9612933469182009435, 8572209183721381907, 8056048067037472186, 16714990476240297166, 3520645146861432874, 4395550491627332110, 9462218612700999094, 6214250154185857186, 7628194292741759764, 3556878717144745691, 18413027616459454704, 10160691680912469038, 13717170760433051685, 15180833335295580609, 1819382907555618141, 13320476638466170165, 10422294181974936444, 7164181547072169074, 4206492057553506325, 12633015044784588629, 379171732810097117, 10351100759422011738, 3673330411049649463, 15927757725693044281, 13690250449236882125, 15900551197649269941, 18329662994600175312, 2110669219011944740, 2226752393294287183, 1014550150137152480, 9887871066385753226, 4568683160401484222, 10951431797661196524, 2312645127290056695, 16937439673591720324, 6396609076318661377, 8389300110486808887, 1923677274274786580, 3549825163974227141, 8566399761898493308, 639620030714191084, 768228320555967661, 8108418530085400912, 10272182341228792152, 16750158829727849854, 4444117530817286053, 586462195320680600, 4278069062735193163, 4273315131401359275, 11611787428091079232, 11835985289253260719, 3096230712379885797, 5322239580881209060, 11938666223318366819, 5060592382016062327, 109409443906808448, 2380457102117134635, 15857731461784222805, 6584665638956888535, 5947254465908568523, 9420786545084124002, 4503761263873856534, 6641486141146012370, 9121700908113990684, 9720958769231915561, 7003782806520614311, 16920307773004245532, 12763580883987437513, 13231043349317133789, 16203109836791501802, 698049430375939280, 3030494131166195541, 10815604140749178453, 13804995432448225904, 2055424018541357006, 17073648888173819706, 15463924428711597599, 13403700103090470402, 16763806955533746160, 10509071477142331263, 7405199613665848444, 1289961083639614668, 13019156453931533504, 511380020193300140, 15833618630547184883, 16532434650886462678, 7779349734049489490, 6380411322746302134, 9492908436973173105, 7167088077189974813, 17396059932024334263, 16483611260630861934, 9669468321319436238, 12712646425834594093, 9288405016973860570, 11325843021373113165, 11258335193384041947, 1997545595799365359, 17390606419645620788, 5130387948734042681, 3121742342628196576, 6099609462914905352, 6524840389448497409, 3251588966299685263, 12515453442966781968, 4351131781828315306, 7915089733711494046, 8605641240710406093, 11102717433954517200, 8816805538627940082, 17227753413606850602, 10263075023716628113, 7686631682618468388, 10330530590800536028, 2587341603576202527, 11500396296312301825, 13531587115648414633, 15808917747546864365, 14333112763098420691, 14761783111500015307, 53964954401492398, 16533467491022296104, 3096485428305684908, 6318844018415466634, 7132560604178571060, 16428604738409136626, 4375929108222206025, 10112133284375140971, 3256631261503314080, 16136845689782815155, 15928971771356595498, 14645130502697393764, 14481748170304871772, 1698922547070724229, 9468607121868930261, 11617214057068823437, 1382928294652688250, 12680084220201263431, 15926122141331194025, 7979147799621842755, 9803599832824191350, 11150566171126503035, 11946016594155356252, 8452284422264862510, 8621047342992105610, 8991106617593209637, 4607652189428377711, 312850746210123282, 13020253158865282886, 9665527964173507749, 18176337504665053651, 10689513521305445515, 1839607582702602917, 13793618456770339778, 12156395506174115903, 15230345865671590927, 4715973552531673115, 14606516029379763286, 17293771405588962821, 16175698567845501145, 3789965395433901756, 7250432289837425960, 2507460993020556336, 16416011798948565038, 6033312224978543324, 14568892906298810894, 9207153067892339499, 14537938431481818790, 16550516704016530385, 9907670198667127499, 11918889385815695319, 5981318855234384164, 6303359496211585544, 897784439258088201, 7533487805017595619, 5938457201719040924, 10019150195260257017, 12026554931880038202, 9224513724236448133, 18208973061276109233, 14240550756243930801, 15387974810151313549, 193781859214087276, 11713954174101604255, 1341093990140003013, 6012491122871297010, 13892530467037865965, 1368649256526022373, 7020819021722718671, 15787587617733723291, 7785870968748246057, 1947448600658942561, 16530328214840567615, 6317941331086952570, 7139842027589405175, 10933153414206777090, 9672586073744099620, 17228494407277874159, 11578033579087247602, 15459493510831207600, 8222705886823487604, 578413881840029844, 2972330100500591542, 7515621234174823899, 6704318956697481184, 7539293268516643247, 1580608997901534862, 1201050878740265829, 10170365701874480907, 9870363666224664306, 17305296184407747996, 4224805619364289032, 15085837243579345311, 2443632602903912157, 13046843267919167284, 12116351035376725179, 263232896451917215, 7772071638110042980, 16549817644785034122, 15257628965480096285, 13004189693733577363, 3864285740392230962, 3468607145721577697, 354566527372793754, 12925883576993237617, 12693175375557728813, 622461988842871628, 11397527121006480165, 12911631110359477732, 13101149248297235307, 3443924800339223639, 11021054325079132422, 5789359016899607332, 15670032899436160802, 17231336489372520758, 15011195019101462587, 17697169511730379360, 6214385185627447169, 10180011765464756731, 11047248145840743090, 2742832730133990272, 14029491892088421031, 7977004417662816272, 14199429721808423163, 18279997024327708476, 13359704350594785266, 18410294947752215697, 4900459096393373794, 17759944268317835227, 7514273237508120753, 5036409225635108741, 18108376710275555530, 2676982762515162946, 510220139774948017, 9208245069742717667, 10376186455595199891, 421637325546718875, 16791119924695165602, 5075099022211468458, 12517850612529158688, 14010730112031892170, 9181830456575508952, 8562092376348428853, 13106552497603917850, 14302339172367595976, 3354417171377350434, 11375931064094009915, 7367612779037974062, 17960646160089319914, 7765039110674214207, 11258859351125514864, 6790503465712539668, 15367600556170700044, 6616796092052086761, 12472062233228758417, 6844102383328993237, 12811249515443122455, 5102740036611216259, 15944761788498002902, 14694830622589958200, 2106296585469395117, 12001390986454100522, 3886258101634881021, 7626447484564536615, 12121778508662936673, 4637632611996699763, 284639519767470911, 6111767225293430109, 14899978058938638435, 9492490138059005865, 3457376194893217608, 6384991674167924954, 16479663265444998572, 2182180597909020672, 15349832040611960272, 6995769868581799282, 7434433066635564427, 7330931577518389882, 11026383041313003706, 12870325652218422628, 1151311929447712791, 9598200806509616050, 17161065747263888006, 6901765437989220429, 17524807833762947972, 7424089904607803796, 10169273845585922571, 427683750176118191, 16198716196396797311, 4234469982734082109, 10433113399561032205, 8455659057075573351, 5339947829324400827, 8994757262942082927, 16110373093388044843, 8165219755821135739, 11079951015921397003, 17913162205445436558, 18307573113704258140, 5184334744599569992, 8209592006521651537, 15233048304519008983, 3893904742760952245, 12843184579518607189, 16317789833580002355, 3932965922048250109, 39643566078340112, 14454778211007988105, 11325761588512978910, 7326308723838667358, 918638912645150633, 11749550850384896237, 11656774623671896072, 4102579533296639675, 1131200342214858221, 17002635763021940679, 12699501461265202766, 18366533628748257986, 4211496006430696197, 15592383694738584641, 12132073284414780422, 14112124548036073660, 640983069936058034, 12843837916043035998, 12619927090786907296, 14878814042191779303, 26802691526432636, 13542740387876579301, 3027951464265029786, 16531319427892075667, 7433366770688989904, 17675108936726475823, 12991848794171434707, 11308307557943773008, 8441361375349434971, 16048668185725998079, 6848195560782317706, 15732631277486546880, 8796031012662685103, 471880524013342791, 2847727284878021151, 8909402802655050731, 9155393982976367055, 5339419398360353054, 12394943475850749453, 1082481852253596422, 2475925758143360234, 16780844326338173281, 9955442783741736414, 16398521725460554238, 11754389093333746016, 9510081579192799387, 10740614081401142716, 6751836211534532930, 3310216743613517077, 4711354618706526528, 11761966320912417805, 36323519866736684, 2431075662700945654, 15771975356730131291, 14504980176985527547, 5551404397884447150, 7328632262405216781, 6659335151951442348, 12904376258123706403, 14766024566003307212, 2729153030346049029, 9776447889426450664, 8565088926995480737, 12733048698734167426, 16140690590167093278, 11999311158468044755, 13598288633972733571, 13732432400180070386, 15194135950298716633, 13160554968820068964, 10539080943199862762, 15115912129273478029, 17652613656477189074, 7952212396658049573, 16131569825649579263, 14739342068703048684, 2756008787672952449, 17980612557340090024, 4505357043573157185, 5886347178459794981, 13467166348185532762, 7542340141940109840, 8604473128836312462, 14161530301987102049, 7768636854450163149, 14487815318986749283, 6851630924543230233, 15816812718841829697, 13309960537373415159, 13533823018337269511, 4066246092121693604, 9157035362257855573, 412214665099375028, 14477789736289307578, 8471884807077804890, 5401116457851954216, 448871182302722508, 11307725734317055468, 10916897930231800956, 12320324583264666269, 9855253221365914708, 10341139850853598251, 473763070798790310, 2738091302514798630, 5726660080813664052, 4685085520987362, 142836371012422078, 12594070839012993809, 10074822048682622819, 12827059438505836814, 16625605990012653363, 5223703331085192665, 9833285584664723263, 8290425612857589870, 6306954960404098112, 9412474111491552241, 3143257994045884457, 16371722385530408059, 155878147658248091, 14824551048836933161, 6944511999081736143, 12540758531163865907, 11983135069038529053, 4545712278933588398, 15077557719097293644, 8824726955621677512, 9467059989026717476, 1832994947759543686, 9395963500530779164, 10187513723496037742, 9614996490866381781, 4074827755791565698, 12833908036330960194, 16292730478901857762, 17035820163674794684, 989273775053529110, 10590449105705689408, 2922575348536557726, 9097036857789013295, 12287791133096088844, 11574082336078807433, 16687006015927882120, 8596744673168310178, 8970905056348840750, 5517972678784462826, 881430805465529877, 3412610955059774968, 7028178389869167183, 5170343795610265286, 11012307439076817531, 12613254778376420629, 4047156878552340678, 14789560647177930279, 4218958252980142613, 6013379809704688444, 10780282427110087598, 3110875217681031780, 1760113645124538802, 4510301077917148010, 11245657134256982381, 3975465112728195039, 10147869619910151776, 9521542758217967325, 9796643369778561059, 18438740993593422996, 5755122647194246655, 13089871854524075038, 6020811568278170849, 2905460035802413789, 5770692989150859960, 9121733696504177003, 9054740045617104954, 6651061222026801570, 6979411400071458744, 3760933926638598638, 16334302020381288285, 2057660950359678276, 11293316249797872974, 11604535997697431331, 11921660539545426320, 9756548788646446777, 7269421896006778050, 3975439838039732758, 4483475473549910496, 11780853832789946501, 8179840661787229204, 2659883347338825753, 11257903019053621162, 9583945287877466892, 16363933527036814071, 1290785704105238692, 8655198258069320180, 12518299182873150764, 7361462000368712194, 9733702303272955573, 2362863984326388251, 14125653338074659438, 8452977297932581636, 12482787099763665262, 14889071888466818806, 13718685624353930921, 5045136353562987858, 5296643588295054890, 13213371806126402767, 3277278393660323717, 5669363365118437907, 15016463550423536857, 16936344489863263921, 2565955327304029560, 4796734652908453706, 1378655232854232950, 9591923038316868621, 16194271618909991898, 8523814065658657216, 968783876319889044, 11876875087504947472, 15343430958924511022, 4726016088940609325, 15814602580682745621, 17553495950903097582, 3845404925865098583, 18216981879371013309, 4102006890010720614, 15988113496959934091, 6019266456198657999, 11837451541533231967, 1877408958200970989, 11155878481768284249, 16966216363889316426, 16449662703095636488, 11722657415321325203, 8151686270422518591, 6829105588528021796, 5605072424730907975, 9610630778445319623, 12490688233524207364, 15924383595417258143, 6293909456050977691, 1520031459958370315, 16878056482786965582, 1567491557266512441, 11553059083075601436, 16588286805077499576, 2831700015193252058, 9291679435178297105, 16696183961702972685, 6110717331497256774, 3508641981673281301, 2888222167255453397, 6382434826249612462, 1615495003744037219, 3450690972855989121, 7373699525385823603, 1487214282399378665, 5054239246312770486, 6325543252810070667, 604916284274232643, 5705249803789781860, 1347389337137481378, 17341491803371701023, 7562092053824458983, 11528860291431916871, 10058885809804159773, 12028682695619691748, 2072309850975849144, 17510902039090560383, 10964691654809950146, 8557150693328114885, 10018287661176094357, 12067793619240607034, 12258652923874874737, 14315661805556678059, 1532344907755129707, 11548306890701017011, 9836569326549702085, 13196528743664879413, 16910466377189639446, 305247665277886260, 10234652344969601959, 6426209661333831948, 13316514153882647236, 320668129269757278, 9513807142666087825, 12132502292274229629, 7907062113630478532, 6769256578404078947, 11077216337588272062, 11192173094112274045, 8665424743913923338, 17273052641666860613, 8242738008086379196, 13851918804734763571, 7049674271488004214, 1410604294587433641, 13544384176158464923, 12468330754572317265, 1317196613823108318, 406832464837758362, 6039154084839734004, 1995025881371264773, 15399759218648596543, 7323767619167721842, 14228968351368149001, 14556483677198851362, 10822573411785744110, 13457687797488671733, 15113597365244568644, 5830040833200595947, 10782120448577939853, 5923233368326767564, 13565433709591402733, 7409835447323460538, 4942580795960776301, 8068857330020361381, 11063008871093537743, 6583328726807166886, 2194893842926463044, 9586490095482756942, 11811119386143060256, 3644614927094824958, 4762559862573353606, 7054841812193239255, 104169344287246978, 13956225391862408166, 4507288715283113798, 11772996098884686986, 12792586168475881829, 15798457727837504001, 16896795677207949298, 10265172010623416483, 14814049521182301273, 14251567652536773005, 11041033214099412656, 6589290323087713529, 17080306026857684487, 8536449894500168140, 13538904949191682258, 998478434926587432, 14670273496850215516, 15311327973305354729, 12644104051633342488, 12970733262467631495, 4625272733914046269, 4694472538276404068, 3167371560249938056, 12856489429820568743, 15490218655488023802, 16928081564771690940, 8200145788070169286, 3346452930233714534, 12795482436352374291, 3314315705851242852, 3285152211139935017, 11224563416094698786, 9705270177443534531, 17644295182363680941, 13520301373099144288, 3541351715009433425, 16020276637771846482, 6027464490277968416, 4251343941648935652, 17763014962498696031, 720132515041512177, 5173394266280593900, 15204667210087004583, 17335914961708883300, 13218634015062319702, 128827822406486046, 13559392235200971420, 17252636495073021415, 750007296061102031, 18254099543935170871, 7509241234704231102, 8157193578702246807, 10298529352072110821, 5298418177375924856, 4741852588831255524, 14527267204533561544, 9095259534397569417, 344527310846137539, 13247449783957233078, 2586644247732041192, 3100790169250176954, 16510173867908259851, 11333281937378448547, 10849352377567806999, 18082377466933472402, 13561723472079052715, 14547157815982897407, 9391369342410485871, 2348830231178979433, 16863733530713957956, 18119733445408743443, 13725121556809406883, 9229975878895702895, 7401016155946807916, 4811692959864213177, 6237359194264984939, 1904440073749912075, 6353600963009324869, 4984137724622228146, 1196090958128593834, 5119707990981594180, 3310978073014066771, 12983216966379762511, 6612762118768660390, 4003198331951059920, 6385796970903716569, 17680686381236190132, 7090591178254990847, 13123476457069922276, 11991645307762636710, 5129610078187868363, 5604361132348700067, 11043762682351635495, 6391120985682487625, 4455513730428273542, 3762654197950669235, 9310420262887992163, 11993439152830872164, 15439986350739535069, 1488229606606016585, 8189570287966130481, 16920767496097942040, 7797006069350129228, 17531953262576833935, 17024439366185018969, 8083356010952666614, 6837066330579419154, 6443183984423798969, 4776996086855661713, 9156255850041051387, 6083831993070398816, 14543764421371224439, 11977571598909514982, 10188060030334373973, 9449009160086154971, 1300044225109284268, 8825712025626564634, 5510762923192959602, 7324962531338046625, 11942013042939202021, 13598796371758253088, 3794998887633576199, 5084084225782194038, 15889660289095533051, 15428522601238467679, 13696067867927948600, 1072542240072425197, 9785760286300726328, 17624535067298229622, 3938570677885383673, 3705077412606219929, 5340068085943913770, 4210056340846145048, 1976665594829638831, 13311220586145473347, 6943938959824844891, 7268540691149845607, 4375885954089016506, 14963703931344653483, 2580585000938123597, 1068177107148635952, 2341910556569696351, 9142288039937977251, 8517576956327184753, 3376248516190748921, 13301443214809490744, 13173593921898127720, 17359893842944679338, 7047222128454518811, 5947406210583265494, 7833766002049023813, 18234948673625328162, 16320032712674678534, 12642441645902018157, 16283613144322847005, 7863579138098504089, 6035051266438089663, 5453172248583632847, 13775470103081167926, 1182333285767268205, 10495826772905540632, 3056962127861644896, 3638669906264037789, 11198631986907530450, 13541149168510941603, 3250675262588623536, 1880073565717482485, 11936216765079705804, 7530067836231811508, 16311420158606635425, 14900155531445760709, 9999132967166761272, 1476154866153451041, 7195014637072196640, 7248062023586150152, 12914546489578466976, 16344645330454865081, 13063707322424725098, 15370611307815629185, 2118132721549701162, 14789791523379164567, 13011177800824348207, 18047963884795850285, 13689837669785098672, 5906277653382226335, 2699555162272597747, 14303717239113776133, 3323572003892592160, 2809044788581830880, 12842135035209068787, 12962493426638468571, 7435779585695058098, 677266868482172083, 10678064418979058702, 10945593620822631517, 8023058850263770330, 13198960821944542699, 11380271889111358356, 8834711603621437912, 4878802483786297049, 13441769216931046849, 2621489868509896160, 2739596448875968624, 18316605028815878992, 6393166579696267066, 16501151485480928243, 5164267149115550765, 2594692795895679355, 14280335185447698254, 4970220064329069703, 12700511247281457031, 9357661341818532747, 5976227213729484842, 2603370613961010712, 12878876453986011658, 12614332416265768442, 11711218014924643648, 10655032017324143953, 17992359291438428544, 2028340169188763801, 11337597956814839013, 3790580704158447112, 15661080312640132051, 5990952720662828532, 2238062688033035456, 7214374085319154262, 6225683889287881657, 14352811622893565131, 14441940256427869428, 11264789359569297809, 13541671887968904175, 8127321364325418809, 1617127834649530192, 11585884571784117082, 3211445923374162685, 17806365145235708527, 14310538800447604307, 6443392190904066779, 12304012177210398685, 9644770647148205176, 10349883319707014538, 13335242320392313944, 11550748494455916510, 14451727464612357396, 12354315710763337118, 5654383747200879937, 12534212795765636178, 5562388391253840440, 18294236533364599656, 1155120808307866205, 7354961778452510694, 18411509148244472731, 16833067451811570610, 11664219918607046336, 1931829024033366436, 9466235535733377083, 16125981341055192255, 13123158579309508422, 2811914968022899296, 13666576380287885316, 12073873146611787542, 13976563976935754757, 16819184991876208483, 7126372516019046104, 3771351679962818186, 14749464410272499350, 1158403298912255932, 2704550233949493414, 2361919431011664920, 5147560855044821678, 316960590350675551, 8956506393667806523, 14816316691312040724, 5483483435418414420, 16492702091910529628, 11531197856172089811, 9119688446381120307, 9148465870444231525, 11348956949863877257, 16515747438741224650, 14748627773020492829, 6792333258618815286, 12745044341734710216, 9118601693019210121, 3426576167844415246, 4516979855142897567, 18383203113196616305, 6037335393642080610, 5178029553332071284, 120594988188384758, 16911068593865363851, 5611330513352860577, 3672922004740508910, 9348962843954154258, 13167081398063848866, 8662579917294749869, 7714235959241362618, 1992168626444259154, 2892890698408203389, 4458208962709454498, 16006038729069481615, 9254965750786898182, 9178915422232682008, 7329871300650615008, 3409678840041114839, 8437730364512235388, 12654053093050306243, 17603379767897285990, 11140578823362012333, 18400373855086378549, 13179220706346381456, 9393189516096637793, 7962379756613380226, 3887762359860195719, 4702005148801552936, 13554138609046523902, 16949160381904484821, 11391648750970778464, 3884921049575088732, 2209098818625079997, 17799308759029324494, 8498222108115834352, 5958053849320451390, 2912489977852727908, 9002784252893780496, 9103973893872873428, 8800570704285521553, 8871184059044310741, 16063400495158915832, 4031307968282193036, 8573254083908951390, 16828584717166299815, 6494527269040260826, 7249207279315565170, 13665554008066255134, 16839236341242902217, 4123411447375871691, 10234357340093040168, 3518390908608069874, 1349715014789845667, 4808798653471270523, 10095338955926329757, 12695489128540790910, 16406780457966718375, 9629301538534411032, 15498997222980997073, 14953211317262356769, 13024285896073029281, 14612862358802352485, 13035854789120349150, 7106552057026833281, 14174041880363702304, 10636381469539675255, 7187203466667480841, 17084717625060872520, 14126252750523939037, 15698822748718907462, 7397904980198721162, 3690934666532247692, 15065052457896220534, 18426160025856536769, 8825186243264577791, 1029026778404309644, 6950954458719738495, 8771914568967577350, 9728022865849579333, 17765239852650572501, 8343956648157842199, 6334778100080475126, 14664915370166297479, 12941375852754193937, 6405436436050091550, 9909891363532277572, 17675467189601777836, 12324897459248787941, 13981335142409795938, 17744674612593350856, 2757587566489447009, 8956578028983169012, 17018240562727015214, 16391639968111798359, 10795774151465209457, 2093281970351304070, 4858229909673020125, 9933967343419708401, 6016509820559456727, 8502253989054157587, 1829270427581251166, 15709494579608995279, 8568909950760020667, 10892820698227375197, 14181785622385373392, 1741244869916907800, 5584342639358924336, 10920058455798795209, 8773147161499562392, 17372651285045475439, 4317270331835178992, 12072221230432227872, 5409998193192839065, 5774604676764375748, 6270673186535390929, 11593578005123149455, 1350291030727318811, 1734041789149423611, 17594245397221493182, 10230281830065256754, 17395251244463936984, 6363273717700984685, 6898868518537597264, 5078809256797027276, 16014780232233692324, 12698021273486013402, 10034628326465398981, 803921083181133037, 15053987885932962839, 2543409146477711493, 1443575144201918042, 15527634810280511429, 4846659158470140918, 12183993101313012462, 12953651110928456969, 15038003468538497849, 16252394591537250522, 4193562522090296620, 12800591763579590396, 15408603400942806170, 17682640208554596681, 12409260763379977486, 9315397818726387830, 14193643034683668324, 16508104272720261755, 13905815394730317134, 3679293709974358468, 5907121386159753765, 5304769534414875015, 18444287322445993596, 16494909212649576365, 1411980536871151577, 16554121151776992767, 10463210072047518059, 18023249470213998238, 12383793606215823679, 800485989566329537, 15071139529581604306, 1895628018455249296, 1105126069974836026, 663584933815778847, 3312928249076628720, 16646825576352631842, 12151072254529924642, 8642785126263747138, 15111584853907028239, 2776308895820674677, 10812673714292641746, 15054903323219264732, 2933094921150563585, 17830062919092998452, 10432330036767081552, 1033494976738144353, 9761049718456631119, 2978550270506139328, 2266577450295768406, 1214959603409486419, 4338607014040436, 4115159162283844446, 16888561205519247430, 4412890126763454080, 85232547048588047, 9970948529228850752, 3713393126801217778, 10760802738778841380, 4895931449000106045, 7255762665740428559, 335936537100116164, 17662778773720603199, 12685690660905184006, 14808811012699062151, 10663380197090780332, 7067049757688041329, 5878922448066220307, 14490189620281922843, 14473260627169887886, 14832232348370447833, 5951438093661647765, 4872796166881199876, 10429350570401478982, 15251172935852223950, 7325621106097392986, 11834629549993290294, 11569303197879748368, 977753391334101798, 6969686311950446853, 7366200137172124620, 14212998724743560415, 8081354270400804456, 880037272912518632, 380852277882293501, 8947498467697222234, 12757931014561147509, 667810441349799809, 2059689120439565076, 4750342010666522618, 12492546560830555305, 10465223395020225996, 9585389043436680319, 16512031046174235646, 9200703296926083957, 2032951915453711444, 8002381174072382487, 2389280604724196215, 5721524692632905547, 7647110976590069211, 12059178411864741586, 11975912934455308497, 17753420811972470476, 9192795740173474360, 12105166740957629248, 1250032644270746132, 4765787287696278663, 13422669569705597563, 11373393845567526876, 9153761787497611672, 12030450058080806969, 16537144145501712177, 5983397454957073922, 2683673672010015032, 3861849825629132671, 12629475949497494729, 9966234113604834798, 8466461060632654110, 3335857898642241962, 10682117780482341111, 39787149161941136, 5109208035333406420, 15684027554962652735, 11748970404336820351, 4095159288133322954, 11402790565133565981, 7401785106763668233, 6248303083190138658, 8738855753439299071, 15339296752899687482, 3182643107247815384, 9378566535341755855, 14162009846460499887, 4109114270719890973, 1511416153435046138, 9020508522805341634, 7477142615652523025, 18385803953807265839, 2546195602154738889, 7405815335061777589, 669094957884330982, 6056073383962448124, 7353716808540962518, 4360012167404246482, 9748894070631625514, 533481526701689863, 10374030482918918166, 8591056344610511021, 5753611323076772742, 17682325790000893453, 17410739240868104811, 5651721564405833200, 6771155463622294161, 16102506172900055409, 3922155114242412611, 8047195046803908182, 10181935025035061310, 7790459581343029499, 12616035204180788696, 11350000801651108812, 9664257517083996508, 6877290837507516646, 2900668296021062883, 5478674374212655343, 6296162153147759087, 16234745308754151636, 7633277882818614712, 12843201503731712898, 14050083812260020416, 95836250787434633, 8997148048216279615, 5687865929885690952, 7684029056960298539, 17362423790832901707, 15489463223618769754, 489477444088932230, 17185715982289417959, 11823522798262762160, 16827938740128105724, 13257410922007807743, 4679309639860400639, 10164917239224603264, 7304922446473936277, 5597481581945817575, 3820424595621388213, 6884972150866725771, 2694324376629657414, 16833520400918984369, 10912563532735352632, 7352008235482304863, 15885791964406330114, 11790453162438620892, 7239285021069261812, 10125071555494474444, 3796211625840968848, 193266766691985397, 14792644085266904226, 12987152514130686235, 9436744123646480376, 8251406129814681521, 6271920831800751835, 12738844182063426283, 15330691163818996222, 1166041665727565335, 13315209544138143871, 2216677316767409466, 12690036582164080137, 3031307738126062683, 11944440105997765289, 2026188631449062025, 9212773879860499293, 3341981308024472580, ], &[ 13169652012768583147, 11662749290968821290, 15540028649212863382, 15222191772599122928, 15852211273603082347, 2960464712590969339, 9805532347048503730, 11483156842014743008, 12223751000089978338, 2069577308821362462, 448020966454441311, 3493610387626232963, 5182130948708681868, 4456536535034921689, 14139535083059739910, 16341604127053129275, 8476750032358968964, 10942274856214572646, 4426573651999058804, 17958371714565221264, 4238987860855800392, 14450925264923938948, 4364481289454625563, 13074790925168694865, 17725186031491616550, 3252385755044260850, 2489691844698347065, 12584453984545921259, 16484939371755776909, 17591699265602016514, 387926126025483991, 2463760292646247776, 1563580628888369628, 12118979090065897855, 7930230430393343357, 8834023487181578700, 3705061516543521950, 4053176902619603587, 6269266280509284877, 5236641881717368169, 6899670106034156441, 12840225294220778634, 3029440279850048735, 9595166473221718273, 14550471357175468027, 1255830945916836371, 5122133954630663971, 1502740582962090101, 9086275497101221342, 5421916064800438697, 2179464833779544632, 8247585817871008274, 10322070671895980987, 10962237209348590213, 1167315820290398061, 4563405457798620948, 5324869835018392710, 3941515430275954463, 1740094742017128848, 6138471019874045522, 9176213051434147108, 12501904812453849864, 11388325168842467058, 17687408972570957542, 4497137255970523312, 11770269946165024215, 10156397926378383551, 2019377424484113393, 3590983554593693717, 15657928449196312716, 14894403732533901822, 14625564293418317463, 17710716015671252818, 638852277383858770, 13800670797826096071, 5519007738268375392, 1013914690263468265, 13249504241724137521, 12893315643913486917, 2437939332985629386, 9866735673756110580, 7894145839618709904, 7802203558085957599, 2394814001366981818, 7648858197866754106, 45932857419714984, 9659675215715090679, 12803466849037463477, 10717587339591792614, 15131328571226415781, 17805628124155724278, 13655343682572989974, 17362327502804463995, 1075287460052064029, 2626850396158965217, 6885136253881452991, 18424853270962528365, 17198461501972637926, 6379806426022159044, 8783653573177405838, 11457364326293914599, 4889546163609369345, 8345334679410921999, 8128212263869118047, 5243835377297724594, 13077589216209892913, 14947690960428829294, 7468326754846892750, 8665069680383178636, 17267364262089018920, 14794644088627434581, 5781944628494317535, 13467037542503882140, 5504287258083448304, 3101706185952735851, 16528687565738693574, 6853101285149030710, 958150364135525317, 13159192403688468400, 9000130047394330226, 12454106782612240528, 10410037892467703265, 2755063393447593674, 16909229563067880679, 14030067308250726680, 304063827283258286, 18020451823918033658, 4591035690657100956, 13162350837887011458, 7701399978207767086, 15815279200816529309, 15597387052720630170, 4740390593486726162, 2909712595092459460, 15729877265226222100, 12096570103612063938, 13702753332858235272, 1411835182384377603, 17487917594195511154, 996305544975114980, 12929066524383774152, 16956610067055251962, 13012122099231548957, 14395689158572846177, 7935429077563080059, 17542764935243101497, 18413828249925519615, 17271321257298840331, 406766324155888956, 14818331828215117974, 8187386216945380849, 16792638575276899182, 6540004189057298818, 465689003663102769, 11974785539062893556, 11523099967255714584, 14591636912283935445, 4871757987380755363, 9308130069290886865, 10612219179153523310, 5420071244571425562, 12724302122592532888, 5173545157589181140, 1429324130148847596, 18414282026575416657, 1721766939064217260, 185288146264311331, 8027581238524003859, 12629121378225318691, 5422022678890177669, 6300007666394297907, 13771277516427401556, 4461063943424152501, 5814271695863693557, 9833762282568603070, 5534898830643720899, 11414581203473717153, 13252208296859650317, 6070377927034194834, 468982118171070321, 15569817073538385644, 8515954578625472255, 17703147536676285546, 2713926565223832109, 16501613896332875878, 12360649233716580846, 6951122318765494287, 1255018572838364315, 5022530899188934293, 14471021290055621346, 3965972119993826976, 10914640319991729939, 4671893019190076511, 8132288757883741990, 7379730619550447967, 7082846353163966035, 7749284037330602929, 17090786448482076935, 3623093583024522445, 6775174256836032571, 5932859643874401763, 9263718069255818484, 11941172789559596258, 7505495305758940713, 8374557854631657796, 5030384219708396008, 3609081759463861677, 2444176790044307758, 12883357531875110193, 2545675590276006076, 1091049428613676247, 3001645527995991696, 9613284625002680960, 13486970893816936976, 11564610387350917328, 7838720830134816136, 3368189672511472263, 16407993343222005051, 3965440550685537978, 4708478243468404768, 1875742626798710446, 109477476572266497, 9185060711428219960, 2062557879153655855, 15504010890019002364, 1436468774610332740, 470895386030379118, 11192666441535176072, 7094623340817246353, 16041820192281853667, 5048179711756437977, 1908765243120848557, 10810219542319634593, 15971282719319513661, 8395180060853137311, 17415231760777435363, 10489441496511966940, 3213813993411776195, 13309643264471443871, 14152370013037392509, 9805694808649718454, 2991106746654603900, 2279780759950444362, 13989789024965052794, 11942900996372546394, 15051646099368945987, 7583267444740224154, 5192555551306992142, 13216959612015226558, 14397593124921798192, 4374707725758052604, 15529039788482882168, 16475619415913302762, 2649655538625316107, 11899566009797061232, 16892018353302708322, 12364166218684092426, 10372683350152669575, 5328477050361662527, 10949313792626687170, 11924230090558408019, 636095257275314085, 10210914536395617961, 6515368615710817299, 17001040330117317563, 4519581466335837391, 12514298524110577503, 1744739741016504912, 9689951195577973993, 2774540351629210180, 7646006525601223889, 7530479442266342421, 10538917317906671989, 6031253606146099659, 4606167752034374890, 17763804757970320617, 6871166461842469695, 3069238346134678776, 6898492556629873366, 18330913680324098797, 11469514731644700404, 541525751461369940, 18096353837092553451, 16390355202675291281, 11980660197830118439, 15349236833293249382, 1901608480726107605, 10754477505423276549, 1780265741680781169, 6204486525934807168, 2675596223932028138, 1082656654749778403, 15313246555910578407, 16597928615331243076, 9259667019969423039, 13966308744186245944, 3711817850123753976, 10380302371138242940, 1102076039759449071, 1796134829015781040, 8320143967311972799, 12603759772660781109, 9343508021191710450, 11833581848018650785, 5036078561764059265, 14477046704375156568, 17958581882146395247, 6312863763728381603, 5890775652924120757, 3024100139720533291, 15594980805126031556, 9929023026443104564, 6003618257535256748, 10584762467178432077, 8070692469310128137, 3448506857138757663, 12067250229870443464, 8289617863280099780, 7705347156484755083, 8239333463449775936, 12953560490361273923, 7863343728067574413, 15499170354027597711, 16789849673988523596, 193554686279189480, 9324166766841362509, 17865442848307712220, 4017570072096420828, 359910874540192895, 14283136222667718022, 15545842610688758167, 9161703351540143861, 10856046010222875891, 270665191423043189, 15816860058997167317, 10604344774996324885, 3421439666836669232, 15362489920565158049, 901986887674190509, 8102011985696643347, 9831189590417175739, 7694208525827500802, 17761503253302918415, 16843825659097088549, 15968418888658984723, 13213298841864639514, 10768746828601368994, 15843374988242905966, 10372481985078119452, 7145529267057724453, 588445411774656377, 6907651744680403237, 13729433346623178186, 7466282812151723072, 2397976897839660773, 3595288154116844222, 3771046205661211665, 18292138992930644589, 5076094080207419189, 16955129624357257007, 3929215337030354093, 11057894513779502294, 11863471976993485758, 9408615240131003867, 2448439901554368107, 7669176413900589628, 13955883899642443946, 3559761514651432863, 5999853120304570098, 2807928142993089395, 6880972979489023884, 8540438276045396759, 13336393887543928327, 14948024915319356336, 754486632845103448, 16252590658474672770, 11838852632524903679, 16841746824793599992, 4866584459095974245, 13046184814853980498, 8710985684981006226, 2355658489901240093, 17682251256218590491, 12738885399031396318, 3641463259326479601, 11573802402437143897, 4785854649163125380, 17654700608592820265, 7689738254866306083, 3911334929659733907, 3805687817679677472, 3372180752527728873, 12516023017017683246, 6541569134387572029, 14932792460356112158, 274079842264421275, 14741476297422044947, 7640237864595124592, 7990415001403780690, 14485175485850127358, 15701126719940798119, 7497786401585040464, 2046586308065249596, 4234230752844127257, 3490034085431124756, 7410205974894450493, 13594277608316567296, 13163068385450899386, 6911330603633557461, 4165273348787835236, 13196815825235476993, 15409229411685315073, 4238586327560550200, 4274172509763128574, 8233070080684386642, 1152981557203525396, 2258263369774438742, 16860590243592954334, 10642146327347114407, 16394076595581895042, 3547145813374894294, 7303429257652622247, 4599869911214805642, 1470127264048118954, 6553553520469198052, 624221776008514758, 16024993613079197687, 12072685851575104500, 4289561477780298769, 14522030035108027997, 10025959010474970695, 4338629041423254482, 12668451231751642706, 7041673834301289685, 1101300709714299914, 15830324192849592102, 6361267392222383309, 12743724653827284764, 13913765213720067888, 12472686594479717483, 17041667280903689118, 12612588174971368395, 4625038945277105759, 4288983616264520473, 13257170061268337928, 15378358854815534796, 1307879339751355693, 9045256242044980161, 13066137780318064542, 17483698129188252816, 5537781126683250458, 15814088167067959984, 17124111106622331645, 2228813159198082553, 12771677329276373795, 7473600359686104579, 10172401847101693206, 8817322474066906889, 10002046533039894942, 18350636570159627372, 2608194133937884904, 16496103406635747044, 3203166370447920771, 1416097169966651887, 860034031549905008, 15435212006888252138, 4982756044520683355, 14527835149012332766, 15648655845991912781, 15220061209366144565, 10713592116389348982, 11856331444132914701, 13011883287657858557, 18375660967945668491, 7611177834315648116, 11475292136381607303, 12142625427672665818, 1644376245508948388, 14986147846200059747, 10358191212479538383, 2124663276626493099, 15025396046176607689, 7566356641233415240, 3834259550197202335, 7422439917941038432, 14335746041650957139, 11010643115481291768, 16639917992723217687, 3400935192914355446, 6526469202356090658, 2911450085827434145, 2592450403666061908, 6573976403851247795, 4285219873414520276, 15329532146725863869, 6799347789229688901, 6639341479260471078, 5137054100466749121, 5102420602612942914, 12454937665202983967, 12962650067948965377, 17483657740097839287, 12223498331603994543, 14079145217780475833, 3310333423646124225, 8148231670879135605, 9541038636961784750, 11089617618703446533, 3560209342825276058, 2574634823119268479, 2588311243176990131, 15013509191556503430, 15455072885984268053, 13986137485131324765, 5720067926322634989, 320358790111393789, 15410939285136639329, 15697272961739331244, 1355846111750777085, 2546959351276906905, 14534695021313396715, 12100942362109396400, 1909839808518887758, 15057164163203198957, 10816292376571145141, 17932667027515587541, 8894763284691124395, 17376767493810914651, 1054656077023869452, 8186894411081110112, 4918609723063820894, 10472223930221187526, 8210872174259857628, 8260857529094096436, 11707883934354468821, 7798711246011152830, 12313898141945763999, 4092899057830195664, 12768752632246510730, 7011904089799177666, 18269846218072729005, 4472126139715717850, 7263280326862818361, 4617033187864299345, 16062484525314928005, 7764862313171817272, 5507098054488704246, 15417948890339509732, 3199184308759380889, 12873647785813929264, 15851634423390314715, 3379562369756927370, 2914796073219663247, 9453518290639493724, 10389507097848983202, 6987583823829734148, 5644521590882572085, 16385036288302112854, 14202037992186130818, 1662729350231436066, 16086866498209553899, 11668110277201388817, 2581723866463834707, 14466562150912612524, 18444381539786477861, 11792751584642451686, 644172128540161319, 15714856399314491326, 6336413224068482580, 15648040294508822482, 3581892413107868745, 2087860646799841458, 12928312782299116049, 4630539989871908829, 6915603518697601787, 14918733616941773093, 15087665207194981362, 613969264471068110, 3544544803540968193, 5220360717428049381, 3375260723217895506, 16778447987047186697, 11894812810172861433, 14542979312432827779, 13561316753657099179, 1968473618327458185, 5456934299993876358, 7469735400543018284, 7068657239043349097, 9254040800524479410, 5214107275553666760, 5001330682797736624, 17026132790954295091, 10969354337912897232, 869351389198733586, 9574587810937905907, 6923373747285449001, 12719903474522918771, 12250857818862900982, 2153256573644871951, 13709729097688338391, 2899377834668376960, 6841869401787596550, 10339715141881541659, 718655127116157511, 13741406681906111321, 15392288868670671619, 17545786767738322758, 11089794771839702758, 219094231550242583, 9674358307241496741, 4002620491443309348, 8012290324302967070, 8714326673970415123, 12380264119087982419, 11108551912665576265, 3708955946231240253, 11607264285750874901, 4216424611300123940, 8256067698160491644, 7506994298913059376, 11501100133000306066, 7549037119651533111, 5112970978157051505, 13518442004335850902, 7350008695599366666, 9542638447580599221, 2158188779042279647, 1604170908932337076, 6391929341437538244, 10779746559124306734, 12656450449103176181, 10121044395803332310, 11651522650180060700, 16328514328541821784, 10523761782294701174, 1822303728984452144, 7260452386953933551, 12204494523152059466, 17100382786462731446, 12548225060484474439, 11326872465335361323, 5596285187831113760, 5909751003547848587, 992306619579834385, 2228664329259510492, 15196270917670055982, 2131889695890586742, 9819776790840463517, 1473593931814601068, 14939513955417919643, 7685117665289355354, 6724244559482510387, 101460542568704969, 7352190705745517803, 2150669404455836808, 455126870518119052, 11553577781469330615, 10384536636375637150, 14364597940339752635, 2495319672618636831, 8180783418013670444, 3773765470722916252, 10227754258298095569, 4811293038656815364, 2304664986814074602, 2418992918773594204, 6388448639180737685, 6893696275605311774, 13851958766811817366, 4793074330182947851, 4813793152033309122, 1098414269347239038, 11751908186279088029, 15167430159498163699, 10528686090760108130, 17120804521852235295, 5538072916971524268, 18284870874128074659, 224523015148941267, 14496093443691170173, 5490655299006793623, 11584315652765207551, 3229579698633170375, 5527375504543907996, 6239324650299686862, 2232148196848710005, 9031256656667465794, 40023723987633148, 14627741678268078967, 11950626749898431344, 14785414395108523186, 870832948163923646, 13004928204786500706, 11732704426571300600, 907514934656616373, 11587740830029349245, 7583505136677874861, 2623787766244261370, 10256163025245964672, 7257287909572091733, 4812915812660879618, 3468364439026649335, 6604147596013682093, 16816894664989923710, 3964120271755066308, 6086548275463043980, 10447117175471304144, 12856607441078849807, 10592398111690221432, 14269275707379118835, 4396127772639422927, 10489721798852691549, 6681412646421684356, 12490106130106455109, 3624408102113036819, 17246634770535451304, 73750230380742720, 3858795004528971618, 18037249274864620640, 9013680198221453825, 11909298583725721915, 7512555591920604211, 17449244834240874515, 7793591661081767445, 16652407448095073621, 11804971167281860328, 16410605854679152138, 1713343542446776550, 16483548344281970818, 4628627981197409087, 9083762764219706193, 17065951854876058290, 11490185594933330698, 9891012968004512035, 368256788081374064, 470621950908252, 17956316299265730194, 8221822257224301188, 6380872247545425488, 9031471961851140451, 17956391258409007260, 13017604911584754606, 9245778199486992293, 8056793204522970093, 2531655295742236851, 16039488662052065607, 4695551407385442957, 16581782264738209135, 9457268466305801158, 2502271077174158302, 836797013558343943, 1224523470498102285, 374165187087964522, 10212314508075547184, 7669093970332858967, 9176723313583927295, 8839526249801396044, 9460240515540152245, 526138750665184089, 6908994573320912372, 12176043050383940227, 8431292525679019707, 7800865258551716648, 2930208417676545581, 12001139080437682925, 2848294057310329443, 3495763019164815081, 13998099468531902475, 2334207795701343601, 1265352082029868252, 5352951968929077427, 11045950825318827473, 17705541510574119706, 10388016860076689091, 6188336841660552180, 3874842388902329486, 3586889024655840994, 7577730940669490050, 3828324032996703471, 7382564057518691083, 18020764642442034007, 3255848346667024023, 913981917700616307, 6544220161742236189, 628453794376152858, 5273139986123145851, 12804359385937816703, 15490118777013724970, 5004956137979193113, 11537600208633214816, 6041778305931749161, 18021165191120757752, 4439552721639804321, 9445924893904633163, 6333608419766441318, 6265966168082228187, 5090746176805509189, 12079779788101746835, 3405057163683809716, 18176431495575685240, 5416316679824315388, 5666993498240944478, 9396996717121195736, 15077940112899068312, 15769845674133811095, 4172092555141541227, 10535661541737621064, 10760049649331328984, 9044328015087752668, 4208484814661836163, 4524519455413453106, 8416163180819044235, 76133776812564214, 8938397440798861336, 7699462000599225384, 9542247023407697767, 1397476485288102889, 12838783590422826565, 11111769246893411506, 17719085637529819037, 18350048131892648764, 647133208572620551, 3545832683987398107, 17392149180006432089, 4645454948531556636, 4638633830898005179, 15832113029610700219, 12312766094616504216, 11054531676785061901, 12882000175930708962, 17065292675540451547, 7348135285662513163, 10368855461513742486, 17213692472848349009, 5448237816391429929, 17475251701204191843, 12352004908893419844, 4421019229248084817, 5233890583141520327, 15415498665325430242, 8699482400205838797, 11081065321342975843, 13692414560354688711, 2057100631763259620, 1768191442150902149, 12463118341434320148, 14697940362261450576, 7225350934202123472, 9180626944525820669, 14817691250517499688, 9524098384486815580, 4894140555324164954, 2309262794362375113, 8645740617004046828, 16829903653299752341, 4278553392732422821, 16174995535301769275, 7274361875865992211, 5483861345936568593, 16555617280692737205, 2106788877369503099, 6355572984153420404, 15413046204382700864, 15184587830187202860, 17638950466015943646, 10142359495639047596, 2852278080143788489, 14902051473257283997, 12684082230048932446, 5127878269602498356, 1458833335160283623, 18343902965575788886, 15956410439937236477, 10143815431586875695, 8519328419973108156, 9379288137799805556, 11116700304696206296, 3269635235146511468, 7446145908658980471, 8423421258962502269, 2960959498368537205, 8029834119982365442, 12951331847284209016, 13335373530776006943, 2051038411438343086, 14988843915712852160, 11070472159205332532, 2405233098821133668, 12872299485466251244, 4146849588411590424, 8652997027024585292, 9417874732592565535, 2771366489480367357, 16381568131097774387, 1160190173665475303, 12142110843989704382, 17157977103678150822, 12240974252728213375, 8005232037362794911, 62748564819661432, 15562900352067429326, 13819933941831285726, 8700733640462543781, 17417693392111317966, 11195518897113567806, 8656545261572504126, 2665140739762930045, 2523114891549547532, 15947075740878853027, 16617762624958355772, 9189411410511795645, 9417682881040880723, 1220008371097876826, 4473435335583972063, 12416336276688398745, 9439155074539900208, 17599514971068491442, 1382978212068751289, 12012964446858847311, 13059411911626363940, 9000605160655962560, 18444429515577739106, 1678358883660355393, 5074103451266196440, 1108189786283239561, 10612698979413855931, 4989895863474068758, 653620819971957060, 12060263383072344947, 15076531277958824549, 10597595939754188762, 15724450558403473627, 16382650125476798913, 8738893762787150302, 9733212779214420390, 5558001311635500417, 2720376062751869999, 2936217033743496825, 3059230718610361194, 5589670835881847684, 12297086381101763222, 12830838307506907529, 7727866232017902927, 16978583538503170044, 5646531489086592542, 5696883024644775459, 1778382958859079024, 9219341275099378906, 17593963150311257769, 198176573650528594, 10425519151629874209, 13457055667833759545, 17213583299444020650, 14862117423842849302, 16906392281688863338, 4290302946266596427, 13505570400341984024, 2056510386911305907, 11571082458161054292, 7566281435617775832, 10210241606684674096, 10697498687651578080, 4947318501826974509, 5861434792576988890, 9869040491958929661, 5532013052186573089, 12416594018569715230, 10820734898252214278, 8537468997207455166, 439343392893541672, 14734630723072977466, 9898041261033982210, 17393034157801306127, 13758525217758656857, 2713096067589327874, 12442874178280670969, 14498768890161377807, 161967360889456606, 11930601082339405958, 11362787206913160786, 12545070484550723467, 14815095129086834610, 8605787829002095856, 12923597973881209899, 10587151577465292584, 14183134664818382968, 5172374334040473114, 9364926097792520560, 6171919845492918332, 4386231931762251578, 2155663571428617218, 7765511219465701910, 12061535530010910259, 16100330205655290696, 9974384126080194942, 9674175848724908032, 1687977953933677553, 2052842863240418404, 18296704913226861337, 4023434438910601547, 9899743965354682742, 5310198234766113901, 5162456985274720081, 8646509974119784542, 6113717383160009894, 6014191554047499022, 8484348411248636487, 2876047496375093909, 6660788054730924011, 1664197372146636482, 2820993293910648101, 11665512417100144808, 6502457677692154814, 2170150732610996776, 15522116097990839236, 15440086643427998964, 3675113412536301313, 8316358419658521853, 189389437052919038, 6981753429704993440, 12802645856607643857, 7243825699014665843, 12796799374814419834, 8068467907492367066, 16310382387876189712, 1486061732225930791, 382533986053029739, 16359148449656380800, 17246074348224240328, 11700746273206874174, ], &[ 3594586856237428958, 5997824235581423095, 18106945694572591425, 5369777421009534827, 9691872015485910029, 8277223356613193320, 8300414822670435844, 5725520566058443298, 12306974089982798958, 18060317567863429618, 7394823371293544803, 5138546813912625630, 11381762187063629918, 13795891775219840404, 16941170847361878780, 3114101041076250480, 1627441821796544575, 14373434374909899003, 15751823974120672095, 7114844122374964294, 12348870676901510257, 3151173383417682310, 776184657901342694, 7622972041378828791, 5661139589349233199, 18444306068281950084, 16717471472783576773, 2453181864182798762, 13878855636164163574, 2697911612949310053, 11500180712127697310, 623643852696618616, 13977789271289438007, 16089002372294802889, 5700728318869652447, 6942655181316110482, 9295484069162391794, 12555799549023063196, 12437824612510230228, 4067237838638331527, 4042260540157790426, 15358031372213218981, 7375293741308867395, 15371448718880351190, 8424391863249382116, 18197512030851004638, 4697565561992305539, 13311590212527810876, 17503569525573518831, 2367367325069191744, 1326471798779182816, 2280875067412000116, 14549571747015679842, 8045789489671491841, 4497686055416253635, 4010202321388359450, 11363219040443956347, 9612974469743198684, 7690596049793655898, 11690906809673142565, 1370450637740102802, 11687342070217262803, 16093412299942800414, 9997008751721738184, 11754987271691383075, 13819834885151063188, 16845077938435135186, 8911914559373522274, 343887892671262909, 4494892451719462524, 12103980406521808959, 6488834388353468959, 4152486077751296306, 16639967652404039047, 5858398271090603523, 14257817111576896046, 10213327217611696698, 2387098889564047316, 17081070436212715347, 1911079021927109060, 15803126456028273645, 1310809663301800181, 17222305861889876939, 10573069897260961823, 9412558929525252792, 9682369889898408635, 11962049311090563982, 5965079569584605350, 14865733614651514205, 2447981910438979972, 17328967927265824822, 15648469744389136728, 18262394773605934263, 14636605825851807882, 9083797794473945893, 9025739053249539298, 11188290513227823984, 10587217410587380579, 13580707444446986131, 12415686714142468705, 1356990184364231130, 14994095845793627286, 6171876359780280353, 17884842314222278490, 4436207453841323338, 17723367308109227012, 15941907207802500160, 3078577564444952378, 11409457214199360500, 9887901919260789486, 4175383141916761814, 1254666319327392127, 1282221168759331968, 11987113675417120377, 5027561805712958447, 3579051369716154108, 12829602108415654749, 5394026478388836602, 16667874914598892310, 3330196459483415008, 16737702178681428488, 1445510889972879885, 17548042718866769585, 3222268498568736762, 17503995634561733238, 2772145265286633159, 9575234631002014001, 6346834313174322240, 327191781114223341, 4183895557314694544, 16857140696266627351, 18436460138829666667, 7798020615570072016, 12122516145084219004, 12341788428980295562, 10542442298029530954, 8783455073968960735, 14365264653978832010, 9696668385411924921, 1353441155706063556, 12228488114599325384, 3203876433604606847, 16806676632896446483, 8463840989872033198, 15588927437296468624, 4451301342299362366, 18319945996946207766, 13389929674620308820, 13104054207717801481, 10315091670901042550, 16344473241124585953, 10552683838679802859, 5880207654879155934, 18375988906573500273, 10832453134957582131, 4636353071690443111, 4654121661690917078, 3577146264251561815, 12797832477719435241, 10740671490864269215, 15040149558523329308, 7796816016238387863, 9542353300619344166, 11390258959435632952, 2087457610716219502, 10422615268763127393, 13112339405809012053, 8723535168958386014, 10239921146965340278, 6513282921669469325, 3450908699159768885, 18047494649011673198, 10298878480552871924, 4031517553125024915, 14129880200307273385, 13245341565180251740, 142293936665696849, 15100564023304297719, 12129521945437763262, 17006618776295397352, 2359253016977701921, 15372275938288271263, 7030508790783967633, 5981151788826319564, 8623897852847710240, 1290827653422197869, 8990203960900044825, 10962966372027430885, 1990016349334739667, 17697377957496422880, 11049784557063177783, 15397557779693153825, 7163175851305743276, 17977382692150907540, 7938361598612816465, 18312648915972269634, 39898235407970467, 17237577292102821383, 14768770315845268220, 12163275050128474188, 3281298543083649154, 16919047222554278693, 4475656313290072462, 18253843931892737611, 1866825044100640454, 9098280484278986844, 10905592904227149672, 9996855374063860018, 16867360352959165488, 11231826979343065358, 14975578212243777674, 1816159648349497108, 15754341121195873006, 14232605178836670191, 12612606094775533127, 16751615573455906924, 6508871566239411316, 14264419405559865222, 1232093328837969021, 4170583985227962960, 2303330123802005356, 11644297178221861888, 8692410420922916348, 2712993562192444989, 8026831745141520189, 8802307139389858344, 1941809897174066559, 17322010029079648390, 342656065441322286, 9672113720462539930, 10910866529513431242, 4289492423082900396, 11058177478258586748, 1364514196857691678, 7032285894941128959, 12066375748474424358, 15365104738538072299, 11816829927945134731, 397729498625998286, 3741077467460124252, 3877765007757413560, 5477217126381252416, 17665551840782024512, 14957739222760165933, 13737131533183627675, 273054997495525283, 1697327593809047125, 3590262663858049582, 4204421060558050693, 12726801568577723109, 15145359045822981311, 7480634943476006094, 9921671236717343483, 11511245887474917062, 15623196281189992157, 8475118117184247401, 5999059679518067111, 9214567244340364868, 13198873116939014797, 6655215016500908787, 1625660385265393064, 12228308354030327384, 12626179472567594306, 12736031813304319055, 8242816500290963115, 12956122689020642237, 10284362726459938859, 3927314022795636984, 12541703238882675397, 1331111124071806660, 12167414537228645643, 7836312689846302768, 17868735452323208457, 3031578802060773881, 14199956931959656115, 12687814210556209068, 5894567003184644132, 8572760900561098617, 3633198830157294391, 796332493389832666, 2041313463324032959, 8724710971529329269, 955634893021271295, 1684853491026057131, 5435036667387015735, 2295851767890888248, 17797894669834829008, 12146236866491126001, 3437637227298033850, 16766898487486492541, 9367430061730288336, 9028668269324087410, 14500356941199773752, 10638204516750195784, 10052294793853632619, 6140242340805688971, 14340939633164106180, 7596475908553648821, 5804277951065053377, 8985885780654311003, 9702056522849965220, 1110953655051664758, 18084119329270648632, 9692529734296553135, 13741246141721263549, 9860293090921242304, 15262709059312175738, 15050881295633264500, 15102394376219894586, 1187517286918163909, 4600494490457780813, 9949997737543033222, 12548051273588091575, 1251294250005854372, 12514674967656354350, 8209795734416267670, 5621953688199880086, 2625216234966125794, 1816441518826280116, 14745883011138909066, 11529564033952170224, 7915149464909709510, 11092522205731322220, 14000262827040453262, 11500588741410946006, 5464182528201394183, 1347089631519193755, 9394782847346205171, 8301709505992105074, 789343227810667683, 16184737414317269551, 3952607262504811823, 5889460465432404143, 5965100411548663972, 4496487369263481883, 10867267336114414339, 7012299638735890009, 6226091031016319999, 11275972049928859942, 7202533585953054701, 17863262545987604213, 829102422123668526, 9423125806946321138, 3195060302966047690, 209948536736776432, 11345127486138365640, 18062559394584387629, 2142702288780102565, 9848954741666431469, 9785773656402403362, 9317384270775958187, 2617653067849148931, 14133946690353986680, 5772105535189370283, 10595418510466854473, 2906482636756668487, 3018817677365523798, 7447507351909056786, 13526968716904621523, 17092790697122522100, 8641236682859520051, 16502034166142995058, 14955857037584629856, 1007758504466420460, 5851324741621223589, 16596211145178902745, 18186625241699221408, 1267103353578998461, 243071599922609707, 14517210614638912070, 15057372306565561130, 9979838156624188051, 7975133518909054568, 13545925822097273499, 12867658143516063524, 17533881262462511358, 16356670253522979342, 6092369572598992581, 4573028473421447357, 13938304275335513178, 1315263866482735308, 380057684148231406, 3835456480460755042, 1828600490288690572, 11524648692118700936, 7668575675477254961, 4927847007606585681, 7642968749404523824, 7681851777026821870, 4005760681469873112, 8422795643629558920, 5036390889567087433, 1380690399737709501, 7361251140747803201, 9250287313903956089, 9740587600198812657, 14906555012214851177, 12881827769629431561, 17572244782122473499, 18370454099654336853, 17860629679055514004, 3546134039020957530, 7931381106272112944, 11706419130620665789, 3740185226392899084, 12262698676041212700, 17026388295780548288, 13694778344125167325, 3072926588523932274, 3756372223493163520, 2335619280215352683, 17531438597287171576, 4552132324090931463, 3286011129278460598, 807082643964194568, 4666185161440732584, 14542335508110047022, 4748593087952186957, 4012889075062716273, 521589536973278552, 17896788016392525340, 17039689444406542056, 6553554992456494849, 1512896227367613872, 12822921313714807925, 4111454639616903489, 14251706422354285056, 13139747483840995717, 1273069312535292496, 2162114314684424541, 4163850841149348549, 3664043121154853083, 14729191601853260054, 15284744750744306898, 12510768474336929255, 11145273181903059662, 5085653485125305352, 6747370505378000381, 15479121662679221243, 9596872513868588029, 5806144004708237943, 17661913749716657482, 12335340174016639322, 8468074092315538150, 13291538602635559911, 2821204544422246680, 17783435143556609123, 12993990360954000430, 3773276397662491809, 17525402731899178090, 17168762357406194265, 10542489918853487246, 15811159675024564336, 15488196215489418830, 8818235696498333905, 3126553358413855458, 8375860131343651072, 2687150660280108423, 11622270767066056142, 17328049472948882340, 11220911893655381529, 224986233278212797, 6604366207763258982, 10303213229226473460, 6150391194307548313, 1532769822993189093, 15441342515854434751, 8341588131988799593, 8558135921887321205, 17208924441221496201, 7858767700070844969, 16471624916022463650, 7717459047018176330, 10599641480680231262, 15994255185665328355, 12696756615582176715, 14863453143000367171, 13847952559705482124, 13784944020159703430, 11340906950214356755, 11292879710786126405, 16143496660810886411, 16724520942083796554, 8368982799465903051, 2150857094949894324, 8955935246122327128, 18438158648606397729, 12835653824919990872, 11957883793292221645, 6052451328426769733, 1746957330104831742, 2757224925857577697, 17661658240813358336, 3709266717503365759, 14389949788790643304, 11675670476414905296, 15500498798366693199, 8258104249313492616, 764096997356311949, 589951004095337118, 12485552986090158378, 1068031484948243915, 16605740691516699028, 10473029485340063167, 3049351104913923232, 15845731788695586589, 14287046325879279879, 6320073903366051707, 16066709192467332521, 15231205866572467189, 16108188309301277950, 10035490566382353246, 18186672753013695389, 2876707137968900193, 13756992643025211507, 11733973078940380621, 1043890832441880486, 8496204537482976481, 6246303435819606060, 6751199421379153121, 4947488112166675894, 4821550422447014784, 13874443557443817072, 15491151791617785605, 8890963329181817287, 3458374110836980981, 8848682385288002461, 14591433581421428549, 14306147895001110991, 17935563696896336143, 8676844021218567810, 11881349447079652233, 4497976175675682165, 10693808496201580095, 13391168868254925122, 15629435612796015718, 15922689757186949286, 3412029294328545342, 701052949043722294, 2423314665570871346, 4353513413515515775, 18166762391978185574, 9186156162309331881, 1268279649890100625, 4308217856415291067, 12173857132780712488, 18144886979589922015, 16243378756945549068, 13507249524703516854, 16831330011876503831, 1994671814775470066, 12796942923946388445, 4529951020994856861, 1714548922942971735, 12371202587820946720, 705076235612627678, 18205142645136588080, 13596626625484305353, 9972137708933558834, 16743495633512909, 1997864468110042410, 3645819153758869891, 1635150662123830519, 18255329060805359785, 9623833873270912396, 6707206270726414923, 115178768724123514, 9107180622069529336, 5779697096131347405, 6562577309923052469, 16399518123999752109, 12767521663616393182, 3437327565019673630, 636692249439777277, 5913139906815072528, 7033361214831924363, 3734621293407093089, 10070285767840610976, 643318167867702369, 16179749096376018639, 17943149477486904936, 4337354385379270895, 9324323254182908698, 9430256495080031743, 6610492419629128562, 14310625820190029921, 17178454846869464054, 9747133334416100079, 13896799715381654411, 5925123084043322916, 17541914329530815758, 7522533365357126514, 8783646848572998744, 14124286620728075053, 11584012692380832279, 12964323900711387940, 9014571252110133244, 4291912469528547260, 6995910770375595064, 15225286416316441630, 11856347119730041734, 18352892908708908239, 8986410291078412150, 16224902571115364893, 4995793911920860524, 10582495465487609975, 7219473912244254743, 6105825861348916268, 3031788142624263331, 2405120948753921386, 3388158164171415180, 15569752261469238728, 11865711447329483913, 17596961426365956296, 15751473638139106576, 11834338523813355103, 13955575815298784847, 16300180716626739956, 10129809968419608061, 14618424154534525058, 5865323586443341580, 9536853263477083912, 17331617928467723487, 2507541630984584427, 11810566947361745765, 4088556367114834748, 14927557845434061919, 3531659285508871954, 990032578264635138, 3080790007096957728, 16774711611413763702, 17277430241980248523, 18159548027432263984, 4006322693443146518, 7180053478882046712, 4240829398198232701, 16769511613034925015, 15868464444235003264, 10658884407927468064, 9589753730320791995, 13702671134001044499, 12013501078802924056, 14238660455565587789, 2508715080067956581, 5780940886051583044, 5443409745788847011, 7087326994450046144, 6502079163893407796, 8465058330099867354, 12329363930722540361, 2269752097155035673, 2473179708552781752, 17813411053932910307, 16718849503997955009, 10311907893650909603, 11711060061729778846, 6202000401339614885, 3175344880215722164, 17102839007824360668, 6084952160688038415, 17055890059971299514, 11459717661872795857, 15376852828128412609, 13588795185785649570, 10811729059202241157, 2519756038449154050, 11772434372968017926, 17918830988326226715, 13640825138017500589, 3616123121466473500, 9468167612990666976, 4316969512187481955, 1290629479158951458, 16455502329838682258, 1393000865873261712, 11125215634614933537, 5192310971032689984, 13233724647142845976, 12952476789215665369, 15899648440834464417, 4269253090160480011, 6973988417787048080, 12333953403131658858, 10726127211359008958, 14591247367332788547, 380641304012439491, 7498776422064942305, 13885928008449988518, 1467814545179490761, 1860370982665971777, 470045086002328260, 6181958881837577979, 15419457425464630845, 14798662432051819245, 11251583330874690989, 22384040680022034, 10150888362324542926, 3760439535169014583, 1602991507463397082, 7459085908332152360, 10605327307673329635, 15917898735677308173, 8343322342584750559, 5393553119991558102, 1290398580225413157, 2838851791633617924, 6337842314760282180, 13081835650479907029, 18255270689222102761, 5678712167855221687, 12541328464692110959, 14559909979575628692, 5734353279371918564, 12436917190356078564, 10579543055668860017, 17337964340272444620, 17657301701865541311, 7908664268390946834, 8862641381140028009, 4974749065227820364, 4337141413352332575, 8199120275579213476, 12891202443273262660, 2231773361773555021, 13035819132778862135, 2254546336903660762, 15884370260923032144, 12247481155770539743, 14424361930230669374, 13563593156228061299, 8781543351600786157, 393240631721848409, 16796624926836825378, 16477666032336065319, 14883422530366228333, 1915530027608907935, 5868846719035039746, 12587791606048318066, 8723399038462045079, 346740222600932583, 14828068206708180956, 10977283960077369593, 12847694693977292546, 16056726334641439095, 15594259272644602416, 10118349040635649900, 12741230853182662390, 778622439867435462, 17514270972681376560, 16971854740961521018, 14118650456693216183, 5046965006942474027, 16614897108688462037, 7340138226120218912, 14527773120548425866, 15646352228941852973, 4302426896604984169, 16784052455801005321, 15921844867285253784, 2381478634388948068, 4470300649945796067, 5479197665701535286, 12776981959611628366, 2319879365110208663, 17856444665198974031, 10746217064232488945, 4315227157765058572, 9898070875314793964, 15229043488147304556, 10381942274045522381, 13512202749827418899, 3763587155861562300, 7620809723570809390, 2526243279162956104, 1465872318491853187, 163352369311588190, 5468294321100649081, 7104806806817952024, 14063132590628866011, 1707301373088073668, 15246878701953806777, 5159707047607769848, 11769340238034172709, 1430874020413856642, 7388615858502655185, 9923975911358924921, 13315267657543568416, 10792641201388628130, 14048832996048194815, 14474171538894906602, 9267693476225801285, 2166605442077617520, 9678297978343640745, 6961373802827361366, 16194647787487880440, 1992823145284553818, 13555598311149681377, 5055968556909288675, 3965798133217150763, 6133510486411807656, 6314071801668480472, 16826390388722280257, 9925190747598025431, 16711420950523223090, 6226330251492191145, 4109937645127578403, 12444630715323326673, 6847234274170061977, 16186450916082564829, 10654826735664227808, 11534265071422990323, 17734451515035863233, 6451694540470755002, 7404688784264462072, 1844661270910640233, 4876341683982415291, 4621995404496263504, 15852427353416125199, 14340224393479650811, 863610120069989202, 4751334033539172809, 2980159108692947478, 15411410315907827734, 173168597281837854, 16032690352854550631, 16378768553918775022, 13737092227419742025, 11762934705688982692, 7938503345444696565, 8435418179073387725, 11712985912566689058, 16004386961795471387, 2962358855338280974, 13259543794369478103, 6353427702673058383, 7085772493310959859, 3588364186986115552, 17915845125226305763, 9808251701390486828, 2158142165912850942, 4691348075235986465, 8053891876321060263, 1701595525057119500, 8245755748230064557, 8613492467772362763, 13675149462262611397, 10509064953231417547, 9646349997577567853, 14545533711220311875, 13021446960830862200, 794927318570186488, 542833742837941003, 5063693132805983501, 14684878417631512070, 5114822238580567625, 8273364330389654264, 3571857504693143628, 799239708861260901, 6273313022460270078, 9518525634488459248, 13571489290801311273, 15752141778029048657, 7291402494164012460, 4290469266006480900, 6554507066785644516, 2959997759427662836, 10541592608900391159, 4293139875450935136, 5525397732806767970, 7898908356659466050, 12509781753727155943, 3405800083118177733, 17728371249128642252, 3947127960407548200, 10092113439899026978, 9328040765672854917, 1248332462096323315, 10603315719765713608, 8205950523916923730, 2296370110105587862, 18038211446840649899, 2071027033926644952, 2611716943963267584, 565426880963215684, 12082798431989647818, 1262807306541300883, 15357984945904141115, 13582028649501060893, 18161107447184229572, 14454134435524387052, 5552991415567030103, 3123389384775661664, 16206147663947982662, 3947731318667216443, 11593347455162248920, 18415263555421379096, 6340683777373226440, 10266965750546344944, 11542931066524989244, 13352235220023597245, 13043895623791507632, 14986530571343407676, 11639651500495701895, 6444695200791802651, 12640532142813710882, 7911807904924532124, 10719275786098695360, 12483421480373657656, 3778288462364007034, 5651386731486987155, 4477484045499644604, 14045624179073493961, 16656727073144501697, 4169610857150766018, 4456317538389096551, 16209680505815783326, 10063139284800726283, 11765236618067514557, 11803908282525267169, 6938903930594536075, 10810073822459096647, 302871153039929433, 18326501470477070216, 11817798423225837847, 17502172116387562424, 4133457004641928583, 4148986140630370278, 10188415158928654989, 17379180441624469170, 7259204778614767039, 16646751529258875918, 11647482332259019910, 8619186828439261930, 8490981817732827712, 10369422717234637195, 2892527542280695470, 17425318346121195814, 10828145750999096351, 7078995839941276570, 213352343672063316, 15094639946644127831, 12607985439395566916, 5955916733332521986, 8579933433192887946, 7871442941120869085, 11554632074995494135, 11652936450602906436, 11007984151853848873, 1041761267322399780, 6144819907763081643, 149612314949206299, 7474008064792379770, 5334042690241861180, 9085572098291138687, 16106658597496927280, 10622412062145819612, 15221216499725086492, 6713674554418687336, 8919398431941295272, 1259305198131407767, 4125305034269587099, 11292723729687104587, 17550520272904869926, 14300285663118054122, 17651649700385538325, 6515515389639875255, 5998975387477999392, 4979569443689280403, 720170541160814491, 14252726231900434814, 151009130836684142, 5985542076789010191, 5480528376021282440, 16074646089168847472, 8744642307435880660, 14992623685451277867, 7322978655333382474, 9459133969841668298, 11616558612523121938, 15237288627981848441, 12340283711300227220, 4307385426083957835, 5060287555018892180, 10025087470765614277, 14171329543463245476, 7492526979752985447, 6346616424925159985, 6141223327769225159, 17247946171138841556, 6261404185163537151, 5023163377322105313, 16254767204788026306, 2828324189558285147, 13506099055854015775, 5346000241174155935, 15287345424248447504, 810002714789219825, 2135544417484474120, 16141045060472012127, 15566657453202917165, 6838050207450986724, 13707280726755471796, 12825372709716849409, 1151801150079586709, 11706356117928581631, 17737810825329609628, 5892064243059884309, 5994591573500892658, 240598676092243371, 14621152024470867517, 7638751021408304543, 3188469996351498175, 15093187474130017739, 8102143523845853067, 7226177729464461341, 8765920226853376093, 17241792527728310878, 11089343816812804469, 13289800619211752263, 9577227935668680360, 9196502297120503559, 11910897679656003185, 12482528177605398384, 11727271477018247784, 12907509334852191408, 8117063924304605269, 17988853154120124135, 412009925290001119, 17562369799410911811, 18077585798078666358, 5187081341925388214, 10050438195489331613, 15887294460579717822, 13146778271460113079, 10954434742696832355, 15714296124420481265, 4919364231403856909, 8799773700844205148, 8772661678971369936, 1511002248336701195, 8677060651418759379, 12053102151285350380, 4291428539944984036, 16248193550878652744, 3824637663415011217, 18225446007255047962, 13248770985631889130, 1762023222033963816, 3596805537342084941, 3815595957794072272, 14221867433187923369, 5047749264671185377, 18318162823063931218, 18043061991589279569, 13988989248662657339, 6282390326345347911, 17920705910930099359, 2847517881043829272, 18414344723509685565, 8464555818524253131, 4696858676453751023, 1984951604633238437, 17261635602989789255, 5596537801149349046, 4616202707945507437, 10212991105412466196, 17007993587029315970, 5827974697795686227, 6175870734113731440, 3567413808879435622, 14988330267451940337, 13736819085881144174, 6544430186937532784, 1333896442106016567, 17651538382929345912, 7645895762930408229, 16335539228424437965, 14762126228238041817, 17638681736142153574, 4801147597457504427, 2593572506126770503, 10777851773729995812, 7597035761959927357, 2894959229604383104, 17813862374126875493, 1667537312990079705, 2111094049852968706, 5512916913740522055, 2313024390417876380, 10374076149445622481, 1070924077269143897, 14272486039721259695, 4852057081224622449, 15871762249192081445, 515235442010765235, 16114206216424388585, 8245890551024474044, 16257218411161590232, 13950049707316054488, 18086082736991085709, 11521768039421816004, 16278766730067268905, 445021635202226342, 16534369824738425273, 853000201976490163, 3341635576142727743, 7507169208341537913, 11735547653623757373, 1187806331431749552, 4421038865123494484, 11056722462547624612, 13754650479612351630, 326222490866134332, 9188864979197147317, 2271946967571040075, 11674821381118154464, 1202775853353787798, 1799855237671823946, 11759565113802254057, 14891253643598468643, 5798627104869023436, 5422824534737725532, 2338362469987961961, 1765062885694374272, 5541710212221099404, 2421202716764084844, 8798140732950326206, 8077790960191128699, 3130257835322872201, 18095796129387652899, 10567043499984600112, 10565948662089842632, 4081434024917174309, 5620143047638028243, 8287199545790302891, 4590832326473224620, 1377872673376488959, 4616051169850979198, 11918102346407772457, 13797555928826955336, 5629375614052972666, 793764946850555548, 298593192495296597, 13643998402531755926, 4612390137906915583, 11473709230976143742, 11340806663028478976, 15979335277407525286, 3382976563275445295, 2992061340144632629, 3005044936437934847, 11499151483727989417, 15253336153928196413, 6291119148276832279, 13516340268274482521, 867708850716575053, 3398142748022933862, 6641053332830210386, 10401620377568476448, 15151139781527318024, 14109502641600673815, 15920595307494001474, 17321718006665648826, 10716082197892102029, 12054728641069632745, 16853165359732652897, 518996277787655763, 18102063294376743672, 3205036357911683862, 9432302472718874342, 13940253316796739130, 15902396957939556327, 12804434055641637086, 10900852703214093959, 6214839016355089314, 3421088351131279364, 13618608303059802359, 8587843003643177485, 13521718276206728450, 18263060908440747350, 5800331361655879155, 7530113700895940506, 13202874917918172882, 14616800240220645356, 5937559843823118902, 12091459054144934373, 10953801563518715863, 16849143362645073351, 6348588031927972798, 12184557995395680386, 17164648569628470093, 173236179981584650, 7739020618507749879, 2407025576603197656, 13619101571430203391, 17179931218690131705, 9285980237565185530, 442047070740903416, 8962603603234817570, 16584548588877119739, 4705022601549530771, 14016313032441334336, 7361079649571850282, 6069184397159611582, 7597198683333267789, 10136712733185102462, 12822423667571059281, 17125882173994320255, 15561492369338179806, 14928805692743950120, 9544191551141455841, 17809625259400830487, 9055445008280062840, 8020117400928630492, 17227722487996339155, 14601418607249783001, 10119058804993586012, 2013497430499002421, 5870521083008018311, 12872127376995267701, 14779433437438001136, 4257318763082705976, 9800931713728889471, 15672805070193657710, 9824998734373167483, 6515096257980305885, 3114082402068450018, 10432755919204823459, 11161904653460844874, 12367548341480903432, 312804941917152200, 10283873964481346287, 1595588969824113471, 6338911369456871430, 3907406277527440756, 9470219563379708408, 15503137061970659225, 7861636390602048222, 16963596896930915939, 7155843803996585638, 515206483478520636, 4620661362482811196, 17984676933167854430, 11746565393808560013, 3663079656320759032, 8459316298636378799, 15380228333692207982, 15674029362437449957, 3058615386053614424, 13272588032975448845, 9253010992972022192, 8648821998170886822, 8496039742746984095, 14262429223710979566, 7358593643192027253, 12029817394250979484, 15060112505401150146, 9540213806836470710, 10737868983367426066, 5354054353160215187, 12167002774907503613, 17269779296322432918, 10488023097382373776, 2076518077268332220, 14627512845597448866, 8547196352174154905, 16202146535871021890, 16199548520701244171, 12672232170111243275, 16024981077313047843, 18425865771930531631, 2129910576502695957, 4520831484431084718, 17698215720270168730, 13625145001218408941, 3060708793266990343, 6902137911719822574, 4036189651081679589, 1364700933898836504, 18317596547376101706, 4465819716720437370, 15502144794460842367, 15678849676752815172, 12626175056053132903, 2236526388064628635, 5773951157772200518, 10433367551848091278, 6345511203913780563, 10016115949949912390, 14489566045759218180, 13632999912860513697, 9400120846257243757, 13879574790471142703, 12729185044957070959, 14837732057410367180, 13707039717518502222, 1478840900618127135, 10022739110683499841, 1085300049627456467, 18374180922241278710, 11113263379188399234, 8323091712777379724, 13303287070971157187, 5881333120165044446, 17289168019467058259, 4352346315266652995, 17048693622617070380, 5375643740896152681, 9463410116162395728, 14011802387533450941, 10506922322301476703, 736147119424806357, 14651443393187204200, 1789716011004515699, 8674068176625995831, 3772548884634554298, 6066809733699760288, 11996643895572412701, 3016035580260393227, 10359734755057395853, 3231360485259740561, 17058419130624653472, 12054301342150639560, 13557887442572034462, 6676378795274656629, 2991764245307954263, 14422737049355291769, 6507074200071143464, 9304450117720665205, 12937792283375351751, 4775291188892116651, 1657417881602428230, 14592588804217603885, 198641122402313775, 3245497468996556524, 2063807586650747380, 17774289269818686966, 15890942843939161311, 17896677076611253034, 7061659020774534947, 7052051283994487161, 8522986888590503052, 16164950784047439642, 15722471590245455645, 16476792238440758290, 7845398727452302385, 4606767613531400490, 3218993439303046183, 5981268411278581823, 2528820699401079272, 9096015514839751191, 6703189116584251534, 10440925736738406514, 7471586021720190903, 17294475123240260528, 1924391209889224849, 15188568825067354262, 8621275628870940189, 14644155652527688733, 3951408744713347457, 17770124769997486609, 13868539020022671551, 15638629279267568113, 11477921878735325863, 9472653318249633758, 14202532955164809363, 16535370727896415875, 7445288758268536500, 7068987396572544597, 8418420489883878791, 13154621189702387861, 15107007450863487474, 16134034636689135373, 12145189861174644341, 2763729420009574112, 2342224067876049929, 1574861857553854847, 5112464449359771791, 10220900379209507413, 6662200590815208051, 8683215886726112491, 17021644651395693066, 1703318512048449293, 4792432496729301234, 10822433316732821935, 16857401887549809525, 1302676010472583420, 15469088288489132609, 6987791491465850850, 8020922250916291337, 8723383673396825916, 209618812168005306, 863147691780840243, 2261258140547481604, 4523264281944194003, 6617004151646627262, 16180601329864141854, 6966082563709973037, 10421816014728281630, 101123035978874833, 17063499646415794027, 10816933943603385680, 14311803210157127664, 16808963640231641404, 16429284467284647587, 10745599117685253791, 13995686705297457818, 13836110408967038001, 7060054210253257697, 6186854614027150736, 10893888996790358870, 4329193319031075500, 832514682419239753, 2762200648842524701, 14810831243892005398, 110871285919222530, 14550177899034441091, 2185578722876905899, 5537084333607722134, 4078093767296457414, 6103925737887687077, 8325329972961379893, 16271339898152868935, 1138347867297980412, 114138619972231576, 5740428581193693489, 693613775886515198, 8029436153456249652, 3344308355696312922, 4541242366340473938, 7528482809825011820, 4152133086009434785, 9315015619955905031, 15104363855493496419, 2594468929320270321, 5109083866657386901, 16374897994774124344, 16083959732406743242, 5090837124606889332, 3258608291626164581, 1629588549235601846, 1616635562542911906, 9231707360684534688, 10952413647773186158, 17868542504461850613, 9925468414044638566, 13854424759141049298, 17034570371808369993, 12297537197377405600, 13939041732952801729, 3380964897248364951, 14563077242064122168, 10657389386018033192, 2886754279183664086, 16642890180982646692, 861273068365160052, 1758020898997212990, 15613846049063666752, 18308267712772765967, 17739201502006020362, 1784151606563307696, 7300607175097014470, 16341738772418413744, 15971459354868364456, 11165614502213695374, 6587728139169672539, 1786277632003808713, 13171307029307411510, 327546644505871659, 7614925720580811111, 6326435263563299482, 15953442436210332366, 8456480261206292733, 8590510172717967165, 838937024086432351, 1856061773879855233, 4069964491639101834, 327493480584993142, 7520829108532062641, 1614967126926521014, 11307463881054155232, 17864587100878517255, 15763537575896112956, 4578262687539382027, 8502225719669465976, 16179696620016923315, 9758472315944533714, 16779725203968381226, 6183875480666892950, 2608493615086467, 17180723153980641883, 3456686138572211050, 7884527685732508700, 14241925547686939705, 13058647316908264970, 6875784030440641084, 8933325337294393084, 12422630052702391657, 10079614668510617802, 10573331982193065383, 7650262932518899908, 17128707710941830916, 10870510854800752099, 17773491963246260474, 806524961307578658, 6842764457708128243, 3445079159386238232, 16483764513234069067, 10653084184989938490, 5903700814029759409, 6828901479408398563, 11912063888633218185, 10913388972688885642, 11885744739002746708, 9257195893081201223, 5930681678077971137, 11806521592186912965, 2630575534018589484, 18026378680378255914, 17084784948241081538, 17326896384453274331, 1866099945567656014, 9550282146391637756, 2463074436852589087, 11585733093552042453, 13174738554743021931, 15035950777112630117, 5558081283202249541, 11689273974223163681, 14741840413427477553, 3416816424414858607, 6766458899003324603, 12410952811502392413, 16409582904445478163, 12759024403161588303, 5846506096916040331, 6071852583112909104, 820557947487718625, 741480266405970307, 12417187439190974741, 13229163230117065775, 4530194262024109565, 8008555870618085417, 17877305109343366799, 13815905787026003389, 7324640884761711445, 349028049855052879, 16353193971302918640, 22560372595432518, 195820086483372832, 18344647481464459551, 737255555262795096, 12070614125814171566, 8614765570997215695, 17372555543859256439, 6743171019085030464, 8139326738322408600, 4165908420227580373, 18442514040545838968, 16630844454588561050, 9571416190602912452, 4657012508686090594, 3686778704845805223, 15973638309180986685, 11656159185708435932, 13322431680068273959, 1751564542162438659, 3348182923206453013, 13874845053138703302, 13876308253542917552, 17285310216133973117, 4000034777188849113, 8256124542460267806, 16590833794204607204, 7704458184954868301, 12492177596185537078, 6001301052100279356, 11072159473051203657, 6151252917038612200, 7836035158533234234, 11335306549737820717, 19315177086761227, 6171461384626983181, 1822458354600202855, 13099374198983726273, 13408159522301905657, 13851767528819394957, 10181771579192114476, 9415015639283483660, 4263806536662962495, 324848264924658129, 14503209993079817531, 14000340004327513046, 11818582924568900321, 8109110686397620337, 2042190457766210642, 8828110432697935381, 5820418605711370666, 9919829550970909666, 12052488162210869057, 15934869979999273254, 7215348901248890832, 3159330338015572597, 742740348898429240, 5571998578872474833, 16341933651780730964, 8273383098225845565, 3326034376020872344, 7274584357797518106, 14773843215521859474, 16698106264937405391, 14040455717338582024, 16448479196576319861, 17266605361670295779, 2205080422456791959, 9583005632984852594, 10250070524499117272, 6651451781199685657, 6176632022465435688, 8122087199625247517, 4510616174816472548, 8182983669598271561, 118122593711296597, 9934905917233313395, 3039393435969291444, 8120493050432758690, 4058819847716511440, 4599342760755215154, 1480973302998690238, 17828904850143881097, 10593342770857406535, 4478070465435761692, 4682095412797127843, 16898667833473266754, 8748764197976097462, 3185375635683792611, 13120281814172681751, 17914614591764258837, 9484169199088431905, 4807650520903510792, 17575569597016375886, 4712387700771102151, 12219631271326131718, 1624416933083818800, 9746390230010361259, 12061121252780758123, 13191062388618927691, 15449059962369037347, 12895355194704606432, 11847552441436471571, 11344827248575736226, 7292490505767840, 1008341823945074655, 4127364818131211815, 4270946748779871651, 12027658246374555578, 12990486587941873323, 11841755495420779485, 14047350735395451602, 8959489495395244296, 4420034934416652173, 12624150215794407836, 6573790355548719031, 13861586779706223977, 11297305894055413472, 9038105502288863696, 11783474356604103336, 1551845953634669763, 17537406743655251318, 13836420862857190675, 8773267827726588192, 18124754071337566386, 11768358750377725767, 17755389318101260579, 3274283977014019260, 1778416556501527345, 5382190231425722642, 13133414606279361249, 7734093784869764550, 215957712867719475, 2984414766272767856, 8131723947477567286, 4398666896366893320, 206703154206980441, 12326076546363934220, 8160942357092498215, 15924256117279207120, 12939783368798075, 5395310234100182365, 607679949225746410, 5666550719038113256, 17675108580067826210, 15502816799164713523, 7841099702038392534, 15882497369954745148, 9402399706745145695, 953583398505708528, 18445717741487620584, 764024304101902997, 14868487130868498451, 1635358341560953539, 4039563583787687147, 16550238810277498954, 16537486469106960712, 3336346802567132577, 11082627603539096034, 4986362159313854530, 15835824893860140029, 2031897620572139540, 15230511233628159373, 14516214625788235622, 222036853239298635, 8073718635044114045, 8911051883637240099, 8827781801920171670, 12310426504065367326, 14816948656941007537, 2827084462190879353, 13161685568663608198, 10249625892127978099, 3296264739939232247, 7033509689079490421, 9525086171579835607, 6473169618871652018, 5392360298796775732, 14776423049723888629, 13597358828152620725, 16833100318324887296, 11971166522475145732, 11872097206066985694, 8256886017230123355, 10314412535333389753, 16835045724519439495, 4706039712196379299, 5870726373620303435, 14198515533136338940, 2470636378569326935, 11369690958187205818, 11254490024722864067, 15445609396452113187, 12551994365532706504, 7340653992159982335, 8648473678223506625, 4626489449677435768, 7626866618263441143, 5977361104488869811, 11325231017650670468, 24021926143410559, 10518928419015543169, 3128581167201575566, 10845247038876435111, 15367170626696526581, 15590613878930469966, 17686020409985847800, 9351869023028888665, 2223400353718632810, 8445700103445407057, 5743254019080062425, 9641427191996032782, 2880617337710745321, 98705364498162062, 6212426535960692329, 18096049861029213399, 8169816906599295342, 9000616375508345603, 6726042380097823076, 17315167572538836920, 13646571690813788783, 2919528228383142104, 10223074182558417965, 3697230257399535848, 10728558488011771506, 12436437847366171572, 18362374704789353589, 190724538241540940, 14997455344563417220, 731172890970164138, 4964378684833634132, 18060859650136590217, 18045696668597737456, 17653418903394015975, 15544323640715880530, 16994229219390286256, 18205591550040615103, 17734493044884548797, 6296908060462462265, 7283087819126840178, 7426061537866959644, 3191966234323480855, 14129783695999936076, 3360711429774065684, 17866164958845125536, 9861298124909413210, 10580599508841918494, 8282189157119747191, 9197770707447859186, 11694374178492840076, 18368802017288109020, 16394403946675230099, 2141375654291981867, 18161140844771142338, 15126603772139881848, 15048331495212797822, 3995638033918575250, 13169773405085893541, 6025934495808462918, 4572080001196751852, 2783436619758877302, 9024267503032915850, 8025963435130321847, 3640916310708301788, 6840661953417469238, 2749986769734168735, 8348551153246843562, 6913211236889562838, 5360496605723998569, 13618712664935776158, 17575162850298585815, 12169990262268572131, 14119680116784171735, 1796931188281174155, 10578372750642831964, 12810071554500166106, 5459429092645213854, 18226416005848684767, 12263214363209816529, 6391897541120811759, 13788023593478687878, 15185370313399382407, 7852752634323735614, 10680723342128514587, 495733052464175715, 12912465070347673754, 18250665729393432770, 8577020260491948036, 9680999401313764336, 4055511702466531936, 13922829230551608093, 17044580456782760928, 1461920314690075938, 9935774488507853328, 4310590961865401313, 17768854053466349121, 8972728810615767879, 10807101176895750865, 14259912900082333579, 17455570158393905272, 9400361617644197827, 3222585990549980881, 10934919781824967404, 4994963365508091459, 97387422948156243, 2281022370495958783, 14043000925252669887, 1950770421033313531, 14292039006175938578, 17228036599323652443, 16418594962299649300, 9220515969405166671, 13807068206103427496, 5762654027968454005, 9482191002376611836, 3077925584740242035, 8071711316681168024, 2883691495308653922, 13301661594185617316, 9766117548540486903, 8893678796058966564, 1477610205544057259, 9796020550269402643, 10463846413771564798, 3399627051454484744, 7300449297128631354, 6200293739440149096, 17316815833695165145, 279212299313192572, 3190098250649783077, 3555664269010983807, 15309533678245941225, 3261793309629691333, 13037226838231936140, 8453766822110843744, 14669528518699125877, 5825134144024227911, 12297418399180362780, 7770269489755807915, 17888986363036981664, 2931111415852485201, 14639292244087297189, 6847208753088773757, 12089103539757219324, 10126240302424868138, 1796081446544571499, 8199277808225787921, 1594480600886668204, 10641848027714533213, 11484122555645255402, 16973005969540728518, 17196319920931889668, 2709835346052075661, 18084755852456247033, 2132028799062933816, 11248099656748788651, 3078026107054490219, 1287642267969602293, 7327615983552677470, 1900974316027471940, 2465104796974688011, 440465215621247360, 3494821416222993400, 17898838494846832483, 10628897889977925683, 14309314836127630966, 13505109427062926685, 6386142816860188269, 2901784813617829333, 15551975240312695477, 9435122587613303018, 4226649603223681280, 331997962735647934, 10485568742856225265, 14917030094729116730, 2073637171424798316, 915835583737744089, 17383229556085295687, 1461250216293218529, 7068239943500340146, 10288334490641399525, 15208234780964400514, 8475559502294427792, 2926092195198358430, 12656704633781670277, 17070487838667522168, 4403502814416839647, 2376050098451057091, 13199999628005904480, 14120263009554684577, 2468181014903045196, 4273221404238097090, 5154057720219142551, 5027721477518319942, 12609684452417053274, 1922522277320945218, 6436521746874764418, 4093773539251325000, 8706855626187686051, 9846278305273128275, 17417037056110132459, 12263059830781470664, 427676242647324801, 3468283337511895036, 4275816585741453581, 192897459204823952, 13550372326052910187, 133570839986679541, 540585874453202119, 11780659758049122569, 12360323334925415470, 13534100053419999325, 2652713032439489910, 2795629568052283960, 1336633232954655365, 9929395103342768040, 10647541508025671068, 13921459546315253196, 12181239385729053155, 9244592432264107366, 14917953490315439053, 8292023989071301332, 17207435505444165616, 10343948035647838279, 16305270801891202880, 10567341749348113023, 14902153447723505143, 11356931487252822795, 1535255066112284835, 15930640229535365568, 15573560888823279647, 15076975392882629685, 10960578593980276783, 17370096640931089566, 3501405511953164372, 14633610166889715568, 1524313386292624933, 11407257912918611941, 16740555220240538654, 16871144196023049970, 2018800046134001582, 8348490438648921871, 4982085025316319837, 11415043705393855624, 222784703639654682, 3466558331671746969, 12326013777821768371, 3025583346757120511, 5724955292043245917, 18294065676811894744, 2085076369095100979, 4972732150574468481, 1584581915654164553, 15440097755359411249, 6279260627318411655, 10980381824523944119, 14840228887064362306, 166495909003667136, 15457192490388086685, 17222407220359250689, 12843576496752906544, 7560072307906075608, 16259381729801863869, 12189888379620317078, 5782443157660099818, 1736348385658973348, 8546351327576605005, 10456802501541553424, 3192223036731401522, 13106139199515235143, 15411306387434042331, 9970219405739610742, 11520445287416838825, 177854206445398423, 11107078321275218413, 239654546708824773, 1768902774088704837, 5254588776066635495, 5979463581485074905, 5347777749022576815, 6937683941497626074, 10711461148089050119, 8144687895487491189, 3276439454308985400, 9934358778921844165, 9422385106116957775, 15095456547064717516, 5070800636017351412, 6521931756812739700, 3932156166666605130, 6050699959511074652, 17344541664528753954, 2988889255669683201, 9353782714615053491, 5589156711002183436, 6682213996533276248, 15943170238383197905, 14899562877580150641, 6764298931472895517, 16276682584602387751, 12125732792481305307, 17741795378783264776, 15129593569550778017, 6986829961662604333, 9964948114247450317, 8616960908998657824, 384856055964112635, 7974572227450703998, 1092885432563198587, 545805536762933819, 17706486245067983795, 1263973849644445141, 12021885634205650976, 4608166390735539641, 2734796012081282351, 6200604703378756159, 5974505481761285766, 9850928205854570116, 9239207633120526870, 3193081802420914840, 7886722472854682054, 2670751422274014085, 8331709031964299441, 8556867030324218740, 5864602765164463878, 9702767835252903283, 2818119218455916326, 11051813316976151726, 2798361718784864539, 12803891989808651361, 6525684565274580238, 14390328213500260195, 1185542698331478180, 2771467110443644732, 1812331778743510053, 16478172183640173140, 2162862050541547690, 3823461949825666589, 17911219118740261734, 3056316107218167659, 14036209218452819052, 14745942794335524299, 5518564424136376571, 2935575073419114001, 1483009244754615051, 16104489200811397531, 1730333865076822590, 8965484080196217492, 9061681468831583021, 16959687546205760251, 10739598289468131077, 12535622924924225066, 7363619354002287057, 14293421377654448317, 5060439359147843578, 12129527773941979550, 2112230986391195828, 4769804105653663352, 10070457010640222959, 15957265372702119122, 13474265233601984371, 6223229738974064148, 1310635690812010762, 911270365813712259, 15875629933427367379, 17125468695201492944, 4284280976538402366, 3746830346804474068, 12276499488868328766, 8321930370653221471, 9942135371805312885, 10489617323540613662, 18366063404217450865, 10893390470035335263, 10458487667984072095, 16596433155292684319, 8360603581927746599, 6971939394626558508, 4060283887681078391, 15351723438016065412, 11680267245463551920, 5790802096533806773, 10713087820458206775, 11332424792139478655, 17912160512036322815, 5732788143095160128, 194157036885958663, 3706729391433574290, 18104188640582475340, 2780227969681270554, 1601397086848874520, 12428065507807642469, 13780772997162403588, 17069706121483733548, 1665870987398124497, 307096882476461439, 13456064556530600971, 14733632907318555004, 4923387323367659585, 9154104095651762498, 9800443787974033655, 15459794479644588197, 451426040309413854, 2788798329416281365, 12293463599613327106, 17830121799669654935, 10759079676082513720, 65630473606081049, 5096392528063815709, 5346856252299867951, 80155407479215991, 1196433294196930514, 16533172301373380653, 10731233255622272875, 10178436775016758536, 9988031047616269623, 12514938561427851997, 15073963212371245955, 2453302056249682923, 12178237101317908190, 11696016410691479119, 5364207712435662739, 13799039328758617062, 7635951899542908293, 15581988062504838154, 12199296096057685395, 9571716157701330260, 12770833407230845374, 7046359335328802215, 6682409275392804966, 17514350522256500453, 2172379224582021646, 13091288462267965772, 5260878034136529591, 5445248199264341584, 10781829337947177278, 11497567710589338478, 5003880921543975167, 17626281977932980526, 16887485374890873816, 962245908798511322, 5108152989985995665, 3799396524860156187, 18162096808895379340, 11529283547909399639, 6390455738944982802, 9936405535146220224, 18410905191303666268, 15806049958088998276, 6686540065405205814, 14871651081256051438, 1965464759731195941, 12452727450091289729, 2722304580139295067, 7449771214146795823, 11184908118487828423, 14059936441587749863, 4087442731977108274, 6305864056451738754, 10570807037282543326, 319866202550247123, 15676864417883625396, 257981265506291104, 1262875953150419606, 7028205644086142472, 115549004372063886, 13349068651466391379, 3871401499320965508, 8851966218204065575, 5085214474391233098, 17945732365705154249, 15777212209105057513, 5140440907304885371, 18438678204170428777, 16248096869816190655, 3367864749909816871, 3722916700775577873, 9992809420040804866, 8403577374360399236, 17679170457988008390, 13194410331607642562, 16187509812940048427, 5026298175140220386, 4876974840029834684, 12871788850461667764, 7104759827829094479, 9436288244563973239, 3159281221018851642, 9752883085161300217, 16232691476973353350, 6189216786307783578, 6640532398843609593, 14448033262042085168, 3940382498318820890, 10262048882525860904, 10061274065512561499, 18423790370453874819, 18050205654249499458, 6839499987405858276, 9642878486148661075, 14327871474315862149, 13544992232424681908, 11373787680316347001, 14533412760069469807, 441032119858968952, 16002383214623845047, 14218288608791285257, 11106928674889946673, 8570586512119540188, 11634529846030850802, 4995459497476047290, 9490295984153672908, 15468267065499713211, 2989892364601413290, 2581156939788249728, 13724611105556739546, 2102140712261013213, 18120444433685527592, 12940831520428557209, 7164672115808745211, 12966905792848817589, 11773978195497059476, 890352368276286044, 13026135521433759140, 12478244758302866463, 6413389638484948810, 3885955303549003020, 11545296721384143264, 4229509895730985110, 16895351180647205028, 5433434349823096592, 8863810222360116552, 7098452189641277834, 16333877257727727689, 15013037256819216230, 4302560698506558603, 16202520488073319843, 12907881483678831600, 16621305076726276091, 10355314267211608878, 7452413003135799377, 14400166494062685646, 1844590774059759861, 4021099544936514680, 9876925569360801137, 13518909505947029222, 6973061477093797453, 12727661908508644209, 18408844351147807641, 7377726373507399562, 6066950890380320527, 7608982295434371124, 7179905088110251795, 17152549488149335071, 8233463606996434952, 5206624787865188169, 11008399855237240239, 1404478959738544072, 10222437285137279198, 13764842761476361167, 267526775623218909, 14074888593090104209, 11079629091416144703, 9971542278925476006, 8892245231600747204, 11294258223088575084, 2098993585796801554, 2071313165222807226, 2133768860233001961, 14915133693464879855, 1581952331538464319, 9639175840198850752, 4603279036103545771, 397124688914837400, 15508222727364896635, 11625935495747427151, 2747623392460771576, 7890205116581168115, 15886026517658120311, 12212687251218189134, 4479673077377102803, 12554927112669616051, 5630714043829684681, 9034914377094571344, 6438149969690220481, 6244960371398694214, 1052896917557446974, 10567823414630738347, 2892355401008719855, 17414574580084103225, 3893733317450926092, 4731799036816590152, 11430162725623505378, 5515277686190787105, 11234159093341446162, 5305935514397952757, 9493854744231574883, 15824659478003978852, 13748377356768536535, 15270190824826719622, 13911471579150742952, 941469693484857457, 8543583469838768654, 9570355218602367528, 15908271030011892500, 15775504622577685589, 15502440155453094152, 13472074873501854186, 7786488156274856633, 325184390931240459, 391006079612096881, 6488611888067900595, 17119716183319735070, 5722239810452364688, 15570270881885807205, 1187208346653885920, 6495212251536365385, 8885994153346273911, 9244631118417101083, 13319829010425196781, 17498600102170453483, 2606308062729035588, 12140631681722133972, 7423666497758255197, 4909403267534121212, 17291602738067558307, 13883694141147284443, 15775430310693654790, 1365705943610219466, 17555638125582494966, 12523045031729295704, 2392330575426183349, 14112467861828070587, 1030880217600210745, 4385374903004324357, 7395532527566274798, 4295926697583681461, 15824788647062302529, 12658431479636413054, 7298062229900514919, 16762658064265907647, 3614060328089930704, 1965221455109127938, 4537598493017046373, 11871860809507888384, 4907011922598075617, 4907239727404512330, 11737261078675068763, 6960397578813780713, 3287532194305208859, 16242004798434108216, 5355636867689031522, 198206763030220413, 12314787670525495844, 2597610581767828313, 912155910938669031, 5621874863922518809, 17621042986327515098, 6509935032915649610, 12034984039300936360, 2432672903988649889, 16938359086817358514, 13683276641443682344, 9789874815574933787, 5073084314220813473, 1320947981283979966, 17394333226431571790, 9065574734268429766, 7547029374160057813, 15702678031816921355, 17830114942365551555, 17586226390965307450, 8689045925427717290, 13674100805654651310, 14947272468697895793, 1536415037143716596, 900913689058556593, 3760203057221746680, 15534161016973117105, 1882158767141436539, 9962312604984275976, 8663719069302836304, 14448629851288213661, 11178083838591395463, 5074408974555005944, 10002377000305244941, 2950452703859403170, 8778821961607207068, 9599108141368609734, 13727328471806688988, 8463951250490880363, 4985262606975468843, 14509435574055577477, 2251537913677065242, 10838249382772174175, 1886092796840457263, 17613611691827851266, 8675160855459284527, 14495552730962688498, 981068889151431304, 14833582687603804101, 16034396285021871754, 3289585821311065992, 229916794190431942, 6158096718005366984, 15892365411025682258, 16012104260833699937, 7229050832450090139, 2375455030577448526, 18332502145755936854, 8113592353194015904, 12102179397583890885, 6146882145645781232, 12871796063368466806, 9689896919156456048, 14832308820056147126, 14224603261131126315, 10728994166622935095, 15844504707021590914, 3148463731124076169, 2191614241121958650, 3930394497432164211, 14975570445035451094, 6175957568623475979, 13457827038927582204, 6569550482770305651, 7910721054828235868, 5396757648809577484, 12425946269835609615, 13080000545390338873, 2228497309022463045, 1000793072110534276, 339755678733494105, 7675452834746366033, 13597453887369667370, 4743316555026734805, 8000798391810099453, 4236658960114346261, 4314995954098326729, 3378109784202067494, 738889711516394796, 18249502043229708967, 13638135114617560728, 7407906194322093125, 9677124450328656632, 5239160397780299008, 4951998289937269566, 5582475260866563152, 4943398101196515933, 14092315760820484720, 13498356481480779062, 2477405837259253676, 2982053805267631149, 5613277799593112895, 3872536722336143530, 14313275147580522478, 14098081093274007449, 9245627422179538192, 12713948618824123036, 3663098222106707616, 16833593522902690993, 9200636416412258830, 2943605946405441891, 531743763255619302, 17390753300460096085, 2824093762754005683, 9353749113650326235, 17521094940135854001, 9905656590497951128, 320439950481807664, 8408113336526795788, 17685823149692305464, 12450049056842881140, 17390416669425632857, 1504913544165201790, 10449491162901619745, 8772252083370989187, 14728900004814406794, 16291675511356570691, 16619460908565992108, 13188318675119868117, 3193278148390763985, 10499359052762173622, 14791030350259837161, 13388837175628846034, 2481027855558432974, 5101481046077782932, 14962852444038402778, 13800116268058936257, 4209800634572843335, 10873765289322019141, 1283737927472492064, 6693974210682179363, 3926941883152776947, 14425372513689620175, 5059676940855286392, 18024474835648567947, 6651263573794035122, 13938725133484148737, 17549714769345186933, 5447384381239220446, 10651750950824041822, 305544616118117333, 14065593823540675662, 14976453164111946509, 4540050816321398688, 5451505567317419192, 2316208300786426665, 8310776038629040900, 16208971995495558244, 13551785652790880950, 1449640464272106217, 12544857006610783141, 10144884639080693658, 10059099142245117548, 10523915445981994172, 10876835489035635204, 2968860783309380797, 5016151962821162573, 17935393084803559776, 11158849805035424490, 9018915535973487771, 4357127364458044907, 10097519122235494012, 17863724194881168069, 8249387391663480731, 17194137921140035540, 4565175158332004125, 14196633677254426720, 12711637975982192334, 1808846428077990103, 7220474391737006935, 6984910202113287757, 8668719005115949313, 15689332789493403404, 11256157016049092832, 16752089932600169557, 2976791285708292128, 8709736126011521271, 11904675423100207085, 16364980313730775588, 10856165918087528208, 4982665602671848433, 6941618699135128169, 12852532311018706484, 14764579611477773304, 2680106450342504094, 2638046584561806901, 2594041699562272096, 2830485688608983066, 12140745904697927112, 14457013334763286122, 14405891806907201412, 16737034769744161242, 6600192696191266517, 8700425283962262097, 18346405359930526606, 8491388585134861252, 17484443895627327293, 6437654615718885147, 15991528328390185419, 578665836842411959, 12826411398220057302, 16935304019869439869, 161325410229363246, 15656104915507544477, 5195403881958848260, 8066669430631501373, 3422823046399351289, 9842336929164283364, 14025201114079171450, 6383160327527294474, 9304888540999769418, 14823032853534026080, 16142342107979604987, 8684662129668287901, 17237002878422481510, 1268377522566088747, 2727385801453676653, 458981449659087882, 15555517854587152653, 11733606025323073847, 14555600935550669653, 14737823349360352373, 6059539353329428657, 11478286028886927504, 3886949283607812930, 345824557705046004, 2158851091870555662, 11495933931583933350, 8794457607221170216, 5458340265128732576, 2872964225108859294, 3279822755074032388, 2257159391808810540, 11307352514621811375, 8781774397128929722, 8461654994159402867, 13470239546503549381, 12451839385253051360, 13649919205807350692, 12307759654667195662, 6121462529213153103, 3178361975991080567, 14969619058896452804, 6543743675636390116, 2570068118140327141, 13782677705633311464, 15539361910618929218, 815767500851296252, 16343440944270931513, 13869851574220153798, 7979967566517823577, 1079617792028207654, 17059495379547625159, 3394944722544524901, 146658049450392036, 920710892733750179, 18267466400597724081, 12840104746512458153, 308895484061420208, 3973848977921678681, 2682725058127533019, 5268781362212396412, 0, ], &[ 12622393184452988185, 6576838566809301648, 5775205735049728716, 8287278668518156534, 12192798229753293112, 13075940713888694545, 12454048030060066070, 811912065849436865, 14514498508890956207, 3718975340013031462, 5748599663081118833, 7103827618714489700, 1300608812711622052, 6273491418082608362, 10602503410062294488, 3181236738912952810, 11220558709822910991, 1757050625501318151, 13622421981172568598, 12832273400791276781, 5855047466166966026, 8265514107974512007, 4674109636920327418, 15064411300962651052, 10245194862302150019, 14697255588820327266, 15300902461722524376, 4133685444341227543, 10059303764976223858, 12025228906916712453, 3342699448606724702, 4043427178402639607, 8354440664524965265, 14685529799335576021, 1998565942493742826, 424458568212209524, 17175147416410219809, 8429313419702361615, 13100329766043560847, 16630087004934016029, 1975643079807205422, 14257249811747812832, 16201214544277583293, 10834834555324096005, 12974966771898232184, 10175033989408956356, 13198699716510876245, 12667628170354632487, 13500517333069730437, 16670408922706885903, 16358625308423139600, 3004604642549199974, 15303830789363557104, 8922231358023374966, 5889284410855917356, 14457653243881523958, 1394588608017240060, 15159743360841977286, 16367826019458727864, 13291054711118709892, 5739609590986339029, 16727185121517285485, 5857477526908140920, 7564539623883188584, 15028512432506130151, 9451165299139733038, 7720569164934553601, 12250119607377112932, 13838627703516838495, 4013168924318862931, 15619946084866502269, 4850331740702252734, 4489013954543776517, 10588792414395604443, 3902488335149478186, 5227683403359005885, 7076009259772820031, 8343084757976224303, 5177402640814818565, 2803445024434417300, 4085994593957453089, 17829839529352422672, 3578735210913423849, 2792806554222369562, 15534236200548977629, 3124727634409390443, 1084234245147417462, 1598571627717804884, 752329673301761003, 12688955135473243162, 3217100306345888294, 14566509229614296336, 11270786911681876633, 6662721337309084196, 12158803014774283480, 8518459513237421390, 5910661800660978266, 744628824726848011, 5469395445007916291, 17702754906843708743, 7968296670638284359, 7510310566936008628, 1793306228498108099, 6353661129197447108, 3126760188195263395, 18414397606186055674, 17486033377523869654, 12070987014285382902, 9991875370105670503, 16129470720148507308, 1039596679504335478, 12158960746785703045, 14081886766117011421, 8985649855006063812, 16817043795641114882, 3052278422002310841, 11364643265564647695, 5842131153676887611, 17671187237412914007, 8666277097534907268, 1983817527033510933, 3541460822071490249, 6007905868789893806, 652610536509913563, 11037032573713184751, 11009156643744878354, 17591018917017615621, 11710867183921879437, 12251167927128949787, 8974964125845019147, 16969705468711169632, 677161721939989175, 1648428070692386013, 17084411431327447982, 16079687398141624486, 2070436743667033809, 2763689681570019260, 5133447300857161972, 15255425835157483742, 5966697992253286903, 361687726752744332, 422697286210467434, 7041898431113518823, 13795043150550399420, 583755960417947241, 2875531821527607804, 4394534528084370577, 12535851821369757920, 7213044591651422167, 1000544905146371455, 4653559762494073142, 7779502532203369012, 16702927718605692181, 12982197318021037408, 11786209078045506353, 15564445991051693791, 168023569501370168, 14266568007896652015, 5832135998445910960, 5245116375679737807, 13311176288056325459, 3321928379396402727, 2233377424088736972, 16828319963915513015, 9909739734979137218, 9397081158643758651, 16237610644843443174, 12049861989729092874, 963173337050875289, 1393288980328672002, 8369734762526854678, 10087190917060030061, 16611332898402499111, 17383970934682687319, 1806005829620081904, 2572338165105796552, 12096685872124824149, 10625877836202904943, 3565777311969108583, 2012783419915002762, 9017825065020723376, 16320469478354954310, 11806049513756650829, 7727243155747891778, 15158785566684134320, 2456938594466970469, 7873271366166028790, 7686875950801483839, 5617367656140550179, 13464612212949386527, 14757590544232715739, 11128260848489879698, 17626653494839808091, 4716501168031180893, 564851231412074685, 8132887702611477369, 17552681344611428819, 3132957846371517857, 11213590168035816092, 5431508051609838979, 4515078710323627036, 13543555744861125477, 309309746143903518, 16853539194117891693, 12430835367581296760, 9255793325320254163, 6591016556383892120, 17100720673447110167, 6061633534359930907, 2424801126737847877, 143356278625650878, 13554246058973057, 2522638740117423042, 17137049738161235473, 13176139598975768388, 1166120501092890058, 13609465226914230670, 1875448353263386203, 11743691709994844759, 11061975822835649567, 3910967390258776729, 13577511757143681922, 13827967505806592907, 2051032579834721288, 13464396192578309450, 12800325352123601126, 5662172040792660351, 4668403599689432265, 13491732430526501935, 14157448317801936638, 9727633765236455195, 9719667367393442680, 65474725188749034, 541181075058713986, 1362959920153019155, 909082441655242031, 10411762570666372898, 11947296633429547042, 2358875224077331054, 18328103363666444110, 9866396237081281387, 8956667376401863125, 3553975952663161681, 14635072569697080107, 15544243098851103691, 1716867379502200816, 8776276410599591217, 15666047021340369577, 18147839669015605124, 5572968214423121059, 3098271794032834805, 9673511458079712674, 16010905689567823114, 16267201338365627673, 3382936832397700934, 14957330839370249294, 2642620075223240608, 1037193656622159510, 9012211029341477206, 11431820793941846484, 8851179188286979417, 1398798117665992200, 10789412881967821793, 9415310270308545401, 3878698623022480586, 5863277386811827416, 7839335917417032151, 2682939031547768972, 13397811690933306272, 6260148512861761963, 250324816893616712, 9085404939459661953, 9291403781568194640, 4943156069611799558, 4012150457352746082, 6743913241329187121, 12017429880940425975, 12929043722801309882, 10207563294594880008, 11011363281303738187, 15710481255331302269, 16065095211995167995, 7729419910130307261, 14687299092290139624, 14212774840097619295, 2696933303282739820, 18380487173546723450, 16340353901250449060, 16974439742831865800, 950395719691498193, 14294722598295985858, 9819629466618736444, 5134213478899186274, 15000357065088523575, 10866834082882265182, 5562209566130970606, 11574047289359876875, 14220066737185616618, 7779431549476206578, 6164322776781074672, 12698699879532635460, 9775735470622210670, 3418783774094779723, 11711261272918394032, 130965081793297038, 17951168177437733692, 10982891057320326220, 15446335221541982820, 3245348832258032003, 16936841548783354130, 17845797372140897632, 15738639878561184724, 8036219019342274839, 1452217306593250967, 6524640126112677080, 9487637664603922399, 9816896718276865827, 6660361176840108508, 7155686979915548241, 5363459444036855846, 14211791847250927632, 3758021753984352623, 14892848306282510880, 5622159652308652067, 3013224027720379126, 6593658810977588348, 8737392006680055212, 13098306207053606600, 10321069935686406569, 7922126603433897812, 16345323120534317859, 2051345375893155420, 2642889174797452752, 15490895676079176387, 3421728094884350553, 1403789733153795522, 18095248776246397645, 1141680856759996549, 18100437303596844925, 10084704427684498223, 6594067795036706889, 6973150786346631215, 18179961484385983667, 13461945752721759987, 11607193624374158079, 15870559753884484047, 5909010369355025391, 6576523373028484144, 16932784188428621626, 4532369146195665092, 8439234310823545929, 1340079530194594172, 14887691618471650731, 12957273899514368091, 12528827801491392116, 13543620352724873404, 15027641031340635112, 3497080345802388600, 12532486649114668085, 6567958427571461048, 15524967599943619324, 9687676309746098775, 17837290175131112775, 6562577965471546738, 15069045445640377298, 15845870183628003510, 4882896822391168376, 299291354580119732, 1253349370757830450, 4019946893924061554, 4835687088435778153, 560543554021366834, 9073367421711646017, 7210725233620419378, 1298874732344651234, 1572176424217571034, 13459119860690231055, 14894361022235972365, 12479129811186551951, 14014563421012570478, 5045150035901968604, 8669967307441751567, 1905648106987249698, 15427548300560765880, 16929690218389356941, 2257784955568148289, 16671033335294376858, 17747845134586030566, 1166533040996500790, 15593722083313803843, 9396109408892612308, 11499981530721896824, 16970499445754392592, 8812544874418820841, 8398666252211387757, 2704923715823740363, 5314497299504523542, 5160833323750080202, 4489614019342255168, 16950479847425158028, 6792145380267486390, 14740232145636169668, 621507344077794685, 3751460578157408141, 8129084486654095901, 10001447130583054783, 12074020860950174718, 4077799248444467034, 6822188364356126108, 600699026381065222, 4751815635139776884, 15367619962178612777, 5104893889903277375, 4661242055023047595, 2154923710109688891, 17429472085810639176, 15724063920670689806, 15216015843686884607, 12102731527843294992, 5923322163550614145, 578844978773347240, 10464767667513753088, 4422886088759698238, 16103295972923438952, 11952617258811913803, 6497649448616698694, 7393337205916981343, 18096118845330092692, 9417521917459925024, 10361801380161480586, 12227883220061157093, 12402861272457739535, 16959542957232270118, 3100109669354124792, 8252021294756255295, 6601544514524806222, 2299228880186395084, 17206687535661702962, 11126365220307664227, 14027475381759030281, 13930713973102273385, 15470781455897247423, 11132792425729103210, 12743536155285333682, 18404252734721007574, 4471349713039799575, 1097648964215121725, 3481722566194833071, 17004865376724342545, 4412003432895082804, 7207210335443122075, 11185557399280223037, 17791545657588716507, 15001384756479157715, 7068904123591490511, 15342280096772936670, 2962241209356984664, 11085614675955826760, 17304628576563637894, 13276820937207248747, 8496585032541849567, 16867719644448479323, 3556128556368553119, 4135507236401264417, 8300362706308478874, 12391805295598536754, 212746375693666561, 17668657797254926684, 11472227395456264735, 3346261809041337938, 10494844376481252742, 1039434633412734920, 3537248641106173003, 15722028107965146028, 3957344489070663630, 171520814732107885, 15701539439111209401, 16266903088897196785, 8162180034652464302, 751396451910146673, 6284978536639446110, 9475038153254288249, 3366181839966720435, 38511352552288459, 5091650762875915484, 15684434521130749089, 3313175693887858849, 3512862245616351559, 5836672242124333533, 7050189281309530509, 6693570573437863470, 1180929186779755232, 13670569646431885520, 12219171873489819591, 4177796076111463096, 12523988008299904003, 2573301004696669683, 14000913768617402515, 1901514323758988374, 15680204389035820646, 4057543360329026133, 10484558774556926484, 16880563214620981386, 9806529946108790649, 64858070620446021, 13058265791054866751, 14208780393297513060, 132444534110050230, 18171930401783150790, 3788701567251119654, 8068556048675251486, 7698349927972499523, 4200940425301802259, 5859679210997281495, 1196917998587841402, 293846739593611503, 742395111532740587, 7299921458271130779, 4013584019577681930, 13051907051578937053, 15460522300561557538, 11739346111540426460, 6000392060961693921, 2093513337710768996, 2971782196230136142, 14650675906567946197, 13044422653436935289, 5393154276677237552, 9414604975305044529, 14383902696216976975, 3526706571033049996, 10453515348838320881, 1300027919459661427, 18220108229306772305, 6736376168692276304, 14279821335279300725, 1137238529965897445, 10675553998207815811, 10380811037741532194, 8166481736795163463, 1781828658320585086, 12391009694347491828, 917764047682931238, 5513578507525454078, 17200064132172477743, 17870911035870211136, 14336835701074601920, 11250050928475332766, 11433063323885652386, 7083842474651714165, 2491363132897582954, 6822759191074732531, 1975703285786766592, 4664247346348091399, 6200670517431733578, 7625423344374743344, 12752241152270105853, 1792181265050143868, 9684341866777183803, 2519544645709853691, 10916780105681637442, 10344955420168669639, 9942180203006299987, 12084291513489188332, 3948266540776100311, 9154092837114088215, 5346858599403446633, 16526650534031004365, 1000379885777408481, 9962324609830950859, 17358968356608808633, 16077501442923026330, 16373391819852480638, 7285769258546345039, 9258849101785002591, 5742154400061770227, 6000603993323989058, 14647716329474708008, 9759234782041772304, 10140774772642173806, 12417308406161902675, 787743125041003665, 16505409716496421861, 13496346584666506754, 6161155548184037990, 6052945594671650378, 3943721555742518361, 1724411800658421894, 5539278770081464366, 15345354647968324153, 11115348357173195281, 14941897866359059705, 13232123053046857932, 10293530598380524712, 6785485284866633954, 2274573151581626897, 7914418682634630883, 9050484888129037258, 5596144246310386066, 16947403501604289983, 4629498933991963153, 12809658963208366731, 15794201530500048648, 13688081233074642819, 13734318539544366298, 17338613223770563244, 8949201706050038962, 7457293230715991355, 3392962986871707645, 2665311774547334828, 14769130061609548831, 14798608201523559143, 4248204495368930031, 2118780687916441347, 7587741700881576871, 14435287502544940055, 5661100765027979237, 16339955561566207846, 8140260981243250155, 8056431096984667176, 7147782631749791333, 2489306669890900889, 4475802923302768991, 16154685423804744738, 7934898789690822040, 6879516481280076285, 9089400825108258886, 17930990199515864021, 14768387486978797965, 18129863777024625000, 10818394317143489199, 15491447326600259816, 16981166881989734434, 16302476576745273904, 6518490351683715742, 8412288793616962739, 6351653340417195445, 13150568765377194334, 13805040795477806115, 5934147261272121494, 1994383077577350943, 16635675973993021427, 12605935823956703560, 17476993101523741670, 6478809187431271696, 2732525537481875395, 9879991725842211511, 6807932982002010721, 7352337837011779903, 2817471936912129199, 13262278618157850043, 10769791684153169602, 16373519399949306992, 2899723188139359765, 10536102085057036916, 6542494148698745845, 8208357062363683807, 7135654628053388596, 9239547683832094589, 5857943902095897523, 2988676895399293972, 10864744325417622458, 5315919323785706256, 17726255358609389283, 548416274855739353, 14341121194849694922, 7541833390688838500, 12990342594130240843, 18010249397570629115, 12270534655132211820, 11089591099925577121, 8904086294203345138, 360354335597452271, 15390384602644239058, 9646385913080766351, 7807991425432087787, 9178671661816533936, 14127492076118037414, 2392162322212242991, 14036941142798507711, 6502240351436565564, 7893899872624843337, 14288594129943657110, 14040928483141897687, 1592502089611546139, 16817286687244219231, 1288452307437286948, 14067519453346137912, 10075887672168075195, 16769912598561257346, 15456884559283078393, 8711311950138380878, 17440519414852901585, 4031578079792007763, 17459032506776526507, 6047439267180308295, 13036838382774047407, 5995888809898483332, 5666540365944124863, 9669239227306108902, 13524757761279567441, 9100467949589737947, 10630607884662362720, 7656432890734400844, 14587775638685276238, 13512825387557617884, 7244019832094584382, 14996712660826603119, 15920594541485478011, 18302888448007121275, 2860853013354641768, 16346890198034118818, 3995008638584894259, 15431133287252532218, 12007621448583591973, 12654616832949992670, 17218932927375784084, 5108339176271521031, 1475805094516082093, 12897404584908775312, 12902004423289195678, 632420305961082974, 3939829721363017782, 8159027656096857323, 5289724432039220494, 8105874082275331898, 7058967362148243623, 7084554565361601863, 10713529750643129586, 16053444010682289763, 16789097964014031314, 2561050582281530128, 5001739943623024256, 5563376828383980501, 7029523460044084584, 3734303822831180195, 17604507458906309331, 15410396100097854167, 12072617536058855445, 9343913967197010858, 17464576053666161449, 14222234943442423138, 3029903299346511292, 2439504202412922232, 17909602716813870812, 7163148054936239235, 1203376532559407808, 13308342071396905822, 9659238717159340331, 9298790467854663751, 13879727520175998029, 3540668590936352635, 9319928603109010852, 7135941863720734900, 4755935102616669000, 16186952942091333092, 868417045309212144, 4614771873250033976, 12695043568719791838, 11555375308916964213, 7608623603624110550, 2657517781272739364, 16275540663546067547, 13686833504204824152, 12138906647042213779, 10867610696309111099, 14724502273153125344, 16861685577613202946, 8743302596210517799, 14587474243501868159, 2572487334058012273, 603248717087965084, 5059320325228404990, 16238530369175832077, 4519037757700474392, 12378671739975925965, 12407484273586632994, 15313162588758450641, 7715370120812724109, 16244624049595468844, 16509798106801620258, 8670816985658531869, 17161563202276681629, 6760859082822229695, 6807294103798050445, 12102809409961330094, 15733867019982720404, 4500829814752383546, 276727174991039753, 7166981968731078898, 6839153022681710561, 9052935609363333850, 180023864532346968, 15036321241551927313, 8004861917338601611, 10433381600254688194, 58897018650060884, 12176800300096084156, 1677464574753824642, 9033479160050603494, 15102533506708978663, 14084179961157892415, 15862200228768947299, 13406816340465864482, 4480435244557703388, 9328135622344307924, 8569086569674090389, 117119659942779713, 53818961148559993, 17499848839935720391, 9136357190515762310, 9027105858395986940, 17989890318601901443, 18097540417946691193, 14525610539500917353, 2154941454922905428, 5904339583092243168, 13443891604996267, 17266860992297653711, 8744756382159865790, 18024305737878696983, 2546630949169889692, 14096991573794098342, 6037463192406505117, 16222309559186427347, 17465566247484999322, 12659653001889101916, 17145147704704336749, 270028953681259627, 10687721792402042274, 7909714047373529261, 1516466812193933964, 18277293846935305743, 16998707418464340047, 10456180009273456482, 10894339053818039134, 7931553102963941505, 5469019641482786787, 15559448848625861221, 13379845259726008039, 15222258432394099771, 9220502339943331578, 11041492625928826773, 13723142119880743788, 13406366780219048563, 16242021890137344914, 3242681820103600264, 7433022400269598514, 13800053899816348927, 10971582708599334044, 16780079125754812721, 7499355964098143157, 6683080229097120149, 4643838630497962703, 2452976410357582431, 13628797043976089046, 12208582264105438774, 10972823060808439197, 5834946779865455467, 7061987228048265540, 1207502404391064867, 4999557813060557947, 6110696626660879360, 16155026384042239167, 14271653985173561903, 15409968780617538981, 12583134000526518362, 14425350186270986364, 4240634153006170791, 15186331103475807077, 3441220359690995595, 7730377008237943835, 4028688972105728738, 2120709666343944557, 15275844229510750384, 18298631304947594122, 13289696428719138891, 12902251465979698800, 17784642778353395327, 8932078122697958597, 2343784433129198521, 2625325561581989570, 6226848264428179755, 9341106183231718139, 9098935814035218596, 7352506358300392706, 2344104557164367420, 12260380423821950355, 5334772679936050516, 4625031027053042238, 16182107767362335138, 16366374610370031102, 4836384899789893883, 7955273434480297668, 6911864392544134089, 16417538807637628387, 7095497393911852501, 13038578327075160812, 3237033976078933963, 12153345193878928470, 8529208509214849086, 3557796804144548743, 4802066316596054332, 15433632645238893171, 7546572980385595878, 11926731397057053166, 12459060237931625488, 14141685648156683211, 7288151748928762022, 4432041251568429780, 15563480646640553472, 16053290806405898796, 15137506699232809093, 8005443786172873610, 2583037632942587270, 17849394642972838924, 14162302110936479805, 2509458716192360405, 5356417310559321341, 13186254752172487693, 11386136498514963040, 17709391199907333437, 10287520916427793726, 16609632513291109233, 2167580474521363269, 12093450528168333086, 7863381164011802024, 3333719694645745323, 11940256871115614834, 15608703623597862105, 12353758136546081384, 6684006108125243153, 12729735272407622593, 5729918571797570178, 836259910264806143, 14839853436536328663, 3503216322132876395, 12081845346843956683, 11452606043277089033, 3278971557269095943, 14460255683089324678, 26212371609850095, 5791996297577934908, 11791872952518605557, 4303537542168010174, 16090584062354399534, 4908264648595320164, 7751540775663330461, 6257171389619325857, 10426410760581414335, 17538696865214967217, 7467505509612490667, 9596349531846363101, 10432645685361251072, 4554200269336177591, 14164090620513306305, 12703411361203184202, 10381679821480302262, 17407993808772229676, 13447212664492178323, 6368763612994722491, 6985317877139191413, 3304210073159911148, 11815333377693368073, 5807352926666783905, 15497939312564010706, 6997355376158126843, 8894976899204659904, 6062763749482474444, 12366982438149692528, 5811941270446802002, 1365585056061256612, 13475218612693439913, 3101226957898170052, 7483152820787337316, 11966132556998778392, 15847594708317668544, 8536570052230898519, 17755327099574675677, 4573875060013426627, 10571694422987443237, 13886938922370949941, 13243541345182765869, 2407150453734919381, 3504658143291885737, 7031357511394950972, 10000971933511773390, 13912116329153795479, 15031415497603451939, 4599320279014918550, 11777085389799050565, 10789465428143426974, 13380525436974205384, 481819144611018854, 5450316677878014202, 15246244400696673845, 2539248742679727539, 13402910818618694139, 17131842085718107785, 1254150638176089903, 4995981122218138624, 7087931693181888823, 15049301175005363928, 108059457248600792, 6415264753538529207, 8176266644263202488, 9913473944910878449, 1695436935634773000, 17297145186449223950, 12551494433741244515, 9893572477404506151, 5018441835213902689, 2942536196417517781, 16905131659211501459, 6905710711318770295, 7616899203962297179, 14893845862286767619, 9802013654239316989, 17646160800663090718, 688334719842856096, 2007794688466179654, 654395123253282904, 8101085388166846547, 129085352126721490, 5656513500529597182, 5068380157352571940, 16823659606299635586, 18201953606184755353, 14292322613095109457, 16683857805140576716, 2453074754987128823, ], ); } } #[test] #[should_panic] fn limbs_div_mod_fail_1() { limbs_div_mod(&[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_div_mod_fail_2() { limbs_div_mod(&[1], &[4, 5]); } #[test] #[should_panic] fn limbs_div_mod_fail_3() { limbs_div_mod(&[1, 2, 3], &[4, 0]); } #[test] #[should_panic] fn limbs_div_mod_to_out_fail_1() { limbs_div_mod_to_out(&mut [10; 4], &mut [10; 4], &[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_div_mod_to_out_fail_2() { limbs_div_mod_to_out(&mut [10; 4], &mut [10; 4], &[1], &[4, 5]); } #[test] #[should_panic] fn limbs_div_mod_to_out_fail_3() { limbs_div_mod_to_out(&mut [10], &mut [10; 4], &[1, 2, 3, 4], &[4, 5]); } #[test] #[should_panic] fn limbs_div_mod_to_out_fail_4() { limbs_div_mod_to_out(&mut [10; 4], &mut [10; 4], &[1, 2, 3], &[4, 0]); } #[test] fn test_div_mod() { let test = |s, t, quotient, remainder| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); let r = x.div_assign_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.div_assign_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let mut x = u.clone(); let r = x.div_assign_rem(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.div_assign_rem(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().div_rem(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().div_rem(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_rem(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).div_rem(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let num_u = BigUint::from_str(s).unwrap(); let num_v = BigUint::from_str(t).unwrap(); let (q, r) = num_u.div_mod_floor(&num_v); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = num_u.div_rem(&num_v); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let rug_u = rug::Integer::from_str(s).unwrap(); let rug_v = rug::Integer::from_str(t).unwrap(); let (q, r) = rug_u.clone().div_rem_floor(rug_v.clone()); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = rug_u.div_rem(rug_v); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = (&u / &v, u % v); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0", "0"); test("0", "123", "0", "0"); test("1", "1", "1", "0"); test("123", "1", "123", "0"); test("123", "123", "1", "0"); test("123", "456", "0", "123"); test("456", "123", "3", "87"); test("4294967295", "1", "4294967295", "0"); test("4294967295", "4294967295", "1", "0"); test("1000000000000", "1", "1000000000000", "0"); test("1000000000000", "3", "333333333333", "1"); test("1000000000000", "123", "8130081300", "100"); test("1000000000000", "4294967295", "232", "3567587560"); test( "1000000000000000000000000", "1", "1000000000000000000000000", "0", ); test( "1000000000000000000000000", "3", "333333333333333333333333", "1", ); test( "1000000000000000000000000", "123", "8130081300813008130081", "37", ); test( "1000000000000000000000000", "4294967295", "232830643708079", "3167723695", ); test( "1000000000000000000000000", "1234567890987", "810000006723", "530068894399", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018654", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253979", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290113", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "0", "3768477692975601", ); test( "3356605361737854", "3081095617839357", "1", "275509743898497", ); test( "1098730198198174614195", "953382298040157850476", "1", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test("123", "1000000000000000000000000", "0", "123"); } #[test] #[should_panic] fn div_assign_mod_fail() { Natural::from(10u32).div_assign_mod(Natural::ZERO); } #[test] #[should_panic] fn div_assign_mod_ref_fail() { Natural::from(10u32).div_assign_mod(&Natural::ZERO); } #[test] #[should_panic] fn div_mod_fail() { Natural::from(10u32).div_mod(Natural::ZERO); } #[test] #[should_panic] fn div_mod_val_ref_fail() { Natural::from(10u32).div_mod(&Natural::ZERO); } #[test] #[should_panic] fn div_mod_ref_val_fail() { (&Natural::from(10u32)).div_mod(Natural::ZERO); } #[test] #[should_panic] fn div_mod_ref_ref_fail() { (&Natural::from(10u32)).div_mod(&Natural::ZERO); } #[test] #[should_panic] fn div_assign_rem_fail() { Natural::from(10u32).div_assign_rem(Natural::ZERO); } #[test] #[should_panic] fn div_assign_rem_ref_fail() { Natural::from(10u32).div_assign_rem(&Natural::ZERO); } #[test] #[should_panic] fn div_rem_fail() { Natural::from(10u32).div_rem(Natural::ZERO); } #[test] #[should_panic] fn div_rem_val_ref_fail() { Natural::from(10u32).div_rem(&Natural::ZERO); } #[test] #[should_panic] fn div_rem_ref_val_fail() { (&Natural::from(10u32)).div_rem(Natural::ZERO); } #[test] #[should_panic] fn div_rem_ref_ref_fail() { (&Natural::from(10u32)).div_rem(&Natural::ZERO); } #[test] fn test_ceiling_div_neg_mod() { let test = |s, t, quotient, remainder| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); let r = x.ceiling_div_assign_neg_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let mut x = u.clone(); let r = x.ceiling_div_assign_neg_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); assert!(x.is_valid()); assert_eq!(x.to_string(), quotient); let (q, r) = u.clone().ceiling_div_neg_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = u.clone().ceiling_div_neg_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).ceiling_div_neg_mod(v.clone()); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = (&u).ceiling_div_neg_mod(&v); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let (q, r) = rug_ceiling_div_neg_mod( rug::Integer::from_str(s).unwrap(), rug::Integer::from_str(t).unwrap(), ); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); let (q, r) = (u.clone().div_round(v.clone(), Ceiling).0, u.neg_mod(v)); assert_eq!(q.to_string(), quotient); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0", "0"); test("0", "123", "0", "0"); test("1", "1", "1", "0"); test("123", "1", "123", "0"); test("123", "123", "1", "0"); test("123", "456", "1", "333"); test("456", "123", "4", "36"); test("4294967295", "1", "4294967295", "0"); test("4294967295", "4294967295", "1", "0"); test("1000000000000", "1", "1000000000000", "0"); test("1000000000000", "3", "333333333334", "2"); test("1000000000000", "123", "8130081301", "23"); test("1000000000000", "4294967295", "233", "727379735"); test( "1000000000000000000000000", "1", "1000000000000000000000000", "0", ); test( "1000000000000000000000000", "3", "333333333333333333333334", "2", ); test( "1000000000000000000000000", "123", "8130081300813008130082", "86", ); test( "1000000000000000000000000", "4294967295", "232830643708080", "1127243600", ); test( "1000000000000000000000000", "1234567890987", "810000006724", "704498996588", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "810000006723000055638900467181273922269593923137018655", "454912836989613466895606299668358255", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "3164062526261718967339454949926851258865601262253980", "278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "2669936877441", "94998781946290114", "1149635115107", ); test( "3768477692975601", "11447376614057827956", "1", "11443608136364852355", ); test( "3356605361737854", "3081095617839357", "2", "2805585873940860", ); test( "1098730198198174614195", "953382298040157850476", "2", "808034397882141086757", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "1", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "1", "0", ); test("0", "1000000000000000000000000", "0", "0"); test( "123", "1000000000000000000000000", "1", "999999999999999999999877", ); } #[test] #[should_panic] fn ceiling_div_assign_neg_mod_fail() { Natural::from(10u32).ceiling_div_assign_neg_mod(Natural::ZERO); } #[test] #[should_panic] fn ceiling_div_assign_neg_mod_ref_fail() { Natural::from(10u32).ceiling_div_assign_neg_mod(&Natural::ZERO); } #[test] #[should_panic] fn ceiling_div_neg_mod_fail() { Natural::from(10u32).ceiling_div_neg_mod(Natural::ZERO); } #[test] #[should_panic] fn ceiling_div_neg_mod_val_ref_fail() { Natural::from(10u32).ceiling_div_neg_mod(&Natural::ZERO); } #[test] #[should_panic] fn ceiling_div_neg_mod_ref_val_fail() { (&Natural::from(10u32)).ceiling_div_neg_mod(Natural::ZERO); } #[test] #[should_panic] fn ceiling_div_neg_mod_ref_ref_fail() { (&Natural::from(10u32)).ceiling_div_neg_mod(&Natural::ZERO); } #[test] fn limbs_invert_limb_properties() { unsigned_gen_var_12().test_properties(|x| { limbs_invert_limb::(x); }); } #[test] fn limbs_div_limb_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(xs, y)| { let (qs, r) = limbs_div_limb_mod(&xs, y); let (q, r_alt) = Natural::from_owned_limbs_asc(xs).div_mod(Natural::from(y)); assert_eq!(Natural::from_owned_limbs_asc(qs), q); assert_eq!(r, r_alt); }); } #[test] fn limbs_div_limb_to_out_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_13().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let r = limbs_div_limb_to_out_mod(&mut out, &xs, y); let (q, r_alt) = Natural::from_limbs_asc(&xs).div_mod(Natural::from(y)); assert_eq!(r, r_alt); let len = xs.len(); assert_eq!(Natural::from_limbs_asc(&out[..len]), q); assert_eq!(&out[len..], &old_out[len..]); let final_out = out.clone(); let mut out = old_out.to_vec(); assert_eq!(limbs_div_limb_to_out_mod_alt(&mut out, &xs, y), r); assert_eq!(out, final_out); let mut out = old_out.to_vec(); assert_eq!(limbs_div_limb_to_out_mod_naive(&mut out, &xs, y), r); assert_eq!(out, final_out); }, ); } #[test] fn limbs_div_limb_in_place_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); let r = limbs_div_limb_in_place_mod(&mut xs, y); let (q, r_alt) = Natural::from_limbs_asc(&old_xs).div_mod(Natural::from(y)); assert_eq!(Natural::from_owned_limbs_asc(xs), q); assert_eq!(r, r_alt); let mut xs = old_xs.clone(); let r_alt = limbs_div_limb_in_place_mod_alt(&mut xs, y); let q_alt = Natural::from_owned_limbs_asc(xs); assert_eq!(q, q_alt); assert_eq!(r, r_alt); let mut xs = old_xs; let r_alt = limbs_div_limb_in_place_mod_naive(&mut xs, y); let q_alt = Natural::from_owned_limbs_asc(xs); assert_eq!(q, q_alt); assert_eq!(r, r_alt); }); } #[test] fn limbs_div_mod_extra_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_19().test_properties_with_config( &config, |(mut out, fraction_len, ns, d, d_inv, shift)| { let old_out = out.clone(); let r = limbs_div_mod_extra(&mut out, fraction_len, &ns, d, d_inv, shift); verify_limbs_div_mod_extra(&old_out, fraction_len, &ns, d, &out, r); }, ); } #[test] fn limbs_div_mod_extra_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_18().test_properties_with_config( &config, |(mut ns, fraction_len, d, d_inv, shift)| { let old_ns = ns.clone(); let r = limbs_div_mod_extra_in_place(&mut ns, fraction_len, d, d_inv, shift); verify_limbs_div_mod_extra_in_place(&old_ns, fraction_len, d, &ns, r); }, ); } #[test] fn limbs_two_limb_inverse_helper_properties() { unsigned_pair_gen_var_35().test_properties(|(hi, lo)| { let result = limbs_two_limb_inverse_helper(hi, lo); verify_limbs_two_limb_inverse_helper(hi, lo, result); }); } #[test] fn limbs_div_mod_three_limb_by_two_limb_properties() { unsigned_sextuple_gen_var_2().test_properties(|(n_2, n_1, n_0, d_1, d_0, inverse)| { let (q, r) = limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, inverse); verify_limbs_div_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, q, r); }); } #[test] fn limbs_div_mod_by_two_limb_normalized_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_53().test_properties_with_config(&config, |(qs_in, ns_in, ds)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_mod_by_two_limb_normalized(&mut qs, &mut ns, &ds); verify_limbs_div_mod_by_two_limb_normalized(&qs_in, &ns_in, &ds, q_highest, &qs, &ns); }); } #[test] fn limbs_div_mod_schoolbook_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_11().test_properties_with_config(&config, |(qs_in, ns_in, ds, inverse)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_mod_schoolbook(&mut qs, &mut ns, &ds, inverse); verify_limbs_div_mod_1(&qs_in, &ns_in, &ds, q_highest, &qs, &ns); }); } #[test] fn limbs_div_mod_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); large_type_gen_var_12().test_properties_with_config(&config, |(qs_in, ns_in, ds, inverse)| { let mut qs = qs_in.clone(); let mut ns = ns_in.clone(); let q_highest = limbs_div_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); verify_limbs_div_mod_1(&qs_in, &ns_in, &ds, q_highest, &qs, &ns); }); } #[test] fn limbs_invert_basecase_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_50().test_properties_with_config( &config, |(mut is, ds, mut scratch)| { let is_old = is.clone(); let result_definitely_exact = limbs_invert_basecase_approx(&mut is, &ds, &mut scratch); verify_limbs_invert_approx(&is_old, &ds, result_definitely_exact, &is); }, ); } #[test] fn limbs_invert_newton_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_51().test_properties_with_config( &config, |(mut is, ds, mut scratch)| { let is_old = is.clone(); let result_definitely_exact = limbs_invert_newton_approx(&mut is, &ds, &mut scratch); verify_limbs_invert_approx(&is_old, &ds, result_definitely_exact, &is); }, ); } #[test] fn limbs_invert_approx_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_50().test_properties_with_config( &config, |(mut is, ds, mut scratch)| { let is_old = is.clone(); let result_definitely_exact = limbs_invert_approx(&mut is, &ds, &mut scratch); verify_limbs_invert_approx(&is_old, &ds, result_definitely_exact, &is); }, ); } #[test] fn limbs_div_mod_barrett_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_5().test_properties_with_config( &config, |(mut qs, mut rs, ns, ds)| { let qs_old = qs.clone(); let rs_old = rs.clone(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; let q_highest = limbs_div_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); verify_limbs_div_mod_2(&qs_old, &rs_old, &ns, &ds, q_highest, &qs, &rs); }, ); } fn verify_limbs_div_mod_4(ns: &[Limb], ds: &[Limb], qs: &[Limb], rs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let (expected_q, expected_r) = (&n).div_mod(&d); let q = Natural::from_limbs_asc(qs); let r = Natural::from_limbs_asc(rs); assert_eq!(q, expected_q); assert_eq!(r, expected_r); assert!(r < d); assert_eq!(q * d + r, n); let d_len = ds.len(); assert_eq!(qs.len(), ns.len() - d_len + 1); assert_eq!(rs.len(), d_len); } #[test] fn limbs_div_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_11().test_properties_with_config(&config, |(ns, ds)| { let (qs, rs) = limbs_div_mod(&ns, &ds); verify_limbs_div_mod_4(&ns, &ds, &qs, &rs); }); } #[test] fn limbs_div_mod_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_1().test_properties_with_config( &config, |(mut qs, mut rs, ns, ds)| { let qs_old = qs.clone(); let rs_old = rs.clone(); limbs_div_mod_to_out(&mut qs, &mut rs, &ns, &ds); verify_limbs_div_mod_3(&qs_old, &rs_old, &ns, &ds, &qs, &rs); }, ); } // It would be a little confusing to only pass y by value #[allow(clippy::needless_pass_by_value)] fn div_mod_and_div_rem_properties_helper(x: Natural, y: Natural) { let mut mut_x = x.clone(); let r = mut_x.div_assign_mod(&y); assert!(mut_x.is_valid()); assert!(r.is_valid()); let q = mut_x; let mut mut_x = x.clone(); let r_alt = mut_x.div_assign_mod(y.clone()); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let mut q_alt = x.clone(); let r_alt = q_alt.div_assign_rem(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let mut q_alt = x.clone(); let r_alt = q_alt.div_assign_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_rem(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).div_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_rem(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().div_rem(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x / &y, &x % &y); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let (num_q, num_r) = BigUint::from(&x).div_mod_floor(&BigUint::from(&y)); assert_eq!(Natural::from(&num_q), q); assert_eq!(Natural::from(&num_r), r); let (num_q, num_r) = BigUint::from(&x).div_rem(&BigUint::from(&y)); assert_eq!(Natural::from(&num_q), q); assert_eq!(Natural::from(&num_r), r); let (rug_q, rug_r) = rug::Integer::from(&x).div_rem_floor(rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_q), q); assert_eq!(Natural::exact_from(&rug_r), r); let (rug_q, rug_r) = rug::Integer::from(&x).div_rem(rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_q), q); assert_eq!(Natural::exact_from(&rug_r), r); assert!(r < y); assert_eq!(q * y + r, x); } #[test] fn div_mod_and_div_rem_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); natural_pair_gen_var_5().test_properties_with_config(&config, |(x, y)| { div_mod_and_div_rem_properties_helper(x, y); }); natural_pair_gen_var_6().test_properties_with_config(&config, |(x, y)| { div_mod_and_div_rem_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert_eq!((&x).div_mod(Natural::ONE), (x.clone(), Natural::ZERO)); }); natural_gen_var_2().test_properties(|x| { assert_eq!((&x).div_mod(&x), (Natural::ONE, Natural::ZERO)); assert_eq!(Natural::ZERO.div_mod(&x), (Natural::ZERO, Natural::ZERO)); if x > 1 { assert_eq!(Natural::ONE.div_mod(x), (Natural::ZERO, Natural::ONE)); } }); unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let (q, r) = x.div_mod(y); assert_eq!( Natural::from(x).div_mod(Natural::from(y)), (Natural::from(q), Natural::from(r)) ); }); } // It would be a little confusing to only pass y by value #[allow(clippy::needless_pass_by_value)] fn ceiling_div_neg_mod_properties_helper(x: Natural, y: Natural) { let mut mut_x = x.clone(); let r = mut_x.ceiling_div_assign_neg_mod(&y); assert!(mut_x.is_valid()); assert!(r.is_valid()); let q = mut_x; let mut mut_x = x.clone(); let r_alt = mut_x.ceiling_div_assign_neg_mod(y.clone()); let q_alt = mut_x; assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).ceiling_div_neg_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = (&x).ceiling_div_neg_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().ceiling_div_neg_mod(&y); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = x.clone().ceiling_div_neg_mod(y.clone()); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); let (q_alt, r_alt) = ((&x).div_round(&y, Ceiling).0, (&x).neg_mod(&y)); assert_eq!(q_alt, q); assert_eq!(r_alt, r); let (rug_q, rug_r) = rug_ceiling_div_neg_mod(rug::Integer::from(&x), rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_q), q); assert_eq!(Natural::exact_from(&rug_r), r); assert!(r < y); assert_eq!(q * y - r, x); } #[test] fn ceiling_div_neg_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); natural_pair_gen_var_5().test_properties_with_config(&config, |(x, y)| { ceiling_div_neg_mod_properties_helper(x, y); }); natural_pair_gen_var_6().test_properties_with_config(&config, |(x, y)| { ceiling_div_neg_mod_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert_eq!( (&x).ceiling_div_neg_mod(Natural::ONE), (x.clone(), Natural::ZERO) ); }); natural_gen_var_2().test_properties(|x| { assert_eq!((&x).ceiling_div_neg_mod(&x), (Natural::ONE, Natural::ZERO)); assert_eq!( Natural::ZERO.ceiling_div_neg_mod(&x), (Natural::ZERO, Natural::ZERO) ); if x > 1 { assert_eq!( Natural::ONE.ceiling_div_neg_mod(&x), (Natural::ONE, x - Natural::ONE) ); } }); unsigned_pair_gen_var_12::().test_properties(|(x, y)| { let (q, r) = x.ceiling_div_neg_mod(y); assert_eq!( Natural::from(x).ceiling_div_neg_mod(Natural::from(y)), (Natural::from(q), Natural::from(r)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/div_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivNegMod, DivRound, DivRoundAssign, DivisibleBy, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_unsigned_rounding_mode_triple_gen_var_1, unsigned_vec_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::div_round::limbs_limb_div_round_limbs; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_rounding_mode_triple_gen_var_1, natural_pair_gen_var_5, natural_pair_gen_var_7, natural_rounding_mode_pair_gen, natural_rounding_mode_pair_gen_var_2, }; use num::{BigUint, Integer}; use rug::ops::DivRounding; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_div_round() { let test = |s, t, rm, quotient, o| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); assert_eq!(x.div_round_assign(v.clone(), rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let mut x = u.clone(); assert_eq!(x.div_round_assign(&v, rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let (q, o_alt) = u.clone().div_round(v.clone(), rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = u.clone().div_round(&v, rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = (&u).div_round(v.clone(), rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); let (q, o_alt) = (&u).div_round(&v, rm); assert!(q.is_valid()); assert_eq!(q.to_string(), quotient); assert_eq!(o_alt, o); match rm { Down => { assert_eq!( rug::Integer::from_str(s) .unwrap() .div_trunc(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } Floor => { assert_eq!( BigUint::from_str(s) .unwrap() .div_floor(&BigUint::from_str(t).unwrap()) .to_string(), quotient ); assert_eq!( rug::Integer::from_str(s) .unwrap() .div_floor(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } Ceiling => { assert_eq!( rug::Integer::from_str(s) .unwrap() .div_ceil(rug::Integer::from_str(t).unwrap()) .to_string(), quotient ); } _ => {} } }; test("0", "1", Down, "0", Equal); test("0", "1", Floor, "0", Equal); test("0", "1", Up, "0", Equal); test("0", "1", Ceiling, "0", Equal); test("0", "1", Nearest, "0", Equal); test("0", "1", Exact, "0", Equal); test("0", "123", Down, "0", Equal); test("0", "123", Floor, "0", Equal); test("0", "123", Up, "0", Equal); test("0", "123", Ceiling, "0", Equal); test("0", "123", Nearest, "0", Equal); test("0", "123", Exact, "0", Equal); test("1", "1", Down, "1", Equal); test("1", "1", Floor, "1", Equal); test("1", "1", Up, "1", Equal); test("1", "1", Ceiling, "1", Equal); test("1", "1", Nearest, "1", Equal); test("1", "1", Exact, "1", Equal); test("123", "1", Down, "123", Equal); test("123", "1", Floor, "123", Equal); test("123", "1", Up, "123", Equal); test("123", "1", Ceiling, "123", Equal); test("123", "1", Nearest, "123", Equal); test("123", "1", Exact, "123", Equal); test("123", "2", Down, "61", Less); test("123", "2", Floor, "61", Less); test("123", "2", Up, "62", Greater); test("123", "2", Ceiling, "62", Greater); test("123", "2", Nearest, "62", Greater); test("125", "2", Down, "62", Less); test("125", "2", Floor, "62", Less); test("125", "2", Up, "63", Greater); test("125", "2", Ceiling, "63", Greater); test("125", "2", Nearest, "62", Less); test("123", "123", Down, "1", Equal); test("123", "123", Floor, "1", Equal); test("123", "123", Up, "1", Equal); test("123", "123", Ceiling, "1", Equal); test("123", "123", Nearest, "1", Equal); test("123", "123", Exact, "1", Equal); test("123", "456", Down, "0", Less); test("123", "456", Floor, "0", Less); test("123", "456", Up, "1", Greater); test("123", "456", Ceiling, "1", Greater); test("123", "456", Nearest, "0", Less); test("1000000000000", "1", Down, "1000000000000", Equal); test("1000000000000", "1", Floor, "1000000000000", Equal); test("1000000000000", "1", Up, "1000000000000", Equal); test("1000000000000", "1", Ceiling, "1000000000000", Equal); test("1000000000000", "1", Nearest, "1000000000000", Equal); test("1000000000000", "1", Exact, "1000000000000", Equal); test("1000000000000", "3", Down, "333333333333", Less); test("1000000000000", "3", Floor, "333333333333", Less); test("1000000000000", "3", Up, "333333333334", Greater); test("1000000000000", "3", Ceiling, "333333333334", Greater); test("1000000000000", "3", Nearest, "333333333333", Less); test("999999999999", "2", Down, "499999999999", Less); test("999999999999", "2", Floor, "499999999999", Less); test("999999999999", "2", Up, "500000000000", Greater); test("999999999999", "2", Ceiling, "500000000000", Greater); test("999999999999", "2", Nearest, "500000000000", Greater); test("1000000000001", "2", Down, "500000000000", Less); test("1000000000001", "2", Floor, "500000000000", Less); test("1000000000001", "2", Up, "500000000001", Greater); test("1000000000001", "2", Ceiling, "500000000001", Greater); test("1000000000001", "2", Nearest, "500000000000", Less); test( "1000000000000000000000000", "4294967295", Down, "232830643708079", Less, ); test( "1000000000000000000000000", "4294967295", Floor, "232830643708079", Less, ); test( "1000000000000000000000000", "4294967295", Up, "232830643708080", Greater, ); test( "1000000000000000000000000", "4294967295", Ceiling, "232830643708080", Greater, ); test( "1000000000000000000000000", "4294967295", Nearest, "232830643708080", Greater, ); test( "1000000000000000000000000", "1000000000000", Down, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Floor, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Up, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Ceiling, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Nearest, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Exact, "1000000000000", Equal, ); test( "1000000000000000000000000", "1000000000001", Down, "999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Floor, "999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Up, "1000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Ceiling, "1000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Nearest, "999999999999", Less, ); test( "2999999999999999999999999", "2000000000000000000000000", Nearest, "1", Less, ); test( "3000000000000000000000000", "2000000000000000000000000", Nearest, "2", Greater, ); test( "3000000000000000000000001", "2000000000000000000000000", Nearest, "2", Greater, ); } #[test] #[should_panic] fn div_round_assign_fail_1() { let mut n = Natural::from(10u32); n.div_round_assign(Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_assign_fail_2() { let mut n = Natural::from(10u32); n.div_round_assign(Natural::from(3u32), Exact); } #[test] #[should_panic] fn div_round_assign_ref_fail_1() { let mut n = Natural::from(10u32); n.div_round_assign(&Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_assign_ref_fail_2() { let mut n = Natural::from(10u32); n.div_round_assign(&Natural::from(3u32), Exact); } #[test] #[should_panic] fn div_round_fail_1() { Natural::from(10u32).div_round(Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_fail_2() { Natural::from(10u32).div_round(Natural::from(3u32), Exact); } #[test] #[should_panic] fn div_round_val_ref_fail_1() { Natural::from(10u32).div_round(&Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_val_ref_fail_2() { Natural::from(10u32).div_round(&Natural::from(3u32), Exact); } #[test] #[should_panic] fn div_round_ref_val_fail_1() { (&Natural::from(10u32)).div_round(Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_ref_val_fail_2() { (&Natural::from(10u32)).div_round(Natural::from(3u32), Exact); } #[test] #[should_panic] fn div_round_ref_ref_fail_1() { (&Natural::from(10u32)).div_round(&Natural::ZERO, Floor); } #[test] #[should_panic] fn div_round_ref_ref_fail_2() { (&Natural::from(10u32)).div_round(&Natural::from(3u32), Exact); } #[test] fn limbs_limb_div_round_limbs_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_rounding_mode_triple_gen_var_1().test_properties_with_config( &config, |(ys, x, rm)| { let result = limbs_limb_div_round_limbs(x, &ys, rm); let a = Natural::from(x); let b = Natural::from_owned_limbs_asc(ys); if rm != Exact || (&a).divisible_by(&b) { let (result, o) = result.unwrap(); assert_eq!((Natural::from(result), o), a.div_round(b, rm)); } else { assert!(result.is_none()); } }, ); } #[test] fn div_round_properties() { natural_natural_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { let mut mut_x = x.clone(); let o = mut_x.div_round_assign(&y, rm); assert!(mut_x.is_valid()); let q = mut_x; let mut mut_x = x.clone(); assert_eq!(mut_x.div_round_assign(y.clone(), rm), o); assert!(mut_x.is_valid()); assert_eq!(mut_x, q); let (q_alt, o_alt) = (&x).div_round(&y, rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = (&x).div_round(y.clone(), rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = x.clone().div_round(&y, rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); let (q_alt, o_alt) = x.clone().div_round(y.clone(), rm); assert!(q_alt.is_valid()); assert_eq!(q_alt, q); assert_eq!(o_alt, o); assert!(q <= x); assert_eq!((q * &y).cmp(&x), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } }); natural_pair_gen_var_5().test_properties(|(x, y)| { let left_multiplied = &x * &y; let xo = (x.clone(), Equal); assert_eq!((&left_multiplied).div_round(&y, Down), xo); assert_eq!((&left_multiplied).div_round(&y, Up), xo); assert_eq!((&left_multiplied).div_round(&y, Floor), xo); assert_eq!((&left_multiplied).div_round(&y, Ceiling), xo); assert_eq!((&left_multiplied).div_round(&y, Nearest), xo); assert_eq!((&left_multiplied).div_round(&y, Exact), xo); assert_eq!( Natural::exact_from(&rug::Integer::from(&x).div_trunc(rug::Integer::from(&y))), (&x).div_round(&y, Down).0 ); assert_eq!( Natural::from(&BigUint::from(&x).div_floor(&BigUint::from(&y))), (&x).div_round(&y, Floor).0 ); assert_eq!( Natural::exact_from(&rug::Integer::from(&x).div_floor(rug::Integer::from(&y))), (&x).div_round(&y, Floor).0 ); assert_eq!( Natural::exact_from(&rug::Integer::from(&x).div_ceil(rug::Integer::from(&y))), (&x).div_round(&y, Ceiling).0 ); assert_eq!((&x).ceiling_div_neg_mod(&y).0, x.div_round(y, Ceiling).0); }); natural_pair_gen_var_7().test_properties(|(x, y)| { let down = (&x).div_round(&y, Down); assert_eq!(down.1, Less); let up = (&down.0 + Natural::ONE, Greater); assert_eq!((&x).div_round(&y, Up), up); assert_eq!((&x).div_round(&y, Floor), down); assert_eq!((&x).div_round(&y, Ceiling), up); let nearest = x.div_round(y, Nearest); assert!(nearest == down || nearest == up); }); natural_rounding_mode_pair_gen().test_properties(|(x, rm)| { assert_eq!((&x).div_round(Natural::ONE, rm), (x, Equal)); }); natural_rounding_mode_pair_gen_var_2().test_properties(|(x, rm)| { assert_eq!(Natural::ZERO.div_round(&x, rm), (Natural::ZERO, Equal)); assert_eq!((&x).div_round(&x, rm), (Natural::ONE, Equal)); }); unsigned_unsigned_rounding_mode_triple_gen_var_1::().test_properties(|(x, y, rm)| { let (q, o) = x.div_round(y, rm); assert_eq!( Natural::from(x).div_round(Natural::from(y), rm), (Natural::from(q), o) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/divisible_by.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleBy; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::slices::slice_test_zero; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_pair_gen_var_15, unsigned_vec_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_22, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::divisible_by::{ limbs_divisible_by, limbs_divisible_by_limb, limbs_divisible_by_ref_ref, limbs_divisible_by_ref_val, limbs_divisible_by_val_ref, }; use malachite_nz::natural::arithmetic::mod_op::{limbs_mod, limbs_mod_limb}; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_2, natural_pair_gen, natural_pair_gen_var_6, natural_pair_gen_var_7, unsigned_vec_pair_gen_var_17, }; use malachite_nz::test_util::natural::arithmetic::divisible_by::{ combined_limbs_divisible_by_limb, num_divisible_by, }; use num::BigUint; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_divisible_by_limb() { let test = |ns: &[Limb], d: Limb, divisible: bool| { assert_eq!(limbs_divisible_by_limb(ns, d), divisible); assert_eq!(limbs_mod_limb::(ns, d) == 0, divisible); assert_eq!(combined_limbs_divisible_by_limb(ns, d), divisible); }; test(&[0, 0], 2, true); test(&[6, 7], 1, true); test(&[6, 7], 2, true); test(&[100, 101, 102], 10, false); test(&[123, 456], 789, false); test(&[369, 1368], 3, true); test(&[u32::MAX, u32::MAX], 2, false); test(&[u32::MAX, u32::MAX], 3, true); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_limb_fail() { limbs_divisible_by_limb(&[10], 10); } fn verify_limbs_divisible_by(ns: &[Limb], ds: &[Limb], divisible: bool) { assert_eq!( Natural::from_limbs_asc(ns).divisible_by(Natural::from_limbs_asc(ds)), divisible ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_divisible_by() { let test = |ns: &[Limb], ds: &[Limb], divisible: bool| { let mut mut_ns = ns.to_vec(); let mut mut_ds = ds.to_vec(); assert_eq!(limbs_divisible_by(&mut mut_ns, &mut mut_ds), divisible); let mut mut_ns = ns.to_vec(); assert_eq!(limbs_divisible_by_val_ref(&mut mut_ns, ds), divisible); let mut mut_ds = ds.to_vec(); assert_eq!(limbs_divisible_by_ref_val(ns, &mut mut_ds), divisible); assert_eq!(limbs_divisible_by_ref_ref(ns, ds), divisible); verify_limbs_divisible_by(ns, ds, divisible); }; // - n_low & d_mask == 0 // - d_len == 1 // - d_len == 1 && n_len < BMOD_1_TO_MOD_1_THRESHOLD test(&[6], &[2], true); // - n_low & d_mask != 0 test(&[6], &[4], false); // - d_len != 1 // - d_len != 2 // - trailing_zeros == 0 // - rs[n_len - 1] >= ds[d_len - 1] // - schoolbook test(&[1, 3, 6, 5, 3], &[1; 3], true); test(&[1, 3, 7, 5, 3], &[1; 3], false); test(&[6, 19, 32, 21], &[1, 2, 3], true); // - d_len == 2 // - d_1 > d_mask // - trailing_zeros != 0 test(&[6, 19, 32, 21], &[6, 7], true); test(&[10200, 20402, 30605, 20402, 10200], &[100, 101, 102], true); test( &[10200, 20402, 30606, 20402, 10200], &[100, 101, 102], false, ); test(&[u32::MAX], &[u32::MAX], true); test(&[1, u32::MAX - 1], &[u32::MAX], true); test( &[1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], &[u32::MAX; 3], true, ); test( &[1, 0, 0, 0xfffffffd, u32::MAX, u32::MAX], &[u32::MAX; 3], false, ); test(&[0, 0, 0, 6, 19, 32, 21], &[0, 0, 1, 2, 3], true); // - rs[n_len - 1] < ds[d_len - 1] && n_len == d_len test(&[0, 1], &[1, 2], false); // - rs[n_len - 1] < ds[d_len - 1] && n_len != d_len test(&[0, 0, 1], &[1, 2], false); // - d_1 <= d_mask // - d_len == 2 && n_len < BMOD_1_TO_MOD_1_THRESHOLD test(&[0, 1], &[2, 1], false); // - d_len == 1 && n_len >= BMOD_1_TO_MOD_1_THRESHOLD test( &[ 4217434641, 2983831158, 957997048, 1656831590, 3000005030, 3397493916, 1524177764, 1158142389, 874701225, 1462813081, 1367619360, 2801303018, 2789627609, 215719367, 3216170452, 431698475, 626354765, 1948186092, 2374814145, 3144956155, 601105061, 1178232240, 2555160313, 2595360911, 4288604684, 4266583859, 125722653, 201817397, 664583805, 1753913919, 2144999578, 3776810790, 1371327248, 4182636558, 3002281720, 1871734359, 2973117455, 2090705384, 824744451, 4231117477, 1910500161, 31831336, 2931836758, 3786849205, 2959137635, 2746351664, 4074106964, 2451006035, 2637785805, 1672606871, 2076991740, 4073897939, 923576835, 1556160088, 3713754032, 2220129449, 1665613419, 2890565429, 2007962628, 3653583281, 3958263098, 2634902570, 503308768, 2860598088, 4267080858, 486522024, 1950214271, 2459522693, 3179388659, 1827961427, 848836381, 2558276851, 4179490611, 3898139084, ], &[2987492981], false, ); // - d_len == 2 && n_len >= BMOD_1_TO_MOD_1_THRESHOLD test( &[ 256, 2983831158, 957997048, 1656831590, 3000005030, 3397493916, 1524177764, 1158142389, 874701225, 1462813081, 1367619360, 2801303018, 2789627609, 215719367, 3216170452, 431698475, 626354765, 1948186092, 2374814145, 3144956155, 601105061, 1178232240, 2555160313, 2595360911, 4288604684, 4266583859, 125722653, 201817397, 664583805, 1753913919, 2144999578, 3776810790, 1371327248, 4182636558, 3002281720, 1871734359, 2973117455, 2090705384, 824744451, 4231117477, 1910500161, 31831336, 2931836758, 3786849205, 2959137635, 2746351664, 4074106964, 2451006035, 2637785805, 1672606871, 2076991740, 4073897939, 923576835, 1556160088, 3713754032, 2220129449, 1665613419, 2890565429, 2007962628, 3653583281, 3958263098, 2634902570, 503308768, 2860598088, 4267080858, 486522024, 1950214271, 2459522693, 3179388659, 1827961427, 848836381, 2558276851, 4179490611, 3898139084, ], &[128, 10], false, ); // - divide-and-conquer test( &[ 2169104186, 2266546494, 587315734, 3739269241, 3114885960, 3686571368, 1230083221, 1369517966, 4291553725, 1232833631, 3745253511, 963470524, 3412093994, 715605915, 3178840986, 1537155511, 2643999117, 1124945145, 1130467184, 505174687, 279956991, 2029663376, 3099875141, 4078932665, 3507974056, 3764533985, 2928504341, 2999119478, 2235181988, 8120813, 2049630814, 816255631, 2958134171, 2134573459, 1356483654, 1353858604, 1377057347, 3050515126, 1981544721, 3471014354, 2173072144, 1505712122, 2385668585, 1593490077, 92053253, 1525861712, 1903853398, 2590603784, 545440811, 731662535, 2914628805, 1579744586, 2159061521, 3862444433, 3486035778, 3569159590, 1798578513, 679586822, 1027034006, 2821087869, 138364116, 3862434540, 3700050828, 3041238135, 203907970, 2724479836, 666267271, 4276247071, 1210965278, 3212904426, 3198623953, 2953530971, 254157796, 4263106694, 389863197, 928000244, 489453825, 3398590663, 3892546275, 132887015, 982972816, 1812112076, 3203181556, 729377309, 2468997822, 4114200925, 3495511499, 2423156091, 642381751, 2588236007, 508136034, 2909297716, 2020665371, 2823339182, 4093944876, 1753900312, 2227288358, 3843178420, 1383018274, 1337754144, 4067699321, 4094839667, 3612619766, 241995072, 43874530, 1329365494, 1161788309, 1343981322, 2661807206, 3916970745, 3208129678, 2607521742, 4068076440, 2254858029, 52800437, 2977865502, 2752070351, 840472004, 993872687, 118561354, 281929094, 241294936, 894356352, 289721033, 658212066, 2618650207, 997997486, 2912241249, 828533444, 1694023493, 368405691, 2952571418, 1897728140, 3178382549, 433809308, 1079641707, 913972412, 127906934, 1696809357, 4135380244, 862031081, 3680249566, 4137097186, 3602972472, 3335499618, 2982048038, 2435876884, 4160199134, 3332420996, 1469463193, 3949621168, 4019057802, 3431928811, 241891262, 4190148730, 991409256, 487806424, 685244570, 703993726, 4044357137, 3327796046, 1784380542, 1000763217, 966313870, 3075333333, 1734085949, 913022609, 4245248443, 3252643922, 806393395, 2476394527, 3747108106, 392268399, 2776259136, 2995460881, 3323006399, 2205717476, 3139072617, 3312440544, 2390989321, 3330711647, 280322670, 3221287591, 3672189452, 2085991953, 2701899535, 944470536, 3459091473, 669958019, 3341466114, 1375663389, 4178951502, 1887416017, 2960114949, 1805082649, 1897118491, 1735206477, 1086467373, 3454663842, 3027811502, 2681987258, 3932510644, 1041830424, 3552076035, 3424876359, 1886621954, 2650649785, 3695516428, 71584725, 168707053, 740198485, 2245105417, 1249177483, 1722102768, 374173663, 297078497, 2990861606, 925762985, 2001492, 1646443443, 3583906616, 3312776133, 1157309588, 1335281328, 2109828349, 34076132, 2168747053, 3778129093, 2613456818, 1560157805, 4195434489, 2487913229, 1609822712, 2764757271, 4283118804, 91257607, 1080744325, 2493394532, 326260208, 187395392, 2939059459, 1885652903, 4191985814, 3258074631, 3513150040, 3580927149, 3407053353, 226470876, 1817235991, 852868000, 214844744, 4207902570, 2902398660, 1397161252, 4138041363, 757796679, 3031247970, 1048623352, 661015139, 1415029830, 2485923562, 141373475, 1787794282, 1976681319, 1253461810, 1392275594, 2429887226, 2877605657, 1263266041, 3484472193, 2640875272, 1801160237, 4069713126, 1934086126, 192869060, 3283904145, 2763023257, 989311613, 4108856559, 4226641951, 3128021950, 2529670899, 2772914524, 1201442981, 176669049, 3707600374, 3706141284, 276672151, 2904754467, 1347188130, 769251759, 3322969014, 4037207402, 89044259, 1314731683, 1220332916, 438537136, 827090059, 272783156, 38244839, 2305761897, 3723044685, 644855780, 3551390010, 3080020204, 3622120389, 1104906535, 2333407502, 1345296288, 3700728088, 1599981349, 3670637655, 3168618533, 1373988250, 2598638204, 2174612205, 945499273, 1516940873, 1689708547, 3883475244, 1794555293, 969139846, 319304823, 197055825, 2598587648, 3355480329, 2619765319, 1140474610, 1254318132, 547674601, 852635669, 2448264593, 1227857672, 2436426747, 1094311339, 1981571015, 648000603, 4136039667, 1172894412, 2484651184, 1368629311, 1617781838, 1466927120, 110324911, 650355804, 3280790286, 242161684, 3602009741, 1994089400, 3324228020, 1722483735, 3385991773, 1733478840, 1986423929, 3118968494, 4214422449, 4257358954, 3002156517, 3342276360, 3961751029, 1044818187, 1302652353, 3780349809, 208159762, 3921381160, 3104805287, 701555864, 1353151101, 2110331602, 1065775293, 3138173139, 2673335412, 1332663987, 2532658640, 1175704936, 3679818302, 2587893347, 1209649581, 2160090389, 330309148, 812388071, 1856530929, 1621848118, 3595859350, 372670625, 856076462, 1710799422, 2493451671, 142603177, 1359238753, 3676968997, 3302712549, 2781924367, 822719137, 1553432401, 2179118972, 2647958472, 4231975017, 3662950204, 1513113991, 3143506626, 4261352924, 2900864288, 2505227245, 1285289303, 3374032515, 1343085626, 1298169727, 2712611178, 2519581207, 863950575, 1044705613, 1608844529, 398557619, 2405597933, 2442595621, 3756322386, 497719075, 958070332, 710843530, 1361414502, 3604632029, 3231349850, 3610106540, 3750520155, 2250988708, 2584496493, 3558352960, 847973690, 291227960, 3347729096, 718140050, 2842802593, 45528740, 1213748814, 823269856, 1820806986, 2274362480, 3357823158, 2054374162, 3650723151, 1083860767, 3888008023, 2654794365, 1844177589, 2412317894, 665263029, 68335398, 1937681761, 1826086466, 2497132629, 2053584711, 766478134, 3524809898, 2670148828, 2393556691, 3637792476, 3212231999, 1742932892, 2227017682, 1415769555, 2646519675, 4134401864, 4082068803, 1489292682, 1791908612, 1508761188, 2209720169, 4078191455, 1533239903, 1768397400, 2157145812, 2565607675, 519979525, 4034426142, 1802535614, 3593889411, 3552848103, 4200389446, 3707485453, 1542526970, 1196075302, 2665590567, 2739194250, 1399657538, 113759040, 3183789024, 386168896, 3295775459, 1126370167, 3951610340, 3551153197, 1690373840, 2358923787, 4229534809, 2290337908, 3142294436, 6187128, 1890727395, 4243456854, 3017228946, 3877724493, 3444342781, 4211602385, 183761949, 1350782665, 592876667, 433343586, 1817557528, 261342788, 2125735308, 3252124670, 1044819933, 2708341279, 100284000, 1935238212, 3692459811, 383621158, 867374712, 1021196147, 530727196, 3915886219, 3705268858, 2857571834, 39817906, 728954116, 3793147370, 406405776, 3215234366, 2390137796, 1950992336, 1570696989, 2517131965, 1753011612, 3117489998, 1817087642, 4076432149, 212175604, 4209324605, 249521560, 23902299, 4101107861, 620892789, 2870257694, 2409554819, 4089101702, 752496922, 362566394, 3459326044, 2058596304, 2035287414, 1288805897, 3459829946, 3477025798, 2693442504, 606291269, 3716454206, 2017617901, 739955186, 226702924, 1506656210, 564432407, 698436937, 254384295, 187952024, 3541301121, 4130651539, 2092000582, 1462681196, 2024159384, 3025822813, 4206822061, 3305239609, 2483534937, 1068789172, 3171775935, 4213371381, 2105143064, 1715930888, 1869129579, 1721290855, 726914406, 1055443769, 4127573087, 1131510133, 3464915074, 3962097334, 4198659475, 449084358, 1255330246, 2217278306, 3142203879, 1060366183, 1086505252, 2196640428, 3020011420, 101613015, 3615286211, 3719078597, 512776700, 1670970979, 2918688390, 539186647, 3899361016, 3899238233, 1503014623, 1487072013, 2554631966, 640480738, 2906553626, 1264192892, 2306406723, 4030568138, 4056096494, 3608358777, 3240979341, 2671626653, 3715996998, 983432302, 712348732, 2406877846, 32785806, 3076643355, 2166512728, 1664977926, 379356343, 2822820700, 2920574885, 1252499465, 3427197294, 1702237632, 1641655300, 310170158, 1001329555, 562240182, 3713127974, 1400603861, 4291073476, 485459242, 1624227405, 3436522834, 1213896273, 893370150, 3608415729, 89540222, 1549103010, 2362944877, 636789508, 2413471028, 2932597865, 3523220925, 3113130274, 669409867, 948785250, 2353176063, 3868467803, 3484917154, 2551915221, 1497486585, 4152651850, 473143127, 998729612, 2905656591, 1182540548, 3623426979, 1806548948, 598537433, 2345218067, 2744900190, 3658378705, 1964774718, 2557442350, 1799636549, 4153665976, 3300594666, 682645932, 3787913729, 2627374889, 2780368898, 3053617139, 2751701327, 1952207418, 761193466, 795600024, 460949087, 2883354289, 2416166804, 2024094265, 2645942993, 1321335098, 4080983696, 3719057466, 2761861073, 876455883, 2265708436, 1295460078, 4221100394, 327768739, 3015153526, 631331115, 3428464785, 644806658, 1607685691, 2709965965, 2477974591, 4185293236, 3564199615, 5024334, 1218905327, 2381178079, 3421492726, 3210172738, 2208193787, 3497539969, 67679408, 7015329, 1644345354, 1219650877, 3999432182, 787420821, 3125125301, 3551310228, 1514288276, 4184725579, 3923600454, 342747221, 2581849732, 654180323, 2328957051, 1611256108, 3331006737, 788693120, 3401041379, 2099076468, 1628705595, 3859087292, 2072660933, 3257911942, 984362662, 3077084901, 1851298543, 1203131946, 1027287045, 3054998432, 2653266373, 3019736717, 195024883, 4171454841, 2527872129, 1247020327, 2238591475, 2136657438, 2340932338, 2934529639, 3272613638, 2185810440, 165859626, 2304003399, 3993415600, 2437076830, 3780217527, 2707007352, 208843797, 3155075128, 336707716, 568567552, 2653218265, 561879893, 2244946665, 369107514, 449372466, 3941906096, 4130057272, 641659453, 4111061561, 812270662, 4279338122, 470975590, 3494637046, 2762073253, 1757357680, 867114230, 2219045455, 94626870, 1137750480, 2094083377, 3138049052, 3894576321, 1378390851, 2665729658, 3104615470, 2936479206, 635788017, 3475293009, 702959182, 4237902922, 313651363, 3029245314, 2741552996, 3659722846, 2604607686, 534266423, 2704761681, 1711186117, 1592045306, 305708572, 1642121404, 1597934575, 1265263680, 4290920109, 537137446, 3140075852, 2898671495, 364470582, 3399686556, 427464562, 1727273367, 4033988735, 2229384209, 977641014, 3910691764, 2268933684, 3451806563, 204040124, 1396741907, 3978224431, 2183874291, 541967491, 3026397898, 2065096561, 961793538, 3683498094, 3088514164, 3743738285, 1346128225, 3719735346, 3228089802, 3009395215, 1568158796, 1870781853, 728601499, 2727218958, 50783576, 351811718, 1118170454, 2810777608, 1996734855, 2444030542, 3509123551, 1649933419, 2057107104, 381073891, 1651296068, 3691277418, 1252885223, 604972451, 3560912853, 3381041205, 97236104, 4018969688, 3285100340, 906433788, 1674945334, 2291802158, 4143691201, 1121520461, 1907818021, 3817648523, 2696920177, 2029578019, 3359867876, 4035314026, 814831395, 402590457, 2757255435, 1617756566, 2573316001, 952926090, 26184857, 1491250719, 479641193, 1246115200, 2071561116, 1740343273, 3930947184, 849382562, 3146753986, 2079815766, 1124558195, 706118855, 1624669925, 2345125117, 1104509365, 4253600455, 2178123171, 51311084, 644240166, 4235897745, 1552583610, 2721864023, 2417820136, 866003296, 3100038290, 1138399889, 2621877527, 35166564, 2925990087, 676411279, 824163386, 3059725138, 3436858126, 639114670, 2354917892, 3668885469, 538607516, 1188540552, 2077947642, 4214121777, 1024066855, 584585760, 3330067560, 3289211050, 4227743647, 1048503204, 3682815131, 3593095813, 724046659, 177523551, 789173931, 3210826214, 4114794229, 2001369528, 1922224607, 2449629560, 2990923760, 1590140407, 3066241294, 2032178641, 1673025735, 728782818, 2805995869, 3173476316, 4095043043, 4188792079, 961420687, 78547373, 331719917, 3623238477, 4199725886, 2474752488, 1757124968, 837328916, 1408306379, 3214330220, 3355378613, 389392287, 2212359467, 2671491064, 2411527388, 3622122999, 1506404106, 3192630979, 135884006, 2398972643, 3221225957, 827475224, 2670120145, 3556393877, 1151874066, 4001558171, 773853920, 261365390, 2930272664, 2171104793, 3679192861, 1286480701, 3052752341, 3704064736, 2857905507, 323617567, 500166971, 3590167140, 46687505, 3603631510, 574954751, 1921803608, 2826015895, 3138948179, 3471354167, 1087583334, 2872377970, 589736930, 3600161138, 4280276795, 610467300, 4258855269, 1847560302, 89888737, 3455621079, 1271345555, 446001635, 1740292174, 1118130455, 1649510985, 1314419877, 2732937708, 749289315, 911962385, 361189198, 1736019975, 901913856, 1697911811, 512137942, 1863970636, 2127135390, 2362086418, 1086237732, 509394495, 2529713980, 229310079, 1661114917, 1240908759, 1028403199, 2183953926, 1127564377, 3529642168, 557447511, 314233677, 1785885521, 948058680, 3314696870, 3418731379, 1093740990, 1408897230, 1674741555, 2040518897, 500968889, 2496717966, 1599286253, 927417612, 846393794, 2100310692, 654673974, 2475673804, 3656332830, 4291477953, 3810417562, 1914048410, 1890554346, 1707870195, 3321510012, 1070941267, 1096480276, 2946865379, 3751928683, 1860758395, 3419660556, 4012128602, 517029378, 1439950265, 502253691, 2697781940, 2999363300, 2555052305, 852916430, 3054976477, 3742735044, 2485908580, 1698982608, 2625028734, 1580539136, 3300904616, 633144061, 886348308, 111258399, 1439126181, 2276519459, 3959771808, 1314171199, 2322947590, 706448164, 998967466, 3140589807, 3516861163, 2443112013, 2783111182, 792015165, 1578481086, 3460528207, 1455852169, 3304443593, 123860242, 1860448346, 2199267391, 3894670775, 3728263116, 530899313, 3431936766, 497193688, 3964977529, 2359257224, 1413751341, 953616340, 2193659597, 2870937129, 2560871048, 3424144210, 2330060314, 476593761, 4111398811, 224492168, 2426790462, 1366265513, 3547692500, 237014373, 126994210, 1698344909, 3097624535, 2606367774, 2139247575, 4278291258, 3111057613, 3597265089, 1486559051, 3888932297, 2068681921, 4018333295, 1237578874, 1394533778, 3019039915, 2435030995, 361267457, 2911469665, 109581803, 4017370036, 3519506811, 1390346590, 4165412046, 1729882859, 2014283168, 1289243407, 2679198626, 49392930, 921068681, 903443552, 3928862909, 3914934492, 1656987052, 432711693, 1092080705, 1009507400, 3442035405, 2796451416, 178836372, 1341085119, 472247744, 1804872218, 209397624, 3871538735, 2625371000, 275406901, 1757188449, 2669657607, 3604284276, 1912410848, 4250918838, 1504400908, 2246112278, 2284856099, 1017170859, 106995822, 2930347834, 545564822, 1065545923, 3484558996, 3235687826, 1118147092, 564820628, 3004798730, 856304451, 822860516, 3255412373, 398693215, 2329594629, 3107774102, 3795269757, 1827602725, 2395215194, 3203911581, 1655534638, 211158317, 3318323836, 1658306711, 3266378120, 967971461, 3700196933, 4059454123, 641302150, 3758966844, 3400068366, 4198115937, 485338847, 4078693738, 2194750103, 1916610491, 1608221201, 592771197, 305961735, 3496309244, 458632142, 1436284187, 1883874902, 362906529, 38314525, 1950785222, 3918473285, 4280158367, 239076663, 2870128186, 1858894036, 1027494104, 3282242213, 4129496568, 441027295, 2379941678, 2193414438, 2212796476, 2277788540, 3450917896, 1884715287, 4063547227, 1121537361, 1032757188, 272161392, 1784943104, 1790206106, 713995873, 1769042326, 535564457, 178454254, 618864620, 1597799935, 3270467251, 1842808299, 1018709091, 3361794236, 4221130656, 1039251424, 1054506074, 2666864849, 3685051761, 2437756290, 4019119161, 832674533, 2148950955, 2940298749, 1756399996, 1105163896, 1271960636, 3581940733, 4143342134, 3823790830, 3488841246, 3005908556, 1229249490, 2249360558, 1520953855, 2394117874, 2966743152, 1745813079, 3874896381, 4191350629, 3459390903, 458890909, 3016227910, 2882279471, 1489028867, 3561423182, 3768844180, 3613799407, 1316785634, 1110714379, 3825900063, 3005543401, 2578216023, 536834091, 1054735610, 2490400103, 3824100200, 1622334988, 2973431210, 3511057535, 3411074810, 2839293801, 3615424236, 1494356926, 2903750858, 2317164586, 798613884, 2208508524, 1120667415, 459634045, 208258335, 2160960212, 3770793497, 1682162327, 2891358722, 4253581389, 1506921959, 1520649651, 1728239848, 347197154, 1030568701, 231999862, 87543989, 4039870891, 3025487032, 4160936744, 824286621, 619876628, 3974227642, 2732935886, 3410258822, 2406057333, 1165743060, 940866829, 3430451491, 1309520185, 262533243, 947988428, 640974029, 2310827524, 1568049953, 913937604, 523285756, 4019938271, 997714649, 2289745882, 2914301529, 2284035199, 1811643961, 1014663687, 2060371185, 3157474020, 348590874, 2826896064, 1227085771, 547468599, 862186803, 1711960313, 1600420494, 1479186385, 3931860334, 602002980, 2799154778, 1091430947, 3212154168, 1149219740, 3667760717, 1338808890, 2090747344, 3732991295, 242914573, 2349118025, 1074929252, 1578439132, 486000813, 3540915699, 313415647, 1456544360, 2413478967, 1922572049, 3983685868, 1692333399, 2800078402, 3672468944, 941785200, 2799315558, 3495998609, 54827483, 3471966058, 1350080114, 1185538001, 1146752796, 2383192228, 816416261, 1367006476, 824307946, 1275718301, 313125425, 4174575084, 2115741142, 2899939598, 1437334171, 4036006477, 3402338404, 1622118790, 1903918451, 2195630834, 2817175072, 1580143842, 10841607, 2218444240, 328726045, 2172285181, 666198999, 47210791, 217474374, 3425261191, 3792177351, 1102768641, 194832930, 2798628092, 1099023742, 2169630244, 1006780406, 4040150832, 3495364601, 1795130764, 2557506394, 687172551, 1437043653, 596022564, 4124841760, 2832726960, 3976626928, 1940701362, 2129400780, 1335265202, 2623243469, 475218973, 4176790636, 2894028481, 3311380020, 3407731969, 3440303872, 4282973538, 1107580287, 2913854988, 3832450081, 2983552995, 3234935353, 1905487397, 1438250438, 199108879, 1165802593, 3979735320, 292406483, 3789152918, 1728782338, 1538302953, 3095891341, 4067011302, 947270848, 2901984827, 472807909, 1124867728, 967972503, 1179911480, 905593964, 3081206343, 1396858745, 1962485374, 660034736, 2323793427, 135073240, 1624297728, 1102603846, 2597005485, 2882403403, 890183758, 3191082568, 1919982661, 3168083235, 1958438352, 1304175725, 2908775316, 1173988864, 294889039, 4007902026, 1120126077, 1310854594, 546116031, 2848470459, 1869698025, 1813333748, 2963438773, 3933908194, 825386399, 2267683410, 2388979811, 1581641113, 433859520, 3307533954, 3715973826, 3034129662, 1356470162, 2053300467, 3705599280, 3545214348, 881711657, 3370463532, 2612058211, 3022216886, 166079300, 3792395371, 771494606, 367422082, 908499242, 1751065177, 3739297223, 2531239191, 1790567517, 3657254622, 1969671979, 1753491710, 4166832315, 3390847739, 2694228751, 3731820124, 1556938927, 832291283, 2595430255, 3509265058, 1963314910, 743669390, 2316110695, 3553152608, 1539708075, 2581957193, 3581782561, 3733834639, 3874869903, 821452300, 2654378399, 1826247143, 427372641, 2528090922, 3136006832, 716079731, 3725286491, 3774681077, 2364200620, 520438267, 936152988, 1300229995, 3318827623, 893385987, 827395790, 1238576928, 1365658130, 4213726033, 68568077, 1878508859, 2980664309, 2505293566, 647443774, 893999753, 576745315, 3786437080, 408297414, 4253424139, 56347062, 1531788504, 4279766238, 897659733, 588650771, 2281920358, 2662121367, 1247856184, 4077376735, 3094366352, 3475315562, 140900543, 2320176873, 2731282493, 2529550865, 2646680520, 3977230880, 610342446, 1738659355, 2322564480, 1977463984, 3253404512, 3381161114, 4072345980, 3740051219, 2680106281, 3143028156, 3832831863, 1270452360, 127171546, 1648356616, 2300166574, 636625275, 1177009521, 846853350, 1040691569, 2730938915, 71966795, 3559433301, 466808619, 1872187366, 3586382562, 358150119, 1901267937, 1893851852, 3145952136, 3674931561, 1233478860, 40233330, 3052854867, 2874428838, 1759762421, 3681648875, 2015813552, 886942698, 1158156557, 1493555589, 1504676074, 3260453531, 1445680526, 606176540, 3851133425, 3378052885, 290847531, 608022018, 409268527, 2561487059, 552122872, 3296447559, 657047951, 1631287800, 3753000079, 4193809942, 884351757, 650107527, 2377568881, 3347052935, 2286485244, 3723839791, 2320149490, 2621979946, 3594571203, 1034530050, 1013146660, 4171674723, 701670817, 2422914046, 3977354486, 3004818531, 2002938131, 3118226044, 1543549044, 4092997654, 3942653186, 1844763496, 2322984163, 3124918738, 1417239715, 235247237, 1050357214, 2534723786, 4219669748, 4011595633, 2692726487, 2351983087, 2725167432, 1625523175, 4047392192, 2234302489, 2849441834, 3972066233, 1791829507, 939116825, 1749334517, 2363503506, 1794949600, 3554843296, 3658516450, 3792519561, 2851405786, 612179385, 3421837507, 1838122126, 1526446643, 473977778, 970578022, 4289507606, 3575021665, 4054714975, 1548076097, 3509765025, 1066969507, 3153376781, 3298819216, 3889250694, 69259617, 1666832803, 210278288, 3699475297, 3835947114, 3339052234, 612647103, 875803198, 3239057673, 3476910228, 1774715092, 2997268264, 1885163212, 2535759355, 4037082439, 4131425791, 1431931269, 2344841786, 589132544, 3925395746, 784033909, 2001561327, 2875535943, 3682912780, 1098615571, 801194772, 2827770013, 1354890928, 2166517733, 939353793, 872778539, 3631178723, 1264903893, 4095947484, 4181434456, 4200174517, 1474870556, 1627027654, 151292710, 368473093, 3942717951, 819142369, 2349507002, 4074749712, 2489107860, 1097307038, 3020812166, 190306378, 3215127968, 397275036, 2249230863, 443420014, 464013638, 2524035741, 2741857795, 2086019319, 1734459117, 3393166271, 3474161219, 2289897976, 4189280756, 901946899, 1802590992, 2188289127, 2913766496, 1889227592, 3897013662, 1464728618, 2940520918, 2906043873, 2148982467, 2404803587, 894173079, 2495095800, 1534807391, 3036557983, 3313990361, 3092310990, 3745247632, 2003342030, 4001597438, 170941187, 3898936460, 1767517480, 2465767943, 2725934507, 905298257, 2054030074, 1040718227, 130491459, 462307151, 79634941, 39984710, 3394369759, 123808373, 1976379290, 2760361748, 2906583982, 2953946087, 809471573, 2116054715, 3917916932, 2343670492, 3233424199, 774812558, 1756949698, 3194486356, 946191489, 3049294096, 206896940, 2241842324, 2913740804, 2608611645, 2252633590, 1782956542, 2558802876, 189416278, 2914035148, 53575167, 657929910, 2197973107, 1186173886, 1652038937, 1667328710, 3827180894, 1328118528, 627951742, 3852917235, 1261933427, 2796832443, 3909139439, 803119467, 3434493749, 3852387669, 827924266, 4132690149, 261809517, 898612437, 1360913566, 3963554976, 3291202592, 3510814304, 1941420827, 410368266, 1914132178, 4062923120, 1846671715, 3606753265, 3301693690, 2422891416, 4171900211, 1179609418, 3026009073, 1460697318, 81708763, 2241853979, 3184526697, 2433342232, 3825378463, 1733696008, 1589648295, 130255373, 693921782, 1859354595, 1919721838, 1186247508, 4108823444, 77734465, 2629607792, 1076377333, 1990488420, 2937396723, 3004759683, 2318594408, 1150102008, 2213733556, 3220708392, 2308953052, 2749064027, 2085137171, 1117546275, 1886156676, 98424960, 2074093393, 2154503198, 189860005, 2916276379, 1952025216, 3574945482, 3027541861, 3394630765, 3511855818, 3454027741, 2764910997, 3888451786, 1821639450, 208178455, 2500754493, 2116466467, 2562510724, 2236268494, 3533596053, 1136585978, 1638867361, 2351171373, 1768471085, 1475147430, 3007554507, 138204569, 355310868, 514355272, 3368854386, 4017757574, 2764261877, 2324034334, 1307181094, 2699433145, 1799666796, 1658078944, 3051201857, 4064940189, 2720978395, 1229071670, 571398165, 3644846781, 1901207895, 398691399, 2312366555, 933751814, 2120985531, 2216142231, 3139218360, 1909928326, 4233628411, 1909827411, 2995576052, 3808488656, 2242622915, 3933434554, 3788084924, 3334517362, 3266016991, 1568666969, 1229301195, 880438760, 3568043601, 4141504174, 840071256, 426306577, 296537409, 3733271638, 617460425, 4156981489, 1596412970, 2310467087, 3835423522, 4164901542, 2204793257, 644780121, 1452829515, 2477069580, 516109421, 524261758, 117982878, 1282333694, 2307680806, 3224487996, 1113925619, 2143297676, 3177316878, 2381663400, 3278164422, 2125512960, 1035639931, 795806882, 3988921620, 3738216448, 1187094494, 111058657, 1478788191, 1563430022, 3618637339, 247022523, 12616232, ], &[ 2598813973, 1904197782, 1215006787, 2930851058, 147918011, 1108782873, 2193711651, 927233146, 4123817534, 3041706771, 2553964352, 2170557862, 2838589053, 2708835560, 2407955329, 1653207324, 2470552742, 3357058396, 1072990020, 1514783799, 1734243804, 1048851304, 3193592152, 1383793603, 2063694499, 3485786208, 990960024, 3569185429, 1155708496, 1416333121, 623402323, 3585705881, 2928088588, 4117621841, 3292316347, 2217241313, 1950216441, 1391040412, 2926386224, 3240560579, 3973468920, 2847202482, 2728825575, 2388048350, 3463506691, 3707514927, 865702555, 681215612, 2250616248, 1724513618, 364443494, 318451745, 1623887866, 1280032334, 35195442, 3837277484, 3573894817, 1602810477, 2072874171, 3800895590, 4253419440, 3499691102, 3587932863, 3517441378, 514856216, 1648457744, 1474005402, 700069688, 1803098596, 378514692, 3068261379, 3834605983, 93188389, 516236732, 2468656032, 4095977127, 3706578522, 3452719188, 1052956630, 813640425, 3047313546, 754584849, 3584789926, 347367947, 1332536470, 94171148, 626270691, 665836088, 426974652, 749957497, 1566095325, 3066600838, 4106843490, 318006871, 162882344, 3632111614, 720131390, 2147721707, 2217002633, 2466031857, 1087787961, 753159680, 366300446, 3082468114, 3984408901, 4057095635, 851983865, 4150513631, 1165194321, 2055798628, 2975996128, 2693369845, 3726562839, 3482086133, 4069043610, 1448967233, 700979569, 1698695640, 2318799208, 3684286306, 4092668018, 3628416641, 584456626, 1679287620, 1813093480, 177926224, 998082621, 3120492909, 1996199168, 3491975384, 3147828383, 2087111449, 381360867, 1127916110, 3472685226, 3293954452, 490729044, 3264678372, 1277191068, 4239255920, 2343436004, 2451796708, 1844810428, 2031787164, 3768550378, 3743966167, 2637191163, 3978079759, 4158883864, 1561267833, 539304561, 3435817790, 277956235, 4028949085, 2643928548, 2755470882, 3796376394, 194519280, 98463778, 3179299980, 2447702226, 150057260, 3463931601, 906456277, 990239469, 512339370, 2261507614, 2826877099, 3855453279, 2271503686, 841719073, 1591142177, 2651714174, 3361609137, 3279250024, 3326254458, 333896144, 3528172547, 3941409760, 1558812882, 3841874000, 3172301956, 4257828380, 4114850067, 2182891616, 2046840523, 1555755083, 2209766728, 2332501890, 607500373, 4124706810, 1713777506, 2341598661, 2284959418, 2746608689, 867377978, 336903700, 2503448208, 701980251, 2377952035, 614377477, 4284955660, 3814775340, 74129761, 1280559390, 2313692692, 1849232614, 2933185433, 1636271207, 630083065, 433420841, 471362220, 4210050941, 406797277, 582028044, 528813510, 2576049278, 540310007, 2789529550, 3534664845, 3236430259, 1506736021, 1977751182, 2006662671, 3679126532, 3806292929, 322589328, 2243078958, 2178902647, 2189720772, 3791358339, 1508304160, 1013509043, 3587377598, 3623382349, 1086144534, 1599008554, 1093927956, 2876914186, 543927302, 2219667262, 3853928343, 2487266159, 2613372592, 3550686437, 3716813778, 961453654, 2039051889, 4283100852, 3145660844, 1250225831, 198998794, 3726057928, 2284062625, 2219120593, 2244278486, 3790941761, 4203700163, 3879487839, 2965718505, 2863698764, 63056401, 475617471, 399914031, 459648012, 3133447831, 3412742746, 1512219896, 402842103, 4119870394, 2231397283, 1516833787, 1104380754, 128232714, 296865691, 1663298638, 716369560, 2904885147, 4237273250, 343946912, 2604094031, 217784841, 1162604926, 1345215097, 1426555576, 3614102008, 3943750939, 1639058309, 3296139198, 1330339563, 426593850, 1532081057, 1300177557, 1482433791, 812987015, 3232993095, 1037853411, 645052957, 2928052694, 1226934622, 2336175954, 1920836876, 2517428765, 3726338359, 4041660846, 2092081260, 3380258824, 1697518166, 3349439761, 743024530, 1795639086, 1779094250, 503268222, 3554837208, 2986098469, 2762697287, 232864157, 3768291070, 2983947152, 1577288457, 1050740564, 834028049, 1274280907, 3769464765, 1910494593, 2197778112, 2813074316, 2881147492, 1559228213, 1461309572, 1700587844, 2988103759, 1717431083, 951586291, 1707887130, 985013185, 3532658879, 2597699341, 1911327175, 3080664111, 3484272917, 794091071, 2311407322, 342113645, 1768703425, 2382063884, 3831832486, 3217975952, 3451120056, 3035392294, 136312738, 1699608380, 700762772, 3631031559, 1846450824, 1131124755, 1046357323, 2552828340, 2598371768, 795498120, 3174589062, 3838467339, 2334795665, 3324675939, 3403942196, 2075108646, 4259667163, 545251542, 749294402, 3324014447, 1729518387, 3551096145, 1758729590, 2379344936, 2455329109, 1757426268, 1706226190, 902425986, 2432676044, 2039145952, 410402636, 1639537846, 1305863342, 256740017, 3207555620, 3925040779, 668173470, 1141011911, 4212893794, 1581027147, 363670779, 2004465281, 1138726957, 645471449, 3585049231, 2777598154, 2922780411, 2222055902, 3815639175, 429697628, 4000303790, 3545345324, 3542109929, 509705074, 3722614775, 1753809005, 1973665455, 3780943261, 2494678174, 2641931684, 3388813526, 3347201186, 619828405, 2625911693, 3122659421, 3479474745, 3245356132, 1832479544, 3308783684, 1963028441, 640786937, 1641844190, 211570630, 1733515651, 2171524601, 3396267685, 3914881000, 996687218, 1617466047, 3343054134, 1737892381, 3544966831, 3416864496, 107959379, 2249494870, 793869312, 3685840230, 1757287133, 1655716303, 4226516527, 2538565645, 278467613, 2644886589, 2699974905, 1984329139, 1005957589, 789155264, 3666799939, 1611583926, 809907316, 3452803056, 1107204019, 2209104411, 1462179962, 2853352142, 3225410978, 2108213590, 4192481899, 1912371245, 1171525154, 3712460427, 2560727022, 1086797266, 952026066, 685685805, 1936296543, 3499184244, 196202245, 3078070455, 2171291372, 2730765878, 1573851700, 2931331934, 2847177501, 3478529515, 2313080814, 1556316903, 1559216686, 3130885922, 1862119430, 3274978261, 206968409, 2624567354, 1978029702, 4063454216, 2415324407, 1518621963, 747943965, 1111109939, 4070402813, 3113587512, 898431887, 316373197, 3046639257, 173632841, 3798588025, 1794547053, 272903937, 863380298, 2774736392, 2777149271, 3206794646, 32657715, 1025716581, 1615425071, 3173842612, 2073903119, 2153824733, 2329799226, 2341967952, 473768936, 3486256934, 2848218304, 2428724257, 3159637305, 2126501230, 765243196, 3425509759, 1131263732, 2515711177, 3855554546, 1023477320, 787209967, 336492935, 2359162223, 1128313353, 2209616384, 389804749, 535230248, 2210531774, 3227122449, 1267072928, 675693308, 1385601874, 1416098547, 4192675028, 2716632450, 4177948782, 13560634, 3703614488, 3901742123, 2270254077, 3759771486, 581228935, 3949774462, 3458012976, 4163726158, 1602955605, 3047124020, 1612897320, 2437308530, 2370536309, 1561087937, 2116794827, 1579558066, 431023695, 689842616, 2342172842, 4203138565, 2160272314, 4192374041, 3675193896, 1455954294, 3940635994, 4025127357, 4027321239, 1155472117, 1928138697, 1875048682, 4087308487, 4291614860, 1175537429, 3503698743, 2187471558, 2673330725, 2702107217, 2763809959, 2274134903, 1077148334, 2166895545, 1831099412, 3296218829, 2076626325, 1104984380, 1764164194, 3056784327, 1988083103, 3849746178, 3460231757, 3983590507, 1641801163, 1321487487, 2277192156, 1700397327, 4163993314, 118570737, 2510013157, 342313019, 328214482, 1456063300, 3771950632, 1226087686, 2343733178, 1108934200, 3650307976, 118441436, 3857631518, 1808729865, 2826187782, 2596972674, 1966611164, 988201436, 3909729734, 2034457184, 3137580128, 437202273, 1431097330, 2630459633, 2423317302, 1422128850, 3011012632, 3611423092, 3531891566, 1592039994, 734168534, 3492902008, 947200226, 1735249159, 3526990689, 1725556774, 1693403463, 3317454666, 2042191731, 3608995702, 497650714, 628421679, 2465885637, 4008542175, 68576338, 1372104957, 1927020046, 3573635655, 3090117252, 1774561696, 3603424898, 55089895, 2060875413, 116850528, 183816573, 478639013, 3736973628, 3606174188, 3086193394, 2548388100, 2591332019, 3032618195, 469584388, 1770142568, 205800329, 174943950, 260521576, 2114953066, 3428041459, 860714084, 1560598053, 2885505481, 3365355923, 2821218095, 814424502, 94258256, 2857874640, 3213633690, 239445181, 1741311155, 70754202, 469749979, 469377271, 634558134, 1314018935, 2663122712, 3425107874, 616125297, 1220520411, 363320242, 1717903421, 2177377494, 2683338356, 210565640, 3061448891, 1561105018, 3639722552, 2586119577, 264509957, 1416442444, 572448512, 3316197518, 4101471127, 1909662580, 3289492851, 702940172, 1747588119, 3288795988, 1441233966, 678854386, 2604723913, 373703246, 2055937039, 1124872113, 1294098600, 4165350921, 347872377, 4149215174, 3215450946, 3307233717, 3600358822, 2659616884, 552889201, 1684681790, 1821948043, 2909781107, 917768879, 2259947602, 2019396153, 3413299181, 603749894, 2467542574, 4017401393, 2519998741, 1106606352, 2283516402, 4262893045, 931507531, 257221572, 1471379658, 4223521274, 2958168654, 1643148068, 537294061, 3213657938, 3835022365, 3594404173, 777970857, 1918635217, 1702205904, 1047564373, 67547546, 3019489110, 483595975, 4130252917, 3081408781, 436773586, 1982914868, 3527757249, 1553562987, 4080227164, 822023069, 1427193014, 2565421648, 3942884687, 586018307, 1138884595, 2613035769, 486310535, 233458001, 106898418, 170926111, 3212999317, 3194995097, 827548055, 1783632131, 1458445783, 4273893842, 4169283956, 3425898311, 1900133873, 2830934989, 3597188167, 60014629, 2917912426, 3137954804, 1361341056, 4180775481, 946784052, 4199341441, 976101959, 1662997785, 1179237245, 372119531, 2815699743, 2114995295, 3901740963, 3080952004, 938243235, 1717858705, 1880470411, 3714648015, 2698621435, 4276694893, 327245390, 2823511048, 1178264505, 2316760826, 1757942990, 1568677829, 1199580238, 3100459677, 1386893348, 1600406349, 3128791813, 874040538, 2965907285, 8663319, 2919597841, 1169807363, 2130724711, 2817929643, 2594603073, 975728895, 3248945863, 1506505714, 8259384, 2395186489, 64139190, 254403781, 3179528072, 3318835559, 872874473, 3221533853, 1278142055, 2865063695, 2096015856, 3893588672, 1650965167, 852689473, 2456343381, 2227877463, 3533995396, 2567915364, 3260019114, 3354960043, 317493973, 4088542285, 603804423, 3133721086, 2455680365, 2501599681, 2371144161, 4224001882, 3900064951, 2295679614, 483545534, 500738921, 259183629, 2958675979, 3886544014, 3382548497, 1341558649, 764676712, 2686742281, 3585367009, 2470017030, 280649561, 504360831, 3177630390, 691028027, 3630869823, 1850039925, 693186712, 2234334464, 3019783104, 1258253876, 2759186239, 2705660533, 1535024585, 16228098, 3597194253, 3856258376, 2530800309, 1756061934, 3703461702, 1458672824, 3009579190, 325542092, 974024523, 937809905, 180338019, 728257472, 1334683442, 1531729599, 4257819380, 3701291761, 2423233504, 3786098144, 776062663, 3861731850, 3717496633, 2918219359, 2369401162, 1963105504, 2673826226, 3238671093, 568083438, 4121947082, 3892853652, 1632686679, 2302193583, 3211408318, 1938993158, 4122064270, 311269184, 2105346675, 1581174365, 2485158976, 2443260070, 1986431168, 1124848188, 1841087451, 2704521996, 1214274421, 3662035084, 2837679678, 4043497550, 552208260, 1644975825, 1950150273, 4027848966, 4079004873, 647675052, 223752470, 637576072, 949880156, 2749078102, 2043391316, 1008133, 253411434, 3799679907, 238227057, 2495985662, 1475105846, 2961884606, 652180469, 1691635637, 1430944868, 15398684, 2278485165, 3795142783, 2981896799, 1330890913, 2239691223, 407470744, 3702570774, 1624292191, 3703366632, 2187395861, 2415878960, 2303069741, 1369122706, 2750340520, 4035673151, 1425244662, 25186311, 123582970, 2490005251, 936607532, 4115073120, 2730391719, 2823090688, 396451377, 2182998280, 1365726601, 4033770954, 3047868289, 2336389408, 688454315, 1299725781, 3304644284, 4238176839, 3914620151, 3029466942, 3172492309, 1190474536, 569450335, 320580314, 4004925139, 2557991799, 1493351038, 949583033, 3275441062, 1311907795, 106222620, 396788468, 3186456628, 517037899, 2177653619, 370023265, 532558109, 3182151426, 954367771, 2865591818, 600183719, 2521622949, 3079560626, 1906789399, 1612708432, 1801660151, 3565921772, 2688352000, 1101243899, 888006794, 2233649225, 2671500356, 1504445832, 1199168343, 2043022343, 1250919220, 1374956710, 1107550604, 957179006, 3319703903, 4110453611, 3311143947, 2774029776, 1456730624, 1014119593, 3012545941, 1650066434, 3431589287, 3624715486, 1072097915, 3568695028, 478299405, 362822053, 2632030958, 955747917, 2974153651, 2880247593, 2837857407, 1533402093, 1550331006, 3833005459, 111580345, 1694562098, 2731241196, 2659074758, 1347615125, 3711588514, 1514710939, 3788474419, 3668780501, 3266213391, 4081085519, 1196081228, 1049947080, 1820720234, 3100382458, 2198468097, 3708538645, 1035729054, 1784655621, 507574130, 2908640623, 3615200865, 1223546227, 3675568182, 1661330896, 1399689373, 1323389692, 2981922901, 4156332999, 1902241850, 1428680890, 3049572611, 4253261231, 2148214199, 1998921071, 3899443086, 1478235253, 3791927172, 1483896530, 3565485437, 915921912, 2258155251, 3426051958, 3307670857, 3029363090, 3673788309, 4082838999, 624603732, 573907442, 3116664857, 3586999255, 557493850, 1739716128, 2397076308, 2312498391, 767640384, 2119706819, 2637314051, 1070866648, 664107404, 616236779, 3020748367, 4122128780, 2009706384, 3245363034, 429196441, 4195520565, 4209198410, 2158211364, 3659713923, 3985561806, 1747634790, 4115935838, 2827667115, 3073689925, 1621229363, 2774950774, 2538390550, 3506768465, 718261358, 564823729, 380006788, 897186389, 3414352487, 1032216622, 1469922191, 2196317056, 2239269473, 3654751282, 613015420, 4098167098, 1281134924, 849099531, 2523299715, 3904840545, 1997547696, 1158713208, 1289444182, 757815917, 899581875, 3622748533, 3063686656, 2979790776, 1553609204, 355408616, 3897614956, 3680334470, 25191644, 355655308, 111682127, 4053312775, 2921335050, 2200671456, 472639194, 1374183459, 2738441274, 1596829615, 959522853, 1993763998, 1832301144, 2263515976, 993190648, 4045308024, 2213735364, 4061773476, 2596920312, 1929252967, 3935609312, 982934883, 3154772065, 4254233108, 1244999206, 765237459, 2528318166, 1563389556, 2293797399, 3495759008, 48504250, 3182637462, 3138309477, 2147232621, 4810076, 3999234780, 2279064264, 2264522982, 3079929466, 1524222187, 1598294545, 2049273389, 2729549735, 2116985451, 2637892533, 1094214870, 2711414546, 418295062, 98357556, 296649589, 2636445209, 4030461397, 3073508440, 4062358649, 1293566861, 1534697481, 1343281639, 3078259374, 386875427, 1145986442, 1790533181, 2987076845, 237202537, 2194958623, 935119723, 1921262864, 943957815, 2336181341, 2723699978, 1638860845, 2630349960, 431757538, 4152375793, 3473513084, 2603606861, 4176464622, 3978369596, 981482293, 929741839, 2111696471, 571254437, 1419237733, 901791748, 3340393111, 221970895, 2605197016, 22565479, 1000841034, 2192399670, 1207300847, 356824298, 3009617459, 2651652098, 2420275852, 1631602976, 575809994, 2928806259, 2831092106, 2629452482, 2842897182, 1909556662, 2496151886, 3385330607, 957152776, 2804092840, 3551246686, 2730894896, 2027253611, 2531182020, 2258110944, 1391264743, 3902230517, 3835546712, 3424753892, 1147410244, 3448482025, 319341118, 1798380053, 2742193162, 2106010955, 3267048655, 3886107336, 3334600393, 3772435523, 3985863328, 2950255062, 1012493134, 3954831363, 325018235, 2523597002, 2454925521, 2861802043, 4209313262, 3868234463, 1685691511, 2786322255, 4244960817, 1991229419, 4239301712, 576152977, 1652411241, 1589394460, 521549473, 266587858, 961791319, 1146831103, 3469211532, 3501779101, 2312218475, 2321025269, 1346459216, 472196028, 3771324053, 1495430908, 463405457, 1940232183, 3937148918, 1156878514, 2831556660, 1644483662, 1787817713, 2339616130, 3815974485, 2298018558, 71674109, 2675299410, 960845405, 3569711116, 1673611570, 1769369631, 1437416980, 4174063039, 2062712084, 2133844948, 196794643, 1935768058, 1831573341, 1418980930, 3294487604, 3544538744, 2334730191, 3988003806, 2274350901, 2023027498, 3447859831, 1671781771, 4023665101, 1455029189, 2419433622, 2943475311, 4198568768, 1395089836, 1092520718, 2430238564, 437551709, 4097009390, 3375079636, 4154198223, 92070792, 974607811, 3873908092, 3374473679, 638725898, 1249915990, 1085664087, 3927733894, 1217984426, 1825247311, 2107887775, 170602951, 1075337232, 1842870533, 3647067870, 2444592832, 3013106942, 1161476947, 3743427689, 1263482478, 69206560, 833594813, 3842989721, 337909675, 3392484922, 370017251, 27594915, 2126835633, 1736323108, 1893331695, 1468455680, 1075562062, 455344215, 969605531, 294398875, 883453327, 3994410499, 1964955910, 1983678849, 556499140, 2199399388, 1506753515, 2562511167, 573514453, 1452183180, 3758124304, 2276736219, 3962356320, 160602272, 2732947819, 1312555719, 808517807, 1646633687, 4057383018, 1177836167, 2724613618, 724351202, 3082498407, 3292565482, 2024078169, 2339554384, 3963173875, 2223760730, 2562066565, 2193608401, 1812209945, 1665831972, 1039920028, 3410644888, 3314911306, 2847575459, 2005962667, 2392982038, 2769384144, 1673231309, 2605033025, 3097232789, 525491643, 1088675733, 389231889, 4053722369, 1394160319, 920345783, 1695188025, 1313259843, 2855284945, 1128781302, 1711293636, 2436253183, 2702553100, 2342544037, 2382554808, 1645824427, 700888148, 3820471891, 2062002896, 1600256482, 3523617235, 3825142862, 4016136295, 3838255962, 2953276340, 394106186, 956179026, 3512260850, 3001113638, 1645204518, 555542490, 409962126, 479780262, 4202384502, 549252742, 1340551826, 190095025, 2842856010, 446626748, 2565781573, 2172050474, 85422525, 151000070, 2413238086, 224534468, 4102988065, 3524737259, 784974768, 3778660388, 2573449273, 956921977, 1416256526, 3821996527, 1297167173, 2183926071, 2745200336, 1745460864, 399929970, 3271657494, 1058524185, 3138265217, 3822962039, 796872545, 555781465, 3355863387, 4265560398, 2445094472, 546611744, 958064176, 2278895404, 2100057835, 789578969, 387055963, 1153298400, 4065547056, 3688020091, 783181103, 1789734962, 1466117990, 1740574947, 1632230912, 4155788342, 1714025679, 3862124914, 2247239755, 3047057899, 3610673443, 1450313039, 3533121399, 1564221183, 4056883174, 319992191, 598075724, 2438292429, 901314271, 2157273664, 435275402, 1774735757, 177332560, 3010394026, 3827445200, 2002098740, 1897812156, 454287770, 2829500771, 3286056227, 1498747083, 3402858410, 58581019, 1048766033, 1640106396, 3774636176, 1228719792, 1768725616, 3094025701, 3705595233, 2943515149, ], false, ); // - Barrett test(&[8; 70000], &[3; 60000], false); test(&[9; 120000], &[3; 60000], true); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_fail_1() { limbs_divisible_by(&mut [1, 2], &mut [3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_fail_2() { limbs_divisible_by(&mut [], &mut []); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_fail_3() { limbs_divisible_by(&mut [1, 2, 0], &mut [4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_fail_4() { limbs_divisible_by(&mut [1, 2, 3], &mut [4, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_val_ref_fail_1() { limbs_divisible_by_val_ref(&mut [1, 2], &[3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_val_ref_fail_2() { limbs_divisible_by_val_ref(&mut [], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_val_ref_fail_3() { limbs_divisible_by_val_ref(&mut [1, 2, 0], &[4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_val_ref_fail_4() { limbs_divisible_by_val_ref(&mut [1, 2, 3], &[4, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_val_fail_1() { limbs_divisible_by_ref_val(&[1, 2], &mut [3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_val_fail_2() { limbs_divisible_by_ref_val(&[], &mut []); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_val_fail_3() { limbs_divisible_by_ref_val(&[1, 2, 0], &mut [4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_val_fail_4() { limbs_divisible_by_ref_val(&[1, 2, 3], &mut [4, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_ref_fail_1() { limbs_divisible_by_ref_ref(&[1, 2], &[3, 4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_ref_fail_2() { limbs_divisible_by_ref_ref(&[], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_ref_fail_3() { limbs_divisible_by_ref_ref(&[1, 2, 0], &[4, 5]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_divisible_by_ref_ref_fail_4() { limbs_divisible_by_ref_ref(&[1, 2, 3], &[4, 0]); } #[test] fn test_divisible_by() { let test = |s, t, divisible| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.clone().divisible_by(v.clone()), divisible); assert_eq!(u.clone().divisible_by(&v), divisible); assert_eq!((&u).divisible_by(v.clone()), divisible); assert_eq!((&u).divisible_by(&v), divisible); assert_eq!(u == 0 || v != 0 && &u % &v == 0, divisible); assert_eq!( num_divisible_by( &BigUint::from_str(s).unwrap(), &BigUint::from_str(t).unwrap() ), divisible ); assert_eq!( rug::Integer::from_str(s) .unwrap() .is_divisible(&rug::Integer::from_str(t).unwrap()), divisible ); }; test("0", "0", true); test("1", "0", false); test("1000000000000", "0", false); test("0", "1", true); test("0", "123", true); test("1", "1", true); test("123", "1", true); test("123", "123", true); test("123", "456", false); test("456", "123", false); test("369", "123", true); test("4294967295", "1", true); test("4294967295", "4294967295", true); test("1000000000000", "1", true); test("1000000000000", "3", false); test("1000000000002", "3", true); test("1000000000000", "123", false); test("1000000000000", "4294967295", false); test("1000000000000000000000000", "1", true); test("1000000000000000000000000", "3", false); test("1000000000000000000000002", "3", true); test("1000000000000000000000000", "123", false); test("1000000000000000000000000", "4294967295", false); test("1000000000000000000000000", "1000000000000", true); test("1000000000000000000000000", "1000000000001", false); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", true, ); test( "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099788", false, ); test("1", "94815577610368829905234938913859", false); } #[test] fn limbs_divisible_by_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(xs, y)| { let divisible = limbs_divisible_by_limb(&xs, y); assert_eq!( (&Natural::from_limbs_asc(&xs)).divisible_by(Natural::from(y)), divisible ); assert_eq!(limbs_mod_limb::(&xs, y) == 0, divisible); assert_eq!(combined_limbs_divisible_by_limb(&xs, y), divisible); }); } #[test] fn limbs_divisible_by_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_15().test_properties_with_config(&config, |(mut ns, mut ds)| { let ns_old = ns.clone(); let ds_old = ds.clone(); let divisible = limbs_divisible_by(&mut ns, &mut ds); let mut ns = ns_old.clone(); assert_eq!(limbs_divisible_by_val_ref(&mut ns, &ds_old), divisible); let mut ds = ds_old.clone(); assert_eq!(limbs_divisible_by_ref_val(&ns_old, &mut ds), divisible); assert_eq!(limbs_divisible_by_ref_ref(&ns_old, &ds_old), divisible); verify_limbs_divisible_by(&ns_old, &ds_old, divisible); }); unsigned_vec_pair_gen_var_17().test_properties_with_config(&config, |(mut ns, mut ds)| { let ns_old = ns.clone(); let ds_old = ds.clone(); assert!(limbs_divisible_by(&mut ns, &mut ds)); let mut ns = ns_old.clone(); assert!(limbs_divisible_by_val_ref(&mut ns, &ds_old)); let mut ds = ds_old.clone(); assert!(limbs_divisible_by_ref_val(&ns_old, &mut ds)); assert!(limbs_divisible_by_ref_ref(&ns_old, &ds_old)); verify_limbs_divisible_by(&ns_old, &ds_old, true); }); unsigned_vec_pair_gen_var_16().test_properties_with_config(&config, |(ns, ds)| { let divisible = limbs_divisible_by_ref_ref(&ns, &ds); assert_eq!(slice_test_zero(&limbs_mod(&ns, &ds)), divisible); }); } #[test] fn divisible_by_properties() { natural_pair_gen().test_properties(|(x, y)| { let divisible = (&x).divisible_by(&y); assert_eq!((&x).divisible_by(y.clone()), divisible); assert_eq!(x.clone().divisible_by(&y), divisible); assert_eq!(x.clone().divisible_by(y.clone()), divisible); assert_eq!(x == 0 || y != 0 && &x % &y == 0, divisible); assert_eq!( num_divisible_by(&BigUint::from(&x), &BigUint::from(&y)), divisible ); assert_eq!( rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y)), divisible ); }); natural_pair_gen_var_6().test_properties(|(x, y)| { assert!((&x).divisible_by(&y)); assert!(x == 0 || y != 0 && &x % &y == 0); assert!(num_divisible_by(&BigUint::from(&x), &BigUint::from(&y))); assert!(rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y))); }); natural_pair_gen_var_7().test_properties(|(x, y)| { assert!(!(&x).divisible_by(&y)); assert!(x != 0 && (y == 0 || &x % &y != 0)); assert!(!num_divisible_by(&BigUint::from(&x), &BigUint::from(&y))); assert!(!rug::Integer::from(&x).is_divisible(&rug::Integer::from(&y))); }); natural_gen().test_properties(|n| { assert!(n.divisible_by(Natural::ONE)); }); natural_gen_var_2().test_properties(|n| { assert!(!(&n).divisible_by(Natural::ZERO)); assert!(Natural::ZERO.divisible_by(&n)); if n > 1 { assert!(!Natural::ONE.divisible_by(&n)); } assert!((&n).divisible_by(&n)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( Natural::from(x).divisible_by(Natural::from(y)), x.divisible_by(y) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/divisible_by_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::DivisibleByPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_20, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::divisible_by_power_of_2::limbs_divisible_by_power_of_2; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_9, natural_unsigned_pair_gen_var_10, }; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_divisible_by_power_of_2() { let test = |xs: &[Limb], pow: u64, out: bool| { assert_eq!(limbs_divisible_by_power_of_2(xs, pow), out); }; test(&[1], 0, true); test(&[1], 1, false); test(&[2], 0, true); test(&[2], 1, true); test(&[2], 2, false); test(&[3], 1, false); test(&[122, 456], 1, true); test(&[0, 0, 1], 64, true); test(&[0, 0, 1], 65, false); test(&[0, 0, 1], 100, false); test(&[3567587328, 232], 11, true); test(&[3567587328, 232], 12, true); test(&[3567587328, 232], 13, false); } #[test] fn test_divisible_by_power_of_2() { let test = |n, pow, out| { assert_eq!( Natural::from_str(n).unwrap().divisible_by_power_of_2(pow), out ); assert_eq!( rug::Integer::from_str(n) .unwrap() .is_divisible_2pow(u32::exact_from(pow)), out ); }; test("0", 0, true); test("0", 10, true); test("0", 100, true); test("123", 0, true); test("123", 1, false); test("1000000000000", 0, true); test("1000000000000", 12, true); test("1000000000000", 13, false); test("4294967295", 0, true); test("4294967295", 1, false); test("4294967296", 0, true); test("4294967296", 32, true); test("4294967296", 33, false); test("18446744073709551615", 0, true); test("18446744073709551615", 1, false); test("18446744073709551616", 0, true); test("18446744073709551616", 64, true); test("18446744073709551616", 65, false); } #[test] fn limbs_divisible_by_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( limbs_divisible_by_power_of_2(&xs, pow), Natural::from_owned_limbs_asc(xs).divisible_by_power_of_2(pow), ); }); } #[test] fn divisible_by_power_of_2_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(x, pow)| { let divisible = x.divisible_by_power_of_2(pow); assert_eq!( rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow)), divisible ); if x != 0 { assert_eq!(x.trailing_zeros().unwrap() >= pow, divisible); } assert_eq!((-&x).divisible_by_power_of_2(pow), divisible); assert!((&x << pow).divisible_by_power_of_2(pow)); assert_eq!(&x >> pow << pow == x, divisible); }); natural_unsigned_pair_gen_var_9().test_properties(|(x, pow)| { assert!(x.divisible_by_power_of_2(pow)); assert!(rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow))); if x != 0 { assert!(x.trailing_zeros().unwrap() >= pow); } assert!((-&x).divisible_by_power_of_2(pow)); assert_eq!(&x >> pow << pow, x); }); natural_unsigned_pair_gen_var_10().test_properties(|(x, pow)| { assert!(!x.divisible_by_power_of_2(pow)); assert!(!rug::Integer::from(&x).is_divisible_2pow(u32::exact_from(pow))); if x != 0 { assert!(x.trailing_zeros().unwrap() < pow); } assert!(!(-&x).divisible_by_power_of_2(pow)); assert_ne!(&x >> pow << pow, x); }); natural_gen().test_properties(|x| { assert!(x.divisible_by_power_of_2(0)); }); unsigned_gen().test_properties(|pow| { assert!(Natural::ZERO.divisible_by_power_of_2(pow)); }); unsigned_pair_gen_var_2::().test_properties(|(x, pow)| { assert_eq!( x.divisible_by_power_of_2(pow), Natural::from(x).divisible_by_power_of_2(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/eq_mod.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, EqMod}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_19, unsigned_triple_gen_var_21, unsigned_vec_triple_gen_var_36, unsigned_vec_unsigned_unsigned_triple_gen_var_7, unsigned_vec_unsigned_unsigned_triple_gen_var_10, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::eq_mod::{ limbs_eq_limb_mod, limbs_eq_limb_mod_limb, limbs_eq_limb_mod_ref_ref, limbs_eq_limb_mod_ref_val, limbs_eq_limb_mod_val_ref, limbs_eq_mod_limb_ref_ref, limbs_eq_mod_limb_ref_val, limbs_eq_mod_limb_val_ref, limbs_eq_mod_ref_ref_ref, limbs_eq_mod_ref_ref_val, limbs_eq_mod_ref_val_ref, limbs_eq_mod_ref_val_val, limbs_limb_mod_exact_odd_limb, limbs_mod_exact_odd_limb, }; use malachite_nz::natural::arithmetic::mod_op::limbs_mod_limb; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ natural_pair_gen, natural_triple_gen, natural_triple_gen_var_1, natural_triple_gen_var_2, unsigned_vec_triple_gen_var_54, unsigned_vec_triple_gen_var_55, unsigned_vec_unsigned_unsigned_triple_gen_var_11, unsigned_vec_unsigned_unsigned_triple_gen_var_12, unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4, unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_16, }; use malachite_nz::test_util::natural::arithmetic::eq_mod::{ combined_limbs_eq_limb_mod_limb, limbs_eq_limb_mod_naive_1, limbs_eq_limb_mod_naive_2, limbs_eq_mod_limb_naive_1, limbs_eq_mod_limb_naive_2, limbs_eq_mod_naive_1, limbs_eq_mod_naive_2, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_limb_mod_limb() { let test = |xs: &[Limb], y: Limb, m: Limb, equal: bool| { assert_eq!(limbs_eq_limb_mod_limb(xs, y, m), equal); assert_eq!(limbs_mod_limb::(xs, m) == y % m, equal); assert_eq!(combined_limbs_eq_limb_mod_limb(xs, y, m), equal); }; test(&[6, 7], 4, 2, true); test(&[7, 7], 4, 2, false); test(&[6, 7], 3, 2, false); test(&[7, 7], 3, 2, true); test(&[2, 2], 7, 13, true); test(&[100, 101, 102], 1238, 10, true); test(&[100, 101, 102], 1239, 10, false); test(&[123, 456], 636, 789, true); test(&[123, 456], 1000, 789, false); test(&[u32::MAX, u32::MAX], 101, 2, true); test(&[u32::MAX, u32::MAX], 100, 2, false); test(&[u32::MAX, u32::MAX], 120, 3, true); test(&[u32::MAX, u32::MAX], 110, 3, false); test( &[ 957355272, 2717966866, 2284391330, 238149753, 3607703304, 23463007, 1388955612, 3269479240, 881285075, 2493741919, 360635652, 2851492229, 3590429614, 2528168680, 215334077, 3509222230, 1825157855, 3737409852, 4151389929, 2692167062, 1409227805, 2060445344, 1453537438, 3186146035, 1159656442, 954576963, 2935313630, 2288694644, 400433986, 3182217800, 3929694465, 3346806449, 131165877, ], 1529684314, 1469269654, false, ); test( &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 3221225472, 63, 0, 0, 0, 0, 0, 0, 0, 4294443008, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], 0xfffff000, u32::MAX, false, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_limb_fail_1() { limbs_eq_limb_mod_limb(&[10], 10, 15); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_limb_fail_2() { limbs_eq_limb_mod_limb(&[6, 7], 4, 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_limb_mod() { let test = |xs: &[Limb], y: Limb, ms: &[Limb], equal: bool| { let mut mut_xs = xs.to_vec(); let mut mut_ms = ms.to_vec(); assert_eq!(limbs_eq_limb_mod(&mut mut_xs, y, &mut mut_ms), equal); let mut mut_xs = xs.to_vec(); assert_eq!(limbs_eq_limb_mod_val_ref(&mut mut_xs, y, ms), equal); let mut mut_ms = ms.to_vec(); assert_eq!(limbs_eq_limb_mod_ref_val(xs, y, &mut mut_ms), equal); assert_eq!(limbs_eq_limb_mod_ref_ref(xs, y, ms), equal); assert_eq!(limbs_eq_limb_mod_naive_1(xs, y, ms), equal); assert_eq!(limbs_eq_limb_mod_naive_2(xs, y, ms), equal); }; // - xs[0].eq_mod_power_of_2(y, u64::from(m_trailing_zeros)) // - m_len != 2 || m_0 == 0 test(&[1, 1], 1, &[0, 1], true); // - m_len == 2 && m_0 != 0 // - m_1 < 1 << m_trailing_zeros // - x_len < BMOD_1_TO_MOD_1_THRESHOLD test(&[0, 1], 2, &[2, 1], false); // - x_len >= BMOD_1_TO_MOD_1_THRESHOLD // - y_0 < m_0 test(&[6; 40], 2, &[2, 1], false); // - y_0 >= m_0 test(&[6; 40], 0x80000002, &[2, 1], false); // - !xs[0].eq_mod_power_of_2(y, u64::from(m_trailing_zeros)) test(&[0, 1], 1, &[0, 1], false); // - m_1 >= 1 << m_trailing_zeros test(&[0, 1], 1, &[1, 1], false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_fail_1() { limbs_eq_limb_mod(&mut [1], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_fail_2() { limbs_eq_limb_mod(&mut [1, 1], 1, &mut [1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_fail_3() { limbs_eq_limb_mod(&mut [1, 0], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_fail_4() { limbs_eq_limb_mod(&mut [1, 1], 0, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_fail_5() { limbs_eq_limb_mod(&mut [1, 1], 1, &mut [1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_val_ref_fail_1() { limbs_eq_limb_mod_val_ref(&mut [1], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_val_ref_fail_2() { limbs_eq_limb_mod_val_ref(&mut [1, 1], 1, &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_val_ref_fail_3() { limbs_eq_limb_mod_val_ref(&mut [1, 0], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_val_ref_fail_4() { limbs_eq_limb_mod_val_ref(&mut [1, 1], 0, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_val_ref_fail_5() { limbs_eq_limb_mod_val_ref(&mut [1, 1], 1, &[1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_val_fail_1() { limbs_eq_limb_mod_ref_val(&[1], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_val_fail_2() { limbs_eq_limb_mod_ref_val(&[1, 1], 1, &mut [1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_val_fail_3() { limbs_eq_limb_mod_ref_val(&[1, 0], 1, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_val_fail_4() { limbs_eq_limb_mod_ref_val(&[1, 1], 0, &mut [0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_val_fail_5() { limbs_eq_limb_mod_ref_val(&[1, 1], 1, &mut [1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_ref_fail_1() { limbs_eq_limb_mod_ref_ref(&[1], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_ref_fail_2() { limbs_eq_limb_mod_ref_ref(&[1, 1], 1, &[1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_ref_fail_3() { limbs_eq_limb_mod_ref_ref(&[1, 0], 1, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_ref_fail_4() { limbs_eq_limb_mod_ref_ref(&[1, 1], 0, &[0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_limb_mod_ref_ref_fail_5() { limbs_eq_limb_mod_ref_ref(&[1, 1], 1, &[1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_mod_limb() { let test = |xs: &[Limb], ys: &[Limb], m: Limb, equal: bool| { let mut mut_xs = xs.to_vec(); assert_eq!(limbs_eq_mod_limb_val_ref(&mut mut_xs, ys, m), equal); let mut mut_ys = ys.to_vec(); assert_eq!(limbs_eq_mod_limb_ref_val(xs, &mut mut_ys, m), equal); assert_eq!(limbs_eq_mod_limb_ref_ref(xs, ys, m), equal); assert_eq!(limbs_eq_mod_limb_naive_1(xs, ys, m), equal); assert_eq!(limbs_eq_mod_limb_naive_2(xs, ys, m), equal); }; // - xs != ys in limbs_eq_mod_limb_greater // - xs[0].eq_mod_power_of_2(ys[0], u64::from(m.trailing_zeros())) in limbs_eq_mod_limb_greater // - limbs_cmp(xs, ys) < Equal in limbs_eq_mod_limb_greater // - scratch.len() > 1 in limbs_eq_mod_limb_greater test(&[1, 1], &[3, 4], 5, true); // - xs == ys in limbs_eq_mod_limb_greater test(&[0, 1], &[0, 1], 1, true); // - limbs_cmp(xs, ys) >= Equal in limbs_eq_mod_limb_greater test(&[0, 0, 1], &[0, 1], 1, true); // - scratch.len() == 1 in limbs_eq_mod_limb_greater test(&[0, 1], &[1, 1], 1, true); // - !xs[0].eq_mod_power_of_2(ys[0], u64::from(m.trailing_zeros())) in limbs_eq_mod_limb_greater test(&[0, 1], &[1, 1], 2, false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_val_ref_fail_1() { limbs_eq_mod_limb_val_ref(&mut [1], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_val_ref_fail_2() { limbs_eq_mod_limb_val_ref(&mut [1, 1], &[4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_val_ref_fail_3() { limbs_eq_mod_limb_val_ref(&mut [1, 0], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_val_ref_fail_4() { limbs_eq_mod_limb_val_ref(&mut [1, 1], &[3, 0], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_val_ref_fail_5() { limbs_eq_mod_limb_val_ref(&mut [1, 1], &[3, 4], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_val_fail_1() { limbs_eq_mod_limb_ref_val(&[1], &mut [3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_val_fail_2() { limbs_eq_mod_limb_ref_val(&[1, 1], &mut [4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_val_fail_3() { limbs_eq_mod_limb_ref_val(&[1, 0], &mut [3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_val_fail_4() { limbs_eq_mod_limb_ref_val(&[1, 1], &mut [3, 0], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_val_fail_5() { limbs_eq_mod_limb_ref_val(&[1, 1], &mut [3, 4], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_ref_fail_1() { limbs_eq_mod_limb_ref_ref(&[1], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_ref_fail_2() { limbs_eq_mod_limb_ref_ref(&[1, 1], &[4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_ref_fail_3() { limbs_eq_mod_limb_ref_ref(&[1, 0], &[3, 4], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_ref_fail_4() { limbs_eq_mod_limb_ref_ref(&[1, 1], &[3, 0], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_limb_ref_ref_fail_5() { limbs_eq_mod_limb_ref_ref(&[1, 1], &[3, 4], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_mod_ref_ref_ref() { let test = |xs: &[Limb], ys: &[Limb], ms: &[Limb], equal: bool| { let mut mut_ys = ys.to_vec(); let mut mut_ms = ms.to_vec(); assert_eq!( limbs_eq_mod_ref_val_val(xs, &mut mut_ys, &mut mut_ms), equal ); let mut mut_ys = ys.to_vec(); assert_eq!(limbs_eq_mod_ref_val_ref(xs, &mut mut_ys, ms), equal); let mut mut_ms = ms.to_vec(); assert_eq!(limbs_eq_mod_ref_ref_val(xs, ys, &mut mut_ms), equal); assert_eq!(limbs_eq_mod_ref_ref_ref(xs, ys, ms), equal); assert_eq!(limbs_eq_mod_naive_1(xs, ys, ms), equal); assert_eq!(limbs_eq_mod_naive_2(xs, ys, ms), equal); }; // - xs != ys in limbs_eq_mod_greater // - xs[0].eq_mod_power_of_2(ys[0], u64::from(ms[0].trailing_zeros())) in limbs_eq_mod_greater // - limbs_cmp(xs, ys) == Less test(&[1, 1, 1], &[1, 0, 3], &[0, 7], true); // - !xs[0].eq_mod_power_of_2(ys[0], u64::from(ms[0].trailing_zeros())) in limbs_eq_mod_greater test(&[0, 1, 1], &[1, 0, 3], &[0, 7], false); // - limbs_cmp(xs, ys) >= Equal test(&[1, 3], &[1, 1, 2], &[0, 5], true); // - xs == ys in limbs_eq_mod_greater test(&[0, 1], &[0, 1], &[0, 1], true); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_1() { limbs_eq_mod_ref_val_val(&[1], &mut [1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_2() { limbs_eq_mod_ref_val_val(&[1, 1, 1], &mut [1], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_3() { limbs_eq_mod_ref_val_val(&[1, 1, 1], &mut [1, 0, 3], &mut [7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_4() { limbs_eq_mod_ref_val_val(&[1, 1, 0], &mut [1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_5() { limbs_eq_mod_ref_val_val(&[1, 1, 1], &mut [1, 0, 0], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_val_fail_6() { limbs_eq_mod_ref_val_val(&[1, 1, 1], &mut [1, 0, 3], &mut [7, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_1() { limbs_eq_mod_ref_val_ref(&[1], &mut [1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_2() { limbs_eq_mod_ref_val_ref(&[1, 1, 1], &mut [1], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_3() { limbs_eq_mod_ref_val_ref(&[1, 1, 1], &mut [1, 0, 3], &[7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_4() { limbs_eq_mod_ref_val_ref(&[1, 1, 0], &mut [1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_5() { limbs_eq_mod_ref_val_ref(&[1, 1, 1], &mut [1, 0, 0], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_val_ref_fail_6() { limbs_eq_mod_ref_val_ref(&[1, 1, 1], &mut [1, 0, 3], &[7, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_1() { limbs_eq_mod_ref_ref_val(&[1], &[1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_2() { limbs_eq_mod_ref_ref_val(&[1, 1, 1], &[1], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_3() { limbs_eq_mod_ref_ref_val(&[1, 1, 1], &[1, 0, 3], &mut [7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_4() { limbs_eq_mod_ref_ref_val(&[1, 1, 0], &[1, 0, 3], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_5() { limbs_eq_mod_ref_ref_val(&[1, 1, 1], &[1, 0, 0], &mut [0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_val_fail_6() { limbs_eq_mod_ref_ref_val(&[1, 1, 1], &[1, 0, 3], &mut [7, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_1() { limbs_eq_mod_ref_ref_ref(&[1], &[1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_2() { limbs_eq_mod_ref_ref_ref(&[1, 1, 1], &[1], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_3() { limbs_eq_mod_ref_ref_ref(&[1, 1, 1], &[1, 0, 3], &[7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_4() { limbs_eq_mod_ref_ref_ref(&[1, 1, 0], &[1, 0, 3], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_5() { limbs_eq_mod_ref_ref_ref(&[1, 1, 1], &[1, 0, 0], &[0, 7]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_eq_mod_ref_ref_ref_fail_6() { limbs_eq_mod_ref_ref_ref(&[1, 1, 1], &[1, 0, 3], &[7, 0]); } #[test] fn test_eq_mod() { let test = |r, s, t, out| { let x = Natural::from_str(r).unwrap(); let y = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert_eq!(x.clone().eq_mod(y.clone(), m.clone()), out); assert_eq!(x.clone().eq_mod(y.clone(), &m), out); assert_eq!(x.clone().eq_mod(&y, m.clone()), out); assert_eq!(x.clone().eq_mod(&y, &m), out); assert_eq!((&x).eq_mod(y.clone(), m.clone()), out); assert_eq!((&x).eq_mod(y.clone(), &m), out); assert_eq!((&x).eq_mod(&y, m.clone()), out); assert_eq!((&x).eq_mod(&y, &m), out); assert_eq!(y.eq_mod(x, m), out); assert_eq!( rug::Integer::from_str(r).unwrap().is_congruent( &rug::Integer::from_str(s).unwrap(), &rug::Integer::from_str(t).unwrap() ), out ); }; test("0", "0", "0", true); test("0", "1", "0", false); test("57", "57", "0", true); test("57", "58", "0", false); test("1000000000000", "57", "0", false); test("0", "256", "256", true); test("0", "256", "512", false); test("13", "23", "10", true); test("13", "24", "10", false); test("13", "21", "1", true); test("13", "21", "2", true); test("13", "21", "4", true); test("13", "21", "8", true); test("13", "21", "16", false); test("13", "21", "3", false); test("1000000000001", "1", "4096", true); test("1000000000001", "1", "8192", false); test("12345678987654321", "321", "1000", true); test("12345678987654321", "322", "1000", false); test("1234", "1234", "1000000000000", true); test("1234", "1235", "1000000000000", false); test("1000000001234", "1000000002234", "1000", true); test("1000000001234", "1000000002235", "1000", false); test("1000000001234", "1234", "1000000000000", true); test("1000000001234", "1235", "1000000000000", false); test("1000000001234", "5000000001234", "1000000000000", true); test("1000000001234", "5000000001235", "1000000000000", false); } #[test] fn limbs_limb_mod_exact_odd_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_triple_gen_var_21().test_properties_with_config(&config, |(n, d, carry)| { let r = Natural::from(limbs_limb_mod_exact_odd_limb(n, d, carry)); assert_eq!(n.eq_mod(carry, d), r == 0); assert!(r <= d); if carry < d { assert!(r < d); } let a = Natural::from(n); let d = Natural::from(d); let carry = Natural::from(carry); assert!(((&r << Limb::WIDTH) + &a).eq_mod(&carry, &d) || (r + a).eq_mod(carry, d)); }); } #[test] fn limbs_mod_exact_odd_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_10().test_properties_with_config( &config, |(ns, d, carry)| { let r = Natural::from(limbs_mod_exact_odd_limb(&ns, d, carry)); assert!(r <= d); if carry < d { assert!(r < d); } let ns_len = u64::exact_from(ns.len()); let a = Natural::from_owned_limbs_asc(ns); let d = Natural::from(d); let carry = Natural::from(carry); assert_eq!((&a).eq_mod(&carry, &d), r == 0 || r == d); let p_1 = &r << (ns_len * Limb::WIDTH); let p_2 = r << ((ns_len - 1) * Limb::WIDTH); assert!((p_1 + &a).eq_mod(&carry, &d) || (p_2 + a).eq_mod(carry, d)); }, ); } #[test] fn limbs_eq_limb_mod_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_7().test_properties_with_config( &config, |(xs, y, m)| { let equal = limbs_eq_limb_mod_limb(&xs, y, m); assert_eq!( Natural::from_limbs_asc(&xs).eq_mod(Natural::from(y), Natural::from(m)), equal ); assert_eq!(limbs_mod_limb::(&xs, m) == y % m, equal); assert_eq!(combined_limbs_eq_limb_mod_limb(&xs, y, m), equal); }, ); unsigned_vec_unsigned_unsigned_triple_gen_var_11().test_properties_with_config( &config, |(xs, y, m)| { assert!(limbs_eq_limb_mod_limb(&xs, y, m)); assert!(Natural::from_limbs_asc(&xs).eq_mod(Natural::from(y), Natural::from(m))); assert_eq!(limbs_mod_limb::(&xs, m), y % m); assert!(combined_limbs_eq_limb_mod_limb(&xs, y, m)); }, ); unsigned_vec_unsigned_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(xs, y, m)| { assert!(!limbs_eq_limb_mod_limb(&xs, y, m)); assert!(!Natural::from_limbs_asc(&xs).eq_mod(Natural::from(y), Natural::from(m))); assert_ne!(limbs_mod_limb::(&xs, m), y % m); assert!(!combined_limbs_eq_limb_mod_limb(&xs, y, m)); }, ); } #[test] fn limbs_eq_limb_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().test_properties_with_config( &config, |(xs, ms, y)| { let equal = limbs_eq_limb_mod_ref_ref(&xs, y, &ms); let mut mut_xs = xs.clone(); let mut mut_ms = ms.clone(); assert_eq!(limbs_eq_limb_mod(&mut mut_xs, y, &mut mut_ms), equal); let mut mut_xs = xs.clone(); assert_eq!(limbs_eq_limb_mod_val_ref(&mut mut_xs, y, &ms), equal); let mut mut_ms = ms.clone(); assert_eq!(limbs_eq_limb_mod_ref_val(&xs, y, &mut mut_ms), equal); assert_eq!( Natural::from_limbs_asc(&xs).eq_mod(Natural::from(y), Natural::from_limbs_asc(&ms)), equal ); assert_eq!(limbs_eq_limb_mod_naive_1(&xs, y, &ms), equal); assert_eq!(limbs_eq_limb_mod_naive_2(&xs, y, &ms), equal); }, ); unsigned_vec_unsigned_unsigned_vec_triple_gen_var_4().test_properties_with_config( &config, |(xs, y, ms)| { assert!( Natural::from_limbs_asc(&xs).eq_mod(Natural::from(y), Natural::from_limbs_asc(&ms)) ); assert!(limbs_eq_limb_mod_ref_ref(&xs, y, &ms)); assert!(limbs_eq_limb_mod_naive_1(&xs, y, &ms)); assert!(limbs_eq_limb_mod_naive_2(&xs, y, &ms)); }, ); unsigned_vec_unsigned_unsigned_vec_triple_gen_var_5().test_properties_with_config( &config, |(xs, y, ms)| { assert!( !Natural::from_limbs_asc(&xs) .eq_mod(Natural::from(y), Natural::from_limbs_asc(&ms)) ); assert!(!limbs_eq_limb_mod_ref_ref(&xs, y, &ms)); assert!(!limbs_eq_limb_mod_naive_1(&xs, y, &ms)); assert!(!limbs_eq_limb_mod_naive_2(&xs, y, &ms)); }, ); } #[test] fn limbs_eq_mod_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_6().test_properties_with_config( &config, |(xs, ys, m)| { let equal = limbs_eq_mod_limb_ref_ref(&xs, &ys, m); let mut mut_xs = xs.clone(); assert_eq!(limbs_eq_mod_limb_val_ref(&mut mut_xs, &ys, m), equal); let mut mut_ys = ys.clone(); assert_eq!(limbs_eq_mod_limb_ref_val(&xs, &mut mut_ys, m), equal); assert_eq!( Natural::from_limbs_asc(&xs).eq_mod(Natural::from_limbs_asc(&ys), Natural::from(m)), equal ); assert_eq!(limbs_eq_mod_limb_naive_1(&xs, &ys, m), equal); assert_eq!(limbs_eq_mod_limb_naive_2(&xs, &ys, m), equal); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_15().test_properties_with_config( &config, |(xs, ys, m)| { assert!( Natural::from_limbs_asc(&xs).eq_mod(Natural::from_limbs_asc(&ys), Natural::from(m)) ); assert!(limbs_eq_mod_limb_ref_ref(&xs, &ys, m)); assert!(limbs_eq_mod_limb_naive_1(&xs, &ys, m)); assert!(limbs_eq_mod_limb_naive_2(&xs, &ys, m)); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_16().test_properties_with_config( &config, |(xs, ys, m)| { assert!( !Natural::from_limbs_asc(&xs) .eq_mod(Natural::from_limbs_asc(&ys), Natural::from(m)) ); assert!(!limbs_eq_mod_limb_ref_ref(&xs, &ys, m)); assert!(!limbs_eq_mod_limb_naive_1(&xs, &ys, m)); assert!(!limbs_eq_mod_limb_naive_2(&xs, &ys, m)); }, ); } #[test] fn limbs_eq_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_36().test_properties_with_config(&config, |(xs, ys, ms)| { let equal = limbs_eq_mod_ref_ref_ref(&xs, &ys, &ms); let mut mut_ys = ys.clone(); let mut mut_ms = ms.clone(); assert_eq!( limbs_eq_mod_ref_val_val(&xs, &mut mut_ys, &mut mut_ms), equal ); let mut mut_ys = ys.clone(); assert_eq!(limbs_eq_mod_ref_val_ref(&xs, &mut mut_ys, &ms), equal); let mut mut_ms = ms.clone(); assert_eq!(limbs_eq_mod_ref_ref_val(&xs, &ys, &mut mut_ms), equal); assert_eq!( Natural::from_limbs_asc(&xs) .eq_mod(Natural::from_limbs_asc(&ys), Natural::from_limbs_asc(&ms)), equal ); assert_eq!(limbs_eq_mod_naive_1(&xs, &ys, &ms), equal); assert_eq!(limbs_eq_mod_naive_2(&xs, &ys, &ms), equal); }); unsigned_vec_triple_gen_var_54().test_properties_with_config(&config, |(xs, ys, ms)| { assert!( Natural::from_limbs_asc(&xs) .eq_mod(Natural::from_limbs_asc(&ys), Natural::from_limbs_asc(&ms)) ); assert!(limbs_eq_mod_ref_ref_ref(&xs, &ys, &ms)); assert!(limbs_eq_mod_naive_1(&xs, &ys, &ms)); assert!(limbs_eq_mod_naive_2(&xs, &ys, &ms)); }); unsigned_vec_triple_gen_var_55().test_properties_with_config(&config, |(xs, ys, ms)| { assert!( !Natural::from_limbs_asc(&xs) .eq_mod(Natural::from_limbs_asc(&ys), Natural::from_limbs_asc(&ms)) ); assert!(!limbs_eq_mod_ref_ref_ref(&xs, &ys, &ms)); assert!(!limbs_eq_mod_naive_1(&xs, &ys, &ms)); assert!(!limbs_eq_mod_naive_2(&xs, &ys, &ms)); }); } #[test] fn eq_mod_properties() { natural_triple_gen().test_properties(|(x, y, m)| { let equal = (&x).eq_mod(&y, &m); assert_eq!((&y).eq_mod(&x, &m), equal); assert_eq!((&x).eq_mod(&y, m.clone()), equal); assert_eq!((&x).eq_mod(y.clone(), &m), equal); assert_eq!((&x).eq_mod(y.clone(), m.clone()), equal); assert_eq!(x.clone().eq_mod(&y, &m), equal); assert_eq!(x.clone().eq_mod(&y, m.clone()), equal); assert_eq!(x.clone().eq_mod(y.clone(), &m), equal); assert_eq!(x.clone().eq_mod(y.clone(), m.clone()), equal); assert_eq!( (Integer::from(&x) - Integer::from(&y)).divisible_by(Integer::from(&m)), equal ); assert_eq!( (Integer::from(&y) - Integer::from(&x)).divisible_by(Integer::from(&m)), equal ); assert_eq!( rug::Integer::from(&x).is_congruent(&rug::Integer::from(&y), &rug::Integer::from(&m)), equal ); }); natural_triple_gen_var_1().test_properties(|(x, y, m)| { assert!((&x).eq_mod(&y, &m)); assert!((&y).eq_mod(&x, &m)); assert!( rug::Integer::from(&x).is_congruent(&rug::Integer::from(&y), &rug::Integer::from(&m)) ); }); natural_triple_gen_var_2().test_properties(|(x, y, m)| { assert!(!(&x).eq_mod(&y, &m)); assert!(!(&y).eq_mod(&x, &m)); assert!( !rug::Integer::from(&x).is_congruent(&rug::Integer::from(&y), &rug::Integer::from(&m)) ); }); natural_pair_gen().test_properties(|(x, y)| { assert!((&x).eq_mod(&y, Natural::ONE)); assert_eq!((&x).eq_mod(Natural::ZERO, &y), (&x).divisible_by(&y)); assert!((&x).eq_mod(&x, &y)); assert_eq!((&x).eq_mod(&y, Natural::ZERO), x == y); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, m)| { assert_eq!( Natural::from(x).eq_mod(Natural::from(y), Natural::from(m)), x.eq_mod(y, m) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/eq_mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, EqModPowerOf2, ModPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_4, unsigned_vec_unsigned_unsigned_triple_gen_var_8, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::eq_mod_power_of_2::{ limbs_eq_limb_mod_power_of_2, limbs_eq_mod_power_of_2, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_natural_unsigned_quadruple_gen_var_1, natural_natural_unsigned_triple_gen_var_1, natural_natural_unsigned_triple_gen_var_2, natural_natural_unsigned_triple_gen_var_3, natural_pair_gen, natural_unsigned_pair_gen_var_4, }; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_limb_mod_power_of_2() { let test = |xs, y, pow, out| { assert_eq!(limbs_eq_limb_mod_power_of_2(xs, y, pow), out); }; test(&[0b1111011, 0b111001000], 0b101011, 4, true); test(&[0b1111011, 0b111001000], 0b101011, 5, false); test(&[0b1111011, 0b111001000], 0b1111011, 35, true); test(&[0b1111011, 0b111001000], 0b1111011, 36, false); test(&[0b1111011, 0b111001000], 0b1111011, 100, false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_eq_mod_power_of_2() { let test = |xs, ys, pow, out| { assert_eq!(limbs_eq_mod_power_of_2(xs, ys, pow), out); }; test(&[0b1111011, 0b111001000], &[0b101011], 4, true); test(&[0b1111011, 0b111001000], &[0b101011], 5, false); test(&[0b1111011, 0b111001000], &[0b1111011], 35, true); test(&[0b1111011, 0b111001000], &[0b1111011], 36, false); test(&[0b1111011, 0b111001000], &[0b1111011], 100, false); test( &[0b1111011, 0b111001000], &[0b1111011, 0b111101000], 37, true, ); test( &[0b1111011, 0b111001000], &[0b1111011, 0b111101000], 38, false, ); test( &[0b1111011, 0b111001000], &[0b1111011, 0b111101000], 100, false, ); } #[test] fn test_eq_mod_power_of_2() { let test = |x, y, pow, out| { assert_eq!( Natural::from_str(x) .unwrap() .eq_mod_power_of_2(&Natural::from_str(y).unwrap(), pow), out ); assert_eq!( rug::Integer::from_str(x) .unwrap() .is_congruent_2pow(&rug::Integer::from_str(y).unwrap(), u32::exact_from(pow)), out ); }; test("0", "256", 8, true); test("0", "256", 9, false); test("13", "21", 0, true); test("13", "21", 1, true); test("13", "21", 2, true); test("13", "21", 3, true); test("13", "21", 4, false); test("13", "21", 100, false); test("1000000000001", "1", 12, true); test("1000000000001", "1", 13, false); test("4294967295", "4294967295", 32, true); test("281474976710672", "844424930131984", 49, true); test("281474976710672", "844424930131984", 50, false); } #[test] fn limbs_eq_limb_mod_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_8().test_properties_with_config( &config, |(xs, y, pow)| { assert_eq!( limbs_eq_limb_mod_power_of_2(&xs, y, pow), Natural::from_owned_limbs_asc(xs).eq_mod_power_of_2(&Natural::from(y), pow) ); }, ); } #[test] fn limbs_eq_mod_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_9().test_properties_with_config( &config, |(xs, ys, pow)| { assert_eq!( limbs_eq_mod_power_of_2(&xs, &ys, pow), Natural::from_owned_limbs_asc(xs) .eq_mod_power_of_2(&Natural::from_owned_limbs_asc(ys), pow) ); }, ); } #[test] fn eq_mod_power_of_2_properties() { natural_natural_unsigned_triple_gen_var_1().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(&y, pow); assert_eq!( rug::Integer::from(&x).is_congruent_2pow(&rug::Integer::from(&y), u32::exact_from(pow)), eq_mod_power_of_2 ); assert_eq!(y.eq_mod_power_of_2(&x, pow), eq_mod_power_of_2); assert_eq!( x.mod_power_of_2(pow) == y.mod_power_of_2(pow), eq_mod_power_of_2 ); }); natural_natural_unsigned_triple_gen_var_2().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(&y, pow)); assert!( rug::Integer::from(&x).is_congruent_2pow(&rug::Integer::from(&y), u32::exact_from(pow)) ); assert!(y.eq_mod_power_of_2(&x, pow)); assert_eq!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); natural_natural_unsigned_triple_gen_var_3().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(&y, pow)); assert!( !rug::Integer::from(&x) .is_congruent_2pow(&rug::Integer::from(&y), u32::exact_from(pow)) ); assert!(!y.eq_mod_power_of_2(&x, pow)); assert_ne!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(&n, pow)); assert_eq!( n.eq_mod_power_of_2(&Natural::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( Natural::ZERO.eq_mod_power_of_2(&n, pow), n.divisible_by_power_of_2(pow) ); }); natural_natural_natural_unsigned_quadruple_gen_var_1().test_properties(|(x, y, z, pow)| { if x.eq_mod_power_of_2(&y, pow) && y.eq_mod_power_of_2(&z, pow) { assert!(x.eq_mod_power_of_2(&z, pow)); } }); natural_pair_gen().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(&y, 0)); }); unsigned_triple_gen_var_4::().test_properties(|(x, y, pow)| { assert_eq!( x.eq_mod_power_of_2(y, pow), Natural::from(x).eq_mod_power_of_2(&Natural::from(y), pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/extended_gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, ExtendedGcd, Gcd}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_pair_gen_var_11, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::gcd::extended_gcd::limbs_extended_gcd; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_pair_gen_var_4}; use malachite_nz::test_util::natural::arithmetic::extended_gcd::{ extended_gcd_binary_natural, extended_gcd_euclidean_natural, }; use std::cmp::min; use std::str::FromStr; #[test] fn test_limbs_extended_gcd() { let test = |xs: &[Limb], ys: &[Limb], gs_out: &[Limb], ss_out: &[Limb], ss_sign_out: bool| { let a = Natural::from_limbs_asc(xs); let b = Natural::from_limbs_asc(ys); let mut xs = xs.to_vec(); let mut ys = ys.to_vec(); let mut gs = vec![0; ys.len()]; let mut ss = vec![0; ys.len() + 1]; let (g_len, ss_sign) = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); gs.truncate(g_len); assert_eq!(gs, gs_out); assert_eq!(ss, ss_out); assert_eq!(ss_sign, ss_sign_out); let result = (&a).extended_gcd(&b); let result_alt = extended_gcd_euclidean_natural(a, b); assert_eq!(result, result_alt); let (gcd, x, _) = result; assert_eq!(Natural::from_owned_limbs_asc(gs), gcd); assert_eq!( Integer::from_sign_and_abs(ss_sign, Natural::from_owned_limbs_asc(ss)), x, ); }; #[cfg(not(feature = "32_bit_limbs"))] { // - s == 0 second time in limbs_gcd_subdivide_step // - scratch <= scratch_2 first time // - n < GCDEXT_DC_THRESHOLD first time // - ys_len <= n // - n < GCDEXT_DC_THRESHOLD second time // - !mask.get_highest_bit() && n == 2 in mpn_gcdext_lehmer_n // - !limbs_half_gcd_2 in mpn_gcdext_lehmer_n // - let Some(gs) = gs in gcd_subdiv_step_hook // - d != -1 in gcd_subdiv_step_hook // - n == 0 in mpn_gcdext_lehmer_n test(&[0, 0], &[0, 1], &[0, 1], &[0; 3], false); // - gs == None in gcd_subdiv_step_hook // - d == 0 in gcd_subdiv_step_hook // - qs[qs_len - 1] != 0 // - qs_len == 1 in gcd_subdiv_step_hook // - q == 1 in gcd_subdiv_step_hook // - d != 0 in gcd_subdiv_step_hook test(&[0, 1], &[1, 1], &[1], &[1, 0, 0], false); test(&[1, 1], &[0, 1], &[1], &[1, 0, 0], true); // - ys_len > n // - slice_test_zero // - n != 1 test(&[0, 0, 0], &[0, 1], &[0, 1], &[0; 3], true); // - d == -1 in gcd_subdiv_step_hook test(&[0, 1], &[0, 1], &[0, 1], &[0; 3], false); // - !mask.get_highest_bit() && n != 2 in mpn_gcdext_lehmer_n test(&[0, 0, 0], &[0, 0, 1], &[0, 0, 1], &[0; 4], false); // - !slice_test_zero test(&[0, 0, 1], &[1, 1], &[1], &[1, 0, 0], true); // - limbs_half_gcd_2 in mpn_gcdext_lehmer_n test(&[0, 1], &[0, 2], &[0, 1], &[1, 0, 0], true); // - q != 1 in gcd_subdiv_step_hook // - n != 0 in mpn_gcdext_lehmer_n // - ys[0] != ys[0] in mpn_gcdext_lehmer_n // - u == 0 in mpn_gcdext_lehmer_n test(&[1, 1], &[0, 2], &[1], &[u64::MAX, 0, 0], false); // - v != 0 && u > 0 in mpn_gcdext_lehmer_n // - u_high != 0 || v_high != 0 in mpn_gcdext_lehmer_n // - !overflow in mpn_gcdext_lehmer_n test(&[1, 1], &[0, 3], &[1], &[1, 1, 0], true); // - u != 0 && v == 0 in mpn_gcdext_lehmer_n test(&[0, 2], &[1, 1], &[1], &[0x8000000000000000, 0, 0], true); // - v == 0 && u < 0 in mpn_gcdext_lehmer_n // - u_high == 0 && v_high == 0 in mpn_gcdext_lehmer_n test(&[0, 3], &[1, 1], &[1], &[6148914691236517206, 0, 0], false); // - qs[qs_len - 1] == 0 in gcd_subdiv_step_hook test(&[0, 1], &[3, 1], &[1], &[6148914691236517206, 0, 0], true); // - ys[0] == ys[0] in mpn_gcdext_lehmer_n // - c == Less in mpn_gcdext_lehmer_n test(&[0, 3], &[2, 1], &[6], &[1, 0, 0], false); // - qs_len != 1 in gcd_subdiv_step_hook // - us1_len >= un in gcd_subdiv_step_hook test( &[0, 1, 1], &[1, 0, 1], &[1], &[9223372036854775808, 9223372036854775807, 0, 0], true, ); // - c != Less in mpn_gcdext_lehmer_n test(&[2, 1], &[0, 3], &[6], &[3, 0, 0], true); // - mask.get_highest_bit() in mpn_gcdext_lehmer_n test(&[0, 0, 0, 1], &[0, 1, 2], &[0, 1], &[4, 0, 0, 0], true); // - n == 1 test( &[6848271667560079512, 13861374652666379954, 600542], &[15542], &[2], &[1371, 0], true, ); // - lehmer_un_mag == 0 test( &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], false, ); // - a_high != 0 || b_high != 0 in hgcd_mul_matrix_vector test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18374686479671623680, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 2305843009213693951, 0, 0, 18446673704965373952, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073172680704, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 34359738367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709549568, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 536870912, ], &[ 11355937970588734278, 3544497895965036599, 5225991727718279257, 11457652450237970096, 16551604813668836209, 17754241944512523883, 3176704704142514002, 12283547505852043241, 17557436704460508104, 18048039364826572929, 13333500704188093729, 892648222726932282, 2946704070161030146, 15809102852568649812, 10556060496835357758, 13999563791465516709, 16795394648020203645, 5473855374714961257, 6317849519380440741, 9533351922984224766, 11199301811587071415, 16104396350303499941, 15525110145422212736, 8203351698546552543, 17779816949061549823, 6150214384826970115, 5864639845877226066, 8432436556130946426, 1694754843869495379, 6921022520123639010, 8168244414130645390, 17924728491331090321, 5240620769674049674, 7948733356420425838, 4164556574449762846, 3737022941502002636, 6332550616406374427, 12049373251003406842, 8298091260394621227, 11402785868193393498, 4794141068545824715, 2293061622321195974, 3997898020907247759, 11390523742316421611, 18016308015666214138, 330601620407517096, 3729949217978051654, 3717164522225869060, 17148162338327991034, 15562487010827154314, 16995664998781727861, 12334576623153650165, 13954922206742126295, 616324677452280283, 12138651863053041411, 2901393340055663681, 4057675599502751888, 12867219672291525155, 16025369701447219309, 18291145072066168978, 6697243850930356977, 18183870876245151507, 16808339866631232379, 1434968293346404500, 7007570804021103186, 8146472655024139630, 6170247347038667771, 11180987210188215702, 2526778521668153406, 11296437792442738742, 2674596804625062286, 15397706259368836490, 8055008760994234140, 3655064363381212415, 6387522636703297186, 14765097444277449868, 2587920917390548071, 3777601956819414189, 1367003930735636394, 14480186758186795163, 14461758439666061901, 3591570641418361261, 6011456982940110770, 13775036746519870557, 3515973171287160407, 11543702048022668014, 17156805461772215077, 7789863248521128989, 8783344931315906614, 8862457044352814825, 12036193712578424925, 10229084237758914039, 2530599756212694767, 12603356233950916099, 10928947856790716992, 1278323263344144909, 10314562964341343646, 1847967980534411513, 5032414221301943483, 15681738326271406631, 3194671023664910533, 8791405941685450275, 2545048889497795432, 10838955567082805298, 13202048406979146028, 735163755852225584, 6550497094317723662, 7255798445537127650, 15294347560795923278, 13594615253945427774, 14024060147812684782, 12481381765690694528, 9035353722672177955, 2282788968895170640, 16368080906407574474, 13331353391507147025, 6871599878570595479, 5812073143362706756, 682268425977891017, 17355206475547621290, 12788943360185483133, 3134625393734037339, 2225918008009480818, 1378922681447539115, 387302346471424560, 7981952752578031427, 14970285989368295976, 15275338493119346159, 2055310172270254742, 13764120124381520856, 11664936006922659164, 2643366467379458616, 529226747378840064, 13267220164946692785, 14547927549716284389, 6963741308123560970, 8742711245029444284, 15261140288624259959, 1578268278352959223, 6373230977423218554, 11890422386430555010, 5886607793090514799, 7833563136219755985, 7841472882102640873, 13312461380742060831, 2395694462667717061, 10862004384554721034, 1646776064683378692, 13189208103829969973, 5966205004575172180, 14738838372597365974, 15020396446219768334, 14413755716895328474, 9344949375716586309, 1229771678439710784, 7660206584697636723, 1183107462498095108, 11726292635609054827, 10699209342165514955, 7230229562793714711, 11021478292667450773, 2118474640913963907, 2558516995497623930, 8845333270363517287, 3191138491812047327, 16410588907577198668, 5980624009289925929, 2451953326569686471, 10018381451241044084, 16452767950546421264, 17471045363239371647, 1626642226703803238, 11701104567773084690, 14938496887472066956, 18243954799407678852, 3462341165977180702, 4440268961210232011, 16503624676021811103, 4947555292161588113, 10068740357286544174, 12722024646736164621, 5215319244188856897, 12819613534111856139, 11761503529124767748, 11212463947616450658, 988714827896034783, 2795486984158021882, 4896614548481253474, 17264411928998635411, 6991695123855584251, 1887206336532761600, 13527521258177629646, 12908415090831708154, 10207645441625616573, 15856236799516388865, 3288848037346427414, 17930163082958088951, 782564826362252176, 11323264037662272410, 7001711656841223364, 4079977115693631469, 695716839503085981, 3374637294286489469, 15889407156945307136, 17581338039905274592, 17094348597898315039, 16353196845043490093, 11759713419000324565, 8686366945008222125, 8269792945343586814, 5052016679434417836, 5028743688612381403, 8025468352838073803, 7047540105303099705, 12096113813124900449, 13098595410767341653, 9941645490018528903, 2681768029589535927, 8355744438980253398, 18089008391368793427, 8436024776108933006, 17749009211783191721, 10332647584692068706, 15007009936211828918, 6204066299283285761, 5021281476904826405, 1600764813061514271, 4462704966228492576, 17611024951628662247, 15690341426616812337, 8381957287367776145, 14636503690521318459, 16361586613759350563, 7143185398224610804, 7421332207926427448, 5160495049104271179, 11790556434194897523, 3358499649843784501, 17568668957737000399, 14738977031978362240, 10941958707885889897, 17560490313279047521, 13068293955179990434, 1311621805545412288, 1724645583247697802, 16533119668392562139, 15946397208845217035, 2606300340733658128, 17993371923203650980, 6437813290399616223, 9301478356539410429, 9078893833335741694, 9800029831447697604, 999283483544934750, 9314490672154120559, 9858011191982789554, 12615742347248446820, 12745352278127739580, 2917880301505433570, 8592553693086187941, 4266384572653881881, 17812593099833733246, 11162145325572414420, 7027733596218655312, 14251233149261343358, 15929293070633912143, 1200937482512714713, 13064217620622038479, 2015406846017082843, 15462831244280919552, 7394985535627986306, 14150714741297842281, 13793998316779245847, 3289635678328566848, 9558502002378655190, 16878996228940187116, 8476207859286148837, 11697860830632493725, 7479109953251976933, 10627692553918524640, 4493048087427514604, 16424502988035425858, 15872913387110937441, 6678548325919201705, 3759106456777908735, 17905057981958618796, 5531956864218250481, 5081485037631244129, 4438034926824582251, 9750567356872273685, 11765980608710836596, 7992997025333311324, 1072399829816605510, 13720036779440702296, 13696412511769531727, 10520426519064259348, 14083672259849678575, 12606102699487046517, 4552441171728662711, 10068561237678333153, 8335629340697562266, 621345583992405086, 11625499998573086286, 12530589677423097443, 5784247379112031930, 9573881388612216072, 306900559918462036, 10802792644526464293, 9005291427573133098, 3210472577739818680, 8109893900355246116, 17173601172370596807, 5639355372463629115, 17776827907372018842, 1825555716078714820, 5825409710015598549, 6386380706326136025, 5491078696742670261, 10890062618237596098, 12934757950932017519, 6089055221572465849, 5302771001651365064, 6529251571951350570, 10422598446055788321, 6986883759388823904, 3479857387959793651, 13932683391655597163, 11857116184895981757, 13620148450025966737, 9662736511030645005, 17272098448231972157, 7373488914627711700, 13816388856223655937, 9152021189383388805, 15526953697508927384, 4566792369617010321, 17748819712249574290, 3975645351903836057, 1254146463110192234, 12624642013341638958, 13179991023549425193, 10496183700093856869, 16501626902202924145, 15437434336748083012, 13304628263916915134, 11770409937478909051, 10425572757187528521, 195983147614623088, 15825069226305924435, 7677098711006719767, 7180623381906900889, 7606998129912024028, 8878945880606186704, 4306880255210982291, 3567917901108795660, 14439736515945599744, 10064132280866806031, 11114740602207314960, 12269057055975187988, 4685568551722956272, 15841611643677594787, 16532384271143875227, 3177002035311213189, 2748439165446028467, 2982768316945625393, 17654574962578819927, 4719556020732610801, 12576980019584600906, 3022659802135895783, 3345674780500898476, 5960242413432350886, 9379987545573944751, 4790778513006264594, 14424237671028891391, 9006219756866701479, 9012561253523913521, 10382281003999164758, 15656746742177270975, 9209056340857015002, 6446905061392500350, 5543733769387719725, 1821801893357102752, 9539889038990067613, 2168207589826710703, 7899714816887939703, 2867435044255337312, 11475557911370381186, 4616251164227426777, 6325316036089337296, 14220172204078683737, 1479433236288691151, 364395557328561445, 10181347790448231666, 13031251690, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], true, ); // - limbs_half_gcd_approx, n != 0 fifth time test( &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1125899906842623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446742974197923840, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446181123756130304, u64::MAX, 262143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744069414584320, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446743523953737728, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446673704965373952, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 8388607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073642442752, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551612, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744056529682432, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1152921504606846975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073707454464, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 4611686018427387903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18158513697557839872, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1125899906842623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551104, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18445618173802708992, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 1099511627775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709486080, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[1], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18445618173802708991, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744004990074879, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073705357311, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551359, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18158513697557839871, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446726481523507199, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744072635809791, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709486079, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551611, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18442240474082181119, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446743798831644671, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073692774399, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709550591, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 17293822569102704639, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446673704965373951, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744069414584319, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709289471, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551599, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18428729675200069631, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446742974197923839, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073642442751, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709547519, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 13835058055282163711, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446462598732840959, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744056529682431, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073708503039, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551551, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18374686479671623679, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446739675663040511, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073441116159, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709535231, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551614, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18445618173802708991, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744004990074879, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073705357311, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551359, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18158513697557839871, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446726481523507199, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744072635809791, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709486079, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551611, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18442240474082181119, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446743798831644671, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073692774399, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709550591, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 17293822569102704639, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446673704965373951, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744069414584319, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709289471, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551599, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18428729675200069631, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446742974197923839, u64::MAX, u64::MAX, 1099511627775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073642442752, u64::MAX, u64::MAX, 134217727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709547520, u64::MAX, u64::MAX, 12287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13835058055282163712, u64::MAX, u64::MAX, u64::MAX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446462598732840960, u64::MAX, u64::MAX, 1407374883553279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744056529682432, u64::MAX, u64::MAX, 103079215103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073708503040, u64::MAX, u64::MAX, 7340031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551552, u64::MAX, u64::MAX, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18374686479671623680, u64::MAX, u64::MAX, 648518346341351423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551104, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446739675663040511, u64::MAX, u64::MAX, 43980465111039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17293822569102704640, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073441116159, u64::MAX, u64::MAX, 2952790015, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446638520593285120, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709535231, u64::MAX, u64::MAX, 196607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744065119617024, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551614, u64::MAX, u64::MAX, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073708896256, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18445618173802708991, u64::MAX, u64::MAX, 15762598695796735, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551568, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744004990074879, u64::MAX, u64::MAX, 1030792151039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18383693678926364672, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073705357311, u64::MAX, u64::MAX, 67108863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446739675663040512, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 18446744073709551359, u64::MAX, u64::MAX, 4351, 11917197538718384128, 467259134428645418, 6788357750791208406, 9242329996563429548, 10886176818018943828, 11527963904631924557, 4619262020403083793, 4693016615877260538, 10656992932246037101, 1201267464050846418, 16892806369450387862, 7260834969008935227, 10946994085667026297, 2372478557069238877, 2649634673312662431, 1971108451836424232, 15920910453133967577, 18343035775416390501, 17675740189836358098, 7961908122306947630, 10522116250551573754, 10720452547870905110, 13993818308946817901, 14981440820269029550, 3964393654674426139, 9188834164259890791, 760657968153329411, 15794852728413988195, 121692186286907108, 8438358951770764798, 4083268543268227949, 14314095372356483592, 16367456820484493888, 16488070997942369178, 2456304038484914065, 5318034970699522900, 2959567294926710167, 771227150064772722, 9625724702091381259, 5539648733388948632, 6296516403289377967, 6612868998968848580, 14679407116108799957, 9179506663297215386, 3126498424100063612, 16405144875690137401, 14320022863621427985, 805941381509761086, 17332784969460251591, 14850035139935864203, 11221361687842258009, 17232401019581260846, 2512367718866898464, 7358878735486392979, 13696731821427345557, 9293081417681328102, 3376318679991353011, 12202221967868047883, 7633929001522110487, 469745074978237658, 15671305152530474150, 16741062484850963239, 9709027825588259965, 14965798704955220546, 10321462006555968081, 14718003047093590717, 14951149626183661907, 18370518234692703192, 6648761387169923655, 3495449149370393733, 4867982887169583834, 2940602529760848239, 15303244725027837240, 12022601737602548345, 5207641806555834805, 18224346526787935271, 5860200105418976315, 4716922763266916746, 2931793719851896344, 4282902489945622759, 15498436420567618761, 17476940285323706249, 10494618185564967295, 17600927612503861693, 4004386666445630489, 7077257573845093177, 15605638591238936360, 12750149264765234722, 16517469446437411092, 5331921608656301987, 15990624057943095044, 6614187095350567819, 14196302046322991345, 13429850979948350957, 11931776027829375931, 13084698857801127574, 12621848468679923389, 733319738320099215, 309720041492809697, 4603997955364266904, 7631309139653548926, 13725082120663996537, 10680613565153942003, 8829919775953886886, 16493213914010845102, 16144038634921769479, 15174454398009102002, 12702158768945839471, 2046486227451675592, 7191766299935265091, 10798251950288187041, 10987381149500371882, 10099075929210891590, 2743950294733236634, 10712909458831282788, 5399984310001985045, 8862585223946748337, 4543078657879193640, 5972083794371718328, 9524422364141495239, 4362149695406553108, 11158165961894005297, 6972411493150091411, 4453604966534596347, 17984472834103892444, 5843292965076477748, 6717839842474511028, 7073071703492082564, 7124040220204291820, 15920817649921953414, 6033261800600136301, 13264404518327225501, 3262602253202307370, 6118361192463397201, 8193286771316418532, 10590174942484499293, 18086507478089323191, 1972161174303495199, 13370520826144684729, 7006982756954362332, 3412148043338776494, 2943191784843802601, 15479594962300053635, 15676367408812095850, 9531517811856243576, 14665612461344295683, 14183812331462869997, 13605479300860815251, 439986791286981930, 4999695897383135613, 16752742798876703505, 5416349380281137684, 13367864008272215535, 11925862678811350949, 9931716501482730002, 5334420036079300287, 1839353492333744653, 6443019339779438740, 5782025392680955786, 3310359077816541781, 3071937103121471824, 10467119917919082270, 8363994716135013286, 9195653300387363065, 1458755452304995485, 14455866113820571344, 4601934972694450428, 8546684886584049785, 2910056131585330183, 8182159409537093240, 11195069301928068927, 7430372455973036835, 9376197352558750907, 7875367292416398486, 13472289725149857346, 12372323834109182274, 13185122839580952616, 13191058148790302164, 4060060639960051391, 14876197669688797412, 6688909374239616805, 14518552553633126579, 17439288972835129221, 11119504087401935490, 16008905564850227906, 16939859930478593139, 7728220727027034101, 17728948512884482185, 2247176307913903150, 17171980041243635507, 12564914981092814500, 8485599174904740776, 14944569965672542135, 8092344633505138892, 2766034468358519906, 11524026593306884882, 7089566729505727299, 16241632485631823277, 2191809207409558025, 8036842641714644233, 3890183076329235441, 8506260809383482703, 8607260503876159174, 5219459906773816617, 6248409563984118024, 16880377339391885924, 7508875978912613905, 11838550668904162038, 5741644075555979832, 4243030907223624999, 1548584199410565508, 4823393122958215219, 1697336748032007427, 4231380010852496070, 17774901739207687366, 4282151946448260460, 15342283292560246, 8454274642438206112, 14884124815651203946, 4801003094746403247, 8409235268196886949, 15945645341541852418, 10566745003011016319, 5373818074808734154, 5957111697658145675, 8098283285193372750, 10627395543896437107, 1004114139502611844, 13028365652123892366, 17285136039620601966, 9771197788525663003, 10778155523054662726, 1252434210094493683, 3104428099285903840, 14545119360465992545, 13482789168297897256, 16892024151842829743, 14958949737586351765, 176813717701605980, 12903584614896208825, 3544269214939263116, 15415961180239667229, 10207167364902374899, 8258933860707013576, 8763504928324220767, 5852219836524758714, 8917845927309407708, 8650576021936229287, 810800948731327073, 9432436806001512551, 10071761069693900691, 17210238083627540362, 16157914338762250976, 18119096037382139092, 15842037880142981298, 1938796891348188518, 18038449534545012835, 830305259048726407, 9824993594160172645, 14270772538553547844, 9335522008741474704, 1598988872301369352, 7135098133003130869, 14517764710188845484, 8381545218247466939, 17513533292688300788, 9979799724575001006, 11871456754305636334, 500149224166155575, 7328657073651369466, 8248404162062141993, 15340141459299322505, 9206212673038925179, 2619013708805290566, 8436839150868422552, 2890681915050735858, 2770401271866467392, 14574922130718551270, 10225699659804069030, 12923931425056680729, 10689108797349759959, 14297241156294088830, 8389319625465870296, 5887233723227419685, 12840203084613907356, 18162673586865404776, 8624225914841328830, 17256823539327648869, 12003135778415512826, 3597599245381760686, 17835387163699274799, 14764468716785611669, 8824977215853469639, 13212822925878714768, 9541684495307807183, 289792700466037634, 3317984079493445473, 10424421285541300784, 5233593699053119648, 860833127156653416, 7602647302770159713, 13448229100450689027, 15851757830006066413, 4347783812519020968, 9705162038645948138, 7816355078824599111, 15657526035174035224, 8345530277219893955, 12809745956138560820, 2322613832317857662, 8390418154009047298, 17480153839918560903, 4531493019552839961, 13306559295694752187, 14105099140485348487, 977744740519166616, 16173275597988793525, 1572613977539690615, 2791693683090500468, 10895607070984380351, 5857659842923811345, 14369477901457758602, 15971387397482177656, 13980771174271954277, 1306374729521782078, 14876646097142535131, 6079868902377495274, 14529054656896311525, 12651646699699387721, 3280738441344740258, 6324653974318535909, 9721040498224073208, 10048475139421707795, 14406563703126166799, 11594579356863630189, 15703055934976840648, 16980517382158489374, 10822592770083340009, 997497860286465677, 17713652607295352317, 14640107518605433045, 11504921534044091590, 7886774575725192134, 16232729784979957146, 8701022159004659597, 9422932370459637065, 683387794982212396, 12522805309568448835, 7838941626001579771, 9312605586518699382, 7599970463029680247, 7574987664186768331, 531198888309344974, 4905818237198157767, 5287443443847767752, 11054912261682802779, 13345315441145166898, 7182824994183807062, 14675180049751250933, 12631232313785864828, 17989108850471182585, 18050543115820893637, 18423857768930007266, 3273900906530304172, 17484423258652475360, 12801016888087344821, 17711012173189143731, 6549738307451038612, 4867667988808303389, 14312538923504157926, 15142482147452710051, 16121208240437843523, 17171879328661211137, 11677738961972655962, 13078497464995716606, 7751113107414976650, 10081753473167432013, 4468516464426989825, 18127602331094353429, 16767975702693811382, 8668788169830842397, 8498402294335646393, 12966177070433820606, 8250332058268580156, 15811118180207537374, 2361477232834668905, 6222737058090237269, 1587885103313658896, 13218473962721980915, 12951574701461712049, 12411105451558595778, 12644766231497403771, 9843819911067664651, 9081495749584620433, 4594060340198124646, 3463880046614810802, 9052295694844495814, 5855780626312371907, 1792160660767445345, 11189389626486793331, 16480123866965071427, 13538658156240740247, 1337769093889100585, 25213735131173653, 13594693503798686715, 2786395866168922127, 9745235819809541326, 1847567857621537325, 3661408106486742428, 15822353907251746649, 635253737448279801, 12536768008212611637, 16205598701707230534, 6208704468299969673, 12632814267855645761, 3983629484208856920, 14463715595702959132, 14068644471445808672, 13071424163135564830, 5048244838017897198, 3957348508978029479, 5171890733073780158, 6090355458677010676, 18410043021067699918, 102411056976507785, 12496578301072641109, 7489537163555902605, 4222835379178602700, 11897049925808045969, 15254226892154904380, 2427764677907392764, 6097459900604836271, 14167293803271640391, 15572454008598321436, 4479437047685147582, 14634864923535733535, 9440363258554695720, 14447172202107496642, 7737099397251411392, 10872252838093293197, 2347781704700902159, 12892601897325517851, 18187570864085126771, 3862570130037604031, 18415681868605222990, 14872486503424548851, 290001522323890694, 12689386207005040067, 18367639946821497130, 23954916269174833, 17245821941163862773, 11894661335959030463, 959150115393729462, 2015998969739268525, 15315512592879336413, 17353907236181211247, 6439362580061316324, 3694810751520126307, 7251119290538843884, 2902818723072045378, 16029591053956459275, 5864718627412226067, 5790025469765734459, 6773868036272256548, 3999623636821784476, 2497507128350253602, 8302623393498593261, 11471292698362373968, 8320975184255973432, 15654963738169930347, 134083697380355810, 1100458250563753914, 9283598718625555235, 5673024045082942208, 3336856015239924756, 8991471779663227287, 18220352109739797206, 3201920047088347377, 14048295331995920496, 2023216756502051055, 3937018610966240739, 9265528332519197997, 13340683957228210488, 16395501556237436690, 11882279545751936849, 10654538555885887306, 1213641065209991369, 8686438495717443238, 3204522269330159380, 15749257989555621891, 7200829664472660344, 4606035142128288244, 7738145978279406878, 8005750434116314508, 10039090611220128432, 5919432049926072824, 1898955354979287264, 13742546998210628515, 2062380153955383477, 10627849102165617898, 10263733156880394488, 6187246165891479344, 6842758231513896980, 1044980371062368886, 11619956366420670628, 5306150757083506465, 14493806618830043219, 8516775388512886261, 12966310564897513054, 7977410936359711070, 6472070119922783488, 11685909650081989228, 11077466008455317410, 93779104345285196, 2263631665127678501, 8484269669373998463, 4317253498968686951, 4086096203557045487, 13581861404151879145, 5728397180081682581, 7010007051891978798, 2821912591057075698, 5879426090505992869, 13569541343551121555, 7149443705748294066, 13910494223862857288, 12658627337344496058, 2951750024777275755, 22962926030546005, 11049711249112626032, 6001166774644846695, 7990182725043000123, 13513885125683051345, 8512916727377461799, 9117393073038165173, 18018665698956545109, 9317438210677247667, 13228179741076658181, 8661423552785887573, 16181753946942005215, 5817006592457107177, 4946404759149000501, 17025463002044524938, 3091573145940415028, 5624455086851730975, 299596446419786514, 16997248996797575926, 5442881049272221237, 16640822063105180490, 7201369405851839100, 1990572593974844456, 18065512913263752946, 18435803827758421726, 3940680480451692192, 14695541863675895009, 18237945747361846765, 11523059833149211458, 14801621049236961830, 13093650885612556220, 18073264199739840152, 11232873781393214848, 4738273277154183967, 8770083886080393014, 9448453106360155017, 16808957868302654163, 15595086290970401573, 6687124880891546159, 11219335141762698876, 9380127018866822584, 10327758572616370786, 12205962561173980334, 1292378777928694178, 7701183202987422345, 18362257942086401551, 6058850841413861423, 13437237384376816904, 10936547361793543928, 15650097713642375395, 9913147450601628212, 15909605568129499495, 11513460193413160213, 12780098351351910037, 5212701352903210016, 11564025864354328627, 8700098770020742313, 4899380922086558778, 4050898917285079051, 13661989352190807516, 10966728149436612554, 16847843417882464903, 274924042498303488, 18222284358029704003, 7577065190825838785, 15003614659630419448, 2624069814584755546, 16881026613694635169, 15300060653308040957, 9570234639793768301, 5784677630619169063, 1135179792440620182, 878922669379348230, 13627915631233840567, 1985946077482791264, 6391853516359415788, 15570291686878623581, 501707176891222139, 5957022918137638671, 5956247526180593898, 18226765754149736016, 13338056793022561402, 6432376523812042513, 767152662715876804, 10201155875474385234, 7446824482480043740, 10487128891092272938, 8753372664509444428, 18079456715932134001, 11624853191447527022, 17566358671204115242, 17018919029686381250, 2111234374616573204, 9480242526387098658, 2429728644808764358, 7252446333936316953, 14812862792274767439, 5422271871225914827, 12412305305577171801, 1185008520838149346, 3050026111086571739, 1479014294376021732, 18040200323783099330, 445973913795316809, 9501364820370671400, 7229301050267458578, 5215280963194612127, 17088616964070030911, 1211285093482602371, 16412084179763424819, 6127319388370601780, 14321419570407056924, 12145388950945552845, 3151594979185432120, 1675376244241883765, 16035687529597509596, 7571293182649441152, 175550498630765698, 16593238056068470505, 1814341778388969595, 3311024737818411516, 12770957752805211539, 17631719244677199941, 8795460689496576017, 3690652674506323732, 2428882789489849159, 14730942683624044492, 18326270070598508149, 11964271508281591609, 9829424265343173509, 15758964916794844298, 2461618406724607460, 709439034532299949, 571182269550622472, 1379073389911508673, 16644335569340215058, 17367543108812074229, 13444880229306119718, 15724530661215895601, 4047906541646187785, 4686650652361404048, 17238280140069784141, 4068910883473961263, 17655282977204804312, 11518276288990596576, 3467897255047563766, 743113880655434578, 1942535316548544695, 6619981797071393726, 5025961891257111145, 16592110483904182561, 3928324895371240622, 9737258859280736451, 5661254605396046378, 11163745722429719144, 17083006376780241503, 17506382401952249312, 1764127145955644136, 2308897656615883377, 122979845480243850, 8075446398869802985, 2187259826315952725, 18434025953725754274, 3124178986621188904, 12866647436942698703, 1357236272197199912, 9078709271602493271, 12468293812747433865, 12437259926403880115, 14436048005013653854, 89642992988117440, 16523797273367389305, 9043367976020866146, 12463395346461196797, 9862261089924822182, 14657746177936768112, 8825469242077938034, 9129609557253922495, 6888044783796588921, 6266713628643147669, 5220942463058228458, 10813630780587283743, 7968832679516396373, 15970129806498677212, 5643891883064886939, 9824143743589185710, 10400697215263251029, 8190620745660574041, 10238618355555564865, 8918941655352077567, 10871235401787589340, 1460739087571168519, 2823745702037521010, 15337263495117106268, 968161936177366335, 16689016160632043912, 7848489458860449863, 10398358129317695375, 11584918823272315734, 13901934479805418812, 9574709144377930221, 2111587472743157797, 9404690877383586391, 1590261001575452774, 6134044942408749913, 9839924636511642837, 14493598904422521457, 15632908487818372617, 487545237727920944, 1802722569923057493, 1958947450166852109, 6867362149480730072, 4772292527599116912, 10583080518323476356, 1221855970145623550, 5948499263531823034, 3495089086729498045, 12066360463076595030, 10771591788577692723, 3954187584618376697, 8187128112385053815, 1454504010792563026, 15959458072896963922, 1581292658782340862, 9692831561010284189, 10309426695412145821, 17906554304756557589, 15054157577871514625, 5058050233476401027, 8977640754771236893, 9627862855892683832, 10699519167644754760, 8312772912482187477, 8332644095735932279, 9049498226063315161, 997818841660225453, 3693781389037645036, 1144225405512234695, 3247638062925459825, 9845499292221371832, 7214100452002833535, 13714743610307947023, 9960430565581967579, 15735339179405466356, 15625934646641742062, 17726446932751133474, 12466451891602142569, 6375000197140594959, 1804204775829221428, 4530402129749433189, 14921578666027523559, 17772348524780474456, 5690248012292173794, 18333653072911688035, 15767765611816527995, 5732035322385811433, 5691521304590002551, 16083874229056371081, 2974572122345241237, 5328620585473031115, 15044351400969060080, 14466412200009582770, 17782787336388788204, 3316258621322435409, 11748403349011599839, 861962132923513040, 4887924627919467034, 18409613134327857507, 1745648181716009640, 5126024415670625429, 16863431110236260032, 2600510782962714478, 942626199781748852, 496511142761735889, 6759476802769137517, 16696041693879173804, 16687962170563294152, 3414843693481777663, 11365529158754670742, 11372869234139609818, 11819362223430480664, 18033204110273523753, 5618547869326219703, 17704195460847759589, 16049329338769286554, 4133452506455359139, 16326665087942006883, 4297538536529132241, 5047883522524396976, 14714906005027183437, 5329799583480738955, 10690501377556811520, 3652332036981148106, 516750725933923982, 4827800595674301759, 10448722013809472310, 11596999240332271563, 5927034132466409103, 12147048889264772882, 1089987820933222753, 4192412164568901269, 11908801153277116781, 10197687527260251620, 17895324101664653242, 10630777741097080977, 15358104418706100699, 17713199249506024637, 6459301066733754263, 16403734392003091136, 4604905190697647969, 17619115205002424831, 5574765860444266579, 13544006739749082480, 234951002765790631, 9100908206014736874, 10656401365796207537, 16925148628801893669, 9449341584538177921, 17352850195614236618, 1022065146657905242, 17397845413549299667, 1472464743447070941, 18057563713057329794, 8983459205909631202, 4925912043959382413, 17616318842542666695, 5163968491091913551, 14413758582451093019, 6337633891942044037, 7925297373525658970, 198793232404117347, 7758553085065395961, 4066515756447206607, 7389360101646457251, 8434909634529440653, 14266840326541123051, 3664978103235861792, 11163743218713176050, 5634257584230363951, 8083953074398386596, 16065890200113083079, 8110187990551805421, 17356164101512399606, 17992861118993870844, 10807783544543478597, 9106380242531919579, 3247174148476821056, 879857043201935030, 7277837200255844536, 10342478810494109596, 7769376500905648935, 6757777022343131040, 14433140844987570288, 3667302115484509962, 4952536985082809733, 1157782009537443994, 7388263404883144155, 13472936065806592300, 17712841629692457235, 5995317353880662009, 10921426583438212143, 12179213766915844655, 5936895377887378184, 14322156414482589235, 3826747354860666209, 572716595769055849, 2210089877779855353, 13835979775768645560, 17170702006657807683, 14591913253321414828, 6903263328385067839, 13237096933292161026, 16330366375298997716, 5525224905127580645, 8788863357092236563, 12448635220486228412, 18383201057494917349, 5685763045488991174, 14048501692736865413, 4769882810124814370, 11545233589288188582, 4494517485389924572, 13535319148707364133, 13735436845168944725, 15623475297010432846, 15624175619779801061, 1105816345140707954, 3727827862044247913, 15622289192708498694, 14187891019453013466, 13669457386124092325, 7787875468170725248, 14784127481172851456, 17500738909398230430, 2638672195611188012, 4369922987899757508, 9267506988909833873, 83899162371683818, 5657982455700308645, 13933782505443221438, 1385537874543388417, 8959434570591275846, 11221790620561509485, 14228125069662643278, 9909285045196542290, 13339627666512404139, 5072335295730660920, 7706783060191260337, 17231367447326094941, 13611972450650655904, 7252643560574698729, 1084812010386004798, 12946864548261445854, 1400313932997877069, 4588814836223113033, 987850811243060775, 3864997441785283522, 17599159350799904312, 13358032302365334533, 10141406154556810755, 17519361843239805040, 10915050108045622994, 10037174394817457317, 14469957883502949034, 7894829998151829341, 5636706558663217429, 15322279537825265034, 2396991900646263908, 8687396393462659176, 13485046092881595881, 9515659004930683430, 9429407622645326903, 9775248867058718405, 10916394549216341610, 483499136658695224, 11696589183261297643, 17279704547926580810, 17981456583759837666, 13325285482477722136, 10885197771076066967, 11092160349269277927, 16052410044282049678, 5037152622918883442, 11990176335222269624, 6948248507362872214, 16693754514326339970, 10461487764282800089, 2923564231271193330, 1920420216782302061, 7678699056037047591, 17659248341954076160, 1344087719368849432, 6013967839271137192, 7354032241978048812, 15496951280651194682, 6849045677301130055, 7404988064599461311, 17038584755626314135, 13989234369614587716, 137578066471879568, 12026307344383044322, 11253546536381009806, 2413006684071354921, 11797891407965975240, 13725020517275346702, 15664516332778507640, 5062525165078702547, 14354507223678652178, 15914941475966331443, 12639494759681519326, 6380510796548352415, 4480105256516383199, 5535744400880483113, 1895958289260972381, 12590320805441890710, 10985511241601241382, 9398017657977186818, 2799034594416011077, 14151939373239242853, 645490586599440523, 3809153665439075705, 4137467509776042994, 17354288216922338214, 6861193332615528070, 14738703648309330785, 98425663280239976, 12633851606975418481, 9785309034847603183, 16384799002475880508, 10931676995354970357, 985219608827803071, 17116957879956090141, 9101128336896036709, 11759983146088777269, 13015836674349684930, 15182092148682035351, 12836219866833634742, 11351106793190323210, 7840239307741716217, 11953726720158733414, 6628111943421404725, 11533662362420450459, 18369026228019546563, 7378513891084408617, 18154554674430175598, 156313846508387694, 16389733506781231332, 13914842726751003220, 18359517497569945195, 153206050418651881, 1048545139235406179, 2343069945378490119, 13221277598353216411, 1007579421943431502, 1087244838874317765, 13458642723894472673, 17777936966601400310, 7403025134549352232, 16597313881116482506, 17238957863339639244, 15264094753736934506, 1521680934845861710, 1557119627713031502, 16758686315895245035, 3796780137441489417, 8041960852929629915, 16608665948179582203, 1625645673158223013, 2300155596532077984, 8697518146661645554, 7409532402929679963, 6094459603168865699, 6558659569835998408, 8795865676999740518, 7414435640027234930, 3251947257573801174, 18427982151104544826, 5089951943467385160, 1401320279557700072, 3443749410134273405, 14030504630906880686, 17717719525826942963, 13215855120775253817, 3132504310059563638, 16144721530636034096, 4419633161552666567, 14954927501148389788, 16040852488245131634, 17441383469187402203, 5726385465541871539, 7394309454153803838, 7805509969418156305, 18037815606213679868, 5291835626363349632, 14635636495828813980, 9527936813559225710, 12597950725219919442, 4482140912854906507, 11126850444677396594, 4603523671821822232, 1649284289763661202, 1352906224724359281, 412590628646840670, 6996792898450011479, 4249279972226121347, 16031651732968496391, 2572334158533663991, 12347635976334350133, 6050273196783955591, 3246101772441301834, 13236089237569405152, 17471674455305786061, 1374645614093451841, 6815512315773585362, 11212487861088835231, 11308144268901363980, 17583948142960339023, 17810432752181566118, 12908796636670459090, 2122965481552992886, 13847569072419969913, 1885242280013246820, 16817717666957161753, 14122999869920814272, 9859723031623103719, 11303579127011954292, 18003588455125152868, 11608919537471305040, 9044967188677210322, 6634260888999233338, 7574880733619538648, 13351352388185143358, 7396424494525052331, 671815673850175731, 12474963203784163870, 9547951060319591849, 972244301322094093, 17949023223636564564, 12094555917714073753, 1826916629327265902, 13700478109063132032, 17067231999223770315, 243553916488249389, 11271453694238339233, 8732841242081706152, 9630793208957172586, 17446946104225081590, 5386829181566009948, 6054032971247389454, 6425015402571254341, 5006727812077047764, 1649789753514978836, 14723706592535708266, 4623978742676807297, 12710669164864869688, 1227780667083299405, 13714687322378497593, 3970422473073140387, 17265185031574773737, 6044830517845117529, 4453913678950321656, 6070005351778429309, 12176528240255678941, 7634537565077394947, 5920003618676265431, 11151627697721642783, 2098910925983806783, 15884306031133129509, 310067712781609295, 14024583474469751439, 17367719315694324874, 14424048877787895622, 12898411728086808947, 8953476654824027211, 7420571574695821582, 16094462443071534333, 7924169231214629362, 6878953677396960568, 154878602193835204, 13117567967104831967, 16556390858921765924, 5307332782841571348, 18150137521763992397, 3419976873747586767, 5858343539030355643, 7242296027220085783, 10965812104117451576, 16926965337779877856, 1601745124903955748, 13043994460177786078, 965169794640251015, 1943838529439481814, 10512319789812683259, 3844363432719685472, 1784837719119553167, 9468342792812849672, 2079904699316123181, 4129639703756184131, 2758297517205037135, 108586575672941788, 15547613664182116875, 6035998724236756, 17879991472252388776, 13693503069715806549, 3369358401497786056, 9688014843989801938, 10886459666257554215, 10393873019075670260, 6474159222462837717, 11243201032507786025, 16480121773023363798, 3226162915341963901, 1639108311236754072, 2585899667596998192, 14880301282874412647, 6970353541542233591, 7066115370491066021, 12694378779036437026, 17300617989102326075, 8283880842910890844, 5733876387824463732, 7951637249672862628, 1884141858212572689, 17015562239978558793, 4101828539017111698, 1103941533641964734, 13926022087478456712, 5024297271233621371, 9812418390690689673, 14992175312699678246, 16469893987247590657, 17570003134344434044, 13774143797513849932, 15772170500133732473, 4505821373766406837, 13996105830221088706, 1307766568769961087, 10729111457938251830, 11903845284444031988, 7854954755461745670, 10702619846963864915, 10608054100914243590, 6496893465131516234, 7241847511138135473, 3290888428315871736, 12664403582508649645, 9256771540519762367, 10264702404701897883, 3440088740965487374, 11529228460257674505, 2557227963071325614, 4351683269520556301, 11480097036161740240, 5615804147927032409, 8696276544281707589, 8117054923564791760, 4144540882354007558, 5246282716979102995, 16995837840762814682, 5002830053652768385, 5801390823422242943, 4685082241623089592, 3291652231640469960, 6091224371117976744, 1812763503175439853, 3813538854131386704, 4814848514078956363, 4046304873091181065, 17556508066037799794, 1871634009072900244, 14472650181236778075, 9420859677652280464, 9135633053662681532, 675213668906522010, 10682442267742318053, 5711990428027981792, 10951451073519478982, 766857567858898227, 10847907462605970605, 6065052831567493122, 10532184994483451863, 8084511492809001972, 6013718559355095905, 9089889612727338792, 13799378013888921126, 12551785775851801559, 1847395314627620923, 7067465808110764515, 9273405725950712925, 16061184093788784079, 14194983586797031158, 16125782867927384767, 11616632751689821401, 13227070560643064832, 17594387943145043458, 5137778382639156537, 16174520549303126373, 12122202659641254860, 11003713498475843935, 4971801422905630248, 1217212572287812698, 1036227015807837693, 10442906734009178473, 11284864730138525025, 9947575731798924567, 5027362708159125049, 3752129144967291560, 2960641676085640474, 11584372829953454537, 10976279527368184254, 4580831562516225285, 8086204985855056132, 8996712180244650002, 7715599106322448832, 15931472255763524212, 1971619108491661283, 18244317999002456195, 1284415258819328801, 12125649841582739326, 4806115081395231902, 10635010712401904408, 13489993017783266749, 10755180102170600666, 12016345415613188833, 3471063253445106726, 14021420171198356055, 17293350725318280803, 10889721386265843914, 16367368287829061159, 6301860042408593060, 8629376189523509271, 3317489641303687379, 15735798542524987110, 11962155895247876771, 1443629942311540747, 12029637317319989121, 7498249727135946277, 14712667982794134650, 12944084830528446084, 2764765003066482070, 2854445344561625747, 882610519371119320, 1386247692016949804, 11437494134261570337, 3707107567076075237, 2363673877960951426, 7184162656421523580, 1374330300807540634, 15336828516996887157, 5900781099131610159, 17092261865532565915, 14088693182396856300, 7691375190364331095, 3746409477975447222, 17991091905749914953, 14111419322357715842, 13211318834446203111, 5418516281310316920, 5670045581494629441, 17658334361689239595, 2108029137002093549, 14313622615058753167, 13683987417197870862, 16060144913570862782, 1067763430575665666, 12632051224603852245, 10851697926622672865, 9588075001168783072, 400613793270516128, 12297195143507882693, 8054731338565754541, 2296983723110295570, 15136311235051063598, 10701258502087521714, 11558922171074870259, 11722638033542392484, 14806800759537087336, 15531881014378368883, 12427494893532097503, 467394085720083263, 18159008869017580345, 5214197392903202485, 6579828274439693162, 9167401586009547292, 10817157266021471160, 3303353746725980480, 5316609299445779753, 1679025852722401379, 11221832940207984935, 8821536010854863600, 17311869774039475233, 15460739364466765413, 11210609456295001830, 6043888992904451998, 14195602925816930035, 17690712454067213912, 10708905609224242910, 13541652695119112477, 2484803431998114675, 905241005534806640, 2741427072113199786, 179516635379145221, 145341081986266738, 4109486671197751144, 9592092440988458306, 16717627225748860784, 18440345496969754461, 10672639747468022467, 4474225683973246234, 10670817900687737355, 3687654351172481057, 2697942980000674645, 4667131075695104356, 11914563608342066044, 10294211024044167256, 12179704490813269468, 9011172897832539131, 11966680153227839937, 18047985765325405039, 5048883640165276858, 11131260788346730474, 13188143378547512028, 3377339845104314856, 11824975074156196159, 17750235040691621925, 10690204996569842363, 256640914422017998, 357868591023193335, 7876808526238499727, 4228665387819803646, 7578347308951882891, 8253955030111801990, 7255801529299328384, 14954517686447376866, 3929485329094621864, 8602942584826959129, 16791305395345025533, 8712508978289902124, 18383688978826077507, 3668185011075959874, 1847275755905255388, 13833908477296618289, 5832883455277909516, 4168134403464322648, 10925334857444642955, 12275783674949681665, 13388380204448837518, 17172136531633985230, 10080697440998614693, 16579748389167624320, 12262047791024296091, 3883734914407012192, 16413746672773190340, 9163722456199806655, 13632385029033553946, 7257756678447084352, 10570740578549843944, 909182340352774742, 9973440265165496585, 15793302665658758423, 892957810907494964, 13567460345135637802, 15915801753926444463, 16314426909780627203, 4325332491558892825, 10282318917480106916, 1430342891281168225, 4340436763451344083, 8602444773228369786, 12577613701092723202, 16840931257276539234, 4094467763753102002, 2249502336046865460, 7328248091561257375, 4621638961215672766, 17229541560790693173, 16545671095960283233, 14518571375507105332, 5804973654107391003, 8709229380030480574, 9990434914736733794, 9723644027904806142, 12057903405794717044, 10818591074630083757, 18348136862696637400, 14678266375372084601, 16900409476169964341, 3034963882425259293, 3167651946632659846, 4410235577786583447, 13575184744453193590, 7077248547196566543, 16830457306748119087, 511485899348349454, 6901473958934680887, 785696383276801953, 8922677902813387176, 5028694348653606724, 17437317432033809094, 14981237845783583485, 7400686487113533807, 12001974820586931621, 3118056124031208024, 10717883141114711950, 17013562329850461449, 7532923731827628356, 1833580041892114837, 12251179626826968345, 11548412145272879822, 1120123386501627862, 5131867092830440217, 18075081008098942170, 12014815695321045021, 18030589421941047544, 16504293085968714380, 17252487903048824044, 7640487705898588388, 3897229150582196255, 11439950389496976994, 17513829770930387561, 5124348564289236103, 13515270180377522144, 18184762162962780302, 3688748029759276686, 4903308852396077465, 18338836340627671787, 4911275278056517679, 15768289954506458447, 11882722021630771588, 6718393444557840787, 17679718798591753847, 4219104908979367799, 11823590828003448947, 5792287036297286600, 1492912452063926925, 13338698090707287608, 7078736767135710087, 6895222399159193001, 1613471817627361876, 1228002015523674896, 9110592915729799342, 16469419496360499135, 12414779780779902169, 9455433338050198187, 10953322759902347771, 687091476176112493, 5471312586012729173, 11228882600950307957, 632835700636907199, 17575996154731445607, 2880149435400104285, 15321998767805560423, 2018468709500559555, 15035929994060302869, 4685637389004573381, 3702610763727170468, 4896722462139312004, 11612596970172007145, 4616444404271446613, 13042306566897879324, 6076061359144311187, 8320474397881696685, 8867301758476067815, 18387741191438019300, 347670170064456387, 14761545560141811395, 16303475827138059519, 6863265773658620949, 4261565355829199190, 11772361460121452650, 17423974086149689574, 12681129455489980346, 5754420294087598158, 7964184772992158089, 7006632461862580536, 7230054181425297855, 7347859753792559535, 6882434486449872811, 7102419138826470627, 14610386652763771585, 8878942332824329099, 11644699200154914272, 15054537940617141807, 7164285287229640985, 8022822127993686066, 7058617349866886726, 3019338566698601538, 4696154451315354756, 6126435485082221366, 2654526620337154797, 17276765426024735235, 9289064677212272920, 16894647485984726643, 14973287106016047023, 6537958514178456591, 13768213571063461973, 3189698594428075903, 7040981916653914956, 7476787091985031490, 8122024880128693863, 1485994591131551483, 14539266872860076173, 15075162335010586478, 8663214674123590959, 14980664576759386812, 3264511451583107616, 16660442336996209760, 13755067931389298150, 3555348286524718365, 16066823018481011177, 1009485870684643739, 16928829830176023338, 12593383784352958789, 13576909900638717802, 8010754241336861457, 8194925413818645067, 17501332405299764854, 18044180854274700566, 5663787458489580246, 13083485429814184115, 14314282841638677445, 8350220439067108544, 8738835826281352023, 12528500853838783816, 9812633903167926546, 886282588018221528, 416147658393672753, 13694192015584360325, 3327910040517474007, 8172937500772585829, 17333974400158156025, 11848986334948736049, 10622557117777672416, 1129941979036597547, 12168369103511572815, 9074668820441846070, 11533110649544965806, 3156369834071381572, 17936728294421846939, 4561241156147284199, 13734562965145777350, 5276857787442099625, 3990232838045952002, 10728645564246549083, 4822495109057834927, 4429949123242424233, 12688029222319074493, 669680392456321210, 17722380388342762339, 4269595772790284951, 3335023966198498491, 11516392821056344201, 9041952461508609253, 15687025895078718235, 14560897698334506574, 9016479274115282812, 16897021433072924395, 18172555947711149923, 8613359814568774235, 12662118507684162438, 18115608179444768196, 10096995119867331301, 15689359985844883957, 5052951553295244820, 14194640351068690551, 9226144077055849859, 7070792885547658582, 13478450510867878730, 3528788801611599888, 1358031493355295656, 7215903336933229336, 14001607369109031663, 11296683305872531621, 12225728043235597625, 2783845218926930333, 832523950912558029, 6537921841160872686, 16655673248615176903, 3655607938115286171, 1563701058216047015, 17498532603296576941, 3724097542032768642, 1322295798949574975, 14822423238604209870, 11097117957896819969, 3937819528496302837, 17274565246881023067, 15537338620040053121, 1415840569465800875, 5097809290847166342, 13308794489786964510, 10045694316133243145, 3203702183981460129, 11892246328800749268, 5346819227097419135, 8161642858180510690, 18404329522341705953, 6667284079159551629, 13331394309390364091, 9418064170232105489, 14079617197476330632, 10007761636440287929, 12914080562421721628, 18113231676002877066, 786975794319221829, 14523653887731625294, 10180382829219895764, 2236935642758046746, 13537255082936007982, 5027843085254689574, 896691321163055234, 11678262980292549278, 17510613197338625579, 15617034645939458747, 6426372294284491254, 9878131142019681656, 7028419299471247274, 9951301707966380523, 6051424005064861800, 16321993232172611515, 6009273340224874864, 16868777393760599996, 420080864297372651, 14292171550152541625, 18017208527943818861, 14260202539735654373, 852696131942719722, 6988735350972839043, 3318740395029351344, 4123261571324085504, 15548297437520045000, 4527080397327303882, 2885662654426481577, 11553617744287073167, 13632897248287146672, 3155708576640639179, 2806396943812538034, 12960421410313926625, 5538346920487066869, 11936724786881105079, 4454497098555324939, 12124962776483380654, 11305627091649666474, 11735775105402210825, 5333950336526186205, 10422103167921191032, 14756072429691103006, 11750422858083924515, 10208182356772880837, 10621209043357401646, 4390175275014413825, 16261941456326475333, 164254036716799575, 10166844304615487512, 6244791849379505525, 16078011614750997232, 4036318310177585263, 14361097783282321656, 14585505580965219492, 9507822645456572052, 4664349727078578430, 7052354054958471179, 11947092215759110337, 13460111811661626699, 8994769339012900452, 4277387408904797372, 8360068307002692900, 9310378853432279044, 3615902653439898384, 5041769760427780496, 13410727718700716906, 9110797065505590467, 11579771720285768750, 14285192567240714149, 17274599643845366595, 17286874018883337370, 11454013703351143610, 5597926447486120953, 13176325654882888793, 6313101041421319619, 108740634031532815, 14905269195276741638, 11322366307935514017, 16815633528983748913, 5882022600736612155, 12439189562728364185, 4856643353739105379, 3954327036570021262, 16048674300333666208, 15827759856980676596, 17069752674814299652, 1483637473027207338, 6399302372831392528, 12543829322110213119, 6557398028878481559, 3235861062713108609, 18114854664282579841, 7928121073523092773, 11824281386341684618, 4613879360523932330, 5898762324569966588, 427539657478203002, 11065231551776559723, 429948483707412069, 6017279081626619506, 1434241201696613539, 13441512677683347815, 7991819517048182282, 7820532433809080051, 12291118114411950946, 18038050760607761151, 11250884854027075924, 6536389319007101094, 2979526318345262538, 958731029266946664, 9561847878611512227, 4955270217488244180, 8692233104356576272, 5650399453825682919, 5316898078890392808, 14204725556732388857, 12472296594517129237, 114028932859603693, 7346441007951279455, 2993553390412865590, 11214018066767678661, 8216551076124430893, 9043724174699501024, 11187961728062826346, 6973801053057154092, 3191578252155726184, 9278206335605853441, 14382261713468120095, 15680426048463410266, 18309945385029197397, 6065510162527225490, 3719251193844189251, 4582246851961785569, 16681448117305890800, 2912633942611231941, 2429705579928960963, 6988351191388166237, 11932315913872258577, 4931244219942820925, 4940928714975771244, 5324071194710253709, 16277125251573781039, 2751637676037259786, 10401440256814804764, 1307572889759068499, 1502250984032475492, 7726545925440886045, 1656032806662940221, 11822218397552301015, 2289520846031533964, 15490893692267786891, 4535934513444611134, 17633149417288572702, 16874001204471565927, 13540306092530783871, 4145907438805773709, 10871695985794371090, 5005301488035997955, 13756561158373279308, 6896402457870892227, 284706874677256937, 2580973494286396192, 3836219749648256661, 15231665013567003561, 11612604375066871019, 6517307196995501234, 8924364917697766089, 9984145169861218661, 2870524370981372424, 3933185181454136636, 11977430299213353784, 8471957562861313117, 2833957102140580373, 16977932011524885779, 11426873969291870718, 16401003021892216560, 5223971594004997778, 11164273851659337825, 15108691663490140242, 8946903902462228322, 17743480016719743536, 11670221545230088109, 12173929035160130791, 14127233364451534793, 5537616024506708066, 10990324138102407756, 14481409468334196024, 14922231597684630782, 16012376992552686237, 12540288017260078276, 2480498301539644183, 7472323237010890907, 13559737596066548001, 6418157844127987707, 9864404905640343955, 5128898457183887413, 3872687913360014460, 11423567717750037264, 11523574907142504854, 14716344991839142571, 15831732058740562246, 11006715245055274608, 1199701175047093182, 2149180782602444574, 1421128213655392022, 8934095049012315045, 5459205696187852592, 17914269599441710739, 1402122902543914213, 9044256663261456705, 6406909240180604811, 1754865501804167107, 1761485560842534079, 7291671102292596380, 12060138754799383202, 11472026615302964201, 696057073114098665, 12629911631647560962, 9367347405349590600, 85807136927016125, 15430213380946414862, 12233268548637196687, 2140692199223470805, 17737335457474117675, 14908016691200697723, 17804554105716051046, 15069742595017583075, 12525483225890821211, 14837612620041397231, 9670067110512761492, 17714417835835552983, 8428117771878070096, 11562484570396319871, 10526422333922154544, 11615006619466995865, 13452572857187284567, 1609873102665335578, 4879154920235573125, 11010206388113931565, 4137448431318189276, 5968008172826792067, 17162550769485448158, 13909224795264552514, 17630913553694492809, 643009131249431123, 2207362898923276875, 3448854862427882075, 7262560717947893240, 6058618404810332952, 3268497246010872177, 11957591260328108638, 6125210992988008288, 5047137679409695221, 12728758876124663989, 17029066770181704401, 9178379647957568897, 15507807900660863525, 3292952536722640354, 7050459093823182267, 12340393048340211547, 18336389747399520777, 644190587862899283, 8023959351238392671, 83727676981969748, 16584836488540229052, 1259432055716651306, 7727914358746015216, 6448714769369717457, 10278960654771263010, 15199591652851415939, 7062747548846039875, 8811388495913321729, 2711047781547287895, 5401009748431019206, 3824967589243349861, 1526460623375056008, 2465353132172645194, 14826396768770243764, 10906493952495351160, 15460723786729923232, 6062815131777206320, 1377316900622524996, 12800047861216579689, 11815332574635611781, 6065594571194629340, 11254396164654802195, 1279831430879743741, 17214226290291957102, 16983364995788549700, 7012924463687489067, 2997757160603943396, 2417746965176164872, 12143030173664736699, 11099341012873078843, 9272827296180936057, 9664025317089888748, 5158247874366416013, 17037506484977904136, 618692057566195685, 10784254437015823955, 7040574858791904652, 6519736019879042146, 9770135322632666665, 4170596140464934956, 6463094379474393805, 1072529125484704476, 4841056206278251713, 739244513488127808, 17148076982612194465, 8805269968390532559, 13887881542261625314, 3366926544980853178, 10348128422039475858, 11820238417797034629, 7962099948786351603, 14818709100788043938, 7534275744141732779, 15843587983232353197, 16879641327119860831, 9445713810238212537, 10789773358477883888, 11533828394901429930, 9295477255768831460, 5790856533021606615, 8333830111421885632, 17773010270819901596, 6505758672939126990, 7969176850027496505, 10938043141814890949, 12181594889570146041, 401687323080081287, 13924025978165151092, 15397532958907819783, 2056101797584940312, 7742931591025575975, 11124839955692797850, 5114695543398304656, 4518298707923922944, 16877557778441938008, 10976178479860920849, 13751444909853634815, 9773498238519080356, 18135455812086228799, 8260614999062789364, 1025804710726167431, 11580541884499409155, 18013675698992726523, 6713678418531943563, 8186296733002816257, 165136842509319808, 15267111329319412552, 1264019288126808215, 18059369012090166399, 6858689468954000456, 1334489658659607346, 9599991333640053082, 11701464904365002057, 3854923311258700669, 13150991028845012172, 17021095010246530720, 17896123562985460032, 14525228140230556154, 14025688135222907262, 15309551971735811350, 6139869695052085053, 17086137392089401258, 18374020364774510211, 1228409558703295466, 17984501054878977687, 11478733700613093594, 9807018845906174394, 5116050770904746964, 253781193362282034, 7977918401840910181, 14846046156658368537, 18188202868821956474, 12345573536400494969, 1137168150068290765, 1098033166201752795, 13979129705387039996, 4317707477574981873, 3951870491690795715, 8980981677896386476, 6941778574542064618, 18257719818335954529, 6566600869588104931, 4027201752989399733, 2614999819200366970, 195374302680629540, 5235101844655770717, 12318374474018970184, 16155186168361195946, 16921004739228036228, 1020916417531530896, 6587653082428756573, 15225850526589296014, 15576607236338810110, 12023054768107002055, 1268885256958117097, 1387885256395721962, 86143020515480382, 770859194853623071, 12199285654960385502, 2671698434115520767, 15694823183817751335, 5262937970748799529, 13165639376314045335, 18123748696869614254, 1691330945206503377, 4344052292378390094, 4980806319203410528, 3869116687748586797, 16959027439001726553, 5479329206018608168, 14617542496041117010, 732506766617530293, 9267567674637442447, 2895098663207534116, 6132091457305790709, 11329205076565039645, 3761087265440840348, 5142445732760231031, 13573259145836490154, 5065000115155919536, 2043805904940961196, 9629132978962327986, 7244888518089969830, 1948921979722125022, 3313201915963548230, 5757814806871679459, 6094552970640076337, 1439487867693348435, 14417385597401774055, 7841792999657658902, 3076809775902249639, 14814563776238376067, 7712812702438315350, 898014195199434041, 4044248619428358689, 7613922997582320177, 8490531434165853067, 3223592688880474029, 7232119155624682394, 6370122322792490919, 17291986194226706841, 9513732286024852726, 2707459798290295657, 14946966441201639899, 8633812368898027351, 16683352123811299836, 9776364893153619186, 2384839478093779221, 17952826390389579364, 2878951794358881640, 13106943397009054942, 10962082447119441594, 11714960526602107545, 18198260212816385861, 16638971078900097217, 8474088692354411132, 3730125342381902288, 1920529178255848241, 7982008994855916096, 10492251611244882579, 3045343214341924821, 2035230566268106301, 3992453840084465649, 10103901945422429452, 7973222863593860365, 18052915162214720421, 6926081449378421754, 17481391009761975025, 770249856887805459, 6913840410997136795, 14978985291892326303, 5700257453542123820, 11921413291993075035, 1371903176063359325, 14184549292918054821, 8498988469340843940, 12069095114955064545, 8255176110717313286, 3697699706969730497, 7452682375661551542, 8499256547722143535, 7382594324831597176, 8626942486336636315, 8956465048555252593, 15950113059022757973, 10156648759102264717, 4395696884234079020, 10036245504043971129, 5950619280132942479, 9168460833348158874, 7620387487793767514, 9277320833806734008, 10382865638416451480, 8411739037702301346, 15801274139139552145, 13692759444960236941, 8563292317718588244, 10925108551772953001, 15308221065571417876, 12606519560536496815, 1425600522958627644, 14974380436528759922, 302177378847238152, 4334555303983646630, 128793880545063465, 5507340077141715611, 5054619723051255696, 12403597630560990351, 17073919416859000964, 9281887294428457895, 1488534379756068778, 5568344527998161881, 13797501273282457715, 4488385602017344411, 1553738284126167233, 7903010851789823832, 1368825049294659792, 6765641777280503880, 10507216635318096685, 8961380496928780667, 11241770898792963184, 17509492195761274684, 7396071766087139346, 14251591074268897344, 5086964574743594036, 4880908160114797331, 2235630954691175555, 6733752218135280084, 11190266532543308203, 10541603736673243674, 14990593910397068876, 2179293842335286944, 10941405748298103474, 6854075889962691746, 17124531760241584071, 15375769732150799184, 3487279552700733733, 8699616349045582587, 13163169994678372657, 10596180029688151624, 4185715526490586672, 13678404153576422235, 2088615142302400637, 16697270157510423652, 5487378316758341360, 14880501956946456619, 3734812580188132853, 6979371733875968251, 11881343947991552925, 10633021967360223399, 13491982804411891763, 13213376568500536010, 2058922053233291267, 12881536125287205059, 7874132473293104087, 2501514450152693578, 15171006305203001186, 8909432522370667253, 18054269355355933961, 10313552183455136101, 3832848210585996650, 4606578973882183018, 15049716177665425881, 11790008416426702531, 7299530752113020112, 8569064548093242975, 11538333797058080064, 16921140284614147784, 16062010705605068840, 10172456083532452532, 5879039819604254641, 5844084193748684986, 2901572555718625824, 3154868065983899039, 6079151086118673158, 10833945584771699263, 7749273335166854823, 5714416769361852910, 2856733009890239285, 861486403877371140, 1603264402517455056, 6610410755884163844, 8741999029695562468, 2720140197580685707, 195099765755947882, 3002292589827409659, 7280149689188131074, 2642105055100929838, 363920280727416429, 7155051547275182716, 13420734408574626363, 3383159474916359167, 744815011998384635, 4792413897876970982, 5872646386592314832, 12847609697504088709, 11049991000453989924, 11778505465529757045, 16644096103569552997, 13132639218780573483, 17735276982649303508, 18324604540958855318, 13751001906313080019, 9280247986707408879, 14095442870869494842, 9220946755408984076, 14175583104563887407, 4548175433510589664, 12894769826017544143, 10391970538224194186, 4124450461341175034, 18326013397595057116, 14639886094494508479, 16029721131827725713, 4913057860707405985, 1342743410006138344, 2155851841363094539, 5569763813476663528, 5610030607420557801, 13370015946103513354, 16591485597018017373, 5090594226365374544, 13513116075969985364, 5397789496524651749, 6325333914758699623, 10021901477969961938, 4685259496793640922, 12660262814582224254, 14644990613126766624, 10535025267127768113, 16118427467518738063, 13317378382651159012, 15563740596549744348, 7217572356154676713, 8628546738744453130, 2610104798471691778, 17619854956884267322, 14218126334866390765, 16555843983955757581, 15263173850242170454, 13761500681846019210, 17348110822241283702, 5502484046183766825, 3294179870989894738, 12416341159928104426, 1999625858621638274, 2862266536813639513, 12183136020749935755, 17897412530693306043, 4957686079307409548, 16645344857638222138, 9643043409865754403, 12234909134059228744, 6668513591081479096, 2342611675640859764, 18083178289407029800, 7998389929560710048, 10851828003425643619, 14984495328198583903, 8980101809150358094, 16524003296347874279, 1474933593585755651, 5144422401974480352, 15712825936980779182, 250182768272668706, 5121690924796146936, 4971458407555002659, 11362565773279690951, 2836476881889502752, 2865560168686439851, 38131667576793724, 6418143577872873902, 12677992079859880769, 16657750063059423772, 4986738252060260763, 10837925372402907062, 16150081226348307154, 10396350591435006631, 13766091613372915604, 1549496982697356105, 7792502859194314858, 12761572613067197764, 17049993598526082459, 868729278549666045, 1615996458243387652, 10448645719813456995, 14691557604932982497, 8513116463021305278, 3646034824771746171, 16427856941706896762, 1478208271091648021, 7352097525108907535, 4553021145465722797, 13739331677419028919, 12109675070757452580, 11753113013883440201, 8034056646251312605, 11098667427307970832, 12556016254090077813, 6818557622115713005, 5488462183448755622, 12037029063880715057, 12387116855729309193, 11649941887264343014, 17934840540156085492, 13484602771387774047, 12071971451684572918, 12318286660913819142, 15000129779756918695, 7622652981715917177, 1941141261167294069, 10066274630204119671, 15700113432403355792, 6548237200041107746, 1317727701078369716, 12538601764087511866, 13107739114994017632, 11329245241925466577, 8443732354610441919, 16838034729120458983, 1295367438438984602, 13208644763541494811, 10148259094169859404, 2977227751878274493, 17188840334593079627, 283448850202454244, 8401837417216766185, 4487644930048504532, 3156993532811122373, 1138015013744168987, 5926890760746486500, 16264358176148091366, 412129087756566499, 2611107355404374018, 12856972341657392961, 3407262884040770992, 6837804285766927422, 1625957534009986762, 18304560731519780849, 4651311055214373439, 2842766752688257234, 4669846989537204528, 1150750474478328166, 9283219454858343324, 9676799940058516485, 9535769819821220898, 4216118818081696379, 7986805549489581730, 14868854119363157417, 725733410570198205, 801999277962258001, 13206373632625309059, 3760414440586727733, 16840016771540534492, 9282485457149687215, 391660042335454040, 89095263622412647, 667207475971320549, 2435833794203345512, 15457776145581912292, 1266826669088883628, 15972850652875384484, 7181604665995622887, 10279792397224347447, 3646646678644615658, 7438918469622920053, 3005423819338038989, 9214478018440060298, 492335584352534986, 16634613640494803192, 12802460657367498847, 17508961995711425056, 6430345804738922208, 16447927318274766099, 5642694475860178585, 7676330869648145581, 13281876988262423281, 12531007649212465595, 3098228591464601210, 9928444057503016020, 10446708652519584832, 17663019705237623696, 11611354087596473817, 7972196754795248838, 13883479044827771718, 4030336379541805318, 14288630327375339473, 15336739048455044386, 10725470152329451086, 4511132777640431631, 2104159951384601163, 1074648154669597319, 12576298471736230338, 3988484885384363660, 1896565318825047566, 2192489736970121614, 8208783911084384627, 9662313388797282250, 4042419181841741058, 9436595455667108373, 14630397932342980447, 7418269832739529622, 5582525728087765736, 12356259344183898484, 14773185212978089317, 9021406452090249914, 12521835756457456438, 13300392157047361944, 5786616474159631237, 11658990613893617225, 3564145209044171749, 6176094153853368204, 4472077630315691522, 669490520051498024, 983973593760858360, 15439105675344215143, 8899845831677639376, 5542861433123934028, 11219402864556685554, 16228880390469218684, 3535940373392638788, 2388420272100198976, 11501553552198346715, 4045226064304188825, 17164733155110543079, 11887602938273783707, 2405996419585631660, 6313079676993177979, 554293591942122383, 8111819752396326540, 4618132309026710151, 16496971100102831766, 9051035532500397457, 6466496038777077423, 15468435833615177307, 5940699253740568860, 17718623687002183744, 7921752055496583008, 14083952605798838602, 2784508214930637696, 827210449935480354, 10523898530260576693, 17261757252211364439, 12435872147459061359, 4801120065269861679, 4507038720982711353, 15022958300666509337, 3466195915775756041, 17056703437397795899, 5032414486866127579, 4460407349226646342, 17618491294669832989, 8342035164337146088, 15835140500563133213, 12306383136166961273, 9311267541528810827, 8710163699797239159, 10527927593789976089, 5023057011324582236, 4214395317065013911, 1988021212043469334, 3308854157275769242, 1669821858580911503, 1292299602023200349, 9999700130597378451, 3039603156497167303, 17231017483669458025, 2459852806047222029, 11079756598252700442, 10112619658231412747, 10770614875273841990, 544736197283340750, 16580266104210218625, 12614455090929871217, 2934226079137110511, 18004304398447730016, 7416717446208912085, 12163064049978815111, 4893763963938738258, 6509354404907597721, 6325085281943652570, 11984901314521563718, 14282973825477465483, 5714567012661078960, 16772765125071416533, 14651207183300066940, 10191770239707765729, 17149725124332256486, 4690209155634308806, 8520738959493303734, 14561086913064233184, 17800760173747167468, 14472389034842835414, 5403737324129354163, 11749701019289937875, 4741513798969134715, 9780504626937729230, 10960003022828004721, 15258900429112413542, 2262948687031028651, 6294928924020932131, 7547753650112118891, 10823591529909358272, 16832354587130586627, 14169835747462772759, 7309804829255164479, 17705713796418377471, 10742295753142489586, 7600981436366483337, 2427395011226258517, 10129372736203276174, 16753031800552306295, 6506489737738421903, 18059874435102886761, 2976515802180143867, 4156942128767398413, 13237126584532261028, 17008810702460226588, 14049267949137828087, 8758735846922903749, 6793053622933564358, 10478083492253714431, 12360026616848218195, 9291146653661796150, 6486933751821767874, 6838648905700449976, 15421478995275913640, 6509001710056253889, 4503397806109962463, 849610157122863946, 9449186064733075333, 9425817453208643895, 3545405330173226031, 5480088929666881749, 14998382455517742089, 17997091255332462765, 6490038724033845598, 2615971105626337870, 15846937377463844481, 9478678072181052774, 17198019661862202475, 16989872775527902270, 12045574565512903232, 1535739634699138227, 6870369663749928658, 14074141003578186155, 15341569269191922427, 6781073497207583805, 16387313021995867490, 9528582840408150724, 2889351218318895013, 8894114255682892490, 5362576750886764259, 18015538182640548393, 15407645145770926246, 7675871236873542484, 1651147983996178077, 17456414881325543882, 1481798489266646244, 2217203618641967417, 10855180092479814444, 6598233241408631079, 13065611539127026297, 3717859246570543785, 6729665115064723174, 16526117635926672270, 17881524254979056029, 11726308082414488972, 8314224276214531669, 18241927651544624528, 104200762255380907, 3008509790108001982, 6145139744234379970, 1036038853992424695, 1973355598635229002, 8570635883412505884, 14054581519160169224, 1556201076209357948, 15943768594544228268, 1513155835862984066, 4363161143157494144, 5820377245820278256, 10198361540002917829, 767043871261244881, 7443956531685316056, 9284331333096250621, 8935133575787953006, 15200652193392659189, 8056712435239102863, 16756818209019893602, 9343226056494439350, 3506162196904760966, 6260373898356213156, 15150209586446889979, 2784586581379403342, 4540380141065828865, 7757418812393030281, 8273294732966366961, 4727924630469683301, 13375618296146569214, 3964754111798509444, 8123960256194764713, 13998712814232413275, 1152977784398432330, 5890404343588959641, 6950895782734829498, 5059884094199777410, 16597208796982226, 718843944856621102, 11848918483770063267, 12000925027170347107, 12597611018517804046, 5718998717332312877, 8110605227325508456, 1985758694665945275, 4519633440143326178, 13423707213455231658, 15784938969952654968, 8208544497117553485, 9659953713035913903, 9321587020770012756, 2087882724388865696, 15335927353602577288, 4885014610259028587, 9372743482129951826, 6274778247258661234, 9634411916626919826, 4523001562907364613, 15369212986412657667, 8840975084897747625, 3064783763370957235, 1622171395572591443, 1400903150821880824, 3145798450489825432, 3019929935687520943, 4514424740291089162, 1119017893812439241, 235132163998217267, 13364228050998359839, 4588820876082475911, 7195397215200596297, 4633351752138300558, 1200561772848463895, 11999111784877677855, 3515014993548986881, 7630631031677618724, 815843603725414525, 15924302202194543354, 14763652070709132400, 1449365498347098434, 4571064241668101422, 4292811896359448226, 16453846927054309997, 426837151166526619, 712068857293805334, 928449188054083970, 8911797645243492493, 14891176613544732991, 2206577781330260168, 9335637607885610626, 18392467357634279632, 15765389947245465563, 17393660415076192986, 16085850839645596007, 11691058094766112608, 2817179822694367327, 930444656245579987, 3164553527192601352, 9174958030450605065, 5376840420505663371, 11107902395101842683, 243984915529749293, 5518860592235265115, 7615228019861017436, 3920891386601626615, 13494884915155497444, 5294307483393825921, 4041905660571667001, 1633580366026153454, 347906503315428568, 7557404877313144124, 5267775115526069937, 4938397725897039932, 15455077922444970484, 15549977328403561026, 11991859023815693028, 2964593792497517781, 12853508080092904533, 15007139139577959607, 14255373463767235095, 2167416467128614253, 15034193822134529069, 15542412129864400355, 1739094818789829367, 3251355985939667959, 6188717326774755165, 14676952870412609933, 12843647308683490155, 12693426455139845275, 15441717063571747950, 11292965910125324965, 18416540647565742265, 3644383303581996762, 12454603000034434095, 17258137073514536075, 17035480272282368486, 3692027693098460257, 13042244040458074122, 14593709879345117166, 377808174597068792, 3910597941335600101, 1639206563387626349, 17639685993484083333, 8341893781740907026, 3399482951883713266, 9494556199895966229, 5477425431243160927, 7506325802369160085, 13434567653969427228, 9137336048227511331, 13041587471477288222, 6583663533314467526, 12733881436954683825, 1209367975582170770, 12621218467455625922, 14529850862267842457, 17399463206531788152, 13183797877091275002, 17218396986893401474, 10472885892073183987, 3023406489489045870, 16368766808557690360, 8037618701151923127, 6106039970594201131, 16602642324869267867, 10069277905876386041, 10698031878409163893, 16317483238809829466, 8622589479253013357, 8035830134083966202, 3466789368751326950, 8809822341797077328, 16241448642666433623, 10634479988374588371, 7351366827359208595, 15379505454490775443, 12524731493685212915, 13198010890124456961, 10281590580742577462, 11815743543936657353, 16427825605786290275, 5206988116217064154, 12698993858793472480, 2147098972970774835, 10844703842232588345, 754149093730464121, 15524670084145457365, 18442396931289442600, 15526194806214575227, 11226399258068037952, 6803959331859231227, 685330062188179512, 1667774848728925310, 2477557307441249224, 9107594310619086447, 3467444511657093926, 12974103859367141247, 16065451317684768653, 10424184331911790711, 4986897706620920921, 16445020967004563083, 7110818062157330393, 10120806882027715724, 13342217923857744053, 18119257660241875712, 4587748292549759312, 13986361365713765580, 192845879240337583, 17739304337797051346, 620118818440128083, 1600199803056704504, 116046090030718708, 14617471831122659266, 13943584176529643645, 1112657171573544393, 7284493486199486007, 7309257126821711860, 17260473038559056656, 13283037481207443666, 13665385997096965883, 17459542133008358045, 8267138424051619797, 2799174643161534155, 11863012576953080530, 1941987460916586134, 11943360221741722363, 1457715441863528715, 277329889242428718, 332873825095835194, 7501402992688587579, 3628806491618898634, 7768316150525370308, 2993059064858857122, 12301993560945128533, 2080438918249564342, 2720997471111607497, 417122196402345872, 16746724723643865223, 5800623165948012296, 7278930935549481211, 2205036363744818461, 15383578674856097783, 17688896809108014274, 18091705869385930641, 15299584681599895689, 14341958767182589412, 10793720060741965763, 2388709234383191992, 13648455390813431619, 8099772337498694197, 11310861744682595222, 11160192519470468011, 10509581407755286586, 15373404840384875718, 7278990844786196949, 8794445823871031405, 3098191891952046980, 10060322354539802633, 13823794368891250532, 15805011174620089588, 16945784220420378289, 13590278912550106289, 3592661444908880171, 15949627482054903045, 15772915220982128265, 823197668483087459, 1618046035248201472, 1569590959026390225, 14523234633419544388, 7961503998156731156, 15627835578621440869, 3560306887993015418, 6938587264408152808, 4787752326200843144, 611061396208139781, 11641518795898305841, 8324161177781401618, 10938195331294167031, 5851054513035129812, 8452327800224939966, 10446295932308757205, 1830073659885394871, 3279098048840542481, 17221852200905023571, 12950231534805229080, 14424497750515463186, 16733053727953017870, 15242696754808178265, 14920851384706958163, 18041462820381813550, 13238602970376315330, 13242119968088342859, 1733782148141510754, 3448505378883116750, 8186541718004755311, 7131351957647573506, 10188018472213724742, 2207173121534036106, 12108311126599926187, 17892207799400411138, 17037421531247930480, 12734837881320648437, 18126534759448645223, 4111714275094514509, 1439374133237106024, 1012729810458125326, 16402685735794125514, 1123233161750004286, 15010675148269385952, 17480778429271958342, 3110280444394188958, 16960074024004555099, 7993184340806640318, 5297659831179840435, 7367988682729477498, 7223595458419964146, 1214342385239353004, 166053549827465408, 16044557811456363812, 11956833600697072366, 1051182785418653279, 9036163790930076520, 3345291322848864256, 3766254070219277594, 4838760200219922801, 7064061086490458642, 9620981472707141322, 5372273351861077067, 9268560589347317068, 11896991449117870670, 4658382946972062559, 3212925312074794504, 7164249051239334466, 8982521670287388677, 634546871782659835, 4439935278560648430, 4683860465504567096, 9979318036592370962, 7944267721914772355, 926407151551170175, 6024508200551734755, 17644513304459109409, 4850626730876551878, 33742330204515779, 16029830391244237919, 18008080643688566144, 9735662429229401670, 7923291891026262232, 6492765676679809223, 1025380667418959293, 12291331628813390780, 4725341855921686811, 5019192253040683458, 12660801616573408431, 1798491736202373717, 17437116372297300095, 1146702207119796755, 9906894350724939493, 12556294068279879168, 3497093078755646243, 1351567753016754277, 8885792570339545281, 7808861980575456833, 12029767717793833754, 4672046316778539147, 2564702071323571812, 6195798103971696351, 2347332678935385950, 16025274631093172152, 6479168990306240665, 6243316335765688288, 10362429540780000581, 7993344388745516777, 8705452196007240474, 1646872239784781861, 14684873660364803941, 18072288026947543374, 13032728012411697150, 5299733198726218881, 9543973837436721304, 6053122207506134689, 3762184894933544820, 1510406071648488171, 12551920471843808738, 14226105012742626829, 1128399128656388225, 1483627947279346866, 14290971912789548492, 12463964661934070028, 5045475485173717018, 3152005529915689685, 17103568736274868485, 4007090876531888128, 8405101586358620248, 9937473108438343540, 17711053794813027962, 12507745859403893440, 4926600379393247173, 13155467843985734527, 225903764017035136, 12869674224895414149, 15563799404524158130, 4282732373778923452, 14127691149210333754, 46164326901096390, 4975883363087601606, 8969099128924193741, 5000052206585316126, 2988737475365684150, 4599698860941872507, 9040350077295174480, 13082787420920215972, 6390490941315643460, 14348441428418931576, 16462073567657549099, 15235294944329363449, 16315523965665762573, 41535089398351151, 13121765570651988195, 3957062665693927028, 515254810501965010, 14879665755970829216, 16127348355184074199, 6338785176491350083, 1759306290554890386, 4370834190411036222, 18089616164495715666, 285337772631130600, 12319821347949750627, 9137018167207056578, 11281056895414041059, 17372813089508340211, 16924685014312545226, 17454489946335356177, 256467995482802999, 14100328988579474424, 12333254810237747557, 9415666686529622384, 1047391820973039827, 10848706068771908213, 14190666472922576499, 11873504703487125335, 5180672692049675813, 18273034321108422712, 3535311693005977337, 12708395321856074946, 2762649881855117229, 14926839529439224642, 2788951805429568305, 11870118452934828734, 4432072422779606786, 5294568137458580077, 12885179771124208318, 7579343333299664338, 3904402522110232917, 12276342431805990716, 8408054797774319933, 13240467605703131992, 4690596374046782281, 16154879448100541682, 3803119835047337952, 7479937186444969041, 4857280192679190310, 6670727446432380509, 10888007857212732752, 3502021384983124929, 18134159133259661308, 12013884292814132123, 12511168716026218852, 15041763947615035820, 1747630449768436369, 15325131514659929726, 6703539015475553957, 14688815588447428768, 10368301362442999770, 9809572111807556873, 4460022268292037165, 17526113707193592812, 13269588295632932383, 4166204288479227423, 3216788132331712537, 9549163652044355593, 9844396548399052183, 9335851721631510288, 12676650725966656147, 18024438749036961622, 3131420681891221888, 16132675902897404786, 581927403140754533, 2754324863941832517, 9779750278789387154, 4297934551052203877, 6467356523142796499, 8604483201299499224, 6337408066829584212, 8922053472934621748, 8746945597319229662, 16971622123220156347, 7948504138275600711, 17735370366312131433, 12008472501734835414, 13291204068391603838, 8386527531991280088, 17133120987291052491, 11748772375292182291, 13526198700280450226, 5899512913956180185, 7266411146495216150, 13568838290051574266, 13033236152930383904, 6669538505842883960, 8121150499135604883, 3269740345166188719, 4698936081730974128, 9717231797239076687, 17953604985799701256, 5472963240502563084, 12219581918594554057, 1177923466299803888, 7220225792698698307, 6519976584059515440, 13257739288133541977, 8513973228295541064, 4256536311342518055, 4545785886955603913, 3814357504355962863, 2993386207472748670, 8742967047711331344, 11560801106698134310, 15814523315233922232, 17857691279016187605, 2139948240315287405, 4320804512615632576, 7825246577951372837, 17773549472581094838, 622682596523409835, 17947133725048078498, 8117734638310414299, 8796856063250752410, 18037619052916271668, 5796076881294205295, 17023947053361435447, 3935346903960768070, 374758818957650273, 8168050406006071529, 8747681807216328314, 2657007752847161439, 8250697365074967904, 3069370441040948847, 7251644013243440677, 2355591785155253335, 9024941558405974070, 12587136685658664079, 16009856695692496339, 15484672303602881469, 16147185411186423391, 16504884094715062458, 13855533029982388925, 14890011718100201360, 15613513089782136953, 8165117711830614628, 4152676446900699357, 18434519859021475469, 12433115243826354337, 9262683485290985951, 16961215102991701113, 13772978727212602545, 5439355243959409088, 13690835360790820495, 2781503970251780784, 2018788090954205919, 15873736665489401557, 1624467943271322534, 15397369596002880491, 13698210041093480449, 7254532444481365829, 13938276555872154647, 17403299192818230500, 17300900391753474342, 15823587634602776708, 13596982771906664242, 16517900074719099164, 16550906358301019631, 3383582004706444687, 6693998219827048243, 18175393713039033001, 9224838094152519332, 1001817119638508260, 3851720173551942604, 7423100210161735740, 601876652081542359, 17768598337583788121, 11907848480462908240, 12879608127741104472, 4578043373124941840, 3960728812747329208, 173270169400073604, 9613182110382996262, 7261894326870559465, 10852334891076958347, 10066751330920937418, 7410944074347516414, 426044005962092514, 7393759344960291254, 2391601550198502201, 11853343544961086987, 13309835142317078770, 6986670231910860872, 4275951483446283108, 9688908301648403660, 16210576897906400097, 14980068656282174480, 1481380337930648019, 10392181060459099960, 8998654262671254388, 1787386242116304722, 9482249120102287728, 4265617223531740693, 10442412550271143801, 17793897510873343069, 17171428856996590182, 4692740185767780190, 17654375126704136192, 11005676982629229590, 14284668016441548929, 11084952759435237010, 17383491326720728908, 13790740388217035608, 9346913141047548014, 9132025420201643264, 10994659389442857768, 8005151900929388182, 12532558397287408182, 17630313180856459785, 6409786025423439159, 3506122461599813718, 7980481922086521834, 2591953102074452448, 676314937024308089, 18076449756015982872, 2754945238605354977, 2697071483018576807, 13223028333842558334, 9060420454378301609, 11012363480529831631, 3563329797828938565, 4244145017166687325, 17767545229430850494, 7653249414371803322, 14583502847827405892, 2526332860421572859, 15958037269213558558, 4145329928447000171, 4471730307350457108, 7521251523140417172, 3111741595034417435, 6099109097781624426, 12021508046798894588, 5583706685772202433, 2602498476004898619, 6033589213449407782, 1510353808776771211, 12987062733178126565, 4649295309586282514, 11386724881084205105, 5412292907152878701, 3173705331351537802, 18156981629930402970, 7575917798563989959, 4907029581994779885, 2812829259529190584, 14887679915597054603, 7469589257050081635, 4036711473116353822, 8064603872881566430, 12589744487775628468, 3398796853962881829, 3272474912442022303, 14426577092658762097, 11160485656781492599, 14202444516205804985, 12484027793360908785, 17570996928062666601, 5502983724724173871, 12631809808658632835, 2765162484901831182, 16096645888581581404, 1922580848351658355, 3021651210670611456, 16725111780432998137, 16123666969517859349, 6818353363180347143, 8654332990526409165, 14761396254845316579, 2825364801562362844, 11688132862347855852, 639915178146882300, 14458476609976551808, 615091437364449676, 16965018890552839452, 15631632543181545115, 10363411110252146444, 4641768019598289534, 3337717668591499297, 4032279587062157033, 15715048231061282294, 8145342649114088105, 11108969196885954454, 12952335318953053529, 9779828041482081981, 2118029380994447880, 15543465899762612133, 13061358323449031278, 11029667414464801594, 6444974349348616819, 3478478453027033227, 11095132347296028965, 16622649840533858680, 12669350756637290969, 7604537880706889554, 11075262189205452999, 17848568097412720543, 4439380568850727902, 3050974537077464502, 16977762972576641326, 3071208956232070758, 12006925938232278918, 17139387541568045551, 1029028403147446993, 2531769580835082665, 3621299895812654421, 15040097540945119746, 3126376340493092964, 8291155842071126939, 14354644429618763676, 18174719584505858806, 594607486937478873, 14712489031452783888, 7521992906805861700, 7583555445032630784, 13540089462881207097, 17379778862108738403, 7497769788698834249, 7271297004671342163, 14978947979260447386, 1424662641618379589, 8177317170008198038, 2718664838590272342, 16843951979854132263, 5497276664118513853, 4777262616250457514, 16116133946405130506, 16384844676068622949, 13411539656969890680, 3428796555601393402, 12678089312746097377, 13355076607868992794, 730874146974805572, 10067155129450460492, 14448473196403840735, 14633029330581370624, 13237745128351506495, 4485472252382345363, 2464355242470120078, 18092330992486483443, 1608746660247486309, 11240083599284269315, 16767129078362415418, 12943617255526784891, 3387518134947108318, 8305964440059804243, 10741331734199493966, 16447837936971542423, 9386581477129031081, 5026063376792473825, 12951793209262677312, 7832228956945548620, 10847237584085266730, 6744706870591455793, 3827795409985050436, 13018060898653577737, 6897162046534702726, 13458224049337953945, 8793383525032746872, 5551312226569691027, 3673957760566517446, 16626600182750615858, 17964491861666341897, 13178253663031001179, 1485441606142367144, 8849644662345581463, 2987934691593642836, 17088012223663480541, 17805475483517845973, 9639648306195237530, 16170580609553263987, 803975342335625922, 16904392454261784475, 9496797177347695250, 833391991562050799, 13884430889601767769, 1399425793939971731, 9669147101224524506, 17387072155956429410, 10249368505544998668, 3187328726622350900, 6284671360870943954, 13885730698193800868, 13469933597227158867, 14865921771049599636, 11068384810566085490, 6672241429515474633, 767656968935235961, 1210338046709859412, 16266543621320324076, 10798914035656813927, 15298640884679743932, 7961930035371383040, 5655258760428371405, 9207134073914205902, 3899155088446105094, 17792259193674587989, 17056465744456219235, 17400556305547534285, 17502188141658577916, 7713328388382019919, 12940743948688393585, 8189438952002546451, 3995778812000715687, 357189510436862907, 10327019172184332971, 14115342301650128694, 3659816433284350278, 9242045595803247672, 492084308509986910, 15296058780201622957, 4103716578320155935, 10609017886137134648, 7303352787746979366, 7200863092744824049, 10946162431970607069, 4793907825411597748, 17221676203534711732, 2123197280153264437, 4490336379513946223, 4079195848999035957, 13897303357999428987, 14778990894625188190, 8832366364673069085, 11688078750300240334, 10156403777309085466, 16152060316096929112, 946073018639738029, 15824837400050099984, 2331032097341716793, 11749726278180048513, 3493980882668221181, 8553314938842944784, 16555546863807027494, 11342451878441368651, 14909271131547230374, 17753212539966711022, 13932914662177669490, 2244037794914221969, 2738235439278475922, 7976219997349009523, 1678514278278786584, 17601058859440730415, 9603606579608208382, 8462945328050541329, 4730866709237902283, 12093039977452908967, 4666928052580836, 5497566805220777041, 185606854266135538, 3679620669313527839, 24082693554547233, 6497385575924244039, 8003599111831814113, 5378003049550960090, 13602896386178353774, 17343085835266212821, 4284151436028780416, 7031446591435174981, 296161209152974819, 7771211154626084447, 4993504749934625200, 15899899719762915665, 5631006189516911547, 1520210104263088378, 13336691969159614550, 10099472222145463563, 11102134333522810275, 799973464581554812, 16696483008544375857, 17275688158593400457, 2830651348456776191, 8561640222838341065, 5927394439969190339, 14337331167814987197, 873195269832328729, 10951208197954893562, 7598038760248036011, 15571273667787969162, 642437384453728307, 1612201519235672377, 15088059640392686686, 3897575791527764359, 14088243142182984912, 7208032776641816649, 3392467592234537679, 18350133499320297696, 1370369301534692051, 14089000100660650199, 16590033024664363954, 4613841140259143121, 10948486091338489900, 4964486316614010566, 6108814066080624107, 3859061645497262242, 9929624355021227122, 12365087599218259369, 15261320050004905408, 10030282029223356088, 17465432443125294698, 15509237629421161755, 6721571464751422812, 9988866795627150958, 9033182163187335985, 1230513633149349464, 13410037090215851236, 13603148167465525942, 1399048741732778865, 11894863627095856395, 17097126701091498247, 5245820012173399473, 12943311619865068894, 11559376495772265397, 9907178558214704197, 8132388361641008943, 17479358858237055639, 17077092513540945380, 7575912724941868395, 12868244636613777199, 2843721422029125246, 8631483452718287224, 3937771687411430627, 7612340530213420538, 1632411560207547096, 6525956156749130644, 17879324930415147455, 13410977357394242798, 1264859501683143391, 3442427426804895011, 12339413920929722852, 14426536401657755097, 14407457523472832287, 12420904904723916214, 1585794846933417175, 6456440328717299525, 8226929716358767328, 11691968347019298064, 775237360506581246, 5688999584721067020, 6844977392207370769, 15974212211191916835, 7823063632945856633, 3556177597887157798, 1628753509556845069, 8358138361138028910, 4310772800450676148, 6922068004317423878, 42506053333018259, 14399301946228750816, 14858506531945257576, 467244703551498310, 2963637344649884754, 10869474233465961041, 5147667463265701371, 7468505150411182449, 6272164769594196577, 901090327063162984, 10381620034549723834, 15251473191487258386, 12240031983677035483, 130619789232430555, 4297037685308237307, 9095722555999267001, 15376634175844006339, 17930955480543244718, 2703287302620414018, 15765274054265256230, 18086736165397226303, 18406756160722155315, 1253540830332662609, 485808894919515873, 2048130977076397386, 2211553136252184297, 3254983787536093233, 3225583789107672981, 3465700358331572457, 13545956631613345610, 11257013535203093534, 3768554384420572178, 17680666510495636538, 18019613346842663244, 13683650661788039959, 3216837734679454344, 599768182346543780, 15351694834892667012, 1989348249687823498, 4435586676023744436, 10538276361095224243, 7775108989585178791, 3399671890568400507, 10057867644642888093, 4843149402449929834, 13835572318041555367, 8800852406641485791, 17112320859664463142, 14107454142887771966, 4598011239748494911, 16306487158209555886, 1660471658317783506, 6265159083777451463, 4979661182937870423, 15911077141382206186, 10583937503792622212, 12821209672436063125, 13379314410757060073, 5547367267265196321, 9327146685831728398, 18343093688835768900, 13747314782052591056, 16807537949609050821, 12285613541024393213, 4564567329408377827, 7114033999707759968, 9007070389230522756, 1867939081541596499, 9685628885188241199, 15449816836858405320, 2661580061957725400, 7930747809049799646, 4149580420032760508, 17666438595093585267, 5460007779168649058, 17356675974936286646, 15319285063623010739, 11241268155457616020, 4212136860213643757, 1241257408276375839, 11619927894746062143, 3420590129249181844, 3886069937736406626, 2771257278182062305, 7178241026728422387, 8023976869179869730, 2904198768396340875, 4399558450402160924, 17165664237884954143, 12428535955846507119, 7834234463575808440, 6170468324715467941, 3611715647217579735, 2689775469310725956, 17517019791755178778, 17399427211266158886, 12539486999876025945, 16610972628254475501, 5160685735427131095, 1053071193335831220, 11929205402515419489, 10683398745150878784, 406114136790304455, 10043508860585031939, 10476972703627940622, 13484157494360196101, 14639106592106172749, 5758975570569287489, 7797640411499256285, 7281315207961356340, 1919799239293125324, 13642360166378290156, 12575445858832217792, 7132983665440037868, 6587252534464540637, 5391820394707043889, 16664606660343981947, 6061927195190257111, 12868301027775621989, 13168068866547789098, 1318345134529141398, 11266663603744656734, 4582221915587287234, 6723933983842182249, 6062860569105782282, 4727183021972063171, 5284120009497525474, 6778511295287344467, 4843206337225340637, 10767518182754239836, 1548354626042658549, 9001977408058927195, 7217754508542745498, 15631458265402110530, 13864685302379111891, 13535152488792849972, 11818782599083369311, 9603495527061931870, 8839167499196567295, 16088151549556216066, 13482887515416292649, 2513999180838980773, 15608057147429203582, 4794774913131833975, 17638371484885917448, 8144969168948411819, 13965388907240272982, 7687647619807877867, 4350345813816806479, 10023434507930578747, 8532518202219247949, 5980099969372155816, 5518220377115813619, 15561231086992162674, 11915431750339478980, 7706791213665021310, 9583355955406832508, 6170148717887590541, 17259131867922972451, 17080151529684503270, 16753756347299773085, 5964302397539577181, 12333452998338138196, 8851688937286092339, 3768586873607448488, 14916498919739535270, 7999154263564268888, 809923163071843452, 18421613792137973831, 1312941051093419403, 2445381438822735841, 11098134972538191779, 17967301096450664820, 13824050126159561263, 4064030765568052261, 6477672197006089054, 13527512461763806053, 2111605512594216638, 4574411455434392685, 10008363457929914105, 2489430936389265730, 524855035488230515, 7683228374472821228, 2310156754124388214, 8169531515270404587, 7551208252532540509, 5657512663784848001, 9635095312974401841, 16164453424602712406, 1454360776919925351, 16083748669010295668, 8005759396488668651, 9955164538215072318, 14108427416365096821, 5846260207310163761, 11589992900467052107, 1185661327558100149, 6083166426747148447, 10113993265216780324, 4418653805692064053, 17645291308565297881, 18157338316165172541, 5844729449876416186, 17457426784643091435, 8780375001861987411, 8024301087269372033, 10726363838890861487, 4665112162461249412, 5691641309040964849, 1089361550193688438, 6657252921262118708, 9613139752297579353, 9206659400878617274, 10061109165927950517, 5006740993929657062, 18017091661979372068, 3038725011112820302, 14286878314162804516, 3711478827511187211, 7399329339103807107, 3277843147503059037, 1214589757545642577, 2641130110405329075, 2310964301861955557, 17244270578204744223, 8615488285531158010, 12395000459712064924, 10986585300186870432, 17798076680461624991, 10366363964870504746, 2595530900609161113, 489845555863713198, 6909196170366930243, 1338615857388008510, 4122435222372546696, 17914347855138707201, 252991105939933990, 2228648829562493492, 18130878113557923510, 3794528427945329583, 16570231967757063017, 10982257444688527431, 6215019330326783857, 0, ], true, ); // - x_high || y_high in limbs_half_gcd_matrix_adjust test( &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18442240474082181120, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 8796093022207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073675997184, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 4611686018427387903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, 4611686018427387903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[3], &[ 2515001291402742141, 854420613834689431, 11039020760595827143, 6756568413549859118, 2136202424706040178, 14816339433745171807, 5979726425609054965, 17860763079996696285, 6137842758941809619, 16208311820416030796, 18420476178176474797, 2134933733929182961, 9646501134892720916, 1462076564527020674, 15145739517548143307, 17085395263023945148, 8286583684341088741, 3343151313427310229, 2575901666292279126, 6307558616370235581, 82586436666909222, 4828590655561120997, 5416657653621327806, 981277938279968645, 13261936915909041036, 2650518741132171629, 6246594792539184293, 17110677893222712596, 17080932936076115432, 10710018177426387786, 8319370182836017772, 54644844274267615, 10338588040015641008, 12314370078315829535, 30985249843116621, 5860983927537346563, 7300274990782092627, 1032465354725755342, 17918827441796904950, 948266268839213404, 14080050351370841785, 11154163051991817178, 8418568617568650378, 2931808994425212696, 14520755666422248554, 17879225383639426345, 1389350041568104293, 18418682222614156823, 3626912026478935225, 13691264771654640536, 2957609324705255103, 2504324778887164565, 540648196212357210, 819771208764003611, 13207260621640142174, 4225979564410740502, 17350218361613991007, 6134528954232718156, 7854153205633315907, 13395593586288016536, 15762316148952715379, 7694036610128122312, 328606494635430301, 13668443390964500027, 15891607328268609015, 14158365113256769142, 11181404893930872837, 3991260254355359695, 9396572444676943517, 17014475636467042721, 7000393941432237072, 8150349275162771166, 4631170617920477010, 6635544524720191779, 9908920515828101594, 5300702252992372600, 7510566684982239474, 108286438156484504, 4824190781658509967, 12581692589316752185, 11159838221811848616, 14968542183549253374, 17084948808360591461, 8191412738586448292, 15677020614935285837, 5215581678572586933, 353723820169197428, 16978751111369553172, 12772558029276683127, 12483628181661652345, 10439703577672350134, 9784945668944849304, 18318385882830590471, 10688587052076496763, 8699671510172701755, 13565813105517860139, 16641955038793794044, 1571349497717409374, 10044316396998302601, 12550672299534617062, 11227013398790037661, 13301296643867969379, 10812643949960334215, 5799004776816415978, 986124572499604435, 3026735939923394639, 18035239152455536425, 2821484567968768351, 6772748663092767963, 3349352749986649667, 15771700017042457091, 2812228100793983087, 8966593753220735997, 2813400646060206620, 9851206416208153804, 1746798591540633790, 15069296932125882874, 16531718734480334277, 16910413985181271676, 2793840408495526000, 448987935536301546, 14569625030330502514, 6065214866412927214, 17232757532354239812, 13829286547109138523, 2921754733414082261, 13303248667654369031, 3891969494180421122, 18167594588298270036, 13498114336686627178, 5851530730899716960, 4946353268947078458, 2144332232832247414, 9916272042008669847, 12426238636657392056, 4522343502857098731, 5264233711902098449, 3954779775408830813, 10152975213010389931, 15213008065604787974, 11906788830806904419, 13727551850222869623, 5581774594200415894, 3138893663025062097, 14227501657171208008, 2659407144214370141, 2470566155700025775, 5963582299596013003, 13476546953720331658, 5938042981535304450, 11568592500582515672, 17163862660310846968, 12049485632173014393, 30540173088117290, 17274458890463538297, 12797745934375629964, 5221784094376183558, 12887507818248264743, 3073813380843058717, 1938915953226043327, 6215200949568404039, 17293727619435885814, 17350499520763989487, 12296292807324796485, 9330319810635756213, 9867294643968220409, 12999888684556283098, 15586741203686585657, 3585691735603878541, 111047201349693111, 3532536732335552811, 9506597734466317004, 11078033442850698018, 10310334087676638489, 17519738454843726681, 1504580147682249334, 5740967789031283951, 16239711638006293914, 7081767932694792480, 2507705597412670155, 6743492328845447866, 13311574418396928678, 17077677532004370398, 535518464752018831, 73839616593119839, 10885240189395538812, 880676260073339171, 14555785395122230436, 990634367782179525, 3690893067528551893, 18134732819841678250, 152075761421318941, 643324364968596914, 2707944766236889072, 2446246525023988921, 8941720554917641159, 13298063652766245912, 15693609475952662965, 16218869215244787608, 4935920149548733196, 12147665972107143149, 16986769241359478623, 15970562718750671008, 11637849485926271203, 814178805403427365, 9973952093046043725, 13501264880263037297, 10349630860648909346, 7464255681522686521, 12871076891447140204, 7394689874210043674, 16300276938237421544, 14728438677586311805, 3359535383018364674, 4127781846509358372, 5741600339581174212, 13244497569979557385, 3782350829137505339, 5625990115735138668, 14895478463059224740, 13994624425384882290, 8186538127184846054, 2675760749528318059, 11677806371436173648, 257446551006261452, 7961448079232066398, 10306944304325243729, 5528847959046042995, 8040444385105100306, 7525704557088309836, 17549739621208763668, 13680452064407681517, 7178228674544011471, 5619710811438216228, 3607399530780455118, 5538141615865239620, 18226947480498324562, 14230448756606521728, 17876036637709099183, 5688793892421081608, 933530647226902936, 15258158162113456871, 5297315348809380891, 10586605564572500962, 3503963101907878240, 14289878178522832568, 17165985800898060484, 12853979216315383732, 7404472913193394806, 13913202037589418363, 11634222484170875844, 3026266052863507538, 13399280110778987507, 17627931264441141608, 6071499774479067879, 15110650858167631937, 11382084799343456884, 9504750370497627769, 13033616890871910192, 17729168561253698166, 466743073658850858, 17764316323418014434, 4998604969161617284, 13549279412875167315, 9296269997641019870, 9166595675043755174, 10529988328854732328, 7144041704891627420, 16361003346086079235, 9943807039687895557, 7046383518941749496, 12722671227372792947, 1779562253292504764, 12537820465345260220, 2614462454272293083, 14193120596701917762, 10780905727513177031, 1374415829793928097, 6748734894530971729, 15928220926843157001, 5535675968257661756, 1525840979353320984, 18122227845708966132, 7230720160297300530, 6852396017866833011, 6266552900448780761, 8828036573065632414, 668473016918889641, 8276491790393950978, 7279053552529835886, 9804715513235295735, 16434777317288501672, 5678310437624346546, 12396952033434667150, 2768090263379613177, 7572255419503115756, 10194149750863488419, 547740606870280321, 1868734200889842633, 12291540836011261895, 4086473465988937851, 2246345386624277202, 8725515398399179464, 12296543879285572534, 13915669807663935494, 17799835982674024419, 16234795638068414452, 5041839365397131364, 3116481237710138732, 7007209678955587212, 15484085310618002551, 12384347212382933526, 10731365408680754607, 7979224485340689000, 11682000340934638914, 7715146871166213069, 18004937464958667759, 8767958691288745734, 4384543045398316360, 3485127456363678341, 7128262331077171193, 13284990951702615619, 1452484727870755752, 17111341335049135767, 476002247405406477, 7146493491496444929, 13990600380366933983, 10496666477640843438, 6465434602120964021, 1103336350096377287, 8596287640450410898, 16738742077912987000, 5486092722515814573, 9391966854232607555, 2924901822237211905, 5111802913982387368, 15205738951038958336, 4696051498319690013, 14568233460671228033, 15625721869732171151, 17104653160814902481, 1221691498953690384, 2602902073875174288, 12802595970918777252, 11308198298413908437, 12431376153828579139, 3896128004167757830, 1759145605331852061, 3364680692104667476, 6392746910923337863, 14634448362305139043, 1059936506490182404, 18384038961084523528, 15307337632849520847, 5057750764679452628, 3105851082659899174, 4308041544222906525, 15191230344446017934, 18373321560647226542, 2919731949711530505, 10727119707982269723, 6190766667049366265, 4000897272982517177, 16089676642731055439, 14119628184550513593, 2006134976415861124, 3698544745472959784, 14481017188550498866, 14155887862378761376, 5842886212661624997, 16238887906885634399, 7835107379437844190, 4240679714676942653, 9864798697895861741, 2654889426506129056, 2443750612854924475, 3050756945961331983, 7730619795125910161, 915197777412081303, 4993690451949388914, 17632803739051902073, 5230703765105447969, 10177762924482276703, 18425135642721773802, 7047081536552732930, 5347536594056270854, 2633293018784451184, 7466111061656128094, 6420112623715945624, 5823698284278701868, 17953979574630844601, 3021282477843919237, 15119256823961490651, 15965505077327397485, 9877099833369183988, 18144349252100197236, 13157507941120467158, 13464212874985038180, 9504795610281513916, 1703591669233958042, 15650479956261780549, 5217281837497790894, 2078962277648208560, 7678727969347867092, 12682511819801310331, 7956802483950223219, 6875858131074550350, 16436613901290988133, 3794223136758377105, 14658822450166390225, 13017728987867106711, 7155247879359864457, 7965517847318671916, 522339382271833929, 17465238844685474394, 1818095920916760722, 12863182984416729310, 15409235235254242938, 37651504890804797, 12090214519410624135, 9935022871661094477, 13620229379418906699, 6249121756195807709, 791826603140909652, 3771084435754642155, 6319295620210998713, 1210757004298517716, 5517177838368090815, 15883102636645032206, 1012083124214994601, 9499143535129292111, 10067482779956600392, 15334057071623629003, 17298012274184577575, 5893650809269089241, 11626975905507353664, 1466731847162385960, 12417063392373210363, 10865945396821522088, 13198490943208480126, 13483622688756049446, 1066515323059661003, 15013161421243860218, 1771721670141859352, 855202711094875600, 6982928918038238124, 17068464697542898752, 787760719502861608, 246796619611468344, 215178779923359289, 4745058650198919472, 11056535399601364354, 8570138833315993558, 2043113223559066060, 13925275147217350542, 4749445102592224230, 8046472464363712176, 8807717763949288182, 12370494318644096180, 12670824172342933514, 15474395937397955519, 6444038014380761529, 17984464511410020727, 7063661334184573121, 8384633981109339188, 1393964766359295732, 5592842941053003601, 17430502775035661619, 4093755182167319381, 15608931425653503688, 17881325231794873601, 7390221156748691812, 2934084929295527733, 4518943364478494442, 15444554029548285996, 1106395487294911879, 2327338137505958123, 2377315771703720407, 15797000292931323115, 16113097742465596201, 7934236897987641139, 7116627593084442219, 7110521353828111764, 5968499948739939245, 18062722304252905252, 4704635294771488780, 8620494853070890873, 17386359699766399821, 9455163570109053432, 802647262668548585, 8981375779157233557, 1180623229659042175, 11621638083573431795, 6206508153262567322, 425948179895758977, 17034149675322907190, 15469737557795513008, 8762441777319685671, 1474432004999733987, 12493767938524031150, 1616342227776059029, 9474016112144497150, 13451807583447437677, 17510689659266049272, 11335563229002520488, 13793961974769287831, 16340429251575608769, 13292831858541393641, 2246818338971190262, 9878804687053045429, 12174826839542241856, 11118437124370748137, 12662817975396705529, 4145154758820420093, 17506617245101781983, 18138019040323987912, 8037383931308538554, 13130844879143696846, 11507881769800396112, 12313177391611223505, 4133773647679987553, 15563992181215663625, 8179779096123962923, 1216215279641195710, 8006702878066821179, 3334877862737012203, 3681401992292006334, 10549528370291796939, 2455409770316887322, 18371511937477382343, 15671614306759003925, 5214943663849407047, 18019664708706320088, 13627796185555316860, 11381831881829304807, 10313921141263578021, 6340963035203353121, 16989136496655750259, 8303662035865456265, 14841434918510827739, 13510657559389555107, 4747690424585188835, 3264163299674819924, 15096799417767492567, 17282031138576733123, 14719148755565244732, 13238320462169256357, 6747272587453298508, 13407725450570859624, 8203939948942345615, 786981056301196136, 14820419160799021571, 11448664349898477068, 7042304000127893534, 14895196209378473293, 13556163463336956506, 8622797343804615812, 14962622149215497881, 12231195146261802261, 4037799004974128959, 10895854889815810142, 5862802978616392012, 16844593706102362476, 12049789751324972243, 16893233259205437203, 13078288919529193926, 13946925587670565896, 1696596771385869382, 14070087665755371969, 3504929149575661201, 650588081987055591, 1849929156722191555, 10169160434034851215, 12447143612128801280, 6971967466031659071, 12810267986621425573, 11503214623483139309, 13110106711526222489, 18415764155594451641, 16856391804960268797, 6432728590161040269, 458784258357986814, 3224916599861516196, 4933037293710291204, 5638412326890009907, 9772005446547314323, 8200609863563573442, 10153178348513441694, 12134352733435333826, 3857162135298749717, 16227936124983595744, 14513727546361656534, 8583116838139674427, 17743031726736986394, 14110212125866090996, 8119106921974863718, 6225571996480263370, 2609337420315491288, 10516746392251636366, 15751915882435849159, 12483067544808116829, 1485652270032314803, 18311102530070418113, 8719450882587331208, 5553122267530249160, 2145920356165283996, 376978604376728991, 5672211522473036947, 5809254138632877473, 15153594272521870586, 1391673376708207090, 11423004622685819622, 18258959003506130710, 13613945546585665525, 4164749841720685135, 16571156176323775872, 11514039312048340292, 16155396173582622202, 17463725357964465212, 9184887395633443106, 13020029065881558512, 4942506926631582664, 16381045959201045589, 2106362836831948837, 12261161563699997010, 3947431246524753362, 17733471504322404071, 12286793252521616564, 6426220193144082621, 6947292739247733270, 11641057623708737282, 1322566685850015235, 15427224547857483209, 10016146846058307328, 3792978918426301133, 13304198151150388704, 10871657560529690675, 7179906814714163649, 7374362796928293622, 2220654016555180380, 11389139868700680742, 7807019663885318404, 9484925769603602711, 11931166942211373205, 12987559998400499815, 2993067006370734831, 15016376717666102550, 17724776981081606278, 15024614106401594703, 12336690208537854392, 5778612453669957143, 2914324590910553322, 1277143230814707196, 2411642454892953157, 17281298722756218929, 16260366008209366749, 5565586386404272938, 4435223658689854575, 9529550531014416, 3351867128828304393, 4560011016724032524, 9043424316421809350, 15837033487214224743, 11244859892602225290, 6834184957643434845, 9817412346858656960, 13676148928799976439, 8927334960637906275, 7518996774367520636, 5390270987862064933, 11888476837807808325, 13038912368901074882, 1929750137522667001, 10493945861592226388, 1205816297639347798, 16656017435467115354, 11862277687543658465, 16162338227952735598, 1846247801505420043, 11081597879978960856, 11029588866050905290, 16331000228856041725, 6933067536224583387, 14460933722873690843, 13362400988688028331, 4849640302737666445, 634757368798041041, 668693994058214887, 13702501766399245617, 4926369712576722934, 6378768149720874710, 6263888538011175835, 11106611436976763157, 3279430840294884881, 3809900877678530864, 11180590846261231348, 3561936376824286124, 5320983168820213119, 17583037133221783618, 1740588168669989923, 883855664743217711, 13527896816865391372, 17665956710316912297, 12228013318526264324, 14133831831179373911, 2743541888235700854, 978178954210294260, 8864340359148715893, 14019636027423379701, 2478210586996267925, 13522083140148984575, 16800404428561425370, 12131307908060979527, 4053103291376911672, 711384950201301929, 15241925078196143736, 13615239229147362421, 18423149255950976551, 6736017045802041716, 15664777527200425750, 12726921588094239882, 13852811095163412373, 5402201901281053490, 17929368853880302775, 1043323482801391585, 2499131487827857634, 17283221477703939976, 10871484974950159601, 2873394744290477627, 16674121765230014396, 14686151691619646864, 10923716745368347429, 13535885537432572323, 9886781372817521461, 1908144129995508302, 8614283914638637190, 9877729515991275153, 7229536295127001600, 7593406000449141890, 2330387904526182713, 14554050992341215823, 17084528578795238428, 7467265620977732102, 10371131499453119314, 6489294400536453489, 8003181381972406766, 8991233424749683730, 13222810618849642581, 5138341903426323813, 4621812142883961480, 17220249279314560954, 18370376338489383808, 2121454475874851695, 7292384979495486428, 12451859669059432139, 17005116503985692572, 15923887364736082190, 9741040868077231452, 9287307062186394601, 5276119823106920204, 4332299501988583036, 59429114366007149, 16055723554462734342, 15383076468565012810, 4336335395667289482, 10147983307882841907, 16304864533239932099, 16502972388644867399, 10048792028018429564, 15830567447633935220, 12909672717119212257, 13836473249028475447, 10273644770906048389, 13788356665950330782, 1707937150769909860, 4493067460049015536, 12693543858340204651, 4884772311435918990, 553385166831159301, 5274955907770780927, 2411800679320271599, 14178853531475327882, 8613133194082393096, 18220883512350630771, 18378054362351620143, 8127790493380643851, 7823830353485168333, 14586153800473533889, 6822514383395850618, 2589830795463718924, 8279858441672078294, 17396935117984044209, 17345788727688123714, 18351439089509717106, 14538543373326411710, 10396908224065911949, 13338978934446505793, 18313701688577710077, 16293563596460502099, 5730554990853211898, 7344386183726263182, 5184494300197764987, 17385718390641642556, 15700751405525322963, 5242201705194534975, 14831963366354935921, 15440693243366151289, 12068397107522921875, 12379624965637155049, 7651137481027798367, 10519679814338694702, 13733165732395488595, 13516802141996347129, 17506600274430688719, 3977477974911304010, 17877588986976054126, 15198589821998017010, 6077336913323725455, 5888658105251434685, 5958596416011299696, 2265856881346294191, 6465474878629275174, 12960151298655211819, 14876269269667052818, 16949705866062378238, 1460194160657425487, 14905284933093808706, 320370970420919442, 2858279891147207173, 16744820089976252400, 11038610998540477411, 12880439103074226901, 468981031211522553, 7508448318407368493, 8699031766472587398, 6347767978817287861, 17930797297509649848, 9844232056995521492, 10563017446095284703, 14177667692198975142, 16022970984583323636, 11729917614716953215, 5470991142379430611, 16519181592859327617, 16218214856346114420, 18186543820910153675, 3636166537466120786, 15361868400737807631, 58232580730402134, 4421434451592010614, 17771650290281880613, 16725846289913759833, 6523114594721655826, 13281393051091272965, 16482766403877211829, 1120665891566488363, 9423655761882537812, 4337313589373653909, 5619532470612393939, 3145715311210082224, 309557327092666823, 691075480884455205, 13170281640773069653, 4723554535449281167, 1867239505027672548, 1966431821400460860, 5177035529985006486, 13295648982205641188, 3817457344931950490, 2747064579001556418, 17104865812966545020, 7533200625109842590, 387134316653880241, 6695213147717592539, 3480369320010043121, 8634306672090942752, 10876805862404750662, 8676104055203724461, 11203164490585546350, 1434200188233611420, 2785883103715267889, 6268988508718431362, 1064864703151248481, 14583487175209956210, 17729173451243854288, 5638564896294884528, 6743768267045183973, 2710040265691230729, 15184406458994826425, 13142446436271228553, 12307500358371189897, 18045877569178129751, 11688277226610063498, 1395376112399516882, 4454781974294348951, 6398527639583479461, 12700137666635334939, 1313564223084004481, 8610599465532839289, 4080635225085571400, 16420676167679215208, 2513207328953160534, 10668954077397322782, 4305500819258312889, 13305015432166052623, 614088297254355642, 4071991968555173348, 2424395969401947628, 5381967489801823734, 13487375359018757578, 7838485949831319679, 18261302325099872988, 13281138566888854873, 1626217206074679834, 9386517865001236267, 6394473794258772168, 1201319982566981136, 11686378161425758880, 15853921274264793290, 10501105997420093691, 5319645284327825889, 9765963311056990259, 17077237164338316373, 5436751834627583088, 9040607447642471003, 15653939325437140812, 17660435209356079888, 4457604051578661526, 15885560556170182150, 1253251786546623035, 14873695397158863333, 5475831779502532820, 1739158307586912378, 7583695389236158180, 6192072175290089941, 4548649192267893250, 13649910683736986507, 1161819030542120347, 4420774647848510287, 17077149490728643378, 1657996450079810595, 9319425350407785256, 4504012284927128498, 7582713871139686563, 12084023229443220890, 12164387696540997240, 7104554354286539588, 7207756866534235178, 390030225406167015, 3044361583650602672, 12149268747999208591, 12403060843805545823, 9076338743083943637, 13370910250573748381, 12723144068139098703, 12383397832265476334, 3763610445407784540, 537511732463380955, 9133848270180885437, 7320300043438524570, 17884842967962779547, 2769066184110596305, 9016076870552304313, 16184696582130341704, 11615845055468105752, 1117304977957955843, 3693196379049358550, 14044062327095135822, 15795337425181710374, 10462348800142411127, 9996758688467879440, 17421964866607841564, 3175335366202798914, 17449138142485208572, 9805829195827408715, 10468542820318207455, 16177197826794610802, 6181362590501631518, 2124068883298087208, 247367958403628271, 2372366957433359846, 1695132931060001133, 6164391294309833361, 64663675256179300, 11557588651043857059, 14587134744505040865, 9114710405134229156, 3510606399464550426, 1743434973047649583, 13366042950828121008, 1509124301373416132, 16764474142924931816, 7110340253305365916, 16147986363433013053, 4906616039461634982, 17722338746846189937, 7031554771986944232, 11375877284248183451, 4001259763077681142, 3728383667644750458, 16069914496245153304, 9341845011074192066, 7629257426543503158, 11291059329299977140, 726211393725385413, 1980253097495525816, 11064505416132925136, 7925519815715815327, 13863781109281331936, 5389442125722254058, 17138511222519768234, 5804924297336654018, 6348919933707702880, 8164519969547439976, 5241570656254779757, 6638454643300708218, 14104198925773079339, 868055213396551514, 16808838493536747687, 15739397852572719983, 12763965506592626933, 6481852598507148753, 16887649107647827020, 8909752446027296716, 9664272216574653900, 7029326684912627559, 4410637660270574429, 18171744024888831544, 15589209566844927401, 8572838356098210445, 1002894101529664561, 12448972282950506812, 12109591013980103320, 14753471218059627686, 4611455272318570281, 2222782975178834005, 5005342132682509292, 11657849844203324022, 12050666096059869804, 4659492679271987741, 14931245896443346747, 2139983811541781725, 16084326278814208310, 8789983356354886921, 6666290577816260839, 17778958944836481462, 5002924097135734193, 6639214290496917576, 555202190923605886, 1906584755795216755, 9283828365983077290, 4635216157403995891, 11478860109902514888, 6819845410379307110, 4903762642991040707, 10399594149641024654, 16091159693062065407, 17640149989785297150, 10019776964298776287, 13152955796527646838, 9023339539227756670, 17467726694216589144, 7479030676030757371, 3131106677233082700, 1526295300257181071, 18247240124634767683, 12993466218079650323, 12770945267118729042, 4324960674102949940, 4458028041066435410, 11125067996360148925, 6246177566999997987, 12265378476572004320, 18120427643132058360, 3295141820497992342, 18202623225686951473, 6249772977581501532, 13320873145304469837, 11791952748164924379, 10294102429543166000, 11469337705392103067, 711334877449512339, 14224951446850982692, 6996297868920347279, 4511503545127977307, 11428118344834629264, 18297179477826106040, 17646353842338150831, 13671110980064914264, 11851552485973603782, 1066732520686157810, 4264959023279443858, 12784690586746327673, 331700500761748402, 10634602570342502550, 12705759435340278246, 197559533053287738, 5790905675666544160, 14559323930359023019, 10168056191608291394, 8469865687764748976, 5807710907522869034, 6155991700771100165, 4813888405585473244, 7354992806522927697, 17144270287872715638, 11591562526757417686, 5729892916794623347, 2484312878306509716, 17051569757193435701, 4269678769245487813, 306644384864157586, 7968443033438304205, 2887633885939912221, 2748493552715807039, 1615335327048478088, 10006917269263164470, 1268928268884465335, 2024284360938964975, 10269257250047717731, 17572217995947717243, 899984848746623928, 13714824776884095214, 13982497664886023533, 2915279402212207490, 1427211981304978097, 5109119376509951772, 4782899418354964393, 8219440134860918793, 18073944328002211956, 11591057268516089089, 18281133770656996690, 15542053463085377943, 8306755400628159081, 12720964388751174925, 8315237200656295943, 15792283567846089634, 12259971141270073831, 1751772640819723419, 14361349416869685270, 13703661671230315684, 732308317562759883, 542088073203739381, 10182637241455920165, 2450123856702709326, 6585820828774621156, 9091773130662137397, 15903509652202794073, 2580247163893445885, 5445561102333903653, 14728770027890355194, 16053806323041146000, 7333012193888736046, 18129090936047093950, 9469627704339179549, 2514858183302989638, 13751604744034622139, 691011265923886767, 6722126760852552815, 2615396821608088909, 2402770843551098083, 15057441181434869747, 8267284207720283271, 14045078736841505930, 7023176877104670866, 2465478386294433911, 10931902401373117903, 2096584880933803006, 12434049572052797831, 4095103484823948194, 16900548245752732148, 10567780520197611476, 1588652019451817404, 7640026991163147257, 17018948230786291724, 4882085518985090204, 4732629495956171265, 5251362635290772306, 1162856488427388640, 10050314133279871352, 15979172975837662186, 10452708099005791218, 8164431510325330646, 15966596978004857041, 1768047579017921401, 17182877298710730793, 9232635109907326699, 3233836244248744028, 3742579069164385108, 13149581049169737533, 14306708069460415147, 14261961778628813934, 10761516721924690271, 18324268268253686319, 2701816801863213274, 12607677693654033429, 12497910122479699809, 8600979099960919197, 9887983342592952834, 585741923663487108, 8736554544652962175, 12496638444187586088, 6843918325624016192, 15390950310770663214, 16328857335961363784, 6497141978978653003, 9512813350685746938, 7381308653385117819, 6989449401305836430, 14117027662053934074, 17622545260249553820, 17691938506164480588, 2733037860583718306, 1768166115637405052, 16901475573141191754, 10447593195229927574, 6570249206928994706, 8383930355787788217, 3395181838551168764, 10743213969491008175, 8321207301725795382, 3811470836827875186, 1253693353280624114, 2267669678985667417, 8774537139024787382, 1941313376450516756, 11539214566830300998, 10173732441935399623, 15560794992773525533, 13831868012912319578, 1535267024957994897, 11354906930263963264, 6004337559798380427, 10416008011036712856, 5998325195889004736, 12049120205423599397, 11864336868929480796, 13867933383425955856, 18247665060104625905, 14290137640730504472, 296413631388457505, 15477932055973215581, 3219305508054546546, 13249156662241663181, 17748041842466462268, 16810207447839738565, 5233887209586580723, 8604749809320254505, 6346688219143701739, 15836474120869883497, 14402339910625700148, 4005479838887410638, 14341958600162769140, 6086506098398557049, 5183875457229035643, 5052329760288184636, 15672017676245854801, 6467939817719469463, 16419835770517321290, 15872993232864737319, 3801117759053043883, 17249592862637031158, 11506237310501662383, 946057480719444507, 7247933928220480121, 8836628154035093259, 7491323203406751196, 2055067657963297458, 16314696752463674690, 11753904836092730401, 8242617865337722940, 13103156419834699947, 1674595314038372899, 11546729184974721935, 17008340376328356977, 17019306230317931411, 331965197024552644, 18057296070972683538, 4401751254592429722, 11171342315201387111, 17674848504785510396, 3476546872703590279, 12590641241781275478, 5028351869821596009, 6736890726908322125, 10057143593243048001, 17989298325083994464, 12097938229471744170, 2694143631170362134, 15355527081523462234, 12257826206242171599, 16655492895464947739, 9365856149251993166, 13547900257399139314, 1627818568517554584, 10133304924492875149, 18074916321590806559, 3042159546484328950, 16864898996457431371, 10017074950495504491, 11635657652211224399, 8730172234639076345, 17949990698017225794, 13505243465904932922, 17012173736815684173, 11607434340252196249, 15351042857703640064, 15976552654179018599, 9059881157827397374, 5489495552742669102, 17474805334518846459, 9931111719569706470, 16687788330467547587, 13023920214754731024, 18377162237118002883, 1005609682301417341, 7802654138731775151, 13801687162897800057, 9477319527505843492, 1220847322375676065, 3544072477095293028, 5222690874449684718, 682645379058438222, 14431934482103782163, 14672201492986023261, 11244316269152966893, 10157295901888189805, 15953537037945376830, 11945945444907003832, 12730361236674352722, 17958650141410421012, 6162560113355379561, 17981594347195083829, 13015393920110391907, 1698663270779280202, 1974726965676640750, 7027988304859124181, 16534814642504300097, 17577748268099038287, 14873573909100745537, 2718247919794438252, 9767645849367821308, 4424671581975295981, 1594908807275063217, 14213430608695304644, 1539495542021484928, 7983929030851536201, 13787217531285446874, 14106895738477166399, 4702727572615649671, 7887778585587939328, 1830987756939994292, 14351814450897504803, 10605141271196984101, 10021693838372338202, 858494216928196352, 12704544021080890322, 3297972477241318260, 13644515069733001722, 15594022823426520712, 8742875502718056393, 10966036217936525052, 11550626313340401925, 4140886717484686575, 6572187662349356233, 5483362840358692700, 18242544725369541122, 6431286756407979372, 3035903235595609827, 5853217611737969253, 13644220257500304744, 10848624307514546444, 17250712209344446229, 893317990939302355, 13994565153977368729, 4483260791808769144, 13967481393480842186, 1226496844816404142, 7836446202870707208, 2589554945045136623, 1473239823031110948, 15502086729624411461, 7151015290753221343, 13904325826714152011, 7116295506272082710, 17325628574845106404, 5618443576510946670, 9926155212668147452, 3494955217698800870, 7735404764194703679, 6486041726831620030, 2921576690244010685, 7913446190610943743, 8069982549034129595, 13615160897497718442, 3206525310916223883, 10337161370019503678, 9418362316042839429, 1343449678358882486, 2485272006767584561, 3463133281486754438, 14762319158904676062, 11608703099935814517, 6040895804344857155, 1916100797052361631, 10836367455173159550, 8421069469273746808, 42758744991666431, 9980255051281087572, 15776338626023931626, 11674488032580756220, 7857825703702437799, 13087345831504893933, 13436891231109251849, 2277312332838299819, 1884729449070239871, 3388888339357489789, 11486925060155251805, 18199013885083131459, 11871716622616964499, 18413905714293555516, 11096368277816629190, 10487461828696364453, 14698582381427357827, 5966818095265464638, 16590080959627864680, 4665946687834090881, 18351541705759007326, 13516620690203788542, 4012239856889635890, 12529168935151928045, 10651740022343900846, 14798647082288231349, 16265301445664953609, 14725558145401739596, 4382649460436336904, 7773047458743487467, 11979125331882349714, 9000238148327613219, 18295290675788721875, 2914799643701042561, 1216075308319805711, 2416632093699289211, 16878877178334976624, 17386965148353835750, 11499932301030857125, 13714714323296213362, 12772072059696863529, 18279267952019317536, 4915355418689594342, 15565939457843054354, 10703825488641735673, 4485946847474345224, 6200445842656420295, 17739055698631942745, 6698159437409604579, 10306192568952172837, 2262187032854957120, 17085393967977758173, 9663392210762758876, 9180883428350697004, 1356299310683971895, 12119332688607271638, 2589348634573352497, 13217357434834148566, 8984549409768341639, 8053051170625489008, 2992761396737634547, 7389660559374485564, 5335747850892359506, 16099918398517293767, 9569320656094517230, 1401588637902105091, 12191649493498875622, 1268322210870561533, 17463304952723735167, 13893168950727729813, 11302851151488679912, 1572907331509703731, 7983905557511536547, 1443247665625874613, 17488980868184992673, 9589343083211045929, 8226463193531541548, 8317142415248683382, 10668689618531552443, 10925748625878201207, 2755689456654047283, 14814154528249494695, 360426969469058288, 13552224868036462873, 9152635562602226966, 1827448246054496370, 516268798028709288, 5164887411146695677, 5108531696699282353, 10163085058919700871, 5195709678361021690, 6927711623015799404, 10126226022374014767, 8362634427915575441, 16488667289280115309, 6298197803457595448, 10871823233649585612, 8089440322305859439, 16235273238777296227, 10557460853800241770, 7766320564989824109, 7852071482019744053, 8690572403558001062, 9941541025712297752, 15998254373070112010, 15081714657886839424, 15185033584926799929, 6268264385514519419, 15788611920315865027, 8161172680964199644, 15029778178674506536, 13938206641136902225, 17961678397477118975, 12626368307855840694, 17605426670316034685, 4079393182514997713, 12702669529883350280, 8792885437258065206, 4898770386310743994, 8183108892911708376, 9410755321843997365, 1428121854605213388, 10543202978546689375, 17297434777400707846, 16069287131716537913, 2127573267393321073, 6275485943101037846, 17693562170448017776, 2641176285234151264, 13727592881310575371, 9898531095295696331, 4527791778418376936, 13977477636481780556, 1335119049062954770, 14733815080412582939, 2792185556309817260, 1177775690814244206, 15184431170493354830, 15488298453275225512, 17951089858115154609, 3388497802780001089, 9454698276958531217, 2557451230621741573, 17093029488146499318, 13450942206973315555, 12147070395527835, 4726470054593536796, 12596554881342530968, 4660430264092530452, 686599603731750948, 4103973267144621277, 8392218014453523651, 9680634981575008947, 2383091101841159554, 689551045294137239, 12108831248236854284, 4755786229450275834, 17355725370483969119, 2449563179852044511, 8549699882415582647, 9969569853887854624, 2156443791404023935, 666020200687112927, 11345632395159494981, 9654186900483857594, 3754125146540439407, 4664262430114282546, 6438026076108589763, 15024182917100054826, 2959578856570772381, 9799617572819763390, 15226177450710180009, 11716015302806391886, 12568331176650972027, 17170130236480363247, 14602128289074376768, 12620803195024204728, 4279592762733123058, 2546168472614599040, 5367039617284753414, 2944161051537973279, 10452752616167548701, 12422456152463887602, 2377215183411524801, 15040474219925479810, 16550041584131598281, 18395524689854611039, 13360480998188672474, 11419198807921962789, 10335111336352245471, 11135075744240285661, 10688249198263722394, 15428273449001923267, 6900957395454868598, 2641719371700640225, 17821918784214268701, 5546115436914850632, 17575504853647190088, 1895383559608928876, 17451482626019754164, 827767814317232288, 7795988622693306556, 15913670401599393330, 4260501096442485671, 5500286428869433618, 3656967577741137659, 10876909627820165674, 12014475667506704453, 12644687203306840163, 15527533353811003868, 6782165186471928912, 12833844674143628685, 12287888738170986794, 6750633161695866785, 6502384995651976530, 5691627495978205678, 12282138833123754462, 951684251514906056, 2676827337473763149, 5651032487027370650, 10317884252370823764, 14180022930931217626, 18371166438102163717, 17949838183249854899, 18045212799073717666, 17865891574493228559, 10589748710520668930, 6108251715119331162, 1997744906266875067, 7722627043158497033, 6843914242192678624, 7089480134810514471, 7910655100432631670, 7356986596203549841, 1017302610519091310, 6135339454032388199, 4584853782183684914, 18145250460720150634, 13456681415955879104, 17959310712198629194, 8262370079635518591, 9129773941441313870, 13492638159724456425, 16712223353038417146, 18429755306802579506, 5004531147310074765, 10234353991821631974, 5844406031776740414, 10891116973398461367, 11234937854329256927, 8807491177843391259, 16169195622306930273, 685667514278736120, 15443691253132530766, 5148853626298138559, 14042321497049403088, 4575537677436329612, 9080158806615481977, 12344760731075881203, 16615807852476536800, 13076850880099004478, 6635208725942342282, 10988721896810464058, 7081800602755356036, 12198887776815344120, 5060069320503715993, 17889890666635871149, 3403246532832959625, 10279919248721834259, 946672354098566055, 15426852245120708179, 9218010203958060038, 14394878370635074331, 2034320435005053895, 18216177347609412418, 479416409275315350, 16566805486174263867, 13207625451141530337, 15182242405141216237, 13295508645753596575, 17467630368571635526, 1229183237675045188, 5797456475832344152, 11709109467479260788, 7660135615077800856, 1333273646913149485, 11727288283866874886, 15815969532567585784, 15869757936255176724, 12370598362160235167, 14258783772170797521, 17917941786619918024, 16726605088253440824, 14813410438710887063, 50038849583098496, 17740645152281120155, 5309439396710080285, 3610986888154294470, 13338414464724903172, 12543037668143456237, 18364920562577944123, 14929054351197662597, 6789627103011330358, 4258098936481392294, 18161589582043031948, 9938007296833840995, 10080003489028335523, 11163404721965160503, 8561848816443387177, 4408220715833913781, 14590367358965455760, 10438642851610329493, 9276391605648693565, 17538235423081182124, 677895694694285966, 3747388757489477642, 5016980456267171322, 12593231220724356494, 1453382565549732227, 14486778507544392309, 13005636717826905832, 7734063902739306578, 12294529312969714466, 17864380130764224982, 3824062162912226448, 15045628103798816311, 17997632444227085407, 7287934410895597570, 16856720652090360735, 12254213686554664876, 9001356487241376278, 5687227347843954389, 2032485274623659150, 2380223130904738730, 13173436303450476006, 6696431373479280964, 9220284150057321065, 4025804818801098669, 5800084260213432321, 14025999890678919831, 10245696946707126693, 17648876148364679235, 1611415031483345712, 12966576446262869655, 147785670415286737, 9116192315476937298, 17338351935897431736, 9265863717624874614, 4235011690366298002, 463373234157965326, 14141619466658627731, 246532360524953765, 13606022891448264382, 10178139364174851885, 2494560827576649714, 15984825820325558192, 2144655353025684706, 14215513064738032459, 9762590622238425005, 3330122025064378209, 15018349400806757472, 11521616236145417844, 17604907448224384006, 5329681146136677644, 9043949155386668189, 7091376406886828660, 17199401079985710720, 14586782375608012851, 16952934176672022001, 15446929413389095640, 9407353556937371905, 2342657837633359776, 15307615161338488132, 8868186885670877974, 6170194821563734064, 12471282804749921526, 17655276352015409298, 13142605243800327213, 7313683268395293173, 9053955665803502525, 8254298709040851972, 1392252389689462878, 2047311284981390295, 5370730727424045368, 1003579048248220272, 13623050024541824562, 2747869603491587322, 18011995124616088090, 12489879745711260410, 5716263864607163560, 16493129586312826761, 4252860335617561536, 13534378467988441394, 11641986757695145565, 7764596020985369741, 15527473536748620700, 11065830314361559754, 3383722340332864679, 650077073233988148, 8542034465356044586, 15930442680489272465, 2672993857465915002, 6074860910883570648, 17225929086546788498, 7944492553855124647, 6981081770961263762, 15314780993506676828, 14428863566721175483, 13619375644602366102, 7197152481918005013, 17679875741231746998, 298283916735204473, 15669083776507206817, 8387259617627304831, 12246039993039527160, 9134365349018270683, 6396470644083685896, 4151613355909304150, 4650271524050972739, 4010285478839376965, 8980904275601015648, 12914926074912656585, 1420918868209717362, 5793362247641412564, 9432237333808527185, 3608072678916598220, 1508876331560526220, 15486092742499189208, 12468755918640089260, 12487415071967422089, 14975564713496643639, 717766782015419948, 4583011795677391833, 10431434081342684717, 18029062858736553760, 3551855154784497868, 4526239048891581831, 4729648150089414468, 15181665415415784231, 5138160418781584082, 3210943746159263229, 13875588919377441555, 7636147787150944567, 9735153169744120003, 7305448201529921527, 537487794215265611, 5100275075877624391, 16825130346999769619, 12149893255312799615, 4369968394379189971, 341441244658381973, 17746623334144800723, 4828926439203311160, 13603182757410567154, 2258457473598484044, 6352248869084350746, 6577304939567299631, 10435461896848223157, 18096985801785355758, 7537055197691054100, 8160940963020890456, 8435945022001866973, 15979457103453824205, 1957679621424407064, 9898206090357423391, 7817909936371509840, 15374813993316015934, 6355307985498980347, 12010588404057067424, 14123879852935100031, 9539167801680744322, 16560643173108608893, 8066719645353494954, 4787914433366516790, 5850355167699461761, 10006197759326785084, 7221221895720610267, 17344463526023172265, 3433134768528219218, 16265872547547573454, 12191343693464144610, 950845942272347997, 12313934626496120402, 7229818459140965650, 15614134223481457326, 10135456210398935451, 1090950758040588071, 8398476328725605015, 1355715495963912428, 6209376685976295259, 9005656041398321671, 15711691060211237759, 10277523831267480163, 11727876656662293206, 8831726166908190426, 11753502413658091110, 4847097836558222325, 15188918346803566330, 164642710349652400, 3874955979128701671, 3707475388488560944, 118680436172075180, 7470475059247484621, 3061899480186353128, 15105738822866170631, 4046374500253195601, 10730158779855605159, 10327922912359031388, 3666932828820205380, 18441140066247343935, 12466963136852511347, 1915861432256793979, 9665076161272512931, 4493168219425349192, 16027633592936849830, 10780076764340573842, 4901746694797429872, 10217087161152212157, 1434598235505982653, 14550581226985699668, 2909012021870260820, 2221506302851566864, 13447840706384344678, 10248839259740437433, 17148581724332029152, 10680087368083151445, 15330100753786539014, 6013383871585679385, 17804337498670019839, 9981371635421549402, 9533383178727980755, 6040305839260194285, 11083436435213010826, 10506549280675880980, 13365451453979725478, 14918618948396614143, 11909181115630743637, 2396227035301473824, 1816854220174599080, 11217296410329195900, 14660609603695548267, 6379797494015156334, 11928359345306576400, 754903689907011506, 2126809552235524519, 1897824169321318449, 4555354446738162080, 12705285348910480062, 11012890672300310420, 15057491630550073824, 8180696341523981966, 16843862420462057274, 13646428529391265551, 6049347760995938113, 4404151806756096491, 11541667245907179008, 9212878996484513769, 8481200654014318835, 584556822495344359, 2537575096305976911, 17707346432087076478, 15455807035829085598, 12775927255815911352, 16448248038909958718, 94831719398223066, 18311020152278458654, 8920015673225800959, 11659763938924054460, 16932805802351878200, 7365528043625539981, 9390008014084423569, 9974482441079471271, 6035819913252177259, 11510958473146499088, 4870159695137832294, 6439409922899588111, 7122868728045601213, 485458708547870160, 8099181092193537055, 7782471347343769188, 11002149757998176658, 9851550671388336221, 1849343516837040542, 15913275140760853917, 17453111596066830490, 17872400777819557230, 13178231050590716912, 8853687323839933453, 11396093957564100717, 5964438257532151962, 2299747606127114042, 10692649258171410241, 8850207100951095431, 12718888898304797427, 2582561174483856810, 12881679014607433351, 5401259815482563621, 16636234862554946288, 2675281638042591442, 3327968313756418042, 1097821402063109479, 7256603776215037436, 16159780022292663956, 17964893318700077025, 10962902536107975247, 7320550439447854389, 14334780521409633054, 4699452739827576826, 9093268785303487009, 6344405044849339468, 11848292709291959714, 14760683788704509466, 4225108478874620861, 2901943652303490660, 6818132424834122414, 16174008530442037804, 6271947949436459450, 3570604482108849930, 12890452366190704954, 8515100912972766831, 2328912653110868223, 2551276586468841097, 1777511200124317812, 13775576098140883402, 3898067160703376056, 6351161380350484527, 16859278051445776112, 14690763963896054237, 9567946959436887085, 15838477932738238738, 9730676848478313229, 8066271786694050339, 4122621761286909553, 15283986993063032338, 3752996388177035008, 15404074806158244183, 4664569365239309400, 17671699018667543313, 6690783097548235595, 6466585595067583758, 14022028503333983234, 7939754610094515610, 8163183386194559637, 10476051353580213825, 4511583491988680073, 9188502261872559113, 7408378497508188518, 1649670196419579816, 1053916178593140007, 7911309861374389712, 15032485360640049189, 9124570128447866504, 14046893636531415981, 250111365613429267, 1643606250555524120, 4155955491523436557, 10870726304981416869, 14944082243353063876, 16421238461518880167, 15924408471434652318, 10731945555425051586, 14495249000183794562, 8846884895280158170, 5565891773087990332, 1837792939541241349, 6112699197700624176, 7562264824078865510, 16849021028091575913, 17246255673370327668, 17580006033844531064, 1351562679496436002, 16771152552690652203, 5274051012054233957, 7648406455783604255, 1246471362969897938, 16120472728146043782, 16166681434816599117, 2623886897349824851, 4023278728763402245, 7283187577873923080, 5084224325637364730, 1476723572967543249, 479713893390980167, 1896209313557836901, 254984415576149738, 8415027322583137901, 14041872703600168181, 11935559776977783011, 13364349759217490994, 15780035685521226192, 8676579092208619555, 16064345951756800054, 5638114870421263136, 6270982746853694228, 13130830212820724188, 10518270735201681053, 11245308360082873244, 3151879320488972838, 8402166224245273877, 5495337374477483425, 18356012286937648925, 2129448815318200193, 7817762379822334015, 1308094065360667428, 9452125716061917909, 16830335368607333043, 7115352597517763002, 12961077632058697621, 6264739998394856219, 10711361719217759622, 2805729415502011801, 16310918919711006710, 14984568792320800815, 5033473820547421598, 12187842566826705754, 4078001430260229995, 4636228512388579231, 11348937457465299114, 5847070676214632205, 8079399555440215553, 6457432316721536567, 4951083125808061965, 6293687095689620804, 11406482222093560959, 12658825924452667114, 10143584571617814544, 10022366761772053513, 355937325950036313, 9105402276098628794, 14972622607769590007, 4815136695954494351, 9515549740001371280, 4507108044850455980, 10153991335189677806, 10475976860885183218, 18392897880757235177, 7749647359532990440, 10232160559790081825, 1832228719152017993, 10890777646249905570, 13622006085705339951, 3231946825126030723, 15685731590656020016, 6084715112214186784, 1215214721646491153, 4231466600123546797, 8168820323486969127, 11634735777117238886, 15448533925907917735, 15937944514800610778, 4056349991916377957, 5094616519526616735, 5413794077342350279, 17973381638741991988, 4337914915291663099, 13739150828488185155, 12791593666472076388, 6307708804293666112, 18045762826377694670, 8496356868191969871, 5807060217263995474, 128039966698714827, 6431461066104336028, 18004817073090175031, 1800020996723291496, 11580212732146715316, 13816860669240708872, 3861721497954223568, 5744224278046122943, 3839434585307875902, 773812752136737676, 0, ], false, ); // - size == 0 in limbs_extended_gcd_cofactor test( &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[ u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], &[u64::MAX, u64::MAX], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], true, ); } #[cfg(feature = "32_bit_limbs")] { // - scratch > scratch_2 first time test( &[ 3897754892, 1591443736, 3731539623, 2201049795, 667019954, 338792079, 2659170876, 3110296069, 2376679457, 2383464170, 1556639511, 3319121799, 3166670999, 2106071868, 4114757632, 350183771, 1813104833, ], &[3508657757, 3011352011], &[13], &[1373166577, 18362570, 0], true, ); // - n >= GCDEXT_DC_THRESHOLD first time // - scratch > scratch_2 second time // - scratch <= scratch_2 third time // - n >= GCDEXT_DC_THRESHOLD second time // - nn != 0 first time // - nn != 0 second time // - a_high == 0 && b_high == 0 in hgcd_mul_matrix_vector // - limbs_cmp_same_length(..) != Equal && (us0[0] != 0 || us_len != 1) // - lehmer_us_len != 0 // - ss_len != 0 && ss_sign in limbs_extended_gcd_cofactor // - size != 0 in limbs_extended_gcd_cofactor // - lehmer_us_len == 0 || lehmer_us_sign // - lehmer_vs_len != 0 // - us1_len <= us_len test( &[ 3762839616, 2967303351, 4062879665, 4165640742, 2234446345, 1620638488, 448679871, 1137926410, 875978589, 2449429151, 119500812, 1645681298, 2261230243, 4012109892, 1880039262, 3823761915, 3823287146, 3298525947, 182661440, 1727722474, 3533552734, 701287629, 2616764708, 3283986955, 1488777769, 2704219188, 3077818025, 1332124621, 1289136174, 2954906289, 1428812861, 2396554867, 1921203057, 2784693210, 2216238152, 3284610812, 95149300, 461371838, 3227938939, 2641070942, 2375717459, 3203938917, 1868106937, 4078179036, 2189762153, 2180822395, 3379470590, 4012169608, 3070486814, 325836440, 2847713220, 3933125061, 1877517798, 2859136122, 2708155707, 123325553, 749102782, 3101320654, 1289955955, 2400149618, 3506792555, 4078214206, 3239665558, 566182347, 3617280016, 2149509005, 13381270, 260919523, 3902125900, 1378889636, 3568804679, 2795835774, 2820285329, 2553570971, 2887752390, 106251296, 2204563920, 2108659045, 772859668, 2676569826, 3062588931, 2781116609, 1249633190, 1317945945, 3848689824, 2255648615, 858513646, 3636484450, 1846465706, 348176034, 2538183889, 4094178045, 3345266791, 725000962, 2785581015, 484198471, 2576668150, 1563131970, 2080449279, 1403091456, 4217712236, 2849047009, 2457566162, 2112594498, 282536535, 3675707661, 919672617, 1763625368, 3483048959, 3627418205, 3149707026, 1247936956, 899012765, 2975733799, 4075719513, 3712606177, 1596851592, 1200276105, 3678643745, 1657748004, 268026781, 216321281, 3542039833, 1034844323, 2165371654, 415846125, 672088830, 1109960702, 590813340, 2856536701, 1324154592, 2925233312, 4128642860, 4224883829, 2946877752, 2516423945, 1920408555, 948662453, 1802422733, 1550713261, 3765914851, 2391591503, 809461282, 1682796307, 430607881, 2259629147, 4205981011, 803329433, 2922597120, 3867519412, 1845488268, 56866391, 1749624959, 3789345017, 852019444, 746073761, 2217066953, 3322916922, 492290040, 3860587330, 3045516348, 2402113307, 1072947248, 3287650314, 3729416957, 3288560211, 2648923449, 2947384134, 978738351, 4206727716, 3799518272, 2523890380, 4240712847, 139648756, 1849818862, 129885306, 1596458797, 592938917, 1695490670, 1049264694, 854799233, 95358756, 230932304, 286523788, 489674484, 2194824544, 2837471612, 1167420495, 561170122, 2323842053, 2693817101, 1977318979, 1803712373, 100240938, 2823914585, 3305999827, 1991119105, 3731378313, 2741941084, 3182956207, 3805467102, 3567148328, 644528644, 4117795281, 1862948151, 3039205689, 3735294192, 3944679490, 2996177165, 3819378812, 1839330932, 3652801991, 3989628037, 1372430413, 1067509161, 3729244886, 3069275542, 329434844, 724055239, 4072117251, 1739491639, 1820536186, 891863943, 3188986409, 3282105241, 1443494725, 3191928513, 3180924502, 2670529247, 1020294985, 4255388313, 436387871, 984529800, 2639531245, 2836663830, 238179551, 3280695056, 394858620, 2853787135, 520661464, 828033417, 1206402039, 2388038671, 3167724755, 992289854, 155743860, 3841622716, 3264917318, 2656941314, 2977148407, 1411905882, 1607242955, 1033507899, 414422850, 2740309834, 3620002421, 279386928, 3369823140, 1133353466, 2401145759, 300829644, 652434123, 4062297302, 2765186813, 3352720931, 1965242866, 3048509317, 1047329756, 3283783583, 1102536736, 2867627346, 713434240, 1900974984, 1889658765, 424376438, 4066161359, 3595866981, 349425704, 1339975348, 3489209212, 4108023084, 1021821676, 3854012048, 2379788417, 4223914814, 1019701671, 3032063795, 2915803116, 815008284, 639272216, 2031646920, 2274852463, 3347440003, 4015644452, 3528407171, 309435395, 2115945360, 660896703, 2842673452, 4278731819, 3716277170, 283430113, 2843703539, 1035009984, 3920409252, 2783446318, 1126636158, 3067742837, 1191242603, 2171152922, 744214603, 1361159732, 2246988530, 4093546546, 1599908321, 922131016, 2517982795, 2540991722, 1318294259, 2620311038, 4294566241, 123572629, 4103296441, 3132380177, 1621894546, 3452280633, 3910486070, 4275454874, 97296377, 716413318, 3491146417, 2929708827, 1527112018, 781388525, 3651012169, 282448756, 3283582572, 1898078758, 1788942303, 1995178922, 3441777049, 173604069, 1724943732, 860875392, 80717574, 2954413462, 2552039446, 2631438427, 1693507278, 3353262523, ], &[ 1693377439, 2515180469, 2439214130, 4133741269, 2582353740, 242054029, 4277621427, 2504984707, 77434695, 2984274878, 1564979151, 3285070373, 2252781630, 3364774938, 3002449910, 1680353696, 1217306725, 1396375684, 2599013453, 3102429128, 4278239524, 3169571622, 1167640580, 2453974881, 2335368085, 1242479084, 2857593953, 3802180829, 3567800871, 3865342345, 3119715092, 379851163, 1397558188, 770778293, 3785859192, 3662070793, 1657684760, 2766622517, 22322818, 2648843872, 885524552, 1667222975, 3327780957, 3899267759, 2700168414, 1035990630, 2964803242, 3658514285, 1521662985, 3875666074, 384714566, 4023835084, 1712455255, 1633372627, 4105720974, 1214600656, 2697565604, 3991985789, 275972215, 2558541893, 549181418, 662068140, 503219765, 447509030, 2261465632, 3114832534, 3921496979, 853023187, 4224408890, 2979976205, 207077487, 1101645904, 929902458, 2590079399, 3323735589, 3164178351, 92191438, 2164068486, 673800185, 653476923, 1564764455, 907896117, 3177543114, 4277815432, 850719138, 3515239072, 3716534814, 4190421623, 312943968, 3826875600, 1990994491, 3709985301, 4221256674, 3556567657, 2610085896, 3745970187, 1435011594, 3892109511, 1715581482, 2105913079, 2419019493, 3909752637, 3371571260, 3345828095, 1028723886, 1191606681, 2887118757, 265947242, 2226697675, 1949040274, 976693848, 2720509879, 1605048137, 2459501086, 1131995726, 2371676741, 3850355205, 3213110584, 1364148839, 4044081326, 1524307989, 2520341453, 3184534510, 534185823, 3259475834, 2531104741, 3170241627, 2809437947, 1223276703, 2218190753, 2148040222, 2903447873, 1896662098, 88908799, 2496611452, 1038079086, 1541073446, 208649800, 1109996254, 1685147065, 4127948847, 2874587139, 2210510801, 1989034966, 3468467699, 3226999107, 2921297089, 3500577322, 1932873731, 1789716188, 4112814531, 165371344, 2432727073, 842353729, 840790720, 1477582335, 1801483328, 1805128359, 3698633967, 3501617244, 855186793, 1230557311, 3486176081, 2409494601, 436296379, 2343301859, 255459172, 3499418449, 555156558, 2170432178, 596711781, 3036850923, 88664421, 1942739632, 3123209816, 2220529354, 3706515643, 1804005296, 728289710, 4075256444, 4215063814, 1180523869, 3481812761, 2904673863, 1722094894, 3238283099, 3983051053, 1438237631, 1121945410, 4229945817, 1270004103, 1119108133, 1935109657, 267055487, 956248707, 3855027428, 2226764505, 984782979, 689899815, 2020393263, 4007327071, 3186231458, 2451483690, 2664159307, 2624554845, 3315837097, 2441190188, 3506544698, 3929763769, 2030117497, 3138752244, 1711107972, 2582482362, 10064793, 872799969, 3783903762, 386063328, 1205008174, 537775062, 2669375356, 3419058256, 1171712416, 1774647095, 1497660848, 3169310977, 295784793, 2216281857, 2466578023, 1813328265, 290536445, 1099646980, 4138641573, 775042501, 77053349, 15639833, 3034370119, 1634213368, 2884099476, 2274185957, 1226572167, 1740332810, 3674005254, 3631482994, 1156096480, 3606707530, 426829415, 1232519516, 25270879, 3086722770, 3941364397, 3405781167, 2415115506, 1517840345, 1606833111, 2565163912, 3988365259, 330707489, 1617180807, 814469081, 2263039715, 1556805104, 3942915981, 458673662, 3877105328, 2446254642, 1556590500, 826262573, 3724262368, 2213879994, 1450645885, 1056572628, 4000758956, 4160404794, 1891118025, 1715959086, 1211501563, 577988969, 2129952979, 3907919003, 4051278550, 3461444806, 131544635, 2593930090, 431700375, 350623646, 398604570, 1171577992, 3886290689, 3850610723, 1591600825, 2928989840, 401164946, 4144495423, 452010787, 3246123860, 1872084940, 3263472759, 1050558595, 2095418475, 3402226626, 3757833605, 1461484814, 11285668, 2262295928, 1891730627, 2181259816, 162673695, 3362648426, 1167165856, 722354045, 1845723331, 2064834481, 3971671786, 1714853922, 3199429669, 358016658, 208221582, 1670486500, 735570681, 940123172, 4101442559, 3587213701, 3552665637, 1900305803, 1548158612, 488426234, 3800857128, 2406068943, 3444303271, 3252716429, 405136720, 4011758616, 3969423411, 71862739, 3329146881, 1260239194, 395385046, 296902642, 3948201723, 3835744605, 1695111845, 175164568, 2187945981, 3522227152, ], &[1], &[ 1393609056, 1668089679, 388101919, 3438788800, 4194117699, 2189254312, 1598588274, 3879253996, 2127868385, 3471466265, 2337251129, 1921288799, 392679821, 1665416984, 1079669059, 1573900002, 1964806532, 2102176554, 4095311226, 3507401786, 2214644498, 883768833, 1519501665, 1304100050, 2966925652, 4224555623, 1799109462, 376762510, 1168427484, 4016439230, 3733525310, 163928847, 3454421957, 1013235746, 4152862368, 1291761337, 1519763430, 27576847, 1580902245, 3591746340, 1007577498, 1184863609, 275405856, 905021963, 3725730585, 3138204434, 3050531811, 3753821538, 4123611368, 2554499493, 644559702, 169964742, 2719569988, 590330270, 74782727, 1034630774, 409876667, 886756373, 3403621554, 3637008468, 864505940, 877730074, 38002984, 2390955925, 3098237160, 291842393, 3391582458, 2018940044, 4060204863, 4153199304, 3763045923, 1440843292, 1571876254, 2366883331, 689380750, 634873145, 2318283923, 3208426517, 3271060718, 1280295173, 2544392122, 1301307279, 1657074264, 1342838957, 3049729249, 1004945554, 2253574816, 1525961110, 2510687431, 514819540, 957979057, 313615390, 1607095417, 4061382021, 3941379563, 1101265462, 1313622484, 1837703852, 2673117468, 1437174024, 1499621627, 529083376, 1940278425, 776798184, 1123682684, 2122099660, 3074020283, 2094844126, 3428277975, 3294333385, 48114786, 2689586655, 3538009580, 1745291826, 489247647, 3322213232, 959686083, 2666000275, 3771267440, 3495977761, 2431492604, 916073707, 436504411, 200716576, 72474591, 2937145867, 1583010373, 4186277170, 2537013278, 2698078347, 393025935, 4150124187, 224908520, 3447498563, 197596967, 3560825651, 3097801455, 2945720980, 659464691, 2979792921, 1348822961, 2747044617, 3337218782, 3229027566, 908197840, 3134460360, 2841826299, 2481153225, 1047716291, 90931696, 1679067328, 2568036144, 2915134830, 489068184, 2772007434, 787204345, 1359526321, 1108174931, 4117450905, 820904957, 3350408170, 1771963799, 866682718, 2435333265, 876077850, 1033960917, 1645617627, 1650743672, 3940682757, 1770347533, 517189836, 920250625, 4008776544, 3119334766, 2164852932, 1430249573, 4056499214, 2473908787, 3470156455, 3546319710, 3909127421, 1660272144, 1089002319, 3675125278, 797600811, 2022127439, 2739608587, 3439244966, 3463881000, 1836767606, 2859304929, 520573508, 3233204064, 471627213, 4182072094, 1251347368, 3602733112, 1033377063, 2460642996, 1016213436, 3231592120, 3226200884, 106079916, 3696456858, 3128931316, 3521087294, 3349410512, 1082958228, 75668315, 3464591731, 2952627950, 1017048554, 1574302947, 1109268720, 3264722269, 3617623906, 47366057, 233054575, 2477361108, 919474704, 3831927354, 3420634778, 3395208828, 851029512, 2323975556, 372064504, 3471244010, 2788291215, 3166971224, 1960533331, 2407342180, 1129220597, 347329439, 1871810614, 340007359, 2759144798, 2286800096, 107458106, 3630233388, 1826813106, 2927588246, 1982203941, 825172593, 708608518, 3042987277, 1724767260, 2508613865, 799077018, 220909067, 3894286154, 3926799271, 2358623483, 3925218124, 2860669724, 1158499946, 3220435185, 3371813630, 3307737058, 2629255355, 359567492, 2904443397, 2635944803, 2112449220, 2211181964, 556540968, 2909852447, 1037277002, 4076912375, 2101537861, 3686624842, 2828607232, 3377387494, 2210360409, 2411894734, 2466571187, 2138028095, 1440618752, 3569307243, 912762213, 699744466, 3771103410, 2890482012, 2912012447, 2658641861, 652064016, 3099409172, 998011974, 1523595687, 3333564359, 983370044, 3841364864, 3424833451, 3066298350, 4126305990, 1400044010, 1205863433, 793974470, 362425761, 2387396037, 2977549597, 2075854219, 3124515174, 3471006981, 69707483, 872083528, 4040308644, 1523307219, 1074317105, 3664463569, 994741592, 4252689215, 505599222, 4060502974, 3061003002, 1418799529, 1680036101, 2316739007, 2468222441, 1045693481, 1473917157, 4182272343, 3855611698, 3668311253, 3286026043, 323272750, 7410276, 1984804150, 1801786556, 264019842, 2066806575, 2925947809, 3721069056, 3755918310, 1429760301, 1134071192, 3565767674, 2487124209, 1642250487, 1038092541, 3790194524, 519027477, 2656188663, 805313971, 1581787635, 0, ], true, ); // - scratch > scratch_2 third time // - ss_len == 0 || !ss_sign in limbs_extended_gcd_cofactor test( &[ 74310550, 3684857215, 4195563540, 1932463403, 2701977359, 4052089791, 2826747541, 1491226437, 2117772829, 2404853855, 1681591153, 501486090, 4035630834, 2942773950, 3965991474, 4174952080, 1311942174, 967870714, 2272005008, 1224704677, 1184062144, 3981077533, 1360003749, 290818846, 1347799497, 2235021764, 3820496078, 2088443415, 1249972471, 3795966103, 2489816539, 1081993569, 706286461, 2866235029, 106879314, 2375809606, 3142865583, 1013483211, 3505736665, 1018680206, 2204848950, 681988775, 2095459452, 2399591422, 2677947559, 3678360365, 1094565217, 2173800169, 3656600695, 4086541844, 894958491, 4122901419, 3753678287, 2178442254, 902457379, 984358218, 2914419433, 1531443436, 4148703424, 203601029, 2344242033, 404262744, 1130385058, 107099317, 2972886656, 2996679753, 4235390624, 3809459200, 4131414295, 4051400485, 1414437089, 3243092392, 2881511575, 776072878, 2435162818, 3450788997, 1630916173, 691381501, 3962265403, 3276437521, 253507689, 599902663, 1579004169, 4202480377, 2042450196, 558721125, 2146913618, 3503780971, 372811960, 2210806951, 1767967910, 1804820784, 1701734377, 4259228040, 868893527, 2102141044, 642487995, 2139687168, 3217271118, 3807418215, 3261976935, 929051287, 3943894160, 255758822, 3861729768, 1584488251, 840003021, 3035292132, 100163217, 1544310956, 1321895757, 3730997455, 3431322122, 3712192042, 2587337131, 250371835, 4292213317, 133986444, 2467011381, 3222257561, 358247829, 1077622444, 4034574796, 753244486, 1417883886, 4173847504, 2395611782, 3784624740, 1170553448, 96736306, 324810407, 163356845, 2781370737, 2626965592, 1711364942, 3620321815, 1037634179, 2159676882, 3030237577, 4003655416, 1317909197, 3872252045, 801107604, 2605152822, 1726177269, 2639322764, 634608690, 202505283, 4287528588, 3529992483, 323119212, 392355407, 2810111885, 1518012210, 1687498186, 2200403413, 3552634997, 925734954, 380011454, 2038632642, 723250497, 2183915576, 2375404879, 3597027590, 1465229539, 1441179962, 1101992056, 465581252, 521753873, 3402618493, 3660408267, 2191505084, 3025386009, 1110551535, 3696253833, 2934449447, 270918983, 3088802491, 3122991822, 1438682320, 1440620889, 2730839421, 4143462998, 137656753, 565499602, 2535950098, 556793223, 321223212, 1525925221, 4171365642, 3904725909, 3644902683, 2051318676, 387867671, 1770768052, 510814112, 723471713, 873977447, 257236365, 615515201, 2578395673, 2753664576, 905559712, 2500927371, 1296710732, 3886865363, 3005960899, 3684007331, 4143041158, 2366878938, 1714542138, 3410115077, 2879409644, 3328247532, 817839754, 855825811, 1894716618, 3629567121, 1206627978, 2852031409, 230625254, 3368218591, 4042809617, 1915413257, 3555530943, 1475738483, 695002857, 1926295572, 1226821611, 3004377400, 2555002778, 3651774914, 3437714157, 28014986, 2973285277, 3673083025, 3242773182, 1517435827, 1421912587, 1177464830, 2455554109, 2595190727, 3155583291, 3310352929, 369038486, 178372520, 1649325320, 2422315435, 3258510890, 3575437924, 294226406, 1387707173, 1920980667, 890867321, 1972378523, 1227213297, 2361130999, 4167202579, 2163533171, 2383008798, 3494162449, 3385820353, 2710406521, 2985041632, 2694848326, 4068305667, 2942916526, 2476626358, 1660135201, 727042092, 268512304, 2048192807, 1207211865, 3670015910, 77783405, 2681566726, 2681823572, 2094390259, 1567797140, 3746350911, 2837598968, 2442753220, 3374824876, 2463794949, 4026074137, ], &[ 3601838339, 3389527135, 3199255267, 167429870, 4120438511, 3791081297, 1051610496, 2831925658, 3138327153, 1738612299, 142767461, 451766065, 1523426819, 1808217463, 1662507181, 433628334, 612971737, 3384254423, 1524658464, 154523660, 833536371, 737557796, 371547944, 1654120803, 835831538, 1784970368, 1788323399, 545602792, 1786466785, 974820691, 2239220379, 1494785387, 3801297697, 75457861, 781481706, 3502813399, 3172635468, 531427646, 3409899873, 3441423830, 2093952094, 205557919, 3981485225, 1751839582, 1974962270, 3891786411, 2096714479, 1971711392, 3256278198, 1035760556, 1066075733, 653493168, 3136688239, 3402779557, 3205564309, 1206349448, 3160959668, 530694406, 2004091029, 2446160779, 2011849976, 902714644, 3007498124, 505798654, 600285365, 2281470223, 780710454, 1905845719, 4092492421, 3973361188, 676446183, 4170170431, 542862256, 2648449136, 1107762383, 4168697101, 2423190399, 634645690, 2427748780, 1100910614, 2480475038, 800791297, 3718104965, 3114992885, 751937105, 2852127039, 3366541691, 1221876612, 633153490, 3280813177, 538197296, 3704159053, 214017394, 4173347526, 2996370431, 3354186763, 964498456, 2614298215, 1295317447, 428880416, 4032691632, 340223270, 1769526294, 3905215417, 31921576, 1536219531, 1566836356, 3150642622, 595168147, 1299756321, 2674132095, 2971109047, 459958242, 2946581288, 1727142010, 703973706, 763870983, 984639964, 2631113497, 501205034, 2799535391, 2400194671, 3292745359, 2786435398, 1521799401, 1082838265, 1561857367, 3191086584, 3021982259, 2827962005, 4216748738, 257549630, 3114248619, 189933651, 965281549, 681160742, 3092658868, 3631419991, 350669652, 2258678213, 2802738039, 10053030, 2224029759, 2587869134, 2954399881, 3203751998, 2244828285, 3023569974, 4052208026, 107088743, 136096065, 1044340914, 3956070202, 3303754650, 3128172551, 837572504, 420546271, 1042960901, 2450628487, 1443820393, 2453824614, 3576780987, 3916987256, 3683003957, 3077152988, 2820843100, 994775381, 2721865418, 2135991139, 624991155, 1118457663, 3552077852, 4201035247, 75044940, 574256973, 3946688245, 69642536, 3075052287, 2136563917, 598694353, 488979649, 2287218854, 3275172664, 2890192435, 1267136240, 2792041779, 1815565573, 1634974334, 211096868, 297005246, 3504012622, 1072110147, 3212420667, 2158377307, 3718128929, 262446033, 1551719654, 2813501675, 106403179, 2870213468, 1483616723, 242287943, 2208733614, 3711810589, 1437091905, 1234730132, 3672062627, 3394277988, 3774429922, 1179097821, 2290210831, 3639274568, 3221308057, 842782026, 3031989022, 276644709, 1697723959, 3742435088, 2548019495, 2980018951, 2436631391, 1182761076, 3162919388, 340442296, 1214857666, 878131886, 110740326, 1307427842, 2331304285, 2202030177, 534226195, 2751735378, 4012895666, 318125704, 2993146500, 1669696977, 1779052631, 592764374, 140645184, 849345706, 3386384106, 1494695680, 525110148, 3360506653, 2674752886, 1931006280, 606982322, 1388477671, 636146571, 3683742943, 1118871516, 2900077755, 2912836028, 3336213952, 3744044153, 302021444, 3994958705, 3934494823, 3784076284, 1481317384, 1994455765, 3359047713, 4189189868, 2775684855, 2268293895, 2244043733, ], &[3], &[ 3743605517, 4179569329, 2073207865, 2553816512, 4117833349, 2637359383, 3704896208, 378306359, 2705719088, 2880185160, 3444990912, 4060308087, 548140866, 2004200601, 3472416250, 1429192756, 3208447353, 4039217005, 4106085374, 4040549815, 1626542807, 2942613069, 3392841446, 4035125853, 947826882, 938796203, 1145736949, 2938715945, 840660849, 3710125848, 588663267, 2882936046, 2949062660, 235176621, 1851170909, 901829062, 3120584500, 555282352, 4259152968, 2423820899, 588264049, 1149200408, 271528610, 1833941193, 3174986896, 562267934, 2220670279, 3894873858, 1012195213, 306864348, 1680322240, 699702484, 300813063, 212871964, 1564539128, 1204678629, 1457509501, 124310398, 1638616079, 1544535804, 2077138368, 210219765, 2483616536, 4254280024, 2340265287, 1796976054, 2198447684, 2605412473, 3617375869, 3033256303, 2875673780, 2320809525, 3575396572, 805995054, 1564225156, 1626913897, 1292974128, 2135559780, 1878970422, 3894404000, 94713723, 2561470561, 1660648203, 979776327, 3949215531, 698838945, 1843823969, 2751208029, 610079597, 3754455960, 360823624, 2987158356, 2994782418, 566986116, 2404661005, 273867727, 869887518, 949533613, 3842355789, 3783404515, 1463818381, 4147016693, 289049355, 1672164913, 3106023939, 2315507851, 2857811126, 3550477869, 860460763, 620224458, 1835826089, 1268899797, 3439121015, 2482534704, 3284302513, 1761503569, 4000140663, 2162987234, 1096469906, 3044581491, 1667797669, 468730477, 2630281039, 3020160336, 3295784045, 633349537, 2531146461, 4245451986, 37001682, 4203279524, 1618196223, 2558909681, 1715347160, 68236321, 1201150886, 817854094, 1480912789, 1255626224, 3294629333, 3940789659, 3125357036, 1599656071, 134729316, 1674181206, 2494740541, 1739168882, 3321943862, 594912209, 118454926, 248900353, 4112996779, 2798650952, 2166813104, 398470519, 1737480311, 703830919, 3410153747, 1614114161, 1358720344, 439750188, 697686526, 2495881421, 3478343208, 443559010, 3876059116, 4263230127, 4247623333, 939127550, 3316698975, 572023281, 2575474657, 1901362389, 1903267166, 3889333747, 3237411152, 4226596762, 1120071913, 2482937441, 1544332266, 625134331, 1591508498, 3106874019, 2851071518, 104456679, 1915266024, 55682651, 2001837660, 702405811, 3100702526, 1645665128, 1345512696, 2022651937, 1007011973, 2944039647, 54653045, 2445423242, 1693931160, 1230191385, 812251921, 858953374, 115415998, 1008523979, 1198867456, 4233225816, 2796537162, 1195686984, 2199106552, 480720883, 3010965825, 2535760037, 2352986652, 254106110, 3749353513, 1592688563, 2353884844, 3906141933, 3067022490, 3216957447, 1241127308, 3210786485, 656356244, 461264467, 41838622, 2791209640, 3882461708, 1905589240, 699011852, 4067016151, 3607049493, 3240323965, 1546024465, 1681907639, 4281764142, 234683244, 4012306441, 859073253, 2109486501, 3896985008, 2402673571, 450935651, 2255996995, 1871535824, 107766737, 3036831750, 853695499, 2071762278, 2901839029, 1804820556, 2461865290, 367151607, 2508680843, 2311143384, 1697717932, 3809283596, 1545348801, 2354684536, 1789458423, 2261515026, 235458984, 3654263365, 3089351522, 3779807866, 843150936, 1354871808, 2127328047, 313337276, 0, ], true, ); // - lehmer_us_len != 0 && !lehmer_us_sign test( &[ 3714073558, 375193035, 1620772021, 2308204402, 626547013, 3688150199, 1448538382, 2668595114, 1009561668, 1343823926, 1509608795, 4028253859, 1815980651, 1785146987, 1342958609, 3553568195, 1725347486, 151259885, 2320707416, 2987769959, 3741775337, 818070422, 827367513, 753102779, 74383384, 1382795590, 1881554822, 227618421, 3934359081, 1962657040, 998065041, 338982340, 1281868418, 2999179107, 1652003177, 3123097903, 3257098, 1621937355, 812876371, 2397377805, 2170739943, 1419963806, 92617000, 3668729026, 2240231990, 3514746217, 3492237442, 2559241670, 1525109693, 3005514966, 3852872611, 531448444, 1669232883, 148128188, 1239481575, 889075183, 2769552448, 2509351360, 2158188017, 1208314937, 2800429516, 4172256108, 861328391, 3116173930, 4030544020, 2551025568, 4268865357, 1482211250, 657549589, 3306982572, 2933298890, 56098708, 1989729224, 1743604790, 110376592, 2139866017, 1072327219, 3469499313, 381416910, 1760787277, 1363950668, 334943331, 3654960685, 782150592, 3701034853, 1136642643, 3692640414, 1959495485, 812950011, 3249389091, 3259364568, 1685592552, 4256698651, 2036050133, 2433308803, 2325012565, 2650618050, 709154390, 2387307041, 118573438, 3470337072, 2607784310, 2364405729, 1417625047, 3236813797, 2729521018, 3639006705, 96799629, 4108743714, 4177055576, 1544958097, 3899425671, 469081179, 2539369616, 2986882604, 1335697326, 2186395654, 3911059390, 4189281233, 2426450063, 3956940807, 3883295955, 3550183055, 3853112591, 1929765171, 245863045, 1784682505, 4002404844, 2509707717, 4274582128, 967068840, 3767407516, 1130216371, 4245379947, 4024085884, 2184101616, 3749613502, 3516580777, 3578117768, 2353774157, 2642207837, 3725043408, 1828260039, 915702978, 2705406301, 3535196378, 2877116312, 3679028343, 2070581078, 3559165185, 773435559, 383510436, 3209711995, 4004820838, 1998784655, 2871662581, 2529625272, 622878861, 2863694253, 3914220048, 2679188786, 3050594298, 3045251700, 3512780649, 2906941324, 3942757081, 2907048772, 100041843, 4170806507, 3700825180, 2709242073, 2179276763, 597377847, 3463521373, 225180682, 1750686210, 1093215152, 3352780093, 1077233189, 3245228123, 2396717084, 3787246723, 892320530, 1029311734, 4280196574, 2345165313, 3450587453, 34019938, 1280657875, 3548776991, 221784082, 3463424486, 4129053861, 2357286454, 1994868751, 1353736236, 691568564, 4253680566, 4055927368, 1499648079, 1286708763, 1365610481, 2611290963, 83252581, 4163076670, 1565784615, 972801101, 3913786720, 2999013362, 3798728041, 1581006671, 404535456, 856581363, 1508425066, 553497914, 3090372112, 603773943, 3850767240, 1741397001, 4026283585, 2777649580, 3530633927, 267199452, 4120305103, 1366237421, 2861373191, 4008286372, 571708589, 4259212487, 4210946087, 976721978, 2468468308, 426418605, 3496624920, 225318850, 2194812088, 3227558244, 444008974, 2090459961, 2364873754, 632622517, 3955662100, 4155243543, 1610700691, 3338597107, 937549997, 3402931779, 3336911213, 2512983483, 1602321580, 385279681, 219089337, 1311034097, 238759500, 390515148, 4014040379, 3622671161, 560560741, 2174041032, 272454444, 4242752401, 2135675415, 4069493753, 2346744121, 2940951489, 3461267243, 1485096605, 279517788, 3812451507, 1527749536, 2519024910, 1054202103, 3151806385, 4045340674, 1756112458, 4218041601, 53056302, 1298620474, 541870411, 1907995687, 3015193382, 2289454404, 2422235646, 3379667784, 2654976724, 231577350, 1935104189, 604588941, 2815299657, 596740826, 2100583598, 1737397117, 2096370396, 3411467032, 2531389141, 80135848, 3230839253, 4011475632, 381422820, 792708197, 1426670359, 2119901750, 2324153190, 1682237962, 137137837, 1206643795, ], &[ 1878485618, 2582823939, 3526257766, 3491869588, 2508972765, 249421064, 1431449671, 3872030994, 3411988094, 2806831307, 3820262770, 53035764, 2850291145, 374665519, 2246783701, 1466683201, 271427494, 2157692599, 4021749208, 409438247, 3155661705, 843312510, 2889651408, 3649983796, 3032237477, 1696325992, 2559886399, 1256508327, 3109597138, 1906214881, 1709991816, 2562870361, 1860860055, 2418306985, 2322779826, 3265670082, 1213618630, 1154886991, 594074344, 3632593081, 163910128, 2797803240, 3572330107, 244626448, 902896355, 3699561111, 4254902447, 2484872968, 3981424715, 10061257, 3123081717, 180908376, 1859280280, 39983663, 1024528265, 1521567703, 2695062267, 149048575, 179176529, 144520692, 2604716899, 1174209826, 1031181796, 177237457, 2719241498, 179940181, 1906705445, 647593808, 1420363719, 3297208800, 3352463250, 788193177, 3800276204, 1542750256, 3053223337, 421095772, 1726003798, 1155660421, 523307670, 1998474431, 1979224306, 391343343, 4104067353, 386326853, 313019445, 2456282888, 641413741, 736340248, 3874706631, 2144435461, 3920080898, 2738344935, 1625068457, 1257024866, 999908850, 396413465, 302677517, 712478295, 4288330089, 800161765, 114814077, 2598054557, 4249317809, 3562854500, 484269782, 2535373010, 1557871774, 656903352, 2034241763, 777050079, 1802902792, 3756904133, 1141679055, 4129277659, 2972241705, 3435283434, 1415816578, 2554167499, 4240752855, 3423411208, 1505288832, 2753282826, 641148943, 1428513558, 3001607402, 1533357009, 1485563002, 2673090064, 3844139398, 2561836665, 2754722198, 970356743, 2201350930, 1066125294, 2733447686, 2885807404, 1881146091, 3757473749, 3701029696, 664108669, 1832641491, 4170070819, 2551964945, 3773757575, 661100690, 3207291047, 986146628, 3383827271, 2748125590, 3125972817, 202953436, 2278076196, 3110516930, 1168599337, 899932496, 2243910143, 2853281488, 3059106833, 2044583068, 4147861221, 980210874, 1469351302, 1095747203, 4153622485, 2513280487, 2134885617, 1218973898, 2842913398, 2337016140, 1594161385, 3481631667, 664510962, 1960349422, 2148836029, 1934322678, 2994217052, 2807256387, 586972467, 4178498347, 849308960, 2927784294, 951361420, 43586941, 3648229750, 3829346381, 2465163307, 2761354627, 290145462, 2055302756, 1957506334, 739571549, 1176710229, 586545560, 49762561, 879936127, 2492005742, 2451254722, 3053414952, 2429125990, 1577259591, 2688316136, 747050298, 1402431037, 1325712566, 1332667383, 2001670166, 2064093114, 1617959363, 1485971531, 2472812436, 433644713, 2191207097, 4235759995, 3894627335, 423077375, 3883830117, 1935314236, 399390428, 3709392940, 3059959818, 3661588523, 608272270, 2929333408, 1168195668, 1014359665, 1608963119, 1434740769, 2972657265, 140005123, 2823943018, 308312387, 1460444398, 840581898, 648060681, 594474654, 3815936159, 3321362565, 2723923184, 1387304627, 4087764401, 3188914647, 900026899, 3428649429, 443357120, ], &[2], &[ 3406323328, 1437213148, 3172074291, 3580970206, 509361480, 237281083, 795015447, 816594087, 2228031405, 2771964340, 4273929734, 3611483248, 33870382, 1800679979, 1174132590, 3808880801, 2623161229, 722129827, 3899957385, 254163815, 2027839137, 1054474142, 169607034, 3184835763, 3564636008, 3159869550, 3200899831, 241206548, 2386472242, 277074084, 1312960750, 3253603208, 3299988794, 2001720781, 1936109342, 4197993187, 2720279340, 3705901329, 370955006, 3234985000, 340427671, 3281730335, 745227198, 1609322938, 765008262, 574118537, 401712292, 3304798364, 2063272851, 1991525044, 2544645387, 4017998867, 3558728466, 508950878, 4246503638, 3527416569, 1898445853, 903897734, 3649484651, 2563954102, 1404672239, 2869315442, 3218531949, 3947288847, 3670363468, 3196146733, 2891736634, 1115855957, 2003404410, 3607223796, 333049480, 3450292464, 857797924, 3821154687, 73688414, 2940240320, 3004681958, 2711715733, 2933235760, 641242249, 1606904497, 1256934537, 1455408390, 2990631750, 2231685976, 1516663662, 4211813488, 775680722, 1686065755, 953397401, 2846902531, 1127878546, 2643735029, 38290869, 1615881341, 2413854321, 1315472301, 1616214705, 2917695496, 4148218743, 4258696849, 1728311609, 861478712, 1850401706, 3177380718, 1929863520, 1679722908, 1746431603, 625484937, 3441894984, 474753749, 2064025745, 3743725824, 3205246567, 554972664, 90620439, 603727869, 3355308857, 201216683, 3643436268, 3340080348, 3822084805, 433694918, 2730450197, 1291413960, 3928122518, 3536301210, 1142177298, 485662346, 382958943, 1922383639, 1224207852, 3978041786, 2536300002, 2882290104, 2550681515, 3125284589, 2706207244, 2123995239, 2756726197, 620302338, 643860526, 1519091714, 2811159746, 620831961, 747749790, 4234219486, 3839492109, 434640682, 3515645257, 377435626, 3002722589, 3449736432, 4247384093, 301245934, 3125659472, 1614908177, 2112184032, 650630492, 1745801604, 3916359745, 4232243904, 3434748876, 1773785657, 3076590870, 2808388038, 2662142992, 317806835, 2316000017, 2973502772, 3446099497, 921292530, 3679071298, 2418515437, 184601389, 2602694528, 1379032605, 629857518, 2498812614, 2883185264, 1561661304, 2328919226, 3205863336, 3082815661, 2741957664, 1771875666, 1720200563, 1495377715, 1857046184, 827146152, 1907180130, 3270990004, 695333232, 665408820, 1614127720, 1875284305, 1074756407, 1714481511, 3427196833, 2977599359, 531127355, 2445543921, 888001330, 2098527764, 3269327839, 2204466715, 1366782935, 1347889789, 479690362, 1872069165, 1666602647, 2771347873, 2625720435, 3337206684, 4261602004, 1908074343, 2391517538, 1479533928, 1069369919, 1736863859, 2247189883, 2754033409, 3222422367, 865055697, 1483030511, 1872918152, 2334541320, 2659208136, 1817963243, 938114447, 1091767874, 2063578826, 2306967373, 1014685314, 3767981460, 3394910046, 3762192898, 21709636, 2808026654, 323922863, 487838342, 4007808710, 2691217180, 32532376, 0, ], false, ); // - us1_len > us_len test( &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 33554431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2097151, 0, 0, 0, 0, 0, 4294966272, 2097151, 0, 0, 0, 0, 0, 0, 4294934528, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1048575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4290772992, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294963200, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, ], &[1], &[ 3912025888, 886896747, 3373539372, 1267971119, 2147779021, 3312219999, 2719874009, 3172532945, 2640908453, 2045545547, 3615956967, 4080410788, 3972086932, 3552447088, 3319021097, 3809844465, 1918653728, 747400109, 1879308392, 3962271345, 3614322235, 793758289, 2287865193, 3157669196, 1077683203, 1670927043, 2580216486, 3905212400, 2918489481, 93135036, 2143954792, 1799458293, 3683476316, 753701792, 1089322801, 1358135032, 999717196, 806389310, 1201158081, 1383118311, 753409317, 2686010612, 3636712738, 194326449, 3996942488, 2228506655, 1941500305, 143503947, 3241601529, 77371472, 3156241712, 2656403371, 1947068169, 144587741, 230138483, 1706046558, 200645164, 2214318189, 1024476384, 704795680, 48216132, 4092341579, 320876282, 994006676, 3187326006, 4232852015, 3916528332, 3569555832, 117636514, 3843928238, 1821537056, 3160390627, 170292086, 2631142219, 3914822703, 564666372, 4056933637, 853978997, 287616595, 2408719114, 3434192280, 2130741740, 3168128757, 680434144, 3404585176, 458928157, 367835397, 4110770980, 2695931191, 11343704, 698798114, 3625673959, 1043790052, 42058605, 66384410, 184835270, 2315385908, 1364230376, 892966470, 3357617286, 108301707, 2803459914, 2217958282, 1725796552, 4071520189, 3010175533, 3524994779, 1453496319, 2567457858, 3860171805, 655593324, 3899607441, 647072905, 3503789019, 283753888, 2432787665, 1918775105, 4034937401, 461045025, 1262551920, 137876938, 1626022576, 2125039095, 2951694631, 2525624750, 2605995038, 3556223501, 326613547, 2589685852, 3986176776, 2395752193, 2831210611, 506343935, 2171409011, 2461001173, 1996789217, 3980633713, 321717431, 965251765, 886772948, 64269788, 4115781956, 1635655185, 2849299284, 1390620294, 3395985232, 2482124294, 35597591, 3997281025, 1453879097, 2766291359, 1604081205, 3973715212, 775011402, 996856315, 3314398346, 3763730761, 2868042149, 2548185993, 3658638415, 3582069455, 2534916356, 2262189034, 2470576613, 741902204, 3798471577, 1042223894, 2744176327, 4102481616, 3815841673, 2528021725, 1956439567, 3626885367, 1826970821, 1833655643, 2182769461, 2901285886, 3148028130, 1549794171, 3867025612, 2540838114, 545015290, 3981077932, 2059392483, 3012154937, 1616718892, 2232172984, 4106220952, 3821667025, 3698143135, 616003913, 3801506973, 2784367244, 975154127, 4114993094, 3560006433, 2380530636, 2790971794, 2341455943, 1784545866, 3140308722, 1611418568, 292814187, 2704783587, 1092745053, 1821185432, 3755423279, 1274854684, 1338434098, 982681233, 2404821761, 776511636, 163394779, 81014300, 1775679315, 3796004898, 3396729377, 3095436406, 4090460397, 2133841999, 1036521501, 71056224, 3099728386, 3974229113, 1681723397, 2384237717, 2740596008, 2690063482, 3343120218, 1712550476, 1731513942, 892884876, 1858597869, 3964286687, 565337651, 252743644, 1829273449, 2466499588, 2561551294, 3302171118, 1018994570, 2589015429, 1224020052, 3359662565, 3099494184, 1311043757, 3341028275, 1082339712, 892972502, 1829253720, 1001497557, 117124196, 542653614, 2450347600, 276857137, 1161175520, 1063660386, 2307654631, 4237080774, 2251229868, 392169910, 1391102821, 3540553702, 109530896, 2, 0, ], false, ); // - nn == 0 first time // - n != 0 first time test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[1], &[ 96334512, 809184833, 609979439, 917841564, 1376291946, 1335372660, 2164003694, 2673108150, 3650205264, 3068908070, 2927066464, 2340580023, 529792913, 1825835699, 4031333697, 79641126, 1524940942, 2201130345, 216393180, 4071458329, 2334778398, 1463729248, 2688261544, 961061519, 734363607, 2195650904, 2552076064, 304989719, 458920782, 688145973, 667686842, 1082001847, 1336554075, 3037365544, 1410343154, 1271544010, 4011614679, 1337488001, 3278149327, 1487025366, 399705731, 2067502643, 1679754713, 3078833879, 151612438, 1393885150, 2434664396, 3337954982, 79498345, 3108679211, 3674525568, 793907199, 3009814506, 558417352, 3284867560, 1384771311, 175686933, 4116330913, 1883204498, 868169797, 3628031203, 3535175829, 2431624713, 543336157, 3786207655, 2343717122, 3270990563, 1420835158, 4174715792, 1691072618, 3024039265, 998065535, 2793871814, 1953366923, 3134561452, 3159790431, 4185140253, 181607511, 4190203131, 882632170, 656530666, 2670822774, 1000882492, 3808856169, 896665594, 824911035, 1132193821, 3890029849, 2872143627, 2480131083, 3557471007, 1229275468, 3208259312, 3837824516, 857041242, 3857046659, 2911246604, 736370418, 1052532875, 1000185943, 1218613152, 3313489721, 3740882987, 496443522, 767956888, 1519603218, 71709979, 2350234153, 2114565927, 2855426752, 3369805903, 1978241900, 1002352731, 3241499607, 3388983493, 1778735503, 614637734, 1604129656, 1918912258, 2576004269, 1928523329, 1455623302, 2515668857, 2673750085, 500092971, 2756790224, 3804228508, 1870441493, 248221761, 383978444, 2907285257, 2183338637, 3322600724, 1057282963, 3575197024, 1684902951, 3136604598, 2648660013, 3768233451, 3841975394, 889367751, 307318867, 802064828, 3106939777, 3435485782, 964261664, 2875295299, 3405318076, 3484358690, 250046485, 1378395112, 4049597902, 3082704394, 124110880, 2339472870, 3601126276, 1091669318, 3808784010, 528641481, 3935082160, 842451475, 3715785947, 3471813654, 1884116725, 4068471345, 2592167523, 153659433, 2548516062, 1553469888, 1717742891, 2629614480, 1437647649, 1702659038, 3889662993, 125023242, 689197556, 2024798951, 1541352197, 62055440, 1169736435, 1800563138, 545834659, 4051875653, 264320740, 4115024728, 2568709385, 1857892973, 3883390475, 3089542010, 4181719320, 3443567409, 76829716, 1274258031, 2924218592, 858871445, 3462290888, 718823824, 2998813167, 1944831496, 62511621, 2492082426, 3159883123, 770676098, 2178511368, 584868217, 3047765217, 2420400977, 2093046690, 132160370, 4204996012, 3431838340, 3076430134, 1941695237, 1544771005, 4238343308, 1721783704, 2185898506, 637129015, 3609592944, 429435722, 1731145444, 2506895560, 1499406583, 3119899396, 31255810, 3393524861, 1579941561, 385338049, 3236739332, 2439917756, 3671366256, 1210200488, 1046523345, 66080185, 2102498006, 1715919170, 3685698715, 3118331266, 772385502, 2119171654, 3008375500, 3240432901, 318564507, 1804796472, 214717861, 865572722, 3400931428, 749703291, 1559949698, 2163111553, 3844246078, 2937454428, 192669024, 1618369666, 1219958878, 1835683128, 2752583892, 2670745320, 33040092, 1051249003, 3005443233, 1842848845, 1559165633, 386192751, 1059585827, 3651671398, 3767700098, 159282253, 3049881884, 107358930, 432786361, 3847949362, 374851645, 2927458497, 1081555792, 1922123039, 1468727214, 0, ], false, ); // - nn == 0 second time // - n != 0 second time test( &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4261412864, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16777215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[1], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 536870912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1813905408, 2994399669, 1767025046, 1779086942, 2560788905, 2495652644, 1950438505, 3389856413, 1199187240, 718638698, 161601559, 2077442333, 4075407509, 3845277390, 14683020, 1999538680, 1419751200, 96817827, 3347799490, 3662737933, 3342437314, 3102257506, 339105132, 3272853101, 3730379334, 787705221, 3554111725, 2785203515, 1774419661, 1465128767, 2602265406, 1521228109, 2739053496, 1046627426, 3656923613, 765353033, 1104147101, 671302339, 3262461653, 4078630863, 1657670358, 2544039916, 2179179584, 497830601, 1482049256, 126030725, 742845439, 2175237293, 4033678621, 2228415677, 1670564945, 2759306986, 1023439704, 1488958197, 3429597203, 3123171067, 3318052400, 2984530569, 3715635421, 183121370, 1084349991, 1691629951, 1899065687, 3149068608, 826500663, 2281938276, 3041462185, 2178159831, 756736147, 1862529845, 2995511255, 967989798, 3903250574, 1193472430, 1277486602, 3518754695, 904406626, 314088647, 2374901767, 2196134749, 183213822, 926245790, 3702808932, 3957649599, 2848150668, 4213124583, 1670145672, 2807366853, 1385422640, 2991547553, 624165205, 3881438754, 2305933460, 3911438826, 927582491, 4032889069, 347916803, 2134561554, 3302645587, 1357660924, 2154811081, 1280187591, 2735553875, 373975768, 678841196, 853469015, 3278550564, 520475764, 3157311891, 3489429195, 1060397627, 3203177479, 2337930986, 58133713, 1525621667, 689658334, 816131014, 3860225340, 4013991369, 1328655415, 4175620430, 953950024, 4222675682, 1818741405, 1159575257, 1412128505, 3305654799, 3520417706, 1008173334, 3164638212, 862034677, 1310804450, 4180955140, 2973360708, 3424935052, 3917844393, 2359655519, 2586539049, 2904566386, 343412185, 765339035, 855298558, 2095812656, 1404030208, 1088714807, 2226459449, 469240772, 1549973701, 751095118, 434095298, 3043907071, 4193862455, 196583660, 2253182506, 1773878770, 1865148082, 3446101993, 1149907000, 2889378134, 1974364104, 1551603166, 2821220488, 3626740916, 3777658710, 746300305, 3535016512, 955214869, 280863174, 335526048, 1145561312, 430003002, 927068165, 1706340717, 4284648397, 3372557344, 3424201062, 740939606, 1563007928, 979547149, 3506089694, 3740685364, 2042197748, 2097283242, 199931170, 544120174, 3139948651, 3136397605, 479334915, 3367331783, 2456091806, 458065766, 4035284494, 713748985, 2151274283, 1168495352, 1499758476, 3008738604, 1823792739, 2502749346, 592079210, 4013832609, 2543711568, 3491177809, 4058973993, 2679304829, 817407178, 2488687339, 3039082602, 2949402470, 4023391299, 2054197820, 2261532032, 4109107205, 2058289294, 3334809850, 4141674277, 960086508, 2551762669, 3957189062, 1960976610, 459116317, 4282783819, 110240464, 1979653617, 2054424813, 3849007869, 811381958, 3202923933, 180903478, 436575542, 1558945067, 573205897, 3911059745, 2987264945, 412640580, 2125178023, 1306319004, 1139223170, 2987568401, 2139924318, 3170068581, 548871255, 1042520000, 892658617, 3449354772, 1669391581, 3971788655, 3934256792, 2934498383, 803442713, 0, ], false, ); // - limbs_cmp_same_length(..) == Equal // - c != Less test( &[ 1582207393, 3257769320, 312002593, 3788671422, 2562360222, 2018485950, 1642000633, 3752939185, 762402457, 2742058693, 4078581054, 758428677, 982403960, 3766131700, 1255139079, 3108603950, 126568705, 2528314074, 2415295075, 21918673, 3116053283, 4135693331, 194784423, 1808182332, 402979294, 596411796, 931794242, 195206232, 1868897994, 918784542, 1261363777, 1006480341, 1062659638, 1058805882, 3206714055, 2895853157, 3416291273, 514638714, 2849366146, 3426402264, 1666868481, 1897213704, 3045828738, 1446169376, 1041377319, 4238908508, 3638156887, 883962932, 816559901, 2638036722, 2363061328, 3964491706, 72585974, 925161746, 1218735144, 4004333943, 2080361157, 1967088019, 2626134784, 1335072842, 838772777, 3390829698, 415396526, 3678882944, 63941908, 2600794954, 1817578917, 3433169905, 1940244273, 1945108649, 4224113008, 3718898573, 818893106, 1481689799, 3896622334, 2229854427, 308038381, 3666467894, 1888945489, 2732049108, 3922935639, 1169676153, 4024049892, 4187442278, 70141574, 945492349, 2888651303, 2991638890, 3912330221, 2097621812, 2083222651, 1545563177, 3543864532, 1628613583, 88188644, 1615033727, 2745317568, 2729755781, 2565654320, 223793519, 1473930704, 1340424864, 2241709609, 1183201612, 3538474481, 4132703163, 1383006083, 3710294684, 1649559007, 1138758070, 497232832, 385488871, 2030896967, 2012159214, 2690074301, 1177105881, 276967925, 2552357416, 1497159533, 1249045564, 2558564347, 3731938099, 3299279784, 2013438962, 2176217881, 1044900010, 3368297890, 1359676847, 2543368247, 311995556, 2992582099, 1265877360, 3340992352, 2640095305, 1496247286, 3736589714, 2190815591, 1130837558, 1293450511, 2472175246, 2117374312, 155971543, 2522195432, 2309601428, 4120082948, 227295766, 3923631693, 617757311, 415744536, 1570375946, 949708862, 1885319289, 1417726186, 526651128, 4220673038, 2768125994, 872982153, 335787553, 3117513091, 2641049716, 269634766, 870696055, 3692553352, 3202663357, 979816689, 1199675084, 721523678, 1405171049, 2436925869, 901381817, 3604940484, 1712751101, 1793704398, 1145600581, 3353832520, 2969573925, 1532429694, 3128602535, 3075652125, 3969048034, 3626545438, 1523568077, 704701136, 2085974891, 2009191184, 3585301931, 1887341277, 1421410368, 3087960281, 1112574025, 2166745609, 177664096, 3179243282, 1920685246, 3406716775, 1983173180, 3101662354, 764088114, 3426634938, 3196605606, 2737417379, 1278512447, 1293248712, 1865368759, 327254618, 1774912263, 2669405639, 208073317, 685646662, 2122803096, 3747942556, 3275924256, 1123816196, 2550246338, 650674914, 3952581813, 589693641, 1650990718, 572049977, 2097148216, 1404038978, 2620523718, 742609424, 954335977, 2825152969, 3540511318, 710103906, 2787842272, 2704858874, 1527789354, 812157329, 2665361451, 1206140479, 3171524710, 3000676456, 3254291138, 150412446, 3929427198, 203714225, 941149876, 849467518, 2614757179, 265139398, 4054468456, 224160914, 779119629, 2564623259, 2376221955, 2179586090, 1198887503, 681, ], &[ 435825370, 4098074553, 3454392562, 2463980626, 2066205125, 4034750267, 1235550246, 3612964936, 2824559949, 1670195687, 438223870, 344385955, 444736095, 3199444570, 158172638, 886704977, 2044060213, 3288661494, 4001830393, 454465757, 3064791897, 2782564601, 3955023420, 346666935, 4203002761, 275338593, 522709058, 1284976224, 2948751667, 3367485833, 1233249232, 249971808, 3540695933, 213088602, 2833797476, 1742024205, 3452629647, 1696507510, 832914218, 1580729092, 2465374891, 68437950, 2231956715, 3260684823, 308203263, 2746696707, 1043692812, 3437464714, 3825284901, 166045774, 2083375883, 770398732, 3567792379, 4235901693, 3593552254, 271363761, 2808185977, 359264175, 3140291166, 3520675423, 3711176850, 951843838, 3535829616, 2487240547, 371184029, 3071441064, 2845112039, 1832840857, 2692234524, 4231322034, 3355583776, 4188014983, 2817671218, 413502535, 4284697057, 1051690593, 1240409713, 165879548, 2316064371, 3497882311, 2157985374, 4048825739, 2209831432, 680648571, 3859995817, 3381008940, 2130982229, 2372662317, 1074987446, 1352350087, 2015117098, 1569849261, 2562226880, 1758118230, 880317596, 225881481, 3197302071, 165280429, 3563559378, 2815615927, 3350513453, 2901794431, 1943518670, 831985412, 2025414377, 93627198, 1529173611, 3054993858, 2314502307, 208142722, 3072703531, 2154180133, 2987426635, 588063047, 3552374157, 1437548625, 3219728668, 570531186, 120668486, 2393191311, 1075671596, 1946938953, 2738773367, 342620223, 2383633904, 3866173204, 1097677156, 3538147128, 3585976646, 3571751243, 3324323588, 2709817236, 1679128706, 1646091223, 1428791560, 3878051836, 1674262915, 297087248, 1609058557, 1953194481, 2343513420, 2049634662, 1189446703, 1871140029, 710948767, 3681771268, 1790615645, 2587436460, 1102785925, 2584527240, 3983566595, 3602286784, 869716973, 1560082461, 754477791, 658106538, 2945530833, 1544959316, 2200987146, 374766255, 662433671, 264742168, 1832966994, 687330684, 222172109, 2483932397, 3256908853, 3984808097, 1333166330, 763252245, 2097445399, 3838271657, 1836132920, 292130122, 1366967552, 1839326060, 2996527157, 263034457, 2169887190, 3624556345, 2979074912, 4271570982, 3150483255, 963738217, 1476868390, 2501930333, 2174990124, 3674869563, 1585059704, 1918987053, 753723008, 2510106958, 2625196367, 2139177155, 3881218468, 258089974, 847766473, 2260969254, 4087904289, 385192817, 4201377213, 1003557987, 2550497304, 3137880396, 2485029919, 1649596665, 2666506058, 3979866806, 1142714106, 4249830455, 1420179693, 3527969716, 3003794782, 3592819030, 1341666099, 2396616618, 628721075, 2882635818, 3682568652, 2713784147, 250751105, 243141974, 3458061894, 1593432079, 3115289400, 1287899488, 293287525, 1587078352, 1684392149, 1243277372, 52614597, 2955462792, 1786223494, 3348936519, 3893130724, 65397082, 2743236235, 1417893267, 236140504, 2014414835, 2586217097, 843553596, 47, ], &[ 533748887, 249255803, 2930278111, 2944470994, 3468438302, 1853367511, 3473647788, 136162040, 2512039442, 4104038916, 3852375212, 1275965329, 1008075871, 2214169813, 1888868725, 1279476908, 4276240090, 1145241832, 967923289, 3300068750, 787590574, 372485986, 1752804777, 563557630, 458612420, 24065909, 2138189643, 1735118829, 2777615332, 4084773909, 1994648171, 1468124229, 3843301824, 3048990130, 3644669511, 2843255684, 1878415349, 935329872, 2974790965, 541343777, 3578971699, 3084472759, 1424633701, 3685324111, 3104832506, 814688603, 2875695455, 3922894541, 1129836145, 5401754, 2147990257, 3049844880, 2173716916, 938037603, 3330445082, 3666254041, 3405270910, 3095678827, 553456595, 891085809, 3061727528, 3662498742, 2303227072, 1295539877, 3135256485, 984687031, 2062195016, 4160985717, 4256936349, 1127108300, 1822161590, 1231105886, 799858776, 1165579553, 1680070401, 2892850160, 648277660, 1647906015, 1349312712, 764587048, 3479139752, 2548452125, 1587150396, 1936309995, 1397979205, 1160028331, 2481265236, 4096534487, 3145854678, 1359507566, 3145122135, 1464105608, 1341054633, 2384267946, 3072197904, 4101048745, 3497220211, 2496500822, 722428108, 2759126028, 157978299, 436271355, 2915111871, 819788815, 61498946, 531442637, 2748307930, 3964009512, 907090206, 3579477513, 1410311474, 3879339413, 3797360756, 525701452, 1865404342, 2036819036, 129435563, 1301441027, 2315064858, 37796474, 2259680720, 3209271106, 3616621433, 1524540162, 742243486, 4244739241, 3963525923, 3841435812, 631237661, 2750627705, 4061472984, 4187741587, 1602558897, 3739064311, 1787560972, 2417808286, 1669713644, 242684701, 4212963222, 3184994942, 2931588398, 3055841256, 164516699, 575009540, 3804101567, 3503774895, 2271510891, 2575068623, 3311266347, 600516698, 1830644170, 197244387, 1762254458, 2485090809, 2054999517, 445307681, 1916458424, 2764936458, 3968851404, 116007945, 1259880908, 2990377981, 3157975500, 63446352, 2623120799, 2892145188, 382309118, 428854973, 1627463852, 2943880856, 2716994163, 757412094, 73981451, 288837540, 683761684, 2645114357, 1148980595, 115985531, 1159455296, 2012810946, 3906610855, 1070751850, 3855881544, 2899111698, 1698770184, 927911082, 1201557705, 2190432453, 3174200176, 1716956464, 80922238, 1516540063, 4140722877, 2868191373, 4074259242, 3395204892, 1374888410, 569580618, 1352129381, 2834006812, 3958858137, 3965389351, 2153688696, 240913347, 3717468255, 1650698409, 3732578951, 4060697881, 1987293497, 3608486299, 2752719263, 3992727960, 96185389, 3861467259, 821639014, 1177132211, 3275501405, 4849019, ], &[ 1655755711, 4258340418, 2774516366, 1572935911, 499947623, 907167292, 3725633407, 1192948598, 1407557914, 2562035879, 632809853, 3145196737, 2065022779, 818461714, 3282493345, 794082591, 4062248109, 4105226099, 3252991187, 3950905876, 2145419927, 1859968878, 2278702340, 1297226377, 13775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], true, ); // - n == 0 second time test( &[ 104199695, 1437842355, 3026540896, 1036691142, 2895760091, 316986459, 3848493166, 4283163139, 1409731068, 2162161861, 3180981287, 2664973704, 3129778597, 1141759869, 3423483599, 3304860181, 1499458172, 2283443318, 304208206, 3898070080, 1624380249, 4217356185, 3984965450, 1989320468, 4046024996, 290564828, 982998126, 714749497, 1256133149, 1964245093, 1989969476, 2845229677, 75994139, 1534010229, 3551668582, 437558754, 2400783907, 1104529196, 2628109158, 767576225, 3386003603, 2589581389, 3197373266, 1119570806, 2388054566, 560919780, 2181214692, 895228346, 2455964730, 1236092704, 3460190245, 2187848751, 355369047, 1999986258, 3567727382, 1691926629, 2725212068, 2592492178, 797372755, 1342659622, 1706103226, 2741335822, 683303027, 2714389761, 3546978425, 1986412131, 762213298, 2333449774, 778670753, 97719623, 581978613, 3531804453, 1122531574, 1722591132, 2538512178, 1919025659, 3171826961, 3494777585, 3878057786, 1159079409, 1839284455, 1154718578, 2665661658, 897285327, 1500853657, 2633085447, 1751356374, 3270858770, 1163694943, 3330045700, 1488678831, 3027918693, 502928061, 1337476314, 3692361284, 2178683191, 3096849964, 970332766, 1824923766, 846751495, 2918346590, 70616406, 3836757211, 2684780384, 2463029602, 3457312899, 887456732, 3244684159, 1709425071, 1650827329, 1114331473, 2300037523, 47504219, 2349860938, 514226917, 2830450926, 3649882524, 3714094143, 301323195, 4142782943, 3785993652, 866247992, 2164534671, 2737799129, 3275770468, 215424696, 4257046307, 1733065842, 2434034911, 1462340609, 3642973392, 3350853644, 4199792744, 684333086, 217713765, 3411993450, 1792335767, 4171842881, 159579156, 2430618740, 3131183234, 3163246383, 2128439763, 2401347699, 2936760275, 3236944394, 2200904017, 2436166477, 4193014474, 3613539040, 2916219306, 4261812949, 115873482, 2180021985, 4055598752, 1260608904, 2416550157, 1259155018, 1431188781, 1176329051, 2299641742, 3980571345, 1599289272, 1782362083, 3811356761, 1974756300, 533380582, 3641430046, 832768712, 672407572, 1502225325, 1016817644, 14093203, 1980541787, 1908462143, 3913154473, 724095260, 1182316086, 719426427, 75511913, 3523894057, 3990195494, 2120530771, 3562485018, 1433690638, 2518584164, 1493664787, 3968793063, 3670159139, 157980348, 1301197374, 3305985080, 3941044403, 612257166, 3771911392, 2763453419, 2718688747, 3693090746, 589991197, 498197071, 2438022286, 3991964070, 377079193, 3099592329, 3321736969, 3902471945, 2307760142, 3013676133, 3258936160, 4011810226, 1053219984, 2837546691, 1856062985, 2092610837, 91102249, 406247891, 890201919, 2559127506, 338532027, 395154770, 3275565770, 1258530084, 2939576662, 2055294057, 1883048671, 3836169741, 2026424182, 3339579277, 1542609345, 417648228, 4191728149, 2895752032, 1515160584, 278532504, 1393858866, 1730994375, 3794676496, 1670361915, 1258111291, 2422641149, 2347194379, 80193494, 2358530906, 2877787771, 1965418230, 4205347720, 2666879163, 4215296303, 2916779693, 3935289306, 3244538076, 1632052180, 4176725684, 992286325, 2739073795, 2079197711, 2797905589, 2449598406, 289423436, 762177014, 2363661744, 772167940, 2765100761, 198147685, 572172334, 3817619946, 162288540, 1223981567, 540177774, 2154166987, 2653356928, 3206160568, 1862076861, 3133558385, 474824123, 2525460202, 3924632969, 1146129872, 1432186566, 737582770, 3316793636, 3709987676, 3557072993, 567470616, 1129703040, 1521364280, 3566052322, 916273230, 2293310523, 1377033267, 1508571570, 3382970810, 2996523808, 1581520543, 2618222496, 3288125825, 2313878894, 349906863, 2219317771, 3176122714, 1013378826, 4116023745, 1921798849, 3062375628, 2736960803, 2501959999, 1510561246, 1700569625, 1652836989, 3312274215, 4195830099, 1132143254, 950525497, 2316560086, 375651095, 2664099671, 455151019, 1159444553, 4198810519, 3127984438, 2144120008, 1969060002, 562539184, 1602239482, 2852481959, 2095454819, 3210933640, 3500352077, 3422305025, 2014869566, 2974700896, 3465912392, 2040467605, 4197300028, 3591134045, 3895974116, 1820422501, 1395818068, 2660152096, 1916184939, 3260276758, 53585995, 927898271, 2259302740, 963522240, 2856612864, 3450205940, 3367413678, 3535931570, 397649639, 3700183847, 1270654564, 3500464902, 3997758233, 3130672822, 2562223359, 638317405, 3181668171, 539650504, 2914453051, 645816251, 4007289298, 3438058969, 2770073590, 864060896, 2320524273, 3692263013, 3473619051, 3882200592, 499549190, 2692529571, 1895097838, 3793943961, 3454593367, 1512683055, 852698565, 1995890144, 865090611, 609912127, 2960073872, 1078887, ], &[ 3965328483, 312519701, 3403268855, 3606492602, 1902761898, 851349064, 3139262646, 633064190, 2260801841, 3139511175, 2981429315, 570792856, 3276826258, 3740173343, 2258820496, 613809729, 241642072, 3441475901, 4294219823, 976984900, 2389777673, 4191459734, 1003327410, 1302790361, 2451013524, 2641182095, 3622343124, 2806631117, 3967790700, 581646251, 2019686780, 2032370136, 2076036058, 856161788, 3365012291, 2890451318, 2127795458, 2187590985, 4093939520, 343783955, 4242308697, 4157888926, 2564079477, 4260723333, 221747269, 2643548554, 3833528808, 1763870742, 825076470, 259966747, 1095002154, 931639969, 3831275768, 2810876375, 3231187357, 3440619698, 2434935986, 612813763, 1378882183, 2162485107, 1140428311, 3695900833, 3397094290, 4162195979, 2662618085, 3751543150, 3243820436, 3516498989, 707780244, 2079085110, 448686345, 1895725327, 2371954578, 512402760, 2522669399, 3692228697, 4274764985, 3682675544, 3852971158, 3189904769, 3141125752, 3990040037, 688067094, 4206021309, 1411303768, 751179620, 1438168058, 3448172742, 917372130, 1562060869, 515503757, 2481107086, 2276549351, 4210575064, 1210846101, 3889280108, 1149707690, 3998423549, 450077793, 3069409039, 1205057532, 4241449813, 4263835068, 777002153, 97116780, 1862501041, 4173027391, 538950023, 2024750625, 1067091172, 3975089902, 3595618138, 1162626458, 2892893888, 185770841, 2582369494, 3927002631, 3209126940, 3017762169, 3322211458, 184442973, 577978350, 564069165, 3126111172, 1558987521, 3158591140, 2367515315, 3627578322, 3638689514, 2197481806, 387613, 3780351852, 2801314434, 1919960640, 414138073, 161239652, 5955360, 4204709093, 49134550, 1616981665, 2152668401, 3606726895, 1857761242, 1299061544, 3099986598, 3846390597, 3355161875, 595322253, 2252701581, 2283337465, 675228606, 2653548638, 3430616197, 2380374646, 3784410660, 1379122536, 3178229817, 3972552968, 3447966842, 1961475461, 918042062, 1365972881, 2129295687, 2448607551, 2884167968, 3568778297, 2408690044, 469704050, 304852349, 2906236085, 2120391091, 606392149, 1797001614, 3658187294, 2116257019, 2708625014, 2498918970, 3223950057, 4105341944, 243352585, 3784332349, 522017452, 1593525595, 4137737627, 167793374, 4087606703, 344557611, 2032896579, 2593781680, 1431393249, 141052093, 2496087765, 2700336339, 516501742, 1876246139, 1822328287, 2252547797, 4061227450, 2006777028, 3501565120, 3466396566, 735894510, 255684379, 303584386, 1336037903, 1323979436, 1064067294, 3553551979, 2832942530, 1268770967, 1027134407, 545735300, 3866535246, 2986685637, 1613305389, 1267557025, 31509612, 771698397, 1878270300, 110063942, 4276370389, 3260973919, 2964940734, 1109302596, 1411099702, 4020146211, 3169853494, 2389480541, 556890992, 1074682663, 1708332475, 2658991487, 2894729410, 2296152345, 1870102242, 955236482, 2125245922, 1470432646, 1889719140, 3468723644, 35016220, 2579705046, 2403600204, 2455839109, 738153092, 361506106, 1501550475, 1570537857, 2512180427, 2079164570, 3284728752, 2525205632, 1765298251, 324508463, 4289185078, 3262124640, 590432268, 3609992720, 1056480497, 1521962672, 2902938979, 3633169769, 818640538, 3205732694, 3783707657, 1320287971, 3427819133, 123698783, 1954647368, 1478731664, 729732421, 3485056101, 3384149754, 886686555, 3524117645, 3672706053, 3467528186, 1825239229, 3605286168, 4252587265, 2476737792, 1468148598, 1767076404, 3098062795, 2235174734, 3938633722, 3377437243, 2055298570, 974103332, 1521104891, 1331281005, 3901922961, 2788866965, 1326440607, 3830433543, 2349058686, 1891550867, 289592648, 833149915, 4062577431, 300173440, 3618259462, 2437802253, 1988806398, 1196009062, 1693726935, 4261250055, 3358655485, 1354639338, 4217909066, 3173323323, 1256774815, 2873946595, 783721831, 3287664797, 1212500109, 544495281, 3943757093, 3869342488, 3580616897, 2288353173, 1381949567, 1954109845, 1071065683, 1907373154, 1605862239, 399825655, 1608845741, 1366351932, 1757744839, 2456500252, 4271660304, 2736932691, 1256196079, 654792440, 3432423047, 814117095, 3916828311, 1478775709, 2623979306, 3502313771, 1912113011, 826313993, 2137260095, 4198684443, 54736831, 380668741, 872309827, 3132896276, 1131528234, 1143308601, 528742460, 3890747269, 2898367605, 3531963195, 2576564587, 2690837364, 2676539983, 1748034501, 3722941468, 2157585074, 738387831, 161914314, 3886930899, 805359701, 84535132, 1019698896, 1024816471, 2120663635, 4600563, ], &[ 436512665, 1372743407, 342109034, 2762999440, 1801741181, 1128075399, 536773409, 2462344174, 4092132461, 1413817282, 3712114490, 446843050, 2277642284, 924335942, 250799808, 1300467839, 3708770080, 346693759, 1462440153, 2514050355, 2607744870, 572189306, 18842802, 85605861, 3453161777, 65109244, 1981480639, 1036404070, 3325202117, 858703184, 1098140435, 137595022, 1796280951, 4121604160, 927712201, 2983534703, 1277109179, 1842338521, 684621561, 3003060670, 1334445980, 3716987280, 2509263629, 1481158588, 101476260, 2332533799, 3920104238, 1799849987, 289899178, 3790057285, 3090879719, 1847908743, 2289570281, 899352588, 1237257524, 3478208269, 2864532864, 4237285852, 2021619931, 2299181539, 2990516063, 1146232131, 1906740225, 365885015, 436254990, 1572217307, 2276239798, 2938321029, 3411408571, 782341583, 245501560, 1212705343, 3987607268, 2685812792, 3162630759, 525514772, 1738934514, 4026775891, 675427556, 2638310706, 1872560581, 378254209, 3521602859, 3209772533, 2171756894, 1916654768, 464606995, 1021746380, 1509799815, 1803124229, 1626950142, 1757247127, 3463260849, 2059493644, 3328028905, 714292268, 4221410307, 3024039287, 245477866, 4111629244, 2454388273, 2288605764, 4069258877, 2417991112, 1008037684, 1584471268, 480491917, 657289197, 740153804, 3304298858, 3549803564, 3389482897, 2285883880, 3754282415, 3452581852, 1300983995, 2563854813, 3387253149, 3144283055, 4223958762, 2984826191, 3538501116, 1630274809, 3571211850, 3145706384, 119892266, 3268130561, 2893468680, 3796377730, 1313792196, 84565900, 2317626527, 1585112821, 2831830124, 3879773053, 3823642743, 260829176, 113541293, 2698035069, 1162236214, 56045023, 2572314428, 3303774518, 786546397, 3304627813, 2532190633, 733612212, 3194392916, 1538645070, 871903777, 346960285, 3824030942, 991737609, 660569608, 25531145, 3125334834, 2019398137, 136254844, 2601227241, 3740691089, 1400597961, 758494376, 1289737416, 176798002, 52677595, 1282844193, 2029711214, 1154925510, 924664133, 2384558292, 2657323714, 3032100806, 2076618856, 3874064840, 2301862464, 2613824074, 2408544438, 3475871678, 4286594061, 3888658535, 1599077513, 3091123524, 691764425, 571533226, 643388614, 1946732585, 231085233, 3636702918, 3681581111, 3187061512, 1902159644, 1741637618, 761538126, 1536383210, 579538109, 2344701437, 1320685197, 429406282, 614226248, 3064576305, 3913009213, 1408468081, 2953160453, 1860909301, 1257356077, 2326226229, 512992927, 4173707647, 4227234757, 2055824003, 1797074658, 723531295, 1055503760, 3723048013, 1019848561, 1813977292, 2245679653, 4188374262, 2764314541, 3543381795, 700976608, 1790968603, 1926021909, 604162486, 3885171802, 886529425, 2545372123, 1099009280, 2144253074, 2286027026, 3759545247, 65262690, 867405492, 478202482, 3860597229, 1950145935, 2338053342, 1301482230, 1694465994, 665328168, 1639519384, 1246558025, 3758953070, 514219744, 1033396600, 2585944964, 73215891, 1407268144, 3275177322, 713201364, 1552227337, 3796620920, 464835142, 2341943175, 3119000857, 2088431307, 3897368907, 878918678, 1090403719, 3163407018, 1730981592, 3537552166, 2597674257, 4098649693, 1903525249, 274610490, 2448833117, 3013444547, 2285961959, 1309148292, 4284801003, 1457869563, 1131416271, 1048930443, 2513500006, 1482041073, 1625081763, 4053050668, 2518621166, 3969148109, 2761689155, 2164832372, 81475261, 3345442184, 3349299825, 2006252039, 3489857052, 1658875101, 691754231, 849076446, 3627267661, 317685450, 4140537807, 2104452006, 3534476970, 2383041805, 3170903305, 738640319, 3255529797, 1446723654, 1118811539, 2937204107, 1614377664, 2969444277, 2952928746, 4001684504, 1718111127, 2073038934, 1656108772, 3191239768, 1185532158, 562604415, 3971592886, 3000494224, 2019311576, 3398207772, 1017177624, 2967316419, 1650769512, 2231731784, 3739468469, 1827669898, 141217323, 4207733620, 2832371984, 1621792041, 4151096498, 2547492982, 308078925, 3687686062, 2475718624, 3561209065, 4026891835, 1696468987, 3574384454, 2592420513, 3300544973, 2850962487, 656760200, 2508381898, 419452052, 626276936, 285665799, 3657891297, 554297412, 2239031137, 2012129, ], &[ 3473487727, 2715824269, 302636924, 3827274248, 3626525609, 3832203487, 2822157013, 3986038466, 2374406499, 276102688, 3649155824, 3628559734, 4208420641, 1414875841, 3147732484, 3104062388, 2316940851, 3263871297, 737125952, 694969868, 47137177, 826969068, 2129205294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], false, ); // - c == Less test( &[ 187934912, 3963930250, 231958896, 4245982773, 1934140206, 440616703, 3262112836, 3803339338, 1055977017, 3477409956, 3459418279, 3536333193, 1703660800, 2104503975, 833240224, 886952920, 3757005223, 3905587728, 2036421476, 979947267, 617694154, 2023645391, 1275759231, 3404109586, 2938320668, 1202003004, 2980604512, 2032763306, 3902352209, 806323951, 3542789010, 3588280904, 2414505309, 2789124635, 708104571, 1248766971, 1432171576, 1128356364, 2875611376, 2278912471, 1150861966, 1291115162, 2748948894, 3634464032, 2110058367, 3206659726, 168682764, 1776545630, 3468415616, 1732523967, 4281271517, 3638902065, 531069836, 2942748381, 2696304125, 3283898896, 87384650, 1737516049, 155566843, 1249785223, 4063953505, 3904749325, 2017386943, 936929068, 1468046637, 686939124, 1127421717, 3660187784, 2539722337, 2063935548, 3712297932, 3468383353, 4239207397, 2627208190, 772818110, 1676680020, 1846256035, 3171012575, 1630885689, 3774178183, 624829565, 3829281971, 3575590705, 1125584859, 331886114, 2810170897, 180881990, 2376892097, 346183958, 1002811024, 2287792836, 2721987172, 1353923230, 173519658, 2840578452, 3046951447, 280393883, 1934407313, 3450248943, 3960335583, 2936886127, 2837374367, 1167738321, 11803000, 3709093930, 1660429674, 2214045250, 3121062633, 1551000516, 3932704671, 1434892291, 3144179262, 1765285735, 919580204, 212878018, 3986423325, 2643867381, 664022808, 1148663675, 441609369, 790629951, 2700888529, 1528024872, 2655036879, 926252445, 590467168, 69936158, 543426961, 2407749697, 3983036014, 3086285416, 1698716849, 1730836693, 558966155, 3162488766, 1631913078, 468599839, 987281756, 1175534538, 1143324775, 2780081223, 2255743401, 600016013, 1213392671, 1581032372, 1214585858, 2655366727, 1703054794, 1334202166, 3011637212, 3091624188, 2151823204, 1922265826, 1392986173, 2440236131, 546335907, 2571698069, 4064180854, 3016119932, 1276149514, 2750959023, 1846484680, 2487394348, 3192553460, 2046714633, 2105197122, 2859158014, 798086272, 3982320680, 2847110299, 566095532, 1909918779, 4064894596, 924591979, 3757772259, 204200652, 2316781277, 1618431160, 1291740177, 2823517809, 2489902405, 3808225904, 2814320098, 2402867452, 2628984107, 506097881, 3690769018, 1916622416, 3396296036, 2817276852, 294193788, 4014046110, 3348468266, 1808087416, 1217606688, 3107405413, 20303602, 2605163877, 4255862987, 1827267797, 4172243166, 1923964418, 151022861, 2805154409, 2725518846, 2804473785, 361448192, 966384361, 1011003843, 2130801904, 2756270251, 977045660, 1231631015, 4117590378, 1824472438, 1239240410, 3967925324, 3591091215, 3425508458, 2441519937, 1576668646, 3970317623, 3149254726, 2461311180, 2975630926, 2573169699, 3785791997, 1817505813, 2416636291, 243972919, 854993073, 641309278, 933994018, 2436076046, 714583961, 4233911749, 2877006599, 1841754465, 798678061, 3291065690, 4250181129, 1054668988, 133850660, 112252231, 1248382546, 2745722364, 2414244177, 1537381601, 375780842, 57, ], &[ 1219238520, 458286836, 571303475, 1095503760, 3936266545, 2915216623, 934419627, 108694817, 825922308, 3909996859, 445552390, 3436248982, 17043256, 2600050693, 3575940214, 4206950518, 1409086111, 3580010797, 4200868738, 3791772787, 3461031842, 3741905335, 1645461538, 2796220093, 571250449, 1978665721, 3872196348, 3512770614, 2265675397, 1898914436, 1471543164, 104009581, 1069204671, 3588685237, 3450163092, 2030632179, 448989709, 741456689, 1962549854, 4122206837, 394103306, 3616942037, 1828786100, 3308044126, 320612466, 2551987032, 745240126, 939005175, 4206308, 3000252168, 2480777179, 130665597, 3796761496, 1775773864, 2872549417, 625407398, 2323690020, 2598551921, 221395795, 2846135335, 1677691399, 1764804747, 1322480221, 2702514092, 907481141, 1520010856, 2089109102, 3213176228, 2731628980, 1909676512, 2922375030, 3610676871, 1917186130, 2032601964, 212603593, 2765257336, 3826304165, 2961560381, 2451767748, 1494602925, 450986581, 1939887496, 2375124190, 2296714928, 2097227393, 2659664732, 797225077, 3883459807, 267885304, 338353083, 43190940, 3825976024, 3634497457, 1621047893, 74803135, 1769067819, 3180705641, 685501232, 3040073389, 2934885674, 166648054, 775479293, 1448421834, 2276093488, 1738529462, 841982763, 1787134020, 1657493921, 908974950, 338854924, 3663099125, 1085361174, 1036174733, 3763552557, 26982837, 413060618, 1373197819, 1979314730, 3213976777, 1302698249, 970720900, 1026620489, 622266192, 2286432101, 3319123912, 3320832875, 7879744, 969439985, 165474540, 2783335670, 4017257129, 1393620424, 3686559536, 2508583884, 1397700564, 1059657114, 3253108688, 3016769809, 2955518996, 3439762840, 1604575612, 3040353199, 1887901043, 2891741754, 3012261550, 321348872, 2842231132, 3205943301, 2186892599, 3416397958, 3130842469, 3049587515, 1348282946, 3082616990, 229484403, 2826363885, 2099377666, 150762968, 1443375484, 1366019051, 574671368, 3425374251, 3605765854, 1133360577, 2107400592, 189470407, 682742956, 329159853, 3068502457, 2834141510, 3819877515, 443046013, 1887862589, 1289509196, 1476348830, 1890826827, 1049086736, 351021297, 391832608, 2086035132, 3540615308, 3691174269, 2350843456, 342151347, 1267574301, 4072009402, 4014660146, 225798818, 2079491499, 546273689, 3761716237, 4145812188, 1436903670, 700677104, 180962847, 2186328381, 2164757885, 1504132650, 136850620, 877049642, 74786002, 2379972976, 3248155677, 3811577426, 3703108610, 2542849491, 2801014761, 2439612323, 1227548239, 315200269, 1034453004, 540738039, 4093700781, 2455957542, 3200948464, 2592553580, 3880742794, 1453493027, 1877232780, 2259655253, 297001748, 2136807271, 3193696895, 3875290906, 3209590629, 1538087872, 3584987471, 3733925871, 1104935002, 1693308027, 4180523234, 4155046152, 4045108046, 2011123316, 3487256278, 1875596161, 2871056745, 4174156727, 1344816542, 3857831725, 2962655023, 1798522437, 3832165252, 3587644818, 1176470348, 3313939000, 1778856308, 3338213749, 138881, ], &[ 1997129832, 3629657202, 2915022059, 3343024882, 3990459908, 2694411795, 3258514756, 3026472385, 1853702029, 3885584109, 1571649067, 4146409127, 3984530047, 2610215790, 3737462160, 1099406791, 2146662218, 788888709, 3056174154, 1041105130, 805009138, 4059467671, 126218581, 1172679122, 977235966, 3659492466, 1913792212, 2951333370, 2882677768, 1142407645, 1914628530, 2290380457, 2645294608, 1071540072, 3675338742, 4268569133, 1325890402, 2114120206, 2748674301, 887843538, 135110258, 858895625, 595035002, 88286008, 368465230, 3466333800, 3978181230, 2244157953, 880291304, 1415196906, 1950141619, 183120630, 3331343751, 3085264924, 3772977910, 2344692597, 1372314528, 4241980412, 2518506943, 1793179256, 3502781717, 4138291196, 631566271, 2941001615, 199022841, 3005296926, 454728643, 1266860929, 1589661982, 1894863838, 578957394, 1114371740, 2919435517, 2479023152, 185063110, 2777031077, 1762844924, 143409635, 3450352997, 222248907, 2631593823, 2561012513, 445601702, 2619088364, 2551601117, 1369538011, 2600641370, 882915033, 3960089315, 894064017, 2204735730, 2859261389, 1569163540, 1412453825, 335934685, 250113882, 2581213657, 2113774668, 2333833748, 3550525401, 2830439907, 3027550887, 1296938289, 4155767149, 1847057132, 1262782444, 2104318482, 2969377868, 2942666919, 2780256120, 72912746, 476732544, 499935671, 2613299648, 3770003380, 3907567510, 1570763914, 613427901, 75022176, 760795510, 980487515, 3982014189, 1706577930, 1261188031, 2870746969, 234951136, 3857521632, 1051273058, 2871865682, 3661635885, 2141962953, 1115899513, 4060498786, 2643559294, 830174517, 1317284160, 1367063869, 161782948, 3985824171, 981195659, 992438988, 1733040918, 1209715468, 4244765037, 1507960056, 26996790, 308817914, 120748456, 4074583276, 4288631919, 1756259216, 3539103142, 2594578601, 939606767, 3170169733, 3302019519, 2595861584, 902451826, 2171009482, 3018639962, 4122320509, 13953107, 720393910, 1565490086, 863799491, 3286780228, 3837205729, 1522600897, 2688343839, 102578734, 4122020506, 2487793514, 3882018410, 2657573876, 1560242433, 3913939651, 2722125884, 2569012670, 2119668862, 332479976, 3976410832, 441652705, 428547637, 3653985669, 3541034639, 140605135, 3401899925, 2195242099, 3515812005, 3799203204, 1162859943, 3822268708, 1042520132, 3579913270, 3487482443, 697875289, 2992841272, 1965247641, 2154121107, 3413224392, 4257940059, 2921786635, 488976439, 1651666056, 4129306837, 874002760, 3753306770, 1455127647, 3856964540, 1208320745, 492650068, 3978622128, 3967533748, 1419634792, 2289002630, 2909276676, 8, ], &[ 2887151513, 2955117088, 3686481916, 1282567524, 1792560750, 4239267230, 3914824829, 3001031255, 3151588641, 956076517, 1285983934, 4183803874, 1140560885, 1030876542, 3543344996, 1462200064, 4016479346, 606984379, 721894422, 1276631426, 45197611, 2675196050, 4142633094, 2013186106, 3704885393, 644846435, 2022612550, 964745357, 3786420454, 4020594532, 83626040, 2888472095, 556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], false, ); // - n == 0 first time test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967292, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294967039, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294705152, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 67108863, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 255, ], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], false, ); // - scratch <= scratch_2 second time test( &[ 2207864798, 267946504, 372323977, 838488163, 989944659, 2604803451, 4238223922, 3691348995, 2672166889, 2939963021, 3204498048, 4080880943, 520137010, 27769463, 2996159453, 1607673725, 49056055, 2967627226, 168375317, 1738935943, 1325619184, 713770625, 2156270437, 281935012, 847234582, 4187043368, 2605789371, 2211145637, 1570439865, 1275820484, 1958339168, 4105135748, 1923071232, 457462043, 761246786, 4214022096, 2195638580, 112902937, 712461934, 4150385043, 2909280359, 1210932542, 2559422380, 2784873521, 1639849226, 471070719, 370170546, 119573553, 1368711102, 1550820770, 2952943579, 1078928939, 1933590639, 3128564987, 3729618936, 380208622, 746284712, 397317393, 1370494230, 3280997641, 741056649, 926342725, 3063757104, 781251372, 2248837423, 4289444674, 3481867568, 2059529012, 2144237229, 1476518116, 2913224606, 2784322121, 1097765568, 1168414897, 1147821222, 3213813929, 1626172092, 4271849462, 2576546258, 3083396894, 279893624, 3759599720, 1914220656, 828504008, 3974235088, 3853012955, 2315717336, 1369841715, 2099820461, 2355062255, 2644110523, 3939540670, 1818016878, 1195833762, 865290937, 3227403814, 1989864511, 1481749490, 3485866574, 310041183, 2533950297, 75004791, 3170685440, 3048279373, 3575702533, 607339517, 1986365212, 1940313431, 3142582191, 353694395, 871105395, 2372958566, 543478756, 520650729, 1271503005, 2299655823, 1652537103, 823994264, 2608198867, 3138891496, 1607548416, 4245522527, 806354235, 370312244, 940261358, 3517654229, 812483183, 4170416364, 3055737710, 597269095, 445327768, 2982695405, 673942649, 3328034346, 591105255, 392089798, 144695525, 1256851674, 624209363, 3254182856, 3318200640, 2228436782, 2636252257, 3867863804, 3299061215, 4250741776, 1207426433, 4111586753, 1433876171, 3615256411, 4063241139, 2498423720, 1094424000, 3501308247, 3428304735, 62836544, 283854756, 190630197, 231903905, 57469653, 2752417874, 3101673320, 3005834242, 1529425204, 3429882832, 1804302400, 1318870337, 3239774213, 1334291598, 269327930, 582347024, 1364483740, 3892520550, 4289141082, 990514330, 2567575103, 1849070181, 4221031912, 1282643459, 593306019, 4102935754, 2687630825, 2454603670, 2459317428, 15501938, 3220012509, 3194948341, 2770827885, 310256151, 752576061, 2802821281, 2143132954, 1951186309, 299076884, 3784631385, 3065258766, 2300539722, 1724661440, 1345721863, 1147424999, 3414798132, 2527323313, 691503965, 1255394592, 1035171486, 3133259824, 4119299626, 2493608670, 599503941, 2765526454, 913507389, 158575106, 2604793526, 3681411980, 3672418896, 2370104217, 2345217795, 2451256505, 182685832, 370382859, 1240673894, 2151490488, 1145090727, 2583769931, 3389299303, 3617246559, 2294336112, 2073635621, 1226465224, 437889431, 994073059, 2739895539, 124748784, 2577790545, 4038673486, 2597483545, 3481432375, 2505906026, 3679053579, 2567446299, 2503584552, 1724814969, 2074264558, 3116425221, 134201557, 1904374056, 3315661235, 549731342, 454384735, 3566798071, 3867940763, 2036012380, 3964771234, 2078494356, 2910348743, 747797952, 2098288390, 986676007, 3208665881, 1099888732, 2812049765, 2863541208, 2056114848, 2807277926, 4173414039, 2185629714, 3676605702, 4090003868, 1521812446, 1591739644, 2803711764, 3349612318, 4152536289, 167187079, 1109738310, 3386413010, 1638194434, 511325059, 2815222562, 2979314390, 888373194, 1756285774, 337401670, 1312397774, 2225199035, 1193707747, 95565948, 3829450604, 2889994162, 646979858, 1291101250, 2723798680, 711154682, 1562997144, 3387241029, 2812924248, 2054189861, 2169838638, 3629024244, 840598691, 609335244, 2414653125, 679470536, 79538859, 1624495387, 2511298639, 2309910409, 3555938356, 268130581, 1947633553, 3045420973, 549742072, 224897407, 668694907, 353072335, 3526743582, 1307392155, 1190166001, 535370516, 3860183456, 4280474483, 4212105054, 4201052689, 2222668678, 1132900091, 1875434903, 780351451, 4242541455, 341093661, 2036456209, 1265036963, 4205331811, 330055099, 3993013070, 973468955, 3971628834, 259595192, 762722015, 2480719174, 1710909965, 2123904953, 196992042, 1557228268, 1413718141, 3778152886, 2345636147, 4003574271, 334744826, 1632792779, 3919020616, 3350171760, 967345803, 2004912676, 2345756953, 431565280, 425143888, 2508188340, 2547798264, 1254968085, 1863009118, 398460841, 1879223599, 494787534, 3574856019, 2613953972, 250872328, 2567364999, 2635183965, 2959501381, 2452785113, 662128752, 4120986560, 2400899916, 3250192037, 4004124111, 633976982, 1310968479, 3727657282, 1817457036, 4229391439, 3957420779, 3239547770, 3301276480, 266768554, 4284644798, 1745391213, 1262080108, 3199469071, 853588407, 2606347792, 2941502225, 1876190400, 930981169, 3941623801, 1625100318, 2604943583, 3782802841, 4060464082, 3647780641, 5070295, 1623035143, 3958489901, 2521266672, 599485990, 1015886800, 1253517067, 2724576291, 3813475335, 3121280611, 1633026042, 1195587036, 2940382331, 529194299, 1351837567, 3738569469, 4045542638, 2346072268, 1273398955, 267131951, 396975896, 286803659, 1149330511, 2801542386, 4199751737, 103066683, 730138847, 1747702256, 3943184911, 1592324021, 3100174818, 1170108054, 295368469, 2424270403, 1735209619, 2694218542, 3164559995, 320787887, 78612319, 2284898023, 11760395, 1289538398, 2139493945, 2627390499, 956126278, 3294394229, 558269595, 3881840986, 1107587531, 1856221042, 1934595832, 1977407844, 111930272, 3225213770, 4099233643, 3154542598, 3008462371, 1277874557, 1835389114, 1375729246, 1757935365, 1022886910, 157600366, 2218081795, 3638914215, 3989555118, 2514846600, 1364123507, 3997150189, 331489658, 732412399, 61544381, 3486712684, 2067650074, 2442996119, 132546950, 3013930940, 286094619, 1351608462, 1526299551, 1736674287, 2966093870, 2304608780, 2310910201, 3584030181, 2286788688, 3580208800, 2724383396, 2370465396, 4031550116, 3189384914, 2876438438, 1882299544, 843001851, 4230731183, 2046387427, 2928994095, 371034597, 3934073305, 1573675188, 2406063825, 2982153066, 2528190111, 3260662096, 3002143549, 1048991067, 686266540, 3261750556, 3221346523, 1507114940, 2647179569, 422609670, 1364060069, 82429640, 176161954, 3184770293, 2169179636, 3563306373, 303785467, 486879944, 3872236636, 518027929, 2299495525, 3476857792, 3781803472, 98494826, 178025696, 1214390986, 647981013, 820079024, 15594344, 2603289961, 3759408136, 1311725377, 2126848746, 49064670, 3681656437, 4273985052, 3089745094, 381952953, 3381602452, 1394470919, 2709871606, 1713656628, 3464289356, 1341017672, 2638003074, 4022970468, 3951442590, 3856460108, 3901197576, 1704975892, 4179858327, 1431684317, 2828263518, 2508657849, 3947513951, 3935760369, 3404427334, 3832119005, 718983465, 1749978964, 215727325, 4216502901, 229208963, 1354930099, 649831302, 2025249346, 2693822228, 502075714, 2421819020, 2747240795, 980027199, 3374599408, 544706505, 2013624864, 2766333752, 2098502440, 3902772424, 338884604, 3634940605, 4080595246, 1638807668, 1684259728, 3059250443, 2172893199, 3538110152, 3478895157, 2800095107, 4043539656, 738227109, 3948708786, 1357612601, 3881918572, 1356664172, 2722239998, 2453995713, 2625605974, 470854339, 1935940818, 3428649222, 2842707479, 2159686685, 2398586602, 3679073343, 4241106730, 3642573010, 3575665306, 1468515834, 398421162, 950044483, 1441313135, 3470466287, 470281996, 2070040948, 639744573, 1886496784, 16593554, 2208929955, 4260306612, 3193473955, 3375276611, 3996290151, 1136146657, 1489196229, 1419887692, 2292036861, 3694112622, 2919706063, 3100194667, 1484197325, 3549945004, 1522671191, 24002284, 3211652949, 2762484261, 3939747829, 1994490545, 1144446909, 1822384341, 1901184544, 4268199168, 2605681981, 697139491, 2856504476, 3045275346, 3379852695, 2641104141, 1330467965, 2369583793, 2478837155, 3509876047, 1888573009, 825341526, 743325155, 1645582432, 3691310401, 1229080683, 3871746042, 2875308637, 169010848, 137004370, 2194237916, 3583760613, 1851012996, 726079332, 1505680146, 1297204040, 2132899026, 4089124529, 2486768213, 2590417760, 817026308, 1141898311, 2558632297, 4105699206, 2987428229, 597663836, 2212062554, 819846513, 923428648, 2462552489, 4135795414, 1543581349, 3064612878, 1312692328, 599302820, 1025016110, 2669833556, 56885279, 1591168366, 3239302690, 2325183122, 1798020769, 2104555363, 340901196, 3194669248, 390374937, 1727515068, 4108789610, 1288974809, 3795317714, 3464480796, 2292039476, 3470123229, 705713191, 4256764273, 2161348120, 1447485170, 3758494209, 788131452, 780229334, 1106864775, 3793660699, 2445133966, 3777035595, 819389524, 3892566390, 3407549413, 3227341183, 300518463, 387764471, 2380248113, 1729197239, 3428482984, 155455760, 829543768, 2722547370, 3554403124, 812426914, 3192715449, 2683124433, 3704774242, 2168519994, 298764353, 697574938, 591667235, 1988966365, 50246387, 4078997041, 2562651834, 1501631915, 2017042659, 3127123704, 25503995, 3119397638, 3301140486, 2329565378, 1981524624, 1297772077, 472910707, 1113726624, 2246419297, 2173176490, 3179858158, 295919283, 1830694225, 1999826380, 2297530317, 2448843247, 2518592623, 1141482305, 3773458233, 3781707512, 1233919318, 3304887301, 1445910053, 607614300, 1129306627, 986762603, 2308600978, 2865579095, 464341339, 1874976807, 2472734638, 4243348378, 1589361130, 1268999506, 2328885250, 3453241404, 3161700650, 2022592823, 2434991366, 2905501888, 1000676904, 2945640510, 350883243, 2057706565, 3723496599, 1312397857, 443053385, 1656623019, 436794531, 2972149131, 2101756085, 2636747785, 2827788136, 3325399240, 1519360112, 2148131487, 4275408126, 2559264929, 2155218555, 408705191, 2678426907, 35399714, 88724426, 1292649545, 193199758, 1785136437, 3293099017, 22207906, 1704235368, 3813101835, 1859471334, 1536488896, 3801116568, 2980539495, 129286719, 3431136037, 422860547, 1093808922, 3271487412, 436540190, 1214949518, 3434807061, 1246383625, 2045880999, 3670278334, 2091673673, 1931453474, 1228423758, 1049668346, 2302097300, 2400619235, 3016364582, 1225008042, 4200508302, 3450569819, 2092048469, 3507292221, 153341111, 870856813, 4181342018, 1189866155, 3010246912, 2579053800, 1117609369, 2417897276, 89947314, 3761785076, 2414464808, 3888012859, 527327488, 1933822526, 362688102, 155109985, 4048770501, 846572819, 2837447967, 2770664498, 145789694, 3839553910, 2866036746, 1808293083, 1070005863, 3548714703, 2507585620, 1302729888, 718439670, 676557718, 3614065087, 3077432353, 2395163490, 4192287340, 322031736, 3582400735, 4205960063, 411313311, 50068028, 2364544815, 3733256371, 1831962662, 3273642479, 1799226082, 3422917229, 79914988, 3885678539, 201486939, 2174260526, 4278173973, 2367863611, 2768836913, 1087889156, 124138064, 3808061676, 2018110790, 682700696, 204550776, 625691105, 1744714606, 1730621404, 3600374506, 1586924064, 2248351654, 3971777918, 1741870997, 4064054751, 2884162546, 3952625505, 3952739050, 172969533, 932280451, 3088028569, 3980924886, 188319657, 1008821011, 897498538, 618759017, 1934226832, 4056744150, 517758257, 1266466953, 1408510284, 4030648224, 3312465353, 670664097, 918175230, 1981211089, 2985646689, 1004639722, 2959165856, 3023976880, 2729741254, 440746831, 1823292900, 3793265589, 726419087, 3812731147, 1386805021, 919129844, 2261286496, 576405850, 3960900338, 3818458090, 2925072331, 2547976826, 1802644337, 4238066789, 2720089855, 3876034741, 3997915349, 2674746723, 2818969610, 520496674, 41932556, 4123589031, 1743180571, 1421796312, 4144865302, 3006197001, 2227936167, 315485534, 2242455699, 2456927057, 607376874, 2675064510, 1495909763, 1239994157, 4005467423, 3082847040, 669418602, 2096857008, 469663740, 1666657154, 3296043597, 1516742664, 4195397062, 2923718687, 3030047089, 3888372574, 3236272437, 3138650044, 3129018831, 4125760857, 3337205269, 3400132539, 1857007007, 1596984050, 2829397366, 4244126509, 2823631628, 2523726031, 1677710269, 2013214373, 798959878, 1793629380, 2132968888, 1648075931, 2845025107, 2097490113, 3906486861, 1807833101, 435514889, 3934764479, 1098486125, 4032520466, 2815744570, 2773869997, 2575535711, 3746043311, 4009497844, 3747962986, 735431675, 3807774883, 1999690510, 1293100149, 1661461083, 2131154404, 4006902927, 1296628909, 1294936716, 1415807603, 1791067758, 2218414480, 2831527418, 3975259639, 2807570946, 3605807085, 1905516363, 1811255151, 2663406871, 946197416, 1052953874, 1452588707, 1222425888, 485961625, 2056322360, 2510622018, 2005905014, 795785021, 1310920835, 2853342075, 1839541335, 964552872, 3047952597, 2254414197, 2255269464, 2926189131, 1254336754, 1439392090, 1781045022, 3157005256, 3483123654, 4037579045, 3428424709, 293895523, 2758713523, 3617061254, 4288799727, 960408289, 2739844991, 2074136610, 3541374620, 3227061912, 3441616651, 3833993152, 3897293889, 1896341258, 2945397484, 2479746639, 1303521728, 977852420, 4280253969, 477750734, 315603138, 1542659211, 2286924731, 1664791134, 3764251784, 2683369743, 2302296704, 190280742, 4155403524, 1959987119, 4018799944, 3661747660, 420947441, 1758427231, 4067565082, 3644362023, 4146725047, 3363603799, 2186132521, 2285103006, 38292869, 4185461861, 3425353017, 138771686, 425583559, 3478794692, 2760287534, 561443352, 1494564865, 250902498, 2087645947, 2076144240, 1642460632, 4288407840, 603095924, 2394191304, 3798358252, 4227860896, 368672739, 1555920455, 173107565, 2567400351, 65160714, 762867799, 1148461951, 2614770170, 458503218, 1735511062, 2269875099, 171964488, 2136814257, 1228414445, 1927572185, 2160278324, 2054309428, 994804285, 2021021470, 4114554993, 1634603738, 982118070, 608007472, 2416606, 249711725, 572999697, 149618916, 1483648820, 2227411430, 2388613276, 2021804305, 824462328, 1735571526, 3019974769, 1749385085, 382545215, 3416879049, 2790726904, 4069675602, 252299181, 3002819063, 2332346451, 308641746, 1957137326, 449388289, 2118742623, 3669011855, 4152476874, 3965751318, 4236449456, 490466694, 4226329460, 2240230067, 3216403093, 2994870716, 119762713, 2230455654, 1399381494, 2101641317, 3187433334, 2108055078, 1391388188, 254099050, 2589444481, 898951953, 2072283422, 3927467514, 845007169, 3577789684, 1558628724, 2651045034, 1212903351, 343329096, 1898445525, 1326838604, 3047851038, 2157437823, 845680213, 518174357, 3522670470, 534362915, 3664218865, 750303749, 1724920686, 587767680, 2139076488, 847957445, 1538394424, 1661039145, 4049218121, 3471436969, 4206426359, 1337744569, 2535491673, 3502643500, 2130710337, 2402741313, 3361602809, 724016021, 807987580, 3177217641, 36267848, 3985940203, 4216766274, 608000979, 2344883927, 2983040167, 456888620, 2160109651, 3855758720, 1150083868, 1971074955, 1150475749, 2208716822, 4053070093, 2383609214, 509367456, 2976646853, 2707623442, 1297168815, 4284713829, 2174028883, 1414644915, 1541470075, 3266194202, 2650005104, 2992521109, 1617855119, 1820910085, 556354320, 1331692718, 3919092863, 483469781, 739285226, 2970950520, 786712984, 3606513875, 3341063418, 1853823168, 293688524, 3140711652, 1492806246, 4149135803, 3878795308, 3579077295, 1196448459, 3313646103, 835334685, 3564142049, 3930788469, 1095693627, 3017450909, 3296148217, 1686531301, 4201249479, 4249709697, 1733600093, 2968646742, 84669239, 911666828, 4218457075, 2397100750, 3946354862, 3895122510, 78534891, 4242121559, 487384917, 1234287101, 325300674, 552528806, 28967938, 2743714447, 880207179, 924380132, 323670498, 746809207, 1873876944, 4001744977, 551745798, 177210549, 4027516709, 3503445130, 2810800759, 2063027261, 2603496827, 1858275470, 2455908148, 3752388973, 3125514303, 447041729, 1331722548, 1601928576, 2663711250, 2157712093, 3107351309, 37006319, 1773106797, 956557516, 3422376226, 2889017577, 1692316830, 1953125949, 1967796663, 3083756768, 1926757633, 2727010078, 115237822, 1110144495, 489100004, 698396872, 668015191, 287016765, 153684426, 3314893591, 1738305917, 2124636239, 3065607396, 1211922237, 4155779026, 2686135517, 3152689181, 2273765741, 2305929046, 3102311785, 4067099644, 376227668, 850456121, 2655093559, 2253410767, 3053960186, 3136517000, 2376506714, 2198978076, 167053539, 1674606069, 2111411809, 3213120115, 780298251, 3145583860, 2106951428, 176501355, 3196899217, 1006630234, 1197567396, 729828289, 4008008083, 2031252014, 3339512627, 1905231540, 2153178437, 4058419567, 2549419534, 1715698713, 1187830199, 2690465091, 2699515267, 387902295, 684677883, 1758402132, 1077553874, 671829629, 1579362859, 3470373493, 2083206420, 1522523196, 2152754996, 1049504922, 3497597593, 303295213, 2681342137, 216056523, 3675528810, 1473254965, 3765716290, 121672078, 3340992172, 2485207380, 723308636, 2669088429, 4128123447, 2047156743, 2477418036, 4121144203, 3357339724, 3564422774, 1669395917, 4079088771, 3993308922, 2459948573, 364881959, 1315333244, 4014398665, 2430429976, 2016468670, 3177070707, 201701441, 3637392629, 1441169637, 1754712142, 4174632016, 4176705647, 693975874, 3368012845, 4274414278, 885317914, 1953640138, 2381435303, 1738796345, 1133209251, 1168367788, 1362136868, 2479222746, 3782466280, 863855088, 1923912907, 1125624828, 679234693, 1634797603, 2094454206, 3142755816, 2908162961, 2072001788, 1661299913, 3875625332, 2707731618, 423307058, 2898907250, 3503268717, 3181758121, 737767364, 918943481, 1304348279, 2566402815, 3496814351, 1564856704, 1388657691, 2406023896, 1896198305, 3069457253, 2923754138, 119355642, 2857705293, 769341058, 2978345004, 1534553527, 663090564, 847347997, 2587240491, 242187107, 2896367723, 3472050655, 2347813662, 1356685945, 494637732, 680685257, 1425963307, 1890409650, 391111402, 117486478, 2687271121, 2569131442, 3448367135, 328970411, 1279479011, 1332847023, 3999391195, 3967117874, 881199244, 281885599, 2831346171, 2662229591, 1111976857, 3384886038, 3385627855, 860959649, 1063819909, 333825758, 4121117400, 1103147759, 918519660, 3863046147, 275149412, 4037688836, 71150444, 3250961101, 3616961172, 764177351, 2871544730, 4294515525, 3907217335, 3960609997, 3990722348, 1874554171, 839685879, 3208875400, 4253927853, 1335778155, 3536387240, 4193480399, 1271939158, 1931098057, 3413750198, 1240012911, 2396181303, 2934711314, 4116556712, 2497540168, 1417536580, 3901731019, 1144472333, 644042442, 3533397404, 1987400541, 3754946564, 2970823585, 76024287, 4146754204, 1160107992, 2522776052, 1035755005, 2198611662, 2401924452, 246565027, 273575685, 3342921856, 162720950, 515478011, 4110888187, 2447034792, 270332860, 2612078407, 3765975483, 1467244922, 1697259556, 3633635754, 1518955080, 4035333100, 2314861466, 4082794026, 2698813143, 1041245647, 172854116, 2514009189, 1660242354, 2410532964, 1249062576, 1759112273, 2861193269, 1859853497, 423258407, 572469463, 2385055402, 1737018384, 3951247404, 1775922045, 2943917817, 4124850023, 4153955379, 3591756960, 3555365287, 1628013687, 2519466401, 1835517069, 803270943, 1901180414, 3222192168, 2430688685, 1126575351, 3964298512, 2870880038, 3596780915, 3280732674, 3962818511, 2399058457, 1405004423, 499866991, 53000375, 2632025099, 1622793184, 1553006183, 3794494151, 2458706012, 2523459527, 126475368, 4106824016, 2194771061, 3688396860, 974769395, 1297012764, 835010776, 2720278216, 63697952, 2810166462, 2144133117, 3029262703, 1543619115, 1995238361, 70403905, 1619836963, 468473393, 3676095258, 1202459143, 297731154, 2710062651, 98122944, 3122073331, 1645035563, 1108115397, 108145364, 2330954276, 526078568, 1404447222, 3526386755, 4140740686, 2322362279, 2587623705, 3384373140, 3046474613, 1536723611, 1686089515, 2571353196, 3088816320, 2761978195, 4069639571, 458472479, 1667007366, 3586522709, 764791214, 2651221071, 1258368830, 1168063154, 1688030022, 82496799, 380035370, 181435803, 794910172, 734721870, 3546283870, 308796098, 1050055665, 2263473439, 266580540, 118179498, 2083060809, 1340514773, 311819645, 4157383340, 1883326002, 660889540, 3418539360, 1752696786, 2275366810, 2614933182, 3518544185, 1267253138, 3889405643, 124625361, 1117414446, 2551289039, 1020556710, 2071173079, 993669125, 448240121, 4198691303, 2317385191, 2347367078, 2180467974, 2562147194, 3426306008, 342770977, 389071347, 2626938676, 3577495844, 2012092897, 1126580865, 3897331973, 3739466185, 3126476921, 1506468186, 2594251884, 3294645514, 1420129006, 3546602078, 3496104880, 4189405101, 3435121191, 1825436329, 439731432, 217831139, 3592377934, 2570558676, 3588355878, 167489809, 3098995631, 1171541367, 285921519, 743609214, 4206476898, 1546426566, 3039013901, 3906658086, 4242703098, 118469340, 288477448, 3303781383, 2719115933, 3828501724, 4045253773, 1841177224, 3192383594, 3279278833, 1930081728, 4190212501, 2897283764, 2844960201, 2771350527, 3138042688, 2694672301, 2131602218, 1150704347, 3013434029, 1173064751, 1305558427, 2843386810, 1471391482, 2759202452, 855547399, 1956204053, 3370880522, 1255955321, 2795686336, 1076458302, 970300036, 3153299065, 4223547074, 3860939449, 4230718590, 38001240, 3064810513, 3384957816, 439992760, 4026444170, 1058668347, 1922732368, 4193111406, 356852998, 3870316532, 3397225746, 668917921, 2266851967, 835585776, 780426826, 3498269726, 3162168287, 174523526, 3443784212, 3504266379, 1642016255, 2273394208, 82106921, 3031323073, 1327917773, 3671270812, 515360527, 3485174413, 1622293521, 2292557065, 1534517419, 2834918852, 2009648839, 406363840, 1564078559, 3221438119, 85746215, 310257526, 896742646, 225399336, 938279191, 489743135, 3166616288, 749448040, 1659919527, 2643680756, 3053562861, 2626371453, 2789182905, 4256520229, 2266034708, 1897042968, 1489068281, 3151211597, 3938498615, 643560855, 2408383229, 2016412422, 1970225890, 3127859458, 1123567461, 1375149358, 885276948, 1927174646, 1504220730, 1155235804, 3493735453, 1050114482, 705530258, 40892990, 2552903793, 2959299427, 1052264649, 3677672328, 1769321260, 80289741, 4089483475, 2224947548, 1916309738, 1431857202, 1074482608, 861817142, 2451620781, 1923149737, 281314181, 1045720895, 2805465876, 3877165887, 2508795311, 2658788574, 1802041190, 1653833199, 2016289858, 2562056916, 460818753, 1988829810, 620386006, 1201360991, 212428852, 2970308761, 445763026, 1902689676, 1259338648, 1635521532, 1336529279, 3385368606, 879504562, 2477265215, 32430763, 1330178819, 1681621049, 543867373, 3975593432, 934817020, 1424412060, 3868906817, 1958034967, 3221474893, 3396815063, 923123078, 2491071956, 2898837529, 2083510542, 3750663645, 1546801413, 3836848323, 3873887257, 1774964590, 223297132, 2867810846, 1025837760, 3141260827, 3591004993, 2996508015, 794889711, 622599472, 2716485001, 3771834349, 3250439816, 969134693, 798429189, 3095405242, 4109754137, 807412357, 2679863978, 2036846998, 387342363, 335795869, 3080104754, 3985604208, 2453238086, 2155458134, 3885993301, 3727575438, 2088458021, 299414086, 235421224, 2322887197, 2170976579, 1720810544, 4057325852, 716222429, 630466531, 108963102, 3405479941, 900376377, 2134868198, 1369037446, 735382677, 2596226624, 3160709333, 1759175216, 3109953837, 959302650, 1701311308, 4004119915, 3938153091, 3756203586, 3215670726, 3902940441, 970223515, 4265172557, 3131049990, 3018035071, 23938165, 3830252593, 3096941341, 2534730323, 540189608, 1257687675, 2224611640, 1098273642, 919283405, 936743460, 2044686015, 1289697682, 2705980395, 1460360764, 2882507518, 957012809, 1857196248, 2374943094, 113023629, 2772719931, 3393213693, 1457109280, 799171674, 1227543017, 3124650768, 1561299938, 1958193362, 2558867781, 2030627581, 3056580313, 1546708173, 3369294573, 990086654, 1018890730, 4269430159, 2978612816, 1393034326, 966883943, 875558742, 937751814, 3254120159, 4125279962, 1890777572, 2548823748, 1766634072, 4154457908, 2927533548, 1337202963, 1799866026, 3588751997, 540880761, 2601559406, 1290846119, 2946813313, 2440536968, 1585788395, 2535923551, 2544923063, 1091952113, 2408246024, 1833297455, 1245351586, 35996687, 2561575102, 1245679498, 1797369424, 2539459724, 4018603980, 1266905522, 3359991042, 2965523367, 2842136887, 3640375794, 1846651190, 926838720, 2797630797, 1656280503, 3716993260, 3815634216, 2829852267, 4127790956, 3069637970, 1297143679, 4036009161, 3451848971, 331658705, 4183579900, 2977429397, 869650821, 2823210870, 1384423216, 3355992925, 327220443, 3377291078, 2183157960, 2170753129, 3685297616, 4002815254, 1218631307, 3500571556, 485900266, 2223534543, 1781234150, 3522077821, 3994164616, 80005254, 1107899367, 2373439633, 2416239294, 4077248641, 600562639, 2506709277, 35719881, 3057800476, 1664138944, 3617887436, 4170522081, 2642895279, 2925504625, 1493795246, 3723550391, 1040365926, 787018705, 3735881512, 1261887079, 2625034884, 314234302, 1009128380, 2741746546, 1502189325, 1956583908, 860027349, 16253404, 2279931243, 2142800419, 2056732515, 3091443754, 257936547, 938621453, 3531654261, 1138201098, 1468158367, 1588936014, 2076905766, 1881555238, 1115940621, 980620, 1921666937, 243373074, 4065573935, 3327157425, 1181889476, 2773479966, 719236841, 2344522929, 1563036498, 687363491, 2853124242, 3942171582, 2891270183, 614415772, 3888652984, 2522401747, 483917577, 1607503539, 3259835375, 1845214990, 2544390924, 3510428752, 518287508, 15401488, 1537862071, 2607212256, 737021210, 59269435, 31901400, 3178751704, 823291635, 540970256, 3611930566, 3780782884, 2548373515, 2502777177, 689549215, 3391163060, 808307728, 2646717405, 2147997472, 2735020579, 2566584531, 1630107504, 39531, 1297790849, 2655041187, 2370282243, 2361911777, 1282851326, 3457585571, 907204238, 548668403, 941578097, 4181153446, 2468509367, 3912761648, 2441117016, 2616287806, 4195570577, 2064118612, 2318617113, 750221145, 1610517261, 2177813430, 3308454999, 180937478, 3206619146, 2074509599, 3983048387, 4105185044, 4126069239, 1177339043, 3092246754, 560726304, 2649026329, 2441046785, 2956435873, 1104195280, 3789602406, 2057735173, 3944401972, 1637107114, 3295404389, 940828999, 2372552464, 1301436580, 1635292578, 2463978109, 1507708380, 3157587545, 3107331090, 3033124569, 1952302059, 2174022081, 2468554200, 3669966186, 2950489482, 884022410, 1273464555, 2109238458, 75941470, 3505597749, 3016439296, 4110905824, 2697859427, 1113621242, 1927971013, 263777075, 209890344, 674546626, 406422800, 3433735010, 1894806300, 3213385994, 1438836610, 108558096, 2503418887, 826008761, 1756346775, 556419644, 2418173354, 697723090, 4204316540, 2438521010, 3708324212, 3859786082, 4007756898, 1207658913, 1876739876, 3362333185, 2002564051, 2376092083, 529190103, 4091783008, 696071515, 602161487, 2450891505, 3994285904, 3673645797, 1761598859, 394892777, 2326707057, 4177076947, 2877672514, 1108139616, 1481659690, 3913915235, 21522046, 137490441, 2064131542, 4016824673, 1815999718, 3395971408, 3872898814, 2704664018, 739122335, 3879952614, 2170216895, 822171254, 3864211038, 1157543801, 4279556974, 338667522, 3778390249, 4251673243, 1134882446, 3449048461, 2497814175, 490372194, 1614478034, 2449676507, 3285255597, 698188477, 2211286358, 3572358210, 2064461182, 3280673986, 2679425296, 1021956592, 1263445490, 3641226340, 2305222965, 1242131538, 3728624529, 2545230520, 2469167240, 2496394127, 970395708, 3765098302, 1007752991, 3313230621, 3815999369, 3974761468, 4151581136, 3872189039, 757531491, 1761466676, 764238951, 3992056236, 4033462971, 273089723, 5130216, 635102000, 1358869059, 4235827151, 3842068474, 834470549, 1382495504, 4077628729, 1223495534, 229282291, 3707402138, 74008911, 3423512426, 268619776, 3183737001, 4116691592, 1561234472, 3174521724, 3964629359, 2934992758, 3385929863, 3678150546, 1033521112, 1033631320, 2398336734, 3927058372, 61775127, 3503024314, 2543416818, 3002873454, 3273671920, 2314439554, 2343128370, 2560404004, 223200564, 3505824167, 2029929172, 652609431, 1843797677, 2556526959, 389484140, 4168965605, 1713633569, 519723200, 467547811, 2950521066, 956859071, 2865951480, 1547835342, 1356165679, 2048881525, 625833450, 2195811934, 754355770, 597026413, 1145132789, 257410419, 1351464915, 3268216458, 1688290503, 2421168405, 3084659622, 1664317679, 654476981, 3089839290, 4043322371, 3169046544, 3039409567, 2983777737, 2384745587, 3822729800, 3952168366, 646743126, 2878675149, 3695507160, 2122663932, 3833408626, 1100226590, 2080497564, 1254861104, 869549291, 4129861030, 1333339898, 3199185304, 1951696094, 2127229443, 952554241, 1962675343, 330897097, 1155824411, 2399540123, 3849911581, 502304153, 1228525171, 2090678312, 2778936604, 1928685248, 1326148668, 278949133, 1155380569, 2077014021, 2154248261, 1811547707, 3092104962, 1877536544, 2258902690, 4015463079, 2518922484, 313873124, 3114627572, 168782757, 4292739149, 1699426393, 1054120991, 2897087402, 1016299387, 348166873, 1656210558, 3277400802, 1234839024, 3653821699, 1047939580, 3320592601, 1680797677, 206912832, 1673987761, 721342671, 71472161, 1183247443, 3861076616, 3375952709, 3717870592, 2708317584, 3637121110, 811088203, 2621702262, 1812508633, 2137382046, 2942356198, 4241340356, 647478471, 862601530, 3254259589, 4191366771, 1783038785, 3492781592, 2694731846, 4035229945, 2514483134, 19314785, 1559470376, 2598636927, 707522098, 913629879, 3316725542, 2197890863, 3259943868, 790933912, 1209008600, 977252818, 560870087, 1345858049, 1272598532, 2100101860, 1460073301, 3810231967, 2332779907, 3329728566, 3374513586, 380064777, 3559279778, 199067497, 1496247894, 3013403693, 1505292651, 1527020411, 2248666664, 1072740489, 3349142584, 2190946807, 2531908207, 1325920971, 3362462391, 283097209, 2976343972, 4118998769, 409630812, 596914346, 3556152068, 98997087, 1133520, 2018406002, 73893637, 684033678, 700648351, 1016840579, 375714874, 3205686569, 1611515901, 2982866029, 2489442949, 2978944926, 3026043400, 1741032417, 568313262, 616435295, 1322139456, 2115673147, 2122726766, 1171022314, 2271561100, 1925355022, 3132186990, 3284714989, 595797359, 1780525301, 224557524, 1782677730, 1382233152, 3762179158, 1190829764, 2851043401, 1797988695, 484888476, 3425567483, 1309865473, 2159690577, 3076787705, 2954117748, 879207894, 3653374210, 2635114894, 961988277, 814246497, 1655626503, 3078243965, 3985381952, 1845355762, 302605246, 3409331998, 165146303, 2877521999, 436450944, 3505698203, 626475985, 3175335946, 2861253467, 2906362681, 3457214865, 3900019220, 3707324556, 3744297070, 13941252, 324629421, 56931867, 1637452242, 4133211044, 967059531, 2392073552, 2155222929, 827777228, 224705208, 2679136100, 2928193744, 1680538879, 2674977225, 431299707, 2656838543, 338076941, 3925410476, 1453159665, 1638291904, 3717080438, 2594117423, 1796481757, 566292664, 1101232579, 1892524354, 2867824980, 1986194419, 3645022734, 95501445, 1035398942, 4206156453, 3313967906, 745187521, 1490957950, 2887345352, 2351344415, 3624760687, 1385080065, 1385613344, 3628174115, 3325276383, 3019903359, 19708163, 59916348, 2259420453, 4156768184, 1972374389, 2713826926, 3263625409, 525776986, 593277138, 2528773656, 527534624, 4192986568, 4069704011, 2353381625, 3443164316, 917873859, 824621613, 1348015973, 2791013820, 912713245, 2301066231, 1043271452, 1427176131, 2194070572, 1515038936, 2214605589, 3319491726, 1909339943, 2792999697, 3352439695, 3846954040, 2746362829, 3422849540, 4234166054, 888443580, 3419461068, 294678858, 2963203454, 3691629423, 1229141312, 1025641218, 1076117873, 1882194608, 2746501222, 1048453531, 3570791631, 1611657035, 1619323055, 3312615746, 2129243489, 3662602052, 2023333004, 4250359816, 3705135710, 1521186945, 1557379762, 4293623153, 3474061277, 889662967, 149515716, 2286534743, 2580349289, 2493889647, 3936210607, 3777337336, 3648682329, 1749187339, 3307377676, 2373135578, 4290786668, 2331614525, 3758294724, 4090863676, 788127985, 1308353102, 2981273145, 4272092012, 2592918397, 80242490, 1789804765, 648951797, 1810479995, 463468086, 876446290, 3224927410, 2741684758, 1511448286, 3280636620, 2111736381, ], &[ 1646146781, 3355366092, 2702609393, 2501235092, 3733186010, 700936760, 2949254378, 3941657596, 1111121033, 4114047683, 21857804, 3660896777, 3180332813, 426317358, 759192794, 133148016, 2444168985, 705181436, 810858227, 544973542, 1045076571, 2767631874, 1386197246, 2229668431, 2408262678, 1954842634, 3210209379, 3240609796, 2975719943, 617575291, 2866649129, 3426939111, 937961033, 2054180310, 3471431788, 1672676648, 3156950223, 3869664161, 2172901918, 1518975727, 1575628045, 1232340363, 3157709780, 1259140866, 3436805064, 110644241, 3472914360, 3885831843, 1214796010, 2486779305, 3866219100, 3359465263, 3846595218, 2133165621, 2667175892, 706531988, 1917852025, 3933960303, 1438158614, 3474111452, 3630409082, 419107516, 1644047204, 340459195, 580898688, 576012343, 4014031077, 3154640491, 3864900517, 3736610191, 3202885253, 2034477116, 400359289, 2065940182, 2338917689, 1071531644, 4121237496, 2530330005, 1036182313, 2226961460, 2130726372, 1703507010, 3358389574, 1225776313, 1887309618, 1041140724, 2976038173, 1594845227, 2269484592, 941206007, 1323369145, 2376782526, 2067414392, 3709104198, 481479269, 645500232, 1764555773, 4276112852, 3020598880, 433428226, 363294871, 2382460155, 1741592224, 751560264, 1763549028, 1027869401, 858293834, 745414920, 2275280160, 200515730, 337140642, 1917257826, 4005848489, 2489874622, 1544738876, 1865379047, 887297512, 1175944717, 3655727089, 2031696781, 2736254777, 2818871878, 2461747542, 4291762939, 1286151054, 867203316, 625891936, 2270318752, 3694153050, 3636484252, 945112863, 2572193756, 1040297298, 2854336893, 3643535993, 3919773026, 3548702381, 4065778594, 3925809349, 1114320208, 51831817, 883978342, 3685226305, 3790877730, 2759683223, 1186418715, 2915574045, 2306134333, 438568791, 436432277, 1508448090, 3999224995, 3003289861, 3131995873, 2626109782, 2125783393, 2590734454, 3521431348, 379388900, 4037066789, 3285658717, 216950511, 2146635151, 1008841483, 1088995930, 2317014732, 3812136931, 3052665149, 623586000, 4291592846, 159122978, 1098774636, 1161856516, 1443893456, 1247911225, 2691592128, 4264994549, 2932303848, 310043971, 2439138785, 1471300723, 72590841, 416269517, 1742690078, 2955604770, 126459712, 1237916340, 3832622593, 3766542510, 3954115374, 462741019, 4154011681, 2422631136, 1831626214, 1724126713, 3374004102, 1617908227, 1823502680, 383531122, 3274056604, 3410013023, 2716762020, 1282998507, 1263573709, 1814401622, 493902553, 4186488610, 1176732404, 1538896701, 2460489097, 1587982136, 1526971541, 1877728886, 501343654, 2394712320, 635931406, 1962574554, 3223124541, 3732290209, 2418986942, 1060861829, 2352911498, 639287502, 2712704718, 1657230104, 2177202118, 1857324074, 2671537289, 3653958575, 3052416395, 1409120341, 219280650, 207974641, 3801486048, 2053036362, 989398634, 2036886128, 4057159303, 2391998524, 1318700555, 1061459168, 4106033714, 4032643681, 466625771, 1256123990, 1667983928, 2189315362, 2551360770, 617849547, 812261463, 3470708155, 2585475768, 2320365336, 1298782542, 3998064195, 3346965201, 198859120, 3305395420, 1790931927, 3297472010, 1269104527, 2507420556, 3420815083, 1101711384, 3746991716, 1567229876, 1065930578, 3063199524, 3304959814, 1626772921, 65856676, 2848887803, 2288463723, 3248694053, 3079420802, 3968253791, 402813667, 3508325296, 3349973232, 3688041923, 1301619532, 3685871260, 487170548, 570123370, 4125725456, 3677755226, 2157460925, 427108406, 3879547774, 869853205, 2554135153, 4061381160, 1913392263, 1365980653, 3908381940, 3129294403, 4292759986, 2875699867, 3804570020, 3144713839, 3363828079, 2252500219, 2989960833, 4022527656, 3371232929, 1658953553, 4065476169, 3864636723, 1530129807, 2034452468, 3810606961, 1400085318, 762877038, 547416674, 3824691318, 2503818238, 2493425324, 1231786822, 2142499902, 1899830999, 3073913029, 2551549271, 1988003374, 1933834159, 886172974, 727208241, 1017262994, 3988743024, 3609733723, 3737234596, 373762137, 262189319, 2434235823, 1359363910, 1597683672, 454900071, 2050706103, 4107843825, 1938290587, 1024370354, 2592270551, 3962726762, 1637931050, 1053400878, 927450698, 1000390015, 2385445684, 2572969347, 3739841633, 3684234613, 271137822, 563269856, 1465838147, 3005314960, 4229712654, 3837253448, 435587471, 828030019, 862923027, 730290720, 1912025891, 2390308153, 2583390009, 3343546426, 79956066, 2827980992, 3413931069, 408627338, 1798679536, 1119514034, 980810067, 2144998123, 2607179866, 2828481231, 1319660174, 3716254590, 4132334094, 3218261136, 1985916552, 1781165079, 1903530289, 1735545873, 3511460291, 2365970305, 2760279427, 2211944401, 2446029333, 2874084882, 891630672, 503547522, 2161173297, 2621987372, 3071277407, 3858752694, 3901093525, 2628974288, 2719072256, 2275671814, 379871489, 925158760, 718779106, 761096692, 1507689428, ], &[1], &[ 1384477170, 2884998501, 1180219469, 4109004296, 997383516, 4044033164, 1642951852, 1446808083, 37175391, 2282859045, 3021624688, 1519116461, 446662799, 251919701, 3626002578, 435516186, 4024242472, 150377540, 2423436388, 3823918787, 4080248194, 3948319529, 2000604485, 3122826894, 3526159102, 3366269145, 2534542644, 2550218265, 3200129864, 2159209452, 2182432402, 401115950, 2821309687, 239933185, 2664953808, 2357894845, 853801210, 3660041542, 318923345, 3517297895, 2212131962, 714145218, 4282708480, 9060286, 332854610, 1640882737, 2274474152, 359553548, 772749702, 21304777, 2685844123, 250427744, 2712214224, 1732121973, 696245192, 3692005482, 431760978, 4036957805, 947474652, 507006669, 1844245414, 3447048613, 4118003939, 3258234256, 332091427, 2676890228, 581426731, 724721810, 3284157922, 2832713193, 3430818129, 1695270315, 1267960932, 3717578816, 447816382, 3427035588, 2945239339, 2054990649, 944648822, 4277320760, 4232599274, 2383932030, 3955112699, 2167411416, 2401960559, 2449661069, 1066034957, 1109347927, 812652844, 3137823672, 1081890562, 2425070195, 4115043270, 287066004, 3477258057, 3243315240, 265080242, 1183810880, 3153328886, 4242653340, 2977780908, 3377641, 2118786885, 3211374316, 2291698760, 3035946153, 3478658417, 2319878939, 786270837, 1645769599, 1867721861, 3170407804, 821369564, 832960650, 28775725, 1301119218, 1275059098, 3451682256, 4158144332, 745700491, 2936987949, 1899895335, 2346517904, 1325249418, 863110111, 1168153138, 1560258437, 3401092928, 2117866811, 1802618925, 1402878426, 2797692103, 592665881, 453682, 2631030100, 149759352, 2084534022, 1795101898, 4182881971, 2649866336, 1921107451, 3994934130, 2816002578, 1822991777, 1349573145, 3032559829, 2540814714, 3013758928, 163664171, 191165209, 2331004477, 1429461234, 2716039347, 2185719156, 1252162106, 464555833, 4154750437, 3679682194, 987581007, 2806961127, 1887482586, 254459861, 2072955038, 2243973750, 2198996441, 2437053653, 3665070992, 1854548618, 3949323616, 2025113759, 439338007, 402662802, 264268340, 3680188821, 151523769, 1731425914, 4278670439, 3370237175, 362147816, 886490711, 1141110037, 2453736536, 2044605310, 3105398498, 2157501656, 3910457974, 691927672, 1446337471, 1613812436, 2666418229, 712270021, 3236367167, 150725347, 1084313070, 1795001305, 1231031361, 1709897758, 2442210046, 3002335200, 3780675251, 3023181201, 3990675322, 3265698246, 3578374156, 912240552, 3797996535, 942494693, 46776743, 2266421929, 4259387576, 3248631026, 677049778, 1453865772, 727557964, 3158196760, 4063847549, 3729108589, 1777788538, 2663505460, 1694551555, 4189846403, 1646696173, 3085522472, 1719621415, 3707623970, 3935633904, 4088061793, 1081642164, 2952049343, 327976869, 2512996297, 3343771543, 3125428726, 2308478069, 1566295941, 2893752657, 39300663, 830599015, 3367437319, 3024938506, 1042041491, 2570706837, 462611755, 3486119893, 2035139721, 1635071811, 569595532, 1720829657, 1358110023, 2914778930, 219340570, 1530923910, 2576687137, 216246939, 3960993840, 2208752072, 3840693415, 472560666, 174320230, 2007799992, 2726548658, 3816296630, 2703856294, 732227014, 3984094206, 1651367171, 496225802, 2327983813, 197957522, 3819963453, 1286871047, 2505137551, 3313005770, 628085062, 478935762, 1739071792, 1625549370, 1198147593, 2291378564, 3651449689, 399851227, 311179769, 1483912270, 1824355223, 1763094698, 437432824, 2953027184, 1022534349, 36805731, 2288180438, 3686039894, 3542100244, 3571608951, 163368977, 92026250, 1303579581, 2386223491, 2086519661, 279834940, 421495954, 2205711554, 763664240, 4220494928, 3669200795, 2725843891, 2942466103, 2008412116, 2067360644, 121006392, 145470486, 2754718513, 28756690, 2686802151, 534105911, 2227506204, 2915524950, 374448528, 3564386234, 2402483348, 1977446727, 1483606137, 2952984093, 4139816448, 1647736560, 459815661, 3285933154, 1207099812, 175342675, 1741221097, 352840926, 2625096334, 2710737503, 2629594976, 3681301317, 2442494828, 1869698490, 3179988132, 4055843278, 3537171797, 2323976681, 2894226889, 2016219796, 1785512150, 1685999381, 3040725772, 3211050132, 3211545999, 2932416769, 3157674122, 3611745811, 1615208817, 754103285, 2917997451, 3057928191, 2740171565, 2322640572, 1252615274, 2175924660, 3853203495, 3691442798, 3389931870, 2729950991, 2582622100, 2045535192, 2165169808, 1715842299, 2841471402, 3631926092, 3961888437, 1563175160, 4006882514, 2443776711, 3570024276, 2788029127, 3244589184, 2037749031, 66483334, 3934700964, 885032286, 1488668201, 3115615962, 1637760832, 2832027294, 33854763, 3028541518, 3945363766, 692524956, 1013718106, 2016756299, 2300366534, 3562014518, 3108634777, 67494910, 2707199766, 1429312309, 1443945944, 3723903532, 961216960, 1135263177, 3349312249, 3843381071, 1825349027, 649833729, 0, ], true, ); } } #[test] fn test_extended_gcd() { let test = |s, t, gcd, x, y| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let result = u.clone().extended_gcd(v.clone()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = (&u).extended_gcd(v.clone()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = u.clone().extended_gcd(&v); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let result = (&u).extended_gcd(&v); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result.0.to_string(), gcd); assert_eq!(result.1.to_string(), x); assert_eq!(result.2.to_string(), y); let rug_result = rug::Integer::from_str(s) .unwrap() .extended_gcd(rug::Integer::from_str(t).unwrap(), rug::Integer::new()); assert_eq!(rug_result.0.to_string(), gcd); assert_eq!(rug_result.1.to_string(), x); assert_eq!(rug_result.2.to_string(), y); assert_eq!(extended_gcd_euclidean_natural(u.clone(), v.clone()), result); assert_eq!(extended_gcd_binary_natural(u, v), result); }; test("0", "0", "0", "0", "0"); test("0", "1", "1", "0", "1"); test("1", "0", "1", "1", "0"); test("1", "1", "1", "0", "1"); test("0", "6", "6", "0", "1"); test("6", "0", "6", "1", "0"); test("1", "6", "1", "1", "0"); test("6", "1", "1", "0", "1"); test("6", "6", "6", "0", "1"); test("8", "12", "4", "-1", "1"); test("54", "24", "6", "1", "-2"); test("42", "56", "14", "-1", "1"); test("48", "18", "6", "-1", "3"); test("3", "5", "1", "2", "-1"); test("12", "60", "12", "1", "0"); test("12", "90", "6", "-7", "1"); test("240", "46", "2", "-9", "47"); test( "12345678987654321", "98765432123456789", "1", "1777777788", "-222222223", ); test( "12345678987654321", "98765432123456827", "37", "-577153682403132", "72144210138067", ); test( "53210985212644002683182379010242100104171729746702422680779813004957564024060483478832914\ 482130776086943264778009917785771400263865734996803824227786705410307715728084358345686525\ 666955903442304160728096000478646410984438412892096337955320031377720994976196082976902515\ 475717316111445459643194929610572824881990973023469555025226995677148631273880820975143597\ 831952984119683964055138681965121900967812243353623419763457671607645603999610405594590486\ 872093104567190784464147432587592450898810445955458144467151620244389730813698904479644791\ 294670488649490319750421527379672354012120444416458908757409522861289562515268026280499438\ 641806141881438096739080037626687584189564479677582527752608125024890483099472450227206754\ 624817717578290132794377168533077053784736901385512425558741488599375141073342655809435567\ 227547685589123962107657740818440198851187052376695978652283425565793719694392992719063521\ 134328692281771049779324906964172346910876836649893103029553852739448996157575281261917767\ 462289778120317683016791957216391056858799293583579767530391770523628160305771464317552404\ 286415844497761280740749180268592936052323253151358109674397371860779496995312051516136343\ 612847181875036518544052191404281333580248246008117110841406622141848028115726825781495096\ 023066580543384031510610514530023329859191130909987959067533104292226831366117223117365539\ 076389748270068524013958358846689057807214037472552997058633682932574608802897333022001067\ 339767267512913044107763435719066947490496062127159179697412179675200594498582437769062032\ 106609527647647155310901097021926836956717765421150081077663197060352698277949891205344276\ 398861495791843547732671833443384827472568583890381928618497270970782368809415629392114681\ 048034518825010025530558395212016441248426070937066334000515283429231039788299226204028103\ 035156559074396814100222600998417211095724539178513979945252990396059722845072657522704853\ 530011258265578883744793665826446961940035340770987704528846170661806469860862323120060600\ 188716257174964605689834771035334287148298050873783292933007990864633863360851706708152274\ 741836663844952580453159016288332429022925661018852374290980352561723666338668811453247679\ 014938296095366457872688823644411907108248712726680503309453969901050687122079964577461573\ 162449057761724243617422749368227513730067603187116527525816979714703280645206367108943359\ 106913022723406929677039338452031585410723171878810424664534307822051012682445600878401920\ 391578438489860798959109565416251907002316381271860455740167875993364799515992972687239649\ 262505346275006613584575234884720386321569557741241845741527499938163930315502221011033166\ 978332933186840659678745110368027451832524439637158308990469666455002407888248194456358359\ 003303584715991518021477565902469791143312856111094055209930912059849631368408330026958170\ 300500052755648852405373421396065524685232424910319283382913578078436761328209023838453572\ 133871613682203794227711619723455082311584610371110039795962654391918340254088377920041056\ 377309453598423058002481787581331503006766698794968240393060646993432133789355956306077522\ 005838667605083279202957084353020652660658144238653295685751148726967548735573418209687787\ 467834141377482348535629112173783424658448326805091434859993190291004665837059259500568711\ 455850112822407840990469904590429374564214805016358736565409593989044710192662123765463450\ 672972588274038572597891463730749923741649553162200715118457359135337272102100729029198028\ 918389058264289464021962419840267900832170796088946861843699490514285866139817826140431958\ 589415626642762349104083760670177290291718048221838912239788379338860589682678474741960115\ 308805411814721629474003485325145328968908328606072640911502882836248802102769614929782398\ 730979902324112602478726951562229293169116613797296312251779636711555303451849944537708310\ 801131408238364215456625216763655273938127881890527292337937027210899452008994857736727918\ 885033534731416970620401446325145822869475926086614847561269180270467972553000381511940196\ 279182572288987445388104237426718319436680800461093698741076654884624736167050671120089075\ 282386495334580204700654987554577746716144292112714866349972381971774912662283900282488295\ 218996190161997330321826846740433118110308620925798899930220391255594082221295100829777595\ 979347307584113527503428496108921160529535700435459104118653387569562978972671042516904693\ 810745225490997755749644402714924878354004249270957656670619686002686882814167999260187282\ 055328251894795584803808155697918384152898853694821363462264146320840510264219534810450612\ 929827615517166467144562282245695274013804708632196293102656043771290261465998585780112007\ 388542114043156335580538623481266070034537267475499199416632459400066621964519464083762939\ 464714380427800499737792650032454181044342899816120428850127417546623784657922281632200912\ 161848262920191580623945633091088538955337107042051551668697130031566457950434604523676163\ 043032891652256507757622090615452544894824913511398707666352802094610340994251033590813299\ 765364312236108674038130828085071997231118916261973118087939248672075257862843017917893314\ 033345178209992539373295968119618157737049619102812429241222762039593668904550053680641639\ 389267383134196322949369118104847075367153574163403499344124070556491291271313163644785541\ 723453866178786858649956547169137241403737306831022854961563771690691014668445005399015743\ 939371799899140664516745666984533538205690486945356410433150062226302533155376556003683260\ 539391785706720537621070094792397845909047047655976082519165231675957064976971963495074845\ 400818760119815443094989219656728142533401627244302260359118740813768823984374575959252833\ 144167528744407735299199580787932320541816850832666571997744821660306170268434905949899327\ 266240469172212654527453885049713145956756927127727870583364826726128281756089904146355590\ 455829914673593711898789960872024428250898271592856329301689603627742736402591974705801123\ 913488054626112958406496491382377502094688225568173187111352310212308380669459790084393363\ 960883523181682291456431327909193716881944868315280595392569779974711532990380265055310891\ 022051373675075944778564890967215880361915872678562811138776286273858432617125011313032313\ 168318678984271504040530108775957206558580572943170989601778895262364393281094944972007762\ 124094331253870797410638264171838445695086318338080769305587531419584524233105109659682203\ 090923064062775237309184959029009607296104219167515035467015219883113736043851707266717383\ 559193712086972417551299928007610742208281705317863761479399221643255488085627999915211142\ 672046384840617199937210833843040740102526458882638797167263946326576840910916562011762226\ 706661382306360487929173691857388546757991075899605094253100264860031215071642999888965997\ 869390671338431704166432399428812946998317163816600390678925054197124972370304217477166546\ 089768163889437951691529426837016116240793274480116483450272217878061145047170546441620981\ 823170749155210537097780210174902502329952048525709554527381750141111597875089446887970940\ 262534007886042193961250806085012300304485692195713700363250476128223889785924988282242047\ 811208321107880647174999725298510927743456763226114735869121851323770951914868919115215317\ 365494366183599970291302382989049305582844781286411645202771800782108267056030270481771127\ 232627235326276085068150025360962124512278936384527298219083493101010604796985932149592092\ 070170567378681819658905585158346941619724195113662650366802273496667910050658093652805409\ 869963179595758113779491694369787691558670017783776813409931952830118752601701691901037586\ 418610004899832067781002855042381352969423310148491105412551508860494898767560096264317892\ 830589036793601578974344275517003959077442276732058503049385598570378664682089672636076453\ 082080632305926571864613777254452402275747692731274482901812940957009957142654303337221353\ 798094669642765671629562320046032765636176312442669290989279817217560679987637165595701228\ 351366685037359968240182767578602441805653770668496072883137747821769182663422011405220423\ 727217640104065163573431179928538260507079965922712687776153947468313356665668723515996291\ 552340142968459634562542946557786741048870587285010793715863275713556072680213389279361568\ 038965518710201803091193737009363656674819832448879814850406487813509908693767107886427038\ 476937063288525152867128415946460612768771476070887109107975523614045879552703548213926998\ 419846194661441809164103065854852763932318796907774950751348476157538370208075103687065896\ 948167859797720286187663893016336917905106535811345801047375780666495580554323392997728250\ 541187081595078546945520695566326266506064602589830874234940044630797297248761948040553129\ 503418374270682794301831412022012475533904383260395490657136380535495354618029622928612139\ 519593340366467161755196399806646295817737292725855915047117049822881000515392663832145766\ 188353944809699342668752899960862785380180673655165578750508424013605762525153272579409328\ 924500985979930675570919202129414835727967374179300788518918789482400970793425585256228619\ 081740926041287768110312330089409730950092765206723292820551676037697566463588073440027619\ 983938331355169156857627805220863954826347048067823720549066551110268768271517993610317591\ 513522070495592868434278031802044259419208412545225016316781705305455205097065236119922084\ 771404744955209445760506196414721295328700384580971655488748393727344372310863411826316595\ 739254443259354847917481178271709881972592331937735246506251014152117886027428023838429577\ 732111238549313001110216938283754490570632543294130258292207071256171783238651813426163606\ 628095387459232009512518082630058983995863610016577240052696973235745212040970034367232808\ 104731784606406027056204571625394610236258846776494225863131465466566526405374505823370473\ 520707017673738942998569172434684116370340822663158977787712737333206451248305988888549603\ 955197923343072509971172659371651177380410476108204283117487321411337910686990689261335221\ 338447456406133595687997654886951956396949111457705781116687931764802765061924644289463419\ 393414121046439112415317741512004234248773134964634958890904518960762592129237311077431104\ 588549710974693588401501363556926820587180528921974033260435999235803014570593669413052639\ 436919382666978608848780897560711427110650599116424995300681743791426389613664702302620282\ 121838824749211336073909492561563101037774890259297393161326986784880258206030293504023492\ 370086206401508292494549552549202756745363414493020119441643375954875549438754562314408814\ 426936447009665627565711004615869460295005775122173629710447631252774622228457241518587615\ 956791269541912241072131273480752931405509875234056047437577200248846944137530449155089538\ 394376552420473710983527523419509606059777670885940592326889264118264472276983496825554814\ 763115461594047614125625603423290018459740978768242759023788556284706971531970679882147267\ 031347386386695261790217699134862613984017229899919526937449697985754434840814975722630828\ 042807504163238870614971272376079064355220059355027968580734422261145684039864327533625629\ 676278136526912980702004761045477499121964848643675704865393521158794355626208344526004780\ 789059780492659952275224196637486580408272129416475260644240132339669185687684808739426659\ 897298261137374008000798171978135550443929130844771865653204625562676864531115837728704760\ 497273891619605225880387092718405651497906324643561511236430550544649637999926184319221247\ 618194357758089057134164362561038381271782792662090240950491969354492855505655908064120034\ 812933302781984817940008716135592679756965697066715740320334780368449441966885213229372986\ 171328622261598326858518868539318302276595053793818260449670297599949805816456533278515282\ 486611166138379819987079275968286707072075400932533136998497276084731936017797620097821291\ 361480270741140435974508680757195666173216352453388395174374030653704233046487081634203106\ 207578691279885846031260954415577833653989433166649581327941516166162451774602342782382455\ 794918167699930744044597561495347138903501195320961502043502535219479152801485120443622289\ 571172204994874763402189523133946117802128111379244125914628860530274893123999063129909629\ 246510888813000461704527831246184145713985209447157599663956515433838904179905280769383252\ 408345027952081044657330942288651843864378904424143599259186715899747781545562079953463616\ 610795016981202182267568087866584306853806059810551537195844600879555996597315278760544939\ 368949212046012458251172874859445840568576598132809498656874159336323866122390377126092357\ 264383212385984858590110103690717148531908354149441382452158926433127232267720449649030735\ 896505540225228012970976277749633885099429501038767455418562060354992992057303994294167925\ 518419271324194262573208628114565671227955125776936190934277505877045484040688946030844159\ 075885247477763270118332191608617711225564068780820085063043694080355310945662744175498934\ 420807611108461164889145870368848775016800251186657074179977099160163550518984762260042887\ 609526367904339069246014677160442152350852856796092327576207334456459293513900086057711602\ 561347813818574603599472588038639012282330059576904032633735133953280934508892281502600860\ 229862131002115408498417938208784776614578451591750103148464697447572476861283707386221202\ 603909900897089264054060199552054752291214332546697940488919568451724127217621421420845102\ 356233578592141456565700246730386492288071008754656762006009007329378194049268147773606863\ 258387539539064263134806899481224009378544903883454861150988875568477665582083252452308788\ 833546551591473441894955111772939643569652319349313157991259432634539326119547082757948962\ 775892992837603973349617164295745322764342086135715570961883793392925689007387796152941295\ 432265149815966623798777628312464956240455268099824925584879630078628469974900734949410774\ 336871837391836112151522941773680110965561490576707550754390661973195239156498337100763445\ 286859818988332314619966060843870503662242319006842916039780988850243739504331159131000546\ 811960036529188560674732472022520197003398047290180608553081595345518026025906646381325706\ 326791392541881930302445181537640936424758161873696536163789755487011712382340766197510895\ 254722596950753098572161799361261932438878445226616639621778736957120056365263820325648859\ 370872993818108818309776221279227966259765679861760757363232181118810231919829746681417020\ 315669960804259123974454277214083893996739023578209473820994234452353870483469432185371963\ 885012025935738870429419499211919327792588569642928402617617427620460693508406430479129132\ 106595517004852196676918840774185222598359879439930811127173482659886372549193030765261515\ 676472568182787899363857207144896351438911627602215270072417457473112896280508843333677296\ 714252523405352142691739893765616318447733411067731879226511656839611367947869122535369359\ 793901353815062581799432643955863175839344268544118463434583260393372664240845940633821910\ 066980284808805430274724011966553069689877496625231934990712513982515464942953801745975271\ 276891686437177410275958037893709120720948628116620044922474190975356430869903177662717034\ 090321858797330630951296639746516301614418881707168695120064299669944883292984036975554245\ 181143796029419109626750862492866113152291511447787407729716296738717129074765485380736103\ 858918674960662109851833748685139785343314124276248707355935194899760496940670983607319059\ 928397655138469897213091513119343029056496922477643069123081954778154004596086675503166344\ 461292561211593161378564280015825191149387011464644991110126260688460777118892191187129776\ 055873415039585889255864709394474515535630844768443406927936742309168300362819502230788342\ 664575797100114176933230234025766207391727933509738897076775660602810565434591906857056972\ 946465687652222471350696269053735088383284345847358219799428381343610096430035374038365551\ 400535331845775502238953745161041565491443302090491162262678046015541266809622780216414237\ 288231262740746260757185008098050706938808358141011032508978277429648021640783534937065618\ 771904176199645260350942468041004902798155285293164378582031779315295695228761727648611460\ 025464380670255245373415551194786362938237470615318607946639031047923837814426470925702692\ 674689200851472865811417322993294864615593803357690505947198740075923802158981214027255978\ 669291969574409656405164981697032483740377816864489771377719132206882915444641199168159392\ 336358069692922805656500075089909599195858869228042414966685803930179036613126605406902255\ 002158583678820208983436383558592165188401267670268446103187229472385950598833849537318663\ 538663450368135724192467172894429666615066746184623923538478136581153536955448776424262070\ 673474746413862815178563692867520086902567919958365836601672696316779281371827544824455367\ 065558130090967135223347998103398492498151386657535029281007295873629327366387897277851725\ 213700651431714307252894971393586315861313246213941227713914460433228477355667587893827216\ 820878830583441757729556009536021276467253565200183930886317339759890638303706426520100985\ 278945028441901357482600338331886519537663646611955086520491311839889060328604783205824086\ 245206621338669328975285401062126574672754288985299321299539081642303391741255871788518657\ 980401514608830508629260152684831273870497061640010492479243737011642499497347574057542087\ 742797107502068544775340766642694764181945383403598265759421361831462323454672096906514483\ 329209312674015064165194973441475998425773543391258409755652171121029257886154401301802997\ 006883388108755307485581166455497587091892681482676248500999083981280563797834765461933403\ 151907194562468098621511757749883920988296596636571096756507642145710376635399779988049487\ 819147927778389096349250470755893476565919579208435912892023825372516182571618463277666903\ 520218673909614883367279769311693685874610803223057242199404275715494253811661601622408944\ 283280551137111891775362449835171355882938424278209982338157642498799717975230250156177526\ 282112036508442616267714780958659026055137471192950787360704382684411165438201039412174827\ 086789449531691962686188372213347422493386094879641356148709873720109790456914996305263281\ 170527101801412682315373971757398564573336883973445747894540215702734902613010545182161780\ 820398650432306479387064236834093552809873998691704831133179206564244369602152734294186137\ 257130680513733350719249378070960664466848998285927763045897717702778310706096778280178543\ 379191393406049107223534550468136073680671435840019825389478094485359546603086881963136822\ 051959914104065111098170049092035898400074889322754788871720158413365477351565764794891528\ 903421232474802909551719640259874469580599122309503864658994327322505122611309900798453963\ 867524092599420188471176351618815906029085683406960540265569050692372543401338413590392775\ 667931935781736736345757414400619178864955561447378022112848249908001507467283235081097667\ 684690018606302002651981845653986672800536639049716226057917899508512561568770687130640878\ 798294428553259583969214288688443190955615558825601276239172886637902528482464477654619747\ 720552411877930064538516724716403737329011118126782378597939930246405984520278068208540844\ 267662269719028631115742059444614934141643368652878541123255813339427239569351536380657366\ 293415719419706633252780491815202434218114688017671076637060903715524887572348608569078922\ 878913327885421713558406785721290106997899056788981152217904688031149042539660017819638460\ 219878124437934404071359454904609849517186309990094429782626938458891344285942204442335092\ 681991516295159648633572588011901755950797119080390871798997000100056864098652477737323603\ 779966475553999532363386226719218469588015822012503831280476941772486218042448111216579351\ 987945958562756506783174447421635283569309323895258645755720814301734633011040505201553456\ 510143629662216857441285142627707917430019735772392985813064679514506920729038942277162370\ 606081935951634552130528385537741466236016590326698925079932239860701919181744046682440936\ 792111121884365650694532358779107006728325186559116109426907971427552389076866463278632033\ 850328088209519477997984456503309480142915392579055953693271498389938190769932574123246172\ 776870649138605357217160711844401066095946011428760992009303609248293469510297497490192127\ 275652736478887004845273814716833712778223360716806799051597137997912038318399732920094392\ 926815819613679325793400111530235933680530448072206981085223173065879842857368938922308096\ 431174739786409215412520953580484422941453967255871319595335732867311092733319819476821311\ 808017497213887538296122904403469844473320288292264292591347104660390230736716435861879755\ 693120331059064348274443863246130969420789093792567240038182555669969374947773991584655446\ 181560451999463938265187620183249761548311984773282827945825583746804383164803640771567872\ 647960230909731485950825279142123246507654835540451598708378355860518705649658674267099175\ 372485029322665572728706208246880841408808333402128123017120121316200331345386126073097837\ 026209846135148431863604208434109311326695113281113954421301638942768605768869320865510627\ 373229151636257367378194064687839360104550419327935117353074606269149060819423786773540534\ 241625560787012168675251113746164402030330355941136032658094210316472491187725655296137051\ 878552844072269739270846255967276306240116398299180794679959069586582684937384083260796099\ 598718751037838635833766337451905979033678892259198802999187169938559678041912437623511784\ 186187588552300881347666934019579668196817403655121532520979884701127916058445377119261302\ 382495687540837489854126545678454487462113002817541158600834750918048840029670520213078601\ 590950234650747939074758354225769799125558855795394185076919422331444299308122170581997473\ 451979906448509165348678386581212488801237641951122708880409408520527482744122048127984886\ 147508584551082521462388317094971685236625727506796968006488338940502645613667120225748474\ 925381734315145132933823942475882350474022223841773921062597397599959147812820629664973316\ 127612714429285183151659101578904052320465338662289551498987550887777000946708897359959452\ 865027856563421096002711991631032829764441640553340146701871056047009876771435845257943853\ 055716143030909226523366326074715190907559097327189806739742784198712428048694134607945077\ 831470633018941771266098103132017692263289698580950805977669499660166863822419155406940359\ 819771935938788849763554252984089992858738303390032099886675414163496309520208674721707670\ 896474082760684170800496605663871346768216667853517619349328927082924644531745397550797764\ 860422749879283352711129723850586678123506654165365192288246417111663874175828836035491286\ 669145621230476458649482908896604208970369861820798034442892002234198480212274873739725039\ 206135116681371512380492991497871588642014022582902719601283731812007185441227894775442871\ 234643650063511582770585111484263398730114707343686821695421516596916899960064725074805571\ 873937357829101380964978427694894971794245941463313096587124940467221581612481864301773393\ 301318561854433111829820756808003402515943154040260525261066342101361599665644649218619915\ 213518153701436861653011940347312469693273015483618506481696580783275677514584529378380365\ 953562686966166658078625404951577010110284645790068401651331271004435750522638568217774088\ 889644047390925159616106583508494910922644267494180975038577468115959485005200892732266444\ 816367103239292670008575197672772982090797246898872909161424793174775644090683591704305844\ 100048598599553869736245347684394894797524892162603450945024735951197071033610168303757907\ 341014338607720184129201525602890024264465625124297477342165127838479383845195473884161211\ 611688099544094975159311976009856960096117269950219170873900670020208495723176551564308561\ 820223586624190922624906104334853748140969913817060530264446616895763727138957509685830074\ 843413423767732092986526615771863442237777219812523011614383889077092189901006635873208719\ 922066553645997398575739002296886606517202811916245948330816384554965448138907398013080847\ 112892857463538216015832494218779318114414595530818029252127014869947058922852500662746072\ 397263586884748445665873463177326597187572793033185928650313148185709319480353293058568866\ 793564547922284904452118235674361044404333090903578117855838512283103693076221715207422180\ 398526049207919707707807110567925667603705194867270242093175963801658781239826716711231123\ 136461859769568886130896454869797472642337234934740135201017850594829854901851851924870423\ 104698485960717323181058740024681269050206600642325124160608799253460497754289168422555754\ 575403067503400531888584177944707920200664073736544932905162493281792864990422586909413520\ 894274611926299502215825902212397522450982169603386188025469603239243743106187780346541141\ 170851428331075081483358839289006704517681359158825073690579737183832223643503835949078697\ 069178510954159534310607500776562922438260099559171439862697895303397811546214855329615411\ 101432879692972826613594365787918674975202444196490774798036452061667504277048744542428053\ 588377780885871952827658565556265008045207428891707890344382985215693071260031317745356827\ 349753756773649095394221686657326046088074577421506630307117484439466669356705200900372057\ 099934802028920366291275566737247603620431701137706461620735559365627051678264704688961995\ 338941916167578929607733045835720703815303696667655338579129235467413693421399657418814032\ 474963919215056351063242502435532926046611975593868647456900169811587988239772248518812094\ 020026398398192899311809598867001800958675363511831931442740247331474406832526214802884309\ 427549741146648383898477788018122534309571063106823339879071310423816585129634551609162836\ 446740721613298798362019280534884186182223512248285272800723495004099228593680196692849458\ 509138834946844185526188997026958578849961862119989784985378063927521625593806777420339363\ 960544182354965388506398381248875137396898550847553259309959014531415401304973572715347555\ 838647724733285249331516101920564912404019464667161164682913167497312949087115219648422670\ 769533931086700190083171784358492731515796526842614816274013859523470237801122446840256487\ 312199280406869363282295581607449044711323618199930444796755021147560598841717449581032745\ 630645567124549827485228772729156299697740419146038238812490152889126719797918198178741556\ 194168247474794622081887046891451934692168292790011031223295760213939737596633741644197249\ 941360621872997980244812470037974149675137662017463403644846140129447654957379918568876013\ 097262455934668632855283900450178951930924801963357396410331892464527951029666805949602854\ 417116141729192289659744024120725915937710668565221989608074963639829168573025253958414328\ 755590675732087563933811834531796725921066474791676760254759496575323936261984896520148207\ 686358631210953507615008232867100558574211443007189542483852113208292296578812235140763632\ 265694819834772278056825404073178563982747184447383725498164160514961362653090869194531008\ 142069061816095585236953888593533920569659264607596903412786841294411157818460023722975678\ 050034516818353711244154952718462513201282067964255358242674298995978493000333833947375719\ 830944083662528218512383608366150619700642114469134348523830311194088142753262297023528509\ 572193563530612536877412118522547732739263958460549069867815692621487290445644956138621063\ 852065373262006190285970629614540866791538822028579730504110653893889513226460027154161904\ 687882100883731173136611077723250015285347847879937333598274642757346545127770015258740804\ 897109780902220973295842591492235284777574773067515508323994560936375177494513882110393384\ 372339973171374745624207040413337416938094584033869484663983941368232305649351539825261849\ 680841109525989067690565432666254520464519749210317225296208097305878315388121732090974025\ 410462446683326456646041939152989671929525357297790331045751354036667544139098453835383398\ 160936168958456313222933191558794330943564631934932094480452128264314633274940461123588508\ 738670222149198697288540527444746526495524597081669570454433472750597763119122130982292813\ 473427163567656953069769843956461225577969997316944595897614105104557616135482599931670440\ 362170658450122969197810733427928481381178601245469455393122322323998511767395909511159642\ 059381975909244067306309019605572881778847444629785612428606278895278892366525934977226189\ 865966339758934266243461057693030563725992125711075647263027596217735556451995662542185212\ 041857008351134364738750998912895326060881523288524106593060603965069473884048043330819926\ 174556474796267714773448587754030984825894131129185609549288091484935017127782563633481182\ 424467666185651664536335217625858513308110018615642491345657183448684371556153471340587462\ 966319172422795764408334807360337444184458825049826426872631152604949581856435980204629712\ 199499434662588829627712849969923949287542656597934989015086340490064126015419440183525423\ 586287608657524098923117707886226609523333327960853549331092429077458534632309240321459468\ 793115965528272722786020226905010570572400272117311644867882949885282220621684025714578243\ 030612999332117195845085398858221494619057941777129855255407348639885448580784404949664397\ 429661590787586413458997215709493701933178295095437408505139782774668497859560923113208981\ 743983407519964060724211253904926909801834013231536733348307234677164697757543330391047943\ 903064021101241362736160036341551490624892592605739663328164747835182505529206766985601292\ 004858800822630634807604841941579621684797042992443712336905150832742887070777763809699220\ 262915466253173122264146926765524209778395789690567690230085466577943866970970420385744688\ 323971024422970089771109314915006713151756339079044571900228144242636760531240052367292641\ 731563538099553082436169551737485312933005366459701305241404807328799739544792075011983818\ 810608804240457591234933004949835451960824908495111627326170545693457672160922684756810085\ 448430619227791650955567650710250435868247217961846982166425683621489844955192752190030302\ 778730490560551787378163545694580493063317868354407855295937736882617076251720976872868752\ 191385701598981082434259839549586589533692175949446257088497696631357171647677524231782254\ 676670066642597789184415140815985051157906471609745766766522673794908628596431049606497826\ 361415173430964496952895128881487041280136267382135451259696949237343852006993487980348166\ 865558326844337598837189537383775357964292953322958461810090078003922443552187608702910155\ 880114128385653870753117999842405065144485006883468308285804213078336025030145941797974589\ 835061496244578877498564532008761364759118931827268178041717255341873047550652709228971748\ 043812770174208342971442572127171205014851149788024935489294998518091893316894537660153057\ 821092424128048919292166749589129110699281150528189365527351286497239204441591428656274705\ 357913402617119872749229349594044780055027997877812068505428570227226937336797668414861427\ 488378163211753940058941620351355901373029821260990259954493891024013213999606949147075818\ 389674239887678654957636321933731406424582583265803308050736573660017819910858239718261983\ 213146038280279210476577719003189303267021758821353608658759270743081970061090628992692652\ 493275175933994025583013448233529521177953247128279061050863879744746407089199213669284804\ 122473919209608646667016485253952107093274367521027614593042778796392069834773008378000178\ 252473647255980826095031285496264743495967519345731757935340754394482870549622571795560937\ 534577148741215121942450171144092736260214572278501119170626439919602583539478632457123953\ 627860252940614313365244326362800684891233336494344101965430602349117446118148332798488196\ 510533962754886078315089216230117888298925103103772007094331795778534585840366815168327005\ 687124896633127140896959787279895061154285170464807284231725803933994355761987140359303077\ 573028344604046984975343953075636303986282207425767088277084890911575999452746804469123666\ 746126784751775663445305658091178529213226897296502215799361192478194036564888641174919371\ 165817580181420797996740863622970242734188942995365594703617340764959715314478591897575435\ 603368658363590139560493130407956415603128152060916843608083096104960513357975827764045164\ 058273113962536768019298188406938320408699793695463118442023803103461161434627863037712903\ 954566536441157881423593362266799006107739624661053099597864544681645628768351485523540555\ 015092592269745182065869670162733906220399455096303718351689728685876278766606554489282202\ 705279464643729227920093299810689160121803260993413348487800475050049696611969172621073694\ 659457873936493316690096742986778354273628509796021661463589579337492979334718539857515236\ 070612467316326436810790824369319776523135994231605250021442809723626391656578072409266339\ 787498479152683728603396581062278585022135991617908706690970401595714531337600335881022231\ 503670837767149415208542560911238877188365476015527527438662589174260301835144236636625959\ 325105968312328292023166543547147466452416524014037652482725258955709911830889050651323501\ 172013143193194795566383325044026549932739429606758402867616267968802605108730043722651029\ 359387860608688809812458841931168503470143968340157886231924896244472797683354296982571402\ 685207514402350278448004843502335591060939401767155739985654307380883063334462049690615894\ 852114008793206461268697169982089767632619211805781392783427077719840756014750378300839173\ 367933984993483361962422415542045037227388377815900098004654899668168298009578269125669577\ 592653961049459055278153017462550709577571083774869032880033588619678476105353526847424853\ 396957262303459591649188095065887954521418668108618064171553959381793544626601993533638338\ 305108986871472602608803820356417501358072696989570858010158406715546196969486067144965051\ 029086483122185812016245962497290491780697070691312822801324203124322470109346578100311688\ 261334150061903521491355160487342316451350852525193685178284794143016146875256977425595950\ 439992974542211918830775191450451379881307597595436387782897701966996028797276286877139873\ 500992211672331402071265765934719578423085967575249070127538732461788226607585565614692679\ 148513727416766282392269806098714742285932603275805463356484358260465211397732149191861254\ 471976889365978493443502972591324728405696836326488914390197017645244356020673496604632051\ 330585509461741888327863670910872033500157591760904416756199558034453111262534439295453222\ 711171934523057756555944470594592820620059929958762055950676753541215039732010402966069172\ 878019159492244679967459043966073877235070932703486131153304602652028576916369169223090331\ 147728862712207794535311038273650490179795637894424255503588470623759143310310957684701822\ 646331262368247399913371171961759719532346100081944225359059980584967538406427689502798576\ 684201468845804772860668944539777905816704242491506323913691438988238717498840109637940027\ 549715170038313293507132418773882566114471042294851297104491472536941514513454162573924043\ 148037192779427214788822332655329336324617565761511846125493008842605337966637588199492804\ 154675050745285205718602733363577787420118163691912528210721563607691199375805612503223434\ 402905178386964507886448947869679760151923781011525105997513514250132286649806498491927726\ 714468887289462343806443761430838653666729932963413594414016136974417528988432881550892082\ 558088990727087543368411399238240589245436121160779532949516685847923079529035248664548659\ 538153631931451669734950339294279191692292424977111455520987667567560456829156465196992933\ 539546522508489554465616715201633261824850526018531850964084767533211600606155034891067062\ 499419027736705393349360755738828453517660651272520889264293087973107781447740472255144640\ 372189983480972371057260226092424689278989029078857524726755149401445434465012332730426471\ 717047708055451664454842791370662602151030271861543553794000712302423052829357277391013635\ 194723307425953807165117212195762228647886765435793509174764013889080873943058997856620352\ 822307300917635846452593675992752927208177768489605001109642859204928563934212770768942554\ 811834447085803222523050355205600724868854701396202242652796774776277073374504563289850608\ 830565260374898160769491555279813987618366184531777016083566628924730031571308601605641645\ 236619268581526672298075223771072892344716731212688194444134139324815405877967007918483526\ 043982235475224712151356809660171796993096102878647945813040863171515562010152966109634168\ 885508986883779453441843342920418871861056815518503664724278834845440021077689584932245929\ 024607732280345254647583135617342292907805802952041310619712406544670760382128153680225914\ 278673857746663060902782397598494857269646751077136495475261413665174551628433295594157066\ 414547602700554218547505310914877055116360686061714276547014866570837125104471664995609660\ 182048749790989169909588557362854380538889978091157550677531864884219973393528055604180281\ 090322931593870124840803038189260912789253744809340364951159543996923355048910890419878212\ 518077517276776022736162236943217049201883147474629276121877929906322315462101934866673916\ 810811481692033991207810886748113326018499083303636283703314599281137721517454691160581443\ 788879099193831422155516383327637260852537289205905007668556394430970406874534208151060389\ 286448115005583316303476154417323820358921161639539101302641040971341248957955710576950814\ 976037772216268764110896879831694569557305794330372692230038239880805909889895742193975124\ 496625908181232696128459928817787696194235706874417753641249616636816622525916685727638165\ 013658243166939442759543761517863889383447853229274292794282626020199085846325119660460786\ 108814120037391435615332504582841077375692383822329012408842994299556055443358077085764861\ 462394900903076654348301248968128606909768390865852658759631487333204170819847917848096300\ 356819107537163713753655073451835002983179487695129262438158892623937347507751405202078818\ 485663526931819489738670235288132710336673203765905594752868501313132368762367923836453312\ 011744077988613281995706241894545168808583416683487071195173636456197093411032333891044113\ 888653940511803805163666655079463582106641857188382883975379757806738350901596312440784398\ 395047545425518638471748444559474170074843888999750669949690091314766706159669951753609249\ 272933069504033246116129934843556404836660996586619656036585438009999775776896409871338145\ 811736842220030153547990154277919530527059312451339753928566631159382851779751455949490721\ 520427868112093453127578008085805813035160233628619910447083395808387454239408861312315962\ 354670344460889358139559385426808422327551018156634282249557360917197430499879694581890396\ 456907800998956535741198414945308095005710323494352588741143414024873388658254623015207199\ 724134987767625720939265461283238000345907697064666924263018179171287108843633967121731742\ 280937352303381044147921184473670785114833766060050023586470228933936024178429097628412886\ 837609505148199088218427368208741891303971425183689209958500604579830978751735650059360903\ 887684695947901853092159857932937648830126870508255329363959585871286349426650114920139441\ 119148617335022683433195029238211321948796263153589183479342594246154210838662393526023863\ 368583045308267410141951632644678017986464840984023422885884951729582630642486573016367589\ 302543164851068254903477435754771393468709949702897146101201120498758869216033766010460308\ 447050412134415492443296522485649104022166728993070915387965360227707334705276505509348253\ 399299827580999140093104677934743786075996598872496611472571355623335444103960650495749583\ 469184599618440443608947725581626057271573040251779354006380604179226460648767743336830399\ 030308556276690297432730800222428047507583851678503534309047050724394369481579049893871525\ 921673150869534824186758190404096590345091087435402179954910916462897678480704214407341811\ 197721736564904422094788508215570526338354643416730837173598647148304817505076435054553127\ 938814558963231516740213263884957858449256250731343089659028986062995722179371729008327748\ 223828634341604417478815224337016521246953324705330795411170414743445725444078081505147877\ 226673528250054569962527799898781771104753328907821489939683924069209200099451033202928105\ 941911695349702891890037890727763312366585201769727765688836495648811804663219970166801416\ 339814356026318247245523681419020379648425879884207413225288366792005313529186519955748990\ 774286017876953309959593182086801990620818082289042853582166720330696168824797838924612665\ 433695060737419307289777029480918675100384565983756404995617757417333089434470677463715104\ 567014385876210809107648779723870717978528331202189871798425005907521798376573560028194160\ 838820830025402156502418188480124090154530358840195880703625452475876568144991352664766643\ 367550100504104656999317746511767098500169413998425519771685930809301528464599878798597144\ 417496985947487966239904495222524826018356972846207036778450083095898204219561527425290081\ 100392168684954871789898330174837335448469481305993720976227224822480060203607345870160221\ 319516198904031432407589029322846757602308232887228800510129190877071112704092890569214356\ 520590212390444011647866930315697634309394751212460674264573704071758880126224065367233236\ 831302888049346078762159224760380378831004367955411996061710659950872049512829214509534935\ 804410516259937362581084601214866855893696723638219903514209097772347516766444061742941994\ 798318495387687984710968027808301734611520628135344301586357217192887053721753301218833664\ 083322284741516803815600812503420669668186176239684986775061599681640207626479673354553351\ 309386933794512333552525735552617039284409366066630705562341033752624873871716696286440179\ 633729402449831735366502142841104789697124585941126884512154685895682146211213018640428627\ 751559219414357158285051465222654824444821125872856106780640147622072673739139880389234076\ 124918568453356285106449326659724916733233545111375520521452240828229296938688802229981527\ 601440606225717359232340598383637661289643660065476822429535832138591060774806255229038116\ 264608741957816762235337308478990045543978772150473889120994897168448327407311688614320718\ 215888843055818091915454955841942328260938570352479081533474152748998291733515385880226451\ 883219241977272533626184311133177735846656198462660501953498881845874059153310409821287413\ 998545592588354322322677576471866648865824692602042163932292944199292452925094397535219230\ 205486272540331689882451358883643588600650513622347125731994425885793555893035509343400419\ 642742147637478981502636200063754174837493116848814115718040460275261780390927555252049067\ 923147942866562057222129842375538000649438238962616527887474198310396283978516062818815412\ 881606149098240570959492930005671131214850852335172806158430332790663568452597724405141806\ 435982886558113546799528419013621214683412472940839948561706059039409307375041862182760558\ 100596809756798770534048122270065914239135464399244860082080863522843443249934872395976370\ 796330962877376458021316441310725016747994190346444959682586124165194651657869640616396624\ 096078101531864349581758158418563969669438189558137779073275638377195218521963709480623634\ 063213587403917849798102305505881642349775154737749718522444233216281217211831557672017251\ 192810751192151346443700939623854646840601746321981767816603822095691113509783908959135000\ 773440289527029695453654011948844417497096698782521226319081591007112366382636311571354246\ 138488837606586471976365401488057928668374549408845813174878770411583266460024851259214853\ 117164880094834521135752105569851245264648974362802291001508731945738874609347630380352448\ 396947950366287397753757245345984797351535570552876412479886673535621745553251779112495209\ 779274661613463787721083976636007062881690330605103730785399197915324203398500367835587633\ 595728132659662544429085184839627655733762583304523980409654984660954742576083490752135304\ 635436703286399615224265095380154399027232164465994726824080617830847871222856057337083970\ 265911543297055516850735870996216167609177220281089722371923283082606193940847699222758415\ 553427392679912784501817536601570475032053236533651436811906768739894040126585781488113401\ 890967176657062710978087326390296155600529647567292772469593181828874178305242484401456309\ 312229085900446941432849399350813296493558102034476639262437288107085988320324250909214063\ 410904238477836040459006049068782144036984973038917316414843977567546818054722080284587879\ 812109349480632728176148720630271595880541248652887395099097678781264498477922929162239307\ 386715064637983519845455368536007070099626510223812169288965038001260588195642574811711278\ 044138327082935546692500386145802400405987194103700579701806017640671715820914024487109129\ 789492000054564056942766294560354168485967964447510794375836170340664440999221598099751799\ 652475699868045099549471033049948151932778738503878936044122155267246070147312367531005835\ 766488975439067836193805818003159648304144159533085657396146070324827303931725956472221073\ 702053872385595224633269198318721462237829505519888724525190350280301969635014258868895693\ 102776340812794910329711268650047374629774560144718292778052475086039610781425818745976919\ 171321640454435815252205967069116540588460624022846556771463354109856108278756436122349211\ 003154025917934852718435387559260631681034603616158652496594515361531488910398040334273009\ 632377275226609565755185528494397437324937217908723826648015960269589542365679028745717954\ 251324667485247103329031431465345106538264438618856815850799877761395668583051206579345008\ 914021828806986137488338004803518533600366255020878454161522706511893110908977864432833739\ 879740445461786879720037599838135659594638041023784937831594000304272060659387665856365827\ 702438935937555960477510278295513162794095450989514355243230521661489476143953542924449652\ 760598496299651344228596539268492188580424482340653035359231581027604547756521096153907812\ 932733432649964089397611351077079062591509001517254013671828813718416110310733580906085760\ 951564067899646203218368291961881374304689853788016189258437546571171111668203192695950359\ 870235689461082945216171364384250554435966188749791148454770603909116175261538689430550141\ 897333282441529186332275845281378468828895235329155143045374789091344965851943850856879448\ 984119525027305802796470522799193754284463354150747661306908900868714357191560932290361823\ 176349573722208503797056308973747493878446681067718447516642549562811808761669745508429654\ 069275204530255898287506112115238257086450106721380163639887273778279017339732863080691516\ 163207455314172979350091044911103562458574954103374618497326732721829089341351937576803920\ 593238077177464904844014649921266460071375341999590273810018548499659174325703645950415749\ 282017512099197928427786962519532874824841133364534758903211023759918931694115055890802388\ 875058218479164578964456877967376876590309595800426523174844486613224552878503456401561714\ 271381192924165793442216113041549341602093450489035015280623381385799123212806729643963798\ 684440539084972849253253234797331940561132028067785948775713368766366062674675489794637050\ 363151637971588364837178614725471776571594177909530917043799807133334663373644221974177835\ 067197986066349776386031092587836320302669605686443159833614542518891330677923122653617842\ 399876827879530823884297462619016321037462101022157301893533678875163541207016856262402562\ 810886294737689925979004135596919368038622270340807038306280673272048756228409957736069441\ 260265147401045809513062320090982978978062094687788485304028342894584904059452767549477427\ 973155205883563413111928133131286886741837589372488034951118123592801825953220661606387451\ 861681883180322239123344351150305365172133441111041461643264034829377283728221473476217090\ 577355222808234343725665853059459481531105426766339329275036950803507941507607068885488745\ 368568388987432850145792905563116948005807705770173361497346924071599873966275262796509303\ 833133209541369209593707970637591817887452995875976814330417536647557351927425456466525927\ 493262663249097844137696374078785414754435994261793384601723635758231910288735940775323731\ 727370396556677766204185143643244741025332304066843196926059794145215479039568808971677535\ 448529335685573654409439024737596181756641955394123196023465047028327962811418469515601881\ 550896447376933661420102209743419712722286634454573195654839480135403757437832172162774934\ 099753965746603567791436363186221798782132802497477944705698360948988037835720909850851773\ 530118355961904729552026270725992160284010457488971493727393771647737751572227468442670703\ 488735572094227676492363375112363930620250817980479257162904502218515184437365925333676572\ 571115306275210167713887710943517057149518256476543239356233930865368653169530022063230405\ 131834927655529724201678685444289714669918709721252680152754612157167052780183988302183910\ 917397004480275778330610867050837704471627606501591951019374927543699737135159065504501771\ 734682673176167445827560026788737764443344046680126524069682832039054325840089065146852654\ 369208030872967566023734095215002014048862337478045995816646816205713112086364825369150617\ 974762655866491205387779843855772393304357178039460136935657549049872897946486314012612725\ 343723040816325763417192182889507424415044658289369176781890317342310756217953749342986103\ 522789425380502911100994575954948825192738022403009303035931399047799555221365331085737500\ 715325887963828520258785082609288336908012719913709346034429837016818920194271331489639993\ 154379922267924434957970117668563504554434926159547361705481390228331638432535891011057751\ 157146228246901674987019128888532315632348556883191440516048950243946541594661180312445578\ 525728584878250913346407134526193481918083807162768143539727456850343896398279313823262691\ 593252372318400927769858812481793601599588245300093193242288016807120062817937987813241779\ 118916389935189395423294030059972572503224591507083743179456718757361232466105266611526373\ 931878152719652158360594732444811320328467361015728718747661888102548659041443121582300710\ 450242806407007030788460760892662603094040767261731339067153304709370530390142583712466020\ 994047177346291787398913101964868037613775414361721781816513799085173751310922192349889115\ 020112806665179284627318623852901386140536266088892800581469662654017864011754345595419786\ 795573875715828238021203539751443197811795478610667962062428967809194529981077076577682015\ 781540927782325092701611695386939015864053806983498499084719328570953737739408003647306963\ 040072538908753949491657875252921903788892937909047178864528696184200552780145714456872803\ 269263784844486861880629238217340845149968645174604415516695071056135682345902472632498062\ 682106164994747809217433496246293033915040575771791756900073283004407632879461204541599611\ 419673105266850863014426818517256401602738910464438636564378292083306879945448761137439276\ 375907579391943800443326047564376980730119835574816396216532562670280025138781324262533175\ 116873311024007112151836411656040276931702353520365742112544828063930054558608447648677739\ 414245415156272687098396989681147615076063686504052186029559273766663167593079495321684953\ 194453229609119793819625338902403798569452327166187161254015115883098166678278412803987893\ 840843194745384677490806064449744558944634700570756126775985644546395590848876343715059194\ 402187126012425441460688986024242298300313497762930922173509593802305479953544921710941555\ 947184482409935051987628911126123973053867591934518020975420864953799799531508214012897405\ 216214000062429268294213182651310436381986675039299069021409871791311458380181816383500039\ 046424219742112173490006578134174273521964245314430114787168157882202069218876201330410642\ 140360655923828430606592830486942105073817044147272527621703558942041051428494652503931210\ 669390409184638609420072921399699026097744179449769829230283435792692810785935470652673635\ 256791723662390644990631704572759064611078833748384456075211277608538192556044041327753148\ 138639089892045656444936555988475562589065877286760984558547751976600325972129678575227225\ 619685799920528350030051970348487136864847191035440635728456432603615008132600506394057133\ 347058832971653764198268857925162950816448503492411487470076612928218406251820348991550612\ 940801800895674341756917604699374767359698534057372195223429721919232420234242877352136900\ 639006816351482858740449976868443079528909008477582130610036320235546788113777273650552445\ 202943894982941552686445756482978479365405361717704484939828203688102960925073585596916779\ 200990858847661941434918337723251192147125531272401841411755944094971056482744695721992542\ 229821369305080298147493567756959755644000002717938319966578319722333029522361298481868505\ 745685587048313714600332457985932335326661117477408799649350100292159909465328950650100777\ 794701920168160041918064495704546924598425978458982463001390216551227492158341712951185197\ 022400948626033593059570224022300324239045849245422803309086630270955200195554499237056468\ 519498149019026900697448497498180290886871558399432063973627229371876379166555264322111736\ 730860872775700652199984879330972515341655852894025803682855719912685355401781090787843237\ 372793441993586872176536524092641299822891826409054304053448080653350337688989011695763954\ 978682287905440865124017382857922518949568590973446452418607539992894697787738730292996438\ 360891296615859179318813487450813801704106222182696978117226262772579473611978806436936387\ 729323129003612702560685747031820501607363267983580334725536397620184040066535245481965878\ 264213944931818618141383250883112767184783434793752383419455501047704319037236322573535491\ 860520345433647915862191356422931755917625639299951797014068648004213171058087285800084726\ 309038395765953087147936895272154611386976886488210423281260392346219329728397638625223844\ 179889904196692345857717255130057224702866687538722399620449874818129559471201328352676471\ 175711204330578605866469803680052605358450553065410515507917361228783273508565515911256306\ 138761878649247420300802879186183893223588744866121392905246316922887271538688579146877100\ 479678157576565003576000332573350981599170852539644324196018548994311316629833150584121268\ 888751615077446178199662593235940453562410211435827189223671128109880010684373765425487846\ 008408669788036744426313844777266464696289511549446371232669189800160864266408820751038188\ 739637459342773372461314485507296836840439497982395356998429550677139406691261223866169086\ 887602933722405597235287965254563142018212643898348721872081557316807412503629666165153145\ 943837304471633443785325736192673052957930025318987402191366405425579152041996215945766605\ 825847658649629423534033474414985522142274007340198625834814349142230855554434530814001376\ 649665188703530675498052952958827093079531068792394880781726265970296180123850083601437173\ 160828860344261740331914428555821832381155920270838450789611999893054586599176134832242660\ 910274446922478189393520535648463500947067109720577399010684666004078418790520413046678769\ 116669858075822877576721334963736208553717448270789290025799034629698620091041169373807350\ 972302507302970746814118960521590522077460411551473464736701225454111898228347351613343760\ 338947587983148987451359652272528287146593338376909906143470662112527289781258986755766222\ 384258207054104526963433485857079484987240759019353725664476320817915900008353636231201914\ 025680289469000489598955631297181064034030517737167646283031374938775671141139995109997756\ 561063869575681307108296767951569585272210647166476004356617428713288777638543838980667707\ 317693431159583213719533228532303403144118481720659905333549487484127225393552733259446052\ 835579743980902278915432548863055431621101056680906592996714989071051104563798765385898764\ 590147381051992001797428328216505077035930818902412345479475304612240047586994685061073310\ 497535792298492906081336180047170420596839385809732846252711823348000342070733339727417738\ 476014798873056778903740243036427255142841442231804348994531243383298887010914083756317992\ 412534424826664149684363456627554510767011071997017399368306248339538989050236195349436214\ 196554357141604384555483656416665423088521475180151210474736625538871183116930214210693569\ 778691453709954494465514969808363683156213775655815038067162705669437897333827712222930919\ 676078469238348663312684252847375562125580663661103166484406800762235868176013484956174181\ 120758036651239295119882287348268866193490812958441363941472832072056464413623599604287844\ 512356159553632061450069362048306914394704109664333398709668476593635796311101372798669783\ 672904581823789502675783005335162812802802772811882012715737204085647914565009012159716689\ 863532747246607654324221352069664612619413482896283955921218909296428209428117475464728746\ 609989358909560917448831183856289144939467445707217533951055842532347038109318529756994655\ 940344975210086221874118412332296854413466462184592534249188378213829009501177613372825379\ 357927657073141087020073937679685945328818391578972437757537575758882517555854721915810256\ 961703028180219669261225920957879471853129832119639820318147154051816955080493120442964237\ 970104813420169168992362485130717390469865425916555301918385629799004668418578510979583741\ 202165645189987929649820132160949568446266303427866244389058490344394227247108839611546870\ 202860717688348606182901406849071981517064624816795297507499949877585707416575106311338991\ 765373552997777837663466055293965965519333033992565011327683916969128753115666662245882391\ 642975166451186196617471070906053329246697340314097031893258409828662120358629517897032481\ 480712481925131239155131215251868109642851263281750420346528154324625814135582601460741861\ 780787196689426938898949817269854392357530298640320507153198643382981226942285073913191730\ 087851376901303283279421757635097893941260711813281226734709140743525129187725356744834400\ 308957013553754143117778808112573626985705001753169752852247938225055640744899837808268907\ 459071069422593865969665001821196778103714826781322262054525193698149505328780309371438120\ 280516373554981458960093680329524997935297872437997964803444348857175573049077734369900478\ 893014026559037487223493326208397585481055941457777011424936743558852112547446017219801673\ 419618185786878496379071893366320174050504139229452740649443883505696487021743944832585722\ 362306222361274814367762591369510447519662422733126456025738365750197234101465296803609654\ 367898547033293356131770768449001649051082896793012653779557410005020366724061795480987034\ 942196861347384494909310832941985760871194532849466900502644450867177485661573335897195768\ 584749895368188541658187278187363192030995074350645017713722052518032551228609495027449876\ 908375753225703097788607783476816163186066048294367872184735523346048841428941032484945311\ 805805455698311459390892886070548241905704007778972652047110421764893656080730763350965398\ 353428283354153494632046065941660652260188611628196401670446956051337007858933175789668194\ 531252016901551654923048812641774693485089537264834697912856704886205769664959065477354230\ 914385964193862081128824121144483305114356773952400117780491293122506258267978048029335974\ 830312321582304187814492085741337626182749859766854805854357164234095017522892087668087137\ 539406998049852784258919493426217457279818629288398524980574734678693168451025623491699319\ 491723762254927041885235686316320558699438527155682886871555681806709937335619076966531389\ 150835813429675250413984112603471807619453394977248598827090679617872430368692730959410393\ 415183104795318088656958542822224735549637210891261051857900420973322589491351970100135635\ 410567163799951305290220074369325774725148226961611982766132008361102652960465503756313262\ 686631759508539998646865550881069191002920813066067807898399880061333323406250307613981232\ 250485248546783062851336256381083198779870449936203114246303597457907906576522325498922442\ 429537703309126861030170697587247585679376967818640151334853661433379541439094820992109725\ 277329343780364273275942628457233452664946863135325257158782290250896596898879375633317848\ 658353043008456685415254569419137224339938809294047003295280285475040153042017111254844253\ 688955155169428956938095780032913294581737195480236922218344635855388669149195203366003996\ 068304820973172034936144051170561573866793836966364184744383299762766720141949399739221890\ 404720452945462345014146843527725873925430520705732144733913689513938521725838828008914800\ 593077533513762646478184904879833962743431975003725034241824108216056320136608106643705544\ 836599668234332177418025435010560351791067637187965881626807183626467131179545755619011346\ 636276494619556603292915194230947611188885317742160050192803328815924839388171728591005620\ 041862878103713859290282847686065415545723683907348715723674382690756614236844568818645582\ 811325540187772657136447888182363599636938101310668673062071334532944161905468234944530314\ 746290447908050975505256327278587308049400222285585679918818397442168344377039693501686060\ 390304937181130673841118397023933390770413107863221238160457575814434267617239035323364537\ 915193424081046562082800763675268493743362640047606639801197116103923615433164428888660232\ 132762534446699356488131224313376978568637725278532038802004023677555728604347250918925008\ 950851413132455221824730596073603429222745640055662149705603880405322091978449119056969443\ 637173091149747213574801555824973100664931969537375105057700384102852443240941875202514488\ 042171060490708855227212616576167232895624346120862678002761595037506029536582284363110459\ 215082997198370873303708615988512390995129920612987470029732563039338854509618573131410605\ 894895751924202434562703378316794561524994687016340487217035732328932792576492536294213651\ 103254159646894625768049497501247179120188590815575696196636948761717953457604852558577816\ 569365834088543602733071177178558201775020798141558097435760335012498645819213842941503837\ 382401397027816509375254517491287462560872157200422079885174324202033612923426031172542609\ 402781484907578508548171653141343296484091708401374858657048335957972443432061870851436127\ 139179522026506594082672873918170659041623738344007985177121379449374222244599267591843559\ 288290928467521359237950344790975435904872991641606325341984164759552080883232215387609090\ 764909020783244253109412545020280343858856532665862283575263496064707127349248679455008218\ 818542303213428548008305505688174413269691120419603317590717324018407279795576803230527201\ 085491634181583488050700228316220619194118993318005748870021375019552327465022456213616440\ 767622946026370868695306192176268393791428335970361892352665973222250148335784875487945489\ 781074175737897866382581576464131424662844003190381261146838390404240564675813454783664477\ 839078049604244679081858575555856032810490461686536143600742490459367871820545656621596692\ 309350830563756676176403588703992747665405565241561151846488349408520372614380540725374650\ 075062463820744777485967751297221492040168136469662974450828651646074861009699760214628520\ 555649974602967682500526821687684945145399216675182202287074187660874105284594646617057035\ 063400320987706964970142786803801317718643677449299469523796186484412880553217118543734862\ 522744454039134352271146013345055478615174782472400120439948589650438449635035092367806631\ 780125058236696398692859625075964852542667289195505065762040882131417732990394309448390546\ 673840482444783858805451696565460889541100162458479385879830998488340179561962407002174343\ 555374621237751793772920897809665083019787046324042230911038438440656879498772045934889974\ 137186638007545027032203456927631915109085010161509393275481973708315493632468771644718798\ 975066665406623907439625929611165700140122360447300916202777345500061784621555250142658071\ 149577061371417159885364176391176900912942387372694148494227641826947138049493730351907745\ 545551844018775712629102950631161845757377189714118088128082341986474046346613825402951683\ 511892377479763577917452981170790858759080280485234272512765197801927132211575913235321414\ 612685986743093152127968660054382787444813605179435378743877617435020217633129282621969703\ 902517451369583002830847872288305470613811691693566257802799288015104408267625338666957229\ 382976968123498765753619241537052057500344946828789133113262236962865117734198879530930117\ 413795561479947770265040268832933282661915738398765559654672858954111744151588376223608701\ 869515540231789939758237616106925356282368285453081473271807315509263386218373543407185121\ 399261063778973674933684689921557020633346066624132241394727721445167341015290020035546950\ 095821174274659507952317137193622387301719009275915579839859267298950201098227084143715563\ 290438686498364023960549260569112283520816235308556155335993071174686791093008878547467053\ 664902373064894806064249668760103944041487318145518392745085491985861833339144396520539373\ 554431855094841489952971627190797162781024110057281288642623129390899286095555842265166879\ 084253347325523519201046398810520006348173923902978358609842121829019232773446845679089687\ 411815074108290528035839605310737044535104306073852732093073596130551591518790028175414413\ 800963204942860288489620064062143126442468771302826251773446614496922642646248921728544983\ 982799928288685837719598772201273245266475894018562885275472358119771746910767074239417861\ 270847501129120085303512205824108193596803467324618109567027292921889108052810490713013739\ 737303813636626175738352151532036089189821286863269322852200079339887785109480313960989981\ 570974220577938459584936715457555751845609512428446101017962373208714058060193230089689422\ 871995754815981375833599203874328821181996926682765168917803661813655628660340726198852363\ 121364601262782497315722462720508886207002216935528087872676781242289848048037986125773960\ 633986939935248249858495245837867568473553107400425781817602643348650340048705334403698262\ 756687937059903365653229646815072112555345733788344523015082241287340085984639572430945723\ 810093658971598375750899869288892216044995874458306901923969575494671457215517149367039730\ 362841234496313948924762815552102228673240597923921775621549807211481701379206580311113188\ 457602604685181166943433274048181759091408933133568520347712150931740003487846384905697636\ 493168628102779788899303990393923941058486658251505241747815178900558068820879026655002735\ 919751915308534601247932343199762417370756337341733723764680480037685647141514704265980025\ 239138158121903697220295044119087552795403443854595323043207420149383545043292167949406337\ 898255991895289236258596574418761244501240642154277450471255423596178793402167102690731177\ 872734674951594993623085396948095917730386289150338574141696476536939218847167710154937965\ 600695482838017779195881981682528791469106757983698470432830569568747804506103511939570168\ 345225468311659043726835804190347696565864379069620534925368680528383367150410101079080415\ 942108165669716036641215547328096135282028963055886682338860867065525992898704493547829264\ 775269472527511919893273496455381820738895021190467038886711115916895929014408454122028957\ 233747602421018226742287722205392634432667651862843760416270671173465851016195601557232955\ 800509373744431272085390476601021098743755430675635621966250623645432021061056691739778813\ 362715898122392866200901924421097933956713788910593382822559685373876365707333054824389760\ 996861890072268135596665964003487846177663986372668439930032689538907788180187843541442368\ 071433066507595306055357689941871290523068121485230993817520430607009740823684519998653069\ 160591383085302931947120323517923258145682903217615784996749231264609364824521646107842902\ 886592363231965100845926630325327626028465499254957037551362154773993596618117086666695879\ 021470948262637498797784920979367186359882087557086643739995290124346555492471017035308962\ 189547803328256327784586762547922854117648708148696270438368634640842334707027877308966637\ 991644059181222408222211827842303477741722863837266405778741368148802440368165246725857113\ 781517233834289511068943276220397616456877338189808623253198102148778021585300425039117347\ 186707458321236406984104969849265614019696696980939736297911899584726370316939420265135825\ 365141524293084089829049119608849812007504152181003314197227300006373767154509849347046779\ 545765091569316238165043111999913381686080480705724946449817461125584748595281309510612565\ 715211226641536755102006081089213367470924775449685451938001231793791219617938754477763104\ 123823454918472272632250529974292346999988260593903026321946450668938166712234012844498708\ 513548165113257636027183974524755569774744181529560764807037424051484271122444709444535387\ 807499275990049129172897786564149923820653336131036247771297822667202095769899575581756342\ 595823919462061212110301005403757359160197538032893852340212895832998711248830211461851426\ 724518237835068585280015530948756066144440242854196638477714582851492062298312383275981450\ 260104691613458731252655735340583221552093537413512168315437721111905432503480701652034333\ 118389113037214235478835110010834720659350962683398882981853393638916128212434779637232388\ 211599905796182341625923888987988242484048212194380356316450605502046612057622732559248866\ 558596793770515368368699372282245608430303307294724477694513537369854349885372543820311836\ 365233796477758068246459602124772335227322672237777936851843438016394577742381827700090720\ 073646056270034109613892564554829927366698940786566705942370091761483749110716656204287786\ 601037004362601142103018457282870191679009907884363719095665781192811372791468260588973472\ 218017955882269558086372806496479791410519211666361125398922574651866852319152168636632985\ 826336573428612553874270092957886344273644567067223286853232544479673616779251369191200257\ 350425488359940923923488893088216032878939102971212664973163983139941691617731057318101532\ 419534064023873666936850111419758894033236943914389677517562252684305563471578959384314375\ 559704982434345983405977688933390420455763362995087079953083458798154849378263225146616296\ 176027290395831169118112507275826980713183910705765288387077575571470541300685102548356571\ 491822142721345610390383582894367534060819033833643746164018362528911612759262146850138194\ 504686146878314275394147367636949532567048330395200214540799703905252085959399928177569969\ 057444806508371614079817236893247099803857916694028446266015360028843752857891756620664983\ 772329271281224107525969446650127813217063735763930303627036651608573650559624440209283076\ 152282918764711560106198270529206945332936554518231908393858594696441962414372002421219825\ 792073820239252616059646810596333527970050040175264402624244522403402435536082142319379287\ 866128561068352102090205243084762986515890064000463971695483345530523394301233930237699765\ 178400286277210236040413364262542764004307862678103677255035178378290366837409519933109194\ 155409456227529457012290263565976798225449302325867260541338312769362329433013659284452149\ 304335941571062715900158314557306672191729749274419650408429305740516678045268214894121636\ 068529504038913417945904584470425541229548077564988375224726035205859608367148771841019659\ 389682244540392467932528177593999367604917427831776095498822601317575913430330753553922214\ 342070867603897076634245377182444070324901239525879598910708942726225786219967777050558108\ 767186969577939773503425659275998668283010301842187633684113870098549941174647432502308073\ 619846225653890466558053362958063660480311189672734633826101841982458764210262578949643133\ 257881148521077337480454592705177152205114892872152565325163622727944396325060978907936415\ 848920171045031612974784947624619562475446366522853584028030478591323988463273186995734911\ 741062083560950328708921120487034214384362311293523299746109282787660825986709808472885202\ 078987462968530082305947765920853060888008580505740807076817710916663800533086887880852810\ 528074057813929456211095087238643210769350361390915434179610108601018802035874415512864272\ 401451518970246702408974560137582585474724204791531977821627493852420273050251455292477873\ 712013704809711757975085009912168041907965289089534626426228652969692620453929931796658249\ 007214956811375068317159696275054675508865683928365685584963366021594168738878084683400286\ 821031514757616615807966062248660806785980608345258844850130050768546896011676817570115927\ 114274110308723993093144390137443348855523338188811033217680694070906708354335007301758446\ 057014081939254655600105770084278918719349692597833409112788662623757848194453638947704116\ 613329485785108236724202701275879329044986407489883277265498600209418383303857737161477237\ 388115409732832165911244586608719316212850918558407945139326998447906978657863795883753956\ 186743555223746687313911341142889546894344049182885624562295676361571641121730124984058354\ 500794992672145130608635817546287099255770540733366690503434341227281148004189073808145492\ 473722031716450683981257518938539635355222135943390906825836727664947954183040019133823053\ 241701873856124237550317612863393413187411553510686071246845282734094923086379455469059127\ 468454507519305779741960475047368250935154377046933699124722596955540328912074023312885050\ 679976766170324298075040573432281823086135089910186171556706541225120549270818310257705522\ 126901869463603966584980044161734675128812963646129259942994519680513395422485672828146342\ 981400549246491556183623452918730409850914564226152795202381299383953438223917764336205587\ 393222138615369734894926216800966072792160805447429752231570208730823401306809160245190150\ 652951688306242793666152906295236889790595373203411893678812111009226689837286390594762755\ 937767871752638798064977649473957295569538897951421185872665095271448432164530912237494409\ 648509238384728413458749224132229012508025355710209545098284261685654800276690548820699221\ 830118398585408910672453311156719468929932381798222147806898695769042675936834752268033647\ 824461834564355494050611449250009198095851762813584775764869576693190436473480910688444878\ 562019649611754762706399218426776863639595983758470559987115390738032379622832529984940539\ 483983767463838091023166748853449818294083778736934603557439733778775759603098722339579270\ 503384560462010849835756845582353296657224136080870345559095173743965656628905228705339923\ 103963097134376678650121188174921140719441868471948055365743845231318726666532810073529307\ 749368355031834448528332083983987052122993421383671307944362273702629257040156540570742412\ 025039115344379205001148237112096860028473863413464187607983084900497309560152931480882276\ 469582980835766222355771949792224937490670160393550241831422211625215897357444719947611144\ 455468074884184067967488405804793862846610439488722291724750258543663144231885434853957977\ 370828034119170313731385482558783576734324563537638874859656286152418903834111897516467473\ 481420558673221463411298018569439729478126205509968630576192985780293500877873627053142796\ 479637506067513608656176349421747736956423947925245058613042366201925720298872746074410348\ 533129986733587723343123684323199984746091136761717759024949478880585880096810819133567185\ 790994377277617430613243674027376214647309332220168572511275849271125214714345641697668732\ 016019356326508721066288065098439546364207800881539874889401606252398493976336439923106807\ 562351458662295515134676051871759398715724342010549256814478334487818936425361152162464497\ 717595710200852268303628811175242191161573184775186624513056107568967668387715856601303575\ 161516530993709220960212777545280000569772540197442949811552322009667043614377925831638761\ 010332508247613494012072252930928312162780465504156960364029274508613967807293271158151973\ 254123151050872496131546986151105421650789867224861512597528131079655255156962828693727862\ 788348742711254409534509647114596870154417113338325125988995829047919031435750910197325784\ 512015904010151268525125664768101577006806986692924216426085943281541270044352493075977612\ 981257576887109189992702577490907224127201145849030818211676385991687435069571384838554407\ 015983811117522728575378869085501429447207379833044626313380402526164439402381714908980030\ 308263458823179548539432606644445717840389478255658680642662356674268644308036885216881171\ 605084795529476095318386537497800291521968226993773734885305239553210820376761290254103513\ 064877528462482197880474514217504126095053758912504991184758542368255567806580608907596875\ 808620955935904579493655693335525933673695171641789061138631762084570676499202288494989545\ 676744802706205199440267282246407608136845343204664962918921813298204546465431625325291757\ 777875759119194932765070130853156491489281330482851672992610305859875813105854444045866330\ 195832930272962868090251629001262427672036352030932271624573869445040044409426115918852352\ 386190488015340472837090770129658523162849641878761448646778950103454738730628574019190893\ 195178961367639977865782855667756942414285086005893214607178681636846032388085361643100224\ 312897103937406450810131171146839155260242860037545658280474321925843225475921991500059904\ 893724867170418166647704369625862112242132648665765232686397266259933413564501203426805064\ 304319947071544477404329128753364984628929227792310333609413373447991009689145772741442871\ 118441121959040036230789198742103810466444010033665192151623482733379862439005446056835930\ 548011647871178517009918194136541722487367967728333796530346553122117742581032147561934805\ 597725949865622154541530752826622344311133946071541064883391118537120396048480336186457043\ 962813791248765286267310243145437402487777748117843552155873907033272251113386216428240877\ 695657651055659021793921091263372680271735839186618464541192774632232900340878356462048584\ 643002143578081834962551834647596645904115465806112721779925717522470006694636594541418059\ 471711348513259826932096758858040775604486877576573612811180134242880097875285667838302707\ 784650956456614083375464215702896348907784522203537032572397228017931252063839431293942361\ 387112168827004958386477465876815968062631615099821322287274435494544704305865146284909425\ 752190115162930996337599961297377993898095757946803647616597127302962527260449414393232184\ 109789154051021476399035838298018155643514192250276335920910054645950817628892075124490352\ 917207444471031911579756903279720476459685884696728521440642700713409969772174267462858789\ 513871181398264896347134332316202728361532264224340888812166540800216231606329985270731825\ 526583588696051602366554350377300001219724190808034927772291703095303454758257080750712881\ 171283327025276282836128382912380657249088149916130455622082428081335137598426087120002006\ 352150088632113052065194653674512930227472975796898513622387814235816564018304016843251816\ 970878940744373070979752030366628960482215788330110556397241899346561620661098211406686043\ 357487244583582765727391555643897052341557307570749704033366516837414991314023295965335528\ 205263747423608045241981391231911705867722936544972609569568326136736300995682212378916221\ 614754012264597745077406333627790846614162867565105995074600755947306011672661928934963859\ 356721696856359853979336130350393612226742538783062843384049466185315797957940709571142587\ 682771827929074054315241526630467647638215287611720015591269220129929114193823048976443925\ 444289752166885563579889887129713409634060799468362969318710370368918880590390651407563874\ 988908564213926543693627881039662002322516832660873727280453277613470608259837382278226521\ 693280123059332612011513729119557790671108961807087934703122444773747371215757499212817293\ 491296263305291247482434462803569253778567582638607631637966722996747286225878804250443706\ 952916301328088938191866899257794561370583018029167225635511332829467483935597840251166946\ 973464998761204164542720737578057135767370446607879487669940418903447444725221179018471286\ 872538815397600171100668199216920904591483004596395106458756290908779244781862535202061994\ 654435638034196467563708787769742322737315587773536401647455326106935356697906498185416946\ 358380402622532181548321503572802117946270790595849184012640937066865116732654512574826265\ 300440927188447262014069991571758310380517971050823181642417563176242157968913841627149539\ 767482546510628399404319016477244511216291384745165998956569908742127439449409225332439548\ 199744897818541967112641312000004919360568508913389315141008346671201357938700807237242764\ 175612671095710707190924871639482148667739603770081107666365285050180218421762832999856314\ 555776280393007773303338320487187735009158203206454693065330580625167361011015239203563939\ 670354562096034451813230420652498617104671334353491692041489789430326150789341564242978170\ 386819341131546669175177110921518699422185516660246656591430670406865333300782452050059151\ 246076742443463871729428758936388613115090689750067412469852864959866958859641545687393717\ 390883145748237210175931692486062179050404695444469712614798990456607955176135906694443076\ 367461848535498780078265714455055407186437114822766208593268581146905592143235331349830178\ 497578076356678053685774194762464557512834895722684120853517597756564866109041170792960587\ 224322922571847971935380601186363715138359724322751509149383850509998408399580083549047628\ 893725380329671081574653755482079952013856558751398407606239621348451578588094057399731098\ 532897935534054342892269914232731323928331429487662480739384018765362548503020718815738466\ 404109033487749892085255158449132132829862948454516652953498009698128038756104845631791913\ 264195920655962240750681011977519469288198484679127626251198365008136156751528470881302986\ 963738691272689346317565389605450039096659819789843822496777079409569728323359873697606857\ 219908242318848573709357184575924838372159022850096103230059929580645091389431197227402407\ 204660802021533900213569023210717453218508495958390596459406149353527106722665878990927703\ 691708535069004187080494536745092882517793371854118060643581160521480658019346196496913290\ 733327494627985536865562100422471592319077141081010056553688822333860018899158642527743478\ 289432946742343050884983132829084707858031545256541369405698544783865200458223175005239169\ 515958096851777293893944971532492230055439266034940615355144103987825128225642023817710417\ 677270518590324282312369742212937032086949295311480972380159037349281880243323462548559564\ 036148564084885624579621609670069598197303484535139909382126618558416065645363264521290712\ 659075640385901469453335293004925422168955388369770710075906023369558181331536059450505543\ 649886145964644573961293151405882255279583802786976689021153056324185556768052162135245500\ 380117823840841567192612660393148715628475976017707508909449627847101777304727517437948680\ 070987926783281646672653515558931371935178660324825022563133305822065147395326088467510809\ 335857672608811240471781821770080748692221417435895777442105862295865660331993993242161014\ 395598217652348309159623592384756565078227920911303508037926069029298772005211594736941227\ 550879675369652280250725705742667735383317560302922120467692528907811367069970518206268659\ 763774009956893863308500331649078592931203171123352517907617259767228785506666764151476203\ 817181719582074168808198064140339865825976662129667495845409023550257211397572253883138723\ 946625686246351625926738822217539589095332910755391967420588355794106600721911348694567116\ 456772724309337558527716790360773120926958218717634311161620113915353672465658072397738294\ 865720988224280587614684004902800784029986983516289313606893789078380001484627234192440164\ 908280955649075614294115830716837873566972065901168676826891589185983283946232334076758075\ 111533225339219070679416548013270176645186488735002181966704279838348733197574813884342167\ 080460674830249768425460935873817549542311473842354465326642131007500706387201763024136299\ 359242128977116787993597421699388777796469439779054263046423282044626175070511095816336979\ 695938246995776700257395172622253330792335984600393784165149355913972400111586275226059528\ 071680719287698179571822060104898765049960669845727202887995927676658793595914758863792325\ 211090582394265841487064022796023689890862847001746523769847033747263480107576895047451369\ 058584954852592323298009229479130824116389676209451862729111887834434712466865758792529440\ 489958356088415964018862863948341012182768265335552103724811820491573102230558963549145601\ 900646378148701973337893877881763865079130247943446518308891509951308496583570066059434248\ 192218459573809718393810466003332657527821455318249355764904508368671624162539077644461203\ 692492131927969004751318820643262823882883218719858194775850910443543458700134044350693671\ 168627197433306505226243766686216337965401016942690899606629506557562963091156294145255262\ 661741286030817656213045294446376016029880731086649716644887758315306689601076907561108702\ 169896119774909306431429208396110540319115228369931752426347005261050627301765698103275440\ 586489326900733099767304615724090841032682975391197365500068749889874623936007063151271092\ 025957354088084894551653488789843974629947240546533687096348925032396895434510188335439205\ 017703217362985915814862753614626455684220321481262821227003277558404637805214772781194229\ 989287195140150305091504649601057490834376908135508958791856629971219262264783584134605005\ 143809902648802662261409499363515893858997830190483425427111416200392851751915534898935376\ 225265204593445747961823434507517589935010448048633710215253148307730785525824748160359193\ 829260766485623015304355774375465943786424910264254595614065858974531793804354964352279492\ 447598956027658878595009622421851651482821119417239721236949780453807897518479112441484892\ 188292087630778224392472284435202178165567006481358645070705601797598718951505104227306443\ 846429356155034939666023276593685270252328917696391954185565047621545589361819188567608179\ 342967274399411705645903495150979925338678598908983102842515061482305438062049825053782774\ 607766651558398540384733154743837601382967901936533437432805757321815782019716515429420611\ 476092931135542432874292969479080276065735922993157332981387011718328212897720287505992178\ 379537395822413275743377155554307493737073202517448238317573573355132952688924235651766373\ 201070832612879648731047232920929940611479451030930155448550600007889745745231892386743273\ 209002268686100510019527887711092411733571204658142586049865876951088587084003380691668229\ 693517509832670443442409762408012903364302455536243943786709155080243752866569007216858307\ 904839798384646987487388454302752753842516011430109454202000271672728518180818990092239140\ 612669850864605543503596603360539619223508385903644516342573854515157748686211302223684474\ 731708343264666995341947804863112080905935415486832036442995474721496936445718246545389915\ 196998541873484728749825118732158464412141384735012748824037358644355975370997230696122765\ 995673096065735166873251692065222630103057524617069848918401781966067160015028616000087752\ 441874667842576438805400751799498818374414789287350548628976074876297719970166852812246321\ 938928858305689927476140904745799072491794964506866128982091420908376763259819780206055092\ 152709260416178906396072404868670431370237284226573897697962667460869092042286713300485627\ 163574126592455870841398774942632705805410803772690396411203269379260677431533816246941783\ 795453409006720697926032099689941579057159131432788111681434558987045860646681318216892288\ 980454256718068037426806924678558146663918465413885297116507179252271417350534888598189147\ 466563826575192981672602039119367277005045000942505770196755650698618499775290430745599178\ 198675483438382756410680338972159378088736221630708590893404952541639854982939176437747590\ 441091779503265500004375786402418922562259530761319147106606618582926033332180209946152844\ 479883274488205639519829920029586712866356752187971088919195054217264647454961294055114147\ 097423707012966007430692426438018974232518180009453463077610781530398041018271765503624888\ 267551300683672439048885596952711026206032822041848601876955276865054648936969601242991163\ 468132386742076304870027372767795582862822288992929802973820813761972191944072065668979954\ 832654970825615692708030373237833630414233503736709360360854144627800159599634863847349094\ 195910918844290566538735523879231392542644239295650535994167707530208855970569508582142762\ 515978150470065581846886607138164929691439138020394533249612370712184962466504944480602780\ 949878243907557364709747082343790891171163190643109487560482213799733758308954250973677318\ 517311848431444093065443073116374364163545593377448991384394858979433337954735733815410500\ 583486699250575677139243747867571173647249146180982521407876743599298356863041872781978550\ 369736653688495068005542260976599776994235050796064402406372807307195744863412039043567830\ 287884425225447699441761028754693162873270147713305672036772880610999416492954769533137410\ 444411149101711092906308934329133997028196781791442852616582672060078198706709116184572179\ 456864963558937969452838969223121429662055314025946635874388068243040636042717385653221639\ 542798798849219728055487325268280680800346320487276663896347714867154116520120268055496515\ 248254068448546087026744166429556344869691444637977783809774052556180687485836749002986334\ 975993104991659339175751336011118749280632082415518320979302547371432390200088605990101280\ 643285405501712304961055185970899033480139782322067827495605256498458240963053045149282992\ 750457126196507480698488009102735294685271463226617056822225098089455521935884866153314002\ 005493158467256206566847421627508640107771351754986756140159768910648481453017991852074495\ 162981822205608327387103693249650550524035069413585909333832252975877746870278724056565932\ 291907901170118125846000280456308868790475360671106371012830114692455446077624345190211337\ 168874543135520828398193897604635051458158640871741874953935737075477438415272230251625675\ 759960321541175106560143283994957724171405256402847751678631278260769511470737547026812062\ 336633123665206526474107723123674374751741115083792194920214071038959941907495895037396673\ 448683077177900181441669426146974107450912132387955016572390183752305074128254199024337714\ 128109367484767457972061645697469113977266132846315186977556912459165078861282699234614413\ 642902293977037634958118640128898328615687185724592327120508293802142218646096285723308972\ 250810523778469850276673700386529195509267285321458677649789538978006450792782756249019709\ 483094305364973843312369550343496542828815259556687749265424162817213079179144832513222739\ 529895381827244825400538551978786604141933806495263694150773854557509288674468524742235976\ 040356854594791258326837251201081521418172351512733489780249085837416241612207988638157463\ 898336262689713898209525457890551736498243939262494573244757322711168373071161148732745047\ 625404441803924748019649398526917120666768521487711593979739076486635564615308576474495031\ 161407642081115993949503485798236198814623476127947590046447170220097703023505957339994268\ 810694663657200083008719702506977273412840083741620318604482639849739798913959791624548045\ 787976372212317073271825317110523802202364636615128729716326389303608487318745749202066215\ 446099077440563842278062274609474227868543987320443194159104382922849979492049510469533885\ 664528634971096642610048849171985326909036233953040930405678415579471763448772809762106002\ 240520188064482683228684432626859804536853273920566034068413929229824219906574892652007708\ 911305815573371760828586896652200243309285447011806818650151360469081938782079505431741022\ 898631746748876572431684001548178020016387237231453975077897805194210272480756007595047817\ 072179641515698081724359536200388835279394499535426179567656068776179076422779380946901593\ 296037912775673679908356871920865222776852930422902573517689917141936405232445748192766752\ 326149114210496843311918312722833233503867222294539424714546680826831431089395830583061110\ 621799703531543112481542835464829973300479213622694624942766451741469287589480772124356517\ 484032241777158244828277226738157892222222774297195682200477454281602781566529432439520678\ 962207922197669500582775135179739758800532765477640360539091021219538810440745503819174974\ 543678830777020963919732277478995943176313802084792368621344588594718937746657023837304438\ 759492483292461465409726716016339256043632909825482806204539795500174658179177788302620851\ 015054726016343362755465477175551702077367816907413663692552902360310772569027147098358138\ 176953080329454468976717130473268258403920268606189394538864533513001272228375760734722902\ 949196778633685221915617523575922091890321476636670102476133480400305484165691133181892873\ 285602300633681336333326980320535419895301776584658910756847682255202181224728027384264113\ 605327717169159314596640988380041964126571004937859339462111794281117404128442632606095302\ 216135318508625893485388698404614908870852878149653901801202031680106302606973515614142945\ 021645407742130961298687397139048808266715608971126774954702069266129390591418273608210741\ 259248494408071911273584395664558613460549516230861165699050985989877179367325141372995684\ 893325155600253522411792216393245129764629320394610882016137420305615278371611350031064850\ 450517144360143958067819227360006456163145886094262954546334759968535770187841445910494483\ 090426961383683055809496573835263363736794876492758007394999296905844558984090704733913792\ 926878531926474428760038488000392742707013479382032566825590647204587496000887019741593791\ 930751546687732745488232359610811879433451337305883193449568393012878887828311857591540372\ 152368564512417672409543849830156148454290984732685831169705065271949149891324447714705640\ 479239961751411167257772348847090215972921374451287282560659001384161897947792004636342451\ 097273679074442716088066777066727945744574828358267649596623681376787463084288157368508394\ 983100279541128475640821629631603635893611755116868173090366115038011857845712456314410635\ 339316084812241799415471575051868505721201175674016234013148487189187783563763059549663968\ 545186369894787858990640633477172084078474527402445523110422092800088165962038606708262509\ 405529073417953868863004636110531807264177444439784167619818270671697809335443896472067055\ 391262524314971313594763228477895020105127268747115467640031793571876020545182899912559371\ 515890437442155112606143052716794170091724480601020832811613516581435790660081668903652866\ 344778611924669118187984910110489920249572382055192090483390367550511107244305630411308476\ 246034973417701566827086650817892082268399452608247497138757452413970380239277204651133588\ 195386583375706752456037932879205415818838946871991812918268798652996353603229825377961286\ 525690638601578415944844449338605302011066760204714339008292388283590992941385144297181525\ 681725219627499750943008070030267952639705517325993040396807649287955801312996530693704504\ 893858711714845695166214823377102941274203331794795987217861761102582133518332225495412332\ 794865769776117657728976710091961906510058802202868352826020098788746426151913989606754585\ 083170982229392644738185802395607511169818825907062400228934499744969376312838562624835963\ 449813109448585481726215828925845960304199979371315813318000963634632578011854880871703266\ 745182161071312572144174593794444470407254103868882677060552177259664684562687005376804734\ 423920390840193907054307323802381480445473113378564453740133451782178956305235908128823078\ 636951948157439244853043577381568069057107414992597148951838962480526682349033976855559886\ 768333360201946264640091464408656617309149852431253488829237267983043644895109455682738590\ 628338233678662331108405458869239108175329649953772577369620664208066777406604247550680198\ 204806249474537813949661966622620241266236596146285628772799759180084369133653644899184803\ 199819197639172538736540825685304737368452743030754495422428874999950062866154624614602389\ 287070144613962661974769449799699775548480531783909649281485248628043470058665293722356554\ 880471411204580090725309280310147584006035143226657335593486783564727318205537734390268599\ 256035629932661414054959338927478521810662688725005434112509496696331972087774539450114157\ 497187074593278096319993002606004247594674444021059350148937292103383339525225320608095711\ 632869400777902046134936588858385025890890380010578272311671619035444658590952483824993307\ 311125107625358818994409675336468321351203765462647979814149039271332090364166897038210652\ 085958840135144700475892890442085564399781650659873195178899091660280092632155432834890759\ 184224468448707611630968599262109508135261629480817297922135676652679970335687416812318561\ 789469546170732951987381753231529954418533372238195872663616020522123720168125538587208557\ 555946878191194074997352803631808645437803132969068066305538771077530012744291209735376656\ 431912020074086829730431253839909948042486217325631420949754395935887245928310466845063108\ 880911868655398898675761320809627011469338079149151691981338168921279809082474511870613033\ 383936915399562675416350951190518496533142823683002975235816914297819972014901873281703177\ 157735663442776785617167135778448996433767744227846200153465412380749278637414708921096753\ 194739038131872185923979374218450097138414431949754937593867093220466225243675201725776595\ 190008499980121406118122896357474176746873241299556717583740275096294752214550949299354091\ 914857852830006376249449590208625201590816685279904725772037272100295716992880651489411491\ 974749059001644361899755581624219885921071096082313539117859154204566276202574518640156669\ 991115133089644915630837435447710936937748204984618026335128642542050519435551328828421914\ 820720325910446182881346221016850383884424071499543221334260986557907070203053000119554756\ 745714266111775725941533048479943827435251584022831205890358063279185974149214939272879661\ 183429850873400851444870573784934172199338402247968788702081580766662859378475606829728768\ 465047089354054048522407833598263451368027296802207184935570651562824617625138161562567740\ 557049414674866570897167246001377324098810527025506025248634952289505612008127192046937719\ 895230220427539784405756892998610560159941320534272573766067633548595544285724450047126510\ 728047529734949700446144176376193686634775933000333311765162590551926122200464221087092147\ 758254291212546570476027322986234596587998580606094108120802503401022363950622785306398735\ 107831241310459190514632632269229805001237303351131894583859789627186916634232706327281594\ 104872235954597725611606564636127031845083212235770353552050167026999352648281675665415269\ 411437773190481496005442332397933906697849720571392876807788026976905314207983204450888440\ 716006065229624618649535244893733349748363220595216457580341010722707672080231160713630492\ 993184204388255083361949121966199532693263516561310928020079320904649951861105886417341696\ 472915558865431315823188914817721486834112177741267944954948677034753612494748387072629819\ 756537513571211040525967861151110056418205210068268984648682398173221129372823967610359320\ 720868347175592825677945781224920495204577337591322353462852339731722991032689171236257135\ 578230101110503962652894359843915458398847085509538860115589927888261194110467781716503467\ 432975718740824884438022951344455676655182195054414463886556400032301644246098556585057311\ 546751580741950626429755591889298716409466794099585716944749529678531120202337903496876615\ 165622966044389646266944134607486991947499105864192741373592881720201815775339733862214683\ 250892425876318451742585755396603322792190049408232489975358298149805159136323045203223062\ 089533940203774786509759462875457010255340194807426469726613857095274152760709576752861136\ 343090472530362954639097423431110123349130014599224528425417876995134068330844903531612021\ 366510996284457354043812484511901646979649160948328451055838695255317134880130921661794259\ 805062985206389896321840011654961597343650228842732867140899567802806004861573668827601412\ 164828306770650894969487528340548256781941451871711857894939266476800166422288777579057560\ 366805661624684486933529424246662011632883971016420857644480363099797064430479492623440691\ 605523311318692290142775414168321647619304698318628808961182376599034034332955414832567780\ 827387778563380321618842818007911179591021589001506406125427718741292760418407223244381283\ 249468038000849231456254436833976197868612812480175157334445529278999446455467559658409615\ 221705850416847657881271759106438354510966315577112464590677047033144214898841393307604689\ 628317928667390366415827610433179766679008678579932468105586461301125236624322796614883929\ 088327496083429533409681976860850136388534170807401366007081717723518891163007426148403025\ 707949861767067441199850613983186789139671953585342432960341291646521101610163079358004763\ 779588286662340532575603834158350392014708872418069701999186124605547481590286213613899729\ 252253197423799843923546220649183477078608985577180291823621936385385111027801361823875700\ 554380246422474067684442988109651704317207171318087893042416584605627468037579218414768722\ 395710690168729596686682745071637354932561366345482509721228212355663337189028720856492833\ 744887592038406303624032902732604618747517241666803983932798099811078126156432983249184932\ 473136572307146854615781787504214488823623822207282237451385961404022080549083543735057830\ 078625359266219032498946296033342496967334137744772656968928260141620854055085178850164926\ 966163110798375382442578243086329744653139520104735091231773446275069515239708357989884940\ 259762884547112594628115079860745073717477371224953481873188607421989899925669464506534765\ 315832211855736580979078332191340642607672024611896901736635958092452806328787088254707750\ 810296559903236476757018102375743624653382025962020905387255595326834271155337737570960701\ 126362899387053591160403382148549056958617157480097927304635569061076501464422461558422871\ 719274903148306130083749845128286690037446939323440977451259226675678786924849429703261050\ 078699779544603709546416898200303604921965901966739621079369797329691209940055207022848650\ 850120234855370246061573153096734344579808093359339167896797868890939240978596243588801835\ 566932348798054099424097479437654044919794668255179495446506282879142122428904822604567804\ 809212174463782525848869524423515136620019328820657452371554345734028886972604813756085142\ 695128000135255167064104978031426010335586584132358183986707331301718592663484171256265696\ 827386195465252591821727129614691077312098971026449495548094661246536715033400219440381339\ 050939279860235113768112384293895172770560191416852175017202353717944307488430970017445902\ 991414630171771627441856642731130048823800687449421860072322735790128760444057044225440854\ 641880474223441567328886228584420951792909470612464842219303001515269646638034847331607617\ 295172905878575178911604084226350700222100432604678889370632689904233406118233045506095065\ 479209575688604275397263069324199916676323699068831625663012082799958332811645505094984156\ 882891812191744747939227691624340578933761852652298612630701899486128576583061793294219433\ 204506787846507163286981973260807566884823848718656503577885230412324762118698687155132689\ 155609070357767942128077574996707926931711975604858655907326154073653157263549608459799093\ 878298615727412162248423308673582935269980285569350033530454431081448610509377414596978455\ 535179077245802932313248605968555406350283832887778615882121860304873324004373133786332090\ 579688147848693092684637067817495022377582230525258773063477882289008085968918394791322317\ 180625714470995010360773055724914272257023496173901990568040350179680643909460244074158780\ 899267150188989719587263436118563621425629514841356709058617850478048599635473401401302549\ 487057768223564263211661020028112704238389209566949834778050515383488322164489903890634630\ 787082922625570917536038325346131874848277664953788711668659291007139020778719701774489285\ 770052544144241621206676900540635934791644404554993917216777610578867081736023355270807782\ 026140606588473450429941263009930241855215247181378704595846267730745425295281947225019478\ 890836381664382576806020247406249722930194605659888988773274232694496489223266344802567289\ 095509093071422011485578096045410854089803415057240347231255441508775084902081991914425972\ 682757232064532393847798803346310000710176797840190048144486098228764863010842530023727388\ 890406061733786346284822599853003356708849637188791406834510939764422440140038457222679412\ 869944171351398025075756826180558676362407068336671423682972405813575058365291417381270436\ 252634979728042320257810122696347785459983155670781951349052442511560634900447996471610913\ 558203151102900621122343649394727258252894077852522420262321167927416066811130818872331886\ 384411496081610094820707968514899635836282436270448625530551867701741689087219413741907483\ 303006372951080315863644183302558565600160707444394101909936633140497846760016702168436701\ 041391533633662081837449021935746582246327317820575813666812366363788208142591568010850475\ 565265973969612820222295995777172202676243959127979676064320997922278889187114535711427023\ 388134947816557182255726036768915930034750421800979830489093634049356013277340811560053696\ 708210234546437359490037883329254262127458561524809162699982302320211977958385638619396750\ 584315342067577186261412240331619185062795418957999338158196149422949785688017230460062919\ 391301228838132414311547083235730760237053326735562675899841833991684542150174148682882466\ 716679626630379820889089177131419554674700935764070833604579427642232609659002948697191333\ 359555610060668704386903939577904889683386230386135356228326002785943648269230493417150906\ 816867363150131431418991262791598509154611194943010143698188010247997600675221374192019001\ 258536678010794762058767602097498480306319364447173990414944444310915594084983622467587036\ 733468286071724922448436281799390647690552350263518734955683889005087257899331236094086355\ 596292869754670676829081962068968092702963219719148711559495435769020625081526376494903171\ 888299538225048159010636706430141636481924724841451993847511336878702067372651362150019886\ 320278210923950189274647295313671276916349507822922900950709902541837457116287891528256804\ 163622548395685688353588830574503091077316005563783210083306510925680346408180601220429988\ 564081191652821776542055168473219261226828750817630405576548229070598113447515611115731442\ 436141219042846761952289435207330980780386972526801138623666896745153682517024465387931795\ 649389985327072677183129398826042589973593024105438244196232842063517253256625665867334881\ 916534480986763428493868706905601179631142859993777010282182506697591463042556361997595988\ 625740329156075441383575975073040645372924414662180844689122596854078085881035058604117634\ 048870467374085876855500551016620651005103259410314494626298400029489400669948922612184259\ 633813049452786575718225144292003688952920623087252891267508927716028159422970303592340020\ 206320250974137167576176120630725257645922573330584745081463445994382367274472107376267415\ 861852026813615963647053024675786755873581626487358864569099290650740948966808382951353867\ 798519156757041420545680486354790279358191960864824612371976584588608712804128344463824880\ 557162484258573591969449621686567377012939106713008094272836542007766036255777711161037102\ 864304896895486745587029819995754115416308852304342500322891439682294248283417164891789388\ 964683060270812974373120152188767442021094213697371394396156878661887640168690668291609792\ 579521106251945909115899365342560558247523025009318460503965637777468187324503983449394481\ 191659963511685119649858345826533563547990202841500140026486352743457483103229831371150862\ 719166145289505458399536924699756864862813875630592398822135090328615247496005185815165043\ 427259154541291415472503958549337020102602509921405725763639960250746925539727209250540673\ 789952330733501642208550454905824014373709427673241753369533165170693817992813763408742910\ 890860072472914734748916057077837897625982620287043943263515577357296774108974620909015897\ 821593378406689735629791688868910668311922021895814220518471358981510882739599697158281546\ 772369695939714558905235318447769171091759577171927782564536611159528231714044331725309572\ 148048605303696101250853749560558247506259564368725027338640683395203742514854314749368042\ 862679505750873501496981100757368471354470143249509848809163231583968293708833309569436562\ 656683668749050706245164835699619920641507763247981769049869524240784704659436599891031160\ 593212225236492891365792588731721189259589394456517262853344452117456469286102653954538148\ 611292558306683781159158705773029614757843401886766635281558084149856355944562552928125286\ 795768922195939460083634477921849688760269784241934897944846856873942450441687210213716855\ 058391422955248259387025726334446959221285224118006664585610824913562441585709266312729574\ 930404901321586058467300493386586896431494049812177913137375134569841094812718317298134733\ 974054542106533853292674821723954653461747797168821854717411145877959646864516550069633592\ 702586049543072919341809849769801193303846787156234825424793958441195143782167404224752955\ 886185849600159026402542303271446301410033873705634336963804640427621760446117331757246167\ 630251743030744490259587710539765867793208734102657436189882016257423158363991837207407011\ 723745232135686419695921066233663274202602273897832942068545505473508027982889060562501985\ 784912442106157678262135704232046583879592645472615560124169290589871813589560144610511304\ 653084567249407224488051119844520873593857530665272554234130553847996706095958340767247389\ 437550102838276914090863885096349143007649318110600062409367991451779012008530165945853595\ 126725813632035083556405803927364962190910362259474638376448162740393441231098898143271479\ 418396813471563315813993538485188886059981049108194801891454541586189155825774846929764420\ 361110440704324355622269134064521615719852781709831866249434065099195761453993691649550630\ 280522533795142858908609680915592022539858966052466051144091292260058381342484073008782997\ 506849621701987152602130976349384138850811464582360302170473483599771191195769441349492286\ 270054990098119570497269201938602994327286525227538178850084665620394761772584698350007842\ 812833358050440730521671316551253208514121744988096128738553988914136510910998063035863871\ 289288957001180056851115849289219097190682426574747278858258830147949019782535691647462811\ 854060001211182521787812857284689712849625119111832624298431821623483504929554348547051810\ 004943030877417320571524874832690298211594329166219740524468332972920024389888787941754261\ 723492672638998005383271020271459957722255539763716024877000463362873040283387957819689443\ 812823487554118544396731177720470665449888522496965295620012348782699539200893365798260545\ 653556424656120643365723314431658015927689932559065245130962218109023456470747881202422784\ 516081355690216764283018613189351241194527855867687117114933328453984191927080913150510188\ 053900973546988092066432582339497884109641800100329840191278918935065191291054887540391341\ 938937914253452717895208324979525104850332885716289309066724447003874630355891587343213629\ 295813397188307429073740523681132772531308477583128640680764927338120768649006083821178534\ 231882421252593160475209347876366022867894786346161989300104170530416596685584108386379250\ 648960270039496104007853678264191149544304170619408606745550730246028289419799215089083030\ 357779550900547233642285022611591450201535610220670241161823500710530351306589598951476339\ 962538590701115039376288702576866092369110293721730793357258686940503936971875060806904283\ 450172626406305611530347647615937848772028119358834615417184851493391088745654551203516741\ 049252625779941388683608251123016695946703624605778686102608501949278384638802687672795596\ 101987910231056478732778755542742098497398706021166366631096586913407253211199019028032079\ 887902886464331703411701397951161365211269109661735796937867092707794733743067336832875903\ 644574676989384544631166130437333542500706745373337299710704629124879789369167412410374122\ 229333540534789624046636561052951181998007191289705010095525673434353667968966277973878367\ 032667466123821409908470565358374387914742809113973925281589469357404181624952686639787235\ 553858657823751457634178101614716979318930589368932544513817939542776550243395612324971283\ 981644794341354626756409056527567305052782710200245934375457665275621318747951883639756564\ 262352461930368366604963962952173822510321961896985927253441955816117358923425092450848619\ 642137682993248945574466178398123078103013572003611141584245535265186693381011540791087277\ 753791269346268624487177970740087735772330112007363804305732617292382170057476489979663707\ 730516936708850329337446242291895369660713218350206191875230323688012052846027864882848259\ 701228357313964337999592919094187542954315038199934947351626232636660813900683995931429234\ 275232497883988387531746796147980559728644094032550849320858447017225191053779746122025390\ 293856659524118700940670618255377041328161470153565769885348129692600671991346683406187404\ 122162260559118061168556125016695766778501991528337127988723843289142276071954357101572277\ 747492357946304708982397416829755276712621092325294086731199992464671408884307828064526627\ 154858618012984893144529254065982651440535202322594021843831491681617202732508862135260971\ 054956925383323817099659792847789592103705266129996676820628100720066735040261318266402281\ 895202358676507456306345227539986877419326853929528618956878195537235695921499279604750824\ 588765075564055392116444178757900011181848811794331791298695702082965280042280234181108123\ 456296503173665516376497198275013897623495321371366964170732065174285988636380245811724321\ 642699521502348090492297677147796202905758003566831023601973035417752762549932933198482519\ 033340228846684288573601294796104079178029935084349235918263815409392202162191126337299973\ 085391905507691530404523972877912023502020268259524123685245249722717806623898593059219721\ 671125285966083589136586569241144798577749561424730365261715542445053121404880119549009963\ 940262229780266389459421325711642452074666067479827481424500358755413989311032224554098600\ 574565090710931389978486043939125309152103942909706547255766111265331703053938672472656511\ 737190668202667955961568647373933368504367595246796560022670828614024510944001419843570812\ 035316882802096152987157192635175599145696929365351128280840469102759254457096887698704481\ 227730529643558479156854116915125046321711006632709104074508545831086758358396848811368582\ 168268135110202243520982111839335996265588876954982247250866935203576355207081462043166690\ 224797698996092949545640451370732244152951305287915235643316412484417319161785947349874164\ 420493634114416403338368439170503832547660676000292210949209559366174989996963051092763659\ 739217101256203680052534093269572885689640918448275087111358268648076610357729307926314390\ 736377283544241978604202729155353922391701334129386139054611641222931440889949319415919574\ 965760368509976487269003294029030908533570888930299070935666660324420317046763615235198855\ 805723479369543519711530650534833557727400563194470682036867192541214827247160244347606329\ 437505568163698740244545933582137985460278090391079898426302190888599593203108093243796000\ 837051500005677415307442023841296321429595533657886608005990023595093038618870168228908048\ 907997679829388915693339278939164067080422245717423906256309395520118753052222897430119677\ 679524735595489324426737976645241292326623772291197564152114277878984801156634916071678505\ 070627677237321581043324158835984791444707011693571085749226645312961361799982095689269872\ 220836335728393266358739159822042068866879998976711541770675645254343685674227484481160283\ 370420564547224464386038569714609371300588180742505737575858790359905300498379894816312604\ 682024071823813328040378220499308551193272903834894542174618040863674572075532211153485505\ 994192637118706786454062304969550359770549218823456415819585823182124532911704477695790440\ 724343169970597782710712144341827675482033003922965698963206685687598793119841743683203851\ 189542344830972426311389035901052711211193165639094994625002338118606707863672619400314067\ 055303369739231130861626694281827389605365111612253660517264388368729056831372055264207608\ 703602087996042936370551486004168518628158586817918533781935905750385451226387690311232190\ 751221826417128365161241275011610603164330193726587616113141660492866242483747071073169769\ 635512074696824594293961238286756634065162567135491685659136988836701083054696429316827261\ 748741994511427403295611849052379501908408409429890575318268021614100032495060929337047238\ 886493196099200412859027950129950023122955239626288365396604288132328191922258258633109225\ 740162199890632526703417497215914037546382069102125313696510346781192537133289241484185472\ 191994207912350578927731782204121136438529707886961713961900059381650629266160385604255414\ 812610441885792558475534332776485111024308513533723742360313386451081721865147713467439351\ 166233199052697441034130017200437878204499782025048339277991179273538441427436885663044325\ 347246689446898607830707017087349294966809793794528161472360208878541805364972744252373111\ 950645208069918973045079779054771488030758531984127997276190919078284116347858530059060502\ 973977271236335837624517580067704646948275577230459828239880836857472122696441163856735899\ 937138593135001631499766800488361478258298501701768877935809297758214362885297259006518947\ 434757962698550239303113302469447679737036435465978158966217972784366291350652807294029366\ 017595253801959655253981909215020208610634637266462782872612117590296831895699429923136985\ 002152086719201885134903865004159364714295080669164318755587913488516068682785428681051450\ 311719224165020474338154852151646941634921372305907905628415334275370832931674705225184469\ 504011117569571607786226007425108760766851889664329109441321343124377157025893065802266219\ 093396000013750100568443887734085728806768012678059162465708901892508876845390422152523855\ 791458713645099185634678263676665871741837932800054588943282887835273785261908723176410467\ 369641656675135370757889653781228103054241121688685818663775876630507617418767673395379168\ 632709705331936487133501351591017075577275947040812881585100120161229734355016484195119741\ 067125252087855021757941772874228122556040050247330856849156883108419638562082765203727733\ 053438152874350279016372907896031132216812541985645012178754867937975571357114545231527041\ 865571908863288443096333124557512538156351716877712771170996233179735707548910026184975287\ 060134407697297834708058511251325214969961948585213069463677620556609247957743166622715360\ 200278724851201455977470408020007196865873450650035877862683156738584094868224201783629459\ 357012216903000117352936586258042353273126269411727103235395218852807604298822998623634981\ 467317840189567675615543880603673804680783999871881965570283438249366329502602137840313216\ 370723714436718287359112101339796337967458706231172948276553303516673986916760702246716913\ 197930156344779389953724667626332988336624131878252708523954165290120063994913201453152111\ 254307081222094254756865565092428295276271004403776412442501486058320614804271080300097824\ 540860558678266306686687439747328171919222597486524843817399047114395086858509795268603048\ 501572158601002439969506518498438010040029959422806746715137935409329625242798391908052405\ 919581725103492224678547694054309288983279202059075881787277202356474690497128045882022785\ 120144279320748261737471698775015314207357452634152513949851185435204823732243137714788210\ 069121725221913486844454548558824224716363884769813462391399381386264013736157750249350653\ 859914473264154041521165563788762178450501641686607053570897529544386087766616328725819543\ 901828453387944308167456166545660852912531980418824133778681939029423225236759800064117962\ 426018965385940930738102044884342341961911879343141265862321612174715902959600092409864645\ 665811705453176054609462660361302822927920927886486768586049382098641738679290492942412052\ 642862669893870087597680590975354197814997105778462286387390516234350362839658478775110370\ 792194147052568852662335958222717292304720859963726535400584066003174352691840697308015820\ 108225302737777647044790471274104708322247367181329484303405140774608920655083152273850525\ 642797645356766354373336165804708994016707355690433034405299388101821764438788801637863706\ 268017246320342981232612653263324728489400894105111661526950491445558915934331109363479487\ 700996529948291515636266965946237181136138047533438901397893500855361482648234830120728895\ 275655096620923030249131510581820984751954941048243786985351356025803292494307789155782087\ 365801823945460122311992774579448550606971966921957173510486681285163133603226093764710012\ 366514376355134971179398057605368629379888185702344751878601233954901544074327497404115609\ 079270678908697207469256038960465926030391454569512567368556013804578339241694393908176799\ 318917278595880318045840137101283459580044824211455654786344904590421238002961130576032019\ 295188692520480481111849503738618428112790307781671826746760286484127372466609139052302306\ 141427938821535333046432218521518751688366555513859578008395402485192853052315589186046240\ 336659379232510575114063940174088286546231232375094624572064605313525559428480724129280002\ 473561533375247676467576539138598800258364762597436404774378234654280047626470635245280798\ 856113993982555390271865695778075205520502714479234742337739390013704668999318501607050723\ 571253341312677076099097929950352242133897423820131218568747158036984654782489334054012899\ 350457859902368925482345333939823598995840815258712068542907348652018937216680175648578347\ 280600631860952404908048051081500201584012382050417695910440129103106717505745127620999572\ 565461172707373578874360272620131450504898604876638945238995199733604095699954659933593339\ 956683608436111072290778933864052755497173730865386920409141509229729056716236217019966504\ 414801805058358940995117441519290940620061782066783035286225965680856429726020686594753790\ 552334753503972439232780957604304715275125113033720235609770463230184828628364135598683448\ 464172758917544023410375783573121877810955564664855333583062173409351472686918753051966534\ 360562138980541994128848579537986987473099323835936589469429671490573526125563585061603521\ 887227437564868439308836947588029163131713130443730950726811766072804290811286447790602624\ 607158565456519846975019561478144296208444321386158225409554468680883480732997101700070899\ 871337163518096857764640888353376224104894402388839212889044228280798826455981312548260573\ 302466872626136956058851365053985178945894311794979384773036557689575761237892583397489778\ 634650121976078180959903786157236401381622072532459953964100686664142203340728874481570806\ 938449833508002363162676209020698107965165028943963542134436695963841043713577528704444098\ 641362720065227930419878395898161271592417828661189136443196005246083195041912103002045673\ 643474779290515457485006631383609895544104164935265274513380242294585467221782830608789114\ 016088204989165842398235678561549657371085758269089411047865628947223849255626218237335558\ 271508564470104237275796045778375044948942340914626143848122340356637304179790337276037940\ 250599713921378676396350686799137440789780860299548492788975979089564412968411339337355964\ 969106481228800442561413460381657450128053777860658569315188272872739221697816932431400485\ 844079311141837381494881969273040099451533628999978539285860032800628035954633877902521477\ 930085693997392922865757243128759131936454522265287765178327037830386985176458600868252843\ 803395118112444081315841135854516287006178425229976181802317875442294702325881121459470216\ 401895919134456511866498263277885881131408682067764349868874607661878403734183756393639386\ 093177918645369578848596411550928251658126865886293017646170825358310879915418855549378429\ 614923995315560133325364462165981048913635797307898351955183481082835033630615626694584505\ 349039622426550608295469229425933549609690644586772554622369689578222332197218442115248340\ 197542009097622344093350300161241885733884429478812067570031214075034208044147139683693986\ 738283638173426285091977125672321699921496651158554063413641273519826378773294725205535247\ 353835552070684288104308094495904438232180714144716654221591029416831552382750963104009173\ 650246896840097059895392230079771653080340892617966803049581244339483590100874257711214210\ 765740179532294625314914504053578793434211959259681414246153992935040172095232154275345712\ 387522794580039057566795224464316983245704899936720342063200026858764886327924238265650177\ 859516177045051668289231278688237206232438272612667863795175640158139298492311616238008629\ 425959815582026628729282265268739395113306786691926756017071415984308378958374011814836520\ 919586202399674582815274941001802875096942160301001448198331312345156060026754802936996906\ 713521643249665497242343102785961586374244166483721450125197070610974421080382478456844781\ 140350762655293403438466564121174477294769406325517589377426324313614982252887530283561214\ 095139637581896923304589858605802173887342071887673117960027401325121974712222700879403739\ 937379652482990841932688876374568096315485746678069675760449098433889444760292773707066356\ 734514139367234666967750021379351601977196099780593652841714877874273897076999700995877784\ 484254224542187364417240127037500070064967215820049746439705772389221397746808100890662987\ 678059284127771720130608989489006969705397948996457137368571925521493212944282518740417900\ 318065137750312220267652743504527022409087153138628483688413776611698484966099352233295753\ 058101507786518018163169965900093076364630416894359375266391896845120634200220596154637245\ 038015789483306305496940578597112136941203453177455683104626248237405020531012455054306266\ 461429766551231608755532248035147667710799575702985725312348897701245449850023407573330826\ 080212600314834506189352522878827755857431429567250822726581726990358253034155160178561356\ 299613215386506134318647797421364593054165338462150438362187128711768622210204074707036514\ 769810563021689294971906209497375568056382771610051183032807410401990291005403256323591858\ 179477996257618804324273972891637521484810284677341296358967623115721025861472918959371209\ 955914895106132818594949773538145773887447960663776070386477222718043264626338576830634431\ 604874140223006489276034016762832193787265518571505506627985459644540648942313914283972474\ 264947160011411259101578785132398127765329665431655750277663100801474963288033774497279291\ 916294773733271215698084214280417833867770632988957953412409199912553780600134664301911522\ 927416812652853657907891553370592607086458180572359745255866068429921890034627797772501915\ 906711535800235444861010185077151768099257736969104756244894183623922864411826339723241502\ 386081474542560075698748071215114007869866870517801947237860846416464165668946081838839065\ 438030889901029182672666454406359555850414990072273151719426474311901040514086485210033055\ 182138035198438530340544045428087925823983791885196183219157475590463612039213173634555074\ 502252287308689018177449316202634077864235544219295863242051755419083631358039691976910768\ 712392964629085234040524930745725491166474825106177394852328597798072061226847878415546784\ 436237626075492694927459463054308382449278480619931056086935888257470752423799731471482968\ 189690403091486078503197687181605807908599061462196675029345994307712989285033910124611124\ 617515236800759742036191302458540127639621245868286075276590655148823984980950524956048059\ 462410770747474492079968699369428701265046530952919040544320852234288996696947029932170581\ 675010258659555742407319209148263668937127040453012275534504027462283875602654920985947336\ 746984925111415756041586494025203540932977979406785155992041738885866983528252711090001126\ 658033854334235866904087633115294753515658939488469834204183733862203607885111360612675183\ 244499196399350700036674104497606815716696409469867899195882954448582740735543961363748724\ 743740126325198742632987451652472936656797691515259071360623713397503708195299902472961533\ 919504798130589454700446450763193705887109573240127420347350032320154053534114639452176145\ 280599429017677145230996220144062790042855839573406554119830951846793361384981605380599370\ 943175767863557569568891879777200527700496996277467356750412946073709906825587775797516169\ 057524990736142297489343752885807056445981506198385316282534170959869444237464762384970737\ 709357536536634857829415426723635212857152474733861124359300179589023398417459217940339640\ 437074430044236230343124590839679224014422546898812036918523569667217725175152469934259697\ 273282597639015550460365135439819211263856452643234976883979986639684164304333384857161253\ 156554627877549993473967908692378269491402059094717026393716894665719061760106978880278899\ 748376509138645533499832783484568516015554654190257575462600607281103734672941990434195422\ 928494591743533285467302899990723929770879747318205893008886529057041409468523141397009819\ 534784948522111624441106506030103669998399060464398113943781537367346282943872312729933455\ 351014196518090276926576068051761219721534258171961338383635624959561021205323887895639376\ 707688639305127092461026074647092179516532810705950364676458024039008286741695396490887700\ 491097704124970574572423396241740380677642717757172426601908137753492250841394772492536788\ 695459704420227316778944019245629197423520448413609127872558233074869226510246952164683834\ 691240897095132736331942305850792353275922110923209974398663118164945565405975460234571146\ 247583118993345025519121566695411844785818447287367487539051053812433210834346104733598625\ 322403001864567085028395627188935463064103545033760399449823558943366725161691586551226760\ 297836242265063354238200790523133867072541000467336935555740602793776630761717552566931256\ 246841161176973246177495867465397298838043635017920594555718483836207336811089517105035564\ 889757721341725581022496713438777882472359601270286277257874551099575668001936525633020735\ 477972200458142432645715006034630239680077043855770490466015294169284998044077276475278351\ 279599949297237953054090947785167105283042450058044257116722195073191682913720167571705460\ 023910364422446168123557198404951242122670141806679683455234724871079673800669476763785646\ 990722853339180390942492232016306232440742092938580028572993856856754652280004885740348848\ 158525092140399790850166217975948862827384496942753929045305978288543408385763598707892493\ 792894688401671699945999384098904828369031385867711025112264491353142821462478649163932604\ 582223305512259105107549873911911750031965157243660222661787079470923843600479547458205776\ 760355330330125995615021823323558378250677226482592010852059558115503942941332077126341355\ 914801310682653041692862892554076093594527871494836040974394905661388402549848200986306542\ 735478192537273777688969106419267061777218569373276934338439477901184876774864414090637646\ 250703978331394112029880233370038202082678452980920333607341278103708787340480810029396687\ 286170881430569951612113494609293682789333024992993009917714163545057420505550963890551133\ 513421069081328008469929060644499144807654337680628040168552158466733178230076700550089619\ 511567046118923273172758397333762220149237220162323860762991076947099500943296288510271528\ 942558751170948115200998029445222759207482945972404167484663728575749848542882433257751542\ 580616146913568713381620189504600109375036587294665060233664333030845109896451302193314459\ 702262225680405825270083581331734175068110108176313834280403882332421225259730542663199815\ 901192018907685131520208264251917239375487782191748452641331719969065563535235339319428016\ 016442453556515955110470446740681620667172115010440113458545035042711324274731358301497987\ 628033929771074213262488279882193299538864873910665410414892295330017003091127380932684586\ 207341711990530994693377987183148453615113213909015593895672761432272924733459359900095275\ 343426309397938253813556004614901381479341410649437879631427150655825049591569920625902203\ 793436281718900528975523828471214689403661747345953083630746235422723895932048794673334098\ 878011267002120554378948746994313336256168183443475199948603530584008303382753575138211391\ 049387768349488348361807740536193988874333033506117086986270618585132637455650572845821791\ 136341442563983653286522105656076939802625328301543100870207559526295341858049116948433128\ 211906148184235122364737817220486810960333885127391468182364036820560572438450175110012769\ 595827294143488028031986006320674667761727455008970139879780646357333553806958995959753640\ 119320234480985834138518032808880919445718284392769341972613706988261085974255896898148808\ 766915558704252679371548323230821911938592376052317687552996618384213759905631006009392374\ 791090350493370698390282919725401929825019666057301930479437437001671624227467258715152009\ 304864164297132923973580507829216590607402867968505132960957170458193626139468791855509303\ 307077309598991478623175663180982512319275524639706861607213128768424408000418835932860471\ 395906861432685695856917336426069543039753344402280000343741234574426795452852982184202247\ 423960010094753425428463596214794438349901355288139607818007271798035303225230674234152672\ 263656667947003234789568837603113226065121846320969851834227256571500858990011513250223411\ 444493584891604219849802463958472877746441691856721758365518892567058861404494660657131794\ 210349947705738770067749837791847771455580690035239348057971457916527629257134647235819890\ 126505514212505720435582559910669949641810271051769356419546258888300927597734262145463923\ 147688629047271443167172969003096370395209831128302169778520293179477520211507408988872073\ 303575754572330014635335413875712202468778331187593857878881480448290039210843250510431610\ 916900968194409869237435496878617384881941397940446741731072418133302394242932099681189108\ 780295473637617987301240157905651646338148045032076147110854278016466327542005573818395933\ 990814857736636672311355102457367324674289366114555653698598312284082531665947602258035425\ 142687048211169763817831024407517329971403235104944071641202457924236434923760288404656542\ 713083027755775258209963103409168455621333810230509345589438941835459524428773097023089008\ 745959101788421201038434121900253826870317070247003701036833903181772874779096708475905356\ 512712484207156109549053090681031132386096226298304719088979619299905725915048170260140707\ 029638019426208785589149090071245947946868788595502503678830711807742885183045013400845507\ 379451969204400012812326626382483660771887161897773419854540790511453329052789601099716040\ 371880340096414263246830201951412226682205858970162550022209132779229549206166207028294298\ 436542054532131893096795673352316484282235117016612450754309688628715490615638311277209843\ 229326111076977951972900027388358885633010289978561727897011932205243885427115701030074750\ 690979871486406297387372287068879742584731121127179556623967388114459467818838193831619150\ 472157229988506829483580549761210785736963968896239398513202932009955536246857710951128326\ 193382973043086900322950274019352166444711881242633979156143330428790318079341982827423275\ 327714184915660815599124235753331656219268736219961191236097800078128167219990826275358780\ 145358949358207827418639228216989249605358372898860435622201722022887135391890585832177778\ 890092284960776710861908660521794748907274908280344962488832788940424516132926846052300514\ 403762188816474941407120139780238123999955941671492298133698179926019163449358922433638483\ 511685224428046980291758406252464561148824867101485940355306784163516427555719164001253712\ 009833024880330212869198223289482054781651014598502909291429165481190396184732550421495664\ 756012523187399230539020417715960524478488621439190718225228160459586725585116088341536234\ 540423724197727262640821015289877730350760003269281825213340015546310289776713057033977917\ 893502162870106835519141632881701341137017235661373996009586235152180021727258519062092428\ 476594528072512348334858692388080243604187964152882516402046508298038290287633962493751911\ 600462615924239335352663534079039032245951852402268110448919375189627688200373549292790604\ 815597681524033589514582285724513696914897760355118174220427873086778036932844354838715108\ 597556701890034679956545226416946071927195573242890828184592919486766598358762181304563521\ 050212226801893610913387619920158316227497379920428694789695087274670285198439278814517785\ 917147799675171948047720049665793526391800355731012337544750707275654261636436134146781573\ 313097447195364506520948235011201583810064686237350113130351305397882757892450402175050541\ 288737341309701672221931866581780933979550803293285021753845846890849501971096690044917026\ 071072867690938930530262054642795539723046329677908373345106230696919139951334015326849976\ 853644752985513912610914704664138226705254945662138629059724861104529291168148077214432191\ 556094067605561762428461244836704112445460314492191734566176933711529367446845034391578014\ 069445423774626848149889869479209231546786409495061653443083466918327010035070088282390366\ 725353640405552070454337254468884223452518006113184648295650989905467995926583695647390388\ 316077523044659647430684168637065060435683142086384565563483754958410316616922513388979686\ 977568355221822186678648753788280763395030466765459368488932685586900448910500271695214488\ 162702918468516390879823616839690108918166681333200998583668246140627128706119112794421585\ 338021856407105708606571950127714284183333551046997156171104728603704778366932750803027264\ 636125584740990006101940958256281313479331561064556642814295562554504819577610858667821346\ 038223788117546979014698061847355663629918146970335375379127067719213654469500370837869288\ 798564735693630305489590713287602117990877410972872095693593264918675247033135457614603825\ 479990832680004910835323223002558446789836775887127052689182540991787467645897300385478071\ 427496170058755427621462452656652629510705120514181816945458854532121213586927522257510404\ 040209174830882069447664445158331780206696071720248373854350609689361561147986781484025744\ 803736778842701742546800546539623498215040490895962181977774719639568800055513137003222664\ 902494647385182997972043453962751256101983776047386102139721100954937489831011254181979237\ 522212085463274487414980752927361669885594765780328036872568030937208729590834434018459219\ 875122739141696181439949795716512102684395051831848041533336320918683681798741712488555611\ 457966337273921301264359143829564129320150793850299463609004312011996709076231964494601447\ 928898709669077901911947948436198570683107369938898348619882273473679961436383086936539295\ 077264792422508666093770276348050934362536038158313939292545986978946876350653325517906907\ 577759604003516634979759086701330225168817208219598282810013627005990105269122815882003997\ 895123914332399777900330589829077390310902482152269872179764775897215319319335129925700976\ 191793132802142407240707309287040591400325339720691908669239773482432847566852892743617624\ 716654139554105729907144407595379797813383835909426383203013785701060049909616672563311609\ 431866651014834813796176955363392746035546634607850097617912515427797200103601033931854791\ 459411524458159668476854727477487280337496421711514070335822578782593472645679344532781996\ 259906939784311553246528226676627350655869368240701651878293978605404807315121373682745367\ 026911068619168745951418634259086849048527741346210559602383702341448325036937962877244448\ 201323647437337763389881937457314044888301763556086593593388528571044109903383766126278297\ 903753190424181199068068454135448348114482705628533042487434360091628845986142570797794087\ 542044386595112887823848503491811194655226967898479093836020074113197068040418745551382273\ 409394660309364105803272828875463024772361962642804235027703413814964870094755369058351488\ 400839743942994094795831476831595776689655039041942511228047553790838781078613905096389469\ 205462598917901482750960816133560724098610399344578581420327253030047169151755490411142506\ 825908504261244955156446905146578891917425751056062155646940339573259566667169076790817108\ 139077723702463025099694328157873508138004528054626496192733647413111239081218337612927421\ 674091008897108637434307162845693677797795692354762285132253828603208514773625710230020722\ 239385303943166812681985395933862668047315294832152524262496659344092356540813121453568368\ 570427476609811288562830611233675713382811032811405783468681002801643984680655650958929211\ 526769835175698413596300470985581129542625366573419093627793138904478728749471773766711515\ 475119655165597811006551374411450101587903885246654524655130879220785141960148463192233155\ 253254708257355362683101025573792811706550827733255024365465484600888897583651175523547936\ 049676635318816752701034645767190387406079644068348373088908196566491875091464319013088414\ 334635734989252238528009448667715239053755405080654887027812772031793398388431305061522705\ 700754008877673768418476856290926072445239232218838615123693077394641116349288221087255165\ 987936788220596408608844256351442846640311232197775525477317170455503487461334178141706541\ 573051574526569715202681246182950291540368143160010753589033963440327660081178282392784989\ 786418133950196666994502846835488683484895939939381335102687049178177493228967145083318501\ 531428488075732228606093354416042211916334058581499289613347230357939063273737732174457000\ 304189440120016672335771254170035183643830031003899575661077835661600745929121572078594403\ 401131491610297414718813892009476795052308113552421388142832726092468971889179729418395897\ 170321150512787335697909947154749235430104522807195684173334522393230690959646054001638389\ 157130045814487664196598546153667299015052079978021572835969348092662447831520618406046538\ 743205133719795065110720491409673729346388219349601556162761126518623762013445550541426096\ 866572628548171913025004217367656107808118815036271245565338989349104922522969348133635195\ 911796146544177372772928182698723656156079981566565872511568918614822529781787357834673428\ 305265035349326042285939683766324448817811205776328732734889299504015061312187293493613911\ 797273753052569784531552875464290783475913710588828315243424419885146426922529755960253152\ 869653520835950409587189585223127397104699656436310414191880323888077880481240586032538790\ 240662980219644995237734293236693514147624547964977396333742616458518956810540654145043054\ 202394429205039103644112999809204762548209432928849948627758346263983194850603357763378893\ 804368082012757183618929421713254985389910360070367033118488143381903045209669029148742069\ 526774224568685217625009725566004175944441964134290697598362041950230036070510297567418760\ 508670107610495441510951147097807072294809058464096447291215960257000389830882606387553195\ 081487379931551996418237804329866274208088372238755708841837016741068062738506049611240708\ 661621993695039389005596562645832680931795053640827696002713781761117361779978660771837575\ 040954056498016867214859773971728723401882072598898679372538036443221366727787074625343176\ 743986993932691092922518238614376256391098644596884717559858973821004428626002082853544271\ 845736216521026852618342461640318445660726070972711928816889589040282119822069775273984417\ 897546120313175532912266024069889346996900904900177047810668770381177075474538544947564933\ 912231450203804481747229975369096805333317816576536030432983762037028929083484446532383951\ 994582531587170585618896043257574779062262042582556248887373959666139771745034987200023988\ 587570009087752197810191387687420058527009595456324654792323616390402803630312998489117721\ 945476822669023175189221261322035708470365382533895043962586215431638022083733959689604335\ 808274702038575515508704776903102893165238790403027547864147609376027562185664063504781566\ 805475247709673996211486735469525378626220396088218290583564622831298613942729421363195400\ 991877507303477645410347745114660973358949081920858964190648046567656704390885905030291909\ 235550419132823638605913286325284558771499042482058508725028825937640550483109291681617121\ 874254970515745226086991672606330054087514824968837487167004839849023114452294617330968416\ 539702251673504893569522143872738084919122024223832462285791992983861062267250687601248318\ 835841915534385432615012385358087348416559747423953598720019664782789682400292744433116343\ 679205410513002945126275715320178462890835164227973069639229586125746402100797824447492781\ 712144879480751815384106733445014815038663265752436713987592841191843056418607402850713384\ 761270616094353130623001975263970014967960006598630985918271731382167091587832475273652678\ 956585347622397309805418482869192447153890532842010001622777412823785372899904995659634327\ 865821133473298967057532387678638361103880075753434341948150232332774665986834053269871835\ 030722778608264785601879127309815044601846240557653260618409785535752928538685598976082972\ 522253668502044715004670656192785887936168343738649125044330500724537698061409255704614926\ 545357781029106313832012743274011593296962376897442865592391997052358745449913591835350162\ 518267444937029259870615692123530043338539197151321910011252626082228712636511688425057368\ 003289626341468996849366810897633477913185356699911630154955361306784681723846597935676765\ 395381111856124317822739645175858546535954438530278608470607641763231373592331592142311323\ 442001608066245942508235499012713144191940330321132866479524791974622133878458787414119636\ 470740018994004200429624626561294680534754417115841953268916522295303985924302312357538759\ 286248162982127909072502486102358892945229320753783508656681487736192647021720141619653228\ 575689930431400420679199230240406041803705389751273223387334740426422248465566012298586399\ 393229827035328284226661157262529439924122669244207615201218557902696129512577936801911620\ 069632203983816410362940678305347976560000450980570135580102860243767098900763664769818374\ 979890824838100094772732181161497728855197224128072440884255212273232352386228510927718371\ 803794865497045667676379881489047938653253921532556625207230094028845793836345817907067333\ 645525825107930125039728057768641672196131143084755712500187720246655499386212959412813535\ 664612874971511941082791282463540250455481105300063402868637261079684201381107564751470650\ 464812030127919142323387435597989691164405258221439726404721719450520675281049331965058570\ 538736257004497534276407709257065503751479920195944648842458417062585351602587746066939490\ 758774881162381225548848834507942456057983688019605907602516766081624970375289321070701164\ 233686741651854396566584828538787888887687902753753128514884083491569032045232590346288391\ 277556420124600928004104309098313545604711228999096115794561757503563543449850527739765286\ 394238027577731402046665013295830798047026523140143475429240155774581541649025824241052662\ 229044339753268407409490138439860374811628924230504311850661721421248459192672137755629543\ 000730291234355481197461679856647964393831900815932055654129087370901173904845183884116797\ 376054494790723417338141062866448024058357076678138698979866584954390861168480026574657856\ 992293050953820082710316735872328089959170634105026502292341436200655269689124119663834228\ 202049732405591471132221273826213364420990853873095875774308475516946790400730811267882072\ 300395229821126755538999963397444013510290478303737114150376149350397721586539791131141731\ 351168935506300880914858376369374279448860807065967591778254228720676737827527500880892838\ 684661926327974263053917982318955765568213804940287492013103440816885478837312056198913066\ 344832559187113588700659045514498402201324886012017217446020777732515544330354225550944593\ 706457274853244264459797375097421029358414284465213619954375291979097554807152776366437259\ 598821188010706387375286303549351349769062495721421065419019359986730205133318964707638171\ 722645346610717864203388037833115934211011329537013984304487504602766562074491807828097150\ 215364061426213379730642639434690142053328283948977355611391931619228518385040280754684837\ 058933181049038449721407680003874967254090113478433541687424481836451234834322202675244436\ 888416759100643939597513849836325993543610084899948049028958997054834371177714245154007388\ 796026719425832980435567598423636126381482840791398567797471633613582117089160323797908955\ 321010432982899958492304813564867929223137334989737890937695541385154549653321610965385394\ 358781330883506331653321127956640643009244209101288789620980195584991501232577336404361293\ 324186820361541841181123706104875506734668499051687479002623604622909191790965010802221836\ 060317019896236136453035271672284497373240452094171823032037881117625160155618610664744867\ 218398658759717399132165011976645279208298029524633670225138996435944507436060473055620400\ 558985739913912206142454439245502853560954119443694582057205091855111318988797338119746667\ 584702068000917061729295794867466929801647017749789467028060090220061047245721078121258764\ 044698952474752647018612299793875507461055231990454503110712701669388561909246173524795041\ 025832930482653304844933070004766251559381942131546408359546049385664979784997753339025046\ 128571167588774849250338752907159073827161797861165717829283806516765524139800350663500472\ 696056932217613201061845098976776413284716230715676950412679654234151554339174006678410631\ 143482177314762706817759812247438070444310226352081127170737732702978815708223851618578960\ 867951087495337472155133924294595299556621943305057169209540613779304695273113384351116875\ 818193508305605912778347311102177044891853156505933891534522984733043365821408583205628279\ 259606777662275493396077117786016879421910887787832634695242631995528533759475530320910866\ 990932291370286271608059747151798905542643533382893193652615369279786203767102104643516183\ 854188251980254965023556055872514919273532769713905892896686367112393665032957354494857473\ 056839963077807492469863994369575550815628858551976029271143035321080867366858843628800107\ 593851444651405348130943640418645806997022865278865644010686889015639285999633117895481627\ 302026233450316863690537998950824617891104652894965304602637410876519583586529864963817190\ 164709391980541185067794323417425373078953681118991318542747373872244414376456701403715978\ 355178988306012598464663243644398067985361979506610939875762574210533212865406942930438604\ 216465973914679944422876151432387489080825148997609996331922328611602012516415225936074992\ 989885244745892561470126917717900238246088075881384869433981100321758797804214872357064731\ 311803015167235105570435983749306219904203535368682469274835356983236529004450204104947349\ 110129395637147478759305711816894520582135668575547567812179709602951894752400910679369292\ 089307848291072064980512428980622211833592767848858377093085305076605032861462776498803523\ 808358869576235294656851029057526153886347373634911563199626498006237226838133349318913461\ 691958699653612324083118067766513550302383615847896383853810980190136106503060593997967544\ 866606442475845293815915704599019525279188877619080163388503503735759120340354473736257582\ 885353888657571752591979271050162212959738879177129724427820933280319959262687502369734466\ 038407019454588520875836685735879325252395818982712426055570558870093069217845810075788559\ 435355847846682657576652702014772691978250005513370493198397393524048351920569139080193210\ 235576785093732051024074057519660685986829324888141799364143244054525387032340352369257969\ 416474274946402982271253832881854382875883762647690776815877982513019256907892958603594286\ 793318785015691782060993857611664870671144959706918764441280915224236555046533598369471221\ 725194267208379288816576748932682780785654101617584596332630832801920734795110698399503112\ 157855992328934836271015874379576524534480741896748103177137856141355255400388179020534589\ 684755534680617228740745249530326670223892112958227668931553907170000680071349615220106362\ 312355744390518299275947736234778559656989292144919707963677049593674271096626937137430231\ 653546459364687627896714489043866010348279766454379034841869268294822604157718495180157721\ 784403737535579185484450092126116565054172089839964714238509560373848835363679558243031437\ 592189926170807813876377610934978934501904785629881862283133868803366507805218267695609033\ 432000899053293962372318085661632609413063771465247958473180174242844665495253240208739005\ 408994850964177591745984035723551326885114847150505808960768282816026211032591525275664971\ 557524290223790359906777959720800593016248943466360425806103837208208342437661731529484288\ 680790947146955773267823307793479082244086114002736901200374586369601060006263408262213219\ 282081461272052124029099009776006225436284347348287653044690426707658206980911197618434086\ 989196621879762242937287697152085425280618600251335998865142247076454495849431255043215505\ 957760935160739422078905950443261531233820995622349193302578308181398432396796967134780822\ 073856716567371009641950539650753485245276393689286438232134036375821686593110107432825057\ 673075700736448009893877169912136736344409286488342576410622454844261846274866299717136827\ 073548429099184860559634415174917940478375108503807742373576697468654162826523746243761119\ 285235801976546180146506208692710556528139446610642009631550275682230100841060877920113083\ 834149251983139108575641538943874126860892737288407202739139803988946516770275042257823483\ 486997038661182362863642670609109526677611237454100706292972759849453019625246260766109908\ 206302445609771693333269492451720518137491248813631253739544484888506043823233988643129684\ 152056711091442086322813513698920306036323206235466355926913563550602518804491838451636211\ 633455754117251321174121249954245940384693735445853882529084948663411567300723117164357217\ 548435449389467480145002831298174264750747785014381874425364093402690929162640879207200445\ 776592614643252134986683840327960804073766331005432421152177094773458006851982966068799726\ 112960913269023913310388937634417388148355871665563656514651499209998457848991312959808691\ 694070689188610179605860655422841689717095416683808563145628178634060934252424697410042445\ 060450378635670902813531964125039538812907110531811064987808010734658682921232267013968272\ 701544006970734894954545315288671260635678832785976394848646153661519467186663678050136635\ 826003877720674444769947305630499066595107623769547014161382543314069490424158215530022680\ 604020635881634799492630324574566540959658329334973290972238933738689446328993567638192888\ 934925902189474069301285723563712301045194446696421857938426775161116906140369287459326570\ 731451727330342560933372979540167932939250871514537784642332571274031517459558922143259815\ 689175685990530589451934483835721893254793944678828581305140537118348336705096578996061695\ 858723123882713906361152433792989602747826994194014146443214448519398806911432757013476096\ 334389213885431166550398304321416587157319414541205209673710544791720931692785988356145487\ 625442114777655222063813778495518203657344728076283761113138472159709831051616301313784518\ 632968325582176212988166198196779646941023035312848868481552951898673469372097735773434089\ 894031285605696687061149999451051226513835957110612819403052474127239028755915310514993916\ 116610483489947597295892410084500438250396073891693226372889065509415964304316723803771737\ 660146339621642220588213340963015512396559907502053707452391076771170820585519826383620191\ 111030558013632593961507571036711481331223901260563059502323455328553218467262734345973983\ 667337413343867590141623098769104106285699492574418891339317110974413229858042629190133506\ 191012804891031157385328459935042694575927293871848349590285169972300433021859319822177973\ 445312211820756960273576882295314070175800078495190043995735400461506811197022259541270449\ 080658271068318720150685941971568425235830816255625090866307143865164947111915989960801577\ 124911678124807040509337805584372329086432145208074879308243365701293249837402609435383780\ 262850727351774836380357185927231718168473810827135357314877652383049747792035499143209570\ 993816543512288049863389550581251827576983490827453017377740655225270528554263878889116439\ 495529160774055865900562513375141367942028387267048874588821022231000667955526490671149670\ 022667151288944281626333746380920537261943418750782330179773564341711788109192946382550134\ 584697805182220240014191185191538229021753782339742955324162367677417396914442082561263735\ 311910918897215914980031972718126814852407596710346836951608119579758213362421497661286825\ 847975925442449494298918359088549452411357405218281371584655048547060139601383062607485493\ 063225014001881390267329868883824769877780316844076055967980250160641354045202256809270616\ 201730805717025468790963691616178942965344645895405879957444461615803895063329934405810769\ 625892170625883267322223106258628695642987934655413250982296975189497698290997235610626095\ 211589033170680799066689268685433992969306885638262735276616165958564152081678269854409447\ 918276494289122680460849677428689642066413127656794508839421252853323513951015434757392140\ 210765992332279727228297996332028186785538336331633176232920064998085038492360428504848498\ 073448495092607969215437103114039742748939296386439742263162695212159282929475268874066368\ 431672535138242426721351910695872194401493362945275312070720309891441688302926891312344905\ 475681461545073742868173099328472241268167985186595876846173017367690181320417605801075791\ 339936503803229442187840714622425488391513214282724876820494226852083536569337926222463034\ 930109941629494342747891138359194023218680635222197224028866776042503751500468538626369835\ 207814978222247695949619160228601735862457027326082377776250672080339441179048637444892456\ 214419622988690726400137526438797900199396815211670157295976657899266591716361704725696802\ 550325296901034510761138717012726829976521724542002861210167344159304069996002635321662744\ 191920910199360395920503390028154170667565264039383896027449599548356112496513095213419010\ 933746946966427814712677171631860976493368267422092531698554615839557758025788071154171673\ 980746661426793119213341121195758178138377075367399783657836311140222259650321743778055495\ 041980067392929166048779276390807796144853598378896422021626607949862722021025070453418659\ 431237658629499776917834482759177350635740797716052455264456026770183488860277107409478815\ 993713362475590392821206210975664823755188792042302365864053216398584303948323500861332892\ 113011467729824831314484043171850153622037811045751637539339464936774579581859047817462377\ 568860614034281508154676175079798993829110080202595100736124187282003271370987314739194028\ 985899348124430838835677101514005965180527889455478103821908142002423034934230249957192402\ 199874272416865080855175822181543116691963088051055211434164585867143918890570504620143658\ 076923837767104419687590694345424152241034609713426107732348351324463907242193083402118740\ 831649155312845140788596286844512233841433740716043574747635502795947515950070110897802680\ 499758207842675504680837049811882228687905600152485213518075868099203132631718200703450220\ 878947640082405523631870248797216545792651089836719670045229445527352980566594342028822916\ 759793244025961988991307777241659565123851490891365873957242831661307525242949244236883863\ 074930285508649943460309207344247758371421216699564229742112278861069798945908323073509244\ 536174708167038310462962458775589269123745745250921259036625022471943221741526683343859533\ 037148343801805273952495783109601915262056455157218385171017832467399534989128323375265413\ 236722339054595624318990856122054503232795111167176061016563701285772367863094820004532588\ 853013535327737866735336975396280473653252752469884498762746603152416849018243733160638163\ 799475230544083035995664644866333534107057150591010823722562044699638719434787634655363321\ 946930487938751559570999129818893536665544036533810337504131459951215796391890830360999043\ 251306370571394964856559918305641692071803348508876153870104183969534427394415052078937852\ 384290056977414826207574192342602422324745760365399347088056278619707252630429325739773545\ 779710380777784904920675138644873684796612631427693423427344363237314206700186198465669410\ 754388353725411741662703818579247276128438506660421640330410308488284968449451929831613717\ 143620700367976620530795798245716886585167465805008842667759813823996950323081206248732777\ 196617790794700049050602497113009007945378966311315853821748993142046298271400198783467438\ 480463713034309656644565928098431195730413993707449826231310903613439220117273672754572156\ 283942876535631682107523071603670023508588946291217921605050257640350314955181214044957573\ 630026279885437300506671419263205154061397594775249020388459079646539732156240971713013181\ 633856674725651158298200391721187803382167115320217641745965393813101863614491713621962221\ 745226270246285853866895174920269815241523338096984766339324879894144815135451791521655321\ 199547311592932617123914340523088024355788623577255348944987911365641577339604268491451269\ 884796657284927564607215252192854577610859052413161105342355484359595956128526914396564266\ 058414013231114923842829869578703708414207734124664220143747741486654866411711026980005587\ 114182994259202098441503240217871711211136185071045553090628123288530158876016543132312862\ 339268678679764009343529522140321198239339460110782087709913996148465089095469864140232433\ 336510305339332715050115747916941992208993994182843010276517160912122185561162073883055198\ 428427754503525905221172366968493356679647521204620154147658994103333001026857943753445956\ 744767595884182909203831423606051791606115419219951159573272885496747544447947434152020410\ 796631147972786963306430731020573748219854961084763306068375210800579405583630887370738966\ 440147335998517604756532094608853489335299743802751248335310478666586001854381977167595641\ 881531187652209330345170489157475303103221786142224100482453109547880122933426253033482590\ 864829468556949825793144110587627928767941219122281962621286358758160539596894708622093484\ 539015071843010446799572884572860952827928581930844346838624752980364782219902201241369325\ 506242535601862254932690692666523141941422723737080529588461884577078656885747651705661129\ 232293582969646666758221538914793225686142532388491298425394256478776284780291437892478304\ 743350247240447716833125868746409412739744961456416327837696826127546159624548233360448245\ 789770577484863598240042240937806195732498325123670172963396135241835416730829265162854030\ 776010583704530020455269062513527405951036149998919680164184244204706981398933160863140937\ 340588909547706481989363256622065856164051484447052730514817549167724560210091336900990825\ 162200840051421714251692729476637415374279848199137459869230189764091031126902826129640388\ 891542588232076436826846181418554177407910048442984627591801871722640768074014132486550376\ 485881798489747677849950648541140668793193474544335249643850637004296967328758756321411977\ 325959192352218454603003197607980214561638551220717168391960045995222362577528582888406681\ 440021249510437743575897357314940167168030779164242591339535087813071502291265896660692015\ 203623709747610771118467268578903780031661223279963412000288012563084398943277222297470781\ 382172635089686762092238016070355493881888081083840469036099200176033826970638253212720611\ 828803569387028958918134695661375744763681906383179588146318373091922302593216969549969626\ 683607403557096773365238543891245865722748082864971965759474417624851482928166448248583688\ 611455611525202086430295827455595567598714683342668521295069555416756988683695315685694594\ 244700249924965155241973953489009832153766406850250047036298257270520884602070820794708605\ 772415028524314485232380962443978770349064080040222124290605548440893515535893639503306993\ 494158285752075790899979788821442369247064074502824242214891030615083379605008480423194065\ 662909947216082833343122998176452635969573242852427229596663277080462587288786605325967041\ 242472394759696715718586639517317200284885109247140976729315465957457501866124772010764588\ 621786005976032827713367122600850666807369652100830477048632082765325500582952692584397598\ 612513281576135596750657829863699810732924466784414942701957510939931148158547484448022033\ 977931879515949597465251680611507071573544826160359563288230510225496105153232936782213997\ 007500792983546931908221666643153477807721279577385002288627595222474879141726267139283306\ 083182512772223175116191144603849166570431293384498409436406360209814467610098074888465872\ 200020862521288520722824453721779789418124071486326005575186321114411252564130679902383269\ 634354416592793353731481284773370131322779333627557704740948554273462048190118138002190318\ 941199859422369168705655092792561671922336888025771757078259100029373074930041083658408218\ 841635231421874962295967913816738423778457510295260332295991322570774769989300706863291073\ 274730077563074844375204087220441976879022624635260439548828705034433758275470459688781971\ 504075797834297815236588798464112448482968546277555528853755579538391465384850561353284337\ 828449543050635337771807520421834793415857203787096162719505451705769845021009353726000365\ 629722509362407502621626931756351353705421933881023076057155303466860016190296837582591568\ 809423495285331178676679094813398071454931634322688470093218811022020588887744027567120481\ 050372078888184546166909772274384827711537840573443168879585000184300505306444947383425027\ 346794766669254418510884117212672586161045978073533386662612135573436000308275641949813848\ 194039379725881246836992334979943793806163942508626095363492967234107921848103915185198232\ 404312495012357370536214944161909818342113186141268182678938435679936601378022166299866027\ 689307149467550495181173442819941121505090696692023278393818394050743940389817691228030887\ 356985461770719685695690648380176698301713355926237747778278061648342657074769859896241078\ 683191246648966911891547778036854688166667435005368785330855875257426100152573162542308285\ 117498717524852356092485728359500467341962522811663330163879076388451303163609359651960034\ 258766509117931213231294836477357572936223867334283935159221935880322360503229548848226215\ 622244933738640073555120160527637244245998199269632497296649322219368434994141486295967015\ 594389865671371900917920406217002725954071716930295714267429354440248820635207756049374495\ 367194025468925785827328353692371567286454725580943701164441783908854966207011574917357045\ 259172497350550510255744691625987190785833453108191679737072689483250121805476747531238833\ 807037830312948335838854790915063231880992187136120419691288047256462823023511868624342651\ 553438772164009783951213810953009504659155584498344723548862160086506531703294027628845380\ 105533746242849630687907430019051334409240737303302821171029346761520604640722321139783230\ 540682747303736831920688399267136280159696936357681593543121643249414200996506130244649584\ 376851172121790453914569420296860620332446554660252434509250164398830888127761993167251842\ 918251778080316475537147324789285078330114039067978146722216283325975683380805138732258915\ 227060702437230999132008198373752985834207364110395710013401108541662357049928179314919553\ 675352123666053611942748946311246495619395639544342783963990130814762525143657881094336728\ 005121581040725980258464169111138887922357726220447764418738068653127743930571718513265696\ 058525985412763215777616087223376709617625202372834010800038457098502008727978515917912076\ 158477374777185823304975751193924333920655776330255889889819038572355589614813580638021171\ 930328386547986048135651640016237241542257013429923557638750784528748890814376018563453954\ 214596242754816485225537643040569381112203227408707177066725868278722227100167898828982526\ 323265600479664501432571526686334616056101213371737748433640228713055132339081403837925418\ 163328110546423606577294374979203146731075728179422067059032339696137958992712836082790056\ 132850788119436774544163293780089895040095196184907260404714370737137186505557376398927575\ 873953038719422200903573508885915778768674238923369630909425749611113054378499075449218350\ 575262744757419667367225145620032474310245907348701425166190115493138055347229372822784742\ 311752563953857789757641407911377337430045135367567509103039464941361190577285234927563883\ 793803777115633155785038531968739973640265863843678214096988808276487594994341304111768135\ 515083061668463666802036689871912276053930159160474272573797854358458690610867563890075964\ 565034680568424757604845886611552435691202254342542413791246074640866115378231589822913557\ 413112598675240633597608386957214963799528807222127109281275192209247715570942241483158518\ 613051873826852021476885091850035038913101326759999634999613872694986005754506750405248523\ 239594704667208546676794863658621674150707584732881339274262986736020455060676576831486487\ 036059057737449370158778345118137944534224672887381266877373522517087908247320902217668389\ 955588854374837935086243046129689849226565621229782135914567474117611126874186239857693108\ 726105749057694209132069101020037233944668244217620767433209182058994136750653309226830858\ 845559290225915349838359236610339153778140787406131817806420554560484447216522494135103118\ 745415184705238357304929643707316342333337546797016248538070257281697765468470412113293823\ 511315205714106546868031695760564641836655301075209173786094902703151395303703364442687035\ 850709841097579351895827338192837348094235151854581379066861638065906883083030435411887408\ 252770589038270160164391294478038124983193351966315936586995059839316288909455532640728332\ 515293387773416533447659399770061832366923767846328666181207715074638354199769137128765757\ 489303647494688534650937161641563014937622216989373700025734766021737763900727886383064620\ 829157795304168815585743803290327736836207340803924248565553482355089905940288375961923087\ 575387414201139309985804670629023476295842412412553049439164952462617899444424820539215117\ 673307869618498065438953525324903826776406903553997114219569289775786648858394897939059753\ 848554974025104048565054904734957391431987877832711897322756539142740918807748235922974330\ 981415871386848151831768354752286473690913849983112397811008456105591629295960038611355845\ 512671078590587246219779907444070895882053220992788089394563885675741686680940225094261572\ 629931057390084625757979825107111580648693076857320809929720359245030891240941490603786411\ 048998551145737805070346864076740002344952511245744182409852860502510957045658535070923804\ 509507248985376923385576176707217096721517594114884204706832278719007993314495624383905592\ 758699524779882584566987475755716590812674697775754702481414063897444622102415726787442445\ 762492581583964578348759099647873689024112736801173764741373387632250062949681062318995702\ 850671947782805710519299146024799571681035464837973503625887088545957064759593211663192197\ 645235515355788754980997378396149542292536932624083143419955730765045492022404936539791279\ 112807123338097299430366422840117467136877471571488459242125401907621000954072879013677335\ 303455919757445094356858702360242611838142796194367257525122450332629457803259739718923916\ 749037513921956021816970499003338334750434149581950502076601183096432230556889924373006687\ 287274369328108597718616009755658957521583437653260042907459326348798607612624927160252050\ 849659057647221962817768272115441474288832541410341284522290350354764984604345407713936889\ 450633549551745462426002476812668304320560559959705969254279600395205716241021134690683702\ 693065413906726594739671987617025004919349812561011976800275556378397599798510722151986674\ 042595226741479334215879697796482822695862602392560251340403866288193510407162857620520553\ 679812423844990144681780416513486831962054127759733871556582550337890537205133566442073152\ 645361331337977801664597007882460817338579741274194055493476955841144058646594308377678127\ 853591609108868412790225034743659380538371025333424567539419414296016626749713658509229374\ 166248794782635945772949798929872740196043072491571748201939647715789068024187766922439215\ 884193345129277680479573237008250307649255143668482464216064745535025204066913988913639163\ 368905332704235376967972083156602897045243381090682302701735880171799467339758653359030877\ 071218627028812912196799159979972944059080642677261021119582546265000333678623622013193009\ 428369647613020082470279957221913936707941610340233740726836399028283573589351611366505047\ 978342414054611825884943519155916814427953322956953608063409751330345525519537162857669026\ 114890242970928354943408491600898680748749134846704884385215354633440023451158947766122557\ 455756795229992560023889862630807113289015651127944299483964525261234221593545529708936161\ 349306686895140727229260672171338224339518386612778711254349073867847716215383856621358336\ 612772783708444107036556899745056042741383064310447375506565580611012047663201236023875766\ 960732030726653402404191685925396774951523060606833973755609546293372508308470935811305292\ 782917846463961308417902523067462260580877544598103628979482817722457520465297807936656823\ 687584457229743313817231072091934054822811119808255860698356888862558375045238723492949643\ 786943431491538336317392645317075175689507141721496924763397237506104892708539493696561302\ 563244888608394786338807732277405694371670383535225420937289429633107244264413029049488603\ 232861753750714812843565911923925233318574663795076497945955907174121651597658585331785885\ 449802335043982170782114946412816960648708596083299569029266676300965012959564284322581268\ 273897678946663616622275349626043126106999557448178655266915604108638370695178689004783785\ 400310305607974327824557157515101432741993812654890291641758312601039495242355249910831570\ 277905963283261032767603243520418850072389502994554484535258549947295380725173977617857051\ 721628840475251540386961255101254706523434957765809557100440671555003319923671878791639768\ 668709560957467133706660327005171738855737810993335977042116790011236198517650927225670240\ 558634057717998740757438259357565994915668257612258687394214278422417448044104038550322681\ 950132979695845779673167764559839305963722763954588595827449780057060206807437158177796550\ 639928851089120391236550453137835787969049970279758183652600079201650219258390079205379301\ 027145044745227065820671719305024834050755247292326993978424814422652020716391651030834234\ 406885133844110487760020504445006692408056477802278960716552858988828479368933522030162003\ 642836267306545228769941284745263413544100794263775260558762666737172059157636664931667275\ 928160002903321701535914206030705828098305383619922402209175109547945961089658111083710529\ 817341517462145165618785880964476434551572312010170614351264100944391005397346045674534805\ 945189269362289080589974827622864095418161408495741367592486452550286505114650195145305135\ 096438367628921425172001066005335090071954348505990002723796644550786077670146427543007281\ 714334411531951070805027734946839858114322147331924105873473689075644929140597163572405967\ 690014932624169519309388797534835389636346245562266893071447793637546733743131923506861658\ 582140078183111549189634271080117585691605372909120213397497523348102156930264916007746587\ 616486361192955787702731147250149743440337548418142955816883501275861337972242767186558174\ 631187296435763665739365048475446247220745327187168820837510416688245944372105997275459913\ 010703232178142743545893132044539057889561730097265053734300577300663398745646344120753852\ 679485890644741534240786072337745833375257885409076667472503098863043291091687728376885215\ 648613558919374992959081283437027822000450049045021486760945656678574828122674706265458560\ 437742534835547443143124019501826826411820822897709881524366563716736727713572331863847619\ 509185717873773217789669831462357180084527102821503483727925929688815128927302582960427720\ 829370350076165606097743131247603785876180733362971469386283170560750805774169782773115777\ 032834379552092486062038667619691459956701497746646688883775205851397639634310979433736932\ 215823512685658301769462712086360113528580665019033348809985467776067598490283077121018394\ 439210255210999068498567323003043707853993594878028801850851083060807314389576197231052949\ 810107001640483275199783612174242770644062902061090630424288375760959066019492125354913721\ 291531303541863878307815340827318849859354824634744671488288165242143969153822668940916469\ 287885282197976814466477055263822612352744220572591151314172977793469944350706042725372596\ 486983054524748615311842932595681510696382376215074891881134140020260210982066324103938181\ 869465754022710562635755378161067658224261788252612963505597023473175198069419750654198047\ 783153671203650973558442415420800069609626661974235649790838758208828705313731376828130864\ 980697736978804692277328108311884913041208819268042274160816123919031549173428003025987346\ 352665235754954607026980215133144180349022126899041001637807600021618621029385225333931299\ 968080274149753975121628595399866205781757213839168684933235499071840115558070312151758699\ 979854189006998191212856384695381664866105347753986261866579154055768464851901942258968233\ 956609170525159440640097774461542675690118505538180646563330330647047762549300849361255300\ 693663896100271486336272502587559540571630364750593676682636328117731081026809966362416310\ 800681248734313552865268786083230282479926440894511250367245029223591084129219276187638397\ 982197897223086634516198314846312205576808365442316915103253952726422973122278880661027605\ 644711908569772862670056818370586824676373324561184165155148816585471865243381914690894087\ 033015351221686947365996737687577357665527776884590974544534900904786072889023630837190934\ 800452153735686043162998298142853895761259036488152866893049263011294669259698081502589889\ 549983123087011699370782138238511176776756850404339828536680927018842316086403759519437432\ 708532101895438358536902636652244749678598873960626484687550715098314234935964301266523258\ 366185289655747866196498033856047792614284566394969169211394407037105330436712340273833024\ 797343204692580422110306470109504647324791688865962674158301251808264836599096339091676504\ 875008763744935698882549796877154577856300685742812333324899096774205510395592484115150256\ 204490300513758936405489214784505743485207696657584169792984432657469009833411319893715338\ 935902706542186105803133375161088010868504280589367984571919628848540299805137496981271005\ 084178453670157790533666627627903545745050281713322718874448925968596269108117391192719025\ 525540150440635351588817527444405377190753595038202502349418664515007900910531208155341998\ 042121875956046996974126408217442370561496612621699937322355311514596469181360667782762616\ 107773746806428394720110567481345909042296054095157701066079529990682551562543536421591108\ 600947180825141553470371192460503436361936133183212270639765008466223421490397812472464567\ 853684559222138298061651971448396908408517648174243285148005804613298047314679100132698278\ 043964260654736046833072381815562662030924078841307785971486168997169179534460440131649506\ 975564806175106835984227947017839983548535736384610232038178044827953228492553533970412814\ 363450383967218425341805746325723089876541632587516095976912698267731522575516343406824129\ 367427583531052454621183406968560118906190317025526611902778794762282977329923906622829056\ 795886909414556756427305992674829970605537260320911031492281197176566556614917380887542456\ 697521049205963834265628402447250221548908105599431109187317655499089771999682240916966063\ 349913261473200904074000061420379514804633443199510543068327644170709892392892952789135667\ 722869907024790499708119528169316603996615250294572281513906289613607501790518531489044677\ 451987162113501479804059280973407477482936793836315543880412187176861554309155814435206887\ 203079723800161281286930815457721592649400264900394028165145864294240577715045149021957563\ 249897467826039643841608891807845502473945399618400145109686453084591497580557736553103337\ 584100376503186963138271468493761006531482335893426639327982408509868442577823993984735599\ 468157072918698203090879893451059593994806490722903145113511887984571878602452679779138169\ 775167935716453991470490182025859313873874160048975637460092091636592275114273838208255353\ 349355597244136143948922038033712587690862944231562545077422392125075566038258555211812151\ 090554924560901859155830550314942237999201906638008220551716247410005772945360311240922425\ 104845420517351345602882166728415002092182748883683772867327917480308265539790657949579553\ 078841888935312555628082799426973996332441310344135590372674991508142506059786757464718273\ 265909899790607968809331951511512876893361628990410967034459829704814458198011082048942837\ 406029405725936109869321440749606160939927195780580017586124567701473147758069771417486288\ 901188703137498739052955999835003777825347539263859635949832767467401193879406818269780502\ 264053642480776371038913654028000063170176460854626439799183002971968334725873858494254439\ 356113496834315966434506497486453324874119657697513341478450004663176352491121330832549655\ 450937826987475115327729338280474405726300857745542736747445009535828626094599622382009408\ 069131553312277795816789683162603715028703718918736573178027013816333580611220814088357725\ 998701444618923351810208690756176163634115623404257373591799692706732074232308358797583497\ 905944899729992153278494047405727689003482086458916410946750286876880005023576602589247211\ 416381716192579688220691332269033091635657931254981369207694529962709948203550322657834785\ 739484966763615466969487143386830418307206081767232631724450026750369032978993975882427376\ 407471598913095519990130168641681175895608903313682189561187591149641981650495555484673175\ 656440569369630462292245502654311732351440711551111829544021803740683807435164704469879644\ 953450957513183703053355802792400502933034855702232637673569309770340652491476726018099705\ 933301480836066473389846073801546160196508327332764489655202522651464615619899073480906116\ 143518385515147335222956814564091523956414990998852751796019115986071579993457433999124537\ 469677516574712213537286819043763005642320306411985169467963219605292935035145456538825127\ 982664728780296440687913036266089600487419887498761019150016256357421754671388895059558583\ 190824458764318768197022514761066210691231967575747245626374214599942170971178927199212705\ 732372062445453888982016716437542816864032459671268612460663469726841393984115766920293214\ 995445037673393468112160173538723804612967890628182541616799635052668089621319372464946704\ 969699499126915743750904003441392322007532939784247483016268201004596759356946145178724923\ 644288434519193626120227261575245027766299715492423180230618125566903455764280192769422797\ 215869412012980822930019652695968321320963476432070052285676335323221910638237904476500902\ 128263898560118483218705055691430537566255572592340970145184164348620173250702296291227498\ 369824257177220827633509656883598347384732745143548521524105928175666615548175375381667832\ 354436318231202338006268950956115449663093487569348853444573078383968978691229890907243007\ 310359224931866459074718126204370677594323249911616854631851948929523491009058039835544205\ 295735553111036181761257228792678228403117859599421646118738225588375081749900226221422409\ 590511604533009230375215339041712723449443934909529602408637268087468658375769476637087035\ 387558289414335634941536080782746531233674581979047237146616134203795141880568715149633703\ 905639213352897843655244984251940072046778287972954202646416662189063031497470980688134735\ 731753214533413136981870116832658950678200914073131476666915216780297810452227354873066987\ 518888121080223387480876769060815389590208676423255892292306874441199613327879745456517893\ 404634513039214401495131440000652802281599127810272247550400047138859512733995769768147896\ 533986667928731119720266636676154850204711059946584205653721341541623199664157830520195484\ 864883846146834349958464806047219153201843282510726560421268714491562540035488894109832955\ 103810754225754867764146257793244292040489827028645899205541387967062079625120270550616307\ 538302353707199787251933443754394143239953882356373687949563751923937994628562153054191056\ 408325584537340778893892517210433511920217543597550208619447846917409797825153627275119641\ 354351834642862989949266510816297850919652814302322281477429218915280224659242398625265053\ 138421072197746987384733585983496782702041088013077723319494648483055369692103432384316309\ 104928507639711171071596841215881727952685638595710569864127561180329781289556393385689284\ 983954115542268683036537673905120580508287581766911608778504923195938991614506547391983385\ 594818969427677078509844907827699283428333584521886786503110390665656057014122305251660919\ 228191373610352574188654366703414114198617450621137815400904794578782767485148191230375155\ 771980220227510044016222198991636223534675886839487046163690572776927660617167987950088108\ 168103354849767233256897345331350298597386388980985379105808503662615377619459957808186539\ 318458549127297880222449107613309564638486505116112731188627263951348373250309457552007168\ 450531131180252547628231767166755461224244589807418776045212576857635775076194490189775089\ 567041344518690363226451985641657492698403832426821164135370761072835677047042593500070371\ 856228883320121900210723314792473814019098482875948150704022387326969706917461593502980627\ 483732711206827086295133499380295380634562294042034768842257326008759124161098518371090280\ 925360145867359997494499622389268228986663046898994402299421019759313303744868535942188906\ 935630593365728900918272642618789716737193426236579567796965847075617059243306050767951390\ 577083620197148742385786758628857741028558776376578099785030656275095145975435711472787837\ 251158514856643288201901848217522577112339726951637694050777279929692020325502084983764918\ 307045117209379689330959715623172877300439555567190290841697311584024364348339253346855599\ 796670548777484642395942546774799942462359669994193367105530061142447168136754435344259286\ 651567642229946877472393232549413921821470030832434235604729311178160509636369048337089013\ 291315464927744692892866806700654893982773531759949598248888181117195223491650873275749090\ 336634832838657606131067102782380369216768419296963177932166749525656681372631616055239982\ 430108750071907829338166609971757557862246730919236854170158773717705974921442824186940744\ 579657166381939951802406648804200489232876086408917851491837869906165902225290699666755584\ 913880348128421355681321820505515895910666900649168841537225454544094249472098564910664133\ 523169200280504870775175840965396128689845501899436993862721532186618715708063329530352772\ 924074494376409735225837892626163904149079718422547617749012531936982601481578459999011184\ 787680684934639811320367580924172463034329549632203794849334765072246415316493794375793212\ 654244519295777643205782434674157491237057368480196149337245135044952782637176900980619703\ 142091064625129495489810016163322410818518466156897402938579470639212166360960854844993590\ 461667989097629145325001332727419724292186497346787953772164468869302566535319783381860543\ 382696009351539668511335249400366843840257932922871286651820107444434429999296283844437254\ 272796008730305327725023793443682124195099173187926292595673699684944800255654175338821474\ 584815656543170995639947144244047358779945521077421113045407034864056975997065893699858417\ 046964770491024141878773809945807222741644782741897532838505032620903079591600534664417963\ 143945577010490674425833202119886795811176497607378093822426316664790567816626047207554060\ 762372940224790689253499749289618673258666730080918007629064500393512200048097109220722397\ 904669364008876861031074236629280849833816881734375707978515552479563970680897866362414066\ 793745105303992393964219912643496481749744437917023045427550290981753057830730439644275108\ 385627862616940512122572168109062282456311161926623337627773051860467270797246045240643989\ 326090253003587156139241120019703325467663495757541206689009256747914795219052229310375818\ 315474347019629018503512511542782776167257279602283585529897385765011088200998306003279625\ 376028925342579080410086764860605742442624777234083282101798211614113953723350461495125106\ 370181179498556409587180036283907808693604473810572473197802566186687130630654231754324833\ 307613717373556673034356657402264829897798113050530809586346609003722262175139965545328906\ 016249482491588682274372704316084122032226889423687517904391857644489430639190217438249964\ 668855273538438413108611914346038643616872042011396663348870909602225698181445216120085236\ 481909314824543617034610254138025469458818423692207678006379356088963681794457791303521853\ 846606685990771082274008534983739433685442414652510012850371344622786936690326787199481335\ 419830014195605417965345941066708597881708852327283567695259309199922823663699556347813038\ 119893900758510644173989428628841566186025424974110086443895373817048168860652178645373250\ 006515355338745052163281196905311481468413334630558010812266878276273486597010096349383483\ 993628359152522190296814701349806769866071378002703099851118642269696517398506257470621935\ 869637959163178318616960348030544252480700075332658054141340797370797866330521380633500231\ 232411012619586562347669432690618465885205539617553953571418196690889432461836094938309852\ 781861942166126289123201440888779752234693238659096699554032724835534520143859988394847657\ 326208729496496342190769854288527202761367139993683026132242775745450216592250147977811523\ 343220304591021018976335211811620321207572276690955176558672495482977111338664414259542756\ 802026031582923711800994087137078778382171240151112684463021679985139029012856371016467750\ 772224282819182984872108386365475958097750994462055652920828070180457729079602901274595941\ 864499845872577621768985037377475963193061200606405846794635734510353255285781074471942699\ 209268573292240455912980446255054564004842261027248823624155755349424634788254040285356676\ 046827288009596167205000017137943937701873005626937174908366627895142985156432967029368831\ 342707209589646948780144113417159107979947763115792792721331421221270938598967929834770107\ 129398599631437675416296860667412170501067511300611690593960148182393985499232933423864649\ 982921668950444890347099838846744339971427449970130808727792647363552393818754425023077071\ 044764197342904146878743520729044389926092952387249100550158330389957137487104445966066521\ 065784873421978944702452408387771818602111154569649044272940430408515504106006793129110596\ 159029151731362605145368167406370362179452273653571436489877942169391167610424615724926177\ 936978732746322848337688200932672144716304886218507292044572075561262143490190364460332371\ 375679090265003974478774499248408700589941386958089139386631258968308198536562710465168553\ 021457157138995330415750999167499078740176084527524062522932250997056270391618029019454700\ 614996383415616460296703600999880550211841202715316179379230891339240985449610617872453958\ 970266971626312596464171630427691691746411077409225971541544120851015544904834545760810520\ 323888408592143048917510794495378596785096154882234565740617639205549784318929489921530992\ 883930931946993374429629800752211273482611346829575732453271172216578070253453096299549741\ 148534683483409309083391142245359559011850979739080223930796586030452544695321984934259103\ 478927989358332718299964955347615070979139589762530787003209310920598649141794218311022777\ 473774377048885947922080317963271979513854562795093099581998051213629135974111371361790130\ 937366725613431601865212229702276497882677907824154219849225950404366283819694885152292484\ 564684337847446693316965445691501777914614311570622279374045332604417221380117494981951984\ 950061029307535402565803014177877976734470282019003579942597517822856357371281538136864153\ 709645313220486327361670134295899919990487837799806793719974050662569553370071114115545173\ 897957797050528900264335781727915686264777216275758753495097937406108267908098867284146061\ 311910344608976011227942137342936735321068428524212531273451033237498352381565017711802288\ 043018298717573771235034762699910114388244957008456083789603083047947008641948742474028580\ 681916098255883884315350106717978291596707490450252507169468392890367873578694536689110658\ 914327959399693531076282369110507576652178181478513354443256365962913113139607508217033030\ 768308277771540933732266786466952618932677094565084289407436261930145718116857542401559321\ 555144026355350474235106440840084139058056737359993178080360563268427059256162755177995029\ 210053272340260760972924858923946496106558887694198529737713573880989223990457488205209152\ 604052237127317254399678676537796049774343023500758783973753918269206997638894728958187457\ 448945261926219859557089370330073103009632125276127893989481385372738374530866335542018528\ 370573629122540353328459493798665407727827201593055799077095653662927864037533179987313944\ 759228333136415422663573312820703190038477204713551895241171382088572847683055795678290302\ 333293024621107106461544599877346270252261778567842259674755590641641815395478074451523883\ 148933628767890730039431176162011548675317468058187056836369961656576734805191255492959726\ 181887884264308592457080936680012154996434227773854806732327952356632085173773115218879108\ 917798736566167121425663420931713518638124073397977652224448864985336788086940984735712320\ 172749929846016853504179783878486329217321974085945953477578336605537254763874580994559599\ 922271822668598551970972062351033564076825298977194565401989113472908229196241237750292154\ 792403702864047505257984583210631326684033145095213382321326958640316805961106003279617318\ 397101937106450145785000684668770160880396141887021715720365222253450405452626596725004937\ 852380497572678339460413908625580940188461933336996762649439076859554750554359367821317498\ 321141289846119763809773630203474497945283713923590617224392390801084518281018359141543924\ 241929094096142552021902522927941479243759896416069976668809176939789502721662708115109872\ 937479999138187828369037849881151312499597898048468990323767651662548432699683839196035054\ 160404584785172080446109019856678974261810841372766326887570596160843148108928295242942495\ 164802861437185772093649965536134513598652147934983016636223544925797774573086576487066757\ 638417175559587318311910660943774270756816430741275031269969101998777664261893131152066653\ 431504347726518731782466848887834685960773805157538841849248459369987354911607158065594896\ 511598491870451321434295050046619082625634189964795452468669117219194879778673064170582396\ 272808866089479246757626587390845363323854238718157149268303502820161297109510695142099738\ 871521991221252985457650763619348791160505121507764197374570533505356574042732817146918209\ 261211752928820823880019528251480589873563077602339650057060120759771565194147529858111196\ 351428100055996969031233595816708949250061089741400353223230526500782112545965379833927531\ 346533552259868931304990589930087735762010913861662979192040218930023022573160878109618138\ 550912345575179642845101658498461804615316685603324007475095633950470738695958901097090924\ 027192404711700217191599521989484330620417628264093800263420247411498275569459019798349375\ 792933211547993287804870529755185803968841032136178828536972034572786833525480167484124627\ 473655211124173221803550703648360604081416675799360034254061326608308948135636389329446973\ 674736232697199498482508539246866873775434186826626425506399522413427219515051488786008734\ 571267510296990317489786661409810481134362773626176250881288631898800708472220839279070044\ 827720006588578381638673452039438476529045247270666832729385851810841619306529396204867297\ 430950474746376198697758477303607893916957862862553259597091302715051901686319291071586507\ 998277153314287046961047115525048615071748408507067448031797093784773914051817282200248625\ 333846037348594303954968562232671078425909563031902548306798558561992671313992810763030678\ 458893995148770501663916419608065247037664821318184687362951168387422335742950577954557127\ 606714109573413192715795057371235932452122235761939102726510939334109593139904966940211278\ 710977779232114273519801267532421100644798166956389381226766727199427152450133063964298003\ 439817117817442666149371236382489713109434946656838748507300685836637318959636609497082286\ 045509064325663262735517244604603295985276136257198296193338934379413239294392685167913093\ 916885763062621879585003012477274091334307346896855350466635081914647992311091245897901746\ 218943642884741889670348535125981263748447372723113730286064642995157235817520326515703528\ 639132541748209022093319372151341497734589915043639053970583517870169117832621596410708901\ 091549264572496006738413548729661769227414545277371511580912263009894257492154356703442224\ 536010345563617074363684182398438473948841266195448584320054548942835260010641850687490438\ 614199589956460481337303408040354902854493138781114536357964427033935632488786705604892776\ 330549948020810384576576349731649917106101219822779780762760995310885448735337968518767618\ 101965139163862651774909549138464616767857630923920111937791344497721475948445241386079965\ 566350120819661251015998120900871163242963128478568588224922539838526958867978898240183512\ 072371661931991791794132661699971285249651767457111994284296566773751434166199500313215786\ 453918943139919968745092338783601890003751115022964111031999734166920481973135651674501116\ 358595644649112479922405240628404592812752073798012585551597702579885052999219991161579395\ 882099382196099456855883741535036887012044461140960316549811288802213779971599490227476416\ 701488872156708433329144652397105908768265158096526600258314693549525050704342812936639569\ 391330034319991338462878920309861480304385916337497726213516806173288763539380390420136913\ 496137979765421553001328549373064722077026795171489778424304978924856197146629461420577092\ 220656537206982287349155858276912970849914882881528914787725569675927179807956969780527591\ 704362304279932919850651745126506986724438779667331563382190294240628160862870395317464584\ 883414453330291456618328566449829639863041677031809661956985299742674209075896798856954352\ 378861454791412247477179735968275862822215604002157076010570379953096739600756948763959592\ 534407865218264245415510968483150607700029121679450971750232399811007822397560941506652929\ 421385371554842662268597444775762188569570216266206278369021145700656514940323051814686464\ 004969972660465387408811405349940644591409593776212350271958436443575632551252190047889964\ 064460467926674690424889596537492774121346710002175190442309851375425835828788759877128157\ 787538574925695461348889034258830230202349280930198845541571689750366341724841268222880852\ 588535800654343855776476447487947176457940644524015339402800341545755450374460463902108686\ 803158329337525694577833670446726012462701162460837636161854634842329904024195906541338350\ 882272608424680455449784245731536249274287293319011911894072519992666537762778607006300367\ 384469250135566838199836433336141249140850033452252102997503651854357055327221308149212661\ 339034189435076839190551772226095274788667778845421817622067613455740612676095883704645017\ 866747031140305371131225469251761648501754912432516580369190203848375477498202681864778467\ 154943279154913873009074490332058035407523452588340537162499089141102791714079215752814367\ 074302089018555272834039028414834274403443501349830415189810030869470494178386478089649936\ 712407082919173997439493501609473595926010281534388671589437323695473258698738760859833884\ 645386676193487148931350550991240576767802124627564087408271552456289306118626989871844751\ 895142521870319286524710930565768434553331903181615086452017087377762673476445780695864158\ 129121454202951696142530104360655685153822950157948069863555965929816726452950609756713796\ 979204333212860042505575547954675274139820929328996840702425337229822039465230992608874235\ 339708475523225003206637776861525598014391565792522507409207547520869447793462177911647154\ 798379634546591782651407245642490993012060936469156245065646035379800435522159498277248014\ 940412220885012750695637735840615856815339544376162960613099326246057788585584089114826807\ 670400724778285438301991274521542114623895223809417811023785308423675404526039067845639342\ 200532948692596429250533256517880146365297547500755593108420443223954265266363489311045018\ 439459247789504621376553374779278518583122525421721827240351379663694106232114164876279411\ 685475516434271403881602132525375342757773976344739195278876292120912939609130037882930322\ 183065120234821163665743286171951291051061543063780663704327153071008267159374665179316486\ 941133007212183171707393793490520526872088971472984174908301170862534241327040574560964110\ 974366138198501816760784055546878138538136155724875522221007276192018695415685785679865515\ 288643290393636524034866317270760208364285252796022797598317889320597474789426927251371399\ 624938532810602167499671611132763997133270582206970993001388515561132692258252463989450157\ 488513317737169705404180766427243136685520491164623029536564736608829584512426781225028477\ 251980696829315884540692794814324282168423744261550579127436998111687558655256104209468728\ 751905619546372011787731692375892945031848403473191076967749702448328640772097422449753544\ 197553589628672813159095308162623011739954498762637506692835081461585904158408677438054524\ 593652325922157481238845164663725595086338256857244835011006332204310887992112230873392602\ 604731775223886006147403297516174091004681685212146436766286018890358903717584402585443882\ 474783257953581429145721358435991296677069456072401588816978578499724035856065905074066083\ 976539745480217518017531487357795920403003243609850123967852077040775556414870441612352690\ 401351409004285523113023671481444402816652687113492858448673884923004309521546906281761285\ 828854900146061087262966693250177148986045798426648413512408202255144293967346460591794275\ 183982281443937292606760697211498247354113485030269392900797114560168900549632923198301277\ 833723151580924817150730091074280418196704149708681692648666094992756642325783631486895432\ 294591598940016690130692143237042737296986261966697482455944321879256687743349732613202496\ 466406297970730201599441562296761017173528466330159181653671522331159736805001610338560285\ 248982661599929009540401375075418531666032000985084296834876332492015945070370505871887360\ 826189043343378897827652970928553452755180056425814609876413484566548370606196620957825320\ 486734982032080228463788142401780411184663987418464306985702509643600128802443131628887792\ 196445873798248028821837874146672946048618374314477161814250735332979767090428088471963376\ 020102805241021102232366403134306610218945194539093207783682572434158817504483753322075069\ 847911650157716628704350517573463570431167099772268798604542163452134948367967486033067349\ 063723458036258444293722234953184981301775867342831392715642220689345521383565570366620737\ 919221893650070111418525905198740915902698579007121894777638164177852081365849316512059699\ 790141198246514502156599834700003448747007570634487030821979893886561851533247879763487964\ 141776086223783176924957448074722521480252455886744851854138506157191109231292044732561402\ 448552785343676577668734371188191580384166660572557090917350482940816397881070567613950757\ 986271285782206930271964685072867955976136347667736756435131285745463984778871833902075954\ 766724903098489976231997169793363499057755757538517557778553667570641633533615171456381011\ 713025610884450726512862761114413724214212773217835687622943494207430640430914937737581869\ 041155964818122403123902694163927209895405331025109959758921301628871377967033324341792168\ 306753260798029642786725891012312592557428727060724426306785754313366873191337522396264888\ 315297212965339200625969110915687660415825086712296490266088237071356085541345756809694470\ 608898031815176206063440380706502594892671613982150361537117221610454105221385481606085385\ 099603250843725179590950408953757297934020086257434607266786098751679532799167653310535385\ 505121869689795911581763135981674940010713327702080072238883873153151910204436427314797300\ 028302471581197687530602780862840594353824603841364505477837178778878096549076930783594084\ 708326194514237962488867323469495768088047112233337328368588520417704171837803201018096846\ 193564783663284432520892251773285598023248366141142568704660394850391804810048087939527578\ 707697796980259825040325619260617560980254906596059591538374140856706676337318525165044758\ 517200323643578908083563670502425077112460864764712300732385160170175942625134806565842452\ 782944561508004263112700079875586982113417562364020284241742564270070437674466155138310747\ 288396643987955431486284031487612248968191674319509884310897839081873580060936748463470513\ 990479024172320323058621085686315376100240538233666045752113855172292363253654160203255226\ 607826638689606290027488237780815122058994796770298007581749058525313920012892091761937175\ 387405457501757071176334883253196051891333958440431521229165914847946059513945549497047575\ 835027505311683980186819015949628607609992448819771498633704415643627080459758323389271131\ 666282433620001508791545080516491578281013066707409910261087736115714313771934224519139397\ 326531675349805740633221407842447409692807027042186273946250181706220610027512238424852421\ 718979605964788320197492068302441498420790015068340308231881142702345308128938551678752681\ 115003766761445711726762617665709118621618770932813125064265260331019706526206909536547738\ 519508617444189960188494105155264079475655710080423102023512434611145744181627196961220694\ 749910209086344451222004993172965908433301511981572659326456798119420184450074711424745385\ 026121439298395878110492835278478428352974188824342813601260439728338625939752166211022858\ 788041220307532816131193288319094801708607069505824868290531824502867642434207863894164227\ 129730752542809961608053349016465968956714070809772904612342712880377104782693875766425937\ 649383327286324391641098544148776870276867952308006839979897466648669238592846708152013949\ 675766825553293144828966484847482395123384678803091368930168458288536916085589318975409157\ 710417442558178956383476775936717769660791475794656472463981733229196674333817812078634302\ 296357780420073497703409087519853497285490708992713422681792026695710779882571554424080515\ 691076051617973324038308868726114302992859730263030819236653619232191474372234231170593275\ 370977070545976863299239780268915306642621407693303992921087247763726028447395791773259386\ 080482011683924817166950803975653089377797856501360331884811559293049629870671465320386425\ 166479697308640672061924295768138272172000594287315591539290803649805260807960116622088034\ 851008703196313375743731316720963916217408638021823801266949681536057162968510021026026974\ 284407032653187364448194874120603420948173961606210993584306899551705886574940460812978329\ 628174287720066101439942343276848431953698030343351086699544162142922673000068619091351680\ 284957222230049419793870880025145291290723198015945132796487612233968407464404722729817805\ 541915789223930912902477812581463098100174546012591436278877966939788380950765334113347274\ 606976562141470961353284238318849061673979161819992989721320183600836333309188019280714283\ 796938242871251704365191336252208614693151987591841307012518328732780044685751466205100885\ 229354993748276036540857167862363073491415719819386888525529256390757000203091307559553879\ 886229843187397550617268325308562516667858876289415157332504989847776841875702542869447491\ 452972264917293949861980963124701491024753123818024157077356803154625347763486608086943123\ 770481706535266191172996171244796988540334116958423636011404157511437856309887141169604146\ 916708622635077647297514026186444743745004186823617100451708176723724376244381103460280242\ 535887886531978347008274150191176018620945216083422982536028332573253553489211050330827789\ 090783857008803888518558615415665146079128599994117519233000835994849498327055691542631199\ 545859802474369743526936024402971561749572643124010387944415937231529238857774674851768075\ 573568633834050058306057883239561536555338870814131932370447207157613044371490955704189005\ 657823141563993737841252529307411718092679395721621360349915249716376650041179735986724216\ 694061487216102743825803564309620609277110879876905558099932536520600695902908479855433034\ 118489317122468323512481393742483462105884264407753318828521822220311092733383576637398626\ 461740979740480928975458027593008161395261613308709766816407821061189373065992361643107867\ 664874736727190459342752046969394983559019178560889474978387905068091924369021714119518176\ 808655834120806154408093544255283123581986372255414085098262769664890004014167691169137628\ 884828677026810545233805489749297751177437281801897137580592392655730764962244698984069472\ 242999983686165318569714903304933704356552177001691310595741248700100478511239555369680126\ 990091000985234359273344426935185357852638106160116445286563521616126730107307987639305924\ 002012169982964610957810470107745773593942652619881893348108397650611762331135632929747959\ 270486409030146943995800373419428738447896106850875368671512929907029239201592367084267899\ 649468077029926269204198590646494729700274014354782698079603068478864517567702526943263414\ 486774243151106652721269777002764576319264752989231013268727841649868099220891804554986844\ 637904176694471696329531126183680166244379671940238365255981970912115678122205772385402402\ 707814662382184140923869951668879730492849886399670358419787805531291843460055625935245733\ 931877371802567332873431064899263814501000839232575574439647335220947953612994392671811879\ 678702198329439176374512134545066278228333004847265335433578281889440670246613548775419496\ 592106644909367791996965221508032811909331971180437270907343750140352848269431405619669858\ 024686945585435334986505382883874504451237661360280779049742073665152291498129485815713597\ 791594919897495430011045575421709730956124189155222693250200454323763544700388211809271754\ 337131146959469865839634157231275245418287380485995031806356461518127050872567095517036428\ 715100871813151311895258423281661546453773605518024827105149702252283311411517484177744466\ 328656605170284749025233764000200950433012087466818570841741423416442307754176681712234008\ 954992161307295030968063958922705041388660781484386398831946016597426603213345318356130458\ 805367917703332589754911662862731481460461972498361098093635094129769670133510017932277650\ 959802990394767937447755851409183224967834397387334001867453632249231237289370657094302028\ 860972433464576515629925712175345940788986758008621344810334058480105569209361294563415765\ 927665160126942134378694803946772338663489235180442299404472152964372135543752091879474633\ 133588246637717247348379095099673847841857812866861761381159944379122975863719234274307122\ 121735981830274796422901046343934829831442516870186536522979518301615869013325931768001988\ 095920932351662007280967963638902816630331385117661736979435631200843555419264578453023706\ 136704279794756269747126462867256801653224439950362380491368249266787621593065061802062092\ 190684193487494846201905182354357364701961007152531828077364521633693710855910878699340382\ 673385747254407376577364907784950086172005620975916935114193574854855244099518269898433383\ 375349595427022767781703263672553932939707957666489292260261466266557837948690949188868422\ 067186042293126606761508219239574485959525789720720484158138220428742018855237740817066411\ 669988509838024725522294718702001126515465546397182160780124593848964133046792521213038410\ 124936806061850047811600425489932034639179690021782334659004036004615548393288350094506338\ 456895782571074776540348270640678490756595492467032790861916324243897670480141219229317783\ 768773828740478157014780654521040570640980101683390816214245068478388397687744101395965668\ 932579712822944669145770047967949328660280385195641822765422121498034317843186512059378874\ 433495288079020891499227154615813085219358362399509328757270355792277272369854597687783694\ 396056285050391193772823350897472885778517806017164289916043606369200950032962516343650004\ 806296676449029674558690169809190551553415819484535267640776804870578717685889594202309293\ 381740177753687038056263031591852524654650501026313597186012099946259254701286202973082600\ 583875577240401608051181894184107954020867213187617916070318983727275433145118686212151160\ 233917465401189518348345628600967187914597600018600837515170707626745763573697675633342729\ 520623519867693784768488856117148347257180333725274677136878580399393320788547738090686721\ 393094955899571293720375088313807452465137353992990019146935025115252227240374209943183442\ 811516934486621427881674745660469493752667836950061518652623698918275682154543950161787591\ 476824973377150353417975644457821425693441508805879423312100534871836425766107429269588136\ 008750016909603381068222308268932912143832832821051294520227001618371477650466264783767771\ 749495636590082947314773169005808873013953308329633229389458447617882634221178314398554624\ 134765778708998862794645200349242812476814034440791128833708992045758074160549787916523827\ 086201782509423198178084449298964215298605609498307896160841280924861213870240913773660712\ 070390481908182690065832111755328777571566699172012457149093445566355849693788673077262476\ 284651595531070544890774884929040024735839047730435863689599939252627874906145526562811757\ 315743653254426787787077806788739133453921571097934623073854650168148255794934843033926377\ 249729125337319647652452485467430465999749769768293316988890511357150733167505268534671354\ 866158267120918806259148719625611569653898816722352057999344504505029478812371857232568572\ 478841118435613024588484414213677081629763324916075757821545917231475971931893389642464288\ 981792398339233026521540460584021214698469262663158629260739675529989351074917855362236917\ 204277022614282832952364145698866994590423520067398686727366251189801564525703200506276675\ 680353815756288876404143026359116869544399160860809459403422924023805485912434567477930400\ 864659182725825279614625915178997015650016213415012522910682681532648775424607151929245866\ 376853538697757654105984583746087502500027271124504911639135450613303823370152593084971546\ 117789681059139870622314809320091350956770740357579314461045400478759539894230852237157876\ 362984644158415021182862228365140461012446733441550668439927694734177690628156652429999979\ 848804690480070004872095677919554841608628057944613385575917560686589102880395675337456093\ 448784029061322194464755089324956761791334550823512894654295123619865972642178980688162256\ 317586314414838484045313605715646222972232208763210385140992638596387028521495627384741351\ 040888394960166537758994603015621068439637349837707669899172120691434990311371546697083871\ 883617072941082600176918580404269061292831370223065646787269897285367302373491674449694769\ 063434868950773027535205188895049296491167458396112327488001464042959127659277477466370393\ 116546259058461828434702980551375293410126614415703296536622454834875896237610480911675737\ 474989721555698522102270330167587012295542821546422423976353551062801645120124781660859604\ 819109683518610261374063154346568115664163731364962491240396857326809693242657474663171189\ 827380163220421071147067772698922812539452449856453328596721632474211350901138650341447369\ 157539704559139055802952226116624040738930743114725740026518076925314501619450671604363721\ 516648679889571879590124428694727457902415232957039377646981460953151815972678488833290194\ 980788721649206208182600727057537112040823616614990394376568021160927487729815631056897376\ 543699481963040425010131191005681237624153009236875987647595805492101512400487563848214271\ 801608218761628810588249693896567756213743174758492776316042700244846195756731580419659959\ 536210994852785448893347535555692164706709722983814666966448160861606889121651722540791946\ 233695617142957079387486465141855809941941127114661891583100139738425236877776615988859106\ 099105596034811566696817952564435046816550389007631562946538784509268191151139524550705426\ 081028076264978217304090212248058255683045742105607556112092321776366956068901673154157452\ 636788069746209504501930569790209927158606541317397836244932936696465508284743074219172183\ 070938161749193049839459875101143095209549198359120005358677331859068307835780202236657500\ 746888365408254631006163484459230013638211258390251770269126926069792117115292768537441649\ 934300660818705524146691354330809492290764847499065286208773509289360328234117826015717285\ 103189554239054670897871567720135039117837059489045683172812276230639978795204496072418411\ 958812599180933735915780408967070361127215863685911658800065707596938621473439191653762221\ 797830759768081688369050676144736666598735505842846725840031288427627373362905507122940164\ 570519929220966305012176868586729090772719558051318951881378911033706575287283748247805271\ 402473693452124543676967333477485461581212699204610081518855482151200602678225141408613885\ 893176168054134958926650644805554769927676908199086342013193067396111252746798040812314705\ 194941684900426902386019808389990004046178737549128266569538470152772661797672063544268699\ 930922255198346258975971509368791880911903375121552961098359879735829841264495462755793904\ 080190532154170532175043101373744271146101414553517973116227388062347236521053763643356307\ 488194195839902535437486330961397955408328824101023140931024023163683256755056321351838284\ 822418347806845937626842417565616214935874985379740964089142142666233028403551184343140009\ 986274439137322971886285738357243072006157389410228162722332089819854135868917829648270811\ 326981788333739471049092859238101238979352360075633603719725176925714354213949434165619089\ 603621903432562704216927903577188938653991765501161425244715805159573572565021476511034664\ 437198493478670797463952518029302215885592299219909826471643501657615339747806626229616877\ 346307030518522047846573803123795478561659602695113971875252672704323590472778697464073979\ 480451556902593587640503195823408306277277075833207950636803141287503195975314855160818691\ 517631990691499619632185437779952872360174600370785161315195292163928014647666433896211698\ 359020874605243126711237413690487823770369017287991997874818068997556600476852253171815010\ 966694502655090983463654204093599218481519719030326642724134171339545890293399220336473590\ 600155565814210781052164197662212023914819858510291765577141949448157177520721343120751519\ 902898374918076142625270373526486309557963617617791464050506235217864728983510097889162759\ 202545417004748377541463348566936879912238102608720845158778605444301578893836537907298864\ 531053320680081460490560651764775109970424673144156325407456190883358510196688455009552782\ 913251446192233116017209524654304646299170665865348045427503437628476332462642218378792639\ 849177224732340177771536134092132155684854079042049301051603943399748734215116477058818756\ 935874261035008830625737657513053848659636207620928499137634370471298591090833026571024437\ 958642152978333200883430622508240032509154375230047228958205026794437919238542440311796696\ 955095110327495360689976456935272924903504382159674562880563182931984045348321788384940851\ 976007632241143034928808428187519853387065848947287493818000928724297709742702820930412162\ 996723016375065136717143271958351973590128845770805473175054691895001718288489188216183602\ 187594625288761828936542655876348644833671185017021354858280242199694710227945080000473160\ 146837875735180056363801028554776712802010569408723329419888618556325112841802630878043464\ 166514555596867797673652723974226158974537893466993912874056478973718284434980222717021144\ 079825347165230573953676073212945514520297147072976958540082163053342244399479411344152362\ 509399597158884488239823762984425647238217328952844993802807579523775708647084714505351770\ 955219557336823933934942723168106058232937667802385887396112782311858051680734576471694771\ 097567830512799943379525662606975115099592320021881760867069186613162425553217730898756747\ 479809569358392254753574329612678209388298016235149613371036960131566939150249888193616386\ 243033520390200773722008876330895531684780802145049655745176063738611154884781865562394700\ 104851966205467536111925674541852097953532003191077137187446075621883890400923753271582919\ 800688576698713468244673467673215276885277300605467345375928503620724761164503238201637111\ 057299960909132380573784714085125413510166467634003471869975956370026421751642707732346043\ 054580811077429690907288967798552122802274445537499882173492317201387215674138988698972530\ 980384456712535025189743643490600536146923227883403333602307988595103684527950296585590174\ 415523210099606497816665661075103951975700583276981187143792274070550296870853840306818535\ 376667712410076229523973405718766031186181143643531213304975420560288836100059314975630002\ 776295061435247002828804394155379635488115682056949475147461812350693599210258128770600071\ 834749833206442798561554433421606315137333695461297758209955629142340725870256290999562862\ 900564956779456906025934709062352067366121709003517620942698283162500422789770574567675395\ 911902931457360831900989326704882321040207540519442460002113389298639924483303667928746697\ 258727041480577963189450797835768467430986284630372852141883686911337566882489934104942045\ 163739792390923695850636115305009918049015983219404366107343440066574887782592620682818425\ 088838576174782320249837017572844458731914110578294285791544537789331029052699382284193942\ 804677743563804637146519489826398294011615330495791121320747962672535812458628484865036061\ 824552429898787810388193464042236371998147594187492046866387231101987008882923086581488219\ 172335853683237481753520038110495925222964600786297124034915794718393959750168901460807371\ 528540524622224264645751927649877005526130381558105466397644480658092214521975908543046920\ 373554585993518395688709256976088032323974936152206673912663391658505690770921062897210772\ 391506505521943716890878857222818702613724065456210466434356748693767776607844222926894752\ 843581825810409248267372380586491955369488974644774244965388695344209783246414109545467244\ 344227791098870136837742890643132429021026192020472793019393335214378910786254038755849643\ 426085704884247907078922727795481420484099334583601044386214897289527674983144269690941291\ 257146762888158914605802787210579824585946196276198384762451732933090040835838909131607620\ 239513911034869174509786277725328413499241069998391646782336019517987399359970037678032993\ 420077712745571198404572585622803066138470592085742543245688037859880799922777989028511187\ 872306081901191283383417799215698751855096473830618767850215808425665834186711081940966981\ 406766282633755278487707591579240715582701725999478600292297501552735209889696310111713701\ 183831505522467343715461954112835530589952260899798839816962338132469806277202981362781355\ 862728998774708109002952308919969555923177682385539820706945318333803786334682840463103257\ 087095122043076322420481078005299611237416264803696912648242826069074328577274208425140631\ 745601240264561522954926168467527113551607702136891868714809592050289677715213943658624399\ 772620511202320197167657757789377692613148844827361462029686759018880688348579856861373710\ 505562054558940537689577881308055867174607584325107447274140819338128694521586059861729088\ 814644797161929262540441333355602604232473200869554553214761817144138707005599275945321506\ 473678554662173612220786657388619690816009817351338647920351110827412594186208393694070741\ 458297406241786032310882257969147950300359826668151192972642829651055647702073950368762988\ 782561154753220780038335404384758311083313730076141993630701121114281325293908054109824465\ 652780576217371193993597967292424956832959785154036718081012923920194087350750969424534228\ 102427804174350507008607125016945475527588335462026187709111873823208637297510286957735234\ 055467674812750230820868464197900724308061364768228998539960929415399041729515488265236326\ 600029438356074805137113489760686462987505771903854806861348343095089465683052739624660722\ 842770619231605333424081972026141141159047999041172236247107189790133023368790041639371320\ 109719409100750578017837617441547288027751492359139003614208422733702684193992429615416310\ 971027866404680961659200718454148592391119735787722988698666866547384333728554407036087116\ 848688565037591841629677298613049096446738482451211911534828536950954834181986777360575317\ 436364951736551175496686080473622700865769061730312897412072715262080001314373578187397166\ 365163047185952712593890409716860970543913372199865518309334774663829413325000110352963939\ 603075827011874110929258397251848401673753748484383439643571721617149805470014675216898315\ 517226789897559284180279551283776338070144545027184099759365075190023735673903633444732912\ 041648095651036740068361342118280479836465862451567166497964509657878243596819384439809935\ 767909332342288886317378810038782123343101711400118381284854638872931385438385020486517024\ 411168906323194724226570499038602321397302276500304022735624187363004652256929684441408580\ 473297258167629287125278364408255267821872644124884987204028780092533178360083178480842441\ 265908461300860229941549020964521890135042968557234786768520310093935798257933355250048219\ 242859498582980403621536589928562639149526350635738038467772487799313529097955585273796303\ 499948235858504288199279739924178456832036359603568178383711620979536107547198226908078102\ 942847756751240669766022418606697516554066991667577569249331211646226660429321804025458372\ 739079174250238946447695860374192128966607780809082812098096861372452473338487294996506169\ 896370422719089341935268847018608471182962503979681313965718325873060041446712966320873383\ 492863527677976423955963124643923389792265080795256625630536858568087207610924788315777552\ 401982320803120855775367359523023578068052330667726752090046405653088527874213219731632520\ 077169145542644804373419818805507870545637378423846473718456607042983557463182117943973121\ 988296977945306814327341584187959013877332116535327289743655634755751285761702586102075952\ 137676511153605695566861051139827381470184415714692306276318601539420643418535541041613496\ 485461074326113050405048625668966303385421319153197488419530388773292017110199678645174169\ 835711291993088654623552610816814449530315379630342949455764266036644706391922877664890724\ 693695580831105058531676840233807624664515441613978342677288914188050413895568230965528753\ 061217075284864060837533497784714011249195167516079041538254161873434508372479416544362704\ 418920528156223568460997911747946734984121583135538902324808605307188907261904417073019747\ 958691696459581894048318482647274978044666763884973636293168129017376190765234678481637206\ 538761223974449083596354264215247553901648689909917648201255473664019401383584777302302974\ 848332760224242610414231456403166274718035870707054087488677554255625263706456628547339266\ 940689820916484358156868203469771192397233146385646679344055307627358464118317612124973008\ 442984023722410486453205589444673847943195351524581553531899267364518745017840498662843038\ 528117286200036624213721360952875241836416495630651089022395201292160307959509618714493837\ 999986611990445103709954662722865275642250669607704200993895480755674563924863063665800672\ 447346036935279536640671963906911758370902086338270690790206389482974380426600772310898967\ 908944212973460047300440360727663986274529987366830587094072560919195378243861736718737179\ 164619003924021096856249744062318082758518572941830056341889380895509456298497581074514832\ 123496743260753541862016951387122359964784763175346756568021457072118893169811066625363668\ 975376913627049477231507594106110275672609411910118160789650484901315510885572616906073369\ 798416099597988101786365406829999036232344477406151616433502363610468468503138122389653364\ 705335626206112307011064506983753907102637897277192679726402406617027311373373634939371732\ 304530917729619214060197078937117404976987400018992833221796841153075380335314272785598463\ 575998149279758860439379680559926100077422099027532690482477049104741442046841561346421721\ 621052053672006357469915455532290306393790172334562735842848654535821726239111238592461013\ 161471765267759367572981132418136696871824429226631816890320564054905655704848292694553647\ 732471205774096504965706128566754081329049628300237117418189354083679743317178253682772862\ 100175034455584624635804770668846947497858954034368217943145163627367687809072210976374100\ 707220942817619463006205165429842000614610080752469820840928229730499320488504550120929450\ 098931810614194473956541951568202347745915683607522641585910123431640668097739240845397624\ 529798159532539240802933532735180331303386453267885242150525824907715722716394582206957637\ 391318387871265256514124148187446060842966484565299696287273196926994401880757489223337726\ 874676743044067223824483231667162104115518182019549563764789233653433739883328847644594924\ 737038747145567119028382451723735283737804503551017549791877990389066131121388150957724033\ 053171810834946059398712536223839852705739905130428759257785478232160019034771396092777889\ 574778490594929083528696364268488729557552749169833311410498499228455208448422583829410982\ 950498762946622485950085259780549094179044179427853522747845783317036987840714344001395035\ 991037510156674604725937057495705582202596166993871774762984915470531242297388431514913720\ 800487070327015602331545333284835203821230878397091916806679019431966355412511490499609540\ 307801136112553591391949730168009028008796768966633698079081215142724182306894544281578316\ 007226674487589378371723580451680081046496983838394954736140503199251620499504337094370243\ 990381273511093543956971832702772890068048689241856184778414761637437587408709758797913533\ 607375951561076526255857580612132094867807217304862157153095295642312102086619464695032303\ 305005028203304507653770991393797542701205912599291342682421938292286475603644762782588395\ 866794304828831451845360683334799458936676451562696322716254785096929266864681155237654106\ 756555591643586426961047059647265634556925375669280825354908744447231225468824775307798708\ 653044113431133514276217944080305942554250577826138510746636601799295181383179340364193951\ 094872045476281180193004541672121910080756879097075950002354194114065630982072952225427318\ 595771665558757540377246752732677754033136069928156724581129571199330932407842236255266395\ 195296514483224460688024471303845943681181095407975359322253118856989030827048091460702735\ 723826030829400122767005062529225108070832544958724385513236771178979426648268340956897457\ 880865905938977404219826472492075581324304970772176733458172650598999816803392184251958688\ 268027583133447687468488301117236578813807939929594904800182594386915321358300345478330991\ 126047315084869513958767314919515333147832103388717797692020264349151066155109581864745200\ 748617039778592564037430180511463148257097810232240712446492788984571588062120300807567934\ 079991751792609437442609925246413864350752861586192159070784500133216762847139670495442893\ 882847330109512240330281527656733780316147828092849218837694646425974228042191474477519922\ 051752902038919568864862008877170889569670536714666221670922692174051614430474741030088485\ 116239117553574584185450369074559387591380414904466887560847676330156983741089190360683866\ 144715498068167689654221335051668826911076986300794497051530461566426926508008790139142016\ 070666278942093539471183116611923995498092558856609933707408327719017906119462015089013843\ 983184906667533318052634477024641111506209937327291327832202564619409883892101536618738387\ 894333621080987519869716469180254104732459366433510892816377150708286017652646696439539186\ 178906121382083011497873781211731003759315203305660135390170366885799275256571444201061710\ 927250549104199337934522016537423211037199367325427511143640679276273750321737521156977415\ 565374415333799668140362471049767561266037982073989552648719592886093008312123142132399747\ 257395256103087664724913725764736531115249316981859440107424353655287887219767351773851641\ 210642686538657523737808279588706361858629899681291684862571719810762865888321028108699795\ 322366367006718220738386200464973404935768961938870493447535964476793682624279336449835678\ 565596871411528605108865234825227287081447761130955215797291101865057907783575125629880196\ 416400265870952492848823466385070190371407883788974396405368677760863611258548820815192621\ 389412233671378885098024796386045676887623240096951242110962330596453799326354001841533282\ 965638585589293138006253275704455855227353195403294252888547243766839212057265391842338419\ 836060235139159036808333162415055572214792881971998671057543468966950103092481430835958805\ 227219504599405022085212434444576861538474302954395649766210708678446694909356135890590086\ 863931167951467924447968653998731070192015579533226808161518406721655354914945704309349699\ 294075472775107506696766224426894559497892783442540554141565449499719807410761906642174614\ 422963230589907815510752577878590138776310307888239747355764122476708916800611729830696597\ 713945462288259378994957807887396942979450862907418739872091703686564978319061218249575571\ 944991177703103410123837731496452716931709058658905118585432141495566593099507500459745598\ 336103736020240484533952455119807008679976905357609842300487325251754549891430950475683294\ 972601856031332285250404702596491730205347416091616374205025731372441606923716246126944868\ 998319310585099785459893727321023436515561135617366142460730920952952812072269008279740713\ 854642327194694781381555911014585442048918536009211671755396528065019645354668676330639035\ 321992140651829047748750840759283839055141313787526363582376525084345625636982166790833604\ 924825011001057310455931230462056325563063105167815607697028873196502955656275147462988120\ 633562341883292268582144376223091982703775131952165287240786846407961216617082062611382697\ 846189031206707419683436197212847121103789823018399314364132560777168710825942159321070307\ 908907582156967349884503400147929528527889456527458084790619725271481712563187743988648103\ 189224772325098517525352192190602556479795240001244653039167631518331506475098982195502050\ 254716444113919946776081086052795812911540653207041200415191847896846474815437367830321628\ 561124514663325294549697347421380255453659522656785485979888020672594290530146261803759798\ 370389677743167109320308177842644356804100727358722052091357644990390763583593598739417203\ 845800748908383165037541225846995322534129743773350451682576838150789934253481810722401106\ 763707446181189751333143902330057184220730558148662215054003623652818675491688765482389331\ 013500591413975383931374332243514997642641620132291868630727671122642159320153909252477883\ 108480122548509849950794609338299491491730867185441859406101466827331312816500822485108919\ 426451328509380919137769892512256056804002754465805230155255038247418971633658880297048368\ 730045363520972630441091142675397648185810778168131104694729082847265376453768270938189355\ 983046298735593463647186237592211597975530483716110810876485191129539717928890004525981067\ 614487021157879708285835811264034174371912807934736276370497977793968466405539494107046055\ 149612373157018872361102189516030924046412701538757194024260916757135520609755137015110883\ 263721340767799679043197268128954407789045370000533013759250639972734600284188875240267246\ 803220602288364954947620155415535929740539918146212590646433636063039057147773114774842223\ 948969637718795695403641458576659879047623903435323755040006746196295894157095282094390640\ 828217133098464304178580904654176281911083182357703962482491236109294866313317715715355673\ 826595765397073204944600494668351589987050271809807929052278939880034879742569071498046184\ 890727340643906482976894931642914673805433557622018853706874712053857974432234604333349134\ 914500334973791645831360359351786945053134816503149773566596658041656865280484596194484203\ 433081388195234548169221469675736136325767117131880630833686610355823024216381184465854106\ 574394912461741058754001440880470773936271351783782221838775678677336790138159785435222718\ 247138847717211727118792112203424213203145012646745420736536717200245396241549151320997097\ 626668548042434086053560480660369052619040801262262487172225088265947701174382984940823522\ 865783531116588482455857908511252619141062170539637631300715029386125583574621492199256609\ 735240274741996301653656400203932975680164759402593578286232899973131096759117772898617740\ 070899611725424505680537288529658933111647577615594362702145001335247091514113479602416443\ 166985920433155720273051597787885974249741232929117368163434381196792057669684371527640373\ 581469433480507729093978962620730135276227584888887111450634085384754811963763715797634013\ 622876524598301062890207929926716392913103704379457375493701136459286336014235374034385458\ 923486492108013087998992874619320516756351906657867950484721844496085133529483843608437879\ 681957601891522658977640045218387061306791762342360141711468483342190530185447099217535756\ 106427978445534230621252059808349217264266831609958393129826326325567448299276234558643983\ 731561803327220314735374885475579344376726115165858084345920477079873486365896555401360091\ 167158990599957368796246713666192496758592466073999625866957729785714809740532154616313798\ 100199718415444112250106252351118041805333008288409075787086020500952261515220759563597837\ 066436405756349164043267907743908360091404123029584129869237055311098475123949623229266366\ 390841716132139550280069591515973660819777752720507683111250939190045573187324792687077512\ 799278292641598322625661676895336648238151507427852003578802980279200321761684449647150397\ 422739044239604844176752669694083261935305519189370246018741005839756419589828876764037070\ 866445767396824034750156491486972128614139133919138205374834121416612758374552690370451579\ 522330179440484617665904118916710759471955137923572174456010959685325543544348882405488669\ 804838245383376098206553488299480704488384052121841483537931255547973221698982331507009854\ 175120626702767620348550693520974373340360957767262402761777566930233635003430247813284923\ 167246138530342835072436061370785754431592518354286401209212936585171547070816213709878083\ 426901310203758038038841467441871622825253320209527195310620979673972909941137653068721188\ 599004112993060537286461006912465140694738056942975192287056995300874277612256800930366258\ 772815996913213235754048284075117023304767114485375227812020508864578673108331193168343056\ 718629203434375401872851356377272740129684536554547014489523196596341537897238372876513944\ 983813729442976245487135613013311357617583985063544407955632662630197274757513432634627658\ 018941593209460299089649941435463212516289347748935227307203686000366033187463813156341877\ 444308431625782649323827519343867638765315164506448592899495940528451286064796841763173092\ 834696764632687648803553221536318909512679035123767991279472094193543630921927171221380497\ 508739118356803007331196856848762320307284499505946480856512965938660409927835413584217343\ 126406866518956386235917067498433949439257171244876151095981804704118632662792873362585437\ 090436676586523147943080901145770327121684930348180727540378785004683544245078655535593770\ 097262369989627797302222571147706878132666427341729864842133484855031656881795195825228942\ 589130968940470031845589966893303362719527092067354823204209459068015868508187477019377047\ 858115429952215312656896581956320540760116203529525185765292395845058863825148702531527941\ 268330717402052212639167583216754545733682771059987589612600995178551339566382637295080357\ 155791588165861014657555359935495878686013472033342301301334083446396367569956648642645024\ 175033346657761991715552720948003195178412318558067431278186689067100702908345099096424578\ 724624525337701610169964707589440294765010881908251823926276482451800939366711383496899922\ 936832682308450250053575338691515694435819034374140587054467475534524367294226339066311125\ 036897776742565843820098107196138101925050889542771249772108001075314456963279016375159007\ 722081579527546658165423599263293327565229121207344782567095835881228480874996444170405826\ 841299531540363614446830947858700184293907365701136774170888847697862187104584996785908172\ 237735249822701119471664981546080791721684666359681091393940507232756212267975956916951274\ 908811862578295594361837548594474624954768592961937082300299046730891399164128055014488131\ 991133004557682178768536024806147221787645065355648729643877098202280225301974395915918335\ 997115562722771243650727917601664246303016453038004778887352845480821030887049464464488640\ 661430541804072244003186749569953489419952815476072535996453950500750023114087882356336695\ 765649531698200170105174019885887413859873897856107408175845483101229726923051010149885313\ 261798209590663544712049688718754709100297930738310612353972779384616106839071334023120515\ 602544408920133495066008011893303243811578828998314745748500846945402301769290141308561816\ 237896324644756607525011066847286498120285071662582256181598203585661021603060214266012131\ 284670619504759709573719731415521068464771786118642809005514184575501463196512553182779454\ 911136613802304391840458777204561773231347080298788405897115748969026447576997450542576826\ 210844338635850156771228637169303934952077684009216221744183409560421930395581516674404713\ 225099209209698509989883302487697683794091414994011895967836867223773212934405243887761987\ 391155570036205977389369624450022026352261026077144930651319739872377910880014147512498290\ 093856967654144018975725355603821544683181989907982844230971963637791238676050180236145415\ 807089131982082713213579881582749665392617986161960345283672809623260233905974271607251535\ 148763133197637310624802859929623976883770646196632381178335267120021290100932220432283274\ 092066641082639816262281481306900868406571342996588550186271715610500639811036875035970506\ 904795308973460591633636849431596815094216043040647502360164838508918012099070860690274242\ 794128198808204654462339512639117391799776030385879171229000773058170637968254564157098694\ 992562863663456286802179387543100698306956086383963751948279992821656983269524385565984805\ 865697958003860622632291114495192821618601902945867702372430137740068607119414905310966890\ 823070516320794046550985720286961785673334655909889718806609227995476793397536706023609657\ 806579824774578965351911226971871704464419496502106989078980592573274681274662798676248323\ 464666458437757819975049785866852289327140724309823813461211386279250403525543131483697581\ 158973334442685551071348606726184925062871912348093275719952703829404270551027457619443538\ 788117616064572702544851916652620447784370774406679497849284566566035728518460896086729237\ 020336547115504569470357109752938171527163937361053713457284756039133710067058502210650167\ 152612849574487854931252625519900054647065160240785879398476323643195486490701934690583770\ 271374088562928117625455790883300579889725767573776055757254529396266666575553052678497627\ 892231206865651997999351137251908004825644085033546808721794809368829356824571950023885403\ 505427031643248789547913591176221056465081595897308059828232386145053777494916171236156292\ 418983202105820906072753800676364125022247806375660289363678292677460537925761232386185407\ 939935515870489384815285363989731967406254961119727925097109576713257569719806573287412783\ 298340410106950253913707470296169298561756691326312191316934804479996094769481301078291305\ 332968330218937724338732491697825475396355835472491789812905073072570797545539821438087953\ 668376704219708234892498270239357331449759111193008735910347226063092675006309060068295203\ 001283721869648724531367921287968150574693570997538297873297709465647012950166049577096384\ 572862727963818775003041403860165515362922533395133654281559827144495321146568999158390318\ 503772437314888308669651104182731630911093829782065515230052433802286703998047921994952748\ 548315856064108756938141217646226180213255556464868285332967239963575905868286351243195279\ 543748360618482641356102383995914979384316307806084466359016133705736871443792558530926616\ 658856377256152780156358982625377333510822508828292713884718203293147778192205852402864276\ 953985013170328019302945244550850906533524501090311799123470637524486950844509851167312392\ 438185515071129739682698385410696773306371787188975195102968494494247011853550101583709218\ 058769938724105054295318120879192492946731443565337739468341955461943046004143823215297752\ 217672997113063229453139238788786820774516250481619973174338533079093848554998473371852187\ 230354529446745245175947100397114301486110574006095919650981271398282623595928415422014962\ 327461887766323404638365571878170185385594609566280490448766884789019983466617881513588067\ 631091566268049346051253627710522356342467635472132256942352548926795250344004871766927676\ 070523707886003511691001646406588893258425281360575478963396102731472038535028489665239853\ 664574072412059839545183704855747291822932034741234950554055536833721275741139594323465427\ 003044826500755410959179952975454495927757139359498133423680561588123640663805811388875820\ 041289548133859801502545536305410809946977272594981498106025288061392410130143818650429574\ 216204011526102728391246374003294501886178750913980543296500749225259866264383882293045576\ 922956442227030425468356372044483412082057433232093251048572631842919410671229779592077604\ 654973849513255526345194720992230082271616140367882907442525939759157894527065087514371760\ 926323320767473735385037787485600521290427362744825475036615553491492557028834179209815223\ 505279740748189617124581952819152356091075070470871173278111396720877465047921017764862763\ 736349120370913955052347990351144941806322786752804525642338755095509926704426280810973634\ 404762843382148605181772232259857347801461733043560177127982744887832455965984385081829242\ 328399865343360096015508899403399153608015578102555023800984832919690307022599312768220184\ 482399042953648025098570891236088903405149586926101524954334675220308030422941880826468428\ 380266857796172529234591154963358190681880329364063007170576897345224615170648113523364537\ 437761970199442261398908109430118755048599268527256065907754430473645189029412504118268109\ 925894205336345598872186272167036198727052280000002684537926378934585111951748702933673085\ 617279454136871853458441729981963664473963234413330070006585956667431314108855568420594186\ 691612178730533281470362340042384756333647996653363690318159452118910429887892249100974697\ 855264353998778619461272166367832401278572331167679627343903969530328505038897545162091347\ 463992114398470534908816698985334680780699101236149218869360135362368190671793871386948672\ 507140366687896834641323782589493462582725768754274609752620759844263845863695310722244397\ 350313727706027267080224453000884894393164126872714885752743028561310560235453330483637756\ 447048725712415482770604216663510116924125547899921308780931913545627068040999532549455182\ 705264608689227283944902205247049120673498616171005017230642479263205192455719384124953500\ 641418005545962927021979336111308776883676726339127455466668046663948250835000842554395381\ 802146242474123778738530089106180270606767638122459243185822535851699669421480225407358506\ 388813749805174989196976852089883660465203566764979991707860866141608210896467509204751757\ 130225395287426437286992860100472581757633911782130845981331092200486712577138852034192992\ 561781782421321670434567732551693455467196590627482507944511302227933728625872916119278531\ 884640454579410956270180121346298527158707983186303809806992941016092830600471311108130416\ 140125311908551605844782144243140674504785647785729437050671985402940674574818795823986293\ 821861176389514509463967832922690199043650641819561026777969823407221311632583666850573133\ 678367007649219426201514764196134614042691629187894907006622216343485780950794438901508584\ 490371634297550230723581733113386365527270050621512743998437778326390816015810847782193598\ 803220744489953134081629507734867689224581169142591081652694772321403783717851744890582105\ 404787781193633867119079469691688832730981655583578849394714728223111383333003775340470326\ 075550084822565431846794346348337153219870326340275964513830404665884016010655505856664638\ 530600086766811132519885401126630466499747276983371725148483879278340277479889933639634551\ 553655952230096838474740207654295658814423200871809899401419806193049753593354690728802084\ 831263409354170451109290175745713008773719932323392647442122515041637854452801152011721981\ 202691588999132878682175045229512421868241607329603025333078885746104612640809221998944058\ 787140579277310874538993995606749737486416095542456272650322249028677992583792351603705238\ 185057734484265520523958689666515523885710979237092789051866471903754221149169046166397287\ 310647471996983906553383539575894842476940664017928480083134172528138575194646359066785850\ 199612780775906039582742654228247314308803022670891375185179204923886419690731405160774054\ 744703454853558825910063870637160510418771918749281689124837293089970618478403206529146841\ 924138723978416975728652070881421523480466317664630255658694436761927604015671738531762422\ 398571918425302398670820541558252856807450164801414420795593211581606129370137561554408987\ 116524238496938765230594797424695225821699180487660233682581468068226206893172899432188812\ 447547450588158259205957073540292364987741294193706120024012223552102081152465060926503946\ 863174261110074811694127056447365812358997369143385554941170476404872898740989262642712883\ 321368065751575560087409064273086276469117943078184110896939762779951782505861571495715348\ 070691940406168589293710426477438533900531131466918909924831951640012484479606934477348180\ 218887501481356550942417522758427929654021821959307371467840453716519813321591814303799080\ 563266741455899739719975303202742058596290226089100379641169194632376806479257252714311162\ 550880044850519892541334484320009012811181157023180444957884236363866113201711672421647146\ 724201693772122952752302378389481263476487459344288486565928245456855718195457800019301552\ 299593100886854099865412131248106028534505356057968453137393939346686312428486268731197071\ 221146044123175815981131583709736065021571268819359960066577364641426017658846705654560061\ 420817749266208380293321193189080836085687756572543002939556995306023968814646159676596003\ 332638549009888724056790280599827616010132603949478141690118611562733526986935843330313732\ 541140806485395544492524802566213392547601570026280667459532477405516089090102478635123472\ 070122546488539474773224821167630951648704931027544868872214243111277673478969318397254407\ 135730112938890898648993707333506534145568102764973906296287307958239305737773394969332757\ 980420199637619728407799123881570051364793519669521861540736543192889216125991130988996754\ 653216629446278900274524540893864964475644693632463644311077776847991003840636713062041354\ 042288817995419408342227046539878230906065565716506681226007408805748077958852490827642367\ 537448295257780407827705035875151620421155625519031314519903941343267902642709462556671515\ 789960105558122592345408111812706796575934185902107923224453427164996076238590110132818355\ 642277853056994944682795205856143661914394932993600824050242272824875620978422282919825073\ 657978661509044262427173896920652729897455073381027639711406975942586117329528243007177222\ 287299097858959251484540687953225859912350704620437253425282745521732110453861481342609286\ 255323137438098790329320501545934003686785627288133691513908636466519739318332197123810474\ 530469625771778367092152024312818600629076143535470808075784549411285637688184249035535017\ 269357732637438158725033681149502599388605542847919815843000533610748036822954371857092838\ 123832526943364716409060703123011160667272850271217219210085054292903883514781951336770987\ 033901099894140470452396436335717702820545861019195569590383673639850435482385284258279195\ 804837454996711420966692439763650923278823209799650643817500381005022096674345237086552148\ 711520455150420078649336365837367742625099629513171216392882478357777030603870359516740749\ 159633076828031047669339315086709484205564827477605124646237385288211905134894097954519191\ 152815629434640588619816845149673372731392412604630049706778225030661640254176375593366847\ 497070062097875648279426819433545294771234860697215918536972573116962134052217861350754781\ 397969725557018886144985666674977790056104883499178203989489829309944945888699323204932128\ 504790440540077900537723954159947039143233928245290625184023793148788121537196878500153746\ 973085050395373187295206968059603445792084766073169284382350374866711084318277882441431096\ 688445900026519467456831090477475811072738889220629586774325579632754702375441307143505020\ 578616715017769878997607098222325006298010917335126737337307972406316063056596600509368680\ 742259538169854285873842972417539766482226632615420065917425003564934487378580585261359254\ 041556186199495768857660576839503991313895900597501712498401595559850108649658015566408574\ 761858391347868857296571242796671381721439699466808935514989546407444279007285369631004805\ 142567979018674313787579720293553364375468023792475344673709500905237814328593223485847161\ 954848717123287850322790277847676936592615709926980616077173471063814277099499724691192639\ 486849617277204504623340377540993336340115123411500781692347746656920348345466097198464457\ 121380523055563518575439109172893658483820967276452390970705755087738227632465308231061013\ 532377234004448203357381720918211350679790192317812502531951205996386339637522184796459342\ 168206751184633711082984425983035738652778584280285926898102975706498168528489458536974820\ 311492699982792171684007170410722317224101706484010181066859373418862884931993286476264821\ 653146269754784487364008283990397670277332184448711987598583044335470018889862496450228445\ 456002326525614189868200721984208224616182490314473186110761550192626149708553384672796695\ 802322368711966525624575283972771606307860328932090547717111087516024103308137153276708844\ 697408622190720181549880331222914272598847205913418103045235693466790672983114538455291073\ 542337758485283817058644237540733586617250208152352934284313855830670088332951376649006813\ 865646180308827455523306355206857658522304518850116240902240670421237479867307079027929207\ 480821261094550078469272201256753474143099722362967135613155937844422707655462905334741383\ 015574899565967978353447577678914487302735252313937729137278104049408905517890227418948136\ 824803366935024407841269155232533740291281873961589796923506366528301780992031509113155369\ 720792776786100434405662781880890395949713026542073491825596027499656714334973434210556231\ 772154741822539741566117250084268616764368307411265662330393593862859192954279137696646582\ 092479240477575940263874859129771525523952323943219452883540258501801992279557746398151078\ 792568917170989809686297936350907504144619857561799540241828739089445803999180664439040479\ 306455045309364061923025869975122275214693311068390966995965815615946296041942695976361628\ 297252107028609759805033956884075800967876443071423941309194798407130783740480431135905144\ 374355392052395106402839432032200576505784176371569392145447346328344453281920758982048335\ 175310652990176402280190883921835731520902219875271874117013186351393558810041022378626257\ 477946856306489738498982753103884145282864896864247695465779507126237331089347216034295660\ 380794880800510318145877181487031560163141962214186495219542633342977282937029962660448099\ 718956861678194708495659819442158413324584402476400584832005553757005236223723269740207196\ 878376032208223058721569922423517444047046373677546675376399213736146264751983757729264652\ 542352016701246490420204067810721304738208880511730090854778084752028948486143871538656729\ 217237809633325906730720374338078111695131136778720564194039418260721192328874773333732979\ 817183770526000160817942682379456504116129842664364260407751559322751919347126628988732384\ 436318337701325388391783490587536758941602448290057259103840178579522291639416906620470210\ 613371853117474448981857970097185379960737973413709833061234098551304060793233060395285947\ 246808839623190938037981000969490622024429214011298724086161905295307407245304868234595699\ 872960866358339927075453303371272344724653288889886815906549198000605999809072756015820534\ 128888632423905343266955782255246855501140265336855217709527509871376878698560598919676354\ 113057761985337330874390897575773263826377027145360261920964401496210090185260972812587255\ 597032220656715880266468993966219143124751100280282723327925652020275004289168325391078002\ 718419788985113446124545009387611556357551709265904026283407401028087401867302063226293519\ 356925900675315561169511476089644724414640017395641082658362311163933148453824302812352744\ 722424017922855429800624757463096314037924120506231658212271022380152275409777188134182925\ 394090431485515063648451395499566227449492701031771082674455517223905602755434225521474400\ 531616024024842709644328584702684491799098187338005168992561305201780019141733825772262909\ 493258383334267726997939608038792576289939394643106323957082372613010467660363856541748485\ 096915329043756145651532766303817721347318349626498047732860613195782222091173097139995260\ 249453420633259434067786168267904237380752725168396563667027836633239845535497561408830117\ 968723566628397566985784494351445732937649335558057983430343924660200533084344834618585005\ 785200518823011292907500073577800006065943786268351131223728572687078646282952763196683589\ 753849508649126686829590934247659738169681222518507435075709433736511065538563503507058227\ 722927826602874200268404493904744520960842768938655314406430758132078073283811891110937161\ 055943007739392574506013004103000045598569220401207559462651638587875892448469075801525586\ 342966813749017372911146963470717340519468244303275502427468586225991068609329775909023624\ 352447991770804961690841200843547819029270510275832422668782509959808756278067865294959222\ 103404794279204202466129786446960180743951094353134377428564910937623192403422605391769116\ 023583313852051342214572523359860961648513300791042237701948017957695239197701061884004465\ 093814657158170666706043613888128493193473241338370724864106883268646808142181472969297953\ 688078998593515626578174987860562445259762887515695401876711610243602800278907704437341747\ 864544791911228361372170920912756429631123621860818653851197444870400534683283104892309826\ 847472518722146719341482232308230231611966775330961299905822568617605126460498355052952074\ 378648136605026205033775707208412125443705173635130955093546593651109036017155744335028746\ 154721909922819431724218946201547333257599519534424026746873345045416086624469637767036993\ 910134628589379482700803165804990205848359026561547030179807980133235279091557463354906825\ 702230565741951452511316041063933822295499692800474193215397818626307162951242932425543656\ 601703450200834480923080583547087241932157818622126630743898988199370279459932644262751330\ 670583398739334597677847952037250700789245622495982336235684589883860643523279709271549993\ 448937768213226339452263955365669736336955848730325337462551094540060567027542952311708753\ 723888160448407752454546828202701252282002342795710509814862227223451684690402719741053941\ 565570989310817940626817812299536931143774616147462825511700897162666210524995745301823842\ 877580041370762911028932770848476148491204359628147997012704702860598013145516453170732807\ 846801467239939352297128196693194917977198761429520125866377723003396182817444318684727034\ 258871171299542353091006361492068853867723515330914461264485635984207714725830469740865675\ 669195629165046352091316642129203031054992787196074198460023852947881869025229983505427160\ 580914495477993064834419757031525756177681958346643177064777069517006221028582902362662480\ 384995688967078429962663103040929774528495201483531086627106233844656767640186471161994279\ 747979343743179934156352380984537486865000147237932067493662377307748292537136238463338658\ 045403146215123963411386484273064151695996737608119243474942625706826769062051274572161085\ 403212461061668608542692766783169762720403242024300306075855921161726821919446110477563208\ 856282177595570990376991041718155341655022788511349652833213277964002715245938142262668244\ 812186456877857078703797100077410084458380264319461772271501969846007366584880731968667312\ 382069687140158304255083557670137226124770612845679118195652493813870509482064306671490332\ 826175712213400809513527032553085015294813347468651728891150157227087934068032768154980218\ 797163966739806841445703098717488426143850754023169206230798107007381965938327696681575943\ 833666227302640555896947730875763023898723843327014125891768629337934445929133472075422724\ 950985524294226890097609600037102271247971719817853556513429638366136375599391041209470018\ 841293622268761528936343099609138063411580678107418635274298276879535794560965912858554420\ 233909898398666210802977358482789067298493565098342094377496297364917739178155354456062604\ 808617963923960771055844737652000400679615274050887678729255532899984442234712740801221828\ 286852584254347104047723931656096984997090251361652072952466921718311420516387590225024406\ 089970409339578980795216629145402536680931340298131751800122538203120571418778306562038056\ 074690964665718759328631650021389838337525607275060020273905036746807175890136031662531045\ 275905470274918086262718844969468895315661324588742003423679510814979684682387137517157585\ 767388013682864348962530210555817976173739305358180070878266225830661811933444447155971675\ 318624312930672630223597538408659769711180017508312217652398893284197505444383685638366837\ 122933032636205682600330205360507232615464574666488315382114928616855773209845347894950417\ 898821955001499101971255207702948256640387113424567295458179450853613484742816194990634414\ 523393774403963628394583717921357239708655977398903671245022816914553109834105542834274649\ 384159174594425764203723548197214642856579170488263456132914919494686957617049734022904859\ 591634185983006110831586100627799456945510024744771776320822286943695732181721285957464263\ 153520531782997861809944409067459565437774355577451270707766819494113079678855827945480306\ 284732335825580654018271907063156210644551174315979232725307001209815462535349385739903438\ 462444854938279057961988074998417676726083906215232644834501385846962623078943543027598864\ 473970334605017369336574539420546374648943226402501076574539618339368169508802177840541674\ 819950450226380531509220302279148378470669569587020995808310606169908080007540977911789022\ 643769614337972274513231615028408910892449254796691987367098393589915087742728754223885809\ 378110692503120686935099119704959148671797929929021647349840629590521039195613595243238698\ 752763704544524903831597142649440256284004218667014156397456900763740470995799829455153550\ 543295562072189836960705167684603835288145611390987307725458270241258293195781577899252546\ 086716213516024465824975336014543918777641349397934700766993460044745608209347527777882182\ 670461640664711918016431212316339412277865260546761328851023573243317795114688432525665849\ 339222594260682703914397533412685420151098627839651274179249201651119995981510956751441216\ 883604734986826061706800289391524740230210467667466119569362923790304908530049539739479213\ 896221566702937154853423470360924688390626449641511296432021830525248530782413897954839341\ 250181257255170206150775948433541297011926006653944490668204585482983251553592573804226193\ 451957794878379681874001891373527425790797699000189213466299986448598296308850200219613195\ 436473497866737445794968104721532864348306283829068698294219532846015871332241429930450504\ 936338103550429184940115532008756784205112122202410280789136455711539721363137998387766967\ 357786067073428216011888689064531380126622911907979172041903164404173615288337284078105128\ 956690974409048226528150426413761257687970617006471925837821428369950040823148105919162109\ 423142591335253756224434068211706668433034867663535896986478319649288253479209500848916671\ 842178522280072623046596430194382660891094530697808362135312883879190904367085951389033235\ 019237255184001277300958506936068237600378627076909055701419306979297756331118168211528469\ 850427989783423164008711649603111040251167816893387330978288093560874751435105328058849536\ 273978811336231749099540721618510622877467534809568676706150182545142179608169234850363361\ 851260300179787691854573208022023443631068234281670907232994212863489233334795143723881777\ 090790428047561187060753267420250304929305760535525966249107739485288295720018105565644597\ 016558134709107304760830538454978831701653979609756956640072576414206839900075122472167027\ 829563302425128889911060923191683526442792244643678074315007589414227489076394025842097360\ 334750038249471775360233908200284147294466595003590592479606080639023704939764358224153531\ 098392096705396693951953247459928086965592961341405419323508306894541574152477382219716932\ 605436105825885604699680251622934610435366227936507964079210424274279114414134300729094425\ 925720623009423320614989458343821073606043616002932364876365226212019007791563872060703377\ 121357536271853928854476259687984041564779506875008516236369335787021218369770528588409905\ 056776314296341126297455682992743429731361930271204637150897108750646756318966476691497005\ 080118420109316249498800108755705840448734623927849359296040221581178795106372209831419686\ 056357849532547487049428825583440251320222910490858507620602591650975613946139486328331405\ 385683550859745658195850841169110198650293216028303864353715461776072864701695345856944583\ 895513757153579614724385327447901218213630259871238796820798200421202321265048381859091341\ 928482970754833451061001526802443193047705691394972937163183037795404396338085397972413537\ 752121710024897084722763948473630603195735845002294792160425936400385804214347740413328060\ 538700001178943658864881860314812400356355229950804561181931489262959146953537404966236106\ 759191526964588169807523730855806115251643670080723702151529870348548704858044318976680884\ 747538588062767743794639484768368860038998162626412630236147100124939637818857924432562784\ 779741937763634686719180567355400920263854647691626433804764735207404194999846872727818737\ 243702821756315305750095986278103395169990544055954107325494483103410036029385470858319272\ 763095730002173864704240979404114731821621589020485100741959568643924103813131479631048950\ 140457705778065149770937585844037008577943725190487288401372964129520270328776738670522320\ 366971267352429688291203418710075461469256350802589204673159238377401207911831859949177007\ 567385236112751325702805305452980643416544425675888345247186665559367364609252996685358086\ 685729776476868096850380396577506740531802234590639164703034897671198152063445160767171189\ 157113694162810394192491478919445702469009171936761841452422480071136987076592113993404316\ 929524789170785404380992947492627820912342686810636632436704743934223856682899339759149668\ 698065213178127481335542399895844454431153998900745643672543039575770480699986255732895556\ 758685333551018200539137753718582311162241817098623610520883290229067452268951152913268153\ 137131990970298674205426927057447571042805142046491392624228530693200831208256492923656903\ 760759626382746481745314119296321790925827841468353827988687419936029439741653538209114964\ 210286767050677709843441281144319615728856470567979378693562536389903970497953931726152984\ 303070818123256142429632701744554142680625812279938117636348862019925169632678845722882040\ 818425436924717988931921806965856200200588377353766757359298040261966348621844566237532006\ 894325146387508435589315755088105482768389059736224164548857603445346582738097439060864125\ 910534150252604194104943513352929736305630542488274426063783434751270338343697217558932755\ 390870839192317767102626100681786940300861529289983816877721030612720243435318024588143851\ 025938823962359897753703011528077013003751825550396671978602650094074828987753963121940937\ 822278566828090815895603900710773287279788433694506859331123149725807256441713062480534882\ 926699498379257530355094925596883670351589973731449191450303841418684127826702752270101712\ 339213312953084795941432903732657623828665421663664936495833913542949187601108825351863007\ 571458715912680455205503732260796492789733489215113057817588341037709320461952384517074521\ 893679620328810380490325943091589484692827558916365300695763132998326576614663266508820934\ 928053470183672109404719429921437482981505296795828170122391932600300239613000261804241261\ 642345915699092927348474813662248350976356888614178592813137133893845366526491009412779986\ 597314049772153474553357056773818194150343614625788527357491277224812095975610475229107365\ 246492217549708365552859559198774871143863431109408951753095074008104272970314344306571104\ 009998417693033152382496205323757876215570102219648025366521594627618327671429249377579910\ 953259375807843581163279524553060046348150761684692093952116302636610604310872270917433043\ 343716818782774439576354333069139329480847578341063819223715926458917107369318087238565622\ 497349105820157006858771427509250846128235395054460547976644776121511149814488600476721362\ 698101075399459727262214585706778053140615578456912923534166498978125896260186318190120424\ 467554458589204336418121062697281301531945022822617245145092945063045027082993705091211436\ 710123983796195506879479060470488019176785582611746147474988327270190334904615062118140222\ 948773809223445764574999037605130667454348566067159204703785144752511767743412404911043711\ 001126931525523687922169517904857149199894182627793694998061203095721414918323848006258228\ 678216339487636015454586611222049484045016185372173662727422716269157981025412732369305403\ 121929494147555989961722309473227822809692827879352544157313868957755394528803557395712820\ 005814234599038632136208443313871239047602620400983540818603586651509735402900331716927638\ 266468605186080047273574247621173233725919002356590090077750156176579050351015764578397328\ 946020992991310585950626723895490046348854883587844625532627745714067914605419294402168643\ 042420031350597777433589215626512243727919337284834370176588839335349410953563318708521918\ 395492889299697933074431586778837603627381948950880382837667810389349561375056086400259968\ 897386195253777987267349048373674985816891078123940947847495701241702653158952349047822200\ 829847007036098123380442443477007832886407876474648736414784479617985615283881904726872321\ 560053582986112720884608132098537202245546518057088743899588720379139798736234643476179341\ 675302262881610533857492926451007574877952039363550367313935473086354448302956651203148314\ 759244822010001567505495231121608769447612363656076067682598626416776810259165746406805176\ 814027566335518874098263886395811315934828710621264985462130007888152557606138312190428241\ 027575726978272094371014914110258219917207385157816708172815693917538480417705404689240057\ 246126176999481548166686890650934613839586119019270284209935658503733513063662946853621470\ 831295736089546079918094208204021305428366856506722539135536132674946120657450625987900561\ 207104037389176008412953935487546809982095660613327435462355461913439798053994024055494971\ 845240678308055300249593802920440428894430671319792809595998493596223164044290951325361734\ 441231816989677411650398761492104323290963878500365428327748816619923261107565762355563633\ 061062561483874616516187902317025851095255935971729826304931587344603850033176762764169885\ 673629912659578386258506072242918191292365329700299670364188673336155963122376752537958154\ 722732326721609767087598653396089954492939048544857274796533117412139828951837430544574513\ 046239051860499289065062890077039876980180781135104694732160812880610481622412049648775030\ 487962747479712420741679879000954539477093020631128336369235145255308227675261196842379158\ 078575730685622144614992594607983010967188314694116502118501618501750847208430224125994254\ 929657885392869970472521738412762781440626738427601428356319547727726330408922777040541741\ 722186723257043175317122946353225184574324923593638674246185958369285048801977851445625443\ 038464854304907538314285854622222070974464844139132317151398168240033499094149260686180086\ 288223563084153475014564041633895205007194877511300045750164962108063404594932617953130792\ 887157370163374777419593002572521280179974370593022235852192502313959183509499597067440427\ 950464940196945734798779569501649848435190622394709934087615695046229794776728423658461508\ 658574914083602363646773189993164631372953361407836831128317953926078522616096977555351171\ 275279453118441954993093134463720713890646424152840598504208174845705617869673104209796893\ 381732705127654455731384435583436970533939491545565552068706453032224148863821071612924366\ 024618490056037817327771497770955484451714758774873650603334913448268109401011148399031495\ 435378519752102482572318883289369563375051446130045821634099032808910954315075165955235234\ 508047988944469568016390188555114112047732125184615377454903595803731833898279163347225338\ 171679307906688159621631782292487930748933363690075805610531762195312661423225877215512489\ 438346672526111507357178155856796261586710589582569629880891073045187120503912296344297715\ 473228998483501206407697079208784846681493165633309105348142838893080914010913125271926176\ 964821793921795549943890667530303121780154852050734703381344513036182533151380189992643893\ 304029832366492909802719543742828296281995607279114085881840270659203496290995326210085056\ 384985719651358705302141383135756740824432071347973540434993811377333367964948428888145448\ 244452760977469422365922425033823548820651588340717797528387853420030400811663873905001627\ 265348791986411729067695966498922187032981694172959258339821285346210713521346087906957600\ 220909546484086061821156693278349121635745108254566551313066110762746968569360990381150435\ 346689691741908487608301307915532685350516578947705060930103397173324154378424464556762737\ 904834952231340027890150914275314814638393188412512343437750833332382263843709855149567480\ 433949546490603380448273841267857983402334524696715826859222037597384411974694471500718566\ 270892814395957149180844025026674251863774706530808447349141202438445653811021644460990108\ 168070752956251343000820087665406084776522079617531071135300032785448374143244909494643915\ 869065000736243421317418415855210493800234835949377070066065265898772313620656242551392000\ 642974101070225828467052256340177424704597985399985725835593669760231924909559883365148197\ 686415063943307120200752246232788713400996933102339086207249076150656345756859266226154906\ 968641684218893163954365532394353912072287233385134763373343904206189876328238137253250601\ 547514573465837402503765096843582345903247934339681924781974727882530755572133701530247723\ 949509384210622130208887803891710651429616341575087060688979892641273412924334515705082157\ 865857972506867811556351461022423746382676404485552401499083789879227693647336262767465285\ 681387979399307132874801602584381527570548737909489485696717868258223822197464912452289454\ 527981048371758332849865320784240949547693899923805416792776750646094232436287382059569128\ 766045028001410356974400451940272681389266969149874067080039625230454051417569349634125920\ 787485762896796317367758956675388923617079951637412185354477713593833729901292174017179161\ 211579459265359545340464837869997287960420085790468486385856403335569819770906940223314982\ 214329826286514779551110861124314216552844473668705967650194024974686241182889528835465847\ 357550611408471611930201838398991320502058631443226734169878563378236057282799127921915138\ 194944454355761154807905879533312958697663457195808933441159855526855374257089320743681205\ 241004963886476995473365764367009601404855644208329888037176954811919882017015584783089372\ 558307716957223405323400201747348500456703000404184202963155628621728238812062550757673123\ 101909723640551244168825273062850477849467641206662292603127802607363271223807530082262449\ 916267969032038234224766137935191785300204106947317806042338242816933708721063213810538806\ 087942370330270326218812259059381520597144110735293471903511533958031090472021209214334994\ 786770698276205170616229719405029804838104206378163173090141885212275855127678131315068997\ 411733758985295791720063108081138786076803159601362439046197536262053480364936656850123233\ 094053868644391267517633310252976583571379099695745293259402663745547834020178944435002748\ 592364953558238994514650383172789263078196790595751949395317985215668100080902025419770073\ 832167506355361409114055266146803601665203830925510579511128245998956946311640237873582354\ 850558000243871888673837227340368144067187533447305346976553892853106099658883897197918439\ 315122429489521089509377842532539511071121948421077044643562278690951911233021072930351686\ 590878810087820896624129587896490939370100170351272713208584171531079240883936883486071577\ 759928881746358510798975476490159836504220450800782716069036450834518566277687614954883670\ 494818203272771061839026285040843011909993163016400467856311379524648211994756325764804466\ 656781139684625303247644907071652445515020670866135661663407554292121874594622178681420152\ 881973079948522547742797539138964879108370133870899564033995007682300908636423886605884506\ 399493294789346129748377613796806975307486800390217083243195295363740506393494013122984559\ 671294109472224031073551771255889076399627601487332931592256197848191291943931725559210789\ 359478684225100571624173092922212998856084472075303608246641343438082654850318333567343402\ 095027053197684745250598393693552672526831903880701953029682303901776675158391646991758996\ 861170076343956288198121422400778655537810198350620805080245372652086429059564576074774440\ 573785374658344243469828840436535286564432784233413149407619893426058163696638744287594444\ 361086887259634011132992190779992898493293130052247281765175739540734946949034171094941617\ 702383402845339884220280565455366409969154898924745060676578645442871695536712447108955981\ 874632852069649768857585634143155221610213518255973224661967076272780062035047624546190489\ 092894544056505972773419973035602601467214284781436663638943962855729289678595112243114035\ 810107925988941094267407086775273230169957521840033731207160777019184644168347004479489709\ 926861805353905906037263020097585422325620989369072446169902085496543469290667284421587157\ 339938681128146753504674952294826712553152788120177321120909063159290535301391162715635854\ 588740626658996451831193365898529664806646149861959691776789092541120582426676543611909507\ 299626434104294576594913344051051600550255854457097885478754472073748183562951018514172891\ 656120407384635107412516642747557601007206281699644533149065348287104684044306334772612698\ 065365579320017769996788065144933039268708310128784910225964811074800267085763888108775754\ 535111702240781775044378617756644745068573019972023934022875685232352006475820911179193679\ 016617541963649401359718331877249371438927461126051021970136248391926932733308457058472169\ 256589196042503975883746842752342685234399500717930194783421854698144080953382810805536688\ 096394870393157724169724860393391995546252586449214542682714753556555859609884380497650610\ 848337604923875925687380381970061743657257172826688155946490354174670973047415914951179138\ 396331091387445533397453423797015169933688037959908823426204918750379951075741473033820785\ 912924779270811000537380264400809479736586899792556596781797434449854483879533429751643524\ 469188690791388375614556665203956150175458398420077091616984828378020534317437508951865889\ 273076292844139279047400683927915597998967663917695690014291387162034581304443360268408283\ 315548081418910831521112115343457817768966771924740924178489503900018373980291054601528221\ 939025209958788171188384577850612610874486824613150217106017253292887510552033998976660180\ 752818140629984152567658677702870211100971382903559508841218192811195293510251417989964133\ 681389649677711669881225194404022975175591519728022658045548550232933575952856368646768700\ 578896243178238532028087289650964863309041316044712981481510707094408433874094420504757887\ 026085598191353744571614453127992815250345957549308372300550132449790747898541288334576048\ 406909507236128173045347111961658315076737224410452074551375267827903281256451801446801002\ 142317232995043080945134567308630898146784010896230002867377862222572842929814408561194680\ 975118144833318817268454381283438732677208365698726705776597432017241903821323843757327831\ 954068971364501322104007957163157548145804339799817932294900888819459879000132819220112407\ 714394772287214555759044998334067987759818768267369804893055078912524266144160470389226312\ 363749345590992397516577884452956114320103196654628448888518824070959051094620376571177710\ 125914723998842311936987553050069347844431532234194158537507359658179531691702418697990608\ 771693262262633740452920295195842461123753989042573200454908124986477395588882008213689541\ 022090404160026959258846797456287849505540002647497630449953625022876547868382940348620417\ 075577411307273871443284065023619974373653678337065940970137092807309170684648462802118197\ 089141823050460866856548760045263626947925294668390169526078324537545816079883495073071039\ 796930029702083137568450070051809150286946883066835896432946297145635018065206224321546398\ 671896728198100311554344016595053546430620819370841659030925762514266032667081901039414053\ 810454749544907705230753303063332786210082592294017885584502999552082712301166889655128630\ 464491410474216585386850642906453721267111338556606539383601432829240561876476787389545602\ 175072656441711240059527395294761513917363528182542073426087949808772591762514664919954431\ 054299205674306678342470630595435994012740268519736832140972723984955734048888403971563761\ 710980245101979505512090495227414785580088119727500742405220029681357955370372843720050128\ 259833774077431701193410722401301604440839657535745587105177358235477435074268968743619492\ 912832510260591130903115593336937317079086770582736487490518835164740467310051910260213947\ 166160524707450421541052066264180154615541037408371877230639325735710743854701728817714591\ 774239782821611256969124544482408848053160277455768430576895799853978352693161351654455275\ 659119017349346439759786697850873197173494832969836369442171553517626296576165437924243620\ 728200985594409637364334651792730798595541491003303279326736075273413537126794210047274603\ 976607764047596457957630829698573917695318326405468049820482437692230901528851111494729053\ 582842000642159789730827091734364745931191777913201704023136135880790721423039055974383501\ 203034737032758153526347305365014310757933042173603663767685683856021317787539573631723661\ 411225727353926881790519695867687242636432148791953351019961529355389505021669269816008185\ 651499366801044501182921481113185371179200183721879616072062152305098750600419580036873168\ 103317058876627837374554941656608924758424228139214741488915396904160794479827789793945654\ 737222552863483098313640340496657786296097880049390207996691786765457040792787842909056868\ 978803961215284247375360268219619935834950276838377374099370836175420760073006427616262012\ 119689855378958067551767718936798754630316390330297285089456183189247048874740812642678334\ 661976549631405239219975997358196961485982143998482278341608159628999386214812184723813025\ 917265064138382954700221114000365917639630215295767394413717246959351130463207834893797456\ 435662016438083717565921512931120265076252544704942630990800063007650791545298552856248167\ 481770564247399480449217999235030321824243350788833613174001807895677750497848129216531268\ 505683847273351972617446602067500783604907863122922034786529505781264761909775000962404125\ 034388384807283962621450457839550980448141064675639536426190938949792916263049378881143741\ 107936302883466596610022456128282993361022873628361316271674590023879286933270896695583709\ 015629997130346424924721155060296040042038835021509587569390613866060630292455733434074096\ 843881527670309669786275094861434166180578366498588279401608162650769478887987781687083671\ 136084521307300753122892716452092880646943180868054286381780071880094527760840411827001321\ 723108461850643346122746573032996360272646283730179870102037276837088601574457568597751618\ 067471324836951378476878573521703891439898653002590285659149683494957859507558932439059927\ 709802415450780482538782899618397184534523329377266446241784262245149172084255398589120323\ 386925414597371177814251466968048435203576252148296661460496976641925985408315121787774955\ 647767183215477137282097068562449099033908677349179086594795541179659381291899606739383013\ 143913288685756043691028699691385106196686371468956981743026834530501779066426664055080948\ 616331357710373520733734394256168302194066061996915469787354219385558090907881709669145776\ 969828331339620676409596957933409975895798982161906449838704664799723163018673165787609803\ 860070905181579719093276571655561929080256939917752629510516985990315654974218951101897099\ 887170616992748682907153355107041654012934255815228707151342519770647170372587676745742800\ 724279522939392083375306422034248534996920486418616901787799172358283264472046794837220017\ 460695553860122283915782202467457570436780894608748252905776221769955331784596802622159435\ 292101717879388296681995449387906029228880034125519143575312064549224956460874479025738282\ 012541872220199388909473303824974195287675416835195818967805952535028433488893236121147696\ 344433347945199581103903271244429797754063984067525769806977286468815839425501982038612470\ 040283378232282497719084074570072289310765837419993291788572084237076742829347980463405847\ 659584916698694232351728632559452581592976379218159200196039589159838545115561073852170272\ 079764430716263816190673068580786460067857905064596018283662136534498323039858175296785306\ 411424958938124830112047771615903987724899671835935975742918117747350812956270698640813864\ 835034972088028791590931115231490274351257786934776989103169597216018745037722401124424282\ 519911032544731036156473253788996570951761943750097530517042513135664039722875309585765570\ 965051286847936739139989147955800243442623577903404912018050243242865871532590932209340578\ 623056058315071240952749988523340704546994849082092801057868194126360985515548045421466861\ 240340199310107669813685683243525913230628203563869652695239355712633245186298757366326271\ 9380221770020348551638219417104711019028877341823736981738972250112", "16570940594449550688674241867425473646648690681374316099763498099863146330209996906092559\ 691551097398316242957988023229502701153583224815411587436774067137110605065059603104899863\ 689798510778429765986191754049259872399520375709881193692819552575414431070026005995777550\ 531756241179528686457808666201032136206623066317710103258842707463480333513555844332454314\ 580108641494595957093883459804729096084483650175439183992412790899376329674890052511117433\ 593417401288194287076951423058816192963088408649958209920662203801011752536689515729004122\ 335906427430425915276646755401102628925840280499382223119732170999930587760582020385827816\ 233624251487698744688545912167127036752105188286670047177927191958606341308628684451172616\ 828427857392661371051125383043872056485148752359617720985231846787694466072936055466626535\ 920164527849310780572612785286727249673457793497153343212217760981800115908647549822893508\ 001189534557962236186694708134771375051413051395836683200360498761435924468016810794627150\ 154707151917113596684806434425791439636084934993325202303729096753325692538287745568297076\ 617648621388826956739129469628257274943210020007870563745790904702483699041238154273663315\ 275105897309743202893218476291728322101767504992242686501300244112782888192676260476520526\ 483719773970535619138744621733935089393325744497776207550688282200424540838957793859183855\ 030255881444701710083679804462971631696401464908101486299145476292988743598181932121587450\ 844803103290087119676061383920282195843971182613201962637394556991215724937209737798826609\ 164735545782598202317146058892527025173838054533279541361097497078955428363190598205374724\ 521326252464829903301506578696657636629589304779241322006856795093758648774778192841566880\ 058954061668065334796510517699057641859900906617789125339844118362982337065423405146220596\ 056562300954294698314558086958286421614809190073606580406652259058398691420757593814911632\ 599286268428798710134300631362492517287955546068069536544759155264696204739401915405047259\ 558838920797084577467546224472608523491245314940834399330187800374418445997511620247385536\ 469137905949455356434251865893041223317361356038278029157178490974670859297727394451519564\ 881620327137722642961810172048476773286496030599654549252364117292299014058611331673493804\ 021993032629944134052475561091632384607526127754826740425998011936093971452558168733676059\ 704297552343112833295893189818671770809099429815722142660702417514713871728466918205983283\ 872890373075322185636781620902054614717605579045345033254018616690433463291298112960849247\ 815994321930083982197060789514418619010269230460340048010604012433389844013158253741564672\ 436647250646514760400580021974184366090518927825927619678456765280786209901714208361936714\ 601874605291957741919407078796915500547783476025174156331673648501387235155794785187179582\ 907365006656385692970741816150159671865209659395111768873094826321085093742339011168758263\ 008051690254587134901968705787702378190303010865410163776169124812248840248313778371177581\ 773203786199413392078554036469538166646695538263934518029822131638803870519000527558913288\ 381334728621364799345850577245820275049243628483150174716061134187396126531998503431801076\ 573550368364209362727133957269053946248410108135947162883142584409667696362449868911288181\ 396217709453407567817560094568432031175323659672079348802200739222490977183078683516131061\ 531153347527809274051565281787581863127153579139073412881289888792845850213082120704609559\ 921367644201279988888342018049576717745786399677818619593904593676764144021237820472539586\ 952045935077412243138128309226148948850040714445753595292375996134279426398247385175406541\ 430939416631898072341987303095343108400681592975927206647604607049908550456320381760996957\ 529827893907768188703923222386738270860429586693465640848799560071364285556538532661321975\ 826755513717225904443193003801434627573284885032072915497656173027253663097337660574083063\ 787633885747311562284586439333841999831892905974473161882897102107140568746733249463747567\ 382127757960971380733777075000841689688355103081337856305717903726750738577862756965094592\ 582357487898496112555864699750441047817882344945106411688131017386126043429867793253529657\ 684268872129701560609248632825226941792972548391296446529306541848552363184737672254358987\ 464864404414163692592951453715484223056499204200589227622722522457095919898362025805044746\ 003391021791104895165741251471417371047107188398658426175619860382835788825481892538691010\ 426308214303654481143205036387364376072875858319427842914653329431042160289446284150151934\ 045333872929268856453832723482457576320071401836328494423497455362168210711771873320456007\ 443686334623274581417709884274616142643658258293639486245193083346756066984980004933039736\ 636057582797952246216819999558033202125617000599454166418267595512175825630389889378126768\ 552000593996134128437192848521804163452800434833088141497566677187041405695419747699674528\ 807552178177151360209038177362078356391334447931364105260608406526894493180933842333655149\ 754033626803473803407640353326085376525825675602425138665997121922053939061286554155058782\ 031959722005217789193613571545466125378562057561861401775577596007039391515081691500180053\ 686631100363627194008627232998992086870429534553091524829057671178072339082797739364589484\ 095773724876689470656147007601897136224197438623291885986615927847290047257207325498950332\ 600600675882951040041293608859401838710576189476632160734500817534218097338100658443020274\ 188558046114550688584592973599508911942686620264498651989772826117486855507872935790225904\ 925091153700177874188471993633940903659740935076982545689515435273518918156258179986783680\ 608258603706090751366060936002315760603474643016725429924275611093840989464093456544483541\ 358717945474938156292298563384698240118005973099352438133323320540298949517071390425196268\ 427050478985141497469137872960968859324777856513321783479167889088324148724064614398741229\ 239653374854313989513827796223066279579908334186382785966927108150912245653005014685138284\ 848872262019246029533118414128000588679980627030901626039193647624784814469562554312146772\ 979137251305947356920280521465549831139793605197458035707725956936058993977839759251756273\ 710671132382982639532703339932574354326865282396116731441846593739884426489288484861595126\ 579507540640792396703336523589235463350810652484861713573418979445759264458821082878918086\ 351414368291182584706691109964483455579621560505121960169250466832701714143980359968361682\ 299249847446913924570607441133757206214420677537449127055129254902443750358877015766420835\ 814293755366396969371762439897940284518790225245107820928799245005845181580393762526382733\ 822143931350502154437216237101705930328615008273563120572138418916525710777338351966608565\ 519759062970825934003822021725250258631965723241073905303776013215244865388834107234820933\ 598896431612363042556275897437220793748116994505214937155763898171598369196021879574928339\ 835586271388241949948203850793517587542972903943655770288481149127553367376946616952183827\ 075395987146716233927829066384232722991192074729800986545816039835944642597269664305741218\ 261099538539162568075285350768211868848759504492788697015411121589606193309717310688289125\ 151749708524666474174663009868542447974545853462096205490760748294006284759502234393584510\ 489817091225602228068400170301553179617596242961255015164814797212554177071991647936545372\ 022414738904707349663229776147749173978873330131917467231682230996074283034411604898315277\ 257985887669181048755471779659284275815994622977636415635246971713581354942579916063917719\ 765665527649448872185786444827182450464483089074593932921718915701794076687411916192379420\ 460787834709511385680688068131286593152285952522294604841818449492902500828039345110163621\ 298017110262903159370601290061999083258558222609756930428764593682268509899113123713243988\ 624175590768883709820700308783691448743691022621514451496016155665028029912809623077896657\ 296870113256382753755858401140201128296248003809076947355615999156379871877401528292773071\ 924349264512533914058917358314062923903086236319493782101416736540502076445771735699521250\ 494568405076617790263047341430717778925062086476919099845003294255737932960217009752532524\ 450339113564644077630012267112819428421245949091616387368183195958458172327505717376614656\ 786878709034009154204446947840851304779667848081736390273304924677063644544100952008950905\ 827298894925782759565568031909576230532981117505774626603475446945483431705287990490444554\ 872006989311159965135064845634570226946481486258900108618301086652227154134421175149152081\ 093343745225448757204015596681832232462482968905863592012245789940713151278288054893013093\ 811126025484661361526246674401709131169778985424152631878441305640746879739091564418641109\ 324366333073818448434104402815311838679325237922663141034570779663188818880313457533535676\ 755006119407295188263815089954239725665142159212281315790093063816455351351813928680868809\ 510482280314474852913262977724156137174039624211647665654620832484488041172211618923191679\ 073787109179439073077220486417307320886238674854884482099132458397416254527495189265816687\ 255371517371945224798121157714366672202172348024115985154559171990626136387667315370961725\ 766494739509558266194085909748847626643046239031759091642318416645956068594845488673788751\ 739079150696379317737899348271200816347564129891849186849687944799924446439429436993554705\ 240949115639378638678374555254298167349495572707520048181798473795261951775250992525658920\ 462978071496269225572198859142876565647685828256518502818530904139092152894993639428251989\ 774934000596424546228835489933826417509583204965680563722694674670822413492818786453653518\ 258840155412039628727538635866503952384976817748956505786547389971140903545694595450746745\ 443009471493708971145934146337477543638543664146900076734543367504201499685070203204524529\ 706972494258876562917130067876307322480883634222235038435526355993543588581645172523860508\ 372786117352281319665395527423966814248634538837369681255655273730554999977317303627840762\ 500442796006614366111025815741314844919904289973351367137969047072594049040855538080906199\ 222343718952104319230467941738474680213987606039662948452176187972593552507642727300421078\ 714173098033041895516783417066228763058324345069636117464176620331111798175954960228534672\ 219142559159359056697003080564653064544783163278730536757868995245363563545114234474266063\ 534023546152332218623564900486962754529597424973968977601923434080921204048176842120531347\ 813272905375197888040438069598461312196559356331789372949788463498140909082727249183779456\ 521594268381021196752259346000641150522241633045681109319363297425475363998363318911013461\ 853246450916581406259021825662461442763035532997398243035290418685196321447993791966267268\ 901150936339713420484842956391981013591611853547885111049885012765668613687523808764833265\ 566370968557868920062401202771648941679664942447871196710700533891175721968587967906638745\ 859472050298440555091166507824116827679365329102047346268126444567899226849130155796034020\ 136368846930763025653751948273777989136153770692140247674844691242169551223264894823695676\ 580617176196607534458529645383226516884612053364563302821848131236716254773448086387444796\ 745845185004697729375951879127467988781179330881085474868251277465468428793801093692341949\ 986222435984866802472765122427048483837885628358656400000160038945365543624624249352843511\ 352252886172685706996991793489439909192779830529163540728599246252197947593480074080489521\ 727760229598333214960392041002947237545452665682530646937052366486798774131561102123824235\ 259122592181128334360557115912008610740893490986741152110931680108541571789778490807704295\ 275022924865624567363721016402191776641103580770859817893299513906016069887974804950212042\ 912377036694205382820414143884852923008337677111714950294044985518132769477026227220600494\ 655699795777500434628528905406716631882210651552412315355024261450688005330445711892808620\ 979702620540813562815538932903495676001817896614458274531998362096025944530372847374502258\ 985443906595983114644500166817523317830901416625080328634795778525562500040453212033035456\ 170906903976395178223290528807119722810947523664942879779261659974688181863756103254577848\ 796260276771338639606960716669165581501376880694081052194907811770291835566155604034879611\ 912284108103570563084283928166999209860628419772034569534622214947562413618545733578426618\ 081747227920173432994641485403749249265957071102326302700424726536130069014412055380238490\ 642850254652930139839649611490055238916772034737647794979527609722746245859147819110812120\ 018949817471655193289952117931682616480296872204760418608976658898377496120206977244362758\ 196712771772219488993459527808841453914028509298956507165427663736590462293194757967712448\ 107671513476623569513810304968636659348267796082083066455879220615641280299128175033062136\ 722625332334308984512949657062146795639902488168404848644782455974221724626614071472223134\ 731375397801067756146603030388549763480593477554764511157897555170646363177897001058146520\ 216898077791209097206266499047252825883109407200984293985363313163025845547153546377319408\ 297888402276206488099939896182087044217744557268362216081217060033937645643789629997712918\ 533591821319319834469371650132181598078803957886224137114944988969734312746026674223273052\ 391566790672052040646718962378608552909938762642389469390343572652348066454028197959360843\ 386783765237360469510933804248771988636348549730003502689163592430932290222444792228942339\ 257716474373233049990927748676273055430569334450371169317826089622086656047125852968385135\ 261949960172245047926794992718636541357388936383478222140101861093632023862456951750052706\ 098533172342214370485966011780604499037464851639266293548831046320167049649320167231532156\ 109335188931336237649748798939452454489645884172510816217500216466366872045609727942032482\ 496246132131645252369558145693493510820243074490962474971805184614655375767919505004526291\ 656460688112131087403855918534578893617870578480247252762140989263301453206383725075171908\ 151858645399181387949774895400211144462887576300292593225888332359211919945564862328557027\ 823571140671217287848648685825787047836754054240934030183951193301951240285667211048231083\ 760142624700899909449706669724857906104503105636948169039946127638398027097295517075674527\ 856232318527196842041544023774726059437066102348575124543245850601121470822697158851991506\ 192583755340469420769850424518197497699882630342361107156432103351869344884230916573988272\ 962364368206459068041067750244232644579557777565591369979261214709376300089789621760018148\ 770199026473007041929246658849239220348683565808486212040923008150490908706877625723654432\ 882794040367143797929713634448927639503992337136262089987581201656417157958162158592392346\ 988180457984846875932830615431897385564311000209785607557082393092860166345830811155788804\ 713041092447798650847557363163681342298442894609588623908962044105751110217970202127337482\ 956653861549797393876615109018168593936175217341659624035961133077400863394007220032694626\ 972973278955272047641244460062000321460697595988645236487373501051661457397734191126465421\ 239653577049772263330486151678089331371685241563916165922827206226895317817994982413560087\ 144803225289088518140293968985153288887237675782459096143196131349318561925866475291483250\ 287294941365676659790030615982501570167126413740800217134262756950601747833413949440156509\ 628845084854316599842040672110997952984040911562096204701516197885195651238641116631154482\ 069822557925043703656700603960827792015093834364526994660238091610097196913704649873224795\ 318401161380640491288567482409202722252566004046323170583589101095271573507008048119545797\ 238023368572412852112548123618150923660645314025145897766465750718530987218766355554545416\ 980255442206014385310363811567096907035482276124351542160253909024829509911505851725685514\ 391847837086898232759787887370471288794500115713528213445307466927777688081471068165526939\ 129498747924358458490637221284321758689712819089962881201383104081251985201703470534533550\ 782927949344570785090084284343173519770611184520720432151895552655201383062843360443332334\ 566622098289197076390914322303650061249156162072662209224707678598179767554411670471812293\ 113148104217574229172898799005643135453567843317445289299166553768509929756389465669404403\ 112830263109384833224327551023690759924843030836008348799967844627318636074400343610381806\ 577597862554273484762367996772045218543017247626064682490817280451872721250135049674996080\ 320168681356083141278245264226210123917664801600089798341302064628170490633552386673547779\ 629459935523009182796049294230583813227820931504488223487265238270059539959480194584320271\ 401199462771430931042427237249868862279511463299652377905825601176340222780250466358017499\ 741416375009007601534322467873289087513152923349548284378835281756900724593519775864992139\ 039387818930245534648672115790131320310749840113836557703902810561558294353376338259212654\ 838265769627968951684212229355604532096380116059632958960024414928444981500629201312258083\ 446620521575297892112313686034026420660241178550386738173521954010953393461990966187125587\ 718125674282926226065321012518997303111661390779405635207045155465695302589253072047875735\ 541944011691691678767595537946741242819139304959920057583483694774573805454015558487640404\ 535859219300316046467666996038468136636694003374312188054533884988463592734856844811898374\ 577428158833498998963602732425732084550424404713527826249706330307490742411732073565223963\ 686404410800377960582183762531134961001092468573068718242252318366410128318891216189677588\ 841342851356772778134355157035931623120190340100851047155652659645610493408050586282902312\ 696258659714033688324421694743826334335672681791801125207587881761361034712455675612360859\ 023482661311995290533755771074945729830072379748234276319624904115557395658571487947986977\ 465570120912985186087095833977836579051889754524761889915068546139270221796292798683221806\ 170984166803767657889062807640670057127761656799460594794514598052734454505982606942643854\ 322890865774500732180594677676286384058742147847865053389426050433475350531496638921638563\ 713375745513148683233932108132805489532224630272617987635137590340326882485148020249372161\ 773609869220103238450301511518943301559753461902227045456131560863243608441976279785070163\ 755421868422973548848724674575138934517098056869778082682725286541892742708446824315314585\ 480088344873987445700806575528775926977604430488083364942287735779460460769558661529385748\ 852682252957758937613488394167483839677176208328025254829966286941975764387906234209925303\ 105343374350280217169514000443480665166058346258755868888863500999634358442394794833611074\ 406705482267206173218460713668505317856225266437863273049930896046835345686939184157234552\ 435910696540492506154144109745916380855757038012531914898022815889387408369041630233587624\ 379744803912814830500998568922518239987612890498619335550019400644731698248247776705960218\ 254480206499759610947322741992463588851870628955608337954403439915156735017709196051710505\ 083405775288590048390605924011412637313677062121763070353505476403733725899127580428976318\ 786656692327567579486696619808413468040531237995199044308237233514292185847169193251466313\ 337701736493914236705228082340353788489955424146145726129566663741871985644542647610860883\ 067608861817091920254563020909125586664597276272937172751605144195770053768603521365748140\ 927148653396611928148485764505130002075807082154381557838434834321916239228184311647945570\ 758793176949767340612845025702364016980014903973666861008262830045540116386268474526183223\ 698156604061680619183408004467383660329762434636322229472684214058960582186255885846097656\ 436129475110718124031689568768272563514170926839865540359095663549309597630027180695029043\ 327867292166456898764494970505482964863913354311174356537382509448593779818332291776797071\ 438041061539067137953826198290623853282989238447628455690223880467926231068432852167735320\ 032794290530913801146093955270402943916580762538763738536386232107806642346013980602646153\ 868121943755882846278808170195366392926394030172305876658583452829545654239536722686882743\ 027906655883910164407061629204686010140836462596514881643657976656485499519475318056482479\ 333111055298476286194039252524687367530025124062809107214691597671475996132368459797049911\ 619796443505195878101414257288230920213536431558321242212454592260158641475934003489025459\ 208013416500329404390889980566434237892403146755726772285834759141871181259776656327461827\ 219251936375278711298144945000841474482637017386282934063906016010044211573921859186180696\ 026362353938185125483961769108820777995153693761823068436788758003851289448247957441987621\ 994272908901808330654811274315031789644250506197571028019467123513834298978864783159995239\ 012203585181607513130064205632471614325088133344429546414172122807319771545645125651700441\ 625734955286367563048662480032233975494630901524627528598931082620175660871709538595145351\ 602044294046613376721375565282255875894742202127176812567641733743144149684425366292656338\ 805639138494670086910979127749030036345492386945022269329382031819928242645093127495848915\ 313806313342990163426219474177812949233570601595520432797125007814511521978871170100401601\ 624527888498258274474618207575794799699209619868930786924849768444836611733585941692181398\ 736117247895444093699063656387398865536841367799047400349205653667371885438658635750652180\ 606052229659753988020820158000236798639256194633829741341608747358563296028712040953084057\ 850991646140871193985138011841475387481250923409067125073272439444196630021538828783650934\ 364508456955084547285221614282590049306570569622468823830359710292295169976661212747790835\ 962965504922238218040928264145392367427185004564730432158050206269536011418014261675769012\ 362720893163536214684536300857690792789969173553370849615604348638378458578174250447996657\ 095783236816185816885226969037228919430647556692377896339543943842744742255168806206977580\ 321963111352868785613439094626579768485222559183236813535617186350582745167087502506450657\ 968065060846153990637150561130933704310442577337875408529166308496422328819375711879150700\ 609536920244627499072459589380212206270929833213492757189730518173125338722536600728257454\ 325296444417938902767948778929046247677457105754464091349406964821833217783949417999005799\ 695527041099550220589432108403914300452089872583123538946789016662823809869917914999497934\ 726059458722011493978268115384425114636629420326723319499159753455481088491700262438186172\ 948999950926744822217270658314182650259070046369504108098912143094007415071968698384782468\ 954551187327385579555571089691621611063136890511886438900432161272852039986806354981437597\ 839056872011555358466701365448815878052799615386450861458580401408025763241187644128572307\ 402139985879238268455630966522794926570377029544068395645966758474690400246783773420627522\ 871481343577681691932786928359861814959262633103310854851250099456202483098885854559988016\ 960106733555315136531507495287942546177296194843112694877383953570799563510511561966787241\ 410142976171873392422123539943999965493130778563249546575888483262991585839422163964060371\ 924648244131012441584885369255627748696594733832864720939291497852874926080487804659456918\ 820139192324625507557145656485595794063197695112945347610582213307047675367040689224420963\ 816690762807724758368186690570460260852311298888381955983249872105765878693133389234275828\ 584918011668136754039162536694881956954045751679882068211342563195152210995247891826287857\ 515774032655434407603833843230124069685201193864992901269427003270234362102736993518930595\ 296381269542052099075744893551988447364442980840976016240668675951450824764059943017196309\ 459589898419366567674533696135372114756829602395005618989032948188641336690496745570287001\ 523215408114181382703703674380690928901408638201146747546569473701242381792456008281554261\ 059122937886184898845916831230376412195739588940703689292965261230670485215752659306911401\ 093995778548083604949657423781111045206689448180846905558558885753992097496775384366584520\ 148655473608597563806927097182649281335155115044512462366998916437344318154786717581313019\ 940716557727730643488760996416977830324224685514629505851846268565448039473896223156700739\ 818409498934838585099396743715708688457116960668213601943542922764012159270732526066671992\ 790481983171041316369126661639760010387421799472672133412870328435034527301342513031000700\ 669778788117127155667403739087796036331503998966439065297782968391930567174267233644561494\ 241487632660746917795753974663065042609663510872094579125173247299002486390480721076569862\ 021738370634423911774028995133267430135812892130023301257538734682038649182610897669733305\ 696371280187998173361965321966622582012086365510912334309993587798182223425414124264132798\ 281920390738319551834643243709758963785752694519475617058300179335869820293679723411463621\ 290683905806383488209312508454999962303238096625764366586477601703158349308456777071460280\ 432165582549780495340516374298450274762789306486133328908649652884610064537489515469469534\ 151497361551839630820967702576900317225353525942633768160163217121154986399025076208299073\ 146309518394644150607651941220360153371512489366286346991904561523048266364756002957038375\ 400277081281681861492618940789486667867448962678055304116292811482003835651309501648598512\ 959302901116479609192313013314730847757198442600213404511053673295975544848098574970138278\ 741678902759722497991988798374741515743167313043040331254782713440234320686374989973344502\ 508160690076121392910056173842375577952066303991189830098861877824894193454908433804760993\ 989164913917422285084525532397453089629864712409678998533857217962133832665532356904231800\ 915778320854520587740129622626234688922644659073594729480613003966219997369369854792679029\ 648100815254527306928697310532380588836862959090884593665948604062154919652544667460037757\ 597112533399331739713424104927119290700773958733507888183789672620264006040497538349397747\ 983453147007151268113699265712882923820044493775034201673758417963067692814185852202616483\ 246895628029989645552174956382218841001776405557840555095433878691531818844383372285895221\ 724211337991272070451076086869148835024462764023255284306916389828633808711378476906425864\ 710286127402472692638136155425261658282967567298144517269927021279914116707658997940292328\ 337344567806596842360697666717854446096091013316204239231782865826404857784660912774222704\ 584180963835022047147774560904968842027052997700586777908478719198168717704732001705809430\ 857351246493591185059708772629426763995363424999962223497654075351457945482668182885740010\ 749126168681605445045744468919267694217406453351276183345489563950565832852326661047793946\ 520569039604217006795359121765791689267345186014325461577285696400244416523690534687767535\ 832804295521681575043131146263602084659623413174726494684877878416984826214850162057908595\ 779103584992792905280336701027654162769994646412858728850362882844893722792278247400643143\ 434282352173798430728665020679325331012107022013892966354596826464954506292813894707278340\ 379296332490053016780455136018144212045651699247057564459945707347193783043252214749146831\ 540380953424162955660067124547419042296887835923999880788478906424441130936046964773356807\ 311033534770650202225301991202422613122257193553646750828206759581919324133787243712297217\ 017849025056841862366828272874709297038546791406630284023700632471280725248515125800700713\ 412228213153756073518957146037923036779602546187684085545570558749703874971358387897439253\ 112160023081043596306612533898808003058256228370692571159423303730855370142393232381083588\ 147601725303520058454537537754967603838005620243291237379676121859351198326747903353687324\ 605246633701559397771354709459051863223388311875968945384885268934894203646638634613499699\ 616416658805984769747442829361987741596666771794100482564250971161920031556829521124996080\ 650699981094438002745421878062527093084118871519817167260695201341410010074047292855031559\ 357659778398718890314831454621773782013996136959565221827898519457159837217484130471855710\ 052416168144225336212421629287788490393830961395497851254065566148124521061961155735758611\ 274350399510230463127899385928178618048465255589747361787384358858153975627799106908363324\ 242347046587763087106842740602784495180868280435501755471408201812983563918610737952125256\ 379756735814131276697482840391309146365659239624787973059891605570855513322066118991776901\ 611272249085921662320590725596536460896126315570229494385084134268982141534089055023884483\ 558555456574926893459240125263791540147998140789902309356386250141650467779607680426764328\ 704077846707166183537408903903758803918090029998227679075485874036441269193172070356253589\ 363224374731506862934568000562118515710253114456287074403886384039578732206963806635746596\ 059326707073560793467189356325361502328801383402997338040370688066679914504126257727315631\ 171455813307298781270443303184891904848821845452258563895726728387850031476895897679662100\ 905696392399440070988821133253450246184711096100359920488691122958338003444505113162817859\ 665594389869462396721573920391780706602659643971157282149684147541072257766759979568747984\ 909301463406775616904273678922708408619966931617911802966327798621251107857910142076844401\ 312806896430124576660696907509305478912697071996967428125912752729358028868104493613443372\ 878294966663300804331788727638745765788463364235720751267075178702106847718197120857272548\ 255246715552768892002450828542105956466692886337660315979392882814749634493915193739507153\ 311157675725731289325169022656231469155227822846758395406846975004888449526441104234022277\ 589475662899443953195651564958785703115649227361885752420338500840189657547075145024248721\ 091549347434943580530777764576957335917101519137549250710068820712691375428602890075534613\ 865360589441308100616656193440365982636874615327940877685402917416614944504190179124711919\ 542358174904303657867705163885264895003942664980830765506701938661077660673971374049881292\ 253428955689134045210567286987961631144652780963889887962209933022854068404306974967569866\ 323000445388765529483424210457781104964243329150090423847934114762256600063804660154967096\ 467828997676044886538065609561339788879630536391380544827171294250508560228413511464214042\ 030363105660820082261557696359276939438234363968155418154099271212124289328453905802823248\ 994106332628307703834797326209168484347886611543903883835208742254645346321694086506319383\ 059097020079340561957941530689602465703654619599513243593211295453933739142086513710683504\ 973573822782701844415216242194082667777347115300479917927202671536225656835204331834189695\ 318038065881590888177967953805254390621535322140616319033174729162490420092776800551770977\ 828014534078358897124639635798181176303067345404504801759445730686218618505404893717136723\ 779349000774398839649009793886037355249836625657663974766542445528533512230450758116449308\ 550288144569956886588228247895030617666306410364891028771284647097414497803740386869445653\ 720243018217449917819856129459504747019774954369942324981684687922532023245191990349128597\ 567797048876808918959003177413776568755658974409132052775994562016452374352522628521631846\ 947978423713269577550292789173277415842327790982936234228452391824076293974738769636561792\ 893192587169846051410301673547885473251631390343694951863773909282509717576410977563431278\ 406691735675267702221594104275815506868132734791617385337269976117203969864384340732306536\ 231375832331681784873525619903294159899382942310418714395561711689371942343204408435587180\ 553742536585413797331972764125029816580316202122718104272847261900465256637667302432512194\ 734523447365160888804024997137061421779196596787437091064922231725528798078850077477772876\ 293946754021331599151769726008269415684146624691481632893468428464230775832011738119056552\ 236684285072891707049098115609251809032438915160951433030013779459188984427310537016775158\ 365723578098610968389076593143379567553845061707016399741360833806664076231861816537433616\ 243986021567993471976186671037521351060855464568839349636364597566972713097701603485891702\ 586541998923843576774977437080683540845903081466672590724237916226404628867294821857919330\ 643216662219943799317883948695317703425905509769087106715905117164124939338762274904865962\ 674699587061626504825532304995584076918390345564383172800664999046664844648580597707200890\ 844857746389041544787184682341452332261735718229715111546718468281424300643040344515697758\ 204633550824884202751542248399760218151151357777668962872911274445723957112297991925016729\ 462225342722839265131175836024850673838936088265065990563776385094370742841972705660830890\ 297297422741449084876559831453472326728859372388373476785705146241242324512548704968738049\ 971544443842646667469291546535769261661132235177966214328536260399310486304341351141547651\ 416934446594729567867730040915393864017319782896452172235705714398288448248694443895212974\ 968559893517200575952335150732951248374046476579662699458809949631779017914913076252136652\ 846116692049335718529473107939611688457037654164756679002714729447200063251465963864837783\ 906927980079127224592386948591606857439987180337249684204348072130366664732360225894661443\ 143569260351297035748304896026792389618888728935732045307973111822179611183356139713558303\ 688024339399926063791661795300337498207271112338301283467295256152325586353774597483964482\ 016877487340279725861327640017279710368662694830085779354030962574224878865792037216430225\ 516272306465835145852946332700197684180947886367593026251810710813620380105448206158357195\ 369973751273143025230159870465352010633892622576141087753794180152675842957104967120118331\ 655075283813354466724700960293375661778760901262624371723024548541923723480724442791489542\ 163690863364013516263045102906066911657903817462636657473163033542688825919804853862693174\ 663238938554389279145786461542708854417977035723413687599937950228164695894948103830624799\ 786667253338722546375128758422674669302594957536871228274848886131931388873514407356766317\ 401867220515057888585549245048924183366091609640010744531160104990504491287041806844412544\ 507984435346865333728063460881607813551135087227425026604306852524642221752708157446459776\ 319295641860073957750899006713218414355688215060947419138749621257488851365443516370188110\ 654289386120880511272768413544256024540857253318833192941165520733738257664095433147569079\ 423997951155732765798104943452414275689163596796432828798584975740977129587568904438062612\ 581357888264793899608057432463863252224480772426602062602728021961552194676876007565047420\ 526115300874934428569625318965934776193364904572395702608859053110109486879495220264005880\ 321813605318580694688417422155105093493407669351956990401878453936283731955716746863590450\ 238311240577523860180868754806174708785749045756851587300735153625797107761835472085805828\ 389223948063739633743231617347361628785509495399349078889527370165667741943104623188678326\ 622934311407138655551770090263698195035069041931884593492857461773034693050603396084184179\ 962628448806727596828066440036188310513987588358660280923924552183316421172429704506987201\ 987083699211694131005915221912579531903921082627736027405690555472049625088940955468397843\ 210746327570899302958745653816624642566098229395573772570025323837622263802584739195766494\ 695503422170282054199031612573256788826373340371859704023257168813194282019547875808972645\ 509424839670486790198245314029957261426604849395447155319681360262886744793536407213984902\ 903380252320617223181202359431496751668386095030798373820269443628613458520776366872509910\ 183454084563551657720845802943695534683957392697785350474034595797326411454714706388211448\ 385404834852561948235574150704110570893767795388079501517823781886415061782004393291565530\ 269795226675173501599652869172546872105343195339662543737901254215443295566663265947224357\ 871824528601265091226382382050554110936555447759110652847062964958539125914650365257530532\ 138777168374246530408911927011587591439346234181803457181521400026235370311649283528956614\ 298274264893212070075556718102195760052672784254645187540833059577546935083090696208781427\ 846652631554670429469825922568533777514950420793343184508395904023923424087421694819592780\ 612268053830738210650610435929234766944516955014489026603365564914807337448554319643251022\ 479484905359236345673654367071469143838899595959426449918630460030431322823864453135549797\ 416355050063003781289654297527484982539900453927694209501690309285483277796626526594454712\ 036258823822784399226840995149184544793606599122509625386371857898644915841980814603497837\ 729615764618847531914260601780770189189484353677211642923805941490251996899716338994400175\ 233602019094613309202668997744091469653207741233629373581062255743936719763367545020534950\ 765621552834511813371082980498151391144237239755200151191456769235348317826038336167385797\ 031672452637927476355335086862119697285598774684705228347490815352052565757296306576250357\ 936395701028870980256250782647258536004237337661408485515940996526687343262228076059117550\ 408860745561914215025549603121045558768165064076200075795961374799119931100655318800557346\ 413471593725169941418674594088778177459810549712043613410506674207275376793425380623117927\ 984589617666769956505271130258959576508500305644279853498406100394259884038786874590726963\ 006642170344873725831155096312021422093311879167136871732239748432267620591525817114049261\ 488390158184917582857589589699685612163700638029571794432751879124074551065877924957621440\ 531674456196877752144197920460499901786657974628744548830217402981605659514870686208991905\ 512131767873440632087463348232584368384008030638083621549010773287853725924655090968294261\ 670023351323829466745282937579381889320376544861618873489707472923342216150982369553361443\ 930956082218278328523832530130203337042828858333223723523669018869522753172988055817742214\ 284162430702233819888170595536118573235793159780671094775199002519106299695446357234079559\ 601502416214873037162772246134983831080942247375496888476654896040005083143988907482833714\ 717603501855528829353633367327505464057860752048298337968613707670729763212486992825733026\ 666051005836892182772206217684472077757067539839010057369801777261658247365292540839569746\ 506307783768996730185633681227557696018465513246586637715419744563290930473741975842617090\ 286099674931686370464276133986368285973696655890773005007335413732471703986115080534910536\ 699070902581443916885422071946429485151939120886821621853777443970992724803208936831454587\ 565381810595864112582262491404805012210279864665329115520589756264585130579876159858113978\ 112329926401344644196895629236586425685920614980786127697688680357288256878189282684237913\ 541101352080410754526920955529550771715297388823965970208974375389201979627076207630931129\ 543140179806865120059764894575864422017220986643749093748810867818056970889367355435601742\ 866653208039916117656007531059277830321501335401045020007094747705913481815305714364064963\ 057682708145345312574712212863986599753141842940895516891639588623459446691887981199865201\ 593093566513520104731766097528047765652412326859495391365808094287320308283428602258802351\ 633705741977956694436281069981854962963856772601895325313754094825388940884639180683333884\ 441109157237336243737565254329827974375159474842112806699787650992546796618541308129165413\ 271375953278258675676674244473849092423095308913267354949124510371813485861790877206200413\ 226824648409900781362062472005124548181695703697310643914309260125710593789788923715126177\ 289132695023385841351970989267628857306394801350985999898399426906247557055856089779658273\ 707173624979258954454324368272854446962586719533610547279056834453974191304935897796618293\ 321278782044656146567639487546452415108507143878165871000810068514134580115426453379714235\ 316898815550642151572301929739624377930987662427099426626105530638644339846892096128228613\ 098737724120090983913077768759758862685010016040208196779615503192572960704793664924140139\ 257654461839378672053700218375622447291556425648981008647774051591247106929964842818518416\ 162612190797151585971072730314235901242324560755346917598764064617498867689314407260928051\ 326812544458068186846812086210388801798881390741648051931189746392667340634460964049653701\ 208399831697900452845045889794997472536439547462088263971329455274460800593042705713848482\ 363547406569078821584947508116040087989031826773128785894073243652068403140931066507504105\ 588376287433279621430821416996497697449900609334943771781045862160195927177726337990255228\ 324327891674402575970146028851323679094116356993768401870503739324282891662310716304823097\ 429815356023255837556163415762244634375018248560156622966369898374702776229558378011965086\ 032359750932562339247113011679914737657416772986855865429428862497835462114403458638676101\ 109828104346278202252478553979573106377491580033399368757422870144022182833833253059879114\ 538034190848133878361077082782290997510048349245864480736003473411658955462946538556418331\ 935454799554563230493513447149553799255083761596463667781843290161230344348857568597123721\ 336404399838574678633560129451511597585250486252455634464101442202911730348204516730911548\ 753734545902103343647891032742898429808308582457686076378477641101393087618362442844432576\ 339581414568508702317578866147888026371989829532570662473561515448334267520416091775868068\ 962183238628280476834804440198141985372010791772237709498858585212776990373505203732467022\ 404812404374834605667659059721812238920131321401785510144575808351885023451381412707254137\ 053358856301900983404716982298796610388715352712244981177037665662024625177461040505220508\ 716966020500899269994366935909967502905630683624316591812817780541588953775094701329322633\ 987059893952591036033979376806510331242093367210741658515826975516889888412432479920921988\ 182405104145050242042789002531833988891920489788913031447982335804725969828327923154815275\ 326111635998595288797918114593032709856674337964120593520386415579805549080570828091329737\ 294338185030543331823257101883411241980445147824587195070601385352110539863460031887346357\ 960180544976420130111372627241359061153560267022825065200833693382574461047691066653528169\ 561815030006571884742503352995836034227257624333861911896686610114111459621718388411208761\ 457799549706583735550074054299148730796488909055588688134486192306307085818887014707844347\ 631754558600944402631681687808894815744648082685589980388529333503195745580377759003477260\ 993593768595773274465243441801482958098763626289096787450016718825295442571640696099247294\ 331842893915270547216131364030214758507006606712305291201294306750318563750036004197126559\ 256729063281300294834804851834465825554252852246843632389886995446135838317908927000002835\ 716072696646906085060336625414943710459788669233218743215767943644805648192355433840545886\ 905054693081464376693770151205718531419900676997921907305987275597783467222378924821551231\ 394178398026410349186890611395811590003884770946548924474155815915298848193018151197975499\ 065092461374162199809718208116325812372495209471039555481751892262682517282290489715350185\ 716281910444089887976008572314092262644459173613090025518152142714079112173844988187766243\ 307947310992353241032535742121801616818851954183256552502862570466105253871211133240789079\ 258924830655251247952073491087624063209035708000942732522888056901671307889055727466332058\ 167926239022475102195214397611488963702579989782853420731007770092115726106978194154807661\ 786690692075738107811261877889018492875443036992624187517009626058806647635225926537433544\ 467110523580716007287214451245117497127192040369898540635587590427652826451452399641212615\ 917798755309521087434819097303021023416913383133495299225605780848139458195669811398676084\ 587234791373272619635792031919282252987959628572816162030623110116868280873746569721781586\ 304685033730098438052496218555851414503348089966472386585037178262930935232745801431646888\ 431530271732006721736261189664523678552638520333755204716789819934611547854532953439689911\ 928755449805360703021701405640053927037598234112674343581684433911455975675887839148370542\ 378086720365130535520991945983668989242247526772285617421456721408560524968547738574650752\ 004832100867983043810481257933299647776030783731994758992957944308993855513346573307205390\ 801281157759301270346001252577209241180698664218169769692489497920004473548004111594299828\ 313161967823364081027798662867966433529066420837792045758007909127555245736308097315790188\ 491474233731502342287491978453557123202284498679858808168140608221989471177438010087130928\ 084495878803571671822369870491915504416525326855707918672673953033836714840840542694649466\ 158836604321963494156181864351095700387049092563775647122309709271224953126649905740499486\ 165950471767644534900855535445229709222510445033995694364814968984284034085828773163564231\ 063657726664341734695953088282782573905351054776128376704778563505288103430868031145165326\ 193030629295367569790589623266008983034499184388186507950085845737751561534855880368429962\ 630036836405998470478105292223054460471940608828533978319079687889638151813534728864600393\ 545478284214071105124106084138982704557114346795416104583257059431274282250403940065901629\ 540785136664175246846540170258066122548879362769943820330938434076519694514123272875645824\ 635828276680947774601411170782839338375294190600344879749343139970466599673918004573872479\ 925831647389194767902341479764021290718962507285042597964888348923917848404825240937979667\ 980836050073831738368260726430759340626212713455490120419656036273845405545129204430220022\ 990678693176415485417690436645155613478260667768864621580604267083865243957851643141266677\ 741359883208268535086322376092909491066499317408818636531018488604214854767121100642938547\ 324484406512621870749517705818560331905346559923513572349005354779014435312459874657099064\ 340751199568748126335707601331168774490749288063077890276026203556716029610309606088263940\ 909485789874705787690366826617792804542930019939057123091097865498259573359069084907843441\ 877175873435360885074566607415026696892705565056495876940808934518471510793917039199491138\ 947743668940843572231101858976247075770934571058200548874359869758344481963405859074665640\ 428003573923058925944689785861328470701298666106556158692837831142278212410566128095359043\ 659826109809620942729243870546308760861144912010946330503520727309439495463461616444102871\ 557375264536432945328576813905437728492208769079170524090515285716219878045038666475394453\ 341637287364898495947313856797961564446729702773068906330555215171871130166445888195182606\ 017430302703685149106627729946142854810860737992447645649253083096547614978966472549202504\ 592956824436820638541447727835290495387604465580956702187954337175157448001418048656678201\ 591852892400128833445436490536050189280782574599625378576109974007697944127619085873291301\ 889033338966247961142875681603343316903848933557584865212235272024810632108350879269418296\ 436018730829815030628007763677830761235880752112161383125091563805475291591434375260912680\ 690367661798715514732686383228310945101830909430873473662232805513934706672007643740145914\ 868595593141385236442100164370434082554300006755432174155522259280318632316861689724409419\ 167621946548621432401930680963162873909467878518066617016058818469402032591196762211921499\ 306463938676198653919983666043978736316584069394729193347275667505425615358592538080889621\ 366882570182068380095171096794990659040402043140913119289709207068284231145914452147585194\ 007521801130391072125893718970690278834188480453689942588383296615422147540517641197415323\ 085208097487751724816022051003821383386021783745670551311279064002007387088514793945887025\ 396749578994621314013405302608897484232246641773142426848776822644449338962813446062632072\ 735024053757206484749609056203819614767190105843753298783853878762795947830839686932657178\ 506521566231578663752567259673444300354779093217363002779801554228509911521850943476332449\ 268069669516864200534676962440933180748413823322207330475494362268140163938410200092920283\ 071685278445079416361979891042095361187880017970206382904109142936550608443766765370695959\ 068893703964695020125366599114057622401456645903390016626619328652945514269975437046759433\ 379696488531771670479230698192576115560841746570936315812675128010679410281542567792028170\ 168050296912452789782035430512499303004145468104368742274240112729972069008518574308050085\ 153225961826715080816379792107608757601064801457130359277487165388170582954444172161304955\ 478705536963855356189145837642976169247591215216901873570916260858772908378361763308562945\ 332650838963693786042517139511036062147739023906395183252153667412047712003573929364738648\ 779744545829079353290750567369602218478252215847797408011361565195584214338987776445758154\ 591488289780050843445228233805815101299450560274750122841743039406842727247966444186707195\ 941783961357815709925952733612122438291438967228467764016961228112269633261407568310666432\ 766922850475229250356690648859748807738983084774391621127383350784220037273782671799240067\ 737611611478581993828424354359778112836832031256400670067020430223614081165688397029851328\ 942125045018299094556399008489721913378634176486669821830010301772805683946232519197143678\ 489678687135469543954819879280492518573588967486784066297586204818618618509913618145263091\ 665584828960294737647800144499305050473764280666130723812007942016466152749355348000455804\ 269061498831381669206820924735515168998217282608862084658425368998475533570904732074838814\ 780731306094347613300660939849150615244811319997929470326137478694000509292875419022468593\ 406878221260600180795180579171027468088150087915655293288046287815116160123972507016998210\ 017815854964425520068505535320899452365581195149191487754575203987502103198085589195980708\ 037702568529873017753192481304684773485403815771798653697784980909359139886303708209263165\ 998754246595232254282729522396389653429627301118728595590925990381338663916600016296884828\ 754611210925297781599543692542646097177788538974174285598804163709557653888251406513635373\ 009169798521624208179815073199707945525946554683710741896587068870513981287478131751903960\ 298900245465780950481552517811100047546329972937563017003297401502897047826767895862915363\ 832771033034932465207012335934079259093526532952728651297608129757173867178874645368984452\ 607486835037304376056912225396132336439075317156766578493421021924361881659287056346445222\ 852057092764349471926534924573143980014389555974410964485292684232346690969221513705163015\ 339871227906433118579963757665385790551761632520479993952776803099430120194356422468196746\ 385825769444995773531037514812852790371778385671362139422400047022583721109482759499335881\ 362138949504409270741992839434219238664672747975338936991888834426399182442390327963312718\ 424619197493749465190837126865997530014015197015900239342583868542322437254759735340294752\ 725834061001497831194024784621999518685852543701893528603394590601475481597909629872496523\ 616549385596187131512682295310096699229116591360367775318076386600159986799868575036356534\ 142696267135760014113814128012940306480433328223573345919675864144057624246632971124533085\ 270582255368449571744186478000757030410830644973628019986893897581999020443001201406664324\ 779568481871171998025174150570111393955372543179179598617700301401194367469282788154611821\ 863281044729280366170180583257655839955935786205023253818964762240549470600585501507408062\ 415788071801684715579696507674806423473386069053542302843593397529426378789526810508202007\ 047091990345184827863396004448901307175685948910362334860387350074665125046297414092435668\ 895810977138425044289392786360531805360639807118222177037766732121220447443201998875297677\ 196699576398277191069866544326276565683637121982816966597466957372659583985691391167476887\ 284717237176415444063373082312310954153455308760650302920450606071763207728040323320817609\ 028024117378826538453650459110962175821612954091206159745935826005651407473900199415067821\ 280766551374247443451370137769870642255072569805633961336339120055919519967760728122519148\ 958088542536734467558977624202202568803067983034475370101047417803015390387804106229275233\ 707823984661637263263762324321240512411253697432320039373185931268728204209843262792852693\ 500877603092605458290589932538752612709809288173569196768538127311421742836481671159259255\ 124607785487739889436775787989727651840617317952612782916530356713404806634302423431056492\ 766139762324630184011978804664952608743514310528251011936652112444381809986147513278670751\ 056129409595491963199434026843230703535074804145664902572907635518468766694990898730925971\ 290305609441554661943327398451689727709418681502146607239231458775984338564039991397783099\ 171672312922711984403823855863903219469304842730767309348152344925271454797960992437269350\ 367332623254362919789008280393737507749516238976092126895102083893632736582531981149622882\ 241041126030470458929056413936552728587948574502225346792173932786976138068161103386471175\ 526598488097433073833221691489899385011947570698933456722019241481877060528558973405478235\ 776484136635374221611726089729766634937245970166065208831538244539306626971881116174788610\ 543527596877831540869107064081438778197988938770632441217502528158682424690862894901336804\ 546296051240349367126753829832694428927197008309172138977131146182152897553864202148177656\ 023280809026352500361373917217811229210578097667879223343840904831083386051157295586356266\ 760688785544463343069638825411269590140359451735362854906127509521973397063312141873797314\ 335334708770768158113611846141759720097748266062295057329018205132018231364708559738934572\ 812392786132767638004440506400279957454700944784904527599407008395041185110143618674815403\ 587592830093859205310957510835013418258812812896197608871700975462913990928546280033562025\ 876167842644135542589496411196950824437033867220082813251349349590127635712509192172685405\ 899024478720617392755302407068770484107343519789005569731380939542164429147992769948652534\ 822174163212622610631181885930358957720037290747429710708852112157192620454118924982084286\ 948090913619217700624093052772573826340010033551806226933151444540495750624536615068514014\ 560514307453668674052095135721615808357188860290872852538721768937044304577893035001841319\ 934152879742718435234286402277627722900179121061868901510608491858784747600724977823813757\ 637046602897572979185749413238571205427816350819033595965925157951578747255672296838451110\ 393113521251295121019554558480519503555164488047153542759637865619280669165508015563023760\ 789014132149241856428712864545370176708189606950967440115910510517051993272578616273262874\ 985624154623030113835330625434427340348183671926262409675157470210851717248482156459311588\ 742128353368199674060045055660561825791459631642825426029565741415067523556271617640853545\ 302354202494047329449144443447427406052600421581380921135906709334730302967074532822162665\ 572081420517775753387265202339735811725286235985093680753119015072019323615911178012611573\ 380366967209004137111212947956496681724924135944851169981399525120691691452773409129510598\ 782819411375179189868502259700195019893750373308212434858079033445643660607843831426690434\ 868973894108147407820091665594515511868102970218056938946531181089798464379320702368676595\ 891018946633583807095926638503303245228465699641420668602491398725805400019782554347603566\ 946542263680863485011443452802091722174199481098709980552092550781429484487788799010348747\ 274638942052594112798114003095650397292565316834364199188537579638966215853674154969713253\ 967483753637686518047921358077234504823818220479923430381970834889326786364581354422587137\ 539538716523929617661587915491371020154089262907900729992762664604558765718533453985990056\ 572907450257318017571352754551833345224031433074840577838196336280016254266960895566922163\ 502762248967909564153440257965161228416739460998710405019331867971495727841759834273347133\ 677797331638461297693218094016913934436190186755012593716376958315660612730165939638566601\ 153460486704024347835074808601883679628410461627113744828185767894294507774981358998676995\ 799101293621575210704449517813759419955124261812447202929403883269918827177153271358892570\ 408453014122421772098058481945138429625097843959219456481828809472139785802465641020221591\ 476517700259867528032261855972287026638567352903733708947631290925972292138633845464000151\ 248226219390003402699181723191771748641150596973616578596214623528700832046176249530196356\ 593669419619347704671306721871987131015636610013104812506168095781706649039072543612248822\ 460956148448778720012242592891693859569061126763287313103889342971642374525217215726786605\ 668603824717552044232758071677986430634347780817537527017222304852507552660183231677329336\ 702174006366112504123602885116597474303295655914006281907198553412109052599531852439299624\ 330289586875019683417577558168935722338025157222869108336492533548080625262327938383155962\ 919458859634308679595815235165797525779953190307068776572195044944268417578241428760904674\ 802959233294415983361524887934958230899744651738036457419907942648615727223041907527299887\ 934211132706635671485661522733837752170592802341069776804170971829805839817383972253854330\ 800389100023968737574548471569716331117585666239476962658851560625187478622800151840247553\ 592360947458354371685020698942447336616278238710022788469330436375847994460567471399409440\ 546974115206381603864407982181467320231849245249227861304163915601985844778106498288613470\ 942180962992255826864796594327707373615889697723132482443605126747793605507221078929355031\ 276695618827871222027065754393582105287828321509719096227697606943930621854449409898151024\ 870761600931974753520777027171735667258285124267991004552577657454611489959295167192148312\ 725536665562927160062937188886615280609698706045106460457124135876618056288645690532485780\ 607704003303137667730179471368157877563913902138824772017233187776136196562254103712180493\ 364469205419288963680169237579509339682192937256531953272982081371282856310126475304463433\ 399253321792310742169334901312556057870962801361056666082053853399434540865735379435796001\ 818191709878625044540270857972667247686960433776244304308078030870582732059727243540499889\ 691005207256295040678412147737238816684678887348944511386525919860359617632750900525290072\ 875217521180245635910668415709984177840381913605389319683207071623062412575993983130289922\ 576054379816378775482669155322523051302721698715512524212398406243721216780264792733898399\ 787345368625471550065629905182747996626601567920571904761905091923709264472333242698738639\ 282526663396855448468540846545904897924598878075380051053754638030637058013171191659381306\ 191289510893667163260039461265707648511015932920128993279722840708042077613022042884575148\ 255530882300832197288810800976885324483248437440011516001730590496795211649773184045207807\ 990708873384248328934309655116043474397822909183434127486197514809062403187556625468342476\ 402407525071179978978360737094749105926673035867565595325856308029673736449787694552163235\ 915400705923285098810671941571419837195370843952023186476681821613888898186946022114330806\ 938626676390608143912678186346361570383729840430014338693285030038750833384531120635919428\ 165245051265206206876021238402530018522110917313359013205235823844387539744648513837382444\ 389316328788065812317326433873048619344779088430266456565556215839667975523786707975044615\ 537219979634886773882992152230105126761023265878699559929374100638919739565647978516318835\ 687586044821205009134490968549752232972454095856700683248818097510870282481747791625736136\ 072402698803570334989408768199507497597374216501585823420314933553547245648053040952140198\ 012508027843727374774215266984965682397355181162056663702958949786834761811360699539872907\ 331091096030507771901645933677886815768123569280107907887161526245609739979241098722246084\ 847185548005690738089187465650481608210018659127707603802276278195923878809428098017902567\ 979256744724302494019194246494125075535787738088540429752956939565753030698190737748203363\ 650783121333601660077772316570430399956953967381635676933262905051162674970164777970322263\ 525260017680570213483916149745604472878727893904578713476709102248941762694321148597282710\ 988772224517347330979398715275347020169213557305677034131039490380330263545980493560205778\ 279977896376659499248713501670862636757290440881872617857949614205740349887794904949543422\ 458188384934616817633398790348241520206668438771995891825935336742718111093649514305732772\ 836876643710883471088676431597819555314338447003956187617149646276483013076880879209627646\ 015692476735098683529240827525607214619864825288055654530034882725347123721625192225899009\ 265707265890139680070785557444953292123836425885998033512510415879057663289907499693876612\ 260577764097116403499218860812445792504860297464790960506572702846048414569099542502425972\ 842140823474690426570793723032665400434153465688842855587752623217892920368881757644690682\ 489037601028209510864234960278349727581926308344427536264962667101925201617177279347619787\ 336336825470304294710238115758271668832049611388613784347376245135571990146623835104015625\ 834092793882196760491906885231706766301389127232569076916091279569505373344456360137192126\ 710122758478306935263858123393224722048316872175010296185907444771041164093064361860365328\ 564284551281651082728737926825385320208771474922046959575274424117640988893769077776748478\ 308028187453739633053864077088029550016767884078801867952916688668856367481623232706605569\ 112617857803748689321796157216663313855143376205170276237021065560904779920570334835624165\ 284511349981279374326779564600354361596523072438832455446704528879224970818757103808093648\ 986524706073751165854726307845694270835682654945739565397118862194734608110444349987460532\ 644321118641415621872359616089875697652229001380020125847021029812274849650674845280316451\ 880462817610222279177543685869793521848572356496517176665562605706926061758925669842258515\ 743094847021450759947347701333402669639937164220296696184847995022825412979200119910397551\ 479366569334274670882328889863264554347903255722479771028057992779989756722369566051197123\ 685510564538515813115741025733669984309416022583062821976224637948613455040834769247282528\ 425623263688143427024184054117970257155577769139555464675175249569373898856178021942020992\ 506395410738382683836972787336231972286949933622248956116528410118739138686637293111586672\ 705516047844886018782224292339768384771626701732524984622710459992570300864445099892174118\ 423395046835360457597396576100370501769277181152854039547624089687609636268417387795002327\ 437527434309352282886069661588350321241650807500614700229539848178399251448180970949359992\ 587744065887273906820327365703163762695913654608268900422537277666035470496282994032133733\ 668724154846657676157601729491753945120919460201973870474269152979868283744467074308600332\ 561689963614550212719973981812577576319582715132647576948012811491220989478249015448505207\ 910327340262774778943768985974773333894552562005597413757555065165686552732304985031608661\ 661606628621948056467880981607314938906625290443715833001595607828464341539360847042390201\ 120077459113913955641760634141458006203571708072387094163455852942022790477501379736236654\ 958512710348096936061209151200850089927346560586252734765100457102887503736791224458015408\ 373495320050119066249700974413987449829291392568239585528561802710515440773419429638449621\ 939796061251827654649265996460258893982054154188864949524579137294246862944099703080232709\ 693415673940624805583938989177675472432770605971250113111669876450774695398257801548536628\ 932749695429092993318684341911440396012415619401451355888916988416484082901724794278225141\ 395979791510641405142073119347346536994793511927710044768916321724780497125188379776608197\ 715936748087500859108032536785372407363580234362075405148436512708641843570466390603110139\ 343266949695804473056297292151901705579317341343591020458603837042475621453888787975265335\ 051633148881573635407930863965906284234411137834112681309887136586999879918179675116486993\ 877647272904374934755634979422392670133496689342231037879608360110756388004738425326545063\ 252869317218358270777615682465717442943410217774812016926185652663723041774580181971780700\ 038373522008267710930672361594955322132743852564395223743217671094864411584101877284475615\ 917443022323892194833324576912928405943278056845443097829633357842911031974932575169542868\ 401041257439883823146093059991300589995814755709030464051782992937638379561404181632699488\ 039589384866897530846864436964404058801710140491406471815917814715550267908001056916511510\ 584749404032142052387710486147909965043111180907143099720409680020979408616308066859903656\ 201091674720690095565773479558194099827819799845041885883488711900053122956369030904413954\ 630079714596109012446769075439874496271885859970034920427414390009750395878800588422358633\ 469370349309505469675004017881025031481282656197047925474496993670790177006374493973269993\ 113484438003515249717357425708817910436214623169035072168905804738854295508809414259200077\ 927966098184370380873294955081298359639656503219402906988285302253014030142144558616857976\ 338975370693276796655276410529848062720942628017821138119652460068258880033245690514732511\ 615488596136335510222527118436475086752061717592162365406333100110888338461912946824899922\ 050992029139426027930852743467203797104925753378454572339747642402179312184962073085406492\ 798608746632894993857197184372514618075049230799855814257352795543975351434179637787267208\ 454047637830144282959621319250521733875502855144385024240006864513491561098405501580985045\ 891232472631902745751372951004456111883078442449202031906217287583410421115675602772968496\ 675113942603253130168601025805258365186770511307816252902612258749380869366845910765664416\ 271156659526390168508529240740834288484486960690939680207492802435110801098128896548682817\ 461648308534996971920495830053143108187356510276602903930215785733440813633962321056094766\ 975053520498409820668727070505147425359506631740058308470448588333548378648900511657699595\ 311911502000406475380234742960875772084798989936651761175441019313758408937290104800823834\ 175983123129597255656470402962000880241860521333557562633469009856252532749975006876074067\ 384929645974512636030352534376059530350039871467767666404587467900325080321051510028691923\ 221683162768298149013165286104654372770886785938729155230110406307635127341589173802739103\ 947538918313439304209410589875553506892176152822474874005061122360072240108048641364874673\ 655595145829185102682923251967085392458130977388694402894657761397388956846398813761018172\ 180714891992188211122735791013934370615012216696471108600506150493590716094372161559948168\ 535382577491021628689401862292741550928952289951073255206908985986939737095057346325254178\ 965184612627562339959129181332243938359659578942518056129897240426595050419448815418332332\ 480632485406637539269121299052683910730297923849834179303381703532978313174281584630288361\ 711222565011634587924563091645814196314515962740019966288877147436301581283389783127447394\ 154801605472291396568593303474074506388233928712121472058248635838448535087127898027353701\ 417937922092329753109760384920322664359918295157511736267912459199956493234106994497353763\ 671799168715488939281588371885994099909181792017117164847437536111246316295056569117092492\ 260025831664199826180001413621430722276372056490721097889773437552126467176785655253000800\ 537219797897968218835110494143246245081504722384815897001820930320491506617563200938082866\ 167245161359360068547635533917128077771289167568590745791587965029048440994062521495612462\ 096116151116268829934322077495318952546735886113830122410716964210984996937312672699755014\ 074497951470500877589401422810124985577220444951685332204788831280482420777934380893998097\ 521560400886792253634822640823527114859632141090564824456294520839828966342692984223444678\ 858711546175596196680370568728443321698865555295196996751205147626130230827507121273617256\ 308147095112414646685535181467744244043252735359629877190370416548165892267217467713163206\ 526244479332436777569201537264655454818762180433994110003337649192132927573630961869690405\ 571222513445334992244170849659152189849346205433783301730164790123541159565851715100217758\ 664917552758337727468772029198290924745886441462251839886291179141094247667792843277082068\ 083047764739968743148798639932420859231580467485640144836421786941484864103816127587924431\ 738980120963447232658818113917619467719388984750935024070533067899259982269847077127180892\ 411868575256251889363784060768519157853446641909461586502537608202369161484097149586871199\ 923221611242095803508859236983898814136966264223994509713206578705402514486928616260371405\ 333615836228600224983712711034687898008653861067005455282920029349435031427129489108630450\ 296600840652736889861088009872545971683195268926877019610982340043762720123437375867369777\ 296012678981972423709493644344701817185397225318740847848308407437400569706181878048289315\ 818904560573850711384289333427803517864340982919878292284370476038293984973564234770986494\ 948056523766440056108698723655832895123417618905077229842527928806521148027755084699553189\ 411327646090216753912304639839273412459505986886404750677217769162228468253058391457889582\ 872046257524751844147441917887679887070213026381418992873697191757741747956994668253853562\ 544073149146395368063543418490898742909094138048122361512563706561264540066793939345562836\ 435386951112649957814692879273860081768134806461542721438095047544158362970157794955404869\ 446499307971982797065957685399744614876517593501919586167926264388791368003295612564477512\ 964173361747752189697388172035729519336808227802651898960534649859080844239280497025708190\ 693869895935996406004876620723028915150280379188950657014027082737209628734470334932822072\ 175376288006082838369274638934318779872218521034579824120635172686447249649569881783995414\ 744695593445443713223014469047985399098888456142170824112315004258709483369887915247807473\ 505604202817933115979239515466993048193206556091052185962606180808125907161000894953877778\ 035775177287221788425373400471736150430088861485396491253820837774563092755148004884372967\ 273649252875013772771030791055745137002899244883894803341845573320148697258398009335142010\ 087448358924302964326019789229620111228826703567496678404841534776922483933367393278911378\ 309667421709693192642283110830739630913679854135905949916415143662754292741090052647347608\ 201059681038336569666573449274451783494304457767890173015456253908604730632510842259023356\ 658407764954387964758522777791610439713287726199456828790876077940108414432857566307232743\ 337581806849837778468943191230067395144562552139400551410891096169961062965936563539196026\ 237789218355354079407014179222598125867974157190600773150572288229254385430747452113400285\ 699187161249072953865553929408903133520243715907554942267642963584627475908124666427486727\ 588987667454018135427297543949039057931592556141423897130012008243035089779001153328843688\ 762745641624934148108184941475706499851755074916467071690217220928823325632583001849656961\ 917099197168993762944690344581014059514912389267159809396419394294134216486712146857516268\ 625535777396335232808482429988099163043911474014996793972117414701725411973424270051120536\ 441198390588045690215338089467224945981803631244151663964585299609622554401506624039425457\ 945659726790363637066324617176323381740271752581741663652867076798302809050821583587789548\ 991811235254909748471260197012887107308762094182293785627548978772679990628927858817496423\ 222409215464087085808728574079811240516346817063344468170135402751561791508752740082786649\ 839630012750256688007415322849083178011669514008561125900405204671688440200076945521381174\ 599428229423352377776596777577555039049391183167294523066542674049321862070611049037039918\ 755851821118547658493032015393525386391653975616416216319322958075681034539154408428191510\ 169272878151433791821283301823111908508206569072869250272488086300534205609803799627032025\ 054421359719831919644821653307223880477851159114837210554375744457510145341245317421896311\ 389831140258311130032092620338697093106253478711438833702729035134011972583248668586729072\ 113407512307046528661089184945504949058587557568481166494619606527841024426355179503286663\ 749072771677006591622699506255081132395248018019685144856363531467099318114185350439292933\ 508324955741153626635458355933579147518701994322755542432208280525174069506371887033657471\ 846656229374824622400150473849348019756393773164148126067327391365932882548069381828122714\ 541749519688503269950554276422595064306576362784011975034498534974223623534869519045652565\ 214451530044187928297600297274728465121973808078883900999809734900532781946631827156869661\ 013019012110875434375847026657590848007603600198122388982771494573093423110332015803379575\ 632892439345888184295085425401819991105165031894129552096782869574576824694450359251419866\ 437488377000924555739926544229228352507141499494541816681323602955740627858190833307168545\ 942203519036151249018489935218341735516247607973559921110517589703512115298037436737549640\ 154275222891988888181392142846784357480633100016283824422775580170323209322164846591231092\ 007661872796572227095899808930052789965767067033000464659464961654305279418534802162523510\ 069495327409873141673205524261091530229668328408705197327487088911964156914299550914633066\ 657725586440842630571090414360297136949319355926621514635825842334103963963262596794175009\ 513908142817170522027165227137614782174044388259125407916053996881458733782205621391794990\ 610892679335155374679217612285445687868920757517878364981246253337133556934108159836534044\ 157945065357831150090023505246773036902334383242590200526764709728710637951442742249602522\ 936685802508568890959286882411812590207350140455664854995109433363268525354179872995983490\ 851579289678363221551518721057784486018770194558168332957008875990031636915911259508176000\ 508536923284171933058905248324461881756919069171105363310933420752829956345621157022362790\ 686579403969379048658123649754158768249130487077081091934811744644012578918696534447465447\ 085666019623829597330641866256169182992674788156381771387275643679418735074569097574206274\ 331551997178016967289455984163020072778069910529898124079754037700011600575545748429279752\ 534811830150270308238666684035739527662025824950201962607420953127036856378205001450207475\ 500682286102211662606776648860334119665537973708597729181029782683669687923140209388655002\ 708269157522922804831686199824153524103351315386984147705443823421280929177776573598400198\ 763694782317814376372580618166803356140770059866617944257194135859684984660129011956998544\ 905139527409467717230160578696710829430982562486385213829893134758381022456070046706927868\ 815987690231317135983181389125898758137522160153755351587844038979925323673861703350722277\ 633712341910647712219310207871038198096470277618101788110624310645923659879588847786439124\ 857425346069426842340223820737055534984479136352216264646028172376556403564407391167367780\ 350745578449243069291944747111705551715531143804554148673839321429201953396377512414759127\ 505990679254075265039766191976420200503259439369884412877928189069163389824824542450405616\ 142122932476013090221035441737291702534987220958532393040013752606864746911104095687475378\ 600497487785974407572169795573223175203515457827870497734337194695547177149814954225816789\ 918940157423610272884421106618550349544852829431626888428886017092305978533898883450673189\ 627650921425108411803457110143752440119031234231696628349947154369260067445109306043793591\ 815910584330180415174441277718181410158231294597281707035218010383447529277073147374784461\ 121703938600848336029122312647757327363799640516797027326512702807474768145439166886395437\ 705144477649623044467811388832353681107099808617107797730338654884661198837747672173168114\ 240304171015988056120583114394337624768419487837165370822989323454544037281233664978886707\ 171052420413622211897975126909064371999553082070063347462790399442372560002462279881346540\ 241268354138063618078837505157917480037914538113008224062011994156798851591821109444755307\ 475786509761703864620526438497580364719068263002441443453832488349349819127222124944674874\ 175251542535904232662311449118864040822452443506662297362767637255442948599302028272512474\ 708380388804159348770840137379756343348255452585469072412819343417254398606065262589879369\ 627137831727749816744514676358878223058453094637641741745996236902053789603943252009496469\ 650232565184163012612746506495666808425460985763812248248330308889628906037963348921266434\ 998162445245079971717419576416650452074492893459870262066067636624453762114224886326570199\ 363371318752890223414205015501141165083466470371642495252718076437645279729695927601054874\ 175647755046334359567614602915356430060015442559945011583838724712856065600557068335549107\ 543457433210320928372239166598371129454350890475405970600420637065518083973022808777438565\ 489305287322544882393849235709584616073434583166009183638775255290247341450557201015475312\ 441129391268280269502281278411165205917924507619532880428442211852110676710106108921684214\ 095089898796780912851036012728252931051566857094166662820877295837390812434556121903075610\ 611177287445109549326752722219940076306198695679591338196147684020779809071654434894933125\ 403262221656633794152722350726346478508495791767889943819432389524048371117662735950284038\ 122630741483233565632459316686922310590972886720045033098916588482809743690203990008910572\ 169060591431306706926504898284962881930937453339123229776453268446404421509176147826722883\ 331397491218618327114067742446020431904556821639713550602776904228684940066581293299263470\ 953957223784075799995925998033480250709932164007453956811258556793735234901136506422340194\ 771216153210724052195521109673791919636106089935157906156011296566102061552179695630702778\ 974250308431771788089458548541074432513344416092954474496627609791991800703742717944891391\ 757316043319897593806086000177811435472003620294860883093218307366389723397105246064765251\ 251356590214506390282140528451455869920743286633181875364535753074356757927082065045091195\ 831058158220724614153495158911232219058511092037791534608277125173358551291289766749788080\ 784762258188686202500152925455499970522289381983389267646984704679237359660928123950396243\ 233960812750851746884109227781849314416910839809896432262265609487951829188062865710201156\ 012699146150910226469895475900923924029813777971354976040126447676687056240787036068509618\ 823520980101495847606528067528929262014207756807267692543858655092693184939326732487687349\ 132898543947711650428723997295236848692744135935628660417967582546389766754596083440755129\ 028182520505274356050115642575502363744104495791576967003536127392930286556384196154374979\ 845843736557511687718271685724174703594296546875068600023251867232884204336525621795618138\ 015652886433042694600144253678466858915803671981152589704998382204477005792186852231442109\ 866920291495200089461563468116041607194799345516908226635374411263277218953463471327287511\ 113070046215003259461240495068688591922058839913911958245809509883223324527450910898119872\ 499719491070323618150763135893881994545976666722371035754367537793068057627433119759864707\ 926688927472732557957232239944325167182043716998530149194713988965904498152925346681404957\ 440823398890317622099950279723681717442553115970634190137491415433891653620741106496628369\ 725121476249864459430545267746012517626364104885701450510712547676983970004666174934258198\ 938322153132312228809344211317256743034725413797265680111985534533238855406732928799714695\ 393092084192184157687281778252443727895486064143453006201405090503682372475266395856754560\ 011162647119258225637496263448133991151286919943127705728913571578805231690086153456429634\ 651149806713427317943808885970269470062936622170623444549827179457533200312346306694141348\ 505041727003601572129875486303226398906659336645311901322045946994664341394843652546195389\ 938185175194900414951682812663113497926204762965641153112568527150253874380635411939856609\ 125819266003969076859964841362693110111782898583015047232954090248922099978897908716093476\ 394155985108783772282145297069964094678409253515236901703303257565580437615471870465075882\ 327471148053988757317546489751381677492791670682894547552250886093562283100935061757443063\ 505421584756288188048027035627245299406752426508419252535067545294620721624198449784147614\ 163098725802978993834568058380318715720326593249573224423528742848900818399988489709129184\ 605976909541230215844877962090347282774315271098356117122900313407577998094674065231606055\ 861400097619818525192683944452472247291764132184942128201452801702225757494043321210453464\ 256515142043205898374874851820353959467484321188991796324710019390627469386118991564527085\ 175578326673389365654962734658301433180155990743518539974385419008497825597834334300010044\ 709733152623803191020228664836773387448790170044909344466875956654175709852107226488346238\ 564746325719560155391574433324442695793327360722007804127957400337964997010267116727294632\ 198236725078113875104893005170412386625860594856591416842225198665646032244553516238850450\ 834010657539123768322348315372028474283750740408359553875389044989771404951065115375136558\ 398357500684885954802902782784342653741192490637629528282887621215681813484578428320673981\ 229600196075370754615262147115810439195871436195342450262313139018853011368808305714656166\ 355253059168711608377543735413859072190292310691555919552778581249678947714756485487879495\ 509985850757575342895015791825397478485606257370349634917978465328471969904798438743836835\ 061411278268187668260216343375151626631455685405711592668212972179654899919228380150960187\ 581540716367190898067861581967158283644398357777696720429406435578008633254328211954154885\ 568161594925146483789808423684905645404228201026005616128313614041520765268513755266303922\ 138025910009345199873262271049085309392007461040457011782297031347449303614838964126607699\ 347979400404125564214378005772509090069108662135427458923491628532450220125229925081144760\ 625562794307074612834779874112395861648200804554906110473292909875528039484921144059064072\ 243433456342593258949120070760095053914717328558442932846420909449746827896769389826619947\ 488911436613777689773718507089874128445268790631780523664454007082368971111791642212376505\ 577479986405643839484690607916486914584603138923262892869616721925920158060233282326724152\ 014039715417755739070030841461870481829504504484453930971766192156117408637853402644044588\ 231052644231997288902193915853721333725839337584889240519733512363715494852659533850069268\ 825964442235235641231962411488083060866705315394789650043784805341528715463080733241646172\ 622044579106246910762854101373404553742381043804142456170514067630503817722419049925255584\ 088079267488303334710466848003089469096375940630089140398675216474547616009986227339888429\ 083518127472554749639688337090724408697427985133411233137834369343443829970682040538282749\ 076522916442771922428057220638780168398699931046528070622691472531443103088981336341298627\ 293063141177926512192875352596828005913257685103896894740743159360099575409164502549932780\ 286202194363588552049738203027387469743247787678784668447405838009685810435810960737508121\ 091997642721586407254758946684701077603603685705541553834348086739935897161389684414972049\ 750833738818409083436927100790595814468471356543972260340090117437536122050133778811323072\ 516010041133160113709485422676356757328879149560547370767142762787476759537995207629347629\ 847939541464976134306615127964888712106764769724131151704448104967405597340031913120708564\ 938008480131341263658908193056250820938644360737624151187522302175202128908322695242993648\ 341042286721347094356637864626200563527281238101882858163894891571910538474517461642970009\ 334868790194949429100763774736531321921440988431123243696603634076905977653832506084922369\ 840965445516254935323356509045400336749284496706195955914498513700041689932675103164286779\ 784070492940567874399675195611299474458269243359846272830874873672172184110598717512834392\ 083912540511894764211132665686595306682754779701455618564601957518670397039995729227571194\ 733484411776063616753364787676502722906371241579405638797589716065855072635095015217354712\ 030416516536669157391648188935850286723235974938381805041336320497248426294582412497701219\ 671366116194617086913327741114467860688779107881727508245262455884840890205164032704223258\ 897407964263692763315283104324972182886131232372476426038028117799044123307875035434503917\ 256196624801057526214226015015057631029068916017715460315126736231352758166465764210541425\ 180381969438833472954753900233264477037810902340987455683365128088193826754284531453524847\ 961938220763108557503658604511985241831135859521702647957110045708762882797613588506729952\ 735512618913567463374614780707514924869494057884020307445837015572539171794542972811872192\ 473137946541666040672153887851564656236578129077918801309416114778114117944941181019960975\ 340342670172647749798698853830325154733695335396047892536593008284346820619843160243492789\ 374633526069156171636274724606477943736230190912780647962866449649540705281539849000320143\ 178691163397798785516559793994620636483131921410455709966930834321751637889214473471683427\ 000499788263154000787998935333820367177224506881166021897167800379537247607661864294796964\ 152910496214284763744899351933291781140345568191907999428458596083878871624666131806390119\ 261227855930379523611690880602039892879449989370614719531486593220594569628018504220936794\ 331936884332512960668282328619161184416862753845653491005592360386203016370668035009927832\ 480671298780833848188401845439221877011390884486309887383269366974824908731732458778795766\ 895163422612518482215126272507178691913976199116395405290926415556648252190966360123331047\ 787731893194106690189578091562614737133804231758695593983475392056384338872441823357853097\ 810076812377246456113698423051994581097875318868321591059991954169232958524651372225730542\ 067459719630914135924247016875354086363359899752917981280053440349896212452455825571237973\ 718811917618166415222846313740348760645622848395104306318199016262929532086605348222011373\ 849682754937019031302017732675913307996343362465550796712879018162791788996865251318873535\ 432751328856699418919358870752346126916044539963164409927433616574119805811276225040070243\ 329931930625856054660225994298530341845824309884889669887054049865546391507588111994810850\ 537305028124913830771042315366037545272978524541377836631670953314743953493874608449229123\ 140910947428170455483687397677424974687849073894144438367717415303544820320015963994333516\ 349914079504978094768370679722766139806178202935857188655003249321535170066951619817645808\ 850355797605302250774739237841447669654164190562348935673473268343156753089550421283305821\ 939414343909771300679351747668053505344693063353213376879000341185057382260333015625392852\ 746088592319686561260570228248906183980506378207026104916230583629759441464463303345936616\ 231099942220268765040946439240786522558500626765170604672679904142178777488399289747483737\ 568610784601438240858046344840215230225039252185650564996137056390012742275511583630785947\ 371701809157639319439082661324300154323707367172809734511125123521673046929641008749062598\ 470787205732380107422521200017902051333160254878708687887047435311491137757519676422220070\ 760947706966153139449661235594007529937463626719658440603244360518633050844856025332101694\ 566503406447053495512779410922297731704425090339362896617824125577931835456936041132771849\ 570819434973518810085842070955152125162469422026224280973828493299827907262670204891983144\ 671007979747396356829131848473477694384516245401471229466701166144608579329772482858774632\ 652756917519780684773681796667121740807924288200566945693639393457612578099932052088973705\ 785746434650187305271298613724479217065667771058951430139783745523030348822707352844046249\ 533866391048364356437596432806452037978480323105116603242070691117029880733122524285864217\ 313502246150941791166254258869258566257759081306510614254354924637736741642291052040922055\ 221150865099124141379655227106168157792882053673070476697097325118883145247092216434805578\ 215686640917031868705473910971492406627253667515113155752993720316033309600907375933417618\ 235428442901700210695137100379809876334005609393468426504866190020801336978111905200606618\ 449482155911846386314325453284740232015272668623384576477013645590057274834385947198768533\ 431788048873592111622315944849043126265710479202757164026089114129137644682836566224882668\ 598187468502403809422290085692512977426626874519448813236857279742621954758133244524376190\ 264786396629180319690231918174921275676991410113733874738648225446914744409753580567599373\ 646637143316965601072839751735716478405163153633936065321189484462982855386914874041470057\ 770825037205799582865648452960666551668524214225078492962688720677916852311052211451283814\ 374552463625456164184688335823261073364521461802750266137077697575057562234072533135462815\ 853736288242247324113316086487710473895630508156948678432134145256269962294050271512757109\ 836991292527027373249154675962411262132251769052664253090578060994403818820087448968370006\ 046160360459826111088015267643943257713901733411589018977378361384499841953871582077244742\ 189012748442063659628506077064348424699820761997366001674655416695625068371996299990687891\ 706298967244468596871852041077309119523647239509155042812955086243140841635939909535484628\ 555185572563554446189600061522306293708294086607693063813278304182413452525707135520051610\ 300388363141909885938348083340056758916940910201262864103579834015425325339658308114355878\ 458262419784586452764451878711939548774438233422063587875552470656300536871368728673370592\ 853034545876140557382131095027392232583167052401504167033622287175895883549081419245964045\ 323510679889162813632336051069134332856559495236720789856964855719145559756614999433287213\ 223071053311248753539792483610549698720997247196487938926833237321443006988412686265371554\ 947749102869922185888657688860711431173096190478627006645691569674762472196715631823620544\ 565047075053161196368195291214492396283541195974617411473590551739844592322516510296891427\ 453696345897201617164288509264230199161360408703191420137841958010832585774389700584795120\ 515316121918079640355508838846429063580348006508073744702096310464227134881654392060136386\ 733214818394476683195667422667148248539512581766453094252206325635298112470440248203526025\ 391147696248637349976071238131810460187327887748112764880866403320017409951178577361157730\ 894626455521115173862792002393683857906659472094494105457434265664262367893407148746797854\ 690493242630736900705090133221583461402615794691488538670597631601841456249729347490431810\ 420234992975434289688371463321037159802872806047369026801557457732696393919428055623221937\ 830363645750014694892977411996399803804436538037446996419001584646595955936966394426845616\ 704551321808868972329257691969439531413598199765065280761298064560617207788122629994026638\ 783981546036964132864051175879874528314633371223445649260007287943726677960927634134457675\ 869945692074824260734080301544941666657147316753305668981214735480816864845460504243332292\ 551351729951441735945613478274469994560011617116870080286202079689245594310750382413363166\ 663509557209563125555665904829813148779001299209061285370332027157592227742300145667812067\ 227618195922983588751526602619371256557464223559171959326531038714174074645873196557480197\ 774713420571897130896254163327555295518853143801300398350265602501422648473179784054619147\ 106264570733747295489740718169070986443863310090184906553957912311333798239803154857113637\ 642562518094034963944881132541813846036671923155768996669745434937924668597446632256511924\ 248715392800730099765372859272291994091510082904164317418903806016073793023924667982134173\ 400544693417208860991436301397622475848500931372209932471227512484746258767916310057952151\ 201664414932856153676805194072568496216839695402467862071363593701613730569684708626112393\ 714420677139952243228083609143295620065665091630006002469850355324463828586190139628939789\ 071862701334962777959088085083038117914566301271089549484843196506102172565649120814551898\ 137094791136056344499857929095182252282820116415837508305600498203980853115585470927760970\ 050691669484361877218938259577380840868921836486702631789009436932028806407656131974029145\ 700078085862194065128176103225944164469075595192973773969790580520277582965215587090761598\ 072688155930885795742274453131966516151805214973979350696703667272460432845602817310590335\ 728181089700620873364814984562732097705280127830775021973925093474252568544968611900940275\ 217928683032370024539536834755391501399325999605488887824387816202829773991958683000221100\ 743650123006492416290886272849765610481384367091964082902076323906691874298042499787407578\ 743977987247361309218719950672314151569783726958159321958802006237392334716435468494440825\ 568669475582638370223665946516507419418593384056284910637111777077467355429125623798506368\ 361557702274115789872460783589861261189158612255010524442290140941157061584677402419836086\ 888880857012501434936039561806107650636053550138220052558114411620420080597922045257518414\ 387575697532469042983079667502578193393868449569743877836952848111511813831667948641069323\ 786817396826184587434557705205552621527719641899261122705996913427166019079254336271128349\ 966590101161169700005078153510425637242672765648567461963610402580507234646566663724815818\ 325920718830417101121374513301412569260847387111822649102976324170394517088834195830443292\ 738199594262614291731710301959293004869171757063253806756021275891161445604137516537791938\ 925257371038688611306241060063993373843031622652720963353574557490265184600516833879553552\ 207670852283961495062888838470440456216029763029772317144858306987310474817400848080785126\ 931945158589294223858590442021740897223962796036205875510240373092804316489859898611464189\ 463573646949690514879008166317620528944950954953634957359107541893253070642344937062785002\ 913469886621758807772145117160063930899906322839466877164242962284742299687827954412339381\ 058181510461271390490564624467484946221887899663606188919627903982293399346283515356795543\ 597373778854006454337234349243185355813492154763935777299551966680287301419054382307863503\ 310291949883420860841857571805212712016054509736976863597812145192483093890005060212760686\ 727004738632409027875821138085894058838743846007219399507053572377095392713689151754334806\ 803915716958010827381906103573087731825790377200080990510820212848270411703237786282671583\ 467785236853007766802957669939702717280072912478037098262857025336198306713069039593237827\ 077173730016955415500317950317259004886069273062729931973338276346539033306512966251356806\ 343070919266727150724777611101648436850474187315519978441987246715770906493058356197425382\ 108173130491461456737713924901967953644163898793018325638453964739450047559788135710615148\ 299294803942046505645223895694924967360483865445752317239239084897405365635180675419491102\ 155982397948167539602983071875188617162168008995886818483264650604958997282297699559655287\ 543290587233695458104028947436368485276766981964614847918957732481781855424357592600961575\ 227080447677190319498588016105320827541448121654000402423236793972844071175297590317585916\ 585637191412012511406443393706779769202695926781300830176246296263967065716781907688210055\ 209546440488380692122707706762693483949339871441146696512976006401873019388141406475002166\ 641852709736988969583098692041536975534149927727786085295126164638207220047784137263928350\ 635530157656484783180196075133633378679505326991367600569627562772320955131579495550416063\ 577335448625797582874963222814149382421395823986253413589518073591783141308060958673773517\ 844692173183972001439963107090659253140153944301783753984298425753202841343993359022386301\ 870003577824488559297724705402767347961152682305708145868577823561587501380281710368695175\ 446710030242706112700552544104689701748387738873465295124306434928185871822102794621591113\ 284288872525218772274769063608634371487737709627055005898143350982784512957440012248955908\ 753635231619591815634610104057102765038643314606393196957779151987804341161848585160046013\ 524349741956230788622043254732618173106627228583843552761602315826280295801927720957409145\ 626847632872560624343120880705138604020061308086240759822866865028965311815518825564203562\ 090157154466304034323128281277728005986763205289753825974585642181550074990762771382127217\ 723800728571164009337894965856673557877375146480586852093994859326016219143175239023359579\ 408824992163028941089944009145922205347769069292775567180039154786579316258561053433714701\ 118783353926104167379391367597330844774678001238889097070539847688248573182320027462989567\ 438512974718285250739405445601041266805260465247924658258508330059723081447498735199626398\ 009038523185556384474455457976518625793836207802136226421468322522062802576075908435138995\ 052159262498765467584564232152838452718603045609631216146948189437691129557741806170613379\ 086247935341106811067602679118127315535329315934324500078821941524270391784136731608607993\ 367374545270810475772302463880252651985671523492464052326489600080701971592543337094951286\ 019532651318426984586589631317463095187101621460808225115973305141505968355110051620160449\ 088825508854152753294586977897669400769145204036127197821897845155564396292591840093603297\ 537000502222322082049917781576631059187252537564037292974714720271217653962932385374605947\ 951359226245557286600010820695974840290900941227838676532857565510827164283369072609829773\ 357161932849108803133015231178784185714210510716336994087221362527697482590456117456361302\ 978824504271017347693776450575606965805316995165604366281453963933425455974059525390435815\ 567242031438847294707925962819525386725523991743863096399175281479440498488500579133045520\ 137275076401337800700216727749186325315472484867068655680474843701091304521843291437663807\ 063672657249055249121248005399435671372464914371944621046720431527922044881452141046811394\ 998531672170897060201008914228657746256950325987327607067389693657200246200439075650041535\ 176662413967461263016032084456525096632973198059849298023672106305075413010296456223207192\ 963386904968418308013192271732750545957160350748516009712865716988121567068963369987705487\ 122655660008270522269521808053261554565069698425702981775428723637459615020894691875579858\ 041649898221339526305858516782276867801351140421755268268805871543506468418547134928462235\ 869173545212591693142810336531147343231398334950060334511502221197393909063746148634683890\ 313981420719323748437116626199055823471590050457505561147619572107159040134768806164467066\ 597225200892847146107763372300738368492604395796932161111954499191475214219361306286614501\ 670613596151283719771563785891923014909838491239909681948790131578194859422065505797687619\ 378249250651149742429102239029942070535154911521361649762540754582063138673928981231072463\ 610759058329427455333719541688595406648976415839265156942985788760245071187342453296969087\ 942960194003922998162670059669239875018657636307928661170234780254264937253189396901029264\ 277441285512271484412075143254794675872345517260550408393502957860130850069575385146462174\ 886315992498625612922686749088165817238936000207634028825667283437690608345495303852250532\ 662335797885362094946831352960591934084537936546524209644465784063474643545753387185603181\ 863154466155087596151522546211193019244656684448029927738664345504613938451691530909709294\ 274372658330524162680226230270577268128080566524705523388620863786775924066259690977255269\ 904910676193153215774636076041617780630627159237956309693668981199592124104949587810501821\ 396716175693550812727608724902180509813839255004248425144889558322783417994774424554591215\ 775576368800394084623083187545966287016554596540617024581457169001601381521586564878780895\ 811760927560862588483710345798692854977839531183639118371308586733955444606807875134804997\ 411349394407033634617902483885955790709328028723006949505529917842664675149388632310043974\ 440662262436827779038981879131582417979548469981960338888311742306797149261321157203750070\ 800029305519255948678812214059594213098604578164011458710152717928052887679105926044827123\ 699447039765762643143238275925446712123082840615882796650253087229620904586375660450637727\ 448996018707864033819157519276763274600281361332309442285624223994588109604598794288930430\ 892570007336324912938441343945253631838538301580064134510723753948299158047240346119457897\ 440595133867463465521410941165329793378423983673273768433085643809960538775423189992713930\ 269448704054770768000100835182131421315223704871477587963057071136993490670115271247761549\ 316402574351420637221294440997009312538674157428570472737013881635027717142038113677491076\ 433269341812743433275400248801054712034428978909846758302093371246276488837003675520341565\ 020557451155331179837080665746343364986638323807037386552245001572865245651870061955001253\ 448890797802768982581811694710295173737119825872288794920434001549481623341177434500276750\ 343629459402440664025408230254320855857733501566285760756220717940827164150544465432984877\ 750061244385940636261192954532303208867789692193639693462619515172636198922368907436350458\ 352815025525338756256782109590774113919826490668815478078472901761832962953457895719698952\ 492330254759173301095017982159728515839573165642516999864581945848566096930586434588148107\ 460237964315401525153060279483863812981440093872952721742067648485159660010754464532014336\ 921927228573795739807337572808448142400647626409233890417126326713057026469624063973154300\ 001216718233593107761452638496363485313268932461653422351971902545022165484914297476918537\ 853527266935949268075113765737398825463563413748261106053664774365582107711330919715477212\ 573682239904132193776125051092663602418545880878328452942763018438141450339189478723717599\ 594784009054219206891216551387967200779285164740601732774861856697229055158578030180219630\ 613488264798711979420180321274929855786207990991679612653227682890557257326974858561241306\ 974438524064205724166185733333034317930887721273036241059480338437133124601235019408889552\ 091699906305417685738890446598065627344082722709422779167649927032269749399767263440814253\ 268614675199691877930453639843751327270609678780522396555256433101759225112753700271526205\ 459010917251720491296609647808082508890041198049201117029272189031081535193109032475710440\ 770758716832071623401399561502647405187916211606003905242690827502099185189859095169783036\ 878869032085178952406026306844297281095215831681805000959737344234521345181431905151217005\ 389602741989264437278620735541805171814119697944882752963858297753284340844261557052180948\ 798004657249097322446684202241977146760233339257560854012782205647406191238730247496238471\ 166236074497417802765495778836862772699965201811132134505779783817430714646147179521759272\ 368389938193196058236776065112495486949806362999714208873730577708179435342414526033518053\ 789435787216531454961577065380999410864434623174745367108577223074525657731701035137732575\ 217956753417178564230141843408854463132780577935640697602062910234306085444485451866804159\ 009219914110926173477523137824718817669831078591629095833511116104937191729105635179797143\ 128002143552124477284150555475248534695284026696066466214060054122906427983404284415972430\ 380764901122551478204494094552739962025841646735729817555428241361876295238962550494005069\ 242988987099917695084778209546700357070878713405496058869652212123174363097333438174273776\ 289522429632726204814206405936013677728011032408129088760360318271989594028215478594898254\ 422559223005863017990901702177168423545448226639869174353208763493487473413548374195432994\ 258206654079522599969995677395858605192311415104510596364170386956132426762982092643975298\ 047526669238404436230398738010304064653981965687515962264118948925697683988233524817665773\ 659155569114697797359087606010503435097687527530195764662644848618478770606012139915464136\ 126497465610709665678279146662918423269766451011071820308480151852318144159087959142884346\ 951266531238909269952631854768799497960083392028988923857348618960356675947040474684190804\ 219689313981188277117315911677078980135122983452850303211438508364047843801407159831757138\ 498195970385706338942655957207394323234244570189547552859163046867177536293763396576878436\ 009723432381692139681224239382372944541962904646092313343888366588710066415448673987861216\ 488532872696716903825854372470638763054147858889199571748768906209669584061667826779328839\ 862541470412890788810346405991790184617385771618636278768006775877193133600327591257869323\ 150011538682941004955257989427562414405539144263953419496295662908621544779337279863233417\ 548917543199833005175292612863449653387764039615943620413853672364422730612001818995938480\ 727671586367143340269442247538457673297083570604392898746458271917106500465521228378536663\ 275450910258105395292395714241555343154431306970348657559992341530468242564026978882868467\ 225419768752379354272182254483220251375416067413924988908560420080451691352558533383394943\ 626175393297754847283537561682681308385271075916304596414182855840519606482739076032405368\ 424853318663011638109382074777842885135778245876034135449534474777838983109304756663401588\ 612279213991679434138677395545368303739157701644780516848932724538775523584709778128811657\ 351657721912617883822517961245255299645315792140522448553111743146884357407463834827245112\ 777258139387398459220133755979909264197811220202845894240971997480829358107572756028877037\ 373561399507684906432079738680656159897397971229375257466834663252318317686130869062587230\ 868861256726061610153081318642296363546260938126947126642490463552320846639343090135581092\ 234329489357185191060543320361060285266520607626932641590776175114086364673698080772225559\ 128712963248942399930413426722302380070449372599288655557187171643158424628378444369565531\ 449697927111294731213956599145995822438484627338683587082612500704956538324098094501406987\ 293595455601923862556419538805204124564896497189012568937154813875373126758606323353120904\ 686428407718661570116023423300058918532699624862961225165616402209279983773166351074374875\ 774850092772760469811261689764472569935884108837210960492272051536132011544748210953102800\ 250295350414600385273454887391071098966328654613007800102219002610235543864053294476390309\ 286888818766766932399560089774453435065226340102369384317497628236693542240036468662248707\ 349026346368215122527118543871848453433596826618139609696243440725676584699297088623426785\ 567743881095283002146300025621178885423622983514014293253191458061566241416482967809752602\ 213510315695009426193813111636169032411690438892517045448461615212667673770485869817108966\ 933625649237911435348239025027636235735306883203282447646393801644253742651151762188170772\ 877374222852200827811032883615095137746365854936876291028821730227904336517965481399074834\ 672987622065590110695479566843199613075484415651355753074299367941320953615667610789483232\ 809116816247842956810525853529068665793242262284711749441173826873307530503704400229349858\ 014494724083628525418225384678988805955009517748320646175429022532971504999966591959271479\ 477096469955029405226866079170980503773631685348848625777681832481377920843930226681519480\ 375692271574966757300478112129713094813411189804467168345052237190570431676952616431503890\ 215552244052059114641852958646972642615639490448020648777478209965013482603078888355616476\ 040138942697816807111850603751510803940351595098269102896123053370595414526683909054816419\ 437700242168549302302811554895733676471507136793328526733837011463261329636813858098893751\ 873668793533581695456179799765486135222364733281039771939366054130790682175000117417825441\ 689348027216526213437402099172486626026166584360360761417066184913774122846821666509842787\ 243032989669400267830016628152101576326028235314127312222435337048739125896439153071794296\ 289077816352246545855890158291244138051365757452173460986304552021002372688797863651208719\ 152588910181228090950890050694457377266976003115699003560617968372511013932949289771136544\ 725684553100118572453710616007402268755627797407039168768336069434547633394927268033470331\ 356481389463449043964416473647458061153664831200370884561048620249807811336331450209741203\ 575877110067883183143710290927887322107626935989402478722144195121284016704274365386548382\ 781003321859547319360026282008611949262075123475569887874238189602558009016712802239332912\ 070860688562618116408699224279267004613503663457544795768001250993102380324898838630537078\ 285950155401789967606392400590298131814544013935579715548165889251326938307416917250513720\ 680422921662393681870410657515846026308596383919027730436391671209421989620130636664689138\ 399328676874586061637289785236937449530931038949746134872196202485169322363727534263674223\ 756570900767692610362769641694173581625757308839296811982176788482131663678310276879312138\ 533245059456406042982513080287206037634919044028486256928312423548490549051472451073249647\ 736115709682984775990980222254988124172930845787777480053791050694401036262592593975288094\ 917806371067460325585283463603043888629864593965354731635769752806030831398761780168256048\ 420701388503011895551535571678999029417043355509283947128135695876259350242118102742090457\ 251610790584232290684860360074506618197184131546808337682831560542591182033292562811024636\ 521792668088952699189484893958002425295553648913983056563247539373013223818865395481863336\ 574425107275693894568866575665891760245128449073331408490870973117297258025394147601004980\ 777437518195975908488392016044465733330504492328639342661096490752835210946946152061354175\ 681103893300935024172379261634785503439658624885979384147967848286128325276080991668805988\ 482878651422480963524942033341451792173616151781309302727706673023295928222888626047435205\ 205040313136475545319059955807101289721988084576436297139358507215808289479712278282205097\ 294195928719049796776703246934367703995480315320994397668182167696011977401912240608180889\ 741077266234716435575560795005337227573743806501461645453723723780673245305934851259891006\ 249515842729512517409979543132258918446807467654632750184097148103013351234951697121866140\ 511538113951305545401642004872609757879853668919070528447196300303755588373596395491864671\ 065618617174432193544466098212886006065421003488893750916000934134630866620418939574910899\ 036739871087345589683862197066052446239803134358076854550709577659556427906715523600827282\ 169928712867366718296313122688790520552582649855364595838268631813434996697169334069716415\ 314921175692054143242928833185805882440245953331867598017616186846109550063817783547320575\ 156311621414039132877494020126601340663448224527036339464320560543328218371820527966554201\ 314284459642635287581391861752217997581658930375817792356084914169082276986008284220906663\ 317678882488974557505481956557530205793074783719142420107339351917443587887193355550148653\ 620425505134236664873158955369365572818983563919808833021168531507121965014061027668992015\ 917998959270263491909882870763900299705470548551450713972190358445943640173423732446441161\ 377465740806707867505704863581828782132229498454100780345948987752773324729896354221810206\ 626792686080169259722316841144568659027213337371390766492732308743951138394789235495622180\ 167137569512314553011125929153691992494975623772674252669325600671174498430098292377878842\ 404787040569775714843632841983220558168120944284942903014097681408495696195603642230456575\ 546156649495376816272217608123144363097910764284531632460310832415407467563728652937141368\ 773024191204649696607706920534763612550126095362223371180874663370769472224214542599690096\ 668131482249591430395282221143472346725158111001375640143069321596366710595960380086446893\ 076841228814000755213628909384322280995185693415488922394380706250082729262959162898539131\ 064148476775229962042623266944623612540047884006407870241361998041242652250168587879438367\ 028611183157071520122970651218113871829069023120789428352080673471126486807056091251055392\ 778085094987538577934345304195831521687212341599599081816288258842742867860492556221336462\ 686034706202726827212593910955745946499985494243536774948456904613604130360450731373031305\ 715854490456455618749355547878718013509577494493739840274954919498989859870952616725776288\ 020869522277186197675410412251126033241735209855244232391128037483163620034067132698715155\ 889654754842016343154597449437674628355751704035423464906455055226903468858918635561335649\ 865821911781216031678391353571104897954066400872310364980904436288770573681040915865990291\ 129160082270541535193878389849188032063481036748115825667412152157391416296057616012595801\ 475995346022655770584869581024158142538658291602792921778176761768324435051991320368747237\ 416928654806010802596144230817132329046898707882273271621601501848299914576612203747654780\ 711191059498633883488942648286217114144311357850832797625717788867637110345160873620193835\ 818467881154720168234097172899428743836306650622313186884793461804257197567195369572151145\ 763067103338719663408217550550273983873002446809657859261378381621615133820122603246644246\ 562399612034177827211391577143410457835134736620779706441286672505262999669244631053461802\ 264823746712456934388221216953155579863663318292432354275757988851278504483763356860043272\ 575162037545120436935674931869697729427217902235016682355307316050450451788396796144077557\ 591671971436353714594813369944662997452020107724385565823540928642799203647978421840629079\ 270837382838376502563890584485505981813211927158608829665908521144322548130192623625478173\ 992736700878288087198666229008759440524663562048807946137270888442010307229668195173112768\ 694692157263398575081107437934687296466125605732485518382117034432221892481724034284458515\ 286130140416699526460680534616435581410310294795618043640886733578512451869975973542112655\ 274998112581670526323042648778974686541121024155698652196203510416335932907678244689081263\ 684110270858537928217973457031225758854018109185245128516756428357568175950794058921580168\ 973196920932254992802554755796090349125400768584113649858891518226990587390337908827023733\ 364042308129625916677321533067242843910690317293762099448445993131656804750234217669479438\ 449794251535886612057924592542244297075651307791597429842256852625563363095594259660875267\ 264543458272067375294211034213440822696628308531846807918392912630122416095566771379192049\ 506198266043532385960111222166806897587075758810456718513926362501549083397564077734272124\ 627304932530446162119089307418395977536856593322004398535675381204871331109667887063353033\ 646860140173426727370797925090229319516628902360487659313928978943589605291201874426439622\ 759156977313745244881501375915090558273589515476587434544813727894021957141937802941856583\ 679758604535140900246125754072166894052920679649489139123140590818166292286960896192298628\ 735314071997718379477275149274129857644455234761867544258537070464997600888985185358317069\ 546402567021357411154706746817201402155640689820968587770353086302961912974469010649953293\ 143485920610372625529751650372600511423004835187362279945025964921744074403933853608434894\ 346922957354265527265851089073799396348316695495055159665359785219390945650598356735008728\ 200671288855147076924935267836418716044267465099988413943718913741266763429950825933180776\ 231312121568429209218100386215486127421661222911709787203468300547970592725022530135232845\ 934343625826864686584713014223116131913001339666371101454566733973706307373625649595127699\ 923626230620144893971910339078505289088312865865092805828341473541681210873267318982419287\ 334790198976781132701115269507535511428302640291976729587610952650313310516120706365547963\ 694164970906095976670746070301590308723620407712248905058874161238717151226250447353804689\ 881292468279219813369353204948316938647369336201661304901951879794276493613449826486211180\ 058334277499755680768111771411749864190316990655132525970382074689735996100448751732115101\ 172967820300637627167813500402433398569467960536727239711130626512611184507946851665445594\ 650330069305518017853109639717302067695043865691914043312401163917723705849469119606549264\ 452578666468901738482722517419869783980832444777645786165819453913883173354201506832414905\ 371060411586977549522150672953625787300819568313298535291483211444148163794142607816544840\ 270295405080430096086167389334816861787064094921001788009469616473525389902728978849013352\ 620037036175134477795376569277043511436217567907467350334549695465656340357692148529760264\ 944616985974782451436834258107062517540651732830748237937932724814669269116394084577579261\ 614877513720396816868127960299678919829833939250556023088589835902662422666282587163510049\ 323867790883575991441134913062802197903937950072364363279731691172744962194218877575689747\ 202813627917851021058636191311434271265709497663639115697502723996741196468892134368200107\ 330663142228020662908868077849836959054403810784580394606750883614847006434073770509686509\ 346370715181004826718535977953480368089436250003429041694976605570673986456388744063900062\ 266910338592914435079071104727660299656299137212490487551510065686523142085884066720891113\ 365949367632079379274362348499827919838485139021270942656127902982071822858856117802167842\ 596289236166898887233737963956882572614402449584928343983326134829153374494274557319469141\ 716729604343649493124785715178057426479515233077419522785152183257729243143966385385720879\ 960551564047201046972840610913518215229102327806364999304906324152993985919000198545778391\ 089516679372282096133540296602765234382064276911420483136333063293401092061468419807458671\ 404135263857149683231098466336552544967555406934525270917703937733023410826137732286334660\ 588566858649837038833101802239981250593518667489737422532979116552624317329905842034798618\ 910146312581848175377333296838076196855903545958304535846525956781666549000258839935933925\ 415751144774729449912325951683672049825217352106737064457003862649092727271533029346012859\ 205953947915240914389410424602336883112243053134772615473645636555320499926133126637414312\ 448421505271581097674059837063321632917882852027213928163288564918082462002016864202848666\ 080930199892136644194453773335906870967797699418726017163745394174754791086927572124690287\ 625354758140521478795706914860742215299108707382296019399768429856807812092298395718309589\ 999569272662435523678176299075211993674739916714327077527874616177445703326358120367498360\ 774859113276712339067937443641739750294094740444618053287575297584165145221754534227181237\ 980246212643340780730361130553719964234498639106144684520790922747550969385520634380914402\ 588918840970406943132172346366731641333207547012221956938314385867038097834032647050293587\ 259964950736353355736960325048958598285605285057898034278825276086312894255946957256644844\ 851534101126497983771080360843803263048609084164241774458857325621284122595563027561864862\ 962318515806002804143690988926901163478414344942937082600987065649802957465525192166847920\ 044290989050506132518490957010981238944046932752108381748206684338012721514378429966783626\ 000314131871750183979915700270817821596661844607871435605204527644362638553030038348822901\ 366615956472075278261797171579509315227326996453099278802112330077519841109748196551022530\ 125839450385181340720220906837783491560369960512287342384317763115856832439935048044235033\ 417430668208585561304072064993619310779929522168220935198618905937314451050659907175606806\ 408161054518571487288750866795987097120077331920621827716718145636841189424473397212932599\ 328688479873550427808346899950623373943612121868755125527947148889701260410503821456845219\ 999800929099058333583545711920959669009299502689305897634713273974431080229998308263332644\ 946565093837857390793235262469502788150387358778870568027483958318278471844304056243185566\ 719038151177457338194087235106475598595327412019348392399980492049561311917961088551234225\ 679286642585451379865251423339875285072647779958161327121179258717280564088563293691337357\ 705743837424470789045573638950040354990364609448316544155245272494711094383663876323759851\ 752167572977250443930840366659423555358267403986970507973334058338458360079992057289229006\ 878022741321296247076971834490218108546738718393413124985850023960644468205825766707192300\ 122931041344895965547588343452125705679369968121204060518085528191099718851319153308595737\ 744846282485239814983216649369499575989404486532176590583459192458886493976460201042015559\ 611881158618163858618156695067612560495871135759606194042264787668804444587001638948045395\ 389105181915512371656842375292808184845312717682110639824273376953201180568707396950231351\ 488961140176958186495193414340755747607128429852964244559135713247151017384102770256654915\ 194668103167600398579155355919397705628913142554667222877679666398191608752746613051177332\ 627837753548125287657773413746338404436134244250389651250428361381140275572653030369912972\ 797921034971581705045829149629850840279900007986099290270184315333054502597391892417347409\ 625336935376032411694938419572722904597566210567001386014353303647470683696094086419461441\ 639021073706267389677884928163000346761703525564896489453824652093678370029628547549767882\ 742247601763710883608876413443260680556358118671233589223322484443711519530278062501892803\ 635930925278747363094973066327065360111865639054517646471538954637019849123209018102223045\ 126175096851549834951551924858194092207669016561646539141552479431371166611094097591134830\ 461789048104050191054466777937342515501454773127234742341018551015582686541959236879376103\ 293437201677126936893541824411778003130384593068039008432685609618779591844977971495771784\ 206066069562065299472890166592688799365212633202037502093827696911028590333095092335604820\ 262516037866924488062091371984631391861421541277967221061356689737063731288696342135476843\ 938738124001049537936758388924073516875478089545703120281940944876617857368533717747207004\ 081276940130703442064311928516395763222405579859469867485927469614815417181941291997684825\ 894354587508026513326608695133530837048007030685207344631212721498703120642985786889731442\ 613682539014226045494358582303169340743922818055151107531728097841401104892173351727399876\ 288144308480601559214513499426207219613496680638309736620692536707016795486403617903245346\ 886773684788353738731609262627553851129577601720742568770923007437022428210692059147674913\ 683353705681464013489118642506792933796287130114256863148836177246453029128672994538795448\ 242769825884588816230570189934500983447890578250461494910804270117170226660148938042591634\ 452937700926148168045894959591593430796338202073862561600696608822562405963132981116609046\ 216354285536768649507764614800778759932394232130597430913820343441762843593793992473988551\ 785454157333383065399779383115367129850609030248878534721830189251066146184519236872730962\ 414939889913198830719300727185917937778960603588888252516509264667531961082409118271836149\ 118059926208454966826106195417879294890330479445622250542766698081221487973570586619425652\ 836169430453391754173002081938382795482971723037313833901105300570626416630380916379407094\ 213597498311963132665214398524012348969360773418720398211636329967456265306926444332418959\ 475516711052178557964311851385832986995760681160358390500932318146767173370660604338883322\ 751970427940255682189511281158542534448461715217301816791690726694867023341687766939808625\ 619464613921404463182326130532938564806992718976508631843708682892640789107704064554852713\ 526665440299317553805775543539498865450456465047331657151223149359173791474164045050608560\ 382794836042464016749275283884211410914977684856002654082443047643358361042755609652867446\ 980260522110193812966410443017165358375351227285718884070501005476419892769691422503399862\ 492336186396110516561649136926367867794887555512663393910798017554016300613454617616037754\ 521573004814393869479590943002648175159363637781374426283738851183829432545535782921612464\ 547427088142029799455043118177158220246461289839362675963822368024532792849380761001456530\ 189283332992162084283402673500078775103839586563058920154792225594408071469441624566306745\ 312431283753287137754188904473207958037409991460881400588418812389859327127611907233131305\ 405256847493793176829453847952199102558264572170329832251953041253944442103128346916120342\ 585709901383296673198078435348559342056949922885442183502681195830692236944842033500649583\ 699924589711186170704611419888090825643089990883506299809462489202483280919375174543291519\ 826395515008579194333429996758729515851398398503771581628733773700857786483145084800718776\ 944089681276737724529741607850051936741961020549920918394797727122065475464526064812497444\ 581443943110924010181334434651820449912298124675605089101345520939943122648324133395616664\ 416392368172632842300192452024332308749200820531721928879344213010702755358616346022663885\ 791590503943655540646182184742434809042431489207045115837211418478688744842231566670927768\ 799555223191197273297877007661413185995369985809075247257918173995501906423536096874458536\ 882726101875507925599635622956396545543675482716321132393526546283079967756722714683570159\ 962055907240223440243115050677954478475274394779873041225291977562418948161133822993900045\ 499307507263025490602171479263175599803471949566027593071886440162326628496411331264005584\ 653819047983270753718407003522080883835360012827751683226720575477480935845942920258276277\ 710397346820377965686771178778220480897791285291013417684129594191760589245868820205388082\ 352012191228094398017601999026842122713616390755747993036626034337300331840617089302517117\ 306901596194065196203213687713133880278049245280927179547428343954333266943914769729712018\ 986683029114373378233687888430817508811980482091325073417204637878701963668380992122208476\ 469656426915792605346737890781960988365785659179568326894681809736272271742888682265032285\ 719956411280913278680408998010302980807456909909952988164927804181728541303616132794037121\ 970678635766131403335195818654045724525795279375704416450072268142006812656038752559676553\ 111941083707447776714311553337326777258735465324141633551909708273182974946902309082436165\ 297868057171145476676975684752928768974655110877559955370463337598004260410507062410268797\ 288881426874384304060437034620750253419711861538974618752206668223010876644603463990040324\ 737202891369611265952371589654367647665408142169173289936170820914197882121299479591904157\ 820001699289243629640672397518132179320441562969714650939695348359886123994069396315438807\ 797307066785966470828836105398531992166610685316723401104735144135378970271996388957324638\ 710409513845013975110932281547665067719954104468127293614946858069464441305377310306912732\ 015556392786496011119208412471742730972535192220788837258170752380735569861126381078665612\ 304222548689025568228836740743516719603692972353530132622361405982583373012471608336108472\ 081655473082311221718166906819610495679724684125306710719639946325126891417239584276495849\ 097838137451255275920661694939915336809285306427797147670930393832818786785700786423166103\ 493892708987833189515998940215113093165433413145500509940982495483660269677402456544342841\ 772167918444658047897615430923408269559375198793771572744713640096423768851867362088801545\ 394236752297554172387526439289206703654701347713860716186901804395404718930017470345966342\ 609303197861681136681676417729705564213539213378507074630025438792690119595865333562028662\ 524484095002347035887799067545196458476358774826890494863933755851403027061586018678961215\ 501641989481429900789867692252025479943177067766580501838572666791239248593508078360518372\ 933633340108230749939216590071688441019093632688592795569886387272379187734759152055590991\ 406619084984137058292679301311194060010766409714331141555927191517651337401539361687721633\ 595782213111878505516903875764244082388626828102282797731408009084573585263019031868700431\ 409235896041541047348108612581104583029654870021238351696530273307615923769348743336809305\ 890505646883479163869801047114155624725877385237125236091993261287022376622373612446203964\ 227397139903236137286778980498378762857579267265755016927849077108731396311056133883981918\ 134643039277098066340605907086519441811156549704123003632037789802524769975252103261184163\ 351173014390422656627474648500546798601688456321028792847261873771524427641095900986274517\ 171958985418903002227021804752699356197698311107817474299445925458354696435124502987114927\ 230465624329343841201035515696472552928680530760244257331827636536589340902124019285075573\ 932697886411524094675263214792716901777017505268546274442076946838037968879153903895596917\ 172997116794337109700335286001622413369342967889210152570821592800265820167155700749424379\ 066887922620978259517399594193575776287162143812179439288279843948522953069360067311849189\ 550867755701948718159045707585999384284459115476146728499504135731596589047466480407844975\ 967115187887646791320865445732299732822001326187339917726696241384460919924912776275521086\ 294579550452752638185542530794310048836527115777290808953700814437267241825582664259013096\ 175755152132225490686758153099862241493819587146413422302488643113315439267901765578014130\ 082938954670264370281516213014558454582681201527299989247340265673583429168673303057015481\ 892659540911354650939653664216567097872882691078363455411007427706102874904732497569520393\ 094650242757021054352176741286574654628456135922484219906004448500738537273261191743693973\ 846043236059576155596359185219175135221403453011720683955634769984468318498708407384566995\ 344176092997808568888856085560294413226883778162514336849594998578304752440345105632931070\ 975798072587913295957854839720450097115943955397788911453363441420243393097289372433419661\ 114626787716644091872336089727234032974140669087695245675930888896764471590626057485053590\ 649019404347353408386774374315067075208567336126003600170057290042227535324556267936208180\ 333745713270480232665238366827488798596449499623828153753832348054622141732185477446919960\ 550014572768144709029494228446064194299995202448460203477262523454057014824179055128175461\ 092566377036924940856410900671980797178282671396289452599751940081205140964256885877509909\ 924309461297227510253500311330907089719674872919730651034383659123424870428823914860230071\ 769014220833360312891427696168154490057957277648875017888800735955162863915799675501828471\ 966825471539253061841095816097601364553535876668314491039059812427342162323159356487515010\ 523180530971499962127861428226915674780800134176806981978789156705994843997337676491367424\ 001989597877533238213484320681525762363731783472227254999481466914210748792393401931634751\ 911211741757235640471349004152866109331284248487936403740881289587370319815783652173350893\ 924513198877928845719800936775062004026852461458138832560175301400798141268351573006256914\ 222425431061450014797559767291254729324114393965485431934683635267012492964473419488320693\ 464946280788151783687214732714880374176323311282951002678695487572684272633938567168591629\ 022277274839413298729037585014046300561558288185652924656604669449620473402685989937179662\ 935178963641176597599376718675012801721630354959203747274528529732037487947893191847196425\ 442870981522095565195913382099370302722331612854944905580056873557969635865618373934418538\ 721598920468141839809013351364873727432059976808988425495897787319791699716401955522056545\ 535465918040730350990222446602147986599944414575447726631642714335212780310600925802957748\ 199446371485945309689013789201285686457205024698507963610951531245905649095503142775969631\ 861499113876845248874561121676088536022800713247274145260004849899169594475236264136869108\ 452994649190882042191314268376702218256497302965458013907500264189766024397474370565317645\ 888272176269197358383570135388433836544679216657658323942166608235755176577953130406650157\ 190559481344478513767832075357521547955595615636817358076434598815462571411564892860315893\ 987232003743983088300513724560935135750050283457307112148832452534329022830246866186372993\ 226740967658286643973250498275949830684421875524860081861503400518102857492940547282824656\ 188740147437811074344549952232728342914667872940534478672743184650812781197637536530155293\ 160091909034114632608486110012077396780695372276165656286842491415208693690976382547045704\ 920143537518587627801735250016481391773961243429517789764601484341823050452956987049783621\ 929135117559608695811887578832177714167125391360853158159094591109738954263289514099808253\ 635480006860708465548611360040530937157387957254670799793491069303678445129962460177103245\ 844065254495434116833333981097899833320498877058914370858208275511470384957850286116973096\ 680177977327474638766424485770180064289555431075683952776713284645358010244345499876549832\ 540539202781748862119371889610299886509353731907843847738364486055466116018473312096752806\ 673157582539770861891503195867508952900802434208382394861123294703446461024774084591236993\ 209574643396595185963920427322824385160898399458311465936948988486428550907816261508693592\ 740752205950993046783473015958426398507493557287401312275783862807888935672165012578576481\ 495002350716117817215921456573054707469140958626301703543700847233690445774645361673355241\ 523284564387503043520595923328687297044948706190224137247507993669374941737654639013442400\ 050258898433200393507274373332314774662951161126066053451501604093646041994280089547124047\ 499813641152465111877661612382140932337981754428166615877738332846460770748393918967053484\ 132396903937261829412227892960804099375892402317129838011214613251064762145851235571343392\ 826143278642005313281468646280464567863802242693989379018833253270036978645886067902313807\ 023642438275322323439808779283276035187851822712155584072360455927077380947239318949330321\ 576782161624589344695425929330076605362319437550397536291222413631062345007547688760620445\ 739622436433394982691496354498111540440408822508100914695043642791184764556481823257917305\ 268654199383970181308653620665950407335557738931188079725309655723942261127952049667330339\ 859485493389878577705459908615419344662172592590571964114722245496280879721260948085948125\ 523935640309407332133287664452908408564796098535397555303905553734128008283064674178673138\ 313675924687156628538849650253767641291353079050172770646419382447962513068344750757920756\ 456776281291535274146644289418030894037634168162132582101430334506805654097937035607670994\ 271502031936001276909799999531421022851022166003618956646812643076639085161143210494283346\ 161069034839534567815207262475325858500079117383321125625596150776322690170656341244476347\ 062525919375800229860879512699890347604874859252481151714658533775253624672228995974882174\ 608620116702561827788252903109237472369621729728951380038157959055906599818854746054665812\ 989302899127794512619677178467680233657659831784091910071109432751768240530613038070683742\ 200726885195494260198511705816331974781015754955615058364273101666024352076784527802381573\ 744322737788570996038167851669916363865581128700370511713319425275076886432987562028976618\ 410914854441662274146213329384825455489711956824759689546878529252724151042171301963268529\ 429037853327993042073439755975363814333098292571450770630054648231690665296987904753260628\ 403854620705642458892439578485248668181362726260498554188572887643552065856106848691322486\ 520941860812316326824088145661194402646859215375653462203506057058144897536871940808154445\ 348067224623479374426655025887937513469896869089284501326452179259724517079353707227769607\ 113514291474901832669924814960855922006805548368498322343335294162386313872385206673875378\ 807122037942654954496862466143231461982927088855243418130869229555233113762939859936902774\ 785925077560435921239775574200717855072745412456224758835666290608026088238529744120379708\ 755428606388979954553534757215696204421444721100437677850648355775690647624962050979270317\ 165880779961829921951991555559176477583396554828450494835484649976633692962533390983201981\ 275799431173538891638248314488740196985595279049263940554403719396386553681485128456633992\ 025050560770250648600755788964120392545288986419321492047454245536001569594073797113502496\ 691193698822742173239576965418268802003215157835436361566810323735366145503408089033570347\ 446130385505781902345373664335790551030948570064405163917005656575424981814788020833885783\ 022953780881435146142464245308790523127713855483970686326527462330412328776970882181054066\ 065387743293134341675839968200042856749040607172321940203258489420606747028843705165140099\ 483716082055554528927091210724184914625841007611204384560861941894671355541050257058338948\ 549289541015759469878058832855986519365045149523033315126650801697168205625848746080392142\ 225068398061166364111195375131430763944473639397544482377171257746327783816136118031933379\ 579510491532883653498630908202020712626532059319327895680663434301519708778298702241036476\ 976396552529576579390054725406419970073171476295407496838345616061608552787723949877817920\ 221927130603372346017718905398813092244477297136608565310722966058653794663676632908065620\ 162713806766168778580296727711393608344753005440880595325460254356933978303446076950354868\ 550845958228208059750198504203032999147503795111026495485863873709525995431052854689268121\ 874090669389910280578288915685888388378459483259642056377840629046863189621066457311586734\ 311188800317584024208659403295521928937954931815938788094094485331152458764493470718075186\ 253067527783725920357522495665759245734386525491225664250649519432138582430771770594215339\ 640716392983499102849364957074210464201788198027983977262406334226672774037524725704512589\ 051499501938089928980545972384167149815400669526678414111647623517306298982055903405789023\ 112017505227097240342481232625505572254803195257759848172126314054978197301856708023847110\ 614878870073602540279210405884514517749795085225326531279627737913449621068712161316085910\ 243813599632232908411480095830539045384505379461270787051666245956537365840754077037523784\ 703723726416874931549023349407778819956031694274848822749540038753567317407754252568089862\ 825940367174418715126903674190255138684505827088272718462660888557184138880426951943117729\ 166673959803761612669473167282610240300993185204368108667647306906156190950395824124005952\ 513342678662586130060789199804730564594641753228386070632461541671332372535434676164697046\ 144173815282698227442898138358124521626168139904997696740703517412144419742576679232639315\ 460914111866749681197976962658372676730316816076919638017679510488666187360124290899236410\ 552256177962632665793951108572005188889622240197095059845848239693008198224125005664921049\ 003654876969838683135976189442041914652184759412569606137274994469992771431647296102855609\ 613339088508869372704898770518145950484900057393128918065071737662144323018449806542358217\ 914393112405660566586530849019223058066759770291958543874581447470772337925801569107112113\ 024494054866031244472030572250607811703274946045188507560501682921466482648594560886714324\ 426618936223460259335690849624629719289648012351684685655843375218034140891688222391017330\ 631773789370933097563404557157043060316986501007997783169418635715735905132240407699404011\ 217848033270129264360250586987011533551844429492766390887349671185928139606702529907829494\ 405416744796240512725186051334298663971448641234553272850232637027326936616570199804655869\ 457690983826891217338357365057050770439990626014392181619435598293748875378839579268095344\ 826507276288941803789352481977221276026294915168922327984347456788019995227313100820859501\ 484029095330677003126001622553891155913544159079458224695287251671208560928966445620886100\ 662507836820557009926750756894139354872263669906027087249958465649228346039620705399208437\ 362074823078547372184052339859301557809579710284480541192913664752047043935056707415451362\ 975026097219643555102242779929961006081395646691393291639947253457430339864140853189978599\ 316623677081022807136093385177534160475244832115856664806385068901301438131003475794562132\ 475269056061671364909995285634204221768745200518565350515837896370368473133867811782994095\ 100461395433895362380785013757517259736098724793175887210562459776112355045091723102537219\ 304624642552153272462800859913580962270398268994958693773157315415972424138532450593474297\ 418191323092654074966539464958243809834150220672921485693045872877281114162897698704133330\ 831439777410191895532490768069921798430968041140846064004645199581015374017881730618162654\ 337232410799600437824171749707401534418875396541896098866572038561243608992777909240397878\ 171504738601100588421873402273921536826695423595441600086787825831152649052358558542052186\ 359736857152643848142927709876092630083051262335951582833703709468398100939754382346670952\ 728479240339693246072857278453337234922894626532432498566895067387994828809012451900771967\ 929807906173886959597414937301874303735927944353495845944248642551569139059139490084413922\ 038867501149294839437895340354587761521599059867928165114885535450469040863937831790434113\ 891571487699431910344000066502887626763480292978265626206101648527794153611651308224645815\ 437532707516560822862279766251131209095392155400471211826024946492626429777078052740936686\ 143384036738640712120817590118257001124534705589089322265600081404074610345780399588536190\ 869104818935840868085229779779183652182738201335875256631463517823837855932974794837830339\ 342475525351667928848078137689136740583108397985892558965300801251271630466216973243329560\ 560873880030462594772256036891075873274142251396705697861353445670707261173380635068245418\ 764678385029923687826667277276002742827656308082015874709975210577695670375677395019971437\ 767429679512373796284858867317703390739735811227781001204805667076746151961561238247481106\ 324090943979592949473786625556693486806409759703222354855487175234173595609013791563198829\ 246430201102482566283709217798329856852587229962424336703434158162040407048115707981852000\ 736218886197296364224610241430865089451584680304321805557471594484140406081533243481573416\ 505539591898550648660269274606706897400224718674793508215513066574699272090434774725276518\ 612805007227918360538100227851487806348659168051666177179667973298639299297041110405233188\ 728354312033451566803659570255087274782483278524663442427151124409578680430621187799316305\ 258967690909515617145316564872066240420937829565997377131955003565049205929487107475409302\ 173873197226292691747913536403412280810194374533150529705609864623599865296905567914929355\ 672640135735482841398026069528678332107857864758747902478544208530721958551773365985044682\ 670049943044778960796146062344773805612325206044593565361008616274356577258534515611509096\ 491554651266248202381631392232438242622432487907467975948232459223727172270046484519876265\ 760357082942948004239534488912218858006386732873425059893302969214925487224690642524622991\ 774187066521876050405680875379112027799066336460266848445444438094496351825591067104667300\ 067348297376903901535808070507647906128206450246578862240790315673442527154943700614651212\ 727997813519836989095168309162704490146689577356291957783727061642258632377540599547413820\ 227468707321692287984833427076296136550818739055433979634968601852866593968367402789137908\ 030477361221059547656914184325932706591124501763636742313007492413798411180580483348580494\ 342899901596970512604770595528493674404597275298907188743611840243640851193307923011484282\ 127249953578182485853749777549140125166780736619372481414469889818371940052763495095296446\ 552618199478042734417356857059292022938345976291469326185529441183466271551229454192214259\ 454457394999971360862704978989094530058121963226072442316071399471153889818130007885399582\ 616657115904806983785352022650368212289793227352536033728855831452107171272218634151144250\ 592764698711213433623691063664974682628857612785080812295388662402858289167402623066066658\ 237807197117273505515935793570067876585165906784456595910290121429811437400400923611205604\ 275726486457064658889999646069761867812233680792002475064436219608020428155850100326216553\ 084587653013780119665215400920097968498819851812421942057239668756584918547099429807575124\ 879110178604113366142510668853685363840384625330223589372756786836732906723675749094145667\ 354868460536624958542897003984223562600793057725817957501691695844277758801345516190258776\ 321871218122120354567722234105309027867514788494845554700563753372026682475505518606562805\ 227608407096372256700097942576826318375372767684865847703172135598358136879549019960511922\ 739537092359217949803883195155134246729430589804463997179540882903407830157960152357752394\ 520052207791626402290943808145465348589285438502692452118725044535820130676248322580992773\ 306906950712029792922547087179728190571996231100878245301286623421981976515101741296368609\ 995615288538051511116488140600185545850388185630968241878876361183947303775102103024819146\ 434057376856403087917049980372431992597418460267961842920061708061457023919866131359495873\ 982068985058961850002802456315511324108245765348601725521570956954993317912757677750107542\ 632797358154628077236502661384365510116147897254646154352383093554074508067908944891720856\ 782753590969921454492337865410528321312402935545381495919218896366034772639467414570325525\ 700100387955672004577071041507201214992101220719082364136031084759712380386634672249040889\ 673891958922403473529996309602340475645055532817129425532859540237298364502035693368294352\ 469253875997590709617655392326283383109466625253852078780296929115199074358457284678935866\ 074731960493923668806092460946062120420512143904010667487175916829828361455633303437240877\ 538767388918857547704911252115207348405112799550434986657138252953661748953714112220378394\ 185378168236952420361371266115618290125341936767369979157659825779689012206624954844238730\ 171497840776288064030097498296675770050706888334414650392641977974851683546461376676350822\ 480083813955139265080838884638397074822290069099535715106444975654788982979958318544094151\ 236633415442775357047751485530685674769560330106814828676903170739440946563364283858841174\ 380530414371619584790461225394422744975203376436954700070899502677962042297997812764390339\ 534746697727807128711438901785696391109613579380515550184306368769213417969599990226483862\ 830734504533290358111543979032940401017123961634731523392406638766522755005302855354053052\ 543690977057742100615434434981309966684477740957141339742701351754065569019131785926082990\ 595407975500691759352253997847639892309060834130584871358863668719710188924936138965304086\ 257592604098595016867009069472318704343238080314941857932574172567393237018652170725206729\ 541013597927421102030212029889930383622051541862044371683551744386102210189562340902902670\ 851403365331774091315078703642734145665875356488824054643007535064045894232417638527262093\ 621434608452125289940103869008182540385864967733428664593767373415004665397718330494357503\ 358657644144923066634103319837082397439851819295958844879732009861023105711438130254936624\ 219168059244658713987316695641782342745016869649284852425484439414494521504549515658202946\ 660606150707301792795684860688269102035957246905755071639666407696197017241718756302980742\ 797662745681388288406679607672744172987906565631364968390725252816250605636141650235317716\ 206131531585914777372500624464833881899936109706048600463049078614615552179915963564265832\ 778804553591161118896430978554485908357188050235088267758508893123602591729583277661042332\ 635683286617532661905819985439666018294411880762459033489795742069808823037170560158021415\ 700312900708883400313262644289025110539482413213624269486548327340899363128285272708193609\ 408755812454621081321957030212564511908499972261762508127776108975194014528158620280125857\ 744313740015884959627954067357952282541458269985729743860952500732526181746501688392723469\ 597670936488444065489862337262864488462343422794322547673457745053307654825678098143199006\ 255831262792281337999920490970094993080925809991952389862157887084254413743414341313132296\ 484820423351321744561772618454574732989975835470587096962707851165374809361825037019833188\ 050194178421487062554323131075188593533573126432571969531229562395773190447934795284984889\ 806742457890984003315576072857561955822524587134188613149679555183469087523669673703708037\ 535912352962287109402691836308005155351360469630171921562203517177511548669621735240455965\ 203353986928952759066311928438300559379370821653321668239212939110025392884549180618162852\ 543492973968827257988618983526038126908436699645985476762179317068113659030301382570026621\ 669486796805414783888265147080310955700135462859134873144220732180294009423929989236659396\ 927192489167660809791065467705274008901861667305354345402094574982745580891197856867679078\ 594733470487495987851277495136317834644641506231061570412640258486840630338189354980272703\ 168504453859338409794029050656506969435241632432352773073017338370508779664466661866333982\ 623671693617934911099705310785203355160833014566137387664146766566864587475958997155787929\ 440947284166822046894292234103645105532608284647346594832962642126496579717367494151130637\ 582913161459633215497531566577955836195074131052261528465877832730547980713299898442549666\ 972371441551109236061541022139294176880415451818616765261104826693333535165907008465176036\ 941153483707182133503414686105098371066169847298628080702276371587942249006632827551618791\ 383192974090202043789610513394516038410018600235716724447008135673146451727955775721438167\ 713521101698220986211876120231653910295083840241141316657425620673346607383106822181401735\ 418574063058576593356076520208439649686520385185219368056382976954217650958474511381866348\ 827269168155496150259791385969885111550122245578897459052231468904226719806961538985047368\ 075235072488327200464485639836473201467875672884622543036532975634708971737184655527306674\ 815211767201044458160348567496234056166767683725789118335072159318725821091630832886531309\ 392417807460025519574355234588632439639360825648315738107751210657534288018933893460389731\ 201584717399474417625301495550132890984145788081137243505907505209204491077396433536479250\ 424195338097477370854525001522133680607474837404689989967658731790447207744243297211921188\ 929720978948994030551763149928505360195381415128605720147708107309331186477619789156871594\ 443775907395412388877763477006452884290554870789684001520065237540798976715129077824117973\ 859495880847934143632436292418000673569289900938033108962873954232616237234897188485223817\ 554520973806277951920354453301171842089815045487875228935459775577964711779001345159437534\ 136660863969755953642200086432690172000619477251125237796130387245949842518329595933432723\ 136925879643809538615337999071640997639748803494723378079191556190530189683042811264325795\ 607755978487900368255008422167896527175743709802282170960146987700082830152248334177218369\ 782286880234838991778948484337604556384407080016777361390796726748221479715415323431570846\ 666931178702300245218099045179486184551514521293309564119138355418121394083929210553335367\ 061968422818847873138165840782161683098130962720978127889553631543502680362494562548949274\ 297232357230864529887310357323634739854476068359068381784080575579919124497582871040813018\ 942816014696763335269596050430134126014281309543521359742144644905182042946567505679933414\ 970602788775964550375153846056216904022865101460878252401787632363329611250293762483030088\ 841266362017347564556720380349801454680387971282823493914843284788472500185392980659476706\ 615221645058247809683806103186955080545861514253347002588629304095402771197399895726279837\ 649987308386968500952987840611020991635704250317226809159014849108364729313708151311128777\ 985826165341199345498535951972825301374579563732245470841107102560053551613930148807539436\ 337126081462674959382407271706711791166671885655916764152776561922629055221820947290541709\ 019656588576019041360506814506024053399856712840748696984760722881347675975903867577381744\ 420206492220535294630210911021151651148049194271995534166739644702156308576571535486923807\ 731670314609344358376616514768407827961520050055275739997560135747507086770906893416097012\ 659102644451015566436051742174577141140240382298681362140625605691690764001272656874290065\ 192902859585745285875236530542758538393506735689165939474826737872793075196188302285595837\ 967717275831563935420733275777939063474935945834531150476951539758476250475446339446484932\ 733983357829045097007313972001430902530254143674366989216933143898022211841740335776052163\ 532986656250962207885457533170744246681314939649919089758961987473969680381862495941318531\ 458311214657228627416084082809006769853310016540724119500341765981267030106796332323755045\ 672517347785598807445516764246176746018558581339203397653985322951173935029961809237546872\ 898000802042200746672487077004655180089748650068589489648494273926239442252041115890231088\ 452313240846186155449461039209171903553103472187251278975974085921714857610004388322669195\ 893134175204953586047152433641142479742935408799718880155936157000759014144693710144322866\ 145714147134983290834409251043677617112562909314152502889554368595445577717827332149652698\ 991754090947246228732633934711796212696885146883464318471953506638109743291284584509302220\ 903889571200429371989474891274388700676483109132082651608375434850468180314642790340943731\ 930592105000771802054348891355375156168983825599982690537042600921339839153775782073418990\ 445791932120999540704057634782240235560126403340604261652174818434219893640872605488351944\ 334857843015208956077854557009449052732271773538179863514436986649888069004640672310776323\ 307022273914001793993636412502702826119662592906703867901025126045854516339829037040040948\ 485870316077845700127735787541716890145628190434400821784543150549754549877301238910644671\ 599997404309617472520178067129808264512104949120517778815842336201657197026983397583793359\ 386394851165283463798267664605637865647665198968503889850724891300784147439005263286600063\ 569550971950398147611441778577956189636701120190307348791016608304888239216140300813322479\ 280739154285655970576517870070095065360973959465197467313761111986963218491149064041999346\ 782356152502272114588343025730112674396503294602858387897237659097746063219939503175459506\ 049295731661203721057937952829473932322160396704497741446256919743107736557938301901582346\ 921959698651357675373143131820666751009248893800818700179861662523968338968062937366072135\ 269447002921682741525152616553305824888611469638786874190746704743458392123716189515697214\ 892938048447711660557609469250886537746601466470413512768977722654786637409832248571564623\ 645738458774874131959123701640859962661201904518126242862678059902058315228786506877674420\ 462945951074680800576877978914403678055067234714888622341444535625353767675153344918686605\ 438402722946508734768414553556129590811353584350116404906212162312508747700846973538649032\ 332723615248521921791692695858591445414680799564761106943266983479160274867620685576940433\ 285390454412319688349595905540108174963901601939092022065116699698538761768300541804872795\ 606065450212238103088226538281196771493958098950662896408903794175225043864473740041246984\ 469092679224209874255663725238245498596755506460393856841638298927364384951389158513305431\ 472728450486876049277782394185010904724709023830056305201942004657299903460275793061180832\ 060638596444245345327170108859335780364196783473216720603049611145960582534818033933802753\ 327030918895352947335009183365663627153300188297543049651154040728752684940683677375519221\ 950541203265843521674373868548134861807520947143386890032142743690454182390983092462580360\ 845054248726735009660851180766407710001891025029276146894264784314926161257967136282582856\ 967951571782449153655271838110864601809500216686960109494907882195021478774107061870477114\ 561591636446855026160805310279458307839132134497087942395250253289733813336562918262822829\ 150934265873915892189241722015213431982545940990170999076390784934241153172704939887387845\ 510961836046829585987242656291275148468601087435204515600915964680033791967896369704837799\ 467377066391106744070097951544579562730838666999883589513633404142392975598040467634078295\ 989257960442986247496972578347817037322069022575545431978104529588573250859147279668159148\ 580989481090511479320871790350081669454294455090386610904053325256882104161809213016894063\ 386090309951569733416568731445360702214564526532031836797253024334335625895441860418790215\ 439762452592875984585436552088344391670338458703954232966288987197087890778661038239548257\ 707995915794319447738714429421202215844948565849611204556857647765963841006220855481311965\ 438507705023389841153382893893563249950682033122851345482301957437272608145065074238162807\ 825489428957871130096817728685095449832630366260799239435109753818794913882634279224417165\ 173314704292383580424322814015831342947837386782712333580623085788424996146357917709430288\ 755208908557167665276774178865167018309581545126595481384836080612296674693029413779653791\ 977188488652317962858805641182515499286756134377862576885714945582716841870840891072857724\ 657479917650913031986646000198906562167310279657866367834496226977305875929363015901455607\ 018664841083892226118830873389240214468674469934220184082968895504521788785081292235412269\ 807049027771821000996334820951054522447253525517757045129317227376221258471641633781964982\ 633972844214227084877428547568678558529747965443872697946190811653229801380232576745745892\ 900816355973380666297974788188350619191125348746822912293915023792933723544034178028847993\ 677481838029344065480887928113797457724584306779759537451150386212227914367941808435187726\ 486266579592443119146971135255851111155023824502854113532587178917705868798548415893029999\ 069383396138308887956582523618663980039309563820451073356224246818342981909755913248968156\ 923384433381746084873743113248658448006965505186184344226639843912495676601092614016678425\ 048936573940151995631468580800598632566713078460103567671490106211105873620014819057126083\ 731528663583240408278066921194451448966139949111178071015800208615554834344697662500803292\ 887559119532861299626579816960925266889270722242105903064606865507158410546748009644195953\ 153025874694830978322782908542287018896666658845641463616128478687320061396294956874290763\ 999948713569493736626932227645599694374927694042719414904075096883172239493347306178042173\ 449804171228119054151705527654011067738745019820138283577449194785408209892511327878678234\ 138742494758202547469030971727906654147707504194778424131706196184009675292993119396900503\ 908880452103152345003887274853548693279564462594734900460445244057785248054300857899291044\ 238879303423099436286150816720254271472121331134827064545840371228876985626216480189054975\ 348367037675618635782372362518243777911951767661731099335452790488495484825598611574761861\ 201180486292119724300461652901986943890280475006727557901271311274501367611177383744563720\ 594931279840861195414380218670014812371057349874858621136466099987346653180030545712797337\ 243121679484214449676179263150393315434727960325634450736049379005837128371272232261509785\ 423206967451509293722664754397980026666896608847838340726457124437605632525566387538010836\ 250235226139265908555131492354746500692891747139340123920506152721468018877432734545095112\ 690656796191376082099154919214966234331238515694129060220146174370434904550720093161867020\ 513792063868398149674157341702187098242564936431752273393954293454470887025079782294537239\ 742919561105547819597663645352335797454994753769178044644901530465759855458350042910112407\ 485992487318467819852289240004115486599690229131202092653042184132865284986822781573833803\ 465379827488149561058457507820283541529692056365359279044947337883791567406274630876318864\ 701145322055878852713252013961101046639843260144114242148342027470462947184154343415012153\ 383469080607963823515752375573863647390468894908174370772553512035541265253463916261553969\ 470817126246389830347311370781465945890705157280444558669158551927888881314474118126863440\ 025488954391219091614046621902517641152602608554961188815550930705175493536824451387567630\ 751385214121621111742123876705053496665306422089719898833139806000833807721655000102869640\ 947887059199383681521984929616333266784905628579137350345908995801205930898254449411187030\ 503450942137962397947415439815149756290492793141838781480477886581940021251575489373065258\ 253741331236222403780755319342340155162314508458410550655177413213236866481228467004590711\ 257186873340957490948126491119820173688092429959923820433249527611859484523531538475923475\ 618682286622841446704552291543156945936211784924578799145619870370781086492502217423845951\ 118730313097544155065027606195874888633366946973802087264497571002570046297853561246828467\ 702348760618244608449415200079548254044254565866809706828042918816337765727292693012132390\ 764891434686870832629385118039461619134792918068314048000965698233840527031228154224422762\ 916988747548656722384983251504153984245435807339003367264133628007200406697122467010597126\ 131420264483912620081105996146416058301723891013050303013830533653292051555434591055753815\ 742824451549438828172733223172616585115010010650027588353753668887897029231520788998675477\ 785873469759651214362490376006237938429232386837811517222492865897482868197697995363912286\ 013238370008420465663560035663992897816766716919765253146488008005146428440000839529556280\ 585534915532758354738705590469782415706081341732737113487012230528422770514257841282218367\ 008294999345743562986496617235551245802945440140043871829374497437224100013086451589019151\ 063151868141693817273282942725188087982725571219558573927651454874287359077609647012649966\ 338189375136500817556884841066254143474500916744470186127691891551019688920043509332794962\ 050489006189079240192083267670685099788072156844817300922734794308346275263612529261401334\ 816113147918008935552497575090652970050254963807888835275132584065015446690388176004412533\ 161675589249287342765575311728930377146896882630963416676067527942830072740744000637552537\ 126427245019108987392745112050337871154517267730032980466602196616471186328191504736968537\ 862974428870322861430216884796281021252168211000694667192636076520314906620891401776407408\ 565633672160556653696585415224394713215987736512582979057105773955128048011408985380362314\ 929910028984967237853773672050750293814827213798180716929041381056382986072948495749606020\ 262831205207050075631437416697163554276181157578905742973473434778002383772862474440108082\ 357807452430061090658802274555215860288765162422410717302413481495317603440270497420058115\ 209495467773045643667949592083173471098685965881583879260367950825828336166349423133658919\ 007875896767224883758166502247154582960667999878761472963010897365479731406053539631871631\ 171689993477811313876189828563179079651838385412077888122351084719782507931944464599113083\ 041290951278000684977590935076859182984630149744422636564393095734650008444057709682660549\ 811583718760146461580729305323882934028493214107279400867335112940680809229968293803965245\ 940599316455385549939525148456972953167145711088501489237824975980706315875503774607612372\ 973341291666142125833569110503676679730805631358445294501219579714600978461424432659831337\ 817456423902196841649700017247570501268786055529264512930259570490710230269181637670917708\ 760160114219187412301604113674734889240250564149528135842057490439899013459072693967135525\ 059578069840711704303373361220603497103790275583153943967572363514763363256601873639794356\ 056316598362130578380149837930740641363150587031110123757748789705090310553171229691807038\ 191895576888824454796782062571576099935070937635437895359314320355334587657467558158239306\ 218306454826677265778254993143628351937778137336232899745868382179004770783757434677609698\ 250941304450650925900803846720376141367261198446827265567723096954360210082294169941365520\ 290588851431997825061558502567117762882688784301198455720068507108688371741906762068948399\ 987421234140620441301163237796218097099283301536035863717280348822036918183697898734797865\ 802973665281309338744434075350256369106889255846305314370941947427758356627643364451395592\ 553201383008327886076165294170635129802633180119079853140897242615367352523817107467474096\ 041491467180092351257673243130989903384860583320385376253002691167321867699528538998989309\ 366569319089222109440335088750034935899612408907567854771713273356411286450300257262071790\ 682857434133697992058138059620945811978859713675323917147847558365563862310790585977606110\ 559040634038493599512892351148019115930544649747884674285809260114577112279807750428326866\ 613882570431895802778554330492966801114151599312777576880282963179131915336545355792386156\ 745520747345340107710302070040341635037514080191145078350640341080910502687267873130733392\ 110840983746192727490694293466209482048244741517598376724950749225275210984435329500243620\ 850019579897751734051581797251343308138244388898261062657225576513391367654197837521621226\ 047770400492356319766594432848874569325567207346204888664556822244173429246737899620767841\ 072535939312015726061008630046947899975545395534737213271286228839371027046737470053316474\ 941479562184771478667793359029217450481529358238528872033283869460662584841727323746155880\ 281344277545816887328850117087817216856627850574955104625193387467285016748913363754737376\ 087273211959492659223654184743160561897457151333382477764264829457422427381707292358112956\ 949111030564150698483060673018173666869930032310177215766914962382985015763825079928931084\ 942114495122222333646653441726533898572442256139051126026587826668959584945021221319019381\ 192686271554125934139241275625505838895131215601590615967165486683919822877241319414763397\ 580084760506671571436452894380249640419996862552542811724636031828153547154700579933798001\ 767317156549895883989454948435218148508911222245262829823374732915181105073639589778030437\ 954328106324957289510132419518730619594931294601410424484045930397160866745272654142434653\ 947351430093574928591994258529530402066577690545441088029549816116857912203189055610562420\ 921072541645885500015028306862209881437171928900407659747135873026736843142574029034986980\ 377613953355699312036455529882833766361318779971730107748013697661054432289928242778107037\ 724663906215818756597766628320363525742768520155007589067459885837624838147884439099789073\ 416203695804869860829133132063298968810134675982899869521266407417552972281203795268398666\ 030336496346966102248965743578028187686793359357244236988441164377622870030431410897300182\ 060132983855115316779020083820856494077968448131558794965500167784084485415915203732350542\ 785882013213766386794128283881950178184031058285972862247728723858779957859858482506411000\ 695476619204407121455535854642870222786380746292003790979786095079821312191749209531657965\ 663043138727837754640236577595368971277718242480085384802788530645488262313190736686523687\ 635710802308106882747657265089551994245174029170756482410187724102383781219006218384928179\ 989677671778617019754680020928059381932252831330591029852546046357584592056422098859579772\ 087813049907086783787325929356142130475210918225256462255595148538819435809550137228406489\ 313202311518014025172131749019722009307109977168320320734665858084157126522602492769147386\ 896736955639606722133819186464189942323366548884901569117947147469415998827024512255105208\ 272980225160430844984642521418689192580858454960376890607302022639103003964848764208289595\ 927908986387445793261194650433491820864185038704795653863580714441434900916796557121086402\ 672301891247218522501781720362206736884735194807305816937982590346386040844947224815588373\ 693913557223402395689125506696066429690678430233369653262465954787377997019273018892698527\ 221450857462869035536345154311394169574404124430165515130694434767289236393466432557858604\ 461909004850615881362437396126993740485285202446229981029726856965768549665898692255265060\ 666673892115905260439629358901354804868012932961752058452846541846185991575754653014334150\ 783602490021040465544724874851810694134187325973911364868107541863115043854763904404535190\ 482343854724888337125918550973114215562659756230513315942499770080785760147421343435137261\ 152332567970930718117569683615193124252810502480358778211790272397047364835954025061237982\ 322980000390004892911221382907165132566954214712078972093883437130632723722060976986592218\ 153696946257355900556425741819115012175522737942889603561029205694424153523158326763697440\ 496545989248328410973285210959250861833510325187130692700661641518908100186663344207799022\ 275057487183678916113081044699424710792516744105587621763651386727016994210907707998538036\ 566405098741010099554322604347439707144300846521522114835318912971640070386674462716421998\ 110168388489319474796122650507909489691933049442130066221172433180336899889759777740789589\ 014154404275765663982838481439179267781397735371951145340274944889370842298063683059568542\ 522858955401764030895126350059418648465648301451748419196552658344211471606871368370186343\ 056657857571340160402591538609294389324449072167351115549280385898765985293011194226777927\ 712059112507052148169049384575936929851380507642626226883196555231831346948186574749503247\ 629752889556032791462254544515204976968472071699151555818633560323714543102460585009530957\ 700944325343307058668030990509041465415676800179983359030484918452195136143209927441068023\ 301893968443360762539680447833687804535382281582734021425406155956415784304393218053137807\ 238186712411619126526001323310920256313449908844740830000169468078749879654216348414217921\ 502871339946285554439243646026284039450655516067707576489486479478024417605883652594072069\ 123720432511122817157460073399718211947599961450321448554620421756564195101592370249640116\ 543498336550752411062509269917535101758241802790255584301029937744508820451669596977320838\ 955908367099339885597539060338299018311943601685281525686569633224920799327689467635814976\ 567779680299644318548917054480583308145690011730106248666618304007688488132571082526965390\ 027116844562528986899673622774111272100550823554637621659724217525476103280204654121673927\ 058855504853241959246483922713969223430301061442589295764843773424701666062797069575236407\ 850225829267581583748380159135779851897164469129540250554327483476557147572480504774036353\ 110978025396961373407252768718289741650613192788266963871727686738157571644448435481041694\ 064763237086857522489977013757196753313007848973327986621156252963472510074355337672885273\ 116955499093013657418571036878203403245477264743724954618000342750479677719512125805238212\ 454146694061242588437532646234516227247775386212994038270444673878133047218221710322375985\ 318198439158288846740084256552484419744016152716649205676254389283460420891651731799413347\ 321426880953568323868036730000986539269549418372583362070250771285086397498285407488539089\ 391485963741812091743626604154394551405547437853948986896413887585358958480621482904849965\ 071038148694631274855885489266586900004460701280726469517072603679834578535676727361931293\ 241266613227363537475168172182967867082341219616396144478513856945482807124944346019960298\ 211861684893955551954921825422643005651417118436811954934793521878155645150659385435287953\ 458866626802006447358340875520150280052912228325726438908731105575466635024059307769423906\ 960244826832722464251787269079802754003468840700353790533063099550067375564275545193849586\ 314955003412676109749256121196546781491689679790890835826890419087042137409018005932554625\ 589601299761152269899718855730716139062528891702227346091555177275360924510841643683831545\ 619710348813284635258582101049383720595715014172350963450733283357227961018433727010510621\ 083027328788099424391317625536733463614958700632999130285253353590694927700161326585995711\ 489215265844904011873482969009403210536831305625641665005644727478073955878058698979715868\ 474065123657604152895408623274637714346252156859884865183897151083755144148603524212996079\ 588620636780864643423254743783167473339562377105749685696010482868861178093898923724843708\ 390642997502433278466677548445624101856306714647645504973651163100310438100178169285587409\ 040734828968604645232751716819081715733043996298570718890483691756232289275061916253482422\ 850168055624662004744494498365297729349283534368605109094036398662787080449847080153257879\ 975849364437672755865354895504785501007177719339242891467630909950216366999763877857638440\ 346693141176732029409145717127157878963266757389877432162295146501849807769131755589294613\ 239447671412421027943073074185436580015411378342844662171533423120599992725780574341923043\ 216989470014307425138657704744941417902212582029539716065263612175762369872854811471910636\ 617842861369499528143950214516109010501663678380527735689048143907872594240827756904331543\ 965739680556146103037459727673595562443699618059410070687676216098487099935603146150960534\ 748550186564152325959412287528018180915111846756115779924898181238993562258108292874310550\ 904304290147801362196665652182941342550783299992150547033539534817302638735582940944594735\ 435516961950498530027044255372551026811964025143105831695701297093601788566970998068650623\ 931197394652298079910566219590432173125470221868269867248412552237857840341360084437750528\ 596370514590581841411265673435586081535363511465451158206214348437620831831374120331033747\ 295566918828444232780855049486154229181875855736509897941986189553822628451125399339885656\ 686689182652826095605189088861406848597217499569605003549625340685651515105493754381533370\ 604607532628301247519972764732857969437498866894204308705044180943076132486406357187928872\ 834481913393738308036645903596988029263299881319615644438131408965927988576732990771021412\ 651520163073028967445129675179829220230209718631652391329940526208471494031617216114087112\ 031747783568880308302983711956954959066280892324579787698413891521518450740862515005213829\ 968173782580769540636662921362629103436498707306551642471944155974785105063525914510291474\ 033380556487822812711209549683732316065473460401895195332922915825580386623156558207402442\ 488745268948595326219719773532223996268043376136366344828609870582675983230260402039856721\ 802341639254829366408576059303752964869938348631295753744620796408864317393125453472362756\ 943340223021607029261964464916590948100293751120832563649683420824674400139998206956081636\ 270315677656882379530030922517431997013457679785973217302676308884097153793680356170293966\ 452574921656764362009778245786782684775807623342688263917887907999518694262574475578905754\ 432310194057960384805652852283458476610121299200339934392235943767677597445213085033652546\ 934001804044551061679262225156451597402822875804716523643879325648853484216548010456900299\ 379222966791052790127090548094314767088554380350268179446777334992183183217622269111888518\ 386988349147825614344666008349327513105611150606460358875223766479250083233424898858597004\ 352913546872956034472577380620014481388756556445392940978280324291152294437428279058881026\ 626783415737654349200280732682182417200759757973202832593874001364666779959717651008479495\ 640513628801321283722029629845380561010712779489624347389433032489033793314430987641219188\ 959700246125024988739795402504396137497467202945784392175414894611657116744595994473412473\ 966849829360385574445011758496563668594411215287055760380904433731006608047285199840927651\ 624515277362125688625661006510910682315930915711390632976468888197883279759305863656739556\ 859582567954364623966603122009165175453680383363406894523713603977429199048405319515067532\ 928137274193419292252518957936672201616404632818544350808534373900606543720518113267927518\ 484881089166476716065619373182169584818418214604113726929750286353032358110518240532229057\ 723852967430015435312420309240789162640382556722350824076007367378311586014031067481966443\ 201788899198931239216481326850961022743233479325566187380684276066268777230340193540774975\ 529949525874726746567691386975792595409800376937058837220818246939352374947644353652598261\ 664922456067446957322541896847680681903919126876493731567770572400019016843745093781891821\ 518991049883641884321365634000119488837520691560005215144772167599052898831129169749508457\ 834121746421986118289912677438908097607170990927887983676650931644482914342648360095743055\ 654942617509664002176780816218919423716337353248394272720432359926408175689475808104128504\ 365667906410409809335977607787446625735608637872314226181742559384796123969845263290520756\ 487223219360592374069369392538571372184327804939301336171256498842445425134600816221171046\ 900971728383246913124300054976618318494522425703761560191830956171171237585393192994115248\ 261398403855979432813413027326497172144573066741138529444036347260686661416638804629647272\ 027903823679138549945962471149273558796624193315660183545076082186608651658193076092470586\ 772548546314622763771014864414733683434498078433551433750102983751672123171081373712317652\ 630587775644474478186059461705360160396528726036490871386386590404352560626215664083250738\ 231396359324811440679784768513549897029926150313751782470984473136058270271347183358413770\ 658743292264626621154061590961214823642447913907821205677724638317421412150326273591559714\ 476767249669210282001140961668542174466171489663919207051813821322176550228294046866514412\ 162215383449640031062421323715537696957782260704546353711502917745688671781439546529339499\ 514040614807937402624856688398016482123875748007689489176780301792352431415565863784175889\ 624556689692713587522401064717758465648879098412735773983218632698463551250037063782036699\ 026750116059257217336905496257464187086255629876528958272436416317979237961410543473707393\ 717848826982419190206393480458324661135940529477797873500996306259120811164436664774415955\ 500428981366175496765586955154568280038586855769877847922115469206037196631386024256008043\ 088666261803312556567132488711745735148635966793712388734013211460733027764561937401470960\ 793062313867869132558828702916408813708150499087085461537870229973707774808364451111316064\ 720517856977544336959756296977283745438875731202600976807373684874818284753584091438414637\ 056475076866097396577549177475690640939068236325451108414341238451632265983982197897715306\ 869189906076521508049754774755403419854611390990883948089120667175983714436920561850097390\ 079803826766977959953257171247965304128393240120758630692461550120949095614124111415088827\ 575820756884401281461807574121663873804575100796231027936031038108092214359282804162208969\ 338830648817861027827096460363446547506381715743427108332808134847975479161647582315634558\ 643323094847465725594424492373101625025544234496998990668624819381743430403200798307560372\ 299922621375882466515669675932685040724759342867631396876596473690221261448789604432735230\ 991683156624152893843172532996612565029189563476854255808394804586720886490348741906063781\ 979852872074375019500043564308847519598161344500622894473807947887546635918870760191286253\ 283201971817244622007084877146024121460320892016053881366722607056582001732200003548619258\ 670807548317141459552673991194861925767545086685647251818605449696962167362537710321084267\ 757054495460978643989403480404827650310457782450342010124498686185926965508843109298541175\ 892750014166533048429183802066879082209200090814516626970880832921084482701014325340582356\ 782639118463453049926700171258436674041480553440067880782203501550762374930799368535443199\ 339252278001692461952634269307901712802214947320390790726753982934873344392437834642748560\ 531366913380840494420555425674008120006550628268007133015938430360310634746238567565258880\ 255004636681628834611150470464589340978041611938443145217886582652546422575500618609347871\ 300965537083827434112534563400016643846330911151089362523882762967648978465403469684407827\ 000622816094330801939305383228303076396528923302649278906505522511173595420145790939538827\ 744420921077165048322075159674709794026348789888273779067232194877883145934283237011004496\ 017289656949794154621746700838045150706622824687225276223122208697750457123648193896115149\ 700245077955869044461386316145745801376428448892624279018314135959920660492443240976094643\ 803458203242585807054687013284079006587060758394935225792217550117373035220422174352338354\ 331478205975115003913794060310909059708563798104243854893587319648493209880947789936133526\ 740308914790744053282526299180998300427863041733977903954469904927654582543742949101353454\ 965736753970051230593000823734778520651194757772880400998360513078781580945466949027451046\ 561524435118854719657513334973642187742528540018549096029609697346015218293122624683248891\ 210524377103505695200113290000101822727887018985840100718264735653600179513579220193137247\ 749993471624271965771177109609621360389338155773605428919718928671186957911065946415127314\ 596574656865866662069430160816352712241399142679613879007516427100149493443986879524396966\ 129726405588417620114932462690105719259933609772285556121782377856633724419168366758950867\ 065818622603895190254580846738267560671213286658981053539859536306995464670571657227020625\ 591074640141926270564229859994910780920013126290611892145391756816483697162471151755877080\ 205744593788244345736856432138338752482971392321479716992129315328178254500414505174091368\ 701546368496010009293857793876532239352439814678478262669371074094337665696816446910185841\ 846359588560081032639075937635538304404279749287951297065728173901758669459463142465022077\ 742912121862896058272543384948036298863870195040207028236475748338689967184921490983061944\ 937346991832180784017579917453080773247152339670531359008677764414079017808682467358949716\ 553987371803673692175629800267730106600621732943341861616445978899056667446764706321699532\ 156935222427591091527570028272915837483732506852818186271359017831687657240462719980524982\ 308695847809460911855718903035892586241215546690509578420183217503403721205512620121648585\ 801905803150289892508764604092088148849036441415912836938581323187463954176830759688096200\ 062867341782020837097174867586348918062197626124620604993037715470960562840814364267979962\ 961267987273507647133788838309299283385202095192673228272113044178829763176828783671412847\ 357226527402801615986011204860342921051852935420203296075641557947482486969891378362254189\ 216621647759527755735347850774145173158055599602128626533747716556770638534633421320695292\ 922577787872517751509445701823461793036206333103708917141187300637796583574917608476198442\ 056363570709861208208863809881970166324782687861781838857265596076339162680928819159204711\ 003370614079361967009368027231235566297344330900632788574785800853710841613734223778191249\ 861919785511292555640942113192765287142639165393855949294444827086021835104539447596643259\ 946765132267404836565550506629393524414875075909406197731452357051223422481092027151391230\ 263207204885022797038548653679509394632537321169924769662325595796261248544041810715577020\ 278563552534048891241704929360387191418788227655072046667812088270139982893938120709781184\ 329537349828691077516263229194825069558354755071131820339605927724387195475485886461143491\ 301300301975846447741037117059673666901551890408934717859159229223441343527678600827660434\ 292998344403357654957763102423231090255849790120481174635685265788365366494872018984811960\ 697629449298377014461145230914793562020452796370585289538155624803245639856663539690424366\ 761629768022956024340250649446520055513028919313980155291870775597055408048782075214312150\ 456318984842089020928888806068306163698321477773566887893691411886206395570142140297020172\ 620173376778189101236922592242068294071758868904707733834723934524370858751729002405235842\ 760175015288146841460761004002439495208417066766709771704811573800143423573247946267852118\ 756109860614621581210916092976875104418566084022366637152160585840949952054962669672234436\ 335094773162927648774062573240731320039329141911029331457011084663113967203960455022667481\ 822966036530235193347516068005083609490928180763676495155190316762720695805910909825005366\ 264642032970659015368032421708287690574476124415268539967304461698697810807027534728564095\ 380439692261527710161362305300276993619626577054686443642538203659171353078169941533610423\ 577066966521193510519079159214249233898693507903059843399688623719189534629696620169711046\ 144648809793357536605782615021517875579927918433720803496320411194486222913896137777764812\ 517339632612850836012106908002540633075147198305161784558144088629547931336260374907822439\ 033748628440495478970387752858201576492320286564571123146561453742261994486128029084890967\ 971722701179358579595032260095492351496306006309825409705090218163266512499785814771522064\ 162940408894901222484528989206657874430820340914542866648357892827734392312065432388670935\ 541889329473491035753831063205978038936316936879427806791421807433099718331780932112462255\ 572838001477478761510475919306240204882990836554603774560038514428463132223256357257743431\ 058634214464322222435251551911166771851010050492795367235448542581829410575351932595163912\ 853064227234153698774315134040580366550489405417649317957786041413538250948021220213594164\ 321515479794143553730088113989874481090230406917861017085358009123003916187581225478198169\ 933449473774603839631887124457546336058318078907807281822215745270596087530179010741349030\ 487876438722733826005555437445931883640375618060274062583798319143061209655165205273908374\ 832205439572427921024274868673377112737260744314627067605470450813394739485980168715006867\ 833198485419169224576382299859055650967647571416196900429349145958282583437709041505538374\ 543323381254823193143292962239240311495190700190982713956487604589313186776115438446458848\ 012939274723984198842384387368328886207189654096077025916294757702823100421673729937184982\ 060563797278493576188544042413649635578556190308083138652916913017932366510185993090650168\ 274465414231738528959897016279839269797052008386424520075460254348337694526626695510378303\ 924246261392826402374492825000969869415033930791299990772383637839359377784142571747089415\ 625826670189158316675676013307128098768062488794098570578890323048955843610628878579798697\ 732549671171946737488818060353987070261408821699665356008497702762002328075649318252790081\ 627959067124044491518006887612763616113852038228258782111671257360523874778531332765523617\ 503736559500023603418048249248261312315545756331826586173396904515749020656538503878137373\ 078693780103343738014428630433179925859264216580192747190854341743656700550740285793398486\ 744663529072105668697632653530565320038484148927610867990417923018195081612293450498152959\ 392944380942953621678799198905062504666562399204442862998913446234202860596455408054273370\ 636476500993143155189288914109434357892253720942472534941810154121725633146606953576181797\ 861875709242807705605600286205802496388134182448859434990805278860387884249856342993260487\ 929691606087491660035872695423367664580559609321190619705726452070505727542931748299673948\ 369690542704676278943376687994231497094803901786352907015769313893501389377326900362084568\ 021285949162379203841873420376843885452660811964700236152910834143966063800470414032011935\ 812952917986644160095038876776864199144802296170480100987178860046099112647254895267178397\ 731946948852461106469409887181665625783417344383419264312768580686470294704434326543225195\ 224913818321979758695051574573513120031428684176930305359738154190949882626029985974905033\ 778047324825206604908864551497304191001272904899711535438277255839603961369244798745931413\ 153111861737480731757861526359691893347213106068106911606038689893548484786845426479344109\ 377382031957305273080007908525939083992429499091328224055878883291789087214426648378622748\ 896399791616641387296688850233502889297619226651403163758146847724330308856027455799946262\ 086668936288084126862019801691692671296381636358532981867796704027846294551100999364983084\ 297196473223832047429360415895383760283882496311411563554864660955659924712595986404218603\ 178110505429675898708725419056065570150778104108011060616754905197198641385054593234033069\ 492145494050737313308446640797483183552725764933245306270860366864412071155263587070154390\ 105784333067625234347514113614629399910230424178556903092260818479748720864878268993428745\ 914178555948889780942446110504009895831995790147793760995675541327461197805097965922110057\ 656501181754207700545587715985509648766580566347050518699661562986553059908032897436599247\ 387267885926490097434764797298254407030061798560251538980990354204288437932747097937635131\ 667288929953279028011040838750985400737948702870099851051763125241204197659770115982180938\ 533568030396246556194552094300951647433416755315501068824865063162416386687369697913813910\ 096132302666157910449376343280122956446639316628874852141682584699474557700368922513422979\ 359709797903662735084544262999617246961445213158450878162734585596651695494229893561270749\ 821030097229003863752472500065972867161551937625936551068485120495484210800827350902308499\ 398616364887775945769749127319506531737380871174867005573115440347947512879593426189448610\ 334434913119343463863051341952373340956441998490841060851041944258095903854040091297760624\ 254425136755499288773190649271169824821957179450398848094142218059553108734194448871320466\ 856882712834085342946639515352866445288925199415531862915694291145720492022076946328285041\ 230212811437156000829395837127682149393135594865921620957352213803298558498097493830645739\ 516536980977636910978537842544355897100471654856354303453035454924651558548802738893941666\ 603421062301133326376860054173314896089358416938198898921137016894841358039387986347982035\ 285973549398100509750500034254529509963818523668464557295156040469029834602543835237816931\ 101051280969067611132083111025359729105204199731387698943207467486643714229967949571020458\ 713019524402361377373547598176027637072326682002500206878341841829805985724473620896714921\ 479646082549785879888512584850375830512467140474386236599704907700898549556328506698101244\ 466052400589085501149550504269609037042588800309004823934579396153664668922872556825907302\ 773745385888919676734819078038255401304190753668260905175485812983509915417390071541999916\ 122518448273406678956611871416997605218456610796003894958983124869865873638002556068509717\ 632769850441564795624396377536242933264663232033246738542806359158815190916729177503671705\ 611039673119864383521120553219388607041327496597999182210175681601427612180729891524483149\ 819570806031334113718444199643769577353859609146397763125228330462979514397130066979218621\ 480850668197829354391841012561280920825100921054206536427629166650176824636198570393591710\ 211507993084952409266015567619713637985632398681787525885010107541384617309727164081169296\ 831350142141491508030823769520097159870296202565212814426273588684830666122992114557243318\ 112694974387493195121772610262320885431347566791482835683473635917737694563242689026959290\ 991615006899622947585761021590342956890527609826805014158304553772443535578953010811812116\ 445786598986433369041194171416459815056033545945788839317992778847624526161232711718517546\ 226098342389639398498958315658397892767300589599708838141435750337431327197070342323326336\ 980060959539385125205880669374712739498069324185010742387802378417014722390701295116083877\ 007734664859970611340410260131062471140329605702711112956680948924225703487197905016346567\ 064297983983407671787011608197624708181631578423606452888873412396972553448138911676724872\ 825412657368662514790182001878743664599473703281472089886904342451502112391608171442250751\ 270051658133367708825788115893880736725947701878603901313435479673619492762335929530796202\ 609505990077039045798464221283411253429176009203722951886400522285987484787637251261463394\ 564655972875310365309966710749672242705094931719620360627113856277483418201455893970478563\ 107255393579803434444504778910020493571218713096762591160050835172039208691968643585869299\ 826491606500398242013642871392859894686292250133793859614819304880457873212180427600752666\ 505759472613336286837783053611673871246668651061933290151056923144775978422551941488366321\ 597451396244313133894395026951140691582969049964759290073311045024857082374454884552476844\ 905720213319588017110745738616085959888179451446123512563731023630313102268522986058781347\ 900207769223558313621407239305298855243604188217428929271035835621659145265820534451440216\ 246350391220472116125995522321179080657497395559863476638647675143773946039690649599502231\ 316587747766438341509768993246406830674938944257830432954651578514908644258233117435926324\ 965744759724767415841936899974631422805418652837275423092498261030938827807801566116126843\ 414751028704173099098731557777980534786449385679377025059351570038471778087697587394753207\ 490707196050847628279435715215543093355362212422733727268552873478572782222459666746858887\ 219718858714830992725920227231631051337402315651657994239894144875348997635934219254518444\ 877280876049302281691568150611615585011590279813144703498786267903603501090830961052551676\ 765619165581831946995223326094797763850490265185620082329946483182308918789074315161176122\ 717898640880621634008684711901528789121051037024353320267875342325136162090209101545564619\ 877955024829061609537471880515774880400535422554613102648745859795772486107895087313862036\ 333762871422159828399976976828203901850118903725144157838046231102730118115332000254220419\ 939809506929796630606114559134493027242983442524274928002260816451104960043644325716232284\ 872105386680611853534466911547978130603797902226432955385675539046260280595788748645647343\ 568375457479936762840877179899351131549072570218954593235205660542535845384234275010197423\ 934644409311344952305309402569479405860310216529646731038530976854127986726957851340769968\ 414590451003545999074150101127235638467742366808555088451406132852128711723603812966882096\ 519016348229099038930500785173201554039789126780220815707227350156885318617573818235479330\ 685181680118536058209396483813491114112437438816990027057678138939766143538664604402558879\ 364276253391864208563021509369104410917088102914803478754746602358348279096269396591614822\ 563114049760501821004675443715892655242836931327471727178745945966750249284275189114487848\ 207155277111337611331303901103975161438932045969556043873511101912493859583498122853163209\ 911776568367949481209477674232487235474889248194915672281379128603166238565434307038558345\ 149821376726173246824176590671720479527619340624753172902130864161542931476638891719377408\ 012258322186933794318691333822337609170176765130077348747009842116832140902601933751064655\ 216304225005557593987190257017250751137248844525324921812159989443211212141233888668587847\ 890396370652369626924714869583340538681766865237480245449684605406225784929558270003309208\ 603473872033256966501329619515894225459696402201322332911132837944776697077677769691832497\ 196880040197619500925178555108993525307421946985819867900217553625928368548677374284555803\ 279192745543503148912874884170868131068012667053752661435166224101288737906790592074610681\ 748724674864323077176053367433426849963718489655402030921566813652082435325094850561281943\ 186033464508182733272518005193877351269818233759077678922391360922540586088262853988304193\ 054755777052783744523545125856505752416055469545790573964716122590052090524271466173418590\ 730801218081618730573093197542501866443893688878186856104660233258827812538623297732499365\ 847722947624669259996114471609977058276676605815911348145334262852236443141437579416233651\ 783463051113366129122562834277193238984117598550516771328091375784039261286344729967140649\ 338292334374273490177652690419121222186760383500186979113921713945961766599799824015754350\ 854911802196131153799852876034397588146647261173537993285012315020825808095590988899076217\ 250387311730634457314469978367840323967210313949718194131409638652300644597089085009784944\ 403053153088950793332340683579760490585797013961852825285310018344504399056694034963764279\ 573819932400136549064513923115943458788873475161946309713039358686751421451237800636922477\ 025486167426159510579333175512825433213707776199062644563781469096492673635106032321498998\ 290792884490369629148858735949356539249215757481928075042503331974105596798547620969425460\ 516020591558129345529466807011749029814423966158620817251902610715926483415248071938848604\ 036879683262539701986524291938150625799036004612236336742925826811113162126420159165439067\ 522150912320315605301678581351130525749021500558886022790613830599315764432313748383321580\ 200929878891990022615904141656782295421827325495579861476237156937111817482503809132296022\ 362688814474952168779554555154951203888977093278996856763325380501131190714718786334923698\ 494638738194466719971491109646804891415397437399206464063825761919249539316503065225307342\ 884252945013389306277373880182632062969391381497524446618795478411334945627334258006587948\ 239779671238685833122361770769116082728324219381598980517550179803544582889369469983187654\ 242651121765230246838216812098944367965926957443730093067055463928392575016326314186476149\ 737699823228207878093512754013568123502063678606553971480786920198978106452748061103367142\ 546727438406486299895037345399419745824612583508544243345981093804781845385491704448846212\ 610711898253968863043108941939740156495510161868441564928136692076561130955839537651933545\ 036039509416763348338357363875144471423940812194600520125566568344174071486886970493991377\ 243342039107913700749614967220122252118306134231255356234384819111116993644581220947678624\ 973952008595324376260380754508646958321395804286945366222783993790038180893424384263540911\ 247036507341899005900246094686960683149030384866358700764497319338539340051277171858594602\ 440585186154916210015456486106386628784559338603251531381568263170475827434560803068355145\ 974377781526014331584744355979966168425535711388562492338966178276147634850091266141743870\ 215855370621329006805508647787064786385884318444424688741014554396846106420322759002903479\ 131024056570457169165224733618679177718767231092224171144280832960759713314037407461590432\ 013672159884325608474429677688855846444840834500907332678267132730032157529202407326270672\ 115716184676572689448690169006182234145224042442973172982112125930785742832653715570506217\ 846343308053043596574846376135214105248334646672947998617017690475192638253701077002286720\ 385499658384925928177464567749201352674512439071656300212219254728700090640717747174248969\ 132782390648847157287962846899582203285160048770398498484862588056267898981476611064097584\ 008385440869573325467637846352099593533477486941896882414390798786062872380949613533141605\ 767895224501767149484752248782698309479930802009948782383850231360901876172286985999892393\ 830549337063856184219194437562419490751072697521841783494663066121359295945919262052692334\ 102239668088055849433832009645480819747743780592243873136287592675107702977115714500610283\ 828229601447565960855959134169491334318386045370108792120177167896297051323485738337524388\ 542948025603789440737070701803017101742587188735890926864042558324733468681754450544008040\ 188643635710838016085214997043036917642538008484473963624718143851733730924256676126387484\ 752284543368643131241540504214209058696293136783940634219179014278429099352245722582220828\ 948557070778581176954629257680246818117690303013891781142334942270181251776071098548618585\ 060621036759127430690635839725556160044782121111384957970782575330073901433067401486194918\ 037188842865614048125408617851510920099955073322226027484755276489613760820111733985060124\ 532666603236804699829247044510996510259116467157306423028777679675659985541345876716013689\ 122730597440756709821291855123529813477007238573034546818549773010179062402329151153697272\ 571648151778859603181982726138144485570781461136771734828576624048511137570914124206725465\ 787775861762535720001830224185522674375319738941146964852745624531506772461016403320487712\ 454333162624944942185622281958776206857648065776633885905781722973023076032284762570534834\ 273331575882583397185519111910326041863363661098625848121472368342028165179745045387771024\ 885029072734264780160920268745126275830919727697539984246703646228149297787975270539048599\ 027843327519982299361856316242997021507477624239093474077931689103505983295723561815520500\ 568574059197916150700152576900650389098745195063979651781188336971917961255972556115383619\ 280712907265350614533367300255609363642474764153606498453631121303405599875658014176781367\ 149919380550045689185397005661039733665840786451741966829369746028861292690097090478538677\ 185349502265835539296694194768214835965860488488014190963155789683131540954094515801047415\ 636898895156863398922005150660748845663917507434876412237994738688565341724366920278224027\ 082827153044528952219337296855958926319221687349504618765879392278473456042054582969517952\ 915116453024394558679245000446248146546289294982364922308943311123083894899230108967541698\ 562376619665437482778088174052025338516736739175034309993371053549107631603988687192206316\ 596022615568416950664570427125222642853184705468138751249490527905106400347224654065795861\ 671046604737229047171205791709543624318072105644659741656185611102511660656072119890843235\ 976720690271486622291104781102982439965257693674881980189592752991094662101990323886512835\ 070326055616347819387120071097226469557612503884460988357523493780481883147580784732346894\ 915776950646419231961879340905008943370364379976185983891658257001827893655481367165528766\ 581910899464615820313781250362011342951378862265047064025742895723315940686244831066366690\ 813187230798792142558297299251382187757021061769190542165486622376722662738943087029578264\ 447056765055961008035588027330541492904876475854855605753703023944802551178024930001892796\ 128733775084585969955931783522492302954861694696368267880820895985099343671565200824153580\ 261746996026059830876574862525161632094214768022105503647878019470456874690773989058703419\ 354162465206369753581558512485886596272807886790572642627063970249843197375914323138269692\ 125924321022624461157861528235983952801027855365926142124870508248228460752837499384260961\ 143814919811568572634348699575009835425365164531780743408792057277854166007172387938855672\ 795618344643495712270013842172533300495480650161063491588307317031685673419675973422338209\ 718445565473348545361538043684270240962707364808182103307851055743130208335048691572000803\ 445355889316071281477818462425493804313998486464158759070934895071421133815225573472670957\ 225597302365627529633927655696389297078124491265176642850713878080694296889129058125174215\ 658787499138982634468932208481638767955068243293551543251900340426024772430221430423081378\ 735092891648747485924997375969515610318279573571898534748197182161461751772879545612723942\ 022901336069257703340572269799946883608354800108340157027540870877280461671841311069437331\ 637273094281221239735732238189157886597877253845108670324699939947795426099410675249498977\ 050766412450287418006772633591343872243070362987386523241568292910825328901366476952078556\ 058529082478009312082084802878156831393187493354623556414223171510492879542682767153458164\ 047160210334263412813512036009215882199075872918230518930353959086190062640484024732974568\ 406962201799306514827156756222417941152315990785124060716415992757127543157218061049421482\ 704337786394503639743989074204481062459102418467515005784211955736198152894778211028922352\ 724431886378789169463661862507856505994780642521030439055661536300952715564855435126314498\ 378716269866142810923532649462236813281215435133145443785467375845648210884915986560253077\ 360279134397762177754828098007624953876161535555024055812059003239815503737509123095044644\ 920688195260054119871710218735128140112323010500603400776743633504982880485919128691552381\ 342980256194313984261707357284719198843513906270505259200470342682807110956248639383468090\ 703704334569613570000785126281450281183878861918112361395243785091219756538134264407439054\ 894645571311154344653695182545726318698703486099259364616119332305821090569523171992811560\ 804267006339299347238917928943086868801223596787444522457597179852875281480378608474465035\ 894760339381909178621898581732429662912551873870478523854925462642108590152790534926556955\ 872532414347076306337084484616929692867393905811461016669961416635603637555469588114434442\ 544468676603099171854435988144767313562344001958659711795053923290422001551407411441762682\ 577934335726848564154649651711465682500421315449217900363615916333778583295644443151663070\ 693379760694611274294269984635277863358932481308367315134383132141913204127240444708785100\ 640440162120297177829390805030136342686413202015114050121816510611266750902542558761538991\ 174329661068230272547185576886154179052153848796079830598536162421856419086559586945413773\ 190394525122663700880133043338676856747921911565308469348815521468928914278141035539041633\ 592960118458518582748303051770057701153564342426482340099190885279923801693168593384448385\ 454275082801906123675858817223420165526917275106226944858638711806359164098112782256673653\ 168588611181178830711961246198382630680530577833749599533057124361509312722043801556708558\ 224103144191423135586951020680639064349632831599845284107694400075066420291681858436618513\ 589640395669689227165976470347841059883924738975177800778791682091827283072084617965360846\ 664435896744860414703776583639106450613804099862563780853447527134273533330352108147922250\ 803546704423281533185058534615449514409907125094548324433626243969663785845069687630044095\ 006194254001787169796420604135541551808782143547429864218332816201630841188759179954139869\ 823408178115884499173175511607577782690352814061077535371256359738609072786804032869889700\ 198187886643225312747930229726624607932458930848603396675760208580304653754868511427991697\ 653149212609403739238274170625059496739403633888811584742885189742872470237685022282016057\ 505023786010033025163058091667011912579579167971824185317223527583711961602243937753561373\ 120697993535288408995619277947345176691388820092884812022014823622119609230788717949427644\ 862920446072097115978531294037263534333073627239494705926923109320957486120118615132310403\ 530719534250182510988039137951326241227352122961755217255032229794533724601680248710070761\ 131623264113466018856824587274428086203690985580600445536852171873811051110686019617595268\ 676198094054473833882598359557581526719412199186248413638190223261636365570623509033667319\ 069519527737993628185864265200132131456742716772422319432055165814830642933496549411953109\ 163362278137683746940516564730933707434985995490717817912923507929420375607188340899950302\ 799717529108100699349237518404976161838972029709943848257040414580397556489342343109862472\ 196584584065153726403350153339517874373288392237135167847706025921154159045671069196324586\ 273913456190099809602200332337064094989813933696501792795236505812693668630387453818572562\ 862528643859053666793039497310904827400402069919210256973770931916403593033775106626676889\ 309305451572240829016583474499590911265672863137091570371974849240988947072628679854626505\ 153026399148292836586527976313723685428347513303114679989494948499386281396810200352424266\ 818651280444265950196086509357379888153338283199651257995968691721519208715203955282761717\ 517459597661693386723907791869754977890108134962700459027527025063693301079225013790566471\ 301508889688903635984285620457829126066436274423192193339739838673536185488353356754834422\ 422477038893540800767108245466836930116749762565739008661839922231373931212735520649802939\ 418679553900133456934742655071385875145202638165778165545565089473845315268834806789962169\ 895055376520820846309183715093486861988504468131634504244467652897370823192322584457673859\ 018757265363325896561317089061562648603013638249335772853581054737615398735451806153762920\ 569125242180412375504223730550144695231551053930827316332617180071565817442291743855839253\ 585492035759182588078158094940843681789346277377283145957951646228126862325971688610515757\ 168688214010417579410574034184812761622160747257623374490303333543348445011604677415022228\ 472743883538087251475617876961838674569502806825452454586024828414478653956749404324074839\ 226132449249959849107231065466572262530532860722843870228904495686447497675507095937298590\ 519077494308467636248270374499926516356784695249275183823426901652545884387591025751654825\ 415805045823861243665912170087406208406276311822163308859796476352266396191688078709586268\ 260097514631282955356757532106019621289013707906989802548918277970552834712333812329008788\ 861061238585318233956087837705005987203108776959565735352126209363163381102453292986862686\ 842099876054716820160868659495179873559767108335031146968290716117653415036498810094943789\ 763009936726499102267786696677392421318680653196994662206081941719942035250696237009924812\ 276860643976649781306683265760953331170773213183053756592365442570900835438129757689205997\ 578321146276971431106684822200983735733920469000336308575007686746260876088673903539589547\ 480119800217278758512632630470188166448943459259429344587726003408686416397845863403264495\ 535107131798146880042161397613890953127690001380870939933248897173761560119778946033084485\ 049427171804756777665378261488257645694250477299551878678259143791926979877986530982360153\ 303426049247071653815421924890008517623121933841660166049165579816299920449919068950593135\ 861841605958929250799781217737388954991903866839039806674020635555812958632810737556430505\ 210478443326172964625773804275399460601338808364266386535124570741818494917711924755298013\ 094815519270806816509154477581460150967627060448159304670513908093291696796726412934079680\ 653845746892462503124554649125148236759489716191884659507881139039845406302124201672066382\ 158796027082476892485821964200069524235163141643279993004789287173883441728070448061045190\ 320490263030990980098693589404954928090236502056838304581165862807416207704791230625643734\ 400281922292172993827576669193177177596938422969295438621190402986563043937730960731257576\ 797471286109641703967950183160458792455256491018183935127733355985340154325236386269492177\ 175438475850034234941389119348607987215127617652089822842541156516613912372032037059169593\ 478320027084193106947712058569855272142567762181149453483150742168288851205786797561425543\ 985419691825418999837706192544020055649072723486081762322861605024991456964494518694082430\ 399655037396624410068279396267473587268204924459505547306088174654191823249937081501200185\ 919597248791741687832210132225847159692317763371228475086132060027473068109842706628054442\ 439045434753362824103412940568679311022871269356756062141616561384112425296800938925532480\ 337559365449409147240428684495644733839595981215929618182533334653205002160544883941896887\ 919423314802462594515042453222030000601510873618198329075569064613235346335717957494349926\ 491167945502926044010607910735343557199416559346004363723241088509778637585041262517830408\ 568067913055082822072734052675106762257367654660100029365834504599946587820729372488494455\ 888145498374843790878095054970255353636206184216122824867313642064935284645817701138342148\ 971605650014302173874965799211510783767358199997810503861192526200805468333977082688533496\ 627086967237608830066140477191652501666384479357516644261136670117855870528055406094423879\ 695084539492366030868968444042700506996324066053405737664774667367044031096215938951217663\ 495511726122426757718116704081809533443063106633376454842305033582755664901422044750009116\ 483269536552963451206351539639105423580075566115268251553061668365345103726217888415671391\ 700092225951314484299202697964096656157559436349467015809778577876992445354075498366439087\ 749193673949066285116346098144072778159670588890476239211485074778980597993353278376710890\ 987974303603209993391524231957502503926179022153426496738446228520147739123271111623393817\ 751497249300136080191207110577703285434868232089915850538282089113517964148964040148595508\ 482206015547050502873369432169604021641869740213817218775200346027298854373442567985854471\ 641579775233962810151185370791667762090961531485856075880651753353874008480447676851838612\ 962277781271608045019745520520996706063815711549000552928893141803438931358997663190775590\ 490110724709959060835726555302739602201011556186032036431304840774669072166825241357746603\ 632723975123813677145526307373296830220992359454881690255064235604927707067757875988784295\ 252499932363064786965802928812027761663684220340283869034718102354427829676323166113873675\ 393786939648196216320786933782104307719935022613300247704303277201871980638668637854217368\ 610292191126080285831781060574240985796930692506028472335745745881514882969941310339449749\ 445169827776255695664798444738753295629549811328327199742592777105573481895397160118606593\ 374801150456091194402156730402931770833893976598384796411181239800772900379409749995736876\ 797989403263601480796877937571240314418024711833645818109386564463826247475655481683733225\ 743694266788223124556508845993973969322251094172354923654563238386299588665799823349198825\ 584068793526186322326129573872333555950628214063821867058786266440886436938901299971202246\ 249857659777748313677046799078170806571834036561256112846916623153328029387615565425084041\ 027362709437781458154746796241510643349525411080657622151695539387765480778647115613410416\ 469284136891685311450204504234522500845005143867265787323401417956966850580112758754432919\ 658084628298241049927235468716326579776914747191020239467093960691068003510826423724121682\ 482621236720649432292823465796049037154635898844502819572065218015507142858650095977432311\ 536248513913841015370275054751076132675061253700456790074856516698163417008809964529638593\ 913555024145613907112778518056850201684534644003677700141645549850877231255706949704874092\ 544719454828886778258939764316501729767474125342943033148340177340137324564333546732880764\ 512377197344710410209289418197689309614792845769598971652995074510705485507815720875687393\ 062949499376870133449171285641498833528452818801479951158572965644898752035380477756775010\ 624479390303241278881904413251479125979076981274101200809566240364887778930776924882842664\ 555678376484072461031820332225214224878865176210216203794860028600824288942470951041016525\ 204290971220357904639998154883195592925244895312548078207776080075433682855848084777809555\ 439700191616416938329608513646861506781767433168218476446643092253055139297598219728275418\ 442543373928531613711045143833173843777248833270410168364296366386892671116305360170023419\ 244451984029374450686418915311249262453037169472197156932835785749714750912821275479623720\ 340463898302984179351297673837317980297926931949439232145001608298215419715656503031966074\ 986958604076189312531440552358025672819029490762777423735810553085443445862467459957805349\ 911831791630211335124394249590766239339015471716369287382186160050004161421161416285815805\ 394028742304920870566944872919248546442607709801811250777642605996246468168661110573568833\ 355761050695423181574649420538266035429111650546042335677269840742466985128123224710780285\ 543012875044034487501847547943223326642777274795301391248985562613295790179894830295998488\ 492259589080685936170993424042324392980130356026980676430267041951371742369925414282905074\ 887110881455657988042810058048055680844991274109522035421777748472518324155249568609858206\ 286835362466754378899847535329042850473854822479046610617682969057950334252962957610998089\ 577393931347993104817320512256665725201132864636621804261711937459829099159266813341146804\ 892252549434178024172156340119284707149450379283247499394575461709070055326366282657666365\ 147036139509796891688423983498615962284463383258380609096789959092760048334165808541510943\ 569772640193211893966349383023485036396071522623642107156630790464100891119585361098169709\ 900263661618310328751341280850901794898672363352480366978493526792469101996557135836134114\ 550390388372734802051844935034213152735069879173898489536259166135741702362194732934947067\ 212831356725495796221627707811761326278423085462707763541899235667621893030656683760240246\ 301453808596872903830307604326901511962739221294755624139549322578027378753417523393741067\ 469764868698765701819592051211351367076365710429996778310868587608867479430932835680241143\ 703062070209341038150813258561677861372974682165396178715759441696412832652823716647892581\ 292418483015360421750049519849955872509302081043926284016711908136851616179854971100708232\ 792313393222259738040078718192897507089371472270280417177114906927460623861568039948722962\ 173674878766461763113201292167130856044393493164923127023950337708608059088688945233140833\ 205412916971242938667073096544274757024581502725722872961436741466541496279485428466476814\ 771942727675872532468660878063722485206116280087971688106714069993655873894466333373155220\ 568850897827844862886607447914591308567027106775603675317216965765056567566130351011090165\ 925235413986697465302650065448248003364724359980831269844958914484794739859994759923048870\ 349923218460714477871545710073799811858888325384849126747689897999004608084336709310951409\ 582930394119580913059585260605406002656368532620608420132171442880395182257121463134458203\ 687399646524580804474478826256707310080217102780571339799917678443345505319596368192167890\ 925953248841209153551864860580401594917590360266180178467632272091792142327292178906932344\ 353201574725031652307576519018588010804909311612639551002271574840908526576190082956008780\ 348943307406308338001335468716452847708141752085782250759423834544687526995547145095611116\ 844297503491975592521847680019093347793370218927818371785939155376764428400895119275032317\ 203061177002004720548906323979303216709787849639300496716635265904914779753414006043778678\ 729267403983409626478411781026733650048858775174586201482373527790818713519638478321876562\ 437149455944046436111853109944870358818089876466973888152276334869574563976509749077684059\ 390708266879332976005851980536772847994190406121071664499930370266123047629985092598312431\ 561808338566404150789304534455611316389793728174250926479708817308070439918328623989669194\ 714312231075894121867439855000322183820552974212931289484322337184072549254637586913161473\ 779742838214553905802005554552353141511825073387001343129294765665293417187802524423371755\ 264797714177899661167043286434849441673300349056629051501558978274777477675134397238785018\ 156961322508457088730898793621731992995103879772150542341194621874985248557222383800142048\ 143204643665307222707147873923733257799991988621804025429990874694820545226725235001972902\ 656690794053402913340620453103002454003655737284357872489178486740982790901030061531584941\ 522115519750627220479911618602077430521465121327217860651712673267635124459703410241910836\ 121679476099872323462257477512215183205384798103173332115604192586645814505764256752342616\ 171279854400807937542604887287053910749136096779876815290487964620232725110097400341182151\ 071179771146126627441087486718425893259122293301561532516640308089098712678108305158733514\ 471833586429601050440088572126727267085404590962628568855235830678691853765220505011175116\ 704842794115261865511783838771779256876530773945323328664371190681784623109538097303279028\ 447476210595593871392973896211605017207512892003765783542096329648842761351124804611621541\ 061922338704376144024218090753040373440108152708856032619259510434201950920051490083485107\ 808074126006510920579317427468863233240881330763402649554368437278859099934747214569746600\ 590425027435166692721229817223617595434965323780779422390762900203177298289929016119696468\ 311345576513621034335462562945147150860510035044219534845521881930836150668605843333250237\ 541944438396310949919756451350361935910114516825053447974658645130304388292026628272115110\ 910557607256951525224976404022858393876770965291787300514105324361404121550383539549597650\ 762547231165637724066266762013975845068125209734279210710571625826535805472359171621021841\ 654179126830433809775110044192256663599003707700679721374453809259543277989941784827997529\ 206066813316732088628420311675073814877141075049060643244280959605893376943092274638048958\ 580466713272817158827721148464653592575493749532857912343592630205076463631451958583684264\ 363067833129837973764697579699763821513332743604545473019314901569204780778329888427675413\ 237351367283795232181858596264285977738546279591351339138775418037244041791814378063507811\ 020808758498675570688068435372204885085554380078441559200383958896493184942243322314509396\ 368035680523371352862644853972906320307038707014685531306931479987376863814637671007321684\ 550252074667777763182828020136358320262656901770688155088997035377197903829146895426186064\ 622518534576812293963468221231695082493321606611847247868051422264129675770703220635632545\ 244724997505727101029094595914590421420523764208956030456776444809288418178926303439079087\ 387467437384806018303132810340416615566523239625821465639688464074386603546637765834762435\ 448280419945793920112699849169595746257121751870734112277655008732256808793201609830155021\ 382409864378914399309626296144624416946088266627185522724704265858420446424451966419496651\ 240297131529988737661493723463656834509200893147563851944070752587726287209731636138198277\ 236323620268249717927317261301778269148169260940191527069810875673534005789427548325098800\ 896209284900434650498230542425124035136146736156532933288029686664354341698645197984275886\ 732005073698532991885885694048566840549392247082009734251720426088521276538603908477607688\ 461595538277687914017052212705738564046404701967686664016951106334838614829278257818057208\ 557578715034796526441949626003472224921800407846481918164552864134438224328471277084061405\ 678160012201972788251858862871239318689425919271192957976446464018113561699813285725693387\ 675410565854708736978555454012321879380549853337302119298963240742254388239969205648211314\ 268310521403128277568772766345849391002289721147872551135650803294207083898095485595725317\ 427260431715931085781252208155944671369434289662133608977630607323199594199895930454779361\ 076399970607741704143841719340491903251978154087527001780024611914346283992267619148072619\ 898306897245912374032737046751997056043044377340787119011549118427630185740790068029628751\ 918126468617787885415475393595280194856118057534314875690494953479668360107672845994083906\ 616633711194059668264370050313261007036002476086875191428782204824566754466428057495570183\ 109955077277499279072951410120374907565358556546541534803440224771154943886096128753007320\ 521437334353225676818883931175674014948024561306631132435694916578752248180555578517255029\ 610056286765485952528369575487455087015685864535094492383250761415145916383197866582640962\ 028937107306712296927184548633215396332234289537882542522100516959508768919923081653601257\ 364999958661765748800919248335061511847298194123093862186126879413866381321323377925975274\ 740260150389211055949911690374554318265637873958778920022854043590057408184440387005600454\ 369753298274690790976075835802558124104548582574708704830773405630204445891209054791635077\ 553025392675747915589332819027559615298589375634334673409870987029916200362946941363431340\ 812011069147362829355841314104204963183741176751337962454501559660725555553631819504515542\ 791068862260090944212234172553045235417404029854428004528297433355022877020829052193463982\ 073973809003923300715351469199518208444426132097271261899738908655044969093822997986005376\ 062627229696037595145081939971246180222112744017722962125831966714814033455449545248263421\ 629028397573155767008515328595789917211633633262986035399744567189023178295385386228807764\ 510543113009835239224117958669913431806884595588152450143797295828139645933930824559261493\ 687776153770131848587727422903446275200545349727146056614787503799705180801693294787262750\ 225520982042888676747594638818771799481051687380846788017922469384072671343453356081824405\ 037331069331789591119193134065150656935813088537759311832739343730437969917096523829365610\ 328695627687647520682140764717372376524076945121186984935609226368511970148446674171079544\ 682750859617990865639125903974299029611684599490493283204193023346779936447375278346770947\ 767745373087680111009500750807625340246172898269310745257243393397220486289611565157661988\ 389283549928118535523929389251718387062645624503639459772322712043858200187396171239777024\ 478881846170982473809533980184017802477777636577028685651746318137834510582401277023109871\ 594666105016432390195707779476956831681213629504728235304650753965620872119855597261590606\ 403234966827919659271890958173800023629617178496425616971300545073862363107489211402839469\ 383016152045302223988753952913823145738271830945098520568831807323601464603514834346696260\ 912698774411446764495458376434860590705712296650035060298661783671126425315923814776954345\ 735747363716866395825670846547446161436787603266461640389557093288546550522289438965279338\ 291364564616066387759142281488368847095048667869600727984407530590491105606812443925470624\ 870565153355780481485382565610169447824021522026117583836178104300647529235658134481677507\ 659690665795887983797106052050430110083232324474414056907601684218221626238421710754057987\ 382647076980734016097538221218522814679789766225342189925782546339827640814451968683541542\ 132815560652711614318345022335854998130215028278227031444227607730003928189477940558918123\ 132520834952369657730134001595652327087128110968628347504450263139480651188149788471912691\ 066076141206630357621646633736428316253067786808852278961783698739767902859092149003897501\ 245457719073314745049510416583525386357458977121197451924001836386013496162975159497875439\ 524808166714169291646673027978544702577736713790660924201258081533602530675226865941246323\ 791806093053625179691214558642099600028643787347709717135110694864023396834729197203837431\ 701962186957728501618847455331786974921235478241062486899556698348280046855482203054292668\ 396454287679110649855553223726548076546262782507840806090344779302392679918990940491326743\ 894308405105462026918237928608552749042628371360365336258532585315118343626119656161653360\ 110285583194716046091204190975293124405462440594622266797462598128622526912969294394518016\ 894619000763744835348564506014544940409604965083045824559813530315638000128710699275856056\ 591624723275782805566258102033137078288654395984079334944881314892353849342268210104659300\ 342695807817422744278023854113646171614441039241190271910009414853809520773910692928162113\ 643639540288960755844358590216681226360224626230678773583013499368605836296340113509492636\ 078709587805803968127496789809493785724138287220519114219562918526123232673629468791230354\ 619835781781863594356793627840149909981919888045042811314229258186259336241617156625067483\ 573742145712930410331943366541319771764502354611145001266654505585379422175601141011090732\ 860767361803157165101639334667083850703260774604830486782288886443367276883267412318783008\ 413218720406840653729627145097796614050366312107081907988638608265903028907141887652494174\ 995420851205003917830744226798585123837126513539519220038159145199099997910524563856049808\ 061942954652193433236929044200353290995179036472678754813971340823375084674719658213972996\ 400285735698996513936169168752662768980962407509019038542952767286375023442972244707485538\ 826203960602910150506197451022410606494142251280617137249529464082616162453209981483464176\ 427712395622896521795566879754489434262727066071891198194670527156617426052442947778226876\ 917545700606397589823321315096657872717582090271487671648411160106542563756549915714127721\ 252046707887163435758403641739675201043984416651453346204244956137982028344196757691963703\ 968305618051645729085998644174216839001406910492986719110188920544271122968151960999455801\ 527999794917547986343314378164380973465404516841311690814113692680907196107487379537368665\ 131100746884443337627200851014345283778651097643335848494503384868234849583456907502663187\ 079138010710343686953555843107993450280334503575312234210797935593156450157551357031009163\ 066373695846067966370685758849198214856777916379920405223410151588099802477042919700088149\ 997159996554722967869244506314330815421711603308823558123523145351722455897767968704010390\ 975946077692159568071017092144443450839434068503230939705062451978094567989205605463333210\ 114251772797928331226407989718196105923658736724894804994623258942296710665402989484131287\ 741817806801286385183778977187042991656857964263204457701319413449808562832097450298066472\ 851986515822720797492974036964139363072182057215628526104187455668227043522116773804212374\ 470399327723005544172450524371112304106371019707850152334874547395065522974746290892108641\ 698444241181512343337907965502675470114358491681832955180315120257003795917739848917205442\ 817701697735857755387052177521154801946832602018968375215645798893189328256381023625071273\ 790154850702080122736188720305008817584299371308616598727120321490522079756984969569287932\ 229846848073021439901730791415825739885790660633964973904194517410990893197287450358555289\ 793343325652734296825344547687715739671166741237033313839768269337418351234639326337793731\ 175941231977983930062252787769147545969595438657428065847991552787058188746994518330552757\ 386894706980519954078230281763628656841901063406184792138373703531335167816884257874528259\ 664613734968829877692396359309969566251026859093102473306690403314520436638065697781811922\ 931022162318322846516608778038937909448501493969576286325212069541026232172557177586554204\ 361292914759676181586153479511270561242956729863791553860974477169587234633630833690766869\ 277825314353060758440235529690024592940241092836655501310580434725822348120207768159282817\ 358053050064632134820463798676888313866406150172591899933677466515515287412155639351612338\ 837815646550933517502744195812920547296428580632141925382769205017900885647101456191095330\ 089571509668113002759047322263770565142165458471872845395769727590306024940033360920121305\ 853970978848837144978236120318082125396669314422968907082477780463941424393559842704747758\ 446329461065648703066504088359570101074432309020147807274240709716091995714213911583393107\ 184852574148799928427144068636317763794054090592702432215468051997655556347150688700416460\ 573346099520771345987545285066787530671815786163790903604656317068939423818835814848980767\ 334319761792380987918444975956416377885131448414380308300017974777687615839990409509716223\ 206962286680010895422470338150041010696252823196221508743467144493076430583762298637915828\ 318694115921815675291967364466522956173256509837059997929216708905049214783814796362397504\ 042289440118762864570289039111766010742224177093057745884426318361357944280311382669552877\ 005751295074586592270363809630983818548728010193661302422914635234844604816962085048882984\ 958484353857499901580880528097759199802917002252694342368307160141503823320243813401891631\ 931768473671488595917583813945873846150634456744300799987147271884502929392569908447829245\ 621641299871060512811598253683913674328815652251631035799134969714768319328966733652258926\ 593273203877397225160067104837020550578782221837730755975582123203622337280910518616348766\ 095459105583989375260945763495958010717068689955629668614881203655727038958629011991585465\ 604340255894161547469729413180034082607257137072217219434969902127270160321716141376537877\ 874964768994265624515356641213521402517495610404959816711621420415864488314723696123193669\ 842222596234184834915308487821397258125204424463351951453719733901719319237436287684119171\ 199899060067312266150737776382540740831484300847841942801094356919525019071330411990218246\ 182575501206196196770397006532379478672890401692358517074641621229772488784047877655747850\ 412129998266662205903904158332740036327448879308571952000970043907644676666634944508975986\ 035698303065290025557203014321053046392676873993823162877936747703804327839595677147969881\ 159607122986193055285660898940104720977611958288260440404922601734285445147249724581136132\ 248517721429624155549710063690401438704194632154384779761822496445435909960793004709686260\ 006011049510922800883066817263166949138625312374866011497874997162148177693063379759214973\ 451765968087296848066374779975346412340116735683967316625166322836613160950350784794834209\ 692121505439778457108520392979973753506500459220951852052861525047966875951023606354717049\ 654331120812282388097199922582509363054337284727407289397694521524432196265434327716369588\ 688782743222781570063776811646470075588222730558387330321074708236664852853478247045216489\ 068714117012111535600868062811819054463147096403582448025452096661821066930934883446977810\ 939710558723890014533019949832710956527779529591091881314637241835660831158581790748794384\ 399661783317903403749561309206878353285818811770817441611757978630676055554873579333752193\ 272001027093748949404801088486371693751498306776321707861499560412986111885503860333503781\ 627885246729264115371100739513558240116207515294067122704442194793267775586713757350206136\ 431092318755474497114317661184409929714639946510421747472770139215012993653240213225129796\ 726138392196140083229801202237978632466737057731965862004864340410974362758674812556058013\ 074718206184915909449241422533416428719940715074385998537404442335510181383816091652206039\ 957823406375602432010648433360207369709027942622136164053175316523218162633715755446242594\ 659704192395382752036378009927780577375770037818499000760872482019191730934438742011938112\ 041777994293913127663644615774247356088980049175013107782004726909671494160704637358763360\ 364076672231420722321086459027152787953799177446015699873440773227508847640153001052984189\ 816317438202655761980798581017636536439131547656845946499963716553797195732450930777057312\ 233536775350200381398109626234844667123128311707622900780540212163671941318405357756513293\ 061827156756350433425729522296126689784868591921102946076526157315828711709768630697735095\ 266669804412911586986473723338977996532121937934819476435981958862706756312897554859032202\ 314985511499450160253323174264814614808233292530886964422554746739342155947332919937775347\ 699217958931001953201422489342143218288674850922859959996712732320878765938135056617728398\ 304102205403724383048998649685656114630818539906009412035046476124420286124901032722385261\ 170376571902092064645396281098524009718381330363895697339032574592495554023804482839539385\ 344139184072897503106930721224737183975123174491261867229073542162730503903813553368859453\ 311846799423092453371333712215696039451066057509052718542343860998642774406812653633500041\ 145192586332341942681566112039722655832599951248592850021888315823084621841945999106167378\ 315479820695190056105859504485391374792785456420202046423341203186404660850261439687186161\ 531187900404832746680757095306227523054186002035487773786449717505822832198122208667073083\ 703512426087158044381914871127544535490663860266532114232176605898737857567044541739005789\ 351681949718484244849025875443154908875641305216088562734531189962929618439678054520621037\ 758560654058114213180979149396158746608080390699627159898887941174848601789643340582273058\ 672849939624631568937017998306508564948940542947121618008433098069106668877500040984794236\ 712912901427088767703096639971100590410371866861515991732376029476808354771688255466737240\ 115778273417383332388931788747532068898547820383640193323764400527548568232465555604819473\ 033220304910020836171753052620846287735018411763755721463783184625052899642511821885082672\ 020650160659848415221325270298332685355855107767344486205593056731566818850873955082680433\ 097502721130887887567210030374056901261346164636347736486168834785154841871124929212977149\ 038612795220958082965894580573988354281396035120540024192201532468190627196734055473387478\ 336649282240142871829321182099722790699125463230519029756882359103273778277413722592415963\ 445434049034292359996174149880249649511120148087173728814289879973103532597598187902185853\ 968784648755063494962162227525778710631444658353778204499578048740740590486950350283927687\ 995033334734067582511927440449923990000433807036319976981220902477876116776831891342806340\ 476059589205769127962862764128825827885841138269503353662711494519042624994110333866768008\ 023606864638687451388665805824281504069794718932999295844839561264579766767178509714731572\ 053875975189282561911935429476319557121178849256471675378781960223949574421134035336768293\ 924142589382284318742327663193989311698702865940569793554826271062167497839459867600411832\ 701794258324969122374861358824909905093526371169685513579717034703554190050254582260217189\ 466396582257490766683230462624055785620834168235670746188048994361638623137586781125688381\ 604869167223575946178807250012219958245340370003048557425018007466477710392080139566011052\ 618098033011505118304274254307054210248273655104248336271076223826589894747241952966948174\ 706258899288441236768091614508418460303459213775871587846051313556126579425138093921214228\ 505417842238139301719218184238382135300416527801435892366668385618170763532412863828797602\ 201923919074857080064938332783240638047635761416130209934690695460978114583268506775803038\ 208153538538779271133469432504816178428956212506527434983897237783616351972988404100561630\ 354343861421128739014325962879443864068208353290858010422366842457627866423449373180398423\ 730458940744773758969462412716516866052162280459501490124904391730178575064322254796056733\ 607210310312860472413212325126966142215216108756635261029549294685496315922928331053480443\ 806731193668043706274947349878800418519664127937887507573847288226802805310919321174311261\ 589473254217538105039034069010034931099556186819114020273364060079382193244967548152196598\ 872153431052425162020898625946314588987349306823360677861513067058512872251791323956357311\ 345117501587855724333348786132872899553534014191262256437055959713490372986682075104949903\ 132743108878602147814813911714018177585780210408322131968814559539598128262644287861032214\ 401100952315747220570505782605041946829323232517886376668612266508384508167670529360096376\ 500685740064237992324056935568889028008722791958186401536403953427392752244007664513745522\ 193885415411688217554846152018672612975883695249566775725183857838052232540063308614030555\ 456358400998100138137958500111594607966180055124499802273159953361174015294771719824095095\ 695974236980721136581625301586043923643367391065553228131899457583175638640923629388181232\ 873743731097444731473358690338603190733334806583336081223050204188076249007571123130998007\ 676064736167986429029870139981959552167153421374647472670873026448192341418399612240951491\ 428798770912768014467618294792938746251282991103656497376942625805342111034080321909767924\ 449851872714621684837950329260252106945147270324269482831716168350119692419558782230720988\ 336285263278181048887301598998543288648832822679823836472374676596444814122885611549032569\ 528418157899947407443165406590103537085511987460394716146210077797865368797059191612506387\ 552661409894671260962814003756553251781176407833305792557377182478946176992288680070224337\ 616364092222747792864711617449014183656512608185125806653046904956658956331491448335254423\ 110637632827252924173062675608111657478050727348635984004653631076265041057381366891747500\ 078356808070078505132638659145417803696839398296703925623917564729473235353982521067202607\ 123218036764329473839445713807873786752525745304596258033604724720889220024354960065429624\ 650337819667642722217718891986544019175802564968133990234276460780371817570550335099045335\ 799827853736353052328033277843404699203530093423012253895902995312076405110124656320728387\ 908270485773257721921853346927625535717751058655721707573283837769407219320642361978159383\ 176407690058770842480254679334469323891812370662824300877332610696212306538021070864980589\ 743127200556038067473811713376941157915012877220336984737814741607576790756445003439137109\ 036876495649487753232671165258484328509605054645389622306052802256906707541956900891309278\ 225061175277992371807993767617636881833361410171911894479148146585470178528251968609770552\ 754637654162437272564163934171157802355045200153095671841748428869396985983421765124940011\ 130329796000828089335274096706351071070654244725866312435397678934315640915505162602696706\ 343368734844096304701237521752796532146152059302776292020629921815259030180017166658587904\ 394163973120116116781729316351097560596983198366866922231368457576525749455052388987925581\ 459850379799149379859760775581269808241160663606248380252038326806593328494469527156379122\ 283544020086635599771961513834239814463328781724479353156169410428274199954914376647875235\ 157080232408854848598940579388950645224400738909640919311662981057867506679252590969997468\ 291969192919162230667261799097031498076143196545453336813907154402579720914077456672465304\ 214882884455753105905341792498075595982548563467449914275133634495997005318370177325878932\ 883556729306772922229920464565695363746308146328114430206008323355131280987459579459590957\ 247131223434989034005686356185085304497380156911154315954166097959006721746239768538683516\ 373154945689101347573298378767316700999292327219828017362466746710345657219537541158211830\ 146459435755743616992209512412771600355405545561487950415236489576625318659522043138203036\ 336967973099118911439137736558876292403908922516507528716853390125957849542092430626507613\ 108845152599861637829496591416664215117353638340003071788823037741536345005902970174368356\ 699826979698511526273717352473303177971815229594793239391671746524771961118447958812698524\ 561137492727615202294939176845814225053692324111984381036495758349109085547612537520869625\ 403434820407110335535534508907035428335336247241499151553311546030666553646322678385477376\ 345310981592277860546829632022055020558514577368659892806392726667022021947826029102059935\ 565729721560281810805015360173224172237304485230011965146167352004996896928433264000099191\ 787725330943952495496006639164400708571875770645647259277152827156091354613756394526725233\ 787881095641256201744303760957143655776693015597581762470392076124376182996208443577541737\ 829843601636721831128180932285798709798738571787439676430585040426310882428442668163376471\ 618061350828388543378761399724932293893036043278921517543320035711345631077961778661582491\ 583276844034122002153004765592822260502831793877386981580792519233053516517145228477383891\ 901154203302923115926183504681738630346517186083067483346883254502407390230115571306988025\ 071191214542436368944297932429131520813667988227987690269189351581870125045100459773193535\ 666320563250328899418603779550363612942830369763093712698420662511416840251351528872846111\ 458917320107311183126493411713684029847636882110121947895898913133554420735943268730681978\ 525319697845581353313920351956221426664236203743319212327666096449690975256043882130202498\ 348610696847246029096522311251951719076573681142029822559480208750979088909232511875529005\ 623956852463490795928831557909374423949871754503191093276793823764968420822802059797648619\ 418094367940235872059466077735539788013572755030458927885373493385926931987682942677872034\ 945280500325419816624443605687051722094154198438502177208031571825175219452838640375698107\ 691665953720376214887509863684282123981372924174122010130480251429690466580559440400853048\ 844087385181339841621064061449095716104280864987764463456118127811437594046698298661140972\ 513595760373691753315937366094085059094485306872215439698393414326950564977553189789369869\ 100937281713675415911145169489810833534820095214086183297256556625567663898352226463832185\ 061487383284397137244017320236277848492359101820127821033341105535357887146947539099889526\ 428395859789586156198420555996004607925504866619586304740978403348588470600462142789010745\ 138742510850172686704817030814941079438443948598144265044628475815784090830113815026252798\ 890845502144561885301935779246778904952278370546230430669569727923973551804453549593148578\ 956746448303830430090462977785081565083316076037514800861047040533587444081332058015570900\ 255109685579348922223685281462041382450453975417089191442587644146372235252071825056591270\ 915170815340593707808757511987596843123474631438335895310524654513646667220833787832256762\ 370457712775867021340317601567883611261494011518138350752236614636120515096448132239623150\ 115238243679034761956896416891431753852224393701522084209974044075600692259687846431601035\ 309540390468892250449732866008527953040796512168609530176433052088238676648363847865597337\ 374594647390784266395292690599953306082982852217465919670696602562173885584236289699815383\ 798005076252317316045718598659243759570273848246137736118492825704394805445443270314107457\ 556071311888618342004404177257702349258204857822218961423619308438163573275654071103571651\ 331620891014237751868248406162313382559767835415853513723795943214764353342759772491941675\ 418667765262495415855660308997140744599293301953183298644238083361496794505271911491015654\ 424037204634088014403247352097509183533858337428042641954107647311230029880262516416658242\ 844780204262561081166183818051718071352773867998621721791111782128405370785339802670554423\ 125200505176886991834230633378435288229017159072303123166965938615751232606720033882114207\ 595525642299792379007897069789385700323161478852277396051328051680401948833735713098354558\ 720060239160341563758228465385195895259698439011272095927786993219275281249122526250274873\ 077035736894555870466896941802753175700194416013822768228676617465318041861329940472565963\ 066868475115504031224883100116469581332428179441549089854329640504589903312635897081175123\ 246609515771846053932913018988734167738080840774370490013204284784820751459648025724856591\ 094107780839533780140457368684296488136103554797146094109465770312547598046103858674829402\ 948333314161685808370140943659478014453028245733863328610366692995057483691142951356622341\ 627739351070594631404107906386812233570183846342126687675562361464907354172146012403208110\ 127811786564788372456667499167792704667905968538910199872537152997994626307513193642807090\ 911876261586207963626795953950112446350951735585835748867778018709738542667355603298555927\ 365998764937880318089561541610725780060321798650837835630498817338781336643092496458598096\ 227674610831367093201853881827678312996254990829884503000829541273045629016025614654459471\ 069452966921130940520678178555037157795422511012895533791688221736202708335113089802514489\ 654672789159850183725195815013652571586211016482729671165813105389771656040066506516117384\ 328693704537899381752157427297575165827293323482306942340546797930330727143057760778009781\ 206164189549184505196312913600578298250377070741133535267347308171555458144802779808625356\ 506955536340760336254293367792119423231687725333073126706584974559493906916432885749605019\ 850431455804710830214915540112755750801247129558330055436273971804860935596256269761776590\ 384418636289034183176385542611545530507581033002297493751106724597483691106142941122359005\ 763366491698126906513380542642632524802968374518584742385701653959972977810282043519487333\ 869614877183906361977954693647398197214640247819639157709217230270917481689084465113605860\ 234959669674076590471502721557942148704661654939683365714519541244968661993282476577400221\ 644367035307261568866440597993321371999762223406080641049669703031502916796847410815170770\ 802402488377141953754145313948831331681122371776100440372747023903651161108509208107683303\ 225173413846396177056870454414572011947458077182908068069151651745163111424429855887565485\ 506936112734800456991610065376495282327090387895909557630912187149528301756899773831007162\ 696285561677947093917274165231850112793217008297561400596560076776809672649042002089721075\ 945995585791394341614882419783253735983726173521967429928502855607164683086439263073688224\ 306227453121389565498092595294629727660645014764259309690865563165545030056389248811587155\ 742637973631801273445835831730824073195994608240808601932574404345255613557249514918934526\ 165452104577924895016941458382953323293979467389228897132701206827618380742715990295774327\ 431050199753821815010098325146478896399956508539943805915843528005298093874745856181478165\ 087955424179761593198054699446020421953293329059612419337727684704129650919694747751342771\ 688708449698973337724482754752027109125924015040991139056068206949180708227057564220803589\ 089491239288535798338954986798201289465566666324734024534070296785604341956802340610280972\ 545367491477243285666487689984084068672972880320113151806200558815149887936741038195587847\ 348954412771349726203155381345583362018988970044305969827884569037456727134444071379334242\ 263729397171967230415364564379061433285731312150464625207361089277252782400053937087636749\ 791664174226509450368457058750658111032018055167022492141350260364141123286976523213354591\ 875063602740465181238666202734068629045689008697003252100017169627208925325053337612413055\ 509981655837532460640270914814435222025524456195085529259298036233624226129884189067644035\ 219295578583444244822920724245009638780708977001115258437247063852444661786235209527840203\ 085006718955624427994586555747046395258655398356934346713336715169254383733066445655964255\ 020011568967873930272626135068502164548202055910563448024737208320516056107275591487171051\ 956999228961885346527119673377237204285545569573337295912568071076203860222457578722224616\ 848515638211056063127231965358264566327792603721560221724884596196496083362224675761142211\ 259334723216541028726417984738012366567064018058841197329261099320434258725031983681626768\ 053854651336494936839175632826295223049879424959253415353502180389260573344124605083642678\ 300202678880277861989766207365189162931208511231208632082788877229420547674286303020533172\ 315347630594434174340623826862619911517832655711562907911686915104540425229103918448586814\ 024339570986883713717174626703306180969436813235564065924759755380987600611829664377027115\ 968468808464152123893888265368681384511043395030539274509038353859543238739714460475163788\ 144075908149661738105800607370514957714486514161698394144549643390794758123855846988278762\ 583662137009026033256534021337157107215909089164354977734694072324304086141428047793428811\ 333274167201914422279143710677546941946896862235794939944131634344411509828155353053401826\ 373461464401678153861098633848648378807109956662018703347581424035315030346069285158333665\ 398162844665093532005238003809801527918228855723447623538650344340754595661826399322625876\ 259428365232725179481563647163082345407206458338236463692721475895377390068018486921079163\ 830583392017797189543166000289489941048508149986751630382076809136122918349000968919624303\ 035539102484539039336142712260720251989800196741346702438773575549260291387021044689247398\ 308529043253072097969046117496838479207144711978720757498955417981375854452352636237982991\ 600358170826364084252540188047806120498118445830061622409896544599152379488314814077147618\ 129386670355121434303533382507603184101824279833960088490369505014743540397278458925841656\ 989160877603465222196744408889964735865539153982484458357484476405363520528656991671056507\ 578812633747891556462795537016412974077965796999607810879666088973863599546171122003600772\ 193635949681661614587777425295060628438331920860614917760159737297221002736216540195898854\ 139746866251745274622762287140604532720252716124742836393693343557242200588845274131787750\ 118400298478494021516546125811776292462374895859885765476755786546734728254675303212223393\ 366530989306134674383642253354879121899924922991020438810379463971214400342900719838472080\ 121357666453802351028329650083282334004530480941755323193825915080269811755663969106653398\ 105810825950318728729738401171525399409110794632567428233097286557171505824959580203461293\ 483184113877889844811611510798652390299589280931390360934884068347816423170948432129264590\ 210729581099244879212002758753931045699830629227416865587847778065431757471293549760507204\ 086988590869046506664694401825433155499284955847901084578026733381172810567515511293397781\ 652863080385086246751330772671273589525988716024863803988586313111124031950762184759479171\ 463775317537269368916763015011125755865217972096420680238424610477098130078188578045612479\ 976321993464059049703548196667947338157979182733825904370432953765140030792406197280277165\ 164460293338894864710510900651884524152510629046468452497014959267651634675083946584997475\ 352649476038155840555999814111663624710967874107764341495224343468882867530432200103293889\ 759276260523376157690051321316877206382565914979929054180591019803563421916596002747779529\ 196397576332264788037873594318507619152693518838836605981471245192884780563391655801407309\ 899769135166424250394623127478598466619648384025234725818443383161782792425060267415065393\ 117091564917753656091525974834923989845823720388503612730020581308854065944064092329159690\ 112536002729762003585727101633960108549803363437661785007553153968365018372135715731541194\ 397245506180255375077448339912748848886795885596889017321460047771518538173447904773714596\ 257952044870213673180200326027823327221170893277164534404602091919083644482180338746272958\ 748190541240025741817089078822769359969354273127765576050589674873137973720831873387861969\ 629409946783595303965318653494036605047222423589013132450844024436239296872077092325890078\ 458028124949165053591147078137640445466782907597678010225458410704180694454298214121982462\ 134523908164817177962452447404031526422463638416726708487093806611551875241655858274384249\ 650054116833904324978784052057274655129769695400317436398759198242569563947657023237578346\ 087113505158689173603168048064229198891338488604405111702677693575364599640070425282142562\ 878202998239577132013310122870842247445792277403295056331881321638220932244984447859801365\ 046146075921314639083482990013419092082167090441777342761104682355390834031440901524590313\ 162776599342081779809633670472909286384068652419686775217516923818575289369193945615991381\ 537838474122432476946077797105497556788744479121604608806684545097210593941547408677319133\ 964714840566837816818754794807195729490499513422950881335975728443917924426109192641715851\ 142683735374691108704426266272456327613780096813345207605705588762500708244117491879741402\ 923543124924260899824653599935640821094740692143010931972732785361783918761596806866325072\ 472964009883071130428217513603577307007889986539358066443309268964888594986415335152516314\ 956474047913039256477179692287800392324510898574106230091697577820977094480061444263123435\ 539376956929503609878021321538128658543861160195738582201823802981123574424960633488365998\ 459841580418652857718468268498787143591563512161651001533214094911229348710722357143971665\ 114038226645515028355972465996724363624198375185430294984335051862981273559558394470752397\ 736603704571134378597452493154016041677946002143265391217911151617406335189753724323534784\ 741630253239308864978642570402259787107939654633998506460814921561429922008079108605170640\ 153866235459830602687481593456759785869841802517755198110115059898107044788435413962235811\ 287037152630569311474799488067680987540678768069163179214250082370096581843843779457871108\ 015554371506967885600721407416541963555568404499609857793124910252101481788083365700626182\ 645643319562694366061104800279475392498484708862623021853792120801618866112172356797060960\ 515975508421724157481936899488717563173623418760767548200753871422435413858996608549666385\ 503747406640283698903809250121442858257580422275509999636195209042329975365760155512657906\ 332301004967056663456324274681392695317952275226702839407476327144537716313768533119920873\ 294830529748197276999315556954392495123334723179716483127203906963627400852268431212209722\ 316016445991779203681111417356680820216535804386070587875756401592297042789596022951358158\ 458164130749195178761862762300006209221878563322893303109287373105846866377995462413784189\ 459561456448573091694293326337367646692425927742780262046238668444252626050998304298951459\ 302485384253757201587308673616789176295578292656888467747754177721674628713067647847673160\ 737099521260754275282985026145382815424574706463549408140667055016722903642678039775117038\ 882465810161886845034480797215913283192548810669173070652986297359594090341917725941310134\ 730946150579331269108918675049647303004975969100239356179255524921208581162553722997230084\ 136746927632410287607529152007515844467336118877911987266042766309671733639824582239586695\ 763809343563432766804908476388541645923386922389190379662636337766383639013238844011670403\ 987291984104686543585992253035785900503601635903190279135779261982925835303597871591324666\ 716371317821518632312340172524791884862318086717127822584569456648198321132683908635189863\ 613701569831090812743535389504921475862824375743774525019719280333498303537280775882463117\ 819159869837333502311792086797517172410046644613281770402371887938076997126448448410469302\ 905962950574289016991168214138919164694451184111301024366907582639805091633896988346227250\ 692377573848823264547619385974350289222991497632862876414683263676473819443753557370929915\ 359503820381103645255444337838558814590834603711782625576705272011322923313443857286772434\ 480943509251681457054757550511756185726830353615496492779968610132963083489700448743594944\ 063384292743863097181591139055877231038430265701343841174741654910867466475497985730279970\ 429929717180020293595475486873020775134647486271857648790447075852307878677993971703054166\ 908013098090054718819666039166261078561526025144555925931193924144364197833361305379911139\ 576860455849304154692236529581664869325243062910001929436021680129531231737232840652627185\ 811502908465944947532327661352443985712836808860801384188693311965718512468510336465414936\ 318676993153860150828248664891399269835500898252906646079019654623775253479841311857078045\ 173654147218513408705000292761292387201066916253083197653707380160117784111219581183025572\ 049315712525211414709849007744143653294489094106524506342167584259057329447444456418210270\ 495245636174744433104309021527323201910280144894213822951329230030848533955549379972294932\ 197733839451350394862975091687171563759164606957538758260794033553065642436607033400568623\ 071707834205040223574866838482613074114707960875918571800239581242028390472660050662239936\ 940912490974892875524061303324817657378088045313745809670659457092736689145151462822510862\ 779968645697605660633910369009338374840521871053522756518589262587532050448307069418554741\ 824903333278962754354762829863590837701512256256169974053014081651213683270930326789709936\ 073930362362747250285729582689042594077260642946309951006468345042644256414420046113323451\ 249745305900212134611998587638295881320792199031369191795634478231156924275604876477579017\ 673355723877553422619290368016284979522621565722169354381958775215113900320277548376153173\ 899600350630344897110125795831110721469226841255090402777308555326587250708911752772067219\ 624180860034435028835931603856045193678115037700108855215472548173905303381162837195529358\ 750177220220315141472218017905700522709901993407490330956007849125663552837490170995120165\ 667913087633764285266265833484257615089954421327359223736647925475131186329337174842905970\ 496654361098594917055209252326414117750631767525400259937284604844698410636404455370002837\ 012242706314686045946061595323497141615958642474789880736203353196259258432786435954315532\ 936883264036191594142255183701193787516837090397796304640284555069732326276821627758845977\ 708384931865134402288628223492549783902763660357415686298398289809800606204216189705230957\ 235803231178494843457232044638022312908773205008435134747107198380144564366017258809994444\ 894369556340393811065096399761102348630027038069006157777667495253724829413885236299150012\ 141574748497632038748879562612847785129220876859375060945334967957180162429606126634571069\ 090111398669227547122417286272235039793634266624060609263092786576193049676183699346490795\ 613696781306332289906613921781106298818112736067165099693988895656143823443167764083660097\ 793948353319800299255012515403116239405390220939395803488536346670552563583892984373688608\ 373966212400110839632421042373855856328252323067988760821564148620508783717608761256379023\ 084427458378568095875884003114506767826348968698810844281923460022667800703379004332634501\ 571134260748037354569009763930802146252162559521154802524767866534723108295090007645529939\ 032358101866771329578008419932443392676668345321279256585824399206255888769122177594491985\ 130404522327832811329334239067398035515289297387214208928434733521805442006185912266380554\ 618337567939419498857296185198049972893755431616948379578777707675929927083665695018898375\ 449192233151338921192095152283498881560031698320545272593064827159140535865510246466368537\ 087166367485555218869859064323275847971652914567893177417393300172134318778933839737846371\ 191563189629949844549735595321558614768009690117686843210468449730881377307491980784465874\ 855352496546741645544210449611654345802456966033120020725273284429166716736892163134272574\ 492457138419581932892534427481179433760489803101898598588631196036920000323270934589524234\ 682018641107565728819794058602091036373521043122645140598753174599071431575232380975498559\ 969698689968851244766935241886273771542028575414190712719242366774066520150035157570760272\ 018271738736780093411224855007876660733991416143324285706495556166433694453476636246751757\ 968149669693130037819398855887680442891312932178377547495900179765138426388231460995843072\ 412525924087872958844486097693182677934733534920220931207111178780222666145813343453082705\ 392512508222037575023296562065795624939450650340541576535374623029075456041997739855981467\ 155283840321722024021332253160465616117619455499523344579276691523302231892713314236874277\ 571823719848128562245935090829883696736933855204371910571012761739385711080286666127573003\ 889529641027632672142284478309967704987305198492501209630361764636126975229075566765393176\ 305517779875043487803311228094587385629363193844456004726871342285915446429320422864163313\ 242393355939322288113414244442589629933661833625697401648109672560078526059256796760182436\ 205093992322054664887068410958684658858194432035707431527523327935680777226893983045428889\ 533354594616267261947395855270783544146840236216003580786464220306965020557738956260504142\ 452577700162762754942991539075427006654316508748359896649248800374189770201665920458402076\ 789541525893010478427276803456041611729066528515750993062956978852103268786419174999586150\ 663512221920414205157108857708692460865394477802405944638997916374277418886444714277798243\ 470191590923721218596458622503769334413017088357290453508761139330576339423445075015598230\ 526668835326151701473260444888476282747860014763861250858442347002025457436205037065634065\ 625149476022029975421214337414545717192869923612463360608217999466022407806366772142909479\ 515952960715606056475311825557737196883624014011034037284308213375178252989539890578731979\ 539653335954949191975810420394950290261447056852388603975763194181418591745541753078486389\ 896528373309548268277576531590137701567697985182549892370651913533642323188664090452994417\ 344227485520135072683938885942589327606143354139676602474617174795132473334255559470481817\ 214560601388541425639344326748184268798221790853774907791716983447220918168699216971504020\ 032589904596118145986348184682922370772712012136630366080700000142570126749950644288443136\ 008218709101470823674487462951709662951409002700685027848690397880449122931200391626345901\ 781271235929009097712162724595406577674145239571290792105752222360338777273703077175474574\ 988428662507460492143972860778049424400590839628151076531340117658945319596063835043318723\ 788356825966692090651236693385080237407792836339119768451961118168332610009175466765544228\ 949950966848645604564079705274746331185549564037816671276064229341213539288800912389556745\ 604724754395549651810695837287725980454594892748679420448482342810763312245112327624667246\ 557646489999192537850415322191336201382836819316256565094988897234190591376000904425821845\ 194962855142957027467313982140926831118603121096049052529933666633752832793879377197311826\ 480012874081015247483268971251265377353642121255861532782479625974410247619277764608598066\ 811878385444669888370060775807341483441530051233178556437795695705025150393411806921293807\ 763476854249369243741127264531333011556183558559279641967515901069383720315817928458147139\ 097408378594200864795589373529374537382667029021106231290953920271063283043431367894953389\ 278649242643564840594313913893320813693722069971721258396047787914131229186548574408603449\ 813063685671247489589783625027184601750229677998033760068212641862509866377038106143054239\ 702916511216679700667168430666329649938585036029574836611073849141542489071945977491091094\ 253408849066058665056016536219012321214247588859826942099504758619062550223826400538780743\ 114167189923296411666170402409575540912288691219792624122485559505951329011557118642226111\ 964933962114868877078207901087592925546287117184962532415709110241087967442453831449484816\ 401370137572027856917719383876277794636276633361691069358456966767850004902680140948282602\ 102151873871483070407763712959204379905202085013891672805970781513897733993504439544625684\ 776794056076882029855189597043995776131063315563547075632857093211662063323610308202013949\ 858308406060276614823281532927421159837060853620311731771632032325528481785242277858445199\ 845825690930690635185780425925370050420141309800582819751999791324397575655220670891982779\ 041802303209519906647178876447446263745625812341805106787873189759798528359682128767131415\ 214234671556157533367991304549810871154323286903337099954799775749738285818084149746030398\ 315589162221400183213254046457680698892458026897595034543761690086582211607427515126523490\ 981772922817149148730708405563189905745699952998892412027439369791697793938950437962557113\ 476047356964898075160390152989669768219451939678218590696614505133973740437470125583218009\ 213485286600324320289990689038449084452564219460089260639820488820905559646274602401483898\ 705092768209003121549307905100196795812416170816145646572380084491316518014110154432955933\ 284837242653592910330003305147904804308774646485366475625713768517244581947176865325752105\ 947860325821570419677427742273467775788392742465139812734714326445709314431417824533480899\ 644943369721021536953560312479461089425711214095225163602819495789598182564390749424612116\ 953392885715494180985253418546328147692854213203670703911593138058422222398280974686403541\ 621705226351752063467805564980322132334743654255760226011110908680315784520015002018611376\ 684090031986906722271036202770082792795569649342923271797391015196009033697682430388079105\ 611820107057942632160426646793227056996269554259872819033848062237946065501577317340667106\ 376835229427023460604520451891148568917939514270783003654048714495655270000454047033161920\ 856280845522200091653698349534457106378275138676724616997192819673826806954591843994730319\ 028307703603819216591461476027643788064554769815846092549952469146908790738513815592094429\ 459035395041712660519713925049039302561892274322493113189017634399250403863324376936133561\ 830183915057241282801875870465300988847606526248038812212701266143876307958895331268708782\ 455669216380796658988581047161499092747724802290023116136162992723336013672612033776327774\ 763800208036991510349735660085859975234687089517334234436627445153628861119382305098284525\ 742249047774958330305182192684836489974671476842234590237517999666688931355194224929239137\ 322426385122558655496761554653671703929436979547975069466515071451181413815694200390930239\ 208822467626361698100938896007190476088914531810552697204725172646473103216969111982297426\ 527275686204825408910471207507805257206716469887445781811057966780179607528945321055578910\ 892619177980609552805736618347529457588505814142767768468906631637213354541806332627410399\ 279104371454344936331104466943972550249216498939203800687924487953650954895340607722136267\ 512308749837477555170425944347996800158569120078920088106046107874565833674891625063235934\ 694376541398058591650127624230613127196169111914591091755830183517225734466815401252987897\ 977616246655519420744889974343510958312557867354437765356907201691702662078573776505421480\ 625916660114074142523747388399625330445300080344536669196788156490016224147212197722412779\ 824303412199998724974820727484578027276859096796005668708696757279369819016129224200989715\ 846179187462603479210282350663801189882531892442519855059974704732608506583455775310362283\ 993565328208037316426862943012303059178183197085770122283889861169198338841260277099055533\ 850392997999089087796693129501577778539835858017817492636202776694264582380779652320993470\ 993182161635970569205684327853591952597731923352941184285276534176541729604805809552480250\ 512105601479825243802452011472572174185811887788758954230308539039268376292523073778076388\ 514810763645534945693554177420042159097043924112987178349214864560040499832074106187015829\ 239944536416565323447609365181222137242468096672653729954613757845222173663769859991196229\ 578953425946323267099139020150509826556046314369533878339527143650658069830941901168871217\ 107749479075461147517116281620053401435246300426732080863202176293593867609773242529858606\ 611189022396919364593815112945718963187442330053206676077079042478272984568739408778587702\ 584137623582101244990791908314336742823083292258366915244435092323545228395998239604974037\ 259487596720671137362000654508632857592033205294788241361349188720585988768304583564723467\ 187848548893796574933096222122589183591838029872817542302394993367646508960327977970247401\ 537552736333341730468357567625614588069569642195136952618918630649900605364198683923114503\ 220090727540374198629893869427799529003824387480690430667332731129085739023955875615103961\ 170488346850534062551287879402374977678782401231341148350110079912974965402057174353500827\ 364945415172405145883967178290837786908919326984968279492473206977896849156950921060529113\ 738661032289971738701867721600513737241334264194797804313970084941749298173469694260609773\ 963182060376432134462100454139556939559481439099496186445117631887791890235343829228300693\ 422622075451868924880081288785672580297988377809664615227889698980735978217246514291623858\ 956299995999556587835585698274468422113147402731645920462340223420239607340075350592568875\ 427968839613506728855566093851831013640090616092177848180462361637497881078426191427773687\ 691497219935976732836996534188946540883960766501238111745335345723368352190039718621297228\ 599561385255859358075169503735402459210909552563753921061297390921761950479178752584359939\ 552111399630022947252274658526158391834878906982276830750794901049556488086747432613305999\ 580641873979559630124378485593721493514175450389323126936846265463108215331064973248177527\ 256047482890825482387749379682382111080322359858558137232675906122027374300446994857675076\ 383969411295058615058836250462514477151017912399209586113142823276325311818894117825083277\ 691607933980243252232390017148437951566687708668863124756979365895057467745424486462294246\ 167964335084994697815046723783163502810210953266192849746444888813851738613545140526249746\ 502452662848962727009356645271760721222176987946355490449306058684947776750439662033028097\ 379309405658565867354112127054533936804083625413150662567836299638363210661922184613182459\ 027147178103118304595661353703048812269982156141437001501032801362012793476821526861473831\ 020379384538424563035840047090800972469045616162471979046629067312843301024239396380332911\ 604203632301364800785574415526640508917159884385108183907565386285538628074816687468135507\ 201658546707370916627723747051488739020012716670418040760871825581381811364660546099543035\ 277534274189815599144840310336734468203450592086883424116316735086627749075376631302353152\ 053519495674686148813083115159291225416007449090140899345551213599068970385491560414374912\ 391326664623084142342691007943487313183362332101373857479162084915883699198480597253126040\ 600148454883317797740452339364483843382264680351850196990040097600593062660519699158490829\ 994170134411075431019790697467957459734626309560211772834233467558485534124872003192704080\ 438453153395867000785379582705576369673259524275867551760676325419482752632874623498178819\ 379072223749827677142576278506762146624583757489326714189215888369045514972784800767239205\ 177063966459958463822598098252871480982052745978607200246855560395100637557024047256010085\ 361254579185134704817996216894670115984062184319213079452146470429058279078033520688646543\ 315016631032486703982094264032486425023050243248288596618934098842845202220002982809973999\ 512105563159935506117095342478111935343809559493721310588576914063491787992365127740634282\ 856987986391715709835945633612215369751975882444945321794681759504655713036011135281722141\ 474449922749243111965435875327454420680049561382715502080402546645718821452643838310542174\ 254660134062467843989683551019360716453923611154613109569757928747017904500100946520124057\ 803430992962926244121804025233725949916151784523207822633808031227502615100062376648963296\ 552658385397410088684977059617059040035158466324478421471517989211600848274006433326935033\ 351151774969027306504412610310760686026332747610087203619806231068015629254199349954970908\ 430330799139067985565254918482193815211413691460974269025605782905805702709870743011108221\ 300309758199405596187474104273218585513123341279058730847633582899207076312823065889381524\ 801477647838846107527902030258603105525430681202168288832398867927188668681724979072556273\ 150134062850875828237272874060531193035520543446052238399662282885214881216047643916496802\ 381777045870911703665128095348515026130184628780351580679526947107334159139775892073194672\ 914520200472456471616266345146156759959701975175183757065692295225352652403337492227146487\ 304482261277621459699207730517128408136148813299231274026897945021536639392747926697816515\ 825101320691467262588969601678612598922887331317433441599631310009863668642414193856216544\ 415885163596623039471279660215064149885069655038917357843065835620230587588169765593118484\ 826787040741042238129654950577667211734466835582111465387799066525651431414031618498584012\ 106587166689051373282539302199225482956707931615704553954849827812271886058454405713484149\ 921854723454906008931563779678887646893311840384255967541543110351333192438823062974867706\ 035391137249998471742024033338353456480732328886875609130718334406315488304314564203532167\ 493435290193712585738751600548865526672588354543764055881827904765770784273657528222957839\ 402414182604300253394252579352089785367457568563837886204337874879545449504781846187559245\ 911555008182608702191554950465187456622933835792775659266734540807414280549485829501319903\ 592419771976962936494675605175472409161328787292078804914780985942542400027693967164405583\ 727206934049445673784710309530247890036623587892714989419339668447885607590579330954903263\ 937253616917677688971474857594119487521685846761841368252116129045372911757488790308120824\ 631994972000816035006731614601034743038574888135946670629783911873414228467883646036235876\ 470480946069838611557096888502092453173715447684286374980379613356804614317417253085735119\ 753237451116805508456583048041927664067634720917605598420661859902478476855114560402372118\ 171206758671429518843491965021376958702793609163201063550323909805788184726072711772146948\ 739069961358389649983378690636574047503901406958722068964258161657980352198630764084631986\ 742622176129880787885285976078902891381517098281180121072555796851027504693026743259122524\ 993530889524528221368130436181121988902178728899181581139236121150959769410547965057275156\ 794022292630732802956115216791079057111419016040828928934749738286324193051160055076290663\ 223326669668580214989616910030898205797462818106692424656629387816836589761537214587913754\ 856351418126184002065758050496901504482859986433947680438768722493238958379141214917821969\ 473669961596172474370108862141949462146559889615609025299698797215613711838281233754218445\ 684606390857800844385523780039503418676774496198202499529294383769396400173338360986079968\ 632029521793747495358661118029677116915739888593262147323704255296477555185650290244218829\ 766933147906369795538162321109149946384152365923897094187370539286643310021067571020220637\ 153262123006443531832197119330267621426307931212461464086422935894249473296837284530174600\ 815034981228019280983199374565571265496590233516242211870960594103067594474895725125497217\ 753879445174072201790223797537381044839710251091861116755927623912593115845884382054013730\ 586620363473526582161878872419486996938175400501227764533048739735579098834331441822613307\ 932145619791531923860734308212535544175471760194708232167559371599514337131326754646809596\ 412929037753184691429382600627426091259624718537986980476500303900115221055361049975158976\ 166897010325442953892166507191293830785815649900313814112197593858884642586396788546354474\ 701047847494798114621888604125551507423319615267852936039920277515689909858716661779031294\ 492024195919977580247703930481780541869983413787259022141726525336680025935382961788199588\ 990439055717394881439337992690900834442059715304737736743891540912824711776603088577005510\ 662129692656248647940921295396607287066902809799380103362384064108596523859199917889677288\ 565536524952615083977629524067627188126115767293149567272687847642615433743370378519096703\ 240341996309373671551140930927875529938294304345469067371229323940358264069683961603258574\ 464362049473074070251737663986249000108047881981067563932429577644850162575562628911192451\ 271281857648623159237296771682864169994735296409568280597719737021181897668740008015910819\ 572554846624458573503368396588281335531827735601173632933225059992931997879893728541346573\ 140025712212626984326267318404489965187413889348837675706186109956592888922438807989644452\ 817536681931600248918927817563394469791425311714972879995657608071344037264505304161290676\ 999609817248566499178369852946056737983146231026606708656776094877789104680001028697816629\ 966989591485856958129919323608829681529795454892870528264023849224913496613233190810698544\ 649714208415513006382558542708045482986842757315733208292555539210942381582889513123513293\ 182119022571371050576755952599730805075168112673198661120449560668631994589722332168020537\ 225245900837108261368525657484280602159395259924361413180417596287249220740374481734002215\ 442868338051767825633763442143764611092942601964960344634392508184979861652687858593913212\ 284017651140306727637379373564840499331953696958400191033939887202980186524398587376076425\ 988296866429655314329625213348514813292639393866044970678376383903912256370105049124710199\ 770923892010081024239659654632962516466936422384269959247133421667612572345666536481377527\ 655622021522346195402978324903204116663309417264329135688149013115186697471838314420716619\ 653380955323191609786252181914309422419540809962167239902130215040086640140320834088163533\ 543207247466810987110208730454426211844865150895125177697268584626260687356237330936608859\ 071818342774648273601127102082286624452083386781022226549172639269485135377234921061850911\ 841968313088404579464762828231059173283740627147248692259388082351116630986603905670525373\ 999507564619622849671149982704782413142079580812587151316304310114266733399978133901350621\ 962691803676439521984425567937780210084025767753158852143005357423071302505303370253851226\ 124416660862659289467762811476414303091859696564464763376254215314290951283492597976893346\ 810323563307032415512857657818320811995394283349460370611497297218157795292977099198158997\ 298323609476954870181368997642017615738342204460348020261463238457668570605319779850293826\ 635887448665055287881179934033757017125751900249910370750711522351900923529550338932872536\ 155714640934098225056295162314582522597524314756859393817377989097624046912121690332799944\ 031247257057250514617405557536068402018937494069957941478254156110329430736024185551829020\ 109579968997316504900273399577403799130388154902358041811298130002389061430781796907045127\ 965032610228008777646421080465916986088713167013923541602887967450019652483872624390393043\ 038527424500532904980908466739288337132193918154693734082598108848281939252068498759057341\ 021647774811842005939311327234894551081184657893750856390314284359923280914203842902822844\ 511442624941915071813520696472792446838909551881863649570278631028860738517168129935174091\ 805351677557621444065790278765704210210445892385927630206190938065343514820607245711555042\ 894092004989596983121520855580503799292475170962318326566381993800351747801451508488624182\ 741583741201048249825972680976997500051822706621953691320806865909989551204324638083783542\ 049222349152343050574252484702847143795419886958948294646728755756518569453782280663754143\ 682676224724229807294917738882063572250040118203971950675985006568119809869509839052128591\ 532624168430123662815563307232105073255184402212253950506932227718742027006055258172575426\ 004143718064743179121683658936279524687101846903625176998570343475253653129151010723700369\ 234637995301276121855445012852129920659674824809026233592657184502583925779480451288353275\ 747069505926261898068862885145294711998184076036346477013143315540482628726714540918176252\ 914689648793011607058965868698447125617694423165220884124998124418041588058625846856055510\ 144880521712647174047914426276006636711373511667073882583633815699012311222847162618636598\ 730161155241426095853944097991696851135610432045500287198210686484000738181556080761239861\ 477220015691630208966596709748530335492528749015096880941034861419432433257943519717262562\ 097424296796342708285619115076032757608275795792297043825878031089148104336514193666022836\ 522607529156980014699668548804817900287921625160124261885629157181677353253049312639103607\ 375750878923891860822771442293091084455547640010862660284955012423643506180873304643838840\ 148479381639534005863301327227688879251525052543859423096955851683014126137498594087452426\ 314564096871053267455279774877662853922810915719409627325553777054576158955597812673504452\ 439690894166464166787165892266597782219720451225866443484780593738298038696577713417692778\ 528823847421239712377866384260602022065393412799714580450637892787738755757211240365325349\ 987544641309869301333579654288482194965309113885039186955262936596365395830902075597260520\ 644380602982692257048831534969376200573309972957808979476095719339158293426331125376659360\ 170815714334475013048408643808632008055484998014607923430249399286889140027445835671280676\ 380646572856705923794961777948456910523989995895277394265215995521210640107246750431329547\ 962832594233175679454000750449848248129190418941553977307125367115702913438890632427879819\ 360557596969927682890630732818699696325246869867179746573565294111684810461960544524713904\ 245903504655320948554297396947728630528472168906162626293398016840072805671218717997594868\ 531438493152229995236756815549089510295479689992896196250431531374500840825345489798755994\ 504492530850652084614348692140246258231939088355476877695423185490479379135531814976643728\ 145657347407460315318146627192844134474710049515321037113560588685573587635314150018093140\ 340475733803627750068257243667613860266555742925472344509521933014576792173400473191878911\ 797011903725781703294414881850023323777407780467585430411813349372002367953610547121311846\ 830290468938722129372355110930085155878154875035439348525830393536063395378430927266039486\ 452067364454794808913327863700542190778278187578826079248470244574260246932215696780929716\ 127411704751195386852321423048609405800207469138607289979065194399330268873223703836040845\ 131181845950457693016936013402098069597307438967018715957141118505956193552453640132078742\ 760404150685873725053608812636728647053450281389808643157091015170026232645380041143007929\ 718088321521326515234937986144938832947635414566359189338847596343630979667525365928114200\ 824049499599513923934683254992722681817444321399122765714169026063757273563133320194650376\ 840367480358449810850680845063378585252253172459672008752277079535902830773170575647332202\ 045666828129204766401175497911150628003298278037582460373737841620680034015369758407535060\ 193273768960865543711551363963530800036252392485964635556871541519618394361553614981271963\ 292109735566551640347562768378860712060769182551333185308631782333497707896849733889547194\ 161244021053968049103347301268529159574062272247213861788594413307992044732910919741710029\ 366143110487254626627055609437313586562815910492556689079042775069127674580254262463476199\ 538379590485424294307805038782921541742178088178667421131075373305027787785721851700172715\ 107401001322626054114955891999801314517394646426254017854801205357504467645126257899174648\ 580224550043458257405976191415690011728452581764257672165244241933978321909358904182004899\ 494272491011341211571265348460247746019790599300704354474131167809797634584856417688714696\ 755971007756588889581209563280635702917537655640019976557584169043106754804924389653559454\ 546421812970882725890840973721156722619778115513801954737273187330719713464478690264378016\ 526861719833290336141793569395468605334347467378791754670499216543820506130379509937294423\ 654546547167307372090567199809560985867558011989796414588220762835256810783284450407688890\ 313034877379948044660292088466012409552822889449578040940179314497728705916081491539763774\ 229956826614636815633583198485289276044651611567777968401291321060849983403058522936329298\ 76861144592523815077121759238607120354676473768607637380", "18080559735315991653476070208258543411613478595752227867648697116477698547113561838299360\ 823904662001558266807556573299452203868322702160067421164446303788610702985052627604833776\ 466763155721160607188797074082727106688856892448985617847667398955874144444783562748472258\ 082884371135234630612697146518313080494507839041082020114345523859147835965048521747806440\ 550937005581463272674348609014432422269257615249415545949446969635186391957037911617627676\ 526841833770707593007061502849201037284572193970948684451926828373269170513666157648050862\ 455910858821269484926888257988614900319272692811134003454727401515964686508588357335179464\ 745016857223790678103820595786105321934227873649228951600144381226346229024934916568740532\ 320566547563991727073543057250726617354500083806679149192874601233267145136138876714917963\ 009879546551191068658690796593144422183383330992185103460435125850623469768824316944216319\ 297621353824512114592383572819035846374021939536510772302661241931346688058122307266272012\ 319513552268736446347367970392856720429413494858476782461993817670417259950280646699096408\ 558533695822638015651618776714755198202500440665195370830738045721746499101194168699681409\ 639821156453418388871136143715537771271961026456316617942623317473902997784849634906667376\ 915813511251554114437561172046490186572198191142432397111986899058259311172203247961692653\ 467636940368482598484707381100776025499787307092875727994421393717736619709190646577441608\ 156722690366484539398444739679419538416839814010973499747438503586665968570642585665194166\ 008732927409385330961349317754593456612850653965236776722830093365422235310843689339925768\ 135511294015423519793265183882084232520982661668341367495234829841669583336911361155483480\ 348460031690476901786752222863420659661208122060047622124530164677139202464548669416506853\ 555479087384185703410790144513521623245263782539513710291357903348419923125650597747864822\ 766583026855202072941951285795984668822164864879611610603180971379494055514906505248211885\ 502983282235262330328025477023199690783122524164321096020354555369016383295683547325594480\ 755571644082304644845339227787859402341929159957541838752216363301075045377020403231476855\ 236952348676217262820113972316633302554850807882079209044350573098934773066886850471070786\ 237964703581256222744827566729713913175026938701704626952734988415461399239244545551218576\ 338417101067354721489914248365155530435241175685192498809669466176143244493141644508064814\ 012152103246823231050110313852660136698312316851624040603244895974859534683120107609424935\ 693338625329229212453568424055261888338251277174490012667978932174356380818048495109270742\ 722209626501706771319641615132257277691014155609789442018161118859649839593034633336961498\ 474724583393739279265165486910530797879226311272886295895097760316780158239914138754345428\ 887380533879020222590340205736543162131037705406547732656864168745112793566598762928023713\ 357652860640309814308249954668274626723843247698677587960706206380196648319983310964573016\ 714105009422913884839331809985639907539079425781348525196029864975711538428809628002289742\ 059147381690832426052628722127498637793517010428978650822152559694123322397119628712547886\ 026485631625725547629224962839603877133923039439681841307357789450544111551622327954939229\ 185420525953625026220342260247607861648364050486293714357892113616823979843682858141364192\ 956407283222733805239253283193230651198752755245807585848385671949924703261605231171899500\ 957721151814376781009756257644278140359549265274435751722947117718256098376729816556291696\ 757867136054028329781083871204394068847096308513077751548815050471744387871955238687683086\ 779401063733112074026478425777188288167736259293249388929317679845766470037900929514125493\ 483944368515811607634095348987559513308146278323316585493003062997436242421724428553793616\ 220219876858974510730580780807039742826327305587087082889065849413534896355619427194153735\ 575717196607585042377890747298088222143878902398431111747634466793205757564396140714761560\ 950218052945065571043805146998965910741312368256396321315043786431495911196064441560751540\ 377374962190918481743583195837954226256364397363752443000368944688949153928697230694197107\ 851574984260071697124043771219032159404512599455616947955361804522911570547171923058856978\ 295117932888553463802175029190451519356178170507029678269673193791043769463315453758156025\ 516831204440146075006233327847976240310989808383654780165493395243663585631639813632640021\ 816958134768734597762375964875014531439611212617198871651587890933187376210695175142029924\ 150530458813701668940651048282693752122740270964580034866555588160141567321184591767674901\ 944927318903274769035506547201183117365503054340489967939391160459345323481806725530132438\ 680433998062702459983342023879198405543895613798708811042797266205829955547731528128196167\ 444457494043689891340482674840361334573787907324870296965621408928778938517954162766149827\ 918480220770631866399209111726123655374032645905486129270737089987291483993967968028816608\ 706653263984659430699042819385343766361022327221916322468999624585582957951179292521448560\ 234020300039445091463863879946906011363611345291550740512385244233837777290102511182467485\ 531633126550113905317280319596342534753763560555469260054796422049881537279648180587804668\ 336967177423390409612784232111773607982639009419895104160522926041536772398766924013613468\ 932178203690686853383880897047402654300379630832714954614842307593825860108039435056747137\ 041738412514422508372715477605354412688455671298477421802648845669209492138827049185932008\ 273017247958395122275456462502691480400587628116745008347588163522880474223750952289707101\ 821222239603570650004736666096029507826990209553752407613022179118629854639143167454736420\ 360344551643387376441660636144259776684166906106855990877528109674990087036066119047919503\ 291697128323111851840910270867796291400000681855421927302682182719995328470172961484636346\ 865298510834565575646199313612797386188435977034516291659953225772648871465815775807511655\ 275424889846481274197890020359423485326984761565148409121811996520813047877362589950357142\ 724688470903509146043573220938285018816324111032685993061124578918786336038414476468378065\ 092951979635788118237876352815121707966625962422183220991696551593203795820984568984669676\ 444533588489983407197380228858459873939425217132222960126104080965574279217659828595664400\ 190730759445037180548342272552065932953296735294397349047324500000540913126539423252159305\ 703689136127099284973685954744506027263072394263222357073411554992003350750295098397710704\ 415968954988805689129111376774441602294819667139346735128141071858761429284977863300105934\ 959408400991501130323201274383508053152092841086742800772875938133021958005840812814344245\ 468522418367691294074009440085700115299985003186871812295793389807878251097826430003040436\ 086248819267868286188845060328920411390679550844535492133758378317907126177996750270156667\ 466901352284152804802669275744986727904234867397398169509764382158357157190741778550000838\ 008053524402283066521145930402892078482389122547063859063946364761772031400495392491491215\ 720304401743143152479013732731894267847398406874715130288276402409401669185242950286222092\ 349600577835416046493701149351591259172580938330390263281287758885415411345564719242733113\ 323974431679196979163705474293308018724174831334605881831696925775794724174501831239814969\ 088977543201085231190526287523590042183496980395257686110859470229315369943837778981825011\ 344232087004426163990379826982638075145679758635398728065225331603619819635862368016912919\ 959406803167120905323615316937354093252233052823581830216758371252548231175879834782961797\ 041750599733733823887384988776529348445945006246694324814628440843441998690824838184261981\ 667467055776285016584966796706543984403569049139552656240000584977752173425914550890338175\ 600099176149224245470392465136689222698061658623049974329817293775767393969951677686937254\ 121075522649243823987328562851391818512268129295450081650527344730172598220381982976207898\ 031495286120914774650082269042779665066487688087042211732414326070397393925066188521475949\ 376358268257745044210408676088486202811339310979076771246720930260153975433102676985121255\ 554863155602751546417253550653020529732183170780451542762252257821548599537354662735157710\ 272453380767908823974141886092779508099411757015181831507951307353506799531083398895842435\ 700617991959484665080103034495617949798067515091312475504575669241706930196869760208712327\ 031501478384608676495723172083355304281781567920995410596843635618308537406581362277911879\ 284579788400479261013712499274152686692138057643435782499371003062685688719800301103684382\ 061759870713395298014992244327290448246137028955540562417197628716127360913376233003878021\ 129458254882006077140883258506611771533618925121245533247439882303949533686775935594413175\ 459677594702165377811978989006006429746420158728393300155732791926835919100084201958405361\ 541384418380677833620674100617764854180513894689185591654580878749445748358284307642405565\ 231286872047710713350044739071998175330334635193641250821256701967743786626132965373915814\ 307243624236437472920708874404727432079435839554680546316659144353716617326438604623275359\ 513794386253959196826112993311096534030960671682730003384960571944826466637806501331285787\ 861874114667462767784078161623163170067939218129709959876043605243314502470881947207073623\ 478809738337815382791145511095415630808927080516215544394729864731169597645495029327200355\ 255535333551343397563021860591215515407361743234094712366622865774507557377018448634747669\ 432580671296437785260441605470903717188611393078376719646818151699975348428516853293565010\ 596809210371711812203396283372526757925317327861722341431337327790239658992632065274354094\ 517438440146646910618239320622352524950558290938349343682237088718470969106214466171514201\ 642004431881149604461470508075836764348404772291884737372212730181305687924302300536123465\ 499173331339897642186053204829787520565633212201148024688278143614319207857191324929311537\ 769130561167069091890438914845640632468704297005169974516790093517494204404643012041138170\ 846234607362048154010441584948811682639868702873082122172172271827698623234786870268482775\ 077359190002760721858782393044322038453199334816688706326980311253721111537748864725439259\ 718434544799079405424422148555099143321848912349167191715823714347314817211198136796872090\ 474142331163938808739911963935585522711556839532380462140049473166245146426970237259842036\ 586853414607576574297566346864633056498958777607453139651756058434468386992411540594165823\ 300108221239212563848909121313085966395418435519850521587772315881289103983666623819744312\ 421322729980019518171331769799937949309371482760393011538299453277855936012083095208105877\ 032615479666961921389687960618980315887238569106828931047724604586100317660394417287786863\ 366000798651564565816027216998846782165292267879103230697962607166220492781464957748453098\ 876815234540681358474517411225226858710014735312184676382905679662769355744134664793787815\ 287149390484366113725435387562492834132039161458076124197735117500489639331886578333342226\ 367119618079033012828613639603160968403595319429322151091623865193707917896098557230258404\ 732968114189655456307476695579825329542426355058627839090007575345714215280496618960090858\ 905972959630181925252641032358626865350319726989900766762529104678473178742071673274490985\ 679775363374783963258234865111745338644367890838577686026052380590875742758958982354161305\ 112576857579790166548823776846210679938467566491752465822639814295443607610101197719217938\ 355139731853268303256708974916596938007286174009438835656146579618638865898271662759983054\ 343204175643172337212204613998407979572016288783179368343431936574966744277298792337550711\ 526553698301176734710252051324520438656604869212054286880714084988122117905865711645148670\ 788317505561768059673885244879457027956873719041661537802608319225998024877634958759243167\ 121455191512225689449402086581638826264981792811880382751588236782562038894354718610318308\ 231203952402925111753918460151688866631695492708114043337354347451264038214260332376560522\ 257730118436618957444497573363330170719807908118025688753012170854770940489118751319777515\ 242082534788342647884713488707153378015365535751023167431780900305197050671547686113559218\ 963292664829382950694664397071226557579661409530441798727128137107241159308059376326307195\ 453451031737430391559974432045458039975953161908346829196541130680829135335978988651686915\ 360087076603979852224470901494069461068185337879658920558220002245580490746648987082597201\ 496970823607332987016310525539063701075064702288680319972582602312027274541293846659326187\ 520212412033178380096854416881427687374414833364866941540091212928777084380044772401581040\ 727285568871630972191617770880972105892926626346402557427195909463552600635318753221055655\ 564998907886273468556094641073690703081606943956502807362101383830820753751735407122236566\ 691889396522634330281572693075802808338933841623378083295274098347542779681656152615721817\ 104716409533032720331421134991914118890931666753480703673565088882836324721850928795991244\ 240873992885645733096973825787803087962868583209539192659308485620271621451934138331934031\ 248287550324155627132296075316933061309755816400537032028313316080571489813118920466353195\ 061761278601117267135553611110174019506283744113085387192763931989032767125912911249056301\ 308718449723200592099555366975096064560385617981544650155726626768516569570071531699304882\ 801197214022707189791986488189795093853163061688811756420067772978400640210043898767399401\ 602845144304804718527247833953803113582421307347174489849111448394492161117110532297501081\ 127382796727014014261348533478243680428479679686164717690702502443341903411035708144621119\ 702790949355254791448099739140733293949770018641422945386233325927700899305282526669713205\ 398155725487094847565100403322049358063190443141908248618573209065471685702179650849342550\ 535069606601680431537490272099652122583794944921168899335033629061084481498523932541006640\ 012982303353237645991697336156177310133209010518015839572968196006687218111076550613414308\ 676372248315492036459907071124713158914120613332987097726600816233236003456585118620717678\ 366039777922315519599231512949693556018262043721992427837716521562798871173486100537603819\ 051265306589718917715298332402352501044726361180406909826145427770647341434651989410313028\ 381643977778380596840957901433141793998374972619245546541655912636709438570103564962643648\ 807914654458931967059313799245709064521762438078713196299118808958209980297279406398252843\ 530797390893966132297112080071410463219805820175357910794022572038852322008296375532313076\ 200569043586791992243813497525164440617719348246628585101094386517941882531702167402095644\ 063460235703861863560237890609498847553674549232698399927668519595586499572353698263077111\ 120740174394472160224606870317600103774199029143900618128758911182084685760344513871578040\ 016600210645427837380756166768415494118973029022844645984436956537224875047590336916003473\ 191388586795392332019334720188189101477342938906440802097914063430897385134512991072172639\ 132686170002050597766695535516764215805919956870113725665447037447416306385101917075209430\ 747633410210716136582622072886604447398334088740457972958554791945187729970723626693191430\ 218950100479941614484805843939278459852075194236784760956809037101270306814712177567297156\ 996397065155727068094119342903653812713618407076178869546623522117836337423773810671080385\ 238047627650797802684336936861147109443472959339340033909779183840321368374341105362488806\ 779220265585780317512590411267422531038074892251079117571570619640187477584383887840064015\ 364102640148564535348793112589021357799801048106489343817567642554830398228509559982695119\ 116704512193121868129214343781439161247595543540785694213209496780656784245962538054769795\ 387643261203402783788320796168583060750182747024334108393713586005731231507303904782556873\ 095035557918678768872579793771427341740262297914177894568747510533350211190301452894020024\ 845571002556512485891406732399002943731499406372955823728905679416678326228681188718599536\ 147010355658694212926663768985325036389750608250022365354076745601658720706837289914098703\ 049914963774957960594207943435517513548781091401304539535886978912289981941120415955004954\ 183747526496647323758065137365084738450417120222643905158341014577450564612191803578955056\ 955141661661685054300628918765342991816270682999498112709638135738294512166342716192749522\ 820783549066161858504693542787272921155716947938118353616097239566868846790890105440191495\ 031430460797728925843222907022629860208682916267191312575395282358368818707930133242701342\ 488659598998265513441713032431863368229593499046508373934347997014353156968701939460657020\ 614502865616645840149190773523719051037901002639262646508989914523919326639107804268897930\ 130831598556003170492278653102508272750661742340570987492945866884055167166388648615360382\ 213934320507876808728579438572430062354398514862836216392984393042495188686782869399632600\ 850489849217545097760915380619666615434905118584525497637760698181413202444030503901697970\ 105044684836908019779588855972058770533939630167647493883130752201183942300304454574083883\ 042290062520877549754193804802951447836647899991524484681402550610757595293556805807708956\ 131477883143551150064520598123610112256012503606083994406714449338046264758915760274096322\ 494937630068464205625900873790048592507784485101337402324336402509909868216030336898677440\ 748369367083748257066044982302327069701246869395460945484318733884276588082257704496423628\ 869239803700492075578049384757418358421276241409781574218945587999402229876305466960003608\ 995798479394379835513565183597534450971202010329725053053109331651123827154808383727331136\ 139537514633968273703116954591760979691262049436975902158980879030180226894830989176170938\ 168265741574892194184467598763250126827407639982156572421494210866891047206019893096257396\ 071619949760139492051892560036151213307517882478730442692349633505154860553760990902981284\ 948526779342052499644511243186047656005952346277072336706137251931482347049927085368356603\ 292838319780867190383360275096519159382213774779535752647951585820098765012763287401471857\ 673460484663865957292567761972700337949409515645106352480204809248909190247107824786427023\ 671610267867826071388590438821232510470988503181960184866580245994310654032637254304820494\ 828296241828628888824014365003947008208493594658693103342803441990063434821718132222448608\ 914251023746581742435834791868161108522778506561256452516753431262674838165638355049406368\ 556272908658455615627507812724909706364911772731747201765601868636368145008054318086043697\ 980623615011207025617898924876248173380271408635960499395992494873293542563016987647980160\ 320530814767210229640704283388483935041392918254872351851961438347363224464220117607611017\ 320565373216835928553654685138973525387771758951481433173824171763768607149968991465881575\ 702663075116837188564426352909565826850101989915944253346158283524393370303428715948396320\ 700380371006008655932120566441583861113363184802302369840928172904792343032677215810538472\ 577252303628971651441846766176721850613532890954254339168965250413819318655696033312157223\ 804232517109746768187250365288615889725754751336877461500827420587312425897059751840627570\ 806926320848086608610501571508631735535673356749681195023723969314249552435013210203554472\ 658755729357378630198622742015755416431893215426934895861359610295327012994166267376096647\ 046342540006784314760137326657871264604387322061364405239670267955031011006517659629327891\ 559812118292047380292863410154474030226230690394562514087024897397960028072523333858715102\ 624424255489268933344398962237647005069332469944637180238421870071438390278669086784726003\ 978770396952264955408623253204484752960255346844575830896512150808187416153937243255701716\ 494730355176860861301681020175128180534279986927724012281470662401634395164750999668405991\ 126950335026853258374440761774020087604787077122838672978480241850146848580103342219171867\ 174317759061802804628474898522890727149634010159221141455500794281066949452972560836903054\ 894532620541687950463763410936864524777201977855248492639857035836235207585524978629856562\ 258925201026364966868345770963418562208968895059732562411530663955561158610501786998503685\ 012608204603889997461897497619265335145029042043264821291566794198060615889531239107227381\ 008188958761065101998820831740354181887259994743316509545589307546149387781904887022131001\ 780650088509790203950291749849318886841019580300933078746683664612561785320799039526303089\ 994054575419587729718991222406818546515799871239356173453525413650369103473876208368862121\ 009110607027361939035362038643719074748347513246974143811268554348206120434616821049986310\ 042051933021145134015870883521484747936172433691919121818909102597710111001397236819684004\ 693399242514188207948554291429132284856454812305486614286776092101551952858936869865032180\ 844532891478574682533981306616131803872812036197833784295569565090642474830785636621155291\ 974688870898020130035539167348225353226337011366077173796921144745481086144022322678698611\ 410126546375634582053840511274389212517546821635809846708170433235393118814135412130893508\ 970970336714039859930190798735000892225149541171572263514712824622329176655947815360376982\ 597661014636787833659114682526783098211913410569284129709184463284528028614618471041703883\ 702721761360877395341505325672398276116909189038149632763725109211352854678044604957948211\ 611946624027947388224134430775719914331552457532716421998580449263779075469726037946288053\ 036895969409344452599228985661576950983649311553013005782333710679824942611113536661072106\ 654287322843076586689974837971052511286513957052288491696702460736953378295735364014280523\ 897409974833482385083237659800122962889213476557321005638856564195049164160860326680075901\ 910150235263192907411389782837787117273223779402466807384920513878615662522843883584058867\ 205161219617720111605758847784231187488162336754398050953336945665923447449614492538348149\ 419641170143743895836348965762245662158222321543609700125619626213917574767098709421453728\ 471342096533163724009678985369365446630784682964762033559201912605760302062088364868635459\ 390390292324697157454524442619756878788663233266561322112019740519283246852451639793771593\ 206307362681986433857626947631009226332157528948285371005080421195171803735287238395202547\ 269223770297680850574127650557535454455427401869672550034479428754999428036033669871990384\ 510196046129592968674606658798481273472351773017034892022020988095935768275603124329977047\ 838763848697611156888533626462642073091432521561912987239986941702649559581349730678417682\ 355718558425961323339911632966742919353221784218735302656395319047051945061982358737070769\ 510321467219860769866074137894737977034648704626895017104249139566366650317801456644376831\ 389798827522684363788872591676137347121934335310400760554113773999284845211092169421968890\ 671909550213068021666755832550328289035750977073557350519290234841892503422832394074147570\ 591842096108057534752860117714819782571354253437645073446219756813157254877214480943141156\ 792647064660638369082932592197115303735325863455451424169878012854599152551102995607242975\ 116809463991353832197453847719926431094928543484775207122425417875664729230204685314106264\ 606364349772341956109676681696406311672763131889500704416221618080540456408481540623014621\ 787432536764857076533929089180919746400922117770167922046337795765038156365598336426818232\ 668106868082310907664130143807191097772018896556421296241771530603434584026973770708716646\ 817517324656295546006385163808284134981461377312364106964746102189534900288647587114693758\ 592222731704110487350156281431680785551440905762600140434334896372843694594800663485171725\ 782519582316475319657087419537746961544360544186768639770688649308177070281841383024184674\ 032312443326736561331586029649627837280618049168359381888144392479537209413413924697546123\ 471854261721854110491534633932574196916822771550234181058265859179178480589642412766760048\ 686436659622845015905029305675602563207659014253282438922239828112138461776542525873740407\ 044729320734752709269125478911007727356465392994587582551276652475101272762396788205755586\ 325147999748246797702240171110654692348077618117866152991197014880884679202570527335266841\ 312097891893655124766776638133188153761444131895920365067324210642576431050306380798071880\ 272709635423864040774403943418093699946118246003195214749720934769427917501680783625496571\ 522190318812851081757446517993374679432887228465587185942636136088079742389640753565867024\ 975047383863325890222215732354705250680504888126277215145708167274145082471433274680263506\ 083496190757223456938214801526043209997615995113523983035768332095568461557969189579222141\ 755108757961880297848955753766992421277152015116391642081014514527563183543679116583012252\ 071818050391105870188457923819197178235713539286718637680715437314628493399702401399381289\ 494798567927848715726488838661601170967643065787270264334744213901181021125299186681144100\ 635807434606225751556250975071742019317408924192797953573501504984607115486614080565316119\ 692578815465282258773926062710644523784610800619647723741093242455001265672989459619787194\ 366166229846884589067820368225294886575126469530697468347193771102513570006700373988479128\ 443083924608368477485719253797570419054332110010952697806510107119222102788544716365053098\ 734645778752909620085040875189830097827038839834363039967300129898560070731879136375327191\ 359060448392494903504381709259627367364041377787297208728252309493718121551179890697745790\ 544792154917441604880851650361646312150392974125006655338358462280123551758011378887534494\ 196040518211464005116874673562866673475328086495102286687307549443216277381902616772517484\ 325598685727392304321981249782254805365307250582455889224995466434813450484179250065757059\ 759325138423101028977975988241037725983492749627798363674266557147114170676950613414276829\ 696949084990911364005382269567011213808092530314901394858564686206200534996680674679036188\ 642499445992532830390106323764157021450378857629571051811826358396421003912169819749572245\ 009060238232771389698413240243196586371275011178807445339870155495298247450812452940264052\ 335305073592488412564483917944891488943268321172043911249597933939548886927863041360140671\ 049565541664193521912960520501361332954315410254148541189004238211957020612017427402006816\ 912302303861443642561824993280473177658606280250349275645076752703196674142452177354849778\ 513652396790965654167491227636426196200262971011672916578206450951654726221537079636240536\ 342283257661428775203963485904396447062487145377232557755187862343205777577275739211138481\ 709654948115642025441544363827544733656712298687906620988344616934588051885248539287482740\ 467315208672849921202321760216289674798394688269511172584758385972325928096561907448638736\ 598492667817593732537340626082227919830153554711240181160920421247885495200183581085241516\ 859619335473064301851839286893698331331586326948017262429827836393499401039147396381078038\ 673937910310619226715335909406209770292514376816432738106490032150680524133055378011113149\ 658959094340301068819375316444489789190918002115102333413727705953618112896537143925030823\ 346240870710783862948563892867861466338852956385663973857502724888566549214868994438965804\ 730336689235251285715969961131729373230673669686268623578363216017370873012441922577331109\ 432652775806415420772803669288082686648663821796644463197964096968966090462846340801920037\ 557732603830286400744114455843602786259976791449699600712746640501783834021183436551626379\ 695899093105394862402918235991209132416280368778666994149484456615560608925656025276159782\ 472291632234189739498535953086540047609468568651133830984189174333478553809087549074451911\ 267256366597265750451866647976164986642761848158975240809333781437954309284676537638215266\ 354263491429839750207163347404013731301580811987476586746120205323060056596262860098445829\ 838501930622923036709957126725674972781495741956145344785887006147693396164813952595998057\ 431642875763892083247054355508345155443581623840095242080257826391693325741985320590544364\ 040278631048232330233368751985379464347690754266889701848014091461620082286155557862507678\ 320227385190144770047639627727317743245792243094218220234964823318705052880366387550103327\ 493430276334565777896521293817045246910958112217305002945373555765195923067061780598999756\ 269966518380084929111009279607833372893872614622527373001788279937609365480848911594722539\ 079009774048740735922336372501079005004806890075978338921553472201636471889647407805445797\ 319392360472506112793746976543307618689438939225037254869679115036576125579333152304669595\ 180197461253934341239233766404550124848151131635527388492756058704479353199809769421548763\ 526674900157463899772526407262043074524708701349939301890819271756827275720197608119035414\ 086910206795005694796343168501083228039171907010437524071865040769154692338860123410310851\ 999013454519680593076181829717986236803857240052699301300927245848923363902994247234908091\ 388859856830900278098084857494075531347421018381441392450038758605751463993103189933876570\ 183392123698303065764961904182440053660430761810177601950410195262111518515776692899888535\ 960818081330249534432537279464393367059721053122438496765455782697072555490150350526512151\ 571745242895613248121320999361550515838925262987938675843469955378031066132045548170377469\ 236887034206754938885176324504579469293949715011806239576997599340014847562368098307304241\ 480358500032508946168981363469195731024993670575085131023219727403597607931796501362210066\ 524037570786958727299979992944582032429483324207137895944520601732008112372265913982395698\ 569155175394556370496670243328403189584578540153005457993917147629039573125477715212979584\ 557565350071191960504199404659346487744804427773158351577252797699033206925252991811857492\ 659581463504741401902958354851571265839141895596717647577498656083081879383689810953080285\ 674464507635428014763423287888777919731368625861399875158533112122632341394487203902348972\ 256165072434548847070245708700552285215965286682907853461308150479765913265712723699868846\ 829003935808359163472546502719347563245103198402225146056426997549257958165488252143848507\ 965720422699424135702389175911017471708135540476289612142147580303068632502975631529371846\ 479032019789500836432511845420758259513706509837445112872422692506598228070652684757870970\ 887166804148257196201038163588711858319345190416895648465704054061946228124577536736767921\ 384059532218459999319514167259010360715840231304973558992717477230312573403740593267887405\ 289691642438254254620048916021880986836735894557147007934759085183732551756147297848085525\ 883101804487877645429751497060991980501091821060102776229443276428862477940081812488976720\ 623596372740267596864002090310940865547723260948403061195127591562466913546958146219359050\ 724563157264006757498937110303046532348020005279776821578402287206162547004615383806992496\ 770569088386151413115699234281365117955827592634298769152730217878350716899736155084561568\ 785094072398259807592104591857527601827570129236978623004734949640975871608762732123474228\ 511029056580594076993397195399768911739490210239441049202862185518262699797686556038119275\ 818097518778674509279690848195687333160664175674991897648920926591425382771209234714161254\ 841676684644620190246371714041626626952289890266054793332933827730627702734471536471318429\ 952299538886281072690904637007435488161140930022124860605032158100651349785725079682669117\ 039307823560438815878271751293811821102416414181436458964128671543701759157344111443146385\ 184894302235637473347850644934427464179289666675265625119438530296142084553855330221763549\ 858402702115760128747315091022246650368754418078041848910688903519262778576169741505955354\ 628019523508289661066599191310312748711703412918634225552579291052845750678256883178660337\ 156888901697918960422205401339389568539708056132919691946907035397884451522501289341864151\ 095025351089695470757358617199418799130378787380809423625338599946665329564465154607123191\ 271657432765653119866964767708947784853663873498876926748918918890417328510911739780936805\ 979460664302599140949951756422765724305833339967071058618769783425664173481110831392482043\ 450712632106431909708139183020558699919414081386895303177049444661352889343887461656005802\ 380100658863200059290966388311728627792142717882990681617725324492610707294180781635550195\ 229474400841228058121988848094168820437958263755801289970702575422418234492729955131308871\ 798999792745914569724474538071608076553107266819644558569631798554129808933927847360545846\ 096475341046864039724558906590345935327627373911110604944201141970970293612636627825437505\ 621976417961334916210017438739953280730358953221992110835702738234729837769941926725884517\ 412625953843585072131216524566301065840845120478969391020577249488056861959404288127438410\ 366343144187297331721859118675031147531671716426543662003454454880641290766378804516806790\ 604977738102141497564924917460712588166032299685390680932970648435294971205701917921630676\ 589085528316762798081020691763976267313494346210274410685955161691894860312253344233674175\ 443185467844610445770937767035287264423396389593322835118391118529776775308615548986524126\ 318010149414940060145294589843413247006073001190302404763881320615008397903248620428838571\ 279193879714584103693717912584829817870739618490643071397611147734534323967837564196123124\ 607612984725669164800208253914282965145876514204508027137675553607645281482172846475741271\ 385702201891186930807991766802340402017391537475135846512493555657217759757024089537023887\ 735712809678631175640611364103413010595826740612412341669738052661954213165773048066163823\ 728947687671751542716161572343218359419301960330711067555026010120400310373548053702766411\ 342439956011202586726179197992970695834225719987188425294931942410515638846466046073811250\ 955220927246436011448069885653563043878553090060869822595627590466954638453686882573178035\ 834501363805454193548256192126797321069306504317400655088778571742138056630135847475568959\ 197329957396149140549891282354727287487287286075917709721265053011857248487602234743710441\ 647858952560964252632287187053493715337171356860974098093547235616190518764811203539862692\ 126260758077198916465861518957656835075570863452139847953361990742990594046643357528872230\ 657576027914788751403867882027996257995236423144087898005805027932118657403495784954662207\ 217841274048291431288876723415689157707432387821239761938033982412388674711006670793787971\ 824359949663724637426896627527216920408949696642740201814396573218395168760056849714778977\ 888273919286371480654420111414559770062851682518157558601353135051070297634872684731481464\ 000978667664872464190432708102345022188650880454219610858445076512367336983506012736743269\ 301922364722306547372685517085486590229982472635809900898316836790729634150053651274692202\ 179238767779608985745388091142218149039376436967300361770212026692298937333927883257809861\ 104078209255316057841974744904305137716982457077753308660729847356708049984007840089326429\ 156965772826064363340946721258938893184056828886055215185292211062304193498218141239963274\ 611901266887699085270304273224173321592265167775809989021623807831027704859056035819040888\ 421073258726989182945455350823730109087556894891940002210083178673444436493754278811046932\ 563893678036602097206254887786701544202351263621146258269570218296401468288758130274817224\ 032826921495766150325902759200539352680118950469976011433268757090317371025186099470062155\ 691389861772041182887275494141419162787065650372657881036669694242264266002086891214494583\ 155175421499960564023228833194541072954702462657587628499778468978078063993177796731428742\ 305484733164927739935471533816669701807467556756470587591692153979251180526301383817552171\ 049866886296197135913547210730486905795383585174803858974597879686167760390173446515329167\ 684037073629831072574683554026159596520054505105801272431022629158950755665171190730111004\ 050134775774442170700306193023287723407757102902274260716295647044804173093717223435042268\ 180857336743435700734620922460431908930336945993786806428663374200096316444995796478225414\ 719520110200542150454148750187613650361836739564930385589820473578635112532833380735774015\ 611495716687247191064160039999860218942000838808540659492564592254467900925578984603010217\ 841675777320562921253764320615544454001862607748124457158961047351157202560125354902157927\ 690565578760523612277121129842037632214563694994691063764334406007611416352909488764293140\ 681809497857461047120506456459119629591489023665289301739864087334889136453476391425842696\ 307306245331833408061218128239355435153572253406478742542278366306143669599730991051816096\ 346234468947078160917257389997041300805664324193697370755079686534663875324567420384897987\ 117850618345029868728208234709152517062885308245701652362935518301444633691429079072701270\ 076878762283071891281789153928317576135282202769890768179945097331209478984951419117677524\ 587414096802301149376098676256437001952319042336651502160013420464951294296693958346472647\ 216771968178724529492553840063071730382769977216478751829961531179222154763663549287285007\ 335699017900194814964443850091849498577317319037854635026493073706534199798436718163590808\ 617626279810335312955850896044109139381007053986175822651572706804624823144685163810257820\ 431222553228641126122675553821064549377702800358866307419646480488044777435468449416828907\ 843136130474151217991658848487790363719862252654862988512963172279987620886068706195953785\ 478860110105736433023682497991808315624695758888565878252765727538270456670209767453195005\ 856610533648758899184340343203088188950565338474300310121612405881981519044559029732797629\ 985387804673372021865549710245972682447650420609456365568078882753019050923233461745272866\ 126046404517642461926079440230091520658746020929433702930876540356361347652270415274429326\ 858485326503739240807473781035412177426508198708777178117967233534711855404374385572900786\ 929051090292797060898091460703314330649781321083708363556558131004453337853946812372053230\ 584150362150952998834607724154550919510781200452005056593918148695214354836147460067540172\ 455221663950215520059019567067508534489433392654446854618091802117398340588791552429404958\ 495858467989811649978576025161892065965861726516153818109184942995895339432778430154706156\ 742508022982540928331670507720150811710566301104206966424372745268365743115098571904034188\ 002511458732781830857188632853089611964055194292339791443096102943764704692829034811146490\ 022425979629967459653284995220636842721930029135094449259338748926767297216681523757170677\ 395828416492926826136279788983538989324906427569574419041593162139201162210943138532741498\ 265591414239111356150420308298443203872259935107680953348018281186356912391776599585195639\ 607748926001426572039286928056393714740992725730409421626408477697293386228377856752752080\ 791916921182144424470331835992753383091736163964686654988118523683047077003167230592915173\ 162673873090526822560054702676817135824264171915909001763885869348176413636292371044757674\ 031223486496985484964866743146004358987245620296033487612366399065226325093793462980274593\ 320059836729741671194016052948223848072929022229398982841468228867988956796599061865666762\ 651300582895693509863784022551239327520516861119647103429451736226075559495683697020746631\ 639745260808335467407342728006416320269114363286028289075613986332989055315461064262262314\ 347782070502623430810441509326399360038754985377030453767137740644340491945197610870429438\ 874534163955044196389378695349569419561919439371979674222818594441392674754734874089336871\ 923919204055228289583882476363817105114330732181823134021512587634502288570467559224287018\ 932111860801214140368389716733806187768527623090335771856386326541048449498760570336914166\ 540724692559127717624004675264616966876905180303490067695478898583424316266125883882537487\ 121598596508690730367168211656251181844152303190222265528476519436396814701329897592988556\ 331347250485258822371808777935776439400799135464738921902049524882822399177875031583336218\ 272249398325371292067296108827609987950376997607162083672541284494064524432626723288511241\ 199263859580280057754500869867744265669429549911411014035305739247304978730874499493060907\ 500279078463304055208818664390294181362479146540712280908310744349858743364963217097940009\ 344630331243485707148103478709104731474856403670247898351739007101217894064267466407060871\ 355816451231181972620277436347954498607371002664567896759580439418159411298587597818676004\ 320086476245724833178699607189518918756384756620326010730808823068268769410353096478687342\ 991155182120180002391339945872371047711652613667972855501300209878008837745725020020449182\ 960702104752579881890976138327205006030681582365911432592773216883725220343917450775374387\ 174719227949462339207560301307685982231815505384963065659403122366933009938682631948320147\ 158261271411763704891280946420735792043182475549432523033916713045161583207005520969324010\ 248465229310542471517459983976054894394388603120473296232023165464072990975646579076838416\ 246502916787444830905249063793397834755053479378122277179828727001527558545903253000948852\ 309294710377553533617935804469267391517603182973152071173438559571173693843447879546891845\ 668304589602225570626816849809546323158837883551840985387300406182675950179723944167978289\ 325253215356741951582916862368490401127020773881086432506945600122472035299054335642600538\ 252095241060931670802877146423268346074187824900869803676128719888308907964426609783711000\ 952985923075011940549874867203097428774329304651093502764308698946016245036447872770063404\ 965951519466611586224962390836592002338515392096451431723483982346258068529808169135705967\ 568143221941924443513905679837103915349519812418242716858282239049446678538842284414541939\ 285044498447498718770547072832398000084194823251696761987496826386928118544972855759095968\ 733927371788804108750719544876390869464752928461184163420889108834159762097262639922410396\ 248710923434633669943828983058014647160344088254234820482825625576530995230898983415675178\ 761773928255951771050301463849824256803591455942219710383918155419574448240928019494257051\ 808708868066284020400002587142046737431433470184633440970098818503392002026476466881574067\ 548152483554410826698999348394658844723543329641710913526919243746309721546161892005189758\ 823326619424939976734935518750297230756138979127414943476834427971611704401854645702267015\ 422559827658345323562296635459527725491229196194289805493596270685186808864601290006131061\ 754225332605338332997683531012776910677781914205773134889538339713885721222621679865803420\ 886371257234502020614509330685122535837534639634399379104803393873119367906013305279239820\ 701339546624574011558883381465928843753678003871700917004033202651510648001876171069549404\ 267534159611981518520743163737078672562540904688630923404741223771494103376148982202297756\ 540815978380732039898447113804225576870753507810424112168307262899651919387888612631080725\ 368926365324321222369958732480752719164334622275176707430691477497444333568045550931908110\ 760426659418505729427090120055579185078136722577474031602647851159646922999298060301198719\ 046830682238097860958758095750286123494015355098715076801177321761033366929406514885623226\ 465801779828202468840257971015602321771324132406045507090396712692870920233343183219121110\ 978729588674169456357870807742040770536878483153924957904751725106686136918635301181833367\ 294589050676241100993791979726023853513562091326458555917661391154127214507994986414573754\ 201673304194632787441301748801112111313676036447097213492529359739379132650598555129193565\ 389742486106402237679026084342364892653816026846252030012339950642201152459863259117192047\ 548513084540015771948057924298645386540715055182889806308490106588530885578183795661830208\ 637055584211642754722107425496341602545378694691562536912048054187585704798895177561883614\ 051908912504415586616709395825772538348063433048546650296123322268355330103755276916153729\ 586452409694623550955584359690189071836623820653308785521148508304595750731287277331373745\ 521255589745436016310611521451994498629088452557855436880166272107858745158289720392566564\ 130813123892687123525560203071747941597264333232308538613667037570620185401636095221684389\ 607574634480973084325398870330779074992624991766681456702307268272918319570803798085362418\ 015776488785300320986856423350753156102445517062037694212075250102416181994725948267676239\ 611761523264377198487149150607822152246175857879181082312740385514195352826245287554335747\ 772471679656547923810166637002574113955828331273853143085909845312794744634520753376881150\ 113317318679741677196816122414708323967254168869355872720119854499023272429932478318070622\ 070347806398025175532521002902025500096930551128689561521062697489651400730847905449531983\ 703382870204333189273975106110548717920633454660856051459964370117266591316123697686438606\ 422229702794133899821936916570061141087332462042213434788915266390893942108034644536731584\ 215791551165556504601647624618260664472420788771907675718101377383155966342459828216282071\ 203759676628006096357418319394973106158086312339861663406769102234373979278632645962711019\ 468048400774943182181905522740472684052433445919066000007894025362541679514585951930363769\ 493061855696410274875364527924944954583203771075062512192108111412067129682260705195760561\ 835311731051312069434380577459628861489157539815746192178315418367570716387016525027585617\ 894381030774146862646732840271123651291156395684965926557054591975569227339835915388083255\ 705326150853898664359196174086909825156449055370141717053001931358605784948442280309834708\ 473070514397859067341459675772692577394775905579677922496908727315857614440292177804938891\ 696724181909757391092456225687868168275458442303990284309404790120132650295762840867832583\ 243840547740738206421698988324027956335747832337623424255231576435099703998089149326989703\ 879671203666849498462447157449937944270508934896466806276250455983903149225150424218867470\ 174728802719326603681799236496569665826484927438563904140616988520202950619176731926136369\ 203244221754213130116613482719853138675720738854706634636716097772602517925925900592841000\ 488523714968528788023809136918518999004029094118949571447534428760551356034789203919375207\ 182588051626772141251268230983521338784196512583951772855035698222962792341097653981266456\ 857524061478560926998076832946807977099181494803395421318776423673098600434370778132171592\ 807643677011376022362593016883457365906193359753862143750653766198495862483231879306501456\ 111820751088197755095372432835081839718650147333176819608538556245765388983393312199523722\ 015204500904265497934755546233756539908381159642194181900736626457264770261902557976628146\ 977896476851416753283177325052085381168546074893595217671769199142888998726872236556183772\ 101310684120351923168249424523101962680914022495861929152460000831608153277783973680097512\ 509731750179981842914722967901323572145086668510498230419864623682638605039947956425856368\ 418767239654042611130860537045539076988620642926865059601627342950080156075586128170250107\ 051230549776064573991061340693122762942801350607920597959210004251157029520464724837878693\ 230465234040603181008202642158149664967745232430241969941493891041487556964612716940819718\ 670472624412756928279541840517467710404977051025267123824375966330658298218784884430117213\ 475989644684681202779795569637483890276857356155897187304430963586341767349854429944905263\ 668351408385677754039507456102238318671409082709314023782434886308442472490244863447364842\ 038802127824978136209384196653551832676752374392513909866126418853883797894022977619610496\ 146237938155834358951795691350005335262159957657038722756293291472375900581390993077842605\ 757145100663122606882887906775320233238629535914957896316286537453839147790690552679490942\ 922881935371740374474531539918059684292199363986239806962004602211839502416543750689227873\ 688975488355981434423885872328774020723193114042877469753462953402826010092416840362401397\ 504982535418961020301218487151679097676143485678665520087690884245933013319103887621781902\ 896264243063265352580458470488515503069621813999301649424159716945248166375815958857014459\ 206479940315162010721514438658983724783902266231728879802130197914465635814083094658908610\ 857020562786731176990749266016849721570969456950757165003307046884491747521141162508095672\ 476600768668856423564674767166281510808941321701142330759421245665530161366724642566951073\ 626997999524220111096688121062412032818260016054634955049739080614023324282352069102596887\ 159965948129026032013604698842988326897518245586832065540918605534465333286746865162324369\ 400618391397120604020467630804000262917586300377144429909903286499757774051065399344522094\ 986264090656156487790488086620149810365812518032486182592379920314678324174538549476275009\ 399774772625992043555886117746091318117389385168077730472801152411632490345725945325886867\ 440314014076482999649423434192071872173373890512021201655479636035836005831589331300831951\ 827481137919359124844766883595928335869058613256041915762327447318727625462919421315738017\ 743588149534496622928585719334695581485357370009165943026825295715843773190872354936836566\ 995365227701994142506075202554904860380458456065420609822101874032599821441560927368681211\ 138024002416990088297488362117570846114341825101344671633501499532836762376002578311841794\ 788250490545367323761651383521038045843801596683075083660511328668259367520497196751142496\ 693538311770724434559721283442473986198762112670137229631585975307832759154247273897596279\ 301334704690128777634809717808778597392586669254091223753365429441451080419539320728710037\ 293397273491009599562192555572135323212918264613817278817188872273707646511545535399515141\ 713053223615503092137505086124431535942857358083290020420206388699685316852839999113054237\ 178533458533540725024640868602044114576583710021820559134585841752332353893184450031852577\ 643079767623086643699491067649066412248573310280451511725662175396906103846629094105867013\ 314099607194321405397006772430177421410827888617315100273775359221495762563465741809762886\ 898512878449657872986302115459710915392576359403602911072717829761034879509670663031267945\ 722294853171595042883122144997130465159444139934779961406190660556902400151163389906334047\ 508581853973993885251418783553859874606638722157919699199505234329828254530958980975138229\ 059548819075795971610250082191472086913552191731531764713269868692152378519624835106983905\ 282453451736900299103372436331275245198484617086666281895730434988117136803767232895206715\ 986297238932359847214254962713684175218561586627346494658533778662065498532371417089691229\ 734302164567807216995125430339828475225099109446216238156598257814973245036805933250162414\ 281936919631132724975738090171521802683415781010410589781095795848869420513298295351312994\ 488113503992717032418490777489162470467708773501394917258112832074765413560198057097662809\ 484729515699828916277854385716704359948709463530977344414442961420684224127571252042247368\ 815932653118603715412708149140695707026269936802051236397936284470250516107258797451374259\ 994419302632752454440120209135199103811913998119349627192505386930414491429402170509017926\ 391366572842712300025432536562199476239997790580805131117541000673623600551677129223536455\ 171039639121489145752208139852236539593192516400493627363938505189065732724076306416886459\ 700438343601662867063353856281229954078760532759748764243737638940340581040982262093177293\ 189804649942232030822279423384066983840695456192816915076623501648935180540262074311313438\ 916850002461783641525546825178489130319522979150463564002450192728459563836958226364680066\ 992526992802221517791799454513059641086451699398014540599704193039042178245933172430026350\ 317830582010477392503824322375913195132010561769543093781440280281600810214937749763285422\ 905423808032980896514669392036888496182373419168625308782752707236520923247842599286023935\ 171481922445999145970176864113314131965230900081469851800117044355944589770948520379236512\ 261898707507899595929446141623641840338519389568252505156683608290377983800575356722678808\ 016027624777595776042569662807921652505515212031294561122525574770805046520211439272602702\ 092181236352064034582490139038968282604708930450231771001199027638198146967639859017973199\ 859551367060472047187523484301966434120200585451645063317834668865709088502680799226666964\ 646860447444535228576659640840659797134259287908909833667352586289635144521209201065497250\ 846549617600120443914242394801291058407971629544917658850480285166204290087558134764637746\ 483721609263331892141724645136524410389227630303795129735433768632335917494233681745944700\ 905555682741900546604189814017848645403079491085450404421472415599810426108845956692152730\ 566206138466875437805257206096983637809067256237846708142908841886824555486926215116973988\ 788073541088719325487269529063276963948326427575862672390540110777656272662177277064010681\ 377069190444372170886706656612374517403113363207575233262616024710450614594390025371796769\ 962059125867896937674559600724471706824309698881517905453870624893030514966999687223886368\ 264475498335049998537370190757898943298766487124720607512704220299039293205609631146923395\ 662390989357638174532214393140340492900622403980501016386160677353321995180961870470981470\ 023588231727927626953794444436053906507574387808908190340838585124762817907073448628160008\ 020398196453264657110130331874264894736312853514924581785520665634202246622768532337408749\ 811878918484311289202968663422213320804329669679081813375059368645952783461280900259346401\ 492226879770639766100589430418477869164099098712065410266215665828036938099050347288377241\ 917652204649388244145039808357373837186081979337602960355049923486605906381725354416084810\ 946039596133153573164932532491196192433452943221106069696434844811092122094764642368518169\ 559142490444550312110969435091258254153290278524242794151085909074662376002809685280133235\ 390969472711878726514072920602026151463072479243766002394515969170595006464935140335279764\ 194890629810771448279415119170357383439994989045608296501057557578237749540378711973031195\ 822754262836365390967967033673321223831167153385399960661627161340923764422173907199844683\ 224368593054226069109027103578929522927794934610975877668250154604288693637279724497764377\ 421470901759468234178507556124567211283942906145011235686141670822060422600738735963839764\ 904153606549575023367248905371352928379989184562769664575659219497377762167994708394387121\ 250065095633483793000193249122572343010183588742566720885247268863397320192551339470272013\ 085284145531781960533577712938389227976626646482160889084488322722435844672488147175135054\ 159770500107789997132915605021576005593622692796003066327031798844309870081750148242731032\ 600054394860118920869948225479822920975012126810185441573502543180594068375175285821024410\ 436131650449488281488578639591859987799612000522989863643937715873782565805735488736338761\ 192967242242555165549843271602716538490872836504225731031392758723676482401349954850357272\ 966537375247570949165493377201649261560487210333528471502717259401067614908414871097148315\ 491275013885782993547166933266025670932325409126015275650309709077244478473795599456198172\ 298865080329894216832414431625512880838572524102257630954742870429671845727900241005797182\ 877625677991041220335637131836739369414585713856889534546766989995660497342368528418061679\ 546795138408232750573418514727558619750188191469273653428772523872210341239737915673923248\ 592935707513816819073987227970033528087737555618467179918988902469768004086328743941228785\ 031819817601198632662232102201951853996028281009809302521128048123012095576382081107774052\ 035467469749008110580159811668802228455347350456732849104498418776014468403576321672379464\ 945123869368882621572271342235648016365176379652496307869608407398582399671145142959346581\ 528743344382476888319524588513888449226522291464864867191294789210314146150284038952254427\ 537664973224479674864859325325518145915296495490360328491854707075535250172016822724392956\ 377475065489309918228080528623990565151369329508800726409539544360775515962185392803500547\ 143965256985172220610355941149289153583177715027143866812909531677824435452149388880116460\ 266794604029382762657190213378638129654565823608724082328938939269204159915652813667722777\ 169261650980247742597371691851417984313770874239495006450927263291777690819639456151812122\ 195362134266019370177233861948117253812989788953646106809805868151327793680682587840731046\ 060556610003247706697657215671391846976474290212554995001238918924690805528595299016047896\ 011785438958301442536196826367326045483276315210046557489155153638529198346854778150366413\ 13203423185070990681268388596224531260264663483490569412", "-1072886528964602468763814059009904508014133318304867541510165207934389161532591989776328\ 690432876813004121271071261853651495309404705438348339419067798831979321818034739406091382\ 748030878507569254284256796377123007942881471894729435871950373200002861892706831689914874\ 333999159043586247134920165452925374562913180066132557313458003721730019009101787228316835\ 929646503307865911464933114731303380750849415007888604576931708910810725233979541512928438\ 179115683504901592600024386445201762563350113395680656604244185957468761475543304208735907\ 799358712352980442404749529644368144399174061689370502697867438236244844348925525750443219\ 566069373340381738885949703556474764030929615093748497478361782752683536563492791049327096\ 096855333302289028550930080415879281926872993128647180656916727630195466996530098696426116\ 502218614031479280766891765530456204458529300017169817715097783754592741636808138092907828\ 768903542350172663514280395847635758977469404183742213057553840654331883918536310017542646\ 588370982981254536880527498761301961061878943034131828066945557799066933805176377024741268\ 873936924112191784529300762687685961481345729104639249226668184018336603043934490956590267\ 409475401699235754101151176185081024075862978244306572366007403197202026325607359813805060\ 129934380896793150152789254784152666712774013225934342571580770339380614468284632241644941\ 834831902014167422931756377078835064805672986713788827628449148508403670470127378105009839\ 324322995308822030493403778080289310270422495829339999545311980561995408286605196469566205\ 595213756196049340516046651105022197810523522322284959936216837487359677213798184860938411\ 849037206016072232992821453838926165910452514666556476259310042533326640387488479357277979\ 635281506658420939205485166084368097544182189277907646602684448904576857632562414881073275\ 164963925599444698176783206868216256725368651026308891502455998853779277688749882165429168\ 024826647819626128730202679886091371462272166219629206967439330899564714209167190492808914\ 633353019623375661262458905957039049255741111822052089699885342604159383681852184762810974\ 817101092102360797012607182272642919837337941616856495178621898578928155890999206217659763\ 275398877533394100234657811801500325090341092897103440876197397161612647019595386621445047\ 062707317560029639650185687499981864187760176643902809761256362387773686188711352579902539\ 429444283302348461778470464409978630255499243858920156900905899158606389501793977542574457\ 134937802441755849190574616029581485621389052450960790512985152517292885513013506488057439\ 782768955702620361636864974627073081056778475260456945759346282784344053426162908954561928\ 200633104395207430556315113882285292818370183574732290730442365278954711274813688074066334\ 221449262857161871224269378905130663512604612822161002336590389158055048658011571431003760\ 956863043904471004425138310892485930479773252338235300882812180806655096615307003041002941\ 449126738368227355360010366583974673513153989969404089586976169867571720875354756225984739\ 817049304883358024826746146421712678878438908806853838198721787278330728069768581473123213\ 413132632603833450592776852065084023317298542779725412147259979930107175460741978725388792\ 380360273819044538629647872632246727523382789979018982169692721814856805076026052583640833\ 091808273549243372354847363924031977505338636751745060417521090869291791688128952051103131\ 259014012483912891661429336580134448017703278445098952233481666529715466249632491263970210\ 745382694865672910875542903271588480714198576145583651021143904352566726195997095214142976\ 527913331270500411287808998883787076914672571881561046712843421512200233068262049491119352\ 615787616115971758651250829471841358761717343881060375300253100581784675242765886360843645\ 145909760685223847526964421867280461191363981802946265750317441563957364818705776613982215\ 327048796976479985267595320527297883505014114615116854109564330795798405361684028294595487\ 368912275668295711804363240154884920089182750284831613406882705101990693314003280189717283\ 267358216911583657789263567027936898201382735149932224842689491850166658783646429113915579\ 339871385430965950032148309511567293065410243428328994634694269385665154519951018023472261\ 234711251093389476606080094143455902781783687651630223382825547203200442507817370575661861\ 563579678673324831907854999896852922812936146381546305234938072735671814262819905039888456\ 150813028093577425581794129364235904752930684615691951662687139252446571234973358534998280\ 197966884159412352403359206078904200530265780051467131732286895030709409168315763573312011\ 607723553786838465754507194784354010877579247279838077618795879688888185033788297132144767\ 774821321036889503210410675535886767821739880781272084435347046186263410839232647445463222\ 597557448917041487616557830313099205628973157482984870620535667250803502893711317764167138\ 851773960775496271468634203467926217828319248235919305022039066721074937032402853729397478\ 175474413916042651327350083667789452764437154996640099236463059245193519405741507619845734\ 054852901962234059652174461384858420071502327738721902988701640059942915676803274983745413\ 766876555610541680818081377950516737626890177044674401712833796401725697845599141291192163\ 329934983144437162778365422808606615293619078797807988371051111269619559959743888145473992\ 376515585651721286590431134923518460015985496186873109935311610862746508410686181657961022\ 006758062144363535894581910460192461083674779124124421571797238287437251752393502473978052\ 683980157269715017347193665688581435433810496429251447197104374358547383180142560838221349\ 789520442508660605847251028551691780887241107988907783485653814182844068783893764443943426\ 674316456353227356821356982302090632004782910160756258898997804622036709328379240158388213\ 914042775445676382962406000262070391721039374512996285113439822344433982382999665661685650\ 657643588580942831844194059459824534068671358067503461636026246686427684085603187518143546\ 144286128135618730589719034080924800125321722022664992062771718613306029144916499083559595\ 312289444641132834452319859930627870915841343494830300784023511760618532156780708441766264\ 188093792488438465520932276953698168863146785339766182135715049288302677005768223524127018\ 480633663325054810052848337041195320585445219331931043307794366274587050468192351488901850\ 168234598879161976847440648949558738461876625732136035229739031015545688512485984781597604\ 092370383344804158403759498786593402717663610418910584980577051939364313495993801676036660\ 724563903985804680975202197607821521926898640033941955905756529411681766321080947465730160\ 368364666007938699628236112178317108093941645913925480837128525489778023962413231137792044\ 569217387580410248514263907963843783021514573477773981776153058250307877024038524589521271\ 568955297324892350618295525023304079783233114983516706778801938541088345074680576523906028\ 509965480197009641726178440231235936614001176046972170941268173193051444886080616443779081\ 884503974768026739378607342396547768678532643415719773349592739119576539396597692070733284\ 057222864005555249223513191080003192056079959060052790385029884165130484477630935437065600\ 785539269378870696778960852691469736852576987855674657959195698773516211435769569454638641\ 458545465547324675134371189961557091101652348107709328788685172874428093249708501103268525\ 939160605172057772817420564562338213867141907377055621384797439870481053568113949033534043\ 080716933340602971534535154078778769277007387445070865691799465808431660366840297547593364\ 259082504645025471341988422655790003347008185147121939116117050513928117358914084392413876\ 285160744252954121115220449342395095602275425239025349383506129474332348263359151591752080\ 851323688493478895882133454510745726654530166068397710380286451470911424813808053498650368\ 276265962003684876515198858140454837743410424278144584313308589019430400429614145786262227\ 208450325033700511999469468170012169240775968310614811202773975188143527583177614412822919\ 538720583704324811319606520963953872809317875286164204339025471576698227072539441558716625\ 653335449885894341138517782803875370269705058196280987836390197295413941437768301647915496\ 164713166499847948911836904036632999364927073127412173570161054712129644279802705977790288\ 920202840738407150068313756947329622127818494285385460481037345755035540660415172166172423\ 200084324069461470584735249202967642481295153553325537904838392890691897284418596770707624\ 348701252411808013568088948001605917510419357329534448944307518441690824311929589201706589\ 214176803583894700375091106786751716595124437598498799306007293455828734867367362381936044\ 491749397756221569439183975100566386584866905301714949996268673411298446070016554446099690\ 819534890403830250636760175272914667852838814940336746579195760295398606117618273703773452\ 110553731280686649851504858947895624253340562542221313373254355679212006102173214764500386\ 760994721623144212994369513811644426738480612210300900456084123194222413177158741586349141\ 437715321591894181572184524135153388261344825416402128719730484766434458174868839632172396\ 446391590690735849895777360844492667751832990095484726657134736860176920442551029823444750\ 797491364251273230099054029184927223399162472348946834223040230823643491762174450998199329\ 240056704628481770579846848678013595124909759516733561970356436294866578815923647374092377\ 188787429229387468791157332478379287320352834510032227698712528628885645029488997379355275\ 067195494729255967841725132841437536664991153189615602975752154288226149859277644104413093\ 563452628009334720118190898769685929449723817272644954784712454901807051460316560032344983\ 451278264777308221230186260473387140000534468354210380789891883759998960570807284658152482\ 154481140013484103160080828852252539056754138740449691285928802524607664025138798135523245\ 948669997928835527245239854016085258498816740251651332042362153972226254740313345386332645\ 485672627918373982018984567891133069177580860920150775027749816164291844762898648655097714\ 819763867110663610241406686971028957318521180263559695658320235104104090200625906759937379\ 140884313098196215766548994699792876728085301556485980670263467925122643629999455795008022\ 649758218275423143036233804759287418282756171409129171476521964147601651682824758875416077\ 400714009251755163132944915076526291061978886440176263364989812742494251943167340328040002\ 739795598124749584778401233706723236735849822270252316811809615436974119217607791264865190\ 969317514034409966401365453657826296547152714038356064814006959356426577995034416500559492\ 730288813050908649336330183265417979942855474782345457098204089862348646931115200235645131\ 343998972334353343648328329613875250881500918152409342443960666085820909557500948426782885\ 489855269250960242312994132398724721884746117128058514828157464805350801794932316114935927\ 093917864867805137437719339383967160005298460928134138061283401364970115614863493653038451\ 342292850297609024159336677644157231543944703887159965961281900871810874008267503683845727\ 594868465323316700073679426980648534848992708977281046261503925916515073718205087246827318\ 487371778405088522666440768343684374869856297639436516932309680193696461679715736962992094\ 601281450743823561858498359391602938845229860627170887335834961140746868819881767037465005\ 375534147915574885803200951762400006064036304707254950653237074927262773597517151332552829\ 948820125079820502169975474854664538681022449104065663140260545341378300651317356610921768\ 587665423121464714932068478292992864123953972032207951858244227174089925005047699912274455\ 557586659256647811944146879410482600579038855013117923641873345521005781916061553399614662\ 783900301590880190915599250607770961909655890568140119313630546538029111211276074579809058\ 196294492258758144260851074484410628321514372070685973654389299806719775770088300096423603\ 738579921134008538377550184054866147562635795232396558825353810138686939867082227578014873\ 060608376647402299848946279281793459211227008662034612999610727389355129946445998090013257\ 948246206017757520577530270955576537745056817650345771040682219229680589374920599380427286\ 460186281458617615618153062335534507840502904723078291459998991168192722350964745909735742\ 527745069992680668498511720978151581184913669673363826330207177298556106201611559484232365\ 766964214027981379842675338862608576140361326243954804737929355231543626456064579525843557\ 752327010948645742500300518667150619933978951529276434896296943055528869025337822419867277\ 807926208423315624862164290513918528189566223174769312797093470125617367907744458452449059\ 130683274639664758718397108697850825086593769089636730436385684306451450531276184780872230\ 230378697758633686351015438834086114637335639812841525921600147682801475399348914787236619\ 074640903479960574687470695359455192915516458380783669974170987209828160396377053956411851\ 125549656749094190039591213424375356365599531373025886140818526758624947379214400417194677\ 173828700447596090747597802756063769474573778242061000146949471753518178740793795492000151\ 469858630511085283440284191659300428237655354556407566147031581636196409392414814440901564\ 382222952027485676447881500240333707835786753832622287215821321391335837924027878085098480\ 518552670508809808696321387037909959568985721575394669533061186710721841699935329400869218\ 084515116616896525103567782446955242827340497504898000573173138719316545408200437488492139\ 258757686550551906134450403818386369969017158857574046576916551115163382802866826244880142\ 289650134358618472612532630792031985394917395953666057621263076300723568367855993981275352\ 727665747619793673118525185824047828498123189540498938348327112314284997086780678679991345\ 026767532494288729412407577184733305761627050605791963837359110354491277108813401616954874\ 384948949341150337482347438078984731668978835771706889622227614339845950309170566489787354\ 378119190972597722669839877569905166236462562142056224286652222933393016864111698673996393\ 134784241308225692477593956386414829565357946970979390864895293046983493522184433285998523\ 926033322982767997839129784462158925435241144091394530860850125151926701539986943120482763\ 963265958818528504183844497407159778915616671613335627707433311969989212453363125291927586\ 982305074970014750757927912474582810412563786171994713090400077367618749812487755132167017\ 482627030083136050777868556563900001676108136923018904546962771470307072487722358501371451\ 712972960534701067630780126830373863826162966157189663343852255454377604183383534031251190\ 142456293295655591754023033032357940683832073867992848926608015525159659409933579050812267\ 760248522256559641865577452362215029845764565883572121750894013672156985148184404652734455\ 464404536125985814369748235954857575692138310808391963788478721136132534081140986240533172\ 613920353339971389037021294634985478932663661277407630405875789909428734717696127768010030\ 740818748802480694633696771750578178842519074383364080691350449981424307402877808700610337\ 354599206330934322481434326035600205852124537397441108989312571074097879305074700243185139\ 849408660131959012510191346873083300939089048668140828570468498578666148806549205225889347\ 000476912477131554039207141113748409558908817789701576152421960635460413591059937472342795\ 601704823675931372928017224372749088005188242537454952388226728117611394504915232084312018\ 405464345827021792391381165058518299028285250332412823105746285352951036173890953019340593\ 902980367308448242252827718012660549337736161623623929718204867950089989585425551065436337\ 597857204671880959288416109911627938519477160758267162459761438600549123591595945507578526\ 882628831092945482542442511460331014927915449804991638580040805718881140276853834627657622\ 864247156210198825097868786282355275515411362783584072692353517238980899449878326352672281\ 290681099994592349129620236230142799261990010794713081390989660876907359707556415064655959\ 277726133881726736187694957408341354949957430226373778610208163092622689044207630785547496\ 434731521467183375528329052945150656807873842357642766313977696659769907477959182339073539\ 693477284463046659260404833788376975944344825425891534405719117126035425164976282663121212\ 830658108909708739278643076041349359725621553896942700985033951159307623361120272358269251\ 999835997572594080386919575963113952601248775487555616191220024471887390136276452493287770\ 930482407367206566384302603967498005384194726149228010939368518846420502266806995296255362\ 285992293304294698487525288864946507808814324086157787285978004603866418154469892748664491\ 614574200312114043395720070957748256247347067023849672642511538831726531037624762188875841\ 724382449265187602848228481864060306344228596346895264778822587279205297897450321323735694\ 332114355431586127663006787204014075672003309259496568847552698414577575457993177028966606\ 844058321141138462231931804303275635678541048746694655585032626716199226880527682597284129\ 638541879751034079964150236485313911426943056274632945767220805667053728708184786038967270\ 952050363153293235459658937587940433144005313282895416426694930163761205351066317966412537\ 443942707531619327793237029282285603660992570108965940494478021866888402913187724270531831\ 455607585727312202704678204396127770006314081962871646069209340578252824270574111214246455\ 409197142803426095032528479462194806768210821362157000555511391486648371888279300714040096\ 924881295867876301818429709141243165532801954011439696044380386177664503397310212447977067\ 118111216452137811020404929527467776236218879426959251197938434764276673923606250094419338\ 795580124723083282518220174692801265233628355444816295637902605101125956378641140094600241\ 322238831442035803459870819229950481487243525738744013231968777729319055401681943221791987\ 980594453997809968524889879486902046587035262467506414666743872244172322728026292408738651\ 022693176083674526295322115423352298869152301508745399650002265999413596444791333669219067\ 858851614013547915650705616040810573288459232477906293124289281130733551778325646820662513\ 169565265735285687722957994227127176898294274160592491811221465695073360005962980109858814\ 570901408129503159809199241780216564478092358180769703254694634595092383516369047811720593\ 560636314223762389349742572510982774760276547153055179530098789459102151396056511837366579\ 845354196213391232740899324842769170301211431805110563237378128314831328324712422281518834\ 421657518737115206894642201728410698046417840425985412307843391879882935991530088868156488\ 401434342253963479012381768210255561346125356801515024910100096261622034257633222298011860\ 462877485317452607727592797381817348632863818353680451229803159658409024059564192321972762\ 801220943187503097637901285880048696322730260696176839893693072825973848181187219835010376\ 206710211317551184417012100033081733286147776232743507709180191364835550569525911762167173\ 043820550536715050002589954301230159480685578438399676614589677709143096664047740748739521\ 179269008893681385087867494236577552671228670524996375589456641335381476711235487092202663\ 080058863177199597505455192780070609700144500286898959337478153521259393587458990631282664\ 411814516633325598657885905912833741884019404971520088181565367307289500709391996616349595\ 229035577645522444974967499460314632965222400510732866829500085149639243240640082354708095\ 681311950812140638108428906011047099690324536131136491101432427335586286662326989995632588\ 546527292997263111092455268305424148708566445166669560077591603920076691167905756580442736\ 093811270942777884437820956585399489003724215775858631900423468355504477313641568241699999\ 788809587822983743086173943574358467810290348561024254049613348370946880654015723576061021\ 102949319943338922703592613764914999369063069975332683122622683809387551216760044500718329\ 927190534742675628698657282232367729958477899450751655023196622085079673833042212225694060\ 578893598362050220300793096007706059819493378053847442002942356456737750537164421041857968\ 352418351021406371882070843386657415447438953671815808835136362496480413909027139873624123\ 213211826486641045461815785402730032246520007331066598087411548826779431860778074402569719\ 357253013305550800153230050202803832093602230689187089669007142690511070976668196930432628\ 288789441789057306093323031046594728804875718845372509367709356499600922772476815139090389\ 955945970056272353461325864091797670575081528172943818011147193437284998385974882494733749\ 046697962202541761972624316315558401525237235091248204924783346178389125226526889470846196\ 654300761646644283723703493077393880715365713210116389187989751449317161616106570495339159\ 340783648478575075083459063412325467807206719259832515217494737579868472254421833000300989\ 109453460574004053101310403202446987595803540234692988515266902711772207673095823960894327\ 536398987560017218601088296043156499974099915822605854046700034188007558358931991132378884\ 941818244761625680619172285826378284125677970450095023113727823295581111436528138129155487\ 917841691588887047690695133043165075637698533471262923691260994015859897547369987743838656\ 317369939994790188049601491542941618501766464937204079204588019248973288458557418301303009\ 332998273347857601348775974939627850134812727096979894738053039324606134692004276445852371\ 456994256190702917036394481525546924262320879989812883799385118194367359589300009595518215\ 885236965144277904710297295969899500791778069333738589612526524735311502142650183467333386\ 812210029684732018997108809660845005456217580373487719060077068755774065269765893612628115\ 240818521185179069460595342256452226185287667617254514407282318987352576485302417325851378\ 876170513471947730507948966816120215942719167737297287479290278698950759006170181604784701\ 080742578527753717761019504973439320745910212537186209159873458124290208984696273780219138\ 358825376934828070892589885415678801719852379950709532278023541651500980572217064884652491\ 336995257178710795382595695147930059486993003925455644123706191759057827606721702588760412\ 087307861509491847930476716497744386404909706753692571069614619644988267320145985204814360\ 666350463183415808088318934867194326939362182656337554803441043740765676874970575306900314\ 934187416216993795160201040601013702902942538910003140700674715540500985477220572964325527\ 073530069191837193043639643328940251342105276797615179462511524150139575744854751571669388\ 646846194697342434115404333568693798631851771467227819934811387408843596916350141228936649\ 038047884243204411974274429223408359586063912167857672706676504656642739530611847281383314\ 281701257973453880189916250416658682409878036171674585981365311853120715537560247175493670\ 236672544535207189202360031038360714400466375707820177567282531454153431913252820498925773\ 754133593800400586739286937409521876621187234505176109947926332449526752233826550432817790\ 590024122636685772700630631651551308531082375570469331491515020175179038662352833511060025\ 103233362609382085357810533928583092166478279397828425821733569880017904040587850559882893\ 760485654432104042255864847197262968669225793719886831261998046044049218034832856960588698\ 998937675252889860014424055455724407387636026004012605493771837618195190545034415030636400\ 994776274558463738709572350831912130149070908860227170448376282947270512328737987165665331\ 914185882039448562370581085367164611722283790829004211582451662414066654973729904764183463\ 195518691762066477114365290555149757768731988676228903915297466801490242638087441096897381\ 267255122584027678892506282320174916228529788122226199782197390663036041659796804933496854\ 700306640167847346747590254007873058527009519570188797737188602728118409327338660452219512\ 722067071752885470935240241679080944216811345310185703564792167483030081246190528414365648\ 843952047198715969729134162592888168788706016376720903664864515890175471380975319057179642\ 971747599626976342389710798989433707786947742146515899760325327418243442106852806767074197\ 196709511297745671106218528067972959859167111189482176886926341120582086933238610360693610\ 318877238911232074877631312451724405771868031645684605269666037253234038714461022498960970\ 143144759411967961141936790886704155134965350032705528140706328551070853008623675234395539\ 257320536045797942846016003655812583980743097353001810835329321571002569605990682149883635\ 815040823820739032070168803969590233935432324779216413885662589377372441066573196305884374\ 431609058954032147708287743256033768038740441907013758321433840178207730849434968969096470\ 169582468703026048040620980357802104807160054674284946580393121698554865813825737809453154\ 670282845168680887197199736138080097554230405575747057123506377987111670792435963694411183\ 041557308908482058206372798286217109441938624854366096189470351434020890464730247720192050\ 873308646157584275667312987489115284284554656178233459347382607732467422403550895930027959\ 627967286245208728948108547186164241942146445298643140206917380348178301028910251582468906\ 424394583379260847829643999243688711127134367756139386942224212896481832142333469586965870\ 832664468469607693346706748598965477802124355492453954257953782063947826254961101262129955\ 409203372242671929939900377672065204030132129325364747061599992654686039072923351902273356\ 171601736967046533947399036795453580498916756406514051060799136169125549776890181970235415\ 589232175578415485846720180164029934629006598921570669659983418488217600421660131746180829\ 954877252747077085608771408900486947195550303865911055592585010980368493226888632993187890\ 603116654641004876651753322203939228299012777171196905927286076828456532605572154809104155\ 381616941815123393726773760603810819559459612704264570285582794451301102332087950453362544\ 012510256960410929163380783606814165577771365866735255752168513859474939726750590861619983\ 720443726111552529863808046697286867726879758640429874852638330215000017337307636586659031\ 659051567364549125682054661638739107968914177936889279179175609541152420442861936421036677\ 656574275636304787148670334376413150600712230205016982846670151698640105612892058026182201\ 840202777401372323835947608258659260989811692131863922846170060121916775639616401975568794\ 146088402493055959409573476849251629720590577635141945091623453520350840856309284682653188\ 651325111915910328346035143747360512672426829068360760765662931614939429177109393279575247\ 496564344906668413171416627233542484782002769057321363832117365285519400706564085510721040\ 056775685254768759538424421937769351103889221742152476992896262159118491838981083541533893\ 209875035573210031453769947258004580824596386382665062772825356343237974493350121979983020\ 797017474651328573089429956588799836795432485479468140383686354285700235164736654787011058\ 628282614660291777569516683176781016098132720217192504912674405892807689453407163113602719\ 928429681830093745282781638222684907222289306412374659516858759799515173136805091793887036\ 952200062281787809595001207738127841889531558786572649929752915898024032850015105226295569\ 902561675215925038089859709348662507570001007322684587374601236711974487928504619049786211\ 744706971680668822809714094789316648038582228559857524985728937069469869891420795429749516\ 873031872122177499207766906842148349143071929030259968783810385006293511776473463872246156\ 985207687712811661822873265976347720916386456901968621229934333274796359184040759538234820\ 135630793909581492493052686781735175289723595946960161789419926944937641212299618367146530\ 322657209520330735293182936032230663835290075546984859183265806914789230347749373214144361\ 111536155027060656208942419937474964993734001078127086065530171502211821405503100257203309\ 880929573767337725896100368219184962323363561898109161054305251937334135318089226349732705\ 801607893553526759348431525529268237099497437979679791851840885513311804865702133628736301\ 637002953592749447074090875066767718906401268714907425769496434990769219455564899677848218\ 127757962580846593223611061314845982888540105328937225960124785101731084562973850628457851\ 297233520893630226542228530145498686458598537500024676434182537321283355333101142279409892\ 259215935487986836911247054691862038030331638227786522062276035369042951955903084154780390\ 257821236398078675739012399381841577623270330618410198693209438149989807681746054041589577\ 510127170294895638402332852767479162765134763936296433563041189391575474379696656896844553\ 965192374590621947688510786417476440647542247609326468254309373121864274847523965748624355\ 150420628591521570104314396129168133442021604342682023610603920016865721794398518710330220\ 355682540919297388945771736342445644000170962548581908767612969497569702292237841420114029\ 781713389461655383815423233540455583237321437408194611758984546508443331544713745681315561\ 031307802794673323104845855894631003790872369683612071245821152822401959894928951615791466\ 825883830316719144306640753624468755615919787888404886875342036881372549887017766857080283\ 581008021659418463767981227632458063967447238136191057135997592441524524934118005976752840\ 551610405213705136287728037592513382619901252716587424799126288959972492934382116029910068\ 439929153503958666526987842030443670749178463515118564409098737901029989872450473197708957\ 088055618450551030974767897043520120559224963086775481325562116003807597322682535381862998\ 430126421312941392400741435900639792053294792674765174464501890568476987135029347984071036\ 824698718962664188090549885338057675168763675824857032030921553538530233537163577360382189\ 366535863983277889362255784805577008648707897611015440985535318611902498119253358632786947\ 858753184990098064985305164811808894060051015868252070450619584752569066249605347281094257\ 065636272582996003131930021970961940745690396362795205216925066460566308578143662493421243\ 860576408093478367737462416151339922019382925124294489430294786058936389596398462355495970\ 037954815059326976208604357454695226782599321702206309627788379741854761185942053087143090\ 467528494787556724505092239598504735538495002378101102743433579588750262322896956936430312\ 816570477938666781833372366758475196630993293052359727271820851556263352399657293536562133\ 825917029099912532424894863615570306831506988881627926011976765012829670425557878648079587\ 681828029731264740120752959984845052766526159389917180696368613729930090415350372058554847\ 749228585626478041601780128498976625044671484757479432345972817231782576028835284687746071\ 291002192051839927966615031636781390847249271570744624105814378649538417259464621979938008\ 493700694125558181861314174196279302504754174253028146756733384153728047307648210932134490\ 521451152532152987425429627658172196596582425980817996485972585947758102100797114073618143\ 291860159954733922921324543840515196435768291409516640918484413120679562455487219650947724\ 778308432540570570045664015584729093311904880872174184167723311684064306591033976276610430\ 387224670869194748078045595091505597021273536393892257815782797282491988268250259948525701\ 483637247343162228042380178696514075102004997328511559779605543531016669844046207478731875\ 396017395884188917096257878403533047746355496024586618882837679753774103387285896750418139\ 132286114599684081242799969532917625639657163678041260943452266704121645901240387725507837\ 178838300382558846125136395465817422710272339724075664550487210858274442535380748912729202\ 140706507882433883891271677846964664699639333253028101659701673475682022913742896899926541\ 407276324212134396140146539213808523383055233340104369396358028512490098811761751716090556\ 907436110634057081250700872342613151369426371305345079527871808955705132057566953122635769\ 146398318335027854985783285683923759691502860111987502232382547288380354032987685639948243\ 024750347084679690974484495221816253484223762698695184482182507606379302492808464961945854\ 033595180701811438840427196212269919267054537803548652923756760920475735620292683520359318\ 011973856032392974309453222387101873250043388606141126280685994918027450162854900022328402\ 748479119134436723714569828905368343082356043605645149822194982463221048216105986236373017\ 534762732623361201367863367424769789540991969905725114849210479654578516502552165932270618\ 952069379637609595681867881550904359166201414469162036867044586074465623733770756041465521\ 738622187537401746538968481556494843972448938316917057227289832638274569993866461385718045\ 958073996097202536765228812105765861253041705976234315163857905593530221206839259818934180\ 519710729243692732236076244358799376652224440861947663386482461618323512594377578323837339\ 362414278649726128948064225593152042947220801373164830440405949703987342569462572632808754\ 702261500103361611133645065875178956107922001945730818689382166064012281278390195885108400\ 604518634275904892626398619433485160981695764032320950332221934787558573929382837504735969\ 773931773902593023836361735434965527739610872021762107540491918975658255067089108142873360\ 654106382824670127797255444840607837260918692506232571934689150143078867214010978861393145\ 186471336515639271890877816097324216998102688088246091475925613850412074045732691630851644\ 176638749053604291423322141143139442423838093431738065543758283257350906197538167047424954\ 907841716003125510564786908916316723217592523809242620191252710528233473819151363735225594\ 195801779718382461276521328040266054683138764243561623383521811128570267123158213578709775\ 172309823443127015860796727024093923837798316876866324003405486955504531185755059868440781\ 164946928750489784535247717956664123298886511483832556385414746193218169983668369481984622\ 215082749744245162570767627241506761366223807390698216752957539502830892214589669367463208\ 397578285076695693473162960914628150930347460367581655750191049529626028450868981734082924\ 836902282558918869955268234692161406410008976036479792139892744779108928186819529561056630\ 804335969986176177348367032404351540988119379371658139912471979657504833511989159400753415\ 506936868212436459251048942967672641923961952341318767579354472339767344382713425445842002\ 487547463102643217092281918603479846392254140463926168017808285363711082931031760033515654\ 320445136958223455850975839014163228169843634886255775940481736735730113445491256963555164\ 915722088048096014938948359647652490179866899344294714285821270839315616734153356013524681\ 621699377149887307586946650276262451186410666474209780131953242885489747625001729504916948\ 095984980509145908555287810352097709842291794740873247863118864543664899249286025390511576\ 779353881114486244657628586842092497091714451535302571823992977382521400792165888072484633\ 530955410058154839740361230671692145915639160855226840439988010717232043470200861075844978\ 518272297833973206890616507688898970387307341520300527790056348853174599392186690584131590\ 581975630670624421722102209739928309350570100421747891060885480907255854667475146039977614\ 731728161100114604852228137064035305553036750252593860247087731493522310878827817356128360\ 873327238090740269821088691780560764713515185623535182633363063779932918319072879312627766\ 497824027922098582925041308559605571599972968655768525209608757102139789238097148853381914\ 715817008193027690734360561133932490260431711236460328853573591756022310063196819276718658\ 977991792598783710483325631109096071865852735119550612388260630465336715050337184444436175\ 480698430379501254955292228383228125083554213110143717877575903205861223522257272747980680\ 711784170402576862944620613364552175607573647022649713428818752932752219552511064075571367\ 681720775384956977731467632744912290429639421213648291639679754464649016256972209523824918\ 899636690434251631511927280595257810454003296396085606227275986697267314866595330615348861\ 389524973571442482501347926954284750488649450090274901229524687898409228258631194978064391\ 215310826264796542145022215774190887543527716131450800603914217562127878510793324710422462\ 090658911121676104610783267235323784268502008784450693730806095661999274394608040023583349\ 190661766054238754353516187165596297204477713746088427713753886004418818874172902694561754\ 345129520234952948509432101587839562983751855458650899923562951279870663743989678430728198\ 594157053087419189223828809637674432936099835173346082717756613153368918511500050192022196\ 197498460809650371630290253546222442436445393543684513174204046432474152251345826045859130\ 156289734397819349701201005466509510214008384552771878772004440132904554013910745455576444\ 770206316269741416345289840097193746149084561464209243881139670866069587750780967872669416\ 666016801474493473763474589217107608306422579013131527840600180381244448656553168949868953\ 318134735641044925178700091994372231667517134177643488515510462606408309783032870397680696\ 496783451575497524831954620074774879445190098943440056425684501983155810240049442011423947\ 834765524563652861173038312158039106975206603659756866186540582021292527125886782766832625\ 170153391068432649684495408122591931596633669621769744371021413478609548559217578825282625\ 187308183498194414342226157338909406578898998915767427471912270982357763165141902742251381\ 036087591240037645837612821398332398513656088024119244046119607826273969868205074520483364\ 996693228472957463215804413717651227510863497925372045987501213235434207145257081289352662\ 679707426988417818425548763727127569500457175444780296682592542349271168136133815455035732\ 625349366140459479165610598298697782010930733683805446673984692063245123881345064346299322\ 333176821830347590886393698588043901931582732135965672219662914404230895440521191791395123\ 367666714884674425051298770844897371440041417470836423566741949711162860040124920063228817\ 683117291611263744805243530425473163386027566453546786587719133972172114977992099353243686\ 083440048287179039839560588081409315150308834002724482331618039711072285228673898169861304\ 298537763388928370343473312430473723048053999141390137194166888835639358342837422783558439\ 876795888962783760490141317281538401464518666096300764777085099178094983413051402176203527\ 348634210243345623934128098809228679588873671485291280066934693921393075773361780745397160\ 197353852062299560110020316197672121046476375806263612458389553292990325699484156649480814\ 702112970314483773079850054456060480519461068517209850041806713512457189745414358707829050\ 483821586986981536931284192012975131175559896602532482132276472186286112573951737230474439\ 930147951468064401410700424774636320142061557939223861400077639932631806054359809166992444\ 667577998230363804697683640420063620149316658476806211241939152544472833634248868296031887\ 597470998528760714560378889421571609461654858434538000764588157337380659568412379856339567\ 165777470280635669158802679904159444790181868572779167228430565006929744969419967466340600\ 679051089257509139148017822066597933865066875515152419939442936951576019236679970522844466\ 396196368470046961894838906761230889325617056988841518997834927092146680126220521789995650\ 649329826801327258643153232158280791412901592158758386646626979303033609273420094883868855\ 995209811968271712797779213605960448945849219324264793707750441186116998497093011100861445\ 705931244705880281006135202810679684246831019590990069769186916067267949801966633267328586\ 371073221335029816357045086132035080545220700930116388973297918787392155254336433019873918\ 929883087637363670114375424976462334382490508928844967064114234269922551618557110815934901\ 876906160861132736228632165899298718943501206629663170780172488017107938313679614820532295\ 543618421571768942751293193790122270519731078734363104037404215817775961622071706710667673\ 312487272952115228707475202606126327462815938340094035200380231686341882709577674992059940\ 963295978770791937575861358368415148598656386349396319056163454569830526866943056584767692\ 024089696546418459683159256632009149359569006637264313503591659482676109683427057074033378\ 339082283158331809096449318714336075135936011278567801735364603544651105391148146365240841\ 166892168731809139164359107296092111059157735755967234067803504909879507376876716761959311\ 920378673432732492712381851564805164381901385128789829973052996808092181555959187695554942\ 480581033393085142281520685429056854037585607328997151995739558540077871159988050141092953\ 662292640953326356202828315356032917096796173892378015328556261153978101876655691406116605\ 607587773467578165086912389735561622951996741711620469752510194812505386957063138887410250\ 911831161684931666290557233579773605547985901529337897990019003727687474074693471311983001\ 681219236339581582808800726913754063113256608526838311595415415428272790510262145128835500\ 721062716587787283315458186841929620226676728447273030546434233595229673526489474526360798\ 809231033843578563696477622290105965256148180684752877081173347746267062100149720229920410\ 951286864777934759580260068914503690632874462399195865371760988338348539350275717698321830\ 226334015252372261589653390538291368621365039209648906550792212107804188170470877353908320\ 826727167051347846169966090800241979467753010421664680301215533370424078812420523253903811\ 916965508052829287836454904824629638900280144756115701568814090402935615816218335109313535\ 054079395218292587891318792234048179289576890026947366581405282678238246857135112850682162\ 007207280212690865831228591911696948127262323901130553240607783549443166525063027505336421\ 815941395295974964549714276306891301117372998094674697520822988024027991119318493542437751\ 160014869152621710936890071711047865749377744534573175485343445360680236016465823381186157\ 000768318736800786145798282520818277416400032475424781970252970962994972387917054094071947\ 402567612404525229186210641205841364083827112977732831807718753061247589528838682496198083\ 238848440136670558793578216275256198129812672958311429052666292989729673278796867716243399\ 845941795519020818112594336913731337553303030359637239471735809326575575231812155355892068\ 887855682292625417924426786565563441342963251955645476861091091364114637297343505014905308\ 732295888576826154321355565732780632139739223091886045141266172094375363307556236401922821\ 788316556493119072342567173753901091561461002681782638777876523156995253491488915812587157\ 053413847047984234119302655191541645917986301116471336698337441758044832293292904063194872\ 096628203244669592588780746372110082239212361364686964249197646651020787722073610050318292\ 436449297589223841735964766019354736450339933630561673866369168893225327076409742015785361\ 989835846057413085797169815535045297680519411762996274784525099417347088711936700043299215\ 303504736195427621192037830011279659604234725713970152296543088131832184423372777280240162\ 542035431290242166639955298880233811437094710331194447588789598981683506737644434107486744\ 765378009728867699120155067109785611988267727714580838412470030292399466901232781109501737\ 618935527601441098097898999439331084690118455671595717657323714477150664111947490616548341\ 951616621349502071740359291326597989781537008925611500805997619146357502362849363895431041\ 461305509483806974207737851856585195331941648483139160707723659618337365227015539093967312\ 649674273034727264765393831953456252198097585361558354047266855018313621219908450929094402\ 135571542647536382717105046414881623017320702662447209485348295222642067998811512814961169\ 506998578558700107504443380795976155077588830420905523971448229773872096834980395228447384\ 858631748249122526673235890206591533998094359805185090030780759265217318932092981323835951\ 294341530751511696197139000351605111828278132369354724264291343174801798229685931759618872\ 360335267349516685058362527963111185480253069737135296282738912900928118252871003004013262\ 369314009791134343115426073133052049130322324753875427388903160217520612053028843024733045\ 377214607718540527368205955366615710230715435746299825284774313620592377550836594171083852\ 905893434064472292929015794485536549063129048185225993554393445829114250051079892901516894\ 142896096115936728257547014510780512923855395217408958427868714448949470736574672796415101\ 442741062881390978598329314070412406570689416104966923795853134171200147571776292710467928\ 945722876366043435203862147172964379968951345208371950392724824258804834050977023615799938\ 453018246262796351965924103865230420901275802788561772778702885309354343418248172202958815\ 519453966694628537377212196374306111131572924257148355412164443336742782794197513717366786\ 586489031430059991101071702011260462882271944420432836430337463827239248075552508263252023\ 032440771888512184558140099088140323605887787164301611898086193844257471954353248310939280\ 993268415535716779395162394524219959916718572433400183040759819585041256568393381207766219\ 355186525735290447321031784275039231200182557348926618638891469682872766425135759671608811\ 883495436434976256355202519546638459729792246729353165117725540125485353381226823007945822\ 384010562461310992527075617523438086397738738529652112106412608845589726314747589109634123\ 228401293432966677777960866147207969640980823894229049404096072682502456664254328972702523\ 585947224847853277557699089820614250713798810158234685951417384238945581753773823594691125\ 396362263931118087464923282973043111251486433066540087688553095483791563023213414682753536\ 014565911504622979412237283327917960397784240012377144282633390281362326984094599209677746\ 101648862671997590386892556163588305076053210770585106496922693633814304348443352574307351\ 942359812363438307960128285865751019634780185759022075382516571795438888026289970650956794\ 627075003799480852546724377963776266559333868307318680485534402319827454269891478720492229\ 940214491884136509149148489350103955457465470179476777774755581810409988069294163684261127\ 660143938837488346262193833549232895260976473255415318552433884590198284452888441149752461\ 585611146394306335531586810602581313853869237232624999097946719244884511981717382862175013\ 176055575318282381337315478506391081184454378868823934608879050290152472668009276133761874\ 877585443654984763350477109419202259754706764477297687733014520121296151141255625101902034\ 578308732282059402510900320935886573649446109308178205270895924268211433160752948813574968\ 936687423735638544883994125734075572661763786395102299869448986691705729277503761735976841\ 690073763454875017300247680768374394004108758035837634016841692073486920110365350366034001\ 472403907739061567360325694407292434502872772581217038366268934185343373394799082493681788\ 275373395375355261454212858188990708139827961777120968772668107426406065067761244780693434\ 109080524629956151550652242213898698536382650238317656228795588244829859339869997196882098\ 236944060811243370417883942680679566106964530934900243507293031998418992536462776106301247\ 889380120560596275660853982458756145999295566419709013852928633660462551376611277851470013\ 989162783556845656181820041854045855500929180072983052718607150049806134677302042993174025\ 067909740223965955181911676915256583610141592097606945684454149633440549998923726287348395\ 856974525910228675766129506289982674026777738275529334030156081855371470056506325922975984\ 257552957958919024341307029787260500052431878425009597996801825998334161633412643727840063\ 188665028448152183325710113986911985927843857915709484773943615922228875738436234102223501\ 782548051450945021044864209252227470661510291595452599058578496478848338630395679505115398\ 440740946329788440378398326816716722855984697856060668086893782390452278167380882417332155\ 797298531127755362219340618982410376725420909614444593559516135151508267672240323580804385\ 421203113262088807566286609505459617858017547099710603754451442292456001619365272535604568\ 164584133796883000998636450216418412732485360818354675734196530644548806966998871560681833\ 320150532393127039962607352649819530846907914688913982802838263496805510942772454510598122\ 529608547891352384780218521708212849869618875259315650910193069071991863411679939101438998\ 849397127130060152092019600778188567290201801941912544532539748152948963839845861729766603\ 385476649070701435438396033835206581032057100875358134355283880234097658544912301781310530\ 357466003300573431262009658798976167257600829323582202442210400773133065796249790244520900\ 751126503919427709670528700539062321819129699836853233021836731290327655620718617512083266\ 252892092442054354031761855401657894782504328994105995077014018461130928191498823963707399\ 686585607931551535732021331118880948828638714964141960009930284207807540330910788233575449\ 491496306307625186173107532060634416110310400808768324310668271668638317784736603056803144\ 475736688791710899799828518993417206586764460996604146389593136065946348552048266955548251\ 618635847179904493652887837973165739178811362059715080382587344487913046471911278437475292\ 856678513124050441560906268013735755374698458542303503558302884143733782832954930631777008\ 910991929074367728568512638820226683808141758513709836240008481979960017479423434148889899\ 074974966282943913643575333333714345936723998958701230719172069292499493539532544167796563\ 219908085352456616276359304345934893304669364931898098558414330801885490532515424924733657\ 778384619951326199925175191948635162707449876335586896087884878339136225743227270197386222\ 277240308854127713864439642854231461809686432792104564571249000147916524984597808308308761\ 298109831309224308230565030858536165951043440881702160095141255491036492008510494898909100\ 228990767467194714930354472116331393095195907053702573694843688039206601614773430708382373\ 623476235759315168850441108750647295033041493152438965296495570036593263412543144969817959\ 785255921519690540321829273072298383467030956758177310102431983709766552833815604249506792\ 376488780818730270186869570649024044118318406327576288480073554058869044116252269218487818\ 331419324113219219245831146373092349796942422020016819591053264149724863605727664808618061\ 639045265367476288098062311189308273803274923107895709788067293327467698473334971025852460\ 528576579965170192097102620095179872573970351692899749219499269022629041847339591019135236\ 156636276571639490940096117305752284209047623120663706101614484740141788347154656765225755\ 727055166540738603983783303333141874898452815375394752689294060148342645894974770393750677\ 735578223476254360332890497273549584457884683608529408450248665822457380121345573543745792\ 577418258087962511766821345219899558393877246055221627071667767385037816773555486307800513\ 156621477672895759821180209096583882602471042430024916087582703805641739105658266094025001\ 246890805248438706168101564013657003693748952227119432885473424404082511865551641342637870\ 920397521320130365184093138101503458674128005445386212864338474436055196252355022795267177\ 942380641681852601850272529649863151090566759043773266114233300073244788324943393061861915\ 002005075680482004362039752579052885993384650137831388058011036110515881509951985449115037\ 350346820241301369947845095491936317035869241791855626389302974466195262238166848191091403\ 898076513241780110328913789189711419493699996308764805957437434406808346904681835106914050\ 954286662232515185724777186582490309523304841477020417561811037429510074777726746462514899\ 199223975580364615456525387955982340591298398795520969086188462911181413986965234317630918\ 333366144245284198466396927116835321011122268366573830840772810163686574381170988081288505\ 545538895174725279494195877267528043358528909258536489339059337965762153973962220852381326\ 450549433940129792329310583229433485069668046207845220499168645755264627598439252558413940\ 992010792409154480761629197578238653465343631006736050847285344058067350447602100263745799\ 761017040817958089100817554958962000073778446149217744665569914704061856518155976016756654\ 927355237429480266310570057877370617317876367587874880609913121237801262564979485197907421\ 620139687611112248631958504940242051468972506438480853050987877100517474144466525614343117\ 164239908137780495181382041192331397349595334090534024909295021958583566709869771330842567\ 685183273192761211711881521964700852012923460066654891031138905424613071814807544032419863\ 332677468840562060595518661057063060119580701086188456667334773407021783062636292037440783\ 079154573981721262364092324874192387804419725627560284043296214582386914264556441244262925\ 476342107328819653722741473107629795929708749688607642445345504878661938845500635307478718\ 653877981177044776144386859773048577591546384347412413244225926285764033384746058330085691\ 960944045324251540037873696671836195329637748786230992871155065538569924367586944300738563\ 883628313589652605857937833098997616762063345117431339854900035600129829422517731417649109\ 546129918293013553363859487592026406375054384617408580960906400839943965090689396918372033\ 883007741906683157523425441724945466747884125990036643416229562193763669052030099125825190\ 790662245550188622225900792488630684129371606844880550253434459632453104538448773783147887\ 451057523978889647438330045029483010785426728377060809845884620807365166876016287331615871\ 990357761317553782255657711301009448672256562630731155332514418666675481598443353739998313\ 079698385092515415143139954257321576118102089416300756401761572563744629737897361225817953\ 109216111741025040715350253469281295036256389417091930133892910492231370511455876731130591\ 539211938474016255006848777099316498087031146567820384472717203430150528196662255817840410\ 294634684640015301513980296572661167609135465050621575780614927713787583858222355282982986\ 544077784349717719885137589481245570812501964664014435792294930185760446812764295556682432\ 887362843738578585264900389620123578861463459038871948005110949830550733231863759682658855\ 023551052765742550461419169908664656809865515038563371844377859114553773296800040025825491\ 012969567504415651665712650904719381166174909914935897543190272215560591699693215027537745\ 388447248264007747233096277342852831961305023600865596520508148388061268903827317213184893\ 288839787460374992205234490256272991894149998037585419438904901963357140533837336505283803\ 767064708333768804447266011548493851454571488814648140711009959208032142104390379672795630\ 130084169444663862300395180799016239377646874384258365390436516626982094268279418265151135\ 204398738381652557670247770554754023736080338672291384103458560831428977396368660728092257\ 952962971817227608917691712776896570778204196484343263931571322766777508303553377628616966\ 410189167117664677350373536161705602419562174387852840788943650168194415938025334810262673\ 656500114973525790714649652120681686300418323471097481433566856838475906381114998693628663\ 749004424394430887259777935793852422505893818782386589108321894283503814506354853233377456\ 146964984665472208014828415738651572763211139758405878392138700482864519924105042107643269\ 756419930288377708102786438781254709322563207129781069248481333918367920959781504511174268\ 214887802235821129921316227261346313861072771793830693132880828158709849460021196323091647\ 224404080259814044474883557558851070864778287835084469433322743190792404414522552784602473\ 771930684441690785490750905598853823853633775941645416306710969091756385577843220421847153\ 685745567952665490933754011854376609835113165835483697951991986612534148444079561283259519\ 754586796904117584435485781936295386781545036840009850956786412760145658448892651142192532\ 851068333342086429755548206608804122641092460534952827167749079235194182267373365075016345\ 522350768925838045731429620368238597066151555490335483393566273470483714391230964267325733\ 711453492126240678026768816840491057555321537598528099407861910266337174883326020249334856\ 843674199694930861577032245550524482533322394458279977774097932434422102593464011491788817\ 500824877226449746677755667267945204553607957049657105913431831364551149150325072090466045\ 366197021223228852043057537215860682718328354759410261964543518075779289024285211581631650\ 152202340192306502930590873374061126422723931431889916775530938665277955808860163047301861\ 762227059814233452848924362057645944968070642530013935393036688911494965281115344712283814\ 605010453169501180163593142607051236840496210794617210932970057625058828504507928855649291\ 681789829218739171736207809423449769329446373523759863325546866027408680743220864169469441\ 682899183327881730002724013274231863077642074399342203975489213052992464500009492908109391\ 334736954204848196251327763224697388135263444973793434066821630030046945532009787723938952\ 096419670382423868336484149940952981181841442094939522944142495449952861472590649402916323\ 983669029973414902152457112832765812912065056029666377231421043912906176957489330880601607\ 352010538555558159766079975439212307700528418217204451847744761309768020756172764756165586\ 793757946857382178496070375425797408034544070355404784664584071940890635269486021586203414\ 958893534488821912515451310351654530570205262810335348784725465814748043272186060088013178\ 453851261350627267286159535698786473942335161114079004431756842517404633611388827805423216\ 997488244155134861490990595821404381838285034574621495816396321840675740316169216220821035\ 346133488721733147387779559042978178595741375888645767879423648458788328648864425178709825\ 811602665327542022802769106347341515804177345536587397386367574224380623296379762697531058\ 630552966437749986249410352345789268367280100879220135957109939603734725426704307093398470\ 668369028726197038412647615521455820205742376740755841803790555871015831232943982950601670\ 082870542368923350378063876438341617693526476213105556127905332445058513281036328950074039\ 466834993939759597504394711330891065072116222931397715610499367411879360626984034233637774\ 506814802590154821639707234731090414290171194190338296950716260854936328222130101944269176\ 195214534749884417460389855104718453694955288761628236660489958281235693703646401752119548\ 154779051027199211172624216723132477664152271553724059804470020163193955475299467133601044\ 895754749158271113940527759431889429079871001264355516389191664256785648420644201184104259\ 466383530848627157456680862307688008438343003119439602815586878147316063251737927164720295\ 414356017262087663087871081224621170283450550710130211042218518240645751090984217341556805\ 085907681608118146390608644278871449317437034687802408732420581021056634639748630417215150\ 414477539914083170317951840140846031888642534831374111233584554433632366611643778071521108\ 243908076637672308075941027910383319373995182960914409222574791797008698501241361898547370\ 828304213095161588899163891406997446235417856989317046402791396650195215432788949964879011\ 915812044961812881570193374014206317809356460600838614572588080483156171112490432795731201\ 166113616834621403433464391253254770278867577271922368981105100430293940374565816566975970\ 398399276617598987435547938265417157364138335901638369338099485892561305334799974333499285\ 800300820252675529817802846880383396028784240673867908957391631912318829785135502467483121\ 617713983983342932630608092352563957004577635893205027761894256625532660153061373592537763\ 219717341168822357664385549557038660078916828052182702394006739879529220228298085186609846\ 128565336991224684887315981161696106185204899136793158020212929950937274796788005070293655\ 137586831921667778015597890951159712109000472086833698017687824900754634136327382254538956\ 339512641199026303842984966836521329887957607172655596837823959056370209692964267387430384\ 163058635255164178917122359772870224465039879988359976836282524435522693660261104563326486\ 516791535221139246043616911384753242547068693919364064148585519774918055294225490507640513\ 732919734508773953481803843969697441915490062144585613235505551075155310977927698602637731\ 166751912313217382456810542784799034647931769831929898742198103174616451067843188917652536\ 920462245429098992999130547362630275465414552443942034436517798660834606640822895992705463\ 580381971382219614070016570981777809300624561212771321786379572484580786396315544966036612\ 289394677063408499127314005565241330513817257075472694337094012635750737305770648765576210\ 221563789991589456199285558808718898183020122875142728870318587680509166653874087359963348\ 689292997116108946565728551705912280318963330163724021277225446153289465154916698680193597\ 342960799506356659552747181798804891461572534891820621532046924555860504572758532661395688\ 428695508489921064277332655062138235872002740335804831222092565153859377902178148421324873\ 414885683121326213560940310400536414009745546157635018009739775819372532951453735089286697\ 574905203475102756921630537823646298211015952830951132132712767752162686313352627057380151\ 088182720929652101048911675162140531034805987063449076235991767071423819652074026199326264\ 521326871548065012835515814267943795023244402889732170177486869602956459462243622056265202\ 101739491410835119165237952656917307377245179703667483580676425433546252698342113145961295\ 783227487207005956745579137736713075545680714089912218622592885013397649280690329739398529\ 260539438974000329433396253388893849015175985053210501285074446754037522817151258298550832\ 851605398774310315946557183872567846496481140550450355903803675715114742273671494698177092\ 898641684830735299457782138325738915785789357094376670418877115594414775215765133157084683\ 207656122971266886229146230601081277467178107986624288792162110311688124067403931642270856\ 970438506192833149129312566922775060680066863085277673886252899358580470754002281893370162\ 238175028917644516469418409413969809174458990978372501418186055487813758365137363943855718\ 675572928099093837524346719904881331450151812203518796775437891709875497338423708778893222\ 414522826803514877090291354545796648229797129867947962881358462491174010958653714398339360\ 591891786253474719073342317338616986610674001174274871422177084007473536769322497239765840\ 134537643472620563429421876844545350633734874566492830693128697490816584586881495447766462\ 586176305507814462274109350195792994910539241541515555891068983041235991852692991248062603\ 162271059360182672408129468634341704348007538374607408180246579119923001683643027948379754\ 712459187716066311795548327576295631602387902462727998300432501222473832281604996104265790\ 854920458766436613394670710194808751242716945747883907608057267065698781668926269291132705\ 671357926608540959747199566891842576348306804287556164447921913182721923242234061019871441\ 347548914673017532460799668596615253705072903208358621483917295591606100561811961514923527\ 111508512272905001212357490174968971689738495192641591465321405821273372269490988366567287\ 659607552329564545145233612686948796733219741061969557271675770282198909205449957312843185\ 594553361219870561213646595268401868635332174660208127252513409212630584660335254641369458\ 493558905564604970628138182871125896957475953842624470020143786043450555836149824798150142\ 602395472537270888219203772603069771840377161313749231072621142055030236689096203280543229\ 710722600768302775193957195814224825288352578523106108560010120400429609168368887679286840\ 471664777771294104221818735948867109060955795636187064921602821982610731874054604159024791\ 051509449128935285426246763678491690144063419819977292902351809643098284746266538261602516\ 173241103603747602954100404677356972268503491470258858799058441854645466578438131158140973\ 519735795490723926710511985936448882450849506058077372417120347863841670642841631540327007\ 326847968121318296435617227366587572477645167760349548498997237290804938601124613552123699\ 144227927398955766295596097647033152038992976230969500751880188757760368956922343193979603\ 793906704423250592425099433954672994389206043576409095758296545681727058238002318174972189\ 858226559924299010282302380271815914584287455300300721806809751449891030234046741951816408\ 313937214879054829214901461893331874540336643066752987662636677891779551241012296758612416\ 560539115903675102427788474800658798952265883576419577730242257469877768258661441169549487\ 252545803795868735885134695624411241135990115763391641009535914923110114412234543423019090\ 060803199986261092718797734378927625176687018741575442736590555315643074310893569766927985\ 149767187002606494850067139287908334049986381189115338834408440394464822236154222584924268\ 427383934937567481013619571704640982679668842586571743112158562229539081446151646980811446\ 212261738418041259507392698388405177254120992830502678488338134766601739490109333620545279\ 825382079526407211744802677559122529352610812273162788344709527772060372270021050449982608\ 138627578379786299084040258054367213064806266903683735801140996382032589985013841631634429\ 304684843805565526912699625685513321455766332919110196334798892528590138826858142390733719\ 855462464430245963171598648257299533349299956150330529096193192777011123580618617271477134\ 527367553133380862654764346945649775009488297101497061194783024606566162686994402467378238\ 650108259367950580810361661348229071042016911681201152392425554197195373126936923288396502\ 803662548203922911854164057179485094614214958643847518765298613553345697974345120011215960\ 529749410647461068960587773966506815042084819409528159314242183174983586836490606808465523\ 590142104451937143013653859426064652037692521095904814838027761242779447251400889213356953\ 254615929555507297749543778692148287317103557999805434227694798162004262646358955388218283\ 087591835013617618744412372927103116549992597051994154933672283525524434038752309345672005\ 107825942658859117654180680250192875505694496069229602916959875445943698470687498805644769\ 975733784938324307213795163086316967380874754907633336448130154390419135152330031326281572\ 413543432522527060369687063195174545862679995044031683729573392859264345823001991500619862\ 121269414977703130950918654295790969169660157860478935755963122529682088521163846995931393\ 350646598266684396825264099736522806964728838978442285854238898885973848044270328928751226\ 434202880964650408182990139270463724778278929486234773453029114451189784003117149621825704\ 286047991379132707746827015900614761850640693869505306651842775381308390535778874468333419\ 546163797990486224134869743449292650546257922289660931567932625109070343334449547539515212\ 327910424910681627558747375059351143289845288236007332732779192519573796942916893505554234\ 717482235049975786747874427067590616730352580255329051062433319866837295374849251036939275\ 399374569454808740447969046122368728880011344510141179635254027726546033010799669235098409\ 733948262525339545952324575543725173168268637861138335530788450458141861041839640866229375\ 250654864888323536066490811987799315495693582777198735528275415655069922485298076191586597\ 459561372907344682056645207833005563884832805028871914402269192672026386249300881032526024\ 997043798789791069137777320473382653917506178340456144532352684312891416122559048863637745\ 347623089226255091310846867841920943504308382794464827451209056003341942207650668432030459\ 068101877872478967943550640614005049457116969689604727832589061961627824599198686176615521\ 185575644504553126428573968191883440745578756857060477942335975880767991864513607976077276\ 309033266042395408507019610689899087925307031679501853635845498151084986876730324442048372\ 435298405916907723789817530588494725367998276745055905588276101510825901479569784122252823\ 007943690662289804335293130645534048139987200140161702460183073471550288248425280424130903\ 505109157346656972066437647817782138809847067954097500426729434142902281400385117755460909\ 291116779978205482558293454127004890598508908478557528673358330354125670625507146059241898\ 269005586039007973917449728122569377330802713322989439330831674153499099478575219816820157\ 515119392571722666516280092076150157117076245459783625997108146677980727750792040800730819\ 053170611630507433191548477799860474014295840558143304597609501532439950579792834197368238\ 120444565984215825657702762871436227204972534030175534358352558744882654913092559548293896\ 158056190030887351529099842048601981249861238131338424899866011571863488882739934279854400\ 819378650633175159246275264882493554597430598773647099479980586167446399466003000318779334\ 825539284076812949621321433489027913593225295882832802516776661470506102510597167048768492\ 683001688400881207407554788443934664774790556530693123053495213402962244042396433861093720\ 040542584423764230436584375605867723940997207547047373114481808794614015547537379475856247\ 127774232267699468810448903857273269523292192055165253333194338141245260304996833225480991\ 520932356432727479639457246002479012156232183277197074903550960430125002341290947060444644\ 337694383953766090051195210958147743155375260500243664001882141899018881730726421062482287\ 898842553541455666858076607618032512967352771451352407378411578502063516789317716848302348\ 600780801114233264438828512202518424639376035243145784592976369210832738256454390616499081\ 112332205512512074604051998338965795233584612360598059927460946335887860395696195804639814\ 704591577452171246524772256664322364425926626811932299860110624869149321299162333534166017\ 593632197325597763767790965960213734248599649261493125585852195200256442303258069166992552\ 855968874316254131399436661896811757500980068462889133136958357216514128593850190051249336\ 761350424777549563452268233439911984180123737686884066377175370133541636811901150835019759\ 917881916923224667341780071471108049176681912060198913988051351018155010924470046382412189\ 844592791577010983618734733647064486534180092617568179814489570201469454500853239064923235\ 936550849457135989434764356858178300969583269581731813006272744042732471797669417777220029\ 852176891812526476035564315794867443293158123726730318050345505667133249526552680632343337\ 309568992834879374205529545859701753915362653366179481967781313712818871986250556401897705\ 555360719447175696180811876037974945423742039988227314081896380909456279715112567080690769\ 411701719411276260703432791672439287510583833936395744496909869399567913441339196008050959\ 549736681168258561114238656393887209169002762522237880268572529047990022857482832432296504\ 579664615537285045470233451880731888808168358257299225264545432360379381548885583601934156\ 238195347436076496681726085333107048177092568269294635642038836012091846369726856752639821\ 144451275618945545591539910479307606457358999757875761517595910173553546491846202280019550\ 922209099914649133467080204269779484982985922655692782541953328299352957333771544590332333\ 657994240038396516540102919508082081143412961457433601285957806641379193179063120320384672\ 928060117956135013047993425224297885198565101032703926012316280917045075420629613263358381\ 867645310455598075319710950592013534166829751234218035611433754694848812767331665924493733\ 669391158696989421101099506230281982696580765268150201480400983830019582253245969124379055\ 769715619494879743030132520406473211088085543674116077980479120698169050765727432912964775\ 298841698108832109881727933254149982061386261420219861463075566910116372741604242588314550\ 511737073148963996242092698483504911821164948909251942628290326964630806392570480045964295\ 179263350420790112243024800749968377399739750214203714109192637842038428646842191337537194\ 220887272158598808359591373873235908352912687731496369047614356829722103484420202419285003\ 187080056982329219956901133561861467613202290507434125669111571003666186278179331940841692\ 624604751628169102614418760795022736186638846918036861603632009221814737235140769304422374\ 909327078926975272426329076018492574273722865747138655015588207571803594952886006733600024\ 355886517068384317441929224949177431550920187933207763977715673461403800432841144796850607\ 677904512928654350522409197023598646066016719206058597901840010047651387978894431878077653\ 981646977152340008952466204872280463500243924361567309615299225196061278917223239103729138\ 386035332568305624300671786944418385327911828592276638710998473393795856024941185203199397\ 180633647224474195665751431687104114915294139507158737238090751409097108312163220086456889\ 079679458319586351815916642784791406272754797490224849045827138287614630011029061842274674\ 533248327956979074381129020365121496529811253237488026868990123115237491781007048945264425\ 454531638112434837512171468999276507835157318949270869505095646363514140580081778271375388\ 895818019736330852103809987834849257755301249376744217950861305540157291605166048420089011\ 590961858286753021089963272806070161240163157613042721852961652677660434142326571296234919\ 708315211480834867114987310428184598167631017044139858074041015458685846940702349327108431\ 362584940009911533919324764686012523604047593159684685202020288711346658913681881524379239\ 898346328698558732057582972969130068084311955005459656931079106753806415107301847800649095\ 209312720359464510283837747293913390619932941311690268563233840953709039082894016315647472\ 946799798522296371384572894989370422697437663626988728079767182123060053910001373404335933\ 891521097733442840084613936926999214408830981309150808152370273329376266625177394608275657\ 144847111364896507518608708502276023315960883998383579752516418440458547693280948047099966\ 176448023671619319312823346701699295137911653781823152589209697330493924805995876713118555\ 779219899850666292950749271341064542684351500784875289826136576306248571603526931613356064\ 287716558645144513052759679346591644812021539953139223208564611966894127887919802483211507\ 407777023762447045212954944417913537153289794032363699887526202181835399462234982111874417\ 848143418747359333851922527427095615836631742689806825047107179846280565355797917152255462\ 321517414315660489220114533666308044372505635750732997849675675128987320108886021144279928\ 552189685551227575659263904274264339180308522002976571598530483084809316342548218763731956\ 514009543196135633510418199234070809479133023568202199001544455507241489918317865494805174\ 002462970866297343934476614843787476443501702142969603482715020269370298500814447097345924\ 130707436662802322178621471607091854995915395960525093793110871366861013489358630794043267\ 242385930828636732461870959221497123060245357201741681245192488462221414158411511100592911\ 770863846920175440232015547288645174766050428945222517961291262132238351986938913017047531\ 153098603909207513776782285339004796401323153135389685023003768594295981036844920203233871\ 204358912622874045281514335876691594619554463355143240222845430581297296158863094519879070\ 988338364439766503775165634696876786111368324701212740461014642034425162390780688322422099\ 729680249215712339196015756557663061098448699312584725168211078656136475369030576257153373\ 154445882689232114342379064055835393389480362988888682303495152582702361925285538031202350\ 587381821002142759764612304833565175578072704245412621116056795603069610420686278819743062\ 382663268284154004581126656414090645461211963254286612314001262801187851455867325401681508\ 250929564895557219972100221265402620856805680229626295056450203146235920988896838929844873\ 190145374167882543180766196024770856873329384958621838504846483943125131526002887363742357\ 124977550489432385007120040338831234679114100851892450839073130496737838222111348475819501\ 851161818725742594479638652629041908636364161285196428264793835578089962723751293580365268\ 502101557045768313343027667114123433085490060252880604175480420145360649656044907509275007\ 535331589932837687929944013994907909760192057250488213684261022091995374377690784961646564\ 784611109957230609859790690484338526832657753049860919203168714812513166155473799550335732\ 542106196285919396830231237407262321350767476716331859420097853036973024030520928736099335\ 970695047373588792176175124367963990006354511793914613466917673209310748084428429005722968\ 793017192141795380409955666799991699289959148022175214704568592130464540312607388364493253\ 723917412052385978212371970837655760296862703980048192180951268784778724273895805113337007\ 969180948651663748784075156306849555000556482325244412198937005251522569854911156176979547\ 597936262979778128608632565807869600256427122883512716211355667511811366398286097102062661\ 987004085933620780735145290175783229207530294604040163689018212502889482841552716902994464\ 622701589772761508848592616221815378178825621168809075354342171331171729967694876162845855\ 165633660302612338378051488902189820386557708005265885759758832180632611242949859129354423\ 479165155152006787656064241026809518185645743735951468864590604649335187265961850303503903\ 217864190730793205975529343158319669049783334400150537047894425583892866653059914610501528\ 353604486097131693847797125433066949274741372973683576564055129474526387329759354751222749\ 062139112678638096194101443421338488080205374191518520409455135196867890282665321603737425\ 975863807099083432499671762474153503455564187215355621912257036111272444801947476819472812\ 861356062375607452236056901298735666909567105156768185855958394538367216083603459939861271\ 281120940764938203209428805433376695824380909560397119128358399700967926397151027381553218\ 683982946890077563774159140049542742451639172119579867795205522759443238529204483881452676\ 487141975021658035152845087352389925078735487370147898757807501118797098806440299653359107\ 147373390458471313307616745111713031159480304448737539691451299203431653102318363167973130\ 369611681780804193970833779031885450696039634988773027318685547489089619305655537873826551\ 039154220757166771910217441558883417170158734656963166862673667470926047231321921566500841\ 977486494367235726219989201140598918962052820377656741027223315631771139839020676332224513\ 941087026208626985612312668805643677851904493314425128888246604579284732115124905747472532\ 316308536814020571293273082879614499786597788064352255016642661955183283633661811682515129\ 319529031386781664846217080551470900409559147484574749366171506618580821868923802695004854\ 170880152068572495183414822739669537528410509231702482821591749801262754430555279343938238\ 356973520813312169665948930612062875057362404491732226222390276323955034695252656359461378\ 758162612951152089816905051362858887597531676387998308689660729243649861202990400713835373\ 400302500722871897137920206419601314476665175303923158863448004817093249728607156416264110\ 275467295416764084994019820418321475720679478742500202595534710978840777729657294361452213\ 494956441953304366330215121893595344813232801390916332455066940505093527500209958486324108\ 002073971688541608812316242396072677505902884703272662401533272003315169322445569857212373\ 374467379823393121478174269347143537349548498010620157824698575689098380753395591484195077\ 475489978007233530536604786766240377049566768726855879134252994132238062618439945349312307\ 701609660506820682284737955776609929552538763741062003014720180521472516194778874754998519\ 704003884181032207124852935515825766353917682562044492309902999110747716891975992427696205\ 369718786742575850157500682768944419356022056694480314832497738932426261830846603895279609\ 256274559964823583447289748922290564974161880553066761228411244522392225190670831690808516\ 064561283706843751322472988598078046110969565593556789655948457879135083240713170826709463\ 365624254826008107552786253818587503492502691029226479557516414348861316898230749218054769\ 982226364426925127199374678115656853504231055451296552442268829474031826735324589945632056\ 815011836446966014253675476864912881543417643443847293769078206252111088743461819911324631\ 563721271676451618982100544199956275185088820013227746874318974779043446951533313697375707\ 698011321406745068890431904440677694031492107571412769972869554641822661044199036353078429\ 886050024568603891167929735773773289136989525938472327101696747922582879126217465185456846\ 502658130404296932689402148691583741063089900249705997943778299529178190416166830890269227\ 477121662140224329742652491157202663913272720240562141468608255788558670337431779374927249\ 012772252494867493864519509857853022908724991704914661732105889392648515771676217289780233\ 969495198045615378770395485812088942537768306805153995114778908991471306022422255609148780\ 204214391698788466793472229641417779130201399820732726138969638983104947178290673125259918\ 119590845987621203021509241397152178636459005501413066305020173521199286173356270607549889\ 705496279421882363179615193995761559131300666536074626867272906481182026552832627601756846\ 207380117528054746232941827564537726285587500736736325035102104044452769147677502236587478\ 255861067623884359377720692710658743802389095703651778879946602815597829140655609801477400\ 027680797144000228071046199918981268646408039118873375725962115342935705596517283106937699\ 693770807676285724535890953944182934665443097418331290959826059121065315961196233801459955\ 338756163507201439142731100781703756688955010494672457474877235564423666588708512246450247\ 666089134825747969972735770842536880606708915399765692754793658398540277398512682265157614\ 991652226304525077609313080688992221835172507061887084798941767251831129248330990753586692\ 476663828242171837474513437362373700468467586421474262679041886123391331455487027530572420\ 964478547863918541605561218670035374054429905881048172347653337404165845705957716778677070\ 195730086517968722192605022411657864523640017069592482920104321761529261082461643870794916\ 181579321634690310066998981209022260655183332437463362924410333591401840960157371845325373\ 871640951179025371911708524821668422312046573987424764519585929266888619313666793020027379\ 456926951910587162255081457059346733913823448094911935428695735737346124742156935860382238\ 560180621562104107108082793584306088037488113652546188265654807242302358755084646267341314\ 816587853518725981318317513571175890382340222131555111568513917404414725830002182329634505\ 142615935046131012598936406804571404473680635164031944813631065721830444896688379981201208\ 687235349526585905940745979496756686123527280643613268729674680557086603065981224628589253\ 957565014452105026762990604647908700085642806953306286980397705388110722187865136327686811\ 078323843785141977068919662805265964384167495156540744368388162787861089064622852806923764\ 563233521960331704032772764912103182059951223847662202978106442579148281025926556333638288\ 079392898093697936738948533100157987337130391099147094010219772240502178806871520072899797\ 898287645142446692170572594848961992429090705904332768903036131583910939899325992646574702\ 121471753716388603027948607438630299896355472607354585896347537406971689928876507023430969\ 198842199469841435837478723687522148943378069592681128564665053656903205319087957774014470\ 513920335952256896514096706016537035444292435419500034889700201718140178507163573544943172\ 952543430753456205842325004276216972743254635195187449255382331424875545734693091902216008\ 722308737658829393223235959589674505673370761698869288354195027092796310291430680817406289\ 537265347600644263490737669203092644152017217953905977206322678925903673995669798035354590\ 148952542440776761037523862865116756248444212585428631084390595974540577625693870954083109\ 679501325406032837995084426416633608706641321032612525479336168388532538648032443138221928\ 593694955836775911733335626635090740699091508595102940612718995328231549147231205195467195\ 909328185775357693972190627429878042709099608127230568370667098852203367650680747541649724\ 203869602949903153314616136235673021996710459274682664112341105202181548794467607070159409\ 615903241162469087223068416370606111532610294209541639017426110104133643547363044959648227\ 252354540768634309895283792697176682316318989796872735985334489138155825862041445180872974\ 630992905964145854038215649360429668289529261446690580219215748894041889941284522759607321\ 597998375333546461876665680573584251746150396226633683569404751044828910438490635068273506\ 085716242207066991279813021322029706510479653639907744651248155151839769329443180398302750\ 747653201227903971703692191368304506281317161377040595303191032516514973766705694368960256\ 364354333370516522315761007877523435248967872371292908481332297043800184415293583334716799\ 096429745391867455289054558720153753750151428463517087985224844856679218807611823260899065\ 283985760619505163318604841197413783925013796592155537930436548162157339695480875365347893\ 578461597206401929516984217305712297772810143325019020731412759288176117654759210126171058\ 457437848642912567953108477478412950499758779268542882285028621461041477801853165214104711\ 214346204063402809995062394481031700889303597845604538404527074220194671035815069574700140\ 487072402319333042304434673616463681627744665935865325760298595727689598934537707559631517\ 519363130503844366015851062302186231516154044153737291431654132516608450769028214480687284\ 541791900262598257932539921751747700807829417257249689063040060885748198379499976858234674\ 353538353481896860361758027391227480040866284388078293376816382346505974265894439463141479\ 534461802609836605260892152570827563694486623718511987289485773388743420995400704530252035\ 127077016168967457539248994407079387421729875148805686493266144658834277809666048587885478\ 634317907393149717961180424292860422125603980302042346479770786894956168689666237099969700\ 560324713959827306043203705743705573750524417513562196550350282146213523730112311828166983\ 011966262450610455542866770606875639258005490173345193641257547843973408519447861642112191\ 065650058501406383808899923793282433726525003672437624330186205638934971838373140882121865\ 250320705877985199865194673679659096250940880475319849592845888396565100180893944480399715\ 215396185139033968698658380342845421468246418700710557508965111182249536370331910183630071\ 031328025982335003247929891006193176535302768712228753694757163162516801661630833413515456\ 944381971335393573797036554975122081183092386689651794797242995866860670530553288759763501\ 958602310041428220889541328146259792928885889077601183461294718983073341380487244029243679\ 692523855580001763911044241002045299523985644932243399689470506064984474426449939291589176\ 385437058574261029694673663241118082895833955283533436302563847147472906088791119198626822\ 855284279859475737633095611455484256311217085140980169842582386915846068700034771839149082\ 902171705826346363947313420445230717786169950305832507802149680402806084659021179026409648\ 693902022426368682215518406352633693191349305535821158617367836396793320672098236785690093\ 054692232013957551641199899907469094181780425567565250839357865961606056954281338156010492\ 358743009424082497691168658059493467385705785934914741452279645268763561196793192904150572\ 262084871570447783815599433418036285341131747503835714763370645275606155582950644084954469\ 025495632855340301199878904543050021975848634193830712088368536721854741832694959722724273\ 938195988977309599356009825481986118033070895482199356029248131570916086473922546756218703\ 041117616541081479291518115539835807457901390459227008964699548181782480793316741416810634\ 277611978968069644050201420966540906827593766882254926070819668499692142155414648019456250\ 187692598591670244524877084009625545873753950136438945975390478006805709951676059949889284\ 892408146469681051569135062685697676220721916574757986587019796330686086073529617542276592\ 169531416785046711422695086404688829533058223722316781707390427333853776800762790429387199\ 693395869946036371448900840362265678294579148397201966859524116432021146989474942327468631\ 312003213135090998833710802740428853588330956825793378334874772424072192289956358938522395\ 168062547009852936773727775296824118155379804145692510659065706583473529551735865773711697\ 115042342986306119088714276410909120754881217515115514725947403366850630526869429030781417\ 266086577529627274591084430809916511173535134512005542471548308752637400637199765154597450\ 166529973183925522372609136323562851829603683674682776173466840214720182629760405184097230\ 545563232373731869677260358540478302566327516930621279328186180069548242203139064557838189\ 579275704159812107740577929426427870870878652924536107070329545232062933472813797286831559\ 210208007691250786408947872258790222593613575144800851807385669185201428966865138690440510\ 668909221099988436352709692255592885950979735165220271388562607799225195370339405823066072\ 471698392171042997573850613015170130244815318041160382207614114804343886309834540889974372\ 887043155576731682206922846267024927794930243272347039668947944045064708696707715059869305\ 668921300919062621083355049278970597306211065976597802629396585939100646571840273074748194\ 084135539007354205496566793965177032643699010396122926298164049097422958573827432185649765\ 572065900293016731587696638552303360917074219228071163550305002472577098450677987685429078\ 807237143970928705189054625113278598713780154255030850594953536902527172371913405461584980\ 400244738901658192414247177556756152077672886686886823153540437031741398535773222983307582\ 173125126988962421461335034659905830441682803152935305966994330377543275613950566279580549\ 686433814539917396269386455313340144582351479993309702134977628771920244293386853782828308\ 887814251528640360888559456613741759894673162583939594735567058030723261581621531457623710\ 876053594491405323087170271017381148571250060027270601612721792084692270052117152323507509\ 371464239494908756095653696528639244598734176196265774309458276894360426714015699227067561\ 973739840749811988379948507063677739217564944803859482388852051260847901492513418555828068\ 007874949927539681527555516441847739829078018920620608023712499937862722272831888881605920\ 421345018432745120006572977264197148931164538584497646364392254581539037244491376647308356\ 103202798858697528604551986398612679233305209887940379207569502958682261055576323609421506\ 645434692575628187095526775449333260494923116369816788874985450007247186095628204836915358\ 934045470504026766855618652539754294033867615047368863133149957956533819405986288147551929\ 379534644424758490910061568981009984220817500334938574812450923390054262770402354074563655\ 126067031716557602022496122462294668517919156179616891220137444867020900113926218813724089\ 387210569281357562003313834653064114571619258565952755294917126940128864599531771577134688\ 595566788926634262452028113716155474974299751334856010111454894101999022277784711759044985\ 400711354055887491817298448108350917394851252247262446860243702297924426979772137354422254\ 363222202042071276276031003705049449738176752204013960419379369656012408377699795288725589\ 500805214413640708113675788699851200422458198820388604825530034384181965371711649830615956\ 754954644941767783405416985897230440428099563768119370780317690749776441337908760907492335\ 840636839489340821237016668543264474837120069850731907325966853713139177796077857250594014\ 327528460141812193851891821934456089369511410462133508440268670747929659508133896348747893\ 851698142400549803973534918260779294993402496425997086284694770946049564464944296155688889\ 752892026635843608239183636405759453307496882515264607070893423922855204198392639738090332\ 530415069627567358947306489365749211751091580951516719532820757792205204994955092422529221\ 034829261347665833333158627861086218071699756788188113193048191811328627916556063285398917\ 989754261482485655938537036727150683856208798848384388384642275282265781921342361794815681\ 595246679592156744809479353865295125156153517907505488688130078728402703079930136634493716\ 142756887724066819833911533096995082322028347413696442738924479464654280916018027290300018\ 701199797870135074380004008013162433371409292066597033094384163485009352080204977243955664\ 205886104057719569400451435672031034521210508787503010360919610097783384921502312958862566\ 849585156346158848740291670633514215536145427855513267847691073578591699557851170206342882\ 282179343365105945825384765136391146054430147986109086819991317985789897161898928229916391\ 604018571519073873521334783857079303950565906891797501264734103403030129111071578434913118\ 929622666196567053095767199375701003923003694766217357101240690322685005443218585808036034\ 319036984684091031784191793228579877128882439626754323458202402094770422586270036423879067\ 905222336164705123461832192408565201950170736360372941218179226733596629315787119101774489\ 321133278438241005638119757385281524849760855899853914162010210217569042979407584456200449\ 156335387684388469328802085185048100123592504089054560530624011712231811133822050579859290\ 823198055961807375056589772753780373773071953789591215326190609148153822360383544476248208\ 064265291188493383841651874898513917073184001450433795710971487089036374688103545037807281\ 606841755239881786276884860778646581157127614820932492451894419352365760751384330628900344\ 207784111450328847737090808070293695002240833455651027949395267542790268991231235111522067\ 313544237321627018957504424794556748692019311121613677793449543737622127802496409770935223\ 740223425896124749443488706756863250807961675912781989548874828708828088434821337272243442\ 554829083475688955656248109958091907037238720502050524062692729686300558314154496822659840\ 683663205436763923232008294920498509005669342804880315323948034130659976365212417124260136\ 459730783700606317913838709066688097722075732237757692280141363522059513935131762390019015\ 695719324134744646046254279109588797935916551105207665541216995764225160274533678673348963\ 584833904647131514445928294597620687791718712243156249974250713662270389809099936611834001\ 469217183896151038319665920541488836543537623316253140332133919700993535551672714914635313\ 238186534449024226321680973109508802472503238196050278858399294011370974725217923169670586\ 257767905947957288899404878251418639804106362729983237268031612530456404946236494106847173\ 087730172345446064189169517832366059291248910609852100671418023199067573017652069995206722\ 578810696339806791064173309454379876343454654550409102305247060554321706799511096056436857\ 460040331816807569327371888909429618758136136832987933763020860130877376037814366103561437\ 423011862003626698550446657507606547172356959454449667474315072254694613076262908295956001\ 636804443765533546707881419688306657053973733181613346856783787593857068713279389419621099\ 447543749527275250247535911714002471699440201826678613838654251229186243819963054804112738\ 134287992197624931723264896754773051345946852765209288534893228674215470068343444764439017\ 514983336270564959443183472012314822116482531077126738306983076006565412185517451537451055\ 029968580910826504239969088344546545348742085614171078660395747742482036290953468766135660\ 228069541233792138430510115415193958348255188417694938321746144141413317362275025042998894\ 830553341035117508972117820884194216771184346850557904556354195450684384703067584507778912\ 844656284110105130765430120955623825649914359051828906157534855494404652035882986581945569\ 502174125217817419998242449069266322072475680742126637525823194766533962798812130212508506\ 133698318489941718509432441281068725349513050723774655721448758851252734760208479023600947\ 943717252915751039469085774804722227090106449962217755126407656250433455814425704012041736\ 161993348610148899160822043609257421293997535241280382650693597953270645332514340259737903\ 890946665504088816937165141066376693447218246821885579586490073155492497560445001727762629\ 253311796330405181537777740291250442189523046363300769065725359381792643453609578257090800\ 425845328074104234048801553572931453316792294536029062971635582476925161961923285351327104\ 089776183243705031827105458445548330791384865744344083127870546885830643167105924981887314\ 827663632359403925078507315187619804580812287088087761442177872379864537624831167507756813\ 208357035928844447158457203795378746223581361165471181383100957403556916022537664448364925\ 386421143775184601313980219909639751577456422589857003108135815097268123078817023433214904\ 271634624622385201515875107914915315233324136492216333366794011213403598680624348772520658\ 477382541719740551087897721867747026104173622424085967505613172043620850088370360256495476\ 803329749307006161402424900001137969760500281322844833474335636904601480975163438599079043\ 466558908056223649357721507718115591829661754270273451140021816057524948693790092289847478\ 120567086655430146756600624621582598801874487363104892891161423430384038593626459304340522\ 087859495718428844414057919436796408413326668836493982459835778952526782546262707126632834\ 848810348815324547038569547281352241304932171207733397263083998408033258353386343114181558\ 100676986777197680115158470516519830292043995478957829937459291883714453487900198533834410\ 865241769185210675023105906535233625646549790654379663934532860753564116956611432545916540\ 573189629406308115305914643367857729471500312174823280943260854007511069379964751472593269\ 444745240808813685519340618996803149812907806503529691103361538174748374587354932599488739\ 886580072948859652350580145163812424117618157800740013998929529710394597119149538090499984\ 866353807231008738389563996275741173765545093685584884504319405017750009160520271416201631\ 879763412633658742378080845634193735616260716966713912007508640217721368339930940697147661\ 112357267373380527508723883616360302823604360554764131162274525323030333578450238209296598\ 673583195158534274422370165453624362415161934862778930986539990546393031136217352613336581\ 463581749547832233197109861510880237168163825451066964188131492530481062136754348998008214\ 490232744034759231530835051572739319995526900973191260864512004601915750106275231100859757\ 182492442266628827110065270813582084583302494737046203303405161528048579860357245318765374\ 516147230879053648791419602410971358308886716725568091976092278464769450509735165334020367\ 687618685007996167153921292461287754934997691577562982960402703640312828205836426505353846\ 085865677353674923331992063589224118145485042327779324588677239524942979552010787973652512\ 188398255069096637678075292970118580911396197071325076380436501100326756243140435391597539\ 992561969346574951576228855670756930562087023155894665428889926088581790690761409313339012\ 300717852370049696228356911342802343704090221131537099348646571579576663370981850464018210\ 090443775597815220078762290115861554218359622704324914461643014198708427022026207940777852\ 763031027091096886530444512665045584702154384127416121197993526806813885194979734705853330\ 938335636747848631968611804695814934199975132073816305350366831312681165565494431247461106\ 818094974682967956704817355016370951760259998876121892098612553307467822051668085561968534\ 427424220757143075924192327110290752049343998606151558587869969890633247329720646199870761\ 841407081251337543668204599115621564934531717604001450962086707604990298592847724322355235\ 349188794488168938511951222836811580195024118431386243172417976722307031283994074291614481\ 177867907699047087882357676863695091468174999852053373447272474563487273658013046886690249\ 816494865970358357899325282633161179343615810714905229996669465315308944168908053799833310\ 184646609457899592992767509216692273828588871874659856480655317523422382657060932853791477\ 456566037618374928180786878830941027479452606873613963931570343307074500345305671874555520\ 354690007439596474581024949933976919344538008378465243618355844987752190120518965545140587\ 466811864340146589931231157010145365785930541360759388429209347146245672232373773840338426\ 385655428195639377771889252831576845036624881646338823833126184133853639032970587658525954\ 698579312188861798391993249043530440823600064969643291236735980925828471823134853339429885\ 685504583974385091078630314651897373840401431206244825131557119357095605476833906257735896\ 918941895044153968303816931012886211600864302352796975853964571536249998956662123691523708\ 180506097808915335036562082661775314908723278457963846302503733802644667678272388250946502\ 097062903649871218940359360163509013107253360919983313242789740791430553259652820653870755\ 452465930755232558610993209683507727760385920058279077288892712778753632221066771447100948\ 477528550475847971673491698323932718136808210052914883985440512445642745664835212704407080\ 014482972823032960416808987980731338487475427931542914006201589268345196734641913711788300\ 593157885325871572555363725251985426250820001796427125425906180693049011527934166540340428\ 481356926194692009969031597397655853492075593911640244201796524174989899839706882672792778\ 717582333852898069003036323865705588441024380834143515499815308041433272643683501106601437\ 171098088186425000052159850564101788863312828167071446252254454743850619509921378307649391\ 486420035652641445937101633606086557499503638725624498227716068386214351617096387089288586\ 748252879329885091407963661410014302331207615827576233404664953440158858675107047036979957\ 771537072951121504147000425121389357766306278532097002529464023174485417483624011752820332\ 443477626078886732060544211393089161739457064161679798420366192730563933489314852106770107\ 472752452995477679095339195597718617586487230077310007109380299232805878593349010078118920\ 828645853547862282432731111789425075049189137562381629510572793687658806739971634254422466\ 884848051457667716865658011312203828919326524267651741102944546907529946968788894700654929\ 681052744513217990465943115754127798474142755951665448710089429143351724186643331008627168\ 723218170648015656195932493752364763456229931136844784637663182207758392843219052260999152\ 321787606308165205695384062005111475662880739102945783807771076632369404793894804355994431\ 313675736937106023148527050501994429409567005265472853073542578655756867624488613669063416\ 531987061483145522442878471636689061245037888430686739055204132682303475123706916060623626\ 845928762205509725311559290245833305887751620902284909894530532662785102299516665481940754\ 151702565727036558439372113625292015004454847003910441766234876436417079929781642822039111\ 278696616038636158040546633001607842368555434467574043092128251522373093796488054553420960\ 313863628858678996201649626736472951821874370776699419263570254362835033948401357356529736\ 937665049681177924464596458273553573443791474483485289880059975365198926245426578251874996\ 203294099997043534554291868956765093664238891676657901356446517100688034923520295629120233\ 357379327126434644537161830336868314857374933643032794250305825166616260216696441559126673\ 854033619271048007467832092841322738519878654430324926934273523255479072308098201345708656\ 772043330940710776661733581739087851242280834304715304858057603057881417473693755673570956\ 212569958432699539640930209332519995861142467819721672047362179366768874238443699374068787\ 760867634346473566787721506782152310804251890299685702367336529971810866266359743670516975\ 424458093982085037795325221834379501463237222263718763377079821072264069520464994327761323\ 647789314028388585822318480015850027327972956540207143610807838165483790191120833942993711\ 160917288550635579927722688684617651523845730040408082407132742183729071412073048653420825\ 114425147321611521530524377200364335976587871626095637451871359386790310861142035742131887\ 909101066426507816241030784669638325419054976235788468239446369858013066875713347011311879\ 127511280510628983837116392422995288775852205888397105143478604985521382285348596997473791\ 133388763334956661018466261692073757562234304285251952079777453071893050340200274483000719\ 608505352256399699472135664652523476707223454824337360390225467069818762414791378206640723\ 899057423056722684638431698542583443340468641287395881924710969238159319658327466855775155\ 489103411106685719787975201355074282264236813004483152807740957459220860463890793151995610\ 025138972384090709393573073011670151973070615403643564092096479646335651343071174788943312\ 736582432424364063212823678728697314430641761665322362883228797127564946138988275455008610\ 957441484939012170423200598550334425427576211596454042674386067914173691322424386782411014\ 247611397059495985386498554714086588234316663015171599488314799919756117319471361163673755\ 723491238896189879764699740769315807097785482494873503240816319774925872907008356405081536\ 449042455355419594147042532475483765634364040502735508015480499991562499458493011215044824\ 734388174723360114527691272980468895258214575829764817243404642662226620109357960028819524\ 621753088098324070915869418288438545374202982965435483421048388737926558835785799153996111\ 161420527378369611315446481280803927997260996892618838549072452142357479100553185551070488\ 029324078219239548112801299935506284971387539735012521926994360023636460683229566606294924\ 746547486210797853973318665488467481382614201467010953000757330056864377089502068025954541\ 909870184797294940171824206605143132784609198190209611134125378473721519692917202462687128\ 164304409095141893550107417395238112213331960393887026940626283175812744586208665520603444\ 760551266586517524664257595730359017331458027653081378300978405861231069228160285513773627\ 520330543557432509652971635061419672174375422335606811728741921949433951324082207524061393\ 945891241837314085237823278871829541190550683456561356089410664202649499016264416926621721\ 780422411478065606470143157542233124896073441181411381631488923319008174230627209602160721\ 167623451349485829514282617287429257336180490337542554355394351545878739691801313226053591\ 771095569690430448681589272858120260599559262352669021244629822930779808392732989379154289\ 108377212463135446672993283918774998859381980078932311576623345183942931335956010148341051\ 207972321217438446176842278358344269172706530803910538208776954756922529954965333427129918\ 491873092043057047088657029206232343353124401155879915646674575621749361214206991015231133\ 805798694011673079843733423771367847863894702609292635909179881859903709943629415958891370\ 941105410546628597549110596979799884413616984129012287592938253598817400314878836156839385\ 060159292200090128795878065542095467327820997274959913137605116949996579276241158880092165\ 957602055219293499432805711942208308287796237347001236397664481496545425126337635517730356\ 091711010307378220743141259860388549056899123589131156842925089550105090835721722163659270\ 745405507482728049338808823481840293949349902978265272271046743181716967297230232996824296\ 375605229070760557567235089177275949374332769217234151562599959370510507630492699652495689\ 396724320872607461638960113042054589235826672897761632943451496224710787495107532030786953\ 778555518908318108743813973851708286917241034372012390689016769921154218249380541909431612\ 559712481131542760758071463919928095825689066932384433221046471917059119813375524014817394\ 075103342207612917387922114756499019980712897041136810473913860458058177515486861517228963\ 017501012146637843787127533310477710760528818943937272251854673896213507343605582005430307\ 866023791346962794834352017712455842440680595849519194515065412436854054348011636717048348\ 825409919498329469062242822806766190530161769395404365827287482023165839639513587248209460\ 820365310574665791619962339625200266188801845184546490805598621773160640879461690567597922\ 939801969234067751943242774607792040774249617183217965123996887880656352965695340711286330\ 502318312622451565908821120204272312854293350016392749845817366968139516871674839580962906\ 987425876820495875464309703570843564116611234932312052113676617462789546897299605911441289\ 798007651751631373970979017557180964901665634864726408970493916103555194007527404688117690\ 043624343355526868463628436649333679546165415573523189926288991571274375933478754711795688\ 033860886817724478130344322039542502019909301152303379178308012044872077381591307089272751\ 393393112054634971960460384529221090850635016524941427509071057048781721498234304269678082\ 009009271562978216391060226561800621286746099134437566064366537377531916797448244205087022\ 834487502201507742277351580269447696208061883601740497659203382526912423973353439614950500\ 145851925631810312542171775761773724170724809111510095796067481012129415246334960408334520\ 905070766242078446600055061012781628837300064673897677486352145789737029523549517151260187\ 910362393924627509093477090740384980898479714722054655752525957935773925286216831591876567\ 220358392620482258806938809304667438351381053793782078151427226407580714357651483290962061\ 370577756723504048071305433111828663887102056477329828464010149563476551865381955104460309\ 938598496758083247148686529782432364230278511891044477575044903610274007265880705373414734\ 694951841689696432666455433789038870186689125064613026357517146187529104080061527978053556\ 493835192317914461571387163037080299594630469512243362325645942689635852841499831374182966\ 212642325804578247970218208599176966215941664456050848222615361373589730207711786387015254\ 581187147430518551935815038763338927768528279349046452255114455193588810074809224028598976\ 891996427272281771404829486538535996186998729571493113176418246209887822961098396736004559\ 969260174800777771162896696057874061227515933938043155501294331602918685012387757625235369\ 433429138916727654294119237807942074088934860070019672080355820564497235119643699562772421\ 883453016842394511689772088924418898477219961627196220110292710518910605860583830805696999\ 218237296848631393045689575740335015131713027417210031722218203302754102273739053352071086\ 418491821157581665075938559356517595650812035171778753407766221605276374774442922762537102\ 043402678962354346438282192960470862635171524559093496566414292267682725082380369278686731\ 160761844052996926959986968148174025689395052763019438982548528667406175108452351326939541\ 635210299802806727606426058636442789316780126696408803438791029496020843383357691463390419\ 884780351010421074672974083730942556178253422321607063730001581839039219731432458202836275\ 791096791274518325668018591413446828880668255754562938279975574398476976180792685551162329\ 985174418707309533885714088626513413413350330845236442324720075521389434784682627741862000\ 755329333330394639241954048350635209064790825642863453026336264054933998421034144880262949\ 119545205255778059321767682160654138220705655331702421509464562787046508371836767762773405\ 995640187026699444943737399838555746819603269905630709623152366815471591937109406536026615\ 086779596571000634961319774610268793286053916065124131964740917820247548150837895334890439\ 977256368110043566673400723212233179342716007449117884113733523791489312818195662493133600\ 434502329082699073628705492299548654356653665234455089163463331235577121471902380529898722\ 616372376313740913266878837127398782527145049164161738576827733375351468563122444556584021\ 221935789247994095445593491806331322928987155733960983502778849854539068097024810419422823\ 712573738482938219426020086003308060418857617926943803206503755870497736691304763786823972\ 262507072714413213772506386605027793773310862521245884944021013546735208165094414571978053\ 812958601688830041260548180519755515763593304148934650190208529656067323644267336055440334\ 113446154838788418720785170603185658097847180621129276574337567116565201562100245216715439\ 809764126618816236326187523870761466577574741800216851490277691651287611425814226505685078\ 428187621635383496710023363713569796436797668236774808256892931022387032994237099683732622\ 752124579254745313743899891940562599124074373538550120196368919900987057170515706410424735\ 098807092837277071566477994404456209360813117130807310447903307562134675662194445796043824\ 010953834447774862698554459291002621110926552360241659468434180612925544469221108433838475\ 592739862286781270241046804038180084083894798347283404258352792397941113915934800434939559\ 930661195856506263161753253228692619052950621353131759637545493274901256666188560449352944\ 039109276753780807990017773885503518458215348667765593113632706106061789004873481089750077\ 624277799903368265426081264674945537780275575760022766221353690357186676387628898136036596\ 290611552361801597732471110200442731057709726694497223596450827459750835507759211159510261\ 762362879205469349397976272511888732660592471102211977063319850053264314696617652945473956\ 367833930021736067632530991517367346053472106324194131999420901047164618347401107418795565\ 415017984909100095910760171165991587239703339939100549002138731040624590707628588578776343\ 733334835426145918406190117801468011193836150258764744810122608008572401136347189697226342\ 824541392739485614198052171822378659311428906236005529755946819133158333258312942319481299\ 881998868045338456174886829082578042420054638631460343036774752253198575270100475662333342\ 278042987191242697565392694523180249406747064714589808082826938388714340592913557655297266\ 097373353041051704513040126076742555470491180882835543841139730385620674780931803124944443\ 978214861700267407696609658292891873522999715034888768477599362636665363164505774496741379\ 823507570718646539260357846339921656146476418999489080978901915059767489291806535383264495\ 528473599104914567382917145125183147174098181773532323750113533915031214341679392078669629\ 630395811613376902281218135705353672040245344797020339508087164814877798485684017168225088\ 793735909658704629486367497338280762931270927382006991360961402440373974420631946736475946\ 110181442258122055544715645384689517178829563606268878190543894612944167891465560583725208\ 613528001720387691971166658585698697003664166809317986339339062600580857894823884910160731\ 078635971188805079084382127433592516804195372333857743398101031505689585824565772734156639\ 253832123740886161758058168543586610238069022172228315214305621937062660867605610510679725\ 732738495748641627394010599821977107433490419920197261197009233917700563087782465102192344\ 654737897148189386991675956704162138840033425733825525797264759303886308861793541531598645\ 094107105713086886729045855173157185846523859016558244428210041730156840337653865090872264\ 589618997509465649743996094660444988660376566015801019897068665673316667002035297955784625\ 428858237549590216155389584942967543196757773697868865135005282826343395369575849592590356\ 717941363219385336424203482070293387264178533293167922916774402728925103875572773912537919\ 648488833605776093523625375905676432654777299713660095771529069936305885727745210555296380\ 809533116751545077276121468119727569401800755559740797890808814723921604321689776415864594\ 045880096551338862387282370014067434054404936725608952022640589041590292296321931421983535\ 445052151452677209069068659047269818555948784988421699476247186084204380406157022322994288\ 867887193952734468851082185206384867881817419486905215828228292507824421800327550315071122\ 238044172700834188980089966332222295160873764557493715766612868010670618437189502315499327\ 526431829972571349785498584707718777765441752374646150356180872754022199542732778822593179\ 756990590545568608571573878717205176326569046024241884755229625767099024371697047549788159\ 397847410006915075568980050596985221817172596219727545555728166760437811149961456065762106\ 417272588074862382174949761106256321309092785337968048928467953706512871036935254246967290\ 652100808969845811358868513435812912322290263706847441277617413058298103308316042270846020\ 846318141757003551074765702540471929051528515721653446742491291233049180252289261479731258\ 735380136124883846665762317815231239434585403270107867914595250325056041228931155717889194\ 444892694867003395089442926164781624967415806689848308384963345734643490594167473672418412\ 854944819018443660031783933737825316906117196054680501011761942258261854156877111299271506\ 277544751954490570752937693743361985743139600444200112278689671722522237262862495850843493\ 744572510745133254853670544750741982766203178873408964910054389564496115094563064365740308\ 427121409739516526031751343903832269927034974621607676764416853641033877004873171528193726\ 935489796902416005007888802235559280705184349305942107775296744994166197401322919673870072\ 336430308000629546422878308319552252746346633262330360450612570884941871121060236752759282\ 120266772164328887612688380933984815533813709759404949368945623298938150627998053178328883\ 553957783415633607050711541164583915203779874065436171966951455094767869059367504880052942\ 440399646018982881757697748123881749332758032882024039424446107782597445836442302031828591\ 187941204993691099221065292469831695829215730781155150637356116122695198511927380848326966\ 484418766078944841561818578609321410532050671137281993038021923446317523253876598885429381\ 371621366112919035217414623431697262776266163901737224236924307195066292185813923642499270\ 115945502486205862152027745733246804379312002354464113530432081470790054124026452458112108\ 324460414020677271139189687240696452626749260135286267739944045565526540153484287942239418\ 252121287449950297120570564760006964062824850722687086140980733972543675330726051048715247\ 026316108536647615388279186685859622351642026036750298922945440230616681747966949386745620\ 579995976064213726368999271923157150908802880657852895881150900963273283388547919939540232\ 717635389614460047504248254683063747426295764619019051932764670945070069849982751133688412\ 952180779150435514005251276147287989550254507129823411407210857515839183343842353989473468\ 652022467717174881727518791575009418546400255763239593843815398996432848599128779294162551\ 490495191943095999598607895896647252620171860435700664817611313090376711778295014908558339\ 763407308687616662238684073471764718830802501488659359699374732880427694130569989296564001\ 639306780363156309914075865817363209646634815230886338566532250448845550293287736602027597\ 813922290376650943064277293055149736689985098104683412128188450083318531391007754204983406\ 525785223045914249491750734749596830823597072597250833896010159559810683905278932149140215\ 533714549966633958073124776363960431258670699076095718353151032665230849659258829036885672\ 467498737119286779912747437599495309816944988312035864916537880580897773607869744713415934\ 357738536371216920948936908583443700374240400603047573458238009189601190489997418822201655\ 135719164173859583516610970024467811724292292045684247762208107529428286517896697941736552\ 002379044361283231480066638960139602128941834640113017806358228851494427350890380126161014\ 994565446534006150824296733425627872641069722203070258440743420783683937750091615249483683\ 328135722676868777220904738594648401639760917869784218610167966560063023207229217510292366\ 067734998584903821517527910670994279831215913916843876617341087146693663302834528307104148\ 426437116658764726684686046347113692043719767400686847996251512816202541321225133071000980\ 201173719069001152302712116215313496903511513303492374686295765903507514971740771431164204\ 489643001088372240459502294653760796263812152403640211895297322938252223767638058017030032\ 257853009593936856628264927267970740962740412444357824398049948506092560495586836813028895\ 803837647164180195477234773388932316676494379287987060629141245380014514535778249042490980\ 681483540018542287673544846386603335363273383581378513450235706440210072789925724633749013\ 544620508244227577208355286679354777356174638741681879484517446079524345081108002379753052\ 820082162914033332628210845986884403301195984185355567970448780909997501514401359763753027\ 759816026418833627652993953797856966905510475311932991398343333449907657837517866868426433\ 576954014797305462583755098386514800971725433620144586127553726483553480742111907115377331\ 447899243209767068635621385747655369423554113148123998582811438255569753567568787982982802\ 151738323574434277027168644841456484844071205337532804629716533277120196995512992808471443\ 065462666061808582233508211997573120921017306568070321953761371937455839111076951759416872\ 844478730897961413657341855511780943812333505942190015582709852733799403963583274747707528\ 561058282538070320906285711787011544777608651071264914907636586029222976374916700521522409\ 071704946158181826729485345383489302775845771269052102505632973136403893491288951494470624\ 901625069366994400221178175213018532452211261662051599612699202540231984756480213846592560\ 996158776057382889021038182186543775665240748053649499521458293117221805484731868478997090\ 640176265367331100053986410050241291285171771340484462871368366506260873977069947621503673\ 750756309042983846159815606396260723672405245228536472371201784608448675588789547309846552\ 656339069921444116741624356929597674588454072374427557386573090599278949143596416937420519\ 108906056693252720545249604524446872993297697749951322748289765294851021464707124165736075\ 866376255641010923604969899643351828470962523490400467530957589280981730613299440056798599\ 001030704626778040861358512787185271618152991004725278121526439840699484968967962646995514\ 006381644912206561198713331577365939698287298254283742424039290531926392958365536893922650\ 487437170202836477472523421388764548945262732332072482708860312474819152472823547592374893\ 931553421743284809805129364337197271636140030204000745742350540460018976370624656982596032\ 515070131418347853689814875525213921997503832707025953605432192780225332327202697459632553\ 351625935571488840421604418453536875890489861185250982421838170881792623059649479665371162\ 204400986137987459941264690141771558898499748559780406932877444326581870677483764195085842\ 175529304711368552115947565591955188890195716695863005102336651790012908689500467515448342\ 540820388492355417443042219904505364102084156622545477877545100912150565004633106874884825\ 689837113086378222711689150523240976386950645132352344940150509902000629691556650670477748\ 765384013112144158757522866108727002186789952785478718778288696594562137310905240228835458\ 402804877796782514869166015310563177271136034983220657397168217227209176473260276736014749\ 535294209993424083073250309949241061605062022481941095343982858792088017507096660682750112\ 193465121687850361349614490287764928868746279134298274504283529583637342859066360016739752\ 063942183798321291028642488236252697047342156095319579215069670865078447247089512855667237\ 102807854519640187729935554794724061035675110525666586094250868933817410560572614193720758\ 654623353392379049836511312625303803997268208491005258731521059704625138930929371849616819\ 355428008490869954617863760711710473722157819052742934983406109673119155754140862882130580\ 143136260446329651649401817787210700865289331661766305735040337422088042279399482455873747\ 277041758208889565734400625592215195425669936912072034861678060807714392343312038320898623\ 469313026439899142246404652908550827567379338390767239640136271586118779990992503086862255\ 432300144242330472965110492896086716408452344354439978087511674672834988629269879850803657\ 742648673150885509366282453196409632516822188608208560149979843395014517714546817898219252\ 417303552413992485106221515657007539578910033715684048227317398771527535857085576902110396\ 450647103274614859385913593343278261248402329599414053072103377858485615433238076071392289\ 573208327996574219661309493211468211082003959265043635217232782557461000371573406712137382\ 037713265004196344418942288310764883135273925728247943179086211172302309142070514852152783\ 041285046772268660986852966057840272658884302457000633101383779318544500615310715827314081\ 685162881735901405856473481603707212043826682063470576372505922867629540520491679843406132\ 142581945251341527153386043989031763956070152749663012805279819444647272766449174804721539\ 346089805362438094546494869257532718938588797341668941597587129382154433054352298839097381\ 296294635968292896715120742048885545421363764527956528590915567919189253639106238493238450\ 558956388791522505632716912121881274411763165076392682827540950444869299163421916840203786\ 767769138590217271542778375201948318441510028481351884770548460034122325358701662223576769\ 420704683053935334658978618785285649282440518149914034243241327081342802037083191545906827\ 566435451060310453546722640136480467746431960515539646144880796176635050106715788326953368\ 979825637230310259148071496936688317009533848136555547157995652333519804673692758421222679\ 986336853902507426533105137725535177546338846290549021151865393187139922057836314388363715\ 633983700068004293008515472335223976624021271085616963368378313629225962290184589270173175\ 966612004366659753236723479395557584857985555558670537223243893341231570014936716048953742\ 620589261653455842041606453872527353290102266074368983972845377318994679274735803510983239\ 554544822374883424867341835631511359943699386930728570381049247555991164933076844570896158\ 343427281167617483602353334854439283334631230177007924961724787066816268470824083461272157\ 541645418246904196029091067337576271329113060085197678415104808796527140433028135435092810\ 329937037686514453758521583247132384720257771027620323632595322937795536889864023033051091\ 937351731007925705888048147369293767292341598239420013725712424023441678366580677848875151\ 949640279208290489511947465205440115213129622668434321338031762134582716160196633323405378\ 728682858662216269201979886585721923760815647074397852845481280467308959999586448930371953\ 362297691896705644282585864186805879606481346937901887862911465768246528079032330176225684\ 032740877954932846825643764717307718539935720624562357479872140608747932907669776430957923\ 602690659252253227147114405526109491823282490484235499708559816158634401261958770416055187\ 646542809284053912922746808701302096797733807033705756687323448661630216372554149889127721\ 028590079994660677296753637813162536684684584038169571293263351494683033044798351870370519\ 523524492809077346991027872249934329112990163333805300815663981832775980297551851967390100\ 451419525487133408263871272782993325167629982495428340641704235398413055876524853501152343\ 281280763790784578281759090954133399439441732015983226268265495195832281894247227486499579\ 136692265459093446790035555245482334322245004903991853060951100945503123498982216587530523\ 557673270232058389411061722379119943256427484503782801369163037380488659504305677193609671\ 204207470638065847780610161340117231609755694422939400232772078584896809411061604276224290\ 996742997419322094715585139046856585886162919519307753074054826601901092329585787887910483\ 782307147959246581641357258090508151703299843848297508598337753181055980790792944072728968\ 142103645391334012909448591718751994680843162032277055090071136592966771751543975412833840\ 806454199510643824922114100638854284192870285611002706815111480028772085162767826883875219\ 867270968706585016045978535203387776110596867264199408672673721337326247901863692272755646\ 992689055064083999847975580143256042536403654673091300164945677792780164496434659824257933\ 776023059970331358353412030670276374975757181777586853662899888725641344808362455933948773\ 917919420058759990656567672829902281817083999096690491068493728349767759334786539380680750\ 102946093141628625247486106420801967153113423988700574919135764691478956084649912954820761\ 394751723366177203517192599156112483666982037782913070573550741862950718112419677426638723\ 403213667008761266498444704733024293916086257320279790324318951250048328931804509665377087\ 198351026933795398415128964780542337999119293979450272539498408461226125116903546757390881\ 605317726654762749581550627399591025244854884908657243593116872479423247874880479923889872\ 073299182534292517947606793544178016859812998333252964307844397539002811743235145103104524\ 370646348127138090366332320504403899460889199099301857077739121772605163487886490693048348\ 746035595691041318568290095424032403230233521559720220819494686881135548579919657068166357\ 367868424482827508467349562192969076811921913453804312761701484923391749206411642088248675\ 894737531294358269507100431565318048714540180953678154997623218221032038079264756674346212\ 092519063493737749119583203952022432314121892332826345875685096962209186475589478586527731\ 759691084260057209366867854259957293348973851371597783509196779604343159940825560654169297\ 397495021690828006856553426301146005057214488518073258382695990573201077223234937930406713\ 182694830824723632631249805190443571902197635735764333998954053982726642217446559906404789\ 658648216642400693291042339410859540409266166491110522069884200190134864238827932437745911\ 106792461125896057528944719389748992071579611010655271188211094649687932347930946699168321\ 484493736967534765769428113880271698095183929473579035751208944280799279979813539247545647\ 768896400895014185587904514330266822049202347970574042732435720039889221566438393810005544\ 041241448099562471420029149305477519526224172613292407578485167879631277234745485674521559\ 246946562215035257854409706175075305362518133546753563562795558233105749031051941791955536\ 242278562283740875115966529831788679649486779340353433127665223155157950944735703645650734\ 740108652799572531535261595956819606440079583041073275698997765626939420695353855897035515\ 488948847718827037783906907135646820854208383721754765428585310822385918341511851292782168\ 305489497539345514076712878449395679023223702781285287077811038383842381320257729145381777\ 718946252371457409800339249702709153636433445338637599422020808397146848091154447544508809\ 048921270176019981246211630063341317275923216532931611152121381772495628900918773196051960\ 097523090419331791074661852550126464775268742202376132364997153632060367740418934533420610\ 069408591570487828514465142234957808820196389135375473595443891790686117395802274782910338\ 819497453244915525966475200155723610555691967188665787334420479302227276460195995055904908\ 612384773100085615512538248241199589934180375673868590910074140908441652649905922237595281\ 445787333631791769443036327961883222721221785490191194232454136473954438527225819759036077\ 345830367704197842680034425147422427464862632016223046832434371323023985035280674313791317\ 575793021965969377269166396380165981607572120573246660239390541541471633964275244332805513\ 716248069904614160045028591766073477082813906485948627411208202386329974234766168255523533\ 044233236525354085334353563686418732212812633100522948051249809159009138860225173722192142\ 479862255905832762454484845160836509560524363101352254524940965946116322688537197409337202\ 968928824552786617586451644317743502049993877787699347326789263715109826959070277216010082\ 654762939458479760713892537199884647575878227679223470538114759218027357821968701473504285\ 328149514410095392376870680403186916893784627603130214450338762219283854535652575582287049\ 115416929014444983451237097343031157943777651928135857138668438971095259146054509221348539\ 538175625077526962765221763623547806952055849841814997643987440791515192303981998110663897\ 572876536787688148081246126145357128016828020369479514811774893566549329417840357235617408\ 947848307283400381197640372714309633873004080433326949901144911709120107355783855969264802\ 461902130871390401145786774594624845484226807289257012271448917428168458307202657854728137\ 455576906630798024255961185749422576920944629532592414181444845779959253088205828727426811\ 753255024805922608615640116356071327276821788890826919591622602283618659975094161501784861\ 521824617231150531683640224945112244239670101860505774266750711705392069282788112020413429\ 366768670199145774172674115110170995038593176750217156407965551238710884033572923967843065\ 769645539847113995561745649786430313422459550996126502323877093706242868566743711501259051\ 656976552907211621194779044201136089671028569336437880198913770002080557043545278881536548\ 607552781414790917901690893923685927997447581677044852232984726117924851339511847289397398\ 111453149908989533833229734310982442301550184908245435407014293381151769991485031190580744\ 383734433788060659705397878697137003942299894454121796649099041522189118983272948234956896\ 859065464802940434027273152939571674701974817575322462298916358348072612784504610462190402\ 878018217358052770082169594990481594631542211670607377528477134526075229036521559300658410\ 831880014475120165118309350361242411017359126844670043017912976788192632258358880011031978\ 013446287219098997083894631104651001379739374796640445117424214424191327345384969235060348\ 451089711107773573579445412013988479679450074462077688356575935850503777514696010471722136\ 110135575976542752318334324359240757290547997721374199529757136111980310691218723683522660\ 409918819370745175705692215615981792525361829137421442952168991761059107951377457689811607\ 058019959930775321690049662391492098995893002558289643219181800023811062783464453275776669\ 529775873190718192930917774810927822279963614028152993455034062842029855864054849030471131\ 022326930302153014774812171883994944049148743344798978604623926702933000823587939017737671\ 992885571492605060783922510175511209337248448558300443799106910758032061552825809497472184\ 680960029902721017754426756235833877173143342593962453761610570069684073524163249550192571\ 680320190962760496261709318811883922168479572598850301679526711540098695085100281489521390\ 534202824006511059295014226871548505240428570932135836409461012132803165949416228251802541\ 972809865692239591294790278103975661756115571058327312609537996524099886421610321714430236\ 863812587796379307627242548743979802893248239224243760540586256577027225622144982833344249\ 318546480039425888370068292564854058360736922080691764537928789176141193948214730359172457\ 988525024859338820586608672840090828288712012480099001173800075571324705954942763214899970\ 445422519252920457702804132759695064794728030181595385352112004290361793590489669511867751\ 084586626688116863126165478988561412542959335612989559811214200258798331704611030469626458\ 651599204335269387355080282011624692926195708811137455915769316262628066429070717522168959\ 830758107193596082270442378693889273191462867370633517228121636920020837601974177170791422\ 073383653300433393008009267295164003609163886409291815492942469595672766078959366754599716\ 179804581784152347670609800427293003471182021596253245456907427190543892956996375867633970\ 634388363988426743603164246371888948817870372398196369643426856488075219072467417215398974\ 660536780074128400384415713338832456252792073998419141605672989633136856058350707499896415\ 134479349255345662692400918143303243540108010414895343153475966704530612745528871025585569\ 519803479535077213586368130231401468845342135338026693438014925110722434180893016244411567\ 937808179956083072995180891815202869741203595823243515711554404935448649283884890940032072\ 512675920581692003463263530408552076372218241071651073240242226175804150760191809729505834\ 914361482246365395871800169266543686360399852570495376123047124622855326231890839815839311\ 337582869837241767011404509971307094523404403139446495487002466419898080976707268487267819\ 921229235511557912406633641036300967570853274216715976403387444245121972487939080623527219\ 233094282999951721232457404473718321359194145660528298352848360872796083691212043818324583\ 917090632336169053615065303671635639317670482134470154292322735583410412749166498247315937\ 346154957821636537507833838394506954403730046530482625963293764487324280251069553952505467\ 096950099729438927461099600688991232257504331800627844446964716973875272474191119668715755\ 725759718047991340019286365215347272646246132151332831252365605480431813803906832598279384\ 858500581235808776186995904989687706996479241723252322035140184299384353449008958129653789\ 863829350182697744906084675798634921000284857145548994121159040780631097503696330743420244\ 298130732924631785063251260294887315871775422165247140950532534579987724992686777184790491\ 773866948750164655429270207202415681722620624273038668712892082683447932982517927633654406\ 912672477616035255565237099753345954423316858726238393192490342844724094764678773266461478\ 489588588643610222061197266275616690051713761928158802870175233606836986285494226110169637\ 519132101751183463487560031606597426968651216562897538827488592149404825329162999453875243\ 073234085250687988704815307142975204632016103914777181025774599934444831305235962829340889\ 815246052517769657258655650439034462786978520763710568994943728477361254391341981931804505\ 417866416421064975334133383719606006764003593711004247084150397301272854345948892947523593\ 658152897808510967206495891263281595184009482079049513332178537935353039703027941689740238\ 712289371188732499601193591933113464014892462898041232735505222089553361372107763243961423\ 563121764653185116833565760254588857521725693634376344146571662611955018939436798291516690\ 731579798519270236439450715390968836133529787029858432282725303298472449970144902633457779\ 478413772735088025027831776658250414223864027663316812267201162798725985156480360256083689\ 103641073543729734231000932872933660291791942360723231489913479841892332148448608467454800\ 176298777737680630995382309858900745261250373990488480528512013187397638432373178296897970\ 704430785554364550165770815777074165206258503070712442690380388954721453810421070724244408\ 533918192041493524540165591865799384238622493860925523532816181256658930919593181696357792\ 050001431026007132801217022411374721738924476653191582019067133362798244493857795949803072\ 033006705382860583048201826966067933038203252277369301234577059136060213981912944866330863\ 168140003555355279051300231591413107694872170685718580142195612323486590514156028628661419\ 944375815297619776625374875147615387049455401145096854877589955820763333866095774526586912\ 897028686294746594342780960190433319178924594427040650098735367597114101492280127717272709\ 923212019669156723305812825458022983951143492083487445895768312988139420875638351365940399\ 730270917892859291709455482317515575242078978347638357129540538876175758291705810540953144\ 122912092015325074807988925165493191241911223144337551141402532163953282254421105219328498\ 951673778987829892271035542816456814214967078012913792763522945850152063969529115756844123\ 679419254169220470608768662884038650590045335558273689018956326142971970329115151510808639\ 945945358144062037281285136111073135702198306258841603104440590782188244842440457847404254\ 592644639168009377884097304139857393760709099472921453371121226758696141131836955097336736\ 842493468968741350152130584627249194400588532546716096875169941674416611497312346139234771\ 704109092033583018359834890935276359036467365043430915821888687659814734793218362803669599\ 268417831419099011848188485696730403006105962023250569156313257161238360548587642492638466\ 262528130190051759856257988915451887230526550393886266312931707114879800722980629062508856\ 618067655991113207189900194140681145495834039728227430153488339663700640623058096123986452\ 251011385430501571290041145705768430641000539050073214365689270935178067840987964409769895\ 267206662008546120504791157096421930196957570403610738282514165324802022419768083014526505\ 642390729522820279289547672604684535219497140884118816477389071748725486053620971962108426\ 851367048696264324451660506077242935921753043566831028639535567952470128723069736098259142\ 879806242527865361960103923021214791246022017287155835275864497251172867495234101923669477\ 301853487433478045669521470558905245236604635846805755059560250437816338626083634174728556\ 907560529879900813388880312259258077275137393899828047467214539096391642741342772898562523\ 326704656285486643929231322832427378408520042765272785893932505307195035847077205281725501\ 590019725957072867956403509018807508515383872140867961630431794586593728537941255213734890\ 510181263864910511864022719357290443693380551945753167789230851378353178691355680566608181\ 476632722892807948687956901780757504045290398648292619890361651680945500741625404709042535\ 270046984234264961846207376600914720145939923072128203574744925021444910542899433347091045\ 683183399902286340694995011899765629900341206899028349537839137273949336570920772096200135\ 031058391466533456114806749003604519779644341474446813708064190261580034233410368700300351\ 834094133069732180960623282926741243349218104263646537513997297939268944930982988631439861\ 474073193093285447571625701863059631098185741101218856967416780887419350984886014172243735\ 178652845436248180226255413005600973301920674367551021595047797351517687316956959286103945\ 356161661092103829150491218472194447446812609114513172889836684817046259103034555383412984\ 056748147011494964552629368039698806828109877389933615717807177789019940199209347825071923\ 188848589006451713722399641023310908349091046508391943879902032001428504133832619776938626\ 956322627694367585692397375779629129156991073136250344669368209499355942770037672984213409\ 862360771668861369760421660644251249959119285088347828725367972699883993123155586354521249\ 890075360845319958918892183824762084290518320125065206565891631701578460927222401820908919\ 794303098141470627602641532384849886004173871156094361438391145705386243002555778794556325\ 654760559770310255949520309181494027973705270089956970737497767500252737128548409523748210\ 985074663527090647552382298871224031990426001462951735347712107800876077591122022226035792\ 685171443911392711397319451793667751145670030493968151330625247057240377306966141937842425\ 294410160785479274557827496434134038643386897484477437617217926462441175495756144398220607\ 782939369507927681817746076931616431698795147404051253854843197163819853853307710112955395\ 930959427435174576479847092230783160331266951094535721230487994470453236856979011828873134\ 904108399840195948825999265580770919755618779546307279853143887522531858642953583029684534\ 738448689887831840031496299243257284215990543576164103836949685227457827921783855390235618\ 638505218736177566400564873078009049023341487362906583828435400510357170007395708050381900\ 343034105543703943623138732864657478914074498613553479524051006887372827638381383871610648\ 835117970706172867795144496137497452916164961998909356869069356895317833335895641637032508\ 800704276243881546864390596554613748541561090039719646712937685485951064077711108822841655\ 014994203224734316222874066711029908602164432778596294406935217997978077182967521964689701\ 592306313649755397149958911563288741990769340077957213070195325812765197439747198392006938\ 804970327738305727495066679140437869599480848442807154438322836087594609850051541215435462\ 156496791774337827304458458859135954520026002303417442210625943686965528353129712196363921\ 752356216367783024273794730381214204719471655325552067559423145633544909390718588443319217\ 572281680374091186065054878528923998589280877114284754170607985919641820147972439673826002\ 920359692377502871296520934427899136227511082662748469429929830026881899657613033225301402\ 741075193083018987819567990203397612556238334625070701241107549132034167596993277695988403\ 579336178011082298100425635664180780546580109150727059033807767464117063322973630662622001\ 392902271358684207880324402222440645956790229076214823229301347912397322871681953171563539\ 666273811899047123558850174013901902160013623556728887763681224793910748836110323037971222\ 077648499052527726322587309240597772560761663124991753903989249920631505242012841249230318\ 627468246205226566629977191962355395532163011020454452224559906420550165599741437232642339\ 259467675613429334947856721028097135028961162831572373618928865462203336530011714110451969\ 164059180983602311082772912949235568374072612109883808602754450460142612480618002594491164\ 037328433898029083628192703705747701230803661363917906878481961780221040659365766508043951\ 168547041457131744579221068918602492230387201886498706807399671308101983347620424594581134\ 839539832261500206827799881190140942548119032244786048797115606846521799584343377645617791\ 379910590015701452072457339969466436652301132934232119706422959226404401218412921599589257\ 830491722140640567190642995177739075731806621524464088735848124681881846477910924425469233\ 968913998361610004176257445595434228303316681861639029421890966383487945387402784382947165\ 913460114870623283928098241383417907812750829417101612126825336796659971162182617089727307\ 087057947818483708209539422546701775592768867394520198177059859172998997181919056259371733\ 469619396786909693740179386786688940307534079328383389476622786414889690511395151841674074\ 235098185406722278413246718104949777669279736596293729295281877756025620197378595471537660\ 775709720020716166178753023717639871279251106375636163687221420086919438531176089503428064\ 014498873540740654590074587765144258092707366628427497193712773750474136376154494840777482\ 758089350255110425901891716266976178412367301517575599368193121268656807120978976572382856\ 556961799501653637477445461870816586069559594420288900061972034468981563884324289068512684\ 767950669113540401633583170091435657164784489553120622707738863068654057673365693974076794\ 644386720064796621256205952586512203533865122521904192042927109295077915324352472540285821\ 172357572012987341515169029004332047658657502025966613331590614839599566558607583561361220\ 880259216605243697406787897900789905220080932541963581791457919311642222017291138354048380\ 386043680274999591494194464564039415502965332753457323430737758929290361871233698760076181\ 158013904824498681752139121562731844682999454357979977946102096000021428624549330702739410\ 669596146580697142239898981386893048914494625930641552789681631206637215199450391442177763\ 398811985285487271326496997736482027487514085728728574376637835370858374642309756107634312\ 611451965852674848594822208555224665923533002760778540411330942977092781782398388931081948\ 364352789110464772660058571662119470035194610483652855130380226030164638776322978727271581\ 319423042370629467330139827860890012526488390684951068365303785445131051095482093575304709\ 317698889173266455468652673106930223789849032031612675161982473038028497895555106195446549\ 627529478619172619901277659834431015599813126172681754858486142529110235327602414962764679\ 256416402459490588102270191506051330498030007033059455936853646213590907845868730447136452\ 285160275502920152033938870368800361481468109429836409401789211742042786315069210454337595\ 687005992421401541090581201990990856063611511206036457753011604717742015261370917781337869\ 496565052623068802107892838653783470918169566635629382872484253391671195951519853171532139\ 115274159884720412770457066884382247120094074126848036580202863333816821084368302038353985\ 154483163721409728469949343846687765889761974162604490011989060476676168034668636215629024\ 790614104456327506209293702800457618265442089881127278026815377707730083001859853702464212\ 665521209700918599891406096931599740364100879909354150741561131132472358582796818378135044\ 524283257859119301592606190970534675399301703932756606739666571298854141310025739506664309\ 918466639742230239926214462895844138107852423678595193039163339649623880231582694355241709\ 404512296843097126933351953784145149475097957384590009142541467608972483488350881709981581\ 821207351391128575138650730014900132602638218220764208217759471592603615565647662001829477\ 980813210980815728158757272089331817911907547207903437227506824593084605337613800044554221\ 025816388188317936870395057681788434105338858931841858276340076367689484100230443168811439\ 577524365551084931925978937567776920498330998287317267664934776131975526160758281587414408\ 902232366145964169778857508249184811718833449318909230289731174015410604856813218807210380\ 144655666789209001295548698884209496388764942495626061495307821875989169768190409454133284\ 160277798080374931146686205504404302257268868808271535848874624986118911546594942802279988\ 498535273779579100917440389521986428668225822372061173910933273014587306247875195445867040\ 939963264605980648828711408801858355708800625247425278829021029849287966785011400361533313\ 512756935769165294887317443704771855260022501031638941021183802848725856725808175073652348\ 568404557571055128023190781300999371788576722891709823463545888882994696831286659014348659\ 304722881266353460658332652569616940737483829659290675398812556352481700986350927076705789\ 494332361255355592602265369087461235469519109954184333287462432942305446834989127450585509\ 057035172490254012231373302041940096905096924379179057916457771205205210404349462726178460\ 237610310060433230757802494316749141849646886728810464039084497963778858193365291757344769\ 883851951352671823261426231043009614614758268772900801762941460878388037868259313216252243\ 724370876967183783633338168528978987387850139513315988082142190195153594024564162322184199\ 428133796527904858706238482554888469252350572515886056980836034737588223676720590126104378\ 840776306166333561320781926877323606606306072549839619003471817747068820999930041423093538\ 827034615209011847314349282014069434284970597546138362825425161311629042544593907494297294\ 085682681496407389521612399802349400433651288640788450044069205077656925923329161176971085\ 669756261708340039241253111011790210123899712899376542961207506699626917097595649066143509\ 326222795099846699563559336109141325203018818134070551156980573448745630524565481769804600\ 078447581522529374314808979181928709246097280942443933049425217668127812944328956119422803\ 512028525115245271790078736616654573900673921564796930226068507203744016025724374674159756\ 607135243448742485710193306848678073543478633717709428783686031291399383173104472077179184\ 886535456021119674559015659334686582953364016753826656911996409174522126832974919503136289\ 933364856754732418412192079950126340928159196408414360757375971062087631536193952692779491\ 047542731695934316939222886364705277855752930464013796025701009374201302846370285685260571\ 479291414922406871977080345864102992876062351199244017289975407712017907738284616130562597\ 114680962351201106370012897610608063328537341758041097926158549191842258133799889270705632\ 852442962750931712267305401289905428988956142479213177905400492577900857674946605082136137\ 525987323521597832792744169673776349157314919261385951610703089406118363010102227859866336\ 569044674503293265192147936367666737625969053617121945342701582194101909464070216648838090\ 677642930101835866321512370519008027360708994580409865639031549760220964220226379788787689\ 143579639618810890244130861746057887322545255177467585667722403689285522033371466091680983\ 197630693218796192103118264664378980542860550933808338043766426397706830392200245690578839\ 233062311541659799471990021149030178469942869837887367511955061941542856935185051025758032\ 427912389544479190806493620668725013820400584589968526838091944476861801029691475165700698\ 517152945168116048321937307146892957984900047680475536170570484405334427592729382484605976\ 545466566535884805084438721538353661599463469803500057705621695081379300891369683576586793\ 904772174261801675548696576709248538229721322643265304056614632366113587503061522227926010\ 958784918854396761414727435602364202919511826412344235156519072450811535199534542241885074\ 153958698503911718895078107080509116215904195078059753998661484643243177110118656892850783\ 442211811695930269403297422469597672207768356426028044223425152241368225476776994935008689\ 656086065249495443249371589924585564004855319454789708674398456756877465324848195656755873\ 244462794804886035158908294578771581096602994516498444645409877880569545643492747818951059\ 028961035436235053189651745179680444408358817467214600939660252902333498150965252036157591\ 902979245627704812243582857143551897711588161263717332081622570575613404981211963802870471\ 336291893288494585760206806490344748055849652151254832907618351640685594042924128427784510\ 181604558593506092869532690388762616539293735081749482601075832116979015397104228828934666\ 396218132974860409170477062873967635313216687651028370172008235851718647027055926223388307\ 336059366903279329965904348686170498525279011326799499731678058212420976862506564540490618\ 267536553088840523623334946458282652712153747417832368117486672397579422641589980549198309\ 317700805308636608572716231543463108844210051683928340261522911811249278548278326972320360\ 934981352046091198631820917557904859547273769604706272698012471738328607622941047728399423\ 450324155680092373426763453666029240497479097176047844169544360280741491850711161465114505\ 819240223558251765486962581151884814014621810719266528164627155369679215126004539892241900\ 626083175504259230920813914514416533896758029032275355237930979402726895258168880782303017\ 204505150353163165423823114337851233007733817840804361471501391880694207607432003634874849\ 315903412714425573071638830620431690101710625775135694650569876967601940581105289099893114\ 371117599259328185216127543676488911270885750548321218660991685296513211670582314320801961\ 191128577869773736159838460311722030781284754163898465992625512072080777257488974731023383\ 294173752554938920529454762128414606714020600957874901148354533342485706018619559602983005\ 578762322208184860306160311692619062637503959495066957227831630767595632160134146350360181\ 869774006332366073913575791259189077140009903336408396438513696866846994570822819096452444\ 107901963546223584024930396493463881480353425291648271166661270517169308463246378078245535\ 324244772594697337990498955197157837543110107426132009354778017975896510396200323589559188\ 189152711560842845247467301597192815532230052385887579917432904900062019269197477720731674\ 560234175101026927969017008596429050177978663583004738079672944834802417843703596315442019\ 553786321408156892232451712880710244650349751541018331597553334691143906523015181818467112\ 340265412467803038687413513013256096428580617152100760692601361348261343623238179347956725\ 982322497102559552332240717794180265028655639470568452065290831529571264824290024802176715\ 756159056642983326302541227987365028416903989479179755699748112265303758800968949043677435\ 856563357546643546432106029860690683429527892845536018625699388250116316701506120472925394\ 607950252300633063508396057259118206718658553513509487523105914621634251653432245477247366\ 846143787908966283399632161310121410468720076976969013194142353472927957814803599476423700\ 624665605875534276964310534521347603945466740363025385585211403334668590920994150210885990\ 171293786224372655275038826976475817574367017429341588866348655036052745085438470771581483\ 793170962971307078017861337824393628826109724654561305060243438168312136765050571557168883\ 396514218416983231651157556336333716624547877283696203721790898826363587593439823757390275\ 393921528760523338145874222057269755701336000264903385935204401807920526871939067642412941\ 713119263425185485850937163701999845112343197450327698274830338061821285248794546073259823\ 731372737549306725246374674786624904924150987390752408772753012248109119408261516463218406\ 034603355718751032058251532819901750701371087836955081524995439056925542293159572072798821\ 421824907154977220438723936495901014429900791735930488766562889488461332699749952101133919\ 136857853084470640224701031469667939864838228104602650631439497178296727664526793301890560\ 544097513839761178120678280043335142713311663144174641471697633133861155198610421193508600\ 930740998248170361256319898227139845883496832441708198093047991933262207778289642127679752\ 951675886460583748767404748146752777073287570504838681723593679882102600952550590932607747\ 306617721965200690361487421199442782141265419708256376979025858379842499289875941640367392\ 389053100728058144403192143473606696034929338131214771630889625136208516193385414622223537\ 946389013091788077439033063842172792692710191258182088447460767990895321474137443139729313\ 159841868129541300016023412142452779920082610674625947433273561565956699489604641550646678\ 694083324001222933101704229546480695365732519995352027569434991436129053206675468097591085\ 811716777461142783730921398282861318379649226058495599510161937009158765942645802263321605\ 511920817340931940855111062476817387065373915435672194882316902162367535454500232452793657\ 079279807535125575957312112058303346129069488580820230466239782242748024575930399427475221\ 037140268929925692583058481935648992971661719383934194687983034269590857800764424779549973\ 417413617837959971049168054538655823023748717569568190095751477438273097312624911663627085\ 320277147873657392210803257524029504907950219224413755795904278738735286594348928121945376\ 197021963543970894274463642952002318601485349156744729595726147599494276274143042433796341\ 218547554263276822340547033181007364597576614562545630461670142612317842731885602379778476\ 799361170226417673569949319634066002934207289065927064634384714937706457829874814568308031\ 056697717659170921348331669421578921240410075415144435220998298723588432909346661185978318\ 319085177353278924291593419356044526010605881386214589924368058949668804019346411158852834\ 129559965299114478083998879656961892753746999515347055809447456231851384549617828576262817\ 079076627783055510515549733616061188755311361483047681813880863412260089433964360813196261\ 268131116788907507023599773943571669743452429831368209460617079641209571057221991684573482\ 053232096865994649996795393536115119921241624458076057441323034511483048398155990574301572\ 802284741282501999063448916077721403141655872385847818034331234750110190701294410079217401\ 668805693260166145991682562696098518494942225329121700225143173761551010438635455592406750\ 651382906234392176099513755456759285068221103041980453267426192588887401794279915871911524\ 684476635510247160688105273312816328479754190974789509373041080861209248017333421900530309\ 657374788828936446109172890425977725059692749619015555285055778124492215455320654443105918\ 828180538945800356023094523588255267308278404445449798748527161362662040263673841119773179\ 564702927443435314827930215959736307295459749443532414603154177851398338181376878063627077\ 530696844104304439638496555460815569853642677987600616612818829429647745376422754831901188\ 521752002269314374468989960204985877574809214492573586609350162351655092864283998207835625\ 335499941145102599757724965989267433129617389733389417834345357992249168911286199331423411\ 284210407458432926756260175286453821611210995439816162997450775388620493788751336622490206\ 414027173907891662313414949431782400071786413604258416495025970942266273281248195661195067\ 388731344054539220858837507023861428174911244461159377513740988217710036243349796378205109\ 921271812807539241828529628115700091541009050835405973060419322904613427518969890162564834\ 352644834736318319821425200816385226296146031007542996134386839214806332348234668831911633\ 998387586294656644656839888578789681742858051327256282424899181169280170888797308943504746\ 009543642312054770251572097937395137552287016612542287150368071540341501949004559776796757\ 282653893425366443173831921644756582311467946341086878001535703514147443573928858537740428\ 292127114305966306452580167846515128779823771369058916114346688092543753702251188897782796\ 807550764370196085451664361821364316063480819477924351643960093644745191724521271915909690\ 552376431093325400280023678466670712159493075802006146253663868226345649104358915881932852\ 761335285379529646132866921989207362425384482904000937650134773445049354853132198067656598\ 698727405008320253761201742549435875775764486721447683725243136547182477027129343491406212\ 240772181269861417471613356146764764151876680922448902599828262491140650835908381854495492\ 338628128954261806050820113755104631019532671768885257961170508154971680407597056215903736\ 489127580672591212055324835654209789779576771456896110893415882109450111971919145100022524\ 597028066099913739570953788334672395642957089132569498606694997277969669148689796071045098\ 074541943958199518597341661907174870822637136937554492885825264199680677454879942622398488\ 787746666513788796515438312502148854793427470719154282795100757058454143095192606262380721\ 738213029317283610286284307507573679729526173435001235087776887932870331089015001903344968\ 251055880736424481253040418517612995789856916343265836795894547395699355086005211052744693\ 144388569971342873473458475429121048341099315706244574044446418903031614630406272972646074\ 710196659350919254352692509862723817386290899479698375553924772100725116927597708004442124\ 405140376159143620109916581459672070264034702854191237680443756745882892470902728578915992\ 614815685959423582935454200811822358366898566625877120369738408615398372010039191578682058\ 422146180748226776442893212136287521002797826970822393931342863436318529292419194576144943\ 757620923985263735522648362305216424122417740364082996332920542107392678476481010196197908\ 021271850340265494849880490517008089931846598629606244364184005145761442948726574667777036\ 530636628258992413791300461509201621248511142658566085911034512825594351097697138576345387\ 697109332397747567045041077364542545065372689532925079559299436810391846390548749144163474\ 930614662788562896506396367543500975079542662304550823570221621858754545199718685418533524\ 252363843859008372812173924257694486668122038295065910337240987573186567618134670026696163\ 208104523527228251726043499779005980215735982954434878743534708917673344834034553886715773\ 599062253800606191712179756889532151061354221388818587609400572611543271095191347262668663\ 705128976609573125547406680639067862933513831513989334359000507105631057790180432302862392\ 273566866742189584725874906975353078297359428443635642563787648510266605271591971047817311\ 177255348780357768725357231772535907746853053415483544252799492158171853643456186605229221\ 032721799221730063271041585912609589517706332339890364321263778179617740151158642571690395\ 147200935004945034311298544965087580165076571182837412909509480463250895561842304032662482\ 963282048087886542392064906064483027216616876822915700018176513006370759334087277048205116\ 063955740859431993979016036204798613774477664905366666316074120139205156219891362574442445\ 370550541767303584272562582856454696039440673592737205376671731070852027229178157111638449\ 722777756607361546495264976274532040335232912577206460891489004876607153852025218792835341\ 382218611774230044608338762971143335675178502916970926955159494204545552443314140714032704\ 431925041354333655176071220710504436643531857821123283422816261699708969661310046237295250\ 511123172532834862411773812621307282401317145873195589850816188088475315519158213508872798\ 997422228725764718210489675896435148620844307616896684119385967045656711082264238576938518\ 384801942602588261560111394048359439774648867116916809134657651949445819991049952609340783\ 364714860643270331688447714221186002467332906799725364339440538648831846097004936077227866\ 106437116009241583247228697743447282521075822930789550860025019564305250224189736342842462\ 366641207856071599888260626400580621718245249692221644595186238729630617827226672800198422\ 656899408972893875160640285551240831149022472734156194355177004630076718399841789718834305\ 094987298375080029946573578890122276834516809443252118978225938466450906613649213071511916\ 494107017812506900869541229695700637492923913619549568629200836308748879666735821780803134\ 282391093705296794753131608961444204070350707008094577206761694455892673257963042255548134\ 751000857831749267747358088433381677471853283734728652489795523850035725995068369426907049\ 523495975013094562357752765413878491248342326051396460408105687685188859628190855827545893\ 920018606306118991354415037847605309736746328565800917768304267531074780665695553023582486\ 705171149438948554103301688629651606141880882095977511021018742631193379383823505908384280\ 702575550879559073468441344981897698191152086710385471294423082586818087894481716571383577\ 679731054668420118088584896274972346353978050805156915998444865951900528240909565008716423\ 336194766616009221398195969325239187054674523437104823078143337898083329562258819452576964\ 312719769516046622279106160144847453438360248952314398982266794881310118672780014169419050\ 776160815147659090675658137386946237175040344487020912757045151779086321697096726415298326\ 712782507675797106577427718702541822651475161744421039795430855167386546078138392320057803\ 570653585049880033094110884708466433849033467612735561873980778346508910742982760157954002\ 236624566866809821613043140664031049496036286065992917276386850637714113923545884983167815\ 652907864830112643197861692291516793789605260660661232116801087208156959976572830436885582\ 845117612582626169617295796298566178971093489394348689779718596114850553509619622122418729\ 702240577266266677683138257039799842291250618878517256443687327444246417667477707572572063\ 391626737054250274813129317264834710204241735337358218008385460245805343685977136972208301\ 879705055912110583151904081209667431953887610246539443952747131454843607597716486468398898\ 359617921534899258814867376931255906227113006988736172997354567893896897071613501747004449\ 928827650406412635190337552499136186148930714067708698560084099907013999728219464966272649\ 003771521321181662470692098247282363862952575066944847240231743342818914945024124735858882\ 402862163118244687716968432963380199971846189912431160296511484512325013459456451081924049\ 375104490074889946248342632033043286786457130261094944934265126492359915712181408575033439\ 117337958597053268018363086807345077101045058116216546621378993456576825704154439561040053\ 974379162385566349957596498928463964702092285820018948152698666577545870361320958467685990\ 526680001768988517883606905767374226965175309125679816355284970214477336316572849524007024\ 180855772553316643521460066301877146632755469103604934372747399911029499041227337596775507\ 122768135744889239825357769072582115726807666414555372452364134838707810546251135624495471\ 680529078905637436947005971235349957405614880165143494250275798276186298890688094566508412\ 787080233040560926024620020571919262848702287976920295383213487182174231184091484721344569\ 403126363110340879579334722287272550152213647493951891259327023027375404069690632943782795\ 269126133441843892907245451561806102417332745061519944147527192022834104759422936565847833\ 699871564896025522719089971250264044562801899810750647085746630357599061269961659085351598\ 533122074455447154605955489119136343505179852050112355785475415840306722799521443086434180\ 193600205332598156248383961444134529811214948776646297329715400350732119614738323967849381\ 672172524311212851320869358804052910307883080604552294509005305947666568225924640755107801\ 550230876180090849093334932440373598268647719273404588781360661902627866657349306037685256\ 205801037493603330230926201672033853837595446529107263522560202037328726773324834422832233\ 587182422008913571326735751291333604263957094254249843287986929024430301135071791562044764\ 810171707259347769314151093709708951490763212226325988025634657102611308467509302349152949\ 237234410260937578374711191854221505337016568085821820702180049157032358131264276837630589\ 332344651188436623345034567009629756230488974250263472669088694642559922096871456546176652\ 309310107194887963915412001451361424816841180189001836708347390876061149456250302749044339\ 849815435499211722912846836566951559866002757585345149729187586201747220329824371591356168\ 397184575391927021334203912230448648491080047684257094468078920518380467290122938245518075\ 509718056445584598968595757552394917419383669105388255131305146508927659000058433002051139\ 273058402293556617600445605604058480327217382420126945576812700527439146484129187636539407\ 001552742116130702273151325069311983555537912205542121658064005424279993255895267855493628\ 492911656645184070876318177940699644758092136403954285850648591583226178738530133847336255\ 537921914873296592236339291837132781075852931642375451999163897244591049509176989849199565\ 679658472393403395143392970138922907162457793387017193259631433806587377665318977448056243\ 369854346554291807569250234267246283751853473698715727194839830044086321988194151069515810\ 313561886779022529111736446778372690431731200545804935383309248711732192258306702575543717\ 165820356253030316971537814678360693675431449290833972148942236619756706950696516167728235\ 463509087872805727413352392452886870340604562906520722239250754741028563210942759333722509\ 650426082863390555393851067319667429300085174194600515130046579385844563602875309532344522\ 873690399814940510921300869418575210611964839395438981342183470189921744938144427735059566\ 934163445292075797952650691040358027115395762778337364147244350833006523399242621245037378\ 758062037327219781453378341906665300606966655193348201238458926830126281940097887566499325\ 574190455724051315911734497183420288755292671709030012196250561747441302659016075245625599\ 936132241320959667126354194501917191157589279221009679007282018393194546562000294363577871\ 491909803616658657650489167953531767605443256759393095198984961406764456559705765526498906\ 231339921626804040051456027428805150700850243154238874690019338272315980482647707049426166\ 399257352666934347593336324427407969718816488833387788288344067148533061382835294761568418\ 389034797574866398470378353928971067809193040096136180676013692544260524088820485535751559\ 556499378159047064721566132294877751374425218262836451959383613389686502765867773525774825\ 848960820214433691895898042968781135045302747100781659186622646442090914706813389268861775\ 173978736839106597371934588147793293851131983673955758388148323080824295841441631271385855\ 917789085064493464590081816690735356258772845651307569960798811630203316444573883232909837\ 319721779994181019802826872528508603183121960862462900670245711957343566244854774026998674\ 596819003575382881685522273190131763033723266436015277103898786952029305704066639866141337\ 626320351319345567592350219969803610857287647634746913652499608156950131746040404710541753\ 392927889157235880891058530471061276862897768824178211382719738056283245472693102092061119\ 917592853238281015600793094741777737017646019964614449316198816060247134819655414308867937\ 757283609994036705227076603048512085573858111240933754861150141884241171460971748015599595\ 003877539830825340620315874411523372577327854664080278540715866650805028855308234698945336\ 656255341291268103580385262654214072501793065341623471704481656090883087619695756097047309\ 996228495584815486509956444664891122464352218095327717792811697155956602737819787265622964\ 454464429933824256516403439820352777524853990489567475425761237353410835885338292713090103\ 902256448536000723136640176063119001148812410424385303737706602260255982046109130252094283\ 505737912205596953753566984398946595731081588998791565969702777839497984786078477978629563\ 453913077804911010567742112047897557699922270830333766601117956128734300339923192522833411\ 977049844959098503364600824305816091868805894604155085874158177190453632101519277998357474\ 040801794336186094691775353507907875877415383450255511577449957940456947268049960097035743\ 569986212805027571276675351193073394863886378730307732966730843023767467041643825239197726\ 202728031264278889275733287206994205364593860664818991502845618257016775995443801818113751\ 312643342364223408129120090001373247821715367686443843220229347043549277037013777241431266\ 365405608641418970795561150280821080815953430418278780148208222519530524584985545714810617\ 899969475504006430884234316693894694854252086406149824815484605921239809564694084898367645\ 350416995605934723566975681467252728049734114805518518162627282041728380109295991461001811\ 792796504299504396321662138422781459703298685436483519430929869107606915330053270561135015\ 200199449329292599686302134707260105649715163050540961735372209516219382072637707878111322\ 558032921773765440624952700677936217719716986549062680435802246689969872046547718862130044\ 372671756370437393564577282447032678507320246560739644931180502858484183632360281997598713\ 231015011703253315472218370200857791580091793516179982048422577878387517475601606934221405\ 592579675586982226706023699515794479427175976571633567094860866259106862551186518258689221\ 515965811720516354641482892265059096106130144755719163699403966144352642836757091317404185\ 767318664184261987775845295736816116350543902133129856810682101402882398169127566380898638\ 877061236180335474602070347087953595906270623154591225159972097070319175344771657083186150\ 654035685225016364626824617185051541199983814295034540184008384607097224200222874808005186\ 787138472028975114619820504296351210332916032377192211595012189806310050758259422555861300\ 270595769687568130373238335937168684214832104340690094758921774314166000104411468555856232\ 763421938498186121799083110385816311215856496687372766870746740227458466959364530193717718\ 917462194092542123711688119110372006481328337841571911548511638699884238623131864919596071\ 140447959044118691982406717883039264654407414349241100962577897224857760624559492542318049\ 833462518953180451730076321173567624964084314746717021643229159708644339285036294277572711\ 819047407114006348125896185844023458646837758031755718396098765058339289711033362465669601\ 167202042898850344349494287017202312765300142194206978918737784815087113216722779833208313\ 478126457653158859005379502510429197092639648954910190044219438700594779260632017141361245\ 432465741902769872839796848384189683761088559896540699375988760461875484242227994316658178\ 861886557406566644395739664660133840577449582789404483475806628885362937589806758194323851\ 422601423726670283957538501412687244449776551462000241939252922622167816213964158657436163\ 040486272385543188407361456711776429988608098779239368396074868786211248594059688233084119\ 917781197309620307461437130078764124598689024486757040317774188136620410690259736682519356\ 673850989976286983201269401836117273783233148745603159794432959316041177733145123160366644\ 120775211830203673853607462124148354289191848458736485488648291548981154739096146169125967\ 875921821161702875069766807757002325875440288411567023781484807840250912480453465162728851\ 367175433023563944912355507869850051027027408885642127302422846015096772335264381347830775\ 098344306007351956768425942567794552549384907902317973547816136418513611278789470816344819\ 364272240013517554929759603175418533003149013710032459403180350982090950959641653175855114\ 937662712898771150841925685968451706456681020489500774892840866959465564232591744149810197\ 905682329185569748540700793090217332199756317623130428261627425849336365628949259465961482\ 927159692117842139889148023790021073243779938152586492817958228136404231330295542360201901\ 553762160244338417362499158850390358936152282212158210217795780409228106939494474844917056\ 331878299547962231112270897403157072192599382523402926463890317313670936708614219895699314\ 235847899690949804934372276057013507342513151210217240598122185618345007622797569892770351\ 462318316885273406567377480489758766147249412816131762334315543381790664076823806742127703\ 316448017583581366831452955807319039901154522094192609202327416877811680836681256340742725\ 702293604366964128525422604322112388390738318442537511788396284206959884225549948286603878\ 237740518596859768003776637872424092223554655739050833196966907969605727770664279569471015\ 224821793073778368277733175750292675406713875079263798714289304580937084457930590196376964\ 222793037386011761092884095554486917238405492519115759009220707330756375693160585797344502\ 131200382016398541605742930700995092426347180175009460885731839950928728554707867164533289\ 922609271976197029362789681815567143257710643811071531868127448029944412168826280870546744\ 903565175734976779404439384127055944639123129136636760699783120612451015684427705230116829\ 784464871555444183800845357450768553919514371275374590191207392012984868305391235627565711\ 584040240688911241600475986876504057813389228654244361765477124312789893282546179445930108\ 264437162837527047258828752373234187151851040857539402412744328544872706119547429957061854\ 684263555633451692221839807369575289024246978189469252925025219880154065807892137244776036\ 423842700980968962759674488551167704631394190150662359127015737111260394696820430581926733\ 256318393466113988342289536747485380041716180186349956830377143653022893671292167636165100\ 223486497661764900329222014033953856632790699003111180442325786684173287902049458537224690\ 521231940709674140088895027563720760296889553262262988281965012043185574196526966810611356\ 485600791977222272257273494002928202733688265349456583476301243399737176717688239660879268\ 995736248751901378075038988160933076945327182685308278818998953699606363539740071345786945\ 704681736811392358117446298614386931464519210203484506910895321421190305852424804889588549\ 674830835447968471712119453733644845352205920611552853509094721659058788563289453195895394\ 748252143447218922917918649017750312277970595518905252233402597061549421724048654323622993\ 216096334952621851349182876800867291081023606339921547021559047318583847178782877434218847\ 949623931210855919643553983401089624973746379026710108192628624030351546635592378648321618\ 568005638280878942628313379747163030802302300780866082921486458742916647162156551101021356\ 187819360466509515331062627356235302027539965833758897718015391340744559154309353188677372\ 833574169171838290564081102769051513052371807284659795182713091595097814286521189174606384\ 631792118172596855291711480713196728202259370004813177729597801712872337484900407004680237\ 904455220423788109698499399216382606493407845668277154204294817536936992932318990381671067\ 334155397421651903807414560551293248622759401360833428527870386852409376835906293804114887\ 018268506818487349335147567216329862158909746704645905076811500583795578083647691717992660\ 603057985340273553902538048975245524786699707019397318421799388851228665902302980107875928\ 456766103157058560315059605264029270366438710014485610089781338681219820049553403709659882\ 424102288076788642126499206444161387906626235011925305047986363762112769314279208699025482\ 351718840191663907436025303855768474961283020530158175628441745059761153397724693954338766\ 535644580585058695042789114797257918079657294687686956199093830471127359444178836385796294\ 375279045917144647700085248908051998056697404480481424387678822506918939410015485981885634\ 277750709941107959533900293613751781618204792072749359859969185750575782120419201263579884\ 708930918548266801442486263195567266434392821998238797625179917528708198954852505058588916\ 295239612664494779285148849665773042438467880174588252236930776474279960719994231595848400\ 497196291783100023559471440152531708350213511753504787976957751666556276476476551327482732\ 666027173210346867628710982694247340680508025244279939734854589764374251390320423170232499\ 849480989217364403569103231100177899845049941941902263511627264495112613656674464371885254\ 342467003193195426054545415270733338754423501536679387657197659454551814449431616325777914\ 149474348038118493416204790740917873665456910119905388710211890671068495269518848332825176\ 911052015406897806192739671163234961512846274389945203335334992824362124092374459316512435\ 913184775996663104000989894830824606985783207455737130764564652333540445890924226428080374\ 602513235546093655724652401873720845995304138901496663630801072347457321145695857402692973\ 621209309791949897207359410970557419415265771297024299630301562708979094512142654206107472\ 759799898233955649980626996801335885898819402776821730204705346310780659580549436195404154\ 060174148240622817757214684665517114991546686881304000287082278569397853923649272962223860\ 015859091188138226667904535982875824528366384424841932076272025485267982651479440999764422\ 015767295818930296659186214987801948949326147726718272643774142448721132350221016939321247\ 105951305168483194939941079932087278547502928031174083960751254870741602494852089227734215\ 886213321595746380769756649620783977820467821265521235506632321035302789161860832640533901\ 198993455369552094683219899775601220559878435939220633732792603806737511936885237073469769\ 684125746617059163232415279072526376867720318611405220312221311574916487798398862151803250\ 092896259313844879077068325744877833205255276932958627863400937636888428825355543536721290\ 302340722360541087832736685010280202944103236679883626704744391074009553954398469956914971\ 673341984561041908994273635306724458020293079173480081498307469673250285557197313099250507\ 249931761284675625474540465959330843269298116967059857106396612516068964776055432117361858\ 256270827071263226914839281894107509879567721066544834485468843563643124658593828649888436\ 107587805085526627913555232705004963660697362242047152460679127360883361784660087637250635\ 187041682368638741466317571307672119858968742406773180361872163655520831896016019638558539\ 292601226268193133075818687605732894232392727648656578585177997546452265376546159208795245\ 193260342489413121040172817785066065371959108244328472345023026194615076363397423844874358\ 399782748566430033032469720113453618423410065955425820063998893459311349253299742524912078\ 903590228535422010334009369696159619009253574159512268496145703389951572421944131103149253\ 304664403652253819007274653812671644762783441805884835468517077108145219124162007481679355\ 724100806880478872550023577540362276770538334711445994876029526655823679288938127666005098\ 049816855337125482214314431536251518385176920174042217250329445342261315427439187491920086\ 059387824451758769453704103093470039807606052602094522982290229039200376058485228466301348\ 207198723730491274229758591360438878650727836437712543266467251415077831982689603947854276\ 509535685374070241842081244911196328258385529392643800155934911760290932501760379552799343\ 762412481957830288059594639580312655787403801308481721182542821280156649650920821422186682\ 461799571716513620879243834968139124172724543474364662856552268741640065483418511949770107\ 408992703343562821272601287426884729719690791069528434065844564874271144060092335928613056\ 016485828207962160657559035333586959452232422744935519608371918402030642747706180638648961\ 949960146091645561858531083789580565762788161004768595630941035497775209860894080959024799\ 473766387163103612118666756906602351629629893710188012702407643885233531382440225187091015\ 501488391506482313683297689527419365806484160147178399228842033458594540537799295930824070\ 718839628246780787022161611743961500563969417278616700120041803543509095677353332609200816\ 863528754301643281053811680845204129709498373534442647817648634143945552463418339562064046\ 066957285158198523025022680330812173155812069046160454021487226364929484509374453520888532\ 723459371298913236866769111924814033441603085721525028330537101362416089296310100477920580\ 694903905554466900528354374662678283841487795483219167589552955198556732559390005340000065\ 934508975945835501469419085151832722440370663406992773069261345635476309013283923276491870\ 217079671190938621082816446990458523349076496892500161067031010981248051691075464315965692\ 566868756422683322827108364707694275257075066925173844085554155751509520402435611316220181\ 088342525331092038245809778830174778031951288896869362498020229478087127281658975468931895\ 643211092972768588561930172750681755450094849218730209594128573739330740060095524404499681\ 236633852266563348251322600679289940899671625890035620485640354802932173086614288648233393\ 659514379584415213329893543493795860445093195351016547591597517684249407355553374293857652\ 289410120240278277300017399998270500577576177565545131427367222322714157747548790857679103\ 080375945956779602741022893285019452239615925328671027145397577072989309659271014091468067\ 400187475664428536181061055366412919961362451759859486306589212698915122292846735609249200\ 828177140174562688083411364463285526744914800497533867214948971085753286161448342225417743\ 575780230174573449149922612971293166120212772165437618439703331978991909659484732063567366\ 559611917095717452819241669407212055917110866949373168667767890639569248348937949030442378\ 571044533137796131286328318935844225359288801947174330500564297511738794377047336201148470\ 512769516567118643091960868612848331421480217901159788120865488767240183878082864974643732\ 246200222096733550461352034595627339075344597948856586511591935545814721876603525726867860\ 065213732524807652046118864579313656829304259006011793071862595403691225589531818131900372\ 931057928638017614518476668949744250670850278123227450121475765493459196554969443599270707\ 084335359081511761556995693474118882577325858102915459578823734242769662966256118830631503\ 829181879466008912808572875247358984949383675075864175759427595871507935038398908660793500\ 203007761085648407996446134924867828147567703630865463755844284505829541887086954692077018\ 218159055292876913039320563324564517424713341436242671375367373181067137414220199287426233\ 580803044569066320253366490846319161319335301403009540456731803156306144720659642682647874\ 660069812180630492879514503342999687545771644365498053426979482556428705248267079690167513\ 441509144144131618617805712196583153090407080534113362420310416730802213498324515973022264\ 373790527174217338863059530594381390804543544478131768180082356448077709763007029421141119\ 338844607693108517476045355991721535040987781506787079076967278596363513147143655593691757\ 185450540141982272063506236953563488870351362781757756465036624715666558961869266828788552\ 671682860330039796319691921578428699983491524072610358491326508085550464177573950192541846\ 303901458069485451535339847511826349492039603140999348754462816910500771871838466538979536\ 873667666251980174194425896744286859652647426152078379452305241103819166120549260471034086\ 283164835599873512665146813999227393287963166232138672440062455418969459903350715899895475\ 915389640427047989744649138719427950500245234301846573418189193575345952179821039411171739\ 029469990466364835389189686291453764321336692306313729594174779148504374339989183746243681\ 397900835904480908754814315963675129943148349911221875619454425063882679545726737167394534\ 086627131597426207576561043366990259052475251612183028907021967725540511049489483889972901\ 198799872395060302741583814560472019174019884833115330376992431559647082339281951126697085\ 724232748071282739584618665628878360354435456162854044828738621089203202540106778723880992\ 790638014979436173533241954807625274107655176220331778441627788902967275062721893175135182\ 762766099756629957843900686659898303208965787530408844659221280744064997165334124148471046\ 320147667890429570606974785958859911900813306146978312151881988379372571255973425594320123\ 199287940302041590527753164999276366961138907061422419975523621994140198944119539334729302\ 457484469884519353283361007798303595981804512040598226873689687754069109997977437561889754\ 736552353913488246092867595537813069821600506677990535011073151876833901548302445448421088\ 023721971347774876130759774341571398733082020735546859723805375846472730949863038494206926\ 807068836448828040676977527628323252580466545511726731537237003618616774498731744045666136\ 421956273647892820524256915739595719438272772610077630502304170154948778466617937856174054\ 968692262232926567014929917892403840642894949723485266411480303172151732573764309001788427\ 178999501359700292281393779866553972302206506141330854134288363857600587640372519852706903\ 602069307183226508788867472920089819663852986286369007160258347900956319513747168881321181\ 833038678376918385203467244407642929586317702145321514469417798094799958356725046384751363\ 692651879190774733949165754498890637427420358728770708600946177784372733444631095229909526\ 987527819854740124491042255894239831622890985249208587904811524579085765944088735391410000\ 059402657158300935972603158553073259581448389153617684735656561454894351663170852644122171\ 633069199061477518683151947668920581373622759088790945739731962443896461615605787490188397\ 286972657585324416719387836539477567199013504451556898361276883791950085179176446095186356\ 971922730002408106767341005087045631433425448437673302288410454327525975331744117364662359\ 993527409435500385577956931038084535522191536242211444408051675927431862132981810464259560\ 835999737663371352273010779395322730038333361223565723580438758190192977114965592592030411\ 547163297654591830516636713771377888458648948454423175270614172165704284619377238044379629\ 715495322785666942730612292880726569173672489598019437776266515066095309639595856671534915\ 791463046274298554081979343276941501107305537246764631350395244306454173393493617160622414\ 033002045262988423833266183258222538733879550081091978094694725506704971097457845946999486\ 568830815091314034716070764843418468372119267806947319833418564767610637176800764367577809\ 919652232141450579142275079154277924189033563290060045346267048863077296680614536374506345\ 595867910859020402491504567641761912685892442918102627588398480394191899575527091809108350\ 689451231119495045185174002131707109950541864281833036123980553827622309400415899969287917\ 699315057293618493610635645322004748985839410808932598710502679488950141500588567595930837\ 067627463671311138232106276609305755914362619581154343804670860157418927634851367271285452\ 332059883035085234113990284289977320374509387398529166011565661528512618809959116133589911\ 008787651273929010232832551098431815277251072309996913070129799280795648052515809128005020\ 506660399820171851864330713758948083591462450594712062782554009609058283935213237065762608\ 576603040379875639365401072590284082968566162870106421447994717160512906865811939899977222\ 119536548935876525579314337006287749603013626895430185480330639859523163535156815489300389\ 765698836747305564938480136702328819302786610867185609574313002417437979283293973440961764\ 094141848932553521555596697217385977576930593047223955514190442894515916394524836086697659\ 430293033464306182860226463367204504874989100078204750660268370680927627521777254571622844\ 712889313775048688631472515715116476258568672349547167304780610782126363603561627459445022\ 560312857460284691863974802744205736318336370445795184429791187987216621694030412426213274\ 936201982689696705966365302306301775082250323250479994061268042190917553458386792451738387\ 433902510009183663943408447736996975945974878456606908656176397089978969778337916404129604\ 889092027235586136944876773802791883662401459105907721567940976924386234898693889489426227\ 934299234594979750007899146792174232737642526337132808595983167689863202809921497552579775\ 152730986090750426326199733681498910127587086183709257767832912354359609309958367117277455\ 727626452984091272545431859566855572622921043160901560811015356095111091648046504583697210\ 753803098389601186763079256854050900376407952995757866199573224249557489195180190104801811\ 722285328366843279223892671409420503840109169153994025605883234564740211858958956996891847\ 869298563653047850577899228396309583463327768832678069788481326160755144167976731907650752\ 180794562970382621314611284740041338799277942560752801823205918555864926271600808517046740\ 150391568420379982890663541842723839065453884739618322060616180338487816438826668798524035\ 352720048057069417796868308091287322336025317924562202954093865056407231309740326585538117\ 590546874367342264783089665318824227208552535330671389155348645745117815063283442264138948\ 952863424881004349229375447462677482427298382700091195887346567899225451008307329578211218\ 494164987845852734199966543947799461083400531473863834659027123319469911494842740200758648\ 692741711354722177468765157470966302093677777731555752192891365992044849435581210315262353\ 476536633517136687072881433785091752350407696750734163560780993683196654684075894097188635\ 337495089434274737968182011586884477054608614011908969775828000062409248887489146852275585\ 871826138307050142074209656989838599528974631257579539992829028502798839657800633339563672\ 111731693014523214662992984259025178829044519782053972699787510946453908318005401639609124\ 057307632540007790044241587691655857532644821181506088188666410443256937227532592273094158\ 788687521785579003768798212750805010725185377752575033260725288311602831217360565192226629\ 085908606605944320301027378370637242356624425885798497172462089377201790118387859733419400\ 470221941023040204645496810559847854946692973781289921551104685950217982880548417556681015\ 445702668838714994987010164642267114652782039292649741143205681604160756447223587780077456\ 305888708412515609125902137794056817289516048950918755459717095912075582062409512571408407\ 842525407884415987162334441088187883149916854334935508874378290007653788433593579185140427\ 326614287994536581955052087268601781428725065667132112100533957538728884683144846071141377\ 605915558524464900792906139219369202106444105457825245581518145643063400167908227089997880\ 764579410546744196734457670041176753196728678797927019349503785889382720239313272575726848\ 020449980451802540282651400894051856357239453978339814523272753878753470679900290038598697\ 346180360277318789379993245552467159018565321744550816971650123351650262808361280162583405\ 892947035320658980513354612372113009504844327220377635473138245956977687580972271355056714\ 474833352591582220317255775140558150665349501231695473779784672480698290150550245148263667\ 610178795512319215619494655809404326049033556828205960779780571799217196591053227582275732\ 016505473460905931288517838977169234443635386290665179792920497442850390650604336184541919\ 983081927210479563606124173396033347258382275981301309455193743479935603276665895899382497\ 888220343241862582533567611656777638331573470578420880097928528023744505919053502324205218\ 528184977869517591554886937285099720642128357783996441509810559802289367023337699532122592\ 934832939093439893042567562500174527724324962181821628829530193876616979432371936448977416\ 698493572835040020424505394770950247412656244231530232599786059314693899267682684556620912\ 788550070092238513517116173295232445924369260395303869878166487410844256456161835217607723\ 338868431238234631545039931830111555045499315792477495489359307100035027773825106369389762\ 395641528416413226769003879512982215289296190362709393094857396480364558962826074785328608\ 153341394346265149499439216980447807526169787079022938756630430265769209162924379814986509\ 369976820790628233298996602606118845016959642101602782580296095139759725601646666340334886\ 248112042308481921331196377110074445428096091390616144858331576170239237943302516653539461\ 385081994567695236140683313533516012649893851571173938200774775158047812840363023573247176\ 701509815231135667794386234070439335252118574309198115331339389907674570375088937573694772\ 931496474717490052352139070177886174238745497270726062583736263833577567820881515652007585\ 649746917560797504027604860145414005966434182128141755606141195404578563850392558340191310\ 791798373360041841605270639087926117538503938253131600842868349528155592080408542118977424\ 687620985237771303779118739640102916726070136702760448931473825094046794219501439465349621\ 236368675904205131710455509715936512449513468090284826215983350671926333606862462802848340\ 980557260940008064387177758359569588682106673842478703239432359624641413837671298092279245\ 991094479604890936783548162263448665550698242326744740484761332762084928700600890379842281\ 983101197599977103116887905597233538604541388720360765510805183368669201338499298744456830\ 606335035205850147391459989008977587994807984962676501277796159152934501102587866906515740\ 192794181184433591900356044446130251275609883149633016104371833002034678904776216115988005\ 186238938477143820443533370911683968020739568578357796457680211552691054986648254464288361\ 484950700169920838640652540317603835673701817615064521745975331871447346804174274856153605\ 601766372694474179649548278109254734621699981812599093457021010349719747799104423047701019\ 230970140004705732474287013956337177840109395896901518324482666103388837563694876307113875\ 911164282286480991761426078675532009560065186177168990526705559896118391467868177371774686\ 585699599116102026653262875887180814608209892942049893327077807055645101091212570986903662\ 644192382241884787771384718780091163839002154843097414377746584447646671104512224830763683\ 484032281026174852092423747146373001751725793955708924337577776734543329727595007417900682\ 826377921002892679190396378283673332762550337441697536580963323099005745505842518197138816\ 512868451964589177543379337810159824428924085644434512388836438175928036280648421674279253\ 686486680368609963051196713660674415729221764786051794755831214879515200295844477975993300\ 693868893584821737750815855622311825710636936864346796401513342299403196395036536984733764\ 782721813103268670623375558950108024382692150946450686870435857791085010055599526359873423\ 569212629042132850820500109224629530274796682518655597490242090403452297494595791693974113\ 379348197854019911256205643152606344239633239099744866996626604843987602576159228363929733\ 362397102657798463663781665183976723226773288951496528761072778901915022876846405672919340\ 247620887930253788171102063291705679081199203305809010430688174873745182618705183532562367\ 032976616839039529680325872272007946606687093897948360814636773581520039494228217720710281\ 102464203692667747088279863151100088924419925307763930519347796305406973289565566185428166\ 307813891828546746558257993303210277436461042301091534234347845580270062859554804362992900\ 730467134883542972837979683969699520077211755023125679756092164443443471932566164976641876\ 717614541569666937552772637154519096652647597977716681293415794504997600507677243463042187\ 960293929949649992417643791605352102931998909248565791448314301048482774913734268895977015\ 162540710233604895787698371050517560598342151869264264205911166450912386048156991306238275\ 918867766559410065691471606138495805569745809950126488384851114367108203056713025386481857\ 162345716605532117330689615144211182560946883159251204262970054727177431691186876012428740\ 551902718584297808365847286186926870643273302955283044088845752649406197070336790598880793\ 513091779217993078347164762359935076148598538140504388209120736112925975058409206962456558\ 460705868012827871569483698462643323145552758906632518343021499630398774979696718522496868\ 913538333334834922789716828143928773171008634765834120593914685453446439165845794329914363\ 231075292318230729845913956177350763031071212664808708939557902954273654854520255804805446\ 145826289583153766205699394128720751644590222457851624910825071750782647531322714808490345\ 324634028062193793688705695184284874460297095281030772986248035642302857156713512939731234\ 165770030888439043852059656839038409614947187026562983371653976936192718745607466152745963\ 486330238109649627204662959772890411611977954337865055752413257992966165743743856365740809\ 450683490547798575525191432401752009317661559977862484321456338585737477634695872655378109\ 308174878655559288308831076960574737426923595968969875170329712215459850137817436810740126\ 097733416347453672631442260324520176170008805386709598705478888485547706827024051665672268\ 606836531782317320993428745449646930303988263027237227685809853101507060475065900625423552\ 851314099181982298698752523919104451233517610932062329761639009446353024162627242656832122\ 452997275238022594828760780711104750478137379257135912926608502873702987211665942279731879\ 300624173509613662971732264338704392679915273181066461559011968792793606804354973859884321\ 718830885502151877151235689230643304103559784082888772420886423411974160282439140639905075\ 028265850252264316906899951059958763102299062684811606847665718710584954869261684654888067\ 290118904250942332549654620706896517278005099850348426287069573719231651085778808993150712\ 838639738810256291633432879274399622830837522084165453212284689484590348754695891155237801\ 431581227907572335091525448109561734988008805835136165902772205957516830251343949601461356\ 879012784151319641402234809051977711760993156412508329317471749629729978660152159586918665\ 249632993457467782222373555215436991275435289204522563623333681552999554914484179957879224\ 193570002165996051280426808665161429854554056673729580724672577948541155662250725502715137\ 092141107785980968150174517862693370038972602891836063328482549070558098937412688447860298\ 882094376933157413064008393819038391402958569559934579551069803795298483546622283833310595\ 074523185895328334537788396181946262106917573910453713961258512966067196620386982098907311\ 683406649454388665497734154880171228905516230186465345424620536511202068603412298787935360\ 481312154430536746054023041759258311975821898625075366595358388652689488853225190389588150\ 172260857040013875900108620209600612644035536201021649311962270404475461263764567763822060\ 761617732699889556224722138294839130885378844903269869167190958384130030288786428514390921\ 857806026888303114899215963277069696584798918451448198542291880209045565274556866960421575\ 420959533534863362881206349005135126182109194805724736862327058182939734054136045166717802\ 482683307488856191342807542756560816880508547792478484944883170356265712660011736972783771\ 027381558272148659664080671596113709958307581604728701727108452053335183122892757450734579\ 849274465369349599805704910234656178252474834158530611026683851691516425967429503947888962\ 690317119305570709054504036647670676578858833295390594704882885499482205011080063150543075\ 627492400186619039324456703630740112441697494180592823313185522127104236785182794511674444\ 245558506587269815343875440170309038983313293999158936471103529842170860408396219529578208\ 148628503336915069476444936196011612196180547661827092249195039058791665845960519114127391\ 780626023598032514393531019051710964589054855005525009483643494835224185799069643568927006\ 630410422987197967789682129614025095540684486672692863049874938380065114074834837496869148\ 635205166027348360129334001566112355912395835023001854179690508866516296480869824328303263\ 430526071642221209026129740473602380609149360580633248191723260151090556048249333056490127\ 085992238193826070413557946631651081198370479607945838534640832995584909219269405704129872\ 407470944542125145446255376179284682448861747126108200719719250079882150391423191586095544\ 825155756179207828386871060405223093962993793113002088739524824192007967782509213367608924\ 576810074723920509908730977307829694888627889628964207834979132780438926251247999106007617\ 023000544096289620749113399844274540425019240605666218584400150992274157591002065998652891\ 022149024855020895040464997791739306714394459461585402754053583338142772467378310848667176\ 303475893285343245283852333781707843500218559341348171775098740171714530748924859931460466\ 082506134638696962988473514721989551146001678237378729472499995342497706086975585960106070\ 117871268594996686959072727620193586315844585293466196350954780823434367832245212619315171\ 587215963561782615633763190779867568879440267138541653821336191348938612724418148045239660\ 975581410186826880178327509320171068879698434661001270282050613422119873796085786786403688\ 844152717542309289267375873539700749937918968564932832108955660912779115510762448433027441\ 062874905442552469363705406303025789454934830864654813203119408537101874382353213570139115\ 868453707933384290454985147598505795844646669481521890055050891359479504364284585346178395\ 971868455538460423455093563968428869276315733108184545177912090717917235385949807479854486\ 328386512127662217975362304105199974019471390340626647481243770355604620414107220793123307\ 514058504337090262469078031223794765607491772491482996578497418415188840001509057313814740\ 052310046759520993412760037938873009538374969672314637701021205585859630052554935790035237\ 831739355596689695727659887206190881772302907889692660032904787501324843549763599575918989\ 281682876379759290887090212571553314552732643759004935581060225405765456129543341672771690\ 929025167365530624852774400554961656682164100246290130575074796581943463455720801817814579\ 076067542793324095060466005021766594770302847395815926460394928059269137644952298441829427\ 599309123814540071935155907836201452666726301436039279323486811400401146513980163665919798\ 759947456702418038108151266877657636257879439016182952744519188891438270707276801528437007\ 863022825319600160617855624611011904352555616654053911482531219538889233960572157418634939\ 316531937921899566654002568591565637727902306988301614579187008312750368130338978562829926\ 435072758551479071304664692898382139544419789786215456946841771883518832360525068968211047\ 008469781850628793085478344567942163190855768743369282131088089178692923369954141221536431\ 873950379525593486276493067911381602061014819030336301361902055033788012781442594020494547\ 716546699730482585617167998867029521471133210446775106737377691239966347587214957492812254\ 720191664525002383073723669041224611163045569434788589832281407349982456229749968621508009\ 842893929472631562485203683418817728060454979631655294326926863205147176311446141862163653\ 921604881934470022371687060600860202488467633651046555060988942396251829481468700848849731\ 252127938056123721889746059755918250037593717201302964589533704929263264202302086633819848\ 033139658088261114579590195049007340970766116080338013449422621561450806024191504522724173\ 563174679770717062466205705769305302157901595416749090693422769001468224698946594006653981\ 188938743723751274677028793274329953593894413439390544933116631315117119299278492171884298\ 458567677340032008113886409848791347018597687550979758296121038270767356293675504635134271\ 922487732023154321266704055924317174195181017043609745619057001709591082824338989268115925\ 077950231219824603493786160675546280948546755381848008550988710119781518871248479967010975\ 268731646138428154066846318680101716035450649576417892196110358598683497366017894279659635\ 452399924697891207895292481816148047882537626893363192290655082005435214690943521103098574\ 076110364161126010469863904772696652403594612726107178382938380948069888730560156199704883\ 029269607832423061226913612128298923719076535716456242587568418064276122348411910051243247\ 420167085819458743016088250440157302364293875455661092628699583810036973758695825066867577\ 966014531223781048502189859959483390861432076717703126781750469184346765844695616576124315\ 812826857625214022239362146747519339149362275017419471632498620282114711668222910069437271\ 204576381919156995504491738817651344661406544050266494269944197888677890479767864008356955\ 154394853022168122400100149669252143847338226364386927633503063926119042854724209873156127\ 870225916521693672291991337207056041332802137352643062942093239532971316019912693352790514\ 425176800198683550231761596897005173644574495482723909146518026595516052924845374862414388\ 485950661635448516552004632212751096168862562667173083517589720808538959495736728372102926\ 362041965867418195366870489159254230320416767872117439770571533738518873830296159918627098\ 908015179450681200490105788048553215453986507703635234905787586953412871964903488137627534\ 425516776913284017747496806498224263915846561298042490768275958852007702647892167153701993\ 693785396548163681147515567090821669359842498549209314183501416261446689874787938645967867\ 992141172375826397097703859053397778449720944424390862490871823881247594242551919872587439\ 479097558081533416045655891626093994452564898698376851763931367742252259259534527613093129\ 774449791015294571462959816821523662497500700025830458617409593547393240934761030051738332\ 575379102134508425576739655442774096118013056562004104177221155181462495045422344245464452\ 976318611043204664463765288716221014459974539882011563564956851909170309320675351964852847\ 695446326411299298660891453950549528229545038936336852892858700337507878061949391321580651\ 859040613605243040100014667182669049147569541460834475799352725047243844582859676781689838\ 594527803257326593097127739703345432460492479172823308183140814632581110537693044312663826\ 173732959777287880373781460755229479412656933226930666373207438091771952430407786209933424\ 417786862665064302901050906305875356445533452186001823355784923062261111774833686903641177\ 683407282489308281604159740064057224540919099599681721699475177004971117992864883354720354\ 214781205077558801041344739998570229624914116588220115062894161459706595727451085896528631\ 735790859973333244943816194907757022908602907755845920315340273244601286770758024645759555\ 345568997495378437192132259351672578844858221431084219802397517462610841126027538467720244\ 507927953068396522131413774152049242470402744267914348837752077369738537608634309660209488\ 328121007418395529017750358170373261154035307701397425423473820867591499984714827283760600\ 666495087746445902089517781864562717109933183412223033314061996144585084061361358371016892\ 028799151575353743224552208836962379568330167476302517162918084931888966027129145276996851\ 475176890263397384270906504398297198225297843858802218245533513787386064994499434104543146\ 316101587133963070492102298429897156151923992592146728334129149532223302206185120718534125\ 929182570032147203806634112864861502104823508044634198576110371455671414571818742918694743\ 658669175091653061739503805717024450039626387496184401725541610858371822080472358145749945\ 485413405885720530335185323796842003818041459058560414512854327543650996382103926766995074\ 192126090239611389838900043187277403263788688716205198782180904492184580938177392665698415\ 541349832219381600213912833007396403549284696893304672408568245063898675692581126120695425\ 553090524095616555500448989388230340693194368206176558793796414488788370114186923056838681\ 237697802215961853216288520542778112205390855829478063609048393754146736251113813040905583\ 231919164748789628532967746699549604133129993446583180704997946075573481560592670574223556\ 416497774715819577458074177819193699597245457100158288245256029659702833062181140991825751\ 750688905323733018424448789668225305374035911176157497060829544743566680219671037570243489\ 335023685973584058996670590149052943224489224388627006085948811019993558103403499743971295\ 973371184847956332499348933995761469708669204770577357858297275034462725883460084931238210\ 073957312295348377814407735944498933247996601395883608409801225945175432162457503545046013\ 737701497174451652245395343592146259625178011731023736862162192744097403055564095394474165\ 695643208785988103171941367526283545068168722749567165191567485252222886427266207126421258\ 295459242227682848114482209358176580089968010135656720868279250888695257128906696807636525\ 356344823348611549711432116332033805430821232530143179688130640376479620530610890524237904\ 470860345176145754398249366352404672164235863667821353370435739949100401924110749989482218\ 077814129173977710096953855015229106993826632448245147255021836110130706862931227650535627\ 669303186750078291579007340330843483812559386616626036769020840836681328594160768566234415\ 979511172891435002551075017374602029527218132441725153964135752767159951368651001219445624\ 885541006684838861457060967898151752614094517189601457525714937474336712652716556722018850\ 799494575952134166495271322253096986998039053569203038000302285844776434726795295755884592\ 175795181725481588974475165201681881886449017660343687002183825067910119207259453250121338\ 788485162855673425569963589107464639146610411839037064436739895418333832602509403881353676\ 543966482257449010761408860999461395181565054512024420198142005766197578034415984838227426\ 272191603185482990859551012479152161147475534376584467792961231489531270970619696292609415\ 279646345111640998487249405751630892834046429783426035811935209882036044470498553313347095\ 452835527267344405520013109116290289305435006561641999876269918976079070599817632243354413\ 304735133406414643639112327483197682589207255396859949826721084297805410815400980452954514\ 004182808062352138860491938258922035280453872374938488045014783630587770473141428222052524\ 683839000795336468214681516406643938642203696353778799532131380855190321259055402501886845\ 626537170979942159794436137924510377651326191626736962235872296378219677534217455828444328\ 996443207185031807339787734697747429630566903559719525837267261199430303382581638639453771\ 148614344350777850198750599082903748501978340037445919638170977030428464970584132555141844\ 009960816651929630402188101601030351001979263183836943746039205146079168076692960348968716\ 556910020536223036369529705253354044310367875905386643962491988007422206753402978846435173\ 305284033539641865046557206325474545051371259295032929933671010765158681058172410721673090\ 672433857794893381330721655274255295286908979681945412864056019721478152758816457592925622\ 412748428692251091144119826417569787967930044850922110060998496038000923193006259791052747\ 483526622636681831012497423010784265629720314837094391287737752916531071612655628170565744\ 007667369318062038387634654609245819819758791214758610103901831186539819131566583511300093\ 365322777794535743672706471695270781807582122790704237992673589907870794469881066289431513\ 282419589926868237376360818623973230684166114695122209599935258903021811299579870833173524\ 766051310531746984300676972053719285706969151205310332602041988415698883122614071596981827\ 641059855904683605800615396148229310614003295274169893025413008072901434048390000751610485\ 347031683615631478275958132578379273356360065562146438006674408391234930805096831841270118\ 922123582949859730380867862507518758502541859958584625864577909354902622742823701103331389\ 901935568326710895937825453156529656084337279961566843195119157480511275063573241397960328\ 037685481245690392805498781161263288670954746174222583991459063586043624125346014731193125\ 071477656793789643820169080743766892533538085121685024189030596055277630263879498426530766\ 078117599008019244311388594634655347023686938223660032858717458170340764184958839308401069\ 864879577404532972752947557266972577339598261573405921789496413906452534922293247500094530\ 171013323308787444597522738192272790383196195613722550718117493824383458124953066947751422\ 307718299777577392602432553464311254460258141016122492820970147940096208468139440066516920\ 913798551523986120275039236377217952331582577421276165153656436655938106428557602680976119\ 777951587770746207717020663003247538097102469822656852884936065848402095280932750505184867\ 534330644716450089437642657506893909349238722574358190808502635784787668880429083542389040\ 279077476227644544279006695927342980532797489309672846051760305515108552353684714416947295\ 163222397965046671664525202917101152901910499426312782096079799561319434987230655024932523\ 135811891376119312579081790376866878248928718792766946336533403557012605238546406497266158\ 046243949658093522888704855386863058098770006319015389051104743462332823686713869390596621\ 199381115995186646881505385508065894036267930781148173218385597430428822713367268162788244\ 858427706912137569308569869364680755661378950250870802044574375165895112215876276153250142\ 166013115451800474541463345271647185551602913132642317520173460819175741335135519578205615\ 460075858497568539969179814040109931038887152787872142494556565152835199911264175940892243\ 220390078109614126867108015827837616282417380612954423209413599822768974758705885981458683\ 826589735031189343813380730115576806486116101776751834664856479657300084965613961331248603\ 147178954287858132330463190384285745342038461762991600960624349587714104861534129568597706\ 360120093557093063799939985779440693859493263629611383132312039496850428064618987711633447\ 720468985923062841399667899898998150721978033854517642288655309351549277662323687682584355\ 692664926849560867290953833315833043164559025141184816628333024740003221491050790695398568\ 910374332151592420856373609083102345712186678093537086967168765409413934488876243711896849\ 726163792812806548391318035593769002895535087400465875441645137360915059009456475754660563\ 520943202244500881036158025313014932450477614930380619549500825953293908440041325880363330\ 899340355751093765416869130206901644637425742621045956915425430388598869494290463604129897\ 891993055304458371203367430058686384071373688201625671562360808950375490340469279513387469\ 527106842170559290957090572898876150897330303580228443108713143241357528325916533849863552\ 638456814950487771555103781460558368594336447265887655251654050375650715515903059142570842\ 234191181337325319630868136301013686994332170281891156875329912149449815678541192993424847\ 577094528976486348360107169509149654587950683733175831681704326453529775390777219018423343\ 831168630589760167008500049298872422246792000407420715722010445802199023352131285736367708\ 552124636460784653497845190446634294598710251343307402925371519647031805101107785299914324\ 590085984791679938267171205183616034951758243628755885347484751421922490477593231820046695\ 519321820245775482284288209463863827037654385454073338061700618308269613984189706720072207\ 325104920720460601129862576850766088736856596564215961241445366571126964805792116067341113\ 064325293483777421550180569017315139616521469964589097898086073939216301053696805723115881\ 648755536675670997645432290626585084866025999347609040019764696666174052931284747909883647\ 321120651824862606541346384892132388262632770606323287829308709496712345760007124724739430\ 580227486064095867771913147147937939915209094286450521256728962813211223882173427608261122\ 157362019699531753034638712596286657058348328674019692853676593119547279269108142774585239\ 547155186127169724247289015487017541726484110595007681206014549698790854745986069910513815\ 961061682288767545842856522772431274274498947591581579305977207701253637679663721178075327\ 963034844049391995404024846030857969665458004548614290255919057709967279435588130978222994\ 086050462683601595605854027747751769354538119442079009093969153160525252744136363075002826\ 031500647797330965683998886464739705057783080643697229304920334674739403896818798306397961\ 657125138280115463000539828734113200127084541554482133130148478193143261531216516036641857\ 421698043534354845020742311506936266178474318235849254439675980347573176547054549456384310\ 089711903680888610260484825541360252456272638975163357757814888151479743991288430952897681\ 561610508940614979589853304896732493225375665055990810322225924587448644295732561935411625\ 017153855718270968724375219067036610213034361239093643092873346185274407193098289872647572\ 436494654242270989347272157977573655991818146587536699662762912502103010236494399231545699\ 280725783279384517246168433254231485589722111886507644207977294316996512285619624917341176\ 917688455959073995346759241499441844177955629188461392672839987987638929685737985302555016\ 121587668136307253542909158794763581262163628564489656699113107400185004523338882232406330\ 419261847122328670257695521440098489877269941055951927880233259834769589162196150977525049\ 531323881289990979504779934936809956723051121125765761028496301124902020050478252875786674\ 819711641027879975627271115867313649552246953264975466477108635588673900481465929912450850\ 733175003227830557194691910181483433314340157917429404624395749207721659474220782762265794\ 262695392731012332334508297176613634975425188780038956845083278814415945243097738513427704\ 376725169876323368190729649994219495720917864531816829814055507529067625370695552708452431\ 196900060689272272343455833975210925441632590990968732381473624082861780225322388366997391\ 937131821972265520129432080300614758690426191043744282117461526507912953171169584934549527\ 416378354883720098146891262416424018970021323534785480612648528925075678916705764381465285\ 034080358781387961631433874758771234420709353505222839363871284015129117772235986286241265\ 190593844986101875260945212434971501605159212450523299590521548623890060441536446887105676\ 350090884857094296523870564291882002490580617355565941788539332408961735987145703505003829\ 160268208327935476338293000243735595128712266322904342161105693447728476524456342256880077\ 233272407199754845090499689492438713080737386639440538189336763961914618326757158314264504\ 015575608037761440993316469419708224237773803467806790313582799242213257729257011910619624\ 466358633225583017841045772135266446836699906618851403351798132426384443746514409023807876\ 319007188814972532056877928304367133337095755010713715095580773050539234388823651595429367\ 787241236643132798468644556935655249861487988987791661406607998137716153021333084641324771\ 075755195629795702877191290303689723550431973504384454659354913631429654341018765667201759\ 319511095750882463855132890493096596076427922547499630226868078393056414466967450077052245\ 480496350912093525997007110010124739417653507375194997671425343762233513927618902872556000\ 502795073561532567817707118179806220616798170476830058795594114246752667737465276823651255\ 673106463868517277858117558800926684006089892777552790975508871058627703082041869082090197\ 043470623116425975325475968976648706686888571777551764845088630114986028864500650697450588\ 112303426383367022491269218554081991330762868400350331712811358972087710671685372411920481\ 087601935801299718870100291113277060469458594720307237373847202760298266658154800147449343\ 089227829623947652987721507825481424100168282517489166123187007283229950763867796006046584\ 138563335530846649105057292986501407253731234466401597737397644218641646559972639855512867\ 738408212827607885762384856025080905633403570317297078155197387091950956827401723433765414\ 673390477118506265749544366214261170963005210598733196493884102447440440972680344908385338\ 048938667256415905708687898934906718636461458976383047087228921594389647606590566056590840\ 213951883463853124507792962443257447240270686175761151147139717909108559009255902464661894\ 546721764710459762092471629777391539773328534285075523690831146363658306589953336463502991\ 052267127395336149634149287984090218623314691197882348150953548117003299264370874968068300\ 189380540091998015422994912991534331262660053264597544675742386498900098511639578942584849\ 830354923956201947240611024504061612125451071553866723517518932179466904639689541003705073\ 483113421196547991946831692948192878978619333304504879711534498072439368999088798651847739\ 956819857778671614290588093999766936039840059931931777889618943316962530843437111703024808\ 485087038147104103073955423374621371974767861779635290330404107109664859511430175497632936\ 085704199635887562879516603579503699630085090952398715139197494307685895400215798576596735\ 879710047022218027882263173014062145680436349948433124438256086535174971802771529557225199\ 390735644899274265286739747554947400084393137091162007156885508157507221432047909114371384\ 167383888844913670052944634224355600344015283552675216595393930535669076621409163144223422\ 905985276553580823095479630779900166260940267372313457134300670116936500145335122600102019\ 951940334389856308938260578444697798521323175119690869533540886504343902796924041398246993\ 993911573651108488589990499630101912512836748950577961438556407982974653427018012251300936\ 034021007148218161405528886776098548803171786435773304640051732246363998099545537098445290\ 176149252405892226082982930761265353276521106872394295299022442688984513421155365962474378\ 189742478476756175383649979558994759435061359758989557847853148352359597721419966447172137\ 734186057635329997633264014357471639672241188235204546902923516450555257855727259189367337\ 251988546755828846255599969145167383507644174763694038943689203054871921659307637015356321\ 638866838815103804626040588224355348774952861541030586209462804841259483874550588312919455\ 019944264840236027770154061248819549191262540898461854909964761068151816129628500971303120\ 516410339802418073507689232036758314090432894440784416298162865884588948321231369875552823\ 592702905203372408215128197147676558818884968329984001279062978887506011686578436488497368\ 984323079193659754473851672022757467068122462280605064359953227379235873793267223656982934\ 812022002808568725987084797691533655959132894301873323519082426985609952116256670518574518\ 672143466007050144009661938429756469546236190883577365009748891306035138528631683002952615\ 378634964813460447123349581248378212911329091068863109661726482569910163950901424134428871\ 358609759870117973525860392106481135736725190422944270352902244822902524986465442286976067\ 089247669112212745069255440145980445971627097976959859532203571609816634759925150660144530\ 095650413580155229511229547955308148984689930376967858395338509623791805871524221553105354\ 282094310187164650809505271550042661197428042936823381598523850772479684341262401623317874\ 823886813664314264815142119492767593588998600027792159430011104925533834328125543127086536\ 649017169225211849327094904032268654426756215223527903175635042693425091812955327101502655\ 844669764169670271733615532715112167389374167771242006904075286965185145282204504615556037\ 461950379484353238586031432716605488045652854541100767790766835825985561501178539619337787\ 540482523609795661084948320482198204803235096656995130047294523418658379311984119417024700\ 758081859594763755001017955572186722702885578654732141152456399612774985197438304112942642\ 969222944920198822115150455117330844618978279810642866837852153045219616747591204847089248\ 472219668634419101005715728310979620178265494909136823377019427382761449215407402832697047\ 577494416587552934944680455122672591431440485460806144469186911441001300430013781653272156\ 403336480692353029432596844093432003138148363394479542371337216510420778433713555616306554\ 615831678876861750988377643459622566149113754422794057391876195328426340026014691663552189\ 374045658676707639569847756485441627044722850950202574164091659040442501672628635893519935\ 139751535954484772610951127683871489137580421031350745300187151347020347211731578984411384\ 741152152326466671405099781251157602372100123878527064014889151055821318617336607548523641\ 474188524945681286985919789369913410906992811578265526641195063605341708929454742345884334\ 011471295016121012210097524442368090257425682611255159404758133278816998404466974862135631\ 014390622944536146483507703702385338337429240632925557378229401278233925167541191181601009\ 922688200651666491972850716160564416348308044472202429024684586884075884430252511912621853\ 386545062311838026323629437578614534322984329183868494179634294378550698068576735430539232\ 938681972108583318529404670804445627301275065194645216673780743921951378831072085781850247\ 304020541110736116181512315693034469313684433919767005193076541133238865975408962070671910\ 900453014496065053335074005707955496616470327043816211776380379438581221813928878373830617\ 791780586136341161876246630610588516734661454738789860246128131088588859762467453578033326\ 975853848615211532541322143267544205223875517227460454280701060997227736538950580289755301\ 437837497823640409566027106832142489435773927334221937062446992728011486159032729527074659\ 109872981093033500915806942421926967441275733465235159221086576777516519166362056392228701\ 088426081672823944005569226267096095238938925739420115228324203930445051829866594377730779\ 273204002804923562987643146553683579921297776788494644961346461656713144556150013870487251\ 043400758883010454756618012171703013307393162342056442116421111669179293699934294135797736\ 419459649542603297670602902369319023600007483682412873760689678959579762907951291256240792\ 342350295237594030242017669608167707650267510320221816711468178252369054422888338723298613\ 450309178189880396666586101835438578209507629723737131716554961199176857508703027566503278\ 632508740464011046190288428441969718960628616031277888170620180121327810413131966111718005\ 621919775027070709886695644087273023769634612634495310169111950549400281153819488786801552\ 630698768590227845493756360536166227980966532199913456013004095995584043957156420232928133\ 543608458900744187503683867742599036552871734427549936969172663680816043200373974249458602\ 616932373469190947419542222405546707073904041118054559147928399601322635801735290000776617\ 884435194130409460539399561226456723500638918753316654684017913603918936529834737049811609\ 798275285393537195319760473521523756472747322685903713666463496246358303844599745553160562\ 957161259905560115762013668262847358362230399411843389803387847467490190268626007193709779\ 947992528296031186454963899610609758596395324370400965724499008036449024369131585247156170\ 207282146831098888943689079672705970230519770239884907029315800965811911994903653087832605\ 561358772113102642697384297310514533752365354696613331923691612691074871047367695756268941\ 129609997289054049608534181347902726995238450254094858459698709706466811172601904823531593\ 426269925743859939475931826527897706432638178314962033746537817552211717804152495081634492\ 277822147186898339320367648912624268840449729059665059504371599896869824968790641701465972\ 971183733602518019579807544844630666044149510874748527889274901571319543698660738390158411\ 239959123260819911493405368576093265202694959767195528323044569231967470504928905889129731\ 735957224904000544254064001448549323571034176606834591177354417602919886055545625432291273\ 908581909505579451783115994193603417508956446073617415336674091881763757969421469165183250\ 563806240102374027688005150621536598723077190192524995743454421975969781921412000479604785\ 601189348878884860658971736998739432448428964338759312242184892632202524103381953976430586\ 066934044455229045280008116097846818721054317021562420986034176264834701703584769690393393\ 696772813648550930766774858497947662533789634911644361261251866768605430297230571360827644\ 751218358355602172010490419979379637685366976799534782071795713108206823429992068619854769\ 742119462469267793952008321309087133234683460919101676422711086803262843078005952247607853\ 945022459040212414390928199333185591463713863301435244089804550547191718363853540584613704\ 047407249775797606979551673065028723843153505471183571567158933007551803999445243174931017\ 763183250498735487057003363601411147996843858015793714220492514712853948719920234416124335\ 572261823748419550048830168163002623025040003490572879955413031925734938707353651020000368\ 493268676837679059214491272479048237833184189000670354879586428085166218823625624567198306\ 017266244977667514530773235399918986045730774411709312301129121324483681922939098009004783\ 742205002897648776655450372683157742768592913052135891612339973409109037317918777837401495\ 837085869288096912791886122546294978389932030348659322138528255377986199906814121428987786\ 902990599819938997663761623396578059424466941813209502962679791845212564370449414676683203\ 106591713289371920260573340713440198973377766384109219294664371558881783314339018206276372\ 593111958972038420057647551263693631523086376675847028242162650084035413797052773913724621\ 757658324438364381670407467382045257015560167962239365764392373400509854188344643904408885\ 252749686497022405462034010607540468081075985835439506930822867296691191905022006946351517\ 44", "34451483850411324823299430931169825968353107817116655268140899833040107629259951380223572\ 346805665993997204038599656222697979717564355544533826322128675652053912683465387966603458\ 994443053409694531635415580521538953353312746684823332351004817493272491521960166258913342\ 342373180252664024157667462375982539104108105341172864611410232496378513419115781507940808\ 170527468432318146868077087124120157902271264364223331896928777149891067633690191535656820\ 897091205178130592547090371963167767708229555068458979421107996836428058017460538748496908\ 111207323867182114805273143991970655106629214755843110375514587544809778703303551388210653\ 559676928255518022127417846024607354647675627462663009134103421330366897594118915183233338\ 405418371410818031976930549485087349287592927111057194910345861966773962551956076839916605\ 668667571737424974557464960284509988107381126905270493288482834765309133784184652590356401\ 885928053781807444837597092350928183031420516270577246632088535963759792739825290341892421\ 210314840661065352975092908709398180986384993273218950527276814604805629374478626627764772\ 485188935806396216976047862875216962448871415075782986955268499047042000101197676464074038\ 396567510184966877967849012312867671990240503189201884868007230804072275898505936078253927\ 805844759204707222468062168195989666730218055824398237481605959167838191560401865967701507\ 253000529407234815298651681997199461379447600411104701857261733466465597053062670063935164\ 093412070118156654329146112330052280589648492001225444013857258298334732616978281389777816\ 679308814556707411905732395516800190900777730393630710654041906698171400970508755242402075\ 804997159314250556333980779296545158052451707345400758844216022975179271910866773004064998\ 293889847099612403751532471065400844401150789218016789810982710701891467096769774096155973\ 076662058008263626743779258134662723923810447638738228784875330801369043111387004496370207\ 023023480567498948009769072811296577926772625470944016499846497851232989174805033735426704\ 401754345772361740710305398981602432839858392281907893784987773958395305162061012125108677\ 358918304359515045782440344223451256206024933058418071421147095085925385566511010708875505\ 143391759359699712902902855649125046462521053067527088443130985913095674557998886417190194\ 091817087543204610477089421791735191155711725548961031690984947623500779592937068388046836\ 952927657338820645541082391241962186370260674181129073198386769387757690220757812450255987\ 398830275102239759157863554446439131341258688347353596958641730487161625947948579244870323\ 305947308450417267095819036918796189679098400984195813313422316742491207583655787440490886\ 298007284424967175626090399957925093538355574872082555471440431008634050086848419623105050\ 979963883882227940850536301168002005227090933609287179859051338370266721367192856034841634\ 380462252724877875952791600209162014400851786947390095090491967032550467103457449770366623\ 241863189316478415536830923266592346544620722406161993792578283425696720645052311925488820\ 308429105619077508194898825046655662839767551839714996882367849263706159358845116298006618\ 727844680016449800282241995219720100761245745067038667709282664203811883409708225042838966\ 538631042260150150599168704362289450260729089999691982810242188027505136501099736647940033\ 593800478292421390974480603146375867165454961479693286995465035591674300623426586535107210\ 388932332372787026577938415078605090354422340032687824008099024604363938703357023027630364\ 292871249826808894293080856462209028659282624979331235546731980166352695144759454030963272\ 502296622756481170706560851592503832402105105757980845870985976783153388274593523749727972\ 040401793713966358887812939386130829019444456960795930555938402991444909456092984987149402\ 428151701692246846687416797688029689905513442522159190326687691608616299564915455628284680\ 372137358088442376873928349003460953941598581356975758600184767608702613380051642851909161\ 247987152945546841111522516319533862237514132116947991455401641234013363516847421112754934\ 607514877300805678805316851265294770508967422698728398461379538341592951145475544427551959\ 067400743840670142301150071428448155955776203674198795177237553657995978052331819456883381\ 455099723351421571878460264927415704629035394978820856756976591731972517186008947371452139\ 263263975551702018392139329446808455229621276307059552941976038257007442776765362811348650\ 905138766563753932841618854558825661762743714682756672518270320160690491558838693394720350\ 477976924420520989075125317438902645743454395195714434578544555102933670421949387729107784\ 974976458035272732960769462692182488657200658550153476719246974948210233007558345016660556\ 970253996117378131586858412420784199265977175643054911033536900475623633318240917416141041\ 831985077735136206314006717191879376511106165189409587036115718362166895102926680397638022\ 836128019813125575861160435615933076815239675366208264769162539926968207906570379303342082\ 515437980671128734042106497668997405571911078326235951448632699595787249260304334693702218\ 393996031745608620051381056325695234435904682147685177887327467336063031606977413652534055\ 510908715388100418636738012794529883204246462500184385289188912169632132527093061936361338\ 877189491156905025625124866895287629311249111665425093030466099439132552416376588785046575\ 445898699930562965024221336812658561937309400706959884257436526882650523519277349666681420\ 764376513513445413823157925840485389490735652994018619351676317811528866626459266101666810\ 506013220558580821283823790173513660077715569315869701364936771288242955486977190348614722\ 824297125308989188541801253123660164413441391712004725654381997332882966172251981286325611\ 680932850180864180098717997111976053193195357127883516969286725799790197027271714543878652\ 318089114605794377454173258755305035298054737378206371852048343277831454660474564902185611\ 954981569288359582857878546238631713015699017988928493761633725944495504282922834189025551\ 034955997321833565025656904567697385151170281369030889181778353434671719121313120861836167\ 032514757939985716206633267937585689173565456116628684124397824900658149487697028933163151\ 082834337439644982975293742010073151499748401890776648805747286521322191969279668583109977\ 330149180887721815953037618263467789121921382319318616715943628470572242406075525215876390\ 944724401125088513703872385280774081436888227227311507939933081235416303038341270511333961\ 766106984547059360159227414849198401911211904583688143280838121847294126079240040035107841\ 805309600923258724779173027052674703034034470269208516785532741160650241386303961348846951\ 365879365427942800814204063398292460722659830453474304804223976075949827423740530286328177\ 670507486558065242182725365612971888809269405964838116384178344273953464112978188065775230\ 792629764656838121320070871624087416826097620472272685701515925496522979080803302267074111\ 746683961832987997460419989024891610491846635134918995713766790979903252244530229633849800\ 683341658108193740193326716632763424481912119658049584880644421003095441414603535606649604\ 696387568768767301348220229501631790841280873686804110114325906797411252741668324616788629\ 283731066812844132164534492894033830843458710866657855090458158446987500946848952827358680\ 584153170305842323335682161886386022652936951100100386464722051921007918344169658219833758\ 866711170080835773305637188922909683201737950283313800071517502565669192369149942619515304\ 769957278223622971046624599539305022654711241271321881402950092379957879896686151739251847\ 060987478936338358531784405988998969527646767072480376710888176087254126071438298474102337\ 567400673041747571003432724244907605765074484537909942140483502276839139229078225025377003\ 227007772905351857640586480572724134859567518646054039961796009706647467440701741998427295\ 538381165976011731891484589068892690857689877489385375025363024730802266965427964311403153\ 059682976705254921992652455798080244209876120085617661914194719029606965969843749701911879\ 620875131786482613735039853788263889283715459233709619299066452010161530950372051663690890\ 012503149545894118667385574733010004109473563212015923697091310537379719232154136839312985\ 778906131287336059733466676561559359886927751424410723536501316433418057100068806703499543\ 496885626196075689054820073169178776289523993985365592344914723153628119748507494879337971\ 130051805952794234286439270309733638978017529772817125682688489133678491928232887434502649\ 217820808543462407258634360834775597062954208649631221664331992417591349195531072400077889\ 256007064407480132817035955085385648125242414021060199810904113403271894896763235781196288\ 652164924470761802380958547033200682030406961813276511011519116214486233594528827960837905\ 807323471783804076336564074463729044856517271487621282742548476710745239522100979080158548\ 498551987964273821478308964127644472844203237821055459140672365249055353827504950029178680\ 022821291496925950008448943451971366977558035566459900116917702164015349057452721935705158\ 404803531105054843062310400635678520336321624994336805114796258045554323628144728070260893\ 487850855368283835909559919698274340451526830285570667388105277835541894060352276582598328\ 751658326541242595506840544176543735901853974638162788744394423375373652048678205762612335\ 132065571118790389189129212782254051998064208245174984475181048639252449493529202070886583\ 466188181879421266041532473028768686787094284113910664982910327771617617263824202957067217\ 448895751570864273321125034029150136935975908450024790363652072622044223693697286659629670\ 929134433081144537426272951437325331049385865827278375868476890597558716459431879830301264\ 258862842682138305826848888799554344478258626975999511509850092517572472208039544493823245\ 536275868845077455899212905013893801757002974469933349422559171313073431995913254690505562\ 336725231802565296748198396917449406561966702728949138084482525014698608231685410973648702\ 984346969078312465217942951143590197487555620465399371812108558101929190195069753910407865\ 130870815296580504747257203705155232440961318572020390240444897304905143083001089086519515\ 566638569036402518528589786053757818672366434547895090769867052964475489523564212955323431\ 542561315932996753559434496840542802228206377995119681243972592202502741959858499197370487\ 707521880038293514700359795101107647234678429006379790261236163936038007792191656468677954\ 375167003907079597069319876759255243996608842627393215800118222477660974666312626019457998\ 374118857044030345588126393994626905426120385538259045507126522164900849343130472337478364\ 984228247298605979297932548920010028193766166491175054532638199786201751368198005607744338\ 428206011798707338401604719749912726435887596533474562745899702629169235117782879506038742\ 456103577573125900689404681235248661052449870801684559999433822338866270038741083766692124\ 168202419679858205205407765404224541747414070890200255245171249396361179208331586778747479\ 095703439032534090408608507763269348688106310040246781301987340152990266081084249603199014\ 068346368660867987650342431829970756681878106307037571550373988219147540507836585496820250\ 722370634407733349597588664354363193736205431729109301404939549416249259152109805332903996\ 427992136197349162655622319922410969602438078726108101098212105254845572682713707291830482\ 356972924251855135897621063703425123083777275585879387520777211096311536558149735272574784\ 537195136637654102593874695663513305990634365203629686264481322783377700662326639771034888\ 805514330085522172413872189636622959624310653455879586434815238981516347220832620296269964\ 360966544859727329415855095913815113663362856109926756052379778597171872085418750153434028\ 518557845551930703696466017362942862818852591131113033099295976824321827139568989626752423\ 690422856509892091285497670787672281252957979849838393652030906179060506628448891744306485\ 382100804697144115114633245200753460099682305487164867482792405008710139310592653334091585\ 840956008848091598133392219068226763885521429864277201471656942789040873655321439511108116\ 878835001147297590840466822725808875177288803992897626429359651791176802718789979753419264\ 397844295085682497515331173323188113801288315550516596592281085788386120506518355975606305\ 241866594647036248103295187982957766535773920891299217667202671698522715962229803815472723\ 149965998161752952422941449093329942557430866416232489916659527595433550762859703651942344\ 538572969239144268957392841245046831036948430945667763820531844228465553912212420018852225\ 225020577653926055111666069107385216670468525811777232240596132659812136140982794821935725\ 529530369197391808065501092722218521597443356394531691871252463773782885446805155905182271\ 570710844423620699214161278548574138113445531710254316161885602253948965721790116249310562\ 074176119353841784216686644363540302412520184749158399880038688611384071562145226236309412\ 025954003609096091196693549152375332728055303791557945182253393004979796043454313270109928\ 301308557461535674579408970352534560298364201202924459278577790189232690352003062147534120\ 577086795478900141660440549924925903651942464995456136682838704457563307836759049502789214\ 119291019249760227546213410815469122467603099122761528748528931097451997267191738686842221\ 227281579457907591596164599467844092814156240022623275966643581665147346072951550641745705\ 551696463152273555860727877607506463379231381145345847649250434860394207767765067388078010\ 623076389861491081441440888256588478514010046977281806287294954164246618512747972640953402\ 956046848252491238660191751595179797088902693712176647301516721042046822506434715329846153\ 778862985010999309749399997015174458288798506241421511745946381134698252816686599358395482\ 086399565381861876975629776451791114984782286798542735573451450332461913580462775341218877\ 734971942258586156428838769130181484595829472243553676600136111572612545815509866021037494\ 780382060627973713167222620516170844587075698048783685153882016440887999384559503243178120\ 868195078976756224285783465205863024253335647381962201541824132350409151595101524764886467\ 457505186496540101752847839483542754048844069208372465161854063150975313029103307321418818\ 119233704685893367710464938988334519818513177042477905036835052454672339088844918558317067\ 977892573729524598815397771787425048613549189809658805909956151064830252564697255207499671\ 574125935320453283742352712670519834578464722637921505788873086239707006367543138659438125\ 174502561594941187596347035957280538575047734501525127519893206532052968635865346356062493\ 718937198584720706002320112571635761998896216483884445354630730536227674466840227807153196\ 096198999572041851351140449067146152137339686115795507805042034469582023190358991329139663\ 974188039996546459499478074594715673706838977572838085267435026806537721184978234104459016\ 485409366911072651922167870282369368009663524362156019767595548424241982796418774826532354\ 375832241060902123458264559278055921102817108325181310110285123796324217668486211652918742\ 198559306475719045388751695440470017338765781879696159991789949478093762813230326543851336\ 696073852616561207960194541332201308828130119582823430313707585392248084260963823712293202\ 085275259774031889913444531570827408919192741750912150811915361495673668157918124360254685\ 519921027843518922603489715378521416713939288867509872379289953489426209520783880739378146\ 865504524488028306961189050487514264734140841554909181354475972182079211508784606146051762\ 339543756043573384573111247024991473539752538624994050631977741705804572697905637673185212\ 242800113399263090375970407125615860445869990344831212421900871406646684369187837788378818\ 877172924977009844835294488210238213866267630358185758660416082157058756169319362177979260\ 546616004837461973716388163312926926148946278758917964445296848116580309911031228869549259\ 412636870591769489882775092897700260126504352246043840151283399007680541346796501431674561\ 323059232837610317621936622461929837002216649914547363925415378909953967529937708790005766\ 040585957821098073563643305674256947116737562169406346876946239532769922299074253802930288\ 665609142808851364690519060719440761375449154896537075489000141803879935188576961796198591\ 544055570745648511288277715522161959520984178784871498839108487767222412949225479370984137\ 490189730674559921408156013122499729144279286850078756211110071212872081887531886347374079\ 112755288163494222573266001038127937782870297657603264285542023008835215760927833970067336\ 165010087826124444721616873931105411767241261650369406838904843197479962397073909232281996\ 522621828075720519714487331801331814757908355092931792571082350459307441844641714914787888\ 283478788809855265417988211347228973899855678075241312542522102686031939322547872792248286\ 675269482592990823733358293555904831160274011572931047298803815931915770329913822471084605\ 366006229894074162622783540167260720017736781550909901686155742257941113264992972394124090\ 318389391119821476465215392669406523445939847952021981806665770637456494614602859783573228\ 074648152918670903031884641321092045177929963199375433017123947771361485283163032912800592\ 438205927534131397682254230851877393397097594038768864513530404016857882458836166128228022\ 937256385917642841512639378706189731438119783502474072350646428490513156723541335416372212\ 315102527790678281276940631218997079244933931322012487645746736272016668362884292142516984\ 968647052061855624461046580440255363545371324916884033418260716924453600613330375766845701\ 993299116295092841218043061518544179212737948107674501099532569718048678756841420109841328\ 306706395299650345093904031225797433044265743360086408656736569363347839893920255251396607\ 060149499589042039197167351925551116394068851429343590800082136985760002214980684799613726\ 894042451574141464139761470212023058128902043943836512316385866499516340987717912975678628\ 686095823507610450222020051512914739180359490141352076687100343664130860083403877465966357\ 191289659877096887974699561997977502974442759413816787470524438108681942208514706111854701\ 337602590140798086494716622609315106637126044955399020227484105102898710878206318886827303\ 336980585182421525412238917679597014122287128668431294790415464220035785288478711836989723\ 850014333416924049314913268802753545785443107899954705507264322288241856118398617478345968\ 589391644436885339684899668223247138308708606315483962289563287882050591330224617709631177\ 778751759080806853227799125329083609323333379871196498969950663857222424722576085161805857\ 602406514300503128780585521703560571460445023350710010625059437079741949376053597914776021\ 397687516347542052760941986916258641774829458956600149609134709983917899967563474581814789\ 682292752808898549800077114365967054718367357591391132706725033249221512136426867955387920\ 209939183562027121241636937188813749462861954296280905501243789899766742681510462838980626\ 369345154995480729252917480001177527787563921059002955496531428565325587694485283546786813\ 990238769896530045090556480336854627192297026743157137155381468394890817960168407459485709\ 558211893080432265089498420152869751850655987848128027604126345302811863471993342719633010\ 849542601565548357590601849780837878651943509070868457117305020893499111449807008645059381\ 659688987043167284637475278626078111869161238673111728650645609422598625528070149103895199\ 562139436764844381663982786266277454537193593473332833368053024772648527253349723430366698\ 939132575256634891812740864145669564405558311563244950441299398709850593010119443943161602\ 701870710606864490460132357637819393370402092042542363193627687353863003930815081251670348\ 129851475251254448539523487878672582106125926727156094137042863702599896027704836247811910\ 258458823128358819786437607605329767760307036878034794828352958427659566334169204021874811\ 538965177344114937038003606503996998136318237834104259584037838308359927629593747063705126\ 858707695418211272424205782878502855402959897074192333985657556476331378586329090379651080\ 991695829880996555381360719265503498262297303266917376931048542613413371960609394260613606\ 430915059415556625702836694599441924277342202652222089075730931322328402397287022941242185\ 717021244517182027880690503057840929695237494069687031508226864841477140555511118153597826\ 471393767148572019592590589661962974943985260586380988632413850784297423932879063755049625\ 048655253583566188345101838156995011000227383700260295834215716843063615859489475908798620\ 631495640921850282304004536457125512346087009132591332433596132447398509370324102637772365\ 811654101441506371350657334595515686562677987371768834329412408846446903559106394935163002\ 416818729012823623014145824781067342062155047786652548734590317107342478714136016411854798\ 847252483002644558253730641528875696357855497168296844278003946177680698879853146317782513\ 767939821210899948098508015724218948662487451187163315005775969927502408812894359669379396\ 778012469048798651918759924766748415410663317531214582704284750051508043110722855105416281\ 210706946926765551063478977529497978013893883374638470109526084619875560401213475780155952\ 342662848246691086403726780314401603911220203700032090079416882756289067081542828355897856\ 525973039882396346771615496003050646138228908176923866644249740778854999559569737152335979\ 200531948958652730858881618097849371240347874788013696321236273274210419682908297421234457\ 707533376016861411884851348789525022955389374553761217211960759863365962152933251387475382\ 406161335298128894324501548832974719333105347026762496259029443264573625749862923217206166\ 416786688216365507514190347196140002317773154246754509004961757355489010275928109218897044\ 357830077490623588989978733429444763045878428091118371874961458115093452754639973682738658\ 211602083971189902789055679922827448563168701305366858815220103663327369941215693565045564\ 119750087904694379986898347043453546453790224591833549909502332445680809337608592412698084\ 896621254991403387388755239960047969770525760851324842289028311447423119062225953325228059\ 795655605211586306827387003501653747980935752229916643479126750540844943458753233064332837\ 075336670553429448250508389311617520142484759769417969980876847385703834060918267016830781\ 006847442790820080105541848405065544682795443014121075391446070781451379604288632734761458\ 398209716125775183920852005515849905618623946476336630304148133428587203955426476550652193\ 215658502873440479077368992358317958099028715294329172442220720349493411763068703812592425\ 333316185868216843027619361719337779771651225530835870756210526154291484781165167505782635\ 444123331379451028271140209035296154859933506708871027360990178168877787891249483294325573\ 867524211035534797729060145665525317364721194821457745282231305963349597707358191193795572\ 672731749476274161521333484526581239039300486068096577231143652723430953238605591909713924\ 422755040482530758644641884981057421222801517641771267703876053315204827718789648696638198\ 181274865524494168483335309659429253831067776833121621734813697751270823306528097742054744\ 500538566062959795081426562368532007715865253163750867900563873003740804109405242257332958\ 062462501274481436360441307061003750220432363619287444496745629439729354414581514488564316\ 451761614476489527702312389041491469638633417340497468593942917252872443087086489147800423\ 828505759793014622964328421955378955070559143893777032056280410308174479911956552126031240\ 402350063876088882229556265517435643170051733043010056341152354997614810295095046869877183\ 096139996607269014326945159567262567191293798305073260996562614425887425455374979891456095\ 229897470900312311925143464978677759466050983479154264080175638895902501142005569715374162\ 439745514651941602635913564127892278781517042368060683524858651633544294595464175919189546\ 287301249133953673786623889576437192336757501689457761778379664115967059899504468708338946\ 174268460667561088618903539860057689040441030537617026454305882440756890397902592175203302\ 078030001665121405262663941436022036973700125805489568090919709895612339333566671608023835\ 455527784847177527377893854967601198740733065785158136780263019698302275232365265252605174\ 452079901674705706649304530869662983124013928801299754345774817552409059640862390806201279\ 235420098307674709156399898966135683014437814014702747320523341553937700053047447504428149\ 533752004984630505423833214428321530005105946061401283205536997650521119081882939966879972\ 453962379650991352482222454387941643450551460540492064982003125742162046560577063924849530\ 142380194111272158866710715642719572256422950807595061247336947138123189823625116107087700\ 944533306182680619124575855919683931198756540598011776459628127590695397809494904846442718\ 649596407235655247734789877074031191565671474394025372900816948562928317555231363679733222\ 574164450899623296236609090004394822149153067940873278533793456899852439870940461822574747\ 759944501033353416935809413001556748775098231627899189501288666606594774684279654217831525\ 996095059859126912080006553043722923653710899543200681630411623378633967355274644192918115\ 805934751344808563981811237311909444235495445951998337209009241502553025904827070286436519\ 291473667058643593892946772761587047218204359175292481330973344149418956234492170217763374\ 978218153111603223037191855013912649889223800790586749220163854236535123669686039036773857\ 165661982687423202295031684701767176521589901360278577844739473092978236356178076026557980\ 589449969283369737486884564783851036005642429755824483970051138445624076916484961519911850\ 095046514841817169640401504443162380462164175526395522736778119522934020424664208798968129\ 606932122184887162402130347045879920983986850384174013865279066289421275327565875423189653\ 420658611274397431231290083905370234352653847832749847761436437340021911408149709215776160\ 175927160465115857324030880396317055770481374774873838009707428904349564300577319269124410\ 244607822617507177913809596171303542672151874659047848793648233858365244696291993519664437\ 788858700502428778828805324497844190474410993782500454236165150041212473801280741528960899\ 595030751921446734361874394080147764515048380576379308723419464387043768049849998069762495\ 150016231356941135656709085117365708148743917116796871067561841442191399511427991297345010\ 932591807729460899690651129003475842539915389762720417438121356836436409856958022133606908\ 970652554057855910264578550207999297611863734275947761521432690943272809551147773015613905\ 808255795195835607962107908719681116481962426756072504782197918031742843352273026853062292\ 769195332490957754903333458978602497326356231116792450891214770031983777371709908730398393\ 594852155167080960791569781719471339023312673628161200379354870963252721724368977647217077\ 776610786408810822693979422452771653463856549241460386637725661145982750591221008011655216\ 190348930397562847395964415571163054486712242584126234236145004396866479558310568286401273\ 073708489652058298850754674398883237113826629279392087718936426293886133450732131209301864\ 111969695699673733548221977940978290943582134393284191699640462089302016872356901120861524\ 019731328220985689194882248781905372537531668233962185171649135663432501482846700499831859\ 135443165051953331965258053149593064919421055652719849993993640775656891725011231094173950\ 644085750532115414792533549406282032875625927929798875490220593443844147447408791968149656\ 327634338602524377087853590689960973148210869297419504799946169666867138213005868201726199\ 542602384453654874562343971206403481539913243804958463318175829091190320780024349037328957\ 160945994880266286323667631884127967896682067485478912931937226009776156413982500702833559\ 292555992422947474719476915970151605776686254842564354302150687592189321529564140718070632\ 406189726637774206342576602034324464032191126504709982463870674362772324950651327113206132\ 831238431350375929785369057776628832494982803637931463012324477796295544372666057388420669\ 247182907265861079707381405946063671040423286221097815774358225748444109952648751545732247\ 988809852771731502082459590106530705261531187388707380253428887617766558383411645389547860\ 009298338843675500510962254607537545229412532540774514539970800946639864752768572312592670\ 457246516476757543442944269473723206705345328209648336274977629413931982098492458397405626\ 601219141551447835466625371840816297855088210473108204312520465263598822973457046492371397\ 049963858766696605009831137568492189015283876528769518313336876860431375874924277724849777\ 945537722607967758495993564510887376708682066093750155078680659932239062086066268560156015\ 660109487451108369978701478788100676754812169949792523375318164560064832262655572938047984\ 078536028158400467090801630422094438966222058959037151399115830403569725870876250495126476\ 390857145748977128712353091949678859469858814210687226080814371014318085888862113569201528\ 169290594033749141121294156299371911224895801604572157842108812079446923233296810158005436\ 175633123327394070699558890783959011112903376158566141838621160916458746840412213494853497\ 474269620212968352580138474375144820460770672719452671602908785997153922921412074452631310\ 131323026109178671892437147240656546783358426023036862775538816256793809660530305602729690\ 633377759040791331123166949287228403314514567484997433608191851213631333797106435919459875\ 262219713058880009786542053894669832714561745229478442734339116089132464047698244655473600\ 953441368743420647351145116259553959005662770386556477618215341669420629834435372399613787\ 296827176599744397350200601727819556759844744995256688472055949395752920298762464686271360\ 669725978702831702395217742251878298108861941333211229423014396530223258662807855295673479\ 162443310133020185131139835424775176490714373992196709127320469252259461968678663790266073\ 551820465994164443225177860745133955633052426021910326393369995832792346105304590671427799\ 534261175042713421174969227391307629176980447061168735472661254908581875030394119428236350\ 382991401750949969372730354612185800970098854831975947105166511743379649637242804437161285\ 225785305507615380799277856263997623738822698328391333166312670966627707230973963507022014\ 220540500422546745710596264983227166883076833356161781648477880677295905141308524026506232\ 866238743005869884180137150434233321904963260081555953973659378071899467106223695523671445\ 258397339087709972884101627712049532114390236460875864346810590996699499880173390706146372\ 025949273818994268245886102951335222080959208253933800007625059755559034468861748574597049\ 682067545742910319182584915779291822344505615217804469264515751558112659264614006487943303\ 717221914332078728042309509034800138934223997677521657840620470145165897181964256067193546\ 376315602196506142872820369571194899734262441550365063324393305472097532592579657277904329\ 269103243710235358678715335469810893733076363161155436911556308939583805479330223984496345\ 538838933652733752093891565812398317331439285438069814674670399689385643518783544657531713\ 781191471077656583061493206364330855917177480669878475561227419658062327860602826460754292\ 171721501963162512792622618339049211469985715337423740053833838664331885801939112097699017\ 217082137281425405379868833299145630761403697552709281714745507511560514913433021518948978\ 429250568514273320922080098149229761295592246812528628990439383119307270194702303629943864\ 758495234939427785771881577598090413583833317083245885497486730894016530011025100116930641\ 461739104454263750344523907633018898760453940896591484286184888046928016682988038012238788\ 189108608776739973014066070003498895913132462858216422697074867072642590302649669713479109\ 481552576289570573000532900320314036556065375832991819589675361214693200917700296687232921\ 813686891830928915063993979725725981320204748644836089446080091192760071712714256697928452\ 460326968113179861034532610299549545044483792369821601059802312435390026312964364299200874\ 112622278064449210405437424913377991627546048644021491367721297926722494393923238472363862\ 566058684851712199901873564598389189706210256088111332717133371878858178396755074976515070\ 222688043871647402055171112523514800211125235679455681419095884479413780834126616741914694\ 579929060021994202566438838207505636928272483386483094726987476358997952133382397694382876\ 713783750104019190383692683029396266833804813562376989985882779576914173173303588370905585\ 835278887965921675888780215189804574598295283770901916257283011898814659164748282388932179\ 570073374462538667692882787320335680170392836484044335311786499553769410238809014358115864\ 867948483537780209307577083788051718674155548903551063229395437469566646526407264003402093\ 697224263588818639499445321009180165186836001301660891094576682409647325911427789090899559\ 224869853837404141914379079841275739713633881536388124098485032396257606443666744838984467\ 649029166141913690942694749693507326362939168605469838344154085283961625642820211794709934\ 703145558042331068812417061473783580853047191725361160516268314845315868690627509571693697\ 720819583879519637768506104321394426349468512714739379929405662884844694723552158063944955\ 067195618245836452248284392493132360402878716966133636444280694672605584995595839181802550\ 345027666514246148395314635513419983674702619826972102388056253739047155829648872521297052\ 403746383839513706170479418987915494534120932056888252336919941760112866960059275048212077\ 230542993140050180013452690369912212993394083071569138986871522097372000579694912384610536\ 413685179375108548844519804629043097885915177510580951585633488112865975498990543783122619\ 192042827194374286324390110432442917536897231126372373333726293046683921760199130042879041\ 822893100340315844483579184733421013149152098786558046892105916687568638153175600812399930\ 304697289541124636143895785942481695753913259380766100940651121079216547013915669901815640\ 301891567050122168261602883826532658868331417205835089804158004347053764561258150540862133\ 489270154514865194693405286402115451722151871453699607651066333176361480613527505838394101\ 953576573518472897020689644038849331126421897238454580535534862867977280619765668775377461\ 002767465466029190942332933089617613652980902149145767806758891591583494644919571595757849\ 254878595659123010761883330025517366663505341739935485015487504857473180927459829732126233\ 662292956046529558061368359103459609973187249155639549973094221576876763726075968005559190\ 359547128832811895996317988902542921103834471306619855811413194776470000275477698391706718\ 307360192999263012448579305892275725767350587810382971675974037760583191401282677446150297\ 944988972934880691942849408627573230213573436452523215067877910849480818802281416164727577\ 528123572483991616190724775035545343445574659978213310215874824130220611792751986615580851\ 470497677731572176221450372100818890137345144383280412423983688010773478524044669450472082\ 287906597779347248554780075275471190308310150275972703552279847294640027246147854151791748\ 651201219333953637447694806296518322561665846501411964515318498534834233898079070641636387\ 995841050805453217745236817203616781559105704806251944969753927541459386518651009128799231\ 609489499535784546047105487447890159596926963676643848504378940387557272211950147983157594\ 381842826654757506690457939789055952967989120610772983903258711661300117117769277306104266\ 011398562330012539074489404371226566236891450734574107658351430725259222094561322457278089\ 347722957969273603955035067080109489625929003072625900176979313739819094223518419951117934\ 816118236100487607429687056339118665111475264581311869512223469808872166915271366742725151\ 359040057535955498995844410169025108372580556828227498943012734518791360901858916756705582\ 389795268301382235643309648882791147188501777493944978494569352588557506757188388511037757\ 665889141114236966334331447488723496934099644827291786456257912462187233750727655792057598\ 329426862087220688893718967715743192292379250453697860904254838060425757196729507089988304\ 527523071642585862598453846915879401679805158735376390810682211210715642635779795105475505\ 071182060929394811991454406993290064412717954252911086681058304237831822077400081178165942\ 965376579678816936743088697111017616800876430116711069689210404198595428599506337070235244\ 314938312919688993028469460540937276619198064226719164594511606413729527294294772794430035\ 436930317783597502495336862290976151217274784962521733168544752700665893512562775108006712\ 833541770442252562841300921704637564587839091847834377598505117015252740729646357121245964\ 101701022578023720741989952391988431838450057085629590551240750758769543961558827908292101\ 105124600569792261830342055100743519991782610317495999506704474579822156036092668504126917\ 952041631539656613219402096328190313988738208071285498595093934263071159766484211456358733\ 613758361446521466746087961053469530645042302362986881275445162507899108532740011574666706\ 461533298873738276891520878608314897316414293819908372038674515359585904031133847611472661\ 207878764434888656752671992965012213797804500783673392391837521046321131075845413725126475\ 111046549336905285903869765548563877723330428510830101617374109395655942097557162412178801\ 724558750728750542308726402621651502410698477075059481887505253757387900781735747399879442\ 465778760763985455156859260366145989415744983882382790056102528404112206686498783785060142\ 953942250494467635910811588601477964389777699005801967775998287157636813829735746126599835\ 779261967674669418334901274625361537535847168586448863576488582134151120224452475695048414\ 901414191253656717565146291706298156738534876291299115465598191425840295527565037965909880\ 949757730413006040129716446604251997079488337797894847307880586279668890057058230922198298\ 642320647682612627601726288449752014614974840941842344903295705543310393743728999162382816\ 504457769262148405093781386118219592507581740854788075959078412667555809724134485584457213\ 485897386006966037243225910966835040484535968205924612619104630704781260090406606585616580\ 709020763832499691235329841754831754009120774942822342682938270769226964095560439568257797\ 337185679331581070771782060625715015794963846842791232802749605942299904698958862013040206\ 379426632927140435055655894530505372014700551645423703150996047937194201008731906747342985\ 190105395615299604365508294205685060239139286672601038602451594601880432411945540602032509\ 075012536680672623487877787785186463873308487486946767622194650798763309136320813230688407\ 172359398217690052285601982945238852566339425197134878721259801907026967961206339453481113\ 330904236961506015262017756531925732442201445910762446132855774763472836779848468701747631\ 320147428345744027119152940698904792952771999383474177838084122448203532117577556731169344\ 615127390307441963227265091747289261406471102435905195221158461757309715104382760448511468\ 461721982816961967905618876364363718250048145330655364018858813372100239177076847843434500\ 756832698856255074591488694697052462704577965609726059744021042730620279219438435580556481\ 700021453256371610058428624240505636627803893166482851106091382006024284587983736896482543\ 212903019123182732217209059099551867353192906961404096841677504555717077298501796471108085\ 392455179175664311379142581128549474469384581503692799439092237369368878554954264280164290\ 246122095939358361276851400109045911030599702296055201264528379655120093149810022946511138\ 105733241581742491782413063780450759411728209475474519683179657784860844939001595568113189\ 946534051214732141228174707685713523204932734235050709508113259321030093258656546377389488\ 497878545206521490290215867317977803962707616778505334228219609618178634541648291011238737\ 118629459271773037184762717120035559459810902527712392366145576712598714029848948563714395\ 055186563959997012851238785052856507845409686171719115742668984659461609399512919460449610\ 501775112209596867949435840513593472279346827248966064360646385885664368653283607203164740\ 088388166925332732130660975944583037358410072603050015705736411981485476081586851668892220\ 744702311620619083395717211809104888078638534481564637713359802630224173504528768615828648\ 799864234972069398251526956476387573686970471269445660283144181058737200492571603035549262\ 741154847566452913425502202537625211442234531402454908573984275624820909011021886072461413\ 161034544235733680303147576128035795799121509504754671491266029334146273945476315524419263\ 286504782820539297127269259309212078653784961748723772554022524639662584648376069109312714\ 048937767413100309246659426471399815370448581718915161813889009382065724628927967110948405\ 226758210489022073073318038797131530762412827901726881719487468156867973978316615071737672\ 031468855477948988873514969339198104181145689186034249727465650182070151619775303464774755\ 971317805411473141964976436274057223055104911644472111485036511392636246499831818400507902\ 290715036122274626513527173838421299802910442217529381096534760828707166702270809216725672\ 780983978882642020937479086098367968716885590496225289594116545550561052887832292183490577\ 350247826623090552614377117264789522407957703611908185421793095992214122324861231503908446\ 492920315594181700232787575378324650486895258476682590833134729212814202098292933062561284\ 046828538187027383441438308012567818695003136563565604640168145043911834344976813961933400\ 060108494405803148102600371656719178534537208181419667134299482072638809730445547153502808\ 929911801290585720132190227938883663950294767300572811573150495180872110353467301793103376\ 242638622737663932322289141580375610938063453351294589845865314763296115662796827261941726\ 788248586508842588712779035121313328383824089606584453313298554994963972278561299095589712\ 312833235590245297690668733791419849573032436667351136128755959192014787655882026298339455\ 487565368155260013808784490088190277793931757267200087518523113718436559977577091821289678\ 114054743821344440737960666235204872009871554136878105554406210834838605097724435198657520\ 744857953697036350562326969010148660064934134026608472604011666872282185021979239938123348\ 513120803612829171359224979548943295770085401066992360674139672434624193066207602929572604\ 282770508762516137972360649375330137177377495264000553952737757723255793807006992188382874\ 975046743477072428429788575400325712120515521567269731880016438341329122485170349218842317\ 490649697594351246269315269841111835069260260422940385137858261543743220374607845396097074\ 700482726949025682964553344132686230159071279693376836608130134126826138399052137940579856\ 676391448581055468098472383507496944757430752698563013485517793799194008156443602606024671\ 106481922842484019610203815886870751785420684239695008955122440265984101144355015756918334\ 838261357838579817655646385370058043596773248241661885115986039007765327660937454299962085\ 391552636114836726164660851342858171376360673924558812020325064207796297262120437548218562\ 923730340281067486568602010814816145708246834659235588270380712828881645876655874430032291\ 495080503265264912628879650267840171168645639095355685086363567945399310319920157491870332\ 542658810461283509022859048412069534025169256501878199793197635777100349196522415605968223\ 934463173339210287255146931086450472009493400862954798940158247735239923371247801205064349\ 638025502647348492986895392666535806245419787008925122118774910985343197880968191070992142\ 975875294591611785806692641875795979215573132980965342259838744835669502544901379190816504\ 844715219908687170558767918062264715963265348492116255119804111557841550002501093505192811\ 623118295793732591152864643240073806495691375298763592372352098478348955892392060583773704\ 826689867797095566977237842719343682185382943856465423711701817313459460281907289511507593\ 259842471195480001434752422669247235884358477474350873482534852839532848388123258916575330\ 997131028501877529371488356130882341472380241437642466681991833253915439724862223769200239\ 286629513359641616581627312922089424074867524958296807310141211410619485194690343387477424\ 224916257562588047788403555206231844610036287391813204257851508188391617960813565666056729\ 123603181574056851765821481552841153027339226859339791910512576213876164319271072341701891\ 633159550767578902262337522718248506401585310424058371696723646396327827039373899886727475\ 349131450195002370860074044429195986371999981920247796926637645407709893245747372408216050\ 588870202635559280678910210195856157091506946562378280579083921964865429411856251598188685\ 197592113389157249638710344534110354875508417686049057107254606636836788503275748848533443\ 824540060600536692955964880810015770728406036492831329735055879961622910972909854151297883\ 999994964354523976270704343280021866498938953663981548573734006977784822140698006725650816\ 549593400619541583158434718437855388009561259037242129971774010716520545375664759305286966\ 657515871605740438573147122457848886252088528273417768425346690518775946023516691955835874\ 489084477916465484701423030437567999207168869242230994008908324637322544382525720452544983\ 266751351600861146787622903515804812397071015194800725302436622466905793991253393648999088\ 594671567242370642981529978316819245026454248361471325871299385121357251978810896388442706\ 146166502551634601482735398901631643223694522034473547210865063696930958208020888367153787\ 376512469136727382250909486907790540450868067502768323458566896978954758189210752070303086\ 251649669251401504420505817360848217901997515253616153559101017133967326697373581979546199\ 588714974661652785311756376520602744204093857233365653198962776656677180673353631695501156\ 526499237516225842775848153619275900378402906231147483012973884161607808424607945483070414\ 991721134722209311557065261636614612876111278939604660170796905037767932378390003322255586\ 058304122906249325630226923288575636745532304584492385980928953403925207793019411613437519\ 232099528006379230539147176628601905588778358563172150503911672861337026102471118837958202\ 747869400641299040637269702760352788082349038270455709323934224670207550368201362456004593\ 749469339528940148234326958250485118230792163777047566769810036600355296600825077018411693\ 493628687121627810991321603585483011967451443770435505512478076374028064001727413547853607\ 997344006869604098375698317884827669772759518784696240009367137238310732806540963055355084\ 906612982650628710025114552859612056425358592227306419477357192105645243192918809318285690\ 001180374586869559404875127236981380624716227115433380189195336057910706342421687425962033\ 283205231630627372417912151367322619843190456341269096081490370966369841829123092133053317\ 240145217285126230193571087519050235593989626834697914309864416274238118273119281595232381\ 344617248775164189511226746701911706944558380215028899330583051741040171704841842122178841\ 980688856302527922763886651890146646619038212310279922713781355485154657168720176653409622\ 083960600505602151827681388150106412708580295219806408121799968523944239293727588963664437\ 883001127181157615452223709165649646716087788930159164600607190995086969492700500026443622\ 554106944738320735285832482685347678829794140562826757381294617605988868055505951714923087\ 620057149303479067370460734828380714630844282870888976450595428648881210190567076898920132\ 107460073543449567429737538666389437010408058457765622419599962634937804212569526418076751\ 329175532689233752326091927287856213057188906388167182712732118714430811714288529624945102\ 847361791372846824390201873655090611726392439485824064322301885824809653697180448560216126\ 262734186636030500644073619864893646465790942400972510929794554272994639292592757027439416\ 883165890259257400312891460943569410129972833464416672641069711543484059216728529388994742\ 124257877775659253355461496157209772072077918560033935659383715536716848247673582886995664\ 763412646012221878463859334078479335414371059520254925521445257433097887850711392712158885\ 729953782612422301318699621735028842436156486467220706475718841678695911266138584049006370\ 205556625543380491908856104597849999869577390376470001342019174876747143264382857097312813\ 723219447168466494003083852663005397328409656500029031702640901273268273767309967265103602\ 358627177108161613418239376520908991838372612719624237566815385226347824687539416370276043\ 912698552877039903116789370073816491420134810194992542255007936761178340861255783798147680\ 767585739168792507388935054046201127415019085888317069884174685508763202013663552911873194\ 467589286892383514609618345005431129153574945121294585832056386156730460468520335526551477\ 049303494219687394404553547850790473100760949901186955004123021611837630061212195886335449\ 093083418195695531052540874186659734218737022093704429421074183712304897805002578025205639\ 958873925800891754898482778723533837978603693732312653966977660010066120336459272944476566\ 494923249273937403410158523810167128691172304360440303995157105825341924699287940149941786\ 404751742101555906478432643963220448518621564617645200735390330151631315662037947884454766\ 546302533345826472487165132996169996710442983846634048236434796543862087463372307387378692\ 057491725351185804480598824214767093379140513076055051851863304459016027351527000099658954\ 915496593517319163935527537520316926866212297518992659915125998316366115407993595694732580\ 819517996678410672157971524825843373979193689328265418884750892429739586026546943350015538\ 469909831987781973415758369829267820925037956141264787491362605390498312628864298962562063\ 291653444025548252427962804131894362346709137818379675493367600394713721998611777409254670\ 568677088668497596543747862969105054370625201115822049208112120759007909097150922572001966\ 553218783543071159888994173958103624039631958737674370642999273817967118687009663762057646\ 786650322864814439235481310627272732734039415039817951080695071048919564187594091307120028\ 562037852674303259504005834090397276151714203638963037373132395803992765668667539096822504\ 295882433633621631248245963537658000206348717888661481133087430927199306926752719989950632\ 290392214717945382968496096564417146058121196695298784141768441788903614231931127960039133\ 873229022252741277405692879896541123949746130911504301687418678297942258784241191543019680\ 048341065477821008435087780103339110547613836920821029242294554469574593973974321916232848\ 171271974888015338328117398677153005598697685831283260850163284773143693942425075575248047\ 089964584500115578361272577336368313229561734628707230981643754300014018612094335933302396\ 274370610768273390138763775911740470957859834495247432741718668795723375990139281296922217\ 055957864330251774218440060559614035700623678669857005345638444595495634325149715360006969\ 986801613681854531377357766571253539189040205650129853068098595419153582334511174248472713\ 405119794060271264640478192593878060136751230794102683018430523572438599294062189329458988\ 731164006115301164754319634551389136323500713151668473949675190726443753416310585183507915\ 444586222447669431012776643569913568736304127252694219842425973205817876936267718652295575\ 227629532387021277321692709941988088012697885859580896393832897690589685196668679189855261\ 203998260497184085141116281105961170478931485463949080005287997183988106049155751760151325\ 508059033474170848432883556378863063668819745519262323377306520784484328209093422306609910\ 732653466474969242940835460987975670745825585218615976427876485330635931169087413348438484\ 597904119061757056248077236926619887582103156969694055218108343393579429186615725566925785\ 337898303204166819398091063699605410050214426575636084954224078651840850708403046656333403\ 786647268065008175851914447397525310444139328560929385732510242617110382140788382004410101\ 688308836997466415897073241806555446545023590025195696214921885038122623441412995068222122\ 348640480295977595761969352621080401650736592802558504737607746791492080645349374049028704\ 635690628236416020897385443870545063282109508935387128032550565976228167014406833808279030\ 912547436223039796930047579651874681475785415609454913833489413107176472096412559725770148\ 596083020407904147560120890803488118770845675395140355158447601352180800573710069763563286\ 199759379882605964245901941036146685036803400914920897622091535052162919620160964153714551\ 038123889635054617980922722871090435136256606116194419818515602498001587709257160488279937\ 065019124710471042195256141466032130089811107330790254979510026341959782474244891548226645\ 625128907755199755788362904681564659023501033583652075303545969362323184086794934387364046\ 922489595372262275993779628648981455279178479575383145602986843002318145249045884777138866\ 062602506146871292967921328893870927633442254522980338459387527683619262415552103168371724\ 330337024462950978792522421393250080575310686931436003843018812669523810124524494931659463\ 558521161401196225880575256269628643619913302299101740718074196927707066023684179862004687\ 967656243437434126252883889237127998310715932996224413579983155174983605508308347582450890\ 719936042497012756580916780333467219321166758627931855377610978812500613070134777702289196\ 656081982942934684152520020069112920372683877565475825628200765904671541936751421392176821\ 347656862812576558502336925351308562209064941583452812727840176958252692710840058547291365\ 280421460626339448301617051122694197817263025963609123654445899762620867438529276875089866\ 392896206527259019636478307421900155350796457099837391033910419275055261341737040427036368\ 596400715095829568349276931884512470474916488754951904610646211411877356579601495005362248\ 346858433322512004528861314045068228949913686895336129522713500453021062975914720555480926\ 110167807707046729010995827123959421071902983691026543258498072295743612732868258937270682\ 689150435858177418586653203132832203720718445256772498064071442526699294547709525566791291\ 443618174033022627503111008151367470415450395023824077066076442905051266752579638093315387\ 803678795611082865645421291554778192302407926127859430044147603954736931755273219697642939\ 251037393181807967504343950873812812808655364778497738449055808225295069460963741806496370\ 501162331881021897171495176603467839559749141173573363392988115726220600696551452220073994\ 483572956167061524237463432302419543777444628183266420871910895429817332965855274950415813\ 044145802456577790206569815613090719168221397227390889342231921675469833141696494927661439\ 725982209258074467283243239473672103849013284940777114683027041092111687123053408939660252\ 905906025552873555707730297332375167779370465417006225880540335443839905647796929032170998\ 809948635905169821256433640762471636215875378209197159362823301646536119401429751894974101\ 529570645426809125834606466909922225170352206808622188148090893616492619461580906983790647\ 919428257667677042120162351820864728131865238479192102998481471542946508093555467594697617\ 977145155205980718756940310142753314519106795565983725992226214719217389581623681269657268\ 199319827913234402661857767968829519917726102242660760747134731829298011530832381753068283\ 176263054300217805535036417240075979824132265526221443405725506999377114311660378189035890\ 054651265984867809596269570587437801459664975994359650534542425648037461983056780695546639\ 437658726678733495982361766318652220022783199911171443205439303755986092324353300109655855\ 692506549891500998146173307489329199195531912480547162891556676198646080507935218264372836\ 385879699109961100517225165850715693776764995759813301326912187795851316659432443711257394\ 260655420988779924795490695283309591092968170732574431386991849488339725956939164471252027\ 522834971638269119286144949892567542862829704672364460237327316081241827149494893929190527\ 047097706768981729934938022668515395397543127687838580468430274372462175976298687387631040\ 603135005410233804420903620508522602853978882153587021046194759292047341243997535346980809\ 664175182350541334375568073696484003099163833022288076343481324931915967620342423254743889\ 724876154110221866707873718615927847857126422485244508478067474072571415937664506804684435\ 035706718073991625033745631359067099962404791012347004534257008660592177677573220886440848\ 061842457422781992253220807271188200850813879344178922930055916238848785041565502036698058\ 525435012407876719082927886438423966568100657489255424720582472672353973510508214315580515\ 934844402717601220447423600361782195454142829991177515607652474215124096931045385862074122\ 015854292359072098548301428396855951874696594941170668859655144258470258479932809167156475\ 379462089806390885784483244058848605358513107483516425693291440867565514581419548627742256\ 674435964805092594067055123264140764340421576823983493202935069684792743705464203937763182\ 173872225373556573186991933965992354934931002564691803500850965504950794232585521104380585\ 052969492778322035499069968812319412546456978593631675823874081464353414220333989604939986\ 311288175477703462577911385914370259645711381094426975445115755180353844116784373982036989\ 068250814598458393812377098601507693868108432878978997151619230877837535752922515229439230\ 065137931451296805879429171797389056593464539948605276367288823738060696358846516109821468\ 750852319234513567295685398961165485012017056307023665883560146944754378965214002570830368\ 250776920954141461082357051856563171825558109240073008575038986214676263242683579179197889\ 799609340407309230188037284304448349727833805096406016814740702375592593861001811289514146\ 678042780034625890289264805055829953968620426107864350681648655933989533070720569512923134\ 185896602172118108474174377143844498131733924905854193283720960095440136288115299767272214\ 187734571547040625535606172595632419292371516418080418742092142535163805336261876863670110\ 419898150250926163004307751643259487994763589227894093100315854607340905622960312773610622\ 039198920415242145170405586577964997272202983193402542022566971472924305133823613560061141\ 533499363284105620811254066763429592246413730979643150659951926546908099685238240739664511\ 093372201415777645319035761682333819809624541021111198758294293546098745782003677307274767\ 421508352582129162097525144955634683572121442434807352241572834749991037672280865550612283\ 033732992736604010436011821574526333834540730180072242401198691312440997787356724556553169\ 723757859323405665854322402284287920187083114162694384407881559153881858378556048451144232\ 183317987048036408153897678133149193644340360151887127875550285136045731856512771868121468\ 993509118462026691685393093823701182296129850170897125464915949530708539834550465752410605\ 693162877977265029758710827061288119658186586812519131042613169985962530633437187098632183\ 086879117328116179310021610186385164581604697404889558136628078506950807103257480131932808\ 264096348892944636432580380069731457519616037022914780656245584917741639131265847521269533\ 814609994543684716503105668531230290577822385499740607856414168320421515847359725789147342\ 900436726101737645366632106733552949497474631312850260776272419405020888494816338790726856\ 776486244139780884449457079620835848928890116072370147522093047002339786473156446037492457\ 692504240072394009097852753715387725681215558641921747337040408758283922868081527583308751\ 416753395446218549235105333089920646895652527899802363781939555917781983205554555776643047\ 322620520430658460390383112320781501478030905886741864989743413738290337542710427901896813\ 362461183268183785779616081050740942201767793473262870584346378028934730285702000161985312\ 183667655571116393865433871875169855002549247534221020095961917358481765928846789871462996\ 501782924683302505969268905764533812046036085767542541476345211274673961579189199269814261\ 309722811156390004439720646643350145101693769390907594948659568872192245762962026563873312\ 178182301398304945456179841186360934446019112283219834175451973840733800456142580267684094\ 969877909699618405252867785746031541558238344558432364270107541270099890990518224729039168\ 957339133366018487080752378478259128966374883159948156859232896264874390405519379396127290\ 692076585630716655598712520208187105591055852527362948668308150707631194186882304300317065\ 928259568377630334847132209889352809703785829472635474031425627872528136135414657738882571\ 283791362642464636230374730293186184697473668925029776945834548019804956045692762152514741\ 451585846984674971603803787345054163600099051687262481555616734848475310935152417537614820\ 754173765124406703616375756171053009477604712518844366195127803182487405276324420689336446\ 982338352673226219382693263660933131019583194623597502351817274620398615346496618074350952\ 778368938883845694902513813828957371361759267970859833168317779998810585556195437566431620\ 580289134068531508560488775268186418886154174852029090377261380684392978291493871147592282\ 759061644713258077273351453068102150576601616163960181457565226109723694787614786512713170\ 306732899647343240263830568835691670205555013160408965522538308120357229050960013882601357\ 851179815896831784912002274662545456947620218467595284994181944237463422478755174089171212\ 124106000193113432006295592998076054898137559843425150808072772030707604392787312107155712\ 612369806534234097143007206655864431930493842517311641052854149781431885850674736190984400\ 907853181904771201901514544831033707013813856814376576503310376357776052161345860678577024\ 556047081999064833783567592336152750087319041220289263032097112952948884504573539533473157\ 550418717933558451338591578872663158158736190812864389817788852121743052527795899354485046\ 328600735710878389007801941684411476388175507400486715829201039847253048516282199383668068\ 430680354070089413722735232255692197056229179642492684188752063016404741214601671978423097\ 101637801462482250110849163377208295109217313756942722515573625465423922146448966883470280\ 311140125616590488864267647683901866669894661517729642150598868302498467404041500327523935\ 993759844041219667995091058886946042056461118888559494581215585889982902358535951428444283\ 497701797436735525935733159325655580069218093105649024973326127622373025440421908095157129\ 414795622856110967555530182998749172534204302743000706502596189655370487160154908324874506\ 807524266930059926233818745998122962329280242753388293787725610833112847817887611553649106\ 642297563698521654571012412464202042072379632625717499455281537555092233937042572604721446\ 944725078819354544092588956545738677491054907370241744003709732356717851889516065176819636\ 127635507000918104874470991185752951985226627017889322831018188637735762074763254871453204\ 160569508038999083914504413515887881994568598756971759507566435327155578214995425358672273\ 448574406239726111309953822382019812252035012692699690427449750390478763781611573668393125\ 864737840180036847047110978231864709501284559093155969165457502142026517046239236054084937\ 744832540063554001259617989410407320041266506693712890252895069858292879741409494991247956\ 277056049429737633317869762010638147470042888926647173675888987877390292098950319707342038\ 796047853652975090285798149570984565712539569186288878003156198921506363857981661379979373\ 962955294517017673384528612648570759997541166233277287786537333706877860836955496437300522\ 969012676157411502112797816172879765186351139289042696672389028906403813325282867525249106\ 195167179345190024808909829500875481264404448206297271208424624523634840369121610824267710\ 537779881428311717987751750413597640996934761216880753963240340899557770281910433672090694\ 804745455026320651441502501799926194130429851372401461297366012615166378744195697268209345\ 196145033145648069925124294322403820953887468582614298793607341125116609117611762842671184\ 713441011241185209929508550900015312420092781307843871751734613796601339988303381615758790\ 850185465933407521114472581169835093105514765123461107359018502848462135993182658967179519\ 438873017254877396701308905227844519812207375960486814167032533600325981525539833004549187\ 918011506981982676989597627850743703563794830275123285485097040049434620984456351947805134\ 283712905093397088646881357307749866714529158397821362359934027094301619939488611880972671\ 460597457884312023883049014865960249090897911990657863135441804342405153277926572671628361\ 549768281867112412885322429080893030409742091788252242393526513536660046748596860272756128\ 079795411428795214629965558096283404108062745095628218495279865717910229265906428774188129\ 419773071840989330883433409466578265046614265834665082121960358121053721950211385716010318\ 610402557938775760178242290207472164181382136357947368210591616658165770503682752888382385\ 712480419382823396299427263624347914025983901956580177385685922416439397677013652369453314\ 471926841085972697416055389146970043119962067276433497450222439116597919614011757896929947\ 738078708818495566105749071343718574693513672030179384815447322455644365483108928663464836\ 024408552954774012226498954688874182831479539800057932307814790348696147195044345507484844\ 552415226839075517454818085952551745218372715531786026421376222179273732391503571391347660\ 235037307867460209015858443431927220368655650297468804549456270409428973648319653486596335\ 315022080307253030252485493188379368287818871168762648542262265211905370596070434884696918\ 054246417074813648475264255976716117336132868794143127520104914399687674508104556191653620\ 274600834959550277021557787673388933731146309549961371306312812762636491813943611872210931\ 845595143916296717301239875547896182587987849318913108111886380889919439093373450603084079\ 332672088020571452798926870801251465635713016511743254241556224525460677585042620094624654\ 922171783375721032142205470633943403238750437260855315002629797015923070950585688337584107\ 928532071947144148384742531128069763705078268663209556397687874902046109831870704532606127\ 001429338255081448422619738237750080140545347173915549462280009144318732287471049467375115\ 408656685674825353518673957321153261479182376644169631201487294368951204195698268769596289\ 796237188630452708254976735112987787904348045185825214315151797541550756776320831903361123\ 975162382361884374581328031392505642172846065752716176122401335600548397107147409887842730\ 051250274738988327588803467070122364683187423262043200861899004020862637841859616668344168\ 593653420928879062038378995666156529362636592864276116059767076576097393457375992333761928\ 764747771679223833855209493500207218171652882311159127846529942617771457998104386741407588\ 272164413904151404697506150909877138080491768421948488780385953700386339709091937772966430\ 600397813069094898665528948802196332336119075184066397863491188093032379862710185025862103\ 539291009495452547697918315149954575932133766218182046852299923835420957509115809511958620\ 809751092498694842651414021455193231313341687976465159150432743830230063680043184551283029\ 904671935969802291811103331483342736284396540329973551664889473652666846480703963947205333\ 749552851223034835845601771071240997841562334811531222172515623741877973440487882165907799\ 131847581310764753545619965310096735513778173219493485854493144225376760534999973135165334\ 715189094993367565841369445577541290723811023471239788314252309349694198587919171438623261\ 132014107022805250796505554014619872323741930556296620344026335459202089421010491641748111\ 966791703625311961386604971739179099595163420422582194376826687736742725146246279425965622\ 510179377794118676000390837167218824755956507539370245430053857270880672937371023037320147\ 647714179636513156775136660095468641309642329783222169011347474937181411742339373121826265\ 322157458919879600362430669183575643483769048433116503519666445462419448083403676684187060\ 169030611123762033110538147536983334260102316450017122314790915595507946651978000236581933\ 782789013775909202301355283806418676280485567862009143461429970376154219653365340781169493\ 817789853072557051170034915603717871871741874615779741216859451032305839132471820178958543\ 816661388658225746404437914794954427130965143198915826883731073522234435489710190629657482\ 771730402713887110332313429047956074436184279941568292876684408550243271142378182356072742\ 818368840654091198593723923470831051267170573185323354199415273447071749986542462684476571\ 567931248030603890685298688472551070117691520339437816429959768966890209264488488927512276\ 332768040222499793017669521901726911023609065380524242729450638943702559229035014213776220\ 678222584320957304543270554232187986366950167294760787769245530154655185407788785682270422\ 416910937120249534054730595567186167722497325930879462934694740422163755439058707422435378\ 145767482340180155941078197698134109523067219972355731295196994822549929631365154271557747\ 507204060686173680282364794416186631054555255375392146394052334721118739957974046872637732\ 408965783630229377234020153700447063334090282522930027442674010130644687004053757459590104\ 045363394704614694034714812324344812077507899839342402819506978262941445484899894151825787\ 535485307117604734060778583465486041950179153422034766486439361173098441573400965210010147\ 282399051021394638268389530225054670516374995942459257769734662751351950452094814596001712\ 490648363347033713540373776790715432890277731100665372129151087760122940198380351355684199\ 643290007537200156679217875263354379632609242795552412503031046448415006523796728653071231\ 047171113298794088849137673475315176339668715316120942202446749166510788821500952493374638\ 718774457579584967012334709356303606448061006392676323685728472833414547822578030004114073\ 342441970483013493260217864801577828932374569974970025658865278921533559941838644620250157\ 574728979765232087597070176366868061955573398206158075953948035996093226603927644528266601\ 969319395444321680253477324627050883938674827319791480706018753099179443871695476672871953\ 189178689019202898125164893929688446862705122893012032377691959095424904612064610022926412\ 645653019406618304104298572405640236124446192995352086397296379496961097384140678266262792\ 687162303380490459268126441194118647912487218562660990913693870738618980802913221310875987\ 805941073298529896824242452596980884472744996189432510742071271025910406596379169714258753\ 002484463920836258403116192274991734191723512762978047068919979189345515118741736475455059\ 124032357358514312608877630108992793316103172524249822282101499357035543465778601500189998\ 557219640724368076167233095622642992964219698431275540760206069583741779279192669836641478\ 630019625550718937334313286489204026602783369382758460658041484330351225197540740865319603\ 755988332229644944433622124645239713321808758272223787478472377564646557050391779105185003\ 678501910809953272485728764484531179940886247220967947443522976779921277807475186515992487\ 104429815432153236665550881408104427496288718328065607442110631319477092909089029856882128\ 642435277498831782733178369217675856469993064665691509674022621417917183720590023684640109\ 351584357600421980616421829939644995421413769443308544054256702406846538890016955269167837\ 186970909280013349924545447354382105238263883202857206177775025256440006259099836799543433\ 593267199552772106983679114929292711765006243515957750276837188658585558830967819789630748\ 109163001952413063288607829759117462891701146022963175088492577583456613427874943610812349\ 996278987134584598227678220406755706281845104206166228292582320540767517922441228143435776\ 069361004829290549462758823229866851029455963625507518123417375151399567304218447556967846\ 081683539797537516740418668759509619495431713427942752427362550307834041191811653034405840\ 336293068524397981231511013163002598639010409844003878226027546710404409802474435483416711\ 498731344796468044701322836277175398863251602476334411607755400488070880746127447924632742\ 419756185504922333477968294559031370539773990372753132771986320955465680050728572949375237\ 047781619278924982871419459553140936454692477520031824082551660905244123824407575784354667\ 622949064871814208602554773081452905917744005133703030829709160248655653295693779476796091\ 892850221140301992784366008104287432380069746588487836275957672480069738470634617293528753\ 303532704883665622827199715042121903016729650908367565505391584758162918374085798473009092\ 555924648829768198758990043994799206290107629293242080097367044862979175747607320420974205\ 895992625731632527914885387806241382727289579134036053835195348881637509822400702845050226\ 340291545720536840846866762521953383018996604016279121832504297597497026013835381766223165\ 840006077358629186684300305760341009270513690189060146264532944211993570899853359829839289\ 852528718096202876761812218640380987932439897891038155792677345448017613891761269195394685\ 267739455492479618691065204107399385552209915185957604697622938721490586369605638200809435\ 394949296733751002812949773037370624245427181003620458938327077024542814567580098532035794\ 305869428672182075907089684604266997302691281494244862464521782539314610765362323440734501\ 669623891221430203310649305547516049143185898969335402302104412901397338454899371227660047\ 938001084294677144352325126725697284640930300739465657064418985272614425180127892358320158\ 341582172413881244408772260976264089992736977070627084148563076010202135887113824762127705\ 826215387328945292655461954900713946040262110732621252467113318738018674355343722970398329\ 765667539089534555408540912782580499658453412450762884150429211287603641943131078443014132\ 706063915174503406506668989595106189542761782277041549784716984109512490295630393393591065\ 963070157439074880238199756127930514055609178456763184688643775286072615240267816970477082\ 355206654670886985731459507187216103077553406114974792386732606051098176302655404088398264\ 391249283518624527189811366043787003975259711888867863955144259119202194468956169549051941\ 459783988454927986149420574036851846823121722377220849168728386239431474370852270471804105\ 068276809531935810209926571048386689206779033362706748841414582096522498229458168167046613\ 724277371635506098582131127488142890056755336676912677968048233766285733070558921914609301\ 111787543939773869679709291798430462660548462916850705018904042958994267000792229764574692\ 322728066470277953294146887034327614380100052116383673723056948128739378716509620244918888\ 881493259652822609450115245988555564224768438198650148355252293422517723890553588255476132\ 686288644372509649445185201079587856555176250524326774807230659164687415762473053459260573\ 212385091634084981469876023225433952546671941415349531064669205914672399203361615289238230\ 785462073014249192224325128928298476332449776869917692912667408327523765092084851202744451\ 831897862972327447354970461052567660876675378574231317431864150562654864827574521707851450\ 496684802668399429153576913616486437750216509624491395031157724155155148382974882511699751\ 783849014605251484604647741213812875252615971836202588664731985622673628438819268561985917\ 539441580946518838971263387590053662762253260349714166096247267981202905090609830810637423\ 780848128798586405726526971720066701541008840810753951100168638645346885369508197042840522\ 428799713110536867383204604343967889947353470286230968247270803119598107889108825339003284\ 643442653604967951691245859122849344724846084501223046064490831906564129528882395481551418\ 675851544341926259360285284204936401283314006662162283590629774629510507134662391131406271\ 406494078862120568630066166923801555154372897202847180128041467757734330891897339824951498\ 552519912432010516986280215022587070484335932935491844240381762606196255690893119252066326\ 613182505034931669532565325217957262838823899065893473864197048572009047662774791681151055\ 840783361981793800698477647477624619353595619216264776149820146433640548557028389663918866\ 475155456905375769140429269918399692972328936043454567511745525246931691825905778291867701\ 498855542132044425741010960493716124297798014902478697391237645178400248094431994549512754\ 832431822875219974717888439698900916968943632926706035907792985666089881589026458466680208\ 209651351807164416154546672249818018419074808799397789520977495317904202445895820422273842\ 013809939598616894898224213147919995350080863168069626744352952846494150861718641496615159\ 633618235150982032133558039956393193877303900097742007354064818130407260664621468640569977\ 541201874171136970996594435227776263070685431733936303840166229403236424805907500776390721\ 155792936453393610530021290817883415795501821124439288532991515913470279612501311212003355\ 639999720390899002397647462565265447040419485015201749781846742172675009653705633884430814\ 769604402945217166774352267542509247999160365977485334538608970356958672183732911963843647\ 550182415342565119326911268184030632422360348470250949669953195512987558683501186285511375\ 605751760633011750118669047115542842275833118479618068468453147152193277281624328008874612\ 986891163553212337745635535651324597922200031221963162201382143506406052887642226077433768\ 661268573870899223963312974807676785311714020220382435413869194851488256169738542093039272\ 983796036775246795962468805702587192249319778265177583873188134881399027025401546615336539\ 435500731037363859812968303041599327336515179778839765493438469627533730538386251243820008\ 652591228261076139963591395578485529821726892209167150090262027094368569852469506557311617\ 203681523854515854236444525256325889487855173991187192609726799080522198381615168845716303\ 557094038317016612328223585986487288859316535283028294189330952976324233514344372373039722\ 008294407923407953087858707800378664746582532376318371623341890734810170691689165324928619\ 299833629039577173138573732039944158686240561013799964880637596138892838301298581717469461\ 904541407589155888113114103011497003490335171108137016622254379540090212728117026267126342\ 939866024471776153163218767737191712614417621398218503465228273344854603582371157111262572\ 252460697001441263027243470324540571263778463722680877409998670203043155688038307511608027\ 542253759506098023692317892551673402147941413962562554691914440034020963185835674588536549\ 286994933872696382296655844258076616457077271592720149828469726868686982515516718830240984\ 954166120453183055217771676906483525187693025913548390282799471614189393775088869830726171\ 044867908496428658344371777128817056570445627317151868482347008754935686247861386123945549\ 607258746386339928228804182224082603810979582131580012280307240794572363250053643386226548\ 246082566915428334767696287763009942113080545656719391991775699828184350184548000487749233\ 250080010219376907915871139562343133507585377800265239197452257271514745870858094429217333\ 740843659428373272934650184609409576113868783340809970631725149252952216351361639961135434\ 292477320867812085025107063346978836893246603620393749531079228574614218700268341296684415\ 134438117409692382172628053638826150485134031965402999842387838895672623880739748621377317\ 312893173059488175248529039057823224614617382857237806040390819613528209825331302565603173\ 991671710489126173213139531551285691831999953777221704964755899051326661208962880070553942\ 217203317926743165767711958335630913674826293921064869363608119971026989952490056916298421\ 580595976780406471639180919518406371338803936966015827784695866197073019668003954194364212\ 263563016313269088173273117085073862773161338990572434953371014029623668885086780417622508\ 528121118652522270148472336141636743700768328955982118737694393060685811351311837274764687\ 046063480419382791324529102296204397169334503688798141399624758374923918521849839806625011\ 858550384569578224217025456959645606071643510234533472570297644482772857333530938595406004\ 651979415656056713136944279579430774017877413475331280102990889613398309305705682883755896\ 216067754297562034959334836008385742915116211450612421083098277374611642698838801179978050\ 592984987779659268653267374162111538427710676726022024213846837891220705078559887704432620\ 008180528691791467999987223734219921031041592491603336169908661912589008444924698819563363\ 339965620668425741270109913740597749489998238725260290253110440122309959345922933083767597\ 414239309708865401153479367835706935035658384321900424592231831236904937262742223668124999\ 796670108992575165872641528529031468255373064300573376835208477135058052620294629993927677\ 569153639559743815075839724886038368879194627265232070205539563945884708589702400902071503\ 757122479113257667369874843488544010750861290581220291561490456949492321524601905118355451\ 687676176827087745027897767566131245619902808894755088586514384452260779513901897320792537\ 224122585203648617634990324367668554128117469382297816376430288461313806677661300057349396\ 294505375256676733011415482876447642206370342632940683209783775657083606376461767234555150\ 571004155485508175082060646635443707751561398869167535726128213648769033585701814087542389\ 643695811806468454359673317374962010313150247331732480424141270621499814180228699460545546\ 839023596122558063561792161122344566799598653083400629318145885885590961819082036127629082\ 392201983516366380971421359826158409465658429254147744665194413317778754840557434409438029\ 671220037794674235617038624619308222813959806534330128665375123373080164064017305101407170\ 278405755204085200047895754868022623968873459588304420138262620385181747138204476728589555\ 088240364274983814607160955367456768959705240285828929582906733583264589486011488120508560\ 323273864432142071972881293306556839531698059423032730307580444860276117546359000753015934\ 948984054652421250841349930333887356048252542939179611695118694806205041586124171063304058\ 521152796656821858483173480571169057976281323622354483279905682714573234706789172130115779\ 617647632999455216984196923097287272745448481444343556756777581803909525572258143809568402\ 737825239829504410658191363450151651570183536930309481109792015077944914458638228391877106\ 453909971331631832384572805193728611952756978555098098546140080696748453006208343670742700\ 479631035539593514600314554202915961355974742847953574885996569761149098601279358869174966\ 578969661034899401383086712163856991899393223089018746758521288934244816607358601962165233\ 824695860918863520550548145168521172943582861465382019332005615644881710812735517198837506\ 053537454725666975265051517412906198320559547731257282868435018473468988603280640660830191\ 722421322986494025729638814720316577147333765349625847241468733882729289893714633011201721\ 276036080735760652387293429983156426372783597749588148016785734015427939558589335186486851\ 768503244910925898991747815264491194752384333539276879432569076309818871991321239014188031\ 459386097407582356393054057696099089645790914781277324189475974684374107806705815625415452\ 124289255491691426212452764793501932906476688853829954813917196242641937640204042610499777\ 418965994716709549574954767134442207882205397300101749793784473500723959918814158856567849\ 818487994250569429918272451695735110886971652398949925621187888960469505936191623318680314\ 587770108788831793251434981384205251591658066624835698067296664686722480310619599206270180\ 024985046243549222610939339702880461408698120948149612145868824417636873289477931292589879\ 160867147683737094377063310674561461848245664723071690797081945819432646574221439033433970\ 654015093106298592251299376889535258523828609677916729205286089667025839998933425567397230\ 424061889248759466204039516676643435603267982168996571584157935482244410334715270177408184\ 652525113002477583587323831708703728117065580776024865302748013367081269803682669973637616\ 754376797782538263500579468247432941320522775789570429360987903529675676252324320637740198\ 874941348055701060454331965705524653618465458239362706395345807610849875264835164090366582\ 491782219674314636560268417570195802360872581452733723213028305357888552228536892507120307\ 424358979338205852935876798134124148981255558576774427704273822026120877898644923527390637\ 747595665593554076099803507735417596422446294428453457771322393069827954129819920831508213\ 154457836503020881495679938484313395390973428239169433675036842633522658703303673102832006\ 871433903607620234942365802720728206050934395316940780554539483405427883425785650291907621\ 042778672390484037827045367334345766963867029289222243474919157131772178456217129010922041\ 603063563264831768214423251654271214481568752851586073691347250170849004436212147904526046\ 933008181787818940296955995842113677693632839854700571099421831987588730481786223065058392\ 488674852556706612901056350376560143596696053860625985395076965332716309656116457088537670\ 613879959463823375304667229751380264837042134875089717353349152166778937894521284543252737\ 176917499124642242945763100334613961960563127135056138683070097349039484465024972702018337\ 029112586143729142606701655027445116089999370376558341571244704913788381289647431146443435\ 688142442425835659925048899860436235087979772594044033611613645366074027320653800993397050\ 631028528958914717841925701027025285833049482004643704097901368832636213576359560618364577\ 659357450611429009768016343562351263052769006901666932207166768404780501584283311683549184\ 217077073945939672706453398137727961089154984233359447002742563752843062372858662624042327\ 973974592180595649080064754254135605935244390200405265975965043261298306570318359140993419\ 538749895921338268575204891120969312161335031691093873319035698164293586066478602434498390\ 025038776519018587429088408754939406449828719401298360532758675194406324218120637419651745\ 812131199435766162621653549384311901208378779471024697632256737324963711737702332536024870\ 776630835302374572548824392311789084484173626848409055162475944395216573394176722559195699\ 852653504841737211220799518661440744823754672543559399940723510298799333842656271445588697\ 310481889366279157113269544134146828532563813705035365812131860791415760061016122105266037\ 955536429864609371337042840198220984156722493393823678455397932175673818559201374853721645\ 723650952544030155714947971327482350967440438069802431381879730671430216159898966219653934\ 097948944162924727386026956526301134964252251256866184608604712925367165720058556762975575\ 543739748915325347080458299775985493351944975307883047060106195901391253704364324900903301\ 223522605200002758204847093884924882110114148880626357940679468633084997697742827257597630\ 220820180685708247480418157697727819540731403639912997688286399764518435073954265914018926\ 761640374640424574861989204304886920839650189093138188497841159021901170678620916014305167\ 736993895033846868436059138079551072094393318124205242760261908845963451201762681815261130\ 637211434848885337387200838884758930913224998364540121636449379731218347618499069681588627\ 745879591654030876042319362410690387553767155228385118951271002866417157117142106105927356\ 410896867238183607084420083833344476414271334985761292447894991884253367588738194098228651\ 186297935246481627898941058905689796302834180300721709413536395724400083088307910671562162\ 761454272186549067971993205886276952662114712798427286202583469007251664256223753710877518\ 613773293974605396709933681703484367296730691200285138312660960125016697298709723423825617\ 618785821942365939459950031822205879054087026794536363749954430102590686716178313450813476\ 837733257224116443893496488909639142435971908337133576444002763411614029385478811600504838\ 237713117473770210002617758839697891836759015323496061947805453263616260692786261250131770\ 078098179038458684915862913803593547531054685666788300610302154844851700975655508096480368\ 693386301161423396465959457713919053420134145316118511549632793727043778082331163590684412\ 596014239555270464118249392490633852206386242316158047911539148026634027367599796207002298\ 818686265349304865757953521854473747889516090989897575063910390646780466458041514223736717\ 076020751405547316484136220062939348820815152352038063156080097354984492702667456286585677\ 579614571084435277563625391313560737915979375147558399583872329692338572441338133626092663\ 447566005221300639273067441540921368129050927675660384144799760259888162798989020747945858\ 560270635873244352861254008518268682702754002226109439295452398176123364883597131221006220\ 663451452287464845218573108632862893234873290765016518584968454576197814392961147356471577\ 173095865367233008584346913160186973136641350110647774244326110665201235257379224879360982\ 315384618760558013754677689024724249896824937296229619654657152203982175429616427430404602\ 355268125951454039741987386448633184900142964314471705356165408572680678860070056567024233\ 821142832991791285146458547793123020067204188317298766469692106853227008656501151698422787\ 583648203094916672847426843318626123472612128110514596631595956955649746980824869020385593\ 349693310821423442254678507268609581580002015414836677936322642172685053838904569829030986\ 523505262170292905722546369583357353519887810674466359312991095760576420028208371900926502\ 295439343029507817076812938567123099901915988668166264520905526363699897239159072472876777\ 074493203552539411559877134135703497379038953648784263301044915680474352244647737167357768\ 189746465521516621571382332826906423915032899782610205142861019384001804859313179267376946\ 296081798582461368174963537652311961514487373258511836595209121585399832908051039969524961\ 916432138053789380101036153720295935507487996478149064470014708925609313078765355330819488\ 268290547508804842565960158284650815558417796760178556011643794737963445412822770307818487\ 466282029847759471777468751224172906399410317965211687907169320402181205094772845882773004\ 100116988708358494033559084840856913060656555900240891459844638334751272898458156117897279\ 084291740231327369979150321941805025740623763614184898168295746918819947965668203234589660\ 201589772199659855678705383559822772147391340425371540713164509055068237080606487042851296\ 651835956957416333050100557963297080386631276867402611534520743461751093569396585742455486\ 849606004724758244951674873945144811402941449185719436609408432600042358155485789997260685\ 592860952785683844694526113946027269522654074322769473137665554993086273908291849631959155\ 894557691990289848169051908357140329552476134642132523845374614415874708179708441877890787\ 997423925231855144966019511528441622354984021729226017107017940640161336109226710942105147\ 917391108275647178114303381199469776654878637296043334084814480969028478646473111918443561\ 197741555056534999830035186976064212450415107438833616945530434039911500612223372379431962\ 902592167951519820876087061727578351315846607090331465178119645916269651634412199921617643\ 031451945743573469824144866044484728799102118033546907722816994128944621033157000054583236\ 471979111485215843383944892007251753743513385768558659100340500589339554335324237085302937\ 531094154182251666136176923914719152288383760183040420469609964771688403602048657757908923\ 628901105819400628562501642572862130863310449374020261139428256125857570674956538708796776\ 274868095170020526360814928099832459869239390300286446509114754280538994835992796115615403\ 587059046612633650241590750203655806152454407574650028324909163833853526994447116768780449\ 732539828058005590501658022690348482609869216923938336685283415633091858774650540740713116\ 851865841503474848653959010380219969737924589559368006722515398922338995695694770086363462\ 895021134105135183326367097346016047167289249392938510346923700678461913210071929656770493\ 701157313172165930312838203874100978211296582906677050973912695137154466062010629213871800\ 910905259368280472964966726878790015041626307499809709381617901071132737208596477320846672\ 193562813519185215354939490883532136196202820243878570252949602688743384941023634975007510\ 851423685902933564280506356933924307287356832180286592014349861619792757776882006527236601\ 186416442845568494177281022872048904779968501825448153618008204958505802771425660039837563\ 192420941561857098724008308514703553787249329546369590748877721133312173372640284029159034\ 127185589313796922313184839958117317086116153708561008979905158525067633551779732091613653\ 640743903664543462173402904918407195861846020781910115301454196362051517358407859912894253\ 445425437667447896517482551389678530860303874556513052739957058061312912636074244303261273\ 716353296359825685136564526790579764067342302134809110879333256513778535696288463542833511\ 971270992294870884258141974424649557400356419365360258135614565523261185759870753837351741\ 645284755393251689010099105823785404017830574654419336204824155813730355659844717413079045\ 765596335290152589994365655519420736773926185440651744757206047956362139690539443119105951\ 523337996829170822358472773130314736859701487303695742557709321664070179926374926098585880\ 184088823469738434213314858636832277823113417494573196001947767262312836434229150351636724\ 330460195421635252646877977189002171210923679952338018381231042602033229039763854852857857\ 400136975269866419512194740836889311610605915039293250570318533684638640998646128167250281\ 605798876463758333948077443491448009008012213970623174487229139636058596628257776576583535\ 356750029552979751184352806078767292254739690279388307850939670370241409142993134264095804\ 785728842784927509678678223305645944833884706809799266362818208075330890930482365456741590\ 694920888891367630723717379901141138271269700112334054076146900312497973306317537440836391\ 170939728603263022556855678632792945261629322878669666495069914810311426730681262772718330\ 997966706450850740322083548588860409868469735883983119712852886129369133571676642964274109\ 298578471870351523987964766202784094404326246943727999610607640260493335505570047561468573\ 098751775467884053979218441980747928372326712680269261535261265891035829104609141768508104\ 229037396662197566558900001383853509526105413941869212692038509143818480329142799900435502\ 301837087158585393266219392784576710910539326471690776595883987016083827804812566153351566\ 676436263302273144122265526859531341003926399249566567832149983877205653744593725789832230\ 601048006038930937664238813275200400966128262471442212390058162824625683676036131219200923\ 017779758087504872275480248130290889189432654853657850186647901598692300573061127448889134\ 065822513322262919587316551024076651005752327605782669659888855451837610854076996603841734\ 075143283287025206068071755827940155251652392000498384306854212609967843672571750813903139\ 717193997122614709237781633954005102850222500860522524487264961776834761035650964420645142\ 148173213395428192372766243792383183145396779781383743187715474656137340174078164644772995\ 924983553880697526272146906355175603314900355373793090196347381126893664325902969364223236\ 311001057049775007497426787937966414623515415614305257225860793089748981218473414784656731\ 095116247751088498503165676361547221822661515935568439461265203667378911762543012707529149\ 069672090484641641274538791756819488245529744596565729953076199037981098320272044003222627\ 086290770450248300731275321176914100751385695932871928702193995849995401919796369209302501\ 317217378124175620870026353323415793474496672524085282563344394466609737200530747231701698\ 200834394991050796630380819866021130147701067811966896947945168024757765986603283305829227\ 771723529107631975691528938303406362013960997887025054411507276866983879254734255600232327\ 014541745519454784191731660722630927571651323335819067697527812493651387153439438466591740\ 740279575749221580349111318680231589275958035487938075277996236319589955956781568149443105\ 058166624265667640595878313527661382031500026060875441756667191368383404631101317189089690\ 260847352286872097864180635957074920500875230188680481299324312130070918551844167737625406\ 421348027537696042822118669598737405382147637542211247010241775270645338721529419187030284\ 504463902594952843933778246966330618170211917798200813662206831537714001240160414767740064\ 908784197598457353322719788168221486143933478965280559595432346123536489660166278523787621\ 932764172131608114582796547214544025130448443758669581170945650508164700728187984014978648\ 403969878539280284278109167674216379096097210814823127436999675332593999262414925777385281\ 323325250754703793804699576287440230858144450611681435933431098473401566370239451967841543\ 808298037975301399075900179956205625005540723472787946578609019360361385152844570503959509\ 812717584673300989098042831195382533814097459029449143473749073578934574169721070323723977\ 812120964912697866876049481444853819845403215250776230696642390835234476306757472516923323\ 495209891010591325525616123386861044932157260527218536730787384434436979321615285198122204\ 583095116181020243917800486867590403975817944890008612212535731075174237030886189175258289\ 031743476950539264787746956674807379569991481328407890369307368334329058950662399550089330\ 745265859205236821074470703671784405246088606550187785151709959449060578957972472087972811\ 065348085003462760799613947392571578866992914045020682910511352431137318078385792501651791\ 971469712656649553478843171754055640123317984903726660453852397018760898196184707126932854\ 881079638250868458458028414918311315636693472183362992768234397784975967854896908088747493\ 489715064813841250640333637439205700075512751364075352005150264132750461368330395800425395\ 661080651399444165987601434587816918375140556051941949316604703708921729174052521055158959\ 239641771524939034677947867424683130662720739109800227495608469213804845013463299411648492\ 673643687885803136583121957919434028166305894278694953188423926827662052587550519834110813\ 116982391856416389168132460230622341336578048797194693921602189104922905072500511195815467\ 897863030879107333198516512800993207781084876905157650614211706536015180044168272624098152\ 249518506202241994109693247152144908486664642595096487057541107969428696437797261886121633\ 644160279331730997850718955006044781871453493879992773351894143018606318123520141728809381\ 940925224971340195892800296268230309656569867944099210746363510545204647480808083049263669\ 809215249355737739736529407712731427264902077149942304255181926741139534314388421606111532\ 794241150031492132095398664723248089468121708615852385685285992682064557713710738551132990\ 664988775348649287187562202030823924943562857009711293867113051515669903061165600387190317\ 148405653941351965578752643867421376027019658407922433726605607702226665837712547773222435\ 402528682387675159644962127895771590749442636033811056647968876052905144837308226866944919\ 728441512332261686731297623467133526035939854588275639262556782078115233670546140442849476\ 727731960464935169862208942587001430347569725200083608317241258777341016563931365176487297\ 639613202254091138620858498513939229255138003128140727593261829065362022837440258472230157\ 605758441068305441302927552799562655170270089655944796861218100232693593696579343727098086\ 555898535954360698482682052664061908347870727772286925456655735007685689059930226187215941\ 137978071470905687170653468823040197380070485541291187212640468768948263765350689280621049\ 120414715510563261699204709277878496472856149922640184728494735768739246628361663640753324\ 999668653622169071778561547456524015738438626857535037624269768463137914794974497799030234\ 916949159268867146979824283989833750695373334216507232692878506271316841955762831444115139\ 369219179137465279235983603753864924971353873393419599937276541945743416199131714506585472\ 125615559841182244298956373959937573163905256230977831098790171101608466592260398520809148\ 590153510985937628330705164073364706982234915917130691217188541075500888915150467700967390\ 238462544185128593745258437747261964575822859163999206387302836368662377651217558663747441\ 170880361944069803777390561963470290717701296067964225223544527820382364872884843500728276\ 205623172514652794644487814776148039235551221649566816400540915369649978126093603635160788\ 491741287462804300250420338754185894724800776970260345093405014437984952927462833372626723\ 493638441605835766562409520498285353232799068971729733615018871311746203704937351775596834\ 977416444852056522312890609391707854124936155439970970580617672160730216908290480173190176\ 809569037066779344943756625055403485833188573411558736220057805377929597657864642608147919\ 360706854290286420734056756530548249306297094471015453295003661629951644916522214499866098\ 182980300023735299500299517741949694984169806771037063016757285774928579309750841817117369\ 957956974017842711419213896540926242677639505872295156773976280750988057880622882918300907\ 659684449085855120015610421607991677966212286027569720835788056316784188321208758355462393\ 579528352036319149558048249143207510446029672904297060503056165987463245949972384783111955\ 017791903826150651573442163891912001222169601820852843505660502168589551256586216723684944\ 205971137767353614626013698614915006729875890150746095564964369070887461906617110039442096\ 623668151477039978463339546122648248917976939940207911766327388403535316762677460185199028\ 661568651836941655732808726570597828067890597604241237102621645051985102975630594886601613\ 801327427519975971645682436154743601494405506648516026263473196642332621316502299563273248\ 492139111689673089824016168288732515133184958910283830288026447796160879050768142810372489\ 859503363973248260418834349267717212132003293771537892117558403403463702422924857115263575\ 819483010018173516087132046362327953391616204492652451586495451545266114205764778140025002\ 048553295585164996511137936402428717371680145620058261830401595819728300110876435095539377\ 262391392747246380456395756673094522740189013517055190532518050436188408554829861900254534\ 333559343877873758428386570529445760525026789362518902146693335869692882743108577352281397\ 318353966022632776319993535844676007294990084301931567176112130094897588641901901348235890\ 154265203607079933127788681303342981028433043324745786253563305537953032164370034365897856\ 750214769599391944836842394801191359350028177879422147055524679867973867766438674581355509\ 185369459608206787651447180271301157033891062469611015830013038142985811792562787581451600\ 496386686734303665624233393933499873830990577099453735194778980627614721315900398599343581\ 365553267578962292747734697057034030817847157078387417240453128235017348818560961004633616\ 946897714656683036573285409248412732069660942669658073033674570698636199802039936344782561\ 443343402401455875753573584123904060756792055173763170185468461671677395833641332416980115\ 754875941288167201356704630608426878759273848948580477629328903179067355045095882779821591\ 314682283698126260066119636626868403283124516718399781731645952608237924162338250195154161\ 311297891642533389609773416928223280228039609047040602871995233451227714837876917916297170\ 869665712478839186102392575072260938261804522375499694489643220142811378858729911835612257\ 647791890287204045412570984891917889829086209441394842408353854458805458993050486967977678\ 115887920587988343345604594269016133598125420571462830184040103030799687768488135769794993\ 295348626112799130159862076070752853333069558536358518919613866495314280065251377869739921\ 341683603260773648772599500698088550182905031723953720495568380953348143177700809038519361\ 993563729013541631618628221153968161711436667323229532067516143313317049800864799503323311\ 959991106433007103771157830844772708253583935375306315110954241758618275666611356296472733\ 866872941565264151291122656528924786839464643097174041243382475529326804705941971893973589\ 897909334541756411130996637509030799958587051460144027720879322546634294420662034606633626\ 992777551143633463191715032479473816227497132945734878152615233160852525967870025656516795\ 977202673795052515429809962675018471780075041759007474756536611579430490683229944983385803\ 281260809212067265947853837636006659752819501678738516446702751450495541300899962598053656\ 611354256397174185660225671946938175931224978416634767763019816817643122657869450558384342\ 435240560682081115051283704672279662320375464535468778562314068872776048885846398138406729\ 124059932477233371773053129853671709244680145158971727592631616190838385571552307425581203\ 950309949559026219755013972138273943224784271177454091916576265210001974620951816012685083\ 894085688230760980456589903581607717407260141879731812667632030371608001376154451578399229\ 796220859825080827760265360235364605637943545189387105352117403599639176483005434573523353\ 586636459096144091622570409179675501204169109394837797671699376027910391324280880036883335\ 880064270518910713560183366568768341217819532972241418089825420394968016436935689915427062\ 767872713948299404423808994692303098920014208885493438031193068601588277629835877742842066\ 676713278076044610854299357888712640012384595810566343243683093153916438283196301855941669\ 568461585366114792257409054983245143731712225655548500173698512019425996748089858173826033\ 932177586996618727758700253128400812833026844297712498052980680501509467493335884236186213\ 324333352707908132865546785873676162646898535364656786556130395666771332210489364849542019\ 049120642521954498733788340460672438639567400159294859630836428862501604398721852577330999\ 972509981834580282452508625575928511101140545799352535611963087512707714980755842085370847\ 847326153362728326781731341066315797526537095001510366930676946270273333317639331722283534\ 044451599272244546839526291076510726675595206015437586015480183370520020681185733158772699\ 489414449070221874717514322782804509637244937308151533122140426874882050768485751282419605\ 721945677634264411084241508886876179560573659913592118030732412424036617120154093214950672\ 904718113130058583400938668424386494554833837514818131932550162442418877460735502777651934\ 039424961568659471898637430999635504824750016153889724379623261487988436114439888413748860\ 344146015185414283022062694073120374894486513506719657302674654893939665947046069625646438\ 260512359055664953754156938817681457395988462859287890152327461615196119032392052270551586\ 797806183656761180028202124383776755606145542416454938864817284147661516107547048200939767\ 434339749510364782903615687425282772454466235028788356041444799553367904633408402205428291\ 298346307749787840601006446231311043776368234787941378195688479949224918203112520968233999\ 380528678002271485683044037508535619186217024634423152116337024167283828458499942680713609\ 244702533030952520569554222379177900463024569019949071369761995656404465909426913913678005\ 702981605386278360159738896777904256330729911497389194075003782090040102250985721201667551\ 527801992921031728528955717437465019280614310090637428448361773674290303418255478941308994\ 414258431230417687670441988834516790365183471604234182093894274603656550235616604543905494\ 951947351694571602296241744385616400442324159984267583749083696700932362946360068896838235\ 336394617100959757527952911058421582699673640867157667777948717399463003004779099043156879\ 066680506899136434017106214423135700329201103349683324876378344122984467240254471832528275\ 096245821758473049197839789354582177315694400660836604587435725163581745929278630310567993\ 496875724362757834449081152401723541189228568989486914596648267668596127352930098216439804\ 973793556614037048775168435414582146877722761901031076213581709407539609512347064510997819\ 087941396742308539739887794543547127434387968561151970465294375997358603027604148649938944\ 143964970332721064220985981408803662007428459216302741337692420099926676295458965591532221\ 577498572110725047069482574377826017570827216854694537744589618813183435040671443220845384\ 331030707320376912828216521073494699786755318843032638917923977601326408627284922284291323\ 198874821944852830158023169839552062097305552303510821076964061365795919080001971864015830\ 437872170729849725861647586503578460410251475688864548016364808300416811556237611604862208\ 289869498036733260417874101245442229846962478841843489209282226934557307545727773700766978\ 046423166102906106084176885216815843175143843074856445101395207782189652912618962194755119\ 142372620943174576002916180024653950507226161952394692470683575842116396567632660351093762\ 628728785843229190453565206506722153250763227411265414349979828621296679050455213809704218\ 630902251228602854388916550202178340757219399138608663714011544545178802303343936211701208\ 202806996556082164126668081628817183319534913784202144738016490974563140639450542243493026\ 505525426512242003081132859767130108324266282647717412816357959141077188917167526848256789\ 175555223390473904381780085591971644285889513326796843093763879854067403258297686699715416\ 917166650970057629487415035399173654216166514241461553147616922876898465438494233865756803\ 978330004300127592772333082557811023735181152948006429899879112730746684322869601745147777\ 514548432029948609166409492070119713364006098420192939570349895263475399154988044877142244\ 860846577117190807995147462032166256191635873527406285275339745723800367647504897155448869\ 821124525659062358978248906920295684058194433329856047440605846146681020212219963539965525\ 195566371492545048742822136810514085591072555151010732386545984657077798364998073341617733\ 756857114260644549054037013982054125651806819026757591208484326880010973654977899696163515\ 054160831415605580864688098182451742793948788696659938992741111143357168755001954805971042\ 913431661231031862751789533141926844779726919973365296588160090717587941875744230190804568\ 794726500494876697078506894703726612490739619983391316800453209008470667929987918029836722\ 726896665585420093091286911217230644163106269554285098802313357964929999505401005559356884\ 926206337058386207521661854558870162312482341233531354217065237068627322093391717547286009\ 043737948473018112015395464798666098936958889964105864887616583387175445459789208355227405\ 719739233718520779642493283763092884761683489848688518801607573496222093894919993484154277\ 561481011539281218735810250334352986508744686002699864456792981524066325951257101219300835\ 627711707053402251299345336335460298270117018140726304944391628958337372998460455100357697\ 015193609777471186599509707716592430676103667267398148505107960771586987602420535920259859\ 315777201928750863304585556017118580476737938954354670754706747682119154528610131593088088\ 690442647278877583510859278378005859248131691557639204723939639443338386028391564703250245\ 274210877906095715544590699634956820939315272191086609569868030688400837400072107265505116\ 216365288556953566798231910276811208819937355451985401087840426104395562552878138098197569\ 367159056520317693952162831605601749971260174039081511551531812517308617219806182711793028\ 465039512408805551938928056759616837458711998039193233508539806840613982503547770226885327\ 561237945779502271078786844572175968149249694867824838043575501231122472094636991169523574\ 517023264320172564788580235435388771212686172968272338104000309239441040611156324651499594\ 180146884420681109240995652533723844288601578426909038073380620010403625743939492674159741\ 251194125676972746736199765011741317477118139538205441536907640220970524407443586953728701\ 762788101533531804985375549275226454139265496303069550569281377403129949023386020745116473\ 813825706696136574576470636932369433462019389054120721548748439871011181233651633497510578\ 254731085052857144164095299606435522789234161915088832610199468391229410857393122861822653\ 460581596921724395158624484653872165838803109493108307880478851256265907321437228272518205\ 673084789655763281835524483652932746339332661282176042847219946749459361553166420003248386\ 852850827011286139290291089789022793879349560367717865519030096146905600792797557304533708\ 863140075997043257957283343359177257585405042258877155388102558065385612351131637040245783\ 210850706649308428726542568912281197912132137915170827777118991574022253278492735374606341\ 638532773620463188083400845177267600862374960642818739822828443760790257447558339785970184\ 577341482351887749837570420387347175765273437519848872208225921918503172355188245193221362\ 202838742236550439218257001393840501700190104896828695092800828546480270311988486527335433\ 605157615480261582530028952472716725413585603484711314876825611718451382645024571070387017\ 706277281947315212044053274672091272178974289648993036857946337178985871243596757480343011\ 373727187634714101685133797974943290546753620602565604923195697953536533855573129322894135\ 823719470007828913383372965113597042482942840005882190617942462064785076998303894079234074\ 348694572270886886783002225449138060004838714342553552656274112948965547723984004346335626\ 025785984576467356485361761008696680011450181500290501433755443462638985563270783798571917\ 841159243391120516202507315584340324537059835173441792152618741739691090517436849203838792\ 624367088076568558401479441670473247934950410436412282664308250956245397476543823844470926\ 986473685223869400699092092648818879542486205012617510768959240169232658868677446514215504\ 277016890043576262910971938749628141325478932346593997058323739142036534136734078289055163\ 379170009719456799432550245278460151152289752356260428067817460650176806213736947600002638\ 660022008863059171419406343485007330880139913008588785202582204938409612973207716626993201\ 250056621927957242558592821870184401533547314840874670537903773893081010515111886657222011\ 218323210365938286573262632225582604768030616553966183782856420795229934539698499753673849\ 901064776301692850247480369834527257288135745819215524598583884547863574437942561864931941\ 974113477017388436290240375527258684210230264328078640465783862439852266785127087156263961\ 795462546888862076589740748447753312207405494409776891655425049321421952960743984173980428\ 117616798275593197641223489004377342402064408639211619072621574601134205540786927513808113\ 475304108443903623870882829942970151476178468033996410415954254270434879035561314761700329\ 380593188687473219812517483665739129236585273598650087695197198678301325696131683039493826\ 319046464636467441393996672569450002784652292393277293140407983298953628472525781480511372\ 082108025006762086652024118161205907069552326549553942582211943519721250370911330119710218\ 680436008789317255401519781818667526915907244772597632170136364444877620637176891184915694\ 411931288446432059101921387714358603845759681816303910245676723041180255418419779013323381\ 235806124771970099630522484704804304032635761588952341783756980688258673478370434713774351\ 777160490016642666166601353795438442722570057603778844770474346184529725392229549518006572\ 788195132505319621789297280788263015823240456594941494852293989718798171407814560797993635\ 276568778700132978576613879262046105163386320628840766063869882519254106725932317196575380\ 221731743639555718189964457434882343406647693244994258162817682202644054237912809726206800\ 505253903771296407680688821374700774133808346464856302964624637463399324255178950863176431\ 091271017696069201172858968829871337307718239782454795228560961655189915071545355827356903\ 965853799665713454873205252399342935480327509997419651813676499098767269583037645179144617\ 935329939614325937886554540772977494766681795262033323281627581096654977680319845319644971\ 441398492577853868171540214788270902757226642691670132447603710124485909162640590710381840\ 106359665638296259678385317323856751774978424224870220003075772068344893031944293504261940\ 936605977426695844667529954597841024830128259286184973679231213308280587935262826536583428\ 222130338005891340748009137539591670180244165106046543486209981753903367231768827635121558\ 248529772422502568393976390927972407102216610508550635873845712405875564068605022272326841\ 508719515009603449859499735202746867542780602842220784530392492266658792295753188979087943\ 562963947374711398457448794810989436960093875355947163713901178354828114807372562309721650\ 343488047680920377069157211637348931506473782464142432739948987575444992101640410280898170\ 621641821429556916355940392977844362526832609390439458201562676763348649451620063051561914\ 019829236854951481760447226165084128428392259810081105655481540890509970703622645197003289\ 142714701935153966841088042019853782663050605404411477974348648683451683260480805813111660\ 587569255688349251425340160730132370852611931374372351665993198630261394117464354524330501\ 658360892305801027336838712819660955919297349175993292052036333720401240677541824410054585\ 000287651414598888550998236643524684150019434991776289283019444268788609024591655336041452\ 629128653849042304536457183738837939894965529857036658752121554765886074602548941906793059\ 125987761076253249995097247084791185910349748853213947398479035019614618248506078535421188\ 946332436406049484223118516013526370124631970435471801630045300825051961730521649586574915\ 669366222587745864387607233271799146382293558582477558204210901882373428836096294139689855\ 210749447075635812087527471550697852025102348394175901417893583473132427646907620505467543\ 201513917780148392588068075003188390332304289634791545093848268064518327564986979251672917\ 779587616079979992945483054941150665517601625157159995616440455390652072297194101717824251\ 593820181427502206782378320055206599819867583270974830850969126220137890788152852627148737\ 022734401214772659373902922699688124979426080072125395343915244204357872622806707106035035\ 924328996099182393775728357369161314770172476532226049995678782879416675563644837742015581\ 598201282622763259413860004143196336873024669124711667770038230543479622375337972969364814\ 165352907425503687540382885253089318064717355779957473168293507291218535020708377027168652\ 413067418311577344441949435967329562262054910355378341396322448937253240999348814822457896\ 014531037480718046289094366757892650182254543941592615980379668415926171715548023607482639\ 370687100518069288131635664008037883558101091478093488402788299806472493976883051868291924\ 979306388435861438062369036878120805434341193292462049013467656406413418514148710540487354\ 655724059218594270447454994177539905244698704240313521279828267589679976973924733594337186\ 245151352750988168989382537688341146968513034619402353617034854868068058080766035928544479\ 387042804871258082625754849516478570650912360637615296722647559820469788641875758922980093\ 100945399132429705226377254593186580921039321680463334535130642163156907809324500330170698\ 548229736738083231612041204100500997231005656944460950563197218314931307970032260714684801\ 379554395098870071656953719878095144084919513596307169303988564374894808242017447127048864\ 506736421462303392137643541585690575666937206259315242903889030984059445794092374504778963\ 693705569706888963608070083146491203024568036926933230942091016112977967324116961139893386\ 069794470728303188488631822370482261744578099357965371253251443174888849992562354017273511\ 450206358571948036703839569016037259761262864977591379776690840472193762578332784420213969\ 342501507515506386267757044780460443803995850933018729135093595105669696322913305510345841\ 883841059780209369748775182892353186781919162135570014462369628725758791573365110556558065\ 486141770476925849750622082202604470064463338129344071579594457229798808966188245960155448\ 797807944564591453917027406478274603579713298497228014117780396546751997442705435177545749\ 559988840528324408011800912005141872404454814823947256438867392809120222334520701208990017\ 853799476891588826364430163873000261966377565564281518636413286945465579861243554107211271\ 185331741472112866571438815383614287298772243783024008770585877355682068733829054050441699\ 897942896832302866536941368694692725933456703931509622835836625159858893594846675127853282\ 312822620084894640864926346514014944538320601024067453159402549508817785000654273030233828\ 034388217372447264793719587400610102949133193277603430700702721451104029203497622459136392\ 378040875950261021829661806046844799164281114875708485341419727782543001475767222948579633\ 447019980601050898911783314426519762372258749263797675708636231633187185916822305388714175\ 869028208683191853956038490300297643474951078403612436448162934506630773646192208558626470\ 189000031676251995352273771184863626214123265348897069671617772352505721604740366688968074\ 586850037739620773179899022470521950777672504536417889900885578408687429943159947714647898\ 161569604313798593533320609958360379406604332918054209570520636617068848937165195061771226\ 731463324875384238066802002813347529071444329383485790310554996365612963628504195686619451\ 209854799140088524866829674931031180570782889058434765637389754113935305359998100119585655\ 522403352850412891399711720264512430435466101816818239757221619536894670564274329953359035\ 180861441986123736015254851177037774658165525587625046445305100743250022693888746486181331\ 630171215736401359749529132328817346826518929279299855352163271454136683314018546173784581\ 838140105580760347307316203406899368034435739226007501370284423939403578026363914976946446\ 490626375806295030012429746632128456144344400234795443544788135517483262042868275537668942\ 556552154118981582970809863772928104992248123035994809454468695823974050472863657090880779\ 384469354373667164398099375587190361001189900973967682989208893897763944524926177892911049\ 013500041921001687329526199935744976193687659787870182299837098747842512635075149601103274\ 432855680234254243174383461859945372325486965580032996264681731747060195438590083993246816\ 521080971706328087920221144871766985947623022935429958343803456002560353588621277023583104\ 730793619033496450390490065982818685785152436239683263832181706239728145101010091602378652\ 216600202382355934295393016247154882884507602817251921161257072323599479399498909334436232\ 954474288090356676046877299823699774177584076012270087057344923590937058227694561874895058\ 200737054512702829306856001325006371368682550733213152251934549319601924536136992047055977\ 887178115057126802264598781910059031878390991690259404049947355215285832918204560433756985\ 472604229354278548668411261618106427881291267044155694366458534293680895943020484228202957\ 601719936645489853302427285392709485296086715252632367989243538904823453201659966831418948\ 468661968377856555838511756359260502241007992574347194383823403860427406788978088447545359\ 028157663550580416933019629559369179630568483688621073993971292955479103577667497696552819\ 757919206179465047605279507096266068311271108805832828565365626045777292759114082022449136\ 384369575479168778369476634435278429369040243207487428153409948742198801613979071069447101\ 997374984695934443587234832705544269167889209019859104879149198186418172637153508837038958\ 356731971915749713655379492245693605207280547209427521190364017934811699234824896619720008\ 294558322378277666797508641529196090560141811424373678666808829906670883230302657605284494\ 394323239294192373696543314883400045416967716613810699493824736624889989348156080579065383\ 097059315833358804784778888158974248758747250878468609422813758416817117369787126093267057\ 511286235890503744624451649656824911248233800305052531295053702296900670432148066168177877\ 954588785626947385793922675848343550880428877994893423691146659021570538295881147251878694\ 037175540445670723058870885532726905010101010935814697201949466126140934516099530169096024\ 330965503333157786352463642706562571036019613298613366123619478235455474035672634218891074\ 419984120158634088604946437053515250113303352986168891382069098230507838872715248017235112\ 630590134858107810132925085711726965678956750287553096998375286815965800476072667481884868\ 040712081312033462951849604318457730915106631741140388734927963286709094056066581446801091\ 702446042048517095557361910411044016301419721183747876809434958523218582356272564475223022\ 477648920802323416574798911219146705302649886135472372633821378255512211377478314317838885\ 510514656114977688644347812557044874404070687471662950385695489823028848533109249773311091\ 471952065578778221945393654245888224040009479048024634146822830765975107993678946934345941\ 757671661873049400137823546773292521835257362413448369402999364688370551934769239818362281\ 665931834941998714281004330720598539671234051590972448377845258980825615156986696530741079\ 451696475975053811331646680476941986304221770661843105947135826929153957868836611314191166\ 736736962931431752838144197580670445022723597136809085048130606720523615370904674428882645\ 378903949938208145018885495286328941788632927852952716737480127130332466317225882544265558\ 628819609011161157442723475794740379641367212882956939225343509254461181102177534907417125\ 784514416942164891102862078183485786246686768002910773198819888648431121502578101301868714\ 598831182168221851912255688096576813486452413759666859626996756489900691509751230866143916\ 607688670329058044168909763385198951857506091530267170953105075463203744201586278950540581\ 374391198691189908059513796598962180258422825606275356267207191170424665830386980758444793\ 246806141859400874875835736961291699576079828319187952849423703704544502691865748731153463\ 123606816520978363719075125721492930196064601535496226709694913950871676485538942756912472\ 425033217538772994235646834896069310503367249121455612674355347649979424335180589411388719\ 063709404281669594565708155367469200412884686497226494350558677834635929121403937541461993\ 377671250849056636233142660709913494007925915803521537271167077478648194907915849700046660\ 002591641575307544370755292021208115250367888957494482999743267417226925772692313899416169\ 160378721406425340437468688429181036853251189888217110925038272335892406822811199145347359\ 575904247324220702586950333915218363104713002217897400255384391212907139450737789432604346\ 170348412056937070450159664579429122738322502495339462263152121350187283189180228776022021\ 961654014776185247573892110646775231864191927236360147567559359919639314681728777846988756\ 774141746991655398745536136909672464964695806239849297416477269385111528187860370050529016\ 918082641763603016458020483193490238819839022084484549577519978725680854251585660704409667\ 669681918564953953338857386834182899420298014630790706407206418254715849532216192063981697\ 456971892038702769465984435287993233822461438601444224043146294166211446217669108458310624\ 548760501890027408614437332303822466509542371436612898067448834659219892650987328170004230\ 081380411004189627568619963089464268380293877054749291935205571597136774613223680845217051\ 846637105378989974410715305975724481633360308976806013631210517275338803274058190778855166\ 875623284434681678845169484750845306708916192820175281072367834190572530063082155686165120\ 699284823710777629781940013986771945409847652713617449297956055643809140763643070685418857\ 843075346991436271640226025196832688220624823945657820953000141514731328038477753847996142\ 675299512761963996451943911711231580624196069657899863692256043862864468446464866654222216\ 250004087764249021242372120005132231760343661522578808491116998475330160631194531936786349\ 481342192506378256433600732389854724864294083645597550159208448198049182986634498833112505\ 554691346353681214647984594277111198987722421243282681730687413669809031486961334227727343\ 031873765265880934310721369131569766463531585643433435956398462574843931920217491959713507\ 071404366299776386643404573012720736646629344380328594807383694750360278181523207316102806\ 905934689220467665377672770797585087431047712097950333274715082777301063305126376006236292\ 298080207575550258502417500346913760074561523894109506464366100785102738905124757361144604\ 366493131341549576148225928830809545985658630300547378899234479495166159445471884511408242\ 885849192829919244611111665854603164437803790439111062026148576147537888500252953161548501\ 426929897657258805133407182106466206633787326770837850533991470263758766898491546879819736\ 371675772104003125031978669489257567693116143477010090011807533129905872767827483399913193\ 151336896748502911926507321942760509632817543394610188998655916074270536393182115298968565\ 694561500312353843039843029450648747339826975499283498056594297970288905851780988755385378\ 608373597092250845468799801443778977819087749963022228250962446893439185646825931194640509\ 234084625318912712663505391492198998880687289733777330851500394519251124099214720569317744\ 985288949358143387982604737463502352528363746596589669061790985135854923810870056889699208\ 828819745955536370938258887372089795584227708649649146170471940172155272432762807407622631\ 412745869741124644387618674258317620095555668605960098693545642987455789959933497524283336\ 544140987706004614908969751942404929658980006133144547689538110452523310913688488995468633\ 875661152700247214819917987572178583589079623301285595653227876776390686282314697911475522\ 281848706363429589683526281914042435214439858916401295428523313433034658808757606605705198\ 140668104858946458771807877475253577008283619277310348718033609457837251008930839671984317\ 318600088382993831182185003403885556475350208169416052127617565031878587783937835888274357\ 120634973550799452542513369483426369263579182035692294694452903684231122838054414528941760\ 836865669826956611210862951753316097129089437983778159493520852535398725920307475041948647\ 255776711278305306423890041533108724524795859655781013836520500038824965508155978709250331\ 591102826864368591497380038852607797935718814170032965940929399592189092138225732259886888\ 792014631034223897416190233030308139001599246121667539350368485966643151818921633393114331\ 388038389168741936587332026782044022802961362226681652815966384204550521205605534551749577\ 536713984074715008299194389337392662915202312468148144453606170679927533023196168939493023\ 978442401323996103866295615266854506622056096909081790681648768935996552497264340520114788\ 932090315678832817112115513154156598307462471177196283372907193721133912290862442698171471\ 055906285082367309944151354930875917301785713916135261496323368948715150974403837414485025\ 393998789945680329208916107781362021182539376636401137553062400554950777488080127012446741\ 657278249692057266242571525161119481899863719842132437471089473146800528476332131800031839\ 374109557943914231913541017179537727454424011312033542444149841561045277135186073700584103\ 588581808435194584111005645569646583646691261687645683790909947275907080696920173435152106\ 648508986579505035116477981901980821358960059077235720096838299778566325399018443235816418\ 801455086097636428200396215366707681989026104218260466993861601472408532364519201665188610\ 984078054468812048952344292799200770877655950395158254889390000648215608005824675071074047\ 179885280912592576175194581942973456146454816288460115535915725312933987829721595811374025\ 812847878043905941541710692657416901770240158576311321892781832432738015770396968587989396\ 268247746628982591931313513343797185924498714415886068488574337855978351115393306176914660\ 658308840089787148860992516550027215647295871082017393571392560259652369091372032173889184\ 519677057879911446736733653871457861292867195942093086627917962103780337271496619529670561\ 539586849915441872635242157743834486553996342130765240792794999657049731030274965643619222\ 096666965870372259279057695251787549875803411110043506731676793644618068119318642992590984\ 771732097498341893600748617317875271879865780472442954636221305097620832587867690710700006\ 853624244902311181036218212238813542010003107107459741368377373480385043798340879179794183\ 375033488663685235630284822796799217635915777502435421994739087842306358774217842374455932\ 643173261277311504467185535125244525295495293924098272833287674201593433131526589616497043\ 569088484624974448377542775264292058094374093249190015618180903756254773588810363012935122\ 595352885593149871592885431625137058060880742576693320618516370264652643813700048502946808\ 298491952593025067968273934934598892220074632041340915793342150690693121521805641654913963\ 025208963188202629489494356080758705001846047587530246058502586562055982195306444458351206\ 227738940364942942716539221388360926293623938158026562676930522477458575540778366088478371\ 910367409095594256518014809709948935747603429294215341327910239124826738694653144604642310\ 337600385130994088265831567079878641177761369470140975883299592012190125345247712990193208\ 533874773921022390735450090946703165969474043241351899789642150674908506100450527311577880\ 254900276841954834738728359742664235556358541211273687249725404535342772260626488571994659\ 131378462539850401315972765028829748033438854142554099806440245872629075158910836528438821\ 928880002927845221236188695967824714455348043044785373511432480780886919614511940826001618\ 325035927556325527663516522625504132698272472572784015404240955904796157672689557037871114\ 407859017805710450085137609006306849504507882567072169475381760062501799664360399094367705\ 724511858041829293753487755618132475776343504983182197499322730221902985640633848031325117\ 538674153301581326479467078044437451582207140263967548473549720964972458385246523620361544\ 309987437774095274741637280756853992430444810359594017615325311788876733480114048164770793\ 518257985850765333084769965327133569456015996254315691275301160496921223248648816343067167\ 175895288234208350769479463264107878711966554992613029017064283635108494221198502355551981\ 112780794324937942304527197199793711142904139650448516810408932016244952836087704912480012\ 442867474225162838684668807775079605189510910841442473152834557239514647855844991139484864\ 776911369403368526857584392930942017200941038389923929853367783820844778966904460854419674\ 614184200773322604909584673546194692347080868933883955742766625112226004861517059107348981\ 585434545841373102893041079422961004553474946292926432936318189041214261538654950273963438\ 478327222290187571527129021448429871199186966881109071485258902006011908354896107109627317\ 434684304467033823798296462769332481448831677239537780796326867888537305159456069094800644\ 676428628320613877181303959680450017545053557622308573264353257389059078953462561966200817\ 221014058447925704929866466426854953565673373230151196226675173011304150086307105238570852\ 337734337152130196046394979549466083110623012111982378166542122123057078454618800100645323\ 432948159837265272345183782832538270722402781427471269498847624121895125060444194165711134\ 691057918780413748581820614287871328578900381435443742949170209116776952964470303558855228\ 855978809317783478215274429685586835197381547840418766581409892381246346190919286451655905\ 153372068469716948973629584705312669685335375266952151410470673742485244507782583078835769\ 648726095928785481304673855959090854155377401360972817779138436388467183574918776485117997\ 535575509958361923246831403412013060992487820459459212690143206386874451312256736233787026\ 903621256865280425543542462926544952592197187403446082478506243538014010399206751974445899\ 659228342389825130732789591974039821501991692685835820327897298977949168581195164381147049\ 069225574463878399990995513671163397527441571538087041691242815238754438765483336091990137\ 547005375831875538743060568726230745501904371281246868133851790174617467859689651620692444\ 818595522413392437020641873028565002209338059673292852068302760471436051682548926193106495\ 156551922836799374513717217496798763484906720156196977239157731781244377905170842639422547\ 369943700986503421728327309802068884186611704324685212374838179784173714522002449706217511\ 219361989829657188939157964497432649545536469841318107730549540541640800568786071609127566\ 896162952104498721953356073921192754197487228855568054712008009679280042370303092669708164\ 179422421670003792118548182701317443083326834776600587370982068550650886041994723812851115\ 228984024518297357147740841977262616628639080969560444948874223776733733934931186947809189\ 673126688802016297238325517208884464793635001124460404187469821866392764718984192151795816\ 576497943567033008702700304906235282641899605835543494632874535780165344544721944168256928\ 474737028667616188774561337879296140575311306503048139768171218780750729055048197844464812\ 671920795581583502942282289755114454413668735859384168431738887011559879809920689663743047\ 292109766394805819606957536218180260990097458991639635529295906977113648489690982424441790\ 973166992682783944366917562933458876397849726735743129721682576048034124533285626693512809\ 349927972792511030682549654490738165325302818261115210942246423784796443488796123535813362\ 252398598004734141138449482911502872371122707056657537758738997799645706217734327671712754\ 904055387082026777862538687723936187353594247560445797517700479681319282010634330742062644\ 352557416168177455256185083555825858152879953637934210888363450470123645722649743583450753\ 127881431060979918127127665935161867099277449980073425825812804677490579093384492235949288\ 705923957253176445693973454170744568302023961651630949481678806634887363462989233072139279\ 454677823528869616017627004713284101834175199706596423120706548319217841878968864834900954\ 276011122919458028173660958160470986072363613795227554678728699663834451728276645064094868\ 459064637019291486216475976811892490445990529035298693114972940929890413678875463484757887\ 567672190156647717120325440427318085423236870999553401635505694123235304720577656349397231\ 624418350175751581758352552210783136679757943104520768400285169971535360337220529011543236\ 066434131116755377012500764311193265203918242511006381331297107624482681775606595305124841\ 929381168620707247898515888081379578290306024764743486878381322956337426338738373818002638\ 227847779167773690517644606216195392048737387184762731778339831090033301996359690039626774\ 310865001363175278601419569354293765690566087837812321971226019526966919891768624510372983\ 943368645907673289196362691584732763058239544140515322483169172597041993728632875681730849\ 601852742173355728458841831917177087176539717846849696221838550829661683754472038245627289\ 430920289653197610923814271103759751062727570343417240348580581361013836185109865876023851\ 499633554056158196016323535435081648631277990687589580472540044753003235787201219354237447\ 725269124652036304184312136093631795857012284421021118478145688415121910456122904892134219\ 431338687273442314434964911412800419589360259188598480112623788048547503419868351480336000\ 901703205733923695367617228065257078622694801663468924606705752410362912423613133413725572\ 192746998283367527375326959204606949070135376818430811181721436901045012314037199995526652\ 759142917842265915782198150309401048830583482138252649108734359957595256781348272385493493\ 430730969433454893163669698408543599403713839583795631981156854606221962515334985798414321\ 558570860050324745351557308080612160152690567520945298742678167806480840083420705893132001\ 529057886289004982084528992823457869327195417416051839159094878303892277015135112370242346\ 419456007979733252073311084428665730637618353389227646465987854667551628451022119576965717\ 628209793854603480239318257660603267324329298125764992110757386489775097312795662594415396\ 786166980560811602662650723701902209225914106229281534770884504333033048103406600655775670\ 144392741430397594274634267022242233930539603000204896054938105818427330145213493282905795\ 139141424550534606025115251671858188782655498937127022308066390175520348455488232883023187\ 537531396347759581940961635984319812222345216829774514065920376430652484907637175314744094\ 040467803910155587855777604472591597910778605779893376344861505509967170808228237775635609\ 963644877056145463631400319795768370775805581142200002202645765132292006491886263613250423\ 861720963987367813961891354543559033448947044511069238506506242741615606021917939191686286\ 887184012617264661768513027778640053296358860530175854998098607560846359436968801731562369\ 288042212257115224279290423367782672368620504504619950259705114851657923249519282136438495\ 111380071116544601688224613544533285994952023841740954859994663136897615609303434690826698\ 449418481160845621879583958984759437313612939267743015304727632480424198007729147591326441\ 273418398806310590171020711953247333268915849872183522520996661097541282516334411147320022\ 336243627555473684309809879048482946448391155384968440716937847979534248472293739803421702\ 625633836332401767135183725753538573358645289160322991927433217210552459351224536410997903\ 945311316279631850846085975124795033512688990390531628963060836412769216312032806529641592\ 616440068239019129545153112316237594054863320222703130339215808643477350750059368958799609\ 553700408649621925018439426059213122233019878045715315168622114024542106985951486810052188\ 041506421559506246088964266831514361927396866631129519406065262614299108486353915336663913\ 748546743468553913149733001693744560204344106787755744116370027581324758025263897186570824\ 702626866841796128308021889558860882615750277805285467130116277241584813580623886339866777\ 714815214646939589511749615548243759225103181654905423851971059722360506603295604107818564\ 984757677612333882077235567194037755572915845777447803120440548151174468527666151135800143\ 590573083774315343488094622121001681248775976137290150625250052982452002838040231374146548\ 364675224011234101534836142437079669005384518241805184963429245659677933035533235875839916\ 332264978348312226762990121001018931695613008685637555457583893736503840766894438264294005\ 921722298861661927507790580083386738641365250680099066901131685490022148479148913920034266\ 604661049873829401818200273965657000825368956894159634016498331327063990911362209203796939\ 594877244359345214231956960280272722811729708607624039145105092602046740323364683675495946\ 270802651274368638050443040673238405154490734140541979532108799172532233240035552187810931\ 062979968311785570606174219290457188900971404518437725131044267042295966546602123578291081\ 853323572722560498937798502690187686645640377399046847826072641987196041093266856735701560\ 019969335802694901903296125082058823814024093945817959998720651411787297429465727990449232\ 941698927020569820054032106549163219329051423226910691062784472466181179743253680071980354\ 678007191016556089142009187353794547583509100323102429329732711194603545338939363457012597\ 053928981895141183823847591784045719245228182986250999564003405454580140636755015738880185\ 876765284379154166460878696547136819277545382157518855576442628949329206656637490678993956\ 482835736796627024040677516606943498338188118411610459046420549875321352310477599331008774\ 143428717464438134906737324819278561874579090847939259350048338140884906400421654693203462\ 104445261645043919658894976155358625753679238831372988480865518305377219517087280057610675\ 447414427755897652403932151231649748846593696044695749803700006595254056851658217334421354\ 930834571606315670809739429852181519809969230490219011877011200461512336564223002946760099\ 107259521770268843068175886859559464954372794985613744654197154007589202283353354900032540\ 952380652191063368802131912244010981829751756497808242418833487962233046174282598494833621\ 550171790387485343492426525174279627119311271788207187153915125066292176829361364553144009\ 256284178029939688690356183885268036616094932517824244675406521441645595629139752661937163\ 690275355537304388512088996932551823747651639557731457446488763872974040348445709646620279\ 167522859492881260434242084235473152054576394597256182223411996572620190264351042188696040\ 938915434494315842704522273924140954111035454544461046748062938770588301763919631654091722\ 288931745429095811307129662572042540784523912087505438419801937323657571015439936891089928\ 287313957681873931144201581724457121625465582895724475981133691154573171705465977171558844\ 269259122377229804675459189548320930490907095773184491376150942150491542694224509995502433\ 695988019712701776856815941672064361994890248374704543562215868991706395264019061812270200\ 088329733633497234663384808656470042749430872130198511102013249897872752525455504761661537\ 866893347224538184942960047641268411093151176643133870154189153427670332648540144262549626\ 966280707940703805292338798354546790264906843089122949172445490545307053414478557906063544\ 823071077897620824767016504054505142444453772410486742070858084103268313809251591002132837\ 362881270433806439594856505367333443072645467361196227014362547358802791906199868135658114\ 016039881260628495758407649214636883076122375843290581044811173890473331231835630081584475\ 231117146032301909227436308997486423339042481383789393931305334876011978460529431024617553\ 483014707682648154903848409606732988050936204221089344699205078736594091501541975366727144\ 819492667808484312341076696630500099843237246267595079129483649332886940354552269826073494\ 553313616838917178453425339467323788481403416395907541032636974599093642713907909197786654\ 738957531362447963921281359241603926953623853730268454502832443516547185890971276490499199\ 254566869545973398731733506690953190097793709692392016155643548142420219206735755505122776\ 163859312701055529510438479551804887751201222925413686657293083775673920465361391535529833\ 051638753633501448390324133613170651763669464533235980463048154192315165123765419147456572\ 690557259735077575087451141467336000919469490795149014313562531730645490792926863644108374\ 037008686795492894534336118933103923084116740617690173012927217082742181153660331557461569\ 952924507806176883439421736941950897960520463270839967082768529656264771346139889691653889\ 200718000671354515652853129638170956993387256479262237598702965711009124650176224184606494\ 182355605626319686535299758673791184305773080200523137212718195823260282635183316289426686\ 295360604408201005097761624179072712836354082317540246761045527528841250924723135594376783\ 503008801575197572600792830633010755050395155013263617087143549806371159334623747287660633\ 815496780646357244731085906891453435654608989642420840604354289302962174534357053026263718\ 958724855388159438708989816981645338610864316153157007602699176084991633677791954552990355\ 186394053973368510603774057684513080155500801166237853245540780854744902648328948053896616\ 372245103459709984908824461713642510641066551627057583696456733815213988415531141122745367\ 271501497680837567840792530422459829799721566728286179263340420592167515324153591612920852\ 349882741656168231853893535951237765554543073391066253667251254364533091695627799245351419\ 117204989278964963149202476535673627171276351392130537602505636488792705380145040276041992\ 241836464723876636315910716869502735837205266022487458105817310189739920325277224126992535\ 042354962778551655478046919280540020604422336227885525746945919286681066417396976926151039\ 929176271599052058805730542152058722478436018427989069476244645261657324796182617410802386\ 284952997750613892095942187245815835093485678977584230209252632519575496700830174823534907\ 471144879985117303818636396353541020549616037836658748919816552603995341254954097518758781\ 668398585253485579592709983462793439426738885707416693175567721212953692791566542436634237\ 018615395864454201401351355643293791830877829282256996868635233954935268543114204006558827\ 725224669670305126537933327190238338521740664146186575934452409647796014963889208342646313\ 877060544538021443481193566310078173930110461476024351244312189465807713927489624490760901\ 720571126590025842913625694567924779710172311320839579864719499256446689906457647513892936\ 378579022073209576668093645017600120080404356439991497485764978695441950005303130443876317\ 815412734160795160410611831737953260549500264220502235907630852386009070820241396677497564\ 494445056865979083551242676452371646756328885874092211872139839453070502005889191650468822\ 970048307448066481411517274027477374649049662726299197853534692428471811517972022273286246\ 157101329073110139780175342330573455135950927075981538354601990293892315277592462115182369\ 799350794201956342670611389625187567280288771446266226001347748593073240979400822044576429\ 095434167006414638068707399384366649794268909125997230588081247815324753013673752129921948\ 696097698485315202893683201186912565299960659863089812350949838717100225802638223180163497\ 843688629629791295285668594153086900196257037778640593792435249392067912221303078469883881\ 055423622047047015456155042629238804054454446097557665708337335723065317445595843816808154\ 340338281415398904065071484114065308061976012585427361138243081012257687446931165614731240\ 596387033203035358606359524165908721957850025726413450499250428992098987716147003998837683\ 515854968056682938431142314592775736587677446400402538140527084060211412095799292750645891\ 605782530015994333026647548854438044704500479967594438784640998121633992018419811876502852\ 992899359330181934285656433729293886872166265010529520435646900002793295081504371887002141\ 837346936684962469159472048441210515385515646124864918035259717806754274938708369612967686\ 054981841548249247763773106230331766923461670615280454550952424727673535499711666138715021\ 593024764323136046861735953790077368681172079495603400962946602788944236581849546408920971\ 512877495944602577730415946234693707977439017676801172325896389362697043537435288106396920\ 572146132687475025616200866026529980685610316041927692458692085512223931839257958750800569\ 122594572606745592499633656545819002929969608515265616419117341725560501390196925968636095\ 404529600234088540435299241266642443905424966053306099754705482870221275887522093540230663\ 749878858631259674567595543574524956561923719949185538303626832333802762850908716106922554\ 793899351405907957481839918413657870050584823224181977440865159073961571827760651295259743\ 443745796832455120191067796459463220103932280285362696400304723771161094014932727408136679\ 247761580246491380140322524634706908257605744291328950635949981067847690977636217869114836\ 248720143960911559912618965928459957312505865237723188022958342289145177214862535925771300\ 246483490673338431349619600644314469440141640298457082249728909169584061902096168609595094\ 254011441677240327874780649799110031541749619473684011978042356361939965919930775189867909\ 703416297642062684354312945594219776262446363710196427820501644193211708107677906724593254\ 122048362707403369284821683248695806150224019176940834013763112815554812983878765072517143\ 909200178924465014690996188683316743993613142179515235233477734033992948202528424319632316\ 957186149838443099741784262507681606931291920180173939665997622716354338043548758323605802\ 988390112039438450361130833261140246809860377813984832808736509178488930330109850654571838\ 735709687975488180985531948814853308593947934163674873194107737831586337877518540771817952\ 486897756729595483554571546942876642788075747260175205393934538820504647855797412133933341\ 150295619368981893115606114359053745322996558791598093588333895337587779193876902125222477\ 202345428769206146299152055362981704974312820550685242148820252525934307247080833216366655\ 895489695533087162381049016626028441882188219710232122865394117834956481945242377982802880\ 074269519649891080341920057003675189317636762764876777297816540169431445626440807872037123\ 281145820198572770543301049516149674324582867841728445003487631455388135883847321974018063\ 631976140544018227787923428462405847675064760202476719743078655164014934086658773964779033\ 697155650566184025526288537427402954350382056445874360598498157839797050489076592975994831\ 658696457599770601600296197163989553275028229830051698506375760026996439494242468084774773\ 224519038968069123022081375791035229962979372983481997448043081645030047664987569102028117\ 067216995233803829353235622454774935703127953543224190849710558172030512721394142598017441\ 014610377125193698515308206500393258371594530596446535713368435662719221608484622823246168\ 119836405719535774611018255193583588846308891712568633375970372746760375384237785148881791\ 182724170203785042329752688631752874087637726061252694409262382378579189310372667969532958\ 964044292842859108203447055982016524451492987616755547613268909495098098506830022313528414\ 571851000427608220231143252243211583079237162649684633227812336390353606591640111568679470\ 672660004729670081587629542485324240181608629450414072312887841873475057989590885253690615\ 996914088343452327047361222076641056705867470952135951638988173227016852206980245245306658\ 163253703180975583471640598334867963477100770505425504653516733266353026860249803818195794\ 657716705156987413289510536732425103524885665182808811859183936431991017558780747690022776\ 261822707669642168020221614707238997578125172949826987620441221152261708537467610534123645\ 635815578797527355948927474964688403683835831752634381791769442981886984745218859081381288\ 391609456757302887661957155929273201639154225627769439719319574969385354252338691623466064\ 787158116586062221053015060723335304285554336587044122090140903819131165215427897789659931\ 298063774232485100349560470892897750567944061248022804595157350563226659673149085895763148\ 970800675838442497742282108977018109948522213101152392754479050126003575218399879379451583\ 044489083937213808305783056105236440267674386240599981503769189506156642131580737729245325\ 096367675504212875551510311767823903141704112228849998550512368026496254594097866169240373\ 401517716767439427490783547656590279364189081870872939895298786938642330886798639139939449\ 945086958900072263969446932159762484155594474898101717563125144158231563076003831363574714\ 284906924830587275427617664643319936281691243745914586278390820657349528157510885468798375\ 432338623333783997168478488378709845191316720124333770929549210774451492979803203634314737\ 612080709982283760357885706850525557986411946720525087953958189919739803042199611548747743\ 915672898259084949395009366409137962034517286105208780318203157748920518316226396495117264\ 731878351375242973266470841362949576624255181110119098064858541040538457518118684446355636\ 591572564429081779039193115729286287060662920043559371002676135438430820277679620285788867\ 827422226856387099125804878591616297907799860286766061202714968219822201701719585959316424\ 754575959038439529521597457335348804413247104017752238873709671805893945030045541366204809\ 982769677361578341907565406581655765794412784908554489588863685757051362057955069347653130\ 150864629768007836570723210405434589077135672646985706346743224102419989028412874878217910\ 276420173622147510278704867927789434702329973050191688768025563163569591447809339680711218\ 243757885897707651953178343222290476436334398907540791930320968840854104822720135878756290\ 574389793648411830656258399610141312910547269502412000176449059129309508973817558234255812\ 284733420209287151951570481435230982499548056078418160753430420382726736861015239567473486\ 101632902167318485859899152466893723075533299756665194331566625184707687028909429868565900\ 140075388054386207475274509423156596008794113354204133093439493756352419923293093236593518\ 562077970100508894837686691376282859842459707737504139455290629463424446460724934304697959\ 443622787280741941237511165281255875551103155151127323827712113301441834748068272871176536\ 264007762834382874419620554315549222707598407474944518958834023566243698928325185938114109\ 557627796397995318586161960418020224300093292281418149545729150868125563120346246770960489\ 181388454236083609759161781935322553667083756994769960923969310963645109898578805472267469\ 612508878058668479396217516570681286183509625609377372251189354414155073850227186955262400\ 929858309783855971869950349465225025620498878111473413076733707397669961413838680897321319\ 796195499838277017449882052919082582942126595788413743906807790686294746569217096127434528\ 584366521921196189420655599364654780997361441278100291765306456592591663247164322744752251\ 480931742736770802142639913783345572115540034002736282000265761578801912050716263470497014\ 779559382884146701216425718664709423048678359430216391478266610225861348535450075122525236\ 339338757253961746035191783499038393602823196829440097858539570417248033092617870422806576\ 652665474164241121467514923924497431521057600997721715241301873599953786540716328851570502\ 710321959743430685390099290964415998316750953312739477374790778640088806265330100493152072\ 056684627636724932000819025465373034474891532298994409459294130307055392216968674868748097\ 211075052689048737991434951206957562505575255815888467109668046208500728918054366256426871\ 221041885290115265236059467977471821182949631885153012900735929751816769328631381375750435\ 084377047370334663233017787334994101653126058507910051686295172359750369716921874730943108\ 132709436564055819085426413757109448659277063966618939388376430054436088771215386821737435\ 690075996433493076520532843209381857025141163218630864462190575432078634701126281475333775\ 594535766667142419245776155495376080892483998920511740222274436157510001431508351574495434\ 252638148497313579156323830882433816466501075318837389976290650949616656281319578551667489\ 863215026461516419550139247062830343415237360973501193052176711511636559510724430029199933\ 046902513946121033371279438993261212425598752569958393568397370640494934878975026343845120\ 074720603377163574441383509531119895700058635064877365133659788103346683628685977825437171\ 033575327937780707952581400804353087792048587856797533864521124320153058689359106056496447\ 818971216166477388428075703342203165544232342781137411051278976709383110278414771561194912\ 547980151346029821562686372903247337065503594784404403563297075337066649758036302993001961\ 776808486896248721983772414195460599522938721321202670979051754324296627200216955201376750\ 901882035377304768576572315002378410112777435739414908751182176817126105249017064455253910\ 578775174810611134041295044277453954218837746661448229396423010403063476625622571878167052\ 934187658981493710609327599418138565982278997476799605615957208593413403652140162550969580\ 931169553781714721050298972346886295014695337263366315983584752599009946391412218443091716\ 384539758941330274720631407488635448614642208516758849476426404171837626856127140831690760\ 974446495723750144848279607866035454759959119533612534020245045683264986701418980504102235\ 073408030654201416702312141173891906404391820316176659217003518769009698890738963598977852\ 245550944817667825877321771179609531911125738522507986285069868257683055070856203489232010\ 704725907756768696535505752752908562720698684472079702796694011508261302362993160114469180\ 122314261340759549772056151997044176294208530591810426092752431119568036411535437266282637\ 956350253846382760939159401924308292865783353786747820732519920810145743091025771152566283\ 470522471605254121546945279649034101417930151117007676995584056155959315468657098188998468\ 207877603573787994553387555642714402561286075554445656538511146197976416381929666513821398\ 518318401275120426479748459892198242565925319335579480097959627371754706210580405405113964\ 674463459396861778570471624686094463714169423138143076369764627471660258936037865753033878\ 601584576466022738787031294944014521268262798938372254988616151069236477634065413732165238\ 024880132173536172525985108259192059220778069655864353484900866797668999862661213513805305\ 337430201544417732188439595381268175505370534467946080386395821809204726442846303888406679\ 321372790541692260024915492027621776917453003626622962664318946775148218801295500139401213\ 216768734694958406657539787878226281994486865335672954393110267058953852229451178968850643\ 862429897575048330461296160496193219531840103596627960909061868285464212342257692864906360\ 684003615788989339014108130024349668885209674034987869741095348446672126857963876141591360\ 207803401267721535147457848155266176654871841382207019503031736823968127486667893985715123\ 822346937323265204851059241913133879189706765813942750589900250651586131889521928639827224\ 846667772533759694855491804982391369338372181466326782377700705222480789950962824000285887\ 070560091561314400900191687959896022953480437404137828658111670642467319254539555887497414\ 939307678214606678217482594554644877911215789277691555685639537428080275814919310660746165\ 511412114536471392562811405350002828544168199096282349848891098274510735730090641896918551\ 647577653379705584775501687672865438754449430118697815680026748350203434493137217281911123\ 450083459344805346954888233694792105991211267468780708141801833042504583679361454664262801\ 052041179494374193769420583596339573294816578067466225137432867423343340226063529502428710\ 090615186211739905511110973633464696930254757364012695266279578910376167059870673734414764\ 965189212146477137836543539798017431898429140366595021606831926756121882689910336365428719\ 336995704697842514027149309799394645336175255914137142866896551340489270507741574316787485\ 350406000302121776749740815144381872530218709554181522666824299398745939315092476782034729\ 224125655259979828258619137102500737350226716868487624404875450270678934185208213954029910\ 256717008664423237084722620831478690724794968006987972042243124060793666154670102393007588\ 722817667453938758993471399917713563038087104584259408977297524853068814654668663221489653\ 324799143015782764801283364111467333609343205819910321060869126848481468693824953323656502\ 287377407320602752817457438300454606834872039336452272937291703656876301636799792144795921\ 287579076908967071773091306954347037457060983901588683068310598609347484063876063599214730\ 082468082993286173302819572379791038181876528159206292399218825227294679814521719688408415\ 982048470618444067695186350609366166511395020564024666716772301532751353973133335176795762\ 848642869590898139878990872653392312848453682184044967410026468842533419910672298525940088\ 927689845006448005716731304691942204842288999211816810001035606074210117554605075818589863\ 804866033137067903223903899395622153044872411014105037600535841901519399973514484140147236\ 742757367957527172861116530498984609099580875321813608012228508884586401788769261752590851\ 876107396620551654047502251556921641393254209879620901404908411438303454063408936849490837\ 827389058247868231689278126116389709561394168763653130459998244029265513846391142320822340\ 240515759154767563192890841946249055660238548863335872914044073633359768947964211172467828\ 544413369047784486950133938560010847840970361096212835939307713249438184810378054832779091\ 713762568397102170748862361041623462911627703317076656658774605486114986048129463657557017\ 423656715503687074608490249070232059085433818070382697712080485545443846258076330944860377\ 519826444848273057457042667312745749471459929041488728279192760243702715456727591002121535\ 758129866696579648531353932731740226805883349623974248963632366625869625185299304980037103\ 522771207736943557911533448360932679354187401475824193400706612836863727391099296678099212\ 116235636077491140565006517659764966861525707276536807801267466258272006108282500583492291\ 988585739146971745504232860322592655623097947542137534386738428328557042840102938248094955\ 621209220737621159134597469538672389336422285360148338085371333565801200939287459194618519\ 136458425989261833351269750747719074036701791363215953951603337225545648456688974106679903\ 532048983531683722876349984594103276287177285762392564350218095967853763610296524891707952\ 145621130500166596348198804913082662303306103475669779582715904782847849700821449954492765\ 255888886173223136365274703996619283840478773622951507959945000040782961557921148115050540\ 808796003704733015687000336178714155545412436967601064739956920179311963361412610542649875\ 587370160838911498122315006441705556435842560651233203548955475527730399568845087977461583\ 738427973175844537942742165776052597487452293319536582038851443883694624289743807897103264\ 998974766133739756466489651498406590421355675325832852287089389668405001632530125768282630\ 214503738487735685504207002913896337663291206114754848970039227101072766322130115860161409\ 404148115399730576852702218512087421163525490481070550521764620679120349264320362544886313\ 812991222738465125783578808319939792532649140554284926781616127170317202365587685374186950\ 953817981429551067188559808379663317528989704059896259420831054229908328875427834511542964\ 116954222103339996002243038491158549604538160728944790674649239512780363003904016748143244\ 616917227459312486171996943692178556365364860074190255243764659929959979319130566295176092\ 045229857037403622028507475643854894126789328056977069390951321204615958519847450048064693\ 250993529326966967778976915020632089050073897856446524494952643062257790230205646352160175\ 684430492082168202972710120408485227575159773843359698561247142734153568013856216843450885\ 185600423422734385269153061712490727981108786557998245545830514480177970232278642772487295\ 649667097809192256663486018809921863243087885066327839947654003202463914521645203448071058\ 569567307868703764131932187378943647677843407999819050446162922601372979567161712422765806\ 989605610268936643345584545047778610459640458230563767923288391804906259485435586293764434\ 688254566434830527404910651054390355274247817279071605552535653282604692695075998341952172\ 805554932722879599935606204042406690251710273353434278200528562345390716939272311822102299\ 322811370146413149652942169243694400972064387623435801842895919326095705682218534771388681\ 743752404736790682775656627809828199647360395926664231785407487820652922800878640096232939\ 771903821293890400275267435357680424697989691912330078317417518730166758724006945527103778\ 717504280046434735560607284359049836034996462100883496173295587148651464236416573390265852\ 473237718005242548022477038781094543352125972915921230816793842309269505972762836582634998\ 052278840391814047946164887287117919162953539394896729257301767331603692703598708725047413\ 146777143062123142657669067728890688456454651207827664760988027658074210242506622929886694\ 805280715029830078882156899554442029104929138663960872347437543190881473046715170357903873\ 786615339602644769795162605338940286007243218119662129094440775702960343676753283188232820\ 227562092728438357712783940537322752183820781948863894430708672194643200830992525091583757\ 470992571319254242155442969985450264554720548864567392914106967041267872323770716931639236\ 851365023461637099021475643511108809305394279809106764577261129618348178312871817873457696\ 903932308538983751250138131643555411882546740029216330355811500328590313090339271455886189\ 041461311308907571692992685796026421068218550883670782874500629528100739682834279597862479\ 632949750315797498315195665997435390290992172317021443892576341101415507024938129577021006\ 002084988498959481032968901507484330926846643860254770297572346789307840072780215018295912\ 661565464442213291350760914731973315005761247139876304935036483485930752535046707111180191\ 447665647799844773992623815527270535108419079816332545804252246970646098481698410835569382\ 329162124607255050941926595945073368165166748133360942282948902111130240881669718119698340\ 389864296739047289307781322747066674687382954847528281234439632858276133601447595262048165\ 647155115944498270100775232362769828174474106706427862584873173006938364593930859305148123\ 718896460504836061373805833065676434425686648302373454455141753341106772530847320033137845\ 688082436397696227390905915594486389469586520339477521057283522556441658293947339639040840\ 279257012142671054779886748717085347974861901903949949656759902631926113926023270177903507\ 322441895704141427280933738550622287607640417475737070004954689291843442516143467093815255\ 148189418827500851105258255003786494682745553344531796599064923058206681437075137140650020\ 102180857115740386708489919815869552754711436785584562270092627542941241590966644943215183\ 704344784580682549588588563168234656360378427537465040068200833271175707764511855857590516\ 151502474098775058197278488525535690306513210742088600665578649912559975663600928054911180\ 458660513070251790014056228473885169662766419463049086020167821717969830013205635834883709\ 585179647462160780187826676098496566674983671711612877000031189575196723464709460576808692\ 168235038738155078455674318559124791162499057433930694864352281091202469815620738756101726\ 488238983591827559119791366438750500816674895809693439707483619503967005140255549282158186\ 456794693145797194364207551614902896992348702373287385764742570161672306750218953688851313\ 693576536616452011239908585566881340801134723847977541205555391298336832366130730706025121\ 316107242646317378049501515611091043349661266453963517697316853570679891933624240633981119\ 880054668938742460701075941212281762647751522812941447144803452482149675872525768019408690\ 189459481554922869904341764728912295221481408577766248272211487879922741115819146615903641\ 134183532801522434254361692615347325300891908763647079645278114872701977828319027820484443\ 937102763070085900687805851931979911206709044000463575439290567267513800731487543088131049\ 751555380213233501144328537921883066157262567533370921634836322100786510087374724447212602\ 873182049111066677625955682700296629518398695796682401620908164534522830880637263675317173\ 144858038530042947529182166630209861240336341589485292739067546690393931167953112979578862\ 714762026263978649706982813957202972902117899499801765930727769471522774016430121154375106\ 028098886036142777943768358836002168924741217552260879626918886079672257908204061722414576\ 399617111928281791929601075911807455719637548060626412890196528147326165790075739483171421\ 083697398645878209141457435338543092508698734098460748250189922323825606189751448026091119\ 086801944154103752737079535959369477746955835895855987679510682319303030817327947708551786\ 053272321279908473878179346244053762687480105722671323061810393391452184996726720527608821\ 254323356936664107605125559895336126758346185234928060588714218199542320467560447181090394\ 801398713975949329158765805685419917579698884606144627840494650517891710500749382662040785\ 169267779127467673612029084700500994533561834987763554296598698414235943839589643734252347\ 865068055821365994977421487928678081053117703164932045312444852211842680624535042994639611\ 844740501250677675921992526530593593752327451082554645326202898794834192818304127980736697\ 227122680169241257054224516188838701977087693221660348210296564602005866575062394765179828\ 895030548446977179596960133185177042282709540680803624105378860282223588844388051285677768\ 548522236442113117971623733303424691277377728748050493689323872332952923127572428319017291\ 140338557107264275543823211288406521844164857882666817173378547292987257630574334581422167\ 579005601110370909214893549093414249743913933731163106662869547146176505560555232630658185\ 157055365810675397697036376085186500546424924713792878571110401322040946076780234673615778\ 193687644538010738449744111821602849794307834442828479782205711258770041632361537578601559\ 409858927825982798407674817410913340780001014801687357060555748428044126714245542153328999\ 301314490269077805553276067458421860352888968428197319403053667402887189743588547775102641\ 928008626119297524678270483695602277963225677257210139184089139800240649183885555027962534\ 111983487253968640223935240570218802951660487842190416054536004369198129626924190839743520\ 585608819283383118100573236637836412028992078264980098347398702322729071163941860710482200\ 492593775496580654367378071996208918967654767722804124889301005265265682004577296163019137\ 980005081954372498106947841182579858416662358876444115286256515364841086564811464287223693\ 089167106406555017807896126475027003162149652557157345418072003807414517715795334434731737\ 411355535702190750454118957461693161841575545292944363551191848284359882461706924534834583\ 572809620878985592467349248877515761967342496272828654505877371037282767315567762439334209\ 787835109610077261304863315193271310109209520514768032225757491789249630664028466675125157\ 203629058305024283393138243165594141501549953296397229467836494972090060300834360365802152\ 120955002512477338930401502577353458493466585650585163324347638748973668075390728588155341\ 059541247395288285478112058062399542297607442979637433233675890825405565427996158382822667\ 394464997837915078169264622626824859022094780128788356919326252972216599314447930073242932\ 242069566077740789992003244575981886084628769362223437215700552742556181987566871850852880\ 920622429661729732367397778676949688455327199378597952808469849051339395661972938110951227\ 462267138143631545834930892837146242547725170945791611641427003821220983999830350508362359\ 540629169422516781939144133513560976709737303302718607063433977687406757703534901399697715\ 886672501435094089196263700895985582898215232921095795210079076176297306993227354180780908\ 991831680836177736105309180905405870747032876481405026472727109196282398772294072691838400\ 895619827341757709127069876931451559592785704623567297424264678673173211151523993138903363\ 888830371479039053494489314454711913854461790072507539627873859493198272353541888647752619\ 416264178275007581964972900058207668226403997836323853569738795699842524193777745028687859\ 210240516647578338772677642709362567280133220883704370233076559126616702293928432330268920\ 646915086105793292046975467076763027401906060860253929958942742949542964743590775043849579\ 342092224996291407358279024505480489398993480953529999737651436747864849156601248963858566\ 446729253417614643856932352557978815695544515918136408774883575708679466852573854109678425\ 914527166291939394672950993853194424774890913621861908465265294456166744483368458029114072\ 235916793901020082956132554222777910386641909642627789664594300940035968773419738707981840\ 342938876722041157016532439520820185082305602433325578154301242348173881129317370080462504\ 371958732739712120336224402262471202583149243837233041090000332605918992912023960067636845\ 519424223068192060922726472000747523259954068742865160388442925456960479799346006121252399\ 620119507227120064064261564135808277955536990997488285498499430314328996417333858064134567\ 170046701388446331713913097561805079660721050202794651268745937189798825493235997775045899\ 675412893672302739001502361590590506327894934975430325282227300659024844294827019688537050\ 150394005004594573503256523805437266863228171596096890531204710753180023214785997201644746\ 784070416810452707925200424069415846363744375133371059966518153202014005100335664771090542\ 622644047800008159988035414067763114956340914593444133457365144303865452732912966039189743\ 852578317986932604793893471658714912936948500293711029940622392181888407411591029838745535\ 504708476560109000916843985528909255881490367390344409966307271285338469259735477142011670\ 313859054961232421865823010040973162216101909762472821648719581884045413835202000474115507\ 054900519316131844115847124028583334001580561716613077776724557919155237480670470334402402\ 458675591151242608430921409869852881832180471644895096256332275563626262729118910193358586\ 381553488259815315549736229770152895469379203540405201897252184313567919525851379560373200\ 162386285664915327350181141896395826180438788848288422344561725298462359820578689962290303\ 329012784014378152005454885199949915073408414981586064032420835722207819642831227968438786\ 101794370232186557490546224625798179138113567408616824306475318182620479117147761952184926\ 148073187965887098409602658793369917682560555020886863173988983745337534235758530034722663\ 207357046283875316658903338783907677873631856601591307704093684448102938785123684176103221\ 409403520435713287394069611857282729097691739108664704036987515055146516785239073818586646\ 292050854332021678482426102750746409202271850326372172973115657366479961545241157319118050\ 512061737376174341958267013044028432061394474041289724413186116312177305548679933839312591\ 593033096608910129888459956110507830487647043168020141703739422963942606054061777590684271\ 816014568729050704542244377163192081357186848193542797088937766337080829800873673793323583\ 778622274948950901275410902858753646304161078494347743883243624497940382571813461814467878\ 724305169883290554740545401929219995659299549094734892004563157164254316676018812102211986\ 219653566163264486630303862472999353024530464609331332552368876527723254792023621320089848\ 946059121491952112874010142490391077406510295190382269251165846358926999734121261269411572\ 840193065399270231914126541269094987005537892888818937642009835810257878088565978887492259\ 883484798447584971431121736735832394092056013996221524439218843181722046751670016761418452\ 320337377310792834048282401157337833958392186369136602061136726347290785011673954391226916\ 963634330485849886383333405980372711006238391422792652129693843047570437466180952033866648\ 385153595748574565009116404387111799496669713742946528395227884071616470378851855306965763\ 790002700269233342688674737104643897757287886799645416392732318058143021579176159813134607\ 245116543351756985655111215269086409065646782189352066323390030360939803143133789474533546\ 195110833017596699567890890014493637805433591264989282704336525846802842723995034671538449\ 768372574458781773451719329127659467580593813194067684073714109199876355739416660357410833\ 143276296535611399989295586895290218562824972886948392488497904554667150269648925960073493\ 022945454671556460603262598222903424966711176731943192464711535952494032514352176936192852\ 010494834498018295100651890294249506583007626792556509618160094548850663571558741998729782\ 292311615340142503892718498417134758755592346896912814429875731200924974273608916238756228\ 837636322044927525361479631302516590883073156147086513125810144500533939633658650571708086\ 461956123561611315870687618197118217554819788933602104411587091522129158928366855768043344\ 127556147497473858734692718954812425298594213475753023815862607193140627192167873793977094\ 219431795869471909004611253927054698458138895640148315356010993824803844392631159032269472\ 838326261569545958630743119201003290744213354632339420358242527074007426476914542879023748\ 466346770852083527197148009166799328622543440057327375298982537457910110193314212997998944\ 038872007742934756769760489751623503731792651985047681455875863336093610415130019480402156\ 402280975039120176878153771322003171657124038305140852994138637556116911078456613463956263\ 073955613288308900050451851208647381343210525775491761969988725540471951798162376433556248\ 577039442364772761253645939002106288038175345344988461666200977876558715110115582235500317\ 286688223875003739015272774244079163405161198650098841695283765653414644017639017923422386\ 088778772839779605779269802586609807649459639446097435310804981296476320118618275407408901\ 463804332390793501495145309249001841904539586019325918025632175933024689859113107449873676\ 034025398990925186698626245877701854683913374166478641502627121577043454927451779722219817\ 628412378419138679575568869963638025302136702967792125743180644677065386502562930187979112\ 587796791484570244098542557406554190098503734958824105697684946452779058272504236818467626\ 916068213927955954165313214305718834315020412545233576924852700946836245989759789611203566\ 556452609298767155676590147077637333667930245608342503306781377960527587113854311488354707\ 324655832836738746173347267627915910121859895762017910472769885607197287722565763758112527\ 938522620411547602836460109595752955946142042142569407334749633072047944102880487217051385\ 008036313764897566262794285248855487091084702186098427165521273887573470897458016725680499\ 504331385527976546775054178646155033126903459158186548377820832036285438153952797060603656\ 116107921989694681004133016097731814167655967211304768859467357024641660911165387640901311\ 313443273875964992081792710206907725736635085758479248531679427442728742329185820823270789\ 625013149537146342974281700843229912254040675629761529875464075314353120889031983648533295\ 245120178053692465799041920610827216453223941359988213810094269658465206276604865351764578\ 035673736935035526886661886876425836827578292006577302533906956514702085455628327044531010\ 774413626897807912199683924619377851749290317697039739492170399443768358141831188601694568\ 457119651806548197805830615935728557001999870938926338896444863614757467179775060276822435\ 281347448501776177375512367281271902392264602407537133486259724139742439683529443458188246\ 799483450053846677119990664519578432172098564237440834291257038004390847113057077920338108\ 528224115897022064933621116710573224755137883553508312737541614095141420241940032840713245\ 094811646239851968200085089622678570887723090686789452479310108498427717961274343520821356\ 762177690285032464027488241884793578702193127014358782335949557525670266113746554796184533\ 087877794136125845368256931014636527350156449494833379543009662511334325716446968238837042\ 637488156586728013251186577282337239102322632163969233569206369213333217179957981626845655\ 610992240371781502009389308306160061248444660852929175673512871159184529196400016922453253\ 634846248261528493410146776628164794747974723685828783103625096962563530954186397523810912\ 910308188406981148835898195923787499360914587285694806734660526191226448314465398650838983\ 008558694169209069509595806222339277037504543129327849801920939965664235817311864340730951\ 179926474108559150189389549728677170130172428116238595185095939028538182750704089210699942\ 300118824755308207882461042155405504565634070570311635564713509014604746126359236419446716\ 253941391654687243392179695910328047739981744111070653781664283403439945647979387247284979\ 429810856819031637229446445524644078894884030485211513566937990492763419492596344266672187\ 162318702194836611987210520251958277117805397538961642166184232449462445958827552411175889\ 017126980884086748966021259727613888913047941621495510242148434511438983923654046501252798\ 178277055938808722848618891473687408972777100881339572137516936551945918101558157098746536\ 510810049973459960556056949357881184473853399664784377037232551645638994635528395879959777\ 720292469009942508474432150887037254034826306276885667636453419691591371714404307155455472\ 217116181233047500294895127248046627228263622657392473670413329826822379823637977104633051\ 515779284042717371924266112017648258052841937965249733791164624696463253751438263704541825\ 064156483336470609055077637050117979523815616524002308483144324663686768629091759872339743\ 813373068023707401154109495902884027293794070593582351727555142988117543143437441219229650\ 758600848993600298860126505791263363317057577601338626812149078706585562923752869274331032\ 599981952122316985038009164617108935605170112767327684914074335446299129160636982805196174\ 663291425069377635130955878676983185504112573840163501046065232510759026527809042305506793\ 956137194037652438142650026016825632036174395621755800300267808305321360369219375859534108\ 968643668056179676698190936207201612735590493649779814788208793617988720255278023392398459\ 522419172531804903790763973627510687099032903916927688997168903134194902217164960769991467\ 712546962897810698473036584369509051831346288737742890087910021860339925659570935013062231\ 642954056252295243874693514233309096702037016735728303187226534619939397986192029228017251\ 096392972261579230652563788127827716682305283661103454347703939707125493897060320515261107\ 844637202786749703361428359834330509133476737455184620734562621641175767719618336604380228\ 432669667918085519777940619216631199613169432675034618645777635548656672923018955899837098\ 074871860056997014063584962293674703556621364945731210667688024954410500262646915993106920\ 061699287897744801930737598712094121928514162967609432880294002840847246257830392984027381\ 355852241460003836770608736304396113676601925541929629938161090308623098342110506272915260\ 893528727639050317417523741258092048688305702249847213821925183289731046247007978021666265\ 605234896824766323140551631117491737090785440574967333766857467737448640352984642092596858\ 156534566718919986520962721650849766869701667867657672389428697739488196506967240661192772\ 879118079553401480823596260093318900849640020261230654581847240909898544409585810490297622\ 626536376685746404567855743443751181285047334256572668217819485314461037541993968312985406\ 968325464651439961741447874671124338983170844499141312523828315415627900101255017494214642\ 617033751837170322632181822955602821565851328341006990761042426288395017543141398258691835\ 336630671594914994490449422204354051580719396803872085870421711488561000434018315708307769\ 965028641325592505126690847658593510024107977907985679739408812897013947541954836298575764\ 260737053342213849786800290052597508793515364513544427749106930481038926136914777594284868\ 431611775446830470040808117066665725281937046949820103433139202395851366300877355191796948\ 417908719325307194204140868504649282294517394896562228117906887402806627806762925204783051\ 037137234031124221492006226966568139214127950752199466859857369601611691515609561509370665\ 701403434897106699810171183749388952365701752560533390023605921537356552752808894452057410\ 873125171072373813517227311745998190294810649431306054509540458973102725322043580677528291\ 361414476260840641428401629325413634304870124867813903192722798857125992867130851243342184\ 864893119231891219770689825235974190726563891536678442703106917989925940600489400270434601\ 453193536789887500145894306070504203203026771610705454108723887206629382805612023090995831\ 656399388802925476588804522119138275946340109446922313813109643930157132319417348334151146\ 276723868130395572486377254949835603804143304979427537150318297641522590729878094576776714\ 941032412961851734607749709019186780800021793561363716089360520774923925190937984072259266\ 979837194430224161465499279016050220124759734236316753427951864359884835542703827327155115\ 223263033632519870806898215009072549501115587657906653907856004805748872411049932874577912\ 752228869327205004546895549517238259038105079209292985580332354096404631203286224918259057\ 555916825015987019241090037035954902749482747017914972895109468547137825860663957767911647\ 850381174697761352231720784013417486700154576978563339784170245027767125587567338279217543\ 318816338319400635014208707688552095996782800968688002162857618175358953745095147234734429\ 227468392932072929367940983706919818624749138975003141069346822399076604089138533630507834\ 324961576156698000199082567206318501641275666104784340078169397167705891392489840052863145\ 672863084028966489520160319154207314595823138488941757766790236994433969130525373673069692\ 859645487803181542603962169797489668732953852178660615964824693234637640340318393927028920\ 316482997231666216833380758067964896714599406918490603571677177367970940880389519439313752\ 707997673138005201943748380015701520171481221195749288565697922742044509129983584479467520\ 729200019351878882996486855371263962434006169602531036094131051545336645353890837142686451\ 723736919942211652614520555971762796994890663690878260721813200582152739702216766253792833\ 747131351560508774759882827380487925224197636465907551101256232558063462071890634101360933\ 067320073045671164199746747013692098947409305197635552849809124094238892320960061005353937\ 033502724257758643716504845344669302978176752567138837590492307574950768757325663434749834\ 547526761768293037531709517130611370570276603903191973505631361358306455561156311729521484\ 288560348407021045540360324896087621445461959401020317507677858265749011500162165656618441\ 190675470042929537744839008709221290662536271349156800456227670621933183540773530322214152\ 787950850621366911839220361506707738428682134317449801009713855559419497784188242133550280\ 041680934740324955218926146522735141714880979285102586819337496249359562553939118416998699\ 009300573032077618745755982915603715394841858552213965510202652989616152835122307411203784\ 961316338320348851607785181455867666915120814823258346592643352333896455314174543108760050\ 995469924053707111565191426396447771712873010560122126389015693529521044104015387149697535\ 112243079423064348525899636890775655720528075206031594540075865254872626984535584493435198\ 775502717234029542983241169100485556418319251069348294728904506799644917697081461783759731\ 438610422440462336984245835513034657403939668888969128593388482112632254129287150226524021\ 496077610402417280877092482774854377923579010187953359697875536837839126433940709502151823\ 727475431171389355050428920953927298929893478768590366817620307906949371958276465378878009\ 801059712423933475097906375916791406955992900672664255600297044495714464620746074200374425\ 115132262481140397375239404821992708347491585686942083975540270307939914478014242732287867\ 552651979027557899943781949631235047792994950177191433160950050565492699056856385312781581\ 378729609909960206015819146766253838983369950900326274097627781904894128367359083058013429\ 786420538241310490143861536000097629391773535790242757257546666435051775642756095870567723\ 286981480696037215901869022624325943767254766199902690419324502191772294881409111899521208\ 041149830893937878800827609156697511918575455220972691629964664737933927594215633270554425\ 860833061380996165516887425706936656216229165018910835282371387481268165208166959092915370\ 153507943988405612322731970765244314393486620630121030362181809102216615235272894739637916\ 495650266801217661937679026960849383601787117949879238244370941724681871718342543381042983\ 638703195899224917944961289007167302403673834397359402373547417003074157638414350504711394\ 406803621135226991089036251033866844819675682848818908840771712546240612655668386654096868\ 702851240826157446955795720697948156388871271952784382718096503657976178661593653084680052\ 511451732551805515694704318174642980852777484967858999073648067151999708454968565753420661\ 625085785514303325539651176266254517127161541558393379683533522467805173932803284804961335\ 764114669115850105007053186698064738818502826217942290751340495884835291329169279930887146\ 284101266670763086520681681493436147288379945891472152053488494020636180481634963668800670\ 719458281213103358661506549656775505930195777196627712211414583277521060270102687960935799\ 027168623897266834717117906761500824934192292085562268342865531095254707895267716053530142\ 315778803195517996473869220685401705276840300489265337441306320358793769465862827845874608\ 957287045659603418406648508147021645328122843436370362188671894636060664093635348803208050\ 658200641824344688755066057376837327260640320737998640887974212366678675604534021639590950\ 565652488396922530403967938299701056077264985855348775669300453312980771590264899918777889\ 209790547377911995593030211525269556326137637997794352661910759734755322337051706380216613\ 142924820493452360047665604475725120349784535110880155702359907571300049782095557234808499\ 624509051885799886723687428425513396535575653212314136254347586543724868661459552021371577\ 960621714193000483822686678760263847282205755057564015411508017104306419499863037621788940\ 822539639881350350754001739094601176513805765295066416342196051500189965230367576016001920\ 450627629296786771723130413897301723033083735268237238273141226247756441434396867224995246\ 549835349482765265342624388926100865487300333082807380096265829731271954365080417419419543\ 953128634842411597615345229710076171625126462150639699053955664651637985031288600873610100\ 765221156300680394895741220147312908567347011306751291495449957653069496082366314229606246\ 888632101438115596949969589607195373206353359565431183101013537379032838762840534853681098\ 544401491550216976348066232188954722608788411739009270300443277210122638270344082769305426\ 612878377340553810273401409042502739611437810184286024410417495433388011107444880204813942\ 300614107389869926350427179158358495600760767013383225743109375285581813876871959768133448\ 135921650182000837462761455890360789931381631333293978421765611558742522174118506382512161\ 896099155779459161753248063094091069798528261602205487683561641735870290541624251066510705\ 720842480647818387614515260147649988781987355610423088796240883035554184676101300750549021\ 237563126934745269889660792383610543928064545892629381169426141541653998579273957269130304\ 961712636065126828546179872881125875982363049141668035691344421331494353198785677326903694\ 645924645117729371754638881740972197477045343201279756611172409653675338093629409189422870\ 969026994755340556024416360544918612042557328351134531925489242588503761635961222596541467\ 190408187099486976016420505911642787411683595139255181462682963780520330666977761841040262\ 448029894793464370448991191083026510297812316636357720615682157038322346664198970241696337\ 116165706919002348357037149665387415540102117231399518613309168423347949980345369697075262\ 178450041192257235339926569473196697226689103158103455022388969919581257957341399991262631\ 930779773735915911997083551596754114523628926312049528239967892577854192871260524934051067\ 842634501217651590299459712500581492530426963106033115954293705811207871918278172435739926\ 776986724809511442311511495288713002118277858513987306113786398847757978073315445463584093\ 521581610284998300549473169963199832049877841907659896212811733339420690973942365111496649\ 894878594294022184474355022503293671485429824425782193828814064058614846335690162784950550\ 239935075972564810187725350198523893505159217754234658546502827683112173684326020048936852\ 965281405759328967622432407304855049940928738225618129717847519838230750880643503027093456\ 696325925168231834317451612654705720871459474862139927064557559322386153859670897891359223\ 392086531575442615100034851029727064347197835919187554153113886383236129431731326372690214\ 648038331240521921589818506243028232785768413870434370355012581627028843014848092877008415\ 140017297533859126426301032329011079446844168070994428840015520857558073249186264230607523\ 007241674595604098543127111721692411682125795172305943261756692912348930081876899031530118\ 684095882634264265561667470822107056241597203802528426611146179141689307028246494129871686\ 550832670494168031612945584554090073473847905144715042008892444580916932248934629123185347\ 099224674639701140736244873344320947665993124671279120466771628631939415547133123763725167\ 947915721644702934392716025248625208420686419444800439652702313615398103863576839419028858\ 378828312742932191753945773019163021418162522332888020697304776250091579567084262889619672\ 721863640292352089181328136279273308265712687971696336436274171960127188063283889897610839\ 698861720759875281849131354258680104972834874876030260271509916996456554985526149590127698\ 786497204432484349121856952748265783402851245638627626739549590028465494215398538861871804\ 429557128405773139151620599790341129555920776224705602654736079381071459007240308891375029\ 471559977944102373565906663631415144829540937059931282261640918888891485034648293616057000\ 401561051330488302177554689350226577478359104930157677429802598005530256331915214974116927\ 047309992250933369891405332666638292720137338625492990763337406307165002053327742434094565\ 124745006825492895302961794175198740373133644363868273625451032325720770905459931303071249\ 588730549271421880297777739874743679836335079248523906527602959027863844819677988320836907\ 145845914491852970671216280253497730666711490746161732770775546748980613032083474792310303\ 552617305743121532227010818253506372144636983063758243210793392897197143810541578398997198\ 534745240138764712536904959521574359199987065651075592073156028222947367658849722604738246\ 164368341014070110743989409272331661122840811218548743604372291828967532702030880502697173\ 359658237082731487875934423904214098278975869373757152571304515144471963161719345330317518\ 172090616343338794116738418096558659710343367922630522524866409948455898153232838187270806\ 158185278876120039307526355646597738864889051797913745623576536587536984228769111826864110\ 924017818963155690037902949820853130068201879673130025287230930056898468479484754645525418\ 023136515133603839490572116651366166725754050275667720758729119042397244509285519558157885\ 686920279431962742752642663929688875059815327462371026419529892309036492442120357583647763\ 695867431390327458250782014174446983243635470262731044548278879714938558799938473352845017\ 588306162866763642427631158110237597138544728035407982434912124254756821126889303326738158\ 390357862524468321967764459243841829724110559400988918258486310457344324719941972507366529\ 080279601269821606251973418189729784630869362951250125786736018721113031400366410815242782\ 955313721625706838751758269961571222441602269356579383311628960172810639684480133632039440\ 936956648057348436575949415846034207196815880884636897222847590781733944467828356788640409\ 606720804345383154207162065118665077576088961051621145808366382049514715097248086505083567\ 851481763591878711521170578866535620552580826524811856207272211396154398679402229579079674\ 525517750599685649914877755911379685491175622146961489392467105481638387705869614881103607\ 318242082493941863416372405087097765598292541281376904768262984250857501946472912375110639\ 489372802503660926754365973442108881506610674209095166747950764555581763800638066064687224\ 226558079171474462332476344183260268238679688405792592575757286242847691878545006372392969\ 920147863211870000552016061814625201609752284457444063211256592482830671543339480193873436\ 047805932741637410421931729874786463078912114749031365797799675061581148580048893525905082\ 924458903715106235642790242957335654992884852804848840750401935977051049667125282129865165\ 812081954980343913384513601641629760603669234524991160764498958766615227062220933688332305\ 674510354765910541534124066756312527240433710186288319100522736957877881598124565010696506\ 651881234669369826372351389651358496898208229032895349891335747781469271963455883410773959\ 404249218389190778367056986271594548458143274214501508663292563608316787370358355010253261\ 764638537279245512608818119814209135193064149508961120083564393069889141223160918079277460\ 350795818467319429655669722575591299042140307576455948158997265769324925612101124710656537\ 714893887021161724127804609513392812186926164707154750957579496429475961304027820119692916\ 274890464231000280102620157624511062234481685915204288829775634319986908532395623713598543\ 298018034018047044360728241516753407313356374698492570427072998101555832466287274071932450\ 293505128113216704811776211772201065842603109986473925465235032582483709649021925553041769\ 078291116181215263666709502049687323157253211596690405021771360876544962653230880529243047\ 202653231892593491431734743042969318754959479760353997797886440040430251253249728330646781\ 904794427902429378951481625449931033802208157139476934989447132679272411551779896165258966\ 673042880321694441846025782045697394697532805296264210634811692041137432970815202596387892\ 034168063178067707361352222489071156983789244453362818356500308736025896560593074280050003\ 881267807494909051095222689899562203862643556154245189118686219752674361838631295287689584\ 582524572212749102035999306379864164993084777186111918149229904345863587729445954504595782\ 411458735948203258784694044487304477797121836598125846088976246049375836947437975736282093\ 261701608594938425044568775086986938767002739622332202140184388556925289349734055596462164\ 272224960339048429402418108719227635447761487518642068373978590296643706398949777977611701\ 676953823252102069730189273637629254401375184165966037244430001021473526210109877588378212\ 280669825031167035797878289846918742048818951492069827290011485111099705159572203282733102\ 743151227093985605004805689307204254556148129553353271883951606363637694897638734181837352\ 485167837207635966663487786227530099596039534061120220176478998750716023256684318283779124\ 204895681790391161130302852704304678628722385628915563220882804716145103818121113270991353\ 986492438560047539562949250838845695274191376629609210750256483699565805528931388579119684\ 687476909834049827182093123448533519491674850055462842525188851003196857629020598799481878\ 137405803883741871091291320279174194547138253660251263881966276569695320992291825480545375\ 790894820190459469659952546011938494828565997178970935614979397075112547947016263985585217\ 692628571414056449330884139865160514557126598847395304313994426862539247844502567748191497\ 102922231015474677834353081714941323786168610054036047194511902959690518230461591398027081\ 553230909857681196863857832278921464898400358793154997959547801472182729283449964942099650\ 930405442709546243330798602710013680848861034954558012518272474775165465036937782971013475\ 299977331817198565556317730258348709299277284029326104788267767903647110382513666454310712\ 328504219348165872353147277420508730440077722751202742788181254189967636587977963364808625\ 024949498122575992542374232818686141801978775373762462342199707802582404844236767348574424\ 812150321470133321016851934302679611830999809345370671031862013614964363171322345882513748\ 942515117446079555758171586384180478318682029885478675764319447861177826393477304787287240\ 020487193792301050482706864412334102764674174929118914976262536107587876280155769273015324\ 788238429289915113949605003899864978445707777547683934771795850352811383971568839586124673\ 497172244332971017765462730414313253000431424842410629317660462871027394584935670371312109\ 521810686603196239172143873132081044918015954645619109525093535745220344734979577645290593\ 223732183528980196201912437124214993957441769061087484277962226575020879516415372030062491\ 353278016371010741620313390196038630825428329847780636730011185516357017573498017045864770\ 407493679289346579201364888387755375075558637219937399594200344285818012955040879152212864\ 388263559775825390059817889609547105444537073537929153300004625780569136291448361435901406\ 787992602935612496306669652276542103943449285271425251837645230363402769076627007729601389\ 601905984612958155969615560393395636847355666546771506263412327206220696121275492312418110\ 625710249943238116210864880119834513670759471484598533179742891934505550928417105593196766\ 971853933517576267548668048754900092423512605144625302523316867728310536018611139099643148\ 503260734506401432299822619635850113968420271786306056813399807408108545984576440269528162\ 269949808432380139500356412598837645702148822157989839720886509601942166164443033099234763\ 253103006883111157058096834324983462143967634942144121932170423948157943367469873950258064\ 253810075938034255058090386594959982890293148575115957506789363088843878173848208640103712\ 794854684546521504287107261028774201563834096235710098029735723028662755307875244911317877\ 699181836497428082627027544538817479394246822361247662216430585584780965987275831672141815\ 394399904607282088306642721702922982709959128043642667076665803650332223040897045082203412\ 034373297257803613660208335008757508656992574514642588259614841208231521074652580211727976\ 472409928339152227271434315022678150141326769855735748742396635968485619414417295085298149\ 738164340690419860606332683596761384214159762730737838064542815867377134672595262572805566\ 988046085298062578955235608390283852468120951209593478765982246238508796094220013208253102\ 411690280561477453560262153378157954112852653234912577877769826269796503949810554521263264\ 839252983899449666943636277934044677176856177848362278417277029545706332383335587868703037\ 448286101373549153152131427233391621920526485444437983492607965468103898798297755006767671\ 472722531617901512289724331816501318714443809145360691474860269149728290912333364512278037\ 010714117274459500149214932555058048170704804452921786991214338048189010313437556864331509\ 905247938986675561145863532170738378650158245175879572225124279043503192374539529374991986\ 252951814868345059427801068228816800865990067335437290313953296915737941949130829421387544\ 405240867076117186764598775664054541130628717021153070170759586058026957556010217817546024\ 465227868706996165985528270313462390044833620707395494474392949857710982213809586516522757\ 772221452700158955139398279975853362628290219886745480751243042263021237833077617615546731\ 061943852876331930492895155372001885842393040639330397097900984307438396113106137558907589\ 065341195909567186120553754257976707328181861282916899678578859162372636404609259504877917\ 332385648795201353300629546136328055992072057430289877892970347126839167162467527828662808\ 260798134911669184020030672461564084806165510328836683247083255062829826579559477913721883\ 864070140668364813408576607389044292337504488385126719949672660055743481069732935249083840\ 946800996882110789693495993281135171513854746911817967857342924839718367451303058876297377\ 935607421783838376608587833157624882277493204582192503978459141212839699079298548511475418\ 716027992948194699798178873553411992813265719850571622558918168334748691562864164764090973\ 060049913518056757880529022281629105627052857752228209356161791937368234336749518502066563\ 527582792080539015823651473441185738522824482799916754338766184653411655535209044153203231\ 791451272517529814358972568753081282141845899365408177271628400884798111064947111676297793\ 686853374160306978011773975253836905305549277569396225039837177004054197820887176520534201\ 740370182482646354781744961595331836746185654070557406077067997742330849258203329437884250\ 916459968859433428132036121047669857707566318508433242167056939329078457302817266515967717\ 609188772363765332960188984086664746099588737694229819373842185944746203674283498192292471\ 146742935679216826477678714576598279259442376906564532262054415386661820346552441561859855\ 031182972148215033656624052212111615850510152724003625116976546355610040094626651082998003\ 857147311305133515064544344485695872831908497365654892367839697491871176239532350897587017\ 834061205439992990588915666016897746961747381607902834675456832857060975676892200411287511\ 783068460458908070136395767207886541643180394608502974152330899806380897763601163603936582\ 584832268624138767516098569789778623308119688863452161596280728856239632574686119484025022\ 936855257480076756766757668545461244157224797558885762167120838896667694035931540468586150\ 428096739873302762688702062780929037760879898997666036149031784451419639278598578725952777\ 307256467467112719864489885185531522714418221559139074001668285282731655672193152313677379\ 820449891567615888023571607286826889478018860670723240747549740682745835900983645331014875\ 715713370058761261767141023584457822318657601454583227431564561953266950689963404034033317\ 467078423452301057228985327111421595656597138909498448890229067026709813921457845107188712\ 978821477103102509415627721711620546484422508315269942186779095113319686076483683027593478\ 248733404371066030397800266452065947155793581230756703027782852690203630510531104862151443\ 368050647087254593687389136607437618311349306422429498184714262074239698588773313947176582\ 199121871321768182564719056186223399791325811303515388267886701545305476172743633951946057\ 712405384117501622866995159317219438710075849713070354215796730055677924268147471644274795\ 345012194905383088937265037479381903629120976006068944433387902684010290943889589283329854\ 309158199072191206425551361817783998338791755398648529608617896876967272219402295956044275\ 183104138116642943989741688832506096810730004323620537431725781136684588095988977440529517\ 224862290212407709833804886553766839698603013699525250586281013922922551596067169706872588\ 409382392660927137183156219117453856546943872656132862955436342588806975451605979448893055\ 806188370052808937331568317826774281553540839021768350418517398692539989262477466066179502\ 659712434887095236134758810011713770872032117262969502613334873581411044544437785546304728\ 553680198666729338663382662849020394980107948259735016938255706886014959170193656766743114\ 586833175843228765694841959973192109251239254674895595985879511824748578464676859684520174\ 127943955839487131569710845766681138670079871406173143240499690560859250603579244659748127\ 432250146558953973995945766522846835971286725251749718711613801487470132509677542206163938\ 970212514148549867549226819113722933370440381306161072467917914193588539584231900788667919\ 150838579344729401193056987461422756388409769893879220506726213942998036101052723031384370\ 399607235270965829425352383755311445737875331721091446698538965667543551187841877794951742\ 966106494551549067799678534605387121153592073093154700793970388829317317150019954778946221\ 384416858377449939241736804995976072496207843437046037312105863003827618331133512508159031\ 310418584037572319447605725859186973499356150122558120934535461843682893020341753362998450\ 841385974855299353363497909256585917384300435167208223048755534766319778357779264865172889\ 240845305100524596257662128622072455471388709269981804047177579309159448211525831707510374\ 353654785643737719267780595001693490920689362574409752634930677447717088442016057726045913\ 653601219239751970246388734549069527800240599101327793001018700915204952030820948200866688\ 258366188775140479312246478495500627050379728646367944082310080492120340666160294507243111\ 931037080906981009497166563005056822474483438100579450521880875983526602857638521827152829\ 890479094430695332835474901564155807670085489200605819579815042291682823446621822952715300\ 619410637133262262740808864159773082738291925234495561054949055642859645858879860338853797\ 840861902432963995148129505897930534350485433825320755850826671780847401218267312643763450\ 803786772388420724922351001299409975841498404303926145475803086580965097593893499141877752\ 158519405435218635717324048735644467849122341919182569568391418266675742719494064236557710\ 096790899621094319686015779413655453482327302954357595576294234557611119936418378883243511\ 229364875475868917461850968845813294649778365898106342996376676127691111993395217569922677\ 776925765191029998582501060117729962118657749207230579233205985112224680236115274440770161\ 924162784977917328356973323476433375279954740847546123713107908692512168893603236488823024\ 030786510169202894563152098978013939452380940673728710968621987312155734946059293958415918\ 363004033087132213801504030222646314643114396401564620911076416369379153743597946080021573\ 810089189924109671148424691163494051399326205742428090614436018902709880763461426539362340\ 897505050633460131874801553285642625347606591449326215151307020041150730634336693741388209\ 159143434288568686415619148494506849143875545905503942124788831211378790596934630106018936\ 487668547561910102396031980586144302147224589454296550744739302985175300752666581367966898\ 992960156177412193578900222377105528894611789335184969054448385769469438287280141076858537\ 109889193829431245944722258392910582322288034759982857434156062766001561463341128970885699\ 843322766544859440782606300832198492203525111141667666752903200374529855267811861314644815\ 344318447799051547245600843988272278463501072101313403080345767127325677206538186899111991\ 766582497654591949414239629368153944088179521415693791947108856146301932841088808397421584\ 307225989665881432522133688280089225271698590007690818236211726855523797919726787945456661\ 616499457494360782604456188606722314191712378646993503797167931325533501113755908017143335\ 673483107400479888383603508250283345224482446305457255466430323124434686175300748137039181\ 552667092463482683134323392835682663925358378752042470190536216049723395030571746476539827\ 359329420208432216188555899882119037930401727902021748581279117996289592057802820859494069\ 244995200207811402994248842389006598635347519096796506453352446138204570041186109783624417\ 771412971218111180513172344739080359964407054037207853702317114323040703801547773982102519\ 053503786542353278191709348232687968360149198902372736058638484820840282180279001856753357\ 564122322744301685289326632771219689686861466777254073209203018684674835013182843477507122\ 429292105206574716770287393157437115875300299286830395383047968403743028955567519163926773\ 743851250118847437676154163596813006526488954670678838673330525469233926731596510664564277\ 818187617467341734479411114268284607828515826613710108221325977206287700178715613463030821\ 480214036982301337178841610861346483976179699625529983485387601848715421743357341748003006\ 583064862412315729842056984353113688741289805820282896075093469705193582563425765193637629\ 584482503262327409096565876974166441239865807991929313947150425155481845390165049079574961\ 162813984497915370501785836753618175935849997346101494075496683730131487957918115840518040\ 467144372695510519320202995431783544506163738942205876141253847788275534447282824063080339\ 651204499345557862828989205796903591405578617778702029423665045416057510216842182173882532\ 040167508546983988375920597616295184695039084868834837798285437875105889472047937214444349\ 762790412243024701830969031707027984274405872784541489350853327061601579747695130384105761\ 368844505889169178882183539843368901280761404751895965387051987750898263823268864780094707\ 771867225159618052984191989365108333423853025435743100237026461204329978353107066572639256\ 793275471789630193739376678896781901400372342525096666344027506865744020872159510858561004\ 392356204947395278115889065866933276799433454506493199153120597519601243725035010240825971\ 434431266268179722945435116434589762265813163442721933482760049576712662485241485638082485\ 640746248132816413007406820956337788386817070078926093617185735540652591653552632120620854\ 907100667775220194916896443772045269736143159110138865673261571483218811759129609928577504\ 038350823882979714494589029714168234190184386624528085906383199325749758702074163560582941\ 437010583301474328088858128467221185117192274007588161843062375819690155869943785764687788\ 038891791065520641745061337836259311992426835327392271657030218275380232593536722802655573\ 881664401409151082967406255454490144969515538997674759735049507713807011421662561811093084\ 716159139563862205821855305946757782830306140150750121509498876375817278619529589982488853\ 679509800794187602107349881672381521767248113912062872041479585800290948838067261893162920\ 092727569114049258182323084743074519679617299047081268645817195256475495635889202906498801\ 397644955622726944218857951786093929573211661917516019883220689533921609073387058423826497\ 503582169072590897291410582821733486112761115085672070531547576728753288828399817807930441\ 507693767656838044384420657068640782388075554455282012120082693969046813768255082603862368\ 515890134325102968905398606078097738667421788290362707106683767104097893252418489888362889\ 605093776812846167290712018476861244746119975790175004689043717274122025376457973725510259\ 297549342959235908429250885032909436675160230359435686090627341198048803192062615160245103\ 061115261009098952548035228595529837638806877001681778675922809931885624791314167256988452\ 761374263817980996434409711927983036657823118325946602194123642147711349178222737060741125\ 444584057748401705595839488230494719175949720602356094439493992723068985938844147775859653\ 980934290916658311629874629580818352969365717379009667277441662561867124142856092870288013\ 735155832450076328502411701482337834161164006588249189343526960444418273990794668000631873\ 771672483976305709883200946140952253479982547768404745663046404882555678376838641565141266\ 134642121616558718621826901117074449184193359737989776779485995590751342306698645253128166\ 793319248166187258436987656467913953790532312924280280027418912161666431166608952052072372\ 906066712946041133051352483529301682655154149492921563055473343729295227647342514357477803\ 221779810656579663018749547873561693868098726681490816382146511067812096160617829559463912\ 606564500076420646616142896555491892248208529761851545744912881627996017758491539608222717\ 361264586406994894926923241298852014562928294746146592187969574270181504976880387584431621\ 057601001186853410333918358063508257721534279578937214328362618851932215712368752763924462\ 696037040368878653364371339565132127667979646014107929008475242270574372033317731082828013\ 282719694649587930840367220043076257742862557023943709975123690115245919411923672020457166\ 494901021947380864333302950411526059675155514596006544498044827404502477636664731094796800\ 772934558765389534297688312733088004070438454481631430859977609725030210199812379772372439\ 390267689921635298631575453365029295599281752954614812523470526350512412402541528147738412\ 535302119659621905416414873440120148572714085557520959448528544607171427333150691967214507\ 948386400004033894883051899033041388447147244912251092411837334849345939620659447636152847\ 035985591847700797914460779596980092942331975871466807592812148414763298653240493530286208\ 900021429732476693612986873736607049393839979191559646982998921502737286627332850680992349\ 165068876116408769105021693878234599654999276123180886208377962162309180625736364607993935\ 407647895889752104795098530842862635261420330894608736945688267060901903993651858622364522\ 657904051978128358914901960271182823298524923987950675993063594423861994441098428657151102\ 646830815130426402875049532856537577631150879310150998389045894257455484697295722005264898\ 736771782244385503550520965779575199252368090018566444987033492856716394133289614844039420\ 098797378248356921506702892006636337738439713328083025312878175623128927957964779861206156\ 020917072418309674484148045112711705733893312057070693454709629586668408821797943786108489\ 852925922313617924970492424689930094977534969226090987441275817993615843711159943487784851\ 882851527838456993019212118177746988988825192831148899477899730122642003340549150823910510\ 834605491418095681533305645337563526728352845193804029180594633851642321885894466170446035\ 835853450446331492659052133502442325946760679790503432686481498185493428352027375039392181\ 016108969709830105920827519291158915307778426320360573365167533639199454175460054636330433\ 298988995924134314277170081245836864484920983765358870935800346049764293683878341481309054\ 462475659307277760771059190470418795451667230002124852295698363052591653027245706659869806\ 566856667440905078506006092303827348357074580348381902146388766120789941048217149386991004\ 952322475271419299843467934638393580502590938928382035408208073012566326803551208744613378\ 690674539935507307752733981410348201235354193543429508256600857844314799733392107849040198\ 462463439146681601014795780171719611736776661949683473500745152724605155910946156332584629\ 646809345678615492942372235369689255426041303684015787970330874465081861551770877643893985\ 040646172974931310900518057545071053099657952673315204944640841706823431149868665929975424\ 536923652958212923877934844492897397552630151986689745908941141383915539882231626131882715\ 584211710078968922895199702273266442982382409720102451499909810418393800866442474021550474\ 988480850682541319948250979723644174564924305530324964925865922671074588854602728752504639\ 112778744924027360118655306690401627476461560716219695229156758289401569114394852275807742\ 249491147844204376476099964019013588828631404806048566598595065031453921428103373738820741\ 076159408775689308438076235766525530199924059911032486750729533518376283284823841367207293\ 522643601183267972464594777844190590091481235496183087601771963328079709717344650362124263\ 846324215281312498541361361449664570722361332001605577392847671370780115263784555726322036\ 867826108615861146125481158492065198192029848771094851305002977464920427162834869070661176\ 385338599987894920306693614687260882530681877700048027335068969791539053629854993553619281\ 173011008611573642500595905512022048115364847541572398819234292681321186326188088027571695\ 718187633592970107581055544557818686316660833222467371897683463128272267037012347521509169\ 739220597814250307671176234650131248893171618899752442788583985587688639308165102420902769\ 577818200346627840657809549505306182789627090551936062736329451728071091109851994770782703\ 694579637690047400176087186630196081146159793180661304547319021029648514673581894961950396\ 333064636762965210919075935083020830271971400124208849912350452307645308241802213582511289\ 929311734114456395020661748893439595935559424516465598195229227495274956043027667299489723\ 671806762970858072460030251511465071529103387123392922874109204798374839125866128978376012\ 753682898050052960650743925593230483485616302943829530689632532849762804789310608323254667\ 069579102408324801836241963158613572896496903640915523485721165256996863203244622421968352\ 340618379634104434650342365272327233173672956202706067419791952994424334950378743645415190\ 773580932768988060703598258176334035713464683112361403787627943686105149560752110880630702\ 515185033214652941828182876985276072011549587992395438635576059806279326148873699803347807\ 870182829042956200909857304361113890232767626463026519052335561315931744757646344822651905\ 145696584231626107764715330668637554555262080463768950613845924623301565546372547554291774\ 664413519174253796854502179224509462999739271458308219120169065145193943986380177766237884\ 832031716818513036253272634362683716121562653419748950929460795704654100517513298585887706\ 192882725235562945701233821765130846080067570839130432290956048335931286039116268654342025\ 619900757936912042889523530750248065241055826242093250967076303380180913818965456305525673\ 402710555264902859458900967538688255927353347203045209316148715850027509169525014847985832\ 993534048994830095492969107282657627901050813433817800987037631918551412420261735286667192\ 518173383244007486778539866021475621695076703206837695214043875050503314664992729268789156\ 260382362382747323663381559328123400555031274686037354895653141465542822470751439017833337\ 380184144829583645786311648163998891046956494270966942409056703784253197675737357371193332\ 541195381794055378949695961374050330707152718166789543931667264635171409271882483649793663\ 721128031870428165444545333460609798310588115220034144145610567559355774452913106205483117\ 265039748842897615142413790281237509906893869930923179875025547738075674813515987004359623\ 385148458421460278353522306288656391288273132991496503726792530098217666752462873663965073\ 328505690578585671315373093191567003114207823170433599953233616695944253780449230263879442\ 832509011736928765574846772457235596236559351317242512984975997670082462273618095100537295\ 764506938439849997947488224482423092524758248985210671766107455871677394642485916128509651\ 874490373153134932688313687757268177923986115949185866308370833757815653507971263959381055\ 801656258532205137900131426267875767925202062913657415884021839591959882362093145786240096\ 989725371429108002796266157047652246407559739512170928298120744669946113708948451413255958\ 740911589855473722110256919193879179368462175135606344721117177139550412327943704123120181\ 966946028844934794836409708906619077374321908162008779525664711883873122000125994710202383\ 043600958487570033998574480103348143967186598811050555015535555952704361071690521217305691\ 683446673090344608783545988044058665744530666797728415015643932212805480164752370321416465\ 412926852562034017946220924840718316893539962457462054769236547162788604636500183277716260\ 312735828981695652917200722174222928876715755217001703215248374615206483595650559988076966\ 395166494194431500119351631225317620151143157636759671131209039051916854215122479528352859\ 507676642240968392159288370321605435527318860012154563292795074854044325209749710920890522\ 678486884689774132216914691338248686186183674703636548344728234468900670485994334265205637\ 431956697397690044263035490589065952394395852367030240739524838274185248587539854512149221\ 174431921899348538647686663149226124175135971335118923800063412824033766234233092865909221\ 142863748433401456169098143353305487366534254679310576115303741310570710687823845911530701\ 101495401834668545004029984246438527556612617300079149277380285823938871573025216184050005\ 973578003747936162751244213420762818518280827494456087119455742453160786524229148045968936\ 519105198162921728500505283419662249813456931158940683480901278168777031523776870015011347\ 727570252878860173155649081797460025699807168865017159915695052220588730996851089600816705\ 467753460177326154121315847743124107464058613226591534554700061635806423061112972630732678\ 006312727149715234273698288231974164634794649620486837408150149717197456840707992997169580\ 646622879536635189624029113611577420509833334569837413547518436804244120262969605205242469\ 263293839571789882661036308578588415610817338401459331258154706929217435660570895525673526\ 330255309589416901030485655017444376265390742345276900032626361643117925330277048015005736\ 600461386309923566786281859818430207901873451057808041197253108757775564756279478023997884\ 771013932061623337767294123211674600724670030186968402257792078572289847901747890348042951\ 116204508878433634879088827136652089364358594946125019418033751512050756254772738179086563\ 693229740334472363662099876234931240447846287389196331843516639018719397105134078461468096\ 621387151826105434169244138115005017717684539205178378027624780971960161229171739656631116\ 893252785259047850709944921749262753650887096721021713117017418737592600964218466915009676\ 112629795113142752576069626806228095665129678373861825497152714004040946658265009551573040\ 185354433954604460133068249235339263001583885719174927706903462486918162171807889879513997\ 625919264988051902711472834409886382854534728597229874271122986143581522074134726671350214\ 536622498136121446951131609904314613591931474094021476079975121933696795703715827875298102\ 816621627690164989258247461264969784063552947368819509276239854743136171039686442559842750\ 632037220649377433548653278989624182398669030436090085130959000549149665231356576358901222\ 109589692797371627647672277443677421516767781441929960686988051920974112908235016114960263\ 742234937473281497833950098681188212886033011283528339612647270795390814137732001843851170\ 293239619147477341161102966853600305071320113195800039182755797149894088174038797931553928\ 481072887798617273728086312700507108972991102300834031979720182553346447446418386657306112\ 669313119723597695642985184487813533131576430408294380018472419780377023668597842666750614\ 102096549811124494194734809369197505025156118836263288396574088715051416772241427552393031\ 960688765295206547029623615177345172387858299761714195820585692447678839951235660322097123\ 160919655851012756705245663777524763175371378553071581812995131667881993220854943561903718\ 110014776978921560844796785222629216063456537525616634477309462199186606530969774959795104\ 268735854952274391898516301860885812881473324086544128573547557041679699928301782345602083\ 569480057868152641062654763473382113504246945095460417016852946974495192422934254892274531\ 425007222413121021502343212067054915684474801539238331984585009620214858674779914475598147\ 731242950429435699610908625542041093811219187035924830178468082176766943785303910926224824\ 252067435846097006753623211493234772859967009017648156764513969917160606549239326715156915\ 187570300074754338389025812947600262830258881152450410674252464202949710935188111825373865\ 688245430470350013895132977979789035377050218886441137508171002052126267591557222979234794\ 557214939722240923112521143245494176274426135175723819793696600708083247369709365165191549\ 819296122973824469992028078575184910776467242958675685675214909088313492584426111764231567\ 724413917006846945124403272890327062145150239539080765099956760298891355946277362299194781\ 362044392900946913707055230880816424965328943442915033714171813160312387275976927586639422\ 145419714636416122736898323270531785146250630137490139525476366402940339285210897625814741\ 201477159788678379235818016016068759942035449486817011394091526219423920958985676623897450\ 143584704788990580298792209816280808575448482745467410062425801814477237638023951884105786\ 071765575947064290343737618072073050123796171690432428525090760749957748249846887067925895\ 545999887479659231915332058738440151243404724648285802926447371994680834661706296790562172\ 891558229062577255048842703548174409528922487252254924152514689302053014228146932316625513\ 925749133058607316388815175585003793451151374128761775135301322057426175108348887635759204\ 466658587534738860240227313513804905095926382698773369104467627160464842434294543954624326\ 682077807758191984463569747651314074392575477177196324474371645144021836008041580659410082\ 351886691536610627357721228499763150805653128690946143745919835917072180549322757173204860\ 411953848419604818885525886573320733175957944437938955345377224990349713647354131831953298\ 570494033036524806862303743871141919767925469368541591869290521988838566334649474119264050\ 553841541796297461084734366807183496272270257303356819949183293568874035710683447800749324\ 457606033744647934177354517001068860720864682906147752149132117595826868785253236673704130\ 934179207886862786190614237595502559090003990329332081178684546793200806721770642645930667\ 499533805477618237563339529981518451243393127865211478272644466883436743484774549648779895\ 760679418354139412654368093728700135336397302975802249875428001147252736043023161573690394\ 434255406081050658562495411436717986662853713815346586838753221174422900605241698734999707\ 712016356894690020265045256105031997448376651562669634401428823999813862659578717583301248\ 444853823494369801996824630387440761524155709947724458307718126350443639309375292879825030\ 490513849617392846955955252018930959259777483791072804969654637966966028823008041491534714\ 508666585521353641507531013816290362843684985376368357752491747739219505221381123470155138\ 966456727925196995629315951098811726883834953165510901119526510541641093117439292642635637\ 481854685346015028404874268648664336452216855508612318247199646193424932056854621399326031\ 319745759427641534212504229576971676585069584597384482843841965992799867215122062030019510\ 890377587718655948740409064665787122293990618629605769056036255252381133049274082239045860\ 723987744287573426469071439667337732275946091539929476395643760302551969068441026197555480\ 836530006943863679603592141403289053955157441353751872195054042368584885238769618493714933\ 985834830905400777345784080644728837831730399512592918980374180030073186347808934639773412\ 781702299872076906793284375252101863627059146926131374694246333371384283595302789803872738\ 887059508374766794935643540147104395471348565257972801749517764402217071467394798400786269\ 084515691722069463529460303532324206664285516126809207137181172276927421408430097051505372\ 018265758235665727167880725904017749896239170541975018389848881238269275849243152012944984\ 889814055138043487602290072756452192726991669526684257084820059940088799069438157449133982\ 971796299404324946728192059519384269438496751332211928665139061925218776164611246309949370\ 427759671413608152615717583863742311540941975477733453042008506964356675322312073296127701\ 549667112273", ); } #[test] fn limbs_extended_gcd_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_11().test_properties_with_config(&config, |(mut xs, mut ys)| { let a = Natural::from_limbs_asc(&xs); let b = Natural::from_limbs_asc(&ys); let mut gs = vec![0; ys.len()]; let mut ss = vec![0; ys.len() + 1]; let (g_len, ss_sign) = limbs_extended_gcd(&mut gs, &mut ss, &mut xs, &mut ys); gs.truncate(g_len); let result = (&a).extended_gcd(&b); let (gcd, x, _) = result; assert_eq!(Natural::from_owned_limbs_asc(gs), gcd); assert_eq!( Integer::from_sign_and_abs(ss_sign, Natural::from_owned_limbs_asc(ss)), x ); }); } fn extended_gcd_properties_helper(a: Natural, b: Natural) { let result_val_val = a.clone().extended_gcd(b.clone()); let result_val_ref = a.clone().extended_gcd(&b); let result_ref_val = (&a).extended_gcd(b.clone()); let result = (&a).extended_gcd(&b); assert!(result_val_val.0.is_valid()); assert!(result_val_val.1.is_valid()); assert!(result_val_val.2.is_valid()); assert!(result_val_ref.0.is_valid()); assert!(result_val_ref.1.is_valid()); assert!(result_val_ref.2.is_valid()); assert!(result_ref_val.0.is_valid()); assert!(result_ref_val.1.is_valid()); assert!(result_ref_val.2.is_valid()); assert!(result.0.is_valid()); assert!(result.1.is_valid()); assert!(result.2.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let (gcd, x, y) = result; let (rug_gcd, rug_x, rug_y) = rug::Integer::from(&a).extended_gcd(rug::Integer::from(&b), rug::Integer::new()); assert_eq!(Natural::exact_from(&rug_gcd), gcd); assert_eq!(Integer::from(&rug_x), x); assert_eq!(Integer::from(&rug_y), y); assert_eq!((&a).gcd(&b), gcd); assert_eq!( Integer::from(&a) * &x + Integer::from(&b) * &y, Integer::from(&gcd) ); // uniqueness if a != 0u32 && b != 0u32 && &gcd != min(&a, &b) { assert!(x.le_abs(&((&b).div_exact(&gcd) >> 1))); assert!(y.le_abs(&((&a).div_exact(&gcd) >> 1))); } let result = extended_gcd_euclidean_natural(a.clone(), b.clone()); assert_eq!(result.0, gcd); assert_eq!(result.1, x); assert_eq!(result.2, y); let result = extended_gcd_binary_natural(a.clone(), b.clone()); assert_eq!(result.0, gcd); assert_eq!(result.1, x); assert_eq!(result.2, y); let eq = a == b; let reverse = (b).extended_gcd(a); if eq { assert_eq!(reverse, (gcd, x, y)); } else { assert_eq!(reverse, (gcd, y, x)); } } #[test] fn extended_gcd_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 512 << Limb::LOG_WIDTH); natural_pair_gen().test_properties_with_config(&config, |(a, b)| { extended_gcd_properties_helper(a, b); }); natural_pair_gen_var_4().test_properties_with_config(&config, |(a, b)| { extended_gcd_properties_helper(a, b); }); natural_gen().test_properties(|x| { if x != 0u32 { let result = (&x).extended_gcd(&x); assert_eq!(result.0, x); assert_eq!(result.1, 0u32); assert_eq!(result.2, 1u32); let result = (&x).extended_gcd(Natural::ZERO); assert_eq!(result.0, x); assert_eq!(result.1, 1u32); assert_eq!(result.2, 0u32); let result = Natural::ZERO.extended_gcd(&x); assert_eq!(result.0, x); assert_eq!(result.1, 0u32); assert_eq!(result.2, 1u32); } if x != 1u32 { assert_eq!( Natural::ONE.extended_gcd(&x), (Natural::ONE, Integer::ONE, Integer::ZERO) ); } assert_eq!( (&x).extended_gcd(Natural::ONE), (Natural::ONE, Integer::ZERO, Integer::ONE) ); }); unsigned_pair_gen_var_27::().test_properties(|(a, b)| { let (u_gcd, u_x, u_y) = a.extended_gcd(b); let (gcd, x, y) = Natural::from(a).extended_gcd(Natural::from(b)); assert_eq!(gcd, u_gcd); assert_eq!(x, u_x); assert_eq!(y, u_y); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/factorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ DivRound, DoubleFactorial, Factorial, Multifactorial, Parity, Subfactorial, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_gen_var_23, unsigned_gen_var_24, unsigned_gen_var_25, unsigned_pair_gen_var_18, unsigned_pair_gen_var_43, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::factorial::{limbs_odd_factorial, subfactorial_naive}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::unsigned_bool_pair_gen_var_1; use malachite_nz::test_util::natural::arithmetic::factorial::{ double_factorial_naive, factorial_naive, multifactorial_naive, }; use rug::Complete; #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_odd_factorial() { fn test(n: usize, double: bool, out: &[Limb]) { assert_eq!(limbs_odd_factorial(n, double), out); let x = Natural::from_limbs_asc(out); let n = u64::exact_from(n); let f = if double { double_factorial_naive(if n.odd() { n } else { n - 1 }) } else { factorial_naive(n) }; let zeros = f.trailing_zeros().unwrap_or(0); assert_eq!(x, f >> zeros); } // - n <= ODD_FACTORIAL_TABLE_LIMIT test(0, false, &[1]); test(1, false, &[1]); test(2, false, &[1]); test(3, false, &[3]); test(4, false, &[3]); test(5, false, &[15]); // - n > ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 // - tn >= FAC_DSC_THRESHOLD // - prod <= max_prod // - i <= tn // - prod > max_prod // - i > tn // - tn > ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 // - tn <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 // - s != 0 first time // - limbs_2_multiswing_odd: prod <= max_prod for prime == 3 // - limbs_2_multiswing_odd: q.even() for prime == 3 // - limbs_2_multiswing_odd: q >= 3 // - limbs_2_multiswing_odd: q < 3 // - limbs_2_multiswing_odd: sieve[index] & mask == 0 first time // - limbs_2_multiswing_odd: prod <= max_prod // - limbs_2_multiswing_odd: q.odd() // - limbs_2_multiswing_odd: q >= prime // - limbs_2_multiswing_odd: q < prime // - limbs_2_multiswing_odd: i <= max_i first time // - limbs_2_multiswing_odd: q.even() // - limbs_2_multiswing_odd: i > max_i first time // - limbs_2_multiswing_odd: sieve[index] & mask == 0 second time // - limbs_2_multiswing_odd: (n / prime).odd() // - limbs_2_multiswing_odd: prod <= l_max_prod // - limbs_2_multiswing_odd: i <= max_i second time // - limbs_2_multiswing_odd: (n / prime).even() // - limbs_2_multiswing_odd: sieve[index] & mask != 0 second time // - limbs_2_multiswing_odd: prod > l_max_prod // - limbs_2_multiswing_odd: i > max_i second time // - limbs_2_multiswing_odd: sieve[index] & mask != 0 third time // - limbs_2_multiswing_odd: i <= max_i third time // - limbs_2_multiswing_odd: sieve[index] & mask == 0 third time // - limbs_2_multiswing_odd: prod <= max_prod during store // - limbs_2_multiswing_odd: prod > max_prod during store // - limbs_2_multiswing_odd: i > max_i third time // - limbs_2_multiswing_odd: j != 0 // - s != double // - s == 0 second time // - *out.last().unwrap() != 0 test( 236, false, &[ 10618490636539735421, 4729263067195600518, 12186030463696251555, 7142237826843540900, 16119581746492108114, 5482041831095653408, 12729359642514511788, 3861260445332999633, 17654643046781915017, 2948639619901500831, 4828424310736619826, 1606991017570978140, 14449535564474352339, 9583999911344645019, 8526753984697305947, 1483125246843554788, 1239190358257616768, 14274595842916600689, 8578099838285951726, 17196912285743182036, 17502, ], ); // - limbs_2_multiswing_odd: q.odd() for prime == 3 test( 253, false, &[ 13440159167366384907, 17464845158472189078, 2826161362940216017, 8037578185636069543, 13742255038126785696, 4563220256937210164, 972898594381496298, 12935003271289472483, 92134269506540108, 1576249685989390350, 9293957639462726276, 13219082968020015738, 14036467266653166020, 5999133297790892927, 7879089681869446232, 2166730567576588847, 17427398953314831214, 15373827890147248358, 3930181242506798982, 16625114769217038348, 16998219128482634557, 10891990883556867133, 64, ], ); // - s != 0 second time // - limbs_2_multiswing_odd: sieve[index] & mask != 0 first time // - limbs_2_multiswing_odd: prod > max_prod // - *out.last().unwrap() == 0 test( 2225, false, &[ 1017787374069377867, 12845616420474236155, 14793541814949268171, 10336267089029193949, 17681045444610962234, 12241025939672520011, 1647783948166186005, 17853335081138702500, 5765698469319069076, 5704200848184839352, 16256105179485582433, 17734124028926156842, 492655904033205979, 11085849896016490658, 3067192438194807154, 11837646166112740505, 10992580052412267512, 1773657253076351848, 17041387235381257635, 15421578608188334756, 4615954739499965896, 13499729159452430001, 414946168188809488, 5319757607719939053, 14636961330979174035, 11228840029340991417, 2679650868790992799, 6523494380304249905, 15240167682641278207, 16817584289869342383, 1314876650236886671, 17986738819629100058, 633572152189350719, 1068154426686527634, 14065257391447683248, 14043628340189386248, 2520373228683116453, 8613302832793040941, 5920151864571800853, 6631973414231062372, 2805822256823597153, 8266805345818108603, 14961584013940036942, 3521359229908934002, 12440093989655599608, 13132030287112341405, 1135400476705565545, 13470237633228184820, 11041193975860352280, 13077192932837691259, 17293836581638404804, 2171592479756569901, 8391859231746033908, 13233250271168303683, 2885150469181476635, 12827004644907825951, 4414861260039887031, 2934847053891069518, 17933902203427299124, 13612729539900541744, 9092564372087223834, 16826850061886832697, 4235092271172303688, 15237133411303617967, 2524372566060934554, 10438528715364626770, 3931468119754873441, 8873546397604882128, 3022623706864869622, 7597020790388111878, 10943741155846665560, 14197476647010604491, 9989007778547549825, 8026201480421198518, 13607446335263109565, 16903088772085727428, 15808374554425019668, 6105563595459012989, 4013715839388158058, 15900509513105858779, 3930550334470266139, 3012225684372399152, 3555814020193574494, 16008860678570397127, 15641857373385284341, 15630999159384499531, 14194771320251995975, 420469150284887121, 13013286608344133197, 8528545810586239597, 5970238577029242260, 2388798772187671996, 7239099684932389496, 15198440189583552216, 11371225490310014286, 15452238839118434215, 5822580676472517141, 13899215192394129457, 17158467603319793152, 10977162731484357791, 6619469008814683154, 11754410156367698938, 2978824074240909961, 273537313978929004, 7247845064959191752, 14411883344186220714, 784118077426499313, 12871601200579333074, 8028216077204519736, 11850247931840500366, 3779495200526023485, 5929422344052886193, 2800123978803955913, 15699871195759344930, 3086311510046848853, 7356496574230285725, 6320159507583018055, 18115938954181399640, 6284941634674233267, 9549047133838384915, 9377608933266367603, 5075665075684086144, 690014617562733994, 4759772792411992244, 6111964336140423243, 16256222171952118355, 6259909518175821262, 3521565945796344197, 17834735129730212580, 9239590528624641975, 2672544178748226145, 12588486577096010536, 1899856248989413045, 12414729356008040141, 673936303178532624, 12049353462684429624, 18170970390317199364, 3895323652602044690, 6247176993757894998, 14018764694053309664, 12148460064737427051, 12519272021732992903, 4265286318973514000, 13246207213367864932, 8092301291433872754, 18157183851941858474, 13632398639372993593, 15041229054496823587, 17438882071637825679, 16897762262634509480, 5985915708134883861, 17069291239962633754, 4604617849471294129, 7404601016313800462, 18032855475618560618, 17278074032422674715, 860111812404472121, 7676514517933742397, 12645077157634386901, 6253760177721599414, 9582459955741222618, 6555031122495818025, 9109772022144641002, 10312926431630695967, 15174450307054914476, 13667236735660909752, 8408881821411653704, 11716946339587432929, 1922786935178624187, 12807837642974514636, 2473722894595905227, 5458426645784377815, 17442014199053342412, 8890119087458894100, 14425743191525790241, 16991179320870950910, 13035467074473694191, 5787345193441130361, 4705313533091031873, 15331508321092401972, 16030846562817685004, 3052481183062108791, 10562728949964566718, 13010480725459192018, 11461359799240800435, 2183835189889431750, 1589077507581674225, 209493893234690824, 17275528419958179992, 13786253520218962997, 8418527685430488832, 4277383631769243150, 553728001632835698, 9744726741627180359, 9472249747805929122, 2320471217112438768, 10501323670386497816, 7960518975670364695, 18361982008650146784, 13597146968161371494, 15048282371199457431, 11721290689994903139, 10236837511513990756, 9365853519324508062, 9624359956681910024, 6464188517998707741, 1613104032762890885, 8208472167568412592, 12800200029551711758, 3442648414208252067, 13536931097714636227, 13680099157307486964, 14296431146446833136, 9490494350514148171, 9088818047483723317, 3574838510805215040, 17710736595066585329, 18387087888522354666, 15545394289660342510, 1906938938574314263, 4795399658629299655, 5999021877917630376, 18186518198482153992, 15325896453672651048, 10288450437885059914, 10416325383170154040, 15252545550781802698, 11203850167434393557, 10930649003967455247, 4205680756002312162, 6052457706079534658, 8809248482758461337, 17439291973136036686, 14540031682752633228, 2866851932511598749, 7403683280133267157, 4543483651640135231, 10836604478698343545, 16677730720541412608, 10783834510772171652, 686367541545890040, 3945636644088204461, 16492288623082307055, 11410592877514597108, 4262454581966561376, 3226936869596190506, 2269258247007518459, 12712674876690317000, 715200030416229478, 4476123276882470939, 11651367928687373644, 7647140969145544226, 7054163724695468332, 9303767112281912798, 2511756170805945536, 767695948141735127, 16013838828931689852, 1660339257018204036, 17879387842407650206, 7329246204095148284, 12230296804697810396, 12554402033302195954, 143442532799357566, 278975221130083403, 704260913362329426, 16783414591993586867, 6420395195518570400, 1242530744355731932, 7229248055319127476, 7329179342212070204, 8801422143729346915, 7202896809469888435, 2740513910203208596, 1605583283743774906, 18133844077322829538, 12114669632852319147, 3777413896736836346, 10534763338306711186, 14271006494232962493, 2194873499284659165, 15408899770262126114, 9187831456838158154, 9493725892599084642, 2706928395034605310, 12457405692640371251, 17219883563575417931, 11342733020178340937, 8953543935614589549, 1650319869406153528, 1699668215805423570, 4658796056608814785, 10191145295455593970, 13899311420360969158, 14471878845989945578, 11625414899748956593, 16598163026893516823, 8574589836055525845, 7512292358343960576, 17973744362666546698, 4748081966508603098, 13114442497466532636, 17717653663975693, ], ); // - s == double test( 2225, true, &[ 18273847592806914913, 14916661124009772473, 13753012507801233945, 2177017738569174816, 16127046055767688953, 861596526990070502, 900331037467932077, 16419285249480787078, 16218119651779998807, 4449144590778508396, 5797432146873167292, 3658745141936919754, 545168142452805825, 17148224939070044052, 12094519636288888482, 1860524967909680000, 11944377795202454761, 450998278972528990, 6229559984764978492, 692524976150108183, 9064236318526181538, 6065732669816418385, 11346079520098762673, 14920005359765058322, 2824584984376391340, 16938886314725057563, 17162544784568094730, 2586797791946541382, 14296668031704924113, 9646825613588464263, 7079812537211058309, 11120058236852537534, 12100085017675020879, 14964503322387943506, 1317980653840108650, 778234578243207603, 596521671354538262, 5006607580276807142, 15407271393272502488, 15573500044631135983, 7935314468229974933, 5125906969614837712, 16281633070145926026, 10841335053186957525, 17450307718756727023, 12333034550501581052, 10335633642357417840, 2658401353173590381, 9928967891637445302, 346433133502823118, 1125969053347945942, 12869295090499245086, 7161688279795242985, 8102170348534423246, 11501976328143442721, 3139756684381179246, 272140454388501101, 17653947300704655935, 18170419175440044364, 11620223751270977055, 15199737729791407954, 7388408950276186267, 9421939597451630319, 2597904459804208335, 6415494893523120358, 11278503427630235513, 17087603759736271563, 8499727139718896059, 13078202821805789519, 6267232287377047314, 12745328769944065239, 633458985557193041, 10591869002113750048, 11717141398383033199, 10182159168145114245, 15297338266339549376, 7675716384162360916, 14044976791404615146, 4826327060564654494, 13824111753357577432, 1900118510953347559, 8934435809233468295, 16936724118164099477, 6715750096675555516, 15742093305101977345, 6770550399746614438, 16893816526813516547, 3972985572344553776, 14352636830428013583, 7235300939595407519, 6482168811103125826, 8529869224520362482, 275752241061888521, 1657885970020523479, 16055229676929243472, 1329626840527245712, 11652057338991275044, 2200299065278759357, 15923824600667998353, 14452285691076415854, 981741195753309331, 7201095575238789005, 13340345121085282794, 2680287044054356020, 9408615051995915315, 10441077296581096820, 14712361458266681524, 8124482655364073111, 14222323278853437602, 17070664871184295932, 17474138478542725542, 15177656584895433414, 2526272351085273991, 6899922232335160103, 4319287874022868518, 15816851634040015111, 12112152024215446224, 3606792321694648705, 9429172934661010546, 16821618974076073653, 12119323924085732779, 9269996314367783608, 11677711150311827044, 14826179744550864313, 14311566973567724922, 11690766935901640332, 17692848354524494381, 11471034271597096968, 1783135434038615748, 14881574202813672930, 15830300711784462210, 630062474555626774, 17060519393404392624, 14757894127409047620, 12461523429328038945, 5445397329406998939, 17884801583819720842, 1818977548627787018, 9113900825703689420, 16915916658972784066, 15622182061515094917, 16920477467185064686, 11826213325249074339, 5465014424784826852, 7335719503225494900, 15841161992748631086, 1299642982951657968, 197715083125423811, 14284377913572972912, 789668823628960978, 81036771547499486, 1988737592120412916, 13618394416444865222, 9426939251263437583, 16147835905603573032, 14670138126638825807, 13365861818007883916, 187274109266309872, 15584591815633641607, 7468625031687560535, 6620786124781371382, 13074327572766063757, 8811083685803335562, 14556428240003445098, 15168607761515723842, 8228373127931581991, 4449537695769626872, 16189599284483220268, 797498, ], ); test( 4070, false, &[ 8108005815282335195, 9146844186444094918, 8660083345757410800, 8098332886796284485, 18327436189098520241, 3444039843702503689, 4140780547010543813, 14037137740150481503, 1778663445558401359, 8801570388752073452, 2100918768041211855, 524703799362959113, 12962247820844726992, 14701744186225035810, 7313567667433951704, 10050831291847253075, 6522212258387665281, 9713357079840432969, 15650953094464421347, 1209849253782734984, 4490688349070706208, 3139050496689458569, 12245827531446440255, 7885981168676004558, 14154661077321356322, 5349852652757407610, 16092452000899791090, 5332211751874201060, 2010166260630364055, 9798313122251961485, 218932147329958256, 9022218650847797161, 9247716414481763471, 14400589478286751493, 155515641352761450, 16090683018468668029, 18438337824921230249, 16750617951041927284, 4466848102871550334, 17245130053737553841, 5684920055966011256, 17485566453638379463, 3876098111780047824, 16170758650201105177, 3329608698571465239, 11098790367425582117, 6479997293989211563, 9589433605206440133, 1627857831675420300, 1732996071343246956, 13677549908265537781, 13009227383550369090, 10961856472489506886, 14877397326320187840, 16507486074381907645, 14585352423433247440, 4772857464862032589, 12016886091453855080, 7931222225152140551, 13652152998550600083, 16998629316990967973, 526526529893597072, 12092338051210294623, 6819207438863426635, 11198129540720007747, 2941664361484076111, 11290270564500831896, 7141368769790257178, 4310192286254467973, 8626208125424982752, 6486300810327348993, 16817813221529065857, 1665451483178444523, 526626375466106821, 1558004989071692770, 17197912381461676471, 2028020400876381294, 6632176584976099417, 15853871790538747381, 12244096904102365064, 7885917276665675411, 15005896934276204010, 10004696875159009950, 564876699456822610, 10276340856888745756, 16929103490933678961, 11766003323021850140, 13379448244674233012, 1700622392771761597, 12998026843356148399, 14386135549950737873, 17103249986604805696, 16786552926533509269, 15192402249011372416, 3682655530759859389, 6438705993413043824, 13321028524215423815, 1823597566198742888, 4362292623191872397, 8810115919852355307, 6024401878081901215, 6718375548708698908, 65836699280473345, 5459920132720522842, 17611518624765606886, 13413230224953721533, 18269011901647493745, 11482220135864365751, 2391276440752141958, 7953372639070979047, 7719335541802590983, 1578078632861068430, 11450608370291117368, 17345790563481277271, 2471612067088960322, 9509634917954887016, 15790984357169346054, 3068287571882149714, 471828767153656274, 13989984920988442927, 7509949839462576562, 10968664464658574290, 6077107907583745923, 14180003222908660504, 785997593410843284, 15346199982210062573, 2127241843253405780, 14106663760181537824, 1816989325079298256, 13585984481704676966, 16775201233882366395, 15894543543338446770, 1107757662154265429, 8343871796706615587, 4004079488409770502, 13897369022267696941, 1900082861214911602, 716522355498280832, 10878671752431301621, 10824325209201257147, 11326396537153935107, 3449811571484933271, 13282337890784915268, 7114243324086389360, 12077364721569316700, 16806236645113874712, 3976467828062833535, 14892561338874070677, 730742184143676508, 8041199874795643530, 10588477393010195205, 8741684265023787402, 9323226257963451657, 12383914466097937740, 5459183481775283109, 8713085987825614917, 13599525973515812615, 18412620200699133025, 6654671808175209159, 15512514585286904591, 3418160363584141286, 5329252877044658765, 1773517879281305085, 6751907522769980960, 5595071891327138711, 15092986339807365771, 2637668950041653368, 9120481822278454853, 6888869033907116052, 2355630305042933816, 15643204059310730325, 14189972604337948712, 15973742050610849695, 6242065490899143192, 10363937503100539096, 11070337623129049141, 8371320746562326912, 12695119021290132172, 10946420405222747694, 11793689207562115243, 9738441606075555748, 4055649477600335048, 3880331981234421156, 13347438816701426930, 17047267217526913425, 14743067117062752918, 7500680963739160488, 3488447525771141371, 9324555149161510174, 7264600294919436405, 9007784967508818611, 6103106720642023698, 10517676694084426843, 15560433103569708967, 2746068979338915377, 4985185996082465965, 16952688848835623971, 5109870761485173378, 8634678600073803408, 2319185650670298791, 12712939795386441047, 12844727668639157639, 18206839820669131705, 13819514640691885271, 4818348659491619709, 6617480138343747641, 15213182099370869167, 14637440613867531472, 9652794545650675745, 6662269855919686728, 15464527851536273824, 6948300103349899268, 753008641517257019, 18423686888802874368, 8667176541059774446, 7099552216889810617, 5097390314227011257, 11164163665133923676, 16601595315094089072, 934251793604345199, 7561790558864090771, 978936761586367389, 17101343332617286825, 18235594016090146675, 8892479711303127261, 9809871209460262551, 2394882822052699187, 17253801929346615689, 11866062736428885642, 16437653361862401491, 7486219130830357614, 13720638887748552989, 3021364063186030632, 4790724598986510238, 14359903221320647419, 15701149522880886933, 5746571782218451762, 7210169400177123347, 10042203436933651963, 12677504245079166833, 18175151564707403074, 9425061978030509015, 5758590662601337386, 15348859264339969047, 84847087193038207, 9111274560170647524, 4278081610518772774, 12529339272615071307, 12409855992802623412, 9523579083364964737, 10131834173738880007, 13754924237593988998, 621522042857583856, 7464325591076653888, 7830537412804901743, 6521359168347430210, 16894039362572777376, 5413242484644566268, 14890107208076170436, 12980026768650320887, 11398310152701007006, 4453768301766954152, 2532536434582483661, 8315666704783771480, 13461364238018113773, 2367277318932022237, 17591329597188385026, 11375623002647255287, 14912925391917134409, 17574598362054282658, 9404088160471690699, 718445096980481234, 12792792291239978324, 8006961223861908611, 16462573277199771867, 15753551978373173836, 1165618856952885551, 13488872490939284662, 6292751434775819077, 17978555343322705896, 11917634234603254804, 162840434454496298, 15468092375694967720, 10967364594358191032, 9314385576792743968, 10874257552955261204, 4080522163464587172, 775060301135710213, 15512539461380143991, 15282862206590121475, 11634145833295838957, 3729296162985408021, 2708304538658858121, 12973478170148581224, 8050517243904765020, 7652018392181115173, 6828100662787911762, 644540307178504165, 9834244593696654688, 717190824240544061, 7918203759694436774, 1381239225989678565, 4037837100601917635, 10802212765762616104, 15085162986324183364, 640803418391629184, 5440933420358031637, 7912472064612543150, 6022949383217060170, 17164562859107739409, 1707274268270363419, 16353036691579357283, 9896120685866007660, 5240055324003979103, 9943488260620580398, 2795797772511437220, 15728639203804433038, 17163352271120418930, 4576984692721900001, 9920664011545963272, 1162651417625311508, 17117469006464985573, 7325235138239111279, 18304978043412704382, 12887402943015993511, 14814534017899278196, 2423645702540296415, 3089940732951430909, 243463633479215389, 1853544701457559150, 16340002828745074453, 14353724121437826749, 10091976479103341782, 16445589728945554096, 12491958380500551140, 16956760932267439248, 8027499409757227236, 6125007472513238023, 9932580797249172181, 8500623667517585457, 13042021579813295620, 15746465657147920157, 4336138550822800341, 9810545091138121169, 5082389296265504858, 2797088738314226811, 1788720676657601196, 13852906260052809399, 15901487609613735742, 16898133139552432839, 9518583808608390497, 3135780694510726770, 15768959579073101320, 5060730587445662107, 13026896330095181663, 13406455708166664349, 15874938122077036419, 12502020629429544436, 3206388887230923597, 5335712912997776161, 18320472783623629896, 12300785747455089667, 13200934099356667514, 16185793709615010552, 10504644792424617533, 3165770672396699194, 9659271587384891683, 14071499891855926173, 10057304373257827497, 8747735409408624915, 7073755668073479290, 14289860991929203106, 2241519710446822187, 3895111632723557508, 2526746390679189521, 3116945709823411600, 17383197281821176783, 7952464668971727516, 6901807899244715536, 18040113216886148526, 4268131054090303895, 1487358751414798288, 7752711065051636269, 782881033717716437, 3048915553972286578, 17944199781198644729, 9389246360770923456, 16122431310696436556, 10776235947384101503, 11061273148200041873, 11376451884458646940, 13228985150393505898, 10201260035282798966, 10960968295486930139, 10150870526387620225, 15622960701236479318, 10830024109717612388, 11069526249991212591, 7177411583475908506, 12883497517546755586, 14452533555439112738, 2319722755462632117, 2707463600284124085, 1640962093580202224, 1781980281809689073, 15431145229979346468, 15450020011414281071, 4610352806777138140, 715901537448564375, 7906779838611334191, 9295186163734943091, 13837118237702626530, 10628587043038215377, 8173817480377720286, 18146513027571012760, 18034377209743766349, 12416434057720465458, 16863109019369808778, 17598425176089192373, 7838352420531465275, 6446253944183856472, 3217827157412015166, 7736416779564775474, 11944279093150198319, 1359722430089967762, 12944512655507306702, 6968226813496259100, 10697114723710345120, 12045439838989284122, 14360294208856859982, 13554544330260187416, 11960481134019314560, 16193728456024646791, 6788935070457860696, 16784253667098474942, 346235036471591563, 12579823797379718533, 11237106727685787594, 7376229368874669746, 2310494137345974933, 10699485085862861475, 17827376656397906407, 12654909010486092313, 12911864664898312670, 16753920293216445659, 6665140426308933113, 16331633263932455518, 10109679348425115019, 15893667959446481301, 18406325439525742133, 933973555678699597, 7168028379341447244, 3151961147604448767, 16537206733760622467, 5066764475441679955, 18142248769235084338, 10267108442140677091, 15428903838728157772, 817803212986250530, 14382377762501152229, 7294220161923800220, 7081723256077136000, 3334475525919947583, 16199270874538651756, 2344559218216607405, 11987285877097183410, 6271232791990646890, 8865933992675026303, 16277240149463018400, 1656896235599446490, 11150448321793527957, 4631896433546355206, 8877084437753247207, 7307284130241324899, 3898492975685743779, 3665446048463257912, 14648028503878372256, 4141262678851999482, 15769177955090495312, 15700478929465111924, 13772286815471806568, 16819697748793130742, 374816477005121133, 9978039585089436623, 5388602092448346783, 7599620772394967758, 13068216955460967229, 2209814478936490342, 11426676931961095314, 3575899553386457735, 10074556064068343208, 1175343165804101193, 2579842808821635021, 12160230121712404482, 4570123963392650145, 11533242066554433675, 8978786221712843977, 2519957542118309466, 11338180312992409210, 17438791722639593890, 235036220639090508, 17299731811003138346, 11345013161471373979, 6808878923112761884, 4906649794209058970, 14510541350917650537, 3129870112661089444, 6780443774321041251, 10383203886842753587, 14791651661609640635, 479104220414488434, 3308544737491745274, 12357304405135409837, 17075636268959836058, 10907896764439381067, 11643599381158439431, 18424980765811796263, 8249222402674259286, 9896706913692159539, 2152931576999706359, 4727177868031013262, 3266165952382965456, 9085838590190029565, 16643373348625444382, 11565678787598161058, 10615433009880595611, 2811627817244839406, 17919168585610158932, 15174362170354828474, 5597023051532920206, 3411824531765525771, 2887283203315816513, 9247340977378434321, 8972524604189795344, 3111627944095111700, 13483341139541609028, 9578789344755939896, 7839906735318986374, 5332229875909435203, 11793410887897771248, 6502944694411264103, 3797221239185211363, 2318303302786427439, 13589147558791336226, 13963887555481507589, 14815243147364150315, 2874636415001201973, 7791969142922524431, 8142478508158078750, 16320253976455093478, 11410599986950683085, 6941190512875461993, 714780298870163634, 12186367514332744780, 7396330582410885775, 11973894210027103516, 15383581181396047007, 16278071189583596534, 12216205906506175663, 6100928555352159602, 2937593753448772352, 14364941381544585739, 7143026965390827808, 12201653352837638909, 8268259781562500315, 17457954864467036821, 1325561951447557612, 1830250720349684188, 6503632833560144671, 8957246064803922704, 13184493622423870667, 3800624358443674755, 5833302624748742405, 5853990385357953007, 4303717340298687263, 4513758912754435790, 10845881821986243973, 18314135169801212762, 814247782154798077, 4175446608061850087, 14066747770756565318, 16223104902964522012, 14386221615141474583, 14286245335107087094, 4797660228332850220, 12494772503717947664, 5046526480383637489, 4695803558343679414, 15207164406494018074, 10746131379349268959, 13427849410099074058, 12960999646017015515, 10875962048958581312, 16380543578406679915, 1081549612447048742, 14988053947085110551, 4719671945245391810, 16089148134643534992, 542091408184916386, 17256758054232279755, 4139827917918018104, 12212703329706756000, 16728271907145403562, 2812092140620955679, 12743744931348422865, 1697950412660640926, 15168405896517504340, 600504526, ], ); test( 4386, false, &[ 2067770789339411803, 13103096875436466845, 10775991317478993717, 12967380299398919437, 12020325680191252113, 17748295712695560928, 1429341763317489229, 12678340224185994909, 4335442947861292402, 5254780375536440952, 17074502202508083505, 309407234721139885, 13452727935428837455, 8651378078472139112, 11512513997222178700, 15910186442568670644, 12845112729418812790, 7897815290878156013, 9244723605015583552, 17818446835461168600, 9268757667201962790, 13518324509513650058, 10462750832084307848, 17365663074296091214, 3601241491427429096, 16011129535131124250, 188279845157362453, 11102064840933848532, 12976705436704377860, 16067635780216235799, 15111235286034779573, 16949342242668510111, 15198057271216638117, 14221135849758717397, 4944363911855682389, 3187706824974319087, 7338540094563526202, 16578881813150901018, 11167625661382169176, 517732891565245060, 16978960760497725346, 8776342161961474572, 7065757446489966082, 7633843099211849039, 10126092316436660909, 7137931307826524381, 10378215122356064905, 17259871895964295908, 12904171429142559149, 3245154771911236476, 14137987011116880665, 3313964895395428359, 17536273921393851251, 713485028257444541, 2504041554095751793, 11868371391163863223, 6651805351133757865, 6667440167584357174, 5410381989650680365, 14991818175930336399, 8257594786289573987, 5706253266337186736, 6124744329210826966, 8947309000932886151, 2828062293304464966, 2945904981118350722, 9340961774751783834, 6991179653428794675, 10353734651419249748, 9995290938924246850, 13748292297662222218, 4892960822908531583, 5001073284079337557, 13395090824536719310, 16748415575373971262, 3794277149064466315, 3471133925886159212, 18287753555606486434, 9672715726223475697, 274643140420740271, 5084208256841635357, 565582889520143382, 14443006075048681485, 15151943957630016490, 2415682863008959026, 3647193967014640950, 4900474299482998069, 7440294411928457855, 7555879457509324101, 11720033631659853173, 7634817390629418714, 5364401984816035681, 14274975916464347588, 18110903883298124645, 10451080161694932573, 17274117833138202923, 13092023069546038740, 12707287623023466476, 17701880209880420627, 2721809281104108355, 17847139586804083902, 17102921262115553190, 15532642833766944434, 1280075840001965788, 3761354226423057718, 10238421667499233931, 16260871926280516440, 9728473062383715969, 5953520808705507799, 263442908611940290, 12837547734028811219, 3287327756734946357, 17180396981733070497, 6685721691481472712, 4223337774056033861, 17203789254093256094, 5506147567525874801, 17525679577751101209, 10962165345191958610, 6263807420731253205, 3923945801149572338, 17284772696566520082, 2337995081818459703, 10159695744432522804, 4645991148779039189, 10456895348208050580, 9609163518931971560, 15343500081229831267, 4516517331522645741, 5703018699998096839, 9289174806651010588, 1907313371747641829, 9700205622504251902, 3384501760799438251, 5592475228402079956, 5699363979963530528, 1772165853917465545, 18293565878034536773, 13506779974076830618, 4433695301786679145, 18316157440486549103, 10582239038922153367, 37236612930183149, 17966150282195407897, 12541413422471328583, 3221443629988836742, 10375517911848610163, 16312415585539573309, 17263637399055711337, 12562964968987510931, 948248222908469656, 15567975209379123460, 8261653520686110354, 1999465121504211136, 5781047899520920323, 6315198745347909330, 2920278920380027756, 4345551993213715119, 6283657344621674559, 3606906764584629572, 3214509309748650204, 4421650669626111069, 10113279086264766781, 6040809634318513184, 10105872563177742877, 7530051675459302141, 14917228249506435637, 4803471693748163459, 15339413088591036105, 1138826137575079324, 16391062326234990346, 14971482629623839337, 12498986044767135726, 1758634949316069683, 3079336619173718801, 8019450776809033904, 11043397957650314282, 12422777714615135210, 1600737775507512235, 18027592484657533779, 3245499257818457797, 16997244019634782986, 3056694745780408313, 16838597974032301566, 4231066868194520257, 10562550261283056758, 8961231382598729157, 12511921298671716507, 1865431125930113477, 2907259905584584543, 16284546744177846395, 16912600838448041892, 5685768352085959742, 16073286910652494724, 6283460899260262733, 11006248608684764980, 12393743873088932506, 12391913626649357467, 15016416664079279639, 9408641421320112644, 4025080079418204587, 13515889317109760861, 6226634619622204428, 14051645394100010803, 6133348733808000448, 6549072550797710617, 3366502349209799505, 4214984042943155540, 13545152513431319859, 795203566590623457, 2957066876294725061, 14037361440208811220, 3567928787052247594, 18129592358468459211, 7391337147860966470, 9745224408810299881, 6273194274566822118, 5865744013188664203, 16331376339301383887, 12655709446461158338, 16058749309251802594, 16013590485222250734, 17377122665244463023, 1879007341157847506, 8175620709685639847, 5052075645054700814, 14604619995008524058, 8996782117651602293, 17751524763342629241, 6405720938723467480, 9374406085408070641, 10902473135566069570, 17299547825885109840, 9378213062126977886, 10748234354845075895, 16298760983383038268, 11912524381622117490, 17531579882154090089, 4638623466945320294, 9718336125194098908, 17748627584772750138, 5929383739994257604, 2634528888377348952, 7452587852059168494, 10479972321254713875, 1207579517364184495, 1227691654580968152, 12283325902343980973, 3630742542495239330, 1557735469640288318, 13148409011485075278, 11694984553024128048, 13853138208344888607, 13075028243661617397, 6077061419898013703, 10759228302707904856, 7134870213220203017, 17700670474189599567, 6488352687619878666, 14335593354894875389, 6344626185331917569, 14406699681719439442, 6714341065455077735, 4791758696562431350, 162497200523271921, 17479090938200299691, 2988688594805820109, 7777421366994092731, 14642692051425214172, 6274682819626865559, 5229423047741496007, 5654852991719816168, 5055395278775913297, 12041756526601788850, 6814108790911398001, 13599277275502247027, 1574731768977388996, 14139185185305594281, 10348783097165818778, 16356555785871812759, 8509205960970416974, 369792736551032730, 4928560669248384211, 1496296389308083367, 275482014864563394, 9515713819908090443, 13779279241489032499, 5922260955368225052, 1092706023383976782, 2360049775560684078, 10830508317428607424, 11355555062201315465, 8822901367110163092, 8360846078201768657, 5610591053096960621, 825839549030470748, 4354013872927963141, 6246140926823935603, 2664120007387415299, 11028705440560322531, 10625898421812353966, 148691473840606177, 8310156060530348557, 6684141576519691078, 10666277726485832508, 12496909850771141958, 12640316601276796117, 1625185014000874153, 12691818688161663560, 7284978345576571395, 13570120000390501180, 17258139152508325657, 16431051452047113788, 18021498085837424736, 147540858693017597, 16489503519317138018, 6384423972105245397, 17968902491833871706, 9389823822199644659, 14015616956644237252, 1624016862827524307, 1133086695225646084, 14210479644264771704, 9354045035850960349, 4999905551939222112, 127779107599803994, 17188565212169682757, 9095797152343956231, 7477994596817475252, 6929119664609167341, 3026229977813010602, 3373603747000003839, 402015014046664505, 26644720949978834, 16550954361894454284, 15537993049361919153, 2802848809767628844, 12723476677303988431, 1452153691672522097, 3434061729562431318, 729282772583672128, 7702161485333588893, 8717527779288695787, 12363485505590025970, 17624693189004583309, 14685537190335019953, 7702477702547611841, 13950049520337589373, 995603177974720045, 1908021199455081620, 8666881553466182833, 18205165727916302250, 9075169860963458400, 14214404287201285116, 3730790297335296211, 16018490608374186886, 3817924654967992585, 2594301786026675009, 15391635385542285594, 12501364696981125528, 15521243366566790239, 15115184551511400222, 11890281585537800925, 13743275121740710291, 18290209697475844389, 9452021830711120855, 9366033362614110364, 15189787976271753218, 13926199825258867108, 15495826818284245741, 8531249945458971662, 17589848977595818263, 5117260420662179148, 10609979181463468221, 4913348785482518086, 10558959588352660372, 8256184825576553677, 15328078566821422102, 8369548310319076057, 14408099923166180103, 12023136302419338418, 4185185540229752140, 6826802409442294703, 7577964011315904722, 5184334342724491008, 993509100019263200, 15931436829275119251, 1146421971146413118, 7457752172737922635, 9303468447317898804, 16896814437635093007, 2897580989878368123, 4607005167306394543, 13191995560910209108, 754818302289945956, 16550875926839443808, 7988613715747824244, 7594021839994771817, 13390383436084264345, 10818741266704850020, 9840567310602600933, 6853317455240951849, 3654318299357871447, 7165021883724890419, 366327955050086071, 14929430926370816287, 15929091848994821752, 11105903166789344918, 17397713166933660028, 940076493347828340, 6881587310329390584, 2525314747911475552, 16039575856899289003, 6590095526609987943, 14780829395712816729, 13403664212049269290, 7776885716456199825, 7327709346503253495, 7797242194106433773, 16614929396385540024, 5614139257682381061, 18047475783289703107, 9666137234872592914, 18196751923076222182, 1735358215136480054, 2825261148642530486, 17958215272827091532, 4229064305320080722, 8107409220128419983, 2659809653637122796, 8461071852700444712, 2853300478568934095, 12627226863684674629, 1725915213416318852, 487301172206353235, 4413773887930902588, 11380364842493382110, 18202450692039293805, 7784494480032084716, 12727459447363886037, 9477329144027792300, 9375946880998142541, 3850113885112012173, 11830472656413909940, 13939088354425096574, 12431341669790120564, 14604778789765165983, 15232263358213700722, 12591997966392050807, 5934537059080957325, 9116727594927728823, 831125065896912587, 6919754862689771483, 10898884224579093352, 10194872422166905419, 2240873485886821150, 772949527074947092, 722360265481154865, 7863960452925898308, 2995106245389276294, 6413625243236464846, 11417572663652050724, 16800248131553723377, 13503562407484296894, 13751605094817502750, 17009103221214602662, 6290212481944391998, 16492192720802115237, 3359973450786126320, 18399902818940892859, 12411848360389779577, 16353647163615635517, 14511780882165179745, 4167580674549721515, 1157978505376818537, 4823712731701839796, 15625736345573532694, 13451767465863821756, 15449238941112417676, 15564277366463860073, 17123483066444823350, 17728013126554602313, 16630084534442117029, 3077949725867728231, 16563931105160154865, 1246592974021224293, 12466022741969968785, 936399083803917084, 1508756071576207725, 12593257295671577526, 15030750707522627616, 13422604362668833145, 5988522993706110934, 15545744445564958732, 1333287819193404898, 374964701110478911, 1268449382615324030, 18152641639961098650, 13911634194020977647, 15751397195385234389, 11910107323217822218, 6719368906000612979, 539357533696613124, 12370714977713865320, 11182314386535123678, 8119574039901243532, 12179800389262010105, 1510115720081333085, 3080816336433056477, 7208163224523064396, 4484890163125768129, 4471197540253572019, 16164979284990145212, 1352434240322204577, 17709563636005322148, 6175465245802596932, 2813064733658804479, 3729563625698838686, 17030954856394461019, 8814338780961745521, 2180303021116863804, 10602246745335408702, 11278176099084345908, 2989599815829423813, 3174997621154098140, 6013428651509341881, 1056309801926189131, 6754803862830721714, 13831276002295643570, 1528921296308702728, 7027293378815715253, 14550621546237275727, 14579138781069179492, 16649016585856135100, 2169005788597798917, 13545574963505347448, 6837331033324486251, 7090962232927689286, 4662659566106165098, 8754777632717149483, 5804275858791907219, 788853342477740755, 16728861156177940737, 11428624619995598035, 14984172660064414249, 7586067300257715870, 13544922098234698859, 13257509618658838381, 2652216851092922006, 7861597740154527454, 1410202913196998970, 729890979789569621, 2143681954235555293, 1922907112472408969, 3628498397933816460, 7247461113839898678, 1912586770250857938, 2554218233645160534, 1743595205444296423, 8767829447546562406, 567862460760224080, 7305055418633592092, 16866314930981097852, 3795937503324310941, 5621962951370066494, 8868249692690458913, 721008487395008718, 7430091675158085829, 16331765483270902465, 7335683441619026843, 3257550354989871481, 18264160295416879866, 11136793850551427435, 10546469165077048539, 5550997632077748707, 7153389858358930639, 5061349939637694485, 3990963419914210519, 15864228418379343270, 10313411382620536299, 3247364825267582220, 16798279756492637943, 4799346260722321334, 18161385831180514221, 5680400420092624151, 10244339711594697803, 865876781659886278, 13652502876619329633, 15440911199202656750, 8821648827419111566, 9157488610126501397, 10945666626044426963, 6969723870784479629, 15622137819654655923, 3894460376560585304, 8699178934690713236, 11719950596492741147, 4303171596568431905, 2201336563349598335, 633521128747937906, 10783414600329714759, 12633157919692423052, 16165320295662473268, 15791357301220105561, 16707503754652450664, 14638594967732844399, 11617299177772471971, 7307198283537189698, 14701917077406390219, 18245496844025624337, 11104562001690845490, 6064130654076660079, 6513424921504926691, 1737851892642531957, 18377988941784482593, 8034223685660909576, 9983995693134438566, 4814979217316997434, 10286008916702006441, 18263950945303861757, 17727582182642068647, 8847975247191099221, 14186530850444591231, 848650607969070940, 11636660174669653982, 10790673005564564668, 14420034928065783601, 8938173207516609044, 18440352591895674931, 13402033683256872796, 18045033870573153376, 2237292078652826406, 10211782132693590673, 772050115413368836, 9260457899141949663, 7450174044286317401, 7479368663774737969, 9236392813906009688, 11260429241598988834, 1295346375121863256, 7631713597562972500, 6013785207649710084, 12504083400869715484, 10391675565598624561, 17086420331228234856, 14617438647774567077, 15964728536429688928, 13460421593436649766, 16408312779121921256, 6520489253483657869, 4730756746647128773, 9028350139788839089, 7953083747782670383, 5096299587699598800, 2951011592716102034, 1556959608597785858, 11489708918307621984, 12277065314059308881, 10220668622316585965, 11995324860038254033, 4353183691485690945, 427717306190904666, ], ); // - ODD_FACTORIAL_TABLE_LIMIT < n <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT + 1 test(26, false, &[11182600415380068643, 2]); // - s == 0 first time test(35, false, &[13586117418673889649, 130422663336]); } #[test] fn test_factorial() { fn test(n: u64, out: &str) { let f = Natural::factorial(n); assert!(f.is_valid()); assert_eq!(f.to_string(), out); assert_eq!(factorial_naive(n), f); assert_eq!( rug::Integer::factorial(u32::exact_from(n)) .complete() .to_string(), out ); } // - n < limit first time test(0, "1"); // - n.odd() test(1, "1"); test(2, "2"); test(3, "6"); test(4, "24"); test(5, "120"); test(10, "3628800"); // - 32 bits: prod > max_prod test(20, "2432902008176640000"); // - limit <= n < FAC_ODD_THRESHOLD // - n < limit second time test(21, "51090942171709440000"); // - n >= limit second time // - prod <= max_prod test(22, "1124000727777607680000"); // - n >= FAC_ODD_THRESHOLD // - n <= TABLE_LIMIT_2N_MINUS_POPC_2N test(24, "620448401733239439360000"); // - n > TABLE_LIMIT_2N_MINUS_POPC_2N test( 82, "47536433370128417484213820698940494664381329406799332861716093407674399473489914861300713\ 1808479167119360000000000000000000", ); test( 100, "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463\ 976156518286253697920827223758251185210916864000000000000000000000000", ); fn big_test(n: u64) { let f = Natural::factorial(n); assert!(f.is_valid()); assert_eq!(factorial_naive(n), f); assert_eq!( Natural::exact_from(&rug::Integer::factorial(u32::exact_from(n)).complete()), f ); } big_test(162501); big_test(162502); big_test(263338); big_test(263353); big_test(263354); big_test(1000000); } #[test] fn test_double_factorial() { fn test(n: u64, out: &str) { let f = Natural::double_factorial(n); assert!(f.is_valid()); assert_eq!(f.to_string(), out); assert_eq!(double_factorial_naive(n), f); assert_eq!( rug::Integer::factorial_2(u32::exact_from(n)) .complete() .to_string(), out ); } // - n.even() // - n > TABLE_LIMIT_2N_MINUS_POPC_2N || n == 0 test(0, "1"); // - n.odd() // - n <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT first time test(1, "1"); // - n <= TABLE_LIMIT_2N_MINUS_POPC_2N && n != 0 test(2, "2"); test(3, "3"); test(4, "8"); test(5, "15"); test(6, "48"); test(7, "105"); test(19, "654729075"); test(20, "3715891200"); // - ODD_DOUBLEFACTORIAL_TABLE_LIMIT < n < FAC_2DSC_THRESHOLD // - n <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT second time test(35, "221643095476699771875"); // - n > ODD_DOUBLEFACTORIAL_TABLE_LIMIT second time // - prod <= max_prod test(37, "8200794532637891559375"); // - prod > max_prod test(55, "8687364368561751199826958100282265625"); test( 99, "2725392139750729502980713245400918633290796330545803413734328823443106201171875", ); test( 100, "34243224702511976248246432895208185975118675053719198827915654463488000000000000", ); // - n >= FAC_2DSC_THRESHOLD test( 473, "24105348290207984100197317421171182490921899413623319647593979414961419154254094380115999\ 189301460161039406301206658065847305231769123134642895607903467624412688193137891638118329\ 605237994774653987740749807295557291435144240110313449108135603699200932257584350374350787\ 323659752996357699013258512218790061191470897010499751650188156859142205866225173540759120\ 884362743953738057721709446884608434913698856509684431470876923079372190040412643076525278\ 35572579953211852767587427960391216326823983495675207677777507342398166656494140625", ); fn big_test(n: u64) { let f = Natural::double_factorial(n); assert!(f.is_valid()); assert_eq!(double_factorial_naive(n), f); assert_eq!( Natural::exact_from(&rug::Integer::factorial_2(u32::exact_from(n)).complete()), f ); } // - prod > max_prod for prime == 3 in limbs_2_multiswing_odd big_test(65539); } #[test] fn test_multifactorial() { fn test(n: u64, m: u64, out: &str) { let f = Natural::multifactorial(n, m); assert!(f.is_valid()); assert_eq!(f.to_string(), out); assert_eq!(multifactorial_naive(n, m), f); assert_eq!( rug::Integer::factorial_m(u32::exact_from(n), u32::exact_from(m)) .complete() .to_string(), out, ); } // - n < 3 || n - 3 < m - 1 // - n == 0 test(0, 1, "1"); // - n != 0 test(1, 1, "1"); test(2, 1, "2"); // - n >= 3 && n - 3 >= m - 1 // - g <= 1 first time // - m <= 2 // - m == 1 // - g <= 2 // - g != 2 test(3, 1, "6"); test(4, 1, "24"); test(5, 1, "120"); test(0, 2, "1"); test(1, 2, "1"); test(2, 2, "2"); test(3, 2, "3"); // - g > 1 first time // - g == 2 test(4, 2, "8"); // - m != 1 // - g <= 1 second time test(5, 2, "15"); test(6, 2, "48"); test(7, 2, "105"); test(0, 3, "1"); test(1, 3, "1"); test(2, 3, "2"); test(3, 3, "3"); test(4, 3, "4"); // - m > 2 // - g <= 1 third time test(5, 3, "10"); // - g > 2 test(6, 3, "18"); // - prod <= max_prod test(7, 3, "28"); test(8, 3, "80"); test(9, 3, "162"); // - g > 1 second time test(6, 4, "12"); // - g > 1 third time test(8, 6, "16"); test(10, 1, "3628800"); test(20, 2, "3715891200"); test(25, 3, "608608000"); // - prod > max_prod test(44, 3, "5577337931669504000"); test( 100, 1, "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463\ 976156518286253697920827223758251185210916864000000000000000000000000", ); test( 100, 2, "34243224702511976248246432895208185975118675053719198827915654463488000000000000", ); test( 100, 3, "174548867015437739741494347897360069928419328000000000", ); test(8, 6, "16"); } #[test] fn test_subfactorial() { fn test(n: u64, out: &str) { let f = Natural::subfactorial(n); assert!(f.is_valid()); assert_eq!(f.to_string(), out); assert_eq!(subfactorial_naive(n), f); } test(0, "1"); test(1, "0"); test(2, "1"); test(3, "2"); test(4, "9"); test(5, "44"); test(10, "1334961"); test( 100, "34332795984163804765195977526776142032365783805375784983543400282685180793327632432791396\ 429850988990237345920155783984828001486412574060553756854137069878601", ); } #[test] fn limbs_odd_factorial_properties() { let mut config = GenConfig::new(); config.insert("mean_n", 4096); unsigned_bool_pair_gen_var_1().test_properties_with_config(&config, |(n, double)| { let xs = limbs_odd_factorial(n, double); let x = Natural::from_owned_limbs_asc(xs); let n = u64::exact_from(n); let f = if double { double_factorial_naive(if n.odd() { n } else { n - 1 }) } else { factorial_naive(n) }; let zeros = f.trailing_zeros().unwrap_or(0); assert_eq!(x, f >> zeros); }); } #[test] fn factorial_properties() { unsigned_gen_var_5().test_properties(|n| { let f = Natural::factorial(n); assert!(f.is_valid()); assert_eq!(factorial_naive(n), f); assert_eq!( Natural::exact_from(&rug::Integer::factorial(u32::exact_from(n)).complete()), f ); assert_eq!(Natural::multifactorial(n, 1), f); assert_ne!(f, 0u32); if n != 0 { assert_eq!(f.div_round(Natural::factorial(n - 1), Exact).0, n); } }); unsigned_gen_var_23::().test_properties(|n| { assert_eq!(Natural::factorial(n), Limb::factorial(n)); }); } #[test] fn double_factorial_properties() { unsigned_gen_var_5().test_properties(|n| { let f = Natural::double_factorial(n); assert!(f.is_valid()); assert_eq!(double_factorial_naive(n), f); assert_eq!( Natural::exact_from(&rug::Integer::factorial_2(u32::exact_from(n)).complete()), f ); assert_eq!(Natural::multifactorial(n, 2), f); assert_ne!(f, 0); if n > 1 { assert_eq!(f.div_round(Natural::double_factorial(n - 2), Exact).0, n); } }); unsigned_gen_var_24::().test_properties(|n| { assert_eq!(Natural::double_factorial(n), Limb::double_factorial(n)); }); } #[test] fn multifactorial_properties() { unsigned_pair_gen_var_18().test_properties(|(n, m)| { let f = Natural::multifactorial(n, m); assert!(f.is_valid()); assert_eq!( Natural::exact_from( &rug::Integer::factorial_m(u32::exact_from(n), u32::exact_from(m)).complete() ), f, ); assert_eq!(multifactorial_naive(n, m), f); assert_ne!(f, 0u32); if n >= m { assert_eq!(f.div_round(Natural::multifactorial(n - m, m), Exact).0, n); } }); unsigned_pair_gen_var_43::().test_properties(|(n, m)| { assert_eq!(Natural::multifactorial(n, m), Limb::multifactorial(n, m)); }); } #[test] fn subfactorial_properties() { unsigned_gen_var_5().test_properties(|n| { let f = Natural::subfactorial(n); assert!(f.is_valid()); assert_eq!(subfactorial_naive(n), f); if n != 1 { assert_ne!(f, 0u32); } if n != 0 && n != 2 { let g = if n.even() { f - Natural::ONE } else { f + Natural::ONE }; assert_eq!(g.div_round(Natural::subfactorial(n - 1), Exact).0, n); } }); unsigned_gen_var_25::().test_properties(|n| { assert_eq!(Natural::subfactorial(n), Limb::subfactorial(n)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/gcd.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CoprimeWith, DivExact, DivisibleBy, Gcd, GcdAssign, Lcm, ModPowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::{GenConfig, TINY_LIMIT}; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_11, unsigned_vec_unsigned_pair_gen_var_23, }; use malachite_nz::natural::arithmetic::gcd::half_gcd::{ HalfGcdMatrix, limbs_gcd_div, limbs_gcd_reduced, limbs_half_gcd_matrix_1_mul_vector, }; use malachite_nz::natural::arithmetic::gcd::limbs_gcd_limb; use malachite_nz::natural::arithmetic::gcd::matrix_2_2::{ limbs_matrix_2_2_mul, limbs_matrix_mul_2_2_scratch_len, }; use malachite_nz::natural::{Natural, limb_to_bit_count}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ large_type_gen_var_5, large_type_gen_var_6, large_type_gen_var_7, large_type_gen_var_8, natural_gen, natural_pair_gen, natural_pair_gen_var_4, natural_triple_gen, unsigned_vec_pair_gen_var_10, }; #[cfg(feature = "32_bit_limbs")] use malachite_nz::test_util::natural::arithmetic::gcd::half_gcd_matrix_create; use malachite_nz::test_util::natural::arithmetic::gcd::{ OwnedHalfGcdMatrix, gcd_binary_nz, gcd_euclidean_nz, half_gcd_matrix_1_to_naturals, half_gcd_matrix_to_naturals, limbs_gcd_div_alt, limbs_gcd_div_naive, }; use num::BigUint; use num::Integer as rug_integer; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_gcd_limb() { let test = |xs, y, out| { assert_eq!(limbs_gcd_limb(xs, y), out); }; test(&[0, 1], 3, 1); test(&[0, 1], 4, 4); test(&[3744702173, 1327092413], 1932313754, 7); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_half_gcd_matrix_init() { let test = |n, out| { let scratch_len = HalfGcdMatrix::min_init_scratch(n); assert_eq!(OwnedHalfGcdMatrix::init(n, vec![0; scratch_len]), out); }; test( 1, OwnedHalfGcdMatrix { data: vec![1, 0, 0, 0, 0, 0, 1, 0], s: 2, two_s: 4, three_s: 6, n: 1, }, ); test( 3, OwnedHalfGcdMatrix { data: vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], s: 3, two_s: 6, three_s: 9, n: 1, }, ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_half_gcd_matrix_update_q() { let test = |mut m: OwnedHalfGcdMatrix, qs: &[Limb], column, m_after| { let mut scratch = vec![0; m.update_q_scratch_len(qs.len())]; m.update_q(qs, column, &mut scratch); assert_eq!(m, m_after); }; // - qs_len > 1 // - n + qs_len > self.n // - reached nonzero limb // - zero carry test( half_gcd_matrix_create( 16, 8, vec![ 3364358997, 3754657515, 2983848742, 3936755874, 1784338974, 2546784265, 1325228501, 2948540251, 0, 0, 0, 0, 0, 0, 0, 0, 48883882, 3336115747, 2904559986, 3732488562, 2492471725, 1228174159, 2572912965, 1596092594, 0, 0, 0, 0, 0, 0, 0, 0, 2193991530, 2899278504, 3717617329, 1249076698, 879590153, 4210532297, 3303769392, 1147691304, 0, 0, 0, 0, 0, 0, 0, 0, 3624392894, 1881877405, 1728780505, 931615955, 1096404509, 1326003135, 370549396, 1987183422, 0, 0, 0, 0, 0, 0, 0, 0, ], ), &[851586836, 2796582944, 2985872407], 0, half_gcd_matrix_create( 16, 11, vec![ 2035904157, 337140004, 3757354024, 670541357, 1156551026, 2954076405, 2306281186, 901391702, 26359260, 3840226876, 1109607712, 0, 0, 0, 0, 0, 48883882, 3336115747, 2904559986, 3732488562, 2492471725, 1228174159, 2572912965, 1596092594, 0, 0, 0, 0, 0, 0, 0, 0, 808024130, 607404974, 3634401411, 320381711, 4246353409, 2141048780, 3541800429, 3925651923, 2116051089, 3713928088, 1381495070, 0, 0, 0, 0, 0, 3624392894, 1881877405, 1728780505, 931615955, 1096404509, 1326003135, 370549396, 1987183422, 0, 0, 0, 0, 0, 0, 0, 0, ], ), ); // - qs_len == 1 test( half_gcd_matrix_create( 3, 1, vec![1918546714, 0, 0, 3992705367, 0, 0, 4279371403, 0, 0, 3759197804, 0, 0], ), &[3543156725], 1, half_gcd_matrix_create( 3, 2, vec![ 1918546714, 0, 0, 2304079673, 1582715589, 0, 4279371403, 0, 0, 3341917811, 3530290808, 0, ], ), ); // - didn't reach nonzero limb test( half_gcd_matrix_create( 11, 5, vec![ 0, 4293918720, 4294967295, 134217727, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 0, 0, 0, 0, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 134217727, 0, 0, 0, 0, 0, 0, 0, 0, ], ), &[4294967295, 4294967295], 1, half_gcd_matrix_create( 11, 6, vec![ 0, 4293918720, 4294967295, 134217727, 0, 0, 0, 0, 0, 0, 0, 4294967295, 1048575, 0, 4159700992, 4294967295, 134217728, 0, 0, 0, 0, 0, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4026531840, 4294967295, 402653182, 0, 0, 0, 0, 0, 0, 0, 0, ], ), ); // - nonzero carry test( half_gcd_matrix_create( 26, 14, vec![ 4294967295, 536870911, 0, 0, 0, 3758096384, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 524287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967288, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ), &[4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295], 1, half_gcd_matrix_create( 26, 18, vec![ 4294967295, 536870911, 0, 0, 0, 3758096384, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3758096384, 4294967295, 4294967295, 4294967295, 536870911, 0, 4294967295, 536870911, 0, 4294967295, 4294967295, 3758096383, 4294967295, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 524287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 4294443007, 4294967295, 4294967287, 4294967295, 4294967295, 4294967295, 4294967295, 524288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ), ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_matrix_2_2_mul() { let test = |xs_len, xs00: &[Limb], xs01: &[Limb], xs10: &[Limb], xs11: &[Limb], ys00: &[Limb], ys01: &[Limb], ys10: &[Limb], ys11: &[Limb], xs00_out: &[Limb], xs01_out: &[Limb], xs10_out: &[Limb], xs11_out: &[Limb]| { let x00 = Natural::from_limbs_asc(&xs00[..xs_len]); let x01 = Natural::from_limbs_asc(&xs01[..xs_len]); let x10 = Natural::from_limbs_asc(&xs10[..xs_len]); let x11 = Natural::from_limbs_asc(&xs11[..xs_len]); let mut xs00 = xs00.to_vec(); let mut xs01 = xs01.to_vec(); let mut xs10 = xs10.to_vec(); let mut xs11 = xs11.to_vec(); let mut scratch = vec![0; limbs_matrix_mul_2_2_scratch_len(xs_len, ys00.len())]; limbs_matrix_2_2_mul( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, ys00, ys01, ys10, ys11, &mut scratch, ); assert_eq!(xs00, xs00_out); assert_eq!(xs01, xs01_out); assert_eq!(xs10, xs10_out); assert_eq!(xs11, xs11_out); let y00 = Natural::from_limbs_asc(ys00); let y01 = Natural::from_limbs_asc(ys01); let y10 = Natural::from_limbs_asc(ys10); let y11 = Natural::from_limbs_asc(ys11); let z00 = Natural::from_limbs_asc(&xs00); let z01 = Natural::from_limbs_asc(&xs01); let z10 = Natural::from_limbs_asc(&xs10); let z11 = Natural::from_limbs_asc(&xs11); assert_eq!(z00, &x00 * &y00 + &x01 * &y10); assert_eq!(z01, x00 * &y01 + x01 * &y11); assert_eq!(z10, &x10 * y00 + &x11 * y10); assert_eq!(z11, x10 * y01 + x11 * y11); }; // - small arguments // - small arguments, xs_len >= ys_len test( 6, &[ 1824026683, 855383832, 2690657440, 2097392823, 1744856106, 145210032, 2603321546, 3714268226, 2572752468, 3552024211, 2105680113, 94008293, 3599160935, ], &[ 2100861089, 4058927494, 3716614958, 1374886937, 1422228766, 4125067565, 2659645894, 3516145724, 333198217, 178588388, 4107267309, 1484604263, 2137933301, ], &[ 1307794677, 4133495830, 1895462954, 3236069911, 3579790936, 2823361555, 1496151737, 2535182824, 534572820, 3734537343, 1327464147, 146259718, 609826618, ], &[ 2641001264, 3832561802, 3044312402, 2136702112, 2248874160, 4213317499, 3447231898, 3536677714, 1313296525, 2266853686, 2052041169, 347717049, 3434352423, ], &[17796630, 1709267377, 3881785007, 955800997, 1047963095, 1178960613], &[3543460331, 2385517496, 2086915063, 4055235164, 948436119, 2870150085], &[773552019, 2621197289, 344580017, 3644778487, 274842105, 3931875648], &[3510151397, 4026412532, 4195503381, 682501213, 1600717006, 4252677869], &[ 2986138245, 1099838926, 919425337, 2682286770, 2754856871, 2818192521, 1654309759, 3195744726, 1787512677, 270014583, 3333887406, 3816198933, 0, ], &[ 343075118, 2459980459, 1480149398, 379857868, 2605135184, 4087866241, 313289235, 2201953346, 57359095, 3003278162, 1714985241, 4181488913, 0, ], &[ 2571956126, 963369470, 3125970281, 2288117049, 561041416, 923295190, 2931384231, 3709683058, 128286972, 2292494833, 488801956, 337168684, 1, ], &[ 2992440279, 2112449146, 2902973305, 109063322, 1501017829, 475736264, 25775141, 3410631721, 3956905026, 3154770531, 1888093339, 1763601187, 1, ], ); // - small arguments, xs_len < ys_len test( 2, &[ 342664039, 3864205283, 1256491723, 1548927821, 721895559, 1910261306, 1235301118, 799978473, 549823983, 2512819824, 2068299963, 2595078570, 2035992824, 1064296193, 3249660883, ], &[ 3453614628, 3979759903, 3415299769, 13499660, 1318795951, 4144584485, 2603705982, 1273366949, 1110716009, 4026346288, 4104893234, 1485704330, 993867679, 3893686890, 3439773462, ], &[ 1413063068, 1416612149, 250032189, 2057599093, 512591148, 2867423455, 157645789, 33515858, 259890804, 2083013527, 2993123902, 3443423003, 2587947916, 2060570216, 358183429, ], &[ 3771316904, 1123102423, 3617951287, 3593485506, 3547215643, 4279031677, 3253560754, 4217820186, 342159470, 3956944812, 4058756711, 3961349923, 734903752, 3497757471, 2783111581, ], &[ 560210975, 3955544118, 1525693335, 2423056590, 1672468134, 1425293729, 3576282506, 2808604793, 2173831628, 3419991459, 1679121946, 1623263180, ], &[ 269931918, 1859534151, 1418011147, 3930467901, 3120401510, 2878732263, 2440621113, 3698526898, 1960607269, 766485754, 1276737094, 1400250704, ], &[ 31094149, 3099789406, 924340153, 1040795176, 864813453, 1273500430, 1433881359, 3857073234, 725256613, 302279104, 1991322247, 3304275709, ], &[ 1816819354, 1423518943, 1640383514, 2897037119, 3299791289, 2007192829, 3211337188, 141201204, 2347531699, 2806328153, 4130308450, 1398383850, ], &[ 2476191277, 2109850628, 475699680, 1695888498, 997959785, 3844200037, 3615832345, 3189739607, 4090633814, 4172440182, 2429164332, 1687921897, 3000987025, 227266471, 1, ], &[ 4293289930, 3312097786, 3225023610, 1814982734, 4123961773, 3202664630, 3288402967, 3423618017, 2648236802, 1235962392, 3785214889, 4142071340, 2656497128, 2555569668, 0, ], &[ 550585132, 1958217637, 1079695233, 2070051690, 1642769243, 2223520962, 2790719352, 1102872554, 1250178031, 2079404531, 2578751592, 3643898046, 2569241678, 1399445906, 0, ], &[ 1489643928, 2454326491, 2000310088, 504396801, 1710204547, 859777848, 2758305889, 1268262193, 931603943, 2447640352, 2661054782, 1778884540, 664908352, 827512809, 0, ], ); // - large arguments // - !x11_sign first // - !x01_sign first && *xs01_lo_last == 0 // - t0_sign first // - *t0_last == 0 // - x01_sign == t0_sign // - !t0_sign second && *t0_last == 0 // - !x01_sign second // - !x11_sign second // - !t0_sign third test( 13, &[ 2327266888, 159606339, 3865198656, 559105571, 2679446641, 3007100930, 1196374243, 2596728943, 1430648584, 25111289, 3084098662, 482968659, 31861624, 1410839754, 2868430508, 2675304181, 2820971697, 8433363, 356205126, 104388181, 4288829918, 3309134473, 419097037, 2074236894, 2540543830, 4244884836, 1103759092, ], &[ 2582817524, 4164383668, 1706646291, 1800000652, 1666270692, 2628289120, 568570643, 1583069261, 439682583, 3837085850, 247464905, 3856266079, 200842326, 965872188, 2600055254, 1543566961, 1164241353, 2239343733, 1797130797, 3623500339, 1808008532, 2868955656, 564142102, 1020590314, 4158719441, 3395391357, 181182939, ], &[ 2210310100, 69043551, 2823304128, 859345289, 809080897, 120879541, 848904185, 3835017916, 4066448129, 827700778, 641878366, 728444321, 22823142, 834400226, 2533421831, 507928329, 398885658, 2332167275, 2030642299, 2377794489, 4277961295, 2703891174, 3551408972, 450706094, 3991414091, 2973081680, 2714910760, ], &[ 3640661014, 3206858101, 1737126835, 2106218066, 1425703988, 2338047020, 712809585, 1420991435, 802147205, 1773895924, 2923903580, 4180731388, 625628901, 81750990, 3245267790, 2492995722, 457141292, 1264357942, 2610553127, 4085223468, 2725553562, 3215595517, 3513268137, 4258341409, 1316871298, 2379198914, 1468344750, ], &[ 3008762500, 1175160375, 2716597715, 2933871453, 475199659, 3313171252, 201726752, 3994474734, 3542696350, 475569587, 3061861352, 2795963138, 283981201, ], &[ 4169211551, 1045673686, 3266173725, 1121123371, 2838095204, 3904211332, 2018560297, 1147750373, 444496996, 2142529574, 3971639805, 3751979387, 2535175321, ], &[ 1047770371, 1327165786, 2797828578, 2685696909, 3147360099, 2201558235, 1866861337, 3761155252, 1834270154, 2215232253, 3198169502, 1924553977, 1837870685, ], &[ 2114181245, 3857180605, 3554288771, 865294166, 1626355571, 408295120, 177441714, 1458573842, 2220915043, 163377253, 1218043108, 2602503433, 528893379, ], &[ 2717110780, 986237674, 4250650056, 1544812173, 3986397690, 3836431188, 1613821249, 2248597207, 2448784182, 2786929074, 1893569847, 1881917363, 2790152996, 3179057496, 3799013333, 237221218, 3475954500, 4281253174, 3125290097, 2813956421, 1855289745, 377172866, 3911404025, 3636398044, 3080186791, 88049640, 0, ], &[ 3505418204, 565465608, 1097112481, 3850268278, 2024670176, 2587290050, 3411014407, 245345981, 2788535930, 2809261912, 2745706761, 556134486, 3944352700, 2638013922, 4093507304, 1504147190, 2989086350, 3911331623, 2934713592, 3270681569, 2138704930, 3059900964, 978968136, 2445899049, 3968088878, 43539092, 0, ], &[ 3865656210, 3194879205, 414139316, 177501159, 2684513621, 1999012183, 2643222146, 294716300, 4274795829, 1085676658, 3215144153, 1601970312, 3171535086, 643673394, 3946671909, 4065144781, 215713465, 172238316, 2724659711, 799017611, 153635789, 429414755, 1974259637, 1237183745, 2501881650, 269223554, 0, ], &[ 858223466, 4042145127, 1530910355, 223572531, 3154483634, 1177157565, 2140895357, 1246913012, 2944555982, 1472007124, 1255831930, 1641310063, 2184842279, 2314841816, 3300111001, 1618884985, 908327583, 2089112945, 1411422173, 2387337957, 3072912755, 3289360053, 2808553404, 730378617, 671725420, 90513297, 0, ], ); // - x11_sign first // - !t0_sign first // - *t0_last != 0 // - *xs01_lo_last == 0 // - !t0_sign second && *t0_last != 0 test( 15, &[ 1698534354, 3051849227, 453937331, 3597744389, 4188491352, 1540429554, 1541686219, 53413474, 2449460985, 2817396669, 2111985345, 2509026402, 1809740433, 3289293410, 2617592565, 2791033656, 2892380542, 4279121468, 1127688708, 1053029299, 916223848, 2015034641, 342194872, 1618165570, 3500431510, 192527413, 2131355967, 3029734551, 2974882323, 1660068342, 2973244676, ], &[ 1838750278, 66304311, 2535657427, 2850224201, 698579880, 1262199901, 3281530768, 2112263091, 2707934779, 1567684797, 1075812175, 3518220523, 1324578919, 2267335289, 3456142629, 3821323209, 1326553164, 564294454, 4194035902, 1211624633, 4195909292, 2658461285, 789623662, 2974487150, 1275698083, 2125737295, 4192486278, 3187284022, 88896961, 2297316271, 3463163938, ], &[ 3818564698, 3079932038, 3482135970, 684071506, 1279597152, 608056186, 4111845555, 4244378225, 1830629760, 3169670996, 2225259632, 2264284180, 3411037700, 2316989665, 4067022578, 3527348537, 1977664147, 2506129832, 2221226065, 1330889781, 1701021791, 644923460, 1849689221, 2715236311, 2773306484, 239859281, 3230697771, 19267319, 558009472, 1404018120, 3728834892, ], &[ 1670192276, 1652365370, 735393172, 511768757, 2457280859, 3609810335, 3935660653, 1797012973, 2672222932, 1933650427, 649516978, 512827590, 782690911, 2062492600, 2388214063, 3703253089, 904911621, 3390829428, 3844496615, 3067716449, 2596709309, 1917646504, 1265079680, 3900449910, 367095064, 999066040, 1909678899, 1128678763, 1656559628, 4266623984, 3645416988, ], &[ 1921432021, 3518700209, 2079139530, 1137029652, 2300568548, 1222502019, 4223478985, 2972106290, 3031541529, 2100809044, 1022823954, 194891273, 3689971092, 3296679225, 4094754776, ], &[ 948939782, 2806265501, 2304000452, 2075826159, 909827325, 768415732, 2455484163, 1934928621, 980278935, 2767893850, 1683388302, 1684144848, 3942412863, 331912133, 3187438755, ], &[ 1356019384, 2887360290, 1007932454, 3678465615, 2580178110, 3043732489, 3324841406, 937504067, 386593536, 1673041889, 3131783437, 1641423898, 4040080328, 3081806329, 1375763815, ], &[ 1047656638, 2177659443, 4241187176, 2747048355, 1596389859, 4248315455, 3794436052, 415309719, 1967342941, 3004037899, 374134042, 1698070105, 2693572544, 3158142963, 4229995607, ], &[ 960652810, 221555597, 2254803219, 2541562745, 754445106, 359755753, 480947080, 1224152909, 4273400475, 2309775298, 69810482, 2561255677, 3113057442, 3555394132, 2689777384, 3342925543, 3147365260, 135644488, 3684637040, 3040946646, 1628023293, 4023411971, 908469819, 409304848, 3324164633, 1421103084, 368154340, 3701822194, 274487004, 3602643412, 0, ], &[ 1997266656, 4144548866, 3822293605, 3926602038, 1609713691, 2892681355, 3749833208, 2219312564, 1687251603, 1588930279, 710521538, 1644589528, 4054199977, 1672634472, 3997104967, 956657984, 1345800224, 3871498877, 1120533029, 4151694583, 3146989749, 3919396264, 3231441052, 3162857783, 2091524393, 124782745, 1890937176, 4230835488, 2323009602, 1051495796, 1, ], &[ 2429170498, 799964546, 2388325391, 317823710, 1840557881, 1282801560, 3546799442, 457834840, 566997058, 2439965867, 3515007146, 3574214064, 4144082196, 3712070930, 4088900464, 931383261, 170089945, 3405025888, 3812686020, 3504707725, 3656419747, 3267430265, 3757212521, 606804174, 1643444794, 1555142733, 2148558239, 3200013733, 3246813347, 347461213, 1, ], &[ 1131485172, 3765288921, 453666926, 1551065789, 1216395236, 2385231809, 2742879582, 2426027378, 4167822390, 2229883144, 4228139351, 1293005830, 2665193524, 202666761, 3531978819, 2231355982, 1235148096, 3915389935, 1798246474, 1563880136, 2945683561, 1359457669, 1027112316, 3946769090, 4219178471, 794179363, 621594377, 2736938672, 401053543, 1075392661, 1, ], ); // - x01_sign first // - t0_sign second // - x01_sign second // - x11_sign second // - t0_sign third test( 13, &[ 1025572927, 4037308532, 206447616, 1333004461, 2310395791, 2869951650, 3992227745, 2130697188, 3157273254, 1749550525, 2868602361, 3060642701, 2426631225, 1974455379, 2987014830, 3508635696, 4024076244, 1755792892, 787921452, 4166340149, 3450397006, 1108082683, 457400481, 879113144, 70830365, 2916933914, 2341310905, 851535845, 216319323, ], &[ 69731978, 32563822, 946916236, 4016159116, 1224868021, 1718595702, 3605404890, 1865781628, 1881971935, 1029571366, 841091130, 1677586018, 810666231, 2272746683, 422109939, 1896472571, 3472541307, 1431848293, 116371044, 608472959, 213411238, 4154745720, 3801332950, 4224350156, 448206049, 1568183327, 3637228341, 3718344479, 2263647818, ], &[ 3460082903, 1733690143, 3780228761, 375677842, 1691069946, 689934922, 2437077094, 3214349377, 2429121920, 653102152, 649867420, 921104070, 4125433869, 2564034244, 2631897297, 1501813458, 3052965366, 2782742208, 4166256185, 995218213, 2136996300, 710550319, 2748268062, 846266401, 385079156, 4270529993, 3575888617, 1142776416, 876703144, ], &[ 3175747111, 594393429, 2604257881, 3289051141, 2317754576, 2939871916, 3748706204, 1013852187, 3343723329, 930022353, 505449760, 486033689, 320591743, 2258238434, 731770059, 3003208735, 1775573735, 3729639165, 3460733502, 3012496005, 1974364986, 642896119, 3342553315, 3822794210, 229391052, 1989115715, 2908530532, 1629235212, 297906894, ], &[ 2771639655, 2551822689, 1209354903, 2178693592, 1193377488, 793947593, 1366547443, 2939017203, 963848668, 851106223, 1557851261, 997940551, 2665723642, 1647387186, 2335120168, ], &[ 500011960, 1984266544, 857628644, 2215374614, 1925463875, 3051446098, 614991784, 3952563722, 3226462656, 3978687345, 2589261427, 3942462520, 1207531315, 1120805743, 1003360645, ], &[ 451008257, 2688612018, 4236929273, 890846394, 3566713276, 489065477, 715681827, 3122623659, 3596792199, 1985137091, 2004754993, 1883145970, 1355971815, 187148563, 3883316291, ], &[ 1364526373, 1859255461, 3407839641, 1532219679, 3952961366, 1871608475, 4041336906, 3915677605, 4046491136, 2645312057, 1120032684, 1046405474, 1502799372, 4217018138, 1023990345, ], &[ 570058979, 1182257372, 2005332174, 4070895605, 782477793, 360549018, 4128785555, 3018190268, 2520343653, 2142831802, 2730358685, 1347549043, 898050628, 2236297907, 3902264192, 3422936759, 3756013281, 352639804, 1061655526, 1986719339, 1128230524, 2860027389, 1088162212, 2410209429, 3802902058, 2977799885, 3237963571, 2052297093, 0, ], &[ 1879768634, 2114652211, 1774713818, 554539813, 3731694105, 2702797297, 2844034165, 2300392570, 1941578090, 3901846543, 983591421, 898885286, 822227747, 3851095686, 2719131109, 3757259511, 2102411795, 1640921620, 3665191858, 2874213628, 2733705524, 3691904983, 3823452407, 1169915867, 1621234879, 3630743707, 3478309891, 760168923, 0, ], &[ 3001545896, 250983613, 389728947, 3814529625, 1132206990, 1065795545, 2212114490, 2023039590, 3597610210, 1780520334, 3734977828, 2468915322, 4140659688, 115504217, 819490125, 2708811829, 3384020868, 1515546393, 3633787370, 1821986409, 2218993449, 3207510568, 3670555307, 3845772841, 3486603021, 1022756175, 2686130697, 2532811595, 0, ], &[ 2918481451, 3610609934, 2847451215, 2220769302, 2338571396, 2165440207, 147236177, 3730198517, 3208724339, 649659344, 1519241706, 1867099736, 1460711278, 2220689669, 3279748484, 1549511341, 227389699, 855766629, 3771440986, 3432825737, 1053106079, 1117588071, 1313153141, 571072082, 2914006120, 3516294505, 1320473469, 1040189722, 0, ], ); // - !x01_sign first && *xs01_lo_last != 0 test( 10, &[ 2010512066, 3816652533, 3172500500, 565989349, 3299472792, 2270934281, 1434273491, 2883068162, 1560071521, 2704546576, 4072612274, 1051271061, 3502419446, 355770508, 10573273, 270934222, 2810553666, 2643486939, 744991576, 1870415987, 2808955936, ], &[ 465514465, 2659174522, 3761352398, 3377965188, 1124434853, 3313355157, 619366950, 3258308994, 2397177830, 4225454449, 3612285332, 2249675933, 913650729, 1455947505, 2849031252, 3527524335, 2078373570, 3478300565, 3188941397, 3478789236, 3675330696, ], &[ 1404705627, 2788199838, 3229806456, 2206730708, 2050218206, 2991653989, 3066690310, 3453635714, 3845109791, 627857052, 3843810702, 1520846308, 2495828552, 1637354383, 2549944931, 3600368060, 108395402, 3341126373, 947408628, 2185962205, 1308735610, ], &[ 1053200638, 3763337935, 4268597333, 3193422669, 3607631108, 3846186640, 1111342197, 552132609, 1307213459, 4257590159, 1367177524, 4201506028, 476759064, 680921272, 2519538412, 238268545, 631677622, 549510100, 771370867, 3109499678, 1448324944, ], &[ 3267186431, 1424299202, 1039441915, 934588642, 50593817, 2147729982, 1547157070, 1504136284, 1637263862, 4122900145, ], &[ 3236915806, 1590507024, 3040977659, 1225520269, 2190057676, 3504088852, 3648192167, 1810940202, 83552157, 2321737355, ], &[ 4225004158, 590791745, 643591931, 3221398002, 1827972871, 1242243388, 2513726409, 1495850896, 4192093161, 50221236, ], &[ 2036607814, 1957760917, 1453625187, 3689677164, 3487789049, 491100324, 1044724096, 3399811921, 4055989690, 1295009692, ], &[ 3263538684, 120256485, 4060593063, 3438619735, 3929215534, 2588618000, 2277735492, 1072816982, 3840198566, 1043147899, 1235395843, 4200415399, 3035243806, 1304983761, 3872141601, 1404040725, 4044445427, 429312851, 3176929590, 2645604084, 0, ], &[ 4122626498, 107203592, 3628216803, 2047112948, 2210020383, 4096415682, 1367835443, 2351498305, 4206740014, 996512353, 1147432853, 2660487268, 2975278601, 828643899, 3534602756, 3189739581, 1167342346, 2278425545, 830131806, 2736051400, 0, ], &[ 2978640553, 1655222107, 3504154601, 1909395468, 3162278697, 2260916194, 3267701344, 1089677643, 751892566, 4225581520, 2977844572, 882459562, 3829381149, 4213372565, 1864175453, 3748132665, 2980365850, 1250882260, 3505860930, 652487710, 0, ], &[ 3447523550, 464011238, 1942725626, 1838669852, 3904733671, 258179587, 3703737903, 1567067340, 3691418914, 1104958587, 1817293529, 2218949245, 4009018118, 2970219724, 3485275615, 2079452863, 3685497725, 785093512, 267920582, 1623141509, 0, ], ); // - x01_sign != t0_sign test( 11, &[ 105108810, 2939008753, 43370164, 1242908972, 1159070628, 84952645, 4165954274, 906659711, 1019556239, 2534013318, 721285587, 1325925355, 1632336316, 4096108923, 1763507067, 3809084118, 2331120351, 2754738494, 2103185448, 1244905580, 1907939448, 2609958778, 730167872, ], &[ 2265464388, 1834541318, 2372682679, 3313972430, 3918258678, 2394770661, 1037415216, 274650728, 3739985994, 2108171684, 2199795287, 566429532, 1157864107, 2882221652, 910859296, 451698206, 2649007716, 1415208273, 2646592820, 3034704049, 2120666349, 979747662, 322674205, ], &[ 3874939837, 1233304929, 106185835, 37158351, 2802916915, 3304535373, 696577680, 3544731437, 3157476288, 1443616905, 3457867645, 4024841761, 4062836214, 2279777825, 1482825076, 4078337234, 3264521275, 3344925347, 3161366177, 2196844487, 898054831, 1438581672, 3352145698, ], &[ 1849881721, 2092152070, 2177899750, 288752532, 3618364405, 4141821358, 4158419895, 2146161307, 3308429556, 282226456, 2214705611, 146486422, 1226466729, 2012446110, 390251911, 3095301941, 1935278338, 1226998912, 102355086, 2004958092, 1379648599, 833731447, 3784213054, ], &[ 1615644044, 2866597055, 1417092926, 358845179, 3417066108, 3643757328, 143514487, 3323797767, 2638762718, 3254012295, 3018153021, ], &[ 344398095, 226628832, 764911662, 2701340611, 2699247769, 4219726262, 242800476, 2930885037, 990361216, 3569632382, 93961188, ], &[ 129918839, 2214278271, 1283256165, 2817801381, 2615176815, 4126216685, 3082478432, 3280512502, 1853758032, 2634521780, 4223054084, ], &[ 2590519092, 2716288017, 4272214574, 3155523983, 4104711693, 2762266943, 2745407059, 2324276365, 326739968, 523560569, 396448235, ], &[ 3666666516, 547769313, 592311112, 2965277691, 3689426122, 853080706, 1356550839, 4168566128, 1148520078, 939171181, 4015917617, 683222651, 4090232802, 3632973858, 1439963708, 1600913535, 187292997, 1577612527, 1212140599, 1900670851, 2445225960, 2669823530, 0, ], &[ 1687083814, 3698143323, 3751827194, 3866919242, 2549527161, 4010635967, 461515118, 2688244606, 3320207170, 3619767327, 434459238, 4066444037, 3805779605, 3312610610, 735569613, 11746680, 3083700477, 155975832, 1514885535, 1758738984, 2620267716, 218832355, 0, ], &[ 3131789211, 3199129533, 2920949518, 53796216, 2859826242, 1820398479, 3973031721, 2637151743, 3165657662, 2168050566, 1715646418, 2044422416, 1930311216, 3380875453, 183533660, 2431952327, 2641905274, 4032322429, 1801301919, 3668108775, 2977500729, 312563773, 1, ], &[ 1292086439, 3252628865, 3795724813, 3949296317, 3955675466, 2439424685, 4209245455, 521673263, 3357923169, 728386653, 1761881489, 2103645314, 4058013613, 1659506293, 3599632745, 96485170, 2801208662, 1691699790, 2077775599, 2126298157, 3250670933, 280076983, 0, ], ); // - *xs01_lo_last != 0 test( 14, &[ 3187643652, 689861248, 4104971615, 2655959233, 1806333930, 2946646526, 716445782, 1855643090, 2911585605, 2840897284, 772165124, 4249869367, 2223216112, 535376700, 620340444, 1645897591, 1333985741, 730570397, 4160730534, 1246271990, 1725573135, 352253863, 1262570932, 1984889896, 2956051954, ], &[ 3195311878, 3038033431, 2773970346, 1168697958, 2813281967, 746268626, 2691595086, 4097287295, 93455850, 492512747, 2710035977, 1223679950, 3946316915, 3578566691, 2992317089, 3174913905, 2131559101, 1331916743, 3949213449, 80715282, 158737627, 2988488283, 2028980419, 3830004661, 250424958, ], &[ 2536403826, 384848984, 1774521292, 2718320818, 310873769, 2046298166, 3228810082, 1178726899, 1925709392, 178731159, 2832365355, 2836635324, 193074416, 728452613, 3469205214, 1514937172, 3814853496, 2161355055, 886569678, 4161288761, 2889870661, 76946453, 1878702060, 1850975782, 1627735969, ], &[ 1725052145, 898802704, 776971836, 1219924401, 4224517976, 84598208, 2148547128, 3866703857, 1192216635, 3270964370, 3470989137, 4065537602, 3771846191, 3811480941, 4062031618, 3552276638, 1926982962, 297558461, 1000365546, 1422440944, 3161036166, 519129014, 2412823237, 2742512283, 1294289799, ], &[ 2124565348, 1850594425, 684081640, 3059091438, 3756365771, 3723911794, 1430887131, 2186106443, 1678377466, 1963700876, ], &[ 1786516080, 1799763022, 3244164991, 2583605118, 2016537122, 396228546, 1776124622, 3149228799, 3618737851, 3722388678, ], &[ 2119342743, 2442803683, 2913523155, 2290813344, 2341544084, 2607906759, 3903931010, 1623427068, 200668227, 866036225, ], &[ 154537600, 2783369274, 2784871905, 2923414066, 238748138, 894157397, 425890999, 2023402367, 2708989084, 1773914772, ], &[ 714150426, 747474047, 711763591, 2505815901, 1931970168, 1830915645, 132011662, 1641495062, 3649937934, 1578564850, 2879358541, 2256534044, 375624512, 402134451, 124437205, 2656206024, 3918226432, 2934327023, 2861387419, 1259632526, 168082530, 1906995676, 1276986866, 966360812, 0, ], &[ 2584563904, 501423603, 3179309343, 2650015179, 1354929902, 930009290, 4239032359, 315773096, 1219190592, 1141774901, 2074216575, 279450192, 2450874439, 247131610, 26955632, 3117135685, 2632739337, 2367699203, 1269501214, 837130129, 824399760, 1192414122, 2569424753, 1942029336, 0, ], &[ 2166600367, 3206417308, 2873245177, 3181806685, 47762280, 4077132431, 3414741771, 595567128, 1650380454, 3351739639, 1204748131, 4239748557, 4216796226, 1580325602, 2295006359, 928145182, 2501406243, 2685614796, 1481907821, 3500619179, 3653788019, 2099044319, 251730683, 1101601776, 0, ], &[ 327036000, 3129689357, 722252402, 3256719743, 762583270, 1730383711, 2418392723, 3837009731, 993829843, 531209884, 2056099111, 2266372736, 1988906408, 2154603398, 2683386624, 826004386, 3819045504, 3703296261, 2407207875, 3346505456, 2182410563, 1915488498, 41659158, 2205564200, 0, ], ); } #[test] fn test_limbs_gcd_reduced() { let test = |xs: &[Limb], ys: &[Limb], actual_out: &[Limb]| { let x = Natural::from_limbs_asc(xs); let y = Natural::from_limbs_asc(ys); let mut out = vec![0; xs.len()]; let mut xs = xs.to_vec(); let mut ys = ys.to_vec(); let out_len = limbs_gcd_reduced(&mut out, &mut xs, &mut ys); out.resize(out_len, 0); assert_eq!(out, actual_out); let gcd = (&x).gcd(&y); assert_eq!(Natural::from_owned_limbs_asc(out), gcd); assert_eq!(gcd_binary_nz(x, y), gcd); }; #[cfg(feature = "32_bit_limbs")] { // - n < GCD_DC_THRESHOLD // - xs__len > n // - !slice_test_zero(&xs[..n]) // - !mask.get_highest_bit() // - x_high >= 2 && y_high >= 2 in limbs_half_gcd_2 // - x_high <= y_high && (x_high != y_high || x_low <= y_low) in limbs_half_gcd_2 // - y_high < 2 first time in limbs_half_gcd_2 // - !limbs_half_gcd_2 // - xs_len < ys_len first time in limbs_gcd_subdivide_step // - xs_len > s in limbs_gcd_subdivide_step // - ys_len > s first time in limbs_gcd_subdivide_step // - xs_len == ys_len second time in limbs_gcd_subdivide_step // - limbs_cmp_same_length(xs_init, ys_init) == Greater second time in // limbs_gcd_subdivide_step // - xs_len != 1 first time in limbs_gcd_subdivide_step // - ys_len > s second time in limbs_gcd_subdivide_step // - n != 0 // - xs[0].odd() // - n != 1 // - y_0 == 0 // - y_0.odd() test(&[0, 0, 0, 1], &[1, 0, 1], &[1]); // - n >= GCD_DC_THRESHOLD // - n > s in limbs_half_gcd // - n >= HGCD_THRESHOLD in limbs_half_gcd // - n < HGCD_REDUCE_THRESHOLD in limbs_half_gcd_matrix_reduce // - n < HGCD_THRESHOLD in limbs_half_gcd_approx // - n != s + 1 && !mask.get_highest_bit() in limbs_half_gcd_step // - y_high >= 2 first time in limbs_half_gcd_2 // - !subtract_a in limbs_half_gcd_2 // - x_high != y_high first time in limbs_half_gcd_2 // - x_high >= HALF_LIMIT_1 in limbs_half_gcd_2 // - x_high >= 2 second time in limbs_half_gcd_2 // - x_high > y_high first time in limbs_half_gcd_2 // - x_high >= 2 third time in limbs_half_gcd_2 // - x_high != y_high second time in limbs_half_gcd_2 // - y_high >= HALF_LIMIT_1 in limbs_half_gcd_2 // - y_high >= 2 second time in limbs_half_gcd_2 // - x_high < y_high first time in limbs_half_gcd_2 // - y_high >= 2 third time in limbs_half_gcd_2 // - x_high <= y_high first time in limbs_half_gcd_2 // - x_high < HALF_LIMIT_1 in limbs_half_gcd_2 // - !done in limbs_half_gcd_2 // - !subtract_a1 in limbs_half_gcd_2 // - x_high >= HALF_LIMIT_2 first time in limbs_half_gcd_2 // - x_high > y_high second time in limbs_half_gcd_2 // - x_high >= HALF_LIMIT_2 second time in limbs_half_gcd_2 // - y_high >= HALF_LIMIT_2 first time in limbs_half_gcd_2 // - x_high < y_high in limbs_half_gcd_2 second time // - y_high >= HALF_LIMIT_2 second time in limbs_half_gcd_2 // - x_high >= y_high in limbs_half_gcd_2 second time // - x_high <= y_high second time in limbs_half_gcd_2 // - y_high < HALF_LIMIT_2 second time in limbs_half_gcd_2 // - !skip && limbs_half_gcd_2 in limbs_half_gcd_step // - out[n - 1] | ys[n - 1] != 0 in limbs_half_gcd_matrix_1_mul_inverse_vector // - n != 0 fourth time in limbs_half_gcd // - x_high >= y_high in limbs_half_gcd_2 first time // - y_high < HALF_LIMIT_1 in limbs_half_gcd_2 // - subtract_a1 in limbs_half_gcd_2 // - y_high < HALF_LIMIT_2 first time in limbs_half_gcd_2 // - out[n - 1] | ys[n - 1] == 0 in limbs_half_gcd_matrix_1_mul_inverse_vector // - x_high < HALF_LIMIT_2 second time in limbs_half_gcd_2 // - x_high > y_high || x_high == y_high && a_low > b_low in limbs_half_gcd_2 // - x_high >= 2 first time in limbs_half_gcd_2 // - subtract_a in limbs_half_gcd_2 // - x_high < HALF_LIMIT_2 first time in limbs_half_gcd_2 // - n == s + 1 in limbs_half_gcd_step // - mask >= 4 in limbs_half_gcd_step // - x_high < 2 first time in limbs_half_gcd_2 // - !limbs_half_gcd_2 in limbs_half_gcd_step // - xs_len == ys_len first time in limbs_gcd_subdivide_step // - limbs_cmp_same_length(xs_init, ys_init) == Greater first time in // limbs_gcd_subdivide_step // - ys_len <= s first time in limbs_gcd_subdivide_step // - n == 0 fourth time in limbs_half_gcd // - new_n != 0 in limbs_half_gcd_matrix_reduce // - !x_high && !y_high in limbs_half_gcd_matrix_adjust // - new_n != 0 first time in limbs_half_gcd // - n != 0 second time in limbs_half_gcd // - n > s + 2 in limbs_half_gcd // - n != s + 1 && mask.get_highest_bit() in limbs_half_gcd_step // - limbs_cmp_same_length(xs_init, ys_init) == Less first time in limbs_gcd_subdivide_step // - n != 0 third time in limbs_half_gcd // - first zero in limbs_half_gcd_matrix_mul_matrix // - second zero in limbs_half_gcd_matrix_mul_matrix // - ys_len <= s second time in limbs_gcd_subdivide_step // - s != 0 fourth time in limbs_gcd_subdivide_step // - ys_len != 0 second time in limbs_gcd_subdivide_step // - mask < 4 in limbs_half_gcd_step // - new_n != 0 first time // - limbs_half_gcd_2 // - mask.get_highest_bit() // - y_0 != 0 test( &[ 4197577227, 3663616140, 2551363557, 471855676, 1132453243, 3890478103, 3255658039, 924933869, 1182514876, 3443542006, 1628670028, 1920607761, 1774928803, 698481201, 1688346100, 3912816434, 1546494740, 295495534, 207209302, 1228953098, 3286562513, 2448096226, 2547931780, 2100456764, 4196096572, 2722413368, 247913388, 3316902282, 60763307, 2236362858, 2725594164, 774854500, 1708955617, 1129631186, 2093339374, 3603997370, 1314390085, 2641774231, 385916035, 2355828959, 821901122, 458162478, 2603441028, 1665224323, 2479737003, 325263924, 3583373830, 1314852315, 3062488937, 2409141051, 2802944956, 1176409253, 4206372227, 3264669278, 376728881, 3979228915, 789107765, 1384935912, 2580449282, 3943579021, 1561210927, 2058485109, 2277329329, 3961162387, 2853000821, 2810633314, 3958004542, 1042177900, 2041876084, 2531779261, 1110199836, 4268607687, 3910301281, 2843809243, 930485055, 309142224, 2144761027, 2416055325, 3266084990, 2447991430, 2443964826, 3786182453, 2724967444, 2929403702, 2871781906, 2093610692, 2665818776, 2885572011, 1023583045, 388434237, 3383760566, 3331268852, 812997613, 743229208, 707412010, 2045807268, 3029838557, 2734070773, 1201494085, 2013003250, 3352629986, 2121723344, 2606274703, 446904615, 1986390279, 777681916, 850787414, 998620529, 3430750455, 4223290015, 850807722, 3597579048, 1953183408, 2598401455, 4174123707, 2094682680, 3126686508, 741312051, 1249776706, 3394903770, 1488538657, 86039141, 1122597620, 4088204860, 1965673179, 3854858790, 1805056514, 712813144, 2223549448, 3340696011, 1057241621, 4123508209, 1178122500, 3345161830, 1643843465, 3443634290, 1183490760, 3948287560, 1351208937, 1585302010, 321331177, 1982899829, 4207584480, 428023286, 313173943, 1893554339, 3657870602, 1184563157, 2577756042, 3633915258, 4107506336, 2000538440, 3462275636, 905594775, 2288056884, 2174527929, 1967515771, 1889360380, 3647702195, 2766306052, 1692805723, 2547117089, 2806372808, 1868864235, 377724386, 2108963424, 1243470944, 3419076435, 215621577, 4277714044, 1847653420, 1364769655, 3409308990, 3221049591, 727661675, 1355876888, 477454154, 159184771, 47758267, 82226374, 173939358, 3989288267, 882358143, 314672149, 241143075, 1276781232, 3729530695, 4062922154, 882397039, 717181562, 1487490701, 2348085968, 3844176796, 3858520706, 2303777194, 1570281243, 701612807, 1685259689, 44118858, 2403065948, 2475839209, 4243425343, 2409356427, 3602873673, 2794543251, 1879804284, 986610444, 1780607155, 2709668878, 3714165156, 3474383994, 52876951, 2738151673, 3272452228, 157949197, 3388390384, 1867287032, 3397657263, 893351542, 359080279, 1867186583, 2633080366, 1691644564, 2228425159, 205919408, 2674325620, 408159999, 2614176370, 2954808008, 4288814065, 592989283, 2421568051, 3947678068, 1076048985, 2725991063, 1466932877, 47765783, 2096755893, 3871926112, 3067385837, 1115438999, 673485739, 4051915345, 3287777679, 3432949036, 712556260, 2115195072, 1163581657, 717872497, 1372142050, 1296789715, 3248464426, 2010337977, 1022298124, 4097244827, 3132735945, 1590029541, 1952666134, 3738758275, 795022630, 1022963383, 322333376, 3927893537, 1123308885, 3926676584, 110023661, 1847201588, 3972030290, 1877137386, 2340701232, 2680282095, 171364221, 1255189251, 4206413144, 3146670074, 2595432946, 2123584779, 421107554, 1661340820, 1717955211, 1093855779, 2562116708, 311124173, 1286538456, 784915601, 2787458377, 2909859896, 2079504712, 2482552290, 381311010, 4164814891, 3498767523, 1871402912, 4280107119, 3555212136, 4263072354, 2428360919, 4030822435, 414962043, 2110229154, 3145804625, 3419521350, 2300309736, 1037962840, 360477135, 2761975814, 3570812469, 2141362836, 3744698030, 2917828184, 1604822798, 524785135, 4123189923, 306254809, 2907418601, 715269380, 2880366359, 85178201, 3315366581, 1234064887, 2261417810, 740136577, 311877843, 916858922, 701414307, 2440960632, 2877171070, 832859154, 1906376412, 2470726441, 746564647, 3169727501, 3847690619, 2569989652, 4143797285, 1181804091, 3467101578, 1620737185, 798590631, 1102046391, 86799227, 1011686392, 2365540922, 1437914259, 3977803079, 2484908631, 3183729029, 770778157, 2110032689, 642819790, 3783384202, 2203826388, 179388270, 3069155346, 2279937873, 3949687834, 2292743729, 1695844312, 1519061556, 333473276, 304895978, 2399722902, 2408889893, 4198515797, 1815311964, 3633226566, 1221066756, 2016659596, 1969286056, 1186325182, 1718972725, 228738772, 2598964902, 4168009255, 2340771410, 3236251687, 3295756396, 359898616, 748792865, 2815036617, 2294605685, 2576581376, 3104446059, 1374922466, 3229588626, 1342195213, 4121614180, 1287499457, 1644513681, 2251892498, 3519911253, 3676415503, 3642198693, 764265217, 3084097378, 2745050223, 3246393306, 561565268, 961468834, 3209498589, 2760753568, 27068759, 1509048774, 1453964033, 1331717633, 2158694102, 1233260646, 2709419591, 177106547, 2429674784, 1301711456, 2208920832, 176199715, 3161955920, 3374145530, 4247833566, 4210175938, 2667521985, 2158406637, 28032585, 3422529443, 2403124753, 4248809640, 1432019389, 2720502195, 3698731935, 3697762717, 3038810720, 73235983, 1930366289, 1889267718, 1024383025, 3630767897, 2664806680, 1701068479, 3104152545, 3126610581, 1945171628, 2107750861, 1705151590, 1384917050, 1013720645, 3504778715, 3696436857, 1705707415, 2189842908, 1689236637, 1657303695, 544592080, 1136857424, 824561482, 2369780064, 2472849354, 2717401545, 2421800924, 580975041, 750461869, 3727051247, 3077843833, 18610721, 194041714, 1077076049, 1259434033, 1763428865, 2241079119, 2783260484, 305088684, 4127815512, 736813644, 540809689, 3159882452, 1825555986, 1501660759, 3053878326, 2824718405, 958691107, 1972676940, 501505940, 2507376271, 4221542679, 7397642, 335120812, 4137134683, 394428968, 867251752, 156156583, 3806282517, 3663693413, 1066638741, 3888387987, 3416832624, 1874236937, 1816284001, 24943821, 2444851827, 2900828566, 2539594150, 779015020, 2409648256, 2933935060, 3781965704, 2113602755, 1850649100, 344087483, 1315113853, 3810878395, 2922986247, 1124979158, 1254362509, 2961155811, 567171845, 1368984368, 3708291355, 3083282828, 1452928286, 2981316093, 3064523290, 1479238797, 2292333655, 2448998592, 3524304101, 3649979636, 68492449, 1954531957, 2750371018, 1841894757, 1097795246, 2048976053, 3845300136, 2399041467, 2960591765, 1149499376, 625651164, 2037776876, 164166162, 2380013720, 66608184, 3818619585, 2131700282, 502477679, 2053801901, 2925841131, 1028579949, 762321931, 3017484607, 2336518362, 2067352515, 3383243930, 3093911248, 1575534888, 4087803856, 1041068290, 1614488293, 3321708937, 1309929846, 1384017125, 1090379238, 439291539, 3162665576, 344261203, 3404316428, 550149101, 2430715962, 2274647103, 1656669548, 1081997280, 1328444417, 2031945767, 1473781932, 2837006571, 1533898454, 3338843219, 3838110065, 1262509474, 3527801284, 2579686530, 3569205777, 4100363249, 2105425082, 2234328532, 2748351804, 2673483805, 3924474224, 2636212581, 3463412678, 4098352143, 2368424540, 4175082715, 2039046172, 3243053164, 1220737144, 1748690383, 2080583256, 1099659816, 1135489475, 2884856950, 4192473639, 1947310046, 2881220399, 3944101233, 2762458465, 4110783623, 1673864095, 1791817121, 2629252938, 2351311744, 1835759362, 1831898034, 3637639151, 2781044911, ], &[ 2582606328, 3907176038, 1869269403, 1460626031, 582046080, 4111410419, 2516532417, 146794403, 430764753, 1289757806, 833414363, 1159861655, 1855686035, 660114073, 2678166363, 976180952, 3948114536, 2765729676, 1405860081, 390581044, 2452693248, 166981518, 4119389957, 2838988971, 1280548287, 2735105611, 2230034237, 807044950, 2753901414, 3377733072, 1260163723, 2906031321, 1160378830, 14255505, 2306821236, 1827788545, 1803661748, 3344014911, 358752723, 3659821753, 1669317560, 230363172, 1671886371, 1424632611, 2409163050, 508495152, 2520039856, 3298638732, 1428088953, 2701777018, 3798098801, 1335576077, 2246521165, 3958581687, 1600454442, 3907674130, 3548795039, 3826552611, 3725833438, 2551041161, 2709616429, 2354699408, 3126481426, 3099474439, 937375512, 2352825782, 1243847506, 1747475903, 233022035, 728638168, 2156419178, 1739901706, 842209461, 1678526634, 4177514773, 1117076123, 2650916066, 3124223161, 1696818673, 1436772296, 3437185289, 261500205, 992897074, 4122050997, 3281707495, 437035780, 764393933, 702695215, 20994502, 1300788043, 2485247663, 2129017620, 1314245779, 2080540901, 3382431782, 4177690980, 496213991, 3620296923, 45820436, 824665660, 1249390567, 2880218577, 793755363, 2099510489, 1127291309, 3018724734, 4045529792, 3787034562, 2447184228, 4231165855, 2543665948, 2685844279, 3687498369, 2465827535, 937827718, 3493198617, 1112432160, 682701349, 2407287012, 261540535, 403665586, 739072430, 4114763090, 276463615, 938788455, 3393306569, 493459877, 2513680357, 229914576, 2765762116, 3809089681, 1975260832, 630837582, 512373818, 2415638589, 816524198, 926812996, 2919108012, 1777763031, 2420059151, 2303215774, 730440645, 2590700033, 4251535370, 4205174050, 4119494394, 960682558, 2886343983, 3540930563, 711941431, 1626586284, 981652789, 2327139618, 626401545, 612995811, 1953752764, 2899519720, 1408949156, 4290924666, 3997643096, 1422846953, 364233241, 2659284800, 965784531, 3136185596, 1794737991, 1004877728, 3355875944, 2432964630, 4193048101, 1130684469, 3045267236, 1286642177, 2756498771, 932256612, 961567406, 1201162315, 1773420101, 2567717098, 709597428, 452677858, 4284511418, 3021868094, 686834336, 268204656, 187140090, 2471076712, 144112752, 793083023, 3609314649, 1553540924, 1941459858, 94249970, 2264076058, 1658809682, 2185281448, 357602413, 2940153559, 2210448220, 1292548375, 144668819, 2795072628, 4170611652, 2951824217, 478980333, 77414522, 2542872381, 310035381, 3503531438, 2774626613, 1665526812, 1575810865, 3550598577, 2584875090, 14090765, 4084436300, 1767381238, 452463079, 547596654, 1305057780, 2372702234, 2823750152, 2615637338, 3915249206, 2017151267, 512190028, 3431028255, 1204341799, 1734623287, 965084563, 2326922875, 953678590, 2503809985, 1951017332, 2478332356, 3743715904, 3536776438, 2015910466, 583258098, 1654548120, 3876369464, 1912036404, 1854124724, 3285753258, 4239446578, 64896010, 3226676422, 709577570, 3605847387, 4233435166, 3578913837, 1305181609, 1104334009, 535007176, 3368595294, 3400831924, 2658360667, 83892703, 452925944, 1148434659, 3632651250, 2497302974, 4052931735, 2825332083, 4085939360, 2559084850, 3079544094, 4119878194, 504432022, 2083265837, 1798431512, 465950253, 2330752139, 1762670455, 4153406121, 171243945, 2564294901, 3457826969, 3997425378, 3322817525, 1219343400, 3494114736, 1472311045, 278005611, 3537646006, 1737609178, 745736375, 1744823525, 271949138, 3132324813, 2299821342, 2740187772, 1351381540, 3548063636, 1535674335, 1875773947, 1619241799, 1128793993, 1049425265, 3145446141, 3425432576, 2046178101, 1387398701, 1597786450, 1263128416, 34613519, 4163179935, 1798039392, 3111216944, 2777264082, 22483696, 1038704995, 3359344737, 3795184360, 1831084665, 228540483, 690048105, 2440634399, 801439700, 1953285894, 1885782072, 490462137, 1220610650, 87049442, 3789599385, 3845031019, 2099863453, 2821455657, 1978309953, 3224772848, 727874845, 120712817, 4094193244, 696826576, 408973252, 2585539339, 633960302, ], &[1], ); // - xs_len <= n test( &[ 1304645631, 3453605495, 2384770191, 4234662844, 193170837, 3507896589, 1570888072, 3287476780, 3273564387, 2083012415, 2738572262, 216274431, ], &[ 140631447, 652003847, 539742246, 1688191151, 622459323, 2568104193, 1918906162, 3927704678, 3061246232, 1898154381, 2239425174, 122041517, ], &[1], ); // - x_high < 2 third time in limbs_half_gcd_2 test( &[ 2504682851, 2582732736, 385625941, 2382204212, 314045215, 2050447634, 503267526, 1775048793, 3749152248, 83577313, 3954681023, 2222858364, 2002028732, 3989047480, 3329901642, ], &[2374767210, 3305948119, 2775088291, 3859016530, 6636685], &[5], ); // - slice_test_zero(&up[..n]) test(&[0, 1, 1], &[1, 1], &[1, 1]); // - an == 1 in limbs_gcd_subdivide_step // - s == 0 fourth time in limbs_gcd_subdivide_step // - n == 0 test(&[0, 0, 0, 0, 1], &[1, 0, 1], &[1, 0, 0]); // - n == 1 test(&[0, 1, 1], &[1, 0, 1], &[1]); // - limbs_cmp_same_length(xs_init, ys_init) == Less second time in limbs_gcd_subdivide_step test(&[0, 0, 0, 0, 0, 1], &[1, 0, 1], &[1]); // - limbs_cmp_same_length(xs_init, ys_init) == Equal first time in limbs_gcd_subdivide_step // - s == 0 first time in limbs_gcd_subdivide_step test(&[1, 0, 1], &[1, 0, 1], &[1, 0, 1]); // - x_high == y_high first time in limbs_half_gcd_2 test(&[0, 0, 2], &[1, 0, 1], &[1]); // - y_high < 2 second time in limbs_half_gcd_2 test(&[0, 0, 2], &[1, 1, 1], &[1]); // - x_high == y_high second time in limbs_half_gcd_2 test(&[0, 0, 0, 0, 1], &[1, 0, 3], &[1]); // - xs_len > ys_len first time in limbs_gcd_subdivide_step test(&[0, 1, 1, 1], &[1, 0, 0, 1], &[1]); // - n == 0 second time in limbs_half_gcd // - s != 0 first time in limbs_gcd_subdivide_step // - new_n == 0 in limbs_half_gcd_matrix_reduce // - new_n == 0 first time in limbs_half_gcd // - nn == 0 first time // - nn == 0 second time test( &[ 104199695, 1437842355, 3026540896, 1036691142, 2895760091, 316986459, 3848493166, 4283163139, 1409731068, 2162161861, 3180981287, 2664973704, 3129778597, 1141759869, 3423483599, 3304860181, 1499458172, 2283443318, 304208206, 3898070080, 1624380249, 4217356185, 3984965450, 1989320468, 4046024996, 290564828, 982998126, 714749497, 1256133149, 1964245093, 1989969476, 2845229677, 75994139, 1534010229, 3551668582, 437558754, 2400783907, 1104529196, 2628109158, 767576225, 3386003603, 2589581389, 3197373266, 1119570806, 2388054566, 560919780, 2181214692, 895228346, 2455964730, 1236092704, 3460190245, 2187848751, 355369047, 1999986258, 3567727382, 1691926629, 2725212068, 2592492178, 797372755, 1342659622, 1706103226, 2741335822, 683303027, 2714389761, 3546978425, 1986412131, 762213298, 2333449774, 778670753, 97719623, 581978613, 3531804453, 1122531574, 1722591132, 2538512178, 1919025659, 3171826961, 3494777585, 3878057786, 1159079409, 1839284455, 1154718578, 2665661658, 897285327, 1500853657, 2633085447, 1751356374, 3270858770, 1163694943, 3330045700, 1488678831, 3027918693, 502928061, 1337476314, 3692361284, 2178683191, 3096849964, 970332766, 1824923766, 846751495, 2918346590, 70616406, 3836757211, 2684780384, 2463029602, 3457312899, 887456732, 3244684159, 1709425071, 1650827329, 1114331473, 2300037523, 47504219, 2349860938, 514226917, 2830450926, 3649882524, 3714094143, 301323195, 4142782943, 3785993652, 866247992, 2164534671, 2737799129, 3275770468, 215424696, 4257046307, 1733065842, 2434034911, 1462340609, 3642973392, 3350853644, 4199792744, 684333086, 217713765, 3411993450, 1792335767, 4171842881, 159579156, 2430618740, 3131183234, 3163246383, 2128439763, 2401347699, 2936760275, 3236944394, 2200904017, 2436166477, 4193014474, 3613539040, 2916219306, 4261812949, 115873482, 2180021985, 4055598752, 1260608904, 2416550157, 1259155018, 1431188781, 1176329051, 2299641742, 3980571345, 1599289272, 1782362083, 3811356761, 1974756300, 533380582, 3641430046, 832768712, 672407572, 1502225325, 1016817644, 14093203, 1980541787, 1908462143, 3913154473, 724095260, 1182316086, 719426427, 75511913, 3523894057, 3990195494, 2120530771, 3562485018, 1433690638, 2518584164, 1493664787, 3968793063, 3670159139, 157980348, 1301197374, 3305985080, 3941044403, 612257166, 3771911392, 2763453419, 2718688747, 3693090746, 589991197, 498197071, 2438022286, 3991964070, 377079193, 3099592329, 3321736969, 3902471945, 2307760142, 3013676133, 3258936160, 4011810226, 1053219984, 2837546691, 1856062985, 2092610837, 91102249, 406247891, 890201919, 2559127506, 338532027, 395154770, 3275565770, 1258530084, 2939576662, 2055294057, 1883048671, 3836169741, 2026424182, 3339579277, 1542609345, 417648228, 4191728149, 2895752032, 1515160584, 278532504, 1393858866, 1730994375, 3794676496, 1670361915, 1258111291, 2422641149, 2347194379, 80193494, 2358530906, 2877787771, 1965418230, 4205347720, 2666879163, 4215296303, 2916779693, 3935289306, 3244538076, 1632052180, 4176725684, 992286325, 2739073795, 2079197711, 2797905589, 2449598406, 289423436, 762177014, 2363661744, 772167940, 2765100761, 198147685, 572172334, 3817619946, 162288540, 1223981567, 540177774, 2154166987, 2653356928, 3206160568, 1862076861, 3133558385, 474824123, 2525460202, 3924632969, 1146129872, 1432186566, 737582770, 3316793636, 3709987676, 3557072993, 567470616, 1129703040, 1521364280, 3566052322, 916273230, 2293310523, 1377033267, 1508571570, 3382970810, 2996523808, 1581520543, 2618222496, 3288125825, 2313878894, 349906863, 2219317771, 3176122714, 1013378826, 4116023745, 1921798849, 3062375628, 2736960803, 2501959999, 1510561246, 1700569625, 1652836989, 3312274215, 4195830099, 1132143254, 950525497, 2316560086, 375651095, 2664099671, 455151019, 1159444553, 4198810519, 3127984438, 2144120008, 1969060002, 562539184, 1602239482, 2852481959, 2095454819, 3210933640, 3500352077, 3422305025, 2014869566, 2974700896, 3465912392, 2040467605, 4197300028, 3591134045, 3895974116, 1820422501, 1395818068, 2660152096, 1916184939, 3260276758, 53585995, 927898271, 2259302740, 963522240, 2856612864, 3450205940, 3367413678, 3535931570, 397649639, 3700183847, 1270654564, 3500464902, 3997758233, 3130672822, 2562223359, 638317405, 3181668171, 539650504, 2914453051, 645816251, 4007289298, 3438058969, 2770073590, 864060896, 2320524273, 3692263013, 3473619051, 3882200592, 499549190, 2692529571, 1895097838, 3793943961, 3454593367, 1512683055, 852698565, 1995890144, 865090611, 609912127, 2960073872, 1078887, ], &[ 3965328483, 312519701, 3403268855, 3606492602, 1902761898, 851349064, 3139262646, 633064190, 2260801841, 3139511175, 2981429315, 570792856, 3276826258, 3740173343, 2258820496, 613809729, 241642072, 3441475901, 4294219823, 976984900, 2389777673, 4191459734, 1003327410, 1302790361, 2451013524, 2641182095, 3622343124, 2806631117, 3967790700, 581646251, 2019686780, 2032370136, 2076036058, 856161788, 3365012291, 2890451318, 2127795458, 2187590985, 4093939520, 343783955, 4242308697, 4157888926, 2564079477, 4260723333, 221747269, 2643548554, 3833528808, 1763870742, 825076470, 259966747, 1095002154, 931639969, 3831275768, 2810876375, 3231187357, 3440619698, 2434935986, 612813763, 1378882183, 2162485107, 1140428311, 3695900833, 3397094290, 4162195979, 2662618085, 3751543150, 3243820436, 3516498989, 707780244, 2079085110, 448686345, 1895725327, 2371954578, 512402760, 2522669399, 3692228697, 4274764985, 3682675544, 3852971158, 3189904769, 3141125752, 3990040037, 688067094, 4206021309, 1411303768, 751179620, 1438168058, 3448172742, 917372130, 1562060869, 515503757, 2481107086, 2276549351, 4210575064, 1210846101, 3889280108, 1149707690, 3998423549, 450077793, 3069409039, 1205057532, 4241449813, 4263835068, 777002153, 97116780, 1862501041, 4173027391, 538950023, 2024750625, 1067091172, 3975089902, 3595618138, 1162626458, 2892893888, 185770841, 2582369494, 3927002631, 3209126940, 3017762169, 3322211458, 184442973, 577978350, 564069165, 3126111172, 1558987521, 3158591140, 2367515315, 3627578322, 3638689514, 2197481806, 387613, 3780351852, 2801314434, 1919960640, 414138073, 161239652, 5955360, 4204709093, 49134550, 1616981665, 2152668401, 3606726895, 1857761242, 1299061544, 3099986598, 3846390597, 3355161875, 595322253, 2252701581, 2283337465, 675228606, 2653548638, 3430616197, 2380374646, 3784410660, 1379122536, 3178229817, 3972552968, 3447966842, 1961475461, 918042062, 1365972881, 2129295687, 2448607551, 2884167968, 3568778297, 2408690044, 469704050, 304852349, 2906236085, 2120391091, 606392149, 1797001614, 3658187294, 2116257019, 2708625014, 2498918970, 3223950057, 4105341944, 243352585, 3784332349, 522017452, 1593525595, 4137737627, 167793374, 4087606703, 344557611, 2032896579, 2593781680, 1431393249, 141052093, 2496087765, 2700336339, 516501742, 1876246139, 1822328287, 2252547797, 4061227450, 2006777028, 3501565120, 3466396566, 735894510, 255684379, 303584386, 1336037903, 1323979436, 1064067294, 3553551979, 2832942530, 1268770967, 1027134407, 545735300, 3866535246, 2986685637, 1613305389, 1267557025, 31509612, 771698397, 1878270300, 110063942, 4276370389, 3260973919, 2964940734, 1109302596, 1411099702, 4020146211, 3169853494, 2389480541, 556890992, 1074682663, 1708332475, 2658991487, 2894729410, 2296152345, 1870102242, 955236482, 2125245922, 1470432646, 1889719140, 3468723644, 35016220, 2579705046, 2403600204, 2455839109, 738153092, 361506106, 1501550475, 1570537857, 2512180427, 2079164570, 3284728752, 2525205632, 1765298251, 324508463, 4289185078, 3262124640, 590432268, 3609992720, 1056480497, 1521962672, 2902938979, 3633169769, 818640538, 3205732694, 3783707657, 1320287971, 3427819133, 123698783, 1954647368, 1478731664, 729732421, 3485056101, 3384149754, 886686555, 3524117645, 3672706053, 3467528186, 1825239229, 3605286168, 4252587265, 2476737792, 1468148598, 1767076404, 3098062795, 2235174734, 3938633722, 3377437243, 2055298570, 974103332, 1521104891, 1331281005, 3901922961, 2788866965, 1326440607, 3830433543, 2349058686, 1891550867, 289592648, 833149915, 4062577431, 300173440, 3618259462, 2437802253, 1988806398, 1196009062, 1693726935, 4261250055, 3358655485, 1354639338, 4217909066, 3173323323, 1256774815, 2873946595, 783721831, 3287664797, 1212500109, 544495281, 3943757093, 3869342488, 3580616897, 2288353173, 1381949567, 1954109845, 1071065683, 1907373154, 1605862239, 399825655, 1608845741, 1366351932, 1757744839, 2456500252, 4271660304, 2736932691, 1256196079, 654792440, 3432423047, 814117095, 3916828311, 1478775709, 2623979306, 3502313771, 1912113011, 826313993, 2137260095, 4198684443, 54736831, 380668741, 872309827, 3132896276, 1131528234, 1143308601, 528742460, 3890747269, 2898367605, 3531963195, 2576564587, 2690837364, 2676539983, 1748034501, 3722941468, 2157585074, 738387831, 161914314, 3886930899, 805359701, 84535132, 1019698896, 1024816471, 2120663635, 4600563, ], &[ 436512665, 1372743407, 342109034, 2762999440, 1801741181, 1128075399, 536773409, 2462344174, 4092132461, 1413817282, 3712114490, 446843050, 2277642284, 924335942, 250799808, 1300467839, 3708770080, 346693759, 1462440153, 2514050355, 2607744870, 572189306, 18842802, 85605861, 3453161777, 65109244, 1981480639, 1036404070, 3325202117, 858703184, 1098140435, 137595022, 1796280951, 4121604160, 927712201, 2983534703, 1277109179, 1842338521, 684621561, 3003060670, 1334445980, 3716987280, 2509263629, 1481158588, 101476260, 2332533799, 3920104238, 1799849987, 289899178, 3790057285, 3090879719, 1847908743, 2289570281, 899352588, 1237257524, 3478208269, 2864532864, 4237285852, 2021619931, 2299181539, 2990516063, 1146232131, 1906740225, 365885015, 436254990, 1572217307, 2276239798, 2938321029, 3411408571, 782341583, 245501560, 1212705343, 3987607268, 2685812792, 3162630759, 525514772, 1738934514, 4026775891, 675427556, 2638310706, 1872560581, 378254209, 3521602859, 3209772533, 2171756894, 1916654768, 464606995, 1021746380, 1509799815, 1803124229, 1626950142, 1757247127, 3463260849, 2059493644, 3328028905, 714292268, 4221410307, 3024039287, 245477866, 4111629244, 2454388273, 2288605764, 4069258877, 2417991112, 1008037684, 1584471268, 480491917, 657289197, 740153804, 3304298858, 3549803564, 3389482897, 2285883880, 3754282415, 3452581852, 1300983995, 2563854813, 3387253149, 3144283055, 4223958762, 2984826191, 3538501116, 1630274809, 3571211850, 3145706384, 119892266, 3268130561, 2893468680, 3796377730, 1313792196, 84565900, 2317626527, 1585112821, 2831830124, 3879773053, 3823642743, 260829176, 113541293, 2698035069, 1162236214, 56045023, 2572314428, 3303774518, 786546397, 3304627813, 2532190633, 733612212, 3194392916, 1538645070, 871903777, 346960285, 3824030942, 991737609, 660569608, 25531145, 3125334834, 2019398137, 136254844, 2601227241, 3740691089, 1400597961, 758494376, 1289737416, 176798002, 52677595, 1282844193, 2029711214, 1154925510, 924664133, 2384558292, 2657323714, 3032100806, 2076618856, 3874064840, 2301862464, 2613824074, 2408544438, 3475871678, 4286594061, 3888658535, 1599077513, 3091123524, 691764425, 571533226, 643388614, 1946732585, 231085233, 3636702918, 3681581111, 3187061512, 1902159644, 1741637618, 761538126, 1536383210, 579538109, 2344701437, 1320685197, 429406282, 614226248, 3064576305, 3913009213, 1408468081, 2953160453, 1860909301, 1257356077, 2326226229, 512992927, 4173707647, 4227234757, 2055824003, 1797074658, 723531295, 1055503760, 3723048013, 1019848561, 1813977292, 2245679653, 4188374262, 2764314541, 3543381795, 700976608, 1790968603, 1926021909, 604162486, 3885171802, 886529425, 2545372123, 1099009280, 2144253074, 2286027026, 3759545247, 65262690, 867405492, 478202482, 3860597229, 1950145935, 2338053342, 1301482230, 1694465994, 665328168, 1639519384, 1246558025, 3758953070, 514219744, 1033396600, 2585944964, 73215891, 1407268144, 3275177322, 713201364, 1552227337, 3796620920, 464835142, 2341943175, 3119000857, 2088431307, 3897368907, 878918678, 1090403719, 3163407018, 1730981592, 3537552166, 2597674257, 4098649693, 1903525249, 274610490, 2448833117, 3013444547, 2285961959, 1309148292, 4284801003, 1457869563, 1131416271, 1048930443, 2513500006, 1482041073, 1625081763, 4053050668, 2518621166, 3969148109, 2761689155, 2164832372, 81475261, 3345442184, 3349299825, 2006252039, 3489857052, 1658875101, 691754231, 849076446, 3627267661, 317685450, 4140537807, 2104452006, 3534476970, 2383041805, 3170903305, 738640319, 3255529797, 1446723654, 1118811539, 2937204107, 1614377664, 2969444277, 2952928746, 4001684504, 1718111127, 2073038934, 1656108772, 3191239768, 1185532158, 562604415, 3971592886, 3000494224, 2019311576, 3398207772, 1017177624, 2967316419, 1650769512, 2231731784, 3739468469, 1827669898, 141217323, 4207733620, 2832371984, 1621792041, 4151096498, 2547492982, 308078925, 3687686062, 2475718624, 3561209065, 4026891835, 1696468987, 3574384454, 2592420513, 3300544973, 2850962487, 656760200, 2508381898, 419452052, 626276936, 285665799, 3657891297, 554297412, 2239031137, 2012129, ], ); // - new_n == 0 third time in limbs_half_gcd_approx // - new_n == 0 fourth time in limbs_half_gcd_approx // - !limbs_half_gcd_approx in limbs_half_gcd_matrix_reduce test( &[ 3657711640, 998557705, 2673527526, 140583600, 3560526410, 3079349729, 1007803327, 208825735, 4004755247, 3170035294, 3362415892, 3152985538, 1012526106, 3432209347, 2014829100, 829200636, 4195462629, 886243751, 4231479532, 3989085076, 697433600, 4029974025, 2553256073, 2180771906, 589193852, 4067672710, 1710672160, 1276816229, 1543905950, 784977036, 2190950050, 3053735776, 2278807238, 3135300984, 139130646, 3731236261, 947882330, 397493027, 2887571315, 998281983, 3936346233, 1563553141, 963440454, 1318816838, 4291981145, 919167051, 2962354621, 2048072300, 777973943, 540037849, 3810855422, 3090640862, 821740314, 3090839706, 2989895484, 717348865, 669874649, 3744157584, 491278687, 2028098573, 1277141730, 808716380, 2793035676, 4006563562, 1685318670, 3368031079, 2624676111, 1345230900, 2205513093, 3750673160, 1587034889, 1439572889, 3845769461, 4280964819, 1482349371, 1079078534, 4168075013, 1635840911, 1957150571, 2178101877, 4115634728, 3398571758, 640182611, 1759062480, 1075711136, 1010428620, 2276894745, 1504571688, 2596747558, 3855398501, 2838338760, 2402020270, 2884702413, 1826928686, 2640885437, 2399131896, 3789994626, 4040600525, 1305079453, 81899822, 2191284405, 1815628758, 2609804524, 758549568, 1578952023, 518043841, 1501449207, 2578767272, 480891725, 2994717031, 2654624082, 527919434, 2238167925, 312529994, 718208527, 2007076208, 586720275, 729308642, 1465364144, 1706713224, 3777764105, 4134322226, 1156823710, 1507266584, 231421089, 144523751, 1853362091, 1463359998, 305379000, 4240641599, 2721880467, 550468546, 4074779797, 3504661731, 3933836974, 4064481517, 1555622614, 657068986, 2312879275, 2981257775, 3082895648, 3388461547, 1981146054, 547361683, 3971819850, 1412877825, 2006992814, 2288122621, 2206203029, 4226095933, 778245076, 1345823706, 3035370877, 389946835, 2749124467, 4010410686, 339262243, 1609006241, 2258477917, 3569782595, 3637101384, 2977823024, 426672744, 1521815787, 1263621653, 499965771, 456736400, 2492983378, 1224546346, 3806307160, 175211074, 1054659817, 3941472726, 1740350040, 1438650030, 2119348495, 2293521324, 3942515909, 614998919, 3084032385, 4144460915, 2482956785, 503211659, 34511204, 1681765654, 3380532341, 3242282393, 551611855, 1154795583, 201141450, 3394599938, 4032836190, 3946663852, 2007181123, 3278589677, 2773028926, 1396191139, 1093235858, 2343752245, 3726488552, 4039496728, 1711775405, 2313196824, 3792644308, 650938588, 2340124756, 2148862037, 1605804899, 2561768954, 4158774056, 1104406522, 160746998, 3547663955, 2740053054, 297320527, 2288260483, 1727465300, 1502488472, 191213708, 3240632447, 2763771729, 3316906616, 286363239, 427523346, 1834992479, 1767311733, 2323090189, 777754150, 2637436451, 3864398159, 3878482105, 3439516930, 3983770569, 2179596123, 3639743147, 3277930009, 132861371, 3016048414, 2479346124, 772138261, 103363267, 2106856453, 3363312313, 2104064722, 2211640386, 2790634720, 1094166731, 472640970, 3707415174, 2379763511, 3660706206, 266699090, 2825551202, 3816959358, 3686617390, 2405346213, 4064944758, 580087497, 3705304882, 804128893, 1526085410, 4259014614, 3424830723, 720534290, 546653993, 3743278090, 1876012283, 1494835352, 4205298074, 165588292, 3110211976, 448529551, 3332834541, 319442517, 580011988, 2786838094, 2921250286, 3100311441, 532629087, 3433284980, 2073128881, 2951256114, 2435157505, 1486539685, 2906352365, 3727836664, 162399185, 4051180248, 1338216875, 3019487912, 857100700, 3261403491, 3401769875, 2049869835, 4188966169, 1293350219, 1594676200, 3476259820, 2694785494, 45498552, 1043174148, 4115811420, 3167680253, 2550477339, 1707821053, 4259857856, 211137496, 198623401, 429308573, 1520075160, 2496533962, 2517139935, 1168536469, 3699138961, 2800251863, 1390306464, 1692109651, 2356645986, 774325761, 3399926958, 4110738344, 3817779241, 2013343760, 2250854886, 351243491, 425031366, 2479242665, 3764357544, 2713277117, 2512350560, 905949970, 117406898, 1332418557, 903482453, 4072632262, 1769369186, 3494102231, 4127403951, 4081588534, 3220287892, 2278166406, 2040914160, 4090789198, 1394480913, 1691201115, 1722070834, 3894412056, 1651961652, 3826548170, 3699211264, 3183549152, 2920880337, 182084175, 102220837, 2221619377, 1758527489, 951379287, 2855734431, 3213300857, 4263069418, 263677350, 3727218616, 689258763, 1971664130, 181797961, 326897757, 3105490726, 232500248, 2261802360, 3085707207, 1389245554, 3666172101, 2146196227, 1681117212, 1108350622, 441387235, 1914462616, 984521004, 859059782, 2826588020, 2946730104, 1218457794, 245867746, 2189555164, 2126866996, 1090542083, 3707825999, 2492424754, 2110587015, 9914155, 497858520, 2957494474, 1624327398, 490541517, 1459216649, 310263141, 933264393, 1522660397, 1285180428, 1470621088, 1023680737, 720481949, 4214305990, 1259717429, 3353303046, 987419142, 2214746907, 932909422, 1788637997, 2735466452, 436276719, 1594193462, 2568346174, 4146642666, 1937705165, 3620182538, 2069795783, 1080910056, 1452556953, 390339039, 4100737699, 3512365053, 2731125385, 4062819879, 1591306552, 3854740242, 64478911, 3073372522, 3345312614, 687806150, 1047499489, 2463969406, 1884499861, 2042651399, 10170802, 936049112, 3939636351, 1291898824, 3075319841, 1421285201, 1306154841, 1288723177, 2905666609, 2906581743, 4126000750, 1274137379, 2020506513, 837593817, 3184876278, 4228491086, 1655288190, 2689287128, 556238442, 113142447, 324605392, 2389209854, 2108685128, 4145207287, 3985615492, 3890009695, 3073605401, 990783580, 960479727, 2794641498, 1841758262, 2666851594, 2839506601, 921776375, 2622653975, 1051634901, 4138029960, 287681273, 2867814148, 4236186571, 3664092009, 1127349061, 1289370427, 1166089919, 3232826100, 1090362915, 2063320477, 324664748, 756968253, 2079873770, 237416454, 1960074355, 3038229413, 3265986384, 2253499694, 3259818663, 4216895416, 1546526391, 954740893, 359758052, 2422581369, 2008469231, 270459062, 2662846020, 198030360, 1699647574, 1189229658, 3064589775, 3086260774, 3492329301, 95140180, 3679964930, 1719240364, 3308170694, 3900158813, 1824364083, 3912229897, 2065183143, 1640649275, 210215170, 3595329392, 2936055969, 3380333840, 2729203827, 1716703032, 3346477528, 2910262660, 1448045650, 3214180907, 3765279970, 2747456398, 1754123031, 2253034236, 1951705358, 3487056132, 4179006228, 715674883, 1154440593, 1890254496, 1287645100, 2931442980, 3677760863, 3113867376, 3657457141, 3252835590, 1969239822, 4012698633, 3027155613, 3969623199, 2878407462, 2876709948, 2688525098, 3727199561, 2234381059, 3136829525, 3554705692, 1831478139, 1674107447, 2082176817, 670088203, 728773244, 1632752100, 1848846884, 1114000722, 775704401, 3844163200, 469678943, 4133910816, 3435744844, 1661656089, 3919969806, 372912331, 3925680842, 1366571708, 2821510836, 649494, 724284323, 505472189, 2687312723, 2405046872, 3125301318, 3256049289, 774087973, 3981705603, 3325439184, 2954835675, 2725563058, 2515754404, 3477776973, 4269454691, 2449194279, 1547625513, 1728063507, 231201570, 4292877797, 3495163803, 4013580537, 1837665961, 1300013543, 1241432110, 3093642896, 1691481026, 3921752027, 1059474853, 3218109461, 4272199222, 3090405739, 784116813, 4280886718, 3547794686, 119045029, 214217180, 1172298704, 272007380, 4168588819, 1539710510, 4048478839, 3293824373, 1932114687, 2517831124, 502648680, 1599065216, 235634761, 2931327099, 1806135786, 2748758605, 4286102182, 2218543471, 4159247954, 2851704864, 959147626, 2366564152, 3019979868, 2655370718, 281510209, 931090423, 499413544, 64739670, 894424336, 1818208026, 2257234516, 2624162454, 3189431803, 1134320613, 3166537004, 2926565501, 2669059446, 497238445, 30233754, 2620265220, 3558625938, 352282231, 3147660599, 1340912220, 3276802486, 3012669529, 3553537679, 326416777, 4279833819, 348274989, 2055151357, 2126716616, 819698272, 1389794698, 2264090128, 204730947, 843480400, 3957036142, 1740808497, 3403300417, 493638729, 3397686538, 2997162679, 4039958112, 3129102367, 4099024232, 4121783672, 3272745379, 1139179399, 285642431, 648122033, 2734146014, 1523103819, 4033077595, 2558609201, 3747324433, 2458964514, 4132460622, 1043448320, 10736, ], &[ 2854126571, 3810922285, 371837910, 2847540454, 486740183, 2160285633, 2017968719, 1221435102, 1141701073, 1526766552, 1231337987, 1813385239, 2734884018, 235620011, 3665183150, 1120279822, 2382922525, 3908597230, 2767187339, 4225970635, 2058878812, 1054451375, 3908013355, 4090049198, 353761630, 943442885, 2028279969, 2755908669, 3495701523, 2274876514, 7111411, 2322147314, 3166509422, 3631852760, 1999836871, 650648601, 2896603946, 4278326950, 2519734766, 2042259469, 2175932534, 3377156271, 2708233165, 1153846353, 569980209, 716406085, 1416372219, 2491866469, 1849390979, 1657511720, 527987900, 312131542, 1483115611, 3019246366, 1772076445, 2597632097, 1806628960, 602363143, 828919543, 4054351320, 745399979, 392681753, 729942081, 3783820494, 958343864, 1891389523, 1916371046, 3957352530, 1940850968, 2999627271, 2056442667, 3600581748, 739316794, 615343381, 2991048069, 963790214, 3579897498, 2727465507, 1291721350, 2257779716, 189799771, 249939605, 2313870626, 3298318286, 2695432027, 1104216368, 858091490, 3612066070, 3242257962, 2819622739, 3621623439, 1645360864, 1858386419, 3690046232, 1963002266, 3365019901, 709477199, 1869694999, 1333459016, 3929260115, 1804302107, 1548831440, 2447603949, 3613058855, 2294343811, 3061585375, 1234689982, 1110502912, 1267669326, 2897966429, 1238959344, 2388962700, 1545916965, 4015877004, 2291501123, 1151613625, 431826202, 2784246687, 1081585466, 861824085, 3830712001, 4199076025, 1169739676, 1721601770, 486252424, 2456992908, 2367988995, 853976555, 2362625785, 847070690, 3892469091, 189183763, 983145128, 604862255, 1284385769, 1440014575, 1449024264, 1124161398, 992775577, 896708354, 1499353865, 1733133868, 2463919313, 856157696, 3778499837, 3108165894, 3335953575, 2577002240, 486391747, 3793776140, 4178059147, 1421326491, 2877075680, 121756272, 2955126461, 1185519566, 439523848, 534575395, 1560554614, 3182072951, 3886491221, 3273785996, 1722350380, 1102349772, 3163492322, 855840633, 749300337, 4268787245, 1616840129, 3057312503, 3760176742, 3207150726, 491867592, 370828011, 1123930175, 3909514255, 607439111, 864050721, 3004872052, 1802788201, 1624858827, 2832354028, 72204982, 457231306, 3454382699, 2189149463, 3840204336, 1209241202, 1978336288, 4169032732, 2876009661, 1082634619, 2497263384, 1326174220, 1253911629, 3737995297, 3263043078, 645177131, 3799451502, 325159611, 1330703088, 441891512, 4125145352, 149253662, 186351587, 4080844290, 2196709175, 845328519, 1100994658, 1730443741, 697455139, 221172934, 284568041, 3633521112, 4012942302, 2503979252, 1982165755, 1603237111, 3062410273, 2172526016, 3932170374, 746842837, 2685299075, 2226087030, 2288686577, 3833519356, 1106715479, 803191120, 2945220717, 3462665442, 1851929745, 3220631793, 825749594, 3850318854, 1995848704, 372995746, 2365949838, 620492561, 1369591225, 223709365, 1954997080, 3882190656, 136576738, 2495749432, 3002183229, 4087193741, 799453426, 942624435, 1615021967, 2904816939, 3821110584, 3804731230, 539775187, 1076068431, 1596180969, 3090422137, 2013680976, 4160179801, 1501779020, 3485041009, 627578448, 1687656645, 1097144289, 967159869, 1069388948, 3185056534, 815670796, 358149589, 682430892, 1919067351, 1080492798, 1738690879, 3469244164, 3048277671, 676563295, 793928921, 778744353, 1648323757, 2221906903, 2287524694, 1039650177, 1679972277, 449929141, 1905719297, 3917418719, 2749202465, 2635810607, 2907978358, 1764745285, 4092093759, 2136036160, 3823420732, 3781081204, 789220560, 76055428, 1068573956, 3496138402, 707619794, 699429176, 1599250365, 1226916168, 2953556842, 3013778359, 445642445, 3359206573, 1634979966, 32169773, 3986006899, 2747561339, 2534736220, 62657613, 1511121562, 2122981684, 3246037727, 3781297188, 1174417153, 2326429527, 2030416725, 4239201915, 1267322727, 4213670773, 3561818989, 2314510277, 2980523839, 1790535762, 4031301214, 3864863880, 178369327, 518325210, 2973773473, 1492340216, 2880227942, 1144890024, 2409210141, 3051276713, 1507874226, 2982534148, 4129621437, 1186413065, 760037878, 152289721, 2233567098, 3431847497, 2459547367, 3925952526, 1236723769, 785269549, 3929478183, 2566922363, 2036461315, 2787863332, 2385369768, 1903832984, 2751226282, 2966793376, 4210685335, 110217992, 2334089437, 832643681, 3824460110, 2884348488, 3553526804, 1696587587, 3077903646, 3774351568, 118586818, 2535051277, 3044137612, 611368190, 2247957170, 4151739331, 3032079141, 2398348531, 301800229, 2489467427, 463881677, 286741354, 919821454, 2514396732, 1049973971, 2885185956, 4278356569, 1106751573, 2780358912, 3165013482, 682728744, 156457261, 966913152, 1795511616, 1102483004, 47768694, 774401181, 382571797, 3418933490, 1337271451, 2553642946, 1682481208, 186752586, 402086066, 1253357008, 636687570, 1174558316, 3075513694, 3581054104, 1520081698, 3462279363, 3127642491, 3337969953, 851993452, 3859511913, 3125432584, 3565365475, 3639315630, 1929579809, 1245576721, 3896701628, 3934477337, 4087201647, 3275038136, 1788711123, 3958067369, 4089205000, 231641077, 2231523824, 2619997727, 441912559, 4072770613, 4240978164, 2974598062, 2924678733, 2970538057, 2736142575, 1105201139, 970816157, 2369699954, 1887951773, 4171767668, 4285132008, 1776816709, 3770203858, 2382945, 2017961118, 2832376676, 2804837768, 3274902934, 3591733883, 3691479138, 52712933, 2612228989, 3628704902, 3513862898, 478216119, 2726352952, 804977216, 3390084015, 4081495820, 1671436017, 2848400264, 3656019845, 2136393241, 431834724, 3510727226, 3071482565, 410753183, 1657700546, 1058987404, 489895964, 1587210753, 4111636005, 2918121105, 803516926, 638869931, 2234185434, 1507756257, 3908703942, 810746259, 2117398521, 3273771795, 2327709962, 1345338774, 2380428267, 1886210982, 3272617401, 2424798876, 2485064558, 3441956046, 4282650102, 1189648611, 161669993, 2174805813, 46186229, 3870678520, 1725393849, 2725996937, 2285861609, 2855918656, 2085727938, 3005980273, 1091105108, 2274905128, 3124240963, 3402918292, 3948459386, 3730327554, 2624673727, 1462493475, 1911926536, 1172198609, 1531781228, 2875744790, 955061915, 3653212440, 1316441536, 1571847879, 117813941, 724461511, 106145092, 3007920163, 509355349, 2361882009, 3290661803, 3009193891, 2101167937, 3236175251, 2600604339, 2409592198, 267656105, 28902868, 3787222075, 3910267520, 518607069, 78112248, 1231828511, 2237810649, 2039587423, 3258311695, 244193578, 1901807321, 1888614436, 724431620, 1229615953, 3602175515, 107889915, 1499981622, 915728462, 3185158200, 3875556208, 1422223958, 74968146, 1782255156, 3690901362, 3148861984, 285887046, 456047577, 1877634221, 4119417329, 2674004542, 771859946, 3841364442, 2576022811, 2774717438, 3707475262, 598699796, 4086485722, 2071933255, 254807101, 2713526148, 4015941391, 590180295, 2462439133, 893362735, 2776258951, 670583777, 3998467192, 4252701293, 3144240767, 929429555, 3121145790, 2186463475, 595824244, 1196211096, 2796145353, 2313718767, 2327057115, 2600569013, 1375960388, 2419292403, 3991920167, 3660567838, 3488689798, 2047799775, 2345831879, 3333113070, 1392141953, 3356864686, 3683415162, 30718491, 2800440004, 305780227, 2420043106, 1237507888, 1479858831, 3600187970, 3379229271, 1429268544, 2752590068, 2152897287, 2762740595, 3499503442, 1412039428, 1580413636, 4255719498, 3321537024, 978632041, 2570103234, 2866926493, 714621483, 2791004236, 2495536081, 343144324, 378104110, 920987435, 3182143689, 1200960749, 1263985718, 1422494241, 235668853, 1459938722, 2182331117, 1534070260, 1037022387, 2359040698, 277760467, 231493066, 4156892106, 3785706492, 1644416142, 279187889, 4046443858, 3644810161, 2159180570, 313719967, 4093063716, 1479097649, 3123510773, 2411818036, 1854765137, 6659591, ], &[ 3522409411, 692426266, 4252687070, 3221722249, 2259982318, 1572230342, 2447667874, 582309214, 3464041890, 833370466, 2502005176, 866026260, 3434778270, 832555619, 577419378, 355707174, 2758409995, 539088491, 4165515733, 3525341005, 70966281, 4112863463, 18093477, 996208336, 2996281883, 243025039, 1724269073, 3456564031, 2183707540, 2623790820, 4068996778, 2003125751, 3979669707, 2092158727, 1319454084, 233637378, 3444775191, 2047163977, 1305370049, 4052656807, 3362300485, 2153220367, 3451943873, 2659951731, 310435720, 240435490, 1283149803, 3779214360, 1819576764, 3267732950, 2661843307, 2263394946, 1901303373, 1858196903, 798526878, 2800696617, 3224809646, 982174624, 559354368, 2472934158, 3806202203, 2295203592, 2945471200, 2663904303, 1357384963, 1650942869, 796482443, 2766778986, 1604012049, 1236473541, 1483190475, 1132242907, 3470424624, 3256605783, 1372433796, 2572130477, 1005422111, 3417699569, 1998572418, 2781008338, 131034958, 2366709018, 2158499536, 4239137506, 2147101299, 3836689278, 1767372944, 198678316, 3099405709, 1642856762, 1359859087, 1016829435, 1775642165, 3166947118, 1370994118, 3565882683, 2697435592, 2988614686, 700091191, 2139458915, 293125924, 1677498485, 324444909, 1956567030, 1647523339, 1288409259, 3433527205, 3488399404, 2692884632, 2629401949, 1865373164, 260321166, 2452146960, 1510030261, 3309904643, 1821006233, 4092693137, 360274707, 430743857, 1022845846, 768344651, 870695548, 4244607652, 2799849346, 1897317934, 907494911, 3494316912, 3319466364, 3831408243, 379446458, 1637847888, 761682818, 2305788385, 488150578, 2591607856, 3487487084, 3482200336, 3409152717, 4191475557, 2349556031, 1024188774, 2357767930, 3538056694, 1299385038, 863893778, 3197830576, 3620847361, 3734458112, 2102579497, 2299090284, 1776637937, 923893333, 3538505849, 1525313260, 1095090443, 1425332433, 4270279191, 3899256887, 2234522273, 3938133714, 1144096051, 2771405273, 4039853365, 2164168861, 2220073157, 3305905250, 3547017695, 3028576138, 3211205289, 2969717301, 1297821450, 3898348269, 536907576, 3526521253, 2984151429, 325158808, 3634226110, 254237584, 1647629802, 1213935217, 1963529116, 2864575925, 248508991, 1681221168, 2138605160, 3011363057, 1667991051, 2164842621, 1221146487, 1896090790, 3584296136, 1197643020, 520819114, 2845411935, 2882123631, 86651362, 2840429882, 305685636, 812868855, 4270240044, 2258043791, 3681398458, 2125157433, 3400174505, 52122812, 3977731352, 2960080531, 1752547412, 1789316668, 2086783129, 2065283260, 474350220, 1392633188, 2642559453, 2623416931, 1213699470, 431976342, 4191881681, 3989646787, 2555136586, 331973965, 3045351568, 1974527188, 1721946949, 2420304698, 3018807687, 3912284737, 2323363082, 4175374785, 3073974039, 2019051853, 3254436577, 4145054805, 2909559648, 1674676821, 618050625, 1701855694, 3844330576, 2368970459, 1142540548, 19839276, 2809741072, 1358679745, 1616340555, 1321571980, 4269787203, 2139498091, 1516379787, 4232094406, 1813501895, 3499360571, 108430199, 2969637702, 953766617, 746993329, 1798819970, 3008070664, 29506047, 3755689428, 1731853786, 2150972169, 3970252289, 1707195359, 150651832, 4272796881, 3214714265, 1289674369, 3832009122, 1863256348, 4208461628, 2928731478, 1909075615, 206649607, 3721679533, 1149140532, 2135144822, 2553592226, 390359104, 2664151758, 4207827335, 791092034, 1418111790, 3869230526, 1229201988, 3450535823, 3141749817, 4170511491, 1808234944, 2870573701, 1933266254, 1944630510, 541620618, 2484636520, 3899287047, 837911245, 318074222, 778344163, 332143424, 3148535492, 3257541807, 2584276077, 3752887648, 1145669314, 2724633195, 168627417, 2600193851, 2188347881, 315294329, 1951166123, 3631461291, 2699587438, 3705790078, 97682065, 3212849906, 1644271056, 2402937425, 1495234346, 2546518537, 3699134635, 1566766581, 4076379355, 1369185061, 1927352427, 3453847057, 2121073778, 3846264460, 3345029574, 990382258, 1093055554, 4020639133, 2106873871, 3558358079, 3623019498, 1126463853, 4000595941, 2326522050, 2496119497, 1177412487, 3737033586, 1970672443, 4124458184, 2182522865, 1950531515, 2217610303, 1875359075, 887126337, 4187532100, 3050435188, 1382650461, 3459929976, 1249535657, 4069389042, 3437440772, 2924920125, 1065376385, 3759927287, 1835638851, 1549066656, 2607123205, 4287679131, 1933130208, 1861085748, 3531803620, 2455707011, 733561985, 2945180228, 3707942192, 3580180904, 3375170391, 1690619419, 3658664211, 3096941018, 1587283463, 3941503860, 3163621426, 526869998, 1316208739, 3776069458, 3759213667, 3343111698, 3552349239, 1698745515, 529667942, 4250086784, 2328783424, 1942833307, 2532170555, 1407840798, 3929450154, 689766216, 603422970, 2945072222, 3148401239, 2154639678, 2439164182, 1799459040, 1555139265, 4024153015, 3988650657, 3734125279, 1894805848, 2147080077, 1860482341, 3275095036, 3629120956, 1637523200, 2484855322, 1006412, 650874934, 3277326964, 1186385437, 3787893694, 3384961602, 31727330, 1019763729, 4132753588, 3078074634, 1730195820, 1742210061, 3980710682, 1476247656, 1537422777, 4040062712, 1425312769, 1848918319, 4087493673, 2365974768, 1886134839, 3875551706, 1685012340, 41954153, 3951521761, 2564745248, 2519620712, 3959816490, 2560867112, 344633036, 3691137569, 1256857877, 2291066279, 2054203203, 1386019941, 4272539404, 3363945588, 2226687874, 3871655974, 1494082150, 1112096467, 2284368903, 975044169, 523309601, 2133056593, 3313692829, 904329125, 3666815061, 222106749, 1616520314, 2393855972, 3705259257, 860827649, 37212776, 2059317736, 3079163663, 932474881, 3394576876, 1706615928, 1819714696, 3820968510, 536368964, 2910847848, 2135453698, 1350335129, 300212611, 2633354050, 153183294, 1928772583, 1021126237, 573543692, 3567442837, 1409698831, 3111277745, 581910616, 1979561780, 396494706, 2463303563, 3166095864, 3105677740, 2400257412, 1913519467, 2416376547, 1957034146, 556585253, 4210367449, 2539364372, 572061442, 4289883802, 2215328126, 294061050, 2040995404, 2952991336, 1040316946, 720150954, 2348132965, 3885697361, 424223697, 3805769810, 554628633, 1894997829, 3738308930, 2890140217, 16184469, 2112778335, 3492087017, 1528198629, 3156309847, 1672825355, 2320695680, 1770693922, 4158833400, 111430926, 2523417395, 2654875625, 3108094520, 2689255279, 2038117485, 2616876984, 2352131353, 3150209189, 3217446658, 836678783, 2785826980, 3252708922, 964549716, 1140915598, 3033957610, 2356630981, 3514265925, 1278364234, 1083297932, 4023829085, 3614439116, 680554138, 3997456824, 2252713625, 2055817074, 1234522698, 3102015221, 3404334905, 112882014, 2007560807, 1487607631, 3501350871, 1111627245, 980132418, 3206101949, 4130779405, 2111302372, 1968609288, 4204601547, 2874374202, 2853878438, 2857752228, 274256864, 1817723765, 1905422451, 3363188610, 3333488106, 463317661, 2351076159, 1477837401, 1418561892, 1866844722, 303232671, 140367367, 3061206542, 1503639539, 589823218, 1918827275, 2600297211, 4277833048, 2393528802, 1661440636, 2339324312, 1263101253, 2873025067, 3441016568, 194170142, 2576615806, 233994937, 2966168464, 3087711309, 1530686231, 2308302598, 3393973525, 2467525628, 469950892, 4103299607, 1794837893, 1549361853, 3580558511, 12661541, 722609243, 965007319, 449849784, 3829064245, 3965630564, 3112166475, 3424263194, 195830868, 3230014161, 201295863, 1892682525, 2243429350, 678386870, 3696010396, 367065208, 3856657124, 3741113040, 3014123703, 739968874, 413, ], ); // - xs_len <= s in limbs_gcd_subdivide_step // - s != 0 second time in limbs_gcd_subdivide_step // - new_n != 0 second time test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294901759, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967291, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262144, ], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294901759, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293918719, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, ], &[ 4294967233, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 32255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4128768, 0, ], ); // - n <= s + 2 in limbs_half_gcd test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294959104, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294950911, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 134217727, ], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294965248, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 33554431, ], &[ 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 16383, ], ); // - ys_len == 0 second time in limbs_gcd_subdivide_step test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966272, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967293, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 65535, ], &[ 1, 0, 0, 0, 0, 0, 4294967232, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967293, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, ], &[ 4294967293, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, ], ); // - n == 0 third time in limbs_half_gcd test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293918719, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967279, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 2147483647, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16777216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67108864, ], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967040, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967279, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967231, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16384, ], &[ 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, ], ); // - xs[new_n - 1] == 0 && ys[new_n - 1] == 0 in limbs_half_gcd_matrix_apply test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294966783, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 262143, ], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294705152, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294966783, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 134217727, ], &[ 4294966785, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 261631, ], ); // - s + 1 == n || ... in limbs_half_gcd_approx // - extra_bits == 0 second time in limbs_half_gcd_approx // - n != 2 in limbs_half_gcd_approx test( &[ 2004596728, 1848887139, 3588545405, 3004392306, 853879983, 1360524256, 1385705184, 3321803032, 2791968922, 3892438424, 1781322303, 3493068948, 2015405293, 4074669885, 2900269078, 3823683574, 89252947, 4038834041, 3432017782, 3193194315, 2816970936, 1259222869, 792476452, 2969025189, 2789393972, 3016742665, 757499223, 11545282, 3423520861, 3616113932, 3465820395, 1979030055, 2104068595, 3714106365, 1466660150, 1712602216, 2630941262, 610797776, 4074395197, 3701243311, 3555176782, 562321145, 3934144323, 2134957404, 1613994064, 2254770945, 844351745, 803798570, 2703265082, 3640524712, 3907579617, 1740863700, 3961951685, 2756477900, 1800563792, 4006854388, 1927911032, 4232194641, 2895575388, 1248300427, 324453294, 865512796, 1640531918, 3337883058, 4127691867, 1251838156, 3755093876, 2638444353, 2277825898, 1079070681, 2347582744, 4086131979, 1292025334, 1141464465, 2190524620, 3815677488, 3218393458, 1168612800, 544017320, 2324397425, 3767722505, 2551036255, 749770338, 3505489601, 3557482154, 3813020533, 446277331, 443847294, 4085812779, 842889652, 494048275, 2419464445, 1214470431, 1228587913, 4005029074, 1143269930, 2427231859, 2933315483, 2923633652, 1889084749, 2411174117, 2305971895, 2959154784, 2927615709, 3241695251, 682460868, 653924800, 3814161525, 2508305181, 1339320678, 3455333037, 4176128090, 2539010236, 2893402188, 1241794103, 3954344331, 4233454015, 3681840959, 1878852448, 4262815930, 166349449, 1235728789, 336877896, 1367168363, 2965431878, 3447952070, 1714138221, 1049768737, 1231199029, 2910381689, 307859398, 899270841, 1606345579, 1234775041, 189535788, 1984838421, 2087074239, 2867133699, 4209429577, 1098566748, 83344395, 1521074408, 1698236631, 1907863376, 1923053177, 3422780594, 787031035, 3522524050, 2028229229, 3031046586, 2851262763, 2888070447, 2834519912, 2885252087, 177502086, 3275331517, 2442998599, 470146074, 499318359, 4217123754, 3089228461, 1039758505, 1609847346, 1217631005, 3141899940, 1645363140, 4180648912, 1348926971, 2872045994, 2516596487, 70751717, 3755810719, 2844208311, 860932668, 3025234253, 4228898226, 1667541479, 3791359976, 430657658, 2775582388, 3472378627, 2507534646, 292448923, 166266046, 3517783361, 2602204453, 3143313511, 1907742516, 2093632780, 3391286313, 2706298791, 1700209801, 646869730, 2296768972, 3445646575, 4251992105, 2910039672, 2099034896, 82722938, 2958905749, 1059663844, 2996112985, 3875276435, 3838463324, 3607053228, 1649011648, 1013811619, 526117160, 1012433449, 885794551, 1704687270, 869082082, 2736112342, 1882492056, 2952317080, 4088973917, 3059951449, 548119577, 134193431, 4269903209, 719387298, 3039694582, 3312858765, 131546364, 3768977754, 1008091338, 736625, 100297344, 2441670905, 2960124427, 4187608134, 1281665081, 347304892, 425777148, 3815705055, 2002210752, 3158348324, 3370719815, 235350445, 3073024597, 2841606549, 3677106047, 627054432, 1463475055, 2306894862, 2004510531, 1215369345, 3796695068, 1705709666, 1910826455, 3380653290, 1669034431, 1326881073, 2691232035, 1345394646, 2505725768, 1643208418, 2278435319, 3975379348, 936580608, 3558291381, 1578739386, 3360990083, 1367648693, 2174608196, 3784418662, 4096285583, 1125126761, 1702879279, 2373900154, 2794269811, 892965648, 3431450476, 1598114090, 518942123, 3942271859, 163233596, 3635705911, 2802569655, 3902026503, 4172233752, 1343615033, 1443283240, 3214860685, 1830135384, 324092050, 3595506427, 4006369796, 3094883604, 1337811945, 1590934260, 1405064877, 1629961311, 3917976233, 2307585818, 1966934539, 1130062423, 1870989582, 1624138122, 363138090, 2804418650, 2247302844, 3205057981, 1897671604, 1838684004, 1004563089, 3421753356, 558428644, 1914315130, 3772633601, 2526221813, 2274129897, 877924724, 3120882592, 3985407655, 3151825377, 3497165637, 4225852164, 3537575972, 1378449691, 3428657854, 917817375, 527806996, 947800429, 136564017, 2885607105, 73317183, 265413671, 113274788, 3223321193, 210252458, 2455534679, 730413621, 3248846851, 904264433, 3785997086, 3749983772, 3451619934, 1253036056, 814792744, 1441772826, 2902751149, 1233888488, 3433013081, 1418759256, 924600323, 3080242546, 1505445983, 983904026, 3815022296, 2057785068, 3901544799, 1289567020, 3045444045, 3571691925, 2469383112, 2902682391, 2637073877, 2288505094, 1098867737, 941340356, 1780640923, 488687629, 3661273470, 2018461290, 4073895479, 4219286255, 1226075625, 1286996168, 2455678338, 544007097, 4088835826, 555104214, 2207823194, 3598396023, 742075093, 1931088791, 3231680922, 2207259058, 1054824417, 2809061923, 3659187103, 667505786, 1038625820, 2546526131, 100718813, 3971349256, 2689176731, 867921223, 216238397, 2926583018, 2524616945, 3105675814, 1929564974, 84832194, 2898985519, 1538371806, 2304769426, 3331366264, 3992871197, 2524313399, 2880073024, 214374078, 3087979230, 3763462972, 1492033090, 2745547667, 1590203017, 2220884647, 1043643074, 270180523, 3619501678, 913269760, 432169997, 1560222504, 3606034447, 370004374, 2242741806, 161846260, 1611153441, 2788329497, 221705084, 1562296329, 2602384573, 2489408324, 26752274, 1012421860, 2870608198, 3339203935, 461343907, 153553549, 769161583, 33015466, 185839789, 1238122110, 1955418650, 4034473489, 258622964, 3142360380, 1154801666, 1938695011, 3543768243, 3169796551, 918987546, 1837828018, 3174207376, 2490048788, 1968348654, 981031537, 2019290428, 2481414836, 4075697852, 2177287359, 2394194295, 2918955032, 3990490756, 2721846619, 4831810, 3676889722, 77410574, 89746890, 984555749, 1700971854, 1157576335, 2282651337, 2161988414, 200058435, 3928266699, 930309134, 1501872778, 2708771958, 700076188, 406467641, 3056590431, 3360765111, 4031233736, 3421740854, 977030487, 99478473, 1098197595, 344694600, 579238328, 3538505442, 2636219428, 2819718878, 1017360877, 4122930426, 1031875816, 893936384, 2187396525, 2651789727, 1406131552, 2442039378, 3802582287, 2558943236, 1638234317, 1996245621, 3369039129, 3228698584, 2117350450, 790103060, 1066928337, 2234731599, 2618583709, 2555385033, 1780760113, 3641524458, 4150990164, 903504072, 4053936972, 3149614166, 2337971588, 890882883, 356711938, 2263542728, 1364381326, 3810269234, 176857342, 3484849272, 545650307, 4095119697, 1070867675, 44185550, 3245052385, 512603627, 3259006013, 1823968935, 820533825, 1968169710, 2512600375, 3565879518, 1297163908, 49040429, 3182956160, 508986908, 410825498, 3306313947, 993237936, 167382405, 3237055914, 1596868278, 149136283, 259065124, 2117102457, 2524094604, 4026729163, 1740524001, 1910248499, 3900973553, 963142543, 1135340442, 1969527786, 4217058880, 785182291, 4104638176, 2329275390, 3800005728, 3604262878, 2318748672, 2241924274, 4146333651, 4280666223, 2529283140, 4007762691, 4137420426, 3087334197, 1001749081, 618981599, 2290019564, 1030626743, 2353440201, 3491060669, 3215041527, 2133818684, 733955838, 1074731940, 1013602989, 1745515239, 3242057247, 3498788174, 755386347, 1719467948, 329147897, 2110573052, 2651634797, 2329469633, 1756488056, 86346262, 3905621145, 2947376796, 3505737560, 1900253843, 2879666387, 2157905472, 1776782776, 199667884, 2726782520, 373441468, 1768340110, 2462560802, 507615514, 1956022588, 2384919250, 3412435481, 3320720595, 1941716387, 2023426521, 920190565, 3248821718, 2537144431, 2247676695, 2897967965, 3195719172, 895846478, 1897877802, 2598950252, 3385294109, 88060678, 1813045139, 1710194386, 534922353, 4115328300, 1579427575, 489224725, 3942695965, 336077582, 1683601440, 3996082755, 4004864353, 3956008235, 3160734247, 220270324, 2211225079, 1810415176, 2384394389, 3863744894, 3644215752, 1441189974, 3953466009, 49244730, 3292932716, 982515392, 1412561304, 2892516725, 2889338602, 2133629116, 333644531, 586020549, 3757651544, 3094771642, 3962017540, 1922803563, 2852357730, 3982002373, 4184765592, 1490335806, 644006294, 3503622441, 191971406, 1321085451, 2933347886, 2298585985, 3942234867, 2711863789, 4287811909, 1869646329, 4193678178, 2300694512, 1672898480, 686525422, 29702670, 2048484513, 3800848401, 1016390476, 2542462976, 1630627170, 2566172213, 3799057710, 826467738, 2081397119, 3825871484, 1720343261, 2134275403, 582093436, 840829215, 3070534680, 2452108732, 3836992562, 3614708040, 642988748, 3799027792, 4279250555, 2415353135, 1431887958, 2718502020, 1396816819, 1619130585, 4148081938, 1571085815, 967105049, 1826809732, 1669740739, 1082141732, 1397004647, 778435201, 2046386989, 104029467, 2259777826, 364934737, 3269047887, 2763055117, 230291892, 451391998, 1891814456, 831038728, 2964787176, 3635108912, 1922422114, 3925407285, 2321391206, 2465927715, 4166210675, 1197190708, 2294797824, 3526000914, 2502435952, 3203138648, 3372900543, 733841109, 3114196707, 2959722855, 3974072908, 125712163, 3949935156, 1192064193, 1085374669, 3982672572, 845787141, 2041667785, 1091167459, 4191929987, 1653040596, 488154413, 960754299, 1195687062, 1016099064, 3052206013, 1445590992, 2800180480, 2391011353, 2595121989, 865889910, 3530257661, 2435488454, 2218519781, 3043715764, 719268352, 4118610915, 2644321404, 2688437598, 3635531668, 1233398325, 421024892, 777080283, 364599954, 3262345441, 1278614086, 1903481893, 1108104645, 3477418707, 2459845146, 2161754027, 3572822544, 3213552665, 667392374, 3742233712, 1344617923, 3673776960, 3333792099, 4171297121, 2361470285, 2456722922, 294864113, 184980340, 4022019397, 1074091825, 1871736332, 874717959, 3297537109, 2857811966, 2634096492, 3743762943, 1543744992, 3070296783, 1414890392, 3534170596, 2874392428, 3120304495, 1883738483, 1248660253, 867059402, 1991084538, 2294883679, 2004356063, 920311728, 2402442236, 3400179891, 4246588249, 1364011692, 3510199169, 637783028, 3953751884, 3539712763, 1197923989, 3315532567, 1772695848, 851905130, 119859671, 2150435159, 709509942, 559611034, 2881395845, 2070876910, 575568326, 1904348566, 3178937360, 4124642603, 2770017354, 462709647, 3534605840, 1958609374, 4276935967, 377299139, 4184852657, 2339718928, 3948556371, 3884870239, 847308351, 1567877006, 942676575, 3013407713, 1391345145, 1561541328, 2032670783, 2115922540, 2840947915, 1424667973, 2625051425, 142557574, 3608928348, 2857192866, 1885061732, 1032209703, 1670027307, 619942102, 577354863, 1991193473, 4106125554, 3897353387, 731765970, 2111758919, 2952189172, 1128764158, 4294956501, 1552565742, 150742947, 1645656939, 2396412695, 1598935993, 3811058692, 4282926397, 2028513885, 3417133207, 1960806103, 2987468245, 1261155071, 1955858897, 2337563115, 880430719, 3940851795, 2851862439, 2837360725, 998053826, 1459954608, 859053755, 1064753371, 2745438489, 3442260013, 2618174, 3064510597, 1526197768, 1172088455, 368916865, 4081414092, 872579574, 2606125510, 2393005057, 3895670156, 2773169580, 2784687800, 2713793780, 824327507, 1882474218, 4007720140, 701440179, 2854102433, 2485031446, 69057080, 1788242193, 717689363, 3404715444, 2079426393, 2150736275, 2447994641, 2919217268, 3473535129, 3831746162, 73654495, 2724500951, ], &[ 2048467029, 459202127, 4051209999, 2641158559, 2529283231, 785114584, 3478830982, 682417094, 4137477036, 1994886259, 3849756551, 1850485567, 1510562924, 3626191361, 235960481, 980403409, 1789076459, 723101310, 855767948, 2804845518, 455915126, 3615072101, 3090232230, 466533522, 1169083525, 1158162624, 1858763072, 3595675614, 1661517062, 868777641, 871705130, 2861391047, 500497205, 2878901309, 1180001451, 686942037, 1956533284, 1920395594, 463032751, 1775551241, 2962069853, 1379946573, 1204600053, 3490263166, 3319964396, 297358647, 3127096944, 2886152999, 54379252, 3229449581, 1810608641, 3761727243, 374040322, 1887571393, 3146210360, 3708571160, 2205846452, 1001286939, 4203438216, 1231239932, 1865353368, 3994983472, 1326013992, 1568675894, 2481470254, 3886943594, 2173153009, 2709989031, 2174267461, 646584830, 3616102992, 4053133949, 481146194, 650153841, 2339337832, 2740187083, 225432613, 589865866, 843055701, 3020975970, 265007788, 1116775520, 2919330007, 3346158850, 3487640422, 1169247910, 997606069, 4010912587, 578436020, 4290033930, 3633599003, 2580529737, 162726999, 3743750914, 1981881618, 391172274, 3576970038, 3723023159, 3307886769, 3395118745, 575247113, 415887104, 1534676348, 2823996659, 4269453883, 760173732, 2138038336, 1086521291, 3199196489, 781423556, 1357123249, 4195648284, 3759296877, 2958948707, 3878993388, 3483121017, 2443771071, 52664592, 4239525630, 804231160, 1853250793, 3941273196, 3701311485, 2618716701, 56163857, 352626830, 3422477586, 3132969079, 3117007699, 181228357, 1045692359, 2223063843, 2343808063, 3122019574, 1709080652, 1254416114, 2121822259, 2976997459, 1780344599, 272725612, 3902688101, 2445075321, 3015383251, 2720256116, 1965686532, 3674920947, 2017493119, 2443555429, 3245745772, 4284800850, 618003105, 2592784982, 3140704668, 1643367542, 4252514361, 3843724900, 217510595, 3357765030, 3943128900, 3880661463, 369505618, 4186357727, 3349936627, 1429436215, 3729602835, 3738804567, 1753791419, 405876993, 2800106006, 3445400414, 2334940713, 365540818, 2000813054, 3402754389, 533916330, 387189415, 2847853159, 66632878, 1077148, 1396928998, 4089775018, 1213790544, 1059352194, 2514176069, 4257435125, 1261407550, 3530893728, 2451914750, 3905023603, 3254919488, 2751582838, 2008398588, 3449851963, 1812431992, 3571267520, 4290833338, 2474346395, 3378814420, 3351611512, 1303922942, 3283346580, 1489524774, 1395585068, 91861671, 2943769869, 3412508982, 2507344244, 2586024774, 660828217, 522672644, 2554574189, 4093332175, 1125997685, 3592656249, 1036705155, 2798764932, 3441576709, 392339390, 3489310669, 2596866038, 1947787118, 3696312887, 226298054, 472935459, 505119706, 3783498850, 867650894, 1072853134, 1072568479, 248365064, 3418187906, 1331699784, 3000650397, 1715193485, 3810874498, 66785355, 3344423276, 1996144563, 2793928046, 2180574544, 3767096859, 1540549268, 2389926167, 4274062787, 4121401190, 442584702, 2431090696, 3507775591, 710194452, 1159458607, 2416059535, 1642122860, 3823480937, 2535544964, 668845548, 1661633586, 2857928640, 2314741510, 377317229, 2483955636, 2957445644, 3934139513, 238200907, 2969751595, 4212529507, 2281068873, 1301743382, 1952773150, 1192593223, 3892828784, 4037269943, 1148821772, 391839522, 3504559806, 4173379790, 3085121003, 1474792696, 628152284, 2698025247, 4076939937, 2416300665, 2652295225, 365441928, 670206063, 1553108013, 1932716485, 1558658987, 368881025, 2692123237, 2519631847, 3865945719, 963612609, 2001573437, 161034038, 1883789309, 2496653544, 1909132409, 3269239063, 510666825, 2562655909, 3241797641, 1506218500, 2991308436, 944858691, 2394342093, 3501775324, 3134551643, 1655397291, 1372472782, 1117006576, 3017788232, 568720212, 1600706831, 1262117840, 549706387, 2176848659, 1793986036, 3712714767, 75684922, 3737373740, 630177306, 343378978, 2300438472, 1144716485, 859910517, 846443936, 3312516505, 3320108534, 1661760387, 1112699815, 1474296780, 1964776416, 724080825, 3106608638, 1122986017, 2775133042, 988101895, 116278673, 4169511163, 1001735315, 487463586, 1705207220, 1191915788, 4098138272, 2818005531, 3023730900, 2655878164, 3026173793, 1966505099, 374525789, 1651006603, 3071722751, 1288077227, 2811531267, 3902509872, 356900923, 2715149970, 2252856041, 1766699937, 430591715, 3645482691, 4287397379, 331671751, 2921221743, 4164993604, 2710905723, 3151975289, 2670586646, 3232311359, 1487120535, 104450214, 2011996119, 1378669544, 260533527, 2931634918, 2932587506, 551998172, 2217304186, 3692803012, 1214595277, 2200712189, 31026051, 1314881730, 4252874943, 3922112067, 841640375, 2518926569, 4060391300, 4091059600, 829994243, 473526157, 2969598738, 1569819164, 3269273437, 1687660622, 769790079, 2939858479, 2314982026, 95679934, 2650280721, 1284506574, 2095382569, 3629187443, 2367705831, 2672087363, 659550851, 11251546, 2844951430, 4117036159, 3658960043, 3566145978, 2512143790, 2139258524, 86934552, 267324838, 2221780235, 710419209, 756024368, 323223865, 3778949258, 3816289645, 2219776149, 388834355, 1068024113, 1222179129, 580874345, 1198868104, 1817835984, 4094192509, 3826892475, 52655050, 287659039, 1120108646, 2058392690, 2104203826, 3037610895, 1029726175, 4061743149, 366112992, 346791754, 3821995524, 536509597, 2325629474, 2066675899, 136719370, 1695618401, 4127537516, 2452460370, 341169206, 3738496386, 2767987524, 3190043068, 3016991314, 1985040888, 2078594914, 2139671587, 3776602980, 2341476692, 2570282486, 930489583, 277160411, 1626294789, 3691686855, 4262789355, 1212444490, 2072677275, 3457253017, 2170703287, 666683948, 3333015377, 504864707, 487969583, 1288636011, 1567777164, 1530159893, 3815252539, 2666881166, 3965829243, 1041099897, 656342032, 1028191164, 3915206067, 3690757289, 1762777065, 3803846698, 1266228114, 4076868833, 2399530576, 195016210, 1445885502, 1995001751, 3704589774, 3772778297, 1868741945, 256483377, 467868342, 1640547407, 225595970, 1128094955, 14460666, 4066078010, 1531108057, 2276851512, 3961921308, 1169342968, 374165010, 2374552173, 1981313800, 2852786477, 4281055282, 1639781930, 1322826308, 3962989569, 2251429162, 3816598409, 4202374414, 4064929266, 4168284369, 213598332, 1878654815, 4012592889, 2331662084, 1902718261, 2647610456, 352521621, 220018838, 1635198976, 870981338, 1528262232, 4278709709, 2883394367, 3811471744, 101869306, 1737965113, 5642069, 4097501724, 1259821990, 3670562669, 1974253307, 3684053909, 2405311762, 2106561791, 3003266622, 3144376081, 3347409339, 3029518983, 1386943455, 1931470855, 2440160434, 3815143890, 1950218632, 2764905171, 2625123447, 1837241813, 2329259261, 481118439, 3173225256, 2962727463, 1945440488, 3710596738, 4277813522, 859909239, 3649480114, 3527231066, 1319170120, 2057720939, 1491180621, 453126850, 1871773559, 1890800972, 3318027331, 178171345, 898881946, 585192043, 2316224458, 320531880, 3894139506, 887621194, 1336067791, 3934764232, 2500940598, 753297159, 2270381915, 617165818, 3189476410, 1156481495, 2662137263, 2316205098, 2461186746, 1238818742, 2671302457, 3259197258, 2457707232, 2069915454, 45049564, 4167698335, 1201886883, 582951017, 231483990, 126335446, 3076808505, 912812759, 2501874082, 540273866, 547753220, 1170424177, 3189829517, 708808880, 3129622972, 2002579360, 1870645386, 390169448, 2894707900, 3908460579, 2350579381, 1331709602, 443459340, 3712574777, 1224504425, 206884931, 2378720574, 1020032309, 1560294846, 3882569460, 1581034183, 2420521192, 3533022079, 1115021897, 629573578, 3657301365, 277294527, 553080215, 3028363420, 1291561052, 1328469432, 3338312082, 1338200129, 1766236727, 3416356554, 2978891312, 3082654857, 606657334, 1276316260, 1068554434, 578254253, 1605030828, 1138302318, 1303706914, 979241233, 2741167388, 4202417433, 1219394772, 2054300069, 652415613, 4270613519, 2111897808, 96742901, 4165401801, 3285972425, 510249183, 3584775636, 2783564547, 1562245500, 2730496534, 663355262, 3500910819, 722790975, 1919819672, 2086954706, 253795458, 2005733999, 2970779153, 1467732358, 3926882554, 183736355, 2926165427, 3506297134, 1277594353, 2214151876, 4114889724, 1981267378, 1672821314, 1973092046, 1816211223, 3995013321, 2372975102, 960109327, 515631621, 1141049977, 2556287867, 1599407251, 1420644713, 2146155618, 483793231, 3212064205, 1747734295, 3877264223, 2699801323, 1227467313, 3524136023, 3700565681, 2022634486, 100193147, 976346175, 2047559949, 178497547, 659438932, 693783143, 1025344114, 3296189331, 4234938364, 3519391869, 741867813, 1210413520, 1131945841, 3748089817, 611872932, 502118182, 1727700656, 207851418, 2667971549, 122428996, 1451993464, 2823431360, 1457011744, 3016921746, 3133660679, 199979290, 2570157746, 3883523853, 2905936686, 4032889764, 1341310325, 3955219349, 3754604265, 2731331914, 3325586999, 450131610, 3586820947, 759246962, 3907198611, 524872115, 2765413843, 2883771692, 147272373, 2712175410, 1690171466, 3722496509, 2121634784, 1639601660, 231013188, 1337728573, 1947365408, 1956500101, 251574525, 858236174, 1259381993, 36329478, 1435388981, 285326643, 3274056498, 369851, 2209662002, 3443099831, 2062553205, 1736753981, 3579525503, 3084085035, 406796802, 1551408425, 4209938819, 3342796945, 653033552, 1255972233, 272582735, 516452148, 2007012629, 892881275, 2969869353, 3262627654, 822918090, 2317982905, 1913126099, 3381804467, 3143222829, 798410293, 1697756544, 4038741424, 3291804708, 78220767, 1148496187, 1458398142, 4048000884, 4101585984, 3148543887, 244432076, 882179301, 720217242, 2211718549, 531560575, 2338154942, 3742711210, 3961239456, 1640123469, 790017482, 748840499, 1853629994, 3073906634, 2530890447, 2206461015, 4030211025, 606026839, 4148432480, 3022974668, 1825681328, 1123927944, 2425759081, 863745138, 3994200333, 1662692962, 2415180855, 2354782292, 808261716, 4050305196, 216852620, 358006854, 1426415913, 1552547999, 4131825801, ], &[1], ); } #[cfg(not(feature = "32_bit_limbs"))] { test(&[0, 0, 0, 1], &[1, 0, 1], &[1]); // - xs[0].even() // - y_0.even() test( &[ 7642088996549441618, 16939115288814344947, 4158423030205990745, 8781531266919626472, 4536426036746990718, 2759142628546321348, 2227485206975570894, 4571191084929603686, 9433785736036925989, 1551184301255450043, 6411840578125486860, 12800352943910688520, 17181013235616069321, 685975652320320677, 16307888956108230656, 8336973718541306978, 8755082279744089483, 16569752005561764973, 13002378357019963033, 6860220932393655015, 3560357731840892678, 7070244414620499337, 8840693397681308044, 16290086784750574360, 11733147242613009414, 6107879515762280778, 9376837729905597698, 17040637707038025639, 5177768201776762198, 8518342977048446763, 8898881218619802887, 10329787183129644470, 1526673743209372789, 10123244100180979109, 8726514720133331124, 12821051538345717782, 10882156112794604029, 14910284544698069484, 8872234416399843814, 15937194738982521740, 8503006142727912361, 3966017325452025377, 14700847728548934808, 14256889243292689986, 2528249268802686972, 7286745106660315912, 1439847309446662533, 15901896417657589110, 10477568383848354894, 4553356972647272600, 5529939210774917581, 14963188060984128980, 5375019716695641294, 2457481744426644222, 10485361437428266879, 5046590988101961772, 13198446382534172453, 15426785494942087681, 16124585910119816388, 3012068926694215709, 12864270021749924937, 11383059477645299313, 4320116732205951673, 15221500672825687515, 2665939181257259992, 10163551729206894715, 13893415558679363380, 5611079099597163943, 11092151207759951299, 3992411646432712733, 7869118229635958729, 11130808158108336850, 16931021319887020092, 10589484424862129300, 131590704017469183, 3810734318365068802, 1788964661632163921, 5738706636053906772, 16881608116606909233, 3243306516763190472, 12976245142731989716, 5499515806711091741, 4710317151847171167, 6683556421601504929, 2662551646050148338, 13562673622930528535, 9707043649639400158, 12788296700706707088, 12642829810299517252, 5102876644822332232, 7646892190996074311, 8078207877741285205, 14186421431011741661, 80547895349629461, 14862011566017513150, 77115327325659604, 12406562955874830673, 17375475859238808323, 7716894176906818727, 2802055520431677536, 2762761117974868489, 8210654419852490583, 8128381653654809882, 14172453553140328425, 11087897451444868103, 4396135003820796101, 14219611943052523516, 13587332761182504345, 17711266467744329635, 14950205666228843352, 9666645683806989543, 13020084189388475608, 7037840100396284962, 18373412346854186941, 11498753076197464725, 469550867963885335, 15259714004312508653, 10050610823962070335, 15262036116174229631, 7354344829290616378, 16006636465759715169, 6784457910192993929, 12937757685409325171, 7348103207566204581, 3244695992856053257, 3640146490035082661, 3037244987945809586, 14532227798128191783, 12631736369162945929, 7229210180128729119, 1338706890404586547, 4471472703522570809, 15106263865480071304, 11243988291566356467, 13331144267559269179, 10751519539999242267, 16921431036638007632, 6340810572216327297, 16133593180565445752, 14463917288006420312, 15840542126788846182, 13181419073605341229, 3946982966135895193, 10759326015518767201, 8447608418599844129, 4353759043775104853, 6237067423655196872, 9599085561312857028, 5365643417931112910, 8257457675273138042, 13475654552193991900, 17137537000886946596, 9313010620863889699, 17623954250315027559, 9114405119196504360, 5242451382075890968, 4211561857798749424, 1420640002606510731, 9161162479506033523, 483617176601131098, 5086158402623829536, 8760073747436331817, 5494506533277800577, 9008744669113942127, 7906886502348947807, 460316122106335334, 11348410017111087645, 17743092384644894320, 4543625687376029100, 17638867588777995538, 9728026851704705749, 5787008173309872443, 3036894650402650039, 67106435017645771, 17925489681419424557, 6389173597207372250, 7144011805433357127, 9295381454741344964, 14053113438378634953, 12217843843723167499, 9140869435106275798, 7517027790294614588, 3777825091021737118, 9367707355787166504, 2718655376583649956, 17560908054609622633, 9438653603987629385, 6976020052495124145, 14469978948800476053, 14607968393097793942, 8465948641441613082, 8829499402923220026, 15526274211406668344, 13263426691391304866, 13513707111700176688, 7058023659658993100, 12343251749665219733, 8922907808653322519, 7970367952666929730, 15924847143147976357, 3013336538735001280, 15754712827326735634, 810163294268081647, 11862926494972533447, 17142226521130689167, 16045131138370367308, 7810014550740933303, 11113360618561317801, 4146999428967559431, 13627063951311659386, 14101121524317207001, 17935556847685451236, 12893002441589054692, 4908175619932706667, 8148134223567687298, 2797861052729079969, 14252667124539620702, 3335552068649661178, 706647811473458791, 18284923027330686228, 1353092748991658850, 365920444454436210, 1178722791964549570, 14053600116413155723, 4250093264582203735, 17814207958723924485, 11616162427315300984, 7445813626020939704, 15051244446850726990, 7657749036148962641, 17550408898208013781, 16543784538024296766, 2175464478760404540, 17382259944663939998, 7085519492527115621, 1948795784424831543, 10153333277365682256, 2691142888904508555, 13042656130996531455, 3184232577077893193, 2321647310467391299, 16266534428918597602, 10813170547829807049, 1175296704970889954, 1336221003418894830, 6552922275158000133, 5879504718196828979, 13617292288202891737, 9159008209770128895, 2004574424000467977, 2728245432858568837, 17787384979230748037, 9410299200382955923, 16609139716214733389, 8268702623607434688, 6088812551270982604, 6106049667290975360, 7607520078701557430, 12472853613137360196, 10887056384527664263, 5597819467365735087, 10585294901756958311, 10513460596082524709, 4393150075765782543, 2683577406985854704, 10995282969723658182, 11867305236638382656, 2547454398707374572, 17029951353545530980, 6779642703694514142, 4391116384641001059, 3196785568538169495, 14807958476666083273, 1763112366273599517, 17875511915567196132, 18293280485747533701, 12994911180160214048, 17806815555469749177, 2603276529594432585, 6451629044374772788, 5131789756208165076, 6368584533107989340, 1442599467663039247, 16334140366206405769, 953757322567328280, 7611656048707188221, 16623430410377913689, 16263978152439933144, 1098065150329876092, 8375896578927982994, 7235501216156156538, 10872521053367378484, 1384698101043873340, 7546487270974101281, 16129196974871143949, 6523889198981083995, 3955763266387866205, 223786943533297226, 14312359200553508909, 166525052874074138, 17540833294310979085, 8682296429517930658, 11898411716692651263, 14647731107592123290, 11418813950965759480, 16276766779066588942, 9109613189145192743, 14365061852139334701, 2637416103257879045, 12683017840408065458, 17251784137128610303, 9857440911685680274, 16899637908997360539, 11676396516728162961, 12445807799710831976, 16409119217540007670, 344530427846566793, 10122735096389448235, 2236083202975860367, 7239130410771478229, 10419077940654134530, 3417466820844546773, 14103102709363050632, 8515412940073771511, 16793797293941006006, 2344964963606541868, 1770709333553370373, 11715027939900566010, 6724317159215710203, 13382766807638929554, 6643722639139813184, 1561112814735278829, 15883495724862322390, 16352011717026042684, 11080163213412729696, 2601285403880727060, 17539809965809036336, 11674296212933365440, 6987308431764628640, 8334299117659294638, 8401136336706455, 798056208147687026, 7585403371491023835, 2768563877851444820, 18160865562203294879, 11088989971128700023, 7958399735371734621, 905009938091789825, 3077994674694137685, 17781743814574321612, 9696234199814814695, 14424204686884620898, 12364803790224779557, 3680446812855063956, 10607012459674795622, 14354213044601441446, 7201960041306030417, 2820537475693014763, 6483412063024289487, 8894703326452336808, 6972597094957544888, 3089113953641583877, 14077274888152871698, 11143284357837217212, 6121624755399734066, 14754677241106442954, 14679578243226120309, 18187552762841862364, 7408374060988262333, 17543224593823838775, 9146972686354667307, 11578511243258357402, 7291446516637915248, 4910731754496429968, 6446378869968255622, 5665946125539935002, 14591605513868934991, 7360982275667630490, 12489166270353119720, 652942929868639081, 6195275995865002712, 8128775784532283838, 3387861524647988828, 10206768616721991356, 8310654759157370255, 12396521032462580315, 8378642939179207200, 8913611503978571346, 8964509316769391998, 6983721973747822525, 1620627079682485170, 3550888596803878384, 16764327882472918320, 12418434124596730949, 6492074094596751971, 14522169762543900271, 9643692256647897071, 10018141547919756836, 18119186792532188547, 17605638757524994218, 15110565499291832585, 3859111113510276634, 3608639569011774205, 16841921385542843558, 6333586318389785071, 17712249436612631968, 13651143305566236494, 6282590680802993984, 16962925672131291608, 17070033603299913704, 343263679484429433, 13960595387387109171, 6824567182512993890, 16643055854234833912, 13368136582061640129, 13407186988250747721, 12067851383097839439, 8734440357301460743, 184374602510479264, 1980281157180345466, 18235178046950429926, 12314150621953387389, 235240640756161895, 17191061665928515024, 1450328693825849226, 11658139939358930335, 9661242385016654415, 6544047620238274887, 10076084993639475413, 5484644773132718155, 8122848295214676448, 11451997792866817327, 8014772838878095834, 6738239678981409331, 7524197632536086494, 4887712629149768445, 12755950013597708083, 9072347758799333428, 9892994336906109770, 6658664089339267041, 17010445991373202740, 4749493607011870912, 15469799747835715648, 1410642028794185315, 9678426427615195040, 14603513578231268629, 10144994305300497927, 13627001390827901004, 3410387289467486309, 4969353610007528056, 6899086728498695416, 15840849162291468831, 794809021087797410, 4128395609120946267, 14603570710676978752, 18014301493566032939, 14554900403738652088, 15417180431811963767, 8123851550316828449, 701668417489927407, 7765872186237343224, 3766544625359426110, 11788559991379689715, 4186838184370360996, 184810421200681700, 9708014331923050854, 2038789855438533791, 12063495557069443857, 13840086852848556400, 13600250597329615331, 2088286198469966080, 5800997251215440284, 16245994826244567566, 12426146991432044569, 14174963417820155909, 15950886475654709571, 9625392305352933399, 4560214803933408223, 1220673912062550801, 5315118346179673010, 15305147243304018100, 8860293966649254041, 9878806918352789226, 9948881370845519892, 8051249634924644385, 9524148673689679734, 12489881836910498385, 9483374649969419117, 2429047588791105172, 15948533481260088039, 6658948169399436464, 7055385462316586853, 6444492735173712353, 12554099647303616570, 9411408437418751476, 3119186149878145385, 11561271469129136960, 4699043282095308564, 13664860088579707042, 11942040945216924956, 14938303604593577988, 6584398232469323882, 12615016316841274906, 17607035342042230816, 16299371719180977481, 9410230100515705546, 468652639351146679, 3099794389553133390, 7426463649192631643, 17220440064639262443, 249838037562419695, 12394557669144716810, 11891068226864790195, 6815470691731709960, 17050323216000491320, 17149156625587840029, 2840995912779779709, 16453929939061252876, 10865711713754680427, 17257962606206172361, 17324377803464599290, 9988049752693630171, 5145541150836693762, 18187548404778944247, 9897108837353120002, 17915722858353969777, 11223487437202128974, 3382309055960184808, 4470363898167775120, 15118823731598210162, 12451723255995030474, 12124942937255563460, 7883323618797267364, 11734899536152960444, 10899101530358100831, 14568463402558702580, 3589575239343156021, 9506082963977245397, 6269914352444216904, 9641949985442899274, 9484754331399933603, 7969595927070810042, 13794981515289100280, 9170567771554076837, 2138421182270581614, 788654717547257666, 7557048352969552118, 10073066668613087627, 18136047902767483818, 4883457934069327911, 6904157286973811264, 480950235088373409, 2214051188032927994, 8438459334885401002, 3359421640238953931, 18193289130141312662, 211796784365007412, 16550107280222789371, 9368274586857413302, 4080579477676412391, 3903589165729627543, 14601294347577892827, 17880615106796162585, 8399371980131050682, 17125581143302260392, 5236347897105180310, 373897691749512425, 13424896419381837167, 7230320496289832265, 9814225131983506715, 3257434254689569664, 15321426119731656450, 248987497038801136, 9132125928890530860, 18068784670509956259, 3834280479551637249, 12658772951095410532, 17093119016378053719, 14830343788339267922, 13054493939738291239, 7771905415521456170, 1347652221288704059, 2017715827457192133, 12475851911823933261, 5352012646013352728, 1878283153860510081, 9615556940143309330, 15598414798481854843, 9895563858845368344, 4068766894729575171, 13899464982406282747, 5859039026557422063, 17961018624926257461, 11439432659782104572, 10132383873951727022, 5668113599918475821, 5618863243783853619, 5296033916369028410, 8363560482197001010, 17475747004498994800, 8474583485147508303, 15911459900369709149, 12741330330991532249, 11847973179510376732, 16000211930346393780, 4738554376721879132, 11907835399609080296, 12646339508581669507, 12828924555217992033, 2386658548311295777, 4342638340328301062, 2558348042546117915, 1515754464721209816, 785688177042406742, 3053211873647924192, 14014331870834149810, 264938968394967629, 5983753879589540684, 267963444144320487, 1239629907294807005, 12062955612488831436, 17308841949048522703, 330482381584177401, 9514664837122696614, 6020475790972444309, 10895879821954360044, 17337803144194880578, 924273726463533426, 16535207821268418094, 8946410913169111340, 16060878889863712458, 15976666724330243304, 15895420185200619297, 10599438926533659781, 16395937774576899123, 1515688300207881192, 17269912862206470571, 4692813434396761996, 9815072710015129472, 8355648274808220440, 13388537609750517047, 17672336807467300633, 6893196003223183422, 1850026996207184577, 9739088825020961086, 10065083987816724431, 4941592917350004042, 7273197156716880397, 11764185831933564101, 3813114017041525493, 3604220821878800267, 8830614448851343613, 15764272711157879112, 15343520873072014909, 17833333986739184436, 11899253527412743432, 6319626654591461445, 8345841242755999512, 13969872924667267068, 14689808446598116235, 5690698738679570394, 16232574524853907406, 16476305072233006134, 3837644082952742591, 18371118811121083512, 6370089221943156975, 3758433368774128127, 12598095657509455351, 15041255601684463158, 219849898456894054, 16347148290535489696, 2952439398365618718, 6463887126673004054, 18006657361418901576, 15554865575024552259, 244493720680004046, 246212287818939397, 8391531415221668572, 17158996591507713973, 1574344884166927127, 2139609011514148330, 15894388729950489361, 14150049620712128466, 13649351261368190439, 12818010881632991653, 15846311295084438832, 18136287659718690601, 17778892669314265107, 17919810337867516752, 14238683656303095043, 9767662762617787421, 8792587365945756712, 16289324204380888977, 12145397565479495717, 13131505318922744869, 3537402907198034169, 15773157789160883228, 13080220658691776576, 14801888581508580861, 4455998795552535017, 11468446901913315682, 8764904591192407340, 16992093112328572788, 14539148855227682162, 9062932246611746862, 12092139254667251241, 16973622956249392518, 2330107601262713612, 14104249685295227139, 7802927139367928835, 17015267038524278700, 8076057374240890515, 15166827418715942805, 12316102967608917038, 5048442745443715233, 14352260581070172244, 18429764753411235196, 290907609897930421, 12832680942495754212, 17691084325410578048, 996179388827615558, 15796651271292023703, 18430169649438059546, 12951979241393380884, 694335279970980851, 6638967085265053633, 17595649263141354482, 4234846945003198207, 8367354156647080658, 17456583496028677793, 17835204410247184698, 13301357937590556083, 6786278664181009598, 3297223935318868177, 16554057669712072231, 12522453888866796248, 1975238565343362470, 10528848975094257154, 10553418118214937237, 13409190148243583780, 5006922367367242363, 13556726007351092492, 7783632275488805468, 9183676289046305416, 15469154331779684343, 13423499673227845431, 7837948571314497011, 2029560205070039291, 16649457177034615332, 13491227518645198090, 9993378618273883553, 8487159310535624111, 2809530522983207601, 13575910212973157992, 2171679949756077498, 1660890720446202624, 15646142722510171608, 16932531575310315514, 13775138986080338436, 10735540465035236537, 7604129283442046332, 12444305356219135513, 18201551442306471158, 11120131523005131855, 2798231246691818759, 15317641731597026057, 8499616562041083838, 6017032731278071224, 1273341979567250231, 6519997694567640478, 2435912850700538815, 169204604573595693, 18269270505596175452, 17459024018388721732, 8266385672999361049, 10680903187132175198, 17375563191275197987, 337068133283788118, 16239907884128954657, 17641011679183022712, 2366475531220210250, 10755304562557576337, 1869838694309764714, 8258555369397490418, 962287818495402559, 4995654753554910199, 11059451160990599794, 10810204279841400750, 1456068596599679097, 7305003907755693862, 14988290547736996217, 6795308809242518240, 8763020957272447790, 3308001334228530973, 16974667325340586198, 991537759276291502, 18008237326885742575, 7753905923063895580, 17512543097224696770, 3595225617413761186, 15058630498302531631, 6622110332814961401, 12488257875553353319, 9044137245617220882, 10271290501572288378, 5585777756799704531, 8295396987659231737, 9215167333658814611, 11104586326674499796, 3810019579782011422, 6888760568785282460, 14532837177301113100, 977805367496486072, 14965851872869659150, 11134550780907874822, 8067904641271727206, 16240490643234968341, 10640644051933721969, 12823704007775718263, 13210674225658496740, 17421304180276102080, 8863993590195462492, 5419546058165868071, 14184558657599665798, 12923876509266120971, 6685006207471871309, 7704595961550622452, 17285923828421938855, 3505207992795309843, 4532252029642664133, 726816466976184004, 10742313034328351171, 15565587799659267510, 6490375145545887919, 17152573783466503447, 15997997319822869691, 10153243598033053836, 9623317771768820586, 15946877188272739767, 6079621748092093763, 4005237073110529685, 10324349804736126549, 2979775683162494848, 12357491130084004088, 6870626476679302958, 15875069688841775050, 7544803566766537053, 6558561331652540514, 11395728505159480348, 15150381432396177515, 1619752167122893719, 9372894574032628757, 4772175913517010825, 16565939614554921583, 15177791327910370589, 4034037178193525662, 14253679894187996439, 4373435865471950380, 9110620573126725481, 15888647814967051075, 15867477839426284043, 18263083430840355206, 3572721603558989476, 18033901510983288634, 11740707689919057494, 1919396080344872985, 4785878236873911753, 9518697307553186252, 2196912231764078547, 16859172788282672634, 1294478177294091838, 3853855925306587869, 5712176474426944553, 10655739333433675017, 16864687770354405683, 479733567774176546, 4002525199861551470, 17884530730667206604, 13118987544304899067, 16693510145083648654, 4348762192364479250, 15651674952754110111, 12941615268132778668, 3413954408450272001, 6437132444235811404, 5911780604883628493, 7027061191226541890, 4541332504662688699, 15278256850661601886, 8783983716478722525, 6762972941032427523, 109436002367794738, 4964075549363170179, 13998615704165248071, 15840448835251983621, 17124026628251673729, 451007725533524973, 8689993352441934927, 8085937255579820677, 15895079089926267008, 9033950962733316797, 16460182791232706419, 11706751917248926231, 1518070523274778714, 12841484353662177921, 1106444835771962416, 3781633741335232752, 7295048037310303538, 3078350382473633321, 5513880551571688035, 14511804401958832310, 14686668965111665491, 1334848572346842714, 13785608726613289908, 5484295527088560108, 4677427364593276486, 10739032089578444339, 9118829737688197133, 2599009188037666293, 6541018502379686045, 15124406767918971296, 13898029149245587181, 7049797326321056181, 7676359806921760851, 9359455871357711051, 13721511461701704493, 4337948462861507669, 12182314864880410336, 18115088039222630086, 13611666747148849963, 16979677843375636930, 13976122741306049418, 15131996055772953287, 5019533830870398293, 17994426892860907985, 12238472482719268447, 8485137745688214163, 10046713214813218322, 9981765980097884884, 5203049149404803705, 5509439206475409607, 16646013403333676735, 5721376623514557165, 17895610288116512634, 4146710226708894505, 4180329068470310700, 15333932579841565344, 14578826506899561228, 11125461119487324145, 7828598169855633640, 13016918249925390910, 11596786187817182424, 3070363472909089566, 13372064806216785587, 16483915751021484392, 3209300474080959275, 9744396152477868876, 5286486708506722214, 13334231276589469146, 1703296437445864549, 6990559773807735786, 4323851084064743622, 8258191458458530560, 5487559074143580665, 14530068425901775586, 13125628672642465590, 7919522946763693741, 11383708583361967263, 8699024886208260276, 5911243921359438557, 2976618942061378858, 101882160229833275, 14947300507963600168, 2624952948637079445, 13110311834336189786, 6328067748328586264, 8026502157595153247, 13077832359361647005, 18034926555389756245, 10932060114415829114, 8921112613501153906, 5010993000512607919, 15729519684045200720, 4230394140032073806, 18249470456439233157, 16698231796621617025, 4922479776459643659, 7326057194769023839, 16485955343145773710, 9357885960145954762, 4908643074768640635, 9426875174076058663, 6269667367780881933, 16372434513892687866, 8166317811376426944, 14210102553507463054, ], &[ 1979867317777782919, 458803043038589105, 14807455935956247393, 102755393029177892, 13661879760043023426, 12743502586850908641, 6485502394763823003, 7006537482591563738, 13464897952724427622, 110941783775954905, 664806907968747258, 13976172522383104680, 7081409417990232579, 11782066704046559999, 15078720815504238982, 2791066361698645774, 1957006820108785098, 7661621907711528521, 7129856627939149071, 12464578713097949843, 12568595944828213000, 5103092420263283198, 15856125363599807684, 12992729636796940656, 10878188187148816380, 2850172728651555239, 5248002320936640091, 6759153103556744157, 14339593489124645610, 18317489909052141708, 15949249147341703950, 9001038595758313121, 11504712957931727005, 8187691649773049259, 12626028481208875277, 12844051055584824684, 9111532080412358373, 11481281377490778456, 9905077354469164626, 10848129645301488797, 12407190902965064104, 3004380005013311524, 7260177637980150880, 6465761219435617351, 11687902913416861598, 11582630797299992145, 5052207193612544256, 10619895585106656895, 3782849494513349232, 1696521729205924429, 205289556233949352, 2309142630958879699, 18013220874964165818, 8780365515667787572, 10777210546602678450, 16689458940952011084, 8786023929671818084, 2959945332887060564, 12595094201729105975, 10555858515424418250, 17838802570355306753, 9768848979007259380, 6400634551878490492, 9350070212380397383, 10825325059459528805, 16240713222773986945, 6773516716020300636, 18379586867066835204, 13392009122775849047, 17446114650305191430, 3443249317411513199, 16590433388663762614, 3592506842077891585, 2547605864889189098, 8921931064104759283, 3745288943697428348, 6683293017020997233, 7599775167852553507, 11479579422714965337, 12242916146470334290, 15886988537674743805, 8027185433862293631, 5037238148478185925, 10545897273866342364, 3749333810592645893, 7567899208857364441, 17332217733795476186, 14570089467947298319, 10687712370800535186, 8398127082315689224, 18138318481654121301, 2550529540627040228, 174434346470095983, 6335843839776953618, 2142199594346057908, 7492814286032687084, 4581612999630224238, 17362182859125741557, 15332694635712824041, 305820774489411582, 11087741421794954545, 8166298207140013628, 13663827369108026131, 11609249890319933551, 4708689618714214726, 31696613282352588, 6229354554698145266, 4430381785479249873, 9093084456389745185, 8620628652860035454, 11032119279655454850, 7436388409999188798, 4508581046303828766, 9266330334354028474, 4654094790776695762, 10477920368471986136, 3040546382665779497, 13578021419513941070, 10874037816916517318, 209250739982139053, 5513314962388268387, 2276087999654805974, 14116993918737387242, 10215096397828559307, 4706886349596564784, 9496675948395405688, 2592786526073230109, 12032023929905220888, 11439071011556767245, 8896841450411382115, 812528333048514747, 4857507773721570306, 2346347769853663620, 893640476967692732, 6002646205477400496, 1258104196359799910, 3298555154777830453, 9831348292240867254, 2983777286176645688, 14012697848669764867, 3281297577197824417, 4818243357287928570, 7599542312723359299, 16303740951463015372, 9530417675969610545, 14307310939799846427, 9411915044625670774, 3098269527533968285, 16636400423591714570, 13575763948252176199, 5311264796988234687, 12230662710526328293, 15591605225575960535, 16170866454635856185, 7154393582831771624, 9746836435275228439, 13154372386985050769, 13955058214451317887, 468470833133904286, 719628130899837785, 14167898993266425767, 10492242376823879424, 4695877358022833681, 14415659841083920049, 2128453387083764523, 17254215071478848692, 3464552401256088318, 5473802745477872406, 12278908178174546508, 10917423561691292478, 8269556840984708513, 15451525009059595276, 14506788958072783738, 10120241313842466204, 897911062165781450, 10413013565287912000, 5183133159721680857, 15306474298436567422, 2072549059193978699, 4803937018033002282, 4902316829203079235, 17182047496719608796, 16148451990121486069, 14460165826013687805, 10861828715214694182, 12852802503672044251, 17897814519242488317, 12830584456010343195, 5025833892983477930, 15171169537313884434, 904875646680899456, 3891209230657191180, 4459567895597613958, 10213064404613271715, 14464647608623247371, 16076880745118924462, 5651027014515376452, 6845292042507662562, 4700263749108232739, 11912023508343584677, 15164089726347867289, 7435959069204688586, 3673845585791184955, 9008233584340774048, 623672340235969578, 15952660561845258442, 15255827823417955924, 403762546093465841, 9023129674293106279, 15962739700493341062, 6108426038775323673, 11423092137795750189, 1431075448616656956, 17640578768263514852, 9182353610308928359, 17753229409310170357, 13898814437210093610, 12126245547088496216, 10888527319957075641, 16039715754410307348, 628180706859646675, 11343014058184488762, 13075222209229766794, 9658840972156173472, 14805748267851325307, 5640565628362124114, 8813449713167462710, 14750431340071075257, 7341247484352499222, 4105134027480979119, 5063597277155075543, 10245719632899271147, 17417102409056111607, 12327200750635056279, 11257956633392412563, 15654204403173941169, 16887277320373649913, 17293310148654704869, 2931320393510833429, 18265112369378689230, 16177931273491220730, 7148441830138947268, 2542111810786801658, 13075348024340421114, 15045402682302144848, 17729484015706193097, 14849701582062849098, 4494999822131844988, 13853067439918054754, 11104593802418852948, 6272834726309696758, 8176562272197586716, 11136460055946228459, 2249625026165448849, 15192391646155487262, 16462654425479085870, 12438135124930472309, 4231754137003607533, 7025530078224271576, 1902066619924498430, 16798677464948394620, 16103591627987069524, 6073783480651248517, 2301126056878392650, 525873165339288975, 3654812541302834250, 4237734633374880968, 7013648087246440503, 2708020996911432507, 410030825299234570, 11409023582536021944, 807125820884538678, 17085267726135611778, 9547871053479185317, 11213262078356721077, 9638233998727018009, 6181404851731546121, 13509648795699246119, 11626561711623336962, 2367028127797295412, 14408238933122914429, 9501259205390120800, 5388820411015324736, 17908911641461106076, 423710192565734379, 9911666373654831039, 7296600371969340330, 16104674231020469855, 17273935562508193984, 13386092434346383645, 10904128763248841619, 15660801723929131082, 1802676326982826038, 16314898646999153588, 11051772565381291670, 9582949690895199194, 16665669325627731401, 1675659856826747750, 13282418735625888151, 7647864912575263910, 414802336339416341, 7456128243593571890, 7401454041271044889, 7259681585053156654, 10297473634673620153, 6291331063601368350, 6858202795057797026, 2331669818605326975, 12264404420708345107, 12089542543065457441, 3633020299658155421, 18428329446154081698, 16353160654361289944, 5081398862696143362, 6121111800778820791, 14309612314653801386, 13306300382927317704, 3064838612410500446, 14989006580151485936, 12725645885424440632, 5569344928439882604, 11093264756688684425, 2529531794792252742, 7787364529152520016, 12100725195740947792, 11015410010827498630, 12770939750081523925, 16423905424192297733, 11305841527114312073, 16891896558850432433, 3225706379047965263, 14166563803489592930, 2355248555503091815, 5476494996858779102, 15360364114708065353, 2946255509562408083, 6223737602577045649, 785528028405825827, 7297867173505941067, 4724393265215111794, 14532649034725999985, 4217904748666774400, 11309973650332868442, 4820265912884088727, 14053660458609997460, 3483460907245444911, 4888448412579236860, 8902978947161354892, 1161291241547718844, 4827742954141797453, 17959154045662307166, 12471977193177859473, 8286419873042983353, 7559677115080818717, 6009725396648616438, 7950724447316580461, 12082875173598285235, 3123141200374415061, 7736739371326140224, 9033893194019001400, 17119540472038591893, 6838993250758979381, 1756627985014158028, 11540944119317576836, 7167619835597129390, 6344439141314015967, 2159381790958961231, 8723275234827128314, 14671976335382244081, 7492612374298612857, 16983115979216019630, 1137928104103949457, 17705437622823562319, 13213748898063588558, 11565618477779377046, 4479222060769626300, 12657805467897134295, 8578789730380785090, 3568050214652067765, 17264603982687227099, 7554571839983616835, 1648213353577773226, 12805556496169022728, 12400854649388722924, 12743032680153521053, 18027191329575892747, 9029998509699231947, ], &[3], ); test( &[ 7798496952823407824, 4811470598592046480, 16634149002718209756, 2816485763131163737, 6764931459572097898, 12135396153038963217, 4726251464409773649, 8573439160265568957, 14269672704267810519, 7649448254104194910, 12613439096551355375, 6638659391603712256, 9240011195460328922, 12704753717311876709, 7176884384156072417, 13235015177754973669, 14756487689013468042, 9212292110542328191, 2882513161370093736, 64849663354449995, 4532026566849740479, 407205524552954739, 16398190979531467263, 5875928748346174530, 10796369575411951617, 14293424794963768678, 9366522120560533977, 4213967089717524150, 13763075659281951487, 13464968737596420936, 6549141323160628420, 110915844406990687, 18075287808720180110, 16664063901861004820, 9897000415442332787, 1486075656392074792, 7382904500810297215, 3592293622273342942, 10008125746032292648, 18321114734333840332, 17920212203847604612, 11217657766511696793, 11281083380440747080, 7892713234117558634, 8902471323128328235, 11892365124252837749, 12611508814807140936, 11815551321438701427, 18110749687253320811, 11715728409437156086, 3339319126985623378, 6325617411041006209, 14096883611650388622, 17687808067973538964, 168019485471086672, 15693590891786235960, 2786725115760255375, 9052512570921605652, 14177547685319586247, 15370386165587184937, 5970865523433924174, 8584955417200346406, 17233739694187471127, 3635034994393071086, 12922974184613453425, 283176399532113592, 9116715092600674482, 533178685039585111, 5221528600415982001, 16669037965261793667, 9659393188345721976, 1619537891333142145, 13016156940489086061, 5348093554893488672, 4125157131954041036, 17147602453512343883, 12283659650945459472, 6073750737922483302, 4112966256314115607, 12848281534595730436, 11698310578341605232, 12515024339763963627, 16720191980955784273, 16331343356415214175, 55095711946944202, 470353114021282512, 18440424164986645711, 7119069413231791773, 7496499681661981147, 8033047773523053512, 964312760862509573, 3077830922660773095, 155832606423296496, 13447886967389293275, 8559367474278812445, 17998261191861118766, 9631655612257511488, 4223841702086601452, 15213562135345686189, 13421535853495283983, 14214420071333045458, 4946777332360956414, 4831925713285482008, 11760595051618114799, 1418683958686722085, 10071047199952333941, 9860212880469572414, 5658526438682259927, 3208658863323316983, 13572249994839707422, 10858577727713550259, 3187235617013222032, 5876918919503422475, 5078114263735950174, 1124267584430625852, 12765353279431679058, 11774222431813768840, 17690097956396545959, 11327308747698708585, 3866755026407601622, 4133257169702318528, 10187715330446905330, 2618131060603979377, 14909622824179687974, 3131981152941396860, 15758444864200993797, 15877508051463207022, 17810056601280430664, 13308597888743200162, 14765083240575543194, 8389207789402457515, 16638724707073855749, 17831200813330442342, 885536911921616113, 15627100060180098369, 13529643776104497044, 13063738574432590840, 3409549155326214534, 13384107634300554710, 14621110597375575515, 10454034361196971254, 8866597122119704829, 7214280631032588417, 2321851294623259950, 2664600902577903557, 8206930671630553011, 11637903730276320737, 6120862895588039690, 10119555767934669183, 15072606566681932076, 9196021740659767391, 17668381905754714807, 14113831610785889688, 2274519386441753024, 16941927109776392899, 8855427208083419550, 8707706292745593239, 6509438127169345769, 7049981796161059741, 14351405462508747882, 8739674628274889331, 17773549691926711863, 16108213739701189254, 46349353234791966, 16335307352245544894, 3372116134019651210, 2026650829541426733, 14482558945555858306, 12178227313839428552, 379954005080389912, 11703446819120251215, 13961335387977718269, 13253644918378197554, 8389008141245407942, 3757779100833278863, 16977903525629057562, 8706100545828799795, 4980644394686364078, 16602809003881382792, 4704649122813882219, 397591639474341233, 5691615138943748269, 11603908706905475525, 7830467758888891027, 752954507775914877, 13742220678588369779, 5512709449415473472, 6602314973830649238, 17294329281209674921, 16353762684852197024, 5198076929899652796, 2451984573929623323, 971255382782649783, 1825437488761527279, 13282135031519430271, 15671289983850977417, 3215788959201267209, 11367230670788525763, 15158322487047971358, 16383227556481842658, 9272710553939316379, 6940559952311103297, 8058002679263304409, 9200541971370090762, 13026270051739823047, 14703602147590614957, 12270036121815530821, 10856837658238904154, 13457513436452657022, 7752098762039414070, 5159679976569317358, 7346882116989161530, 17098000856751349286, 7528478613810311492, 14595271732066598782, 14345174012514521088, 8917561215963658071, 12444774771012436781, 18003493577034559128, 7401267539893108958, 10703654441621295266, 3928975917156990612, 12068658501017100188, 14247190926978777640, 11887379833560086066, 16388813962188846581, 381956448283854400, 14770881628537066339, 12486489047707489763, 6358578569341757564, 14298750548968079945, 2056466734423394877, 6368203595950482405, 3223554386699468954, 4227760395094299567, 8534762536962691709, 12548903028463843885, 4967345662728519086, 16943637153763582029, 14715091124220815237, 12141001306263104014, 12175816912849205543, 1803108872161511343, 13641105341345940724, 4467984689873651089, 1855564851398276223, 9806860208915759902, 15434907399817341842, 6414202967398339339, 1952032742127311977, 11903471585924758516, 1684708809058774974, 9584411782518918504, 10773185872250646792, 8181377602390776035, 8122154254362200238, 12902500799759276861, 6582720162263342292, 16706580731489248920, 2000050292502342191, 13921749765600186584, 15656774592958567364, 13515604429385540270, 12553127158817424021, 7759293979203731105, 11524585147783123654, 2416828035660522180, 3815782196161663623, 12068235656126232794, 9641578300488516781, 9227047490937534043, 12288329318600678892, 14357764900702876515, 6643728818780923790, 9169952627439601524, 16190860163944860685, 7224449977289312853, 2426010657612704988, 7097348057731348819, 13428085588675193837, 2243566205788137318, 3521617463718109980, 10311601150383225693, 18028456914623038645, 10958023041184848012, 4863849643405996604, 13982944808354970647, 5078862720378429165, 6995084509678946294, 7623261163534034449, 7251391284527626801, 6642144335648839474, 889957175812482926, 14115678510823527946, 10943283669987163106, 18022097549698166076, 1064779896422972216, 260976419678710154, 11706337798784823402, 7339908486105356132, 8990824151888743890, 5645262432865657530, 1657496751968765591, 3530038441891535071, 11181694072782782766, 10650389332231278211, 15390473409517527604, 13153289830091656667, 12038556920917300027, 18066231150944097445, 1618038226618345054, 3389192047673882355, 11082945276561617384, 6705349877566422413, 9781054992335109493, 12253545225617312403, 16999500068120091746, 8769791004306726764, 4768271990176342717, 16794616123670513863, 3996402883485570523, 9211678469009515216, 14027728220422542365, 10496749002692321926, 11703646058430893877, 12334209370443949878, 11449604462076360388, 4396255705900668331, 14533140968852883773, 3491798162892333300, 3038311448490854168, 13013057516520639140, 5160377804146514933, 14399436147471941106, 11193864615898836432, 8531481285844220199, 3654104119756094460, 14734961005960740209, 3654191345397549727, 8388858864047403816, 17927724813621687727, 13429016298799125048, 5367750080313919027, 6393224854041665242, 4821520064553474661, 8442502022517558844, 7752658698916624934, 9550072160911665752, 4540818189505722827, 5059997612305268209, 7060253925263482470, 5083054112761819250, 5803398198426211912, 1380106897985489402, 18071437738740065909, 1345071843572391414, 15710434610483386531, 11071377898640965589, 17641605384866702714, 14870360628358138696, 9827129489073260439, 8450415892983753145, 15666761634961775100, 7270545221532941060, 12053279433290804257, 1622313886640544491, 5340667040115210848, 926087624946022227, 7935611017520266364, 14642870615373560695, 3125283099898630391, 2050649978125224472, 205120195037820803, 747063854179462342, 3789699371533579595, 1035701621096547349, 16018212365729931952, 3789866428655158698, 6388723914616296058, 16510613621210149584, 9894647709359168130, 3013404062090041115, 189489053932127657, 10633648435212574812, 10348107062615836735, 12002471873905392969, 4237459592751843708, 11637939215779621043, 14922365631690025380, 11760271887075563159, 678386638816913540, 8019936738073295856, 3836915660118827695, 8019505309874069847, 7265558081469259310, 884417125200105927, 1753033849914718324, 12690803762933082738, 2546869581652302833, 16955148199618032179, 11708042465849324633, 205152477319765645, 16629796025665189045, 4790774024455362541, 17402843893609042859, 14744403841742504335, 9084693659612921572, 3083238898476439769, 5569669417086302690, 8634335868370264618, 17597532536692475916, 6829124881401627081, 16057844520727040534, 4393594275785544998, 16870174283907099328, 16864947511372305749, 7933670409689289709, 8062243686940958546, 11511723944420066352, 5390996783507099517, 13514845063338313048, 9120727178683820530, 7135404489830930274, 4698074799063558795, 1336268150592162916, 3371186837701723352, 12497753092049419593, 10662480898239412552, 17887743751120115746, 8037614308177933475, 15269519858742411375, 10429730734252577378, 1782248407797168163, 13511127986090773154, 9879755090209915206, 1548237506818739800, 15336522777265989638, 16083355574386989716, 6892661436203042392, 17708965875006543343, 12487267807383327705, 12371079313118864644, 14239391039731513177, 9712715537776006647, 1339505136772159105, 3012551510428362794, 12357355653088287352, 8187824344238681106, 3206470745685510953, 16525705376900723725, 17797473822898581012, 14891087890601797179, 3429920644657740961, 372799842385126583, 10159920898351373304, 17084534135671018643, 13674012061365744215, 9062521393516717101, 16249511416435877582, 770466755139844308, 9792258604515956754, 9847259338113774618, 6524319705326716888, 1309518254525408764, 10346103312499662230, 7796705521616045141, 5244441786886038342, 8458019209005484172, 7382931637777326782, 11162469257770583764, 10053536657529816615, 14155165939639076903, 3216040867013041656, 9855256377105714377, 13333494298177667840, 13870977529578497762, 17702198111172052493, 7063132479007076033, 15117903718709274386, 15643124275645359631, 13246097376953615105, 13943153081968370799, 4129477198714818132, 11857346290084810717, 6481315132425963863, 5719683682695494401, 5296814144172527318, 760666829981906503, 5590808134778217760, 756772015698441472, 14491844706456542800, 18082567968363957214, 9270285920051865537, 14699652027310128713, 18248498453132658193, 11684467957653234109, 15881769941581835167, 314546154914222688, 8114343064128916817, 15594029378006079537, 7306033488226269464, 13428690195826711521, 9052721018056013484, 5948173439127948390, 15052909961655625285, 7325957567666136697, 7255216113309866460, 2339005174917919375, 3541464599868150096, 10620807105734506848, 10401555768719983049, 3223209184831011265, 13219238608657336815, 833402815708396065, 5409227984281460817, 9625361525616921089, 1310345922942938948, 3164590508354402136, 13571591791085099481, 6449583851417093650, 12132073172938161206, 8472582943832045347, 10769099083212939156, 31772634679058711, 17768858162967447980, 3724817912633131560, 16347858930007720615, 4581178512905307749, 14675184379874252691, 7800880386417268233, 10500558640555793613, 10907473822263746966, 10349360455162450796, 16243419016207551444, 7948477362985436355, 5648370989495638971, 12554130341333656507, 5387445954608484822, 2435984528448136931, 15926990095133510448, 6240279474886617484, 13162027311361639933, 9845498081224385677, 15136770857402679488, 294172832127927540, 11812753576130759285, 4714994681116169573, 16515438329473328309, 12715644809880958907, 2687151289233831920, 705088298937614828, 286079974305964184, 9155582999882597057, 8821011997760107375, 4417717245202189035, 12959997704010734603, 8879211443564867802, 13288247630269789338, 17556983875558228264, 6934174419250934018, 5626105851946025353, 4683143168831417573, 13583545217544294035, 14621427723839799891, 10439845563205327853, 7115341531213749311, 5705625326650783712, 6329845201407641639, 6588043698151966955, 16484557210962277459, 15151791142829317538, 15329622087488955522, 9042731875468481521, 11804081118316930516, 16855488448748462109, 14875244187197991269, 10172305946442195983, 8757636627949073627, 5243026113735495788, 8936037042873886159, 4876890161176869416, 18006537171731967094, 12374747388220381150, 11864668767677461873, 7189191550084420743, 11292555383413732769, 7884526425467136896, 15623541190026103730, 11092209719983693999, 8028450957205620326, 2499868879825625711, 10808424434450244851, 1850120526551312291, 3579487434391430254, 7970110833128773015, 11502636942992378521, 16957022813958395608, 6038123073412640652, 10534237287670598452, 17692645144952827790, 5499913016452810923, 9577924119610418763, 11827916510345201494, 5412361981268336080, 4983789128726775001, 9907721766352553361, 7746668222533981953, 1540831215979961919, 7169664330498339513, 7180697286303485988, 10347276511906245411, 10823488766645044528, 6133595352212519820, 16312710139973589114, 9648734934782395917, 6873899491086510519, 15241958636619718674, 16002332770379796259, 11637713949810347145, 13428135478576143504, 4025997171210729991, 5342284361833989558, 1000822021319843263, 9261749846705840856, 3617262093116689162, 17942289330270390442, 11385597809028053659, 7287780710901341369, 14762598407984080840, 4264460461385592109, 14094826370185134517, 3283046943932850948, 90170700188501807, 10674057436346217291, 5644642641840061204, 14527433886721542373, 2131222867340329316, 196797277728757979, 5366091626020562492, 3409153327989827025, 4841679307319540953, 17375418154652407166, 10510576230334042050, 10924962062840002463, 15837684901594184503, 4027939380558138063, 4777859749711837977, 10339218989308260901, 1733730490652215991, 17672772903076977070, 4032065712363831295, 2119394036996489161, 987475587307386853, 16359915610191834692, 2709426785752979104, 10375088739222959162, 3980631508144303014, 7635434081101942188, 9892236427381386255, 11126971916211561413, 18061085022989404170, 4126100172567117562, 15208180968378211631, 6986134894614109495, 9994988553517585717, 2632796961456398601, 12453342373460829884, 18429381111478672292, 6111081134345892184, 11421541247114134041, 13469814569972052947, ], &[ 4315916980033521479, 10449503521530616424, 4856252820643173925, 5526086074914510628, 4004011662776259923, 5158952861074217646, 11028260963063447109, 1944236596442929396, 12978824640840365242, 1151930226841764512, 10613193664134350842, 3406265646941928560, 6672407465186936153, 404800540740440978, 7124533336742235930, 1535890670990966696, 9493802817341566679, 621347847648491799, 17912640652451605620, 2057204868614013785, 10921553714374066298, 15047552947027887029, 7153383190925766965, 15249704771014948657, 60519377435496530, 7590844620858428748, 2351909720781490663, 10190678499481197044, 11234076827730248200, 8663598726765213238, 14736154147389138508, 7450150289749363751, 9994057649404380563, 10753782001926929150, 10644356419589646708, 15190339138217087552, 2505074458053073474, 16648880076747597464, 7963405054197062708, 18208284408934866346, 13858469707329190922, 15486996602241633122, 15371317889350309918, 4743078453820751273, 14468006621724512200, 11417572129138578356, 1945302117073820127, 15602118317671954659, 17407209257242841534, 17548975927464502643, 13226541172879034674, 2166519041665030706, 7724204530219097389, 10010504212552996397, 17838743458463889271, 11013562737265801641, 17168811270168264857, 5237040028916263925, 6323527791308699056, 15194073900873025387, 3202913343800201178, 1168012655630214373, 9877657453665156045, 5804139521458303612, 6595671049679611796, 6954590572896979451, 4507247193899927433, 14712120891718480637, 5958832049354060597, 5425095238966069586, 17880721668223019279, 13362575027039102816, 96566741790470098, 14428275782443426147, 7864448756177300200, 2963734043870314563, 3442157303656685599, 8099372328576403206, 5242482823389764537, 16276205423603762402, 9018844860545664107, 8496776552307752745, 3126198658080841968, 17584426086604861041, 1756526742975593168, 2722838766637822731, 10403662163231417462, 18139392105860519830, 6989823411439348939, 14393884001575488137, 1056172704485379305, 2679761112328917598, 9221013185085765008, 8290458915554542198, 8622981061497119850, 10021485082278739094, 10922752463306949341, 3289501128306314106, 17397609516531025243, 6547400758074542842, 15604289899859356945, 333978770812190992, 18218065973916833475, 16127810661386041132, 11230122129491639064, 6981851969231440484, 7558646420357403778, 14981775577710827750, 1746996883223053842, 13747448642231442753, 284062948563354937, 16854308500433009747, 4830313735216528914, 9674939829599862099, 14383486138223897061, 9922042067933595738, 12607420209760730250, 1163951431708057810, 3418701428468514056, 3177302917570982047, 3217945469089509208, 10238490471876301438, 5914047890159119576, 14313932311282384038, 7873142415009831359, 4600498391648960475, 13057538823866330734, 3217841119719619774, 14930867195971443144, 14900443877098569143, 13613747010984006363, 8607287334267369143, 16223902093134349994, 9855946615528227230, 17467986127811625595, 12851343650380341965, 5268799467297904422, 4860865339571653719, 7510950311328510427, 9121129615704026263, 9985294510085760109, 14647944548541534193, 4617350593903353212, 8812378543069741404, 14071575867988825908, 2197500103128929398, 17867729371980602795, 4932436132645521745, 7924275711546185628, 12144473368809175292, 11700647470688753729, 1944725794374986851, 17806041080297052928, 16379940501892332881, 3902394385929377917, 8986013537553457661, 1385017881577471384, 14464349274173417728, 2673059619166647089, 3060973120132903588, 2757656221899057349, 3067604880707584831, 2601234120306252174, 7813691230943610885, 13146165512554955859, 17640598915084737523, 2582363950458650017, 14304837210049245270, 12688683908862842695, 4386971208506064471, 8522626829538031462, 17452505302106071681, 10361450896110735337, 10033458480810018017, 14206004007517991051, 4493284979823281928, 9561668643117213356, 10841903269895892982, 11911984372297937793, 5781966583230334816, 9995084957311531830, 15667884071677615567, 17480826442761249432, 14163687943258512351, 12105651512320717073, 10102397412947964263, 4152524068034934712, 3440079042684086691, 16421551598963516241, 7663030021306742265, 13641230882631300397, 16458918411371638964, 11750365409353937867, 5836777064043393355, 11948592356238334408, 14094063963862587516, 763866157967517588, 2553862217811471056, 4978286061786547408, 5951252532271028398, 2814480147432244251, 8355110176394453512, 955000046590858084, 418817683267489635, 2375669799293008536, 7741560113544470025, 12527540215014459606, 4807648140530199663, 1917176557989775622, 17997529450210348748, 15775937348841841853, 12596647388874725944, 13005922925492525774, 12825247172998644416, 16941346907459597295, 5414495758637984503, 17648512745626862850, 11441048783055867665, 2036278509733973065, 5315013389272641810, 7534399943553945358, 13985254988036165342, 2129886592790964187, 2867979934993314327, 13920262515085521981, 17918001318024984167, 3987525118516777291, 9181953991016110928, 6703466246932157306, 5900079110331853186, 9052887944141651668, 7478034775976637552, 3278041148445352516, 12130157979346423214, 16449898609250782176, 812026766466081590, 17656773672307181547, 3744388208002889360, 3791099528357775363, 4068520361909439414, 1959438401502413602, 11329035886548464086, 10221578524418919372, 12980191277097844908, 15691976303951341468, 2706299845840454932, 12001725521641928149, 10405356943915977601, 1550503560697397676, 18146165230312144992, 8775540381707621983, 11230591336406034981, 6228681596165483174, 2133581336729418768, 12129007378508537384, 12921300519235974025, 9375678805406296547, 3613435617709574498, 13499610044718144807, 4451336373698242504, 2534710693960094303, 506672095186947791, 4599686050411382715, 10283437000867486258, 13944373918161748057, 10749539207857035250, 3256947136842373881, 3968459069819041327, 10310512027304093296, 12371354326187333906, 9649271905569519482, 18149492230911698719, 18039253857035728470, 11544885873395786648, 13115665719718705181, 5883323805103076804, 3340581244109826221, 2740719998676740975, 14211314271529644273, 10971959826690424178, 17661039620102652400, 2681458501156387899, 5479854823106014662, 5974561045219278043, 8473215965038242639, 5583715930653494870, 3470313942834108737, 10304624977365929872, 4990026433557930610, 7637937049242001677, 10791009944394783717, 15219205922075360764, 9002830569992670547, 17065169854478898187, 12114851395722862577, 1902980232892183122, 7339703717537327983, 11311240986114825051, 8620902745551541255, 17653580530932288202, 17446311100802812161, 16853776905767232590, 13528658510971153664, 8133142991621414981, 9198712440714819892, 1307139024561145181, 5651509534538305425, 15500876791491139019, 17261865242402821483, 9959143234495304378, 11774306485096011083, 3518307525093596569, 7341017580248227715, 14703612145595470399, 13172639134670980973, 15947158997811220828, 4125585181533726245, 11285884221627271297, 12648910027228429661, 3451176029776968001, 1260658404823488448, 7386532199423374411, 6316655514361401347, 874446896878374135, 16116423058515004551, 16702770564150696101, 15010314591562646705, 12772639082035296672, 311476976636214455, 9575298239012600874, 6021099187287010095, 15330804127436984700, 7874626841370189235, 4317595748546784391, 12774690740232998893, 15545525633486974557, 6452739508938620757, 17947552420114643348, 9263225273262064697, 12599141493060226685, 5119406136789734734, 1051975011747189152, 70796958152999221, 8899487974683094789, 17856135838574362662, 12228587125188734252, 2703592016861351703, 3828901820603468627, 9226218297991283269, 17840028174806686402, 18075865263748024826, 1008172625769821573, 17053104036036352842, 2643037037180017789, 4043044186653414452, 704036817524553677, 3469270838261112340, 10578260962346328018, 10307304960872788772, 11100501830170637887, 1321067784267748201, 16370290911883104830, 7277997026279002914, 9194370955407098554, 11697789085283623477, 10882102725986890548, 879575900258556559, 910006071300607678, 6634060453928245455, 7018272357233154950, 11323085799124732661, 12126704870344489768, 8719425209364909409, 16077720234498492898, 11214722890560245831, 6014665085557683621, 16140295979403357547, 4017919047975150715, 11618339290071597454, 8158854164475996114, 1011200605525249603, 11363709319397659744, 1454324493486065313, 11129023648824172197, 13020217682594858999, 9576952898239586398, 16616477346929370162, 4371687970173016192, 3516034006703213050, 2937269151616655609, 16747880970476287063, 669709731153728654, 6519853652860201133, 3659032765342780810, 15864573400056223462, 6297095765997928564, 7110555922376283110, 12550039101483110657, 11249126606834391837, 950080327127089799, 15797663250049566938, 14397834648452338482, 1543039640649750930, 8341556893541845701, 8116982948323973962, 11495256912967207206, 14766071288504085467, 16705412473803765100, 15090506094727735986, 18163874144022445889, 3916968151577833899, 1879421924266860262, 13373480014502105640, 13041781611237972179, 4588441522074875825, 10845619956267400739, 3765600421600530679, 2843644382474146543, 15132659436045892883, 17171692480556923795, 5511726102977095602, 8616390053076116361, 287094189132243978, 16223004946374614921, 6933607314950995247, 9122079358883202054, 12052612540225242210, 17627899458327225659, 14820053630940743790, 13081262502511482639, 9047814330512425859, 13819374748836811348, 7420314415541064490, 14372043945426241322, 2870595232152592358, 5825108302965985850, 3862751306343773746, 8297143078061668797, 7623527790129832636, 14976108347586383938, 15504660286044115876, 2036590244330470013, 2396696097468395360, 2679032459898693923, 7254694992336225547, 14405708262513989917, 10988568636010211554, 14393755906624408223, 564784608828851932, 8920394545124086885, 12652866383919054316, 18214421540006560542, 12566908496483953419, 2267263971377502968, 709404620135786373, 12523996199173167681, 17951676580855933198, 13650747407959441932, 5824756462266699490, 2509616646477747837, 5107467310813142389, 16298586900092698229, 12700441253440908190, 8046451347626774059, 3010230833910681313, 10061781544557486512, 8463916499683381809, 8747329120239848091, 17820189950727523713, 15204506030714195945, 14056191164190175147, 5065311670562888038, 560164632281916303, 13209321978701212835, 4258270003760268847, 9871801017584276954, 10084189192084678352, 4825074015064392667, 9581605763592146729, 1918163350850726962, 14567773874300155163, 12638976926425573615, 3649380560217639658, 8018661822408339507, 11706665997779706276, 9943212030613917839, 15457711824935005280, 18428573928454707729, 3926330427544149380, 7530117517842274315, 10714583863650741692, 1570545389027504522, 4106262895329894829, 17297335240441020752, 15663839296267508861, 15407625046661333980, 14535107337220563598, 16174049732199757779, 18176047754016168171, 11399573902740750349, 5214080916822086211, 10430898001880200017, 8371115051436088011, 13474730252470615587, 18200790159037433152, 1982492498839193382, 18199849879554882755, 13198581683370037706, 9793735608111398723, 7320054643250375233, 16550404964849262419, 5735793832830119704, 17154806469016832501, 17937411786820605740, 10105704169377815273, 10847289282838740100, 11160609093695125779, 1612622088505295863, 6640550752178901560, 10559041691527414248, 8619667673730810344, 1695749010443858836, 1362829788780114710, 4786165899179147947, 17288418297634566832, 8293662777453621345, 8957181791504387593, 2223163959711304788, 16096735981526477251, 7019659893524176984, 9142198120820553927, 9989692970304817734, 5594683658237316423, 16694216368899223114, 2065885423694944515, 13511522537087683010, 15544029444344603365, 11829821522884913752, 13656682188207614177, 13642072954609141700, 13491639210730977338, ], &[1], ); // - n >= HGCD_REDUCE_THRESHOLD in limbs_half_gcd_matrix_reduce // - n > 2 in limbs_half_gcd_approx // - n >= HGCD_APPR_THRESHOLD in limbs_half_gcd_approx // - new_n != 0 third time in limbs_half_gcd_approx // - new_n != 0 fourth time in limbs_half_gcd_approx // - n > s + 2 in limbs_half_gcd_approx // - n < HGCD_APPR_THRESHOLD in limbs_half_gcd_approx // - new_n != 0 first time in limbs_half_gcd_approx // - lhs <= rhs in limbs_half_gcd_approx // - extra_bits == 0 first time in limbs_half_gcd_approx // - s + 1 != n && !... in limbs_half_gcd_approx // - extra_bits != 0 first time in limbs_half_gcd_approx // - lhs > rhs in limbs_half_gcd_approx // - new_n == 0 first time in limbs_half_gcd_approx // - extra_bits != 0 second time in limbs_half_gcd_approx // - new_n != 0 second time in limbs_half_gcd_approx // - limbs_half_gcd_approx in limbs_half_gcd_approx // - limbs_half_gcd_approx in limbs_half_gcd_matrix_reduce // - m_lens[0][1] != 0 && m_lens[1][0] != 0 in limbs_half_gcd_matrix_apply // - n > mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[1][1] >= mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[0][1] >= mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[1][0] >= mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[0][0] >= mod_n in limbs_half_gcd_matrix_apply test( &[ 575467399379548741, 13839490846250736437, 4628353154773839253, 3235160437296904652, 17926538529589113070, 16254839488328114822, 415479271776402024, 701612307177551527, 11282731308138649969, 15549163798131727182, 9275741579154885251, 17195569079203512713, 16631195896462029517, 11189046172373216916, 11335804956694503413, 869753568386833458, 15161202273898364556, 1685153641796888684, 6519812799688796045, 9450660698529279434, 3976001355746699381, 8755860526328087486, 9379845976868252993, 15449115864235101519, 6189820805905752291, 1999656252072726648, 14614135148721558801, 9412442668458141131, 4769782526372985369, 12603364410326539145, 13266305682919253319, 6179093516856398542, 11728866005263196505, 591231256352012886, 10891822735763494610, 1379643190812867975, 17915879013573969253, 15654737824492381077, 1665878964172006292, 2193929907146049204, 3753704553030045025, 2643617658743102861, 11826899300652102169, 10741401269021818528, 16693959619336879180, 15822691007875207875, 10165667636444252806, 14646332733026063930, 14294714305812123116, 3675743870135516810, 15588872085226591434, 12249381630026428042, 14466388694354825190, 8226637301182652689, 6338248525489182911, 8273376484864616169, 12903702679068332011, 15684253830538215322, 120323452105612013, 15775771470841035677, 6517337253986486974, 5057172938462112267, 11146259301803018301, 14217857571428393275, 766104140274144406, 10403765575570339080, 15356388955716644394, 5960156924753840614, 3826246010691114683, 5270840977803713435, 17897998794972987383, 10234944855653803379, 14541987689760337937, 12820656189348873593, 17473239792591314758, 10637029214964504494, 3122622009615558433, 8796921122235952176, 15762598310456891225, 11517241390289576301, 8995337670147793236, 16090454643652603796, 10491545194936292088, 10581918733379812780, 15469777875510035481, 13740696746710275167, 17697148650091366126, 4516632692241420113, 13479012489115713946, 613181577666567755, 6543068365906077489, 7140413973568370039, 2632693564220941486, 6548358243833847767, 3580011453626046476, 1595786269113597220, 3589869122329502051, 7680790515161529472, 7672816417510866152, 9617378297316545875, 16326449292469902699, 3356438369767744837, 13626365580692467927, 14645408437700981054, 8993455766562141654, 17100348831087759519, 8482398362235761502, 9005320120246465195, 13985608369059524000, 4578760409329988524, 13471973404906324912, 13767793875782618021, 13576218399241367176, 8607505428292681990, 8640829853824545675, 12917106086264067348, 2578206011448221694, 3353125869856782607, 17577121109228709335, 2905314237462392356, 2331575639922950207, 4757803209372475504, 10407523519854888205, 10427101613638544570, 10653559167855267862, 15969139228571015937, 3229545277738910965, 14459186466317664575, 2719373534120139652, 2311539788396444793, 919197711709305677, 12869313012019772102, 4142489328916681739, 5563346075417511527, 17320278674721747488, 7600057562482304294, 137102128861993913, 6729510908740032907, 2556227730136563134, 11485309894508721441, 1975505609886762679, 7418018451444286248, 3280800891052345674, 11300546422663834076, 12023912948840777770, 14142233633360973935, 6536078661153825094, 6708126313364507897, 12979314974688288248, 18110797927987234453, 13375595970475713854, 4145852684577155155, 13282868696425541670, 1506114690671120983, 12037668219018850757, 9552135080245814694, 12689050870789160910, 9641464072414519358, 17404100951282287670, 584528148396378983, 16991192139314454706, 13435398806093646746, 1806232481237325720, 10525369207353922053, 10539096468693644137, 16823332166945560763, 13216271451931684405, 4272527731081782876, 9174012089272655562, 4803739085170580403, 18043308998760359964, 2466414918609999948, 299112418477190901, 9176472152403710719, 2100151601463253457, 14066759482920415398, 5442308713266599475, 7797794762570542387, 906654145983003262, 15049619616558215358, 13797241706831616579, 15969242154524883291, 6664585166752881617, 456998176808935659, 6372085307953904476, 9486438637948175687, 6172262737033149469, 15771388893063576724, 16211053079428108900, 9836380621269080797, 13835412758795578440, 13022293692163806538, 7291668881817289573, 10943660404337870608, 10465252139732007687, 13584635332527095924, 5217773945105333432, 475626079396510382, 10012875662407091202, 2294484038393548897, 17235255650481874514, 12855466329954989704, 7640972869677452753, 604066466212666838, 14544408987813543082, 2255330913952415488, 11487976173612122909, 2606969224171147592, 2732228719296019687, 4805516573329683679, 12510535481770618043, 16080547195251234240, 17158216987147533124, 16252483889283702887, 8566122285474978824, 17992433483153604641, 9742248099517142775, 11846307866686350293, 10183020136820942338, 17751314439768932469, 706526091974895358, 16112150740402760937, 8208604329380417289, 4681925112017699576, 16023990145260210172, 3147541399400389021, 3572534572158190145, 8720556900734060281, 14350849130427767056, 14103987208350104747, 4009902137374730692, 8642370345566348130, 1509235310089233775, 1803584577779548576, 8103474899679352369, 7632155887896411012, 6720505338030753233, 16056811053006708347, 20245868804036263, 7392162968739567715, 2667133607635776013, 4088935200661832474, 11027949378461390904, 1298518526076811529, 15048847519112317617, 12370787403008587786, 10126193873658259058, 16077210093715640601, 339546017124009341, 3262625473090659650, 155522514636863280, 17133870939862804712, 3881378537141359797, 3319617006815341131, 408938678387296349, 3519452531868310218, 9151628810034763447, 9069824551063458035, 16175438057441830093, 1025725608441043501, 5528120455681184714, 14962174970099838556, 4628262249268118080, 7668604952914400894, 14421245150669261123, 1475685311148681328, 17331200229977607, 7008482707614634954, 954865196375036588, 12721130434144713155, 17772110747932936263, 14883220430477114612, 8346701667063923797, 18346426769719184589, 511089516893085384, 1049490684134535594, 2717769095812545487, 9939780542757419537, 178653728154192874, 13977596259293439969, 16604267703708773284, 16824820253288999719, 5015044192952183202, 17285062680923371961, 8633846623132382042, 11767312170862342174, 7070173857681433256, 3195337349333954080, 10624389626802650454, 9952227996635558303, 16103075034219456497, 7190762260873686947, 7637572995251515694, 2880941320441182648, 12986992855187366282, 11480249557832197501, 10992570334494572171, 15293473353050840400, 9953353185709986649, 5473168766758534422, 2273834546925865179, 17481576375175014631, 16007610327482007771, 10021685763866120088, 15140422720183585810, 14599059403330408270, 10717864391356784188, 11043776937872366176, 17231223364983083606, 9444955609293032145, 7583866547951445190, 15822743417483210898, 12379430402523343421, 15499380185272809582, 3872771344819526970, 10944774603860747612, 11364607709396745305, 12930627891344540854, 12649577033823599142, 71081790476548864, 10661442845094180250, 3320677886965881318, 14395511939432853712, 7178607417614281470, 10608904905068105566, 12919112359212522946, 1457156061186787292, 2630619879897285370, 10619217959672149607, 17259595048026584368, 18382463142617996350, 18080737559467551761, 17900172273670393807, 8256196626665198496, 7885528354153161605, 12390361365175881721, 16121675154134812463, 7006162423030601567, 2487450624947473633, 9170525836949058136, 17199587696327682411, 2778440771740106085, 4214370535755222213, 10220293195635704465, 3494084265135192718, 6536254103726059629, 15347315270124235902, 3035309337163064046, 7593827964874002724, 6657250220369903762, 689162306084882817, 16988617413925292293, 11542800279639267463, 1161396193556683066, 1404354998405277747, 1863751006442991062, 10942498162725872124, 14089151747681183597, 12287715267573932219, 5639989966754469874, 17232323616379757319, 2169863596718309595, 15913207380900188862, 17154942699109451282, 1054068200576663493, 8407670488993208585, 8297969397912590617, 3923918644147518797, 4050822028508586151, 12069177518272170880, 5457932827045810178, 4319428590498199749, 9292628295755403796, 13596479411267714291, 18144016285235947108, 12061613157169340922, 18436504313134004880, 10205373579634205498, 8932673649062542092, 8602267798898562736, 8434725739455235221, 14593112102164617091, 17742461694491219842, 1082380225638646367, 14627119236030669240, 2111648930588633111, 474310462095504152, 13588341283759929919, 7334643839189036863, 12082398814720285337, 8117633276713593164, 12226067923217154647, 8613740435987095407, 1720065821455369500, 2278123359132376316, 17520489735769768440, 6164160529494561583, 15817606273461591467, 16954590151677190424, 15025003150656907625, 13700051717872658120, 18267946311324265571, 7224134171579686436, 10357746181071061772, 13702788007820740199, 10454471612142559644, 7972010451335281611, 6566222485717554672, 17140404477880114834, 18107075263792008325, 14436650980335290332, 7462985729135152620, 4479257078280106616, 4963716523662716997, 12351075264308888998, 9381613057424655832, 17915205681210289409, 1103301032493960092, 7390733404857910899, 5646956458723265003, 6881852031997766673, 11474462020537223114, 10074504892595096981, 18270265530986154110, 13033898379492425364, 11329340856110014657, 6846873962487852009, 14679284715132950511, 5762958206899451423, 16858950997373083608, 12658415513768184148, 605947486630544932, 6969263633905442272, 3234937740604341173, 1110148774247830933, 11668278583677202055, 10407754098687553297, 2417686119102800672, 7530424168582333814, 3002680222699095327, 15704675259272891668, 6690366115936985010, 16337949845558804413, 2409247934459548168, 5864915702415821624, 8338701638724044373, 10371049922614905160, 15037630168919872234, 16870779050531029337, 11956871297691917533, 12868211179118475395, 14334258502588542830, 13588326263831172805, 5710629666230160718, 15210061214358246229, 16673563803302426473, 4360718753401653475, 3446288193042059415, 1969211299957512841, 8046929029837267934, 15830991705791077436, 10834502346805259928, 9453135954245593947, 6441617549735024559, 9334325755693495501, 4869716018763257456, 2055831415614097075, 15166689527799496398, 7485029880680080630, 6151920967401870361, 1397222502143791728, 1505614305862413992, 1461010374171129069, 8184035195339364309, 14399586491732116557, 12965712207658014223, 15682106046619552556, 1797345002211603047, 5346629789286835515, 7778106305028050324, 1706742763731171237, 10724467824751483089, 12579419113050252513, 13399259254836577641, 11915423084091485936, 946678182575130804, 16458121607357953511, 6990972249370508484, 890502451259139532, 4270424368509631593, 8247545724300513941, 1801612845852339952, 17483758041308719540, 6916086592936859862, 2737745973138711233, 2417887524053243596, 5384664014111896333, 14943057063528297642, 12718394952034204173, 2446982003060425908, 5936547835318690226, 17541689392918972185, 3455600047399472979, 11462977481241656022, 7740652593808978357, 10168544572978624960, 11513860485512401268, 3032850452841422431, 14616088035414255613, 3419881191634612824, 1329030780492877420, 10207424479064655105, 920157290452308485, 18230987435407639144, 7055850666076657796, 5759861191162096611, 964791846480760906, 6298102481822543476, 9631778414172323400, 16943337751488106591, 3139604193492917469, 12954525486464279958, 7171879659975320847, 4855521043517721810, 17861560950998429622, 14439556530136032678, 2146560660676406638, 2477931805045525478, 18220630939687468083, 17480104655582276103, 9658906588685453758, 8900401944077573595, 4023418835120043589, 16832899872978339110, 1178686892293228748, 6270325765175673747, 8254729669168021969, 2574138951229186786, 12307389417966828562, 15258107791537644761, 6677177683840339446, 16181736336365239342, 9100009209370850781, 7463319891721190323, 1942611152231324238, 14939657768700897026, 11782521561154004074, 15467452972304115086, 4250458310696784935, 5671021285338647749, 3705241574832771219, 7348665909967657559, 53271397903297119, 5064947506099634152, 1740366402276272014, 17408710193712200177, 15448498405302092263, 6743466464363127079, 13994255903404715641, 4783992854853242349, 3539481428896870175, 13315689057294289634, 13906894805247831409, 12514428970190120434, 2383999110333252405, 12520070852614084840, 13941905089326614282, 3879009791548345242, 5979410257812776821, 3636697787393253030, 5008829046821158587, 7227070514537338449, 12200965607507694664, 7540152508302974608, 6967838404828435305, 17393893632848259796, 13461232236356481701, 13462754845856901516, 11871853053738474797, 17468976883674757298, 3137741177962244202, 14775774099242061613, 6439034393988288499, 18322704676228151809, 6195120941011064230, 5959979991317651909, 6056847048610236236, 17042162839256174523, 11417561881130884824, 15046047411544517103, 11443682701040972606, 8885365268842644015, 11048448950702337745, 16247143345753969584, 12368813636786226982, 15842543547151376353, 15534220375707255951, 9323544182631077818, 14651867219777215640, 9676432759358709067, 11349135523271337221, 12060786354814026861, 8455537878716528518, 2516611220455718552, 2834697229574266766, 14026724682567928496, 16194065834422785902, 3536210387556942108, 12326677060567301436, 9778401785405835160, 8484860443802595491, 5813709913322243461, 8582854521396621439, 7760384300089398842, 15214249845203742378, 13051924444243483780, 10084811846899799566, 18409493367524167584, 13375466455709327221, 6692904664653654257, 2974376177859028080, 3466412890624951601, 5012652013243004425, 11419071376621362405, 10316171806558216583, 5304122490809205486, 11763687800639718258, 16915991620777140302, 17449952616849033525, 16529039178071253953, 8027460945600074954, 8304586649338777354, 12754974260089353895, 13718817585228096432, 7288624726912044947, 16364439710625277815, 3691598768778868311, 2498599291857236321, 6150206881275523166, 879919669932726787, 3847940289848302727, 8973108085527702201, 8835099474718086428, 1775428154619381056, 9674646708055315901, 4804998374748022266, 15667197068183761268, 11671080770163037365, 18183825577612667035, 5196715115451817409, 15261256208797059090, 5927143056185064875, 17671549775031937034, 6124967124699154958, 13687636407913038076, 12821802172321286627, 4864176808142239921, 5229559739743490410, 6174384646073847274, 7112492701662019566, 9769272169645010501, 13117020385783746137, 14025298218438666393, 8279159244498971116, 2334429611427765108, 10286834819889245065, 176437083060235308, 18255037520240585085, 7311361854076984296, 11074214072414559793, 10912633555496661543, 17232209863183538075, 18034444892277254827, 10491712314983717396, 3133053357505241959, 6725182279679382786, 14409286461548123921, 11093186142603324357, 8906125291613303780, 4630236334690968087, 9064682117492342230, 14099842337035371202, 6795865635352330540, 9453610425174835156, 5504251706304899694, 10745438811936662910, 14010490525842433630, 13462566825848569025, 16518815534025225957, 2444138423121228954, 5677161677290594311, 3025414318278761996, 6832862260509708497, 10197340078921197729, 14469811983250567107, 14646056929411495838, 13731529545280703888, 16319880459285614587, 12262255476906895937, 17339208589673690773, 15977537099031596016, 17939410429932459674, 12993182878867114917, 17238534706082454727, 2053282981771798329, 17052484244277786848, 6511994569524351950, 8560880924849275780, 9955809746666973580, 17440412924022450091, 17993918571689756735, 13924657572680467944, 1305456412826022861, 5539105772156152375, 464733736235545179, 5605508855364158677, 12934212145390513447, 15031133559727375097, 5841364006666456088, 1367659995759183499, 42284530567339042, 16950527371076027928, 447288040070705023, 2086500570182007777, 7164047686888175900, 9253094623176419046, 9704031988894964036, 16219232125061732819, 134218840105885090, 15790690030012805981, 4913504368646859620, 6677364960496702314, 17441912887943685967, 6845050781100696434, 9944304098024264884, 2658333825110326706, 14495710831763589870, 16816753026986606684, 6108394693883656217, 3674825700349441172, 5455306879888392581, 11040129116055440406, 5939138794432433453, 10354992546645397455, 8132690955796952994, 4208614571757937725, 18389691378136656443, 9724927671847420016, 2111877634342327228, 11060010589057515988, 7413966364618415182, 1813137957718448210, 7364915359267899434, 5364164985059412672, 11301900090444374505, 8657891306154732866, 15450480317670354391, 6417954264199031581, 12414015469094402379, 4315624036191063136, 16872774353815857445, 17184838727437143309, 3265431588659804865, 812818791443395933, 10989782102893895704, 599436186045403275, 12236521865769865542, 5485432756957314907, 13060869015958528066, 1409406384233490669, 7232635343932008180, 5044656061617487397, 2740598907970496901, 5318021266376254330, 4866687283454287503, 2013910043464447712, 4064631991160546597, 14894022554846975453, 1002053896740550311, 1390923179817260512, 6747621518522632264, 16874591559626718282, 17148422615678889623, 7004449378946284875, 6029197897777350194, 312526901452736192, 8266420277206881650, 16202883668988805792, 5182030222897424979, 3955555814727488768, 13309653404546689989, 9715158796448409403, 15033855213424393775, 9207460156539719265, 13871549650556323801, 10311613446804515333, 6029742500327767946, 9239513459549335068, 5437631879089476615, 18257107349942274740, 12524770742693351803, 7714074761538734976, 16596296037668501301, 251038933261335040, 4226458194164141432, 9779997902902433133, 3030602692656943865, 9331391008102809870, 17747445712689774610, 2740918437486283758, 9665828446473412335, 13581408964710460718, 12469303281264099059, 8893571674672442832, 1379442413022712016, 18199326928352063107, 11320581769377597151, 14066714968631958958, 6105762775909832952, 4189227983184722066, 4883704839132061778, 9916861677661798965, 11462346480649342207, 14778409334292907777, 4493884456551625778, 5976634023115886514, 10089921274563850061, 10995886567862393002, 12514005106594925266, 13487422864108832690, 5949940164660002021, 3798824308267675643, 51594519353241699, 14042191609008111878, 1084198794703441457, 6187735363348137007, 2222453422075951471, 1977733178909367094, 1855687927268674141, 13507429231362965288, 4563427348875562453, 53052655758196469, 12248719414065642395, 4043781334046130258, 16594510413478092317, 9909324764498283904, 10006246414842585456, 6639900859435585807, 12538869588808265068, 671676141501348307, 154891531251131063, 407141030039689521, 14303125054294315595, 12519957692091445501, 2575047121342740832, 4442053191994286549, 7257403838939964182, 11301512346343729354, 5649479332294422836, 17444069867132128440, 15039830200779644809, 969922697460401557, 8850382822556140468, 17587617640514588961, 5792622618189642538, 2959871208851481004, 4002969457198766845, 14733844908986830364, 16619267403139166511, 4982510272869901766, 13969983195542601865, 6407607444387703463, 4503458032777136243, 13276938846993601029, 9999572350287586232, 6077554759008956961, 9914549221908685340, 9747419718740154953, 12283917679445155804, 12506018878600868562, 504483054041077175, 6931585527138520093, 2510695777487713047, 1217537109908330722, 6299518530600532997, 4461483227388303475, 345473314729953715, 11577208925864677728, 13714009284775997558, 9306564142261809693, 10493376611772360762, 12114735030824310442, 3723726520319678928, 13936502274367500072, 13361717531410065438, 11054299856501427866, 2346032701355553484, 16480112851446496738, 1716080732608071776, 13906214996195234076, 5677286823010362674, 5031920382916298075, 11682583709157560454, 14368427604644474820, 11974313857346928172, 7875781703666737260, 16031516164256186906, 4566375739076671625, 5097663793007619497, 12165327848553281827, 14159539264387775940, 17711785725905262208, 746306330982150615, 10618303353707428560, 16415694862704526911, 9426321299626982899, 203404317597163992, 9784341849958013566, 17737510091254724918, 16467553962565191057, 14963305126792873612, 7875246701602917591, 15395884754391863730, 7674782145333341935, 17779948927306734041, 4692271260276963472, 9147303984837818022, 11261482143084613378, 6771303715480347754, 1021253236102285456, 2938757268921792891, 8110317487741901284, 5629482782068783477, 14074967295738352943, 11830360745467057113, 16065773322812244383, 6799648256361227046, 10881530047107857944, 17272480164822477419, 14188187909112608200, 8492727723243508205, 1239958563141876800, 2396597814031561226, 6365846116588909456, 1747799098922280685, 12329761501577087761, 7103565661859178619, 12929732902203489138, 18130721204914820146, 7404709294083080877, 4076736505655677441, 13997485323848566931, 11355165264923013442, 6265382391023965751, 15037801805473945986, 16283172306662528168, 10784174118773201917, 15442466842568320074, 6792336536532509513, 6841433016666743757, 17062933928060878150, 17995161545501763874, 398314979814197042, 5371491177519133552, 7487291916923596074, 17726809651563472115, 4276741984609027067, 9063884951015483403, 6604298906930427610, 17639693268109172166, 3512896200182209296, 14176754219633674214, 13075641158366811356, 4304608617823480610, 6827519196509520249, 10991757902125467581, 7985198732976208765, 15286834137228061227, 58281206065522927, 13204561433899186751, 13223435687875504648, 2520091453248762960, 1336536536994438540, 2657040408513167000, 5767035770652592231, 17260962340791386954, 17641333140100333702, 9700277297324555168, 6985084747499361442, 2237371457239959946, 7946926051156145397, 14111197867527256838, 8805745012779252660, 6198429337106777414, 2615850794923160576, 11783140326213116396, 14893203149537487125, 9567314701273251044, 11695128483656617057, 647988395719472509, 11422708536691070047, 13239243760652390256, 16636779351598291051, 18437576843798320734, 13792983340413428549, 12074737915047871515, 17066180541625455492, 15179271581398274415, 8175824910139502819, 14714425222088264251, 1989693470019103578, 9855573943302266616, 6236520060938959996, 13109545139113435074, 13566528788838365110, 1410706471600329523, 17673327292701259018, 1282280051559055632, 9017178883540247720, 15228935123367154482, 1258177275149976100, 2018246390800272584, 14356985980164438273, 1823604866366992170, 17903023640589067433, 9347737820956061500, 9735146081773156261, 6689847293073153955, 11126271016334934544, 5994793191677038724, 3604730352973328532, 17605242569431998414, 10327617156260919079, 10682252855809435330, 9100234729746896760, 16993079188042570603, 11254975990606724502, 16242311059560795961, 14227003883755270012, 18285710061812359350, 7387005544448366058, 1145109023330252723, 15022228266755818179, 18168093935820946866, 8922807670716322377, 17623516307873116019, 1206890136710388934, 9516372380550133567, 10133157547696520694, 4294971167499340423, 9743061062772065165, 5377657584522832108, 14225392737899643394, 4157013585438895700, 10125549201612144267, 4100226799738447148, 2075172157465998108, 13195036640815520738, 6821431496943827604, 9246396951088662598, 9751868297178759982, 9700779142744360518, 3658815564772137188, 6538317493999171090, 11697362137005293086, 1923505046610352654, 475014807978174723, 3630137128781123727, 12150077442705041079, 12427124278971727290, 13479235332914334363, 5496164611508275158, 14936501386999605874, 8882652803543653011, 10952558904165612665, 6739207228856725932, 8456163010594333639, 10535813937687860141, 9505036768783170961, 11099064892618807360, 169745221320748492, 4707891234763005567, 7738425121897682831, 11404840688507500898, 8691505940234327527, 11771261818863120062, 14723964031553687059, 15287258300729004005, 7573783454674360892, 18179022528685282485, 13245862641188327159, 10588353385460229379, 2735402380843149021, 16860704493911100849, 9024623514323424705, 12333075916853020349, 18244278992464300971, 4867301239541398634, 1314358060529143728, 7666882040058016129, 13150073136816015157, 6301083950105345225, 13976444210903821837, 2060352136785153044, 16200698722576705758, 6460888606184453894, 16445752899318815973, 17179709527494545154, 15536997874687360034, 13022268941493329839, 2696716978218378749, 3362347068528182905, 13565362575501294811, 2079150969445622376, 4810345717233969931, 4472152818411820065, 6453260112485098774, 13356564228328639839, 17110313288592456745, 1435938168541586853, 7462678282816862243, 5371246349000737177, 8429218073787618630, 5346521300198079286, 12789353917659187733, 14442956055750007343, 15244751088029774551, 13297251472118828207, 7215676263905100435, 6007211881525156123, 9493592255758432036, 16602057928234062153, 16587917920906294320, 16979836431020046439, 13094140568345251281, 13916421500525839258, 5769668949157229760, 18086484472032192111, 15116469247160210173, 10732312892355549063, 12164027081808213486, 3079069950535673423, 12585139553289800020, 12875306561259226432, 8811443258909940002, 8124174848473646108, 15670453854511445398, 803566658286118334, 13806458323797710500, 4762982112857169920, 1859710041066580425, 15720087592804142456, 16303182845117023833, 855870575093385721, 4703327830937492490, 3313518290113627482, 1178633794722110520, 8354185752905946404, 14766290794342661211, 15214154729438679475, 13729401929312370465, 9011734493161906949, 13113532936632755704, 1345447462867773483, 6448244176056184701, 7012477124755342304, 15580038433286556688, 17848919842496199431, 10028316423612011933, 869027013079958907, 17009799055507152201, 18041218704541497506, 6045145319869314743, 12377421195637201983, 8449076291782840438, 1397849232559267847, 2187434984921684478, 3403378911422360969, 17480693808924740870, 982483816965115826, 15888731420268623003, 5280522824450934391, 18281748078592209071, 4719177826249662435, 1969348133672517676, 14302905663206015829, 3255827777415561924, 2578045746540552666, 2573896329300556567, 2391501373699313740, 4791581547865311205, 6247840047570325773, 2469705008517634438, 3056326695519610316, 14948296709540615024, 1062923194288577107, 16375392771639774947, 1015529378012280447, 10746830707201373455, 7715886963806302343, 16297406106746590647, 17715588202572550265, 13527139072558963929, 99211582412004024, 2711459600905895935, 8569541865276767972, 7613790287433305305, 653208029905987655, 1727854787208424357, 15748356304420272869, 9959409749691667969, 14291894407744446212, 503703217735428309, 7876851416985445297, 6431225480119190090, 449483234453843792, 11523298865591649623, 3435872863223259742, 9552329090845154230, 2896972164361149982, 1269310417738704553, 18384605444802363468, 1237780458899379603, 16910833523727563142, 4482981074603401198, 2121371960521454641, 7796532283059204409, 25790177388111233, 16120544267889484355, 6144232545049390988, 3521563904857210638, 556210369885776174, 8324534100827531805, 13516226267058770145, 8747429514104290165, 8026816217324859006, 15405579933448964648, 2482550910924013528, 6079310715073401336, 10449962361225046441, 5524633401100253579, 16053481108469650499, 2790101718009979348, 9301878289303197606, 997249373872362850, 27300315815771942, 17737705294943786804, 1424935685660120924, 8424798139585257768, 16211516871950763803, 12990358998177017683, 10249597119118506275, 18408586087691363166, 11438404066809034737, 11012584279891838821, 6696271295716018307, 9930416860933484049, 13215962566134307271, 15246803897725633075, 11387065919388119048, 2466603392488411175, 681132078373685642, 5130503773631633718, 2509149940966576933, 10411902793773420668, 3635262312863149371, 1603062208885790503, 9360721267289057530, 2678321596504669944, 249229520366360442, 17329668685637718997, 8915036515108497990, 490784964147667014, 14515392651593343599, 2409201985556015912, 1611664978682553018, 11850486551349563879, 13761189022094302350, 3698463909621999146, 12569860844893297150, 1227995028080714851, 16075767045086341788, 10199406988903905473, 17794651552362356270, 16092930490238021824, 9328723035395370944, 4734866727034661155, 2657796117079752451, 13923818243046619790, 16472136068270228914, 18058223245533848756, 15345222547995310311, 18050028532712597482, 13589945113509429199, 11522903866982422064, 17951848030650642905, 12633284474117061774, 15115880423554767983, 12930423604492456604, 13329164597703249258, 18338837626925469553, 6367228635373808510, 8371066919516397122, 2160980766020466019, 13425362939901273481, 10449588671756455076, 13946011226909253684, 6563076431328948436, 3467066912321557163, 13817709282661574385, 1954831874337376368, 13247212989673443019, 4305395659031332051, 2576959295441697293, 6896780844531978074, 4838944567483159792, 983435118873209304, 17099666216820037611, 7618027338181614041, 12740220343512004286, 15668003088622161839, 6307065336155032471, 12866355547695255339, 18105505267682088262, 309702548863399257, 11431934014429398771, 16337123462420112626, 13455974306445806251, 16619990986003346004, 7250047582443547679, 13575492233443252104, 13911871272758592885, 17460767687190632452, 15247929310408202516, 18331682218295863001, 261323487582141633, 7614661128980424817, 6422108758439359265, 2081056287942587161, 7220787374877583349, 717472904341595891, 17813723712700157238, 3241494416439598726, 12794513487028370881, 5358721158543461549, 4452065304298022398, 11030176201923581521, 9210001828401987024, 10912815101479991274, 7091546400312646488, 3013240817218288252, 8910956722230923212, 9054959438387840764, 16851843825181072249, 13414604809457485698, 12075986842954907009, 4658854495181538571, 10995225665179398310, 10440147773274056063, 3614430051441949604, 7271983795362664750, 3047687937173698630, 1994619618655862338, 13179073926046162775, 4202285970439440298, 1118379597613009280, 15519245009495040243, 4256675708756697669, 8238649640283351416, 7342244199313224551, 12880588809549328523, 1187652721118103080, 5424444711048922656, 4396267379797475032, 7873701471102341918, 15699709671604289187, 5918216801351035784, 10814352802756983884, 17646214522162102119, 16006963122846937167, 1430365631320738851, 376457101376932550, 8871916202315560716, 13011781717220903069, 15215597531017339743, 12289548108447181959, 7346780333055067602, 9224378704987626829, 15268931953997841814, 14041223036336774753, 8927234293163765947, 2897790799008400374, 14582010918862717675, 16940686021857041143, 17809536309397136921, 16537410647678046250, 11385770080898495399, 11058909064571773777, 902170224533021061, 6155050419392920377, 578026483489571474, 12192209733415829173, 9800697958307651530, 5325607519225962561, 5749788716129163638, 3339204573835152173, 11711084023976848626, 15800866735538093521, 11602514118015409575, 11845686896612751865, 12805561555388014296, 6833731309656940130, 1683693695029104238, 3252505788213114441, 12861064563156096686, 17880480561349418723, 7109337509100178473, 15672204595961079139, 12610706960087661501, 14127013368071208214, 17303281711208279022, 11071871840671280390, 13019666508300875107, 13450446740352112547, 5215478633835401279, 8173215137132965511, 3385959284242241690, 1162541066556458857, 3982176102869150348, 11033193378737041188, 17515896641420400261, 5108442075949478481, 7390295244279229703, 13200704351272018481, 7838787871014850842, 6967690604184701289, 17306979495731024219, 8091038377110761360, 8807486371208741534, 13035790401659421556, 18352767143317290044, 5794344711151456204, 11362614524307015732, 13861808480505787139, 10664293568977350297, 12429231307955906550, 787191891079923458, 10802046887566427941, 4479080089699981872, 10284905844912789930, 11562290707970545935, 10020771126265957209, 4492419641191856378, 8315733702710074653, 8179451464749720683, 11440898133834467541, 996731441922278873, 9874517357398478369, 3191161615687645368, 2749003557840473686, 9190738483349545066, 4941311214960612971, 7731219348943068526, 9841834562404157494, 4980436855570339065, 1530764681258350086, 699509151710528021, 13504108558405070318, 9218776911300271865, 194583242318484046, 1219401915806982494, 10269323235937088132, 16474197391285416186, 12429159956713323486, 16406837010296707669, 2096879123910896284, 9478062389402448298, 10390582542218348554, ], &[ 5506952908463110193, 3806848119604616776, 15253829699929639786, 6153710766072962714, 7724992251147712460, 18274643156043175664, 1050131577594375425, 3075260137230555926, 527421990694193641, 7584901852578630990, 16965489008951068436, 6638899686914020055, 5548349519839988674, 4340131637208080214, 13231812794129139237, 5782596599117579099, 14707631542809621934, 13005413828836673107, 5027517060994695773, 2409119181385285185, 12072018513207904945, 4610121114335836886, 13007992267227833961, 10768178433595858647, 5655501324069419836, 4047945395373106430, 16148618693961270401, 14207121723132763208, 9303659817261703525, 6150302743552282248, 6626197242081859424, 14180443744733228035, 16111493454316570674, 14281519617792962564, 15852632623980128457, 843715310399868484, 371586007013897923, 10616674417688079376, 15194274051554944848, 13553160050325440579, 17628757169066045879, 5422077471618948581, 13336098216102409317, 17615444491978875175, 7561910121468822316, 16521387743687265557, 15893994794718565447, 14500498851291186914, 15404349041758659271, 1033447516621898753, 6046875549177986318, 14017892727616312226, 504532865625997473, 12327954595628496718, 16114003010774897368, 5123840833265554878, 12135628469575155214, 10148936972500311133, 270050642558637886, 4713725442176248124, 2061684810683917013, 5950651629769154975, 13856635522463752336, 3060080971213245973, 15505219872384321749, 15660711294880766518, 10399903341728067157, 6651665398472767861, 14008720726998708431, 13564382325331985222, 12275490277448149552, 1079407395917348059, 9571671064864316311, 10464498765191388869, 3257185038323220608, 16947719475258977056, 9041734436677629237, 13800437069910936773, 15077537963562816357, 8788516953891922746, 15832918598557989385, 14579847279540664520, 12622946476897850698, 5338253386688349876, 364868833142768548, 3894073811511765730, 10883504329458004367, 5694806037383475667, 17592653866771118524, 16359891716286511995, 11831511743093412575, 5346828754811097128, 11209687597326063736, 9730095457442822720, 10190594511925207302, 16828792882592167118, 4455664427487546597, 16063117532002702952, 9448048817668105636, 4972988473343674204, 3912110890459805268, 11377401507523354142, 11367029609143622993, 9108192617717426353, 1385875158717547342, 5297004339925541821, 159593902424474731, 14192871358313078323, 15224505595714662032, 6200287398085215168, 17286563738527915901, 9791571204583847414, 17516325043571924340, 14366344976190972987, 9435375229224263329, 6178661234763053743, 7945181496515342114, 9354008202308728070, 15540756784774251412, 17860277456202575278, 14209596746285961883, 9512088169794924312, 5267634490833581206, 1676119196958948766, 8311957173462535989, 439611748176266368, 5925545614682176396, 16253071308860013431, 12311940603650557324, 1541228309549358910, 15649818561737411196, 14275602707926342519, 13975876390445667038, 1479178557847854141, 3285270572845634784, 11593180894357303235, 1042820108092959158, 4253569036877676973, 403560233122940030, 9510252758318344055, 12102364779301891941, 17721965720899710575, 14089693913291613024, 11315184887553464912, 11126194784026669316, 18349021879540859921, 17629602484099316111, 11791433535374809407, 1403337479180362893, 1702732204405483129, 14577210696810087119, 10119062496336415952, 3215108150128546038, 9555329295127310367, 14813961943202590306, 3854717936189991211, 15305281209892145119, 6753116109099393644, 5167941309253736764, 4805407145840605183, 12052939585848547177, 13815002107314275347, 479262239434164167, 9984369164481245166, 32617941710885992, 3534732426571034215, 8949504569861129446, 7141129504706409563, 14837112786678223968, 12646159468354254402, 1634895633875002200, 4501516205577371448, 9599178568514083396, 6662855285932438630, 4249204762219666393, 4995345425484051611, 8852943034822615167, 14664266321575016915, 2189704958175050818, 8112056909545221404, 13405743490067994915, 12177032774091373498, 10374323912657667558, 17137017152638854266, 2894829133650272487, 3043154777910298559, 14556828612298618138, 10439272111024509541, 10616042914455131442, 15806801477164016164, 15930845540381766256, 18017643322697943023, 17619291702832936657, 9117612259919897577, 1044226778242844875, 14631310785412098609, 10136888858639713266, 14449349093679970154, 18069697024764971954, 7973459274000903425, 4238333360181338745, 1025957588977991867, 3591096666629647249, 5973242157764053501, 14633601316455469060, 16491905444740244101, 5258795269555777153, 7917683918101720763, 6957575575665285083, 12471933279161455709, 17374669784850184346, 10294948521464027513, 5365059148739477552, 7931647940471320382, 3732756674714358060, 5378482385455801316, 605630847399035668, 2662239966283783678, 15246382162602486789, 15502092928361596926, 14822462227958686755, 4355260933028095719, 1388811864175835035, 16111165341634520801, 3856506329330266599, 5480941990955834423, 4066690789803835796, 3446091266660667833, 4443837396874554687, 9382184593756836423, 3662513746157661468, 5981768571534548910, 7224757717208818003, 14120780684632575241, 9320634833813385940, 6667622706595582265, 16878293759452873978, 17088541568896866063, 7372626780022230514, 436808405518274966, 14252678732721446921, 2104869524947222071, 6631685410375788505, 2149637305151365415, 806417526627454955, 7421434493476719453, 1465989281562985011, 563947906496868418, 4704820607165988411, 8173652582005143181, 17819565157595430094, 9845347207851603114, 5241769880445368831, 16575699457001929457, 5985635078953360403, 15978649837734735596, 11510702129036230197, 5228690908831482531, 7526030925056215404, 3287154526100936638, 12117225562485013813, 16823232684363470438, 583977556407730332, 17697878485894786632, 3845824921059996004, 6726269658160672612, 18123920920510771001, 11508614555715257982, 5614311603142419893, 6606919581194165114, 10784854988123637320, 2264767800782756074, 7796673814299662386, 10902499857059539779, 11823788150079598671, 157113151127610790, 14352523930925726283, 8130167232929626062, 7847535894354429131, 11565590994444363555, 8077867159278395820, 17389179712963819345, 14935277299146800308, 14474917870682010210, 319588319279269778, 3134118488268119033, 9681404746624604797, 11814370242537451152, 120347778578480442, 11682962956864175266, 9032999928833956716, 8517160786434081542, 18099054458154837484, 6305653560187270190, 13238111375831798679, 195224219159194139, 10509000520281398525, 14440378477979315635, 10540539637383947317, 1816835103067453372, 12292190545991200585, 11929309142065466032, 14923664747079208466, 15293490320152873937, 9334278390697238298, 16215015280814728675, 13898634333978600541, 3445627973235322308, 17969481267516901478, 13335832845120597892, 18326371021140590109, 5890488708488729679, 4406980003802585112, 5344445953698019450, 5013673532816678285, 15961414409746022478, 18404414171806953543, 11468650198917792431, 15531825206300874617, 14738477539196458932, 8676622966697723522, 1368635071662477864, 6543668723466390118, 12114558566232943413, 2303004786445269111, 14170489424093999995, 1985671304134573656, 8331463571610542764, 3873015007715912993, 27894306076102606, 7104654970761334900, 5686730752548624804, 8233904160277754285, 5172053108218104416, 12113360256208938435, 10280077545660908320, 13821974650155757108, 1742749416226970211, 11654300655577230702, 14976077464467803998, 13890928519824763701, 13181570432818935900, 18400222548512349578, 4900627745620570574, 9237622473186007483, 8348806201397375307, 11644861466959244564, 7660774625358692180, 12640800868812968394, 10126105491751574188, 7963584681349558312, 996039405712308551, 15174300658579374594, 16133028349079126235, 15172075459306840070, 4754453455507644582, 2082474474919902411, 2006285022788280185, 2422722200295769492, 10019647931754062695, 16349712694947095249, 14083930401576374224, 615386692410750348, 12397858553466621141, 1573457883557036777, 4980959182073659021, 11443908431408514446, 6984262965031673234, 16633481031388421272, 4161251318834567407, 12821551347784643969, 6608155693481660229, 1611043482167472050, 15122218494830750408, 8839500240035607198, 15384724866021917283, 3070733572920490549, 8592993878808367240, 4271248517927408440, 10865144033685961973, 17023530530649284392, 3353462395956110692, 18120823811324392964, 10221129839711512089, 3227448551694007251, 1988380654856065045, 2242021796806927365, 13590775423321667198, 10692026012126777875, 11306555419118442917, 11316252767034863343, 18760321466791470, 1337100093785900848, 6492339287439306118, 12125411568967459196, 1797441814675370229, 1631938251008432317, 6985480655598205780, 2348176182416429294, 95412213746880721, 7175549597849762403, 2094795596458793654, 7829002790007311465, 14746732570765651081, 134877455607034691, 15638581748054019794, 7599776457298678362, 7986432103542221551, 7500529350917377326, 15884143360659537974, 9903748562237486241, 4664581449394265591, 2962548990311093356, 16023325614230646625, 10426247192951388751, 11003478360555882777, 11539013974193753851, 12270292209530478200, 7423475458257570239, 13100711480717389630, 16388389606841277356, 15191771423361849007, 18427249344570625913, 4348367306971908628, 7942807882176181032, 16409042118394465962, 863438358079742954, 1124736515135783861, 16872942745563460973, 5139090909118018177, 4669623391383642012, 5118057586113819116, 17891190081052445844, 14867908875153657094, 9390870292482891489, 9171235516940002341, 2343634198674654987, 10960182345705330093, 10619370169029979867, 4571519790281325513, 12889605798772993499, 15970143036917147631, 10001359583966733655, 4381102045316081715, 4163914690821122330, 6468638717365001528, 17479787593534552160, 7599949586205261816, 10593115230897863905, 10775345788560696421, 3838567407183537934, 16971529548430600403, 4980854155284411004, 5827837251392141026, 14830810846144815135, 3821271250454438306, 129239671811848792, 1581976158752737667, 2612788759361274201, 12230162761710825594, 10097159439277024421, 4401184023778243978, 1406084492350700231, 11938842502217979388, 7158646758876276842, 11154483509538442887, 3807887936265348548, 4411855765274191285, 14464002811165395280, 670130159021436363, 12640940208761414730, 7728254476113900072, 8282009448283823101, 16968891258239181965, 3688865346582500831, 1861487375161465963, 18109147777912453913, 14054735663838606991, 5895084269872329312, 3180503889143088947, 16735588978438822575, 8938486803129382823, 8074810307626673403, 9199264274209535698, 16453402421557915146, 16952664837297462870, 5161275365544152420, 3147874599125818621, 10656989901498080537, 17283970806496112517, 11904772904109037898, 10815600643737317830, 4190612046695163764, 12931964669364485889, 4640956854723597761, 12010307958665631876, 1817311075096228914, 17760293859189071748, 8658199478093129696, 5980712071282278126, 11751139410599894151, 13230413742965562522, 2646723965833712773, 13682876666838619530, 10800431924235403175, 13382436438625160191, 15176810074556266548, 14653393669910477601, 3089870430325875498, 7482067547555813276, 9577971917293864659, 6960932610226841152, 15130393967538609694, 6648313153230285085, 10536236724893566776, 1093917583121871970, 17300922283598420212, 15626332485235410632, 5710388017071160883, 16425715338132198876, 10099451213347819493, 15114188552391671070, 5219737568429214388, 10291251738376368665, 9999550435891258477, 11261758167548915441, 2059999575592944296, 4808217191002697670, 11144850771283015677, 11420508211474364970, 16799732563689238327, 3497095200015961133, 18400167689108815834, 11950366853355105307, 11210662566186499912, 7630565784488556621, 8708124700824936536, 16451883938293396059, 3856271038937245480, 5014991179538099218, 13960473819858174514, 125754478403752818, 6836966187910773427, 13398538180289167798, 4342012043427584780, 10587058069497406375, 14137841459960663361, 10659720389989370126, 6102546442785984287, 12392236227630837883, 8332615892803265341, 11617599899986402733, 13605114078859281596, 7114983647870611256, 12404096710235362863, 10847060057289621091, 9048460749990878785, 9926828906222562343, 517853205147118455, 8179968105148709421, 558104921847325950, 7022967858240775546, 8937761758962462261, 11010345473796135921, 15162173902777211238, 7737154465700094829, 10934536765747213009, 15409842658458358292, 5139225699322622015, 2424051831250781183, 6113891917550200290, 175401245396128529, 12650806140631886299, 6488833543271648807, 12206734304450002273, 15167188033176677277, 14723303654739655264, 2179622318393018228, 9921850291797916605, 1533691482276731934, 7193267197928543879, 7697000401879611136, 17905282013737611432, 195708939669136652, 8568890883842831118, 541635191945155915, 5909439847022830310, 17931009500490606267, 6813293046347240, 10373454508133137832, 2518969817879302450, 2557266502794028272, 11482262686846267489, 9426469967764905872, 13731315097386886251, 15575568313782898237, 13595230256649138562, 10024833956978279813, 5285361198933870158, 17437810250035109171, 15432785004507430528, 10310987294856413932, 7168389759122719634, 2631016883595934144, 17529280321808157946, 6962165250869702643, 18242038243432348673, 9407887776756608694, 17629211158466299816, 651801541305818097, 7005455043755295025, 3693142147562879928, 13937562557249975083, 17185080793670498070, 768121941451659874, 3094549444790063442, 13260257407036400094, 16126489432734117941, 10272660138986488848, 15438764110169806984, ], &[1], ); // - xs_len > ys_len second time in limbs_gcd_subdivide_step // - x_high < 2 || y_high < 2 in limbs_half_gcd_2 // - xs_len < ys_len second time in limbs_gcd_subdivide_step // - y_high < 2 third time in limbs_half_gcd_2 // - done in limbs_half_gcd_2 // - x_high < 2 second time in limbs_half_gcd_2 test( &[ 18446744073701163008, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 4194303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709550592, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 2305843009213693951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073441116160, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 2147483647, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709550592, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[ 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 9223372036854775807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446743523953737728, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 288230376151711743, 0, 0, 0, 0, 0, 18446744073709551360, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744056529682432, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 288230376151711743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[1], ); // - !limbs_half_gcd_approx in limbs_half_gcd_approx // - n == 0 fifth time in limbs_half_gcd_approx test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551488, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8589934591, 0, 0, 0, 0, 0, 0, 0, 0, 9223372036854775808, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073675997184, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8388607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073707454464, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18374686479671623680, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[ 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 576460752303423487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709420544, 16383, 18446744072635809792, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 16777215, 0, 0, 18446744073705357312, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 72057594037927935, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073575333888, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 268435455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446603336221196288, 18446744073709551615, 2251799813685247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709518848, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446743798831644672, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 2097151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709547520, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[1], ); // - n <= mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[1][1] < mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[0][1] < mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[1][0] < mod_n in limbs_half_gcd_matrix_apply // - n + m_lens[0][0] < mod_n in limbs_half_gcd_matrix_apply test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073575333888, 18446744073709551615, 18446744073709551615, 18446744073709551615, 33554431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709550592, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18158513697557839872, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 1099511627775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446739675663040512, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 562949953421311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744004990074880, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8388607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073701163008, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 144115188075855871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073441116160, 18446744073709551615, 4611686018427387903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709543424, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 70368744177663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073705357312, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 1152921504606846975, 18410715276690587648, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 2305843009213693951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551614, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 131071, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551488, ], &[ 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8796093022207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709486080, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 4611686018427387903, 0, 0, 0, 18302628885633695744, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 17592186044415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709547520, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446741874686296064, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18014398509481983, ], &[3], ); // - n <= s + 2 in limbs_half_gcd_approx // - m_lens[0][1] == 0 in limbs_half_gcd_matrix_apply test( &[ 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709027328, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 1125899906842623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551104, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551360, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073701163008, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[ 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 70368744177663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551488, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 36028797018963967, 0, 0, 0, 17870283321406128128, 18446744073709551615, 18446744073709551615, 18446744073709551615, 33554431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18437736874454810624, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 9007199254740991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446744073709551612, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, ], &[1], ); } } #[test] fn test_gcd() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.gcd_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.gcd_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().gcd(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).gcd(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().gcd(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).gcd(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigUint::from_str(s) .unwrap() .gcd(&BigUint::from_str(t).unwrap()); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s) .unwrap() .gcd(&rug::Integer::from_str(t).unwrap()); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "6", "6"); test("6", "0", "6"); test("1", "6", "1"); test("6", "1", "1"); test("8", "12", "4"); test("54", "24", "6"); test("42", "56", "14"); test("48", "18", "6"); test("3", "5", "1"); test("12", "60", "12"); test("12", "90", "6"); test("12345678987654321", "98765432123456789", "1"); test("12345678987654321", "98765432123456827", "37"); } #[test] fn limbs_gcd_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_23::().test_properties_with_config( &config, |(xs, y)| { let gcd = Natural::from(limbs_gcd_limb(&xs, y)); let n = Natural::from_owned_limbs_asc(xs); assert_eq!((&n).gcd(Natural::from(y)), gcd); assert_eq!(gcd_binary_nz(n, Natural::from(y)), gcd); }, ); } #[test] fn half_gcd_matrix_init_properties() { unsigned_gen_var_11().test_properties_with_limit(TINY_LIMIT, |n| { let scratch_len = HalfGcdMatrix::min_init_scratch(n); assert_eq!( half_gcd_matrix_to_naturals(&OwnedHalfGcdMatrix::init(n, vec![0; scratch_len])), (Natural::ONE, Natural::ZERO, Natural::ZERO, Natural::ONE) ); }); } #[test] fn half_gcd_matrix_update_q_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_5().test_properties_with_config(&config, |(mut m, qs, column)| { let (x00, x01, x10, x11) = half_gcd_matrix_to_naturals(&m); let mut scratch = vec![0; m.update_q_scratch_len(qs.len())]; m.update_q(&qs, column, &mut scratch); let q = Natural::from_owned_limbs_asc(qs); let (y00, y01, y10, y11) = half_gcd_matrix_to_naturals(&m); if column == 0 { assert_eq!(y01, x01); assert_eq!(y11, x11); assert_eq!(y00, &x00 + x01 * &q); assert_eq!(y10, &x10 + x11 * &q); } else { assert_eq!(y00, x00); assert_eq!(y10, x10); assert_eq!(y01, &x01 + x00 * &q); assert_eq!(y11, &x11 + x10 * &q); } }); } #[test] fn half_gcd_matrix_mul_matrix_1_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_7().test_properties_with_config(&config, |(mut m, m_1)| { let (x00, x01, x10, x11) = half_gcd_matrix_to_naturals(&m); let (y00, y01, y10, y11) = half_gcd_matrix_1_to_naturals(&m_1); let mut scratch = vec![0; m.n]; m.mul_matrix_1(&m_1, &mut scratch); let (z00, z01, z10, z11) = half_gcd_matrix_to_naturals(&m); assert_eq!(z00, &x00 * &y00 + &x01 * &y10); assert_eq!(z01, x00 * &y01 + x01 * &y11); assert_eq!(z10, &x10 * y00 + &x11 * y10); assert_eq!(z11, x10 * y01 + x11 * y11); }); } #[test] fn half_gcd_matrix_1_mul_vector_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_6().test_properties_with_config(&config, |(m, mut out, xs, mut ys)| { let old_out = out.to_vec(); let old_ys = ys.to_vec(); let n = xs.len(); let a = Natural::from_limbs_asc(&xs); let b = Natural::from_limbs_asc(&ys[..n]); let out_len = limbs_half_gcd_matrix_1_mul_vector(&m, &mut out, &xs, &mut ys); let bits = limb_to_bit_count(n + 1); assert_eq!( Natural::from_limbs_asc(&out[..out_len]), (&a * Natural::from(m.data[0][0]) + &b * Natural::from(m.data[1][0])) .mod_power_of_2(bits) ); assert_eq!( Natural::from_limbs_asc(&ys[..out_len]), (a * Natural::from(m.data[0][1]) + b * Natural::from(m.data[1][1])) .mod_power_of_2(bits) ); if out.len() > out_len { assert_eq!(&out[out_len + 1..], &old_out[out_len + 1..]); } if ys.len() > out_len { assert_eq!(&ys[out_len + 1..], &old_ys[out_len + 1..]); } }); } #[test] fn limbs_matrix_2_2_mul_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_8().test_properties_with_config( &config, |(mut xs00, mut xs01, mut xs10, mut xs11, xs_len, ys00, ys01, ys10, ys11)| { let x00 = Natural::from_limbs_asc(&xs00[..xs_len]); let x01 = Natural::from_limbs_asc(&xs01[..xs_len]); let x10 = Natural::from_limbs_asc(&xs10[..xs_len]); let x11 = Natural::from_limbs_asc(&xs11[..xs_len]); let mut scratch = vec![0; limbs_matrix_mul_2_2_scratch_len(xs_len, ys00.len())]; limbs_matrix_2_2_mul( &mut xs00, &mut xs01, &mut xs10, &mut xs11, xs_len, &ys00, &ys01, &ys10, &ys11, &mut scratch, ); let y00 = Natural::from_owned_limbs_asc(ys00); let y01 = Natural::from_owned_limbs_asc(ys01); let y10 = Natural::from_owned_limbs_asc(ys10); let y11 = Natural::from_owned_limbs_asc(ys11); let z00 = Natural::from_owned_limbs_asc(xs00); let z01 = Natural::from_owned_limbs_asc(xs01); let z10 = Natural::from_owned_limbs_asc(xs10); let z11 = Natural::from_owned_limbs_asc(xs11); assert_eq!(z00, &x00 * &y00 + &x01 * &y10); assert_eq!(z01, x00 * &y01 + x01 * &y11); assert_eq!(z10, &x10 * y00 + &x11 * y10); assert_eq!(z11, x10 * y01 + x11 * y11); }, ); } #[test] fn limbs_gcd_div_properties() { unsigned_quadruple_gen_var_11::().test_properties(|(n1, n0, d1, d0)| { let result = limbs_gcd_div_naive(n1, n0, d1, d0); assert_eq!(limbs_gcd_div(n1, n0, d1, d0), result); assert_eq!(limbs_gcd_div_alt(n1, n0, d1, d0), result); }); } #[test] fn limbs_gcd_reduced_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 256); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_10().test_properties_with_config(&config, |(mut xs, mut ys)| { let mut out = vec![0; xs.len()]; let x = Natural::from_limbs_asc(&xs); let y = Natural::from_limbs_asc(&ys); let out_len = limbs_gcd_reduced(&mut out, &mut xs, &mut ys); out.resize(out_len, 0); let g = Natural::from_owned_limbs_asc(out); assert_eq!(gcd_binary_nz(x.clone(), y.clone()), g); assert_eq!(x.gcd(y), g); }); } fn gcd_properties_helper(x: Natural, y: Natural) { let gcd_val_val = x.clone().gcd(y.clone()); let gcd_val_ref = x.clone().gcd(&y); let gcd_ref_val = (&x).gcd(y.clone()); let gcd = (&x).gcd(&y); assert!(gcd_val_val.is_valid()); assert!(gcd_val_ref.is_valid()); assert!(gcd_ref_val.is_valid()); assert!(gcd.is_valid()); assert_eq!(gcd_val_val, gcd); assert_eq!(gcd_val_ref, gcd); assert_eq!(gcd_ref_val, gcd); let mut mut_x = x.clone(); mut_x.gcd_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, gcd); let mut mut_x = x.clone(); mut_x.gcd_assign(&y); assert_eq!(mut_x, gcd); assert!(mut_x.is_valid()); assert_eq!( Natural::from(&(BigUint::from(&x).gcd(&BigUint::from(&y)))), gcd ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x).gcd(&rug::Integer::from(&y)))), gcd ); assert_eq!(gcd_euclidean_nz(x.clone(), y.clone()), gcd); assert_eq!(gcd_binary_nz(x.clone(), y.clone()), gcd); assert_eq!((&y).gcd(&x), gcd); assert!((&x).divisible_by(&gcd)); assert!((&y).divisible_by(&gcd)); assert_eq!(gcd == 0, x == 0 && y == 0); if gcd != 0 { assert!(((&x).div_exact(&gcd)).coprime_with((&y).div_exact(&gcd))); } if x != 0 && y != 0 { assert_eq!(&x * &y / x.lcm(y), gcd); } } #[test] fn gcd_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 512 << Limb::LOG_WIDTH); natural_pair_gen().test_properties_with_config(&config, |(x, y)| { gcd_properties_helper(x, y); }); natural_pair_gen_var_4().test_properties_with_config(&config, |(x, y)| { gcd_properties_helper(x, y); }); natural_gen().test_properties(|x| { assert_eq!((&x).gcd(&x), x); assert_eq!((&x).gcd(Natural::ONE), 1); assert_eq!((&x).gcd(Natural::ZERO), x); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x).gcd(&y).gcd(&z), x.gcd(y.gcd(z))); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).gcd(Natural::from(y)), x.gcd(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen, unsigned_vec_gen_var_1}; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::is_power_of_2::limbs_is_power_of_2; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_gen_var_2}; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_is_power_of_2() { let test = |xs, out| { assert_eq!(limbs_is_power_of_2(xs), out); }; test(&[1], true); test(&[2], true); test(&[3], false); test(&[4], true); test(&[256], true); test(&[0, 0, 0, 256], true); test(&[1, 0, 0, 256], false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_is_power_of_2_fail() { limbs_is_power_of_2(&[]); } #[test] fn test_is_power_of_2() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().is_power_of_2(), out); assert_eq!(rug::Integer::from_str(n).unwrap().is_power_of_two(), out); }; test("0", false); test("1", true); test("2", true); test("3", false); test("4", true); test("5", false); test("6", false); test("7", false); test("8", true); test("1024", true); test("1025", false); test("1000000000000", false); test("1099511627776", true); } #[test] fn limbs_is_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { assert_eq!( limbs_is_power_of_2(&xs), Natural::from_owned_limbs_asc(xs).is_power_of_2() ); }); } #[allow(clippy::cmp_owned, clippy::useless_conversion)] #[test] fn is_power_of_2_properties() { natural_gen().test_properties(|x| { let is_power_of_2 = x.is_power_of_2(); assert_eq!(rug::Integer::from(&x).is_power_of_two(), is_power_of_2); }); natural_gen_var_2().test_properties(|x| { let is_power_of_2 = x.is_power_of_2(); let trailing_zeros = x.trailing_zeros().unwrap(); assert_eq!(trailing_zeros == x.significant_bits() - 1, is_power_of_2); if trailing_zeros <= u64::from(Limb::MAX) { assert_eq!(x >> trailing_zeros == 1, is_power_of_2); } }); unsigned_gen::().test_properties(|u| { assert_eq!(u.is_power_of_2(), Natural::from(u).is_power_of_2()); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/kronecker_symbol.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CoprimeWith, JacobiSymbol, KroneckerSymbol, LegendreSymbol, ModPowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::WrappingInto; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_pair_gen_var_40, unsigned_vec_pair_gen_var_32, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::kronecker_symbol::{ limbs_jacobi_symbol_init, limbs_jacobi_symbol_same_length, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_8, natural_pair_gen, natural_pair_gen_var_4, natural_pair_gen_var_12, natural_pair_gen_var_13, natural_pair_gen_var_14, natural_triple_gen, natural_triple_gen_var_8, natural_triple_gen_var_9, }; use malachite_nz::test_util::natural::arithmetic::kronecker_symbol::jacobi_symbol_simple; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_limbs_jacobi_symbol_same_length() { fn test(xs: &[Limb], ys: &[Limb], s: i8) { let x = Natural::from_limbs_asc(xs); let y = Natural::from_limbs_asc(ys); assert_eq!((&x).jacobi_symbol(&y), s); assert_eq!(jacobi_symbol_simple(x, y), s); let bits = limbs_jacobi_symbol_init(xs[0], ys[0], 0); let xs_orig = xs; let ys_orig = ys; let mut xs = xs_orig.to_vec(); let mut ys = ys_orig.to_vec(); assert_eq!(limbs_jacobi_symbol_same_length(&mut xs, &mut ys, bits), s); } #[cfg(not(feature = "32_bit_limbs"))] { // - n < JACOBI_DC_THRESHOLD // - bits < 16 // - n == 1 // - y_lo == 1 test(&[0], &[1], 1); // - y_lo != 1 // - bits.even() first time test(&[0], &[3], 0); // - n != 1 // - bits.even() second time test(&[0, 0], &[1, 1], 0); // - !mask.get_highest_bit() // - x_1 < 2 || y_1 < 2 in limbs_half_gcd_2_jacobi // - !limbs_half_gcd_2_jacobi // - let Some(gs) = gs in JacobiContext::gcd_subdiv_step_hook // - gs_len != 1 || gs[0] != 1 in JacobiContext::gcd_subdiv_step_hook // - n == 0 second time // - bits == BITS_FAIL second time test(&[0, 0, 0], &[1, 0, 1], 0); // - gs == None in JacobiContext::gcd_subdiv_step_hook // - let Some(qs) = qs in JacobiContext::gcd_subdiv_step_hook // - gs.len() == 1 && gp[0] == 1 in JacobiContext::gcd_subdiv_step_hook // - bits != BITS_FAIL second time test(&[0, 0, 1], &[1, 0, 0], 1); // - x_1 >= 2 && y_1 >= 2 in limbs_half_gcd_2_jacobi // - x_1 <= y_1 && (x_1 != y_1 || x_0 <= y_0) in limbs_half_gcd_2_jacobi // - y_1 < 2 first time in limbs_half_gcd_2_jacobi test(&[0, 0, 1], &[1, 0, 1], 1); // - n != 0 second time test(&[0, 0, 1], &[1, 1, 0], 1); // - x_1 > y_1 || (x_1 == y_1 && x_0 > y_0) in limbs_half_gcd_2_jacobi // - x_1 < 2 first time in limbs_half_gcd_2_jacobi // - bits >= 16 test(&[0, 1, 1], &[1, 0, 1], 1); // - y_1 >= 2 first time in limbs_half_gcd_2_jacobi // - !subtract_a in limbs_half_gcd_2_jacobi // - x_1 == y_1 first time in limbs_half_gcd_2_jacobi // - limbs_half_gcd_2_jacobi test(&[0, 0, 1], &[1, 0, 2], 1); // - subtract_a in limbs_half_gcd_2_jacobi // - x_1 != y_1 second time in limbs_half_gcd_2_jacobi // - y_1 >= Limb::power_of_2(Limb::WIDTH >> 1) in limbs_half_gcd_2_jacobi // - y_1 >= 2 second time in limbs_half_gcd_2_jacobi // - y_1 <= x_1 first time in limbs_half_gcd_2_jacobi test(&[0, 0, 1], &[1, 0, 3], 1); // - x_1 != y_1 first time in limbs_half_gcd_2_jacobi // - x_1 >= Limb::power_of_2(Limb::WIDTH >> 1) in limbs_half_gcd_2_jacobi // - x_1 < 2 second time in limbs_half_gcd_2_jacobi test(&[0, 1, 1], &[1, 0, 2], -1); // - bits.odd() first time test(&[1, 0, 1], &[1, 1, 3], -1); // - x_1 >= 2 first time in limbs_half_gcd_2_jacobi test(&[0, 0, 2], &[1, 0, 1], 1); // - x_1 >= 2 second time in limbs_half_gcd_2_jacobi // - x_1 <= y_1 second time in limbs_half_gcd_2_jacobi // - x_1 == y_1 second time in limbs_half_gcd_2_jacobi test(&[0, 0, 3], &[1, 0, 1], -1); // - y_1 < 2 second time in limbs_half_gcd_2_jacobi test(&[0, 0, 2], &[1, 1, 1], 1); // - bits.odd() second time test(&[0, 1, 2], &[1, 1, 1], 0); // - y_1 > x_1 first time in limbs_half_gcd_2_jacobi // - y_1 < 2 third time in limbs_half_gcd_2_jacobi test(&[0, 0, 3], &[1, 1, 2], 1); // - x_1 > y_1 second time in limbs_half_gcd_2_jacobi // - x_1 < 2 third time in limbs_half_gcd_2_jacobi test(&[0, 1, 2], &[1, 0, 3], -1); // - mask.get_highest_bit() test(&[0, 0, 0, 1, 1], &[1, 0, 0, 0, 1], 1); // - y_1 >= 2 third time in limbs_half_gcd_2_jacobi test(&[0, 0, 1, 1], &[1, 1, 0, 2], 1); // - x_1 >= 2 third time in limbs_half_gcd_2_jacobi // - y_1 < Limb::power_of_2(Limb::WIDTH >> 1) in limbs_half_gcd_2_jacobi // - subtract_a_1 in limbs_half_gcd_2_jacobi // - x_1 != y_1 fourth time in limbs_half_gcd_2_jacobi // - y_1 < TWICE_TWO_POW_HALF_WIDTH first time in limbs_half_gcd_2_jacobi test(&[0, 0, 0, 1, 1], &[1, 1, 1, 0, 1], 1); // - x_1 < TWO_POW_HALF_WIDTH in limbs_half_gcd_2_jacobi // - !subtract_a_1 in limbs_half_gcd_2_jacobi // - x_1 != y_1 third time in limbs_half_gcd_2_jacobi // - x_1 < TWICE_TWO_POW_HALF_WIDTH first time in limbs_half_gcd_2_jacobi test(&[0, 1, 1, 0, 1], &[1, 0, 0, 1, 1], 0); // - y_1 >= TWICE_TWO_POW_HALF_WIDTH first time in limbs_half_gcd_2_jacobi // - y_1 <= x_1 second time in limbs_half_gcd_2_jacobi // - x_1 >= TWICE_TWO_POW_HALF_WIDTH first time in limbs_half_gcd_2_jacobi // - x_1 > y_1 in limbs_half_gcd_2_jacobi // - x_1 < TWICE_TWO_POW_HALF_WIDTH second time in limbs_half_gcd_2_jacobi test(&[0, 0, 1, 3], &[1, 1, 0, 2], 1); // - y_1 > x_1 second time in limbs_half_gcd_2_jacobi // - y_1 < TWICE_TWO_POW_HALF_WIDTH second time in limbs_half_gcd_2_jacobi test(&[0, 0, 0, 1, 1], &[1, 1, 1, 0, 3], 1); // - x_1 <= y_1 in limbs_half_gcd_2_jacobi test(&[0, 0, 1, 0, 1], &[1, 1, 0, 1, 3], 1); // - x_1 == y_1 fourth time in limbs_half_gcd_2_jacobi test(&[0, 1, 0, 1, 1], &[1, 0, 1, 0, 3], -1); // - y_1 >= TWICE_TWO_POW_HALF_WIDTH second time in limbs_half_gcd_2_jacobi test(&[0, 1, 1, 1, 1], &[1, 0, 0, 1, 3], 1); // - x_1 >= TWICE_TWO_POW_HALF_WIDTH second time in limbs_half_gcd_2_jacobi test(&[0, 1, 1, 1, 1], &[1, 1, 0, 0, 3], 1); // - x_1 == y_1 third time in limbs_half_gcd_2_jacobi test(&[0, 1, 0, 1, 2], &[1, 0, 1, 0, 1], 0); } #[cfg(feature = "32_bit_limbs")] { // - n >= JACOBI_DC_THRESHOLD // - dc_scratch_len > scratch_len // - n >= HGCD_THRESHOLD in limbs_half_gcd_jacobi // - n < HGCD_THRESHOLD in limbs_half_gcd_jacobi // - n != s + 1 && !mask.get_highest_bit() in limbs_half_gcd_jacobi_step // - limbs_half_gcd_2_jacobi in limbs_half_gcd_jacobi_step // - nn != 0 fourth time in limbs_half_gcd_jacobi // - n == s + 1 in limbs_half_gcd_jacobi_step // - mask >= 4 in limbs_half_gcd_jacobi_step // - mask < 4 in limbs_half_gcd_jacobi_step // - nn == 0 fourth time in limbs_half_gcd_jacobi // - nn != 0 first time in limbs_half_gcd_jacobi // - nn != 0 second time in limbs_half_gcd_jacobi // - n > s + 2 in limbs_half_gcd_jacobi // - n != s + 1 && mask.get_highest_bit() in limbs_half_gcd_jacobi_step // - !limbs_half_gcd_2_jacobi in limbs_half_gcd_jacobi_step // - nn != 0 third time in limbs_half_gcd_jacobi // - qs_len != 0 in HalfGcdJacobiContext::gcd_subdiv_step_hook // - nn != 0 test( &[ 1873633918, 123030658, 719377342, 1504696614, 2362755734, 3961478485, 781485753, 1658134515, 2113542903, 2810709120, 516343343, 592412664, 389523939, 1066227422, 3298185546, 503562514, 201347799, 3837685524, 1791253076, 2719252242, 3220584319, 2228118840, 2873093023, 3277574845, 4183085011, 1024538582, 1879444551, 4131206800, 1120880147, 693962231, 3607359350, 2707994236, 1776336830, 1261880384, 4191042108, 2802674416, 1093640235, 1117222130, 4191804349, 488263639, 4196953979, 2945863127, 3796408273, 3918535658, 3739145025, 2025532414, 3908394825, 3730013238, 3918858199, 2236390519, 304075529, 588039508, 464824988, 1043329929, 4024659213, 777233325, 2754590310, 430183448, 2116763050, 2194568215, 3983851431, 3079663737, 3609827959, 3165570624, 3778786312, 2207000505, 494983090, 4061038956, 1847009994, 1374726069, 2216864799, 287045089, 1522632156, 3701999684, 628940848, 3777561277, 1853948570, 2149163542, 3146560430, 2662015036, 3673560784, 3148979133, 1498637710, 647923219, 512319396, 3874841555, 2725763682, 705802490, 955850189, 1466834834, 2958146031, 974815424, 3925846741, 3990055262, 2385857769, 1785254473, 975242909, 1640367194, 17679830, 2162917366, 833169313, 3823256168, 3933828973, 3314871585, 801976468, 3300008476, 189067881, 968522820, 701167717, 3456031850, 3807893479, 3883967676, 3397552960, 1177591619, 2235569799, 373301573, 874195563, 2179365380, 2119067928, 2720245803, 1010696918, 1442726415, 1066758009, 2565507481, 2473976884, 3393774679, 3952059313, 3757956916, 3261899893, 2443126808, 1361119172, 2208060333, 3775473672, 3653607071, 1293439175, 435448758, 3990892991, 1286144898, 2494049465, 2398440308, 3756264187, 4812695, 25801943, 226806926, 3042686908, 1989123535, 3254845113, 919895168, 4209027670, 4166349537, 148522488, 973817508, 3765422389, 2523318742, 579963969, 2098988831, 1365027916, 3658076322, 1733252939, 1043406512, 717910858, 2103188848, 3566233409, 1012130235, 1855787810, 156497531, 1958213821, 715897916, 4210647949, 1362164018, 3523905136, 678285695, 893316222, 4002270604, 2743748491, 1734398700, 4013187857, 3355679131, 3312607834, 671835519, 151753042, 3175422619, 2357087390, 1388249743, 3345521534, 2885692694, 3727953305, 210133499, 1091341046, 3272930824, 2473688375, 643815394, 2815077147, 3640266733, 1129170891, 591859561, 92728385, 1710489516, 2247919245, 3303371411, 2878106269, 3299382591, 6838220, 2207248685, 1067399745, 3227744596, 706680457, 347073425, 2315288352, 3459009392, 369508525, 2058436577, 723699746, 1636431631, 1393077501, 4220412446, 1818976107, 1429834151, 1320074954, 1810726444, 4038059510, 3467618009, 320963964, 1111140807, 3131364647, 1235553534, 16798724, 19240978, 2108447774, 143304067, 1703667778, 861127847, 1186666148, 1478800880, 1170455588, 2625617857, 488704999, 2402011494, 1397588188, 3587645117, 379450888, 2093883128, 1089613602, 1380578556, 3780609811, 2264391031, 1078858400, 2436761299, 3025683539, 4068664961, 3262585229, 710877465, 3189533901, 3423405972, 4226527191, 1281614997, 11582026, 4187361634, 1934508614, 2978905528, 3811137180, 254480797, 3957068379, 276691084, 980502794, 2333498429, 2402962021, 1968336748, 937179998, 328237312, 3105135306, 2708438479, 807396072, 4090616190, 338836192, 3493021773, 1007932634, 989046118, 475565105, 4280477458, 2889310878, 506168430, 2744969090, 1717140865, 180101187, 3946998676, 3256792444, 1651611832, 2217469837, 639375671, 3754995303, 803291429, 559260186, 3312276405, 1307739531, 637914444, 800094865, 1566616440, 8698228, 205523792, 1663664157, 4012170144, 1845279876, 414628822, 2589258003, 2046627153, 4252798243, 888708228, 1078803694, 2357638662, 4007813553, 2748056828, 1261654782, 3168764324, 1241689206, 2318873504, 376674550, 1961382315, 3250714815, 47982921, 1081086646, 2017910660, 3376874155, 3907817672, 3337262433, 2781215129, 700917261, 3986793763, 603713597, 2286652653, 2487070286, 3503515107, 3549521582, 2229840842, 106670130, 2152342444, 2614172954, 2980612046, 1711600105, 3367600130, 224267645, 147721273, 3762102334, 909656137, 2765963499, 1287501967, 3853510171, 2602535793, 687227193, 3372261235, 2071559967, 2243249886, 1302529466, 1536608166, 141064408, 1798146420, 1490894727, 4069708793, 539834647, 3483430067, 3470554577, 1125163274, 1002230975, 782459269, 1965180788, 1031655683, 957046550, 1927934983, 1014977728, 748904605, 1278878668, 3257529883, 1525236512, 3452233244, 595919552, 3284927605, 3947267553, 990044496, 2645462059, 3185056815, 3364504564, 2742517875, 2254394076, 256336642, 2622723662, 2255022161, 307535959, 2740603712, 326158350, 4134908299, 2331131321, 2268360042, 1661560181, 296127993, 65765671, 2991972277, 3942011917, 2155904650, 2798972906, 19922601, 336740766, 2370937438, 2954540796, 1662173899, ], &[ 1077171533, 3384534038, 3509377481, 3012981171, 2169372009, 3568066367, 510541737, 360351115, 1116770051, 2058732872, 3226198045, 1078176389, 2950624729, 812262025, 1430083408, 61306667, 64349919, 2388720201, 2804807299, 3487065571, 1162686670, 2184575935, 1234374819, 3462973209, 2204618738, 1955732567, 4274764191, 487910035, 2794693464, 1455130957, 2647605728, 4211289912, 3386405281, 117329687, 3432428417, 1300225461, 3461206919, 449524200, 904979455, 3971171435, 441380375, 1283836003, 2682594354, 1152961793, 1318795928, 308922730, 628004645, 1003117196, 1035594263, 3028460626, 3737759554, 3080878651, 2013071269, 157811103, 3209212678, 1794098871, 1571763958, 4118994167, 3323265833, 2779923965, 1781531454, 3074442432, 1330835008, 231050954, 1972822306, 3779389322, 2550908177, 1122947161, 2607600449, 2966179614, 1165225297, 4222222976, 1020266087, 1019514006, 53769477, 62821411, 3078440286, 2087323177, 4209236301, 146146381, 453393163, 4244430148, 624415024, 2096395426, 1915435196, 3779399544, 3641826296, 4157323023, 4049792386, 1892149154, 2185863226, 1046224168, 3568999985, 982204298, 154455361, 2605934809, 2605177974, 1652215061, 3058430834, 1573346022, 3979000833, 1424146496, 758475042, 3880559465, 3331749655, 4009275982, 309023272, 343958017, 2544085697, 1960862631, 1082361995, 534185037, 331011064, 3662295811, 3280920837, 2366184597, 1029851460, 1149922348, 3242309342, 3498011365, 1869617138, 2033933372, 2449772239, 1769059102, 552671522, 2541136194, 1837261562, 3331388737, 3882095076, 2111080116, 3488393361, 3110154197, 2503543094, 276095820, 109038743, 3401659741, 2955647843, 3730124703, 4288579615, 2840357519, 433563482, 3742367408, 2287152115, 3054337338, 2305325930, 1838329967, 1117989732, 2731369203, 427022429, 1959348870, 107371881, 1378273431, 3969746745, 137314119, 3494302009, 2316521941, 1304670415, 2017956904, 3960566359, 3950960171, 2483760563, 3248620299, 1282201932, 2666453601, 290925463, 1315172510, 2244058356, 83064665, 2794575253, 2751020494, 86251099, 1497864163, 1309606664, 918139255, 2382232313, 3431694285, 4197334044, 3779739436, 2597050321, 4053750034, 1347898240, 2068381165, 530540195, 777294114, 1563424547, 714733079, 251090961, 1222614986, 409927269, 2552943554, 3813553790, 2619995688, 2754487462, 1001623689, 4043538191, 780110724, 2756539090, 2640687797, 2974350673, 1702213372, 2898669867, 232176052, 2414666354, 300281312, 3252747308, 2375533144, 3579260801, 3856594937, 226065085, 2855017957, 4106625762, 4251800319, 271717704, 796181594, 2015816818, 572129733, 1578027849, 208352494, 3329313861, 3272451839, 1390383564, 3754291474, 1022210892, 3402379185, 1055267474, 2105880379, 1377373336, 2125916506, 3713096588, 3227913500, 593660170, 3662162553, 948899397, 3959019656, 743736078, 561608271, 4154259253, 753202703, 3057879152, 4093431092, 2849520862, 1298183896, 1072767461, 3844624206, 1553109174, 2211737614, 2944064724, 1134344972, 2846368205, 2535247938, 1454739286, 1408186915, 3022639671, 2985835925, 1242350664, 856614531, 3277904750, 2435844371, 2288413570, 1941580081, 2330069009, 3763753263, 1617186357, 3858822820, 3899619764, 957776791, 2415934649, 1903499570, 362345092, 3162421697, 857308796, 2166848441, 2794392063, 2916482641, 547554093, 393697940, 319583576, 3206427070, 3502792667, 3979846702, 3580352012, 3854879140, 3646613450, 4113031775, 856333171, 1029998771, 2090645466, 3125086584, 2494710984, 3249027001, 3828101842, 4278721100, 2901896440, 3549366611, 2066085974, 3815811960, 2980213693, 2418009668, 4168963107, 1522903282, 3921187989, 209293309, 1026651789, 3652402308, 1723212287, 3005358245, 3972955479, 3432513818, 1135457591, 2609451544, 1728509125, 1610815908, 1281322374, 2308282400, 1650462965, 785788526, 3039230497, 1454810597, 2847801652, 868324593, 2811238675, 1592440137, 2837082164, 2293886194, 108023352, 1338057151, 867454780, 660204887, 2727424012, 3251699301, 2307270502, 3508727390, 444210859, 4112897129, 1692014843, 232384981, 3746950478, 2035293041, 832494472, 4167968781, 2088468820, 1082123254, 2004377194, 739887690, 3903970376, 3917684808, 2220241302, 1623595193, 3168893289, 1380144222, 3245294302, 1942246969, 1017235276, 1075796476, 1420638313, 2370978268, 3571300703, 2818383559, 3979048442, 4070073076, 3639658932, 2458302928, 1936855091, 1097653713, 2517446959, 395058431, 2490534065, 3621579656, 537422087, 820775047, 1621745064, 4147607605, 773085439, 150346009, 3309770346, 623052976, 223120997, 1047915001, 2440220896, 2701090680, 682463717, 626719149, 2752394251, 2245504316, 3599570937, 1008202886, 3061625147, 3833145985, 2287104975, 3419855448, 542949621, 2260871982, 3411141468, 1089194931, 3865896761, 1906114014, 3523746087, 3034843700, 3980408914, 1779312499, 2670385907, 3943945115, 3040560985, 968208310, ], -1, ); // - qs_len == 0 in HalfGcdJacobiContext::gcd_subdiv_step_hook test( &[ 3557994669, 445289342, 1108435216, 1656651402, 3854541936, 2345816964, 2732613883, 1181815769, 560246346, 2217942797, 3034747849, 2128803109, 193138609, 1787921939, 785846271, 690755, 4293433511, 1146911147, 4050052816, 826026913, 3182494773, 3156626600, 1014266169, 3323102091, 2921068424, 476686040, 7910507, 654440565, 3535711772, 3930398141, 4128513830, 2598121764, 4062960176, 3972780227, 855940423, 2256067460, 392376529, 2033808759, 3816270018, 1855458657, 2715891121, 3669089929, 3731047748, 1721938090, 2227294219, 3031269426, 1551726027, 3859144725, 4149437041, 3000994525, 3261175418, 2833753411, 4060863432, 2716969708, 4189891569, 677103308, 1365006263, 3293330016, 1768027889, 545258844, 2935866981, 250251281, 3680035401, 2700291474, 594423218, 898497607, 887621248, 3695367571, 2120585809, 1695812396, 645346742, 1835776782, 3264740207, 3486429797, 4208339033, 72066698, 2225784172, 1683577015, 3001910364, 3707465962, 1815190269, 124430948, 1869715335, 1801604000, 213381934, 3130033208, 3564635797, 474180177, 4240626321, 2076460830, 3656363137, 1132903283, 3991161472, 3821161503, 1744455617, 1045140442, 3902771928, 781148403, 2357356142, 3040623797, 2619406559, 195467574, 641531975, 3441001365, 114745412, 4134746228, 1311731821, 3461413652, 979311481, 1305256219, 977408510, 2999824757, 440721333, 3844175796, 1924795791, 3120129120, 532972790, 165893187, 4147094465, 3990693806, 2964895445, 1000735990, 331761162, 373581533, 1064345288, 1266123883, 2040591269, 1523811553, 2568191458, 2481902226, 2320866160, 1436736, 4008889052, 1280546217, 2098385450, 4119408023, 411283261, 3289104101, 3425489515, 2456862903, 2125542000, 1789202658, 497535957, 417045728, 3331787711, 3672146250, 1403849606, 1158118016, 1513052203, 1137714766, 4254706104, 2031746768, 1359724368, 3803765572, 422159546, 898111315, 2724325274, 1627832336, 1830223095, 4270287508, 1215166891, 2436306311, 907260779, 4034312884, 1698645062, 1078681555, 3198597175, 1586826465, 2046732632, 66062249, 3358599308, 232196012, 629981202, 935508892, 3170800564, 2191875696, 2503459156, 447871479, 3269004498, 2153827076, 267450909, 1520769342, 1163927607, 2575984589, 2978684947, 1813055270, 431843507, 226606783, 811301393, 2458665352, 585771839, 2841530354, 3556530842, 2435178025, 2845793940, 3637609260, 406241340, 144056695, 3122547306, 2101164412, 3905238054, 318269719, 3253726651, 1443434883, 178618945, 153042080, 2023190013, 2275803876, 2774886429, 3703342339, 2715860001, 1015326289, 2988607429, 1091753318, 1280790766, 779483175, 4181404689, 797271578, 3837324542, 965653269, 3998678544, 3707299808, 518493388, 2081242998, 565821490, 1370788325, 3775338190, 3238414037, 576068479, 2735674700, 1184491085, 4009553275, 3572635037, 1243646536, 2911509472, 2973906905, 1907167846, 1458306202, 2123107667, 989552556, 436261057, 605573158, 3483230043, 2880983042, 4168409866, 4019136255, 4253327858, 2651830192, 17400570, 109318954, 2078546974, 3534044718, 346014829, 3754708985, 592559018, 1742898159, 33427990, 856129692, 2342055152, 1941602123, 1408405136, 894595226, 2387883501, 3646482099, 3519957459, 2080906515, 1904107628, 3069440838, 3932421765, 3266993370, 4136525054, 4220115422, 788731893, 1686867215, 1519823776, 2877756565, 3793887677, 329226793, 3893797702, 3583826624, 1694823997, 696220909, 3611742558, 3078864649, 3766315815, 1632326088, 2654432468, 3981882671, 2280957273, 793625459, 1157977495, 1441316728, 197154581, 1561124715, 4189778267, 1333945477, 3967181114, 1421232429, 3533069272, 887767315, 2239652930, 1638811648, 3473233699, 1181657596, 3085652783, 1287675993, 2455078898, 1233237192, 2458447943, 204196519, 3524654715, 336439681, 3814153229, 3678776643, 2407863111, 2675325179, 2161593579, 1925372399, 675067792, 2605820490, 4256815185, 1323539594, 426745374, 715074163, 582328134, 2873514058, 2781239268, 466361343, 4220762639, 3844401378, 588421780, 899607035, 1173758884, 3529587577, 4191404586, 1689668754, 339535512, 11588832, 81658456, 477141048, 206734791, 3326055602, 1891545837, 117975561, 2547113968, 873099055, 682751521, 398130815, 2348739960, 182088623, 1296089616, 2510361486, 3939228547, 977564178, 3496437434, 1651453093, 2664075234, 4143568438, 387896255, 3402931396, 289202123, 2509994131, 385929339, 1853496317, 3349095771, 3744525316, 2501099484, 1571812210, 744319117, 1974272901, 862213254, 1175782054, 1175784197, 3493591642, 3451744657, 933240322, 2199334346, 2473006426, 1633463866, 448919678, 1987732235, 475336389, 2531498167, 2845909593, 672719533, 3917070486, 3812486327, 921951784, 935351493, 880449089, 3861127468, 2856437655, 1122235431, 1105796631, 1824141540, 3552996529, 1526795410, 634765135, 2225592783, 1934399617, 3018228838, 2932938217, 4119878576, 2645355264, 2039885213, 4107872338, 2577396222, 1300242611, 1610879235, 2886027894, 83647147, 1142510940, 1637400124, 3325978372, 1118962329, 1227985700, 4176365484, 4116884066, 93911175, 1843931255, 3241661048, 2946824243, 4229518060, 4153977648, 1821838858, 932057741, 3403948153, 681930575, 345042433, 3238398483, 3522674175, 1511145458, 2225511649, 1601323695, 2734513014, 2978365108, 1606989364, 946945525, 1990882013, 3195215258, 3914587165, 2448441155, 1748490947, 2249032459, 1619210750, 1164959769, 2865145797, 3737266053, 3035927303, 2962530478, 265946106, 833476822, 666127741, 3717419208, 2958451448, 244770831, 1823748962, 3500566168, 2067490898, 3303161181, 2858054390, 4069571771, 3028106864, 8735465, 3953855297, 659633477, 2990915486, 3679301885, 1463896161, 3797786358, 2022879581, 2799640567, 2175987369, 3245839346, 4240563036, 2551089091, ], &[ 1659959583, 2904634437, 335609799, 4208083935, 2129829927, 3164938818, 1437094842, 4128695178, 776066331, 3206868490, 256975577, 3354430510, 2140456023, 4193571596, 4266016240, 1376301017, 506915445, 4013967736, 3657139290, 223860627, 3175388958, 599853167, 725799221, 4128800655, 1480213210, 175078040, 1886675185, 1738455879, 2008734389, 1737895694, 2834508091, 1703658096, 3507753057, 3993341225, 568791580, 1023600771, 874605814, 65887225, 30573824, 2705597852, 2665836303, 3561654523, 3508037727, 1392125564, 3754257083, 2020933944, 4083241095, 4072208472, 2907998249, 1804340494, 3200608953, 577970893, 486672367, 1814354067, 3513024420, 1138655286, 1536324596, 4110629631, 2808131793, 69933854, 2475345926, 2887472024, 4116014864, 4018460348, 608873722, 3537176373, 3911227381, 3805837398, 1420242961, 1313695988, 1355817019, 764772441, 1215440552, 2083287207, 642044699, 921046423, 2265142632, 906587028, 174772424, 4104145270, 4199953868, 717960181, 2001049957, 2366068998, 2336245127, 2655659318, 782347589, 3183312496, 3382146064, 4213611770, 2427981515, 1765643471, 3126151525, 1453973803, 3252697014, 1560005976, 855968672, 1728830740, 3385306541, 177162479, 1024782804, 268504726, 1300885248, 1892046392, 1894377755, 3334999753, 780888935, 152771001, 66154343, 753130677, 1724675242, 3416975300, 2011564755, 3092786038, 1173839777, 502502924, 3514522395, 3492457582, 1655067969, 298388618, 1507409745, 4042261481, 1925841276, 514542391, 3251704090, 1720846063, 1424865256, 3297538873, 1875557160, 3572248143, 3236552016, 618425118, 1198410399, 3256702606, 2084542045, 3780234755, 2145950572, 97693459, 544125496, 4169732002, 2879169387, 3259419966, 2845079327, 1681321406, 553984684, 1625241374, 3667423846, 3512256822, 179220058, 3368809252, 940925092, 2204117315, 911144717, 3702475909, 1079496526, 3502765039, 1331463976, 1674009176, 4251763704, 475983445, 3375462610, 2031227825, 405099033, 101760435, 2599463798, 2175561479, 253471718, 2996294940, 612011453, 736609471, 1270127612, 928651447, 832132468, 1202045767, 1512660791, 1685269400, 1866039474, 3003538147, 1306427040, 2419401400, 2727784058, 2592708024, 1060360987, 3688549328, 3939457653, 213067692, 1791205457, 2313629636, 2382874156, 2897125589, 3092816471, 1459440010, 140615575, 3161769034, 1594344003, 4022901885, 3044761935, 2388083845, 3637404570, 3671760657, 3492650532, 2761768206, 3954822945, 112327455, 3219134020, 1811940545, 1378571471, 3747780753, 2264252238, 2008656851, 2223880320, 858157798, 1785441029, 2737890036, 4190598099, 3967960030, 4007684525, 2861863392, 2650800814, 1535056048, 2444559101, 196252521, 1487672921, 1520614795, 3333508154, 3661606593, 629421626, 358772008, 4003360989, 2950979293, 931493453, 3325437104, 3144184501, 447882868, 2892677553, 3287394621, 2397328790, 2248463212, 1418526562, 2117014926, 3686766031, 298649829, 584205839, 3627557585, 2998315853, 2977920493, 726632938, 3587672184, 2031497493, 3536637527, 2147351398, 2994151365, 2357491055, 2685427052, 561736037, 249434731, 37851003, 2139420207, 1456949077, 3499596051, 2387808327, 698459036, 2829626440, 1153227452, 2967364067, 1308820861, 3023499589, 3279604314, 1351494432, 889784871, 236547645, 2007227680, 595443432, 1146281314, 3645152419, 3684480237, 1893493610, 3759196246, 1654652555, 1570985606, 3168763126, 1011656140, 443293510, 4075348841, 3769289235, 3178746711, 2447901158, 1462169783, 2059860955, 3176730687, 4250518815, 2494049638, 2842999845, 2660773548, 2429754290, 2910792523, 447755453, 1292065721, 1364296417, 531674748, 2193540777, 2412916570, 28609683, 2221611024, 3779881643, 4195316838, 743899040, 4213767553, 27880778, 1574053906, 1155505137, 439874260, 3750284675, 3525838570, 1095901379, 578703301, 3049020885, 3076480478, 600357557, 485719043, 2996666070, 969220829, 382916967, 4127194422, 1105131550, 1274911215, 804142925, 1973587943, 3032041047, 3584540133, 3351136224, 3543725084, 2962955598, 4293881521, 2425133896, 660514410, 3361169054, 77763049, 4229878743, 4011932021, 1090195601, 275885704, 3640421637, 1393243181, 1181392749, 3389311176, 2310097427, 289908933, 1711535789, 4033213111, 393665786, 923868932, 4018570793, 760848544, 674950332, 3344550397, 4011950991, 190003021, 4198189972, 3933037427, 3414307787, 3621605663, 3363592942, 2828152179, 644352484, 2918972032, 3175404448, 1785883817, 3697552954, 733843149, 286590854, 1214528285, 4166016418, 471561591, 2415332960, 1189766994, 1211081173, 4272651438, 3658504023, 755193424, 1817559547, 3945505192, 2450391056, 608673849, 1759503207, 340654448, 4134788276, 716854876, 1927628933, 3770411883, 3272236481, 3570235672, 326127009, 243730071, 1195661416, 3081806246, 3497515351, 2099772515, 1455307780, 1228408049, 4104831308, 1973834358, 4080297784, 578026510, 1512759928, 1470813128, 2584189047, 2637446524, 1698422615, 1284857912, 486923383, 174367540, 3702801188, 1161365394, 2737086689, 4265331868, 2412069202, 1870108327, 701659394, 2415165383, 1604722515, 2870993251, 471129547, 1280015857, 2050493217, 274565042, 2441183839, 3443859668, 2340505028, 1660404263, 2752768160, 560703857, 2104329624, 3452739653, 1013253476, 721912154, 1823929621, 3194765430, 1314309520, 4145569405, 1487647842, 1711679024, 1867628450, 2953439882, 1443642820, 2877245620, 2468137212, 3585016849, 2470055841, 2779688530, 3723417454, 2154058910, 1467213764, 3245268497, 4158596454, 4019385724, 2344037496, 1740779840, 4048853262, 1322676367, 2118663058, 2422287837, 2128664579, 2216474287, 1392815988, 747608508, 3828366939, 1008849042, 2597739640, 1600350391, 1209606111, 1982580858, 1492943335, 3554519928, 154739547, 1939048949, ], -1, ); // - nn == 0 first time in limbs_half_gcd_jacobi test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967168, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294950912, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 3758096384, 524287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483648, 16777215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4290772992, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 32767, 0, 0, 0, 0, 0, 0, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 31, 0, 0, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 4294934528, u32::MAX, u32::MAX, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 65535, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], -1, ); // - n <= s + 2 in limbs_half_gcd_jacobi test( &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 262143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4026531840, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 131071, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4293918720, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 2147483648, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16777215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160749568, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967264, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 134217727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3758096384, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 536870911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294836224, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], 1, ); // - nn == 0 second time in limbs_half_gcd_jacobi // - nn == 0 // - n == 0 first time // - bits == BITS_FAIL first time test( &[ 1077171533, 3384534038, 3509377481, 3012981171, 2169372009, 3568066367, 510541737, 360351115, 1116770051, 2058732872, 3226198045, 1078176389, 2950624729, 812262025, 1430083408, 61306667, 64349919, 2388720201, 2804807299, 3487065571, 1162686670, 2184575935, 1234374819, 3462973209, 2204618738, 1955732567, 4274764191, 487910035, 2794693464, 1455130957, 2647605728, 4211289912, 3386405281, 117329687, 3432428417, 1300225461, 3461206919, 449524200, 904979455, 3971171435, 441380375, 1283836003, 2682594354, 1152961793, 1318795928, 308922730, 628004645, 1003117196, 1035594263, 3028460626, 3737759554, 3080878651, 2013071269, 157811103, 3209212678, 1794098871, 1571763958, 4118994167, 3323265833, 2779923965, 1781531454, 3074442432, 1330835008, 231050954, 1972822306, 3779389322, 2550908177, 1122947161, 2607600449, 2966179614, 1165225297, 4222222976, 1020266087, 1019514006, 53769477, 62821411, 3078440286, 2087323177, 4209236301, 146146381, 453393163, 4244430148, 624415024, 2096395426, 1915435196, 3779399544, 3641826296, 4157323023, 4049792386, 1892149154, 2185863226, 1046224168, 3568999985, 982204298, 154455361, 2605934809, 2605177974, 1652215061, 3058430834, 1573346022, 3979000833, 1424146496, 758475042, 3880559465, 3331749655, 4009275982, 309023272, 343958017, 2544085697, 1960862631, 1082361995, 534185037, 331011064, 3662295811, 3280920837, 2366184597, 1029851460, 1149922348, 3242309342, 3498011365, 1869617138, 2033933372, 2449772239, 1769059102, 552671522, 2541136194, 1837261562, 3331388737, 3882095076, 2111080116, 3488393361, 3110154197, 2503543094, 276095820, 109038743, 3401659741, 2955647843, 3730124703, 4288579615, 2840357519, 433563482, 3742367408, 2287152115, 3054337338, 2305325930, 1838329967, 1117989732, 2731369203, 427022429, 1959348870, 107371881, 1378273431, 3969746745, 137314119, 3494302009, 2316521941, 1304670415, 2017956904, 3960566359, 3950960171, 2483760563, 3248620299, 1282201932, 2666453601, 290925463, 1315172510, 2244058356, 83064665, 2794575253, 2751020494, 86251099, 1497864163, 1309606664, 918139255, 2382232313, 3431694285, 4197334044, 3779739436, 2597050321, 4053750034, 1347898240, 2068381165, 530540195, 777294114, 1563424547, 714733079, 251090961, 1222614986, 409927269, 2552943554, 3813553790, 2619995688, 2754487462, 1001623689, 4043538191, 780110724, 2756539090, 2640687797, 2974350673, 1702213372, 2898669867, 232176052, 2414666354, 300281312, 3252747308, 2375533144, 3579260801, 3856594937, 226065085, 2855017957, 4106625762, 4251800319, 271717704, 796181594, 2015816818, 572129733, 1578027849, 208352494, 3329313861, 3272451839, 1390383564, 3754291474, 1022210892, 3402379185, 1055267474, 2105880379, 1377373336, 2125916506, 3713096588, 3227913500, 593660170, 3662162553, 948899397, 3959019656, 743736078, 561608271, 4154259253, 753202703, 3057879152, 4093431092, 2849520862, 1298183896, 1072767461, 3844624206, 1553109174, 2211737614, 2944064724, 1134344972, 2846368205, 2535247938, 1454739286, 1408186915, 3022639671, 2985835925, 1242350664, 856614531, 3277904750, 2435844371, 2288413570, 1941580081, 2330069009, 3763753263, 1617186357, 3858822820, 3899619764, 957776791, 2415934649, 1903499570, 362345092, 3162421697, 857308796, 2166848441, 2794392063, 2916482641, 547554093, 393697940, 319583576, 3206427070, 3502792667, 3979846702, 3580352012, 3854879140, 3646613450, 4113031775, 856333171, 1029998771, 2090645466, 3125086584, 2494710984, 3249027001, 3828101842, 4278721100, 2901896440, 3549366611, 2066085974, 3815811960, 2980213693, 2418009668, 4168963107, 1522903282, 3921187989, 209293309, 1026651789, 3652402308, 1723212287, 3005358245, 3972955479, 3432513818, 1135457591, 2609451544, 1728509125, 1610815908, 1281322374, 2308282400, 1650462965, 785788526, 3039230497, 1454810597, 2847801652, 868324593, 2811238675, 1592440137, 2837082164, 2293886194, 108023352, 1338057151, 867454780, 660204887, 2727424012, 3251699301, 2307270502, 3508727390, 444210859, 4112897129, 1692014843, 232384981, 3746950478, 2035293041, 832494472, 4167968781, 2088468820, 1082123254, 2004377194, 739887690, 3903970376, 3917684808, 2220241302, 1623595193, 3168893289, 1380144222, 3245294302, 1942246969, 1017235276, 1075796476, 1420638313, 2370978268, 3571300703, 2818383559, 3979048442, 4070073076, 3639658932, 2458302928, 1936855091, 1097653713, 2517446959, 395058431, 2490534065, 3621579656, 537422087, 820775047, 1621745064, 4147607605, 773085439, 150346009, 3309770346, 623052976, 223120997, 1047915001, 2440220896, 2701090680, 682463717, 626719149, 2752394251, 2245504316, 3599570937, 1008202886, 3061625147, 3833145985, 2287104975, 3419855448, 542949621, 2260871982, 3411141468, 1089194931, 3865896761, 1906114014, 3523746087, 3034843700, 3980408914, 1779312499, 2670385907, 3943945115, 3040560985, 968208310, ], &[ 1077171533, 3384534038, 3509377481, 3012981171, 2169372009, 3568066367, 510541737, 360351115, 1116770051, 2058732872, 3226198045, 1078176389, 2950624729, 812262025, 1430083408, 61306667, 64349919, 2388720201, 2804807299, 3487065571, 1162686670, 2184575935, 1234374819, 3462973209, 2204618738, 1955732567, 4274764191, 487910035, 2794693464, 1455130957, 2647605728, 4211289912, 3386405281, 117329687, 3432428417, 1300225461, 3461206919, 449524200, 904979455, 3971171435, 441380375, 1283836003, 2682594354, 1152961793, 1318795928, 308922730, 628004645, 1003117196, 1035594263, 3028460626, 3737759554, 3080878651, 2013071269, 157811103, 3209212678, 1794098871, 1571763958, 4118994167, 3323265833, 2779923965, 1781531454, 3074442432, 1330835008, 231050954, 1972822306, 3779389322, 2550908177, 1122947161, 2607600449, 2966179614, 1165225297, 4222222976, 1020266087, 1019514006, 53769477, 62821411, 3078440286, 2087323177, 4209236301, 146146381, 453393163, 4244430148, 624415024, 2096395426, 1915435196, 3779399544, 3641826296, 4157323023, 4049792386, 1892149154, 2185863226, 1046224168, 3568999985, 982204298, 154455361, 2605934809, 2605177974, 1652215061, 3058430834, 1573346022, 3979000833, 1424146496, 758475042, 3880559465, 3331749655, 4009275982, 309023272, 343958017, 2544085697, 1960862631, 1082361995, 534185037, 331011064, 3662295811, 3280920837, 2366184597, 1029851460, 1149922348, 3242309342, 3498011365, 1869617138, 2033933372, 2449772239, 1769059102, 552671522, 2541136194, 1837261562, 3331388737, 3882095076, 2111080116, 3488393361, 3110154197, 2503543094, 276095820, 109038743, 3401659741, 2955647843, 3730124703, 4288579615, 2840357519, 433563482, 3742367408, 2287152115, 3054337338, 2305325930, 1838329967, 1117989732, 2731369203, 427022429, 1959348870, 107371881, 1378273431, 3969746745, 137314119, 3494302009, 2316521941, 1304670415, 2017956904, 3960566359, 3950960171, 2483760563, 3248620299, 1282201932, 2666453601, 290925463, 1315172510, 2244058356, 83064665, 2794575253, 2751020494, 86251099, 1497864163, 1309606664, 918139255, 2382232313, 3431694285, 4197334044, 3779739436, 2597050321, 4053750034, 1347898240, 2068381165, 530540195, 777294114, 1563424547, 714733079, 251090961, 1222614986, 409927269, 2552943554, 3813553790, 2619995688, 2754487462, 1001623689, 4043538191, 780110724, 2756539090, 2640687797, 2974350673, 1702213372, 2898669867, 232176052, 2414666354, 300281312, 3252747308, 2375533144, 3579260801, 3856594937, 226065085, 2855017957, 4106625762, 4251800319, 271717704, 796181594, 2015816818, 572129733, 1578027849, 208352494, 3329313861, 3272451839, 1390383564, 3754291474, 1022210892, 3402379185, 1055267474, 2105880379, 1377373336, 2125916506, 3713096588, 3227913500, 593660170, 3662162553, 948899397, 3959019656, 743736078, 561608271, 4154259253, 753202703, 3057879152, 4093431092, 2849520862, 1298183896, 1072767461, 3844624206, 1553109174, 2211737614, 2944064724, 1134344972, 2846368205, 2535247938, 1454739286, 1408186915, 3022639671, 2985835925, 1242350664, 856614531, 3277904750, 2435844371, 2288413570, 1941580081, 2330069009, 3763753263, 1617186357, 3858822820, 3899619764, 957776791, 2415934649, 1903499570, 362345092, 3162421697, 857308796, 2166848441, 2794392063, 2916482641, 547554093, 393697940, 319583576, 3206427070, 3502792667, 3979846702, 3580352012, 3854879140, 3646613450, 4113031775, 856333171, 1029998771, 2090645466, 3125086584, 2494710984, 3249027001, 3828101842, 4278721100, 2901896440, 3549366611, 2066085974, 3815811960, 2980213693, 2418009668, 4168963107, 1522903282, 3921187989, 209293309, 1026651789, 3652402308, 1723212287, 3005358245, 3972955479, 3432513818, 1135457591, 2609451544, 1728509125, 1610815908, 1281322374, 2308282400, 1650462965, 785788526, 3039230497, 1454810597, 2847801652, 868324593, 2811238675, 1592440137, 2837082164, 2293886194, 108023352, 1338057151, 867454780, 660204887, 2727424012, 3251699301, 2307270502, 3508727390, 444210859, 4112897129, 1692014843, 232384981, 3746950478, 2035293041, 832494472, 4167968781, 2088468820, 1082123254, 2004377194, 739887690, 3903970376, 3917684808, 2220241302, 1623595193, 3168893289, 1380144222, 3245294302, 1942246969, 1017235276, 1075796476, 1420638313, 2370978268, 3571300703, 2818383559, 3979048442, 4070073076, 3639658932, 2458302928, 1936855091, 1097653713, 2517446959, 395058431, 2490534065, 3621579656, 537422087, 820775047, 1621745064, 4147607605, 773085439, 150346009, 3309770346, 623052976, 223120997, 1047915001, 2440220896, 2701090680, 682463717, 626719149, 2752394251, 2245504316, 3599570937, 1008202886, 3061625147, 3833145985, 2287104975, 3419855448, 542949621, 2260871982, 3411141468, 1089194931, 3865896761, 1906114014, 3523746087, 3034843700, 3980408914, 1779312499, 2670385907, 3943945115, 3040560985, 968208310, ], 0, ); // - n != 0 first time test( &[ 2527776570, 1096068921, 3262306218, 1320735475, 3585033863, 837181718, 1434028202, 101347753, 1225665622, 67225439, 876392417, 2005928391, 1055641927, 2192872866, 2819789958, 730215470, 1621800044, 4036225587, 3556548105, 3110943208, 3185668368, 2027089067, 2101840218, 4225448827, 3021189927, 4280012260, 3622060673, 2596479319, 2588713825, 1028636336, 3005767087, 1249021277, 4164898722, 731420324, 1545357905, 1990024360, 2640852447, 2424127910, 1870854337, 1406415699, 2196092126, 1310967564, 232318981, 3146607976, 4083502397, 22174679, 3737886384, 3144967018, 4263470608, 3780127714, 2165861131, 3336828897, 1694667359, 1492938371, 494778850, 3046154974, 1157896728, 3074135421, 2504833163, 810655235, 1557262964, 1363420755, 2702433995, 1177464584, 3371204921, 3586238385, 281106173, 1653503734, 2385994192, 3794586631, 3194300174, 847482886, 2910519739, 3968032513, 1772081491, 2782405946, 4234346611, 3594663949, 2600834058, 1201913439, 3836544822, 2596924324, 3356614882, 1073086697, 4071118647, 1627306041, 25361421, 5025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ 5737393, 656355346, 2428436877, 1659347327, 1816624877, 3040364388, 1159326770, 4206559661, 3092296489, 1558251555, 1049236200, 2222235583, 2014235172, 3291004209, 934339935, 985867991, 762407537, 1409401405, 778491764, 3564656357, 128109175, 2460849082, 1890568470, 461692287, 817897242, 602238225, 920048131, 3418406322, 708192111, 2567463295, 1875671904, 1148800469, 3212120696, 566830399, 1427401847, 3369501422, 3485886037, 2817269664, 2227802377, 4283410186, 2703903094, 936664805, 4157101885, 2263955722, 2647106937, 537917125, 4056960194, 3912645532, 354245311, 2717804064, 1109582468, 2727640815, 425052729, 2611473321, 3879075705, 716899167, 1914192905, 2601501681, 462694240, 205229129, 1093878128, 410346932, 3439980661, 667954709, 1052656728, 2148601811, 2379731442, 2268999665, 3706142073, 1456579358, 3757504240, 463695214, 1436957313, 2049267296, 3303570927, 1864647396, 900688508, 1835551150, 71395285, 1425899737, 2287259914, 962161837, 2938663406, 2857261272, 1146595809, 3764487743, 3300056528, 3137301789, 250445987, 1997329543, 192312160, 3417776853, 3623584574, 2403647678, 3849791382, 3065151486, 2112108309, 2184865682, 2147711161, 3337243558, 2646696137, 3744234210, 3469704297, 804280152, 2812030004, 283967646, 1530700123, 2959520978, 133999661, 1311943460, 2409420442, 1378063817, 1306691126, 2795816917, 175853898, 3436153597, 4094879999, 4061387058, 3142348235, 3450122749, 997635528, 2383423341, 946776870, 1390313886, 4272495253, 1329111605, 1783381058, 1235280956, 878145167, 1050060880, 4215806346, 986268144, 2398596766, 1847782969, 2662963332, 320753973, 961489657, 643166461, 3665561600, 903526756, 861869280, 1582519883, 1724972430, 3647434888, 922278554, 1608919692, 3498480811, 606385525, 1264439673, 1258996822, 3155308373, 1047873974, 2173644429, 1417008977, 935021011, 722697374, 3318510778, 638992840, 1692733318, 1533146701, 2599254955, 3256732986, 11478574, 3245879834, 3651129160, 890914331, 1936401914, 4269069338, 652796490, 1855438614, 3711917465, 2231167869, 965528216, 4083742438, 3888862032, 4027832595, 3194731005, 3855267812, 1331497794, 1036129210, 2454849236, 3936763814, 2166230922, 2221233340, 3494633119, 2135677604, 1957161469, 3441858755, 3165789630, 3502273733, 3935502624, 935473926, 951630970, 3241427305, 3626833422, 3344353486, 384196385, 2893969144, 371257580, 1895300995, 1538534547, 4247925735, 3906194642, 3278920998, 190467029, 660834078, 3047471694, 3139110501, 2945327231, 2791821139, 3787430397, 11897902, 3071804998, 2906353083, 3986347125, 728226352, 1721418756, 3790033644, 2543845828, 4201817595, 1241190909, 2172638407, 3176874190, 212681671, 2217059787, 2568436099, 4160058240, 1550824349, 1589798596, 2384281069, 4106120578, 1772814852, 2711184704, 1753902606, 3147375646, 3197706153, 4069187110, 2497336677, 682542752, 3631288002, 1821492432, 4111201809, 3496083848, 488832033, 1487521654, 1028323258, 2626975117, 3820273648, 4203958355, 1957204165, 692251647, 751713885, 2869803205, 699099042, 287040513, 1256261134, 1435317843, 2516495821, 2172617698, 2350001365, 3127743304, 4210222956, 2394254147, 1395276753, 2466938438, 1054538356, 145981627, 152373092, 2285902580, 534742531, 2919481209, 1870713895, 800843175, 3498230341, 29966677, 1374519390, 1746138239, 90290568, 2136928464, 1012080534, 4220785618, 2331149605, 3177894074, 4194250977, 1793677512, 1812254290, 755277024, 1050843937, 1441079766, 4177809358, 2569374720, 2516736232, 1486921399, 666656868, 1100619139, 2587149122, 2221024508, 2951375366, 2349454937, 4266896936, 4091705443, 4244036995, 3327195836, 2611529411, 538404573, 3970374943, 3102287318, 1164998997, 521166464, 3125925988, 360672675, 3568959356, 1328059403, 2778221822, 347086039, 3797350591, 3600929164, 849738110, 3879666101, 2751748132, 3317854867, 2059575942, 3146620321, 1367551383, 2518113922, 2136751883, 4171468116, 4267631229, 3031791643, 2334887552, 2773212213, 480854415, 482867572, 8189, ], 1, ); // - nn == 0 third time in limbs_half_gcd_jacobi test( &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967280, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 4294967288, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 8388607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190080, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16383, 0, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 134217727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294965248, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4290772992, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 262143, 0, 0, 4292870144, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 524287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967294, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190080, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 16777215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967292, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967168, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], 0, ); // - bits != BITS_FAIL first time test( &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], &[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ], 1, ); } } #[test] fn test_legendre_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Natural::from_str(u).unwrap(); let n = Natural::from_str(v).unwrap(); assert_eq!(a.clone().legendre_symbol(n.clone()), s); assert_eq!(a.clone().legendre_symbol(&n), s); assert_eq!((&a).legendre_symbol(n.clone()), s); assert_eq!((&a).legendre_symbol(&n), s); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!((&a).jacobi_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!(jacobi_symbol_simple(a, n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .legendre(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "3", 0); test("1", "3", 1); test("2", "3", -1); test("0", "5", 0); test("1", "5", 1); test("2", "5", -1); test("3", "5", -1); test("4", "5", 1); test("0", "7", 0); test("1", "7", 1); test("2", "7", 1); test("3", "7", -1); test("4", "7", 1); test("5", "7", -1); test("6", "7", -1); test("7", "7", 0); test("8", "7", 1); test("9", "7", 1); test("10", "7", -1); test("11", "7", 1); test("12", "7", -1); test("13", "7", -1); test("1001", "9907", -1); test("10908", "9907", -1); } #[test] fn legendre_symbol_fail() { assert_panic!(Natural::ONE.legendre_symbol(Natural::TWO)); assert_panic!(Natural::ONE.legendre_symbol(&Natural::TWO)); assert_panic!((&Natural::ONE).legendre_symbol(Natural::TWO)); assert_panic!((&Natural::ONE).legendre_symbol(&Natural::TWO)); } #[test] fn test_jacobi_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Natural::from_str(u).unwrap(); let n = Natural::from_str(v).unwrap(); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!((&a).jacobi_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!(jacobi_symbol_simple(a, n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .jacobi(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "1", 1); test("0", "9", 0); test("1", "9", 1); test("2", "9", 1); test("3", "9", 0); test("4", "9", 1); test("5", "9", 1); test("6", "9", 0); test("7", "9", 1); test("8", "9", 1); test("9", "9", 0); test("10", "9", 1); test("11", "9", 1); test("12", "9", 0); test("13", "9", 1); test("14", "9", 1); test("15", "9", 0); test("16", "9", 1); test("17", "9", 1); } #[test] fn jacobi_symbol_fail() { assert_panic!(Natural::ONE.jacobi_symbol(Natural::TWO)); assert_panic!(Natural::ONE.jacobi_symbol(&Natural::TWO)); assert_panic!((&Natural::ONE).jacobi_symbol(Natural::TWO)); assert_panic!((&Natural::ONE).jacobi_symbol(&Natural::TWO)); } // Odd n is already tested in test_jacobi_symbol, so here we just test even n #[test] fn test_kronecker_symbol() { fn test(u: &str, v: &str, s: i8) { let a = Natural::from_str(u).unwrap(); let n = Natural::from_str(v).unwrap(); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!( rug::Integer::from_str(u) .unwrap() .kronecker(&rug::Integer::from_str(v).unwrap()), i32::from(s) ); } test("0", "2", 0); test("1", "2", 1); test("2", "2", 0); test("3", "2", -1); test("4", "2", 0); test("5", "2", -1); test("6", "2", 0); test("7", "2", 1); test("0", "4", 0); test("1", "4", 1); test("2", "4", 0); test("3", "4", 1); test("0", "6", 0); test("1", "6", 1); test("2", "6", 0); test("3", "6", 0); test("4", "6", 0); test("5", "6", 1); test("6", "6", 0); test("7", "6", 1); test("8", "6", 0); test("9", "6", 0); test("10", "6", 0); test("11", "6", 1); test("12", "6", 0); test("13", "6", -1); test("14", "6", 0); test("15", "6", 0); test("16", "6", 0); test("17", "6", -1); test("18", "6", 0); test("19", "6", -1); test("20", "6", 0); test("21", "6", 0); test("22", "6", 0); test("23", "6", -1); test("1001", "9908", -1); test("10909", "9908", -1); } #[test] fn limbs_jacobi_symbol_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 256); config.insert("mean_stripe_n", 32 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_32().test_properties_with_config(&config, |(mut xs, mut ys)| { let x = Natural::from_limbs_asc(&xs); let y = Natural::from_limbs_asc(&ys); let s = (&x).jacobi_symbol(&y); assert_eq!(jacobi_symbol_simple(x, y), s); let bits = limbs_jacobi_symbol_init(xs[0], ys[0], 0); assert_eq!(limbs_jacobi_symbol_same_length(&mut xs, &mut ys, bits), s); }); } #[test] fn jacobi_symbol_properties() { natural_pair_gen_var_12().test_properties(|(a, n)| { let s = (&a).jacobi_symbol(&n); assert_eq!((&a).jacobi_symbol(n.clone()), s); assert_eq!(a.clone().jacobi_symbol(&n), s); assert_eq!(a.clone().jacobi_symbol(n.clone()), s); // Legendre should only be called on prime n, but it still works for non-prime odd n and we // can't currently test primality anyway. assert_eq!((&a).legendre_symbol(&n), s); assert_eq!((&a).legendre_symbol(n.clone()), s); assert_eq!(a.clone().legendre_symbol(&n), s); assert_eq!(a.clone().legendre_symbol(n.clone()), s); assert_eq!((&a).kronecker_symbol(&n), s); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!(jacobi_symbol_simple(a.clone(), n.clone()), s); assert_eq!( rug::Integer::from(&a).jacobi(&rug::Integer::from(&n)), i32::from(s) ); assert!(s.le_abs(&1i8)); assert_eq!((&a + &n).jacobi_symbol(&n), s); if a >= n { assert_eq!((&a - &n).jacobi_symbol(&n), s); } assert_eq!(s != 0, (&a).coprime_with(&n)); let n_mod_8: u8 = (&(&n).mod_power_of_2(3)).wrapping_into(); assert_eq!( (a << 1u32).jacobi_symbol(n), if n_mod_8 == 1 || n_mod_8 == 7 { s } else { -s } ); }); natural_pair_gen_var_13().test_properties(|(m, n)| { let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); let m_mod_4: u8 = (&(&m).mod_power_of_2(2)).wrapping_into(); assert_eq!( (&m).jacobi_symbol(&n) * n.jacobi_symbol(m), if n_mod_4 == 1 || m_mod_4 == 1 { 1 } else { -1 } ); }); natural_triple_gen_var_8().test_properties(|(a, b, n)| { assert_eq!( (&a * &b).jacobi_symbol(&n), a.jacobi_symbol(&n) * b.jacobi_symbol(n) ); }); natural_triple_gen_var_9().test_properties(|(a, m, n)| { assert_eq!( (&a).jacobi_symbol(&m * &n), (&a).jacobi_symbol(m) * a.jacobi_symbol(n) ); }); natural_gen_var_8().test_properties(|n| { if n != 1u32 { assert_eq!(Natural::ZERO.jacobi_symbol(&n), 0); assert_eq!((&n).jacobi_symbol(&n), 0); } assert_eq!(Natural::ONE.jacobi_symbol(&n), 1); assert_eq!((&n).jacobi_symbol(Natural::ONE), 1); let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); assert_eq!( (&n - Natural::ONE).jacobi_symbol(&n), if n_mod_4 == 1 { 1 } else { -1 } ); let n_mod_8: u8 = (&(&n).mod_power_of_2(3)).wrapping_into(); assert_eq!( Natural::TWO.jacobi_symbol(&n), if n_mod_8 == 1 || n_mod_8 == 7 { 1 } else { -1 } ); }); unsigned_pair_gen_var_40::().test_properties(|(x, y)| { assert_eq!( Natural::from(x).jacobi_symbol(Natural::from(y)), x.jacobi_symbol(y) ); }); } fn kronecker_symbol_properties_helper(a: Natural, n: Natural) { let s = (&a).kronecker_symbol(&n); assert_eq!((&a).kronecker_symbol(n.clone()), s); assert_eq!(a.clone().kronecker_symbol(&n), s); assert_eq!(a.clone().kronecker_symbol(n.clone()), s); assert_eq!( rug::Integer::from(&a).kronecker(&rug::Integer::from(&n)), i32::from(s) ); assert!(s.le_abs(&1i8)); assert_eq!(s != 0, (&a).coprime_with(&n)); let n_mod_4: u8 = (&(&n).mod_power_of_2(2)).wrapping_into(); if n_mod_4 == 2 { let four_n = &n << 2u32; assert_eq!((&a + &four_n).kronecker_symbol(&n), s); if a >= four_n { assert_eq!((&a - four_n).kronecker_symbol(&n), s); } } else { assert_eq!((&a + &n).kronecker_symbol(&n), s); if a >= n { assert_eq!((&a - &n).kronecker_symbol(&n), s); } } let a_mod_4: u8 = (&(&a).mod_power_of_2(2)).wrapping_into(); if a != 0u32 && a_mod_4 != 3 { if a_mod_4 == 2 { let four_a = &a << 2u32; assert_eq!((&a).kronecker_symbol(&n + &four_a), s); if n >= four_a { assert_eq!((&a).kronecker_symbol(&n - four_a), s); } } else { assert_eq!((&a).kronecker_symbol(&n + &a), s); if n >= a { let diff = n - &a; assert_eq!((a).kronecker_symbol(diff), s); } } } } #[test] fn kronecker_symbol_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 512 << Limb::LOG_WIDTH); natural_pair_gen().test_properties_with_config(&config, |(x, y)| { kronecker_symbol_properties_helper(x, y); }); natural_pair_gen_var_4().test_properties_with_config(&config, |(x, y)| { kronecker_symbol_properties_helper(x, y); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!( (&x * &y).kronecker_symbol(&z), (&x).kronecker_symbol(&z) * (&y).kronecker_symbol(&z) ); assert_eq!( (&x).kronecker_symbol(&y * &z), (&x).kronecker_symbol(y) * x.kronecker_symbol(z) ); }); natural_pair_gen_var_14().test_properties(|(m, n)| { let n_odd = if n == 0u32 { Natural::ONE } else { &n >> n.trailing_zeros().unwrap() }; let m_odd = if m == 0u32 { Natural::ONE } else { &m >> m.trailing_zeros().unwrap() }; let n_odd_mod_4: u8 = (&n_odd.mod_power_of_2(2)).wrapping_into(); let m_odd_mod_4: u8 = (&m_odd.mod_power_of_2(2)).wrapping_into(); let p = if n_odd_mod_4 == 1 || m_odd_mod_4 == 1 { 1 } else { -1 }; assert_eq!((&m).kronecker_symbol(&n) * n.kronecker_symbol(m), p); }); natural_gen().test_properties(|n| { if n != 1u32 { assert_eq!(Natural::ZERO.kronecker_symbol(&n), 0); assert_eq!((&n).kronecker_symbol(&n), 0); } assert_eq!(Natural::ONE.kronecker_symbol(&n), 1); assert_eq!(n.kronecker_symbol(Natural::ONE), 1); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( Natural::from(x).kronecker_symbol(Natural::from(y)), x.kronecker_symbol(y) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/lcm.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivExact, DivisibleBy, Gcd, Lcm, LcmAssign}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::unsigned_pair_gen_var_34; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use num::BigUint; use num::Integer as rug_integer; use std::str::FromStr; #[test] fn test_lcm() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.lcm_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.lcm_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().lcm(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).lcm(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().lcm(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).lcm(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigUint::from_str(s) .unwrap() .lcm(&BigUint::from_str(t).unwrap()); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s) .unwrap() .lcm(&rug::Integer::from_str(t).unwrap()); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "6", "0"); test("6", "0", "0"); test("1", "6", "6"); test("6", "1", "6"); test("8", "12", "24"); test("54", "24", "216"); test("42", "56", "168"); test("48", "18", "144"); test("3", "5", "15"); test("12", "60", "60"); test("12", "90", "180"); test( "12345678987654321", "98765432123456789", "1219326320073159566072245112635269", ); test( "12345678987654321", "98765432123456827", "32954765407382703654271530905391", ); } #[test] fn lcm_properties() { natural_pair_gen().test_properties(|(x, y)| { let lcm_val_val = x.clone().lcm(y.clone()); let lcm_val_ref = x.clone().lcm(&y); let lcm_ref_val = (&x).lcm(y.clone()); let lcm = (&x).lcm(&y); assert!(lcm_val_val.is_valid()); assert!(lcm_val_ref.is_valid()); assert!(lcm_ref_val.is_valid()); assert!(lcm.is_valid()); assert_eq!(lcm_val_val, lcm); assert_eq!(lcm_val_ref, lcm); assert_eq!(lcm_ref_val, lcm); let mut mut_x = x.clone(); mut_x.lcm_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, lcm); let mut mut_x = x.clone(); mut_x.lcm_assign(&y); assert_eq!(mut_x, lcm); assert!(mut_x.is_valid()); assert_eq!( Natural::from(&(BigUint::from(&x).lcm(&BigUint::from(&y)))), lcm ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x).lcm(&rug::Integer::from(&y)))), lcm ); assert_eq!((&y).lcm(&x), lcm); assert!((&lcm).divisible_by(&x)); assert!((&lcm).divisible_by(&y)); let gcd = (&x).gcd(&y); if x != 0 { assert_eq!((&lcm).div_exact(&x) * &gcd, y); } if y != 0 { assert_eq!((&lcm).div_exact(&y) * &gcd, x); } if gcd != 0 { assert_eq!(x.div_exact(gcd) * y, lcm); } }); natural_gen().test_properties(|x| { assert_eq!((&x).lcm(&x), x); assert_eq!((&x).lcm(Natural::ONE), x); assert_eq!(x.lcm(Natural::ZERO), 0); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x).lcm(&y).lcm(&z), x.lcm(y.lcm(z))); }); unsigned_pair_gen_var_34::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).lcm(Natural::from(y)), x.lcm(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBase2, CheckedLogBase, CheckedLogBase2, DivExact, FloorLogBase, FloorLogBase2, Pow, }; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::generators::unsigned_pair_gen_var_24; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen_var_1, natural_gen_var_2, natural_pair_gen_var_3, }; use malachite_nz::test_util::natural::arithmetic::log_base::{ ceiling_log_base_by_squaring, ceiling_log_base_naive, checked_log_base_by_squaring, checked_log_base_naive, floor_log_base_by_squaring, floor_log_base_naive, }; use std::str::FromStr; #[test] fn test_approx_ln() { let test = |s, out| { assert_eq!( NiceFloat(Natural::from_str(s).unwrap().approx_ln()), NiceFloat(out) ); }; test("1", 0.0); test("2", std::f64::consts::LN_2); test("3", 1.0986122886681096); test("10", 2.3025850929940455); test("100", 4.605170185988091); test("1000", 6.907755278982137); test( "1000000000000000000000000000000000000000000000000000000000000", 138.15510557964274, ); } #[test] #[should_panic] fn approx_ln_fail() { Natural::ZERO.approx_ln(); } #[test] fn test_floor_log_base() { let test = |n, base, out| { assert_eq!( Natural::from_str(n) .unwrap() .floor_log_base(&Natural::from_str(base).unwrap()), out ); }; test("1", "2", 0); test("1", "5", 0); test("2", "2", 1); test("2", "3", 0); test("3", "2", 1); test("3", "3", 1); test("3", "4", 0); test("100", "2", 6); test("100", "3", 4); test("100", "4", 3); test("100", "5", 2); test("100", "10", 2); test("100", "11", 1); test( "999999999999999999999999999999999999999999999999999999999999", "10", 59, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", 60, ); } #[test] #[should_panic] fn floor_log_base_fail_1() { Natural::ZERO.floor_log_base(&Natural::TWO); } #[test] #[should_panic] fn floor_log_base_fail_2() { Natural::ONE.floor_log_base(&Natural::ZERO); } #[test] #[should_panic] fn floor_log_base_fail_3() { Natural::ONE.floor_log_base(&Natural::ONE); } #[test] fn test_ceiling_log_base() { let test = |n, base, out| { assert_eq!( Natural::from_str(n) .unwrap() .ceiling_log_base(&Natural::from_str(base).unwrap()), out ); }; test("1", "2", 0); test("1", "5", 0); test("2", "2", 1); test("2", "3", 1); test("3", "2", 2); test("3", "3", 1); test("3", "4", 1); test("100", "2", 7); test("100", "3", 5); test("100", "4", 4); test("100", "5", 3); test("100", "10", 2); test("100", "11", 2); test( "999999999999999999999999999999999999999999999999999999999999", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", 61, ); } #[test] #[should_panic] fn ceiling_log_base_fail_1() { Natural::ZERO.ceiling_log_base(&Natural::TWO); } #[test] #[should_panic] fn ceiling_log_base_fail_2() { Natural::ONE.ceiling_log_base(&Natural::ZERO); } #[test] #[should_panic] fn ceiling_log_base_fail_3() { Natural::ONE.ceiling_log_base(&Natural::ONE); } #[test] fn test_checked_log_base() { let test = |n, base, out| { assert_eq!( Natural::from_str(n) .unwrap() .checked_log_base(&Natural::from_str(base).unwrap()), out ); }; test("1", "2", Some(0)); test("1", "5", Some(0)); test("2", "2", Some(1)); test("2", "3", None); test("3", "2", None); test("3", "3", Some(1)); test("3", "4", None); test("100", "2", None); test("100", "3", None); test("100", "4", None); test("100", "5", None); test("100", "10", Some(2)); test("100", "11", None); test( "999999999999999999999999999999999999999999999999999999999999", "10", None, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", Some(60), ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", None, ); } #[test] #[should_panic] fn checked_log_base_fail_1() { Natural::ZERO.checked_log_base(&Natural::TWO); } #[test] #[should_panic] fn checked_log_base_fail_2() { Natural::ONE.checked_log_base(&Natural::ZERO); } #[test] #[should_panic] fn checked_log_base_fail_3() { Natural::ONE.checked_log_base(&Natural::ONE); } #[test] fn approx_ln_properties() { natural_gen_var_2().test_properties(|n| { let log = n.approx_ln(); assert!(log.is_sign_positive()); assert!(log.is_finite()); assert!(!log.is_nan()); }); } #[test] fn floor_log_base_properties() { natural_pair_gen_var_3().test_properties(|(n, base)| { let floor_log = n.floor_log_base(&base); assert_eq!(floor_log_base_naive(&n, &base), floor_log); assert_eq!(floor_log_base_by_squaring(&n, &base), floor_log); assert_eq!(floor_log == 0, n < base); let power = (&base).pow(floor_log); assert!(power <= n); assert!(&power * &base > n); let ceiling_log = n.ceiling_log_base(&base); if power == n { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.floor_log_base(&Natural::TWO), n.floor_log_base_2()); }); natural_gen_var_1().test_properties(|base| { assert_eq!(Natural::ONE.floor_log_base(&base), 0); }); unsigned_pair_gen_var_24::().test_properties(|(n, base)| { assert_eq!( n.floor_log_base(base), Natural::from(n).floor_log_base(&Natural::from(base)) ); }); } #[test] fn ceiling_log_base_properties() { natural_pair_gen_var_3().test_properties(|(n, base)| { let ceiling_log = n.ceiling_log_base(&base); assert_eq!(ceiling_log_base_naive(&n, &base), ceiling_log); assert_eq!(ceiling_log_base_by_squaring(&n, &base), ceiling_log); assert_eq!(ceiling_log == 0, n == Natural::ONE); let power = (&base).pow(ceiling_log); assert!(power >= n); if power != 1 { assert!((&power).div_exact(&base) < n); } let floor_log = n.floor_log_base(&base); if power == n { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.ceiling_log_base(&Natural::TWO), n.ceiling_log_base_2()); }); natural_gen_var_1().test_properties(|base| { assert_eq!(Natural::ONE.ceiling_log_base(&base), 0); }); unsigned_pair_gen_var_24::().test_properties(|(n, base)| { assert_eq!( n.ceiling_log_base(base), Natural::from(n).ceiling_log_base(&Natural::from(base)) ); }); } #[test] fn checked_log_base_properties() { natural_pair_gen_var_3().test_properties(|(n, base)| { let checked_log = n.checked_log_base(&base); assert_eq!(checked_log_base_naive(&n, &base), checked_log); assert_eq!(checked_log_base_by_squaring(&n, &base), checked_log); if let Some(log) = checked_log { assert_eq!((&base).pow(log), n); assert_eq!(log == 0, n == Natural::ONE); assert_eq!(n.floor_log_base(&base), log); assert_eq!(n.ceiling_log_base(&base), log); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.checked_log_base(&Natural::TWO), n.checked_log_base_2()); }); natural_gen_var_1().test_properties(|base| { assert_eq!(Natural::ONE.checked_log_base(&base), Some(0)); }); unsigned_pair_gen_var_24::().test_properties(|(n, base)| { assert_eq!( n.checked_log_base(base), Natural::from(n).checked_log_base(&Natural::from(base)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase2, CheckedLogBase2, FloorLogBase2, IsPowerOf2, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen_var_1, unsigned_vec_gen_var_1}; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::log_base_2::{ limbs_ceiling_log_base_2, limbs_checked_log_base_2, limbs_floor_log_base_2, }; use malachite_nz::natural::logic::significant_bits::limbs_significant_bits; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen_var_2; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_floor_log_base_2() { let test = |xs, out| { assert_eq!(limbs_floor_log_base_2(xs), out); }; test(&[0b1], 0); test(&[0b10], 1); test(&[0b11], 1); test(&[0b100], 2); test(&[0, 0b1], 32); test(&[0, 0b1101], 35); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_floor_log_base_2_fail() { limbs_floor_log_base_2(&[]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_ceiling_log_base_2() { let test = |xs, out| { assert_eq!(limbs_ceiling_log_base_2(xs), out); }; test(&[0b1], 0); test(&[0b10], 1); test(&[0b11], 2); test(&[0b100], 2); test(&[0, 0b1], 32); test(&[0, 0b1101], 36); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_ceiling_log_base_2_fail() { limbs_ceiling_log_base_2(&[]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_checked_log_base_2() { let test = |xs, out| { assert_eq!(limbs_checked_log_base_2(xs), out); }; test(&[0b1], Some(0)); test(&[0b10], Some(1)); test(&[0b11], None); test(&[0b100], Some(2)); test(&[0, 0b1], Some(32)); test(&[0, 0b1101], None); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_checked_log_base_2_fail() { limbs_checked_log_base_2(&[]); } #[test] fn limbs_floor_log_base_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let floor_log_base_2 = limbs_floor_log_base_2(&xs); assert_eq!(xs.len() == 1, floor_log_base_2 < Limb::WIDTH); assert_eq!(floor_log_base_2, limbs_significant_bits(&xs) - 1); assert_eq!( floor_log_base_2, Natural::from_limbs_asc(&xs).floor_log_base_2() ); }); } #[test] fn limbs_ceiling_log_base_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let ceiling_log_base_2 = limbs_ceiling_log_base_2(&xs); assert_eq!( xs.len() == 1 || xs == [0, 1], ceiling_log_base_2 <= Limb::WIDTH ); assert_eq!( ceiling_log_base_2, Natural::from_limbs_asc(&xs).ceiling_log_base_2() ); }); } #[test] fn limbs_checked_log_base_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let checked_log_base_2 = limbs_checked_log_base_2(&xs); assert_eq!( checked_log_base_2, Natural::from_limbs_asc(&xs).checked_log_base_2() ); }); } #[test] fn test_floor_log_base_2() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().floor_log_base_2(), out); }; test("1", 0); test("100", 6); test("1000000000000", 39); test("4294967295", 31); test("4294967296", 32); test("18446744073709551615", 63); test("18446744073709551616", 64); } #[test] #[should_panic] fn floor_log_base_2_fail() { Natural::ZERO.floor_log_base_2(); } #[test] fn test_ceiling_log_base_2() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().ceiling_log_base_2(), out); }; test("1", 0); test("100", 7); test("1000000000000", 40); test("4294967295", 32); test("4294967296", 32); test("4294967297", 33); test("18446744073709551615", 64); test("18446744073709551616", 64); test("18446744073709551617", 65); } #[test] #[should_panic] fn ceiling_log_base_2_fail() { Natural::ZERO.ceiling_log_base_2(); } #[test] fn test_checked_log_base_2() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().checked_log_base_2(), out); }; test("1", Some(0)); test("100", None); test("1000000000000", None); test("4294967295", None); test("4294967296", Some(32)); test("4294967297", None); test("18446744073709551615", None); test("18446744073709551616", Some(64)); test("18446744073709551617", None); } #[test] #[should_panic] fn checked_log_base_2_fail() { Natural::ZERO.checked_log_base_2(); } #[test] fn floor_log_base_2_properties() { natural_gen_var_2().test_properties(|x| { let floor_log_base_2 = x.floor_log_base_2(); assert_eq!(x <= Limb::MAX, floor_log_base_2 < Limb::WIDTH); assert_eq!(floor_log_base_2, x.significant_bits() - 1); assert_eq!(floor_log_base_2, limbs_floor_log_base_2(x.as_limbs_asc())); assert!(Natural::power_of_2(floor_log_base_2) <= x); assert!(x < Natural::power_of_2(floor_log_base_2 + 1)); }); unsigned_gen_var_1::().test_properties(|u| { assert_eq!(u.floor_log_base_2(), Natural::from(u).floor_log_base_2()); }); } #[test] fn ceiling_log_base_2_properties() { natural_gen_var_2().test_properties(|x| { let ceiling_log_base_2 = x.ceiling_log_base_2(); assert_eq!( x <= Natural::power_of_2(Limb::WIDTH), ceiling_log_base_2 <= Limb::WIDTH ); assert_eq!( ceiling_log_base_2, limbs_ceiling_log_base_2(x.as_limbs_asc()) ); if ceiling_log_base_2 != 0 { assert!(Natural::power_of_2(ceiling_log_base_2 - 1) < x); } assert!(x <= Natural::power_of_2(ceiling_log_base_2)); }); unsigned_gen_var_1::().test_properties(|u| { assert_eq!( u.ceiling_log_base_2(), Natural::from(u).ceiling_log_base_2() ); }); } #[test] fn checked_log_base_2_properties() { natural_gen_var_2().test_properties(|x| { let checked_log_base_2 = x.checked_log_base_2(); assert_eq!( checked_log_base_2, limbs_checked_log_base_2(x.as_limbs_asc()) ); assert_eq!(checked_log_base_2.is_some(), x.is_power_of_2()); if let Some(log_base_2) = checked_log_base_2 { assert_eq!(x.floor_log_base_2(), log_base_2); assert_eq!(x.ceiling_log_base_2(), log_base_2); assert_eq!(x <= Limb::MAX, log_base_2 < Limb::WIDTH); assert_eq!(log_base_2, x.significant_bits() - 1); assert_eq!(Natural::power_of_2(log_base_2), x); } }); unsigned_gen_var_1::().test_properties(|u| { assert_eq!( u.checked_log_base_2(), Natural::from(u).checked_log_base_2() ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBase2, CeilingLogBasePowerOf2, CheckedLogBase, CheckedLogBase2, CheckedLogBasePowerOf2, DivisibleBy, FloorLogBase, FloorLogBase2, FloorLogBasePowerOf2, IsPowerOf2, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_11, unsigned_pair_gen_var_21, unsigned_vec_unsigned_pair_gen_var_13, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::log_base_power_of_2::{ limbs_ceiling_log_base_power_of_2, limbs_checked_log_base_power_of_2, limbs_floor_log_base_power_of_2, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen_var_2, natural_unsigned_pair_gen_var_8}; use malachite_nz::test_util::natural::arithmetic::log_base_power_of_2::*; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_floor_log_base_power_of_2() { let test = |xs: &[Limb], pow, out| { assert_eq!(limbs_floor_log_base_power_of_2(xs, pow), out); }; test(&[0b1], 1, 0); test(&[0b1], 5, 0); test(&[0b10], 1, 1); test(&[0b10], 2, 0); test(&[0b10], 5, 0); test(&[0b11], 1, 1); test(&[0b11], 2, 0); test(&[0b11], 5, 0); test(&[0b100], 1, 2); test(&[0b100], 2, 1); test(&[0b100], 5, 0); test(&[0, 0b1], 1, 32); test(&[0, 0b1], 2, 16); test(&[0, 0b1], 3, 10); test(&[0, 0b1], 4, 8); test(&[0, 0b1], 32, 1); test(&[0, 0b1], 33, 0); test(&[0, 0b1101], 1, 35); test(&[0, 0b1101], 2, 17); test(&[0, 0b1101], 5, 7); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_floor_log_base_power_of_2_fail() { limbs_floor_log_base_power_of_2(&[1], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_ceiling_log_base_power_of_2() { let test = |xs: &[Limb], pow, out| { assert_eq!(limbs_ceiling_log_base_power_of_2(xs, pow), out); }; test(&[0b1], 1, 0); test(&[0b1], 5, 0); test(&[0b10], 1, 1); test(&[0b10], 2, 1); test(&[0b10], 5, 1); test(&[0b11], 1, 2); test(&[0b11], 2, 1); test(&[0b11], 5, 1); test(&[0b100], 1, 2); test(&[0b100], 2, 1); test(&[0b100], 5, 1); test(&[0, 0b1], 1, 32); test(&[0, 0b1], 2, 16); test(&[0, 0b1], 3, 11); test(&[0, 0b1], 4, 8); test(&[0, 0b1], 32, 1); test(&[0, 0b1], 33, 1); test(&[0, 0b1101], 1, 36); test(&[0, 0b1101], 2, 18); test(&[0, 0b1101], 5, 8); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_ceiling_log_base_power_of_2_fail() { limbs_ceiling_log_base_power_of_2(&[1], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_checked_log_base_power_of_2() { let test = |xs: &[Limb], pow, out| { assert_eq!(limbs_checked_log_base_power_of_2(xs, pow), out); }; test(&[0b1], 1, Some(0)); test(&[0b1], 5, Some(0)); test(&[0b10], 1, Some(1)); test(&[0b10], 2, None); test(&[0b10], 5, None); test(&[0b11], 1, None); test(&[0b11], 2, None); test(&[0b11], 5, None); test(&[0b100], 1, Some(2)); test(&[0b100], 2, Some(1)); test(&[0b100], 5, None); test(&[0, 0b1], 1, Some(32)); test(&[0, 0b1], 2, Some(16)); test(&[0, 0b1], 3, None); test(&[0, 0b1], 4, Some(8)); test(&[0, 0b1], 32, Some(1)); test(&[0, 0b1], 33, None); test(&[0, 0b1101], 1, None); test(&[0, 0b1101], 2, None); test(&[0, 0b1101], 5, None); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_checked_log_base_power_of_2_fail() { limbs_checked_log_base_power_of_2(&[1], 0); } #[test] fn test_floor_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Natural::from_str(n).unwrap().floor_log_base_power_of_2(pow), out ); }; test("1", 1, 0); test("1", 2, 0); test("1", 5, 0); test("100", 1, 6); test("100", 2, 3); test("100", 5, 1); test("1000000000000", 1, 39); test("1000000000000", 2, 19); test("1000000000000", 5, 7); test("4294967295", 1, 31); test("4294967295", 2, 15); test("4294967295", 5, 6); test("4294967296", 1, 32); test("4294967296", 2, 16); test("4294967296", 8, 4); test("4294967296", 5, 6); test("18446744073709551615", 1, 63); test("18446744073709551615", 2, 31); test("18446744073709551615", 5, 12); test("18446744073709551616", 1, 64); test("18446744073709551616", 2, 32); test("18446744073709551616", 8, 8); test("18446744073709551616", 20, 3); } #[test] #[should_panic] fn floor_log_base_power_of_2_fail_1() { Natural::ZERO.floor_log_base_power_of_2(1); } #[test] #[should_panic] fn floor_log_base_power_of_2_fail_2() { Natural::ONE.floor_log_base_power_of_2(0); } #[test] fn test_ceiling_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Natural::from_str(n) .unwrap() .ceiling_log_base_power_of_2(pow), out ); }; test("1", 1, 0); test("1", 2, 0); test("1", 5, 0); test("100", 1, 7); test("100", 2, 4); test("100", 5, 2); test("1000000000000", 1, 40); test("1000000000000", 2, 20); test("1000000000000", 5, 8); test("4294967295", 1, 32); test("4294967295", 2, 16); test("4294967295", 5, 7); test("4294967296", 1, 32); test("4294967296", 2, 16); test("4294967296", 8, 4); test("4294967296", 5, 7); test("18446744073709551615", 1, 64); test("18446744073709551615", 2, 32); test("18446744073709551615", 5, 13); test("18446744073709551616", 1, 64); test("18446744073709551616", 2, 32); test("18446744073709551616", 8, 8); test("18446744073709551616", 20, 4); } #[test] #[should_panic] fn ceiling_log_base_power_of_2_fail_1() { Natural::ZERO.ceiling_log_base_power_of_2(1); } #[test] #[should_panic] fn ceiling_log_base_power_of_2_fail_2() { Natural::ONE.ceiling_log_base_power_of_2(0); } #[test] fn test_checked_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Natural::from_str(n) .unwrap() .checked_log_base_power_of_2(pow), out ); }; test("1", 1, Some(0)); test("1", 2, Some(0)); test("1", 5, Some(0)); test("100", 1, None); test("100", 2, None); test("100", 5, None); test("1000000000000", 1, None); test("1000000000000", 2, None); test("1000000000000", 5, None); test("4294967295", 1, None); test("4294967295", 2, None); test("4294967295", 5, None); test("4294967296", 1, Some(32)); test("4294967296", 2, Some(16)); test("4294967296", 8, Some(4)); test("4294967296", 5, None); test("18446744073709551615", 1, None); test("18446744073709551615", 2, None); test("18446744073709551615", 5, None); test("18446744073709551616", 1, Some(64)); test("18446744073709551616", 2, Some(32)); test("18446744073709551616", 8, Some(8)); test("18446744073709551616", 20, None); } #[test] #[should_panic] fn checked_log_base_power_of_2_fail_1() { Natural::ZERO.checked_log_base_power_of_2(1); } #[test] #[should_panic] fn checked_log_base_power_of_2_fail_2() { Natural::ONE.checked_log_base_power_of_2(0); } #[test] fn limbs_floor_log_base_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_13().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( limbs_floor_log_base_power_of_2(&xs, pow), Natural::from_limbs_asc(&xs).floor_log_base_power_of_2(pow), ); }); } #[test] fn limbs_ceiling_log_base_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_13().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( limbs_ceiling_log_base_power_of_2(&xs, pow), Natural::from_limbs_asc(&xs).ceiling_log_base_power_of_2(pow) ); }); } #[test] fn limbs_checked_log_base_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_13().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( limbs_checked_log_base_power_of_2(&xs, pow), Natural::from_limbs_asc(&xs).checked_log_base_power_of_2(pow) ); }); } #[test] fn floor_log_base_power_of_2_properties() { natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { let floor_log = n.floor_log_base_power_of_2(pow); assert_eq!(floor_log == 0, n.significant_bits() - 1 < pow); assert_eq!(n.floor_log_base(&Natural::power_of_2(pow)), floor_log); let product = floor_log * pow; assert!(Natural::power_of_2(product) <= n); assert!(Natural::power_of_2(product + pow) > n); let ceiling_log = n.ceiling_log_base_power_of_2(pow); if n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.floor_log_base_power_of_2(1), n.floor_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(Natural::ONE.floor_log_base_power_of_2(pow), 0); }); unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { assert_eq!( n.floor_log_base_power_of_2(pow), Natural::from(n).floor_log_base_power_of_2(pow) ); }); } #[test] fn ceiling_log_base_power_of_2_properties() { natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { let ceiling_log = n.ceiling_log_base_power_of_2(pow); assert_eq!(ceiling_log, ceiling_log_base_power_of_2_naive_nz(&n, pow)); assert_eq!(ceiling_log == 0, n == Natural::ONE); assert_eq!(n.ceiling_log_base(&Natural::power_of_2(pow)), ceiling_log); let product = ceiling_log * pow; assert!(Natural::power_of_2(product) >= n); if product != 0 { assert!(Natural::power_of_2(product - pow) < n); } let floor_log = n.floor_log_base_power_of_2(pow); if n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.ceiling_log_base_power_of_2(1), n.ceiling_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(Natural::ONE.ceiling_log_base_power_of_2(pow), 0); }); unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { assert_eq!( n.ceiling_log_base_power_of_2(pow), Natural::from(n).ceiling_log_base_power_of_2(pow) ); }); } #[test] fn checked_log_base_power_of_2_properties() { natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { let checked_log = n.checked_log_base_power_of_2(pow); assert_eq!(n.checked_log_base(&Natural::power_of_2(pow)), checked_log); assert_eq!( checked_log.is_some(), n.is_power_of_2() && (n.significant_bits() - 1).divisible_by(pow) ); if let Some(log) = checked_log { assert_eq!(Natural::power_of_2(log * pow), n); assert_eq!(log == 0, n == Natural::ONE); assert_eq!(n.floor_log_base_power_of_2(pow), log); assert_eq!(n.ceiling_log_base_power_of_2(pow), log); } }); natural_gen_var_2().test_properties(|n| { assert_eq!(n.checked_log_base_power_of_2(1), n.checked_log_base_2()); }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(Natural::ONE.checked_log_base_power_of_2(pow), Some(0)); }); unsigned_pair_gen_var_21::().test_properties(|(n, pow)| { assert_eq!( n.checked_log_base_power_of_2(pow), Natural::from(n).checked_log_base_power_of_2(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModAdd, ModAddAssign, ModIsReduced, ModNeg, ModShl, ModSub, }; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::unsigned_triple_gen_var_12; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_pair_gen_var_8, natural_quadruple_gen_var_1, natural_triple_gen_var_3, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_add() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&m)); assert!(v.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_add_assign(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_add_assign(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_add_assign(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_add_assign(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_add(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_add(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_add(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_add(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_add(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_add(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_add(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_add(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(((u + v) % m).to_string(), out); }; test("0", "0", "1", "0"); test("0", "0", "32", "0"); test("0", "2", "32", "2"); test("10", "14", "16", "8"); test("0", "123", "128", "123"); test("123", "0", "128", "123"); test("123", "456", "512", "67"); test("0", "3", "5", "3"); test("7", "5", "10", "2"); } #[test] fn mod_add_fail() { assert_panic!(Natural::ZERO.mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_add(Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_add(Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_add(Natural::ZERO, &Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_add(Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_add(Natural::from(30u8), &Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_add(&Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_add(&Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_add(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_add(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_add(Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_add(Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_add(Natural::ZERO, &Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_add(Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_add(Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_add(&Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_add(&Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_add(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_add(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_add(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!({ let mut x = Natural::ZERO; x.mod_add_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_add_assign(Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_add_assign(Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_add_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_add_assign(Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_add_assign(Natural::from(30u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_add_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_add_assign(&Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_add_assign(&Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_add_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_add_assign(&Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_add_assign(&Natural::from(30u8), &Natural::from(30u8)); }); } #[test] fn mod_add_properties() { natural_triple_gen_var_3().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let sum_val_val_val = x.clone().mod_add(y.clone(), m.clone()); let sum_val_ref_val = x.clone().mod_add(&y, m.clone()); let sum_ref_val_val = (&x).mod_add(y.clone(), m.clone()); let sum_ref_ref_val = (&x).mod_add(&y, m.clone()); let sum_val_val_ref = x.clone().mod_add(y.clone(), &m); let sum_val_ref_ref = x.clone().mod_add(&y, &m); let sum_ref_val_ref = (&x).mod_add(y.clone(), &m); let sum = (&x).mod_add(&y, &m); assert!(sum_val_val_val.is_valid()); assert!(sum_val_ref_val.is_valid()); assert!(sum_ref_val_val.is_valid()); assert!(sum_val_val_ref.is_valid()); assert!(sum_val_val_ref.is_valid()); assert!(sum_val_ref_ref.is_valid()); assert!(sum_ref_val_ref.is_valid()); assert!(sum.is_valid()); assert!(sum.mod_is_reduced(&m)); assert_eq!(sum_val_val_val, sum); assert_eq!(sum_val_ref_val, sum); assert_eq!(sum_ref_val_val, sum); assert_eq!(sum_ref_ref_val, sum); assert_eq!(sum_val_val_ref, sum); assert_eq!(sum_val_ref_ref, sum); assert_eq!(sum_ref_val_ref, sum); assert_eq!((&x + &y) % &m, sum); let mut mut_x = x.clone(); mut_x.mod_add_assign(y.clone(), m.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x.mod_add_assign(&y, m.clone()); assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); let mut mut_x = x.clone(); mut_x.mod_add_assign(y.clone(), &m); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x.mod_add_assign(&y, &m); assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); assert_eq!((&y).mod_add(&x, &m), sum); assert_eq!((&x).mod_sub((&y).mod_neg(&m), &m), sum); assert_eq!((&sum).mod_sub(&x, &m), y); assert_eq!(sum.mod_sub(y, m), x); }); natural_pair_gen_var_8().test_properties(|(x, m)| { assert_eq!((&x).mod_add(Natural::ZERO, &m), x); assert_eq!(Natural::ZERO.mod_add(&x, &m), x); assert_eq!((&x).mod_add(&x, &m), x.mod_shl(1, &m)); }); natural_quadruple_gen_var_1().test_properties(|(x, y, z, m)| { assert_eq!( (&x).mod_add(&y, &m).mod_add(&z, &m), x.mod_add(y.mod_add(z, &m), m) ); }); unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert_eq!( x.mod_add(y, m), Natural::from(x).mod_add(Natural::from(y), Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CoprimeWith, ModInverse, ModIsReduced, ModMul}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::unsigned_pair_gen_var_38; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen_var_1, natural_pair_gen_var_11}; use malachite_nz::test_util::natural::arithmetic::mod_inverse::mod_inverse_simple; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_inverse() { let test = |s, t, out| { let n = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); let result = n.clone().mod_inverse(m.clone()); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); let result = n.clone().mod_inverse(&m); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); let result = (&n).mod_inverse(m.clone()); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); let result = (&n).mod_inverse(&m); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); assert_eq!(mod_inverse_simple(n, m).to_debug_string(), out); }; test("1", "6", "Some(1)"); test("8", "12", "None"); test("42", "56", "None"); test("3", "5", "Some(2)"); test("3", "10", "Some(7)"); test("12345678987654321", "98765432123456789", "Some(1777777788)"); test("12345678987654321", "98765432123456827", "None"); } #[test] fn mod_inverse_fail() { assert_panic!(Natural::ZERO.mod_inverse(Natural::from(5u32))); assert_panic!(Natural::from(30u8).mod_inverse(Natural::from(3u32))); assert_panic!(Natural::ZERO.mod_inverse(&Natural::from(5u32))); assert_panic!(Natural::from(30u8).mod_inverse(&Natural::from(3u32))); assert_panic!((&Natural::ZERO).mod_inverse(Natural::from(5u32))); assert_panic!((&Natural::from(30u8)).mod_inverse(Natural::from(3u32))); assert_panic!((&Natural::ZERO).mod_inverse(&Natural::from(5u32))); assert_panic!((&Natural::from(30u8)).mod_inverse(&Natural::from(3u32))); } #[test] fn mod_inverse_properties() { natural_pair_gen_var_11().test_properties(|(n, m)| { assert!(n.mod_is_reduced(&m)); let result_val_val = n.clone().mod_inverse(m.clone()); let result_val_ref = n.clone().mod_inverse(&m); let result_ref_val = (&n).mod_inverse(m.clone()); let result = (&n).mod_inverse(&m); assert!(result.as_ref().is_none_or(Natural::is_valid)); assert!(result_val_val.as_ref().is_none_or(Natural::is_valid)); assert!(result_val_ref.as_ref().is_none_or(Natural::is_valid)); assert!(result_ref_val.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); assert_eq!(mod_inverse_simple(n.clone(), m.clone()), result); assert_eq!(result.is_some(), (&n).coprime_with(&m)); if let Some(inverse) = result { assert!(inverse.mod_is_reduced(&m)); assert_eq!((&inverse).mod_inverse(&m).as_ref(), Some(&n)); assert_eq!((&n).mod_mul(&inverse, &m), 1u32); assert_eq!((&m - n).mod_inverse(&m), Some(m - inverse)); } }); natural_gen_var_1().test_properties(|m| { assert_eq!(Natural::ONE.mod_inverse(&m), Some(Natural::ONE)); assert_eq!((&m - Natural::ONE).mod_inverse(&m), Some(m - Natural::ONE)); }); unsigned_pair_gen_var_38::().test_properties(|(n, m)| { assert_eq!( Natural::from(n).mod_inverse(Natural::from(m)), n.mod_inverse(m).map(Natural::from) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ModIsReduced; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::unsigned_pair_gen_var_12; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_pair_gen_var_5; use std::str::FromStr; #[test] fn test_mod_is_reduced() { let test = |u, v, out| { assert_eq!( Natural::from_str(u) .unwrap() .mod_is_reduced(&Natural::from_str(v).unwrap()), out ); }; test("0", "5", true); test("100", "100", false); test("100", "101", true); test("1000000000000", "1000000000000", false); test("1000000000000", "1000000000001", true); } #[test] #[should_panic] fn mod_is_reduced_fail() { Natural::from(123u32).mod_is_reduced(&Natural::ZERO); } #[test] fn mod_is_reduced_properties() { natural_pair_gen_var_5().test_properties(|(n, m)| { assert_eq!(n.mod_is_reduced(&m), &n % m == n); }); unsigned_pair_gen_var_12::().test_properties(|(n, m)| { assert_eq!( n.mod_is_reduced(&m), Natural::from(n).mod_is_reduced(&Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModAdd, ModIsReduced, ModMul, ModMulAssign, ModMulPrecomputed, ModMulPrecomputedAssign, ModNeg, ModSquare, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::JoinHalves; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_pair_gen_var_36, unsigned_triple_gen_var_12}; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_mul::{ limbs_mod_mul_two_limbs, limbs_precompute_mod_mul_two_limbs, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ large_type_gen_var_21, natural_pair_gen_var_8, natural_quadruple_gen_var_1, natural_triple_gen_var_3, }; use malachite_nz::test_util::natural::arithmetic::mod_mul::{ limbs_mod_mul_two_limbs_naive, limbs_precompute_mod_mul_two_limbs_alt, }; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_precompute_mod_mul_two_limbs() { let test = |m_1, m_0, inv_2, inv_1, inv_0| { assert_eq!( limbs_precompute_mod_mul_two_limbs(m_1, m_0), (inv_2, inv_1, inv_0) ); assert_eq!( limbs_precompute_mod_mul_two_limbs_alt(m_1, m_0), (inv_2, inv_1, inv_0) ); }; test(1, 1, u32::MAX, 0, u32::MAX); test(1, 2, u32::MAX - 1, 3, 0xfffffff8); test(123, 456, 34918433, 1162528328, 1277088208); test(u32::MAX, u32::MAX - 1, 1, 0, 2); test(u32::MAX, u32::MAX, 1, 0, 1); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_mul_two_limbs() { let test = |x_1, x_0, y_1, y_0, m_1, m_0, r_1, r_0| { let (inv_2, inv_1, inv_0) = limbs_precompute_mod_mul_two_limbs(m_1, m_0); assert_eq!( limbs_mod_mul_two_limbs(x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0), (r_1, r_0) ); assert_eq!( limbs_mod_mul_two_limbs_naive(x_1, x_0, y_1, y_0, m_1, m_0), (r_1, r_0) ); }; test(0, 0, 0, 0, 1, 1, 0, 0); test(1, 0, 0, 1, 1, 1, 1, 0); test(123, 456, 654, 321, 789, 876, 213, 4164192732); test(123, 456, 789, 876, u32::MAX, u32::MAX, 467532, 496503); } #[test] fn test_mod_mul() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&m)); assert!(v.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_mul_assign(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_mul_assign(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_mul_assign(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_mul_assign(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_mul(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_mul(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_mul(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_mul(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_mul(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_mul(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_mul(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_mul(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!((u * v % m).to_string(), out); }; test("0", "0", "1", "0"); test("1", "0", "32", "0"); test("1", "2", "32", "2"); test("3", "4", "15", "12"); test("7", "6", "10", "2"); test("10", "14", "16", "12"); test("1", "123", "128", "123"); test("123", "1", "128", "123"); test("123", "456", "512", "280"); test("1000000000", "2000000000", "4294967296", "1321730048"); test("1000000000", "2000000000", "4294967297", "856068761"); test( "1000000000000000", "2000000000000000", "1000000000000000000000001", "999999999999999998000001", ); } #[test] fn limbs_precompute_mod_mul_two_limbs_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_pair_gen_var_36().test_properties_with_config(&config, |(m_1, m_0)| { let (inv_2, inv_1, inv_0) = limbs_precompute_mod_mul_two_limbs(m_1, m_0); assert_eq!( limbs_precompute_mod_mul_two_limbs_alt(m_1, m_0), (inv_2, inv_1, inv_0) ); assert!(inv_2 != 0 || inv_1 != 0 || inv_0 != 0); }); } #[test] fn limbs_mod_mul_two_limbs_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_21().test_properties_with_config( &config, |(x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0)| { let (r_1, r_0) = limbs_mod_mul_two_limbs(x_1, x_0, y_1, y_0, m_1, m_0, inv_2, inv_1, inv_0); assert_eq!( limbs_mod_mul_two_limbs_naive(x_1, x_0, y_1, y_0, m_1, m_0), (r_1, r_0) ); let x = Natural::from(DoubleLimb::join_halves(x_1, x_0)); let y = Natural::from(DoubleLimb::join_halves(y_1, y_0)); let m = Natural::from(DoubleLimb::join_halves(m_1, m_0)); let q = &x * &y / &m; let r = Natural::from(DoubleLimb::join_halves(r_1, r_0)); assert_eq!(q * m + r, x * y); }, ); } #[test] fn mod_mul_fail() { assert_panic!(Natural::ZERO.mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_mul(Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_mul(Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_mul(Natural::ZERO, &Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_mul(Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_mul(Natural::from(30u8), &Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_mul(&Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_mul(&Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_mul(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_mul(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_mul(Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_mul(Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_mul(Natural::ZERO, &Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_mul(Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_mul(Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_mul(&Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_mul(&Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_mul(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_mul(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_mul(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!({ let mut x = Natural::ZERO; x.mod_mul_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_mul_assign(Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_mul_assign(Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_mul_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_mul_assign(Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_mul_assign(Natural::from(30u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_mul_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_mul_assign(&Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_mul_assign(&Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_mul_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_mul_assign(&Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_mul_assign(&Natural::from(30u8), &Natural::from(30u8)); }); } #[test] fn mod_mul_properties() { natural_triple_gen_var_3().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let product_val_val_val = x.clone().mod_mul(y.clone(), m.clone()); let product_val_ref_val = x.clone().mod_mul(&y, m.clone()); let product_ref_val_val = (&x).mod_mul(y.clone(), m.clone()); let product_ref_ref_val = (&x).mod_mul(&y, m.clone()); let product_val_val_ref = x.clone().mod_mul(y.clone(), &m); let product_val_ref_ref = x.clone().mod_mul(&y, &m); let product_ref_val_ref = (&x).mod_mul(y.clone(), &m); let product = (&x).mod_mul(&y, &m); assert!(product_val_val_val.is_valid()); assert!(product_val_ref_val.is_valid()); assert!(product_ref_val_val.is_valid()); assert!(product_val_val_ref.is_valid()); assert!(product_val_val_ref.is_valid()); assert!(product_val_ref_ref.is_valid()); assert!(product_ref_val_ref.is_valid()); assert!(product.is_valid()); assert!(product.mod_is_reduced(&m)); assert_eq!(product_val_val_val, product); assert_eq!(product_val_ref_val, product); assert_eq!(product_ref_val_val, product); assert_eq!(product_ref_ref_val, product); assert_eq!(product_val_val_ref, product); assert_eq!(product_val_ref_ref, product); assert_eq!(product_ref_val_ref, product); let mut mut_x = x.clone(); mut_x.mod_mul_assign(y.clone(), m.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x.mod_mul_assign(&y, m.clone()); assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let mut mut_x = x.clone(); mut_x.mod_mul_assign(y.clone(), &m); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x.mod_mul_assign(&y, &m); assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let data = ModMulPrecomputed::::precompute_mod_mul_data(&m); let product_pre_val_val_val = x.clone().mod_mul_precomputed(y.clone(), m.clone(), &data); let product_pre_val_ref_val = x.clone().mod_mul_precomputed(&y, m.clone(), &data); let product_pre_ref_val_val = (&x).mod_mul_precomputed(y.clone(), m.clone(), &data); let product_pre_ref_ref_val = (&x).mod_mul_precomputed(&y, m.clone(), &data); let product_pre_val_val_ref = x.clone().mod_mul_precomputed(y.clone(), &m, &data); let product_pre_val_ref_ref = x.clone().mod_mul_precomputed(&y, &m, &data); let product_pre_ref_val_ref = (&x).mod_mul_precomputed(y.clone(), &m, &data); let product_pre_ref_ref_ref = (&x).mod_mul_precomputed(&y, &m, &data); assert!(product_pre_val_val_val.is_valid()); assert!(product_pre_val_ref_val.is_valid()); assert!(product_pre_ref_val_val.is_valid()); assert!(product_pre_val_val_ref.is_valid()); assert!(product_pre_val_val_ref.is_valid()); assert!(product_pre_val_ref_ref.is_valid()); assert!(product_pre_ref_val_ref.is_valid()); assert!(product_pre_ref_ref_ref.is_valid()); assert_eq!(product_pre_val_val_val, product); assert_eq!(product_pre_val_ref_val, product); assert_eq!(product_pre_ref_val_val, product); assert_eq!(product_pre_ref_ref_val, product); assert_eq!(product_pre_val_val_ref, product); assert_eq!(product_pre_val_ref_ref, product); assert_eq!(product_pre_ref_val_ref, product); let mut mut_x = x.clone(); mut_x.mod_mul_precomputed_assign(y.clone(), m.clone(), &data); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x.mod_mul_precomputed_assign(&y, m.clone(), &data); assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let mut mut_x = x.clone(); mut_x.mod_mul_precomputed_assign(y.clone(), &m, &data); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x.mod_mul_precomputed_assign(&y, &m, &data); assert_eq!(mut_x, product); assert!(mut_x.is_valid()); assert_eq!((&x * &y) % &m, product); assert_eq!((&y).mod_mul(&x, &m), product); assert_eq!((&x).mod_mul((&y).mod_neg(&m), &m), (&product).mod_neg(&m)); assert_eq!(x.mod_neg(&m).mod_mul(y, &m), product.mod_neg(m)); }); natural_pair_gen_var_8().test_properties(|(x, m)| { assert_eq!((&x).mod_mul(Natural::ZERO, &m), 0); assert_eq!(Natural::ZERO.mod_mul(&x, &m), 0); if m > 1 { assert_eq!((&x).mod_mul(Natural::ONE, &m), x); assert_eq!(Natural::ONE.mod_mul(&x, &m), x); } assert_eq!((&x).mod_mul(&x, &m), x.mod_square(m)); }); natural_quadruple_gen_var_1().test_properties(|(ref x, ref y, ref z, ref m)| { assert_eq!(x.mod_mul(y, m).mod_mul(z, m), x.mod_mul(y.mod_mul(z, m), m)); assert_eq!( x.mod_mul(y.mod_add(z, m), m), x.mod_mul(y, m).mod_add(x.mod_mul(z, m), m) ); assert_eq!( x.mod_add(y, m).mod_mul(z, m), x.mod_mul(z, m).mod_add(y.mod_mul(z, m), m) ); }); unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert_eq!( x.mod_mul(y, m), Natural::from(x).mod_mul(Natural::from(y), Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Mod, ModAdd, ModIsReduced, ModNeg, ModNegAssign}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::unsigned_pair_gen_var_16; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_pair_gen_var_8; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_neg() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&v)); let n = u.clone().mod_neg(v.clone()); assert!(n.is_valid()); assert!(n.mod_is_reduced(&v)); assert_eq!(n.to_string(), out); let n = u.clone().mod_neg(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_neg(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_neg(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_neg_assign(v.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u; n.mod_neg_assign(&v); assert!(n.is_valid()); assert_eq!(n.to_string(), out); }; test("0", "5", "0"); test("7", "10", "3"); test("100", "101", "1"); test("4294967294", "4294967295", "1"); test("1", "4294967295", "4294967294"); test("7", "1000000000000", "999999999993"); test("999999999993", "1000000000000", "7"); } #[test] fn mod_neg_fail() { assert_panic!(Natural::ZERO.mod_neg(Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_neg(Natural::ONE)); assert_panic!(Natural::ZERO.mod_neg(&Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_neg(&Natural::ONE)); assert_panic!((&Natural::ZERO).mod_neg(Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_neg(Natural::ONE)); assert_panic!((&Natural::ZERO).mod_neg(&Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_neg(&Natural::ONE)); assert_panic!({ let mut x = Natural::ZERO; x.mod_neg_assign(Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_neg_assign(Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_neg_assign(&Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_neg_assign(&Natural::ONE); }); } #[test] fn mod_neg_properties() { natural_pair_gen_var_8().test_properties(|(n, m)| { assert!(n.mod_is_reduced(&m)); let neg = (&n).mod_neg(&m); assert!(neg.is_valid()); assert!(neg.mod_is_reduced(&m)); let neg_alt = (&n).mod_neg(m.clone()); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let neg_alt = n.clone().mod_neg(&m); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let neg_alt = n.clone().mod_neg(m.clone()); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let mut n_alt = n.clone(); n_alt.mod_neg_assign(&m); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let mut n_alt = n.clone(); n_alt.mod_neg_assign(m.clone()); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); assert_eq!(neg, (-&n).mod_op(Integer::from(&m))); assert_eq!((&neg).mod_neg(&m), n); assert_eq!((&n).mod_add(&neg, &m), 0); assert_eq!(n == neg, n == Natural::ZERO || n << 1 == m); }); unsigned_pair_gen_var_16::().test_properties(|(n, m)| { assert_eq!(n.mod_neg(m), Natural::from(n).mod_neg(Natural::from(m))); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingDivNegMod, DivMod, Mod, ModAssign, ModIsReduced, NegMod, NegModAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{ExactFrom, JoinHalves}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_12, unsigned_vec_pair_gen_var_11, unsigned_vec_pair_gen_var_18, unsigned_vec_triple_gen_var_57, unsigned_vec_unsigned_pair_gen_var_22, unsigned_vec_unsigned_pair_gen_var_26, unsigned_vec_unsigned_pair_gen_var_27, unsigned_vec_unsigned_pair_gen_var_28, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::div_mod::{ limbs_div_mod_barrett_scratch_len, limbs_two_limb_inverse_helper, }; use malachite_nz::natural::arithmetic::mod_op::{ limbs_mod, limbs_mod_barrett, limbs_mod_by_two_limb_normalized, limbs_mod_divide_and_conquer, limbs_mod_limb, limbs_mod_limb_alt_1, limbs_mod_limb_alt_2, limbs_mod_limb_any_leading_zeros_1, limbs_mod_limb_any_leading_zeros_2, limbs_mod_limb_at_least_1_leading_zero, limbs_mod_limb_at_least_2_leading_zeros, limbs_mod_limb_small_normalized, limbs_mod_limb_small_unnormalized, limbs_mod_schoolbook, limbs_mod_three_limb_by_two_limb, limbs_mod_to_out, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ large_type_gen_var_12, natural_gen, natural_gen_var_2, natural_pair_gen_var_5, natural_pair_gen_var_6, natural_triple_gen_var_4, unsigned_sextuple_gen_var_2, unsigned_vec_quadruple_gen_var_5, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17, }; use malachite_nz::test_util::natural::arithmetic::mod_op::{limbs_mod_limb_alt_3, rug_neg_mod}; use num::{BigUint, Integer}; use rug; use rug::ops::RemRounding; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_limb() { let test = |ns: &[Limb], d: Limb, r: Limb| { assert_eq!(limbs_mod_limb::(ns, d), r); assert_eq!( limbs_mod_limb_any_leading_zeros_1::(ns, d), r ); assert_eq!( limbs_mod_limb_any_leading_zeros_2::(ns, d), r ); assert_eq!(limbs_mod_limb_alt_1::(ns, d), r); assert_eq!(limbs_mod_limb_alt_2::(ns, d), r); assert_eq!(limbs_mod_limb_alt_3(ns, d), r); }; test(&[0, 0], 2, 0); // - shift != 0 in limbs_mod_limb_any_leading_zeros_1 // - r_hi < b in limbs_mod_limb_any_leading_zeros_1 // - n == 2 in limbs_mod_limb_any_leading_zeros_1 // - !divisor.get_highest_bit() in limbs_mod_limb_alt_2 // - !divisor.get_highest_bit() && len < MOD_1U_TO_MOD_1_1_THRESHOLD in limbs_mod_limb_alt_2 test(&[6, 7], 1, 0); test(&[6, 7], 2, 0); // - n > 2 in limbs_mod_limb_any_leading_zeros_1 // - !divisor.get_highest_bit() && MOD_1U_TO_MOD_1_1_THRESHOLD <= len < // MOD_11_TO_MOD_1_2_THRESHOLD in limbs_mod_limb_alt_2 test(&[100, 101, 102], 10, 8); test(&[123, 456], 789, 636); test(&[0, 0], 0xa0000000, 0); // - shift == 0 in limbs_mod_limb_any_leading_zeros_1 // - divisor.get_highest_bit() in limbs_mod_limb_alt_2 // - divisor.get_highest_bit() && len < MOD_1N_TO_MOD_1_1_THRESHOLD in limbs_mod_limb_alt_2 test(&[6, 7], 0x80000000, 6); test(&[6, 7], 0xa0000000, 0x20000006); // - divisor.get_highest_bit() && len >= MOD_1N_TO_MOD_1_1_THRESHOLD in limbs_mod_limb_alt_2 test(&[100, 101, 102], 0xabcddcba, 2152689614); // - r_hi >= b in limbs_mod_limb_any_leading_zeros_1 test(&[u32::MAX, u32::MAX], 2, 1); test(&[u32::MAX, u32::MAX], 3, 0); test(&[u32::MAX, u32::MAX], u32::MAX, 0); test(&[u32::MAX, u32::MAX], 0xa0000000, 1610612735); test(&[100, 101, 102], u32::MAX, 303); test(&[1, 2, 3, 4], 6, 1); // - !divisor.get_highest_bit() && len >= MOD_11_TO_MOD_1_2_THRESHOLD && (len < // MOD_12_TO_MOD_1_4_THRESHOLD || divisor & HIGHEST_TWO_BITS_MASK != 0) in // limbs_mod_limb_alt_2 test( &[ 3713432036, 2475243626, 3960734766, 244755020, 3760002601, 301563516, 2499010086, 1451814771, 1299826235, 3628218184, 2565364972, 3729936002, ], 565832495, 295492150, ); // - !divisor.get_highest_bit() && len >= MOD_12_TO_MOD_1_4_THRESHOLD && divisor & // HIGHEST_TWO_BITS_MASK == 0 in limbs_mod_limb_alt_2 test( &[ 540286473, 1475101238, 1863380542, 2517905739, 81646271, 3172818884, 2759300635, 852345965, 3647245071, 3875987988, 4229899590, 4100778302, 1641902155, 1289745333, 3414845068, 119899697, 2175381145, 2490291811, 3047506964, 1815484255, 3379971995, 1695675424, 1418284338, ], 436775226, 165213921, ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_fail_1() { limbs_mod_limb::(&[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_fail_2() { limbs_mod_limb::(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_any_leading_zeros_1_fail_1() { limbs_mod_limb_any_leading_zeros_1::(&[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_any_leading_zeros_1_fail_2() { limbs_mod_limb_any_leading_zeros_1::(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_any_leading_zeros_2_fail_1() { limbs_mod_limb_any_leading_zeros_2::(&[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_any_leading_zeros_2_fail_2() { limbs_mod_limb_any_leading_zeros_2::(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_limb_small_normalized() { let test = |ns: &[Limb], d: Limb, r: Limb| { assert_eq!( limbs_mod_limb_small_normalized::(ns, d), r ); }; test(&[0x80000123], 0x80000000, 0x123); test(&[0, 0], 0xa0000000, 0); test(&[6, 7], 0x80000000, 6); test(&[6, 7], 0xa0000000, 0x20000006); test(&[100, 101, 102], 0xabcddcba, 2152689614); test(&[u32::MAX, u32::MAX], u32::MAX, 0); test(&[u32::MAX, u32::MAX], 0xa0000000, 1610612735); test(&[100, 101, 102], u32::MAX, 303); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_small_normalized_fail_1() { limbs_mod_limb_small_normalized::(&[], u32::MAX); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_small_normalized_fail_2() { limbs_mod_limb_small_normalized::(&[10, 10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_limb_small_unnormalized() { let test = |ns: &[Limb], d: Limb, r: Limb| { assert_eq!( limbs_mod_limb_small_unnormalized::(ns, d), r ); assert_eq!( limbs_mod_limb_at_least_1_leading_zero::(ns, d), r ); }; test(&[0, 0], 2, 0); test(&[0], 2, 0); // - remainder >= divisor in limbs_mod_limb_small_unnormalized // - len.odd() in limbs_mod_limb_at_least_1_leading_zero // - len == 1 in limbs_mod_limb_at_least_1_leading_zero test(&[6], 2, 0); test(&[6], 4, 2); // - len.even() in limbs_mod_limb_at_least_1_leading_zero // - len < 4 in limbs_mod_limb_at_least_1_leading_zero test(&[6, 7], 1, 0); test(&[6, 7], 2, 0); // - len.odd() && len != 1 in limbs_mod_limb_at_least_1_leading_zero test(&[100, 101, 102], 10, 8); // - remainder < divisor in limbs_mod_limb_small_unnormalized test(&[123, 456], 789, 636); test(&[u32::MAX, u32::MAX], 2, 1); test(&[u32::MAX, u32::MAX], 3, 0); // - len >= 4 in limbs_mod_limb_at_least_1_leading_zero test(&[1, 2, 3, 4, 5], 6, 3); test(&[1, 2, 3, 4], 6, 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_small_unnormalized_fail_1() { limbs_mod_limb_small_unnormalized::(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_small_unnormalized_fail_2() { limbs_mod_limb_small_unnormalized::(&[10, 10], u32::MAX); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_at_least_1_leading_zero_fail_1() { limbs_mod_limb_at_least_1_leading_zero::(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_at_least_1_leading_zero_fail_2() { limbs_mod_limb_at_least_1_leading_zero::(&[10, 10], u32::MAX); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_limb_at_least_2_leading_zeros() { let test = |ns: &[Limb], d: Limb, r: Limb| { assert_eq!( limbs_mod_limb_at_least_2_leading_zeros::(ns, d), r ); }; test(&[0, 0], 2, 0); test(&[0], 2, 0); // - len ≡ 1 mod 4 // - len < 4 test(&[6], 2, 0); test(&[6], 4, 2); // - len ≡ 2 mod 4 test(&[6, 7], 1, 0); test(&[6, 7], 2, 0); // - len ≡ 3 mod 4 test(&[100, 101, 102], 10, 8); test(&[123, 456], 789, 636); test(&[u32::MAX, u32::MAX], 2, 1); test(&[u32::MAX, u32::MAX], 3, 0); // - len ≡ 0 mod 4 test(&[1, 2, 3, 4], 6, 1); // - len >= 4 test(&[1, 2, 3, 4, 5], 6, 3); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_at_least_2_leading_zeros_fail_1() { limbs_mod_limb_at_least_2_leading_zeros::(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_limb_at_least_2_leading_zeros_fail_2() { limbs_mod_limb_at_least_2_leading_zeros::(&[10, 10], 0x7fffffff); } fn verify_limbs_mod_three_limb_by_two_limb( n_2: Limb, n_1: Limb, n_0: Limb, d_1: Limb, d_0: Limb, r: DoubleLimb, ) { let n = Natural::from_owned_limbs_asc(vec![n_0, n_1, n_2]); let d = Natural::from(DoubleLimb::join_halves(d_1, d_0)); let r = Natural::from(r); assert_eq!(n % &d, r); assert!(r < d); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_three_limb_by_two_limb() { let test = |n_2, n_1, n_0, d_1, d_0, r| { assert_eq!( limbs_mod_three_limb_by_two_limb( n_2, n_1, n_0, d_1, d_0, limbs_two_limb_inverse_helper(d_1, d_0) ), r ); verify_limbs_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, r); }; test(1, 2, 3, 0x80000004, 5, 0x7ffffffdfffffffe); test(2, 0x40000000, 4, 0x80000000, 0, 0x4000000000000004); test( 1614123406, 3687984980, 2695202596, 2258238141, 1642523191, 274277675918877623, ); } fn verify_limbs_mod_by_two_limb_normalized(ns: &[Limb], ds: &[Limb], r_0: Limb, r_1: Limb) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let expected_r = n % &d; let r = Natural::from_owned_limbs_asc(vec![r_0, r_1]); assert_eq!(r, expected_r); assert!(r < d); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_by_two_limb_normalized() { let test = |ns: &[Limb], ds: &[Limb], r_0: Limb, r_1: Limb| { assert_eq!(limbs_mod_by_two_limb_normalized(ns, ds), (r_0, r_1)); verify_limbs_mod_by_two_limb_normalized(ns, ds, r_0, r_1); }; test(&[1, 2], &[3, 0x80000000], 1, 2); test(&[1, 2, 3, 4, 5], &[3, 0x80000000], 166, 2147483626); test( &[4142767597, 2922703399, 3921445909], &[2952867570, 2530544119], 3037232599, 1218898013, ); } #[test] #[should_panic] fn limbs_mod_by_two_limb_normalized_fail_1() { limbs_mod_by_two_limb_normalized(&[1, 2], &[3, 4]); } #[test] #[should_panic] fn limbs_mod_by_two_limb_normalized_fail_2() { limbs_mod_by_two_limb_normalized(&[1, 2], &[3, 0x80000000, 4]); } fn verify_limbs_mod_1(ns_in: &[Limb], ds: &[Limb], ns_out: &[Limb]) { let n = Natural::from_limbs_asc(ns_in); let d = Natural::from_limbs_asc(ds); let expected_r = n % &d; let r = Natural::from_limbs_asc(&ns_out[..ds.len()]); assert_eq!(r, expected_r); assert!(r < d); } #[test] fn test_limbs_mod_schoolbook() { let test = |ns_in: &[Limb], ds: &[Limb], ns_out: &[Limb]| { let mut ns = ns_in.to_vec(); let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_schoolbook(&mut ns, ds, d_inv); assert_eq!(ns, ns_out); verify_limbs_mod_1(ns_in, ds, &ns); }; #[cfg(feature = "32_bit_limbs")] { test(&[1, 2, 3], &[3, 4, 0x80000000], &[1, 2, 3]); test( &[1, 2, 3, 4, 5, 6], &[3, 4, 0x80000000], &[268, 328, 2147483575, 4294967251, 5, 6], ); test( &[0, 0, 0, 1], &[1, 0, 0x80000000], &[u32::MAX, u32::MAX, 0x7fffffff, 1], ); test( &[ 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, ], &[ 1430162564, 1873089879, 3090281851, 2861182896, 2502166555, 2486624904, 960387080, 3073064701, ], &[ 1030827391, 3064551024, 3176366775, 3772761918, 2268243711, 29902504, 2510544116, 1188988289, ], ); test( &[ 0, 0x4000000, 0xfffff000, 63, 4294443008, u32::MAX, u32::MAX, 8388575, 4294836224, 0x3fffffff, ], &[33554304, 4294443008, u32::MAX], &[ 0, 0, 0, 4294443072, 0xfff00000, u32::MAX, u32::MAX, u32::MAX, 4294836224, 0x3fffffff, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 4451260977376821357, 18241701617364042056, 6169989192350218482, 15071965537117101028, 13509168527678537782, 12224278653171635329, 16077066393714953826, 1433938684868066489, 13014970036232570373, 899282336249563956, 3089487642230339536, 3787737519477527148, 16667686214395942740, 8787122953224574943, 7841835218775877827, 9693303502025838409, 16122224776459879427, 144327425397945219, ], &[ 2350654041004706911, 7834348511584604247, 12756796070221345724, 3842923787777653903, 12373799197090248752, 9712029403347085570, 1426676505264168302, 10586232903332693517, 8387833601131974459, 6290888746273553243, 9503969704425173615, ], &[ 12688955427180652274, 7641660693922643933, 8789985477567049482, 5698832637416200787, 14684840547760545685, 2822100467869581421, 3557573565928866957, 4409631974409684922, 16994214656621423610, 4513108841166793667, 9009005527785483287, 4330767427200269309, 11409205475757922767, 12430752173702915207, 11990819624778098799, 4145020291153594556, 7099200056207569977, 3510167930325480168, 4731667122118327121, 10720310942075546738, 5799804483118787221, 17268037247251138479, 13305947798457087249, 1405091439325174594, 13072181651983436371, 16122224776459879427, 144327425397945219, ], ); } } #[test] #[should_panic] fn limbs_mod_schoolbook_fail_1() { let ds = &[3, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_schoolbook(&mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_mod_schoolbook_fail_2() { let ds = &[3, 4, 5, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_schoolbook(&mut [1, 2, 3], ds, d_inv); } #[test] #[should_panic] fn limbs_mod_schoolbook_fail_3() { let ds = &[3, 4, 5]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_schoolbook(&mut [1, 2, 3], ds, d_inv); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_divide_and_conquer() { let test = |qs_in: &[Limb], ns_in: &[Limb], ds: &[Limb], ns_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut ns = ns_in.to_vec(); let ds_len = ds.len(); let d_inv = limbs_two_limb_inverse_helper(ds[ds_len - 1], ds[ds_len - 2]); limbs_mod_divide_and_conquer(&mut qs, &mut ns, ds, d_inv); assert_eq!(&ns[..ds_len], ns_out); verify_limbs_mod_1(ns_in, ds, &ns); }; test( &[10; 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], &[718, 910, 1080, 1286, 1492, 2147483434], ); test( &[0; 3], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], &[0, 0, 0, 0, 1, 0, 0, 0x80000000], &[0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, 0x7fffffff], ); test( &[ 1341443830, 680228019, 2358294753, 4240552485, 4220791420, 3445360969, 1267691556, 3340881424, 992535572, 1421700486, 4136881179, ], &[ 342694080, 2041952014, 1126110022, 386493367, 2712278177, 1646877232, 868323005, 1128141558, 2508964077, 2270408768, 413397861, 276293957, 2413870149, 3904853505, 1276303079, 2556190902, 3967785388, 2803311564, 1963309088, 2281251697, 108392083, 3821172642, 2048710986, 445614759, 2901896991, 3601903082, 1748962330, 658337341, 3756770944, 2926642090, 7482898, 2241569433, 3381544088, 3275875595, 3036252835, 2075586864, 1267727773, 221607050, 3946214050, 921175728, 655433083, 3594825352, 1857831165, 3460211778, 2710641188, 1271591399, 263125866, 3619333728, 1041602820, 3231202083, 259949419, 4156557841, 3419638674, 3270070813, 2084018311, 2951772182, 860428573, 1138531819, 71044931, 3406637788, 3662652535, 3741808197, 86584983, 1543795459, 160951322, 1039367499, 2428548772, 3604743617, 1138310711, 2881638514, 2899388867, 3501166651, 161644747, 2395978477, 2682256494, 3417971200, 624066885, 1772236754, 48275686, 3979745914, 2458268763, 2470110876, 3143857674, 3359279240, 46246098, 2912257532, 2916568936, ], &[ 4267671814, 3181376526, 4204274026, 2772982826, 171341955, 3239339748, 83269891, 2325049318, 746305994, 1290717192, 1805639230, 1856363646, 3445599715, 1388597950, 2699498310, 246990054, 1396771726, 265087723, 3372840761, 3260397695, 2010115470, 2211074582, 1883962263, 256363687, 4012920099, 2367091978, 1485341992, 1836339208, 1434180757, 2616877872, 1145425491, 1261399773, 3926766027, 3115015865, 1741783714, 3802513218, 4081750672, 3856503286, 2137512595, 1192985123, 1863041957, 700637154, 2503934926, 2021744810, 157763047, 453501781, 1898727251, 3741166728, 105996483, 3390681922, 1127471458, 4229032301, 254843851, 2729237155, 1707011850, 1756734415, 1864969309, 96539023, 220456923, 3061776324, 1741151628, 1199010536, 2099212259, 3095715999, 1369052975, 2575251120, 1821995904, 4169452262, 3299830336, 666854626, 3647011057, 3965571435, 1551218489, 726151433, 1730753749, 750433250, 2084548637, 475638490, 3209308986, 1536371286, 3458731894, 451976715, 1463077982, 2401462738, ], &[ 50882392, 3543059939, 2606418187, 171797978, 3702339267, 3400795540, 1675838746, 3131956910, 3246773095, 2366066134, 1942572319, 200951604, 2751524401, 2229461380, 953596498, 2149080321, 992246008, 2665146762, 3598754770, 101403369, 2364937647, 3687287854, 3518388658, 3773344884, 2952272227, 2179289728, 3985568008, 2985468384, 1733586261, 4006520661, 592636589, 1738983882, 3771432433, 334405279, 30528997, 3353300809, 3694124666, 1257341879, 1142716002, 3178475445, 1431232435, 2733787829, 2350134046, 162973337, 604966704, 1355497537, 2006066960, 1053669332, 2166548589, 1297102232, 878976420, 1030095675, 3202690801, 955256572, 1487108550, 2945568597, 3875785235, 1390419282, 1216776596, 786261001, 3784540042, 1845909951, 1777517834, 12237310, 475982412, 3059699536, 4125207911, 2924612871, 3238196381, 2479221661, 1483884124, 433754513, 447002430, 2684532044, 3494064078, 619277683, 2680056541, 538552294, 1984267024, 700348592, 1278341418, 1614761367, 3944408375, 1269851701, ], ); test( &[ 3656551823, 3383257247, 550091805, 1932339117, 3279901067, 2864941409, 3440756420, 466783416, 651341619, 2318022162, 1201487629, 3064175522, 2345469826, 3581748650, 2606599593, 3742095121, ], &[ 3689695988, 3117118992, 1237207334, 1180101208, 2947083336, 2827697081, 221923985, 2507264800, 619323315, 1516562901, 3186068769, 1013769776, 1271582351, 1669896397, 2497959088, 3504047880, 4212568439, 1608150067, 4150555892, 374787916, 889323122, 3833122938, 4262272989, ], &[ 3226059476, 722714803, 1915993039, 2160412527, 1484228011, 1715426198, 1611850737, 3097214810, ], &[ 1074470868, 2174113464, 1715956530, 3963027838, 1871758691, 1809783936, 3173233408, 1926929270, ], ); test( &[ 2108009976, 2838126990, 827008974, 4157613011, 3782799311, 839921672, 879731301, 1926496935, 3712149888, 2363043408, 3863476261, 1703718215, 499165670, 2993223230, 4279694017, 2976095205, 2193242813, 3593708162, 586354096, 296757650, 242624274, 199363552, 2802933005, 2759687879, 3925865458, 4217980786, 621040829, 4008464542, 3795907109, 270168250, 3625538473, 759155103, 3959828159, 1835721901, 1818377089, 114690984, 2967220963, 2377698568, 2241245638, 2252300906, 3116551983, 3644576818, 2608501946, 2181270779, 1815210824, 1268283136, 484429506, 1180516809, 559610343, 2543044915, 3719740023, 558939794, 3989231279, 1089033996, 3509826828, 3545449066, 3353643945, 2822587915, 2300900020, 309191900, 2371088678, 1169317833, 2688462322, 704882387, 1429447898, 2514029776, 1955158460, 3862686818, 1584130288, 482000750, 4224830364, 2104097699, 1183456674, 2270729014, 2607655660, 2966545947, 2931252595, 759652385, 3970839358, 2487392344, 1507124762, 758697388, 3840603988, 1293583672, 252424514, 646352064, 1756992845, 2309291248, 3392597937, 2946557682, 3659552460, 1720311830, 3395887210, 2674135679, 3196424053, 2895118562, 1256983146, 2482795730, 1922474903, 2105232035, 3692384401, 2891711374, 3496171341, 515080177, 4073860792, 2051799135, 2279442367, 3258846627, 70977295, 1937954703, 2800340027, 1760719187, 646417623, 3158839049, 3176203007, 213391749, 869819866, 3906922929, 1586646665, 1614123406, 3687984980, 1177302158, 272342927, 1441818617, 2083855650, 1541781406, 3311904586, 106907162, 4108429222, 662974012, 4140594255, 1984524179, 3259771450, 3863443649, 3307256449, 3597197635, 3771753969, 3551628070, 3550518548, 2546464879, 3812123817, 2299164636, 2258249267, 815945886, 3725185601, 738801212, 3862546442, 207778311, 1535617953, 2150997157, 729581295, 143725958, 1410055499, 4204574368, 2185442793, 3653861199, 1767186378, 3537808267, 1766021033, 2239408696, 1986025224, 3625288948, 4046347844, 2490523057, 3491861717, 1312039469, 597857291, 206880668, 1812928615, 3684502664, 3820772609, 1327777451, 1237379465, 764273090, 3594853086, 2859643842, 1243019386, 3444655918, 1596721727, 2221238575, 2483346164, 2064518283, 2282844430, 1960424205, 4028198846, 2342293800, 1645322170, 3508868511, 2376856302, 1764497492, 2461899059, 3430260828, 1083983032, 1448541077, 2081767380, 1131293272, 2121152826, 4212689224, 2039367869, 2193844060, 1864700761, 1182989130, 1481869846, 969270162, 3997775597, 1483663077, 394034269, 1586435653, 2281434261, 1937512315, 836935557, 59742568, 1854699653, 2116629465, 328821302, 1999851100, 604863759, 556389113, 2057620108, 1992554416, 427465103, 813735424, 487055225, 402647361, 3006998394, 2146302389, 2308517156, 1063328348, 2382344201, 2665908320, 481118926, 2376219143, 1164055989, 128362737, 2711666601, 1898018298, 2928344090, 3862251511, 749517272, 2790599579, 3506539103, 2592038317, 1682088920, 1332639030, 3053921374, 3066891587, 242466377, 3536065834, 2016487096, 1321862427, 2409873623, 3088797737, 2840818323, 2052021858, 4079299898, 452968540, 3880575723, 2680668784, 1502544423, 1619882634, 1068420458, 3236073318, 1740351058, 1183565882, 2761799103, 246817911, 2967032269, 4003972840, 969974269, 3193561842, 1002645557, 2347161653, 4272895273, 1522072178, 972383725, 3026624523, 434293193, 2855690795, 2455822196, 2413168892, 2999634230, 784531194, 249556803, 2559695464, 3131798530, 668810109, 2114036394, 2861740558, 370716909, 2126014070, 3913884200, 1577476936, 855642956, 2074597201, 3461659621, 3292762038, 2153122643, 1658901071, 1562860969, 501980289, 1611843440, 2433026108, 3791871978, ], &[ 2325147333, 1406197332, 1502532645, 137754493, 1488912421, 1014222449, 1678300831, 2078887154, 2311629707, 3855402290, 1904906031, 1350026944, 314061674, 919972212, 1429252796, 544807358, 2607111216, 3001219316, 160533550, 2875169678, 1402474615, 3234840532, 1662112023, 1943050521, 4132256985, 2915369430, 699620367, 59590583, 2461837586, 3986106860, 2659659366, 3589796255, 4168995860, 2337625655, 4292546333, 1793085295, 2647770730, 2871508164, 2660729400, 3630964395, 3874212033, 1240042620, 1713051992, 2105061240, 968807145, 3026819276, 2442427316, 2718248469, 2572140009, 1793916894, 2112926236, 1058005225, 1528978151, 98430379, 3348888463, 2121431457, 3545708238, 3975070402, 764453596, 192861224, 2698588322, 1493819664, 2502294971, 3139295505, 1318649192, 1552623529, 2989328476, 1592829691, 1175278450, 182489613, 1858350437, 2440903999, 1622786339, 162763913, 4106583944, 609833788, 1344925844, 3910333895, 1369398307, 51929280, 2214052160, 78601532, 642016948, 3966440550, 4161875340, 3764174238, 2944905670, 832634369, 2082700552, 3444794582, 962611192, 38510846, 2733538376, 2141542785, 621670923, 3130866640, 1666281368, 3628581169, 3965100367, 2889091703, 762371524, 3752935086, 656901001, 2374421435, 3084212494, 1186140919, 3420046356, 775236355, 1337865306, 2051118555, 713071112, 1946850844, 1427068060, 3949026319, 3075128554, 438166063, 3975561046, 858907746, 26964870, 3843362808, 1461820702, 3090970200, 1037540471, 289966660, 2768763862, 50890120, 580189324, 2911422550, 3684738914, 2025034397, 414622319, 2287243961, 3268939669, 3547523099, 4011963324, 1768695320, 1859343614, 2123856143, 4141054481, 765801396, 359993985, 3668605792, 3613648266, 1778728280, 2547397231, 2456061149, 2562918666, 2903450513, 1994190773, 99234624, 3722083920, 4262323306, 202219441, 4201857695, 3988878636, 1533308334, 401400520, 1069756554, 2457773969, 2892388936, 3423117995, 1944069442, 492036629, 3426800580, 2282483359, 4006366620, 1695364515, 2555180845, 1669287836, 349290429, 778467450, 2020203604, 2218159817, 1450404019, 1278304750, 2412695340, 1592154884, 3868182043, 2240370481, 3859902860, 1008825116, 412233394, 2475457637, 3664379433, 4204584226, 2750684469, 4113507475, 2916584959, 285955744, 739598569, 18278051, 3768126932, 2181905109, 2612988076, 1827656088, 1160380415, 4160443718, 1846086671, 3050604645, 2547108010, 2828666778, 3252702258, 3885923576, 2331974758, 730724707, 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, 3428792463, 2896462048, 2985885576, 1819460734, 21206096, 3560441846, 987100555, 2844904275, 84854892, 1268249628, 3963306788, 3338670067, 2504599089, 65588657, 321493327, 4249673617, 4150876068, 721566898, 2186945060, 922948272, 1502464627, 1426914435, 2906888275, 3454987739, 2609132626, 2073366782, 1058809001, 1226951003, 2624503637, 282722778, 1407178266, 3304346308, 3613017687, 2397594777, 161128076, 1938083248, 3042822216, 3958145306, 1431161184, 4147630074, 1744618540, 3729847703, 2366216428, 2101731625, 2812677939, 3587016062, 1626785569, 3117017254, 3720581461, 4254564252, 2400911475, 750362271, 3062375802, 2182368701, 268751862, 2682134876, 274793576, 2417658182, 2321240923, 4200603818, 1349142841, 4066976957, 1043247680, 679021323, 2933095037, 1621487581, 225868669, 1030678959, 1236344244, 972640788, 1784301152, 578117349, 3509551550, 214420003, 3786992737, 802372148, 3562194086, 2187046946, 3600373521, 4275090943, 2120016813, 4177241875, 3185774231, 2397692077, 1015362399, 2178889151, 3433916223, 1688082118, 1971242178, 236388706, 3802829765, 521309115, 2299816689, 3207614143, 1053195464, 3584561145, 1178690670, 2940812254, 3321982035, 2754825123, 3073598062, 202404806, 547895545, 1188944547, 1056841779, 529463805, 204665384, 850370055, 2063320161, 3724100092, 1180272690, 1398467003, 2814052449, 1311768018, 659771105, 3226477227, 4230080238, 2134344405, 1461172705, 2728018383, 1816821358, 3231137250, 2012377728, 2206916761, 3121807673, 3037967028, 3653505029, 4164239058, 1337501466, 2487452346, 428839025, 3321493092, 2920064796, 2750126813, 3635762100, 2659829309, 1992243088, 2359420187, 861816585, 4182313312, 1389528266, 2890138969, 2195001695, 576635805, 1974585967, 851480113, 1896534852, 3143828462, 4276040597, 3921135859, 2394233682, 2692972118, 2103941456, 3931376544, 3790764632, 2278428793, 3381340311, 3516241824, 2923157557, 1276268033, 3471729699, 2370137091, 2637023305, 4027814477, 3711009696, 3667995314, 459819000, 1002878772, 2658190707, 1189561796, 1831813150, 2874008201, ], &[ 1703326352, 1625259628, 3642322228, 911402341, 2158835226, 939248485, 3607511108, 2863853568, 1611642161, 1312857772, 1839433327, 567060478, 3139863681, 3642698184, 3744632443, 712538472, 2692932947, 576185818, 156934113, 518107105, 2803035863, 2284220097, 3447382922, 2400125006, 3565062840, 160044186, 3644393084, 4196433258, 3391883838, 1115703759, 2380388002, 962895870, 4001772616, 2311278419, 2620271020, 3047789793, 3229254302, 3182628087, 2718480927, 2872538422, 1963990826, 2856537226, 1729736384, 372544200, 1482170753, 3370665422, 305555060, 4060802437, 1456459795, 2848113958, 1036273297, 3245835346, 3355862097, 3242734427, 3313897419, 4230036415, 1425594704, 2428756491, 420147714, 3218149930, 1791217142, 2881741659, 3231612869, 845372829, 1635665046, 1525482197, 3779462557, 2279005731, 626908159, 2963734610, 215448882, 2517668355, 3294128769, 1167990371, 2344651228, 2882002195, 3350056381, 3749638142, 476010196, 2304276366, 1088082897, 1927672185, 3316329053, 1174989749, 1101596429, 3054511229, 1685228241, 2301284206, 2526016461, 684171580, 3869889559, 2606492401, 2114658735, 1419214215, 2779052449, 2594333668, 2225446358, 1211258458, 4029343999, 2816277230, 4098142949, 1987363952, 2732004911, 2516355975, 2365350298, 1747416524, 3951513077, 3526462790, ], &[ 1707334789, 979340170, 3926273349, 2029694660, 686358037, 1260123629, 689471236, 4127009836, 1697317324, 3024229658, 3968952300, 2265029759, 733830093, 2234057965, 799627406, 1641742523, 2511563041, 678204198, 60484965, 1732955108, 1348641815, 1389334445, 3762643904, 3914179461, 4076462931, 3234877741, 2806715190, 3058911852, 3068848122, 80861952, 660210165, 2035863667, 3882844515, 2652987274, 207029959, 4170201248, 1224653886, 3554890284, 323203565, 969583090, 2280910221, 2548241625, 2048045350, 3691775573, 3750377304, 2623340073, 1726676400, 2551234664, 3420452119, 1785849707, 3581615935, 3521097022, 4008380099, 4200557552, 3795120169, 488463511, 3784467967, 2462685342, 1684084055, 1072125823, 765304928, 2900468163, 3209242917, 399160769, 3897765190, 3241572534, 1027203705, 4127226109, 154941175, 1755153596, 4225252328, 1209101989, 2906888698, 1481930532, 2884731435, 2416462752, 553651049, 2247421040, 3347507436, 1936621186, 3156059073, 4059864280, 3191940359, 3872902453, 783002816, 3711047515, 1471051688, 357992570, 1061754510, 3765779801, 4106840335, 3213049794, 1824410844, 2555550067, 1066295382, 3248869963, 4006861446, 3297772017, 3418388327, 2284151457, 766215224, 1091253635, 2070830666, 1435103841, 1408352671, 338399542, 2946293497, 412804347, ], ); test( &[ 3333140561, 2349469031, 666934289, 3646788197, 3373340607, 3062489357, 1781577064, 3971231072, 2027939726, 18149756, 461121573, 1026270057, 4154481498, 3854995191, 2829169318, 2604923553, 1399568275, 4214150257, 1269657447, 527209086, 559827800, 1978807620, 1942748659, 3544969161, 760896836, 694370989, 3323597771, 1950755821, 1740588707, 2716546795, 1636681281, 131422512, 2683077565, 4107286368, 3475458482, 1406752921, 2741526831, 625075474, 1356017187, 660778033, 4078598031, 2127023485, 1900179860, 2413773277, 2442990944, 850894581, 1061627184, 2255197913, 490496693, 400007380, 3092474488, 1228905086, 1949288324, 1866222251, 4084867584, 219026194, 1513678816, 2415719293, 671740632, 2331463444, 1649508273, 622524186, 36198287, 385821590, 3891184984, 3888867762, 823766845, 871168771, 4220135146, 3182319759, 3811051122, 2244319794, 1994956782, 3515960993, 3523512148, 4142104035, 11404747, 3407068856, 2661473296, 1343912700, 1278923149, 1319603671, 3928437020, 2678906106, 1133029551, 3498992572, 3960506675, 2156562886, 2180928089, 4027866586, 3363079195, 2699625088, 10633112, 1776348429, 2657266039, 366882369, 3755249663, 1513004482, 385462618, 1235118123, 2498536948, 2963795538, 373052379, 4211662453, 1125414031, 3132282357, 2555861787, 3949045845, 2694335672, 335933961, 2882374566, 3487775198, 1816750435, 3017829161, 964613564, 159555703, 1822850997, 2275865751, 4158541302, 2501990511, 3721844651, 2781838144, 1795741626, 377630941, 2137086277, 150771080, 3410699853, 2181744662, 3165518125, 156617039, 3099687100, 2159351188, 340108091, 2408725718, 1639869303, 1752843886, 1941447467, 2157946488, 1515895552, 3624132653, 3556726921, 2697391196, 3650363912, 2596921683, 3641623430, 3884964637, 4229700714, 1936259996, 3765315225, 4087511128, 746291101, 1752759843, 699518598, 2102672534, 2335948897, 4138231225, 3162828440, 2881768368, 1254885146, 2977691172, 2250072411, 2614007259, 2771551612, 776074685, 3162839614, 1471012556, 523323297, 1856466918, 4090405884, 813410161, 100155385, 1084252628, 1599609446, 139407955, 4121369443, 1963225032, 2735275753, 100107317, 1064061529, 50786861, 1654370440, 3334472166, 1385803654, 3881645932, 3538258401, 1238925138, 1307191791, 2439918414, 1853442725, 3584719283, 2139830944, 1008033673, 2159214266, 1728151904, 2054140804, 2246372905, 1296034828, 732486414, 4197166746, 2149038695, 2421556216, 2209917678, 2053724924, 3695308867, 2810551805, 3486105675, 979515789, 2065617241, 3321246575, 4275036932, 3028497318, 1883398852, 1301060583, 2486427309, 592113155, 2482121819, 53211642, 3067158128, 2316354328, 2457370797, 1766767168, 4130364650, 1394191393, 893956183, 3188688185, 1875859783, 3686866863, 3294062742, 2146834313, 2406586432, 1574602180, 3208002016, 1067708846, 1620126309, 593911816, 1573785767, 2208656217, 4037191927, 3437397556, 425721135, 3749387007, 407468749, 4203518167, 557223936, 3186718435, 3473504989, 2673679280, 1478635903, 4172750097, 1469776418, 2542136327, 941914936, 3438581078, 3116581940, 3479694655, 159558945, 3809792710, 2458053073, 945749848, 3386290936, 950397544, 148027778, 275178526, 1664599931, 2000347485, 3312866545, 4123761723, 2408292910, 4050298, 4225958969, 2745635153, 1877283873, 90573827, 3031684040, 2275034810, 476532317, 4006527249, 2818283214, 661127690, 2880950746, 3285389422, 965419004, 1273458580, 1611437669, 4165036259, 503131762, 337440890, 1274837150, 3486913543, 1110808141, 3573281492, 3543428578, 4165550725, 79661970, 1465954224, 4160343768, 3753977684, 849800837, 1568284940, 1214508489, 777072754, 3766232553, 4163385462, 3428999259, 906027128, 4231567110, 1070253805, 2975789822, 1794042990, 2937404746, 3315145973, 3978541255, 191961431, 2940436214, 614874984, 868388988, 4078685796, 2613877234, 3380127687, 2664922311, 3262235038, 741871774, 1144269180, 4258950699, 3668553647, 3162392321, 927199539, 557637561, 1114912670, 84346866, 4241634616, 592125931, 1914166161, 1225886409, 722682712, 2163011354, 2585075265, 2786722853, 1993844439, 3433052694, 3718814733, 3881165856, 1749980152, 2115861966, 3664836486, 1644814678, 603487648, 821270634, 3041437740, 925329308, 414275079, 3675481275, 583965775, 3319812843, 270816609, 1752806861, 3191564196, 3197116565, 2440000620, 4074382088, 3346183865, 176525856, 3011091744, 746158938, 1522027948, 930706422, 2574400675, 4141639266, 758742087, 1418306156, 493509688, 4102390641, 3757183059, 2174506350, 3715933078, 3450125642, 1345548124, 3845070193, 1563795423, 1304049315, 2604880108, 1998271877, 4078353958, 966179722, 3401781407, 1708183977, 3890171386, 698646214, 604975097, 4189977050, 1847675543, 2745048720, 1585177380, 3886892753, 2534712423, 1830125662, 796996186, 3789574770, 2219095884, 38427113, 3653683439, 1791769536, 3941686320, 2991883118, 1081207663, 3863639548, 3017351034, 741393256, 2333573607, 2783158305, 2015776314, 3034707152, 1871224010, 1795881414, 928539629, 3211747317, 461147496, 1512738445, 1178891684, 2603472964, 1694950214, 3121022285, 91788635, 2303571910, 3259041724, 1240577113, 827064078, 3847765430, 1254285617, 2609289648, 82835530, 2235563901, 2939680484, 3327268666, 3659752183, 1783109461, 2828509671, 3804296197, 406800911, 2037292519, 941994402, 3350211940, 4004870359, 1105941782, 2367553097, 2440982990, 1468367, 2369391483, 3613174135, 2337161925, 2600055725, 1612773644, 1037201309, 919122459, 1114016493, 670586694, 594109706, 113464329, 4093636009, 307208587, 3876235186, 3370598978, 934478190, 2843794891, ], &[ 2368917411, 3160758175, 1531480588, 2746326450, 3122359045, 1995296172, 310451197, 1100329853, 2141732304, 3562890277, 4172526924, 4143185198, 2397101926, 620168044, 828452963, 3271569899, 2726758945, 1647557222, 2748652901, 1029871186, 1773072595, 1311795717, 2792240418, 3100733307, 298902661, 2608361440, 642743765, 3026335712, 1586592828, 1251923561, 2152803283, 3359308047, 3979690761, 2548031009, 2148504694, 2514911217, 401310800, 1418125404, 2325652800, 716233458, 422262103, 376190943, 1713380879, 2534508846, 2080413009, 2690193951, 2909422387, 2435837201, 176977642, 224472737, 1590904934, 1664979624, 1748982641, 1284257790, 2779881254, 385265989, 1148527382, 800142050, 3595556318, 3950265146, 3931111523, 3399894595, 4200004994, 3727110364, 1510525540, 429323681, 2586345405, 3441619670, 94654169, 2266545045, 1451808026, 286040435, 364003484, 2106693078, 1916214330, 2622096560, 3504008387, 1867458297, 4209615436, 2899684845, 3149003214, 2731979274, 2481557740, 234269740, 1239420776, 2726912636, 1844267393, 1488044058, 1587005400, 145015793, 1637696129, 1990069464, 3053970062, 676336554, 625771493, 1492378707, 1231018082, 3059699722, 4113615249, 2967103567, 3335726303, 2137774253, 273460502, 1561489611, 1227429414, 778315897, 3061631993, 2437789514, 2566029814, 3017507824, 3219754602, 35255136, 1934306764, 1655248959, 3655963814, 2821596564, 1431977748, 3114012833, 3915822059, 343010167, 3704265251, 2691314567, 2602475242, 2459094882, 58857240, 2230690665, 1357656795, 3025543277, 3488674640, 408985076, 80729036, 246851391, 1419653386, 530010128, 3529087076, 3980421141, 4129023783, 1630771696, 2057278583, 2501545742, 790764428, 3984347668, 2562445985, 2262348292, 2515967925, 1103371818, 3735595401, 3210477145, 3387257181, 538884374, 2695206119, 4211749041, 1006274735, 2406061865, 2654644297, 1268724640, 2399689302, 157759259, 564853502, 865205768, 2174783618, 3167863384, 1770172407, 1906775255, 3171669377, 2455086709, 1355327864, 3351895167, 4184858376, 2699533565, 2939169294, 1702277740, 3447680482, 3322351998, 4248517760, 4100425921, 1169799041, 524849931, 1743345401, 3987645088, 3022177240, 3263737545, 3656340460, 239445170, 4089162190, 1208712978, 1453215235, 3390225374, 3337889603, 717395279, 1066458381, 2162685522, 4009460245, 2575879990, 2578471337, 4218103221, 3046325563, 1352991515, 1561949281, 3488911174, 295633326, 1993756395, 3677304657, 796898320, 45622345, 2999482773, 2078651788, 1552765091, 428170722, 1748054862, 4158222865, 1050292437, 249107, 2651086861, 1540178674, 1275557298, 651050585, 1895599156, 4150309716, 2064336046, 1021257319, 2422595446, 3116755258, 2756656575, 2328011578, 3632905157, 2576200202, 830418644, 2430246370, 3913080080, 2371749061, 2683067461, 3611558701, 1603392737, 796477803, 604567756, 1376069347, 1491246154, 2728262664, 4138498935, 3008562381, 1061547384, 285679033, 2358943172, 1884649492, 1783482693, 1010268161, 176114433, 794165875, 2362278477, 3903204233, 326754905, 1988607850, 3187254334, 1749797209, 2986661384, 1759716588, 3137467938, 4067743599, 1134210801, 3799848836, 1955405545, 3881788427, 3097574490, 3844756657, 3183850151, 2496328910, 1468671385, 2888878911, 2306353811, 1498824361, 4152891378, 1588217107, 79108222, 2883552792, 2390312777, 1587172303, 2070384343, 2265280181, 4013380367, 2742676878, 2654283484, 1471778694, 970959698, 1006151052, 1276307400, 2874101774, 3169092608, 244587925, 2402787407, 1635687252, 835856534, 321407542, 2307278464, 2272745321, 2574317642, 729437319, 1682288870, 1482920833, 776000268, 3908963888, 214874919, 4233311318, 1441385448, 2358127573, 2753681514, 467574656, 4139948165, 1538275035, 3244920878, 2576965792, 584068468, 3054546876, 2629688518, 4253271747, 3723872815, 1652066683, 990821089, 2335421805, 1989570928, 240486517, 2872315587, 3869991906, 3870517664, 1540804424, 397183643, 3750033565, 1433260634, 1506168711, 3616651625, 512028445, 3746712828, 3278592880, 2611514549, 1214563129, 1259227909, 1067976218, 3425169051, 741795595, 893688343, 2674408703, 3694908868, 2478153735, 2220661625, 1022546736, 3719214155, 3161293211, 4131981986, 1473264088, 1651777063, 1438502715, 290022167, 59234682, 3458968160, 2552001459, 3451530289, 3800073253, 717882913, 845719525, 1038699111, 3058303772, 1117505279, 3682430977, 2869037104, 2562493618, 960519305, 4147639705, 1817463351, 3166022129, 3200769866, 789666262, 2654485924, 3686362402, 2179867687, 3980226915, 3671542918, 1896992204, 1514962591, 815867715, 3924270086, 4262628477, 3977258034, ], &[ 491933121, 4095154087, 1190388341, 2123387578, 3299683037, 3840239224, 3891252433, 3823858915, 548023871, 3189021809, 130119335, 1406023029, 1691542279, 2101470388, 367145009, 521045073, 1370995123, 202251222, 2377400220, 3656022509, 2413445446, 3583191945, 150872893, 1253881977, 3664619565, 661519973, 672952411, 1111416155, 2582282747, 2253466637, 3993637585, 1023965093, 4055175549, 1721196160, 4271105372, 1844335262, 794907961, 3970777280, 1279126024, 3389187110, 6388771, 3557792034, 2503975364, 1216157736, 4081863507, 1212796362, 22717034, 3517296783, 3126258972, 454147562, 4182968994, 685295412, 2996150679, 840677609, 2775806132, 2555856748, 2855553012, 2971949846, 3057579317, 954558068, 1251032539, 2673204563, 697957636, 1312479140, 2686740988, 2005131101, 664387193, 2169938189, 4081160067, 3469684725, 123152292, 2899902365, 1142266692, 2066860665, 647803613, 3574778631, 1302596512, 678200322, 3509569151, 849744577, 1521760114, 3195673981, 111241164, 623461570, 3571445453, 200189218, 4138515602, 665845464, 4184871542, 1353865395, 2913489035, 3076207781, 2549062531, 3446687793, 685940105, 1430268106, 2488363196, 1172253595, 4151501269, 3292280286, 2025935004, 3388911026, 1080796771, 3386986959, 4175562557, 2440556214, 9871988, 5488492, 4179517076, 908443542, 364965294, 2303037125, 369102673, 1570100894, 3615415741, 3133015360, 2623933135, 211314818, 3377760249, 2285528104, 3096807957, 3213907502, 3633343924, 2065769028, 300167487, 1745300631, 1943126607, 1065862406, 2422304458, 523765517, 57630113, 520436682, 581485167, 527613705, 1677813796, 2698743484, 2448718551, 1681977324, 4183961145, 333724319, 2667028740, 3403027352, 1499647517, 2965583197, 1090547876, 1536215624, 3407325498, 1392474450, 3354142052, 3326326224, 1138672330, 1577104875, 235932133, 3877789753, 1822119722, 305251772, 3802044423, 608489509, 2727503310, 865373313, 3763994776, 3206318655, 88097048, 4241064408, 1171067683, 4250936686, 729121178, 763857558, 450636528, 2096197907, 1427186250, 1251064262, 3036762405, 2966424923, 880639864, 1995310474, 2023015792, 4198637421, 3996151657, 3070092174, 331733799, 2680348059, 2601390369, 92920881, 600583651, 1323663334, 4258529164, 2493258032, 3313489774, 2050494797, 1494880112, 1342788885, 2493538385, 1096813856, 27701253, 2762164402, 3934044073, 2289089808, 721323988, 2246162231, 2514451824, 3095057964, 1921436785, 2847276160, 1369952734, 4246781184, 3442030977, 3930627222, 614706399, 3051396564, 3044240928, 3450585985, 2120836933, 3006035710, 178202067, 736149219, 623937260, 1958379885, 3104814268, 3269365015, 914726129, 2951180538, 3940965189, 1869582492, 2599100173, 1009213592, 1410445689, 1179880005, 3583285938, 1921636631, 434725812, 735782942, 2548761027, 3733379485, 3466163816, 2455801926, 1673952134, 2422059957, 4005305357, 2795894062, 3245947918, 4171997564, 2269244989, 1975479474, 2449387935, 2550893401, 4033149, 3723976428, 3871853952, 3210178057, 2062131312, 1434821634, 1130065536, 4276609753, 41976415, 968125282, 853099726, 3675357389, 3545982836, 1237895428, 88970686, 4259275077, ], &[ 3428605691, 3747865452, 3179948115, 2350061225, 568002466, 1150456745, 398797276, 1289784855, 1713342581, 1243415582, 2262476431, 2640854581, 2126611553, 279688048, 1750838292, 4147801215, 1090003542, 3022523567, 193306367, 3095010320, 4106129220, 2615828356, 2229875117, 1066352114, 1628397898, 370050060, 4157038478, 3551524420, 3356007005, 71309641, 801692593, 3448737794, 2187893878, 3694205688, 3993669226, 1704384353, 437976508, 281233142, 3685881986, 557022935, 2623696682, 3473835466, 2373703925, 4102552649, 3005124737, 1604665678, 2894612216, 113726438, 326916434, 2354584210, 2207672568, 1272863868, 1643657755, 453968751, 3873638645, 2388412558, 2026577065, 3555348237, 2342844423, 564662317, 3301275728, 2205414701, 1980322846, 2111846734, 3351655044, 3986317737, 3746472405, 4065813457, 3783710419, 2063617629, 3337397526, 396000532, 1367889075, 3493608147, 3502046919, 4063752078, 2026966957, 1730343114, 1889308216, 2064908820, 1350757250, 953211432, 3171180512, 3683852864, 2865517189, 9728788, 4075807873, 230559850, 3447666295, 3875782338, 2964025959, 3279832060, 1701408562, 1524777719, 2018628821, 877683542, 2894422993, 2842238026, 2368190181, 2574790540, 3301078931, 519264490, 2640226714, 1382986517, 2712031077, 1268830384, 2018243821, 1374899410, 1932087493, 4236194373, 2079152365, 1069353434, 2794047491, 3019576051, 1360117274, 3615353679, 3816194597, 563906666, 1827758233, 3391740972, 4039283822, 474920421, 602146150, 3520459365, 2217822485, 1815675107, 1257332805, 101198736, 3156910259, 1281759597, 2577040428, 1316988841, 790502779, 2183328888, 3514409721, 3117638288, 2751392867, 625199304, 4183171081, 810287943, 199775540, 2896399552, 1276626819, 3536203521, 3977249862, 1553852925, 1596788767, 4199876212, 4164476281, 1700598937, 4111801568, 897035781, 3318378574, 4049506305, 2522517679, 2296942227, 91515126, 2738354614, 3444113221, 776723413, 2322159108, 258188842, 4014626824, 2677530556, 2630906411, 2348643583, 2619411399, 1783064149, 3684137491, 4249816060, 2342260236, 4186117248, 3931377058, 283592002, 2818946531, 2155019855, 1212182985, 937681548, 520081464, 1686760025, 4003314294, 120323668, 3282730481, 1331500167, 2103184161, 453960707, 3079516933, 4193898972, 279508919, 2459211929, 4262295127, 1413249938, 2652447340, 1521334653, 3641279725, 1047788888, 2569690437, 3517124875, 527659101, 950373677, 562851515, 3518587604, 2668894245, 2265163836, 2975852422, 3168107907, 3219343979, 3364338005, 4122186542, 3517854206, 626303838, 201513242, 4042863292, 4203206994, 154681851, 1046188872, 1014035958, 1565481708, 783475007, 1419399714, 1439418252, 3671223860, 338436030, 2221870804, 275182251, 790279697, 3288665213, 3033639795, 2320556485, 1648356934, 326278183, 429784181, 104482651, 1051376296, 3823684587, 3057907898, 4214146560, 2770254088, 2132180852, 515232230, 3723417512, 3994583184, 1170935740, 565152109, 1486190861, 2906472005, 3154973145, 1571950735, 1391459913, 2972445791, 1670706254, 2522911431, 2665886703, 2875123532, 623767904, 1291947264, 3935970871, 2500309617, 3931020115, 3436644927, 3672390796, 2307254280, ], ); test( &[ 386353625, 2283334827, 253851108, 4279287864, 2561872983, 1000131216, 216965099, 1733322743, 3814906874, 520558483, 2573981410, 3011109093, 1361665859, 2981910167, 2501833654, 2673979284, 2696912361, 797890797, 97183495, 2324611911, 3471887001, 1013155374, 524729310, 3971281568, 2873934524, 1076401482, 1645093822, 423739674, 3400177353, 3716049850, 2858905860, 3351077705, 1478568656, 3370413874, 3966773377, 1660817988, 3770638166, 698194415, 92466505, 399941585, 3301477423, 2578917060, 3012966571, 1915213695, 3062576400, 2979801504, 3838450560, 975685759, 3154985631, 1986911427, 3559636850, 2134674515, 3128102806, 1097660929, 1212690783, 3611467219, 1232001761, 904465835, 671601217, 2829397960, 3910014855, 2035732477, 3262086074, 3077756473, 1064556527, 3095006074, 436186642, 3844079107, 2798261317, 3470373096, 218408908, 4184804463, 2826021777, 1939569756, 1452808097, 1149547097, 316749819, 1631475409, 4023391942, 513096309, 3730431754, 3391919570, 4153138767, 1328779762, 3015228258, 2487205968, 213982794, 1927310263, 897606115, ], &[ 133654450, 371159391, 40768202, 2113895976, 2732923987, 3215138425, 2391931662, 2672734577, 195120416, 939150931, 1941696822, 2919872876, 2564539452, 3080820908, 2846583634, 3349568397, 3465385329, 3550405793, 1724556069, 151917586, 3772273289, 4156003461, 2380288065, 356475766, 4123619567, 1619017859, 3739529130, 490749645, 267879469, 2890847693, 3854244893, 3384266657, 115723042, 103663103, 267682519, 965965574, 1841386548, 2476428873, 6965648, 3347378817, 4174270937, 911558590, 1958087705, 1467103561, 1925556384, 607664404, 2051263137, 3092553737, 3239342455, 1360744647, 331798903, 938411111, 3063265275, 4144610940, 624250586, ], &[ 3712980585, 4273305215, 2588121912, 1482202110, 247010829, 2649827458, 2673293530, 50266420, 3870816552, ], &[ 3140142351, 3638334268, 927590030, 3257445174, 190628332, 423978494, 2125526010, 2335881748, 2011775260, ], ); test( &[ 3451729766, 1173985848, 93029266, 2489920009, 3973680219, 780152687, 1953113811, 856318718, 3314090115, 2569865885, 10849561, 743853677, 1946859719, 3063924404, 3352045106, 101532091, 429420318, 3158186124, 1342100634, 1680882573, 4042659776, 565667221, 989688746, 4541446, 834463803, 3523014310, 3432977627, 1818084880, 3544409611, 1926948225, 3663387900, 1035293697, 285923430, 3096314023, 664014848, 2054069437, 3124990832, 115905130, 1379323203, 2244054884, 2012040660, 1620087465, 1907788850, 132467852, 3020885577, 238576412, 567018667, 3426013542, 3145012002, 2070201540, 1421424259, 2074360440, 810615969, 153078550, 825376847, 2436604908, 1365021492, 288298963, 3753461462, 4215347696, 514661745, 3484458912, 4247537127, 1579462876, 3865189996, 1018915575, 2974009562, 3501816358, 2821759336, 2722697353, 517866351, 632193686, 1959130106, 2570573609, 3726681184, 1695074321, 1803440017, 268435105, 2059636298, 1870796488, 3616705235, 779907146, 3840642834, 3690603635, 889240128, 4220497978, 1506894274, 3744062951, 3031958651, 4062058444, 2309758423, 1411665710, 1638698058, 1784343146, 373693019, 3239595939, 1656022725, 1985062241, 2188775097, 395478226, 2732514978, 2804731752, 4294707867, 2796289890, 4286815139, 2694259304, 3400027223, 2866208426, 712658287, 3005677674, 3799280383, 333964254, 426632823, 1071506508, 424615774, 1216913008, 1528084851, 2440789637, 8647650, 1482353199, 1079815951, 1741478231, 335212928, 3230225069, 812456049, 1107265661, 309740350, 39813940, 1038050523, 3708554333, 2276389162, 3145208114, 286364489, 2078653938, 2343246544, 761958231, 2400118006, 2820784413, 91083352, 868359282, 2976918690, 1899156995, 2927253740, 2971404198, 955553520, 2163090892, 1779162381, 3706789234, 1427323973, 2892945053, 3765307938, 1888304940, 4281185143, 4063224403, 3895821018, 292451283, 1315405597, 1278053061, 2659048964, 1651475603, 2464063324, 2470117886, 885060568, 2223396118, 983203622, 2153273837, 909540554, 11662729, 1290088356, 3558268851, 2470462290, 3816443571, 1219777270, 1663771088, 2059674235, 3741754207, 918293007, 1170814255, 2592844500, 34078497, 868179007, 2916133370, 224466504, 1457353443, 743181292, 2045016399, 4268051489, 2582113750, 108054210, 1045580699, 1021681246, 4287699909, 2442965928, 2358040249, 2188665290, 2493816549, 1868457202, 1538714165, 3141445884, 1886427078, 2413842865, 3754082182, 1242353411, 837326189, 1891378866, 2004934119, 2718308820, 1293740965, 3706050263, 660923758, 4037329521, 1659464686, 3767070633, 2733667846, 1303579884, 720201259, 4178102594, 1521257108, 3676354960, 2861869547, 1694835235, 1663377877, 1033893232, 1788049008, 2131980496, 1380320795, 1706971693, 1547085187, 4249747381, 4022331904, 3773862935, 186851005, 1122661765, 2869769810, 714482846, 122240297, 1990969517, 1505355345, 1418846887, 2157766299, 3944099174, 752193837, 2717991695, 3106584127, 2176113460, 2424010054, 2202537322, 735567917, 2635174646, 57167007, 1501943516, 3981020168, 2264071537, 1811387936, 3230232665, 2056500724, 2470649052, 298208196, 361093257, 837772742, ], &[ 3759203346, 4116788486, 472182301, 1657732406, 1379670583, 1302865697, 694415200, 281678172, 1654699562, 3014506006, 1741431230, 3860463155, 1145719988, 3566676616, 2320845102, 2321995000, 536415919, 2387437419, 3567575351, 89009414, 1112333426, 3147195251, 3149954561, 1503279897, 3064049622, 172526224, 3226367243, 4252316042, 2985921401, 3319920602, 2971463135, 662010514, 2716903751, 3114900209, 4294888231, 2302528059, 2985636330, 4227410510, 523042380, 1128527265, 2237860860, 2902190407, 2028066064, 43980114, 85965472, 1423570354, 370469915, 2799642260, 678694776, 4007712353, 1236341524, 2105667795, 1513858354, 3031596159, 3550734930, 4152331215, 778814882, 736616127, 1334786757, 193672910, 4005017476, 49451649, 274162308, 193472860, 3849716547, 1147344616, 3779102036, 636364760, 49841072, 4203872775, 2917594088, 2516158563, 1718950767, 2409600701, 4112139783, 968713133, 2367692503, 1383637739, 1447827357, 70112330, 1597216524, 1036612170, 47442040, 3535655506, 3217988958, 1524147015, 1542229372, 4278993048, 1177373055, 2455939135, 3977288741, 2323766505, 2631150922, 2494146789, 1766908673, 2014027584, 3170299898, 2200469205, 447095672, 3553741345, 1471247393, 1705231371, 3597764506, 2179927417, 2057038135, 2877684583, 4157842671, 3988568107, 136943619, 1758053719, 133243005, 1316787143, 3912460869, 3007503154, 673776671, 2300353234, 2544200665, 1154464703, 2377559298, 2085288775, 570803259, 1718587627, 1887771341, 2141823671, 812587685, 473768462, 3537328856, 2051785610, 1867482529, 386483431, 2102139021, 3579998391, 1082229057, 4197498026, 2004997074, ], &[3960768807, 1512612890, 3846503597, 4289005374, 3202073567, 4260281911, 4219386150], &[1749675900, 83311145, 2319870768, 2301367900, 1271820700, 747192890, 2232034578], ); test( &[ 1444823481, 1895962470, 1145820971, 951685031, 1619286897, 645659681, 3225126137, 1237595037, 528204561, 3332610202, 2935828481, 3511627759, 3794280700, 504366468, 2867551534, 432130908, 1682537913, 2112976328, 291513836, 2849031909, 3326433036, 1925364297, 3779561553, 487877982, 435659240, 1540143453, 3711236017, 1440132082, 825660149, 1624471959, 1941539144, ], &[ 110690520, 2114031203, 436730283, 2624140005, 3364550071, 806172129, 2495686202, 3508099340, 1915440069, 3196245075, 3757278096, 786923263, 1820433641, 3283619351, 2326488762, 119217121, 3545365539, 3063896557, 1866040341, 3325517573, 713948948, 2863092530, 2356199798, 3131342786, 4122497749, 3637172320, 2586791774, 2794104974, 1738360752, 1591954820, 2633103962, 398797289, 30804220, 2682142316, 1858898375, 2406882215, 999588447, 645011646, 3469603876, 3657151690, 2477958807, 286833025, 1802487901, 2709688493, 2318425877, 3516543869, ], &[ 3866576925, 1873138890, 1768109056, 2705255084, 4241776445, 658244374, 286815054, 153522406, 2020517918, 87408861, 541283899, 2327698817, 696800449, 1357243166, 2373189783, ], &[ 1748815118, 2402822363, 2091637344, 2074482742, 2316188658, 2370992052, 3607116276, 2077769165, 1723590682, 2807481888, 338472032, 1807369086, 4009280963, 3941733223, 1094544382, ], ); test( &[0; 7], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 1, 0, 0x80000000], &[0, 0, 0, 0xfffffff9, u32::MAX, 0x7fffffff], ); test( &[ 2516900350, 3628420684, 45459239, 1513614219, 989392388, 453507217, 1512254264, 2426221826, 1233076550, 244898124, 2764583004, 3329101881, 1699874673, 3208045667, 2210327365, 948719692, 29636434, 309163724, 626642377, 3476255186, 2213282765, 3561515942, 4189534597, 950518908, 139348404, 1259661856, 694161725, 2634491186, 3727710582, 788362676, 3045474119, 4091304988, 2805201294, 3987583308, 1169494314, 1793738933, 1926962859, 143323906, 3767356737, 2736821279, 3155234958, 369913573, 2104538395, 1964464892, 120182245, 1607533355, 3512159772, 428709975, 3273911427, 1151542509, 2860816013, 1136173381, 662332459, 3578077057, 3243603823, 818341966, 1912641848, 3483224197, 605429894, 746864868, 3712846888, 2818736253, 462940792, 3732576280, 1660947800, 1011233610, 843846147, 2308498613, 1878649446, 1442264468, 2962205673, 2832862233, 1244894861, 1156622958, 1582973750, 1574948490, 3846938629, 935089728, 1705244040, 4043433438, 3114254174, 1062986960, 3905677705, 1930766407, 1354562200, 955778452, 2932639939, 249007379, 3763599833, 32702674, 3759419411, 4281057196, 1688108074, 3861261668, 444663411, 2875533494, 971084229, 1671724356, 681694042, 1336342690, 3989885039, 3351736702, 3656186109, 2518436399, 3272921467, 235621572, 641659042, 2119882595, 1983842751, 1488017726, 3187465143, 2506358055, 3348535321, 999852594, 4293611527, 1073384603, 250481194, 4148825621, 3839501948, 3818994640, 1414056232, 2701465891, 499495991, 1361504858, 1308748876, 1650859371, 3722040369, 223548436, 2431095012, 3829963049, 367284736, 451104830, 3192609374, 959276880, 2266256342, 4176815348, 3580491737, 674113379, 4084740134, 883805748, 892822580, 2297912891, 2348080766, 3777075710, 2743249275, 1929349295, 2464988855, 1327032420, 1398791640, 2085211945, 889984414, 883598216, 1429348413, 154972877, 3622910749, 1670306325, 2187005411, 651154286, 2688016708, 1041316505, 2776658464, 161390395, 3846865057, 3267383835, 1010302540, 3607316170, 1418199870, 3954492322, 922710287, 1323651551, 2431904946, 3054195005, 902509698, 1670133092, 1092971517, 1075109776, ], &[ 1426636939, 2291732338, 3067548371, 1958595483, 4265832187, 1189668824, 2839754982, 3301139255, 530760593, 3029188645, 1298922175, 1055363550, 2070850046, 992858009, 1206997984, 1510007185, 2204463849, 2600547912, 3402640587, 372285673, 54684613, 211924658, 2690037178, 1114469505, 374316665, 319939537, 1363579227, 25099128, 2808696886, 2318162131, 1283473588, 4173665536, 1302236115, 2981103428, 364658024, 3500679214, 73401477, 2399140443, 2401409782, 974668784, 3260945138, 700031094, 619920306, 2267288646, 225106679, 2520705554, 760523499, 2971006600, 2155228491, 967349835, 2899641188, 2567983244, 1086821788, 208644014, 2327565301, 3873773388, 1254243651, 3371628757, 1486945462, 3153661571, 3596439034, 3448680976, 2884772533, 2113693162, 3571562346, 3271064301, 2352298427, 2624271304, 2147301202, 1628031526, 2268489536, 2460058239, 3824853526, 1114448457, 1711950597, 2805133745, 3886047152, 1482425544, 3015333985, 1726209429, 1945238011, 2536476005, 1974758758, 3373425305, 2797746190, 1649833243, 2549697741, 2772403629, 1276934258, 1197267921, 480328120, 3145095762, 647795990, 605209910, 1896440782, 2021024361, 4280085434, 384535302, 228210377, 1342562609, 550195641, 304643910, 803682708, 2640613597, 214734489, 3610647775, 3787633026, 3169459037, 2718345417, 1486978425, 4213419405, 2452166506, 2369416903, 2146131022, 3632701374, 857903632, 2077812289, 2633196639, 1727541399, 1445819648, 1663740433, 2573746586, 150961985, 2843003920, 2121435332, 503235641, 2162411412, 2641993335, 2306838455, 3013627797, 187911601, 2832638744, 3245525711, 4114681913, 4248626985, 892023341, 4180070411, 462293938, 2339665566, 886499165, 2680618581, 1275413281, 1653569893, 3506841220, 805196234, 2798162194, 2468871331, 3396930973, 2515921922, 897743120, 2034157178, 2373161268, 3355723218, 3914014661, 994426990, 2992401161, 2581503631, 697892172, 82419160, 2053001658, 3320533046, 3791389127, 1839288008, 270908689, 1413534997, 429338594, 997502210, 3103236226, 2401510054, 2663896427, 3727426794, 2724686279, 3944143754, ], &[ 3845376373, 2532376922, 273377135, 3677509657, 2349096840, 865593650, 3913447585, 3605798835, 2383627001, 256434907, 1598943794, 582857664, 2095029213, 493203050, 4072709797, 2373943493, 3435129133, 3493851471, 1582101091, 2328189763, 853133742, 2400321806, 3544763029, 3255311766, 2487877428, 2345846021, 3540974504, 1867377852, 2499885368, 3386759756, 3964579463, 3290899719, 2797957335, 2863338106, 3380325251, 1361967176, 2820693326, 1270065483, 2316076985, 20080038, 2796142674, 1493193006, 3582143536, 1315905237, 884491638, 2352205614, 3522766470, 1928358187, 1698951621, 4079830723, 3210021170, 3465329392, 3919799352, 4222905913, 255999498, 707431500, 4259794201, 604859264, 3884712299, 2790776367, 3466495862, 1352500875, 1421557254, 3449668508, 339288181, 2600471637, 2364459698, 1593691125, 3908068568, 1590428078, 3967743945, 361284513, 1947639764, 2146594709, 698658216, 2934691142, 3852641925, 2677524346, 3136105113, 3755616420, 393422782, 4055467971, 836734774, 1342622278, 1842869702, 3646198604, 3250586544, 1155965487, 3143510276, 264136749, 764849704, 2833843864, 3628999351, 1603529516, 3414178524, 2241268229, 1653241000, 3792840587, ], &[ 2033854275, 3346500754, 1026391195, 2931755468, 4132970223, 507488150, 3787819697, 4267307150, 2229023955, 3535124792, 2115982537, 3261552465, 1403786253, 4168838966, 2905077003, 3343366362, 4058434477, 3051762274, 2754465216, 2139644668, 2121257326, 147231635, 1411313351, 1942773925, 1518792733, 4026871852, 1608765600, 2674641821, 3388658059, 4045496133, 4161170911, 1328400056, 1288717066, 741487928, 2130937044, 3073981280, 486422437, 2174741216, 4004413829, 1284627600, 1179437164, 1177246499, 2634583310, 2950709339, 3500520165, 502702338, 3556716680, 3168781392, 201139498, 1773610178, 1336109110, 75169920, 4261358748, 3946913462, 1177416531, 1904421971, 529501654, 760059661, 2718436151, 1695275660, 769729199, 1160292778, 1476806846, 913674448, 1863234151, 2549859956, 2693241338, 2672780028, 1641057282, 3939169714, 1414934690, 318354912, 300864018, 400872379, 1081977009, 3047385148, 3103660917, 175274494, 1331622900, 1558233166, 3851938640, 205628404, 992837552, 615234521, 3588694980, 848421132, 513268312, 468730797, 1030322804, 1991013271, 1629772980, 3351179781, 2259742484, 957712992, 1217297297, 2285959262, 947300257, 3115413281, ], ); } #[test] #[should_panic] fn limbs_mod_divide_and_conquer_fail_1() { let ds = &[3, 4, 5, 6, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } #[test] #[should_panic] fn limbs_mod_divide_and_conquer_fail_2() { let ds = &[3, 4, 5, 6, 7, 0x80000000]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8], ds, d_inv); } #[test] #[should_panic] fn limbs_mod_divide_and_conquer_fail_3() { let ds = &[3, 4, 5, 6, 7, 8]; let d_inv = limbs_two_limb_inverse_helper(ds[ds.len() - 1], ds[ds.len() - 2]); limbs_mod_divide_and_conquer(&mut [10; 4], &mut [1, 2, 3, 4, 5, 6, 7, 8, 9], ds, d_inv); } fn verify_limbs_mod_2(rs_in: &[Limb], ns: &[Limb], ds: &[Limb], rs_out: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let d_len = ds.len(); let expected_r = n % &d; let r = Natural::from_limbs_asc(&rs_out[..d_len]); assert_eq!(r, expected_r); assert_eq!(&rs_in[d_len..], &rs_out[d_len..]); assert!(r < d); } #[test] fn test_limbs_mod_barrett() { let test = |qs_in: &[Limb], rs_in: &[Limb], ns: &[Limb], ds: &[Limb], rs_out: &[Limb]| { let mut qs = qs_in.to_vec(); let mut rs = rs_in.to_vec(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut qs, &mut rs, ns, ds, &mut scratch); assert_eq!(rs, rs_out); verify_limbs_mod_2(rs_in, ns, ds, &rs); }; #[cfg(feature = "32_bit_limbs")] { test( &[10, 10], &[10, 10, 10], &[1, 2, 3], &[1, 0x80000000], &[0xfffffffb, 1, 10], ); test( &[ 3347432287, 667250836, 2974407817, 429996943, 2750501459, 981155607, 2784121354, 3415523349, 1074478768, 1820977205, 231390348, 1372589414, 2069009514, 2430571486, 1857553253, 1536218533, 3666738280, 3477095993, 1509486443, 3092180985, 1588218081, 2448257324, 672729993, 2374023188, 2913701567, 2541072953, 762935357, 1333399576, 2676378567, 2962748936, 744662462, 1379794240, 2290146289, 4080012384, 2739115667, 701035190, 4208500661, 2190862255, 3061320303, 3853993751, 2324138270, 2878407932, 3552024846, 3816909905, 3815506441, 1255343574, 1901570312, 91219029, 1399539132, 3118241152, 3325617992, 2881339798, 2520199899, 3667594206, 1853889834, 866669545, 4104229459, 2070282300, 1484152931, 3098893530, 358952500, 2164190448, 4138312509, 727032566, 2750086730, 3119399990, 1390731909, ], &[ 1037101017, 1727794380, 1490452070, 1098486148, 4011045557, 2946764072, 697788893, 2534857680, 3261736561, 2991036431, 3203952375, 678147993, 1718071908, 1324397528, 3227412704, 2808109049, 2498489092, 1483895999, 1974627636, 774482390, 1844543122, 3947438938, 1357670917, 3021715202, 2044056785, 26339702, 2002972036, 2442219903, 3581261805, 291932047, 3070844846, 1561991523, 2591235485, 4062653222, 432295028, 3024980126, 3174836607, 1645982854, 968272899, 3101889669, 3996099656, 1637081358, 2998072999, 2235890151, 553838585, 1688691976, 4092350095, 2065416776, 3709647283, 1072755910, 2385936305, 2615766642, 136864038, 757727106, 2199116578, 2066024664, 3784388877, 896467499, 298040025, 315565009, 4174702765, 3225704704, 23210826, 2346706257, 1990744556, 2040289114, 1584842987, 1498510914, 2668413122, 2503096531, 2005961409, 2272795985, 394426800, 2285275525, 2471642108, 2784697818, 1258928804, 151106578, 3449120105, 169880528, 3307735530, 1735274873, 1875100806, 2033402873, 1707359177, 2748179285, 3611534985, 3379681783, 1722155183, 1210860589, 1583939074, 1413313200, 1958033089, 1382323587, 3321046184, 2567768608, 2706224116, 1925292443, 486456966, 33556563, 4003036360, 624876701, 2847313485, 3451353450, 3432337713, 1567344163, 2879538252, 624051431, 1206504435, 3713613381, 1062990555, 498008949, 1798769609, 3937669287, 4147083150, 2479873449, 1454286408, 665997230, 331654711, 1482116196, 2545259161, 1591656626, 904758973, 1600224317, 3734588228, 2386781283, 4212676921, 1479533912, 2157734799, 3588439224, ], &[ 3380102021, 2452922302, 1962966574, 3357220828, 3890634007, 1037328979, 1799391942, 1004666291, 3982464365, 4257152024, 187444313, 3439720141, 1266693503, 724678963, 3437259008, 1572104078, 4039559445, 3285865736, 3569601379, 1308348984, 1718729371, 284719758, 444404442, 4151851178, 2692003849, 1055982587, 4035467383, 3921915216, 3487944745, 1817447325, 1542763265, 3937726417, 2223825009, 1394339428, 1214099970, 4192217805, 3753293552, 3811191236, 706896668, 1075933013, 3658129436, 156288657, 1259909922, 1889374713, 2941065257, 81950085, 649933990, 3336906952, 2183193381, 1175410937, 2580459452, 3904196981, 2723001189, 1789637716, 2009908016, 3170700121, 18873175, 2237687603, 1424198121, 980763182, 1043721413, 1070004656, 3240828354, 1874904174, 1859325685, 914946875, 3171367435, 891888508, 94557928, 2528939804, 1026794028, 412407977, 1504097351, 2321903212, 4049474173, 2376576188, 2102495452, 1976457360, 2692728936, 3130170922, 2123163736, 3537525633, 1557920518, 2628772698, 453031939, 451448604, 2142259, 3310964267, 2745320950, 2734144127, 3699687158, 784837860, 1503636827, 811700689, 582299446, 2429787592, 1210273821, 2702547973, 2699574096, 3370153605, 1236597584, 1088015704, 2939670102, 165924895, 18853284, 3700200624, 3220442711, 2965715000, 1488424876, 3464105223, 217616508, 315230760, 1429465794, 1372241659, 4248780864, 767395681, 4105247821, 1532652179, 2100932260, 2674903482, 484464190, 3609058420, 1471559178, 4122200129, 4198439348, 1623393770, 4254969136, 2270601790, 4239377868, 588832613, 2695326914, 1952240370, 2369526722, 669955508, 1561380904, 1661607015, 491163324, 4063133286, 339180970, 1218080293, 2858927543, 2211268294, 4242441810, 4166777931, 459461625, 2722830085, 1984526624, 2371328931, 3795073119, 313183280, 3291949415, 1843511154, 809173981, 3006056205, 3286577997, 74654418, 3553288229, 2169290280, 151023939, 1586116459, 3040308252, 4142315068, 2646953656, 4225002928, 4051564438, 1032308582, 4166856711, ], &[ 2427812263, 4051563058, 1632406385, 3107965286, 2723923069, 1032718410, 1300669246, 1686783039, 2900234860, 381961320, 3860838802, 3653570244, 1848772343, 2404802446, 17732494, 2990806772, 1910668969, 3421521828, 1829199569, 2997918403, 3557175274, 3519619382, 740250212, 998547797, 140767728, 1892932539, 668118324, 497299250, 937663333, 2612689662, 4010699478, 389960621, 3786256383, 1395295829, 1276717484, 1869006600, 2093853956, 1555847120, 101097965, 231988325, 1792259822, 29327628, 408838665, 3646864419, 2451151869, 3859710466, 2245716151, 2883931737, 1198282734, 2659505911, 354206954, 3482662941, 3212522494, 4106878300, 1901956875, 645864641, 1078147214, 1797412778, 3856838800, 2428567766, 662568175, 698243503, 4146493635, 150220967, 3723014797, 1944885174, 2282033009, 3395489773, 473095209, 3085161317, 2999589203, 3878818308, 1223719023, 352990164, 249223561, 4143029861, 2622703186, 796827870, 1054862138, 677020780, 1289629518, 3449239587, 3541454564, 3311081075, 583050818, 491332673, 1997521794, 627632367, 2864835203, 2880916227, 233376741, 1067584403, 2454677969, 4048829167, 2955413920, 651548741, 1667224967, 659069317, 4019573675, 3305249558, 3965166031, 2657374006, 1899323245, 2478966232, 2865170658, 819362488, 2414458118, 203150817, 3555808793, 3366944226, ], &[ 2882761542, 785407498, 1124133487, 572386909, 1169675686, 3567625455, 4199715839, 3851396630, 3274146684, 3477301663, 3302596192, 1480559142, 100842294, 3530609196, 4086393700, 1190308308, 4263459677, 1142007717, 2247036858, 4120633014, 2294603452, 2399429000, 2624162280, 1454610696, 270143073, 3957844361, 3046891288, 1549007386, 233535161, 3109659080, 209449866, 498073310, 2626910641, 195499996, 3976787267, 3922992490, 349292363, 3307104635, 365992265, 4190381097, 3755383481, 2478897620, 1546723896, 4001998632, 1128630761, 2676599750, 2475921888, 3233603626, 1483504432, 2551193799, 3557144097, 313815765, 1349744193, 1374844288, 2400211342, 2986607421, 3195157472, 1299836347, 1861689827, 742292964, 2823852296, 448143737, 1667945403, 633976860, 2902355589, 2157443145, 243118113, 2840619921, 2919500120, 2742747945, 845926917, 220468159, 1355718767, 2330428847, 3717678284, 1787470596, 2523167223, 2214932965, 2055827539, 27888400, 2211687684, 526284755, 994343204, 904008663, 487598580, 2347713123, 3532282785, 3549720901, 2459046510, 338578128, 1168895967, 3291681132, 3787087696, 1555047248, 894667165, 1085939503, 4100902874, 309142266, 1088553857, 2096128611, 1104848719, 3907470805, 3414980158, 3260046959, 2704772147, 288217831, 1781865616, 179692408, 1428188291, 2562193479, 1062990555, 498008949, 1798769609, 3937669287, 4147083150, 2479873449, 1454286408, 665997230, 331654711, 1482116196, 2545259161, 1591656626, 904758973, 1600224317, 3734588228, 2386781283, 4212676921, 1479533912, 2157734799, 3588439224, ], ); test( &mut [10, 10], &mut [10, 10], &[0, 0, 0, 1], &[1, 0x80000000], &[1, 0x7ffffffe], ); test( &mut [10; 3], &mut [10, 10], &[0; 5], &[0, 0x80000000], &[0, 0], ); test( &mut [10; 125], &mut [10; 405], &[ 2824467771, 3299124311, 2818671068, 3680778570, 981687343, 2406693669, 659467593, 2993414243, 45406089, 1478779191, 1711786852, 1750419133, 2909274013, 511107722, 3561218251, 1136025710, 993075881, 3516743656, 2114794292, 1997914, 3812643652, 2505455342, 1465178283, 1978590884, 2983823507, 1628362808, 1695987706, 2508198478, 518693670, 835288758, 1012607974, 749782274, 577737644, 2333209317, 4167594129, 2270730042, 3116080031, 2989072664, 3700594452, 2080277190, 1740782490, 2022893854, 2980102855, 751636825, 3922671264, 3391149880, 614930929, 120867901, 2567507861, 1524427749, 2580678371, 2199894921, 1776614185, 1166041925, 1079838738, 110556090, 2831653230, 2555307604, 1415160216, 250952335, 1727168666, 4114643415, 3895205129, 692242739, 1888273350, 3407947612, 2500185766, 2392325992, 454908683, 1510488259, 627605677, 2579656597, 503296566, 732883994, 1804534661, 1024632105, 2582676903, 2186193446, 2035546222, 1537608294, 2871563506, 1842379464, 4285710796, 1145782664, 2168389602, 2821015070, 3799000303, 1910989354, 2712163170, 2373188937, 94374379, 745462864, 1273218817, 599427865, 3025428597, 4170147632, 654664457, 999597566, 1301587861, 785951171, 1404519917, 226625774, 114784173, 1303174335, 1991080402, 953508169, 2955695351, 4272100018, 4152229685, 505603829, 1367830508, 275280730, 1743334800, 136640107, 543638242, 2867205034, 3205072197, 122133232, 2907110177, 2577983454, 4044792269, 1426164254, 3391219052, 4077004042, 60445643, 361888880, 1370511290, 4140611, 1545574856, 337863511, 2696753299, 882513095, 2220102704, 4040224968, 3895008884, 3144563393, 2298197836, 2781817257, 1704369652, 3931316078, 315544063, 3497851423, 3664143565, 952326443, 3938628137, 2331019960, ], &[ 3222658839, 1719980949, 49002116, 576454969, 2480526346, 4090562449, 3826526799, 1957153338, 2225171960, 2687643162, 708981609, 3176715792, 2962973059, 2652817195, 1197341180, 2939993186, 3554367730, 1570613844, 2536409086, 499280456, 3247067732, 1595825640, 2368929206, 663346056, 3132360609, 1474802683, 2339072148, 2202454503, 3728785029, 3203437738, 904057293, 3413710811, 2642403758, 3344563036, 4027597111, 1888090288, 1863907782, 2464957062, 2688706102, 569142547, 397802070, 245946780, 3489512252, 2617239243, 779718731, 179625066, 4023449096, 3996006819, 953561942, 1127504598, 1992436862, 3073123794, 1835220635, 3142367806, 3159289192, 1927251431, 2830198394, 910503635, 2897643083, 2932878381, 1507827586, 3067247947, 885528755, 2017570727, 3134837176, 499511463, 1535166690, 1643153113, 2968177930, 3952804609, 3989699184, 256167900, 567717900, 3896800262, 2310644620, 2351013373, 1964719080, 1905779649, 3311747907, 1340733718, 2870734940, 3144732377, 1107086597, 3017452910, 32224803, 2995638379, 1782145516, 3064028223, 405412838, 4063680301, 3415165225, 1788170832, 3805938672, 1902801261, 2231309030, 1810036873, 3470233158, 2413346472, 3530489706, 110880408, 887205258, 3604865827, 2857625992, 3018122209, 2631997677, 1125977084, 2461114861, 2161802286, 273825728, 2086061888, 541221199, 1806844610, 1376732414, 3802142465, 3535151037, 2954021790, 2116798495, 3735046347, 1186632354, 2833281426, 3457883657, 3962766016, 13814577, 1650009216, 4147309188, 2302630822, 3980940746, 4258997501, ], &[ 671156763, 3522970087, 1803674928, 705095332, 2537912304, 2452859779, 3450873050, 2679364048, 3526396093, 4177976105, 266611217, 1151557614, 2132817166, 3877142811, 507210298, 2972523503, 3073806840, 3566048488, 880991998, 3345680417, 3235170656, 2403723979, 1313154315, 2771932402, 1330267204, 3414255915, 1179382708, 3233207082, 2503609750, 249317411, 2632726993, 130324620, 2032071659, 3005726146, 3875282024, 887247870, 1998016163, 4254819443, 3740865454, 3553274754, 2446121384, 3275444724, 233325872, 539446483, 1087952312, 1835245616, 3627109091, 2510529404, 185630261, 3706778570, 3098183261, 1931085512, 798171652, 3040444481, 1161846676, 1038636293, 3421904104, 2901743603, 300733872, 3719079820, 3468813384, 2881344572, 2125343174, 1936937822, 598427076, 1712995528, 4084208860, 3733468538, 1669487237, 1385196430, 4053752992, 3005943092, 2525935674, 282240792, 4279794411, 4125983631, 2329629976, 2704369810, 1464421682, 1313908108, 1226002425, 1808406752, 3275768064, 3175836384, 931684775, 589156533, 3002460872, 2667576199, 1619914000, 3662683434, 3389418364, 772131109, 3768421507, 3396906380, 2736076174, 2900071166, 538472464, 373492649, 1143475222, 591038056, 3736209846, 856338986, 232250025, 3427987228, 159577157, 485970599, 624042727, 2427226926, 758605639, 309500365, 1623348751, 4085018849, 1073894303, 3272403714, 3990448709, 1089031712, 1648217954, 1406121363, 1462876615, 1399073841, 3264088864, 3357032142, 1754184006, 598504776, 2188603491, 1888083714, 2827226198, 3414026126, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 115], &[10; 1254], &[ 2401497277, 3741262706, 691871239, 1949640889, 266070694, 3295242537, 3037066187, 3875417448, 1358853731, 4158125741, 737486219, 2625351318, 2205206855, 501024225, 2060376077, 1953521053, 3762056723, 163485007, 769999701, 2385831686, 2388009068, 3120433785, 609866149, 1014929431, 4255522153, 3908104955, 1296186549, 1400337892, 2481196402, 1530226708, 1736756203, 4267671814, 3181376526, 4204274026, 2772982826, 171341955, 3239339748, 83269891, 2325049318, 746305994, 1290717192, 1805639230, 1856363646, 3445599715, 1388597950, 2699498310, 246990054, 1396771726, 265087723, 3372840761, 3260397695, 2010115470, 2211074582, 1883962263, 256363687, 4012920099, 2367091978, 1485341992, 1836339208, 1434180757, 2616877872, 1145425491, 1261399773, 3926766027, 3115015865, 1741783714, 3802513218, 4081750672, 3856503286, 2137512595, 1192985123, 1863041957, 700637154, 2503934926, 2021744810, 157763047, 453501781, 1898727251, 3741166728, 105996483, 3390681922, 1127471458, 4229032301, 254843851, 2729237155, 1707011850, 1756734415, 1864969309, 96539023, 220456923, 3061776324, 1741151628, 1199010536, 2099212259, 3095715999, 1369052975, 2575251120, 1821995904, 4169452262, 3299830336, 666854626, 3647011057, 3965571435, 1551218489, 726151433, 1730753749, 750433250, 2084548637, 475638490, 3209308986, 1536371286, 3458731894, 451976715, 1463077982, 3275775647, 1176722184, 946473888, 295088963, 1154092407, 103838303, 3743650178, 4149308777, 1617840168, 3465913339, 4133656500, 186966677, 1624567957, 3264214229, 1285455678, 3951367256, 1685500601, 2890483019, 3692192743, 503129144, 3972113270, 2472468030, 3386552094, 520995657, 318761291, 3652507947, 876136924, 451086694, 2855321222, 557040372, 805677163, 2526778273, 2320694361, 1256424719, 1952008095, 4056766614, 4133706458, 3948099450, 343436346, 4192911370, 284826582, 674589589, 2186532130, 3868256489, 3551620239, 3301954255, 1174676675, 603478538, 275555563, 2405977791, 1847784099, 896249737, 2255526478, 1787445221, 239988612, 1297053793, 4022115314, 3399153034, 1717528213, 1660404772, 3074772866, 2806710693, 1643510791, 3184377187, 1540838982, 134943412, 4022881239, 1840380980, 3861497294, 2510066751, 1433230269, 2045075002, 2415627101, 1223566402, 3367143819, 612631145, 1154322627, 3247079704, 1778868389, 272795417, 933297265, 3458460741, 1389431679, 2907745644, 2086192882, 2684128325, 2650239535, 1784197442, 3949401651, 1783533373, 4288056634, 888203755, 437001866, 1407050668, 3135687315, 3463879635, 1702062054, 1204976730, 4177166610, 739673691, 2277342971, 3478834440, 4081300483, 914246861, 2121339885, 1961961557, 92095006, 2260302382, 2461228008, 3993959318, 2950464602, 1950783601, 1224172324, 2576903297, 576707684, 4125788986, 2560012161, 1956729376, 1629575657, 4036954933, 300086502, 4022406600, 3237472700, 1646970397, 2062807673, 1759249491, 1956866526, 2025198625, 1297980907, 2709447351, 3977405586, 3105592010, 4167079730, 2234262082, 3282437095, 3492171389, ], &[ 414354569, 1366704839, 3104154714, 3052961192, 1917209478, 527538773, 96279538, 131392026, 2197344782, 2544900655, 3721689046, 1511768113, 2703760155, 1445726112, 1858496576, 1575565932, 3793123807, 1385830602, 411844037, 2236175811, 573323765, 2565409615, 2461667516, 3785284514, 4260465727, 3052818977, 1895970970, 3792821387, 4109605593, 1615504561, 3239716852, 1706559703, 3187779838, 3278892149, 3231274931, 4198044737, 1513165468, 245082668, 1270047387, 3396787938, 1940745611, 3740768753, 2072323188, 285189880, 644016853, 3495689253, 1168360917, 2400702434, 984958722, 222994595, 3006232190, 2064852513, 2152929014, 1163603446, 3191172136, 1835493220, 3277922296, 3636603619, 1531000264, 3057499684, 3823394467, 2647235938, 1717867123, 499456838, 4094707383, 2454454468, 3671059285, 3201191048, 2439390676, 3022007460, 4061878398, 4243531226, 3389689292, 558186288, 3777835601, 3123712634, 3503180938, 3691679764, 1701324443, 835309072, 3906212426, 4049064285, 1768153688, 2228746280, 3594304220, 2961136397, 213262897, 80889120, 4109164941, 1704207190, 149603550, 4140450876, 835389387, 2885880052, 439529491, 1516869648, 2050960198, 926155485, 475035022, 1187115633, 894340078, 343754206, 3955497730, 1344991704, 598758584, 4056958135, 2153619389, 2541228501, 3084209032, 689848357, 1722405264, 3359713626, 1572612273, 740065643, 1582253391, 4070651569, 1908850964, 495396647, 4057999777, 3077955309, 4157175191, 2258556901, 2113839, 3880102604, 2790333280, 2943303426, 3912791781, 4284145483, 1840413180, 3097912758, 1064553745, 1126983800, 2256085399, 2448922218, 981100464, 266358012, 1971087790, 1988527723, 237308225, 1936681335, 4258331432, 1348277821, 529864588, 2497818319, 4244738664, 564460927, 1832999941, 65438986, 1185234412, 1316363591, 1608606945, 1000964619, 1732529786, 527797972, 150140396, 2156815817, 4220448391, 1051855867, 4280728484, 1058663428, 4250194724, 1036504424, 3657621656, 189944192, 57605355, 3072751931, 752978294, 1461890065, 2724185615, 141061473, 1466705961, 304569847, 2188875717, 617186800, 3058558545, 1591798676, 88078245, 623288082, 132838333, 1534710499, 2200810995, 2857112538, 3863089059, 3060974440, 16773497, 1918012630, 3327340967, 3661341852, 2395761457, 1535964139, 746843178, 4060399981, 4287382590, 1336021602, 1599090737, 1174816250, 481099617, 918021470, 1173582832, 1368734491, 888221269, 510154884, 1262941262, 2567813829, 1077623012, 2261930141, 2307570205, 2069365574, 3586190102, 1698424580, 615530592, 4037104804, 1283475105, 4214495193, 3288288012, 3585802470, 261207221, 3506861813, 1536248070, 3151134123, 645179327, 490399820, 2479385864, 3709733877, 396138285, 2627168580, 4028642442, 2012757271, 1884810033, 4051927252, 2652348818, 2069059332, 2416554871, 28369250, 1321756354, 3314148643, 2588326180, 3141604522, 1974534297, 4170320959, 2683069809, 1278314467, 312763173, 1481522722, 2846196729, ], &[ 3521949631, 142488398, 2558755806, 546733190, 2792635139, 1330279357, 3430917364, 206259042, 1647608238, 3662226174, 2677354502, 501681320, 3339919968, 736768019, 4258570929, 4202792087, 1651152858, 415339868, 1437647081, 1371825040, 1535867295, 1113678172, 4268196599, 2619516870, 4117420686, 2491883937, 1711537149, 3681498741, 487272454, 3249094136, 2833249206, 1984417080, 608254353, 2280645468, 3395986408, 3532393236, 285299266, 249977069, 1222542802, 1102282847, 2598354195, 439643199, 2126654464, 607909799, 2936741523, 3763227596, 4235714917, 1698786602, 1862433691, 2965568505, 2196568398, 3068583313, 2467355500, 2575639252, 3699104542, 1440347634, 2202871610, 1085633678, 2985993155, 1566387171, 2653399887, 3340197769, 2614511546, 565555655, 4058797643, 1841325854, 671657716, 560998985, 334170781, 85067287, 1935383603, 3452109092, 3454188157, 154367468, 3636444053, 3436201211, 2489786062, 1247734460, 4255062573, 1485745449, 2725636745, 3754874076, 4135899179, 2423709040, 392644331, 2072210265, 339068725, 3933463273, 4288485419, 4212008073, 3733609991, 4120877958, 1466616375, 2958829060, 83050688, 4089523843, 2719660596, 3345635470, 4218331277, 176804352, 2942885054, 1103429906, 1232548981, 3336211973, 2320933704, 2354076844, 2529582693, 3959342251, 1769056129, 3021361560, 1001511651, 766365010, 303546733, 2838329868, 696771802, 2198903959, 3831700812, 4192525926, 2867372730, 3200189248, 2637281548, 3606733360, 2672897488, 2624221199, 1766256987, 3059086417, 3482969658, 2697305862, 415920845, 1575345078, 931452186, 2064246173, 3556532318, 1127897667, 4176776745, 1103206019, 759429637, 3840446634, 2669415208, 4098858695, 3968696636, 474286523, 3603742455, 3683233930, 3910949095, 1016216353, 1693878242, 2936976170, 2258461087, 1543964790, 1257134506, 2705742284, 619723369, 2313052342, 1916338183, 3578695856, 2388468521, 1417556272, 2630850792, 2327790132, 3594026023, 1659979016, 477242076, 1948563308, 2803059042, 2392360966, 2007275313, 272222339, 264018609, 1147760126, 4131679216, 833601075, 1429546506, 3426172207, 1125974375, 3584187622, 1582857679, 1084294484, 2193982331, 3084073169, 892928835, 2823566821, 3544239939, 172135078, 2430777811, 1620416268, 1792703584, 2899867927, 3974701277, 1890638601, 3367278100, 4278027820, 3171315428, 3696212814, 1038269559, 2729624661, 173005716, 3652244541, 724827867, 3530325019, 2203073321, 2587791340, 1909841295, 1412031121, 1429200221, 3614105795, 3265396657, 1362525000, 1906071103, 1060149404, 2733619757, 2675449568, 3414488370, 210765135, 2800530139, 3014478492, 3230858260, 3409460781, 3411785589, 2543986390, 3934724152, 3235965806, 2053739672, 4085596199, 1563589410, 2817526968, 4048637993, 3055675422, 2173262993, 2970495556, 514198452, 1591956633, 3852865086, 124440700, 1002712372, 596340824, 3999538417, 117476573, 2037586050, 3291573274, 1511567035, 1614566437, 3821078763, 961133253, 2796121934, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 9467139676469209549, 590281264913108801, 2444597864339828042, 14864081623018167053, 17247631583397892818, 14553244820490552393, 12829855212365838534, 3531466761266135925, 11372171159031384620, 5870847048926628622, 9193240591510160396, 4025304033900694645, 17261252553070218810, 1960954339685170046, 9689788042403522315, 6777781555383721706, 564338697137211139, 2236230241770389317, 7260612298284603217, 7551831827404764167, 14240930170717885933, 5403113159439788814, 11890192816726889700, 4571074562843162754, 6585174915018781919, 16820621164336832115, 2906428786044704407, 14549789283221663094, 8574533295629171239, 2554371108614275803, 12102140726062325305, 5927759880327312421, 1947106727211751169, 4243634376196439953, 3958901784387088795, 11997496505606868854, 8614259227764305665, 2851316343853334425, 7360014330841540867, 12833167596911644967, 16420023392297553774, 448987443751486030, 1127916262354476550, 998365641524414747, 771182118275428982, 3644906482543632509, 12008471662501141232, 6735530311778854203, 14937996347189247818, 10310266533399488799, 14173112110010990829, 10048196983951682150, 7660343487007291390, 5442254482173747309, 11894682918116055490, 555474340707057713, 5454210195350763050, 6335921756850263208, 11125242160747149811, 5950900297278200050, 4972887779003626968, 15099558014605218082, 8070946285642924813, 5661924633602804698, 4017981546647826153, 3298784914124356106, 1048634509662954303, ], &[ 1601810336850541391, 6414377018375174391, 919960012376992260, 7432535796251013733, 14687204344100976419, 4239980047441451729, 3419961342059496953, 16241811836659790563, 582511433240649668, 246415310737356671, 4213289580820322712, 6570486144808547472, 649071692625916450, 16246395526862594705, 5418002168615819323, 8787804720479728592, 16606257073152622475, 1410262373214068670, 2846556520446018460, 12702224195603835801, 14824788470038136235, 8070823597295684045, 10064047777457825217, 12473928276513608352, 4502242984490214594, 8213242804638977717, 11407293275124988149, 15303970978422100227, 5734015081210218763, 6780255848655226189, 5308681743121306497, 3590094480707706491, 924657275311967241, 13313245703725306506, 13755314570936606477, 1722612846595274627, 11310713460998976321, 17860713973992950196, 4832972642835413575, 6159638888337886550, 16436259186156623772, 8219825892743153908, 12825816757113080127, 17576561025816321316, 16426316569762062979, 7041069634919241163, 14958139263401063299, 8541928253694453091, 14623281385826596559, 5881920493887697974, 2856125878289959548, 13138961086309035424, 1445182795958550281, 989371283719803801, 14414401959190662319, 12694741659414145902, 4944169755440522083, 4850330269090259826, 7263731888738583042, 3847985956261979907, 10886313908655224591, 16884924304355496352, 17434369248195376612, 9624045826924140661, 9440358242723121635, 44413621672380228, 14501853932445164832, 4412509400967439905, 4059150452772511000, 14121559478607349396, 6939247432141568945, 9144772592231287902, 9035665952014395555, 14897716038428818227, 15076823799682351749, 16277606343067785741, 1901372957955104636, 9089098420745572372, 7424125507905187829, 12368330388186365917, 12778631331588513256, 7648700244963873530, 3776028467270636181, 16107369772612157292, 9046543866366629415, 13251838453492673272, 2975138303374961664, 2462966081502544324, 814917744063498594, 13005222969141014201, 5026855542811222762, 2382391535955253463, 5899528506680208740, 13336141787604226636, 2972106516856532181, 14045206722662122716, 13361481863470745757, 1303122885509130861, 2127042842590220699, 6185514996199626930, 16622745329653187578, 1256533115604594696, 11243434057073050028, 9066405370642929758, 4552716624777987017, 1128092841571320177, 3756894170446405064, 3328979948330012406, 15049042231988504879, 3530903968533512703, 17905884378428276079, 3713606437359152813, 9370125751473669209, 10012381228375856292, 6916709082927033810, 17606888822444197359, 10818646898854586102, 9927520028322801489, 17015575684851383261, 15287563104761130407, 4246630569287612899, 6737522138244324583, 16956805675707509108, 10507692348129622148, 1144006384258648355, 4260138925314579646, 14508270375905482517, 3559046762122289814, 15199903498605585717, 16432575538338639756, ], &[ 5592822181652430458, 17506309594623475426, 14050063092843436505, 7714948654849123602, 12960251261153655218, 12293354553127881932, 18236552269356335752, 8116592444680865353, 5788148289215893900, 8971586422059718981, 7830225577778842728, 16542468928391674395, 7685364916096821326, 10621040870461365797, 13017786142160529410, 15623634767986429431, 3570280230795725028, 5462496964935066825, 13096782281304038571, 1028538565298248606, 1306240401949593430, 9752885768751332733, 16834186448734276157, 7637206024963845142, 14347989823115406647, 11694534965309339857, 17506164867360865472, 18226657528377127028, 17113377911080849277, 12836900580850373696, 7624296086468816307, 3241150049341673184, 11432625191496196476, 7201112746916642381, 14159401858377741999, 13042389876849434472, 6539044773109830458, 5626612565019858620, 16855355146181557220, 2896027096805100269, 1749121842377065409, 14486576285464434664, 13003134176160772443, 4520736241988979615, 14386190542886985088, 5203873393963986621, 2767011034432552285, 6993214728799607735, 16219726698174042484, 12883752315794694947, 4638588568194864850, 13671093412063473486, 16507766724668892429, 508640878850638089, 10821378407060575406, 7345992160360704865, 10043908069076742056, 18320857698273010360, 2218460838923946432, 12515547441597943704, 8373193888106171069, 11138535537637434655, 2449630875466873477, 8767699022869197665, 6446940169111329267, 12481583138381941451, 18405856492243480913, 8856983257605794349, 11977198292403090397, 4992072464455161558, 1429124422280954077, 16695629052720642207, 15320583853113777709, 9270873446273846783, 9544568698292818385, 16150036388405871492, 4707553634577955164, 12819651092171657742, 6194167822526464289, 3302239600303656809, 13520149877311082646, 3658928982143500918, 6938149248133961941, 3561482775788486836, 11608588618646326460, 9312042305619109305, 7752033026671842884, 17638989744464665362, 11720586895422616384, 17488161719714908794, 14359533380966089634, 9112047402314539693, 9045007769242360827, 14039981061261051366, 12161985564133395359, 12552005864162233454, 13987473146854769743, 18218863257920884509, 527093394921779615, 10809320813728048297, 9176568449151735783, 16181777654712188911, 3708863559833042684, 15705373009786311560, 12044345266545331965, 15745097802473032619, 3448641903062070968, 7079863925626111888, 10936059842602692227, 3949990826310278419, 8781569794504977516, 2710649351206510739, 8045244454460377457, 16793164706992819994, 14171071447733414359, 6442975288102390424, 13408292761208182437, 18190891873633561623, 14416452326133420106, 11467995109126255854, 10355921853391241663, 3362337025912778005, 12828210017750944427, 6724529289281531448, 17910365619735459537, 18061583666579344364, 7385510916096038449, 14735084634699542626, 2983574817812405387, 1160726944282883582, 2119364765206141036, 6464791768964988391, 8824016806539484116, 8270030586906660422, 15002907845345901548, 5776511587881140498, 8026215921305305807, 4715947225014261487, 1386404302622265399, 155879991043344208, 7029054386547293524, 11220489073691424833, 2733588115435171341, 5063187558440228172, 14208382232307280669, 3376720278729662133, 14690710213721258877, 11094816467682244196, 13929756812886477086, 14698847015580325706, 15992372099283576304, 5818288394714584003, 5038324365106419021, 506432342213631013, 7781480413773762085, 2275557418573742756, 8703301345083257514, 11424227525030059244, 8529590924998378026, 5577211436885609271, 16859602499387351883, 5848360527348246100, 2118117857825986323, 3178709503818913442, 14068618324826971348, 7820101807986528976, 16849757836429474618, ], &[ 10900792384749518304, 1752565570529908396, 3402229115647561238, 2472381872242532960, 15748089475115162936, 1958855681762413475, 12100416912810779188, 12256578057348862042, 6556831077371185734, 15914846823057329492, 17346954154793811255, 17566187606614467459, 1433606366066775495, 9089332045922722756, 10056944581186126460, 5324425019386643029, 5281765195814058625, 1449711238109407238, 5903959110668039125, 3336955200427408551, 751494194154096512, 15350321905800137137, 12407374450431165353, 8705815621686854350, 18038286270431178148, 11671842546699641930, 9343865367071815679, 13401838367914321671, 18365991333043790435, 17428290065100096976, 6040216493892400727, 4224515713015397505, 16578741590625036060, 11835373548777581169, 18413478850867685366, 8453265724386285209, 5394500720474148965, 1927463313122594080, 4177838821929605731, 10680620304882583021, 180005403771618203, 2256408572502279608, 11718426532525535626, 14260315287467647015, 4035759666841010016, 16259497729863184485, 7772704202422133476, 6815813069474359325, 11207378575459431371, 18308033894506293455, 9875145231436590806, 15354934628544213986, 761822562304640527, 7391550101325083295, 4023926600201752832, 922969942182092752, 12110946035817932140, 16574399923422896843, 7087993004495856759, 8299428112066197874, 4589434828506762129, 13978205413565566735, 15675366647238478172, 7819770375827015142, 6823625407675143456, 2042269662440457350, 11521115322912473140, 13703874674141705702, 1295561690992462505, 12464082489717915012, 11378922861990148970, 2076282285705918066, 1390689690731346588, 13670979351308531000, 12980996477862222169, 10496970808504864546, 14015388605987660396, 4171129107047347396, 1656857204469415571, 17492457435753920912, 10132937897450237781, 5065601177732655021, 17498367701449356268, 9552937910825811119, 6213399497134928078, 12865519292113075754, 8548871019474664332, 12973212090641168109, 3018095992673320728, 4102580256148037725, 11411505815957245048, 8044142604358855954, 6163064685377006161, 7676133172626151339, 15177331097378985405, 923128391789363540, 8405355494789853124, 8409013636286216842, 17519952046647436442, 12690425880634822079, 7295927951214020420, 5103171252065286692, 4531269626482776566, 17509133779966482098, 16771567673323510549, 9940518318209913958, 2566490491730418524, 4997841530198583881, 11759671980624847072, 12804335234851198898, ], &[ 11770973102809246906, 5654064914644075203, 14154195031168297145, 3196816914765589663, 13269534898382935070, 6602763211194544985, 16018516851544910792, 3180625223944165224, 5350941027330432714, 6398743157953739295, 1906167046060045935, 3556291732895289080, 17581917949159063577, 11917842024560925369, 5513291200181693371, 2805207190711928628, 10488935147153720707, 9353681503295456349, 11923702266366452872, 16445534228693736707, 1321572029020662220, 2088179387423767363, 2940575338916006997, 5660751381096282465, 9379032325552965866, 6155754375040762615, 17757845483758379498, 4791726927249442785, 2271154604380575561, 2810516188026226067, 17085166475121940699, 99572451658953140, 5696266492111718158, 10862208603440047636, 17394577092287756526, 8594037627948854376, 15384378431083587966, 8688372331869182594, 6898185140759317855, 9871173932216986045, 12528452101456458662, 13557460938391962098, 4450262203153213242, 9384263431241833822, 9013347668307504163, 11311595079831956259, 936915772753461789, 8433063029106192581, 16896552532247465449, 436920621494623275, 17030913520242164150, 9892849888317096483, 10846215292694646349, 8237341484379572099, 16094501558496758251, 1945916543779639318, 18090461816104963907, 4146339453090156488, 16829166437621172993, 3078631608488886297, 4439257821416126689, 7705380192038328855, 3538871580337510846, 13746211561839200096, 11905905983562326697, 13358208869614303744, 5843566918809605864, 9427926296554685300, 14598289187890400060, 11008519655031485653, 8593121017807548632, 9396415039249055836, 6268435325877250293, 17232661262414298575, 72834733148045272, 10210620080322964005, 4785045324389620807, 12743978039683515133, 1532018623508178307, 1626858325392940984, 14509988664710915642, 11484970178386722683, 9637331423956040786, 16727570268905595418, 17007646468471636895, 11784309337440826435, 8264087540904628249, 5386650781848750246, 2634849477861627672, 13571530405202238935, 957020390364360749, 10551951282480361215, 5860903308359481633, 7956790956638521305, 8737258119314118945, 12342128112549159916, 16715653993533680030, 16954242660912593528, 2489318600286989195, 7710331526401780284, 14799339212986303952, 15607538409164651487, 16839239842720015730, 12565794445330275268, 11582072386774199841, 7158773820903321984, 1329934199003039189, 6297267245832566486, 6153026408185751289, 3259942857823462030, 17905884378428276079, 3713606437359152813, 9370125751473669209, 10012381228375856292, 6916709082927033810, 17606888822444197359, 10818646898854586102, 9927520028322801489, 17015575684851383261, 15287563104761130407, 4246630569287612899, 6737522138244324583, 16956805675707509108, 10507692348129622148, 1144006384258648355, 4260138925314579646, 14508270375905482517, 3559046762122289814, 15199903498605585717, 16432575538338639756, ], ); test(&[0], &[0, 0], &[0, 0, 1], &[0, 0x8000000000000000], &[0, 0]); } } #[test] #[should_panic] fn limbs_mod_barrett_fail_1() { let ns = &[1, 2, 3]; let ds = &[0x80000000]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_mod_barrett_fail_2() { let ns = &[1, 2]; let ds = &[1, 0x80000000]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] #[should_panic] fn limbs_mod_barrett_fail_3() { let ns = &[1, 2, 3]; let ds = &[1, 2]; let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut [10, 10], &mut [10, 10, 10], ns, ds, &mut scratch); } #[test] fn test_limbs_mod() { let test = |rs_in: &[Limb], ns: &[Limb], ds: &[Limb], rs_out: &[Limb]| { let mut rs = rs_in.to_vec(); limbs_mod_to_out(&mut rs, ns, ds); assert_eq!(rs, rs_out); let rs = limbs_mod(ns, ds); let rs_limit = ds.len(); assert_eq!(rs, &rs_out[..rs_limit]); assert_eq!(&rs_in[rs_limit..], &rs_out[rs_limit..]); verify_limbs_mod_2(rs_in, ns, ds, rs_out); }; #[cfg(feature = "32_bit_limbs")] { let test_only_verify = |rs_in: &[Limb], ns: &[Limb], ds: &[Limb]| { let mut rs = rs_in.to_vec(); limbs_mod_to_out(&mut rs, ns, ds); let rs_out_alt = rs; let rs = limbs_mod(ns, ds); let rs_limit = ds.len(); let mut rs_out = rs_in.to_vec(); rs_out[..rs_limit].copy_from_slice(&rs); assert_eq!(rs_out, rs_out_alt); verify_limbs_mod_2(rs_in, ns, ds, &rs_out); }; test(&[10; 4], &[1, 2], &[3, 4], &[1, 2, 10, 10]); test(&[10; 4], &[1, 2, 3], &[4, 5], &[2576980381, 2, 10, 10]); test( &[10; 4], &[1, 2, 3], &[4, 0x80000000], &[4294967273, 1, 10, 10], ); test(&[10; 3], &[0; 3], &[0, 0, 1], &[0; 3]); test(&[10; 3], &[0, 0, 1], &[0, 0, 1], &[0; 3]); test(&[10; 3], &[0; 4], &[0, 0, 1], &[0; 3]); test(&[10; 3], &[0, 0, 1], &[0, 1, 1], &[0, 0, 1]); test( &[10; 30], &[ 3099176493, 2686179191, 2963763290, 1498905807, 2459138342, 883505904, 186294937, 1240988195, 1152000807, 3485254691, 3058980612, 4051918579, 84687528, 3474110821, 825051253, 2495113655, 4269053297, 531158278, 2131423786, 735959410, 1116746011, 2099249419, 427789428, 2182383446, 3493666451, 2086611578, 2349523902, 1865831092, 104597580, 720145483, 1653677313, 2449086005, 1225118075, 1458687427, 2284889737, 1178000580, 1204354477, 1109887135, 2302764777, 1833071533, 2749496868, 3989183692, 3112262804, 2143914125, 71393498, 3686808425, 568295620, 856601035, 205234115, 617861388, 102368116, 561132401, 733711249, 2931194848, 1371887453, 2942553563, 977874680, 3567773306, 2225947571, 668306082, 3150218776, 3697051793, 4272816685, 2926797142, 2177250555, 2840203688, 51052169, 1663516163, 3085068676, 471736374, 3127282104, 1358199856, 250868071, 54398826, 2107868776, 1621910930, 1677400830, 20889047, 4180454819, 908186988, 1625301399, 817226551, 4039437379, 261787419, 1484678288, 1183594253, 3154399910, 888455895, 1713982625, 2925178936, 2076694919, 2288237521, 620657938, 2457761902, 2906110636, 649773865, 1387981473, 1600821385, 3512543520, 2803028516, 1584293468, 1443490691, 2589741655, 3170284085, 1902835632, 1603116322, 2850443356, 60694796, 779743237, 4006039758, 3272304347, 2442366350, 3601524312, 720808564, 3291979084, 1675880280, 4139440559, 3672978467, 3938651783, 3257918674, 2077369764, 3027135446, 3940308694, 2533432781, 4105883289, 626796131, 608794713, 810463080, 2363401530, 2800065942, 2679046183, 4063827982, 2327835929, 522607612, 1660561124, 817356463, 2984129158, 146372510, 4293731514, 2558750639, 3948304613, 1448810261, 826590770, 2423032883, 1050524737, 2770168039, 265887860, 3353243705, 2674401993, 1496121248, 2053790031, 1863298286, 1068977659, 2875518960, 4137037281, 2888534695, 473250405, 3368783492, 3797281057, 132028186, 316202261, 381223941, 3366394660, 425124513, 4083952857, 2301832392, 3321645917, 509444341, 361894284, 3976042471, 2957832871, 250836826, 1408114735, 1614725824, 4214313885, 4081964203, 2663894263, 145380453, 2329325761, 2055092903, 126874014, 1000460254, 3910319503, 2561073113, 4231784000, 1042785346, 3511487116, 1270832223, 3456586087, 1210528079, 4119713948, 3299598065, 4178946856, 1623358249, 1001721969, 3964704699, 4133343553, 2193492316, 407893767, 2484237727, 3782842008, 2959959832, 449539588, 2978317444, 4008576738, 3478248618, 98697842, 3986898689, 1622966191, 3594042026, 3280563264, 270713233, 3999415188, 401848066, 623805281, 1710411200, 1801291443, 640646012, 2283134929, 1043531051, ], &[ 3120245340, 1558358768, 2311090615, 3377497278, 2047683134, 1453801550, 1974940808, 1545066418, 2840151982, 2463969682, 2025473894, 697610529, 906262319, ], &[ 4239744213, 626950715, 3916878897, 2974637695, 488695410, 1094975104, 2496621051, 205419221, 4192241096, 3583664917, 511224033, 2016541230, 718692763, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 215], &[ 59488434, 3053025912, 3197673861, 28499967, 919132002, 3254889605, 3510992086, 4155414397, 1401076337, 3663475665, 3859836963, 838452584, 1714061888, 756807500, 721664913, 2122189093, 190377396, 772161692, 337532878, 2801246946, 3347165247, 504261973, 4207433768, 3203836949, 1637702776, 3950126612, 3575550053, 630469114, 2468674532, 3237190898, 2699368075, 2126693510, 2005217541, 990977199, 211751826, 4095342386, 2390539499, 553381774, 1202910267, 3124334908, 3631027545, 3118560130, 3505258080, 2533393565, 3897399802, 1644233433, 2966724466, 1228506720, 4266980301, 1975806255, 3087455989, 430105567, 2496389669, 2559019944, 1343075842, 515604272, 2623722375, 3549762134, 3517683279, 3564893038, 3816995397, 21727446, 2930818039, 2672793843, 1589653728, 2917937865, 665591277, 1222288512, 1197537333, 2425822187, 3647080994, 3180811677, 3800694132, 4006852228, 1392314914, 1823809919, 3315974102, 2004045597, 2557007205, 532899885, 1088861606, 3969820933, 711573681, 3744617855, 3618206965, 3834838995, 601286347, 1494520421, 2007503431, 3672534190, 3437739925, 3075991743, 1108097829, 438830502, 854842946, 798336207, 2497251014, 985928236, 1930130581, 260199427, 3446617597, ], &[4005818469, 1809723722], &[ 1137651599, 55996911, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 178], &[ 3300759985, 47489222, 1596412201, 3681499224, 721942549, 2798268772, 1725678834, 1018213306, 278963757, 2162182910, 4238919550, 1480123217, 3550714331, 2714414047, 1584331762, 3790545549, 2452172382, 3823866136, 3793112677, ], &[ 2532879920, 749327979, 378994598, 3512427187, 1768486327, 874381062, 3750599339, 1824619676, 4102262081, 3872688397, 4080392661, 1233784995, 3967512105, 536874, 1334357500, 533131065, 3802334171, 2688028352, ], &[ 687097313, 233246948, 2670005176, 2918696316, 2059690051, 3559547370, 982825692, 2828616847, 3397764024, 1640472335, 1827782800, 239756415, 4169556349, 1129911247, 2514993175, 2469589340, 3137350801, 1512435665, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 6], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[3, 4, 5, 6, 7, 0x80000000], &[718, 910, 1080, 1286, 1492, 2147483434], ); test( &[10; 4], &[0, 0, 0, 3, u32::MAX, 0x80000000], &[3, 4, u32::MAX, 0x80000000], &[3, 4, 0xfffffffc, 0x7fffffff], ); test( &[10; 10], &[500160962, 3482059973, 3833374734, 2382534866, 7345183], &[1962915382, 2761901894, 931109938], &[3497463394, 501014622, 297308821, 10, 10, 10, 10, 10, 10, 10], ); test( &[10; 20], &[ 3406830026, 653096149, 665840651, 3475733215, 2990001405, 3962996135, 1125790437, 510807273, 2268497988, 3801098676, 4251717337, 4009243500, 3093915781, 2221063229, 1145961534, 1520950302, 4156341537, 4051749345, 1887697916, 2938053362, 1317017771, 2551451381, 1165783725, 1692722530, ], &[ 757200076, 1850648953, 1310285965, 43796838, 2811750593, 2350568971, 1162649579, 3588922014, 843685186, 327689313, 822131258, 632127361, 4287259347, 855554137, 2978907761, 2140676852, ], &[ 1472562202, 467285767, 3874015352, 3774608073, 3547803297, 3252310888, 379016022, 3915526178, 172347662, 1424794357, 2354655682, 1763403834, 1622341466, 1527845266, 321699454, 1968063162, 10, 10, 10, 10, ], ); test( &[10; 3], &[3156053040, 2869923590, 2300216426, 1369503], &[177914576, 1102898054, 1547778], &[0, 0, 0], ); test( &[10; 255], &[ 4077004042, 60445643, 361888880, 1370511290, 4140611, 1545574856, 337863511, 2696753299, 882513095, 2220102704, 4040224968, 3895008884, 3144563393, 2298197836, 2781817257, 1704369652, 3931316078, 315544063, 3497851423, 3664143565, 952326443, 3938628137, 2331019960, 3709840874, 886597817, 2718223965, 2271519236, 1069952925, 2973484971, 694036791, 3948658826, 1091836994, 3976014345, 2590014773, 1030558914, 3050284515, 4064531951, 227487465, 1614818201, 2853653798, 312516670, 1131265287, 1079324522, 2790732553, 2857570668, 2459258033, 3676592728, 1861660079, 3846516218, 2487383610, 820186200, 670229005, 795815915, 4236865449, 388462685, 3530199852, 4067109237, 228011739, 3243897206, 2102622551, 3066279582, 2307396469, 3918457987, 3177100158, 1165801255, 3470877002, 730654273, 225744395, 303984647, 71923315, 2631641933, 642193977, 214491076, 4083126324, 1300818039, 3145270519, 3071074628, 533164498, 2260983885, 2398373112, 2291850622, 2549903002, 2876921663, 2087750942, 3012568578, 2072377257, 2300996389, 1724754966, 3663537905, 2452259556, 681943280, 495483009, 1806854180, 2022877157, 3545541285, 3155213185, 1520127898, 881038528, 2682219847, 2061051159, 4091777429, 2973569703, 2243163157, 3812478845, 2868568231, 538252316, 915738068, 3645567840, 557499318, 586868707, 334386881, 1009292772, 9683309, 1394382805, 1469121902, 3538152891, 192398621, 3298083372, 291538032, 454155529, 3467440904, 107593274, 2581455983, 4068643130, 1289926312, 2620830750, 3599696168, 845286964, 93649777, 211929373, 405469122, 2046160625, 4269019707, 3153165259, 3273675158, 740768718, 1724953971, 4107531497, 3669145824, 2308427932, 4057339865, 30691770, 4215434099, 2209368084, 3410096812, 3930010459, 4058257897, 1401228000, 3205298856, 919645629, 1080800085, 3531478127, 4244298042, 1920158944, 4150416695, 2942997287, 621554087, 2193963845, 3535984780, 1948458592, 1237268195, 4059838770, 4178023707, 2225635923, 1078133440, 1904752780, 1129557671, 2721601376, 3991770285, 2491529378, 2424674576, 4164361438, 1566434777, 3112804218, 2185237562, 2557399204, 967876237, 2243639679, 2436745635, 2376273731, 3848434966, 1970386149, 294413738, 1420657192, 694358663, 647017168, 4094657777, 3013362236, 590143693, 2285757920, 2393504081, 116938458, 891518480, 696284131, 2710811430, 3317562620, 1647436225, 1605219555, 3358343198, 2183786684, 1105785201, 248367120, 1398964063, 3309346508, 3273593185, 2032930327, 2675472140, 557577078, 692086759, 1588022257, 1734092444, 927029618, 3696557822, 3370092072, 2151067302, 2650483754, 3670460764, 2763985465, 1126450086, 3029345718, 1504895755, 3694166108, 578785502, 294874178, 110079616, 1327583117, 2661938072, 2345632606, 3722933355, 656745495, 671269721, 2346516327, 1169529001, 4238866211, 949351039, 3500460463, 4199863511, 2082398726, 1281275042, 2560151133, 1138051905, 468589983, 727511715, 2554428159, 2014177155, 3346720979, 1317583392, 1714879892, 4249909774, 2158352329, 3040382616, 964600510, 319055149, 890296957, 2071841867, 2811829970, 3945344817, 4075668231, 1336582250, 1632615222, 2996499016, 1247703908, 2161089989, 1757474064, 1957983140, 2427088146, 3819098678, 1414774317, 1685786700, 2842967660, 2434489739, 2748571761, 2393986575, 585646425, 733271380, 4096908487, 866235842, 1811304066, 2337315068, 4064326552, 2517677609, 595634311, 929413085, 2556167349, 2814648343, 3447175234, 4171314821, 3354462286, 2190450759, 3693163187, 817168953, 753817804, 2679932775, 2584000650, 511478235, 2858863655, 2320104001, 2367392444, 1724096919, 1152655320, 3131579385, 2076635048, 3557452129, 3931367674, 1011051727, 3910860016, 3742755232, 3977120817, 178461096, 1938068862, 1480470517, 2997286985, 196403685, 3581556360, 3800228840, 2583177118, 3801520456, 1254931401, 3392702841, 1046934176, 412728369, 2864978525, 970771733, 672204372, 1528132877, 2673063996, 740759188, 1840165684, 1821213771, 3111387733, 2386566079, 2682984985, 808050061, 4160818440, 1656303941, 2884647798, 3997066586, 3727980283, 4181671626, 2736389654, 1808865173, 1642983278, 875419327, 3960909969, 3751011271, 2807559080, 1535615269, 2321637137, 2745054513, 3020092780, 1359015906, 2466514344, 591997660, 2754906030, 3487658632, 3722637404, 1613546148, 915678357, 1842708127, 701921987, 1207101857, 1974760740, 2410755764, 3324705651, 3105821672, 335929431, 1887715703, 4035171395, 2815003797, 3632947325, 3664189665, 2211203246, 1473602679, 3802261181, 3699100807, 3964975584, 2757250875, 3240191191, 3824907808, 1582581356, 116402974, 2321914135, 933007824, 136161346, 2857937718, 1044097090, 477414473, 3966936277, 21169877, 2518410639, 1938987054, 4164953085, 3287593768, 96004465, 3316812094, 2635456314, 2931969475, 3535012794, 3954299175, 4188146823, 1054040153, 4020697192, 3043463112, 487456176, 1536604607, 2191156801, 2869189759, 650124563, 54254415, 910946976, 3240585021, 4240104628, 989174439, 3235043341, 607641178, 2910679971, 4072297259, 2664931864, 2560203429, 3992282762, 480443057, 3944140064, 1601223002, 3984987075, 3894479377, 1082591102, 2444518988, 2566734417, 1272094512, 2581007089, 3838472665, 2810473520, 1590808097, 143027202, 1667662742, 3686892725, 228309572, 4091365295, 1107025920, 938240502, 567559985, 2237721627, 1939039548, 3053102548, 3379831217, 3536253061, 1586694963, 931323468, 593457460, 1981974171, 443146100, 11888347, 2403661012, 2646485528, 528884126, 1040587284, 2828170682, 512577110, 3534338212, 1642316111, 124785841, ], &[ 3924577409, 3801138880, 2554871927, 1797946680, 1773117295, 3509783608, 281892096, 2358224613, 4217828194, 1339769957, 439570060, 3151617679, 1384372613, 4141908033, 3034076248, 201556707, 1940999750, 1134129834, 1062995144, 3653931665, 1653789920, 2219526834, 849219893, 3448402897, 890163003, 378127096, 3324725657, 2858888153, 4101277783, 1736762052, 4083759525, 1398269743, 946713296, 1332088349, 1241448676, 820326205, 1554372778, 2902257209, 2531752530, 593903741, 283370156, 1184475111, 4048000423, 3262885223, 3065903568, 2181798675, 970937186, 2831985588, 3318099557, 125775489, 2602810229, 1265835529, 370295842, 3885440035, 332195328, 803805465, 2339766805, 3074827324, 176637217, 2717782694, 3228882886, 2079180306, 1985828369, 1451458086, 2647399511, 653380804, 2816232893, 580123271, 1284828784, 1488365849, 3992136885, 1712696753, 3200712671, 4019248351, 2502831049, 3353947366, 3805407296, 3975182552, 1255379188, 3079539536, 2754826248, 2654365805, 1932758080, 2018940849, 3987435655, 2107608701, 1979416324, 2553264951, 2332482333, 3854067399, 7383141, 2032883058, 209316404, 1509786266, 891329562, 2446773803, 981357189, 289424276, 1563495883, 1124421740, 4019623418, 229810471, 1293459273, 685378813, 763089605, 543868756, 4294383498, 4256223402, 3521141578, 1300426165, 4203249157, 2446225842, 3483103616, 2930204118, 3459214772, 2242535858, 2845721016, 2523036196, 1191008269, 1438983871, 1990994626, 1369473842, 3325530252, 2436280648, 3247037040, 1827745637, 1440370214, 565710731, 918521819, 3174181412, 2021188910, 1292274207, 3161583133, 1940037031, 1320244184, 1944735324, 1624924970, 1914256377, 1558283566, 1557557944, 819014915, 3477749819, 2317549528, 1815788616, 3410581584, 865672422, 3902451420, 47231850, 2052078859, 2128580726, 2861615294, 2875806926, 2504678981, 2922243612, 2567002225, 3176460060, 3501319351, 256937154, 986867411, 2877370533, 3829593455, 169449010, 1762966206, 126552381, 3303194639, 437611604, 2065984359, 215674808, 2549495983, 226202732, 19733282, 265226462, 732006741, 2011526642, 2592527346, 3141322109, 980881336, 4085884669, 2038689570, 3704380296, 1688979285, 1869912321, 1472588169, 3395855158, 2409096192, 2603014340, 2571643809, 1244430574, 2331499515, 234553812, 3949996932, 1906820531, 1849149876, 4204335779, 1113287279, 1165814564, 3834491692, 3992932111, 1545656810, 1251393152, ], &[ 1301325451, 2202463531, 827674839, 2990077551, 3515177881, 1362651403, 481136630, 3397298241, 3518449263, 76128572, 4225087952, 1094548681, 282440964, 1243437992, 2536206935, 1312305087, 2350135248, 1191467757, 772049416, 1651785710, 13757971, 4177684085, 4225218737, 3829973687, 4224488792, 835349925, 807373018, 2003072240, 1998180420, 1893011542, 2772647530, 1845722545, 3927750947, 1582656468, 3929302887, 2309901890, 2219253077, 74452907, 3721812597, 3102504646, 1837697683, 4169869788, 1109227870, 1893389948, 1637025892, 401123956, 2362840033, 3249816285, 1331916977, 11330013, 1790389738, 4046514714, 4242300773, 386281183, 4154390602, 2907471583, 596332521, 1031920105, 1416982457, 936732589, 620289351, 2021344934, 4134683536, 254271151, 3153428294, 2775130118, 767392350, 1524517878, 1803212363, 1935475282, 476597337, 1665283842, 385826494, 1418089792, 1583155781, 904332458, 2167494919, 4213977373, 2749948942, 1366862995, 974249813, 2151831423, 2426239456, 4154619782, 1909704093, 82889380, 1836307000, 1860128761, 2497608852, 302875545, 2512570768, 3465381901, 3664521586, 2113690348, 3208498261, 211553098, 1122435807, 3989762258, 1790955068, 1274985561, 801567833, 206607829, 1945509947, 2689438654, 630881630, 3166357111, 950757161, 2525660644, 2782583030, 2082925684, 4017471838, 2770389652, 3152723497, 2730012549, 375610667, 331640140, 3189394626, 1169047456, 1269402316, 366259196, 659129976, 1835642575, 1109092533, 1409510258, 1055228915, 3865844484, 1951513725, 1561115766, 1535328235, 566121235, 1218990885, 2397023975, 110038834, 410651474, 2293988363, 1341825237, 3049031992, 1068909343, 3433095008, 226980250, 234888265, 3753182189, 712474545, 3392300015, 358854770, 2053632965, 2314494072, 3270641699, 1763895670, 4027033942, 3610557903, 1952033954, 3311300088, 2108677074, 2293958755, 649449413, 1137877459, 1632674803, 3368118971, 4027363661, 3533599056, 4112294692, 1992613374, 2157460184, 2344709644, 3126961604, 3915648450, 163946806, 3452706048, 3278493797, 3569418312, 619110361, 1791108219, 53432167, 1675611199, 3468608269, 3380246190, 3977636639, 2303818017, 2959386722, 4259696814, 2826759181, 1786462977, 974733518, 2879253522, 3102475706, 2731858652, 2537398244, 2096104946, 3000514581, 821433471, 3175348116, 2836803346, 3386301193, 400757797, 3528093517, 689295706, 494008951, 3664544857, 1053036864, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 1098], &[ 1563750116, 2761722522, 2234492700, 664378669, 2289696554, 166287485, 476834844, 2920420087, 2528304999, 1938173917, 3950825207, 4243596790, 2986888741, 3513584208, 1621935302, 3010962100, 97331004, 3497602837, 3156993605, 4246943277, 3773399914, 1791046376, 1330596670, 2066725731, 3080890361, 1411737887, 1547876370, 3080590448, 1532248923, 1435492412, 3448185497, 1125870178, 3236487585, 411921826, 2813696973, 3217407722, 3223519146, 3065092232, 2369951103, 2509352358, 926337125, 3014682136, 2966028824, 1505359010, 1713762975, 4092602064, 637732943, 1302647295, 2902550792, 889992967, 3865589903, 1419953312, 9792449, 3415320263, 564771153, 1688162383, 2484779041, 309493832, 218454065, 3482805065, 3854968150, 917520015, 394395502, 1316087688, 4013170326, 3611139371, 3969996396, 845435642, 1250928392, 3564637530, 3534519817, 4193257039, 1210838207, 1018604374, 1039438522, 3241956599, 283401613, 3791643370, 2495704071, 2807365421, 66163757, 3720427495, 929326153, 1056427022, 2224017890, 3983649303, 3242577483, 2252715700, 3763817420, 3945056819, 2536219802, 2347365037, 1332467980, 932313386, 1344905435, 1546705437, 2064541576, 1511380419, 3830839286, 1360902083, 3503290266, 3917441903, 1833414880, 3943874358, 1755117544, 2923194969, 2839238526, 1436154878, 2022570233, 2627252135, 514344885, 3629007310, 2734265902, 3693108522, 3208247898, 2234133971, 1972552128, 2954899309, 2020593517, 2046949131, 3731357545, 1937584680, 3590346900, 3944796673, 1847972007, 2243279972, 659814707, 354026232, 3897554349, 2861167827, 616720453, 3566033773, 667580062, 2925065641, 1209421025, 2590558623, 4061392256, 1200913167, 951116272, 3677973046, 3503505276, 3890324717, 588682794, 1822470598, 3062466072, 1622960923, 2217967478, 1671943310, 3797078111, 306673750, 416365363, 1127402537, 4051830565, 1295357578, 3597600014, 3944475003, 289083572, 792152829, 1866204223, 154676033, 1521441452, 3508161103, 925444108, 1492828246, 661274700, 3234551268, 2848116256, 2684114954, 1278505794, 1135004416, 1528837298, 903435517, 897822285, 1306717602, 1475128383, 1820901356, 1682104357, 2694156349, 1295051939, 3518824442, 250688398, 2216356021, 3513738778, 1822646861, 2230691522, 3766112863, 615919379, 1974329303, 1351423644, 2477642991, 1213629777, 1378792281, 2617577340, 2140073178, 2191340227, 2566413020, ], &[ 3993985187, 418743558, 1313360511, 1682822200, 2190606963, 1153956890, 2732042229, 1286070126, 662863720, 4186279397, 540453600, 3865675059, 1267823400, 3515598059, 2652841176, 1202274130, 1747727592, 4024332644, 1774850346, 681999022, 3602470822, 2758087563, 1879963947, 3431635945, 246837220, 425774791, 1105979956, 2942553343, 1698889280, 2350552370, 3068812671, 3185616175, 3088938498, 878065968, 4173406915, 3359260462, 3381157370, 170884832, 4229318755, 2494013993, 1549083413, 4140845217, 4084551031, 3363271174, 234069829, 579586268, 409399673, 3823445787, 644521777, 2518846537, 536802144, 2920279334, 18872050, 1166062818, 330384075, 567479240, 242105288, 2256634487, 2099809688, 3182064703, 3455323968, 3796049588, 913224553, 1273986744, 1216752331, 3471953608, 4141617369, 113668956, 2271813874, 3836046471, 1442113087, 1985184453, 1605355495, 4002876308, 3555195054, 1327862010, 2467826608, 2786784068, 2229364499, 4162880057, 2362120653, 2428764072, 3253302211, 4041072194, 3342725375, 5091414, 4236090390, 645428080, 2998645452, 2029624491, 56740124, 2165228859, 3087533984, 1636492749, 2209776976, 3692581237, 607934780, 2356087899, 844604833, 3795358717, 1191407440, 2348446542, 2260870238, 3095317646, 2239633241, 1510395276, 1414456297, 1992793921, 2093060671, 3555947012, 2097207883, 2341507439, 1797902178, 3894103463, 589765482, 4279776370, 1462654158, 1306903445, 2072601153, 2881422521, 41492691, 12234573, 1317588012, 460035424, 2087095783, 1325294692, 639610198, 163158835, 583584804, 2753511772, 3964488699, 2486983401, 2238895215, 1588375790, 2681620680, 4165955199, ], &[ 847465617, 4013314980, 3846912964, 910246757, 2972404216, 2762134840, 1953196515, 4029750073, 4055861164, 1261155057, 4100430088, 2785511074, 497236120, 1367918422, 3738577206, 736241263, 650868678, 2349520844, 3387563635, 741561301, 2423229549, 2724745547, 894805326, 2982356553, 4201925489, 3718492797, 3268940283, 1316855216, 535979702, 1867135512, 2894454664, 1953954059, 3331547089, 3629484636, 809197002, 3453878941, 2710176999, 2236099000, 2474407754, 508610082, 3021250908, 950343151, 2347617926, 3116087366, 387686701, 1840236979, 608794169, 80987566, 2929948001, 3099591933, 1498594442, 976518465, 2412591727, 4182908032, 3079365048, 2450010282, 2281968581, 2243779001, 309401913, 3783895152, 2093682035, 2006514294, 2836109544, 964684103, 1645279117, 3042605589, 3518893342, 3753614018, 3245078642, 976146102, 470909372, 417907929, 584991811, 4141480919, 3596625836, 3530716922, 1149488478, 595234233, 353336372, 638993563, 341110766, 984515266, 1262652725, 843520981, 594906936, 3922870845, 2571018879, 2329734185, 4233366705, 2923004114, 168356226, 666545721, 3625364230, 2627653737, 2717371138, 3344260869, 893744508, 407453169, 1376334915, 1670800848, 320471216, 2114539766, 1671037181, 886024377, 1940914459, 1457430737, 1427559259, 3091470472, 2856003945, 2098123517, 1418768818, 2088924969, 3884270171, 233325771, 2475658630, 3306400235, 1042747488, 2251057616, 288186037, 1069520858, 1716749834, 2851756715, 3107695069, 4055132959, 1800778936, 1250813397, 4225902318, 3898227912, 2436303557, 4099682647, 4014271299, 2579688947, 2474049743, 1793988451, 1750223744, 2886556309, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 915], &[ 685114319, 3257424506, 414393229, 2860628494, 121479429, 2579870766, 1597023839, 2474392621, 3223958133, 1457435159, 3048194581, 3047568591, 328216793, 3688729284, 1474966660, 3229714080, 1674178552, 3622356479, 2813923308, 420491140, 1181947036, 2552013519, 2545590339, 977030817, 1410754865, 418734423, 3219708398, 3814271579, 856825330, 886986018, 2340527841, 1574000724, 1326246490, 2345646501, 3649082184, 1757236341, 3333117097, 4191792834, 771549916, 4014890173, 1767239699, 1537408864, 860021926, 3301854273, 2439584990, 3450574632, 2067936331, 2217599411, 1936116337, 3184038132, 3501118169, 1312763670, 1815889084, 4185547518, 1921708290, 4252193163, 733366199, 1748333822, 3613571030, 2021878401, 674325326, 1834274504, 1974211381, 2155793730, 666543182, 3988638747, 719903603, 4243752700, 3417033998, 578937389, 1954345891, 438767411, 1067012960, 2140679028, 2616731558, 3608791372, 234168266, 115663374, 37715525, 3155431063, 1484074906, 2987669067, 1980354536, 201618151, 2443603378, 442745319, 2757914412, 1266139308, 4142086597, 1989465976, 3517367864, 1441253229, 1295109068, 2757883716, 1533532909, 4121897334, 3324479034, 33282683, 1821922930, 1002968212, 762196862, 13770263, 826603273, 4072569825, 780821896, 788706413, 2104768306, 1607373740, 341951230, 1675442736, 3679554432, 4040499065, 571466582, 467434507, 1883560688, 3831540337, 740943368, 2376257013, 1304728970, 917813781, 3342830532, 3374539547, 1366263565, 1830393744, 3801219913, 3174561984, 3973286677, 1398849159, 369072692, 656722452, 2994544393, 2007585192, 3393313477, 2976738602, 1184554260, 1566038994, 826752733, 477094709, 3837269061, 2769881480, 2709841643, 2163313442, 1223013930, 2855285371, 472880962, 695734454, 3106659328, 336220721, 2424316775, 1005851508, 3997249632, 3813922059, 4109122372, 1011074885, 44571353, 3135429322, 2678006854, 1812501650, 531726754, 684688016, 82728273, 2816638159, 2837354685, 3655899911, 36796549, 4088908020, 1199108102, 2363335387, 2702162409, 1359179115, 4038752961, 4132030616, 3472925013, 918360670, 1612076468, 1617334280, 3399902835, 1794719516, 1364930290, 3884047381, 1715844217, 2543581627, 1948226880, 3734808909, 1123962649, 6885664, 4055662667, 2036545059, 1825684950, 626135857, 3682021373, 2923868404, 1141437069, 301320286, 2038697946, 4203441370, 2625080149, 2416510088, 3453059660, 2196830401, 1003239496, 766384828, 1454135529, 3753927217, 289196672, 3027589815, 386319177, 4286570851, 34998813, 2808034465, 654631613, 2919774640, 3980646343, 3390105294, 3876707444, 342623382, 3063311246, 2951194817, 2409427609, 277380170, 1128962197, 512899487, 1130696384, 337608154, 4248250968, 2538526153, 408791364, 1355901969, 930023605, 619907788, 1270155017, 2669635170, ], &[ 933436633, 2314417619, 1779862136, 2339830299, 3359221691, 1983848875, 2097698892, 1645402710, 49190984, 3806363526, 2374325643, 638588450, 3467828663, 2693267297, 3081019625, 2568134532, 3644457728, 2630819968, 707790566, 1984505565, 3749563552, 3700374589, 2579510542, 4246015133, 1527325532, 3034605869, 2134963426, 3613350443, 2082268909, 3145097012, 497158738, 1750605816, 1683654362, 1392048080, 2595287102, 1859642116, 3880370994, 773829956, 2727575776, 868421082, 910865307, 4010486592, 72360528, 2330397412, 2764112435, 2833247271, 1236763483, 1139702723, 3454679019, 3138128998, 3268622050, 3622582141, 1726130545, 2831795892, 391680447, 1964919870, 2937963749, 260385042, 1893950828, 1182888075, 3460030123, 2590897592, 3391091057, 3700415037, 1619162545, 1524016666, 1313243906, 3716478858, 1054838129, 1929422210, 4093970820, 1243478860, 3650034984, 3598628391, 99479112, 2103638976, 3422493162, 3133671222, 3540259323, 1874029880, 1634209319, 2379655185, 1946213151, 2520479253, ], &[ 4135839129, 3082159379, 2808741151, 2746492478, 1317271925, 1590248590, 1871245480, 883232624, 3985674442, 3997584338, 2338792001, 1776575346, 2531584902, 261625854, 3578066182, 2058830353, 684820033, 3683099826, 1776182826, 2182228087, 919424929, 4095708279, 1423878550, 172604911, 255380658, 4104949687, 3178922494, 1444103543, 1691042525, 1011488353, 3955571774, 2253259467, 3143874569, 377143694, 2390377782, 1070304427, 1715840158, 2972468795, 455414172, 3300053546, 2552753048, 3276730351, 1581696761, 1405031742, 2503564946, 1980393840, 2686153828, 3279538716, 1074513470, 2389426005, 592338809, 348493719, 3669366843, 2086362650, 1888752201, 1485850549, 3098846363, 839653456, 2380177511, 1732519385, 1998829691, 3296699081, 2705709135, 2848494034, 4155180828, 1425421469, 3752183557, 2319259329, 2757221818, 1921158733, 3302049214, 1696454223, 3356952349, 3100878977, 324054921, 2131412976, 1078305944, 698318350, 4151030129, 2259288990, 762849915, 3134288938, 4090864118, 1223661238, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 1458], &[ u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], &[ 1699768805, 1493014143, 2592376845, 190926105, 542951397, 3841252648, 1343830055, 2073311615, 2471501748, 1744126095, 4269392231, 3721081862, 3530443208, 1084284148, 467429630, 306942799, 1316059964, 2458728017, 4217570360, 2624704102, 3521450981, 2608224726, 3040435965, 2267671055, 471534848, 3629410298, 1363200167, 203206966, 3414918917, 3335382360, 1913622484, 1218762755, 3956682428, 1037359525, 5531615, 3407338094, 3864111971, 3057551672, 1048359741, 3074041931, 1285559492, 2147056083, 4091000908, 3900432305, 3556431023, 1451794634, 2393864263, 2505694122, 2968009980, 1048797969, 1048151529, 817832869, 2521994756, 2426006163, 3275649087, 941801312, 1575422758, 361314564, 722834359, 4247301247, 2186131251, 3429599060, 2212966801, 1219957676, 1702525945, 940680423, 333505183, 2493537355, 354760063, 274436852, 1639243309, 2924727204, 4285739645, 4001422648, 105606253, 3112142556, 3975066309, 409404932, 3040839303, 4022137216, 276092852, 3345019055, 1650156126, 169273103, 1920493641, 197903490, 4009771827, 838073342, 3939112618, 3406907996, 4120898973, 2720730518, 2834644027, 3448317034, 3673080760, 1810888516, 2181591183, 2952080694, 3794819074, 676604950, 3118739900, 606918192, 1316167449, 2730639798, 1815557579, 1808982050, 2109827633, 1671035061, 7558450, 1554665087, 520056416, 4218246290, 1161585267, 1878255675, 2486870832, 2088887262, 1303298097, 164712340, 2377403159, 525890592, 3347413040, 1697811557, 3373912443, 1800652721, 1430587466, 630390988, 1443110580, 572173114, 3006613569, 163802577, 3661300485, 2066285319, 3197778371, 1266266830, 3617690296, 4233259050, 3805452611, 2682754452, 1121170085, 4239996815, 2574739406, 3293943958, 589250712, 694935820, 2394149134, 3507180662, 2403010680, 1341157799, 688040930, 1064943055, 1576175762, 2748814503, 3365706670, 2331616371, 3891308187, 3625939659, 834228833, 2747861390, 4238259694, 2400594789, 1064448439, 1457694712, 2503273199, 848323770, 3879018391, 419366498, 2787183492, 1572178433, 1143352485, 4132728989, 3611364165, 2042218208, 4202715626, 4222254124, 3573214358, 2530238089, 3214459960, 199438106, 1990033748, 3797350881, 2039620692, 2196170141, 2867974320, 218349677, 2334991902, 2199173454, 2635928703, 1960733130, 3298739914, 1745262170, 2022670546, 1773942006, 4022957449, 3487536364, 4203797706, 321674131, 2963478216, 482717037, 423207073, 2529853593, 115650857, 1559406958, 2515253401, 4253176221, 1494891359, 54215779, 145831030, 2534290332, 722379383, 3288965822, 3478280697, 114345927, 438460383, 4120362834, 3417392370, 3871144709, 2774707897, 2662801524, 3802201761, 1044223137, 817062608, 964570171, 2627601973, 2648686193, 2728498120, 1589690733, 3285610776, 295629246, 3995872256, 2573726546, 231960020, 4274030532, 3444536058, 3882840099, 2252235022, 3959235737, 3485371602, 1365773288, 33313646, 1392617408, 1844121885, 993486158, 821274239, 2676605019, 3812510576, 3432776114, 495146668, 216967234, 3172737228, 3417198461, 1629229154, 1821830950, 1340735610, 3211463144, 3560398150, 1050123642, 874441227, 3169516221, 2783241998, 99843330, 1175436161, 2825581162, 3259620982, 3350111857, 1606464613, 1911911079, 4127551535, 3229370127, 3828823712, 2744685123, 2859704702, 1106636072, 369804135, 2989745290, 2768260583, 3275220193, 1104864623, 2290350054, 1049972093, 1592992521, 3598788064, 3350912109, 2954408081, 4230173468, 2901042813, 1614811380, 1930643862, 4235254046, 3520012632, 1160373738, 3249852125, 923106635, 2511906301, 2055083218, 3193170540, 843255473, 3274357481, 1069334404, 2160558830, 1247811861, 1960090087, 1260505746, 273679994, 628898405, 3731946987, 3821611375, 1479367897, 406962212, 1951524671, 151905808, 2697376333, 2827375721, 3738186384, 2398267382, 1189552516, 3271847863, 3695955312, 839640611, 391563549, 2851226168, 533382637, 4005632192, 779063015, 972248299, 4160069328, 1551848869, 2901173293, 1788886403, 7742522, 1152154246, 3162815742, 3933026131, 2093435260, 293643707, 537139803, 166837469, 1353454767, 647497063, 3056417780, 4130500121, 2563320691, 3004161478, 4266673072, 1525376895, 2692236203, 612090721, 3803502732, 1472545930, 1285255741, 3563385061, 354899818, 3985901869, 1077755288, 3764626839, 1736779714, 1388617683, 373259603, 406803142, 2250511459, 3661744930, 1712371282, 3755716304, 1001652736, 1437790589, 2722214878, 3509431789, 1045623456, 1477384299, 1529044191, 3485492831, 777726776, 3111945645, 87325680, 3674053827, 3777562490, 2467629264, 3920974102, 1118313420, 518650065, 2779852693, 3938004723, 351444334, 2301762313, 1696242659, 915234550, 3426770333, 2623516555, 2367502869, 1764681654, 3012087599, 2970366387, 1214823325, 1416807413, 1002068525, 902786108, 4219021066, 3685197343, 627261248, 275319515, 1048180581, 184895903, 4054317442, 1164782510, 2969271356, 448119019, 3225650628, 3586253056, 13844949, 4265695528, 3156376136, 2094798072, 857381027, 2996376430, 2313835774, 421527113, 577824604, 2027011737, 1936987926, 1716119129, 2495416975, 1566342556, 1974265475, 100699876, 3818621196, 864167162, 264481383, 2779691848, 2519054856, 356904428, 1425193402, 2029146838, 3791198981, 1181286580, 2106244436, 4074963191, 1156817098, 2002193018, 584536494, 1252244761, 3576951572, 2017920970, 1604293290, 3010503460, 1201492606, 1555982397, 2556964369, 3428819809, 4168489079, 4171058202, 404720822, 2480856269, 1813722898, 2093837710, 3164853594, 3430042720, 2545385245, 1253945679, 2067139932, 1049755734, 4162345450, 1330690410, 2567802121, 3494789533, 4027320953, 1359086506, 697144652, 2171860846, 1885681379, 3200348033, 779514913, 3892431243, 3292022849, 3206367229, 141294896, 1247341423, 1286221471, 2030904879, 133272354, 1441910339, 3982161305, 2696309947, 3801057775, 4053369379, 3233631762, 3173498696, 19486328, 3282282805, 2117833655, 416934200, 2476837107, 3550654071, 835595228, 2784887835, 1849982594, 1215825494, 120169702, 3628150453, 813273996, 3164608875, 2585886019, 3468354974, 2529654702, 3937155612, 2948360421, 3839784361, 3626976122, 3884938510, 2182665318, 1984077334, 3592802345, 974314095, 2658877268, 3320515471, 3220348329, 2057524489, 3330170042, 1859432638, 180803537, 1712128971, 2278567221, 2233418239, 2029256422, 183505236, 1671411329, 207176584, 2036148357, 2313901094, 3988184694, 2436690588, 211724920, 3032356297, 3340214696, 117345076, 1500403818, 1365050888, 2323945197, 2919933846, 3023641486, 599606728, 3628676259, 1581385213, 1427038937, 807104522, 3978940995, 3629484758, 47151915, 1224789415, 2759574529, 2839954032, 1315873434, 3168847820, 1610459325, 3726598118, 896590825, 2419742875, 3430079217, 3778931934, 3687222980, 332999836, 1043316180, 4189864653, 685607150, 3695627010, 196835870, 3941428183, 676485145, 986494888, 1049128467, 1888162207, 2801108003, 2947315222, 1894059346, 454711531, 3589935315, 1803051198, 3655137369, 983821858, 3081875497, 3803393764, 2428490033, 1679378736, 246071720, 1483050983, 1382043974, 895942294, 2442009263, 68111122, 1626094364, 1007851423, 4064984075, 1533309302, 3360582064, 2740180933, 883885210, 2989133634, 678055765, 2661431250, 92559696, 1032783565, 22899740, 2361882691, 2393385114, 992907787, 3373832203, 343145453, 1165167516, 290287284, 1707286378, 634939907, 1875541381, 1297012104, 3157634640, 1929967474, 1519414443, 3881762803, 2681995819, 1775206192, 2755218098, 3910825543, 1860602393, 1832806570, 415596447, 2186155905, 2791826564, 1816344456, 4023525966, 243382839, 748453584, 512556810, 3922005623, 1061467548, 276741166, 2229273612, 1738207771, 4128865796, 1984054190, 1324502121, 2297662740, 1222235249, 3182342363, 1665477641, 2147473685, 2421806673, 2322492629, 3459362839, 293710623, 3706578807, 1598383617, 3666283079, 1011133678, 2189483475, 938644636, 847088475, 195518118, 544927250, 1332819612, 2366720962, 3995717811, 1985243513, 948001598, 634366393, 3212334449, 4000960249, 3974258285, 4013403482, 418753555, 1101654041, 1090819318, 1675158019, 3683152713, 1204756106, 3841987860, 2260147808, 102023094, 238154404, 533560693, 4086126380, 642534617, 1632145671, 1006291121, 1435987078, 1313038313, 4186175328, 843360286, 1839639056, 1353648132, 2221125136, 3732368512, 3339185832, 662563454, 2744469998, 1331973650, 1343096038, 3251304725, 3601378173, 3422205067, 172706680, 908147887, 3728762498, 3795011129, 3044217576, 67031330, 2499472547, 4147725229, 2529069049, 3741434149, 4201254595, 3779595001, 42489268, 2053548825, 985282652, 3980674776, 3248961215, 3376433654, 38182659, 2602101994, 1925777855, 806407427, 2317267910, 1380652265, 3701097444, 1220848862, 2025812459, 3482791264, 1753046753, 598143651, 2616070898, 2479609320, 1868138196, 945178683, 3832269010, 2314371642, 2400732781, 2048750780, 54093670, 327716566, 3334970102, 28861124, 4118278855, 3714357594, 541833330, 2000911880, 2666752754, 499968133, 1548730866, 1814521338, 2487369228, 1138644653, 739248636, 126190040, 3978033791, 1817304821, 1225794794, 2871919793, 940731169, 504076316, 995594649, 3329757458, 2846947354, 3891292748, 3959049218, 2127628616, 810346662, 2271875593, 3880247584, 1164066271, 1750445267, 338639562, 1699074958, 959302743, 2956590033, 867798509, 627451437, 3510106002, 2473252158, 1509206912, 3352377241, 3802665519, 2147957812, 56184472, 1718654148, 3672624374, 3511414009, 2682054173, 3922316656, 2414259176, 1496250883, 3967344788, 3214918603, 1624761599, 2724006253, 978208159, 1113357772, 3487098045, 4270740839, 633061828, 2261921853, 3462914738, 1530768806, 1364864048, 2876294873, 2510835104, 4242821662, 2474987381, 3633586220, 979932165, 4155189874, 2525154569, 1335483880, 639760624, 1660790427, 2226690500, 4135706134, 150618757, 593063255, 3258479253, 3728374085, 3007800944, 3679685736, 694904689, 102552353, 1428747995, 1176285881, 641509845, 3270509599, 272169854, 3047261598, 1287492008, 3351279172, 2404469180, 459751592, 1333387953, 735177161, 215716037, 536597459, 3665567562, 822815388, 3602692316, 3168229037, 1054147108, 4146505577, 1580773238, 1088501561, 3629868530, 2978204283, 3610240644, 2223237525, 3153209697, 448561701, 895234984, 1592358205, 57857782, 851682344, 4181525201, 1988009551, 3651424110, 3655716749, 3787661870, 2925252014, 3708997912, 3309060091, 4188222270, 1673276025, 2192528846, 958274526, 1258766035, 3525801758, 1215614889, 3051826051, 2354974337, 1541657893, 1271755575, 496264166, 2626820052, 936952045, 3785181421, 1294902361, 1958901697, 1604821791, 218282718, 2246953449, 538193118, 1919817946, 1243076425, 799521120, 279827487, 2722496365, 4019574708, 990869332, 2181585056, 2705356597, 610157367, 4119248513, 3343890269, 3121261960, 4085000780, 1022014736, 4240976369, 2817889889, 4075894073, 560049242, 373205120, 334714162, 1892034277, 51733004, 1776487312, 1265439929, 529285398, 2048981213, 1833004632, 827301005, 1648393113, 4281016481, 2048185380, 784315559, 3245679058, 3513265995, 1369181664, 4269143782, 113931975, 1398194472, 540409306, 216516009, 2627890586, 3694809441, 2573974797, 1396611872, 2646365320, 988053471, 84792061, 963667070, 2114579379, 3564371585, 3893773169, 4197725787, 2378021272, 3273607654, 1738197474, 2402812179, 1278628015, 2317178895, 3160300732, 603898477, 1287079046, 392763347, 445875312, 318139180, 1903469143, 3585413276, 885483094, 1674549044, 3911672420, 1575430246, 1867282418, 2115410448, 4189894183, 3512999498, 2833930381, 4284803257, 2594863293, 3053172089, 442647755, 2456733276, 3207156565, 1248598530, 3135346976, 2511563725, 2761431370, 3552853409, 3064928230, 1668127734, 2151818142, 1573413967, 2528903432, 2255579949, 4086541389, 1008056620, 651544198, 4099217330, 2147059795, 4189054906, 3160158060, 3084688966, 1829066970, 366751766, 1086760266, 1823021570, 3035776668, 3725549438, 303569416, 1637955291, 3070457854, 2756834184, 1117066585, 2815830458, 1229154243, 978732541, 3666377420, 2646214554, 3084488532, 2757010866, 1756160517, 2475577838, 467860047, 3125348085, 990351000, 3303850398, 1120462919, 1920695807, 2980611720, 142863055, 2378648555, 2707355873, 3519612422, 3266835497, 2512195477, 1941306513, 365527762, 592954943, 2552580189, 2606501901, 1933724422, 2729691276, 28289820, 3017728757, 3650961916, 3696374759, 4228636665, 1241471494, 3355869165, 1455843481, 2403725149, 829901760, 2618851388, 2623034964, 2752098284, 962418521, 964160519, 1174284358, 2043907493, 848741317, 2520932535, 53649688, 4228750878, 3694987632, 2694050164, 1097113047, 1221352269, 3997202409, 2858697527, 2874569664, 82995009, 2474870382, 608319794, 2793235942, 1762763510, 593568738, 4140942494, 3399850155, 3632742015, 1495257590, 1987803076, 3040781503, 4185563847, 2095097137, 2984180367, 2385825018, 276655462, 2186224265, 242785858, 25971964, 960934651, 4259630073, 2869516035, 1099452330, 1108772812, 2208212843, 138327599, 3047969124, 2406962821, 3234115454, 2013090243, 1253595634, 379537518, 966627542, 2289594467, 3820588844, 3307962615, 2251395356, 1086612191, 2411787092, 716861072, 488537062, 4279016079, 1024670198, 3162868375, 2993498248, 318817475, 1204805151, 2917216152, 202544687, 4055006202, 2166902046, 777932120, 1954248209, 1436706075, 392807099, 3560992122, 3690436481, 4086456539, 1672219993, 718561908, 1329443408, 41759831, 3830929272, 468558885, 2850993192, 1203438200, 173099196, 3100895691, 3212371819, 2727223413, 265778175, 1306749738, 1945372531, 3409735664, 1829111612, 73857789, 1967847248, 111126146, 1941085939, 2157306354, 932967688, 1524770100, 3562820290, 1815865396, 618928660, 1954521715, 2791055048, 1472833149, 2745012885, 2590581857, 764068138, 3810864565, 2068720839, 423731968, 2781829173, 671016197, 3626671545, 578830019, 2263629204, 3196999908, 979097653, 3960854009, 2652280123, 2014180777, 3212225669, 1901793582, 791028866, 1535961645, 3425925260, 1728220859, 906987059, 1320441954, 103740087, 138471919, 2751991892, 3763793139, 1930252328, 2302777807, 4166228863, 1898736904, 2679190175, 1902812084, 3494412200, 2003091421, 647088593, 1275527793, 1571337951, 1296166873, 952173553, 3873665860, 2863399704, 1687749991, 1019315430, 262989750, 1995806398, 3977438566, 3065387570, 194327737, 2433254350, 3852864758, 3086016127, 1848276257, 872733825, 4293282833, 3839899541, 1287823073, 2617969813, 1718468275, 640897626, 2796238324, 2471345611, 3038580905, 1824539690, 2178312422, 3642675324, 4168141874, 4093223514, 1058804935, 1645178046, 3320651392, 2520046692, 1724703883, 821899232, 481110608, 2492775734, 922020621, 2923405792, 3392950548, 76237439, 3904683294, 256504571, 727968315, 59423766, 3078236506, 2465675774, 2942973709, 2930861254, 2455418902, 2986403934, 3056400696, 3599867309, 595501194, 2042151651, 2763604081, 65000450, 398696589, 3026108404, 4199385741, 3349995311, 129915120, 2486649758, 775313272, 2784093349, 1582665104, 2775814261, 1584569957, 2195691054, 2575677337, 3244017237, 2457054839, 3897157261, 3195991591, 2030342150, 3727062402, 3706029571, 1179068874, 94821848, 2230566710, 3669075264, 2425831169, 2438414276, 1720898289, 138216286, 3807634131, 346144588, 1780209932, 694722911, 297024116, 2795490416, 1836169972, 2915769303, 591959219, 2377921602, 4158591575, 1182337705, 231710027, 2274507465, 2241869617, 300827881, 4150367209, 3585840019, 4167111741, 1023965277, 1674153048, 887595527, 1601672948, 1765479313, 4065509701, 3915091640, 1297871355, 3479625154, 2831036720, 3785201761, 1221164796, 1647627464, 2551945655, 1768755122, 2079192478, 347747455, 4045445050, 2954562195, 3495749867, 2264323612, 3116421719, 2118887029, 432847575, 3976298717, 30083877, 78749340, 2656872748, 3171516677, 944561854, 202462342, 339834758, 1199920281, 488096540, 3380838041, 3470160182, 1755758102, 803450485, 738480354, 357618351, 8551902, 812925594, 3218358491, 2918846080, 3174772578, 822290689, 51990462, 3350891640, 2729296982, 2723805763, 3540769319, 1145905142, 1754039404, 4289454572, 4153901476, 1336760032, 2717506348, 2938254966, 1476941276, 3458786809, 2378593502, 1537570700, 476723401, 1207306095, 1092996894, 1187377294, 3666979500, 3948059620, 4150681293, 719413909, 1118296918, 3753268822, 905882560, 1638884713, 1259563753, 1063300422, 1502884288, 2285369399, 1874551590, 2040785043, 1775679918, 1144757520, 3854262168, 3821097323, 282903083, 197139966, 976017372, 3684024526, 3746169537, 108937132, 2444167905, 3366454633, 1002555971, 3961863482, 1693512346, 4219424106, 2731825813, 2173055658, 3589347522, 1180897582, 349307065, 132252171, 1286185962, 2906205536, 2843606103, 27822898, 2481699072, 2948630201, 1774092707, 1171123309, 3404061713, 2905420837, 2351973006, 3971568799, 3248015376, 2297549471, 2624549152, 2864086950, 2757145051, 284981704, 4116824485, 786416861, 455364234, 810567289, 1304615212, 2127708286, 3066389895, 3906659140, 1621009466, 4060905456, 2498550541, 2021095657, 189923381, 3015918335, 394513300, 395082750, 1997152191, 3900214471, 2076041515, 2762331608, 3059576182, 634566583, 2077367009, 239466771, 3512081528, 3492757347, 1343506243, 144657866, 1186993011, 2942254420, 3813487876, 640076454, 3107898063, 4057144155, 2951251839, 4059833593, 2265248880, 2051308911, 3838642653, 1427962716, 1138966813, 1697969541, 3885404282, 2547515947, 2006341172, 1338884621, 3673075887, 2250647769, 2303605646, 4029999904, 2015620651, 429025216, 4230380695, 3438741639, ], &[ 1988498380, 3050132581, 84001963, 3445692001, 2734783387, 1774219496, 2162032114, 770345120, 3457703796, 3559428633, 4257360364, 1090466591, 3567817053, 2497380424, 3534691541, 1279435419, 2742018051, 2205075879, 641106, 1754923528, 58973331, 1715000559, 1117715270, 2272741525, 2115935795, 1483835360, 1296235, 1796957756, 3968651424, 152068196, 176938861, 570875261, 3336099773, 1193842175, 3048757774, 764666488, 3843941623, 1548464729, 1897867882, 2878929765, 448571520, 2406065734, 3568376411, 108079736, 153179622, 376615879, 462260105, 973865240, 3413391101, 2811718165, 3572533591, 3909460695, 3134008033, 3897396582, 1040616570, 2998174467, 4068999806, 2523162074, 948788147, 2600716643, 3959424266, 2966714, 526886335, 3296693425, 2243375988, 4143935802, 1111766991, 1144066805, 2311007495, 1010976381, 845073483, 1135483459, 3990880342, 294797346, 2679966602, 2533930988, 1664564718, 268281267, 2092673357, 469524764, 3945653712, 326073803, 2694037849, 3507600917, 3290201609, 121045908, 22654279, 1505718612, 551101589, 2556674091, 3163892929, 1910818775, 3418844366, 3372741206, 130020156, 715267628, 4274925122, 1048026555, 2835427841, 3505581892, 1602295761, 2414351668, 1553499591, 4229635398, 2519192505, 2021787900, 2301738189, 2691817702, 5305850, 1565221152, 3538706617, 3057801765, 2874943612, 3131932103, 2612726193, 1166707551, 2820888127, 3160538692, 3124232750, 481384322, 2617755783, 3630694751, 1672329146, 3497041986, 441500257, 1563794131, 666530710, 1149258814, 4274365529, 169180791, 4187510295, 2714548495, 3562799169, 2904591043, 1774457729, 800521106, 1411048330, 2663300606, 22655328, 3774883767, 3819965706, 3800295936, 3668492475, 1379825015, 4213938165, 1132023495, 3760304231, 2917225913, 189390673, 1938798483, 3140766517, 2153396970, 1928404388, 2785977327, 934591575, 2405323840, 3637359453, 981340132, 242310679, 981811654, 2288564752, 2987925303, 4031514738, 197635692, 2859303437, 2533609681, 1151769485, 2644644277, 2635940433, 3366453887, 4277743333, 929550085, 40133408, 1833321431, 2429701519, 1464545187, 3066929948, 3904082769, 373116082, 2430829492, 2571513045, 3885018135, 603068030, 1172828581, 4065558289, 1163895893, 2468059427, 1548489900, 1717402470, 4016751470, 1013738008, 1034029588, 3482329597, 3435207029, 1673410325, 397717038, 1500823297, 1911172810, 1420629560, 3358784452, 1312197637, 1152173034, 367120884, 384630941, 3440282377, 2522765605, 1597847376, 2683717257, 2561199311, 639683785, 3817861808, 463544224, 3991704969, 3376721583, 105154089, 1533594425, 335823085, 1107739913, 1452695631, 954081147, 1472744072, 109401385, 3210541127, 1847806577, 327707567, 2422910059, 2867854042, 1286261864, 2777291397, 2491134001, 1866376440, 1442628329, 1148774257, 327348168, 796722022, 1651402005, 2839518531, 707220227, 442580375, 614584592, 4054371638, 313021875, 3191805300, 2207878775, 3933190445, 2035546077, 381129617, 3161098198, 1019615010, 2743759521, 1458405016, 1891243747, 3502084250, 951344904, 2669441803, 966435550, 1450947158, 2445618755, 2629179958, 1786188217, 1157343233, 512400759, 3058846955, 1691540553, 3902487730, 53457416, 827127510, 109080803, 2065162700, 2595989450, 514516885, 3571421189, 1946474067, 3695201586, 529285628, 2120794437, 1831163308, 1518439076, 3361874260, 3805558145, 2288973775, 2352901588, 4206307376, 1343461937, 1115914255, 241429811, 2386351727, 3283851422, 1570726296, 4171557460, 2197857248, 3493510408, 2254067927, 3407035296, 1925479341, 3186474620, 953208782, 715061374, 1181448968, 1220358590, 1370257748, 2925654278, 3323438388, 1322650109, 3766704524, 3870430557, 3257441173, 2439781482, 1554488089, 800150735, 1514175574, 3153400949, 1583649143, 1280421056, 3882604400, 2181270798, 2782475677, 3148486479, 4071326639, 1764147111, 3505719068, 1862656169, 1261162987, 2211270974, 3217710591, 2927566184, 4232715549, 3582658271, 1363726747, 3233373581, 3022128605, 3193686951, 1851291940, 2618042857, 2848579530, 4293396464, 1928252986, 528145280, 300907511, 3891802439, 1267856769, 1165928777, 4227625628, 540012700, 469250948, 966533455, 2875072197, 2230103081, 2000106078, 3086794985, 4244235827, 3081744548, 3713073740, 2925851679, 2315339278, 2558156736, 3723155058, 3227292432, 2941681952, 4041413976, 2097513703, 3042683335, 3624088138, 3936977773, 2820887559, 1664662915, 2334141648, 4092839529, 274159708, 4055649255, 3512716978, 1365039076, 3916570667, 2158939813, 403036637, 942532489, 378445989, 2167306547, 753402418, 1193358264, 3877024670, 3743152347, 116435136, 1948333248, 569098908, 2922999784, 917671206, 2718173867, 1010784137, 1804409345, 2242631895, 3989814639, 2044343096, 723486672, 1841507274, 2333301606, 4260854855, 2763867469, 2805327422, 2351089720, 1719837442, 4008440919, 16200186, 1228294632, 3833322142, 151876299, 3340352893, 647820547, 3228338641, 3940895065, 1697980005, 2505263582, 77077868, 1311758352, 2346165371, 2652028800, 3480066477, 1481299332, 2948248752, 501377681, 3276784059, 4102724530, 1207318829, 2947644680, 3069480791, 1116349810, 3395241135, 3570300879, 3836110678, 23881082, 2523984619, 86893874, 2919930037, 3241130876, 3697730978, 1459589531, 486161579, 3036213671, 2106273230, 391770200, 1135761788, 3542580424, 2902564186, 4169447111, 1908429065, 498329772, 2010302804, 1930725702, 1614128757, 1901201146, 2340750074, 2621544559, 1554979341, 2490973900, 3039157328, 2525878574, 2064002895, 2981842962, 513591182, 48663763, 346106995, 1067873617, 1664056855, 3497080122, 2640223678, 4006771320, 1595836468, 2008498009, 1036368219, 238997308, 168075897, 876079826, 2934854956, 1075263443, 3803042525, 2802898866, 2169905202, 3377165843, 2465797619, 1978983742, 2322310751, 1590628498, 1459551643, 4156365433, 3054380889, 1819890111, 2928185712, 2553214234, 3066671630, 3394771139, 1734126526, 247246953, 3320484300, 579355057, 1177404814, 1327413352, 2035170753, 1052379386, 3339678481, 2430828601, 3360847369, 2961791848, 484983472, 3181472945, 3105431626, 1283580906, 3703197182, 1961222326, 3649286491, 2664156595, 2335129028, 230491131, 468504878, 3710487036, 3159611165, 3544126878, 1088644958, 2961497435, 2785759884, 1537524580, 563225344, 2114093362, 4212602497, 1169631938, 2088081811, 4006629680, 3089709789, 3749609771, 1969435408, 1786420402, 3870446123, 2169555554, 1571013574, 506991779, 2174983408, 2376333115, 1813451470, 2875689985, 2056697043, 2022446139, 828430986, 710475734, 785980495, 505758805, 3139780897, 3708680832, 3390307357, 2434318195, 330093210, 3019701899, 3546042185, 202048370, 3017694172, 3813711930, 1950710894, 2336832114, 3123649938, 3799964456, 1278675670, 1776925346, 23381263, 909581672, 3084101661, 1592521095, 3095643203, 1245783006, 917301336, 1175072489, 1493603974, 537178477, 3098462691, 848961674, 4083634813, 485866548, 2460787176, 1957075662, 1653349530, 193311723, 1510554197, 615759127, 3054909658, 3810118423, 3275067767, 2822189856, 1822027915, 641453111, 3902949794, 1707895715, 187255999, 1547540130, 3996925138, 3744594623, 279929032, 2815355330, 1197018567, 334914949, 104288985, 152451615, 2257137946, 495821725, 3891425071, 2698902656, 4248123041, 3994796663, 2283493355, 1792145295, 771358160, 57983054, 2699162282, 3252719646, 901108453, 21411013, 1214186627, 3971974103, 4284646962, 505661368, 2014789373, 709655680, 4019528811, 3456428712, 3896941342, 25228952, 3267679573, 2554048052, 1140488725, 796840032, 1008803984, 1769445882, 450164846, 183418978, 1557823191, 2205206958, 2186287277, 4041341207, 2277585274, 2647704834, 3299210809, 465486816, 81165601, 3688958209, 4134919427, 308497409, 1670228519, 1054621084, 3997139209, 642331675, 877436795, 3750152836, 2099953927, 2407318768, 4064392686, 3499776748, 2890558934, 4257002037, 409497686, 1871363314, 3488166608, 368834184, 683374402, 3315975032, 3919319927, 1636872711, 3746724350, 411713899, 3127168268, 1541472093, 481068370, 3914726958, 3809187727, 1019234471, 4257529799, 1795024406, 2169201644, 180192691, 3146544995, 3086567728, 1371853848, 3442647104, 1956649571, 3221872492, 2599010979, 3825880037, 129532942, 1962882180, 2981643769, 501519665, 1104150124, 3577388513, 530338682, 2379351921, 476796974, 2079075205, 523122306, 4175790511, 1769173929, 3684943051, 203952644, 2367960727, 2956929713, 724249999, 3868724734, 3128867062, 788369620, 183457300, 4030548412, 320471199, 818557389, 3673114423, 3427092352, 965641427, 4165737446, 546271097, 3179039741, 1968478116, 233505213, 3523513681, 3185397073, 1639252860, 192368536, 2476919576, 1286359266, 3468793964, 3927932569, 1554017778, 381977140, 2630912557, 3248408028, 1380148387, 434027229, 3679247941, 2320186711, 4049616334, 1306803801, 3657216807, 4072237788, 2409653033, 16652557, 777239076, 3435314631, 953899982, 375200832, 3240441496, 1403201300, 3463532889, 2152357282, 1492290956, 1756116611, 2979347831, 157726282, 597994889, 3571510881, 4022595441, 3689069225, 3371053456, 1105664287, 381184864, 3760869170, 2128986335, 4138730626, 2108903255, 3330167716, 1193420433, 4081108869, 2371248791, 2008259868, 329286806, 834934063, 1587339743, 3835392552, 3027794970, 2946227510, 2759445311, 4153403869, 3246082301, 2169502676, 4274409702, 1618245891, 3538641406, 2440237498, 291928949, 1309678695, 2248858018, 1259269551, 3062553916, 2375747923, 929738114, 3593316299, 395934754, 1240422334, 403599738, 3596058407, 4199195184, 708535732, 1045565478, 2985960024, 2935035441, 1902361158, 1360356647, 655818324, 1464367881, 1402852252, 1605910196, 1553177831, 2270937291, 3867336542, 1242299751, 4201495317, 1894193944, 2952284338, 2983597634, 3331327699, 2688007694, 1534358324, 151501193, 874435351, 113820939, 3053243228, 2461547215, 3493411866, 2931307581, 243458129, 2419713971, 2259098050, 4153522826, 1347753364, 789286836, 3723853308, 282228699, 31083181, 212832201, 3992535406, 3841973318, 3150180785, 966530634, 1983757001, 4224102508, 4103842551, 2315916292, 797697662, 915301841, 727577536, 3413485655, 917582931, 843507358, 1529131982, 1843003612, 3002449886, 346610535, 991891575, 2565267970, 3912371508, 2710618386, 2330075864, 2735484155, 2546043717, 3241769509, 2210455214, 4169254026, 1482724431, 674379398, 565771066, 3142137141, 515638418, 939683105, 1345730468, 2404207571, 249108973, 1883806778, 2156914196, 1564711040, 3370156804, 1857590348, 1147780810, 3733908955, 2181248732, 1904993207, 3694175594, 619779923, 3491824168, 3612713452, 1216174279, 663457690, 4014509322, 2569761593, 14109664, 1828397087, 2936522368, 4158885908, 657033012, 3173212007, 472151655, 684251460, 4075235611, 4224354174, 1004777987, 505536516, 1454022092, 824505586, 3067613896, 2235424889, 3665322087, 3481517352, 2363451123, 2771040650, 3235122422, 1154036889, 969497501, 2563704447, 3797108, 1395020021, 2762840789, 1908946824, 3014468569, 925225402, 1138335619, 3624023401, 14380823, 2839985590, 1786726385, 2046596657, 862236402, 214661254, 79111383, 1583211853, 1641485501, 2710635102, 4088715922, 3860998541, 1323605849, 3597942622, 1491675000, 1599602967, 3388494990, 3354632479, 2528582795, 215618636, 394082738, 1141528681, 1784788922, 1221028471, 3234711669, 904205099, 1676230442, 3127792899, 3994795553, 2452526892, 2165805680, 1335373003, 192721187, 4240993835, 3133423197, 1689272558, 3673814847, 1422539041, 3736049673, 1833170900, 282944559, 2338828666, 2779222702, 3327509347, 103394172, 3158363803, 1906876457, 2941521396, 4107834947, 3417951529, 880661309, 2072508295, 589009441, 1335393037, 4277398556, 2493403024, 3409655003, 3109850219, 1180552996, 2381399690, 2298638016, 3501746890, 846617313, 2905524779, 2707401285, 2041915730, 2296396459, 1041902038, 889847207, 1989421094, 1389388870, 3827587250, 1783862700, 3828138938, 1868614698, 4248902541, 3581264817, 3916285777, 1776264454, 2214767964, 2937276417, 1736659895, 1395637227, 280854206, 226975266, 3550562380, 1121092319, 159004679, 3748222278, 1260252989, 1422903228, 3336410666, 194417341, 2723594163, 2281242077, 1784282179, 1034680840, 1402111826, 335654645, 294940873, 2853511062, 378984905, 2532157416, 2195182123, 3873081897, 1625154299, 260395831, 3540310196, 4273320806, 2622305394, 2711543735, 200100618, 3414809217, 2926348222, 1329786033, 4245332557, 3574371092, 2777917577, 321179615, 3642895588, 1496048120, 797710555, 3671936109, 2438718323, 45015662, 2137354414, 874208938, 3450439142, 1916685905, 1662667234, 2856738964, 3829688032, 3404462996, 2848035045, 2061762938, 1260861712, 3010572066, 3394836279, 2342878342, 1271875691, 4111464444, 2126598368, 2380694046, 2430271490, 1145499017, 3787409979, 1555528697, 3376084869, 642452482, 2589187231, 1081315770, 2087941360, 3364823763, 3805619618, 486395332, 908395706, 2499268457, 2420556587, 474512813, 2481646657, 3492741661, 1968018988, 1074530387, 2014914730, 2803826225, 3220982875, 1438277839, 2775829138, 1528403642, 3794191286, 2608342366, 410785526, 2637600256, 3490750019, 1440381245, 814635701, 2260916755, 2650730282, 415890751, 2524080685, 3474570208, 2446217936, 2397550701, 231181743, 736834280, 1383997656, 1496783958, 623278112, 1645711091, 2659144562, 2936379758, 424018844, 1549465529, 2669736270, 1664977313, 1523334854, 193915346, 917134660, 1861003559, 2211424692, 3594457673, 521847126, 2663400187, 3341032570, 1640978768, 3374727890, 2984430165, 3295971473, 3727310438, 4148801904, 2931771022, 3471915299, 3774018978, 243266066, 719450229, 786371556, 1967721517, 3662692002, 2660462613, 3406551440, 3689369626, 4170908863, 927580754, 1492537107, 1444056133, 934562830, 964303678, 1533941876, 4122966823, 3705199737, 1112924448, 95199848, 343531614, 594658489, 808416147, 2905432520, 3584653211, 1387698320, 3110254075, 179755886, 2585492770, 826193502, 633023598, 1166009098, 1290016012, 672935203, 442560997, 2496163987, 4194310358, 522918013, 4222433924, 1620670288, 1584642952, 1110116518, 2050444989, 3738181405, 2449666200, 1322361471, 3346873860, 1704204055, 2765918523, 1681401174, 1734783149, 2990922980, 2845873797, 2655480068, 1134013632, 627992748, 2305459149, 890878648, 3702690433, 2308583593, 1647897272, 3079544696, 2470471677, 4040208261, 2073585273, 1793034905, 1713771355, 2220715251, 2553773388, 1442482611, 3113497415, 2768408881, 1270025121, 1399831313, 1630862433, 3377364946, 1442504714, 2789927137, 3191151633, 2578873407, 208337033, 3096561372, 3943415949, 3118056636, 1664092654, 533371474, 1132049460, 1378502069, 1205939688, 2646775436, 873517579, 3647947118, 4249353240, 1234899426, 3562671303, 1028908207, 3806236229, 2688126461, 2379248861, 4273316716, 1028554767, 960050373, 34458263, 2497415615, 2000699114, 1654490516, 3970420809, 430138864, 2839090700, 2992085491, 2048751357, 747829112, 2102051019, 2747342438, 3939874657, 204736053, 132477025, 2895769009, 4049016784, 4006488678, 3010059929, 3869487365, 820665998, 3637576575, 1400083196, 3176270933, 1580718861, 1862589245, 3687231820, 2811111046, 288642712, 2708675068, 3659920550, 1043267703, 2675211709, 2471783225, 3908671780, 1796097076, 3884725302, 2618455344, 2727437605, 3198512809, 77833978, 4002905580, 2475905855, 4285041054, 1379496519, 2810710199, 3524329171, 2422823286, 3888601537, 1921960588, 4141779429, 3945205304, 2680621131, 4186120628, 1952951538, 2875169441, 3303243339, 574383361, 2010030917, 3924461786, 1497240891, 3972138842, 3082719894, 700821923, 1225799274, 39941891, 1579154501, 2895091775, 2026419054, 3180814760, 1239600240, 3443816247, 4103641786, 1778116375, 1356356349, 3003002432, 2464906412, 3106084532, 620250446, 2199567717, 4285388064, 1443224417, 1183702872, 2361871288, 2889920918, 151923059, 3665604400, 902272748, 3673929087, 777413599, 2880183228, 3116820884, 12649513, 2151951398, 2517689255, 2603024997, 1540902312, 413276528, 463295145, 1270795006, 3197387059, 1235198896, 1591251569, 1536841283, 183104831, 1099570929, 4157586543, 4245916264, 1187513801, 2725120513, 2263045835, 3616676335, 1441932591, 859970322, 1785738074, 2632201495, 3074325275, 3739260875, 3210655551, 3115242275, 2776972168, 1857654859, 3388697322, 816121986, 4034608581, 3645370625, 3901309336, 3655082618, 694485749, 2189293828, 4003306605, 2104718709, 2248125819, 1242466666, 3425122185, 2526773969, 1997783773, 3366295660, 3638946293, 236310604, 3074020533, 1544508523, 2720105666, 4275312048, 2125511485, 2928099726, 3115904574, 1659470574, 2302631502, 2782437446, 3351759933, 3997936888, 2966997408, 3158966556, 2819300721, 1647111112, 3003598038, 2858959466, 2179510155, 2584211049, 2202151208, 3064305858, 898246753, 1503685985, 3011437597, 3645693595, 2240988222, 3440343576, 4238868402, 3504605984, 693969911, 37266154, 53849195, 240646457, 1676768678, 3078948456, 353299888, 3398599422, 1225876435, 3474721352, 2919885255, 1645273187, 1329251097, 63136291, 3744051145, 3578975497, 743346836, 2992151082, 2097992510, 2029339826, 1064760489, 4287623009, 690583934, 2137261889, 2523731672, 2989051237, 3080671706, 891097198, 705467787, 3974619780, 2507988307, 3580098689, 2900468355, 2065761093, 1093422169, 3699292714, 3679511724, 1376356943, 190833907, 1757023356, 2392875706, 1341718208, 3312756053, 1335629721, 3842952633, 1585023162, 3483717351, 1166983906, 3797224124, 2704194560, 3663191348, 1943345575, 2900370013, 98538425, 2337184175, 665720157, 3985681094, 1514818198, ], ); test_only_verify(&[10; 100], &[123; 20000], &[123; 100]); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[10; 17], &[ 9995257893114397114, 9401504468144459131, 558615837638945228, 10733662027974786928, 18295107704289976677, 1814706268673753787, 12474943759854623335, 8814778832826774208, 9159057654048965906, 4451260977376821357, 18241701617364042056, 6169989192350218482, 15071965537117101028, 13509168527678537782, 12224278653171635329, 16077066393714953826, 1433938684868066489, 13014970036232570373, 899282336249563956, 3089487642230339536, 3787737519477527148, 16667686214395942740, 8787122953224574943, 7841835218775877827, 9693303502025838409, 16122224776459879427, 144327425397945219, ], &[ 2350654041004706911, 7834348511584604247, 12756796070221345724, 3842923787777653903, 12373799197090248752, 9712029403347085570, 1426676505264168302, 10586232903332693517, 8387833601131974459, 6290888746273553243, 9503969704425173615, ], &[ 12688955427180652274, 7641660693922643933, 8789985477567049482, 5698832637416200787, 14684840547760545685, 2822100467869581421, 3557573565928866957, 4409631974409684922, 16994214656621423610, 4513108841166793667, 9009005527785483287, 10, 10, 10, 10, 10, 10, ], ); test( &[10; 23], &[ 748159237152854524, 14199895651244313572, 9044210482484213648, 3880401870711113518, 1694971440240542063, 13547801197479934494, 5244069077418598572, 17329479401291658084, 12613311850003558282, 5618071535926791206, 16954511293879569524, 8600749590433482901, 11708546551548237376, 10879843710159659952, 9101678715417935644, 12126242459863584426, 17259866272884195621, 4418382641453775715, 542305129955142216, 6563442437678466173, 12794875758080454756, 7461769876910639905, 17925257245127463276, 5137728719899113924, 12905981752247605071, ], &[ 2654882163556630563, 2047318842992691178, 17944530594807555614, 17278864523505748498, 1160166728089482341, 18368953657130322418, 3937719995815345698, 12007028340444721520, 1496744539933999053, 1476923054783110845, 6551619938265612084, 16801911333947266527, 13986495313155597995, 6571595571877061463, 10140569634762389822, 16210530410764331582, 15172903143228403872, 5831780706385794192, 12288937301416472500, 16224579586702000460, 14545605105156691376, 8614987803254853144, 16629891239728134900, ], &[ 18140975738986113396, 16765596268029991308, 14497740378349400824, 8834432760455669008, 2081502095596466916, 16785570606386467383, 5299348241512211807, 17503170383548190207, 16775442261989831354, 8131705923782084593, 266320274487676679, 6602256474512308593, 2102043233085822823, 11614561527212258722, 17915538208051341722, 5710195504177465517, 2094480568485157388, 14339014023087152780, 6947889352398323832, 10985139413433625547, 12373170520775701923, 9198039438688117621, 15475638737141339650, ], ); test( &[10; 56], &[ 14660214196707223375, 14265972253040120215, 15506320303100465818, 17085621003033826581, 11203337550022453944, 15493204961705835371, 5803021083410871755, 8112917457002746745, 12663484193891261040, 1721048899893287199, 8062187621610464306, 13431761655884620090, 7331427712144411262, 3626934647030185267, 13231383914073320042, 11637171044660683638, 15189928975258171045, 941827519265124224, 2992792486091076914, 2044203374633195985, 8310380355675814732, 1677894573715118386, 1863631713396879617, 13750903464355877990, 13561054993991137710, 6643134394212488277, 9782189322903525535, 7987880548748269544, 17396502810230452231, 9355336424066456608, 6974435047841500624, 4695995454788932008, 9790410161672155866, 7324176676989916049, 14873447357313289350, 17933513319573948354, 16221633809094225356, 1119296061370324791, 13659405622992751643, 10536448431317839371, 15771892335411705715, 6450515195565208913, 12583173873673842188, 8943105588740166659, 16781237121411387206, 7355272525679995848, 8924936502454129260, 9464007023044637842, 2392086820925613645, 6952992660961663836, 15709161892606831425, 15961199354349516091, 8170938350051511007, 10106337242460916657, 4519632767875399815, 13966478644099829332, 18146666299243951179, 18001892575388798951, 17442461326088111501, 12996149925790510613, 15125238000270787220, 13458137050174539117, 7565676737178758148, 7820895745333505106, 18391820881894926862, 17227107494212736312, 16170524482788524562, 18292226432698054709, 16409124153431213414, 2622798522164114141, 2030148142272451724, 12631034221630749586, 12521714531249855181, 4869764655816857917, 18312880399388298885, 1881841240505020002, 16686085102712131293, 1638984612454565124, 5980766772519196081, 14473546029553426533, 2610255570241349719, 4121823778233332328, 15196027812344512481, 17634932614139407184, 14566629132274047837, 6629067916649366603, 39453246491293667, 4118307938296638515, 176389639877922730, 2385844666265721927, 14424300909552701177, 2596064544694255252, 9262830285738421829, 8366979142044016136, 12451088247268499723, 16456341544263224076, 405434591376297036, 5989071471671786526, 17922319711997177283, 12402685985480014221, 11440567647536028583, 17109382986734751589, 1165111999013207871, 9042409351611763515, 335396288523389342, 6889397323074150916, 13998858741906849976, 15927944587197048898, 10995067153735213576, 13255077995174337515, 11985913648073551062, 16606199253171990948, 16615211378568935152, 13000672060735124358, ], &[ 6726150808576237754, 9590776370558469124, 4613857594775205869, 5605914158178321857, 12627075307783464761, 456502911636413728, 6201419543988208076, 12457367465345491402, 9194484469177303126, 14469237774454463326, 8872571916644400618, 10371861714649740250, 9551882050917532587, 1418647961867356190, 11742587182398063873, 11015016132415914044, 8777839015232205587, 11080046461630228193, 13740325869131645472, 17716201322003396844, 2184375889136968144, 2744007897878529583, 10107840174031679018, 6807210551800087042, 3927845063936277496, 4657264236265855475, 18202437017170404187, 5332422779150911238, 15515262280249200267, 248667350560422394, 3473467338029486524, 5450666559053310869, 9114347711968955703, 1001965327187909086, 9391480248060184246, 9069754537718985217, 6108113375902101471, 615335597740998377, 7341924484422171664, 7557688311245960406, 10629369615492290302, 6551022068682485711, 13009629572214277263, 9801266711191462998, 12475469715378400041, 16817728089246511388, 5318131496704799888, 14034696640350324685, 173195053797772988, 9465580662794117123, 9395502290798332505, 172507413604644051, 13462235362634225088, 9267822876689174860, 12978933587961252639, ], &[ 16979197013852036393, 4534519222829727882, 5127955051936920534, 5669732551578654322, 13787946500638697314, 2666880029397285003, 18286001525339884787, 3747928243980886079, 5670276194023029484, 15201258611907138387, 6046915833599742673, 13282924752646783062, 18026143804639821221, 10186643213552896189, 17209309200088910354, 13215180252119768256, 1246399679408038126, 4186715523775575401, 16756959752065842207, 6600048850655585015, 4543693866439677976, 15594233518271892275, 15247811862837572166, 6322126320582019533, 649809830609098083, 5229876751712742127, 17719948521867410031, 10737539927122287433, 12476905306147178753, 1539850235988803702, 13572545877865905325, 11163694899331373883, 7882148214994127637, 8164419266634080608, 5782587821804107698, 12155391719814216620, 8020222143449740150, 8489927257914490530, 15688922762526028920, 207673185831465902, 13825819490340731785, 14207999229863934400, 10163751595898713958, 17777080404153962435, 17016927136773389232, 3820023214020965653, 1892439588667561762, 16909683715900311832, 11919385779232783009, 11201007117990222527, 8700983269916503928, 5034192113764375450, 12790439085134048151, 17790018876931315900, 5953092655978688336, 10, ], ); test( &[0; 1031], &[ 18285600144381611747, 2607658718107379546, 9747604544742966856, 2960103437306950033, 11333576199308712527, 14238003202284088532, 16265332193148604979, 1379942304307770309, 16938783330207677640, 2745252988447228002, 6791234087903673829, 12518174636027607009, 15674280970395865818, 13974288954585950791, 14841204964098561443, 8748517132169388864, 17525897240098709564, 16349048229068678114, 17968982428715890523, 9358013674764648602, 5199229606169954727, 422943872008603371, 9250194632016078797, 10021555560097390790, 2684614891063859627, 7440654004485895845, 15497536988658560429, 16091759101488274182, 7624403524401510649, 10159556756468762769, 2567573898157529790, 15609657766585643253, 16236943306986434793, 5890548198293774422, 17362921261219419202, 2808858681174890249, 6640440299319480962, 4326748503634915406, 11456055721778818238, 10707187402450482341, 10505948868316563545, 18366980076276187881, 15068095720303300745, 4952650647951470154, 15911634980226720120, 10740745397838202379, 3200127162032008025, 3763543940730164508, 3723483274937556495, 17871783614248259146, 8786059543177366813, 13050056601003380055, 5623281846050325544, 8511114651096961385, 10891975825673952044, 16080052858418260073, 7171941023859325850, 2503165103241590389, 11967819128596062687, 17746426492658731021, 1524291256148953421, 2076038155471824980, 5880985691677435840, 4713693495653829540, 8577899432290161344, 11976146392187565938, 2529575305527670284, 3765314673643814808, 7234028569335439232, 12375682646064399341, 7101569992574162906, 11098657045492285566, 1153652218824818047, 1210454437960036069, 2694638310421669121, 7870059579873173861, 3508868899875540240, 13609981818610730741, 10703439073683625892, 13071420953159015459, 13716502475013538938, 10634244764110852465, 16403497596959564382, 15306415780193612609, 17601327182445704540, 18298349615021078405, 18111916165749794999, 7537294468737253688, 7386987937618099419, 10775482015504178918, 8525379645714838775, 8788609183023289620, 895207535126054757, 17118106622782691546, 16749800484842219686, 10933310771357651927, 17045784651422893806, 10055875188754575183, 9519498699655590213, 17322601174638910336, 12118730165352641482, 5930728976613565641, 17159697904528121051, 15309680603600886131, 2354852814839706361, 1866864355164982520, 14799678913936204761, 114516480202556771, 13374320542339641716, 17948849241297689882, 11937303202723535389, 8708253685264852524, 14784022410383824926, 15741150074911773529, 4751508515383369506, 6753819133127024063, 7615256392835158829, 14330334546462075477, 5916715905113385520, 16699087896061936717, 2161501163497237132, 7657705954734728178, 13842299391403386537, 6172027960597539813, 5307601271781038790, 4555363624168980660, 8897561972602250232, 492135721000809790, 196374542645899516, 14990889098212601995, 6381940097804056460, 7088456247368733765, 174918913838309902, 14001140535865588809, 16643163063827173806, 1238954875765713073, 13202778059857945377, 13892311264186089515, 13771970066908683469, 14995846051430041367, 17421145547571170005, 10821698378431695436, 5316647583697276386, 14051654090444941132, 18388943018780729150, 11259779711269878259, 8742581111664031470, 8889827116461862655, 17319531559654594882, 6500455467003400955, 3959184730122082747, 4054561166041887982, 17316966724931034861, 1607293446195331113, 1556357414629043861, 11011377910730701009, 13217502480646592162, 5556764467305459566, 12021589498137324260, 531690648537094954, 1038223775874752655, 10112707642670009067, 16909364180557997068, 13549292338140530580, 14089674983696767092, 14960833416043686252, 3361732906192010803, 15411952217752187419, 475547270098839964, 8227352829235176532, 4333410121135356569, 16974375358381043398, 7462799035629267008, 3961814110661375506, 3191195952723002366, 15267463856820101363, 2682345599906528119, 9202835087842166762, 5753494002443879006, 13496926465554347490, 15537050413782275199, 4005699994847427717, 13011783168070790177, 16932430119108925312, 10469912374234875027, 5996081763274312546, 13299322992254047535, 13566444816251120959, 13441242515242491906, 6531470165275421029, 6998803913624387519, 5190923639408924125, 1301326112306077751, 2724835656803633652, 14868270067404848561, 16428689823791581153, 6363562758622431773, 5795421246045082577, 13738077193279334339, 17818084837848061577, 7409215264364848571, 2893214122000373991, 4066741278513513286, 6208913273098798518, 5323770029909018782, 5551337708190405618, 10281953507639521630, 7674048265312145606, 13913805095945202464, 11645578449852204207, 5216827728522108969, 18149089235876418482, 4193193659542496963, 4384037638695340997, 6264405355262516799, 5923041840648053673, 18445416708501282570, 1449616427668184913, 17814282379016188485, 11394546105942760801, 514272123860845956, 5487867953647208460, 9765982880054791980, 15269612196572547812, 6933672683776753268, 10897766962490536850, 7963503740124897799, 1249067770622312125, 8521634516253063564, 15047118858576393194, 3052485574284313450, 15762145598668916146, 18313105704770544279, 6541634279146063106, 3775400747866844137, 16496810669859720010, 8379319521731425820, 10800415684660017782, 6142541123129235279, 8861768666560539302, 15721050291326133652, 11134786092605171040, 13017548541999335364, 16909509841464459084, 8484654924270783553, 15005512331960977142, 4074672441814183738, 4078543398182843194, 6773998236248908357, 631977413504183184, 9491750397437496755, 3377999220825657249, 3346615552296940898, 17604589720878522247, 5769086022977878966, 17347842858220401404, 11931418629108149400, 14490915772427782374, 11545152969051431084, 18194530049847403452, 14802318193842666424, 16217304261948074309, 1412773250833563909, 7479345161017490691, 14305628603682480019, 14047111540339531390, 2202019933845371318, 213291111871207451, 9537101822050445095, 360483935799398585, 15821799940301882413, 13587044781648265473, 11158232757574497759, 12493764616797894572, 12454593638118113923, 16175783796857016626, 11972175061436709392, 14628387199635430458, 5253379621963585234, 6809274079261887574, 1124840670828961539, 5990829238947221675, 16084193379498378212, 6869638953004510310, 17906409028525617365, 2739791577758847487, 480131078003075884, 16023370915391221306, 15817682603522356534, 12423449398808644199, 14130320721960901031, 7934273914237433979, 786249691033407308, 318299827682676802, 17097143809787660310, 17521193394806881361, 8643211685837497345, 1204030043754228035, 2676537878172957478, 1780844249865247048, 1857038044392024228, 15537174113724189402, 15216184620024948614, 18295257315773355758, 5049495368122551869, 511689711728309335, 16940513174832634299, 12104504465679211266, 15914220570778735059, 6279446781938212962, 601029894044123455, 17804281207827746870, 433540216199633732, 7944481812184613751, 3853777775611712418, 12126936213601232312, 7065913778676807607, 43238211455364752, 8192260579196809431, 8266744677261407642, 4334793912650253838, 12956232517663155469, 5369404211871099568, 3235414488456415006, 12567595135095181283, 13364037675200086203, 2815554933029326376, 6185051196142844265, 16989212187178652008, 3878956585408701458, 708958585074504373, 16920922562467588927, 18249699025766906652, 18027337540317897651, 2618966708286475266, 1113776870378384593, 5988471205905783011, 11449408349082147321, 6427498821108845882, 8757628250113942992, 3713195263318788838, 601232850676293890, 9498794059653193118, 6534298968814526870, 12486527138072517297, 15783607638066166551, 17817123635789116996, 1248377855370621035, 11141540237607695650, 11310946791190236066, 12846390650128150341, 15186900836698527641, 3867690890119912186, 4589172752928224161, 18406516299291763072, 11413251654981660385, 16024801440525265600, 4278405775100889986, 8755603474239908996, 3160069975842943114, 9906744402561181341, 9965035381218832722, 6752543667701180453, 9346639648731189767, 10661232594877011901, 14936909082854570803, 1969452932415658459, 1696145335740060250, 18164995195644723626, 5001142711409868759, 502680569449519136, 3022117952710893422, 10177903082752941255, 15652975217635236869, 2966845407346038740, 475611270044318476, 16066077773226714888, 15255919358962415817, 11732084421089027684, 4677384405854396649, 4610350216539332701, 10328878907789481841, 6555568935797623159, 3017832515483377819, 14707077320201566872, 12590581217649731730, 3161603588075729925, 2563665003397527163, 5979170469664323613, 5626012705821413010, 14527466196441398570, 9288633927607394750, 14475257195709120279, 11865264300717431518, 17136126069177251144, 1473429666850111981, 7510246272136643144, 18310164183004169194, 3593138027022744772, 6350576143506118040, 12773591294872180021, 4700465661075210908, 18143542497507479548, 7719757932210686713, 4338121025681527358, 15571485830471842974, 16406722845577898376, 5721314859539898709, 6589287198671761501, 9745964795756887415, 10659452091068591333, 6690465060747950210, 728586915321808599, 8500603684008829799, 6301121250492508617, 1984503548524816268, 18268190305907234300, 7454276134026583117, 8547492859943863047, 9499474055416732782, 300834181303701699, 6423420221300563233, 10906772834067949181, 12139236772746843296, 15479617127388528892, 7255634393137870745, 422813312578980582, 1148428423488055078, 2405372466822606988, 18202859592780650711, 15123472874738759666, 2160560009262204586, 1220679802754985663, 8755041458565252857, 10511683773218681884, 3102123453859609904, 2170460789136594842, 10540612896965819281, 11507452270722296921, 3888033478974547053, 2913172211662715309, 5819754293645132724, 5417423241393498910, 1121133064615112577, 8899735394209007976, 17939515994389118968, 3057735335191827376, 6167592388365551096, 7859032161115089000, 16392857948131842701, 9672772119042623246, 6861392074297507574, 10079830057029967718, 1610021695530123734, 11499290474395739628, 18357287834621605730, 7842767805813604560, 17595414094496571456, 7727166516961623663, 5489874195960679366, 16978517381214022058, 11807176188692933608, 15778362166265505627, 12826269652469979971, 7799517220815997172, 6941343467007860979, 14716681029145080878, 5685272761645196256, 13841850638623453280, 18117357664247936176, 11360524534267913074, 18408319184374782489, 7834872787814949745, 16527576874764684677, 16576008924894848236, 12304125447826256834, 18301056937365686021, 4783517752793787963, 2014695633627143026, 8288284640512774782, 14976342552024779031, 2436344641520555003, 13990286257760881060, 18118120610252892651, 8432102189510702685, 9013208900764457155, 15956895100219663594, 11965405775699735022, 11479704069694999185, 1315304162999565265, 7619720903122481473, 10798255112249544769, 9067939483463584201, 8242338589636256000, 11595456341434427053, 14057071507676286987, 13492895734414905617, 8167664880787891961, 13065353170057145433, 1390434145929843432, 15097573448811012551, 10002618775785350116, 13037941058513405166, 10812662834979031696, 7926490047107184245, 5399553758270644040, 15603376937288512903, 3817798784005377844, 12622533130989118638, 12217900933744511855, 11495811053435066455, 17088770095627295990, 6282760152901843934, 11339571359698956951, 10010250182369906159, 11956984034096448616, 230656938835165573, 155123462325204273, 16323688331673735090, 12405389233556129322, 16866268093283320126, 8076215192615100819, 17788391733691877517, 13738263070347903116, 17514698963264490076, 14361153193344045623, 10697613194968260318, 398797896589607036, 11354436663860273814, 3988804407101251650, 11718246560466989132, 10607955713165345856, 12293428353299936422, 2774193885283164233, 12111880818145942696, 5269109320979566091, 17700804638146972952, 13483325589659749714, 7018249448187819229, 16605502462498173206, 14334331196281817568, 17997264741331536966, 16942067749941194095, 18326105716816079857, 2873713554755956975, 89972251875212547, 11011206003344840167, 16263607631557095555, 3956845690962774124, 15843733851407790844, 4532327333478987933, 14523922448792187179, 671512032483507444, 9051952980308527779, 5771887136664598504, 7318486125138347367, 2056863287621362849, 5319340499967729915, 6771692072764865726, 4993497900077789612, 14846578576184294087, 8749976795074478239, 13944161778625889141, 13939659589211557709, 8674498121103871446, 13858955528517010167, 6854968788299690525, 9785571842093558996, 6616581398547260916, 11173134838307567854, 15020736287331849950, 213678875278769463, 8136043007787109258, 963815884865140222, 14383997603758711218, 2441395136452256841, 2285295004115032555, 14143394511135418137, 15622142144369079201, 16493347221813991820, 17474381401274268608, 936058552355041089, 12942246561895670820, 10317584384347004208, 11782536454405046773, 12350945172113506786, 7391214981076111463, 7073023377646396731, 4011509139909188128, 2257833537102580311, 7274600296374037369, 2769150843750451970, 9102426399850639067, 8214223108585585549, 11637757222275081002, 9169116734789273638, 13195915003973211388, 5475411329499291917, 5086118280372242975, 17718728186337638844, 16105088227769019766, 6209815346219807551, 2881314910093736440, 12490322405428340882, 12004395323760866113, 9968698365927837252, 17316938449682856319, 15625883316417529399, 12226632472013770838, 14161693092908388449, 17778030898846793856, 13976693691407275877, 3477953777282076567, 13740936608896808297, 17180555612721269478, 13416907629329031924, 5869124347540464645, 13384341358033251916, 14313718444333031397, 3376219002404246289, 339811206717616611, 2616093060711965335, 8204344482414301835, 9186789611379643507, 14338727533336579685, 12784860191396059227, 10489777731949698480, 14621154301243573986, 13692422118348399108, 3784610479458294357, 7735714461152647872, 12931998015666009092, 12887123618479150667, 4005389619579094200, 12949896351841026182, 4274952326880371758, 2252542616091249178, 11223191016227664360, 12276921256190460942, 9311103011248164424, 14618190821987444804, 16794211813689377361, 17066759525543500866, 7695930135720339816, 15636206560014700744, 7080595571863441999, 16002741097850788650, 7266069110373243930, 18266417640341330095, 12863061635472560818, 2804143153090216476, 5360410260257436881, 10259005860191386447, 3129239898744374569, 5704118451966324874, 2617683975038617110, 1419008983250810424, 18176995508939903574, 3428325565738056333, 15807295691769067887, 17098475885649833094, 435386771621069983, 3749240361804507548, 3484935049619675621, 14151734623085313892, 7107401439542109862, 9140252282652202082, 17139755393802157327, 1840890360164731160, 13945742659422648167, 2993927710006218010, 5123393630446195909, 12126601606897174993, 3757237441333108331, 13430475145736272456, 141286591810884028, 13716994059020442018, 16256272733681835404, 13021661888272553737, 10938682475722641190, 16670594791610413108, 7581768967654565510, 7258449528404661741, 16972464178815325271, 13103916238623071625, 14383222643604888683, 9134614536502072501, 4484749605592970811, 7617523826265603571, 286970167644433897, 17350844883213337166, 9372418001867268906, 11036524012081184976, 14599471605351296864, 14353873970303354160, 13804851709719425521, 12542207662034387249, 5455404902951618435, 18208534021141654431, 10760289922882806669, 10594303509090562894, 10523612649331418075, 10175165805141093468, 3845925331470243881, 9968712325133293994, 12632170237051093440, 14407500129795275129, 7039838041956792694, 8486437057635491253, 12990896208114377714, 2169038646525679305, 17731701498975515823, 12645000352324144895, 6940383608615873690, 17112601588170442293, 9898015000882658910, 14088035355956248952, 507013420654526970, 16055894587901325067, 17646639921892423762, 9750921155184562446, 854792204257329267, 1907596925043325411, 13186585073232938657, 17324756184357468589, 13215141704644982246, 9990033614756242368, 10703741257062175210, 17316690423805264994, 10087888281338300084, 1089239266776577821, 12176439490507890322, 12695856964012192215, 11884436036930363286, 16729977556989227363, 10923433806234038450, 12992592892604117864, 1268144030942582108, 10300209358150898566, 7832544414491392865, 6657397193574515418, 17331856360490769436, 6685863352121534775, 4872607912521754323, 13925034245904306548, 15794800294630432773, 4150702655832044776, 1922931668614047821, 12163445688451808604, 6814128619400384333, 1631984743731389500, 3778862171994919347, 15454466802087055901, 9264991358295251267, 9936918682375797148, 18157798989566244240, 5581635369737696387, 4479378944085838523, 1634001250673190201, 9492710507275012642, 9234172590874940829, 8783494515876021547, 10628896245581316049, 9175567334027325902, 18216027702703135409, 11634672812751315604, 5707660447334077643, 10202156378293455124, 13892983828551272913, 9908193203293924452, 17571530454157193212, 15072879288037447844, 127116006100922087, 11771185510908260613, 2445074823174851909, 10670868476525820983, 7425728342067716996, 2985971528087667631, 7395252277468977294, 2997333798387301672, 17435969755936090886, 2284549800776567351, 1549552636061955968, 2562232096971944509, 18175473291905577073, 2694680735549112623, 1791226765063856042, 6639691018975209776, 14450608736185529781, 776581885259523327, 481545710834071552, 17904221072369375896, 7658678246624118033, 14858939803632465766, 16638621759785444057, 7852705140401778814, 15504288742303235325, 16123480377693163548, 17580674642691781753, 2060059788952429927, 8044488423463356775, 12159915697800522747, 9979462535316088472, 11464540989399692426, 9723421225194612320, 6449580914984939699, 9406550367550615810, 5311403373873226147, 3066770575413693918, 633416401733094941, 11712977725629062725, 4883265930195070560, 16189146570612520152, 1698905934763835706, 950927367170890858, 8829376333788190736, 7907286046365739950, 3164878452294289455, 10511755255842705560, 2924155429164172446, 16124299828159551950, 6010099555943764977, 12724759932455911822, 8127212736140639283, 10128696763620279450, 18035084640302368027, 8781918799260800755, 14441294204200284647, 1927193541320801341, 17060847707989835700, 8195209044950545498, 4420757359342589946, 3727277256040667922, 385534260624886499, 3266025280223616765, 8307518494652840749, 10628505726158916146, 12481632216062021685, 8443059664409740255, 17083655987996225144, 730490563149619104, 16115455384269067104, 2382469211629823819, 15299473012699513736, 2545726390341274697, 9566636451267734313, 17404798143522728759, 12853265630229752228, 2172148070178466503, 11003520300346660378, 1134402141777052949, 11771658227786580781, 12088790715698048033, 17088312113295353834, 9858438140481896937, 4732279313243969474, 9302577460868509370, 10413475674288905591, 13021872760990946904, 9638439145954399186, 2342341335564065825, 18026701375952328694, 5788988813536004381, 6112690485750689530, 12277817288452946380, 7006316162927315897, 12091459534025657274, 2152473017451714429, 7117646493299604201, 1591263581497951670, 12905706257967317715, 9739330975167177950, 14245120246238342654, 5445126088677322792, 8475451974915724213, 16532703318231814798, 11346158079313546034, 2587775018559680831, 16042335036595321112, 2783584919636232962, 9477074304137314302, 6679970828349102077, 14914134423793746235, 8835496380779847657, 13649036745393349622, 11800533244055495841, 10329924636422821002, 12857463828194064326, 376873602561854006, 13991526512239117933, 4244930150917248420, 9377193637737929560, 13470983451570137106, 13709193869228195237, 873834737899882109, 17298475531540644799, 5157431525573101837, 15694890039292357223, 7263973093257735703, 12810611197004081294, 17159179774131359627, 16320123751204284184, 6659167957772819702, 3559977382115542403, 12297726256906381994, 10545494770323931829, 14423760345131502963, 11951650428815262297, 3552160721881779344, 3921553500551057972, 8827773853996085356, 13035185276040540279, 2431229196115555640, 8867095302754162942, 5824531700307273486, 17795693614810306555, 5327408766240893952, 16204495625665346776, 4520750388436708886, 16011790401268552431, 13186223796877430470, 5894651091707364204, 7349710328825984565, 12990495590567591633, 15789659485048909512, 8110395238510363562, 7157879492847706094, 1855521204456327951, 9387090323123631218, 6983791028671987424, 17264360937175821593, 8964335962673307125, 4438686713691513133, 4609268036048721815, 13573223706586323329, 4370839728814507274, 7190667190262397984, 10585250032143309718, 5262324401338557970, 18436298550586124762, 615281048933821162, 7892081066718287534, 4153026337684348988, 1998277297931299322, 9570951836837442866, 4214601792245837204, 12544321637650748092, 9861635514343412559, 5163007832201827055, 8357508302373244198, 14941521234529596324, 3025149840692592346, 1565659965409485275, 8113415648323406877, 18047137088865383715, 4761751436090139639, 410742697284005702, 8123281234742203725, 2300465198396824513, 7573276443955885792, 18354607580020177721, 13826724636992006395, 8759796250561912860, 15446866439938431144, 6466830870344794620, 7248618897690538684, 10968843377874574640, 4538534083565844065, 10463149345079834509, 7862094636026465434, 9363380870281847317, 17750231516234915849, 10605066658889662478, 8651524573226517322, 18099624785064356749, 9012260115980472797, 5112736631921184699, 16433387801586396924, 11364983784749187252, 4592720300056375272, 17400478621152089229, 9960304372235946193, 6810543488590694603, 9421463587360187007, 11110051932845796606, 15820198248392525417, 17370225890188484838, 5511348958827419764, 2047354351196049067, 8842128025677787612, 2546794526658883557, 9990966093285021784, 10968573027006701235, 8153649946073344163, 3435896373516278367, 8854351008479838087, 15172945879518770400, 16101272223167010392, 6080119325930559085, 18336117387797080742, 11495477657407490192, 13799378353686928991, 814519040394412554, 4055424121543431351, 17971320561372651, 3045424347018335501, 9144749175919467258, 17693139582687085722, 15549618811805620741, 10042978303090035766, 11250820672049577391, 14650606162160854310, 681053092156505443, 1467784211081816986, 14292070206822113207, 3356550259250142987, 8897529911380186072, 15774124171111764637, 3608035896189707114, 14945841364780812283, 13638982384303383036, 5615554819198447325, 6604755778043315386, 13154764512915240378, 15781224930202608619, 5254282127938948208, 15314350610960881010, 127785624547347482, 553562291991422824, 2665385793464509946, 11960374868185251273, 11044390920977985650, 4524189753866435423, 11922516208188195244, 7322728958220573958, 4566122595518047958, 9257927878541886507, 11778087706650674305, 12675707724087743775, 14040780876086782366, 10310608200410344735, 14747492163773576994, 14763717547881637874, 4519119406094329744, 5416745750548195790, 8698677371585009606, 10540691781438295688, 7621321253979898000, 12870309033904607776, 8766530226422390333, 14410571192410377800, 5017391940288233504, 8156621488957733235, 5701635921482105032, 8697544584237000467, 14463840701596743299, 1132393248669674482, 17783802461705335925, 3379973927717106230, 170233915427480249, 7721198001501959996, 5984888435057942981, 11741252369856674270, 2667584213579254971, 12391311788904160680, 6403858222659082204, 1706835705335237525, 6951651160442697621, 3395001754770416725, 16336009550495654242, 1588611969581977597, 3369833199693136814, 16679631221398536370, 17143410383401198876, 10718378066292328788, 5098802788047763943, 5003995899412543356, 7797753734199884695, 9804992578690571817, 852561252664521182, 676543942240459737, 12047623372899199507, 12688884395525848756, 2909502726897081899, 6031120528123066491, 10187664230696218588, 1634984456433807424, 13461263282968829173, 562535253767547543, 3262317265760851658, 10159933570831396212, 9610081805557490182, 10645180788472548796, 3825134762043109512, 11454131642474959474, 9401675919629678678, 14450914272139752267, 7874801920832590192, 18054728540681521894, 15303403280502540543, 15467520708986418749, 7705766485597949742, 204013254901132813, 13967733294005655167, 4001477583895779972, 5972807400755250985, 1217989087590450380, 10862887725324735466, 1706534929358469389, 13264418588578493513, 10626892394654962607, 2832066031146486501, 6506140673085843042, 14326905332890415966, 4447185119806812807, 10289677945299645724, 4459612687423833871, 10867968914888905042, 6485974059834599556, 14142727197114410913, 8587964753565667799, 8972765350531032618, 2292328948393940314, 935062418987300570, 6736600688398044784, 7931198222933701097, 12299736294122528410, 14482610418638535345, 14434918807907278467, 2439305975663118437, 4480608229958318339, 3952066067287563861, 14258451016047506475, 1231074371015334625, 10331248234059926878, 748201218435577445, 17462982229802307244, 15686869687340151573, 17053063210448785862, 3599854718778131864, 9301737618251045483, 7627446349617553731, 12835054936982245416, 6336754664191040283, 5870029311999289016, 6027766907695007223, 4082089270941640253, 10932978191544782698, 858542788191451824, 18173438258887704458, 15950175591359254382, 10496438189070905854, 3761196574957125185, 8070795822731288097, 14333885717356195593, 12907535393235068762, 1300746091836895017, 16095775835363872226, 5221409894943186677, 10801943559441670680, 2226518879270450694, 14144518871296969095, 8329328663632421754, 14151247548153947290, 7005388744793033852, 3731783672032466610, 5642923046890143070, 2243566518435928649, 17827722312011386647, 3288494091174335807, 12802408479052688767, 3941775622555625432, 13974527790491109973, 7184506709498460272, 11905130726430415767, 12898188848602614942, 3336329541205892765, 16740350675338109671, 335449286526469870, 16670399530115701446, 3370759555155341636, 13153054802454960430, 17020347152181004363, 16005180766456295251, 16035747705790056677, 1904525470716808389, 1362939978621142721, 14268989953945718594, 3131759537359596393, 12623877369046640758, 16034480904634718634, 7205849095551422163, 18352760423874563428, 9294184574071126998, 4855176006968938932, 13740659884417148386, 9678792914697707031, 17346691148499799327, 3661296281536466662, 1858171995289042067, 18199380542019467146, 18435270579529426778, 8792805062170870691, 2216926146372155391, 3336698928747087340, 15361162057883195491, 2230334966886787987, 6790919905652555693, 9523654540872868833, 2373039885555601800, 4493652711092482273, 4848735304745253118, 4615650132005261688, 7011332091469251441, 15051588471309214410, 16436499359483898767, 5534529923924019676, 8031782014972324826, 9587715117105518067, 5201232572863714631, 6949484852216655045, 11242297859309211887, 5445327566402416511, 11759527029723480062, 7401655792007047741, 12981437329323060492, 16627917972301844941, 16086064209851186236, 18317605428363897776, 5479987106722795675, 470044962552825995, 3263508437049006276, 8532199872517472836, 179963713893634086, 14750710828805195780, 8566890372208465530, 457434420254160615, 9026428119711082888, 5051697286542220522, 4066845298260571291, 15266943848838025449, 7790231715639606132, 18047039423184779192, 7097787949459808218, 12326346119319424869, 14895758855340221400, 270818421368673258, 10953991395430365501, 10722834322274726220, 7175276538034253286, 12293270138776886211, 10868230614957475384, 15568806031450505970, 2173332627995000239, 14888402241228040414, 18405500854031799916, 9396217995786697609, 8638079772902395024, 8700301862255582170, 16669714149683986916, 11791960995856983997, 6941956874526614041, 471913500417437253, 12645657659237731696, 7344954555441957686, 8576764504255171238, 17045229481365431866, 10710908163870404781, 11301570355963434173, 5971177578976838887, 115032958122130333, 16996195561179864691, 5303610406571283411, 1557215249726500571, 429079935597742432, 6007572072647948719, 8793841786368287656, 209772504980789061, 12514491936429933001, 7014555801251009174, 5854792368971550756, 867919854085761466, 11854155159921686895, 13142074624110571417, 7907850875814485970, 16861742288872511551, 1208590626489658408, 8601279929820923503, 2258924690462246171, 9585184984627008623, 5315828210383196353, 1297805663260559339, 7398320505542428444, 17073967214624996598, 17704120650146094638, 1299385581680024947, 1443489762904405882, 13518221354231615324, 9070126881206870042, 993730884724745294, 14081041013869681380, 8359943552596347499, 6866696380166200245, 3837542845849508667, 14602652064433499913, 14314340020057352466, 8839559535694012406, 14227230979046046062, 10298228782846904508, 13298718693240900028, 13909155817605919274, 8780642200132615642, 9412091595152829592, 6822145839018577251, 8785978531052338151, 4948528066049804851, 1172628369060862431, 5666685907911162463, 14153629140204265152, 10500845530057771412, 14608765724027887761, 5087095504941752721, 8701919577673940506, 17137520717957261114, 9199637801040704714, 7095886304415555902, 15925336741311965253, 13077337771490692636, 145710441006655783, 13157185292334340173, 13407008567503772150, 14215960022966892561, 11985156240556559472, 17945288516894513884, 14097688271959790972, 15505832877271523166, 5843174730859038007, 16205337090179264073, 17606308108912062454, 669419080191010051, 15851467430769620452, 4936909049694472990, 9426661750545745060, 15134074240235574428, 7927257239677744604, 13865931916371651548, 9055694221969554578, 18105938911030359772, 17344312477772739728, 7984780979580024449, 17946659128143746086, 3659014353178730517, 10881946920507249755, 9643240829875041416, 9979006042478131099, 3624673912637648606, 10183097162206305022, 14705929380474025749, 8560872261129163553, 8542571307034562924, 2849336599501641328, 1427173016960915063, 10561422500956348533, 13953646915815013961, 14711009426065697276, 17629582482698947067, 5068672373293663589, 10328236305608973133, 11390625625852214740, 16171676010227409920, 12007752012156277746, 8787339600696104751, 17147558071877953304, 6243146155416198819, 16781815705425825152, 9276534213532622927, 5681999116735330218, 16852010554258505062, 1705868855435043353, 14818213196970587370, 9256091199810743680, 10438037318676504268, 16794099631419865392, 9815261792343983998, 8286783569926236889, 337573434858179240, 16820096306284770618, 15966431763494632363, 6481208570789422743, 8429344246220730373, 27262454150324780, 9516508385964067765, 12876008564654096078, 4071754764426708210, 11593726207040321843, 10464906996437266409, 17795281436982488931, 7949644313068982658, 7004988298640898067, 12037768710549869791, 16790409316897618369, 7084103797769437957, 2419445775321185382, 8074279743518467644, 8069323749479463736, 17160974715554385442, 6446198417065372686, 909199233418090118, 17988046405451941411, 15619199660230837101, 8540771809211736979, 15004059727603767665, 9970067037279458294, 18037810830226270966, 7395784361237814976, 441608911830412969, 15193617525949907726, 8329750585903900376, 9232838481221040709, 13862722871242295122, 2651785001097390772, 13513885689469842635, 2916635381190975954, 14673366675350976320, 16796162449704211211, 15311238965453782301, 17048079530325153354, 6357896971279650981, 6912501188214061635, 15767706566209693421, 4950547784710662682, 6818275469676220067, 6311416403137682772, 14192827820659451230, 5519753761822532883, 6327790738344616319, 1571492847028444517, 519836968001291628, 8880684714326015791, 4414274058554177288, 6693694082558848552, 9180328506312734588, 11851754793034588133, 17892308745832908148, 12122989628255788470, 9813496966285232956, 10955347908495147392, 7570827623140202413, 12207236341183232786, 4777412212063025006, 12385252236023114447, 9508166476039999651, 114906234504385867, 9207258060511755437, 9210800729712345963, 5771423404639548192, 15194614200877751860, 4338352328776016735, 2610599495858282641, 16733979028371628176, 1929910361255473211, 14137591116693762330, 11276030669834631098, 8384908437274376663, 9932945040858512861, 6671057894832572720, 15600691762738444868, 1090424207156031951, 7633234269493162481, 1452672955493924651, 8042177265524791320, 5918487395429243286, 6071477929355428400, 8446553879294519239, 17238305490194970122, 8987047329207310489, 12398791106166157316, 15174911221193868718, 16946345338721827201, 10949948458544444544, 17318691300002579588, 3998415180681624527, 12750967780890975278, 288347833998723232, 16095212211245790724, 7822321122528030405, 1109063169170634828, 4652215944166612902, 16803163450585461189, 2776655336762420387, 15642000619067002463, 2018031858324511467, 11237756472829950832, 17565143038179107620, 16281738469740252935, 17600775725533342946, 14750124410220606835, 12883103971220877489, 15936542280450981255, 9714323865324229767, 1469778854158587075, 9593652974682074282, 11762461414294133530, 1404229929827068795, 16503900992928085410, 14684251465993475323, 17706137844161464268, 3909560365123413776, 9861484314350641439, 12009083324415037686, 18169123171153377641, 2393555352820887974, 12841835092045423984, 5564097118032313065, 12777929502410633133, 5078336225337553091, 8694020844593690446, 11388328638584884970, 13970084235020262491, 829772823417380360, 8286179729255644084, 957139202750627952, 3221879212666198953, 7645002751366998370, 16715354970243034507, 18304845819423800855, 9447343833119941047, 15163436489241423867, 2479924668890227186, 7818020209349584296, 10580682200967646169, 13911404593504958709, 8718275660345998055, 10124290490841409455, 7651303722187917624, 8976889705380896709, 11163660337280624646, 10388784795451265724, 3541771203499561964, 6075152751154669243, 2218667547472367527, 3995516111323252367, 11180655997089000245, 5073383660790586917, 13458152992621454755, 11676714551890338118, 1494799466123513971, 7327872328474238339, 2389581909384645325, 16687753253842922782, 11699615151482669193, 14774804959571915475, 947896829667145566, 10573954710522391072, 7072571908216975157, 1921454675444217366, 11232731567954977537, 14840397076140631292, 5060980672779376677, 12975040048834693618, 10752224255692434704, 1306885046650589222, 1930876755170305305, 8739276995254053408, 17062175909187112484, 13994219820475631601, 15241051299228638903, 13189674117437271785, 3224946313788614445, 2946953495584212148, 12515092889993340415, 8549243107224308830, 6555967774604787675, 17074340742411084655, 15860252206376208136, 2452901849982359121, 1217176756850333549, 15260442969744536089, 15266619117940483626, 3092040621234773226, 8592622982489602359, 17268283100249965729, 9118863795573669565, 5004589504450812591, 6062182260926951061, 17997691517876082652, 4684918577412859882, 15422706458772273904, 10373853167444581181, 9008368442714488639, 3624691764843327336, 1028359463583846893, 859230892908817598, 4558109131236939269, 9197636145007824268, 3397702897203024845, 17645318682095346025, 297912191657103235, 16707811002284900618, 9544713268645707384, 18174588433767285273, 14115044574398526220, 9550382630286578375, 5669098498675234593, 1419240760313025600, 2624357144105750680, 1883325833631791743, 12465653732071455581, 14016850785680848114, 10853862374929837476, 9213307118918963573, 17446748283231651532, 6944359057113621208, 4376214699313790455, 4272171302826636053, 1361571807732899930, 15928311517924806859, 10979193193168197302, 14315748858106823250, 11415251230794226377, 14341688199410222112, 13372316746789815573, 12205797915700991132, 12054245058919264469, 7420566807537884143, 5432588773028217373, 6350587654471565537, 6531829368743229731, 2207976572300046135, 12703622166413274712, 18356491416550058865, 11743861089192075323, 9975481076082250423, 5270519543247843824, 16596875614345327407, 264970638689993857, 12731851329939038802, 4100374548344342900, 11696626303514932259, 5795347109604371486, 4018536166291403802, 11605839014492166891, 4046122976220313619, 7173051512574373511, 10760222355399775007, 2397452537849365173, 7000689557970901078, 3508218483424754056, 11249130935335670874, 15485017380487364008, 14838383309738250533, 1654265944033471910, 6550408986795246586, 11574017534658799615, 4938545842279886871, 6987608227293293739, 8490763818451756454, 15553940026252549950, 6498239556873819401, 8894315085699368208, 1767452481216158212, 17391068041642225358, 12099770647562592260, 3232275359468560052, 9875417733360604587, 7344425724555447442, 18431729052975636742, 2951164042491135904, 15903903429564563858, 17834292681718510486, 4198460729209826867, 18283343945753908147, 13114879247072451198, 6308546439134988873, 8448793227573510403, 12883523838880467178, 12608354838733343984, 12284418193790956340, 3099459343498815410, 3160460005758859474, 17209423043124247155, 10299954565801063517, 17312198705527288316, 1159079074290265282, 13803764368072178660, 12357928111570535493, 9319226950413258817, 7861389264222959398, 4208357822974886032, 4724453996000826506, 9219506857747054473, 16650755835313196333, 4602357483273387357, 8421668150799174361, 12464268335381289971, 16842331782835636444, 2164847798539863920, 11848181286892607238, 8483204622866252940, 5177013341061819166, 6794893916803855304, 830729528874930746, 10838023688403983614, 2936119661394195602, 16749442537019148931, 6282125361565649956, 12522652324110588825, 706946363036865451, 287377191870510960, 4079038197618045672, 65600267963984525, 15852196146124192732, 7791496333170096323, 1197307315361468886, 12564376588501612052, 18287064409980818748, 16513413097113895910, 13772586176619885924, 17412579692431697526, 9943582674770693553, 18017460763820483721, 12774668415999817484, 17419661422487800791, 8542296650831811427, 11030794367359113173, 3091992835617551759, 6647390664467556203, 4760797422569339325, 15821430759187595540, 15905919720868415262, 6964495470980486330, 11481098497210815485, 13606157196874073055, 2545548939497776096, 17492549168216383449, 976625893298873591, 3307888858281262315, 4406331424039826265, 7251492960589745703, 1462803411594068207, 14615947077492017745, 14477853980032711958, 6580067844089943084, 8164600499091902269, 4672103301095852237, 355042099720565535, 11026766258596173656, 9849960052517135155, 16725670149953992537, 15683028676578831515, 10104782290810509683, 4905343590849641899, 17726532108833531580, 13910286230069122723, 9139857611408342006, 4873918044036171351, 5211230260928194081, 4862798578450111352, 8040863435679951765, 9157211979753234216, 5969001182224545740, 14666007377730777715, 746412171062253704, 5788296420214704699, 16052313287704740168, 15016980204491105152, 128634126176999080, 12474550947728802418, 17798334047543705551, 16546317352521543345, 5935130659172645630, 9017751516052971809, 8734332868677069231, 4489180421214586024, 10852153455030219222, 9452853792027507, 7518566350390737179, 226398539584556263, 11348207575144575782, 11286381051277848898, 2699324198517442237, 5176288375717881953, 7814733078102607208, 2870574509136744908, 13870395192961519685, 16224938596653908092, 1164830155402073602, 6289706313355675934, 10093838410108560175, 2551691589709651401, 15882696485463451559, 3395731646324122865, 12473003610421288231, 7149619960361615882, 9872807622306918213, 6663012576266477470, 17016549792515115205, 7914178572800158023, 17014701567637435932, 14346020259284370257, 5074365976986728463, 4760168726990175515, 9895948792206852207, 18273255159788978236, 15744547484672365588, 16864050091650583468, 7152138044891906219, 3133231435713995056, 14654289506261133725, 14216037513719362689, 6883938067921952514, 13637751749205284541, 3930907102025842836, 7818503413066881742, 16512268473175446131, 13618638131220285482, 3526560852689406895, 16317348279030286281, 5781706287563855208, 16877706843053345782, 9787389520151320440, 1672625892740702444, 17775094144895143457, 7284734471708236532, 6265912061217026214, 16428427284586036469, 7239300285490611080, 12257099262814629130, 1443098110450745157, 7111333716613874437, 10912463389630114261, 16046472632120791101, 11071308475967108461, 15827031925467657247, 8451701545861351835, 2032718007638091987, 9275305708809424137, 10133532607349132521, 62031173551766505, 1069668934694816298, 10021315903394494037, 18062320514241791111, 16614273374620642998, 3874528406029009574, 11609554407744278526, 6664429329059042685, 2466789265733227250, 13791862987730476433, 3100076428479694646, 1940573727807547478, 1717992312877296193, 3858278897688455120, 2708391244967786582, 5897077897033357390, 13903090124093303714, 5210172753029188249, 7461814148277300830, 9825991953137124992, 8749849231144845954, 15733619176610014569, 2536045915051793710, 2795322555877650589, 15164137179922407098, 11311210084140344802, 10571285191092929225, 4809833504711226607, 15053596169163492600, 12405664553095020547, 16471715640263755395, 3828351876877550724, 8499888452131579133, 5279727535149011805, 788643833745941437, 11012285726544455006, 15140257364221864448, 1834285009459528474, 6667182475201903438, 15294024395589453460, 10526482467856757788, 11877982762793807927, 16230316864465358123, 15723393603594181628, 18424513935220466565, 2247141586434891619, 9561372576131838874, 8725104655684175177, 4143398848385382705, 15142179196637056843, 17330386941741492571, 8185673125837710067, 14939737481973173962, 10478395787666924945, 2774689508274990026, 12451742284278860222, 10819437460867617255, 13731567691766219490, 2010973683387239919, 9908150371329956596, 5142510757399393995, 8739166923706997151, 16903649040425907246, 6887419514989237100, 1875697363324020800, 16410802797521308346, 135862499096678312, 1002710565280860416, 5506348106905501784, 11368287034717703998, 12947266586015982813, 5318254909926585664, 9296468205284792595, 8004814724160061752, 366393468717204226, 10790734687437783398, 4968864942084278227, 15798662312565535644, 1358717464422009379, 12888686466434430386, 370520483338984073, 9184642588343372758, 9427179068402613262, 10546786545869440465, 12655417731444306355, 9241957630409402290, 821497951821470195, 3197970711092278947, 2184424336239199737, 5106022623290447939, 16287048031456496603, 14037056338746814782, 7474000199931218562, 12188148167023924203, 4192028392289466906, 7847291769851591899, 3599561900723047299, 851922034760320751, 13587138821847499752, 15960408996225570897, 3252001517847791314, 794174927197992513, 13500786923616416327, 10492520307372562282, 17778963725733766896, 9940193524688369200, 7839429243680619309, 11152685327758330011, 4793514629906514769, 12571317405831554973, 14236764890442489777, 14285226682975878252, 4752465601541667238, 7069073862761309134, 18297621617638524964, 16921089529724869008, 15310629395363439387, 13959904965987734388, 5530325767118220975, 955257971161171732, 9249687876412175486, 6437014646360143974, 1355675591008680076, 14363814817404705228, 11444699168208672882, 16890344077647521215, 13663194688247169944, 9311758702620596945, 9111333905244008262, 3739308534752587737, 10082399017494306243, 14502104680453962352, 3240447658814963588, 1945616413338215240, 12702436196323839746, 15056103164643567233, 14232906369316952845, 8850081479512611348, 78742167026295742, 10346207199790592003, 8330318603106182342, 7555172829812303483, 9135554534047252825, 2213978715965424041, 14487841485121669529, 14201073224315526620, 12002576656710628646, 9216161229854384642, 15287364979646883311, 4707577895128497224, 14025232799632084648, 5317706395334588893, 1489525665074354154, 9157439364142092486, 7033808256892914411, 2856904746309353752, 11315255790030198921, 12167475608624586287, 14898366696798509538, 9918128939648387398, 15155651994814693417, 7300960472494546400, 2127526231515960912, 8923406206829661118, 16210393114988425815, 6582813395371196199, 15621762854392338472, 3789550044424910854, 16988798023618902953, 16490593537106458722, 14139545158028230044, 9923635478455782946, 8897217280317716469, 8453814653444266828, 7491325054712040563, 12316700761490127631, 3768457975900229126, 3000037930881673503, 16933057766750635435, 15031174928418481583, 3019987484089942716, 18385609936539305759, 17538768527945166806, 5447221007766299602, 4022798439534764827, 17074805847175217989, 9477194110020170032, 10200259846152838876, 6455055232471034376, 5679758327656142352, 7374147007380920949, 10200477410022066193, 2678287199491553725, 5011120062607229052, 7214257460239674372, 9631753064650306646, 1151983673963114572, 2455508156322019163, 13344796472161923955, 17003695385004214505, 11166307372098954131, 2221946328882472137, 7061489614039858629, 3790971501091116413, 7833733804721228481, 193935756315502298, 10256338066976304411, 6065749049589877362, 10736472690437134411, 10155365416269683464, 8189737882773858983, 13671211115390707327, 9578025336797949473, 4003423028251739147, 4500512304316856151, 16693811644887033093, 7707767344560596984, 5599541458797859603, 11592325835943024402, 13355669588132489385, 15932001697488084536, 9870357379952328535, 18310499762741838752, 16196774945614723862, 15790487345250753382, 11990590655367464148, 6718674416650039299, 14857329469228715563, 15423479737409206383, 17779878703537243863, 2210183662909405344, 2815540909030329829, 5940765014986549489, 16884893974961992656, 4351638805125702042, 17084353252120736247, 5724252085645496824, 17794301429798973952, 7949129492433028333, 17290229503720706399, 12839841549866653659, 14863383260888850679, 15788917858243172461, 12477975711782044218, 12362210923589911101, 12864920132785914749, 10860162458674426789, 15634366676531407135, 6076026769874036504, 12186624835981223643, 477838969646790588, 10209086843687255723, 4453597694185557465, 9792638779490749472, 8664773568287178159, 18322711946104316656, 5061590004040013161, 11611936838758532137, 3299611430381151917, 3978890638406515286, 5081581149863744934, 6181936955807580784, 3372188069238850634, 17854265102071578827, 1268076978660794505, 4722477313014336378, 5471980643922086499, 16788648796682094709, 13328529160256523927, 17816434316065398701, 4038311782651024619, 8255869964978262613, 8890037824421975027, 7319879894513022697, 15914698902244750946, 8857389029776818687, 441863541258666465, 3208037884158506723, 6113734693574039276, 264986606662698668, 1166237501799711319, 1823307447602740420, 5025672756710206999, 18278689422657324853, 4594507497487291210, 1280886041213346013, 11896598892872950706, 5576693076164380614, 10907097907235031727, 317196941106545936, 10598515286008372146, 10232665246931238263, 16641631582624438065, 1996845757059763068, 8450189738658666487, 16874433980334624325, 11462456373743157203, 17922058749640783486, 10312126789368172997, 13340565145612845891, 2211332034685909397, 6280821632118062402, 11495261020831147497, 7525751008510944548, 16481618138878161375, 17687291635686050126, 4726039693402439590, 6224312974372200845, 177270674822437819, 12844674102136119940, 2765095317735756740, 6375785787962152345, 4765877337254522185, 5699318866607950771, 7726266014961936643, 10439969907866586583, 11215604933445164846, 11144874084048847665, 16677507722859793772, 14926605406115980653, 11021418173114133993, 18143508384673173911, 17869384978881128193, 539841771736061948, 813906843235746774, 2120916504386756315, 17563694758070096975, 5807011249822640473, 12074412278826937750, 10494691749052118094, 4034710777981084065, 12945928140391853828, 13460531663356368909, 9805968628270501084, 8389235258735557083, 4653641631812286778, 8961436573446073348, 6695344158613046716, 16832827001219019801, 5227374831316662089, 5088308882683339576, 3279167959625059741, 10436103497832123501, 2797296687506317311, 18305760283738580632, 3531912382829235411, 8745021258521548248, 2062796519113317445, 7005506890190360164, 15260828944473012523, 11736618288708934540, 15523033936060000556, 9071328583193116055, 2949954518191771020, 9219149478710608069, 1788704922178497999, 3917123331723493156, 8283987826876682192, 3926515941902592230, 4576777655155350003, 2895291773949819710, 5409491793062473762, 7827016058731337158, 2360244091777092634, 17765210336693396066, 15413391993237156529, 9542656815625824892, 9430563399204843121, 11559365450247449510, 15796909749180552904, 62820771556683371, 17275496805851130274, 6527142162623953967, 4324187305635963626, 8775772925418898915, 4283973075245351015, 8846184539722500106, 2860502690824226817, 1240652940592194, 15064048316358894661, 15864254034666279286, 4098943802367114793, 2956682521101031793, 1877556925464957894, 9589792900125026809, 12161426439049578986, 6435540582736037161, 10575856639119978060, 14751225739652781433, 3642975302329400055, 10213336036038833464, 7137807512192531866, 15715238576819145647, 17891816262406767004, 2885759842806217828, 10001842985502100171, 16889965688337087910, 7192241521508241891, 12459052609846245573, 16045056395445218777, 14263408894637697194, 6319194484923808205, 6887168986137924562, 4723017923445345268, 8785445940747788332, 2221153194351157100, 4112058037714640844, 16624774310058492682, 18155682498135649179, 4932684590312312624, 6466580926084050461, 13095557293811313234, 5629819270691955218, 6705036397567572049, 15096504303120814344, 17813708390329054153, 2867801270346878637, 4428369643259246081, 14356128800268363075, 2105538175211522946, 8157169805154179676, 13281934124532911335, 721993975496515367, 9731311970803693633, 17408383560695508306, 3661032291356469843, 17118601234529144108, 14173384340046827967, 13956269658151533336, 14193288209519401944, 10854924829501094491, 9362722838007437994, 13139075107441548779, 53888779219483732, 9991228977857148506, 11866192603390104699, 1903043806364214756, 14664090553522048890, 94655028324146279, 5944941626254245313, 3067815658183085252, 10088835779690593635, 12586879497500128294, 17338285387265829132, 13546679410630118150, 4684155179104389445, 17373141188216408963, 10683275227724384825, 11727464505463619204, 16890013009763926299, 12256558554118856945, 1692369148468240661, 14260594858617396870, 8079067481737035693, 17302479952759473929, 3465288033646104738, 7033532051975356541, 5750806504528053243, 16142598027708695045, 3763071556050151375, 747332911728793689, 7125512446937882000, 1711762381076986594, 15200743445044769163, 567070148436076824, 11150986733649743405, 1751542514779667937, 14904426643112052682, 16243812463903474525, 4313436371286419450, 18281797249258270726, 13863976627696030069, 12604750965802575212, 10295616727116267978, 7795942372543067322, 6713137871239810667, 13830865828728404463, 11139257890131452244, 2759969414377994154, 151123411588221984, 1548247161690787301, 16234894685549118874, 13392592243844300663, 4341718471344294648, 7137644906875460827, 5416631993939117377, 11693386548832817142, 11851058952064231493, 9690204938813699131, 68528268163302809, 13565043622050152230, 7983220844142817842, 6794808910151851013, 2118666482985725107, 7247597207626321306, 16937693375274789158, 10616884815388828659, 11696015248644704721, 3352478958667054947, 3225871086863590754, 180230908445925268, 6654741577584823985, 11710009687907650028, 628457965752902770, 1735690146666342885, 16556237906505825388, 12440271636242780312, 8713058872068144699, 8975441040195700002, 10850963832660773043, 86339822673122508, 4000323666157343936, 12142567722725546249, 3374710818178624781, 6392232680788016964, 12790199390015157427, 4671003891873822839, 4452182512321524727, 3905095889403963026, 16726139916064776463, 3453332349452466770, 16221710379420353742, 4632551944540970365, 8387501246722919769, 9326344266173346561, 14810846036626389828, 7283658938651037849, 5813262143148998917, 11727805907650385268, 9857096480403873519, 6356324418997451940, 4218579215729792881, 10470999063206203293, 622196070040738252, 17021144211023071215, 272053703337182123, 1450758744433386057, 8397337301039096971, 1756739264090010567, 14804942979114893233, 12762190712783408010, 4486114271404551982, 13538690353341899530, 6182493449368831960, 2768435790455158079, 8491588540734758297, 5001428683933385935, 16861055012236061995, 10578636081126268849, 14449779720168257980, 9370646703732609468, 476896208068404545, 11604128769892258429, 3178840918267575500, 3407583825966649895, 17913378662961900390, 1138652617523020638, 4702124733398535376, 16197108716716127538, 16852598869081929632, 5020614776073585872, 1188708373797737364, 13456434315549496452, 3798071449732352219, 6593816705053129140, 8463318160472344568, 10114730768365942765, 2093191144313711189, 12720945689550243678, 17481264965133664645, 17640221870440170657, 3490097599238691289, 3624992904734580452, 5383687377060455481, 10776924742527744182, 15746021472289883888, 17925392760128571522, 12689005861958409137, 5231100489367895272, 14007286820825332338, 2397858260918981403, 3320067181759583430, 18227252228223404573, 18011328143837002368, 4798104660333169602, 10865877383638846865, 3767167656736085179, 13252620599128939387, 6636747284560413010, 13514887050922862847, 422456370340431886, 9612933469182009435, 8572209183721381907, 8056048067037472186, 16714990476240297166, 3520645146861432874, 4395550491627332110, 9462218612700999094, 6214250154185857186, 7628194292741759764, 3556878717144745691, 18413027616459454704, 10160691680912469038, 13717170760433051685, 15180833335295580609, 1819382907555618141, 13320476638466170165, 10422294181974936444, 7164181547072169074, 4206492057553506325, 12633015044784588629, 379171732810097117, 10351100759422011738, 3673330411049649463, 15927757725693044281, 13690250449236882125, 15900551197649269941, 18329662994600175312, 2110669219011944740, 2226752393294287183, 1014550150137152480, 9887871066385753226, 4568683160401484222, 10951431797661196524, 2312645127290056695, 16937439673591720324, 6396609076318661377, 8389300110486808887, 1923677274274786580, 3549825163974227141, 8566399761898493308, 639620030714191084, 768228320555967661, 8108418530085400912, 10272182341228792152, 16750158829727849854, 4444117530817286053, 586462195320680600, 4278069062735193163, 4273315131401359275, 11611787428091079232, 11835985289253260719, 3096230712379885797, 5322239580881209060, 11938666223318366819, 5060592382016062327, 109409443906808448, 2380457102117134635, 15857731461784222805, 6584665638956888535, 5947254465908568523, 9420786545084124002, 4503761263873856534, 6641486141146012370, 9121700908113990684, 9720958769231915561, 7003782806520614311, 16920307773004245532, 12763580883987437513, 13231043349317133789, 16203109836791501802, 698049430375939280, 3030494131166195541, 10815604140749178453, 13804995432448225904, 2055424018541357006, 17073648888173819706, 15463924428711597599, 13403700103090470402, 16763806955533746160, 10509071477142331263, 7405199613665848444, 1289961083639614668, 13019156453931533504, 511380020193300140, 15833618630547184883, 16532434650886462678, 7779349734049489490, 6380411322746302134, 9492908436973173105, 7167088077189974813, 17396059932024334263, 16483611260630861934, 9669468321319436238, 12712646425834594093, 9288405016973860570, 11325843021373113165, 11258335193384041947, 1997545595799365359, 17390606419645620788, 5130387948734042681, 3121742342628196576, 6099609462914905352, 6524840389448497409, 3251588966299685263, 12515453442966781968, 4351131781828315306, 7915089733711494046, 8605641240710406093, 11102717433954517200, 8816805538627940082, 17227753413606850602, 10263075023716628113, 7686631682618468388, 10330530590800536028, 2587341603576202527, 11500396296312301825, 13531587115648414633, 15808917747546864365, 14333112763098420691, 14761783111500015307, 53964954401492398, 16533467491022296104, 3096485428305684908, 6318844018415466634, 7132560604178571060, 16428604738409136626, 4375929108222206025, 10112133284375140971, 3256631261503314080, 16136845689782815155, 15928971771356595498, 14645130502697393764, 14481748170304871772, 1698922547070724229, 9468607121868930261, 11617214057068823437, 1382928294652688250, 12680084220201263431, 15926122141331194025, 7979147799621842755, 9803599832824191350, 11150566171126503035, 11946016594155356252, 8452284422264862510, 8621047342992105610, 8991106617593209637, 4607652189428377711, 312850746210123282, 13020253158865282886, 9665527964173507749, 18176337504665053651, 10689513521305445515, 1839607582702602917, 13793618456770339778, 12156395506174115903, 15230345865671590927, 4715973552531673115, 14606516029379763286, 17293771405588962821, 16175698567845501145, 3789965395433901756, 7250432289837425960, 2507460993020556336, 16416011798948565038, 6033312224978543324, 14568892906298810894, 9207153067892339499, 14537938431481818790, 16550516704016530385, 9907670198667127499, 11918889385815695319, 5981318855234384164, 6303359496211585544, 897784439258088201, 7533487805017595619, 5938457201719040924, 10019150195260257017, 12026554931880038202, 9224513724236448133, 18208973061276109233, 14240550756243930801, 15387974810151313549, 193781859214087276, 11713954174101604255, 1341093990140003013, 6012491122871297010, 13892530467037865965, 1368649256526022373, 7020819021722718671, 15787587617733723291, 7785870968748246057, 1947448600658942561, 16530328214840567615, 6317941331086952570, 7139842027589405175, 10933153414206777090, 9672586073744099620, 17228494407277874159, 11578033579087247602, 15459493510831207600, 8222705886823487604, 578413881840029844, 2972330100500591542, 7515621234174823899, 6704318956697481184, 7539293268516643247, 1580608997901534862, 1201050878740265829, 10170365701874480907, 9870363666224664306, 17305296184407747996, 4224805619364289032, 15085837243579345311, 2443632602903912157, 13046843267919167284, 12116351035376725179, 263232896451917215, 7772071638110042980, 16549817644785034122, 15257628965480096285, 13004189693733577363, 3864285740392230962, 3468607145721577697, 354566527372793754, 12925883576993237617, 12693175375557728813, 622461988842871628, 11397527121006480165, 12911631110359477732, 13101149248297235307, 3443924800339223639, 11021054325079132422, 5789359016899607332, 15670032899436160802, 17231336489372520758, 15011195019101462587, 17697169511730379360, 6214385185627447169, 10180011765464756731, 11047248145840743090, 2742832730133990272, 14029491892088421031, 7977004417662816272, 14199429721808423163, 18279997024327708476, 13359704350594785266, 18410294947752215697, 4900459096393373794, 17759944268317835227, 7514273237508120753, 5036409225635108741, 18108376710275555530, 2676982762515162946, 510220139774948017, 9208245069742717667, 10376186455595199891, 421637325546718875, 16791119924695165602, 5075099022211468458, 12517850612529158688, 14010730112031892170, 9181830456575508952, 8562092376348428853, 13106552497603917850, 14302339172367595976, 3354417171377350434, 11375931064094009915, 7367612779037974062, 17960646160089319914, 7765039110674214207, 11258859351125514864, 6790503465712539668, 15367600556170700044, 6616796092052086761, 12472062233228758417, 6844102383328993237, 12811249515443122455, 5102740036611216259, 15944761788498002902, 14694830622589958200, 2106296585469395117, 12001390986454100522, 3886258101634881021, 7626447484564536615, 12121778508662936673, 4637632611996699763, 284639519767470911, 6111767225293430109, 14899978058938638435, 9492490138059005865, 3457376194893217608, 6384991674167924954, 16479663265444998572, 2182180597909020672, 15349832040611960272, 6995769868581799282, 7434433066635564427, 7330931577518389882, 11026383041313003706, 12870325652218422628, 1151311929447712791, 9598200806509616050, 17161065747263888006, 6901765437989220429, 17524807833762947972, 7424089904607803796, 10169273845585922571, 427683750176118191, 16198716196396797311, 4234469982734082109, 10433113399561032205, 8455659057075573351, 5339947829324400827, 8994757262942082927, 16110373093388044843, 8165219755821135739, 11079951015921397003, 17913162205445436558, 18307573113704258140, 5184334744599569992, 8209592006521651537, 15233048304519008983, 3893904742760952245, 12843184579518607189, 16317789833580002355, 3932965922048250109, 39643566078340112, 14454778211007988105, 11325761588512978910, 7326308723838667358, 918638912645150633, 11749550850384896237, 11656774623671896072, 4102579533296639675, 1131200342214858221, 17002635763021940679, 12699501461265202766, 18366533628748257986, 4211496006430696197, 15592383694738584641, 12132073284414780422, 14112124548036073660, 640983069936058034, 12843837916043035998, 12619927090786907296, 14878814042191779303, 26802691526432636, 13542740387876579301, 3027951464265029786, 16531319427892075667, 7433366770688989904, 17675108936726475823, 12991848794171434707, 11308307557943773008, 8441361375349434971, 16048668185725998079, 6848195560782317706, 15732631277486546880, 8796031012662685103, 471880524013342791, 2847727284878021151, 8909402802655050731, 9155393982976367055, 5339419398360353054, 12394943475850749453, 1082481852253596422, 2475925758143360234, 16780844326338173281, 9955442783741736414, 16398521725460554238, 11754389093333746016, 9510081579192799387, 10740614081401142716, 6751836211534532930, 3310216743613517077, 4711354618706526528, 11761966320912417805, 36323519866736684, 2431075662700945654, 15771975356730131291, 14504980176985527547, 5551404397884447150, 7328632262405216781, 6659335151951442348, 12904376258123706403, 14766024566003307212, 2729153030346049029, 9776447889426450664, 8565088926995480737, 12733048698734167426, 16140690590167093278, 11999311158468044755, 13598288633972733571, 13732432400180070386, 15194135950298716633, 13160554968820068964, 10539080943199862762, 15115912129273478029, 17652613656477189074, 7952212396658049573, 16131569825649579263, 14739342068703048684, 2756008787672952449, 17980612557340090024, 4505357043573157185, 5886347178459794981, 13467166348185532762, 7542340141940109840, 8604473128836312462, 14161530301987102049, 7768636854450163149, 14487815318986749283, 6851630924543230233, 15816812718841829697, 13309960537373415159, 13533823018337269511, 4066246092121693604, 9157035362257855573, 412214665099375028, 14477789736289307578, 8471884807077804890, 5401116457851954216, 448871182302722508, 11307725734317055468, 10916897930231800956, 12320324583264666269, 9855253221365914708, 10341139850853598251, 473763070798790310, 2738091302514798630, 5726660080813664052, 4685085520987362, 142836371012422078, 12594070839012993809, 10074822048682622819, 12827059438505836814, 16625605990012653363, 5223703331085192665, 9833285584664723263, 8290425612857589870, 6306954960404098112, 9412474111491552241, 3143257994045884457, 16371722385530408059, 155878147658248091, 14824551048836933161, 6944511999081736143, 12540758531163865907, 11983135069038529053, 4545712278933588398, 15077557719097293644, 8824726955621677512, 9467059989026717476, 1832994947759543686, 9395963500530779164, 10187513723496037742, 9614996490866381781, 4074827755791565698, 12833908036330960194, 16292730478901857762, 17035820163674794684, 989273775053529110, 10590449105705689408, 2922575348536557726, 9097036857789013295, 12287791133096088844, 11574082336078807433, 16687006015927882120, 8596744673168310178, 8970905056348840750, 5517972678784462826, 881430805465529877, 3412610955059774968, 7028178389869167183, 5170343795610265286, 11012307439076817531, 12613254778376420629, 4047156878552340678, 14789560647177930279, 4218958252980142613, 6013379809704688444, 10780282427110087598, 3110875217681031780, 1760113645124538802, 4510301077917148010, 11245657134256982381, 3975465112728195039, 10147869619910151776, 9521542758217967325, 9796643369778561059, 18438740993593422996, 5755122647194246655, 13089871854524075038, 6020811568278170849, 2905460035802413789, 5770692989150859960, 9121733696504177003, 9054740045617104954, 6651061222026801570, 6979411400071458744, 3760933926638598638, 16334302020381288285, 2057660950359678276, 11293316249797872974, 11604535997697431331, 11921660539545426320, 9756548788646446777, 7269421896006778050, 3975439838039732758, 4483475473549910496, 11780853832789946501, 8179840661787229204, 2659883347338825753, 11257903019053621162, 9583945287877466892, 16363933527036814071, 1290785704105238692, 8655198258069320180, 12518299182873150764, 7361462000368712194, 9733702303272955573, 2362863984326388251, 14125653338074659438, 8452977297932581636, 12482787099763665262, 14889071888466818806, 13718685624353930921, 5045136353562987858, 5296643588295054890, 13213371806126402767, 3277278393660323717, 5669363365118437907, 15016463550423536857, 16936344489863263921, 2565955327304029560, 4796734652908453706, 1378655232854232950, 9591923038316868621, 16194271618909991898, 8523814065658657216, 968783876319889044, 11876875087504947472, 15343430958924511022, 4726016088940609325, 15814602580682745621, 17553495950903097582, 3845404925865098583, 18216981879371013309, 4102006890010720614, 15988113496959934091, 6019266456198657999, 11837451541533231967, 1877408958200970989, 11155878481768284249, 16966216363889316426, 16449662703095636488, 11722657415321325203, 8151686270422518591, 6829105588528021796, 5605072424730907975, 9610630778445319623, 12490688233524207364, 15924383595417258143, 6293909456050977691, 1520031459958370315, 16878056482786965582, 1567491557266512441, 11553059083075601436, 16588286805077499576, 2831700015193252058, 9291679435178297105, 16696183961702972685, 6110717331497256774, 3508641981673281301, 2888222167255453397, 6382434826249612462, 1615495003744037219, 3450690972855989121, 7373699525385823603, 1487214282399378665, 5054239246312770486, 6325543252810070667, 604916284274232643, 5705249803789781860, 1347389337137481378, 17341491803371701023, 7562092053824458983, 11528860291431916871, 10058885809804159773, 12028682695619691748, 2072309850975849144, 17510902039090560383, 10964691654809950146, 8557150693328114885, 10018287661176094357, 12067793619240607034, 12258652923874874737, 14315661805556678059, 1532344907755129707, 11548306890701017011, 9836569326549702085, 13196528743664879413, 16910466377189639446, 305247665277886260, 10234652344969601959, 6426209661333831948, 13316514153882647236, 320668129269757278, 9513807142666087825, 12132502292274229629, 7907062113630478532, 6769256578404078947, 11077216337588272062, 11192173094112274045, 8665424743913923338, 17273052641666860613, 8242738008086379196, 13851918804734763571, 7049674271488004214, 1410604294587433641, 13544384176158464923, 12468330754572317265, 1317196613823108318, 406832464837758362, 6039154084839734004, 1995025881371264773, 15399759218648596543, 7323767619167721842, 14228968351368149001, 14556483677198851362, 10822573411785744110, 13457687797488671733, 15113597365244568644, 5830040833200595947, 10782120448577939853, 5923233368326767564, 13565433709591402733, 7409835447323460538, 4942580795960776301, 8068857330020361381, 11063008871093537743, 6583328726807166886, 2194893842926463044, 9586490095482756942, 11811119386143060256, 3644614927094824958, 4762559862573353606, 7054841812193239255, 104169344287246978, 13956225391862408166, 4507288715283113798, 11772996098884686986, 12792586168475881829, 15798457727837504001, 16896795677207949298, 10265172010623416483, 14814049521182301273, 14251567652536773005, 11041033214099412656, 6589290323087713529, 17080306026857684487, 8536449894500168140, 13538904949191682258, 998478434926587432, 14670273496850215516, 15311327973305354729, 12644104051633342488, 12970733262467631495, 4625272733914046269, 4694472538276404068, 3167371560249938056, 12856489429820568743, 15490218655488023802, 16928081564771690940, 8200145788070169286, 3346452930233714534, 12795482436352374291, 3314315705851242852, 3285152211139935017, 11224563416094698786, 9705270177443534531, 17644295182363680941, 13520301373099144288, 3541351715009433425, 16020276637771846482, 6027464490277968416, 4251343941648935652, 17763014962498696031, 720132515041512177, 5173394266280593900, 15204667210087004583, 17335914961708883300, 13218634015062319702, 128827822406486046, 13559392235200971420, 17252636495073021415, 750007296061102031, 18254099543935170871, 7509241234704231102, 8157193578702246807, 10298529352072110821, 5298418177375924856, 4741852588831255524, 14527267204533561544, 9095259534397569417, 344527310846137539, 13247449783957233078, 2586644247732041192, 3100790169250176954, 16510173867908259851, 11333281937378448547, 10849352377567806999, 18082377466933472402, 13561723472079052715, 14547157815982897407, 9391369342410485871, 2348830231178979433, 16863733530713957956, 18119733445408743443, 13725121556809406883, 9229975878895702895, 7401016155946807916, 4811692959864213177, 6237359194264984939, 1904440073749912075, 6353600963009324869, 4984137724622228146, 1196090958128593834, 5119707990981594180, 3310978073014066771, 12983216966379762511, 6612762118768660390, 4003198331951059920, 6385796970903716569, 17680686381236190132, 7090591178254990847, 13123476457069922276, 11991645307762636710, 5129610078187868363, 5604361132348700067, 11043762682351635495, 6391120985682487625, 4455513730428273542, 3762654197950669235, 9310420262887992163, 11993439152830872164, 15439986350739535069, 1488229606606016585, 8189570287966130481, 16920767496097942040, 7797006069350129228, 17531953262576833935, 17024439366185018969, 8083356010952666614, 6837066330579419154, 6443183984423798969, 4776996086855661713, 9156255850041051387, 6083831993070398816, 14543764421371224439, 11977571598909514982, 10188060030334373973, 9449009160086154971, 1300044225109284268, 8825712025626564634, 5510762923192959602, 7324962531338046625, 11942013042939202021, 13598796371758253088, 3794998887633576199, 5084084225782194038, 15889660289095533051, 15428522601238467679, 13696067867927948600, 1072542240072425197, 9785760286300726328, 17624535067298229622, 3938570677885383673, 3705077412606219929, 5340068085943913770, 4210056340846145048, 1976665594829638831, 13311220586145473347, 6943938959824844891, 7268540691149845607, 4375885954089016506, 14963703931344653483, 2580585000938123597, 1068177107148635952, 2341910556569696351, 9142288039937977251, 8517576956327184753, 3376248516190748921, 13301443214809490744, 13173593921898127720, 17359893842944679338, 7047222128454518811, 5947406210583265494, 7833766002049023813, 18234948673625328162, 16320032712674678534, 12642441645902018157, 16283613144322847005, 7863579138098504089, 6035051266438089663, 5453172248583632847, 13775470103081167926, 1182333285767268205, 10495826772905540632, 3056962127861644896, 3638669906264037789, 11198631986907530450, 13541149168510941603, 3250675262588623536, 1880073565717482485, 11936216765079705804, 7530067836231811508, 16311420158606635425, 14900155531445760709, 9999132967166761272, 1476154866153451041, 7195014637072196640, 7248062023586150152, 12914546489578466976, 16344645330454865081, 13063707322424725098, 15370611307815629185, 2118132721549701162, 14789791523379164567, 13011177800824348207, 18047963884795850285, 13689837669785098672, 5906277653382226335, 2699555162272597747, 14303717239113776133, 3323572003892592160, 2809044788581830880, 12842135035209068787, 12962493426638468571, 7435779585695058098, 677266868482172083, 10678064418979058702, 10945593620822631517, 8023058850263770330, 13198960821944542699, 11380271889111358356, 8834711603621437912, 4878802483786297049, 13441769216931046849, 2621489868509896160, 2739596448875968624, 18316605028815878992, 6393166579696267066, 16501151485480928243, 5164267149115550765, 2594692795895679355, 14280335185447698254, 4970220064329069703, 12700511247281457031, 9357661341818532747, 5976227213729484842, 2603370613961010712, 12878876453986011658, 12614332416265768442, 11711218014924643648, 10655032017324143953, 17992359291438428544, 2028340169188763801, 11337597956814839013, 3790580704158447112, 15661080312640132051, 5990952720662828532, 2238062688033035456, 7214374085319154262, 6225683889287881657, 14352811622893565131, 14441940256427869428, 11264789359569297809, 13541671887968904175, 8127321364325418809, 1617127834649530192, 11585884571784117082, 3211445923374162685, 17806365145235708527, 14310538800447604307, 6443392190904066779, 12304012177210398685, 9644770647148205176, 10349883319707014538, 13335242320392313944, 11550748494455916510, 14451727464612357396, 12354315710763337118, 5654383747200879937, 12534212795765636178, 5562388391253840440, 18294236533364599656, 1155120808307866205, 7354961778452510694, 18411509148244472731, 16833067451811570610, 11664219918607046336, 1931829024033366436, 9466235535733377083, 16125981341055192255, 13123158579309508422, 2811914968022899296, 13666576380287885316, 12073873146611787542, 13976563976935754757, 16819184991876208483, 7126372516019046104, 3771351679962818186, 14749464410272499350, 1158403298912255932, 2704550233949493414, 2361919431011664920, 5147560855044821678, 316960590350675551, 8956506393667806523, 14816316691312040724, 5483483435418414420, 16492702091910529628, 11531197856172089811, 9119688446381120307, 9148465870444231525, 11348956949863877257, 16515747438741224650, 14748627773020492829, 6792333258618815286, 12745044341734710216, 9118601693019210121, 3426576167844415246, 4516979855142897567, 18383203113196616305, 6037335393642080610, 5178029553332071284, 120594988188384758, 16911068593865363851, 5611330513352860577, 3672922004740508910, 9348962843954154258, 13167081398063848866, 8662579917294749869, 7714235959241362618, 1992168626444259154, 2892890698408203389, 4458208962709454498, 16006038729069481615, 9254965750786898182, 9178915422232682008, 7329871300650615008, 3409678840041114839, 8437730364512235388, 12654053093050306243, 17603379767897285990, 11140578823362012333, 18400373855086378549, 13179220706346381456, 9393189516096637793, 7962379756613380226, 3887762359860195719, 4702005148801552936, 13554138609046523902, 16949160381904484821, 11391648750970778464, 3884921049575088732, 2209098818625079997, 17799308759029324494, 8498222108115834352, 5958053849320451390, 2912489977852727908, 9002784252893780496, 9103973893872873428, 8800570704285521553, 8871184059044310741, 16063400495158915832, 4031307968282193036, 8573254083908951390, 16828584717166299815, 6494527269040260826, 7249207279315565170, 13665554008066255134, 16839236341242902217, 4123411447375871691, 10234357340093040168, 3518390908608069874, 1349715014789845667, 4808798653471270523, 10095338955926329757, 12695489128540790910, 16406780457966718375, 9629301538534411032, 15498997222980997073, 14953211317262356769, 13024285896073029281, 14612862358802352485, 13035854789120349150, 7106552057026833281, 14174041880363702304, 10636381469539675255, 7187203466667480841, 17084717625060872520, 14126252750523939037, 15698822748718907462, 7397904980198721162, 3690934666532247692, 15065052457896220534, 18426160025856536769, 8825186243264577791, 1029026778404309644, 6950954458719738495, 8771914568967577350, 9728022865849579333, 17765239852650572501, 8343956648157842199, 6334778100080475126, 14664915370166297479, 12941375852754193937, 6405436436050091550, 9909891363532277572, 17675467189601777836, 12324897459248787941, 13981335142409795938, 17744674612593350856, 2757587566489447009, 8956578028983169012, 17018240562727015214, 16391639968111798359, 10795774151465209457, 2093281970351304070, 4858229909673020125, 9933967343419708401, 6016509820559456727, 8502253989054157587, 1829270427581251166, 15709494579608995279, 8568909950760020667, 10892820698227375197, 14181785622385373392, 1741244869916907800, 5584342639358924336, 10920058455798795209, 8773147161499562392, 17372651285045475439, 4317270331835178992, 12072221230432227872, 5409998193192839065, 5774604676764375748, 6270673186535390929, 11593578005123149455, 1350291030727318811, 1734041789149423611, 17594245397221493182, 10230281830065256754, 17395251244463936984, 6363273717700984685, 6898868518537597264, 5078809256797027276, 16014780232233692324, 12698021273486013402, 10034628326465398981, 803921083181133037, 15053987885932962839, 2543409146477711493, 1443575144201918042, 15527634810280511429, 4846659158470140918, 12183993101313012462, 12953651110928456969, 15038003468538497849, 16252394591537250522, 4193562522090296620, 12800591763579590396, 15408603400942806170, 17682640208554596681, 12409260763379977486, 9315397818726387830, 14193643034683668324, 16508104272720261755, 13905815394730317134, 3679293709974358468, 5907121386159753765, 5304769534414875015, 18444287322445993596, 16494909212649576365, 1411980536871151577, 16554121151776992767, 10463210072047518059, 18023249470213998238, 12383793606215823679, 800485989566329537, 15071139529581604306, 1895628018455249296, 1105126069974836026, 663584933815778847, 3312928249076628720, 16646825576352631842, 12151072254529924642, 8642785126263747138, 15111584853907028239, 2776308895820674677, 10812673714292641746, 15054903323219264732, 2933094921150563585, 17830062919092998452, 10432330036767081552, 1033494976738144353, 9761049718456631119, 2978550270506139328, 2266577450295768406, 1214959603409486419, 4338607014040436, 4115159162283844446, 16888561205519247430, 4412890126763454080, 85232547048588047, 9970948529228850752, 3713393126801217778, 10760802738778841380, 4895931449000106045, 7255762665740428559, 335936537100116164, 17662778773720603199, 12685690660905184006, 14808811012699062151, 10663380197090780332, 7067049757688041329, 5878922448066220307, 14490189620281922843, 14473260627169887886, 14832232348370447833, 5951438093661647765, 4872796166881199876, 10429350570401478982, 15251172935852223950, 7325621106097392986, 11834629549993290294, 11569303197879748368, 977753391334101798, 6969686311950446853, 7366200137172124620, 14212998724743560415, 8081354270400804456, 880037272912518632, 380852277882293501, 8947498467697222234, 12757931014561147509, 667810441349799809, 2059689120439565076, 4750342010666522618, 12492546560830555305, 10465223395020225996, 9585389043436680319, 16512031046174235646, 9200703296926083957, 2032951915453711444, 8002381174072382487, 2389280604724196215, 5721524692632905547, 7647110976590069211, 12059178411864741586, 11975912934455308497, 17753420811972470476, 9192795740173474360, 12105166740957629248, 1250032644270746132, 4765787287696278663, 13422669569705597563, 11373393845567526876, 9153761787497611672, 12030450058080806969, 16537144145501712177, 5983397454957073922, 2683673672010015032, 3861849825629132671, 12629475949497494729, 9966234113604834798, 8466461060632654110, 3335857898642241962, 10682117780482341111, 39787149161941136, 5109208035333406420, 15684027554962652735, 11748970404336820351, 4095159288133322954, 11402790565133565981, 7401785106763668233, 6248303083190138658, 8738855753439299071, 15339296752899687482, 3182643107247815384, 9378566535341755855, 14162009846460499887, 4109114270719890973, 1511416153435046138, 9020508522805341634, 7477142615652523025, 18385803953807265839, 2546195602154738889, 7405815335061777589, 669094957884330982, 6056073383962448124, 7353716808540962518, 4360012167404246482, 9748894070631625514, 533481526701689863, 10374030482918918166, 8591056344610511021, 5753611323076772742, 17682325790000893453, 17410739240868104811, 5651721564405833200, 6771155463622294161, 16102506172900055409, 3922155114242412611, 8047195046803908182, 10181935025035061310, 7790459581343029499, 12616035204180788696, 11350000801651108812, 9664257517083996508, 6877290837507516646, 2900668296021062883, 5478674374212655343, 6296162153147759087, 16234745308754151636, 7633277882818614712, 12843201503731712898, 14050083812260020416, 95836250787434633, 8997148048216279615, 5687865929885690952, 7684029056960298539, 17362423790832901707, 15489463223618769754, 489477444088932230, 17185715982289417959, 11823522798262762160, 16827938740128105724, 13257410922007807743, 4679309639860400639, 10164917239224603264, 7304922446473936277, 5597481581945817575, 3820424595621388213, 6884972150866725771, 2694324376629657414, 16833520400918984369, 10912563532735352632, 7352008235482304863, 15885791964406330114, 11790453162438620892, 7239285021069261812, 10125071555494474444, 3796211625840968848, 193266766691985397, 14792644085266904226, 12987152514130686235, 9436744123646480376, 8251406129814681521, 6271920831800751835, 12738844182063426283, 15330691163818996222, 1166041665727565335, 13315209544138143871, 2216677316767409466, 12690036582164080137, 3031307738126062683, 11944440105997765289, 2026188631449062025, 9212773879860499293, 3341981308024472580, ], &[ 13169652012768583147, 11662749290968821290, 15540028649212863382, 15222191772599122928, 15852211273603082347, 2960464712590969339, 9805532347048503730, 11483156842014743008, 12223751000089978338, 2069577308821362462, 448020966454441311, 3493610387626232963, 5182130948708681868, 4456536535034921689, 14139535083059739910, 16341604127053129275, 8476750032358968964, 10942274856214572646, 4426573651999058804, 17958371714565221264, 4238987860855800392, 14450925264923938948, 4364481289454625563, 13074790925168694865, 17725186031491616550, 3252385755044260850, 2489691844698347065, 12584453984545921259, 16484939371755776909, 17591699265602016514, 387926126025483991, 2463760292646247776, 1563580628888369628, 12118979090065897855, 7930230430393343357, 8834023487181578700, 3705061516543521950, 4053176902619603587, 6269266280509284877, 5236641881717368169, 6899670106034156441, 12840225294220778634, 3029440279850048735, 9595166473221718273, 14550471357175468027, 1255830945916836371, 5122133954630663971, 1502740582962090101, 9086275497101221342, 5421916064800438697, 2179464833779544632, 8247585817871008274, 10322070671895980987, 10962237209348590213, 1167315820290398061, 4563405457798620948, 5324869835018392710, 3941515430275954463, 1740094742017128848, 6138471019874045522, 9176213051434147108, 12501904812453849864, 11388325168842467058, 17687408972570957542, 4497137255970523312, 11770269946165024215, 10156397926378383551, 2019377424484113393, 3590983554593693717, 15657928449196312716, 14894403732533901822, 14625564293418317463, 17710716015671252818, 638852277383858770, 13800670797826096071, 5519007738268375392, 1013914690263468265, 13249504241724137521, 12893315643913486917, 2437939332985629386, 9866735673756110580, 7894145839618709904, 7802203558085957599, 2394814001366981818, 7648858197866754106, 45932857419714984, 9659675215715090679, 12803466849037463477, 10717587339591792614, 15131328571226415781, 17805628124155724278, 13655343682572989974, 17362327502804463995, 1075287460052064029, 2626850396158965217, 6885136253881452991, 18424853270962528365, 17198461501972637926, 6379806426022159044, 8783653573177405838, 11457364326293914599, 4889546163609369345, 8345334679410921999, 8128212263869118047, 5243835377297724594, 13077589216209892913, 14947690960428829294, 7468326754846892750, 8665069680383178636, 17267364262089018920, 14794644088627434581, 5781944628494317535, 13467037542503882140, 5504287258083448304, 3101706185952735851, 16528687565738693574, 6853101285149030710, 958150364135525317, 13159192403688468400, 9000130047394330226, 12454106782612240528, 10410037892467703265, 2755063393447593674, 16909229563067880679, 14030067308250726680, 304063827283258286, 18020451823918033658, 4591035690657100956, 13162350837887011458, 7701399978207767086, 15815279200816529309, 15597387052720630170, 4740390593486726162, 2909712595092459460, 15729877265226222100, 12096570103612063938, 13702753332858235272, 1411835182384377603, 17487917594195511154, 996305544975114980, 12929066524383774152, 16956610067055251962, 13012122099231548957, 14395689158572846177, 7935429077563080059, 17542764935243101497, 18413828249925519615, 17271321257298840331, 406766324155888956, 14818331828215117974, 8187386216945380849, 16792638575276899182, 6540004189057298818, 465689003663102769, 11974785539062893556, 11523099967255714584, 14591636912283935445, 4871757987380755363, 9308130069290886865, 10612219179153523310, 5420071244571425562, 12724302122592532888, 5173545157589181140, 1429324130148847596, 18414282026575416657, 1721766939064217260, 185288146264311331, 8027581238524003859, 12629121378225318691, 5422022678890177669, 6300007666394297907, 13771277516427401556, 4461063943424152501, 5814271695863693557, 9833762282568603070, 5534898830643720899, 11414581203473717153, 13252208296859650317, 6070377927034194834, 468982118171070321, 15569817073538385644, 8515954578625472255, 17703147536676285546, 2713926565223832109, 16501613896332875878, 12360649233716580846, 6951122318765494287, 1255018572838364315, 5022530899188934293, 14471021290055621346, 3965972119993826976, 10914640319991729939, 4671893019190076511, 8132288757883741990, 7379730619550447967, 7082846353163966035, 7749284037330602929, 17090786448482076935, 3623093583024522445, 6775174256836032571, 5932859643874401763, 9263718069255818484, 11941172789559596258, 7505495305758940713, 8374557854631657796, 5030384219708396008, 3609081759463861677, 2444176790044307758, 12883357531875110193, 2545675590276006076, 1091049428613676247, 3001645527995991696, 9613284625002680960, 13486970893816936976, 11564610387350917328, 7838720830134816136, 3368189672511472263, 16407993343222005051, 3965440550685537978, 4708478243468404768, 1875742626798710446, 109477476572266497, 9185060711428219960, 2062557879153655855, 15504010890019002364, 1436468774610332740, 470895386030379118, 11192666441535176072, 7094623340817246353, 16041820192281853667, 5048179711756437977, 1908765243120848557, 10810219542319634593, 15971282719319513661, 8395180060853137311, 17415231760777435363, 10489441496511966940, 3213813993411776195, 13309643264471443871, 14152370013037392509, 9805694808649718454, 2991106746654603900, 2279780759950444362, 13989789024965052794, 11942900996372546394, 15051646099368945987, 7583267444740224154, 5192555551306992142, 13216959612015226558, 14397593124921798192, 4374707725758052604, 15529039788482882168, 16475619415913302762, 2649655538625316107, 11899566009797061232, 16892018353302708322, 12364166218684092426, 10372683350152669575, 5328477050361662527, 10949313792626687170, 11924230090558408019, 636095257275314085, 10210914536395617961, 6515368615710817299, 17001040330117317563, 4519581466335837391, 12514298524110577503, 1744739741016504912, 9689951195577973993, 2774540351629210180, 7646006525601223889, 7530479442266342421, 10538917317906671989, 6031253606146099659, 4606167752034374890, 17763804757970320617, 6871166461842469695, 3069238346134678776, 6898492556629873366, 18330913680324098797, 11469514731644700404, 541525751461369940, 18096353837092553451, 16390355202675291281, 11980660197830118439, 15349236833293249382, 1901608480726107605, 10754477505423276549, 1780265741680781169, 6204486525934807168, 2675596223932028138, 1082656654749778403, 15313246555910578407, 16597928615331243076, 9259667019969423039, 13966308744186245944, 3711817850123753976, 10380302371138242940, 1102076039759449071, 1796134829015781040, 8320143967311972799, 12603759772660781109, 9343508021191710450, 11833581848018650785, 5036078561764059265, 14477046704375156568, 17958581882146395247, 6312863763728381603, 5890775652924120757, 3024100139720533291, 15594980805126031556, 9929023026443104564, 6003618257535256748, 10584762467178432077, 8070692469310128137, 3448506857138757663, 12067250229870443464, 8289617863280099780, 7705347156484755083, 8239333463449775936, 12953560490361273923, 7863343728067574413, 15499170354027597711, 16789849673988523596, 193554686279189480, 9324166766841362509, 17865442848307712220, 4017570072096420828, 359910874540192895, 14283136222667718022, 15545842610688758167, 9161703351540143861, 10856046010222875891, 270665191423043189, 15816860058997167317, 10604344774996324885, 3421439666836669232, 15362489920565158049, 901986887674190509, 8102011985696643347, 9831189590417175739, 7694208525827500802, 17761503253302918415, 16843825659097088549, 15968418888658984723, 13213298841864639514, 10768746828601368994, 15843374988242905966, 10372481985078119452, 7145529267057724453, 588445411774656377, 6907651744680403237, 13729433346623178186, 7466282812151723072, 2397976897839660773, 3595288154116844222, 3771046205661211665, 18292138992930644589, 5076094080207419189, 16955129624357257007, 3929215337030354093, 11057894513779502294, 11863471976993485758, 9408615240131003867, 2448439901554368107, 7669176413900589628, 13955883899642443946, 3559761514651432863, 5999853120304570098, 2807928142993089395, 6880972979489023884, 8540438276045396759, 13336393887543928327, 14948024915319356336, 754486632845103448, 16252590658474672770, 11838852632524903679, 16841746824793599992, 4866584459095974245, 13046184814853980498, 8710985684981006226, 2355658489901240093, 17682251256218590491, 12738885399031396318, 3641463259326479601, 11573802402437143897, 4785854649163125380, 17654700608592820265, 7689738254866306083, 3911334929659733907, 3805687817679677472, 3372180752527728873, 12516023017017683246, 6541569134387572029, 14932792460356112158, 274079842264421275, 14741476297422044947, 7640237864595124592, 7990415001403780690, 14485175485850127358, 15701126719940798119, 7497786401585040464, 2046586308065249596, 4234230752844127257, 3490034085431124756, 7410205974894450493, 13594277608316567296, 13163068385450899386, 6911330603633557461, 4165273348787835236, 13196815825235476993, 15409229411685315073, 4238586327560550200, 4274172509763128574, 8233070080684386642, 1152981557203525396, 2258263369774438742, 16860590243592954334, 10642146327347114407, 16394076595581895042, 3547145813374894294, 7303429257652622247, 4599869911214805642, 1470127264048118954, 6553553520469198052, 624221776008514758, 16024993613079197687, 12072685851575104500, 4289561477780298769, 14522030035108027997, 10025959010474970695, 4338629041423254482, 12668451231751642706, 7041673834301289685, 1101300709714299914, 15830324192849592102, 6361267392222383309, 12743724653827284764, 13913765213720067888, 12472686594479717483, 17041667280903689118, 12612588174971368395, 4625038945277105759, 4288983616264520473, 13257170061268337928, 15378358854815534796, 1307879339751355693, 9045256242044980161, 13066137780318064542, 17483698129188252816, 5537781126683250458, 15814088167067959984, 17124111106622331645, 2228813159198082553, 12771677329276373795, 7473600359686104579, 10172401847101693206, 8817322474066906889, 10002046533039894942, 18350636570159627372, 2608194133937884904, 16496103406635747044, 3203166370447920771, 1416097169966651887, 860034031549905008, 15435212006888252138, 4982756044520683355, 14527835149012332766, 15648655845991912781, 15220061209366144565, 10713592116389348982, 11856331444132914701, 13011883287657858557, 18375660967945668491, 7611177834315648116, 11475292136381607303, 12142625427672665818, 1644376245508948388, 14986147846200059747, 10358191212479538383, 2124663276626493099, 15025396046176607689, 7566356641233415240, 3834259550197202335, 7422439917941038432, 14335746041650957139, 11010643115481291768, 16639917992723217687, 3400935192914355446, 6526469202356090658, 2911450085827434145, 2592450403666061908, 6573976403851247795, 4285219873414520276, 15329532146725863869, 6799347789229688901, 6639341479260471078, 5137054100466749121, 5102420602612942914, 12454937665202983967, 12962650067948965377, 17483657740097839287, 12223498331603994543, 14079145217780475833, 3310333423646124225, 8148231670879135605, 9541038636961784750, 11089617618703446533, 3560209342825276058, 2574634823119268479, 2588311243176990131, 15013509191556503430, 15455072885984268053, 13986137485131324765, 5720067926322634989, 320358790111393789, 15410939285136639329, 15697272961739331244, 1355846111750777085, 2546959351276906905, 14534695021313396715, 12100942362109396400, 1909839808518887758, 15057164163203198957, 10816292376571145141, 17932667027515587541, 8894763284691124395, 17376767493810914651, 1054656077023869452, 8186894411081110112, 4918609723063820894, 10472223930221187526, 8210872174259857628, 8260857529094096436, 11707883934354468821, 7798711246011152830, 12313898141945763999, 4092899057830195664, 12768752632246510730, 7011904089799177666, 18269846218072729005, 4472126139715717850, 7263280326862818361, 4617033187864299345, 16062484525314928005, 7764862313171817272, 5507098054488704246, 15417948890339509732, 3199184308759380889, 12873647785813929264, 15851634423390314715, 3379562369756927370, 2914796073219663247, 9453518290639493724, 10389507097848983202, 6987583823829734148, 5644521590882572085, 16385036288302112854, 14202037992186130818, 1662729350231436066, 16086866498209553899, 11668110277201388817, 2581723866463834707, 14466562150912612524, 18444381539786477861, 11792751584642451686, 644172128540161319, 15714856399314491326, 6336413224068482580, 15648040294508822482, 3581892413107868745, 2087860646799841458, 12928312782299116049, 4630539989871908829, 6915603518697601787, 14918733616941773093, 15087665207194981362, 613969264471068110, 3544544803540968193, 5220360717428049381, 3375260723217895506, 16778447987047186697, 11894812810172861433, 14542979312432827779, 13561316753657099179, 1968473618327458185, 5456934299993876358, 7469735400543018284, 7068657239043349097, 9254040800524479410, 5214107275553666760, 5001330682797736624, 17026132790954295091, 10969354337912897232, 869351389198733586, 9574587810937905907, 6923373747285449001, 12719903474522918771, 12250857818862900982, 2153256573644871951, 13709729097688338391, 2899377834668376960, 6841869401787596550, 10339715141881541659, 718655127116157511, 13741406681906111321, 15392288868670671619, 17545786767738322758, 11089794771839702758, 219094231550242583, 9674358307241496741, 4002620491443309348, 8012290324302967070, 8714326673970415123, 12380264119087982419, 11108551912665576265, 3708955946231240253, 11607264285750874901, 4216424611300123940, 8256067698160491644, 7506994298913059376, 11501100133000306066, 7549037119651533111, 5112970978157051505, 13518442004335850902, 7350008695599366666, 9542638447580599221, 2158188779042279647, 1604170908932337076, 6391929341437538244, 10779746559124306734, 12656450449103176181, 10121044395803332310, 11651522650180060700, 16328514328541821784, 10523761782294701174, 1822303728984452144, 7260452386953933551, 12204494523152059466, 17100382786462731446, 12548225060484474439, 11326872465335361323, 5596285187831113760, 5909751003547848587, 992306619579834385, 2228664329259510492, 15196270917670055982, 2131889695890586742, 9819776790840463517, 1473593931814601068, 14939513955417919643, 7685117665289355354, 6724244559482510387, 101460542568704969, 7352190705745517803, 2150669404455836808, 455126870518119052, 11553577781469330615, 10384536636375637150, 14364597940339752635, 2495319672618636831, 8180783418013670444, 3773765470722916252, 10227754258298095569, 4811293038656815364, 2304664986814074602, 2418992918773594204, 6388448639180737685, 6893696275605311774, 13851958766811817366, 4793074330182947851, 4813793152033309122, 1098414269347239038, 11751908186279088029, 15167430159498163699, 10528686090760108130, 17120804521852235295, 5538072916971524268, 18284870874128074659, 224523015148941267, 14496093443691170173, 5490655299006793623, 11584315652765207551, 3229579698633170375, 5527375504543907996, 6239324650299686862, 2232148196848710005, 9031256656667465794, 40023723987633148, 14627741678268078967, 11950626749898431344, 14785414395108523186, 870832948163923646, 13004928204786500706, 11732704426571300600, 907514934656616373, 11587740830029349245, 7583505136677874861, 2623787766244261370, 10256163025245964672, 7257287909572091733, 4812915812660879618, 3468364439026649335, 6604147596013682093, 16816894664989923710, 3964120271755066308, 6086548275463043980, 10447117175471304144, 12856607441078849807, 10592398111690221432, 14269275707379118835, 4396127772639422927, 10489721798852691549, 6681412646421684356, 12490106130106455109, 3624408102113036819, 17246634770535451304, 73750230380742720, 3858795004528971618, 18037249274864620640, 9013680198221453825, 11909298583725721915, 7512555591920604211, 17449244834240874515, 7793591661081767445, 16652407448095073621, 11804971167281860328, 16410605854679152138, 1713343542446776550, 16483548344281970818, 4628627981197409087, 9083762764219706193, 17065951854876058290, 11490185594933330698, 9891012968004512035, 368256788081374064, 470621950908252, 17956316299265730194, 8221822257224301188, 6380872247545425488, 9031471961851140451, 17956391258409007260, 13017604911584754606, 9245778199486992293, 8056793204522970093, 2531655295742236851, 16039488662052065607, 4695551407385442957, 16581782264738209135, 9457268466305801158, 2502271077174158302, 836797013558343943, 1224523470498102285, 374165187087964522, 10212314508075547184, 7669093970332858967, 9176723313583927295, 8839526249801396044, 9460240515540152245, 526138750665184089, 6908994573320912372, 12176043050383940227, 8431292525679019707, 7800865258551716648, 2930208417676545581, 12001139080437682925, 2848294057310329443, 3495763019164815081, 13998099468531902475, 2334207795701343601, 1265352082029868252, 5352951968929077427, 11045950825318827473, 17705541510574119706, 10388016860076689091, 6188336841660552180, 3874842388902329486, 3586889024655840994, 7577730940669490050, 3828324032996703471, 7382564057518691083, 18020764642442034007, 3255848346667024023, 913981917700616307, 6544220161742236189, 628453794376152858, 5273139986123145851, 12804359385937816703, 15490118777013724970, 5004956137979193113, 11537600208633214816, 6041778305931749161, 18021165191120757752, 4439552721639804321, 9445924893904633163, 6333608419766441318, 6265966168082228187, 5090746176805509189, 12079779788101746835, 3405057163683809716, 18176431495575685240, 5416316679824315388, 5666993498240944478, 9396996717121195736, 15077940112899068312, 15769845674133811095, 4172092555141541227, 10535661541737621064, 10760049649331328984, 9044328015087752668, 4208484814661836163, 4524519455413453106, 8416163180819044235, 76133776812564214, 8938397440798861336, 7699462000599225384, 9542247023407697767, 1397476485288102889, 12838783590422826565, 11111769246893411506, 17719085637529819037, 18350048131892648764, 647133208572620551, 3545832683987398107, 17392149180006432089, 4645454948531556636, 4638633830898005179, 15832113029610700219, 12312766094616504216, 11054531676785061901, 12882000175930708962, 17065292675540451547, 7348135285662513163, 10368855461513742486, 17213692472848349009, 5448237816391429929, 17475251701204191843, 12352004908893419844, 4421019229248084817, 5233890583141520327, 15415498665325430242, 8699482400205838797, 11081065321342975843, 13692414560354688711, 2057100631763259620, 1768191442150902149, 12463118341434320148, 14697940362261450576, 7225350934202123472, 9180626944525820669, 14817691250517499688, 9524098384486815580, 4894140555324164954, 2309262794362375113, 8645740617004046828, 16829903653299752341, 4278553392732422821, 16174995535301769275, 7274361875865992211, 5483861345936568593, 16555617280692737205, 2106788877369503099, 6355572984153420404, 15413046204382700864, 15184587830187202860, 17638950466015943646, 10142359495639047596, 2852278080143788489, 14902051473257283997, 12684082230048932446, 5127878269602498356, 1458833335160283623, 18343902965575788886, 15956410439937236477, 10143815431586875695, 8519328419973108156, 9379288137799805556, 11116700304696206296, 3269635235146511468, 7446145908658980471, 8423421258962502269, 2960959498368537205, 8029834119982365442, 12951331847284209016, 13335373530776006943, 2051038411438343086, 14988843915712852160, 11070472159205332532, 2405233098821133668, 12872299485466251244, 4146849588411590424, 8652997027024585292, 9417874732592565535, 2771366489480367357, 16381568131097774387, 1160190173665475303, 12142110843989704382, 17157977103678150822, 12240974252728213375, 8005232037362794911, 62748564819661432, 15562900352067429326, 13819933941831285726, 8700733640462543781, 17417693392111317966, 11195518897113567806, 8656545261572504126, 2665140739762930045, 2523114891549547532, 15947075740878853027, 16617762624958355772, 9189411410511795645, 9417682881040880723, 1220008371097876826, 4473435335583972063, 12416336276688398745, 9439155074539900208, 17599514971068491442, 1382978212068751289, 12012964446858847311, 13059411911626363940, 9000605160655962560, 18444429515577739106, 1678358883660355393, 5074103451266196440, 1108189786283239561, 10612698979413855931, 4989895863474068758, 653620819971957060, 12060263383072344947, 15076531277958824549, 10597595939754188762, 15724450558403473627, 16382650125476798913, 8738893762787150302, 9733212779214420390, 5558001311635500417, 2720376062751869999, 2936217033743496825, 3059230718610361194, 5589670835881847684, 12297086381101763222, 12830838307506907529, 7727866232017902927, 16978583538503170044, 5646531489086592542, 5696883024644775459, 1778382958859079024, 9219341275099378906, 17593963150311257769, 198176573650528594, 10425519151629874209, 13457055667833759545, 17213583299444020650, 14862117423842849302, 16906392281688863338, 4290302946266596427, 13505570400341984024, 2056510386911305907, 11571082458161054292, 7566281435617775832, 10210241606684674096, 10697498687651578080, 4947318501826974509, 5861434792576988890, 9869040491958929661, 5532013052186573089, 12416594018569715230, 10820734898252214278, 8537468997207455166, 439343392893541672, 14734630723072977466, 9898041261033982210, 17393034157801306127, 13758525217758656857, 2713096067589327874, 12442874178280670969, 14498768890161377807, 161967360889456606, 11930601082339405958, 11362787206913160786, 12545070484550723467, 14815095129086834610, 8605787829002095856, 12923597973881209899, 10587151577465292584, 14183134664818382968, 5172374334040473114, 9364926097792520560, 6171919845492918332, 4386231931762251578, 2155663571428617218, 7765511219465701910, 12061535530010910259, 16100330205655290696, 9974384126080194942, 9674175848724908032, 1687977953933677553, 2052842863240418404, 18296704913226861337, 4023434438910601547, 9899743965354682742, 5310198234766113901, 5162456985274720081, 8646509974119784542, 6113717383160009894, 6014191554047499022, 8484348411248636487, 2876047496375093909, 6660788054730924011, 1664197372146636482, 2820993293910648101, 11665512417100144808, 6502457677692154814, 2170150732610996776, 15522116097990839236, 15440086643427998964, 3675113412536301313, 8316358419658521853, 189389437052919038, 6981753429704993440, 12802645856607643857, 7243825699014665843, 12796799374814419834, 8068467907492367066, 16310382387876189712, 1486061732225930791, 382533986053029739, 16359148449656380800, 17246074348224240328, 11700746273206874174, ], &[ 12622393184452988185, 6576838566809301648, 5775205735049728716, 8287278668518156534, 12192798229753293112, 13075940713888694545, 12454048030060066070, 811912065849436865, 14514498508890956207, 3718975340013031462, 5748599663081118833, 7103827618714489700, 1300608812711622052, 6273491418082608362, 10602503410062294488, 3181236738912952810, 11220558709822910991, 1757050625501318151, 13622421981172568598, 12832273400791276781, 5855047466166966026, 8265514107974512007, 4674109636920327418, 15064411300962651052, 10245194862302150019, 14697255588820327266, 15300902461722524376, 4133685444341227543, 10059303764976223858, 12025228906916712453, 3342699448606724702, 4043427178402639607, 8354440664524965265, 14685529799335576021, 1998565942493742826, 424458568212209524, 17175147416410219809, 8429313419702361615, 13100329766043560847, 16630087004934016029, 1975643079807205422, 14257249811747812832, 16201214544277583293, 10834834555324096005, 12974966771898232184, 10175033989408956356, 13198699716510876245, 12667628170354632487, 13500517333069730437, 16670408922706885903, 16358625308423139600, 3004604642549199974, 15303830789363557104, 8922231358023374966, 5889284410855917356, 14457653243881523958, 1394588608017240060, 15159743360841977286, 16367826019458727864, 13291054711118709892, 5739609590986339029, 16727185121517285485, 5857477526908140920, 7564539623883188584, 15028512432506130151, 9451165299139733038, 7720569164934553601, 12250119607377112932, 13838627703516838495, 4013168924318862931, 15619946084866502269, 4850331740702252734, 4489013954543776517, 10588792414395604443, 3902488335149478186, 5227683403359005885, 7076009259772820031, 8343084757976224303, 5177402640814818565, 2803445024434417300, 4085994593957453089, 17829839529352422672, 3578735210913423849, 2792806554222369562, 15534236200548977629, 3124727634409390443, 1084234245147417462, 1598571627717804884, 752329673301761003, 12688955135473243162, 3217100306345888294, 14566509229614296336, 11270786911681876633, 6662721337309084196, 12158803014774283480, 8518459513237421390, 5910661800660978266, 744628824726848011, 5469395445007916291, 17702754906843708743, 7968296670638284359, 7510310566936008628, 1793306228498108099, 6353661129197447108, 3126760188195263395, 18414397606186055674, 17486033377523869654, 12070987014285382902, 9991875370105670503, 16129470720148507308, 1039596679504335478, 12158960746785703045, 14081886766117011421, 8985649855006063812, 16817043795641114882, 3052278422002310841, 11364643265564647695, 5842131153676887611, 17671187237412914007, 8666277097534907268, 1983817527033510933, 3541460822071490249, 6007905868789893806, 652610536509913563, 11037032573713184751, 11009156643744878354, 17591018917017615621, 11710867183921879437, 12251167927128949787, 8974964125845019147, 16969705468711169632, 677161721939989175, 1648428070692386013, 17084411431327447982, 16079687398141624486, 2070436743667033809, 2763689681570019260, 5133447300857161972, 15255425835157483742, 5966697992253286903, 361687726752744332, 422697286210467434, 7041898431113518823, 13795043150550399420, 583755960417947241, 2875531821527607804, 4394534528084370577, 12535851821369757920, 7213044591651422167, 1000544905146371455, 4653559762494073142, 7779502532203369012, 16702927718605692181, 12982197318021037408, 11786209078045506353, 15564445991051693791, 168023569501370168, 14266568007896652015, 5832135998445910960, 5245116375679737807, 13311176288056325459, 3321928379396402727, 2233377424088736972, 16828319963915513015, 9909739734979137218, 9397081158643758651, 16237610644843443174, 12049861989729092874, 963173337050875289, 1393288980328672002, 8369734762526854678, 10087190917060030061, 16611332898402499111, 17383970934682687319, 1806005829620081904, 2572338165105796552, 12096685872124824149, 10625877836202904943, 3565777311969108583, 2012783419915002762, 9017825065020723376, 16320469478354954310, 11806049513756650829, 7727243155747891778, 15158785566684134320, 2456938594466970469, 7873271366166028790, 7686875950801483839, 5617367656140550179, 13464612212949386527, 14757590544232715739, 11128260848489879698, 17626653494839808091, 4716501168031180893, 564851231412074685, 8132887702611477369, 17552681344611428819, 3132957846371517857, 11213590168035816092, 5431508051609838979, 4515078710323627036, 13543555744861125477, 309309746143903518, 16853539194117891693, 12430835367581296760, 9255793325320254163, 6591016556383892120, 17100720673447110167, 6061633534359930907, 2424801126737847877, 143356278625650878, 13554246058973057, 2522638740117423042, 17137049738161235473, 13176139598975768388, 1166120501092890058, 13609465226914230670, 1875448353263386203, 11743691709994844759, 11061975822835649567, 3910967390258776729, 13577511757143681922, 13827967505806592907, 2051032579834721288, 13464396192578309450, 12800325352123601126, 5662172040792660351, 4668403599689432265, 13491732430526501935, 14157448317801936638, 9727633765236455195, 9719667367393442680, 65474725188749034, 541181075058713986, 1362959920153019155, 909082441655242031, 10411762570666372898, 11947296633429547042, 2358875224077331054, 18328103363666444110, 9866396237081281387, 8956667376401863125, 3553975952663161681, 14635072569697080107, 15544243098851103691, 1716867379502200816, 8776276410599591217, 15666047021340369577, 18147839669015605124, 5572968214423121059, 3098271794032834805, 9673511458079712674, 16010905689567823114, 16267201338365627673, 3382936832397700934, 14957330839370249294, 2642620075223240608, 1037193656622159510, 9012211029341477206, 11431820793941846484, 8851179188286979417, 1398798117665992200, 10789412881967821793, 9415310270308545401, 3878698623022480586, 5863277386811827416, 7839335917417032151, 2682939031547768972, 13397811690933306272, 6260148512861761963, 250324816893616712, 9085404939459661953, 9291403781568194640, 4943156069611799558, 4012150457352746082, 6743913241329187121, 12017429880940425975, 12929043722801309882, 10207563294594880008, 11011363281303738187, 15710481255331302269, 16065095211995167995, 7729419910130307261, 14687299092290139624, 14212774840097619295, 2696933303282739820, 18380487173546723450, 16340353901250449060, 16974439742831865800, 950395719691498193, 14294722598295985858, 9819629466618736444, 5134213478899186274, 15000357065088523575, 10866834082882265182, 5562209566130970606, 11574047289359876875, 14220066737185616618, 7779431549476206578, 6164322776781074672, 12698699879532635460, 9775735470622210670, 3418783774094779723, 11711261272918394032, 130965081793297038, 17951168177437733692, 10982891057320326220, 15446335221541982820, 3245348832258032003, 16936841548783354130, 17845797372140897632, 15738639878561184724, 8036219019342274839, 1452217306593250967, 6524640126112677080, 9487637664603922399, 9816896718276865827, 6660361176840108508, 7155686979915548241, 5363459444036855846, 14211791847250927632, 3758021753984352623, 14892848306282510880, 5622159652308652067, 3013224027720379126, 6593658810977588348, 8737392006680055212, 13098306207053606600, 10321069935686406569, 7922126603433897812, 16345323120534317859, 2051345375893155420, 2642889174797452752, 15490895676079176387, 3421728094884350553, 1403789733153795522, 18095248776246397645, 1141680856759996549, 18100437303596844925, 10084704427684498223, 6594067795036706889, 6973150786346631215, 18179961484385983667, 13461945752721759987, 11607193624374158079, 15870559753884484047, 5909010369355025391, 6576523373028484144, 16932784188428621626, 4532369146195665092, 8439234310823545929, 1340079530194594172, 14887691618471650731, 12957273899514368091, 12528827801491392116, 13543620352724873404, 15027641031340635112, 3497080345802388600, 12532486649114668085, 6567958427571461048, 15524967599943619324, 9687676309746098775, 17837290175131112775, 6562577965471546738, 15069045445640377298, 15845870183628003510, 4882896822391168376, 299291354580119732, 1253349370757830450, 4019946893924061554, 4835687088435778153, 560543554021366834, 9073367421711646017, 7210725233620419378, 1298874732344651234, 1572176424217571034, 13459119860690231055, 14894361022235972365, 12479129811186551951, 14014563421012570478, 5045150035901968604, 8669967307441751567, 1905648106987249698, 15427548300560765880, 16929690218389356941, 2257784955568148289, 16671033335294376858, 17747845134586030566, 1166533040996500790, 15593722083313803843, 9396109408892612308, 11499981530721896824, 16970499445754392592, 8812544874418820841, 8398666252211387757, 2704923715823740363, 5314497299504523542, 5160833323750080202, 4489614019342255168, 16950479847425158028, 6792145380267486390, 14740232145636169668, 621507344077794685, 3751460578157408141, 8129084486654095901, 10001447130583054783, 12074020860950174718, 4077799248444467034, 6822188364356126108, 600699026381065222, 4751815635139776884, 15367619962178612777, 5104893889903277375, 4661242055023047595, 2154923710109688891, 17429472085810639176, 15724063920670689806, 15216015843686884607, 12102731527843294992, 5923322163550614145, 578844978773347240, 10464767667513753088, 4422886088759698238, 16103295972923438952, 11952617258811913803, 6497649448616698694, 7393337205916981343, 18096118845330092692, 9417521917459925024, 10361801380161480586, 12227883220061157093, 12402861272457739535, 16959542957232270118, 3100109669354124792, 8252021294756255295, 6601544514524806222, 2299228880186395084, 17206687535661702962, 11126365220307664227, 14027475381759030281, 13930713973102273385, 15470781455897247423, 11132792425729103210, 12743536155285333682, 18404252734721007574, 4471349713039799575, 1097648964215121725, 3481722566194833071, 17004865376724342545, 4412003432895082804, 7207210335443122075, 11185557399280223037, 17791545657588716507, 15001384756479157715, 7068904123591490511, 15342280096772936670, 2962241209356984664, 11085614675955826760, 17304628576563637894, 13276820937207248747, 8496585032541849567, 16867719644448479323, 3556128556368553119, 4135507236401264417, 8300362706308478874, 12391805295598536754, 212746375693666561, 17668657797254926684, 11472227395456264735, 3346261809041337938, 10494844376481252742, 1039434633412734920, 3537248641106173003, 15722028107965146028, 3957344489070663630, 171520814732107885, 15701539439111209401, 16266903088897196785, 8162180034652464302, 751396451910146673, 6284978536639446110, 9475038153254288249, 3366181839966720435, 38511352552288459, 5091650762875915484, 15684434521130749089, 3313175693887858849, 3512862245616351559, 5836672242124333533, 7050189281309530509, 6693570573437863470, 1180929186779755232, 13670569646431885520, 12219171873489819591, 4177796076111463096, 12523988008299904003, 2573301004696669683, 14000913768617402515, 1901514323758988374, 15680204389035820646, 4057543360329026133, 10484558774556926484, 16880563214620981386, 9806529946108790649, 64858070620446021, 13058265791054866751, 14208780393297513060, 132444534110050230, 18171930401783150790, 3788701567251119654, 8068556048675251486, 7698349927972499523, 4200940425301802259, 5859679210997281495, 1196917998587841402, 293846739593611503, 742395111532740587, 7299921458271130779, 4013584019577681930, 13051907051578937053, 15460522300561557538, 11739346111540426460, 6000392060961693921, 2093513337710768996, 2971782196230136142, 14650675906567946197, 13044422653436935289, 5393154276677237552, 9414604975305044529, 14383902696216976975, 3526706571033049996, 10453515348838320881, 1300027919459661427, 18220108229306772305, 6736376168692276304, 14279821335279300725, 1137238529965897445, 10675553998207815811, 10380811037741532194, 8166481736795163463, 1781828658320585086, 12391009694347491828, 917764047682931238, 5513578507525454078, 17200064132172477743, 17870911035870211136, 14336835701074601920, 11250050928475332766, 11433063323885652386, 7083842474651714165, 2491363132897582954, 6822759191074732531, 1975703285786766592, 4664247346348091399, 6200670517431733578, 7625423344374743344, 12752241152270105853, 1792181265050143868, 9684341866777183803, 2519544645709853691, 10916780105681637442, 10344955420168669639, 9942180203006299987, 12084291513489188332, 3948266540776100311, 9154092837114088215, 5346858599403446633, 16526650534031004365, 1000379885777408481, 9962324609830950859, 17358968356608808633, 16077501442923026330, 16373391819852480638, 7285769258546345039, 9258849101785002591, 5742154400061770227, 6000603993323989058, 14647716329474708008, 9759234782041772304, 10140774772642173806, 12417308406161902675, 787743125041003665, 16505409716496421861, 13496346584666506754, 6161155548184037990, 6052945594671650378, 3943721555742518361, 1724411800658421894, 5539278770081464366, 15345354647968324153, 11115348357173195281, 14941897866359059705, 13232123053046857932, 10293530598380524712, 6785485284866633954, 2274573151581626897, 7914418682634630883, 9050484888129037258, 5596144246310386066, 16947403501604289983, 4629498933991963153, 12809658963208366731, 15794201530500048648, 13688081233074642819, 13734318539544366298, 17338613223770563244, 8949201706050038962, 7457293230715991355, 3392962986871707645, 2665311774547334828, 14769130061609548831, 14798608201523559143, 4248204495368930031, 2118780687916441347, 7587741700881576871, 14435287502544940055, 5661100765027979237, 16339955561566207846, 8140260981243250155, 8056431096984667176, 7147782631749791333, 2489306669890900889, 4475802923302768991, 16154685423804744738, 7934898789690822040, 6879516481280076285, 9089400825108258886, 17930990199515864021, 14768387486978797965, 18129863777024625000, 10818394317143489199, 15491447326600259816, 16981166881989734434, 16302476576745273904, 6518490351683715742, 8412288793616962739, 6351653340417195445, 13150568765377194334, 13805040795477806115, 5934147261272121494, 1994383077577350943, 16635675973993021427, 12605935823956703560, 17476993101523741670, 6478809187431271696, 2732525537481875395, 9879991725842211511, 6807932982002010721, 7352337837011779903, 2817471936912129199, 13262278618157850043, 10769791684153169602, 16373519399949306992, 2899723188139359765, 10536102085057036916, 6542494148698745845, 8208357062363683807, 7135654628053388596, 9239547683832094589, 5857943902095897523, 2988676895399293972, 10864744325417622458, 5315919323785706256, 17726255358609389283, 548416274855739353, 14341121194849694922, 7541833390688838500, 12990342594130240843, 18010249397570629115, 12270534655132211820, 11089591099925577121, 8904086294203345138, 360354335597452271, 15390384602644239058, 9646385913080766351, 7807991425432087787, 9178671661816533936, 14127492076118037414, 2392162322212242991, 14036941142798507711, 6502240351436565564, 7893899872624843337, 14288594129943657110, 14040928483141897687, 1592502089611546139, 16817286687244219231, 1288452307437286948, 14067519453346137912, 10075887672168075195, 16769912598561257346, 15456884559283078393, 8711311950138380878, 17440519414852901585, 4031578079792007763, 17459032506776526507, 6047439267180308295, 13036838382774047407, 5995888809898483332, 5666540365944124863, 9669239227306108902, 13524757761279567441, 9100467949589737947, 10630607884662362720, 7656432890734400844, 14587775638685276238, 13512825387557617884, 7244019832094584382, 14996712660826603119, 15920594541485478011, 18302888448007121275, 2860853013354641768, 16346890198034118818, 3995008638584894259, 15431133287252532218, 12007621448583591973, 12654616832949992670, 17218932927375784084, 5108339176271521031, 1475805094516082093, 12897404584908775312, 12902004423289195678, 632420305961082974, 3939829721363017782, 8159027656096857323, 5289724432039220494, 8105874082275331898, 7058967362148243623, 7084554565361601863, 10713529750643129586, 16053444010682289763, 16789097964014031314, 2561050582281530128, 5001739943623024256, 5563376828383980501, 7029523460044084584, 3734303822831180195, 17604507458906309331, 15410396100097854167, 12072617536058855445, 9343913967197010858, 17464576053666161449, 14222234943442423138, 3029903299346511292, 2439504202412922232, 17909602716813870812, 7163148054936239235, 1203376532559407808, 13308342071396905822, 9659238717159340331, 9298790467854663751, 13879727520175998029, 3540668590936352635, 9319928603109010852, 7135941863720734900, 4755935102616669000, 16186952942091333092, 868417045309212144, 4614771873250033976, 12695043568719791838, 11555375308916964213, 7608623603624110550, 2657517781272739364, 16275540663546067547, 13686833504204824152, 12138906647042213779, 10867610696309111099, 14724502273153125344, 16861685577613202946, 8743302596210517799, 14587474243501868159, 2572487334058012273, 603248717087965084, 5059320325228404990, 16238530369175832077, 4519037757700474392, 12378671739975925965, 12407484273586632994, 15313162588758450641, 7715370120812724109, 16244624049595468844, 16509798106801620258, 8670816985658531869, 17161563202276681629, 6760859082822229695, 6807294103798050445, 12102809409961330094, 15733867019982720404, 4500829814752383546, 276727174991039753, 7166981968731078898, 6839153022681710561, 9052935609363333850, 180023864532346968, 15036321241551927313, 8004861917338601611, 10433381600254688194, 58897018650060884, 12176800300096084156, 1677464574753824642, 9033479160050603494, 15102533506708978663, 14084179961157892415, 15862200228768947299, 13406816340465864482, 4480435244557703388, 9328135622344307924, 8569086569674090389, 117119659942779713, 53818961148559993, 17499848839935720391, 9136357190515762310, 9027105858395986940, 17989890318601901443, 18097540417946691193, 14525610539500917353, 2154941454922905428, 5904339583092243168, 13443891604996267, 17266860992297653711, 8744756382159865790, 18024305737878696983, 2546630949169889692, 14096991573794098342, 6037463192406505117, 16222309559186427347, 17465566247484999322, 12659653001889101916, 17145147704704336749, 270028953681259627, 10687721792402042274, 7909714047373529261, 1516466812193933964, 18277293846935305743, 16998707418464340047, 10456180009273456482, 10894339053818039134, 7931553102963941505, 5469019641482786787, 15559448848625861221, 13379845259726008039, 15222258432394099771, 9220502339943331578, 11041492625928826773, 13723142119880743788, 13406366780219048563, 16242021890137344914, 3242681820103600264, 7433022400269598514, 13800053899816348927, 10971582708599334044, 16780079125754812721, 7499355964098143157, 6683080229097120149, 4643838630497962703, 2452976410357582431, 13628797043976089046, 12208582264105438774, 10972823060808439197, 5834946779865455467, 7061987228048265540, 1207502404391064867, 4999557813060557947, 6110696626660879360, 16155026384042239167, 14271653985173561903, 15409968780617538981, 12583134000526518362, 14425350186270986364, 4240634153006170791, 15186331103475807077, 3441220359690995595, 7730377008237943835, 4028688972105728738, 2120709666343944557, 15275844229510750384, 18298631304947594122, 13289696428719138891, 12902251465979698800, 17784642778353395327, 8932078122697958597, 2343784433129198521, 2625325561581989570, 6226848264428179755, 9341106183231718139, 9098935814035218596, 7352506358300392706, 2344104557164367420, 12260380423821950355, 5334772679936050516, 4625031027053042238, 16182107767362335138, 16366374610370031102, 4836384899789893883, 7955273434480297668, 6911864392544134089, 16417538807637628387, 7095497393911852501, 13038578327075160812, 3237033976078933963, 12153345193878928470, 8529208509214849086, 3557796804144548743, 4802066316596054332, 15433632645238893171, 7546572980385595878, 11926731397057053166, 12459060237931625488, 14141685648156683211, 7288151748928762022, 4432041251568429780, 15563480646640553472, 16053290806405898796, 15137506699232809093, 8005443786172873610, 2583037632942587270, 17849394642972838924, 14162302110936479805, 2509458716192360405, 5356417310559321341, 13186254752172487693, 11386136498514963040, 17709391199907333437, 10287520916427793726, 16609632513291109233, 2167580474521363269, 12093450528168333086, 7863381164011802024, 3333719694645745323, 11940256871115614834, 15608703623597862105, 12353758136546081384, 6684006108125243153, 12729735272407622593, 5729918571797570178, 836259910264806143, 14839853436536328663, 3503216322132876395, 12081845346843956683, 11452606043277089033, 3278971557269095943, 14460255683089324678, 26212371609850095, 5791996297577934908, 11791872952518605557, 4303537542168010174, 16090584062354399534, 4908264648595320164, 7751540775663330461, 6257171389619325857, 10426410760581414335, 17538696865214967217, 7467505509612490667, 9596349531846363101, 10432645685361251072, 4554200269336177591, 14164090620513306305, 12703411361203184202, 10381679821480302262, 17407993808772229676, 13447212664492178323, 6368763612994722491, 6985317877139191413, 3304210073159911148, 11815333377693368073, 5807352926666783905, 15497939312564010706, 6997355376158126843, 8894976899204659904, 6062763749482474444, 12366982438149692528, 5811941270446802002, 1365585056061256612, 13475218612693439913, 3101226957898170052, 7483152820787337316, 11966132556998778392, 15847594708317668544, 8536570052230898519, 17755327099574675677, 4573875060013426627, 10571694422987443237, 13886938922370949941, 13243541345182765869, 2407150453734919381, 3504658143291885737, 7031357511394950972, 10000971933511773390, 13912116329153795479, 15031415497603451939, 4599320279014918550, 11777085389799050565, 10789465428143426974, 13380525436974205384, 481819144611018854, 5450316677878014202, 15246244400696673845, 2539248742679727539, 13402910818618694139, 17131842085718107785, 1254150638176089903, 4995981122218138624, 7087931693181888823, 15049301175005363928, 108059457248600792, 6415264753538529207, 8176266644263202488, 9913473944910878449, 1695436935634773000, 17297145186449223950, 12551494433741244515, 9893572477404506151, 5018441835213902689, 2942536196417517781, 16905131659211501459, 6905710711318770295, 7616899203962297179, 14893845862286767619, 9802013654239316989, 17646160800663090718, 688334719842856096, 2007794688466179654, 654395123253282904, 8101085388166846547, 129085352126721490, 5656513500529597182, 5068380157352571940, 16823659606299635586, 18201953606184755353, 14292322613095109457, 16683857805140576716, 2453074754987128823, ], ); } } #[test] #[should_panic] fn limbs_mod_fail_1() { limbs_mod(&[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_mod_fail_2() { limbs_mod(&[1], &[4, 5]); } #[test] #[should_panic] fn limbs_mod_fail_3() { limbs_mod(&[1, 2, 3], &[4, 0]); } #[test] #[should_panic] fn limbs_mod_to_out_fail_1() { limbs_mod_to_out(&mut [10; 4], &[1, 2, 3], &[4]); } #[test] #[should_panic] fn limbs_mod_to_out_fail_2() { limbs_mod_to_out(&mut [10; 4], &[1], &[4, 5]); } #[test] #[should_panic] fn limbs_mod_to_out_fail_3() { limbs_mod_to_out(&mut [10; 4], &[1, 2, 3], &[4, 0]); } #[test] fn test_mod() { let test = |s, t, remainder| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); x.mod_assign(v.clone()); assert!(x.is_valid()); assert!(x.mod_is_reduced(&v)); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let mut x = u.clone(); x %= v.clone(); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x %= &v; assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone() % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone() % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let num_u = BigUint::from_str(s).unwrap(); let num_v = BigUint::from_str(t).unwrap(); let r = num_u.mod_floor(&num_v); assert_eq!(r.to_string(), remainder); let r = num_u % num_v; assert_eq!(r.to_string(), remainder); let rug_u = rug::Integer::from_str(s).unwrap(); let rug_v = rug::Integer::from_str(t).unwrap(); let r = (rug_u.clone()).rem_floor(rug_v.clone()); assert_eq!(r.to_string(), remainder); let r = rug_u % rug_v; assert_eq!(r.to_string(), remainder); assert_eq!(u.div_mod(v).1.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "123"); test("456", "123", "87"); test("4294967295", "4294967295", "0"); test("4294967295", "4294967295", "0"); test("1000000000000", "1", "0"); test("1000000000000", "3", "1"); test("1000000000000", "123", "100"); test("1000000000000", "4294967295", "3567587560"); test("1000000000000000000000000", "1", "0"); test("1000000000000000000000000", "3", "1"); test("1000000000000000000000000", "123", "37"); test("1000000000000000000000000", "4294967295", "3167723695"); test("1000000000000000000000000", "1234567890987", "530068894399"); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "1234567890987654321234567890987654321", "779655053998040854338961591319296066", ); test( "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0", "316049380092839506236049380092839506176", "37816691783627670491375998320948925696", ); test( "253640751230376270397812803167", "2669936877441", "1520301762334", ); test( "3768477692975601", "11447376614057827956", "3768477692975601", ); test("3356605361737854", "3081095617839357", "275509743898497"); test( "1098730198198174614195", "953382298040157850476", "145347900158016763719", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test("123", "1000000000000000000000000", "123"); } #[test] #[should_panic] fn mod_assign_fail() { Natural::from(10u32).mod_assign(Natural::ZERO); } #[test] #[should_panic] fn mod_assign_ref_fail() { Natural::from(10u32).mod_assign(&Natural::ZERO); } #[test] #[should_panic] fn mod_fail() { Natural::from(10u32).mod_op(Natural::ZERO); } #[test] #[should_panic] fn mod_val_ref_fail() { Natural::from(10u32).mod_op(&Natural::ZERO); } #[test] #[should_panic] fn mod_ref_val_fail() { (&Natural::from(10u32)).mod_op(Natural::ZERO); } #[test] #[should_panic] fn mod_ref_ref_fail() { (&Natural::from(10u32)).mod_op(&Natural::ZERO); } #[test] #[should_panic] fn rem_assign_fail() { let mut n = Natural::from(10u32); n %= Natural::ZERO; } #[test] #[should_panic] fn div_rem_assign_ref_fail() { let mut n = Natural::from(10u32); n %= &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_fail() { Natural::from(10u32) % Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_val_ref_fail() { Natural::from(10u32) % &Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_val_fail() { &Natural::from(10u32) % Natural::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_ref_fail() { &Natural::from(10u32) % &Natural::ZERO; } #[test] fn test_neg_mod() { let test = |s, t, remainder| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); x.neg_mod_assign(v.clone()); assert!(x.is_valid()); assert!(x.mod_is_reduced(&v)); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.neg_mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().neg_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().neg_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).neg_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).neg_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = rug_neg_mod( rug::Integer::from_str(s).unwrap(), rug::Integer::from_str(t).unwrap(), ); assert_eq!(r.to_string(), remainder); assert_eq!(u.ceiling_div_neg_mod(v).1.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "333"); test("456", "123", "36"); test("4294967295", "1", "0"); test("4294967295", "4294967295", "0"); test("1000000000000", "1", "0"); test("1000000000000", "3", "2"); test("1000000000000", "123", "23"); test("1000000000000", "4294967295", "727379735"); test("1000000000000000000000000", "1", "0"); test("1000000000000000000000000", "3", "2"); test("1000000000000000000000000", "123", "86"); test("1000000000000000000000000", "4294967295", "1127243600"); test("1000000000000000000000000", "1234567890987", "704498996588"); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "1234567890987654321234567890987654321", "454912836989613466895606299668358255", ); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00", "316049380092839506236049380092839506176", "278232688309211835744673381771890580480", ); test( "253640751230376270397812803167", "2669936877441", "1149635115107", ); test( "3768477692975601", "11447376614057827956", "11443608136364852355", ); test("3356605361737854", "3081095617839357", "2805585873940860"); test( "1098730198198174614195", "953382298040157850476", "808034397882141086757", ); test( "69738658860594537152875081748", "69738658860594537152875081748", "0", ); test( "1000000000000000000000000", "1000000000000000000000000", "0", ); test("0", "1000000000000000000000000", "0"); test( "123", "1000000000000000000000000", "999999999999999999999877", ); } #[test] #[should_panic] fn neg_mod_assign_fail() { Natural::from(10u32).neg_mod_assign(Natural::ZERO); } #[test] #[should_panic] fn neg_mod_assign_ref_fail() { Natural::from(10u32).neg_mod_assign(&Natural::ZERO); } #[test] #[should_panic] fn neg_mod_fail() { Natural::from(10u32).neg_mod(Natural::ZERO); } #[test] #[should_panic] fn neg_mod_val_ref_fail() { Natural::from(10u32).neg_mod(&Natural::ZERO); } #[test] #[should_panic] fn neg_mod_ref_val_fail() { (&Natural::from(10u32)).neg_mod(Natural::ZERO); } #[test] #[should_panic] fn neg_mod_ref_ref_fail() { (&Natural::from(10u32)).neg_mod(&Natural::ZERO); } #[test] fn limbs_mod_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_22().test_properties_with_config(&config, |(ns, d)| { let r = limbs_mod_limb::(&ns, d); assert_eq!(Natural::from_limbs_asc(&ns) % Natural::from(d), r); assert_eq!( limbs_mod_limb_any_leading_zeros_1::(&ns, d), r ); assert_eq!( limbs_mod_limb_any_leading_zeros_2::(&ns, d), r ); assert_eq!(limbs_mod_limb_alt_1::(&ns, d), r); assert_eq!(limbs_mod_limb_alt_2::(&ns, d), r); assert_eq!(limbs_mod_limb_alt_3(&ns, d), r); }); } #[test] fn limbs_mod_limb_small_normalized_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_26().test_properties_with_config(&config, |(ns, d)| { let r = limbs_mod_limb_small_normalized::(&ns, d); assert_eq!(r, Natural::from_limbs_asc(&ns) % Natural::from(d)); if ns.len() == 1 { assert_eq!(r, ns[0] % d); } else { assert_eq!(r, limbs_mod_limb::(&ns, d)); } }); } #[test] fn limbs_mod_limb_small_unnormalized_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_27().test_properties_with_config(&config, |(ns, d)| { let r = limbs_mod_limb_small_unnormalized::(&ns, d); assert_eq!( r, limbs_mod_limb_at_least_1_leading_zero::(&ns, d) ); assert_eq!(r, Natural::from_limbs_asc(&ns) % Natural::from(d)); if ns.len() == 1 { assert_eq!(r, ns[0] % d); } else { assert_eq!(r, limbs_mod_limb::(&ns, d)); } }); } #[test] fn limbs_mod_limb_at_least_2_leading_zeros_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_28().test_properties_with_config(&config, |(ns, d)| { let r = limbs_mod_limb_at_least_2_leading_zeros::(&ns, d); assert_eq!(r, Natural::from_limbs_asc(&ns) % Natural::from(d)); if ns.len() == 1 { assert_eq!(r, ns[0] % d); } else { assert_eq!(r, limbs_mod_limb::(&ns, d)); } }); } #[test] fn limbs_mod_three_limb_by_two_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_sextuple_gen_var_2().test_properties_with_config( &config, |(n_2, n_1, n_0, d_1, d_0, inverse)| { let r = limbs_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, inverse); verify_limbs_mod_three_limb_by_two_limb(n_2, n_1, n_0, d_1, d_0, r); }, ); } #[test] fn limbs_mod_by_two_limb_normalized_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_18().test_properties_with_config(&config, |(ns, ds)| { let (r_0, r_1) = limbs_mod_by_two_limb_normalized(&ns, &ds); verify_limbs_mod_by_two_limb_normalized(&ns, &ds, r_0, r_1); }); } #[test] fn limbs_mod_schoolbook_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_17().test_properties_with_config( &config, |(mut ns, ds, inverse)| { let ns_old = ns.clone(); limbs_mod_schoolbook(&mut ns, &ds, inverse); verify_limbs_mod_1(&ns_old, &ds, &ns); }, ); } #[test] fn limbs_mod_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 128); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); large_type_gen_var_12().test_properties_with_config( &config, |(mut qs, mut ns, ds, inverse)| { let ns_old = ns.clone(); limbs_mod_divide_and_conquer(&mut qs, &mut ns, &ds, inverse); verify_limbs_mod_1(&ns_old, &ds, &ns); }, ); } #[test] fn limbs_mod_barrett_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_5().test_properties_with_config( &config, |(mut qs, mut rs, ns, ds)| { let rs_old = rs.clone(); let mut scratch = vec![0; limbs_div_mod_barrett_scratch_len(ns.len(), ds.len())]; limbs_mod_barrett(&mut qs, &mut rs, &ns, &ds, &mut scratch); verify_limbs_mod_2(&rs_old, &ns, &ds, &rs); }, ); } fn verify_limbs_mod_3(ns: &[Limb], ds: &[Limb], rs: &[Limb]) { let n = Natural::from_limbs_asc(ns); let d = Natural::from_limbs_asc(ds); let expected_r = n % &d; let r = Natural::from_limbs_asc(rs); assert_eq!(r, expected_r); assert!(r < d); assert_eq!(rs.len(), ds.len()); } #[test] fn limbs_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_11().test_properties_with_config(&config, |(ns, ds)| { verify_limbs_mod_3(&ns, &ds, &limbs_mod(&ns, &ds)); }); } #[test] fn limbs_mod_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 128 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_57().test_properties_with_config(&config, |(mut rs, ns, ds)| { let rs_old = rs.clone(); limbs_mod_to_out(&mut rs, &ns, &ds); verify_limbs_mod_2(&rs_old, &ns, &ds, &rs); }); } #[allow(clippy::needless_pass_by_value)] fn mod_properties_helper(x: Natural, y: Natural) { let mut mut_x = x.clone(); mut_x.mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; assert!(remainder.mod_is_reduced(&y)); let mut mut_x = x.clone(); mut_x.mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let mut remainder_alt = x.clone(); remainder_alt %= &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let mut remainder_alt = x.clone(); remainder_alt %= y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = &x % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = &x % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).div_mod(&y).1; assert_eq!(remainder_alt, remainder); let num_remainder = BigUint::from(&x).mod_floor(&BigUint::from(&y)); assert_eq!(Natural::from(&num_remainder), remainder); let num_remainder = BigUint::from(&x) % &BigUint::from(&y); assert_eq!(Natural::from(&num_remainder), remainder); let rug_remainder = rug::Integer::from(&x).rem_floor(rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_remainder), remainder); let rug_remainder = rug::Integer::from(&x) % rug::Integer::from(&y); assert_eq!(Natural::exact_from(&rug_remainder), remainder); assert!(remainder < y); assert_eq!(&remainder % y, remainder); } #[test] fn mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); natural_pair_gen_var_5().test_properties_with_config(&config, |(x, y)| { mod_properties_helper(x, y); }); natural_pair_gen_var_6().test_properties_with_config(&config, |(x, y)| { mod_properties_helper(x, y); }); natural_gen().test_properties(|n| { assert_eq!(n % Natural::ONE, 0); }); natural_gen_var_2().test_properties(|ref n| { assert_eq!(n % n, 0); assert_eq!(Natural::ZERO % n, 0); if *n > 1 { assert_eq!(Natural::ONE % n, 1); } }); natural_triple_gen_var_4().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x + y) % z, (x % z + y % z) % z); assert_eq!(x * y % z, (x % z) * (y % z) % z); }); unsigned_pair_gen_var_12::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) % Natural::from(y), x % y); }); } #[allow(clippy::needless_pass_by_value)] fn neg_mod_properties_helper(x: Natural, y: Natural) { let mut mut_x = x.clone(); mut_x.neg_mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; assert!(remainder.mod_is_reduced(&y)); let mut mut_x = x.clone(); mut_x.neg_mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).neg_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).neg_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().neg_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().neg_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).neg_mod(&y); assert_eq!(remainder_alt, remainder); let rug_remainder = rug_neg_mod(rug::Integer::from(&x), rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_remainder), remainder); assert!(remainder < y); } #[test] fn neg_mod_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); natural_pair_gen_var_5().test_properties_with_config(&config, |(x, y)| { neg_mod_properties_helper(x, y); }); natural_pair_gen_var_6().test_properties_with_config(&config, |(x, y)| { neg_mod_properties_helper(x, y); }); natural_gen().test_properties(|n| { assert_eq!(n.neg_mod(Natural::ONE), 0); }); natural_gen_var_2().test_properties(|n| { assert_eq!((&n).neg_mod(&n), 0); assert_eq!(Natural::ZERO.neg_mod(&n), 0); assert_eq!(Natural::ONE.neg_mod(&n), n - Natural::ONE); }); natural_triple_gen_var_4().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x + y).neg_mod(z), (x % z + y % z).neg_mod(z)); assert_eq!((x * y).neg_mod(z), ((x % z) * (y % z)).neg_mod(z)); }); unsigned_pair_gen_var_12::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).neg_mod(Natural::from(y)), x.neg_mod(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModIsReduced, ModMul, ModNeg, ModPow, ModPowAssign, Parity, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_triple_gen_var_15; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_pow::{ limbs_mod_pow, limbs_mod_pow_odd, limbs_mod_pow_odd_scratch_len, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_pair_gen_var_5, natural_pair_gen_var_8, natural_quadruple_gen_var_2, natural_quadruple_gen_var_3, natural_triple_gen_var_5, unsigned_vec_quadruple_gen_var_6, unsigned_vec_quadruple_gen_var_7, }; use malachite_nz::test_util::natural::arithmetic::mod_pow::simple_binary_mod_pow; use num::BigUint; use std::panic::catch_unwind; use std::str::FromStr; fn verify_limbs_mod_pow(out: &[Limb], xs: &[Limb], es: &[Limb], ms: &[Limb], out_out: &[Limb]) { let exp = Natural::from_limbs_asc(es); let m = Natural::from_limbs_asc(ms); let x = Natural::from_limbs_asc(xs) % &m; let expected = (&x).mod_pow(&exp, &m); assert!(expected.mod_is_reduced(&m)); assert_eq!(simple_binary_mod_pow(&x, &exp, &m), expected); let n = ms.len(); assert_eq!(Natural::from_limbs_asc(&out_out[..n]), expected); assert_eq!(&out_out[n..], &out[n..]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_pow_odd() { let test = |out: &[Limb], xs: &[Limb], es: &[Limb], ms: &[Limb], out_out: &[Limb]| { let out_old = out; let mut out = out_old.to_vec(); let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(ms.len())]; limbs_mod_pow_odd(&mut out, xs, es, ms, &mut scratch); assert_eq!(out, out_out); verify_limbs_mod_pow(out_old, xs, es, ms, &out); }; // - ms_len < REDC_1_TO_REDC_N_THRESHOLD // - ms_len == 1 in to_redc // - end >= len in get_bits // - width >= windowsize // - bit_index != 0 // - !limbs_get_bit(es, bit_index - 1) // - bit_index >= windowsize // - limbs_cmp_same_length(out, ms) == Less test(&[10; 3], &[3], &[20], &[105], &[51, 10, 10]); // - ms_len != 1 in to_redc // - end < len in get_bits // - bit_index < windowsize test( &[10; 3], &[123, 456], &[789, 987], &[135, 797], &[2939877551, 399, 10], ); // - limbs_cmp_same_length(out, ms) != Less test(&[10; 3], &[3], &[2], &[9], &[0, 10, 10]); // - ms_len >= REDC_1_TO_REDC_N_THRESHOLD // - REDC_1_TO_REDC_N_THRESHOLD <= ms_len < MUL_TOOM22_THRESHOLD in select_fns test( &[10; 102], &[ 15231838, 2040644427, 3019562008, 1849879669, 3035273653, 1126993058, 47231998, 1272966966, 808826123, 2613679871, 3880209905, 533657556, 462055026, 1995462791, 2669440556, 964537932, 1111256412, 3618168224, 2814460867, 3500086570, 4007554324, 423675806, 4263852014, 939174181, 3372315870, 2404528019, 2462982568, ], &[4284714037, 4294504709, 3097020148, 1061316867], &[ 2895738059, 2222742945, 2200913266, 2474343961, 674884792, 3868751732, 3089689534, 2430632097, 2488368713, 3062061319, 4067596626, 511264582, 1407628892, 2272907418, 959402877, 3744259866, 3311299232, 2145791174, 43238938, 3833638835, 4110565129, 4008973369, 104651202, 677542079, 758926920, 1101277253, 3001021931, 998015387, 1742463066, 558329360, 2693367111, 3480565457, 3612553333, 1301555794, 519337581, 3300908468, 3530322699, 2448060428, 4064907740, 2664586778, 1523503672, 3213102458, 1257460118, 2076514388, 4071643827, 3592057262, 1402398574, 3017877057, 2055576849, 732723305, 1414294091, 4223824602, 3201010967, 1895660785, 1135353915, 2148174613, 4048519927, 121851082, 2198350375, 1783615559, 372909943, 614317668, 3372914919, 2755021756, 4017557367, 2133054830, 1948457571, 1938410224, 3325075631, 3634267258, 51102224, 2458277488, 3478591381, 1824685083, 3648635504, 481889501, 1100046228, 4153007238, 3393775448, 288899148, 1691342799, 541535815, 3936683203, 3579439411, 1281616696, 2097613162, 1182389689, 2985495353, 2822637621, 3933095442, 4138905254, 4281995886, 1468542161, 503073229, 1438766160, 1146230629, 3365322628, 594370818, 3970846533, 2993627984, ], &[ 3220228332, 1289044619, 4090486882, 2935175502, 1036421691, 322080634, 2520677041, 782484792, 3367131407, 251234797, 3793043809, 2859808531, 1341835713, 1429457528, 2859236711, 988242793, 3516913319, 3085390135, 1767135385, 3505108006, 941241196, 1517169544, 581305334, 1456461198, 1628771306, 864062263, 818489872, 3761869500, 808518712, 1576582852, 3807006337, 2323525681, 106379360, 3251953336, 2046814458, 2437108016, 1297677798, 129047745, 3490510139, 1806687715, 3213874668, 139669025, 919576894, 2643933393, 3980690050, 2652575541, 1927756447, 2123306615, 440563656, 2040387516, 4243697106, 428296898, 915674737, 498045820, 3130354008, 1193458405, 3406781642, 3252972448, 201621523, 1862360144, 2039264045, 2329252476, 2686526115, 1116276280, 287363272, 4049536496, 3211163886, 2780240991, 3185623463, 3699825246, 260938527, 3712407400, 50158619, 4082561437, 3981632240, 1645303993, 1388449088, 1723061239, 1436532661, 1932705168, 3620788285, 4096149072, 2319194551, 2203579540, 1766526917, 783820005, 3067485228, 3442142247, 2486918849, 2955962844, 1280634082, 3907853014, 1337542963, 2795904203, 1989841069, 973220557, 1353182775, 2705903522, 3829991598, 71670781, 10, 10, ], ); // - ms_len >= MUL_TOOM22_THRESHOLD in select_fns test( &[10; 132], &[ 2688238368, 1370389694, 2050030377, 2515208601, 2857390881, 4197651524, 1239390266, 1406670778, 2579838638, 295836633, 3196840122, 3842197805, 3093150937, 3921979512, 3334864271, 4051787844, 1715354699, 784724006, 2641707538, 91367600, 564566325, 4232021563, 3303269258, 1546428796, 4081815008, 2772422919, 3080061263, 3655857709, 3221167157, 3188437627, 3509421900, 2117096697, 399342008, 595809629, 3677310060, 4115179023, 755358759, 2356175810, 1130123131, 1730880525, 295144730, 3749456557, ], &[ 870678421, 2796837091, 3293178107, 1768925464, 1619766842, 2289477468, 1997089941, 1122217361, 1351469882, 2292919231, 1820507033, 811208831, 2962958283, 49325855, 904973661, 2650666234, 38738475, 1350510862, 3541603511, 1957000434, 626956257, 3679451040, 455567141, 2358641221, 1772224239, 663265109, ], &[ 3910996289, 2816958662, 2867701269, 2489588705, 4139766686, 68347912, 3545464089, 186840093, 4192695275, 3384626828, 1867478774, 3430502357, 2070259035, 1818903078, 185487092, 1945164940, 198992488, 1340594809, 2884280378, 2659028966, 2731883802, 3386600963, 4226259957, 1351345124, 1596030101, 1412857735, 3371378007, 1255307044, 3627261742, 2728165048, 3740045608, 3893125603, 2353417837, 3173894525, 1712654005, 3756974619, 1870314396, 3071976119, 399143608, 2618882156, 2758650080, 1057786871, 2222605504, 3375739680, 696795589, 3386974205, 359484891, 309512373, 299872079, 2278512560, 532043407, 1466190502, 733728197, 3362102523, 2180739566, 3829805290, 397079472, 3354014956, 1906213944, 3156244881, 3388567106, 369361961, 264909755, 3405203581, 2313150087, 3156935606, 1429648656, 3898358330, 1257746430, 1594676943, 170660532, 2745162133, 2864414636, 2142084396, 2569588942, 3853728956, 2233612974, 152936585, 1575814183, 519325569, 2275674013, 1085948185, 2072284470, 3541789119, 4034514248, 1610140625, 3875476257, 1035874049, 3543420948, 1561693735, 966255080, 936126918, 2523487827, 2895401694, 1142029713, 862454352, 3620226631, 69690788, 3246184999, 485393839, 3514148744, 2848543979, 4007221509, 175089578, 1517243713, 1261753161, 3257856227, 116328541, 2289524271, 3087481870, 3446271192, 1201816042, 3910458324, 1249156998, 1230723249, 3753644481, 1117866811, 983288816, 2732615778, 743509902, 3225264110, 1171181988, 946574108, 1804691841, 3423828869, 959970900, 2507443216, 395931811, 1259542577, 2396067278, ], &[ 1025852633, 79270077, 3301788792, 1386637604, 192346455, 1456906572, 69195851, 3129723136, 2519645061, 2541961631, 1794686607, 4106028394, 2701350434, 1348632655, 1867572334, 1249803339, 1440960895, 250478100, 2889620165, 961879123, 1291616398, 432573079, 867602404, 778350117, 4216286390, 4226436012, 2329382459, 2871255036, 2542841218, 1342004849, 1363690216, 22108213, 4073323393, 4067883423, 3008421638, 2102737805, 3312566592, 3539262183, 4034305910, 1392816118, 2717447275, 2310567812, 2894277860, 2383199219, 4103937620, 708098321, 2949556562, 4211952216, 3158171510, 4137870672, 3903904439, 4282380128, 855731951, 659589583, 2557106859, 576388003, 313616280, 331520688, 1277940989, 2708897033, 533029719, 487352515, 1949824586, 505072740, 4038013897, 2298668550, 1178798567, 1512613139, 4068988335, 2153062284, 4118780280, 597996449, 1606074452, 2335555420, 2054577350, 3045549370, 2701737868, 3618701098, 3636119053, 1005071332, 2303326104, 51535250, 3397405829, 3833534865, 2425051659, 2190540066, 4180788716, 2608530236, 1439369848, 2112154998, 2289724846, 2610833560, 808802563, 2996847623, 3253345649, 2123523552, 4214461433, 1492789177, 3467294232, 2909754357, 3226703424, 619540384, 1914094063, 1208434472, 3653698470, 753691175, 2501672947, 4171705775, 3829738927, 1900544129, 2509951656, 1518574100, 2809954004, 2621465363, 2267697036, 3991643575, 869359274, 502886394, 1517544442, 868396157, 2801850027, 190888001, 4244506669, 3019225248, 1504559895, 3027372440, 1152465509, 3085485694, 2286582782, 1487765908, 10, 10, ], ); // - xs longer than ms test(&[10; 3], &[123, 456], &[20], &[105], &[36, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_1() { let out = &mut [10]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(2)]; limbs_mod_pow_odd(out, &[123, 456], &[789, 987], &[135, 797], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_2() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(2)]; limbs_mod_pow_odd(out, &[], &[789, 987], &[135, 797], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_3() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(2)]; limbs_mod_pow_odd(out, &[123, 456], &[], &[135, 797], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_4() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(2)]; limbs_mod_pow_odd(out, &[123, 456], &[789, 987], &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_5() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(2)]; limbs_mod_pow_odd(out, &[123, 456], &[789, 987], &[136, 797], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_6() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(1)]; limbs_mod_pow_odd(out, &[3], &[0], &[9], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_odd_fail_7() { let out = &mut [10; 3]; let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(1)]; limbs_mod_pow_odd(out, &[3], &[1], &[9], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_pow() { let test = |out: &[Limb], xs: &[Limb], es: &[Limb], ms: &[Limb], out_out: &[Limb]| { let out_old = out; let mut out = out_old.to_vec(); limbs_mod_pow(&mut out, xs, es, ms); assert_eq!(out, out_out); verify_limbs_mod_pow(out_old, xs, es, ms, &out); }; // - ms[0].odd() // - ms_zero_len == 0 test(&[10; 3], &[3], &[20], &[105], &[51, 10, 10]); test(&[10; 3], &[4], &[20], &[105], &[16, 10, 10]); test(&[10; 3], &[4], &[1000000], &[3], &[1, 10, 10]); // - ms[0].even() // - ms_zero_len != 0 // - xs_len >= ms_zero_len // - xs[0].odd() // - do_pow_low // - ms_nonzero_len >= ms_zero_len // - ms_twos != 0 test(&[10; 3], &[3], &[1000000], &[4], &[1, 10, 10]); // - xs[0].even() // - es_len == 1 // - es[0].wrapping_mul(bits) >= t // - !do_pow_low test(&[10; 3], &[4], &[1000000], &[6], &[4, 10, 10]); // - ms[ms_zero_len] == 0 // - xs_len < ms_zero_len // - ms_nonzero_len < ms_zero_len test(&[10; 3], &[4], &[1000000], &[0, 6], &[0, 4, 10]); // - es_len > 1 test(&[10; 3], &[4], &[1, 1], &[0, 6], &[0, 4, 10]); // - ms_twos == 0 test(&[10; 4], &[1], &[2], &[0, 1], &[1, 0, 10, 10]); // - es[0].wrapping_mul(bits) < t test(&[10; 4], &[2], &[2], &[0, 1], &[4, 0, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_1() { let out = &mut [10]; limbs_mod_pow(out, &[123, 456], &[789, 987], &[135, 797]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_2() { let out = &mut [10; 3]; limbs_mod_pow(out, &[], &[789, 987], &[135, 797]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_3() { let out = &mut [10; 3]; limbs_mod_pow(out, &[123, 456], &[], &[135, 797]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_4() { let out = &mut [10; 3]; limbs_mod_pow(out, &[123, 456], &[789, 987], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_5() { let out = &mut [10; 3]; limbs_mod_pow(out, &[3], &[0], &[9]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_pow_fail_6() { let out = &mut [10; 3]; limbs_mod_pow(out, &[3], &[1], &[9]); } #[test] fn test_mod_pow() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let exp = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_pow_assign(exp.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_pow_assign(&exp, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_pow_assign(exp.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_pow_assign(&exp, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_pow(exp.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_pow(exp.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_pow(&exp, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_pow(&exp, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_pow(exp.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_pow(exp.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_pow(&exp, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_pow(&exp, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "1", "0"); test("0", "0", "10", "1"); test("0", "1", "10", "0"); test("2", "10", "10", "4"); test("4", "13", "497", "445"); test("10", "1000", "30", "10"); test("2", "340", "341", "1"); test("5", "216", "217", "1"); test("2", "1000000", "1000000000", "747109376"); test( "1234567890", "1000000000", "12345678987654321", "10973935643347062", ); } #[test] fn mod_pow_fail() { assert_panic!(Natural::ZERO.mod_pow(Natural::from(3u32), Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_pow(Natural::from(3u32), Natural::ONE)); assert_panic!(Natural::ZERO.mod_pow(Natural::from(3u32), &Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_pow(Natural::from(3u32), &Natural::ONE)); assert_panic!(Natural::ZERO.mod_pow(&Natural::from(3u32), Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_pow(&Natural::from(3u32), Natural::ONE)); assert_panic!(Natural::ZERO.mod_pow(&Natural::from(3u32), &Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_pow(&Natural::from(3u32), &Natural::ONE)); assert_panic!((&Natural::ZERO).mod_pow(Natural::from(3u32), Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_pow(Natural::from(3u32), Natural::ONE)); assert_panic!((&Natural::ZERO).mod_pow(Natural::from(3u32), &Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_pow(Natural::from(3u32), &Natural::ONE)); assert_panic!((&Natural::ZERO).mod_pow(&Natural::from(3u32), Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_pow(&Natural::from(3u32), Natural::ONE)); assert_panic!((&Natural::ZERO).mod_pow(&Natural::from(3u32), &Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_pow(&Natural::from(3u32), &Natural::ONE)); assert_panic!({ let mut x = Natural::ZERO; x.mod_pow_assign(Natural::from(3u32), Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_pow_assign(Natural::from(3u32), Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_pow_assign(Natural::from(3u32), &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_pow_assign(Natural::from(3u32), Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_pow_assign(&Natural::from(3u32), Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_pow_assign(Natural::from(3u32), Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_pow_assign(&Natural::from(3u32), &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_pow_assign(Natural::from(3u32), Natural::ONE); }); } #[test] fn limbs_mod_pow_odd_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_7().test_properties_with_config( &config, |(mut out, xs, es, ms)| { let out_old = out.clone(); let mut scratch = vec![0; limbs_mod_pow_odd_scratch_len(ms.len())]; limbs_mod_pow_odd(&mut out, &xs, &es, &ms, &mut scratch); verify_limbs_mod_pow(&out_old, &xs, &es, &ms, &out); }, ); } #[test] fn limbs_mod_pow_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_quadruple_gen_var_6().test_properties_with_config( &config, |(mut out, xs, es, ms)| { let out_old = out.clone(); limbs_mod_pow(&mut out, &xs, &es, &ms); verify_limbs_mod_pow(&out_old, &xs, &es, &ms, &out); }, ); } #[test] fn mod_pow_properties() { natural_triple_gen_var_5().test_properties(|(x, exp, m)| { assert!(x.mod_is_reduced(&m)); let power_val_val_val = x.clone().mod_pow(exp.clone(), m.clone()); let power_val_ref_val = x.clone().mod_pow(&exp, m.clone()); let power_ref_val_val = (&x).mod_pow(exp.clone(), m.clone()); let power_ref_ref_val = (&x).mod_pow(&exp, m.clone()); let power_val_val_ref = x.clone().mod_pow(exp.clone(), &m); let power_val_ref_ref = x.clone().mod_pow(&exp, &m); let power_ref_val_ref = (&x).mod_pow(exp.clone(), &m); let power = (&x).mod_pow(&exp, &m); assert!(power_val_val_val.is_valid()); assert!(power_val_ref_val.is_valid()); assert!(power_ref_val_val.is_valid()); assert!(power_val_val_ref.is_valid()); assert!(power_val_val_ref.is_valid()); assert!(power_val_ref_ref.is_valid()); assert!(power_ref_val_ref.is_valid()); assert!(power.is_valid()); assert!(power.mod_is_reduced(&m)); assert_eq!(power_val_val_val, power); assert_eq!(power_val_ref_val, power); assert_eq!(power_ref_val_val, power); assert_eq!(power_ref_ref_val, power); assert_eq!(power_val_val_ref, power); assert_eq!(power_val_ref_ref, power); assert_eq!(power_ref_val_ref, power); let mut mut_x = x.clone(); mut_x.mod_pow_assign(exp.clone(), m.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, power); let mut mut_x = x.clone(); mut_x.mod_pow_assign(&exp, m.clone()); assert_eq!(mut_x, power); assert!(mut_x.is_valid()); let mut mut_x = x.clone(); mut_x.mod_pow_assign(exp.clone(), &m); assert!(mut_x.is_valid()); assert_eq!(mut_x, power); let mut mut_x = x.clone(); mut_x.mod_pow_assign(&exp, &m); assert_eq!(mut_x, power); assert!(mut_x.is_valid()); let num_power = BigUint::from(&x).modpow(&BigUint::from(&exp), &BigUint::from(&m)); assert_eq!(Natural::from(&num_power), power); let rug_power = rug::Integer::from(&x) .pow_mod(&rug::Integer::from(&exp), &rug::Integer::from(&m)) .unwrap(); assert_eq!(Natural::exact_from(&rug_power), power); if exp.even() { assert_eq!(x.mod_neg(&m).mod_pow(exp, m), power); } else { assert_eq!(x.mod_neg(&m).mod_pow(exp, &m), power.mod_neg(m)); } }); natural_pair_gen_var_5().test_properties(|(exp, m)| { assert_eq!( Natural::ZERO.mod_pow(&exp, &m), Natural::from(exp == 0 && m != 1), ); if m != 1 { assert_eq!(Natural::ONE.mod_pow(exp, m), 1); } }); natural_pair_gen_var_8().test_properties(|(ref x, ref m)| { assert_eq!(x.mod_pow(Natural::ZERO, m), Natural::from(*m != 1)); assert_eq!(x.mod_pow(Natural::ONE, m), *x); assert_eq!(x.mod_pow(Natural::TWO, m), x.mod_mul(x, m)); }); natural_quadruple_gen_var_2().test_properties(|(ref x, ref y, ref exp, ref m)| { assert_eq!( x.mod_mul(y, m).mod_pow(exp, m), x.mod_pow(exp, m).mod_mul(y.mod_pow(exp, m), m) ); }); natural_quadruple_gen_var_3().test_properties(|(ref x, ref e, ref f, ref m)| { assert_eq!( x.mod_pow(e + f, m), x.mod_pow(e, m).mod_mul(x.mod_pow(f, m), m) ); assert_eq!(x.mod_pow(e * f, m), x.mod_pow(e, m).mod_pow(f, m)); }); unsigned_triple_gen_var_15::().test_properties(|(x, exp, m)| { assert_eq!( x.mod_pow(exp, m), Natural::from(x).mod_pow(Natural::from(exp), Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ DivisibleByPowerOf2, ModPowerOf2, ModPowerOf2Assign, ModPowerOf2IsReduced, NegModPowerOf2, NegModPowerOf2Assign, PowerOf2, RemPowerOf2, RemPowerOf2Assign, ShrRound, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::LowMask; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_2, unsigned_pair_gen_var_20, unsigned_vec_unsigned_pair_gen_var_16, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2::{ limbs_mod_power_of_2, limbs_neg_mod_power_of_2, limbs_neg_mod_power_of_2_in_place, limbs_slice_mod_power_of_2_in_place, limbs_vec_mod_power_of_2_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_unsigned_triple_gen_var_1, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_9, natural_unsigned_pair_gen_var_10, natural_unsigned_unsigned_triple_gen_var_5, }; use std::cmp::min; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_and_limbs_vec_mod_power_of_2_in_place() { let test = |xs: &[Limb], pow: u64, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2(xs, pow), out); let mut xs = xs.to_vec(); limbs_vec_mod_power_of_2_in_place(&mut xs, pow); assert_eq!(xs, out); }; test(&[], 0, &[]); test(&[], 5, &[]); test(&[], 100, &[]); test(&[6, 7], 2, &[2]); test(&[100, 101, 102], 10, &[100]); test(&[123, 456], 0, &[]); test(&[123, 456], 1, &[1]); test(&[123, 456], 10, &[123]); test(&[123, 456], 33, &[123, 0]); test(&[123, 456], 40, &[123, 200]); test(&[123, 456], 100, &[123, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_mod_power_of_2_in_place() { let test = |xs: &[Limb], pow: u64, out: &[Limb]| { let mut xs = xs.to_vec(); limbs_slice_mod_power_of_2_in_place(&mut xs, pow); assert_eq!(xs, out); }; test(&[], 0, &[]); test(&[], 5, &[]); test(&[], 100, &[]); test(&[6, 7], 2, &[2, 0]); test(&[100, 101, 102], 10, &[100, 0, 0]); test(&[123, 456], 0, &[0, 0]); test(&[123, 456], 1, &[1, 0]); test(&[123, 456], 10, &[123, 0]); test(&[123, 456], 33, &[123, 0]); test(&[123, 456], 40, &[123, 200]); test(&[123, 456], 100, &[123, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_neg_mod_power_of_2_and_limbs_neg_mod_power_of_2_in_place() { let test = |xs: &[Limb], pow: u64, out: &[Limb]| { assert_eq!(limbs_neg_mod_power_of_2(xs, pow), out); let mut xs = xs.to_vec(); limbs_neg_mod_power_of_2_in_place(&mut xs, pow); assert_eq!(xs, out); }; test(&[], 0, &[]); test(&[], 5, &[0]); test(&[], 100, &[0, 0, 0, 0]); test(&[6, 7], 2, &[2]); test(&[100, 101, 102], 10, &[924]); test(&[123, 456], 0, &[]); test(&[123, 456], 1, &[1]); test(&[123, 456], 10, &[901]); test(&[123, 456], 33, &[4294967173, 1]); test(&[123, 456], 40, &[4294967173, 55]); test(&[123, 456], 100, &[4294967173, 4294966839, u32::MAX, 15]); } #[test] fn test_mod_power_of_2_and_rem_power_of_2() { let test = |s, v: u64, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); n.mod_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(v)); let n = u.clone().mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.rem_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().rem_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).rem_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 0, "0"); test("260", 8, "4"); test("1611", 4, "11"); test("123", 100, "123"); test("1000000000000", 0, "0"); test("1000000000000", 12, "0"); test("1000000000001", 12, "1"); test("999999999999", 12, "4095"); test("1000000000000", 15, "4096"); test("1000000000000", 100, "1000000000000"); test("1000000000000000000000000", 40, "1020608380928"); test("1000000000000000000000000", 64, "2003764205206896640"); test("4294967295", 31, "2147483647"); test("4294967295", 32, "4294967295"); test("4294967295", 33, "4294967295"); test("4294967296", 31, "0"); test("4294967296", 32, "0"); test("4294967296", 33, "4294967296"); test("4294967297", 31, "1"); test("4294967297", 32, "1"); test("4294967297", 33, "4294967297"); } #[test] fn test_neg_mod_power_of_2() { let test = |s, v: u64, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); n.neg_mod_power_of_2_assign(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(v)); let n = u.clone().neg_mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).neg_mod_power_of_2(v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", 0, "0"); test("260", 8, "252"); test("1611", 4, "5"); test("123", 100, "1267650600228229401496703205253"); test("1000000000000", 0, "0"); test("1000000000000", 12, "0"); test("1000000000001", 12, "4095"); test("999999999999", 12, "1"); test("1000000000000", 15, "28672"); test("1000000000000", 100, "1267650600228229400496703205376"); test("1000000000000000000000000", 40, "78903246848"); test("1000000000000000000000000", 64, "16442979868502654976"); test("4294967295", 31, "1"); test("4294967295", 32, "1"); test("4294967295", 33, "4294967297"); test("4294967296", 31, "0"); test("4294967296", 32, "0"); test("4294967296", 33, "4294967296"); test("4294967297", 31, "2147483647"); test("4294967297", 32, "4294967295"); test("4294967297", 33, "4294967295"); } #[test] fn limbs_mod_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2(&xs, pow)), Natural::from_owned_limbs_asc(xs).mod_power_of_2(pow), ); }); } macro_rules! limbs_slice_mod_power_of_2_in_place_helper { ($f: ident, $xs: ident, $pow: ident) => { let old_xs = $xs.clone(); $f(&mut $xs, $pow); let n = Natural::from_limbs_asc(&old_xs).mod_power_of_2($pow); assert_eq!(Natural::from_owned_limbs_asc($xs), n); }; } #[test] fn limbs_slice_mod_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, pow)| { limbs_slice_mod_power_of_2_in_place_helper!( limbs_slice_mod_power_of_2_in_place, xs, pow ); }, ); } #[test] fn limbs_vec_mod_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, pow)| { limbs_slice_mod_power_of_2_in_place_helper!(limbs_vec_mod_power_of_2_in_place, xs, pow); }, ); } #[test] fn limbs_neg_mod_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, pow)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_neg_mod_power_of_2(&xs, pow)), Natural::from_owned_limbs_asc(xs).neg_mod_power_of_2(pow), ); }); } #[test] fn limbs_neg_mod_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, pow)| { let old_xs = xs.clone(); limbs_neg_mod_power_of_2_in_place(&mut xs, pow); let n = Natural::from_limbs_asc(&old_xs).neg_mod_power_of_2(pow); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn mod_power_of_2_and_rem_power_of_2_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n.mod_power_of_2_assign(u); assert!(mut_n.is_valid()); let result = mut_n; assert!(result.mod_power_of_2_is_reduced(u)); let result_alt = (&n).mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let mut mut_n = n.clone(); mut_n.rem_power_of_2_assign(u); assert!(mut_n.is_valid()); let result_alt = mut_n; assert_eq!(result_alt, result); let result_alt = (&n).rem_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().rem_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert!(result <= n); assert_eq!((&n >> u << u) + &result, n); assert!(result < Natural::power_of_2(u)); assert_eq!(result == 0, n.divisible_by_power_of_2(u)); assert_eq!((&result).mod_power_of_2(u), result); assert_eq!(n & Natural::low_mask(u), result); }); natural_natural_unsigned_triple_gen_var_1().test_properties(|(x, y, u)| { assert_eq!( (&x + &y).mod_power_of_2(u), ((&x).mod_power_of_2(u) + (&y).mod_power_of_2(u)).mod_power_of_2(u) ); assert_eq!( (&x * &y).mod_power_of_2(u), (x.mod_power_of_2(u) * y.mod_power_of_2(u)).mod_power_of_2(u) ); }); natural_unsigned_pair_gen_var_9().test_properties(|(n, u)| { assert_eq!(n.mod_power_of_2(u), 0); }); natural_unsigned_pair_gen_var_10().test_properties(|(n, u)| { assert_ne!((&n).mod_power_of_2(u), 0); assert_eq!( (&n).mod_power_of_2(u) + n.neg_mod_power_of_2(u), Natural::power_of_2(u) ); }); natural_unsigned_unsigned_triple_gen_var_5().test_properties(|(n, u, v)| { assert_eq!( (&n).mod_power_of_2(u).mod_power_of_2(v), n.mod_power_of_2(min(u, v)) ); }); natural_gen().test_properties(|n| { assert_eq!(n.mod_power_of_2(0), 0); }); unsigned_gen().test_properties(|u| { assert_eq!(Natural::ZERO.mod_power_of_2(u), 0); }); unsigned_pair_gen_var_2::().test_properties(|(u, pow)| { assert_eq!(u.mod_power_of_2(pow), Natural::from(u).mod_power_of_2(pow)); assert_eq!(u.rem_power_of_2(pow), Natural::from(u).rem_power_of_2(pow)); }); } #[test] fn neg_mod_power_of_2_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n.neg_mod_power_of_2_assign(u); assert!(mut_n.is_valid()); let result = mut_n; assert!(result.mod_power_of_2_is_reduced(u)); let result_alt = (&n).neg_mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().neg_mod_power_of_2(u); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!(((&n).shr_round(u, Ceiling).0 << u) - &result, n); assert!(result < Natural::power_of_2(u)); assert_eq!(result == 0, n.divisible_by_power_of_2(u)); assert_eq!((&result).neg_mod_power_of_2(u), (&n).mod_power_of_2(u)); assert_eq!((-n).mod_power_of_2(u), result); }); natural_natural_unsigned_triple_gen_var_1().test_properties(|(x, y, u)| { assert_eq!( (&x + &y).neg_mod_power_of_2(u), ((&x).mod_power_of_2(u) + (&y).mod_power_of_2(u)).neg_mod_power_of_2(u) ); assert_eq!( (&x * &y).neg_mod_power_of_2(u), (x.mod_power_of_2(u) * y.mod_power_of_2(u)).neg_mod_power_of_2(u) ); }); natural_unsigned_pair_gen_var_9().test_properties(|(n, u)| { assert_eq!(n.neg_mod_power_of_2(u), 0); }); natural_unsigned_pair_gen_var_10().test_properties(|(n, u)| { let m = (&n).neg_mod_power_of_2(u); assert_ne!(m, 0); assert_eq!((((&n >> u) + Natural::ONE) << u) - &m, n); assert_eq!(n.mod_power_of_2(u) + m, Natural::power_of_2(u)); }); natural_gen().test_properties(|n| { assert_eq!(n.neg_mod_power_of_2(0), 0); }); unsigned_gen().test_properties(|u| { assert_eq!(Natural::ZERO.neg_mod_power_of_2(u), 0); }); unsigned_pair_gen_var_20::().test_properties(|(u, pow)| { assert_eq!( u.neg_mod_power_of_2(pow), Natural::from(u).neg_mod_power_of_2(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_add.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModAdd, ModPowerOf2, ModPowerOf2Add, ModPowerOf2AddAssign, ModPowerOf2IsReduced, ModPowerOf2Neg, ModPowerOf2Shl, ModPowerOf2Sub, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_add::{ limbs_mod_power_of_2_add, limbs_mod_power_of_2_add_greater, limbs_mod_power_of_2_add_in_place_either, limbs_mod_power_of_2_add_limb, limbs_slice_mod_power_of_2_add_greater_in_place_left, limbs_slice_mod_power_of_2_add_limb_in_place, limbs_vec_mod_power_of_2_add_in_place_left, limbs_vec_mod_power_of_2_add_limb_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_natural_unsigned_quadruple_gen_var_2, natural_natural_unsigned_triple_gen_var_4, natural_unsigned_pair_gen_var_11, unsigned_vec_unsigned_unsigned_triple_gen_var_14, unsigned_vec_unsigned_unsigned_triple_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19, }; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_add_limb() { let test = |xs: &[Limb], y: Limb, pow: u64, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_add_limb(xs, y, pow), out); }; test(&[], 0, 0, &[]); test(&[], 0, 5, &[]); test(&[], 5, 3, &[5]); test(&[123, 456], 789, 41, &[912, 456]); test(&[u32::MAX], 2, 33, &[1, 1]); test(&[u32::MAX], 2, 32, &[1]); test(&[u32::MAX, 3], 2, 34, &[1, 0]); test(&[u32::MAX, 3], 2, 35, &[1, 4]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_mod_power_of_2_add_limb_in_place() { let test = |xs: &[Limb], y: Limb, pow: u64, out: &[Limb], carry: bool| { let mut xs = xs.to_vec(); assert_eq!( limbs_slice_mod_power_of_2_add_limb_in_place(&mut xs, y, pow), carry ); assert_eq!(xs, out); }; test(&[], 0, 0, &[], false); test(&[], 0, 5, &[], false); test(&[], 5, 3, &[], true); test(&[123, 456], 789, 41, &[912, 456], false); test(&[u32::MAX], 2, 33, &[1], true); test(&[u32::MAX], 2, 32, &[1], false); test(&[u32::MAX, 3], 2, 34, &[1, 0], false); test(&[u32::MAX, 3], 2, 35, &[1, 4], false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_mod_power_of_2_add_limb_in_place() { let test = |xs: &[Limb], y: Limb, pow: u64, out: &[Limb]| { let mut xs = xs.to_vec(); limbs_vec_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); assert_eq!(xs, out); }; test(&[123, 456], 789, 41, &[912, 456]); test(&[u32::MAX], 2, 33, &[1, 1]); test(&[u32::MAX], 2, 32, &[1]); test(&[u32::MAX, 3], 2, 34, &[1, 0]); test(&[u32::MAX, 3], 2, 35, &[1, 4]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_mod_power_of_2_add_limb_in_place_fail() { limbs_vec_mod_power_of_2_add_limb_in_place(&mut vec![], 10, 4); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_add_greater() { let test = |xs, ys, pow, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_add_greater(xs, ys, pow), out); }; test(&[], &[], 0, &[]); test(&[], &[], 5, &[]); test(&[2], &[], 3, &[2]); test(&[2], &[3], 2, &[1]); test(&[1, 2, 3], &[6, 7], 100, &[7, 9, 3]); test(&[100, 101, u32::MAX], &[102, 101, 2], 97, &[202, 202, 1, 1]); test(&[100, 101, u32::MAX], &[102, 101, 2], 96, &[202, 202, 1]); test(&[u32::MAX], &[2], 33, &[1, 1]); test(&[u32::MAX], &[2], 32, &[1]); test(&[u32::MAX, 3], &[2], 34, &[1, 0]); test(&[u32::MAX, 3], &[2], 35, &[1, 4]); test(&[u32::MAX, u32::MAX], &[2], 65, &[1, 0, 1]); test(&[u32::MAX, u32::MAX], &[2], 64, &[1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn test_limbs_mod_power_of_2_add_greater_fail() { limbs_mod_power_of_2_add_greater(&[6, 7], &[1, 2, 3], 4); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_add_and_limbs_vec_mod_power_of_2_add_in_place_left() { let test = |xs_before, ys, pow, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_add(xs_before, ys, pow), out); let mut xs = xs_before.to_vec(); limbs_vec_mod_power_of_2_add_in_place_left(&mut xs, ys, pow); assert_eq!(xs, out); }; test(&[], &[], 0, &[]); test(&[], &[], 5, &[]); test(&[2], &[], 3, &[2]); test(&[], &[2], 3, &[2]); test(&[2], &[3], 2, &[1]); test(&[1, 2, 3], &[6, 7], 100, &[7, 9, 3]); test(&[6, 7], &[1, 2, 3], 100, &[7, 9, 3]); test(&[100, 101, u32::MAX], &[102, 101, 2], 97, &[202, 202, 1, 1]); test(&[100, 101, u32::MAX], &[102, 101, 2], 96, &[202, 202, 1]); test(&[u32::MAX], &[2], 33, &[1, 1]); test(&[u32::MAX], &[2], 32, &[1]); test(&[u32::MAX, 3], &[2], 34, &[1, 0]); test(&[u32::MAX, 3], &[2], 35, &[1, 4]); test(&[u32::MAX, u32::MAX], &[2], 65, &[1, 0, 1]); test(&[u32::MAX, u32::MAX], &[2], 64, &[1, 0]); test(&[2], &[u32::MAX, u32::MAX], 65, &[1, 0, 1]); test(&[2], &[u32::MAX, u32::MAX], 64, &[1, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_mod_power_of_2_add_greater_in_place_left() { let test = |xs_before: &[Limb], ys, pow, xs_after: &[Limb], carry| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut xs, ys, pow), carry ); assert_eq!(xs, xs_after); }; test(&[], &[], 0, &[], false); test(&[], &[], 5, &[], false); test(&[2], &[], 3, &[2], false); test(&[2], &[3], 2, &[1], false); test(&[1, 2, 3], &[6, 7], 100, &[7, 9, 3], false); test( &[100, 101, u32::MAX], &[102, 101, 2], 97, &[202, 202, 1], true, ); test( &[100, 101, u32::MAX], &[102, 101, 2], 96, &[202, 202, 1], false, ); test(&[u32::MAX], &[2], 33, &[1], true); test(&[u32::MAX], &[2], 32, &[1], false); test(&[u32::MAX, 3], &[2], 34, &[1, 0], false); test(&[u32::MAX, 3], &[2], 35, &[1, 4], false); test(&[u32::MAX, u32::MAX], &[2], 65, &[1, 0], true); test(&[u32::MAX, u32::MAX], &[2], 64, &[1, 0], false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_mod_power_of_2_add_greater_in_place_left_fail() { let mut xs = vec![6, 7]; limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut xs, &[1, 2, 3], 4); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_add_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], pow, right, xs_after: &[Limb], ys_after: &[Limb]| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!( limbs_mod_power_of_2_add_in_place_either(&mut xs, &mut ys, pow), right ); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], 0, false, &[], &[]); test(&[], &[], 5, false, &[], &[]); test(&[2], &[], 3, false, &[2], &[]); test(&[], &[2], 3, true, &[], &[2]); test(&[2], &[3], 2, false, &[1], &[3]); test(&[1, 2, 3], &[6, 7], 100, false, &[7, 9, 3], &[6, 7]); test(&[6, 7], &[1, 2, 3], 100, true, &[6, 7], &[7, 9, 3]); test( &[100, 101, u32::MAX], &[102, 101, 2], 97, false, &[202, 202, 1, 1], &[102, 101, 2], ); test( &[100, 101, u32::MAX], &[102, 101, 2], 96, false, &[202, 202, 1], &[102, 101, 2], ); test(&[u32::MAX], &[2], 33, false, &[1, 1], &[2]); test(&[u32::MAX], &[2], 32, false, &[1], &[2]); test(&[u32::MAX, 3], &[2], 34, false, &[1, 0], &[2]); test(&[u32::MAX, 3], &[2], 35, false, &[1, 4], &[2]); test(&[u32::MAX, u32::MAX], &[2], 65, false, &[1, 0, 1], &[2]); test(&[u32::MAX, u32::MAX], &[2], 64, false, &[1, 0], &[2]); test(&[2], &[u32::MAX, u32::MAX], 65, true, &[2], &[1, 0, 1]); test(&[2], &[u32::MAX, u32::MAX], 64, true, &[2], &[1, 0]); } #[test] fn test_mod_power_of_2_add() { let test = |s, t, pow, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); assert!(v.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_add_assign(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_add_assign(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_add(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_add(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_add(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_add(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", 0, "0"); test("0", "0", 5, "0"); test("0", "2", 5, "2"); test("10", "14", 4, "8"); test("0", "123", 7, "123"); test("123", "0", 7, "123"); test("123", "456", 9, "67"); test("1267650600228229401496703205375", "3", 100, "2"); test("3", "1267650600228229401496703205375", 100, "2"); } #[test] fn mod_power_of_2_add_fail() { assert_panic!(Natural::ZERO.mod_power_of_2_add(Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_add(Natural::ZERO, 0)); assert_panic!(Natural::ZERO.mod_power_of_2_add(&Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_add(&Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_add(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_add(Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_add(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_add(Natural::ZERO, 0)); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_add_assign(Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_add_assign(Natural::ZERO, 0); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_add_assign(&Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_add_assign(&Natural::ZERO, 0); }); } #[test] fn limbs_mod_power_of_2_add_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_14().test_properties_with_config( &config, |(xs, y, pow)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_add_limb(&xs, y, pow)), Natural::from_owned_limbs_asc(xs).mod_power_of_2_add(Natural::from(y), pow), ); }, ); } #[test] fn limbs_slice_mod_power_of_2_add_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_14().test_properties_with_config( &config, |(mut xs, y, pow)| { let old_xs = xs.clone(); let carry = limbs_slice_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); let n = Natural::from_limbs_asc(&old_xs).mod_power_of_2_add(Natural::from(y), pow); let mut expected_limbs = n.into_limbs_asc(); assert_eq!(carry, expected_limbs.len() == xs.len() + 1); expected_limbs.resize(xs.len(), 0); assert_eq!(xs, expected_limbs); }, ); } #[test] fn limbs_vec_mod_power_of_2_add_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_15().test_properties_with_config( &config, |(mut xs, y, pow)| { let old_xs = xs.clone(); limbs_vec_mod_power_of_2_add_limb_in_place(&mut xs, y, pow); let n = Natural::from_owned_limbs_asc(old_xs).mod_power_of_2_add(Natural::from(y), pow); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } fn limbs_mod_power_of_2_add_helper( f: &dyn Fn(&[Limb], &[Limb], u64) -> Vec, xs: Vec, ys: Vec, pow: u64, ) { assert_eq!( Natural::from_owned_limbs_asc(f(&xs, &ys, pow)), Natural::from_owned_limbs_asc(xs) .mod_power_of_2_add(Natural::from_owned_limbs_asc(ys), pow) ); } #[test] fn limbs_mod_power_of_2_add_greater_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19().test_properties_with_config( &config, |(xs, ys, pow)| { limbs_mod_power_of_2_add_helper(&limbs_mod_power_of_2_add_greater, xs, ys, pow); }, ); } #[test] fn limbs_mod_power_of_2_add_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().test_properties_with_config( &config, |(xs, ys, pow)| { limbs_mod_power_of_2_add_helper(&limbs_mod_power_of_2_add, xs, ys, pow); }, ); } #[test] fn limbs_slice_mod_power_of_2_add_greater_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_19().test_properties_with_config( &config, |(mut xs, ys, pow)| { let xs_old = xs.clone(); let carry = limbs_slice_mod_power_of_2_add_greater_in_place_left(&mut xs, &ys, pow); let n = Natural::from_owned_limbs_asc(xs_old) .mod_power_of_2_add(Natural::from_owned_limbs_asc(ys), pow); let len = xs.len(); let mut limbs = n.into_limbs_asc(); assert_eq!(carry, limbs.len() == len + 1); limbs.resize(len, 0); assert_eq!(limbs, xs); }, ); } #[test] fn limbs_vec_mod_power_of_2_add_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().test_properties_with_config( &config, |(mut xs, ys, pow)| { let xs_old = xs.clone(); limbs_vec_mod_power_of_2_add_in_place_left(&mut xs, &ys, pow); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) .mod_power_of_2_add(Natural::from_owned_limbs_asc(ys), pow) ); }, ); } #[test] fn limbs_mod_power_of_2_add_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().test_properties_with_config( &config, |(mut xs, mut ys, pow)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_mod_power_of_2_add_in_place_either(&mut xs, &mut ys, pow); let n = Natural::from_limbs_asc(&xs_old) .mod_power_of_2_add(Natural::from_limbs_asc(&ys_old), pow); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }, ); } #[test] fn mod_power_of_2_add_properties() { natural_natural_unsigned_triple_gen_var_4().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let sum_val_val = x.clone().mod_power_of_2_add(y.clone(), pow); let sum_val_ref = x.clone().mod_power_of_2_add(&y, pow); let sum_ref_val = (&x).mod_power_of_2_add(y.clone(), pow); let sum = (&x).mod_power_of_2_add(&y, pow); assert!(sum_val_val.is_valid()); assert!(sum_val_ref.is_valid()); assert!(sum_ref_val.is_valid()); assert!(sum.is_valid()); assert!(sum.mod_power_of_2_is_reduced(pow)); assert_eq!(sum_val_val, sum); assert_eq!(sum_val_ref, sum); assert_eq!(sum_ref_val, sum); assert_eq!((&x + &y).mod_power_of_2(pow), sum); let mut sum_alt = &x + &y; sum_alt.clear_bit(pow); assert_eq!(sum_alt, sum); assert_eq!((&x).mod_add(&y, Natural::power_of_2(pow)), sum); let mut mut_x = x.clone(); mut_x.mod_power_of_2_add_assign(y.clone(), pow); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x.mod_power_of_2_add_assign(&y, pow); assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); assert_eq!((&y).mod_power_of_2_add(&x, pow), sum); assert_eq!( (&x).mod_power_of_2_sub((&y).mod_power_of_2_neg(pow), pow), sum ); assert_eq!((&sum).mod_power_of_2_sub(&x, pow), y); assert_eq!(sum.mod_power_of_2_sub(y, pow), x); }); natural_unsigned_pair_gen_var_11().test_properties(|(x, pow)| { assert_eq!((&x).mod_power_of_2_add(Natural::ZERO, pow), x); assert_eq!(Natural::ZERO.mod_power_of_2_add(&x, pow), x); assert_eq!( (&x).mod_power_of_2_add(&x, pow), x.mod_power_of_2_shl(1, pow) ); }); natural_natural_natural_unsigned_quadruple_gen_var_2().test_properties(|(x, y, z, pow)| { assert_eq!( (&x).mod_power_of_2_add(&y, pow).mod_power_of_2_add(&z, pow), x.mod_power_of_2_add(y.mod_power_of_2_add(z, pow), pow) ); }); unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert_eq!( x.mod_power_of_2_add(y, pow), Natural::from(x).mod_power_of_2_add(Natural::from(y), pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_inverse.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModInverse, ModPowerOf2Inverse, ModPowerOf2IsReduced, ModPowerOf2Mul, ModPowerOf2Neg, Parity, PowerOf2, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::LowMask; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{unsigned_gen_var_11, unsigned_pair_gen_var_39}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_14; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_power_of_2_inverse() { let test = |s, pow, out| { let n = Natural::from_str(s).unwrap(); let result = n.clone().mod_power_of_2_inverse(pow); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); let result = (&n).mod_power_of_2_inverse(pow); assert_eq!(result.to_debug_string(), out); assert!(result.is_none_or(|n| n.is_valid())); assert_eq!( n.mod_inverse(Natural::power_of_2(pow)).to_debug_string(), out ); }; test("1", 6, "Some(1)"); test("8", 12, "None"); test("3", 5, "Some(11)"); test("3", 10, "Some(683)"); test("12345678987654321", 60, "Some(454333680368735313)"); test("12345678987654322", 60, "None"); } #[test] fn mod_power_of_2_inverse() { assert_panic!(Natural::ZERO.mod_power_of_2_inverse(5)); assert_panic!(Natural::from(30u8).mod_power_of_2_inverse(3)); assert_panic!((&Natural::ZERO).mod_power_of_2_inverse(5)); assert_panic!((&Natural::from(30u8)).mod_power_of_2_inverse(3)); } #[test] fn mod_power_of_2_inverse_properties() { natural_unsigned_pair_gen_var_14().test_properties(|(n, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let result = n.clone().mod_power_of_2_inverse(pow); let result_ref = (&n).mod_power_of_2_inverse(pow); assert!(result.as_ref().is_none_or(Natural::is_valid)); assert!(result_ref.as_ref().is_none_or(Natural::is_valid)); assert_eq!(result_ref, result); assert_eq!((&n).mod_inverse(Natural::power_of_2(pow)), result); assert_eq!(result.is_some(), n.odd()); if let Some(inverse) = result { assert!(inverse.mod_power_of_2_is_reduced(pow)); assert_eq!((&inverse).mod_power_of_2_inverse(pow).as_ref(), Some(&n)); assert_eq!((&n).mod_power_of_2_mul(&inverse, pow), 1u32); assert_eq!( n.mod_power_of_2_neg(pow).mod_power_of_2_inverse(pow), Some(inverse.mod_power_of_2_neg(pow)) ); } }); unsigned_gen_var_11().test_properties(|pow| { assert_eq!(Natural::ONE.mod_power_of_2_inverse(pow), Some(Natural::ONE)); assert_eq!( Natural::low_mask(pow).mod_power_of_2_inverse(pow), Some(Natural::low_mask(pow)) ); }); unsigned_pair_gen_var_39::().test_properties(|(n, pow)| { assert_eq!( Natural::from(n).mod_power_of_2_inverse(pow), n.mod_power_of_2_inverse(pow).map(Natural::from) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_is_reduced.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModIsReduced, ModPowerOf2, ModPowerOf2IsReduced, PowerOf2, }; use malachite_base::test_util::generators::unsigned_pair_gen_var_2; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; use std::str::FromStr; #[test] fn test_mod_power_of_2_is_reduced() { let test = |u, pow, out| { assert_eq!( Natural::from_str(u).unwrap().mod_power_of_2_is_reduced(pow), out ); }; test("0", 5, true); test("100", 5, false); test("100", 8, true); test("1000000000000", 39, false); test("1000000000000", 40, true); } #[test] fn mod_power_of_2_is_reduced_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, pow)| { let is_reduced = n.mod_power_of_2_is_reduced(pow); assert_eq!(is_reduced, (&n).mod_power_of_2(pow) == n); assert_eq!(is_reduced, n.mod_is_reduced(&Natural::power_of_2(pow))); }); unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { assert_eq!( n.mod_power_of_2_is_reduced(pow), Natural::from(n).mod_power_of_2_is_reduced(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModMul, ModPowerOf2, ModPowerOf2Add, ModPowerOf2IsReduced, ModPowerOf2Mul, ModPowerOf2MulAssign, ModPowerOf2Neg, ModPowerOf2Square, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_mul::{ limbs_mod_power_of_2_mul, limbs_mod_power_of_2_mul_ref_ref, limbs_mod_power_of_2_mul_val_ref, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_natural_unsigned_quadruple_gen_var_2, natural_natural_unsigned_triple_gen_var_4, natural_unsigned_pair_gen_var_11, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20, }; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_mul() { let test = |xs, ys, pow, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_mul_ref_ref(xs, ys, pow), out); let mut mut_xs = xs.to_vec(); assert_eq!(limbs_mod_power_of_2_mul_val_ref(&mut mut_xs, ys, pow), out); let mut mut_xs = xs.to_vec(); let mut mut_ys = ys.to_vec(); assert_eq!(limbs_mod_power_of_2_mul(&mut mut_xs, &mut mut_ys, pow), out); let product = Natural::from_limbs_asc(out); assert_eq!( Natural::from_limbs_asc(xs).mod_power_of_2_mul(Natural::from_limbs_asc(ys), pow), product ); assert_eq!( (Natural::from_limbs_asc(xs) * Natural::from_limbs_asc(ys)).mod_power_of_2(pow), product ); }; // - max_len <= xs_len + ys_len + 1 // - xs_len >= limit && ys_len >= limit // - xs_len == max_len // - ys_len == max_len test(&[1], &[1], 1, &[1]); test(&[1], &[1], 5, &[1]); // - xs_len < max_len // - ys_len < max_len test(&[1], &[1], 33, &[1, 0]); test(&[2], &[1], 3, &[2]); test(&[1], &[2], 3, &[2]); test(&[2], &[3], 2, &[2]); // - xs_len < limit || ys_len < limit test(&[1, 2, 3], &[6, 7], 100, &[6, 19, 32, 5]); test(&[6, 7], &[1, 2, 3], 100, &[6, 19, 32, 5]); // - max_len > xs_len + ys_len + 1 test(&[3255925883], &[3653042335], 131, &[2997571685, 2769295845]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_fail_1() { limbs_mod_power_of_2_mul(&mut vec![1], &mut vec![], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_fail_2() { limbs_mod_power_of_2_mul(&mut vec![], &mut vec![1], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_val_ref_fail_1() { limbs_mod_power_of_2_mul_val_ref(&mut vec![1], &[], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_val_ref_fail_2() { limbs_mod_power_of_2_mul_val_ref(&mut vec![], &[1], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_ref_ref_fail_1() { limbs_mod_power_of_2_mul_ref_ref(&[1], &[], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_mul_ref_ref_fail_2() { limbs_mod_power_of_2_mul_ref_ref(&[], &[1], 2); } #[test] fn test_mod_power_of_2_mul() { let test = |s, t, pow, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); assert!(v.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_mul_assign(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_mul_assign(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_mul(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_mul(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_mul(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_mul(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", 0, "0"); test("1", "1", 5, "1"); test("1", "1", 33, "1"); test("1", "2", 5, "2"); test("3", "2", 5, "6"); test("10", "14", 4, "12"); test("123", "456", 9, "280"); test("123456789", "987654321", 60, "121932631112635269"); } #[test] fn mod_power_of_2_mul_fail() { assert_panic!(Natural::ZERO.mod_power_of_2_mul(Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_mul(Natural::ZERO, 0)); assert_panic!(Natural::ZERO.mod_power_of_2_mul(&Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_mul(&Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_mul(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_mul(Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_mul(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_mul(Natural::ZERO, 0)); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_mul_assign(Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_mul_assign(Natural::ZERO, 0); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_mul_assign(&Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_mul_assign(&Natural::ZERO, 0); }); } #[test] fn limbs_mod_power_of_2_mul_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().test_properties_with_config( &config, |(mut xs, mut ys, pow)| { let old_xs = xs.clone(); let old_ys = ys.clone(); let product = Natural::from_limbs_asc(&xs).mod_power_of_2_mul(Natural::from_limbs_asc(&ys), pow); assert_eq!( (Natural::from_limbs_asc(&xs) * Natural::from_limbs_asc(&ys)).mod_power_of_2(pow), product ); assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_mul(&mut xs, &mut ys, pow)), product, ); let mut xs = old_xs.clone(); assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_mul_val_ref(&mut xs, &ys, pow)), product, ); assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_mul_ref_ref( &old_xs, &old_ys, pow )), product, ); }, ); } #[test] fn mod_power_of_2_mul_properties() { natural_natural_unsigned_triple_gen_var_4().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let product_val_val = x.clone().mod_power_of_2_mul(y.clone(), pow); let product_val_ref = x.clone().mod_power_of_2_mul(&y, pow); let product_ref_val = (&x).mod_power_of_2_mul(y.clone(), pow); let product = (&x).mod_power_of_2_mul(&y, pow); assert!(product_val_val.is_valid()); assert!(product_val_ref.is_valid()); assert!(product_ref_val.is_valid()); assert!(product.is_valid()); assert!(product.mod_power_of_2_is_reduced(pow)); assert_eq!(product_val_val, product); assert_eq!(product_val_ref, product); assert_eq!(product_ref_val, product); assert_eq!((&x * &y).mod_power_of_2(pow), product); assert_eq!((&x).mod_mul(&y, Natural::power_of_2(pow)), product); let mut mut_x = x.clone(); mut_x.mod_power_of_2_mul_assign(y.clone(), pow); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x.mod_power_of_2_mul_assign(&y, pow); assert_eq!(mut_x, product); assert!(mut_x.is_valid()); assert_eq!((&y).mod_power_of_2_mul(&x, pow), product); assert_eq!( (&x).mod_power_of_2_mul((&y).mod_power_of_2_neg(pow), pow), (&product).mod_power_of_2_neg(pow) ); assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_mul(y, pow), product.mod_power_of_2_neg(pow) ); }); natural_unsigned_pair_gen_var_11().test_properties(|(ref x, pow)| { assert_eq!(x.mod_power_of_2_mul(Natural::ZERO, pow), 0); assert_eq!(Natural::ZERO.mod_power_of_2_mul(x, pow), 0); if pow != 0 { assert_eq!(x.mod_power_of_2_mul(Natural::ONE, pow), *x); assert_eq!(Natural::ONE.mod_power_of_2_mul(x, pow), *x); } assert_eq!(x.mod_power_of_2_mul(x, pow), x.mod_power_of_2_square(pow)); }); natural_natural_natural_unsigned_quadruple_gen_var_2().test_properties( |(ref x, ref y, ref z, pow)| { assert_eq!( x.mod_power_of_2_mul(y, pow).mod_power_of_2_mul(z, pow), x.mod_power_of_2_mul(y.mod_power_of_2_mul(z, pow), pow) ); assert_eq!( x.mod_power_of_2_mul(y.mod_power_of_2_add(z, pow), pow), x.mod_power_of_2_mul(y, pow) .mod_power_of_2_add(x.mod_power_of_2_mul(z, pow), pow) ); assert_eq!( x.mod_power_of_2_add(y, pow).mod_power_of_2_mul(z, pow), x.mod_power_of_2_mul(z, pow) .mod_power_of_2_add(y.mod_power_of_2_mul(z, pow), pow) ); }, ); unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert_eq!( x.mod_power_of_2_mul(y, pow), Natural::from(x).mod_power_of_2_mul(Natural::from(y), pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModNeg, ModPowerOf2, ModPowerOf2Add, ModPowerOf2IsReduced, ModPowerOf2Neg, ModPowerOf2NegAssign, PowerOf2, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::unsigned_pair_gen_var_17; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_11; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_power_of_2_neg() { let test = |s, pow, out| { let u = Natural::from_str(s).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); let n = u.clone().mod_power_of_2_neg(pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_power_of_2_is_reduced(pow)); let n = (&u).mod_power_of_2_neg(pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u; n.mod_power_of_2_neg_assign(pow); assert_eq!(n.to_string(), out); }; test("0", 5, "0"); test("10", 4, "6"); test("100", 8, "156"); test("1", 32, "4294967295"); test("100", 100, "1267650600228229401496703205276"); test("1267650600228229401496703205276", 100, "100"); } #[test] fn mod_power_of_2_neg_fail() { assert_panic!(Natural::ONE.mod_power_of_2_neg(0)); assert_panic!((&Natural::ONE).mod_power_of_2_neg(0)); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_neg_assign(0); }); } #[test] fn mod_power_of_2_neg_properties() { natural_unsigned_pair_gen_var_11().test_properties(|(n, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let neg = (&n).mod_power_of_2_neg(pow); assert!(neg.is_valid()); assert!(neg.mod_power_of_2_is_reduced(pow)); let neg_alt = n.clone().mod_power_of_2_neg(pow); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let mut n_alt = n.clone(); n_alt.mod_power_of_2_neg_assign(pow); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); assert_eq!(neg, (-&n).mod_power_of_2(pow)); assert_eq!(neg, (&n).mod_neg(Natural::power_of_2(pow))); assert_eq!((&neg).mod_power_of_2_neg(pow), n); assert_eq!((&n).mod_power_of_2_add(&neg, pow), 0); assert_eq!( n == neg, n == Natural::ZERO || n == Natural::power_of_2(pow - 1) ); }); unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert_eq!( n.mod_power_of_2_neg(pow), Natural::from(n).mod_power_of_2_neg(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2IsReduced, ModPowerOf2Mul, ModPowerOf2Neg, ModPowerOf2Pow, ModPowerOf2PowAssign, Parity, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_16, unsigned_vec_pair_gen_var_3, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_pow::{ limbs_mod_power_of_2_pow, limbs_pow_low, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_natural_unsigned_quadruple_gen_var_3, natural_natural_natural_unsigned_quadruple_gen_var_4, natural_natural_unsigned_triple_gen_var_5, natural_unsigned_pair_gen, natural_unsigned_pair_gen_var_11, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21, }; use malachite_nz::test_util::natural::arithmetic::mod_power_of_2_pow::*; use std::panic::catch_unwind; use std::str::FromStr; fn verify_limbs_pow_low(xs: &[Limb], es: &[Limb], out: &[Limb]) { let exp = Natural::from_limbs_asc(es); let n = xs.len(); let pow = u64::exact_from(n) << Limb::LOG_WIDTH; let x = Natural::from_limbs_asc(xs).mod_power_of_2(pow); let expected = x.mod_power_of_2_pow(exp, pow); assert!(expected.mod_power_of_2_is_reduced(pow)); assert_eq!(Natural::from_limbs_asc(&out[..n]), expected); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pow_low() { let test = |xs: &[Limb], es: &[Limb], out: &[Limb]| { let xs_old = xs; let mut xs = xs_old.to_vec(); let mut scratch = vec![0; xs.len()]; limbs_pow_low(&mut xs, es, &mut scratch); assert_eq!(xs, out); verify_limbs_pow_low(xs_old, es, out); }; // - bit_index != 0 && !limbs_get_bit(es, bit_index - 1) // - bit_index != 0 first time // - bit_index >= window_size // - this_windowsize == 1 // - bit_index != 0 second time // - bit_index == 0 first time test(&[3], &[20], &[3486784401]); // - bit_index < window_size // - bit_index == 0 second time test(&[123, 456], &[789], &[426102667, 1687864191]); // - this_windowsize > 1 test( &[55455610, 1786865634], &[ 597666165, 1946668956, 2861877195, 1004122685, 3052222557, 4193145938, 1332420253, 4049695026, 536465941, 13401346, 206750422, 2547236772, 718474167, 1253952310, 4175135275, 3923178820, 3877868744, ], &[0, 0], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_low_fail_1() { let mut scratch = vec![]; limbs_pow_low(&mut [], &[2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_low_fail_2() { let mut scratch = vec![1]; limbs_pow_low(&mut [1], &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_low_fail_3() { let mut scratch = vec![1]; limbs_pow_low(&mut [1], &[2, 0], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_low_fail_4() { let mut scratch = vec![1]; limbs_pow_low(&mut [1], &[1], &mut scratch); } fn verify_limbs_mod_power_of_2_pow(xs: &[Limb], es: &[Limb], pow: u64, out: &[Limb]) { let exp = Natural::from_limbs_asc(es); let x = Natural::from_limbs_asc(xs); assert!(x.mod_power_of_2_is_reduced(pow)); let expected = (&x).mod_power_of_2_pow(&exp, pow); assert!(expected.mod_power_of_2_is_reduced(pow)); assert_eq!(simple_binary_mod_power_of_2_pow(&x, &exp, pow), expected); assert_eq!(Natural::from_limbs_asc(out), expected); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_pow() { let test = |xs: &[Limb], es: &[Limb], pow: u64, out: &[Limb]| { let xs_old = xs; let mut xs = xs_old.to_vec(); limbs_mod_power_of_2_pow(&mut xs, es, pow); assert_eq!(xs, out); verify_limbs_mod_power_of_2_pow(xs_old, es, pow, out); }; test(&[1], &[2], 2, &[1]); test(&[3], &[2], 2, &[1]); test(&[3], &[3], 4, &[11]); test(&[25], &[10, 10], 5, &[17]); test(&[123, 456], &[789, 987], 42, &[426102667, 987]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_pow_fail_1() { limbs_mod_power_of_2_pow(&mut vec![2], &[2, 0], 5); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_pow_fail_2() { limbs_mod_power_of_2_pow(&mut vec![2], &[1], 5); } #[test] fn test_mod_power_of_2_pow() { let test = |s, t, pow, out| { let u = Natural::from_str(s).unwrap(); let exp = Natural::from_str(t).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_pow_assign(exp.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_pow_assign(&exp, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_pow(exp.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_pow(exp.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_pow(&exp, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_pow(&exp, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", 0, "0"); test("0", "0", 10, "1"); test("0", "1", 10, "0"); test("2", "10", 8, "0"); test("3", "10", 8, "169"); test("10", "1000", 30, "0"); test("11", "1000", 30, "289109473"); test("3", "1000000", 100, "1176684907284103408190379631873"); test( "123456789", "1000000000", 100, "1180978940853570377595087681537", ); } #[test] fn mod_power_of_2_pow_fail() { assert_panic!(Natural::ONE.mod_power_of_2_pow(Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_pow(&Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_pow(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_pow(&Natural::ONE, 0)); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_pow_assign(Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_pow_assign(&Natural::ONE, 0); }); } #[test] fn limbs_pow_low_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_3().test_properties_with_config(&config, |(mut xs, es)| { let xs_old = xs.clone(); let mut scratch = vec![0; xs.len()]; limbs_pow_low(&mut xs, &es, &mut scratch); verify_limbs_pow_low(&xs_old, &es, &xs); }); } #[test] fn limbs_mod_power_of_2_pow_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_21().test_properties_with_config( &config, |(mut xs, es, pow)| { let xs_old = xs.clone(); limbs_mod_power_of_2_pow(&mut xs, &es, pow); verify_limbs_mod_power_of_2_pow(&xs_old, &es, pow, &xs); }, ); } #[test] fn mod_power_of_2_pow_properties() { natural_natural_unsigned_triple_gen_var_5().test_properties(|(x, exp, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); let power_val_val = x.clone().mod_power_of_2_pow(exp.clone(), pow); let power_val_ref = x.clone().mod_power_of_2_pow(&exp, pow); let power_ref_val = (&x).mod_power_of_2_pow(exp.clone(), pow); let power = (&x).mod_power_of_2_pow(&exp, pow); assert!(power_val_val.is_valid()); assert!(power_val_ref.is_valid()); assert!(power_ref_val.is_valid()); assert!(power.is_valid()); assert!(power.mod_power_of_2_is_reduced(pow)); assert_eq!(power_val_val, power); assert_eq!(power_val_ref, power); assert_eq!(power_ref_val, power); let mut mut_x = x.clone(); mut_x.mod_power_of_2_pow_assign(exp.clone(), pow); assert!(mut_x.is_valid()); assert_eq!(mut_x, power); let mut mut_x = x.clone(); mut_x.mod_power_of_2_pow_assign(&exp, pow); assert_eq!(mut_x, power); assert!(mut_x.is_valid()); if exp.even() { assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_pow(exp, pow), power ); } else { assert_eq!( x.mod_power_of_2_neg(pow).mod_power_of_2_pow(exp, pow), power.mod_power_of_2_neg(pow) ); } }); natural_unsigned_pair_gen().test_properties(|(exp, pow)| { assert_eq!( Natural::ZERO.mod_power_of_2_pow(&exp, pow), Natural::from(exp == 0 && pow != 0), ); if pow != 0 { assert_eq!(Natural::ONE.mod_power_of_2_pow(exp, pow), 1); } }); natural_unsigned_pair_gen_var_11().test_properties(|(x, pow)| { assert_eq!( (&x).mod_power_of_2_pow(Natural::ZERO, pow), Natural::from(pow != 0) ); assert_eq!((&x).mod_power_of_2_pow(Natural::ONE, pow), x); assert_eq!( (&x).mod_power_of_2_pow(Natural::TWO, pow), (&x).mod_power_of_2_mul(&x, pow) ); }); natural_natural_natural_unsigned_quadruple_gen_var_3().test_properties(|(x, y, exp, pow)| { assert_eq!( (&x).mod_power_of_2_mul(&y, pow) .mod_power_of_2_pow(&exp, pow), x.mod_power_of_2_pow(&exp, pow) .mod_power_of_2_mul(y.mod_power_of_2_pow(exp, pow), pow) ); }); natural_natural_natural_unsigned_quadruple_gen_var_4().test_properties(|(x, e, f, pow)| { assert_eq!( (&x).mod_power_of_2_pow(&e + &f, pow), (&x).mod_power_of_2_pow(&e, pow) .mod_power_of_2_mul((&x).mod_power_of_2_pow(&f, pow), pow) ); assert_eq!( (&x).mod_power_of_2_pow(&e * &f, pow), x.mod_power_of_2_pow(e, pow).mod_power_of_2_pow(f, pow) ); }); unsigned_triple_gen_var_16::().test_properties(|(x, exp, pow)| { assert_eq!( x.mod_power_of_2_pow(exp, pow), Natural::from(x).mod_power_of_2_pow(Natural::from(exp), pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ IsPowerOf2, ModPowerOf2, ModPowerOf2IsReduced, ModPowerOf2Neg, ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_14, unsigned_pair_gen_var_28, unsigned_signed_unsigned_triple_gen_var_1, unsigned_triple_gen_var_17, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_signed_unsigned_triple_gen_var_1, natural_unsigned_pair_gen_var_11, natural_unsigned_unsigned_triple_gen_var_6, }; use std::ops::Shl; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_mod_power_of_2_shl_unsigned { ($t:ident) => { let test = |s, v: $t, pow, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); assert!(n.mod_power_of_2_is_reduced(pow)); n.mod_power_of_2_shl_assign(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_power_of_2_is_reduced(pow)); let n = u.clone().mod_power_of_2_shl(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_power_of_2_shl(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!((u << v).mod_power_of_2(pow).to_string(), out); }; test("0", 10, 0, "0"); test("0", 10, 8, "0"); test("123", 5, 8, "96"); test("123", 100, 80, "0"); }; } macro_rules! test_mod_power_of_2_shl_signed { ($t:ident) => { let test = |s, v: $t, pow, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); assert!(n.mod_power_of_2_is_reduced(pow)); n.mod_power_of_2_shl_assign(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_power_of_2_is_reduced(pow)); let n = u.clone().mod_power_of_2_shl(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_power_of_2_shl(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!((u << v).mod_power_of_2(pow).to_string(), out); }; test("0", 10, 0, "0"); test("0", 10, 8, "0"); test("123", 5, 8, "96"); test("123", 100, 80, "0"); test("123", -2, 8, "30"); test("123", -10, 8, "0"); }; } #[test] fn test_mod_power_of_2_shl() { apply_to_unsigneds!(test_mod_power_of_2_shl_unsigned); apply_to_signeds!(test_mod_power_of_2_shl_signed); } fn mod_power_of_2_shl_fail_helper() where Natural: ModPowerOf2Shl + ModPowerOf2ShlAssign, for<'a> &'a Natural: ModPowerOf2Shl, { assert_panic!(Natural::ONE.mod_power_of_2_shl(T::exact_from(3u8), 0)); assert_panic!((&Natural::ONE).mod_power_of_2_shl(T::exact_from(3u8), 0)); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_shl_assign(T::exact_from(3u8), 0); }); } #[test] fn mod_power_of_2_shl_fail() { apply_fn_to_primitive_ints!(mod_power_of_2_shl_fail_helper); } fn unsigned_properties() where Natural: ModPowerOf2Shl + ModPowerOf2ShlAssign, for<'a> &'a Natural: ModPowerOf2Shl + Shl, Limb: ModPowerOf2Shl, { natural_unsigned_unsigned_triple_gen_var_6::().test_properties(|(n, u, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let mut mut_n = n.clone(); mut_n.mod_power_of_2_shl_assign(u, pow); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_power_of_2_is_reduced(pow)); let shifted_alt = (&n).mod_power_of_2_shl(u, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_power_of_2_shl(u, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n << u).mod_power_of_2(pow), shifted); assert_eq!( (&n).mod_power_of_2_neg(pow).mod_power_of_2_shl(u, pow), n.mod_power_of_2_shl(u, pow).mod_power_of_2_neg(pow) ); }); natural_unsigned_pair_gen_var_11().test_properties(|(n, pow)| { assert_eq!((&n).mod_power_of_2_shl(T::ZERO, pow), n); }); unsigned_pair_gen_var_28::().test_properties(|(u, pow)| { assert_eq!(Natural::ZERO.mod_power_of_2_shl(u, pow), 0); if pow != 0 { let shifted = Natural::ONE.mod_power_of_2_shl(u, pow); assert!(shifted == 0 || shifted.is_power_of_2()); } }); unsigned_triple_gen_var_17::().test_properties(|(n, u, pow)| { assert_eq!( Natural::from(n).mod_power_of_2_shl(u, pow), n.mod_power_of_2_shl(u, pow) ); }); } fn signed_properties() where Natural: ModPowerOf2Shl + ModPowerOf2Shr + ModPowerOf2ShlAssign, for<'a> &'a Natural: ModPowerOf2Shl + ModPowerOf2Shr + Shl, Limb: ModPowerOf2Shl, { natural_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let mut mut_n = n.clone(); mut_n.mod_power_of_2_shl_assign(i, pow); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_power_of_2_is_reduced(pow)); let shifted_alt = (&n).mod_power_of_2_shl(i, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_power_of_2_shl(i, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n << i).mod_power_of_2(pow), shifted); if i != T::MIN { assert_eq!(n.mod_power_of_2_shr(-i, pow), shifted); } }); natural_unsigned_pair_gen_var_11().test_properties(|(n, pow)| { assert_eq!((&n).mod_power_of_2_shl(T::ZERO, pow), n); }); signed_unsigned_pair_gen_var_14::().test_properties(|(i, pow)| { assert_eq!(Natural::ZERO.mod_power_of_2_shl(i, pow), 0); if pow != 0 { let shifted = Natural::ONE.mod_power_of_2_shl(i, pow); assert!(shifted == 0 || shifted.is_power_of_2()); } }); unsigned_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert_eq!( Natural::from(n).mod_power_of_2_shl(i, pow), n.mod_power_of_2_shl(i, pow) ); }); } #[test] fn mod_power_of_2_shl_properties() { apply_fn_to_unsigneds!(unsigned_properties); apply_fn_to_signeds!(signed_properties); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ IsPowerOf2, ModPowerOf2, ModPowerOf2IsReduced, ModPowerOf2Shl, ModPowerOf2Shr, ModPowerOf2ShrAssign, }; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_14, unsigned_signed_unsigned_triple_gen_var_1, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_signed_unsigned_triple_gen_var_1, natural_unsigned_pair_gen_var_11, }; use std::ops::Shr; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_mod_power_of_2_shr { ($t:ident) => { let test = |s, v: $t, pow, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); assert!(n.mod_power_of_2_is_reduced(pow)); n.mod_power_of_2_shr_assign(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_power_of_2_is_reduced(pow)); let n = u.clone().mod_power_of_2_shr(v, pow); assert!(n.is_valid()); let n = (&u).mod_power_of_2_shr(v, pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!((u >> v).mod_power_of_2(pow).to_string(), out); }; test("0", -10, 0, "0"); test("0", -10, 8, "0"); test("123", -5, 8, "96"); test("123", -100, 80, "0"); test("123", 2, 8, "30"); test("123", 10, 8, "0"); }; } #[test] fn test_mod_power_of_2_shr() { apply_to_signeds!(test_mod_power_of_2_shr); } fn mod_power_of_2_shr_fail_helper() where Natural: ModPowerOf2Shr + ModPowerOf2ShrAssign, for<'a> &'a Natural: ModPowerOf2Shr, { assert_panic!(Natural::ONE.mod_power_of_2_shr(T::exact_from(3u8), 0)); assert_panic!((&Natural::ONE).mod_power_of_2_shr(T::exact_from(3u8), 0)); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_shr_assign(T::exact_from(3u8), 0); }); } #[test] fn mod_power_of_2_shr_fail() { apply_fn_to_signeds!(mod_power_of_2_shr_fail_helper); } fn properties_helper() where Natural: ModPowerOf2Shr + ModPowerOf2Shl + ModPowerOf2ShrAssign, for<'a> &'a Natural: ModPowerOf2Shr + ModPowerOf2Shl + Shr, Limb: ModPowerOf2Shr, { natural_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let mut mut_n = n.clone(); mut_n.mod_power_of_2_shr_assign(i, pow); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_power_of_2_is_reduced(pow)); let shifted_alt = (&n).mod_power_of_2_shr(i, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_power_of_2_shr(i, pow); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n >> i).mod_power_of_2(pow), shifted); if i != T::MIN { assert_eq!(n.mod_power_of_2_shl(-i, pow), shifted); } }); natural_unsigned_pair_gen_var_11().test_properties(|(n, pow)| { assert_eq!((&n).mod_power_of_2_shr(T::ZERO, pow), n); }); signed_unsigned_pair_gen_var_14::().test_properties(|(i, pow)| { assert_eq!(Natural::ZERO.mod_power_of_2_shr(i, pow), 0); if pow != 0 { let shifted = Natural::ONE.mod_power_of_2_shr(i, pow); assert!(shifted == 0 || shifted.is_power_of_2()); } }); unsigned_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| { assert_eq!( Natural::from(n).mod_power_of_2_shr(i, pow), n.mod_power_of_2_shr(i, pow) ); }); } #[test] fn mod_power_of_2_shr_properties() { apply_fn_to_signeds!(properties_helper); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2IsReduced, ModPowerOf2Mul, ModPowerOf2Neg, ModPowerOf2Square, ModPowerOf2SquareAssign, ModSquare, PowerOf2, Square, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_pair_gen_var_17, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_20, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_square::{ limbs_mod_power_of_2_square, limbs_mod_power_of_2_square_ref, limbs_square_low, limbs_square_low_basecase, limbs_square_low_divide_and_conquer, limbs_square_low_scratch_len, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_4, natural_unsigned_pair_gen_var_11, unsigned_vec_pair_gen_var_21, unsigned_vec_unsigned_pair_gen_var_30, }; use malachite_nz::test_util::natural::arithmetic::mod_power_of_2_square::*; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_low_basecase() { let test = |out_before: &[Limb], xs: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_square_low_basecase(&mut out, xs); assert_eq!(out, out_after); let len = xs.len(); let x = Natural::from_limbs_asc(xs); let pow = u64::exact_from(len) << Limb::LOG_WIDTH; let expected_square = (&x).square().mod_power_of_2(pow); assert_eq!(x.mod_power_of_2_square(pow), expected_square); let square = Natural::from_limbs_asc(&out_after[..len]); assert_eq!(square, expected_square); assert_eq!(&out_before[len..], &out_after[len..]); }; // - n == 1 test(&[10; 3], &[1], &[1, 10, 10]); // - n == 2 test(&[10; 3], &[123, 456], &[15129, 112176, 10]); // - n > 2 // - n.odd() in limbs_square_low_diagonal test(&[10; 4], &[123, 456, 789], &[15129, 112176, 402030, 10]); // - n.even() in limbs_square_low_diagonal test( &[10; 5], &[123, 456, 789, 987], &[15129, 112176, 402030, 962370, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_basecase_fail_1() { limbs_square_low_basecase(&mut [10], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_basecase_fail_2() { limbs_square_low_basecase(&mut [10, 10], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_low_divide_and_conquer() { let test = |out_before: &[Limb], xs: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_low_scratch_len(xs.len())]; limbs_square_low_divide_and_conquer(&mut out, xs, &mut scratch); assert_eq!(out, out_after); let len = xs.len(); let x = Natural::from_limbs_asc(xs); let pow = u64::exact_from(len) << Limb::LOG_WIDTH; let expected_square = (&x).square().mod_power_of_2(pow); assert_eq!(x.mod_power_of_2_square(pow), expected_square); let square = Natural::from_limbs_asc(&out_after[..len]); assert_eq!(square, expected_square); assert_eq!(&out_before[len..], &out_after[len..]); }; test(&[10; 3], &[123, 456], &[15129, 112176, 10]); test(&[10; 4], &[123, 456, 789], &[15129, 112176, 402030, 10]); test( &[10; 5], &[123, 456, 789, 987], &[15129, 112176, 402030, 962370, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_divide_and_conquer_fail_1() { let mut scratch = vec![0; limbs_square_low_scratch_len(2)]; limbs_square_low_divide_and_conquer(&mut [10], &[10, 10], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_divide_and_conquer_fail_2() { let mut scratch = vec![0; limbs_square_low_scratch_len(0)]; limbs_square_low_divide_and_conquer(&mut [10, 10], &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_divide_and_conquer_fail_3() { let mut scratch = vec![0; limbs_square_low_scratch_len(1)]; limbs_square_low_divide_and_conquer(&mut [10, 10], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_low() { let test = |out_before: &[Limb], xs: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_square_low(&mut out, xs); assert_eq!(out, out_after); let len = xs.len(); let x = Natural::from_limbs_asc(xs); let pow = u64::exact_from(len) << Limb::LOG_WIDTH; let expected_square = (&x).square().mod_power_of_2(pow); assert_eq!(x.mod_power_of_2_square(pow), expected_square); let square = Natural::from_limbs_asc(&out_after[..len]); assert_eq!(square, expected_square); assert_eq!(&out_before[len..], &out_after[len..]); }; test(&[10; 3], &[1], &[1, 10, 10]); test(&[10; 3], &[123, 456], &[15129, 112176, 10]); test(&[10; 4], &[123, 456, 789], &[15129, 112176, 402030, 10]); test( &[10; 5], &[123, 456, 789, 987], &[15129, 112176, 402030, 962370, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_fail_1() { limbs_square_low(&mut [10], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_low_fail_2() { limbs_square_low(&mut [10, 10], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_square() { let test = |xs, pow, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_square_ref(xs, pow), out); let mut mut_xs = xs.to_vec(); assert_eq!(limbs_mod_power_of_2_square(&mut mut_xs, pow), out); let square = Natural::from_limbs_asc(out); assert_eq!( Natural::from_limbs_asc(xs).mod_power_of_2_square(pow), square ); assert_eq!( Natural::from_limbs_asc(xs).square().mod_power_of_2(pow), square ); }; test(&[1], 1, &[1]); test(&[1], 1, &[1]); test(&[3], 2, &[1]); test(&[25], 5, &[17]); test(&[123, 456], 42, &[15129, 560]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_square_fail() { limbs_mod_power_of_2_square(&mut vec![], 2); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_square_ref_fail() { limbs_mod_power_of_2_square_ref(&[], 2); } #[test] fn test_mod_power_of_2_square() { let test = |s, pow, out| { let u = Natural::from_str(s).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); let n = u.clone().mod_power_of_2_square(pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_power_of_2_is_reduced(pow)); let n = (&u).mod_power_of_2_square(pow); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u; n.mod_power_of_2_square_assign(pow); assert_eq!(n.to_string(), out); }; test("0", 0, "0"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "0"); test("2", 3, "4"); test("5", 3, "1"); test("100", 8, "16"); test("12345678987654321", 64, "16556040056090124897"); } #[test] fn mod_power_of_2_square_fail() { assert_panic!(Natural::ONE.mod_power_of_2_square(0)); assert_panic!((&Natural::ONE).mod_power_of_2_square(0)); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_square_assign(0); }); } fn verify_limbs_square_low(out_before: &[Limb], xs: &[Limb], out_after: &[Limb]) { let len = xs.len(); let x = Natural::from_limbs_asc(xs); let pow = u64::exact_from(len) << Limb::LOG_WIDTH; let expected_square = (&x).square().mod_power_of_2(pow); assert_eq!(x.mod_power_of_2_square(pow), expected_square); let square = Natural::from_limbs_asc(&out_after[..len]); assert_eq!(square, expected_square); assert_eq!(&out_before[len..], &out_after[len..]); } #[test] fn limbs_square_low_basecase_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_21().test_properties_with_config(&config, |(mut out, xs)| { let out_old = out.clone(); limbs_square_low_basecase(&mut out, &xs); verify_limbs_square_low(&out_old, &xs, &out); let expected_out = out; let mut out = out_old; limbs_square_low_basecase_unrestricted(&mut out, &xs); assert_eq!(out, expected_out); }); } #[test] fn limbs_square_low_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_20().test_properties_with_config(&config, |(mut out, xs)| { let out_old = out.clone(); let mut scratch = vec![0; limbs_square_low_scratch_len(xs.len())]; limbs_square_low_divide_and_conquer(&mut out, &xs, &mut scratch); verify_limbs_square_low(&out_old, &xs, &out); }); } #[test] fn limbs_square_low_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_1().test_properties_with_config(&config, |(mut out, xs)| { let out_old = out.clone(); limbs_square_low(&mut out, &xs); verify_limbs_square_low(&out_old, &xs, &out); }); } #[test] fn limbs_mod_power_of_2_square_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_30().test_properties_with_config( &config, |(mut xs, pow)| { let xs_old = xs.clone(); let out = limbs_mod_power_of_2_square(&mut xs, pow); assert_eq!(limbs_mod_power_of_2_square_ref(&xs_old, pow), out); let expected_square = Natural::from_owned_limbs_asc(xs_old).mod_power_of_2_square(pow); assert_eq!(Natural::from_owned_limbs_asc(out), expected_square); }, ); } #[test] fn mod_power_of_2_square_properties() { natural_unsigned_pair_gen_var_11().test_properties(|(n, pow)| { assert!(n.mod_power_of_2_is_reduced(pow)); let square = (&n).mod_power_of_2_square(pow); assert!(square.is_valid()); assert!(square.mod_power_of_2_is_reduced(pow)); let square_alt = n.clone().mod_power_of_2_square(pow); assert!(square_alt.is_valid()); assert_eq!(square_alt, square); let mut n_alt = n.clone(); n_alt.mod_power_of_2_square_assign(pow); assert!(square_alt.is_valid()); assert_eq!(square_alt, square); assert_eq!(square, (&n).square().mod_power_of_2(pow)); assert_eq!(square, (&n).mod_square(Natural::power_of_2(pow))); assert_eq!(n.mod_power_of_2_neg(pow).mod_power_of_2_square(pow), square); }); unsigned_gen_var_5().test_properties(|pow| { assert_eq!(Natural::ZERO.mod_power_of_2_square(pow), 0); if pow != 0 { assert_eq!(Natural::ONE.mod_power_of_2_square(pow), 1); } }); natural_natural_unsigned_triple_gen_var_4().test_properties(|(x, y, pow)| { assert_eq!( (&x).mod_power_of_2_mul(&y, pow).mod_power_of_2_square(pow), x.mod_power_of_2_square(pow) .mod_power_of_2_mul(y.mod_power_of_2_square(pow), pow) ); }); unsigned_pair_gen_var_17::().test_properties(|(n, pow)| { assert_eq!( n.mod_power_of_2_square(pow), Natural::from(n).mod_power_of_2_square(pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_power_of_2_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModPowerOf2, ModPowerOf2Add, ModPowerOf2IsReduced, ModPowerOf2Neg, ModPowerOf2Sub, ModPowerOf2SubAssign, ModSub, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_triple_gen_var_11; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mod_power_of_2_sub::{ limbs_mod_power_of_2_limb_sub_limbs, limbs_mod_power_of_2_limb_sub_limbs_in_place, limbs_mod_power_of_2_sub, limbs_mod_power_of_2_sub_in_place_either, limbs_mod_power_of_2_sub_in_place_left, limbs_mod_power_of_2_sub_in_place_right, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_unsigned_triple_gen_var_4, natural_unsigned_pair_gen_var_11, unsigned_vec_unsigned_unsigned_triple_gen_var_16, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20, }; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_limb_sub_limbs_and_limbs_mod_power_of_2_limb_sub_limbs_in_place() { let test = |x: Limb, ys: &[Limb], pow: u64, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_limb_sub_limbs(x, ys, pow), out); let mut ys = ys.to_vec(); limbs_mod_power_of_2_limb_sub_limbs_in_place(x, &mut ys, pow); assert_eq!(ys, out); }; test(3, &[2], 4, &[1]); test(3, &[10], 4, &[9]); test(3, &[1, 2, 3], 70, &[2, u32::MAX - 1, 60]); test( 3, &[1, 2, 3], 200, &[2, u32::MAX - 1, 0xfffffffc, u32::MAX, u32::MAX, u32::MAX, 255], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_limb_sub_limbs_fail() { limbs_mod_power_of_2_limb_sub_limbs(3, &[10], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mod_power_of_2_limb_sub_limbs_in_place_fail() { let mut ys = vec![10]; limbs_mod_power_of_2_limb_sub_limbs_in_place(3, &mut ys, 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_sub() { let test = |xs_before, ys, pow, out: &[Limb]| { assert_eq!(limbs_mod_power_of_2_sub(xs_before, ys, pow), out); let mut xs = xs_before.to_vec(); limbs_mod_power_of_2_sub_in_place_left(&mut xs, ys, pow); assert_eq!(xs, out); }; test(&[], &[], 0, &[]); test(&[], &[], 5, &[]); test(&[2], &[], 3, &[2]); test(&[], &[2], 3, &[6]); test(&[2], &[3], 2, &[3]); test(&[1, 2, 3], &[6, 7], 100, &[0xfffffffb, 0xfffffffa, 2]); test(&[6, 7], &[1, 2, 3], 100, &[5, 5, 0xfffffffd, 15]); test(&[6, 7], &[1, 2], 100, &[5, 5]); test( &[1, 2], &[6, 7], 100, &[0xfffffffb, 0xfffffffa, u32::MAX, 15], ); test(&[6, 7], &[2, 3, 0], 100, &[4, 4, 0]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_sub_in_place_right() { let test = |xs, ys_before: &[Limb], pow, out: &[Limb]| { let mut ys = ys_before.to_vec(); limbs_mod_power_of_2_sub_in_place_right(xs, &mut ys, pow); assert_eq!(ys, out); }; test(&[], &[], 0, &[]); test(&[], &[], 5, &[]); test(&[2], &[], 3, &[2]); test(&[], &[2], 3, &[6]); test(&[2], &[3], 2, &[3]); test(&[1, 2, 3], &[6, 7], 100, &[0xfffffffb, 0xfffffffa, 2]); test(&[6, 7], &[1, 2, 3], 100, &[5, 5, 0xfffffffd, 15]); test(&[6, 7], &[1, 2], 100, &[5, 5]); test( &[1, 2], &[6, 7], 100, &[0xfffffffb, 0xfffffffa, u32::MAX, 15], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mod_power_of_2_sub_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], pow, right, xs_after: &[Limb], ys_after: &[Limb]| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!( limbs_mod_power_of_2_sub_in_place_either(&mut xs, &mut ys, pow), right ); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], 0, false, &[], &[]); test(&[], &[], 5, false, &[], &[]); test(&[2], &[], 3, false, &[2], &[]); test(&[], &[2], 3, true, &[], &[6]); test(&[2], &[3], 2, false, &[3], &[3]); test( &[1, 2, 3], &[6, 7], 100, false, &[0xfffffffb, 0xfffffffa, 2], &[6, 7], ); test( &[6, 7], &[1, 2, 3], 100, true, &[6, 7], &[5, 5, 0xfffffffd, 15], ); test(&[6, 7], &[1, 2], 100, false, &[5, 5], &[1, 2]); test( &[1, 2], &[6, 7], 100, false, &[0xfffffffb, 0xfffffffa, u32::MAX, 15], &[6, 7], ); } #[test] fn test_mod_power_of_2_sub() { let test = |s, t, pow, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert!(u.mod_power_of_2_is_reduced(pow)); assert!(v.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_sub_assign(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_power_of_2_is_reduced(pow)); let mut n = u.clone(); n.mod_power_of_2_sub_assign(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_sub(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_sub(v.clone(), pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_power_of_2_sub(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_power_of_2_sub(&v, pow); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", 0, "0"); test("0", "0", 5, "0"); test("0", "27", 5, "5"); test("10", "2", 4, "8"); test("2", "10", 4, "8"); test("0", "5", 7, "123"); test("123", "0", 7, "123"); test("123", "56", 9, "67"); test("56", "123", 9, "445"); test("3", "1267650600228229401496703205375", 100, "4"); test( "10970645355953595821", "19870830162202579837", 65, "27993303341170119216", ); test( "14424295573283161220", "2247489031103704789", 66, "12176806542179456431", ); test( "2247489031103704789", "14424295573283161220", 66, "61610169752658750033", ); test( "340279770772528537691305857201098194975", "5708990430541473157891818604560539975629668416", 165, "46762343404498631680132551366007801946215309901791", ); } #[test] fn mod_power_of_2_sub_fail() { assert_panic!(Natural::ZERO.mod_power_of_2_sub(Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_sub(Natural::ZERO, 0)); assert_panic!(Natural::ZERO.mod_power_of_2_sub(&Natural::ONE, 0)); assert_panic!(Natural::ONE.mod_power_of_2_sub(&Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_sub(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_sub(Natural::ZERO, 0)); assert_panic!((&Natural::ZERO).mod_power_of_2_sub(Natural::ONE, 0)); assert_panic!((&Natural::ONE).mod_power_of_2_sub(Natural::ZERO, 0)); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_sub_assign(Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_sub_assign(Natural::ZERO, 0); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_power_of_2_sub_assign(&Natural::ONE, 0); }); assert_panic!({ let mut x = Natural::ONE; x.mod_power_of_2_sub_assign(&Natural::ZERO, 0); }); } #[test] fn limbs_mod_power_of_2_limb_sub_limbs_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_16().test_properties_with_config( &config, |(ys, x, pow)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_limb_sub_limbs(x, &ys, pow)), Natural::from(x).mod_power_of_2_sub(Natural::from_owned_limbs_asc(ys), pow), ); }, ); } #[test] fn limbs_mod_power_of_2_limb_sub_limbs_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_16().test_properties_with_config( &config, |(mut ys, x, pow)| { let old_ys = ys.clone(); limbs_mod_power_of_2_limb_sub_limbs_in_place(x, &mut ys, pow); let n = Natural::from(x).mod_power_of_2_sub(Natural::from_owned_limbs_asc(old_ys), pow); let mut expected_limbs = n.into_limbs_asc(); expected_limbs.resize(ys.len(), 0); assert_eq!(ys, expected_limbs); }, ); } #[test] fn limbs_mod_power_of_2_sub_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().test_properties_with_config( &config, |(xs, ys, pow)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_mod_power_of_2_sub(&xs, &ys, pow)), Natural::from_owned_limbs_asc(xs) .mod_power_of_2_sub(Natural::from_owned_limbs_asc(ys), pow) ); }, ); } #[test] fn limbs_mod_power_of_2_sub_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_18().test_properties_with_config( &config, |(mut xs, ys, pow)| { let xs_old = xs.clone(); limbs_mod_power_of_2_sub_in_place_left(&mut xs, &ys, pow); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) .mod_power_of_2_sub(Natural::from_owned_limbs_asc(ys), pow) ); }, ); } #[test] fn limbs_mod_power_of_2_sub_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().test_properties_with_config( &config, |(xs, mut ys, pow)| { let ys_old = ys.clone(); limbs_mod_power_of_2_sub_in_place_right(&xs, &mut ys, pow); assert_eq!( Natural::from_owned_limbs_asc(ys), Natural::from_owned_limbs_asc(xs) .mod_power_of_2_sub(Natural::from_owned_limbs_asc(ys_old), pow) ); }, ); } #[test] fn limbs_mod_power_of_2_sub_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_20().test_properties_with_config( &config, |(mut xs, mut ys, pow)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_mod_power_of_2_sub_in_place_either(&mut xs, &mut ys, pow); let n = Natural::from_limbs_asc(&xs_old) .mod_power_of_2_sub(Natural::from_limbs_asc(&ys_old), pow); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }, ); } #[test] fn mod_power_of_2_sub_properties() { natural_natural_unsigned_triple_gen_var_4().test_properties(|(x, y, pow)| { assert!(x.mod_power_of_2_is_reduced(pow)); assert!(y.mod_power_of_2_is_reduced(pow)); let diff_val_val = x.clone().mod_power_of_2_sub(y.clone(), pow); let diff_val_ref = x.clone().mod_power_of_2_sub(&y, pow); let diff_ref_val = (&x).mod_power_of_2_sub(y.clone(), pow); let diff = (&x).mod_power_of_2_sub(&y, pow); assert!(diff_val_val.is_valid()); assert!(diff_val_ref.is_valid()); assert!(diff_ref_val.is_valid()); assert!(diff.is_valid()); assert!(diff.mod_power_of_2_is_reduced(pow)); assert_eq!(diff_val_val, diff); assert_eq!(diff_val_ref, diff); assert_eq!(diff_ref_val, diff); assert_eq!( (Integer::from(&x) - Integer::from(&y)).mod_power_of_2(pow), diff ); let diff_alt = if x >= y { &x - &y } else { let mut x = x.clone(); x.set_bit(pow); &x - &y }; assert_eq!(diff_alt, diff); assert_eq!((&x).mod_sub(&y, Natural::power_of_2(pow)), diff); let mut mut_x = x.clone(); mut_x.mod_power_of_2_sub_assign(y.clone(), pow); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = x.clone(); mut_x.mod_power_of_2_sub_assign(&y, pow); assert_eq!(mut_x, diff); assert!(mut_x.is_valid()); assert_eq!( (&y).mod_power_of_2_sub(&x, pow), (&diff).mod_power_of_2_neg(pow), ); assert_eq!( (&x).mod_power_of_2_add((&y).mod_power_of_2_neg(pow), pow), diff ); assert_eq!((&diff).mod_power_of_2_add(&y, pow), x); assert_eq!(diff.mod_power_of_2_sub(x, pow), y.mod_power_of_2_neg(pow)); }); natural_unsigned_pair_gen_var_11().test_properties(|(x, pow)| { assert_eq!((&x).mod_power_of_2_sub(Natural::ZERO, pow), x); assert_eq!( Natural::ZERO.mod_power_of_2_sub(&x, pow), (&x).mod_power_of_2_neg(pow) ); assert_eq!((&x).mod_power_of_2_sub(&x, pow), 0); }); unsigned_triple_gen_var_11::().test_properties(|(x, y, pow)| { assert_eq!( x.mod_power_of_2_sub(y, pow), Natural::from(x).mod_power_of_2_sub(Natural::from(y), pow) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModIsReduced, ModNeg, ModShl, ModShlAssign, ModShr}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::test_util::generators::{ signed_gen_var_5, unsigned_gen_var_5, unsigned_signed_unsigned_triple_gen_var_2, unsigned_triple_gen_var_18, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_signed_triple_gen_var_1, natural_natural_unsigned_triple_gen_var_6, natural_pair_gen_var_8, natural_signed_pair_gen_var_3, natural_unsigned_pair_gen_var_12, }; use std::ops::Shl; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_mod_shl_unsigned { ($t:ident) => { let test = |s, v: $t, t, out| { let u = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); let mut n = u.clone(); assert!(n.mod_is_reduced(&m)); n.mod_shl_assign(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_shl_assign(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shl(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shl(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shl(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shl(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!(((u << v) % m).to_string(), out); }; test("0", 0, "1", "0"); test("0", 0, "5", "0"); test("8", 2, "10", "2"); test("10", 100, "17", "7"); test("123456", 100, "12345678987654321", "7436663564915145"); }; } macro_rules! test_mod_shl_signed { ($t:ident) => { let test = |s, v: $t, t, out| { let u = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); let mut n = u.clone(); assert!(n.mod_is_reduced(&m)); n.mod_shl_assign(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_shl_assign(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shl(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shl(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shl(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shl(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!(((u << v) % m).to_string(), out); }; test("0", 0, "1", "0"); test("0", 0, "5", "0"); test("8", 2, "10", "2"); test("10", 100, "17", "7"); test("10", -100, "19", "0"); test("123456", 100, "12345678987654321", "7436663564915145"); }; } #[test] fn test_mod_shl() { apply_to_unsigneds!(test_mod_shl_unsigned); apply_to_signeds!(test_mod_shl_signed); } fn mod_shl_fail_helper() where for<'a> Natural: ModShlAssign + ModShlAssign + ModShl + ModShl, for<'a, 'b> &'a Natural: ModShl + ModShl, { assert_panic!(Natural::ZERO.mod_shl(T::exact_from(3u8), Natural::ZERO)); assert_panic!(Natural::exact_from(30).mod_shl(T::exact_from(3u8), Natural::ONE)); assert_panic!(Natural::ZERO.mod_shl(T::exact_from(3u8), &Natural::ZERO)); assert_panic!(Natural::exact_from(30).mod_shl(T::exact_from(3u8), &Natural::ONE)); assert_panic!((&Natural::ZERO).mod_shl(T::exact_from(3u8), Natural::ZERO)); assert_panic!((&Natural::exact_from(30)).mod_shl(T::exact_from(3u8), Natural::ONE)); assert_panic!((&Natural::ZERO).mod_shl(T::exact_from(3u8), &Natural::ZERO)); assert_panic!((&Natural::exact_from(30)).mod_shl(T::exact_from(3u8), &Natural::ONE)); assert_panic!({ let mut x = Natural::ZERO; x.mod_shl_assign(T::exact_from(3u8), Natural::ZERO); }); assert_panic!({ let mut x = Natural::exact_from(30); x.mod_shl_assign(T::exact_from(3u8), Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_shl_assign(T::exact_from(3u8), &Natural::ZERO); }); assert_panic!({ let mut x = Natural::exact_from(30); x.mod_shl_assign(T::exact_from(3u8), &Natural::ONE); }); } #[test] fn mod_shl_fail() { apply_fn_to_primitive_ints!(mod_shl_fail_helper); } #[allow(clippy::trait_duplication_in_bounds)] fn unsigned_properties() where for<'a> Natural: ModShlAssign + ModShlAssign + ModShl + ModShl, for<'a, 'b> &'a Natural: ModShl + ModShl + Shl, Limb: ModShl, { natural_natural_unsigned_triple_gen_var_6::().test_properties(|(n, m, u)| { assert!(n.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shl_assign(u, &m); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shl_assign(u, m.clone()); let shifted_alt = mut_n; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shl(u, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shl(u, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shl(u, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shl(u, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n << u) % &m, shifted); assert_eq!( (&n).mod_neg(&m).mod_shl(u, &m), n.mod_shl(u, &m).mod_neg(&m) ); }); natural_pair_gen_var_8().test_properties(|(n, m)| { assert_eq!((&n).mod_shl(T::ZERO, m), n); }); natural_unsigned_pair_gen_var_12::().test_properties(|(m, u)| { assert_eq!(Natural::ZERO.mod_shl(u, m), 0); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(Natural::ZERO.mod_shl(u, Natural::ONE), 0); }); unsigned_triple_gen_var_18::().test_properties(|(n, u, m)| { assert_eq!( Natural::from(n).mod_shl(u, Natural::from(m)), n.mod_shl(u, m) ); }); } #[allow(clippy::trait_duplication_in_bounds)] fn signed_properties, T: PrimitiveSigned + WrappingFrom>() where for<'a> Natural: ModShlAssign + ModShlAssign + ModShl + ModShl + ModShr, for<'a, 'b> &'a Natural: ModShl + ModShl + Shl, Limb: ModShl, { natural_natural_signed_triple_gen_var_1::().test_properties(|(n, m, i)| { assert!(n.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shl_assign(i, &m); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shl_assign(i, m.clone()); let shifted_alt = mut_n; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shl(i, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shl(i, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shl(i, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shl(i, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n << i) % &m, shifted); if i != T::MIN { assert_eq!(n.mod_shr(-i, m), shifted); } }); natural_pair_gen_var_8().test_properties(|(n, m)| { assert_eq!((&n).mod_shl(T::ZERO, m), n); }); natural_signed_pair_gen_var_3::().test_properties(|(m, i)| { assert_eq!(Natural::ZERO.mod_shl(i, m), 0); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(Natural::ZERO.mod_shl(i, Natural::ONE), 0); }); unsigned_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, m)| { assert_eq!( Natural::from(n).mod_shl(i, Natural::from(m)), n.mod_shl(i, m) ); }); } #[test] fn mod_shl_properties() { apply_fn_to_unsigneds!(unsigned_properties); apply_fn_to_unsigned_signed_pairs!(signed_properties); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Mod, ModShl}; use malachite_base::num::arithmetic::traits::{ModIsReduced, ModShr, ModShrAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::test_util::generators::{ signed_gen_var_5, unsigned_signed_unsigned_triple_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_signed_triple_gen_var_1, natural_pair_gen_var_8, natural_signed_pair_gen_var_3, }; use std::ops::Shr; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_mod_shr_signed { ($t:ident) => { let test = |s, v: $t, t, out| { let u = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); let mut n = u.clone(); assert!(n.mod_is_reduced(&m)); n.mod_shr_assign(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_shr_assign(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shr(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().mod_shr(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shr(v, m.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).mod_shr(v, &m); assert!(n.is_valid()); assert_eq!(n.to_string(), out); assert_eq!(((u >> v) % m).to_string(), out); }; test("0", 0, "1", "0"); test("0", 0, "5", "0"); test("8", -2, "10", "2"); test("10", -100, "17", "7"); test("10", 100, "19", "0"); test("123456", -100, "12345678987654321", "7436663564915145"); }; } #[test] fn test_mod_shr() { apply_to_signeds!(test_mod_shr_signed); } fn mod_shr_fail_helper() where for<'a> Natural: ModShrAssign + ModShrAssign + ModShr + ModShr, for<'a, 'b> &'a Natural: ModShr + ModShr, { assert_panic!(Natural::ZERO.mod_shr(T::exact_from(3u8), Natural::ZERO)); assert_panic!(Natural::exact_from(30).mod_shr(T::exact_from(3u8), Natural::ONE)); assert_panic!(Natural::ZERO.mod_shr(T::exact_from(3u8), &Natural::ZERO)); assert_panic!(Natural::exact_from(30).mod_shr(T::exact_from(3u8), &Natural::ONE)); assert_panic!((&Natural::ZERO).mod_shr(T::exact_from(3u8), Natural::ZERO)); assert_panic!((&Natural::exact_from(30)).mod_shr(T::exact_from(3u8), Natural::ONE)); assert_panic!((&Natural::ZERO).mod_shr(T::exact_from(3u8), &Natural::ZERO)); assert_panic!((&Natural::exact_from(30)).mod_shr(T::exact_from(3u8), &Natural::ONE)); assert_panic!({ let mut x = Natural::ZERO; x.mod_shr_assign(T::exact_from(3u8), Natural::ZERO); }); assert_panic!({ let mut x = Natural::exact_from(30); x.mod_shr_assign(T::exact_from(3u8), Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_shr_assign(T::exact_from(3u8), &Natural::ZERO); }); assert_panic!({ let mut x = Natural::exact_from(30); x.mod_shr_assign(T::exact_from(3u8), &Natural::ONE); }); } #[test] fn mod_shr_fail() { apply_fn_to_signeds!(mod_shr_fail_helper); } #[allow(clippy::trait_duplication_in_bounds)] fn properties_helper, T: PrimitiveSigned + WrappingFrom>() where for<'a> Natural: ModShrAssign + ModShrAssign + ModShr + ModShr + ModShl, for<'a, 'b> &'a Natural: ModShr + ModShr + Shr, Limb: ModShr, { natural_natural_signed_triple_gen_var_1::().test_properties(|(n, m, i)| { assert!(n.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shr_assign(i, &m); assert!(mut_n.is_valid()); let shifted = mut_n; assert!(shifted.mod_is_reduced(&m)); let mut mut_n = n.clone(); mut_n.mod_shr_assign(i, m.clone()); let shifted_alt = mut_n; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shr(i, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = (&n).mod_shr(i, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shr(i, &m); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone().mod_shr(i, m.clone()); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!((&n >> i).mod_op(&m), shifted); if i != T::MIN { assert_eq!(n.mod_shl(-i, m), shifted); } }); natural_pair_gen_var_8().test_properties(|(n, m)| { assert_eq!((&n).mod_shr(T::ZERO, m), n); }); natural_signed_pair_gen_var_3::().test_properties(|(m, i)| { assert_eq!(Natural::ZERO.mod_shr(i, m), 0); }); signed_gen_var_5::().test_properties(|i| { assert_eq!(Natural::ZERO.mod_shr(i, Natural::ONE), 0); }); unsigned_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, m)| { assert_eq!( Natural::from(n).mod_shr(i, Natural::from(m)), n.mod_shr(i, m) ); }); } #[test] fn mod_shr_properties() { apply_fn_to_unsigned_signed_pairs!(properties_helper); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ ModIsReduced, ModMul, ModNeg, ModSquare, ModSquareAssign, Square, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::unsigned_pair_gen_var_16; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen_var_2, natural_pair_gen_var_8, natural_triple_gen_var_3, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_square() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_square_assign(m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_square_assign(&m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_square(m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_square(m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_square(&m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_square(&m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "1", "0"); test("1", "10", "1"); test("2", "10", "4"); test("100", "497", "60"); test("200", "497", "240"); test("300", "497", "43"); test("1234567890", "123456789876", "100296296172"); } #[test] fn mod_square_fail() { assert_panic!(Natural::ZERO.mod_square(Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_square(Natural::ONE)); assert_panic!(Natural::ZERO.mod_square(&Natural::ZERO)); assert_panic!(Natural::from(30u32).mod_square(&Natural::ONE)); assert_panic!((&Natural::ZERO).mod_square(Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_square(Natural::ONE)); assert_panic!((&Natural::ZERO).mod_square(&Natural::ZERO)); assert_panic!((&Natural::from(30u32)).mod_square(&Natural::ONE)); assert_panic!({ let mut x = Natural::ZERO; x.mod_square_assign(Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_square_assign(Natural::ONE); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_square_assign(&Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u32); x.mod_square_assign(&Natural::ONE); }); } #[test] fn mod_square_properties() { natural_pair_gen_var_8().test_properties(|(x, m)| { assert!(x.mod_is_reduced(&m)); let square_val_val = x.clone().mod_square(m.clone()); let square_ref_val = (&x).mod_square(m.clone()); let square_val_ref = x.clone().mod_square(&m); let square = (&x).mod_square(&m); assert!(square_val_val.is_valid()); assert!(square_ref_val.is_valid()); assert!(square_val_ref.is_valid()); assert!(square.is_valid()); assert!(square.mod_is_reduced(&m)); assert_eq!(square_val_val, square); assert_eq!(square_ref_val, square); assert_eq!(square_val_ref, square); let mut mut_x = x.clone(); mut_x.mod_square_assign(m.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, square); let mut mut_x = x.clone(); mut_x.mod_square_assign(&m); assert!(mut_x.is_valid()); assert_eq!(mut_x, square); assert_eq!((&x).mod_mul(&x, &m), square); assert_eq!((&x).square() % &m, square); assert_eq!(x.mod_neg(&m).mod_square(&m), square); }); natural_gen_var_2().test_properties(|m| { assert_eq!(Natural::ZERO.mod_square(&m), 0); if m != 1 { assert_eq!(Natural::ONE.mod_square(m), 1); } }); natural_triple_gen_var_3().test_properties(|(x, y, m)| { assert_eq!( (&x).mod_mul(&y, &m).mod_square(&m), x.mod_square(&m).mod_mul(y.mod_square(&m), &m) ); }); unsigned_pair_gen_var_16::().test_properties(|(x, m)| { assert_eq!( x.mod_square(m), Natural::from(x).mod_square(Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mod_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Mod, ModAdd, ModIsReduced, ModNeg, ModSub, ModSubAssign, }; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::unsigned_triple_gen_var_12; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_pair_gen_var_8, natural_triple_gen_var_3}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_mod_sub() { let test = |r, s, t, out| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let m = Natural::from_str(t).unwrap(); assert!(u.mod_is_reduced(&m)); assert!(v.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_sub_assign(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert!(n.mod_is_reduced(&m)); let mut n = u.clone(); n.mod_sub_assign(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_sub_assign(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.mod_sub_assign(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_sub(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_sub(v.clone(), m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_sub(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_sub(&v, m.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_sub(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_sub(v.clone(), &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().mod_sub(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).mod_sub(&v, &m); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "1", "0"); test("0", "0", "32", "0"); test("0", "27", "32", "5"); test("10", "2", "16", "8"); test("2", "10", "16", "8"); test("0", "5", "128", "123"); test("123", "0", "128", "123"); test("123", "56", "512", "67"); test("56", "123", "512", "445"); test("7", "9", "10", "8"); } #[test] fn mod_sub_fail() { assert_panic!(Natural::ZERO.mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_sub(Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_sub(Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_sub(Natural::ZERO, &Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_sub(Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_sub(Natural::from(30u8), &Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_sub(&Natural::from(3u8), Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_sub(&Natural::from(30u8), Natural::from(30u8))); assert_panic!(Natural::ZERO.mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!(Natural::from(30u8).mod_sub(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!(Natural::from(3u8).mod_sub(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_sub(Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_sub(Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_sub(Natural::ZERO, &Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_sub(Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_sub(Natural::from(30u8), &Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_sub(&Natural::from(3u8), Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_sub(&Natural::from(30u8), Natural::from(30u8))); assert_panic!((&Natural::ZERO).mod_sub(Natural::ZERO, Natural::ZERO)); assert_panic!((&Natural::from(30u8)).mod_sub(&Natural::from(3u8), &Natural::from(30u8))); assert_panic!((&Natural::from(3u8)).mod_sub(&Natural::from(30u8), &Natural::from(30u8))); assert_panic!({ let mut x = Natural::ZERO; x.mod_sub_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_sub_assign(Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_sub_assign(Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_sub_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_sub_assign(Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_sub_assign(Natural::from(30u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_sub_assign(Natural::ZERO, Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_sub_assign(&Natural::from(3u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_sub_assign(&Natural::from(30u8), Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::ZERO; x.mod_sub_assign(Natural::ZERO, &Natural::ZERO); }); assert_panic!({ let mut x = Natural::from(30u8); x.mod_sub_assign(&Natural::from(3u8), &Natural::from(30u8)); }); assert_panic!({ let mut x = Natural::from(3u8); x.mod_sub_assign(&Natural::from(30u8), &Natural::from(30u8)); }); } #[test] fn mod_sub_properties() { natural_triple_gen_var_3().test_properties(|(x, y, m)| { assert!(x.mod_is_reduced(&m)); assert!(y.mod_is_reduced(&m)); let diff_val_val_val = x.clone().mod_sub(y.clone(), m.clone()); let diff_val_ref_val = x.clone().mod_sub(&y, m.clone()); let diff_ref_val_val = (&x).mod_sub(y.clone(), m.clone()); let diff_ref_ref_val = (&x).mod_sub(&y, m.clone()); let diff_val_val_ref = x.clone().mod_sub(y.clone(), &m); let diff_val_ref_ref = x.clone().mod_sub(&y, &m); let diff_ref_val_ref = (&x).mod_sub(y.clone(), &m); let diff = (&x).mod_sub(&y, &m); assert!(diff_val_val_val.is_valid()); assert!(diff_val_ref_val.is_valid()); assert!(diff_ref_val_val.is_valid()); assert!(diff_val_val_ref.is_valid()); assert!(diff_val_val_ref.is_valid()); assert!(diff_val_ref_ref.is_valid()); assert!(diff_ref_val_ref.is_valid()); assert!(diff.is_valid()); assert!(diff.mod_is_reduced(&m)); assert_eq!(diff_val_val_val, diff); assert_eq!(diff_val_ref_val, diff); assert_eq!(diff_ref_val_val, diff); assert_eq!(diff_ref_ref_val, diff); assert_eq!(diff_val_val_ref, diff); assert_eq!(diff_val_ref_ref, diff); assert_eq!(diff_ref_val_ref, diff); assert_eq!( (Integer::from(&x) - Integer::from(&y)).mod_op(Integer::from(&m)), diff ); let mut mut_x = x.clone(); mut_x.mod_sub_assign(y.clone(), m.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = x.clone(); mut_x.mod_sub_assign(&y, m.clone()); assert_eq!(mut_x, diff); assert!(mut_x.is_valid()); let mut mut_x = x.clone(); mut_x.mod_sub_assign(y.clone(), &m); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = x.clone(); mut_x.mod_sub_assign(&y, &m); assert_eq!(mut_x, diff); assert!(mut_x.is_valid()); assert_eq!((&y).mod_sub(&x, &m), (&diff).mod_neg(&m)); assert_eq!((&x).mod_add((&y).mod_neg(&m), &m), diff); assert_eq!((&diff).mod_add(&y, &m), x); assert_eq!(diff.mod_sub(x, &m), y.mod_neg(&m)); }); natural_pair_gen_var_8().test_properties(|(x, m)| { assert_eq!((&x).mod_sub(Natural::ZERO, &m), x); assert_eq!(Natural::ZERO.mod_sub(&x, &m), (&x).mod_neg(&m)); assert_eq!((&x).mod_sub(&x, m), 0); }); unsigned_triple_gen_var_12::().test_properties(|(x, y, m)| { assert_eq!( x.mod_sub(y, m), Natural::from(x).mod_sub(Natural::from(y), Natural::from(m)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedLogBase2, DivMod, PowerOf2, Square}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::common::rle_decode; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ large_type_gen_var_1, unsigned_pair_gen_var_27, unsigned_vec_gen_var_6, unsigned_vec_pair_gen_var_1, unsigned_vec_pair_gen_var_2, unsigned_vec_triple_gen_var_1, unsigned_vec_triple_gen_var_2, unsigned_vec_triple_gen_var_3, unsigned_vec_triple_gen_var_24, unsigned_vec_triple_gen_var_25, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_unsigned_triple_gen, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, }; use malachite_base::vecs::vec_from_str; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::mul::context::CONTEXT; use malachite_nz::natural::arithmetic::mul::limb::{ limbs_mul_limb, limbs_mul_limb_to_out, limbs_mul_limb_with_carry_to_out, limbs_slice_mul_limb_in_place, limbs_slice_mul_limb_with_carry_in_place, limbs_vec_mul_limb_in_place, }; use malachite_nz::natural::arithmetic::mul::mul_low::{ limbs_mul_low_same_length, limbs_mul_low_same_length_basecase, limbs_mul_low_same_length_basecase_alt, limbs_mul_low_same_length_divide_and_conquer, limbs_mul_low_same_length_divide_and_conquer_shared_scratch, }; #[cfg(not(feature = "32_bit_limbs"))] use malachite_nz::natural::arithmetic::mul::mul_mod::limbs_mul_mod_base_pow_n_minus_1; use malachite_nz::natural::arithmetic::mul::product_of_limbs::limbs_product; use malachite_nz::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_6h, limbs_mul_greater_to_out_toom_6h_scratch_len, limbs_mul_greater_to_out_toom_8h, limbs_mul_greater_to_out_toom_8h_scratch_len, limbs_mul_greater_to_out_toom_43, limbs_mul_greater_to_out_toom_43_scratch_len, limbs_mul_greater_to_out_toom_44, limbs_mul_greater_to_out_toom_44_scratch_len, limbs_mul_greater_to_out_toom_52, limbs_mul_greater_to_out_toom_52_scratch_len, limbs_mul_greater_to_out_toom_53, limbs_mul_greater_to_out_toom_53_scratch_len, limbs_mul_greater_to_out_toom_63, limbs_mul_greater_to_out_toom_63_scratch_len, }; #[cfg(feature = "32_bit_limbs")] use malachite_nz::natural::arithmetic::mul::toom::{ limbs_mul_greater_to_out_toom_22, limbs_mul_greater_to_out_toom_22_scratch_len, limbs_mul_greater_to_out_toom_32, limbs_mul_greater_to_out_toom_32_scratch_len, limbs_mul_greater_to_out_toom_33, limbs_mul_greater_to_out_toom_33_scratch_len, limbs_mul_greater_to_out_toom_42, limbs_mul_greater_to_out_toom_42_scratch_len, limbs_mul_greater_to_out_toom_54, limbs_mul_greater_to_out_toom_54_scratch_len, limbs_mul_greater_to_out_toom_62, limbs_mul_greater_to_out_toom_62_scratch_len, }; use malachite_nz::natural::arithmetic::mul::{ limbs_mul, limbs_mul_greater, limbs_mul_greater_to_out, limbs_mul_greater_to_out_basecase, limbs_mul_greater_to_out_scratch_len, limbs_mul_same_length_to_out, limbs_mul_same_length_to_out_scratch_len, limbs_mul_to_out, limbs_mul_to_out_scratch_len, }; use malachite_nz::platform::{DoubleLimb, Limb}; use malachite_nz::test_util::generators::{ natural_gen, natural_pair_gen, natural_triple_gen, natural_vec_gen, }; use malachite_nz::test_util::natural::arithmetic::mul::natural_product_naive; use malachite_nz::test_util::natural::arithmetic::mul::{initialize_context, mul_slow_fft}; use malachite_nz::test_util::natural::arithmetic::mul::{ limbs_mul_greater_to_out_basecase_mem_opt, limbs_product_naive, }; use num::BigUint; use rug; use std::iter::{Product, once}; use std::str::FromStr; fn series(start: Limb, len: usize) -> Vec { (start..start + Limb::exact_from(len)).collect() } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_limb_and_limbs_vec_mul_limb_in_place() { let test = |limbs: &[Limb], limb: Limb, out: &[Limb]| { assert_eq!(limbs_mul_limb(limbs, limb), out); let mut limbs = limbs.to_vec(); limbs_vec_mul_limb_in_place(&mut limbs, limb); assert_eq!(limbs, out); }; test(&[], 0, &[]); test(&[], 5, &[]); test(&[6, 7], 2, &[12, 14]); test(&[100, 101, 102], 10, &[1000, 1010, 1020]); test(&[123, 456], 789, &[97047, 359784]); test(&[u32::MAX, 5], 2, &[u32::MAX - 1, 11]); test(&[u32::MAX], 2, &[u32::MAX - 1, 1]); test(&[u32::MAX], u32::MAX, &[1, u32::MAX - 1]); } #[test] fn test_product() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let product = Natural::product(xs.iter().cloned()); assert!(product.is_valid()); assert_eq!(product.to_string(), out); let product_alt = Natural::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = natural_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }; test("[]", "1"); test("[10]", "10"); test("[6, 2]", "12"); test("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "0"); test("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", "3628800"); test( "[123456, 789012, 345678, 9012345]", "303462729062737285547520", ); } #[test] fn limbs_mul_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(xs, y)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_mul_limb(&xs, y)), Natural::from_limbs_asc(&xs) * Natural::from(y) ); }); } #[test] fn limbs_vec_mul_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_vec_mul_limb_in_place(&mut xs, y); let n = Natural::from_limbs_asc(&old_xs) * Natural::from(y); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_limb_with_carry_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry: Limb, carry_out: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!( limbs_mul_limb_with_carry_to_out::(&mut out, xs, y, carry), carry_out ); assert_eq!(out, out_after); }; test( &[10, 10, 10, 10], &[123, 456], 789, 10, 0, &[97057, 359784, 10, 10], ); test(&[10, 10, 10, 10], &[u32::MAX], 2, 3, 2, &[1, 10, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_limb_with_carry_to_out_fail() { limbs_mul_limb_with_carry_to_out::(&mut [10], &[10, 10], 10, 2); } #[test] fn limbs_mul_limb_with_carry_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_1().test_properties_with_config(&config, |(mut out, xs, y, carry)| { let old_out = out.clone(); let carry_out = limbs_mul_limb_with_carry_to_out::(&mut out, &xs, y, carry); let len = xs.len(); let n = Natural::from_owned_limbs_asc(xs) * Natural::from(y) + Natural::from(carry); let mut xs_out = n.into_limbs_asc(); assert_eq!(carry_out != 0, xs_out.len() == len + 1); if carry_out != 0 { assert_eq!(*xs_out.last().unwrap(), carry_out); } xs_out.resize(len, 0); assert_eq!(xs_out, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, carry: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!( limbs_mul_limb_to_out::(&mut out, xs, y), carry ); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[], 0, 0, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[], 5, 0, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, 0, &[12, 14, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, 0, &[1000, 1010, 1020, 10], ); test( &[10, 10, 10, 10], &[123, 456], 789, 0, &[97047, 359784, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, 5], 2, 0, &[u32::MAX - 1, 11, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX], 2, 1, &[u32::MAX - 1, 10, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX], u32::MAX, u32::MAX - 1, &[1, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_limb_to_out_fail() { limbs_mul_limb_to_out::(&mut [10], &[10, 10], 10); } #[test] fn limbs_mul_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let carry = limbs_mul_limb_to_out::(&mut out, &xs, y); let len = xs.len(); let n = Natural::from_owned_limbs_asc(xs) * Natural::from(y); let mut limbs = n.into_limbs_asc(); assert_eq!(carry != 0, limbs.len() == len + 1); if carry != 0 { assert_eq!(*limbs.last().unwrap(), carry); } limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_limb_with_carry_in_place() { let test = |xs_before: &[Limb], y: Limb, carry: Limb, carry_out: Limb, xs_after: &[Limb]| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_slice_mul_limb_with_carry_in_place(&mut xs, y, carry), carry_out ); assert_eq!(xs, xs_after); }; test(&[123, 456], 789, 10, 0, &[97057, 359784]); test(&[u32::MAX], 2, 3, 2, &[1]); } #[test] fn limbs_slice_mul_limb_with_carry_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen().test_properties_with_config( &config, |(mut xs, y, carry)| { let n = Natural::from_limbs_asc(&xs) * Natural::from(y) + Natural::from(carry); let carry_out = limbs_slice_mul_limb_with_carry_in_place(&mut xs, y, carry); let mut expected_limbs = n.into_limbs_asc(); assert_eq!(carry_out != 0, expected_limbs.len() == xs.len() + 1); if carry_out != 0 { assert_eq!(*expected_limbs.last().unwrap(), carry_out); } expected_limbs.resize(xs.len(), 0); assert_eq!(xs, expected_limbs); }, ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_mul_limb_in_place() { let test = |xs: &[Limb], y: Limb, carry: Limb, out: &[Limb]| { let mut xs = xs.to_vec(); assert_eq!(limbs_slice_mul_limb_in_place(&mut xs, y), carry); assert_eq!(xs, out); }; test(&[], 0, 0, &[]); test(&[], 5, 0, &[]); test(&[6, 7], 2, 0, &[12, 14]); test(&[100, 101, 102], 10, 0, &[1000, 1010, 1020]); test(&[123, 456], 789, 0, &[97047, 359784]); test(&[u32::MAX, 5], 2, 0, &[u32::MAX - 1, 11]); test(&[u32::MAX], 2, 1, &[u32::MAX - 1]); test(&[u32::MAX], u32::MAX, u32::MAX - 1, &[1]); } #[test] fn limbs_slice_mul_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); let carry = limbs_slice_mul_limb_in_place(&mut xs, y); let n = Natural::from_limbs_asc(&old_xs) * Natural::from(y); let mut expected_limbs = n.into_limbs_asc(); assert_eq!(carry != 0, expected_limbs.len() == xs.len() + 1); if carry != 0 { assert_eq!(*expected_limbs.last().unwrap(), carry); } expected_limbs.resize(xs.len(), 0); assert_eq!(xs, expected_limbs); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater() { let test = |xs: Vec, ys: Vec, result: Vec| { assert_eq!(limbs_mul_greater(&xs, &ys), result); }; test(vec![2], vec![3], vec![6, 0]); test(vec![1; 3], series(1, 3), vec![1, 3, 6, 5, 3, 0]); test(series(1, 3), vec![6, 7], vec![6, 19, 32, 21, 0]); test( vec![100, 101, 102], vec![102, 101, 100], vec![10200, 20402, 30605, 20402, 10200, 0], ); test(vec![u32::MAX], vec![1], vec![u32::MAX, 0]); test(vec![u32::MAX], vec![u32::MAX], vec![1, u32::MAX - 1]); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn test_limbs_mul_greater_fail_1() { limbs_mul_greater(&[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn test_limbs_mul_greater_fail_2() { limbs_mul_greater(&[6, 7], &[]); } fn limbs_mul_helper(f: &dyn Fn(&[Limb], &[Limb]) -> Vec, xs: Vec, ys: Vec) { let result = f(&xs, &ys); assert_eq!(result.len(), xs.len() + ys.len()); assert_eq!( Natural::from_owned_limbs_asc(result), Natural::from_owned_limbs_asc(xs) * Natural::from_owned_limbs_asc(ys) ); } #[test] fn limbs_mul_greater_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_1().test_properties_with_config(&config, |(xs, ys)| { limbs_mul_helper(&limbs_mul_greater, xs, ys); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul() { let test = |xs: Vec, ys: Vec, result: Vec| { assert_eq!(limbs_mul(&xs, &ys), result); }; test(vec![2], vec![3], vec![6, 0]); test(vec![1; 3], series(1, 3), vec![1, 3, 6, 5, 3, 0]); test(series(1, 3), vec![6, 7], vec![6, 19, 32, 21, 0]); test(vec![6, 7], series(1, 3), vec![6, 19, 32, 21, 0]); test( vec![100, 101, 102], vec![102, 101, 100], vec![10200, 20402, 30605, 20402, 10200, 0], ); test(vec![u32::MAX], vec![1], vec![u32::MAX, 0]); test(vec![u32::MAX], vec![u32::MAX], vec![1, u32::MAX - 1]); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn test_limbs_mul_fail() { limbs_mul(&[6, 7], &[]); } #[test] fn limbs_mul_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_2().test_properties_with_config(&config, |(xs, ys)| { limbs_mul_helper(&limbs_mul, xs, ys); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_same_length_to_out() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before; let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(&mut out, &xs, &ys, &mut mul_scratch); assert_eq!(out, out_after); }; test(vec![2], vec![3], vec![10; 3], vec![6, 0, 10]); test( vec![1; 3], series(1, 3), vec![5; 8], vec![1, 3, 6, 5, 3, 0, 5, 5], ); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], vec![10200, 20402, 30605, 20402, 10200, 0, 10], ); test(vec![u32::MAX], vec![1], vec![10; 3], vec![u32::MAX, 0, 10]); test( vec![u32::MAX], vec![u32::MAX], vec![10; 4], vec![1, u32::MAX - 1, 10, 10], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], vec![1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_same_length_to_out_fail_1() { let mut out = vec![10, 10, 10, 10, 10]; let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(3)]; limbs_mul_same_length_to_out(&mut out, &[6, 7], &[1, 2, 3], &mut mul_scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_same_length_to_out_fail_2() { let mut out = vec![10, 10, 10]; let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(2)]; limbs_mul_same_length_to_out(&mut out, &[6, 7], &[1, 2], &mut mul_scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_same_length_to_out_fail_3() { let mut out = vec![10]; let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(1)]; limbs_mul_same_length_to_out(&mut out, &[], &[], &mut mul_scratch); } #[test] fn limbs_mul_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_1().test_properties_with_config(&config, |(mut out, xs, ys)| { let old_out = out.clone(); let mut mul_scratch = vec![0; limbs_mul_same_length_to_out_scratch_len(xs.len())]; limbs_mul_same_length_to_out(&mut out, &xs, &ys, &mut mul_scratch); let len = xs.len() << 1; let n = Natural::from_owned_limbs_asc(xs) * Natural::from_owned_limbs_asc(ys); let mut expected_out = n.into_limbs_asc(); expected_out.resize(len, 0); assert_eq!(expected_out, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out() { let test = |xs: Vec, ys: Vec, out_before: Vec, highest_result_limb, out_after| { let mut out = out_before.clone(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs.len(), ys.len())]; assert_eq!( limbs_mul_greater_to_out(&mut out, &xs, &ys, &mut mul_scratch), highest_result_limb ); assert_eq!(out, out_after); }; test(vec![2], vec![3], vec![10; 3], 0, vec![6, 0, 10]); test( vec![1; 3], series(1, 3), vec![5; 8], 0, vec![1, 3, 6, 5, 3, 0, 5, 5], ); test( series(1, 3), vec![6, 7], vec![0; 5], 0, vec![6, 19, 32, 21, 0], ); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], 0, vec![10200, 20402, 30605, 20402, 10200, 0, 10], ); test( vec![u32::MAX], vec![1], vec![10; 3], 0, vec![u32::MAX, 0, 10], ); test( vec![u32::MAX], vec![u32::MAX], vec![10; 4], u32::MAX - 1, vec![1, u32::MAX - 1, 10, 10], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], u32::MAX, vec![1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out() { let test = |xs: Vec, ys: Vec, out_before: Vec, highest_result_limb, out_after: Vec| { let mut out = out_before.clone(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before; let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs.len(), ys.len())]; assert_eq!( limbs_mul_greater_to_out(&mut out, &xs, &ys, &mut mul_scratch), highest_result_limb ); assert_eq!(out, out_after); }; test( vec![ 12709525342598979476, 11509224300783138838, 393964466388471327, 14232928317295888119, 13732076968605655238, 15707747516397285107, 8732499155930007762, 9865419549041312495, 1072105962419307309, 17879862180104468293, 17068561868445402638, 1866096115219256579, 6855809432664356654, 1393588600207482081, 3815615263372249309, 4991042746319579278, 15465001638246553057, 16087255091514657862, 5044736888141764583, 2779747905405388451, 583627419881315049, 4335440233116895431, 9498366494409866085, 8645413868323766569, 10728932435460960803, 2150088858744686298, 9562258835198494013, 17827191588813955307, 13784645620229731318, 6296382068077415813, 11689157886369173742, 17754283123435968230, 1461090916898201642, 1288610558427232175, 8104103888086828127, 8032176301470720968, 12200951204181999648, 9485404571555436368, 10222400990562648891, 7599079551870785840, 11203522977648266038, 18338050175108207759, 12077517359207243953, 1611826255828631363, 15837930674386751191, 461582836356148934, 16860704548252932358, 6041830073720446893, 16833467135075592988, 17496069201595551026, 10318992522772404757, 13524041658187206186, 4506190253313254923, 17231310439197044711, 13546843641632582646, 7651927160556964586, 9190936365032409113, 9913829309881494193, 12083378901909297431, 287809474670991447, 7728504523588277111, 16741959317437359789, 9529628049862654500, 13419553383911388725, 13376506161484177119, 8176094358898406545, 13190641351956097350, 12568817836646213483, 3486855157615498387, 14702408831781542831, 98979558380456360, 13178740567667926424, 17968226918253726036, 9245411514261104062, 2907160002341084957, 1980943369383764848, 6564658997896463013, 13002525217264158147, 444335199954317567, 16863109666887451301, 11108312108618761726, 7630498129836691848, 5435171385264263429, 10900954800466810672, 16615568172072435554, 4587778094537619469, 10961411668824294491, 17076006711925106918, 5351453460500307468, 7629258051101663482, 16987233075558685907, 7043270533100406405, 1951394976862135309, 13689790855612457174, 2278410054587042806, 17001418508549255568, 11660613606297735566, 2855471124776808043, 10065175989746288214, 5055380914672426055, 14126789454240780537, 12269074817478677711, 15318371572624008687, 17454608042943339898, 266175370449515926, 10258065246409153340, 7913204199005555677, 2015162987422567864, 947599677954716876, 4742046749175767719, 4638837750457895566, 7651567606901939182, 1517253577417508168, 10046266355925262869, 17517100300192594127, 1840911236085514585, 17925925769498956584, 649534223875437606, 4629497761671206138, 6940070820665949971, 11499097596331562367, 6066662975772729994, 14012285030054181, 15069455665359536649, 15693110947967738351, 6137496527357766025, 17475548660925055392, 7927767715587303464, 8531250928287116369, 11631019584025111086, 14052618820385867457, 3118784937861555333, 183376537996253187, 5402208906954882112, 4415682544496910978, 4679985880085587510, 8446593383458511654, 15604884470214334395, 1138627504082666786, 10518517338133402469, 4864527599992532396, 13936709675277621349, 564858321719103528, 17954444276502582707, 7973580172007214272, 5448002835725952206, 17643582902922581336, 6555152033284063414, 10046934352485272915, 13709275446788968044, 3781650587286942277, 856963687705102140, 14231130335064067998, 12012182879109532509, 14408852620208381144, 18399276894609882283, 8786560043544514971, 9040897797784271497, 3289492106827693022, 2537349882995177, 9547621122715901978, 18031028021813298205, 13759002194232082515, 8230796682226694274, 16497307259652601605, 4532459299949788115, 9096244343722808065, 15835940740299471650, 16962714874349511272, 12751247365216834654, 5665483802634541323, 5932524403187765899, 9724384992325030819, 4567260165559481416, 12988617208150638305, 3810267272444218110, 12215376695703433417, 15917770368925117452, 10076439022504697381, 15419145301042845244, 12520526582226591499, 10731090420480517823, 7095369748974936538, 7265727720840614264, 14328612713128953576, 9796482770007505116, 12823579117053411854, 5055821064893108365, 12630218511428402185, 5189066330700437332, 5109762584664698804, 10723647767885063411, 15665488082047274789, 4569259999401990745, 3735809282876517401, 7285645596632892122, 10962161595160119179, 4816357354602339409, 10873333778222769846, 8013894684430460951, 1877066355845544058, 9184544411342906577, 1919785302854216344, 11743122258369849152, 3429022440866576828, 7006536176872515230, 12354403703503061654, 16589390678996741825, 8567087982659180500, 8236943971468579104, 14606686909208062275, 4461894282559697271, 2623848805529273446, 6820927267034378486, 14393599619569715182, 5199894747923716756, 206321364421131251, 4071363758717862161, 11965914866997389305, 8109905844769656284, 3492539957359367736, 16856371139562646083, 4333218987558602531, 16089995180748288161, 11191427142864224026, 2622884336931596940, 16105201810330583174, 11381683384063743452, 7873797126730706201, 11178731223505120377, 16800978016652635785, 13461685021093913844, 3055116765865974959, 3602813646007838280, 829147354810404950, 4780507430409308744, 18314860632940156926, 6995096023652594133, 5759566466885931830, 4840076000542784388, ], vec![ 15245088662193948010, 854969528224537163, 192457876290468361, 3156774054099849881, 10102117358735393641, 13923135497401538045, 15603007686998930972, 3707765480829539463, 1075990372015045994, 4440028045035707188, 779932550205535682, 13284596850012603887, 13447370325749987403, 10657005451799608034, 17344058779081327933, 1801131630646010099, 17879455113972297046, 1049662270419803525, 17887003202529550415, 13730724178286439296, 3086493866184691051, 7455503161286080904, 14945249663072669446, 7413071270018261565, 8165098975144402988, 15667870805615006559, 4534237642686726425, 5675059133984408369, 13542693529471369730, 4650690134857994243, 10593876026982724440, 8719234160809710444, 7340192483727047710, 2225660849988538666, 3260628781823840386, 14784063213821786553, 13478324037708856111, 6239844587086244103, 14508626048519473050, 11443816492520902359, 7084448144752764341, 11673478635762496725, 13444020463604694513, 1798574113181758005, 15195278749704748030, 3490272214933312037, 15632500462832370824, 9808665338648603851, 6377980234800091876, 11306384233660763805, 6392788317448223882, 8005181869701567455, 4601526777105113530, 9348184476999479133, 16105441815997897842, 15373735633778437011, 11733794529384137433, 769246272107807645, 2922899274256775805, 16218486247871807873, 10650657974127272786, 579665301817927565, 6403006378940431337, 10150254532952843560, 3736822004545760197, 10244207440138560761, 16631379436671010056, 17418302422321190629, 4844439457855539440, 9662799133272397874, 11622100630061039998, 11017257064923257696, 14025546287952884200, 1170766120552674008, 4852413824670160293, 18019298735978800767, 14042374992041286164, 6103187929964524269, 5988592592688695870, 5579172720281387479, 10738878044274955012, 8401646271610146442, 12016061916593958227, 14752402557741497038, 5053283107906893264, 12910662726197463795, 787526459034857809, 10304827788120361107, 8387521101013404665, 6030209567663971422, 7511028869236306454, 11105170944119024313, 2911699195421772292, 11710398806568443147, 7599646386487625804, 2146501359265516686, 1193294087739295886, 16419769173966961854, 14779980297792837632, 6286361066120350249, 8246126699673376536, 2339493649448723726, 12383521129608538925, 17459816050942292574, 7213741082075285427, 14702683527305456088, 17849030573001874153, 3273901152373442943, 10086273715179643444, 14351251935054659627, 3067622597087477151, 4241957707372911307, 16686513037697490920, 1503886102490162470, 4222986769290077389, 17209928444872897872, 10064374817012298812, 1391022681726221923, 3482099619102309134, 151151415131464647, 5477310851692317777, 8185741896741403527, 12297179519749775078, 6980896315258250234, 5491311995173541969, 10908311176531272611, 15140263006374103771, 16292302828281485620, 13488663273854028028, 17078235461511918753, 523009743565281503, 11105648925812514991, 13827146014280242829, ], vec![10; 373], 3627981030815073084, vec![ 10242139703917377352, 6869501223013262871, 3374240433299030218, 2448664517749959925, 12614665088252879609, 15275142410865499832, 7415514779145416012, 4634939093621563784, 14236482271744498259, 16987935748141823121, 9662195261206294164, 8327530275898959224, 17948858401312480900, 16590992031072707948, 8981557837131782478, 17292811815398261598, 10343772151713015660, 16403800522193054061, 11001578312297934300, 9055563331722809276, 6861684031441187837, 6179379396114830115, 15119399843907730738, 2747263417069121706, 12218921993633141137, 15314449116975726182, 2870623933631129133, 8433855307245599470, 9663369547205952712, 16656478013118492468, 5014296474163082063, 15045852603430413673, 9039056709562337243, 1775730247666171519, 10284009922885822735, 17264560580274867574, 8659184543116501827, 9757501208876960807, 8107556209186377816, 13981920571894003246, 8697727621393221097, 10111281749746035823, 11547580803378751509, 9866091897888262831, 6932444770006022090, 12886358055723945255, 5304800874292271788, 11523612872653318479, 3158091624397075356, 17376725070179056084, 11353224313201827872, 17568378701446022201, 7083677611886335059, 16630882804589833859, 17071293908015663903, 3335332823966517520, 4551571010812166323, 13956655949392024934, 11137278406051829526, 4896962372622758702, 11813643533502615793, 4581901117239147425, 14593775693535083700, 1510447605784811068, 5229627540215802358, 627282762635294446, 4791499629805752429, 10361188936025453248, 4774699819640096953, 13333081235316911046, 10942108924892665866, 16109048665458409419, 15314689190690266823, 7310144211471143550, 16609282512397289062, 4726986969285156208, 8190850143304789515, 1542721709305293842, 12747051062417360628, 10431119479932549840, 5201202511017795553, 7741819653940246707, 2687570019862487900, 6488374897263692453, 13582359095544274953, 14484022084752061384, 5515018660843652873, 8092760845580227599, 2766454334996797883, 18180569531864904251, 3565091373050863067, 12322298177624181037, 11958316134617603606, 9878952926876342598, 5302556749713428981, 8825508234500799831, 11910303768250068310, 326451074713852933, 396115137030276241, 12871099826433440706, 4304686608856751519, 13291683117058685204, 9284558513918029302, 3718112862893900571, 9149607979222078382, 16527849990011073270, 7727656976171348203, 6573616922619656711, 16034045732340296623, 5589930567903701070, 10683802387965352692, 2587318764516570107, 10209376077208389402, 17079775160514374021, 6530000943687323192, 3718180221149684880, 18189517521112254114, 5384059937475335410, 609609335008271023, 3896142000481106293, 16658219747219000806, 13778288993082074923, 5582595801212065024, 14131451705219445462, 359265879248692883, 16936956071544174710, 15873091614777053247, 2434660658463974075, 2592075329848798604, 14194422636533088807, 7167203043317150959, 11315395284250045497, 2099964792961604585, 1566230315841355073, 16092624371341405050, 11961408413498591004, 16535764519833385727, 16358286323170046012, 460344037919559599, 14169011134767857411, 14106023301858944314, 9862229088119368783, 3357504073133417614, 1102923706048286862, 13563108311952119833, 2143046275198271992, 3979966820061122245, 9996599392497104038, 18113381312649782606, 2789577810558634539, 2505893204182156006, 5459782976231228406, 14606983256382437526, 17289593816561860577, 18339393907946617355, 2258995667690444422, 8894197183418385086, 18341894792090069275, 11391274557331577482, 1810514891585419128, 7148289154353071487, 2119113819713138874, 10271861970912805029, 7676899172550981679, 8624446484952065684, 5656835932522160843, 16121420157925734770, 14082469678115799904, 10255722969024722343, 1662291548355896945, 6389399781869176377, 12541949260215847692, 7144384677827477175, 7282727395448468407, 12150328138548453752, 3472826938551266818, 3748717285404782518, 4780951876470252398, 16824789631565337027, 15839657600800222362, 10490421032004326835, 13577644447718918237, 6631866657761640573, 981988710472148081, 2178386723930299579, 4509700998976576445, 7085230111532242363, 15742412314382227975, 1728841640197493179, 9413625884895979097, 17011657766150783108, 7453240289129863943, 14356227040755802558, 8727877790598607374, 6442754498625288772, 7392839418676330133, 14897473376443001590, 6366239299333724836, 9325048183999746407, 3440007856498006275, 15045549040986890155, 14490217742673747202, 15278519326741232153, 6554990600736077400, 14130125167723787542, 13808426692316226071, 5353065033486249758, 1150929840748552011, 12174365818942611676, 8325746398590604908, 1113711086245528668, 10314080011282631969, 8859099728742225981, 17921003815641223868, 3105591894080053316, 15297241643811159913, 17457505649562044023, 2057745826478669102, 4884750341838598362, 16356083315993976675, 9101726946186468401, 14354106624548323412, 9370983965070459320, 7738440263290367492, 8917029115165607445, 2195272365194297011, 9558528105439905340, 8030625988101552152, 3397298078799745318, 9736711397155048940, 2460615496131263256, 15140262761582421804, 6475970420636983572, 15248938774827950731, 3601954052709238929, 3331181884995306372, 5102925218725345470, 3667800919502192980, 3004240798812901640, 5533280375618915829, 5107586811468410440, 10224278806003351694, 6476631719990351159, 2003572440276248817, 12145591924789065893, 12519472837420433198, 17782311381537397376, 5661681639850380779, 10364042884708771431, 1695509166589750758, 14618040013233272293, 13897753646384009557, 3750141258844328560, 2521464661853413252, 6278261092787958914, 10406656955141036872, 3275028812461691395, 12925016960899871398, 9841323801652199824, 6731798363764447936, 16237427233498849184, 18347750732935739357, 13607917507344538804, 7384152260726915035, 5463321849210106032, 16371815515677214027, 8832632406517327899, 8268519393788774229, 3669915584804849690, 1269556794163966064, 17809810670965530193, 15840056410475484689, 4076484974516366053, 9606036112446697020, 4868364087195523723, 2058736710151928793, 10897356652781847288, 465078533977740804, 16624721881706870960, 11964802914009109220, 16816447700891974174, 3690088264896558634, 7147174284749790878, 9145833698882950169, 8784425020769374260, 1861407397398056953, 12834090279159906525, 7662444631348458158, 14132542110004422269, 9328868421834468934, 16741858393921937122, 15694875428320019398, 14994603044491181705, 9746169230120941506, 7938113624909327958, 13340368850853929072, 7651461065837541114, 4476063835934825867, 8693815106327834329, 4988903731011095573, 4462304735549234904, 8428813472483033040, 4788353502021621362, 12565779699104064716, 3068625859269266553, 2676497072041684077, 6224517250248606913, 10155182336700912649, 4789285195609433162, 16223567669480014548, 7428311545244653529, 16614898660347133660, 18158662267123053326, 3623664384860961629, 7652479537264294496, 8606705184150939035, 8275137754514789786, 1964775551555279291, 1438900651657172959, 17673106577623030111, 6973507447558830112, 15423010115647882749, 3472057791767023426, 5848284772473138216, 2890665771216618892, 9314934874321984084, 8734072522843080836, 14327114341827253389, 4434569283869444664, 12983438456823218137, 10233784466676928341, 16291964559077701283, 9678367439362828938, 7822571001351685129, 15858728294074423230, 10852593355325202465, 12352889154252904310, 12472638922147628465, 858263613939813395, 12316650043304516782, 15905737765854758582, 5901848627660760442, 8757164316447879955, 1327307879496998670, 16419197412056777506, 11241454192064071141, 5669708276938693043, 3575232442870910395, 17428985550073658716, 15774059386607531181, 16583828728361725400, 2690073375909258220, 3913838352065921651, 11930346452395449553, 7508883471181453189, 1979183109855731075, 17205167019849574415, 6202127415457809639, 15616037631795263171, 13758692529633453573, 4703023550466089121, 6440538290327762255, 4617056828336967974, 1016260815990065725, 10542530738319933236, 13839074645977905740, 6298401080101494064, 18179185785092266771, 808757022663954675, 655320984483308172, 6492165610369841580, 10622849106810507658, 3627981030815073084, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_fail_1() { let mut out = vec![10; 4]; let xs = series(6, 3); limbs_mul_greater_to_out_basecase(&mut out, &xs, &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_fail_2() { let mut out = vec![10; 5]; let ys = series(1, 3); limbs_mul_greater_to_out_basecase(&mut out, &[6, 7], &ys); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_fail_3() { let mut out = vec![10; 3]; limbs_mul_greater_to_out_basecase(&mut out, &[6, 7], &[]); } fn limbs_mul_basecase_helper(out: &[Limb], xs: &[Limb], ys: &[Limb]) -> Vec { let mut out = out.to_vec(); let old_out = out.clone(); limbs_mul_greater_to_out_basecase(&mut out, xs, ys); let n = Natural::from_limbs_asc(xs) * Natural::from_limbs_asc(ys); let len = xs.len() + ys.len(); let mut limbs = n.into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); out } #[test] fn limbs_mul_greater_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 1024); config.insert("mean_stripe_n", 512 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_2().test_properties_with_config(&config, |(mut out, xs, ys)| { let old_out = out.clone(); let expected_out = limbs_mul_basecase_helper(&out, &xs, &ys); let mut mul_scratch = vec![0; limbs_mul_greater_to_out_scratch_len(xs.len(), ys.len())]; let highest_result_limb = limbs_mul_greater_to_out(&mut out, &xs, &ys, &mut mul_scratch); assert_eq!(highest_result_limb, out[xs.len() + ys.len() - 1]); let out_len = xs.len() + ys.len(); assert_eq!(&out[..out_len], &expected_out[..out_len]); let mut out = old_out; limbs_mul_greater_to_out_basecase_mem_opt(&mut out, &xs, &ys); assert_eq!(out, expected_out); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_to_out() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs.len(), ys.len())]; limbs_mul_to_out(&mut out, &xs, &ys, &mut mul_scratch); assert_eq!(out, out_after); }; test(vec![2], vec![3], vec![10; 3], vec![6, 0, 10]); test( vec![1; 3], series(1, 3), vec![5; 8], vec![1, 3, 6, 5, 3, 0, 5, 5], ); test(series(1, 3), vec![6, 7], vec![0; 5], vec![6, 19, 32, 21, 0]); test(vec![6, 7], series(1, 3), vec![0; 5], vec![6, 19, 32, 21, 0]); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], vec![10200, 20402, 30605, 20402, 10200, 0, 10], ); test(vec![u32::MAX], vec![1], vec![10; 3], vec![u32::MAX, 0, 10]); test( vec![u32::MAX], vec![u32::MAX], vec![10; 4], vec![1, u32::MAX - 1, 10, 10], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], vec![1, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_to_out_fail_1() { let mut out = vec![10, 10, 10]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(2, 2)]; limbs_mul_to_out(&mut out, &[6, 7], &[1, 2], &mut mul_scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_to_out_fail_2() { let mut out = vec![10, 10, 10, 10]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(1, 3)]; limbs_mul_to_out(&mut out, &[], &[1, 2, 3], &mut mul_scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_to_out_fail_3() { let mut out = vec![10, 10, 10, 10]; let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(1, 1)]; limbs_mul_to_out(&mut out, &[1, 2, 3], &[], &mut mul_scratch); } #[test] fn limbs_mul_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_3().test_properties_with_config(&config, |(mut out, xs, ys)| { let old_out = out.clone(); let mut mul_scratch = vec![0; limbs_mul_to_out_scratch_len(xs.len(), ys.len())]; let highest_result_limb = limbs_mul_to_out(&mut out, &xs, &ys, &mut mul_scratch); assert_eq!(highest_result_limb, out[xs.len() + ys.len() - 1]); let len = xs.len() + ys.len(); let n = Natural::from_owned_limbs_asc(xs) * Natural::from_owned_limbs_asc(ys); let mut limbs = n.into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_22() { let test = |xs: &[Limb], ys: &[Limb], out_before: &[Limb], out_after: &[Limb]| { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_22_scratch_len(xs.len(), ys.len())]; let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, xs, ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); limbs_mul_greater_to_out_toom_22(&mut out, xs, ys, &mut scratch); assert_eq!(out, out_after); }; // - s != n // - !(xs0[s] == 0 && limbs_cmp_same_length(&xs0[..s], xs1) == Less) // - t != n // - slice_test_zero(&ys0[t..]) && limbs_cmp_same_length(&ys0[..t], ys1) != Less // - s <= t // - !v_neg_1_neg // - carry <= 2 test( &series(2, 3), &series(3, 3), &[10; 6], &[6, 17, 34, 31, 20, 0], ); // - xs0[s] == 0 && limbs_cmp_same_length(&xs0[..s], xs1) == Less // - v_neg_1_neg test( &[2, 0, 4], &[3, 4, 5], &[10, 10, 10, 10, 10, 10], &[6, 8, 22, 16, 20, 0], ); test(&[1; 3], &series(1, 3), &[5; 8], &[1, 3, 6, 5, 3, 0, 5, 5]); // - s == n // - limbs_cmp_same_length(ys0, ys1) != Less // - t == n // - limbs_cmp_same_length(ys0, ys1) == Less test(&[1; 4], &series(1, 4), &[5; 8], &[1, 3, 6, 10, 9, 7, 4, 0]); // - limbs_cmp_same_length(&a0[..n], &a1[..n]) == Less // - limbs_cmp_same_length(&b0[..n], &b1[..n]) != Less test(&series(1, 4), &[1; 4], &[5; 8], &[1, 3, 6, 10, 9, 7, 4, 0]); // - slice_test_zero(&ys0[t..]) && limbs_cmp_same_length(&ys0[..t], ys1) == Less test( &series(1, 5), &[1, 0, 0, 4], &[5; 9], &[1, 2, 3, 8, 13, 12, 16, 20, 0], ); // - s > t test(&[1; 4], &series(1, 3), &[5; 8], &[1, 3, 6, 6, 5, 3, 0, 5]); test( &[100, 101, 102], &[102, 101, 100], &[10; 7], &[10200, 20402, 30605, 20402, 10200, 0, 10], ); let xs = rle_decode(&[(u32::MAX, 8), (4294950911, 1), (u32::MAX, 21), (536870911, 1), (0, 25)]); let ys = rle_decode(&[(u32::MAX, 2), (4294963199, 1), (u32::MAX, 18), (268435455, 1), (0, 34)]); let out_len = xs.len() + ys.len(); // - carry > 2 test( &xs, &ys, &vec![10; out_len], &rle_decode(&[ (1, 1), (0, 1), (4096, 1), (0, 5), (16384, 1), (0, 1), (67108864, 1), (0, 10), (4026531840, 1), (u32::MAX, 8), (3758095359, 1), (u32::MAX, 2), (4294966783, 1), (u32::MAX, 18), (33554431, 1), (0, 59), ]), ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_1() { let mut scratch = vec![]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_22(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_2() { let mut scratch = vec![]; let mut out = vec![10; 7]; let xs = series(6, 3); let ys = series(1, 4); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_3() { let mut scratch = vec![]; let mut out = vec![10; 7]; let xs = series(6, 4); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &[1, 2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_4() { let mut scratch = vec![]; let mut out = vec![10; 7]; let xs = series(6, 3); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &[1, 2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_5() { let mut scratch = vec![]; let mut out = vec![10; 4]; let xs = series(6, 3); let ys = series(1, 3); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_6() { let mut scratch = vec![]; let mut out = vec![10; 4]; let xs = series(6, 3); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_22_fail_7() { let mut scratch = vec![]; let mut out = vec![10; 4]; let xs = series(6, 3); let ys = series(1, 4); limbs_mul_greater_to_out_toom_22(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_32() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - !(ap1hi == 0 && limbs_cmp_same_length(ap1, xs1) == Less) // - t == n // - limbs_cmp_same_length(ys0, ys1) == Less // - ap1hi != 1 and ap1hi != 2 // - !bp1hi // - hi == 0 first time // - v_neg_1_neg // - s <= t // - s + t > n // - hi >= 0 second time test( series(2, 6), series(3, 4), vec![10; 10], vec![6, 17, 34, 58, 76, 94, 88, 71, 42, 0], ); // - limbs_cmp_same_length(ys0, ys1) != Less // - ap1hi == 2 // - bp1hi // - !v_neg_1_neg test( vec![u32::MAX; 6], vec![u32::MAX; 4], vec![10; 10], vec![1, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX], ); // - ap1hi == 0 && limbs_cmp_same_length(ap1, xs1) == Less test( vec![0, 0, 1, 1, 0, 1], vec![0, 0, 0, 1], vec![10; 10], vec![0, 0, 0, 0, 0, 1, 1, 0, 1, 0], ); // - t != n // - slice_test_zero(&ys0[t..]) && limbs_cmp_same_length(&ys0[..t], ys1) == Less // - s + t <= n test( vec![0, 0, 0, 0, 0, 0, 1], vec![0, 0, 0, 0, 1], vec![10; 12], vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], ); // - !(slice_test_zero(&ys0[t..]) && limbs_cmp_same_length(&ys0[..t], ys1) == Less) test( vec![0, 0, 0, 0, 0, 0, 1], vec![0, 0, 1, 0, 1], vec![10; 12], vec![0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], ); // - s > t test( series(1, 9), vec![9, 8, 7, 6, 5], vec![10; 14], vec![9, 26, 50, 80, 115, 150, 185, 220, 255, 200, 146, 94, 45, 0], ); // - ap1hi == 1 test( vec![2543705880, 1859419010, 3343322808, 1165039137, 1872701663, 1957510151, 1589243046], vec![1919189400, 1295801997, 354566481, 1212146910, 1886225431], vec![10; 14], vec![ 1753714240, 1114397484, 4100081063, 2352383720, 667557204, 920036609, 2291920497, 3338154324, 3806846000, 1880963052, 291601955, 697949587, 10, 10, ], ); // - hi != 0 first time test( vec![706760835, 4153647095, 3843998199, 2077172825, 1158686949, 3157624247], vec![2847735618, 2779635711, 2471732382, 2655639495], vec![10; 10], vec![ 2814066374, 2022835469, 2101335047, 312674723, 2952296274, 1055977952, 590716674, 290888444, 3944399226, 1952404077, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_32(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(3, 4)]; let mut out = vec![10; 7]; let xs = series(6, 3); let ys = series(1, 4); limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(5, 4)]; let mut out = vec![10; 9]; let xs = series(6, 5); let ys = series(1, 4); limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(6, 3)]; let mut out = vec![10; 9]; let xs = series(6, 6); let ys = series(1, 3); limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(3, 0)]; let mut out = vec![10; 4]; let xs = series(6, 3); limbs_mul_greater_to_out_toom_32(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_32_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_32_scratch_len(6, 4)]; let mut out = vec![10; 9]; let xs = series(6, 6); let ys = series(1, 4); limbs_mul_greater_to_out_toom_32(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_33() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - carry == 0 && limbs_cmp_same_length(&gp[..n], xs_1) == Less // - s != n // - carry == 0 && limbs_cmp_same_length(&gp[..n], ys_1) == Less // - t != n // - s <= t // - !v_neg_1 // - two_r <= k + 1 test( series(2, 5), series(3, 5), vec![10; 10], vec![6, 17, 34, 58, 90, 94, 88, 71, 42, 0], ); // - s > t test( series(2, 6), series(3, 5), vec![10; 11], vec![6, 17, 34, 58, 90, 115, 116, 106, 84, 49, 0], ); // - v_neg_1 // - two_r > k + 1 test( series(2, 9), series(3, 8), vec![10; 17], vec![6, 17, 34, 58, 90, 131, 182, 244, 296, 315, 320, 310, 284, 241, 180, 100, 0], ); test( series(3, 5), series(2, 5), vec![10; 10], vec![6, 17, 34, 58, 90, 94, 88, 71, 42, 0], ); // - !(carry == 0 && limbs_cmp_same_length(&gp[..n], xs_1) == Less) // - !(carry == 0 && limbs_cmp_same_length(&gp[..n], ys_1) == Less) test( vec![u32::MAX; 5], vec![u32::MAX; 5], vec![10; 10], vec![1, 0, 0, 0, 0, u32::MAX - 1, u32::MAX, u32::MAX, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_33_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_33(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_33_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(5, 5)]; let mut out = vec![10; 11]; let xs = series(6, 5); let ys = series(1, 6); limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_33_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(5, 5)]; let mut out = vec![10; 9]; let xs = series(6, 5); let ys = series(1, 4); limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_33_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(5, 5)]; let mut out = vec![10; 5]; let xs = series(6, 5); limbs_mul_greater_to_out_toom_33(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_33_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_33_scratch_len(6, 6)]; let mut out = vec![10; 9]; let xs = series(6, 6); let ys = series(1, 5); limbs_mul_greater_to_out_toom_33(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_42() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_42(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - v_neg_1_neg // - t == n // - limbs_cmp_same_length(ys_0, ys_1) == Less // - s <= t // - as1[n] not 1, 2, or 3 test( series(2, 4), vec![3, 4], vec![10; 7], vec![6, 17, 24, 31, 20, 0, 10], ); // - !v_neg_1_neg // - s != n // - t != n // - !(slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less) test( series(2, 7), series(3, 3), vec![10; 10], vec![6, 17, 34, 46, 58, 70, 82, 67, 40, 0], ); // - s > t test( series(2, 8), series(3, 3), vec![10; 11], vec![6, 17, 34, 46, 58, 70, 82, 94, 76, 45, 0], ); // - limbs_cmp_same_length(ys_0, ys_1) != Less test( vec![0, 0, 0, 1], vec![1, 1], vec![10; 6], vec![0, 0, 0, 1, 1, 0], ); // - as1[n] == 1 test( vec![ 2363703565, 2011430902, 405935879, 3293866119, 79230945, 4067912411, 54522599, 3863530924, 2648195217, 3696638907, 2693775185, 2466180916, 2288038816, 3085875921, 2622914893, 3412444602, 1714899352, 1458044565, 4160795266, ], vec![ 2010684769, 395852000, 1475286147, 263729287, 1827966398, 926833006, 3647866695, 2299638628, ], vec![10; 27], vec![ 2935529197, 2628679470, 2989406385, 4135607148, 3098618197, 1986483787, 2969118597, 4064944337, 1353361316, 3300804798, 3539475248, 1813351909, 4189109323, 1508204245, 3032195050, 2111172804, 2647234523, 763063403, 499753337, 484003129, 951290762, 31889895, 4291170933, 743974460, 931456782, 3403938046, 2227799389, ], ); // - bs1[n] != 0 test( vec![ 1023706198, 1055957821, 62637438, 3129002448, 1343635842, 1979891039, 2332614953, 820715064, 126240740, 3763174513, 874511155, 1433571832, 1799667271, 828081508, 1790140791, 3456862168, 182082249, ], vec![ 272565221, 2271318511, 3915555663, 752672586, 2086228575, 93709012, 4089106295, 1296382745, 4014782836, 4084383484, ], vec![10; 27], vec![ 2478924526, 600853546, 3764116188, 869876026, 49911338, 2430145334, 1531060628, 4131353567, 2147110402, 1698823317, 3610138028, 2221603642, 2262453949, 2700908655, 2085097953, 1179421079, 2314185794, 3274969801, 956808943, 183640877, 769743340, 2499732116, 168215214, 1611459466, 1659741921, 3303732250, 173154690, ], ); // - as1[n] == 2 test( vec![ 0xfffff, 0, 0, 4294965248, 0x1ffffff, 0, 0, 0, 4294966784, u32::MAX, u32::MAX, u32::MAX, 0, 0x80000000, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], vec![u32::MAX, u32::MAX, u32::MAX, 2047, 0, 0, 4294705152, u32::MAX], vec![10; 27], vec![ 4293918721, u32::MAX, u32::MAX, 0x7fffffff, 4261412864, u32::MAX, 4291035135, 4294967231, 1049102, 0x20000000, 0, 4293914624, 0x1fffffe, 0x80000000, 0x8000000, 2048, 4294966784, 4294966271, 4294705151, u32::MAX - 1, 0x20000, 0x80000000, 2047, 0, 0, 4294705152, u32::MAX, ], ); // - asm1[n] != 0 test( vec![3338024033, 1570788701, 4067509056, 680440343], vec![599772085, 925834366], vec![10; 6], vec![1056633749, 686831275, 2758938475, 3727232403, 1859912609, 146677497], ); // - as1[n] == 3 test( vec![4030415682, 3643742328, 2586387240, 3719633661], vec![708497006, 797041707], vec![10; 6], vec![4203348572, 3202027474, 4170951291, 2012723103, 3609216593, 690273745], ); // - slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less test( vec![ 0, u32::MAX, u32::MAX, 0xfffff, 0xfffffff0, u32::MAX, 63, 0, 0x80000000, u32::MAX, u32::MAX, ], vec![0xffff, 0, 0, 4294967264], vec![10; 15], vec![ 0, 4294901761, u32::MAX, 4293918719, 4293918783, u32::MAX - 1, 4265607103, 1049087, 0x7ffffff0, 4294932480, 63, 0xffff, 2147483664, u32::MAX, 4294967263, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_42_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_42(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_42_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(5, 6)]; let mut out = vec![10; 11]; let xs = series(6, 5); let ys = series(1, 6); limbs_mul_greater_to_out_toom_42(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_42_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(3, 2)]; let mut out = vec![10; 9]; let xs = series(6, 3); limbs_mul_greater_to_out_toom_42(&mut out, &xs, &[1, 2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_42_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(5, 0)]; let mut out = vec![10; 5]; let xs = series(6, 5); limbs_mul_greater_to_out_toom_42(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_42_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_42_scratch_len(4, 2)]; let mut out = vec![10; 4]; let xs = series(6, 4); limbs_mul_greater_to_out_toom_42(&mut out, &xs, &[1, 2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_43() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - n_high < n in limbs_mul_toom_evaluate_deg_3poly_in_2and_neg_2 // - !v_neg_2neg in limbs_mul_toom_evaluate_deg_3poly_in_2and_neg_2 // - limbs_cmp_same_length(small_scratch, bsm1) != Less // - s <= t // - !v_neg_2neg in limbs_mul_toom_interpolate_6points // - !v_neg_1_neg in limbs_mul_toom_interpolate_6points // - n_high > n in limbs_mul_toom_interpolate_6points // - special_carry_1 <= special_carry_2 test( series(2, 11), series(3, 9), vec![10; 20], vec![ 6, 17, 34, 58, 90, 131, 182, 244, 318, 381, 444, 468, 476, 467, 440, 394, 328, 241, 132, 0, ], ); // - n_high >= n in limbs_mul_toom_evaluate_deg_3poly_in_2and_neg_2 // - v_neg_2neg in limbs_mul_toom_evaluate_deg_3poly_in_2and_neg_2 // - t != n // - limbs_cmp_same_length(small_scratch, bsm1) == Less // - *bsm1last == 0 && limbs_cmp_same_length(bsm1init, ys_1) == Less // - s > t test( series(2, 12), series(3, 8), vec![10; 20], vec![ 6, 17, 34, 58, 90, 131, 182, 244, 296, 348, 400, 452, 462, 455, 430, 386, 322, 237, 130, 0, ], ); // - v_neg_2neg in limbs_mul_toom_interpolate_6points // - v_neg_1_neg in limbs_mul_toom_interpolate_6points // - n_high <= n in limbs_mul_toom_interpolate_6points test( series(2, 19), series(3, 11), vec![10; 30], vec![ 6, 17, 34, 58, 90, 131, 182, 244, 318, 405, 506, 594, 682, 770, 858, 946, 1034, 1122, 1210, 1235, 1236, 1212, 1162, 1085, 980, 846, 682, 487, 260, 0, ], ); // - special_carry_1 > special_carry_2 test( vec![ 3785023459, 4249117725, 1551102690, 4239134101, 2264608302, 1455009194, 3261002629, 2233313730, 3807192178, 2550029068, 1259253479, 2657422450, ], vec![ 2921127090, 3493254221, 1579329255, 2624469567, 1678656523, 1653055771, 493445097, 1702866165, 1046762910, ], vec![10; 21], vec![ 3169501142, 3910307595, 310092603, 1408815552, 1786334527, 2452212521, 670758829, 4142968613, 1110881016, 3529286248, 2119180760, 3066268191, 1902231557, 1262478906, 4083142666, 784312035, 3990199726, 3180402195, 1845375516, 421486236, 647662966, ], ); test( vec![ 0, 0, 0, 4286578688, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 7, 0, 0, 0, 0, 0xfffffff0, u32::MAX, u32::MAX, u32::MAX, ], vec![ 0x7fffffff, 0xfffff000, 0x1fffff, 0, 0, 0, 2147483520, 0, 0xfffffff0, u32::MAX, u32::MAX, 4290789375, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], vec![10; 35], vec![ 0, 0, 0, 0x800000, 4290772992, 7, 0xfffff000, u32::MAX, u32::MAX, 0x3fffffff, 4290772984, 134184963, 0x1000000, 0, 0, 8176, 64504, 4261412868, 4294967167, 2139095038, 0xfffff000, 4263643135, 0xfffffff7, 255, 0, 2147483520, 66846728, 0xfffffff0, u32::MAX, u32::MAX, 4290789375, 4294967279, u32::MAX, u32::MAX, u32::MAX, ], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_43() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test( vec![ 18446744073701163071, u64::MAX, u64::MAX, 0xfffffffff, 0, 0, 0, 0, 18446743936270598144, u64::MAX, u64::MAX, u64::MAX, 0x3ffff, 0, 0, 0, 0xffff000000000000, 0x7fff, 0, 0, 18446744073709518848, u64::MAX, u64::MAX, u64::MAX, u64::MAX, ], vec![ 18437736874454810624, 0xfffff, 0, 18446744039349813248, u64::MAX, u64::MAX, u64::MAX, 0x7fffffffffff, 0, 0xfffffffffffffff0, u64::MAX, u64::MAX, 0x7ffffff, 18446744056529682432, u64::MAX, u64::MAX, ], vec![10; 41], vec![ 17879290520660869120, 18446735277682593791, u64::MAX, 288228211488194559, 72057594004373504, 0, 0, 8866461766385536, 18446744073709551552, 18302628885835021327, u64::MAX, 0x7ffff, 18445617082746798336, 144114380622004095, 0, 9214364837600034816, 18446744073700114495, 2336462208959, 34359738336, 0x1000000000, 18445618173803233282, 18446744039345618958, 127, 0x4000000000000, 4611721063213039616, 18437736874454810624, 0x7ffff, 13835058055282163712, 18446744039350075391, 4398047033343, 18446181123756392448, u64::MAX, 18446598938174685183, 562949953454079, 0xfffffffffffffff0, u64::MAX, 18446744073709518847, 0x7ffffff, 18446744056529682432, u64::MAX, u64::MAX, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_43_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_43(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_43_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(11, 12)]; let mut out = vec![10; 23]; let xs = series(3, 11); let ys = series(2, 12); limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_43_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(11, 8)]; let mut out = vec![10; 19]; let xs = series(3, 11); let ys = series(2, 8); limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_43_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(12, 0)]; let mut out = vec![10; 12]; let xs = series(3, 11); limbs_mul_greater_to_out_toom_43(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_43_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_43_scratch_len(4, 2)]; let mut out = vec![10; 5]; let xs = series(3, 10); let ys = series(2, 10); limbs_mul_greater_to_out_toom_43(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_44() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - limbs_mul_toom_evaluate_deg_3poly_in_2and_neg_2(bpx, bmx, ys, n, t, &mut scratch[..n + 1]) // - limbs_mul_toom_evaluate_deg_3poly_in_1and_neg_1(bpx, bmx, ys, n, t, &mut scratch[..n + 1]) // - s <= t // - !w1_neg // - !w3neg // - w6n <= n + 1 // - limbs_mul_greater_to_out_basecase in limbs_mul_same_length_to_out_toom_44recursive test( series(2, 4), series(3, 4), vec![10; 8], vec![6, 17, 34, 58, 58, 49, 30, 0], ); // - w3neg test( vec![0, 0, 0, 1], vec![0, 0, 1, 1], vec![10; 8], vec![0, 0, 0, 0, 0, 1, 1, 0], ); // - w6n > n + 1 test( vec![ 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, ], vec![ 2700212626, 3890522506, 1407330442, 2072012244, 292784856, 2848511017, 2011019434, 3729188240, 1314875514, 1752114201, 3480385261, 1532349465, ], vec![10; 24], vec![ 301610262, 3665600695, 2790869988, 562719619, 254881625, 3646308155, 2857045174, 4219173388, 3417896791, 458617279, 3882403287, 617740409, 3296542840, 435168928, 3570119313, 863483077, 2646855475, 2878510649, 4228994627, 2357119023, 2589237669, 2274199643, 3000367783, 688838692, ], ); // - s > t test( vec![ 1588217107, 79108222, 2883552792, 2390312777, 1587172303, 2070384343, 2265280181, 4013380367, ], vec![3177381025, 2776698917, 954518943, 3785176644, 3521195169, 550485155, 1499535299], vec![10; 15], vec![ 2639930611, 1074195093, 3974952249, 2825437951, 3084912647, 2589723741, 1008656003, 3022162475, 2305314017, 1619919364, 894905935, 3957960884, 814161571, 756465381, 1401222667, ], ); // - w1_neg test( vec![ 1047248630, 339306853, 1100911694, 3907715577, 4281628442, 1447091409, 3425204321, 3871347591, 339462242, 1765234031, 3774533011, 980706746, ], vec![ 1454868694, 1975460471, 2212752551, 1982786615, 983847073, 3073742136, 438698610, 1215648998, 2824467771, 3299124311, 2818671068, ], vec![10; 23], vec![ 2438877604, 4249888081, 2301349363, 1817920534, 2538709343, 1739256708, 179543633, 2275519806, 1688820820, 759475921, 3927834077, 2138533648, 958932069, 2429920287, 3858014276, 2853106604, 1837491388, 1616377262, 231659922, 680814190, 417532392, 428918230, 643611358, ], ); test( vec![986333060, 254638637, 1577120658, 1458096412, 474582958, 4115735719, 4031007047], vec![2096725444, 3871299248, 1414038108, 2617834141, 1553210626, 2669030715, 3093885541], vec![10; 14], vec![ 2067797264, 3922708625, 2600678884, 825822853, 2499590824, 1035492325, 1957325707, 1890833276, 3433274404, 1510974136, 2269171082, 854613327, 1796482159, 2903741417, ], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_44() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test( series(2, 4), series(3, 4), vec![10; 8], vec![6, 17, 34, 58, 58, 49, 30, 0], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_44_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(1, 1)]; let mut out = vec![10; 10]; limbs_mul_greater_to_out_toom_44(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_44_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(4, 4)]; let mut out = vec![10; 9]; let xs = series(3, 4); let ys = series(2, 5); limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_44_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(3, 3)]; let mut out = vec![10; 6]; let xs = series(3, 3); let ys = series(2, 3); limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_44_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(11, 11)]; let mut out = vec![10; 11]; let xs = series(3, 11); limbs_mul_greater_to_out_toom_44(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_44_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_44_scratch_len(4, 4)]; let mut out = vec![10; 7]; let xs = series(3, 4); let ys = series(2, 4); limbs_mul_greater_to_out_toom_44(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_52() { let test = |xs: &[Limb], ys: &[Limb], out_before: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, xs, ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_52(&mut out, xs, ys, &mut scratch); assert_eq!(out, out_after); }; // - degree.even() in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - !v_neg_2neg in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - t != n // - !(slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less) // - !v_neg_1_neg // - !(slice_test_zero(&bsm1[t..]) && limbs_cmp_same_length(&bsm1[..t], ys_1) == Less) // - degree.even() in limbs_mul_toom_evaluate_poly_in_1and_neg_1 // - !v_neg_1_neg in limbs_mul_toom_evaluate_poly_in_1and_neg_1 test( &series(2, 15), &series(3, 5), &[10; 20], &[ 6, 17, 34, 58, 90, 115, 140, 165, 190, 215, 240, 265, 290, 315, 340, 314, 268, 201, 112, 0, ], ); test( &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 1, 0], &[10; 20], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], ); // - n_high != n in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - t == n // - limbs_cmp_same_length(ys_0, ys_1) == Less // - v_neg_1_neg test( &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1], &[10; 20], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], ); // - slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less test( &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 1], &[10; 20], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], ); // - limbs_cmp_same_length(ys_0, ys_1) != Less // - limbs_cmp_same_length(bsm1, ys_1) == Less test( &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 1, 0, 0, 1], &[10; 20], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0], ); // - v_neg_2neg in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - v_neg_1_neg in limbs_mul_toom_evaluate_poly_in_1and_neg_1 // - limbs_mul_toom_evaluate_poly_in_1and_neg_1(as1, asm1, 4, xs, n, s, &mut v_neg_1[..m]) test( &[ 281500646, 1572406350, 108746052, 4056047843, 89307364, 1006007374, 2902260577, 1250995384, 1556873818, 3846421711, 280743259, 1728158805, 467926284, 2330565417, ], &[2509320863, 2201587434, 926371577, 1243694325, 1112023631, 2791032478], &[10; 20], &[ 1191903194, 1277561191, 2672986331, 45667421, 2742410814, 2602170945, 2815699572, 2317624023, 952805243, 577394769, 1002744907, 4175910221, 2433548489, 2550394831, 3650814344, 1121996596, 3441179979, 3561879910, 1574546788, 1514489709, ], ); // - limbs_cmp_same_length(bsm1, ys_1) != Less test( &[ 2331447040, 1003213663, 1873981685, 3371337621, 3796896013, 4144448610, 2569252563, 2859304641, 1027973602, 3158196152, 4058699545, 2002924383, 3295505824, 695758308, ], &[725028139, 2984864771, 2939417227, 3047223286, 3526157986, 1078000342], &[10; 20], &[ 474121472, 1561322164, 715684992, 3182777436, 384530074, 3827205870, 2267366778, 1586160630, 3779201468, 900553139, 2867049131, 2027414411, 2054056558, 2671776484, 3374007062, 3091178442, 1888125000, 2974781424, 307612679, 174629431, ], ); // - slice_test_zero(&bsm1[t..]) && limbs_cmp_same_length(&bsm1[..t], ys_1) == Less test( &rle_decode(&[ (32767, 1), (0, 5), (4294836224, 1), (u32::MAX, 5), (4278206463, 1), (u32::MAX, 2), (31, 1), (0, 2), (4294443008, 1), (u32::MAX, 7), ]), &[0, 0, u32::MAX, u32::MAX, u32::MAX, 0, 0, 4294967232, u32::MAX, 4227858559, u32::MAX], &[10; 37], &[ 0, 0, 4294934529, u32::MAX, u32::MAX, 0x7ffe, 0, 4292870208, 0x1ffff, 71303040, 4294966784, 4294868990, u32::MAX, 0x7fffff, 16760832, 0xff000000, 2047, 4278075360, u32::MAX, 1072693247, 524320, 2149580800, 259839, 4277682176, 2147487743, 0x1ffffff, 32, 4227858432, 8190, 4294443008, u32::MAX, 0, 0, 4294967232, u32::MAX, 4227858559, u32::MAX, ], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_52() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_52(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test( vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], vec![0, 0, 0, 0, 1, 0], vec![10; 20], vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_52_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_52(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_52_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(15, 16)]; let mut out = vec![10; 9]; let xs = series(3, 15); let ys = series(3, 16); limbs_mul_greater_to_out_toom_52(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_52_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(14, 5)]; let mut out = vec![10; 6]; let xs = series(3, 14); let ys = series(3, 5); limbs_mul_greater_to_out_toom_52(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_52_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(15, 4)]; let mut out = vec![10; 7]; let xs = series(3, 15); let ys = series(3, 4); limbs_mul_greater_to_out_toom_52(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_52_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_52_scratch_len(11, 0)]; let mut out = vec![10; 12]; let xs = series(3, 11); limbs_mul_greater_to_out_toom_52(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_53() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - !(*bs1last == 0 && limbs_cmp_same_length(bs1init, ys_1) == Less) // - limbs_cmp_same_length(bs2, &out[..n + 1]) != Less // - *asm1last != 1 && *asm1last != 2 // - *as1last == 0 test( series(2, 5), series(3, 3), vec![10; 8], vec![6, 17, 34, 46, 58, 49, 30, 0], ); // - *bs1last == 0 && limbs_cmp_same_length(bs1init, ys_1) == Less // - *as1last == 2 // - *bs1last == 1 test( vec![611094747, 2426195984, 3948451542, 3575143460, 2163084716], vec![1043494367, 2432724646, 1148376235], vec![10; 8], vec![ 2911651269, 2135822080, 566305911, 1285474929, 3971527858, 1120629777, 2330897846, 578359487, ], ); // - *as1last == 1 test( vec![83336617, 52963853, 1461131367, 615175494, 2376138249], vec![1085015601, 823246134, 3222784883], vec![10; 8], vec![ 4003668825, 3129188105, 1975732797, 2019047981, 943873016, 1483316813, 305883771, 1782966412, ], ); // - limbs_cmp_same_length(bs2, &out[..n + 1]) == Less // - *as1last > 2 test( vec![ 3853679659, 4236745288, 2469732913, 4265854402, 4207372271, 1754370134, 137881047, 1325109821, 2212043812, 3074170203, ], vec![1666773246, 4177391250, 4175984066, 2859904653, 3320165100, 314964734], vec![10; 16], vec![ 2336719530, 919351696, 4142757378, 49781824, 1315087108, 2534950116, 2674417418, 1178559126, 171926136, 3132896187, 2074730624, 3561766617, 1155879861, 3985534229, 380101898, 225439482, ], ); // - *asm1last == 1 test( vec![4171807709, 1363035595, 2692148345, 3728232161, 2672522097], vec![178202067, 736149219, 623937260], vec![10; 8], vec![ 2793195559, 2168235304, 1582195836, 18437203, 671570200, 635034059, 2378259056, 388241865, ], ); // - *bs1last == 2 test( vec![361692441, 3665267779, 1770324312, 1221560416, 2810295690], vec![1887715703, 4035171395, 2815003797], vec![10; 8], vec![ 3298754463, 2516900264, 30373680, 909364693, 729609199, 3973437903, 3392713387, 1841921601, ], ); // - *bsm1last != 0 test( vec![1542637461, 595638956, 1883922642, 2681579369, 2641006916], vec![3723002977, 116606811, 2193352864], vec![10; 8], vec![ 2246996853, 3232877055, 2347711939, 2476049074, 4132376421, 3855440382, 4040315714, 1348708775, ], ); // - *asm1last == 2 test( vec![4043423637, 312331403, 3088235367, 41162462, 2934893364], vec![2702987034, 4184574368, 2455116868], vec![10; 8], vec![ 2912448546, 2297161059, 137328692, 115875329, 1975003140, 2441893159, 4034859213, 1677662647, ], ); test( vec![0x3ffff8, 3221225472, u32::MAX, 1, 4294934528], vec![0, 4294959104, u32::MAX], vec![10; 8], vec![0, 0x10000, 0xfffffff8, 4196343, 3221209088, 0xfffffff, 4294959106, 4294934527], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_53() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test( vec![u64::MAX, u64::MAX, 3, u64::MAX - 1, u64::MAX], vec![u64::MAX, u64::MAX, u64::MAX], vec![10; 8], vec![1, 0, 0xfffffffffffffffc, 0, 0, 3, u64::MAX - 1, u64::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_53(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(5, 6)]; let mut out = vec![10; 11]; let xs = series(3, 5); let ys = series(3, 6); limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(5, 4)]; let mut out = vec![10; 9]; let xs = series(3, 5); let ys = series(3, 4); limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(4, 3)]; let mut out = vec![10; 6]; let xs = series(3, 4); let ys = series(3, 3); limbs_mul_greater_to_out_toom_53(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(5, 2)]; let mut out = vec![10; 7]; let xs = series(3, 5); limbs_mul_greater_to_out_toom_53(&mut out, &xs, &[3, 4], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_53_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_53_scratch_len(5, 0)]; let mut out = vec![10; 12]; let xs = series(3, 5); limbs_mul_greater_to_out_toom_53(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_54() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_54(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - degree.even() in limbs_mul_toom_evaluate_poly_in_2pow_and_neg_2pow // - !v_neg_2pow_neg in limbs_mul_toom_evaluate_poly_in_2pow_and_neg_2pow // - degree.odd() in limbs_mul_toom_evaluate_poly_in_2pow_and_neg_2pow // - !y_sign in limbs_toom_couple_handling // - y_shift != 0 in limbs_toom_couple_handling // - x_shift != 0 in limbs_toom_couple_handling // - s > t // - carry_1 && !carry_2, first time, in limbs_mul_toom_interpolate_8points // - carry_1 && !carry_2, second time, in limbs_mul_toom_interpolate_8points // - s_plus_t != n in limbs_mul_toom_interpolate_8points test( series(2, 15), series(3, 11), vec![10; 26], vec![ 6, 17, 34, 58, 90, 131, 182, 244, 318, 405, 506, 594, 682, 770, 858, 895, 912, 908, 882, 833, 760, 662, 538, 387, 208, 0, ], ); // - v_neg_2pow_neg in limbs_mul_toom_evaluate_poly_in_2pow_and_neg_2pow // - y_sign in limbs_toom_couple_handling // - s <= t test( vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], vec![10; 26], vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], ); // - !carry_1 && carry_2, first time, in limbs_mul_toom_interpolate_8points test( vec![ 281500646, 1572406350, 108746052, 4056047843, 89307364, 1006007374, 2902260577, 1250995384, 1556873818, 3846421711, 280743259, 1728158805, 467926284, 2330565417, ], vec![ 1365578038, 3224231142, 4103857906, 475734936, 3828952167, 3071966456, 1450111251, 1166414077, 2218130537, 3324650407, 1559641024, 2423373264, ], vec![10; 26], vec![ 3471157380, 2179990259, 735116018, 3928626279, 2606792426, 4065628313, 3326106964, 1358767242, 58836620, 2388814047, 1881937395, 448453590, 699295041, 2539838591, 1014080982, 2627397171, 1231543630, 2956184941, 1108982880, 2083442227, 1445361702, 3773463966, 3902311612, 4169089467, 614631841, 1314987876, ], ); // - s_plus_t == n in limbs_mul_toom_interpolate_8points test( vec![ 1372428912, 2999825770, 3824933735, 1252466299, 1644332514, 577056155, 267504800, 2188417248, 1146838357, 1601878440, 2555350187, 2326995902, 341200833, 3311243465, 3983323172, 1591023018, 498264278, 879686658, 2445286712, 3168806215, 3363960673, 1002293448, ], vec![ 4155394173, 3251572031, 3012777338, 1405107169, 4263655764, 202386116, 2762119705, 1046271690, 3730474184, 1761497041, 3530189728, 452831577, 2351117985, 3074633806, 2337874996, 2372535352, 1907593160, 2034262144, ], vec![10; 40], vec![ 3438536880, 4020840252, 3753658662, 2750457729, 3984463794, 1677702279, 3627178035, 1938289829, 2347934241, 1059164524, 3077109858, 1455283397, 4245424824, 2265496611, 2507273589, 4106853892, 187386657, 3541881161, 3520589236, 977961476, 205850208, 3040196950, 1303835716, 3039701923, 525989195, 1042461957, 4189151284, 3358396344, 275215531, 2907721257, 3086020483, 2914223316, 652103889, 2430562590, 4256409533, 774831877, 3808631269, 3720895601, 1034939105, 474724830, ], ); // - !carry_1 && carry_2, second time, in limbs_mul_toom_interpolate_8points test( vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfffffff0, u32::MAX, u32::MAX, u32::MAX], vec![ 2047, 0, 0, 4294966784, u32::MAX, 127, 0, 4286578688, u32::MAX, 0x3ffff, 4227858432, u32::MAX, ], vec![10; 26], vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294934544, u32::MAX, u32::MAX, 8191, 2047, 4294965248, u32::MAX, 134217215, 0, 4290773120, 0x3fffffff, 4286578688, 4294967279, 0x3ffff, 4227858432, u32::MAX, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_54(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(15, 16)]; let mut out = vec![10; 31]; let xs = series(3, 14); let ys = series(3, 17); limbs_mul_greater_to_out_toom_54(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(15, 10)]; let mut out = vec![10; 25]; let xs = series(3, 14); let ys = series(3, 10); limbs_mul_greater_to_out_toom_54(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(14, 11)]; let mut out = vec![10; 25]; let xs = series(3, 14); let ys = series(3, 11); limbs_mul_greater_to_out_toom_54(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(15, 11)]; let mut out = vec![10; 25]; let xs = series(3, 15); let ys = series(3, 11); limbs_mul_greater_to_out_toom_54(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_54_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_54_scratch_len(15, 0)]; let mut out = vec![10; 15]; let xs = series(3, 15); limbs_mul_greater_to_out_toom_54(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_62() { let test = |xs: &[Limb], ys: &[Limb], out_before: &[Limb], out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, xs, ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_62(&mut out, xs, ys, &mut scratch); assert_eq!(out, out_after); }; // - degree.odd() in limbs_mul_toom_evaluate_poly_in_1and_neg_1 // - degree > 4 in limbs_mul_toom_evaluate_poly_in_1and_neg_1 // - degree_u >= 5 in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - degree.odd() in limbs_mul_toom_evaluate_poly_in_2and_neg_2 // - t == n // - limbs_cmp_same_length(ys_0, ys_1) == Less // - v_neg_1_neg_b // - *as1last == 0 test( &series(2, 6), &[3, 4], &[10; 8], &[6, 17, 24, 31, 38, 45, 28, 0], ); // - limbs_cmp_same_length(ys_0, ys_1) != Less // - !v_neg_1_neg_b // - t >= n // - limbs_cmp_same_length(&bsm1, ys_1) == Less test( &[0, 0, 0, 0, 0, 1], &[1, 1], &[10; 8], &[0, 0, 0, 0, 0, 1, 1, 0], ); // - limbs_cmp_same_length(&bsm1, ys_1) != Less test( &[0, 0, 0, 0, 0, 1], &[2, 1], &[10; 8], &[0, 0, 0, 0, 0, 2, 1, 0], ); // - t != n // - !(slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less) // - t < n // - !(slice_test_zero(&bsm1[t..]) && limbs_cmp_same_length(&bsm1[..t], ys_1) == Less) // - *as1last == 2 test( &[ 2291585918, 1380546066, 1861205162, 1395600128, 1509813785, 1715266614, 3251195596, 3140058077, 1998653517, 3140019184, 2534426976, ], &[2477133296, 625749873, 3687467688], &[10; 14], &[ 869772320, 253774892, 3270059412, 1629301906, 333315526, 1485838973, 1182872659, 3973435471, 3570040059, 138616924, 3845622124, 4243476600, 2488800838, 2175946157, ], ); // - *as1last > 2 test( &[706760835, 4153647095, 3843998199, 2077172825, 1158686949, 3157624247], &[708497006, 797041707], &[10; 8], &[ 3596223050, 1899342498, 3768933007, 59388593, 2997914214, 150267535, 1848145862, 585978436, ], ); // - *as1last == 1 test( &[ 1817453168, 96871997, 3927306877, 3090061646, 3474317652, 437148773, 439538568, 324686794, 772632617, 1424328970, 580538580, ], &[4158498322, 3126677346, 655989538], &[10; 14], &[ 4142861280, 2093741387, 1223409636, 3430701278, 154561385, 1065478559, 1434432315, 1709306376, 2647162930, 2288715437, 510829208, 3519993529, 1581992297, 88668250, ], ); // - *bs1last != 0 test( &[478149678, 4026802122, 1384639138, 368837837, 183900171, 785221208], &[1458158767, 4167624669], &[10; 8], &[ 1921854322, 141249793, 673006993, 2183916852, 295623924, 3471440317, 3387755993, 761939975, ], ); // - *asm1last == 1 test( &[760464004, 3698115579, 1282981837, 2124133062, 1943175022, 3815903204], &[2302225798, 423133196], &[10; 8], &[ 1718420760, 4288660832, 1043184986, 2518603664, 1668853787, 1047988481, 4101944437, 375936580, ], ); // - *asm1last == 2 test( &[ 486320673, 3488920730, 3556919186, 380261964, 1609664786, 3382076763, 3478178414, 1464325754, 2543330707, 3900552438, 1432199477, ], &[1190326122, 1081384689, 2610845505, 3919894794], &[10; 15], &[ 3164946602, 4284198222, 380177155, 837655879, 3034889727, 3503063664, 3315274214, 3998279880, 2501466635, 3524441, 312561544, 2480833439, 3092764257, 1045878247, 1307127829, ], ); // - slice_test_zero(&ys_0[t..]) && limbs_cmp_same_length(&ys_0[..t], ys_1) == Less test( &rle_decode(&[(u32::MAX, 17), (31, 1), (0, 5), (4294967232, 1), (u32::MAX, 12)]), &[u32::MAX, 63, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX], &[10; 47], &[ 1, 4294967232, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 0x3ffffff, 0, 0, 0, 0, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, u32::MAX, 4294967263, 2047, 0, 0, 0, 0, 2147483712, 4294963199, u32::MAX, u32::MAX, u32::MAX, 31, 0, 1, 0, 0, 0, 4294967232, u32::MAX, u32::MAX - 1, 63, 0, 0, 0, 0, 4227858432, u32::MAX, u32::MAX, u32::MAX, u32::MAX, ], ); // - slice_test_zero(&bsm1[t..]) && limbs_cmp_same_length(&bsm1[..t], ys_1) == Less test( &rle_decode(&[(1073741823, 1), (0, 7), (4290772992, 1), (u32::MAX, 8)]), &[0xfff00000, u32::MAX, 0, 0xffffff8, 4294443008], &[10; 22], &[ 0x100000, 4294705152, 0x3ffffffe, 4026531848, 67633149, 1073610751, 0, 0, 0, 1024, 4290772992, 0x1ffffff, 4294705152, 4290773503, u32::MAX, u32::MAX, u32::MAX, 4293918719, u32::MAX, 0, 0xffffff8, 4294443008, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_62(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(6, 7)]; let mut out = vec![10; 13]; let xs = series(3, 6); let ys = series(3, 7); limbs_mul_greater_to_out_toom_62(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(6, 1)]; let mut out = vec![10; 7]; let xs = series(3, 6); limbs_mul_greater_to_out_toom_62(&mut out, &xs, &[3], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(5, 2)]; let mut out = vec![10; 7]; let xs = series(3, 5); limbs_mul_greater_to_out_toom_62(&mut out, &xs, &[3, 4], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(6, 2)]; let mut out = vec![10; 7]; let xs = series(3, 6); limbs_mul_greater_to_out_toom_62(&mut out, &xs, &[3, 4], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_62_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_62_scratch_len(6, 0)]; let mut out = vec![10; 6]; let xs = series(3, 6); limbs_mul_greater_to_out_toom_62(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_63() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - n == t // - !(!carry && limbs_cmp_same_length(scratch2lo, ys_1) == Less) // - s <= t test( series(2, 17), series(3, 9), vec![10; 26], vec![ 6, 17, 34, 58, 90, 131, 182, 244, 318, 381, 444, 507, 570, 633, 696, 759, 822, 828, 812, 773, 710, 622, 508, 367, 198, 0, ], ); // - n != t test( vec![ 3047748962, 2284186344, 3132866461, 2331447040, 1003213663, 1873981685, 3371337621, 3796896013, 4144448610, 2569252563, 2859304641, 1027973602, 3158196152, 4058699545, 2002924383, 3295505824, 695758308, 544681384, 3452307839, 1190734708, 4232023153, 451772934, 673919865, 2022672425, 3493426012, 1142609332, 477542383, 1304798841, 461115870, 3268103575, 2243523508, ], vec![ 3987208830, 1336657961, 2605546090, 1112778759, 2243645577, 3695113963, 637209276, 527642657, 1586863943, 2178788843, 4128924923, 574016400, 118333022, 3019059425, 3734056582, 3974475640, 958936732, ], vec![10; 48], vec![ 901282364, 4131825926, 550521101, 4239081984, 354957348, 2987335611, 2947836402, 1594339509, 1900787939, 3942224706, 1915750189, 2686147736, 455238733, 595779993, 992449470, 225135268, 4216025815, 112446550, 2736130746, 1015352940, 1166343395, 3559470539, 2787138552, 3128535813, 2203140859, 3479459112, 599923700, 684443693, 1557326194, 1699057519, 2198150417, 2196463130, 1973109458, 3642841764, 426750624, 1438683694, 42406461, 1444651840, 2152704621, 722727455, 3882030279, 205951250, 838845869, 2997862064, 779154540, 1753953589, 1791445120, 500911172, ], ); test( vec![ 2547108010, 2828666778, 3252702258, 3885923576, 2331974758, 730724707, 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, 3428792463, 2896462048, 2985885576, 1819460734, 21206096, 3560441846, 987100555, 2844904275, 84854892, 1268249628, 3963306788, 3338670067, 2504599089, 65588657, 321493327, 4249673617, 4150876068, 721566898, ], vec![ 2339094549, 568841948, 757218994, 54206328, 2888117240, 1758638903, 3215886938, 2041086168, 259363425, 3740850804, 3272104239, 3101597497, 4170226346, 1487680512, 2997309052, 1761169487, 680164259, 104354801, 3642294827, 2001649447, ], vec![10; 56], vec![ 4156749298, 1238334534, 3541686335, 400023669, 3354392679, 146448234, 338562445, 2541647274, 3476105410, 3869729511, 2592129633, 1524174755, 2864342013, 3189404137, 2408966423, 1748955694, 848863232, 2061232865, 2863992687, 1780371599, 1814973544, 4129152748, 1067034680, 3960771432, 1978132071, 249147649, 4113633238, 3331366833, 103867284, 4274561406, 24372440, 1874890180, 2262704206, 4185039557, 1493676561, 3605651563, 184712156, 1714079946, 3695806969, 3114374817, 2698021971, 2617815992, 3374318018, 2710182754, 2217042831, 3166354273, 3526471084, 2282901181, 17853137, 2805842653, 2980411632, 2879849003, 22987084, 2408312078, 212023482, 336282883, ], ); // - !carry && limbs_cmp_same_length(scratch2lo, ys_1) == Less // - s > t test( vec![ 275320572, 2678313698, 1997150503, 1718206458, 3389415001, 1347098060, 423205500, 1228674579, 1683636524, 1761485682, 3886555164, 1343770739, 3728441996, 3386212640, 4218849286, 3154177905, 383775865, 685210915, 2915358388, 356527607, 1399377005, 2203631586, 3950305635, 4107289625, ], vec![ 343872945, 2028904125, 1525417887, 867188532, 3911999830, 2139706847, 3256484706, 961423019, 1530068826, 3577946967, ], vec![10; 34], vec![ 367134780, 454511356, 740068730, 2466817027, 444007987, 2116910983, 3588258390, 4148666142, 241899205, 3037479671, 967522541, 1695514557, 3417684811, 1755587152, 57889847, 1893598444, 894827452, 1259092281, 343759711, 417669929, 4250137916, 2931151486, 4137704826, 1616987343, 118402896, 3476900958, 3144858924, 799089809, 2899882887, 413231425, 2515242049, 142267098, 1727945779, 3421601015, ], ); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_63() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test( vec![ 6746486103788831552, 2922469023463657485, 7190781201699911122, 6369274278675525514, 11602031538822447399, 18146097755068799938, 10715195159596301824, 1582667531232164822, 17310503547119278200, 11108448614311336701, 16131384432757080248, 10724146198461527790, 17486718158725257827, 6011711000953739951, 12044019786490872751, 12126819472937875768, 11736689834584491812, 2624631955548590096, ], vec![ 8718882040837103283, 12513261442998616191, 3363599670593686195, 2576001491054566526, 8476413363242630098, 11800520882738943180, 15256756628116724015, 15102633230716809194, 4752404995807312312, ], vec![10; 27], vec![ 11055708298853713344, 11718134630995530406, 1540454672309197922, 2461234873920328802, 12156343925049526190, 7669775936281025739, 5569544286309952271, 1251802631971472159, 7852335389754101252, 16331287242162052217, 16922468211499817236, 1090055930057904858, 4774304109866833132, 2115064630415334045, 3041714142401192073, 5249251501654981623, 6324653539847586925, 7895228639492924348, 13455067205957702368, 1142009976612635724, 13095096323291438869, 4348574203955863428, 8491467291307697179, 3535832683825156722, 3832291870552829557, 16965222076837711040, 676179707804463061, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_63(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(17, 18)]; let mut out = vec![10; 13]; let xs = series(3, 17); let ys = series(3, 18); limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(17, 8)]; let mut out = vec![10; 25]; let xs = series(3, 17); let ys = series(3, 8); limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(16, 9)]; let mut out = vec![10; 25]; let xs = series(3, 17); let ys = series(3, 9); limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(17, 9)]; let mut out = vec![10; 25]; let xs = series(3, 17); let ys = series(3, 9); limbs_mul_greater_to_out_toom_63(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_63_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_63_scratch_len(17, 0)]; let mut out = vec![10; 6]; let xs = series(3, 17); limbs_mul_greater_to_out_toom_63(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_6h() { let test = |xs: Vec, ys: Vec, out_before: Vec| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); let out_after = out; let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - xs_len * LIMIT_DENOMINATOR < LIMIT_NUMERATOR * ys_len // - degree.odd() in limbs_mul_toom_evaluate_poly_in_2pow_neg_and_neg_2pow_neg // - degree > 3 in limbs_mul_toom_evaluate_poly_in_2pow_neg_and_neg_2pow_neg // - !neg in limbs_mul_toom_evaluate_poly_in_2pow_neg_and_neg_2pow_neg // - q != 3 // - !half in limbs_mul_toom_interpolate_12points test(series(2, 42), series(3, 42), vec![10; 84]); test(vec![0; 43], vec![0; 42], vec![10; 85]); let xs = vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ]; let ys = vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ]; let out_len = xs.len() + ys.len(); // - v_2pow_neg_neg in limbs_mul_toom_evaluate_poly_in_2pow_neg_and_neg_2pow_neg test(xs, ys, vec![10; out_len]); let xs = vec![ 2176876728, 2496909862, 111654638, 4071443844, 1244732003, 1399710541, 3492272815, 2804216879, 294683567, 2823495183, 1539340600, 2732661048, 2371405604, 611094747, 2426195984, 3948451542, 3575143460, 2163084716, 2877537071, 1849282685, 1662381818, 2022577840, 552741512, 1863034519, 2109621858, 3426780715, 233006082, 2766239663, 1257764921, 1179443268, 3311729910, 4228711990, 3676801557, 83336617, 52963853, 1461131367, 615175494, 2376138249, 1373985035, 3055102427, 1823691121, 175073115, 3051957217, ]; let ys = vec![ 344785207, 1075768263, 3315797254, 2656376324, 160336834, 3872758991, 671370872, 1253701757, 217686653, 4064957864, 1185854346, 2308111201, 847669579, 195002426, 1955159211, 2003106801, 1041767923, 3605273739, 3153084777, 2806535311, 1401436525, 1148858479, 958627821, 1267879008, 4138398998, 1028065582, 3914213477, 3370118288, 4054975453, 1815994585, 2486521917, 995353494, 16609723, 4010498224, 1214270934, 797624362, 4000265982, 1287753121, 874311717, 2200865401, 21122981, 1507911002, ]; let out_len = xs.len() + ys.len(); // - r4last.leading_zeros() < 3 in limbs_mul_toom_interpolate_12points test(xs, ys, vec![10; out_len]); let xs = vec![ 2327202328, 3179332026, 2188958336, 2717879675, 130062885, 140536268, 2499125438, 3163111280, 4259661702, 2176278885, 422519228, 2482586299, 2904549185, 656169575, 2052350629, 1346745024, 2132509288, 3672720658, 1036389958, 1864007789, 4247227128, 3920036168, 1436562554, 4261984498, 3509215437, 583752676, 3145348403, 2267709494, 2846186667, 95392897, 3743233716, 2210401890, 333864866, 4114644153, 3030283850, 2885600773, 209380485, 753945396, 719327396, 1293498320, 881901364, 2799735404, 3880748109, 2227099476, 2045911493, 279042015, 1825819541, 1783146691, 2256898093, 2186071881, ]; let ys = vec![ 4062960470, 3852836537, 2696572187, 2332897564, 3819654112, 1805852435, 2339319161, 3891614436, 3143079880, 3244604349, 2122448594, 1926396564, 3938383812, 51745369, 2731805677, 4257919711, 2550692774, 4079294279, 223709465, 1648526554, 689775843, 3524108772, 1404538310, 806199241, 4278266886, 2467028886, 3773289773, 3246095241, 2201055218, 2036154035, 3144210007, 423367788, 3883829868, 2190252193, 2069131777, 3027047320, 1576225469, 3459606326, 2343356582, 2658410138, 1927376994, 3129832669, 3772482523, ]; let out_len = xs.len() + ys.len(); // - xs_len * LIMIT_DENOMINATOR >= LIMIT_NUMERATOR * ys_len // - xs_len * 5 * LIMIT_NUMERATOR < LIMIT_DENOMINATOR * 7 * ys_len // - half // - degree.even() in limbs_mul_toom_evaluate_poly_in_2pow_neg_and_neg_2pow_neg // - degree > 5 in limbs_mul_toom_evaluate_poly_in_1and_neg_1 // - s <= t // - half in limbs_mul_toom_interpolate_12points test(xs, ys, vec![10; out_len]); let xs = vec![ 1940830933, 3780770129, 1587254032, 832573251, 1504418072, 4247592896, 317874907, 949850421, 2252881736, 3574316069, 3062236166, 1396410954, 3249498785, 3495392204, 540855070, 1908700137, 1469179505, 4199276220, 953657385, 3056452157, 2141569526, 2342475731, 3746376146, 3271677606, 2770490239, 2212992129, 1758619376, 1446549455, 409094501, 767129031, 3284625381, 1887741449, 1134874072, 2988924415, 1641550007, 856704035, 80648349, 1467185629, 2753807208, 1609415681, 4087676277, 3276525355, 1530490532, 3475014952, 1971819359, 2190766950, 2667577576, 2404497182, 4128259693, 2449514447, 4199089872, 2205116036, 4089987616, 457231895, 2931469481, 3147651033, 2352907189, ]; let ys = vec![ 3461606200, 1584050797, 14355481, 3385840230, 1703326352, 1625259628, 3642322228, 911402341, 2158835226, 939248485, 3607511108, 2863853568, 1611642161, 1312857772, 1839433327, 567060478, 3139863681, 3642698184, 3744632443, 712538472, 2692932947, 576185818, 156934113, 518107105, 2803035863, 2284220097, 3447382922, 2400125006, 3565062840, 160044186, 3644393084, 4196433258, 3391883838, 1115703759, 2380388002, 962895870, 4001772616, 2311278419, 2620271020, 3047789793, 3229254302, 3182628087, 2718480927, 2872538422, ]; let out_len = xs.len() + ys.len(); // - t < 1 test(xs, ys, vec![10; out_len]); let xs = vec![ 3796896013, 4144448610, 2569252563, 2859304641, 1027973602, 3158196152, 4058699545, 2002924383, 3295505824, 695758308, 544681384, 3452307839, 1190734708, 4232023153, 451772934, 673919865, 2022672425, 3493426012, 1142609332, 477542383, 1304798841, 461115870, 3268103575, 2243523508, 606810814, 4235312469, 1885993181, 114475077, 757688489, 1965769398, 260629125, 2265559181, 2568323569, 4202738507, 422918034, 1258453131, 3552221985, 1666914845, 4063631552, 1893061685, 1362616670, 3828572660, 3003680479, 119501228, 2101943449, 1119123129, 2512417484, ]; let ys = vec![ 610160726, 3751120540, 2655318738, 2490069121, 732352936, 1985503906, 765573690, 2709177647, 3058016350, 1432725430, 2213840145, 1911049343, 3116245242, 519557432, 1828983405, 3092431113, 3844759473, 547304293, 1609305183, 1824076406, 2409386071, 2970173039, 4255413180, 894750419, 90356879, 2880999631, 2157180976, 2261258057, 715581698, 332174009, 27958638, 2464799420, 3232925197, 1952944696, 915312443, 1464711675, 4079172443, 2445511584, 2092009263, 3412361485, 2354390078, 3106038172, 3481973486, ]; let out_len = xs.len() + ys.len(); // - s < 1 test(xs, ys, vec![10; out_len]); let xs = vec![ 2187046946, 3600373521, 4275090943, 2120016813, 4177241875, 3185774231, 2397692077, 1015362399, 2178889151, 3433916223, 1688082118, 1971242178, 236388706, 3802829765, 521309115, 2299816689, 3207614143, 1053195464, 3584561145, 1178690670, 2940812254, 3321982035, 2754825123, 3073598062, 202404806, 547895545, 1188944547, 1056841779, 529463805, 204665384, 850370055, 2063320161, 3724100092, 1180272690, 1398467003, 2814052449, 1311768018, 659771105, 3226477227, 4230080238, 2134344405, 1461172705, 2728018383, 1816821358, 3231137250, 2012377728, 2206916761, 3121807673, ]; let ys = vec![ 1717557648, 1819215517, 3449795284, 844168976, 1574237607, 758725457, 762624299, 533122182, 1201164787, 1968174784, 896982568, 3419630169, 2247559545, 3983311870, 3975342941, 1112833399, 2721518545, 2493587613, 3444837338, 3313000598, 751186769, 2970698395, 915811688, 1206259449, 1340427760, 3844346545, 3762393860, 543253569, 1197933603, 3734607133, 4037352821, 2263945478, 2831362781, 3363558852, 476952769, 1916745391, 208671986, 2395250976, 1549715018, 2746690542, 1219103496, 256305249, ]; let out_len = xs.len() + ys.len(); // - s_plus_t > n in limbs_mul_toom_interpolate_12points test(xs, ys, vec![10; out_len]); let xs = vec![ 1976230069, 2821313230, 4002048052, 2248747478, 1208640865, 1469538686, 2438066233, 1106183979, 1877645648, 2583513281, 904899723, 1001323826, 3134049747, 292171929, 1479818350, 821125410, 2017124898, 3447449059, 2073983663, 1214861045, 3270809855, 2826108666, 412311360, 3687943078, 157663911, 447468817, 1727023746, 1120132848, 462566659, 21711861, 2204912119, 631663514, 2655508903, 2912870262, 1326931248, 1409724492, 3912444286, 1986726296, 190162730, 675575771, 234714100, 3787240294, 3149710501, 1950469069, 1222949463, 218525862, 929916299, 1757577031, 3896857869, 443052809, 4256330379, 1106528307, 2502814887, 108409846, ]; let ys = vec![ 3774873792, 2622161570, 566787739, 1447674683, 1128900692, 2570098345, 3920242059, 2431899603, 1456341665, 269610676, 673205188, 3712878022, 3795578329, 996518376, 3414916195, 4167667588, 4013410429, 724257700, 698186720, 1170923258, 3652768880, 1373260172, 3271469225, 971070649, 1556038273, 2204702414, 673789949, 3790414001, 1550521405, 2173912108, 70968354, 1856452807, 2648613270, 2751500372, 1057118618, 3117394831, 4409774, 2422780755, 3367234488, 1080583495, 29356841, 3627216363, ]; let out_len = xs.len() + ys.len(); // - s > t test(xs, ys, vec![10; out_len]); let xs = vec![ 2764481948, 3824853452, 3714446166, 1652416239, 2448871004, 3349954116, 2715554665, 2953094534, 2191528165, 1105735060, 407641991, 1058849514, 2583237649, 3635224830, 1509496009, 2360185935, 2419261549, 2433663350, 262632960, 3504095388, 2570319009, 2415092334, 72373859, 3953007752, 3259518037, 3401184350, 574975346, 1921349734, 1293058836, 2824387015, 670301824, 3449438821, 3149566748, 2370941125, 3445476733, 1172535390, 684380840, 4007537582, 3019960994, 3833788436, 2407231528, 532343833, 438092212, 830534904, 325324494, 1629611634, 3991887007, 1617691624, 3806774950, 2737609900, 4123817599, 1139254855, 4270594452, 3772632696, 357643096, 978439292, 3535266500, 1036728326, 408519941, 386395864, 986295007, ]; let ys = vec![ 2893157767, 2933782072, 1630695663, 765017133, 148924741, 3933388144, 2827967305, 1580462312, 4233997190, 2184167709, 1124313531, 1269787970, 2637050113, 1899399034, 458443927, 676372848, 3341236235, 2358837775, 78253712, 1308766267, 1398616295, 442007911, 3803960772, 2890078708, 2362278228, 452577827, 2295445770, 1281833658, 3733263779, 3192119570, 1465309963, 4149236735, 2550067398, 3391554453, 3763654782, 280954439, 4216404337, 2988297132, 1171366979, 752568358, 3832355781, 3002295862, ]; let out_len = xs.len() + ys.len(); // - xs_len * 5 * LIMIT_DENOMINATOR < LIMIT_NUMERATOR * 7 * ys_len test(xs, ys, vec![10; out_len]); let xs = vec![ 1537074800, 903591185, 3505885895, 1600301704, 2247503777, 2456507858, 354178772, 4264234279, 4276311343, 2137271746, 3095634214, 3503644667, 3271712752, 1235289576, 3972513632, 4268165027, 3304957815, 2349877036, 1814187379, 1622480961, 1887152020, 617829740, 2759792107, 2650325546, 3834300382, 1711067002, 16368281, 3248020475, 1355293366, 2500355734, 3216660200, 2844209744, 919471841, 2536405197, 286948869, 3207728956, 1786641001, 3909697676, 2990524533, 3373134471, 2770917041, 2941741335, 2275165617, 610985518, 1663622513, 780492488, 696913656, 1787332447, 1693914179, 2059746330, 4084862137, 1720114882, 2072770321, 2800094080, 164377327, 114079185, 1630830573, 866212705, 86571916, 2701570437, 1022361296, 2774191689, 1485998454, 1449541799, ]; let ys = vec![ 10887125, 840662268, 2350057862, 3489480809, 2643647461, 2120151555, 433525765, 1719122308, 3784715068, 3156307967, 4113669583, 607844816, 2149779595, 55766995, 3922134877, 1464452041, 2877070520, 3517698059, 3219767758, 138329276, 1434547315, 1010269423, 3836852303, 521525549, 1124005096, 128173038, 1627976147, 4217098680, 963901397, 4003948876, 4078383999, 3163439869, 1376461045, 1260808800, 1583549957, 3016546386, 601137572, 2476346948, 1057124592, 2232232546, 2939285402, 2703166574, 2566511508, ]; let out_len = xs.len() + ys.len(); // - xs_len * LIMIT_NUMERATOR < LIMIT_DENOMINATOR * 2 * ys_len test(xs, ys, vec![10; out_len]); let xs = vec![ 2480817744, 2385986715, 908796583, 3725142486, 4259996640, 2324291843, 2514777689, 776517112, 1179390166, 2884250121, 2107025487, 1847592315, 1214792717, 581761941, 2035752941, 3257884740, 1011095107, 388625485, 621566511, 1878249130, 2298430809, 3893830507, 2516166455, 1685998768, 3349147146, 4262358486, 164529678, 1000098113, 1468664761, 1088142633, 2140348214, 672483433, 4236152545, 460911546, 1948312076, 1030937440, 3633681142, 1170002101, 2159285228, 1104198886, 1581288546, 2266152509, 1437951300, 3854459332, 88193405, 3804599756, 577997778, 3610194716, 2527782134, 4194448103, 3390832927, 863423772, 2308481008, 1764994151, 2876150765, 474256942, 3850214133, 2831691105, 4251752821, 80285354, 3225163007, 84390462, 1489215151, 1516077116, 299402893, 1093360002, 706962212, 375054336, 678692965, 2794629958, 3684518009, 1067098399, 3918266067, 770155119, 1400555696, 4260143847, 3420662760, 2234352998, 2627202272, 2396298990, 2703934662, 2975030448, 1678542783, 3962857080, 2037990778, 2350341680, 3690768614, 3327392397, 2374080995, 1568940040, ]; let ys = vec![ 2432887163, 3617411153, 4065664491, 954897002, 1958352130, 2690853400, 3170435422, 333223996, 1886503369, 2874118364, 2360990628, 3409169651, 14803166, 2428352279, 2882529293, 215157778, 3595826381, 1351666697, 3213081864, 1796627015, 138520647, 1446708749, 549025603, 1154696063, 951257454, 1061151557, 3578338019, 553024835, 1032056788, 3332695385, 1916952270, 1402847201, 418140204, 1113800470, 3311963507, 3579825680, 283695808, 1030062334, 2885288472, 2307021635, 1215165167, 361703549, 3359666682, 2960119991, 3759575408, ]; let out_len = xs.len() + ys.len(); // - xs_len * LIMIT_DENOMINATOR < LIMIT_NUMERATOR * 2 * ys_len // - q == 3 test(xs, ys, vec![10; out_len]); let xs = vec![ 2182584668, 370736031, 944597706, 368333101, 3076089385, 4269551750, 455799119, 1640998687, 1332255273, 3039440200, 1094187469, 4158542740, 4241437189, 786279542, 3313987323, 801901648, 2460914857, 2458651362, 1161118074, 3733983107, 1911753349, 4261306583, 981590361, 1357088215, 210591422, 1159943023, 510963968, 2705428227, 3460159465, 1967595187, 703584117, 3474024702, 3343010520, 1232104952, 823854220, 4012290690, 3252492197, 3975386640, 1309751464, 232265040, 2026518879, 794539121, 1849747498, 773993567, 2415934846, 842827728, 25297943, 3952540535, 2909076393, 4183158950, 2579267900, 898983053, 2480815324, 1004385686, 3272214418, 2360496610, 3884948711, 3937994494, 1355835525, 1862072763, 4077270583, 456721854, 1202741767, 1334238573, 3202598432, 2518498766, 1873498914, 1155219866, 3257357513, 3381800028, 777225471, 1628571355, 281982096, 1238331533, 728101793, 407378640, 1088081860, 2405377044, 2080950804, 3105324348, 3065313268, 2776290680, 1200951260, 1789619269, 1088225065, 317598486, 924903972, 3504476787, 1605816151, 388266283, 1613602905, 4051481387, 2773856406, 3434866445, 2039264971, 1587433780, 1787644933, 2852323335, ]; let ys = vec![ 3040086267, 3720432305, 3025753876, 3307555779, 2232302878, 1705545587, 3746861739, 3551552480, 3791909589, 3559707401, 3597994914, 1201195479, 2759785652, 2538497144, 2628719068, 1220743906, 2592330951, 357425155, 2683446134, 369894528, 2918070813, 3201581079, 352827384, 2667389301, 406071886, 1478662115, 3424718337, 3498162517, 1851891341, 2009161130, 4175528772, 2739823403, 2691610015, 530787751, 2995441702, 238468207, 84087963, 2802633771, 2722772179, 1905704311, 791349630, 4036308669, 1333503772, ]; let out_len = xs.len() + ys.len(); // - p == 9, q == 4 test(xs, ys, vec![10; out_len]); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_6h() { let test = |xs: Vec, ys: Vec, out_before: Vec| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); let out_after = out; let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test(series(2, 42), series(3, 42), vec![10; 84]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_6h(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(41, 42)]; let mut out = vec![10; 83]; let xs = series(3, 41); let ys = series(3, 42); limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(42, 41)]; let mut out = vec![10; 83]; let xs = series(3, 42); let ys = series(3, 41); limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(41, 41)]; let mut out = vec![10; 82]; let xs = series(3, 41); let ys = series(3, 41); limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(42, 42)]; let mut out = vec![10; 83]; let xs = series(3, 42); let ys = series(3, 42); limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_6h_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_6h_scratch_len(42, 0)]; let mut out = vec![10; 42]; let xs = series(3, 42); limbs_mul_greater_to_out_toom_6h(&mut out, &xs, &[], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_greater_to_out_toom_8h() { let test = |xs: Vec, ys: Vec, out_before: Vec| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); let out_after = out; let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; // - xs_len == ys_len || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < TOOM_8H_LIMIT_NUMERATOR * // (ys_len >> 1) // - !(Limb::WIDTH > 36 && q == 3) // - r6last.leading_zeros() < 3 in limbs_mul_toom_interpolate_16points // - !half in limbs_mul_toom_interpolate_16points test(series(2, 86), series(3, 86), vec![10; 172]); let xs = vec![ 3581553119, 2147449432, 208926434, 2037430803, 4143975728, 2356343321, 937192435, 1637432038, 661638621, 1801480924, 3779152128, 4243491821, 1667774376, 1715755489, 3661813139, 1605971891, 4030695606, 2961165054, 1368430397, 2222904896, 2817587025, 1714442303, 3822714979, 300305701, 1874484285, 2601340412, 2275789197, 2695461089, 2246464394, 1119579754, 1646098622, 3280004748, 33497272, 1940830933, 3780770129, 1587254032, 832573251, 1504418072, 4247592896, 317874907, 949850421, 2252881736, 3574316069, 3062236166, 1396410954, 3249498785, 3495392204, 540855070, 1908700137, 1469179505, 4199276220, 953657385, 3056452157, 2141569526, 2342475731, 3746376146, 3271677606, 2770490239, 2212992129, 1758619376, 1446549455, 409094501, 767129031, 3284625381, 1887741449, 1134874072, 2988924415, 1641550007, 856704035, 80648349, 1467185629, 2753807208, 1609415681, 4087676277, 3276525355, 1530490532, 3475014952, 1971819359, 2190766950, 2667577576, 2404497182, 4128259693, 2449514447, 4199089872, 2205116036, 4089987616, 457231895, ]; let ys = vec![ 1495737173, 3863569894, 2781409865, 2031883388, 2335263853, 2715800358, 580338429, 3465089273, 419683969, 372309798, 2092398197, 1587236508, 1706866472, 1926863329, 2427550983, 3014840641, 2591183237, 311998012, 1838159904, 2382380991, 3168560843, 2457672651, 1329938456, 1585986499, 32624746, 1886190156, 1819802220, 4189456784, 2354442118, 1007664036, 3528608675, 3607011918, 3175583218, 2103466232, 4139172560, 1977990249, 408055457, 1917901811, 4285926188, 2576630504, 3833124229, 664620480, 3594197860, 38119241, 2843152292, 1589895470, 132829200, 911163756, 3350029197, 141124331, 628197809, 3184483823, 2738720089, 3684675439, 2998575143, 2394913714, 2088681890, 2743885961, 2257026807, 2812703572, 678096205, 2964972038, 1641032123, 3238217254, 2452280240, 193873172, 277301379, 106064560, 2264572378, 3461606200, 1584050797, 14355481, 3385840230, 1703326352, 1625259628, 3642322228, 911402341, 2158835226, 939248485, 3607511108, 2863853568, 1611642161, 1312857772, 1839433327, 567060478, 3139863681, ]; let out_len = xs.len() + ys.len(); // - r5last.leading_zeros() < 7 in limbs_mul_toom_interpolate_16points test(xs, ys, vec![10; out_len]); let xs = vec![ 3998843185, 3237409891, 364765898, 887299373, 875693912, 790653310, 1949338310, 309040598, 2753929769, 1560315881, 2158749638, 124625299, 1949071109, 4293842935, 3418183766, 1387429696, 64843603, 1303399904, 455978049, 3724928213, 4182321093, 1342619213, 1692503310, 2594578249, 2811338438, 1715625698, 751013184, 1529801113, 2582454920, 4199343251, 3183268625, 2516721877, 1167772050, 2317983168, 1793272983, 311653702, 3588179354, 661601476, 2154410870, 2334965650, 4135084105, 1682699224, 47903600, 3273743199, 3845966395, 1357302998, 3756718174, 2451701689, 2321438159, 3211448326, 2377823945, 50814995, 1672303030, 4158805623, 2661886690, 1846253587, 702414278, 4059841129, 3727323213, 1424047747, 2939622087, 2231052374, 2013876172, 2053003398, 1741887596, 3509712959, 5142212, 3825464748, 3375048072, 338658021, 2655991044, 2889153792, 2332483687, 934832926, 3863652984, 1414099507, 2895368376, 1013122176, 2794762768, 2981493251, 3152252275, 1564424419, 536147906, 242465174, 3000707896, 3526733161, 943706939, 349997931, 1497577916, 3473622068, 1517005385, 2206423568, 1544165865, 3199998353, ]; let ys = vec![ 1562512360, 3239315566, 2225439589, 502536858, 1867965636, 618137922, 4149231651, 476678563, 4203415530, 4178036608, 1956783646, 4023049148, 2645084690, 270122366, 201340005, 4276855303, 1021151730, 916821881, 663141922, 2795604136, 3762385264, 348487994, 2655354829, 343872945, 2028904125, 1525417887, 867188532, 3911999830, 2139706847, 3256484706, 961423019, 1530068826, 3577946967, 2361035355, 337639742, 3774308229, 2185652798, 3532716804, 4018761888, 1357817255, 2216301712, 2861241181, 3053055924, 3777579308, 795689292, 3386662598, 4160296368, 2005833155, 1297354264, 2851045342, 954306552, 1613754854, 2227385445, 528669733, 3315107199, 3402866739, 1117279433, 232818134, 1490857876, 1962534623, 1227821174, 159891958, 1385848424, 4061426539, 647828819, 2061390815, 4239314784, 1854131914, 3258304017, 524974854, 450125309, 684998491, 2942294237, 4191667771, 2230185588, 1844054665, 193300986, 2652500966, 4050934267, 1133780381, 3709046706, 909867408, 4209959016, 4275912160, 277155368, 1775051743, 4190065677, ]; let out_len = xs.len() + ys.len(); // - !(an == bn || an * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < TOOM_8H_LIMIT_NUMERATOR * (bn >> 1)) // - xs_len * 13 < 16 * ys_len // - half // - s <= t // - half in limbs_mul_toom_interpolate_16points // - s_plus_t > n in limbs_mul_toom_interpolate_16points test(xs, ys, vec![10; out_len]); let xs = vec![ 2456061149, 2562918666, 2903450513, 1994190773, 99234624, 3722083920, 4262323306, 202219441, 4201857695, 3988878636, 1533308334, 401400520, 1069756554, 2457773969, 2892388936, 3423117995, 1944069442, 492036629, 3426800580, 2282483359, 4006366620, 1695364515, 2555180845, 1669287836, 349290429, 778467450, 2020203604, 2218159817, 1450404019, 1278304750, 2412695340, 1592154884, 3868182043, 2240370481, 3859902860, 1008825116, 412233394, 2475457637, 3664379433, 4204584226, 2750684469, 4113507475, 2916584959, 285955744, 739598569, 18278051, 3768126932, 2181905109, 2612988076, 1827656088, 1160380415, 4160443718, 1846086671, 3050604645, 2547108010, 2828666778, 3252702258, 3885923576, 2331974758, 730724707, 1528859315, 4288784328, 3677151116, 445199233, 3304488688, 3566979465, 3541025426, 2491779846, 3112990742, 2583249486, 3403111749, 1930721237, 3428792463, 2896462048, 2985885576, 1819460734, 21206096, 3560441846, 987100555, 2844904275, 84854892, 1268249628, 3963306788, 3338670067, 2504599089, 65588657, 321493327, 4249673617, 4150876068, 721566898, 2186945060, 922948272, 1502464627, 1426914435, 2906888275, 3454987739, 2609132626, 2073366782, 1058809001, 1226951003, 2624503637, ]; let ys = vec![ 3941840558, 1662743930, 1905993615, 2485835810, 3925643251, 3071436009, 851721712, 1325046168, 3214018378, 1465803515, 2459667310, 2361559987, 2668552637, 2425633974, 3200812339, 2594448814, 4170435967, 1112582678, 3198704424, 4028094030, 2482710119, 2990475705, 708195759, 612294539, 2794828841, 2498141427, 3805184114, 3010938369, 1479667740, 660767380, 1641177565, 1782849661, 1915222559, 1626388136, 1816788637, 1338361170, 783877621, 4003339370, 1930607900, 1259399167, 3351643097, 1641708262, 967800396, 1800752717, 2198926109, 1163817943, 2710351254, 451351637, 1285647338, 865168955, 645286276, 2685132510, 1773153387, 4273868103, 2604563645, 4105767904, 2556376985, 158907213, 3579937882, 3059825408, 1920542835, 528717490, 1430681949, 616489338, 597761261, 3760865497, 963173252, 2915089223, 1441674715, 1717557648, 1819215517, 3449795284, 844168976, 1574237607, 758725457, 762624299, 533122182, 1201164787, 1968174784, 896982568, 3419630169, 2247559545, 3983311870, 3975342941, 1112833399, 2721518545, 2493587613, 3444837338, ]; let out_len = xs.len() + ys.len(); // - s > t // - s_plus_t <= n in limbs_mul_toom_interpolate_16points test(xs, ys, vec![10; out_len]); let xs = vec![ 2166912886, 3021127478, 1088026295, 863338925, 1902617744, 2706401163, 3211745137, 3537828549, 2310228205, 2585051285, 3210490216, 612524924, 269492174, 83675252, 3088638931, 2020592214, 884676247, 2114372012, 2448236682, 3651962645, 4142890271, 3807368959, 3038213130, 1740849525, 1839016815, 3718350068, 1798083657, 4018300117, 2557824626, 1367910868, 3524299249, 2718734101, 2199735437, 2156117642, 3314330151, 91570504, 1763771190, 730175380, 3035959105, 930897603, 4104577491, 1545111417, 2973200358, 1531233892, 3216274102, 2879326700, 4043195388, 4012932329, 1225928231, 3148638781, 3350412374, 571148440, 42117077, 2619230436, 570695610, 3533920410, 2337569860, 2616128436, 1101128308, 986097032, 4127211776, 1459526104, 121723950, 1459838938, 1563443987, 3106615121, 2637954840, 238917822, 3086105506, 2960421944, 2937286162, 3871313970, 554575295, 450448609, 493464699, 3492897008, 3198787067, 2691863142, 874317820, 1804414164, 572281701, 2867423932, 412542374, 239109523, 4270925097, 1858402222, 3784404338, 162014339, 182208178, 171269941, 1556499146, 3122050585, 2070559038, 1293272336, ]; let ys = vec![ 131674806, 603734923, 2440163395, 2896151903, 2142986136, 3702794463, 407655836, 1281722924, 1990690788, 2883417209, 1106804242, 965105623, 3369860750, 2422075060, 1042530548, 1864787458, 1722387953, 324177444, 3169639558, 1324636283, 1394919591, 1382200609, 4014256585, 1943865290, 1318181231, 2753206532, 465681637, 3556126827, 3726586809, 2859198026, 1880611700, 2743775719, 2312093882, 2611444395, 2043850780, 1748249887, 1827465861, 1827026074, 3842470222, 886015214, 1202152837, 1760966154, 1303682364, 2141063912, 2027419958, 3046273896, 276337299, 1629565318, 3973822671, 3586055166, 515343743, 4150823547, 3812419028, 4047886683, 408756427, 30807697, 3839670586, 3241113948, 1946580966, 211283947, 1648787704, 1254977229, 324210665, 409019127, 999906525, 3589880779, 2652719468, 2740912614, 75319316, 3276454084, 3598090610, 225502084, 1039377126, 3755265351, 299690912, 2582901309, 891564570, 1062813956, 318910996, 2153235228, 2834278326, 130377847, 977327805, 3290994684, 2956083989, 826986477, 1417957671, 2007397536, 3845476521, ]; let out_len = xs.len() + ys.len(); // - s < 1 test(xs, ys, vec![10; out_len]); let xs = vec![ 1012246656, 3781649075, 2144318856, 2608903399, 688555306, 1040133166, 3831584367, 1593112617, 1823654254, 840638304, 3109717334, 188514461, 398797195, 75875990, 1486449995, 4269057266, 3729965858, 1861862237, 3631015569, 3651675458, 103019792, 4115125912, 854107191, 437995362, 1626634580, 1556708150, 2197935825, 142443256, 2516681044, 165384798, 622726627, 2804275513, 3768014324, 1019999140, 1630141384, 1569491385, 2650112147, 404117490, 959368136, 1567892691, 3740061638, 1492035182, 2806958299, 3558543973, 2394278513, 193040368, 140963621, 2363913022, 521760299, 1509309827, 1222622424, 236238235, 148145098, 1185145642, 4050835140, 3496710859, 2912031916, 2811044753, 293786270, 1593967022, 3059741198, 957447590, 999733770, 3225819121, 389969264, 1617194653, 930042654, 2073424372, 1334988223, 2244143480, 3036433790, 314486992, 3505856530, 2253001666, 2732695676, 2150239253, 2058771616, 2553846568, 3156714961, 275374496, 2154639432, 1705499511, 2661128488, 2996751598, 1991220721, 2971546013, 947096109, 1988630082, 3629027637, 2894867708, 982953971, 1288656915, 3544920961, 2725968940, 2718109332, 1685012966, 2463009759, 1861144639, 2364403606, 3459863283, 983775524, 3466796660, 1976698215, 708098181, 3069387825, 3638611575, 2579187312, 632774203, ]; let ys = vec![ 1809516468, 2803977220, 3078159083, 486681337, 1568336896, 4117841648, 422990983, 2706208156, 3747890395, 2705136812, 2904348475, 1582408791, 723059442, 3021061511, 4080366324, 344817763, 4291264074, 846996023, 4266039848, 1034099747, 3469554547, 1098932136, 4197098884, 2840685725, 3598360260, 3858664271, 2988904929, 3788334949, 2778508367, 2862059554, 3453038230, 315104137, 659918534, 3119028578, 178870393, 1471088291, 908295683, 5373305, 1643272591, 1306263419, 808966614, 4084169993, 740212697, 4046005160, 2962244838, 2183688745, 2126344144, 2041407930, 201066579, 4119015900, 3263668172, 1482349211, 660638692, 596028971, 3002749394, 3127689329, 147925750, 1069598238, 1868876453, 1293290441, 1391999979, 1064595909, 1912901608, 751720124, 313663396, 2718231373, 1813378594, 1913592155, 2372166689, 312370283, 1294902637, 1519106439, 2159217107, 3862662328, 3650935678, 3673744494, 1365354839, 4239084491, 2676645359, 906655247, 2012326184, 363781147, 121405308, 3179196888, 1415338639, 788446024, 2165764832, ]; let out_len = xs.len() + ys.len(); // - Limb::WIDTH <= 9 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR >> 1) < // (TOOM_8H_LIMIT_NUMERATOR / 7 * 9) * (ys_len >> 1) test(xs, ys, vec![10; out_len]); let xs = vec![ 4119986492, 3769784140, 1016845783, 1462133596, 4070906664, 3720888633, 4162266585, 357581522, 1461543577, 4176530320, 4211178471, 3101664977, 3852655570, 166352500, 1437797012, 3499540684, 1659293446, 4040889056, 2872135683, 3443479700, 655062062, 1438477128, 1251147166, 2862092792, 1899445621, 1706155530, 2740470033, 732343724, 3637646944, 4084594941, 2604690616, 4034800391, 3052473123, 2211244267, 947388355, 584537104, 4143732645, 753960748, 3490638800, 3716731483, 812984705, 1845462359, 65215620, 4176252687, 2616921776, 2554085123, 4119079055, 4015290385, 697509015, 234073199, 845662165, 1354305840, 981298174, 1565184955, 207005143, 3409837524, 1220287572, 729153595, 4103593694, 3696910742, 3965466426, 2266950204, 3856396952, 1764904477, 2684424799, 2851670593, 1238534904, 1193928568, 775873269, 1360693711, 2015831201, 4011315900, 3412793575, 214657369, 4288738109, 2288646350, 4016569358, 3132961648, 4045851426, 3660819126, 4044839853, 3089247133, 2180567261, 2646234732, 1387965746, 2657998851, 713566741, 3356621670, 3732665499, 1904626236, 64110644, 1408823950, 3590020345, 2474929782, 849015605, 44073994, 1392682200, 2899713947, 276297197, 2522590522, 3057126922, 2424068009, 1656987557, 1344629217, 2147192728, 3358875432, 3127883048, 1416207351, 2542101426, 711240683, 2104649063, ]; let ys = vec![ 2166824272, 3241826034, 3119928903, 4235394337, 702909009, 952063230, 3767289278, 3471432542, 1289423414, 4165356232, 1144080646, 1098693005, 2158644075, 3466960484, 107907398, 1849951849, 1697379716, 3245621651, 789557144, 3055443426, 3784862213, 3687293729, 3527108073, 2085509714, 2098672286, 4237955923, 1799505183, 4280924128, 1714047371, 679046973, 2920210487, 2630108623, 3799940507, 2820960341, 2480102998, 3063576036, 1124333889, 3649141414, 3766465016, 1301782752, 3365747207, 318110166, 1798715740, 3939897237, 1972418626, 525713989, 4204639302, 1845175119, 3066964494, 3197166778, 2045294098, 1778200774, 1122512884, 487879411, 3912690682, 2631572995, 119236796, 3659697136, 875446358, 2784882013, 724223194, 2290104863, 3553626657, 1049986268, 1149074120, 457683007, 342994481, 3969592954, 4124706173, 793289745, 50385201, 428623925, 330776585, 154172871, 652756593, 1305471058, 3295431270, 1976260297, 1729803474, 1132360814, 2965768226, 3482945302, 2017386623, 1093051437, 2874103717, 2882475975, 3735654948, 1766940801, 3723445548, 3203977826, 1788553316, ]; let out_len = xs.len() + ys.len(); // - t < 1 test(xs, ys, vec![10; out_len]); let xs = vec![ 562392731, 220608607, 3016011233, 1988425644, 1753293069, 202000452, 2988281129, 1833355482, 2406139229, 3819843447, 3864310556, 2964129037, 3243750205, 1300008578, 213321522, 4162936161, 3499001762, 2548817881, 797422884, 3464557820, 3172918275, 3342298017, 4095467160, 1278405537, 2731045246, 1797909329, 915931552, 1234105774, 1721010619, 393116356, 3595672812, 246921897, 3156619416, 367413315, 835896205, 1133867872, 732164137, 2864249493, 4191919416, 2012484604, 2046119300, 464214194, 1309621688, 2133767576, 1817717936, 3210357881, 2703486295, 73128890, 3834854978, 1247202589, 3867658887, 743571365, 623502109, 2414902368, 4157134303, 505113368, 3563229135, 2326845431, 1870329856, 412186635, 643126122, 918171482, 3174437348, 992920198, 2549886607, 2594507263, 870344606, 3354423872, 3768408002, 1124888954, 3015715321, 3554830011, 153164314, 2571405898, 3088317836, 3826710038, 532463221, 2174408986, 4066384743, 2858347925, 3362316763, 3912725306, 1672655485, 747559434, 2494848220, 3353179599, 2958541661, 2754014801, 2253228000, 3548360599, 2532574632, 3609949183, 4224112455, 2830762232, 1638592699, 748357099, 2027377618, 2154359009, 2042715188, 2328113060, 2228778844, 3805284055, 3740811424, 437279916, 2305090412, 2502181871, 3285232891, 3972490704, 3821166397, 3272678301, 2818983671, 4257635933, 1730183078, 4193248424, 1863033893, 2751966968, 1985590742, 1553448103, 2731396486, 102894954, 1596356734, 2399109494, 326183031, 3303826610, ]; let ys = vec![ 1675796150, 1752707855, 2960577702, 4246206199, 1769535683, 1968809225, 2828046910, 2881173858, 4049894594, 690462953, 288094502, 2301238042, 171278398, 2941234911, 3855716963, 3569445656, 3999649666, 1033046275, 1441788099, 1121368236, 3979411258, 1744237927, 2218358768, 3293576320, 3290293896, 2918243870, 1271587143, 1530970846, 1057501000, 1208621673, 1776318661, 2630121830, 1577699073, 3947123592, 1916313897, 3189157970, 1684300643, 5245214, 2973935012, 1013692937, 2575458340, 1202811269, 2350985644, 938605227, 710807110, 3840777315, 2476378686, 1408221563, 3963538750, 1495981337, 345677390, 2267206171, 597425252, 3652332994, 1484311898, 395641995, 508511757, 1756437663, 1140313927, 4146891666, 1764315654, 3179667093, 2753886170, 2955381796, 1486042517, 194560773, 4113616196, 3870970045, 687965138, 970031260, 4029682995, 652798493, 3718790353, 2790548419, 1973920939, 1737499520, 3093968446, 4016940528, 1440510403, 2896783742, 3442955437, 3111677005, 4265014223, 2141411993, 177598581, 1546615872, 1296900550, ]; let out_len = xs.len() + ys.len(); // - xs_len * 10 < 33 * (ys_len >> 1) test(xs, ys, vec![10; out_len]); let xs = vec![ 2699110155, 1597521691, 470373633, 1547603733, 1114505968, 121868046, 1203637014, 1508031395, 2678363006, 1428373366, 181016145, 2228522822, 3784155833, 1174663302, 3119880811, 3351843127, 1893166310, 2733160757, 573074872, 1444139090, 3771161592, 3202218806, 1184188558, 1337716051, 2651973158, 1523269291, 3416369561, 374511279, 2679410392, 1510022750, 228616166, 4003251265, 4290642350, 3280834410, 1463007103, 2311946289, 160203186, 1585276951, 3812024477, 3976220702, 3453132955, 903478724, 1692984648, 32969770, 393253462, 2089515635, 2580037721, 1368262724, 3975524017, 1095890302, 3362835893, 1467244702, 3126524190, 1558041706, 1473844963, 2931771668, 769941843, 1383766743, 2048229827, 3587516656, 744923988, 3114188668, 2900631137, 1550641047, 3971430916, 1024708451, 266103704, 1961354549, 2996989736, 96509114, 3209890269, 558760343, 1942895993, 3030238742, 3901981217, 1553802266, 1100766439, 3617908428, 2903765815, 160559154, 3223711195, 1505354960, 3400362702, 1532921847, 2633984159, 2547091597, 3753857128, 1603256426, 1467979288, 834683287, 883770936, 2091938738, 717946381, 1738927478, 4212395432, 3554713903, 2891799196, 2460462345, 1068611661, 1983982847, 4254702408, 2862607717, 205351503, 899537845, 4178691861, 2027719370, 1613590765, 1667586567, 658709687, 569869145, 2542265621, 4018309335, 3115945617, 1860868443, 2042873761, 2857432666, 3454761191, 644158605, 952236065, 1246066126, 1054146509, 820815201, 4116210106, 911797864, 980581305, 3662945636, 2395465042, 2988547838, 1592529958, 4123985797, 1086072833, 1344358819, 2713461665, 1166149285, 868088866, 120572741, 2719927699, 1609748024, 1381464015, 2371158669, 2027765235, 2167125167, ]; let ys = vec![ 1088368182, 3374520919, 2135624591, 387360487, 3348241848, 2559227752, 3399060139, 2714380393, 371475119, 1878664574, 3306012397, 3678253780, 2537332523, 634258529, 2378309044, 1907416933, 2176550942, 3624058493, 608851538, 77324946, 854257549, 2563267740, 1842976277, 2560652658, 1177372492, 4164431297, 2857340159, 2813781292, 3608170666, 289363804, 1276568988, 1858470908, 2027103570, 1210716416, 3885179582, 980951621, 1332461771, 2439102632, 78855299, 1535655076, 820717475, 1372739985, 4277759699, 1928781862, 2056547589, 2689637269, 3487926306, 1712399855, 2387894324, 1345157890, 420194957, 2408734980, 1088476282, 1237271902, 1570597541, 1299046081, 2179334980, 3757788366, 1320170918, 2220338411, 3413493273, 4047658929, 1004605073, 3758106669, 3623304103, 2595195415, 3392723185, 227342906, 3297612463, 1577658966, 3646845515, 1442494023, 1805636027, 1293916606, 1856823520, 2157779944, 1701394115, 1586957718, 2203990942, 3794477956, 470446365, 3294563814, 2801795027, 2712013665, 1473818504, 2726878536, 4276109446, ]; let out_len = xs.len() + ys.len(); // - Limb::WIDTH <= 10 * 3 || xs_len * (TOOM_8H_LIMIT_DENOMINATOR / 5) < // (TOOM_8H_LIMIT_NUMERATOR / 3) * ys_len test(xs, ys, vec![10; out_len]); let xs = vec![ 561532292, 1489901668, 253691236, 2318497628, 4251899866, 2953100123, 2461942387, 3249119706, 369296206, 4217598289, 2953582842, 2377320700, 2568035293, 3298340549, 2920237456, 546954422, 3577037488, 92033404, 145112422, 2502470868, 1400281201, 2303329463, 633903343, 3944799609, 57410139, 3300617501, 2988597979, 3756577241, 1111328153, 2315706065, 2359556880, 170569603, 1875977300, 2265470483, 1673672630, 2694260146, 620660163, 4086502272, 2268845329, 2531408738, 745892765, 2985301421, 641961881, 620799476, 1513471210, 2206613713, 895576219, 3432428917, 1326478424, 721293050, 4129832181, 2328492091, 790053303, 1886834609, 2560250292, 14318242, 2263105643, 3768652300, 3685567034, 1053183071, 4035043131, 1140590999, 1312717632, 820131789, 2381319255, 515196511, 2436315339, 513976227, 688721295, 2969875582, 2843970288, 567346371, 2277297382, 3266747935, 3125131739, 391700432, 2628083321, 779071641, 2971551059, 3314957816, 871191953, 3336232721, 2709555815, 918246312, 923872244, 2827827195, 2966239254, 1586350108, 1024706608, 3525365202, 594940169, 1872199600, 3239665333, 694926057, 4271587637, 3916707341, 2190558956, 2300957253, 772629754, 238192213, 4247448230, 3565892036, 3184365211, 2516885224, 3979985839, 1180780557, 783722885, 1061155274, 3798456603, 3320505371, 589311966, 1623819314, 1001947009, 4232577387, 474033387, 3930737007, 1729002759, 3148522805, 658463592, 1424102704, 2305467923, 552214960, 1642169523, 2066768192, 3794357111, 3557589618, 4204044663, 1778418301, 1181058217, 1612951946, 588858899, 3836952607, 2977777237, 9660119, 2962495164, 2992962211, 3923151463, 3345257705, 2981383558, 2363319525, 3608470059, 874691575, 2586822309, 912499640, 603852379, 1888867173, 2770352234, 4238262229, 3877831016, 2596074823, 3663087235, 542677879, 228437282, 480155344, 709141324, 782255006, 2839979153, 1271748198, 1031245745, 3053801112, 3462023195, 172164778, 3874269611, 3279470898, 4076666435, 3596981639, 810288236, ]; let ys = vec![ 2267307147, 2856749182, 90961593, 1052868712, 3437758783, 899762302, 2825414504, 3100252964, 214994098, 4262558841, 2740902902, 1743352008, 1922058509, 2975766063, 3399126202, 897115238, 401142729, 1715015464, 244955103, 3177992227, 405891649, 1768495060, 3524094602, 4080016656, 1432684874, 3397000143, 434821341, 1754546815, 4094846559, 4286153335, 2240106918, 2310322076, 1713831329, 1428414845, 2188185809, 2111765503, 1131727372, 929039425, 465389857, 2677898170, 1160632541, 3376736943, 491317513, 3242464822, 2045506450, 1242019843, 3965879224, 2484620055, 3447163057, 2809067396, 2409780789, 548871240, 2024164190, 4133800101, 105887616, 4257692355, 1942633927, 1532037864, 2395107706, 1815832330, 3470252735, 3388820081, 2275739186, 2499364631, 2076801086, 3670985009, 395675635, 4219873512, 338672631, 3757753689, 730801911, 529959909, 393050276, 2506914867, 349901023, 889932113, 2359995672, 2260685091, 3193258383, 993644814, 660499678, 4213349264, 915065087, 44382277, 1138965336, 3728412916, ]; let out_len = xs.len() + ys.len(); // - xs_len * 6 < 13 * ys_len test(xs, ys, vec![10; out_len]); let xs = vec![ 2628750713, 2361938253, 4208887130, 2080756349, 672997060, 2130716095, 4212789307, 1848408220, 3496438901, 84923093, 3765911616, 1894564551, 1611354899, 273564832, 4150644671, 3064400972, 1543250045, 2858928926, 1070491873, 1579001797, 1184344436, 2022081087, 579467674, 3617124184, 243126922, 3969739693, 3428743965, 4195070089, 3234082950, 333482038, 2496442330, 894715026, 434494401, 2735937738, 194433417, 3547773069, 1310458322, 1092526211, 460831665, 314882384, 352225614, 2524634920, 3907974253, 3587596708, 90585625, 3922151265, 2706453821, 2479984430, 1899379393, 521798300, 3544490367, 4025847744, 520557399, 1960228079, 2440638916, 3922652110, 2874111917, 3780219346, 1155970954, 3101729918, 1154605497, 1641746684, 3885558155, 713658859, 2298415211, 1104859444, 397648670, 938276629, 2245930839, 351999985, 3962599907, 162580649, 4135267160, 3893533927, 708603373, 3649893874, 1549341047, 446919848, 3848748260, 1193215655, 1667453481, 4263900238, 3083741929, 569862864, 111540402, 371222591, 836814821, 2523967214, 3373518119, 288800478, 2983910658, 3822451776, 3717238299, 4103554210, 497321656, 1267537380, 2210886058, 393666292, 2341926460, 2993069655, 3449632275, 345728673, 1850135319, 1546568315, 349065480, 4148532822, 2743969263, 1135023914, 856540508, 710683508, 621037301, 2245404525, 1375763902, 4230256152, 1103848377, 4068950000, 2774111626, 4005998377, 1420452414, 142442998, 296389949, 1793483671, 3236856344, 1470778143, 2199111141, 1485252921, 3021831668, 3409728715, 494048497, 425352623, 547187992, 307378564, 1878128309, 3632431108, 3608263098, 3158948042, 268203532, 1889965332, 2413564070, 494017444, 4018318246, 2256416411, 2325799856, 424840978, 1475143253, 2578705133, 3454058108, 875893914, 3369487214, 2161583703, 2368049199, 3710749831, 2234731371, 2548143256, 1212646047, 775618131, 821458424, 3027168315, 841398247, 3991240853, 2094376383, 3587145176, 1943420573, 781156526, 2434343084, 2126213029, 2402207510, 4019808646, 316909832, 2750686513, 2438176721, 308346316, 242903105, 3531437189, 4095795963, 2087963376, 3007755141, 1683404210, 3086330285, 1333246101, 1581088323, 1356633529, 3666603849, 540703941, 1410918479, 2987931996, 2750320701, 3483743338, 2503688388, 3308034421, 3019960566, 2668657879, 2363438262, 1470517413, ]; let ys = vec![ 2312659839, 2350424241, 1787407270, 1271425122, 4187967770, 818645453, 3539315256, 2178962268, 2575529612, 3589703821, 2051328589, 1350506812, 1181962471, 440960359, 1364212437, 3414960630, 901255513, 1225743051, 2301315145, 1970642256, 2850715818, 3128888797, 2317420929, 2155667782, 1962983120, 2710186451, 648444928, 2272821232, 133989660, 3141011857, 1529770260, 802759102, 2173416392, 1305065341, 45650077, 1082105231, 1602486318, 3755990436, 1936896216, 2400713018, 1591016508, 4068454220, 3596573883, 2619324298, 33580971, 2286577695, 3083324417, 1169438566, 3225233768, 808739442, 2766243970, 3455083573, 1549857550, 3592398125, 2248831497, 3521856807, 1967034, 3078700295, 1346379862, 3820864333, 2903766704, 3884607466, 4174763992, 270916374, 3218398044, 3434381035, 159751999, 2768080251, 2464394277, 566049661, 442155673, 4112913396, 1456961327, 38309439, 1525792638, 2372197825, 1956558568, 4294769490, 3096019721, 2031664251, 3017984223, 1381760341, 4260655051, 2253457354, 2984264086, 1088854315, ]; let out_len = xs.len() + ys.len(); // - Limb::WIDTH <= 11 * 3 || xs_len * 4 < 9 * ys_len test(xs, ys, vec![10; out_len]); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_greater_to_out_toom_8h() { let test = |xs: Vec, ys: Vec, out_before: Vec| { let mut out = out_before.to_vec(); limbs_mul_greater_to_out_basecase(&mut out, &xs, &ys); let out_after = out; let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(xs.len(), ys.len())]; limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; test(series(2, 86), series(3, 86), vec![10; 172]); let xs = vec![ 4161517722334671206, 271035878974614969, 8768264966582261304, 8206956804546718361, 10016740860128464264, 2943682457917422384, 10577659840261915262, 12098681961003341371, 2525073961085508373, 6868684266500244649, 509821878609210517, 4263249474085213536, 2307565444887817803, 12419028787241261317, 1281995004584322618, 13869993964458308221, 4485392892470363180, 3274613913599014818, 13075432300049036016, 14042578030952079199, 13098932791585915075, 10142506622182970580, 7251838551095799764, 17051632328075633635, 14834683551906590335, 18022997779550454484, 13851155116066438974, 3279920275984726839, 12575373964173554443, 15489604937489489906, 12630529117895897413, 9562379919499143009, 1417878505992996127, 2188363987094684136, 4744951957683006311, 12112952790370550632, 313413052918057660, 952838993607855174, 5933080761807357068, 5875775551766205334, 10228588026136726855, 13111641204516926240, 10636665232562365918, 11359964631071199362, 5929704785320756798, 7890881054270407934, 4884891330151666074, 11055829837821054078, 13707765469312479203, 8153558212434726394, 17445193585880639275, 6568289716541023323, 8041757936108402209, 11089742802624534358, 9104866424438942973, 3236275382520001400, 9213626463300221545, 5359296447813232573, 2888775200925828643, 1504166968227419931, 14327007717613163305, 11802896026004225094, 12726419078417922871, 13309155468447837337, 8586421913645886721, 53962250520164792, 10299535356260218467, 16946113957982976032, 2902460381404773190, 14757465720632393328, 4285719983639600380, 8437230965528545912, 5716398831975234496, 1373020012523386515, 3326027605041066746, 17656221602314109866, 5927567778944922379, 7395768072445629410, 11551011221061348004, 13862329630891761456, 3443745263810155735, 497965567194021216, 13073929868627981515, 9340721263069758697, 16189911797862953019, 17331477506134450185, 18441976800868209749, 3733349995001197864, 6937510789920909911, 10459182483341515090, 16282716012969111817, 3142838808933013004, 176169927348158611, 11447076894000834768, ]; let ys = vec![ 3898028307372664956, 17056541935478225194, 14004255653437064260, 5500365157672511509, 15774417221201329293, 3229812365626959565, 1542674716041014040, 7356251598468809943, 18181760582149085284, 6447899299954117957, 15228766707939040914, 15272444333081468110, 8256864946368840840, 15131537266446006793, 15615697223616434527, 18149135087211146951, 6359898540214993921, 11306735121000975748, 10447887135010383963, 12772438236294882417, 17631737056955710770, 8945404460793598129, 8945720889114856152, 3648711115155303988, 4353348842999127960, 2258094147328762698, 17154005505580115535, 13882701371593165208, 1610163839528654069, 15350954595089578211, 2071555476679360064, 7797386300145290156, 12827100752536039252, 9294676638100895403, 13194197740670114341, 9490868657650122292, 13133123495028388830, 12350221742051084451, 12424378851382358824, 9807292823459903392, 10987641767148832341, 10914994897211362878, 828242546480310184, 18006801931269403354, 3042908768715701160, 8117699035539485321, 11944855102415629844, 7384949013429384602, 11066738683960763872, 14686958392900209441, 16412025437157422416, 1334344044228684681, 1631366399820348565, 18062594111889109095, 5175299421808157128, 16616812968596909641, 797326939277169478, 14593183003025528412, 3580961852669434633, 2104948106588459323, 14322976299272137248, 3536903766355663369, 6932211742640251008, 17616766237027326857, 1477865108082927148, 7817082715310166375, 16183969129154492111, 18146981620947356859, 11618268397687338183, 15294321769160092821, 2447614867702883346, 15261926111061449320, 4029723450982123355, 7820711996327940306, 6188156586792352365, 15703528769184364862, 6698415575574578533, 7770946582061166480, 3543987370105940918, 8845414905041844753, 13110356713999163167, 12862812457872444435, 10749027774576978236, 17822296942008093229, 13898152040175560707, 1879212271519144526, 5428215269251527991, ]; let out_len = xs.len() + ys.len(); test(xs, ys, vec![10; out_len]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_1() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(1, 1)]; let mut out = vec![10; 4]; limbs_mul_greater_to_out_toom_8h(&mut out, &[6], &[1], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_2() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(85, 86)]; let mut out = vec![10; 171]; let xs = series(3, 85); let ys = series(3, 86); limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_3() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(86, 85)]; let mut out = vec![10; 171]; let xs = series(3, 86); let ys = series(3, 85); limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_4() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(85, 85)]; let mut out = vec![10; 170]; let xs = series(3, 85); let ys = series(3, 85); limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_5() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(86, 86)]; let mut out = vec![10; 171]; let xs = series(3, 86); let ys = series(3, 86); limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &ys, &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_greater_to_out_toom_8h_fail_6() { let mut scratch = vec![0; limbs_mul_greater_to_out_toom_8h_scratch_len(86, 0)]; let mut out = vec![10; 86]; let xs = series(3, 42); limbs_mul_greater_to_out_toom_8h(&mut out, &xs, &[], &mut scratch); } #[cfg(not(feature = "32_bit_limbs"))] #[test] fn test_limbs_mul_mod_base_pow_n_minus_1() { let test = |out_before: Vec, rn: usize, xs: Vec, ys: Vec, scratch_before: Vec, out_after: Vec| { let mut out = out_before; let mut scratch = scratch_before; limbs_mul_mod_base_pow_n_minus_1(&mut out, rn, &xs, &ys, &mut scratch); assert_eq!(out, out_after); }; let out = vec![10; 905]; let xs = vec![ 6809535447687914471, 1103330005972507068, 372788324988356904, 3310988417383334329, 2768136713654061049, 17867128683005223868, 2238946582723710409, 3081056558438604150, 17026613024401611127, 1744473747933758430, 4884032754714318833, 5071706901657208751, 12689572021505695693, 10978480551041753799, 1800129976413451867, 16286820002622524539, 7281000574726170357, 4219678291438654832, 15700081839772688751, 15205907878248907247, 14393184334614991066, 14756848254875178077, 4793637008204029812, 9858797803427744303, 16884118866110086987, 2330774877124323542, 16233995226797389662, 6091870787973288330, 5905123672617126566, 6532637120046850310, 3781012952181700512, 1147955258215944149, 16381863291477272057, 13470194198585905847, 2807745192926696062, 10417338102018291024, 1182003379390951531, 10572015994470653864, 11256589899556451377, 7047560236256902575, 16809106838958682299, 8167397083217775737, 10405120914265859441, 6050515699222625782, 17283763639396397450, 12481792043865481917, 10515115098175408116, 3547231139273206009, 2955870806881464447, 81763485884574417, 18038197306999979657, 2697663113419170508, 13640328591104580425, 16380387086795482436, 5937997179794219672, 11280227770841311656, 15247718447550407960, 3356207189433327172, 9295483089881333487, 1048090603086884014, 17630347864859687326, 16292502783826501772, 2554058376409680235, 8746244974811121511, 13601151617020904249, 11424464616482878222, 16592787416774613845, 9541965809588758702, 10304263209519954371, 9718232210246640079, 3964199137038797179, 1133689222449100290, 11762544598027160268, 8892566166642784135, 4992855273094478682, 3467095579457639126, 17527051578764837605, 12788831523184320706, 15884832626408420422, 15445614371886990386, 4605408054811466579, 9468992277252416191, 16059556135741327423, 13703354904914355468, 12651524370372775470, 12076530382821868093, 9203720925482564499, 6751521177612318975, 14730048400600245248, 9583087821356332745, 7635737274166465491, 15909961927185268608, 15152412967792641434, 1117148048506231546, 15036765086001151283, 9461075977858154319, 283984775170615496, 10870934978120381565, 16402595751643852267, 13300950714409955136, 16269834104766854165, 3823800040156766433, 8001239710257605750, 8854456135465589491, 3559503577426585699, 82907824154359285, 10429508186090534661, 1795271336507026791, 16052612691484506490, 4449527904102534257, 6652828614119627650, 9436314767260323923, 14084834581845197080, 3924506166878684856, 4006253714000661354, 16835787368527074469, 2939573978616449941, 827685924983906914, 513438846841933201, 5499086145667050935, 5970432596053952196, 2357808915999726215, 13130152994826263557, 1029371010558121271, 9673453535289645591, 13630045027309361503, 15140438118448998733, 14475237670869667854, 646607524428232975, 8603154126726854477, 562632002079264944, 11132087168116199036, 712016548873706286, 1162552953778143562, 2720821187699295729, 12629405027198622023, 10085431077125120126, 11036408623217209328, 9412034889605831573, 3580947814659655797, 2384617485952276249, 11991332791506170431, 355732385395682650, 11957596579072080069, 7637503009753705463, 8641065560841157989, 5385185370436588141, 14613602605895034796, 16149929536213837897, 14926494841744326505, 8478550502351441150, 4754411934055301811, 8446559217491804253, 175563428577047295, 13317411913787179089, 1999388610388624930, 11997574948104529333, 7709394800320180604, 141106960118475071, 9185076664574888313, 14711830716786764563, 8646328906792567341, 6435770954980752754, 10889857927018380675, 4856598903599320278, 5559749328765755744, 55448005653193385, 18376290341644060781, 5411230779476997204, 3208977317832509473, 17939099296520163690, 14610289283912272679, 15727344360076838968, 17691225907664733828, 6277158099136871988, 6227268882497066304, 10537912046761025798, 4569425383713839933, 1540443185169512503, 8083699057632389568, 7713824171800942769, 8199521127345296820, 18024850838783811685, 11847360547777377558, 4462968389243655548, 3995475265600836322, 1735988164410255922, 5169863977080869823, 2205341702567171145, 2235183401932173280, 4237083636488253034, 8651273126396740151, 7677914001769310460, 2488550701988271373, 6362894001274871299, 6938141915629282617, 15289077957178314583, 11369273085874533146, 15146552950762343609, 2250130405529921684, 4507408042222997556, 12067657188384750699, 753594982979265248, 9819871477024072995, 8074675523776512539, 17863686634271613087, 10148559641897798765, 12078707926245944334, 16056144107847929568, 11477562644132166451, 633839849054735197, 1974937519863601198, 9431759751115500349, 16231263638095445675, 2852944099010004296, 10805052896366212239, 1090853228632071464, 5943661063504137996, 12279437176065016726, 6997180572817064008, 5167976820090909749, 7252605595265132660, 2377574067337995256, 898853472418766215, 15283250736100608687, 11681971203683297764, 15733049786589504720, 1874550821442898161, 10775751683446032879, 14346795044143203654, 7996691180178068337, 7988670994586391460, 15438536777951336029, 15583275281862893881, 1645086929138484726, 345744887729039216, 3687893952132688571, 10659362456954960532, 9602393538964870338, 16520689555988157334, 12546754178798486611, 8040849778898919845, 18425567932309437192, 7524804173796997825, 7482803818757957426, 2159381166607938760, 11953191500503254263, 11662381083106843270, 15954507061982303817, 2311355641538841753, 6262214959978467810, 3205610786437952171, 5833762588841339039, 9584891950834271718, 16431258786750754174, 11295777256302945260, 10262743010189168916, 6579167273633548585, 10655344951630924167, 12426159972843518796, 13809556914733676017, 10421408021758282646, 13742014587503715343, 1213383935103977733, 6155186430649126184, 180686018379637244, 6671736391598895649, 6711423272868884639, 10567222126096946863, 236255051969434496, 10538599139522078386, 1840416208489527534, 14920772374579070414, 12181583640158673672, 13150385378549419551, 2385161800547570055, 7427796248918503499, 1086611422915217495, 1034188908993802486, 17895224758095668351, 5605583861310416260, 8276090981819119594, 16774347628768167103, 4438689443393994418, 1445832965009646259, 12020209207509332983, 12101154623632027374, 15952145139262310731, 4569147745515423074, 1032438357998575006, 7719204784227574899, 7620365528941515938, 9134138337791325501, 17595820721307989341, 10837897611871188641, 3628300610284347069, 6056782082517998847, 11889121953261384595, 15658848261681587671, 760281128415892566, 9901843341271410215, 17997287540098693599, 11471174400256577350, 13773435664609284401, 224645455536727129, 3248370257584471677, 3402146064818516495, 15419892046652096835, 6817408051904455983, 13462567452174648864, 3865219578658340818, 6401692728490725482, 12241061753482985847, 18093898726091231688, 2085695270753393724, 1486152210073874278, 10962392580868374592, 18233050379629714175, 15440497426454102854, 17029248778709090701, 11943840019902256468, 1838494147415724342, 10624384750477063994, 2802400104447544796, 14482700272009891532, 7488752288284248623, 16689053330367821624, 8122258539396763672, 9378594940099937779, 1953829770254669263, 9095248272317331200, 8866691394084862202, 13201017990930506125, 5874101266603325988, 12758355031414108476, 10906401543018450367, 7070115242582431545, 8015463853343573521, 6337419761897564053, 8245569799737529081, 2143044650526073628, 10001469296387640338, 11129612211343148678, 9846592166231801208, 3293328206977069772, 8271586651454757561, 2516303987084978983, 18226852422794010543, 15105013013529789613, 18154225228636318154, 2013990863661732083, 1784747160358384741, 12567581004427688912, 12324983884662973603, 4935897487517618842, 14994876132441559883, 3460392282827044973, 178151701108469307, 14330685158880278679, 17005759398710652579, 12918079073431941444, 14737890013936547836, 13116140709796209375, 4406659418908136238, 12427086661031458855, 7492548499951595477, 16111633531233494957, 6547469955282364389, 10562100669850668222, 15418878616411295006, 4956757255402949102, 8013302230254643702, 528640010877453099, 14207088120532813066, 16751882716911936366, 7949419147113034512, 1638837693666608472, 13878268226712426549, 8273407385523164786, 11509174550235804944, 15966833959669295468, 16501367189938100697, 18237618137386130737, 12449896376279048977, 18110666911456042806, 3193062725115205782, 6188346541223558421, 8058450572610971381, 6102995183728564982, 1217219394955358461, 4696899915064498873, 3897448246350199671, 12662172956137287871, 6610124623177066401, 17355303367288349560, 2046855789488294262, 3211014904560014361, 17115241076245460723, 15298358927000333664, 9182539314691893135, 5164209594070862585, 9062044958688820752, 11123512834458221854, 2659061244791686400, 6806035717656270289, 1027290028815967628, 9405947735639936936, 2540349601344589130, 6895259978837037548, 8904474026325226434, 12273615493885622366, 8677764880724506780, 6002959367751808149, 13123965742105252412, 11735284964695785299, 2417001610052848193, 16769279424767143997, 7098399088498274096, 9910748236374366737, 11111297830299095939, 13640041663283902885, 15915174780574330612, 10929481089808875146, 4581632826936763294, 8581099749824253588, 12645736569302882821, 7359153121066395683, 114042912187761457, 8021867264848320576, 15492861144941287563, 17574065125533105845, 16374369432221228355, 10459169993431587286, 16366034776295832243, 2627084718398353897, 18099240392705942111, 4326916362018195403, 6552915731272193737, 4273219172539573763, 12682979794809012349, 2630341686377453497, 2883112777041844122, 17280553753834600520, 16523493292363775458, 4645653082909935710, 10857150457399097857, 16240900012104288727, 13936061320958754124, 7489056125188749067, 3240618672663587347, 4473897013556224538, 15959787311013455542, 6807910945586226902, 9410336371061067189, 6906088553149840730, 5605158148442495482, 884531864210940213, 1872297304786275835, 313522309067627421, 17334018801756959340, 1675436862731542012, 8842978529412038193, 16491099153488944340, 3255602365380029669, 4091823593236384660, 9059086866751700824, 18074592049968473162, 8939611511088706324, 2901954556715326677, 3168063820638083277, 9642457237234984168, 12973730047202029231, 12383420012085361069, 11980461635855055601, 815939574328079776, 14011981531029282088, 3819777392902083260, 3664266433302366398, 3842827072078938508, 11680613555445372946, ]; let ys = vec![ 15245088662193948010, 854969528224537163, 192457876290468361, 3156774054099849881, 10102117358735393641, 13923135497401538045, 15603007686998930972, 3707765480829539463, 1075990372015045994, 4440028045035707188, 779932550205535682, 13284596850012603887, 13447370325749987403, 10657005451799608034, 17344058779081327933, 1801131630646010099, 17879455113972297046, 1049662270419803525, 17887003202529550415, 13730724178286439296, 3086493866184691051, 7455503161286080904, 14945249663072669446, 7413071270018261565, 8165098975144402988, 15667870805615006559, 4534237642686726425, 5675059133984408369, 13542693529471369730, 4650690134857994243, 10593876026982724440, 8719234160809710444, 7340192483727047710, 2225660849988538666, 3260628781823840386, 14784063213821786553, 13478324037708856111, 6239844587086244103, 14508626048519473050, 11443816492520902359, 7084448144752764341, 11673478635762496725, 13444020463604694513, 1798574113181758005, 15195278749704748030, 3490272214933312037, 15632500462832370824, 9808665338648603851, 6377980234800091876, 11306384233660763805, 6392788317448223882, 8005181869701567455, 4601526777105113530, 9348184476999479133, 16105441815997897842, 15373735633778437011, 11733794529384137433, 769246272107807645, 2922899274256775805, 16218486247871807873, 10650657974127272786, 579665301817927565, 6403006378940431337, 10150254532952843560, 3736822004545760197, 10244207440138560761, 16631379436671010056, 17418302422321190629, 4844439457855539440, 9662799133272397874, 11622100630061039998, 11017257064923257696, 14025546287952884200, 1170766120552674008, 4852413824670160293, 18019298735978800767, 14042374992041286164, 6103187929964524269, 5988592592688695870, 5579172720281387479, 10738878044274955012, 8401646271610146442, 12016061916593958227, 14752402557741497038, 5053283107906893264, 12910662726197463795, 787526459034857809, 10304827788120361107, 8387521101013404665, 6030209567663971422, 7511028869236306454, 11105170944119024313, 2911699195421772292, 11710398806568443147, 7599646386487625804, 2146501359265516686, 1193294087739295886, 16419769173966961854, 14779980297792837632, 6286361066120350249, 8246126699673376536, 2339493649448723726, 12383521129608538925, 17459816050942292574, 7213741082075285427, 14702683527305456088, 17849030573001874153, 3273901152373442943, 10086273715179643444, 14351251935054659627, 3067622597087477151, 4241957707372911307, 16686513037697490920, 1503886102490162470, 4222986769290077389, 17209928444872897872, 10064374817012298812, 1391022681726221923, 3482099619102309134, 151151415131464647, 5477310851692317777, 8185741896741403527, 12297179519749775078, 6980896315258250234, 5491311995173541969, 10908311176531272611, 15140263006374103771, 16292302828281485620, 13488663273854028028, 17078235461511918753, 523009743565281503, 11105648925812514991, 13827146014280242829, ]; let scratch = vec![0; 964]; let out_after = vec![ 14914577666128062141, 12068273989972843735, 6116694005478833271, 3562611869773989286, 15670691724611128823, 7249128461000381996, 15151435496873338180, 13770931346629219578, 1187535282027344550, 16236693325430049515, 2991034239214163143, 6018061923835566187, 17284480928832658068, 14451687627520119240, 8458802009939241800, 3578663573390196265, 11053350197861111769, 10545908371462300770, 12247772832897108412, 4468839684066577960, 4549770468763696098, 17752125097317086921, 4544887864950226436, 2945143834276229802, 13648049166616052237, 12600592346334587273, 166409088005131745, 13013620684136565587, 676730163848086040, 12404388221407599051, 10705640677758869552, 4689698885735113463, 9700890479828306187, 9036861144548712951, 8094206411676899952, 17821082304555823758, 5054804670485674122, 16421357706067082536, 9704734314786980295, 13265421291054572321, 4619919032177510478, 9576547362592346883, 2025158308184190088, 4984956647828393866, 5567014476440543897, 7390123682276500529, 18303245037317000170, 4525541943295462130, 2509303616856320788, 15659980472438820675, 13570563127509629314, 13564844957739564512, 5956170799543933857, 14572147749185034353, 15936664264029850696, 3337746889684993302, 5339311381497232535, 791608983511277044, 8425434054207053106, 4098815735774818440, 13011885841922962026, 10478691500722275800, 288311354477678992, 16688724556777848799, 3854559944896493088, 4787579643539441431, 8914365544703418944, 14867687936657046038, 17948945926508777996, 17265394933400453261, 6520518082305967564, 6823369778027186436, 14260127132198472109, 5636179564496979683, 7510494946039669953, 7445089968619727375, 13151208295034342548, 15327531597402220486, 6165165423748958807, 7649301241163383867, 932300362699473366, 10332384620840363496, 1645779973200198914, 6819633096753052339, 8430257326959342191, 3365328330624946043, 17882376594601626429, 7931772344347882099, 12207106533717173393, 9553942214328281184, 1211963965695483236, 5986284857424925918, 1725008760284435757, 13885703170228952143, 679979762314983844, 2803926223916590493, 15129803423596480560, 5700355505192464858, 6737697386531803219, 11676336532156262967, 11219388591096271471, 6036126874875117221, 12759399619486488762, 1075627928411788278, 8986609583347352588, 315614912525710770, 2968976622267634808, 9398679997246989312, 7442449431966307944, 11074315772256995625, 13059753170473066158, 15516530300302448410, 6694913298086290552, 12225172653086039386, 14693751743728804585, 8946708930559907274, 14677397241988234315, 3209366617332728026, 6979717107269587401, 4941778982576664589, 12304520439559413990, 16634028143562183371, 8142239299779908752, 13355303957199352688, 16647311136213462709, 4819997788796101212, 2740900572266512222, 4917952099793992792, 15276502006380998408, 11163544344324054972, 4805821501449058572, 8031120161948062386, 9296985703342487576, 16564164538495558074, 4151584010060908718, 736580097771121849, 17811365526093310331, 3584057130812467869, 15343174508489570281, 6663904409520260794, 5148198311285516597, 5459037875257818034, 1732839752669203018, 5817171919148564506, 14532823584962157630, 17664910567425460977, 1606328717145502899, 7258676117087673712, 13564853056256859610, 15566073818913471128, 17505691249649149638, 8720681711808526345, 9299675336460004741, 12175130218583331200, 17275662125027429780, 5254636675017986768, 4584180635141974747, 17229718845518394206, 9903358674827047499, 14227884446253370289, 10238808006451695682, 15776343954783670697, 3568203177480129616, 10791516058691563224, 14667733988945443113, 4760849120471199172, 14824266274906749858, 4738766195452531583, 18201869520178488918, 7991042165868231006, 14001045459551827213, 9728825906169570644, 16356820821501653437, 4624890364800751139, 3202345381085270173, 10825323351814264733, 12844260821347730875, 17890471175274365223, 15983756164008599310, 9229389060056964014, 7980425933216172325, 14689445497065509264, 3947266856163410121, 13986662827479113948, 14086840354569963505, 13182084671726443227, 9173479010912744389, 4592278812024543534, 15484536985258289385, 12413608308331869638, 2694433334520487941, 1628652491883279350, 3020979365812132524, 4761921028454215909, 9912693764834406519, 14831540747828363756, 8079998785196191830, 11252016841358535301, 1583433672276669340, 3452712503195064151, 3057285240369947887, 2595743348455770874, 13596185098573058903, 11667772373252099988, 3692370881551772687, 14912011223264263901, 3289162294555844501, 11705734929820375948, 17609626782993672509, 18117255127345119328, 1604093155153663473, 9302755008283648290, 4607754412797627670, 2438148241672671544, 7767633059920523266, 3595119232557040143, 12437965844493362543, 5945493114625270416, 1881882682439839256, 12119104281808262978, 6340145747352803155, 13626236273901226360, 13270069380549785256, 15850889016963874457, 340925488865420050, 14028143098693299269, 3675481773099673886, 15132383794361616982, 12233631174234968448, 12037785574496977166, 10737440493925210255, 17968097042350264930, 17680205263988402231, 10859227415540706659, 1792989334549221826, 2177480830391393668, 10338369798118713206, 11542959090623521328, 15037173432548249812, 4664260954029694873, 9780024773679095230, 15423051572962932558, 9219085292170154212, 3117519792300278178, 15201618561147315107, 4493458887555315362, 7071488025555767928, 14797673892858036574, 15761839968701169338, 944266743877977151, 7946878991241141272, 11588285294320616520, 3085763786364505728, 382160258300824544, 5755505265595418236, 15139252786842523155, 3984606858609787503, 7067124810169118107, 11087518322251373936, 2145074716108216620, 13925513670821357445, 11473752360428444547, 3033405528387034503, 7582032677934023131, 6892449022193017132, 13657958745036075118, 6128417560891330511, 12848284770679740346, 13130020275156534634, 15464211076162624262, 5054410800851766065, 5483902692780184480, 4738318744782334997, 16867167009329238452, 2678560575986600940, 2615258434432884977, 7292976780151019583, 7128935031167862533, 18221899987307473439, 11248303633169678295, 12738639111676263555, 3155353877742869694, 16071495863264781073, 4264698448823081203, 7418994727203896067, 14811917097660163843, 7385790368475083290, 664373701990601810, 13483754102463667701, 7612123824094233525, 512453134520186948, 11691341684613561710, 13867096232148780503, 7687434174716142000, 6803483980923514751, 13342782916572404854, 8439201436522607326, 9757760943763629593, 5981970754483057908, 4190757094163155311, 5660547043969581137, 14325603855966161415, 8929633236673768270, 9297312576387550830, 1693558263949957284, 6836793952945831062, 10347383165146273428, 14661681337332505439, 17963531302478114205, 1709137293854005147, 3006720702657955228, 7329219772915910677, 17104100208631258612, 1949699737886797762, 17000436044616227003, 11324808183485510201, 13235495906244342819, 15749585439652205935, 13303759086698322754, 14891288338853864137, 2704605299240507925, 18013575082547999538, 2430267745104734440, 6179542971962498102, 16185308076341237746, 16642985193904420358, 2654686382891502775, 14166125840594907890, 13875221482589820174, 4356811139286595070, 7880657059321548510, 9955951238878446164, 17891804138739212705, 11829321244704294673, 11236151306675978093, 4831011344740993127, 15572388809599316560, 17846543352626240390, 7199845863441340373, 11121886749027339043, 4373695674384726918, 17093036459186744076, 12232005422016339414, 17131567018724437993, 16256199016182051711, 13475963188288260257, 911027923034979647, 6400295517498242996, 8837389249699670037, 2811700517251274120, 513035437159887251, 15619284911695136524, 399375572943822801, 7075743944967114918, 15672634271222934582, 7207711819265953469, 13693046740725554616, 4027434095315202255, 3539401330347027933, 14804329511729011870, 349324242806502305, 9296277440807870703, 7176700326904811702, 240113067969972951, 8383831921575151446, 1722116363229832243, 11612954111300504655, 2215733152712733871, 13493183699196154480, 16071186765983825953, 4130784068501749192, 7338573984508524547, 10825001941195956075, 14997934222654203001, 6505703712429055284, 7221915757982082460, 1275601006259924603, 5672514881351973473, 14882830470570010681, 10941637348461954999, 9488919083136123898, 14043552860848000866, 16822079753245337019, 4714248213100277643, 969715273010037797, 15521864292227188985, 16073105970793932270, 15708820798300121289, 13898215817316628619, 12776496008354836588, 14999798045466993632, 3260898735577297939, 13139436153787118831, 13332280475731022238, 17383012290790364040, 2995641007327542345, 14136727525433141277, 17334568127137876546, 16958828191205021632, 12417369554667951160, 3090518852098624195, 13657230135070531823, 11743085280276876203, 3114616886140581544, 6043287503993377429, 17550757261658589945, 17149590190690566703, 9103040591046283294, 7946146551153766574, 6328750617512334061, 7611645677682650836, 15633620719663274568, 9212436143674176261, 15788907043061834348, 9498761316246368036, 7352496413262997914, 9095543535942948357, 13109519298804112825, 17605710606152813899, 11836475532966293267, 15936748974921397105, 1111801049346591026, 15762144272111321164, 13004674117006965866, 11908453630639663926, 8672383672749866782, 2088248899380502026, 7296610571351867175, 13755695345060796205, 2999982423435890541, 4129519642079256449, 12622156276462967022, 7111496398765881581, 14480787311565160150, 3469939266209117746, 7438701329152033623, 11629269482462741856, 4885777542024810464, 10705129561986474549, 12704646697057875, 6458480273092609348, 6552269679491575287, 16764409845541378365, 5112781772516022587, 8008989787537536761, 1103584530948037829, 16382841334779146359, 10554805089071823936, 5435260964051060833, 9791508728754514420, 490382068908134805, 17435419070710567937, 14195398757764953304, 2963888499740999291, 4662041165840469949, 6744621662455431846, 13427204268640870135, 3887747288146601313, 15443876414310792510, 14209765039523837918, 15685162874875886369, 17718873723062454563, 3899085415479325935, 8112448753673506965, 9870640447409364221, 11832870733499002257, 12563697741369320162, 7101757806260064829, 8836333095435223130, 2301074177341928226, 8276824997793946999, 2827834280767843126, 11204234843351418659, 14057032714422307544, 16637779355549534512, 17293043019105638911, 5235444579393367735, 7875158171121328348, 12032932633735348172, 17577724652120330660, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ]; test(out, 480, xs, ys, scratch, out_after); let out = vec![10; 905]; let xs = vec![ 12477471680342457016, 7439834363175998259, 8364531072478531307, 7720669117264982572, 13871089126608066865, 5538739089658515009, 13485862549968349516, 16668965138415286574, 12815918125584966674, 14984155091932260860, 16644766636646585123, 306590725006293979, 8429368518159297616, 9218529725576681069, 15016741949480768499, 1670879514738013725, 8417955162372577946, 15387720484925756369, 5110476884223883348, 1816362467650579730, 6344760880304946457, 4582050077501139760, 11544561500401244826, 17507375286136941082, 6780825611959218867, 2173592718397418409, 14895320899302250577, 1732130437372403944, 2652228013798656770, 14059887082577558829, 17320142963333434007, 14639018477416372959, 4436670787324500429, 5494397060264160564, 14648982379079464056, 4281784633461453767, 6798187094949642558, 6608877920405717218, 12631712797504769978, 8551308273612802041, 17246776198396440310, 6444397599333607623, 15925650298696285563, 10601768410796015631, 15000906276520941112, 3338797399168993953, 1246352375954040582, 11420394385271506024, 17068095307090480528, 7644631914604520606, 11033781661348318008, 11117169690184835735, 258761790873428567, 17489901188933003933, 14840505235785535230, 13227413113638715481, 16997698053799118525, 9019797589817151925, 4493694255366969932, 9725237995968980495, 15577413875064628551, 2280312394933338862, 225569847977698671, 2323301829890963353, 10256874123357921822, 12539122566148296448, 9989537237723725906, 6811992642529374338, 88727847633051669, 15695593575052197094, 2761202085861005143, 16533039048484256106, 9351088285086271793, 4055478109313752276, 10213434408975318081, 8762684020269433141, 5837079994402234584, 16514518402377369291, 12378208937452956180, 14421807887515276362, 3988627559762405319, 3918544582422029230, 4755956678288947720, 9676877814462397554, 224961575368542488, 14611489560386313010, 5196486534973110781, 14213777193365038984, 4602978866967803674, 11003619085742827120, 16763677630294953394, 1684559030448096764, 17767374982649848838, 4877949630873126245, 3682814944580280752, 2561235719818456295, 2364934896956055350, 18263613281445563076, 4089114060737928308, 1871768083735193579, 16678770828678552573, 4414846026098045432, 17125831209897882395, 3912127090800830255, 14011181803889192282, 1295043426575781791, 10420967703804408197, 6199906131836288010, 11807153033347357192, 14265899593105313257, 8147605267573587369, 3295330776500509264, 16732577613226211515, 3630606949899242603, 4077531443619740772, 11812426165247810337, 780989759563676061, 16843715221613475518, 520503200629457264, 15698734581373560858, 15717047446773117386, 11739182472950746776, 5508507755766772851, 11277744890514126849, 7102937323315103744, 15043426316219001362, 17264933403548961444, 4786858792980655802, 2014728966166520846, 13049152613696846196, 8986797982833879405, 5686978963676857351, 772150166774986658, 14517086870053753709, 14954116996489490375, 7746391697910526188, 4606434146793009376, 3009553593220536962, 11834331104428006940, 9959812709547803325, 9312818550721389795, 8167722699792448458, 732874657192970052, 698773781905867242, 12119405880051172902, 17673033350796167980, 13538870733321508367, 2664725175527539380, 7636536994105874784, 8629987496621113680, 2000550558774774739, 13628751714628702436, 3345724186836801042, 5296651644730514746, 15440075910536479523, 11566524344598274755, 12142530999548267726, 3178476168461706193, 11231993373182544616, 5535836762655782188, 1821857691788680579, 15398067123112832375, 2959937906512595934, 9894128090659796945, 10977676213479413606, 9896053141077387340, 4732359585478105829, 2782537058538126590, 16748650113511090469, 16234573623069140583, 13526364553240274764, 3472042735026885459, 1375504011635585658, 14134901088610758184, 5812986093773998116, 18343907802066284210, 10338195362284836496, 4538933452393836273, 7202972851508573831, 10663048845744919725, 11111095559628771539, 15813947556665176307, 3844063447234634925, 5652338735091822320, 15812061039848958137, 8229753298839583649, 802923134917039889, 4829163585440544772, 15429176731296846429, 8019558793413477543, 1452525545607666514, 15573790577533593753, 491936016981197942, 10062863560179613545, 11061384784011621889, 1900052214617990619, 7753731008479284745, 16019010346473083888, 10253841258470892164, 13903408453788781151, 10169884958783022914, 1771119784479465694, 16876761255984683913, 4507734336556855851, 1644190668914968903, 11524855357000701681, 6768296219427733234, 10057582861726337550, 9899648217778374596, 18140808584162437045, 3502136377186507090, 4607134693582048621, 13936949880580583914, 2596788772608678076, 1796713826239012327, 4260582063129126187, 5748801488885906379, 16694615442676144004, 3887305188180051618, 2550350767205712363, 18068173339311621649, 12758173303022710234, 9740862123276893551, 5102010307820377604, 10942936333209708005, 18421941488948996650, 11388637231777062032, 9127668535392226249, 6469837987038520357, 14193922743168722337, 8879463076013852218, 1299536255974471810, 11657123384643255381, 7261659951101262301, 5894363505946510117, 4245862285394351605, 5678371230350087802, 17178046578086915046, 5767351492432132301, 2765778331274782081, 5032104048099942935, 17629257268172754881, 3538476034090404567, 9059696921132002704, 10148267678588608063, 7431557905485244392, 17701219837659593435, 11179519028472592747, 4072852058212419917, 6998722206646617171, 4881588377784087158, 8942392135657118187, 12450098984983403167, 4877380715364130438, 7442425351254657978, 16893368119062256892, 4133190116578139434, 14033231224823505685, 17690698791038106309, 69885719555671168, 5451291976155541960, 7641909931651695485, 14034042004808926588, 12720147227862124510, 12957030947591398482, 12124026692922785247, 4883408107294185147, 3308537627824539756, 4406371143811003270, 17321810257306281660, 5243104860854009275, 16431126877381187748, 9754896554997520777, 6749101884247660127, 6263295512058358448, 8583119091158463486, 5555416137611535608, 9162144452187531823, 15840624178481981270, 6187472780701357377, 3164204801472770089, 9460961259991884760, 12198117330023239045, 9445542084090344416, 6826521970103491663, 6996442717256261847, 7363775912789871847, 1821616883363314737, 13718695280220668528, 9265991471759860428, 15403328465978445840, 10435756695146507564, 9134138337791325500, 17595820721307989341, 10837897611871188641, 3628300610284347069, 6056782082517998847, 11889121953261384595, 15658848261681587671, 760281128415892566, 9901843341271410215, 17997287540098693599, 11471174400256577350, 13773435664609284401, 224645455536727129, 3248370257584471677, 3402146064818516495, 15419892046652096835, 6817408051904455983, 13462567452174648864, 3865219578658340818, 6401692728490725482, 12241061753482985847, 18093898726091231688, 2085695270753393724, 1486152210073874278, 10962392580868374592, 18233050379629714175, 15440497426454102854, 17029248778709090701, 11943840019902256468, 1838494147415724342, 10624384750477063994, 2802400104447544796, 14482700272009891532, 7488752288284248623, 16689053330367821624, 8122258539396763672, 9378594940099937779, 1953829770254669263, 9095248272317331200, 8866691394084862202, 13201017990930506125, 5874101266603325988, 12758355031414108476, 10906401543018450367, 7070115242582431545, 8015463853343573521, 6337419761897564053, 8245569799737529081, 2143044650526073628, 10001469296387640338, 11129612211343148678, 9846592166231801208, 3293328206977069772, 8271586651454757561, 2516303987084978983, 18226852422794010543, 15105013013529789613, 18154225228636318154, 2013990863661732083, 1784747160358384741, 12567581004427688912, 12324983884662973603, 4935897487517618842, 14994876132441559883, 3460392282827044973, 178151701108469307, 14330685158880278679, 17005759398710652579, 12918079073431941444, 14737890013936547836, 13116140709796209375, 4406659418908136238, 12427086661031458855, 7492548499951595477, 16111633531233494957, 6547469955282364389, 10562100669850668222, 15418878616411295006, 4956757255402949102, 8013302230254643702, 528640010877453099, 14207088120532813066, 16751882716911936366, 7949419147113034512, 1638837693666608472, 13878268226712426549, 8273407385523164786, 11509174550235804944, 15966833959669295468, 16501367189938100697, 18237618137386130737, 12449896376279048977, 18110666911456042806, 3193062725115205782, 6188346541223558421, 8058450572610971381, 6102995183728564982, 1217219394955358461, 4696899915064498873, 3897448246350199671, 12662172956137287871, 6610124623177066401, 17355303367288349560, 2046855789488294262, 3211014904560014361, 17115241076245460723, 15298358927000333664, 9182539314691893135, 5164209594070862585, 9062044958688820752, 11123512834458221854, 2659061244791686400, 6806035717656270289, 1027290028815967628, 9405947735639936936, 2540349601344589130, 6895259978837037548, 8904474026325226434, 12273615493885622366, 8677764880724506780, 6002959367751808149, 13123965742105252412, 11735284964695785299, 2417001610052848193, 16769279424767143997, 7098399088498274096, 9910748236374366737, 11111297830299095939, 13640041663283902885, 15915174780574330612, 10929481089808875146, 4581632826936763294, 8581099749824253588, 12645736569302882821, 7359153121066395683, 114042912187761457, 8021867264848320576, 15492861144941287563, 17574065125533105845, 16374369432221228355, 10459169993431587286, 16366034776295832243, 2627084718398353897, 18099240392705942111, 4326916362018195403, 6552915731272193737, 4273219172539573763, 12682979794809012349, 2630341686377453497, 2883112777041844122, 17280553753834600520, 16523493292363775458, 4645653082909935710, 10857150457399097857, 16240900012104288727, 13936061320958754124, 7489056125188749067, 3240618672663587347, 4473897013556224538, 15959787311013455542, 6807910945586226902, 9410336371061067189, 6906088553149840730, 5605158148442495482, 884531864210940213, 1872297304786275835, 313522309067627421, 17334018801756959340, 1675436862731542012, 8842978529412038193, 16491099153488944340, 3255602365380029669, 4091823593236384660, 9059086866751700824, 18074592049968473162, 8939611511088706324, 2901954556715326677, 3168063820638083277, 9642457237234984168, 12973730047202029231, 12383420012085361069, 11980461635855055601, 815939574328079776, 14011981531029282088, 3819777392902083260, 3664266433302366398, 3842827072078938508, 11680613555445372946, 12778807841055009071, 12110239716506060424, 10455001326219377212, 14037063373827903372, 7343791660755545799, 12328389593346708858, 7199828106464912509, 4858835493732869191, 4210694898816644452, 5207062729711049186, 6686010191777285325, 4765116176650914771, 4260203503346398077, 1759950825465072730, 5230132100642234984, 14615940487884510813, 17309789486063144027, 7278701880222450078, 10589604955548805402, 13389545410598327517, 8048423454310044609, 10174798177374038317, 11695819581512336602, 10798166591000354836, 10103293254150868119, 157182158726905133, 1338674327495139085, 4359740350600884386, 3252895658818469796, 10919494111178843097, 4907614062557818120, 4955680854509122805, 11945192504152771627, 7975797138321745283, 6605506887556783622, 6135553468556837256, 12830560358150860589, 3963138074064936645, 17071621175761233015, 16942996036353652149, 18009074714271793604, 1722999483884168113, 12926214689279125494, 13895491362136161766, 2282857362875456337, 9142994644696487964, 9268762722221367534, 10573580827711251601, 4334519573500535534, 10883875644989605426, 7004415645651661648, 10027237496943886389, 13381566800231151857, 17337229971572030119, 9544236017718236057, 16499558730912147790, 16696764467460841050, 12783153673325726862, 4801788834514363554, 9769596680827455135, 2052933989795058774, 14012190388893162910, 2328488528431981564, 6422943144920158158, 3344277493662982427, 17332086124044133390, 6603250179050887938, 2729973167059384364, 10215535361886902702, 12469382708903994601, 1202997051177792035, 3047394247674395800, 2411456312940888474, 4837088057329031859, 13226164937828712217, 13151155632897757600, 11689971584362603020, 14721057194516503031, 3506623688955464241, 1023806484371714024, 616780495049061260, 5550447694830386961, 11303599457452379703, 4026477090451957914, 12426562795004232982, 15911784896145106699, 4007234390509453717, 10984488057956831607, 10127069533632441573, 17026212809323057241, 9318803717581063712, 14225402896737171843, 15831782058852344212, 14685942491342656916, 11353950141420870530, 6899840258039698024, 16365793951924111762, 11054065770384370104, 12313481690905923958, 11429182630674761557, 18037807349797853208, 17855698087768272616, 9322152574069274970, 4942329044664759235, 7995065847246945033, 17234608471288129109, 8540482286126463, 14042109278380290397, 4245459658137149297, 8630372384706772616, 16951967420255591896, 6140983990759814658, 15799001042328537181, 293899216979442252, 18375466344090472198, 5023361203279264131, 2158584219052773880, 2430714777079983012, 18439679719922027552, 8247095638003041692, 8700129222990386425, 9065370516758531054, 7621645239059490705, 8198370193753546038, 2570516211974541846, 17033362784799911757, 16322248788609588904, 9688378877889012051, 17078622631971263745, 14000745586739559896, 10022578092954937154, 5445108204439341684, 18386610455808271244, 5092210157433941468, 6213448264919356969, 4883013329288095834, 5478996930332110750, 8026855029996672366, 16024447858887376249, 12067879178821404087, 11518543008940438069, 3823610091713721972, 18069601801912264214, 11258822797166212826, 13964841203412084177, 9414776283754541624, 10293058710824631389, 11948877430367495415, 8513392542107963113, 6296507345123212825, 6477999943576666411, 9572404293136150991, 5100835030655003210, 13325655857556084165, 16324080076960251181, 8879608339499901790, 18301788022265813222, 4530918631858474410, 7355857660645482071, 3649239901919106124, 12889973024998083984, 11695005857389286582, 3475833048468156819, 995729836358583730, 12325666763829458288, 14110440261397920019, 13769832493884639171, 15593753283105934190, 7109324739675458351, 5421147768472920505, 4412734743279888925, 11138246548885387220, 14351840348441253310, 3556324819053975644, 464172005362873872, 6330105154140333710, 199716684476189301, 30491931320003660, 12784214407370490288, 15867394285597021458, 15049472685881722845, 10832317644389672128, 14180787391549176759, 6195021812685555238, 7097651423104249027, 14212466040470804288, 933065029493216032, 340700391640325051, 5222909044979876332, 12662368682228247352, 2784558090880586519, 11524226622572698014, 7185977984788112517, 10872431215518209444, 13748253290972801025, 5038089701011291997, 7535346948699029838, 13797006813111000874, 4892711692291451444, 6793466025450692149, 12784267157149526257, 10296537403905285004, 2323577800704132951, 5312137140467217143, 6430484854861543636, 6338831277270911406, 3380263422470065531, 2021125064519606784, 6156495890069554972, 11783498133679281022, 15578447545577779722, 15814546899991104192, 13941553944244468050, 13634474865486767598, 1056230272770991969, 6544470833237086052, 13788795813455716701, 7695789694537545607, 8392131987884965107, 4446829805611351645, 5546547554488839716, 12941176365951974041, 11083456017770653320, 14243587238307940226, 4340314402890900681, 11706773788443852730, 4344412554812442687, 11193626359760223528, 4305913696407512521, 152872300974481317, 17563972177873767735, 6689134738611919649, 3781413393308080648, 8321615330761631580, 14197467496901526225, 14546626676044239226, 16456266795492152384, 11928059952577597101, 3835042046532738036, 13754911224713375253, 7514650130698543676, 8858336584435716580, 14887091898219032624, 16911851326374546737, 15781280213878900978, 13174567334832245983, 12698715736553212443, 482862054634250522, 11881655003769883900, 13759377508601776198, 1380626582194380651, 12709962724490385600, 11830407677567487487, 4707511235470141279, 8988833435496096196, 12849153210950239984, 6129552893611029481, 10992680122519594516, 11411390234302369473, 12356274253287847627, 8358264938578134057, 2779498090106587161, 18154716656404340371, 6939980780951404838, 11644899556767279317, 6503403399166403612, 1788328284304710501, 3402885645044344883, 6160850982285943593, 1361188868372704452, 5295494278668069110, 3856033404817891402, 5165875819581549636, 5432481755911013545, 6887089866491061103, 12248786783098658185, 1872380111306967890, 10371211044437237288, 3640308804221372831, 11707751977394310973, 2441379059837646171, 17261873795536786450, 4576230298744928057, 13439891433013201618, 13066055068615706211, 5023766490253071135, 4737378710842155527, 14130528255898995994, 9297196539004306162, 10213190959948266193, 10762620391958680674, 15631352907504559989, ]; let ys = vec![ 15245088662193948010, 854969528224537163, 192457876290468361, 3156774054099849881, 10102117358735393641, 13923135497401538045, 15603007686998930972, 3707765480829539463, 1075990372015045994, 4440028045035707188, 779932550205535682, 13284596850012603887, 13447370325749987403, 10657005451799608034, 17344058779081327933, 1801131630646010099, 17879455113972297046, 1049662270419803525, 17887003202529550415, 13730724178286439296, 3086493866184691051, 7455503161286080904, 14945249663072669446, 7413071270018261565, 8165098975144402988, 15667870805615006559, 4534237642686726425, 5675059133984408369, 13542693529471369730, 4650690134857994243, 10593876026982724440, 8719234160809710444, 7340192483727047710, 2225660849988538666, 3260628781823840386, 14784063213821786553, 13478324037708856111, 6239844587086244103, 14508626048519473050, 11443816492520902359, 7084448144752764341, 11673478635762496725, 13444020463604694513, 1798574113181758005, 15195278749704748030, 3490272214933312037, 15632500462832370824, 9808665338648603851, 6377980234800091876, 11306384233660763805, 6392788317448223882, 8005181869701567455, 4601526777105113530, 9348184476999479133, 16105441815997897842, 15373735633778437011, 11733794529384137433, 769246272107807645, 2922899274256775805, 16218486247871807873, 10650657974127272786, 579665301817927565, 6403006378940431337, 10150254532952843560, 3736822004545760197, 10244207440138560761, 16631379436671010056, 17418302422321190629, 4844439457855539440, 9662799133272397874, 11622100630061039998, 11017257064923257696, 14025546287952884200, 1170766120552674008, 4852413824670160293, 18019298735978800767, 14042374992041286164, 6103187929964524269, 5988592592688695870, 5579172720281387479, 10738878044274955012, 8401646271610146442, 12016061916593958227, 14752402557741497038, 5053283107906893264, 12910662726197463795, 787526459034857809, 10304827788120361107, 8387521101013404665, 6030209567663971422, 7511028869236306454, 11105170944119024313, 2911699195421772292, 11710398806568443147, 7599646386487625804, 2146501359265516686, 1193294087739295886, 16419769173966961854, 14779980297792837632, 6286361066120350249, 8246126699673376536, 2339493649448723726, 12383521129608538925, 17459816050942292574, 7213741082075285427, 14702683527305456088, 17849030573001874153, 3273901152373442943, 10086273715179643444, 14351251935054659627, 3067622597087477151, 4241957707372911307, 16686513037697490920, 1503886102490162470, 4222986769290077389, 17209928444872897872, 10064374817012298812, 1391022681726221923, 3482099619102309134, 151151415131464647, 5477310851692317777, 8185741896741403527, 12297179519749775078, 6980896315258250234, 5491311995173541969, 10908311176531272611, 15140263006374103771, 16292302828281485620, 13488663273854028028, 17078235461511918753, 523009743565281503, 11105648925812514991, 13827146014280242829, ]; let scratch = vec![0; 1444]; let out_after = vec![ 7119213209737455664, 8035111372284977647, 4572010150225077091, 9836693742249819546, 11913987255489332987, 9795418934522178134, 12039823881052227957, 1703597587030553464, 17173440207558913559, 9133942906034722304, 9892190423857277000, 11450449925285493571, 8229203118528410575, 18272483595874326782, 12286453845032957559, 17397683281593428252, 17307726796177375265, 5885130845879194191, 1645176018776340060, 7680193366109147043, 16734119958955208667, 6536578624341273644, 5770440598266592917, 843542653879105004, 7846103239972868550, 17767498093293336141, 8852927397266500772, 2375241440134626999, 4434060166952587700, 2761540810749122567, 1453459469045559424, 12942116308370467698, 5506016901067697399, 11535214645442000706, 15126978367780356744, 12154399742028506377, 496043512841547027, 17912935272640820199, 10986022757903652151, 6556183826080645558, 14546786726747802513, 12005748109900862598, 7028659269647722317, 7445941872312834859, 17378556553372415985, 6579722616703715705, 15110932971155985188, 13357716021096701878, 14805225292079398749, 4846395190680470669, 5496704586153785876, 13902332896674228944, 2782564501691101676, 12874276640173358887, 16083587358039033190, 18355037119147466217, 17905645348986250355, 17336266670070672432, 7329875537940689357, 15143929848768191816, 2335192162346001268, 3675321604843848800, 18055470666128734882, 7825904415481215047, 5109358240684702569, 14285416470839730663, 5712671120250540046, 1447875149083639731, 16825523458715974110, 435887853762049989, 6289440856649262026, 5079567923272969509, 11992232716208537238, 13597285185096130255, 11829047305733652617, 4311086504067261381, 15175721011032302019, 5062112127396725677, 5556662484107594780, 16961425301235550719, 7249744124354557124, 10415169108908960370, 10792331692568535985, 14481109731941072963, 3493798658848957833, 3820132639380218489, 16270989634898866497, 12612959379075825823, 2261231936675595340, 5397727033090527090, 1595530071661307000, 8721991197262817968, 2097281716258616855, 9720159116732069000, 13847028604290243745, 1259097204603535157, 4488418560755904013, 6367333815591827979, 1110836537797269745, 737322139420954828, 10719862516375734296, 17641235722877078710, 4007603116973007245, 8186031591789355966, 824809602592127358, 15459023162084506830, 2781779707947579519, 5340603447447048495, 10487772282235399213, 139590844844775293, 8448523529988919651, 11294430762236913551, 7417787798712521690, 7898687579828307114, 460432324038279684, 17287858692967790320, 1003171402208274758, 12432863151610498290, 1772583694811023620, 2398714257155470903, 14638551745572956179, 2453888832037177615, 17965720127679021564, 3482752704874523706, 9460983625185291928, 7861173646556463420, 2092158584793655622, 7860343108590151278, 5798668224892394938, 14344358780928405264, 8930780312248882738, 2041974908151755313, 5267057435060043630, 16349241761951706605, 7937085583298782596, 1533874153792017121, 8977390985744119243, 8213952522673826258, 5985476232972805345, 1767819075525805690, 7890652703767299436, 7833570395707421953, 16483497150383186636, 3111844668913506626, 10592215978440849992, 15760470899502034545, 14841199295755801240, 13457358926996905771, 8495921566729048945, 12384251008552336501, 14611927430049516374, 10145411926842313555, 13313983588964854484, 6522555254793521962, 14886168792472123947, 16563223991574184817, 11970636068147089860, 487573490069849866, 14517767327925834099, 358889874180177533, 2722904686908914583, 9331922038722423702, 10427207646299323058, 4058944134252549339, 2943158119917296684, 10957133362022867886, 11807644687289257630, 14152770343532942991, 644765569764633457, 12835933538365183555, 3489836693155058202, 7930565595074376717, 10663397566559525483, 10415977712042153468, 10629891694308728614, 17218729211483121702, 12882631064819497692, 11823247409777216976, 4429760090149085341, 4992836119218612253, 16968182235411645979, 2833341723517409131, 9437468414857756700, 9342501551191707874, 5401538590112566847, 11565576817184943683, 17418902749314320121, 15515057935262510, 13023198767155479105, 12322345548326767749, 9805678358507392118, 15196802879249030007, 8590456626380559194, 12181129450616746226, 4662360147888268775, 7743459026687301615, 12227881705402238521, 4104871394210118957, 2982631795273577607, 17405629239503027027, 8575042458975896270, 5499669298608315445, 455410535869802297, 7801072276748452974, 10258654969684304036, 5019332302330169406, 13851706526542678368, 14388718431838510370, 6994627771674318027, 5883188522176688608, 6953100454027368107, 16730449049154094699, 4479760571164126224, 2442817149002290432, 2594209501779693152, 17000985552959046155, 13392630901869088171, 4351699921480478565, 830530327244063521, 6175340290035796626, 11478838337470764581, 4282543001913023167, 9749956107550685821, 2694451472405341333, 14159005131955878971, 188623324081031138, 2113957709622881014, 13346278264743742220, 1490312624045928630, 7257319265988714790, 12897840546280054308, 10261220359148798170, 11623514965826520552, 804176158748924112, 17254294564975652336, 14961613837993764505, 17022609814041542140, 5050795566934959858, 3133859061844734723, 16471861622774443737, 12873904550161604219, 8955720228538638459, 6705947195280088455, 3312252979433304494, 13064308724359909641, 17877454778920390520, 13974626528815595051, 5830057811107410067, 1680557938316663873, 5360522541537691866, 16002353064982324832, 10193786265901148495, 5965825498900060524, 14004637605477595175, 13444980433515313059, 17123381832713041503, 395654489392928755, 17905210858022857309, 11695619457011399410, 2050293660264041357, 13214005508111947011, 13721733314071779620, 6957322551477640013, 17200941870372170988, 10377268746838169434, 17697877660887283146, 13909454659468606094, 12263365692987306251, 444868280971136448, 2249487486097442707, 10287367344673627295, 15227830943213591291, 11384605430871297252, 18114267789275369190, 9609419984349670064, 7173216608425317330, 3785723985326055000, 2525275194754047614, 13535151049834722889, 17273215075095328812, 9379065185520973134, 13156080046058576550, 13809311185533464020, 9698193583022285357, 11293045682332858022, 3789086099334034431, 17423609786192009535, 8700938259391751384, 6754612211313466065, 15592171130416925401, 16281409111498332713, 3330243176102830812, 12431102122589837326, 16006104650687086798, 5881832849234936462, 9558494019188617372, 5910373903796225502, 7012489078165397708, 1678461096818873552, 14039349728684147747, 16767452777528123993, 10223391806015696982, 15346818030164147356, 1162766693101697053, 18234451668077951680, 8347242572094928214, 6666731739952625453, 1062103725054959015, 2916817885872081012, 1252775340062153472, 16701352066718298728, 9660144340038428104, 14959287155729434404, 3349821657014683971, 14124329647242713467, 16768224457728633355, 15245206340382728113, 13349975818727705647, 7060168455288126345, 14358009543123557047, 1671493412977635062, 13147000836819401629, 18412981554162763098, 11420833773021925355, 4462121868113237202, 3673613052681393780, 7933932278185611848, 2994094088837084031, 617851389487072906, 936087254346174626, 6282395350939998602, 5564739907135838574, 357676340385459789, 4488114251655788009, 15267875158424192348, 2784291869179885450, 11312568718856999737, 8569642291350942890, 2238202569818012692, 11656862683686826121, 15262363620109289295, 16524990113573459437, 5562790604256723201, 3345369486980494832, 12006274934570630789, 9946114845665174629, 13671323181231836463, 3970220369626629149, 7776022796090455195, 9590755788237311534, 8142856981292265441, 321465156536801162, 5953069648150855351, 16986574134926902837, 9332812118546582409, 10453305700229109136, 6745273322860959577, 2992371413743712642, 16607737435713483528, 6982491039985356345, 10635374366254201081, 5489787617426825481, 16512907085669471327, 12008394332273820459, 13681713057282914887, 1825484281011599499, 10265338194463676800, 231895184071445598, 8684485436743230364, 18314390632816293564, 395173997200045924, 3458959778923434284, 14875618389446705178, 2026228713879608348, 8096896632351243884, 11898068926472226654, 11401424330286284371, 11388179279009736427, 8567780769863850951, 5420955600339252740, 9557718016358557523, 10293539895922743855, 10709104391440822839, 15398390488930753996, 11609873443226591907, 3799303761026674488, 14827504231551333743, 5857678196927724111, 8450122285857845619, 6120869104368170858, 13208767594813061501, 17440504615103435089, 1352314430040358495, 4594662627540876693, 16103658665190650049, 4604995467068533697, 1965756000963933588, 11590357129340578915, 10706020607921767648, 435959974903581847, 8114156514383604689, 150635546028022237, 2046711193518988780, 9302159929442525204, 4102862072533955538, 10755931112512381521, 13759570670120566522, 11886492672468308648, 18368564319937059130, 9170256735689590352, 89744806848865555, 17004092425291241458, 13341437623654656084, 9602103451691077650, 805686450066544356, 2830839197815761419, 1956329411504418821, 1856751313451126046, 8360952867730129523, 2655094640585883682, 1812351508323318765, 5466452692324458722, 2317993471554330319, 8386109932957812768, 191643434261986870, 8672383672749866782, 2088248899380502026, 7296610571351867175, 13755695345060796205, 2999982423435890541, 4129519642079256449, 12622156276462967022, 7111496398765881581, 14480787311565160150, 3469939266209117746, 7438701329152033623, 11629269482462741856, 4885777542024810464, 10705129561986474549, 12704646697057875, 6458480273092609348, 6552269679491575287, 16764409845541378365, 5112781772516022587, 8008989787537536761, 1103584530948037829, 16382841334779146359, 10554805089071823936, 5435260964051060833, 9791508728754514420, 490382068908134805, 17435419070710567937, 14195398757764953304, 2963888499740999291, 4662041165840469949, 6744621662455431846, 13427204268640870135, 3887747288146601313, 15443876414310792510, 14209765039523837918, 15685162874875886369, 17718873723062454563, 3899085415479325935, 8112448753673506965, 9870640447409364221, 11832870733499002257, 12563697741369320162, 7101757806260064829, 8836333095435223130, 2301074177341928226, 8276824997793946999, 2827834280767843126, 11204234843351418659, 14057032714422307544, 16637779355549534512, 17293043019105638911, 5235444579393367735, 7875158171121328348, 12032932633735348172, 17577724652120330660, 7795364456390606477, 4033162617687866088, 1544683855253756180, 12172662201233721356, 3756704469121795835, 15900453600187755478, 3111611615821110222, 12067333759598666114, 2460839148177982607, 7102750419395327210, 11545587889066437759, 13014356072259624231, 9055277810304247492, 14625948105355344074, 14619092238615835856, 4627724365506319628, 12192367475393288119, 4660777525583106578, 10602596814120768352, 15235390391666982533, 6262394583518039046, 11215546472975813276, 17221191340393185135, 2101601180397124797, 5801945926643183687, 13279838326750802748, 9760225764448182588, 10638379244001938587, 14689414070605049956, 9642847410658476483, 9252181208713310128, 10194326651074197381, 4194873578760608787, 15948390572816263861, 11413972117606094823, 5666682562527317380, 4558761157644127095, 16955166507135813953, 17165455630592879759, 6709237464973926762, 8519876379139259581, 16017543326401035900, 13443243112246019386, 15985758849225110622, 6635201996777679527, 810401065572784823, 3192312066161014982, 9614569995908311868, 6150822398486473654, 10813585281758350005, 8073858541355843438, 18109256134774887184, 3173606297852832180, 1697871109011675466, 18299820979700369122, 3429453844247078700, 5880410106220533795, 1902086387150156227, 1095558516266363748, 7401629960716178240, 10676693679576960757, 6803369895878427000, 679584762058495726, 8862820141296633751, 17191945777921342135, 8948907246409262383, 3201694424452878897, 13419812787573406307, 1123422467792803886, 16829507079638403272, 231077225656705538, 1743801854754216927, 2267894415989934871, 10485638453110401044, 14128191714015568951, 3134003464552465993, 16422231357711592145, 10265419470005494808, 608502939641364027, 9134620013637384764, 12129300312054467857, 18363959585640954741, 9300192354341214544, 10785267438521530991, 4936458668110384357, 17991939764954279170, 1611386959702759931, 13765557038981607892, 9945874597041578052, 4156215181237754094, 18063177967743727852, 15711037733871659565, 18074471117735370517, 4165544053496883142, 5279695231734291715, 1544829019313055335, 10641384862840576547, 17779765763310188495, 5626860848734533473, 10939014392735308139, 499526074720537175, 6841635225707590127, 8751796502513481516, 11336340410331983928, 8161799980755225229, 3303335824150755556, 187196914320055288, 4058076549799940817, 15401421223440460347, 10934724927412220331, 4611229640484146507, 4222099538065534859, 17723869573083320478, 4326485073257732271, 14233319419690524901, 10105594311301668570, 13674225839779959556, 9223247539431781352, 5207133412458563780, 2543064725421193686, 16112712767696009427, 14180139311525005755, 8623263245810438804, 9872551252324828981, 7186327511028170781, 15405568215949189408, 648741987472856599, 15504353064913393130, 9477833781488603469, 15265929637105201324, 14321785262909727449, 5989145253796307072, 4029928268282443946, 214922776543851469, 14661242500471677738, 17649450017688656343, 8833974540349191087, 13816848681848193227, 9357698275516764935, 4896085333994455104, 15704289681227768777, 16072211553259947696, 3696086675995567997, 2705327250235057879, 3940607606521307638, 1904439667923426432, 5211873495099253275, 12248061263800319556, 5068931489527810664, 3181822810361134627, 2893763819599633264, 17022013858675764406, 14432435821204701872, 5652574963789809237, 2389493332555305833, 7138156757153353567, 11060288640704436502, 16742145355448544339, 13832335420610765016, 13868994572073192755, 7515903319542781099, 6444421916061246995, 11587739604890358174, 6732571924439013884, 11724575869028146429, 12250459832157882902, 3016621587617492227, 9032739925629140208, 17557103950413855460, 13601852701212599067, 10511208766396769010, 1798260311095193927, 5693423254942127954, 12655656726468149287, 11019197760486093174, 12053338214040694646, 18408373830237784798, 6067223765497148246, 11553996073859513969, 4236552940838351761, 9458987771514077962, 11856103773548100132, 12956542515015205037, 4644161276287406073, 8685301764457396658, 1616507854541499544, 10201320335307975884, 4576763754089281023, 2461338218102810280, 91262760005101889, 11335499049722647439, 4878593686343800958, 12877266813141124945, 11027535651547021298, 5250333616946137743, 7088081721141062141, 14298861153503504925, 7147145447148416343, 17047545950712643349, 4493827337401588739, 12928986855103603232, 15542818123557007044, 13140774562703256605, 3866700096503647014, 11880459985577020267, 9892678920934094494, 7884199841722717749, 15763760571691417193, 10614999011319354481, 12234066605168430720, 13097736774835846982, 11019050032839105206, 127993841633501445, 18442075166379932728, 5173423558140830113, 5040877753307545604, 17492079016333825987, 1593793193144791850, 1051352355195775735, 5943763991772466352, 13308051483591590190, 9343693271988203192, 3520113272999099435, 13156437544558533124, 4628664430619092695, 13839519774612268130, 1561524063476792872, 1786105529617874762, 10743318550189039818, 4780466308508262376, 16286344021354707563, 7706876683201466759, 6056690298161881679, 10055051256791782547, 2985438843283121106, 5662611066107180778, 11762504057786722681, 6492163523688561469, 11903314370703515089, 6639143404964802752, 15352864297227042626, 6467331344424294098, 2513138096890065757, 18252010886576525300, 2137309836787405465, 5062748182344476458, 11543605570449724492, 8967616081750626506, 14081282030384505465, 14030488276049836901, 10391269999968368055, 1394499028419468024, 15566682361173996820, 4824266726532780984, 10757268905789656792, 16462615027839033267, 3588952369216858747, 7608658025855812414, 17838642938949526141, 94781055844175262, 711508162709410434, 16198763120066216543, 14522827050618946105, 8827834881271403758, 14961924349064399313, 14406825157858343587, 10665706975132276032, 584919077692434094, 12685151994185398186, 13214723590065181555, 13213787529887690386, 8702815823276144804, 11800457387620589360, 17199643293763420877, 11515884665346482491, 13888785899717119262, 3507252794824964582, 4603659836413814919, 4686748937472750550, 12421832631783901099, 3359573926155290420, 8446017905393844760, 2262184677731317052, 13013248939510347462, 14572693118580589660, 11022830998326129411, 8408924655992625371, 10410179516308402041, 6729141891150201635, 10466696767386859740, 2677788096731405850, 8361098508510730897, 1435994109558943177, 10128073597738606818, 921651131688578288, 3784288897383787482, 2528827532726381824, 2745271865598231885, 4303509657664184356, 8598151439188559180, 7339838340151008759, 4102212049950464432, 12029559280219172530, 8134545883285853776, 1905850669581557220, 16936295454560454463, 3680651425193647974, 13599577612277546424, 15046713416606033193, 456361953791851675, 4752112709649208116, 16115819506587034188, 2144813052901824207, 17046622154581665407, 2876106397373513535, 13003327799466428462, 16437033639571166321, 2399609620924500287, 6243590631410196409, 533278795730307090, 1033111886262872863, 4866574245728597909, 2464030264651522958, 13205453272650124362, 11723186208228000543, 12969372141223026578, 13167498178415442543, 11172031751757823858, 13257370093102747268, 3420723884940420444, 1598261708381549908, 4391211331742607590, 17534127798353752916, 7341206993048506664, 14415020221961337361, 2046719475561107676, 4259820090742316823, 9276901061275297500, 4961643293623327681, 17911768139050064538, 7558076127984989238, 568046345613284638, 6669214817759616213, 13786197531743943161, 4249924081611420922, 3529848342623085628, 5686448815512694800, 2430075147871613846, 1061366453609214842, 11667688802723514202, 10816922529577173425, 15297819755158335361, 12893049998502519066, 8535913883749763696, 6339822152676352172, 15201150192746395949, 6947773417864595038, 1035062681571489613, 5378407968343096021, 7821838471743655524, 8160693950261852840, 3806489823381045221, 9110537314944891991, 6678462809405704107, 13148862938001788174, 18343376155927784359, 1347615916836827854, 1983837968641288273, 4808698262452924116, 16203540206877084005, 3735610071301703267, 3879614205585090263, 14396127625458802513, 12971705508774594652, 16855551153787363016, 13770590905219407421, 8320920749683191847, 12731079676051788661, 6315049700706159729, 5520681748122702259, 18377945140487117991, 3750012964925257010, 6112975361804514180, 7762601797879075263, 7806585903492997505, 11722560531200514496, 1245601739242598527, 9851142601372397178, 5448093531458783000, 6655626903986665730, 1791030450653932131, 4267138194183414466, 11787121723746760335, 8737617848190145545, 1279353625599713991, 16837389613968560264, 12170971524469207688, 5744210997797297631, 6252807583283253984, 11981409579764369313, 13423106411424571122, 13506594589042509585, 9696374086757887423, 12259201030407607956, 1940425431459421890, 6794826149146208424, 3390019520570000181, 15663291992287526262, 8024326304926259059, 15605237955532295324, 7521900870833785280, 17076272368081584726, 14317742593729071792, 6186803591370756697, 8693074866179823680, 4521657215447236495, 7139214124438529536, 11252767985352986779, 9244757738422684376, 9181380892380409585, 14124397466598078340, 14092092430731683920, 13444150800556990844, 4618564184049153098, 11716810196377677056, ]; test(out, 960, xs, ys, scratch, out_after); test( vec![ 14220278540957382380, 2341486122221271577, 7196589596013057856, 1551746986989660725, 10730116577084868866, 5936722303301071470, 10369883251536410381, 12850276745016711948, 5296892922384710655, 17927383456923143639, 4297800151447374193, 13092886296891104150, 4359313044481849916, 3298387784200302647, 16596015395483459285, 6430047254377585078, 6434371216959893287, 14030068303817750616, 17753911968053092798, 4279608746592328433, 4376377052237075099, 41468300827872346, 14769069119913127616, 9177168551686374492, 15140565915751014925, 924212491380315180, 1560999192236438812, 18226600332889405930, 13348576723395503060, 3609063818274619379, 10959876508495766635, 1673947094507794325, 8930147615298565568, 1510138210058461841, 138658670646289458, 12458879312664552547, 2808979850323582450, 14034036666484023484, 5585848372598666548, 4257210144363692139, 6338629395801650540, 17487850811313620991, 11723765031594531899, 12058758430990318672, 13113234745283246366, 14258831759967032298, 5702057171550109179, 13097449289463197974, 4956526745376824433, 5705156949115651685, 12015733702012855186, 8669471405965585399, 1905089081593904691, 9375413288655317408, 2862087246546719140, 1438802037360108086, 18188344038773760076, 6710952137267346735, 5113990331512729307, 1249942195157804768, 12370173123137454524, 17270573617823502592, 7850217070904007210, 15008954292697138434, 14323227552451257069, 3071194499601430769, 1423266339629343645, 17719424777360227280, 5817741038340475518, 2288688081269683349, 1294813101366983999, 11187697042332288595, 16383307749918316156, 11964485411396601998, 2882482593432453314, 9642249517934314115, 10542384929787952175, 1685709334753615213, 9706601754650993843, 1704742035456300361, 14513229339862334723, 6682003045097239025, 4714611199273627241, 10432585451230614215, 5273605414681358823, 9969985476182536371, 5399491654701460340, 13433254437284849384, 8737041519297820559, 14151041462241779583, 12800325041646118168, 1054683376318581041, 10442674392431772880, 1301805922104023475, 12991162900765496493, 14882797183035693101, 4301011085545481404, 11250534379510854507, 6111542722921923807, 16925710356305375375, 4650629800913345495, 8040250152135495246, 6010724734735944849, 704649712350181160, 12623719311045527320, 17274359723691631952, 12634456101984828972, 18130410107220630156, 11889003125474723933, 16069412996687629414, 14767547198599161992, 1104256363303539555, ], 112, vec![ 10900792384749518304, 1752565570529908396, 3402229115647561238, 2472381872242532960, 15748089475115162936, 1958855681762413475, 12100416912810779188, 12256578057348862042, 6556831077371185734, 15914846823057329492, 17346954154793811255, 17566187606614467459, 1433606366066775495, 9089332045922722756, 10056944581186126460, 5324425019386643029, 5281765195814058625, 1449711238109407238, 5903959110668039125, 3336955200427408551, 751494194154096512, 15350321905800137137, 12407374450431165353, 8705815621686854350, 18038286270431178148, 11671842546699641930, 9343865367071815679, 13401838367914321671, 18365991333043790435, 17428290065100096976, 6040216493892400727, 4224515713015397505, 16578741590625036060, 11835373548777581169, 18413478850867685366, 8453265724386285209, 5394500720474148965, 1927463313122594080, 4177838821929605731, 10680620304882583021, 180005403771618203, 2256408572502279608, 11718426532525535626, 14260315287467647015, 4035759666841010016, 16259497729863184485, 7772704202422133476, 6815813069474359325, 11207378575459431371, 18308033894506293455, 9875145231436590806, 15354934628544213986, 761822562304640527, 7391550101325083295, 4023926600201752832, 922969942182092752, 12110946035817932140, 16574399923422896843, 7087993004495856759, 8299428112066197874, 4589434828506762129, 13978205413565566735, 15675366647238478172, 7819770375827015142, 6823625407675143456, 2042269662440457350, 11521115322912473140, 13703874674141705702, 1295561690992462505, 12464082489717915012, 11378922861990148970, 2076282285705918066, 1390689690731346588, 13670979351308531000, 12980996477862222169, 10496970808504864546, 14015388605987660396, 4171129107047347396, 1656857204469415571, 17492457435753920912, 10132937897450237781, 5065601177732655021, 17498367701449356268, 9552937910825811119, 6213399497134928078, 12865519292113075754, 8548871019474664332, 12973212090641168109, 3018095992673320728, 4102580256148037725, 11411505815957245048, 8044142604358855954, 6163064685377006161, 7676133172626151339, 15177331097378985405, 923128391789363540, 8405355494789853124, 8409013636286216842, 17519952046647436442, 12690425880634822079, 7295927951214020420, 5103171252065286692, 4531269626482776566, 17509133779966482098, 16771567673323510549, 9940518318209913958, 2566490491730418524, 4997841530198583881, 11759671980624847072, 12804335234851198898, ], vec![ 564820221219774033, 4488711358679422475, 10020082426042197380, 17225157352286806558, 5780768250525361575, 1970180556702143116, 5857604197270789289, 4060596445048742789, 4197799076012455571, 7044577438443748571, 9865458079653433267, 16329626967551115891, 4152461199188161627, 13000775528850398936, 7619420622350160180, 14900279174214956337, 1704825421557733731, 47372161928033978, 3056759021249434255, 16034528189533406528, 6435981853629992716, 7347416955208902363, 7867885339734871956, 16003312811447303393, 11973054691848315139, 4061237791967812067, 2991418391396596002, 4703879799196538602, ], vec![ 17578771842269238556, 10550562699554142644, 8014103604728001619, 7390436293466268454, 7100508597220429999, 13756539744133134331, 3525655558627413814, 170556856626573274, 13733802409149293411, 7547658189901533049, 10109863308220110581, 2718018624165645986, 17221869495150324628, 1084076247398656329, 9986824749465272556, 9281213789632200478, 8263835511857229414, 2738190782342964576, 4727749457903038288, 5193416305832697137, 10922073469544468796, 10479120898291460619, 16531138594227806551, 5669282286095321480, 910652003754331469, 7613181106845480358, 9797364435815597385, 2605791728953382133, 3252270662152843680, 14622379517499579600, 15478463498321531331, 11333349078754873211, 3607338878951398292, 13712359136800994328, 2877919791629132004, 16504311509495367657, 3984067008787761258, 12750589284505094681, 2943531823722430709, 13059724297333425458, 913829495058925011, 18148528311470701517, 9740722521202851845, 14187622249425297058, 18404294373540546372, 16126489610510541686, 7594528449544330894, 7307162781265364836, 18291168119091813753, 6207931594466286839, 4606167418509673090, 14995240148627089997, 15715313103810577432, 18105567578045566655, 722560899028528632, 7800517321196764697, 0, 11237865801974219633, 8495979800230117621, 9987880506353342706, 13881397368512772448, 16410969001089181498, 333374346498930988, 4965563385767496990, 672660669687292950, 15110765557390623369, 6227398366445560799, 10437883884413763417, 186853687685224617, 12984935070726568218, 17363252202577108630, 11014686580262231685, 12860125675167553971, 5547449898028817740, 1954311880857527678, 12081499992106861757, 14088922543958348561, 5962182563926402036, 5741569353545905243, 4210355652762257668, 9053751503514703697, 7217335315946897611, 6001545942842673798, 2462625304327945285, 291604632040409357, 2217739517798639603, 2459684629220685427, 3250634546851783096, 6059950473822714693, 582656439794855702, 10281608630795849151, 15786006397997472307, 16261716592524561399, 17594773541694900671, 16563607893390940119, 15505686658080216809, 2051217090370709743, 13908204460746584986, 10039065459685700894, 14729811272925582111, 2491677743278343614, 2841321092069312904, 15064468426708488588, 9844013577617278901, 15394077255564897694, 7846267917227712141, 2926235763818832770, 3614802673424810100, 9439654670958755441, 11228283553719081427, 300805303577965353, 137972366037263628, 0, 0, 17236590422641137780, 3624909720816563168, 14760980184861256094, 12619697833885886701, 11158654646608400806, 6427394341906398356, 14871794339281852631, 4436807681521846899, 18179949743405593894, 13872577160616872141, 5825838831881338115, 3862312932472761757, 138044675074312990, 15071993629914359360, 17124765792905529105, 3248142733680724962, 3891075505082712037, 6225475960510427854, 11369706706515368571, 11286728465632095620, 5182849661875987731, 11179192798752789740, 10750517245961749782, 9660102259642485054, 7905348372980940366, 6606241368966986909, 10292241739332011027, 3848900457088510551, 12152591835908862357, 4562770772987021222, 15938089548127288011, 9698047696083781011, 13560645597951715331, 7732793292629543444, 7001973034910440318, 409123120027429255, 17678180108806694420, 12698074214205994356, 7447251798260171941, 9757491913093219480, 10221393982691316695, 12294139009925614381, 12645218559587650799, 1569889406832824935, 15186575789336541212, 11156326477797897792, 3241434575939356910, 7753423363217428843, 12882554975845472437, 8367515576296379496, 7308654739706172282, 10357093098345630105, 7448894655389345071, 13033958940183436012, 4023926600201752831, 922969942182092752, 0, 0, ], vec![ 428006685349647609, 7204145293518952443, 11791003654963925746, 2505792214484682253, 8108316487989608659, 13780196866264665329, 9953181804399070508, 4136674009057114789, 16606729965278593786, 17177157337945625561, 4837680254021048240, 9379658380128247416, 3012240265336162150, 10902131616911906952, 4485885110776748559, 11729287033558411069, 3601025811236822387, 16042927197309963407, 15195320086232266472, 1335053215979905641, 13532069890206403083, 18094969954718697842, 11554202269641514254, 6403207599202754602, 5506746445690691110, 15578759879114917443, 8851198090240221910, 33092233213362571, 3901122084110515729, 1066956798888524232, 14634384737761094242, 12113217349928728328, 9311779266239300758, 3954657017302988647, 15532948787491930233, 7561648003514142824, 3533375924863968581, 11403256543506170549, 14720984883173782359, 17386473882517270759, 13904760793036335927, 1743693703212112035, 16080759313684757024, 16414994735840739, 5271412552749845691, 14285133708577039222, 2285218927081566054, 4416233718641470493, 18000037526325532907, 9874370178595584823, 2431098204987529914, 16053941488194364614, 13953671515916339883, 2042478395473246676, 15825222700565763229, 215338277757125297, 11715801345488940860, 15276655380547065511, 18173108185582673895, 14702410041012894911, 17207703913939254166, 4048944409583435567, 9240704600129021640, 10746010074070008578, 10882274053549736437, 17502803382613798018, 17103667474686148623, 1210754893985321636, 14411333195446047958, 9505671694718631767, 17438945960504601463, 17181086340701682720, 2087061119253391199, 4309925416075845511, 15682876991754565762, 1083109033127246208, 4261779269652031267, 12103546078796301947, 11869822949907847429, 10776362556491885652, 3496260740980747565, 1952845492765004055, 3956805099328134345, 13449597823431522461, 1303096111058814577, 2380211731709650934, 18106526914056683197, 11484139358020791769, 2127792824095743993, 4065001616617210813, 16699812364763026472, 7039834103740457737, 13922378224749177434, 3842744781605852390, 2881049947442869386, 9197037672589549736, 16294658006443583090, 1354837441772061197, 6800107739861512622, 7157401423299319780, 11344094968696196811, 14476284546277236050, 5424464793786542079, 5963838631551795433, 5066844411121684619, 17308776236012135105, 4153319859448120557, 9810663971090332314, 4914337127311050195, 3998867848399474691, 5662987571533822588, 879647540404803095, ], ); } fn verify_mul_low_1(out_before: &[Limb], xs: &[Limb], ys: &[Limb], out_after: &[Limb]) { let n = Natural::from_limbs_asc(xs) * Natural::from_limbs_asc(ys); let mut ns = n.into_limbs_asc(); let len = xs.len(); ns.resize(len, 0); assert_eq!(ns, &out_after[..len]); assert_eq!(&out_after[len..], &out_before[len..]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_low_same_length_basecase() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after: Vec| { let mut out = out_before.clone(); limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); assert_eq!(out, out_after); let mut out = out_before.clone(); limbs_mul_low_same_length_basecase_alt(&mut out, &xs, &ys); assert_eq!(out, out_after); verify_mul_low_1(&out_before, &xs, &ys, &out_after); }; test(vec![2], vec![3], vec![10; 3], vec![6, 10, 10]); test( vec![1; 3], series(1, 3), vec![5; 8], vec![1, 3, 6, 5, 5, 5, 5, 5], ); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], vec![10200, 20402, 30605, 10, 10, 10, 10], ); test(vec![u32::MAX], vec![1], vec![10; 3], vec![u32::MAX, 10, 10]); test( vec![u32::MAX], vec![u32::MAX], vec![10; 4], vec![1, 10, 10, 10], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], vec![1, 0, 0, 10, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_basecase_fail_1() { let mut out = vec![10, 10, 10, 10, 10]; limbs_mul_low_same_length_basecase(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_basecase_fail_2() { let mut out = vec![10]; limbs_mul_low_same_length_basecase(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_basecase_fail_3() { let mut out = vec![10]; limbs_mul_low_same_length_basecase(&mut out, &[], &[]); } #[test] fn limbs_mul_low_same_length_basecase_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_24().test_properties_with_config( &config, |(out_before, xs, ys)| { let mut out = out_before.to_vec(); limbs_mul_low_same_length_basecase(&mut out, &xs, &ys); let out_after = out; let mut out = out_before.to_vec(); limbs_mul_low_same_length_basecase_alt(&mut out, &xs, &ys); assert_eq!(out, out_after); verify_mul_low_1(&out_before, &xs, &ys, &out_after); }, ); } fn verify_mul_low_2(xs: &[Limb], ys: &[Limb], out: &[Limb]) { let n = Natural::from_limbs_asc(xs) * Natural::from_limbs_asc(ys); let mut ns = n.into_limbs_asc(); let len = xs.len(); ns.resize(len, 0); assert_eq!(ns, out); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_low_same_length_divide_and_conquer() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after: &[Limb]| { let len = xs.len(); let mut out = out_before.clone(); limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &xs, &ys); assert_eq!(&out[..len], out_after); let mut out = out_before; let mut scratch = vec![0; xs.len() << 1]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &xs, &ys, &mut scratch); assert_eq!(&out[..len], out_after); verify_mul_low_2(&xs, &ys, out_after); }; // - MAYBE_RANGE_BASECASE && n < MUL_TOOM22THRESHOLD * 36 / (36 - 11) // - n1 < MULLO_BASECASE_THRESHOLD test(vec![1; 3], series(1, 3), vec![5; 8], &[1, 3, 6]); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], &[10200, 20402, 30605], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], &[1, 0, 0], ); // - n < MUL_TOOM44THRESHOLD * 40 / (40 - 9) // - n1 >= MULLO_BASECASE_THRESHOLD test( vec![ 461989387, 2665399848, 3579300374, 878189998, 4019917942, 1906890030, 3540714906, 785021435, 2655957692, 3564967487, 2215671253, 2954375312, 3945786785, 2381932623, 570517012, 897945067, 890538555, 4176726399, 1938024252, 1214448000, 2607894539, 1325279234, 1564558613, 987829481, 2178327923, 4147856447, 4083057668, 785634261, 2167973152, 1652571464, 70145184, 217938310, 1833392838, 807859939, 1395394971, 2852311871, 2904303228, 3198169893, 3331434354, 735263109, 4147668831, 2611779917, 2853615276, 1375955505, 2451249431, 4226040869, 171021557, 1972314766, 277184426, 2375785672, 2222399598, 810164152, 1039489350, 2933759445, 3534834167, 1138611909, 672716981, 2084719089, 538544765, 3894759873, 937996537, 1412775694, 3879993313, 1085679676, 1967211093, 1504744432, 3666320291, 2237452530, 1826697476, 3221257357, 580543441, 4245347387, 4208784414, 3482952509, 1951149172, 3708033640, 586662200, 345242773, 2377487665, 3100161675, 3699715979, 1377295273, 2132506492, 293803895, 1798986191, 4197257911, 627991308, 2783841978, 3918540249, 29355619, 3412985598, 1519516456, 3710419939, 721212175, 3932373394, 4152619047, 2587596408, 456847065, 1492972877, 2878578092, 4224013690, 4183847837, 3441313194, 715397057, 4270121821, 1405478162, 3277147812, 3938142059, 2533309358, 1504116963, 3653366746, 2109153696, 2511274585, 90325377, 1647825264, 836765640, 1125067095, 3544759944, 2652860738, 1079540720, 1986083965, 3960406547, 349138094, 2949875969, 2733651822, 3091427333, 3570148981, 733070163, 4233388956, 3214072096, 3112563117, 1651509303, 2142845704, 1051620120, 3770606367, 4159133142, 2506712000, 1161310860, 1621911269, 2878403318, 206258321, 1812136445, 3881335928, 703342820, 4106909674, 3002521966, 2923723774, 3098805336, 1503909373, 827876722, 188113568, 342517338, 743560400, 2994196952, 1909518945, 4098343484, 1410898722, 1188050013, 3739587846, 1187118353, 2097511427, 4268272529, 3038427753, 3211203785, 4227105159, 1129593228, 2044890920, 2369860975, 2369399578, 1454306337, 91937919, 798293675, 163666826, 774359002, 1184861045, 717591688, 1661912106, 2791047481, 2777706888, 3878079014, 1418504920, 2448450319, 1922646614, 3068210241, 16469458, 4024185119, 1215576054, 311246292, 4059710876, 4265782141, 4187978245, 4278365409, 4288916077, 1305069248, 1563951794, 2960618962, 2009022918, 1272389839, 2439394275, 4208883918, 1504352264, 369924536, 13357077, 1532849248, 485135885, 2924605508, 841648515, 705817258, 954451953, 3740323831, 2757913511, 3424971384, 2775642081, 1876912734, 630579777, 747682898, 3056441789, 2407022149, 3613070805, 2027387425, 4277873093, 3802579285, 744104253, 2776789109, 1370095770, 1305744491, 18166236, 304885422, 2971797302, 3549745966, 741626137, 795961656, 1741115244, 3220360703, 4121898682, 2553071415, 3851952692, 3272833446, 1749035103, 3660315457, 815620200, 4112719780, 4169868140, 111675416, 572996149, 527650323, 3028027759, 3074169491, 3295530784, 1548029727, 410371832, 1384175276, 1019155445, 940733503, 3362087055, 313802022, 1997544491, 472489619, 1402431484, 3640929705, 203857340, 399422159, 2714826274, 1480889873, 2185368870, 2143561855, 837780556, 4244388174, 347736364, 183686097, 896312971, 774613537, 3413697161, 3233389068, 4019739363, 337295178, 1832529524, 1289908799, ], vec![ 3152074368, 2609279004, 2289393871, 1484468596, 1208431774, 832849643, 288683182, 3006999416, 1903458849, 3111117159, 3671553126, 427622591, 3190285531, 3311271958, 234886006, 1671522985, 529046783, 2869877832, 2642573124, 60209762, 3035295220, 2511225368, 2206515646, 3850823730, 222908649, 2567682433, 2162714751, 490925601, 1537433919, 3002058493, 2023135946, 875430531, 4129401376, 1327326767, 752062706, 4112039026, 3726450563, 3167143759, 3983527603, 842382530, 3153795246, 3598914654, 3417317498, 3553459715, 1106685605, 2142189479, 2339845222, 2514744298, 1446296496, 3075359392, 317750583, 1297434773, 806470314, 3548517324, 2896883965, 1547969571, 2485824310, 805179503, 4202831898, 597659823, 3535591228, 855958045, 1755923867, 3365965707, 9682282, 3287632414, 1149281829, 964617017, 4003502184, 1850865215, 987376895, 22121503, 3262730353, 3067466886, 1231496573, 683689717, 2341771143, 2402732693, 1733447213, 492218933, 1092253813, 3015603177, 1300236300, 2607300207, 2327157037, 1107197558, 1862484547, 970467880, 1116477123, 1727183986, 1866387311, 4294876996, 2433423873, 1947645522, 3490401276, 3091887938, 2150744771, 1590400854, 4235775628, 2260414990, 2867210260, 1289781050, 3796740921, 1443787618, 2784677595, 2242443647, 2083926475, 492343557, 4143467814, 4259917315, 2370814617, 1512402965, 1165630944, 1172451831, 448126667, 2504642429, 2943134913, 253722272, 3930555887, 236043678, 2028066178, 2274670726, 2117908175, 1814596459, 1589398655, 3643981976, 3708172828, 2628370440, 2994406702, 3768287526, 3697661671, 72250477, 1952682906, 3890984670, 2335366358, 1486511900, 3932950080, 4154600910, 1641913905, 1181402070, 1236047930, 3178973441, 3150857560, 3584289380, 609401228, 733328893, 3965865377, 3698014337, 2769360864, 1034884438, 739582397, 1922193210, 1130663039, 2639094031, 2919470545, 3614476088, 1565067122, 120324146, 2567666261, 39022936, 4114703092, 165126137, 2949477884, 2405325064, 2237215558, 2498656017, 1425552926, 1121499119, 1406111625, 3405344040, 1219643487, 3602348463, 512125432, 1367217197, 1477847901, 2226582448, 1871611823, 1134590604, 3982040908, 1623284673, 1857753233, 321590484, 3220580378, 727231217, 983590217, 3953357093, 514378029, 3972342992, 2131575137, 3154014995, 1075955265, 1966241007, 3201815871, 3097020322, 3758733690, 762231963, 344183707, 2857398231, 3337254067, 218375481, 882367684, 2204572067, 1038287244, 3321266584, 2994716041, 1768291972, 3957932586, 3024157312, 621247724, 1627210559, 3958490863, 2281045736, 3555698779, 3902429680, 426592368, 3133450642, 4010080363, 1875043293, 3628899254, 2601848204, 663261663, 1664093718, 3328282988, 2238354920, 4012861950, 920971329, 1582693646, 3875328875, 3096546242, 2216996167, 347539721, 454900186, 2025219395, 1756065860, 1337774773, 1867666187, 584376262, 2443135798, 699177444, 2101251123, 1815621294, 1747522047, 4180260619, 2565611399, 3614008442, 981733561, 339547618, 1433098485, 523523039, 756060971, 432087064, 1056119297, 3262021204, 2309315188, 36557289, 3784506551, 3467316194, 3626135421, 2707559086, 895034761, 805184221, 2207233543, 2613952626, 2493110341, 1147976987, 3110836167, 738569324, 2424079556, 2624128221, 441916235, 2974993618, 1131709928, 1556781361, 2518935270, 2504025847, 61629344, 3838407260, 1506641084, ], vec![10; 556], &[ 4070586240, 2326530569, 2261395410, 825689729, 2475737777, 2607579621, 2779055768, 1031674491, 1535775813, 3799159704, 2509339137, 642496935, 1388726819, 253797856, 2389660485, 1933170407, 612455389, 4107963146, 1906296838, 2898497315, 2050606412, 3001222322, 1228059054, 2396274750, 2706199930, 3790047803, 1941351862, 1789409896, 1715227383, 4265202904, 256846097, 2002262811, 1019015022, 2082931322, 892118471, 1902650557, 1821044055, 628436942, 992944813, 2152035281, 3205031699, 3012731022, 640270255, 3942556100, 4180900492, 3316509849, 1950826436, 3810257818, 2224553717, 1511731290, 3648751071, 26431626, 4214594419, 3417633336, 1456941539, 858305585, 1967412985, 3623211292, 3984085024, 1384481949, 747470989, 3106003382, 1550527069, 3614045491, 2344422097, 373587226, 2547151647, 994917426, 2913847676, 2378129020, 555898239, 1108784126, 1609305655, 2815855409, 2517331928, 235971500, 4146164385, 513982484, 3224855761, 616267314, 3033012116, 944903736, 4143585656, 1155526042, 1713184683, 1067605397, 4185794190, 3837642784, 2629382351, 937694634, 807052082, 200210144, 925428999, 2855412451, 351040428, 3193751061, 1327138015, 1236708649, 762670968, 637002031, 3265514324, 1325649336, 418630090, 2004473621, 395337679, 1254733858, 2979245588, 2917625161, 4154932643, 333114873, 4020812672, 196942723, 3805667762, 1295056656, 757090141, 1581564716, 3028221550, 652769076, 2520564087, 1804643123, 597439055, 2022877640, 2295355063, 2554644875, 2505050304, 1251254106, 766564249, 736769858, 655024585, 3983536005, 2807999031, 2526649460, 3997807999, 1027142135, 3147220153, 2611110579, 1353792039, 96665204, 3799354781, 1169870906, 163280197, 1201147091, 506111450, 560981310, 2487787507, 293569384, 1660966093, 4172508795, 2079157727, 427559941, 2199181463, 766276398, 3590398380, 921568940, 1978512327, 2526895800, 155351140, 1734194686, 4286806742, 1665643514, 2910888313, 1105506458, 2792013812, 84803204, 2779601075, 3530726950, 2109503137, 447716492, 249291965, 871214282, 1950969439, 831198533, 2725086482, 1111889448, 3879479978, 2578937795, 2360329247, 849485221, 3118220783, 3215737700, 2629034929, 1803802428, 579744897, 1521586187, 3794906163, 1682984424, 2501371511, 382339060, 1548025441, 3993119644, 2642540168, 445700200, 973327482, 672676716, 3810693263, 3980560630, 633737607, 2979566412, 3035890974, 2663806368, 3077368948, 559094664, 873179537, 3907578303, 2898488985, 559532336, 1951693750, 3221546487, 519175878, 3817909883, 4143965836, 2159038430, 2155451492, 984127081, 1552180477, 3998228380, 951987999, 3271220480, 3991577644, 189427243, 1451593380, 2417528240, 2707909762, 2545325149, 4092625458, 1678828086, 65074887, 2912853674, 2298196517, 1962123671, 3156663717, 1809562653, 3422933930, 3543349121, 1539368201, 4132862547, 2117037713, 697944662, 3761970455, 3210335685, 4061395188, 1399948007, 2797740984, 523361390, 2891000343, 4043976998, 3948000788, 2806803391, 372268870, 3066648573, 1552197320, 1104893676, 1977956692, 4206072635, 1777799765, 2593085983, 909587553, 701089400, 3025031477, 3150914776, 3383493968, 3297968979, 2127114185, 347641566, 1133943045, 1397026960, 1102135376, 1790048118, 1531899702, 38573247, 86358464, 807071035, 1322974764, 3918796486, 2658009039, 1875612194, 2278918363, 4156398458, ], ); // - n < MUL_TOOM8H_THRESHOLD * 10 / 9 test( vec![ 1131150821, 2762649368, 1291624341, 1701704353, 4014105561, 3682713698, 514896869, 2382721993, 4199508292, 116228850, 1913167611, 2543927978, 3462810307, 2182535806, 3234802163, 4243621064, 4189108519, 2844896515, 265654095, 2925399216, 1942537721, 3688510290, 1467767823, 1331956526, 1810538674, 3416955279, 2622944711, 3883742491, 3716395614, 2226266870, 4231113757, 1703472377, 799710037, 3188891105, 2002885312, 863976785, 2197487335, 3973964671, 982134718, 3039352665, 4058841706, 3126556723, 1839202656, 3512286394, 1526861314, 2857382087, 1509071714, 3983699181, 4164670109, 3541034768, 3414363792, 3719311258, 4228436631, 418239225, 2810981500, 2839232135, 75036670, 349836787, 995927099, 1154560390, 1157124967, 2338833107, 3519575136, 3676349342, 1999912677, 1473285447, 3384834599, 3729173386, 837302670, 1824368274, 4080054412, 3463347047, 2292431457, 4047304953, 3186147982, 797486141, 2414391350, 621753596, 2992059534, 1538383233, 664053981, 3061928211, 3215272269, 266835070, 2414626927, 159250143, 3019791116, 3731135237, 2761751093, 3586027201, 2089419276, 374111952, 49970046, 2897511132, 849093074, 1002730932, 3171254030, 477351679, 349956886, 1571756720, 2974023410, 2229070678, 1445469779, 3125204262, 2251629977, 3617654578, 3758587650, 3379646707, 3221020164, 3946481152, 746980266, 445806733, 3092441206, 2414172109, 45651552, 3218735738, 1981382211, 3339893115, 577943370, 3262981881, 3145699413, 3050111476, 2776211838, 888798694, 1098018756, 2384093069, 137109573, 3849877919, 816321891, 733291770, 1688860823, 3776150706, 259328987, 1793361953, 1360633863, 2822514209, 1611568653, 3671864876, 2995705621, 1703631428, 2545904596, 3558099294, 339073366, 1914245190, 2248240708, 2918919078, 2367951631, 3244616755, 1246248837, 2724721481, 1977303106, 853273015, 609224845, 2572706277, 4120826908, 3132172741, 2679460826, 1731116641, 1420934603, 4095172779, 2134926401, 998210691, 3678534171, 2288544872, 2333609559, 3187493478, 497033878, 13547027, 1366761551, 3620514533, 1846847912, 3066898750, 4029310316, 1785305517, 2975988788, 84028222, 1604571422, 159814579, 3302598788, 1860412674, 3924970651, 3084289036, 299916336, 2801290202, 1879794819, 3343450230, 2673079282, 3615958442, 3162274325, 3102296518, 435434416, 2915209493, 1817171393, 1159766844, 574519135, 3033326838, 2027440653, 1457685030, 2574873438, 877258212, 1477651381, 258103620, 4236228819, 1480006308, 2237899379, 4229629566, 1151532728, 1869635395, 3423452052, 3699388043, 91696809, 1622972763, 822248470, 1515292231, 3842486533, 3927210641, 3225680067, 4254069260, 3886678620, 3984473786, 2759203157, 2517007583, 145365022, 1533952248, 3917863954, 1567125726, 3108296518, 1454586200, 2011082282, 2132338201, 3182831171, 1413497090, 1856759670, 1984669926, 4212692874, 1110589546, 1440032735, 3646801244, 3610860056, 3043101171, 3857863470, 708594714, 3801293829, 84401414, 4009945641, 718064348, 1782564232, 2884677460, 3817956052, 2164661851, 1032113674, 2265026833, 3990818483, 1979791851, 1179815111, 1179610990, 3801644913, 2951826902, 1933447922, 1907000683, 2045622439, 3615799713, 4178470833, 488268281, 1409188637, 1338007608, 3944782180, 3885373568, 3104460402, 3927888479, 471271819, 3870427647, 4196319798, 3583191843, 3310030186, 860772115, 2433189612, 830226736, 3738387750, 1448499320, 526587241, 3892532590, 3439491908, 1039036501, 2388493771, 264726903, 3966258028, 2505867608, 407881715, 1631490147, 2823006404, 3497117958, 646382286, 3107394453, 3277949521, 439910091, 309065703, 1950804341, 1808416502, 170990188, 1335198213, 689918674, 1582196175, 2640621496, 3498813308, 2761060243, 1678685681, 454638300, 4004659669, 3681198397, 3976254726, 1940449540, 212889053, 1912817590, 1301852137, 2300183575, 2626591779, 3662656365, 2241640523, 2073990699, 2843210521, 3907897499, 2127053203, 3464740089, 2517063724, 849818543, 2198029686, 1607835696, 2158656964, 2474427278, 3105729582, 2593228154, 3652599476, 2493295322, 4214474951, 2092751192, 3508872416, 4135027724, 1087631006, 3869783862, 4127959478, 3950654826, 1413528055, 1583176859, 3118004380, 3469658789, 166660010, 3732069246, 1165982209, 3249209142, 3030024737, 4209637631, 1574902930, 612943597, 3575711404, 2421873039, 3084377476, 826443943, 3566117097, 1367287788, 884174375, 160667863, 839942561, 124546248, 3443852897, 1935836700, 3578696710, 3442653707, 3106215554, 956073431, 352475044, 3325573670, 4056377273, 2444639044, 4059211486, 3187262860, 1232076586, 712845366, 2490553931, 750933277, 1200249747, 4114847099, 3132331434, 426349171, 3418210348, 1864124410, 3635934842, 1778322792, 1268045228, 1155805234, 3891131459, 78081971, 2759073032, 2990099706, 752418656, 1424173464, 2440522876, 1954352637, 3476425702, 1980817220, 3283383787, 3606231400, 510762389, 4244763535, 2869358935, 1727272135, 3522246353, 1733965890, 274429005, 1074555950, 1116810589, 2059372124, 1433737439, 686360791, 3524954413, 790420924, 253262937, 2490041017, 2988382494, 2680296403, 740237358, 638968890, 3561449712, 1270014183, 2732717194, 2652066843, 1127846686, 1905112070, 7000223, 2815346469, 3485672034, 4150256142, 1201712608, 782060943, 3850587668, 891222391, 3919270279, 2284997530, 3355185596, 853556214, 2382672975, 4082635614, 1975597308, 775008313, 1221881305, 318112932, 1558885629, 1659368995, 2737245040, 3182289543, 2865953307, 1913563745, 3407843590, 2774667399, 2006733037, 214221440, 2867329721, 1460609363, 1420414655, 2442726895, 2077873651, 2078741260, 3351565491, 2650010589, 3624853117, 2808835283, 3576673605, 3312161027, 1089529182, 3411999136, 3214717560, 2569067404, 1395383167, 2628670095, 2534091665, 3416849349, 602644653, 3868242106, 780173614, 2918196647, 1069725684, 3173740663, 3441776760, 1918895783, 2591986841, 2047011602, 4037432, 633731206, 2672531137, 3708159409, 2150429215, 954500477, 3990097385, 1947492698, 981465130, 314252035, 358539692, 683336340, 2361937249, 2060146559, 232682027, 87274822, 3435325468, 4227641462, 882380594, 231040832, 3746812704, 502289657, 830742778, 3389856631, 2652175412, 3688357856, 3281892315, 1707485812, 227398450, 531784725, 1476141529, 2868884010, 1656814989, 2816953357, 1091559808, 1917641087, 1677755142, 548205597, 175354774, 3985092082, 3309818895, 464474156, 4204834984, 3761500115, 2438523503, 1732610689, 1486464139, 3967200098, 3929926820, 2339786049, 3907108412, 2199568695, 1134103910, 2216911633, 2182031298, 2579739862, 570100824, 3289356324, 3458481331, 611877571, 1507859299, 2274314160, 1548661374, 903468480, 264167483, 2119844238, 1038239445, 2988435265, 2038849220, 2021865993, 666366893, 1683542644, 663579226, 2516381838, 1452293108, 2860570530, 4048880023, 4066088025, 3363037289, 2542443950, 2325290119, 4126749311, 3549516466, 2259054696, 1124113431, 2596211298, 926851034, 4100110238, 619577504, 465050718, 921970188, 3443237807, 3185995153, 2512437958, 3138724608, 3421198187, 1215660513, 2802265359, 3639819408, 698058093, 4005388493, 701032232, 1900034464, 1258990473, 1384847467, 47742046, 2533738470, 4033217779, 193441436, 1167926881, 563345579, 1064730454, 1028831057, 2118889296, 1922177050, 3759770599, 762133197, 3305899630, 1774669125, 2184377046, 3697369449, 4032191246, 3613695996, 2714184171, 672093641, 2806515914, 754799026, 2811057556, 3677282514, 1644648375, 519012895, 2947700042, 1068870929, 1749850446, 2745609943, 3915641236, 1473746566, 245175508, 464459969, 2300554864, 452081255, 3542824159, 3984931523, 4038093048, 811698203, 3990065017, 1843168045, 102873045, 1872945131, 1381891297, 2689743436, 156330831, 3030944325, 2925864612, 868161142, 1955093372, 2271793313, 1293536600, 3877989118, 4085300196, 20015595, 1524783113, 3220067646, 1128665882, 1605056207, 3769938324, 3278249586, 865516226, 2018942727, 4285193298, 4136394815, 18140432, 1298007913, 619558910, 1468345138, 3640156579, 3844459024, 4251273955, 1279325353, 1490675071, 3812253034, 1588374415, 1408352173, 1856222658, 3479408648, 2553632750, 539602295, 2953721539, 3550404522, 2987339861, 3573803000, 2985536505, 3408426662, 394679673, 2338150855, 233169574, 2666618942, 885970658, 1261112849, 3026593914, 1941961461, 3178744470, 3418317636, 2483060546, 247068105, 3869710296, 2601474183, 1861230264, 466844147, 365421277, 1647470055, 2545886518, 3344491344, 2743895143, 2612409420, 3015491275, 2263288257, 3788192586, 3621947232, 3632971491, 2590893591, 3078266930, 837964625, 1062932151, 2387310193, 4263324106, 3590937645, 2690575361, 3471028939, 3052123108, 1287391629, 2780458428, 2899985132, 3768032123, 593582914, 1049982970, 3417846725, 2745208959, 2638635678, 2782226812, 723243488, 2883204599, 1861655363, 2193262251, 460750285, 408576776, 3151751571, 2348465332, 1090324024, 2080133910, 1884601095, 1792700738, 1586206119, 588433151, 1694897587, 3243922990, 3147195067, 704523940, 715280464, 2859196369, 2818686408, 3845709444, 388946443, 3822371361, 1083710054, 3973525343, 890875638, 336962766, 879786542, 3372880597, 4017818517, 4022694260, 1246618400, 3272410744, 2932065660, 3037109199, 1994060649, 934925733, 2550662182, 3369254727, 3300198891, 1222413593, 364996956, 2915355551, 2528303182, 1340653763, 6095745, 430607376, 2462322073, 82876788, 1168959908, 1417636305, 1265099813, 274745957, 167508621, 3915190887, 4169873122, 2699401240, 349817411, 1083358516, 378109903, 1137415528, 2610418640, 133616096, 1079889395, 1596538242, 1340572700, 3806709899, 2995810782, 196324185, 2670063802, 2058666273, 2243102740, 2109579437, 3319920398, 388799298, 1644474748, 3835051237, 2938119592, 857157002, 3904318910, 3191603530, 4005173949, 2864727253, 1049195541, 1431710706, 2394529501, 314388331, 3586260934, 1413117985, 1378439215, 90290944, 1187129087, 2806417408, 2252578657, 731737960, 3976349288, 2835651723, 3336636332, 1381984503, 1669124519, 3410912262, 3447243564, 222368697, 1603262029, 195964253, 1003881737, 3008564716, 3332124267, 3723209179, 48076559, 3962702541, 3175563645, 3613059603, 170958653, 1413948782, 2426947383, 1103046276, 3139837644, 502007526, 877737020, 407264876, 765859135, 1474201609, 2991446344, 3468949411, 3551131726, 560361863, 3036580569, 3430955843, 1011987611, 3299206602, 1953068741, 1760110431, 1246003603, 1099977647, 39794154, 389004595, 3989513261, 2907906071, 1622738740, 458000748, 1389814785, 699501716, 2230559, 2553609548, 1451109816, 3441722227, 3416954130, 2885301526, 1740199906, 1803806248, 1403790177, 3516185322, 457833177, 1470646316, 3450277077, 2082948067, 2481239364, 722376046, 2758592798, 2482526812, 4010504381, 3378951917, 1539096335, 1599687582, 2811560884, 2435502051, 2900235322, 3627166120, 32186692, 701703510, 2447124866, 1509277763, 2326977874, 1288896304, 230630067, 4134237779, 2960340409, 2917586567, 1164733926, 24754896, 2143494083, 3622160753, 1940106076, 3135397968, 3020065317, 1748012748, 1014590694, 162297287, 1327741722, 746744365, 3185502087, 158350155, ], vec![ 603622954, 2186113344, 2211632492, 2411520388, 3589635543, 4086364596, 3581723392, 2612098311, 2096044537, 1640167886, 3342490559, 2125968601, 1990634435, 312775010, 1802349863, 1309411103, 3200864131, 1358335036, 1912893833, 1596337323, 2247665998, 2443116949, 2420155681, 841076086, 377456615, 1237592486, 3216360690, 1624285201, 3654260727, 2790733511, 204168525, 4052634612, 2854194678, 3030697959, 948115195, 3826905149, 1976102477, 1784393101, 2995452496, 3261601101, 2842141116, 191128211, 1816171240, 2015310936, 2049251282, 613801401, 3835986911, 2470139377, 1942210663, 3899898568, 2985108866, 466048082, 1427695846, 860088895, 1905116312, 17072967, 3747648444, 4050068534, 1235378754, 3463008343, 2901169501, 3732797830, 3827542306, 1442668438, 2553056440, 3128009710, 2361840470, 2945391897, 2844092880, 1669579593, 285906550, 271337390, 3550080313, 1550684000, 761190775, 1986821670, 2760227175, 3755739359, 3195863504, 1506193392, 102572887, 3429355396, 2738466594, 2588290861, 921241140, 4000693169, 4200573367, 494632512, 3030208655, 4097675912, 3273014929, 1507497783, 1426537214, 1292494848, 737012202, 840807439, 4173254089, 2614555500, 2112014072, 524226642, 4134209698, 3019212395, 1098411347, 1127762058, 2520698217, 3618515874, 2710325152, 608562040, 3514989488, 4158363396, 306180876, 1211447956, 507700449, 911736750, 920771768, 3055911518, 2660700314, 3162062346, 460147980, 3893374896, 3335254211, 1730373325, 1769502379, 328248258, 3605468276, 839999978, 2617035765, 3256832677, 4166868036, 3034242873, 866786060, 1439047189, 1075047697, 3791824427, 2428657149, 1942106734, 3406726485, 1061929031, 1911794305, 2055938947, 4130327586, 3752449664, 1741794117, 2088328119, 625641627, 315760669, 2840762267, 327041843, 2880804433, 3266656983, 2181853630, 349055847, 1614300853, 3026780591, 3723351880, 4108567046, 2344446900, 2195753474, 1660780233, 2121691315, 102176310, 2695465705, 3089322092, 2775472883, 2630273841, 2862312016, 2071059637, 1584923974, 609930669, 631828585, 1504369275, 892077659, 3793274532, 111247066, 576379360, 3257765683, 2389261674, 2210132561, 623967505, 3475583657, 4078514517, 2696227314, 423351810, 219536780, 1292034857, 3134390109, 2644943026, 2175174277, 854381939, 1615329948, 1003209984, 1497561541, 1581742618, 3453870211, 1697610716, 1386823953, 1754275998, 1049523617, 319480181, 52790852, 1843711621, 1677461984, 2268587847, 1467575383, 809390384, 3208538160, 1710678484, 3852975493, 3491099676, 2208895838, 67474001, 1909240027, 552833552, 1068516200, 797958994, 1336265228, 52799811, 3497387824, 2615050498, 2306496091, 1509488357, 3175308944, 1400875928, 2613915127, 4014015840, 3770610211, 4050294544, 1133059937, 1931794550, 609394840, 730823155, 2274984932, 856801557, 2940954445, 1507833826, 3361523681, 4114500875, 4016167065, 4145941303, 3897868338, 2892060643, 2413714784, 254604231, 966264223, 3162224073, 4257953665, 1775093780, 4059868817, 229216133, 3095801819, 2780776724, 4197103660, 3945827647, 3590005880, 3385750965, 588116955, 933606134, 2954149398, 3136897257, 3742737011, 1904500440, 201319529, 1627670998, 1436294506, 2391068109, 2754913831, 617553192, 1237348537, 155331642, 666659293, 2505670832, 589051162, 1617401511, 778060751, 2180910952, 4141824369, 600328318, 4045490772, 4118525083, 916092943, 3026682184, 2750156732, 1451420324, 1940219622, 2451125563, 1894319083, 712954796, 1241142933, 1547315725, 2191677486, 3213688112, 3550409294, 1708221443, 295690779, 4139342911, 4044286844, 2827851250, 3745891811, 1142267160, 1568307568, 4187843675, 2744250115, 3543324184, 3231805406, 844623162, 552365416, 2085517327, 2950237187, 3595863774, 1726025744, 3066980951, 2635434821, 3786966597, 3778968631, 2367918512, 1544339264, 3675143945, 2263950208, 256073448, 570000958, 2196435922, 3645119110, 1544421656, 3665474053, 2710076922, 3456896575, 1661288153, 798098177, 3205290044, 3267217028, 2164126201, 991695109, 2360577181, 736096951, 580335383, 440415808, 2970181697, 1174793452, 2790186381, 154139411, 682753359, 1362922244, 3445269063, 3850397629, 3630608237, 999211182, 4270325568, 2222213569, 1671798056, 898355980, 1426188949, 3343654679, 2919951295, 3693477162, 3895401157, 3560721913, 1888596458, 181288724, 3829829389, 1579972422, 3144117276, 199801876, 4054633683, 525925388, 3648577609, 286807073, 4061577217, 3752567147, 1201522573, 3610440980, 3336089737, 4143647920, 1346119142, 356944187, 3589071297, 331350548, 443179702, 4287676723, 3902224692, 670781524, 1151314689, 2224154332, 2643145761, 2418685337, 2754610868, 1367435799, 989379597, 3280309063, 664367389, 3695457682, 2932182363, 1637715984, 3078239282, 3890423242, 694186670, 1022735416, 3766855053, 96343600, 2950575721, 3694574064, 2063490620, 628896960, 3009419511, 650278649, 217113522, 4054867950, 4085775949, 2253647601, 1323118326, 2776229090, 387312318, 3830031367, 2855934165, 1727237588, 3168211450, 985024091, 4065976202, 4100263284, 920460504, 1019722484, 736802555, 1091160058, 3986567293, 3909716414, 2117717711, 1378801332, 3582605439, 3974837927, 1975607076, 341568791, 772919682, 1404531926, 2319942259, 2541979115, 1537431363, 3469010753, 2351635824, 2574168815, 471490424, 429652049, 1888748017, 256119513, 2622167989, 3890927619, 734423772, 2108123100, 2720692858, 3149485041, 3738523581, 2699573275, 2549388345, 2521302893, 2530474986, 3520669288, 417822002, 3240327386, 1661401307, 882983082, 1924087083, 4263722671, 154785737, 2892272366, 2096794030, 3065733707, 1274676481, 3173744694, 3170057336, 2560528531, 1992114189, 763608132, 886242142, 2381935549, 2696870385, 1183400652, 632435857, 1114549236, 792694237, 1050118375, 3043570987, 408243821, 3246069230, 3595014201, 4242308859, 2732256078, 417888811, 157189594, 1578645677, 979394949, 2715618148, 2084946492, 2779545872, 2746594737, 3600471957, 3690418809, 80909094, 479165038, 1299019782, 4248583974, 2122215085, 4100895072, 1510073775, 4108853940, 21876970, 3804082593, 1194473031, 1013294843, 797533856, 3555511188, 712992910, 3147433210, 230132027, 1173487980, 4269226972, 3090952473, 1190923232, 1679528279, 769279893, 1422455341, 1485744354, 391718383, 376237997, 2772702841, 3412931239, 3901610169, 2108304638, 2830169940, 3849960095, 3043501233, 3973846143, 1627749584, 2509012508, 2993028673, 3443779088, 2629553481, 3345770078, 417661904, 299926134, 4221411771, 4277090614, 1911866219, 1551326585, 93131922, 2142950833, 998841580, 2131273819, 264704024, 72761473, 311706753, 2773201027, 1819604430, 1325781384, 1828296785, 475315722, 2752215033, 140320306, 1043096704, 855365740, 2476726857, 2581734598, 3861106067, 1436208963, 3415450549, 3570329317, 2687213974, 2613842059, 516462296, 3037378709, 3263570551, 1681420526, 3415302057, 3511450549, 3273504333, 494102854, 304288318, 3697281980, 1996479758, 1635215124, 47632440, 22355542, 906188237, 4149186094, 3151082744, 2531819048, 1644757840, 3101983578, 2011269244, 3866138172, 2127822384, 1903103074, 3932219954, 1821169710, 169278046, 653152755, 1929628869, 1986843845, 1656941273, 1820043656, 2237572096, 3650186585, 3171963679, 4233697440, 3755777109, 3448968195, 133782836, 4267699280, 2851793115, 617641793, 3256436523, 1407468314, 4096930119, 1868261036, 2551660459, 17209088, 1655418735, 499829078, 3115810383, 2942436423, 1117668901, 4054638152, 3401715738, 386251371, 1788551278, 541357881, 4092916714, 2788358548, 400852308, 2632328808, 3366533041, 901146853, 3250917102, 1993332902, 1740749354, 3817981431, 2227569979, 4241229228, 65274376, 1935767139, 3249336235, 3922555776, 921336913, 2814396307, 2667550257, 2055331186, 30339902, 845791404, 3302805554, 2378743215, 3928499493, 2035920961, 4033017204, 3562284680, 2948673159, 1367405928, 2477125781, 724878315, 618610843, 3464131396, 4106290593, 2761582218, 1911670733, 2255224976, 679995901, 1694101202, 1457350452, 2415077238, 3832605769, 1548512392, 3910956093, 2960448392, 235679115, 1336039703, 4056841792, 2704719451, 1221241812, 1530676776, 758875004, 3989933820, 2315326962, 1755061483, 984103973, 3552706434, 4146283304, 1900596987, 3224925366, 4289171038, 980557750, 2062175350, 3065172916, 108844606, 293646367, 3415841496, 152825526, 2072381275, 4285030108, 2847377365, 1313245709, 1976515833, 484145483, 2307919762, 1902482190, 1346944178, 353282945, 4113734314, 1863262682, 1245717043, 2241864885, 2280528335, 1019309397, 3289776976, 2376807409, 2952610417, 103415167, 3638228557, 3235194883, 3241161224, 2125883305, 1232190514, 3549022975, 149807933, 2961278754, 2383239375, 127409706, 223990857, 1600263562, 3325399391, 2741861086, 244824352, 85948473, 3124738586, 3484658404, 2949005416, 3110472205, 1541858124, 3817776205, 69164118, 2954933199, 2925668013, 162217966, 547673095, 4181924147, 3823145053, 80676848, 868737602, 2205414045, 2279798936, 102486197, 2587491480, 2241109714, 3451004219, 1101855332, 1254174284, 4162654397, 2075550533, 3279994730, 511501950, 1774750940, 2330903266, 2010908807, 1405100744, 2399290465, 2186798761, 859965651, 680542282, 2464087287, 1717488673, 1106965230, 132594854, 1192599975, 2168482389, 2337484280, 1431281627, 2161439863, 731837641, 753400083, 718352079, 2920193564, 4014452495, 2840575861, 850092154, 4013385863, 2889779981, 1887731992, 877392739, 3501145229, 1077314268, 1838346422, 1325751328, 2289785549, 1040644978, 3430927961, 2641937927, 2285310825, 2723705356, 3969476694, 193167645, 2688798767, 1812500605, 693030278, 3173921056, 2188596291, 2180502082, 2208231604, 1512410467, 2765076968, 3989339249, 2744873321, 422780839, 2753112367, 861241423, 905851909, 1219406342, 3083085811, 2111384879, 2487677895, 362839625, 2300647559, 2252314956, 38471328, 3558718806, 1713409176, 708493886, 2645700082, 2196532746, 1397262287, 612919750, 1411685900, 1134021085, 3675861851, 2168510458, 173154823, 2489748386, 2499456938, 2828871069, 3373056478, 2660114090, 2270829594, 3459032228, 1357929287, 1162183927, 1097818577, 1542913661, 1981968930, 2944755083, 579671294, 147480949, 1988196545, 777407838, 2354930885, 2534601251, 2766511651, 68413970, 3533296816, 2575956638, 1355214150, 2719147503, 850624539, 3284264812, 3928845488, 594971150, 549980540, 1796991397, 776876250, 1460934050, 2463458608, 1640602524, 2160282188, 381030894, 2276755467, 3897004968, 1525634949, 2084303318, 4038502302, 650730684, 3893039590, 2120711163, 1075785968, 642329759, 4286493776, 298483904, 576520111, 670640982, 501843005, 2317149359, 1723210307, 2714699821, 2647759513, 3372861558, 3302356979, 1135050697, 1794914040, 2501115240, 1473307986, 4055431991, 386019549, 1642338927, 817175303, 63704969, 1918346370, 1060455488, 3296205488, 2611534290, 319202585, 3589598600, 1061424333, 256294593, 2086764847, 1889683341, 324402820, 4230133797, 971777609, 2913835299, 567526498, 3967034861, 2199121094, 2595932876, 3882641499, 3024547071, 2251608750, 1562313747, 3646762714, ], vec![10; 1840], &[ 925805970, 771512525, 1321505884, 4093572597, 758716614, 1377765832, 1278203380, 1001888643, 1355158095, 201085215, 4149044771, 2521855414, 4152533261, 3002132831, 4155360674, 1795934109, 2247306354, 2834452223, 3656644513, 2792060749, 3230919138, 483669446, 3693350164, 2766501057, 329182922, 2273808186, 1047344319, 3115798204, 3566682772, 2408293239, 2794877731, 698720575, 327005792, 1558338384, 1008199867, 2492809980, 2810143023, 1784882162, 524641759, 928770560, 1130801733, 4222233720, 195758472, 1891783101, 413324813, 3563105984, 4225585084, 205810396, 2545279346, 3861389278, 2373143813, 4024119708, 780120208, 3432178227, 1555529931, 2554973234, 2502444226, 3344683717, 1641184112, 98587931, 637912572, 1021943377, 4037505911, 614639139, 4194497843, 3049554202, 637648248, 2123348064, 2634366226, 3207837322, 3066784253, 2994933327, 1976651548, 2366296173, 1641868749, 82351438, 3355135280, 1553860281, 1605364581, 4075743977, 2941712013, 3386363575, 161305709, 3498025167, 3591439792, 3723487074, 1286356811, 2869673859, 3058493670, 1421607538, 550853035, 912260189, 555605432, 2564864712, 2716459709, 3225217761, 1778511468, 3587420558, 1207869481, 2862990086, 4126739672, 3193798621, 3165324498, 76671852, 3202055203, 3698858085, 2586219907, 2247010126, 3962725977, 2619019864, 2122584571, 2759072926, 2355594856, 2680875986, 3809288380, 3113157553, 2998504932, 1438335802, 4042229352, 3236956253, 415640042, 2304719113, 476088551, 1007695371, 2386089176, 2181311976, 736590680, 89015838, 391491629, 638291307, 2877449105, 2962906061, 3979685552, 3627063001, 492677310, 2231326821, 743398531, 1133825751, 1719921083, 1840883029, 1166898759, 1601037521, 2409186612, 1623857150, 2793429784, 1436913897, 4140973832, 582129472, 4207088238, 3200623818, 1475586379, 3384915939, 743709146, 2191495369, 3563177671, 728383298, 3754965841, 3795767466, 4009441303, 406982577, 3135143383, 1456106797, 4160967347, 2816553701, 3256668188, 1014590891, 728446496, 2331482373, 2184086986, 2476758117, 815465765, 1957139615, 93446988, 3589331411, 3457536764, 1745564725, 244069742, 3319690805, 819795556, 1486648551, 402515678, 1904027145, 2183046265, 1437045043, 3646826056, 3694590855, 3691191903, 912588953, 2869059243, 915090531, 1308341773, 1914740545, 1372995357, 1821589353, 1750436980, 3326691416, 1030623833, 1495253922, 34912358, 1499274973, 998994535, 2935614243, 1565643646, 3474712008, 2524137404, 3968547971, 732339375, 3134376500, 3712532227, 1085750881, 2607575268, 1414329062, 583507621, 2489115057, 1425727804, 624607973, 3077024829, 2685992057, 3682897129, 4071136447, 1727489833, 21203108, 3392758652, 509383349, 3119006823, 3045101600, 4129122439, 976347783, 750957340, 3621119842, 119059944, 3926834627, 3278710060, 3524620828, 2053225005, 1628028369, 1741363163, 4055830757, 877491867, 1503296989, 3349399277, 348921314, 2220238102, 2327127101, 371334052, 3730431190, 4254998900, 3276010967, 884857325, 2799001549, 551761767, 3358096790, 2020737989, 2913273611, 795353920, 995285043, 1255353878, 1081464851, 1485661898, 248227391, 2646461730, 288845121, 990971374, 4151523546, 850493727, 427991127, 2225569843, 1598181146, 924478291, 1006667974, 1424598842, 2544076586, 3839052630, 2039302967, 1751844817, 4119169517, 1378503947, 2112648581, 486800876, 1589075140, 1774624325, 3380949714, 942159303, 1934386105, 1853027873, 1625283567, 1798870407, 945414724, 1916704482, 1076254981, 3546161383, 2299585539, 3247652613, 731481822, 1011891129, 2768863308, 1813803045, 3860051875, 1174964707, 1324160940, 2574847612, 3513978083, 2554787041, 68699746, 1212730198, 996237523, 2736940550, 508920579, 174371335, 1886271926, 3087461373, 2201998413, 385737266, 2695461851, 3309543132, 1687035998, 692717227, 569529002, 642730495, 1998450569, 2877673596, 782260981, 714386348, 3796153446, 3810357608, 1220822655, 37559611, 3062930083, 1952046909, 2938302747, 1937200848, 139230150, 3652241605, 3385303728, 3427356966, 2415007129, 2062827063, 3399013574, 1412210998, 3780689301, 3309010376, 2776522750, 788159042, 2338674637, 3597251270, 1111645430, 2344936207, 987533024, 312063196, 2164245832, 2981634349, 4146252745, 509985595, 473738885, 4080179792, 767682002, 742937862, 3390341429, 1201520568, 2705803790, 1096534023, 396035895, 3045556830, 262555759, 2223158076, 2460071430, 537129776, 2525318176, 2465664490, 1718928604, 1677204238, 3488426978, 3891524565, 2842016557, 2193145485, 978116097, 1615400737, 2757085537, 2962918904, 2163577224, 4068394581, 3963381668, 3027498111, 413627370, 3985257787, 1911780465, 1431948560, 899666734, 3073534561, 3931614071, 59372171, 123789420, 1311815775, 1600081512, 3500852529, 482022179, 1349872136, 2023099554, 1623971264, 2385783366, 335038849, 4237603646, 1512003698, 1626113404, 3863467432, 503775132, 185919438, 3413070813, 769549664, 277742984, 1457016660, 3916310980, 3679543908, 428500520, 291415144, 382143301, 3479675016, 1558773305, 3828015203, 740311290, 1658202239, 1352230160, 2929801762, 1144182359, 4260518531, 3904249580, 38453053, 519928994, 611178254, 1815173805, 2687791381, 3576348672, 2210369382, 3101623249, 98144578, 4159402306, 2478115488, 3668828837, 1846949400, 4015333955, 1478301555, 2864273669, 2676396505, 2824169479, 2008756433, 871452488, 197076407, 493093639, 3590505476, 3419603591, 1983646327, 4172389974, 1331126951, 2749313151, 3914363144, 838421991, 3713866955, 66943799, 3022889908, 905930887, 3450837393, 3122388323, 3601001575, 1461966185, 1217535252, 862426054, 3891322611, 4057584483, 4137459924, 3050986698, 3775562735, 2206917997, 1326425299, 2177316293, 665366502, 1789591450, 3869393426, 4111791353, 2042667844, 3888104816, 477695341, 1400818483, 391421351, 2511869577, 1543099376, 522205537, 3741717060, 3983781829, 1450661430, 1952049614, 4059193972, 69169697, 3733732140, 2178094107, 3638192198, 2483181869, 4237963289, 2635888235, 625414314, 2309845963, 3133618224, 1030061929, 2628713359, 147776022, 3665551893, 2606716720, 450703348, 1433078851, 665870068, 4274367632, 2346780289, 34636636, 3570617418, 2610375041, 1570695957, 3235022132, 650696914, 1579637045, 3924586750, 4122461112, 3973884299, 3203913749, 1074902525, 2038914363, 1313155224, 280192559, 2654627254, 3904119153, 4289367389, 3931774924, 4088574946, 2110508780, 1965188425, 3870415513, 3028849533, 2643890058, 3118914716, 4132754639, 2063814685, 2477010069, 742144369, 3675862178, 1638220213, 1788413389, 3612081483, 2827592335, 4269582882, 3849921609, 1214642500, 3132507662, 460322913, 3555344490, 2582789072, 2773409763, 3731720324, 725828860, 4142291526, 1289918833, 2376436341, 2080195956, 3652068261, 2052975451, 1056381829, 1504404622, 3530088199, 2543774820, 3588528773, 1181550632, 4134199347, 3106435739, 2666774217, 3422590531, 3887880807, 4070997105, 1394848137, 701703628, 3061521160, 2887272490, 2229516066, 1310837786, 3154190631, 711892595, 2435668654, 4100746898, 366709793, 2800825180, 3469579669, 1872527030, 558351001, 1574511606, 3461209655, 1498408413, 1726832352, 1807209931, 1051547963, 2514355744, 3694086296, 3693097900, 169040251, 1625096327, 247216005, 1690358091, 1853931622, 2241580553, 2665852926, 378855913, 2849826467, 2882598381, 1966643823, 3863600372, 570512458, 89553660, 1580933547, 1670795700, 1701383225, 239477568, 663996049, 1663598319, 1774418754, 2745157344, 3324324155, 3068121254, 2019212774, 3363185868, 1017744423, 1422898847, 3076406441, 3863671242, 2045305657, 2537743046, 3610837965, 956029186, 1782391421, 1492413923, 3211086299, 165767576, 2846934457, 3007723858, 1141836320, 728275693, 376616587, 2573940874, 2162417375, 2260336910, 503501143, 165113603, 3530206110, 2914422259, 1430643811, 769845616, 4213816224, 3629319288, 4239130817, 2081610750, 625758813, 3255558354, 3479654242, 2472621110, 3007522636, 2750717810, 3286123194, 731654699, 2774722656, 3054704647, 3343723513, 3353349653, 3916558188, 4002272233, 2120337200, 413996446, 2630363679, 2841712842, 2347010620, 1903664219, 2118706367, 4121870331, 4262431689, 3571095308, 4041525390, 3390066445, 927914151, 2343554013, 1134637778, 3558586975, 18737389, 2499628916, 1647908776, 3587615205, 1651636386, 3701620970, 3344465418, 406209565, 1774097768, 638612711, 1894889044, 975120431, 1901267275, 3825095883, 3013288190, 1213152309, 4081208841, 2283263447, 3257861369, 566807683, 766774226, 3630232255, 2719893472, 2539687707, 3216385587, 2660398423, 654074066, 1010432189, 3431364371, 4163956052, 3832935048, 156489928, 4188655690, 1306690249, 98975214, 2421098560, 4163230789, 4156164818, 4443391, 617931997, 4154608614, 100420976, 2222597381, 2417575506, 2990762034, 204752919, 3415006628, 3522988641, 835715926, 156827736, 2308716058, 1572542144, 184997832, 157493958, 940407358, 3759427593, 2158763575, 1564687549, 3909269978, 1283986657, 2367598132, 1568363717, 1710227345, 2793907548, 2427230705, 2893825635, 3768618922, 4124795081, 810037070, 4125345353, 3607694888, 770621562, 632370000, 674117742, 765128043, 1173992895, 3674396824, 2526304384, 3829190715, 775137268, 3029466301, 2820944962, 3085195001, 2621306925, 2125299873, 2214882737, 513034349, 908126002, 3167919913, 1027217000, 1178561950, 511143524, 985493719, 1655744880, 2033154762, 1280998575, 3453548532, 1570014775, 2222753891, 3327333588, 2154641854, 1735888068, 1817079241, 2722314559, 1762274850, 1167853659, 2392945518, 196410344, 2937981909, 1154226053, 4232721914, 700255979, 2415771290, 1791869427, 2898400848, 792514249, 3599536910, 3227896255, 1529237487, 2400490460, 1826096927, 3142666937, 2785566731, 2723268878, 2079318688, 4034165354, 958450787, 1749435564, 3977035150, 3576602733, 729666328, 72221437, 1176330488, 3920869422, 3994801636, 2732985628, 1490190123, 1354581325, 568851886, 2669564985, 1060093818, 3170119834, 3226579436, 764079092, 1913198946, 1083783781, 3261947326, 380306393, 4209390001, 2158391567, 1689298052, 1046236714, 442820313, 2757723527, 3143120919, 4267903837, 3015944922, 1574598807, 2206549514, 4259852673, 442217304, 1830366479, 813570743, 365463383, 3543466921, 3138253410, 2683541076, 638143597, 995642363, 2769878603, 4107223702, 3481953453, 3133262725, 3674261732, 1033288545, 3669732737, 3503245892, 1530461030, 213751298, 1629050977, 375601856, 3395574573, 1885945502, 1714265586, 97662695, 2156915149, 148240149, 2725333961, 1842005317, 2670201827, 3018625279, 2036280580, 2241502128, 2888719467, 472203886, 1658540185, 3258448659, 2760284408, 3494196803, 3420499172, 2950901152, 4276940915, 2202303771, 1096785836, 1693282825, 1017323714, 954195871, 659807759, 2833714030, 2600259137, 2719988621, 1351376955, 889846153, 1588673264, 1457310902, 3149228705, 1509379998, 904691368, 3109598917, 2820147688, 2098775601, 556249763, 2898076541, 1003774548, 3470807399, 552610489, 3623150789, 2629316482, 1385503428, 3451073512, 997009862, 3235185265, 2184096609, 3290579922, 171379862, 3550817154, ], ); // - n >= MUL_TOOM8H_THRESHOLD * 10 / 9 test( vec![ 3325828688, 2222275271, 2251341024, 536425450, 4031282462, 1974932579, 2802802687, 2494652102, 4097509118, 3929993760, 2523272424, 3991617974, 1383705144, 964369450, 4021179190, 2350994587, 3952940920, 2309645523, 4239355231, 2251911575, 101330509, 33531098, 3923438820, 3326248612, 3928986797, 3712073953, 656648130, 3992081850, 2462208525, 1232308887, 3597612252, 355901660, 210877106, 2675099515, 3078639028, 3753546437, 2179616483, 3320544043, 4275906121, 925959266, 3421489454, 4036352291, 3528964180, 1961636686, 4029362615, 4282725968, 1508419584, 454322447, 1001429999, 2787320225, 2760755036, 1794472322, 532278069, 1568975823, 813350455, 1179027655, 3449886418, 2662435721, 327795406, 75354904, 1665124401, 3382081813, 3780617120, 608468859, 363983678, 3351287669, 172973237, 4290451185, 1931365909, 1235521618, 2978614510, 2419031024, 1057701246, 1493733706, 2567636367, 1775786991, 977238213, 375184150, 2098442552, 3863490194, 20320547, 2460513991, 3622662467, 3550564454, 866710499, 1402820025, 2079884728, 3083812684, 200095309, 3509895595, 2058450016, 802356608, 3193234061, 2967885003, 3592035474, 2888252198, 1738389872, 2122697745, 2521126706, 3044563659, 4010640449, 1357672322, 1713997889, 2361412719, 1177264933, 1279061404, 4226778687, 2234083457, 1990126293, 3249778747, 2856364385, 2539332735, 819602532, 1941236090, 148789327, 489490234, 3063005023, 3823539446, 2078730493, 2897346932, 377341414, 3559412328, 2789507932, 2744784480, 2083318692, 473338846, 1592405981, 3262908934, 3803857538, 2113012145, 4218812261, 2611838077, 2967681456, 394117396, 891428411, 94508804, 2461818431, 2882613800, 408794286, 1367921120, 3936232028, 3371928555, 13284201, 2693865930, 1445840494, 62166267, 1950431070, 903939097, 3181498906, 2135209486, 2379836866, 3164065611, 3089382166, 335815175, 4115282369, 2843606362, 3030658374, 1981636253, 1913879380, 2497243978, 1058325216, 1962967322, 2964668797, 316843966, 787872107, 3686059070, 3432414174, 2952226003, 3159358517, 3532762764, 1103507717, 3261418139, 2938324789, 1645903335, 2648573661, 4131792913, 2593029209, 466073693, 1785143940, 671647647, 3138504192, 2192173137, 2335379487, 2298646507, 686675623, 3214302238, 950130948, 2421785284, 41585098, 3553768120, 3417442608, 3058443407, 4154557833, 1412178160, 341659142, 1776579622, 1881568208, 3733601960, 964911720, 3954636144, 2069281179, 3720759380, 3881878556, 3401603350, 2025509639, 3992322872, 3417427856, 2078371992, 3655861835, 249491133, 897420882, 1663580203, 4250858290, 3783171030, 1618859415, 3059683957, 757177328, 2284779051, 1397702306, 1846926211, 1628089495, 1310971676, 638095836, 1920389982, 1228576446, 672122730, 1853316843, 991512951, 777308841, 184904686, 1065934342, 904702614, 2120865508, 3991071908, 3089750336, 2087140090, 2698642164, 2746911990, 463823593, 2169525572, 3914335068, 3895138434, 1167324714, 1405364247, 408435330, 1048149429, 1549143044, 4160291749, 2958661271, 135472469, 1664575385, 2395824355, 2799959090, 2058237486, 1885870506, 1018852433, 2464874288, 1472031882, 1920049008, 2124900114, 1894970634, 718935470, 4135614331, 2870932762, 3046996347, 1175241218, 3337056067, 2823776676, 3880099332, 317500197, 2412894185, 2360582270, 1748097135, 1117101645, 3999621027, 2508769432, 1134413571, 297583666, 315312277, 445840313, 835956286, 652883235, 3449607625, 3112977447, 3858652947, 242783714, 3248680155, 3743017765, 3771708806, 2121953660, 169624798, 3334753694, 1024518980, 2123582216, 3512992458, 181383076, 388250535, 2264863429, 559757274, 136676916, 3010225408, 3261874572, 3254590586, 2353758191, 1769226054, 2574994323, 1412248375, 2194959705, 3161480726, 1173862339, 3060136500, 2067215193, 1559995937, 4097665144, 2227105594, 57455397, 2781855816, 413139676, 1262905949, 3710184455, 4204785080, 3841061262, 2600467865, 756074612, 1833352799, 414287525, 2487131325, 225976232, 2868255206, 3149420271, 2893863898, 2674087497, 4201275735, 3557697552, 2539732703, 2075871670, 3238490486, 3281311242, 4105032293, 1061668000, 3948441870, 2632408910, 3965993308, 2773976056, 3997099675, 1044008934, 643256924, 3662238906, 2364413528, 1890816109, 653190236, 1449201495, 830290176, 1608991933, 1977703847, 3177041981, 41644776, 1806748422, 46749183, 1969966265, 650370247, 2860464309, 2000093407, 678041782, 3053985966, 4126712541, 4206913677, 1804281861, 2562943781, 402107792, 3743850770, 1880600543, 2284692048, 3402413270, 1372820757, 410822514, 365444773, 1581271018, 1311294256, 2098281541, 3795689061, 2741077395, 1671858646, 779953232, 1441988536, 4122756260, 3219142143, 2003131209, 3186044612, 3862216190, 2906214392, 2843498419, 1258517655, 2377662254, 3165185832, 3743620644, 3149688047, 1175443948, 1119755292, 2586039430, 3583379409, 100277700, 2686178939, 3718199786, 144906097, 893565260, 2837950407, 3324016696, 682674679, 31411133, 1272850441, 784780622, 3423224341, 488352871, 4077116759, 26700931, 3657423384, 143033774, 3228467568, 32720232, 2721507038, 1816011700, 2818467222, 1533431835, 1268665537, 475079949, 3341112122, 2698588771, 2611521940, 1972051120, 3510532417, 1731958257, 1183168565, 2931876429, 434380301, 1295823, 1351376380, 3803168520, 92207634, 3345836213, 549845616, 3480463245, 2630703140, 4194446958, 1396974448, 2365711823, 784004900, 3467957992, 3284726834, 1131138204, 4158973228, 2854147296, 594452704, 1221140243, 3732311917, 4211451998, 4201866268, 538219794, 228992404, 463147167, 697753586, 3806158550, 1256983333, 3561565763, 456221521, 2524923884, 2331508852, 3915487198, 2219329827, 1899461941, 1568614606, 3436289344, 4105213304, 2685855293, 1185390866, 2047983481, 1781737500, 832012199, 3513225593, 3319838870, 1020767641, 198457781, 2727609160, 3813889481, 1016920097, 666935018, 2505214320, 3346073559, 2415444335, 488746607, 2468423301, 1532367906, 244477084, 2784080007, 3392011412, 3296350838, 3408789716, 2601539997, 65837806, 3808173608, 2740909858, 313044653, 976945537, 695283633, 3903895508, 1256467142, 1796137849, 2299402928, 1030847133, 491304484, 1618179568, 3575375798, 4084273125, 842560443, 860483107, 1477578512, 463362438, 4047759459, 4170469452, 837933293, 1510207028, 1002537167, 1913407491, 484611587, 72194857, 3758699609, 1038836152, 3702790723, 1602454353, 3156992372, 555460491, 3102910892, 4107831420, 1379557424, 109354775, 324500806, 1309470828, 973263813, 2913644320, 2556229913, 20916645, 3990007622, 1827025683, 894739570, 286790026, 257745524, 2888654551, 2829856014, 4024894743, 2592875773, 3482365150, 2197208367, 2008450133, 1021127724, 252619891, 2171006932, 907971982, 3664509602, 1585606268, 3112067844, 1006461549, 3762990233, 801101738, 2502145896, 1780081016, 2853239568, 366864228, 2569203482, 376803343, 6955716, 2316603781, 1631421558, 3996270452, 2436912056, 479717229, 2577014660, 3814374282, 2295304310, 2205472042, 1941857703, 3835035113, 1672360810, 1473045908, 1338619978, 3516219559, 3903963113, 1518163632, 75200618, 1452199469, 1006778265, 2872308953, 2526575667, 3217010709, 2082180265, 3503205635, 1689527017, 1366271253, 2419427984, 3090351720, 758562413, 2893201179, 433319737, 289828739, 2697292032, 3319507333, 376413377, 1856268054, 1102691038, 406692403, 4199659161, 1030925701, 2852188477, 2282715864, 1222230217, 3204793449, 906571587, 4246852852, 2109467439, 2758293720, 2590683410, 426954830, 923580140, 1720968355, 2177884542, 2700069460, 3414003144, 882029796, 673015972, 925314297, 394315706, 2405566770, 1356681458, 3704192657, 2420160690, 105120919, 4135620617, 1146779249, 4215347588, 3808058087, 848912652, 3166226285, 2673900140, 2633829134, 4227829168, 2976863082, 2756181703, 3969932852, 2310706349, 2623195640, 2975200819, 2683387458, 3670713004, 2711197327, 1005309237, 2656065409, 3585314671, 1067912540, 3244103997, 1167067071, 1147905270, 3508458421, 4173233272, 3528308485, 2229102062, 438675126, 482013728, 933288742, 772078253, 1545301066, 2048214401, 313457524, 1830857166, 4210633504, 4033732262, 1784314122, 1876717626, 2898790181, 1714304237, 1513498365, 466291039, 2125921729, 1375952994, 1759597111, 3485421103, 988486613, 447644730, 2659753292, 800671165, 2297304303, 983566542, 706647696, 2025875912, 750248929, 3818471532, 1823442438, 797944894, 113229111, 881004126, 3388066422, 3504793499, 2531563354, 776681039, 1855992120, 3089939582, 3975063378, 2197425240, 1859908221, 1050864539, 3696699978, 2797794284, 67143977, 1476449198, 425254009, 258997293, 1600017642, 3718913920, 2057245496, 376988171, 3765611739, 1761878897, 851389543, 2221681000, 173564387, 543006829, 4033266201, 3495318826, 4944235, 77704986, 2003516763, 2947938566, 246616380, 3811434913, 1498883939, 2662747924, 3098460145, 2789081063, 2011354011, 3559521162, 2222938111, 3518312618, 2907191527, 510822818, 236641464, 2906121970, 2726617494, 1403621963, 2506337633, 1393649778, 749094150, 2141211894, 2997803954, 3536825181, 125817965, 2928546113, 3962138194, 3488998295, 2977774519, 870261554, 3145088767, 33204035, 417892208, 82457330, 3761918526, 3185089606, 3717474816, 3759935038, 718221041, 2584890356, 3125768610, 3128296046, 3921989069, 628371462, 2854153931, 2322749823, 3560748642, 3598001904, 1525423357, 3489200883, 557488134, 67075987, 215443365, 3960989574, 3610937359, 1994915328, 1322852160, 3224593059, 681359565, 1428522926, 1509511379, 2910418227, 2950733843, 2264582595, 1066502645, 1270894973, 1982059326, 3466419533, 1247820141, 2814957983, 3674243179, 359593364, 2852856092, 4250958308, 4209800488, 3182992525, 744053024, 954527614, 1920812186, 3420696600, 3538429076, 1174859849, 1575837064, 2476180617, 23409444, 2303547985, 3866558298, 3511588040, 2073420498, 2694981488, 3634968032, 3148001223, 373812485, 3760234630, 1989707843, 553246242, 2798142055, 402011062, 2572428035, 3149472471, 2641777212, 2341709250, 659173885, 2636588362, 465418139, 2855449653, 168901226, 3411187454, 3648538254, 1914534945, 2021809126, 1765630658, 4210072200, 672743231, 237435144, 1466943252, 3665058313, 1360883147, 1208845855, 4000190916, 3503509301, 1932609745, 2525291982, 3149954146, 2863621568, 4103714853, 376631824, 2290852702, 2496109340, 1639920015, 3769422630, 1510557202, 3513608516, 2550439168, 3553460045, 525038818, 4129480327, 1125484353, 2835875384, 4179933318, 2509396027, 1732889211, 2751886266, 2147307212, 387970481, 695149207, 2541343790, 2839783121, 1160657192, 3963440385, 2789882800, 2391592284, 2916503838, 3282735897, 913624563, 3175831231, 3466284576, 46459397, 3590165825, 1395008049, 54895546, 4114843666, 75582093, 1715376849, 2361175117, 2492505326, 473253401, 3209625236, 1910683327, 2303707709, 1595992099, 1067727453, 2175266120, 1187538095, 3338022275, 3861034887, 3646604070, 3901278763, 1297481444, 1740087966, 1713911231, 3579924993, 438772896, 2847030160, 1091694853, 1462997245, 223788055, 378112136, 3379831769, 1612071297, 1026371651, 3588586410, 3550643691, 3517421864, 108677329, 1708329683, 2705550295, 536532842, 1609412940, 2350366954, 3999999603, 3009090634, 3009405637, 108513089, 433572330, 630309072, 768308286, 3130148610, 696549190, 567069842, 2991858807, 3544523483, 3196876723, 392972829, 3810464826, 712888215, 4116891580, 2898306195, 3552494747, 2628398237, 4210499108, 103633346, 2236449210, 3834327177, 3420048764, 1756265114, 15054403, 4040225317, 1594762873, 3042414357, 2480439624, 4223576462, 2518287349, 1400158860, 3257170441, 1299629753, 592407606, 183091721, 3221878045, 312797076, 3985484678, 3630279986, 18819047, 441536758, 2381837163, 4169471868, 2170394338, 2181312095, 2448805236, 3378100655, 2844803458, 1168647372, 383072198, 1590554568, 2280721135, 4116487539, 3850200505, 289261506, 3357742687, 1915184525, 2779238680, 1251240337, 4273338571, 2883259275, 233548562, 4271818632, 733727140, 228666724, 2488848008, 2996503489, 1445047215, 43172552, 3015066792, 4234864747, 2683528981, 2327797015, 142567097, 1677432447, 2182227962, 3561493714, 616143851, 1146197188, 4043856658, 1532480004, 3914042242, 384129295, 1027270960, 3759841559, 3306756270, 280945974, 2272666526, 1787905496, 1356479606, 1003577488, 3182186379, 2080620780, 489613844, 2145748221, 3602256409, 4039936254, 4230034790, 1041216417, 2869721346, 1061058447, 4187665645, 2056653701, 293593624, 1671090495, 3743958178, 221756712, 669423751, 873593705, 1984521258, 596253067, 1854401523, 3641730818, 1795122963, 3434366685, 144714542, 612800121, 625529195, 2115632120, 2458286503, 2991075249, 4294925998, 3484272210, 413395376, 2841974813, 2198382581, 153452909, 2362633408, 1029933732, 365559147, 954593410, 2340863943, 4224478519, 1711517777, 2382640557, 1471136977, 1243256182, 577943866, 2877182972, 3120699107, 2099481569, 4027415860, 972360440, 328292954, 2580374611, 1126114830, 2447790959, 3167058778, 52949279, 1503347494, 3102470619, 2850741785, 1440074775, 2983184898, 2958779770, 1423341775, 2638966039, 3414709326, 1746843145, 1962096213, 1231942872, 322282459, 2520802915, 1397156397, 1136524931, 1077984387, 1082573606, 1369475996, 1343216443, 2853222460, 459314534, 2082494332, 1868894956, 2863227388, 1267699732, 3838811811, 2085654049, 3478261558, 801390064, 3020980804, 1592039288, 2043252793, 658119035, 351482607, 365151551, 2321964000, 3105703149, 2651451296, 1332089903, 203189386, 4065665344, 2087988078, 3509982235, 3663789691, 640321038, 126379371, 758704611, 2976133119, 338240358, 2847694981, 3405531815, 3501389852, 365915081, 1893710987, 1017798137, 1329052770, 900124839, 593520276, 1673088115, 2837108009, 2725846942, 2370117674, 2364056627, 1588943446, 3447621374, 4188928348, 3651554937, 3256606153, 3302425960, 3080093332, 265589115, 4231992887, 2117604928, 2355480969, 1006273543, 2284486530, 4056290811, 4091031679, 4079416675, 2288531059, 786357019, 3958013190, 3469028967, 2618870759, 2582243721, 3134347005, 1897624527, 295895331, 3299510488, 287519621, 1532582663, 3409797611, 2683376466, 4283418958, 1877809103, 2723998791, 3144672840, 3727310197, 4009525850, 889434429, 771869475, 3566747894, 2738193100, 813849012, 3911388965, 1279847132, 1685856902, 3082912514, 2067299920, 1405185595, 2885740666, 2118178130, 2496932272, 4158468024, 2915749138, 649483477, 4206421293, 2757754394, 3314522431, 2269462235, 3993183136, 3700765328, 1068976941, 4261401847, 1124755401, 3801610743, 1969610114, 3664892243, 1112960775, 1912361842, 1030225346, 967360681, 3986502374, 2169456113, 3758060719, 1480705586, 492248116, 4222874616, 3319928478, 2992291382, 2450502117, 3949036192, 1815871387, 3254185821, 711097033, 3511389055, 2820383871, 3171069864, ], vec![ 219605684, 3733847704, 3016635823, 3294762792, 3944405696, 1769872727, 832659846, 484088999, 3505517372, 665090353, 981244631, 1379204518, 2636388743, 2646535623, 4245306143, 194502210, 883787587, 458392293, 1851531468, 3012939792, 3916075164, 2268609087, 1167270783, 4176306316, 3743775706, 2950832151, 3594959653, 2285984635, 52893824, 2172982965, 1248959379, 1470557476, 1201448597, 3375520425, 3748208049, 1257559380, 837239835, 4133304044, 1858466116, 560253153, 3678427423, 455815704, 2048555203, 3908746885, 255785748, 3209187195, 3421604835, 2632159689, 316833694, 4281401440, 102090580, 3721736010, 266287611, 3373488642, 594309134, 2738851237, 1684934520, 1276732189, 2903617658, 3296557081, 3563767242, 2176348197, 2313418457, 3233080717, 2735279615, 394359834, 623713995, 140049212, 498519169, 1402029947, 1678680803, 3015892739, 427600690, 1125893168, 2179497262, 4057603178, 3496071310, 2899325724, 3677322280, 3804953038, 278886520, 645458896, 2486879584, 2394473074, 3850599181, 792951084, 663635668, 2927466603, 3639001969, 3606253415, 508580584, 396794482, 2985523809, 1445903235, 3313779349, 1676477042, 103850445, 229595348, 703720916, 2578553830, 2458841523, 1933251296, 363644571, 645442292, 2557064683, 962374614, 1700508145, 3794324048, 2584976073, 236173708, 3764420274, 279923540, 4075757279, 2235622749, 3191608858, 4006438835, 1908504238, 1404730391, 2893611100, 3418919975, 2761500606, 2538142606, 3656578307, 919774545, 1445376035, 3424913709, 554731787, 2870801108, 3893878559, 2515735309, 4049168009, 2736235180, 4046071341, 2836164363, 3926498800, 3814849323, 934280090, 89568632, 2294387373, 3912402110, 2118681178, 1351750387, 2447640447, 574461143, 3931298943, 1794049409, 825791603, 3855614361, 3804227287, 1483097620, 4259972568, 2252285343, 123276475, 3161686393, 3218037245, 256027861, 809544208, 2486313226, 1050383855, 4237284978, 2694106279, 3038308664, 3410660322, 515412998, 3869866599, 2994392437, 3269069042, 3947466847, 2883348919, 4052591666, 1863977555, 188271850, 4149287894, 3890111279, 397365955, 2163011790, 3701205263, 2638690803, 3839607326, 914036595, 4046887696, 1336652496, 822203045, 2784897683, 1265234986, 1784732027, 1447844299, 625275839, 82219488, 2987602621, 3044052434, 1181776664, 1530351091, 1110986421, 2060624013, 339066774, 1590502368, 2317588177, 2244585652, 3492887264, 2212680022, 2640475326, 348926579, 3246343174, 2561437332, 581962653, 2221706178, 4069194219, 2284871124, 3048622008, 373685125, 4025211847, 1292047419, 3120672305, 790731263, 274475368, 15199343, 1922359621, 1749773031, 4241521715, 2479848827, 743662349, 2151293746, 49164230, 344935070, 89801179, 142306069, 2327816182, 3527604729, 861275048, 3754133025, 105007617, 1606758768, 3411783480, 3900766726, 229816895, 968892827, 603676768, 3067574405, 508084800, 4163966682, 2520459787, 815626761, 3750642090, 4109045197, 4021986339, 1510247485, 3001110466, 2167226521, 3591300424, 1416732703, 910590371, 3408174912, 3155039041, 1139149626, 447404795, 2716484878, 4070167463, 308857448, 4282968848, 3099451490, 2414982180, 316232599, 642439731, 1545686574, 666961383, 897959935, 3374635967, 1881209465, 1374103300, 642609814, 502781940, 3682373645, 2489773845, 1283267440, 3894229942, 1941929986, 3934687928, 3333644753, 2997423793, 837943158, 67336216, 3255568419, 190224485, 2837663345, 4207768659, 1708933825, 2772287530, 1154500232, 1693433014, 292641434, 1754396219, 2542674547, 1190079584, 2269894063, 2721853439, 663916801, 2362454970, 731922427, 3742164411, 707311168, 3046591691, 1748326630, 1845653289, 1016681698, 2994353806, 2735719342, 2704445240, 2854070151, 1607062766, 3744430615, 3544224665, 1886417222, 3425058873, 1609422240, 542845843, 3147109760, 1424468935, 2839056308, 2918717971, 2811887991, 2790495639, 2132641907, 792891625, 3102872968, 1651448144, 998081822, 979132706, 720547406, 4025787009, 2735580435, 2457487375, 1065238981, 3412254354, 215131432, 3048596830, 1669254548, 2090345212, 509499351, 3615558193, 4162117786, 1536698846, 1534147203, 1923724108, 3528335633, 3395028864, 404544658, 4167466929, 1214045063, 3598864251, 1326576655, 855338193, 3368941689, 1401909859, 3124328704, 67082155, 1595352370, 2689198649, 770470257, 3065267028, 1211541561, 422514087, 536466990, 995741725, 2502422928, 137873536, 442872337, 2288928710, 477168639, 2527159632, 2500546045, 1397043975, 2205863722, 2911856171, 3714388841, 1549554282, 3753612677, 1890046352, 4039530596, 4146084646, 1706325322, 2454110812, 211090074, 3163995441, 1637968681, 365653242, 4282639641, 20611554, 3054560222, 1999188492, 3488521981, 2868372811, 2973275585, 796515146, 822994172, 1030297677, 1588520622, 4228102402, 2708306471, 1208006335, 2078217033, 2586553571, 303653553, 2132325166, 747687456, 1747825014, 2837410885, 438830471, 1600784035, 4134092721, 1506389233, 2127970290, 2668085318, 4089024642, 2575734777, 327185130, 2469533410, 3597704057, 462560760, 3152215881, 661472818, 1938255716, 356786526, 3439418576, 6826038, 4187428395, 60261767, 3087172989, 1450929937, 3651563872, 1589078139, 1677344341, 1470806427, 903804397, 441015765, 1272755045, 814260009, 2653285733, 3860945219, 1455674283, 1096658320, 3516576877, 3023176095, 3479966062, 3407627614, 144957111, 2468468573, 133078933, 860997956, 3491202246, 1622521278, 1232931671, 1342648914, 1925040885, 4195720141, 3799076149, 320357412, 1260627691, 1901795898, 4006861680, 2967730799, 1348760243, 1207763786, 3372249393, 3370014578, 2928367142, 1013740101, 3800825723, 3853764948, 2540691600, 4288140609, 85729198, 2054750317, 975078435, 1603168880, 752297715, 676265726, 3745588378, 1190456489, 3199796255, 2568311924, 1636039660, 4172418324, 451873022, 1488096996, 3888837104, 2380625095, 1503612236, 1174254768, 3690690154, 796118737, 950243347, 870818727, 3575441985, 2933836937, 4012643254, 4154690232, 313943165, 1194823142, 112872260, 1583856748, 3091518525, 3848126856, 2316319296, 1177342115, 1834090, 1312844134, 562564763, 968697255, 2625292379, 1560369157, 3793042995, 1360344305, 1561892888, 2561644342, 2880487899, 1329308678, 991881816, 408459653, 2048208943, 798151371, 3438869282, 3477838848, 1731589585, 2405599989, 996289971, 2339728423, 2712816129, 3199519522, 102417245, 3737926264, 2499734949, 4289682039, 2043689414, 2819686077, 1679268219, 222221440, 4008029847, 1560387789, 1298710311, 1243123895, 158514034, 3873321117, 3004642495, 3872001585, 1663566476, 1107233170, 293716059, 275162247, 936579960, 2990240463, 1926069351, 3296513110, 554621834, 4144199052, 1392609836, 1034899022, 1208790097, 2807112109, 3964061416, 1653167562, 3742290159, 2346753191, 3650591545, 522876039, 3945783347, 3065661379, 760781159, 2219622460, 82469461, 2887087892, 2552061061, 3838920437, 1162671243, 2030025601, 81626876, 1751905726, 2166036662, 1557608721, 546818324, 1585093311, 3667292391, 3522898667, 2321723183, 1047786840, 2621628330, 2989416129, 1420910156, 2819893717, 41408882, 1090794692, 254861895, 1531947943, 409858928, 2688575425, 638494402, 1137167657, 1407867246, 1512173911, 1408432723, 1473209607, 774943403, 1286624130, 3425873895, 3620263656, 1909123130, 2551706705, 1549113484, 1091256254, 2885486188, 761917899, 1632560671, 3199850510, 3435108107, 3984491598, 2758162447, 3408358152, 3614032341, 960132339, 3328987609, 1661534291, 3165532505, 2611312032, 3366533473, 1979920417, 1312551138, 117282700, 691866345, 4139053046, 3105013808, 2777561811, 2635054512, 497784664, 3126213089, 2216274215, 530791472, 4066290432, 2800488077, 636174841, 3629392743, 1077206808, 616054960, 3838079466, 2365491331, 4280387869, 4085608937, 2387284685, 2905568474, 3687210908, 2676786135, 2880576182, 2272479710, 1199932595, 2261850657, 3804274819, 3762551932, 1458028870, 2897463116, 2416202598, 3392536019, 2870202002, 3613666863, 2249394797, 2992036599, 728534566, 1120088649, 3979378545, 935693277, 1031467147, 84108903, 746798643, 627228099, 2800690251, 2173469180, 2830223765, 3137722777, 4178739722, 411466414, 859751380, 1559439628, 3694498090, 3260343774, 535054266, 117084126, 3399243337, 2495976075, 4076251817, 2926801036, 436287733, 3705696306, 3667196595, 96134495, 3729370692, 1515068169, 264787485, 2798154317, 175985133, 1313840608, 760864127, 3967639961, 3959432295, 1635932259, 3331385869, 1070261894, 246190898, 982482783, 3854791453, 2982674210, 502540469, 1076671794, 3188598990, 1279447641, 3784328740, 2394101763, 3346901062, 537444017, 1055795404, 3549995587, 1164547440, 1373235322, 371022910, 2435082373, 3557245778, 171522386, 1140771969, 3265269810, 2780244587, 1553185664, 1890478317, 3220213095, 1312302522, 2431923700, 1223485266, 2282493771, 921148941, 3067060161, 324175533, 170250519, 570500159, 1035903244, 2479701867, 255677361, 2023064938, 1790936466, 473377155, 1918210065, 2072725791, 616083034, 3885053377, 662826718, 1434245870, 1910220894, 2309848114, 525544021, 356039132, 2359013744, 4239245004, 4026803267, 194151528, 795233412, 305493034, 3267801916, 4080918986, 329727861, 2899234059, 1357709403, 3251519907, 1938363589, 4131025749, 2594354892, 1660726670, 271386306, 499198400, 1339562618, 1867450859, 3440407368, 1403232131, 1272086132, 2465102747, 1633075747, 2461437511, 635308997, 681776567, 3489150051, 220625570, 2311229261, 4200050354, 4050773484, 370413512, 931753989, 3307172724, 183245723, 1765157394, 47788463, 3937773236, 2598232722, 3424882189, 1276600447, 1644552616, 2626308042, 3268722786, 3810874590, 1058205206, 2654249153, 3483559388, 1838428373, 3023229213, 2148907687, 259958622, 2710064692, 277383554, 1415212012, 4053351646, 1877209663, 3049048356, 2164707394, 811696118, 3639050029, 2733433970, 3499435557, 84856309, 946720455, 2593206349, 1653444547, 628472620, 2602758976, 989666944, 1666426206, 4093401526, 2013618092, 20022648, 3142131018, 2920750232, 3012941536, 713849141, 217371192, 2291693390, 3420908933, 840008593, 509521091, 2216030985, 762663986, 1144893566, 1669626401, 3553089528, 3848788572, 1322528707, 1139160791, 3245062559, 354845554, 3395160786, 3002919588, 2479702839, 289294866, 1247980658, 1768709894, 38829267, 2796896988, 3280594127, 597391183, 1674125, 154337128, 1219465231, 1594491341, 215253014, 3941260773, 530738196, 1659968693, 1997144375, 2363494810, 1887727442, 2372279514, 3569468084, 704702032, 3254327350, 3274665109, 2746129291, 2402740279, 680910327, 3196302449, 1515184422, 3018121467, 1533706515, 2154506929, 4271801874, 276946657, 1454657398, 2035806618, 2347369271, 4167466602, 846913372, 678827116, 906512673, 2989625336, 3380365559, 1817466418, 746879498, 4161207963, 2652566219, 3997761296, 1729126521, 1915492417, 1387691720, 3792948085, 591813962, 4166608463, 85460956, 2019829952, 1093520400, 2115527596, 917437663, 1506881666, 2919904171, 1226740800, 2827153204, 1804490316, 3305326376, 2228657260, 4144079407, 3834647065, 2630139426, 1540825792, 2224653587, 940767108, 3878245257, 1227320069, 3532608478, 2225819731, 3888521056, 2837907080, 3526288423, 2888635755, 241668691, 2791059392, 1425900065, 900551913, 2183647741, 256669272, 723956303, 1186667535, 1960634662, 438856681, 37239087, 3623703669, 2346924024, 4084706232, 3401696786, 1070387337, 3327464499, 2530115640, 4095803022, 1354739657, 1132191762, 400698935, 3582112175, 3859178123, 3682980963, 3946109014, 99291864, 1473874678, 872297294, 2480703905, 2587482474, 4621945, 3807688592, 1223705190, 3415437317, 2878715234, 179753873, 1451307698, 2351373338, 3977117882, 742110068, 1159308459, 3051728070, 1114874234, 4063286511, 2958632124, 1126682061, 4057528706, 3462397411, 3615907500, 3832358400, 1520557386, 387566035, 4181990938, 3576980813, 1763909198, 3546068004, 2178077355, 2942665537, 1777408679, 3972359411, 1398692519, 1334374308, 109850799, 3967277062, 2696558472, 3920736437, 131453960, 1927970889, 3285016317, 1862961941, 1740391758, 4268655537, 3710775553, 145796565, 246130446, 1603042751, 595310227, 2018018140, 3941725849, 2484543949, 3362738863, 1417106401, 1903645571, 334821664, 3294839018, 757433484, 2445590565, 1336706929, 958713100, 3159315785, 391507292, 2052141380, 2910107823, 1346035310, 2963367850, 2254143762, 2499969819, 280296612, 1528879389, 902597237, 42322638, 2748873147, 2698107871, 1431611471, 1665375338, 159237274, 78229197, 3026759027, 1323534075, 3917805809, 2391056398, 1505295912, 2068279224, 1338863823, 1696316814, 2515636746, 1277950518, 3450429578, 2101302290, 3205130735, 196407224, 188726922, 3038097197, 57783385, 2383491391, 3407259298, 2799181690, 1609954168, 4123135002, 1545697370, 3578629713, 3610539005, 3582171858, 1278392959, 3967450424, 1821082540, 2433887435, 2290405682, 4274636433, 3622463783, 1758441609, 1745493987, 1614890805, 392482483, 3736377100, 3290414371, 2674564964, 2735379425, 1246652091, 3449848348, 386473850, 3866749153, 2138760498, 2782728745, 1548369266, 3567061001, 1675699086, 2780788787, 506858834, 2071383164, 4047965152, 1464258966, 3695163491, 1868717279, 3813178694, 3237288978, 986068490, 3435148318, 2122044747, 1246656336, 3896225324, 1575964969, 4213793464, 1109969802, 1452144015, 3212129159, 2302557278, 1502824613, 644906755, 2914538770, 862243454, 20971484, 3662171943, 2417948473, 1231550572, 1646849971, 853366230, 1122931640, 1756293226, 179544062, 4215085567, 3606104577, 1712071933, 4088212811, 2878352034, 3938556619, 3688177756, 2048888802, 999798004, 2557974383, 1010120016, 1928428516, 3117908667, 37540987, 246311472, 3280437538, 1881918816, 967577101, 767831376, 76432915, 1933946275, 1880512603, 2935718302, 2245985548, 3963035840, 1648734611, 2660142479, 2100871578, 3438105035, 1188821535, 2922385250, 1576180774, 1250780564, 16622501, 1607339944, 1002015015, 1956060360, 2787486043, 2001196000, 79889482, 2303305799, 836938799, 2987765730, 1277324921, 2034841065, 1879315225, 2747596182, 3859208697, 2145327881, 3726096234, 859087533, 3800200229, 2564257259, 84263127, 3662504708, 3381867668, 2731347057, 2864062630, 426312130, 3193065885, 1387307327, 4214426077, 2162510558, 3066192340, 1444678925, 1828433112, 2030683995, 1082098839, 86577056, 1337431284, 2125134795, 872245494, 1176391120, 428884772, 3304879081, 980353105, 2336105576, 3729442548, 795317116, 4102415034, 1559419254, 2186254311, 1543348898, 718848601, 2040045237, 3036429816, 1652063812, 1902927644, 849332164, 3237344326, 1209554830, 1529964693, 3810905532, 726503750, 2332940752, 369345572, 2173720310, 748171910, 2703721711, 4016901944, 2494187032, 655988358, 2624619843, 306589730, 444322440, 1527584196, ], vec![10; 2458], &[ 14315584, 3896075743, 1720456290, 1860987977, 2435033617, 3283815521, 2217962614, 3596711492, 3391485167, 1542534513, 1934312914, 3597773264, 2544643458, 1148491463, 3826173723, 532566836, 2635112328, 1797080596, 774807823, 998727897, 2159932141, 3789188038, 2274360197, 2025617756, 3512355374, 3159634613, 2709146823, 1381235091, 3610000364, 1734574093, 2844675590, 4140474299, 407090994, 4164501520, 793085329, 4062427786, 610657511, 2840989864, 251486974, 234324123, 4278826782, 4151036614, 915714573, 163464758, 588848332, 1721190312, 4005707399, 2749479472, 3315373811, 2305992663, 3034658613, 1026628922, 3044818018, 2078949981, 1076394351, 633172928, 919810481, 1844153183, 47796503, 3838473951, 3914821415, 56916074, 4224374707, 118214008, 58206586, 182773179, 2277119069, 3833074478, 1426405443, 4012102085, 3842259766, 1661555376, 4173078834, 2160138718, 2641435466, 2401625776, 4135020452, 4261341778, 3597435941, 2878333847, 1697222430, 2479834161, 3501940583, 547428987, 1699694744, 1589714856, 3094092039, 3812401988, 586705178, 1771549859, 3889356571, 2081044636, 3915524440, 2215969097, 2785923765, 2891035393, 115204411, 3555780024, 120731371, 2792997289, 2604840991, 3947175716, 2504012389, 2822841753, 1071118219, 3845128151, 4253970477, 4253952215, 1276169564, 662601090, 2764969415, 404556610, 4025178844, 3248541914, 1234899686, 927203128, 2307975612, 2491917326, 3535570818, 963945728, 24837075, 169486507, 613376340, 1332659157, 491080348, 3160651461, 4114780572, 1838553440, 1987857586, 3430700602, 2158770837, 2614368496, 1084388381, 1858796295, 1522300999, 2839927145, 2816285905, 1707265160, 2776617220, 16197005, 775024741, 1662486904, 623200432, 3946294781, 4240745436, 2146661189, 3067562449, 1836712122, 106845872, 985435189, 739872985, 1460204407, 1119513446, 330890579, 3254283935, 1656228797, 43939001, 1237958976, 3472042242, 2309388228, 1106182843, 3555794821, 36926079, 540976529, 773787735, 1327045353, 4226128278, 193584290, 1239226396, 3512329876, 278414825, 3926266087, 3786237276, 3579952270, 498291988, 2823774255, 1688087301, 1721289947, 196581659, 83087956, 4112121408, 2559494911, 2199502433, 1055770183, 2819943945, 33589713, 2283678521, 286507459, 552667298, 1451047744, 2651022894, 2228146245, 2540846830, 1050328076, 3047039299, 2766587484, 3691700280, 1049254813, 857110920, 1159205473, 1941578771, 717689503, 569892065, 3678807637, 2220477814, 1080351362, 2806798851, 3447297122, 2221865362, 930511843, 3450660262, 2680179755, 2917564544, 3939325714, 3771507323, 3259386687, 1467770684, 3837894085, 1528988932, 2370052746, 1580760722, 2250263564, 3487457499, 3543162480, 911819585, 2979157164, 3598196682, 3923086759, 2653629140, 658857317, 3722939978, 740695757, 629152520, 2170296541, 113912870, 1694943806, 3625922241, 2631571610, 3862073130, 2092081805, 22919059, 1192280719, 3218239082, 669906544, 2006614820, 2447850554, 3276882114, 1137509778, 4023609475, 2022005152, 832009711, 1067392044, 2457787508, 495444281, 4057527981, 2638116211, 1032205613, 654939893, 1867393721, 4259720808, 3864862105, 2580711081, 2986252975, 3554203437, 2309301009, 213616538, 2337770026, 794663587, 553040278, 952559472, 1647697621, 1129676241, 1195552408, 2257179988, 4158151542, 263190063, 394788678, 304472849, 1116700229, 4164233473, 4138582682, 1331620795, 3961214508, 3206483671, 3619459583, 3942761684, 1127994404, 3795525621, 1793064957, 842585732, 4265730476, 2213297660, 1058117485, 2424506278, 1522441713, 3775954625, 4272294225, 4189249235, 1363414580, 3480077270, 3908998115, 1436206873, 2926155546, 2818708656, 221476678, 1306834349, 1783935758, 3783744354, 1055993798, 3867370100, 3300333089, 3110025292, 2247488535, 4015323199, 3356815720, 2045189358, 174230219, 1749374739, 1218246124, 1727443760, 961240189, 2297210165, 3075205019, 1458465736, 596183329, 883659603, 1101688800, 3102408665, 1868011842, 1960371344, 1643686155, 1063869191, 2969813860, 3816241530, 1760766422, 2415281333, 1552385643, 3433917314, 3680135132, 2620866828, 3307471651, 1980286844, 1955169126, 2687159626, 334855600, 117109258, 1746064251, 3376322566, 3584584566, 3601971429, 604861952, 2830443525, 1679490243, 36269131, 796031070, 3561439893, 4022657332, 2985918676, 17127477, 3761141990, 1343371600, 2767901251, 3804378567, 3191436147, 3852862884, 3016005135, 1779020584, 3175770274, 511808311, 1203545175, 1008529794, 700155497, 1917226278, 1626847419, 3459828508, 1537231, 2773424015, 388817294, 3515169103, 474940622, 844323074, 1246271484, 808369492, 3662858240, 3038799386, 837049977, 694305488, 1015863588, 2925540413, 4159464622, 3677790522, 2662594853, 3511496512, 2011009488, 1290229871, 641420037, 2128199318, 596608790, 4224311625, 2444741761, 2082021242, 105250274, 3696760907, 725737773, 444696069, 1930303327, 641100376, 487548132, 3502604477, 3831249409, 3112472257, 3558333009, 2068118493, 2883838540, 1151392095, 2621367657, 456338853, 1553499738, 1204143117, 3272252059, 2070211859, 1217939590, 1139521074, 1196251017, 2724271013, 414971260, 578940848, 3971160962, 2353021486, 428914039, 1466220029, 1196519558, 1433890287, 3488235345, 1745391024, 3271389992, 2189565159, 845963688, 2022888924, 1318009346, 3106363223, 3294116257, 3097893493, 1464480728, 1050593463, 2122671271, 1211170363, 3885668892, 2267117947, 863642472, 3731190320, 1733566259, 178546948, 2468292835, 2325992738, 1754129674, 2704515549, 3611719433, 2588929153, 1954312759, 2795607335, 279835277, 57394715, 2914757129, 828581834, 3849284465, 2023672381, 880214213, 1837624514, 3173571098, 2422433820, 3834459050, 2009223418, 4111196121, 2821937543, 792678184, 3501133001, 4215472170, 2198345623, 923662366, 3183651064, 1599187385, 2463494975, 2989458960, 1408484683, 2889663583, 3518183569, 4157181297, 2205842269, 1585684381, 391762939, 2611826234, 1196804558, 1572135490, 3975160311, 2275902996, 1069102622, 1315683334, 3852967713, 3301170698, 671161065, 128192467, 2613903289, 1009831606, 3749541003, 4268007757, 3092087731, 2140417700, 4096277941, 3660903771, 614384141, 531790068, 1909595317, 860446255, 3382696660, 1061474464, 3069773013, 3315525987, 3523354010, 2175878609, 3945364084, 1871031220, 1024296174, 2318503761, 3880021755, 3483182385, 1136511304, 1854660657, 1351215670, 665018554, 200157670, 2960727314, 4133284053, 545593913, 1878146619, 4080637287, 1319623815, 1371326109, 1538817431, 1523233024, 113264668, 129051258, 2403826474, 3690426422, 1876099463, 3478112649, 2967083172, 3506759557, 409569116, 303290950, 129270085, 2185938088, 1654816429, 1606016066, 1937302705, 2748203621, 182457345, 4251467861, 4087619332, 1455766758, 16900151, 965491445, 2811127049, 30198978, 3752372717, 2055927564, 274588215, 3391994008, 1128217088, 347809028, 3079847934, 2217407060, 425522097, 2570086835, 2332474322, 3806978544, 185777147, 2699474347, 3590619670, 2292054738, 2754393328, 1364967129, 3456367406, 3229262504, 3058183589, 3530281963, 1260299809, 2813856498, 1699609618, 1560668741, 3219892482, 1660863042, 2699447087, 1139225248, 1391362567, 2863783940, 3505675545, 177973681, 2882782098, 3651046939, 2456664276, 1206225175, 2580372242, 861145421, 2184732085, 2769725519, 2282301357, 293785, 2972930264, 2386258075, 3859546565, 1169200071, 889331732, 2826596513, 817584661, 3393024390, 1855368622, 1827205276, 2387127529, 2630010835, 3209679365, 418840491, 884209449, 2057532721, 3963456408, 2146511566, 3657939615, 3357975902, 1077069037, 724050579, 3103467640, 3641072139, 2311523389, 289677346, 2339409410, 593745130, 2263567727, 138391246, 796328585, 2755156236, 2335316903, 2840103332, 2555558267, 4191162130, 2041604517, 1454327959, 2762012248, 345711112, 3271322778, 251706744, 1529366113, 1560060753, 1273744532, 1745715986, 3472355943, 4216660608, 2700388481, 356464407, 3241914579, 2079624535, 2335385338, 1915268218, 1444165795, 909641004, 3058658356, 2994984668, 478335584, 1460779062, 3467507749, 1754767550, 1567226851, 1002377325, 3381130756, 267437249, 2121264436, 253481028, 936579317, 1351715032, 3705651480, 320805320, 2843650545, 513701327, 4215594992, 917564150, 479566665, 859669441, 3157609161, 1488471594, 2176388201, 3238827013, 2441825796, 4172095140, 2146136291, 1038154134, 2320185255, 837531952, 3680644283, 2246178890, 1376172528, 1150716697, 4062481636, 3411210837, 4222364616, 1565814963, 1958710568, 3912317092, 980972994, 878840575, 3785073185, 3184461301, 2896839434, 1329190240, 1611142107, 1066960053, 3030553308, 2739555728, 1219677550, 1319663819, 3807245276, 3038804156, 3975511475, 3474347779, 1787854544, 601721716, 2066121273, 1574211264, 2629698714, 942513094, 1970368862, 253914275, 2798995017, 521161377, 4169584747, 1284753624, 1230700315, 1384968294, 1964859012, 3291627178, 1980345114, 2549783785, 3965567049, 1871888126, 2413764615, 3746715727, 47085565, 3023290394, 2113006968, 2213295793, 3257150141, 4076997720, 1957602743, 2506897077, 3936832338, 2584432072, 3577991725, 3315218282, 3479103036, 1346566712, 2371604946, 2925130936, 1641375567, 2326216376, 2392362615, 3415032383, 1114138902, 2782317125, 3786087099, 2257642242, 3028343849, 2677315638, 2362678290, 1186576050, 2383638912, 508976689, 1371440287, 157924594, 578155066, 3045004846, 1531823852, 4127560618, 193156585, 885851934, 393568866, 2698643032, 1487115201, 1785690912, 1560880139, 3506823440, 2249790562, 2196069771, 1655354644, 1502736684, 2846902313, 3224146927, 1069425847, 1484301171, 3937349528, 3672862019, 27599350, 3951201728, 346872759, 3254389195, 344295907, 2578553021, 923584949, 3534810913, 2615758701, 638597905, 271997715, 3258597336, 3729321294, 2555257257, 3160826970, 2162970558, 3448099455, 4067658524, 2977860211, 711143050, 3898990729, 477305732, 4126099437, 2285319322, 203339387, 2313974244, 3497142096, 3829537435, 2373684329, 1580063789, 1630563529, 4181047728, 4251813960, 2633137079, 239130144, 3187401945, 2137440975, 1756486693, 835326208, 1219590260, 9685703, 2802769936, 2828332335, 3395480672, 159349648, 1474549022, 753761752, 1033399146, 2663571984, 3293328810, 1708860985, 2775321734, 1290639360, 3469415209, 1932741667, 4131857604, 3548751506, 3873065925, 1317695774, 3167730054, 2212798570, 963071706, 2239017839, 1663037918, 2024879418, 1241586100, 2977324887, 3668861062, 1460374273, 1519821695, 4149671041, 3603428895, 2544181925, 1881748848, 1326890903, 934934583, 4041040169, 1251595343, 330283292, 251256048, 2781853181, 1285941088, 3857270978, 2172118120, 2411830912, 4263916993, 1501520015, 1668582518, 4232592653, 879763972, 2835329802, 2391710926, 2956348612, 1044031187, 2315020555, 832842187, 1640823936, 3687293347, 3245417753, 1428535947, 3947019553, 2520875375, 1870345747, 1192441840, 3799658925, 3361841552, 346211097, 2455121685, 883553097, 3147539750, 3584951361, 1998974973, 3410409445, 1192475577, 1099659862, 3119506960, 2253622822, 1486966019, 4268179280, 3660479674, 3393207880, 244989765, 3307625178, 2228507794, 380460232, 3068292465, 4049554096, 3930654451, 2211137620, 2857990237, 2174742086, 406693768, 3903681170, 2502874185, 337283200, 2457367138, 2750431953, 718191090, 4292594176, 4100702015, 3730247801, 892058377, 4270730729, 1475580269, 1364594981, 498258814, 1627557888, 1445371571, 381298578, 3302152308, 1501315700, 1540275847, 1508419086, 2490558448, 2211045301, 1960092236, 764821667, 3011598950, 2610267528, 1305693830, 1576485405, 482671602, 939273544, 229216422, 1132377588, 1530307612, 2725258345, 1846376247, 2496250877, 2069965191, 2820337527, 1422645778, 3199513164, 399431965, 2806995769, 1924011870, 3052206613, 2926865488, 1616505509, 2747673810, 1857370974, 2194952150, 1497926871, 3238231671, 3731302543, 2809222691, 1647371626, 4292916721, 3256825234, 3570979652, 3007380634, 2699365431, 2248095940, 885821273, 2678808130, 3323361718, 1143883958, 30479033, 2004872945, 3382927648, 2168115449, 3511946758, 278718047, 4014380536, 1096793656, 1075537158, 2961900536, 3710219996, 2157081806, 4239096658, 831258008, 3208663634, 1065180774, 1716500895, 2672567069, 1232298720, 2125798236, 134823113, 3792486128, 3436278410, 2111754152, 942157649, 2586630610, 806131922, 738294633, 637501765, 1534594581, 80662048, 2778145971, 1982921733, 1684072932, 3372420013, 3660171935, 2135748383, 2694039659, 377728688, 700503753, 2985608912, 1084882191, 4151983585, 1926421903, 3882296979, 710544755, 797297863, 1874922381, 600821424, 3469363770, 2976113533, 3097650285, 3213892345, 4283796693, 3738314537, 584844598, 1238389442, 328722752, 2261560780, 1963218488, 2722962954, 1970611970, 3995953308, 1850769515, 3152074077, 1001957645, 2384943533, 3877044968, 1975105919, 1107878264, 2803250607, 3005721228, 1384517066, 2059492073, 4218640871, 880506282, 4072429242, 1924150062, 4080336746, 203753502, 2881428894, 1944674533, 2510372468, 2208936106, 160544268, 2169335406, 1295089250, 1389517169, 601874109, 3482835876, 995715955, 860499899, 3257518826, 1582699703, 811345812, 865361290, 3350101589, 2302946008, 526905664, 3463993986, 3786007662, 1461421857, 558553300, 2659196735, 1878306353, 2120863173, 1521235460, 1668716843, 342506011, 1304470509, 1883246634, 904885016, 851659242, 618465764, 62782100, 3904388641, 3401400130, 3033132634, 3695267353, 4184494689, 2096681402, 2136444941, 2379668661, 3570388220, 3650934881, 845257826, 1658386111, 216440227, 1448252242, 3867938137, 1041551940, 1271424127, 1694854790, 2618966358, 1212830768, 2944316262, 3255928108, 1311149209, 1634132716, 46015894, 1762774538, 3731249278, 3730743730, 4122659132, 4259690078, 2131268672, 1847903623, 2590863134, 1598577933, 2201759887, 2734226325, 3886633845, 673785124, 1543386385, 2392366384, 1010403234, 1157937717, 1379471091, 2428469664, 778717505, 2131414834, 690273672, 1633129278, 275458335, 2948558713, 3736213388, 1165582721, 619527248, 3580718374, 2331959084, 4015892607, 22218657, 57793748, 78895829, 2261931181, 2176427545, 254353123, 288354796, 1811254416, 4175221279, 1999304075, 2243073703, 2406263731, 3607071103, 2509308494, 4227058988, 459041177, 1288003499, 171257138, 1527074103, 946436740, 4096275409, 3439222084, 1039960427, 682450971, 624577877, 2383738920, 3781585168, 1998082771, 456216047, 4084776014, 2465435506, 1212194082, 2219178103, 3115504881, 782294840, 3975566931, 865020752, 3621258027, 19776526, 3786071932, 3553320495, 1278472279, 360299885, 101923276, 30803414, 705340594, 3798470694, 1725093175, 3767628802, 2745865016, 2628443054, 260876871, 511035750, 4013822465, 52914465, 1896658602, 1346680681, 2022488278, 1329922307, 3852700935, 834456360, 1442297319, 842245334, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_shared_scratch_fail_1() { let mut out = vec![10, 10, 10, 10, 10]; limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_shared_scratch_fail_2() { let mut out = vec![10]; limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_shared_scratch_fail_3() { let mut out = vec![10]; limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &[2], &[3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_fail_1() { let mut out = vec![10, 10, 10, 10, 10]; let mut scratch = vec![0; 6]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &[6, 7], &[1, 2, 3], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_fail_2() { let mut out = vec![10]; let mut scratch = vec![0; 4]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &[6, 7], &[1, 2], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_divide_and_conquer_fail_3() { let mut out = vec![10]; let mut scratch = vec![0; 6]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &[2], &[3], &mut scratch); } #[test] fn limbs_mul_low_same_length_divide_and_conquer_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_25().test_properties_with_config( &config, |(out_before, xs, ys)| { let mut out = out_before.to_vec(); limbs_mul_low_same_length_divide_and_conquer_shared_scratch(&mut out, &xs, &ys); let len = xs.len(); let out_after = out[..len].to_vec(); let mut out = out_before.to_vec(); let mut scratch = vec![0; xs.len() << 1]; limbs_mul_low_same_length_divide_and_conquer(&mut out, &xs, &ys, &mut scratch); let out_after: &[Limb] = &out_after; assert_eq!(&out[..len], out_after); verify_mul_low_2(&xs, &ys, out_after); }, ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_mul_low_same_length() { let test = |xs: Vec, ys: Vec, out_before: Vec, out_after: &[Limb]| { let len = xs.len(); let mut out = out_before.clone(); limbs_mul_low_same_length(&mut out, &xs, &ys); assert_eq!(&out[..len], out_after); verify_mul_low_1(&out_before, &xs, &ys, &out); }; // - MULLO_BASECASE_THRESHOLD <= n < MULLO_DC_THRESHOLD test(vec![1; 3], series(1, 3), vec![5; 8], &[1, 3, 6]); test( vec![100, 101, 102], vec![102, 101, 100], vec![10; 7], &[10200, 20402, 30605], ); test( vec![u32::MAX; 3], vec![u32::MAX; 3], vec![10; 6], &[1, 0, 0], ); // - n >= MULLO_DC_THRESHOLD // - n < MULLO_MUL_N_THRESHOLD test( vec![ 667555911, 2348733364, 1961106649, 1440628769, 1419633260, 3052369574, 1108620071, 3434026162, 3916636599, 3102975331, 3886608438, 726540295, 1959301605, 1097548123, 4197775113, 2426454473, 1977350598, 815012862, 2487421470, 2968184113, 3186369366, 2845700438, 1474463355, 3590404890, 2351730037, 3978816218, 227579243, 185502596, 1922772057, 2864373880, 1909608765, 307719594, 4182459185, 3812324913, 1740357086, 619281590, 1426834026, 2868540501, 440166317, 3324081248, 1368857307, 3133154844, 1142185935, 2703145826, 1436656515, 2490167985, 2881509383, 725592411, 1056415214, 1801603748, 1098036334, 728276877, 1517386665, 1881520126, 2784785117, 2287558410, 3556820397, 1380321205, 706755221, 2829962299, 3613994343, 1462484606, 3627636556, 490302213, 2592459816, 866144376, 609122783, 1451416993, 3785904246, 4131235963, 74121435, 3878638497, 588893998, 1092662611, 3469958113, 2363382228, 2678844074, 1733088933, 3784272536, 4005990872, 2863454468, 3205477346, 3748950603, 3944338479, 59852399, 3489893816, 1468407650, 596065110, 1335233230, 3643254705, 1408578383, 2465303822, 2349399082, 3471899735, 2696915607, 1269986424, ], vec![ 2722576082, 2281236300, 3094793404, 2870225073, 1804040671, 2878250398, 737079723, 822732050, 655707872, 4207992704, 1851690693, 912905035, 3291778825, 2516279380, 636556658, 2839780581, 3193297014, 1756749995, 3651621870, 628948913, 380312917, 2361120672, 2262818273, 2071766395, 4162768312, 2516781023, 3406285004, 1455245572, 2587465945, 1378482824, 241323934, 2280756750, 242112740, 69419369, 2603755088, 2163412563, 1341439609, 321882770, 736087982, 2995521870, 3671192545, 1265948417, 548486283, 3124707078, 290930553, 742853646, 118648394, 3811259549, 2371785381, 2042286901, 3723558867, 783245266, 2393779385, 1940230299, 1556220091, 3235087403, 2441469134, 1125637818, 1712201794, 2216073164, 4175845099, 958349548, 4262398424, 3171987471, 363107024, 2664611701, 2971536098, 2823614641, 1683011498, 1406296445, 3951206397, 3996972934, 3905528336, 920273699, 1258344157, 2971218980, 1721322990, 1804720416, 3946193389, 1866895548, 2875334355, 2152965895, 1192611565, 3662025315, 3450196924, 3273347968, 3209563794, 1516062635, 679683317, 1998597190, 2857249714, 771410307, 3851158594, 2246899647, 1910389835, 3917001975, ], vec![10; 96], &[ 4002931774, 1904598186, 3234829245, 3606564796, 1306091105, 2193187486, 3152048235, 591394468, 3956728348, 1387100164, 1906336788, 3282287701, 520335280, 185717337, 2805648626, 3053703744, 140292430, 3997128531, 231327311, 15232560, 1661811744, 661469371, 576722126, 854577401, 4168087387, 3545117380, 2423373377, 3239419618, 806391738, 3880336495, 622341226, 2747181685, 1811142986, 3822894835, 1547377963, 661471733, 100990771, 311111243, 617447537, 2129281438, 830310054, 2479129328, 3642060387, 3489744434, 1954771548, 3535568842, 3876438817, 943110050, 2741340933, 1863625282, 3029160300, 687011149, 2856703096, 1137282724, 1230235236, 3485141654, 2955294074, 4088046039, 1413613081, 4175441078, 3746030422, 287749227, 1646738360, 1501205414, 1096064838, 1755515350, 2556528506, 238519283, 3569605126, 796573795, 4090746106, 4149522856, 583205784, 2821201119, 3555712047, 1090519982, 2976948004, 3580487377, 627104596, 1130079835, 490101583, 1570134181, 648065435, 1085439524, 3896882529, 2919299575, 3301848876, 1413509397, 3259269725, 2509252448, 2214096765, 1288915975, 2839044440, 1348673262, 916617232, 3060106377, ], ); // - n >= MULLO_MUL_N_THRESHOLD // - !TUNE_PROGRAM_BUILD && MULLO_MUL_N_THRESHOLD > MUL_FFT_THRESHOLD test( series(1, 9000), series(2, 9000), vec![10; 9000], &[ 2, 7, 16, 30, 50, 77, 112, 156, 210, 275, 352, 442, 546, 665, 800, 952, 1122, 1311, 1520, 1750, 2002, 2277, 2576, 2900, 3250, 3627, 4032, 4466, 4930, 5425, 5952, 6512, 7106, 7735, 8400, 9102, 9842, 10621, 11440, 12300, 13202, 14147, 15136, 16170, 17250, 18377, 19552, 20776, 22050, 23375, 24752, 26182, 27666, 29205, 30800, 32452, 34162, 35931, 37760, 39650, 41602, 43617, 45696, 47840, 50050, 52327, 54672, 57086, 59570, 62125, 64752, 67452, 70226, 73075, 76000, 79002, 82082, 85241, 88480, 91800, 95202, 98687, 102256, 105910, 109650, 113477, 117392, 121396, 125490, 129675, 133952, 138322, 142786, 147345, 152000, 156752, 161602, 166551, 171600, 176750, 182002, 187357, 192816, 198380, 204050, 209827, 215712, 221706, 227810, 234025, 240352, 246792, 253346, 260015, 266800, 273702, 280722, 287861, 295120, 302500, 310002, 317627, 325376, 333250, 341250, 349377, 357632, 366016, 374530, 383175, 391952, 400862, 409906, 419085, 428400, 437852, 447442, 457171, 467040, 477050, 487202, 497497, 507936, 518520, 529250, 540127, 551152, 562326, 573650, 585125, 596752, 608532, 620466, 632555, 644800, 657202, 669762, 682481, 695360, 708400, 721602, 734967, 748496, 762190, 776050, 790077, 804272, 818636, 833170, 847875, 862752, 877802, 893026, 908425, 924000, 939752, 955682, 971791, 988080, 1004550, 1021202, 1038037, 1055056, 1072260, 1089650, 1107227, 1124992, 1142946, 1161090, 1179425, 1197952, 1216672, 1235586, 1254695, 1274000, 1293502, 1313202, 1333101, 1353200, 1373500, 1394002, 1414707, 1435616, 1456730, 1478050, 1499577, 1521312, 1543256, 1565410, 1587775, 1610352, 1633142, 1656146, 1679365, 1702800, 1726452, 1750322, 1774411, 1798720, 1823250, 1848002, 1872977, 1898176, 1923600, 1949250, 1975127, 2001232, 2027566, 2054130, 2080925, 2107952, 2135212, 2162706, 2190435, 2218400, 2246602, 2275042, 2303721, 2332640, 2361800, 2391202, 2420847, 2450736, 2480870, 2511250, 2541877, 2572752, 2603876, 2635250, 2666875, 2698752, 2730882, 2763266, 2795905, 2828800, 2861952, 2895362, 2929031, 2962960, 2997150, 3031602, 3066317, 3101296, 3136540, 3172050, 3207827, 3243872, 3280186, 3316770, 3353625, 3390752, 3428152, 3465826, 3503775, 3542000, 3580502, 3619282, 3658341, 3697680, 3737300, 3777202, 3817387, 3857856, 3898610, 3939650, 3980977, 4022592, 4064496, 4106690, 4149175, 4191952, 4235022, 4278386, 4322045, 4366000, 4410252, 4454802, 4499651, 4544800, 4590250, 4636002, 4682057, 4728416, 4775080, 4822050, 4869327, 4916912, 4964806, 5013010, 5061525, 5110352, 5159492, 5208946, 5258715, 5308800, 5359202, 5409922, 5460961, 5512320, 5564000, 5616002, 5668327, 5720976, 5773950, 5827250, 5880877, 5934832, 5989116, 6043730, 6098675, 6153952, 6209562, 6265506, 6321785, 6378400, 6435352, 6492642, 6550271, 6608240, 6666550, 6725202, 6784197, 6843536, 6903220, 6963250, 7023627, 7084352, 7145426, 7206850, 7268625, 7330752, 7393232, 7456066, 7519255, 7582800, 7646702, 7710962, 7775581, 7840560, 7905900, 7971602, 8037667, 8104096, 8170890, 8238050, 8305577, 8373472, 8441736, 8510370, 8579375, 8648752, 8718502, 8788626, 8859125, 8930000, 9001252, 9072882, 9144891, 9217280, 9290050, 9363202, 9436737, 9510656, 9584960, 9659650, 9734727, 9810192, 9886046, 9962290, 10038925, 10115952, 10193372, 10271186, 10349395, 10428000, 10507002, 10586402, 10666201, 10746400, 10827000, 10908002, 10989407, 11071216, 11153430, 11236050, 11319077, 11402512, 11486356, 11570610, 11655275, 11740352, 11825842, 11911746, 11998065, 12084800, 12171952, 12259522, 12347511, 12435920, 12524750, 12614002, 12703677, 12793776, 12884300, 12975250, 13066627, 13158432, 13250666, 13343330, 13436425, 13529952, 13623912, 13718306, 13813135, 13908400, 14004102, 14100242, 14196821, 14293840, 14391300, 14489202, 14587547, 14686336, 14785570, 14885250, 14985377, 15085952, 15186976, 15288450, 15390375, 15492752, 15595582, 15698866, 15802605, 15906800, 16011452, 16116562, 16222131, 16328160, 16434650, 16541602, 16649017, 16756896, 16865240, 16974050, 17083327, 17193072, 17303286, 17413970, 17525125, 17636752, 17748852, 17861426, 17974475, 18088000, 18202002, 18316482, 18431441, 18546880, 18662800, 18779202, 18896087, 19013456, 19131310, 19249650, 19368477, 19487792, 19607596, 19727890, 19848675, 19969952, 20091722, 20213986, 20336745, 20460000, 20583752, 20708002, 20832751, 20958000, 21083750, 21210002, 21336757, 21464016, 21591780, 21720050, 21848827, 21978112, 22107906, 22238210, 22369025, 22500352, 22632192, 22764546, 22897415, 23030800, 23164702, 23299122, 23434061, 23569520, 23705500, 23842002, 23979027, 24116576, 24254650, 24393250, 24532377, 24672032, 24812216, 24952930, 25094175, 25235952, 25378262, 25521106, 25664485, 25808400, 25952852, 26097842, 26243371, 26389440, 26536050, 26683202, 26830897, 26979136, 27127920, 27277250, 27427127, 27577552, 27728526, 27880050, 28032125, 28184752, 28337932, 28491666, 28645955, 28800800, 28956202, 29112162, 29268681, 29425760, 29583400, 29741602, 29900367, 30059696, 30219590, 30380050, 30541077, 30702672, 30864836, 31027570, 31190875, 31354752, 31519202, 31684226, 31849825, 32016000, 32182752, 32350082, 32517991, 32686480, 32855550, 33025202, 33195437, 33366256, 33537660, 33709650, 33882227, 34055392, 34229146, 34403490, 34578425, 34753952, 34930072, 35106786, 35284095, 35462000, 35640502, 35819602, 35999301, 36179600, 36360500, 36542002, 36724107, 36906816, 37090130, 37274050, 37458577, 37643712, 37829456, 38015810, 38202775, 38390352, 38578542, 38767346, 38956765, 39146800, 39337452, 39528722, 39720611, 39913120, 40106250, 40300002, 40494377, 40689376, 40885000, 41081250, 41278127, 41475632, 41673766, 41872530, 42071925, 42271952, 42472612, 42673906, 42875835, 43078400, 43281602, 43485442, 43689921, 43895040, 44100800, 44307202, 44514247, 44721936, 44930270, 45139250, 45348877, 45559152, 45770076, 45981650, 46193875, 46406752, 46620282, 46834466, 47049305, 47264800, 47480952, 47697762, 47915231, 48133360, 48352150, 48571602, 48791717, 49012496, 49233940, 49456050, 49678827, 49902272, 50126386, 50351170, 50576625, 50802752, 51029552, 51257026, 51485175, 51714000, 51943502, 52173682, 52404541, 52636080, 52868300, 53101202, 53334787, 53569056, 53804010, 54039650, 54275977, 54512992, 54750696, 54989090, 55228175, 55467952, 55708422, 55949586, 56191445, 56434000, 56677252, 56921202, 57165851, 57411200, 57657250, 57904002, 58151457, 58399616, 58648480, 58898050, 59148327, 59399312, 59651006, 59903410, 60156525, 60410352, 60664892, 60920146, 61176115, 61432800, 61690202, 61948322, 62207161, 62466720, 62727000, 62988002, 63249727, 63512176, 63775350, 64039250, 64303877, 64569232, 64835316, 65102130, 65369675, 65637952, 65906962, 66176706, 66447185, 66718400, 66990352, 67263042, 67536471, 67810640, 68085550, 68361202, 68637597, 68914736, 69192620, 69471250, 69750627, 70030752, 70311626, 70593250, 70875625, 71158752, 71442632, 71727266, 72012655, 72298800, 72585702, 72873362, 73161781, 73450960, 73740900, 74031602, 74323067, 74615296, 74908290, 75202050, 75496577, 75791872, 76087936, 76384770, 76682375, 76980752, 77279902, 77579826, 77880525, 78182000, 78484252, 78787282, 79091091, 79395680, 79701050, 80007202, 80314137, 80621856, 80930360, 81239650, 81549727, 81860592, 82172246, 82484690, 82797925, 83111952, 83426772, 83742386, 84058795, 84376000, 84694002, 85012802, 85332401, 85652800, 85974000, 86296002, 86618807, 86942416, 87266830, 87592050, 87918077, 88244912, 88572556, 88901010, 89230275, 89560352, 89891242, 90222946, 90555465, 90888800, 91222952, 91557922, 91893711, 92230320, 92567750, 92906002, 93245077, 93584976, 93925700, 94267250, 94609627, 94952832, 95296866, 95641730, 95987425, 96333952, 96681312, 97029506, 97378535, 97728400, 98079102, 98430642, 98783021, 99136240, 99490300, 99845202, 100200947, 100557536, 100914970, 101273250, 101632377, 101992352, 102353176, 102714850, 103077375, 103440752, 103804982, 104170066, 104536005, 104902800, 105270452, 105638962, 106008331, 106378560, 106749650, 107121602, 107494417, 107868096, 108242640, 108618050, 108994327, 109371472, 109749486, 110128370, 110508125, 110888752, 111270252, 111652626, 112035875, 112420000, 112805002, 113190882, 113577641, 113965280, 114353800, 114743202, 115133487, 115524656, 115916710, 116309650, 116703477, 117098192, 117493796, 117890290, 118287675, 118685952, 119085122, 119485186, 119886145, 120288000, 120690752, 121094402, 121498951, 121904400, 122310750, 122718002, 123126157, 123535216, 123945180, 124356050, 124767827, 125180512, 125594106, 126008610, 126424025, 126840352, 127257592, 127675746, 128094815, 128514800, 128935702, 129357522, 129780261, 130203920, 130628500, 131054002, 131480427, 131907776, 132336050, 132765250, 133195377, 133626432, 134058416, 134491330, 134925175, 135359952, 135795662, 136232306, 136669885, 137108400, 137547852, 137988242, 138429571, 138871840, 139315050, 139759202, 140204297, 140650336, 141097320, 141545250, 141994127, 142443952, 142894726, 143346450, 143799125, 144252752, 144707332, 145162866, 145619355, 146076800, 146535202, 146994562, 147454881, 147916160, 148378400, 148841602, 149305767, 149770896, 150236990, 150704050, 151172077, 151641072, 152111036, 152581970, 153053875, 153526752, 154000602, 154475426, 154951225, 155428000, 155905752, 156384482, 156864191, 157344880, 157826550, 158309202, 158792837, 159277456, 159763060, 160249650, 160737227, 161225792, 161715346, 162205890, 162697425, 163189952, 163683472, 164177986, 164673495, 165170000, 165667502, 166166002, 166665501, 167166000, 167667500, 168170002, 168673507, 169178016, 169683530, 170190050, 170697577, 171206112, 171715656, 172226210, 172737775, 173250352, 173763942, 174278546, 174794165, 175310800, 175828452, 176347122, 176866811, 177387520, 177909250, 178432002, 178955777, 179480576, 180006400, 180533250, 181061127, 181590032, 182119966, 182650930, 183182925, 183715952, 184250012, 184785106, 185321235, 185858400, 186396602, 186935842, 187476121, 188017440, 188559800, 189103202, 189647647, 190193136, 190739670, 191287250, 191835877, 192385552, 192936276, 193488050, 194040875, 194594752, 195149682, 195705666, 196262705, 196820800, 197379952, 197940162, 198501431, 199063760, 199627150, 200191602, 200757117, 201323696, 201891340, 202460050, 203029827, 203600672, 204172586, 204745570, 205319625, 205894752, 206470952, 207048226, 207626575, 208206000, 208786502, 209368082, 209950741, 210534480, 211119300, 211705202, 212292187, 212880256, 213469410, 214059650, 214650977, 215243392, 215836896, 216431490, 217027175, 217623952, 218221822, 218820786, 219420845, 220022000, 220624252, 221227602, 221832051, 222437600, 223044250, 223652002, 224260857, 224870816, 225481880, 226094050, 226707327, 227321712, 227937206, 228553810, 229171525, 229790352, 230410292, 231031346, 231653515, 232276800, 232901202, 233526722, 234153361, 234781120, 235410000, 236040002, 236671127, 237303376, 237936750, 238571250, 239206877, 239843632, 240481516, 241120530, 241760675, 242401952, 243044362, 243687906, 244332585, 244978400, 245625352, 246273442, 246922671, 247573040, 248224550, 248877202, 249530997, 250185936, 250842020, 251499250, 252157627, 252817152, 253477826, 254139650, 254802625, 255466752, 256132032, 256798466, 257466055, 258134800, 258804702, 259475762, 260147981, 260821360, 261495900, 262171602, 262848467, 263526496, 264205690, 264886050, 265567577, 266250272, 266934136, 267619170, 268305375, 268992752, 269681302, 270371026, 271061925, 271754000, 272447252, 273141682, 273837291, 274534080, 275232050, 275931202, 276631537, 277333056, 278035760, 278739650, 279444727, 280150992, 280858446, 281567090, 282276925, 282987952, 283700172, 284413586, 285128195, 285844000, 286561002, 287279202, 287998601, 288719200, 289441000, 290164002, 290888207, 291613616, 292340230, 293068050, 293797077, 294527312, 295258756, 295991410, 296725275, 297460352, 298196642, 298934146, 299672865, 300412800, 301153952, 301896322, 302639911, 303384720, 304130750, 304878002, 305626477, 306376176, 307127100, 307879250, 308632627, 309387232, 310143066, 310900130, 311658425, 312417952, 313178712, 313940706, 314703935, 315468400, 316234102, 317001042, 317769221, 318538640, 319309300, 320081202, 320854347, 321628736, 322404370, 323181250, 323959377, 324738752, 325519376, 326301250, 327084375, 327868752, 328654382, 329441266, 330229405, 331018800, 331809452, 332601362, 333394531, 334188960, 334984650, 335781602, 336579817, 337379296, 338180040, 338982050, 339785327, 340589872, 341395686, 342202770, 343011125, 343820752, 344631652, 345443826, 346257275, 347072000, 347888002, 348705282, 349523841, 350343680, 351164800, 351987202, 352810887, 353635856, 354462110, 355289650, 356118477, 356948592, 357779996, 358612690, 359446675, 360281952, 361118522, 361956386, 362795545, 363636000, 364477752, 365320802, 366165151, 367010800, 367857750, 368706002, 369555557, 370406416, 371258580, 372112050, 372966827, 373822912, 374680306, 375539010, 376399025, 377260352, 378122992, 378986946, 379852215, 380718800, 381586702, 382455922, 383326461, 384198320, 385071500, 385946002, 386821827, 387698976, 388577450, 389457250, 390338377, 391220832, 392104616, 392989730, 393876175, 394763952, 395653062, 396543506, 397435285, 398328400, 399222852, 400118642, 401015771, 401914240, 402814050, 403715202, 404617697, 405521536, 406426720, 407333250, 408241127, 409150352, 410060926, 410972850, 411886125, 412800752, 413716732, 414634066, 415552755, 416472800, 417394202, 418316962, 419241081, 420166560, 421093400, 422021602, 422951167, 423882096, 424814390, 425748050, 426683077, 427619472, 428557236, 429496370, 430436875, 431378752, 432322002, 433266626, 434212625, 435160000, 436108752, 437058882, 438010391, 438963280, 439917550, 440873202, 441830237, 442788656, 443748460, 444709650, 445672227, 446636192, 447601546, 448568290, 449536425, 450505952, 451476872, 452449186, 453422895, 454398000, 455374502, 456352402, 457331701, 458312400, 459294500, 460278002, 461262907, 462249216, 463236930, 464226050, 465216577, 466208512, 467201856, 468196610, 469192775, 470190352, 471189342, 472189746, 473191565, 474194800, 475199452, 476205522, 477213011, 478221920, 479232250, 480244002, 481257177, 482271776, 483287800, 484305250, 485324127, 486344432, 487366166, 488389330, 489413925, 490439952, 491467412, 492496306, 493526635, 494558400, 495591602, 496626242, 497662321, 498699840, 499738800, 500779202, 501821047, 502864336, 503909070, 504955250, 506002877, 507051952, 508102476, 509154450, 510207875, 511262752, 512319082, 513376866, 514436105, 515496800, 516558952, 517622562, 518687631, 519754160, 520822150, 521891602, 522962517, 524034896, 525108740, 526184050, 527260827, 528339072, 529418786, 530499970, 531582625, 532666752, 533752352, 534839426, 535927975, 537018000, 538109502, 539202482, 540296941, 541392880, 542490300, 543589202, 544689587, 545791456, 546894810, 547999650, 549105977, 550213792, 551323096, 552433890, 553546175, 554659952, 555775222, 556891986, 558010245, 559130000, 560251252, 561374002, 562498251, 563624000, 564751250, 565880002, 567010257, 568142016, 569275280, 570410050, 571546327, 572684112, 573823406, 574964210, 576106525, 577250352, 578395692, 579542546, 580690915, 581840800, 582992202, 584145122, 585299561, 586455520, 587613000, 588772002, 589932527, 591094576, 592258150, 593423250, 594589877, 595758032, 596927716, 598098930, 599271675, 600445952, 601621762, 602799106, 603977985, 605158400, 606340352, 607523842, 608708871, 609895440, 611083550, 612273202, 613464397, 614657136, 615851420, 617047250, 618244627, 619443552, 620644026, 621846050, 623049625, 624254752, 625461432, 626669666, 627879455, 629090800, 630303702, 631518162, 632734181, 633951760, 635170900, 636391602, 637613867, 638837696, 640063090, 641290050, 642518577, 643748672, 644980336, 646213570, 647448375, 648684752, 649922702, 651162226, 652403325, 653646000, 654890252, 656136082, 657383491, 658632480, 659883050, 661135202, 662388937, 663644256, 664901160, 666159650, 667419727, 668681392, 669944646, 671209490, 672475925, 673743952, 675013572, 676284786, 677557595, 678832000, 680108002, 681385602, 682664801, 683945600, 685228000, 686512002, 687797607, 689084816, 690373630, 691664050, 692956077, 694249712, 695544956, 696841810, 698140275, 699440352, 700742042, 702045346, 703350265, 704656800, 705964952, 707274722, 708586111, 709899120, 711213750, 712530002, 713847877, 715167376, 716488500, 717811250, 719135627, 720461632, 721789266, 723118530, 724449425, 725781952, 727116112, 728451906, 729789335, 731128400, 732469102, 733811442, 735155421, 736501040, 737848300, 739197202, 740547747, 741899936, 743253770, 744609250, 745966377, 747325152, 748685576, 750047650, 751411375, 752776752, 754143782, 755512466, 756882805, 758254800, 759628452, 761003762, 762380731, 763759360, 765139650, 766521602, 767905217, 769290496, 770677440, 772066050, 773456327, 774848272, 776241886, 777637170, 779034125, 780432752, 781833052, 783235026, 784638675, 786044000, 787451002, 788859682, 790270041, 791682080, 793095800, 794511202, 795928287, 797347056, 798767510, 800189650, 801613477, 803038992, 804466196, 805895090, 807325675, 808757952, 810191922, 811627586, 813064945, 814504000, 815944752, 817387202, 818831351, 820277200, 821724750, 823174002, 824624957, 826077616, 827531980, 828988050, 830445827, 831905312, 833366506, 834829410, 836294025, 837760352, 839228392, 840698146, 842169615, 843642800, 845117702, 846594322, 848072661, 849552720, 851034500, 852518002, 854003227, 855490176, 856978850, 858469250, 859961377, 861455232, 862950816, 864448130, 865947175, 867447952, 868950462, 870454706, 871960685, 873468400, 874977852, 876489042, 878001971, 879516640, 881033050, 882551202, 884071097, 885592736, 887116120, 888641250, 890168127, 891696752, 893227126, 894759250, 896293125, 897828752, 899366132, 900905266, 902446155, 903988800, 905533202, 907079362, 908627281, 910176960, 911728400, 913281602, 914836567, 916393296, 917951790, 919512050, 921074077, 922637872, 924203436, 925770770, 927339875, 928910752, 930483402, 932057826, 933634025, 935212000, 936791752, 938373282, 939956591, 941541680, 943128550, 944717202, 946307637, 947899856, 949493860, 951089650, 952687227, 954286592, 955887746, 957490690, 959095425, 960701952, 962310272, 963920386, 965532295, 967146000, 968761502, 970378802, 971997901, 973618800, 975241500, 976866002, 978492307, 980120416, 981750330, 983382050, 985015577, 986650912, 988288056, 989927010, 991567775, 993210352, 994854742, 996500946, 998148965, 999798800, 1001450452, 1003103922, 1004759211, 1006416320, 1008075250, 1009736002, 1011398577, 1013062976, 1014729200, 1016397250, 1018067127, 1019738832, 1021412366, 1023087730, 1024764925, 1026443952, 1028124812, 1029807506, 1031492035, 1033178400, 1034866602, 1036556642, 1038248521, 1039942240, 1041637800, 1043335202, 1045034447, 1046735536, 1048438470, 1050143250, 1051849877, 1053558352, 1055268676, 1056980850, 1058694875, 1060410752, 1062128482, 1063848066, 1065569505, 1067292800, 1069017952, 1070744962, 1072473831, 1074204560, 1075937150, 1077671602, 1079407917, 1081146096, 1082886140, 1084628050, 1086371827, 1088117472, 1089864986, 1091614370, 1093365625, 1095118752, 1096873752, 1098630626, 1100389375, 1102150000, 1103912502, 1105676882, 1107443141, 1109211280, 1110981300, 1112753202, 1114526987, 1116302656, 1118080210, 1119859650, 1121640977, 1123424192, 1125209296, 1126996290, 1128785175, 1130575952, 1132368622, 1134163186, 1135959645, 1137758000, 1139558252, 1141360402, 1143164451, 1144970400, 1146778250, 1148588002, 1150399657, 1152213216, 1154028680, 1155846050, 1157665327, 1159486512, 1161309606, 1163134610, 1164961525, 1166790352, 1168621092, 1170453746, 1172288315, 1174124800, 1175963202, 1177803522, 1179645761, 1181489920, 1183336000, 1185184002, 1187033927, 1188885776, 1190739550, 1192595250, 1194452877, 1196312432, 1198173916, 1200037330, 1201902675, 1203769952, 1205639162, 1207510306, 1209383385, 1211258400, 1213135352, 1215014242, 1216895071, 1218777840, 1220662550, 1222549202, 1224437797, 1226328336, 1228220820, 1230115250, 1232011627, 1233909952, 1235810226, 1237712450, 1239616625, 1241522752, 1243430832, 1245340866, 1247252855, 1249166800, 1251082702, 1253000562, 1254920381, 1256842160, 1258765900, 1260691602, 1262619267, 1264548896, 1266480490, 1268414050, 1270349577, 1272287072, 1274226536, 1276167970, 1278111375, 1280056752, 1282004102, 1283953426, 1285904725, 1287858000, 1289813252, 1291770482, 1293729691, 1295690880, 1297654050, 1299619202, 1301586337, 1303555456, 1305526560, 1307499650, 1309474727, 1311451792, 1313430846, 1315411890, 1317394925, 1319379952, 1321366972, 1323355986, 1325346995, 1327340000, 1329335002, 1331332002, 1333331001, 1335332000, 1337335000, 1339340002, 1341347007, 1343356016, 1345367030, 1347380050, 1349395077, 1351412112, 1353431156, 1355452210, 1357475275, 1359500352, 1361527442, 1363556546, 1365587665, 1367620800, 1369655952, 1371693122, 1373732311, 1375773520, 1377816750, 1379862002, 1381909277, 1383958576, 1386009900, 1388063250, 1390118627, 1392176032, 1394235466, 1396296930, 1398360425, 1400425952, 1402493512, 1404563106, 1406634735, 1408708400, 1410784102, 1412861842, 1414941621, 1417023440, 1419107300, 1421193202, 1423281147, 1425371136, 1427463170, 1429557250, 1431653377, 1433751552, 1435851776, 1437954050, 1440058375, 1442164752, 1444273182, 1446383666, 1448496205, 1450610800, 1452727452, 1454846162, 1456966931, 1459089760, 1461214650, 1463341602, 1465470617, 1467601696, 1469734840, 1471870050, 1474007327, 1476146672, 1478288086, 1480431570, 1482577125, 1484724752, 1486874452, 1489026226, 1491180075, 1493336000, 1495494002, 1497654082, 1499816241, 1501980480, 1504146800, 1506315202, 1508485687, 1510658256, 1512832910, 1515009650, 1517188477, 1519369392, 1521552396, 1523737490, 1525924675, 1528113952, 1530305322, 1532498786, 1534694345, 1536892000, 1539091752, 1541293602, 1543497551, 1545703600, 1547911750, 1550122002, 1552334357, 1554548816, 1556765380, 1558984050, 1561204827, 1563427712, 1565652706, 1567879810, 1570109025, 1572340352, 1574573792, 1576809346, 1579047015, 1581286800, 1583528702, 1585772722, 1588018861, 1590267120, 1592517500, 1594770002, 1597024627, 1599281376, 1601540250, 1603801250, 1606064377, 1608329632, 1610597016, 1612866530, 1615138175, 1617411952, 1619687862, 1621965906, 1624246085, 1626528400, 1628812852, 1631099442, 1633388171, 1635679040, 1637972050, 1640267202, 1642564497, 1644863936, 1647165520, 1649469250, 1651775127, 1654083152, 1656393326, 1658705650, 1661020125, 1663336752, 1665655532, 1667976466, 1670299555, 1672624800, 1674952202, 1677281762, 1679613481, 1681947360, 1684283400, 1686621602, 1688961967, 1691304496, 1693649190, 1695996050, 1698345077, 1700696272, 1703049636, 1705405170, 1707762875, 1710122752, 1712484802, 1714849026, 1717215425, 1719584000, 1721954752, 1724327682, 1726702791, 1729080080, 1731459550, 1733841202, 1736225037, 1738611056, 1740999260, 1743389650, 1745782227, 1748176992, 1750573946, 1752973090, 1755374425, 1757777952, 1760183672, 1762591586, 1765001695, 1767414000, 1769828502, 1772245202, 1774664101, 1777085200, 1779508500, 1781934002, 1784361707, 1786791616, 1789223730, 1791658050, 1794094577, 1796533312, 1798974256, 1801417410, 1803862775, 1806310352, 1808760142, 1811212146, 1813666365, 1816122800, 1818581452, 1821042322, 1823505411, 1825970720, 1828438250, 1830908002, 1833379977, 1835854176, 1838330600, 1840809250, 1843290127, 1845773232, 1848258566, 1850746130, 1853235925, 1855727952, 1858222212, 1860718706, 1863217435, 1865718400, 1868221602, 1870727042, 1873234721, 1875744640, 1878256800, 1880771202, 1883287847, 1885806736, 1888327870, 1890851250, 1893376877, 1895904752, 1898434876, 1900967250, 1903501875, 1906038752, 1908577882, 1911119266, 1913662905, 1916208800, 1918756952, 1921307362, 1923860031, 1926414960, 1928972150, 1931531602, 1934093317, 1936657296, 1939223540, 1941792050, 1944362827, 1946935872, 1949511186, 1952088770, 1954668625, 1957250752, 1959835152, 1962421826, 1965010775, 1967602000, 1970195502, 1972791282, 1975389341, 1977989680, 1980592300, 1983197202, 1985804387, 1988413856, 1991025610, 1993639650, 1996255977, 1998874592, 2001495496, 2004118690, 2006744175, 2009371952, 2012002022, 2014634386, 2017269045, 2019906000, 2022545252, 2025186802, 2027830651, 2030476800, 2033125250, 2035776002, 2038429057, 2041084416, 2043742080, 2046402050, 2049064327, 2051728912, 2054395806, 2057065010, 2059736525, 2062410352, 2065086492, 2067764946, 2070445715, 2073128800, 2075814202, 2078501922, 2081191961, 2083884320, 2086579000, 2089276002, 2091975327, 2094676976, 2097380950, 2100087250, 2102795877, 2105506832, 2108220116, 2110935730, 2113653675, 2116373952, 2119096562, 2121821506, 2124548785, 2127278400, 2130010352, 2132744642, 2135481271, 2138220240, 2140961550, 2143705202, 2146451197, 2149199536, 2151950220, 2154703250, 2157458627, 2160216352, 2162976426, 2165738850, 2168503625, 2171270752, 2174040232, 2176812066, 2179586255, 2182362800, 2185141702, 2187922962, 2190706581, 2193492560, 2196280900, 2199071602, 2201864667, 2204660096, 2207457890, 2210258050, 2213060577, 2215865472, 2218672736, 2221482370, 2224294375, 2227108752, 2229925502, 2232744626, 2235566125, 2238390000, 2241216252, 2244044882, 2246875891, 2249709280, 2252545050, 2255383202, 2258223737, 2261066656, 2263911960, 2266759650, 2269609727, 2272462192, 2275317046, 2278174290, 2281033925, 2283895952, 2286760372, 2289627186, 2292496395, 2295368000, 2298242002, 2301118402, 2303997201, 2306878400, 2309762000, 2312648002, 2315536407, 2318427216, 2321320430, 2324216050, 2327114077, 2330014512, 2332917356, 2335822610, 2338730275, 2341640352, 2344552842, 2347467746, 2350385065, 2353304800, 2356226952, 2359151522, 2362078511, 2365007920, 2367939750, 2370874002, 2373810677, 2376749776, 2379691300, 2382635250, 2385581627, 2388530432, 2391481666, 2394435330, 2397391425, 2400349952, 2403310912, 2406274306, 2409240135, 2412208400, 2415179102, 2418152242, 2421127821, 2424105840, 2427086300, 2430069202, 2433054547, 2436042336, 2439032570, 2442025250, 2445020377, 2448017952, 2451017976, 2454020450, 2457025375, 2460032752, 2463042582, 2466054866, 2469069605, 2472086800, 2475106452, 2478128562, 2481153131, 2484180160, 2487209650, 2490241602, 2493276017, 2496312896, 2499352240, 2502394050, 2505438327, 2508485072, 2511534286, 2514585970, 2517640125, 2520696752, 2523755852, 2526817426, 2529881475, 2532948000, 2536017002, 2539088482, 2542162441, 2545238880, 2548317800, 2551399202, 2554483087, 2557569456, 2560658310, 2563749650, 2566843477, 2569939792, 2573038596, 2576139890, 2579243675, 2582349952, 2585458722, 2588569986, 2591683745, 2594800000, 2597918752, 2601040002, 2604163751, 2607290000, 2610418750, 2613550002, 2616683757, 2619820016, 2622958780, 2626100050, 2629243827, 2632390112, 2635538906, 2638690210, 2641844025, 2645000352, 2648159192, 2651320546, 2654484415, 2657650800, 2660819702, 2663991122, 2667165061, 2670341520, 2673520500, 2676702002, 2679886027, 2683072576, 2686261650, 2689453250, 2692647377, 2695844032, 2699043216, 2702244930, 2705449175, 2708655952, 2711865262, 2715077106, 2718291485, 2721508400, 2724727852, 2727949842, 2731174371, 2734401440, 2737631050, 2740863202, 2744097897, 2747335136, 2750574920, 2753817250, 2757062127, 2760309552, 2763559526, 2766812050, 2770067125, 2773324752, 2776584932, 2779847666, 2783112955, 2786380800, 2789651202, 2792924162, 2796199681, 2799477760, 2802758400, 2806041602, 2809327367, 2812615696, 2815906590, 2819200050, 2822496077, 2825794672, 2829095836, 2832399570, 2835705875, 2839014752, 2842326202, 2845640226, 2848956825, 2852276000, 2855597752, 2858922082, 2862248991, 2865578480, 2868910550, 2872245202, 2875582437, 2878922256, 2882264660, 2885609650, 2888957227, 2892307392, 2895660146, 2899015490, 2902373425, 2905733952, 2909097072, 2912462786, 2915831095, 2919202000, 2922575502, 2925951602, 2929330301, 2932711600, 2936095500, 2939482002, 2942871107, 2946262816, 2949657130, 2953054050, 2956453577, 2959855712, 2963260456, 2966667810, 2970077775, 2973490352, 2976905542, 2980323346, 2983743765, 2987166800, 2990592452, 2994020722, 2997451611, 3000885120, 3004321250, 3007760002, 3011201377, 3014645376, 3018092000, 3021541250, 3024993127, 3028447632, 3031904766, 3035364530, 3038826925, 3042291952, 3045759612, 3049229906, 3052702835, 3056178400, 3059656602, 3063137442, 3066620921, 3070107040, 3073595800, 3077087202, 3080581247, 3084077936, 3087577270, 3091079250, 3094583877, 3098091152, 3101601076, 3105113650, 3108628875, 3112146752, 3115667282, 3119190466, 3122716305, 3126244800, 3129775952, 3133309762, 3136846231, 3140385360, 3143927150, 3147471602, 3151018717, 3154568496, 3158120940, 3161676050, 3165233827, 3168794272, 3172357386, 3175923170, 3179491625, 3183062752, 3186636552, 3190213026, 3193792175, 3197374000, 3200958502, 3204545682, 3208135541, 3211728080, 3215323300, 3218921202, 3222521787, 3226125056, 3229731010, 3233339650, 3236950977, 3240564992, 3244181696, 3247801090, 3251423175, 3255047952, 3258675422, 3262305586, 3265938445, 3269574000, 3273212252, 3276853202, 3280496851, 3284143200, 3287792250, 3291444002, 3295098457, 3298755616, 3302415480, 3306078050, 3309743327, 3313411312, 3317082006, 3320755410, 3324431525, 3328110352, 3331791892, 3335476146, 3339163115, 3342852800, 3346545202, 3350240322, 3353938161, 3357638720, 3361342000, 3365048002, 3368756727, 3372468176, 3376182350, 3379899250, 3383618877, 3387341232, 3391066316, 3394794130, 3398524675, 3402257952, 3405993962, 3409732706, 3413474185, 3417218400, 3420965352, 3424715042, 3428467471, 3432222640, 3435980550, 3439741202, 3443504597, 3447270736, 3451039620, 3454811250, 3458585627, 3462362752, 3466142626, 3469925250, 3473710625, 3477498752, 3481289632, 3485083266, 3488879655, 3492678800, 3496480702, 3500285362, 3504092781, 3507902960, 3511715900, 3515531602, 3519350067, 3523171296, 3526995290, 3530822050, 3534651577, 3538483872, 3542318936, 3546156770, 3549997375, 3553840752, 3557686902, 3561535826, 3565387525, 3569242000, 3573099252, 3576959282, 3580822091, 3584687680, 3588556050, 3592427202, 3596301137, 3600177856, 3604057360, 3607939650, 3611824727, 3615712592, 3619603246, 3623496690, 3627392925, 3631291952, 3635193772, 3639098386, 3643005795, 3646916000, 3650829002, 3654744802, 3658663401, 3662584800, 3666509000, 3670436002, 3674365807, 3678298416, 3682233830, 3686172050, 3690113077, 3694056912, 3698003556, 3701953010, 3705905275, 3709860352, 3713818242, 3717778946, 3721742465, 3725708800, 3729677952, 3733649922, 3737624711, 3741602320, 3745582750, 3749566002, 3753552077, 3757540976, 3761532700, 3765527250, 3769524627, 3773524832, 3777527866, 3781533730, 3785542425, 3789553952, 3793568312, 3797585506, 3801605535, 3805628400, 3809654102, 3813682642, 3817714021, 3821748240, 3825785300, 3829825202, 3833867947, 3837913536, 3841961970, 3846013250, 3850067377, 3854124352, 3858184176, 3862246850, 3866312375, 3870380752, 3874451982, 3878526066, 3882603005, 3886682800, 3890765452, 3894850962, 3898939331, 3903030560, 3907124650, 3911221602, 3915321417, 3919424096, 3923529640, 3927638050, 3931749327, 3935863472, 3939980486, 3944100370, 3948223125, 3952348752, 3956477252, 3960608626, 3964742875, 3968880000, 3973020002, 3977162882, 3981308641, 3985457280, 3989608800, 3993763202, 3997920487, 4002080656, 4006243710, 4010409650, 4014578477, 4018750192, 4022924796, 4027102290, 4031282675, 4035465952, 4039652122, 4043841186, 4048033145, 4052228000, 4056425752, 4060626402, 4064829951, 4069036400, 4073245750, 4077458002, 4081673157, 4085891216, 4090112180, 4094336050, 4098562827, 4102792512, 4107025106, 4111260610, 4115499025, 4119740352, 4123984592, 4128231746, 4132481815, 4136734800, 4140990702, 4145249522, 4149511261, 4153775920, 4158043500, 4162314002, 4166587427, 4170863776, 4175143050, 4179425250, 4183710377, 4187998432, 4192289416, 4196583330, 4200880175, 4205179952, 4209482662, 4213788306, 4218096885, 4222408400, 4226722852, 4231040242, 4235360571, 4239683840, 4244010050, 4248339202, 4252671297, 4257006336, 4261344320, 4265685250, 4270029127, 4274375952, 4278725726, 4283078450, 4287434125, 4291792752, 1187036, 5551571, 9919060, 14289505, 18662907, 23039267, 27418586, 31800865, 36186105, 40574307, 44965472, 49359601, 53756695, 58156755, 62559782, 66965777, 71374741, 75786675, 80201580, 84619457, 89040307, 93464131, 97890930, 102320705, 106753457, 111189187, 115627896, 120069585, 124514255, 128961907, 133412542, 137866161, 142322765, 146782355, 151244932, 155710497, 160179051, 164650595, 169125130, 173602657, 178083177, 182566691, 187053200, 191542705, 196035207, 200530707, 205029206, 209530705, 214035205, 218542707, 223053212, 227566721, 232083235, 236602755, 241125282, 245650817, 250179361, 254710915, 259245480, 263783057, 268323647, 272867251, 277413870, 281963505, 286516157, 291071827, 295630516, 300192225, 304756955, 309324707, 313895482, 318469281, 323046105, 327625955, 332208832, 336794737, 341383671, 345975635, 350570630, 355168657, 359769717, 364373811, 368980940, 373591105, 378204307, 382820547, 387439826, 392062145, 396687505, 401315907, 405947352, 410581841, 415219375, 419859955, 424503582, 429150257, 433799981, 438452755, 443108580, 447767457, 452429387, 457094371, 461762410, 466433505, 471107657, 475784867, 480465136, 485148465, 489834855, 494524307, 499216822, 503912401, 508611045, 513312755, 518017532, 522725377, 527436291, 532150275, 536867330, 541587457, 546310657, 551036931, 555766280, 560498705, 565234207, 569972787, 574714446, 579459185, 584207005, 588957907, 593711892, 598468961, 603229115, 607992355, 612758682, 617528097, 622300601, 627076195, 631854880, 636636657, 641421527, 646209491, 651000550, 655794705, 660591957, 665392307, 670195756, 675002305, 679811955, 684624707, 689440562, 694259521, 699081585, 703906755, 708735032, 713566417, 718400911, 723238515, 728079230, 732923057, 737769997, 742620051, 747473220, 752329505, 757188907, 762051427, 766917066, 771785825, 776657705, 781532707, 786410832, 791292081, 796176455, 801063955, 805954582, 810848337, 815745221, 820645235, 825548380, 830454657, 835364067, 840276611, 845192290, 850111105, 855033057, 859958147, 864886376, 869817745, 874752255, 879689907, 884630702, 889574641, 894521725, 899471955, 904425332, 909381857, 914341531, 919304355, 924270330, 929239457, 934211737, 939187171, 944165760, 949147505, 954132407, 959120467, 964111686, 969106065, 974103605, 979104307, 984108172, 989115201, 994125395, 999138755, 1004155282, 1009174977, 1014197841, 1019223875, 1024253080, 1029285457, 1034321007, 1039359731, 1044401630, 1049446705, 1054494957, 1059546387, 1064600996, 1069658785, 1074719755, 1079783907, 1084851242, 1089921761, 1094995465, 1100072355, 1105152432, 1110235697, 1115322151, 1120411795, 1125504630, 1130600657, 1135699877, 1140802291, 1145907900, 1151016705, 1156128707, 1161243907, 1166362306, 1171483905, 1176608705, 1181736707, 1186867912, 1192002321, 1197139935, 1202280755, 1207424782, 1212572017, 1217722461, 1222876115, 1228032980, 1233193057, 1238356347, 1243522851, 1248692570, 1253865505, 1259041657, 1264221027, 1269403616, 1274589425, 1279778455, 1284970707, 1290166182, 1295364881, 1300566805, 1305771955, 1310980332, 1316191937, 1321406771, 1326624835, 1331846130, 1337070657, 1342298417, 1347529411, 1352763640, 1358001105, 1363241807, 1368485747, 1373732926, 1378983345, 1384237005, 1389493907, 1394754052, 1400017441, 1405284075, 1410553955, 1415827082, 1421103457, 1426383081, 1431665955, 1436952080, 1442241457, 1447534087, 1452829971, 1458129110, 1463431505, 1468737157, 1474046067, 1479358236, 1484673665, 1489992355, 1495314307, 1500639522, 1505968001, 1511299745, 1516634755, 1521973032, 1527314577, 1532659391, 1538007475, 1543358830, 1548713457, 1554071357, 1559432531, 1564796980, 1570164705, 1575535707, 1580909987, 1586287546, 1591668385, 1597052505, 1602439907, 1607830592, 1613224561, 1618621815, 1624022355, 1629426182, 1634833297, 1640243701, 1645657395, 1651074380, 1656494657, 1661918227, 1667345091, 1672775250, 1678208705, 1683645457, 1689085507, 1694528856, 1699975505, 1705425455, 1710878707, 1716335262, 1721795121, 1727258285, 1732724755, 1738194532, 1743667617, 1749144011, 1754623715, 1760106730, 1765593057, 1771082697, 1776575651, 1782071920, 1787571505, 1793074407, 1798580627, 1804090166, 1809603025, 1815119205, 1820638707, 1826161532, 1831687681, 1837217155, 1842749955, 1848286082, 1853825537, 1859368321, 1864914435, 1870463880, 1876016657, 1881572767, 1887132211, 1892694990, 1898261105, 1903830557, 1909403347, 1914979476, 1920558945, 1926141755, 1931727907, 1937317402, 1942910241, 1948506425, 1954105955, 1959708832, 1965315057, 1970924631, 1976537555, 1982153830, 1987773457, 1993396437, 1999022771, 2004652460, 2010285505, 2015921907, 2021561667, 2027204786, 2032851265, 2038501105, 2044154307, 2049810872, 2055470801, 2061134095, 2066800755, 2072470782, 2078144177, 2083820941, 2089501075, 2095184580, 2100871457, 2106561707, 2112255331, 2117952330, 2123652705, 2129356457, 2135063587, 2140774096, 2146487985, 2152205255, 2157925907, 2163649942, 2169377361, 2175108165, 2180842355, 2186579932, 2192320897, 2198065251, 2203812995, 2209564130, 2215318657, 2221076577, 2226837891, 2232602600, 2238370705, 2244142207, 2249917107, 2255695406, 2261477105, 2267262205, 2273050707, 2278842612, 2284637921, 2290436635, 2296238755, 2302044282, 2307853217, 2313665561, 2319481315, 2325300480, 2331123057, 2336949047, 2342778451, 2348611270, 2354447505, 2360287157, 2366130227, 2371976716, 2377826625, 2383679955, 2389536707, 2395396882, 2401260481, 2407127505, 2412997955, 2418871832, 2424749137, 2430629871, 2436514035, 2442401630, 2448292657, 2454187117, 2460085011, 2465986340, 2471891105, 2477799307, 2483710947, 2489626026, 2495544545, 2501466505, 2507391907, 2513320752, 2519253041, 2525188775, 2531127955, 2537070582, 2543016657, 2548966181, 2554919155, 2560875580, 2566835457, 2572798787, 2578765571, 2584735810, 2590709505, 2596686657, 2602667267, 2608651336, 2614638865, 2620629855, 2626624307, 2632622222, 2638623601, 2644628445, 2650636755, 2656648532, 2662663777, 2668682491, 2674704675, 2680730330, 2686759457, 2692792057, 2698828131, 2704867680, 2710910705, 2716957207, 2723007187, 2729060646, 2735117585, 2741178005, 2747241907, 2753309292, 2759380161, 2765454515, 2771532355, 2777613682, 2783698497, 2789786801, 2795878595, 2801973880, 2808072657, 2814174927, 2820280691, 2826389950, 2832502705, 2838618957, 2844738707, 2850861956, 2856988705, 2863118955, 2869252707, 2875389962, 2881530721, 2887674985, 2893822755, 2899974032, 2906128817, 2912287111, 2918448915, 2924614230, 2930783057, 2936955397, 2943131251, 2949310620, 2955493505, 2961679907, 2967869827, 2974063266, 2980260225, 2986460705, 2992664707, 2998872232, 3005083281, 3011297855, 3017515955, 3023737582, 3029962737, 3036191421, 3042423635, 3048659380, 3054898657, 3061141467, 3067387811, 3073637690, 3079891105, 3086148057, 3092408547, 3098672576, 3104940145, 3111211255, 3117485907, 3123764102, 3130045841, 3136331125, 3142619955, 3148912332, 3155208257, 3161507731, 3167810755, 3174117330, 3180427457, 3186741137, 3193058371, 3199379160, 3205703505, 3212031407, 3218362867, 3224697886, 3231036465, 3237378605, 3243724307, 3250073572, 3256426401, 3262782795, 3269142755, 3275506282, 3281873377, 3288244041, 3294618275, 3300996080, 3307377457, 3313762407, 3320150931, 3326543030, 3332938705, 3339337957, 3345740787, 3352147196, 3358557185, 3364970755, 3371387907, 3377808642, 3384232961, 3390660865, 3397092355, 3403527432, 3409966097, 3416408351, 3422854195, 3429303630, 3435756657, 3442213277, 3448673491, 3455137300, 3461604705, 3468075707, 3474550307, 3481028506, 3487510305, 3493995705, 3500484707, 3506977312, 3513473521, 3519973335, 3526476755, 3532983782, 3539494417, 3546008661, 3552526515, 3559047980, 3565573057, 3572101747, 3578634051, 3585169970, 3591709505, 3598252657, 3604799427, 3611349816, 3617903825, 3624461455, 3631022707, 3637587582, 3644156081, 3650728205, 3657303955, 3663883332, 3670466337, 3677052971, 3683643235, 3690237130, 3696834657, 3703435817, 3710040611, 3716649040, 3723261105, 3729876807, 3736496147, 3743119126, 3749745745, 3756376005, 3763009907, 3769647452, 3776288641, 3782933475, 3789581955, 3796234082, 3802889857, 3809549281, 3816212355, 3822879080, 3829549457, 3836223487, 3842901171, 3849582510, 3856267505, 3862956157, 3869648467, 3876344436, 3883044065, 3889747355, 3896454307, 3903164922, 3909879201, 3916597145, 3923318755, 3930044032, 3936772977, 3943505591, 3950241875, 3956981830, 3963725457, 3970472757, 3977223731, 3983978380, 3990736705, 3997498707, 4004264387, 4011033746, 4017806785, 4024583505, 4031363907, 4038147992, 4044935761, 4051727215, 4058522355, 4065321182, 4072123697, 4078929901, 4085739795, 4092553380, 4099370657, 4106191627, 4113016291, 4119844650, 4126676705, 4133512457, 4140351907, 4147195056, 4154041905, 4160892455, 4167746707, 4174604662, 4181466321, 4188331685, 4195200755, 4202073532, 4208950017, 4215830211, 4222714115, 4229601730, 4236493057, 4243388097, 4250286851, 4257189320, 4264095505, 4271005407, 4277919027, 4284836366, 4291757425, 3714909, 10643412, 17575637, 24511586, 31451260, 38394660, 45341787, 52292642, 59247226, 66205540, 73167585, 80133362, 87102872, 94076116, 101053095, 108033810, 115018262, 122006452, 128998381, 135994050, 142993460, 149996612, 157003507, 164014146, 171028530, 178046660, 185068537, 192094162, 199123536, 206156660, 213193535, 220234162, 227278542, 234326676, 241378565, 248434210, 255493612, 262556772, 269623691, 276694370, 283768810, 290847012, 297928977, 305014706, 312104200, 319197460, 326294487, 333395282, 340499846, 347608180, 354720285, 361836162, 368955812, 376079236, 383206435, 390337410, 397472162, 404610692, 411753001, 418899090, 426048960, 433202612, 440360047, 447521266, 454686270, 461855060, 469027637, 476204002, 483384156, 490568100, 497755835, 504947362, 512142682, 519341796, 526544705, 533751410, 540961912, 548176212, 555394311, 562616210, 569841910, 577071412, 584304717, 591541826, 598782740, 606027460, 613275987, 620528322, 627784466, 635044420, 642308185, 649575762, 656847152, 664122356, 671401375, 678684210, 685970862, 693261332, 700555621, 707853730, 715155660, 722461412, 729770987, 737084386, 744401610, 751722660, 759047537, 766376242, 773708776, 781045140, 788385335, 795729362, 803077222, 810428916, 817784445, 825143810, 832507012, 839874052, 847244931, 854619650, 861998210, 869380612, 876766857, 884156946, 891550880, 898948660, 906350287, 913755762, 921165086, 928578260, 935995285, 943416162, 950840892, 958269476, 965701915, 973138210, 980578362, 988022372, 995470241, 1002921970, 1010377560, 1017837012, 1025300327, 1032767506, 1040238550, 1047713460, 1055192237, 1062674882, 1070161396, 1077651780, 1085146035, 1092644162, 1100146162, 1107652036, 1115161785, 1122675410, 1130192912, 1137714292, 1145239551, 1152768690, 1160301710, 1167838612, 1175379397, 1182924066, 1190472620, 1198025060, 1205581387, 1213141602, 1220705706, 1228273700, 1235845585, 1243421362, 1251001032, 1258584596, 1266172055, 1273763410, 1281358662, 1288957812, 1296560861, 1304167810, 1311778660, 1319393412, 1327012067, 1334634626, 1342261090, 1349891460, 1357525737, 1365163922, 1372806016, 1380452020, 1388101935, 1395755762, 1403413502, 1411075156, 1418740725, 1426410210, 1434083612, 1441760932, 1449442171, 1457127330, 1464816410, 1472509412, 1480206337, 1487907186, 1495611960, 1503320660, 1511033287, 1518749842, 1526470326, 1534194740, 1541923085, 1549655362, 1557391572, 1565131716, 1572875795, 1580623810, 1588375762, 1596131652, 1603891481, 1611655250, 1619422960, 1627194612, 1634970207, 1642749746, 1650533230, 1658320660, 1666112037, 1673907362, 1681706636, 1689509860, 1697317035, 1705128162, 1712943242, 1720762276, 1728585265, 1736412210, 1744243112, 1752077972, 1759916791, 1767759570, 1775606310, 1783457012, 1791311677, 1799170306, 1807032900, 1814899460, 1822769987, 1830644482, 1838522946, 1846405380, 1854291785, 1862182162, 1870076512, 1877974836, 1885877135, 1893783410, 1901693662, 1909607892, 1917526101, 1925448290, 1933374460, 1941304612, 1949238747, 1957176866, 1965118970, 1973065060, 1981015137, 1988969202, 1996927256, 2004889300, 2012855335, 2020825362, 2028799382, 2036777396, 2044759405, 2052745410, 2060735412, 2068729412, 2076727411, 2084729410, 2092735410, 2100745412, 2108759417, 2116777426, 2124799440, 2132825460, 2140855487, 2148889522, 2156927566, 2164969620, 2173015685, 2181065762, 2189119852, 2197177956, 2205240075, 2213306210, 2221376362, 2229450532, 2237528721, 2245610930, 2253697160, 2261787412, 2269881687, 2277979986, 2286082310, 2294188660, 2302299037, 2310413442, 2318531876, 2326654340, 2334780835, 2342911362, 2351045922, 2359184516, 2367327145, 2375473810, 2383624512, 2391779252, 2399938031, 2408100850, 2416267710, 2424438612, 2432613557, 2440792546, 2448975580, 2457162660, 2465353787, 2473548962, 2481748186, 2489951460, 2498158785, 2506370162, 2514585592, 2522805076, 2531028615, 2539256210, 2547487862, 2555723572, 2563963341, 2572207170, 2580455060, 2588707012, 2596963027, 2605223106, 2613487250, 2621755460, 2630027737, 2638304082, 2646584496, 2654868980, 2663157535, 2671450162, 2679746862, 2688047636, 2696352485, 2704661410, 2712974412, 2721291492, 2729612651, 2737937890, 2746267210, 2754600612, 2762938097, 2771279666, 2779625320, 2787975060, 2796328887, 2804686802, 2813048806, 2821414900, 2829785085, 2838159362, 2846537732, 2854920196, 2863306755, 2871697410, 2880092162, 2888491012, 2896893961, 2905301010, 2913712160, 2922127412, 2930546767, 2938970226, 2947397790, 2955829460, 2964265237, 2972705122, 2981149116, 2989597220, 2998049435, 3006505762, 3014966202, 3023430756, 3031899425, 3040372210, 3048849112, 3057330132, 3065815271, 3074304530, 3082797910, 3091295412, 3099797037, 3108302786, 3116812660, 3125326660, 3133844787, 3142367042, 3150893426, 3159423940, 3167958585, 3176497362, 3185040272, 3193587316, 3202138495, 3210693810, 3219253262, 3227816852, 3236384581, 3244956450, 3253532460, 3262112612, 3270696907, 3279285346, 3287877930, 3296474660, 3305075537, 3313680562, 3322289736, 3330903060, 3339520535, 3348142162, 3356767942, 3365397876, 3374031965, 3382670210, 3391312612, 3399959172, 3408609891, 3417264770, 3425923810, 3434587012, 3443254377, 3451925906, 3460601600, 3469281460, 3477965487, 3486653682, 3495346046, 3504042580, 3512743285, 3521448162, 3530157212, 3538870436, 3547587835, 3556309410, 3565035162, 3573765092, 3582499201, 3591237490, 3599979960, 3608726612, 3617477447, 3626232466, 3634991670, 3643755060, 3652522637, 3661294402, 3670070356, 3678850500, 3687634835, 3696423362, 3705216082, 3714012996, 3722814105, 3731619410, 3740428912, 3749242612, 3758060511, 3766882610, 3775708910, 3784539412, 3793374117, 3802213026, 3811056140, 3819903460, 3828754987, 3837610722, 3846470666, 3855334820, 3864203185, 3873075762, 3881952552, 3890833556, 3899718775, 3908608210, 3917501862, 3926399732, 3935301821, 3944208130, 3953118660, 3962033412, 3970952387, 3979875586, 3988803010, 3997734660, 4006670537, 4015610642, 4024554976, 4033503540, 4042456335, 4051413362, 4060374622, 4069340116, 4078309845, 4087283810, 4096262012, 4105244452, 4114231131, 4123222050, 4132217210, 4141216612, 4150220257, 4159228146, 4168240280, 4177256660, 4186277287, 4195302162, 4204331286, 4213364660, 4222402285, 4231444162, 4240490292, 4249540676, 4258595315, 4267654210, 4276717362, 4285784772, 4294856441, 8965074, 18045265, 27129717, 36218432, 45311411, 54408655, 63510165, 72615942, 81725987, 90840301, 99958885, 109081740, 118208867, 127340267, 136475941, 145615890, 154760115, 163908617, 173061397, 182218456, 191379795, 200545415, 209715317, 218889502, 228067971, 237250725, 246437765, 255629092, 264824707, 274024611, 283228805, 292437290, 301650067, 310867137, 320088501, 329314160, 338544115, 347778367, 357016917, 366259766, 375506915, 384758365, 394014117, 403274172, 412538531, 421807195, 431080165, 440357442, 449639027, 458924921, 468215125, 477509640, 486808467, 496111607, 505419061, 514730830, 524046915, 533367317, 542692037, 552021076, 561354435, 570692115, 580034117, 589380442, 598731091, 608086065, 617445365, 626808992, 636176947, 645549231, 654925845, 664306790, 673692067, 683081677, 692475621, 701873900, 711276515, 720683467, 730094757, 739510386, 748930355, 758354665, 767783317, 777216312, 786653651, 796095335, 805541365, 814991742, 824446467, 833905541, 843368965, 852836740, 862308867, 871785347, 881266181, 890751370, 900240915, 909734817, 919233077, 928735696, 938242675, 947754015, 957269717, 966789782, 976314211, 985843005, 995376165, 1004913692, 1014455587, 1024001851, 1033552485, 1043107490, 1052666867, 1062230617, 1071798741, 1081371240, 1090948115, 1100529367, 1110114997, 1119705006, 1129299395, 1138898165, 1148501317, 1158108852, 1167720771, 1177337075, 1186957765, 1196582842, 1206212307, 1215846161, 1225484405, 1235127040, 1244774067, 1254425487, 1264081301, 1273741510, 1283406115, 1293075117, 1302748517, 1312426316, 1322108515, 1331795115, 1341486117, 1351181522, 1360881331, 1370585545, 1380294165, 1390007192, 1399724627, 1409446471, 1419172725, 1428903390, 1438638467, 1448377957, 1458121861, 1467870180, 1477622915, 1487380067, 1497141637, 1506907626, 1516678035, 1526452865, 1536232117, 1546015792, 1555803891, 1565596415, 1575393365, 1585194742, 1595000547, 1604810781, 1614625445, 1624444540, 1634268067, 1644096027, 1653928421, 1663765250, 1673606515, 1683452217, 1693302357, 1703156936, 1713015955, 1722879415, 1732747317, 1742619662, 1752496451, 1762377685, 1772263365, 1782153492, 1792048067, 1801947091, 1811850565, 1821758490, 1831670867, 1841587697, 1851508981, 1861434720, 1871364915, 1881299567, 1891238677, 1901182246, 1911130275, 1921082765, 1931039717, 1941001132, 1950967011, 1960937355, 1970912165, 1980891442, 1990875187, 2000863401, 2010856085, 2020853240, 2030854867, 2040860967, 2050871541, 2060886590, 2070906115, 2080930117, 2090958597, 2100991556, 2111028995, 2121070915, 2131117317, 2141168202, 2151223571, 2161283425, 2171347765, 2181416592, 2191489907, 2201567711, 2211650005, 2221736790, 2231828067, 2241923837, 2252024101, 2262128860, 2272238115, 2282351867, 2292470117, 2302592866, 2312720115, 2322851865, 2332988117, 2343128872, 2353274131, 2363423895, 2373578165, 2383736942, 2393900227, 2404068021, 2414240325, 2424417140, 2434598467, 2444784307, 2454974661, 2465169530, 2475368915, 2485572817, 2495781237, 2505994176, 2516211635, 2526433615, 2536660117, 2546891142, 2557126691, 2567366765, 2577611365, 2587860492, 2598114147, 2608372331, 2618635045, 2628902290, 2639174067, 2649450377, 2659731221, 2670016600, 2680306515, 2690600967, 2700899957, 2711203486, 2721511555, 2731824165, 2742141317, 2752463012, 2762789251, 2773120035, 2783455365, 2793795242, 2804139667, 2814488641, 2824842165, 2835200240, 2845562867, 2855930047, 2866301781, 2876678070, 2887058915, 2897444317, 2907834277, 2918228796, 2928627875, 2939031515, 2949439717, 2959852482, 2970269811, 2980691705, 2991118165, 3001549192, 3011984787, 3022424951, 3032869685, 3043318990, 3053772867, 3064231317, 3074694341, 3085161940, 3095634115, 3106110867, 3116592197, 3127078106, 3137568595, 3148063665, 3158563317, 3169067552, 3179576371, 3190089775, 3200607765, 3211130342, 3221657507, 3232189261, 3242725605, 3253266540, 3263812067, 3274362187, 3284916901, 3295476210, 3306040115, 3316608617, 3327181717, 3337759416, 3348341715, 3358928615, 3369520117, 3380116222, 3390716931, 3401322245, 3411932165, 3422546692, 3433165827, 3443789571, 3454417925, 3465050890, 3475688467, 3486330657, 3496977461, 3507628880, 3518284915, 3528945567, 3539610837, 3550280726, 3560955235, 3571634365, 3582318117, 3593006492, 3603699491, 3614397115, 3625099365, 3635806242, 3646517747, 3657233881, 3667954645, 3678680040, 3689410067, 3700144727, 3710884021, 3721627950, 3732376515, 3743129717, 3753887557, 3764650036, 3775417155, 3786188915, 3796965317, 3807746362, 3818532051, 3829322385, 3840117365, 3850916992, 3861721267, 3872530191, 3883343765, 3894161990, 3904984867, 3915812397, 3926644581, 3937481420, 3948322915, 3959169067, 3970019877, 3980875346, 3991735475, 4002600265, 4013469717, 4024343832, 4035222611, 4046106055, 4056994165, 4067886942, 4078784387, 4089686501, 4100593285, 4111504740, 4122420867, 4133341667, 4144267141, 4155197290, 4166132115, 4177071617, 4188015797, 4198964656, 4209918195, 4220876415, 4231839317, 4242806902, 4253779171, 4264756125, 4275737765, 4286724092, 2747811, 13743516, 24743910, 35748995, 46758772, 57773242, 68792406, 79816265, 90844820, 101878072, 112916022, 123958671, 135006020, 146058070, 157114822, 168176277, 179242436, 190313300, 201388870, 212469147, 223554132, 234643826, 245738230, 256837345, 267941172, 279049712, 290162966, 301280935, 312403620, 323531022, 334663142, 345799981, 356941540, 368087820, 379238822, 390394547, 401554996, 412720170, 423890070, 435064697, 446244052, 457428136, 468616950, 479810495, 491008772, 502211782, 513419526, 524632005, 535849220, 547071172, 558297862, 569529291, 580765460, 592006370, 603252022, 614502417, 625757556, 637017440, 648282070, 659551447, 670825572, 682104446, 693388070, 704676445, 715969572, 727267452, 738570086, 749877475, 761189620, 772506522, 783828182, 795154601, 806485780, 817821720, 829162422, 840507887, 851858116, 863213110, 874572870, 885937397, 897306692, 908680756, 920059590, 931443195, 942831572, 954224722, 965622646, 977025345, 988432820, 999845072, 1011262102, 1022683911, 1034110500, 1045541870, 1056978022, 1068418957, 1079864676, 1091315180, 1102770470, 1114230547, 1125695412, 1137165066, 1148639510, 1160118745, 1171602772, 1183091592, 1194585206, 1206083615, 1217586820, 1229094822, 1240607622, 1252125221, 1263647620, 1275174820, 1286706822, 1298243627, 1309785236, 1321331650, 1332882870, 1344438897, 1355999732, 1367565376, 1379135830, 1390711095, 1402291172, 1413876062, 1425465766, 1437060285, 1448659620, 1460263772, 1471872742, 1483486531, 1495105140, 1506728570, 1518356822, 1529989897, 1541627796, 1553270520, 1564918070, 1576570447, 1588227652, 1599889686, 1611556550, 1623228245, 1634904772, 1646586132, 1658272326, 1669963355, 1681659220, 1693359922, 1705065462, 1716775841, 1728491060, 1740211120, 1751936022, 1763665767, 1775400356, 1787139790, 1798884070, 1810633197, 1822387172, 1834145996, 1845909670, 1857678195, 1869451572, 1881229802, 1893012886, 1904800825, 1916593620, 1928391272, 1940193782, 1952001151, 1963813380, 1975630470, 1987452422, 1999279237, 2011110916, 2022947460, 2034788870, 2046635147, 2058486292, 2070342306, 2082203190, 2094068945, 2105939572, 2117815072, 2129695446, 2141580695, 2153470820, 2165365822, 2177265702, 2189170461, 2201080100, 2212994620, 2224914022, 2236838307, 2248767476, 2260701530, 2272640470, 2284584297, 2296533012, 2308486616, 2320445110, 2332408495, 2344376772, 2356349942, 2368328006, 2380310965, 2392298820, 2404291572, 2416289222, 2428291771, 2440299220, 2452311570, 2464328822, 2476350977, 2488378036, 2500410000, 2512446870, 2524488647, 2536535332, 2548586926, 2560643430, 2572704845, 2584771172, 2596842412, 2608918566, 2620999635, 2633085620, 2645176522, 2657272342, 2669373081, 2681478740, 2693589320, 2705704822, 2717825247, 2729950596, 2742080870, 2754216070, 2766356197, 2778501252, 2790651236, 2802806150, 2814965995, 2827130772, 2839300482, 2851475126, 2863654705, 2875839220, 2888028672, 2900223062, 2912422391, 2924626660, 2936835870, 2949050022, 2961269117, 2973493156, 2985722140, 2997956070, 3010194947, 3022438772, 3034687546, 3046941270, 3059199945, 3071463572, 3083732152, 3096005686, 3108284175, 3120567620, 3132856022, 3145149382, 3157447701, 3169750980, 3182059220, 3194372422, 3206690587, 3219013716, 3231341810, 3243674870, 3256012897, 3268355892, 3280703856, 3293056790, 3305414695, 3317777572, 3330145422, 3342518246, 3354896045, 3367278820, 3379666572, 3392059302, 3404457011, 3416859700, 3429267370, 3441680022, 3454097657, 3466520276, 3478947880, 3491380470, 3503818047, 3516260612, 3528708166, 3541160710, 3553618245, 3566080772, 3578548292, 3591020806, 3603498315, 3615980820, 3628468322, 3640960822, 3653458321, 3665960820, 3678468320, 3690980822, 3703498327, 3716020836, 3728548350, 3741080870, 3753618397, 3766160932, 3778708476, 3791261030, 3803818595, 3816381172, 3828948762, 3841521366, 3854098985, 3866681620, 3879269272, 3891861942, 3904459631, 3917062340, 3929670070, 3942282822, 3954900597, 3967523396, 3980151220, 3992784070, 4005421947, 4018064852, 4030712786, 4043365750, 4056023745, 4068686772, 4081354832, 4094027926, 4106706055, 4119389220, 4132077422, 4144770662, 4157468941, 4170172260, 4182880620, 4195594022, 4208312467, 4221035956, 4233764490, 4246498070, 4259236697, 4271980372, 4284729096, 2515574, 15274400, 28038277, 40807207, 53581191, 66360230, 79144325, 91933477, 104727687, 117526956, 130331285, 143140675, 155955127, 168774642, 181599221, 194428865, 207263575, 220103352, 232948197, 245798111, 258653095, 271513150, 284378277, 297248477, 310123751, 323004100, 335889525, 348780027, 361675607, 374576266, 387482005, 400392825, 413308727, 426229712, 439155781, 452086935, 465023175, 477964502, 490910917, 503862421, 516819015, 529780700, 542747477, 555719347, 568696311, 581678370, 594665525, 607657777, 620655127, 633657576, 646665125, 659677775, 672695527, 685718382, 698746341, 711779405, 724817575, 737860852, 750909237, 763962731, 777021335, 790085050, 803153877, 816227817, 829306871, 842391040, 855480325, 868574727, 881674247, 894778886, 907888645, 921003525, 934123527, 947248652, 960378901, 973514275, 986654775, 999800402, 1012951157, 1026107041, 1039268055, 1052434200, 1065605477, 1078781887, 1091963431, 1105150110, 1118341925, 1131538877, 1144740967, 1157948196, 1171160565, 1184378075, 1197600727, 1210828522, 1224061461, 1237299545, 1250542775, 1263791152, 1277044677, 1290303351, 1303567175, 1316836150, 1330110277, 1343389557, 1356673991, 1369963580, 1383258325, 1396558227, 1409863287, 1423173506, 1436488885, 1449809425, 1463135127, 1476465992, 1489802021, 1503143215, 1516489575, 1529841102, 1543197797, 1556559661, 1569926695, 1583298900, 1596676277, 1610058827, 1623446551, 1636839450, 1650237525, 1663640777, 1677049207, 1690462816, 1703881605, 1717305575, 1730734727, 1744169062, 1757608581, 1771053285, 1784503175, 1797958252, 1811418517, 1824883971, 1838354615, 1851830450, 1865311477, 1878797697, 1892289111, 1905785720, 1919287525, 1932794527, 1946306727, 1959824126, 1973346725, 1986874525, 2000407527, 2013945732, 2027489141, 2041037755, 2054591575, 2068150602, 2081714837, 2095284281, 2108858935, 2122438800, 2136023877, 2149614167, 2163209671, 2176810390, 2190416325, 2204027477, 2217643847, 2231265436, 2244892245, 2258524275, 2272161527, 2285804002, 2299451701, 2313104625, 2326762775, 2340426152, 2354094757, 2367768591, 2381447655, 2395131950, 2408821477, 2422516237, 2436216231, 2449921460, 2463631925, 2477347627, 2491068567, 2504794746, 2518526165, 2532262825, 2546004727, 2559751872, 2573504261, 2587261895, 2601024775, 2614792902, 2628566277, 2642344901, 2656128775, 2669917900, 2683712277, 2697511907, 2711316791, 2725126930, 2738942325, 2752762977, 2766588887, 2780420056, 2794256485, 2808098175, 2821945127, 2835797342, 2849654821, 2863517565, 2877385575, 2891258852, 2905137397, 2919021211, 2932910295, 2946804650, 2960704277, 2974609177, 2988519351, 3002434800, 3016355525, 3030281527, 3044212807, 3058149366, 3072091205, 3086038325, 3099990727, 3113948412, 3127911381, 3141879635, 3155853175, 3169832002, 3183816117, 3197805521, 3211800215, 3225800200, 3239805477, 3253816047, 3267831911, 3281853070, 3295879525, 3309911277, 3323948327, 3337990676, 3352038325, 3366091275, 3380149527, 3394213082, 3408281941, 3422356105, 3436435575, 3450520352, 3464610437, 3478705831, 3492806535, 3506912550, 3521023877, 3535140517, 3549262471, 3563389740, 3577522325, 3591660227, 3605803447, 3619951986, 3634105845, 3648265025, 3662429527, 3676599352, 3690774501, 3704954975, 3719140775, 3733331902, 3747528357, 3761730141, 3775937255, 3790149700, 3804367477, 3818590587, 3832819031, 3847052810, 3861291925, 3875536377, 3889786167, 3904041296, 3918301765, 3932567575, 3946838727, 3961115222, 3975397061, 3989684245, 4003976775, 4018274652, 4032577877, 4046886451, 4061200375, 4075519650, 4089844277, 4104174257, 4118509591, 4132850280, 4147196325, 4161547727, 4175904487, 4190266606, 4204634085, 4219006925, 4233385127, 4247768692, 4262157621, 4276551915, 4290951575, 10389306, 24799702, 39215466, 53636600, 68063105, 82494982, 96932232, 111374856, 125822855, 140276230, 154734982, 169199112, 183668621, 198143510, 212623780, 227109432, 241600467, 256096886, 270598690, 285105880, 299618457, 314136422, 328659776, 343188520, 357722655, 372262182, 386807102, 401357416, 415913125, 430474230, 445040732, 459612632, 474189931, 488772630, 503360730, 517954232, 532553137, 547157446, 561767160, 576382280, 591002807, 605628742, 620260086, 634896840, 649539005, 664186582, 678839572, 693497976, 708161795, 722831030, 737505682, 752185752, 766871241, 781562150, 796258480, 810960232, 825667407, 840380006, 855098030, 869821480, 884550357, 899284662, 914024396, 928769560, 943520155, 958276182, 973037642, 987804536, 1002576865, 1017354630, 1032137832, 1046926472, 1061720551, 1076520070, 1091325030, 1106135432, 1120951277, 1135772566, 1150599300, 1165431480, 1180269107, 1195112182, 1209960706, 1224814680, 1239674105, 1254538982, 1269409312, 1284285096, 1299166335, 1314053030, 1328945182, 1343842792, 1358745861, 1373654390, 1388568380, 1403487832, 1418412747, 1433343126, 1448278970, 1463220280, 1478167057, 1493119302, 1508077016, 1523040200, 1538008855, 1552982982, 1567962582, 1582947656, 1597938205, 1612934230, 1627935732, 1642942712, 1657955171, 1672973110, 1687996530, 1703025432, 1718059817, 1733099686, 1748145040, 1763195880, 1778252207, 1793314022, 1808381326, 1823454120, 1838532405, 1853616182, 1868705452, 1883800216, 1898900475, 1914006230, 1929117482, 1944234232, 1959356481, 1974484230, 1989617480, 2004756232, 2019900487, 2035050246, 2050205510, 2065366280, 2080532557, 2095704342, 2110881636, 2126064440, 2141252755, 2156446582, 2171645922, 2186850776, 2202061145, 2217277030, 2232498432, 2247725352, 2262957791, 2278195750, 2293439230, 2308688232, 2323942757, 2339202806, 2354468380, 2369739480, 2385016107, 2400298262, 2415585946, 2430879160, 2446177905, 2461482182, 2476791992, 2492107336, 2507428215, 2522754630, 2538086582, 2553424072, 2568767101, 2584115670, 2599469780, 2614829432, 2630194627, 2645565366, 2660941650, 2676323480, 2691710857, 2707103782, 2722502256, 2737906280, 2753315855, 2768730982, 2784151662, 2799577896, 2815009685, 2830447030, 2845889932, 2861338392, 2876792411, 2892251990, 2907717130, 2923187832, 2938664097, 2954145926, 2969633320, 2985126280, 3000624807, 3016128902, 3031638566, 3047153800, 3062674605, 3078200982, 3093732932, 3109270456, 3124813555, 3140362230, 3155916482, 3171476312, 3187041721, 3202612710, 3218189280, 3233771432, 3249359167, 3264952486, 3280551390, 3296155880, 3311765957, 3327381622, 3343002876, 3358629720, 3374262155, 3389900182, 3405543802, 3421193016, 3436847825, 3452508230, 3468174232, 3483845832, 3499523031, 3515205830, 3530894230, 3546588232, 3562287837, 3577993046, 3593703860, 3609420280, 3625142307, 3640869942, 3656603186, 3672342040, 3688086505, 3703836582, 3719592272, 3735353576, 3751120495, 3766893030, 3782671182, 3798454952, 3814244341, 3830039350, 3845839980, 3861646232, 3877458107, 3893275606, 3909098730, 3924927480, 3940761857, 3956601862, 3972447496, 3988298760, 4004155655, 4020018182, 4035886342, 4051760136, 4067639565, 4083524630, 4099415332, 4115311672, 4131213651, 4147121270, 4163034530, 4178953432, 4194877977, 4210808166, 4226744000, 4242685480, 4258632607, 4274585382, 4290543806, 11540584, 27510310, 43485687, 59466717, 75453401, 91445740, 107443735, 123447387, 139456697, 155471666, 171492295, 187518585, 203550537, 219588152, 235631431, 251680375, 267734985, 283795262, 299861207, 315932821, 332010105, 348093060, 364181687, 380275987, 396375961, 412481610, 428592935, 444709937, 460832617, 476960976, 493095015, 509234735, 525380137, 541531222, 557687991, 573850445, 590018585, 606192412, 622371927, 638557131, 654748025, 670944610, 687146887, 703354857, 719568521, 735787880, 752012935, 768243687, 784480137, 800722286, 816970135, 833223685, 849482937, 865747892, 882018551, 898294915, 914576985, 930864762, 947158247, 963457441, 979762345, 996072960, 1012389287, 1028711327, 1045039081, 1061372550, 1077711735, 1094056637, 1110407257, 1126763596, 1143125655, 1159493435, 1175866937, 1192246162, 1208631111, 1225021785, 1241418185, 1257820312, 1274228167, 1290641751, 1307061065, 1323486110, 1339916887, 1356353397, 1372795641, 1389243620, 1405697335, 1422156787, 1438621977, 1455092906, 1471569575, 1488051985, 1504540137, 1521034032, 1537533671, 1554039055, 1570550185, 1587067062, 1603589687, 1620118061, 1636652185, 1653192060, 1669737687, 1686289067, 1702846201, 1719409090, 1735977735, 1752552137, 1769132297, 1785718216, 1802309895, 1818907335, 1835510537, 1852119502, 1868734231, 1885354725, 1901980985, 1918613012, 1935250807, 1951894371, 1968543705, 1985198810, 2001859687, 2018526337, 2035198761, 2051876960, 2068560935, 2085250687, 2101946217, 2118647526, 2135354615, 2152067485, 2168786137, 2185510572, 2202240791, 2218976795, 2235718585, 2252466162, 2269219527, 2285978681, 2302743625, 2319514360, 2336290887, 2353073207, 2369861321, 2386655230, 2403454935, 2420260437, 2437071737, 2453888836, 2470711735, 2487540435, 2504374937, 2521215242, 2538061351, 2554913265, 2571770985, 2588634512, 2605503847, 2622378991, 2639259945, 2656146710, 2673039287, 2689937677, 2706841881, 2723751900, 2740667735, 2757589387, 2774516857, 2791450146, 2808389255, 2825334185, 2842284937, 2859241512, 2876203911, 2893172135, 2910146185, 2927126062, 2944111767, 2961103301, 2978100665, 2995103860, 3012112887, 3029127747, 3046148441, 3063174970, 3080207335, 3097245537, 3114289577, 3131339456, 3148395175, 3165456735, 3182524137, 3199597382, 3216676471, 3233761405, 3250852185, 3267948812, 3285051287, 3302159611, 3319273785, 3336393810, 3353519687, 3370651417, 3387789001, 3404932440, 3422081735, 3439236887, 3456397897, 3473564766, 3490737495, 3507916085, 3525100537, 3542290852, 3559487031, 3576689075, 3593896985, 3611110762, 3628330407, 3645555921, 3662787305, 3680024560, 3697267687, 3714516687, 3731771561, 3749032310, 3766298935, 3783571437, 3800849817, 3818134076, 3835424215, 3852720235, 3870022137, 3887329922, 3904643591, 3921963145, 3939288585, 3956619912, 3973957127, 3991300231, 4008649225, 4026004110, 4043364887, 4060731557, 4078104121, 4095482580, 4112866935, 4130257187, 4147653337, 4165055386, 4182463335, 4199877185, 4217296937, 4234722592, 4252154151, 4269591615, 4287034985, 9516966, 26972152, 44433246, 61900250, 79373165, 96851992, 114336732, 131827386, 149323955, 166826440, 184334842, 201849162, 219369401, 236895560, 254427640, 271965642, 289509567, 307059416, 324615190, 342176890, 359744517, 377318072, 394897556, 412482970, 430074315, 447671592, 465274802, 482883946, 500499025, 518120040, 535746992, 553379882, 571018711, 588663480, 606314190, 623970842, 641633437, 659301976, 676976460, 694656890, 712343267, 730035592, 747733866, 765438090, 783148265, 800864392, 818586472, 836314506, 854048495, 871788440, 889534342, 907286202, 925044021, 942807800, 960577540, 978353242, 996134907, 1013922536, 1031716130, 1049515690, 1067321217, 1085132712, 1102950176, 1120773610, 1138603015, 1156438392, 1174279742, 1192127066, 1209980365, 1227839640, 1245704892, 1263576122, 1281453331, 1299336520, 1317225690, 1335120842, 1353021977, 1370929096, 1388842200, 1406761290, 1424686367, 1442617432, 1460554486, 1478497530, 1496446565, 1514401592, 1532362612, 1550329626, 1568302635, 1586281640, 1604266642, 1622257642, 1640254641, 1658257640, 1676266640, 1694281642, 1712302647, 1730329656, 1748362670, 1766401690, 1784446717, 1802497752, 1820554796, 1838617850, 1856686915, 1874761992, 1892843082, 1910930186, 1929023305, 1947122440, 1965227592, 1983338762, 2001455951, 2019579160, 2037708390, 2055843642, 2073984917, 2092132216, 2110285540, 2128444890, 2146610267, 2164781672, 2182959106, 2201142570, 2219332065, 2237527592, 2255729152, 2273936746, 2292150375, 2310370040, 2328595742, 2346827482, 2365065261, 2383309080, 2401558940, 2419814842, 2438076787, 2456344776, 2474618810, 2492898890, 2511185017, 2529477192, 2547775416, 2566079690, 2584390015, 2602706392, 2621028822, 2639357306, 2657691845, 2676032440, 2694379092, 2712731802, 2731090571, 2749455400, 2767826290, 2786203242, 2804586257, 2822975336, 2841370480, 2859771690, 2878178967, 2896592312, 2915011726, 2933437210, 2951868765, 2970306392, 2988750092, 3007199866, 3025655715, 3044117640, 3062585642, 3081059722, 3099539881, 3118026120, 3136518440, 3155016842, 3173521327, 3192031896, 3210548550, 3229071290, 3247600117, 3266135032, 3284676036, 3303223130, 3321776315, 3340335592, 3358900962, 3377472426, 3396049985, 3414633640, 3433223392, 3451819242, 3470421191, 3489029240, 3507643390, 3526263642, 3544889997, 3563522456, 3582161020, 3600805690, 3619456467, 3638113352, 3656776346, 3675445450, 3694120665, 3712801992, 3731489432, 3750182986, 3768882655, 3787588440, 3806300342, 3825018362, 3843742501, 3862472760, 3881209140, 3899951642, 3918700267, 3937455016, 3956215890, 3974982890, 3993756017, 4012535272, 4031320656, 4050112170, 4068909815, 4087713592, 4106523502, 4125339546, 4144161725, 4162990040, 4181824492, 4200665082, 4219511811, 4238364680, 4257223690, 4276088842, 4294960137, 18870280, 37753865, 56643595, 75539472, 94441497, 113349671, 132263995, 151184470, 170111097, 189043877, 207982811, 226927900, 245879145, 264836547, 283800107, 302769826, 321745705, 340727745, 359715947, 378710312, 397710841, 416717535, 435730395, 454749422, 473774617, 492805981, 511843515, 530887220, 549937097, 568993147, 588055371, 607123770, 626198345, 645279097, 664366027, 683459136, 702558425, 721663895, 740775547, 759893382, 779017401, 798147605, 817283995, 836426572, 855575337, 874730291, 893891435, 913058770, 932232297, 951412017, 970597931, 989790040, 1008988345, 1028192847, 1047403547, 1066620446, 1085843545, 1105072845, 1124308347, 1143550052, 1162797961, 1182052075, 1201312395, 1220578922, 1239851657, 1259130601, 1278415755, 1297707120, 1317004697, 1336308487, 1355618491, 1374934710, 1394257145, 1413585797, 1432920667, 1452261756, 1471609065, 1490962595, 1510322347, 1529688322, 1549060521, 1568438945, 1587823595, 1607214472, 1626611577, 1646014911, 1665424475, 1684840270, 1704262297, 1723690557, 1743125051, 1762565780, 1782012745, 1801465947, 1820925387, 1840391066, 1859862985, 1879341145, 1898825547, 1918316192, 1937813081, 1957316215, 1976825595, 1996341222, 2015863097, 2035391221, 2054925595, 2074466220, 2094013097, 2113566227, 2133125611, 2152691250, 2172263145, 2191841297, 2211425707, 2231016376, 2250613305, 2270216495, 2289825947, 2309441662, 2329063641, 2348691885, 2368326395, 2387967172, 2407614217, 2427267531, 2446927115, 2466592970, 2486265097, 2505943497, 2525628171, 2545319120, 2565016345, 2584719847, 2604429627, 2624145686, 2643868025, 2663596645, 2683331547, 2703072732, 2722820201, 2742573955, 2762333995, 2782100322, 2801872937, 2821651841, 2841437035, 2861228520, 2881026297, 2900830367, 2920640731, 2940457390, 2960280345, 2980109597, 2999945147, 3019786996, 3039635145, 3059489595, 3079350347, 3099217402, 3119090761, 3138970425, 3158856395, 3178748672, 3198647257, 3218552151, 3238463355, 3258380870, 3278304697, 3298234837, 3318171291, 3338114060, 3358063145, 3378018547, 3397980267, 3417948306, 3437922665, 3457903345, 3477890347, 3497883672, 3517883321, 3537889295, 3557901595, 3577920222, 3597945177, 3617976461, 3638014075, 3658058020, 3678108297, 3698164907, 3718227851, 3738297130, 3758372745, 3778454697, 3798542987, 3818637616, 3838738585, 3858845895, 3878959547, 3899079542, 3919205881, 3939338565, 3959477595, 3979622972, 3999774697, 4019932771, 4040097195, 4060267970, 4080445097, 4100628577, 4120818411, 4141014600, 4161217145, 4181426047, 4201641307, 4221862926, 4242090905, 4262325245, 4282565947, 7845716, 28099146, 48358940, 68625100, 88897627, 109176522, 129461786, 149753420, 170051425, 190355802, 210666552, 230983676, 251307175, 271637050, 291973302, 312315932, 332664941, 353020330, 373382100, 393750252, 414124787, 434505706, 454893010, 475286700, 495686777, 516093242, 536506096, 556925340, 577350975, 597783002, 618221422, 638666236, 659117445, 679575050, 700039052, 720509452, 740986251, 761469450, 781959050, 802455052, 822957457, 843466266, 863981480, 884503100, 905031127, 925565562, 946106406, 966653660, 987207325, 1007767402, 1028333892, 1048906796, 1069486115, 1090071850, 1110664002, 1131262572, 1151867561, 1172478970, 1193096800, 1213721052, 1234351727, 1254988826, 1275632350, 1296282300, 1316938677, 1337601482, 1358270716, 1378946380, 1399628475, 1420317002, 1441011962, 1461713356, 1482421185, 1503135450, 1523856152, 1544583292, 1565316871, 1586056890, 1606803350, 1627556252, 1648315597, 1669081386, 1689853620, 1710632300, 1731417427, 1752209002, 1773007026, 1793811500, 1814622425, 1835439802, 1856263632, 1877093916, 1897930655, 1918773850, 1939623502, 1960479612, 1981342181, 2002211210, 2023086700, 2043968652, 2064857067, 2085751946, 2106653290, 2127561100, 2148475377, 2169396122, 2190323336, 2211257020, 2232197175, 2253143802, 2274096902, 2295056476, 2316022525, 2336995050, 2357974052, 2378959532, 2399951491, 2420949930, 2441954850, 2462966252, 2483984137, 2505008506, 2526039360, 2547076700, 2568120527, 2589170842, 2610227646, 2631290940, 2652360725, 2673437002, 2694519772, 2715609036, 2736704795, 2757807050, 2778915802, 2800031052, 2821152801, 2842281050, 2863415800, 2884557052, 2905704807, 2926859066, 2948019830, 2969187100, 2990360877, 3011541162, 3032727956, 3053921260, 3075121075, 3096327402, 3117540242, 3138759596, 3159985465, 3181217850, 3202456752, 3223702172, 3244954111, 3266212570, 3287477550, 3308749052, 3330027077, 3351311626, 3372602700, 3393900300, 3415204427, 3436515082, 3457832266, 3479155980, 3500486225, 3521823002, 3543166312, 3564516156, 3585872535, 3607235450, 3628604902, 3649980892, 3671363421, 3692752490, 3714148100, 3735550252, 3756958947, 3778374186, 3799795970, 3821224300, 3842659177, 3864100602, 3885548576, 3907003100, 3928464175, 3949931802, 3971405982, 3992886716, 4014374005, 4035867850, 4057368252, 4078875212, 4100388731, 4121908810, 4143435450, 4164968652, 4186508417, 4208054746, 4229607640, 4251167100, 4272733127, 4294305722, 20917590, 42503325, 64095630, 85694507, 107299957, 128911981, 150530580, 172155755, 193787507, 215425837, 237070746, 258722235, 280380305, 302044957, 323716192, 345394011, 367078415, 388769405, 410466982, 432171147, 453881901, 475599245, 497323180, 519053707, 540790827, 562534541, 584284850, 606041755, 627805257, 649575357, 671352056, 693135355, 714925255, 736721757, 758524862, 780334571, 802150885, 823973805, 845803332, 867639467, 889482211, 911331565, 933187530, 955050107, 976919297, 998795101, 1020677520, 1042566555, 1064462207, 1086364477, 1108273366, 1130188875, 1152111005, 1174039757, 1195975132, 1217917131, 1239865755, 1261821005, 1283782882, 1305751387, 1327726521, 1349708285, 1371696680, 1393691707, 1415693367, 1437701661, 1459716590, 1481738155, 1503766357, 1525801197, 1547842676, 1569890795, 1591945555, 1614006957, 1636075002, 1658149691, 1680231025, 1702319005, 1724413632, 1746514907, 1768622831, 1790737405, 1812858630, 1834986507, 1857121037, 1879262221, 1901410060, 1923564555, 1945725707, 1967893517, 1990067986, 2012249115, 2034436905, 2056631357, 2078832472, 2101040251, 2123254695, 2145475805, 2167703582, 2189938027, 2212179141, 2234426925, 2256681380, 2278942507, 2301210307, 2323484781, 2345765930, 2368053755, 2390348257, 2412649437, 2434957296, 2457271835, 2479593055, 2501920957, 2524255542, 2546596811, 2568944765, 2591299405, 2613660732, 2636028747, 2658403451, 2680784845, 2703172930, 2725567707, 2747969177, 2770377341, 2792792200, 2815213755, 2837642007, 2860076957, 2882518606, 2904966955, 2927422005, 2949883757, 2972352212, 2994827371, 3017309235, 3039797805, 3062293082, 3084795067, 3107303761, 3129819165, 3152341280, 3174870107, 3197405647, 3219947901, 3242496870, 3265052555, 3287614957, 3310184077, 3332759916, 3355342475, 3377931755, 3400527757, 3423130482, 3445739931, 3468356105, 3490979005, 3513608632, 3536244987, 3558888071, 3581537885, 3604194430, 3626857707, 3649527717, 3672204461, 3694887940, 3717578155, 3740275107, 3762978797, 3785689226, 3808406395, 3831130305, 3853860957, 3876598352, 3899342491, 3922093375, 3944851005, 3967615382, 3990386507, 4013164381, 4035949005, 4058740380, 4081538507, 4104343387, 4127155021, 4149973410, 4172798555, 4195630457, 4218469117, 4241314536, 4264166715, 4287025655, 14924061, 37796527, 60675756, 83561750, 106454510, 129354037, 152260332, 175173396, 198093230, 221019835, 243953212, 266893362, 289840286, 312793985, 335754460, 358721712, 381695742, 404676551, 427664140, 450658510, 473659662, 496667597, 519682316, 542703820, 565732110, 588767187, 611809052, 634857706, 657913150, 680975385, 704044412, 727120232, 750202846, 773292255, 796388460, 819491462, 842601262, 865717861, 888841260, 911971460, 935108462, 958252267, 981402876, 1004560290, 1027724510, 1050895537, 1074073372, 1097258016, 1120449470, 1143647735, 1166852812, 1190064702, 1213283406, 1236508925, 1259741260, 1282980412, 1306226382, 1329479171, 1352738780, 1376005210, 1399278462, 1422558537, 1445845436, 1469139160, 1492439710, 1515747087, 1539061292, 1562382326, 1585710190, 1609044885, 1632386412, 1655734772, 1679089966, 1702451995, 1725820860, 1749196562, 1772579102, 1795968481, 1819364700, 1842767760, 1866177662, 1889594407, 1913017996, 1936448430, 1959885710, 1983329837, 2006780812, 2030238636, 2053703310, 2077174835, 2100653212, 2124138442, 2147630526, 2171129465, 2194635260, 2218147912, 2241667422, 2265193791, 2288727020, 2312267110, 2335814062, 2359367877, 2382928556, 2406496100, 2430070510, 2453651787, 2477239932, 2500834946, 2524436830, 2548045585, 2571661212, 2595283712, 2618913086, 2642549335, 2666192460, 2689842462, 2713499342, 2737163101, 2760833740, 2784511260, 2808195662, 2831886947, 2855585116, 2879290170, 2903002110, 2926720937, 2950446652, 2974179256, 2997918750, 3021665135, 3045418412, 3069178582, 3092945646, 3116719605, 3140500460, 3164288212, 3188082862, 3211884411, 3235692860, 3259508210, 3283330462, 3307159617, 3330995676, 3354838640, 3378688510, 3402545287, 3426408972, 3450279566, 3474157070, 3498041485, 3521932812, 3545831052, 3569736206, 3593648275, 3617567260, 3641493162, 3665425982, 3689365721, 3713312380, 3737265960, 3761226462, 3785193887, 3809168236, 3833149510, 3857137710, 3881132837, 3905134892, 3929143876, 3953159790, 3977182635, 4001212412, 4025249122, 4049292766, 4073343345, 4097400860, 4121465312, 4145536702, 4169615031, 4193700300, 4217792510, 4241891662, 4265997757, 4290110796, 19263484, 43390415, 67524292, 91665117, 115812891, 139967615, 164129290, 188297917, 212473497, 236656031, 260845520, 285041965, 309245367, 333455727, 357673046, 381897325, 406128565, 430366767, 454611932, 478864061, 503123155, 527389215, 551662242, 575942237, 600229201, 624523135, 648824040, 673131917, 697446767, 721768591, 746097390, 770433165, 794775917, 819125647, 843482356, 867846045, 892216715, 916594367, 940979002, 965370621, 989769225, 1014174815, 1038587392, 1063006957, 1087433511, 1111867055, 1136307590, 1160755117, 1185209637, 1209671151, 1234139660, 1258615165, 1283097667, 1307587167, 1332083666, 1356587165, 1381097665, 1405615167, 1430139672, 1454671181, 1479209695, 1503755215, 1528307742, 1552867277, 1577433821, 1602007375, 1626587940, 1651175517, 1675770107, 1700371711, 1724980330, 1749595965, 1774218617, 1798848287, 1823484976, 1848128685, 1872779415, 1897437167, 1922101942, 1946773741, 1971452565, 1996138415, 2020831292, 2045531197, 2070238131, 2094952095, 2119673090, 2144401117, 2169136177, 2193878271, 2218627400, 2243383565, 2268146767, 2292917007, 2317694286, 2342478605, 2367269965, 2392068367, 2416873812, 2441686301, 2466505835, 2491332415, 2516166042, 2541006717, 2565854441, 2590709215, 2615571040, 2640439917, 2665315847, 2690198831, 2715088870, 2739985965, 2764890117, 2789801327, 2814719596, 2839644925, 2864577315, 2889516767, 2914463282, 2939416861, 2964377505, 2989345215, 3014319992, 3039301837, 3064290751, 3089286735, 3114289790, 3139299917, 3164317117, 3189341391, 3214372740, 3239411165, 3264456667, 3289509247, 3314568906, 3339635645, 3364709465, 3389790367, 3414878352, 3439973421, 3465075575, 3490184815, 3515301142, 3540424557, 3565555061, 3590692655, 3615837340, 3640989117, 3666147987, 3691313951, 3716487010, 3741667165, 3766854417, 3792048767, 3817250216, 3842458765, 3867674415, 3892897167, 3918127022, 3943363981, 3968608045, 3993859215, 4019117492, 4044382877, 4069655371, 4094934975, 4120221690, 4145515517, 4170816457, 4196124511, 4221439680, 4246761965, 4272091367, 2460591, 27804231, 53154990, 78512870, 103877872, 129249997, 154629246, 180015620, 205409120, 230809747, 256217502, 281632386, 307054400, 332483545, 357919822, 383363232, 408813776, 434271455, 459736270, 485208222, 510687312, 536173541, 561666910, 587167420, 612675072, 638189867, 663711806, 689240890, 714777120, 740320497, 765871022, 791428696, 816993520, 842565495, 868144622, 893730902, 919324336, 944924925, 970532670, 996147572, 1021769632, 1047398851, 1073035230, 1098678770, 1124329472, 1149987337, 1175652366, 1201324560, 1227003920, 1252690447, 1278384142, 1304085006, 1329793040, 1355508245, 1381230622, 1406960172, 1432696896, 1458440795, 1484191870, 1509950122, 1535715552, 1561488161, 1587267950, 1613054920, 1638849072, 1664650407, 1690458926, 1716274630, 1742097520, 1767927597, 1793764862, 1819609316, 1845460960, 1871319795, 1897185822, 1923059042, 1948939456, 1974827065, 2000721870, 2026623872, 2052533072, 2078449471, 2104373070, 2130303870, 2156241872, 2182187077, 2208139486, 2234099100, 2260065920, 2286039947, 2312021182, 2338009626, 2364005280, 2390008145, 2416018222, 2442035512, 2468060016, 2494091735, 2520130670, 2546176822, 2572230192, 2598290781, 2624358590, 2650433620, 2676515872, 2702605347, 2728702046, 2754805970, 2780917120, 2807035497, 2833161102, 2859293936, 2885434000, 2911581295, 2937735822, 2963897582, 2990066576, 3016242805, 3042426270, 3068616972, 3094814912, 3121020091, 3147232510, 3173452170, 3199679072, 3225913217, 3252154606, 3278403240, 3304659120, 3330922247, 3357192622, 3383470246, 3409755120, 3436047245, 3462346622, 3488653252, 3514967136, 3541288275, 3567616670, 3593952322, 3620295232, 3646645401, 3673002830, 3699367520, 3725739472, 3752118687, 3778505166, 3804898910, 3831299920, 3857708197, 3884123742, 3910546556, 3936976640, 3963413995, 3989858622, 4016310522, 4042769696, 4069236145, 4095709870, 4122190872, 4148679152, 4175174711, 4201677550, 4228187670, 4254705072, 4281229757, 12794430, 39333685, 65880225, 92434052, 118995167, 145563571, 172139265, 198722250, 225312527, 251910097, 278514961, 305127120, 331746575, 358373327, 385007377, 411648726, 438297375, 464953325, 491616577, 518287132, 544964991, 571650155, 598342625, 625042402, 651749487, 678463881, 705185585, 731914600, 758650927, 785394567, 812145521, 838903790, 865669375, 892442277, 919222497, 946010036, 972804895, 999607075, 1026416577, 1053233402, 1080057551, 1106889025, 1133727825, 1160573952, 1187427407, 1214288191, 1241156305, 1268031750, 1294914527, 1321804637, 1348702081, 1375606860, 1402518975, 1429438427, 1456365217, 1483299346, 1510240815, 1537189625, 1564145777, 1591109272, 1618080111, 1645058295, 1672043825, 1699036702, 1726036927, 1753044501, 1780059425, 1807081700, 1834111327, 1861148307, 1888192641, 1915244330, 1942303375, 1969369777, 1996443537, 2023524656, 2050613135, 2077708975, 2104812177, 2131922742, 2159040671, 2186165965, 2213298625, 2240438652, 2267586047, 2294740811, 2321902945, 2349072450, 2376249327, 2403433577, 2430625201, 2457824200, 2485030575, 2512244327, 2539465457, 2566693966, 2593929855, 2621173125, 2648423777, 2675681812, 2702947231, 2730220035, 2757500225, 2784787802, 2812082767, 2839385121, 2866694865, 2894012000, 2921336527, 2948668447, 2976007761, 3003354470, 3030708575, 3058070077, 3085438977, 3112815276, 3140198975, 3167590075, 3194988577, 3222394482, 3249807791, 3277228505, 3304656625, 3332092152, 3359535087, 3386985431, 3414443185, 3441908350, 3469380927, 3496860917, 3524348321, 3551843140, 3579345375, 3606855027, 3634372097, 3661896586, 3689428495, 3716967825, 3744514577, 3772068752, 3799630351, 3827199375, 3854775825, 3882359702, 3909951007, 3937549741, 3965155905, 3992769500, 4020390527, 4048018987, 4075654881, 4103298210, 4130948975, 4158607177, 4186272817, 4213945896, 4241626415, 4269314375, 2042481, 29745327, 57455616, 85173350, 112898530, 140631157, 168371232, 196118756, 223873730, 251636155, 279406032, 307183362, 334968146, 362760385, 390560080, 418367232, 446181842, 474003911, 501833440, 529670430, 557514882, 585366797, 613226176, 641093020, 668967330, 696849107, 724738352, 752635066, 780539250, 808450905, 836370032, 864296632, 892230706, 920172255, 948121280, 976077782, 1004041762, 1032013221, 1059992160, 1087978580, 1115972482, 1143973867, 1171982736, 1199999090, 1228022930, 1256054257, 1284093072, 1312139376, 1340193170, 1368254455, 1396323232, 1424399502, 1452483266, 1480574525, 1508673280, 1536779532, 1564893282, 1593014531, 1621143280, 1649279530, 1677423282, 1705574537, 1733733296, 1761899560, 1790073330, 1818254607, 1846443392, 1874639686, 1902843490, 1931054805, 1959273632, 1987499972, 2015733826, 2043975195, 2072224080, 2100480482, 2128744402, 2157015841, 2185294800, 2213581280, 2241875282, 2270176807, 2298485856, 2326802430, 2355126530, 2383458157, 2411797312, 2440143996, 2468498210, 2496859955, 2525229232, 2553606042, 2581990386, 2610382265, 2638781680, 2667188632, 2695603122, 2724025151, 2752454720, 2780891830, 2809336482, 2837788677, 2866248416, 2894715700, 2923190530, 2951672907, 2980162832, 3008660306, 3037165330, 3065677905, 3094198032, 3122725712, 3151260946, 3179803735, 3208354080, 3236911982, 3265477442, 3294050461, 3322631040, 3351219180, 3379814882, 3408418147, 3437028976, 3465647370, 3494273330, 3522906857, 3551547952, 3580196616, 3608852850, 3637516655, 3666188032, 3694866982, 3723553506, 3752247605, 3780949280, 3809658532, 3838375362, 3867099771, 3895831760, 3924571330, 3953318482, 3982073217, 4010835536, 4039605440, 4068382930, 4097168007, 4125960672, 4154760926, 4183568770, 4212384205, 4241207232, 4270037852, 3908770, 32754580, 61607985, 90468987, 119337587, 148213786, 177097585, 205988985, 234887987, 263794592, 292708801, 321630615, 350560035, 379497062, 408441697, 437393941, 466353795, 495321260, 524296337, 553279027, 582269331, 611267250, 640272785, 669285937, 698306707, 727335096, 756371105, 785414735, 814465987, 843524862, 872591361, 901665485, 930747235, 959836612, 988933617, 1018038251, 1047150515, 1076270410, 1105397937, 1134533097, 1163675891, 1192826320, 1221984385, 1251150087, 1280323427, 1309504406, 1338693025, 1367889285, 1397093187, 1426304732, 1455523921, 1484750755, 1513985235, 1543227362, 1572477137, 1601734561, 1630999635, 1660272360, 1689552737, 1718840767, 1748136451, 1777439790, 1806750785, 1836069437, 1865395747, 1894729716, 1924071345, 1953420635, 1982777587, 2012142202, 2041514481, 2070894425, 2100282035, 2129677312, 2159080257, 2188490871, 2217909155, 2247335110, 2276768737, 2306210037, 2335659011, 2365115660, 2394579985, 2424051987, 2453531667, 2483019026, 2512514065, 2542016785, 2571527187, 2601045272, 2630571041, 2660104495, 2689645635, 2719194462, 2748750977, 2778315181, 2807887075, 2837466660, 2867053937, 2896648907, 2926251571, 2955861930, 2985479985, 3015105737, 3044739187, 3074380336, 3104029185, 3133685735, 3163349987, 3193021942, 3222701601, 3252388965, 3282084035, 3311786812, 3341497297, 3371215491, 3400941395, 3430675010, 3460416337, 3490165377, 3519922131, 3549686600, 3579458785, 3609238687, 3639026307, 3668821646, 3698624705, 3728435485, 3758253987, 3788080212, 3817914161, 3847755835, 3877605235, 3907462362, 3937327217, 3967199801, 3997080115, 4026968160, 4056863937, 4086767447, 4116678691, 4146597670, 4176524385, 4206458837, 4236401027, 4266350956, 1341329, 31306740, 61279892, 91260787, 121249426, 151245810, 181249940, 211261817, 241281442, 271308816, 301343940, 331386815, 361437442, 391495822, 421561956, 451635845, 481717490, 511806892, 541904052, 572008971, 602121650, 632242090, 662370292, 692506257, 722649986, 752801480, 782960740, 813127767, 843302562, 873485126, 903675460, 933873565, 964079442, 994293092, 1024514516, 1054743715, 1084980690, 1115225442, 1145477972, 1175738281, 1206006370, 1236282240, 1266565892, 1296857327, 1327156546, 1357463550, 1387778340, 1418100917, 1448431282, 1478769436, 1509115380, 1539469115, 1569830642, 1600199962, 1630577076, 1660961985, 1691354690, 1721755192, 1752163492, 1782579591, 1813003490, 1843435190, 1873874692, 1904321997, 1934777106, 1965240020, 1995710740, 2026189267, 2056675602, 2087169746, 2117671700, 2148181465, 2178699042, 2209224432, 2239757636, 2270298655, 2300847490, 2331404142, 2361968612, 2392540901, 2423121010, 2453708940, 2484304692, 2514908267, 2545519666, 2576138890, 2606765940, 2637400817, 2668043522, 2698694056, 2729352420, 2760018615, 2790692642, 2821374502, 2852064196, 2882761725, 2913467090, 2944180292, 2974901332, 3005630211, 3036366930, 3067111490, 3097863892, 3128624137, 3159392226, 3190168160, 3220951940, 3251743567, 3282543042, 3313350366, 3344165540, 3374988565, 3405819442, 3436658172, 3467504756, 3498359195, 3529221490, 3560091642, 3590969652, 3621855521, 3652749250, 3683650840, 3714560292, 3745477607, 3776402786, 3807335830, 3838276740, 3869225517, 3900182162, 3931146676, 3962119060, 3993099315, 4024087442, 4055083442, 4086087316, 4117099065, 4148118690, 4179146192, 4210181572, 4241224831, 4272275970, 8367694, 39434597, 70509382, 101592051, 132682605, 163781045, 194887372, 226001587, 257123691, 288253685, 319391570, 350537347, 381691017, 412852581, 444022040, 475199395, 506384647, 537577797, 568778846, 599987795, 631204645, 662429397, 693662052, 724902611, 756151075, 787407445, 818671722, 849943907, 881224001, 912512005, 943807920, 975111747, 1006423487, 1037743141, 1069070710, 1100406195, 1131749597, 1163100917, 1194460156, 1225827315, 1257202395, 1288585397, 1319976322, 1351375171, 1382781945, 1414196645, 1445619272, 1477049827, 1508488311, 1539934725, 1571389070, 1602851347, 1634321557, 1665799701, 1697285780, 1728779795, 1760281747, 1791791637, 1823309466, 1854835235, 1886368945, 1917910597, 1949460192, 1981017731, 2012583215, 2044156645, 2075738022, 2107327347, 2138924621, 2170529845, 2202143020, 2233764147, 2265393227, 2297030261, 2328675250, 2360328195, 2391989097, 2423657957, 2455334776, 2487019555, 2518712295, 2550412997, 2582121662, 2613838291, 2645562885, 2677295445, 2709035972, 2740784467, 2772540931, 2804305365, 2836077770, 2867858147, 2899646497, 2931442821, 2963247120, 2995059395, 3026879647, 3058707877, 3090544086, 3122388275, 3154240445, 3186100597, 3217968732, 3249844851, 3281728955, 3313621045, 3345521122, 3377429187, 3409345241, 3441269285, 3473201320, 3505141347, 3537089367, 3569045381, 3601009390, 3632981395, 3664961397, 3696949397, 3728945396, 3760949395, 3792961395, 3824981397, 3857009402, 3889045411, 3921089425, 3953141445, 3985201472, 4017269507, 4049345551, 4081429605, 4113521670, 4145621747, 4177729837, 4209845941, 4241970060, 4274102195, 11275051, 43423222, 75579411, 107743620, 139915850, 172096102, 204284377, 236480676, 268685000, 300897350, 333117727, 365346132, 397582566, 429827030, 462079525, 494340052, 526608612, 558885206, 591169835, 623462500, 655763202, 688071942, 720388721, 752713540, 785046400, 817387302, 849736247, 882093236, 914458270, 946831350, 979212477, 1011601652, 1043998876, 1076404150, 1108817475, 1141238852, 1173668282, 1206105766, 1238551305, 1271004900, 1303466552, 1335936262, 1368414031, 1400899860, 1433393750, 1465895702, 1498405717, 1530923796, 1563449940, 1595984150, 1628526427, 1661076772, 1693635186, 1726201670, 1758776225, 1791358852, 1823949552, 1856548326, 1889155175, 1921770100, 1954393102, 1987024182, 2019663341, 2052310580, 2084965900, 2117629302, 2150300787, 2182980356, 2215668010, 2248363750, 2281067577, 2313779492, 2346499496, 2379227590, 2411963775, 2444708052, 2477460422, 2510220886, 2542989445, 2575766100, 2608550852, 2641343702, 2674144651, 2706953700, 2739770850, 2772596102, 2805429457, 2838270916, 2871120480, 2903978150, 2936843927, 2969717812, 3002599806, 3035489910, 3068388125, 3101294452, 3134208892, 3167131446, 3200062115, 3233000900, 3265947802, 3298902822, 3331865961, 3364837220, 3397816600, 3430804102, 3463799727, 3496803476, 3529815350, 3562835350, 3595863477, 3628899732, 3661944116, 3694996630, 3728057275, 3761126052, 3794202962, 3827288006, 3860381185, 3893482500, 3926591952, 3959709542, 3992835271, 4025969140, 4059111150, 4092261302, 4125419597, 4158586036, 4191760620, 4224943350, 4258134227, 4291333252, 29573130, 62788455, 96011930, 129243557, 162483337, 195731271, 228987360, 262251605, 295524007, 328804567, 362093286, 395390165, 428695205, 462008407, 495329772, 528659301, 561996995, 595342855, 628696882, 662059077, 695429441, 728807975, 762194680, 795589557, 828992607, 862403831, 895823230, 929250805, 962686557, 996130487, 1029582596, 1063042885, 1096511355, 1129988007, 1163472842, 1196965861, 1230467065, 1263976455, 1297494032, 1331019797, 1364553751, 1398095895, 1431646230, 1465204757, 1498771477, 1532346391, 1565929500, 1599520805, 1633120307, 1666728007, 1700343906, 1733968005, 1767600305, 1801240807, 1834889512, 1868546421, 1902211535, 1935884855, 1969566382, 2003256117, 2036954061, 2070660215, 2104374580, 2138097157, 2171827947, 2205566951, 2239314170, 2273069605, 2306833257, 2340605127, 2374385216, 2408173525, 2441970055, 2475774807, 2509587782, 2543408981, 2577238405, 2611076055, 2644921932, 2678776037, 2712638371, 2746508935, 2780387730, 2814274757, 2848170017, 2882073511, 2915985240, 2949905205, 2983833407, 3017769847, 3051714526, 3085667445, 3119628605, 3153598007, 3187575652, 3221561541, 3255555675, 3289558055, 3323568682, 3357587557, 3391614681, 3425650055, 3459693680, 3493745557, 3527805687, 3561874071, 3595950710, 3630035605, 3664128757, 3698230167, 3732339836, 3766457765, 3800583955, 3834718407, 3868861122, 3903012101, 3937171345, 3971338855, 4005514632, 4039698677, 4073890991, 4108091575, 4142300430, 4176517557, 4210742957, 4244976631, 4279218580, 18501509, 52760012, 87026792, 121301851, 155585190, 189876810, 224176712, 258484897, 292801366, 327126120, 361459160, 395800487, 430150102, 464508006, 498874200, 533248685, 567631462, 602022532, 636421896, 670829555, 705245510, 739669762, 774102312, 808543161, 842992310, 877449760, 911915512, 946389567, 980871926, 1015362590, 1049861560, 1084368837, 1118884422, 1153408316, 1187940520, 1222481035, 1257029862, 1291587002, 1326152456, 1360726225, 1395308310, 1429898712, 1464497432, 1499104471, 1533719830, 1568343510, 1602975512, 1637615837, 1672264486, 1706921460, 1741586760, 1776260387, 1810942342, 1845632626, 1880331240, 1915038185, 1949753462, 1984477072, 2019209016, 2053949295, 2088697910, 2123454862, 2158220152, 2192993781, 2227775750, 2262566060, 2297364712, 2332171707, 2366987046, 2401810730, 2436642760, 2471483137, 2506331862, 2541188936, 2576054360, 2610928135, 2645810262, 2680700742, 2715599576, 2750506765, 2785422310, 2820346212, 2855278472, 2890219091, 2925168070, 2960125410, 2995091112, 3030065177, 3065047606, 3100038400, 3135037560, 3170045087, 3205060982, 3240085246, 3275117880, 3310158885, 3345208262, 3380266012, 3415332136, 3450406635, 3485489510, 3520580762, 3555680392, 3590788401, 3625904790, 3661029560, 3696162712, 3731304247, 3766454166, 3801612470, 3836779160, 3871954237, 3907137702, 3942329556, 3977529800, 4012738435, 4047955462, 4083180882, 4118414696, 4153656905, 4188907510, 4224166512, 4259433912, 4294709711, 35026614, 70319215, 105620217, 140929622, 176247431, 211573645, 246908265, 282251292, 317602727, 352962571, 388330825, 423707490, 459092567, 494486057, 529887961, 565298280, 600717015, 636144167, 671579737, 707023726, 742476135, 777936965, 813406217, 848883892, 884369991, 919864515, 955367465, 990878842, 1026398647, 1061926881, 1097463545, 1133008640, 1168562167, 1204124127, 1239694521, 1275273350, 1310860615, 1346456317, 1382060457, 1417673036, 1453294055, 1488923515, 1524561417, 1560207762, 1595862551, 1631525785, 1667197465, 1702877592, 1738566167, 1774263191, 1809968665, 1845682590, 1881404967, 1917135797, 1952875081, 1988622820, 2024379015, 2060143667, 2095916777, 2131698346, 2167488375, 2203286865, 2239093817, 2274909232, 2310733111, 2346565455, 2382406265, 2418255542, 2454113287, 2489979501, 2525854185, 2561737340, 2597628967, 2633529067, 2669437641, 2705354690, 2741280215, 2777214217, 2813156697, 2849107656, 2885067095, 2921035015, 2957011417, 2992996302, 3028989671, 3064991525, 3101001865, 3137020692, 3173048007, 3209083811, 3245128105, 3281180890, 3317242167, 3353311937, 3389390201, 3425476960, 3461572215, 3497675967, 3533788217, 3569908966, 3606038215, 3642175965, 3678322217, 3714476972, 3750640231, 3786811995, 3822992265, 3859181042, 3895378327, 3931584121, 3967798425, 4004021240, 4040252567, 4076492407, 4112740761, 4148997630, 4185263015, 4221536917, 4257819337, 4294110276, 35442439, 71750420, 108066922, 144391947, 180725496, 217067570, 253418170, 289777297, 326144952, 362521136, 398905850, 435299095, 471700872, 508111182, 544530026, 580957405, 617393320, 653837772, 690290762, 726752291, 763222360, 799700970, 836188122, 872683817, 909188056, 945700840, 982222170, 1018752047, 1055290472, 1091837446, 1128392970, 1164957045, 1201529672, 1238110852, 1274700586, 1311298875, 1347905720, 1384521122, 1421145082, 1457777601, 1494418680, 1531068320, 1567726522, 1604393287, 1641068616, 1677752510, 1714444970, 1751145997, 1787855592, 1824573756, 1861300490, 1898035795, 1934779672, 1971532122, 2008293146, 2045062745, 2081840920, 2118627672, 2155423002, 2192226911, 2229039400, 2265860470, 2302690122, 2339528357, 2376375176, 2413230580, 2450094570, 2486967147, 2523848312, 2560738066, 2597636410, 2634543345, 2671458872, 2708382992, 2745315706, 2782257015, 2819206920, 2856165422, 2893132522, 2930108221, 2967092520, 3004085420, 3041086922, 3078097027, 3115115736, 3152143050, 3189178970, 3226223497, 3263276632, 3300338376, 3337408730, 3374487695, 3411575272, 3448671462, 3485776266, 3522889685, 3560011720, 3597142372, 3634281642, 3671429531, 3708586040, 3745751170, 3782924922, 3820107297, 3857298296, 3894497920, 3931706170, 3968923047, 4006148552, 4043382686, 4080625450, 4117876845, 4155136872, 4192405532, 4229682826, 4266968755, 9296024, 46599227, 83911067, 121231546, 158560665, 195898425, 233244827, 270599872, 307963561, 345335895, 382716875, 420106502, 457504777, 494911701, 532327275, 569751500, 607184377, 644625907, 682076091, 719534930, 757002425, 794478577, 831963387, 869456856, 906958985, 944469775, 981989227, 1019517342, 1057054121, 1094599565, 1132153675, 1169716452, 1207287897, 1244868011, 1282456795, 1320054250, 1357660377, 1395275177, 1432898651, 1470530800, 1508171625, 1545821127, 1583479307, 1621146166, 1658821705, 1696505925, 1734198827, 1771900412, 1809610681, 1847329635, 1885057275, 1922793602, 1960538617, 1998292321, 2036054715, 2073825800, 2111605577, 2149394047, 2187191211, 2224997070, 2262811625, 2300634877, 2338466827, 2376307476, 2414156825, 2452014875, 2489881627, 2527757082, 2565641241, 2603534105, 2641435675, 2679345952, 2717264937, 2755192631, 2793129035, 2831074150, 2869027977, 2906990517, 2944961771, 2982941740, 3020930425, 3058927827, 3096933947, 3134948786, 3172972345, 3211004625, 3249045627, 3287095352, 3325153801, 3363220975, 3401296875, 3439381502, 3477474857, 3515576941, 3553687755, 3591807300, 3629935577, 3668072587, 3706218331, 3744372810, 3782536025, 3820707977, 3858888667, 3897078096, 3935276265, 3973483175, 4011698827, 4049923222, 4088156361, 4126398245, 4164648875, 4202908252, 4241176377, 4279453251, 22771579, 61065955, 99369082, 137680962, 176001596, 214330985, 252669130, 291016032, 329371692, 367736111, 406109290, 444491230, 482881932, 521281397, 559689626, 598106620, 636532380, 674966907, 713410202, 751862266, 790323100, 828792705, 867271082, 905758232, 944254156, 982758855, 1021272330, 1059794582, 1098325612, 1136865421, 1175414010, 1213971380, 1252537532, 1291112467, 1329696186, 1368288690, 1406889980, 1445500057, 1484118922, 1522746576, 1561383020, 1600028255, 1638682282, 1677345102, 1716016716, 1754697125, 1793386330, 1832084332, 1870791132, 1909506731, 1948231130, 1986964330, 2025706332, 2064457137, 2103216746, 2141985160, 2180762380, 2219548407, 2258343242, 2297146886, 2335959340, 2374780605, 2413610682, 2452449572, 2491297276, 2530153795, 2569019130, 2607893282, 2646776252, 2685668041, 2724568650, 2763478080, 2802396332, 2841323407, 2880259306, 2919204030, 2958157580, 2997119957, 3036091162, 3075071196, 3114060060, 3153057755, 3192064282, 3231079642, 3270103836, 3309136865, 3348178730, 3387229432, 3426288972, 3465357351, 3504434570, 3543520630, 3582615532, 3621719277, 3660831866, 3699953300, 3739083580, 3778222707, 3817370682, 3856527506, 3895693180, 3934867705, 3974051082, 4013243312, 4052444396, 4091654335, 4130873130, 4170100782, 4209337292, 4248582661, 4287836890, 32132684, 71404637, 110685452, 149975131, 189273675, 228581085, 267897362, 307222507, 346556521, 385899405, 425251160, 464611787, 503981287, 543359661, 582746910, 622143035, 661548037, 700961917, 740384676, 779816315, 819256835, 858706237, 898164522, 937631691, 977107745, 1016592685, 1056086512, 1095589227, 1135100831, 1174621325, 1214150710, 1253688987, 1293236157, 1332792221, 1372357180, 1411931035, 1451513787, 1491105437, 1530705986, 1570315435, 1609933785, 1649561037, 1689197192, 1728842251, 1768496215, 1808159085, 1847830862, 1887511547, 1927201141, 1966899645, 2006607060, 2046323387, 2086048627, 2125782781, 2165525850, 2205277835, 2245038737, 2284808557, 2324587296, 2364374955, 2404171535, 2443977037, 2483791462, 2523614811, 2563447085, 2603288285, 2643138412, 2682997467, 2722865451, 2762742365, 2802628210, 2842522987, 2882426697, 2922339341, 2962260920, 3002191435, 3042130887, 3082079277, 3122036606, 3162002875, 3201978085, 3241962237, 3281955332, 3321957371, 3361968355, 3401988285, 3442017162, 3482054987, 3522101761, 3562157485, 3602222160, 3642295787, 3682378367, 3722469901, 3762570390, 3802679835, 3842798237, 3882925597, 3923061916, 3963207195, 4003361435, 4043524637, 4083696802, 4123877931, 4164068025, 4204267085, 4244475112, 4284692107, 29950775, 70185710, 110429615, 150682492, 190944342, 231215166, 271494965, 311783740, 352081492, 392388222, 432703931, 473028620, 513362290, 553704942, 594056577, 634417196, 674786800, 715165390, 755552967, 795949532, 836355086, 876769630, 917193165, 957625692, 998067212, 1038517726, 1078977235, 1119445740, 1159923242, 1200409742, 1240905241, 1281409740, 1321923240, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_fail_1() { let mut out = vec![10, 10, 10, 10, 10]; limbs_mul_low_same_length(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_fail_2() { let mut out = vec![10]; limbs_mul_low_same_length(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_mul_low_same_length_fail_3() { let mut out = vec![10]; limbs_mul_low_same_length(&mut out, &[], &[]); } #[test] fn test_limbs_product() { fn test(xs: &[Limb], out: &[Limb]) { let xs_old = xs; let mut xs = xs_old.to_vec(); let mut product = Vec::new(); let (size, new_product) = limbs_product(&mut product, &mut xs); product = new_product.unwrap(); product.truncate(size); assert_eq!(product, out); let xs = xs_old; let mut product_alt = vec![0; xs.len()]; let out_len = limbs_product_naive(&mut product_alt, xs); product_alt.truncate(out_len); assert_eq!( Natural::from_owned_limbs_asc(product), Natural::from_owned_limbs_asc(product_alt) ); } #[cfg(feature = "32_bit_limbs")] { test(&[0, 0], &[0]); test(&[0, 1], &[0]); test(&[1, 1], &[1]); test(&[1, 2, 3, 0], &[0]); test(&[1, 1, 1, 6], &[6]); // - factor_len < RECURSIVE_PROD_THRESHOLD // - factor_len < RECURSIVE_PROD_THRESHOLD && carry == 0 test(&[2, 2], &[4]); // - 1 < factor_len < RECURSIVE_PROD_THRESHOLD test(&[2, 2, 2], &[8]); // - factor_len < RECURSIVE_PROD_THRESHOLD && carry != 0 test( &[ 3364358997, 3754657515, 2983848742, 3936755874, 1784338974, 2546784265, 1325228501, 2948540251, ], &[ 2931171496, 2374327460, 1603352486, 1643105815, 3729295616, 3598234472, 675706642, 97731883, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { test(&[0, 0], &[0]); // - factor_len >= RECURSIVE_PROD_THRESHOLD // - factor_len >= RECURSIVE_PROD_THRESHOLD && carry != 0 test( &[ 10008125746032292648, 18321114734333840332, 17920212203847604612, 11217657766511696793, 11281083380440747080, 7892713234117558634, 8902471323128328235, 11892365124252837749, 12611508814807140936, 11815551321438701427, 18110749687253320811, 11715728409437156086, 3339319126985623378, 6325617411041006209, 14096883611650388622, 17687808067973538964, 168019485471086672, 15693590891786235960, 2786725115760255375, 9052512570921605652, 14177547685319586247, 15370386165587184937, 5970865523433924174, ], &[ 11912117198576943104, 13014631084302689641, 13412132452197408442, 2451810739915146054, 11634661136866399370, 4370855263334042992, 15668998660816175865, 12986191105652374961, 13086723724779814479, 11723085021234472016, 11995103430870542887, 9025449360203176092, 2596804721077076476, 17187504964195613394, 3993660956642255072, 14652834649000131068, 115931129580828916, 5908166419484799210, 5266332857336541018, 10618265378208305889, 15818414605397825971, 1340104142930176609, 707009434669, ], ); // - factor_len >= RECURSIVE_PROD_THRESHOLD && carry == 0 test( &rle_decode(&[ (0, 2), (18446743798831644672, 1), (u64::MAX, 8), (131071, 1), (0, 1), (18446181123756130304, 1), (u64::MAX, 1), (0, 3), (18446744073709289472, 1), (18446744069414584323, 1), (u64::MAX, 2), (1048575, 1), ]), &[0], ); test( &[ 10985406156730349404, 16998073653641921623, 17457059674168741173, 7286565767689019192, 18125356898477139174, 16492808515310020304, 3477958611236241232, 16292175871113024008, 5585730561604558759, 6236295300549613743, 10319623255002503349, 9463751064224151456, 591089135516199459, 2252218169318269834, 862892606080353458, 5048725452063866206, 8818325570889918907, 8659485206830156469, 13423243087758132387, 5931638651683836702, 726189598260086702, 17552568882310631283, 16362554893644374308, 2407211671412641092, 1658933737262819201, 8531670718492391711, 7551068411167036177, 1219676338169570619, 3249808943561478386, 8240095392791493806, 18379760227315341655, 15217742262236663404, 17914601533857880122, 6316977119306097487, 15466746727219811764, 3809403759956883034, 7752635439402559334, 18006879800705758675, 10224737295140518487, 8383030445894670697, 7272423850473130597, 9751703358656322718, 5778325638584493526, 8175215950976649646, 8581067395248196883, 4729909244293992358, 7626677144783852491, 15620921255634335582, 17768397379068248272, 7127187304413875110, ], &[ 3631027199567462400, 1271721650030716672, 2994855603235436973, 17610775060915408482, 5067312238234780182, 17332419541318968246, 16256455013715596255, 8446753555477097340, 6176580983302425584, 4478791418516115226, 4543632153902351949, 8389257049215340154, 7312665208898130485, 7684632819757707617, 3755281952906934158, 13259632617670669038, 8815229384280433597, 18114656906332551194, 8751551051855969605, 3831140942508279269, 3191248804852725269, 2021644817234089610, 17966341018397783935, 17567823138927086650, 7667876961419931279, 14788070825593093177, 18150799194320967018, 10911257712565360499, 17179583904099919127, 13486844951716301158, 10333473285718288690, 11178175053564016056, 7882508656916287058, 10989425714502087490, 6829028223894926894, 810375652491815426, 17216794810099974028, 590650088582786587, 4701269004129928787, 3119542545671269984, 14375368104481453295, 124160740720125385, 1360655591798967164, 17850602821256829937, 6139583463573727145, 14578358562855390329, 14560675482255305936, 16662995492200800253, 666535375735877288, ], ); } } #[test] fn limbs_mul_low_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 512); config.insert("mean_stripe_n", 256 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_1().test_properties_with_config(&config, |(out_before, xs, ys)| { let mut out = out_before.to_vec(); limbs_mul_low_same_length(&mut out, &xs, &ys); verify_mul_low_1(&out_before, &xs, &ys, &out); }); } #[test] fn test_mul_context() { let context = initialize_context(); assert_eq!(context.clone().serialize(), CONTEXT); assert_eq!(context, CONTEXT.deserialize()); } #[test] fn test_mul() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n *= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n *= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = mul_slow_fft(&u, &v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigUint::from_str(s).unwrap() * BigUint::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() * rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "0"); test("123", "0", "0"); test("1", "123", "123"); test("123", "1", "123"); test("123", "456", "56088"); test("0", "1000000000000", "0"); test("1000000000000", "0", "0"); test("1", "1000000000000", "1000000000000"); test("1000000000000", "1", "1000000000000"); test("1000000000000", "123", "123000000000000"); test("123", "1000000000000", "123000000000000"); test("123456789000", "987654321000", "121932631112635269000000"); test("4294967295", "2", "8589934590"); test("18446744073709551615", "2", "36893488147419103230"); test("4294967295", "4294967295", "18446744065119617025"); test( "147502279655636565600250358452694051893980186696958535174009956523855720107322638159749368\ 0808217479494744305876890972595771484769733857514529616096199394092858302265998260483416016\ 5763904522044264005938281072568140883513713255548643044250086110483617215935636533809248102\ 6926590789142079805638445494760177551776636747830014495012489743990407355232286842071418922\ 9921358409573480901624487977319782755422730834468673438076805532952821406024399006814390166\ 6949827530796971086011267864607814906313334525518102221919643040440267323688341889035864376\ 1377246644579088153222669672271414315240318439843720039808993886410874969340996645010795670\ 2133518716987668865936529827437388042190084309005369564717390726257594902619365180097509576\ 6240189037770619308206906414128686856349950952623970023039440323701643457411485666776354448\ 186307133288106956593939073729500658176632828099789", "577397114388109712462006371470162814529304445639807296878809567953200969820156259914159240\ 9106139481288193067515284601342023565222679498917484131095648263181800618990427694244342686\ 4412105186059052689237237088193855584354278755933606296018800151986520872701706693002473648\ 4330061421236425747083307907706860804054565348593527605104495080560663025897787060638154303\ 7631781316565710346299551930891169154491973589315700505458672804104869879731391323700304", "851673906388325341550957943071111911557800036845129556099360938813259608650267079456739978\ 1156959952275409185911771336067392377245918291754269000751186715279414560474882570499082990\ 4913122978897463970860833616251189242098804876664368441608727895141238953179204529256780277\ 5978105200286025161944212712977056343127682601975191673217459602567633602198262568921008081\ 9448556670912575287371251190800855926311768876808375177446530243635212748346921654224589861\ 0625170426812525829689862407515510419445335472631905610235915226032848323874067128872385291\ 3730739275467227364692195226129501338887049710586931141309357190341064532366013123280106098\ 6468151628797945455179649866890394481799639832540978091736379482964522229064478167730317490\ 8194108506704480750395054067032502530392147690725919399930683143510771646869931527123340650\ 0547649792331568913460415939722111305270588701531404490040034302102101083691706550376288655\ 2667382899390792494118931379237432071316543313379792218794371176529684614085109418328963817\ 0601432767270419229719490809539776535671938041618536196941370647945336401901450921413823163\ 4059991707077834107830876756821880651429748186401020760113859498185638133726165286481741014\ 9079906337286599226335508424466369316294442004040440528589582239717042654541745348050157252\ 3448224036804997350851153108395928780441635856", ); let big_test = |u: Natural, v: Natural| { let mut n = u.clone(); n *= v.clone(); assert!(n.is_valid()); let product = n; let mut n = u.clone(); n *= &v; assert!(n.is_valid()); assert_eq!(n, product); let n = u.clone() * v.clone(); assert!(n.is_valid()); assert_eq!(n, product); let n = &u * v.clone(); assert!(n.is_valid()); assert_eq!(n, product); let n = u.clone() * &v; assert!(n.is_valid()); assert_eq!(n, product); let n = &u * &v; assert!(n.is_valid()); assert_eq!(n, product); let n = rug::Integer::from(&u) * rug::Integer::from(&v); assert!(Natural::exact_from(&n) == product); let n = mul_slow_fft(&u, &v); assert!(n.is_valid()); assert_eq!(n, product); }; // - in mpn_ctx_init // - i == 0 first time in mpn_ctx_init // - in sd_fft_ctx_init_prime // - in fft_small_mulmod_satisfies_bounds // - n2hi != 0 in fft_small_mulmod_satisfies_bounds // - b >= 2 in fft_small_mulmod_satisfies_bounds // - in reduce_0n_to_pmhn // - a > halfn in reduce_0n_to_pmhn // - in f64_reduce_pm1n_to_pmhn // - a <= halfn <= t in f64_reduce_pm1n_to_pmhn // - i >= l in sd_fft_ctx_init_prime // - i < l in sd_fft_ctx_init_prime // - a > halfn in f64_reduce_pm1n_to_pmhn // - a <= halfn in reduce_0n_to_pmhn // - a <= halfn && t < halfn in f64_reduce_pm1n_to_pmhn // - i == 0 second time in mpn_ctx_init // - i != 0 first time in mpn_ctx_init // - in next_fft_number // - q.significant_bits() == bits in next_fft_number // - q.significant_bits() != bits && l >= 5 in next_fft_number // - i != 0 second time in mpn_ctx_init // - in push_profile // - in crt_data_find_bn_bound // - q < n + 1 in crt_data_find_bn_bound // - r > 0 in crt_data_find_bn_bound // - !borrow in crt_data_find_bn_bound // - x[i] == 0 in crt_data_find_bn_bound // - r = 0 in crt_data_find_bn_bound // - in mpn_ctx_mpn_mul // - in mpn_ctx_best_profile // - bn <= r.profiles[i].bn_bound in mpn_ctx_best_profile // - score < best_score in mpn_ctx_best_profile // - i < r.profiles_size in mpn_ctx_best_profile // - bn <= r.profiles[i].bn_bound in mpn_ctx_best_profile // - bn > r.profiles[i].bn_bound in mpn_ctx_best_profile // - score >= best_score in mpn_ctx_best_profile // - i >= r.profiles_size in mpn_ctx_best_profile // - in flint_mpn_cmp_ui_2exp // - an != 0 in flint_mpn_cmp_ui_2exp // - r != 0 in flint_mpn_cmp_ui_2exp // - an <= q + 2 in flint_mpn_cmp_ui_2exp // - x == b1 in flint_mpn_cmp_ui_2exp // - x != b0 in flint_mpn_cmp_ui_2exp // - p.to_ffts != None in mpn_ctx_mpn_mul // - bits % 8 != 0 in mpn_ctx_mpn_mul // - in mpn_ctx_fit_buffer // - n > r.buffer_alloc in mpn_ctx_fit_buffer // - in mod_worker_func // - in MPNToFFTFunc::apply // - self.bits % 8 != 0 && self.bits % 4 == 0 in MPNToFFTFunc::apply // - in code // - bits - j != 0 in code // - bits - j == 0 in code // - in mpn_to_ffts_hard // - bits - j != 0 in mpn_to_ffts_hard // - in fft_worker_func // - in sd_fft_trunc // - l_u64 > LG_BLK_SZ in sd_fft_trunc // - in sd_fft_ctx_fit_depth // - tdepth >= depth in sd_fft_ctx_fit_depth // - in sd_fft_trunc_internal // - otrunc >= 1 in sd_fft_trunc_internal // - itrunc >= 1 in sd_fft_trunc_internal // - itrunc != otrunc || otrunc != usize::power_of_2(k) in sd_fft_trunc_internal // - k > 2 in sd_fft_trunc_internal // - in sd_fft_trunc_block // - otrunc >= 1 in sd_fft_trunc_block // - itrunc <= 1 in sd_fft_trunc_block // - itrunc >= 1 in sd_fft_trunc_block // - itrunc >= 1 && i < BLK_SZ in sd_fft_trunc_block // - itrunc >= 1 && i >= BLK_SZ in sd_fft_trunc_block // - itrunc == otrunc && otrunc == usize::power_of_2(k) in sd_fft_trunc_internal // - in sd_fft_no_trunc_internal // - k == 2 in sd_fft_no_trunc_internal // - in sd_fft_no_trunc_block // - k <= 4 in sd_fft_no_trunc_block // - in set_j_bits_and_j_r // - j == 0 in set_j_bits_and_j_r // - k >= 2 in sd_fft_no_trunc_block // - k >= 2 && j_bits == 0 in sd_fft_no_trunc_block // - k >= 2 && j_bits == 0 && i < BLK_SZ in sd_fft_no_trunc_block // - k >= 2 && j_bits == 0 && i >= BLK_SZ in sd_fft_no_trunc_block // - k >= 2 && j_bits == 0 && a >= l2 in sd_fft_no_trunc_block // - k >= 2 && l2 == 1 in sd_fft_no_trunc_block // - in sd_fft_base_8_1 // - j == 0 in sd_fft_base_8_1 // - in sd_fft_basecase_8_1 // - i < l in sd_fft_basecase_8_1 // - i >= l in sd_fft_basecase_8_1 // - in sd_fft_basecase_6_1 // - i < l in sd_fft_basecase_6_1 // - i >= l in sd_fft_basecase_6_1 // - in sd_fft_basecase_6_0 // - i < l in sd_fft_basecase_6_0 // - i >= l in sd_fft_basecase_6_0 // - in sd_fft_base_8_0 // - j != 0 in set_j_bits_and_j_r // - in sd_fft_basecase_8_0 // - i < l in sd_fft_basecase_8_0 // - i >= l in sd_fft_basecase_8_0 // - k == 2 in sd_fft_trunc_internal // - itrunc > 1 in sd_fft_trunc_block // - itrunc != otrunc || otrunc != usize::power_of_2(k) in sd_fft_trunc_block // - k <= 2 in sd_fft_trunc_block // - k == 2 in sd_fft_trunc_block // - in sd_fft_moth_trunc_block_0 // - 0 < ITRUNC in sd_fft_moth_trunc_block_0 // - 1 < ITRUNC in sd_fft_moth_trunc_block_0 // - 2 < ITRUNC in sd_fft_moth_trunc_block_0 // - 3 < ITRUNC in sd_fft_moth_trunc_block_0 // - 0 < OTRUNC in sd_fft_moth_trunc_block_0 // - 1 < OTRUNC in sd_fft_moth_trunc_block_0 // - 2 < OTRUNC in sd_fft_moth_trunc_block_0 // - 3 >= OTRUNC in sd_fft_moth_trunc_block_0 // - i < BLK_SZ in sd_fft_moth_trunc_block_0 // - i >= BLK_SZ in sd_fft_moth_trunc_block_0 // - j != 0 in sd_fft_base_8_1 // - k == 2 && otrunc > 1 in sd_fft_trunc_internal // - k == 2 && otrunc > 2 in sd_fft_trunc_internal // - k == 2 && otrunc <= 3 in sd_fft_trunc_internal // - in nmod_red2 // - r1xx > q0xx in nmod_red2 // - r1xx < nxx in nmod_red2 // - !x.squaring in fft_worker_func // - in sd_fft_ctx_point_mul // - in f64_reduce_0n_to_pmhn // - a > halfn in f64_reduce_0n_to_pmhn // - j < BLK_SZ in sd_fft_ctx_point_mul // - j >= BLK_SZ in sd_fft_ctx_point_mul // - in sd_ifft_trunc // - l_u64 > LG_BLK_SZ in sd_ifft_trunc // - in sd_ifft_trunc_internal // - f != 0 || z != n || n != usize::power_of_2(k) in sd_ifft_trunc_internal // - k > 2 in sd_ifft_trunc_internal // - in sd_ifft_no_trunc_internal // - k == 2 in sd_ifft_no_trunc_internal // - in sd_ifft_base_8_1 // - in set_j_bits_and_j_mr // - j == 0 in set_j_bits_and_j_mr // - j == 0 in sd_ifft_base_8_1 // - in sd_ifft_basecase_8_1 // - in sd_ifft_basecase_6_1 // - i < l in sd_ifft_basecase_6_1 // - i >= l in sd_ifft_basecase_6_1 // - sd_ifft_basecase_6_0 // - i < l in sd_ifft_basecase_6_0 // - i >= l in sd_ifft_basecase_6_0 // - i < l in sd_ifft_basecase_8_1 // - i >= l in sd_ifft_basecase_8_1 // - in sd_ifft_base_8_0 // - j != 0 in set_j_bits_and_j_mr // - in d_ifft_basecase_8_0 // - i < l in d_ifft_basecase_8_0 // - i >= l in d_ifft_basecase_8_0 // - in sd_ifft_no_trunc_block // - k <= 2 in sd_ifft_no_trunc_block // - k == 2 in sd_ifft_no_trunc_block // - k == 2 && j_bits == 0 in sd_ifft_no_trunc_block // - k == 2 && j_bits == 0 && i < BLK_SZ in sd_ifft_no_trunc_block // - k == 2 && j_bits == 0 && i >= BLK_SZ in sd_ifft_no_trunc_block // - in sd_ifft_trunc_block // - f != 0 || z != n || n != usize::power_of_2(k) in sd_ifft_trunc_block // - k != 2 in sd_ifft_trunc_block // - k == 1 in sd_ifft_trunc_block // - in radix_2_moth_inv_trunc_block_1_1_1 // - i < BLK_SZ in radix_2_moth_inv_trunc_block_1_1_1 // - i >= BLK_SZ in radix_2_moth_inv_trunc_block_1_1_1 // - k == 2 in sd_ifft_trunc_internal // - j != 0 in sd_ifft_base_8_1 // - k == 2 && n > 1 in sd_ifft_trunc_internal // - k == 2 && n > 2 in sd_ifft_trunc_internal // - k == 2 && n <= 3 in sd_ifft_trunc_internal // - k == 2 in sd_ifft_trunc_block // - in radix_4_moth_inv_trunc_block_3_4_0 // - j != 0 in radix_4_moth_inv_trunc_block_3_4_0 // - in f64x4_reduce_pm1n_to_pmhn // - ai <= hi <= ti in f64x4_reduce_pm1n_to_pmhn // - i < BLK_SZ in radix_4_moth_inv_trunc_block_3_4_0 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_3_4_0 // - k == 2 && f == 0 in sd_ifft_trunc_internal // - f == 0 && z == n && n == usize::power_of_2(k) in sd_ifft_trunc_block // - k == 1 in sd_ifft_no_trunc_block // - k == 1 && j_bits == 0 in sd_ifft_no_trunc_block // - k == 1 && j_bits == 0 && i < BLK_SZ in sd_ifft_no_trunc_block // - k == 1 && j_bits == 0 && i >= BLK_SZ in sd_ifft_no_trunc_block // - r1xx <= q0xx in nmod_red2 // - a <= halfn in f64_reduce_0n_to_pmhn // - in crt_worker_func // - in MPNFromFFTs::apply // - overhang.is_empty() in MPNFromFFTs::apply // - self.n != self.m + 1 in MPNFromFFTs::apply // - in convert_block // - in f64x4_reduce_to_0n // - in f64x4_reduce_pm1no_to_0n // - in f64_reduce_pm1no_to_0n // - a >= 0.0 in f64_reduce_pm1no_to_0n // - j < BLK_SZ in convert_block // - j >= BLK_SZ in convert_block // - in big_mul // - k + 1 < n in big_mul // - k + 2 < n in big_mul // - n == k + 2 in big_mul // - n == k + 2 && k + 1 < m in big_mul // - in big_addmul // - k + 1 < n in big_addmul // - k + 2 < n in big_addmul // - n == k + 2 in big_addmul // - n == k + 2 && k + 1 < m in big_addmul // - in reduce_big_sum // - in multi_add // - n == 3 in multi_add // - r[k - 1] <= limit[k - 1] in reduce_big_sum // - r[k - 1] < limit[k - 1] in reduce_big_sum // - in add_to_answer_easy // - tshift == 0 in add_to_answer_easy // - n == 4 in multi_add // - tshift != 0 in add_to_answer_easy // - n == 5 in multi_add // - in f64_reduce_to_0n // - toff < z.len() in MPNFromFFTs::apply // - in add_to_answer_hard // - tshift == 0 in add_to_answer_hard // - tshift == 0 && z.len() - toff >= n in add_to_answer_hard // - tshift != 0 in add_to_answer_hard // - tshift != 0 && z.len() - toff > n in add_to_answer_hard // - tshift != 0 && z.len() - toff <= n in add_to_answer_hard // - a < 0.0 in f64_reduce_pm1no_to_0n // - r[k - 1] > limit[k - 1] in reduce_big_sum // - goto_sub in reduce_big_sum // - in multi_sub // - n == 4 in multi_sub // - r[k - 1] >= limit[k - 1] in reduce_big_sum // - !goto_sub in reduce_big_sum // - r[0] >= limit[0] in reduce_big_sum // - slow_fft: in mod_fft_worker_func // - slow_fft: !x.squaring in mod_fft_worker_func // - slow_fft: in slow_mpn_to_fft // - slow_fft: in slow_mpn_to_fft_easy // - slow_fft: bits - j != 0 in slow_mpn_to_fft_easy // - slow_fft: bits - j == 0 in slow_mpn_to_fft_easy // - slow_fft: bits - j != 0 in slow_mpn_to_fft // - slow_fft: bits - j == 0 in slow_mpn_to_fft big_test(Natural::power_of_2(100_000), Natural::power_of_2(100_000)); // - bits % 8 == 0 in mpn_ctx_mpn_mul // - self.bits % 8 == 0 in MPNToFFTFunc::apply // - tdepth < depth in sd_fft_ctx_fit_depth // - in sd_fft_ctx_fit_depth_with_lock // - ai > hi in f64x4_reduce_pm1n_to_pmhn // - i < l in sd_fft_ctx_fit_depth_with_lock // - ai <= hi && ti < hi in f64x4_reduce_pm1n_to_pmhn // - i >= l in sd_fft_ctx_fit_depth_with_lock // - k > 2 in sd_fft_trunc_block // - in sd_fft_moth_trunc_block_1 // - 0 < ITRUNC in sd_fft_moth_trunc_block_1 // - 1 < ITRUNC in sd_fft_moth_trunc_block_1 // - 2 >= ITRUNC in sd_fft_moth_trunc_block_1 // - 3 >= ITRUNC in sd_fft_moth_trunc_block_1 // - 0 < OTRUNC in sd_fft_moth_trunc_block_1 // - 1 < OTRUNC in sd_fft_moth_trunc_block_1 // - 2 < OTRUNC in sd_fft_moth_trunc_block_1 // - 3 < OTRUNC in sd_fft_moth_trunc_block_1 // - i < BLK_SZ in sd_fft_moth_trunc_block_1 // - i >= BLK_SZ in sd_fft_moth_trunc_block_1 // - itrunc == otrunc && otrunc == usize::power_of_2(k) in sd_fft_trunc_block // - k >= 2 && j_bits != 0 in sd_fft_no_trunc_block // - k >= 2 && j_bits != 0 && i < BLK_SZ in sd_fft_no_trunc_block // - k >= 2 && j_bits != 0 && i >= BLK_SZ in sd_fft_no_trunc_block // - k >= 2 && j_bits != 0 && a >= l2 in sd_fft_no_trunc_block // - n2 == 0 in sd_fft_trunc_block // - k >= 2 && j_bits == 0 && a < l2 in sd_fft_no_trunc_block // - k >= 2 && l2 != 1 in sd_fft_no_trunc_block // - k >= 2 && b < l1 in sd_fft_no_trunc_block // - k >= 2 && b >= l1 in sd_fft_no_trunc_block // - k >= 2 && j_bits != 0 && a < l2 in sd_fft_no_trunc_block // - n2 > 0 in sd_fft_trunc_block // - 1 >= OTRUNC in sd_fft_moth_trunc_block_0 // - 2 >= OTRUNC in sd_fft_moth_trunc_block_0 // - k > 2 in sd_fft_no_trunc_internal // - a < l2 in sd_fft_no_trunc_internal // - a >= l2 in sd_fft_no_trunc_internal // - b < l1 in sd_fft_no_trunc_internal // - b >= l1 in sd_fft_no_trunc_internal // - k == 2 && otrunc <= 1 in sd_fft_trunc_internal // - k == 2 && otrunc <= 2 in sd_fft_trunc_internal // - k > 2 in sd_ifft_no_trunc_internal // - b < l1 in sd_ifft_no_trunc_internal // - k == 2 && j_bits != 0 in sd_ifft_no_trunc_block // - k == 2 && j_bits != 0 && i >= BLK_SZ in sd_ifft_no_trunc_block // - b >= l1 in sd_ifft_no_trunc_internal // - a < l2 in sd_ifft_no_trunc_internal // - a >= l2 in sd_ifft_no_trunc_internal // - k > 2 in sd_ifft_no_trunc_block // - k > 2 && b < l1 in sd_ifft_no_trunc_block // - k > 2 && b >= l1 in sd_ifft_no_trunc_block // - k > 2 && a < l2 in sd_ifft_no_trunc_block // - k > 2 && a >= l2 in sd_ifft_no_trunc_block // - k > 1 in sd_ifft_trunc_block // - in radix_4_moth_inv_trunc_block_3_3_1 // - j == 0 in radix_4_moth_inv_trunc_block_3_3_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_3_3_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_3_3_1 // - in radix_4_moth_inv_trunc_block_3_4_1 // - j != 0 in radix_4_moth_inv_trunc_block_3_4_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_3_4_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_3_4_1 // - in radix_4_moth_inv_trunc_block_0_4_1 // - j != 0 in radix_4_moth_inv_trunc_block_0_4_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_0_4_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_0_4_1 // - k == 2 && n <= 1 in sd_ifft_trunc_internal // - k == 2 && n <= 2 in sd_ifft_trunc_internal // - in radix_4_moth_inv_trunc_block_1_4_0 // - j != 0 in radix_4_moth_inv_trunc_block_1_4_0 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_1_4_0 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_1_4_0 // - self.n == self.m + 1 in MPNFromFFTs::apply // - k + 1 >= n in big_mul // - k >= m in big_mul // - k + 1 >= n in big_addmul // - k + 1 < n && k >= m in big_addmul // - n == 6 in multi_add // - n == 5 in multi_sub // - tshift == 0 && z.len() - toff < n in add_to_answer_hard big_test( Natural::power_of_2(0x3fff_fffe), Natural::power_of_2(0x4000_0000), ); big_test( Natural::from(0x3d500b05e209u64) << 0x3fffffbc, Natural::power_of_2(0x4000_0028), ); // - k == 1 in sd_fft_no_trunc_block // - k == 1 && j_bits == 0 in sd_fft_no_trunc_block // - k == 1 && j_bits == 0 && i < BLK_SZ in sd_fft_no_trunc_block // - k == 1 && j_bits == 0 && i >= BLK_SZ in sd_fft_no_trunc_block // - k == 1 && j_bits != 0 in sd_fft_no_trunc_block // - k == 1 && j_bits != 0 && i < BLK_SZ in sd_fft_no_trunc_block // - k == 1 && j_bits != 0 && i >= BLK_SZ in sd_fft_no_trunc_block // - k == 1 in sd_fft_trunc_block // - j_bits != 0 in sd_fft_trunc_block // - j_bits != 0 && i < BLK_SZ in sd_fft_trunc_block // - j_bits != 0 && i >= BLK_SZ in sd_fft_trunc_block // - k == 1 && j_bits != 0 in sd_ifft_no_trunc_block // - k == 1 && j_bits != 0 && i < BLK_SZ in sd_ifft_no_trunc_block // - k == 1 && j_bits != 0 && i >= BLK_SZ in sd_ifft_no_trunc_block // - in radix_2_moth_inv_trunc_block_1_2_1 // - i <= BLK_SZ in radix_2_moth_inv_trunc_block_1_2_1 // - i >= BLK_SZ in radix_2_moth_inv_trunc_block_1_2_1 // - in radix_4_moth_inv_trunc_block_1_4_1 // - j != 0 in radix_4_moth_inv_trunc_block_1_4_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_1_4_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_1_4_1 // - in radix_2_moth_inv_trunc_block_0_2_1 // - i < BLK_SZ in radix_2_moth_inv_trunc_block_0_2_1 // - i >= BLK_SZ in radix_2_moth_inv_trunc_block_0_2_1 // - in radix_4_moth_inv_trunc_block_2_4_1 // - j != 0 in radix_4_moth_inv_trunc_block_2_4_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_2_4_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_2_4_1 // - in radix_2_moth_inv_trunc_block_1_2_0 // - i < BLK_SZ in radix_2_moth_inv_trunc_block_1_2_0 // - i >= BLK_SZ in radix_2_moth_inv_trunc_block_1_2_0 // - in radix_4_moth_inv_trunc_block_2_4_0 // - j != 0 in radix_4_moth_inv_trunc_block_2_4_0 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_2_4_0 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_2_4_0 let p = Natural::power_of_2(33554432); big_test(p.clone(), p); // - bits - j == 0 in mpn_to_ffts_hard big_test( Natural::from(0x16fb3b96u32) << 0x3fffff34, Natural::power_of_2(0x4000_0100), ); // - 3 >= OTRUNC in sd_fft_moth_trunc_block_1 // - in radix_4_moth_inv_trunc_block_3_3_0 // - j == 0 in radix_4_moth_inv_trunc_block_3_3_0 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_3_3_0 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_3_3_0 // - n == k + 2 && k + 1 >= m in big_mul // - n == k + 2 && k + 1 >= m in big_addmul // - n == 7 in multi_add // - n == 6 in multi_sub big_test(Natural::power_of_2(63936), Natural::power_of_2(63936)); // - k == 2 && otrunc > 3 in sd_fft_trunc_internal // - f == 0 && z == n && n == usize::power_of_2(k) in sd_ifft_trunc_internal big_test(Natural::power_of_2(64512), Natural::power_of_2(64512)); // - r == 0 in flint_mpn_cmp_ui_2exp // - n == 7 in multi_sub big_test(Natural::power_of_2(86016), Natural::power_of_2(86016)); // - 2 < ITRUNC in sd_fft_moth_trunc_block_1 // - 3 >= ITRUNC in sd_fft_moth_trunc_block_0 big_test(Natural::power_of_2(103936), Natural::power_of_2(103936)); // - in radix_4_moth_inv_trunc_block_2_2_1 // - j == 0 in radix_4_moth_inv_trunc_block_2_2_1 // - i < BLK_SZ in radix_4_moth_inv_trunc_block_2_2_1 // - i >= BLK_SZ in radix_4_moth_inv_trunc_block_2_2_1 big_test(Natural::power_of_2(196608), Natural::power_of_2(196608)); // - 3 < OTRUNC in sd_fft_moth_trunc_block_0 big_test(Natural::power_of_2(831488), Natural::power_of_2(831488)); // - 2 >= ITRUNC in sd_fft_moth_trunc_block_0 let xss = "24332291938350038903987086117452297484640131355471951974855407437218461662995085424\ 1860343418803581980657405626860254652890061074767469192047813813799932319718522304171962256525\ 7568055010500751693801073277207915783608062444476635234859794533294164960300047032518429869718\ 0052375107888369790876137797913656159503367175950921134284892262945719972924783600113662790091\ 7723137030730717109700031076462319946729252039277677223053596049990468731493768134267546652245\ 9447539562895196690291348300229856993968834050493144473459087214855851757452241695990617787853\ 5199110900136732650745267977111595354409876835104545902940816295224847190897196586187642185942\ 7115084845311162640011317079975305649053712739504852532939021059106632665478282767934276018468\ 3772465062808400010091575582223455939006711157609546345615881921362719919601326216561019357404\ 1307776016479445080199091132571997412545060655069163981698127006802628570553632609577780538500\ 3707180977422074551828555726659024662683193823385532498118408491723608092599551772313009613576\ 9202093170363335286917554623386262649548756047946587691518367947774996520656284075670983115064\ 1575561983250471453563242494332027835434592225708375455816732666820644708164077370144244709924\ 2886492316681462424687403046620621334999846710010915455227140598754811069666079446786776250465\ 1158391318965589187497341988747157410814695119596376070806690317808127211429138816443900046579\ 1713504851157547960393907525383172895098955573889994108135487994839225140144512698339040295307\ 4983198507370789525216254751572115706023212347379274683752751119359793048368824363371149895523\ 6708716721566125659384073633508318562863418191074523407590701176579663244163366170416731471042\ 0881494463153749413765094325829460446318165910401791976980543893866068276302268063932544653016\ 5446401851712336229001129440172467672330551520402075974514581592122579944576588625658770872147\ 3814466924989513800849277908506132844631331613100121400327222682060783945131182176703570032858\ 1694191759633514739449029442304916719067359422626377238687968978008224643603240938590144618019\ 5974470266383166442744450178377455275616015689358085839578524704077624355704288991739128107030\ 7944356865755249007269951629748947739853589497099489959849775244527083957050938890967276078321\ 7234404421413669718730038426475200271735571020287092847099289050730297264949167253932526806757\ 5761574850542650689403252780749160325307909643026214138555913283748651923074985778370994249224\ 0538100363691026775023717853871551279871815549992695845552242809187014152149852925091682826897\ 0100250490120849350712930590565284560396151845148609154567900261991659015189427805827613513840\ 2170254890548213557921865008034436480864143142943575002317883943975921600818662788252456195796\ 9447581468425720833225730520539264714015417324821258134938643521929335724439553850668221566620\ 9653372789560194862201973172518669820406209880954310599408074691560758794196569253974787849604\ 0774806073544962056857697166426572919998961349923037111540287606972184621706891929894655664837\ 7299630550611392558865110193262321196476727501877710107986226105792040010118482608036131448182\ 0117942605612310576811461708465035885447882695924553186493804383583383296673755075165009425413\ 7902911985641095285650983114630215230812593379260105786492476324242972811986138247168152651256\ 1657597868369438065816705013956080825126024961539665573062075205110450571733109317102657929184\ 5392136845155953496969869518778271324578196626603171710776025271793126614077090441609966141249\ 7564550738269080462472436036602779169468412236753684502462987305092434452135040410366722125314\ 2121092955111992583432284424064604710829455130399212898733562868981102772481600659980518115186\ 8941956481181061336467477352250281585781890099852282348615063663284636964073977423518637726988\ 1882455638952079577385262849303256253047928272821306192874241480405083194569987960280849589197\ 9041502642441824495701127000226367651264029302468437554790510342503980748137332892679198508283\ 2745785497776645520349039567530649346901888256310592138908124191299572459222799154644000700887\ 5493273958509265831183039516557237163741608869141769472683318845718901198903429866035439036703\ 1660739118209863418959025889435705192584893889664911545868560854311859470957036057997797971494\ 9594620952627927226895665205135051298929237955012336474516638364366879602654222749489576920140\ 1318979413859115848991007818030170744198159538630775848274453280720838340018046108312511173154\ 1188508107938930293795518178576635436138460554498353633963905882970277705168749377789845155952\ 4046716501223496052457375457150747483247403948712634771689237194996834184555628278768787640661\ 2372930326732128380641801437674515050015102288649901511810982723595351594068392716225599079089\ 7141248147850585347340347757078749027234015237390954477920785794414160228011889578891858827269\ 4508081089273025619651528529620265738787963624424963422805984686902171986907635940163516673467\ 1155594542959710450739107283869735164216439962843577553460754034992131140408553869374139050671\ 8450114951382241887892041208648008140979233339479046369051440737102608072264939682976419595968\ 3413896931667290581888677992785581066829903256901254436110000731831303537790270657076522229890\ 9754224348408990685592550990298278035179012217735194179912617357301891964389443682832716913065\ 5919450467625243008402724262864414724869527161380535200659835132577737473843355193862226646260\ 5917441484316297436589404142390177228546728707107334838679844265630396267767368973104829422596\ 4841863445594624523412084728039594631547587966918797170352167897829291584959443989673299826182\ 8176064493225754295777402784264651240473071834468650888202279832376595199290014151001790898088\ 8058661551199293778280650366579556501013484442751446773728015384143389787231217456258934188739\ 5896429594127218742822188813069161682965414824040997384010926995603056099487738813358316336237\ 2734428969066095632539853611968820662320319907498725771573336282476197704351509672049102759380\ 1044103415660565643697738457112577215858363311385328752890557311941900303869448413209818047617\ 2161153309772547939099075533202437403831740157362321227529471592353138031815867815519584071649\ 0075624207080493141540692388138745915962336493655092425288749464092167701822102541814916477264\ 3225692001069823029594562785625284238026849939613336498119461792246559953436606295049089119377\ 4141880555871541099485841865699217690368990323296714388728658411576310723412148324894713183283\ 4801500365755458165963393555761451023119653317501067666748424009917402509388520284485265783859\ 4511326665481049662430681317565668801625733953464868640523431972011024627186538495185957786882\ 9978407950806799105487884906168404211352484266994537079818819955059544683145533593154717193045\ 5690117445417170001831918307910549744284542110192258349795624756723502659770683585718793894280\ 2618016103430682458503045911456259958793713838831389358734769335617062903694409579189685200809\ 3962764608923109615152818499046008749652174640992925750313000312436473383850032668149986379348\ 3052059498095257336376699231032337021048693681952251198585124389201819206230457935652529344909\ 7032725206275909927921260089910589468718979227475505269422145304016465491141881920960641536301\ 9140778639285252843615315347803978849851275461130830082552705990112742076614360383648416456541\ 2620740441101005039101955780389522613136336610613941329477210480185426325439358233001773297660\ 9163306882983187966915074460848060626898018842789705866023645418113336930855359551069826565004\ 0921102721631559172518354921016090739304963047991219849191894350293960817841734486950376870017\ 0076890631341409067384852676671730509374135458737119463320500805149470712740494774765551306005\ 7497065504745979610060646071615547125076512272991200851098787288526656035043802369734788537676\ 5999527227307243709948931238288328361709198802167306871854810710240003118830094819219292506636\ 5177957833829982816610132430867293318027373604707422789037821690540765963683896618187295645179\ 1465465910620464203666009275003558490179921077930931841015356629871206543956889840135639950613\ 7943153152975279122303869038568618475611119099638012260534125935003687543282958757834514274329\ 8029540976704570219566860682432822482158902375283592902784329782496305851046570054193792219427\ 9485151146259777609149738244956435012404750481510259192922058659329097228841369921119338248144\ 5144990924670230925806613274253511654078353750986815191334361655047686458006940103554742338844\ 2996477697587180518909174341201833718921101902191805699329999642546038418439738974037767934139\ 4743240993941394237299681520300292915929157415122041138714963094923702569798082717524956709263\ 7469162139345324717625587072860337921223986281051880784176277686207708498055728109949736823705\ 7245406404338640127150902630698793282752353626567738257348054787636152150919474556424556416085\ 9242324913557076550403003463354315260332742839134901122827265128935344664134760590658232898313\ 4749297924337839102130389030256770756058101552976916312109473278623132414203960858313527050774\ 8416019492226068732568542682794600052262279127731494596591717964985920066225626223198223796413\ 1784081307061487078712109666514043915684890820934517841584866232599220848561086080433302064635\ 2818636241118301134711714478472109195521641030791287959152500316191060632930686770715396136911\ 6145212472889552306439006284375931483070640164268382500190346782914018049417391064347247556582\ 9413442538635109096759187010332782147239059430531857250909638754562430988011098753736861604897\ 8472333444845034550062549828954661268433024332114249123455785180064689320176371932182264176035\ 8294482591531728830671400138343351662388507919381384945834162923650554738532233248236905717208\ 4371458846779017274596261199191657039553147558727987908937446203014783299434908856942547391898\ 2927501875542627249407163335088990877365710910999693654933279772003198350572004741962455931775\ 7171123129267098877971493113576729981547769942560816700917696252793245955639009321078227773329\ 7851130748491137795432271895769808348131521593099235911758726082604043978287828511366498366272\ 7946332260722583996941431178344"; let yss = "49986023021671159338234958176162840952750418022066456297978552959263821471149534290\ 1697813271825404512098259628101645631265382807342205907557504103916359976160073306946293880698\ 1662074805927546804336458708253892368556595356275551333432939856763403440056846017507376179154\ 6130070689002887720179755066181472399803996205313588880667402355892709408877039008165376155611\ 8833053299304919241773521395447464574914194618709827505030318572684286207139960048221916106759\ 7388136957593182004515327723852486922779902882315701756480152829849481353729417070316130463012\ 4915620377469778282378671900319212800220341585503454020200498048551225521991137349961355639059\ 9045683055121749029430429913783794621627008689181999482845317945110832673932889057461313419591\ 7366856121415704241159870644369868436539309674069236834052704360730458108482806016773495335956\ 4528677611065085068374102907023639986197979487152880688132523807643407387541681699574051916707\ 0856611470229956834194648266355010747625653820905927618097314765243765600873978740755411521339\ 2343489348696429854679396160063333561928973571320460657290371523206395514385969450772655908356\ 3946349652553436962781388799395105657256079392649940276869323151880453779456303906669618884418\ 4748213872919853121921649700464759290793856659707061350368861694158357035539960829806629938765\ 8524059543868212074822662384543242523137785846616894644999628024338373327335670240422427532490\ 4976957556832131150797694352637314063419871686706121808418852137774685433345853146152737466053\ 9027847096902811897278891837763549141081018305350099606428686972075414535727837623589103289889\ 2653033906922683170983111487034653245661901683224583717438274009780766663932952889867173872216\ 3528834042840064974161831805467075423358308345791666657282483731621589611702692621655620635132\ 4647383475600294778328782760149901051783697552634983886672165494284112212226996408909260092172\ 1209515365523076697613793195345034249576286829616236018833516540275239929095595320728790483468\ 5952567115663448293467918755035112907283582981180892655910365086569310851994903995611331244083\ 0759101920816860006762328287625653148732441277373752651290948147078399895543658282424602680512\ 4450319258670159177503948997092473091634337478435841649565395552198228515220026631361038515989\ 6008909655674643454636534859266174227862769005497970812712788786438416933181370095915134881593\ 7453823784993350480816235445230899481282835134853215069171296466903952486563572719247905311627\ 0496670286299027705582613627110949955544857867258854710759283897123655985161413141553463266669\ 5284086972851941120003596474309921298102521418698713818004812560079034519833169906858085634879\ 8492549066845639204143632742452049096507871475616729113428720350859433409227252203624555741060\ 3196352280527701042841089345637124435223914874828124802748560281881681799439537320633256056580\ 4156026787910778438508277249005521534630639301441732364023551715928961017459736841352186138801\ 1337148412994518373489133794679517322318365623247353057252452496661753255047570675115957301860\ 9112177772566247230223009000540616912993224490975694174266633020622987721635236329911120466456\ 5418407900957106349110150601850739989712518415082040797557572247929861269033908150734384968110\ 8932455850426214452112011729709324456960260108601691062738149082220832267730898589815279434890\ 8731367664671689830915200543507814253666591232649680025848675839428814036938186706298556028019\ 8340087240686784933163060071736151475110131245549108127116529261607596945172302196135332469182\ 2458607332485123957028751177656722291448808792368654264327261281014154853457778969261777340559\ 7820944059397018304265075538641167817892288619991267263371281902098303123446276145187692893714\ 9519477717893540354124457356479560755692246865603374437898985061206835197663878005596126352779\ 8973735718985742351606661813037929337194407431390752136954074249275422986339524417693143549802\ 0335270164598612214223957762794369560852351531305033791198149794138338640587678243218831296244\ 9252352565142214912078307808513477954279768798278928482294453975202584186089232485657574888185\ 6031763044216088151481252369367292673988611669575689475800498206137106305998068313746955957820\ 0898959943715624581680437628483422508930020239888595530624411360849877220442056634888338116460\ 5796781702339175060718767743806961654069186864640928091912320604237499435818315873883177549731\ 4438904608176247944489768409828794492539633534990683608905894741058481841707656906146599397796\ 6768259361077203430956669648441598210464782762231903192060859166679745206592863086434524406080\ 5061755086355357462714581875611743718074941956885489546796755461792504837987295794891172817287\ 0724068070496151658738717629278041508299657508683362051771745956810759194283451521508725826963\ 9728920379968574843966573614659163753591890794499691092061855684094434397565281152388322750830\ 2936562287627323018853086396258713256975769929020698380563560822565434548344902010781581961113\ 6846799702142004544498000369221380175772227843670470877051624358052371815798951337768390510076\ 9409832265531426982386129993248366541262908912775394898991260470179640239850971572873576639146\ 0766023953632563710626344216028593861078092260436139150339410472941227133577975903169047261355\ 1286160605974435750779172103351483297148795491707834283345653811958446520751210104929605906463\ 8185475917883307983337605285498406960425765658701147677389858761447063612138035885880248764418\ 0748709518703251644755843442465444670908671645745260888437535662991793184515770447143003193711\ 9812800905926079799287254740538420618385578908149484836090770265514044030253609447874025119272\ 3480780734335681961228953453625209470164376934899598331663140871406504756470067958176602840891\ 3436442573858116115859927570931711479720756600147839785260298044727713113502175161458254976961\ 5193984435343121159688571749401128857212741047738499804621155554862904838772869693286169394915\ 1312799926015215198733037480015574027711692265262920774454728864910483477543058234197233693982\ 9854575761867426951614210435618496028943715087175509224607105302432211645050050014916735867955\ 8103623297355427518046543928487982692762907797960498528428131138612102741202908788346397760320\ 2524143378401628287662841125571954135057948368738774757969643636714767963407417162659302685512\ 8078751656882349980792598629587459818756718355995492110337091777094448215056286946305420952348\ 7907976968085868385719164309501356100989128621029393183784698027409528502198678395311126499017\ 5184078585187462463126390818095767355613741195752813402056469274433803969542775165270549682738\ 2994221189144324375616529121968065193153698977889390489529063408255321227994387793667565786248\ 0808528776367839679631291070375207236929445733454058666648248477769134783729050011898234448139\ 8993349590845032746041683821367673923688025810664386525049996592462264181990263339376525654153\ 4688151621726091616535727805714892825811298471657355668420402131840889243871828391480349478084\ 1213765438943540133044085760161534161208789357410256539569977329485151326150253004654954138455\ 9528722792944814364403837930363539896602600983699004042866687632353453663526069531834494269643\ 6624147575765331407694382297848351919166320173044864770828732883439182068060588130882501033804\ 0426743547448560272270992151301010517288598482787736061847035042543408941070253189852377368236\ 5819285727707133621429682730553395262311383860592921007748108439490439695147542072175642494720\ 9186868357355874856321966099953420439063924992162849756038603496112175054259539095438866582976\ 6448034908908817431100755042166004224252366973363571941886452859732159244757259171690567663609\ 7820964546827311588907206586044315551261101653299643794653053921049546419022858313716515856016\ 9161352282239091485605774765418891283015609612161818811141756563412398965270446850439762930727\ 1265075579650826465228364126253295503805755667305256326858589301862775090627315862498749476466\ 5428979346350682598783408400338865960837778435472824084279088177330330924438375832485050622689\ 1845171136765480273513707659451547470995294048552664487099071040377185268342654442566810830732\ 4273513559219196205203596252617697591102969064233059094243908088488693919507934017774058038965\ 6263477430311466323204338900688790511716430260269131263610162536382141534419239598123834721535\ 7844592966593264252037726111804716954810757673132330127022598731762031385743976596172355813665\ 8480585852428547059110495615340614682950702555357034774448527842527146113799842996037197304714\ 7511095490017614974885494779593205520787632249896540560961973768456316308007702563131577489302\ 4561823195237759568667232432027224183051859663362951333169612156464887803455625542942599160437\ 5624552818074522769402266855047645311091525988788806372446915533919508544950989012353064267814\ 8722029063631900541826014930971405994493634820662854594679957921971967269769680442274246327486\ 9746371794640241061632031872872053100078737421077754432648654919104914170154435065760826466975\ 7169377910522567372804407001292614259638626753514507271966727696261573427794915793151679539763\ 4989425490891894541416149446530840365758986362872467856074888391102749796306735242750309946782\ 7579284241115079618442310878308488366619100287557690496233096974073161139330022873310171282850\ 4635571065857423603544509499047009712504115889494586205527905746183195858773353311783193070505\ 9428691781371137736515083221254304729786933875723962919401362205138045992360794107715696913012\ 2363634336555761019688771513854347236745591124597977931405047860990814058116324491611973808078\ 8746960293563921321195150193375644913386886152791398578015232715295689691142604068424501220707\ 7788613749364152338025022822664609020596184735818260271093787518347711368354620419591342960229\ 4934671771673075601901855504491624212792968594327756267651515758730103152919533027139889964288\ 6292506703401688639837384652257978255734467511755799544669144610945157888358221232087883623303\ 7336755369954272851540923633879586178859053839517598591994009903776871896539495808824221515299\ 9619928149403248241048135646994567076173140201129595245173866036775948723989175231691600687146\ 2371427211437232442634762429962042736305968547125977281297596069746748020754875733965108044186\ 3763137353813976688054206726402967783171906947227503091923172924009664820220071663450524990481\ 1945104599860297464777237922614956378065063679948653629951460111041261464500508663182414576795\ 4000719678894140937974409070550812074001499406734602910143851047307308360678796014677323567818\ 0450168089940330290360709389098366611796682858811124857036910846797801916334077428533361491667\ 5845136113084514958652880145099929905918630443588356653224719499124763809124211973358004517696\ 8706425654805403429023865013160069207660629615239426877230724212687859465529115217627878556897\ 1638150738123832518092554735755792320495355998230714470444854106602427967029384193253867491473\ 7437146125337596900140389709103055161683821547785426150170598626093352210883309022624155459005\ 7023874273453933333145549786552126218329698096093321915695210032747749195700141202903866023274\ 0376633417085953345929177515640194608571280489382840834700778870646340564131039840486762803387\ 8662602815513501875838289244070743971820590656831867856198960478033876196228477483069329209006\ 6776885868466994131646489834529037463487506421343322355100757225755441259884596858232828982843\ 4651649119628632304969902774966388158308632803045338660094941692386732432017110234780880092628\ 3649392078388188822343673570603295943980920810074101483329113978921981993197172306955792863870\ 0670904292434515529343533958764853200311790341334890613459290566779335199536065037960295448113\ 7925935086611484850281668515785944773203170743155592727715467609268423284205942098901179664537\ 3404417709386817738463277133698265088091414301653009565806991377858914014096157420849022539503\ 7005978994395410100409901622576780438723136932658434089792158053603100876816330760350084907612\ 8364007449447019604977244808931089296625313671915025405830000848017458187191803647966668368091\ 5375491728096552655673108940550343585304244886521802832130426211912860269555074832924115409645\ 385085658742611904956365491830224265423778799183469243527078852296914873108660775012984921"; big_test( Natural::from_str(xss).unwrap(), Natural::from_str(yss).unwrap(), ); // - k == 1 in sd_fft_trunc_internal // - k == 1 && otrunc > 1 in sd_fft_trunc_internal // - k == 1 in sd_ifft_no_trunc_internal // - in sd_ifft_base_9_1 // - j == 0 in sd_ifft_base_9_1 // - in sd_ifft_basecase_9_1 // - in sd_ifft_basecase_7_1 // - i < l in sd_ifft_basecase_7_1 // - in sd_ifft_basecase_7_0 // - i < l in sd_ifft_basecase_7_0 // - i < l in sd_ifft_basecase_9_1 // - i >= l in sd_ifft_basecase_9_1 let xss = "92178880216095181211666676829145138370840306649787951361975829268163297384165754808\ 4756063405654098801011060930436693280675742944960017098004214801917753316815018149158787859165\ 9395300322111008817206410403503222862298862158402706092516171953423073235157842305744193289276\ 0199823879480276467262088886778607308395525062932232880604136063041439063365460112144872325877\ 7811437625627573820240086261266117827231674835705510157352288567620759933922883923925467129485\ 0814639434022945267787254298597769652760997261721274518217329594058447021665620310437095357991\ 5175605696860846854327832301621757698220417241976755189345968350443138036702177163804669879333\ 1749587961567883818459754867867584245313746514165087972856312186120232022411062835757426550707\ 4622170384289216212403163481519739652983828591245806571451382580470001509986746550375107141829\ 5041192502748258698046492665731973650404141610257237221869777201853847126201629101101256979663\ 4215522985230416617064181229401998214577283162762452604574976316076929257476979465101831676820\ 1407487941066549241059843831269982406703297048975397272372445630568821339462845327127639496465\ 9576066224901105931725511863239462309019409925105346234004749589849409525460428465344371928686\ 0219899854178944512710338988282872909796497905006394284092127080626764661241393784661494717501\ 9664612685452361581265902721321729281560792834146225698198834679678903863930368756204253548447\ 6428237547963380775849781198163880820474234887408515810717626954294464140037086445325925419546\ 9226360044515838714915264740444059908780715895432857870662394025378890373067951136803185216007\ 3267164960283497260307420569343262172781570488027068806082866923981856952745381456929132034376\ 9175300241163200578334333305706617719059873705842235195056271069666326205208928369404251271893\ 3679946274464722744915581527296637624266349680128155611492841157104585722091143836374221805531\ 9983693380210475132545075682573465444552559118913610843383605974999247732100246151434575077175\ 2324345777747697049984956782474383557955569367286883667999795201706433344171377686149604990073\ 1167006658978867618711730400636322091203486501669277691054842914826267934941319910773704032237\ 6901035670205399259609811903617317317239598548068552258882943496440422231759832082385172579673\ 3331969546275022130006965080924395968485228901579436785320618998984653205155824603155427127186\ 9640843127394901649965498579948667455013615081255964805120103800401047094561889908057163200952\ 1485704879293795487658072678397606334516804146599466551451609053119103475485952130347173420542\ 5212275039559539681798308537856842558661070023438378480938524659311644882052743234093728450377\ 0904737018473044412897568594028401352439121564448346666005199157182859046003456230628252461646\ 2711568894086127552365778510467688968662691174905311846804723311446774142560531887766216309336\ 3547191766862995534545173810101282955215815803628507655257102184911633402387766068877259795064\ 0321509419156026324303710620592463147900840578444449323728803668303265138630374806617203187939\ 9906449865725064523851265717887390715157466783059933912068354503772214431979866290078579445355\ 8311261036030403472816783125699826576008508857219508442253238585849562016110478170452653797356\ 6212208509721134378400928511072078679723080003929731897593219180380830579686828918716120845148\ 6175127225958344843950193844481292801585339136308436578596447853517992043624639728347006509853\ 7645007548083913941726649541874597481305636803050913189875829007224207317847021339958173233400\ 1712685939213407698422779479008460565279512703710259903749612358081689590389622906948233869256\ 0012492063107507109701774650303553632653740676976306821294715531656243033116599516349942536341\ 1093295657027473445688838148738744167833015407259539432581571029579904480644793185529659263176\ 5214500159261834752730651400287945044066099866450175911882657673457747672971994979835331469088\ 6761756186808135204119248623596175993310510418285026467753122760968111744956741234929794049670\ 5347673696159738183626721683311243235707795942817994465680764248391615160785062871842558451083\ 1339698690300490733834377921936270367617110035127089791814903617335372758323457766221713419774\ 6472792448605921707551485285461428583031592169673278783263213185912619450164367624776936642465\ 6273519820033037165002205826158934743920822502599592958620667050196380246628072166942635791625\ 0922384490346589214339776581366735557200699008501068658383639384490006927079512613289497434799\ 7461417696179680119649742194484780658648709021116240165383841901768276933995680531932803451677\ 2447215854056207524129671519115954026224280023981715172583589454751572892059637735557709314675\ 9614367552876651272478352620179235530014789180213278962452283157832712698082010993439068008188\ 9918857932694844622179284416754675467795584192049455977283167136406717372964723938937208182768\ 5013915564058594855936357150037519065095240454959489333829960212039617372399785804850638592188\ 1185636078604139805634314419412614234307685798822297347406108521092686215255734286770089882515\ 7923825125232165876477739927411833999162006648812432004052451946583874661334023073014089427850\ 8270338200972791935823864684587008940485166174868624369837127938577060779240011871830292449034\ 9128796331002290445091235824592283208919864702368255151420802886504733241071514413608377719259\ 7198960031560678408230290799222850549952463000372910229453782197060823813481495920742856040949\ 7477679686839921356630705779326050698559706152469704731173114624819858779789982073668503103812\ 9116139263689468007613564657598234720953327366346996966571186943350899797174365121222246896863\ 7221351940925426761264036759509345626928829972437883257644837430451542927850371310080746857069\ 4800477439955286688087534532390434950304131990936170409201041302784336144783741045897124986181\ 7334541620866082164232368178079141456696355950280346752700365855026890326851869018925993980945\ 1190398024697946844904047475581875749782560261287746650868841791259036261039200278782135931030\ 0782131174092977580699020263995105441271759555505011693918241151765887128720623241116404293610\ 1923292627085870867393548182007796021866852695922195275342465144379196649770459440766917386302\ 6776005956027991392409937269932473435933713822539166656743979553036761912815753035316276329577\ 0874510146987681799168986373420735204084919646712157014201805783078949291062908206747304756492\ 7879397124771964413717240397812305084259508141255101875179348611567144285618735656540711900949\ 7029001937983346923401736988902323695457290889631609533075610484926462009936704929818182704705\ 8017655821021066290136112935595028217940069910677671936094814910441564321522026892491234918570\ 8564621687485001351047337465401912169742334534779661485341751949685743634811315985698254376754\ 3025790786443561684835833702412315988839780478980899429408336125534480930044846763776106091769\ 0514823143670562542683319031611585067129161098222491599546168502744910015925610633633425675706\ 1066993949981678958362797543858063359037543865440014070132996477175185936440787126529924315529\ 4943454294093710429576747545278679922236959930892657575870089340248831082862229067209622919093\ 4073445691747142356696308086296039653967907619641863124834095617354055141122506921883702374793\ 7109303134178596140013601097991116052670307286704679250315187855735837101339266761102834044362\ 9303093023778163671874243749720377212970476095974737364896496380605464028704558991946533842833\ 9675365260521430209441760297960803535730934864497055331435491989520478327770564128276045994846\ 9520777291062084817263598711916719643081904490517722416950189009691734051927166097118544194905\ 1393312546522471137952144538483991829403692987889358362777668013850475701384826297874021966349\ 2141368666127198930874118380051061562324568468459954404893756398602674524285726602451929789469\ 9607817327896692112984377078996768713609103857368623105625257549732775905043227777179586178886\ 2553846355994126446820221615432282713214522203090800626070215103384442011757697813596755235172\ 9170131915564003672213847841292872567985677685250510477430433638890916808364576735879602462105\ 8986988619059094347209036156373594367071492556747985018304845427381072727888644194216874474808\ 8002474539202324865830757812839432952248221832182632495937656020758736436065506614095216024687\ 3755468924199344491382168137938162666620026291859121756933375384637822543685095224097607130638\ 2256493867669553916340062843739469201199065709174989531891176805035467679915871057087966252767\ 3825307885682391581477145504978341477808964137229447268541761194949442317984843665891711271844\ 6045786396262528404655592311101367364533066524720336308550453506747417774194941731095499942885\ 5408255870806070478469005046854416474664785183942399923759946384881611490673104810076244599024\ 2954328861110032039173248286117862758787175389607707457077352698015602790544545883276477818583\ 8316975077058488887087959578842226393372459869627513326675195048780942841174563111767424798284\ 0072432721697650949712793829692100232539401570436241381870852007034950568517733580827434129761\ 2027193817931433171784653188732875786064634307330295753504279262531072437063447213799853453300\ 8670505926285718232498839256736996425605106569715727088357300687295961375438686109216505880093\ 9191846493588711974825465549087725749140853506509967866011545230350632829065800789139904175257\ 7607665730530077281835939808102166168493504330911328053282537057899630209099651294982555339798\ 6174280526767447718403961619678780253118784055508834839675969196623243660910509260597024743878\ 3399548982518117300470741917819568590000541917666596121452911108556361144138702974254970861988\ 0816278176086358329239799052105949841651706001615453133929056862168843497683744777278859388176\ 1300556882918954099021980521521939477824608074039639482408729761163255533162206943512971563858\ 2361653253510440392367424484901792810423457799195686065902526236770682045627023782714860114863\ 9656665262576788651234623753158992296294440902126267293241565329022130465342457341462436816012\ 6135489496594888610327802655738344162066708992458789307819397797541260600282181022670716361373\ 7959819721372150824083678527700638740242279188874524974239900377814862814934300663909597527852\ 5737463709791950249849471636896555808186577642133671133810924204537378310684134725318345372422\ 6914397584149954068197310260368660455315809614334287298973364483663549973369146776416268869236\ 6056564157942658083517747717265601444988852047794375949408923235515024269379015050989523380551\ 5083786505576022733067029969698976479152155690199875958796333312070749464883892084395256842444\ 8872109742397972063089113758997640245753247124989104603946453090879950000000000000000000000000\ 00000000000000000000"; let yss = "10908414505912971054286609488569140565924687687245433094058547648020905598778587205\ 8800917601340102783279566646405229412956270860607348480697253321586425043921831743478345047346\ 1620612167756704235757660325826576703080825391458174158824924439376273566916427171725586252750\ 1135740201145208707398808419246609478468381871915273365995060747114547363636609791355017672900\ 8201140785708890745884659007022718348185215707899394766286151497972902968283000616696870152162\ 6162746788372883461620816411110712443880711195642228057093182653022326335575815190841233133154\ 5901983170623957734740229277533918089178781604188333617309668081763114384234809933223105723238\ 2175980988120314742525716865267570025262654047389794738086985999544779709382195868988972881105\ 6010758553679552998640915723718648168439102943931156658884682882398526699741823504320497280006\ 2233172072338982693697909214335376944537728610357916775549830616691045001061464613851455530681\ 7308539191939806478658138509922120292951164960952328660597685734370646072651479086911688862304\ 8875301954852916676396233885137710320297960219852527443598828696170773054985131164421008908505\ 3863320417453851138667430234873894787171599955890314482164675353481585980639187279213966221796\ 5362854604657325895421198321632027418186827123198514863665841105714406474704034591180228164014\ 9642956321822921088252308223918014534841857789241869742606068706996171891615174190123403219662\ 4694777160422452994177062670048758669388437663096069386059959441677724612434597345905683766946\ 1055057117676803358353474491892699413028718796396868804108014150403709112074360823885178794866\ 0785781288305878033552932547631853463898395521590933426651792614798049763342694458280504145140\ 3665748723657073979003591739560756591025818772766505732418704785362503865781294271883673261323\ 8244310518890045378127654157707367854319493666203793894105229571079353714855333982629786090302\ 7837491606132504951123941719242813218185035978434220621999879772544538748463376634367636346508\ 1602702528148162734659676974892864958359681301046175079633314001005611690725163396287513515288\ 3913279769534748341225675859384140633636338791936452232302173386906100814004098359573142396051\ 2661247624312379688078919444292950874768630849279644346459184541173730046172095511638612531426\ 9097219216661743675715333301559833797427427400745112255170583174289673187024018839000100563387\ 0719703750355234035408650091288610610877203832740320899874680869756323084625747379551103669190\ 3505324008472502629432601921885954615996411873404669472296378620842382069900579982304023036153\ 8123648137367394386593544688596486540220469963815141357683091871241851080033949208733040110554\ 1247051934233870718046700620778161164989796368301384044131797998491403133195259242819167115518\ 5816517529457503351254593461559001785254210897236276080828714411364793978007086569379444315193\ 9377500275308573034484218489554587387541686908462623901390499232968430606711226431616434521316\ 0284053164954588847174493425863191549299393592782815842128911091193645749088411535603155371794\ 4129304261364706080036780428805260606767981809574091259695762789767948001862905416437261575234\ 3954265321713528294798414220654911320027000477838099979500193309165189979860417585807753068976\ 0281061990971476228263978656980855648031088030251672499225498688104513509977731408862969394218\ 6386276357582152634076041568118285410386441075195995867767651149290882464625916250443969492322\ 5628927486455555369152293014491362015298191531222392373609267504874575559889774034926000489817\ 7334526861246181296845240134439620809897213746151667196619762607144020565237882575905537158634\ 3056054908893766595565270533152466052621846730797010667794912760319148461367888763432494033935\ 5770908233084550614579340756425880254606922896741720944365354373570553150827983181717626088237\ 9679468449439034129602017212159637115118265619492837063365788805219766122886118308676712391088\ 2324009989002058473353246079357784966236956727583834236773508377892013589638618125956187698984\ 3218483425259650845473870067046846051070702708381555436098035065316030560047619978075283136359\ 1219954452355538322062830035691454022290392542169743502327894299079400545580507355600786959793\ 9624701048378670711329960655592220917609724764842751610959942400606275938014051504230616140018\ 8879857896133032555293577263952648116925997705012329620620478256895448504324988771177759067797\ 9685926970825616654420691303155998809303438108623562246344595620487486685244575306209274563310\ 7303293543641811601614726641573107460829422811372172890261193401813784507634222106872343021755\ 8127223627217096368595505709005031678375575598517602520348491607448326383707762981243032536559\ 3625470197795113179542059984449403386721653734312880344083479538140623113438676899891035543956\ 0664089922352971148605047798328160271308209156897724820444922468937965894673531797498394142966\ 5857758936934390567120174052381161197241040596063882603749888839987952737678329885160229153197\ 3627482762117122991618207578170408102438153153261452366598098158243494465335493266945931886503\ 7903632842945111926728497738954208614098685611308083801899501366844644166267205140021620509734\ 8119955316842219810323715020900743528885943317665844308800167109679826577826108793697366801259\ 9081950467644628725893320857214120101376808632600359292866050987057452844302263617517906040576\ 5674887917985848237034070626149611228942663426325618923801045134789861474439009174710508480712\ 9894947335611031852610712285062172997459722763304847889730406437698498538694439638506771442247\ 4013481175348438524054192463564520454684118442597736403817854257772505310904724584854983989424\ 6273392368489356350002740521466119702121244888833208570062627308059658535546618618071475020847\ 6538160445315044447183564159680838145314807302681804945432318617824529984672714412766283349082\ 8407764907677913142630759364135717912139478554699048433046548009120622646311513936889849742005\ 1938417026585665195612967816256378569952519374000705346481080979656465412008908001891724511486\ 7640475429657981337674015944960532535501275691386076519906518480574604299315242594098005752731\ 4610901359392893551453521631112599200679457441857234352392720829022312219594847781134060134022\ 5235887458839044674409526779369062271419980932798621256026580865555413161303206785178305013445\ 2107159169710346185816180019959032636468139243857857588840330896418995161477668537012309811973\ 8294955663531293331130842946474929058168065491370658446322353288277527314175541070198181380258\ 5627326641228849308615217633455100949833458755735234728716629977114313043320267519024787537552\ 8555367407369345421631652421147888603456834809450748094823338604001218330848719666149313133233\ 0445623926214710486202012606270751008405873956167696089035019409843543396007380423406687466711\ 5232957625014826761610980527654739998859355453107419625880750871523919862469169853312492661186\ 9156740625756599779007148665171341208602089316522574306147186910710107485456688199733465277268\ 3393843865910427446792056897036338271401645263300543021899378928692066622697555508071100595666\ 1062215349114300910067438992756623927928016286120836042817703179688342075786600949254291750343\ 4750708506791204286311694404039771923099598305448092718740229873101908407957959733461551894492\ 1579356861293670935808137300698040600029078991154342700019287757204762318287041884091377923485\ 9013869981431557475619089641076646856902263659910192569696542041864420136272478708376655545551\ 9694802937758276476716416124793122039529318497748797935926710835530513956653980932496720195731\ 7863287800670097466375178866915404746844093936887901349854870947952754083626896575654244798278\ 5547704673589024994641144633673598532770836586690680765954828440204432314708331719061335590092\ 5098305594752790298805162335119615401677163849881114073460850657617030727422896736632519036392\ 2396421114817113186996471689857069210863649088866902911367277105114485752092310382681885586395\ 0557321841363516785550317383323531005761838734758410902748665143631225356098342510730339116700\ 4597502421978797921420130259346353389184048227417312961873358648793515851822657953530446529010\ 1921359266179061947464407216576883723070344846453309743546494248461538434465836728331111890678\ 7484360607577953793591859647377034714660500658601875268665404207814136388746945006570499607305\ 3912343943109777726072396255467966538286469487763984952121160856740333021560313166067636040640\ 4068763872735011006347765984195289456857762332379863692759538215794872957829767381599380828854\ 8443921951661519963100664342118118921219279515021185683158420124115882452249863439341643403614\ 6843677143694611514956957708817871493504199114073996635054666124076303336350879973720797542833\ 1697896521973131000604974199398266640485651830616668487905027012056207944523621716307696523667\ 3597104482223882886396000021941104793645669267397640541092898382866348761241388125840939420329\ 6532973581791194802847453568931481369344088975705699191689777654605119514346049437056288513498\ 7155592258519997246357561935326410564448361888670687962434733967023291889623448244314471808428\ 0196297795384611407015967995341036410237700416482276236892954314658618411182119637254165850533\ 4834073094907220770590906009066257259843924005632996808671009557797497167816984186567799661537\ 9780444732450365222591119710142165851813076664677375451651931168621254677451224008508782113496\ 4657512249549200288871452406908900398381042331882093417629266387252953255550505590845527881944\ 3110570104904927958043433168286770189478960615851176655127496333090691158707959561438394682032\ 5160929459708430095164135070071862512042596426249742795916444624439930350748025991581576680533\ 0341203235303899496900614261068923708664991316508518279778113430335835816638507476873470089783\ 6406780902558393821806547923053076179756975407588471246852634330682522594299832621823244274276\ 2274716983155299679950862020920180917945648878066432712692620308077426320341626218768578222373\ 2490917291430934357043048072772336865408717182113482257697207277942785802382211345454198422846\ 1007845402204507486797907417524150799426920895214057215895835400250840948613772715502311132351\ 1934442519919659248801091067532724916094212111299747251719833940498490882506561273622516955130\ 1430592598460273648638553585105165838859847053014167740762963441840459950884493067041229592675\ 7653346192027629855391471262594734312745968333924246485847967214784158400263364747001747254132\ 0139438345777136098540487695554612468049173310114717790707949801028382729062408344786764000130\ 07974072283267003978025920705373933996414576872881250000000000000000000000000000000000000000"; big_test( Natural::from_str(xss).unwrap(), Natural::from_str(yss).unwrap(), ); // - k == 1 in sd_fft_no_trunc_internal // - in sd_fft_base_9_1 // - j == 0 in sd_fft_base_9_1 // - in sd_fft_basecase_9_1 // - i < l in sd_fft_basecase_9_1 // - i >= l in sd_fft_basecase_9_1 // - in sd_fft_basecase_7_1 // - i < l in sd_fft_basecase_7_1 // - i >= l in sd_fft_basecase_7_1 // - in sd_fft_basecase_7_0 // - i < l in sd_fft_basecase_7_0 // - i >= l in sd_fft_basecase_7_0 let xss = "24801620217142871826036343153479407090126215259762287367249892345144118932702489936\ 5363795589499546396403673519051026819105518787067224323769279116349709420907345437632156864434\ 1719712090266415333143863606208648709524053891659568275087027717316930121389635764688470706597\ 5260238307434514511330927574432874399626586191130779511802671364838622423411286055789129948098\ 1178265409083662423394531391028173462050869303104169627336623271406627770919091188225928618106\ 4713114322277663317786276493528845775041485729411472335540726817499202367094531882398266179399\ 4396123199097972358415306093494701595919658308909864070872958276339824332368025541875747517955\ 0899020335121913751781769393281419548313186141224281866222012670740306330841714185544970277499\ 7949646249056294601039141509289643343708985818923998032269079309261400551966043601217975239719\ 6408889320846199985860655489911830005831615385224440166840984579520679211193021083123485314369\ 5654066547783370223020878934081204581414986655885449097842755766133888136018219565557242540726\ 5149373712403684852662663716434216575760780363589455906851052886649070163670814395905012848524\ 4242446267154335678308664419312848891987762791830981878424250015822257117004102272186632736917\ 9119679587348750698230120795953015381310613636951425019385198418188130147785129853747860449234\ 3111593352621318851953556826045146645506734114753703218105594390418926678577158352422807088775\ 2294185104092084009892063231523664183304785969283813134062463766512484317120364377393743390461\ 7422318544650418272783852547540328086475483046207595884076650062484568680142887118125740802001\ 1814422290022771494661379479722402142512462424259935181298667972646258965369426797145671601257\ 3456521213190961189225857134212433306204489198779714698241234900344161098963055902202240618376\ 9859668829973054610485982170521059702403944522913905969195277084459959400945830814455349634822\ 9514379583336225546808973914755774851896024752453243312275750967605016793833577168949111969922\ 1907556733307217551726415777621331521130598612920650632078403806727568767037952526679260811030\ 3751944137922537483270468977224977663485606368449211798925361810577737747375779407305305797428\ 2798253152332705802507373425809672687526986389941353946219403222120876199384802007872586787954\ 3697311325196500009654804240131348410347962800948264924279749965697761666401503469206406970743\ 8428366818045726327737929159783769117170914719089362105850626389743263054399450295811591554080\ 7866704302075305818706148358975826976113852522594096030427305055000951804161946861461022304989\ 2419920771607345334113662668454683137585429733510875327902484229103740799048128043423506760030\ 2963281620016317883915659767991397362369018982599615304051419212606802922909786900535895747331\ 5850274174048535453057467436067472601602376470305447160532146404859814335250724164139148444374\ 6273711713481819274612781628279689923981360515542013840617865093890122773088283535124247431995\ 6278074512061077876204760704155585044660127457477584271708662019950243758769785861925054225390\ 3414228018582814161813904023987793337002492901628562277946366602498318204677429605568916355194\ 9922124903907265853520495365260260616644641378401667408962281710099264689674030943933048440007\ 9774804881510104193426113210360088414879358106752293165686220032973225342542719050078434180185\ 2876767154128684802221973838015033946039851470380862592934296543873926498565961575661536309661\ 8485617719450532875384580304901130164237074848423225970067408533947704611471300380290324886160\ 1420615374930656205328913687104424509502847298886945958892993595437295580461677094798620912683\ 5959686935295316360139914618858258964686796340164171229162409225936142589627081116905572179317\ 8987080640050856431852999281897326723181251400563560560719771158181122142749359267857628353127\ 2196475905839201276924105027608964192651513010566218469744909171849066603999656785804745205505\ 1533559630336373496852631024536451792161172485586823390786287789598561652394134561137700882814\ 4994958269714667017225870865420984668478510922459011353495855686566713219487882014673374524750\ 6235449276055414278628998329186247791138201201786653714825490430774041309330234612266548796570\ 1558891582121302852462763559806987239277805004952044818099594071200253555384139052201037968268\ 0609396058166355507215613145892733846964827406809673844645141552760397635623841703098607202245\ 9628950185193994563125602014923027324506137588055673291810163281685018307705677977440755847878\ 5916277604830640254277898054605868201480668282810669100843355030953924632782394406885199531302\ 9343850555141955613317143511145358709825213063147220964913196258670378761061675258475965304642\ 4192069588637880395926581575815697288541128198691089251603619035327243368691695264021892295986\ 5889780966484746478395779290871875154688400185519128100216558450122245181891309207793010508303\ 6416857414355256318673035757621581622270794416594254177960159813429502907716713481236081448433\ 5167183445843846781174087267465133510937494388536466915186437288464113268982714919312370144418\ 5478118813752301023415966772621669096071573453729479198778763149124753526673825318149686437086\ 6430721201377401591984353850172840752574345765648391553975200336875117065968969717110090662659\ 0799325923454101045113718139506724517777981054216414936798353994664901640816953202708983427805\ 7913481961715995518115460075505375435320367594989130696360686409592902662627062564233683144235\ 3306352299952553611761999078760977422528843600754441682703049692885047251010003815883800160366\ 5280641527944325699017622403517549590923183930533283278529086207291192425364579604314935588585\ 1693519596840077770781952778109101537766725608978732632299214969888918463879848802761171950265\ 2398813285115692323045579373085393415838292883198244036459469673824726479066609543567049594886\ 2935208113075265099882566482211744719826130334433041673694056499364820677631886831328118016218\ 2611205570546607670772197454938016083495983113422792221646066252988843272419764722174051225648\ 1507195634970844024198117675858775719352197272161411525807766192873933283667941194109812233923\ 4334263398373019117809710855445579706185608943172670305216268869651041992025999116220318287536\ 0423688260665409896126529997567152348551532346969279305939977406229419529446540470805374053761\ 9744921601874214230978961900286172051665806923356388029991929410183503405737171343250092109344\ 1018200066087752813802222361379807317429558062818368473686275437801009254140036872958848355740\ 2158023808166868059068643274484472339252480597717238171933729169413630278779545692332602615882\ 5324816019394496988274403337442788641965946488732848302646563463683015530959148266655802504723\ 4677998225420757728274262679001829294681204262349568644240806135129346668538289966443734777148\ 7211742754145623950843032634798050811942614376805226907932826219830363978816270284226953255503\ 5132192956546677916303937883010930501219830342114926410501187312657755659868108929184945899160\ 8862905381082072422327449678693945378837416796328928892017232982368760300152911970187567088488\ 8097947167659620858700222018612285946652891622226294886056360184451943518037946918114820724400\ 0429198311126509366214329687970631381794063097888578616881955118004758106571366185986414256977\ 1545560189127902188261632692703550990312712272839510166399109501916003979918101116071382820165\ 3446973089768128042015712151763822886214185958989147339539935866157045125209972350947292199651\ 4259742057342693534491154260236292285417640325594116041571041564942102248647573573647884547511\ 7927255769718870091118053075433084403832946528725884272467905657778487139561464352416470291030\ 2427158826406118478410699528201546213130172513604601018165691033855911428137879851841789833619\ 9779931779172451229767533782653146679926707039058446897926139634612541382291024451194484049102\ 0348913898927032847202815428368696072513337467195829811548665133822009164641881251586467067224\ 0964321378840420780217477999530460642523083012164077627539763204174768242867227854830328954921\ 7981666810065286274945627556154803188195753990286753666419846739125189127009813177667668239807\ 9424575676331594419861212128780125361574019822615548084169716668189221832110353012860158916947\ 5827510211193336763368742226324664581013245906834314840457381465961932539437863097237795753280\ 1661941586455185014947171137236101248267786335931819609193050437761716093483101514718237405202\ 7479497435087476658239039539063751145149561944449333360970515488978120316059885587826030336866\ 2188730335673068409747996575099733869985243532001758864333332530346177681011603409119293655822\ 8893886929078673772413715762007967874898132314483333034476602521803484968813572856526496682146\ 8221586472111562832599731582793942461939560928095638102889425554429230004204077753546874138138\ 0764442380412951852178947461992146606850486405096319219459727741079990440468721505715754388667\ 4118133454983515240334943784479894247614641095638315034977297914742463950610247253497752692007\ 6730479586638718683611576252110583793610787347736095598359562861436880697949555023614431860514\ 8357314779405315475401981574515799145365987236477149342960167141069596759769629211766877333385\ 5407163672399332224852034723283298474204385218239662868225611612294312993851280320940883558539\ 8580005571505321113524087260373784519780495864927629034321722748179924380062999280878882162735\ 5283051076015877174230202216012277715275992738776540554935875809789509568896060386462295143434\ 7877590551286685086675498692452942892144752175759451106662646977672876231646732973482354621948\ 9277585817243118533225841329319406216059150820257932243760688523140709174083272705506157402668\ 5992682298721836236657489955597525585488444164365276000738884409745287210528931447311897748916\ 7450593470801502928938576387339485766248306067294156419272751014756065662304678931390271952620\ 3959013850455520419402155064233049792369143875043797623932686120817778457456585514982451826028\ 8789435115686272407357789290361785396395536198452116277773665642963680357095740509614359557039\ 7441832856177332383313605277250112357787228532743058978808882704171148969993469338822310750511\ 4942868847881585122066906914895879995389295937345589112036978208548496367330729758507212990828\ 1228030926825131401274879075771071263284119766835855851658228338891772217626087589429251134492\ 3500024228635210964941925743185476880268833789086585218226987988338155646982943209964788887840\ 5553096865337058954646790774765686373985677941724432335210764876153282287234984853472126533922\ 9473068686802760890054601903725571898116268020979065140463821048274659873386718101013530934541\ 3647545154140939552075151573395533545400331296578991110975407867994610126346288535292425511495\ 1624551904972797209552795049463608181258840004171045569338881308597788465681460245499949456384\ 4120872114017229564841935889576120783825467303833769104609799824778138395312378928231281528261\ 6078794045498349679661993581597613566357329368786386219239869784113833079447627832849056597725\ 3995215643904955403203380583558657416160722240993588532547592610142221646539649478263522350000\ 1952880080691371341336716288449425960123314946510423908943585507358338677082153457709236158457\ 2551978452710466699582086341653802603727429433993853707467652045144374492838724249066303540055\ 000000000000000000000000"; let yss = "12589013916460106277897858542056322488000094675856038864646344558907306049281511809\ 3614136473331758487033647545863565888296791844990366713538746685954428656201293778129225358841\ 7353863078097156371331389396993279517446187182494637469283466377460580501065673665435598840206\ 7142251990868317617561579410148930145591214360541256125925993641360336618423521594488521058481\ 1109899988306120162541408553945745351720597119378160518192449498440188780985585537647431021968\ 8110671180958675457849815485891061836525309239860886863961315717167721978071934857201612867766\ 8543767461173340378350887499166155076683685125902584892511373819988521816900192183182339280275\ 1482744980662742669748521682570253532711665349160344575879370522782059930077176386245541198579\ 3798400317650318004189313061972576676273465035043255600045494116932709242182501732769680538148\ 5099556686399958248166710269752554388376742485921374544193100340790114044640017730004677743890\ 1641647335308537912257025798264834155552412583943243046337517914751639422517260488407611185645\ 1730619934401959425302421172362775105944233136904439633848435635846777646375790028619032927471\ 2019801480514034142177189099392380741088500843010959280891017888481869335028508904437940756241\ 4546481877549870422936979705567193763651239836671431992799139430207382743790568467181259455857\ 2537982542196470615094253109736505511904177145527402473142627553430867471258204334734353007474\ 9340133594144542561926521439528835243422125771887951940513126216237839752399914304915379096334\ 3522265892037530846209019108970923475160288516251073580364734709155418377580354465277601146816\ 8618137357816163963169988675501838350458426103138395279925524535977657129263446890650409261593\ 9812895789722633350234460877451524069695112720707390486618079038153928199167931340042669103554\ 5105445688058063298659688780458262753196362871200273574519795726160816757036237710528906867457\ 4770079751625132809375536926770169830292897920513074075512111334200651273622499815832497410060\ 0190008935269325977350196281860238594923514357147602539474824350893668720099396394956973569888\ 3853743567236663702416144891850857854103839114308314238346701530127080675807942825452815860343\ 1453248670268604803082205448053749443877556826778448038157598886077430045570366045778733481240\ 5559761415354934815192157872590816386301017469878076709132405304502202976996810053062214111761\ 3683293987653845361693494701211475476889236212653277406394381060320481527005517041197308837677\ 2964509726843699281857743271686770247486726899265947978969459705007844330001093453089819744305\ 3372168474590060759203310510900315004763325776477399635804696939396802899102399443178760977495\ 5269021478676321306641542242490081984902627007643733459356437362648529356870268953499568851827\ 8993191062323659633666618340618744418228923927761649436448495338509381124461427047169334715974\ 4201578033359942262570823049846229161990018993165697683021812397482322435520314552211860320783\ 2855492916989369856974670766814204739558583408511834353874162893083530139959882033001480193034\ 7685795651651810705239982604805321646908529202721583394569320280801137417613565370089661646081\ 6228739874453998238272728212666348202358362664051060557411110264246742561904274054537861377304\ 9576198698426550098960364240338901002104466221634474935116308314280105844241072526575579864349\ 4425540270319371619718024964051418605541961453788836812214934860525645226168635875017599100567\ 8411370147729668061827209213548126409459764273182851594452853417872307326229393337098897968136\ 5377063330667435895234325001344831298676808194669482523446052933258820409219447130674392163326\ 2082975934686253351694363235158923019419140012831771442092833791515988608113442990374486413959\ 7300411124089411534022656455717079496022901023145121791504586285756480438733819992612620266044\ 4508928253870513173628509025625479831245902190565253903837333992139262402927244896189927511304\ 6015355971134307127532745646911229172799497031118695438155116685869392486459174954625467216829\ 6139914776531061459245432019683916310131096402322825617216858819953487413642252808664007370113\ 5130097927839211213703618643600921442853592282519207838345872683150366457709248888709812305872\ 0029961121795751169708850803536613732415754586541158724977017852055722636519561544321864924737\ 5729555942502259129241300117325778441223140558408708588127871216478851667867027641810903022393\ 5026279552540069634984608661141902490594861040385134045301870985868381762867745315703165705848\ 8741539079298928101255947801722324349147240427796708732299443729960956696665969019743856226784\ 1158106555297521401973061713721294415390319416824497089718721319260930153497019211032189753833\ 3524757752041208539454524254191530204587978267794107277313119835122104408780507106860855053432\ 6715989201509918081324709356266150887454766869419534319269582933416447397362562523951965586576\ 4831584826593399486108570617002771071336494297564163153529531520685660419677199438433441044737\ 2847443382173195912174417438075173315823025629475165381478134649511343243037904838787690053816\ 1448304859110512660315869110216207500306748016638564074983211432091239558029436864970311201013\ 9494204663451931447003852648629167327901026967817174517123762233469206554169502522631768779019\ 6574760572729599494752710165846986105206751360431814385187378977204437044390896146215317658828\ 5934603009271073563597032886566322116787071789139727488326970091444490126827295067012933821962\ 1554754332569543237304472483359184936142988429812850308417562272727104297326786153398324275574\ 5155518426198816509252895265227065999950375286440313834470432544665229750181021510109369574752\ 3356743532958194280997267115053157799138739193732065092158146615765660215610507254884871133791\ 1698218461062736695547742573390984523443030770645318395967518545333476901051694382928011857621\ 4861580709678692048640464956124881032637709917322830810929926863905737922495824338348617134831\ 6314749492263784807017615497731340611368142443865631703125557977215256653947164477889267069355\ 0721207438162105024465587381551162027875192714674519224641045938831803031008877074458359164697\ 7769244276944282245715425148104107693701637684140087117033308856452097048733781522061306259197\ 6709836700234923180916761040773082826569884302957513147799259219185565324882675590765307866712\ 6015769131049789691940099626992191545891474462776846187883153534302839641384655701574144237436\ 7769077386181999313015029561230765611767744161714772985591890471981679710399252311545198227971\ 1663782961179770785790224606401624161861715111784750295368007295732593525566603789022076628804\ 8527661256713043958604316033970981497744866983597919553507025043650842329592485811439638375310\ 0609906019629269586733970151806216941155151610224001113041582772445794841512626172140741919316\ 8802979545222635406623764116165125367944926276816354414368612714584815365795736574803755307099\ 6452056234794680246031135120551613425648163024369763768999062128512834773075976966796909186811\ 6780561202941750407809414299089100142690218458444776551938846499876353427650825949459549435343\ 3932692400561339061059747834789286348238882330400198769344338775274912804452941503441465759007\ 4602799801217437772641049936726626347294647100583535416780422440084362064239940902266909492293\ 4405688983447180996873076613708418605659134527663969190831327685081461214556778853732555576823\ 4990338599017039376114987542929273098206308364715535827638305721948012233312271810174647085529\ 2277684236204894820725532708344438205860758888068636734833382932466235420832510604744873850096\ 9282611370707354542652016812425185882217727416968621933780020111039992008016696671959153814041\ 4316674523809170176165664411006219334346748795389918179082831172957466870498039550283432266454\ 9529543420692277213789018843024164290569450635030907914447146188443173383043062919961045271561\ 7929668549172376815356944264330717421180960969485664114635780047634627977048629938156558500603\ 3921592421689134629228739721072796713746140401486141278138384689894423080154113785779029068807\ 1330308362597265783414518880121147171683550973428807789715720035181817986760006812853184805566\ 3785340220057799903883713709429081894094007883906813541431379032059433956095001119523041099601\ 6839788703071835426735250764828966760377489390861353034238509692213776825289155748118892852493\ 5637171565811661303195202467420591310963472679145339785689609953794186286443227923216652631277\ 3788447542393494415437088181226420410106957407522481752168712138008194374277529483239799590139\ 9298990645494535426228995661442278904865179613379566733737728911421044644137297947182107348820\ 2525787819027913151256735340221837708712039570106141436639126142561390083199792785805374415495\ 1022755644811179056160950054045817133229585793735694826907423502685382504565944253095448659814\ 4808274930441626005413799153931517381712891019978042126613521037556183391817965550385735061177\ 9163449653877143552562190397607785113032971003564036121765482082842404669534010182444712706294\ 3141958700831346145451221092417417138575079645510457430481608322647953559194816721831783859721\ 4151621676205166904770089938502438614169265103111833294017362898396088188896132098887610683480\ 2898322845387201832250138459093671963069739618350027540454891198833790835932411903674111449254\ 2419439905077199123214719032891959817826230728737015620259791224209531828279826710851775647355\ 1285617312949168800369774113761607720006799553427389688984990286591434956700614820259704779412\ 0872401006900523223325454594460509510390907494592159646406340918870929843130647412621697397004\ 1798552049735509610309462063444838111088940175802141790427562995223848783965027874749159346332\ 6990640333039827022607006580373414160850100543843323448046531039447253576046043436630175355397\ 3299289722260075024807344047612826849175942636796884646906477088720839757937044126660733071672\ 6925103862410468103254723758901355044069368732319544861647206735503116923764564332268824973377\ 2525266171983647738196072458532465538970240268893897579295277262629385586566443454845338874096\ 1351003127840180356377574155035064592797909407262204358484869515362222205335327978022954209337\ 5173159447777345124762301117968347303285073220801082812082941668952725507872054852067060598323\ 8633045336762278736339343240446216041436312543472033782088489115934263312317441758715321621398\ 2893694194507118735687348357481382982660963131067599585703851061893564997542800492382150704628\ 8481176839747118963671849143035732883999547117376084206648565334776978440262738559060670092448\ 0786099302872817568083523212549328513305277274217424197340898405157721222283929814492126885251\ 1412961325059061297265782609785280838720240520453470040992326233839897606285487471747003140410\ 0057877074406960533508202301549079492579415741980786293828443271085764094023220276789143263683\ 5287092293953276312654493149679934771905531087755559871059281077739977789296394659915457026295\ 6908735121264889427252659177584494256490080250572666745152641320167197309221519742810756902908\ 9298173985278772765903268833981114666803657906117584700148956974562696779322051091961792870409\ 1017421869683431439216634457883170152430698818565631810772094980586613656344000000000000000000\ 000"; big_test( Natural::from_str(xss).unwrap(), Natural::from_str(yss).unwrap(), ); // (large test case starting with 1093184750055110... generated by setting LARGE_LIMIT = 1000000 // and running Integer pow properties) // // - k > 4 in sd_fft_no_trunc_block // - a < l2 in sd_fft_no_trunc_block // - a >= l2 in sd_fft_no_trunc_block // - b < l1 in sd_fft_no_trunc_block // - b >= l1 in sd_fft_no_trunc_block // This used to cause a stack overflow big_test( Natural::power_of_2(1073741820) * Natural::from(6u32), Natural::power_of_2(1073741824), ); } #[test] fn test_multiplying_large_powers_of_2() { for i in 0..400_000 { let p = Natural::power_of_2(i); let p = &p * &p; assert!(p.is_valid()); assert_eq!(p.checked_log_base_2(), Some(i << 1)); } } #[test] fn limbs_product_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); config.insert("mean_stripe_n", 16); unsigned_vec_gen_var_6().test_properties_with_config(&config, |mut xs| { let xs_old = xs.clone(); let mut out = Vec::new(); let (out_len, new_out) = limbs_product(&mut out, &mut xs); out = new_out.unwrap(); out.truncate(out_len); let xs = xs_old; let mut out_alt = vec![0; xs.len()]; let out_len = limbs_product_naive(&mut out_alt, &xs); out_alt.truncate(out_len); assert_eq!( Natural::from_owned_limbs_asc(out), Natural::from_owned_limbs_asc(out_alt) ); }); } #[test] fn mul_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 2048); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); natural_pair_gen().test_properties_with_config(&config, |(x, y)| { let product_val_val = x.clone() * y.clone(); let product_val_ref = x.clone() * &y; let product_ref_val = &x * y.clone(); let product = &x * &y; assert!(product_val_val.is_valid()); assert!(product_val_ref.is_valid()); assert!(product_ref_val.is_valid()); assert!(product.is_valid()); assert_eq!(product_val_val, product); assert_eq!(product_val_ref, product); assert_eq!(product_ref_val, product); let mut mut_x = x.clone(); mut_x *= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x *= &y; assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let product_slow = mul_slow_fft(&x, &y); assert!(product_slow.is_valid()); assert_eq!(product_slow, product); assert_eq!( Natural::from(&(BigUint::from(&x) * BigUint::from(&y))), product ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) * rug::Integer::from(&y))), product ); assert_eq!(&y * &x, product); if x != 0 { let (q, r) = (&product).div_mod(&x); assert_eq!(q, y); assert_eq!(r, 0); } if y != 0 { let (q, r) = (&product).div_mod(&y); assert_eq!(q, x); assert_eq!(r, 0); } if x != 0 && y != 0 { assert!(product >= x); assert!(product >= y); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( Natural::from(DoubleLimb::from(x) * DoubleLimb::from(y)), Natural::from(x) * Natural::from(y) ); }); natural_gen().test_properties(|ref x| { assert_eq!(x * Natural::ZERO, 0); assert_eq!(Natural::ZERO * x, 0); assert_eq!(x * Natural::ONE, *x); assert_eq!(Natural::ONE * x, *x); assert_eq!(x * x, x.square()); }); natural_triple_gen().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x * y) * z, x * (y * z)); assert_eq!(x * (y + z), x * y + x * z); assert_eq!((x + y) * z, x * z + y * z); }); } #[test] fn product_properties() { natural_vec_gen().test_properties(|xs| { let product = Natural::product(xs.iter().cloned()); assert!(product.is_valid()); let product_alt = Natural::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = natural_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }); natural_gen().test_properties(|x| { assert_eq!(Natural::product(once(&x)), x); assert_eq!(Natural::product(once(x.clone())), x); }); natural_pair_gen().test_properties(|(x, y)| { let product = &x * &y; assert_eq!(Natural::product([&x, &y].into_iter()), product); assert_eq!(Natural::product([x, y].into_iter()), product); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::arithmetic::neg::neg_num; use num::BigUint; use rug; use std::str::FromStr; #[test] fn test_neg() { let test = |s, out| { let u = Natural::from_str(s).unwrap(); let neg = -u.clone(); assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); let neg = -&u; assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); assert_eq!((-rug::Integer::from_str(s).unwrap()).to_string(), out); assert_eq!(neg_num(BigUint::from_str(s).unwrap()).to_string(), out); }; test("0", "0"); test("123", "-123"); test("1000000000000", "-1000000000000"); test("2147483648", "-2147483648"); } #[test] fn neg_properties() { natural_gen().test_properties(|x| { let neg = -x.clone(); assert!(neg.is_valid()); let neg_alt = -&x; assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); assert_eq!(Integer::from(&(-rug::Integer::from(&x))), neg); assert_eq!(Integer::from(&neg_num(BigUint::from(&x))), neg); assert_eq!(-Integer::from(&x), neg); assert_eq!(neg == x, x == 0); assert_eq!(-neg, x); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase2, IsPowerOf2, NextPowerOf2, NextPowerOf2Assign, PowerOf2, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen, unsigned_vec_gen_var_1}; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::next_power_of_2::{ limbs_next_power_of_2, limbs_slice_next_power_of_2_in_place, limbs_vec_next_power_of_2_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_next_power_of_2_and_limbs_vec_next_power_of_2_in_place() { let test = |xs: &[Limb], out: &[Limb]| { assert_eq!(limbs_next_power_of_2(xs), out); let mut xs = xs.to_vec(); limbs_vec_next_power_of_2_in_place(&mut xs); assert_eq!(xs, out); }; test(&[3], &[4]); test(&[6, 7], &[0, 8]); test(&[100, 101, 102], &[0, 0, 128]); test(&[123, 456], &[0, 512]); test(&[123, 456, u32::MAX], &[0, 0, 0, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_next_power_of_2_fail() { limbs_next_power_of_2(&[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_next_power_of_2_in_place_fail() { limbs_slice_next_power_of_2_in_place(&mut []); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_next_power_of_2_in_place_fail() { limbs_vec_next_power_of_2_in_place(&mut Vec::new()); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_next_power_of_2_in_place() { let test = |xs: &[Limb], carry: bool, out: &[Limb]| { let mut xs = xs.to_vec(); assert_eq!(limbs_slice_next_power_of_2_in_place(&mut xs), carry); assert_eq!(xs, out); }; test(&[3], false, &[4]); test(&[6, 7], false, &[0, 8]); test(&[100, 101, 102], false, &[0, 0, 128]); test(&[123, 456], false, &[0, 512]); test(&[123, 456, u32::MAX], true, &[0, 0, 0]); } #[test] fn test_next_power_of_2() { let test = |s, out| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); n.next_power_of_2_assign(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().next_power_of_2(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).next_power_of_2(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = rug::Integer::from_str(s).unwrap().next_power_of_two(); assert_eq!(n.to_string(), out); }; test("0", "1"); test("1", "1"); test("2", "2"); test("3", "4"); test("4", "4"); test("5", "8"); test("6", "8"); test("7", "8"); test("8", "8"); test("9", "16"); test("10", "16"); test("123", "128"); test("1000", "1024"); test("1000000", "1048576"); test("1000000000", "1073741824"); test("1000000000000", "1099511627776"); test("1073741823", "1073741824"); test("1073741824", "1073741824"); test("1073741825", "2147483648"); test("2147483647", "2147483648"); test("2147483648", "2147483648"); test("2147483649", "4294967296"); test("21344980687", "34359738368"); } #[test] fn limbs_next_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { assert_eq!( Natural::from_owned_limbs_asc(limbs_next_power_of_2(&xs)), Natural::from_owned_limbs_asc(xs).next_power_of_2(), ); }); } #[test] fn limbs_slice_next_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); let carry = limbs_slice_next_power_of_2_in_place(&mut xs); let n = Natural::from_owned_limbs_asc(old_xs).next_power_of_2(); let mut expected_xs = n.into_limbs_asc(); assert_eq!(carry, expected_xs.len() == xs.len() + 1); expected_xs.resize(xs.len(), 0); assert_eq!(xs, expected_xs); }); } #[test] fn limbs_vec_next_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |mut xs| { let old_xs = xs.clone(); limbs_vec_next_power_of_2_in_place(&mut xs); let n = Natural::from_owned_limbs_asc(old_xs).next_power_of_2(); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }); } #[test] fn mod_power_of_2_add_properties() { natural_gen().test_properties(|n| { let mut mut_n = n.clone(); mut_n.next_power_of_2_assign(); assert!(mut_n.is_valid()); let result = mut_n; let result_alt = (&n).next_power_of_2(); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = n.clone().next_power_of_2(); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = Natural::exact_from(&rug::Integer::from(&n).next_power_of_two()); assert_eq!(result_alt, result); assert!(result.is_power_of_2()); assert!(result >= n); if n != 0 { assert!(&result >> 1 < n); assert_eq!(Natural::power_of_2(n.ceiling_log_base_2()), result); } }); unsigned_gen::().test_properties(|u| { if let Some(power) = u.checked_next_power_of_two() { assert_eq!(Natural::from(u).next_power_of_2(), u.next_power_of_2()); assert_eq!(power, Natural::from(u).next_power_of_2()); } }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/parity.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivisibleBy, DivisibleByPowerOf2, Parity}; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::test_util::generators::unsigned_gen; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use std::str::FromStr; #[test] fn test_even() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().even(), out); }; test("0", true); test("1", false); test("2", true); test("3", false); test("123", false); test("1000000000000", true); test("1000000000001", false); } #[test] fn test_odd() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().odd(), out); }; test("0", false); test("1", true); test("2", false); test("3", true); test("123", true); test("1000000000000", false); test("1000000000001", true); } #[test] fn even_properties() { natural_gen().test_properties(|x| { let even = x.even(); assert_eq!((&x).divisible_by(Natural::TWO), even); assert_eq!((&x).divisible_by_power_of_2(1), even); assert_eq!(!x.odd(), even); assert_eq!((x + Natural::ONE).odd(), even); }); unsigned_gen::().test_properties(|u| { assert_eq!(u.even(), Natural::from(u).even()); }); } #[test] fn odd_properties() { natural_gen().test_properties(|x| { let odd = x.odd(); assert_eq!(!(&x).divisible_by(Natural::TWO), odd); assert_eq!(!(&x).divisible_by_power_of_2(1), odd); assert_eq!(!x.even(), odd); assert_eq!((x + Natural::ONE).even(), odd); }); unsigned_gen::().test_properties(|u| { assert_eq!(u.odd(), Natural::from(u).odd()); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase, CheckedRoot, Pow, PowAssign, PowerOf2, Square, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_pair_gen_var_29, unsigned_vec_unsigned_pair_gen_var_31, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::pow::limbs_pow; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_unsigned_triple_gen_var_1, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_triple_gen_var_5, }; use malachite_nz::test_util::natural::arithmetic::pow::{ natural_pow_naive, natural_pow_simple_binary, }; use num::BigUint; use num::traits::Pow as NumPow; use rug::ops::Pow as RugPow; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_pow() { let test = |xs: &[Limb], exp: u64, out: &[Limb]| { assert_eq!(limbs_pow(xs, exp), out); }; test(&[2], 2, &[4]); test(&[2], 10, &[1024]); test(&[2], 100, &[0, 0, 0, 16]); test( &[3], 100, &[3476558801, 3600055637, 1531049845, 1731684438, 1514558410], ); test(&[10], 9, &[1000000000]); test( &[10], 100, &[ 0, 0, 0, 2821623568, 2863809288, 2384534140, 4085960256, 2227490315, 2095778599, 2904921283, 4681, ], ); test(&[1, 1], 2, &[1, 2, 1]); test( &[1, 1], 10, &[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1], ); test( &[1, 1], 100, &[ 1, 100, 4950, 161700, 3921225, 75287520, 1192052400, 3122658912, 1404300575, 3856263611, 1591254002, 3258062030, 899556955, 803216378, 1310151248, 1499375850, 2332619193, 3968431524, 4085749530, 1136679331, 273489285, 3338642246, 3544105701, 844866219, 1175366874, 758834048, 646998201, 3049457170, 733614013, 1400647268, 3979434005, 2770685599, 4038926785, 264011298, 2126789533, 3205011234, 3674235589, 3864120130, 1717547830, 3817918906, 2976806973, 2930427077, 3798905017, 2672346699, 2426398649, 1834316445, 4131270269, 887459147, 1698650569, 3123194158, 2868271121, 3706731654, 2073725215, 570568395, 729640870, 1868322716, 3338774936, 3779458204, 3890882669, 1414262575, 1200805502, 3641833126, 342345696, 1286652406, 3703949518, 47177294, 1562872441, 3379562707, 2490682825, 640606377, 1577764504, 3545174992, 2808433500, 3939117033, 343741199, 2292546107, 1377056316, 1693477863, 368237605, 832210433, 2481934560, 2826277781, 3285796914, 2204777130, 3821989418, 1802445372, 1367480655, 813259882, 901179532, 3258302570, 1591286535, 3856267598, 1404301014, 3122658955, 1192052403, 75287520, 3921225, 161700, 4950, 100, 1, ], ); test( &[1, 2, 3], 10, &[ 1, 20, 210, 1500, 8085, 34704, 122520, 363120, 915570, 1980440, 3692140, 5941320, 8240130, 9804240, 9924120, 8433072, 5893965, 3280500, 1377810, 393660, 59049, ], ); test( &[u32::MAX; 3], 5, &[ u32::MAX, u32::MAX, u32::MAX, 4, 0, 0, 0xfffffff6, u32::MAX, u32::MAX, 9, 0, 0, 0xfffffffb, u32::MAX, u32::MAX, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_fail_1() { limbs_pow(&[], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_fail_2() { limbs_pow(&[], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_fail_3() { limbs_pow(&[1, 1], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_pow_fail_4() { limbs_pow(&[1, 1], 1); } #[test] fn test_pow() { let test = |s, exp, out| { let u = Natural::from_str(s).unwrap(); let mut x = u.clone(); x.pow_assign(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = u.clone().pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = (&u).pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = BigUint::from_str(s).unwrap().pow(exp); assert_eq!(x.to_string(), out); let x = rug::Integer::from_str(s).unwrap().pow(u32::exact_from(exp)); assert_eq!(x.to_string(), out); assert_eq!(natural_pow_naive(&u, exp).to_string(), out); assert_eq!(natural_pow_simple_binary(&u, exp).to_string(), out); assert_eq!(u.pow_ref_alt(exp).to_string(), out); }; test("0", 0, "1"); test("1", 0, "1"); test("2", 0, "1"); test("1000", 0, "1"); test("1000000000000", 0, "1"); test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("1000", 1, "1000"); test("1000000000000", 1, "1000000000000"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "4"); test("3", 2, "9"); test("1000", 2, "1000000"); test("1000000000000", 2, "1000000000000000000000000"); // - xs.len() == 1 first time // - *x <= HALF_MASK in bsize_1_helper // - exp.even() in bsize_1_helper // - *exp != 0 in bsize_1_helper // - *trailing_zero_bits_out == 0 || *out_0 == 1 || *out_0 >> (Limb::WIDTH - // *trailing_zero_bits_out) != 0 in bsize_1_helper // - exp != 0 // - len == 1 || exp.even() // - len == 1 // - bits.odd() // - len == 1 && bit // - len == 1 && !bit // - out_0 == 1 // - trailing_zero_bits_out == 0 test( "123", 456, "992500687720988567008314620574696326372959408198869005198162988813828671047493990779211286\ 6142614463805542423693627187249280035274164990211814381967260156999810012079049675951763646\ 5445895625741609866209900500198407153244604778968016963028050310261417615914468729918240685\ 4878786176459769390634643579861657117309763994785076492286863414669671679101266533421349427\ 4485146389992748709248661097714611276356710167264595313219648143933987301708814041466127119\ 8500333255713096142335151414630651683065518784081203678487703002802082091236603519026256880\ 6244996817813872275740354848312715156831237421490955692604636096559777009388445806119312464\ 9516620869554031369814001163802732256625268978083813635182879531427216211122223117090171561\ 2355701347552371530013693855379834865667060014643302459100429783653966913783002290784283455\ 6282833554705299329560514844771293338811599302127586876027950885792304316616960102321873904\ 36601614145603241902386663442520160735566561", ); // - exp.odd() in bsize_1_helper // - out_0 != 1 test( "123", 457, "122077584589681593742022698330687648143874007208460887639374047624100926538841760865842988\ 2535541579048081718114316144031661444338722293796053168981972999310976631485723110142066928\ 5249845161966218013543817761524404079849086387813066086452450188162154366757479653779943604\ 3150090699704551635048061160322983825429100971358564408551284200004369616529455783610825979\ 5761673005969108091237585315018897186991875350573545223526016721703880438110184127100333635\ 7415540990452710825507223623999570157017058810441988052453987469344656097222102232840229596\ 3168134608591106289916063646342463964290242202843387550190370239876852572154778834152675433\ 1890544366955145858487122143147736067564908084304309077127494182365547593968033443402091102\ 0319751265748941698191684344211719688477048381801126202469352863389437930395309281766466865\ 0422788527228751817535943325906869080673826714161693185751437958952453430943886092585590490\ 23701998539909198753993559603429979770474687003", ); // - *trailing_zero_bits_out != 0 && *out_0 != 1 && *out_0 >> (Limb::WIDTH - // *trailing_zero_bits_out) == 0 in bsize_1_helper // - bits.even() test( "10", 100, "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000", ); test( "10", 101, "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", ); // - *exp == 0 in bsize_1_helper // - exp == 0 // - trailing_zero_bits_out != 0 test("2", 100, "1267650600228229401496703205376"); // - xs.len() == 2 // - xs.len() == 2 && trailing_zero_bits_in == 0 // - xs.len() == 2 && x_1 != 0 // - len >> 1 && exp.odd() // - len != 1 // - !CountOnes::count_ones(exp).eq_mod_power_of_2(bits, 1) // - len != 1 && !bit // - len != 1 && bit test( "12345678987654321", 5, "286797196211272153445658333952148540084053148773966942500383143133144940612575601", ); test( "12345678987654321", 6, "354070611898367606555445954656918550154832595750628623501854823341167403514406003590115726\ 6821921", ); // - xs.len() == 2 && trailing_zero_bits_in != 0 // - CountOnes::count_ones(exp).eq_mod_power_of_2(bits, 1) test( "26872817533106", 12, "141826844138959364185940647071896554485587687634106997683499856265150283163630969349636867\ 234174443605205673555107919666790176734540047683138771242870390213185536", ); // - xs.len() == 2 && x_1 == 0 test( "14823718968", 5, "715790392004360489610590536764569459261039357165568", ); // - xs.len() > 2 // - xs.len() > 2 && trailing_zero_bits_in != 0 test( "24424421844081699326", 55, "213961716190310170274088594850318375142996259342375501592273155327928007898048540877403565\ 3947261530991648842767731271386297041920019953715121571673691873897348960187317337771890905\ 1572382143119842882294517424053653145781261386562757014940642327399405478861990592953674053\ 5435746102693851943687705326429729387827027180615610631114411764811616316442929883964904298\ 3315499400867326194538467726927965720256457038271587840064522521610550522662098778092390775\ 1204011661884808984320689270774425563736748276177153496839435580581401399443258277883965208\ 0795662477157903348885713252035517047912637599810655108674777287567258783790305252352655254\ 9161655860569081456083564805569388857136788414537348033500867479587662770873397446881847014\ 6730827427892395144171556599844946073138166223624637280926661575895662911794190561258748348\ 7934048838204018355648003975520634897314818368802033588189644263971368238570985509229153518\ 4180400851608974878145053640167246336219940448713158030020593993974770074718137925127520351\ 9045385528768578776802376700963217886663279210963568902459805925376", ); // - xs.len() > 2 && trailing_zero_bits_in == 0 test( "762845729280891732629", 6, "197069908665560609451994985160700801551868029168403239983377351218306354370509861303202043\ 757725875289425891538656609168767721", ); // - x == 0 test( "576460717943685120", 9, "702954903302866311524348366058883550484761300374963994159100861262489870076604686210427395\ 8248045324225063677698694075567381512070601339698619038564352000000000", ); } #[test] fn limbs_pow_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_31().test_properties_with_config(&config, |(xs, exp)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_pow(&xs, exp)), Natural::from_owned_limbs_asc(xs).pow(exp) ); }); } #[test] fn pow_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(x, exp)| { let power = (&x).pow(exp); assert!(power.is_valid()); let power_alt = x.clone().pow(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let mut power_alt = x.clone(); power_alt.pow_assign(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); assert_eq!(Natural::from(&BigUint::from(&x).pow(exp)), power); assert_eq!( Natural::exact_from(&rug::Integer::from(&x).pow(u32::exact_from(exp))), power ); assert_eq!(power, natural_pow_naive(&x, exp)); assert_eq!(power, natural_pow_simple_binary(&x, exp)); assert_eq!(power, x.pow_ref_alt(exp)); if exp != 0 { assert_eq!((&power).checked_root(exp).unwrap(), x); } if x > 1 { assert_eq!(power.checked_log_base(&x).unwrap(), exp); } }); natural_gen().test_properties(|x| { assert_eq!((&x).pow(0), 1); assert_eq!((&x).pow(1), x); assert_eq!((&x).pow(2), (&x).square()); }); unsigned_gen_var_5().test_properties(|exp| { assert_eq!(Natural::ZERO.pow(exp), u64::from(exp == 0)); assert_eq!(Natural::ONE.pow(exp), 1); assert_eq!(Natural::TWO.pow(exp), Natural::power_of_2(exp)); }); natural_natural_unsigned_triple_gen_var_1().test_properties(|(x, y, exp)| { assert_eq!((&x * &y).pow(exp), x.pow(exp) * y.pow(exp)); }); natural_unsigned_unsigned_triple_gen_var_5().test_properties(|(x, e, f)| { assert_eq!((&x).pow(e + f), (&x).pow(e) * (&x).pow(f)); assert_eq!((&x).pow(e * f), x.pow(e).pow(f)); }); unsigned_pair_gen_var_29::().test_properties(|(x, y)| { assert_eq!(Pow::pow(x, y), Natural::from(x).pow(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase2, CheckedRoot, IsPowerOf2, Pow, PowerOf2, }; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::logic::traits::{BitAccess, LowMask}; use malachite_base::test_util::generators::{unsigned_gen_var_5, unsigned_gen_var_15}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; #[test] fn test_power_of_2() { let test = |pow, out| assert_eq!(Natural::power_of_2(pow).to_string(), out); test(0, "1"); test(1, "2"); test(2, "4"); test(3, "8"); test(32, "4294967296"); test(100, "1267650600228229401496703205376"); } #[test] fn power_of_2_properties() { unsigned_gen_var_5().test_properties(|pow| { let n = Natural::power_of_2(pow); assert!(n.is_valid()); assert_eq!(n, Natural::ONE << pow); assert_eq!(n, Natural::TWO.pow(pow)); assert_eq!(n, Natural::low_mask(pow) + Natural::ONE); assert!(n.is_power_of_2()); assert_eq!(n.checked_log_base_2().unwrap(), pow); if pow != 0 { assert_eq!((&n).checked_root(pow).unwrap(), 2); } let mut n = n; n.clear_bit(pow); assert_eq!(n, 0); }); unsigned_gen_var_15::().test_properties(|pow| { assert_eq!(Limb::power_of_2(pow), Natural::power_of_2(pow)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/primorial.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Primorial; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::factorization::traits::{IsPrime, Primes}; use malachite_base::test_util::generators::{ unsigned_gen_var_5, unsigned_gen_var_27, unsigned_gen_var_28, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::natural::arithmetic::primorial::{ primorial_naive, product_of_first_n_primes_naive, }; use rug::Complete; #[test] fn test_primorial() { fn test(n: u64, out: &str) { let p = Natural::primorial(n); assert!(p.is_valid()); assert_eq!(p.to_string(), out); assert_eq!(primorial_naive(n).to_string(), out); assert_eq!( rug::Integer::primorial(u32::exact_from(n)) .complete() .to_string(), out ); } test(0, "1"); test(1, "1"); test(2, "2"); test(3, "6"); test(4, "6"); test(5, "30"); test(20, "9699690"); // - sieve[index] & mask == 0 // - prod <= max_prod // - sieve[index] & mask != 0 // - prod > max_prod test(53, "32589158477190044730"); test(100, "2305567963945518424753102147331756070"); } #[test] fn test_product_of_first_n_primes() { fn test(n: u64, out: &str) { let p = Natural::product_of_first_n_primes(n); assert!(p.is_valid()); assert_eq!(p.to_string(), out); assert_eq!(product_of_first_n_primes_naive(n).to_string(), out); } test(0, "1"); test(1, "2"); test(2, "6"); test(3, "30"); test(4, "210"); test(5, "2310"); test(10, "6469693230"); test( 100, "47119307999061849531624878347602604220205747734096755201886348396164153358450342212052892\ 567055446819724391040977771579918043802842183150387194449439904925790307206359905384523125\ 28339864352999310398481791730017201031090", ); } #[test] fn primorial_properties() { unsigned_gen_var_5().test_properties(|n| { let p = Natural::primorial(n); assert!(p.is_valid()); assert_eq!(primorial_naive(n), p); assert_eq!( Natural::exact_from(&rug::Integer::primorial(u32::exact_from(n)).complete()), p ); assert_ne!(p, 0u32); if n != 0 { let q = Natural::primorial(n - 1); if n.is_prime() { assert!(q < p); } else { assert_eq!(q, p); } } }); unsigned_gen_var_27::().test_properties(|n| { assert_eq!(Natural::primorial(n), Limb::primorial(n)); }); } #[test] fn product_of_first_n_primes_properties() { unsigned_gen_var_5().test_properties(|n| { let f = Natural::product_of_first_n_primes(n); assert!(f.is_valid()); assert_eq!(product_of_first_n_primes_naive(n), f); assert_ne!(f, 0); if n != 0 { let p = u64::primes().nth(usize::exact_from(n) - 1).unwrap(); assert_eq!(Natural::primorial(p), f); assert_eq!( f / Natural::product_of_first_n_primes(n - 1), Natural::exact_from(p) ); } }); unsigned_gen_var_28::().test_properties(|n| { assert_eq!( Natural::product_of_first_n_primes(n), Limb::product_of_first_n_primes(n) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingRootAssign, CeilingSqrt, CheckedRoot, CheckedSqrt, FloorRoot, FloorRootAssign, FloorSqrt, Pow, RootAssignRem, RootRem, SqrtRem, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_32, unsigned_vec_unsigned_pair_gen_var_14, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::root::{limbs_floor_root, limbs_root_rem}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_7}; use malachite_nz::test_util::natural::arithmetic::root::{ ceiling_root_binary, checked_root_binary, floor_root_binary, root_rem_binary, }; use num::BigUint; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_floor_root() { let test = |xs: &[Limb], exp: u64, root: &[Limb], inexact: bool| { let (actual_root, actual_inexact) = limbs_floor_root(xs, exp); assert_eq!(actual_root, root); assert_eq!(actual_inexact, inexact); let n = Natural::from_limbs_asc(xs); let r = Natural::from_limbs_asc(root); let pow = (&r).pow(exp); assert!(pow <= n); assert!((r + Natural::ONE).pow(exp) > n); assert_eq!(pow == n, !inexact); }; // - (xs_len + 2) / 3 <= u_exp // - bit_count < exp in limbs_root_to_out_internal // - !out_rem_is_some in limbs_root_to_out_internal test(&[1], 3, &[1], false); // - bit_count >= exp in limbs_root_to_out_internal // - leading_zeros != Limb::WIDTH in limbs_root_to_out_internal // - bit_count.significant_bits() > LOGROOT_USED_BITS_COMP in log_based_root // - !approx || ss[0] <= 1 in limbs_root_to_out_internal // - need_adjust || qs_len != xs_len in limbs_root_to_out_internal // - rs_len == 0 || !out_rem_is_some in limbs_root_to_out_internal test(&[1000], 3, &[10], false); // - root_bits > log_exp in limbs_root_to_out_internal // - need_adjust || qs_len != rs_len in limbs_root_to_out_internal // - pow_cmp != Equal in limbs_root_to_out_internal // - carry == 0 first time in limbs_root_to_out_internal // - n_len - 1 <= next_len in limbs_root_to_out_internal // - carry == 0 second time in limbs_root_to_out_internal // - rs_len >= ws_len in limbs_root_to_out_internal // - qs_len <= b_rem in limbs_root_to_out_internal // - qs_len <= b_rem && ... in limbs_root_to_out_internal // - carry != 0 first time in limbs_root_to_out_internal // - n_len - 1 > next_len in limbs_root_to_out_internal test(&[123, 456, 789], 3, &[24415497], true); // - leading_zeros == Limb::WIDTH in limbs_root_to_out_internal test(&[0, 1], 3, &[1625], true); // - pow_cmp == Equal in limbs_root_to_out_internal // - rs_len < ws_len in limbs_root_to_out_internal test(&[0, 0, 1], 4, &[65536], false); // - !need_adjust && qs_len == rs_len in limbs_root_to_out_internal // - !need_adjust && qs_len == xs_len in limbs_root_to_out_internal // - carry != 0 second time in limbs_root_to_out_internal test(&[0, 0, 1], 5, &[7131], true); // - (xs_len + 2) / 3 > u_exp // - approx && ss[0] > 1 in limbs_root_to_out_internal test( &[ 10045114, 111940252, 2181719322, 1883679021, 2601294413, 1872079876, 578360935, 2248016248, 1648448409, 589499551, 573051942, 3101629567, 486103882, 3213846717, 2339835332, 2340868500, 3988971200, ], 5, &[2416867165, 2555201003, 3891828300, 7026], true, ); // - qs_len > b_rem || ... in limbs_root_to_out_internal test( &[ 2055929154, 2630529572, 271121346, 1501542260, 1183697298, 2075827756, 4275724366, 1648161837, 3297263182, 4114641001, 1962106184, 3607497617, 561001103, 1137290806, 2335506779, 1869248612, ], 3, &[2524001878, 2377965049, 719885555, 160379071, 3624665804, 1231], true, ); // - limbs_root_to_out_internal, root_bits <= log_exp test( &[ 1321882439, 1623785800, 3134073276, 2565564486, 2821610380, 2583585204, 3897897848, 47587649, 2888164080, 1492585590, 1855797547, 1510761479, 3993330677, 2012682921, 1836519625, 4236374717, 1223607044, 3596509294, 1741147226, 1412323213, 3811971203, 1621563690, 3665246834, 1046970441, 99078224, 420931190, 2916287708, 1336157470, 1469113083, 970862367, 3439357619, 2526884655, 1520990535, 3107383205, 3321150749, 828096485, 938849804, 164343730, 2130891622, 3754519147, 2436884346, 2736885571, 405986850, 1875306972, 3010233736, 3737129860, 2106807103, 419975711, 3145892129, 1185575287, 4062252394, 543504740, 3340440476, 4196738733, 2082551138, 1234502144, 3392112010, 3994477994, 1472445754, 934569550, 3244797218, 3086244200, 1419671372, 933654118, 1800407464, 3858653268, 180317861, 1556428454, 3366377290, 1090143530, 1147295140, 1271219922, 1096608888, 655592159, 1364844184, 1674114515, 1285632542, 2458523712, 2081876810, 3935363261, 4174442908, 2398083509, 963931968, 4194789136, 1729071894, 228036838, 2088259023, 2777007731, 2094146444, 888346074, 3199577164, 2715723581, 3607954173, 3433473090, 3678701040, 1035050400, 2036582500, 3748434538, 3152072052, 3413508577, 3191081341, 466218778, 4141778140, 2149717819, 2938658940, 2989191274, 3671957666, 727865845, 568269125, 3615953546, 2956535711, 879106809, 1582857293, 783679777, 604923241, 209547277, 3813482434, 1362157378, 1505311679, 2420123937, 4156219100, 2338704513, 1016908906, 2362401070, 125533635, ], 189, &[2306151], false, ); } #[test] fn limbs_floor_root_fail() { // - xs too short assert_panic!(limbs_floor_root(&[], 3)); // - last element of xs zero assert_panic!(limbs_floor_root(&[1, 0], 3)); // - exp is 0 assert_panic!(limbs_floor_root(&[1, 1], 0)); // - exp is 1 assert_panic!(limbs_floor_root(&[1, 1], 1)); // - exp is 2 assert_panic!(limbs_floor_root(&[1, 1], 2)); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_root_rem() { let test = |xs: &[Limb], exp: u64, root: &[Limb], rem: &[Limb]| { let (actual_root, actual_rem) = limbs_root_rem(xs, exp); assert_eq!(actual_root, root); assert_eq!(actual_rem, rem); let n = Natural::from_limbs_asc(xs); let r_1 = Natural::from_limbs_asc(root); let r_2 = Natural::from_limbs_asc(rem); assert_eq!((&r_1).pow(exp) + r_2, n); assert!((r_1 + Natural::ONE).pow(exp) > n); }; // - bit_count < exp in limbs_root_to_out_internal // - out_rem_is_some in limbs_root_to_out_internal test(&[1], 3, &[1], &[]); // - bit_count >= exp in limbs_root_to_out_internal // - leading_zeros != Limb::WIDTH in limbs_root_to_out_internal // - bit_count.significant_bits() <= LOGROOT_USED_BITS_COMP in log_based_root // - !approx || ss[0] <= 1 in limbs_root_to_out_internal // - !need_adjust && qs_len == xs_len in limbs_root_to_out_internal // - rs_len == 0 || !out_rem_is_some in limbs_root_to_out_internal test(&[1000], 3, &[10], &[]); // - root_bits > log_exp in limbs_root_to_out_internal // - need_adjust || qs_len != rs_len in limbs_root_to_out_internal // - pow_cmp != Equal in limbs_root_to_out_internal // - carry == 0 first time in limbs_root_to_out_internal // - n_len - 1 <= next_len in limbs_root_to_out_internal // - carry == 0 second time in limbs_root_to_out_internal // - rs_len >= ws_len in limbs_root_to_out_internal // - qs_len <= b_rem in limbs_root_to_out_internal // - qs_len <= b_rem && ... in limbs_root_to_out_internal // - carry != 0 first time in limbs_root_to_out_internal // - n_len - 1 > next_len in limbs_root_to_out_internal // - rs_len != 0 && out_rem_is_some in limbs_root_to_out_internal test(&[123, 456, 789], 3, &[24415497], &[1082861218, 142292]); // - leading_zeros == Limb::WIDTH in limbs_root_to_out_internal test(&[0, 1], 3, &[1625], &[3951671]); // - pow_cmp == Equal in limbs_root_to_out_internal // - rs_len < ws_len in limbs_root_to_out_internal test(&[0, 0, 1], 4, &[65536], &[]); // - !need_adjust && qs_len == rs_len in limbs_root_to_out_internal test(&[0, 0, 1], 5, &[7131], &[1889423061, 1656574]); // - carry != 0 second time in limbs_root_to_out_internal test( &[ 10045114, 111940252, 2181719322, 1883679021, 2601294413, 1872079876, 578360935, 2248016248, 1648448409, 589499551, 573051942, 3101629567, 486103882, 3213846717, 2339835332, 2340868500, 3988971200, ], 5, &[2416867165, 2555201003, 3891828300, 7026], &[ 3289703629, 3644089536, 1993609161, 1739315193, 2220455044, 1795995908, 3261364903, 2481515404, 3316729739, 227499169, 1205565253, 3882526697, 534818167, 1092514, ], ); test( &[ 2055929154, 2630529572, 271121346, 1501542260, 1183697298, 2075827756, 4275724366, 1648161837, 3297263182, 4114641001, 1962106184, 3607497617, 561001103, 1137290806, 2335506779, 1869248612, ], 3, &[2524001878, 2377965049, 719885555, 160379071, 3624665804, 1231], &[ 1938096298, 2492483757, 416851523, 4009456064, 358434376, 1470400066, 2808049667, 1641457454, 3086626670, 2101663143, 3655678, ], ); // - !need_adjust && qs_len == xs_len in limbs_root_to_out_internal test(&[0, 2], 4, &[304], &[49217536]); // - qs_len > b_rem || ... in limbs_root_to_out_internal test(&[1002403925, 303302627], 4, &[33783], &[188673716, 30155]); } #[test] fn limbs_root_rem_fail() { // - xs too short assert_panic!(limbs_root_rem(&[], 3)); // - last element of xs zero assert_panic!(limbs_root_rem(&[1, 0], 3)); // - exp is 0 assert_panic!(limbs_root_rem(&[1, 1], 0)); // - exp is 1 assert_panic!(limbs_root_rem(&[1, 1], 1)); // - exp is 2 assert_panic!(limbs_root_rem(&[1, 1], 2)); } #[test] fn test_floor_root() { let test = |s, exp, out| { let n = Natural::from_str(s).unwrap(); assert_eq!(n.clone().floor_root(exp).to_string(), out); assert_eq!((&n).floor_root(exp).to_string(), out); assert_eq!(floor_root_binary(&n, exp).to_string(), out); let mut n = n; n.floor_root_assign(exp); assert_eq!(n.to_string(), out); }; test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("100", 1, "100"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "1"); test("3", 2, "1"); test("4", 2, "2"); test("5", 2, "2"); test("0", 3, "0"); test("1", 3, "1"); test("2", 3, "1"); test("7", 3, "1"); test("8", 3, "2"); test("9", 3, "2"); test("10", 2, "3"); test("100", 2, "10"); test("100", 3, "4"); test("1000000000", 2, "31622"); test("1000000000", 3, "1000"); test("1000000000", 4, "177"); test("1000000000", 5, "63"); test("1000000000", 6, "31"); test("1000000000", 7, "19"); test("1000000000", 8, "13"); test("1000000000", 9, "10"); test("1000000000", 10, "7"); } #[test] #[should_panic] fn floor_root_fail() { Natural::ONE.floor_root(0); } #[test] #[should_panic] fn floor_root_ref_fail() { (&Natural::ONE).floor_root(0); } #[test] #[should_panic] fn floor_root_assign_fail() { let mut x = Natural::ONE; x.floor_root_assign(0); } #[test] fn test_ceiling_root() { let test = |s, exp, out| { let n = Natural::from_str(s).unwrap(); assert_eq!(n.clone().ceiling_root(exp).to_string(), out); assert_eq!((&n).ceiling_root(exp).to_string(), out); assert_eq!(ceiling_root_binary(&n, exp).to_string(), out); let mut n = n; n.ceiling_root_assign(exp); assert_eq!(n.to_string(), out); }; test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("100", 1, "100"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "2"); test("3", 2, "2"); test("4", 2, "2"); test("5", 2, "3"); test("0", 3, "0"); test("1", 3, "1"); test("2", 3, "2"); test("7", 3, "2"); test("8", 3, "2"); test("9", 3, "3"); test("10", 2, "4"); test("100", 2, "10"); test("100", 3, "5"); test("1000000000", 2, "31623"); test("1000000000", 3, "1000"); test("1000000000", 4, "178"); test("1000000000", 5, "64"); test("1000000000", 6, "32"); test("1000000000", 7, "20"); test("1000000000", 8, "14"); test("1000000000", 9, "10"); test("1000000000", 10, "8"); } #[test] #[should_panic] fn ceiling_root_fail() { Natural::ONE.ceiling_root(0); } #[test] #[should_panic] fn ceiling_root_ref_fail() { (&Natural::ONE).ceiling_root(0); } #[test] #[should_panic] fn ceiling_root_assign_fail() { let mut x = Natural::ONE; x.ceiling_root_assign(0); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_checked_root() { let test = |s, exp, out: Option<&str>| { let n = Natural::from_str(s).unwrap(); let out = out.map(|s| s.to_string()); assert_eq!(n.clone().checked_root(exp).map(|x| x.to_string()), out); assert_eq!((&n).checked_root(exp).map(|x| x.to_string()), out); assert_eq!(checked_root_binary(&n, exp).map(|x| x.to_string()), out); }; test("0", 1, Some("0")); test("1", 1, Some("1")); test("2", 1, Some("2")); test("100", 1, Some("100")); test("0", 2, Some("0")); test("1", 2, Some("1")); test("2", 2, None); test("3", 2, None); test("4", 2, Some("2")); test("5", 2, None); test("0", 3, Some("0")); test("1", 3, Some("1")); test("2", 3, None); test("7", 3, None); test("8", 3, Some("2")); test("9", 3, None); test("10", 2, None); test("100", 2, Some("10")); test("100", 3, None); test("1000000000", 2, None); test("1000000000", 3, Some("1000")); test("1000000000", 4, None); test("1000000000", 5, None); test("1000000000", 6, None); test("1000000000", 7, None); test("1000000000", 8, None); test("1000000000", 9, Some("10")); test("1000000000", 10, None); } #[test] #[should_panic] fn checked_root_fail() { Natural::ONE.checked_root(0); } #[test] #[should_panic] fn checked_root_ref_fail() { (&Natural::ONE).checked_root(0); } #[test] fn test_root_rem() { let test = |s, exp, root_out, rem_out| { let n = Natural::from_str(s).unwrap(); let (root, rem) = n.clone().root_rem(exp); assert_eq!(root.to_string(), root_out); assert_eq!(rem.to_string(), rem_out); let (root, rem) = (&n).root_rem(exp); assert_eq!(root.to_string(), root_out); assert_eq!(rem.to_string(), rem_out); let (root, rem) = root_rem_binary(&n, exp); assert_eq!(root.to_string(), root_out); assert_eq!(rem.to_string(), rem_out); let mut n = n; assert_eq!(n.root_assign_rem(exp).to_string(), rem_out); assert_eq!(n.to_string(), root_out); }; test("0", 1, "0", "0"); test("1", 1, "1", "0"); test("2", 1, "2", "0"); test("100", 1, "100", "0"); test("0", 2, "0", "0"); test("1", 2, "1", "0"); test("2", 2, "1", "1"); test("3", 2, "1", "2"); test("4", 2, "2", "0"); test("5", 2, "2", "1"); test("0", 3, "0", "0"); test("1", 3, "1", "0"); test("2", 3, "1", "1"); test("7", 3, "1", "6"); test("8", 3, "2", "0"); test("9", 3, "2", "1"); test("10", 2, "3", "1"); test("100", 2, "10", "0"); test("100", 3, "4", "36"); test("1000000000", 2, "31622", "49116"); test("1000000000", 3, "1000", "0"); test("1000000000", 4, "177", "18493759"); test("1000000000", 5, "63", "7563457"); test("1000000000", 6, "31", "112496319"); test("1000000000", 7, "19", "106128261"); test("1000000000", 8, "13", "184269279"); test("1000000000", 9, "10", "0"); test("1000000000", 10, "7", "717524751"); } #[test] #[should_panic] fn root_rem_fail() { Natural::ONE.root_rem(0); } #[test] #[should_panic] fn root_rem_ref_fail() { (&Natural::ONE).root_rem(0); } #[test] #[should_panic] fn root_assign_rem_fail() { let mut x = Natural::ONE; x.root_assign_rem(0); } #[test] fn limbs_floor_root_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_14().test_properties_with_config(&config, |(xs, exp)| { let n = Natural::from_limbs_asc(&xs); let actual_root = (&n).floor_root(exp); let (root, inexact) = limbs_floor_root(&xs, exp); assert_eq!(Natural::from_owned_limbs_asc(root), actual_root); let pow = (&actual_root).pow(exp); assert_eq!(pow == n, !inexact); assert!(pow <= n); assert!((actual_root + Natural::ONE).pow(exp) > n); }); } #[test] fn limbs_root_rem_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_14().test_properties_with_config(&config, |(xs, exp)| { let n = Natural::from_limbs_asc(&xs); let (actual_root, actual_rem) = (&n).root_rem(exp); let (root, rem) = limbs_root_rem(&xs, exp); assert_eq!(Natural::from_owned_limbs_asc(root), actual_root); assert_eq!(Natural::from_owned_limbs_asc(rem), actual_rem); assert_eq!((&actual_root).pow(exp) + actual_rem, n); assert!((actual_root + Natural::ONE).pow(exp) > n); }); } #[test] fn floor_cbrt_properties() { natural_gen().test_properties(|n| { let cbrt = n.clone().floor_root(3); assert!(cbrt.is_valid()); let cbrt_alt = (&n).floor_root(3); assert!(cbrt_alt.is_valid()); assert_eq!(cbrt_alt, cbrt); let mut n_alt = n.clone(); n_alt.floor_root_assign(3); assert!(cbrt_alt.is_valid()); assert_eq!(n_alt, cbrt); assert_eq!(floor_root_binary(&n, 3), cbrt); assert_eq!(Natural::from(&BigUint::from(&n).nth_root(3)), cbrt); assert_eq!(Natural::exact_from(&rug::Integer::from(&n).root(3)), cbrt); let cube = (&cbrt).pow(3); let ceiling_cbrt = (&n).ceiling_root(3); if cube == n { assert_eq!(ceiling_cbrt, cbrt); } else { assert_eq!(ceiling_cbrt, &cbrt + Natural::ONE); } assert!(cube <= n); assert!((cbrt + Natural::ONE).pow(3) > n); }); unsigned_gen::().test_properties(|u| { assert_eq!(u.floor_root(3), Natural::from(u).floor_root(3)); }); } #[test] fn ceiling_cbrt_properties() { natural_gen().test_properties(|n| { let cbrt = n.clone().ceiling_root(3); assert!(cbrt.is_valid()); let cbrt_alt = (&n).ceiling_root(3); assert!(cbrt_alt.is_valid()); assert_eq!(cbrt_alt, cbrt); let mut n_alt = n.clone(); n_alt.ceiling_root_assign(3); assert!(cbrt_alt.is_valid()); assert_eq!(n_alt, cbrt); assert_eq!(ceiling_root_binary(&n, 3), cbrt); let cube = (&cbrt).pow(3); let floor_cbrt = (&n).floor_root(3); if cube == n { assert_eq!(floor_cbrt, cbrt); } else { assert_eq!(floor_cbrt, &cbrt - Natural::ONE); } assert!(cube >= n); if n != 0 { assert!((cbrt - Natural::ONE).pow(3) < n); } }); unsigned_gen::().test_properties(|u| { assert_eq!(u.ceiling_root(3), Natural::from(u).ceiling_root(3)); }); } #[test] fn checked_cbrt_properties() { natural_gen().test_properties(|n| { let cbrt = n.clone().checked_root(3); assert!(cbrt.as_ref().is_none_or(Natural::is_valid)); let cbrt_alt = (&n).checked_root(3); assert!(cbrt_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(cbrt_alt, cbrt); assert_eq!(checked_root_binary(&n, 3), cbrt); if let Some(cbrt) = cbrt { assert_eq!((&cbrt).pow(3), n); assert_eq!((&n).floor_root(3), cbrt); assert_eq!(n.ceiling_root(3), cbrt); } }); unsigned_gen::().test_properties(|u| { assert_eq!( u.checked_root(3).map(Natural::from), Natural::from(u).checked_root(3) ); }); } #[test] fn cbrt_rem_properties() { natural_gen().test_properties(|n| { let (cbrt, rem) = n.clone().root_rem(3); assert!(cbrt.is_valid()); assert!(rem.is_valid()); let (cbrt_alt, rem_alt) = (&n).root_rem(3); assert!(cbrt_alt.is_valid()); assert!(rem_alt.is_valid()); assert_eq!(cbrt_alt, cbrt_alt); assert_eq!(rem_alt, rem); let mut n_alt = n.clone(); let rem_alt = n_alt.root_assign_rem(3); assert!(n_alt.is_valid()); assert!(rem_alt.is_valid()); assert_eq!(n_alt, cbrt); assert_eq!(rem_alt, rem); assert_eq!(root_rem_binary(&n, 3), (cbrt.clone(), rem.clone())); let (rug_cbrt, rug_rem) = rug::Integer::from(&n).root_rem(rug::Integer::new(), 3); assert_eq!(Natural::exact_from(&rug_cbrt), cbrt); assert_eq!(Natural::exact_from(&rug_rem), rem); assert_eq!((&n).floor_root(3), cbrt); assert_eq!(cbrt.pow(3) + rem, n); }); unsigned_gen::().test_properties(|u| { let (cbrt, rem) = u.root_rem(3); assert_eq!( (Natural::from(cbrt), Natural::from(rem)), Natural::from(u).root_rem(3) ); }); } #[test] fn floor_root_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { let root = n.clone().floor_root(exp); assert!(root.is_valid()); let root_alt = (&n).floor_root(exp); assert!(root_alt.is_valid()); assert_eq!(root_alt, root); let mut n_alt = n.clone(); n_alt.floor_root_assign(exp); assert!(root_alt.is_valid()); assert_eq!(n_alt, root); assert_eq!(floor_root_binary(&n, exp), root); assert_eq!( Natural::from(&BigUint::from(&n).nth_root(u32::exact_from(exp))), root ); assert_eq!( Natural::exact_from(&rug::Integer::from(&n).root(u32::exact_from(exp))), root ); let pow = (&root).pow(exp); let ceiling_root = (&n).ceiling_root(exp); if pow == n { assert_eq!(ceiling_root, root); } else { assert_eq!(ceiling_root, &root + Natural::ONE); } assert!(pow <= n); assert!((root + Natural::ONE).pow(exp) > n); }); natural_gen().test_properties(|n| { assert_eq!((&n).floor_root(2), (&n).floor_sqrt()); assert_eq!((&n).floor_root(1), n); }); unsigned_pair_gen_var_32::().test_properties(|(u, exp)| { assert_eq!(u.floor_root(exp), Natural::from(u).floor_root(exp)); }); } #[test] fn ceiling_root_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { let root = n.clone().ceiling_root(exp); assert!(root.is_valid()); let root_alt = (&n).ceiling_root(exp); assert!(root_alt.is_valid()); assert_eq!(root_alt, root); let mut n_alt = n.clone(); n_alt.ceiling_root_assign(exp); assert!(root_alt.is_valid()); assert_eq!(n_alt, root); assert_eq!(ceiling_root_binary(&n, exp), root); let pow = (&root).pow(exp); let floor_root = (&n).floor_root(exp); if pow == n { assert_eq!(floor_root, root); } else { assert_eq!(floor_root, &root - Natural::ONE); } assert!(pow >= n); if n != 0 { assert!((root - Natural::ONE).pow(exp) < n); } }); natural_gen().test_properties(|n| { assert_eq!((&n).ceiling_root(2), (&n).ceiling_sqrt()); assert_eq!((&n).ceiling_root(1), n); }); unsigned_pair_gen_var_32::().test_properties(|(u, exp)| { assert_eq!(u.ceiling_root(exp), Natural::from(u).ceiling_root(exp)); }); } #[test] fn checked_root_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { let root = n.clone().checked_root(exp); assert!(root.as_ref().is_none_or(Natural::is_valid)); let root_alt = (&n).checked_root(exp); assert!(root_alt.as_ref().is_none_or(Natural::is_valid)); assert_eq!(root_alt, root); assert_eq!(checked_root_binary(&n, exp), root); if let Some(root) = root { assert_eq!((&root).pow(exp), n); assert_eq!((&n).floor_root(exp), root); assert_eq!(n.ceiling_root(exp), root); } }); natural_gen().test_properties(|n| { assert_eq!((&n).checked_root(2), (&n).checked_sqrt()); assert_eq!((&n).checked_root(1), Some(n)); }); unsigned_pair_gen_var_32::().test_properties(|(u, exp)| { assert_eq!( u.checked_root(exp).map(Natural::from), Natural::from(u).checked_root(exp) ); }); } #[test] fn root_rem_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(n, exp)| { let (root, rem) = n.clone().root_rem(exp); assert!(root.is_valid()); assert!(rem.is_valid()); let (root_alt, rem_alt) = (&n).root_rem(exp); assert!(root_alt.is_valid()); assert!(rem_alt.is_valid()); assert_eq!(root_alt, root); assert_eq!(rem_alt, rem); let mut n_alt = n.clone(); let rem_alt = n_alt.root_assign_rem(exp); assert!(root_alt.is_valid()); assert!(rem_alt.is_valid()); assert_eq!(n_alt, root); assert_eq!(rem_alt, rem); assert_eq!(root_rem_binary(&n, exp), (root.clone(), rem.clone())); let (rug_root, rug_rem) = rug::Integer::from(&n).root_rem(rug::Integer::new(), u32::exact_from(exp)); assert_eq!(Natural::exact_from(&rug_root), root); assert_eq!(Natural::exact_from(&rug_rem), rem); assert_eq!((&n).floor_root(exp), root); assert_eq!(root.pow(exp) + rem, n); }); natural_gen().test_properties(|n| { assert_eq!((&n).root_rem(2), (&n).sqrt_rem()); assert_eq!((&n).root_rem(1), (n, Natural::ZERO)); }); unsigned_pair_gen_var_32::().test_properties(|(u, exp)| { let (root, rem) = u.root_rem(exp); assert_eq!( (Natural::from(root), Natural::from(rem)), Natural::from(u).root_rem(exp) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, DivRound, DivisibleBy, Parity, RoundToMultiple, RoundToMultipleAssign, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::unsigned_unsigned_rounding_mode_triple_gen_var_2; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_natural_rounding_mode_triple_gen_var_2, natural_pair_gen_var_5, natural_pair_gen_var_7, natural_rounding_mode_pair_gen, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_round_to_multiple() { let test = |s, t, rm, quotient, o| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut x = u.clone(); assert_eq!(x.round_to_multiple_assign(v.clone(), rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let mut x = u.clone(); assert_eq!(x.round_to_multiple_assign(&v, rm), o); assert_eq!(x.to_string(), quotient); assert!(x.is_valid()); let (r, o_alt) = u.clone().round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = u.clone().round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); }; test("0", "1", Down, "0", Equal); test("0", "1", Floor, "0", Equal); test("0", "1", Up, "0", Equal); test("0", "1", Ceiling, "0", Equal); test("0", "1", Nearest, "0", Equal); test("0", "1", Exact, "0", Equal); test("0", "123", Down, "0", Equal); test("0", "123", Floor, "0", Equal); test("0", "123", Up, "0", Equal); test("0", "123", Ceiling, "0", Equal); test("0", "123", Nearest, "0", Equal); test("0", "123", Exact, "0", Equal); test("1", "1", Down, "1", Equal); test("1", "1", Floor, "1", Equal); test("1", "1", Up, "1", Equal); test("1", "1", Ceiling, "1", Equal); test("1", "1", Nearest, "1", Equal); test("1", "1", Exact, "1", Equal); test("123", "1", Down, "123", Equal); test("123", "1", Floor, "123", Equal); test("123", "1", Up, "123", Equal); test("123", "1", Ceiling, "123", Equal); test("123", "1", Nearest, "123", Equal); test("123", "1", Exact, "123", Equal); test("123", "2", Down, "122", Less); test("123", "2", Floor, "122", Less); test("123", "2", Up, "124", Greater); test("123", "2", Ceiling, "124", Greater); test("123", "2", Nearest, "124", Greater); test("125", "2", Down, "124", Less); test("125", "2", Floor, "124", Less); test("125", "2", Up, "126", Greater); test("125", "2", Ceiling, "126", Greater); test("125", "2", Nearest, "124", Less); test("123", "123", Down, "123", Equal); test("123", "123", Floor, "123", Equal); test("123", "123", Up, "123", Equal); test("123", "123", Ceiling, "123", Equal); test("123", "123", Nearest, "123", Equal); test("123", "123", Exact, "123", Equal); test("123", "456", Down, "0", Less); test("123", "456", Floor, "0", Less); test("123", "456", Up, "456", Greater); test("123", "456", Ceiling, "456", Greater); test("123", "456", Nearest, "0", Less); test("1000000000000", "1", Down, "1000000000000", Equal); test("1000000000000", "1", Floor, "1000000000000", Equal); test("1000000000000", "1", Up, "1000000000000", Equal); test("1000000000000", "1", Ceiling, "1000000000000", Equal); test("1000000000000", "1", Nearest, "1000000000000", Equal); test("1000000000000", "1", Exact, "1000000000000", Equal); test("1000000000000", "3", Down, "999999999999", Less); test("1000000000000", "3", Floor, "999999999999", Less); test("1000000000000", "3", Up, "1000000000002", Greater); test("1000000000000", "3", Ceiling, "1000000000002", Greater); test("1000000000000", "3", Nearest, "999999999999", Less); test("999999999999", "2", Down, "999999999998", Less); test("999999999999", "2", Floor, "999999999998", Less); test("999999999999", "2", Up, "1000000000000", Greater); test("999999999999", "2", Ceiling, "1000000000000", Greater); test("999999999999", "2", Nearest, "1000000000000", Greater); test("1000000000001", "2", Down, "1000000000000", Less); test("1000000000001", "2", Floor, "1000000000000", Less); test("1000000000001", "2", Up, "1000000000002", Greater); test("1000000000001", "2", Ceiling, "1000000000002", Greater); test("1000000000001", "2", Nearest, "1000000000000", Less); test( "1000000000000000000000000", "4294967295", Down, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "4294967295", Floor, "999999999999996832276305", Less, ); test( "1000000000000000000000000", "4294967295", Up, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "4294967295", Ceiling, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "4294967295", Nearest, "1000000000000001127243600", Greater, ); test( "1000000000000000000000000", "1000000000000", Down, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Floor, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Up, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Ceiling, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Nearest, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000000", Exact, "1000000000000000000000000", Equal, ); test( "1000000000000000000000000", "1000000000001", Down, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Floor, "999999999999999999999999", Less, ); test( "1000000000000000000000000", "1000000000001", Up, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Ceiling, "1000000000001000000000000", Greater, ); test( "1000000000000000000000000", "1000000000001", Nearest, "999999999999999999999999", Less, ); test( "2999999999999999999999999", "2000000000000000000000000", Nearest, "2000000000000000000000000", Less, ); test( "3000000000000000000000000", "2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test( "3000000000000000000000001", "2000000000000000000000000", Nearest, "4000000000000000000000000", Greater, ); test("0", "0", Floor, "0", Equal); test("0", "0", Ceiling, "0", Equal); test("0", "0", Down, "0", Equal); test("0", "0", Up, "0", Equal); test("0", "0", Nearest, "0", Equal); test("0", "0", Exact, "0", Equal); test("2", "0", Floor, "0", Less); test("2", "0", Down, "0", Less); test("2", "0", Nearest, "0", Less); } #[test] #[should_panic] fn round_to_multiple_assign_fail_1() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_fail_2() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_fail_3() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_fail_4() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(Natural::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_1() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(&Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_2() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(&Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_3() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(&Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_4() { let mut n = Natural::from(10u32); n.round_to_multiple_assign(&Natural::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_fail_1() { Natural::from(10u32).round_to_multiple(Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_fail_2() { Natural::from(10u32).round_to_multiple(Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_fail_3() { Natural::from(10u32).round_to_multiple(Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_fail_4() { Natural::from(10u32).round_to_multiple(Natural::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_1() { Natural::from(10u32).round_to_multiple(&Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_2() { Natural::from(10u32).round_to_multiple(&Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_3() { Natural::from(10u32).round_to_multiple(&Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_4() { Natural::from(10u32).round_to_multiple(&Natural::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_1() { (&Natural::from(10u32)).round_to_multiple(Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_2() { (&Natural::from(10u32)).round_to_multiple(Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_3() { (&Natural::from(10u32)).round_to_multiple(Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_4() { (&Natural::from(10u32)).round_to_multiple(Natural::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_1() { (&Natural::from(10u32)).round_to_multiple(&Natural::from(3u32), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_2() { (&Natural::from(10u32)).round_to_multiple(&Natural::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_3() { (&Natural::from(10u32)).round_to_multiple(&Natural::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_4() { (&Natural::from(10u32)).round_to_multiple(&Natural::ZERO, Exact); } #[test] fn round_to_multiple_properties() { natural_natural_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { let mut mut_x = x.clone(); let o = mut_x.round_to_multiple_assign(&y, rm); assert!(mut_x.is_valid()); let r = mut_x; let mut mut_x = x.clone(); assert_eq!(mut_x.round_to_multiple_assign(y.clone(), rm), o); assert!(mut_x.is_valid()); assert_eq!(mut_x, r); let (r_alt, o_alt) = (&x).round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (&x).round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); assert!((&r).divisible_by(&y)); assert_eq!(r.cmp(&x), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } if y == 0 { assert_eq!(r, 0); } else { assert!((Integer::from(&r) - Integer::from(&x)).abs() <= y); match rm { Floor | Down => assert!(r <= x), Ceiling | Up => assert!(r >= x), Exact => assert_eq!(r, x), Nearest => { let closest; let second_closest; if r <= x { closest = &x - &r; second_closest = &r + &y - x; } else { closest = &r - &x; second_closest = x + &y - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!((&r).div_round(&y, Exact).0.even()); } } } } }); natural_pair_gen_var_5().test_properties(|(x, y)| { let product = &x * &y; let po = (product.clone(), Equal); assert_eq!((&product).round_to_multiple(&y, Down), po); assert_eq!((&product).round_to_multiple(&y, Up), po); assert_eq!((&product).round_to_multiple(&y, Floor), po); assert_eq!((&product).round_to_multiple(&y, Ceiling), po); assert_eq!((&product).round_to_multiple(&y, Nearest), po); assert_eq!((&product).round_to_multiple(y, Exact), po); }); natural_pair_gen_var_7().test_properties(|(x, y)| { let down = (&x).round_to_multiple(&y, Down); assert_eq!(down.1, Less); let up = (&down.0 + &y, Greater); assert_eq!((&x).round_to_multiple(&y, Up), up); assert_eq!((&x).round_to_multiple(&y, Floor), down); assert_eq!((&x).round_to_multiple(&y, Ceiling), up); let nearest = x.round_to_multiple(y, Nearest); assert!(nearest == down || nearest == up); }); natural_rounding_mode_pair_gen().test_properties(|(x, rm)| { let xo = (x.clone(), Equal); assert_eq!((&x).round_to_multiple(Natural::ONE, rm), xo); assert_eq!( Natural::ZERO.round_to_multiple(&x, rm), (Natural::ZERO, Equal) ); assert_eq!((&x).round_to_multiple(&x, rm), xo); }); unsigned_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(x, y, rm)| { let (n, no) = x.round_to_multiple(y, rm); let (i, io) = Natural::from(x).round_to_multiple(Natural::from(y), rm); assert_eq!(n, i); assert_eq!(no, io); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 . #[cfg(not(feature = "32_bit_limbs"))] use core::cmp::Ordering::*; #[cfg(feature = "32_bit_limbs")] use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ Abs, DivisibleByPowerOf2, PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, ShrRound, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_rounding_mode_pair_gen, unsigned_unsigned_rounding_mode_triple_gen_var_3, unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_20, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::round_to_multiple_of_power_of_2::{ limbs_round_to_multiple_of_power_of_2, limbs_round_to_multiple_of_power_of_2_down, limbs_round_to_multiple_of_power_of_2_down_in_place, limbs_round_to_multiple_of_power_of_2_in_place, limbs_round_to_multiple_of_power_of_2_nearest, limbs_round_to_multiple_of_power_of_2_nearest_in_place, limbs_round_to_multiple_of_power_of_2_up, limbs_round_to_multiple_of_power_of_2_up_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_rounding_mode_pair_gen, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_10, natural_unsigned_pair_gen_var_13, natural_unsigned_rounding_mode_triple_gen_var_1, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_round_to_multiple_of_power_of_2_down() { let test = |xs: &[Limb], pow: u64, out: &[Limb], o: Ordering| { let (r, o_alt) = limbs_round_to_multiple_of_power_of_2_down(xs, pow); assert_eq!(r, out); assert_eq!(o_alt, o); let mut xs = xs.to_vec(); assert_eq!( limbs_round_to_multiple_of_power_of_2_down_in_place(&mut xs, pow), o ); assert_eq!(xs, out); }; test(&[], 0, &[], Equal); test(&[], 1, &[], Equal); test(&[], 100, &[], Equal); test(&[0, 0, 0], 0, &[0, 0, 0], Equal); test(&[0, 0, 0], 1, &[0, 0, 0], Equal); test(&[0, 0, 0], 100, &[], Equal); test(&[1], 0, &[1], Equal); test(&[1], 1, &[0], Less); test(&[3], 1, &[2], Less); test(&[122, 456], 1, &[122, 456], Equal); test(&[123, 456], 0, &[123, 456], Equal); test(&[123, 456], 1, &[122, 456], Less); test(&[123, 455], 1, &[122, 455], Less); test(&[123, 456], 31, &[0, 456], Less); test(&[123, 456], 32, &[0, 456], Less); test(&[123, 456], 100, &[], Less); test(&[256, 456], 8, &[256, 456], Equal); test(&[u32::MAX, 1], 1, &[u32::MAX - 1, 1], Less); test(&[u32::MAX, u32::MAX], 32, &[0, u32::MAX], Less); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_round_to_multiple_of_power_of_2_up_in_place() { let test = |xs: &[Limb], pow: u64, out: &[Limb], o: Ordering| { let (r, o_alt) = limbs_round_to_multiple_of_power_of_2_up(xs, pow); assert_eq!(r, out); assert_eq!(o_alt, o); let mut xs = xs.to_vec(); assert_eq!( limbs_round_to_multiple_of_power_of_2_up_in_place(&mut xs, pow), o ); assert_eq!(xs, out); }; test(&[1], 0, &[1], Equal); test(&[1], 1, &[2], Greater); test(&[3], 1, &[4], Greater); test(&[122, 456], 1, &[122, 456], Equal); test(&[123, 456], 0, &[123, 456], Equal); test(&[123, 456], 1, &[124, 456], Greater); test(&[123, 455], 1, &[124, 455], Greater); test(&[123, 456], 31, &[0x80000000, 456], Greater); test(&[123, 456], 32, &[0, 457], Greater); test(&[123, 456], 100, &[0, 0, 0, 16], Greater); test(&[256, 456], 8, &[256, 456], Equal); test(&[u32::MAX, 1], 1, &[0, 2], Greater); test(&[u32::MAX, u32::MAX], 32, &[0, 0, 1], Greater); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_round_to_multiple_of_power_of_2_nearest() { let test = |xs: &[Limb], pow: u64, out: &[Limb], o: Ordering| { let (r, o_alt) = limbs_round_to_multiple_of_power_of_2_nearest(xs, pow); assert_eq!(r, out); assert_eq!(o_alt, o); let mut xs = xs.to_vec(); assert_eq!( limbs_round_to_multiple_of_power_of_2_nearest_in_place(&mut xs, pow), o ); assert_eq!(xs, out); }; test(&[], 0, &[], Equal); test(&[], 1, &[], Equal); test(&[], 100, &[], Equal); test(&[0, 0, 0], 0, &[0, 0, 0], Equal); test(&[0, 0, 0], 1, &[0, 0, 0], Equal); test(&[0, 0, 0], 100, &[], Equal); test(&[1], 0, &[1], Equal); test(&[1], 1, &[0], Less); test(&[3], 1, &[4], Greater); test(&[122, 456], 1, &[122, 456], Equal); test(&[123, 456], 0, &[123, 456], Equal); test(&[123, 456], 1, &[124, 456], Greater); test(&[123, 455], 1, &[124, 455], Greater); test(&[123, 456], 31, &[0, 456], Less); test(&[123, 456], 32, &[0, 456], Less); test(&[123, 456], 100, &[], Less); test(&[256, 456], 8, &[256, 456], Equal); test(&[u32::MAX, 1], 1, &[0, 2], Greater); test(&[u32::MAX, u32::MAX], 32, &[0, 0, 1], Greater); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_round_to_multiple_of_power_of_2() { let test = |xs: &[Limb], pow: u64, rm: RoundingMode, out: Option<(&[Limb], Ordering)>| { let result = limbs_round_to_multiple_of_power_of_2(xs, pow, rm); if let Some((r, o_alt)) = result { let out = out.unwrap(); assert_eq!(r, out.0); assert_eq!(o_alt, out.1); } else { assert!(out.is_none()); } let mut xs = xs.to_vec(); limbs_round_to_multiple_of_power_of_2_in_place(&mut xs, pow, rm).map_or_else( || assert!(out.is_none()), |o_alt| { let out = out.unwrap(); assert_eq!(xs, out.0); assert_eq!(o_alt, out.1); }, ); }; test(&[1], 0, Nearest, Some((&[1], Equal))); test(&[1], 1, Up, Some((&[2], Greater))); test(&[3], 1, Nearest, Some((&[4], Greater))); test(&[122, 456], 1, Floor, Some((&[122, 456], Equal))); test(&[123, 456], 0, Floor, Some((&[123, 456], Equal))); test(&[123, 456], 1, Down, Some((&[122, 456], Less))); test(&[123, 455], 1, Floor, Some((&[122, 455], Less))); test( &[123, 456], 31, Ceiling, Some((&[0x80000000, 456], Greater)), ); test(&[123, 456], 32, Up, Some((&[0, 457], Greater))); test(&[123, 456], 100, Down, Some((&[], Less))); test(&[256, 456], 8, Exact, Some((&[256, 456], Equal))); test(&[u32::MAX, 1], 1, Exact, None); test( &[u32::MAX, u32::MAX], 32, Down, Some((&[0, u32::MAX], Less)), ); } #[test] fn test_round_to_multiple_of_power_of_2() { let test = |s, v: u64, rm: RoundingMode, out, o| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); assert_eq!(n.round_to_multiple_of_power_of_2_assign(v, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = u.shr_round(v, rm); assert_eq!((n << v).to_string(), out); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "244", Less); test("245", 1, Up, "246", Greater); test("245", 1, Floor, "244", Less); test("245", 1, Ceiling, "246", Greater); test("245", 1, Nearest, "244", Less); test("246", 1, Down, "246", Equal); test("246", 1, Up, "246", Equal); test("246", 1, Floor, "246", Equal); test("246", 1, Ceiling, "246", Equal); test("246", 1, Nearest, "246", Equal); test("246", 1, Exact, "246", Equal); test("247", 1, Down, "246", Less); test("247", 1, Up, "248", Greater); test("247", 1, Floor, "246", Less); test("247", 1, Ceiling, "248", Greater); test("247", 1, Nearest, "248", Greater); test("491", 2, Down, "488", Less); test("491", 2, Up, "492", Greater); test("491", 2, Floor, "488", Less); test("491", 2, Ceiling, "492", Greater); test("491", 2, Nearest, "492", Greater); test("492", 2, Down, "492", Equal); test("492", 2, Up, "492", Equal); test("492", 2, Floor, "492", Equal); test("492", 2, Ceiling, "492", Equal); test("492", 2, Nearest, "492", Equal); test("492", 2, Exact, "492", Equal); test("493", 2, Down, "492", Less); test("493", 2, Up, "496", Greater); test("493", 2, Floor, "492", Less); test("493", 2, Ceiling, "496", Greater); test("493", 2, Nearest, "492", Less); test("4127195135", 25, Down, "4093640704", Less); test("4127195135", 25, Up, "4127195136", Greater); test("4127195135", 25, Floor, "4093640704", Less); test("4127195135", 25, Ceiling, "4127195136", Greater); test("4127195135", 25, Nearest, "4127195136", Greater); test("4127195136", 25, Down, "4127195136", Equal); test("4127195136", 25, Up, "4127195136", Equal); test("4127195136", 25, Floor, "4127195136", Equal); test("4127195136", 25, Ceiling, "4127195136", Equal); test("4127195136", 25, Nearest, "4127195136", Equal); test("4127195136", 25, Exact, "4127195136", Equal); test("4127195137", 25, Down, "4127195136", Less); test("4127195137", 25, Up, "4160749568", Greater); test("4127195137", 25, Floor, "4127195136", Less); test("4127195137", 25, Ceiling, "4160749568", Greater); test("4127195137", 25, Nearest, "4127195136", Less); test("8254390271", 26, Down, "8187281408", Less); test("8254390271", 26, Up, "8254390272", Greater); test("8254390271", 26, Floor, "8187281408", Less); test("8254390271", 26, Ceiling, "8254390272", Greater); test("8254390271", 26, Nearest, "8254390272", Greater); test("8254390272", 26, Down, "8254390272", Equal); test("8254390272", 26, Up, "8254390272", Equal); test("8254390272", 26, Floor, "8254390272", Equal); test("8254390272", 26, Ceiling, "8254390272", Equal); test("8254390272", 26, Nearest, "8254390272", Equal); test("8254390272", 26, Exact, "8254390272", Equal); test("8254390273", 26, Down, "8254390272", Less); test("8254390273", 26, Up, "8321499136", Greater); test("8254390273", 26, Floor, "8254390272", Less); test("8254390273", 26, Ceiling, "8321499136", Greater); test("8254390273", 26, Nearest, "8254390272", Less); test( "155921023828072216384094494261247", 100, Down, "154653373227843986982597791055872", Less, ); test( "155921023828072216384094494261247", 100, Up, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261247", 100, Floor, "154653373227843986982597791055872", Less, ); test( "155921023828072216384094494261247", 100, Ceiling, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "155921023828072216384094494261248", Greater, ); test( "155921023828072216384094494261248", 100, Down, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Up, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Floor, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "155921023828072216384094494261248", Equal, ); test( "155921023828072216384094494261249", 100, Down, "155921023828072216384094494261248", Less, ); test( "155921023828072216384094494261249", 100, Up, "157188674428300445785591197466624", Greater, ); test( "155921023828072216384094494261249", 100, Floor, "155921023828072216384094494261248", Less, ); test( "155921023828072216384094494261249", 100, Ceiling, "157188674428300445785591197466624", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "155921023828072216384094494261248", Less, ); test("4294967295", 1, Down, "4294967294", Less); test("4294967295", 1, Up, "4294967296", Greater); test("4294967295", 1, Floor, "4294967294", Less); test("4294967295", 1, Ceiling, "4294967296", Greater); test("4294967295", 1, Nearest, "4294967296", Greater); test("4294967296", 1, Down, "4294967296", Equal); test("4294967296", 1, Up, "4294967296", Equal); test("4294967296", 1, Floor, "4294967296", Equal); test("4294967296", 1, Ceiling, "4294967296", Equal); test("4294967296", 1, Nearest, "4294967296", Equal); test("4294967296", 1, Exact, "4294967296", Equal); test("4294967297", 1, Down, "4294967296", Less); test("4294967297", 1, Up, "4294967298", Greater); test("4294967297", 1, Floor, "4294967296", Less); test("4294967297", 1, Ceiling, "4294967298", Greater); test("4294967297", 1, Nearest, "4294967296", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "7999999999992", Less); test("7999999999999", 3, Up, "8000000000000", Greater); test("7999999999999", 3, Floor, "7999999999992", Less); test("7999999999999", 3, Ceiling, "8000000000000", Greater); test("7999999999999", 3, Nearest, "8000000000000", Greater); test("8000000000000", 3, Down, "8000000000000", Equal); test("8000000000000", 3, Up, "8000000000000", Equal); test("8000000000000", 3, Floor, "8000000000000", Equal); test("8000000000000", 3, Ceiling, "8000000000000", Equal); test("8000000000000", 3, Nearest, "8000000000000", Equal); test("8000000000000", 3, Exact, "8000000000000", Equal); test("8000000000001", 3, Down, "8000000000000", Less); test("8000000000001", 3, Up, "8000000000008", Greater); test("8000000000001", 3, Floor, "8000000000000", Less); test("8000000000001", 3, Ceiling, "8000000000008", Greater); test("8000000000001", 3, Nearest, "8000000000000", Less); test( "16777216000000000000", 24, Down, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Up, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Floor, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Ceiling, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Nearest, "16777216000000000000", Equal, ); test( "16777216000000000000", 24, Exact, "16777216000000000000", Equal, ); test( "33554432000000000000", 25, Down, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Up, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Floor, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Ceiling, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Nearest, "33554432000000000000", Equal, ); test( "33554432000000000000", 25, Exact, "33554432000000000000", Equal, ); test( "2147483648000000000000", 31, Down, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Up, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Floor, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Ceiling, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "2147483648000000000000", Equal, ); test( "2147483648000000000000", 31, Exact, "2147483648000000000000", Equal, ); test( "4294967296000000000000", 32, Down, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Up, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Floor, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Ceiling, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "4294967296000000000000", Equal, ); test( "4294967296000000000000", 32, Exact, "4294967296000000000000", Equal, ); test( "8589934592000000000000", 33, Down, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Up, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Floor, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Ceiling, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "8589934592000000000000", Equal, ); test( "8589934592000000000000", 33, Exact, "8589934592000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Down, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1267650600228229401496703205376000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1267650600228229401496703205376000000000000", Equal, ); test("1000000000000", 10, Down, "1000000000000", Equal); test("1000000000000", 10, Up, "1000000000000", Equal); test("1000000000000", 10, Floor, "1000000000000", Equal); test("1000000000000", 10, Ceiling, "1000000000000", Equal); test("1000000000000", 10, Nearest, "1000000000000", Equal); test("1000000000000", 10, Exact, "1000000000000", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "4722366482869645213696", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "4722366482869645213696", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "2147483648", Less); test("4294967295", 31, Up, "4294967296", Greater); test("4294967295", 31, Floor, "2147483648", Less); test("4294967295", 31, Ceiling, "4294967296", Greater); test("4294967295", 31, Nearest, "4294967296", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "4294967296", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "4294967296", Greater); test("4294967295", 32, Nearest, "4294967296", Greater); test("4294967296", 32, Down, "4294967296", Equal); test("4294967296", 32, Up, "4294967296", Equal); test("4294967296", 32, Floor, "4294967296", Equal); test("4294967296", 32, Ceiling, "4294967296", Equal); test("4294967296", 32, Nearest, "4294967296", Equal); test("4294967296", 32, Exact, "4294967296", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "8589934592", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "8589934592", Greater); test("4294967296", 33, Nearest, "0", Less); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_1() { Natural::from(123u32).round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_2() { Natural::from(123u32).round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_3() { Natural::from_str("1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_4() { Natural::from_str("1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_1() { Natural::from(123u32).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_2() { Natural::from(123u32).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_3() { Natural::from_str("1000000000001") .unwrap() .round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_4() { Natural::from_str("1000000000001") .unwrap() .round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_1() { (&Natural::from(123u32)).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_2() { (&Natural::from(123u32)).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_3() { (&Natural::from_str("1000000000001").unwrap()).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_4() { (&Natural::from_str("1000000000001").unwrap()).round_to_multiple_of_power_of_2(100, Exact); } #[test] fn limbs_round_to_multiple_of_power_of_2_down_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, pow)| { let (r, o) = limbs_round_to_multiple_of_power_of_2_down(&xs, pow); let x = Natural::from_owned_limbs_asc(xs); let r = Natural::from_owned_limbs_asc(r); assert_eq!(r, &x >> pow << pow); assert_eq!(r.cmp(&x), o); }); } #[test] fn limbs_round_to_multiple_of_power_of_2_up_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, pow)| { let (r, o) = limbs_round_to_multiple_of_power_of_2_up(&xs, pow); let x = Natural::from_owned_limbs_asc(xs); let r = Natural::from_owned_limbs_asc(r); let (r_alt, o_alt) = (&x).round_to_multiple_of_power_of_2(pow, Up); assert_eq!(r_alt, r); assert_eq!(o_alt, o); assert_eq!(r.cmp(&x), o); }); } #[test] fn limbs_round_to_multiple_of_power_of_2_nearest_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, pow)| { let (r, o) = limbs_round_to_multiple_of_power_of_2_nearest(&xs, pow); let r = Natural::from_owned_limbs_asc(r); let x = Natural::from_owned_limbs_asc(xs); let (r_alt, o_alt) = (&x).round_to_multiple_of_power_of_2(pow, Nearest); assert_eq!(r_alt, r); assert_eq!(o_alt, o); assert_eq!(r.cmp(&x), o); }); } #[test] fn limbs_round_to_multiple_of_power_of_2_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().test_properties_with_config( &config, |(xs, pow, rm)| { let n = Natural::from_limbs_asc(&xs); limbs_round_to_multiple_of_power_of_2(&xs, pow, rm).map_or_else( || { assert_eq!(rm, Exact); assert!(!n.divisible_by_power_of_2(pow)); }, |(result_limbs, o)| { let (m, o_alt) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert_eq!(Natural::from_owned_limbs_asc(result_limbs), m); assert_eq!(o_alt, o); if rm == Exact { assert_eq!(m, n); } }, ); }, ); } #[test] fn limbs_round_to_multiple_of_power_of_2_down_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, pow)| { let old_xs = xs.clone(); limbs_round_to_multiple_of_power_of_2_down_in_place(&mut xs, pow); let n = Natural::from_owned_limbs_asc(old_xs) >> pow << pow; assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn limbs_round_to_multiple_of_power_of_2_up_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config( &config, |(mut xs, pow)| { let old_xs = xs.clone(); let o = limbs_round_to_multiple_of_power_of_2_up_in_place(&mut xs, pow); let (n, o_alt) = Natural::from_owned_limbs_asc(old_xs).round_to_multiple_of_power_of_2(pow, Up); assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(o_alt, o); }, ); } #[test] fn limbs_round_to_multiple_of_power_of_2_nearest_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, pow)| { let old_xs = xs.clone(); let o = limbs_round_to_multiple_of_power_of_2_nearest_in_place(&mut xs, pow); let (n, o_alt) = Natural::from_owned_limbs_asc(old_xs).round_to_multiple_of_power_of_2(pow, Nearest); assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(o_alt, o); }, ); } #[test] fn limbs_round_to_multiple_of_power_of_2_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().test_properties_with_config( &config, |(mut xs, pow, rm)| { let n = Natural::from_limbs_asc(&xs); limbs_round_to_multiple_of_power_of_2_in_place(&mut xs, pow, rm).map_or_else( || { assert_eq!(rm, Exact); assert!(!n.divisible_by_power_of_2(pow)); }, |o| { let (m, o_alt) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert_eq!(Natural::from_owned_limbs_asc(xs), m); if rm == Exact { assert_eq!(m, n); } assert_eq!(o_alt, o); }, ); }, ); } #[test] fn round_to_multiple_of_power_of_2_properties() { natural_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, pow, rm)| { let (r, o) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert!(r.is_valid()); let (r_alt, o_alt) = n.clone().round_to_multiple_of_power_of_2(pow, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let mut mut_n = n.clone(); assert_eq!(mut_n.round_to_multiple_of_power_of_2_assign(pow, rm), o); assert!(mut_n.is_valid()); assert_eq!(mut_n, r); assert!(r.divisible_by_power_of_2(pow)); assert_eq!(r.cmp(&n), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } let (s, o_alt) = (&n).shr_round(pow, rm); assert_eq!(s << pow, r); assert_eq!(o_alt, o); assert!((Integer::from(&r) - Integer::from(&n)).abs() <= Natural::power_of_2(pow)); let (r_alt, o_alt) = (&n).round_to_multiple(Natural::power_of_2(pow), rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); match rm { Floor | Down => assert!(r <= n), Ceiling | Up => assert!(r >= n), Exact => assert_eq!(r, n), Nearest => { let k = Natural::power_of_2(pow); let closest; let second_closest; if r <= n { closest = &n - &r; second_closest = &r + k - n; } else { closest = &r - &n; second_closest = n + k - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!(!r.get_bit(pow)); } } } }); natural_unsigned_pair_gen_var_4::().test_properties(|(n, pow)| { let shifted = n << pow; let so = (shifted.clone(), Equal); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Down), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Up), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Floor), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Ceiling), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Nearest), so); assert_eq!((&shifted).round_to_multiple_of_power_of_2(pow, Exact), so); }); natural_unsigned_pair_gen_var_10().test_properties(|(n, pow)| { let down = (&n).round_to_multiple_of_power_of_2(pow, Down); assert_eq!(down.1, Less); let up = (&down.0 + Natural::power_of_2(pow), Greater); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Up), up); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Floor), down); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Ceiling), up); let nearest = n.round_to_multiple_of_power_of_2(pow, Nearest); assert!(nearest == down || nearest == up); }); natural_unsigned_pair_gen_var_13::().test_properties(|(n, pow)| { if let Some(shift) = pow.checked_add(n.significant_bits()) { assert_eq!( (&n).round_to_multiple_of_power_of_2(shift, Down), (Natural::ZERO, Less) ); assert_eq!( (&n).round_to_multiple_of_power_of_2(shift, Floor), (Natural::ZERO, Less) ); if let Some(extra_shift) = shift.checked_add(1) { assert_eq!( n.round_to_multiple_of_power_of_2(extra_shift, Nearest), (Natural::ZERO, Less) ); } } }); natural_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).round_to_multiple_of_power_of_2(0, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen().test_properties(|(pow, rm)| { assert_eq!( Natural::ZERO.round_to_multiple_of_power_of_2(pow, rm), (Natural::ZERO, Equal) ); }); unsigned_unsigned_rounding_mode_triple_gen_var_3::().test_properties(|(n, pow, rm)| { let (r, o) = Natural::from(n).round_to_multiple_of_power_of_2(pow, rm); let (r_alt, o_alt) = n.round_to_multiple_of_power_of_2(pow, rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/saturating_sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{SaturatingSub, SaturatingSubAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use std::str::FromStr; #[test] fn test_saturating_sub_natural() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.saturating_sub_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.saturating_sub_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().saturating_sub(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().saturating_sub(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).saturating_sub(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).saturating_sub(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "0"); test("0", "123", "0"); test("123", "0", "123"); test("456", "123", "333"); test("1000000000000", "123", "999999999877"); test("123", "1000000000000", "0"); test("12345678987654321", "314159265358979", "12031519722295342"); test("4294967296", "1", "4294967295"); test("4294967295", "4294967295", "0"); test("4294967296", "4294967295", "1"); test("4294967296", "4294967296", "0"); test("4294967295", "4294967296", "0"); test("18446744073709551616", "1", "18446744073709551615"); test("18446744073709551615", "18446744073709551615", "0"); test("18446744073709551616", "18446744073709551615", "1"); test("18446744073709551615", "18446744073709551616", "0"); test("70734740290631708", "282942734368", "70734457347897340"); test("282942734368", "70734740290631708", "0"); } #[test] fn saturating_sub_properties() { natural_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.saturating_sub_assign(&y); assert!(mut_x.is_valid()); let diff = mut_x; let mut mut_x = x.clone(); mut_x.saturating_sub_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let diff_alt = x.clone().saturating_sub(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = x.clone().saturating_sub(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).saturating_sub(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).saturating_sub(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let reverse_diff = (&y).saturating_sub(&x); if diff > 0 { assert_eq!(reverse_diff, 0); } if reverse_diff > 0 { assert_eq!(diff, 0); } assert!(diff <= x); assert!(diff + y >= x); }); natural_gen().test_properties(|x| { assert_eq!((&x).saturating_sub(Natural::ZERO), x); assert_eq!((&x).saturating_sub(&x), 0); assert_eq!(Natural::ZERO.saturating_sub(x), 0); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( x.saturating_sub(y), Natural::from(x).saturating_sub(Natural::from(y)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/saturating_sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ SaturatingSub, SaturatingSubMul, SaturatingSubMulAssign, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::unsigned_triple_gen_var_19; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use std::str::FromStr; #[test] fn test_saturating_sub_mul() { let test = |r, s, t, out: &str| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let w = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.saturating_sub_mul_assign(v.clone(), w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.saturating_sub_mul_assign(v.clone(), &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.saturating_sub_mul_assign(&v, w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.saturating_sub_mul_assign(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().saturating_sub_mul(v.clone(), w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().saturating_sub_mul(v.clone(), &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().saturating_sub_mul(&v, w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().saturating_sub_mul(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).saturating_sub_mul(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); }; test("0", "0", "0", "0"); test("0", "0", "123", "0"); test("123", "0", "5", "123"); test("123", "5", "1", "118"); test("123", "5", "100", "0"); test("10", "3", "4", "0"); test("15", "3", "4", "3"); test("1000000000000", "0", "123", "1000000000000"); test("1000000000000", "1", "123", "999999999877"); test("1000000000000", "123", "1", "999999999877"); test("1000000000000", "123", "100", "999999987700"); test("1000000000000", "100", "123", "999999987700"); test("1000000000000", "65536", "65536", "995705032704"); test("1000000000000", "1000000000000", "0", "1000000000000"); test("1000000000000", "1000000000000", "1", "0"); test("1000000000000", "1000000000000", "100", "0"); test("0", "1000000000000", "100", "0"); test("4294967296", "1", "1", "4294967295"); test("3902609153", "88817093856604", "1", "0"); } #[allow(clippy::useless_conversion)] #[test] fn saturating_sub_mul_properties() { natural_triple_gen().test_properties(|(a, b, c)| { let mut mut_a = a.clone(); mut_a.saturating_sub_mul_assign(&b, &c); assert!(mut_a.is_valid()); let result = mut_a; let mut mut_a = a.clone(); mut_a.saturating_sub_mul_assign(&b, c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.saturating_sub_mul_assign(b.clone(), &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.saturating_sub_mul_assign(b.clone(), c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let result_alt = (&a).saturating_sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().saturating_sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().saturating_sub_mul(&b, c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().saturating_sub_mul(b.clone(), &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().saturating_sub_mul(b.clone(), c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!((&a).saturating_sub(b * c), result); assert!(result <= a); }); natural_gen().test_properties(|n| { assert_eq!((&n).saturating_sub_mul(&n, &Natural::ONE), 0); }); natural_pair_gen().test_properties(|(a, b)| { assert_eq!(Natural::ZERO.saturating_sub_mul(&a, &b), 0); assert_eq!((&a).saturating_sub_mul(&Natural::ZERO, &b), a); assert_eq!((&a).saturating_sub_mul(&b, &Natural::ZERO), a); assert_eq!((&a * &b).saturating_sub_mul(&a, &b), 0); assert_eq!( (&a).saturating_sub_mul(&Natural::ONE, &b), (&a).saturating_sub(&b) ); assert_eq!( (&a).saturating_sub_mul(&b, &Natural::ONE), a.saturating_sub(b) ); }); unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| { assert_eq!( Limb::from(x).saturating_sub_mul(Limb::from(y), Limb::from(z)), Natural::from(x).saturating_sub_mul(Natural::from(y), Natural::from(z)) ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, ShlRound}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_gen, unsigned_gen_var_5, unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_32, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shl::{ limbs_shl, limbs_shl_to_out, limbs_shl_with_complement_to_out, limbs_slice_shl_in_place, limbs_vec_shl_in_place, }; use malachite_nz::natural::logic::not::limbs_not_in_place; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_signed_pair_gen_var_2, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_triple_gen_var_5, }; use num::BigUint; use rug; use std::ops::{Shl, ShlAssign, Shr}; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shl_and_limbs_vec_shl_in_place() { let test = |limbs: &[Limb], bits: u64, out: &[Limb]| { assert_eq!(limbs_shl(limbs, bits), out); let mut limbs = limbs.to_vec(); limbs_vec_shl_in_place(&mut limbs, bits); assert_eq!(limbs, out); }; test(&[], 0, &[]); test(&[], 5, &[]); test(&[], 100, &[0, 0, 0]); test(&[6, 7], 2, &[24, 28]); test(&[100, 101, 102], 10, &[102400, 103424, 104448]); test(&[123, 456], 1, &[246, 912]); test(&[123, 456], 31, &[0x80000000, 61, 228]); test(&[123, 456], 32, &[0, 123, 456]); test(&[123, 456], 100, &[0, 0, 0, 1968, 7296]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shl_to_out() { let test = |out_before: &[Limb], limbs_in: &[Limb], bits: u64, carry: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_shl_to_out(&mut out, limbs_in, bits), carry); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[], 5, 0, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, 0, &[24, 28, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, 0, &[102400, 103424, 104448, 10], ); test(&[10, 10, 10, 10], &[123, 456], 1, 0, &[246, 912, 10, 10]); test( &[10, 10, 10, 10], &[123, 456], 31, 228, &[0x80000000, 61, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_to_out_fail_1() { limbs_shl_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_to_out_fail_2() { limbs_shl_to_out(&mut [10, 10, 10], &[123, 456], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_to_out_fail_3() { limbs_shl_to_out(&mut [10, 10, 10], &[123, 456], 100); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_shl_in_place() { let test = |limbs: &[Limb], bits: u64, carry: Limb, out: &[Limb]| { let mut limbs = limbs.to_vec(); assert_eq!(limbs_slice_shl_in_place(&mut limbs, bits), carry); assert_eq!(limbs, out); }; test(&[], 5, 0, &[]); test(&[6, 7], 2, 0, &[24, 28]); test(&[100, 101, 102], 10, 0, &[102400, 103424, 104448]); test(&[123, 456], 1, 0, &[246, 912]); test(&[123, 456], 31, 228, &[0x80000000, 61]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_shl_in_place_fail_1() { limbs_slice_shl_in_place(&mut [123, 456], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_shl_in_place_fail_2() { limbs_slice_shl_in_place(&mut [123, 456], 100); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shl_with_complement_to_out() { let test = |out_before: &[Limb], limbs_in: &[Limb], bits: u64, carry: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!( limbs_shl_with_complement_to_out(&mut out, limbs_in, bits), carry ); assert_eq!(out, out_after); }; test( &[10, 10, 10, 10], &[6, 7], 2, 0, &[4294967271, 4294967267, 10, 10], ); test( &[10, 10, 10, 10], &[100, 101, 102], 10, 0, &[4294864895, 4294863871, 4294862847, 10], ); test( &[10, 10, 10, 10], &[123, 456], 1, 0, &[4294967049, 4294966383, 10, 10], ); test( &[10, 10, 10, 10], &[123, 456], 31, 228, &[0x7fffffff, 4294967234, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_with_complement_to_out_fail_1() { limbs_shl_with_complement_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_with_complement_to_out_fail_2() { limbs_shl_with_complement_to_out(&mut [10, 10, 10], &[123, 456], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_with_complement_to_out_fail_3() { limbs_shl_with_complement_to_out(&mut [10, 10, 10], &[123, 456], 100); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shl_with_complement_to_out_fail_4() { limbs_shl_with_complement_to_out(&mut [10, 10, 10], &[], 100); } fn test_shl_unsigned_helper(f: F) where Natural: Shl + ShlAssign, for<'a> &'a Natural: Shl, { let test = |s, v: u8, out| { let u = Natural::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("2147483648", 1, "4294967296"); test("1000000000000", 0, "1000000000000"); test("1000000000000", 3, "8000000000000"); test("1000000000000", 24, "16777216000000000000"); test("1000000000000", 25, "33554432000000000000"); test("1000000000000", 31, "2147483648000000000000"); test("1000000000000", 32, "4294967296000000000000"); test("1000000000000", 33, "8589934592000000000000"); test( "1000000000000", 100, "1267650600228229401496703205376000000000000", ); } #[test] fn test_shl_unsigned() { test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|u, v, out| { let rug_u = rug::Integer::from_str(u).unwrap(); let mut n = rug_u.clone(); n <<= v; assert_eq!(n.to_string(), out); let n = rug_u << v; assert_eq!(n.to_string(), out); let num_u = BigUint::from_str(u).unwrap(); let n = num_u.clone() << usize::exact_from(v); assert_eq!(n.to_string(), out); let n = &num_u << usize::exact_from(v); assert_eq!(n.to_string(), out); }); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); } fn test_shl_signed_helper(f: F) where Natural: Shl + ShlAssign, for<'a> &'a Natural: Shl, { let test = |s, v: i8, out| { let u = Natural::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("2147483648", 1, "4294967296"); test("1000000000000", 0, "1000000000000"); test("1000000000000", 3, "8000000000000"); test("1000000000000", 24, "16777216000000000000"); test("1000000000000", 25, "33554432000000000000"); test("1000000000000", 31, "2147483648000000000000"); test("1000000000000", 32, "4294967296000000000000"); test("1000000000000", 33, "8589934592000000000000"); test( "1000000000000", 100, "1267650600228229401496703205376000000000000", ); test("0", -10, "0"); test("123", 0, "123"); test("245", -1, "122"); test("246", -1, "123"); test("247", -1, "123"); test("491", -2, "122"); test("492", -2, "123"); test("493", -2, "123"); test("4127195135", -25, "122"); test("4127195136", -25, "123"); test("4127195137", -25, "123"); test("8254390271", -26, "122"); test("8254390272", -26, "123"); test("8254390273", -26, "123"); test("155921023828072216384094494261247", -100, "122"); test("155921023828072216384094494261248", -100, "123"); test("155921023828072216384094494261249", -100, "123"); test("4294967295", -1, "2147483647"); test("4294967296", -1, "2147483648"); test("4294967297", -1, "2147483648"); test("7999999999999", -3, "999999999999"); test("8000000000000", -3, "1000000000000"); test("8000000000001", -3, "1000000000000"); test("16777216000000000000", -24, "1000000000000"); test("33554432000000000000", -25, "1000000000000"); test("2147483648000000000000", -31, "1000000000000"); test("4294967296000000000000", -32, "1000000000000"); test("8589934592000000000000", -33, "1000000000000"); test( "1267650600228229401496703205376000000000000", -100, "1000000000000", ); test("1000000000000", -10, "976562500"); test("980657949", -72, "0"); test("4294967295", -31, "1"); test("4294967295", -32, "0"); test("4294967296", -32, "1"); test("4294967296", -33, "0"); } #[test] fn test_shl_signed() { test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|u, v, out| { let rug_u = rug::Integer::from_str(u).unwrap(); let mut n = rug_u.clone(); n <<= v; assert_eq!(n.to_string(), out); let n = rug_u << v; assert_eq!(n.to_string(), out); }); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); } #[test] fn limbs_shl_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, bits)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_shl(&xs, bits)), Natural::from_owned_limbs_asc(xs) << bits ); }); } #[test] fn limbs_shl_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_22::() .test_properties_with_config(&config, |(mut out, xs, bits)| { let old_out = out.clone(); let carry = limbs_shl_to_out(&mut out, &xs, bits); let len = xs.len(); let n = Natural::from_owned_limbs_asc(xs) << bits; let mut xs = n.into_limbs_asc(); assert_eq!(carry != 0, xs.len() == len + 1); let mut actual_xs = out[..len].to_vec(); if carry != 0 { actual_xs.push(carry); } xs.resize(actual_xs.len(), 0); assert_eq!(xs, actual_xs); assert_eq!(&out[len..], &old_out[len..]); }); } #[test] fn limbs_slice_shl_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_32::().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); let carry = limbs_slice_shl_in_place(&mut xs, bits); let n = Natural::from_owned_limbs_asc(old_xs) << bits; let mut expected_xs = n.into_limbs_asc(); assert_eq!(carry != 0, expected_xs.len() == xs.len() + 1); if carry != 0 { xs.push(carry); } expected_xs.resize(xs.len(), 0); assert_eq!(xs, expected_xs); }, ); } #[test] fn limbs_vec_shl_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16::().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); limbs_vec_shl_in_place(&mut xs, bits); let n = Natural::from_owned_limbs_asc(old_xs) << bits; assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn limbs_shl_with_complement_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::() .test_properties_with_config(&config, |(mut out, xs, bits)| { let old_out = out.clone(); let len = xs.len(); let carry = limbs_shl_with_complement_to_out(&mut out, &xs, bits); limbs_not_in_place(&mut out[..len]); let n = Natural::from_owned_limbs_asc(xs) << bits; let mut xs = n.into_limbs_asc(); assert_eq!(carry != 0, xs.len() == len + 1); let mut actual_xs = out[..len].to_vec(); if carry != 0 { actual_xs.push(carry); } xs.resize(actual_xs.len(), 0); assert_eq!(xs, actual_xs); assert_eq!(&out[len..], &old_out[len..]); }); } fn unsigned_properties>() where Natural: Shl + ShlAssign + Shr, for<'a> &'a Natural: Shl + Shl + Shr, { natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n <<= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!(shifted >= n); assert_eq!(shifted, &n * (Natural::ONE << u)); assert_eq!(&shifted >> u, n); if u <= U::low_mask(U::WIDTH - 1) { let u = S::wrapping_from(u); assert_eq!(&n << u, shifted); assert_eq!(n >> -u, shifted); } }); natural_unsigned_unsigned_triple_gen_var_5::().test_properties(|(n, u, v)| { if let Some(sum) = u.checked_add(v) { assert_eq!(&n << u << v, n << sum); } }); natural_gen().test_properties(|n| { assert_eq!(&n << U::ZERO, n); assert_eq!(&n << U::ONE, n * Natural::from(2u32)); }); unsigned_gen_var_5::().test_properties(|u| { assert_eq!(Natural::ZERO << u, 0); assert!((Natural::ONE << u).is_power_of_2()); }); } fn signed_properties() where Natural: Shl + ShlAssign + ShlRound, for<'a> &'a Natural: Shl, { natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n <<= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(n.shl_round(i, Floor).0, shifted); }); natural_gen().test_properties(|n| { assert_eq!(&n << T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Natural::ZERO << i, 0); }); } #[test] fn shl_properties() { apply_fn_to_unsigned_signed_pairs!(unsigned_properties); apply_fn_to_signeds!(signed_properties); natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { let shifted = &n << u; let mut rug_n = rug::Integer::from(&n); rug_n <<= u; assert_eq!(Natural::exact_from(&rug_n), shifted); assert_eq!( Natural::from(&(&BigUint::from(&n) << usize::exact_from(u))), shifted ); assert_eq!( Natural::from(&(BigUint::from(&n) << usize::exact_from(u))), shifted ); assert_eq!(Natural::exact_from(&(rug::Integer::from(&n) << u)), shifted); }); natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = &n << i; let mut rug_n = rug::Integer::from(&n); rug_n <<= i; assert_eq!(Natural::exact_from(&rug_n), shifted); assert_eq!(Natural::exact_from(&(rug::Integer::from(&n) << i)), shifted); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/shl_round.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ArithmeticCheckedShl, ShlRound, ShlRoundAssign}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, unsigned_signed_rounding_mode_triple_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_rounding_mode_pair_gen, natural_signed_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::ops::Shr; use std::panic::catch_unwind; use std::str::FromStr; macro_rules! test_shl_round_signed_helper { ($t:ident) => { let test = |s, j: $t, rm: RoundingMode, out, o| { let u = Natural::from_str(s).unwrap(); let mut n = u.clone(); assert_eq!(n.shl_round_assign(j, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shl_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shl_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", -10, Down, "0", Equal); test("0", -10, Up, "0", Equal); test("0", -10, Floor, "0", Equal); test("0", -10, Ceiling, "0", Equal); test("0", -10, Nearest, "0", Equal); test("0", -10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", -1, Down, "122", Less); test("245", -1, Up, "123", Greater); test("245", -1, Floor, "122", Less); test("245", -1, Ceiling, "123", Greater); test("245", -1, Nearest, "122", Less); test("246", -1, Down, "123", Equal); test("246", -1, Up, "123", Equal); test("246", -1, Floor, "123", Equal); test("246", -1, Ceiling, "123", Equal); test("246", -1, Nearest, "123", Equal); test("246", -1, Exact, "123", Equal); test("247", -1, Down, "123", Less); test("247", -1, Up, "124", Greater); test("247", -1, Floor, "123", Less); test("247", -1, Ceiling, "124", Greater); test("247", -1, Nearest, "124", Greater); test("491", -2, Down, "122", Less); test("491", -2, Up, "123", Greater); test("491", -2, Floor, "122", Less); test("491", -2, Ceiling, "123", Greater); test("491", -2, Nearest, "123", Greater); test("492", -2, Down, "123", Equal); test("492", -2, Up, "123", Equal); test("492", -2, Floor, "123", Equal); test("492", -2, Ceiling, "123", Equal); test("492", -2, Nearest, "123", Equal); test("492", -2, Exact, "123", Equal); test("493", -2, Down, "123", Less); test("493", -2, Up, "124", Greater); test("493", -2, Floor, "123", Less); test("493", -2, Ceiling, "124", Greater); test("493", -2, Nearest, "123", Less); test("4127195135", -25, Down, "122", Less); test("4127195135", -25, Up, "123", Greater); test("4127195135", -25, Floor, "122", Less); test("4127195135", -25, Ceiling, "123", Greater); test("4127195135", -25, Nearest, "123", Greater); test("4127195136", -25, Down, "123", Equal); test("4127195136", -25, Up, "123", Equal); test("4127195136", -25, Floor, "123", Equal); test("4127195136", -25, Ceiling, "123", Equal); test("4127195136", -25, Nearest, "123", Equal); test("4127195136", -25, Exact, "123", Equal); test("4127195137", -25, Down, "123", Less); test("4127195137", -25, Up, "124", Greater); test("4127195137", -25, Floor, "123", Less); test("4127195137", -25, Ceiling, "124", Greater); test("4127195137", -25, Nearest, "123", Less); test("8254390271", -26, Down, "122", Less); test("8254390271", -26, Up, "123", Greater); test("8254390271", -26, Floor, "122", Less); test("8254390271", -26, Ceiling, "123", Greater); test("8254390271", -26, Nearest, "123", Greater); test("8254390272", -26, Down, "123", Equal); test("8254390272", -26, Up, "123", Equal); test("8254390272", -26, Floor, "123", Equal); test("8254390272", -26, Ceiling, "123", Equal); test("8254390272", -26, Nearest, "123", Equal); test("8254390272", -26, Exact, "123", Equal); test("8254390273", -26, Down, "123", Less); test("8254390273", -26, Up, "124", Greater); test("8254390273", -26, Floor, "123", Less); test("8254390273", -26, Ceiling, "124", Greater); test("8254390273", -26, Nearest, "123", Less); test("155921023828072216384094494261247", -100, Down, "122", Less); test( "155921023828072216384094494261247", -100, Up, "123", Greater, ); test( "155921023828072216384094494261247", -100, Floor, "122", Less, ); test( "155921023828072216384094494261247", -100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", -100, Nearest, "123", Greater, ); test( "155921023828072216384094494261248", -100, Down, "123", Equal, ); test("155921023828072216384094494261248", -100, Up, "123", Equal); test( "155921023828072216384094494261248", -100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", -100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", -100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", -100, Exact, "123", Equal, ); test("155921023828072216384094494261249", -100, Down, "123", Less); test( "155921023828072216384094494261249", -100, Up, "124", Greater, ); test( "155921023828072216384094494261249", -100, Floor, "123", Less, ); test( "155921023828072216384094494261249", -100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", -100, Nearest, "123", Less, ); test("4294967295", -1, Down, "2147483647", Less); test("4294967295", -1, Up, "2147483648", Greater); test("4294967295", -1, Floor, "2147483647", Less); test("4294967295", -1, Ceiling, "2147483648", Greater); test("4294967295", -1, Nearest, "2147483648", Greater); test("4294967296", -1, Down, "2147483648", Equal); test("4294967296", -1, Up, "2147483648", Equal); test("4294967296", -1, Floor, "2147483648", Equal); test("4294967296", -1, Ceiling, "2147483648", Equal); test("4294967296", -1, Nearest, "2147483648", Equal); test("4294967296", -1, Exact, "2147483648", Equal); test("4294967297", -1, Down, "2147483648", Less); test("4294967297", -1, Up, "2147483649", Greater); test("4294967297", -1, Floor, "2147483648", Less); test("4294967297", -1, Ceiling, "2147483649", Greater); test("4294967297", -1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", -3, Down, "999999999999", Less); test("7999999999999", -3, Up, "1000000000000", Greater); test("7999999999999", -3, Floor, "999999999999", Less); test("7999999999999", -3, Ceiling, "1000000000000", Greater); test("7999999999999", -3, Nearest, "1000000000000", Greater); test("8000000000000", -3, Down, "1000000000000", Equal); test("8000000000000", -3, Up, "1000000000000", Equal); test("8000000000000", -3, Floor, "1000000000000", Equal); test("8000000000000", -3, Ceiling, "1000000000000", Equal); test("8000000000000", -3, Nearest, "1000000000000", Equal); test("8000000000000", -3, Exact, "1000000000000", Equal); test("8000000000001", -3, Down, "1000000000000", Less); test("8000000000001", -3, Up, "1000000000001", Greater); test("8000000000001", -3, Floor, "1000000000000", Less); test("8000000000001", -3, Ceiling, "1000000000001", Greater); test("8000000000001", -3, Nearest, "1000000000000", Less); test("16777216000000000000", -24, Down, "1000000000000", Equal); test("16777216000000000000", -24, Up, "1000000000000", Equal); test("16777216000000000000", -24, Floor, "1000000000000", Equal); test("16777216000000000000", -24, Ceiling, "1000000000000", Equal); test("16777216000000000000", -24, Nearest, "1000000000000", Equal); test("16777216000000000000", -24, Exact, "1000000000000", Equal); test("33554432000000000000", -25, Down, "1000000000000", Equal); test("33554432000000000000", -25, Up, "1000000000000", Equal); test("33554432000000000000", -25, Floor, "1000000000000", Equal); test("33554432000000000000", -25, Ceiling, "1000000000000", Equal); test("33554432000000000000", -25, Nearest, "1000000000000", Equal); test("33554432000000000000", -25, Exact, "1000000000000", Equal); test("2147483648000000000000", -31, Down, "1000000000000", Equal); test("2147483648000000000000", -31, Up, "1000000000000", Equal); test("2147483648000000000000", -31, Floor, "1000000000000", Equal); test( "2147483648000000000000", -31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", -31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", -31, Exact, "1000000000000", Equal); test("4294967296000000000000", -32, Down, "1000000000000", Equal); test("4294967296000000000000", -32, Up, "1000000000000", Equal); test("4294967296000000000000", -32, Floor, "1000000000000", Equal); test( "4294967296000000000000", -32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", -32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", -32, Exact, "1000000000000", Equal); test("8589934592000000000000", -33, Down, "1000000000000", Equal); test("8589934592000000000000", -33, Up, "1000000000000", Equal); test("8589934592000000000000", -33, Floor, "1000000000000", Equal); test( "8589934592000000000000", -33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", -33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", -33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", -100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", -100, Exact, "1000000000000", Equal, ); test("1000000000000", -10, Down, "976562500", Equal); test("1000000000000", -10, Up, "976562500", Equal); test("1000000000000", -10, Floor, "976562500", Equal); test("1000000000000", -10, Ceiling, "976562500", Equal); test("1000000000000", -10, Nearest, "976562500", Equal); test("1000000000000", -10, Exact, "976562500", Equal); test("980657949", -72, Down, "0", Less); test("980657949", -72, Up, "1", Greater); test("980657949", -72, Floor, "0", Less); test("980657949", -72, Ceiling, "1", Greater); test("980657949", -72, Nearest, "0", Less); test("4294967295", -31, Down, "1", Less); test("4294967295", -31, Up, "2", Greater); test("4294967295", -31, Floor, "1", Less); test("4294967295", -31, Ceiling, "2", Greater); test("4294967295", -31, Nearest, "2", Greater); test("4294967295", -32, Down, "0", Less); test("4294967295", -32, Up, "1", Greater); test("4294967295", -32, Floor, "0", Less); test("4294967295", -32, Ceiling, "1", Greater); test("4294967295", -32, Nearest, "1", Greater); test("4294967296", -32, Down, "1", Equal); test("4294967296", -32, Up, "1", Equal); test("4294967296", -32, Floor, "1", Equal); test("4294967296", -32, Ceiling, "1", Equal); test("4294967296", -32, Nearest, "1", Equal); test("4294967296", -32, Exact, "1", Equal); test("4294967296", -33, Down, "0", Less); test("4294967296", -33, Up, "1", Greater); test("4294967296", -33, Floor, "0", Less); test("4294967296", -33, Ceiling, "1", Greater); test("4294967296", -33, Nearest, "0", Less); test("0", 10, Exact, "0", Equal); test("123", 1, Exact, "246", Equal); test("123", 2, Exact, "492", Equal); test("123", 25, Exact, "4127195136", Equal); test("123", 26, Exact, "8254390272", Equal); test( "123", 100, Exact, "155921023828072216384094494261248", Equal, ); test("2147483648", 1, Exact, "4294967296", Equal); test("1000000000000", 3, Exact, "8000000000000", Equal); test("1000000000000", 24, Exact, "16777216000000000000", Equal); test("1000000000000", 25, Exact, "33554432000000000000", Equal); test("1000000000000", 31, Exact, "2147483648000000000000", Equal); test("1000000000000", 32, Exact, "4294967296000000000000", Equal); test("1000000000000", 33, Exact, "8589934592000000000000", Equal); test( "1000000000000", 100, Exact, "1267650600228229401496703205376000000000000", Equal, ); }; } #[test] fn test_shl_round_signed() { apply_to_signeds!(test_shl_round_signed_helper); } macro_rules! shl_round_signed_fail_helper { ($t:ident) => { assert_panic!(Natural::from(123u32).shl_round_assign($t::NEGATIVE_ONE, Exact)); assert_panic!(Natural::from(123u32).shl_round_assign($t::exact_from(-100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shl_round_assign($t::NEGATIVE_ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shl_round_assign($t::exact_from(-100), Exact) ); assert_panic!(Natural::from(123u32).shl_round($t::NEGATIVE_ONE, Exact)); assert_panic!(Natural::from(123u32).shl_round($t::exact_from(-100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shl_round($t::NEGATIVE_ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shl_round($t::exact_from(-100), Exact) ); assert_panic!((&Natural::from(123u32)).shl_round($t::NEGATIVE_ONE, Exact)); assert_panic!((&Natural::from(123u32)).shl_round($t::exact_from(-100), Exact)); assert_panic!( (&Natural::from_str("1000000000001").unwrap()).shl_round($t::NEGATIVE_ONE, Exact) ); assert_panic!( (&Natural::from_str("1000000000001").unwrap()).shl_round($t::exact_from(-100), Exact) ); }; } #[test] fn shl_round_signed_fail() { apply_to_signeds!(shl_round_signed_fail_helper); } fn properties_helper() where Natural: Shr + ShlRound + ShlRoundAssign, for<'a> &'a Natural: ShlRound, Limb: ArithmeticCheckedShl + ShlRound, { natural_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { let mut mut_n = n.clone(); let o = mut_n.shl_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shl_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); if i < T::ZERO { assert_eq!((shifted >> i).cmp(&n), o); } match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } }); natural_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shl_round(T::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(Natural::ZERO.shl_round(i, rm), (Natural::ZERO, Equal)); }); unsigned_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { if n.arithmetic_checked_shl(i).is_some() { let (s, o) = n.shl_round(i, rm); assert_eq!((Natural::from(s), o), Natural::from(n).shl_round(i, rm)); } }); } #[test] fn shl_round_properties() { apply_fn_to_signeds!(properties_helper); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ShrRound; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_gen, unsigned_gen, unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_33, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shr::{ limbs_shr, limbs_shr_to_out, limbs_slice_shr_in_place, limbs_vec_shr_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_signed_pair_gen_var_2, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_triple_gen_var_5, }; use num::BigUint; use rug; use std::ops::{Shl, Shr, ShrAssign}; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_and_limbs_vec_shr_in_place() { let test = |limbs: &[Limb], bits: u64, out: &[Limb]| { assert_eq!(limbs_shr(limbs, bits), out); let mut limbs = limbs.to_vec(); limbs_vec_shr_in_place(&mut limbs, bits); assert_eq!(limbs, out); }; test(&[], 0, &[]); test(&[], 1, &[]); test(&[], 100, &[]); test(&[0, 0, 0], 0, &[0, 0, 0]); test(&[0, 0, 0], 1, &[0, 0, 0]); test(&[0, 0, 0], 100, &[]); test(&[1], 0, &[1]); test(&[1], 1, &[0]); test(&[3], 1, &[1]); test(&[122, 456], 1, &[61, 228]); test(&[123, 456], 0, &[123, 456]); test(&[123, 456], 1, &[61, 228]); test(&[123, 455], 1, &[2147483709, 227]); test(&[123, 456], 31, &[912, 0]); test(&[123, 456], 32, &[456]); test(&[123, 456], 100, &[]); test(&[256, 456], 8, &[3355443201, 1]); test(&[u32::MAX, 1], 1, &[u32::MAX, 0]); test(&[u32::MAX, u32::MAX], 32, &[u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_to_out() { let test = |out_before: &[Limb], limbs_in: &[Limb], bits: u64, carry: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_shr_to_out(&mut out, limbs_in, bits), carry); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[0, 0, 0], 1, 0, &[0, 0, 0, 10]); test(&[10, 10, 10, 10], &[1], 1, 0x80000000, &[0, 10, 10, 10]); test(&[10, 10, 10, 10], &[3], 1, 0x80000000, &[1, 10, 10, 10]); test(&[10, 10, 10, 10], &[122, 456], 1, 0, &[61, 228, 10, 10]); test( &[10, 10, 10, 10], &[123, 456], 1, 0x80000000, &[61, 228, 10, 10], ); test( &[10, 10, 10, 10], &[123, 455], 1, 0x80000000, &[2147483709, 227, 10, 10], ); test(&[10, 10, 10, 10], &[123, 456], 31, 246, &[912, 0, 10, 10]); test( &[10, 10, 10, 10], &[256, 456], 8, 0, &[3355443201, 1, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, 1], 1, 0x80000000, &[u32::MAX, 0, 10, 10], ); test( &[10, 10, 10, 10], &[u32::MAX, u32::MAX], 31, u32::MAX - 1, &[u32::MAX, 1, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shr_to_out_fail_1() { limbs_shr_to_out(&mut [10, 10], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shr_to_out_fail_2() { limbs_shr_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shr_to_out_fail_3() { limbs_shr_to_out(&mut [10, 10, 10], &[123, 456], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_shr_to_out_fail_4() { limbs_shr_to_out(&mut [10, 10, 10], &[123, 456], 100); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_shr_in_place() { let test = |limbs: &[Limb], bits: u64, carry: Limb, out: &[Limb]| { let mut limbs = limbs.to_vec(); assert_eq!(limbs_slice_shr_in_place(&mut limbs, bits), carry); assert_eq!(limbs, out); }; test(&[0, 0, 0], 1, 0, &[0, 0, 0]); test(&[1], 1, 0x80000000, &[0]); test(&[3], 1, 0x80000000, &[1]); test(&[122, 456], 1, 0, &[61, 228]); test(&[123, 456], 1, 0x80000000, &[61, 228]); test(&[123, 455], 1, 0x80000000, &[2147483709, 227]); test(&[123, 456], 31, 246, &[912, 0]); test(&[256, 456], 8, 0, &[3355443201, 1]); test(&[u32::MAX, 1], 1, 0x80000000, &[u32::MAX, 0]); test(&[u32::MAX, u32::MAX], 31, u32::MAX - 1, &[u32::MAX, 1]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_shr_in_place_fail_1() { limbs_slice_shr_in_place::(&mut [], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_shr_in_place_fail_2() { limbs_slice_shr_in_place::(&mut [123, 456], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_shr_in_place_fail_3() { limbs_slice_shr_in_place::(&mut [123, 456], 100); } fn test_shr_unsigned_helper(f: F) where Natural: Shr + ShrAssign, for<'a> &'a Natural: Shr, { let test = |s, v: u8, out| { let u = Natural::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("245", 1, "122"); test("246", 1, "123"); test("247", 1, "123"); test("491", 2, "122"); test("492", 2, "123"); test("493", 2, "123"); test("4127195135", 25, "122"); test("4127195136", 25, "123"); test("4127195137", 25, "123"); test("8254390271", 26, "122"); test("8254390272", 26, "123"); test("8254390273", 26, "123"); test("155921023828072216384094494261247", 100, "122"); test("155921023828072216384094494261248", 100, "123"); test("155921023828072216384094494261249", 100, "123"); test("4294967295", 1, "2147483647"); test("4294967296", 1, "2147483648"); test("4294967297", 1, "2147483648"); test("1000000000000", 0, "1000000000000"); test("7999999999999", 3, "999999999999"); test("8000000000000", 3, "1000000000000"); test("8000000000001", 3, "1000000000000"); test("16777216000000000000", 24, "1000000000000"); test("33554432000000000000", 25, "1000000000000"); test("2147483648000000000000", 31, "1000000000000"); test("4294967296000000000000", 32, "1000000000000"); test("8589934592000000000000", 33, "1000000000000"); test( "1267650600228229401496703205376000000000000", 100, "1000000000000", ); test("1000000000000", 10, "976562500"); test("980657949", 72, "0"); test("4294967295", 31, "1"); test("4294967295", 32, "0"); test("4294967296", 32, "1"); test("4294967296", 33, "0"); } #[test] fn test_shr_unsigned() { test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|u, v, out| { let rug_u = rug::Integer::from_str(u).unwrap(); let mut n = rug_u.clone(); n >>= v; assert_eq!(n.to_string(), out); let n = rug_u >> v; assert_eq!(n.to_string(), out); let num_u = BigUint::from_str(u).unwrap(); let n = num_u.clone() >> usize::exact_from(v); assert_eq!(n.to_string(), out); let n = &num_u >> usize::exact_from(v); assert_eq!(n.to_string(), out); }); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); } fn test_shr_signed_helper(f: F) where Natural: Shr + ShrAssign, for<'a> &'a Natural: Shr, { let test = |s, v: i8, out| { let u = Natural::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("245", 1, "122"); test("246", 1, "123"); test("247", 1, "123"); test("491", 2, "122"); test("492", 2, "123"); test("493", 2, "123"); test("4127195135", 25, "122"); test("4127195136", 25, "123"); test("4127195137", 25, "123"); test("8254390271", 26, "122"); test("8254390272", 26, "123"); test("8254390273", 26, "123"); test("155921023828072216384094494261247", 100, "122"); test("155921023828072216384094494261248", 100, "123"); test("155921023828072216384094494261249", 100, "123"); test("4294967295", 1, "2147483647"); test("4294967296", 1, "2147483648"); test("4294967297", 1, "2147483648"); test("1000000000000", 0, "1000000000000"); test("7999999999999", 3, "999999999999"); test("8000000000000", 3, "1000000000000"); test("8000000000001", 3, "1000000000000"); test("16777216000000000000", 24, "1000000000000"); test("33554432000000000000", 25, "1000000000000"); test("2147483648000000000000", 31, "1000000000000"); test("4294967296000000000000", 32, "1000000000000"); test("8589934592000000000000", 33, "1000000000000"); test( "1267650600228229401496703205376000000000000", 100, "1000000000000", ); test("1000000000000", 10, "976562500"); test("980657949", 72, "0"); test("4294967295", 31, "1"); test("4294967295", 32, "0"); test("4294967296", 32, "1"); test("4294967296", 33, "0"); test("0", 0, "0"); test("0", -10, "0"); test("123", 0, "123"); test("123", -1, "246"); test("123", -2, "492"); test("123", -25, "4127195136"); test("123", -26, "8254390272"); test("123", -100, "155921023828072216384094494261248"); test("2147483648", -1, "4294967296"); test("1000000000000", 0, "1000000000000"); test("1000000000000", -3, "8000000000000"); test("1000000000000", -24, "16777216000000000000"); test("1000000000000", -25, "33554432000000000000"); test("1000000000000", -31, "2147483648000000000000"); test("1000000000000", -32, "4294967296000000000000"); test("1000000000000", -33, "8589934592000000000000"); test( "1000000000000", -100, "1267650600228229401496703205376000000000000", ); } #[test] fn test_shr_signed() { test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|u, v, out| { let rug_u = rug::Integer::from_str(u).unwrap(); let mut n = rug_u.clone(); n >>= v; assert_eq!(n.to_string(), out); let n = rug_u >> v; assert_eq!(n.to_string(), out); }); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); } #[test] fn limbs_shr_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, bits)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_shr(&xs, bits)), Natural::from_owned_limbs_asc(xs) >> bits ); }); } #[test] fn limbs_shr_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_23::() .test_properties_with_config(&config, |(mut out, xs, bits)| { let old_out = out.clone(); let carry = limbs_shr_to_out(&mut out, &xs, bits); let len = xs.len(); let n = Natural::from_owned_limbs_asc(xs); let m = &n >> bits; assert_eq!(carry == 0, &m << bits == n); let mut xs = m.into_limbs_asc(); xs.resize(len, 0); let actual_xs = out[..len].to_vec(); assert_eq!(xs, actual_xs); assert_eq!(&out[len..], &old_out[len..]); }); } #[test] fn limbs_slice_shr_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_33::().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); let carry = limbs_slice_shr_in_place(&mut xs, bits); let n = Natural::from_owned_limbs_asc(old_xs); let m = &n >> bits; assert_eq!(carry == 0, &m << bits == n); let mut expected_limbs = m.into_limbs_asc(); expected_limbs.resize(xs.len(), 0); assert_eq!(xs, expected_limbs); }, ); } #[test] fn limbs_vec_shr_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16::().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); limbs_vec_shr_in_place(&mut xs, bits); let n = Natural::from_owned_limbs_asc(old_xs) >> bits; assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } fn unsigned_properties>() where Natural: Shl + Shr + ShrAssign, for<'a> &'a Natural: Shl + Shr + Shr + ShrRound, Limb: Shr, { natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n >>= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!(shifted <= n); assert_eq!((&n).shr_round(u, Floor).0, shifted); if u <= U::low_mask(U::WIDTH - 1) { let u = S::wrapping_from(u); assert_eq!(&n >> u, shifted); assert_eq!(n << -u, shifted); } }); natural_unsigned_unsigned_triple_gen_var_5::().test_properties(|(n, u, v)| { if let Some(sum) = u.checked_add(v) { assert_eq!(&n >> u >> v, n >> sum); } }); natural_gen().test_properties(|n| { assert_eq!(&n >> U::ZERO, n); }); unsigned_gen::().test_properties(|u| { assert_eq!(Natural::ZERO >> u, 0); }); unsigned_pair_gen_var_2::().test_properties(|(u, v)| { if let Some(shift) = v.checked_add(U::exact_from(Limb::WIDTH)) { assert_eq!(Natural::from(u) >> shift, 0); } if v < U::exact_from(Limb::WIDTH) { assert_eq!(u >> v, Natural::from(u) >> v); } }); } fn signed_properties() where Natural: Shr + ShrAssign + ShrRound, for<'a> &'a Natural: Shr, { natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n >>= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() >> i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(n.shr_round(i, Floor).0, shifted); }); natural_gen().test_properties(|n| { assert_eq!(&n >> T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Natural::ZERO >> i, 0); }); } #[test] fn shr_properties() { apply_fn_to_unsigned_signed_pairs!(unsigned_properties); apply_fn_to_signeds!(signed_properties); natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { let shifted = &n >> u; let mut rug_n = rug::Integer::from(&n); rug_n >>= u; assert_eq!(Natural::exact_from(&rug_n), shifted); assert_eq!( Natural::from(&(&BigUint::from(&n) >> usize::exact_from(u))), shifted ); assert_eq!( Natural::from(&(BigUint::from(&n) >> usize::exact_from(u))), shifted ); assert_eq!(Natural::exact_from(&(rug::Integer::from(&n) >> u)), shifted); }); natural_signed_pair_gen_var_2::().test_properties(|(n, i)| { let shifted = &n >> i; let mut rug_n = rug::Integer::from(&n); rug_n >>= i; assert_eq!(Natural::exact_from(&rug_n), shifted); assert_eq!(Natural::exact_from(&(rug::Integer::from(&n) >> i)), shifted); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/shr_round.rs ================================================ // Copyright © 2026 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 . #[cfg(not(feature = "32_bit_limbs"))] use core::cmp::Ordering::*; #[cfg(feature = "32_bit_limbs")] use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ ArithmeticCheckedShr, DivRound, DivisibleByPowerOf2, ShlRound, ShrRound, ShrRoundAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ signed_rounding_mode_pair_gen, unsigned_pair_gen_var_37, unsigned_rounding_mode_pair_gen, unsigned_signed_rounding_mode_triple_gen_var_1, unsigned_unsigned_rounding_mode_triple_gen_var_4, unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_20, unsigned_vec_unsigned_rounding_mode_triple_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::shr_round::{ limbs_shr_exact, limbs_shr_round, limbs_shr_round_nearest, limbs_shr_round_up, limbs_vec_shr_exact_in_place, limbs_vec_shr_round_in_place, limbs_vec_shr_round_nearest_in_place, limbs_vec_shr_round_up_in_place, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_rounding_mode_pair_gen, natural_signed_rounding_mode_triple_gen_var_2, natural_unsigned_pair_gen_var_4, natural_unsigned_pair_gen_var_10, natural_unsigned_rounding_mode_triple_gen_var_1, }; use std::ops::Shl; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_round_up_and_limbs_vec_shr_round_up_in_place() { let test = |limbs: &[Limb], bits: u64, out: &[Limb], o: Ordering| { let (s, o_alt) = limbs_shr_round_up(limbs, bits); assert_eq!(s, out); assert_eq!(o_alt, o); let mut limbs = limbs.to_vec(); assert_eq!(limbs_vec_shr_round_up_in_place(&mut limbs, bits), o); assert_eq!(limbs, out); }; test(&[1], 0, &[1], Equal); test(&[1], 1, &[1], Greater); test(&[3], 1, &[2], Greater); test(&[122, 456], 1, &[61, 228], Equal); test(&[123, 456], 0, &[123, 456], Equal); test(&[123, 456], 1, &[62, 228], Greater); test(&[123, 455], 1, &[2147483710, 227], Greater); test(&[123, 456], 31, &[913, 0], Greater); test(&[123, 456], 32, &[457], Greater); test(&[123, 456], 100, &[1], Greater); test(&[256, 456], 8, &[3355443201, 1], Equal); test(&[u32::MAX, 1], 1, &[0, 1], Greater); test(&[u32::MAX, u32::MAX], 32, &[0, 1], Greater); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_round_nearest_and_limbs_vec_shr_round_nearest_in_place() { let test = |limbs: &[Limb], bits: u64, out: &[Limb], o: Ordering| { let (s, o_alt) = limbs_shr_round_nearest(limbs, bits); assert_eq!(s, out); assert_eq!(o_alt, o); let mut limbs = limbs.to_vec(); assert_eq!(limbs_vec_shr_round_nearest_in_place(&mut limbs, bits), o); assert_eq!(limbs, out); }; test(&[], 0, &[], Equal); test(&[], 1, &[], Equal); test(&[], 100, &[], Equal); test(&[0, 0, 0], 0, &[0, 0, 0], Equal); test(&[0, 0, 0], 1, &[0, 0, 0], Equal); test(&[0, 0, 0], 100, &[], Equal); test(&[1], 0, &[1], Equal); test(&[1], 1, &[0], Less); test(&[3], 1, &[2], Greater); test(&[122, 456], 1, &[61, 228], Equal); test(&[123, 456], 0, &[123, 456], Equal); test(&[123, 456], 1, &[62, 228], Greater); test(&[123, 455], 1, &[2147483710, 227], Greater); test(&[123, 456], 31, &[912, 0], Less); test(&[123, 456], 32, &[456], Less); test(&[123, 456], 100, &[], Less); test(&[256, 456], 8, &[3355443201, 1], Equal); test(&[u32::MAX, 1], 1, &[0, 1], Greater); test(&[u32::MAX, u32::MAX], 32, &[0, 1], Greater); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_exact_and_limbs_vec_shr_exact_in_place() { let test = |limbs: &[Limb], bits: u64, out: Option>| { assert_eq!(limbs_shr_exact(limbs, bits), out); let mut limbs = limbs.to_vec(); if limbs_vec_shr_exact_in_place(&mut limbs, bits) { assert_eq!(Some(limbs), out); } else { assert_eq!(None, out); } }; test(&[1], 0, Some(vec![1])); test(&[1], 1, None); test(&[3], 1, None); test(&[122, 456], 1, Some(vec![61, 228])); test(&[123, 456], 0, Some(vec![123, 456])); test(&[123, 456], 1, None); test(&[123, 455], 1, None); test(&[123, 456], 31, None); test(&[123, 456], 32, None); test(&[123, 456], 100, None); test(&[256, 456], 8, Some(vec![3355443201, 1])); test(&[u32::MAX, 1], 1, None); test(&[u32::MAX, u32::MAX], 32, None); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_shr_round_and_limbs_vec_shr_round_in_place() { let test = |limbs: &[Limb], bits: u64, rm: RoundingMode, out: Option<&[Limb]>, o: Ordering| { if let Some((s, o_alt)) = limbs_shr_round(limbs, bits, rm) { assert_eq!(Some(s.as_slice()), out); assert_eq!(o_alt, o); } else { assert!(out.is_none()); } let mut limbs = limbs.to_vec(); let (b, o_alt) = limbs_vec_shr_round_in_place(&mut limbs, bits, rm); if b { assert_eq!(Some(limbs.as_slice()), out); } else { assert!(out.is_none()); } assert_eq!(o_alt, o); }; test(&[1], 0, Nearest, Some(&[1]), Equal); test(&[1], 1, Up, Some(&[1]), Greater); test(&[3], 1, Nearest, Some(&[2]), Greater); test(&[122, 456], 1, Floor, Some(&[61, 228]), Equal); test(&[123, 456], 0, Floor, Some(&[123, 456]), Equal); test(&[123, 456], 1, Down, Some(&[61, 228]), Less); test(&[123, 455], 1, Floor, Some(&[2147483709, 227]), Less); test(&[123, 456], 31, Ceiling, Some(&[913, 0]), Greater); test(&[123, 456], 32, Up, Some(&[457]), Greater); test(&[123, 456], 100, Down, Some(&[]), Less); test(&[256, 456], 8, Exact, Some(&[3355443201, 1]), Equal); test(&[u32::MAX, 1], 1, Exact, None, Equal); test(&[u32::MAX, u32::MAX], 32, Down, Some(&[u32::MAX]), Less); } fn test_shr_round_unsigned_helper() where Natural: ShrRound + ShrRoundAssign, for<'a> &'a Natural: ShrRound, { let test = |s, v: u8, rm: RoundingMode, out, o| { let u = Natural::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); assert_eq!(n.shr_round_assign(v, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shr_round(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "122", Less); test("245", 1, Up, "123", Greater); test("245", 1, Floor, "122", Less); test("245", 1, Ceiling, "123", Greater); test("245", 1, Nearest, "122", Less); test("246", 1, Down, "123", Equal); test("246", 1, Up, "123", Equal); test("246", 1, Floor, "123", Equal); test("246", 1, Ceiling, "123", Equal); test("246", 1, Nearest, "123", Equal); test("246", 1, Exact, "123", Equal); test("247", 1, Down, "123", Less); test("247", 1, Up, "124", Greater); test("247", 1, Floor, "123", Less); test("247", 1, Ceiling, "124", Greater); test("247", 1, Nearest, "124", Greater); test("491", 2, Down, "122", Less); test("491", 2, Up, "123", Greater); test("491", 2, Floor, "122", Less); test("491", 2, Ceiling, "123", Greater); test("491", 2, Nearest, "123", Greater); test("492", 2, Down, "123", Equal); test("492", 2, Up, "123", Equal); test("492", 2, Floor, "123", Equal); test("492", 2, Ceiling, "123", Equal); test("492", 2, Nearest, "123", Equal); test("492", 2, Exact, "123", Equal); test("493", 2, Down, "123", Less); test("493", 2, Up, "124", Greater); test("493", 2, Floor, "123", Less); test("493", 2, Ceiling, "124", Greater); test("493", 2, Nearest, "123", Less); test("4127195135", 25, Down, "122", Less); test("4127195135", 25, Up, "123", Greater); test("4127195135", 25, Floor, "122", Less); test("4127195135", 25, Ceiling, "123", Greater); test("4127195135", 25, Nearest, "123", Greater); test("4127195136", 25, Down, "123", Equal); test("4127195136", 25, Up, "123", Equal); test("4127195136", 25, Floor, "123", Equal); test("4127195136", 25, Ceiling, "123", Equal); test("4127195136", 25, Nearest, "123", Equal); test("4127195136", 25, Exact, "123", Equal); test("4127195137", 25, Down, "123", Less); test("4127195137", 25, Up, "124", Greater); test("4127195137", 25, Floor, "123", Less); test("4127195137", 25, Ceiling, "124", Greater); test("4127195137", 25, Nearest, "123", Less); test("8254390271", 26, Down, "122", Less); test("8254390271", 26, Up, "123", Greater); test("8254390271", 26, Floor, "122", Less); test("8254390271", 26, Ceiling, "123", Greater); test("8254390271", 26, Nearest, "123", Greater); test("8254390272", 26, Down, "123", Equal); test("8254390272", 26, Up, "123", Equal); test("8254390272", 26, Floor, "123", Equal); test("8254390272", 26, Ceiling, "123", Equal); test("8254390272", 26, Nearest, "123", Equal); test("8254390272", 26, Exact, "123", Equal); test("8254390273", 26, Down, "123", Less); test("8254390273", 26, Up, "124", Greater); test("8254390273", 26, Floor, "123", Less); test("8254390273", 26, Ceiling, "124", Greater); test("8254390273", 26, Nearest, "123", Less); test("155921023828072216384094494261247", 100, Down, "122", Less); test("155921023828072216384094494261247", 100, Up, "123", Greater); test("155921023828072216384094494261247", 100, Floor, "122", Less); test( "155921023828072216384094494261247", 100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "123", Greater, ); test("155921023828072216384094494261248", 100, Down, "123", Equal); test("155921023828072216384094494261248", 100, Up, "123", Equal); test( "155921023828072216384094494261248", 100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "123", Equal, ); test("155921023828072216384094494261249", 100, Down, "123", Less); test("155921023828072216384094494261249", 100, Up, "124", Greater); test("155921023828072216384094494261249", 100, Floor, "123", Less); test( "155921023828072216384094494261249", 100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "123", Less, ); test("4294967295", 1, Down, "2147483647", Less); test("4294967295", 1, Up, "2147483648", Greater); test("4294967295", 1, Floor, "2147483647", Less); test("4294967295", 1, Ceiling, "2147483648", Greater); test("4294967295", 1, Nearest, "2147483648", Greater); test("4294967296", 1, Down, "2147483648", Equal); test("4294967296", 1, Up, "2147483648", Equal); test("4294967296", 1, Floor, "2147483648", Equal); test("4294967296", 1, Ceiling, "2147483648", Equal); test("4294967296", 1, Nearest, "2147483648", Equal); test("4294967296", 1, Exact, "2147483648", Equal); test("4294967297", 1, Down, "2147483648", Less); test("4294967297", 1, Up, "2147483649", Greater); test("4294967297", 1, Floor, "2147483648", Less); test("4294967297", 1, Ceiling, "2147483649", Greater); test("4294967297", 1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "999999999999", Less); test("7999999999999", 3, Up, "1000000000000", Greater); test("7999999999999", 3, Floor, "999999999999", Less); test("7999999999999", 3, Ceiling, "1000000000000", Greater); test("7999999999999", 3, Nearest, "1000000000000", Greater); test("8000000000000", 3, Down, "1000000000000", Equal); test("8000000000000", 3, Up, "1000000000000", Equal); test("8000000000000", 3, Floor, "1000000000000", Equal); test("8000000000000", 3, Ceiling, "1000000000000", Equal); test("8000000000000", 3, Nearest, "1000000000000", Equal); test("8000000000000", 3, Exact, "1000000000000", Equal); test("8000000000001", 3, Down, "1000000000000", Less); test("8000000000001", 3, Up, "1000000000001", Greater); test("8000000000001", 3, Floor, "1000000000000", Less); test("8000000000001", 3, Ceiling, "1000000000001", Greater); test("8000000000001", 3, Nearest, "1000000000000", Less); test("16777216000000000000", 24, Down, "1000000000000", Equal); test("16777216000000000000", 24, Up, "1000000000000", Equal); test("16777216000000000000", 24, Floor, "1000000000000", Equal); test("16777216000000000000", 24, Ceiling, "1000000000000", Equal); test("16777216000000000000", 24, Nearest, "1000000000000", Equal); test("16777216000000000000", 24, Exact, "1000000000000", Equal); test("33554432000000000000", 25, Down, "1000000000000", Equal); test("33554432000000000000", 25, Up, "1000000000000", Equal); test("33554432000000000000", 25, Floor, "1000000000000", Equal); test("33554432000000000000", 25, Ceiling, "1000000000000", Equal); test("33554432000000000000", 25, Nearest, "1000000000000", Equal); test("33554432000000000000", 25, Exact, "1000000000000", Equal); test("2147483648000000000000", 31, Down, "1000000000000", Equal); test("2147483648000000000000", 31, Up, "1000000000000", Equal); test("2147483648000000000000", 31, Floor, "1000000000000", Equal); test( "2147483648000000000000", 31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", 31, Exact, "1000000000000", Equal); test("4294967296000000000000", 32, Down, "1000000000000", Equal); test("4294967296000000000000", 32, Up, "1000000000000", Equal); test("4294967296000000000000", 32, Floor, "1000000000000", Equal); test( "4294967296000000000000", 32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", 32, Exact, "1000000000000", Equal); test("8589934592000000000000", 33, Down, "1000000000000", Equal); test("8589934592000000000000", 33, Up, "1000000000000", Equal); test("8589934592000000000000", 33, Floor, "1000000000000", Equal); test( "8589934592000000000000", 33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", 33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", 100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1000000000000", Equal, ); test("1000000000000", 10, Down, "976562500", Equal); test("1000000000000", 10, Up, "976562500", Equal); test("1000000000000", 10, Floor, "976562500", Equal); test("1000000000000", 10, Ceiling, "976562500", Equal); test("1000000000000", 10, Nearest, "976562500", Equal); test("1000000000000", 10, Exact, "976562500", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "1", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "1", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "1", Less); test("4294967295", 31, Up, "2", Greater); test("4294967295", 31, Floor, "1", Less); test("4294967295", 31, Ceiling, "2", Greater); test("4294967295", 31, Nearest, "2", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "1", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "1", Greater); test("4294967295", 32, Nearest, "1", Greater); test("4294967296", 32, Down, "1", Equal); test("4294967296", 32, Up, "1", Equal); test("4294967296", 32, Floor, "1", Equal); test("4294967296", 32, Ceiling, "1", Equal); test("4294967296", 32, Nearest, "1", Equal); test("4294967296", 32, Exact, "1", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "1", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "1", Greater); test("4294967296", 33, Nearest, "0", Less); } #[test] fn test_shr_round_unsigned() { apply_fn_to_unsigneds!(test_shr_round_unsigned_helper); } macro_rules! shr_round_unsigned_fail_helper { ($t:ident) => { assert_panic!(Natural::from(123u32).shr_round_assign($t::ONE, Exact)); assert_panic!(Natural::from(123u32).shr_round_assign($t::exact_from(100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round_assign($t::ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round_assign($t::exact_from(100), Exact) ); assert_panic!(Natural::from(123u32).shr_round($t::ONE, Exact)); assert_panic!(Natural::from(123u32).shr_round($t::exact_from(100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round($t::ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round($t::exact_from(100), Exact) ); assert_panic!((&Natural::from(123u32)).shr_round($t::ONE, Exact)); assert_panic!((&Natural::from(123u32)).shr_round($t::exact_from(100), Exact)); assert_panic!((&Natural::from_str("1000000000001").unwrap()).shr_round($t::ONE, Exact)); assert_panic!( (&Natural::from_str("1000000000001").unwrap()).shr_round($t::exact_from(100), Exact) ); }; } #[test] fn shr_round_unsigned_fail() { apply_to_unsigneds!(shr_round_unsigned_fail_helper); } fn test_shr_round_signed_helper() where Natural: ShrRound + ShrRoundAssign, for<'a> &'a Natural: ShrRound, { let test = |s, j: i8, rm: RoundingMode, out, o| { let u = Natural::from_str(s).unwrap(); let j = T::from(j); let mut n = u.clone(); assert_eq!(n.shr_round_assign(j, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().shr_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).shr_round(j, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("245", 1, Down, "122", Less); test("245", 1, Up, "123", Greater); test("245", 1, Floor, "122", Less); test("245", 1, Ceiling, "123", Greater); test("245", 1, Nearest, "122", Less); test("246", 1, Down, "123", Equal); test("246", 1, Up, "123", Equal); test("246", 1, Floor, "123", Equal); test("246", 1, Ceiling, "123", Equal); test("246", 1, Nearest, "123", Equal); test("246", 1, Exact, "123", Equal); test("247", 1, Down, "123", Less); test("247", 1, Up, "124", Greater); test("247", 1, Floor, "123", Less); test("247", 1, Ceiling, "124", Greater); test("247", 1, Nearest, "124", Greater); test("491", 2, Down, "122", Less); test("491", 2, Up, "123", Greater); test("491", 2, Floor, "122", Less); test("491", 2, Ceiling, "123", Greater); test("491", 2, Nearest, "123", Greater); test("492", 2, Down, "123", Equal); test("492", 2, Up, "123", Equal); test("492", 2, Floor, "123", Equal); test("492", 2, Ceiling, "123", Equal); test("492", 2, Nearest, "123", Equal); test("492", 2, Exact, "123", Equal); test("493", 2, Down, "123", Less); test("493", 2, Up, "124", Greater); test("493", 2, Floor, "123", Less); test("493", 2, Ceiling, "124", Greater); test("493", 2, Nearest, "123", Less); test("4127195135", 25, Down, "122", Less); test("4127195135", 25, Up, "123", Greater); test("4127195135", 25, Floor, "122", Less); test("4127195135", 25, Ceiling, "123", Greater); test("4127195135", 25, Nearest, "123", Greater); test("4127195136", 25, Down, "123", Equal); test("4127195136", 25, Up, "123", Equal); test("4127195136", 25, Floor, "123", Equal); test("4127195136", 25, Ceiling, "123", Equal); test("4127195136", 25, Nearest, "123", Equal); test("4127195136", 25, Exact, "123", Equal); test("4127195137", 25, Down, "123", Less); test("4127195137", 25, Up, "124", Greater); test("4127195137", 25, Floor, "123", Less); test("4127195137", 25, Ceiling, "124", Greater); test("4127195137", 25, Nearest, "123", Less); test("8254390271", 26, Down, "122", Less); test("8254390271", 26, Up, "123", Greater); test("8254390271", 26, Floor, "122", Less); test("8254390271", 26, Ceiling, "123", Greater); test("8254390271", 26, Nearest, "123", Greater); test("8254390272", 26, Down, "123", Equal); test("8254390272", 26, Up, "123", Equal); test("8254390272", 26, Floor, "123", Equal); test("8254390272", 26, Ceiling, "123", Equal); test("8254390272", 26, Nearest, "123", Equal); test("8254390272", 26, Exact, "123", Equal); test("8254390273", 26, Down, "123", Less); test("8254390273", 26, Up, "124", Greater); test("8254390273", 26, Floor, "123", Less); test("8254390273", 26, Ceiling, "124", Greater); test("8254390273", 26, Nearest, "123", Less); test("155921023828072216384094494261247", 100, Down, "122", Less); test("155921023828072216384094494261247", 100, Up, "123", Greater); test("155921023828072216384094494261247", 100, Floor, "122", Less); test( "155921023828072216384094494261247", 100, Ceiling, "123", Greater, ); test( "155921023828072216384094494261247", 100, Nearest, "123", Greater, ); test("155921023828072216384094494261248", 100, Down, "123", Equal); test("155921023828072216384094494261248", 100, Up, "123", Equal); test( "155921023828072216384094494261248", 100, Floor, "123", Equal, ); test( "155921023828072216384094494261248", 100, Ceiling, "123", Equal, ); test( "155921023828072216384094494261248", 100, Nearest, "123", Equal, ); test( "155921023828072216384094494261248", 100, Exact, "123", Equal, ); test("155921023828072216384094494261249", 100, Down, "123", Less); test("155921023828072216384094494261249", 100, Up, "124", Greater); test("155921023828072216384094494261249", 100, Floor, "123", Less); test( "155921023828072216384094494261249", 100, Ceiling, "124", Greater, ); test( "155921023828072216384094494261249", 100, Nearest, "123", Less, ); test("4294967295", 1, Down, "2147483647", Less); test("4294967295", 1, Up, "2147483648", Greater); test("4294967295", 1, Floor, "2147483647", Less); test("4294967295", 1, Ceiling, "2147483648", Greater); test("4294967295", 1, Nearest, "2147483648", Greater); test("4294967296", 1, Down, "2147483648", Equal); test("4294967296", 1, Up, "2147483648", Equal); test("4294967296", 1, Floor, "2147483648", Equal); test("4294967296", 1, Ceiling, "2147483648", Equal); test("4294967296", 1, Nearest, "2147483648", Equal); test("4294967296", 1, Exact, "2147483648", Equal); test("4294967297", 1, Down, "2147483648", Less); test("4294967297", 1, Up, "2147483649", Greater); test("4294967297", 1, Floor, "2147483648", Less); test("4294967297", 1, Ceiling, "2147483649", Greater); test("4294967297", 1, Nearest, "2147483648", Less); test("1000000000000", 0, Down, "1000000000000", Equal); test("1000000000000", 0, Up, "1000000000000", Equal); test("1000000000000", 0, Floor, "1000000000000", Equal); test("1000000000000", 0, Ceiling, "1000000000000", Equal); test("1000000000000", 0, Nearest, "1000000000000", Equal); test("1000000000000", 0, Exact, "1000000000000", Equal); test("7999999999999", 3, Down, "999999999999", Less); test("7999999999999", 3, Up, "1000000000000", Greater); test("7999999999999", 3, Floor, "999999999999", Less); test("7999999999999", 3, Ceiling, "1000000000000", Greater); test("7999999999999", 3, Nearest, "1000000000000", Greater); test("8000000000000", 3, Down, "1000000000000", Equal); test("8000000000000", 3, Up, "1000000000000", Equal); test("8000000000000", 3, Floor, "1000000000000", Equal); test("8000000000000", 3, Ceiling, "1000000000000", Equal); test("8000000000000", 3, Nearest, "1000000000000", Equal); test("8000000000000", 3, Exact, "1000000000000", Equal); test("8000000000001", 3, Down, "1000000000000", Less); test("8000000000001", 3, Up, "1000000000001", Greater); test("8000000000001", 3, Floor, "1000000000000", Less); test("8000000000001", 3, Ceiling, "1000000000001", Greater); test("8000000000001", 3, Nearest, "1000000000000", Less); test("16777216000000000000", 24, Down, "1000000000000", Equal); test("16777216000000000000", 24, Up, "1000000000000", Equal); test("16777216000000000000", 24, Floor, "1000000000000", Equal); test("16777216000000000000", 24, Ceiling, "1000000000000", Equal); test("16777216000000000000", 24, Nearest, "1000000000000", Equal); test("16777216000000000000", 24, Exact, "1000000000000", Equal); test("33554432000000000000", 25, Down, "1000000000000", Equal); test("33554432000000000000", 25, Up, "1000000000000", Equal); test("33554432000000000000", 25, Floor, "1000000000000", Equal); test("33554432000000000000", 25, Ceiling, "1000000000000", Equal); test("33554432000000000000", 25, Nearest, "1000000000000", Equal); test("33554432000000000000", 25, Exact, "1000000000000", Equal); test("2147483648000000000000", 31, Down, "1000000000000", Equal); test("2147483648000000000000", 31, Up, "1000000000000", Equal); test("2147483648000000000000", 31, Floor, "1000000000000", Equal); test( "2147483648000000000000", 31, Ceiling, "1000000000000", Equal, ); test( "2147483648000000000000", 31, Nearest, "1000000000000", Equal, ); test("2147483648000000000000", 31, Exact, "1000000000000", Equal); test("4294967296000000000000", 32, Down, "1000000000000", Equal); test("4294967296000000000000", 32, Up, "1000000000000", Equal); test("4294967296000000000000", 32, Floor, "1000000000000", Equal); test( "4294967296000000000000", 32, Ceiling, "1000000000000", Equal, ); test( "4294967296000000000000", 32, Nearest, "1000000000000", Equal, ); test("4294967296000000000000", 32, Exact, "1000000000000", Equal); test("8589934592000000000000", 33, Down, "1000000000000", Equal); test("8589934592000000000000", 33, Up, "1000000000000", Equal); test("8589934592000000000000", 33, Floor, "1000000000000", Equal); test( "8589934592000000000000", 33, Ceiling, "1000000000000", Equal, ); test( "8589934592000000000000", 33, Nearest, "1000000000000", Equal, ); test("8589934592000000000000", 33, Exact, "1000000000000", Equal); test( "1267650600228229401496703205376000000000000", 100, Down, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Up, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Floor, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Ceiling, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Nearest, "1000000000000", Equal, ); test( "1267650600228229401496703205376000000000000", 100, Exact, "1000000000000", Equal, ); test("1000000000000", 10, Down, "976562500", Equal); test("1000000000000", 10, Up, "976562500", Equal); test("1000000000000", 10, Floor, "976562500", Equal); test("1000000000000", 10, Ceiling, "976562500", Equal); test("1000000000000", 10, Nearest, "976562500", Equal); test("1000000000000", 10, Exact, "976562500", Equal); test("980657949", 72, Down, "0", Less); test("980657949", 72, Up, "1", Greater); test("980657949", 72, Floor, "0", Less); test("980657949", 72, Ceiling, "1", Greater); test("980657949", 72, Nearest, "0", Less); test("4294967295", 31, Down, "1", Less); test("4294967295", 31, Up, "2", Greater); test("4294967295", 31, Floor, "1", Less); test("4294967295", 31, Ceiling, "2", Greater); test("4294967295", 31, Nearest, "2", Greater); test("4294967295", 32, Down, "0", Less); test("4294967295", 32, Up, "1", Greater); test("4294967295", 32, Floor, "0", Less); test("4294967295", 32, Ceiling, "1", Greater); test("4294967295", 32, Nearest, "1", Greater); test("4294967296", 32, Down, "1", Equal); test("4294967296", 32, Up, "1", Equal); test("4294967296", 32, Floor, "1", Equal); test("4294967296", 32, Ceiling, "1", Equal); test("4294967296", 32, Nearest, "1", Equal); test("4294967296", 32, Exact, "1", Equal); test("4294967296", 33, Down, "0", Less); test("4294967296", 33, Up, "1", Greater); test("4294967296", 33, Floor, "0", Less); test("4294967296", 33, Ceiling, "1", Greater); test("4294967296", 33, Nearest, "0", Less); test("0", -10, Exact, "0", Equal); test("123", -1, Exact, "246", Equal); test("123", -2, Exact, "492", Equal); test("123", -25, Exact, "4127195136", Equal); test("123", -26, Exact, "8254390272", Equal); test( "123", -100, Exact, "155921023828072216384094494261248", Equal, ); test("2147483648", -1, Exact, "4294967296", Equal); test("1000000000000", -3, Exact, "8000000000000", Equal); test("1000000000000", -24, Exact, "16777216000000000000", Equal); test("1000000000000", -25, Exact, "33554432000000000000", Equal); test("1000000000000", -31, Exact, "2147483648000000000000", Equal); test("1000000000000", -32, Exact, "4294967296000000000000", Equal); test("1000000000000", -33, Exact, "8589934592000000000000", Equal); test( "1000000000000", -100, Exact, "1267650600228229401496703205376000000000000", Equal, ); } #[test] fn test_shr_round_signed() { apply_fn_to_signeds!(test_shr_round_signed_helper); } macro_rules! shr_round_signed_fail_helper { ($t:ident) => { assert_panic!(Natural::from(123u32).shr_round_assign($t::ONE, Exact)); assert_panic!(Natural::from(123u32).shr_round_assign($t::exact_from(100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round_assign($t::ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round_assign($t::exact_from(100), Exact) ); assert_panic!(Natural::from(123u32).shr_round($t::ONE, Exact)); assert_panic!(Natural::from(123u32).shr_round($t::exact_from(100), Exact)); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round($t::ONE, Exact) ); assert_panic!( Natural::from_str("1000000000001") .unwrap() .shr_round($t::exact_from(100), Exact) ); assert_panic!((&Natural::from(123u32)).shr_round($t::ONE, Exact)); assert_panic!((&Natural::from(123u32)).shr_round($t::exact_from(100), Exact)); assert_panic!((&Natural::from_str("1000000000001").unwrap()).shr_round($t::ONE, Exact)); assert_panic!( (&Natural::from_str("1000000000001").unwrap()).shr_round($t::exact_from(100), Exact) ); }; } #[test] fn shr_round_signed_fail() { apply_to_signeds!(shr_round_signed_fail_helper); } #[test] fn limbs_shr_round_up_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, bits)| { let (s, o) = limbs_shr_round_up(&xs, bits); assert_eq!( (Natural::from_owned_limbs_asc(s), o), Natural::from_owned_limbs_asc(xs).shr_round(bits, Up), ); }); } #[test] fn limbs_shr_round_nearest_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, bits)| { let (s, o) = limbs_shr_round_nearest(&xs, bits); assert_eq!( (Natural::from_owned_limbs_asc(s), o), Natural::from_owned_limbs_asc(xs).shr_round(bits, Nearest), ); }); } #[test] fn limbs_shr_exact_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config(&config, |(xs, bits)| { let n = Natural::from_limbs_asc(&xs); limbs_shr_exact(&xs, bits).map_or_else( || { assert!(!n.divisible_by_power_of_2(bits)); }, |result_xs| { let (m, o) = (&n).shr_round(bits, Exact); assert_eq!(Natural::from_owned_limbs_asc(result_xs), m); assert_eq!(m << bits, n); assert_eq!(o, Equal); }, ); }); } #[test] fn limbs_shr_round_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().test_properties_with_config( &config, |(xs, bits, rm)| { let n = Natural::from_limbs_asc(&xs); limbs_shr_round(&xs, bits, rm).map_or_else( || { assert_eq!(rm, Exact); assert!(!n.divisible_by_power_of_2(bits)); }, |(result_xs, o)| { let (m, o_alt) = (&n).shr_round(bits, rm); assert_eq!(Natural::from_owned_limbs_asc(result_xs), m); assert_eq!(o, o_alt); if rm == Exact { assert_eq!(m << bits, n); } }, ); }, ); } #[test] fn limbs_vec_shr_round_up_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); let o = limbs_vec_shr_round_up_in_place(&mut xs, bits); let (n, o_alt) = Natural::from_owned_limbs_asc(old_xs).shr_round(bits, Up); assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(o, o_alt); }, ); } #[test] fn limbs_vec_shr_round_nearest_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, bits)| { let old_xs = xs.clone(); let o = limbs_vec_shr_round_nearest_in_place(&mut xs, bits); let (n, o_alt) = Natural::from_owned_limbs_asc(old_xs).shr_round(bits, Nearest); assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(o, o_alt); }, ); } #[test] fn limbs_vec_shr_exact_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_20().test_properties_with_config( &config, |(mut xs, bits)| { let n = Natural::from_limbs_asc(&xs); if limbs_vec_shr_exact_in_place(&mut xs, bits) { let (m, o) = (&n).shr_round(bits, Exact); assert_eq!(Natural::from_owned_limbs_asc(xs), m); assert_eq!(m << bits, n); assert_eq!(o, Equal); } else { assert!(!n.divisible_by_power_of_2(bits)); } }, ); } #[test] fn limbs_vec_shr_round_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_rounding_mode_triple_gen_var_2().test_properties_with_config( &config, |(mut xs, bits, rm)| { let n = Natural::from_limbs_asc(&xs); let (b, o) = limbs_vec_shr_round_in_place(&mut xs, bits, rm); if b { let (m, o_alt) = (&n).shr_round(bits, rm); assert_eq!(Natural::from_owned_limbs_asc(xs), m); assert_eq!(o, o_alt); if rm == Exact { assert_eq!(m << bits, n); } } else { assert_eq!(rm, Exact); assert!(!n.divisible_by_power_of_2(bits)); } }, ); } fn unsigned_properties() where Natural: Shl + ShrRound + ShrRoundAssign, for<'a> &'a Natural: Shl + ShrRound, Limb: ShrRound, { natural_unsigned_rounding_mode_triple_gen_var_1::().test_properties(|(n, u, rm)| { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(u, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o, o_alt); let (shifted_alt, o_alt) = n.clone().shr_round(u, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o, o_alt); assert!(shifted <= n); let (shifted_alt, o_alt) = (&n).div_round(Natural::ONE << u, rm); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); assert_eq!(n.divisible_by_power_of_2(u.exact_into()), o == Equal); assert_eq!((shifted << u).cmp(&n), o); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } }); natural_unsigned_pair_gen_var_4::().test_properties(|(n, u)| { let left_shifted = &n << u; let no = (n, Equal); assert_eq!((&left_shifted).shr_round(u, Down), no); assert_eq!((&left_shifted).shr_round(u, Up), no); assert_eq!((&left_shifted).shr_round(u, Floor), no); assert_eq!((&left_shifted).shr_round(u, Ceiling), no); assert_eq!((&left_shifted).shr_round(u, Nearest), no); assert_eq!((&left_shifted).shr_round(u, Exact), no); }); natural_unsigned_pair_gen_var_10::().test_properties(|(n, u)| { let down = (&n).shr_round(u, Down); let up = (&down.0 + Natural::ONE, Greater); assert_eq!((&n).shr_round(u, Up), up); assert_eq!((&n).shr_round(u, Floor), down); assert_eq!((&n).shr_round(u, Ceiling), up); let nearest = n.shr_round(u, Nearest); assert!(nearest == down || nearest == up); }); unsigned_pair_gen_var_37::().test_properties(|(u, v)| { if let Some(shift) = v.checked_add(T::exact_from(Limb::WIDTH)) { assert_eq!( Natural::from(u).shr_round(shift, Down), (Natural::ZERO, Less) ); assert_eq!( Natural::from(u).shr_round(shift, Floor), (Natural::ZERO, Less) ); assert_eq!( Natural::from(u).shr_round(shift, Up), (Natural::ONE, Greater) ); assert_eq!( Natural::from(u).shr_round(shift, Ceiling), (Natural::ONE, Greater) ); if let Some(extra_shift) = shift.checked_add(T::ONE) { assert_eq!( Natural::from(u).shr_round(extra_shift, Nearest), (Natural::ZERO, Less) ); } } }); natural_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shr_round(T::ZERO, rm), (n, Equal)); }); unsigned_rounding_mode_pair_gen::().test_properties(|(u, rm)| { assert_eq!(Natural::ZERO.shr_round(u, rm), (Natural::ZERO, Equal)); }); unsigned_unsigned_rounding_mode_triple_gen_var_4::().test_properties(|(n, u, rm)| { let (s, o) = n.shr_round(u, rm); assert_eq!((Natural::from(s), o), Natural::from(n).shr_round(u, rm)); }); } fn signed_properties() where Natural: Shl + ShlRound + ShrRound + ShrRoundAssign, for<'a> &'a Natural: ShlRound + ShrRound, Limb: ArithmeticCheckedShr + ShrRound, { natural_signed_rounding_mode_triple_gen_var_2::().test_properties(|(n, i, rm)| { let mut mut_n = n.clone(); let o = mut_n.shr_round_assign(i, rm); assert!(mut_n.is_valid()); let shifted = mut_n; let (shifted_alt, o_alt) = (&n).shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); let (shifted_alt, o_alt) = n.clone().shr_round(i, rm); assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); if i != T::MIN { let (shifted_alt, o_alt) = (&n).shl_round(-i, rm); assert_eq!(shifted_alt, shifted); assert_eq!(o_alt, o); } assert_eq!( i <= T::ZERO || n.divisible_by_power_of_2(i.exact_into()), o == Equal ); if i >= T::ZERO { assert_eq!((shifted << i).cmp(&n), o); } match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } }); natural_rounding_mode_pair_gen().test_properties(|(n, rm)| { assert_eq!((&n).shr_round(T::ZERO, rm), (n, Equal)); }); signed_rounding_mode_pair_gen::().test_properties(|(i, rm)| { assert_eq!(Natural::ZERO.shr_round(i, rm), (Natural::ZERO, Equal)); }); unsigned_signed_rounding_mode_triple_gen_var_1::().test_properties(|(n, i, rm)| { if n.arithmetic_checked_shr(i).is_some() { let (s, o) = n.shr_round(i, rm); assert_eq!((Natural::from(s), o), Natural::from(n).shr_round(i, rm)); } }); } #[test] fn shr_round_properties() { apply_fn_to_unsigneds!(unsigned_properties); apply_fn_to_signeds!(signed_properties); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::generators::unsigned_gen; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_sign() { let test = |s, out| { assert_eq!(Natural::from_str(s).unwrap().sign(), out); assert_eq!(rug::Integer::from_str(s).unwrap().cmp0(), out); }; test("0", Equal); test("123", Greater); test("1000000000000", Greater); } #[test] fn sign_properties() { natural_gen().test_properties(|n| { let sign = n.sign(); assert_eq!(rug::Integer::from(&n).cmp0(), sign); assert_ne!(sign, Less); assert_eq!(n.partial_cmp(&0), Some(sign)); assert_eq!((-n).sign(), sign.reverse()); }); unsigned_gen::().test_properties(|u| { assert_eq!(Natural::from(u).sign(), u.sign()); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::sqrt::sqrt_rem_2_newton; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::arithmetic::traits::{ CeilingRoot, CeilingSqrt, CeilingSqrtAssign, CheckedRoot, CheckedSqrt, FloorRoot, FloorSqrt, FloorSqrtAssign, RootRem, ShrRound, SqrtAssignRem, SqrtRem, Square, }; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ExactFrom, JoinHalves}; use malachite_base::num::logic::traits::BitAccess; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::logic::traits::LeadingZeros; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ large_type_gen_var_2, unsigned_gen, unsigned_pair_gen_var_31, unsigned_vec_gen_var_1, unsigned_vec_pair_gen_var_4, unsigned_vec_pair_gen_var_5, unsigned_vec_triple_gen_var_28, }; use malachite_nz::natural::arithmetic::sqrt::{ limbs_ceiling_sqrt, limbs_checked_sqrt, limbs_floor_sqrt, limbs_sqrt_helper, limbs_sqrt_rem, limbs_sqrt_rem_helper, limbs_sqrt_rem_helper_scratch_len, limbs_sqrt_rem_to_out, limbs_sqrt_to_out, }; use malachite_nz::natural::{Natural, limb_to_bit_count}; use malachite_nz::platform::{DoubleLimb, Limb, SignedLimb}; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::arithmetic::sqrt::{ ceiling_sqrt_binary, checked_sqrt_binary, floor_sqrt_binary, sqrt_rem_binary, }; use num::BigUint; use std::panic::catch_unwind; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_sqrt_rem_2_newton() { fn test(n_hi: Limb, n_lo: Limb, sqrt: Limb, r_hi: bool, r_lo: Limb) { assert_eq!( sqrt_rem_2_newton::(n_hi, n_lo), (sqrt, r_hi, r_lo) ); assert_eq!( DoubleLimb::from(sqrt) .square() .checked_add(DoubleLimb::join_halves(Limb::from(r_hi), r_lo)) .unwrap(), DoubleLimb::join_halves(n_hi, n_lo) ); } // - no adjustment needed test(2000000000, 123, 2930859019, false, 2746357762); test(u32::MAX, 123, 4294967295, true, 122); // - adjustment needed test(1073741825, 0, 2147483648, true, 0); } #[test] fn sqrt_rem_2_newton_fail() { assert_panic!(sqrt_rem_2_newton::(1, Limb::MAX)); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sqrt_rem_helper() { fn test(old_xs: &[Limb], n: usize, out_out: &[Limb], xs_out: &[Limb], r_hi: bool) { assert!(old_xs.len() >= n << 1); let mut out = vec![0; n]; let mut xs = old_xs.to_vec(); let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(n)]; assert_eq!( limbs_sqrt_rem_helper(&mut out, &mut xs, 0, &mut scratch), r_hi ); assert_eq!(out, out_out); assert_eq!(xs, xs_out); let x = Natural::from_limbs_asc(&old_xs[..n << 1]); let sqrt = Natural::from_limbs_asc(&out[..n]); let mut rem = Natural::from_limbs_asc(&xs[..n]); if r_hi { rem.set_bit(u64::exact_from(n) << Limb::LOG_WIDTH); } assert_eq!((&x).sqrt_rem(), (sqrt.clone(), rem.clone())); assert_eq!((&sqrt).square() + rem, x); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); } // - h2 == 1 // - !q // - r_hi // - h1 == h2 // - r_hi >= 0 test( &[123, 456, 789, 2000000000], 2, &[2012297342, 2930859019], &[1917624951, 2990305571, 2377342468, 942810576], false, ); // - !r_hi test(&[0, 0, 0, 1073741824], 2, &[0, 2147483648], &[0; 4], false); // - q // - r_hi < 0 test( &[0, 0, 0, 1073741825], 2, &[4294967295, 2147483648], &[4294967295, 1, 0, 0], false, ); // - h2 > 1 // - h1 != h2 test( &[0, 0, 0, 0, 0, 1073741824], 3, &[0, 0, 2147483648], &[0; 6], false, ); } #[test] fn limbs_sqrt_rem_helper_fail() { // - out too short assert_panic!({ let out = &mut []; let xs = &mut [1, 2, 3]; let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(out.len())]; limbs_sqrt_rem_helper(out, xs, 0, &mut scratch) }); // - xs too short assert_panic!({ let out = &mut [1, 2, 3]; let xs = &mut [1, 2, 3, 4, Limb::MAX]; let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(out.len())]; limbs_sqrt_rem_helper(out, xs, 0, &mut scratch) }); // - (2 * n - 1)th element of xs too small assert_panic!({ let out = &mut [1, 2, 3]; let xs = &mut [1, 2, 3, 4, 5, 6]; let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(out.len())]; limbs_sqrt_rem_helper(out, xs, 0, &mut scratch) }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sqrt_helper() { fn test(xs: &[Limb], out_out: &[Limb], has_remainder: bool) { let n = xs.len().shr_round(1, Ceiling).0; let odd = xs.len().odd(); let shift = LeadingZeros::leading_zeros(*xs.last().unwrap()) >> 1; let mut out = vec![0; n]; assert_eq!(limbs_sqrt_helper(&mut out, xs, shift, odd), has_remainder); assert_eq!(out, out_out); let x = Natural::from_limbs_asc(xs); let sqrt = Natural::from_limbs_asc(&out); let (sqrt_alt, rem) = (&x).sqrt_rem(); assert_eq!(sqrt, sqrt_alt); assert_eq!(has_remainder, rem != 0); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); } // - shift != 0 first time // - !q // - qs_last != 0 <= 1 // - (*qs_head >> 3) | qs_tail[0].mod_power_of_2(Limb::WIDTH - s) != 0 // - odd == 1 || shift != 0 test( &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[406519538, 874900746, 1431655766, 1, 3], true, ); // - q test( &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], &[1984678003, 1990369149, 2938805076, 123516853, 207243], true, ); // - (*qs_head >> 3) | qs_tail[0].mod_power_of_2(Limb::WIDTH - s) == 0 // - cmp != Less first time // - slice_test_zero(&scratch_hi[h1 + 1..h2 + 1]) // - cmp == Equal // - shift != 0 second time // - cmp != Less second time test(&[0, 0, 0, 0, 0, 0, 0, 0, 1], &[0, 0, 0, 0, 1], false); // - !slice_test_zero(&scratch_hi[h1 + 1..h2 + 1]) test( &[0, 0, 0, 0, 0, 0, 0, 1, 0, 1], &[4294959104, 4294967295, 32767, 0, 65536], true, ); // - cmp != Equal // - cmp == Less second time test( &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], &[4095, 0, 4294959104, 4294967295, 32767, 0, 65536], true, ); // - shift == 0 first time // - odd == 0 && shift == 0 test( &[ 2193991530, 2899278504, 3717617329, 1249076698, 879590153, 4210532297, 3303769392, 1147691304, 3624392894, 1881877405, 1728780505, 931615955, 1096404509, 1326003135, 370549396, 1987183422, 851586836, 2796582944, 2985872407, 2598301166, 356639089, 2071312376, 1106184443, 3682669872, 1019062633, 3091583269, 502719907, 1700144765, 1387866140, 1704631346, 2770368441, 1350352297, ], &[ 1761794912, 1811046967, 2629492573, 855368414, 1733978088, 3870361288, 2771154681, 1755982555, 443586875, 4077786862, 37569597, 1268220478, 2132005861, 2264846737, 2419409154, 2408260566, ], true, ); // - qs_last != 0 > 1 test( &[ 4294967295, 4194303, 0, 0, 3758096384, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, ], &[ 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 65535, ], true, ); // - shift == 0 second time test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294966784, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, ], &[ 4278190079, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 65535, ], true, ); // - cmp == Less first time test( &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294967232, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 2147483679, 16777215, 0, 0, 0, 0, 4294967040, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, ], &[ 4293920767, 1073741791, 0, 0, 0, 0, 3221217296, 8388607, 0, 0, 0, 0, 4294967168, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, ], true, ); } #[test] fn limbs_sqrt_helper_fail() { // - out too short assert_panic!({ let out = &mut [1, 2, 3, 4]; let xs = &mut [Limb::MAX; 8]; limbs_sqrt_helper(out, xs, 0, false); }); // - last element of xs is 0 assert_panic!({ let out = &mut [1, 2, 3, 4, 5]; let xs = &mut [10, 10, 10, 10, 10, 10, 10, 10, 10, 0]; limbs_sqrt_helper(out, xs, 15, false); }); // - shift too high assert_panic!({ let out = &mut [1, 2, 3, 4, 5]; let xs = &mut [Limb::MAX; 10]; limbs_sqrt_helper(out, xs, 16, false); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sqrt_to_out() { fn test(xs: &[Limb], out_out: &[Limb]) { let xs_len = xs.len(); let mut out = vec![0; xs_len.shr_round(1, Ceiling).0]; limbs_sqrt_to_out(&mut out, xs); assert_eq!(out, out_out); let x = Natural::from_limbs_asc(xs); let sqrt = Natural::from_owned_limbs_asc(out); assert_eq!((&x).floor_sqrt(), sqrt); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); } // - shift != 0 // - xs_len == 1 // - xs_len == 1 && shift != 0 test(&[1], &[1]); // - shift == 0 // - xs_len == 1 && shift == 0 test(&[4000000000], &[63245]); // - xs_len == 2 // - xs_len == 2 && shift != 0 test(&[1, 2], &[92681]); // - xs_len == 2 && shift == 0 test(&[1, 4000000000], &[4144860574]); // - xs_len > 2 // - 2 < xs_len <= 8 // - xs_len.odd() || shift != 0 // - xs_len > 2 && shift == 0 // - tn > 1 test(&[1, 2, 3], &[3144134278, 1]); // - xs_len > 2 && shift != 0 test(&[1, 2, 4000000000], &[2375990371, 63245]); // - xs_len > 8 test( &[ 2572912965, 1596092594, 2193991530, 2899278504, 3717617329, 1249076698, 879590153, 4210532297, 3303769392, 1147691304, 3624392894, ], &[3491190173, 18317336, 2518787533, 3220458996, 3998374718, 60202], ); // - xs_len.even() && shift == 0 test( &[345016311, 2711392466, 1490697280, 1246394087], &[2306404477, 2313703058], ); } #[test] fn limbs_sqrt_to_out_fail() { // - xs empty assert_panic!({ let out = &mut [1, 2, 3]; let xs = &mut []; limbs_sqrt_to_out(out, xs); }); // - out too short assert_panic!({ let out = &mut [1, 2, 3]; let xs = &mut [Limb::MAX; 8]; limbs_sqrt_to_out(out, xs); }); // - last element of xs is 0 assert_panic!({ let out = &mut [1, 2, 3]; let xs = &mut [1, 2, 3, 4, 5, 0]; limbs_sqrt_to_out(out, xs); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sqrt_rem_to_out() { fn test(xs: &[Limb], out_out_sqrt: &[Limb], out_out_rem: &[Limb]) { let xs_len = xs.len(); let mut out_sqrt = vec![0; xs_len.shr_round(1, Ceiling).0]; let mut out_rem = vec![0; xs_len]; let rem_len = limbs_sqrt_rem_to_out(&mut out_sqrt, &mut out_rem, xs); assert_eq!(out_sqrt, out_out_sqrt); assert_eq!(&out_rem[..rem_len], out_out_rem); let x = Natural::from_limbs_asc(xs); let sqrt = Natural::from_owned_limbs_asc(out_sqrt); let rem = Natural::from_limbs_asc(&out_rem[..rem_len]); let (sqrt_alt, rem_alt) = (&x).sqrt_rem(); assert_eq!(sqrt_alt, sqrt); assert_eq!(rem_alt, rem); assert_eq!((&sqrt).square() + &rem, x); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); } // - shift != 0 // - xs_len == 1 // - xs_len == 1 && shift != 0 test(&[1], &[1], &[]); // - shift == 0 // - xs_len == 1 && shift == 0 test(&[4000000000], &[63245], &[69975]); // - xs_len == 2 // - xs_len == 2 && shift != 0 test(&[1, 2], &[92681], &[166832]); // - xs_len == 2 && shift == 0 test(&[1, 4000000000], &[4144860574], &[1805423229, 1]); // - xs_len > 2 // - xs_len.odd() || shift != 0 // - xs_len > 2 && shift != 0 first time // - shift >= Limb::WIDTH // - xs_len > 2 && shift != 0 second time test(&[1, 2, 3], &[3144134278, 1], &[1429311965, 0]); // - xs_len > 2 && shift == 0 first time // - xs_len > 2 && shift == 0 second time test( &[1, 2, 4000000000], &[2375990371, 63245], &[3710546360, 103937], ); // - xs_len.even() && shift == 0 test( &[2977742827, 3919053323, 1548431690, 1948915452], &[733991603, 2893186501], &[2063111874, 210353161, 1], ); // - shift < Limb::WIDTH test( &[ 1347797001, 1439220470, 2750411815, 3145460224, 3430380546, 2707019846, 2327263540, 551116682, ], &[1077346225, 1488699754, 3604020692, 1538514909], &[4064782248, 3993147064, 4166228975, 2172636662, 0], ); } #[test] fn limbs_sqrt_rem_to_out_fail() { // - xs empty assert_panic!({ let out_sqrt = &mut [1, 2, 3]; let out_rem = &mut [0; 8]; let xs = &mut []; limbs_sqrt_rem_to_out(out_sqrt, out_rem, xs); }); // - out too short assert_panic!({ let out_sqrt = &mut [1, 2, 3]; let out_rem = &mut [0; 8]; let xs = &mut [Limb::MAX; 8]; limbs_sqrt_rem_to_out(out_sqrt, out_rem, xs); }); // - rem too short assert_panic!({ let out_sqrt = &mut [1, 2, 3, 4]; let out_rem = &mut [0; 7]; let xs = &mut [Limb::MAX; 8]; limbs_sqrt_rem_to_out(out_sqrt, out_rem, xs); }); // - last element of xs is 0 assert_panic!({ let out_sqrt = &mut [1, 2, 3]; let out_rem = &mut [0; 6]; let xs = &mut [1, 2, 3, 4, 5, 0]; limbs_sqrt_rem_to_out(out_sqrt, out_rem, xs); }); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_floor_sqrt() { fn test(xs: &[Limb], out: &[Limb]) { assert_eq!(limbs_floor_sqrt(xs), out); } test(&[1, 2, 3], &[3144134278, 1]); } #[test] fn limbs_floor_sqrt_fail() { // - xs empty assert_panic!(limbs_floor_sqrt(&[])); // - last element of xs is 0 assert_panic!(limbs_floor_sqrt(&[1, 2, 0])); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_ceiling_sqrt() { fn test(xs: &[Limb], out: &[Limb]) { assert_eq!(limbs_ceiling_sqrt(xs), out); } test(&[1, 2, 3], &[3144134279, 1]); } #[test] fn limbs_ceiling_sqrt_fail() { // - xs empty assert_panic!(limbs_ceiling_sqrt(&[])); // - last element of xs is 0 assert_panic!(limbs_ceiling_sqrt(&[1, 2, 0])); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_checked_sqrt() { fn test(xs: &[Limb], out: Option<&[Limb]>) { assert_eq!(limbs_checked_sqrt(xs), out.map(<[Limb]>::to_vec)); } test(&[1, 2, 3], None); test(&[0, 0, 1], Some(&[0, 1])); } #[test] fn limbs_checked_sqrt_fail() { // - xs empty assert_panic!(limbs_checked_sqrt(&[])); // - last element of xs is 0 assert_panic!(limbs_checked_sqrt(&[1, 2, 0])); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sqrt_rem() { fn test(xs: &[Limb], out_sqrt: &[Limb], out_rem: &[Limb]) { let (sqrt, rem) = limbs_sqrt_rem(xs); assert_eq!(sqrt, out_sqrt); assert_eq!(rem, out_rem); } test(&[1, 2, 3], &[3144134278, 1], &[1429311965, 0]); } #[test] fn limbs_sqrt_rem_fail() { // - xs empty assert_panic!(limbs_sqrt_rem(&[])); // - last element of xs is 0 assert_panic!(limbs_sqrt_rem(&[1, 2, 0])); } #[test] fn test_floor_sqrt() { let test = |s, out| { let n = Natural::from_str(s).unwrap(); assert_eq!(n.clone().floor_sqrt().to_string(), out); assert_eq!((&n).floor_sqrt().to_string(), out); assert_eq!(floor_sqrt_binary(&n).to_string(), out); let mut n = n; n.floor_sqrt_assign(); assert_eq!(n.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "1"); test("3", "1"); test("4", "2"); test("5", "2"); test("10", "3"); test("100", "10"); test("1000000000", "31622"); test("152415765279683", "12345677"); test("152415765279684", "12345678"); test("152415765279685", "12345678"); test( "10000000000000000000000000000000000000000", "100000000000000000000", ); test( "100000000000000000000000000000000000000000", "316227766016837933199", ); } #[test] fn test_ceiling_sqrt() { let test = |s, out| { let n = Natural::from_str(s).unwrap(); assert_eq!(n.clone().ceiling_sqrt().to_string(), out); assert_eq!((&n).ceiling_sqrt().to_string(), out); assert_eq!(ceiling_sqrt_binary(&n).to_string(), out); let mut n = n; n.ceiling_sqrt_assign(); assert_eq!(n.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "2"); test("3", "2"); test("4", "2"); test("5", "3"); test("10", "4"); test("100", "10"); test("1000000000", "31623"); test("152415765279683", "12345678"); test("152415765279684", "12345678"); test("152415765279685", "12345679"); test( "10000000000000000000000000000000000000000", "100000000000000000000", ); test( "100000000000000000000000000000000000000000", "316227766016837933200", ); } #[allow(clippy::redundant_closure_for_method_calls)] #[test] fn test_checked_sqrt() { let test = |s, out: Option<&str>| { let n = Natural::from_str(s).unwrap(); let out = out.map(|s| s.to_string()); assert_eq!(n.clone().checked_sqrt().map(|x| x.to_string()), out); assert_eq!((&n).checked_sqrt().map(|x| x.to_string()), out); assert_eq!(checked_sqrt_binary(&n).map(|x| x.to_string()), out); }; test("0", Some("0")); test("1", Some("1")); test("2", None); test("3", None); test("4", Some("2")); test("5", None); test("10", None); test("100", Some("10")); test("1000000000", None); test("152415765279683", None); test("152415765279684", Some("12345678")); test("152415765279685", None); test( "10000000000000000000000000000000000000000", Some("100000000000000000000"), ); test("100000000000000000000000000000000000000000", None); } #[test] fn test_sqrt_rem() { let test = |s, sqrt_out, rem_out| { let n = Natural::from_str(s).unwrap(); let (sqrt, rem) = n.clone().sqrt_rem(); assert_eq!(sqrt.to_string(), sqrt_out); assert_eq!(rem.to_string(), rem_out); let (sqrt, rem) = (&n).sqrt_rem(); assert_eq!(sqrt.to_string(), sqrt_out); assert_eq!(rem.to_string(), rem_out); let (sqrt, rem) = sqrt_rem_binary(&n); assert_eq!(sqrt.to_string(), sqrt_out); assert_eq!(rem.to_string(), rem_out); let mut n = n; assert_eq!(n.sqrt_assign_rem().to_string(), rem_out); assert_eq!(n.to_string(), sqrt_out); }; test("0", "0", "0"); test("1", "1", "0"); test("2", "1", "1"); test("3", "1", "2"); test("4", "2", "0"); test("5", "2", "1"); test("10", "3", "1"); test("100", "10", "0"); test("1000000000", "31622", "49116"); test("152415765279683", "12345677", "24691354"); test("152415765279684", "12345678", "0"); test("152415765279685", "12345678", "1"); test( "10000000000000000000000000000000000000000", "100000000000000000000", "0", ); test( "100000000000000000000000000000000000000000", "316227766016837933199", "562477137586013626399", ); } #[test] fn sqrt_rem_2_newton_properties() { unsigned_pair_gen_var_31().test_properties(|(n_hi, n_lo)| { let (sqrt, r_hi, r_lo) = sqrt_rem_2_newton::(n_hi, n_lo); assert_eq!( DoubleLimb::from(sqrt) .square() .checked_add(DoubleLimb::join_halves(Limb::from(r_hi), r_lo)) .unwrap(), DoubleLimb::join_halves(n_hi, n_lo) ); }); } #[test] fn limbs_sqrt_rem_helper_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_4().test_properties_with_config(&config, |(mut out, mut xs)| { let n = out.len(); let mut scratch = vec![0; limbs_sqrt_rem_helper_scratch_len(n)]; let old_xs = xs.clone(); let r_hi = limbs_sqrt_rem_helper(&mut out, &mut xs, 0, &mut scratch); let x = Natural::from_limbs_asc(&old_xs[..n << 1]); let sqrt = Natural::from_limbs_asc(&out); let mut rem = Natural::from_limbs_asc(&xs[..n]); if r_hi { rem.set_bit(limb_to_bit_count(n)); } assert_eq!((&x).sqrt_rem(), (sqrt.clone(), rem.clone())); assert_eq!((&sqrt).square() + rem, x); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); }); } #[test] fn limbs_sqrt_helper_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_2().test_properties_with_config(&config, |(mut out, xs, shift, odd)| { let has_remainder = limbs_sqrt_helper(&mut out, &xs, shift, odd); let x = Natural::from_limbs_asc(&xs); let sqrt = Natural::from_limbs_asc(&out); let (sqrt_alt, rem) = (&x).sqrt_rem(); assert_eq!(sqrt, sqrt_alt); assert_eq!(has_remainder, rem != 0); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); }); } #[test] fn limbs_sqrt_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_5().test_properties_with_config(&config, |(mut out, xs)| { limbs_sqrt_to_out(&mut out, &xs); let xs_len = xs.len(); let sqrt_len = xs_len.shr_round(1, Ceiling).0; let x = Natural::from_limbs_asc(&xs); let sqrt = Natural::from_limbs_asc(&out[..sqrt_len]); assert_eq!((&x).floor_sqrt(), sqrt); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); }); } #[test] fn limbs_sqrt_rem_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_28().test_properties_with_config( &config, |(mut out_sqrt, mut out_rem, xs)| { let rem_len = limbs_sqrt_rem_to_out(&mut out_sqrt, &mut out_rem, &xs); let xs_len = xs.len(); let sqrt_len = xs_len.shr_round(1, Ceiling).0; let x = Natural::from_limbs_asc(&xs); let sqrt = Natural::from_limbs_asc(&out_sqrt[..sqrt_len]); let rem = Natural::from_limbs_asc(&out_rem[..rem_len]); let (sqrt_alt, rem_alt) = (&x).sqrt_rem(); assert_eq!(sqrt_alt, sqrt); assert_eq!(rem_alt, rem); assert_eq!((&sqrt).square() + &rem, x); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); }, ); } #[test] fn limbs_floor_sqrt_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let sqrt = Natural::from_owned_limbs_asc(limbs_floor_sqrt(&xs)); let x = Natural::from_owned_limbs_asc(xs); assert_eq!((&x).floor_sqrt(), sqrt); assert!((&sqrt).square() <= x); assert!((sqrt + Natural::ONE).square() > x); }); } #[test] fn limbs_ceiling_sqrt_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let sqrt = Natural::from_owned_limbs_asc(limbs_ceiling_sqrt(&xs)); let x = Natural::from_owned_limbs_asc(xs); assert_eq!((&x).ceiling_sqrt(), sqrt); assert!((&sqrt).square() >= x); assert!((sqrt - Natural::ONE).square() < x); }); } #[test] fn limbs_checked_sqrt_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let sqrt = limbs_checked_sqrt(&xs).map(Natural::from_owned_limbs_asc); let x = Natural::from_owned_limbs_asc(xs); assert_eq!((&x).checked_sqrt(), sqrt); if let Some(sqrt) = sqrt { assert_eq!(sqrt.square(), x); } }); } #[test] fn limbs_sqrt_rem_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let (sqrt, rem) = limbs_sqrt_rem(&xs); let sqrt = Natural::from_owned_limbs_asc(sqrt); let rem = Natural::from_owned_limbs_asc(rem); let x = Natural::from_owned_limbs_asc(xs); assert_eq!((&sqrt).square() + &rem, x); assert_eq!((&x).sqrt_rem(), (sqrt, rem)); }); } #[test] fn floor_sqrt_properties() { natural_gen().test_properties(|n| { let sqrt = n.clone().floor_sqrt(); assert_eq!((&n).floor_sqrt(), sqrt); let mut n_alt = n.clone(); n_alt.floor_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(floor_sqrt_binary(&n), sqrt); assert_eq!((&n).floor_root(2), sqrt); assert_eq!(Natural::from(&BigUint::from(&n).sqrt()), sqrt); assert_eq!(Natural::exact_from(&rug::Integer::from(&n).sqrt()), sqrt); let square = (&sqrt).square(); let ceiling_sqrt = (&n).ceiling_sqrt(); if square == n { assert_eq!(ceiling_sqrt, sqrt); } else { assert_eq!(ceiling_sqrt, &sqrt + Natural::ONE); } assert!(square <= n); assert!((sqrt + Natural::ONE).square() > n); }); unsigned_gen::().test_properties(|u| { assert_eq!(u.floor_sqrt(), Natural::from(u).floor_sqrt()); }); } #[test] fn ceiling_sqrt_properties() { natural_gen().test_properties(|n| { let sqrt = n.clone().ceiling_sqrt(); assert_eq!((&n).ceiling_sqrt(), sqrt); let mut n_alt = n.clone(); n_alt.ceiling_sqrt_assign(); assert_eq!(n_alt, sqrt); assert_eq!(ceiling_sqrt_binary(&n), sqrt); assert_eq!((&n).ceiling_root(2), sqrt); let square = (&sqrt).square(); let floor_sqrt = (&n).floor_sqrt(); if square == n { assert_eq!(floor_sqrt, sqrt); } else { assert_eq!(floor_sqrt, &sqrt - Natural::ONE); } assert!(square >= n); if n != 0 { assert!((sqrt - Natural::ONE).square() < n); } }); unsigned_gen::().test_properties(|u| { assert_eq!(u.ceiling_sqrt(), Natural::from(u).ceiling_sqrt()); }); } #[test] fn checked_sqrt_properties() { natural_gen().test_properties(|n| { let sqrt = n.clone().checked_sqrt(); assert_eq!((&n).checked_sqrt(), sqrt); assert_eq!(checked_sqrt_binary(&n), sqrt); assert_eq!((&n).checked_root(2), sqrt); if let Some(sqrt) = sqrt { assert_eq!((&sqrt).square(), n); assert_eq!((&n).floor_sqrt(), sqrt); assert_eq!(n.ceiling_sqrt(), sqrt); } }); unsigned_gen::().test_properties(|u| { assert_eq!( u.checked_sqrt().map(Natural::from), Natural::from(u).checked_sqrt() ); }); } #[test] fn sqrt_rem_properties() { natural_gen().test_properties(|n| { let (sqrt, rem) = n.clone().sqrt_rem(); assert_eq!((&n).sqrt_rem(), (sqrt.clone(), rem.clone())); let mut n_alt = n.clone(); assert_eq!(n_alt.sqrt_assign_rem(), rem); assert_eq!(n_alt, sqrt); assert_eq!(sqrt_rem_binary(&n), (sqrt.clone(), rem.clone())); assert_eq!((&n).root_rem(2), (sqrt.clone(), rem.clone())); let (rug_sqrt, rug_rem) = rug::Integer::from(&n).sqrt_rem(rug::Integer::new()); assert_eq!(Natural::exact_from(&rug_sqrt), sqrt); assert_eq!(Natural::exact_from(&rug_rem), rem); assert_eq!((&n).floor_sqrt(), sqrt); assert!(rem <= &sqrt << 1); assert_eq!(sqrt.square() + rem, n); }); unsigned_gen::().test_properties(|u| { let (sqrt, rem) = u.sqrt_rem(); assert_eq!( (Natural::from(sqrt), Natural::from(rem)), Natural::from(u).sqrt_rem() ); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase, CheckedLogBase2, CheckedSqrt, PowerOf2, Square, SquareAssign, }; use malachite_base::num::basic::integers::PrimitiveInt; #[cfg(feature = "32_bit_limbs")] use malachite_base::test_util::common::rle_decode; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_gen_var_21; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::square::{ limbs_square_to_out_basecase, limbs_square_to_out_toom_4, limbs_square_to_out_toom_4_scratch_len, limbs_square_to_out_toom_6, limbs_square_to_out_toom_6_scratch_len, limbs_square_to_out_toom_8, limbs_square_to_out_toom_8_scratch_len, }; use malachite_nz::natural::arithmetic::square::{ limbs_square_to_out_toom_2, limbs_square_to_out_toom_2_scratch_len, limbs_square_to_out_toom_3, limbs_square_to_out_toom_3_scratch_len, }; use malachite_nz::platform::Limb; #[cfg(feature = "32_bit_limbs")] use malachite_nz::platform::SQR_TOOM2_THRESHOLD; use malachite_nz::test_util::generators::{ natural_gen, natural_pair_gen, unsigned_vec_pair_gen_var_22, unsigned_vec_pair_gen_var_23, unsigned_vec_pair_gen_var_24, unsigned_vec_pair_gen_var_25, unsigned_vec_pair_gen_var_27, unsigned_vec_pair_gen_var_28, }; use malachite_nz::test_util::natural::arithmetic::square::limbs_square_to_out_basecase_unrestricted; use std::str::FromStr; fn limbs_square_basecase_helper_1( out_before: &[Limb], xs: &[Limb], out_after: &[Limb], ) -> Vec { let mut out = out_before.to_vec(); let old_out = out.clone(); limbs_square_to_out_basecase_unrestricted(&mut out, xs); assert_eq!(out, out_after); let n = Natural::from_limbs_asc(xs).square(); let len = xs.len() << 1; let mut limbs = n.into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); out } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_to_out_basecase() { let test = |out_before: &[Limb], xs: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); limbs_square_to_out_basecase(&mut out, xs); assert_eq!(out, out_after); }; test(&[10; 3], &[0], &[0, 0, 10]); test(&[10; 3], &[5], &[25, 0, 10]); test(&[10; 6], &[1, 2, 3], &[1, 4, 10, 12, 9, 0]); test( &[10; 6], &[u32::MAX, u32::MAX], &[1, 0, u32::MAX - 1, u32::MAX, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_basecase_fail_1() { let mut out = vec![10; 3]; limbs_square_to_out_basecase(&mut out, &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_basecase_fail_2() { let mut out = vec![10; 3]; limbs_square_to_out_basecase(&mut out, &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_basecase_fail_3() { let mut out = vec![0; (SQR_TOOM2_THRESHOLD + 1) << 1]; limbs_square_to_out_basecase(&mut out, &[10; SQR_TOOM2_THRESHOLD + 1]); } #[test] fn test_limbs_square_to_out_toom_2() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_to_out_toom_2_scratch_len(xs.len())]; limbs_square_to_out_toom_2(&mut out, xs, &mut scratch); assert_eq!(out, out_after); }; #[cfg(feature = "32_bit_limbs")] { test(&[0, 0], &[10; 5], &[0, 0, 0, 0, 10]); // - s == n // - limbs_cmp_same_length(&a0[..n], &a1[..n]) != Less // - !TOOM2MAYBE_SQR_TOOM2 || a.len() < SQR_TOOM2_THRESHOLD in // limbs_square_to_out_toom_2recursive // - cy <= 2 test(&[1, 1], &[10; 5], &[1, 2, 1, 0, 10]); // - limbs_cmp_same_length(&a0[..n], &a1[..n]) == Less test(&[123, 456], &[10; 5], &[15129, 112176, 207936, 0, 10]); // - s != n // - a0[s] == 0 && limbs_cmp_same_length(&a0[..s], &a1[..s]) == Less test(&[0, 0, 1], &[0, 0, 0, 0, 0, 0], &[0, 0, 0, 0, 1, 0]); // - !(a0[s] == 0 && limbs_cmp_same_length(&a0[..s], &a1[..s]) == Less) test(&[0, 1, 1], &[0, 0, 0, 0, 0, 0], &[0, 0, 1, 2, 1, 0]); // - TOOM2MAYBE_SQR_TOOM2 && a.len() >= SQR_TOOM2_THRESHOLD in // limbs_square_to_out_toom_2recursive test( &[ 315937763, 473311027, 567550122, 1916950171, 4059671672, 732330624, 3931833255, 435611156, 3441308858, 1231108682, 571470188, 1643911325, 1855842520, 890506741, 4051150309, 1624118035, 4095320898, 832808382, 254544287, 367192823, 3029770132, 2530961358, 168199720, 556928054, 3574899773, 901884181, 3037235269, 2537532649, 3638603141, 3105834733, 756731319, 2666260459, 3459942852, 3113152432, 2490378291, 2524064262, 2837473716, 970558109, 1280992412, 3025351268, 1176324257, 3832993853, 2960008574, 143054238, 2025124021, 3355284231, 3700222977, 959518197, 836633203, 1753652842, 3863610502, 3683672960, 2678694928, 3768243585, 2643427081, 2597841461, 809616697, 2770459249, 938499903, 2306605358, 806972689, 462004905, 1559140947, 880982517, 4000827930, 1625323545, 2071445194, 3924145010, 3049042401, 3015341713, 2642970230, 680495934, 3572593922, 3776563282, 3584817478, 1511664158, 1048142251, 1261635752, 2674531050, 1166719307, 3811800408, 3532080230, 853430491, 2558475297, 2417944189, 3094847515, 654669385, 2934541460, 2625633289, 4100222514, 1517941214, 3805734203, 3486264903, 2658767168, 1176863503, 2377983813, 4010981779, 1334807591, 3581560372, 231495094, 2680779981, 953071754, 1140610841, 4139855852, 515631497, 845705671, 505532954, 1555952001, 1319192795, 523566796, 738834566, 2397343480, 3709100568, 2754977717, 2105634100, 2622287225, 3069665844, 1499378188, 1024995116, 529523547, 1573018435, 2475374120, 3949433831, 748808472, 1404353612, 3021083538, 1713559320, 706538487, 1788875531, 3976761851, 1912518906, 3712335343, 3425283422, 281500646, 1572406350, 108746052, 4056047843, 89307364, 1006007374, 2902260577, 1250995384, 1556873818, 3846421711, 280743259, 1728158805, 467926284, 2330565417, 1366395459, 474848905, 1190711031, 4146575846, 1359337485, 277106601, 611834097, 4135958043, 2404499652, 3266860581, 4084179847, 1694432029, 2659591080, 438254541, 2191377959, 2215296842, 4215722030, 1219192120, 2382641840, 3275049666, 1893229486, 3003341825, 1385119378, 491641953, 3636318537, 409287515, 1702143228, 3653042335, 2210372129, 3091759374, 3445226074, 283146383, 1663694381, 1455499100, 306155088, 3031133107, 30443875, 336170015, 3291741077, 1240501199, 206913137, 1160607143, 2885974827, 3313462225, 4194793586, 2065489618, 3883470150, 4055315445, 582773660, 2582421365, 1454136391, 3061250840, 3468396503, 3488155264, 3029987831, 3156489841, 3463417120, 290496437, 4073099736, 180400746, 2106957818, 2769052442, 108172964, 284413173, 3344416865, 2269676748, 1574448658, 1902898868, 2316487593, 2771218024, 559367309, 3806016235, 2226674034, 1387375714, 3568612053, 673940445, 953264754, 1654240319, 2440830479, 283579272, 3231076957, 3939738751, 1493681204, 3397390673, 202532089, 820322467, 3747993335, 219997922, 1605225930, 4131306261, 1601302257, 521986372, 2770985700, 1963676063, 1439552511, 3555657222, 2250141846, 2503842498, 1970558797, 4169645939, 650372536, 1069598113, 707461834, 2970635546, 4043174034, 1642439873, 4249605930, 453278516, 1404882141, 2914837424, 1989551821, 1391677255, 2183893344, 1584545759, 1373876512, 2646970263, 246551016, 1589680164, 3758709566, 1942743739, 3244781899, 3123447530, 327409007, 2868166556, 3076801053, 2736084122, 3120784427, 199119660, 2691390162, 2174609870, 3758152774, 3735826978, 379752927, 619293957, 1527231068, 2991592006, 2710895459, 704686889, 4267216023, 2557068229, 1719941939, 78238238, 2962383502, 2393733803, 1004503772, 4066720355, 2075559616, 4243473886, 3935513315, 1002981165, 3794209454, 1615720966, 1568227265, 1813739753, 3362817192, 3305123208, 396682192, 4129516924, 882778042, 2077448918, 3646338728, 3577300535, 2457120647, 3540612431, 1671071497, 2995114160, 2400776059, 842998576, 3518689093, 4224316739, 1023092271, 1070023790, 603487484, 1374775086, 3498521370, 1323561470, 4087319908, 2455563164, 2011118687, 495516162, 3626408376, 672930363, 996279995, 981700082, 3228699492, 2150767183, 519151136, 1312076022, 1336129777, 4010423712, 2637820943, 2292814695, 942739251, 949393103, 2458673154, 768725091, 1832836796, 453300228, 4261116655, 1701896567, 2144567659, 3699180161, 3087788471, 2755320709, 1748927126, 2706369429, 3729051121, 1295882152, 3846117499, 4120997689, 3272456369, 3495028726, 3839821698, 3333310547, 3768072175, 945089968, 3361639032, 3268636237, 2279991624, 3672799919, 1759060635, 2771604505, 1771544561, 2787457919, 440535646, 2504067590, 3105361213, 353200529, 2099162584, 378937981, 3561464661, 3915066715, 2729297678, 2088428747, 710187304, 3736425617, 1392889178, 4161612762, 3599125244, 2012759904, 1706559215, 1741496559, 1644051828, 3760773690, 1619711282, 3088530914, 828541325, 1116610363, 812269687, 1076986782, 3303686357, 1446933100, 4010678422, 1326813853, 2348597983, 570937405, 3521228878, 2567079846, 2753504122, 4168927609, 4114588897, 4058328886, 3726683252, 251974901, 1610363499, 2152010449, 2300844173, 2883860828, 2276005572, 2627023715, 2700844654, 2659717603, 3243052767, 382173215, 2253713687, 1545258562, 2782986095, 334263358, 2481258310, 2291585918, 1380546066, 1861205162, 1395600128, 1509813785, 1715266614, 3251195596, 3140058077, 1998653517, 3140019184, 2534426976, 844092771, 4270350187, 424082283, 3804651493, 2962777391, 32884830, 1331871085, 2047357436, 2562052720, 1663431404, 2097420816, 199104030, 1685999636, 2207406189, 3119926828, 654294011, 3715835629, 3855214036, 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, 952637669, 1228316620, 165464703, 4219993004, 2243168861, 3690831859, 1956297624, 2833425905, 2707262033, 2571314297, 388071395, 1896528257, 1225824551, 81572020, 1409232203, 1080694913, 2547917588, 621110800, 2702861568, 2198117710, 1555339014, 2581264646, 138377579, 2293745610, 3914562495, 2918275417, 75829334, 1774985081, 2747349051, 1950994159, 394477872, 316913102, 461555308, 3548648328, 1617956386, 3126524770, 3123423878, 2182889796, 1568800505, 4279897761, 3333589672, 3792226100, 993443061, 1159842193, 2865953114, 2512277991, 1357746528, 3671513246, 2616265767, 1074303241, 2050907943, 268286549, 498690132, 4283094777, 2802371317, 3676403238, 2934500589, 281990329, 3074366974, 3387527201, 157777380, 2405204656, 142578723, 3660296423, 736731392, 1974042455, 1159614597, 4162674193, 1332482037, 1658304045, 2913005509, 481813632, 3626506485, 3221737748, 1374358866, 3827774417, 3308590869, 2205316972, 2619601751, 1879495531, 1688667307, 3945492802, 949715752, 165718259, 2529864207, 4033163217, 1627807449, 814761495, 2394041772, 163917860, 4137152849, 871080750, 2809100301, 126889608, 3338024033, 1570788701, 4067509056, 680440343, 3399634957, 1674234215, 2430678482, 1482962229, 3917262730, 2701308470, 3764650279, 4224967620, 509844418, 2494825785, 3803774464, 368493499, 4238556118, 4030415682, 3643742328, 2586387240, 3719633661, 3755880620, 2176876728, 2496909862, 111654638, 4071443844, 1244732003, 1399710541, 3492272815, 2804216879, 294683567, 2823495183, 1539340600, 2732661048, 2371405604, 611094747, 2426195984, 3948451542, 3575143460, 2163084716, 2877537071, 1849282685, 1662381818, 2022577840, 552741512, 1863034519, 2109621858, 3426780715, 233006082, 2766239663, 1257764921, 1179443268, 3311729910, 4228711990, 3676801557, 83336617, 52963853, 1461131367, 615175494, 2376138249, 1373985035, 3055102427, 1823691121, 175073115, 3051957217, 2611956643, 8092274, 4103495923, 2566129626, 66490664, 347807097, 730572423, 583932817, 2193587874, 1998219581, 3806043908, 3146127947, 3440818438, 4105053798, 806574510, 2647710257, 213825364, 1827399426, 3250558290, 4022072337, 2163344675, 1249293165, 94983795, 1430041053, 3690143296, 2906241747, 3282031769, 1948701801, 706760835, 4153647095, 3843998199, 2077172825, 1158686949, 3157624247, 3424621906, 4056374038, 3423674225, 511889851, 1745449688, 2554422250, 3004747460, 3576364631, 325806114, 1453902201, 1181646483, 784925267, 2018211516, 1758948179, 3236113206, 2773633419, 2329747557, 1612586727, 2954856193, 349470489, 4039284565, 2170178879, 641328078, 2932878730, 2057036386, 3758698550, 1389788861, 905696645, 322846493, 622200893, 2990601641, 779473385, 1637467878, 273757826, 1187850568, 3072937718, 3191465645, 3858350034, 2959907236, 2299744720, 2690960451, 2949783744, 1102614926, 1689432656, 934117703, 1940112928, 3379564708, 4199340399, 1881321211, 3929726949, 459862695, 1350630556, 2137584308, 1243785894, 983397001, 140271427, 1266031183, 3559919295, 702977622, 3883080853, 1830599918, 3030922777, 2650241556, 2807154392, 2218698435, 1904442293, 2992923456, 1481791037, 4079300846, 2680084216, 656285791, 3396057405, 272065717, 766725345, 1681255263, 1707458816, 1535744308, 3830462997, 1607479268, 3475252676, 933054715, 4058518411, 1139150315, 1176656025, 2657461768, 3149905151, 2833828072, 1407836276, 189062495, 3008111084, 3911286362, 3969377587, 520858887, 1921886086, 2410034665, 1853865087, 1218625232, 3157059817, 1933332942, 1324005415, 2613648167, 575584498, 1622716448, 2776523679, ], &[10; 1600], &[ 2337798985, 1719809325, 1766146956, 1432871059, 1913282470, 932051231, 2253427743, 3337839354, 174212766, 2418943939, 1818195854, 1795016853, 2023061831, 65726280, 1576822705, 2489110480, 1755680124, 1010622883, 2410047067, 2957950721, 3821505888, 2029055790, 919813873, 1454524914, 302707966, 2263686386, 664775132, 1441592353, 2668276189, 1029874670, 412976722, 3461537739, 165618775, 2805755420, 3986913245, 3750850515, 3911747004, 1709726859, 1430494098, 892950310, 4242511728, 500894641, 3512661539, 2383455966, 3902393679, 560808026, 1002183845, 3645493779, 2496237617, 1188317615, 1160331230, 4049090763, 2880495307, 2497687381, 756372816, 3883382263, 1412825102, 2798212291, 423470242, 1304918648, 2518462534, 1602052053, 3195498278, 1567441227, 4149369335, 3579099384, 722916608, 219424070, 3527901104, 1360861314, 3127386676, 1175600452, 2707542312, 2622395649, 4068363495, 3280638003, 2049563983, 3599786937, 1642977740, 19557413, 3844757830, 143230124, 3229601666, 1815836866, 2078167034, 1978389011, 4052689102, 3596571824, 2305736773, 3086821173, 2783854453, 3475178187, 2809907276, 56497958, 3665195047, 1855481649, 1557213590, 3186218749, 1579659414, 150730557, 2380493806, 1190332347, 750653467, 971803647, 4051923874, 2632706878, 961664618, 504169243, 3226989251, 176983832, 940067439, 3293538260, 2637791019, 2191083272, 3752981185, 2657937635, 4070370999, 4174783071, 419043165, 3539337388, 2961294405, 2250070055, 2129849842, 387044251, 570402960, 2429786867, 1321852772, 3796327549, 3651696376, 48730390, 660939665, 951624653, 1018250603, 1969566385, 3101262553, 2638971565, 1283036253, 172956163, 1683623272, 2766676731, 2164693596, 4149757659, 1029834025, 2691905287, 2446385107, 1005918892, 4205867169, 3216497085, 3428921101, 1770814161, 3015757934, 3464827848, 2494805438, 4035181431, 2179278559, 1424330, 1495619547, 3264150186, 3878153512, 2533738492, 138095927, 3968650904, 2988833739, 1178707551, 1851845851, 3283468943, 4205297379, 706168803, 520798040, 1611948341, 1295934146, 3768257794, 3872350135, 73022895, 2256463338, 1559961103, 279286159, 3232753970, 708275492, 1289339849, 2043694079, 2524360705, 2745749567, 1949784728, 1216039087, 3116384382, 1740530329, 3607118652, 4122786400, 530757090, 552544450, 4258552404, 1083733061, 1242098549, 4033981212, 204615559, 2161166767, 1611351590, 1176002643, 92570843, 1842133474, 650271884, 187375074, 1991479387, 1465587133, 1104658610, 2335293990, 214374954, 2350932521, 3814143087, 4138623525, 1116785125, 1647270088, 3109205647, 1522224221, 1795795952, 4049380771, 2003489406, 2717299085, 3865480913, 483542617, 1812810600, 976115739, 1874969238, 3323862135, 3433813421, 684253543, 2649590287, 1373773333, 485552995, 2472189256, 2945214935, 794984346, 1746460381, 1757396273, 1743887526, 298380984, 1352704452, 3966715730, 4113217885, 1241297473, 2453395403, 2954244651, 3774288543, 1444839196, 1548334790, 1122875432, 4121317990, 3947157568, 2712619444, 4223807490, 4005476489, 2308148699, 2684648139, 612866543, 1452041438, 2217463262, 4199719912, 3956456988, 1855047341, 2513694528, 4275971633, 2747007746, 557514185, 1719154861, 1529793338, 889576708, 3968812169, 2510679393, 803503931, 2692261222, 4080870372, 1511006235, 2711504643, 975058190, 4061501572, 2837215732, 2193743263, 4181374242, 2506045727, 2059941818, 2631701397, 4223127935, 2130862853, 142213618, 780119847, 1085548982, 2585032692, 1428661966, 2131060363, 667385220, 1225586380, 4242414988, 3975059186, 339067021, 4069839975, 4207550632, 767730479, 1439311207, 3446124465, 4246386072, 2908059873, 3369915408, 3255651336, 3020663495, 3546510376, 803064470, 76924606, 3832623942, 4020318607, 2730283796, 2953477768, 1922322168, 2956148578, 2539451553, 3716309785, 3125952755, 2075479202, 776522024, 2500281600, 4171655545, 2729325135, 34251037, 1476015613, 4199561321, 469926930, 2222437139, 4029482883, 3407168764, 828942664, 3994809377, 1646421728, 4162196041, 1109742320, 583773405, 932723359, 2529525319, 312357632, 2879219364, 1065489156, 132224124, 515226881, 2446629197, 171479349, 3993018508, 3278247564, 2928823997, 4231434757, 2985885115, 1806357710, 170081371, 2586404971, 53743121, 3915349183, 4256978965, 1282122127, 1334176954, 2896736246, 3168160222, 2723155581, 3801770034, 2474069641, 3914138112, 1703132960, 3050910113, 4000063991, 1156533771, 4197722875, 322247103, 2828309651, 1418664555, 3855814973, 2969749183, 670899946, 3684238847, 315272562, 1479787957, 3630248247, 3896795856, 2284924078, 3448742593, 2587913739, 2159727850, 4271757822, 2635451852, 1460173359, 514583636, 172745403, 305115099, 1158098813, 846374874, 4085016243, 2073661719, 3009482284, 2414138245, 3524500656, 388867611, 249517102, 3006883043, 4017176253, 2805544688, 3976760186, 630506689, 1780244360, 2737306104, 232231247, 1782076434, 387667825, 19793987, 2435181870, 2071669258, 764507081, 4155368519, 1451401907, 2360299858, 2330980099, 248454712, 3446078666, 2051966307, 2583383245, 706199696, 1890612504, 430574014, 2138787679, 2072311300, 737930085, 1521104440, 1585866980, 3120273, 3745204278, 3810187595, 901979488, 73759262, 3666590185, 875095827, 2485005683, 91444278, 997368547, 1551767372, 2677837051, 2596775070, 2673462320, 3055136566, 2778177188, 2822170891, 856301750, 717584730, 2775561644, 3235679827, 156925055, 4291892081, 938088712, 3712668621, 259963917, 188910174, 649460518, 1817160593, 3709183455, 2402569350, 2081244206, 1509583715, 159399436, 1005960034, 1584342275, 2708952291, 2083036721, 1827439806, 1920055605, 3099081841, 1505885624, 2705667938, 2970467008, 238736756, 680180549, 4265559140, 2686154915, 1275991160, 3321354017, 2666491064, 3391755967, 3136520967, 3492830782, 3080081809, 3240774903, 3389225939, 3016812645, 2761181256, 2165228292, 2154406921, 2542813197, 1465309996, 1179307147, 2930429249, 3040580106, 1976482529, 922355195, 3971063173, 277150860, 731857282, 3242189049, 1177214447, 3390437917, 3079667926, 1364420250, 1590973945, 2232278086, 232355078, 2582462161, 4037245230, 1049343960, 902676573, 4050492428, 1639129006, 3718138732, 3141580653, 766367797, 936894223, 1660677846, 628659564, 3365679999, 2561586784, 2229241133, 765418610, 782213348, 3067170394, 2191065093, 2774229638, 1023995363, 2412486840, 1635182131, 3748032748, 3129138020, 3607863873, 1174858263, 3616713190, 4187572066, 1546395074, 2027798083, 809553599, 1094121220, 3654162279, 1622703946, 148537568, 2385824297, 4061752858, 2543105581, 2622844203, 232849043, 3196673684, 2978718963, 1149528105, 2668110812, 2785402592, 3000100584, 1104866593, 70336191, 3432727170, 1109464777, 3746930874, 370280554, 3173358988, 3028594704, 2568130308, 457794435, 3383280274, 3346977517, 3484110806, 3153332792, 2425789545, 1474803746, 1781168328, 1989549162, 1032111952, 1331522816, 576372512, 1501541893, 2363428250, 1240303586, 2086180513, 3295867599, 691258190, 1008095124, 1776518245, 1495400690, 1519584986, 161360441, 1772372163, 4268396252, 2962917231, 2427675136, 2392936739, 272706848, 2620154363, 3998849772, 145937813, 4086621724, 1362430997, 1197771365, 4043072616, 916377810, 744218349, 1540693771, 2677728030, 553310668, 4229748447, 2011546593, 1970733497, 348172273, 762490238, 2152384213, 3411715628, 963109640, 3705793619, 3279035870, 426700692, 4278708730, 3586142296, 947806688, 1271342014, 715263589, 3455580436, 947104307, 1544685336, 2935774907, 2880317443, 3966149687, 2185422218, 2734810890, 3501513946, 2776353382, 4018451746, 2143808119, 736225303, 285334126, 2476018967, 3181930537, 2187294402, 3466164771, 2701302654, 3965790213, 2725436454, 3988416777, 3703472799, 1987980159, 923281388, 500013102, 74776770, 305061946, 3071827551, 486104690, 1384936530, 2111519171, 4124986050, 2429853625, 4015640194, 1966593586, 3123465599, 3341712852, 4213415239, 2396791960, 2722817611, 3004299255, 3857147942, 3516645579, 2072674201, 4175316375, 1683909736, 839905161, 316481248, 1683979804, 322038557, 677362982, 2973808772, 2596414587, 2730969268, 631888150, 1120341313, 1741270077, 3073620475, 1271943658, 1569862398, 3466496720, 4035716713, 2628306778, 2724723494, 1112102889, 3113513358, 2206163467, 2242575348, 2370657615, 3589371005, 1709622823, 2134510725, 3551117280, 3530138199, 922367384, 2890039831, 3559757981, 2345560704, 4221190559, 2332246771, 947123098, 3646442248, 488399645, 93684888, 851205014, 1145927652, 2376994496, 3976460398, 1154212282, 957935206, 353710365, 389412511, 1861961516, 3877610160, 1563516521, 1691953718, 1806258524, 4051249633, 2608084101, 1791724368, 4265828682, 98939002, 1131349528, 3141506279, 3747754883, 326404000, 2478362343, 2588680395, 2143336059, 3872805152, 720855604, 3231146872, 4275393682, 3215503747, 921660765, 2211457002, 29403278, 3071719374, 1901061486, 2988763100, 2195689231, 2111188612, 311057207, 1729785466, 339631061, 2566255664, 3558053739, 3017329992, 1834837913, 3911826467, 3826490857, 2838519210, 757698577, 3906322785, 4201094194, 828603290, 285313241, 2371084832, 3768763374, 4233968501, 2691202024, 3896400582, 2354807465, 1716960373, 377187758, 608315962, 612112524, 1866928118, 698937084, 3816198943, 980195413, 309169402, 3078719903, 3432153242, 2612946281, 3514540944, 1049878875, 3323542228, 3935174984, 3091793763, 2991245938, 3124186421, 2329117733, 4292494429, 3470963710, 1841188513, 2240113560, 996388563, 666396431, 140044984, 3132435687, 633020765, 385791735, 3533664654, 3369755757, 121447338, 3171287490, 1099415033, 3453496166, 2706291058, 2916008410, 2132445090, 3625133577, 2720560195, 205034264, 2411022473, 1225251622, 3873743850, 1878792569, 502287331, 2162793456, 4157617048, 837095026, 102278594, 4160514510, 3816646879, 1992533021, 191007446, 2727236802, 129396988, 613409573, 3431367662, 2099891725, 1930966876, 3122423745, 1075336928, 863500290, 1570806513, 3846730261, 393471418, 2624737608, 2647735688, 691426271, 3857369437, 1117350889, 3803433479, 1203945720, 486509596, 2702784498, 2971427393, 3372426095, 3448620625, 504644590, 2331180067, 1754142124, 3989228411, 3173048257, 2864751203, 2554761519, 3900913911, 1061646112, 3932675694, 658022597, 617264464, 343231796, 3115501645, 3550409916, 74722842, 1255450930, 2831976136, 1240738374, 1193141623, 1676518965, 262041809, 394954934, 2219224532, 1441157802, 2927116538, 3501791300, 4176181037, 1666097702, 4152025817, 2970386591, 1834278661, 207867662, 2514518143, 3049374496, 1354176149, 1820727688, 2928930650, 3260452331, 3926267804, 4240562748, 611877548, 4128238218, 1421140789, 1585228831, 1946949310, 3958532496, 812912156, 1645465057, 2509683759, 349966819, 2396774296, 2965066365, 3761846427, 1231196649, 409766126, 430753233, 599727165, 545964841, 3825372245, 3623870288, 40038191, 2884208155, 3417332481, 35141341, 680406210, 3702828808, 4118568845, 731073893, 3607543676, 3868323054, 4067601050, 398479428, 792773465, 1353851383, 1392719352, 4029808759, 4021129172, 796278946, 3939062404, 1195296489, 1756744309, 1001193500, 2465821931, 509185625, 3191666804, 3687287932, 1874396329, 1969891759, 1678441456, 2667925867, 407814354, 3603659969, 3800228642, 120101583, 3424508412, 1520495793, 357902760, 3271308342, 1286919855, 2382756661, 4274587703, 1127960573, 866377732, 3518954640, 1286199460, 661518652, 3127729633, 1529991009, 3425483485, 3157156519, 2726813487, 2701731704, 2083479105, 2893033595, 4240983598, 1299967832, 4080212138, 1905892689, 1858214875, 3672725881, 1081535884, 174040383, 3896862135, 3010343151, 4061479962, 3572367057, 1510459761, 3360785724, 1087858215, 57335744, 820510676, 530845883, 4228688641, 3696711033, 2135986325, 3913568995, 179524639, 3658604236, 2806792625, 2316354532, 1051562581, 3907381452, 2034461972, 178565993, 1284664272, 504824744, 3099567341, 2469345824, 3658913004, 992022622, 2786623537, 1021202198, 616895091, 2113750936, 1970082270, 3116426075, 3366259439, 585641047, 1328830246, 2258836941, 1322082749, 2241797667, 3399199649, 892467755, 2102971037, 1617097228, 4217502934, 974168861, 207492006, 2121251711, 3696018919, 1120006335, 1446317229, 3759235761, 3849699334, 3914866958, 626085181, 2420743789, 207902456, 1160796838, 790516805, 3187963410, 1515106146, 1296852237, 4089144091, 4241451860, 2783094488, 892183279, 338178727, 3053725583, 265766843, 623486416, 3796894823, 4202268968, 717565135, 2342024161, 870503465, 7128667, 1592323423, 3245656364, 4067369565, 1962250035, 816069811, 4232891752, 1558892228, 1888603643, 2666913616, 1404984687, 1433926934, 1743547609, 4112246183, 2021577654, 3544918251, 2020707701, 76188917, 1820900427, 2354637472, 1284257266, 3136451484, 1141115948, 1840829393, 4188399303, 802488874, 2059431097, 2804849229, 3775794144, 202946897, 765182653, 1168548737, 586672791, 3563384658, 981277056, 3279509061, 2445793196, 64294419, 1062640550, 2175903265, 2304846254, 2637942449, 2075197790, 3502280781, 3858345076, 4216378544, 2289775386, 4139983440, 4063679757, 3287916447, 1524609875, 997055195, 3660166441, 134003661, 3205014674, 2978476890, 966447865, 2850295105, 2243044897, 2061254489, 2262245077, 4083038201, 2257930427, 3015088005, 4145891046, 1511251913, 2595200020, 3831470358, 2985310963, 476732156, 224979971, 1156465354, 764683574, 4214444004, 3261415121, 3429123803, 1523213339, 4245223903, 956158970, 2891732999, 2765282146, 3400683065, 1587606157, 2046079544, 1389905331, 87824577, 1777986777, 3384203137, 4108947902, 3482879397, 77745361, 2507275334, 1986893298, 4022922416, 733916179, 3139522709, 2999889833, 1161829779, 3605866360, 3134683460, 1728850270, 101032362, 62872782, 3248731114, 3862793560, 806307801, 1524032149, 3064849448, 4077118848, 502698332, 2947670365, 3513995935, 1827518528, 3167131171, 2509065020, 4042175975, 2127503650, 3059544483, 2518990490, 2579930555, 3651523255, 1289189775, 4267073320, 4253053136, 1213724392, 3151111200, 590705794, 3805447266, 3183254479, 2646011908, 1917642749, 430090695, 2498363140, 3589876748, 2624132115, 862795528, 568833509, 910667954, 1592134880, 1702960475, 2406368070, 3705761960, 1626081901, 2311944971, 1460097114, 2239030549, 4037205008, 4273988634, 1412019747, 2720054955, 1955567590, 112988394, 2557385250, 3008605370, 3633217123, 2655501518, 3036362106, 3626585998, 3056603934, 175647684, 2736699914, 1284866439, 2063512562, 2760127268, 529053475, 1262482220, 2324393750, 2930386123, 506365850, 2068269090, 3640453693, 2392681207, 3657296390, 3557179631, 4229254256, 2832847420, 3127293618, 1056645988, 1784949673, 4137331301, 339663936, 2042994969, 707619349, 1267257087, 176084099, 204051889, 3609720855, 1203172342, 2503775670, 1897808209, 1819022477, 738716411, 2467366231, 1314393857, 3943102895, 560966695, 2733358928, 4155172253, 3318993281, 478303408, 3297724926, 1480431524, 2011292966, 4204677255, 598093968, 125630774, 802875169, 3174837530, 2200212794, 2531478045, 3528472075, 2409062863, 3624879168, 1298461038, 300487657, 921301375, 3034772385, 2870175987, 2489528255, 1422650999, 1959898718, 2148368644, 3530668930, 1343992028, 3420621297, 3185617672, 2169713229, 1381510115, 1759851866, 1671105009, 1972863997, 451922074, 2574366942, 2565022677, 85073139, 1400004844, 3414904623, 2991965703, 3324493380, 2662461579, 3371935536, 2685047962, 2084406666, 2522680379, 2216032134, 1833426925, 3564115877, 3629214939, 1386564296, 432334582, 3401734285, 3470776247, 3295439412, 3275391820, 2996027786, 3541192247, 1596293240, 1534677041, 4242524641, 3867762559, 3182515057, 778449780, 509849285, 1894106033, 3758007661, 3817124330, 114867286, 380293626, 3988986517, 2249146814, 1555156359, 862290373, 4289162394, 2797154341, 858657091, 2332904187, 683283785, 3310320458, 1908273940, 2996192820, 1274723594, 2256894660, 1011908845, 2088109931, 633224466, 776763995, 1482429362, 3311871094, 1334262064, 3149388402, 977459388, 3758068268, 3549396571, 3621273547, 2294655742, 2027549028, 882796118, 3763000843, 1211550434, 276620274, 230856654, 886280116, 819485199, 1395058832, 43453671, 612049046, 3593376018, 739190917, 551328093, 636688917, 1113589747, 1200914090, 1966124296, 388857045, 1499391582, 1096623475, 2380951002, 1179204203, 2425898283, 1568845412, 3305045134, 3461499409, 2929744718, 1843517946, 2263560109, 2614227766, 2598972927, 4211663438, 2238818808, 2123144987, 846869844, 1597863731, 1413784936, 942259755, 1435252365, 2763188690, 2011949466, 1724258311, 2878814633, 2216290126, 3890752531, 2688893713, 3467941951, 1532473463, 3726393479, 250588825, 2421895595, 1130251300, 2404278908, 2621227970, 1495570965, 3587745666, 3863085648, 3893033445, 2167432349, 2521288540, 1110696395, 3019115, 1557260537, 3407264044, 2647957557, 2212494188, 873933723, 1846630096, 3510283303, 416301122, 1671897732, 1541550351, 1498687513, 1182466031, 1497564883, 2250283938, 4174125262, 3058762721, 695042319, 3583491610, 1633913101, 2527176860, 3899685837, 911160283, 3039645347, 3348668230, 2349978768, 2310300756, 2452401376, 1521793036, 340141858, 3417831892, 1389692609, 2209437861, 1011293226, 3553183727, 2864651565, 2961816923, 1538336212, 1210400781, 937878795, 1776525302, 323549324, 2934290713, 3627165984, 419595827, 398867637, 2034794941, 1105787003, 1506150941, 3463860621, 3093035089, 2621956154, 3805051230, 1104966082, 1511537428, 3334056299, 2819684443, 1450375895, 3859160045, 868818555, 3021376565, 1583993024, 1655491252, 2323362595, 1623767895, 3277267299, 1439181227, 2210615033, 3342026791, 1303089351, 673713047, 2454990941, 4159020796, 3236264164, 4102788727, 836725026, 122766192, 2743591988, 4073411178, 3664777611, 1441783934, 1903288297, 4015225793, 2287805599, 646110839, 907079317, 3224989229, 3271827456, 2930105235, 2009175609, 4132152618, 3613216751, 2599489077, 767951771, 2330827095, 3178900160, 1672891072, 2558969779, 2413882700, 4123689082, 2821163535, 402922506, 2568613951, 3501945651, 931224777, 2219590700, 2669231230, 2761628391, 1010318635, 3912099512, 2137382107, 1740783570, 2900437537, 544334460, 1851950794, 2487565757, 1501873778, 493353971, 227575783, 3993627568, 2857758942, 1794910929, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, ], ); // - cy > 2 test( &rle_decode(&[ (0, 29), (4294967288, 1), (u32::MAX, 76), (4194303, 1), (0, 83), (4292870144, 1), (u32::MAX, 12), (255, 1), (0, 204), ]), &[10; 821], &rle_decode(&[ (0, 58), (64, 1), (0, 76), (4227858432, 1), (u32::MAX, 77), (4095, 1), (0, 5), (33554432, 1), (0, 12), (4294963200, 1), (u32::MAX, 64), (4294963199, 1), (u32::MAX, 11), (2147483647, 1), (0, 71), (1024, 1), (0, 11), (3221225472, 1), (u32::MAX, 12), (65535, 1), (0, 409), (10, 5), ]), ); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[18446744073642442752, u64::MAX, 0], &[10; 10], &[0x10000000000000, 0, 18446744073575333888, u64::MAX, 0, 0, 10, 10, 10, 10], ); } } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_2_fail_1() { let mut scratch = vec![0; limbs_square_to_out_toom_2_scratch_len(1)]; let mut out = vec![10; 3]; limbs_square_to_out_toom_2(&mut out, &[5], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_2_fail_2() { let mut scratch = vec![0; limbs_square_to_out_toom_2_scratch_len(2)]; let mut out = vec![10; 3]; limbs_square_to_out_toom_2(&mut out, &[5, 5], &mut scratch); } #[test] fn test_limbs_square_to_out_toom_3() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_to_out_toom_3_scratch_len(xs.len())]; limbs_square_to_out_toom_3(&mut out, xs, &mut scratch); assert_eq!(out, out_after); }; #[cfg(feature = "32_bit_limbs")] { test(&[0; 3], &[10; 7], &[0, 0, 0, 0, 0, 0, 10]); // - carry != 0 || limbs_cmp_same_length(scratch_lo, xs_1) != Less // - s == n // - SMALLER_RECURSION_TOOM_3 // - TOOM3MAYBE_SQR_BASECASE && n < SQR_TOOM2_THRESHOLD in // limbs_square_to_out_toom_3recursive // - SMALLER_RECURSION_TOOM_3 && *asm1last == 0 // - SMALLER_RECURSION_TOOM_3 && *as1last == 0 test(&[1; 3], &[10; 7], &[1, 2, 3, 2, 1, 0, 10]); // - s != n test(&[1; 5], &[10; 11], &[1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 10]); test( &[123, 456, 789], &[10; 7], &[15129, 112176, 402030, 719568, 622521, 0, 10], ); // - carry == 0 && limbs_cmp_same_length(scratch_lo, xs_1) == Less test( &[0, 0, 0, 1, 1], &[10; 12], &[0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 10, 10], ); // - SMALLER_RECURSION_TOOM_3 && *as1last == 1 test( &[565087108, 3577014007, 448420006, 2768629557, 3704090824, 1883403892], &[10; 14], &[ 4218985488, 4220575665, 485151065, 3638109583, 674533688, 2474892467, 3104074041, 1104686790, 3937806198, 3714955349, 2353052328, 825899239, 10, 10, ], ); // - SMALLER_RECURSION_TOOM_3 && *asm1last != 0 test( &[ 1863564690, 1421495353, 3398346856, 3502315373, 3245074461, 3371098228, 1920119175, 2322725516, 4131580343, 709402630, 2656476301, 228065352, 4270876554, 2188759820, 3809088484, 1278459410, 3688098765, 3792157672, ], &[10; 38], &[ 1275914052, 2813541102, 1776167565, 3816433009, 1506506355, 905535255, 3807374706, 1119336832, 2821426754, 1687683145, 3194676438, 3617711780, 3181480047, 2569874763, 63947417, 284228079, 864468110, 3049865574, 3349291193, 1069485525, 2676088498, 2386507281, 152204676, 977297146, 1013377091, 279563853, 1416452708, 3923795588, 2090135739, 1920980986, 1947396916, 2353294051, 1096614562, 656612539, 4107024100, 3348211714, 10, 10, ], ); // - SMALLER_RECURSION_TOOM_3 && *as1last != 1 && *as1last != 0 test( &[ 1340632901, 3164542962, 2229190317, 2072028339, 3600460563, 4242593376, 2627243024, 1009360033, 3245433778, 3317979701, 3334268713, 956862889, 1903527801, 1422003495, 3902138254, ], &[10; 32], &[ 1936517273, 2149059626, 3482772768, 751986309, 1917548379, 2845313364, 2764088089, 2639949097, 754924916, 2372685186, 2487592500, 3468889594, 1517341799, 2635848785, 2441035315, 4022727698, 668317312, 3146195097, 42876009, 69685896, 3753683781, 2617058485, 3637068186, 3137670920, 3218047800, 2570868414, 910498312, 614648473, 1455459795, 3545238393, 10, 10, ], ); // - (!TOOM3MAYBE_SQR_BASECASE || n >= SQR_TOOM2_THRESHOLD) && TOOM3MAYBE_SQR_TOOM3 && n >= // SQR_TOOM3THRESHOLD in limbs_square_to_out_toom_3recursive test( &[ 315937763, 473311027, 567550122, 1916950171, 4059671672, 732330624, 3931833255, 435611156, 3441308858, 1231108682, 571470188, 1643911325, 1855842520, 890506741, 4051150309, 1624118035, 4095320898, 832808382, 254544287, 367192823, 3029770132, 2530961358, 168199720, 556928054, 3574899773, 901884181, 3037235269, 2537532649, 3638603141, 3105834733, 756731319, 2666260459, 3459942852, 3113152432, 2490378291, 2524064262, 2837473716, 970558109, 1280992412, 3025351268, 1176324257, 3832993853, 2960008574, 143054238, 2025124021, 3355284231, 3700222977, 959518197, 836633203, 1753652842, 3863610502, 3683672960, 2678694928, 3768243585, 2643427081, 2597841461, 809616697, 2770459249, 938499903, 2306605358, 806972689, 462004905, 1559140947, 880982517, 4000827930, 1625323545, 2071445194, 3924145010, 3049042401, 3015341713, 2642970230, 680495934, 3572593922, 3776563282, 3584817478, 1511664158, 1048142251, 1261635752, 2674531050, 1166719307, 3811800408, 3532080230, 853430491, 2558475297, 2417944189, 3094847515, 654669385, 2934541460, 2625633289, 4100222514, 1517941214, 3805734203, 3486264903, 2658767168, 1176863503, 2377983813, 4010981779, 1334807591, 3581560372, 231495094, 2680779981, 953071754, 1140610841, 4139855852, 515631497, 845705671, 505532954, 1555952001, 1319192795, 523566796, 738834566, 2397343480, 3709100568, 2754977717, 2105634100, 2622287225, 3069665844, 1499378188, 1024995116, 529523547, 1573018435, 2475374120, 3949433831, 748808472, 1404353612, 3021083538, 1713559320, 706538487, 1788875531, 3976761851, 1912518906, 3712335343, 3425283422, 281500646, 1572406350, 108746052, 4056047843, 89307364, 1006007374, 2902260577, 1250995384, 1556873818, 3846421711, 280743259, 1728158805, 467926284, 2330565417, 1366395459, 474848905, 1190711031, 4146575846, 1359337485, 277106601, 611834097, 4135958043, 2404499652, 3266860581, 4084179847, 1694432029, 2659591080, 438254541, 2191377959, 2215296842, 4215722030, 1219192120, 2382641840, 3275049666, 1893229486, 3003341825, 1385119378, 491641953, 3636318537, 409287515, 1702143228, 3653042335, 2210372129, 3091759374, 3445226074, 283146383, 1663694381, 1455499100, 306155088, 3031133107, 30443875, 336170015, 3291741077, 1240501199, 206913137, 1160607143, 2885974827, 3313462225, 4194793586, 2065489618, 3883470150, 4055315445, 582773660, 2582421365, 1454136391, 3061250840, 3468396503, 3488155264, 3029987831, 3156489841, 3463417120, 290496437, 4073099736, 180400746, 2106957818, 2769052442, 108172964, 284413173, 3344416865, 2269676748, 1574448658, 1902898868, 2316487593, 2771218024, 559367309, 3806016235, 2226674034, 1387375714, 3568612053, 673940445, 953264754, 1654240319, 2440830479, 283579272, 3231076957, 3939738751, 1493681204, 3397390673, 202532089, 820322467, 3747993335, 219997922, 1605225930, 4131306261, 1601302257, 521986372, 2770985700, 1963676063, 1439552511, 3555657222, 2250141846, 2503842498, 1970558797, 4169645939, 650372536, 1069598113, 707461834, 2970635546, 4043174034, 1642439873, 4249605930, 453278516, 1404882141, 2914837424, 1989551821, 1391677255, 2183893344, 1584545759, 1373876512, 2646970263, 246551016, 1589680164, 3758709566, 1942743739, 3244781899, 3123447530, 327409007, 2868166556, 3076801053, 2736084122, 3120784427, 199119660, 2691390162, 2174609870, 3758152774, 3735826978, 379752927, 619293957, 1527231068, 2991592006, 2710895459, 704686889, 4267216023, 2557068229, 1719941939, 78238238, 2962383502, 2393733803, 1004503772, 4066720355, 2075559616, 4243473886, 3935513315, 1002981165, 3794209454, 1615720966, 1568227265, 1813739753, 3362817192, 3305123208, 396682192, 4129516924, 882778042, 2077448918, 3646338728, 3577300535, 2457120647, 3540612431, 1671071497, 2995114160, 2400776059, 842998576, 3518689093, 4224316739, 1023092271, 1070023790, 603487484, 1374775086, 3498521370, 1323561470, 4087319908, 2455563164, 2011118687, 495516162, 3626408376, 672930363, 996279995, 981700082, 3228699492, 2150767183, 519151136, 1312076022, 1336129777, 4010423712, 2637820943, 2292814695, 942739251, 949393103, 2458673154, 768725091, 1832836796, 453300228, 4261116655, 1701896567, 2144567659, 3699180161, 3087788471, 2755320709, 1748927126, 2706369429, 3729051121, 1295882152, 3846117499, 4120997689, 3272456369, 3495028726, 3839821698, 3333310547, 3768072175, 945089968, 3361639032, 3268636237, 2279991624, 3672799919, 1759060635, 2771604505, 1771544561, 2787457919, 440535646, 2504067590, 3105361213, 353200529, 2099162584, 378937981, 3561464661, 3915066715, 2729297678, 2088428747, 710187304, 3736425617, 1392889178, 4161612762, 3599125244, 2012759904, 1706559215, 1741496559, 1644051828, 3760773690, 1619711282, 3088530914, 828541325, 1116610363, 812269687, 1076986782, 3303686357, 1446933100, 4010678422, 1326813853, 2348597983, 570937405, 3521228878, 2567079846, 2753504122, 4168927609, 4114588897, 4058328886, 3726683252, 251974901, 1610363499, 2152010449, 2300844173, 2883860828, 2276005572, 2627023715, 2700844654, 2659717603, 3243052767, 382173215, 2253713687, 1545258562, 2782986095, 334263358, 2481258310, 2291585918, 1380546066, 1861205162, 1395600128, 1509813785, 1715266614, 3251195596, 3140058077, 1998653517, 3140019184, 2534426976, 844092771, 4270350187, 424082283, 3804651493, 2962777391, 32884830, 1331871085, 2047357436, 2562052720, 1663431404, 2097420816, 199104030, 1685999636, 2207406189, 3119926828, 654294011, 3715835629, 3855214036, 2460989955, 642673607, 1971681331, 2338977519, 475442971, 2516527409, 3470931196, 4262052990, 952637669, 1228316620, 165464703, 4219993004, 2243168861, 3690831859, 1956297624, 2833425905, 2707262033, 2571314297, 388071395, 1896528257, 1225824551, 81572020, 1409232203, 1080694913, 2547917588, 621110800, 2702861568, 2198117710, 1555339014, 2581264646, 138377579, 2293745610, 3914562495, 2918275417, 75829334, 1774985081, 2747349051, 1950994159, 394477872, 316913102, 461555308, 3548648328, 1617956386, 3126524770, 3123423878, 2182889796, 1568800505, 4279897761, 3333589672, 3792226100, 993443061, 1159842193, 2865953114, 2512277991, 1357746528, 3671513246, 2616265767, 1074303241, 2050907943, 268286549, 498690132, 4283094777, 2802371317, 3676403238, 2934500589, 281990329, 3074366974, 3387527201, 157777380, 2405204656, 142578723, 3660296423, 736731392, 1974042455, 1159614597, 4162674193, 1332482037, 1658304045, 2913005509, 481813632, 3626506485, 3221737748, 1374358866, 3827774417, 3308590869, 2205316972, 2619601751, 1879495531, 1688667307, 3945492802, 949715752, 165718259, 2529864207, 4033163217, 1627807449, 814761495, 2394041772, 163917860, 4137152849, 871080750, 2809100301, 126889608, 3338024033, 1570788701, 4067509056, 680440343, 3399634957, 1674234215, 2430678482, 1482962229, 3917262730, 2701308470, 3764650279, 4224967620, 509844418, 2494825785, 3803774464, 368493499, 4238556118, 4030415682, 3643742328, 2586387240, 3719633661, 3755880620, 2176876728, 2496909862, 111654638, 4071443844, 1244732003, 1399710541, 3492272815, 2804216879, 294683567, 2823495183, 1539340600, 2732661048, 2371405604, 611094747, 2426195984, 3948451542, 3575143460, 2163084716, 2877537071, 1849282685, 1662381818, 2022577840, 552741512, 1863034519, 2109621858, 3426780715, 233006082, 2766239663, 1257764921, 1179443268, 3311729910, 4228711990, 3676801557, 83336617, 52963853, 1461131367, 615175494, 2376138249, 1373985035, 3055102427, 1823691121, 175073115, 3051957217, 2611956643, 8092274, 4103495923, 2566129626, 66490664, 347807097, 730572423, 583932817, 2193587874, 1998219581, 3806043908, 3146127947, 3440818438, 4105053798, 806574510, 2647710257, 213825364, 1827399426, 3250558290, 4022072337, 2163344675, 1249293165, 94983795, 1430041053, 3690143296, 2906241747, 3282031769, 1948701801, 706760835, 4153647095, 3843998199, 2077172825, 1158686949, 3157624247, 3424621906, 4056374038, 3423674225, 511889851, 1745449688, 2554422250, 3004747460, 3576364631, 325806114, 1453902201, 1181646483, 784925267, 2018211516, 1758948179, 3236113206, 2773633419, 2329747557, 1612586727, 2954856193, 349470489, 4039284565, 2170178879, 641328078, 2932878730, 2057036386, 3758698550, 1389788861, 905696645, 322846493, 622200893, 2990601641, 779473385, 1637467878, 273757826, 1187850568, 3072937718, 3191465645, 3858350034, 2959907236, 2299744720, 2690960451, 2949783744, 1102614926, 1689432656, 934117703, 1940112928, 3379564708, 4199340399, 1881321211, 3929726949, 459862695, 1350630556, 2137584308, 1243785894, 983397001, 140271427, 1266031183, 3559919295, 702977622, 3883080853, 1830599918, 3030922777, 2650241556, 2807154392, 2218698435, 1904442293, 2992923456, 1481791037, 4079300846, 2680084216, 656285791, 3396057405, 272065717, 766725345, 1681255263, 1707458816, 1535744308, 3830462997, 1607479268, 3475252676, 933054715, 4058518411, 1139150315, 1176656025, 2657461768, 3149905151, 2833828072, 1407836276, 189062495, 3008111084, 3911286362, 3969377587, 520858887, 1921886086, 2410034665, 1853865087, 1218625232, 3157059817, 1933332942, 1324005415, 2613648167, 575584498, 1622716448, 2776523679, 1406325147, ], &[10; 1524], &[ 2337798985, 1719809325, 1766146956, 1432871059, 1913282470, 932051231, 2253427743, 3337839354, 174212766, 2418943939, 1818195854, 1795016853, 2023061831, 65726280, 1576822705, 2489110480, 1755680124, 1010622883, 2410047067, 2957950721, 3821505888, 2029055790, 919813873, 1454524914, 302707966, 2263686386, 664775132, 1441592353, 2668276189, 1029874670, 412976722, 3461537739, 165618775, 2805755420, 3986913245, 3750850515, 3911747004, 1709726859, 1430494098, 892950310, 4242511728, 500894641, 3512661539, 2383455966, 3902393679, 560808026, 1002183845, 3645493779, 2496237617, 1188317615, 1160331230, 4049090763, 2880495307, 2497687381, 756372816, 3883382263, 1412825102, 2798212291, 423470242, 1304918648, 2518462534, 1602052053, 3195498278, 1567441227, 4149369335, 3579099384, 722916608, 219424070, 3527901104, 1360861314, 3127386676, 1175600452, 2707542312, 2622395649, 4068363495, 3280638003, 2049563983, 3599786937, 1642977740, 19557413, 3844757830, 143230124, 3229601666, 1815836866, 2078167034, 1978389011, 4052689102, 3596571824, 2305736773, 3086821173, 2783854453, 3475178187, 2809907276, 56497958, 3665195047, 1855481649, 1557213590, 3186218749, 1579659414, 150730557, 2380493806, 1190332347, 750653467, 971803647, 4051923874, 2632706878, 961664618, 504169243, 3226989251, 176983832, 940067439, 3293538260, 2637791019, 2191083272, 3752981185, 2657937635, 4070370999, 4174783071, 419043165, 3539337388, 2961294405, 2250070055, 2129849842, 387044251, 570402960, 2429786867, 1321852772, 3796327549, 3651696376, 48730390, 660939665, 951624653, 1018250603, 1969566385, 3101262553, 2638971565, 1283036253, 172956163, 1683623272, 2766676731, 2164693596, 4149757659, 1029834025, 2691905287, 2446385107, 1005918892, 4205867169, 3216497085, 3428921101, 1770814161, 3015757934, 3464827848, 2494805438, 4035181431, 2179278559, 1424330, 1495619547, 3264150186, 3878153512, 2533738492, 138095927, 3968650904, 2988833739, 1178707551, 1851845851, 3283468943, 4205297379, 706168803, 520798040, 1611948341, 1295934146, 3768257794, 3872350135, 73022895, 2256463338, 1559961103, 279286159, 3232753970, 708275492, 1289339849, 2043694079, 2524360705, 2745749567, 1949784728, 1216039087, 3116384382, 1740530329, 3607118652, 4122786400, 530757090, 552544450, 4258552404, 1083733061, 1242098549, 4033981212, 204615559, 2161166767, 1611351590, 1176002643, 92570843, 1842133474, 650271884, 187375074, 1991479387, 1465587133, 1104658610, 2335293990, 214374954, 2350932521, 3814143087, 4138623525, 1116785125, 1647270088, 3109205647, 1522224221, 1795795952, 4049380771, 2003489406, 2717299085, 3865480913, 483542617, 1812810600, 976115739, 1874969238, 3323862135, 3433813421, 684253543, 2649590287, 1373773333, 485552995, 2472189256, 2945214935, 794984346, 1746460381, 1757396273, 1743887526, 298380984, 1352704452, 3966715730, 4113217885, 1241297473, 2453395403, 2954244651, 3774288543, 1444839196, 1548334790, 1122875432, 4121317990, 3947157568, 2712619444, 4223807490, 4005476489, 2308148699, 2684648139, 612866543, 1452041438, 2217463262, 4199719912, 3956456988, 1855047341, 2513694528, 4275971633, 2747007746, 557514185, 1719154861, 1529793338, 889576708, 3968812169, 2510679393, 803503931, 2692261222, 4080870372, 1511006235, 2711504643, 975058190, 4061501572, 2837215732, 2193743263, 4181374242, 2506045727, 2059941818, 2631701397, 4223127935, 2130862853, 142213618, 780119847, 1085548982, 2585032692, 1428661966, 2131060363, 667385220, 1225586380, 4242414988, 3975059186, 339067021, 4069839975, 4207550632, 767730479, 1439311207, 3446124465, 4246386072, 2908059873, 3369915408, 3255651336, 3020663495, 3546510376, 803064470, 76924606, 3832623942, 4020318607, 2730283796, 2953477768, 1922322168, 2956148578, 2539451553, 3716309785, 3125952755, 2075479202, 776522024, 2500281600, 4171655545, 2729325135, 34251037, 1476015613, 4199561321, 469926930, 2222437139, 4029482883, 3407168764, 828942664, 3994809377, 1646421728, 4162196041, 1109742320, 583773405, 932723359, 2529525319, 312357632, 2879219364, 1065489156, 132224124, 515226881, 2446629197, 171479349, 3993018508, 3278247564, 2928823997, 4231434757, 2985885115, 1806357710, 170081371, 2586404971, 53743121, 3915349183, 4256978965, 1282122127, 1334176954, 2896736246, 3168160222, 2723155581, 3801770034, 2474069641, 3914138112, 1703132960, 3050910113, 4000063991, 1156533771, 4197722875, 322247103, 2828309651, 1418664555, 3855814973, 2969749183, 670899946, 3684238847, 315272562, 1479787957, 3630248247, 3896795856, 2284924078, 3448742593, 2587913739, 2159727850, 4271757822, 2635451852, 1460173359, 514583636, 172745403, 305115099, 1158098813, 846374874, 4085016243, 2073661719, 3009482284, 2414138245, 3524500656, 388867611, 249517102, 3006883043, 4017176253, 2805544688, 3976760186, 630506689, 1780244360, 2737306104, 232231247, 1782076434, 387667825, 19793987, 2435181870, 2071669258, 764507081, 4155368519, 1451401907, 2360299858, 2330980099, 248454712, 3446078666, 2051966307, 2583383245, 706199696, 1890612504, 430574014, 2138787679, 2072311300, 737930085, 1521104440, 1585866980, 3120273, 3745204278, 3810187595, 901979488, 73759262, 3666590185, 875095827, 2485005683, 91444278, 997368547, 1551767372, 2677837051, 2596775070, 2673462320, 3055136566, 2778177188, 2822170891, 856301750, 717584730, 2775561644, 3235679827, 156925055, 4291892081, 938088712, 3712668621, 259963917, 188910174, 649460518, 1817160593, 3709183455, 2402569350, 2081244206, 1509583715, 159399436, 1005960034, 1584342275, 2708952291, 2083036721, 1827439806, 1920055605, 3099081841, 1505885624, 2705667938, 2970467008, 238736756, 680180549, 4265559140, 2686154915, 1275991160, 3321354017, 2666491064, 3391755967, 3136520967, 3492830782, 3080081809, 3240774903, 3389225939, 3016812645, 2761181256, 2165228292, 2154406921, 2542813197, 1465309996, 1179307147, 2930429249, 3040580106, 1976482529, 922355195, 3971063173, 277150860, 731857282, 3242189049, 1177214447, 3390437917, 3079667926, 1364420250, 1590973945, 2232278086, 232355078, 2582462161, 4037245230, 1049343960, 902676573, 4050492428, 1639129006, 3718138732, 3141580653, 766367797, 936894223, 1660677846, 628659564, 3365679999, 2561586784, 2229241133, 765418610, 782213348, 3067170394, 2191065093, 2774229638, 1023995363, 2412486840, 1635182131, 3748032748, 3129138020, 3607863873, 1174858263, 3616713190, 4187572066, 1546395074, 2027798083, 809553599, 1094121220, 3654162279, 1622703946, 148537568, 2385824297, 4061752858, 2543105581, 2622844203, 232849043, 3196673684, 2978718963, 1149528105, 2668110812, 2785402592, 3000100584, 1104866593, 70336191, 3432727170, 1109464777, 3746930874, 370280554, 3173358988, 3028594704, 2568130308, 457794435, 3383280274, 3346977517, 3484110806, 3153332792, 2425789545, 1474803746, 1781168328, 1989549162, 1032111952, 1331522816, 576372512, 1501541893, 2363428250, 1240303586, 2086180513, 3295867599, 691258190, 1008095124, 1776518245, 1495400690, 1519584986, 161360441, 1772372163, 4268396252, 2962917231, 2427675136, 2392936739, 272706848, 2620154363, 3998849772, 145937813, 4086621724, 1362430997, 1197771365, 4043072616, 916377810, 744218349, 1540693771, 2677728030, 553310668, 4229748447, 2011546593, 1970733497, 348172273, 762490238, 2152384213, 3411715628, 963109640, 3705793619, 3279035870, 426700692, 4278708730, 3586142296, 947806688, 1271342014, 715263589, 3455580436, 947104307, 1544685336, 2935774907, 2880317443, 3966149687, 2185422218, 2734810890, 3501513946, 2776353382, 4018451746, 2143808119, 736225303, 285334126, 2476018967, 3181930537, 2187294402, 3466164771, 2701302654, 3965790213, 2725436454, 3988416777, 3703472799, 1987980159, 923281388, 500013102, 74776770, 305061946, 3071827551, 486104690, 1384936530, 2111519171, 4124986050, 2429853625, 4015640194, 1966593586, 3123465599, 3341712852, 4213415239, 2396791960, 2722817611, 3004299255, 3857147942, 3516645579, 2072674201, 4175316375, 1683909736, 839905161, 316481248, 1683979804, 322038557, 677362982, 2973808772, 2596414587, 2730969268, 631888150, 1120341313, 1741270077, 3073620475, 1271943658, 1569862398, 3466496720, 4035716713, 2628306778, 2724723494, 1112102889, 3113513358, 2206163467, 2242575348, 2370657615, 3589371005, 1709622823, 2134510725, 3551117280, 3530138199, 922367384, 2890039831, 3559757981, 2345560704, 4221190559, 2332246771, 947123098, 3646442248, 488399645, 93684888, 851205014, 1145927652, 2376994496, 3976460398, 1154212282, 957935206, 353710365, 389412511, 1861961516, 3877610160, 1563516521, 1691953718, 1806258524, 4051249633, 2608084101, 1791724368, 4265828682, 98939002, 1131349528, 3141506279, 3747754883, 326404000, 2478362343, 2588680395, 2143336059, 3872805152, 720855604, 3231146872, 4275393682, 3215503747, 921660765, 2211457002, 29403278, 3071719374, 1901061486, 2988763100, 2195689231, 2111188612, 311057207, 1729785466, 339631061, 2566255664, 3558053739, 3017329992, 1834837913, 3911826467, 3826490857, 2838519210, 757698577, 3906322785, 4201094194, 828603290, 285313241, 2371084832, 3768763374, 511342167, 2751348498, 567611672, 3901537525, 637319646, 1586443362, 4009827455, 3278659128, 1377532409, 3930965051, 2016750432, 3351589103, 778112140, 3371765631, 1556855495, 2344340916, 684075640, 1324448534, 276848285, 2687066552, 744693016, 4155765815, 4053126644, 2290562982, 3537232030, 2910327479, 117184916, 3754357390, 101277221, 4265748564, 237634245, 1512268980, 4214404190, 289404203, 860074778, 2529446104, 1189797004, 2770192524, 2903941734, 3102660368, 1570144478, 3804933549, 3389588359, 3001536844, 2329211683, 1407331884, 374375577, 615849274, 2245748633, 2486770001, 1799357670, 4178076266, 1730691052, 1412641489, 4079190253, 167714251, 2752796561, 2070727620, 3447368889, 2159992367, 444800747, 3415638783, 27624656, 3085487729, 1630578659, 1765087260, 2272809030, 578971753, 3739324834, 26506801, 1503547836, 679618433, 421139499, 897586659, 1601201904, 808638444, 347513570, 4164626224, 2090150387, 1662217048, 2565908593, 2258638212, 2582887050, 3049842268, 463985909, 2843964551, 4162362888, 2547552905, 4002549257, 576087401, 4183702585, 1675063714, 2051066642, 3803031947, 2090450590, 3938803751, 4049575988, 1691762818, 1183856575, 3533472587, 2933123695, 1151648587, 3776826260, 1976737738, 3067649231, 1952953790, 3925101821, 3114071537, 79952452, 2770129385, 3762518198, 423331885, 3544738199, 209503969, 154615406, 1342149697, 1333109660, 3903240401, 4022118150, 3243003401, 3515425193, 3260933615, 3935151733, 4243861151, 4004716179, 2252411142, 3479623550, 619349788, 1822112124, 2051960597, 1448228280, 359331793, 3493974512, 1499344774, 3571669552, 608039076, 779605949, 2580871072, 2251891637, 518136121, 3357386849, 65613722, 1488211247, 1109960833, 67264203, 3897572692, 2842883700, 2822459224, 1333894132, 3652423328, 1827881649, 1486551958, 1571054719, 4230029963, 702745680, 478183618, 2813365752, 3051672215, 1590426347, 2661100659, 55101147, 1797728425, 2199206234, 3839519875, 1207276266, 3036038417, 3369821540, 4101140639, 3792842778, 2183838104, 3104645351, 2683538102, 717718063, 353527065, 3212696538, 221589441, 2454143520, 758857780, 3420448097, 239590213, 23041004, 912346001, 3384986593, 1335670788, 3610216946, 646607297, 2605581924, 3636256200, 2749404520, 3889217397, 3394201566, 1531295181, 1698305780, 736640736, 750817311, 2871203445, 3452494777, 3810316319, 4076603850, 2526619779, 1700794355, 746419560, 1898566119, 3189889287, 3338810189, 2729295103, 2714969082, 2936456989, 3452671603, 2798522437, 437710940, 82894680, 616072789, 1015800875, 1512158212, 75197689, 476169713, 192025813, 524644193, 3794046224, 4244912276, 847093610, 2301381132, 1503243934, 1403928108, 158653817, 3646897441, 751695739, 4092438272, 3539174158, 894208709, 3715408536, 1948913594, 11782301, 2703823913, 2270669901, 2370842917, 79716581, 877131359, 1231152090, 1856286664, 2471452235, 948189203, 674655372, 2821992252, 1092374320, 1563306677, 3626103505, 788520296, 1680746361, 2034836927, 2145159834, 2683063452, 2325545538, 1679113114, 1781024218, 139230084, 2908338938, 128867250, 2773176251, 3373230127, 395443889, 1634814549, 167825197, 1634796464, 1947803888, 2013614903, 879558209, 3672470617, 2886990675, 3688303523, 2987479497, 2229348558, 587602058, 3906889763, 3854711354, 1112626065, 3202904797, 3617514763, 3830554002, 2623747222, 739593158, 2754233724, 3280368708, 3050050571, 3069966571, 102976562, 2660327223, 3154039373, 247909998, 1031888281, 2121369508, 1224991377, 1890973752, 821369319, 113934081, 3380255436, 2479287499, 1913468809, 2502572678, 42228251, 2547189732, 4192517413, 1139547766, 1817165040, 726033457, 698589048, 750185110, 3384778627, 3490929155, 446473745, 103788750, 3026909394, 1055231164, 4240688633, 3651482557, 3385090223, 1111522119, 1564791281, 696626826, 428086133, 3067805263, 2544546481, 125648522, 427117978, 2492806758, 758056653, 3815718688, 1140343992, 1358469708, 1626866970, 1240757277, 682728998, 1466110233, 2962773326, 1742672810, 3256580108, 4251921945, 266158792, 118939513, 2916956256, 636321477, 2048301669, 3939990726, 1833678549, 3760980311, 947426840, 3055111977, 389083530, 2929345109, 4074386053, 1207476606, 2098662696, 1009814293, 1721235386, 2166808996, 3676341420, 1580747174, 2420879730, 2936498003, 3851224601, 1756566266, 1433935651, 2163763603, 128011896, 870207060, 328814509, 3272836422, 417135654, 2134909145, 123087570, 143532130, 3952868764, 2264741741, 92272491, 451493523, 776152550, 3732787266, 2953295060, 3559556493, 2328927145, 1387636129, 2840288941, 3683868368, 657932935, 53274814, 3241991768, 2880314385, 2643648654, 193180120, 655739143, 213868419, 44322408, 2965031094, 50461007, 3427495871, 146323106, 366166724, 1593053501, 3891132959, 2339070049, 2542807225, 3524375478, 2445432623, 567789085, 2455095121, 3487838079, 324840768, 514002614, 3617316100, 2192827359, 2607188524, 3653260415, 2685010260, 3200131371, 3698837126, 1195649853, 2454441885, 1343900861, 2888532827, 2243639168, 1855497424, 2235931710, 3907102759, 373855366, 2533941006, 1090440978, 1130102303, 3219593164, 3894670197, 1205959277, 1450376615, 885945151, 4234487411, 3955662037, 604242859, 1071651950, 2808913673, 3415749340, 3169116955, 1904598515, 1618878962, 524110893, 1274587728, 1769666847, 486193268, 1225449416, 54462106, 3167517049, 1853470197, 3313746392, 1396507753, 4241416760, 3339458134, 3634453408, 1073796257, 1414975063, 1460370363, 2106622507, 1792975007, 2815127526, 2891513438, 2795682287, 2704422611, 3162025328, 1087203693, 543725994, 2875511524, 540827460, 1415231959, 3628537754, 1896281252, 454300903, 2939977473, 3238208763, 1463107559, 744269904, 4129041087, 1154286436, 286775081, 4150671346, 3215856039, 2586174644, 2563594889, 2196859856, 3205583567, 1930394162, 1139079005, 1479679530, 1140049436, 451850993, 1680818185, 3392353496, 5765140, 3847965440, 2278586137, 1306641523, 972265605, 463819917, 1939105652, 2869882851, 239574945, 2564712374, 129695980, 1735318026, 1420648022, 2123663339, 2027937441, 23375658, 1937902123, 1034857426, 2862590085, 3506651190, 138519821, 1642289401, 1815640052, 3843060468, 3937934872, 2541728666, 3647355803, 411875524, 2988212624, 3529096099, 3244835052, 3434038830, 935500591, 4288020208, 756725580, 2264629201, 706062635, 135532718, 404448949, 4217556456, 717035686, 548833827, 3466891038, 2856986718, 3788562080, 1679206321, 2360817878, 1887014729, 2136917320, 2678810492, 2318105492, 77644154, 270026670, 2469142799, 1258494672, 3303653570, 3251229703, 242982511, 2902818172, 2974491897, 687201130, 1937150315, 2072181359, 342212755, 4068202459, 3451390875, 151260748, 2225880191, 2434808522, 916359556, 550136815, 746825531, 765768149, 2349587579, 4072937105, 174417938, 3148530641, 1504175015, 3999535866, 1504529431, 1181191996, 1294428167, 4294136970, 2112623260, 503759728, 3056809474, 3388597346, 3849318842, 3380162945, 3559697464, 1354499564, 3494243064, 2645181724, 2170305933, 79889832, 3023482863, 536000382, 3651862662, 3670290411, 2909658138, 1894327321, 1418292472, 1216369280, 2511425638, 1050447185, 2988291110, 3551716466, 4097897144, 1505967739, 2613042625, 4017491189, 1912275908, 2258357614, 1215885768, 3858405513, 3673669938, 677857927, 2958223732, 4048898278, 2169301793, 707103171, 956741434, 814165925, 3107480917, 3017104307, 3800299352, 1918539549, 3896439938, 3554811242, 2694303574, 925177824, 3032136063, 1749291165, 3998280950, 70049108, 3513897898, 2588855417, 2172098802, 1051273303, 3992914166, 1261460493, 1213244238, 3496736059, 4225265498, 1061148097, 2074121139, 3310195209, 2831272871, 3233236277, 2445284097, 2450635558, 1605855513, 1131284715, 3245154368, 1322372270, 2869178843, 2039261099, 1645142070, 3892994082, 930236435, 218807811, 2708516696, 2919789769, 930030621, 3846860441, 577616256, 1404894950, 765463042, 3314145877, 3733206019, 124841976, 3710712329, 683923696, 1125790086, 3250988117, 2181832546, 971084557, 815150268, 308158225, 443224487, 362401816, 3552358764, 3135530439, 33121314, 2154300664, 3768676730, 4180406514, 378587418, 2431499223, 2994441286, 1808890752, 3869540064, 1119394536, 4246394107, 1591781751, 2468039252, 4073888957, 292786140, 3200606452, 1487044474, 1803005899, 2652603821, 1815522155, 2672502342, 3653226357, 4217143309, 2889763440, 2152398432, 3980661644, 980636278, 2406751312, 993261713, 1673889350, 1373487543, 272064537, 3918533839, 3803826067, 4142045136, 2526731415, 2509904676, 3639345361, 974151539, 2071745290, 3793653508, 2230238759, 1813052313, 1190657876, 3606736124, 1461775176, 3044525512, 427548577, 3178636804, 3979867448, 1551173298, 173766289, 659710123, 63335203, 3730225690, 905952458, 1672077454, 1507641131, 1469489153, 3225770126, 3203644989, 724743997, 1500316720, 3619698934, 609736340, 295270861, 1627587660, 3874266477, 3066185777, 3368074666, 1479073449, 531786015, 746257560, 989895752, 3614796517, 2035671335, 1419905384, 717808529, 2807381697, 2747634147, 454509787, 3261464931, 612828385, 4209343220, 2085288654, 460480903, 10, 10, ], ); } #[cfg(not(feature = "32_bit_limbs"))] { // - (!TOOM3MAYBE_SQR_BASECASE || n >= SQR_TOOM2_THRESHOLD) && (!TOOM3MAYBE_SQR_TOOM3 || n < // SQR_TOOM3THRESHOLD) in limbs_square_to_out_toom_3recursive test( &[ 9525251150715707485, 8587763504821516080, 2117747772997939438, 3548585473389575775, 4368725143826266690, 4151422622588495985, 4202765536837222381, 6536868548778498226, 8537832607905834756, 9336293381477767433, 18090648844404510506, 3105525971724643379, 12707275375611860976, 3317865524960562713, 823982841074944760, 12143276137407678534, 11718343265209945098, 972615260809311500, 4497808493385741158, 4284234930706130439, 7584650555635583701, 13401700804872779083, 13056378070380119176, 16204947268987935954, 16754422922407328446, 3616382235390010996, 12081821858664337228, 12298806784194631642, 11068381938728473266, 1166551759858966293, 5303215576037036724, 1459955941298517816, 4011807711704072033, 7096373155148960903, 16682910161941435568, 8024381590924490417, 6949947117794717851, 9040317863012712195, 4785228307667500564, 13067737071940529766, 1789161767332960961, 10829540163630385583, 7172597173152077539, 5503961818523919125, 8087706384348918471, 4492802132769991717, 1188164630850319633, 13164198248699467318, 16183338424361636779, 9532503617554385117, 12467724616830286857, 8664003772679010381, 2864953899335878328, 8424900728671425836, 9730105501383490341, 13243619488513115315, 1992085995601070126, 4541056932031034892, 10048052926002006333, 4149742854488410708, 6604581724576852902, 8116872836838236679, 12909377853889042956, 2618412544527404589, 6240717678602672320, 17262717497935134385, 8933339373489336979, 4555255977252543496, 3187455824539014469, 1325520967350793711, 17902242471445880413, 14791679552918179638, 11505616209756266048, 18413169815441978527, 17159886807923826780, 8658827867630023515, 5729773240957150070, 17835287398020799335, 6255399748948477863, 18317413051795712550, 10021633350178308396, 9052815322626548310, 6892740207763967297, 14104401112852513805, 11421574096539340635, ], &[10; 172], &[ 6521696094589149641, 4476496593920112007, 281309484216721907, 3501015758154527618, 6372184862122315850, 13688972428608086357, 16317656242078388643, 15101948131376431224, 5029853447670483189, 11857951831679478013, 15911717557773435334, 10081601695810456394, 1782014398144673191, 14288539596211323341, 16626396315520681674, 17495406981900207848, 3659501794893247590, 14880407439063352148, 1525506733701671488, 12123557288153863266, 4155930172230135129, 4600799950904277212, 2074105507200300978, 1951113240555337310, 3387612412432668331, 2623403007819134632, 10215465147710453219, 1047131846193932057, 2254695478731133865, 13171169631787598429, 6585033052635255371, 12479656688140585709, 17676979602274596064, 2391506265209764529, 17881709395411630221, 9746579689294008870, 13656540280781249559, 7229227979790181928, 10738687500038878332, 10338166995316843087, 18351464591211450630, 6545644910633268964, 18257631102917691063, 15830085040765163904, 9853171674704361990, 4352529114219728818, 10371228500919079735, 12485073622709250281, 15200491753279014192, 13246789146543897642, 7234816350013842534, 17595498453701622340, 16417158337244228654, 15114011684238968813, 2755589762268003783, 1373249593523787270, 14512161456400844802, 17568489402488073296, 14869330884086877990, 8932022192310164117, 8839191912876243333, 11198937113445572692, 5498890674282919428, 8711441066608447276, 9856393259542505349, 12059896877231420142, 14513435611803050697, 13933775272811002776, 10845024410875135797, 10964948883907295543, 11008031582623668960, 18305235824609309463, 13936721840960294996, 2044893320015902126, 6586201943401086906, 7091941077862592671, 6651723114251478907, 10079416802056897654, 1539419857340461721, 9726041209688664271, 1989043203520864507, 15243466181397237955, 10868460317029042323, 15073556725205188647, 1777713915616219774, 1475371842789103627, 3970746438630823745, 15013960969967729832, 14426785376130414731, 7401374305322657250, 13337358005297018111, 3695563535331097080, 3412314266436852339, 5460481935370382358, 5789922616650608658, 2323320016068189849, 4266010817511936746, 3361964336501286415, 14185575797132229991, 5365726025616057734, 2992361504309085575, 11012270044677505862, 5139796591831649499, 3466076567659969205, 16705667066832559351, 5158533291895496483, 3746616024396156784, 2785159065183843560, 394631110435288330, 13638544389702077257, 15244306966358109382, 18440767283552965938, 9602917640375617089, 15115704595863040058, 14059130653134044307, 10288209935028450560, 14443546216698200603, 10258953817987364134, 9228449901492508549, 13814303746571428462, 16548279012015496124, 1070860953873829429, 5156291658423572264, 7302978081219328732, 14240414203936719255, 18095404503533136331, 9038473668915574152, 1652552463718420588, 8063692498356788885, 14965328966174753198, 9058258371493607659, 15788310587268630945, 2538688827757657801, 17765893059803430559, 7418620390864905673, 12272658634918366651, 8323094697253518567, 1543060190059627517, 10790616911161792244, 15839589421315724004, 11590668330600693342, 4736357234864118945, 5752655573361113076, 15181059741781119493, 3336974282102801709, 4224895603965182820, 10906356334967598732, 936316274897213383, 1913155927351588139, 11099566112059813190, 5936790069913243447, 11148342313918998148, 15668128280235073164, 10654047073134913897, 3624998946013372412, 6006678731810089858, 14292046510765622790, 8463949827558560433, 3930745276585662112, 16423967958955090871, 12480778808376637277, 12047684158052058686, 9338456483853840552, 8423305664340603430, 13808682977569853100, 9298864371157050935, 11728939008585660650, 1313559708163679747, 9976580221699673100, 7071836326317347417, 10, 10, ], ); } } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_3_fail_1() { let mut scratch = vec![0; limbs_square_to_out_toom_3_scratch_len(2)]; let mut out = vec![10; 4]; limbs_square_to_out_toom_3(&mut out, &[5, 5], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_3_fail_2() { let mut scratch = vec![0; limbs_square_to_out_toom_3_scratch_len(2)]; let mut out = vec![10; 5]; limbs_square_to_out_toom_3(&mut out, &[5; 3], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_to_out_toom_4() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_to_out_toom_4_scratch_len(xs.len())]; limbs_square_to_out_toom_4(&mut out, xs, &mut scratch); assert_eq!(out, out_after); }; // - basecase in limbs_square_to_out_toom_4recursive test(&[0; 4], &[10; 10], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 10]); test(&[1; 4], &[10; 10], &[1, 2, 3, 4, 3, 2, 1, 0, 10, 10]); test( &[123, 456, 789, 987], &[10; 10], &[15129, 112176, 402030, 962370, 1522665, 1557486, 974169, 0, 10, 10], ); // - toom_4 in limbs_square_to_out_toom_4recursive test( &[ 4139948165, 1538275035, 3244920878, 2576965792, 584068468, 3054546876, 2629688518, 4253271747, 3723872815, 1652066683, 990821089, 2335421805, 1989570928, 240486517, 2872315587, 3869991906, 3870517664, 1540804424, 397183643, 3750033565, 1433260634, 1506168711, 3616651625, 512028445, 3746712828, 3278592880, 2611514549, 1214563129, 1259227909, 1067976218, 3425169051, 741795595, 893688343, 2674408703, 3694908868, 2478153735, 2220661625, 1022546736, 3719214155, 3161293211, 4131981986, 1473264088, 1651777063, 1438502715, 290022167, 59234682, 3458968160, 2552001459, 3451530289, 3800073253, 717882913, 845719525, 1038699111, 3058303772, 1117505279, 3682430977, 2869037104, 2562493618, 960519305, 4147639705, 1817463351, 3166022129, 3200769866, 789666262, 2654485924, 3686362402, 2179867687, 3980226915, 3671542918, 1896992204, 1514962591, 815867715, 3924270086, 4262628477, 3977258034, 1340257907, 6618754, 2720861064, 778635062, 682181834, 2891943360, 3002120306, 3399643048, 3139375492, 865948953, 3273305779, 388881948, 3544744413, 3963050187, 3002594763, 3339669779, 2722426929, 1246819181, 2786076007, 708438365, 1013683719, 3027751127, 1766272571, 2839608714, 2866928644, 2107420563, 4035553421, 2376700546, 621608197, 1993043072, 2666011084, 2265522039, 3230507984, 2869423257, 1776134078, 2413254013, 3859414865, 193597892, 4255395370, 168637254, 3364100552, 3883433219, 3117797624, 2738841992, 3052596910, 3280507008, 2860095630, 4031447725, 3454885698, 1783630119, 3036202894, 3585701130, 4184585287, 1329572188, 2352399996, 3076023682, 2989927975, 320530428, 2081170907, 933271377, 2974966675, 3452895778, 2331110373, 995864819, 1177147317, 4084213472, 1179430541, 361665403, 2401303908, 3027157843, 2778759588, 1031442202, 542151276, 4259656091, 745358488, 2580062497, 2004998882, 2066508478, 341659477, 958017378, 2415007725, 211645068, 3630737942, 2670158596, 3544834081, 2043760261, 2149621570, 1287267516, 3353570061, 3758258174, 4171807709, 1363035595, 2692148345, 3728232161, 2672522097, 3234166892, 1337714504, 2475062988, 902334395, 3470019951, 1789926953, 39991566, 1071624731, 2480238280, 2010573056, 2975909089, 2685102208, 1752958961, 2957725128, 2441562510, 1615057382, 2739912075, 962437876, 1445592393, 750430353, 2848157371, 3515397641, 2140566969, 3080139371, 3564834440, 561913271, 1812943111, 1349101061, 1627550717, 3467766096, 194766042, 3125120919, 3021598191, 2389614341, 2536207717, 3687483968, 3746428277, 1304917109, 4262793424, 1046105397, 103309888, 2808595193, 1896772845, 2625389818, 1425524079, 4245371665, 1376995745, 1906643058, 4123808395, 4010921636, 3668036324, 538106732, 429893286, 1473862381, 692485290, 728791765, 4006267410, 2159349173, 1146991809, 1105326804, 855626330, 2350214961, 3945267379, 4182769713, 1218539569, 2795526933, 508156606, 1596052577, 4135932990, 4009064452, 3154371819, 1789912473, 3737225773, 2339289640, 382599364, 2822801808, 1231473766, 3195594892, 3686689017, 2674031129, 2724276086, 4112764261, 79570030, 1908454621, 270118882, 3204318684, 2240304382, 1923066108, 3669840087, 3114917464, 57715381, 3015749933, 3183317351, 2563719945, 2409212385, 2256893938, 718636813, 3965735223, 1345089653, 1264444, 2296052850, 1092210950, 3468764525, 3967443918, 788417425, 1924956491, 3656370968, 4266402294, 389687964, 3067575949, 3786278950, 4368934, 3414260125, 1500941491, 4197777812, 1901284905, 2548021755, 1986057606, 2732888210, 3872664452, 2787539702, 3264559111, 753549553, 1048190618, 2900005727, 1868077400, 1284542693, 3154799998, 395567255, 2005460208, 4005052806, 1893310835, 3217932531, 2607307407, 3917316670, 2028218244, 3745680211, 2397481422, 736482987, 1916844834, 3868328610, 938512555, 1559481864, 729544587, 3690980706, 1759014647, 2060717833, 2250640148, 3619925046, 2153794810, 4127168634, 3259374700, 2051907961, 3964686808, 3841055905, 4242264783, 2314742304, 2209077724, 2577227865, 1487635776, 1585379583, 3475070421, 1683734827, 3363053669, 3722095029, 3857335408, 2852846850, 456879372, 2473892714, 2928343667, 541075767, 3595876467, 1688710352, 2071331730, 1142047400, 1817453168, 96871997, 3927306877, 3090061646, 3474317652, 437148773, 439538568, 324686794, 772632617, 1424328970, 580538580, 3999279969, 2022469388, 2802303848, 1147488095, 2053949131, 3046702544, 3822972379, 2920233521, 4031279543, 2356245098, 2951036256, 3287235943, 2760424423, 140913700, 689952328, 3916658401, 1694797888, 82150998, 4075118605, 1967095926, 1704543314, 3154572744, 408071699, 844684417, 1174429103, 3583461805, 1015646627, 861970508, 1906905868, 2272773809, 879277860, 2980820537, 1917774935, 247497916, 2403283458, 553129122, 3303057196, 4005726052, 1808761740, 1909802116, 964057278, 1586240623, 3097009405, 2048123311, 2481968244, 3155267854, 555253647, 4027932249, 229358586, 1015669317, 4112551330, 351151415, 1331401879, 1749898409, 3352469407, 710145444, 2903798473, 2876271745, 692844392, 2354652850, 100021926, 4212629124, 2971597719, 2697935131, 445511347, 1636699871, 2524940444, 1303870696, 3634945394, 2398930906, 1337769794, 3955409228, 2657553814, 1455809030, 701994564, 374320080, 519334058, 71402463, 2995013099, 1573823285, 2419768029, 4108602983, 4266125692, 3514998795, 2367509976, 2654621106, 562141353, 3101668250, 2753822172, 406447740, 4132920329, 3645443797, 4221410098, 1000631411, 2319369935, 3987192941, 609889174, 569928846, 3471449767, 761399938, 2925981744, 3610481831, 364846710, 2579622933, 1755359875, 3327963251, 2230753636, 3897751713, 3685870953, 720576993, 4008645094, 2170973511, 3057371253, 2362087099, 2415801497, 3804893423, 874616900, 4188156090, 2114593709, 3626784402, 2090293821, 1178445498, 3501583487, 3787814639, 1160994150, 3773261324, 3438864014, 3474697300, 3232616282, 3082635737, 3290126053, 1041836645, 1497490946, 2116412677, 78748560, 2610841375, 406515051, 2540982558, 1278151559, 910145724, 2942229044, 1412896287, 2420692111, 2829066497, 2762072644, 883699073, 4146766932, 968581437, 2262117978, 4102625453, 753476188, 3237270935, 2018964783, 1357948517, 655508609, 4163647115, 2220146134, 3618211357, 4228425409, 2053237402, 260628807, 4078275010, 3945722198, 3264848882, 3968277361, 1416596317, 2102516261, 833088009, 3907840277, 2017643605, 1067842330, 1357529659, 2472927668, 1649000973, 2222344018, 3784049396, 3227757245, 2898271180, 4043134215, 3862532400, 3955686618, 98246491, 3365854338, 947695294, 594787742, 320576666, 3333798817, 1904306436, 2975705325, 2991782885, 1736852103, 3844447384, 1817569919, 3224273837, 3598752781, 1577803239, 2950514537, 1562681940, 4068361583, 3868379584, 2088936482, 679461158, 301319738, 766873076, 1943559698, 2477791081, 359203531, 248689484, 1396200027, 1850343941, 1125961151, 3934233911, 1148111021, 3719148359, 1654482658, 1197396856, 3954632576, 2122559365, 197233285, 407487633, 4158181537, 3053296658, 2799166403, 2081625494, 844237749, 3509575975, 3964633958, 4179613577, 3338942399, 3816968642, 3007984156, 872005283, 1859074434, 3956327811, 56397907, 478149678, 4026802122, 1384639138, 368837837, 183900171, 785221208, 3231446529, 4057339631, 2617885657, 645209974, 3749331053, 3387891965, 3097021752, 3337686487, 207272201, 4090597826, 1337950862, 1489880288, 1626252138, 1844132502, 3785436754, 2455659736, 2722719185, 3556302565, 1609527187, 2416226913, 2766580345, 1869533642, 3531500453, 438426623, 158796542, 3488893438, 3084370998, 2058790923, 1154169553, 1385226416, 1509103535, 1162048903, 797370674, 170054390, 2752067502, 3119807393, 1923267976, 3762356971, 1978871808, 3723074764, 3460095249, 2837581806, 73932499, 3524773614, 2454111707, 2818213028, 3004873518, 864066450, 3576610451, 2315784966, 151779632, 1178401043, 3765993358, 1348598145, 3576623674, 3204205857, 3883955902, 2023814627, 795831378, 2827807531, 1331064687, 1837025931, 3540224087, 1381156075, 141174913, 1539904944, 1709050097, 22990830, 2938269544, 3188893513, 1701451446, 124677463, 2376122456, 3735869779, 3855792596, 3836459842, 3548479279, 290636702, 246664, 797902866, 2875170064, 2475070809, 4116284414, 1208231388, 2828093914, 3711751904, 2624075253, 758366641, 4278761943, 679106142, 1679478312, 4110848533, 540768264, 3004089076, 890051787, 1527108158, 2687541799, 1379201802, 1778300800, 3159280475, 693175137, 1706052065, 2740998490, 610778078, 1254469442, 555145750, 4257282365, 4088567402, 2722156643, 2973326370, 2580839471, 2297203610, 1325248528, 2289415165, 2027203297, 118624041, 3143737015, 3150787590, 2027511535, 3762291585, 2693532637, 2791300523, 2662758110, 3136152569, 3442748961, 1004378785, 2651776322, 2521157696, 2559348070, 3806708201, 1867376555, 3308198648, 792265193, 1257869334, 3432781024, 3378655514, 2353252813, 320451009, 3968297418, 237777247, 2490314264, 3266186675, 2255726749, 3147278539, 564923137, 794399730, 1624402708, 1616480718, 3606683399, 757916498, 2887385172, 2854589997, 3276729119, 133652525, 1045552210, 2262021731, 3248481891, 630857187, 4136667563, 3680583667, 2458003061, 102973943, 571665205, 4057786651, 1569357837, 1410019960, 1524881406, 1358182388, 785354230, 3829905260, 213334008, 2101845387, 3881098191, 1678603844, 2662511679, 2818265908, 3742761039, 662343317, 2881658894, 3293956365, 3576730814, 491183503, 2939708573, 879732964, 1424495345, 4226077578, 1724320764, 1649293059, 994517776, 3889024255, 3687388011, 2119938117, 2827748429, 3235814626, 1943795862, 982655659, 1583416575, 3637162242, 2899231071, 2356372330, 3229140115, 198960123, 3846475068, 1379416053, 3794102303, 4194710328, 1622023564, 2980258783, 1612348456, 3206356835, 2346630402, 955347169, 821327724, 4081137787, 2863165917, 2043355649, 448503436, 3529831118, 1098373576, 2154452300, 3915536064, 1741721503, 3989667375, 2498018598, 3111090221, 2451239649, 371187044, 2476450463, 2115422939, 3108069162, 4258140100, 2689547883, 1035006996, 290446056, 3920544792, 28092053, 2601721063, 4021987364, 318467100, 1559961229, 3913031650, 2150104709, 49270356, 3722496751, 2311386769, 1143265675, 3292662688, 3972381519, 2455100296, 1617099761, 2421726076, 1783080166, 2261765086, 1218624302, 2857474674, 2302060834, 3546888248, 1032153741, 2340941676, 328079068, 2490189793, 740867935, 3624104142, 1585037711, 1856136911, 1717156296, 2551956249, 370730527, 1811127937, 671199828, 1973541789, 806145565, 2632536732, 2824694830, 2549158326, 3875815943, 941204372, 1001702521, 3826400052, 4193710040, 50745642, 1293062837, 1041970744, 3817762988, 2674255278, 1058357022, 3904842671, 2225254087, 4291341999, 2609553612, 4143229959, 4237512560, 2910271684, 4066468195, 830828098, 3194488049, 2949340222, 2932945527, 2929064674, 1551247455, 3984924241, 4112937654, 1045724925, 2309857853, 2137885547, 2923347121, 4181282731, 2915373843, 1568721132, 1544506706, 2853606986, 1231383293, 2575465448, 3131073921, 2053909572, 2942680140, 396827888, 3916340049, 3526097716, 3106089469, 3522561956, 3015937009, 3739198049, 1425146641, 851135341, 3019020815, 4249482313, 4186849406, 3142115855, 4096457822, 1432901702, 1952216623, 2397263357, 1868450777, 1021098076, 367053436, 1889683424, 1528567953, 3087804116, 689228227, 2409781986, 2752631639, 2960393344, 2301774469, 4157044152, 730723095, 338324989, 783259147, 1430926216, 364208092, 2781791540, 805329298, 3841626209, 3970169746, 287294352, 3731446660, 704479128, 1206988970, 3298938102, 89005416, 3951683481, 835191365, 679211944, 949588029, 4076949094, 1529663160, 3763599166, 1992389156, 3959751596, 2621078932, 750118917, 882657993, 300498126, 1496181503, 3757618374, 3957243704, 3918083074, 1894830898, 1138422947, 3463164955, 3636023625, 257441260, 1054022983, 4011330770, 634925427, 1390194826, 1996961100, 3964708260, 1299498822, 4278592313, 1555238361, 1205023411, 311299324, 236721311, 3010275108, 773372856, 3619575032, 1947972130, 922773743, 1813182889, 1430693131, 1140839147, 3512260679, 2399704504, 2884240894, 3489240991, 3667939455, 3637582953, 3111367472, 2822381631, 703081566, 3036849914, 2845998620, 773679554, 526636749, 3314520937, 13776732, 796381020, 3189459033, 1934043296, 139616721, 2828193945, 3267247609, 589042452, 1387645753, 433640237, 1712804027, 1437726094, 2315749526, 27879840, 2472687972, 4005884263, 2644286003, 3168722815, 3959061551, 2404760593, 987990445, 2910703005, 3677874076, 4091231914, 4119403177, 1473482319, 1037359752, 1631420571, 2267882683, 444729973, 2607180061, 2466991138, 1500108829, 3858708078, 941735860, 3449116164, 1032454377, 1971102799, 1555909634, 1983708971, 3293773413, 2291541419, 1909009948, 3757184049, 1659282643, 3010427039, 2230678723, 3692534068, 1571464599, 533744779, 900521822, 737309762, 4215816039, 4242327287, 3884240140, 2486598498, 543513492, 2325077751, 1441237310, 3453763982, 1762843580, 1455435252, 3579975980, 1431912968, 3904977435, 3063717287, 8851622, 781126329, 3347412227, 2209219872, 2335275863, 4089034368, 1297331762, 2395499389, 1735909479, 1433771236, 1874079286, 2401526645, 3979584502, 814026601, 430924818, 2581307431, 643293685, 1092152530, 3681627832, 392138944, 3285203886, 1924582243, 3446213836, 3409964164, 2159521691, 3859916944, 485937737, 3082540537, 2628652573, 2085005488, 1570820241, 3255326214, 2324771674, 968029126, 551752207, 2734613650, 2519802827, 770398677, 588214604, 1769698821, 1440668325, 2016437193, 1333156524, 1671885991, 3833566075, 1771521418, 3300003753, 1697599567, 530705419, 2676238526, 2443737372, 3125150670, 321490908, 2097084981, 4189778990, 3647867606, 1625184465, 4268086243, 1553897575, 2306003829, 2205478208, 3688371963, 1133515039, 2669386733, 2223812538, 2214358594, 96593859, 4190632593, 1452197431, 1135606083, 2782212791, 2805304587, 2716383209, 1021017905, 1848454580, 637206058, 3630544172, 3327436426, 1359058780, 3757283546, 4081247529, 476986455, 2103327529, 261011811, 3377587780, 2208830435, 2954839100, 3294212947, 3523724980, 572494204, 2312304117, 2237590844, 1825143066, 3523469615, 2955256347, 2205596286, 3913732250, 3169279660, 211384653, 3129298603, 3451891904, 1392695925, 3936245195, 2315924122, 4256973470, 4208012834, 2914727856, 3790633264, 1352414024, 3268830516, 499517949, 174767898, 1457739315, 2708146151, 462102433, 15650350, 442999273, 3598360532, 3949145914, 4359748, 908554163, 2068608696, 1151136361, 3549502220, 3930154182, 1209162050, 2329490399, 3594864904, 1344017956, 2894570798, 1303761033, 880238473, 1215599665, 2238714951, 2775189345, 1440983553, 1580240888, 3808296473, 3676441154, 2656910063, 2780259105, 440787528, 2668696704, 3016754110, 73074429, 3699432385, 2168409706, 230768634, 404640783, 2512075223, 1443974378, 133144391, 3126908580, 1897307179, 285748108, 649198164, 3258373165, 619570044, 3705326499, 629753586, 2028146489, 1628060293, 1463155954, 594254860, 4203563010, 3465791513, 3768995488, 1179379840, 2659134767, 1087684809, 3708559675, 9397244, 3404138946, 3058055295, 3741047003, 900728367, 307309239, 1593283123, 3051916956, 2277186179, 2986400049, 2430308800, 3704675438, 3404110336, 3483462036, 66099132, 2203628450, 2586730089, 2420731626, 4042472356, 3655978764, 1856089837, 2068061659, 116363573, 1803321038, 802435566, 3965886166, 3600776237, 1563947327, 3756986210, 3427924426, 1576590362, 1417428898, 1027624544, 2293607126, 3716905851, 1499703715, 898967036, 2023639876, 45607182, 3304340202, 2558449320, 2150787328, 2110495244, 104517510, 2634417946, 3511927445, 2617983280, 1519839278, 2080506268, 3510088443, 3374267769, 36753302, 1909343363, 2722532212, 3354690838, 256523639, 1948127569, 819808246, 841164328, 1517898429, 1087337370, 2670414963, 179511035, 4259795329, 1457200223, 1097109826, 3252883568, 2453318932, 1234667752, 1093803264, 2111693083, 3511689983, 3823822344, 1905658711, 4144934159, 3435456888, 3949822649, 1400424939, 3976610504, 1652341050, 3552094049, 1465533861, 700947875, 2014956419, 1226278410, 573601914, 2391611176, 896583523, 3273421219, 2062693644, 2473342105, 3141025520, 14886427, 3812114714, 1853239414, 530505244, 2291720315, 962867072, 4243165058, 3342695710, 760937000, 4153054130, 2531380355, 2739976263, 469524224, 1295576354, 315429703, 1260352560, 2029030092, 3865675090, 3044871516, 1022845266, 1911371710, 2029537835, 561158867, 2174744632, 1969959061, 4102284246, 3981415584, 845291562, 664613325, 3222931218, 99095455, 2730475474, 2493017145, 2530889390, 3882983360, 2776234628, 427527768, 2075694791, 1903254438, 4039149192, 30770042, 2496262182, 1075501546, 1857577671, 4034387356, 1298016668, 554687483, 3783554334, 970938499, 2302276336, 2465839556, 2875226988, 3946025154, 1605779475, 212491074, 2039324795, 2511272148, 3923741618, 666705577, 2301221278, 2244215846, 480775695, 267961632, 1398864729, 3539474141, 2896696240, 3188210962, 4263170711, 2166709809, 4043606422, 2748308566, 2036300676, 3485163043, 1231312509, 2222796131, 3353346189, 691566953, 1926907588, 3143133996, 218024902, 3303115913, 2741933253, 3455832203, 2188548704, 330825015, 2988198047, 4113395594, 4274856590, 3454076086, 462612564, 3932732738, 2847173559, 94324448, 302685117, 2819834066, 501928546, 2918695331, 3730187626, 4047509480, 3958497929, 1405651323, 5198493, 1435107633, 1798603038, 1425239659, 3810371916, 202010946, 4127037492, 3579977862, 4105633677, 1697820216, 4098674964, 3877256724, 392149415, 798840279, 3279443441, 4160309648, 213003724, 240523366, 4254997725, 1194184072, 2242246894, 1565800018, 3099244883, 1899811749, 1295189975, 139297877, 1760389535, 1791623988, 2047447468, 2718025083, 478431801, 2261672798, 4163824143, 954044303, 166186880, 165190820, 3209346046, 1767632545, 3208218630, 2170624938, 1520217187, 2770731000, 31985474, 1167140123, 1247499067, 1192858555, 2000398094, 323618032, 2385630760, 263840016, 3630549869, 4085715997, 3305918489, 577978082, 2569352262, 496663850, 3244713533, 1371046284, 1053634009, 1596337603, 2530667353, 3571699092, 2985850617, 3506241759, 3886001202, 321142492, 3535666188, 2809260421, 2520009183, 505825281, 1161639420, 3107872099, 1807858866, 2661099911, 3683524084, 1968535972, 2137059248, 520800332, 1760245308, 3261727857, 3808954978, 1344215885, 1106658531, 2477902650, 3739801516, 2862406397, 3752206269, 2406717892, 852545984, 1600683943, 515483582, 1404164392, ], &[10; 3074], &[ 544355609, 2080612505, 474062054, 2868914381, 4175375943, 2284265987, 2006086926, 1022807704, 1191462239, 4057295077, 1742845546, 963995393, 1793330401, 1777031405, 3410368287, 739939995, 1041362294, 2237517990, 3085234326, 1911882398, 1000116872, 3212496084, 3541713881, 486343212, 1144839297, 1769684617, 1326843881, 138007851, 3707784046, 495830531, 1399261079, 1847139479, 2758723677, 4043629100, 1320821374, 4234751272, 3837875302, 3913989801, 1186691311, 838895898, 1384482259, 4283811402, 367047088, 3643107896, 2526085076, 649223414, 1791169839, 2849235592, 3419557243, 3263372986, 3370732365, 2796562442, 2444974720, 4023941956, 219991109, 2722363964, 1745771730, 800298616, 3768599036, 2911796707, 4207776422, 962505160, 2276283929, 3745370900, 878306616, 1043868890, 1598992851, 3541405234, 3585481924, 741739358, 768416754, 2104158416, 667188290, 94999734, 1449245983, 1304898387, 3952648610, 3749151338, 3907793782, 4270886514, 697343495, 462890036, 3107970742, 2832474331, 53068652, 1591760679, 2493047965, 2269712178, 3127212332, 1627727636, 220072933, 1058723788, 239782222, 615409930, 92540838, 2239440158, 3229400779, 132365712, 2244883029, 2717014577, 3284349185, 2715245566, 2087016028, 2149900384, 2668083770, 3150016178, 4104628003, 3235315111, 116298815, 2863524918, 1851896166, 454745201, 2517300177, 3047989747, 3119930396, 3686293348, 227886227, 3942608635, 2173702672, 3705534387, 1370183089, 558572653, 3069040441, 2683696611, 3880030022, 2807151772, 3568078249, 3853541718, 1077019831, 1531990636, 2961805760, 2610976776, 779162368, 823574272, 1069286399, 3289229818, 215126626, 2410932476, 2128498220, 3276432715, 2928896858, 503147677, 848353265, 2922884423, 1302835606, 2596230484, 2703044913, 1523643853, 888898125, 3158939337, 1235805909, 3942344516, 3809919793, 4237160464, 1727222209, 1680614061, 1319363756, 1944995002, 744276474, 3789911609, 1595380803, 2797067237, 3627131268, 2372510515, 3029519061, 1552562132, 104910634, 666808881, 3689834577, 148283381, 2667276613, 1387543237, 2874274079, 365866176, 1748800741, 461139348, 1430749296, 475634569, 3863794037, 2976737976, 4226341364, 861052916, 2875033169, 3833545214, 1848290121, 673168334, 1696741758, 1567226374, 3750857642, 3352956156, 3512091573, 3065375646, 1061612315, 696567469, 2311589288, 1868895607, 2411058075, 2448930081, 3347410796, 1698003839, 2027838925, 2090786401, 3902975685, 1003715587, 3624383073, 810421072, 676664439, 410073539, 1745213221, 1706439870, 2839758065, 396679277, 3138119414, 3201857757, 2682423198, 4121890843, 399855883, 2905061072, 2453953975, 2703354213, 554677285, 259183339, 2188009201, 1361539690, 3631921384, 2749692972, 2594065240, 852665377, 2764939748, 1376526587, 797837718, 1107381816, 1336266326, 3851966951, 991265584, 2684419585, 1149376886, 2399653029, 807442420, 3882889584, 1226935278, 2244303599, 512947831, 2947892533, 2275841879, 2092713823, 285115983, 1600604463, 1184575984, 2741305334, 3339710255, 3585371074, 4139863808, 4232952527, 1352122042, 3414599427, 487864314, 1493967975, 893714998, 2208073270, 3601682776, 571426814, 1729996166, 1769140101, 867892680, 248785719, 444128848, 1420394413, 211620358, 725005128, 3811507891, 2674064258, 1462026079, 2212287862, 282651282, 4067320883, 1238856730, 533900559, 2220084201, 4060944136, 1193456289, 4115136345, 2260451127, 444418500, 2239948572, 2187568976, 3112894026, 3100618629, 3477513467, 832766583, 1063501963, 1098701627, 723902089, 1440862175, 1758307914, 1444117721, 1945605599, 3520968071, 3918782575, 1074744480, 2617148864, 2479987951, 1315574524, 2243849353, 4172397503, 473326373, 1156124782, 157766890, 673744894, 3172150267, 1171319614, 3133792904, 3781709316, 1725956188, 2960793571, 831947718, 1234879482, 2243106260, 1151575826, 1619494546, 2918418271, 1032275766, 575484696, 1902010103, 2115212007, 3102396978, 1178091090, 128951007, 3505520912, 110589647, 306799550, 2923957282, 2889535970, 3892716896, 3462061802, 141240336, 4094303930, 2055495582, 2991144910, 57488757, 610331479, 1212049985, 1755404171, 4087127463, 1599682327, 108549293, 1947624328, 1598336622, 1923508724, 1899546274, 276013626, 1637086109, 3439572386, 2595854833, 3322277930, 3124995765, 839416381, 2963675606, 3415056358, 358293777, 3857023566, 3922751231, 108125165, 3372985231, 3721218511, 1384426460, 3064886104, 659089119, 1339971848, 3971603972, 2446343777, 2403454741, 2863794997, 1916677070, 2015369852, 3104590431, 3056618309, 2156827214, 2307905130, 488558245, 2385003556, 1292779627, 2787456671, 2909130254, 4021667611, 3458226840, 3595701687, 2158188879, 3127097448, 3311473188, 3919657756, 3067540899, 299594906, 4077196443, 537966839, 743854847, 3860094268, 3209048499, 2702918213, 3164248873, 317003889, 3917679498, 3799050992, 951266511, 4225991118, 4266739594, 2120739469, 3738621457, 1099651895, 374074539, 1265691403, 2284873652, 3646098311, 4071518796, 535945130, 2124137181, 3799225436, 135130867, 3172238162, 4292781580, 2119931866, 464178370, 3767627159, 3038212842, 1517053286, 1373709770, 3206724807, 2485420751, 4048155892, 2927521795, 1557446590, 2850031089, 3887281135, 3031617589, 27036204, 2594933381, 3658916771, 568750334, 655449437, 3989400884, 870434119, 2424378357, 3308556968, 2496148173, 926500626, 453310341, 3007786788, 3572176970, 3046431089, 70595777, 2085799171, 2034796533, 486525793, 2625764439, 4140008006, 2843236988, 3203487606, 1142801527, 377634806, 3336004949, 2194740748, 2517752844, 1749583456, 1819363747, 317702209, 998472125, 2894865062, 4009728651, 1292745578, 605771590, 2985770441, 529717869, 616022604, 655055107, 3769545808, 999957674, 2639392664, 389728170, 2432365834, 483707577, 312118155, 1833398102, 1741491866, 4149823795, 3365822742, 3296721134, 1639516381, 1544385625, 2514130449, 2336047201, 3589938788, 3496135682, 4083263061, 2561381029, 2812904127, 4108861608, 3680511663, 811663733, 1486852554, 3205990693, 245170915, 1447693317, 1428078991, 1963724366, 2590241079, 2162317267, 2989776811, 3089003008, 1353427699, 3236242526, 2772630345, 2586319460, 567743793, 3351249614, 1483216367, 2833043888, 502766384, 468604393, 4074177567, 283893874, 1885892172, 2775655802, 3268796843, 757932028, 182396962, 483265576, 1827630762, 1348814828, 1914599768, 1542736747, 4008837377, 3928031398, 3959798677, 3267417150, 1831724203, 1940628810, 1689020497, 4024291136, 3599565751, 1053265784, 465418337, 506963367, 2361541882, 4054921138, 2041763965, 3380272634, 1069313562, 2662913459, 2911073713, 2063745024, 3042615940, 2885707484, 49955617, 122795689, 1432659959, 3566838899, 1022912305, 3074366276, 2709235897, 779370753, 815074193, 3609718797, 3955653232, 1977587688, 1092726583, 3460400576, 2402412912, 2289905750, 2283096093, 2485302212, 2110598404, 3037676077, 617723850, 3773615999, 1901972354, 4085473584, 1247720697, 38284959, 1475039295, 775357884, 1230046128, 4022114392, 1513239213, 3466970347, 3994679267, 78794367, 4164607793, 2404524874, 3501817385, 3648692470, 3582023751, 1516804600, 297037858, 3301716622, 4143991070, 1433511023, 3636151271, 785725003, 3256947243, 2993732768, 145528213, 2882082827, 306287102, 892689880, 2858200468, 673572608, 1114857729, 4039728859, 3781145679, 3489731809, 4050294518, 1015252516, 1606235882, 3246096674, 1237150149, 2696921885, 1004457220, 767366998, 4082637480, 404715162, 2488959529, 2678767407, 3470904027, 1957522208, 680787044, 2133572802, 4287690094, 2425234665, 2319466303, 3124182319, 2946314551, 4118395310, 2418044788, 1641411535, 2331894759, 1115181240, 1690753245, 3582163090, 4114829311, 3999259349, 3932770197, 3981656983, 158734810, 2791366216, 3126668984, 2329125862, 79170654, 3288883194, 1116608616, 3593934678, 680174024, 3734292056, 991025399, 628166212, 838778775, 422270740, 2052636586, 3236693731, 601983914, 2569941689, 956277823, 1460769101, 2314502408, 85666892, 2983372669, 4106120511, 2780933363, 1326799232, 588063451, 2157573778, 2194779493, 1349171294, 2139192181, 1738827207, 1904136648, 2704236600, 1190895845, 2509911864, 4106505453, 1789804188, 4116232187, 1607726772, 1423657896, 203660459, 3556905534, 4052550667, 3661443020, 1156588830, 2805709187, 2184734484, 4130306836, 2927048269, 3971037292, 2842478405, 2781492032, 2845544971, 2405419136, 1229584051, 1704985343, 802298352, 1315673769, 3070548996, 336912256, 2309309114, 2488808086, 4074100102, 2980713950, 1883306562, 1896416460, 2685437861, 1988595995, 3482976932, 1994751201, 1054411077, 2247266871, 2622594946, 2557403421, 2100367020, 1639567414, 944674620, 692581566, 3497401683, 4012350565, 70814296, 2364269654, 3892323191, 1574657311, 3805241597, 2646812902, 686993135, 501417336, 390190378, 81134463, 3969793329, 4088317331, 1563897186, 1210055530, 2418797645, 2949631413, 1028385013, 4253532571, 3271519271, 2168853833, 3385633090, 294123522, 2383157911, 3736161561, 421034609, 4212341207, 57710600, 3169107690, 3547598164, 1686629028, 2685848946, 3944310507, 3528974931, 2572063697, 2375154673, 1778716843, 3528372789, 2468656618, 3071584083, 1128961192, 3683193636, 4264628822, 2606286479, 3683466786, 343295774, 1491201524, 1324059187, 1273065858, 2947022196, 949706186, 3139787517, 3027668981, 513483209, 2342866950, 1266538374, 693610101, 199671380, 1615539257, 443020503, 3933429452, 1401582990, 3367992542, 1392526946, 3888223168, 3880705051, 3649058260, 1007051372, 4107344112, 1760297433, 2354240414, 960825810, 921810569, 3231825378, 3059257576, 1131654349, 129500080, 2605388156, 1865453484, 2126231061, 2139625780, 27436657, 2742674470, 3553648145, 390804806, 1848660501, 279438783, 2491570135, 505315416, 325197569, 3548414492, 3270595689, 3671811806, 3684623752, 1478777341, 507514100, 3783080022, 803976630, 3386243872, 454876331, 3758085216, 3800389363, 49854907, 530276073, 2294324496, 540748232, 3137528263, 587679483, 241157100, 4259372319, 283145971, 3833436183, 1757121148, 3331836651, 1029534421, 1137051106, 1617366805, 3616255466, 1150694365, 1505061843, 2723097393, 469442150, 2353136647, 3180649084, 3055477050, 2020452838, 1847113164, 1234875175, 2918051924, 724398594, 3800245220, 3073723744, 1377564728, 3712594581, 142337349, 2221242370, 1822228854, 2036943806, 1283238486, 717982286, 2220204244, 2788518871, 4087772284, 4140881301, 336583084, 934183049, 4127199100, 2422142089, 4134684551, 2002084614, 1407851482, 2825561155, 473115594, 3804454149, 3756070324, 98277398, 2736658987, 3835540621, 1666817843, 506136422, 346575074, 2713055765, 54649123, 3718842846, 333996391, 1375596046, 3429343896, 2222155793, 307076719, 2844291252, 3170323009, 2190094191, 722584267, 680134050, 591286112, 1781766288, 2649541898, 805407678, 4239934253, 2802854602, 3394256891, 2679967939, 3968333, 2282595467, 553579031, 3256675495, 851693005, 3740760052, 3873978264, 1539085407, 2577644981, 3005994199, 1512823780, 233392417, 4044923329, 614175247, 238946405, 4151502616, 2895824639, 2892298577, 4109109568, 3448807072, 1820447786, 573431056, 2758023719, 2233076218, 3251538528, 2807960216, 580233560, 2192653133, 2533930510, 1201446917, 430846225, 2598684172, 1625389104, 4251720843, 658085697, 155173541, 720428389, 835068946, 1111888517, 4108792020, 3993189257, 2850665517, 751278615, 2004209215, 1265975261, 3335070052, 1523409381, 836145757, 4073164649, 2610287253, 1225343379, 801694973, 1537640195, 2775974480, 2125318804, 3503233119, 2203019623, 3771029544, 1379439490, 2365560747, 628400928, 1856950251, 1967226098, 1292166597, 156503532, 3960895865, 1869014599, 3443518432, 2169255606, 4201459709, 1500591038, 730743899, 3318533450, 755872014, 4121547193, 666804686, 3088350896, 462999997, 3278009499, 303940334, 4063551426, 608129041, 1213223861, 1061590490, 1512754548, 3452663696, 1217722668, 3519482218, 2418190620, 3453670568, 1120841384, 456418284, 3387215218, 3662706237, 1790431321, 1320586405, 1813568193, 2936719936, 896771582, 3927131254, 3142775285, 1557700940, 2326809706, 3275552402, 3581023717, 157618985, 2030885822, 3103063223, 2850318185, 797823914, 1893765086, 751439807, 1389213262, 3356591972, 2930199659, 3909407822, 3238228902, 2252894660, 3159833014, 3565354529, 1144015255, 4166316542, 3451726130, 3301755298, 92345338, 2110091485, 233933603, 2038950148, 3807492982, 3951911538, 679060338, 2391680161, 1906417047, 3494346728, 4259683905, 1053098728, 988641744, 3749343758, 3005386887, 1962427861, 2387760070, 126939628, 3037361186, 3735412627, 3820100034, 2877271723, 2827593384, 1467042632, 3554961566, 2199126491, 1474834584, 2134653916, 459572450, 3351483327, 1063061880, 2546994043, 959403293, 1453480783, 45023651, 4182656431, 1621609181, 1049162248, 2587382448, 298280334, 1160086482, 1798572995, 1324196838, 4213575980, 4082125512, 3659257898, 1496522682, 2669601542, 1240791449, 396787736, 2384741656, 2300186205, 511911782, 3022808512, 2171807370, 4181893952, 1651646200, 57933192, 68207219, 2305160100, 4260477147, 4262150028, 2752852327, 949687421, 3269112793, 452432433, 1368356411, 261337000, 2958549600, 2162649686, 3851709264, 4130077532, 3618268535, 3716606342, 1278243876, 482097980, 777983234, 3966135108, 70902155, 2457361915, 617387805, 2001651528, 496373342, 3278313308, 1649028393, 1574941569, 2228636013, 227524447, 3558505853, 3450551386, 4036721720, 2883739434, 3987908438, 276027716, 2199572845, 962950325, 463160521, 3157657410, 2545135267, 299986190, 2225624032, 1335091033, 1116210333, 1341749985, 1200309524, 3632337243, 3178244627, 2075617198, 2280834777, 3806603492, 233497405, 2845574276, 3966355075, 3796588723, 3789497905, 2442366521, 1137466244, 3731928636, 3909286263, 1377159164, 2865504518, 1868538298, 2374721835, 2341537275, 1006554548, 3773876265, 3882008299, 137750768, 3589400563, 16312058, 484192503, 3868107471, 1573223847, 3647124730, 1415086936, 724749097, 2338843504, 2361959105, 2115018391, 538057079, 362974782, 668678785, 2531183318, 394218310, 3386890306, 3336523293, 296517260, 3858301570, 1716601718, 2006160620, 2372397969, 264548388, 2512734401, 2866715736, 1538211958, 3505363984, 355312830, 2918157313, 3070019382, 1917401646, 3649489497, 2242874579, 949987212, 1064697480, 3999448529, 3828574403, 1900689197, 3083807538, 3273525671, 1615606943, 3222910677, 2684389644, 3585208519, 3623035487, 1629134891, 2938685351, 267953950, 4070365596, 4037659768, 3019560913, 807559385, 298035491, 2598163507, 3457982022, 944125531, 667947136, 3527192466, 2934540867, 3844971831, 1664033826, 4019501589, 2257507754, 381974031, 323084062, 2848925430, 2525252210, 2997747030, 2010446890, 4151995925, 2219016264, 635511729, 1938335558, 3262666460, 4017378474, 925183423, 181434660, 3416005846, 2375706535, 1893169843, 867425139, 4266560011, 4261001209, 1974081833, 1495783336, 3645315131, 1371952384, 2231366915, 1809283710, 3174162783, 3692065585, 932072189, 2143319139, 1935751070, 1389073735, 3228643052, 2716651400, 2008913204, 622096395, 707783747, 3856671850, 415242370, 1529820732, 937112442, 790265210, 3512314545, 1249764825, 983820497, 1495557988, 1049339557, 807750281, 2099568336, 2869908992, 2378854541, 519046482, 3623024174, 2043891665, 3268337415, 1523536610, 2556116012, 513967987, 317614571, 3921124626, 2688549432, 3163209270, 3460158834, 1676365720, 3406680830, 1895314009, 2478089264, 3994902569, 120933160, 3371964816, 3548031081, 4188121739, 4165669542, 4262472718, 2548169460, 1994026898, 3762147713, 4229144764, 2355673778, 3781193367, 4115281455, 4230995643, 1081916479, 449667065, 2375935285, 509312700, 1572206518, 1039467114, 33291215, 1736165798, 3386906161, 1403006013, 3057089388, 725608373, 832959637, 3326066952, 2758630720, 780306312, 1823175215, 1756482562, 3783642888, 2582262724, 2782974185, 96828431, 3432789810, 324379740, 2675018082, 3242192356, 3308487904, 2171079066, 1920850114, 347250594, 4049217084, 174334290, 2894755770, 1682660733, 3639674097, 3022460606, 4172589658, 116943302, 3986361534, 1422166077, 393384801, 2739155544, 907894212, 3551541090, 3873518725, 2744430045, 3807711638, 58201325, 343788661, 4226811714, 3878700816, 2311468073, 3495630203, 3565734040, 1740927154, 2246969894, 371220115, 2886036850, 2868234004, 3808320577, 3149189084, 1344292273, 1383218952, 2797016240, 13274617, 3646672567, 1715541479, 4008465882, 2746489174, 2032923305, 1003787730, 389106831, 1625722354, 872791047, 1163755310, 1782833457, 1122780937, 3674301793, 2962567527, 3027005428, 3421675397, 816528114, 2520772421, 3882265850, 191185211, 1915088679, 1136131632, 2917934999, 51969557, 3873182913, 3829719891, 3763027591, 2071822148, 2948549465, 3685647774, 3740460724, 3983815305, 228233670, 306748240, 2205655390, 2169840196, 57631823, 3501748332, 692415311, 3651127800, 4148163821, 39432986, 3699741440, 1198366749, 2669224033, 4013719886, 263487157, 3143931081, 1829033426, 1290237561, 4253302762, 3620861217, 3026498367, 1924278865, 2129615734, 1284338993, 740419088, 1476115804, 1674349471, 1373590050, 2962840532, 1086886015, 2948050969, 170021597, 1963009014, 2524590563, 923284704, 1535707291, 279837676, 1841164350, 322588089, 2750328817, 3646141378, 1024203883, 1969779698, 380904461, 1439698428, 211451903, 2996746791, 1790199287, 714183289, 2057885007, 3055483047, 3085898, 4282811050, 2202405947, 3212388463, 3791241669, 1458404120, 1181255669, 1163142856, 3365570634, 3840757205, 3227216263, 3218780114, 2183401479, 1668253988, 2521856256, 3531099575, 813705343, 3186927278, 2613309797, 977097253, 2838513713, 3131199744, 2159039969, 733325244, 4085628955, 3261547479, 1808066772, 250992165, 4027173056, 2516628679, 2485664871, 4066943892, 3885129031, 3128271561, 1605078579, 1412687920, 389648195, 3134571763, 2090188111, 3535196873, 3250823634, 1963313595, 4236639174, 3188091747, 1558647340, 1587110630, 2362648960, 847667422, 1818600295, 865349696, 1355021043, 2896242028, 987445793, 2259009360, 2058641378, 3017932902, 4263925141, 4039030529, 922140284, 678661653, 3124465806, 364324461, 53160573, 961854258, 262562705, 3642350584, 3187364726, 2946984520, 2337837903, 2577496482, 254618959, 1658071001, 445095500, 2572019250, 698759728, 3489488655, 660305830, 3172869360, 3008333264, 4108869853, 1480659919, 2193222371, 3164881436, 577842645, 396864946, 2251498887, 2783115466, 818817030, 2777540659, 3292804029, 2495573384, 52861550, 196516661, 4081623143, 3182305453, 3639468541, 963044873, 1723976782, 1743809340, 415885010, 262631269, 2541205840, 1887739701, 3537112992, 677373721, 3376801371, 1366605844, 2050672696, 2009821574, 3363232635, 2699378367, 1656613261, 1106865976, 3325917870, 3709679487, 316233653, 1099555783, 2917740812, 1819153436, 2758919991, 136411226, 3303510560, 1950234035, 3123211002, 1661268876, 3092013391, 3401906228, 804899207, 3429735604, 1119104687, 1527334549, 110162900, 4205306363, 2965045371, 3224282444, 1387479162, 3482021749, 641230778, 2484149227, 74145495, 667532876, 746632698, 615670999, 802531291, 4068450187, 559037508, 2410203600, 3173998761, 2414949060, 4250307478, 2677924923, 254875175, 2750491186, 451361625, 1490449121, 1911989075, 705273128, 2993458230, 2531413775, 221330602, 3607043619, 2832975328, 2785439377, 2175420602, 461343516, 2149257009, 64004519, 1834736566, 3526694904, 1345324, 2574179543, 2173541213, 3648164188, 2441837986, 2302064699, 1897950238, 2062029056, 623179729, 235835418, 3696876389, 2275547090, 1063491599, 2500366108, 2553421358, 516021674, 820064438, 1829558386, 2269327248, 641085617, 3571348267, 3414776281, 555925412, 3415049186, 4071446477, 1844604868, 805541049, 872648823, 3801041544, 3068396764, 3071270530, 3794865520, 4202235705, 2297800920, 763632754, 2083936963, 2836971110, 3995016591, 3398237394, 1203477946, 2507654360, 426992170, 1021567254, 4126934650, 1551918171, 1902836221, 994606291, 1687196968, 3302729384, 3862031719, 2323821450, 2198316563, 2540812003, 496118884, 3246203986, 2646253091, 1728288511, 3272115902, 4238725201, 1853048564, 2057055954, 2674412833, 2822025441, 3295385080, 1559234133, 3000676765, 2870421002, 1548768696, 3428399922, 4084596073, 1413011680, 2246354194, 221378010, 1761252139, 1162599628, 3513756657, 90592612, 1988494097, 1105275258, 2089567745, 2998838495, 3953491813, 364632274, 126200165, 1612007030, 1567790004, 846868583, 2547791738, 269855914, 4032384370, 3746164021, 394230659, 845662026, 3845072850, 2566488043, 2170205621, 3514481342, 2982439207, 4222310093, 1365580426, 1870921277, 702951042, 1487443801, 2206519103, 2816450438, 2084648461, 3634087131, 3370864055, 1170986620, 1307914636, 2464599466, 1928094516, 3449406714, 1486190614, 2804318619, 4199030156, 1372088422, 2721401584, 1823089391, 3589579994, 53903387, 775871039, 2148863830, 1211809608, 1466549974, 2932329000, 294240089, 4148011680, 2606394538, 1551595207, 18437086, 3870848475, 3963451133, 3858293930, 583780669, 1777740415, 1168874756, 3801614, 4054375944, 404916297, 3086659167, 1644039632, 155306589, 1877697577, 1819574777, 1655511547, 1975709851, 2155167407, 1317557508, 977888829, 387692628, 1801386365, 1355070840, 3779570486, 2763830935, 1814654166, 3686825878, 879580242, 3556208695, 1189422865, 3256473657, 2689265288, 3584464400, 1389798501, 2299654449, 1596970200, 1635139470, 1600912664, 1065106519, 2318834717, 4232317329, 1934733510, 2634026131, 2195642198, 2845879342, 2471256312, 3146307258, 1592946628, 98590245, 1040185173, 4164930384, 1488170192, 2059223958, 3951794327, 1156875867, 3150550335, 10771925, 4062792278, 621778379, 2152178624, 802155041, 1101029092, 354527136, 104311386, 2196011265, 1549512013, 3601741721, 458783748, 291023277, 2220275894, 3787925037, 3574728081, 2371901638, 3350167974, 491057564, 2040235893, 969422326, 3498791458, 599513800, 3876713234, 4058021633, 2197825372, 824758175, 2871127338, 1236739351, 1729601061, 1736072444, 2744326965, 1782185189, 285956005, 1370284895, 3879897183, 4093460340, 1003366293, 2067288838, 4080067907, 3219653336, 3794136183, 4213407944, 1650954752, 1864697860, 890337590, 2483342995, 3096470221, 3211240473, 1541081149, 4272180820, 1921941795, 4276868501, 2657782250, 1082867515, 1593771653, 4249740408, 393671700, 847016998, 4258403125, 2279321782, 3127544068, 2330799618, 3388263646, 1011035931, 2302492200, 3679422512, 2739454712, 2447725944, 1410204193, 1239960769, 2335415742, 4034628289, 217154321, 2312929490, 2847283323, 1758010662, 2798182716, 704650518, 1764636405, 2063450857, 38578646, 3093858691, 3167715523, 3774603764, 2989934348, 2012331954, 4062917415, 1735784556, 1562528417, 3078303612, 3332798558, 3821642404, 1112683342, 3744817608, 918262034, 370379804, 999987263, 665306315, 376490441, 1825664304, 754450413, 2510096664, 3789316010, 3052362459, 2687717750, 2218594038, 4293298946, 1788948562, 1367398961, 3870136645, 821541271, 3969748788, 1155451493, 1747425575, 1690656610, 1276266112, 2250260017, 2020612442, 2529425772, 2309227100, 2807241536, 3929922893, 1183227047, 2977259793, 1311217435, 999070078, 2752168524, 4223283642, 4246380954, 4123508068, 1731849455, 1134288471, 1756001130, 20824059, 1710254099, 1376878106, 637049007, 945651865, 72123517, 2664241016, 3514853577, 2713931455, 4046027446, 1955984198, 4017621545, 3041248107, 3639683889, 1214300370, 2218289283, 2894749054, 195827613, 133969750, 717701437, 4154927656, 218695447, 2738177196, 1420974119, 1002222984, 2136588504, 4175421234, 4286398959, 465010593, 1649044263, 1870887768, 2706060571, 2993578519, 4210257282, 352665767, 1626990747, 2122106151, 1991441823, 484609398, 1968108637, 267034235, 3663944477, 3497498817, 1298555467, 1820946055, 813976817, 973979545, 3558149570, 2052858623, 129423978, 813351723, 2860388596, 2874594109, 1894276258, 3875175622, 1181838780, 552362494, 2927906399, 680589035, 4189428995, 4100440378, 1459281238, 2696223655, 685225908, 557773591, 3692585034, 4095389710, 3507920903, 1100694461, 1200458755, 2700047360, 1010756832, 2836878993, 2599716200, 2421020345, 2525438781, 1587688915, 319331066, 3610048142, 3826219458, 605791648, 3609407242, 2538477707, 2460599980, 3036140482, 257193064, 4035967000, 2498611358, 2444041314, 2373434868, 2140306999, 563567659, 1159698233, 2762641126, 4154818731, 1764008133, 2952860729, 2027173579, 3800550668, 2682398852, 2945858522, 2356978046, 473298920, 1390211385, 1626451727, 3339732957, 3975656012, 963281208, 3223569785, 2186966411, 2825438410, 3066200364, 695250767, 2595558683, 1743100366, 748707855, 2719933058, 1020605740, 2648119052, 3505763871, 1875706095, 3622101865, 4038036748, 4093851036, 2691592284, 1248587369, 1144467957, 1921816097, 378585862, 1775800559, 938045171, 24817745, 2803294734, 1065147136, 2906907023, 3516494325, 1172235966, 2183375603, 1511831851, 1152614918, 2840253990, 1107546663, 1134755588, 536608442, 2111631275, 758552262, 2487574261, 3279088860, 2497117721, 1697010519, 2712455268, 2404149025, 4099555062, 3576954053, 4244802645, 1796996455, 2036356956, 1202823228, 54979161, 2680738268, 2788198200, 3210203298, 1836202712, 1137233831, 1629065704, 2804856386, 469139538, 2833170458, 469500302, 3325984525, 2705206009, 1967695924, 1585889929, 2146430815, 2347120626, 2124064426, 3965474758, 261325335, 544186624, 1690898942, 743159471, 2013266750, 2914223957, 3960466984, 1765154541, 983001537, 3976159631, 2683703437, 1174049322, 2874826165, 1262077369, 2769829886, 3531066519, 66016270, 2067537480, 3858041267, 2664217656, 1278779111, 1799701397, 2460646357, 279927022, 2547633840, 2971564668, 844621964, 2407301651, 2547958744, 4060907920, 775539021, 2273284541, 3411076307, 216981865, 3387791693, 4038497000, 2064678592, 223689239, 3381597575, 2785720594, 4028130365, 1088922312, 1428400526, 2058741956, 1938445154, 2901891415, 3533906848, 248391562, 1598571189, 1274277407, 2662721864, 3387940906, 2652463762, 2010354071, 3783520106, 179401923, 3510135610, 741510312, 3674896164, 1147072826, 384850468, 4177726882, 1143423694, 2632405832, 3120714386, 2337623953, 3642474663, 278717623, 524868652, 1668357695, 522688744, 1287850641, 2158007299, 2485773856, 316192556, 2808005423, 3298013517, 1709332799, 2966420037, 1594118586, 657895176, 2660878261, 3063768836, 2975113253, 1069435351, 4071721369, 3148504718, 2639750143, 2617415862, 4246948401, 2744669640, 959176102, 2879440624, 260950886, 4264677991, 890604030, 3943171503, 1153581582, 2648776662, 341880069, 3802271662, 2082556612, 2052482296, 1396470246, 1291404816, 894775492, 1870279878, 2587444056, 3220469802, 1393682137, 1363647579, 777022364, 1426882091, 2369790077, 997107878, 177923107, 3831198071, 2125001182, 3921642379, 2441779185, 1633189248, 2367759250, 4079331442, 1413642253, 1901177515, 1936953724, 1879598361, 755185816, 844490707, 749620419, 1858996628, 3372432253, 3635783608, 3291277496, 2646751941, 4275867653, 3315645015, 965526434, 3141557797, 3545226235, 455560691, 2910050619, 4230554591, 2514237392, 3475136309, 3414853019, 3439994926, 677034233, 863272265, 774851933, 3215462454, 1626257754, 1060195911, 3330518326, 2058735742, 4277830382, 120508857, 10349099, 2360047298, 1147270030, 1669346204, 3164948300, 3276712406, 1090825495, 3336858910, 1067156081, 811708915, 2217482785, 2187684339, 1105052253, 2899523744, 2144117806, 1182890427, 603527208, 400025719, 1635531955, 3184515856, 2996156197, 1109257516, 1438412469, 1128184215, 3835631242, 1986630841, 4215212096, 2147483812, 3296027198, 4247185794, 4028891232, 2992689352, 3199348010, 4166661900, 1128505410, 1818937517, 977379987, 559699801, 3526456143, 855066198, 3162577377, 1844016075, 420257003, 1020528439, 797490656, 4195410773, 2042327528, 1981205681, 1634173708, 3290076459, 1188324461, 2194485264, 249257667, 710780707, 3902304963, 2563721521, 121410281, 1010789176, 965480853, 3551582682, 1414069580, 364509720, 2618252137, 2202510871, 181090986, 3262751128, 3162233271, 3324791535, 3286198872, 3126251757, 2867781188, 3214600621, 3420241587, 1701458765, 1107110151, 1880972823, 2366736607, 3802279381, 1147706669, 1678354017, 2338064135, 378205819, 543458596, 4067960199, 326647146, 895182393, 1620615430, 3236775151, 1676297168, 2723074476, 313615280, 3458558228, 838532854, 3836338910, 4126720179, 447107335, 2522588986, 358162529, 3102875855, 40331308, 1700560944, 2619282419, 1323032831, 576655124, 2121890683, 454009455, 1611856018, 95321415, 3159099343, 2624793510, 139254963, 3007002967, 3046869496, 2504389944, 402007098, 1120401945, 2320367467, 3822028515, 2128547975, 728566168, 2720263950, 376370725, 671504810, 1102525681, 858802947, 2407677110, 3899865885, 3238068758, 928258875, 3503253617, 2496097677, 1090472781, 3769635775, 713162550, 3924147908, 3088019766, 2794584330, 3921762979, 4263696196, 4099925085, 1452359352, 3071060808, 2171402846, 1775765123, 3353726136, 693656823, 2215697894, 1581680393, 2459109874, 2610514747, 1636281368, 1935156617, 1518326299, 3811662146, 3052308992, 4016011731, 2525869209, 3199868849, 781183068, 3909124675, 1855754701, 2718011142, 1017563932, 3009254942, 3771127673, 1888265122, 3655046264, 2733133491, 4269920361, 3968936320, 1387307540, 3911304570, 1381672884, 2631100794, 889839068, 502873971, 1645726487, 3409353188, 4207111356, 2389633452, 3169396047, 556329990, 1275839227, 1919169103, 3421757222, 2063449467, 1344911918, 440063664, 575382039, 2778635596, 659279135, 2865737756, 1497472026, 3455082775, 2351352609, 2218315286, 862912648, 2275185045, 1044902041, 3742809957, 798827446, 1303950178, 1389761794, 3459284470, 1627506744, 2946964178, 3119156935, 985565880, 4012898742, 4254608009, 2019607596, 457517311, 908198848, 2391346217, 1280204952, 3186268, 2327766882, 4007742117, 268675722, 1508916405, 67592678, 2909233082, 2975352339, 4150088609, 845353802, 1246467789, 3211639510, 1598175163, 2015042287, 1159535595, 3039644640, 2024780164, 3817310144, 1314793916, 3931129644, 2297902041, 2744401140, 2155319197, 1274333778, 1590647569, 2064174726, 839581832, 3180899057, 2734604085, 250368037, 2325830975, 4021903632, 4209659583, 4087575978, 660545834, 676331819, 2332664139, 3915409196, 3869013874, 2072254366, 1489561563, 41383485, 3373077713, 2339267375, 768611244, 2111817536, 3308344638, 329648827, 4058123276, 3596509162, 157841641, 3025011358, 745256997, 751836219, 1738832488, 3104811027, 2572481274, 556241905, 143116006, 2981693323, 2825496962, 955861689, 3150803899, 1797906830, 3632639062, 1111189328, 1854921423, 1611801898, 1732904082, 2380496915, 852045714, 1582105277, 2128955243, 3610026083, 1842139797, 1651848148, 2184981539, 1566494807, 1023570434, 3427831203, 3318420767, 1891760251, 115998922, 3008231250, 936023514, 940664041, 3503816225, 238596895, 2415722666, 3544614197, 3992896188, 3062834010, 3584536939, 3253098143, 194333715, 381258355, 1983199885, 1683403067, 2218849076, 579428679, 2440305438, 1460652462, 3030360784, 3505984098, 1364689613, 1357944353, 3051635011, 3030326404, 1461020438, 1931054651, 429832151, 412640230, 1101806527, 2407972600, 1754169295, 2925930697, 1799944013, 2477339313, 2252685253, 1781295997, 2161398638, 984942638, 1997653908, 3175765172, 886822188, 2072153716, 2559904381, 2906429790, 994568336, 4137548428, 2165395553, 3721532569, 2791955106, 4002005849, 1795290415, 777356562, 1283796138, 885689301, 4200387845, 3520650868, 1793108559, 1944953438, 2519625856, 1321083559, 2471609790, 4154088871, 971788699, 96486902, 3917953517, 192828625, 1360773575, 3934994426, 2734798540, 2618623306, 2827539934, 142408573, 332353652, 1071198438, 3052822037, 3669652208, 3349217466, 461828931, 1955352011, 254370177, 1493951591, 3811317580, 954414114, 866375483, 3419445101, 2214895394, 3517054322, 4161425935, 3973658488, 1894053030, 2918545108, 1843644863, 2422639014, 217434620, 3471716433, 2175164467, 4147044804, 1399830516, 2600229730, 3230553946, 349040171, 3308181171, 1722528579, 1892962581, 674543130, 1359065857, 888420701, 2239693478, 3134792376, 2261014987, 4972872, 3972656514, 3917247995, 281467403, 2386392677, 3427533977, 4190760555, 861503511, 3094011736, 2544900610, 3235067355, 4281089945, 893898096, 623017175, 2684358541, 2982621388, 3420249402, 1836312846, 1762132747, 3524441344, 3694431079, 2521182822, 2689482723, 2792871670, 2075567778, 4270142052, 1117455219, 2245600198, 1016538829, 2546770766, 3472047555, 476718632, 4102270410, 544907404, 400447925, 3078669830, 228044931, 4278139634, 509097914, 748704700, 1380534690, 2641425727, 3989091583, 796153283, 1488887826, 619046017, 3894025574, 2789984449, 915402991, 352971303, 3305199704, 302470373, 2958663620, 518499443, 320714422, 1818844192, 4179963684, 3546212233, 4281710896, 2693300985, 1843803815, 2109594921, 4133092241, 2200735204, 1950193752, 1649263275, 2084626250, 3979601508, 941132824, 1451427563, 589459270, 3858283949, 2464707023, 3257666949, 576301490, 1408214844, 4148284079, 1145082510, 2106736992, 2796596950, 2734784935, 3965180937, 2507456961, 2179846796, 2989661423, 2394534594, 4170707335, 2543880785, 2016782127, 3784924498, 1537622300, 320799861, 1451798802, 3665445143, 3285671710, 500367279, 524317043, 1516855663, 3416184232, 3830147566, 254079675, 3570808067, 3320568378, 2199094843, 3510157338, 1516001239, 2660566405, 4200281643, 2033492861, 2710458394, 2729223326, 2914055217, 2869164325, 3832975412, 1119282624, 1614883519, 2740796061, 2350354698, 3165195297, 972490337, 3303052553, 3246153805, 1815033751, 1093989571, 3725330351, 3380415411, 4138242707, 2798484855, 1488934274, 376319971, 2514579391, 502969557, 2839449931, 2981245353, 3127078684, 2759028517, 1376881472, 54822087, 488974487, 4010000483, 790974199, 1562528726, 978852295, 3833172997, 776544691, 3327119386, 3897537975, 2441018003, 3448454588, 2561580089, 3001392606, 3492750996, 544985387, 127819369, 1548131438, 3256827686, 3575247036, 4235524680, 3362541587, 2527132384, 1226743504, 3766442212, 3386986119, 1229394146, 461344162, 1331451495, 1966184329, 2491528033, 499382589, 2363039326, 1457684120, 1604016885, 3036831259, 4163090959, 2088877393, 2865208752, 1780187520, 3801239798, 1479955908, 3715027132, 882761528, 3020106543, 2562989248, 215766281, 2877522592, 3431546771, 1934700267, 1489283044, 2391771743, 2778608932, 3492958770, 1334965651, 2700169807, 2797883820, 3697186486, 4265006073, 2307263582, 3889090615, 2570991705, 585261922, 1375634260, 129417005, 1472879519, 4073252018, 2553392302, 4265850970, 75767481, 3003655040, 3361343474, 2134392662, 2686376109, 2073937069, 32815425, 3037049210, 2035074966, 2872325821, 187691478, 2715568668, 2745559907, 623684504, 2894400344, 3029550303, 2363555631, 2631089937, 606345162, 1919753740, 2701766153, 3083385171, 1493708157, 3413450998, 980996156, 131411013, 3473633711, 4087723125, 3396774492, 1004362022, 3937398693, 1412265574, 2776644340, 1092202248, 3117392672, 156745532, 1113823512, 3731618243, 1610364966, 181555257, 763891692, 460747886, 3299024691, 1632086016, 1939971267, 1076845572, 4137057593, 2177781934, 434207944, 709542822, 1744608982, 2452746239, 2143386816, 364665238, 1414204650, 2904303341, 2516259832, 2634602687, 2495694518, 3819272975, 4163770417, 3108194507, 2373881269, 1745665511, 3707303810, 1317466643, 2307551462, 2907951889, 2553226050, 1750425047, 1373792353, 3807535219, 3569571047, 3988805730, 3429621677, 2696895991, 1904430116, 352288071, 1248001798, 2699070151, 3828759487, 2848844620, 2438811302, 1119522597, 1824741145, 3115800133, 1437081946, 2674343726, 4238203648, 2007544784, 870095964, 2565980411, 3812426992, 1363015406, 1503012411, 2824513491, 1743996942, 636807769, 360934985, 1080753647, 1164183179, 3287213084, 635077248, 3502357311, 2270792149, 3791720568, 773273062, 115844337, 1890641046, 2210523344, 1310502919, 299491584, 3891834665, 2856565132, 1436615862, 3985164389, 1847420590, 172093621, 3605036360, 2238641967, 1545522874, 2865289249, 2951291433, 2022052811, 2695476968, 2061897674, 2722830901, 1498945697, 1493305686, 314672784, 156085298, 440472968, 3157836752, 2281606826, 966611104, 3295950744, 2755473393, 2922508586, 2688920417, 723065331, 756048932, 742667620, 1752775923, 592330858, 445704881, 2143212239, 2780727399, 1670831470, 2426725859, 3109452807, 1301139343, 1328433398, 2780459752, 3685996476, 3634310216, 3315816012, 255771578, 3165776355, 818752449, 163163565, 1453259694, 860383030, 643825696, 3049373901, 2662874838, 526238388, 4042681677, 2142910645, 175935869, 57508530, 3075927426, 3414951840, 2702600015, 2812408381, 1612918658, 1767878877, 1389979148, 2532184009, 1722111530, 3274892408, 94104031, 459066974, 10, 10, 10, 10, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_4_fail_1() { let mut scratch = vec![0; limbs_square_to_out_toom_4_scratch_len(3)]; let mut out = vec![10; 6]; limbs_square_to_out_toom_4(&mut out, &[5; 3], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_4_fail_2() { let mut scratch = vec![0; limbs_square_to_out_toom_4_scratch_len(4)]; let mut out = vec![10; 7]; limbs_square_to_out_toom_4(&mut out, &[5; 4], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_to_out_toom_6() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_to_out_toom_6_scratch_len(xs.len())]; limbs_square_to_out_toom_6(&mut out, xs, &mut scratch); assert_eq!(out, out_after); }; test( &[0; 18], &[10; 40], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, ], ); test( &[1; 18], &[10; 40], &[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10, 10, 10, 10, ], ); test( &[ 2869037104, 2562493618, 960519305, 4147639705, 1817463351, 3166022129, 3200769866, 789666262, 2654485924, 3686362402, 2179867687, 3980226915, 3671542918, 1896992204, 1514962591, 815867715, 3924270086, 4262628477, 3977258034, 1340257907, 6618754, 2720861064, 778635062, 682181834, 2891943360, 3002120306, 3399643048, 3139375492, 865948953, 3273305779, 388881948, 3544744413, 3963050187, 3002594763, 3339669779, 2722426929, 1246819181, 2786076007, 708438365, 1013683719, 3027751127, 1766272571, 2839608714, 2866928644, 2107420563, 4035553421, 2376700546, 621608197, 1993043072, 2666011084, 2265522039, 3230507984, 2869423257, 1776134078, 2413254013, 3859414865, 193597892, 4255395370, 168637254, 3364100552, 3883433219, 3117797624, 2738841992, 3052596910, 3280507008, 2860095630, 4031447725, 3454885698, 1783630119, 3036202894, 3585701130, 4184585287, 1329572188, 2352399996, 3076023682, 2989927975, 320530428, 2081170907, 933271377, 2974966675, 3452895778, 2331110373, 995864819, 1177147317, 4084213472, 1179430541, 361665403, 2401303908, 3027157843, 2778759588, 1031442202, 542151276, 4259656091, 745358488, 2580062497, 2004998882, 2066508478, 341659477, 958017378, 2415007725, 211645068, 3630737942, 2670158596, 3544834081, 2043760261, 2149621570, 1287267516, 3353570061, 3758258174, 4171807709, 1363035595, 2692148345, 3728232161, 2672522097, 3234166892, 1337714504, 2475062988, 902334395, 3470019951, 1789926953, 39991566, 1071624731, 2480238280, 2010573056, 2975909089, 2685102208, 1752958961, 2957725128, 2441562510, 1615057382, 2739912075, 962437876, 1445592393, 750430353, 2848157371, 3515397641, 2140566969, 3080139371, 3564834440, 561913271, 1812943111, 1349101061, 1627550717, 3467766096, 194766042, 3125120919, 3021598191, 2389614341, 2536207717, 3687483968, 3746428277, 1304917109, 4262793424, 1046105397, 103309888, 2808595193, 1896772845, 2625389818, 1425524079, 4245371665, 1376995745, 1906643058, 4123808395, 4010921636, 3668036324, 538106732, 429893286, 1473862381, 692485290, 728791765, 4006267410, 2159349173, 1146991809, 1105326804, 855626330, 2350214961, 3945267379, 4182769713, 1218539569, 2795526933, 508156606, 1596052577, 4135932990, 4009064452, 3154371819, 1789912473, 3737225773, 2339289640, 382599364, 2822801808, 1231473766, 3195594892, 3686689017, 2674031129, 2724276086, 4112764261, 79570030, 1908454621, 270118882, 3204318684, 2240304382, 1923066108, 3669840087, 3114917464, 57715381, 3015749933, 3183317351, 2563719945, 2409212385, 2256893938, 718636813, 3965735223, 1345089653, 1264444, 2296052850, 1092210950, 3468764525, 3967443918, 788417425, 1924956491, 3656370968, 4266402294, 389687964, 3067575949, 3786278950, 4368934, 3414260125, 1500941491, 4197777812, 1901284905, 2548021755, 1986057606, 2732888210, 3872664452, 2787539702, 3264559111, 753549553, 1048190618, 2900005727, 1868077400, 1284542693, 3154799998, 395567255, 2005460208, 4005052806, 1893310835, 3217932531, 2607307407, 3917316670, 2028218244, 3745680211, 2397481422, 736482987, 1916844834, 3868328610, 938512555, 1559481864, 729544587, 3690980706, 1759014647, 2060717833, 2250640148, 3619925046, 2153794810, 4127168634, 3259374700, 2051907961, 3964686808, 3841055905, 4242264783, 2314742304, 2209077724, 2577227865, 1487635776, 1585379583, 3475070421, 1683734827, 3363053669, 3722095029, 3857335408, 2852846850, 456879372, 2473892714, 2928343667, 541075767, 3595876467, 1688710352, 2071331730, 1142047400, 1817453168, 96871997, 3927306877, 3090061646, 3474317652, 437148773, 439538568, 324686794, 772632617, 1424328970, 580538580, 3999279969, 2022469388, 2802303848, 1147488095, 2053949131, 3046702544, 3822972379, 2920233521, 4031279543, 2356245098, 2951036256, 3287235943, 2760424423, 140913700, 689952328, 3916658401, 1694797888, 82150998, 4075118605, 1967095926, 1704543314, 3154572744, 408071699, 844684417, 1174429103, 3583461805, 1015646627, 861970508, 1906905868, 2272773809, 879277860, 2980820537, 1917774935, 247497916, 2403283458, 553129122, 3303057196, 4005726052, 1808761740, 1909802116, 964057278, 1586240623, 3097009405, 2048123311, 2481968244, 3155267854, 555253647, 4027932249, 229358586, 1015669317, 4112551330, 351151415, 1331401879, 1749898409, 3352469407, 710145444, 2903798473, 2876271745, 692844392, 2354652850, 100021926, 4212629124, 2971597719, 2697935131, 445511347, 1636699871, 2524940444, 1303870696, 3634945394, 2398930906, 1337769794, 3955409228, 2657553814, 1455809030, 701994564, 374320080, 519334058, 71402463, 2995013099, 1573823285, 2419768029, 4108602983, 4266125692, 3514998795, 2367509976, 2654621106, 562141353, 3101668250, 2753822172, 406447740, 4132920329, 3645443797, 4221410098, 1000631411, 2319369935, 3987192941, 609889174, 569928846, 3471449767, 761399938, 2925981744, 3610481831, 364846710, 2579622933, 1755359875, 3327963251, 2230753636, 3897751713, 3685870953, 720576993, 4008645094, 2170973511, 3057371253, 2362087099, 2415801497, 3804893423, 874616900, 4188156090, 2114593709, 3626784402, 2090293821, 1178445498, 3501583487, 3787814639, 1160994150, 3773261324, 3438864014, 3474697300, 3232616282, 3082635737, 3290126053, 1041836645, 1497490946, 2116412677, 78748560, 2610841375, 406515051, 2540982558, 1278151559, 910145724, 2942229044, 1412896287, 2420692111, 2829066497, 2762072644, 883699073, 4146766932, 968581437, 2262117978, 4102625453, 753476188, 3237270935, 2018964783, 1357948517, 655508609, 4163647115, 2220146134, 3618211357, 4228425409, 2053237402, 260628807, 4078275010, 3945722198, 3264848882, 3968277361, 1416596317, 2102516261, 833088009, 3907840277, 2017643605, 1067842330, 1357529659, 2472927668, 1649000973, 2222344018, 3784049396, 3227757245, 2898271180, 4043134215, 3862532400, 3955686618, 98246491, 3365854338, 947695294, 594787742, 320576666, 3333798817, 1904306436, 2975705325, 2991782885, 1736852103, 3844447384, 1817569919, 3224273837, 3598752781, 1577803239, 2950514537, 1562681940, 4068361583, 3868379584, 2088936482, 679461158, 301319738, 766873076, 1943559698, 2477791081, 359203531, 248689484, 1396200027, 1850343941, 1125961151, 3934233911, 1148111021, 3719148359, 1654482658, 1197396856, 3954632576, 2122559365, 197233285, 407487633, 4158181537, 3053296658, 2799166403, 2081625494, 844237749, 3509575975, 3964633958, 4179613577, 3338942399, 3816968642, 3007984156, 872005283, 1859074434, 3956327811, 56397907, 478149678, 4026802122, 1384639138, 368837837, 183900171, 785221208, 3231446529, 4057339631, 2617885657, 645209974, 3749331053, 3387891965, 3097021752, 3337686487, 207272201, 4090597826, 1337950862, 1489880288, 1626252138, 1844132502, 3785436754, 2455659736, 2722719185, 3556302565, 1609527187, 2416226913, 2766580345, 1869533642, 3531500453, 438426623, 158796542, 3488893438, 3084370998, 2058790923, 1154169553, 1385226416, 1509103535, 1162048903, 797370674, 170054390, 2752067502, 3119807393, 1923267976, 3762356971, 1978871808, 3723074764, 3460095249, 2837581806, 73932499, 3524773614, 2454111707, 2818213028, 3004873518, 864066450, 3576610451, 2315784966, 151779632, 1178401043, 3765993358, 1348598145, 3576623674, 3204205857, 3883955902, 2023814627, 795831378, 2827807531, 1331064687, 1837025931, 3540224087, 1381156075, 141174913, 1539904944, 1709050097, 22990830, 2938269544, 3188893513, 1701451446, 124677463, 2376122456, 3735869779, 3855792596, 3836459842, 3548479279, 290636702, 246664, 797902866, 2875170064, 2475070809, 4116284414, 1208231388, 2828093914, 3711751904, 2624075253, 758366641, 4278761943, 679106142, 1679478312, 4110848533, 540768264, 3004089076, 890051787, 1527108158, 2687541799, 1379201802, 1778300800, 3159280475, 693175137, 1706052065, 2740998490, 610778078, 1254469442, 555145750, 4257282365, 4088567402, 2722156643, 2973326370, 2580839471, 2297203610, 1325248528, 2289415165, 2027203297, 118624041, 3143737015, 3150787590, 2027511535, 3762291585, 2693532637, 2791300523, 2662758110, 3136152569, 3442748961, 1004378785, 2651776322, 2521157696, 2559348070, 3806708201, 1867376555, 3308198648, 792265193, 1257869334, 3432781024, 3378655514, 2353252813, 320451009, 3968297418, 237777247, 2490314264, 3266186675, 2255726749, 3147278539, 564923137, 794399730, 1624402708, 1616480718, 3606683399, 757916498, 2887385172, 2854589997, 3276729119, 133652525, 1045552210, 2262021731, 3248481891, 630857187, 4136667563, 3680583667, 2458003061, 102973943, 571665205, 4057786651, 1569357837, 1410019960, 1524881406, 1358182388, 785354230, 3829905260, 213334008, 2101845387, 3881098191, 1678603844, 2662511679, 2818265908, 3742761039, 662343317, 2881658894, 3293956365, 3576730814, 491183503, 2939708573, 879732964, 1424495345, 4226077578, 1724320764, 1649293059, 994517776, 3889024255, 3687388011, 2119938117, 2827748429, 3235814626, 1943795862, 982655659, 1583416575, 3637162242, 2899231071, 2356372330, 3229140115, 198960123, 3846475068, 1379416053, 3794102303, 4194710328, 1622023564, 2980258783, 1612348456, 3206356835, 2346630402, 955347169, 821327724, 4081137787, 2863165917, 2043355649, 448503436, 3529831118, 1098373576, 2154452300, 3915536064, 1741721503, 3989667375, 2498018598, 3111090221, 2451239649, 371187044, 2476450463, 2115422939, 3108069162, 4258140100, 2689547883, 1035006996, 290446056, 3920544792, 28092053, 2601721063, 4021987364, 318467100, 1559961229, 3913031650, 2150104709, 49270356, 3722496751, 2311386769, 1143265675, 3292662688, 3972381519, 2455100296, 1617099761, 2421726076, 1783080166, 2261765086, 1218624302, 2857474674, 2302060834, 3546888248, 1032153741, 2340941676, 328079068, 2490189793, 740867935, 3624104142, 1585037711, 1856136911, 1717156296, 2551956249, 370730527, 1811127937, 671199828, 1973541789, 806145565, 2632536732, 2824694830, 2549158326, 3875815943, 941204372, 1001702521, 3826400052, 4193710040, 50745642, 1293062837, 1041970744, 3817762988, 2674255278, 1058357022, 3904842671, 2225254087, 4291341999, 2609553612, 4143229959, 4237512560, 2910271684, 4066468195, 830828098, 3194488049, 2949340222, 2932945527, 2929064674, 1551247455, 3984924241, 4112937654, 1045724925, 2309857853, 2137885547, 2923347121, 4181282731, 2915373843, 1568721132, 1544506706, 2853606986, 1231383293, 2575465448, 3131073921, 2053909572, 2942680140, 396827888, 3916340049, 3526097716, 3106089469, 3522561956, 3015937009, 3739198049, 1425146641, 851135341, 3019020815, 4249482313, 4186849406, 3142115855, 4096457822, 1432901702, 1952216623, 2397263357, 1868450777, 1021098076, 367053436, 1889683424, 1528567953, 3087804116, 689228227, 2409781986, 2752631639, 2960393344, 2301774469, 4157044152, 730723095, 338324989, 783259147, 1430926216, 364208092, 2781791540, 805329298, 3841626209, 3970169746, 287294352, 3731446660, 704479128, 1206988970, 3298938102, 89005416, 3951683481, 835191365, 679211944, 949588029, 4076949094, 1529663160, 3763599166, 1992389156, 3959751596, 2621078932, 750118917, 882657993, 300498126, 1496181503, 3757618374, 3957243704, 3918083074, 1894830898, 1138422947, 3463164955, 3636023625, 257441260, 1054022983, 4011330770, 634925427, 1390194826, 1996961100, 3964708260, 1299498822, 4278592313, 1555238361, 1205023411, 311299324, 236721311, 3010275108, 773372856, 3619575032, 1947972130, 922773743, 1813182889, 1430693131, 1140839147, 3512260679, 2399704504, 2884240894, 3489240991, 3667939455, 3637582953, 3111367472, 2822381631, 703081566, 3036849914, 2845998620, 773679554, 526636749, 3314520937, 13776732, 796381020, 3189459033, 1934043296, 139616721, 2828193945, 3267247609, 589042452, 1387645753, 433640237, 1712804027, 1437726094, 2315749526, 27879840, 2472687972, 4005884263, 2644286003, 3168722815, 3959061551, 2404760593, 987990445, 2910703005, 3677874076, 4091231914, 4119403177, 1473482319, 1037359752, 1631420571, 2267882683, 444729973, 2607180061, 2466991138, 1500108829, 3858708078, 941735860, 3449116164, 1032454377, 1971102799, 1555909634, 1983708971, 3293773413, 2291541419, 1909009948, 3757184049, 1659282643, 3010427039, 2230678723, 3692534068, 1571464599, 533744779, 900521822, 737309762, 4215816039, 4242327287, 3884240140, 2486598498, 543513492, 2325077751, 1441237310, 3453763982, 1762843580, 1455435252, 3579975980, 1431912968, 3904977435, 3063717287, 8851622, 781126329, 3347412227, 2209219872, 2335275863, 4089034368, 1297331762, 2395499389, 1735909479, 1433771236, 1874079286, 2401526645, 3979584502, 814026601, 430924818, 2581307431, 643293685, 1092152530, 3681627832, 392138944, 3285203886, 1924582243, 3446213836, 3409964164, 2159521691, 3859916944, 485937737, 3082540537, 2628652573, 2085005488, 1570820241, 3255326214, 2324771674, 968029126, 551752207, 2734613650, 2519802827, 770398677, 588214604, 1769698821, 1440668325, 2016437193, 1333156524, 1671885991, 3833566075, 1771521418, 3300003753, 1697599567, 530705419, 2676238526, 2443737372, 3125150670, 321490908, 2097084981, 4189778990, 3647867606, 1625184465, 4268086243, 1553897575, 2306003829, 2205478208, 3688371963, 1133515039, 2669386733, 2223812538, 2214358594, 96593859, 4190632593, 1452197431, 1135606083, 2782212791, 2805304587, 2716383209, 1021017905, 1848454580, 637206058, 3630544172, 3327436426, 1359058780, 3757283546, 4081247529, 476986455, 2103327529, 261011811, 3377587780, 2208830435, 2954839100, 3294212947, 3523724980, 572494204, 2312304117, 2237590844, 1825143066, 3523469615, 2955256347, 2205596286, 3913732250, 3169279660, 211384653, 3129298603, 3451891904, 1392695925, 3936245195, 2315924122, 4256973470, 4208012834, 2914727856, 3790633264, 1352414024, 3268830516, 499517949, 174767898, 1457739315, 2708146151, 462102433, 15650350, 442999273, 3598360532, 3949145914, 4359748, 908554163, 2068608696, 1151136361, 3549502220, 3930154182, 1209162050, 2329490399, 3594864904, 1344017956, 2894570798, 1303761033, 880238473, 1215599665, 2238714951, 2775189345, 1440983553, 1580240888, 3808296473, 3676441154, 2656910063, 2780259105, 440787528, 2668696704, 3016754110, 73074429, 3699432385, 2168409706, 230768634, 404640783, 2512075223, 1443974378, 133144391, 3126908580, 1897307179, 285748108, 649198164, 3258373165, 619570044, 3705326499, 629753586, 2028146489, 1628060293, 1463155954, 594254860, 4203563010, 3465791513, 3768995488, 1179379840, 2659134767, 1087684809, 3708559675, 9397244, 3404138946, 3058055295, 3741047003, 900728367, 307309239, 1593283123, 3051916956, 2277186179, 2986400049, 2430308800, 3704675438, 3404110336, 3483462036, 66099132, 2203628450, 2586730089, 2420731626, 4042472356, 3655978764, 1856089837, 2068061659, 116363573, 1803321038, 802435566, 3965886166, 3600776237, 1563947327, 3756986210, 3427924426, 1576590362, 1417428898, 1027624544, 2293607126, 3716905851, 1499703715, 898967036, 2023639876, 45607182, 3304340202, 2558449320, 2150787328, 2110495244, 104517510, 2634417946, 3511927445, 2617983280, 1519839278, 2080506268, 3510088443, 3374267769, 36753302, 1909343363, 2722532212, 3354690838, 256523639, 1948127569, 819808246, 841164328, 1517898429, 1087337370, 2670414963, 179511035, 4259795329, 1457200223, 1097109826, 3252883568, 2453318932, 1234667752, 1093803264, 2111693083, 3511689983, 3823822344, 1905658711, 4144934159, 3435456888, 3949822649, 1400424939, 3976610504, 1652341050, 3552094049, 1465533861, 700947875, 2014956419, 1226278410, 573601914, 2391611176, 896583523, 3273421219, 2062693644, 2473342105, 3141025520, 14886427, 3812114714, 1853239414, 530505244, 2291720315, 962867072, 4243165058, 3342695710, 760937000, 4153054130, 2531380355, 2739976263, 469524224, 1295576354, 315429703, 1260352560, 2029030092, 3865675090, 3044871516, 1022845266, 1911371710, 2029537835, 561158867, 2174744632, 1969959061, 4102284246, 3981415584, 845291562, 664613325, 3222931218, 99095455, 2730475474, 2493017145, 2530889390, 3882983360, 2776234628, 427527768, 2075694791, 1903254438, 4039149192, 30770042, 2496262182, 1075501546, 1857577671, 4034387356, 1298016668, 554687483, 3783554334, 970938499, 2302276336, 2465839556, 2875226988, 3946025154, 1605779475, 212491074, 2039324795, 2511272148, 3923741618, 666705577, 2301221278, 2244215846, 480775695, 267961632, 1398864729, 3539474141, 2896696240, 3188210962, 4263170711, 2166709809, 4043606422, 2748308566, 2036300676, 3485163043, 1231312509, 2222796131, 3353346189, 691566953, 1926907588, 3143133996, 218024902, 3303115913, 2741933253, 3455832203, 2188548704, 330825015, 2988198047, 4113395594, 4274856590, 3454076086, 462612564, 3932732738, 2847173559, 94324448, 302685117, 2819834066, 501928546, 2918695331, 3730187626, 4047509480, 3958497929, 1405651323, 5198493, 1435107633, 1798603038, 1425239659, 3810371916, 202010946, 4127037492, 3579977862, 4105633677, 1697820216, 4098674964, 3877256724, 392149415, 798840279, 3279443441, 4160309648, 213003724, 240523366, 4254997725, 1194184072, 2242246894, 1565800018, 3099244883, 1899811749, 1295189975, 139297877, 1760389535, 1791623988, 2047447468, 2718025083, 478431801, 2261672798, 4163824143, 954044303, 166186880, 165190820, 3209346046, 1767632545, 3208218630, 2170624938, 1520217187, 2770731000, 31985474, 1167140123, 1247499067, 1192858555, 2000398094, 323618032, 2385630760, 263840016, 3630549869, 4085715997, 3305918489, 577978082, 2569352262, 496663850, 3244713533, 1371046284, 1053634009, 1596337603, 2530667353, 3571699092, 2985850617, 3506241759, 3886001202, 321142492, 3535666188, 2809260421, 2520009183, 505825281, 1161639420, 3107872099, 1807858866, 2661099911, 3683524084, 1968535972, 2137059248, 520800332, 1760245308, 3261727857, 3808954978, 1344215885, 1106658531, 2477902650, 3739801516, 2862406397, 3752206269, 2406717892, 852545984, 1600683943, 515483582, 1404164392, 2625795199, 1947658962, 2081075491, 1506117942, 2881196791, 1124436092, 943233079, 3830847156, 2066671345, 1714460049, 3341680517, 4122571588, 2566663117, 3684270833, 667555911, 2348733364, 1961106649, 1440628769, 1419633260, 3052369574, 1108620071, 3434026162, 3916636599, 3102975331, 3886608438, 726540295, 1959301605, 1097548123, 4197775113, 2426454473, 1977350598, 815012862, 2487421470, 2968184113, 3186369366, 2845700438, 1474463355, 3590404890, 2351730037, 3978816218, 227579243, 185502596, 1922772057, 2864373880, 1909608765, 307719594, 4182459185, 3812324913, 1740357086, 619281590, 1426834026, 2868540501, 440166317, 3324081248, 1368857307, 3133154844, 1142185935, 2703145826, 1436656515, 2490167985, 2881509383, 725592411, 1056415214, 1801603748, 1098036334, 728276877, 1517386665, 1881520126, 2784785117, 2287558410, ], &[10; 3102], &[ 1090717952, 2156108212, 350273489, 3024455201, 3838859480, 1763682042, 149424184, 1964532786, 2975786529, 1330105564, 825339885, 383596706, 1309738864, 3102683106, 1267756411, 331533132, 2276890860, 3327701870, 3922167079, 2896074883, 3076190602, 3663514288, 3805009976, 3294968413, 3454159952, 1433044633, 1418330474, 3359465151, 726279979, 1342757809, 1717772144, 1003085734, 2383148345, 3108498579, 857262627, 1951196781, 970979556, 3558349653, 719437007, 289934369, 2266211882, 824447611, 3232349724, 578075700, 1450980059, 3899374024, 3220048941, 3157852665, 1409605220, 4279778126, 723171133, 1113923114, 4140464683, 1264137218, 2056188435, 258995120, 892162965, 3829554944, 2681105510, 1583433375, 2372905114, 3063477039, 1123473845, 2771465128, 1571676395, 3132543233, 1955633100, 295321580, 262431222, 3909294962, 1234323475, 1146977857, 1180244615, 2708777032, 2757620357, 763176798, 3489960920, 827421850, 396692493, 863122461, 2175230819, 3275878842, 174471042, 3146862584, 342421814, 3357270023, 3523699447, 1545479571, 4121473980, 3235129130, 321714055, 2578600590, 3034329217, 4088280907, 3865395634, 2465310687, 458941873, 866729095, 2456475470, 337410335, 2743205123, 1612928815, 2774001661, 2444680802, 2258871830, 294989145, 4032430053, 4160268372, 2581206833, 337233193, 2411041307, 2210559675, 1320636980, 3315911595, 3275455465, 2302984096, 672110132, 3653048361, 2876650516, 58619071, 3097462899, 913822537, 3958759751, 218968646, 841019768, 323642580, 3646079085, 1025622444, 1153752989, 896362417, 3233047963, 3053144671, 555216364, 3984925976, 4208406960, 1290598093, 2870076640, 3997709916, 708454500, 3105972733, 2678703766, 4256363437, 2450765138, 2014095400, 4105425179, 2141725957, 2199910230, 626073960, 2865754057, 427257176, 3022160073, 748977777, 711453669, 185620628, 360059795, 2223254315, 1556884756, 2383089920, 3314628127, 2991750905, 1339531032, 2488885176, 3516500513, 507416144, 1013539888, 3457856430, 3755907081, 1921624927, 1369652151, 1997994368, 1850993214, 459124004, 110586114, 2684660650, 2943708645, 4489517, 3069666339, 2647257714, 822416462, 363903775, 2782178150, 1587688149, 2234131461, 3028274281, 1791850871, 221035845, 1804019576, 1116698406, 367798193, 1053448930, 533397614, 863734009, 3655389622, 2116781843, 1800956650, 2698452833, 767322912, 483461998, 2355309940, 691456151, 3678411612, 2512848231, 372079251, 506701987, 1632924476, 3355892148, 2737715179, 1086990673, 3418273230, 1792484018, 775455026, 2920706888, 4051313610, 565136534, 4187413306, 2454459484, 185646538, 1004207878, 1369245165, 2500961438, 3476225504, 3587974751, 1342369718, 2164703585, 3648159154, 1734858305, 93034281, 542413582, 440717259, 969487131, 2111774966, 2310936947, 2303488867, 3256353251, 4175586953, 2454152906, 1789194116, 3011411086, 741565289, 1498115892, 3457474742, 540380691, 455385499, 2738934502, 4210812951, 1783205427, 3541032100, 3134343662, 3009641213, 4026234562, 2665343131, 1063120987, 3884850565, 1192430939, 323970520, 559177982, 1345369739, 626751520, 2278721886, 2044575907, 4214314085, 219732149, 3523631645, 3754346449, 2727490575, 2376307667, 1853405706, 1796550525, 2321489264, 2107896542, 3370749017, 3741446121, 671566537, 2578490527, 3744263087, 933713676, 528348682, 1174527824, 1633600618, 1449659937, 1961464045, 1435261180, 3435913817, 1674813267, 740556665, 1925082839, 492222737, 1152842767, 1001774028, 440836527, 3036608531, 1628710758, 816418073, 1474809294, 3227390248, 2473395569, 3414888182, 656330010, 1479130138, 1403564030, 2205423473, 1247584460, 2852752376, 1655058304, 2479120219, 38826481, 1340254185, 111081908, 1620256762, 1749504704, 1852459215, 2510520240, 2086199461, 3994374087, 3258598584, 2820729717, 1611066701, 4286907151, 95624364, 1655577300, 3038162660, 3792169258, 1389255698, 3165831955, 1013041891, 1743225847, 3756082384, 756057249, 3740236323, 1795451296, 949660704, 50247423, 4079440605, 2989395115, 1289662311, 4288930487, 3333588594, 2615848486, 1227497733, 1656848582, 1924450768, 769521968, 3824099572, 2690512143, 866732272, 791334430, 3170063201, 2262692873, 2019319346, 1988855699, 4294430135, 3180929851, 2601513082, 1603406395, 1885990005, 406936623, 1438215835, 3974653918, 3787167260, 2006412026, 2528692573, 2467218254, 3650037147, 3033752051, 3510656300, 1271810081, 2372454283, 866402934, 2630049394, 4166224831, 4222042215, 1853495757, 1769261901, 203136510, 3068716734, 3556331093, 3833823460, 4009822672, 1117591552, 2600758025, 115168937, 2239630873, 662560619, 1009759809, 1016185325, 369907564, 2714888372, 2548423860, 2933324161, 1227687572, 3678548600, 3042825716, 4237920281, 1386892686, 800137739, 596857528, 3934884250, 2863590771, 3293648172, 2223633865, 1469744532, 1385852890, 2677459493, 1806385946, 2846680173, 1411276972, 120856454, 2703947889, 1947260480, 2346135942, 1873485442, 4151173139, 720130513, 636391399, 1623982495, 3511571348, 52205464, 2998575109, 3988636401, 1858864814, 2075342271, 3424565081, 497032190, 1560863922, 4135822115, 2092981905, 3311540620, 698269898, 1152018580, 1909520409, 2872237614, 24480757, 2360114419, 3727056709, 2450315687, 1706072395, 1363125084, 3558698214, 842373150, 3007100963, 575589645, 3945857620, 568147864, 1712374375, 2278524802, 2531072210, 3394971793, 3997305283, 998833657, 2762896540, 2604155699, 2561679888, 1502429283, 2218509049, 1921148339, 1519092093, 3213228029, 1426760811, 904739278, 4177682877, 433244268, 2891249341, 4260379469, 2639356759, 1731392423, 2649822319, 2830903281, 1565442855, 3287897195, 718318198, 2284432862, 2006933712, 4097550874, 13736850, 2821878762, 56426552, 678446210, 3753678933, 2849007117, 322553273, 2421252828, 1292094921, 3540150159, 1096045236, 2005002267, 2734110428, 4181867407, 380970148, 2730665136, 3608809718, 1558885713, 2108112789, 1305784440, 4154730813, 971831325, 845397285, 3234766202, 1845019061, 3973141971, 2319898554, 104962486, 1711747429, 3665718545, 163140566, 1806449280, 1900592958, 998178499, 718808781, 3659633411, 2190327415, 3403836612, 1913275374, 2847860912, 771283178, 543991354, 2586448373, 137792067, 1555519986, 4192340660, 1091533283, 40094006, 4223660489, 1665194480, 2105973688, 2543304158, 1816216675, 1621624381, 2460983951, 3973282113, 1072985609, 1564938369, 3846983434, 2823315144, 1402159257, 2475804142, 368277433, 2818088611, 17259334, 3968611178, 2260375095, 372916005, 1244823290, 2674108040, 3840991642, 2166858920, 3274751710, 4055119042, 1743188075, 3224809785, 298824667, 3551364331, 225111868, 180196113, 984373701, 1080566822, 2282104552, 873734654, 1881710617, 1957406795, 2819529053, 3699498999, 618406261, 1411687477, 3294142138, 4109228357, 1111709181, 3569930975, 3649563402, 1370505339, 957537026, 1430887326, 3375729420, 1668002127, 335031937, 1302213471, 1514370498, 1390927782, 257051248, 2717891633, 734437066, 3616114417, 1440854276, 4172452465, 2701364793, 3398370598, 1583363955, 3382697344, 2680576291, 2364087309, 4291593259, 2189798514, 3893095284, 633222065, 3971445386, 2677954705, 3531415053, 2724261077, 4285221053, 2129687493, 2000487472, 1855835954, 2928282181, 120966311, 4042989755, 866331527, 1123468962, 3298045818, 1530473651, 1024041639, 1984893129, 2159094037, 2026770150, 4185797651, 3520534549, 843974370, 3393354829, 320908341, 1886807044, 2973647480, 2675842038, 1637217421, 598904119, 2024029635, 2658505892, 3774538401, 3858157606, 1813337451, 3136106883, 2837603055, 4184201045, 1940623301, 759878760, 1966671788, 435061790, 3385122062, 1905704773, 3714157614, 3688288, 1159893594, 3153676685, 150883081, 4079967367, 821718676, 3872020012, 3059753072, 1402694601, 4120735845, 2607623231, 4068440388, 3189599962, 2613614363, 2618032086, 3926196446, 1828331864, 861167636, 2070698459, 1204088555, 2405297256, 1745183089, 466608482, 4223052110, 2840116968, 984003195, 1777097647, 3586028764, 3251800257, 2497665107, 180188399, 3126896641, 122622265, 2953497981, 4213464561, 359409662, 3467947387, 2765137292, 3348609502, 2858265693, 3004789546, 1269756788, 494948201, 695533571, 2753599690, 3076351820, 49293197, 1051805370, 3181933172, 3454734763, 755937365, 2254590157, 2668130189, 124478903, 830440858, 2704494129, 467678347, 742307954, 3320076210, 1519646818, 908766880, 2271488850, 208381207, 465993605, 2245579121, 2633035144, 4006178687, 898741217, 2837373528, 2220638821, 3393350699, 768736986, 1547408793, 2330591601, 293657158, 3599057271, 1812009558, 608741132, 2340820056, 432828948, 3362138705, 1779513577, 764640091, 4199816090, 626042994, 637848155, 4008262411, 1871364792, 1182368468, 1997552252, 4138958968, 706743330, 2820852489, 1421174910, 680654415, 564585995, 2379717993, 609794982, 3377050361, 4109006795, 693815803, 3936809934, 4210673087, 2231890421, 472108163, 1077965906, 1522202179, 3359781314, 257775293, 4283133175, 2205671557, 1009994332, 3754176374, 1713220074, 404565102, 4052218526, 2542881209, 1590444400, 2250412460, 2752916267, 1925025990, 3034563370, 381150924, 72207796, 1529203850, 3440350135, 449786087, 3057224398, 2931026809, 4126185768, 1832779724, 227349743, 3257828641, 2622027559, 53496088, 1386578061, 29143174, 3318504792, 4263015279, 3862476972, 2053287632, 2383813692, 1392710041, 3380892795, 1203449048, 3219491462, 2527771468, 1928066139, 2782747093, 3776664325, 118161862, 972613496, 75206914, 2466998424, 1114784434, 1544184426, 204356985, 2904648548, 3177980220, 1196742597, 1654051743, 3517300309, 1274643016, 2640753294, 49691557, 3046622357, 366932489, 469041546, 49806420, 626931782, 1692259333, 2477527404, 327796810, 1483597922, 2101724339, 209085880, 415898213, 1647132242, 3755738074, 928274496, 1980242813, 1895479875, 307921801, 978937472, 907914793, 1477318094, 4294477183, 3428889472, 173168981, 1095503453, 2228668963, 2549539931, 1805920496, 1290978426, 1833393520, 3213182098, 4134091325, 1919861738, 3763217622, 2484858079, 12506978, 1169905736, 1821786542, 3080936118, 2779223089, 1621604259, 2577844383, 3243664640, 1209156142, 1769054118, 21985663, 340266898, 2704604015, 3519465106, 640285774, 1363951121, 2556443906, 742602348, 3518175490, 3944113811, 1501116841, 703021247, 816817219, 3024244920, 2267970897, 2505826303, 4070809695, 303283887, 1827570052, 252725529, 1243973712, 1267175904, 582246720, 2585781617, 2588311835, 1377916525, 1900612480, 1207441804, 1660238122, 2834816049, 2104192369, 2477665501, 3367278470, 2796413335, 1773026653, 147981809, 1982946959, 4231593516, 580296265, 1418923635, 2537093055, 513778444, 2367344803, 2177583029, 3362655803, 3451631757, 4109532326, 2539927008, 1250994482, 3891200603, 86105003, 3058541377, 4190093248, 3084970970, 2573686253, 3673810648, 1244190515, 3704012891, 2239671505, 216284468, 272559052, 242082122, 2364929555, 2092733433, 4175166062, 1412396441, 4114858830, 2811682670, 2896056289, 2988499227, 2057139246, 967496767, 1605158087, 1835725667, 481013101, 4009066892, 3973153481, 360650401, 9673641, 1172058675, 528556840, 847141449, 719939397, 2217183389, 3726446785, 3537383829, 676852573, 3187467251, 3958350690, 4039017732, 1346223337, 1094346663, 3497436668, 302069974, 1931231492, 3398249626, 4270841307, 3765287180, 3024646894, 2031908674, 3446020856, 4081067913, 1373057287, 1518315822, 1321439374, 2274678388, 2203534338, 2077694709, 3889954809, 2691565169, 3514870949, 823524823, 612494827, 3081677782, 1756533912, 586779579, 2007011479, 11949231, 1709414254, 617070129, 110741675, 1131207946, 2022387375, 720764579, 2772437999, 1890786295, 371370784, 2216802804, 1277094996, 3383296822, 1554099211, 263584016, 871207305, 711728830, 1670583866, 1505094099, 2977812939, 3719071492, 4019779868, 2361512439, 2724398820, 3358209161, 76635792, 2067770060, 1919005351, 3765149890, 2344651247, 918395809, 169000954, 4104553001, 4012423504, 1943167921, 1994534083, 255873856, 3950635658, 334633561, 1665872361, 3346436189, 2305043435, 672270453, 1104556131, 197449005, 3318764807, 3346696173, 213679635, 1562798352, 3887250019, 2797885903, 4065398645, 235286644, 4213189332, 2242827500, 2188052452, 995609888, 2430405513, 3810523151, 2895640923, 1914975173, 2785119419, 4131596840, 1701708501, 1661661704, 2366597389, 3369325724, 3245037819, 1383273697, 1656215277, 3750856436, 1367025729, 3564417360, 2412789958, 4225228883, 4236896437, 2240915942, 2808123402, 3838053646, 1569872718, 4278558531, 4276284730, 1829338066, 3443489953, 3921710904, 2917043594, 1130555892, 3624712831, 1571788245, 4007696588, 295001472, 3768023434, 1288510992, 1089344678, 2299571576, 1650317650, 4132048019, 761783149, 985242260, 3205994716, 4280891346, 4272726879, 2084216996, 2494832090, 3255068444, 2248563077, 1158015972, 3873260610, 3948057787, 4111883998, 2626290680, 3248889779, 2613319216, 1697116413, 1548773610, 595185087, 3322718086, 3857871350, 4152897235, 4047671533, 2219020175, 4192126272, 1664095302, 2280956458, 904136331, 510232447, 1427249491, 1384316914, 1343969612, 1405104663, 1412838080, 1476707740, 983465790, 1762062407, 3363737156, 703158981, 1526075277, 770375910, 3568014930, 1871625831, 505558396, 1017104640, 2494021223, 873554772, 2312538837, 968308840, 276194724, 958905359, 228346057, 622614964, 2894593284, 3631833740, 4239282380, 2847443233, 1501352802, 953618502, 1180605596, 1353723774, 693839282, 1122299711, 77184461, 1683234463, 2281879614, 4121777231, 3522513017, 2049478114, 2745113460, 3632696079, 329131160, 235023372, 4284514543, 1898778476, 1796742997, 3536086557, 2779325362, 3524449373, 4163660793, 2136943826, 2396463271, 3446767937, 3132326206, 2604357400, 981079321, 4262890828, 515133864, 3176759850, 1406774082, 691951040, 890959523, 358451693, 4210979366, 3571647669, 1991124066, 3815573534, 2698390520, 465718229, 1747912439, 1022819130, 1181589573, 2978236388, 2676969630, 929644975, 3869558367, 3136501481, 2215312177, 4240502976, 2372154096, 3817126393, 3887982659, 1230240476, 482004751, 1800315429, 1729911876, 3787661423, 3326543309, 1303724155, 1071421675, 2680803161, 4286403669, 3426551850, 950418497, 2546459214, 1712894075, 1780385242, 2797706354, 656883086, 658627077, 405731949, 3490825447, 3629282277, 2851187329, 3303974662, 3783966209, 1210867902, 2910057846, 924013199, 2064510236, 588108706, 2350934006, 2721042338, 2248021494, 1663126823, 345965610, 196405091, 1853524882, 487839382, 3592519115, 4182087353, 1936152219, 1567506485, 2440099834, 3773647079, 3111662822, 1469095034, 60088463, 571298405, 1342514879, 2387059260, 2609978893, 2695605052, 1500695679, 3737563751, 2671030982, 3087242738, 1646842298, 1395645920, 4219026547, 1468460189, 473402276, 2416556337, 4236023635, 2053449695, 2713842570, 114714595, 2242466738, 1491093214, 1414923813, 490509229, 2469148401, 2940805508, 3189209581, 1147864558, 1254489556, 4141609417, 2762564973, 2412084773, 3201308958, 3153180883, 3803488695, 2885402304, 2959502779, 850343331, 3223354997, 1567976160, 2929300284, 2953604238, 1397946866, 1922417506, 752371599, 625666244, 2495734608, 4023531640, 2020349711, 918493671, 3957957161, 3763438620, 2199610945, 3489887697, 3986857188, 2065535844, 2378756250, 4277390505, 2773369964, 1818343729, 2423482669, 3908636840, 3078629510, 1244167101, 4044098654, 1959172939, 1733689283, 1583866376, 3413740736, 664020126, 1224172498, 990411245, 1549178739, 3629152519, 2242650388, 2250444626, 634849745, 3527843259, 2108135310, 3442116693, 974285693, 663652224, 3115263249, 365396304, 944904105, 4019092791, 3919726411, 3018566975, 3159500255, 3686651445, 3175277558, 922171779, 2462000472, 1259172224, 1121292435, 903437378, 3672774344, 3832051306, 594779593, 1987297741, 3676480663, 6274837, 1587502305, 1498165668, 1995238509, 2854473725, 2112467068, 743398066, 3255144759, 1703355494, 1225160060, 890700306, 948609091, 3849870887, 576173943, 716212019, 3994517475, 758386819, 3758908380, 2542843562, 738235372, 53239691, 294660356, 4147877271, 921649500, 3545910888, 995778640, 3088349278, 2909584602, 69702828, 3002528754, 905054529, 594966730, 3991421200, 3346531150, 2708808877, 518682141, 1377883437, 2811283284, 1998649211, 432506178, 3582090857, 1518553251, 704966865, 1152794276, 1887013814, 1606546655, 2320565517, 1854706060, 3492917451, 1016685248, 2483681864, 3741032493, 141821228, 3608375345, 1853130503, 1371936898, 1504662965, 659041904, 3170653560, 3609090220, 3396501567, 1315443498, 146480212, 3196730981, 1893578665, 157156336, 2959755534, 177913752, 3735639523, 3943319643, 1868850449, 3900298242, 967046318, 723106397, 3866951859, 1936369464, 275735231, 2279235939, 2546839449, 3873546747, 4166821386, 2744063441, 3564652067, 1764640063, 183521780, 3369633040, 3841701836, 3465123851, 3367453304, 3256197924, 3102854106, 2846655002, 1849894409, 2339775549, 2213818357, 3714526900, 2044167006, 3352934076, 3296142050, 1452861726, 554544616, 2961402676, 1347269459, 3272438691, 3364677600, 3569402429, 1567032362, 3983089605, 2451070925, 2400442159, 3827034395, 2662868458, 2511023251, 3619351425, 3848346514, 114730582, 3724974821, 2960418392, 2121837371, 3171187943, 967074174, 3916094096, 753095554, 100041453, 1885072049, 2560238217, 1031033424, 3006225480, 1813703517, 2189855798, 1600252638, 2604094431, 645137521, 2310043678, 1161735533, 3829093982, 163252700, 1418800082, 2157595605, 2830571794, 51442976, 1287917767, 2778577998, 4266383296, 1450100630, 3956325244, 3528166696, 4098054148, 951318213, 4096964166, 2902917401, 3266826735, 152519616, 1330044083, 2306910623, 1929913059, 1427154621, 1725587483, 3719781347, 2554687446, 2159039897, 1672822753, 357590121, 772599334, 621477550, 2577487631, 1456833286, 1824017186, 65454326, 1430310725, 1007554257, 255221774, 2188204551, 1758408610, 1160946986, 2894288687, 3620984191, 951189524, 2755450021, 4099420945, 891823081, 4255264434, 4243288840, 787332307, 1890387056, 3513444862, 896706384, 3158454173, 2469720952, 3022826122, 2611183721, 1054857002, 917646884, 2768035117, 454153864, 3120766455, 633549521, 1204655955, 3547479820, 2162564840, 2842981918, 4026548120, 3266113360, 405856795, 3682064348, 3126006800, 674032447, 1764963884, 438742236, 2447142230, 3021367030, 2514998789, 1705836733, 1380221336, 2579667377, 2970936764, 1297148982, 2782179170, 1625370043, 764959316, 4158350195, 4184242253, 3750959699, 3650216491, 3225748766, 3647469461, 1194669376, 3552307158, 3438538382, 1054824592, 176660371, 3685211071, 3670270749, 2855384617, 9252392, 1920385273, 2712554076, 680835555, 1053296577, 914406856, 1795998638, 2307750018, 2948698901, 3145311923, 521933093, 1912726100, 3784412874, 2098064263, 2623067987, 3796163168, 979837958, 4023799720, 3375366620, 1920292696, 792476699, 1084089143, 1202809667, 3357598656, 482513650, 1511366084, 2992623407, 3103016547, 2014609861, 1583241419, 2134081920, 2838589214, 2621048092, 4044456315, 187066713, 1368683450, 2424216066, 1122555665, 2510355077, 90137727, 2622045406, 4108832384, 3121348668, 2043157364, 3982086563, 2090723643, 2394520773, 705037344, 2143802253, 4087276882, 2242288088, 2475241732, 3234452249, 594913607, 734641233, 525750012, 2852738132, 1968495033, 3638882186, 543234264, 93792643, 4228836549, 850324946, 17108280, 3979354506, 851946399, 462754350, 4271566266, 1537479465, 3197388712, 201266837, 3381103246, 1558750422, 1285409370, 1617844183, 1039519019, 903635871, 4189886186, 2162565381, 2747933445, 2069332021, 4025367631, 1191397034, 1002342220, 1544722534, 4252588612, 2972277693, 4196170304, 2530494220, 1043573515, 2930652362, 1947531410, 4236990206, 1998844327, 2544287898, 1641430284, 902320686, 1896257916, 2722677955, 1260327212, 423335173, 93517862, 2290694376, 4293469204, 1957975652, 1486420896, 3229984163, 4214679783, 1518585308, 2053864860, 742898184, 2978819458, 229275214, 1661842236, 2678757516, 1888406463, 4085428614, 1421680217, 879251405, 3747442139, 2986833536, 4028746843, 1912392024, 2830010811, 1073534909, 1734569594, 3352364486, 4037547573, 2338368578, 177678500, 3585980747, 3269301550, 1033091801, 2584017523, 2965800986, 4148820471, 2107295221, 2835315859, 670873512, 1389861129, 3240020275, 4254842616, 1967535174, 981045842, 795039997, 2144384538, 3646450746, 2926920389, 2945522910, 310716807, 3171657481, 3782484158, 2804975020, 320691793, 2538630600, 3345140860, 3907217116, 3588798560, 2302258812, 870080377, 4291369835, 1552626327, 3096042415, 124363476, 1773131013, 3692965805, 3365861899, 1440753454, 3191843337, 2962696432, 1643478745, 2260344049, 3607121949, 1759413053, 3986873957, 2571700697, 2430473406, 1600575845, 1250435260, 3449710690, 1896873262, 3993858569, 1829325303, 3778745723, 1869764328, 247424907, 2673542813, 1633451397, 1536583182, 959172859, 3023933956, 3443239452, 3786779412, 2644779263, 983493006, 60836914, 3222293290, 419611365, 3049044539, 1208192321, 3948428355, 624555495, 1860297378, 976795529, 334412730, 1994993637, 2819246877, 2576458062, 1087908116, 2833894502, 2677739964, 2811979157, 2517954057, 1637620437, 2458393310, 3673047611, 240571064, 3210916349, 3312493293, 3438038688, 2150989232, 3621771756, 122828809, 3545508854, 980904068, 3855688819, 1237373036, 4161703203, 1893639080, 88677119, 998508480, 1489790657, 1975373296, 2611701077, 2939601762, 2978318366, 3813682176, 2225053558, 3231623010, 225533216, 3944071269, 1564635199, 2343194673, 2530207686, 2340255500, 3816901672, 649184789, 1121329047, 1087851888, 2874542704, 708723948, 2609890935, 3656624002, 535082954, 3176067461, 3442417389, 178468661, 2818052584, 3742446892, 2456023331, 2548297173, 2580631947, 837014222, 1567401775, 1653498571, 1923413408, 1365889663, 2964931174, 3792373609, 2215673693, 1786761842, 604133457, 3365238281, 647615447, 527376929, 814324092, 4273832745, 919246612, 566719871, 307737007, 3712365072, 1524061048, 1524890363, 4092313480, 357812892, 3328168844, 2949414373, 2938445048, 67720828, 3995463577, 1870752735, 2120315869, 538643399, 4086093125, 402131964, 2238597389, 999762330, 427027749, 1616120047, 1591012383, 846594556, 202955790, 1134267268, 3950396506, 1647097265, 3504648495, 1769374949, 153033933, 374476209, 788738829, 1914430731, 3479045135, 2977421979, 3501171925, 3454162751, 3246400544, 3324897747, 2100461800, 15110345, 3452738848, 3211481462, 20701978, 1896280106, 2689927937, 810040042, 2380782960, 4175999832, 4218788747, 2554924667, 2963420482, 3759592461, 2324175672, 2360296168, 1838860028, 852248206, 1568702062, 4157135131, 1498675881, 796772123, 848763645, 4122624167, 3127869000, 1447507171, 2802093629, 948109017, 3347335001, 676536526, 2568518559, 2560679521, 4268927159, 4145377471, 165505618, 3949709446, 1688814684, 2268511074, 272089127, 3955035194, 2001405835, 3873913486, 1576821167, 261684918, 3193199693, 4119477844, 529856174, 2101755958, 1650260527, 3905241885, 205252992, 2693824643, 2976972096, 273295797, 4083434052, 3461316693, 3442230710, 3998690634, 2636674871, 1189998180, 2171509956, 2082057288, 2022768325, 645984611, 2756493565, 981778672, 981279567, 3222030309, 1747828105, 3442464419, 2424375076, 1053573265, 1692548062, 2593452704, 1227124588, 3910979094, 60218500, 3393130547, 1815065370, 900666599, 2399318039, 2625976054, 2257451800, 169819114, 599462951, 188953128, 2274909215, 1405804440, 2540040583, 2316287854, 2380563279, 1367384723, 1529971027, 1413792674, 1012779143, 2283238631, 3411576953, 1598508626, 2824669832, 1188144502, 2130880255, 3179661299, 1166155355, 376688695, 1655696639, 145405343, 1870834401, 3542234305, 3431720942, 1720828281, 3313882955, 1854717001, 3328868161, 3324154256, 1950430133, 3625647058, 1820699380, 1546930631, 703592478, 839845293, 4255537706, 791203080, 2463244189, 1250836566, 1315888676, 4190687145, 3746092139, 357974384, 2947059052, 1617792833, 2115336259, 3789781037, 4102275412, 232466785, 2117636784, 3561246037, 3891171536, 2400671709, 959295915, 3468994326, 882558056, 995818751, 842505291, 1375865878, 884734747, 1807343546, 4068710301, 4275708922, 3842367136, 3327635120, 3559343941, 3897202178, 1832779951, 3370322615, 2551120161, 1890611584, 2553195125, 4178608716, 3327118638, 2896858239, 2162417957, 404937854, 1209844330, 59011523, 4274953916, 3162740132, 1404307510, 3641227010, 718193242, 4157967246, 18673180, 3882631874, 2063563823, 3172671728, 3666806220, 2721843184, 3439764862, 2622506534, 2383614293, 3270660691, 1555093174, 339420557, 2475108746, 3234567896, 2459856402, 758779244, 1522145773, 3088733605, 3223606950, 486818855, 3109975010, 201156160, 4283528790, 3448372090, 3328453383, 714383428, 3870535362, 3267062666, 1229012874, 3307226664, 2282699730, 3411577545, 3495367161, 3245914759, 2854786930, 2844907553, 3908364222, 2332836238, 3906847828, 836578228, 4260685242, 3661400554, 1069625777, 507842506, 2448309617, 2468478631, 3309541641, 3198772167, 1480745272, 4189065351, 1214355932, 1885820768, 30124027, 1364507667, 935429203, 318413319, 540980510, 3335435896, 3811593068, 392335562, 3608453729, 3270550385, 1790622107, 3501192907, 3146957015, 1447622224, 692793060, 1221092644, 2193608712, 1319210665, 3671568896, 919095971, 1077813191, 1135659859, 272015253, 3673441172, 659115740, 1893380452, 2653100874, 952959873, 3923508328, 1760506770, 1551515664, 1009297206, 4142944355, 2234970293, 3858209119, 2366087613, 3951258095, 1624277057, 665267078, 1962633094, 863137927, 3121800236, 2889332728, 3802215978, 3753185849, 2552558880, 3265389719, 437744040, 1853492870, 3804222377, 2693295668, 2632787758, 1656907875, 2143290242, 3457216477, 1451753165, 243784919, 2023761773, 2065250609, 9646372, 1970513220, 1312792672, 440036037, 2488357056, 3639213145, 2611194916, 1889531994, 3225504644, 596909661, 2152896558, 2038094556, 1861652613, 1018694909, 2475981091, 700897709, 2146477855, 3769379630, 3368410765, 4244654878, 416409473, 107818777, 105990419, 4172126075, 268176292, 159823783, 1823412801, 1297955325, 212684646, 330158778, 120048839, 3792210872, 3641969613, 1943970600, 1613650042, 4275884189, 2472239129, 11331342, 3062157963, 3212286511, 1103205343, 1315340436, 4132020485, 3019591722, 4194601959, 1607564095, 4129504386, 3426709937, 2139181342, 1378434292, 3827077065, 2663113173, 709062578, 3097108122, 1798417285, 2382236480, 811616442, 1324683208, 3546708534, 3807247071, 640982464, 3324209008, 1964450563, 4000490920, 4071170833, 4131722497, 1394339839, 2981940813, 1778660969, 515254052, 4028019812, 2702072097, 3460082516, 3790423972, 1562590275, 3101465409, 1862295751, 1582260043, 1748740302, 3681621631, 2922975488, 2961770159, 542936060, 1739340671, 1180333375, 1239500855, 926887387, 2406821640, 3753531316, 3141391563, 2259961182, 1228591410, 174823, 1381806956, 566138055, 2988175853, 1847393008, 3120710698, 3685278846, 3752242903, 2351962528, 1313271459, 1723591949, 3890970742, 2432689984, 2597394588, 2324945656, 1234261438, 1449738156, 4019842501, 430346341, 2951682903, 879630840, 4062129429, 562553003, 253797203, 3388149782, 2984362495, 3117043224, 2228577933, 506205902, 3817676085, 998121764, 2125626383, 3220681080, 1686680581, 16509846, 615404463, 624554411, 448057940, 3316065388, 3240405537, 2081588339, 30362609, 1684007187, 279962186, 3671833315, 458117527, 3254809987, 2942938590, 1594590517, 333342174, 1536541098, 2220689083, 2586047801, 1762722501, 2214456921, 1051130482, 564287951, 307008931, 1103460176, 2490005633, 4144286582, 3555713937, 3215428036, 1761896138, 679137448, 561037918, 1699795881, 2691553148, 685340483, 4080586952, 3274331518, 2770205739, 1282421707, 4121918929, 4985385, 1951371148, 1159075654, 2322137818, 177753850, 1434268326, 1088010561, 2752068702, 1511836794, 4008131577, 3479864517, 1744822207, 2913695807, 3258009367, 3580025204, 2965393138, 3453364576, 2844745717, 835302736, 839039831, 2781405794, 1211313828, 3004688333, 2595413047, 759773972, 2350229462, 344879303, 3050901125, 1030996325, 995511420, 2711476436, 1128357122, 456082744, 92376230, 3683366700, 2722846874, 1932234121, 335160721, 1351904570, 600118072, 541435748, 783832107, 2993459208, 3595542215, 3942419725, 2446984719, 429878035, 1893115836, 2948894203, 2954433219, 2079855466, 591139768, 2880173575, 64417503, 965466126, 3674400416, 2264200664, 3182148247, 3607752001, 16834413, 861612277, 3032639933, 2056520569, 1804478026, 3979615910, 2691939460, 51539456, 3631589374, 1630958116, 4026361062, 2572889891, 1142860281, 800243742, 3188319389, 2874524465, 2131066391, 1165150424, 221764370, 2086104276, 1815209496, 1565680026, 1537335378, 4097730794, 1599259210, 3307537268, 2823908227, 1533642679, 1908801686, 2305728426, 3094775737, 2008136290, 869012357, 1256653833, 4217413536, 3118658181, 2200543057, 2688925841, 452036996, 513601384, 722999925, 4203179368, 181147728, 864354253, 1526756638, 4052239276, 2863675779, 2567633284, 260724472, 4022721940, 3993630330, 310802034, 4024815047, 728911693, 2638130142, 68235221, 1882052451, 1890512547, 1164790737, 925191506, 1264638819, 3721978815, 4173325802, 821918673, 858405562, 2210711857, 1653420086, 430564296, 3991905241, 1833601995, 4132502168, 237428510, 938869191, 2919152192, 525867136, 1566225721, 2093630670, 4040865821, 2168254206, 1960676495, 1730270792, 3890844868, 1724493311, 3586016013, 1773227630, 3582791676, 1289814758, 3857458430, 1525923386, 2021352525, 479700812, 2717626279, 1581718030, 3179634604, 1365160899, 4185135681, 1960448370, 1809662556, 3239464395, 2074836917, 815269633, 2727994335, 2315955854, 3386483003, 1702296473, 2165420918, 1571285903, 860561699, 4261289241, 870069641, 3640150341, 1774315360, 2006457589, 3494234126, 4211016707, 394063437, 478303695, 1663740923, 4189597769, 3513219426, 1690203624, 979703116, 1621868768, 2228302822, 3121018607, 2070777040, 474313707, 964390434, 518234662, 1967154235, 432133417, 2239874742, 506227550, 2595369041, 3132054150, 4015392530, 2124789290, 2242019286, 1230943980, 1822197331, 582857410, 467088114, 2763203421, 2466430735, 849450791, 2794904765, 716330682, 3722471424, 3064621482, 178439072, 1076106489, 1255493902, 3917320170, 2775325420, 2855363987, 685669290, 196823150, 3685244946, 2935338840, 829265596, 2927560277, 2456521601, 3035476472, 1916575651, 2474285543, 3366680049, 2128574278, 2393009544, 3953608423, 493981643, 1214878889, 257202509, 3778130474, 4199504317, 242866090, 2252619127, 4138049927, 4030385239, 4162976044, 1280543060, 1260617044, 1008504039, 3709925501, 1694820371, 2442533097, 11918615, 4293956227, 4190080169, 2746391848, 3308229435, 1442137248, 807093091, 985281284, 1518148371, 1804888998, 1246676442, 675655620, 1740021031, 764650815, 3651726177, 347249717, 3751262952, 694784102, 2857637502, 558672315, 2601157793, 3396384241, 2162573632, 897395163, 2263000949, 2774919987, 1778699084, 2752679717, 828403875, 2559885412, 2081134411, 4169751413, 3352276240, 3881457299, 3687951378, 19898867, 2166699, 3833879814, 3218939133, 2902625013, 3484366082, 2181432503, 43952774, 450338235, 1776381616, 490735568, 2577833147, 315569781, 2122554801, 270722497, 53265133, 1296347928, 2751504799, 3342962376, 2013100420, 3846129199, 826974244, 1897924759, 2250374413, 55771204, 3633077451, 2527289848, 1588560428, 1117045629, 1414486401, 3994082012, 557086011, 2556433397, 2153722700, 3903795019, 3727444931, 2322452789, 3928613352, 2920522258, 1686657128, 3297173360, 1258675512, 411033462, 705858004, 1427950666, 845484968, 551668666, 1760754031, 2141652084, 1172781772, 2565447550, 3711650081, 2754985880, 1911726263, 1879536444, 3692877686, 516006272, 908623218, 520544633, 452250976, 717464903, 1625562552, 3621918142, 3649704573, 1482029117, 914595761, 2087104122, 1831373821, 364342028, 116407561, 1188561625, 2880886054, 2465025657, 2187446613, 3422355176, 2807403544, 1444564554, 1414792151, 2745005767, 420342188, 1946476801, 3197369828, 1364413738, 3306383751, 4052597961, 2486977882, 3777196203, 3951157624, 2089986205, 2056290617, 3964313814, 3104503970, 3200894508, 3834525025, 3144980278, 4256976943, 4134498427, 2006863293, 608488083, 3110296263, 155498049, 904412641, 3635239019, 3375074997, 1222338404, 3947120331, 1256932920, 4132657810, 564150985, 1617956858, 1201339472, 1220575749, 490094286, 3105423246, 3343213749, 974372115, 1048357964, 2439210106, 4108037217, 1059634268, 3952116021, 1863452552, 3723374272, 108963594, 860454568, 3381052191, 1530812987, 2329419108, 1770864833, 765389924, 2653057283, 1742993789, 854700043, 846739047, 4164764289, 4199874403, 2886865990, 2991120887, 537278932, 2170375127, 1911819960, 277995468, 258757441, 1431722326, 945902204, 814769724, 3771460369, 224240442, 545100864, 1386087527, 1973344301, 1924069532, 2143144953, 434634552, 3180678556, 3930724305, 1974861416, 454671486, 3780535492, 2502400332, 538721058, 2822401256, 1725208044, 3343724393, 992347781, 3594080009, 16970441, 2776099541, 549268067, 1954667551, 839914759, 4178655010, 3704611183, 1510561865, 1317672183, 2885477342, 380275029, 3650553990, 1406141939, 2649954712, 1517007530, 451658040, 3936738689, 344669439, 4144471857, 468857489, 978719918, 4178163232, 3044214541, 3674634820, 3245678177, 1186123363, 2992277175, 1364528749, 872813725, 541724829, 1573233103, 3336991950, 4231101501, 3290720120, 1629177276, 1957572573, 3095857698, 2438764770, 3231975458, 2297545915, 2589745455, 3871200411, 4123498825, 3675131738, 1696809776, 3575790569, 1470722314, 2424229630, 3049512525, 2460513989, 1742213257, 2723209838, 3377470518, 3782709641, 3881572953, 1582733309, 194208212, 2405059621, 3256534788, 1909225492, 316114277, 1213788028, 4013104257, 4055930611, 2527142190, 1149210155, 2914605223, 852269880, 4219884239, 2870707361, 754235859, 4033614569, 3041579008, 1938861434, 2230963354, 2780977324, 3560811745, 1866753742, 602587560, 4003549379, 1577201486, 1717950809, 3391079573, 484370756, 3385285575, 2180978421, 4236884316, 3948675744, 2700899696, 1309604450, 2975740377, 1034625179, 2267472467, 3514149425, 3755469467, 3768989883, 655846446, 4063418197, 3416400770, 557815481, 982462063, 2392592841, 530612911, 2579137983, 2675531859, 2439972768, 4182325284, 4015840729, 3333485239, 852131971, 3316932240, 333573712, 3293871003, 2751603416, 1581865260, 3592040341, 2876257072, 610913145, 2535408995, 48474847, 3637833931, 807992384, 990368672, 4005491236, 1382597411, 933293375, 1357586413, 767593205, 4282780699, 2877597092, 3335971387, 3379740745, 4089439338, 1783444819, 1108770337, 1695533733, 519050238, 3387487769, 2003140754, 619802326, 1272812925, 650858527, 1921372615, 2313839722, 2157136205, 1842249277, 1040478662, 1589932723, 1220380321, 744387749, 2674026385, 1067888088, 863026613, 3848803190, 2268126617, 3048074584, 759781005, 4229955121, 1477420498, 1379276472, 2046283327, 2813120214, 3751122200, 4012488390, 1102552718, 3163046400, 2380927460, 1136445998, 440019240, 4097448192, 3309797148, 2093272107, 3551767615, 3494186556, 1502196889, 2716931778, 3114769267, 788478695, 3905035157, 1507634924, 3759022520, 3090113541, 3369949254, 1052357559, 1869089406, 487766368, 2365186477, 3556842411, 3757558618, 25548106, 2533975663, 3068990040, 2385674242, 1421310030, 2717468996, 3249780987, 1546490869, 4233142166, 258358972, 901763923, 4238527662, 4158111361, 299123097, 3066436922, 3607014103, 1392414106, 269539737, 487084561, 21148978, 322955907, 682073411, 1527919326, 501257590, 3450267704, 2292307642, 2183698169, 3057446174, 4191080591, 3246432, 1471477988, 1799426585, 579132465, 3466145207, 2440568434, 3202538202, 822683443, 1151203840, 1314673302, 2520542479, 2694394725, 771901393, 1405434724, 614752012, 628351575, 668803379, 3420735386, 786247436, 1369032643, 2080324514, 3129557875, 476843199, 4062668113, 3899659481, 729803722, 1481521093, 1532107033, 3303872165, 2325098620, 3219830419, 2656419533, 3358525939, 3458682380, 3714725363, 3434469137, 1428337086, 940155878, 2917585577, 2271658920, 3237667404, 2854497872, 4056209146, 2474718026, 3749310908, 3110447533, 1372196071, 3435236848, 250475452, 1994061343, 2026076419, 2957092136, 2560647358, 2509203823, 1876910657, 146921968, 975853368, 3740087298, 3002839117, 1075232988, 733811391, 803046553, 2454902040, 1812093967, 1090420636, 655996017, 3329279291, 2322947212, 748567901, 2942104676, 3465351178, 2103447107, 3886697892, 1027801882, 1306420829, 825207095, 244977902, 2773696851, 3093407554, 1227404034, 3100670380, 189857925, 1453403818, 995308018, 1749746117, 10751303, 1552161918, 3905605880, 3725229977, 2372356793, 1047257269, 879378463, 3736161620, 3396121574, 2566215211, 3603276532, 2741805686, 211564186, 3809573094, 606448183, 252912591, 656006076, 3951493868, 597894372, 1416628820, 3762682345, 4259857151, 1570072777, 3960575560, 3755031012, 1109938818, 4156979565, 341066366, 2346460362, 3129212455, 3854091588, 2299300661, 1218384942, 10, 10, 10, 10, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_6_fail_1() { let mut scratch = vec![0; limbs_square_to_out_toom_6_scratch_len(2)]; let mut out = vec![10; 34]; limbs_square_to_out_toom_6(&mut out, &[5; 17], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_6_fail_2() { let mut scratch = vec![0; limbs_square_to_out_toom_6_scratch_len(2)]; let mut out = vec![10; 35]; limbs_square_to_out_toom_6(&mut out, &[5; 18], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_square_to_out_toom_8() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { limbs_square_basecase_helper_1(out_before, xs, out_after); let mut out = out_before.to_vec(); let mut scratch = vec![0; limbs_square_to_out_toom_8_scratch_len(xs.len())]; limbs_square_to_out_toom_8(&mut out, xs, &mut scratch); assert_eq!(out, out_after); }; test( &[0; 40], &[10; 82], &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, ], ); test( &[1; 40], &[10; 82], &[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10, 10, ], ); test( &[ 2208784279, 2917482314, 1540602536, 2403282522, 3177507876, 3568390418, 2503198964, 4098975582, 959428927, 1848421791, 3138244039, 1769511894, 2937718665, 2012490954, 3221845295, 1007046661, 2166807976, 1636825832, 1944008481, 3095709286, 3511221073, 1407038208, 2770922765, 161532758, 1448298614, 1265783012, 338379034, 1683441961, 113409617, 1323550674, 1979665089, 2291057706, 4113814820, 2714933463, 1535427301, 2929891523, 63992461, 3135004776, 3786738844, 2632680024, 2667412795, 1360966727, 3362839603, 3006655596, 3260539071, 1444145379, 3409747220, 2237275473, 3174097601, 716285927, 1978614968, 468942927, 1738052841, 2807377443, 2101735604, 1391753243, 3633841872, 3742362774, 3397153211, 2486594767, 1832858939, 32128770, 1219349803, 776132652, 4063064247, 3946545880, 3435957924, 1773045681, 2512572133, 2748139949, 413389504, 4140727133, 192234101, 1304882265, 124891939, 1568548351, 550540615, 184249541, 3323513356, 3451542605, 498713131, 4173565981, 2912286925, 1944682204, 842665901, 175934507, 339425560, 531887691, 3989856760, 573597854, 2081030961, 3859173697, 4194200498, 3521120776, 3645192939, 841194406, 1521764848, 409716666, 962456872, 4266112778, 572132898, 1259140690, 1690488098, 2391102659, 2060622378, 2300472459, 351585093, 1183324953, 1908841714, 3322377068, 722941835, 2830281597, 1004902780, 2872664652, 322537088, 1791512843, 4017515142, 2146163968, 1656233949, 1884364542, 306445970, 3652330492, 396065313, 3852716985, 1587730681, 3101285019, 3740403893, 2161419587, 510565625, 753946267, 1714965880, 3587046876, 1295766051, 2498965643, 1325702012, 1431647324, 901386556, 2047960754, 3487840600, 1254569117, 40339744, 2616107038, 547609462, 1456048961, 1597978299, 2534590699, 2623463548, 2924931016, 3824539980, 1241754779, 2807078816, 1959517846, 1793420648, 3099529579, 1245372244, 1269555469, 2704143705, 1845831862, 2005962203, 403832192, 1836487508, 3372628044, 4117005657, 941993979, 692771149, 1567368465, 3808788560, 3371838868, 1431310159, 1292752938, 4116886194, 1323248504, 117286428, 882674942, 2556580751, 2488476497, 3028819401, 1972752317, 3945085030, 3949512183, 1581135818, 2848525168, 2428342027, 3306651167, 3371724128, 3339766283, 3813913124, 119594870, 2508612847, 2953803757, 167008047, 1804301887, 1108240771, 4239379241, 16441896, 2455828635, 3537715003, 3996443808, 2554165441, 3217810817, 3794783475, 49513858, 3689899898, 3064356999, 3496440951, 190703695, 1892022525, 3357636682, 1349153321, 3506495030, 2016023232, 458032748, 2207102076, 2588320789, 2422944465, 2140461881, 3116891845, 2782530105, 1176015888, 4038240333, 3208025332, 2887025133, 2458309917, 864777664, 2993890986, 3510353851, 3084590293, 124043231, 282471342, 3117519350, 208219794, 1735342516, 1499437868, 3601067217, 4212801592, 2812545736, 2233658738, 3199963441, 2055482553, 1064371620, 3066979407, 4195062909, 3565514444, 869170992, 1788898939, 4005423148, 61033493, 2037097301, 1944306569, 638551846, 2868693808, 1912050866, 2567645011, 3935679297, 1762098685, 2905977740, 3704796792, 1754878863, 3413206511, 3256490941, 1428825306, 3696982563, 2917432388, 85329539, 149522635, 570541346, 1207356892, 3801489178, 1372575796, 3220881463, 3867113380, 3715629250, 582652775, 3745445916, 4145201987, 1838987939, 3758141979, 3461320697, 411322170, 3595735722, 920178743, 3857634522, 3825785923, 218304872, 285359422, 3948666125, 2352664389, 1747154882, 1730683963, 3707647324, 3956885105, 848333536, 1522849970, 1998369555, 3520190518, 2402642000, 3026980409, 1640122597, 792809401, 511457917, 3616835355, 475825290, 737294517, 4060291056, 3683165567, 548159186, 1992119560, 1865982009, 1723693971, 1753302493, 3381199726, 1974683508, 1890412775, 1641026925, 1334190938, 2660075150, 77762983, 3669872228, 1224792082, 3222400510, 3263897252, 3494238165, 873566153, 4204420378, 3856812948, 105989063, 562255177, 4266130916, 1113999468, 339584161, 1858645360, 1603041743, 2479571274, 2305399676, 2373569675, 2591079565, 4097288709, 3266991636, 3194187297, 997157963, 3550975070, 3843381019, 2225528660, 3601736403, 223505403, 3392490624, 4206434869, 3344317943, 353353783, 4167600645, 2808728425, 3234719428, 1677973313, 2814182812, 1212851463, 2308027233, 3187325028, 3226622472, 730161085, 1322467845, 2053488127, 943020033, 4154579643, 4187988361, 694857341, 1721301049, 2692769166, 2070754373, 2778749125, 3756217004, 372909366, 1434770482, 757686870, 777360411, 2237386076, 1009169518, 1144146673, 577213669, 644990051, 539809035, 4187893177, 2777851194, 4120194532, 2647199726, 3979704400, 2340413190, 3440177693, 3624877063, 4247742958, 264928947, 3675639294, 857162390, 3421070176, 3234981589, 3628992659, 3886434764, 231401556, 968207812, 1344218760, 1608404085, 2306925846, 2301608525, 2502473613, 1292114060, 3317085030, 1866696884, 4054098927, 2454813953, 387618240, 520675113, 4272476759, 1536834588, 1302364418, 866979997, 3549341801, 3225944791, 1542282645, 2653393832, 3621105792, 4272895662, 1077344679, 2022177778, 3153056929, 3703744756, 3833275803, 38920897, 2222405636, 1926157497, 556170935, 2986201658, 677131536, 375578189, 687932681, 2043149400, 3620892751, 2914749198, 2974027923, 2932504125, 727099747, 3649852946, 2362460848, 3718425209, 2628058340, 1256430718, 2281676000, 3475598187, 1375067783, 659739290, 2924886241, 1519085881, 2121799090, 823489777, 2761452031, 689532542, 1086988319, 52902115, 2429537045, 138699782, 1558366393, 3854355145, 424874583, 303611432, 1726717753, 2895113369, 1920908658, 3631405698, 215678476, 4175872484, 4243180164, 3812966673, 4182374507, 3434218291, 3346269740, 3708909697, 768625224, 2671341874, 1481115014, 524158027, 490851555, 2565683058, 2196003149, 2059318553, 2455186518, 2688273996, 3380657927, 337050138, 2208679271, 324120092, 3103851531, 3675684635, 1942739093, 192902782, 2181840282, 3037209091, 107748570, 1799867763, 1544470445, 899481557, 3574203340, 992496129, 1691306757, 594120588, 55130785, 3948236640, 2366017337, 2332356682, 4261339803, 3495561922, 1066889961, 2483355538, 2549105674, 382477549, 1684218866, 3179143300, 2115767175, 1477682777, 2404584277, 1508933427, 1079336347, 1260205517, 451523794, 302136644, 2205319263, 2332211187, 435482503, 2181643799, 861659376, 4173063642, 4177757588, 1991206489, 2126982104, 1746764084, 2110629749, 28755331, 274389360, 2325228784, 903173711, 2667794870, 3234841692, 372044653, 1101818495, 1830539842, 157622659, 2813335571, 2418219371, 1781705394, 3545284119, 116430215, 3917281080, 1163312583, 4077000899, 3560352603, 1529980053, 147658472, 2806321933, 2409294381, 1401901685, 25756065, 3235130080, 52971194, 3555689967, 720701685, 2753411419, 1915995649, 4084376336, 1886404857, 3282391420, 3689618917, 1647397786, 4253979137, 10312899, 2753539655, 1687053631, 3692805500, 3993614409, 3160043908, 2206895430, 3473461088, 1268398000, 4187760109, 2510114302, 99249479, 153265006, 1560476225, 4253804017, 4135139486, 1777500622, 1210814030, 2790690151, 2927531451, 3700995836, 1182346854, 3482669161, 953954861, 3201731324, 2502044358, 4170301767, 2241382906, 2270553989, 823184791, 86181548, 2227199159, 1425393472, 2002161207, 1335155557, 3722077212, 3185842059, 3361021373, 3718385416, 2960194495, 1410306613, 1336602151, 3868250088, 3852775200, 3671651883, 3595610890, 3879654447, 3740609494, 3251169960, 733009204, 2683981814, 3053043462, 2744847944, 3800177150, 2138411333, 4217614018, 2608312502, 2415560573, 3843669535, 1145687109, 673955819, 3783054822, 3577373451, 3896153086, 544023980, 1361119525, 1515635606, 2569181589, 1082902602, 1175605356, 11666898, 1249712808, 620029252, 4244992311, 3309183056, 3733927807, 3286813711, 2391137179, 1370037877, 1885533562, 1799712249, 3650961319, 3329689005, 1667704282, 1165070994, 666343217, 3096079301, 3335446925, 838739188, 2016879384, 2932687893, 2211867129, 782981385, 382783736, 2916698207, 2330900310, 34774866, 198258018, 440993902, 2707559911, 2705439512, 3585937910, 2050052686, 976019697, 4019030687, 2308424646, 2011004295, 365211687, 2445434254, 562670390, 148804797, 553128146, 837133067, 3912537192, 2317629340, 3035245763, 2380229490, 2626950229, 191274969, 2610487441, 3582910240, 3311155592, 2958867418, 1170213450, 1121481867, 2164744667, 855295685, 293584176, 3535547991, 896027254, 3151737672, 446316243, 3398926143, 1487526475, 3859821507, 3888044230, 2912541642, 4200996888, 1844240177, 1985758237, 2467185057, 306505837, 1618640295, 2300538248, 1237599289, 3252353589, 2663563949, 6609793, 1855830249, 3102008143, 843816122, 4244891683, 2597137034, 496037769, 598572108, 4101489775, 149332750, 2768661725, 3269228717, 2874201280, 635382695, 3809849274, 985790869, 3514952614, 2346966757, 1082306099, 2303159063, 3101682478, 622060689, 87737751, 3770334723, 1916337620, 198019398, 4156112198, 1971126184, 2844823044, 2231209991, 608565398, 2683168775, 3762824483, 282223687, 474446399, 1282650254, 783878888, 912161761, 2647590029, 476100694, 1833615559, 877400814, 1143318809, 1044305214, 3464407272, 1758024618, 3439710711, 2746979168, 4050593671, 3645248342, 3120906100, 3197909098, 108360054, 750307312, 4052730711, 1094680734, 3815071626, 505637591, 2194599792, 3669546981, 3965877294, 757706288, 1687251959, 2243209320, 610178335, 2222146034, 3066108199, 358065378, 3649999798, 1104042781, 1155599547, 487100701, 155435292, 3253330215, 309344256, 1394080536, 68067987, 3485978844, 1164779252, 64012659, 1957399785, 1768137866, 4111772919, 2903748276, 1997724393, 3590965606, 3351321711, 367478601, 2901671882, 2811175561, 1831368469, 37226423, 2549394739, 3908509004, 3441252901, 3368356812, 3158173106, 1982634083, 168113402, 205412531, 1757445074, 3846077342, 1054916653, 871505255, 950574314, 2339482640, 1810618196, 2576199998, 2228705853, 2039707896, 2730693829, 709433529, 3258773332, 1479501012, 4251201523, 3250056802, 3841243465, 467330021, 1648791516, 3860034449, 3315902346, 192703287, 1375227648, 157365651, 2887824516, 1199147028, 2666807397, 1864630330, 611827605, 2210095636, 3455555159, 2896731514, 2201913044, 2270549816, 1559846320, 2363678436, 3881266828, 2491558724, 2205067377, 2537764365, 1273766953, 3512578935, 2755079279, 1601988718, 635246697, 3339833926, 851014482, 2631169753, 3874048946, 2185188712, 1632479780, 1412475166, 2134443192, 3166187705, 916204599, 1740128938, 2928637868, 3729374296, 1941247992, 282215320, 1881961933, 3545012769, 44013821, 3462052825, 4012152566, 2782318148, 3325475182, 1164565687, 1426995196, 2817841661, 3382660012, 3600519598, 103228229, 3055674000, 894525568, 3918313708, 232222959, 2973624297, 2064371759, 1462237723, 4220017388, 129175762, 173476391, 3218281720, 2114599921, 2743802447, 2401678148, 2375230604, 728853890, 3499018139, 2251927835, 597813589, 3027094542, 18644508, 962718316, 653518484, 2600931635, 1751582989, 581773069, 2075127089, 3061492115, 291713112, 711113212, 3886411257, 145935140, 2620711838, 1463857026, 4009447712, 1436719717, 4113548617, 1916316479, 1459884216, 1407211063, 2411956172, 1620836811, 741617186, 3780170422, 718465650, 904165649, 1795800930, 2879673786, 3040754253, 817754274, 2477881291, 1388942998, 3164684738, 4280399147, 1010043651, 3720993142, 912273008, 1578944784, 390968590, 715739714, 3630234462, 3499579393, 120828829, 180928797, 3971313268, 109998102, 3921894457, 3239454247, 1080946542, 1835673541, 4212575143, 3948965153, 3799046381, 652057606, 1314740386, 4052313496, 3467451145, 646076896, 245129392, 3016775061, 2328785169, 960487245, 1796031809, 460949678, 3236903207, 1178674059, 1210665850, 1193844599, 4271374872, 567904721, 2025467077, 2472512897, 1859313255, 2645120321, 512119874, 4089157359, 2501339142, 914099863, 1411293436, 3981480830, 3778665606, 2885773596, 3571264765, 1527182779, 2937865021, 923962279, 1945373513, 2400145110, 3093632880, 803965487, 4259799788, 868852494, 523239642, 212026662, 1348277205, 2033954931, 2671853683, 2992155294, 2404118752, 3262441671, 2358245043, 1998726385, 1856962421, 2820111324, 3944154915, 967097160, 2805097360, 4033390412, 3111763238, 2237914714, 1908890884, 3455767886, 3896277122, 3582480465, 3866847358, 1574406586, 2972733765, 1896156916, 1258929454, 3805663232, 1533224016, 2929414752, 3149590529, 88187458, 2460596126, 1558314108, 433783522, 1630044588, 2339107597, 2798668894, 1428360625, 3557302061, 1637886616, 3231181211, 794089928, 2405733483, 3988234469, 2807396944, 2337372191, 4249190897, 3879737130, 1321256620, 1006408359, 3429892900, 3077599139, 3084526511, 2997756926, 2900724574, 427269455, 1580590500, 2424041645, 131659419, 2201432336, 3778030441, 1428304948, 829214496, 884953543, 1844095209, 733095970, 653918424, 3819676715, 3057668763, 3565066760, 1555388443, 2165553291, 2914622082, 2963084576, 3354717690, 4026182713, 143181484, 3729896588, 2688455400, 517110709, 1897690925, 3496744705, 2378325974, 3973997476, 4095655687, 3507137541, 1661752595, 622243029, 1830684675, 918924646, 1481970012, 2507864370, 2365391063, 3097880134, 3555498195, 1755254860, 3930383669, 847229114, 612986996, 2368763877, 1838609612, 1503917373, 3677547659, 1939998627, 2715845452, 465660991, 2898504512, 618023938, 2015425202, 97947889, 2507353594, 720170483, 1358962790, 3913982533, 2458716793, 114906654, 3999024990, 1602785653, 1921315674, 625011248, 2278721817, 2040412697, 2787497529, 4138485117, 3000743648, 3434785413, 2336734220, 364662893, 2940803710, 559551722, 1910189207, 903950621, 2019508009, 776406310, 3654821919, 2706405638, 357404964, 2464445130, 1578186555, 3263961674, 3822735326, 2528772706, 1777579469, 1337968661, 2586309509, 2434099989, 349193692, 4110889470, 4118137503, 849184446, 3681650163, 2550944864, 2813598863, 3691010755, 250045178, 3659363571, 1272113098, 3603625184, 1827553711, 882516419, 1684663435, 2497226884, 3732829395, 4199638565, 2824533881, 2950639217, 2727198684, 1403430676, 2240042622, 3910098491, 229558683, 712576203, 1103892989, 4229384718, 3877080792, 3381436031, 942554112, 1476033974, 2877490315, 697119873, 266866670, 3678113072, 1540428017, 1229779521, 2351358390, 665147347, 2304732707, 3094803794, 2375833352, 982432305, 2581691697, 2941803891, 3588755278, 3179495857, 117197450, 4088689685, 1417974990, 2897428031, 4092907174, 3531117732, 1734239461, 1433102123, 2281332037, 849160020, 3612140551, 3438533198, 1645435281, 181786796, 2890331065, 419030224, 899006549, 709350914, 3555564755, 1330179330, 4103281272, 124103149, 1724766869, 1457674901, 190539956, 1180447852, 587006978, 236562474, 4070809481, 2480018795, 1819379258, 2409296313, 3679773767, 105244242, 1570549025, 3922353198, 1849426002, 4264045073, 1672859272, 3551516232, 331873626, 633164225, 2515240316, 2312561291, 664889581, 1829614400, 2369683650, 1107401767, 572524146, 1597721066, 519433799, 264645, 2872957856, 2759402796, 3003957439, 748149095, 3188554379, 2386125323, 1849446903, 406588509, 2673520905, 3275474803, 1463555154, 1904755678, 418458444, 3824928632, 1032505713, 1646057065, 740076291, 2048854068, 2472310810, 1458805748, 3496276460, 1002901812, 4232041355, 2497927343, 1941784309, 2367135662, 3696245408, 1121954729, 370307920, 3418751543, 2703762668, 398632139, 2202769671, 1594862631, 50175652, 3250183014, 2771612032, 4107550857, 2003785814, 2681126737, 3046686349, 2064054562, 976129296, 2916897424, 612385634, 2124001896, 176317758, 120254479, 947864126, 470050807, 3705126703, 1484042456, 636896650, 3444011938, 1786425117, 1955911564, 904249773, 167672871, 2783985377, 1450994601, 767109187, 2846797806, 3598682817, 965446295, 2787946278, 3017761851, 3782717627, 2020641727, 3387052838, 3151721739, 416200856, 2604211199, 2221750166, 4276448083, 1865093279, 3323583242, 2499829337, 1472571460, 3019798861, 1619367608, 2665785104, 2526109781, 2415813803, 1971417217, 2168315771, 2251130193, 3074039354, 2253181775, 146608751, 460880302, 4202211516, 3639989754, 2207072265, 3627306367, 2838643311, 3143146237, 382139454, 3215955489, 3780378205, 2972372844, 2576925576, 1874035811, 788385224, 1047032968, 3643363543, 420139440, 4137494742, 1396832765, 1912613937, 80944320, 2606768003, 2865851030, 786402135, 1323826113, 2881470994, 754561541, 2038385795, 2239121958, 3710053237, 3157551721, 3771662576, 1982966842, 3574225739, 3982348487, 3458718663, 2826455911, 2269384134, 142164337, 1549195392, 1082915277, 1856488336, 328847100, 1212372695, 1482883066, 3110169830, 158612414, 4200770807, 1880462602, 3077303142, 1447950946, 2211310010, 1015183588, 1479771761, 482219684, 2398380946, 3929425906, 4220173591, 43108679, 678684660, 2834720733, 3145356539, 451572857, 680598723, 3865391278, 994603415, 3470620999, 673962053, 3910258173, 3199464352, 393227350, 3397874558, 3340387149, 3949796634, 382428197, 1206353417, 401457558, 2544516446, 574119387, 1285672394, 3583098318, 214208070, 1523936274, 772887512, 4171689778, 1824856913, 2413564333, 1549748904, 4152892839, 2906454732, 1090762117, 2431277774, 167622288, 3064847800, 1458633976, 1225335082, 3150128424, 2166852981, 2185899970, 660470883, 609092458, 3021517883, 1678961441, 4181857413, 421510420, 1317189193, 101896141, 2236582587, 1318297493, 2780205185, 2860537933, 3260782217, 3759404083, 1088711857, 1830654534, 2702735840, 1159987790, 1645108481, 4077459678, 2136247442, 3429367236, 2390409199, 2466015914, 886132397, 2524894129, 2614918256, 601796631, 1277092878, 874731029, 1944818692, 636784514, 2237389672, 4100434311, 1187262766, 4124867136, 3285614912, 1596621151, 191417416, 2841705449, 2146369048, 156085081, 2379446487, 3919962238, 47394345, 1263681455, 2247166294, 3007467768, 925438688, 2771269088, 2359016534, 5347116, 3397097254, 2464722227, 4071047259, 2978393992, 4145704224, 23083008, 2780252389, 155462704, 1813720213, 3689032388, 249602355, 2942206368, 3246481010, 3454561620, 2696971913, 3664427208, 1943952478, 1958985807, 984037433, 3438916415, 2082297431, 3857476934, 2627020547, 3393914677, 1368477057, 2474331804, 1320710005, 3432316500, 3155046413, 3435661395, 1632152192, 2450448357, 2279326868, 41133290, 363644754, 1292305864, 3887169714, 463260533, 2102068583, 3848001924, 3445460435, 639069451, 1910366283, 3511720510, 4011470290, 145508597, 309070081, 3904980580, 1022981671, 1802347616, 1107531687, 3817701828, 2186553382, 3012228893, 2787755917, 4204074545, 700721769, 3543889424, 60016059, 343814681, 4064758543, 1876314447, 1766656069, 852712848, 3401352430, 949357577, 2933534528, 984195568, 336010225, 212635917, 2418858375, 2417075801, 744914132, 4019136601, 3763314831, 3267744206, 3847787244, 3492644271, 77063559, 1866482909, 1725523753, 1855513878, 1470420975, 1568979853, 452303744, 648129746, 3902833876, 3465479188, 2549697000, 3915943704, 1102256431, 1139532367, 247124117, 3441162879, 2715413814, 3499085014, 3245161538, 3046164381, 1537664764, 781373547, 1159401544, 1138886841, 3162893383, 43768212, 1711332912, 3478794404, 2932562276, 1079826421, 3097209204, 1971142968, 50490582, 2344975517, 3888627052, 751440299, 1898349657, 3464659774, 1965725622, 1079219945, 3424011904, 2557910409, 3450709268, 1062763619, 3688932453, 546866669, 79147227, 2766016743, 2252593348, 2201723140, 783925597, 1229604025, 2184234813, 2900491613, 1002742679, 4193477090, 430653153, 1632649591, 4161092195, 3036650674, 1023958621, 2483714092, 4294524978, 2519716129, 2644830451, 3402354736, 4166319894, 1032140134, 2396318776, 3541228906, 397434479, 1435711167, 3172127057, 429665541, 2065172821, 2229977019, 3280825368, 2396499440, 4163140945, 2343456276, 2432733775, 3593240190, 3414363239, 175709404, 830386589, 1936417183, 3334463782, 3832048307, 2307093741, 507837791, 3350977711, 1165253221, 2942233360, 3647952216, 2842899964, 1813748197, 1562321857, 3915134801, 3503984227, 2067794634, 732362852, 3193139406, 4008764521, 3894497800, 4199555310, 2589913497, 2245388630, 2957719900, 724500531, 2420582759, 1987894074, 350967036, 290813050, 921507662, 2486129274, 992387594, 551956194, 1387588925, 1754338721, 130413781, 1369204550, 1835887875, 1256533652, 1546491662, 821411390, 2794985674, 3358733394, 3653274779, 2038598923, 95611052, 1732138892, 461928438, 986541664, 4099947837, 1889842213, 2525639306, 410533753, 1020900093, 3907577771, 1253677383, 626473519, 2464700888, 3377897813, 2093475677, 3479272206, 1515697283, 166456980, 3807925827, 2010002696, 2930902489, 3043122535, 3107114262, 2626168668, 2609077643, 3241374507, 3741650446, 957357299, 1728065297, 3993409525, 4274739848, 2218816574, 3813136883, 4034994558, 2639521692, 2117610693, 860767662, 709933672, 1670082568, 4218493868, 3830520118, 1637803926, 2614804513, 280768175, 1417538952, 1044920114, 811213049, 877310835, 1302883537, 3390509745, 2827927128, 2303069038, 3478272008, 297811903, 2238230110, 2616176401, 1950813104, 2734814660, 15758437, 3321564684, 1647322961, 2356650769, 3865305266, 1010959276, 1021614176, 2458785165, 3153785427, 1647369146, 4257820945, 409092029, 2992708858, 1179414539, 1693001075, 2378421109, 4032223339, 1549509056, 3662410899, 3731075771, 2226257702, 854739192, 2333168376, 3831123162, 672459584, 2105255949, 3941486408, 3063931623, 3785513419, 2454733900, 2814451407, 149252521, 3850018836, 2493517320, 445200997, 3777868852, 753763226, 4021231089, 1034604267, 2132847427, 3137530222, 1444528826, 1568377846, 4174881449, 1688659572, 1734424123, 4003363111, 706779272, 2717570473, 971914323, 1469697660, 1589458359, 3876467411, 3555382477, 4094407876, 3045207290, 3971347263, 1446967667, 333138153, 2498108121, 934242766, 1394602728, ], &[10; 3636], &[ 1689479953, 3685371534, 4033111375, 2546236409, 1992526355, 3704353609, 2980686246, 1962205010, 493853510, 3330949079, 3404775486, 995963370, 2359476618, 4166337269, 4122885245, 3807397862, 254950871, 939656465, 1152901624, 4053891363, 403489740, 1785761074, 1668697582, 2067302399, 41387989, 2253039569, 3927766471, 1431410460, 3833461627, 415336119, 3883105936, 2410940587, 2653928229, 995634000, 2858992119, 2988806752, 1188927329, 771118054, 2195745265, 108976395, 845032275, 2069454932, 3471071335, 2060102913, 3228691171, 2308719511, 2945302523, 1820942245, 316675140, 1150419465, 1211232052, 1158444240, 3173670921, 1686034098, 2456947982, 2848533978, 1479222291, 690366707, 3370078179, 2770865607, 1233532402, 153836862, 1806019361, 3091045128, 874731740, 2993354220, 1266470867, 3613083638, 2885315914, 3242335441, 1125608752, 3515334805, 314144256, 2337633870, 1854926272, 3312630344, 3265619517, 3610666982, 702111969, 515972312, 4053141872, 3622471868, 809790617, 892763171, 2910876060, 3440091579, 4234874023, 2764367458, 3136920824, 3494605116, 1982819561, 167177314, 2241971921, 3887514525, 698132290, 1490198321, 3652759059, 1621787049, 722771688, 3595184214, 2564985420, 1178669595, 3937546813, 3317244391, 2122523467, 2946067119, 2189818336, 2902163966, 1141546340, 254808090, 1955202257, 951810816, 4081592658, 2909053488, 3208529775, 3841938874, 1497747485, 349952546, 4157578435, 61619680, 3889423462, 2187522521, 1198768122, 1194160079, 1050136991, 756692966, 1195586963, 3211099388, 1912062610, 3622069566, 2897159796, 948263532, 1532710538, 1802135919, 3533830169, 3856207252, 197515290, 3506670317, 1620700477, 2256517135, 4154090467, 3594024579, 3262925099, 3254169581, 1699842655, 847331989, 3409717419, 1352842262, 2828082947, 1965631295, 3273595500, 2243530439, 2938559397, 2810391252, 2010423336, 2002052643, 757086441, 1620578432, 3426231828, 2007498669, 2398908899, 115544526, 3067012604, 2668057303, 2793223364, 1743336418, 3982673394, 1654091471, 576892166, 4157782674, 3462254224, 2284093351, 1399551134, 1036325351, 1731219496, 4168117172, 272151080, 612943017, 2192619260, 115775515, 92983999, 379551810, 3661451825, 2769027885, 905651037, 699519503, 61886171, 2966524714, 3201099618, 4198150790, 594005019, 2773210292, 3469678241, 2518165259, 3302956992, 4272562297, 3020363744, 3447097873, 351941971, 2781830337, 2374469323, 747786029, 3875756236, 3399944941, 1495211859, 210486031, 2758232522, 3380808106, 3498738899, 2780757169, 938777406, 1214252733, 1227336750, 1193339709, 1969983025, 2158100324, 3857354319, 1221730229, 1794819479, 3127680485, 1905497414, 4149231578, 3615970206, 2281482001, 1534088517, 541767496, 3126249491, 2888409452, 1068848373, 3120384427, 2541336983, 4129074361, 2159428870, 3946301876, 800764413, 3715235528, 3158825006, 1025161030, 231986559, 951077055, 2322136482, 4286048902, 1344763649, 3892401771, 2025457891, 944503280, 1558437118, 3650522151, 1919645785, 1530516973, 943007339, 2450980377, 4041919084, 1088539733, 2757862394, 992606829, 3041819168, 1614960401, 2279582969, 3075199231, 129454288, 846208986, 1234625046, 660809146, 3532880429, 252628601, 2423696271, 1858298031, 1388778105, 3504842644, 2733630767, 2248186669, 2239896138, 3099657735, 190376317, 4060941430, 1245037447, 1858363105, 3374140310, 2013206587, 3277964190, 2584841377, 424320173, 688240262, 765738214, 2152654415, 3604646242, 1167364606, 3139180609, 305962507, 3278904226, 2216417259, 1732931020, 1815790309, 522130889, 1446263974, 2636689241, 3735678668, 41392474, 2958898515, 2132044035, 3992828420, 1869274208, 2235893947, 2933194004, 1650239327, 2431660513, 1569791435, 1682334612, 990651015, 710574561, 2273823059, 1278475386, 2434675573, 3396438082, 1775365481, 3610889176, 960217185, 3558882767, 1818298153, 1114764111, 3174946022, 3276125305, 3434492342, 943048667, 2085491824, 746060159, 1932047283, 3794215547, 382927920, 1986062285, 611246559, 66218118, 4123379197, 561468147, 3984284657, 1009668765, 1318100633, 72107280, 2189759123, 613019399, 2695021240, 3203675755, 1043143343, 2525551493, 3793021769, 2060684945, 4271593290, 3787213308, 1409675772, 2088988330, 2709094673, 1745553143, 4134186269, 2966553782, 4248927999, 1415462585, 2077903946, 2170555889, 2284763394, 376804117, 2120600961, 1547223081, 3156360969, 3506247528, 3974314253, 82614436, 686791205, 998502952, 1752036701, 3387012871, 3021091285, 1846925484, 1523652509, 3709746915, 2156518023, 4199210449, 3018517467, 3546322968, 2248925146, 4043448871, 2088132192, 4042743708, 2996208097, 1121252975, 2022549993, 599051074, 1226341730, 266614051, 2143284540, 312560684, 2415441639, 424050386, 2720730533, 4139901252, 1291360004, 1202626490, 2954417424, 2821034122, 4212158671, 879484766, 4183448049, 2249422276, 3280998954, 92143606, 832623402, 3621294127, 2830388417, 3639209588, 4207096570, 1284153145, 3905456885, 1714211191, 914899411, 538466307, 635569437, 3891116773, 163323364, 1443353015, 735796114, 3567232355, 2369238294, 1560517720, 457709958, 3903751547, 974724114, 3067312154, 2697003909, 893782473, 3275415433, 1926375676, 1626637046, 1639093142, 2020991854, 986443050, 3524164386, 1986151996, 3200666719, 3678890297, 2645218461, 1681120796, 1595373268, 4285950338, 2565021869, 1025685298, 2842355440, 1423518737, 3577876446, 346787895, 3712464676, 1393634876, 135728953, 515475296, 4013218269, 492697456, 3573383387, 3814290175, 138834790, 771401067, 2293921802, 2903029034, 1412060797, 4271694554, 3397814298, 3382109865, 2910052910, 3675314680, 920791699, 219901661, 3100824534, 447921565, 2555613265, 1717732013, 1726129496, 3868656814, 4087551693, 3280000582, 566705240, 276475299, 3143437043, 1070688008, 3820602685, 579353003, 56781749, 4107744534, 321202401, 2610178709, 369557547, 791953613, 3340350862, 213738916, 1313095032, 2358306826, 3404845027, 2499456597, 3975781611, 3019341016, 1359848152, 3377984398, 807849168, 3592392188, 3625287916, 3896010427, 68914522, 2666916100, 1398306734, 3664389462, 2285977204, 1937090277, 3769043620, 2944706208, 1368976735, 2929039409, 3409690847, 2466270671, 2109122630, 3689958538, 2822571144, 2389696162, 389660314, 1022111843, 3326801528, 1922845276, 4040134641, 1089319195, 642426100, 2230567323, 1010953440, 40342353, 3717399643, 3642971273, 264568430, 2735055235, 2169228130, 349336330, 4038959286, 3893956178, 1541518205, 846168460, 215763475, 2966198792, 3823464051, 2357808617, 3733849808, 2829298148, 2818349331, 23548460, 3908373916, 737793651, 1252570487, 4227353578, 575916627, 335142225, 1949576824, 2910716359, 1162643743, 1301629052, 1470679705, 2581073585, 3946593246, 2636260076, 1145193195, 2536915898, 2181940804, 387671990, 2198865228, 2889254819, 3694401161, 3743697870, 3702393901, 3877656850, 436292574, 306499740, 1932066477, 1222907338, 777997962, 767846189, 3422304245, 2654237098, 1691890450, 1423805919, 2793155311, 969086158, 608867030, 723940812, 3829434904, 3698741440, 2198252225, 1073862189, 1870233325, 2945313240, 1713253401, 4266219011, 62006678, 3380440119, 2081143161, 2628825197, 3885535614, 33965352, 3211652782, 723727386, 3132341601, 1177495474, 4160229077, 3186357631, 1602138390, 2075192637, 772617785, 880291822, 2049877410, 1168560536, 1609804482, 3208323270, 1738061301, 1986167645, 1282687244, 1590039983, 1369825018, 1581183582, 3791409534, 626070490, 2835186285, 1167323511, 2362699417, 1906302864, 3875076978, 1811254861, 1952540063, 4077593108, 2066119832, 1234760656, 3819355313, 2496855793, 817790761, 1323251498, 4242582140, 2811911460, 597309051, 2667324841, 480387058, 1864617722, 171377032, 391867307, 240309613, 434543863, 3720669009, 2315945600, 1155720023, 2324747354, 3593519746, 1978174723, 1632551714, 560466621, 2369939811, 3838110393, 1895556248, 2334676543, 3860877002, 4084080183, 1653427618, 2333288623, 434060673, 1950369077, 2094498326, 2403598111, 3319240198, 3128867376, 93575480, 1448414395, 61831623, 1707790840, 3582728318, 2433330126, 3121590541, 3776124939, 4042319150, 860209440, 2067934458, 1267323322, 3477945458, 341210736, 2636499778, 1442791938, 1030739190, 4172051003, 591312878, 2535261077, 1363492883, 1946779052, 2538938847, 806269788, 2170457601, 4068920607, 1113820442, 1320778728, 1711984915, 2844848911, 2121794146, 2093321164, 1354948731, 2834137272, 3168927696, 1582827389, 3417750246, 2715721587, 336975965, 53775112, 296809315, 1422886644, 267088944, 441826151, 1595155088, 189084532, 2007261753, 2011435517, 2752974820, 3611356593, 1075874443, 609678245, 1508842188, 2860450500, 4251587252, 1243206835, 1385789599, 717247823, 1660282032, 423844602, 629857559, 1032304057, 3264912268, 16784015, 1007967185, 219409269, 1854277819, 3855877583, 3774618047, 2594977894, 1582081213, 1323306622, 3159925504, 4059130427, 3482011214, 361232698, 3721986714, 173607136, 2826556138, 3232270031, 263556241, 3189969290, 2471918738, 4260558075, 2670248989, 3126116667, 2556499473, 2606829010, 2951541343, 3310065835, 2459916580, 3048829171, 3883857465, 3488692503, 4202189598, 3948941477, 3228702107, 1178612117, 2586525147, 3286061921, 3391923513, 2521167873, 3172508572, 2299431200, 2075951247, 679350794, 1833191229, 3832233440, 2606213209, 2307374344, 157066023, 57454904, 1555904572, 874755295, 4193506986, 3776330617, 659313975, 2884022987, 926134856, 407007539, 2667604746, 4144959214, 2353533390, 3651735332, 3912622595, 783871727, 334008272, 1596551186, 328725723, 2017002333, 2813759025, 479384045, 1094205407, 3460645745, 2176695263, 2031169958, 3700887403, 570794101, 3329978579, 442193859, 177510695, 1246907927, 4211920294, 1439116362, 644614459, 1370218689, 3223269073, 1540383943, 851059080, 291617017, 249987291, 646227661, 1999413406, 396901401, 1158325017, 2173115664, 3094509081, 2284452007, 4011870978, 2580272312, 2125495977, 160998839, 4038294532, 4068915708, 4008489801, 3818160950, 2037081837, 1897458323, 74048804, 3298940335, 2453262946, 1170804052, 3729599052, 793866416, 1505433495, 3210217092, 1289767743, 2427482247, 1699914534, 2309140705, 1392709958, 2271028884, 2975454449, 2303695092, 1947549722, 2585331171, 1564261943, 3122141591, 1117882323, 3823838139, 1951127733, 2618650885, 725855784, 2885778001, 141631296, 1012437015, 3106878342, 3734126487, 2691077783, 2708310422, 1642521959, 363727910, 4162659544, 3295064194, 3989870957, 2348205117, 1410306408, 3403760692, 2133115242, 4201323221, 223129633, 4186689976, 2783741890, 3455737161, 652143453, 99216126, 466125887, 3111207944, 1831061873, 4215377421, 2860354741, 2032120457, 209951559, 2877151846, 2610955998, 2615971729, 1820149219, 1121448703, 3918557321, 4145726816, 250069769, 3601824251, 2425899740, 3159017099, 2088565383, 3107254419, 2360222345, 3119803151, 1060116494, 2397044160, 2022997879, 4037538002, 1667834405, 1983034038, 3079880508, 3324007826, 246650870, 1806445885, 382011810, 4196153678, 2707808626, 778105883, 277293813, 405037737, 2480851369, 520365878, 383090558, 1859659831, 2963694384, 2519087750, 4129026943, 2887796997, 3441456932, 681605695, 1935908051, 4082578667, 501692944, 2586554895, 969054976, 2643666108, 3192695444, 3537481024, 2027791375, 3156926222, 168581455, 2498413755, 2770043936, 1779891884, 4038975619, 3190035594, 3462597430, 1234455375, 4098697148, 834062881, 2753543726, 3044846390, 2179394097, 2460818962, 374817783, 2045460491, 1618837806, 3157089736, 274826574, 3757185257, 811521100, 11813727, 3779922725, 492684396, 3015056497, 2034583118, 2565777608, 2984428118, 1632112099, 4257294791, 3625499529, 3474533559, 466664110, 3206241640, 288166232, 671449910, 444797800, 4291439428, 3723150568, 1037922235, 1442984940, 1000292861, 3436107318, 2679137855, 3383334735, 2520302591, 1609273129, 2857914655, 978670894, 2845899315, 2388419165, 3580281943, 3417091255, 2409469498, 3975334897, 2759245997, 3194255054, 1797141666, 3252922278, 1354355931, 2660605803, 1213536930, 3994236234, 2937076377, 2937610964, 1076596335, 437925456, 3125544050, 3937749237, 3409723728, 2799028557, 4196003, 3832449641, 114765079, 3320248373, 3459233935, 2315620109, 2438628570, 1986417128, 2743347404, 1544655871, 2977042407, 1084572644, 2021448125, 3614331394, 1046031004, 970111583, 2171915217, 527339301, 3762746313, 783974921, 223854801, 567316104, 294880921, 2149052493, 245390330, 2278660889, 687725930, 551762183, 2317545332, 3219299323, 2918212026, 1649523093, 1507822979, 4081404014, 3334156272, 2129074111, 3087309631, 4089663886, 2072999253, 454289181, 1637178038, 3176235130, 983793591, 2442522220, 1799416024, 517489419, 2468868262, 621903281, 3945097547, 2836978758, 3201503255, 1258516991, 2861695304, 1209464854, 2422574488, 3671154363, 2543876385, 4189253095, 3365633529, 840184461, 3655439800, 3981292932, 995972756, 2179662181, 1498227827, 1365764941, 2539583345, 987266807, 951279142, 2690569250, 836866894, 2803186995, 3142361029, 2480108172, 322063224, 138513086, 3307682392, 210064865, 4004572151, 3914740899, 1902475798, 2444675151, 786777820, 3891858223, 46833343, 867537823, 4032212075, 3864493779, 2274176340, 4269403709, 1664272702, 3148987672, 211515203, 3213183135, 1064477451, 1886619939, 119907588, 1763695580, 1137788010, 1070848636, 2380340717, 2008753869, 2243310038, 2254452168, 420507278, 4238737558, 476544486, 1027946082, 4098497244, 2987773020, 2594971986, 3933543751, 4128433629, 3220979532, 2943736716, 369135285, 255363967, 1484001861, 744498182, 1782217456, 1337148224, 4036991417, 743169988, 1309721404, 2273491320, 2123096396, 2137418246, 1197976413, 487719177, 3486628676, 1740236865, 293554311, 1241237266, 242071315, 1022831640, 3704597480, 2429997384, 432113667, 82097287, 2254662456, 3940734887, 3475591576, 3137105254, 3991358983, 490002339, 3684106298, 3520847937, 3051366766, 180168041, 1519172738, 1779013739, 390964089, 3977190717, 1798884350, 3452012853, 3032553213, 987642496, 2451677707, 2708299902, 3475129220, 2702396337, 2316707082, 4120730953, 3827302854, 720672011, 3059924458, 1611668599, 4271987380, 3334962081, 2845220490, 2288381264, 1774544509, 2351525548, 2897807760, 973879886, 713264799, 3283893303, 1318656705, 291934618, 3603245708, 1822680205, 702162980, 209419299, 4141222812, 750506921, 4172646803, 3751702496, 2302071777, 2134343419, 481830090, 297394254, 2268030553, 4250599826, 2400026812, 3848063806, 98645017, 1905605167, 1656848264, 3635405750, 1349007121, 3665147685, 616196239, 2465135417, 2962732899, 1864187602, 2718887139, 16886570, 2246634204, 3326512044, 2571667935, 1160007357, 3071223515, 3246054390, 998465839, 1629678212, 101861913, 2984807746, 2495017805, 3497256251, 3199319442, 1125347888, 1360242257, 4167976807, 498743683, 4026681588, 2973980091, 2236624635, 828852129, 1294447829, 2231113860, 4032820622, 2477494850, 51373745, 2077300376, 1228698983, 602193592, 1080190881, 2341885886, 3252125538, 3698523622, 3197797056, 3887445074, 1816709009, 603827916, 3131542078, 2445055597, 2747259926, 2674003923, 404166043, 1258415914, 4081926360, 3708672880, 1307270581, 130515698, 1232689370, 844184447, 2125229292, 811439099, 2381195141, 606058317, 1595640123, 2873016787, 2288347624, 1768267576, 1140986292, 2806921510, 2330260149, 3555319291, 1040154033, 4071652159, 3667323109, 3843957045, 3629965830, 3425297516, 4011060252, 1428220755, 2395447002, 4148749813, 976260738, 4045911573, 3768993353, 1566874554, 790487894, 422535921, 3633624722, 3084935659, 3530348184, 1522858025, 3930970317, 757456642, 2764125394, 1271606702, 2043643656, 4167445856, 2875300050, 2334977507, 3666063607, 2062225439, 3415997854, 2570087929, 1872393864, 3058937106, 1478242396, 3311261031, 3327328058, 2968064976, 2027315412, 3051301341, 4240853773, 3721533880, 3417998346, 3256497279, 4105998587, 2801629523, 3816575480, 2097322942, 1877201309, 1423279412, 2966108575, 2707662913, 2208951536, 3155700397, 920421538, 2474155241, 282129529, 246270957, 2942900650, 2382865603, 145426821, 4026932016, 2119600746, 4115426848, 2451802377, 1795129560, 1857644645, 1363053522, 934343575, 1607399511, 3837946432, 1661942208, 2460809148, 146081762, 539145451, 3994413144, 1186020281, 3746267118, 791874622, 116689076, 1678197037, 1081204606, 802674785, 1821529384, 1599874656, 642992505, 3828343440, 118250081, 1547197371, 300482688, 3498923598, 2024147409, 2225551926, 2784186719, 3590853554, 2444211159, 1910708895, 3328161159, 2960509663, 261693067, 659391140, 1477907049, 2475545284, 609125167, 3708576651, 128566817, 2700022256, 3772319662, 3205402417, 607867778, 35765470, 3664750492, 923160230, 3512625207, 1526189031, 630567214, 312225845, 2863233060, 1454918057, 1836229030, 2263747440, 4220210180, 4041495293, 2286442296, 3297704827, 3681472880, 2571651409, 1231492678, 3310495257, 1759963235, 2017102488, 483028560, 3477067958, 3779556007, 1037991751, 1488253132, 1626120205, 3965838232, 642076510, 2772001672, 3352907626, 967946209, 1329426959, 904407395, 4287761476, 2117807348, 346501549, 2017467790, 1712248496, 3090003832, 2740727976, 1175602056, 2704116504, 2228546392, 2001963876, 2829399891, 3218378007, 4231063139, 243022702, 3241631802, 4189274453, 3803958756, 3576735623, 1917548369, 1025900170, 4123245418, 2265346420, 3936555459, 3498521772, 1479507035, 868619187, 1142241680, 3097571890, 1349848159, 2065481968, 375485612, 1631946130, 6606562, 274275763, 49667592, 1487086660, 1845842391, 2357242575, 467259241, 125869839, 559708189, 291488197, 770373353, 825488061, 528595254, 2517694918, 3884661747, 1797499647, 1057298306, 3983764498, 805346698, 3058617732, 249320339, 515324764, 2612033966, 627814198, 2366225823, 1276656413, 1249673518, 766412003, 1663221119, 4155392841, 3942002780, 2097042486, 3123053624, 3954336954, 3252770750, 2974430297, 1960686632, 3790329968, 1997188153, 1998914803, 2594873727, 2693091253, 1227140324, 1213873209, 1651729488, 350449328, 947558271, 2419068624, 2391366241, 4275323171, 1609113602, 2823728377, 66529505, 744148532, 1609823852, 1906921648, 2271564188, 4186254187, 1178040066, 4023115514, 1305792228, 1690613212, 3458113244, 496460370, 2618476375, 1190544066, 2176560202, 2276473837, 2522161430, 2610000464, 440518595, 1001658010, 3324204442, 1263928225, 1485293695, 3446137087, 3909570758, 2127019243, 3695260755, 3359349906, 3141098292, 2541398172, 3575448726, 3222721978, 165253206, 3135199663, 460110423, 2385179813, 1631504080, 517516259, 1564055745, 486059524, 1418925436, 3059270125, 3210293303, 414855607, 4202927121, 3837221574, 533361178, 2712745385, 3290088534, 948639616, 298484197, 926218206, 1442074810, 1064020282, 642968472, 2908976133, 92856881, 3867366389, 2363221869, 4054296546, 2589468845, 1187867253, 2760375067, 3885177157, 2053648391, 4117621494, 3080758166, 2690978782, 901728841, 3281893688, 4227520312, 3812007653, 578797819, 1029878447, 2914247689, 886586584, 1248147975, 4210992818, 561199869, 3270867934, 308839339, 3895262405, 192385229, 3772159951, 3396462893, 2514226586, 4185157789, 2022448536, 2514786928, 1848675048, 3597534632, 3386922450, 1443705113, 274003774, 3803570996, 3529374128, 2618211788, 2553692266, 3226363672, 826462207, 2780892770, 102431722, 4108068467, 1514449499, 16916063, 790468106, 737455902, 388909337, 1060871246, 1980294792, 4020694397, 3421707652, 3558247153, 3868241436, 3650372822, 454870313, 3190861269, 1121056466, 2160709840, 1487447127, 531375459, 4006552618, 1367526003, 2049953384, 4242984695, 591782438, 3620499955, 3484689592, 3195066728, 2227109051, 2224733666, 3064559967, 1002850564, 1741551474, 200038933, 236231763, 241608448, 1125647989, 1733945828, 2748977838, 4245341740, 3973165452, 3692968986, 266033770, 4031581082, 4176579206, 4176011405, 1635921130, 4246049839, 1378901965, 2582237341, 3897386600, 2020921730, 3812280911, 4112479160, 2965028984, 4270899054, 1144134566, 1030809753, 103237802, 1976575698, 3291391509, 3987713093, 1752261770, 1224606301, 3019364112, 1594514740, 1846241836, 3520740283, 1106436435, 3762747664, 1664894769, 3202570996, 2736584864, 4065973429, 1497702943, 460904489, 3419319493, 3663664671, 157299306, 294467156, 3053318226, 1954453123, 2902024272, 3954099364, 1435891455, 1200952825, 462363771, 4072271634, 2320864436, 213783610, 719834276, 2353049209, 2385102228, 3689591523, 1668822365, 3862038087, 3226479764, 150925708, 1404619162, 3258264053, 1333417229, 1578105238, 233886220, 2959191636, 624793378, 1747005891, 3014971815, 2772914499, 3582324477, 1698139368, 4135587991, 468564861, 3469855870, 3840371606, 3368607970, 81247725, 2513246148, 1908078625, 3543563617, 2845092613, 2537091921, 3281313322, 1164265431, 810332022, 2955114644, 62816586, 2792318884, 2636062838, 935519120, 686525478, 1240254896, 2820221328, 3668051423, 2047287614, 747732773, 977739916, 3119771059, 3438223878, 2110947565, 2295365445, 3700651115, 1594930835, 1326328115, 3522403990, 1581047373, 3642258254, 3643833459, 1442203680, 3985817160, 3359497845, 3567742088, 2703933881, 3286503035, 2716577830, 2455212492, 2944340719, 1744687635, 4201727787, 746359664, 2309400684, 1443319803, 2822497091, 3952225358, 1266751291, 1552262601, 2664857167, 738558864, 918193930, 3233432628, 3883227720, 408624322, 4224897587, 2920895445, 3574204814, 60481955, 1557884522, 1756716917, 916909101, 3661455996, 2861736733, 1335145748, 3162280916, 84878597, 3775068288, 1369947025, 1105445783, 3133745215, 3118158526, 1219630817, 409706604, 101744074, 1974571608, 3991681153, 608799768, 2425583796, 3121594464, 2868366050, 1290542011, 3826018622, 1052859250, 346669398, 3252761547, 1752812895, 2116190764, 1368270810, 809767833, 907751840, 3235605061, 3921003263, 2785209237, 3472207248, 4282859029, 444948076, 2309068816, 47377213, 55235131, 4151310506, 797428759, 1280116312, 3949643772, 1523687038, 502974093, 1374335610, 2016063664, 672538456, 3855027382, 2642939730, 3920110085, 1431378911, 3182719501, 3226314076, 3550233008, 2843936526, 1844531037, 1461312622, 1341306514, 1735290609, 2395141662, 74650360, 2213667353, 2372419588, 2514285293, 4165332515, 1069041235, 18240510, 3009105031, 4247238665, 1358739270, 3742754122, 3101555340, 3257719306, 3973455129, 3763335030, 496222953, 2931805409, 584178382, 4205230521, 2406412778, 543292816, 1556087588, 91201694, 1004907209, 3998304829, 2669022995, 1024110775, 855737062, 2934693606, 4086665390, 217474758, 4185692391, 3630606523, 4260974327, 1064624969, 3979549033, 4117631371, 2560854802, 1873572115, 3477939028, 84454657, 4158311865, 947577724, 1981667660, 954073202, 2530779598, 1906604658, 2581265848, 161799394, 2539843422, 3374973153, 3281766109, 2708538328, 2496184317, 946045554, 3923271365, 3003624942, 44367286, 526430955, 2379276524, 2628065138, 2054070052, 2835653082, 2408767093, 2200542235, 3133166590, 3103533911, 1618827108, 2337578618, 554779330, 1877587927, 805925111, 4083532900, 4119063607, 4094145462, 3800247708, 3097776190, 3828122568, 328856056, 2087701413, 3507308880, 3295544625, 2558779233, 2415437903, 2734011836, 2482408771, 1446479447, 561714919, 101350506, 3868078636, 1939417956, 3724743531, 502213291, 321477517, 1091134027, 1374936116, 2601120184, 1082085776, 2218405402, 2593749478, 4014470084, 2547858922, 3945522028, 1789900808, 1309653762, 698211039, 4262093683, 2994540354, 2932194625, 2512009314, 3516090705, 3433773106, 765214719, 3954254778, 4274743875, 2586062537, 48725311, 2318175537, 2966026065, 1998156091, 3604337015, 2589164236, 1479833572, 1276704396, 1558933223, 1777724570, 1464319686, 1618776366, 3178012457, 1491987603, 2036107848, 3479801899, 569571166, 74211236, 660351793, 551899518, 63632211, 1650073300, 3835378904, 591005946, 3671060744, 2108971615, 3896431581, 2167756512, 689307396, 52941191, 1798314696, 113046222, 3990303672, 296491437, 1136355576, 2802375123, 926185509, 3119566734, 48260029, 3353012417, 1055524799, 1094796423, 2464468009, 3005975624, 777936673, 2851287717, 2025527642, 1589454470, 473046103, 4291371754, 1411361884, 3136946679, 1752457439, 2406543962, 3782736499, 173562397, 1135476471, 3417785482, 1913281654, 2004058482, 854085513, 2274358926, 2006316150, 845969262, 1363650305, 767423334, 4219043013, 2108203495, 1391321388, 92614808, 2638397579, 1625105828, 3199303404, 424744970, 4055540445, 1950463844, 1615106969, 3594450298, 2160514369, 3287049922, 549721170, 2819316519, 700345342, 1829032754, 3909073800, 843756052, 3943348323, 1182935117, 952651084, 2244934408, 2200348674, 1977011522, 2444186657, 2142916255, 2147345310, 2434135627, 3052046286, 2254117922, 1822579677, 1567825379, 1919065971, 349114077, 113358004, 609194458, 138808635, 1995061228, 1302815309, 2878779823, 3415266902, 2869660799, 1016025931, 3335856096, 883527774, 409652170, 4203782183, 1855526550, 40212257, 3525134238, 3678763465, 74131589, 3826372638, 3970369882, 3482037176, 4179430299, 965319189, 394262916, 2462172558, 3925263781, 4133777999, 3188738267, 587031879, 3454471188, 3982289199, 440544328, 476792674, 3345660659, 1895005972, 2053792458, 4134858390, 2429890414, 3304083305, 2392604182, 3395163690, 2605833369, 1666281741, 3228552126, 3979068584, 2527460000, 2347138934, 3123976326, 846077745, 1878780364, 3265560682, 1403833441, 890912218, 1380482915, 2465711556, 3647092006, 3370796849, 4236615940, 3586267443, 373728198, 5731137, 1243905856, 3470858780, 2796818161, 1238908162, 1584148758, 221770729, 3700200051, 1499779925, 3117049016, 2327976210, 4136532828, 965956791, 1680323133, 3215683204, 2178759560, 1732184813, 2755885165, 3823403799, 1902450762, 456020793, 3663422204, 3811589041, 1857954995, 2771097813, 177543012, 2569158780, 3708456423, 2528175033, 2080927043, 3680699272, 4023854803, 3809799093, 2371544632, 198202999, 1497390699, 890250824, 2769881560, 3194865750, 1684145181, 452145694, 2991889421, 4144843353, 3617207764, 3936271187, 1888135133, 3570340477, 3235145096, 1623855795, 2156134139, 4024884924, 2178204752, 2483127118, 916349188, 2554473700, 1443854317, 233737404, 1476198027, 515142283, 219340509, 3903163154, 1036861316, 1751209967, 2608587693, 2099772214, 1665732469, 3640692940, 1207393516, 1894081469, 3785834247, 887800476, 1682942477, 2048898909, 4222500608, 4276211921, 1373682636, 3791996368, 41716502, 2124422739, 1908458226, 3822116606, 743748407, 3145479211, 2452722417, 3733950629, 3162660014, 3622735657, 3497841429, 489897133, 2942665159, 2044804733, 223574165, 3776817195, 4082509983, 293862276, 1468912429, 103056195, 889161041, 1966953849, 3609876707, 2638065928, 1047905493, 3398519294, 1459149575, 3653946708, 775904631, 3344325826, 3854925531, 3146591215, 1543400143, 1286305299, 1097831620, 3814556351, 1594687103, 2113488526, 1483526237, 3807813211, 1175223255, 371540392, 3577846351, 3656743164, 2990923805, 4163557475, 1184662610, 1562684052, 3875455396, 530201974, 3563735536, 2924370187, 3802067413, 493795622, 3302108264, 3959076190, 991809575, 3790738454, 2200910384, 3470166339, 439053460, 3463112738, 1601747871, 3492602097, 1831054492, 2159047155, 683788148, 2417360498, 957441114, 3609045281, 3877704898, 785019165, 2054440276, 3353013277, 3418718269, 2746047459, 4026183656, 350438566, 184040812, 2052350906, 3967553243, 4017912439, 3023412728, 3981147025, 2561779615, 904031255, 1467577417, 3069914862, 4142230394, 2665876235, 4186456195, 598937839, 129946526, 3336739268, 3454671035, 4058349830, 2325596322, 1384293515, 3417683270, 1148857156, 398134011, 995116192, 4009371398, 1190266862, 356079055, 3395729282, 516920498, 3773319277, 2224415508, 1364285773, 4241870984, 1929215048, 1982917207, 1060681561, 1385177924, 2093856238, 1157884680, 1523090084, 2440720483, 785742014, 2344457397, 2451934062, 181495597, 2838865450, 455103850, 1847462635, 1857129816, 617726251, 533706755, 2323829199, 887492253, 3669678334, 766422621, 2551377116, 3769626589, 3052478013, 1272334214, 3370684650, 1238471614, 1283888404, 1093592931, 3971239378, 4183695633, 221423754, 1311480232, 4284291584, 1065660787, 2997149504, 2021597782, 1260499852, 1862303473, 2217798464, 4132482698, 3991747985, 2803154616, 1689402801, 741635457, 1586623886, 23968392, 2917945969, 3704724021, 1986593466, 1025079427, 163946901, 2614765396, 3829334814, 157726426, 304865048, 3889433559, 3988860896, 1233717994, 142420932, 1881719095, 537691535, 136246017, 994812518, 3796224388, 4045415767, 220351354, 674375440, 2998040855, 120450481, 226329006, 1904563614, 3237210881, 2027356413, 1913138530, 3044811367, 728913106, 1882651485, 874480565, 1374079012, 1745572834, 1322314392, 3232099910, 2827984607, 4215028467, 2143330077, 3742910733, 770738485, 2586508431, 2534440519, 4262086070, 1538337478, 925337160, 1397248459, 2835793954, 807501809, 1088863792, 1062604194, 4006484491, 874173023, 216305838, 198446709, 3229792024, 3229634861, 108433180, 2369055698, 3074696468, 39957286, 922106346, 3969368463, 1251206350, 4254324701, 1617965310, 3674752218, 2059215825, 2389702629, 1480268914, 256473984, 3939192840, 1026369386, 2084973527, 3154088165, 2751420649, 2771299049, 3303682443, 647635940, 861713349, 4054257968, 2644785711, 974864213, 1391305458, 796623050, 542009228, 2418575427, 1272626747, 354685077, 3531332167, 4048228268, 913350633, 944902477, 670411593, 3815770329, 2977477017, 1933705649, 2179465175, 1321626596, 3524651628, 3647479831, 3184951104, 3934770931, 3759354566, 1300200998, 146528926, 2514715252, 2038725791, 3603246392, 804639451, 927985280, 2605466503, 926968751, 1650620111, 243404233, 3880687324, 649985879, 3763728004, 3128971332, 1163963763, 2270481655, 1680842455, 3817842888, 372617912, 2367770416, 1521078009, 244172464, 3849098759, 17213868, 3683347717, 3667803373, 664776799, 627463253, 3965720804, 2678723605, 3947486986, 3604393079, 169215751, 3415040937, 2956402237, 2516352387, 2961241821, 3002752765, 1674635482, 1418275283, 3679981873, 3168190528, 1552912051, 2881775950, 349603732, 1998010250, 1643694071, 2230183983, 1208716578, 3487212087, 3185208593, 3306534729, 3775045140, 1661678170, 2436469105, 996816068, 4144171051, 2001836944, 5143238, 2662872030, 1114224303, 943645357, 2631400103, 1306570990, 3012447212, 3337497501, 2792281632, 945046401, 753119848, 1748673315, 490411348, 3831769979, 809682968, 1230679525, 3152591256, 2293609806, 3178622941, 1939835562, 1285634605, 2018307184, 3865772136, 2836503039, 1611136160, 4206035666, 951054753, 2773947666, 2871150909, 3117316476, 852775100, 1629450391, 1866062404, 3914188345, 633227979, 2209839847, 3769583182, 3276201938, 781985901, 907853783, 254660179, 2459795416, 1153992447, 1340828206, 3875202342, 3692780610, 4146633463, 2995551331, 4064483051, 3633336277, 3166949516, 1895018799, 1213176499, 3807740849, 4243665322, 2068831805, 35308613, 182839257, 3765266983, 457069208, 3146140372, 2047859687, 2425657613, 4070347510, 246630712, 3916610787, 1411026053, 1220761679, 3809749314, 2278309569, 2033459538, 3646988066, 448882456, 393448551, 4068290188, 4007045718, 2086086506, 1511536294, 1884227698, 3570325017, 836698716, 1830587520, 2278607230, 3709637320, 889145912, 361149653, 3037892398, 2349362704, 3720035488, 3930480736, 804598022, 4218700745, 1493408173, 162094858, 936663144, 3772859229, 3331137555, 1237082854, 2169615063, 366884571, 3557471134, 2281510298, 1429043064, 2666224918, 1373059234, 2972483471, 1991504395, 3431520491, 310755855, 1528073141, 1031105567, 224295805, 3424368174, 3150971464, 2305024143, 1228144108, 4014845246, 630413828, 2733742672, 3062587703, 341998745, 2960897358, 1850792298, 2338620067, 3217035035, 611710038, 597879084, 371658931, 1372059629, 1570101919, 232519862, 3150578760, 3993887192, 3045844719, 2849070546, 3349219867, 216832346, 2830103332, 340214898, 1974175280, 3831608232, 2908923236, 1314492805, 138089778, 1121354546, 2359042253, 1075516604, 1809603427, 2615964539, 656847733, 818142496, 686360761, 2504800877, 1712087343, 3207256785, 3676407803, 1617818504, 4068141722, 371522199, 1314806895, 3510183437, 2342405661, 3291155119, 2872122866, 1368588283, 2071123966, 3145894046, 3579869358, 1763887316, 3189756248, 3417949087, 572557458, 4263138265, 3066838495, 92990668, 2592368372, 1660723640, 1356119881, 3964730869, 741520441, 2065320302, 1530448020, 2458363175, 2619888805, 2674400490, 3472517629, 982503561, 4190020652, 1507233762, 852476202, 3110605057, 2059460948, 2784583304, 2279798041, 4255875574, 1285286879, 3885946290, 591729172, 2894365955, 2225184312, 1955326411, 2739502251, 452598289, 2335856360, 1880792954, 1362849872, 3908988398, 2419865633, 1027653817, 537841437, 924184405, 843918297, 3414422045, 3353072269, 1150303989, 448736065, 148315163, 3321325923, 1053550534, 4164378279, 3035227477, 3631102566, 1032112828, 2654432312, 3024592760, 242076594, 4028719359, 418406890, 2143389645, 2031532841, 3374578463, 3195583439, 1899730870, 2211084963, 1043062681, 3898196322, 3570591556, 3014402959, 1058542324, 3982931298, 3225118542, 3604472840, 2623187602, 2842769080, 3673798708, 2320983080, 1503232208, 568529821, 2595869355, 2032804190, 2272688330, 3980332019, 2641795133, 2988176828, 134507432, 4241721584, 3818435189, 4137355511, 1247830223, 1540166618, 398566715, 82945547, 3520871022, 3037864944, 2355612038, 2922815715, 1380952336, 1377440990, 3291630710, 2593192206, 2840982225, 1381454852, 4247382976, 2730153619, 1371886177, 2187792535, 3720941471, 1584608929, 1907112417, 3165529489, 788838219, 2392094719, 2757512848, 1490237241, 3446377867, 1953251083, 2966067679, 2649047343, 4015865685, 934788106, 2721418606, 2645175788, 2146440877, 3607717247, 2027478612, 3331164292, 2424939111, 231093199, 1928064611, 1889189031, 1996484024, 2462578397, 911391499, 2839332138, 163585026, 3216853820, 889447435, 2925890744, 3974842063, 3861984373, 37152326, 2371538867, 2851217234, 422797641, 1566886508, 4013456353, 2419384199, 1820317090, 900766000, 118293793, 677768296, 454666009, 1821152324, 1206919790, 1665156067, 665840213, 2415489724, 1662813609, 1605024391, 2455746991, 2415978633, 3228424226, 1170681887, 4209416263, 372421722, 1367236194, 1582475107, 2534855529, 4225119737, 1733839847, 3035349979, 2017373481, 3541817080, 385649444, 4053965046, 923745909, 3909753404, 1708758694, 2970726850, 3653995769, 2490628201, 3039101053, 1429972501, 594123445, 792127498, 2653775795, 24163512, 2159019427, 1447633967, 3788353734, 2530224048, 1535376847, 3637529541, 475737890, 1480354663, 2033042310, 1063661, 1960643507, 4231965784, 3777061289, 1589178837, 1370750524, 583972425, 1858145954, 1396655253, 1424769143, 1740074414, 733007009, 366220186, 2615602388, 3628366359, 3725371152, 2734902959, 3840576465, 3169707518, 2331576541, 172639875, 1335045968, 1242995077, 3535273387, 1348006215, 3327977440, 2252861586, 1819516327, 2697492906, 3536060972, 364354085, 2128099587, 1097669609, 2369539262, 1899308232, 2826027076, 251610714, 1833366456, 2498004327, 4209925928, 3083802268, 757770687, 1493785567, 3963538538, 3992191871, 3395635674, 3915089747, 1587752483, 2076692304, 239175639, 1181624781, 4072705845, 1585336863, 3730655922, 3098725949, 4160909147, 1386306068, 1230885936, 1161941648, 2081458729, 3335663614, 2681845720, 1525266294, 878004624, 1982738846, 1493492914, 3869755414, 3558460894, 3318620625, 1211153278, 2923817154, 2134666173, 90206626, 3774147601, 3159242217, 211850634, 1683920975, 3419509433, 561248501, 2219201393, 2704473464, 2109930370, 1966590295, 3763961321, 3710255434, 4111083708, 3669630234, 3613482874, 4227197028, 3200913345, 3176949944, 2570851313, 3007437836, 181922762, 3355997794, 3613776821, 2494660250, 2991177118, 1722445340, 335420791, 1822004217, 1020647226, 4216435952, 554872562, 2714512558, 678375918, 792717391, 1184324912, 3699517264, 1387222798, 715681960, 1762504673, 494737474, 2430735845, 1294960793, 563625208, 2521249590, 1359399068, 1529030962, 161693920, 3692550682, 4261806889, 3911140268, 1796777798, 1560560503, 3253954915, 1478993322, 4059118339, 2218697307, 4228806326, 2922262283, 1389385047, 1520245031, 120421632, 215017916, 941957196, 537434329, 285532838, 1319019517, 2260588795, 4246464086, 2513401292, 1255780628, 582555104, 3776819498, 1964386863, 198549809, 691527119, 1455336753, 2718376963, 430317133, 534234672, 3963888184, 2939870602, 1013503572, 4251027930, 351032584, 2506780282, 155322293, 1603457426, 629221313, 940929669, 2140168814, 3118526863, 2975043414, 2542950348, 1672189235, 2091819583, 156791564, 801424438, 1579481769, 606448367, 2676797638, 1095660494, 999737097, 1180771007, 2705415919, 41171434, 3973781203, 1140191691, 3872339385, 2174068911, 1171782493, 3162791523, 4016408468, 1505797535, 4230233395, 1472675231, 3877988453, 2256455964, 2213131637, 290987424, 2419314882, 3938908490, 1876277179, 2206256766, 2462184605, 571242904, 2804624265, 2537742358, 1512930954, 20443981, 406585626, 4159045829, 3743334477, 2720271699, 1327186622, 2282715474, 856172708, 3358599987, 3908731226, 1473501203, 1040125791, 1013411175, 2178428342, 179178690, 3299338066, 657503960, 1545374802, 1426666903, 3837024697, 2807513087, 3191662271, 2929270892, 2837727006, 1178843414, 902457495, 1503862797, 4128316640, 505227925, 402394707, 1239082017, 2532495641, 2213659649, 2453021542, 2833770939, 4075060441, 737288063, 3196564671, 3347031354, 1128774756, 759830554, 367496832, 1845668500, 1022723613, 2125318989, 3193171564, 1296593784, 2100962794, 928469721, 3513786287, 3254304913, 2471056685, 323600219, 3708437214, 1494329704, 1323222619, 1037364325, 605738342, 749879495, 2580477944, 1541792255, 3578355076, 1583200785, 3705915572, 4189346050, 316968268, 3066282807, 2057963356, 1504061835, 224110056, 1232523877, 1756186392, 1481507640, 4193355243, 1739426324, 2577102061, 3897674924, 3493979988, 3504168938, 587951092, 2483301859, 2158160898, 2500450333, 545127629, 1640229616, 725035055, 2587931433, 4113473744, 4013037468, 2959986602, 2768797776, 323074624, 3890671630, 2627301401, 129761041, 901881866, 2355775310, 183903732, 1304973560, 2325771699, 2604899306, 2712839713, 3314617282, 2383066369, 3939162262, 2358804150, 2413816673, 3870280269, 3333721889, 761424285, 1621662176, 3737972215, 3797133469, 2927249190, 311560447, 2983529496, 1645662697, 2815579772, 1384605226, 1975569750, 3438896430, 2153425055, 1933394184, 666699680, 1896630748, 3037753431, 3058622420, 3123120096, 3276515450, 1056251605, 1132159421, 1773572347, 741172336, 4199407673, 4292517641, 1258588807, 2359189321, 1890989499, 1436616678, 3725810143, 1344959, 3169383524, 1846476021, 3620567306, 3964415846, 2584023408, 1788946809, 2432113874, 3021455913, 1025198631, 1375330149, 1734026140, 2112521040, 234854014, 837796525, 3469588005, 3558565274, 4181968885, 2254419984, 3688734642, 2849215967, 2082915962, 628793510, 2668077688, 2671658432, 1960044042, 2297993582, 1677267956, 4015811883, 2957427505, 1711985518, 1967619462, 2363307899, 3229014012, 413632917, 802674958, 4188881074, 1001001610, 1178059427, 3086148039, 763569311, 2473147016, 796453303, 1992026949, 2986634059, 3708112546, 2217334304, 393217384, 2409040458, 3294661042, 2008477371, 1983407099, 1535775309, 2253074183, 2365159699, 25041784, 969938953, 919813306, 3255007835, 4126849006, 1149295401, 1616961575, 4049610625, 3714928640, 31167510, 4029635202, 1593639277, 674210358, 2407087181, 2082038934, 1540952457, 335427986, 3365342309, 3437864350, 1717068274, 3174196744, 1422250091, 510506978, 1544552477, 4176789708, 4166623697, 407519622, 1691350559, 3244576628, 829324152, 136672835, 3258593955, 46194264, 117115285, 3643458495, 776722375, 3434492653, 3692988566, 1323992511, 2957036283, 2564967609, 207000418, 1612202275, 938281365, 3500670015, 2514147455, 3619943885, 2420380525, 1766106326, 230055465, 590347524, 3819437181, 1536699885, 1459966380, 887109960, 3761856421, 326207459, 1198114966, 2352746750, 846264182, 4087651522, 4260980083, 3692531527, 1224333971, 3026948934, 2848503003, 31151839, 1677236216, 1070803401, 3213905770, 2956179232, 2304979954, 3554966962, 736917059, 711943740, 1085866479, 2424094464, 1071927164, 1569764952, 1199810187, 1253877148, 3493654865, 1628631752, 473149744, 19967766, 2211455156, 1652785765, 1154981846, 2774085682, 2612294675, 1679324998, 2671156232, 2452932446, 904349261, 2138112251, 2095345180, 1863338470, 3301354610, 3353141736, 2363343186, 3026364498, 1026177201, 1760516901, 4143092446, 3035764696, 2907752387, 4168883524, 2741880350, 1087390243, 135260592, 3472841234, 840102962, 3177200036, 72163601, 611139117, 3870133867, 4121596405, 2505403848, 2896610046, 1072017518, 194138634, 871843203, 2946005084, 1429997613, 2813236145, 3628760953, 592821787, 2169431099, 1233289234, 326972645, 2432580133, 252411516, 2017334732, 1076658184, 791291644, 4027958541, 1141025814, 3852232131, 613290295, 3966875164, 2105931102, 2923888127, 3209191925, 1880563412, 3321080014, 413557757, 2344104686, 1575721926, 4277920045, 1076013736, 4105760337, 3621812886, 933169454, 1186603493, 3510283027, 1915413223, 2200544669, 2432233674, 4082056572, 922115840, 1689213262, 2377389201, 1814721075, 3855682276, 2000264314, 541395077, 2968926312, 3025525181, 2914038586, 4291299266, 2535225757, 3837563224, 803339381, 2017564654, 286531342, 3066511824, 3998396363, 1039972840, 1380844035, 2503093716, 3716231825, 895232486, 2294846888, 532581067, 3206382725, 3449924423, 2087226435, 666272241, 1896734046, 1140696422, 1508691072, 2180232380, 1428701432, 824643080, 2280104877, 3193488674, 4090367226, 580731921, 2333351837, 1895188244, 1008211486, 3517726308, 852465789, 1648818849, 2388943747, 1586854372, 2691387894, 3275879436, 3164792947, 66258512, 1196105716, 3676932754, 781697518, 1080202479, 958201596, 2162422236, 3364770007, 1515375142, 1589722636, 3631817432, 1366228945, 1469994991, 1276073576, 1597950139, 3355976269, 2725693850, 2376110416, 3059497687, 102703797, 3888416268, 1470515832, 3796069020, 584659380, 977198149, 196400770, 3037884708, 3181078823, 722050075, 2373531064, 2771864628, 3538629168, 3672564050, 3522094929, 901823916, 4097143023, 366310736, 3418688105, 1633812143, 1247435996, 3668222980, 1451125043, 1252574848, 4224623388, 10671035, 1973152294, 4216050200, 241671052, 4160736399, 3111838663, 885192095, 3166478147, 3629428720, 4202015792, 3255160511, 3898689749, 2814086752, 3095285886, 3778617102, 1489822200, 3852275618, 2531920686, 2166576667, 2583337462, 1524875147, 3267980921, 2397031089, 3240526150, 2000115455, 1311787505, 3099442844, 1274817071, 1012829326, 114610774, 375904181, 269466199, 3772035037, 2205104815, 2830995073, 3706571547, 3677141686, 3490869491, 702814974, 2778579045, 2455955272, 2611360460, 656925090, 337783112, 1781235217, 1204115916, 3287054846, 2614466560, 3901711198, 1944357669, 1824143158, 1826193010, 684250230, 1652928224, 2611789693, 2507319901, 214867654, 659570618, 3932627009, 371231775, 2208149317, 1404862649, 2398679622, 2296858980, 1492259029, 399587501, 3552307575, 5156467, 972274518, 3064887182, 1574975785, 2333109332, 708249006, 4214315469, 2632927799, 760593395, 738911951, 3314585045, 2703384626, 4128070655, 4017861798, 2402659367, 3860763803, 2787243388, 2645666766, 2585208498, 4294336880, 1073908643, 3345719900, 850162876, 1322587908, 452836223, 10, 10, 10, 10, ], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_8_fail_1() { let mut scratch = vec![0; limbs_square_to_out_toom_8_scratch_len(2)]; let mut out = vec![10; 78]; limbs_square_to_out_toom_8(&mut out, &[5; 39], &mut scratch); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_square_to_out_toom_8_fail_2() { let mut scratch = vec![0; limbs_square_to_out_toom_8_scratch_len(2)]; let mut out = vec![10; 79]; limbs_square_to_out_toom_8(&mut out, &[5; 40], &mut scratch); } #[test] fn test_square() { let test = |s, out| { let x = Natural::from_str(s).unwrap(); assert_eq!(x.clone().square().to_string(), out); let mut x = x; x.square_assign(); assert_eq!(x.to_string(), out); }; test("0", "0"); test("1", "1"); test("2", "4"); test("3", "9"); test("10", "100"); test("123", "15129"); test("1000", "1000000"); test("123456789", "15241578750190521"); let big_test = |u: Natural| { let mut n = u.clone(); n.square_assign(); assert!(n.is_valid()); let square = n; let n = u.clone().square(); assert!(n.is_valid()); assert_eq!(n, square); let n = (&u).square(); assert!(n.is_valid()); assert_eq!(n, square); assert_eq!(&u * &u, square); }; // - x.squaring in fft_worker_func // - in sd_fft_ctx_point_sqr // - j < BLK_SZ in sd_fft_ctx_point_sqr // - j >= BLK_SZ in sd_fft_ctx_point_sqr big_test(Natural::power_of_2(63936)); // - x != b1 in flint_mpn_cmp_ui_2exp // - n == 8 in multi_add let xss = "25384011009295806532357690038301328678178355953143389004680558796704961731811371769\ 8348887554225838035390073190759696975022053239122423162346051254744840880490984341177697039394\ 2496357496943277061191765920774224515779467940405470702545201277606530020609086200858337557813\ 9932094955323117437035296373337749227037144486879327887878580264803153246332648728070722720409\ 8748122149130475786531555676642745076046195290007644144605436402851580347563884203630770681535\ 4339134562152412313231385866864609620432477673101106194143665361318643443010110310914139246281\ 4495900108750339496814154628497416421978520801168208029449033909250882426338036373004325931019\ 7906528070532009056454776199466663095524968424927657055569719442685881822819618376975628796773\ 3527868177798018856821550982309020750081279052471927764378814922511379061604076463607235118234\ 8384316873776087725943446126467665804994475669679957697182110285399045928047528825422656995045\ 8956301794491664284561446424981681643258755837488352663756958005055472250585622975523682821742\ 5840653038854964611048717103932275160172239933405239897300176009565797811948235571555901113905\ 1874732815468960729168615214409027131456131781126349835002781348528907385429144964609711518835\ 5008058187218750939209554897567356048633008722784956226083589857211299371319988453193631662551\ 5484498900269994184165775869251782148873698784897783347370507568614203339461261909548049759647\ 2918330935579645513120774610863131017686926514081163438086814799460964646115620831525831022716\ 8661320082717818421230039253955360442944920047738765693843427880547620279352186880579974554091\ 3350838625295922244488969926978740524724781507248898183556840656961784557366539635828189934252\ 1122813367647256569224304004607475771994181609185090164509092303014816587643910403864439469973\ 2686263720629419621174275942012040654958220673513208970394443999237682758900183335264384977195\ 3686439445857485430402768242460837593696661212772576377186247560095103803818714123355404139446\ 5732964026831514807876996950701171053276598465626671715848414016087007600656026811407674702365\ 9848495932305895568286483780044870848691514368304725672251145929943004054162654910881497587562\ 5416341363864193355141370683481134661213865113604215855928353054857941163955199487788782308165\ 5623894766595490155113595182375061933022111829192604845343656798690907820834817559722140972541\ 8382650561598301445526174699214976280467755148143335452757875682670478371898616441245954181370\ 8868144071767292349586406425219361491555000486081574037383774578330210302150118482776750063341\ 4194020566397686475958691180641496679063333643420822404142355165651971531840080804015572223388\ 1258339561030457165269538438678490155051046099690001363606141423898882695850926669919852988428\ 0578684124433071204019517813704847509309940921064397212741562907432256419960194867787432719318\ 1899135355889770170409266009332048474018778353135813269373098033178363769402489322516317661840\ 9820353267705488299782251468550073470541714609297592468768078243256629420265546392128067902869\ 0505973272111947890733165472126346735954704474435913727608806258863821718690315051451963571139\ 8335385241551266160493808020591826272296952205945153429907020710794628836446098862137789988364\ 5061370139023316556076292861481684373573306082044255549588283921693803817779486572168220366204\ 4018612794022551767036187935986194443733071637993828200406787926247245637976040171215025296615\ 9462104357615602073499028665033625449317796047666402127182821614897622573895034921399540765544\ 8441031239505059083196212784176901507812098458105420675901642619341302303143544645518088848596\ 3184597636126366577642853717224019965102347995098496247517393480419332592390561364999691202007\ 1185739252664638146579014680449022778373951379172826428713082103946952905370446169287541859632\ 2794343456553052565388340544618493006573615131036074181390312178951920287512464374485368261345\ 3285859271322941597763295688086522082554769078220489253988823108121642168300868654325668697535\ 9587853618010147449311193031347604866357248426353518640775085786811503130132389109768637826447\ 8323601852508403175339814410330299638970688977829545016716072157810339305725743812160164010590\ 0673490844622396328063435237640471189542105226205301600396475215650106363593354566827940252794\ 0430585216191804549638059781031446670057882657140793210354349848990160602509614207869428160963\ 7782349868027597342987759249888314273569473949545208129107801505999539349905455150981787279054\ 5346245323706556871120711064161980785324105139456583933823278158232347534171855886541924842091\ 1737032914068394836641794292817368148472600104289879258245450279727971327950846920868390466249\ 1016222359459333505939176959616412687902039156284248997626574893498615792188716287486029467150\ 2932500212759012140192315599398307309331875531193733932483351268906044484917359053413919621351\ 7272029441853699773461074454201852140908776426983487837821887706640384320160377247437893216368\ 6833075136247161632953013832486882529646579541065125623654805777426833427467087059007616312680\ 9967660645183806465200459519623881521373761018012122837506690418937977751569372480639729425849\ 1374260421861952456442342860198914827769703548668834723432191653397425374473058252877784472118\ 6920112457565465249490567248435495508179288788477040045389260509460263724021682785762214878585\ 7808989995442948389450838640541574020926685354586156360130753799664001965364850457997252042106\ 8548320682139771530488711871919673183710867449515518785561373802327090407241978461659896652913\ 5699124875465572855258388271096860626724298503587458626473725259256315615255855548091011872871\ 5286963645160042236386864659165831462867544542719499599855553068703411489762649252914556106274\ 1290786172537110180950625761492781878812956823402274732371854261197667391087749719071249961522\ 4160644862653984582664842720195942152572600432375038286056477375484561566854254375103835388425\ 8036474911589660346038100244508879003470776417428368297714709155334464205918816433537393341685\ 1147401139504040287223160449553590046881221213554223155493075558627722703847440445249762513403\ 1868810444388545879696053793942419008628407151610813598112538731557401446958254532742010060592\ 2735337959425468914029440996705454670147168495845254559961058699973773865059452667677792048416\ 3472028066320728793401957450785337350807218895748411362968398032018526002727212274510100012685\ 4367605076018476933629314070045039657618753784021130243097459306966741527339170146696561736123\ 8577572652305334620079355394641553262238396080544644498226701351521140722987250949694829386708\ 2104291735537976893161141917371623978225048341070220918139230932341774973113896232081741084984\ 4415519568694333375410891812563607315597369201669943455920946468259277809275781388930325818427\ 0146980199529055148199661003351456361099424603047626478920294791899035300884737862133262973915\ 9843019172172042532960784120337132451454382424300456465507273471494446083324999362290945689490\ 5941966302010990106705115790958717255876023094124321408100620636413032241457078352947098059536\ 1642135713666231160748022375399683065356590225274671241801692131917173381307377989727567818297\ 8826910463595500754697303243214592063971091420233456955263391169025482521188943803946575917850\ 1117952795221883399268282252442065588937629344571434136542419361835423984590971873750638258940\ 8423888198503388302227936384625030701949181494698078717265292212846415563298966861979257088255\ 2500847712904728662018280311091347082989117026943560749333370606210825813207481796753163127948\ 4814441461271154131440012144666118421248720261430675374512701974465035034637885904075985369363\ 3415686643166599393717080961797782568467707812455334362910353113483759516064115222185261477967\ 0969523733728915308182695190384478569312790075719968607804447965259923721205900208887993875984\ 2868069309855978805047691318387636819666080094734586905138357878418940906746019731845286523799\ 4271937396067729878906508029890833509284093448625385832899540649547023209536634670045863111206\ 3541702880123348233066467205427959302119632134915525743322759397284161743702839389644540462605\ 6176552456095073028642039703331873351310505526175076834667598647914144009601701706217955676420\ 1132678490107293678753755545001085562512784125069621257720305077951687781477335464853332632878\ 8156930881038543533413327378839162898523739790522761464180108214305445553749237770992422058635\ 2612596059372064171690621909659228399250175309894964560325578359374850114792145015584153494438\ 7252353021758984148913306680600019237374558790235827029411060207645871894119946680572493409662\ 5881042982928268060025627750225425954173122928825336836990946641071331028524499131420797581706\ 5238809331965940294339494916890724472231664452423677760859750713983397799332000669409467967438\ 8800316762033138570589257187243940910075387788756545567060111307531817347014968848893394732162\ 7448425737016414883971064454082712586376800310567632640551141141493652431266727552791705948387\ 8166950001478074577561770998321486912409551058036697600791987415279444046672619287521341306853\ 3464290752658976775750987495207372781570888398967312364243881778598754999321987594999522225435\ 3874404985621617253999219818304506136797042780278676436277899738218829963507467624652514087850\ 6581386489334939217133057442567188534229203448714587288955063795654469444147750523110916425852\ 2174283105640488071314474411337508490710319809031828758753934876005622251190592716257023290010\ 3291815048254796503237214580095597960156236842954959709857312425021649060958133485805287743111\ 9248737080127113221708515428108088215908907688452489711647594163337038805594842036378951076855\ 7026292367256591649056210501407315069367357671956949821448329432554193195522404127846714948148\ 4529929595612307998419800800493441162182075085847593081293922265108550290961868801569896232224\ 7565117447743726825375443938317898977214062433766452659242574618075262951715922441802290486892\ 8330829623460802717111858664912559088290147772544210742975927644591191030266494783580939074500\ 5668322720568969435506279392999853365574717182174240562011023407493609363852213491783178286666\ 5662129723448805530019689639938202663947437150842500251815582784329376469124616309714336419096\ 7681216517203903998037002064204995164577769613621480061345303257480111147489355100340528893778\ 9103796133732994582627823109436950753537955959188317367365729189466615977063986145546144811732\ 6796415889342754492635237598972292367836031256859561355613175723591450750762096950365419212359\ 9275191154714224299856671669667736872992072917582515246225582798843325444179831335821790853162\ 0319382985533282843953854107506427900502148569837565436091351443119540684768218146039013678691\ 4373291829246886835035824393343707639698529301453246233962438511434722441246430886328603467893\ 5167817334174816644287708769125945161423154255133693277076574013694842624834000767329904329706\ 2622206167027131115251805111422461932364100161341170031355057802421893355298742231358342605475\ 4433571553721395899092923258160288719521998702371897771192782011320341382862554060521880314967\ 2585662970557268026340856771858556909113274429599195148416224819882888413365963453606650852196\ 5935884927311811945359607841412720662705695418544968043134238224285401416633915603942200164186\ 2367237980979227984787818476518761035944269867295600752842960846811676883265052393496085273654\ 9217411480105573595887017864406245209769014902820778326795071324256161049189880743751674907615\ 1431754168848023102013007174412959126668872823596341277436844442194988441017254456099525570563\ 8709043166437751820753589793755105468096028660635531110432840722598043843028797254328196179165\ 4832767864171744531834812250109172479492988658198141131116996364128810429196392213914062307310\ 4941929247557847363895141888905095928515690265655587922791428181672824496650883518424004372498\ 4974723133777672121642534362417516618468165247783437623121090972587093372159232768444789371228\ 3113487805920369999462968887527077547142763375027474886504089586243463092090950364767254779081\ 0189112300896193300114124516709478790611511861520793690362268542564437069485068139093567770698\ 9550358116430099675072103114233933809491207869958612342311968111072880775146257155076875912873\ 5616362325461336326392341048700811778324015654839972008346835174777985516563626525729563295176\ 1149266406510340344664463312809157985974983620697765393144808094643070664408104702172834026219\ 7232358292533213505206150876204674865079227579353270631542995876263304681059417188576722568851\ 6947562221232889044961688679166619280889066880291426247870371347906758238393272426328737822593\ 7542949865212630553997338363807182415052496628281807565322180405477148948947842212138657442399\ 3092556320888938642303970180478701320730227959023572323642533269545729898966240243388111236388\ 3468617383816594255866788632898508862540477743208403455794652380615589800108974895555062352158\ 5166064874166957158899720893721230010965757086639527439467410577370969418657815100150506172959\ 8304617521780089995000483797982829476217509440124870510444419347528041254942378488709935559562\ 6591161961283140764930700350494562359343071925276016592109835362463925079212814489749575520540\ 1031938410798165128905519152012668578181794292848105904283881526279720990440869571172821007815\ 0645748787498416468137345046749783663888148613668420695421301662014622270408084300416240671318\ 6492730554744689889523023339562843195386885626843337533649590968874453732751467472149971540252\ 6686648345809260713911017906903026015192536865175915597500589619481845572391828552036495430419\ 7631064995903165408350342825183891048439930001191546383386344275748772349765030459089534583456\ 3793605917339229110802629693801962101092021169017634408001461101678809695719060616055769200054\ 0568201434229917663915997836950017202909114770410078708028106324022252271589322313482586935287\ 6474016067275258506271062353280310551822473097128651129904805345160290048546893447192214481400\ 8388133959098809873956403502056449282340633794108211102599044968283243490620821424553918757620\ 8858237000663708935195116872381196452696057701357496896081575628347546975102099801562468554213\ 3122156393383689134122291283772466424112015479402268465848433938567464298072469939240020194014\ 3163184533297646286371806328751815732891748228453602466605927974401080339039916995235085517666\ 0080177621126138539648524281432672685051316295838419336325546278742337292906642836094937249909\ 3683628230694799801588292805384325614126371712309613169315599426401891565334118956690677588148\ 5099510178002797592174196325730950510490799363196815650376080703761993076712176960496518460064\ 5189084784650283534991039639376149276870794416400661835331739305211215719118080816198367963693\ 7272904257125864726546033647796784187807146657852511831209883841855540428137644240861863727499\ 6971074165199927731011766976975736144131153172927812449969241977132698633144383408431279775838\ 3112755195938488768567544565906877476512360591689182736425096536129359180232938347116658061187\ 4860912344394725707273855809039085890586113931725537411826115934545607855881072370359435989431\ 8492738926040293119689084147960344094018481572703823039721243562926278480057873162870281344617\ 4355201006771399436900412325991723733873248851782316037053780567529316169075788021820561301256\ 3356529273623332815917681289901945419464592275859186736848496007237187137775691723271735682698\ 9653553503942199687887366467319320557230520299298891537331558990134045055742553241659792473308\ 1771513397077910180669013779824841142341962892055292302118458844985425392869167962605396204258\ 4352030450474903068938347211001275582635005469850097191107613315747637680735112764426837118749\ 6598972883252849857968552648267857420187426101958508760850007649829232922663281207839543775529\ 2293775486983903904382236944538901374039403833763298749609357115492715200637557622161661766662\ 1748171821118219596964027796602389169489979779799945745690170409851826717179717152749672031123\ 5141972309254741869227575985802126307892657345768515217926607539746997671825761430713558834061\ 8586246491369649690010511216472743140291857584082725124859266931987661038975654248562446809159\ 8893933170781996281579983413259838820831406670293176052334211880584271535641104434019519368524\ 9046378825291911849231957267634203168819513006764229544311274102222762699511008630787981672590\ 2329239619680715768519549091019457009738278689974421703623692951383097306818683027179669923029\ 2175395459930277459681334641508727008577702840467531039484888426981727204952758321685240634135\ 2180128950384815451339222682028862951870030014546575652348485675770296710397579649599150170735\ 8716771253316616632212253772365393503392423200810048046541087221291905825980652593195708691052\ 7223538951986216233113975725938095841144613141336569844722175533648814397498908779483326025912\ 9048363303768023668510037177338795904906085597741632327603630859941512315875203706449507945620\ 6353616466601807060918043634007246467327594216230529057123600377979048555819919103848849902881\ 8999047441574890288062316009416586517284801511677229027999343314631162689765116492586638873769\ 2014771357214803086812298318571047163942847106638171345620585333463822705198270185825822825030\ 3523736385455140560292620017853328171528206465970115664656800908229480489843172618430023152175\ 0539118118808632391983756404156569518616145843607380617032101413134086356927748819072076815746\ 1283210562364930548643143092236216267187497934978356871168599821050241119723360249050857302480\ 3075561875018184260782580535118349808264243989860110500604825075724096527059616883769370277703\ 6252669827586706905055086086944244684050390537152166679343437340526882480448279154555125589891\ 5350297782767980128816626307215829638831145214708544254623549919505153403217824354378986620568\ 6176620661718616062022505893545202752119903500092459702348230774745468924860192844230458601581\ 1304259661972403552508544600769173735036894135680932084119363519745608441888842350679587176479\ 6471659931790458205998622715180386112951660855702959737672288733273925772375448459755103082909\ 0852000682985509852445421323092918505220669176853108032182730244971211225145767245003922090266\ 7176127750228852204393629080006849061964749604011536607391221064325728183594592975373679704592\ 1045967295486997475314059978018758251228044188898871031142553034439007225425534378243670011499\ 5257902561701839346526269711120222564455297038736633646054000926941594496819248542165417691979\ 6479610232762838676162681608232442381534860618652830096704838341888255132951357197885268774182\ 9321899253040323152961057984707504136084890127788153373956561990482790466967453589861974887228\ 5833893544966692715403187577777333068118894911701033065324328065600685898926878974529930760342\ 5428569688359245045415232671817533438124316171548661217740386472386031047129402093175172829153\ 6991209594767632654915542157284901547564215235587651241560760151826147506332298638060055611058\ 5247275121697461687813041184799149892596983063086418851494810726375228591224446359135385008433\ 3642566404209472838542946423120614611635187190070759579968301335303287279582016907716678188779\ 7399899847371787226091650523065917078284791023095344628044878177532150886672702246055437458747\ 4321702369486255638665509046833250400330654401030628423218084317414518262283385148751739576260\ 4749000998321112922411259649010751755878954117056979167531464726913169981073449841606296457682\ 6765427531846185744923923102619831111602552545834571673225861435215062183573322049830976650925\ 0353083269809875574480941486464138080240542238325432323641985789169827052818487692851682992171\ 6338072265155123294435453335807679716244477621418895180550411773098261282046296649072275976963\ 6175611428189572320687910601294559290641174711015926843829736881082340820097667030056065486576\ 0182727525709931845715230635722084341818287166904944104345995253765775582023358205119853091720\ 6759161149258538655285691868793116684622525542751603181951935804418586566981220345111531539450\ 5343533003081665862439749947259370047493595051068065291737626475513773904547948521694728950780\ 8152152169341779372318518499665781724869738453441752220317065605145176051692687096959987260341\ 2756634171390284514381496654244131739767680496178136017633407256332465723694653881157772078166\ 8649152345944339382279223392521431435995142012781749500076820301466283040735126140245119075737\ 7758414735235960105559539974934506231191403842805961305649151658369578315932597431524304083386\ 8580397904361613211073052635217514269908652030145837617907106108150946030599691536926880250789\ 6714114638007481358303566044734879026461014188491633314687983880314037537252606121277396993192\ 6956629139830959925501116557394149191180008548189888551440447388254211334965671482700808934968\ 1901361986914593593924628545098425839821222083410843216289370194077867018185189076810129205336\ 8177002422155323046471022317075622174346535137925984133971727700708307100778255215609589531301\ 6037380328801398660164935472198872118088636661545947951408312026297059437462693949348900881312\ 0582483136238316107043517171426928239628845762756029734168935384387310896406717445447658548321\ 3630018921584161251670342213373613731401761485092574162273703786911483173696855991908278743734\ 6258659965377271536493887252109012003512861685260076585893368887873369981706406933594077143340\ 0142421406406226969247172972316639474850346647348899678587053537862938948608510065148401828099\ 3645891453899901496118543099945282207819968884038526535677335294041121607537731290090513048932\ 9521490683593273776976968048463323829502394983373672840015404447442856385281502368815695954684\ 9136447546639995475136701369077130404974872258699463368138895224835247633927241925875923681277\ 2187054577614089930203756004901712759691379559701812338090329309367485685112137169080380142282\ 2792895241238540156073438743030028529006516861642396711878059379637314818736003376477638747094\ 5550667771146547380476949822834952643076033063985122996208346542659019090381113130040646937150\ 0884949450775327613140935824709121316097394619346427497972741342722795414458996547283075887494\ 7256445393002873139572260430445758767949725310076015600076703197510033369124100887687046429678\ 0560759090742841909748258088404693496225075669515140086726253373410715059599096649234223782115\ 1572925003019818773149959485182718542197258743252013891172718120817277013436148600804472739351\ 1798705020069851160301701130238682313144930933190145568700439654385253763535428396224457510225\ 6907956699821145184472889510331374382476145252097123201123871066817365984917202578219157899740\ 6844852524942010747715069444992775476282876280284010259638431719802043757260110168619661443442\ 9470593541999242351836884858779840239260477633822877758957630622185898320347823096160990988232\ 9521159412403470805601743913525018738830616197030740343651445566694549114585388042782392278940\ 7973221533368776459822987931174212097217888852907308310208393823567777741963944649293356964813\ 4196196020236550677472645879463611901559288776482878735660870452355906392855722428548829974892\ 2967356701688949092354892973096469492456427669112376843726612944369430957678621352579825595684\ 7817736358708828035442020328745070065082296495982966719687838177878184099025577331988646603662\ 6227846061411008144812239085988285259987682322932417804569943145672823521915803006185653251201\ 9859452237419474847481111897581264138677277405669186265959851016298871800366594006525622880007\ 5908401394411510458487286746829091687514255456234844686701718106497710112250338220688419416429\ 2474286502236110437369934360255846058766283099144003298343932474248751071518074427609948467748\ 8462118949286067527104876956816083948716541970206291192761496250316998166668716241620577010162\ 3290116243666950562097499453542457516520263532197562979166448925141936004933233352708523759561\ 4290057748247731716764736498912473718627185978537573534320033810522168566721563419622285420526\ 8619969699503632989228703994209321254168320771759051073228868164519290953301858904967150170809\ 7269396581081317115236473912865571421591026272268341155046445747528791217627353283824931329664\ 7268674965921892551361035299621188169954661556419523865287985376174312761145200794375920101659\ 6938803339337594916094015754075726332834557416625284711261745198538435878584359623936742886602\ 0964514529129787120956034351830864528457405516418766938636139638208977998946520040867499357884\ 0200844645536434002937259727369013445947995164977069000590589458262978792030101956729210901987\ 4108945048681225163017631958770587330031017918499013857985129947102708463190132573861279108371\ 6407061004372155108716698190254214383599716749614484555752908091820212258069293963154882798012\ 9690252773641283800470634841422300518586814207900389159019310513727596473855626777015032259236\ 3872783534654588238200468758952641501685285967585806404662327779458770929113083890958644399725\ 3013352243964611168800918719931709628395844407757736526677318655479310777075800521682138123655\ 4858418187039828430915333289428645073362467328578205419635479622941562629705284745126674486754\ 4297754329401519814234493937892853339583135339230043378106424532814709523309080248344326865952\ 9563589713683163776667076039454061663883595281925071304642080038408124794564899256026386778143\ 7908727833850022616527743783028282051166273669675963231840817888457267017001291140220929214639\ 6773419925321143654010253526009815298466254805204887031101229890952833354854358627036097952878\ 0812622789972053782230194489265327838834633581914304516707334284259829291913918196287037485209\ 0569263790174998656080152898751382018120060315048674788933918548640517186958608860996859996729\ 4179364599102600712136199903671066180337090434256018322627398563329287936617508668152100548543\ 0716708796498653693389225516787523466857182109215459182832140638809862393206623471453009677023\ 8605907320451506804429182842304434619907047102409013565577177282952367156008216574038981759503\ 0718201578756541904659296546798573455184258125610581812184158911778431451854053286354970929705\ 9306123992912034872370972391631830956178693802641388561245637595247635112591182424499010508138\ 0747320473478459411971818471332673006342244224091354414514178931971296080593476880367946437987\ 5692981190191715441348950731617034102087411565584292802462985445630273564390339518530253964609\ 1525580774048567421257058538669106359258285466397689364379546508483709765834070118505264803632\ 5998406175518765869749812997513677765898371810895695299643488681090473353777448812553595394636\ 0713929607748580355557913281557443289648379818143565246814652340654451076593523843184671984660\ 3116168491870998924714876549815708479359515040930580425000973046232649905603625640022820563484\ 1388714160387534629718727744331119446325485078273983874855426110146416485335297546409469646853\ 4095860891414502044728602816001631133316931918929627628456877326209326454063699006788938011741\ 7344774223792931880594905575354484875546552615499568051332834161480070879254963327997990076902\ 8124737977487799253175664109630918575571386372608397033940255241680933832675540360973501331276\ 6335254065428459941528608628236069802125419195665104016399307017747517222924724218528375830718\ 0599636784270900296670462938700161317689945947625800160625746405358477456562881794596090125379\ 4315114421416453150073982622705135871514981072538770150613455503715272811093058188226691047664\ 0441595040953175861733052148424883666772996510405753902535338208036317074566401345830203141243\ 5798355377794955123701957400219099084445320649098160676634081709871756811646599691983924512899\ 8438847040006335703918866759677049326364293999771016690110973645051017123878584914506671680730\ 3995597946636861398980540956696405687973958725248588485631814679767072780943250363861274214674\ 7297242366389309146775256628575040015575685066368900971044306922505165780418749870955838297573\ 4886951513222591224372392259657396551768898762199478071189236156553768029597210298915680686229\ 9071344424084911901164805201555582864408046264167160438517610389649287993424709630140744443529\ 7354657041714975962886194514898158699997573857108030471238357969611697607560636670700003029167\ 8023392222781924890537801610324958615387319082879900273105659720725518681610597198766358557538\ 1231747953171601101945302926842971013111796537390976037914094199774005083416293107504370960144\ 9975584268733672557727371619397680756432069485272987332359887781926969040409225605386782548685\ 7482952693628718944874493242356238688300414576771832753955287954272413192612002079286806522775\ 4422923151176433305456266490797360779392129163038846211881378138430800501771775017994679493296\ 7062737747405318636785730824217365838245550240536549861475983428566924184504354202753241236389\ 1916519915527812197631016743816503038410800440838174883210548158066564942540595873349859874149\ 8572866345539247542605825027267529612209294456714469821615162481679077182551390465808196945561\ 1466892219080527862227754618312683827529557217690169537458539836586895350902230093330296243260\ 9915021710216737240686841475211516170292610065631640471043764219037595171607989244783541013657\ 7060460247590964164036811749121576835429200310373453972472452235823411464601866020199033170603\ 0209833462012513091869873456657220222541421936112590699693962995835029236143833849732159589140\ 6601196155651551541327348958077223058881914967050186767875316880973830559669752607137131404187\ 9402377559489383547079513566238020664138313001536756567194770254045102856759945541336613617815\ 9767387753344041702070773103090004392048321380688520855116582070589819429399457680037329161443\ 6766792556270598837272627547286224500496199398744524789148347944357738284440392164997479907221\ 1342954558046700697806147616384324900812782771547879427312307170300659482075289946559521759709\ 9694469043337528357020363583421781786472577318792659334282542052604590561031821371809361741772\ 3913925436233543089915140327645793873786334639526291065816676991582969503747832395307834399011\ 2872680929979999606818504631629293778560133933061989168103860011333009867786564365171719678405\ 4802442546689711365755313007010599349587776357015659093656778743639018624414139147169954622671\ 8591395543608289750305302424498008822964656766252699273747874957601086462034354319084102293725\ 8179325440472894305329925644570766475495293296378444911874243213186978647918984662740846137047\ 3895565503121318690908970638911945385080344397457006076760672618119014278783111904877385997378\ 4717673393832495968431021655646452915687102850876974875511098939274174207421851822028368260576\ 8140281507774085990728817959041372862127166101778334333516794836245621588607088472587620613250\ 9100087638823742528638155736930914818459533024059458831831072463861078601500013012777591897847\ 0212100642646481521946253260393962273411037868712760095059343004906058933110099332829876324054\ 0778915076707451022662060098364072983445583165568555550882529629722368297918929308705928302607\ 5655052995758844162177944247966427913403318884756568487276252976306098091842879268832824433620\ 8755021525661993196219458059620539251504874047430314557477858466933140274557208846870064542552\ 5590848059682893290385365870656019332693656932992429983769134187107344377662156981541682289459\ 0325692904840593899792418469522283629289701121370684408769593847583678608314484560418181520094\ 1833420443105975964816872427438244458946717776738545464630835197710521184803595561648787711671\ 3467120650712815237086739186058539672934333167908434025428422903823151128089325304617000913402\ 3394905171257497231151651017163580913201832902971425325701994594452436033180531916026238331725\ 7569508907015797863633463731618653857717879374477441096367056772455758690616782749192185593044\ 4203996792942755486789392884032358252727338245229868530829388366813520247032807007639583960489\ 1140570066822135909581038973815253853073250934254236252008803089741609717305229957052002487754\ 9045644690781423597186882212582490107828032055717527820162392608522732231268648440297070804744\ 4790796369429203559899730039233881976435883422786532802018250634899324465488840076404986633882\ 5231918843089623712037303555906442194990200325338463939051821275471704231971722468708142375396\ 2596816700999408932141938943502603587713289916499594477648125664048449927091546853042918691392\ 8957033921586279378442665367717294984703253843935093214307849729024579113196581206094365492002\ 5352897006933699971383053566386030486135712833891181444745163607943027604536599436902718298981\ 4098417556765191930126789156482372569236216911273301648234016641295715841434052529355870428470\ 8263700697063645111420353557023611045319751880205615896574582701937986175494253199547497660450\ 8344733453499048527184584008357502850089274408277249982060066047901304039628038719026400729314\ 5380150520919442221586744112663478826752004789009711205347149401788458612736895413704744380319\ 8773009136427206366432311115978772693071630349808080003761842341579624391331241115868328549502\ 0523124652284983816835029935527867945465203422151834167385707469634588615887236157670899062570\ 4349650889674508161879215672920982719755571860814902023182137758123606265319421475261852486792\ 2050778828395401163815379545189470431517309851295879214942901071176278820032170881225061808856\ 0788064651691683803557326226590218111259654769025548486006011022370236709601177867114029167880\ 7165459597218990353895480043690192894412553227732333972352770279939732242628698052341964811149\ 9577347795457277850573504943883464206783424420404278731014679495206551390357191427165231323325\ 6334789302476720943011825473081773449232646851915338081349746005296171540030084516410444575083\ 3418198353394198609929699815954369204298918717377677413268989572581688785332989586139622170715\ 7558065074431762807220083415009272146657375888271042692151846731356888334314399560033362910020\ 2512243997508785449199375009752955061994013493696409993477937095279793261182398914777039973900\ 8467961838139107802371201685652356965030082434245504313867677992376128456666452925633015278028\ 8935643221081362597987767269547427293250562158696862143041730147866734451357079907548063945529\ 4792775358696278026516279160834325306856766416325958868501559018852969330688613391472519017164\ 7739314433305923140162159432053858755341483618606131941142673501933717293415067813326576306042\ 6172706802947812229674449423485837196779680069101487732204219582498510296576427654096797858130\ 5818087864948052466418478352158946842178051530294271850383436179149265262486959861599029301112\ 9316032867292339067206625464632039564126206425552917425145794622575513722280190318068399675022\ 3330003870072037949562818635379200174016916959988487399870156616875742707259363005810527945749\ 0346079429770497881433976206496376268741162680074832031153542944538607758752115143791790481549\ 0781103703757806468711915620154532867858853718471746071589856557207982280842252941886935845381\ 9359346218395607280624319562539992852180022881096415520704599137376077603983212545698832506387\ 5154555417904034467128267641988456567819228959216200146586006845080484525080356888317784246323\ 9503104691520794167665882466504281443605160981553194263748208512457256561306210401826430906615\ 5834871370183373036623123527110023691265941444697705948908218255757070686146506252670208814809\ 6103953485173154240689447585407389851840435183985621901192970270784893510100062072004799388067\ 2453019216817310841384321521565711568490966018293679211262867433502554732255211512071024844123\ 1941153588221378132009756373274648552599977015374113155319361556155039343523604707829191904220\ 5165931987917232046014940492454683557332747296111457513209849566733139593839636954212795480514\ 4577437025282948818044435284030899540745321080095413669644451552402574768718721360317735882807\ 4635353931072355248025173430348861567020268709764060023317664101041927987666742524058944585858\ 8579564597607050023015634670423794322789323591110601504492202809488488754677155422835118113052\ 7662682658783734036762257073078726113028638632541196544385531533712231924488026458688998643408\ 9811899717878309859661264020256848392227218024366124498181866182577836176461879979639031385066\ 5030721164891422501650152392787535782065616767098139292347221530087713109649836881306200698815\ 2775432619528021536760697654221958590290469196734650624550779871429856739510396945833890173446\ 2680428878257054112406907121257715760285719261479815805270582039456983670621101506692230050699\ 7650788726309625568337446868262156308396922832991676641785462889173346703627517032822125487293\ 7271760628688216785963101977235403410047964899432598419232682648895074095021070922208520433323\ 5291780208400090375831935067105549705304091225029629853591894199723944072005928286111379559551\ 6071188136595617675031375584533701013778505828926374346944662177140792954372915833445145027467\ 5544444415153716504588426608055093304888520819482432114237605726699585357107140524793992756376\ 9147094024995299888175190530070468612006832989898087637951079738411959709580555510390414852897\ 1033542667656804349446012743127471300546652591862229683033907035141165475615279384293927453518\ 2273710084635720440864233948952615577012210766649293695203764389644195149046332355236557248516\ 0669250964622068201028089137579015370483388890931749831758683916698808747864268549760939985443\ 0352380283247905413671657497003431102797013026702953402822161276430590479989146118245027599098\ 1777525428118965979895185673377108065750272787801662449783852985324012121491628417427532503678\ 3374271185458638739815472114582482563066090001961827863736188096330024445096707219425328562803\ 0348155814658054733865849082527068942990680219866394827169688943392381665695647155443716518468\ 6857338283506961800839544367497654423469276166856752774008995140891531727165096001430387657612\ 4368746356915254569228130411544256351297228305891903750133957194690642025679801423733260427244\ 5220327715059912212605369494610674632196566459157503521939307019233216692428715017692302705496\ 2926242226340550184901229253407308579233325774945757320147870441745307127548606944700346538161\ 7524989621433539816855636196374359669063464081971413552682850858374203621521209713267339414055\ 2674850555448978760620879045922965959047166985159923391316468155458829939817850941500011541470\ 5028840776792498910963556286345509421366169504675945410530742051036978860561733811067036608757\ 5462504784007649633217515377888265439258761111255945907156891381252854358604552996263363529007\ 9818721552633179657280064259073399571025915666937936827973372250042607016360870955766012025807\ 1839709392593091222619413508675331517879579071631796750737128339126382448926549580644812030733\ 8305698009075393381295220601636382314720823004914613281269047442767847482295882241178084302592\ 2862105658401937195678974998720053464785313847986996198455754005553497470320963787643200766331\ 4946314316041645432407806805985898816754288239966302863651745032794610225629929074863206489562\ 8573672880256684679265049964668064472804658665692076144955643999632537966285990323747370299903\ 3082943342562206433363556812869437252650022966653055107663241635946635526262187632446380498591\ 4911396355089993277022834694432004912777110241603899839869291170284660077684620982192236892730\ 3632059951627739317616400090782863677928919423137395109867996830884080997660055624549739870250\ 0551535764666668838764200606702573046206134414453814986926354584480196269467599813748424371391\ 6446849886755633971435087302768502451539775150587241960056017344614651327511237537925859828520\ 4432329191711258604245307424193144005342146315791016821726050901476044568557891333026970392437\ 0420826343704288121165679291567630469110037613031829081832359307059037863949170803478862279305\ 2127524609591623144665629578617141687850360473487551226655707598963758208807345170775334603869\ 8133157835731052877207820832280820613846490523477336059006134964594853034640094650346737898896\ 1266197792913519972989098386066896750792751746367250586591532581237759800679914179914405078820\ 5195671293830668536817809368820189200961922268272542409455420587114831936882235400781620595288\ 6372274992984662798848942173636801771861203827843235294289582399517260642440623148924790821478\ 8110768258008233270030515091168650982688579400949431584426808237905269034439183295463276651937\ 0703966954489245616416606121336574375756423125395952179234408508413380103422733622256858781860\ 0306158946998435585503913439019610909497448236940477540043298607305060213703312911394103923580\ 2679544168621161806053683176952361536737200739132840161732548723892888472138166707807349444018\ 8310673908796462511960941802745370770148437697858231121715471935833171914645595648202988456484\ 1779638946721089636962577905306196392358366437345974134985243201290754994957681052725993383339\ 3145807992765935087579476039509226844186925847153756558469685398312257111738589884043186851112\ 8665600706600032113752658739170075719791270419479750876197106832785544800882619058147783920375\ 4350513560058778771089110538830803276161127097058500337123960759479258703446810549091019183032\ 6606693743340123785857769433626489553984697515427005275922270574202933750165699113932336783946\ 7007453490196752231928107982383493218818317845611512421273323777410849770047757098722847568645\ 9581138039666424442888487240882084073565700232842608348338115803945807739865569616086838269678\ 9856756712730220996468541014128476718952598964649510885535486231259083247318386923799366117574\ 5126241175841522936742730137028897602024632758641018341521795717220921497959276831171841034318\ 4093139631868820093624093153384071750518410399488843472784756936398821420083873719449918012014\ 7688412180571992641536136807370776958147189660826555846074621655121121370695295984430364366008\ 0344184540806378696858395710641302301113481848234619218382134954270734528349050966747184349556\ 0303375328510494748849072040264954284175913469357468107173984232558915378300698414902533390053\ 3853153946846411786568418453270138246371905493309924859599998963231260832846137600913206918398\ 1195351975128761221826667122045828645520350915576103402235593941358930367741894291610834376094\ 8747510021943185135202199238910549595889281465505602364419959175291367959566951042645661981160\ 2519060120858629588848823711428998296586027596118721036299646512201151308009097991093558392477\ 8912795347771535421991507020996449447329902794653811542658666113472003540264619386220706105387\ 9470902695817095262992083304640122594671957889229713689286488705442703493779167949819683401400\ 2719712491708219579705199235841062861807660681783580319950004932805645346644544464259919307718\ 4901755853313415434528812136756651876883212999764520716211518024330189373365333481664421663175\ 5292455210325324000560065614099830779964657501209426972386991030316312275696532283041635418399\ 8981137434731118769283016242864812030189451681072593460116244454369177342637799046931942581121\ 3350553071786468362741339902008352704655206386839171906943436576934896830354313819559367462772\ 7762122233965521287336175281003168309074589266764688025471053311865178675812887583929317588669\ 2259423527829867335169897314106834843580180191850935697296788428695939809210099078879005006529\ 8932184510021118522602442423197763712292118491377588660521335363175273726766370672936461120328\ 3544483724860698159219071943154241319827723889974300567419392035912070375402072205212139005086\ 8057136019232074252185823593353052803398461447038700756685927367927447804183171924750793482021\ 9433670226336275314274279138110760608126152705231887577359466211693401090047930606065273806297\ 4077620317571044475376459565599779392265080216612453101384539403639175208290617892347280234776\ 8421947058834451013650975113112023963672004046008872273863400178996679719718361096577618463341\ 8011134004710204532777921448326694379059851782429534846884351002382544925525478993536492644131\ 3638326093246649772307340011255170368604503668423664890336871550302585261046394299787304289327\ 1990555335160493767041831058041946637801770192478902971258897751088024526029758870392116784272\ 7020401332162125785997616070593546460378993309438757406540354350862427998929429394051033989883\ 7697504097937832397906254922631241374083826782051989720201345779090057977417144577131032468740\ 9992347098978754064831572909883411003351204016035282061732665438956161493883397792984569594153\ 6363715009297922675989608021607924267737640091581408036235169250264332836689569684161786895982\ 5857807673865711692335501259049331544896829550320483662494080111708821841047465118861040146287\ 5405263590884243130359030123426158949715640588437642875172697957682648987543675881158501644115\ 3754384599187230511216405938230277048082763016124375243547525581000114278161288896112408279292\ 9336596654941799725367899008149188127743728729379607189662100930839514932712937067952676441350\ 6621188156842370601543413135822384151703489029580324393028138561240556572761578213702743259473\ 4262859957877999876594648271548278554981882976298156705788755896565775303422894022342477061447\ 7229390290148513849058806943866462014348912992414173524907893472149197606289451964273920980074\ 1005952546880507034931840307764943467848950484223348319433056702615381828284139554919183288960\ 7655269726845688253343224209506007418516612423349801446983432607382786588084947757877453825975\ 2493337191176089886905272805889749196140418833362158089610685749996462534562724903248827357284\ 7802169010896620434779249629113463315453808635390079898632680828972643296225780593612864111895\ 2872965328166992021034878331538111528085012620731327135539406924470912212044896007767694946146\ 3607941992527472256798500592780740208124095746876013048038583505113060226726866169835698904214\ 4218599757697200004902016510579509029851567264506665597755635459567018566455875538221046917674\ 3232519326615207401742064785290069057600284892473785894673515378187496197691202871282730537501\ 1033700017644957320624685490704527997622977696693051169800322586424725820185451576414223366171\ 4005189029333400356477647803379071823386558174016900341882496730822101982009816487573961535583\ 9911773345981868781243979530590321308053624014441495929585037359728720546442713348018174267632\ 4946389544329820097748043891809587834877324921350671081530494474720513092494103083372711485062\ 8712473375471057605525422199045244694069264255051828983004335791054084537466799553608268146532\ 5001472062045302494675133142504572136246109662848388882368338661022036228122552164078140834502\ 6293815886285066027490868487927755681662059982779207208183646980021139721422387386519166753871\ 3578186352028004647199373988922654261176811929372330077895630558125132269151320277004509221775\ 8606020689158596595665422792102432407902891028114293997935954620948148278468355841677763208400\ 9327440914680159234617160251137089581317078505959121562731197920493920234880431995614128345512\ 8835502915015285944065386128204083697059321277125819229437797244068943918000312325327643624008\ 7878126915941723367874187203769416236804913081220000160045262532411059897653617381155838027643\ 4428644660158119860108602528331493973336803202514184079921289111958392713644592360972101958356\ 5032773253483689660095994872825646110380696530548175873783675811451553685509120093773160818891\ 2059653897538350954024853171332234066066389815651919208034329556420671232638146155328034251774\ 1984448190782285414769327630954797957822686449915984917504234203729499337225639903806102709754\ 2522339648485203541012139292820362370473872602217592250437167911441684655537464051426288605234\ 6502602089958677404526071428051727398375573351762796125676747255241329840574548027557936477041\ 4443706032056779554166437822599939539634862146928670316257167219310806138795792491917111084908\ 3735722744253340386116930263305438799807052811738196288855157994152986777503981138167376803014\ 8732416416564204154957593231891489031451893963240621268148718973420416992528003367160189811811\ 1097407091090268623469590384724420262123749138899646714626041501848266770013271877278041299017\ 3368203244877523066514180635557658482539660471843123873352798300057703505229369192610236192712\ 7800442244539763483055827137160649577537540931749886533819201100003743173594894746090602847864\ 2844111400822139495666756147412707840450529042113652765107097828493168203545904710930251986127\ 8910138818673544747681647423091893084619164172961680417857587587255648950657774342235623319594\ 4033081158252410684658085400866589844657359545886863254535373943773131520526995050831136775653\ 0324538628930451043187380552474878472840113979651068645603171202547035715354323933987438910652\ 7471326592698721626216491907226876130141432498246947761991634488998930349175393223491643337776\ 3163002112157169339877758027871227040232330728764306801067541679132902161534769429677524473515\ 0205005571479421479255265068739279527579864291802253337648521245205155683599879007916056009627\ 9041947938530711982075707936489890192503643361957978103469061593881789852051668137857835108227\ 9421307276111839376977118247675816351128438108249856935745911840806697112300085907155097865096\ 7982602959201685798793960500088917234473239098177584952492200263227478873068574713012299084648\ 6949271092481247956107042793487429314390209183477529594168098787148384288124829071826013346555\ 8183461236256530728282426158932692144866292994316600907377765155736446627131631167617992259480\ 2085640927812070082189444761518990089621225130603887256178901604982681260172717189970919491497\ 3640900803453639003393587581177572027673891948434763137409521831152334968795409069859556412983\ 1022170884383798885361305381659131111147833326080113095556984380414442356272566003246494287198\ 7583085764772304170399708979779588112277443624134585546595655771159157816757638083872685494140\ 2300988085991249215214053766336591547280343225365127412793592597524536768178713220440792413801\ 4858655451377200575482246348825055892062922564935207766230512677226668138764192637541480733833\ 5242319707235797130955281454897090870946296737882896014542982676911331657544860484399792913809\ 4139181441311338496779253196532310910062581164615302124201523474632256886298915417460394954710\ 3812640901861004618237203645857902479257614956646406102211705777946680631395531404203428858813\ 4460072611012585160665408841145375784962033136555623220630337435684222406404421224018092825369\ 0615398203185964459453838019330556552638324374361962071613722146710703445399533680479437188702\ 3941647711892322385424056812059263109445502178222362338011138895297720168572427395590131880229\ 9669674282776687396261835194828271373132399270192559286353773278974460196090430832564496526643\ 2615400672509749126871948869388122333532560194496563268626596019522270912026154281727940444477\ 7135044722979543860126220968128615582793658440514811853622958907649887774800114197426067687024\ 7399366341970384490918274933771854602805279050559177747467197009433784075976327142789873920241\ 6833674805835021069922060162090064978998119170856003456212721083160141410072943547397855485155\ 4022403802576524834685396761355397641279719852564244927064079646303117098193790293356066980176\ 1043488091169340576172081325327715900938690425199562055852842932978861758353711272586138944217\ 3402099805400889771878759204589844960044411103880614847621022458995383934665088279540584790124\ 0477149889149584417647928794175418507198846309373368870082133492754716694121480475686063486247\ 6720281848787169810683864077679596128832269457022223100979380426947521699920503625675253292852\ 7649772356077226357867087657281941878023016362368778301244876544656307107944043397721959204068\ 4693911913926965504924794668371915188536940886817654690059006073275174773909801704991133893838\ 7945991817842558646271359086834891518329227952849494258226374869224865326249831613017976664458\ 8164425955962731988859041872225519878818712938368855248634905094839459723926969804364093050737\ 5037075279451107233955003655231165920572738972400719877542114548830760689290217879357704297461\ 7432036474473932317319052452533985771520836213285282929147778910111574630493540746670885857181\ 6028874706983154742961632313044732477202810741263738745761876046962370992742225860462566048870\ 7072325627310731969155930119767496326223541916310163406720024154418693256027064530172789156793\ 5655404103723084481105842263607534282057960716967156777327602680222428698959125178313331198132\ 5855781363087913475945457820335689706063080119967798527122206106501640478645536265552632343817\ 7363492777354676268500429161040902350080995351905462269488006181705150395083162251427990752795\ 0753428533313876557708610554807973983397924659314952423915792264903091854116462164426996543114\ 1053421331420648089881868779371591045340393891739153278630715168559728309653330698158325007827\ 4222436142495498965761344283305205403186109127275563785056175914954280320216971799665006008095\ 2718209456695427230572245583805812083103209976982283746517557380253223354550729621197638881766\ 2963688078947488192857594522864828433537962426402109281911794141726419314676166902696225236384\ 5287633359658745914015563344739374857969831777380649666066771019644841293410479955424044325314\ 4315084737145927407608322634670879721357412302215380753325396225354004819605993725222807352482\ 3990985847046340178049524665938002889767399867940105512637485919810928798857449761030121647894\ 3447271429249053145494009542162056285314978672224274713462428116425884631954187132907523783069\ 2381164906909505561180844028482008573950183078892872117714035505696333232189713500410488945518\ 7002978625071425103590021449196515925001893735679983052302827811173678667382461384021117245042\ 1727197495968969055289078400675120605517040782439873039963191106559793416814648610563769067633\ 0911008046340826200314670205983191010996356708871441277436482287686879774085658656307903246917\ 5687661430930256794975566063829030114601323061909972905678545384960475289010611618851433570742\ 6015169506365416516337977019915513790919115292916092731900342805332705782140402751894067041490\ 4469997773515902992700422709993304043520157399149966654028734598974645488044558054704138117175\ 8724804438235810563304670595009357337075708892691532657674973619310752409492521634206632206573\ 0015715945090113676281103183964011616337294802012957236460400951871623180758709664695370467758\ 9542344575477621565817894489671545282924641557712057448007750507443636638333278632114617187343\ 0831026852059911165958195902057674721952496332078065670321100639282807948670753626595146052589\ 0478268545255397446260712672127508576315340237991838171122653053262999342674986566545738015201\ 9804985280467634631813725149370082405569600318532659968717578503820291267480898539533476090772\ 1818763375472652474453997352827788601101099405018078265302840445656487639513140923173608464127\ 8375288338302960046249428731339604594764834434479833167392851268845016507870780491054718794035\ 0963203716200613700106299934198922724754574556558498028309410995783524213370305064337574675433\ 9218328702386974018732746198105548324884696028879066267391045523559957714915140883717654709348\ 2395408662167222488451979709155828207304944832394400232614845607624755758071966929731298342230\ 7673386338607523745986546976335292136389667303669294236053602258951360855103089106167238871640\ 9077793972244662022907785308095151958717616376138794370649012788495728720033223978867672036732\ 4882615202490353538410807049372056197463152237650577951593452967317708955159801277314711472328\ 7103902344157037792268771705976204679165031675797417576216445806792949678402047032069930897939\ 7982240268771031142092997467855111030785213768245700480320555005327254829912717128115321391814\ 2786549095360467346649906477633732024606360785005188850289050447023783191408234309752593654426\ 3355075944043861528606732000662789146564343626586550818024264344321096570812933064530385304565\ 3361950447880767956327994918467710488301531534893233415455765610144259930795251596089073699352\ 1455780217314462436579344212653592885761379799717989229860634301422979123075990140535847010764\ 5888988432639836420880729750663974605497883296512938794109781325526585843811706501958502641773\ 8384003677614103849224537674785015956160490539357769804006353099895890865484042812917601861376\ 7840116957798909487811472473131454886152881061490990165185376577139538162657796880969092629725\ 6183545439701335023766856900639727461687131015759306539178935189349549599521513618153537679150\ 0804043650530913685906987440269688342103105437520859401480887589449221229020474950216870187246\ 1585520265870284882699257331051532044657202648787897816917406757815054138376985219041973819969\ 1838221214273199873774567422428982254118635204874909072908404162385613633017306841203957967046\ 4784498088009823206999252061633901218664860222108095756215429230373441420295162479566273831149\ 1263784843136247637068322837054221179983671467670593412162647992873209002504675329421006870059\ 4181454512231033024374508022721952734207900604216698568194332477951341638897032031756855624638\ 6669242164138217117840510716946343783958620780469851642633322185508407534198322484059246826182\ 1336922640514773814771915465541887965942267972322947243857891959667085000699595425678008015821\ 8097396763649742026275508890651623484504288908245023097480291867170200504465369503634319450070\ 0490984035364323787828506301174545798684842361269328501242481365065731121542203990301312491153\ 8550455990934054810422144169162332910710011301622612322044664527368520031809183775261554152853\ 3129968782142978861135774684435732281462400335975970911357829442954002933554931406933837420475\ 7673844413363656662141540750095214049535132775837362141215366298949416182433222781140965709190\ 8838930131689436586953906442044463834646495205177156294783463329494394704019398367866538716111\ 9850187113839192187193128129466056865674362076435478661160378979188213202846735473481499296738\ 4397238106989457117833359632699278053900755907075279999350538008065503322846629318336876980098\ 1135877995416658660888131889611537789163512453800817411448167763743820351447750444993582406399\ 5258123024295972311468672582411621223625113216141993815409221038795818015215567519304513272095\ 2205182873169095913960145302950799936630637502943979003796843432275302129201109500145962015915\ 1153240616264231369884355194997343865675725073277034526525746718763249346662826675945357738249\ 2181613978902701657754890874948258148864448461214589353015261683252211558194798038169934559544\ 6747330426643278476281397370071732193799506846955516525069554810682911542776035800375373267800\ 1731838539300664530163657254516961773336805712471760377631429212068043932376726136664419977955\ 2743574751559641041118118572681001445991692491212222776349510030526476299071023050607810140496\ 2456636149756442659150104549977113500578483065986299038360960493009764616584693706461126784157\ 1374860301777090634159213529901190279275184984142935565283656498245384390585087278130505161649\ 2252558416013332164562323090393151536725523105889056297475652721305571308670784245512302247255\ 3844367294948704342135230366403272071525909145910737605465546929906298886004700726506267280138\ 7684206179709494783017380672538321603726290621632621729778807150425409140260849326707129537450\ 0823472526176123649012848470618742486059747957728021685757184482630407950412127743137158678696\ 9665370241942873028902262443243952212860780666878820339316685263664250454838355886622222483094\ 1396760403654054869993125587219867827001319555343778654186341526332086411164928223320800138089\ 2252816642478336401116584172029865418983186038487568392422954090729831320373332097791257975604\ 3227478166690231137529904262356496476556789627309238138821102703532432752985812038665565581620\ 8041976553656407372261169375789083335281220355319828606699663335767068934540996241722066457527\ 3022771453173028271171188258284542269573297034776661754941896106477563839446964443361180752656\ 6778073728440018230222361899443734900589807256319231611271840737764787280768842324902174929714\ 4716650264072751331988098131438585120181938862967776419827369765500934159771369985817055073086\ 8777232999326899076453845087461563174746903830565990308848904594165734426323472241310713940995\ 1614274337624354234571787634990317955654844799524191026099785323819795693131479849622596433978\ 3095258620043573230741845563026591129780595886510906347086447220491822047132326273213754900204\ 8322328602889933597071180175731486874190622830167454735784488806272953690140478994705475003526\ 4746555819376796096058582551233642434738693868688681498739454682470843090451675086423671636080\ 8489711827539188063266797944760108271104931713750003351993757893244593183997607749392930953445\ 2001214766011737509284582780882802728940648245078576591262556554412207943455519014677962535132\ 7737545243645110344191932674560272681832869821684286038778512722906202483625056934637989016365\ 4511529559225710187792945985973824232897012868981186971297338549300341181193401256494388126733\ 1193644449199150835665571100172277446020043649603932515823230909381602271060069911313841304453\ 3542515915235267616985906695786043677738238024824673281553535300983302916692223383337798423605\ 0294322624571606680477339870425422853062923702935954408494715694842025399231958033215249553201\ 1052150123460085228468666436792944286867150517673894209843312312734459397330798583754703131838\ 7347240783248651174148788401268643825346009462008708508591128118906379013516853536047953068554\ 8246857559088886061790087264396223198554512097741809861956965753619976516768235535679173127056\ 5690065404393158866896679054692671677831747383247910047393196725345089419587589808890447987485\ 1096407806907134173508107285921554371189687653615785457266816776466947383719035083383833212553\ 1878300825179044878220189432663623212985970370516327847468890013227008489681684298357660560999\ 8653983454278828693863905079389602234217345658296605224320636355973111764476197578030669321021\ 2017767734079933224620134998877724604226716541102618321828600931006478076333664446231443138247\ 6221862072332754840473053829363261176036148136066874284929992582868355431910035542005951194319\ 3513941738897111045903669187502132534406140338303259106632469602840174692937878215360576485573\ 1070304220779949377019162250591797884343231645838512335138999405187947304301621248809146101057\ 8730106538518420598701447965686069443555593970860500422636942961058128083045006147225471809204\ 4748261041762979003975619388082627020349686286660223587140172887903541352943513666314089292276\ 4993614636913885508235343352954378868714845236883465027535363383085256716208885541182437855094\ 2446248627813806125759852561791579987081932633268609961098662270060594647678708091108325792573\ 6173190887673092689092287418848896960999035919034783136358094557457478678081886894628759915469\ 4417575663481993914403253996849995434282610446743737300711065410730014611219016333269131661932\ 3647993719215975191048874133225966553396655405238306192420552950803950229654266615935089157419\ 6748570941267643428231176652068209108612364431197657716596013578673389358243063478097383106805\ 1230447876309507487673613608878419459186411178177879385877102519623628106952343411589760211796\ 8508828387406768201033029475203464603353989050513492540102636009205844216582866386728812319479\ 7298201624528442648598604768729205780150665009214671820149874418977683182022831095622887865937\ 0118076704409862427098662857651055075325964530232101403270460460891528816506992179860097112400\ 3918232075389504127762905958781657082910362656388481822687818754396751374818350972720922013286\ 5112188639007782198038783261916662640279390241267368279113504021414193256586857659585234167173\ 8030129900375073061502159276664817375939822800982286277565375763237342854095450724380941049070\ 7119407521927559683346651454182407824345114929511753633884319381443143718512722461234617922207\ 7342932638448629031295610660627880247741185074776728842034250351498730613517556390605428560563\ 8975773063431628641893421102954939397003887646277689939166688307399758995036925500664598239656\ 2102790041888224640628140720163400256169061087238737037926243249830162731860916964381153667321\ 1291561078600283040526467304579634647102127598167087296919725222303408722411174139009823327612\ 9946446844263537031334735678981305065202812944296266266935879197099031025305780760030672189643\ 5008976089341215507015578862249287436393775145491852259332471621203734364559140060323553597215\ 0097451406581724246194696498138695335235746923098700255971902718677618710434300674485731419269\ 7966815804484760029115910649525029134347186022351592008541211613786552065583257446739245978809\ 6364820554393387353404933666414532089593288020779241558258127329892278325787694620094892181326\ 6734184245669587099070855380241423312420650370678306563989009743566684390785368249622758746587\ 1560022076796040422405672231048236141133083986829823329183188887162876821480830526805450134199\ 5111550394178822657670068568411544089249388802847438153250318158231038154267642599735105213245\ 2988303845112473778376494282329752336734024969470652577580199904190872416332764705078902381439\ 3991003371053441763085654792427530165174381857952417859073904296457210096014469600059674336555\ 2578321409588979439953355854131899149727845874177397182464801237454953424068216641243675319677\ 7000626125510834360634649378483857711910102340127634371738498017427311755800104853217716178473\ 4824582084226876319270914745740622959399857458868805104883716487030080830402109227388763812810\ 5495157448408182747491579486059742913570941772396585139017169397865490888268960819949095571090\ 0707836220067096217670977132897023054091346927964460624464113349776848330352018878387157761559\ 9613213356415060976768388095492258190189666215970011057908086253213817505549317939084792418837\ 1414993762716735628506289800543825133792522416584601648345780403245677807441489890415504356109\ 0829011964850866376525103029878368120474332167407235578460169585551286430245657086220473196362\ 0658213314297163781717447363655293363175422160417861577839397611595412176827431834486665080063\ 0601560289518362304164755993194562331378717907595471683854573084870953068289961093803768299833\ 2035980817639988774192029399444777547010380028245862147526104734910183935408631315634443891748\ 8096681599951356810859134031525723471951867694638687218975494884865310423965206897618057755722\ 0713650724572488520542222874111074281757142760461402400411794349491372246149457651033794838799\ 0612839883252836302126931086781141241555879475782057050313776418821740075241723875284520586119\ 2881749019359358898209200325553542044493811829589393283782679576749250318864218409475942949232\ 5593865186848222901441748708290600490543432378557130820226808276428995428611967534263557549606\ 9889938955548643252887678827139758166536773845774228160271366643303699252948751227212019506256\ 8688087721252625584283078428482155478751492842165876907990558254379515461320861631395524488878\ 8245409441159124271756288504462457578811412706815425779852147779193080009451550794637013516049\ 1906310535480834909327005095149132432191449275574528753268337536328797575432950664448093784343\ 3085063169982701386537392679324134729942672979696690284878021950876995257363765247708304171198\ 6731341842651046834402354097961479989289090087933374457838033382568865761543224589895798981138\ 5891799696026324817682157661976207758404846187751673232111673174686376285704872138831387867091\ 4635140146506455891008640964137048046015716178592439370756615534600199381166880121004061389205\ 1992322716927945711824491648753339942847846558531546718025983479809456445565056199852707432875\ 3475725742762873803056792592954151322869476991839033569443220573067192554725432502388374544954\ 4181821445410533630689099747531531319098754432889458187589129954845622261258781903886405474514\ 4751059998268376827521077114557373743399793887411713981652324545390633570361845175227315759696\ 9297479599023524301938742373226560935379188423670759662967491745248159744356182948710143869778\ 5062985848804480322697085982065511307785504909585003737068309193261554617288908502413731284670\ 8531263977467944305806603479548114749290966667424357952313311465580602822881792679592049198906\ 4304287887774207455633634974981975043488951726108041064053994812153421501554635515147485583499\ 3114220472296288713855373115313925624763073368274476130014739304878486024900387123292492178177\ 7085249878618135386868747800775693093976959229348718890502242663312296946636752802901952549553\ 2313286083576523662096361463930157507980742008202726244411278681785742557355350952027002908591\ 1197936954062807986421391681339299682412911311560378425277498517206058002099341995050856608067\ 0936229988560119952374688051604931600754630780647022831411412450551198674132553956660927980694\ 1470143954861491310265624790372465830912553113750371285592742907039765602200095038053718274026\ 6707779822382521112279096750409831582516585493927010635261359546530390373683934842811239771082\ 1489258754822485043937882633391241044314686070581130928823593906961130876758146593791771793763\ 9827004483893065191399305163250287981546412695248038094103176366568576956600011912523715994794\ 8440889604717690057978253205087560211199581593986359550033723296123449303955667685988492750775\ 4833111362623386108980907806599555949497776272733202877832157845116359946853362437152142019528\ 1226692073339740341853930469673164440355202090600015099426386618884041226101177961616705041538\ 1932877915394996303681988854683851271604024477972778015480616057338813644422250744249674536384\ 3655367577272026179275648315500730257422203086698938127468303716147307049038239871017104700642\ 4425157323137061684126050007819348491607990742937428745782885268984618757432945755184941238589\ 3636360426695935113288548926418567696647097430373122984246343495107101877205124452931779773014\ 0880546534623694698498731299653011690923144313601177196911542845354267193315049738559302814525\ 4088829012700821246098357103343071916632239096968152591741743170116103735445930083108123552076\ 6450307099622639059511527367950905894350946489964948506700470180597113734576035834216911431265\ 2868103622971280555782386014800160165470522858906031068049674329883533643088784372814000397887\ 4695311940113701552442963951516478029569311083438189618382532301542274360219719080012704724069\ 1598523590855346354091604827824770548119429209129561879844143807207788274076812320263173224316\ 8585638647186051618854298345850040600008609368505236697285741666404187793023725784177339202893\ 3554146809219300272752520913379032634248411571379628688462646125146105050803153681773368649991\ 5148028401552447284738700649778987761008713849462049672597790898179947010905671096785947728436\ 4030872009705755197477029636440753994304378034336207982997166745076785983357633915672913903185\ 2336398541885477877945872774274748458037850332874597865970854171578966641625506670173962692069\ 7439281290130880551887252448425428157136645063183730576215295781864594620174197842315008246121\ 1290587069917028976137784424522721582058537703108186214140241219400496058948572831872883187074\ 5316338220010848964922900149839256216448842853679285127502904708371633308172257798129723081903\ 0069333910527263137623641939985873738989210984703712322266330660332087077564611327074669176159\ 7343091701837040219158466172865921864564381142977857269857980684098961092351052095676553195494\ 1818564271820761232423697304520626020119965487550361573734420764425512222440428386952358874237\ 0102828899801480591986779788073101233083666289037288343405914901005273624655199814562237250992\ 7447711083360267706832907674851543695566548204588758413321034827311863796471565222280734463650\ 7967116210465640294497565078109807792518304816978099255474123830274833862325541740566052881785\ 7977230759824189687510178193000467854171046415790510097027077132983886296790096132097614950842\ 6983661084112677098434788101200440287894427544071067341556868518829876298152195219077646409100\ 9263553284313977398301624540908117984056272763695117007472272640843619005874090487533484420643\ 6666335479108284267020528941078205495942099615840404899746052925589612646800148313087232570068\ 2524890300088621489028302041194704293751111795631056798063093650489566786966169210949486264037\ 3099506807912568827161783849698895282351575851708754428443204903504054947125634210760365103716\ 0272407079217120522045000159794376979963209997925207885212937281690324400837042116903194908813\ 9026742085485007719342986133130912329440108292229114395259310567268669331753978547854140743408\ 6483161431434489781146084495271924898914706638861781686827319022426433262301807228862756144218\ 8996580490990995052399033600432311589004177648797329968211930166638495751761802512253798081959\ 0458566608720673869049784934213247397605468758316558749259617857136239762993967992650414837243\ 0046097423401781618529475851171640472276830254514877046921309149401663161827795987197356655078\ 6555169407891223207605963734370742356342993089461963139816412959102030305821367920191009582345\ 9234415479405738477919414657851753192864065445615385841664601476342619861590095043537979265337\ 7116699714278859907001378201167350871314096848923409378280357870887693517401352442819312469509\ 4003924618058387565523983120173873380369196112956552158388700075199566348824479848186494516062\ 9778984332447330382371516270194840957256382407920761559288333290795977290707450739304722950985\ 3253003812667506495661812272428066360729183874574386475395842245242219971339686947126596994668\ 9435565858234434193129496729107174658550726802243716481306257242997059105270990496618845285425\ 5388472350459971521240154972715329319372653045978322396304798953215562832509791640521826888927\ 8256036723276069786338922625685717041962697036743839132106925988523542693838850855247013884031\ 6853505151068301208829776266147235554197678677456941221822136783312252244214735921731101214970\ 9834208993274423882525133687389826176990868625400055580839284389058107572730890929466341395730\ 5512689881012453341129479265728382703098388154979364366283617901721777513337694608438770055850\ 5091640042211257842646029082716489402732812191427843549235241436802225852420946323280663655549\ 9041042631755768666657467655935059912005010271059768417046783507354212314735423815554713477886\ 8903662553871108568419283102841750841848462367513081318908002590802182066298771047848184172413\ 3294353241270382263506358426667722513139426649415087761986886287056110048410723552878285320088\ 4249056285297973257194038760373411663182986520798848284610033044364058317763951020809959878136\ 6039987516104986291362077187218923661349774182167187011889853411940334672966964374675800007944\ 5596668606272791201948267198923108374694890610469808640533381876709205716948664839026765434045\ 4528144861407875578670584549571786638841172728147738817596507256567549558082271135295243422287\ 3162292873266615284332753280601585470382405647683866802465304314168331178681379424213165351084\ 0509502893609322104381090650333422756262425152143344565694710175516664815412851377445225869740\ 6025256749662266454295243312148814980628133484287319514181739070321562944408709447117191178348\ 2919287437101511438473240364472048823840895200337587792583811132200840385540598006924575391710\ 2245895808831896032554105450302685330159471297417066252685081636542129763320411058598771914941\ 6819613177064222562873351855418507248073028864297336814720583695326969541895412290640232848078\ 6251935019891602161547528539316565597166954421743487369393220278517759023706955600342560556973\ 3647397278308873619085684603287389730685136672162339711513901158332751800168815425167522552195\ 5573925057989063985143636252894124375381500070333945450020407225868319664427793475830987138540\ 0449391004853503663607458426095647881624965166442913049631707838074424144027566477604426780489\ 1304384579583406781952237646581448316101101818515020864943148840396412130363072822775434617957\ 7751330794597259562864339783435610441689024044258275689457130778855554434929518224901640482154\ 1433197848540119255601066895419262150592847898719324815053994210002385258500047413083138539558\ 9322144714342940392433873294205203253713587067870446466195111741727586473524642270818040310053\ 5905218027305203726181709939073128028063761835756890686779284526050277403306095552397627978902\ 3192700829822137286285075098360313211530736275970364765346802910049508607334693478461401402887\ 7068553790589839013792412640015535517610931319513583630663020403189212544361786141308282015759\ 1571406295928317338643894037820621501630383118788308372429142752024863370536555013447884564670\ 8442004269320071249943409975188964009456474402452729679796878365289258718411556117910965886695\ 6690847646026376322664884306172379952297938506454032951277488088325388540296697602660252724944\ 0787760389202392247717710885973331770830990175219466014333864829275715297481877860567485325369\ 4949578173471085663644859620748590388464812123925069345309311926550800256384341524677296501611\ 9348394997340592517052474187966692442359209813722956755962471780235073898962214994725625459501\ 0760906516781558123116643227084845529876619215812933117218914560533994540632079978759401119515\ 3395694786931299339853008679779946527433324253633089312678375484888209946374481226456340077247\ 1777635583526350891313719253417439410775135316040956987757288887800758991734596253286194974188\ 8170799823171161324801866979259627406454097266811122401851157942642535512952096610135511900409\ 1107368686027868244061286920085785796045078974067012946022819541788779462989226188039287168926\ 9597604097027064004556723112810453912879424636428579397779086949472844166809190071269798919863\ 0656196691599718963828443212082897796214730364916216797777194276525306270671382266725208053274\ 3893660067949195600095475555136220802439993005332751881144628833553086034981799309017561134194\ 3574731246189572086125818273639906680947683230406839078017320201772459213688892626515424675791\ 7811512936150909092028155588242129674351841970351981503192865986647111199539059099854964834276\ 1676112003695538377413319007237909221412743955617460725767145663640411108028850236469263509768\ 5636765879688945380457996639603724274655947935829877762122623089589302765766720849683296591691\ 3454882595625270141236176405937909975618545443901955540257466852343545641378284017927409996695\ 8247338252694309730747873059116080834099031134216070492754842275532862973649343321636768385283\ 9150949714896873337928524674632131021549545694781580754118220208255318726594072857550267318894\ 0501863070331454605328754584666364994385135073091157990168400235891804791659195147334038972242\ 0800066814627515710060793060407570327275422550747984459068473623342078308386355115844137438691\ 2092853702493224762455269818365112624670531838521948584953490317594631003513761090325389015329\ 0648936280143184848857751535525559378728375566595412981267534717397265549763539188614875749620\ 4793407631690013779096875401915181985524746695747740687852091525583627887404389561499633897242\ 9431068832808334830903440688369352303200547558942520093642994027116480341346130943609676816024\ 7973436966690772872415801150346085731638224299997708679735387763421868567470745551203632381578\ 0056969935690473225821679394175911598758106458294235518526188794804697034983899334140143944480\ 5534626455383345098788723511775373283103860829300921294538960744740009374633612837718966197363\ 2062789082544150245486487798607768764178429227466358582579480009241165188615342824353223671950\ 9373629087499948844815579064138946674892205975888852544869485325001623464758950079550973589173\ 6058063026392742082681514918830685980783112688504984202464196878808863320990229487874397171495\ 9350964982760107779110793983814448200541737380548195188845291942750948138664434498067914172350\ 3255468253339190466728872161969390639397759505887802300762745036358599231765044868005524721959\ 0445670925953809762228004947514693298884775169429002200255010248500386079960355791972911801792\ 9318593454177299828872945751870209021776557344705966625330657986604920980415135641871451108353\ 2076422683513917621033546430098952474920528672901449186460849103759443111113202340023605941906\ 3019128754609039796954671863423701690981129445615089311988557344405500172289422743588031541901\ 4286609541908793975819823241057266331435478220802355817782679838598883800077131587962135628863\ 4593414821289738729080363845997192621384089747012325330308708932197219071894423844089495185463\ 7733649426874821170174749262977747352868396926623161988332118860196063521513377607854936886912\ 1942711386782685774118655486686181323762125150757730466590708650805213672667400954906673236421\ 1298095889505675229375628835210052546795717110870215750578827889125758420606987196379876444062\ 3209122108417027386621384319744521992484062390421001386791190345343185703185813889051082697023\ 8304015633603734168006124284685988580996865861591741347291552468441939911427684492906068636243\ 3143552951719826412965562987637691767380653115170031264436928772925940913492635734475026933535\ 3452525833104228877274077410741046031129237549242364778096054295448503518975568290842771586972\ 0843048624455214474414143940152235990711024541114352352241911100073273125562600486647203075564\ 0513459080822285257878071237474948047291332205313781240452632131011964188298038362456758194416\ 1135451426449990106958170999213441817539853866761051734879516970953856354332845327912839009817\ 2841713295886514014430656956756604695636030028882040979085736352267337397547715742573602436230\ 9815608647034678822720539931356779121831619329153852482141626524173065346937164189611499927890\ 9770387580718910954462183447857885030789472146886883140446083736977982197679157966967734359738\ 9233964175793960482165257117513522227545387173590197234516614943978609911674458107418227404628\ 9394786165861556302409811034916095757891622144230686545234894236214340730713668469850603433764\ 7914861079468194886314228364749884456939783949521377292882630017706461787620089349586642960817\ 3461557601283636628575191617245437917972640637466669129972822325602929971761194000161591554878\ 0331766810736089597725803089115551738979534821580232268478750566861556184771540174668894587755\ 3092874847725444054319873728239387375169819134156825708054181378636705022792258559790330398460\ 0384642242045534839601990475648474048491356283930392305876814704131598747147986740656558636101\ 3672469538476220593856864730361005924018319164793759009744851785567438256454486953527593472937\ 6239550056051904523502708169203774654443807721144847024555878019246626824483692286467714859321\ 6302768820294468208467761776367964582114307012923925090685094678900162254686296092106730078550\ 2337161572220741768222346753493266761951403116852334155611044822550552969932726148995738155087\ 4871185338614801626018288508178567577009136597815057248179622768516387830453340936832674775488\ 2288260288157574018795845919058167892253971737055457122732562950256254898973250550823969214271\ 7304996959867359756823956147988861902313133149418117625627947068069776592964781452111535607497\ 8874737273208205316149095284150830130246302261050091535212036731697010819040150718212417071483\ 2945354986429291740900604003207638450870025112577651062797647948602932341342039218351242070995\ 4610077833113805785668547908676776803072261543184686043458724660095234396063067558980431877468\ 4600678525871190495105997477230193528730977191689111856520398733941010470172910992272112678536\ 9932472247511541076057686494478145461958294082780830430843898068267824779037642199878327301620\ 1159022742525808986796825805654523738384189445115268602288624479189458186190943071012297824448\ 5110664177712998914941699014497482240170820476123758451984455593023642564760494254451762550649\ 0086832726320383616705412754679308577207772886144909167279871631046444370270545599447266973436\ 5664031684666080361877508142445895567702549590136324294701692869980690520845565357584629746405\ 4405842188672550638583841768034074575151675505532838095171168413225359044922838433827117640888\ 9519619402305440830805354121143523402307650845805601570045301641201922130860082322526788216609\ 6713158903867288183732684755430753302815301877471726754466875732957036153044309829337989051300\ 6538753390574205139340861495144155446473093463890904842797882118284017568576955695692908251925\ 9330204667662492791047174708448127117633844651438520801654944997752364548954340772897862912080\ 7053321116817317072854724416282012565033306019627518762431509068707599348084296007555644885734\ 1708051189857118579693410442433808159615574222982234348125513494118778145513877514182861847498\ 1798536640146430352238181974898201671026701086774232744451362569053437022760500630527817640288\ 2682679029355304474605911516224159357045123464818767995779198368035824794189673872197504686446\ 9372144471076864839621879001130722168787969938622407423317563128844394684739924080885504780076\ 1993313530347330361471212811948436941671454443704693387839631725066558816804563459166946193204\ 6436401358882044909622772657180937601202343935289833766876523485955254654651082041026695300487\ 0293594809008230473576589525012113013874666936566541207932293601062025473835112527870194221835\ 8251776664851403047474319800554300488339284228785799029732786070605222372711810488449049391345\ 9838286468630073054423592272876888772582673803253882594842030872750780218852661639376740750564\ 4796136974407232026468573561952753830211469148783182433799756029856599106420951019903268026052\ 6496372647522025138848902887265274249236707330687430814473909080088199857692672608880187217275\ 6662277264390665968365413026638970130976544720861027034493029454391093322099987259960930075335\ 8210298758850587810742869416255240411424165760199956505468930988112316728455816930100377848482\ 4211579131939550490064549637804380427318108197702513344975813444682602917423500798381314005449\ 7122113500234232823875422887907687794448232700808238268706433789511775083404222460540558834075\ 6209606949799970054861276214701435482805025600294308058686307664251023419159872703898312870195\ 5930148763777950587488049921386936515117676668133210675548630328368022531582773708100180576099\ 3618979915126682536766996745757783237734110868812891726625680549995796834461117222495850074777\ 5962182829944993907899286497683625489856944068423814424230268615512099878878597233410942235509\ 0302890953242462883818855035423980987793279590008776998329549776087192586813854656630427540028\ 3158734656749497317489066117387643310365888304451162478334633403806444053802131235519984795748\ 7531222379626904555785230035759607850993094300429250150807167625432445345735256731954259285050\ 4458480350032894085773076815157666491432183960993373435811503872890921354363110997583801223604\ 1317926246156638140807408757482247766409131163697886194656238836376553935501814697683323789851\ 5586477622936257442015126922003202238268616021898886851684374505552604229859159990817289655415\ 8121300401645188636755803431555695504028573210485806130445979561747613138958894367283957552832\ 9126748501106408159668729335465467073353628084491232404232433878058990572609087684282437668926\ 5919287889824322077076733519741449761573042454231262343479714661166425684064672976535599258212\ 1148725852443606991570006219745043825542642852468054527398358660134178827117758759143919513130\ 4033371052487035066457434237055283458284565685736542193456004132106597679379725366550078430912\ 9232048472221073131061257965183235527873535637686165100817895123484110621271133626704007795800\ 9733905059882070271093577772707171846631812387469727460626343251990195325694426246747201212961\ 7318214338137206835829462539022490605570128092710518725177427378414477930031370325735232612510\ 4565898202380154662945287446349915570990363128840817873392804410800371214853837499361422144892\ 1498493585925464110758083916009852497830360433015819165639657322278290711946826669159247942710\ 3625146086550081035429801005735057617321469312158705411348402839661751468684779002716714033098\ 0566366256757513408124989755803643939895737147354006581707442221528673030108776550813853707783\ 1405489056276392510145314890279948853448880264624072250613535576547424197342429507922598191147\ 6983108122845516592309484198769708377350152759182027473719690620588011118924883644427370117343\ 2782812799104860832517443156843315285142304592334679501798155734049769484157815913262217067897\ 4208822079271625703613955860716614739957446338694297217435605860924837849657830801493568932760\ 9318367772551871548224149579664786543952543043383958948272377201239332996041436640500417199718\ 2154896417702965505544887061118621555442476616981703638721018831865075624588281718758272146824\ 0733378513641480052924781617835884034774706378959254209793471003139421027522923114336050404709\ 8269950270605099533625225110516365674936037052968257633337630226239787787250383928500059338498\ 4471867354743908649022302207177890753948084358015946927277852642519230821584573824256672839676\ 8281195240348094795494086820429581038649475093764661716555904569115856808580870252509573994378\ 7522226051032062090281014055589098700556586142776018683421625227387692410739118169019692331123\ 9419780564948066689338333231861906305409149708768158950880867001596166260532254561106180033787\ 4417085649210044496580241223087771032303537786888745653696694006104670384159564869039558745835\ 5507942399768770104831203830576482273612282237431010790533562791438477686310114545934826767199\ 1774726085671223718044805011456331805187330277426321889267005912386811329571221113071196137550\ 0360825562163324643542629629950560271262254396137269384663591615280637283743417606104694776260\ 7778214329135502287081546623846767561626500821662279632622013858473563982568007898558578292748\ 1312862194797407443321888463230264289461164279147696434907272420748184543592109243542029978154\ 3351731326098900422568388872625041033310784874395525501998395931892012199150656912214489550125\ 6954563643503328186839526702327778035039731817479812376076236275099624647682547978695132419038\ 2261350239395986734909895944898803439261241863066948760030527761453271083064809026191636756683\ 9301520598094028977755697584067854210033517907386583768396066595064962545552793209167824077535\ 1037070635053332678334641723903439880418878443828258181061281287142450192143358733458617730018\ 1097004166895450304555987121285831343445133979830345669500485553541513015181760345081242547902\ 2923215776618108780905101304068658838472180424314194131858266803390778940391487016302409661424\ 8159718739442964500462925860013678736389465313988904957999097308854915936842822674457183764059\ 0610157904809600910402929072401036340333838753932363214287698039311230763963266051728020379422\ 0793129688323177728761231437979107112262520468616860993953375043655072951464665214779576950433\ 2794183908328747231289652486649935335495112505569011070339669402268250362915021438895966220631\ 4067807131978420835255968722003992479803039619348583939831922736817428165805234358626235454049\ 6707926980819274050798939016614627839558833718678621763557599414870191607338477385458438275641\ 9384845393765870735570178604360782816818651928781868540002691296476251319799814999240743537284\ 2107354386733260708717012500251453130984561323676978888913362481621650191636990016495148632066\ 0713565269244304755209676362949147278499970748599487783674034461016119366231922958595293781426\ 8513959892420996103393623281089998859321010522115808133352274241943800365570461473330633223438\ 9553586462721204938753139217903757716747127251593656649970111420023524653612402894370949087610\ 8487642647336383399317583666192486851783705253512022549358734781444970680708408348655936343927\ 6680156473110692738861594222795445407054351143455321946938022569915334031048575477042692826743\ 7921270132141372617190157886980855741072992068796987458007595457078604414851910626504255860776\ 3804797211262201720672187028684237512902006670516035225702601335958144631840100840361238488982\ 7731897990925133813893528323545291875213722757735536750914271450569304781313046216317279669623\ 0910917450438603436662167799123964812906884187724559400021190914259887354908740889812243115798\ 2353289113691348571238399678548447160985545354301991856306331738025171410084269137778809056565\ 8043991810978742315663074035735536138451887318106192314679833737814458565492133835735010422039\ 7962700427128356230311758503707317608374945343648366433181733960744026861751020237024924303511\ 9222015637184992108263116624751205624981255028294148352130975424583311763843545542426735085513\ 0168544705207445407087201595527109733695433156694258548536650208377975233762900080383886585971\ 7212150244724173318372124605814851803832409881347623684796354281708688233722765817535591703322\ 4978479264973755241079064828828129643807439760198624796687411820034927857679632521554838323857\ 6147698244485412873683109450240760538561110591540476284065176423226748189317420734027535089366\ 1791087363903918681567381021318463825729243772059144428565916239072961836772091460930622053060\ 3329835668142915471182379452231819180114516699883263949125453952871579313023129462159420769813\ 7286652687455522665668562822706313590011180927151513555544106059230035195257718018838455543755\ 5982672227419838878242796057328325759899082007838793234271657928419744640093497220195871266048\ 4890803989574161712666202723445994915689697506616864831567958547331631010051488523529588164812\ 5004193795198507182716696114576669313299470923294949015037737923874404818395381443663283980215\ 9485109240868519505260229513323782095256331759949594018161587251596140789971472606610308090848\ 6967603709347181049673564010686257868270331015615216290309334172373071124515681205249619342229\ 8310985456857061261075056471964214404333734116438891469934031843405322088372550804731410270981\ 1905044868360595595051681191827182954522816506134784986613710268817134097603069174387237582025\ 7740037746217740853140902401753368109995875576895496287425448105360837186607267985020193196861\ 5154038473882890378150768776061344253676646001434848812069344013354140331666457527490866053463\ 6517578526963761609203060494957802196775438006327865744064351518862497837373561178697688417730\ 2815035582814671458296834231181633259819363033097031206668847227729465970810871640341630996176\ 7406925359850282464293705991972277417251746456968860550833656512852261754641846659054258722513\ 5749192955551574669442606101844673671123306984839618526870562207870073656355616583888718402695\ 0590565711160142121078607902659652271464743187737902204942214009052937554751629611812980882049\ 8604373876809161385171315505241600326080392462068454508144238757408405530109735162798875193653\ 8967255060574722884175572056645247037004188822857258949191418537791026692768966829197722173409\ 6761571513732806873614683113679573359277899968485928444259725998413480429646638277628918828844\ 3486034100670713546278477741259077313057235102738020735572250817657424209427415598040077015169\ 0616981906023649270713965416397111608193509117666862912006825948669208709493431528109048695465\ 8698868716470568257557191695996071498668202394382503164310895564302015549846733534962313145289\ 4151519202069772127469229889108596566629129549662197755922525336296603504221566821453755064614\ 0625676802928093636722749054122445474544819003138411801831042442539098942579056011954624930719\ 9538743652576731537675312839547137402624290437901940491033526686769689954575899412063741317164\ 7115417745700026383870902477729447013781281197336210707077918969217595235149708840424414964824\ 2399081188977165970203423347178218042225026806185144737666248302155212207940878992854717074902\ 3084898523280680279027999445733437687921535259321912243892488158050691807811679996193948040686\ 1209889866273314950974549271643631902413463019075688559545773788914657219713220026479479904221\ 2379997953097211187922830993645517756452133954012371703373842350231583351625587552028455220166\ 1998589263816232512934461697555412531124184001314969937133086537442474678454181027841605942458\ 3811034295298991746609816552517338712032296463203993500964542239412981847732667559931451590549\ 7673163077718232383233655872278172121771913609736311060298303112569100285220187717042517133453\ 1640422640272994356151529490910525471503222812362742044960487537499302712584629848105183616558\ 4409448141390006986230221239268152609119078664011666006106489659988492227616911360296740805424\ 9223689769031952226921612942473838683528440618219327151209741576504336975284216881834363347946\ 4505194292094581467761364801003422219234520875208538399026661285996227585227728246196914023293\ 0146989896887731417281129246620612525798485844439158678913497624443773608771411014236656621519\ 1605561992516516127815784939475826540848150504627231344835831812977464063625417721404073158675\ 7708500212245809739377340389987395843224202123961568284273330192745965975669501997230349768512\ 6729066065196077925949830532317751258575104969139595255212215628725332789440521527575455539554\ 1983081734234420775884332513884307660311189429896114803784057122716347993534242324673281556817\ 0622993703103950396784239765507682230845312793653458482429364737038042323908550668296084671088\ 5634617961436689989878141913497800030947851309738808536254552465773979576511822491375529079695\ 6395885978804841817303832907998997280419652837879028884727454466314525438442264401748670095842\ 8857264092526856086348964216752997022775938788324825215371839956505132981583688984609456096244\ 0347594290411306631543593183077087828580545743469591012265229715453562674954131692303409562546\ 2539119873042248421022218016157939048745438298525172484438641293815624494504595175906042449886\ 6445990719884479904087188202515126107748231000926176039635005028351515006148757832746950644371\ 4351390290563880456929895718459432740192124977827445352916520809336344840061545400005779789411\ 3075981121666766469654650787396456873434761265394184320579862623155388291762585342940834231621\ 9412132435130912927125776406592171083644903273715172176188068020336786044720692082538505375701\ 6835798619303171048030217740086866669262643974124613977541696945713878700798211199549076263087\ 9463280405622252190726382444419951038139483251082228838701470479559688967945667557712738701303\ 9339758537452157196833184725583282008222654203732489782474707027736889608977418952718345580901\ 8869936784132547433820518610901298344791796323349608368109542284240196131965921073069455499695\ 4580684164590280183538139327716709724955646040575264440297277220911945848399572371649446507661\ 3040800689993766264836596699662043397192319495529218089482905808921150054251593040032946363169\ 9066949595171106376261792761601602443581402647004202564066283071146342800740259789452790704312\ 3155703790683206856867496606685517902043883730581330543951328002408984386798260211349946478672\ 2995105009276170462550894440483844747583003172283455212153898848290847910201958488960160909756\ 3053812330651137666179182775923094834272795585052253224559093820119132776062859316977058857038\ 5597041609486395709218482977994750420215487654284794668061141300082762246072081626653283147434\ 2083400386499531092236665587682425834925546094396176846727063690868162641083239226639020102319\ 2318782150220455108333241176550722605362098678898572029620591938124566203711220799045304008750\ 4059088512459701252913354607763371603257471657207194785494028866345081280419692995149421928987\ 2984976264962858787565626997277956811672645671215392560962535911950794622297415637258735695379\ 2006937114421907808544300266507261389572763957635386179010846397879007651269841289723640710630\ 1588418933877463479816101317772863466731427212640481622691554595766751967961417405614276380237\ 1449854125292619914148554314827955699096693274213840367763234190778750570946871150514512021863\ 7019310782149696470169670770061256467200027551055364275504707901765599160324808913450760541462\ 1321878662779158098573283380856583673072157949139981903874462485739855184181483924676233322747\ 5633127440635897918747553851627549210346666141078404477867896528873895339372079872433518214959\ 4960361282403299358645625226915275942312972554433201080575891462547530116676542421401967797617\ 5181154912864898222152282806774712989941686915996376944757746050466440355485407522727069893452\ 9874325719899277374358679426229719320916734095490161843792356997788284966035023927218761288312\ 2611686617707748045853065550436032685468992947592812751170891013890966512970044366603628514042\ 6460960142047897069884352855036381744937265348492971634988554873469960922732763470438060078332\ 7519571536660054445605836979184039281134021898849980070311972773913816339922625995300228821196\ 2945001790717344466440253905135941065750060505716418841706890249179699754739746042468810548108\ 9463480134196996212423234243705252528605297328621065325225757849885586962370777078834260400056\ 5084295645391847124540635443553666238023651741688944200238152688675671682236853730676889595025\ 6092837496460916577816450821113494381648420767279503925507089728407573920826513081521260014845\ 0785584942481542765646800707854053302133902342678057476697215684637312553429604392826482068551\ 8916847738915882903451335896905118261689054745411095147785887861218106583367922040370957720295\ 7815388757933408218907418788935791986535441163506055755516456960690894867629722961970287255875\ 9671828867737525433426192683096176090969033846621509752321886118513585227963794788543464137908\ 8537818847547493485493704559884819584170543763020317673669042719131470948909695448452341022253\ 0036899079704749293783467673361222190274012218767030771974429744394731334561386658891749830628\ 1082239166712459255787607189978280294793207946719985916434718406609245359469448894503408542182\ 5665256296181705534342185310243847715929452410736708558407865176944902637065083078888158742947\ 5851310270061818284711739557553902890175674996857024105277450960612034214851291660450324549878\ 4581942021022802256209914125451324623570112997483380223822462110103398126588669767213055678744\ 7282489723023294693783529907663136025909531450358007432420695404956568105764798600421041865785\ 3872712492525286941034508161889132167827796979254418781408712200442892273329143599656364165022\ 5378096415273672809447469022192213291915247930247066053862792050536208517981055338436367581879\ 8862911704949359061574839082145289720701845440769509431370889459595566698626617415888187879307\ 0734713736356506427725705228096515568748183818556627385553038951612675253679299594253518056897\ 8644094980075678732523939338244722314992294563388118379978333968570880069380031765129801354178\ 1785262568801847269969420664664784825005650876160625982398950733830654014961657366744578836113\ 5847891540697210214192232876747073002154110105089545095574135764109091532285339430754179597855\ 0348950548195601693927009399044810648151749216251410654596487937407532268693126798891607577716\ 3158141029056134575022139625152217560684739805524940809141583016479437549937511193900311672745\ 4049461471202003926669325820465823166842820544401166542600173201927636292089759388108286077282\ 0870493692731777858931731652452818971946920335762575800520186594318688938485989850514769340999\ 7625426715580985698904664174159430966726390485459619841288059782769921280564713008229033021990\ 5763080605969202151221935142483115060802375953737041273161944153870012245249383827729055974107\ 3177829367136499931571968402390575631667454804688644500626771047853834343782268972534694758664\ 9240474365083400734942984873528648722412952371592151671817302198638970442861305309613983287443\ 1847981563002445278819963549613534729226759157601013046367247819947700274195161845554024534273\ 2721789037138066344933177038090835574335308121878179002725289686432206042710904526144678876272\ 9602015515914460761714248979059637132568820537487979665284698802657700126570609271123452455236\ 2088241941193416542964327008122088181355367977637237071112942623340117012890335797646539747693\ 4868622846679284346563119807178856284760867859708394055048137988612812060005287921286648044766\ 4527956984131280723486088069712910548663720898301361154935075190661066573564350820630315092436\ 7064325415469416126790854882129196828701633359722195571863768881944589640598960961941531434451\ 2939339290972399676963194598957491875775878716218089407799227209656532219452755254613747575293\ 2267614385165009175556628241791089192581152637613108701735234885399274102702269731991825446767\ 8185866384520360650616018984454188775475202467031618045354545817083602774094422703970839557826\ 5729664996947605123502212680926163728696641724906147946330972934304471559577413374715325545952\ 8800673382038372225234021563868396957020322156455485918069278237358992596543585195184134945261\ 9425266001807496697854548367906155137018800393090504592594790851166486712180223949570859088681\ 6580720701752956121956079854521646529334606071998945929354106755237387368006573432482419250447\ 4162775563330195660401861903389390593727713321306481601128443645545192373897491872680944756482\ 5331250150205465379725814104283307489080103500145552383900518203357256817382584842292151110160\ 2844918596927868590410879670990421124123622219366030097304042384005296724341465781415327070175\ 1684313680583436750245732594591192512063418235359077501063404241040191532768058356356772016692\ 6313122875691995271382633643957830486155147292049371515462491342986346133316165070251206463588\ 2543429830170935844301659946719601639190197379961017634033577813447661917008957538338727688915\ 1330524769917105009866090210436294943045738805777966733072352031719521522555274216115633571417\ 3368547389120049310923770832711646375527744028463254753247971092839126971587767865993442442708\ 7646140119843781096653318121398634925936637758855419383628204143334372211766932325017755686408\ 3324095503930886406586489520567730547755672555075315353063067569015333002256289712873507982178\ 6207631017680770898434554698584001368244811264333956499475981887201745963938364394725036168602\ 4674483945504842513184770606816169402610272016158430291797667839748492627651246500242580355606\ 3771178601448086757480213358119113370164762123877484991970555809441370742176749959618467134789\ 7590689285463256044787241425241717258819017922168207165059262236955990865305741795109402049417\ 4556845159645652160131114493692190252476065581463508509534737699772634298097068044482332378845\ 3203881927871537073201862968843236510849162107400602724810487686919620200212979118806786837671\ 6525376026795666047679395234631384473650215122803919642122856753335624971936441804899161755318\ 1808874143252656957280808694427796956232652303343191409691261257277578132833415480838557392561\ 6991691897475725538811358886367537324130778458276336594505215154561987759365731683891349997623\ 9365044122408250544720009114343859741997359199633588816167975678510723901912096519083313335933\ 8445810837825920096127564687896128438190407339365375720232891138576757789817681881181861089712\ 9027916867227747522010317135277311480570914655805402957261325504052063576018513534747336843688\ 2121792630188462392031743257773074047017104960602256538853591158601895022883848406455349546159\ 6693543355236835333948673610066639127556198714477029668460214346167578930826187576076605400800\ 9405404502544414919116903293087151262080728464590083261772938760822502714075428820453558114637\ 2038788788117533517182319067102837614587182790327143004905904368892110783047372690321618314083\ 6489057777011395574709169046746839774224016251858639654028094506679375345930081660884214178009\ 0784366002900884113303620749343537965426708526679223233187826908327818771266183468601570067271\ 6641205541989313407116884828385290768130111993617894535547481289158144288668741129409822321880\ 8538892199440220731275531917479594778965199894444816614142196878793097746980791923863151828040\ 1491363526788311033538805858008776544628241993872866533396951488761012170238301196741318244534\ 1239432917123311655425001946466838196033510237431247620112308274100068645298027976629893080788\ 0709618634165186546748988624837918768396823887013817111260002720357831555471158771441763266990\ 9802566658949567175656909765117589243303234229084828129444665948750114484289361781931125041133\ 0145244234911292305944338807304483905102994624795273013762048183771955922215347351730731333405\ 9076540123035207777116011936346073348361362814924679506755749586562173261551395220267151039096\ 6190228307634789493072902383332930645494574020158223394210291637676073959163368823685677260875\ 8413302006959928920137585302074252310485516869917050992640628992901949710852580810025689671685\ 5540174313703397539619030005395154827525630493405156922783238450572194121632778657626505815425\ 0863824677880488712196786000634700940767546634917394296281794926864855038271802249953047658406\ 0850054645145895536799683886979934976805382809777877548155335792156851558876912694864707064865\ 0657865632892432900696252468597553810063984332794995902547870170031919722728396813529929539546\ 4264900652470424513029231161510113470688496180330303430170665316053166833678294920636193747978\ 9410979021108997594675030922190258734365415037852332699026738931925646093833501506316989926239\ 6680478011350902786692292649376703052038408362703138785902866016701686191983925689929408077377\ 7155188615509286740540726496116494320583833218037964979183232929362312674114405148399753371582\ 1435343706735544301859703292378090204720568938284786332916942348236058092256220484190424948874\ 8442255147592547809538718474877368493919243866267899518966158269775137618772130267647352302796\ 3300540473340895851325370116762347090712323689006771405113735411864650799415814926294700506837\ 9071064410757289843201060042467646746122900367447570683517760918907963380903283082903160869262\ 0799627455731528087904628392882573211033145812639221095674838259570004764474643324371911379822\ 4095856971806648737609666909090241868044633832047613791299288556060441005825158943183005798733\ 1719415044921766766345839657953849448999863501515075485704848992457927170183941143594249695040\ 1554653615788150676883086925282681737675227183011679541836680991874175860334340090109403794432\ 5753476800615327703398980348094005193088221664361668360915147505213222438051707163933897771770\ 3812651634243556604220160885796845765833820142000876787880602498253486612023351604509758596546\ 8828622555188244196688367807931412683650445839735729976584353642815244973107982737389555572123\ 3972017319158104659107093863155009178125249080352377836685074437088606674728536679774918014548\ 4636134593910080680602898692295811718215979598137100595311268325153894848627567516555426086249\ 5836169117340652872819092508183105949329358135639401750716384039434531052939028785954398164610\ 7432977783059774555152973375730281736568098760773187419782689372833193394065433504128317240785\ 7034235767128796310832296565787914461239777568383736817029572546477017619918696999892013490260\ 4943446036157470247387208927865359365787270147633949663709056103335710446669760051531283015106\ 8421822172603915974863774970605643426413234176627616638405529998330768268541119834011902001019\ 0307236052344873016529597533471129121520267746713246211576748381789983613693026887263321575409\ 3207727134263982071028931601521642906175520981875098952373936355972229079358070457347068385450\ 3849910489708161251980719764115518488218526205788959563753397943700672582897391848405169672159\ 3634312064223994051035735739879333055884553364322299253991732036096044261628484038927126213115\ 2436150947923087077613352040789534117376340152534437229879176882365587093292106552586292120281\ 7169836160212241389573084124475359245545429367921612346020844210349607549498209465131641236562\ 0314463403452844635398780322672090425149746187645857639572462547734628483516854662652972441197\ 2962993642614054867573931724634358610502867130938334821007138818021366491512945345054001416198\ 7834691063885800575406221360728018708278145754014705854724817693995488035831332533600476364935\ 3568523686780202023379651153204217199382721073894881428355107014006128278556851843295408454243\ 4126617649859274674186631843935177011489001477513980827338028732868053894767697839262600957620\ 6948542059912273624579526810931724875665856147867155467646213813020920457281661165199288336024\ 1773410198223097287092513858947140853731869494886578290703763367337105898978244061116774471494\ 0903354303008217360179921682539986469125581304275470040548079278540184816835980514626235923189\ 6800529877168364470038952576287654802542084951800831676273236638749933817623654388836269530954\ 2432416951154504918391879190603727446440352871545277761044395459691935874023118448969117525132\ 7115022981192453960186912382450610197849577953191574847306856449901351605671955499402416310853\ 1131281234766766774237411525577547289614252734535121956531577529746988214510331526213202397321\ 1629989473298004894339291574536986333409447156287271063962869477176087400356479941401688082468\ 1637728332354227590242899079942411578208682635040714945811777075869268347329590377852893411138\ 3667902941046692969778937886403930894167098113183055630913394990408472065492573953808169849835\ 4520197892748228948000265141338702262585088462729788047216130839479550025912812505378443922202\ 0052816283612015521884981713394017080563710522470963949843086408187036375129078127078044532868\ 1755499918007508698658757391469503219030129971571508534001835968472698248157616230565948967149\ 8133354440726263894639839331128205167923672014676324137133509092077720164121649932146536666596\ 8594833454427402236774665567661752174957093948121333500227304409556813510492963344213310439517\ 6309197446056327488527807993079054139435414067498946048231634548169991240044129560635559042215\ 2877956959332636712430747378024052485741530488654193821960064094973131050678111089694948267370\ 6716300389958860637373890900587394014381578871869373040445640715144802921919266324217302160615\ 7125126271361408442442308096894083436717497836831669106325823531665486489607989195651776654671\ 4817775387988444163791223590304902071387427741999219603597449158370619150505355165888119171344\ 6474923546158362353837096077852534988653363709953465858686776774431772969470765199362695381138\ 6807211483249164127723893102451091382980212498848143391876181675847481962964716657090762722543\ 4181025020258578115057974134248636599891105515008118362113513499276539963427476671692101363689\ 0608053066131749620413748334667502314765225078480440137844466926922397217546973847369969512621\ 0313902293917240033451304471419042366474232565323320382050618576889533123050513095408170471539\ 7596627027971170920210783926116488881567743077339646801745170703391109184644555628075982563859\ 3937937441935530999115042534857253958202444954898118758705387351924749366614442324655352420202\ 5928444620922627804509686926902419655997095667180237490775748270008912008555339437778761769381\ 3381804578040494913186756659034753832253260567215039301097783197242623347325462714944845361740\ 6955844031435851833429643276495352185270920651514352128983616753771860950406680730563538009400\ 3797695084843830933566640697545035496274118508873040622965863462665984336426323492859881102598\ 7915748139600822475457884087672531219615318675625912656793324212543629640176839986391394479559\ 2618107429615462015911767403348106574617358391668714109348648830410056402116846364508041365907\ 1022736400918208127171733054233403070668554519429588115515126030717401243972641722666565714992\ 0405450627060037224268238581869679825453589053863746043288512276008315248917729262691025033803\ 9867933337700760799981566024253516511956458154392939603524414705546010606857022403786395382276\ 7149995135779846142041748421788901989614919608724465493931033027384623653145940529810079089965\ 0774274473052668698118216765028913187078843696743586343485190689392539853857891191174828419219\ 8277820132706779398950439342333785089447393611750844957903096721464054271606573691307857341596\ 1502081792709913766918915678599489428479822411179657363040520349560786098368719129525551918972\ 1723588637294013046000389881523727224981181850611112257876978559176756924305227045554364932988\ 5614389148957282937068708924236336530358197507044910249212869501736477762471338073522209563869\ 4117314963793900264212468283061405598561040727828063351351203880105028824070820367662038169689\ 4752915085397960721759773020872865463644932807864747275049541308511730865644090107485725879032\ 7075809313297017062405682684841671106764256144420724002503760157816652927733260533691896825825\ 8985426337759354735260168915172919900692506856909597226331338908066069464446229465717430052020\ 7541751784649178596745736676195717575734815687283855964036379958358073688889005983879797204184\ 4793893358400342063551475272266292885386232665879530739595348204319888398265284562995283156595\ 3833672222264136813983502669387096260785503212895545314325350428103049415104380569768617096107\ 0138348417006275418648418426713389436990923928063037376368714903032005117786457344785348079978\ 7635367631708034971827524762139581097779926866006099919547151136601540205294342683205449777782\ 9329065415496454259242664045797633861419208949841966890035386434047628810721799782892826862027\ 5817521468507809746178263880498999842441747509226756259968678927485802488106890065296715926499\ 3522050366556332163019951196167861728434692975964927447318292109764918810982888388275655060870\ 2130058919397838210889665541875094956431553253292756404597161737899475065107349222395782870155\ 9559657094016421303507652979136800650905595033968385599907751792888597510114541943822265219659\ 0309300696109000099408849775814744463137664368930927638855820326480503482808503499624001415702\ 8225276816670693465873918810609298278276549242579208358599020836350089685275556648597897263531\ 5402088402241420852391740962007928627840303117189660108718172248874988817994060434403125550796\ 5460220782802236151100365276355487638906589617567405079847142264727715951513275148073117674774\ 9097194949437161997022969723790557807035733538079511574078790007764059258248995153616262418245\ 6842036289226236983358160379325116649737746329135260933568618922961612122514836308237735390604\ 6793651210222512282081114131357078080590419252259811492259197206236164466697764987179756650355\ 9056616919895774227817660047007379129529832710446057416135285915046510688063287869879612560063\ 2558547702457519096153709539917451144426910656629791998421519443297551287712754018122850287905\ 6405867309010472762318346095333936139430514863756443632773538852589959844147884171556222243586\ 5290425831517078398609280550746004897165672221324473406834150992641270060637631720693690722554\ 5762856126348680074936984252264144911051497619671253401801375616311133709612339517866936699623\ 7350387096012534936525709461233289491847577141096330680614559348044357554354942775176517107988\ 7153672085392829896139979484564439906220322453013434209527983025296374733958734404054848107140\ 2708137160987670363243707245945059825387387153302632163092295908069475729916052432997958232711\ 6654654074816120073825095867970276361918863967650316555837379992156845947449960391984647116235\ 7346092307023609195179500557621761307294665293814710362671772354324835235571525891644718207298\ 0914201620856816469619598410855103925638930421841224091440978601882681693431322468109723201100\ 6407428262188288957147049420418562464036627697176030391245335633122197913828568095846855821080\ 6539785984692408950289075600469305576160283222624281552039544355065598093642572297309269247677\ 0320913466146654573857028725187517306550957303516196228860266461976461358883479644099277609548\ 1573157190129017412161237918240327500851329518825979839946346435346125625876901967451257956523\ 3695287249423312936527439460156783537155944044221123904073511969586888299603584354885782320846\ 2900534403615673127939440504857180752294123919460277150175552192049667628305619688667627246426\ 3941333775628574125921357655271120330675466360546231332784688408491541513512880234131538641848\ 1253698541579397563148236152115121223564047209289750810270981731759546246459605460077902501606\ 3752617886346415451526561239240458687261183146656623944076085283431224974387079455653269650398\ 0104743637333540537776457161518116857296049075724877315149848708678325029422140906180132503479\ 5606935264142810211406222322327328903701510046716784304190269483272399570150753460972475318365\ 4531403019116660224741335978149278388977640802198046668484938203907237890566625943112483300034\ 9968390231445767305048770955632826603089323972555045536668564958436273918887501771685346956870\ 9866118605137964939566562314499983947120490985336055402575207402008557314365355760662988896440\ 9756726816841261088154335088520997104506834734880930808416787774980831433503972693654270273322\ 0323014507055437532605758109692053787724663892551416101017703670360827611490201653867646052573\ 5821295606855125682465650705304523034135523526578883064936323377759070761410046424755836816899\ 2040988225316427429983217941576215401230979289720049059853320713123921710368289305328472162537\ 0658854962655163335222376880820688731868669213483682609361372381160164987506482424994827213800\ 0618958809599410768673122240741679829775544625349394384979839062970320330040042338354589618782\ 8916088299477998113107232593206192377152789427705066160038875349800044992065014930899433465953\ 3763456460074199331343427856633626214006847717746976970213422921207848355509635861808447934850\ 2582755440681587726082117542397193691599988092190599588548841278883381832078210320903090818769\ 8480606826350810580700011828806826911998019118040854644074228924198890052711089832998010253003\ 3780101009297960999372117594520148312623757912400460137837877741716145930651707608943323223272\ 1704231845618510814523536840795499506758051011265059320502239178108759798879942213615649640686\ 8787181127373980101278745440878737072062943643272694785995765234085547249052589457351132569021\ 3101295268150255340821158347389235759850760327883243789349321934342365544038221210952643415064\ 5865004600946725382751542029266960124700273670106635117549217298788238315659199531839758353456\ 0378810967948115828793121113839475225918344988610832538222266743741707570550733069936739482218\ 9860213987534844138782301852215644704079411707865928746274422600919160222968271592107974155705\ 8142229434062141143919248412774735124357905953483534272705591861285911755780230399753571264955\ 7555756485813714054452192175552107327130135847558152634218610411167585966710177809735904998731\ 1930777977777800923866079452041446565572129061543653170591053357782917901476318310453101069770\ 0791399802957323982013278585610119535998520636897327632901581723362558015794005334082752643517\ 3565355892294490983503909167132054337608891342420118012738770734403622729999134675227511589034\ 0794173609730407414051529058828751137221981244480071490579601177216226063422812329923121943301\ 8241371158206118940823980304939822060974943867784590149334030248837856827097441855806896795982\ 1314436594405728636697552736605498368770434054230044615589923793515381644736861537101627110292\ 8745155937565482060874261041386492765420013567061391392464185738816882273925985269079752141697\ 7544033454132353983905506318831081584673689336636587520807530757041159045167757640832060085320\ 8155421965173598813500372067448243759097262529113032139052905288326272339534308355640937990866\ 0832863484078935540379141387592716178235197446745155082402862725836586546476809932609083204449\ 4887574110490659353926177364992988225742327349946736416303719565385099433939997477827467203261\ 9389172357773781994759915907586630500380157292885712604466643500682033676600204905163868871602\ 8933658309417878885634537634067075675553299466783660206966772763469476439887292715117096018752\ 8202565848253992900201882429031845444619087580632353079643976866561608372340580311730367291434\ 3905519331901261704820003779713208920674461568585528144607270251138575734620832297713100279295\ 6125607621630756412640984152201327957755933360633565486966375542761810894307480928785134015015\ 1650366652711683687671262926438500946162998180232609236235132949251586802784644664154575063951\ 4546622217880760966625358998929485894690373062824871333704353861463392560546653723367356567866\ 1958621108387785604292238630290564073060487413004632233062924853770168356787598417934726256234\ 7208788898861605739726755693099222821194430052442302531958741271078422001084691932856676531383\ 5142691303959358755883863487027380604296978673224651355781086471968866197539190890451679457211\ 0499017365987081101174657782684404032653388963292370623210605556970298520917293978739837239333\ 8300146746686758898279818030209318822481230411687340956511602937409981386991094362733630367348\ 3898256345302329713970355275526470152083659758915506680008558004642329978373187185108476714760\ 4425465767056402360356401392568486609823675135811920264863904682493274590148739701696997862550\ 2113387259624501540474072779067986346596694808503562658785276206760406016111009577973998645903\ 3643915539425977512695076248415413452972726618556652480452792987113171672143324880752988915575\ 7791619351300484894167803616133059089070684359002230983412990041070558825469269703056663674888\ 1535369008593467656624193698537048172971106253752484727764573323384332212809060611613938972306\ 0351200950695439958119935331706856080320746964073455217921367130673551667339694638276624145463\ 2591533459753628890108498859345541353557974034775537312341444975583452883320370257164280871060\ 5827117865261676856914798437066110798873955800843868051365405405104871521822600138614064229902\ 5589581547788537570540942136858463434949539469435593673599603367935886935362668217754336122112\ 2516470132557548117360585087147050742544764567030116341386315765045406464632125187499432373250\ 1291731576750174765130632744284418913476925472174122527774361899329216365754376349180093632140\ 8234854543513889695598484740489032273078767297606846290158436094651765628984636126931024732261\ 9222342837635630333687058820352285622918840638834110254352626385374130047458973278314702964180\ 7557208787358058152202625567107063388063339900623332312117444340010128201179959554083770769069\ 2612694436918907310016369749417849568674294312449448662119416303168244281222910282081625080404\ 6816538547347522822123125814756427441061028755678633354176677501907024413470066249753897381877\ 4105232807137565144778303967100794595268106622771853740165084840298283688251532934068319924007\ 8770775332040779706924249451111074964162437486695498665810644334050067859245462325186068465343\ 0737070101686434441612981816817995164831539292335905147804150878156767880276006569884646993612\ 3264200524156937031976047040529705934433601729127500580953099764204985348774734317916850095535\ 1936173388487277301473519895021994289411043411018071806219337427730978366748173379209473844622\ 8433373006543557045004909021985092508583816387166397673512206639764621030627926019546005495706\ 0489748338717746729114650268711016148125937018635454938448688044303551689769682312984529131105\ 8252889732589369551146318532103348608426969010851700495522399728638617902001305402058431785184\ 3507859475194008347094895926876969713688172307588794629603325531046967876400041200211096160584\ 0642776282225892840036595207921289019811036679156661780022483944860182888719774281205700799422\ 3529797248189893035862399966737335628154999152668767680086147974954702436522514821218076915796\ 9529463657918688666189274666875224698852107137871864603505984703783417681435056840007027569204\ 5776834970473143910566328142343369941879474447176828653181976397653465524679213810515230579520\ 9748468922965279149019694839750918311279870220242415894552905027955606531102146479213119024445\ 8896080079282337903037583488488209805166547844174591289058418324983593891515691927894898038709\ 9366510046037023694319336501243620773173135059398951524779322451766230016698080963788871328083\ 2672098138554577071782132024832791877535444351811492276832368832427142631657281710920281548777\ 6299204553164176249512060521026839094271816035066359129713600767248594618720601872686963380210\ 2450711252586678378090381942809510100176013553461845415127532882302777781442436369302006663367\ 7254694654243460797669711399359011824670028408358970325898289853856544820222485431361330500996\ 1541102579057162406247111447715063243347976450845247076451644008939667505685298407801598823429\ 4181830881680649605095288860868399842772597772998784387367612568639816769619578173383009015011\ 1793432044734045703697944336883683682607214673500413606966081600450121033067640088649390967645\ 9765967997189435508673614849545277786892457284599394134333017188765492900388293531321942260221\ 8738094148556605306928811304466590253733753976668828231543190688518010021104770859169143967037\ 8993810861138866869911312909580025654677700011954692261161382229373041688738782618066438498719\ 5052132985542307402995809581987617097696055666130775910292700202421882383174422263134939132171\ 0993332050639054163220940771568255288222308106330644523020940332484093726481539956200837763508\ 4170565222507878377123781402927286256921938260953795540154222101388428058351177391717873091289\ 1652904452807083058365718964923611795424548383959755762230255341049063600541785333412013331836\ 1728148397239776083680860829504101128843359946580883613910851897089872324150558304053931023373\ 9790814451412051043617896173858876150464697191891082006569358634632094208016759456066503083000\ 0725982996601507397848661795889719163362465746842765124621554984673082925981238431310595475750\ 7463346661422480301597037038758268646867673382465131333569883339348669393554842332668741513675\ 6083961779034560799890924183968674047659779894303425431136203671020576627675372401772444836705\ 5682296388108128353498456696831896817086686647874365711346162140447893850501748119347216735186\ 7809472465109145704796615086026271218641594501991723022837186732727941016440694084242685919326\ 5279890907077431182696209891799034406724781183129747891769923824277462421288545337604531839047\ 9293511951246017775100405981230163932348487592336749919019844599477363369143427551965539045777\ 5303329098672069607429080715618064057096474300810740595133325729564604723288356996717791149455\ 4627049257380620796912619526441759005580198904716592446143635478560155625427150241890404222006\ 8801976711285819481662277915328214784596869094176607343006288359464096874593009781820156037068\ 5925116485153511280245452117257115933800486525317013236197331653716754576590416956094712896063\ 1146346754988713823753409517849420392875367083636729917061814666240161087221050786160445890039\ 8827491383583028476684831325257716512040887226851083173239895003663870975861418740378265537685\ 7375078479105183665692815632468384393215422817545329630046760798512477002718852361197372927590\ 4544940263723206933779458306519292645234422471289564069062411112410154968921860741802584310225\ 2168177681635443787885953699651122987648010748575543688820064692859194196013952488656897594201\ 2102087464884142503396295183768819415061475552246155107315442239439013287988498536918038076629\ 8710062391717328254462784364627309678027300924620324503070879178559728100128677123424132001351\ 0905038082506185828466881290907544125208825072875288409749896302489633949051310477945306069883\ 8386196914055943376829724115789367124490135630855388665299133958125696873641176467485599093109\ 0766052743380027428261486843016575572163352033690143070556246896125278535268239238951086257091\ 3596785407805282914139550885019921794966832750176723496866763779308688756449156114287332217961\ 7875764934286602982450988656033925160217601322401169680260678742377179245767956475384331143803\ 9013413919698772089624841561986193187868514081077754381544374046310960347602698542443795193937\ 6683904938328543756485737226086277654434629717240620279866023702057681134014741392774936280861\ 6268925208839928324688739689744929458280498986688232419818030000549369087167710234140559662245\ 5825580377961532240789977828366722267968459301331684420407870681692440123215848025006501186887\ 6327233242018736627756319711306642728781456993542586682125796701832127444897394161165182340116\ 6768322807990240202292126112665109510856987428760929869335947245776905772249181587446107229475\ 8084922252835729213294231062398354312120381087125551931174512579074234579943027344067775262161\ 2454227193571448419040442490642030145392518547863624390754361051268743810911585899401149108609\ 5358696287338109956690294963096603542260144770860750533471140568541860702099412161489387730231\ 2326986215391097356552395565073650049174232857410081891016030548339837079394283171491511399711\ 1187849196933930004481078764865636160290558400034826598972691259133072328304578480181660933095\ 4281983410905289207109131314122427240701364097469798524680897891013387063987184975829191500846\ 3025909129414228032016508354834507351569665853098966742288267672117928423597534284861151288595\ 1681715410988508907876396034590629305645697821071577223955339940279150320527891576915043391673\ 1644081214480387038218353775921091956688156962023790738797611787929999608685554366146503225422\ 4760113351355544172611786263838719727833677034178796409297109728125574591769665236779603755358\ 8118515362664930993352258410159884835678133316298278184776145950880836272495481679471711960312\ 1257308410436914862604521616483786521135614669641932939715808849588886306461947012875023029285\ 3041156945014382442208470888170618736078005838749702114396740781288852657559902139733422191733\ 6302783047045519837983559461091751967093689553336046291187682657340325352960867718051804894000\ 8839248661928930311480884189812379778792761551860842010670404500070473866334599264629843298255\ 6639264212818260463101799125905102400782124717085671482072101215515550929618197475743343747820\ 6024004874510741784780943354090159804821119965751823206838845796277273183933656415666757099936\ 6229837712781203074269685904644179913879846045832070274613826333658052002516909757222510520582\ 9024499892925791124300359111962283674350101395832843945819071485794663761236408392736476301306\ 5084514376146696265373796285914103577444862279870887334508334790610753837077865563778692674927\ 0680991396779767029369570045837175150479224926289278185635326043977917487309076617550844812162\ 4759310518323622376541737035892426421764491235992341187350623820292778027403475321196477109102\ 1096547762195140098379091283458705787836845701503175481041464800152749382449167568033839412628\ 2631042809051840141021274723958625440556218168704133903020191775024990047212503780643552988749\ 2169901751011225529560699396988315877028974158023354746036437784777284400498416442831056337173\ 7797821006034166243670107609989084195698598170531821232012077971261328522227877504611754417961\ 3461236243190489946902684531963199752165436039242136933484457528921518781832889132590406613550\ 8002653831395928901516242332914375911086672099214082331119959473429631914354388947186922439693\ 6828664278465417507171458172794097757523988303577506663253804353444377009951756624888393829691\ 9436225648546553169150674596431897422954372647682072599181272736664583079698900329281753234595\ 9266256283456740681675324021169449269545230476811819576883198068385694725573796180262074622883\ 3681818360320628660539201713663147975887187419907862739858081594834396103819300455233951885219\ 0571190736217122505876232957697021289067425485799125443514813378515533703146699553839721623282\ 9263428665242673106317050363200552456798934370655671995661640234924541976954759270379266320955\ 2960155717530677327703723573376286874668584515918019659376517572237507440880448385933941127159\ 4828176694691481465458051959701104177064058509306670642396993058881267242383643642616028462549\ 6206194541651449642184743894515343309301923992198684024568277079504754375444701316685887859042\ 1879603846214742204416900815083926139518258853191790463085980786375797477734887566715947078888\ 0494032135394764155793204981216565683756419771417517725444223564213634086017536789616665416475\ 9780737943350123792049264536552216480053111006236044580500663502193720087224762633010118355381\ 6711162285910079383450518866488516367127865034652506116087212399640343195407740665756519101569\ 8962752272541451422835819535105066727831165970121332463001550320419181778243601209680805897070\ 7449357620361343468718384726812028393224855851655856818571431056223983474604423208852015514866\ 1512073349179124402572728197774515322285644527824164661714300167293377827636297120981470998313\ 7617910959109918276576145552927191318717259615404222668315609805261753407840060853761544373163\ 7330776843811219745467410621182883343648193475135076599580367800346710329098987929657975160580\ 3410969723420434764465522550832941098947555554771677310985242461702460864813238507267082282513\ 0920673856080332881081309842020059103102342820058778960131769944996780941902702561780785894494\ 6441723274990621626800968761417603449699386714394922194427068574071897921310117737828389107151\ 1517743583256906107772205229812985212779055356595559873513666047189621376775370170267631419720\ 5832968631764306933502534229402046038345076472709023742220948581725524663603565811035096340805\ 5134606737796826544429178728521769083389067611003367146765776605262087862766052508892089494630\ 5614458492676250142255585530558639660710005116210835255065635574511358571753021804271935824781\ 3580776480528805828932212890815149420085820254294588208665741926324436572707950229548196883904\ 4146284509864169029532126281611049487220565047972381343647167665615635833471743589280590789630\ 7063074387638585608879522748642407498070482536927607400931592500843279029412514751219020774014\ 4066170323648862904622699303493981243612091840116523587410356782163270142510244165916615740423\ 7510683059460116620995224621961030162250401699152508297471036263278218365194950154340246959287\ 9948034730154073136146616576060676968449061373254220151522293059899504740532938284218483250453\ 2480129628529591906345054495845214296244800907082044213679782356415541493146559852235540426916\ 4351903947636925446421538314403927167272918579420458423849129599998052723204142646404665530268\ 9745706979912618972785465578856304955269953743781690225756872432115337700683547093076422875290\ 1726264786640283361982417811784700046919523479992217332482781981531963590029319927230292716493\ 8459346419994153792053493033101520825967580967004692452865674836484254606875579258602571538787\ 6307051935913079268637955062092780468463166616074368518581488054790690299974254457668465136024\ 7396200442691594879243607012599973298576940951112304442641549267306440626001898220953167585391\ 3363112246954582213864577243489338166713878709806405642694610730645596513979991497637535633305\ 3059318963790607283007856256229247503575831419452792287364105232013592993451398516593844071800\ 8956540649345629430183173744228708500346820847852856961910655577128074562171776747585259661582\ 9608498270796215563600464386500518231307974578827698604551504392970550655336999272846396751112\ 3364840453659907674925594331479701341976208773405742012931649081444677945726813816870607489159\ 8061187001789814110166236525082419271004037597012352574522360359901839811731765883198108442819\ 4568075474006557344392695792442232383545293233238173176959637067839315196048585802154998919797\ 0286569833426963345204210821283338345618603565488351259343193762888452239147243983840297457216\ 8674576368066407455444405477555879314461583923776943971680159211233141077363278569295214072169\ 3035411366355557640085095288672290623213287675403873645179886202241237355549358082619465205470\ 4583756850976708340451789546197031098894524997602307604293139459571479823205894654553943932472\ 0264786398366506558125402111023639707863015844245292822454621207128565938772163840489144814481\ 7642412017634400136770021485217732039128749712341040005968001478371911198180795114343869805872\ 2211944885670083350735560142621187121709949650176114962246943262366606938701554916449095519242\ 0164405270236691229839518993128996638801752854486864698598918072032595084072696773151579051152\ 7129598128248830043129925511107290009714291824412930843241728916135705403949181791390280921734\ 5010947633287888280411951046648925901958036131022479837176557505145811173463257971266651836407\ 2050955530640439294985963365961764266529932353803135633585401891296009707285038728472987827406\ 9484466521057207407255986205407865105198583000380492916096564506835222101774280189383017662838\ 3312263623548282149127321765312893099510703467537544779459902965490641449393310773255903792739\ 5327884233774686983805179178321059526295584709334024116831500254285720678295859961435988600931\ 9365963759570230006293769250910495078056811391781628767888372612333731406261250499312884064356\ 4958190252450187150340927709245366535190506618364806284883744620289028741947698898095590232842\ 5858302023688045405806987803873163732261330360286550111340796611913599169970695605679228846609\ 4199366068397213439498351391634248519600028455854084697310544920452686496136312478066653843951\ 1749935546980423760060467979792236103601922134170872456838147163926040249966817411928878328876\ 4933407175404050213896513891460491555501301882926512553481361600867027936051704403863276680545\ 6965052704462035768139399657180414834021546423509548251326085264167983252064542913051788247280\ 1260741662762212508073024921727554181230961145041318207540865322440953941905202083366916277446\ 7254580702967937540694151196843065832350903992800244627758842213824551392152021312865106713392\ 7294185586299670445666003100053117246446993176689116840934944542045612286212742353065618481946\ 0037750593971750879003160043520069520989587023004852456497618004337800389820963294522591892737\ 4802679820691342535916704167370634903399975647796932374468192474684175191597337139732178910787\ 5292287896134056308321263295789069662479889012917994811214523519880784075366304592878269708301\ 3467910134123307822610854992135631170273388467465500008476221025282759138769402018089469927257\ 0174215555753590277510120521115714484933866487991701217837306942715808523568608017342507731268\ 7693082930460764224092389999215439951881479339984633530668689991965873660779178301086592127280\ 6899969421361487081256795351975520204490715293622750525204764857759259819385219265718956506083\ 6370096569148514731633345649484956364090176452892850980093643516664306949837355010930014077362\ 6163020980852627687714412036537647498456897689678918792011823802912368962313224919557944689622\ 9121258635045424956897139965899577952502708105241498115757900584435340328095630506723426420737\ 9805651922147082259703346574612549088543578850067601883232412169639927777972168480247578519260\ 7427049732171015349765019333018708910930745202911317467678631889982102842707196195247361210564\ 0706692223586717723449314623630519143771295449260648982382091649243033186967794565298682016701\ 1601013625314936944301295066770612236249106137544523880267581515258559708402603836535576753792\ 0409491279520937913825325398217091113183676692436505409179341915309636866303752104779849557814\ 4106226229899577364891804115977898353640744654889708726993091973720026299528308543199525042504\ 0257060412860151040650802819105919383211238751002531956607235630619958080191586305746714651516\ 3977167761396675446222246072127656018938314504759753742182014457184172377996748125999848249999\ 5470953479064452469537774302677158311192564665698421791144064592671924014936094356183978628953\ 4902679013334282445501819007493621738858366894181714972465622345638243641459559612495317043707\ 4730605314605818446630773371362565490524639577433775603789039043589561557949716797893074327970\ 7158703991560196949855013478666868921755800539517266892749878721656627692620014137669154459862\ 3604012934702326071240412274310714958780502591101382130701431148345047274748663817763575457656\ 7815089599606657228401507823483876484774133398507621621560480531847181512624075391736743488484\ 5079914166488471417403233388691575982343177958585584784618458842158256974069960823258466067310\ 0699746535582284512646529350317870273347337425867166009356544929240811730071907655639433021905\ 5876556256039182896759420335130644216621805603126925230907756698404346094204264309974088313133\ 0203860498183658774858131477348216927110654482822021608347800866564035890297378061127960428059\ 3816442771766283591373868636935201925007024961291738737122875231683452213393195713158865452309\ 8302491685998210518502759690728470138994374040710632233518810351452008759308926141703279917131\ 0904917569230534535023077992299391888700532241267194291587907670363952228550217951417244948635\ 4608580915860393809369375019355678318342091448239841470642681784258952268528815849274140057283\ 5951720717336134131205248578205978529271081134550305917516768075884008074162954269277984014751\ 2223776455711611717739662807831965231035834369352427475368691740352962886076308328555790180753\ 5787567894246495637217190705035577695566126087781544835065659659879739805536479076764091473492\ 7967107216145168642120649685660567349641384307756430329480765338225646003893693169550743399639\ 2665791594405913052513976091862844332786885126012584229822147158170207420477417912553335953930\ 1288480994255069707450959281632493113442150922317137275783743682768481364476929854628122055331\ 8928718647801444104207706174025450656300921175612244581608491649034922582457471565451267627542\ 7923523001335073264431931386170683129276445884621697815660857194487792455478428431131413750508\ 5832131003012676539287747130125657679260322174475550177487060834493975464247623599779650644823\ 3862826778923698138479827076490366463633814372058151258184600999464258894985767741834237732870\ 1943615916893928519631786923877564989469166745995340965131109556935926082302151412628584001319\ 1456239493591732547669692698401374663849193468482678351775496024474926957865104116273672614764\ 4568437049989959716180249417312859887940561114082738319559269575031314414246516471780427141899\ 3796881299857501784820343062916979491085716557055670714757573566558837251632893043816459112545\ 7558364226563147055696933468155611931443363262242061197735233449030210982449528715427542715216\ 5842987478191796440152431330598645891710587129385620634406672213799117832635105027568608814894\ 7151064875790463715143617581300399386115098458298861612030972234715046285002596358261386153468\ 1930490258563138687263435519647215215016534009893820296460634968504812357468683034338056181206\ 5342318372204740050993275256672871820815755490931088902074454559464765342406787184924864730056\ 0787333873958548345579147714183283091899814009193345805882490170688481747051167870187069086835\ 2273049182138627084418575332075286359965367418067319694051554577806128547305497326129434027755\ 0708779268455476865410708461255210476085634864103300529535797555842289275535923673041262765637\ 7545496531217425687258013207577110468960161314774457033322531362650487881671457550850855793126\ 1586497955121949076484286349788828252304834367067578666809252208285225078115807123990879125031\ 2603638777998455051053659103307241054559299169788668434713732350345301847298427299124292845242\ 8794159848925488172724585394956765954326156413235585949241033640371608288521794839833446091082\ 0656025947363256832158656849372008375316343284469029434972625805165707428542075385149284461927\ 8774144484692762362974774086739617424740909950681537352708103012015606450861078352170567767172\ 9531060647309091227829794794514705928650600022221761379830944981653597051527344998804302967034\ 7194498983294739147316013633285888803212624871132170181034479463148329560153332217152484423819\ 4536943445952970439181670428744595453039609236655861256058052250191954630211196514978730656407\ 7167035186748760270812028839031205032510360595936883620350031887930767734563461588924618863026\ 0711760783806211335142905071990488717478543935063418082477030061573120766982700681602232985310\ 4703674570296760004721466321653883732700311638705227754999880916010049127738782285213415489397\ 8984374983140322142362582153701802737344081624870617291125331768282770588809847254382803310690\ 7785248727286906235877964101155681143714980033587348245612547689621052807007537638282538681266\ 8001920999559321467959161324567882476544232970505387985065529733461541032784822500003225883945\ 0774491911174512704622667178073981792216049989990966795640632936578249732248263640119443527935\ 9249737355686492042733745938071418208355350899720527693897488220637335966299658040011265242979\ 9810206620833723376543300935571947901776608972958215416144239558222521912689317321227855402451\ 2225521199131860672729596415288806879619428699533403995258258074013390298671888164066842289959\ 9519483167486437870301615889814194731879789184219649680400832253732073540330001469379443809171\ 7411267229003178853598714279521688336428577854121678158830133323785950908445413079947323745710\ 3424291469251779474563872422414009041535723537874219768766376983834760998461736912707532237199\ 1386051987958810317153925672665551936556909470938637906935958942594348387462477038358841994633\ 5795535774944533346174065613057576864216317276275128593165623077304668386050554031494287744212\ 7376874767131520571385745365737674384555438035953427560756451250667936881341360581748227673905\ 0586945080995423647663843621609568712337238681288928389733910162666710181702765835384803115500\ 6383004278796054355083355035798787051305967799214524406526059147590440729357266948443280577057\ 1436838425900911075869573685324062150207301590798701634755495066456261156373459325776332816105\ 4754396691326965066507039585625644673462348333975181918690142852823413700112039556745961077132\ 0207729147556157645673088464770557729024901883561668027137301759640650559570599734572405658680\ 4961859290624080649731570288783005263133047529059260617815436533912521007896972927397165576230\ 3335892915372844174502190348483587790012231885136030295111962679895038522338652134725676433077\ 9945991934982643869104362378534019192237300550782117800341753989618737716698950200093237561849\ 1281092011738739352412591156993894568616142466607841063976451057044229300236476461374775012342\ 5671865882317443887605827292640556957847144856746320759133831080201900118617021131573754630751\ 5647474705705849113505540682043235083466413274122056694295896946911034329582001638657323156213\ 5521119799551791455244095154585363595347296326282347862447706530161090138405760583650980294165\ 3531113607106187437193339135676897333916594560847487523569365877536816583469997948771331000053\ 2041679446210655663601119939716883071893903954491677518266879638099297353954180986449899262711\ 1122526015966369044523430654997508832519351778405242612300250688638448284396575648122719340271\ 1642398050866058998419602748250313019183723346388234605394677955540742023912135078395106147476\ 0103575014775091414630029475666782157676233696851506259500174803898221540481375514949058026817\ 3649934995476963799561336728595995626297625652222421776513536481171843354145579346553395570507\ 2294033825579612862066420926727169838773722669733947998653583900060983177448667784736445787474\ 7819366523115446266878796416936787059815746180604209064904953231230326032147500566790687182581\ 1546368248624137528796512138410129743455532274683053820325061971223306382206231189372729376659\ 5691948134725691253609364884882590305110573834942435247705885887737678807264996211596359621121\ 4903033095094202780068952496952470380983415335220574380550849642772993622167251478364286133845\ 4075405688768007466118639099387705758393073081759859981105123899396238932271705447599146930788\ 8078054176491629102105650574976959834162716278148302095364531847156818244619490042076933918354\ 6339728340395982050673862057594322868693802377750533673649558195345846909701087899662801101677\ 0909693626265213903760235383383841592211142122987032643485796703962616661607825652387720967307\ 4605949770347077358256921757065587317634733635531790354296927346654968736690883602974455554497\ 7615873821780294023163336284744504791264627458278597288014843069947034409854096077970962653023\ 7074711154173422144773544767514702579480853332175371662209475121103341708619155949667450705715\ 4062649308594081554616371721225567044657880018618224985393237973504319353120877514730885896728\ 5870422653511477552953627561828711558701654265352377305904500937999577254075535738868937831672\ 1039580486349617292314912356743264440381120909755517823261991389625307342476537933265455586738\ 5146604647545137822086217646651850203555106763419050977985887869058384930260307375750241025146\ 5916494295583878233466499302616630351345487876581151076000931256805479358626449890668921429571\ 2008685694025632849015743450361802627364334272707636357945120248935106215613393705800257148728\ 3110827843886442567621022055353114923174160014068418502986960566350639307592182210538221029647\ 2983731927617636508105729893030260561146952304287354510347640939348623215809133621990753049300\ 3098630762956623691601795937354209970213639392897587361277016701840171036681379633450956192200\ 1965955593266872784235659638345688512246614941712526954712682341613631591952227310694095609921\ 7509021928646507162521288621357415700117905801792877995185647944515664256591793362338094136105\ 6420476154434301548273980924259374562736748222866488118669481548035552310989383031738897540946\ 9015448023759646045530115236220904940021063804389661690672098630143275663976770522398840186438\ 3153680375724021276841359130486393340241592173245731043060439518529299513185325339548690134792\ 8782223325047306830882353149027489343788402656613754459607621160314090192042998725107919819406\ 3260602545970297217072669803293359634723038611490028877540012025116087353402713479984361823843\ 2831882168079739711161715854774666088047847074641169068302762390990543141109339318342149222849\ 5976230587485114303865417741796005401777217851412741104238268425617314351450391058170770183054\ 2554487246175976350855782312995198392145839121984051926346081657996038120566733326427056157582\ 1652140057900502151132090046397273276323885451506232224144959349542432071907128237173549601345\ 3317244452877169194609277272142859975349946535613457451686468128938140860117052435600679910991\ 3413984438707984925110033721908499278131806264670317654215765235391846555642158896258832011999\ 9961688635790153437909119541807428337079974997431757806134625704079169365434058979805787107059\ 4593585555935437686280815663881097129272960062680685712091475315150628799199325123763010228930\ 5712461046135169488293400149514824888731174129839106296048005576008447179645643473686856588020\ 6274413593261292679306547475374474538126901796814029269686548030171030109928265877813889730273\ 6241637158987636177456566898985921724497352303431912020291622964643959736263570444977724613945\ 2265227012969736657088965661008001869794073034267582297913524481345261556039037384460764472164\ 0457561069912982868316833041187807033679169150447978929220323540591371074297433594274526407941\ 3865920521576499795880166269715746227624244463477489726121918875995142707819316890570214691210\ 3443750692824447690252064346231815261641254971000452227584613460041979026661449346096719601718\ 3282938241983799965095168392183000584430246989570840256134946717586996793828627147206727335082\ 5567103270932025455864952273964024757812918206444389853594968036845338293789631720748369638157\ 0311727962177627985754362211576222809940009299399214965135086617351703817554089081279573569635\ 4368087840245179470651605827569869147588454596171627977240261053034674934901016671682204281676\ 7213357375554593416947252726370093722260591084646272013116206368448854710430800890613220505384\ 8774140996952864505036278404853900945914982198632667084780490293175160107160819844284165539847\ 2074415788622907380192824659354136466877080444853094242677421601123695737795370478991033868818\ 1094369886759892690961959981097507162619952000602757509277588372355572927236691701758714082033\ 8338332455390738972460488184872977564103292985731106072801715120744518257575296802609289708622\ 6843589573076421379140993080881769124519296563848474634214265627292338047414863425385279051657\ 8408304071004389064207481494458067993778976651436262872628056427172230395722474146094210810606\ 5678801951134961070883966444622999069077434376855980216446054715375412826900536382162853991731\ 2077428313421871026030467275688296926705829747837736639901839632533819749580348633058451522028\ 3449731167725698297479746949869830425213764115795709568329381510431494957744815572103230137382\ 8298866605231454756838433781143891152607738055179091655393831061297820116660400841790649375803\ 0615447650409930909249717325006563614181908479271958245193034195827540993422599909285492220932\ 2851748394418141432296690131784288734445487744207153216859264577980531648183504588684411924919\ 8015455357584333017178580471076863751500532493343891046354510281255786943412397821767121983521\ 6799255951021803909124949648456753339002951353560908476113503737547152719461993655639343984987\ 8548933274678902969789266484653715208451025654648566145662875859311462661061931885134215455934\ 8523166610086387078065271616508719813837439189258761526345277360787983743552878666925642028861\ 9129607380877441745598638146662674165698484340112990413546152369442363923024378914744128339689\ 4154969482099840635671011217937804580073538789158784129078555241803772131601944178266025480965\ 6780407096459337059748706349233978271870646323294571447437591142320363875181369575603622721087\ 8424470523628520855467877485123328127442609331682539782253661552878329811665635077951585739705\ 3998532668901504555157939900678290309073042789359488636043934670932034685751036920257465064214\ 1534750551195941976374523693031224278453101753565520547159110171424801369053380783272476338692\ 5915394704417311797748898088361318824179230939093825129420893660089037439764839047202688903729\ 3986233008141199119019999120176459559123111594847963579802374692717282451729171496486242127971\ 1429585693862552148114658538587605625094701636696312394345702037289408878524338917401640266193\ 9589232015872292975713396908145592083269238004144956744634597223566301863805331109688026697237\ 6429106129731066021730258112808789830702665739382543989599413041414259724341049034233760205143\ 2438371407464655386395460276943425383397002680687080570709858202306297226590498460576672653091\ 2381449702305074991863273347784267504919196809381745156480224658477599599641191413303963095414\ 6624493720109558423884171777264813314115739522352878337043115649994811820804411837701607979982\ 9204136604361277549562548591257170171579403398952425235357397726398371758291141717989961811204\ 4937012907403529298020645856170714639885418500917874684462856827649934884310677057339035677576\ 1043528760376601895740725801390182464279961742083187063282256768947017181372921955036287205962\ 6416480759361709130271624587082376349196769192183022887333248561850997978051860664884387038779\ 9705828246100188243670856828332409288581316765894798416274573835444284125420962277047071556005\ 3667659439797177652213082603974158813501837062803824978833784872621636402645291642613502593236\ 2662424180151027264461117596544249151702125930560186328243443775684316785831288512564691840568\ 8665598379381176027355950457176506082302148645504440215280461853144764633389735233662189755030\ 9138052818544635803918193894341345501669655084061157294436889325890362010436724481776610174262\ 6801179238028633058106944147271919025863951640835724793873138486939957812978736773835075690676\ 4056553430116266619398699556204142331741848859057159275264359877086691086708436386657869142633\ 5319042971885481389201822906851803489862135450779586390377090538637579397825277942330450584265\ 1024303227963506889391980170178377238347575171272048199453954874436338215325248525254466872442\ 6788350879814544903866936608053765568076297569764199656795724886810396095166445120730588477273\ 3289433549936404364831186285718819596392098747745906901591908609649350064250911214151725164710\ 5729428959093778682001117800840104694074402961540448526864800748358502593800735721334168342741\ 6292663575247192183357216945966867386669708264978896201607227622129669075084506921317123469427\ 2162792130116274388903176051396734457853826051259319308265552253516234553381814943270995507303\ 8188748008959363081922669241507893405158976852416577042668135786384386094431477305324595922566\ 0039314423443479299605368314400612798961072248833726670406248782700156681574206582128338615565\ 0608682758218556147690615764890743098728151359795768494603157025174163547857765085718049172892\ 2334257803616931539622297939903880610003506584522956333850072481545294130681068196310662563391\ 1688055194126636573723738082107679272895582382270813390744165004768918074193548421362992450102\ 2509844215293506941123732643077048243695076240079812114405118616460096406250746097176184721335\ 3320105549877738289450971951860617394410122127632239309585154732696375946952255942652982532357\ 3487131913159703299281081281974448688540775373778458760824140792848890297652794519912692553129\ 2107484132995730900051529004068097572207925463309976464354756968780397444093338066513705572466\ 5526397965956895901972949562124075873897274360135037511273525398068632718805728155027406135878\ 7099991566639027321753736801784251460026371821079491630115609546679507621361452959564577147502\ 1888906186264893319863679317692998353434731266172471007352453955052880131139739426361841839038\ 1675349009908212996283460390589695071453598690993538469164488231366932875696126495649418256865\ 3454581478406381406351653972082096545265174017273727780231283382631492704104004009981368742941\ 3578420419688021617178007633346914955782503224130565751741289752097136554575931310722833172176\ 6376769462257452667370790410133198940546951253961903131124175918521563894746861685440570382247\ 0667230733658444146472309289174545437209089796833553932067698645155746469664323655803977346210\ 0845159429360582687847752438208444968216675695790339949689958133028030358099306313571714266098\ 1348706875651445415070136823786942349279305749742308594927335050359593133446001765583019214000\ 8488427001021469114525131487507599818721174302066528595546998147389807943130093133415098743251\ 2989105795754596827781303601723087936541136734566813077230898766024106684176280355213394036735\ 8249642906067383344368515125065867508768121676267517943809810352526503528882361994588348307106\ 8338115563170043548920714678490889323187148787079612262566877852211083791653800970680092605270\ 8102010759533072252794334866353344404536435923636597486448953699871579351289913753549358751801\ 3799503184987794051239804983553099127311506355681765659108869949539947118079238815711347390607\ 1983228689803191129979958106064291499709737371574601861171947953599703987072462437335481189154\ 8655885862510894689682961045750960923964330665474280199946490869322993180364540662013583104913\ 6560502936539124453000893384700516563055468246320950086077862847130752315626282651785015458805\ 6774212950838901489853918672987775916911319712767945237373641850078495643815856778917482157740\ 3419588918549913350748477141165342800669010823782910726681048695486552010765662052138375334264\ 0960745756777953589232918271206971818193235446106900487041789577019276517798093846827435777050\ 8864273416199375282186670952867194165749784424882886588427777515869899761264115688763468766063\ 4290245150493617801993757184716778288906802649766587571480474032464380087641283782302089780810\ 9628816921164965083717801064600988403295488678450069761986687382232458322403428829161642462565\ 0065682309429440305889615984111735213293952329581498303861801476381007067682971287372202416123\ 2993483641162112639867342909814560181052415027299433877523724228126268161150547642967486813144\ 4921284603844258009271155360392580070344910658234864811129983246485993330749731157497890166403\ 0653785899197083101722689637103220526264911931022296427271734361895795366471979461927592800964\ 1213946211103058063840911928478132059206725510904494117672644470792295145672236906977142930693\ 1700506867737899867534932470830657135543050162312653047128608998187569678500503465690857630936\ 5572631386316453197549382823809046362384042730850655565070001657462049442271963277950798107505\ 6488023244100995200195441215944571170534176720986286904044702337037735743428855729466101901577\ 2371092881221416932550819038262562940381617578417788201192880106555000770947735197490758242156\ 4224577619665764060876424746819100697467041894807077722373053700851842680516206927237944228106\ 8573999899617798150313310508272830651135658054850856239373659999704597344862544079702849134417\ 2967036139490424153334986345996393009651715349865646221368469444188789770460781699274065153869\ 3292129544926561092947629173266082641518576753039344060395119999538808422908149492953790170964\ 6444123295191750312287275695912793644538284979226667556145998093413414393310250929962892982203\ 1109543546829583762537283692281578646373790723662189340849784969121352440209233674072962707146\ 9188922383750716808571527099190690973088011585982170565673513183702521777910271939151672409314\ 6598678206828380440558843335128180524978626974594936931512348395457617886833195403867869884364\ 9664665899529671516384185914629098399862422326992207101541719445545704752443457764535466051010\ 6629032423243654129128457193525337173126084661344053149085231694408292325197433159625647854859\ 6960046606749422898013967814631805382096867892889730603687470076400156458967806212529327264493\ 1967605185203411387049683820610438311428718551434174008529477944825369668397698782229057152823\ 5100603018887472342963890720986980055400856093651968267138780453332803865872662725464177809698\ 3180885661201440182347684173730748177825057760027746298983408612229052459484933287293845579990\ 1712365764010187298672550477877517157862616457583676996707107171624536140984907524103584434367\ 0477285495637122600971455318307959733040899955869201552671343810808225285476789071145568400678\ 0571294450978442085698525932601653322131858748503602140005270144367401899700155127294065056372\ 6910935262285363619675099698210995923780774232573745397931356237896648788704039226134602761676\ 3273206314863317919733125838527150708569134568084625143657354915506542142909946468742514074849\ 8979813773392114308600645065774587025769029715069629151625511768936214690474448975354746551578\ 4255595221124298447134075839411308476337300236967840724529660486669074992478015985384476008333\ 3163343491827041840813003978137352888679848935064327040975168682221931181479742541896612153579\ 7058440638595178463553216107213431970580652320070903496369631079133432199587258323269889710840\ 5631209838864642622566786085830762772248475118866509970325540182207504556189476898054259826877\ 5489796402840075122739528987003017852101792326661170946053359553217169487316831334168465122845\ 4953899564888395604338142796616795414763884846815992291089180012975277734225559916037467507693\ 5201078301127509840319737387874976231253870428712337001741918743026293996180968896499720318467\ 6337092039462282368883661690662027975732184874034323345282466368860783913081030957372632907861\ 0327251190663742157641913978727871607091738966221741603228855052980789651016490528564140092870\ 2600419004482647918774903480173296252963324801143284793453610360472767392135593925836258263473\ 2445329369133210247116583252677221977349816306069637027704763262965621430188031264584118738270\ 7590386071888720357712019714767613858585766798179231965045072466967297474437055160025516660338\ 6862137991598954720457153486843687589438061856563979382341679777641072873850892736818638761696\ 2779643700696995160477938681310209708552088940713041500580395665110364507581797029061891499649\ 6195552845614614774817929528744592804050893592960019681911424824522771487943171220633451278346\ 7888065217875915288075088777216111371889591048696400061292129264630454229789780288334061934313\ 0163939140168559416774156118657939898577251261342625224531920860597208080005934846098046947733\ 5120295174979268836598788915583356781875678807118158366080682138479457967448846783927603013580\ 2314079082674740909147856147734521152036801625263690976303547435311829823565384130860362378289\ 1654554285288183811568739035185891164435491555215203168801792491017857457886008725273466299133\ 6025026928606722681871203223295043916992992595278093235184503864591749920727937933833607681694\ 0497584505964481569061759185367496576133342143846848544336989611114047211747336175998663033369\ 2780742897639449854015701085670906570932905513297091385315384202730010478000904251933793526636\ 3089294073227316395051533842693884761361405696837714334604611102643429254571264933614999063541\ 3449113620753364808281444518268092383052771491614974036876513138313965914830063065981370829238\ 6310503593684865449145536491439583876643855725540045754066853265700293397375364103949699334779\ 9956635430494917417918105186578173734780327070301442210567759900175750816528922387329000416775\ 6276447776788643488167112004167874916036087972162481540639181879394353517955270019622184610513\ 6940809467019458157664118913285843606415160753943632618356899679504220745662567666381443540982\ 7533527469432999133466236718133401821223653152888686364623876383018487921772032463554427861769\ 7387203505389852065440160609748716034741770776615697974559970017019365345681167653607269083231\ 2522253639456660274201520185820491454610281124683046639040958500244911179736854368930897221223\ 2969183855326785808857152415080047118878430556232062512744223354437332458322357524865330110723\ 3092476217159618332938617126586959879192261279495755242869779219111588843494039382155819655902\ 5183922375111330902699475850079988570001705547069012123935321805508520779652671231197953366071\ 9156240811816208429977316849169002766644317169737757545234329957340477217039952736534620070624\ 4929723204800844761167449369126995658764531440168479915322323571274102718715297974604043674691\ 1474332771586701025211738094963010347601988553055710201942636505461617157324416225610559689666\ 7293433924018328817047533002986758994628231050237187629158768569452479918566793526818090287476\ 1096937276829742166331472974680292719721100822544179539550951710913177761610405963815545304674\ 9158952719109841601874598212598177068931505831741797347919830591158514708441179204046777751607\ 6651438099947063670845439974928199117961097997875575101037361694622069987150959500717355492549\ 6061795575900790888064967137160126553984934005721826932549420070400532517233489257648934231576\ 3470804179599516388060678750359081697707157493674112984761658405806553696191927671016030222196\ 0219512884342738742188062078010894119375666774550811570237811456288868960823118652841479732199\ 2074215547668359613430868576770939225034088622669121218835348151676320568389025684400735010758\ 7767476334280418540448717431532839270499505471656710543581791688806571628281483227272685395517\ 6099594226250595694923040771609478260696994404853381187273225506800290016815277308234543779710\ 1964555950916041035100941820005590017152356220589279390114011054131905420499231088556561317316\ 5927075833262794419353408056952656196039359877423803930444868187704067869380044275854134690023\ 9776442198859051849304321506707993539292096857582812879703099923940978530216597515604808464442\ 8655036385408895224106036230435390526924841311289855389426730449538254443948009595912502007726\ 1804120491265216528331990057037086724045232355001165628400624391771939502350683593448056895620\ 2046774960289467499287175085861125158371154054475848429313000536687773811015307072213130869705\ 8559223829027502972495215578919793543504312781008712699249485703378080304640132680909087296447\ 9028556554418473817224984392772438089146104753109918025514600244398154195162311971460516738927\ 3180160885230638642580495217386400758090549342375713737365369212600989014592997143439568649703\ 5770998653936814991355767617607938779829912639711185724786306009362282962292743211162516512096\ 2166445263895979864786632851756493012173374851266277362012623242359466445369867437165612119174\ 7700887387943023953347620114457254545348189955402809190124634697316474191708699676165607968592\ 9587363032505177437801930580402422362121106881996369583855006925849798258721880395173011336728\ 9888892601263761204408692022413756542306374049759089740244955487726866858892251356523698867778\ 2409924638830867083263182837699614316302523358118102316123066348292924532832205238249955095353\ 0029689793955371509469278303536087836952511269324185041556983212709293389756225824446135870147\ 3274003858380693691444507541437594527979703741661075214185647471210581496266583064080210948285\ 6358073439578712199083849587615085525968787384231951026454323049743256675300533523397770532413\ 1523766558047259657329421431160194875260481847197054556160011685068575784827568181754285562496\ 1920205878695410627982273796680373963613549218143595783087896904411778062337850567874010483917\ 5512709435241917429119049729299563496636533159855205226366348559847140419480867120223544725741\ 7013569682218784809679643428390450650237139657648766549499881987454070023844951762073494923154\ 7885698083919249939066302058176376987999362894970754368554903341641729174489989353554991915341\ 5563502522993323262512938358385654866103234117489784070713210878522436586506989680837098232956\ 5178841719524681846150404829508362030749514706162727641219609369166710308505610768034544569922\ 4846879803393859871871497826036445458378452848806574362621812449760736726948723766813066800586\ 1477512174771361710294791180129928347787800988545319101538262601930239740311389631903995278590\ 2053717296131036440380812906601562544108527585446686935188490339043042855218532982197718889777\ 8220881193973258705442245248481827251259699103862042682542446586266305798534363646779725324399\ 8918735913145630494023925024327373259845813464123230658214515627919114023900480740644078495943\ 4407636373381739666251101183955548389620147905726734404277843649457705505249060903240024926401\ 3376070687813936399250577555133644203139137685389680100462876009904297560747897571937589842724\ 0367766478086588915843114241983199214011507011982633836242670711964555825921527876393925493673\ 8748584181768251230312367790108090981754626741379396337904540937548972521326378711358114182321\ 5127286526405247162555438033300864883080507057903056786589408279133026180503957016846126633010\ 6477804487399546238948234544062870852190903982628939530592161907904826806338365676875931704405\ 3327372710015113116034696281100426819586939824658862566625923052160809032117585700396113700645\ 6278833841834887821859439531191450834311118825538194630464894251163571840485922254712587402500\ 5164211061403427048142750292354798243915561494274305366697026985532119940632085699602962234625\ 6498555741271575282399109061903017034509292814429517306602858920876256567741455991149694811445\ 7940041169150521677022730829016997268157534913654777488466732417604583658144355714431315875080\ 1065322827252666493318205473023771578346231728337485856643885445547139238145401029295996856572\ 7348596530591031310765913468569005603306371586782117495989615340314503860952542182738831972214\ 3049742151494066026144737454647062146672621132852589885351076663083184396085871992366115506107\ 5241330042654314274175152066271292054271435532945652168784954431503057431988418180946420763105\ 8137662662076434585183220290253463872477504764432325777805541119256371307820720125004604887479\ 6228223290835622944943543540789949426112781645055545456579715937254018183226231796291982225861\ 9614345522592602695924168496111134748770617287546936935526677480963236426882908859082242078391\ 8191918603260295135158114905739853838599450968080431419102183868041333118115912195600243475931\ 4520198882312571763798264133826067935615422294408508360317121517033486720276917704492275059344\ 8813167113869627516976291722414467194759463952909131015374028353478128350255686929190198238999\ 9935479559850038165794517332973074606891550581179332521224946020408705094591788149182099667469\ 8144579359592936512394773631471655018698234761124970562972699311072266022819857215672973957641\ 6349744184245475259186043125833684767326506662826461831634313310798604693470230585951376508071\ 7537474401339151158908135365186277011500909460680742982814407553346893685137459425059687085007\ 3387936813407741264159712500109593515686672060071704340517682383176600663574639843571600324539\ 8474908290093292174347678741035438865894024013685668285439993983996151024551885235062752497907\ 0819258297975726424295287173618901861186070147277919645853379176641959907695709432065294358050\ 2742133970388391241568479354434192704042738142291650232998581984158599214532721306326090504447\ 3836549717575035988575009500183412435384131668722285618774850663808436325875905905717742255228\ 1541436652946814567541583269105621884741337292458689340397206680408489682712713228775595152047\ 6226472337517889786225774067408702115893695882077345886323469768010064001734398184591058693384\ 8838524501272551371230046456739794139524404582057345115653933263215684720974823145331914649291\ 5345110433572197925961661147891690197208190784587263101713679487479546680990137349266347215165\ 6521471823809534552307813022856388109983518768980622160681466645088902051115386617172439758719\ 3783997273510320813266108926655887322822924388847509365440900814609176057584344169268142860531\ 5351934245427682745943147815296542501853961954637908778926418798103581846529445626012945729466\ 9549105086002955335599336243465607807544040863519139464299456943078065692464565511472159735236\ 1292804785386786123091707215153884742102842306749389350511276572059722271808299720100383002492\ 8474861791305974901913247278565382584730136078663333171979671915504102036534409258763243051916\ 0428908357798423425586737869717725428282253535435566324087941528824140994228108634766688837851\ 1802472214437088933773923915812387249848823114261182376689327672008570998021561632808368618265\ 9490779794745641954434496675256275580945300337144760132496079969324186839756153773154794527344\ 1304653796964390883089374609369036292973715529438786385582111766098964696465667932824408649525\ 0365060588860434661476881599541703155050239363924299170422173863719238323240104716028835864322\ 2926768933314710161773788090034794209407008572109976192695125523599160775384731944941108830788\ 0754122604442305826954764477005134954708673885145684013498692607330080346308838273845516019170\ 3432324496929310003676689235452685300403490743323821940090900206829755697379518254812831143671\ 6829137958663742958217337051384589577184299390705863504093943989540556746784538044450872776728\ 8016042438181105471569768429711549607238259558477871800039362091874750516808407999658903214854\ 7534822379256708817960526052863614862460759424164927971802628996066586547717469916846991895546\ 2036717827706001824478826040356777672426019456366587814956006638454412121597558344423506305760\ 4492454949411904623213871711942899553403037735995611898813304068692293843865100454520775761157\ 0010295926310228462396078978449145695639910867591333503855623144838060711680558258416790647514\ 4704826762577664733796441971555701270443940973528243983744493090290056291560887658274544228583\ 5948365065982708617266709675221633623463106338765999816301051735407446139197522367296995667029\ 0109397345383745450494415549555449896190457400930987005020756274979107878059569614844303722191\ 5548645387156772166772617419080593253081277818372754021930016057134476173052636704796006479560\ 9991931457283947448688846129647078066623556046644505832056654838996976351802839760507115175632\ 4067719303531267660372360365719954310961481304463234782469973242284963019829576332035543348985\ 7190056997544658015790722500470318162068131703475498235305658890162573752500458233939017466741\ 0444010789537100498217521010479356515181905542951105993819323594231214150374376793316552590307\ 6342508554581745513651711688330958683670851031241971069330703232174243331176602275248754383385\ 3578429947108999315160798326387028470411744070234754406380167462793804465600631780264809326713\ 9163222954218726593810502426436534578974856851482977882103629344827384580053576315539391469880\ 4518972859592573157549608020115989714280705390224914479019338897065452367982775683330139403113\ 5663108037512952856236642772632097321840133220139682496969002546321209143288416100328964073275\ 5673113980255069306954397092766404727544222762463002172029724457425253964761656836169542970400\ 6108564720952355561304900385086880049017011707414337725353366529944707128420195609213171383793\ 4557333451439186312815352282628223221421039887397522151617643990231101323079765761414478085503\ 2412430030424921681866002100559321457287676086641569745987561101226172994627840561867752295951\ 4673415881547171129791425327171243348847516601443940097692879628776181191105622147710885406451\ 7558163065286142180699613489010915103418974173608025589484955409987855083538127040379214423377\ 0463117095237604944008894328197682921511250159590079096463421764015691143152548528997651390899\ 6647074639286689643269659546952537893435580064902462537714468259063617593531704869734908901522\ 7180832557488855992308583552847915683917215749547819407154165950377387139821848499231332081358\ 6293267300902541580294962768850933649615132506886327960731444325376778995904860229022066391930\ 9638000104381724941063961942858066382967711506661573395287637986240601918457263172038473314838\ 8204742952674281583038571398086755685567167756644507485889248515916143175736304760830182743941\ 9818251662244774793784934598731107484812614212004792661428791714036050173312123053363807753851\ 1635022040912667177250777668343144129009579408818012636950480474426830076086676871544192397302\ 7597546356503215336236748844156792901573291484337331881160711622017644205085541931157869567393\ 7864807746456603001268140622371495249051365292544506338682161141916511219277107344650188026801\ 6480997576844566641486939878634478493787421937967870610816032012722885205279963442738832664285\ 4079241687723327892293505943603052149646482379461047817085806379878360754959018632475115679765\ 5424620777073246996862656504120856275511246599414767391091481580761427030397961274106903067568\ 9310734841030422965916675931413326264270969889625783654222862674927041744270514512589305692074\ 1390177368842742180288532207247283312542329599781084513963145683900176383088143919661906764565\ 5799614019761474505664832314659125062287811721360184277442479839223156861097844205393373269472\ 6715150436485932282270860528756007258917595404912079818498692426326753225085126044810738927110\ 6976135450363635828402400972737979566586890680685324649563708266598550879142072669895636381779\ 0977390323838017435579508462716356037400580866952273052095222147572004107316677781283619679463\ 6225218484681060435531753283046506684077648743455101794415563649802152756286910181312398572980\ 8712922854427873947061976865365307437115207904173295523945224540555685302643986800809583319386\ 0386864490371664878396409805450412474021070765393153627048828482947008198906379761187979061076\ 6159552138520669594807323953623348385400383811388590913744763125003944785449695895560583693865\ 6192511656037800652799203099942644243852306843470489308510754079444574598107286206608941023223\ 8388326110862521394291643038356164918910485685033289435400566730290697842733503826229621117195\ 2278903540947930170761841425321602734087812967792375329780220313034158856105556876705680146604\ 5789496818916038038810333753768263037297091224309244554481665882385591118131661979335986768117\ 4615321145921000640435738984847711087870683337830632064560428566303784490722295340562137118706\ 2503871412813458351262674519556384946026142956221797136589437990006798328520910094388540478485\ 8834284580846207096423691970216965285859856229241016558398522577871850991904722347961339123250\ 6051215038438643985690622380410967065884016917889155692883157168938646903132096868616738035327\ 1055040833642879118342737369765702218393438797612138911262816476928214256627194649606383867481\ 8304146247476227694597398801000647222927302434429500392125162282321138069245421748149718847440\ 5733968942839443779826416602041887907665112507350690926623467350059318202870385250653791024544\ 8783635450507554441782323029720876542647793973451586928633071022432357275894539688228800789051\ 7544813884537650423045254013431528798295046329296885656821275226498874192394513777641066608415\ 4007661630719508654487877119646177173523004800927646368284261796861495189115849000102663729751\ 0649957224999533689248825761867563718660078287530679794443877974366743348629001941591009316193\ 7770222436441225046346163185325859804631667496278407195253225623537032018485303980925681947208\ 4262391425064244292589495680794741579535491498471845922373875475240267697934668903196073092577\ 6329035203410314134680595283995923489330491371600699821572559457020847655026656240014397189339\ 7069441282827342371243216042908614254591384413888370847038908240613618141602100457572787475681\ 4810915539714033472018626868932126812186094062375095864368752531882431769526633710532654472461\ 6701378101286434446934635016560642108632731685171914521407929944697716916580655026974231880447\ 4090594905030916672357675485959664098477984528198462588328561820351914203415206249968804639493\ 9551972415776217461405556920790966551579585184188029607605564599854655063886938845491149827690\ 9653621863872011281023367978725874797473337173695738133327244344969082843118656006050962695853\ 1215750067161507304842415028160985183375705517718467451594726427559666668940821000616872854354\ 3272388946431865603764251081896199344799222904518466603889718240779989309287529733241455169855\ 1052547315567902847253806250749074327371881547418355281503283221822703697651421980874782349972\ 2508532722296127482908488738591479368685486864654591995216874342873680472100363570971019014537\ 4665149065227552836317005730447525749934192020995020378955582835482235817047535202583865082338\ 5098463739387268313300442409546604661852817358675429581140151311541348498698775888595189241678\ 2686006160711019447664689955096076589622035684840903294166519606271092427418786809250055246923\ 3281046349337183024246498038459160822191524499217794658705996605444896771920550112700221142200\ 9088091242956568329007570458783721517496499795694810239366242600283981411675262813714737161216\ 2067704186684071089096573972819373642640239143009805995343448917574771584658267014616363630373\ 3476160581456336916517155445363103307435102987711948503462779291107574118321968947413632510225\ 2133909972785766510991827178989757838863566068616594828392805231922617235390604063229109050358\ 8855978923791740522180792020824503376513707046805591140361096482198271786099674200125116077219\ 4908075175125552321333035916864709213601829837509791677911472120258010228234896400450570672464\ 9694532393501624580358796238474713120725846580658568214935448569378847988271305344612132727179\ 0455178808151756273540510497454495635232938330827303444309061086776339944794361949267632645979\ 7919029249223823186656764342331956958910013947308812648914565736933919381248139916265160488970\ 2291252866545003334049170526614882169307770185973212827384401546673459568446243084971998911100\ 5326792440786643138588614209266853308554992846612711426621469809402609582845501279562411017494\ 0147738635892016825671090069867482231681557236763435067193667001125703807107531952258943024728\ 3921052865828915119901358886094052176165885784360655788300462888063584423771596651725190184966\ 9203910215756389666340817765360881319973351941549128775909703532074301169552166214490573570525\ 9455030043523095150649677468465892932436417179886007070738145321017121549931537273283627338983\ 5037587809857877044049625445251701235997299250236550381266436190884013564496992394395416821282\ 8341355032434304180808265525647728404598167182866317969906623139871301638623537245001306502571\ 5443525504108070153824023483672800062105217757480195608084685875526998622511144442970094663123\ 7514777630655572875176850829198813489343396953884280110060995923413673495531547399154227676385\ 2555772986492275829484797833708747099236427789893292139714499664023786297864082092344609935661\ 2026277351743891695307786319840813920329181884297515375378144371138474135258674414265093797112\ 2681081997102550897033212787169223785012975040392196032407641478654591590284135907549868938183\ 2998566202785203136653711609341329089111345597458370887262957525217988987314930161324405129142\ 2439941256086245402686363037093874867758364500268311300951124586050881268382806955386807729011\ 8416624159802831763195490027748817870307000273655133315752415739250653706940161520879806115554\ 8712575134987510732460615008430654223775002415107215661783860520266712626458336070685739369304\ 0759355350312790304718787282560019219273955207047753584011354898804108179515911229044070099772\ 2389609143238998829347816879882243465944286425610593616587403532151018946796140369364080352755\ 6496112196689177113317569008650319084516603520460739031787211219600544883916974871367918686593\ 6512486208676290690849175867106232628479178603366367928104794892981361913597520853613543272163\ 5495642084789093915087936334420160784535976085904507402919452669635779463107482689951798656075\ 7285450697418916685064910402061658121750997955764094700079718369538608512305451815184200072233\ 0670598515609353361800447999149903970293941704606329146066237869661374285991676673277512136219\ 7063663546266701975814190680994165291739928729266766214173888644648163400809444693322872772124\ 3483116401088651205024636568749678151703342709061952309550600535803965258822045392354813000646\ 0292301358013369744322109206552408309486353077763090722024463346657811495534242074868579244592\ 4269190753856389421331964038404829041409313171336221715821468209404510356874008005265786558487\ 5417210071565397788449999921766594999024952111164363850093924801080026999149077555009612681039\ 9975294768450179317473482092648740093509532139274104278741954615438390410397690230595655261249\ 6953249532702837291184269875607547434764077432955767033411423459569605903850869451912777694176\ 5995576271235335208620872673047227249726399351390841569742848879473785491622537998738212771907\ 1472531490898345340873309652982204147011607954788446386256230836639674624264764171796273126929\ 3936561072691883205923362042553221914717372055107942205662738004854482544544846848827511732661\ 5877286981491091297314751794915997081173983938706851283657165992318779465224028028941703794069\ 0309662506011319011284525304583517284547892136370746905510203149237547992621590536617970019732\ 6233947548969131479345316429007526886721879999293968099448849514065696465210724216150042593739\ 1401873375864297865356596196202425555069423787414768203574437362688010018860413962151056043517\ 9045848271230520523146270324314232534707274632761079790890906128777208523408961665394709092748\ 5098746653866042556486972267130676177049010693858934636713655603445784707015946310076903130321\ 8618008750066468944057520242388842642058340648186713790668931095520084429406672100483990454356\ 7194875639336565589877325424508755509062663144637586976496092744949927147984288954885118254987\ 3109917277975392175277703990217635124538718142064664926300510225632601048379907793244767296556\ 8809362782768805038967500610613918272432371928985107196720643287550788375514099706088967595424\ 5066009545791838237533317587604346232928122903243722937009096156402381538434520088511110606342\ 2769281226315393623100797349751529734813041605943706259499439165470645346326289355149035412236\ 4873460902400980859080006158950965172313340536011396826982962567597797656761467420376403058845\ 3840969794516229170313461330957353602799002945397901797461204004590843756545448171823083114121\ 2216800241359486884436301787104720532282037557822018953689650656673176328154035622470576317934\ 5334166719130572433735160794615521373983659620355060940681149100312460563595532783377054412350\ 2515990515236677708210598961682430019237179139071472429565573162311841248580831694335777686868\ 4647681034818901953521799958807411969445730723076910543720565638576379091791647235229616480548\ 4958009686212004416619410400068481620686988190821892275438194978929200764834327223960194331414\ 9930751853565978137795594401409170369319454403444553172917271682704149715375943238166807126913\ 9502567785487545401800163189618869539165058286360998047566953050716251332921462975913802095047\ 6364439042211571760235992413574461669063922451369609669205302887085036536394799614851322937749\ 4828736718743179547802535695062811002372309595843466796966041166564826331299921767776669168594\ 9087944049672618976644746460602717652165200246732219016009287150535193835874513680121484717210\ 1065724184508534737717102919775999548991425189761752555619247245962901792769320015415590285288\ 0866187203938332776110902845779739191981421162382762541301352239760602153763489161736395353967\ 3915370135690148619031159149846927329693906969828608840801143891649538450276161006058439223311\ 8607009433596689285043104011276491014657346709563067997831891334732831425314954099567884717017\ 4270758869323404853490378536808315994423804776568301241879090560544366853791976168441852557034\ 4268585133340531342997101424284091760684595924774333476620510004351693423301549352383929580033\ 1983039830500976972488759091760674523704579849269087069907698330364664333968602070591037827347\ 4691998740809343372826761447554865386983455959451835046047449596759237126483873220414308875879\ 2827870109985104888338242961972945184487107979331228215102949425821023843753590418772531393877\ 6456424415163661862771460790583728528083662889503370475715696868311797128314387300310910943863\ 3351779209792974762989468416566009186433100765450576251340902621211290955175160889441492639575\ 1555719609616064095738389802725394076405527387366894118668375224933091628801439700830616063682\ 7341832406423108334811514557541888803504695018425420979357568935695681395660393140619751360647\ 6979585762221003863803109916613192368619017594045670075150704384641334374449427926042855142258\ 9640080852545813187603526952097475428519628999150432296312302489076408927653400610022547307668\ 4637662495199397676186419777146316062906846915828283650652469362352741265074740502751727482571\ 9055338988710784649230855304720681841140841776716630069376017839055207761471891059481157307054\ 2326072166479175837208779030477809572147595101688790682656020003697308068441894169755936255279\ 8074845505666233745103734353563240338610476882262209699992333775503670613540676321837659962050\ 2511457482340486704728599648489067374837468613252378875966914304838175264104829235942374661836\ 6290874103693943843178049422577344167709401427128691810579553558322065293394866465365951756753\ 9040914684841188190127005063437499205256976758333131267933375745812700716702983177370192595139\ 8340651249214382799964778937270688448043322934214327837219964328213319652480062303100554244705\ 5690794258038952153555237058017450857670989235743394741444875655424952726202694072695111336354\ 9339848118121381640820553226421492418869502599678314600473932264961881709605500893316729487348\ 0618000362706612571266631141404624214075148496376193228822233175840036855004721371126927918419\ 8586898095184930921196152915053899390520932743225438727158232076419792258892446134415677707795\ 2088962591165199651330256635911785079552673176583221768957688743629698084754610757346051955456\ 8751808194206971625835994520010990624903666394993625766537988058635010157579633195940464572360\ 4086987579297554239636839343172430691913646967803709899813632361268847715491439761457392310889\ 6645452336141592994558956262559749396531622082816285696728427047206194692732114666782340973256\ 8457761688187619939072217853875785942229563578536975858050686417277836268100501742728851074317\ 4185527573620236311076475730451135495056947691090638741137198575529321575883804822878548775715\ 9012128912742125784915728165754839622139522186811154183055014762062351293064832751803640152632\ 9426044936716945439392603335066920775008300123447434997283657305793060984594416138709686935835\ 5123662787546341718740142936473673151481111111311817236894292052181733399970935572012854914010\ 9540722697496620823036798613966554750400466361247272715836392072697889849534986292398962792106\ 3357941992218755392889759257873510296285028525925181902107762346622031029081952939430048494949\ 8832290138517567574910528645646686613449362537342373328693819413100612538174306703190118451978\ 1943659531559448517696338668256141169384567243009710419302147856519135137241862117735104794782\ 4675285533639721278213763959455666655766721589914447995893672765305013778103861743927774935052\ 3842738760562501497042239978634531512579814391934325908980604408945809791972871623409453582384\ 0332090438354918794112907657121132745699412676830249159139199133392831221787997947805594693555\ 4916941682104468951241315874757716673019515854077551172026968932828614200730235721727187393351\ 7901937342960877470116216462008192454650609406113758873963065799126449364356036881226737374432\ 9038673921872440458256132104198330816865401819096907420741336830514290141061824558834850375434\ 2523526316121979958704016906237376864240193432017707929954977189636617940741911705641245771407\ 0561351020895494260852793065772990118754948802883013941990809039699817025789526133254325410208\ 2608170605077961261835120433226274914042267303495652780971488651239168809541705466906692299055\ 7048948511861731102210606995054395892101912311088537664588757972832520670498408201276237196010\ 8512520110851265564153194710188932980302287091155544549879775883350762159890671189088708752965\ 5656001585777451612868662080761603725668785869653935955552985145277283673684947522863785141440\ 9487878555858982014336778260686560807640013442221851001558496035430070125031277890432477799684\ 0993060893337924762684543930133125010183974267823845681922080988057494360848386936201543780659\ 6584796880211789008122934077856529543554087045466947189174036580904080734103401980732929898491\ 4651355172261709103632666805916854849192270297599258727335412466569065548468822386350177617614\ 5797346133217205065924966148314888116269486594637277264776637014443897340594928739479271931183\ 9618045496125856277423401430715994477057124683851893064816137352146096913342849697924143206779\ 8121299705673282514560809725504114216012848825915219790140526451527500982419356018268149746755\ 9644421908574373703884249033468280447249107894263330218719260814394613550346333700954166539533\ 2829180558341383324390245518312046432087734304537796864609971845339032572633884148867628859308\ 2683210901602956272107176876877207836525405915088132941615007622396456551544296599879076938611\ 8615440654716502391369268684171582186213330878763807928574705922489178358914957171819761320355\ 4938420786009285456409061754332485134733596128117882771966892280242814305012579773753700923101\ 2503958721036342503987105508269328767085812720196705649919626775327101846237237075279784720924\ 2633055352003715860396049311264034311866247139937133523168875153887150023373069807245279251544\ 8141747408373496670111172179222767628024426895403032985579388404465199150920629458643697503288\ 3795913078148151901445403532560147343712658242731051809597052373669991765842549367651462311492\ 9862690481885744390333399453995508319771522542122005603614569969238111889363892779907778044052\ 6353989356954121493777175738426501327985123978994551018927234072273139950310276653126942797114\ 9992671979075769593300614669921440573477139042490561155364179610132684134717250905971352709557\ 3746368058519248941732792815242513822186061639110620977557854389579696158642131123768455755716\ 5420963953878588609003209348773869339647594157603534453231539131596205991450123020912675459160\ 7199533212931317703494991012497623684355506403523865897003875420654678815131370103652331918883\ 0013338967551366138780186260837815620667357794862496839699473489371304444461864472202007469615\ 9107286297397047634967751013372736767608900210859921722204460779577811746944878531225949149949\ 9731261214684142994581198107255722189637097103299003307782538749169845002299120241861252939490\ 0485194631300935927763498096875792178396446994140194865870988452786159030515956812127025945661\ 6732028846459270976846450367311283706745626311410722265020933279728949147347275424480937869928\ 4382881589847868919228196608903200504721229579388826567013147865286711818374425747492507483900\ 1147380308709057226376709098334260411819646659944698357996551038302868923162861546098912898759\ 3875331009869900871464290715107025197457791593915454112209596665809227278711811972939296383361\ 3149215371053866936956624612757216796559893200070304744924287243055045787542874960263044145085\ 2782366079159424974494878535853078705432589836463966730145002732813547828016461796241958222293\ 9910553146888551910819576780375337086035438371178102589868799099998289231196335448967286226105\ 9855880782346716734463639842048009774484241341978553075781165033523470789123043328353865309620\ 3608103701865661188537889516138530892696009461280324973213209476749130676450971734368831362617\ 9720699422052854646525563835397136934510053708352098078182758896958268763944533960021547407832\ 2728907792263695017319980081451967396172276243451445166680598417002118775501359732591133779308\ 7698756735904014064720463574704379742171036876199398636266122598374711711514341447894202149278\ 1499355472743627554501486160467969034359689000455154106837368680913202917444728714882848765930\ 3754279411961840906475788252402019834990642832412803190119639342662154034710122955060658897479\ 6760280197081650928916156355837455829836221785108407264651723679699620986019018374536049031714\ 5014738021633810959459920015228436475714286227451555549908007368706600224977020310359868831323\ 0997508679418154314234431157511733254146115024540544299253771994294897082620396562437791165770\ 8410832988482415796500346299401410155856081600918786905527556007936817613765617234925419361714\ 0640606208912486948297956406937842829919579798233412245024908571376000649646397394458408564450\ 2283733249601451698942926441190492380001703542675672074597526846144324931720200588807532804859\ 7974066850258199882101629711837873575884607468445329604086423238871105396864098771662854446934\ 2713025851273273712338634066452810015306673786681542632780445315873156211224932703348181182922\ 8578329219769817207432326289603505910116465847073045680604739585848701832110584071806266684817\ 0291547906859237170582115426005075272410891563003534821114404078137492603627231398256462497354\ 4219863724411781103016246369551580655257415791274926683256746576422310144726734227609410164153\ 2905779852866781219113435196588682058822707601381332214885810772051187772541466143220300051650\ 2486018231681825205293103395802244471366919295238300039165606181416450483686947398782378608465\ 6363382405969018137078394922137756067560459203149761906358014284953871953741156150421791520852\ 8971200862114105791527899249280719101209492784985057564088848960271166703204195167231917136373\ 5228319531752952243803182420233213046792613884526564971338094291919078190774229086152222328503\ 6363754064205758874833846291167436341388296952767136720293652246351520890644653508319186154598\ 5078298409997142885786372523344524727625274230711007423368592521710391612752448408999145920733\ 5881485202280089692388380069582040107877387509241553538585750455472214116774796591938046694204\ 8327102010821341797661579064064147870013368857232287045515421957262613503701180169386931596085\ 4841358394765696093503473232328975635377228487789628253166164360406388416523446388884939331920\ 4977807387885819252286500884773256079878222770369142466815763583947730130614932098440418665830\ 5082904672391783726267449815756007707486336206087847917223744556301485965501560294077865065646\ 4219914013760448094333670976368791579678477278572013661317990637385453546665670749443381960066\ 8217518542280776026856510209214450692790911592073361089624762034937087593167370917339716827308\ 9933663441650135658066553581004063247849055878815268708721239409235127815651605120800613358963\ 3433230974882080690382702419661669010266393993313981641119433831675567913992074255430274353615\ 4632939540419595797855516288921771587314425335036851072967041617414569037872741693210379052584\ 6832826315628609010068627840730766634379704886839725081004463250618122779373726054996921457770\ 4431723191837423151082584198221258693892440586180719372963173108775170408790830732868629498393\ 8029335288322138689023918891289835929336821332113700940991474781934312871379994269460624049782\ 1443393105858601873187158681238985344636912411599470666869625116586189427303147024935143058329\ 2346735795619656344545214816065235716431901421713718137216495736636711414650015073363422332955\ 0365107519054860450149242868408986685684698408908177767234886754673999772250882637189726722473\ 6569687034056783792643466965001353371132057580753309875344407374382265945097745706362746963311\ 0594835000833674061900979889697462754569677561148212458571765465395714925924194738052522852883\ 6542451605806476078503815427922517795315962020987297605453176916705223160045393046962436769314\ 2097017271707020004960355314454399005930783170319552654520197469937527050639350551034098451751\ 2954858878717871143400662614213094613710120407152028648576908510274634026995444979824163222377\ 5697582009514819989495070992613965782780776112887338283980660239728192517195043108040635252785\ 5426632749848451834341495429851715620918817084136349748021317296058140144134021535047911307581\ 3056410188631281765225940762058185081294564554759541039830420634829414153706264664071942095294\ 6312038236939219569133360692987447417239599597464350655135657217636149910540326610763063599200\ 2141917799119261610510943463268954513256107834097382024461440061774432037748560161169205643521\ 8272292923108410378751647649928349815640097164637698820223707000239140308736990730706619530236\ 3925183103197288358867501948550737687142811160227583496310931126512772842505473470272527679265\ 2802221669834283062395823476875430733500657149271650889957848938718370196313726351161647708252\ 1116466518272360816207764116724188045616956212253611591875310309800659686838103253828382078402\ 5964505525239043805000117589632048005513115089527368536820819273411221773039391062016713474568\ 0233719976564089871148085824476495284431814668498905126745806569089136269100402295752294576584\ 7726820294163843663191522381873660078842776236168380655028292922472462862232677969912748167535\ 1325113921660626693904099483268182185527674921462352749750726231945469296647550771202743904846\ 9728582259387386415609103159060101943321457801121867143759453796912343846122069864925049953795\ 9494780407979407485929254691189986243203840225446777983614690024509760845281995274354054504295\ 1533827391811196071259681967481694678368690573050950030010078086253806130361019163870018779993\ 8257573273069478864435283836431210867968649460223187703109456235034385591138304439191347680560\ 4312954950171253871838617302029078204543718682054248573220094900614178431289616756029511915809\ 2549200684043619000184272966884647590281949350566791071903378319782080213780775998822130054814\ 6953441367841462374336453313079634284257878717903315303297178750030328699623915864457256989532\ 3479254394883276381324319528822213994778096722039029406168311060761208620608134986376085349486\ 5340131815336372095249133680699372110214488960397765380071090647809337760360004832525253190874\ 1667318440722472875714950428342316723418840316751642602897960218218078827260648004480160955201\ 6261653903343193534947470858414396039383662740194268366051037369809570592049768514073181843761\ 0920779133217485567375729387735218036838401107590794472567835234201760265465755234542540370294\ 8378068043138579703737139454211645667977083288964478301488956333924393170128040897699453504321\ 6889678425479083282017849131712074133636201357762607043670517061739592185004781156622783373131\ 3489682061609641804414607318086152434111783627339548793787239008023212105363057930017568932447\ 2778066431935135799844099193033994892550967714635336583359265844437416997621113062243327597691\ 2114256737591767861307183428879399662328776697139714097495626515268549023690432630126782244621\ 5591127026832562283704141097632347053612418864948518696433530978498951412788430215989874447806\ 7445171098439667940593551534698219907448287223664558904138241989263092344500561548767236350238\ 1145893052389901604591873227349810889760319697731265997139962794801054102689140966409525922550\ 5294678833029264206628503502464740487495295826409454187115443152157810462103807558938533671030\ 6466503046588428764787430222017417300498265953974037214152810359729878021070261488287705893422\ 8044230069088974658105588221563790180663241361110157709734484178845792425160413560967900701638\ 9992685925870239707555326047542890034687881278271520157678674168559707780996928349069616103713\ 6990026080122921410977598565226421090832570140459328747875066571215259757679677298836342787870\ 7726172003191621426884208661205057439345634592904447074963493547962615947829613918789753109577\ 4992811404928081447083709278477609501350540551580163644227003259542713087293660532914449759107\ 6772532428728711582962758985257772392543810066821933281796819243675673539555440330929674854526\ 8206902612711570153567271896171340766325535954536810929106446434691575359622475434432329867040\ 1489495227375867315705578940547579777035964501958723452999100828239236099059223019340816276582\ 4091238541631821953869365818269612093131104278839775829565474218939964337619982845091410513018\ 2465912102250195994313177480360442001840327333642715546220112375979483851543468614933606465477\ 0799196433218352766045248645521929275469980829145174191812399425101836717223232301201050742376\ 0147884145502206345929423228807337222539756550162997417232363882339678585811122000691785496903\ 8995102017992076894712310248298325742387779824764265492218964125758832259826989909202565596172\ 7911549214166933190931383824772664471471879085658670543468790886102272941566737937432343848838\ 7768874229835785731395535745040859479379341547459309733166572433409867720059254622636897349986\ 6722311946422718828428744521672170760749634587927579950956976504344678945071599422556505772054\ 9822931343343946265220569026981548345789717740130521010569971227181132901300189322541515140731\ 0836111815895493661047471535019431295429691843310462626639512345916522192253766435688913265561\ 9583748673905785028558876057698732900530968989173471723137761512539540718927370873693946950252\ 1150669915304990554091808358157270791559360707491967768441649145551631302999498268009796510543\ 2168253263156567161559627539467931597158562796924794845417465315228605338679783225951604501673\ 4352332403401839924930744484679330414148338999750135001318155801119438943862308601251316577609\ 6304068878977508602166918428796754047705941737640544145645841495974536914147516254630197807963\ 6768322321963941105057189485165812796402341916138572032152351453563507836310065654050031686112\ 3020504607660730301945500818751248838844366824918756762720662975229099515180665621801901239176\ 1201782057380518738545302791939264959488545304017870004644821267794052022107373078602235660533\ 7380319147835492750819916023077266734672932088413893033166349663731200623021220327478063639159\ 2534553808486633502823145058197671819649558986392167421188319863453951447993894844305037964765\ 7307738644663714729898222332298974986753371500438912719758246028930738181208083259798651507963\ 5263989002096040455581138002479279307176155335963173638691315270634171745785254904823515097999\ 6582460010619845572414334481213759684426189064428448100322397507936726386346225274046860380944\ 7912882911935464270228771042777657863903069640503895910105372365947940566709026565002358442759\ 5387103811815183118297440580821703967888226994607750802525389738545458362882841099180109442399\ 0026665602608291969914740256209847439014955349277811509465025003362245509572791141730753476040\ 3120188390407855661753453205792886900082452099003646962785886759400935976798478871365389833009\ 9028964646156640561050823151349600282737096045149516166043681022525169019414950726775691376352\ 0154849529147470824647046400173828649134933581261460809816920848183147945403156723530325657555\ 8621761656884785190699550504561769191010387843974505540903495749063458110916564233186821969242\ 6283060665546706990919864826652793408965735277206555963773482975384476486615212453735841251149\ 5594711012551945939224997258173556183578026627199961203162525263895299400893077422140300116969\ 5861227035343947569908628468191913738546617885744414687718598360736221069304238683299574342241\ 7099921879290851057074221694915587816235882737389059026571892180783223307456152358988546527847\ 9779255524131859031878981099834107386073015945922820064499606000887961185926709654100789834573\ 4978382843036529679571839044194784643995503011668634657061216110610317493103277665469471198692\ 5078524590230031827899280344566298958818726186515256113384434391254775627784788201380235749709\ 9205419349398994093873958552046195827428894490853701361525284581993419602010981913638759673750\ 5808056543375959273106461354674225488655619670068611779379653807735674993519277478129119083844\ 2808842257029640443375693766057186774103055292540491565553681087076289514404234055793918598286\ 7236125417879462212907286401710013765832743548670456889248109765681353863868631832360990035186\ 6281599909266821593809693473073109682445688005273993258178007853008144166427660077798057542562\ 7163706342173586271865291183844487504548170888601133482814027948481107712440812797541385679489\ 8729927493315575289581677148743542641919493801107042847288918455740311830882596201123335631023\ 0402721484022252435224616640052994094779641900703433533170987673031245098239793823730284119007\ 1383135554361168657035025678942274155625733940101375711930303494082281208092652905464134384269\ 9317196072195017086630226246943429000984129175414627450555172782620255626262053963954802772505\ 9880269066182980114355627765711174985513358150868615480035565249197902151490061153032407878335\ 4716559228147347946017655130073864318906512273016314627954630102997743604681377918226787246005\ 6746146924131723323015755835571506943073456416071227204570590237191166732048434826409473724211\ 7846406652739419264042100569528847379044404495562856721840937463378380596233285843289523362553\ 9024912004591799603738274271399304522790500086067307398295599084156874887210853841955308146146\ 8036537524007486764299421963941865887479860095274774814152877616551301204760019543146756771378\ 5421041329901897489952223178336717954409249294659473081996115446474813874799523219220710689773\ 9525210299370134750866112012804097613662687410995293615964069452040555646543014093605850226095\ 5337690355988225388434114241062855544272168438874023989679411417505524287868078931771505763272\ 4390062457960523658327771466626078063398051059545046879505986914247850498412855163929837574892\ 7824326161896120894604827295100788600463078897539481670445904506134002508477106529524596716906\ 9144310240009436705812633966137894274198403236822500278297246511718090394992679090883058824393\ 3266063053812836463704963028423498931264613572452119329382644351437442204652633521975061776390\ 3346552994757887072191466578589462796305914806194776349527556198587767732033351555668124817608\ 0221485681955241980766888933049674902874274845816963375435628043324264882312663123925263330130\ 7081692910619302569691853830583061815779632484348540485558152530137306353609592625470425652790\ 4177120994295363975658381240976477090738472242000421261891325469265588043299426456507971025608\ 0377645346221011080542516405140525687144904211574953047199857536402353061631542876555297333409\ 0351169825765984258141540791344868898254876767673411486347412559649437013951814766411334789497\ 4101317679942735254114617564932218885755670719282861666597208279032820196112343154428881223755\ 0391916538457014198730533052174716631945269770466321947594816285961777069013248037283672500669\ 6076889514867066957593896978312669137857931499829889569011621232432934953261985041316010026536\ 8475397073372753817941383589217055824583616406688326306645176928354097726877404868952588360536\ 6394076872812134276613439969668083449352084638187146467300360141824926279838484835953798603272\ 3683987480309169025893109334695197715725740830698223737868606124485917165519549155207056670053\ 4829364282792574198754064585271308617982734013338358747675627411739375864290225080306306717929\ 5160502765162225463280629702491635267435037434003657248839624217064855066590778016843379232083\ 4274283889202758617303965866651060162973044970668281902956811369495204921749094811269407996351\ 5115010499027784471126440622059193056786340657695105760542095256648485275727509357452477767114\ 3036465864074337730613640975482705477867951398788076519400165200259999486013001245744348551688\ 8762111420201524496243844199915851778363546066026272430033327606136899481752369896748643333025\ 7613306072478827749746404049755443919723532707251729493618819885588080194996192913638883713661\ 8176351655111827385631448758871993620570436278759658964624629962988766150971162287009805836024\ 8373612972964269477355848188567188374340256819040502006586883092992707420016358173211233885744\ 3365613701731546218723904769505148068991958700423724177798764576798959083128560627643036575150\ 0423066099689758412691917232125880455445769178514373089571174804143031489379371237623406394568\ 3694380822491132232655343638354680986702809215267774190090655615344333390653136218609437796621\ 5349996700949598264746224090963383114621762502012508452062425235740786906510255412593791673330\ 7046245538699429697566422855597353832860850911326328021086249753786279154593346613792361308400\ 1080216335828764177585366208373163474173870129179038740529706695025845307912156614388512063889\ 8528694034987675176810432258269450385545292738424545318548829920497974846030980507637790524755\ 6138260191179914002970022369178775624569254113377223775248775877174460340587757905038146126750\ 1981055112324610763141861656648736160384502283985439794222350001535056233784508521393170647516\ 3503900284305496002843040431446937331325615724935407847580953036108410619761931436687573182429\ 3426239786539828774710245888444602552028748134131769419527800329205882510812268330077041138030\ 1117032226836919972097053312091543288358472719242261581433329784877006680945506526476865966940\ 7286986905167579384365762762633621701303881708737945460253771547730607224895532434015315256085\ 9788713364666718680916297661613440498064737341006401268767575616847836419237716930650632384714\ 9450625462913510121261585479411924317219202229859798829399117418826389365904098191323664366569\ 8380848896368767763788399395289304325355081810531075414788688742474486231768279449817695917039\ 6715339492018711739592130551379787943331398079168596694815722867940241471490260486038670972485\ 4454943414768113081552174733164301806339593556093053393087451963690412267049266959583773375595\ 6115655415232879740266386110936718650144580463511791206237472582654265584495457280426006154949\ 2874585920779396115394718653426832188770025285537935156897489829549207188335956710741652317824\ 4782882355030553989428419175854331592500150914128584188603356123940437961274391268631908527284\ 8298382237992707274717426329752685421766067827177428396536031749715265990115263385999546737971\ 6935064599015473834969618200713366761706762137387975653403380292064240998273255931438071033300\ 9473621828764210308387021891369522398813384750761082241809969371593376986965876296358092947538\ 4307148025739489433838267123109052200066096344061853908466542390698451570555765864686977971384\ 4738391164052557731853204602295817774215457905243831037420263616145166820623277989117050238812\ 7292346575125252020030901830060253197731737301376869276785273936002105204221818358233481423515\ 6158789169013268191455059425568822634535045213044043386291336449406623671946701178629014782683\ 9758550955264107591621217774572729139749734721915597511630696856698834271714230120827436667310\ 6367425371476287065999618789242121757883470015145002067090364349263064713866250530431658419616\ 0486984490682890791818562980336843784333456142740497705372795426121200441456789853297701368060\ 9631662203980189303800757308526599422293500468217945315487559172435299187292206276248437051076\ 8505008473862355713556459439777326801870852873798166761385824310780217546116245500072624442235\ 3180661651349266680240142201025615185267273306420854820833032707036203134826248122452124901905\ 6005787447885695392063972437888182811963858638164257822549531007611743641570240435121479362619\ 2870012209970926723335668717578789983879558632849362475623130144207393837979521816197242505593\ 0039176104795128309599355456298682177329575307984376517172250864204941667171396190029860024018\ 6763906009288625159090634965937816879606797107007085095582627648635862172514730952623042284623\ 0525402600681548919722933900422823655607640004610142625856573657266115828758430932716311524473\ 6283424271962795216504067352646647447065813584549210749497642793534134859186351205547980834541\ 2925874904926710129322536397490606484652802321707503364186629463809373515202850676272513003424\ 7561373850456604521727806526975184346286041505421681172715874231532428396014217340794252150370\ 9735509758922854385812421921864855591193461039563690485737377723089151416263735993856313231080\ 3079763890678779340335283757134363712201454769929893559350046314748430734713695888148637733325\ 2239913911606618152175248033303471279142406602840415538846120447424503058817309457982908551662\ 2117830266378952304037893424334420085591236771336996946804363399970407734404704892832377118512\ 5926735972229061251597439578597485017482954479957665397548504693469519280431135112834299858321\ 4554188323689048752945781283680624576249017164424679995649076507382673312708080569922912938181\ 4403439935252259151045113709078587017822467639847807370641493259816957900823541862866124047305\ 5591395123282876903292229762430153695695441977226165471839118199261228596130714766731914228964\ 2869559981561845143511730330003709687904680528430031391485084735293303606195575121928272086530\ 5831244749719380820885862574241756530318538772883698570840446024482219310938159651297655679749\ 9983391588459642252646789188270153229196989445704181543186752509934713764517041873999557576829\ 7784904028054126555094298875401471460121634619717371080465811043564902125604424055643998727889\ 7571581337981277783254222619388737561723985054309348116663181953821205144947367352792758557671\ 5265472259932275567103371744279098317331926780395924612077723496782539822909011021872878586987\ 7453802162827672483559835121232607868661416774405981882018883729967664437003280774262491411429\ 7720983076001626217368921318650347874671449490431716561018554790639643300531829377788411489982\ 0672346149472319425577791215782304214565933739628472814414489455168039578654059698173977670450\ 7571153397320675931163219700047322289885453725534115653774420377944616164557617874519063958180\ 6159741081652389710818868750830720145882486883987157792872423330192069490281783241462228935787\ 7063127696742447278104298060179873891202763387648752161746892936708897548146322664992386127495\ 1951531820887269303483316756678912102585037038267099841902285295992906067097749053250379989872\ 6587108844510829024607945246129018759844698587886602077894225556416163822280576023914496326549\ 3929108356170407119668740496396925544876272547949869522527495804272626294449176779986894795601\ 3754754159390356838017688698016634968734461964325848614378518679201440238454967073617660388403\ 6793735102919607807906908757115945712474448953978881118796221435656770910526698314772804204081\ 2324256233745703439776301172571103263596530973758668555903745224780901892794051929592360045153\ 5625147215501130423900591368525942196420979864487081345188192787598177371584166360563488892274\ 4936790285980959457894215642504306216919214980458037495831677343317570562486721706150805651705\ 3448760615550057157447715276117779480354329401235072986211619814888730557236801076192555099463\ 2784517936370990833393762544986819191528793304117428641312181606571171947621561586739433079825\ 0967815005744769346829984414360713798227656044954008768584598861842837565981766025854649437820\ 0767282431750471563715732208027090702327942602695640777540947241387355990294106409355177098452\ 0659046479088774941058807130775700834991701101766808616343512435113815719444285178065874535618\ 1327633720609679651047952185791980503456405129593410283035609575820124525927724230690984416885\ 4064510092983130879815473628915264225272822280510290749162541358281341060637533019121015318152\ 1179297030939671010788049315849404001055792189134512547989603248671739626125609447523479493755\ 9166003178252746868669709940525164090520199743363093220189615467295551867115244613946253560796\ 8229585356938646514451346931424574167791086190669854205903318234260579177804486379249485326683\ 0586358643143016604558137563224624657302371690724952157146232727972849832362965391429380525162\ 1497117731183313924496453940116308893290044595049457929392008892093841637248752108773043419378\ 6035872301890470730274686768875677788348717814981644009913802097227180569216267269628540606292\ 3922730815264941090596649258847221903522405850312759191956554419029454722327709408724112633394\ 2623195856980479010998291549049743897377052386229168045886299259253651434523366298885225685786\ 5897619422708635652629476401258989313710462895148820619498335624646680952878225238694795567783\ 0312771336941117185628692723980451411313990112702802648916854058237642651164527971314678733263\ 3145543444399639252979269255851735265534234166157332487101747484205738231719162802766612094326\ 4414677987030336112762101544620087864792507942863359216480890210277943210263232778691872907355\ 7421834355632185478884217033440151054944914916073561488696757767662377459349494224669472904565\ 5600651040031656698959841402541812872465907832877773381419631902572175202353369764249244871748\ 1997358931634133869971892419894872516834608138690571268200822014031395023319493962134212411019\ 8354363702070125249904036496687757815038457430021303971266946663396855542158607068694315820547\ 9577826302629448207717747911660405221844267422640730608259866866516679212620588668527998178550\ 5623926477282737216143247702640303282995114556932108502511372358767166980724994376753874531267\ 0563268802182287574320473932330469595960282640566430223394558951505829201543785923242694861520\ 0039188427740481018803463584078366518273655972187385080616408000181465362526428026889896802799\ 4112500444992596369095005591603533935509040367206097579783547043083022417692659560203474449848\ 7218782449801870037641881289897596371148247282686389594027964186444754142486505066742362814056\ 5025747113629662581497963129581961225597544143705780724156143095258755101707640700882311627830\ 0437484545568683698297882041677634497525865192772907406839420924974469194639184604635404112113\ 3371917987938452497743539649856829632002440238547834048393929866287798979502151853187229511263\ 7857089376947508121648779513243910311398038131923737441031910236597498924403188044152991223393\ 8955472408995906024875342983844054843518672743230215081865628919697693136856246200005424583928\ 3538269518697261933924167102495736781655715042823475344923258745036291618705806514591829362849\ 0464533201095931017495053837545898902513131494154700747194871261466894010230732075625073015000\ 1967970786171295368641018691319735761710732608534486367773992816893786257684044396577037980283\ 3616174728487238930544253911795800344672619062443969379509351858264319095034950823479912101339\ 2858713363584819200801785342844606138051835208772938971094900822595991523005317927292748431128\ 0668655896158147077069545741639696914213216411548138302276016092550355893967049506645452775811\ 0736620206195785951830734558521147967219024634013973844050831381189653244884313865227300252190\ 4613012959193684147218252203122619757960524607681220150379802930402954348644208576249075310056\ 6567290406057601386255046079398111000571007118176055265449482447798075279131926630890953038862\ 3430244582893383002189305535802887573801880159593136679210425677118209183020257361902577430286\ 7656731511530788895355366784810056787280238747348222295389405615049879549348049456964222391409\ 1302624154653519778881511983417297550049151306442466796925286857409231017257773749362150855478\ 2171355255630019877982930377420337888537156800905353409814506432449117666403696037610923281324\ 3302897636708163086724167162929849573859194557045001214439851251131584499489450873109687128653\ 5951110837834100669958213026735121550092983012223463942153173144805305901986370141151840535623\ 1143147020411115291386919307027770084887374079049782007081309885591021744839345717944264208361\ 4747623830458892088445870837914420195988243642199720611229283434832863437534105133138555164233\ 4065812334150146976393424513868514742112359056645313887385641894522046368904243188407327405448\ 6037608021484223320756042557584994627383409289525291710074575793609784753453756995283790880793\ 0112357710225129479013903631342876995746508167893128715322272571360872869085226440606733121356\ 7665826350182216419222179682543294072421873315625672376328769246603698607895826585140301108579\ 7369409946527704937075558095388619253038856297432540498593946192631118185351734895794028656672\ 3416982807185209136227275892810441477150935097677653814643490974453013464847268552081903239220\ 9238523606638574001965370471587269470912619986385256636270966923964089772319896622438508312645\ 1151383905884523628258318935345476244738483570919244042634088732186982248397092701300321120700\ 3237935095789401706750021463855282835661060395632160176214848651107889698271553506491878526252\ 7405781946766024192949423164262081152690322715461383000205495184297292434178198693596907758308\ 0800352971507593056407786388982851151289560605743788709702062354992624611447262259985372638526\ 1827424359165597007126934017230979402759971495293164454014540033284770264468204826081848527700\ 5704964598569295075284293742989474597903631443639152666725884041355826959899910548620469958813\ 0831378073441636785351559207855010647649022654768361770306968638013244768982493909146543780252\ 6940155841879622607294685155674953744413871125201521412604541530704323736238810940068785159327\ 3445474335257463342053762942055182459103326246295387520213966811071659627625705954187543179780\ 3222988729406990762341152068805636573216303445192748211826242226905626849225409610022261302572\ 1617413661219531188651691078930393741575108147912015769085022932570198229339456373770925199549\ 1061173001665663988463720108925904655583559933684784624675347006100029260872859721533887657617\ 4560930470895224681061454759298272305069925656470889127036780297211125744458101441196168183171\ 7768573866980123377600117302361584847395003006025128242533119574165051008773574463666013723570\ 1525856330529544873254492378678354872546820588449981564228262437601408927556766385420881129327\ 1927962328670626255410823822228559801660868925620874089681545786195527472087654563039144918344\ 2149069103489072500528569945688595813377521647375583791779366861590178212564016919804208037337\ 1905644945964829878176967191000021272036464781679390243496490671525621610285528693572573013956\ 3300261114103793162264886858587443294680563469627245653461350372108701382457957758651598054131\ 8845550828794178430811509762356840094972677397571272729485856201982553604922077053957315876718\ 4594708132605848642764217898250722605990856446585089275886078238847331256649561209774111272554\ 8352903534501123024339595889110296805848302363326846418032448936988654727989880824076941804864\ 9078892626053677602411350912273555807131913993306979932655113467304735749716828761007427894692\ 0603847461425100803561453900717460651399262493541131384041898343050775998698605196404966339777\ 2298422982602569572339110048259234731714752477935790386394893816534364231211762073293418557177\ 6250620072145119709830772518346032175827902549113525596618643712322756517008445330542963911354\ 6256551231165889140045721865285741583316204809336011213837356926173864360307741239263145126127\ 4449483133470929564541754436155305845062830577942904488073798264870399853367377838689831816953\ 0812372528016286193411494424092958051400277397065647542387515301035893028828199845464270739675\ 8107132128377393247445202401097529067462764783276287407503077706290062178915419364659481659309\ 0057098697322648016521264477159694504667368254166456012251044620641734752503121202599521246028\ 3660856715283183702096100581826466355127390385414085709578680365538036779260770879230737271712\ 6152428000461024183893262170826667724983459139162425496789386049924754798777493965057712773482\ 6300506558635449148428381007019048975417074761222383172674906055315009477584955328596205203654\ 6910241782466346361263072789385549682685150156005534954384329899532301527717001256578133716361\ 5043215773804862555693748124074935223130577741573518987398694228679362701285155289222960201010\ 0892647408893405466506164598192149345292168107645429857362007641382153574429662270724693789740\ 6332728504330626833034013775547685203382256757348659374670649460052933937316831397015339027541\ 8226505152744210893837462141008082874337642806099235005954205232073535345384368306597048990598\ 1569044850344914106886701593829291825697078501346351870217821968727411566380722799089468382378\ 5718832640256104378581591837042646681889095373674889173913909056949737714532124002844629961885\ 1065016715004721012759435057719277856120565870663306562446411838570286747571963897693572380973\ 3083021986875292103491797983916685250597100335948165539097017708837243653962728703155525688052\ 6989880062429539809608125152313948939991695764009724472367180174695653206536693334549324331307\ 7620616594759017585770359265987006825955346505450522882672407461572444826955188675896596153783\ 0077335018545479752335063734174339276768445811719115967506674573752205248409366305500337204689\ 3147039824880869351387765484726634196834173568456511850107101493993607017582831332880703168575\ 2492034741857892379242573600584502539163823677474553607704335823585724908225849241394756995258\ 6736768512378545868865793055304866246422092271414009977795964665593862999346776199429430278724\ 9145218235429212467736497098139012515723631895962865617864951880690112453850755835686968144021\ 9351163447412683467180885868619126193814859421151096950286262092569968212967297049443801591351\ 9760413592369508431568312394712324828495364899486023383020525904259672037985136361280650053035\ 0920190921006502061567932185998624713087326465116988379606496348675085759806314440868335391742\ 2656732524370643969270368393417902471285618917510834526067988967625574591064050498885458672254\ 6572265478684901534275449724164891605051542515681453969559232478727055869677431237701965811136\ 2719676349107475692492626944844607259358653310842968228964055107934622796271399007833040126617\ 9221699945697590910634108854769500697657120491987530859525591773702902546417094689462213459786\ 2292373987509312460753889986322366013576904551732146234221864864394715633239357975426844895932\ 3172010355186097452721933677237555933519612521453380247681611055287973565236376883045473707338\ 6408157679691626929255972383226757566462454593031818298821837032082388673695862160188190107585\ 0568071828634171067280294374083883262389299579426341985094188819202220923132344399926877896062\ 8457210418484028071319626598360978322915009039967481353368973564020030504673027085116007132341\ 7453854579845320926038682916145193066145916314471354340639960305948967686024491648896104046012\ 1955019890827415582744849096771729802101263565778223246890141142464669829778344980209868781475\ 4806510079142114305352634941764148119182942056166791112191251043765720923434288492830357228341\ 3413272827068087565371717405080511987035139057121162638669130391353302307056380602148873549661\ 3496125528460357688025681731207540945103594968613875446690162490510899259158294352680796293239\ 1937581817143632338026872382946403514569634226505950399256379980189833077621290827354196715253\ 7150883997035843917251684280478669157078581455611893323000609208805588677360884475711657232753\ 8619229717463563582889211456753585947295574287909803689687394375805048362267771264130700183523\ 4375999201102749016663770149231210988226327830188073811410559130638761234352033520960163756547\ 3790131681280984142968634325082529375273300589159936158236239060773177603257774842212935278732\ 0076460270365412630483887618835451809115911538320584593742555734636561753292064689552068982558\ 0761473650525310739789360229623744851832392575262484006521607629482586991276734049311726557457\ 4376270970094680827929455043159459438889945106194527417715986943582150045197124103982908128974\ 5614365974321565950508824044979641030646753875494781598505740503065270584173848256440152090166\ 8233414147655139931173703204818963470639736491956940133368151828271829119302606800418008275611\ 6197021985501192582090915514904960258197387590052113724691664275465569397356161673572994648499\ 9790596545862797423672417086552528058613290962802932878927096846685523126650468122590806839601\ 1476412044213912842499652356760121195519707279207905874535240170823172287136603060656616759682\ 1593026210721285675907273366759980022603244819815545336477398269949453443088294542643078605288\ 8107524617012009732205151819995940360772124417342418122937651110368275157305626573197002022334\ 4579687081452620382266571434033816013158575935435108268200997830888585666075040335274406433291\ 9053106266389394762145483665157823572119146412601918856391145119970482960229208533988699215981\ 0431915034463729853104086073683415707127745741442106821653878608703143214670612029734896604738\ 0141650701520419057593730941698036762486136702337360976128342260080416459255913248721978424722\ 3401613861218274004746772983911224160021262996849118822187190755087451346286003160486822109668\ 0329213637716299445123148314628851940974143733846346969640012867662211614991745960699758817757\ 6138097123412063557268892610732558742860529991097522361409620149279258752141494687227760994857\ 3093391603516660549070658886094655549626631240490339540557530332526334634183123725462762424675\ 6666228772091174866778726192884548317646428717065004529703912847123203778183200500841564544819\ 6895074149963061776718915867592164549569396252570844810516967779719027034229167022450559169794\ 1937198336526938706461409876228210666560758502990947264094616659120667985484213162549450771186\ 5554362699684055958846466208729853428121854466091492225815979975860386945194447761134484622585\ 5329874748554466834768695342217023181518682808487636888962377643840923375708407363089365269338\ 1574110238854823553617885342629648501587959561680194460460449154297842667487762352723448549267\ 4548265666102854523546434059937084975480401161534036334558351465215629508716155649668679142327\ 1300583186554850747476504356704545335167766958098871656385897548944504698861675106489942191275\ 8748712520552982250357176591872640863881356749286656880933345518637476049988813869481578430055\ 4485213871608083173115056014574379873934666426303135580301063701746714949142002661311213969737\ 6702648231707756872643998859281217933333027680760271753048784222134305028596542622674996570886\ 7675983746884585527570076276706685452558624688545405843696429548672403992877187688685699380620\ 0274121141027023495379479762007713224399764650609476410711658062877888296092618388900069349903\ 5408654437899812186026244638270874240801765987512334999386606247739521396016319289056092027020\ 1928308829950059285445425965675980428403121241364441659905392589282121047152264506445656418014\ 3210041021761785504293213952061908275203288177112107409022601686375197514452641256482051370716\ 0368590786210741506217911939016071450745172980022164672795719173420508584140496026141419845802\ 1216401246343006874818359449551834137822438214872685016906188958646228377258135070544434935457\ 3022867126630602576991680573015640907560483896013334349705580570548602536595349662751778371150\ 9867258181021812240723528200860994024615292495786134552065697359731867991229213375292560350216\ 6423763484295104918381406141986728826503055521864159773506378115670601030299129043277392671947\ 3368338597701583629180278268598585077413541706467873211406159501189029245395644407383139213173\ 7970477645697705690504371266272074432501078211216211020037845320729469460844554740930870359532\ 1972102962315687403223651980036994232870107342831659151229057459034190267621432000935543946296\ 5948371430845982004427576923738214791653084016836860711908991180216871329457064175791727018949\ 3122018808718962382993985476705178953374193719199506637752727368137339246325012962744943815230\ 6290421464027727522321727388823715947365131545145337139684655321876565590405528287247073013418\ 0671398232633660965505997684956231719379034973370327360225386228813969628423520233882024674648\ 6456439291872168934716093844101930074516454599746778867042108994722175185522459101825092621492\ 2110890141926323019513869867244410902019216032791343629676389546281558104194854990117187686707\ 6243624923002186207110298370918503438697478360872693488992539097091823083139713206297951425596\ 8467440117077233681437208515422872881243514020017003768035851612408276903609939306279968471087\ 7783582374309922812499022373674040182436798796323444895238362089909254867704529867665769842621\ 7210377237608753501526040081244736051905905064014866123549536026982615330293391038682295221668\ 2910127516914921583792803402164228970782980809523214662259220352809191565577367474906340005864\ 0330988597241883774047172960509836727845177621271950664189862523040679201594671505129311925494\ 0694370871893089734429029315249222730021768942785729695579897710980859736693014780263168053460\ 1343768769827978005004779426891511377299694512332773992139700080338943327013308488702795837070\ 9107591273199405934463565906237221096616218145205256179538913066024789859835535363067678604269\ 1513060793045269790987048586087065295374116142143226969726895516592414803815763496441906778653\ 0486756378067639931505451665238237789119963945167955126944329961238808674756730597546335625450\ 6963558071370080766720959741113092215445946165529910099992283393568013632384166370219392068719\ 1117225059113628458238566541516995908903063866949942747385311994752007024231317342130112165257\ 7108897028933681697214800620693633190257489543941655595016263504101472041823010417121542516044\ 0238220790529663095466385304851138284762446495031652664393121460500158596458955928363597299339\ 6770200241129745110364011832593831221713568445270313350189980264730807651159154300310833921245\ 7303756189906139403056834654053140637430893249111736143718741019477817881421079590489964617108\ 6916429051727182962271125612902855480842645205767471218920660070744559963653848248317203906592\ 6249452667285213938931778708002370168090789276450313450451624295086821336884749952489212114075\ 6320462575734963871891816969837858916916443642542060819339955756862184613100561876139443408467\ 8607027684437658060318011295712135183054362283691448821347158028753802692346033073801213501084\ 1227934660139937419723593064878162589344987807299352925653393096484881938835074806773539725894\ 6425339608252147035242695673491431356492051570239488962131652108991544162643508770296433465530\ 5165222522448285132630221217821524816942368984274422766327316800312403194440543004533091544639\ 9073230080690353125459638755353954811767292273049581592079573346100353449403993636666772995070\ 5910645505874812300131222572217954593038243652972093534019905890286440454687273546542420893949\ 2610108117722981077973411362443254492525875300756765585515566162725574194584924459543091031351\ 3872622636190833931686779104743610036393556401233624211266438636197838147946873091768663083528\ 8580125683169083788197738165892491002490494056752070217641935644921771662713462688705310983918\ 6547101173688824504540114783781773532396573216793520642019397713057955571570690637349520509551\ 8791976412180230424070392098418911680407925546319021584967499393072119804286378625104442274289\ 1833178416638981975176350587653885248488187618664363986813487465155777288651058847208459316605\ 7110142881159128891592473025025923407516195150437242321457142079939896758422255996358991115286\ 9302615926196019441038709590513555272710042124077911238420466420210673274485904446234081346740\ 4084594838142943919749204023651770935777859765122248023636660788955477103435748531061215811334\ 8770880226215449994451717850644436694452171624264889179068322956343371215677497456119119790486\ 8175995141104176649464319454531885275258354362172051943011213348193246817489577532897805696721\ 8492029549400491737699046055963722382553625519736898541997105616655891298765368729761670459362\ 1211024917737579748720217950722367345752845599816419292084436029340296946269798353145829969163\ 9493947650026928368062684496867056374806323489934262168600705118011691655790348325391177339248\ 7245397577412297318107099024024882718896447319840944772772515967585665834698428683073019011443\ 7893839921571088797127610631259275766807701173437398957240285746948244197422625219800543516199\ 8413001492977631712267498402068756766793183783551853508299459888773172217307653422426891276367\ 7343041105000558466812049955132228992338776194484998145413748684214867257803543822692013984559\ 1197646015616968655488974420654483938007442802190931003993019999456118115556278353637069865314\ 2047944432051514307105935787584482327025103891634219761274831030216796994286943345984834381689\ 0441069867522825019590782911579382291809012795242988116056019596854124401758004527224696098703\ 7259345143768788954234582961877658693873944996611246433649786662984839907320211755076860634740\ 1023647044310484716998628334983248292593265355255141708160789083813752801447738308487196398762\ 7569692897679121024812579201576922283034894986203311138112647342525584229972653187013929566801\ 7198638017039960291711693233154802814899031768848563352733129467398957075088787053674356624559\ 7428275082488999999327402092724922310405239186311715589447154547199808754399468274945519833040\ 0073888622882263386619841272540369838364491779392245701867285521983860811815284693069223221721\ 0947593494567137813547154995892990925229072661781070238034702660164068652089269188317899455363\ 6802523177554638823160162630876784891482280791790478158181944113867547178397831828067540234576\ 8928380618332783781050831547830710377236991815722150967454065017440319738698768346717186381399\ 9287588139069072055663986322079973867034258864058461467313008152068575898166445812004494184095\ 5945123430988798956309540598220207198200747063924706448552105229199740100082999094773040248263\ 1172252120539650533124372228362832018984265253693359856663173285247265861807097837406540769965\ 1583894185146997033002884930012700397472548491011619902856285735246937071208240840760019113678\ 7898500381993492710290091731521495188201876243607753944554644531399785354775829338090486531319\ 4725730529275443267636580017796309451023396496703887274557626480859002166086404182887352751813\ 5310938949072006851273878403943149330947288925781605230347401434534867044725313643298410556910\ 3402959684182323466758505488881093230315807677924693008696151672045668766387796671104496013999\ 6796955739368443022931713797018965664882152672408946101690277022005412231219218492425330839301\ 2319751071265897538197145128730285629189943219531593731906582967509949775904523370381868708473\ 4516016114435884609323560484254611185394973210579176267849409680910569361109234404385738664711\ 0284252232528355231600691671151133412491562255108212011841635882315239279224310470460395241546\ 9681017621266080607917827115065920075408133991866163084590502821918366054457849406799998034007\ 2576481197809627339914668643034084200371789338649334651885919126814503774575752321150076964274\ 8133602309570766459260035552107431919156130627985072243470460931663391278841828876443723790379\ 5742197460711557244047993921610844819598394804914240502461634326828448683554278572096749571832\ 9656214739253645230193473672372389798730185789871337661093670171225066124438913023966421609073\ 1491495940133831476999162399717666411454321438157354633819321349510317307575109965806008923538\ 3111131776475660778757116689212449970647324279755375416002199390354613546355749817637729171820\ 5846317609729714521923833852384040218515354807681026729188421046980938142768409004620489009524\ 2618214205606430542526070955755243826131458951628318819493177619175330028521221979377453017059\ 3374866878017692253597386364246529914097042264824504170908283589275449629246590083919247506606\ 4521586180359978537625359409600320327754845852161680374244582070775648449131148811850939749377\ 5247323600672151556192057083303574832155078828395809561279526235847843765466630538811718601296\ 9974300587549453270518978367273562060120802827480468660814535444688130408256849754148967548642\ 0654722688905478615717468806182237702176633976927357250505090034180296962967062902420630544233\ 3598857313936136334221840449155617813369881202111374989312717488064077583122524662737663549313\ 7253436281513385358933867801269490172084328560751318312784608927176844578343905351310684379681\ 9070578956727011965382171832416446071338617440002228029708440943210207719695747897137169115619\ 0424046599644997499625751834997286023265148995786338272872660363041253279223850638504663763710\ 2640061920073847867917166855774374989484457853970873894924097113056729910042280510068300285320\ 0984229559891779319982711408022177799069092327253468608943561614326516212424155341652852920699\ 6828198322817670838742598534848560206838581374874359625530423130032853654825544997501847841013\ 7870575916371665152155929805844201686622894244667816042069948550063242547736013269287699450563\ 3900006294230298910388336468992637768985508153439186948171694126704915216703207323615444199003\ 9544262183579430744549510733983717109866097421457663159949072795771996542657379438667103707086\ 9148161657566205340598899279227957108993067118190827996766490304280806152975939352203506994767\ 2378097591618459289383649102856973374980940140101442995313773540057338405167159158494420809313\ 4138426064521772009491624268243298862707586125544318154762433510316426882133610145381969804838\ 7820425447665197498892989054983962685728001343973156712313168052388157742992199219410744345625\ 7427997957183512175108526815707462662081475858488656884024333688064449647100724203067968493501\ 1096016479912905036832412735214944322710489831493809089449015939964015974152170167929719773650\ 7464193232442990813992482278895639884781401912623835091138643848853935852861153026623500117330\ 8905157945404020355567708989437965209760075524608568421875960799997534235505360769652159686945\ 8810232409667565556838092371417868895724906344471217387156671028237849195284743431702724289570\ 9024369685791987263683099943891484809376993821934945407986219978498505945049694452216807745443\ 5765441505944665516187981995551936319967003470848116265040925422827517237124035044113649362427\ 7163081837597178690889114512753644078973421011064109113688040056530723909151832691730804580561\ 7816446132262973576869284800122627497391604733011847114327759140484632326021528718448873146577\ 1572580133245297503203085313213351702563045548530383089210268024604616835486858413454462958837\ 7808128219949574023144617023271765536936123534044833652350201373318076118307176922001535769002\ 1756274046098680152261106895256679960962441519370712536642124467066288904920991365323774951957\ 4594893208312288971854218593717560829480117810008783447382962798038091817978476980567878604562\ 4887729954865437428848031661872402136668305597163741203153435157170495291091738310954520425547\ 5651944111118465376735328569749897840716719308270377046010822389634534182164880399886104089371\ 4756816646182634517231984200453971105454338860249390023070859987734630701442496172060771534442\ 7737669410295620491466807438521907420919992054214963522124047040759576329213856065049562933295\ 2083344336103314564601708322044568502968893311957855817428663282737938969177810070275909816446\ 1457125426642250530123922975359247467628637662505366354057149352334004852794503760315539775646\ 0269614748474720998546607800629356048523974649990907204027533977406299498681169411869419751271\ 8686830818242442781955702882576805590200576612389102433169033341123579414040418024567297961804\ 9446108819539198121676558839849566367006932571687418681746296429800490752000600055813705139882\ 2317416152369595597523517665658004085062510839276644817275379413262653711733464270794921010973\ 3088322742492648370183393200111443586048273904701015873698489438308452286823053912885063243401\ 5942784532626516895230393723401134373150054118787541321517607651973081586216190151389339139371\ 9841947081206896456865200503456444080112904342590424812345409265000883231988349405922967588581\ 3402506035927685720602322023282586450198429101180290622236413625405899949328438207736181415857\ 4355870863535615625358930098511956455573359621774402203501385550424641355544554984249923077226\ 2116136318233896082655185683890992750351581900095499106045590638268416406059413842264886291538\ 3344324044904999555762245036057548970034350827718218857039549405713722855763821074721457414877\ 4004357683224289822402205942118567940148338332885881953916643067308069526396178297184997736541\ 1866789473370751049038852490962708893963893195108852804100607972671792417785379317385265623494\ 9308892938657993562168508438072581360275999753720252774056751292129528142441018571075788047092\ 1802446308101889739344681241499635260756568136732099864343571699265082515335176227172259660041\ 9472082889414378246868227853535257356172169291816268850510130614414024745597416435158548610564\ 3481763551375869743053129282129463428804974435888851442711737677930440721281473437803100892452\ 6567589365775968465726315388169165607448043132491289398767810085216561431374462603628054131009\ 7462449481993205113796560073605671293262589565486642943259992370075305134736125775169794489863\ 0836667614177809972808397884779242068829149941200980979925209031725222019888644294753897066548\ 1678580674206741809965622700215357111869203241338696870493985610016577609225839778265830191515\ 0752240864667709454934124727560151380157223866383295722008618667546060523870343766455749733741\ 3611060088561799386478051465145027898113881199850379664628435888599186461562175378522313673804\ 8546113786386403362719974108221233299218582564964339249096134009020119448705122584948597060430\ 4643374611625562295266971474357687208989834525537835478912535463254976660203533705359290193170\ 6338453200971991292482592981562966635095850196833877883799845225989422085162484902187882697924\ 9388080469600067820836353647324672202034562610551901725296000216296380127849334236552900012851\ 0518746579429674111748364321719685757599100972598238470778906099040764342132859112570359159309\ 4309412135709085594596047428194586900619279672628882027386362825811581174874733093336561946994\ 5445527080178800641594895499744877153923860032076873489968567567021154573591625673966945757242\ 2555192158034399446220529930239281104271977632656600526106609862983639785025854683873229481534\ 7553200478977697493419990441395302824900587730644070819751890642993699963133446025425228969888\ 0090273378430530132440530587926928353335259625123102094966402992139401451290609582101059008391\ 1388376239017673421908542045707043932146434403569926967666351082119518940281094827370735944592\ 8569934007948926991014689781466350700654994733220548601622332966414495588793910569380596506335\ 4561729632362357117691678665402616510269551458086402180275166172353089391556144004056983154080\ 3228441535544267116851067295412505562160671315057146902403553937794146715284694028980387804642\ 5952110237495828616473569882829731181647082342194944099473828633832205428778950809582678596363\ 6463847240813866860817451199771834131932642865312589133761064132104924196581476622542632215519\ 4635874734287782264713215858342552847205433242519842883809666681968527927975078583078497587726\ 0683699357393851821452810077186296620266155086121896153098769165446220358401594495144212623858\ 8763456950134714661594242116441104439288959513871135463954758003420822915162303360000920160231\ 5760620165405242417167776640904117690368781276653732630583082744361361050043805232515250122663\ 5630833437686638810423982886965388533282633982177574635319795920407584762513860731271563331591\ 8005038330754702084049222387089542688032135594022263139963698400609742507300385964687550143325\ 0167178035394547380970945046977465980532167610797020363505384511327940668254294936398019200615\ 9736101797379734710152961299435848639238555758993394164403328508143829699013769089637752872326\ 5192390016373008700527790305418331603058440367616513086816384432822807304224672093302069087961\ 4919342381900155196523140998778374206044795036505956423309496177975487163619853721218460984630\ 8582531420880272494106785378161711030307605921608921610488594752781429873674999308137356212716\ 4859233833757494813184678106661213831301392894210095220540624007007089376342664947250224391559\ 7280514031609135978983024170597774071127721465103689846376379622119340817782078713870149084036\ 9926392987561888971339209946126233877332657272591269877412475067557874858417061834942792039607\ 6552588972693359005371997298034342524126801478131361175834225801108925555513240766544519911010\ 0422223196735555855975409955275828336996931610653577180682632334058312997977531434251685625134\ 5694632981447865381469284098913039797156147448950194267416902524747007585621919156415372411932\ 5165690304885621315378214124774735948390567384282086701355470581713108701634487173766786449007\ 8183155959343149375406284383001450102515540466841528628055892918474648248451918846754412136464\ 2319206863441133083255782785595562462888133712001741902749605754442626155050350947412794345099\ 5029677597704654038705113288019335589266247133216517153113945220309374623869663879146931207133\ 1104132921266971538763188695607168397022609851690796852242730001758494206107256397645360886245\ 1358881344528682436253895755968151554349285708605973183826631413715247667013545036914651753067\ 4070971513057600190807513944509283572430652250166954100468504530371168289059586773359784493450\ 5597515179186040312996823550431829980791924515559203843779946146918293948440539321270578606510\ 0857445095738889619847526720292210788166063030134803954787008868092209346622461521427383097163\ 8130609602761798019062976648582635182585540483436611876809497831743324291539714468012350323255\ 6684669803740345721846482505846748174906879829719201718119767052761224689744475360133257046220\ 6049527908634880834170128746291208754967131082389892126952672658481939886709235886444128293670\ 2002866426063638599341886924150301556289038122375670436949515932708476220441682397274490144668\ 9721513174127939713977103654440043467005054536505597310424530728301082247013913280507038493381\ 9662436236137339504139762574225452064030243080119361653790348689358729005804499628011544998350\ 6530905684367570110584735694287343497651348234957566913035076550023187800589019791711103579986\ 9738773537100008144482061452868490861597404778104966394928426532106139386666759835707437720631\ 8226206870629742525689707313499800604029141664831180617803001233719144391655591780834961919479\ 0841717904607755993097041081714963011273320047002362363348807891544946002451096290225677671297\ 1053478480407251022542178864696674826232976115787979703890068127761121024140483531378717888607\ 7496266071604013017065094504003961055675503301625561104336579792885614990962656626535695850779\ 5665657479824217263906620913617879548526438222189836218576991374093020985714218424200425154195\ 7289776434237594888036681239979169490316748736224409607557135925952584706786222405926135297745\ 0942307398230689365795428778115188195101939333568942501762357332509417480094434408877879749516\ 7921144497278874658228890427704038253126727634964325941291631107182410830497408046475681192256\ 6412645890199481929468669328724981288143206048729400411722909848597103705266745173842613390618\ 2645974261715317313080207438321115395262650211951055001236849217447935228877477542772815628394\ 3860588134330455851487249731889920407916534272593307629930291202869215913233742573904860529990\ 1698548106285981351273138707097175758788534676397484851991425424437104187816788657333015913686\ 9581218165837792139195586848422158691037512167912778860740860965548002960932256060183193052337\ 5203389115236604417918430968521093155525204209824847110618518638670464179576604466671347150012\ 8408418962706124062998296397112185264432858579019312476071322687466069753584422469003952844752\ 4172468698942462215481054650189332528611711607948774099055732046710424588983168616757587379901\ 6227664273662783415660535059926220353970071467331830024797713047607652341717725655065608566138\ 6800811410304029190541452603803561590411920159026886178704411681470380331193785474599536134037\ 7994521298799242597507239739257447269151791557487775309002402417080920430749433781761020219693\ 0659284148336912940952739372669970263200721479092658858818806556482543086118449514121464165440\ 8725165139804907616816291613872398523948766326318657291319297590287836221010040647926845797349\ 3679235464093322110382059981821233874491508565372739350873339781493052793787170869558242872223\ 7636894776039080948328798607906577444024502290629469487294271372854203676391051152152502617191\ 0783044403504570144607729318333426376691904369573812823946352422271790760904697285698568401169\ 1751421998572693494914050067084392971746193251269696550108859233844932279337156766747221263135\ 1109248784620864592632430473325138058377607187766491730971926959596013517849933686480502535276\ 2420489168905055482555040839295692860674735625604190476709107849027408464965324644773465097556\ 6031572003965108518725395731091929255044568141305682931024533264721860296745517171931102897556\ 4285123640288549043496853694155534551438295466994673726574402751815064049567480533571810760437\ 7174446505869928488822833903000533717720153871587173637053174880093415632930224719955863282659\ 9774742209566017915456926158678204932556501065895866083451911885282848081542800016363874469577\ 2312250081114398242506614831667956729192534316679228909689395019930398998423756547402046523399\ 0056730520799038507321301256035038393307792272212131485249526326599097763808454436320573575055\ 2945983647521108937402695637889218105188585192281378381530957511599233037318458878739277757459\ 7721464470800899532358929867312010719586582309302833287714702089578099802559674380233790801193\ 7946027147844097717207898982891624094225182740270888903153717543466672452271903485867238699166\ 1074457459389292517519391186813518547657532468624510140787290401741193206189232720732574570560\ 2796701500340651458393341950429656239007181863379988431222853046241472046065929850988468150938\ 5779990546381348020333389475301642042314267137699419995242507873821954763722948836352769014531\ 8839036599733091046248682638170189408460952891407282549215372045508919287746494560302452166579\ 6756275913372543951013718192854023178055429828656848748162787833726989468790410161345619205998\ 9324386595789982677505140365727508888051502603487264280598880263683377505712126873473920886657\ 2473232464627749915832410759077184086825859818080906974211455234090971944847357392380416910322\ 7681330913393267928817256009902135395560254098483282845888394497174322081862086118232087144686\ 6783324635834917318302503242286010630775640298598674520153756628815409612056497785868468789993\ 6015555031060116652943383298846949217920864549043470806067328112530437783086583105505420272573\ 0082510908055711447338058688938599623233510621323233062010576776919238218714119872061172928469\ 1256404033469820497060904572979593637759703200619215657927244528862248582601852227316221888557\ 0129135754201886388988532007276742484843498254342116868398375475983816098317915345466432231211\ 2913099371130315958357824417388862754925609695242769439571943605991099681733000368368112140505\ 0633567263393325618443691175998224309655698220336231359708680962885670088431002484139430222768\ 6511233091231210669508540426068114297120281942854825177334377919730865846343158347530760521558\ 5350602501493249584750952243314629273921136996983518738621034892729678486414759859220977305674\ 8617812825068028611162314290987234807799376574884937301004191243453521050315743111898822512989\ 7222722417121455523093769794206225513806393949878612763214560341886808498684729043339232248279\ 1070186689651355576156389674254714464266154262790482587562277818146462631384775616814236258733\ 0004645302992976588911804399483451874922493408378858780302774988915780287028023037017968085944\ 1465122704542531183107566746868465979005360437202777892882725181583465002209346514814769973105\ 5078440629624486596895209929160201760909552554581200678737620172959486346510588091481460560114\ 7753132184967950590755105272225157524032312270934072296610489539887938353642775308115224251079\ 6531392837334885650330417344394872638823181743425089859713402808412061847032338365874157510670\ 4742531582072033026151765831735766611344842364978306435080004371641078327056706952675002552213\ 5095676153055922102553357999048027615622909539993733920325275888734819112386391010783875702165\ 7926188414510663012065484100815745123949048316232166851298500447067071520081548245336983757981\ 1638194814855898100375476175992971961317132793280048551102949640292719860996014889278486005784\ 9219601937815340701203219572015531417493229459237373339672885052210850558229933102101476876861\ 3773582894088166087117975427097732979163603684951032646095721913047023651384853488591618563944\ 0560611848916195938952289220119875484612299948011684081955391613282403121356320993261747772864\ 5819295330954775274017405827983137282052570940487017819187116542068148156021764837988412365363\ 9525966501615437924095701702711673216503412369140745050587578173811744477063646069402240695411\ 0634415974761683502215955807370638067824738090542610098121123213414391103899475173994344234464\ 9108052757119837049045791259978303662969925696473366227027276834869518039905409029350446784873\ 1119070191475704053746624778946660350229215132870484174134040114642435541201147382836141579957\ 3092978665808642629180562198262491265723419630930823971293808330898884429830910986788247066486\ 4045826906300894489064800435815290505177824760362303693354046880281490260764308246383396815068\ 7426477866377436136432638457965501130463001433746882769078983846611615817394708686232527703419\ 5536998178685682629554334086444928752137947289177696286006847319282217661108119487584145391283\ 4774080843451347329763846398423030979810325583624234666415479900947005785602663888513423450208\ 6290529648715519179742747741977090370849892516505106742745824335634404058636027022524144094350\ 0421230316311866939796921705642821063763637125011986268816609838905441116018746737418380523944\ 5079822210980884593598652075745607941488907376017705219012268196554563221960357570756904728922\ 7151745033586255091065084836283265572389422033931922407938215633857837074612624180606551397555\ 0034770198937085892313520286255461978524429818731438917592909486778075470468199432334862009457\ 3433279900386963843701699303521405882827652572199780520460397923814566007824517103442359501493\ 6306595077153288548317747075984337550272528005765282414769816126136303950885193010728609512440\ 9377881220984451923917564198229182944117655455180414754514873694780268094268131432105305221935\ 6469795539854638585789623781086825646052457518160078172843930345630195572863697803958275477532\ 0445983554014219055882960201341425428676298832042917612573123491038435899784959819538303247132\ 1486678273036157360603732227150111577816635732832727696174088375131518100173142844740398222969\ 1919394945239768615195445211589712366520458601968047127590069142210349345485562292750329571689\ 9441746034784079737771240553443926271923475255530806223350665933406761848874970392708738118068\ 8420042343762662622408227622847285974032866406164023194287800049246909011658082553650482078217\ 6984657581272741502732900421554385067262354191729655047430396224822952237223509131366750303561\ 7049182686466370719607632004055397061627041130130784136516189534176063503643933931242971619216\ 4436630179523239992753149139753815756605545893534515088766257798530053952215116816539637256205\ 7137037174062891633576567388004555606838204241823619891595194371191446112490029180302040785192\ 6325810646682986016330167924392628105538027485761116329147819533648400678086740785430149119883\ 9513959527100014294778393944377161354244958191573961993273095104653102310523883361896564224722\ 4753631711509106739187521664843366306839619182635132630815261563797968484233210428661144702126\ 9195588401458261545783444902571377891761299433700051758824301694473085747859121011900458149542\ 7716869321219423725683226584921683496227442434819083622228603752421618100247752199061690005434\ 7133298209226064652884433812407746950158891804622459209238204291637550294259640255277855542500\ 1873867009402080456939382165944755538190890443199629112473988097487903594313725345186541214029\ 0853680596164481146205265625904464896494190097536388590996801389458426014926854273553515642722\ 8656374777059965595471237820334542992982858229670515242821465701382538014231996263174228933365\ 1518698873132018797300878683413804291041923189757431259815194422117984178739304485079328101402\ 7482589133112146785410736513279321703255489485450891720857311269593089175524724704162434658083\ 1304956037664417328718179028812882867161659117344863738281581686360447981809774728521803445677\ 1605580713888760725203505590192960039473421055841651819498651055970520162339396811235862308373\ 7161525709163981695788756270327733173380936104274433955636956096929886840910653231461491506793\ 7699886344393164010687501000632237451188709409122247855235617765453690463226690267715099572909\ 5594500695970857293209627369464798111978370852526857473316978708632039386842486494762494554782\ 4331695590792783679408166491884259714293660459704447142894024905302567360059450971610952188746\ 0643146301631131521207644816006485857072200215398311113758117532550403762740323868742075825748\ 4066683707050297563098007608202682927703224945588827975165320931954203590747241829672676517459\ 5042256211258164296082988958602774526583161791677207873607956156198701707494062374808685638468\ 2689430271761661218018771762528285912513233309867169310077941550937679114669950667158294686429\ 3533284277641915133146680828234028961807377686574853083006819673845650111747657485595913379190\ 9254833309175210037350962778517606209423015121458044390200998369429612465360030124484463542734\ 6309635881246547480042413493112894609438942279754735275480742183395952933714800657786571710812\ 1594761171964214066913181042012324029533951896864538948229428007391087471022936476211743504456\ 1046186761082280534031665409095279413486721603381951918062272086638639709669273863519862454761\ 8084378377323145444794680874348888359995190485647705810844652958786776037919683674060340039252\ 3819294343970610124390947978682243897913997947543458336459499789955736186588902879541192366864\ 8511080036008818641612130313093601271970512517854926710237581918566041394822287324311704856206\ 9503480942472711415964252859570117192423295933415567029133039737373407397960792923592909277268\ 0163080754544438633281783559454127272593056703285375222856630329841288311127679551254032468209\ 9294168280331398998695625794463395139113314811422129609097365873099333508479831375487608465635\ 8432871572680663225432081747646310156946007268211657759520841945290470128362250685366124734342\ 1478892371378552827648793620309168052329125728798606036205441982004557798766864159788902437468\ 1236033238071204504467316383112552759196228205354203668919507757072346821289206242254861623382\ 9602926300838409912053988865609817257480747341032706555687861174872272925972480546125256243463\ 3269449881256137555715972334250997072654958256192676040662817986640529210200714700579499966894\ 9136044698962783430857934644873527001915321107179323514515407856563723403171844434287753036116\ 3024309938388170294237454135779933764193732783574260144657674016690847114994903506721521369046\ 3374131824425345568097875951496441716903105888172261537942368189134931387261325161071641357449\ 5115822489169772942825559371680141142157333864921265655265854427986449398374506800010953314597\ 0273454127848380537201266446447972380407682139117295460725621201013909078806435084124587250674\ 0961879163798735996608898179558920070704136209607657337803828286714565466508437434848119738780\ 2914283416822139877501089701670393535913613716287901167560519460036979872037094888200703875045\ 2596539215859459929149816307950929305271833246066153442086667038274744881498484498169348685845\ 5455917951266349035340483362973107281366805669827669295349542030441063731731044204683076063627\ 5433387315133433538312915013315128149887922643665917298460286239888228371401568396261386308309\ 6012166871239741623081668871624751027698031871519270250640074400792488653989713215323517325957\ 9710286841456537605063742178601228831810177542480604202237287407417761392728157657296055021825\ 8440001222638199906126481062682286248230797205187378929498705213350049105905266334863378046393\ 3664725555765807844022657642688645077611522594893147346952268490098205858416746088648883579548\ 1871795814462515469155800973267742685464181532760144011658380777381950395703647890618072894102\ 8799450772904896943426555662092026226008637546353684981071763597124018619095622030971948376767\ 3848558606828016979054091562450220121677884443944427433054294898387017900438125922005052750084\ 6003247320533101474335532355483246343380735161924193695750876198829338857995455189623518748747\ 7677129349430381760136261011379229310194656716329530766888997971051030166084881189811903202672\ 9990795153365580424092119891425348985043815716429845871022315775087869684413001177925056654985\ 9791394801665846483150021415129366659136141244636985675221823889301484653669219897814726024295\ 6312862594505668347588350845490712999506130022371235298190182087287683769481380662472622434980\ 0250597906325104760647737241453108518526001944499096761224740422504211173507616663084287138640\ 8870451233335261879703569556355066528583564475780168061275325867563956636068932248553182877746\ 3163508083217676046096593973028505912134707032329985902325935790491852665784215416781550745013\ 5845841597398355423770719879709999422727643934158992906920209549032030340194365538849769703702\ 2384669473841121097281549446285875761077919920078593966984688723067495278750276282796398162621\ 8631603578004765532372375648520644597969766229277143295512574600949576779219559680212561482123\ 8154474553736935639601026650629098963497082574337765759299813786429648802255409225808323174636\ 3048901317575254157191322054711150584741657773108845884304205465404902797628522011015779347869\ 1741592535901567468913318847243107359311143921210213144705795867176326529335229351204242888169\ 5633022801393307922747372581157701063895933768530832665722836833036116004153500682191112142764\ 4632250231478976077615796124773325063656486169728355932716462074833075055201857660659307341688\ 2718625694396191591414603036995637645642299833617894181248873010379626329354973732771016846544\ 0173231672866178878530854390904217698853151897385153147893007390281424882858798284041928010757\ 9198104030045521220750794045673073322927459626838284883816907820261747327620782048152029348883\ 2167556948157678183337424486602027444620237318866678581760207403674513569691308886717604839952\ 2996282901721804186364973051774429497587590413012084800353344859072960418132004763986849141971\ 4657578933018576785710470179644825425822606463063603220636921432578054588126100399038584342734\ 2101053349330952310132084901854386062577796228674444669666328653767590609728691394340200001547\ 7471726552567112641665755311895798467990240565355615643898713185074610775984127716116868472552\ 5532271085116885072900372239074945939421460306665831972054658688596184499456174474582870596927\ 4457571006281117447111081899574776394888917778244429896396502114058852976793567842975731689128\ 4293629361176711645697204655535560868749236397969128933761105253394498899628282183973733752653\ 0324683424464727191957542925681835878309374932194138892743095536726434892528974422552393252065\ 4512560389719109129632820862504718871599009545760413944663741488612374395050768927268751595817\ 6214266141093719800134401654655369689747904408244584556828222363401049935183744260797045475068\ 4051249282475903312792566710799420809210284016518046609601809231787461616392414011764965413660\ 6747391234813550130436176363470182710003753676388779127103759639709508650242208319301160851534\ 1143602795067898991130010002475293729588241016681579161137612670473824242147065705296267581884\ 1209657864706020470976039480999124688971521529002411156873358650625932489412881086194727269739\ 7786513215377193100117891757623183760800049005375103195456455115314433727046981920749064190221\ 9783928205756967973677449360277856277917354287885646257486225885860023868414941175633799620667\ 6480635835658497607567696358810735594625733059298222763287491045996394149397104051506675940700\ 9258867824002815872060596525100539868655250661438734927239744547461132015859819788771136654301\ 3458492820882066656395557386079484866325196338235406081623461077284908439724354469880760781243\ 1797382215323881555927727844933485701562202076654682416689440298268478510059187578476029367048\ 5782314104222952016135691410504925588405502815856881733527761496446861998836060994451947489194\ 8460022452367322070074005248342739161846785623770126297519550432516790546279601080109534418139\ 4997261718506159571780758192098476149568044707759756845389563290867737507954221788531261727759\ 4560424214797587333358892114693121477051350010895573739562838886237185110057633218713212489710\ 8702622100164440488625506829182958407302525330400038741980617290171382033873695815999403007033\ 6341201546544022082577968375939208549882243550974440383461618290727455505603998628988834580075\ 3278469282548945122281765154970041650105828150775044646122132470702114362492344668808869767112\ 2540712958795281193629275417487272764657698126850686718222843141439746013775282370789140152632\ 3526776201463863594788904529022603315900531247913384330737410771150367783860576837737282992182\ 8508990722587282339332848920632240739344930681956514265952839273535460651991794916544123317344\ 4350254934937710894820519927774313955628235857372110319974108955219430312157526267356701771786\ 3362967291825195391061093500791411125018065547521808708340357091707749116172285749140413138290\ 4371920189872680131202328381334171161675982482770941940550750205311312562027870187280639527166\ 7597978779023902060895312694163059155422791716324539953204164993362798410488047002304151228318\ 5357500438001310601603572548161438759966486578623713023781916442085399135383388140668633164472\ 2801354899827827824869383355593093026138470671683287447749537310141740507457893756964498519637\ 5577122909307269818219884891189075152867467784726948993882411037164337690411543269991412101885\ 6318858247108362539097459374738588140526177174421416126389046040237920822393270202095553836816\ 1146966309276069019413079463432872624989349325354063944765106402468743637081819062452013893075\ 9360932867277520265922522346015900645544408438390527353208631926831783779160169165855467620691\ 8712547755623388016262166082815812165590196141177393503850936441891319190510469993867437617100\ 3699911008561950570930485361828892179648391423542385172622700331033684492846462902275752895585\ 9638086937830345563363075348496755507160619540899370730698596032786003736974719689245865497022\ 5474769243479921033743917572262341428388338318682709330964418034487816737032023495607340191426\ 4686234693605158161366818030129317687890345694204644077022012086697145290527082780132206457406\ 1556357642397360729543257004001572178387379326647050623290855033386056039003801897018811847365\ 4617127591988827556540642063088117146607054047919435389028416329646043049688819934259598749951\ 5219897825915967269842352978206727585466899064574695010559104239178176175283298744071645925053\ 5535537537274773059044764491397664109650121703656533247632389808820902237395809673145766074103\ 1243143835484232907127118173243143552791042270314301367993394857212444656094923749249661349196\ 7525119444365466415336973141457112772526802558988452423465579322244384023975296799655623791683\ 2505959053876994218655705117387351653908424671020459275676417617649716190691866866649928709636\ 2221566212487472454647969291468807072429071551566205980597700363049254388895913716319329106083\ 1859279506551364669916412559188069463460971883332552197507197861683957413227128744293138243436\ 2323214426746871778116829064023509651164993067226996200926924712569295380815921226408200212500\ 3482697839601273075749580914757330993043235728539497677822607532348513369730002601024164436570\ 3346628112696073741649013082952082142839075946039476298909540411994413094528017334658124744629\ 4769118085670858654563236940347313209884732620309564268126789296450308503957025584717959449996\ 2382180417978305932364144993741905791703759967691587166054804640560850076824342129378978144954\ 7284032469238060043952778570686334678988747331159874005583227585702064499587075603726125375744\ 3334757442487383142700755870683588465200632670808359139470243806806242716061908248389449343723\ 8009540494765015689661959194975640245488210270728719920654761299852219124070655427323010751603\ 1336454477728024559391022854088928821766828468740425865369533544028806579158722219874868942578\ 6194798789504892854812485376203122762373397742129429568112901607901899954671953438821877002615\ 3261530791309587523061926076794495517348655886913668036446888251917726154745946037038352805966\ 3498867147379390168339759421432131190233148739545888347683922431713993076653908865572708439599\ 6274248041228770702709652076466012080386648386266895705911639615101934627909468101923035099848\ 1071576000421292555396195182606758930121104322569199686168662182824938759157767622158081728316\ 2331994428455723049249297948123338128477540535905324709770321447793546911759749680138644188283\ 5540379241277947492512597667104213123926776635637095678362568619481283551822188959939383683258\ 2862223342855415989986734272894636518302128273322960397067532005967582687668186845550341839772\ 6435703101971997358078934071852320834325961003508287392679418674350617060031179450135996215531\ 7764135580669243812379980980056146997741810121993474895455275450706406004509366436697885171206\ 2610443919996535617254037695180986386052892596861437652473807776641391430871544883246207175684\ 5493463277901548973086202293754854472870753721283093932932050137914938888467205236602961452447\ 7817664008623531835262144732585408468863070689225233372242352413136611150814522525026283757186\ 9247676184487552412495123929203447341746139067229753471669263868739277040681163542776972760338\ 5590503273152176743394805600621275745076810270679276750595378075284934155834453411627157638532\ 1655122852737654987638231991704167924667674492836892718870011298298982081256206946966319984525\ 0949080539093058625017365117715317862019889522266817298914279165263443111482136597165192527451\ 2747174074794837061353491951846888407851989471441432102986866807885105294453243258501730501484\ 0016511527572675350193833079835269395337630759475000686594733256440167294416105214598290131618\ 9182624741013281465182880639588994730641372589737856187683557826777400789167496671074500419906\ 6030836418106927540596117086466824794745776408019073316666053168526264929985762229105999296794\ 9102150073012007167161996936471004613418031012715755695144956043444127814019860232482168621651\ 0994050190912032744726147319992739321635642515596929481046585873505253637790818492189028508398\ 3902885256659717132455679315185676577730949983852544345741443226012293454399752515537722127710\ 8912013697369760102321288723164965456509788636433606201317056130219436045182096253481325089138\ 4638982530117056358022907076377364520565241848859483641694111134766144797729643025373647356626\ 2516599926733996417853920490458268221156861994435475073113643842229481416611114619759898118564\ 0025743832498362671414115674138052660398087753485667098759342980707282630699414074131840784910\ 3393952201244888528853439558031697658623571115149231670089846803452280465914234374607698085775\ 6966095309117645046061151542511894207810566428534992701625416054589074276442939273246757839096\ 2304851637595529387343214380121405117474590580947990647147528584887676256872145924952314938159\ 9021698525076481400293186834743045094074791782128268105880851397718765960854749598660072534132\ 5182333493299899660936199184889255499232852286115575992365519042898259746138243389308409785104\ 5906063360578179521925307322315414747832683540931162614008004631524542122870119907065545672896\ 0527250841376315463899084903423418960536999180117544896840040296089959312254197700658699013706\ 2585982509487784542521457659471820537431676160376375162738764555165969321554868555588916466204\ 0821851666891820597454591725972812854163274828277253943473552194066412802931098713339812832438\ 7129453728360619274894959907167284746946722210223206880031799449483438671500440806643291176656\ 7715029580475013144198932217599308456423343504355025951309831662798345690082741237234816301174\ 4652913077404344358882095417602718864401716461009346261577423872668396392042564235203446776333\ 1052562628957098203968944665194446763879736301703824361242075566611688967675987231722905593912\ 6510538406997146527585542022453332781721539660791570767390917943961310666993288780231351409022\ 8373147644002585912049963845281510694285093964477736242502199058827926662953278315990335497904\ 4957572366223184065219765537112631176632845278322164852306530920138099122209215309249219936165\ 3296992762248162426793620857957594853585687239892623714800342800170042309620311443255360633181\ 3964615798506874634544416949697990204689351557463858169900185301984164356163905618237822569989\ 9804487693719301200502647110007712616198413550313659483333670963701762107684136775410403256166\ 7782627794221278750801953294910010877324994983785950867566935572163849168644546738565208911744\ 0805728829074711949288882244771101925874749531107009000584632843076787438229422114744871481866\ 4660923186955428520935858260984121751654618308198171665043401752870573316643552326847943391329\ 3630781717786677438098510623883474022694387391757253732278639363993569909259619325186517984753\ 7713922195933590457509397783173149028852891866365519199490961567141219853934645994379662182369\ 8909621598506085873098110581212557026478052707540744089328945643846625900154860219683089717592\ 0689980102997122773293844616408576220077587452481008084946984718936463596694020892465628936120\ 8920436487702929626050911136683209303265186385116675783831948551643538172797646178930980185245\ 6743637679539885962827078344010072135588416114176150795859882135568641285514355294327220752079\ 2766640316983914456965167186047934799209806517718298233746378487529162769427143783918333906861\ 6574583092556546723341135871427658617767262894005899030901242494811495926567992424196773409323\ 1450159559634395043123680208992796253676565849801880795891836649647836355504257136115889567974\ 3687509021600078036948850421411571372077019530309088897093538501163624929497464425055293321410\ 8527071261632481875988531299113732988287628038866152129241018852260897526821968898895234680982\ 5186391752564926063192423866607200271127789684679966090915866987140921128560377043566565699866\ 9994897482201572919113005560485467378320797622099053412680370629890849846411244706011389885659\ 6074271131786386783515289428712493719136558049295172253814854793118397416771632956450668324322\ 7690482187242889150768477481598484146086073750082502415706459605676831752871512269598877966564\ 7536753244335243730952650109680724424378765346257132347488622473720295369693533153812381433788\ 7658508747404129588200987466598159290232283068303744107292806012361365003956855339369927931695\ 6942558453480291310133147001362673771265050483080724903525056643940841080062642038636238290772\ 0278037226114290004749779142519968676280794469059168383789400771520911063640173239744226201603\ 7331655004616226106352014524961301008012834548049702141272570924062705429007329595812500757658\ 5060636591682158552985340913902797754880983307096571233494024789167072169943589199158596652083\ 5377918902840820157892903185114565355308895171283106652883158000224286088797424003498486153419\ 8838543804176330725085057847909648668328319143486986334336121885712118084625058665057303558014\ 9508371129139428504978804852319517857591040317667025913067457704975001642422353043875046882605\ 8684458946486661581178127454564807161307152866261993065807523764578497266909171034006529663682\ 7025252485753320502860648840673900715519596714470941010045903941037872314608114388324639713964\ 2940251479038570740912213502189985870026593572680357383049631596198286894413821734993147466508\ 4976132012125539107715411774149300191531461209767652572528659928020044122153336079798032934147\ 6870052861463239860657897885564475207817541985288426395404718053977974441516556719612778520649\ 8493556405658070159782838993032540886845248032716302745117213873748136727919450400326755418638\ 9739981714526739863573351051217876494581238020959156931725768562924573199978187114376621947896\ 2894946747563759129726874387813246757994506049989832906342079695465399212952945280687262853103\ 3025216549121318652453806230255629545780721690237281993627136356439069542493310765739108993173\ 7744206882117588379667447931734796171088187334856189428738195005469974949936657190306020077684\ 8747688014066160301054764832486892699349300874763252332415738080376967957033981070874084979650\ 4140800458403385229908461946100326112184211060513764206209939718939227118540679905548302220350\ 9075105259967573036151933724884191159114906456802196261540281712887986331295864264125990736940\ 9679026438719490209612809475096660591134008508711224691206749345667800214185189860017087726033\ 1841828589970767462606398486541919633079607804640072799381259462606297990609576613770794273443\ 1713895091591364412349108593483054829266709621776814249163139408277485231717061866282839952488\ 7755286042233618460105188432021246588988682165045182325358252260876487090141003416088225163742\ 5592198509256511116248231987795074762613583180549895705877349138532809458384284847539399140502\ 2590509323538940481191359977313075111369753405506410967620626059186289197078195239846160122103\ 8186416641149915727382453067050163149387883849771383234938946416941003556780949769253837743410\ 1151053972225532143825466603172601159313149612905649858552824810351131510560165107475581339341\ 5501997540748485316705471496625647869011347885167441508935781091154524988397895577680146158388\ 0143280083876689652028094845987239330878114978449976218320322666338046526788219581787444065557\ 4681266349081883371471599333675010765415272399437659467791772057829497557412104374180452462358\ 2944911861786571866629864437357349262872958215193945565732487922864259220494573808518985170507\ 9078015822644254480976901530404972460419216098782756485784632355951329068869600383544149124259\ 7701847992921619090628561064276679155284347982030085339255242999520867223824350075326644099354\ 0009664462930822704593037957825667984292779580355881427852364513267623738139319179901700465761\ 0851274230938767563414306613748738707322115422660843014356204158429907646513160215239591267917\ 4799690861846083105340886698527164756173835983063638456707066301970001560157982290537617675808\ 2932925814828280849945016308553486973289954525216713505825202022050323443872260876252508106065\ 4110905564874092620132845696900602614372023555561136501888448708858617695380947525374046134568\ 5079145206729552493117314933219669172058450538123954572980783432960703782907016149918300020346\ 5842793846560296111818214220305325812561935699065619547955721470644331335928920827045909873717\ 1727493131157088314436392290863556499106207327045956560977922653751074409668902333929428328061\ 3042862397308540137548671065985622489985758809413762210948918227274808466114957182573925524261\ 3545324255415242037414184167693395858847339257513338911595473622705910978458113820631167023530\ 4854399636596344563919783747072132510806047840303674039209051425931036470821565523785542996400\ 0720858493449464211706313987878389047582508770405846967592367514926757246509491408131282308923\ 2525178763731794997298711338926674309241343195756748182285390801855067404074572642667011935287\ 5310650775188533879305192677540576366387770050639466590655211856384313873443802215714780473895\ 2661573185032423857213286941570839422124067272224858612440174273990527884845834348267978189802\ 5813912118653940956663832453309916944360429451042143752521390935122858184354861326743799583305\ 5810409106348105513800937265501362495641719635934578275204605441041783326352706641731402189922\ 6123329597795695514024592788331857771510187023356820386555752121115960997175894824463224782705\ 0957787953647102192017604938139758708031090402911109741306085573569319134074933367602792116201\ 2376169980577187408391509623617076461053225127980178722184685110087896371343901626279134382607\ 2414385915348545652700442266963089175565305742704302065155780922147565145495008431715693138630\ 5990362378933394884217359744919763750108418481407476146652436712610665806101118245203310385745\ 3947819749476401778186789250869868272024782224142143143282598915058285009364809007514128660700\ 5896923997482850983319332365768025559005688257017388126366855442653368085955349495285814235239\ 6866156018817756634828363930974106803160478045119467529897109601475695099246619949758758576846\ 1913905664735988252860289634688529299915444702412399514182182476970925312178283476412468781365\ 4483682281583318731678329254788069568223390515398811674960071909994646669994671920056467756520\ 7864396375197383836257708593055301101630059983423010218063777748549809030217387235867570622528\ 7520799497085508967948239172379206069780142990593854329156396011431430796743657937645668430858\ 5768367677263297896196546327364972050227592099214013523065554959744922439180143806910538069308\ 4999214126889688011685494527885951664699071796979281427276028527287882040134038812144975229867\ 6222978939487138553553782860234879449615876744198310033857236244573074146558265024480788099544\ 8187824682266430714167070548874626275686552109139097055846999162090458914761917765994957918172\ 1568198229982116631501820255775637537514433631002853053635282951300860742507194954906708822936\ 7241767155096832712103874480529506783300493895569104829825347189985503356643915370380907109754\ 5363091530768018961331096898306147751753589603343107764236056177766305911998311269538235027572\ 4449939592838233129316733224152819393810225407238384387992648168502931710446321795091669265528\ 2234624381343913419601118204109569869597480540747979421646149755879402230859974149863874860243\ 7347519808015928303271444570116713517760697462734111464791471354341037109773539317399936123310\ 7988477013685038783934488413866251960281115975467282695482558164734853698312383727586459961823\ 0579389848821276533896918005054212705936082850374850070282625218334265323720987564532906516907\ 4871175720775949364391705341218959933635092299503230490199753091889105694200304305951213487903\ 2236157852730250236415826661506720791963188134812128407541089460664858144159069470260752125527\ 0350573089697593422703953178271077582177257527746044829650613200847630000709925116883120674506\ 5332957978166127732175668004233161471870958433859054600368871899576916414821481786799669423856\ 5210292554242166065482892831221025509789503791917667643627575975381906975196078953103988402695\ 9867369009925321523501457500544622939065173129652474333458864736075916570676179991634167778657\ 8207459714053217518728506105219897213464045830718952471930107024089753066249341325745238179491\ 8667088770289931394112247473444053076971600587014524757649429972940916629628175787974300707389\ 8993579156888063131128345145871661613620265274321723456302903312777949810147644115918095944366\ 2004536662140602832302922557780731245574193862822439243298105689246585957806828838477834377393\ 9359758993318639512359798255454049234957484350223660627425482995200700115707632485853324053339\ 8406523642685231245463031438384696899299918944288055225846413164769337947500245477757147687642\ 3492148449726949186651788037994126660806270816315192402897163369946874684754503259967055501677\ 4091502677992484253861379057853881557523779180215169544091271083448357315027672103474334642985\ 1008997595417895694097668261141335917651875859920002853907309261495600532469808774179330092191\ 5471229547312704454839280193541513121208987670130145935353877924444553847863319271514902422243\ 2283273171327640540872767570519128293211150015799152371303764629330173008825961315045874665892\ 4712138018815070904583849927528316107246050575712528695744711516642599970750126788687338013177\ 5255730388580342515841554387415589604410434482204707981009918889171518917027106826191311892354\ 3155873325934704080894373031054812801813693698093953449009533420391946421642377609024843439008\ 4432397202408440444636323826705326900119653155534346088851158129981344943862418569485540651427\ 1008257403967446039476527077428458645992078998427928037474977738314771198880054237213457733683\ 1369195741799008609651674971777706677489588549370277626073610020142454570564149303210896356956\ 5219353005792031110275115640068713664941689127650235137458625207883633463973140720915549275293\ 6133853243069973608221705621226155115371941258970765101034468449386521538626525477875091833470\ 7299594151099724628115913230585234990357734261217752886448334478776545452310832564152534376521\ 3070566077978009174792533100392707237178011322883681903073355691501858012437355192459362909857\ 9915124578855030619637907411420784491132327426550437489644711167218578525803535542043269617441\ 5788494638303787129235214992934966549165662715163533134489590741897804787293600019497554301057\ 2242110278628325455374760145514029197463904739513028818643777027709929371047595414381182646002\ 1184782321743337794984485769984207970228267677682240127451616620780548163049939093057975267162\ 2543413606323576162863617607758160196233251581477982957059712255595103382270980019407458443156\ 7925111493091653057831563438490805881395956908626062164542910157112071426454066108045331778948\ 2563679246112897010644839903699084695852968929301133419881090056758960986360444921933737926317\ 6743713063556755142345207178922333676311455927853642224232681283878176630520493254008217539509\ 2968388305260264020331336142549067006592167069148532694257666936417935512592084506106655405790\ 2505376261366596722887283286371854270326257099160176004945087046454513081994300218198702596824\ 4337145312695256193482408208048400742033870884746299337030378338377145061357246306100473720291\ 4571756150694156899947164128124197248790740325755149881032805338950439311499817853438087864728\ 6143082512590808870928412554008555886894471990252729199539163568104690003277822863839856109480\ 5323425206004215653824258044988618186531333646685135777267818549202224027730294299599155398297\ 9889852327733955677843659560024823102314301922223676842187050390914927286193644760437652671941\ 2511311417000635298676902816468662353017198096539966079862895657789909521600366041635880664834\ 9187616691867829071724669035967222772978418219262246413594332335537333391040201644678819309732\ 1615471053260859252171779021162904368691020825175843588675731065977458852896661753170610209353\ 6086836922412111344227562653098103596893422361680118045669670745974217904303981443842332430144\ 9364380805354794097391961689697434756595552642400039831968137547381323366631473130595146728390\ 5971595751110320261610028339113136326569078526578198079251111656900595402526531793047667286562\ 9429266858318791244501089411813366542714234253182454163906709046300793790108908209991524648338\ 5782613135457888528500988094674349961432030224150963988816149288573640048893508183019628645052\ 3028192656612139959320571838548680109408293585446564331481529039233812490104088018675592145455\ 5739442669052200493794033425651571826478085956854978711052217485617162456141548526590777985823\ 0705435290498866348331853302331196590928406802063734550885584668561758947213729750926920258629\ 8899454786494433851071538968346361304330348259434129102305176245384638866503085368612257642267\ 6932114911632597426907817304015051789122855671742825114765949201306837843194310964306957411827\ 9873817590589878668640380602858465908002823505173469499131036023833935350805944054202082879875\ 4480215139893841434741965456370628572743095670620446122358849422816670603545764731885107808267\ 6542815575376749993500869899057117388592264997561834231065637565293081599964856821346151069975\ 2840569839706033693537473090519225222793869304648130500376454322118259845153438491361411166310\ 8197457482438579664106189070409007237572797345637613687966758563318479535200596608884649514447\ 0567908984066422235096089280020052518362429984898718882770003109897267933506202477790690410564\ 9423863822360068592731920248341290707272080599017357856259091565596580858617264519794703266810\ 5429021609271148340305547807187958688088479597312823378563507794256158365493190628411692435369\ 5434920381297487478503765847625041269281734898409546931155339902323382358274579190062327540467\ 0550463373039322387660869406931221594217494592299953775230561871179026503787993366012674629453\ 4673501246384013989689625441115669043234075930264306388141614772205907268107747543267906438127\ 7009309095474898509316507881451540828406999131650612970688430830088810943645743101522092269562\ 1122964616340096758962165942087116597087095026083089575552953547086344586680560874686904556814\ 4522310857911362257392520556644614710285798242137528290234602894494926574700027138028840864992\ 4390669256935703886999361447828574476082676358397511952406584311794444968068054054535890532683\ 2028145228443744001746112746987801777381216463100293833252924777806939398057463200143430090981\ 1185485929774053388878866502491140312588794284456083217017382685137497648898708351375579711727\ 2650220887233359205158213442582629969222654331603016350914584938567167262153635571937506052615\ 1745513638094900049266202096043394871382448276372852356484864830281406520146549932895292528396\ 2996222957337602022307171471757298316533088289790493746418043639923165946262120752062987553650\ 9795409739276001610593994442848652271305359549257964516446125132113474645477016597871172321334\ 8828684989676168146737509776212373722831105753277144826094307613886652343212877012867072988594\ 1872473901065755256180171617715030558193729563939704281679004007693296847582156223586563634382\ 2826390365463940724205334663603080281991477677821054752782065281881008862427622948948782577432\ 4297965175623111799732915929796910599748307217379857800323159213007440788907051312748118864592\ 9551098209527182152441600572549079240200291729673452999767880645874352885953871855776305366505\ 5254788704680905368859299456379357149607320031969419996439250066628165251602250485536595676392\ 6248353129622980223429008649959551278591703418315111956802136957257608765901001251260627225939\ 4432274536675472759255693327228734259236208778024386465619426703301931188777850004846321981361\ 0414908395358971049385802573704430723722609725498240422560459667449869238505009577193586327139\ 0644104725697762313345539459525377545653145041294328445073764185446501164692003190207898126506\ 3800502603234812696335486892293157999208129070852886435971745995701303847083312274514815912141\ 2797133235819674266710557019860321327916716982777256805546521749775402563327941713292135739481\ 6907397229179277050534471134875244417858411180868124733569279108157101023092302358431793300750\ 3815544385897890387270629316325654694393783829656818081554628668343474247749641979190285904575\ 4421929433302975942357824061448839491851566801184438019920245216935188782685231920931594929706\ 6646439897915169150094068136251236136304737882667576398609684271455314379047896963486969097412\ 2186922854764140588259753876180719189710633371122633155678314632174911934641044187031105996433\ 6328677393689662790458421450834689015474882754693030240727885842258215867401765792678650233260\ 2040431231648985330787508002147966169887879654153824760973562205829187452247250035693029342296\ 0057229397033879007203749239208230983114761398996943844383398948673919981964790861943101048989\ 2686120476159084604557439420091981026562579318783045441980631873043434626583723670655328761396\ 9863571515635944614087328978763013228875622729761434092831399021199182611354008977322080675655\ 4607634014195051967948706501984086677845928051493773315842069885422640879732391588452206606074\ 6821116830367694686270103202249032858099288957187556122840105110647532168636717933411129373851\ 7348914573875476101490482265669830719178666464207511880675432283345595784884503750129025157883\ 1301410457763225304389533251566760991342128155228250463035935209711321543039012967810242938466\ 4084957223481669806861557343477687861929315409102994095383008545673619490738857417723389317210\ 6489222639254788818832844255739310493469549056055351160926728459832204899618543601404983781217\ 4740896661963059976120351126573675405853909320485711518983184953106923738435480125963376776399\ 6473008631952060508606863486179025155516875253010223959291524028929935147448228664408639193636\ 0471276096939781310662181413941054400813341859329006076958682334985380271133729842396553460928\ 5659096449733205259256091928666624235623495905756144170979045148557031331618775585199124136864\ 3513981248990516887221519851062004559807947938988488260171978155405357416542870200440741436528\ 9682657868619301715673083930490288334170273244857936773912408842832100400525306956654617926617\ 0178295923214600557281845895566600695602315166090326607368371785049282953569842942672336339511\ 1361779312351420435273048358428916497219788252844277930411596659478511837184905026419515187042\ 8365489369813397504394194493720134267762387342488769732852766351164223478774974580366678348864\ 6984335594971465669211785792968299694338093118228526437234289660055763477177445088830386656253\ 2662207959213544553553664372039719137171448847735297301872759525438014613640589994538048613560\ 6252018471673099599793560555714481627266577759227057971606253439981928729432044912784869882866\ 3597435893528175259767199757719816429567820382995991563197101926408666826492239945995904619633\ 7153756861800189713876696798224736847167312944792166384275653177179050506546985756215141669558\ 3002687731932532149872440548538891726396087053583861271151462797615740514461806926068226533330\ 4873904405731319797771148875088259290673102717079204973168602288449618973134667161642102760256\ 3508647411976932668645284811931538519479761026105260682082252697721929679745097567058514891992\ 1436864096680150975178917742993571463987085051621429183802292600828624037094088089884817087679\ 8904125677954708198339999368577306153485151536821067569618825448939170888502495711247884139255\ 0564431688185902732400428632185763858099017119000139187568323535178862744217059292656985505843\ 5177097915374786314623565785723373691892604163055670756204809700290420999071022050422034416285\ 0387190319596410011118827651536187625564265595832623978702513469821641774788743228099357500399\ 8455476005275645877579474176946438887597739253752915679829073593805282956998240244838620111219\ 3225105420624727242382559262733245562741733192026156006902268656563812937693611530510632385794\ 2209119293339793538960005699160180002058417719353603360252724521971081889349365849263246579800\ 1356261421057747225453063194909354468613049077235718866481593149592601441552266369040300991822\ 0462359413201013897124487491521197935923529763152910617644899611383622453191528536537782144336\ 9283121489167362011632896606585936107132636209972794816019347107700063519748863464804693713793\ 2944874204772591648199330014043888345748610310662876991946116492390242870106139494582583327680\ 6994127741858670244673462406522777745738964267208834396705454075745761716597894998303969066359\ 4414954906381648963201539825067285523354458910582838018644910733063513030215272356548266777496\ 9567756941038881401760227047709416719641544226535481936960554172484550139006731641284585401635\ 1417034263012858276709248229109246237350805758550215601284344351403495562346242669568808415917\ 9966798218006507633001057247623757921380611579339108190186131590806878103479365745664259025635\ 5512458684214620165072190205851311412044838878841932630644566584617222155331673178906189927650\ 8134424165675091868329079944760440325063930028413237567099236771447297578791015628690774957427\ 2016382920296092015192035688218716179396620566917073890550480889239725441652153131111165898694\ 9735643709220269873038506182451703890582500362959177530252896116901880532514864601369965314511\ 2058695963554450923635153674081576425815558495202903546476838510374189963748978911340046705320\ 1611615847337329402241913154903055612280887594464936447565244837917803574304435513684536613064\ 8288097364949904378534773145813927156098634298520425400639347051541486152736821008448536722742\ 8913986188201089427391325754086181131419887267595822618520139159766794011833306209633923182680\ 6479689622550133631655313404906299524167834912307859220277083705060886561561745226496207957841\ 9060450662552061970685087441065781810672899752142451337280922447698363049050069802355847075629\ 2366582875113654216154179753047185419348580756557229112135184567415471604126671826893536898340\ 7127889353663421974390128176193401826190890672289220634097672614197245510644809361151631811762\ 5644521659280557733317710441397243092184620513879584463976280824373606343351626556153506431325\ 3458308678184806661614066741592167007847132645778637641743401119105283892613722924725724601428\ 3467152489455848020712722883762138111868769349317451668421548672238457130497524318143655918709\ 3535812547346871410043521435185383605438042234895776898380399438157944973347556729438308846381\ 7674414116941786124932742076365188037574038085415979433885648396918030754303032668691337953598\ 4511180103322240661273435895538670725763257940192515839638009222850739893311851152124357257012\ 5740772313637034176713691912368188465602534707363437828759755689806613691479633887611491975123\ 2282381607042775386533499015589475721673651983427430585037832151602866898477154256579739477225\ 2827508115936536101178640695319289047528806260227465022954764926405496821638001128266954075350\ 7231520422586428003997503105117815021957501094380826210901342101298576226112379104112848276567\ 2348037462618544502779554402710754495958826071243265781951333754864699455023434506838821000987\ 4672447537963036397124842685892045778992853184390454147858818801869947229211514487495234974905\ 5467932248113328164496163972328023350899782186673956941156062438735136863475349804940551544875\ 9344579183251778195723966576801645108634256354582354833812062931161159956523638566475258399961\ 1966690357788296363402947406332716530701155248346807286384622016814585305678983981539373464540\ 4085265629468102117856978366605848218188372276371806138353574250465573883435245690674885439424\ 5837789069087118820408558605390831864029569346733554912251998928479437792839933628701695043322\ 1662081550045907598507604736714970564319956324638958932411293948339639065243918319888059001073\ 1385207170744006922474626083290874394416299613888357564178060929651550892566514638045369304669\ 0665466414047083795405746717674604062470268609676053872089853680705778446790485912223859200502\ 9480936553004178544035006178171896646508676793426551484466939124323858051634018458336026089564\ 0205238799637572409249150924484835941600458822742333490688883504544909078291764822792789105945\ 7737700223341250334833895608230728583002941015372063146636682772857010765133676585066203932756\ 2246357835690237443139828279697216805149537442557801345847744156577999484982829965396750156241\ 1850590878127195823692798927362905984777039001252577681434395287723973342449319895124524724431\ 4279990129674608069739592974143421852834630021325881098073923970654424305691678580190512373679\ 3993401537542675089469427664366201361736929983575403291938526558674145044424648125807425918569\ 1337215589736066111018310084111519623290187087821989978007477012673346038047769968720084878265\ 6767001220474239133435888045263501583307982199400396478573020312097160093373121695586431413481\ 2873893136988140415905320253220238291270404381928027413542872687890550802445375869453511722945\ 6667847613770920902940060363855718964716965457050869710626910968614020818341154504441236734955\ 3041031979484932434868959199206311018864211454380108276399855341122744183817506404130564595195\ 2213600260911351123118313263482300586338268038995124050934609588032208072791165118421643087312\ 7741947970699128835861223326007393737087317733196769287787477450425237759713566812833373084094\ 7804437520091946536042742565179096516204480744492238686219436283502819074069305588929807390117\ 2343961301699622502805819602494111047531235890133501825844375073557969800975765505601028620279\ 9395482118028243599598900249417702561430844089113013083223401694540606939654053087957158397595\ 6730680730165430775161229056091414943223200154157507279709254540399902348926733897477134274123\ 9677775413537205957189050222045639664942742974256544241400388369409655898653279612476768245090\ 8176923714240735903595472508660050537895708975105447392472505882192988900468666321671064651531\ 9958064034533442652343873487993060793793683219296530999719139191404990405850024201204635137019\ 7426273069588793338867803356104490240394551587116622423376859201506123276833926280284088549995\ 2188903119070834698365146208844663527548995910350352409565111363049326245620128314569148607313\ 0404738954196164810168981485764998201041341770275774686831902657026711628677481884233942231653\ 1126653049849977559671094295626750874081490570584119834039994668509365291043304459727152597677\ 2394509160102401976915946714594121914791578865912979907008026099934447591158102048171030892153\ 7197669623072394499874856026236217509985698228443383377896926031516148580629283807337610167768\ 0639218010259301012324188329606187028019359951164560431291293130688719794647836990751218122404\ 8006710781683982698591786994559527655820384108079962082608672637246975389007428237829060773520\ 5625397827290868067097481181188129229067230156654111912168256657777355777378003576471489649985\ 0529009032016463134003049654308123821957422703972678722696746574139738240102252572409002937755\ 2170062078099872126658509965058286713102678054112578785180630705795035508223286472186797765097\ 3992199594714325216707641081482147788319608025373019360950452083680351422248325049572351272609\ 4880607808500773802286096355926495134138461381220207216847202156207506315161692144929762298547\ 8305929339219622915552749087373726825124213185223644350124446447497247670734422379240588264104\ 6161192426247838499062370220056432208277195127569199775571550287264819659103551571544341620591\ 4940913532756635590441179197892534425556125339128359574953994307523477428097657991273789865250\ 3093075599290532770238868782555271320578066735361037128469040238250031689860721990535708272986\ 8440015031454772103485484804523699989795262304823695188352951385677497909054982695469474038555\ 4562178115201269196937723833844455498123863803284587087079491444756797979816294385070811723197\ 9938773184668684850361319247374517449218006140789063632314427834818282868358064958656332485199\ 5797214606184930151998347423395972844729949981517676314821222091543056843269092102867198638514\ 1001005835772259266076494798549342904584876505929037430234582327648321141138924912882939380639\ 9151443671217895860439180457767393695234250712408312922202414177498088157872877302054626326136\ 6503650930281113347379715705428005694170644268465983971272700894383447092855547253454220574686\ 2818249969388704384624882025303644865160595072013711257838824281669848216345521705207815418989\ 6483064470857849474370616119042490260841589340556884520605462959338476818989809767247709248892\ 5786193039015335146318932442552479215610947994652617672937877434056772350562695129498234581717\ 9520452495709861547995607401229206521040413585027304172654113601046723589880874602662467952265\ 9861577731754665996040070383783041376708090559707167449034925182887701624437754902072703910816\ 2507696483531431362804161201608013285950570803366631229930737611781216535338552103525963943896\ 9206798808344770338034895477644700623209585454436707131941199967743334958942036415464278672362\ 2771678804683011053333777518303780291491656473383863545592723975347303410028187393151459503998\ 5734870111384738474858035581567262457186776327540138738887987377847423069273527502703022868171\ 9576214255358603720161344832954973241275694899784470619246574879483459452572872236661988503610\ 2594594534673223448987093818005455951330497052322701680243339607220222563561575290737490496918\ 3869567243438913338787464303321716100819818108851320878118964311803447323605656285364029332735\ 6130944491837340467872948321790462045581330395356592714062848659785821967649549568901100036898\ 1310466839542364193690002578790314529824809217140431882285014437223480299139310687401560545310\ 0838668893066694153261839154042684087862909484448238313591083296912905144330930961647004877564\ 2111268056905908739200582342108266751861775984759864437500132447644644654342972824127208421473\ 8149343307630013710815996053286050598690416584968027984196806636731822007078783208096577670684\ 7793983125996338075405332056004692227235721606723245112990106752227388969454626808276341830516\ 7645026502790558335731231917116343529935391015670073529275040073916030691657465363243171188529\ 2968469035041602538886820504033709039393510710930998437850802153494834075352966021367331058101\ 1172449226976871268492537873523351112292021155324090317844403163015317276120078878634396985779\ 0764263341114805168087208835092429062639348995875394729109216320382373357763492831898663431587\ 4354018468485173238527115484219054312059287952898238026454591357914501373654179497468117688282\ 3760240072178619810528770764972860038827126414539653864788843494944368478276857799590750942492\ 6145932057362296009959720313839175263170235480322585716624172269560473773214826845714172014374\ 8102301951882721334981371323005346557044521521567773636870934391516118698325199313382728801078\ 0467984364698202980945027550380365211463645679127175980291477681832507494227540030335337935440\ 1645218970582699088442545845586402393937213660920622830841175046450773864563440697202575933166\ 5310433795095401880399396686512056703754991344377508005649415261035634397417760450850908929406\ 0698841251373716975251097014569331436163633373675040693629097131611322475704334363433080067191\ 1176510559881739759182602586427847376273268995388482356643764282513461971865398484902185339502\ 2454613364710039520119525952332786061510936302326719199535842757012713020247420595558637867629\ 4017217646985447854236898672603122190527836070532756341899415628277336958942083170079321047803\ 1005262793801115722158215255500831439554815186681893156442116503903820305936166039110319458623\ 3752656279776040889455354310345478297355771145981877254695404705038731985254215749653760603425\ 4956294077665210967369160450414041110281657206301203367526368444950351028294438084323387073476\ 2430939358553074457375061973537519955456558428536697685346902502932437449506853172516370233602\ 0835258083286462811468262931923257208382049862584044452061597405574296680971093945496427663214\ 1985647018184436061519705609143028291598915436333066464822955594451039227842205546892576892223\ 8849946947759136052617851511295889886662231806293161239428279961055338223307521335919503460456\ 3778916185391527882807567542180389751024147259223279316053160729089423830382519084235715269826\ 1325574851359818264046760789418752238187383181404655764785985911120731851643960016275215328772\ 0608846564100926330579906026056924581861589215785276839209568122067876919114537684732593384817\ 6071180848241493453056562897171893183538544934603814408293170055788810887215497839974944257428\ 9293183198349238381450370108680826221343098816251356292903071422818732269593863212880749389509\ 1962593890314479381349589460513805896487501609320992476313995635600126279981017964633331179318\ 7171239096705749871437018807695917455656485241952982385922276403423745951285910737818716458615\ 7328310017352493815059885607242059892778938879400308019826883749362295239053635693946877464069\ 5537308098455600630121812830658367272037000140085016804349226325540419729131165930171769998388\ 9681749398283520329228067750412653305950228268030156457619678310519616073008416494695193873663\ 1726755147599728903567844375041606193731006912495036859997712139230251759541232359647205517077\ 9680159220724331021586100683837304879722612136093080756811625247328467827227640511315714173841\ 5166266964982605574848215077034945313398686166002703634868753621878738626614638791524454124540\ 0801728633260796855489623288678509473978579499211460519192629646940839007598055658140038022808\ 4324416245466216265568335765751592408280120317201629074007912964992925665576214633209437292402\ 4533024113168277324421278735940612478014623602149380350755544350349090287267045614359412718030\ 3812351364053468698543983358934805217184378788814555629601821692219283796098626755349825285793\ 8447464936650897561429198098361458331851462524644088949487439625986432324446535931561604917866\ 8577183422772201318510444680349732995439484541266886618833799446191973306860421746900938910409\ 6686051459761363520788287944809901333536765750082892098823125756726271963970106881462688027182\ 6372318025154458959383367175741095130354850673762366763155904601741271115133591887082237579926\ 7786874887870050051469798726723718251732495958903283230718444315036473724366284862957642883073\ 0134470061949677288883513784629124851035017636764090385909938753348730682990240199835505406908\ 5599393778312881298068877766920181334642705231492825841866286671260124584566120036143460913948\ 6055620036750955085159644486440293986745531309509961662915541506097012646418533181389973085181\ 8746525666309595270655206589832189757885996201290626094784645181353418221145990166745974215257\ 6206104309108806005437897025842756804828657874854886559293643663614547604107935124319692147633\ 4933788563581539311568260173396866240335283715030180830331783231929738027666056038997996595994\ 8652508669164495416231625605014228513224511695275166054624727823818047351674684169177337237748\ 0127633340139864059701780029245511380753800021386523425624067065932607815268155724976979074708\ 2726255549321067113951568833641910444747351957269101241580968386527101719252613043274784237604\ 3376282054241024323468651217264315286486015491380864127169440887133396238129796141146505330632\ 0045718918585922413464665177499405103682872069897951185457462256674724932349947233921031534825\ 9583710195694142366254775074923043443959994848376177546087189566034364380751871657799197340990\ 9864790696350321219406616858083280169968247488079087436509244923241058172275302612728156300367\ 2221276216619267149969016188930116617186400911286968738236479803924642402408624756679007202941\ 0844573534856819341108764161869992364561145711692268977628969524571930393528376894978011115503\ 0620078512410888063049789533566602046163881447164967694187196186792563037554016439361001513702\ 9948771095175304721893846119925166672071992276612581771460988328372857460106057145467458926142\ 3314063196081216099326868705267498216779490564823859241607404818169214113356160228585326980594\ 2251192602320777385556958936007311631170021810962001013444033210243450227920300027242863999996\ 9447186109428687924357667450624507691041375051492214977425066236842800071859927810047522176063\ 7832842581856713255795557441929605297250268143482902498290129097234740684333078486295524921420\ 6398313604738150956441534868221592028355483831601933146268468915349716401759326920896701364053\ 4609422893909007574570876501046492516908732746153908485432803930386465784572747949430233566627\ 8013317145680955156022804852412224976114902740533030263142805638476757837349600963609892347917\ 0375635627830460447136969342310742010257748875499398962901239191901973987482231180104129569355\ 4170056459916048505294896973120776432257589509560855416836129979112961150320332996099447752776\ 3490761522323521223348250801299410203842715038973675766310067709716576719130748529210129499552\ 7206432116229985164848190099202559606274535071904685356177084796119788973841666956453883654437\ 4506305939021123003154903641375918786757589365669604949499385615143248513606740700713209606212\ 0505869746189103150161695253195804049332284085064087142687032405006588113725210368839222592366\ 9657375543477101354657310467371761673396809838393742960600613271983583782544266893166897965130\ 9713583607152681631673929004467306414850010403989509901129925235025960079687829406336836339820\ 5285199388753512994699386664850750548047334253479071761366999018902586773163735413823106234610\ 1309233031476868360744291856511738817859122466949250479072280625595755404072883575309216243079\ 1567961434112707478924663261332071279172137854825248088834484872389676842401902927575780652973\ 3458991619748847911231262850038913343813740479690687473840028378814530227231345678154340887637\ 9780164353161083701160458579856936782174728958710076477283537432778340755354096514536607342704\ 4919596002833531526752225106467867391440056776947760632887001104164366829244899602195148790010\ 1510330424351792802334874102075951661330102017439400589975469109891641636965237829774255813178\ 2179169909427123922249807500615819166728768782722126275859950363878530700791336089350618065956\ 4283842532118134041715485850827426079911856352837289782786472343558944761575954936658410040442\ 6916354368204898073048665117684646728572159992398953258219409433812625337320824664518331739472\ 4664109768510652358018005681038485825595081361744274419697414843835520267545943416250308770627\ 0825932204646233537126784357320817626887441883096484144628616176331513038088989962636345172800\ 0572424382062601801805480759194764653532280123920345247524075956916942500838996153991619177705\ 8228022422410383281171211405295852060591248102892412137912474310430723067589472306239729712401\ 7241866239657271765753178853023769601738658010395259330864973181742973655124978721171627391870\ 3081278494820356161480458729801708094469747289446494257540519157588203941343039020287459935469\ 3784515726481348996497930598830657684027881859567339754665328988261399720782504601749573217526\ 7386762992063479275092395349322984197988395123858250086506072498579664268928634402082877884164\ 9093692711003402220925592591517942289216554994402856945150786863999285361043386865550041716203\ 1881089064797467020787418115240953808693326953934351932354389364432271857587499000993523421346\ 8572540800498986144346370480226659694339630133142090626260448759004326682123508777039162148694\ 9094408931458918612738099762460710654431271518394339209014670051063410464239483189181274793515\ 4472632853207293944458361388935253288883074828715502355131227462559679427038467891676139342661\ 2758218922608877541137915570994272080105881568072572871838320741592633096897388799474344365426\ 3866453646992323292297305949010974153450311928429859321029005167486276006344834951149833342250\ 6235626098073511518232048988627276021187399366233894128121026006223241194026977082904739961562\ 8270927901035570842817096962840369203403979738262419395014652822579803736817964060073424169747\ 3485174487021211402487147276798740111087666002353388103718809643242878979101956145398055460097\ 6858546436446361776747730113097832313929465435873871501374303983572111065608023027014787700750\ 4568600120644467562135133396789185289747493749167048463861838660682082211741058369712393632673\ 8300987795451942243955994989391085131980453603784384380398915638524479373336841527627215288237\ 1086277836162713777669494890086680310243637151790992017476226119268140836218648372498738945653\ 5525260346409879084427269201483780250005975123590449338548727111229424575634938662060331160315\ 5222715962030302112491249244692336626768665326390302647862244750989212874766118437087814120259\ 6173482390621142351431381919057088481470746850481655364118688498758016560383853061183860355150\ 0569817319081156939507855211159364231330322145141399663913542534770886779441098644539168340289\ 5010276327785150220243844226759379345105555177381729433242611320942793084460881038855396778407\ 8141785008260304120225824808011500692505588854156565365006629345254271716464241227574550474674\ 0480890694110362623804787011550309189987412414639987917979421879731401341570777479311396061653\ 5325975844401939589968731851105599530644845087050018585918664414560378930346152502084500546824\ 9576962998769159968102094359549060504240937895277573800489287965852381164411486238499425960635\ 4616673807691935841732245541922020591001686744439146343422769843441648055152928359010683590492\ 4822820884962215724086960939474455952217544257389810949018857012709983363997782145049994162443\ 6564251977908608069907313047168131713411084262766915531833106896396574333306707977374163624780\ 8291371914059710254457809725242775366127268765794509966653296768746541649398344511071136107711\ 9590761532932903540348175962796960400453491860163008712706994299446047058931021876749461877881\ 2534251340002157665421435835006109255088272308199804449188353519223203683856617059458828374020\ 1552534164725721013755117704808135445706973434023258170300008239394078120830277163459923118424\ 6764255626194805673199706632539635089758622671629519900448386112110747398175796364848148948105\ 4436247538166854917559468773731122976522770431595243343822965802990558868039885491727646784455\ 3923920134678789859952436832353038388890746727442173496278402654842347243102315844306504189999\ 2159744118627007856350172722562395337650347936962294952837620278817449427867970849652664864945\ 4596934113499184916166571684879822531559768878608057823246103939118887468938239566657546475744\ 0419369259519526997812489811893855293731936879653161774015991511988280851869357708264813176361\ 0068481271511593301393083988413575898279876997918872425871406970610327180704786550675828427418\ 8014071786425836675891434134062013819178658218016814670363380780309451572858211489012815852748\ 9109890827906698860825511183738451122729550925693345321316060253863782482604664510825206394199\ 8870666565821273977858225179708979697938101967308370012777058632582836437109334550971052949621\ 3590456093439035011974259927848260640980435299495679245135019869607587234728648251217046447985\ 9983494114146688961288077780380264885904043023697755041773612068608253644896791872002145003023\ 5603449078042962091484950141797703024508862436958269667038069928013263375968651294790479601384\ 3239909738345764153377531742731003916634366320546104717745207586852751336044795382549067845074\ 9596663139757364223853588766191992273273905812409132938750368155330017061675325849027540434616\ 7952540820738018575617854798336784221422212646427976392594088988120766316252092953780820556296\ 0214269017596284038803494492043244951360807265589358694440206889307048360838113039006960033860\ 4025531710582907208307156413671392115861357252356342843036135681735393838432135925124631207431\ 1043196689952992488237390478157955705443639399881899936904719573332803931106711679747274790925\ 5790007758003458812809292699454029921833639697888105600881361862127177125252593052992869058585\ 0705663154333371044265527767342381241384284791022763602784827029342008484639444946828262292671\ 0003427439820335164244621500500179124002657378534788563756063422938755869623129457098933035119\ 0063896220697661270686612852181336459846239653290769947750709702307976361427045883844851086627\ 7839018199491189832629619492478131106580990385682195026707742833351403532451814911419938599107\ 8379404343354612960085421644763220044935286461608185221623604272368423895184520722754943148406\ 2050612401026310121134861913551513945620031589810670167757672588554997450453326111853952799961\ 0177007098044980459563939552085186347215577594205881653936411590666698735648029568600490084047\ 2409246071653451172343339494955039979316868128232692797658340910800044051824959923737078413807\ 0659393422693878377228304911372779161392364075904361959093743192210676374212954904693324802452\ 9376848464993761436301471153775040425279293253287141321565461315571990255630009970393851211543\ 1802949592719741501951817513980380202911108543998051927362656782375387141258290123689734604352\ 6107569254760419419288533711595342182197448624095281405091553165364237925331752063440005475610\ 3584394968957408107505871061781848629029861390727418965204042942378345240162573937228131955169\ 8328336436061184354319452447782436360163526875730768121211799953866614673890708773036259793812\ 6669859613899801867265347836440098503639855078765081900458098515747746236995801378499805702497\ 4507909201709082454544171397320675486709114078235159456256670924356520648652553898951785886799\ 7490821113831701468736026467125865249482435500362337874438922308603810513175630713091218100931\ 6486976836471328121132008424747776162702194259051122296613621549414837756251057451347401470852\ 1636195555912929476997810095122297743809414734691712356395528135855098595756545445409691269431\ 3663669239742744423852839495976585805702315566873258585841937678375161588091463878792587414859\ 7040940096928476618540590255078458725058743801704552297373397653126267423323771904187987413735\ 7762182907917941526419664081410682817232227335462765037759769600404542054245965642003962627017\ 0182315395098148252452171045440385237265436077302837279080558726289199639108587843640167384441\ 9110696994667406921368733584702321692206563692692867137642237380658243411581881422537641548440\ 4881731331858191313976970007472177123526871376673377746332839027571018368022710723032837587975\ 8961663821678072370091925429493586699116343089447073571825469069448101814960058750317093677964\ 5861778734943208534816903894964699167130663313736360790804304906404835782982213293686095935863\ 7760428251982541955808698750879949299446659648807140876003817871709409066740602369917935162446\ 4693316084356579973580736239855312987344104335025402718204503856153937629567319151294055857305\ 4305185122483180711177133527230720733152582925338393741145949925318323405165439333911946433448\ 0785809642605378819054784887877367824519255462284790471157255555911679642767835953149729440494\ 7767598503570686404586709158105883092538043372995196442351186434427550822085097172372195807939\ 1225926445521065995324664254519775188585456613066692226629615235354907318620576165248167477703\ 8325848249787201142330632055336175902885843513603987778670269948566453817501091465479193442831\ 0027700069649153255952741190953857575634690710218280502348627437259574589419484063741330289978\ 0681610695250578757957514522657473668239255737640555800091025015651671679064455070159539796720\ 5524174326749312222494977347364376107886370390580439756576690225209817268065581424133051444349\ 2003393640302286484709044070328222613049147174896143500862661443951939842723783126698016800845\ 8970148204330679356134732518413350286884813382853932044938490643812126600194853126748524916201\ 7855376683711488037701417360000015252606938039787410234655961526376542616002679692033431757689\ 3472438833375698939673345293301845829365099188898673106185590015920475185776316502574466455619\ 1234998247328789719632915564787032075857467240351760462718591678283381324503943695324786465753\ 7485671700558599688824065127879015845129048855746488397748995980063348918799343910574622103400\ 8958119326200099193073135092578592666957914709070955311861082148973364971802441389833259930382\ 7596270481930593182055019002454595682892346794722127722147945142352331802750518505491313558263\ 1401248233134990734598445936790359327676894574796062667978190937469867681200039957816053888426\ 8425899318546252932100434530727211869172765370669198521553511607759480378578804925152699299246\ 2578740428740824398900079482840352104450013317440750007435046930672945213449458374617916898257\ 7049033978308009243832058514475735486723102956838626770691676978138783387369871405587471004011\ 3849538052850656391884492854181900260674174545435634337741942110626174089201913845646742306791\ 5967113987997295802861474653736810682712461878781690011006253503518950329042732796111010373159\ 0776211508386105245316433736936494686835466566151958743003585766272906635499573543770114407431\ 1699167804644643203127924298797820044856594067904268001842852875162513246823848758846396900602\ 8953325687822606779157266994460455770398781848648782842466945864564411208305127493204592572922\ 4501238104660734821093275809828363708679907939358213295735660113687552811485041125859160420435\ 0277221262016217549431215563914624387513052878593968626674124357455225373580501094640609153317\ 5789965865733571276611981414898996827056628592592310144930242815199479954450694392138934144042\ 9898334434848565982816905591227504975397658173649894595323321384671215785557971463968517735428\ 5020272188733167549512215518299342922192781648632625689303837328931827205717624235895664671355\ 8335256316929839068542045392080914190099913737864773430155751958726311716817172891918455920482\ 3709922674109916198851633258662335532500708919124406958706702298304230340515360865869287224570\ 9278744293341106692053944383331091185377390807915098339679504029334476621049821295892498303380\ 6237751422794208579317661358268661359232454203839076516414541359711511052233517231837224288946\ 1017466676473977562751990293859121291042913951661309992470232589660265314683256150068698457406\ 4591904849213442599196608208025193169654441688445694522391707826166966116059712629727864899954\ 0306250438289204909263651259100539785747463865427414148762773495965848095114126962822604900165\ 5215157224643259781077328067773647504277653744393796971211325232211352432660178425290617287572\ 6781766841951734115691296325966370214571610143084501690759370699839918309865818842377067809852\ 1147405296157264125060219401261513874059017020635284091282345396742276918036631374839180408330\ 4786309828628146187776631990653243631174261783870569942586887786766609967319761778237270920139\ 8739799205470563469118737637016903717592353384661799898101325785281681373419772300175487618241\ 4669309794202576463752972739272603140500161949780058858829332424077442895792405528045160477765\ 0074985638947066865871749320083488439607237272412707997190443634448534442883875731362572618482\ 3974440594026816548918469287602190335024490988543231860656468234966983816129193456982601843085\ 1203282102962708067866607421201172160053816515907227324083854797563318335346476659051425350735\ 6895788447914745401715102222467900297640934968054945818744955676848778891834073446076092175033\ 4807139354616151271016859103258459118338971454999259440476406761024621253066568275588947379364\ 6419788416507018630124640481623654980074046086044421364842798140424286181386819240762674387815\ 1928221577331933929560259908926859198503888408683291386654918088811665269445454170443646344193\ 1466800158700545097767144053906199752674259090305283570568443483248934475284808183590511507846\ 5642903136282706050568264574637181939984306575924450328377517194763291301894673641115126088355\ 3162440475678982813904625599713942698056005097103925183144078816802210002607272876017106897906\ 8825274590479613682709982759341635218625312336883799479774727758399073020212011695396535253090\ 0612764212018200903229268275929740701517741063004038704850406232769031680353198861719515255327\ 5601704668049558480984440144457418509673629462554444470904277775353375874813483050555559294190\ 8563342601962265314017494962153966737308208944729736436625043479641621243108698440971781541084\ 6278207184983715876023281017839864973617178863462629623584195782807426106341594754087315002910\ 5265464206614093828100242426079256207491940867550518807874841553819589285442148971296336572212\ 6039288882826971653352103610633306323259228440497591980454631986444617580982358330433028002385\ 5876680728241836073792064035669491034632823727022881498619200140806984701259457281007099430902\ 5146564112251387909536649068490379918408781249065678561253403809861032075925851629218478397551\ 6306208724961771065800213610200310606040276549595521705726593573723900669505044545440455467757\ 2304216824185217317797740101218652487054682415179983033836059397147923026475323643804422095699\ 6667701802364166996317209356319718134782776358655599947417817194454992769771435589099891767416\ 6405227073517912964817132908091354204741746217292673452044150275752870737005565968598231361764\ 4316661960101529854136097420939173542172765124392870723411213948316791982237727258033539541532\ 1048037496409726303282172752590536527041995767607237735349388759336752826177895622652234868124\ 7217580353440388884488377723104257959201966538703231862324221557558666205477893025118675561289\ 0464452961589975214284900663861765957919549214648985317251303885957494944160798565456189236617\ 2767095607479657387570171657088911399345568787663336530430542633941490161129771506928592607719\ 8071121840503144708646170821298237008503548535498621073619222599950107038118837955522996780801\ 8965445625408510741668252967620835318997378186939014966447451925744738018673121562155989905096\ 2212837754505147413813522646600595191633222843692337066499563879872147450798264087396685102992\ 2623016743757310819163445180740995231967580383231379515066891428364910365436511560128465306865\ 6739725910393613697381187485259004663425802120748681637589788455268376298230865028983462935263\ 7400692425034672386854533671661339875797587910621272640563361838563746287921592391695147767499\ 0804676628996825989400504354514674324582694661087663695757860787417371073479684217693595055715\ 0447805282032264542466470832123837537547881039569670271763828365925866302779325544148343236529\ 4457793878778150448332026804974341897874855969127131512061328680954682920601831994336518623648\ 9507976968983200315389249933321185964943025993520982005629611055847016750348153014448589832282\ 2767733218338816491694905785417297099396960273205747516449336690159467971821811158163298395821\ 1456546748738414210138204442675184539921832045144950460940482916404088253670499271599688762096\ 8684071323916296105662761712662011556245599785642086728552228779805489084769881568348146436564\ 8715066578609268318365894542435847653088122566467147879045665156237430775634474352650662558865\ 2677909368019223873222751692758181504663720338082803471954486464353944604762803560752915558167\ 0314769762054969763641402581696652569804929121627053926549255591514458408315006809825963417556\ 2297998121701518778439792735270930945666531277776367496849178788646338408519815426835544289487\ 8263289236353091943949096520962894433764935264416736497837986801910200210069177917111947982984\ 1905345651589137079374087226345948178203179682214301447658673985269038988480032782087014265211\ 6807558408912072893838717053168004005290352514566890164928625926099396014128714657510365860679\ 3049516769816174916251093533648705099071378549876032599310195133581869188101342419517958610073\ 5095810630386794730043151850701631873261857689324418045735376677857258952005682014307099751273\ 9318035103551059740319978456855313639140829676610023970546278741060530300305461601476759292209\ 7934688555798272125947277099348353522731905449317496430605558456643324020034343142065059970766\ 3177192412270032681402558861678839898665667265836830157028891087164776715592332936220260392874\ 7223974670363114250068639304069767718607813690137633373835311671663706934042798117075971704450\ 2254056922498402371410129659412462091336993721871322437258130186631978297049137132920347128130\ 3219075632880689453127369002777696859625805534454001462614571928741175512707310844408786366138\ 3820886557220357569675320890066798937528777017298100073432748166860104192718265591722535449141\ 5272849315444236320724474612851928108505524386924029533835645774538355759097660710601114706871\ 3712902951873790378893645240937262293139674813366581157832741273789213400044385114704448525264\ 8738055772462498163646133585665008175207684469540692884989677921092424095651500814766020587793\ 2349112376924391240341358536112184216925170750881662736172480129141220072949517654461108129933\ 3081191649921610872249521724031391329645461279390735171373347087473993157692829355597253575447\ 5957912779724606469213714879722656128881644499484802786230115917531017320484153659541312635692\ 4511000808296257240722746146764655594806308413323854532367786309013418172660510976048199649489\ 1326043070746266892724817770714544644578859455232239899752951115911545090154670796811744606613\ 3763032336138047212813833879469396163186456917618689181416253577367791262648066853150702283653\ 2527038974109242971739930423704150309868016551330621765814438157400561810487263974911767818935\ 0805931772597988992439611367329479164831938204297931093593042949132408738591804540449355725849\ 0086968932171424580797983905276728012786996140928780804143701595835408925401399973648828642630\ 7765940275171959109110862325322827267664755882957810066315532549008410094872406322453908817905\ 9826408083357138111881737375889342311309363352298275417515788826702045464354167129774243926892\ 4419782237572765179895338169371511116690654234242003670362848135152627518211037375630531598451\ 4183232182844195842775173440149397962293763901747849324335767511696778056513422183837649348759\ 1968924291497171486725023548335505344658926087957136683223706500058043696872263552860862678778\ 7412128591669404256497873967468432647645007498194795833253854000144012795709124928332760369595\ 1625992040494448120338984366014615116142730604520101980675728143925708602075304794388216648202\ 9082775001056778435935325908873268648725208873506111324839770522506744109632563331958872971571\ 9643707048693678725472884515621085332972896036582202867308825589051265524984552328753693214356\ 3413200413694584944204334869592285026059151698131832294405744172069575113365277407651876910829\ 1466792198612488781962525722823665755456579900843598067754919866920213207911353793205254819246\ 9380420455910917151461481978011491365243528730356227366800011038280965615007240176153186532844\ 4496411275960929132196653880506660720127744917734275452942916540342094709318500264491475449995\ 5288846928494720790002666235985457753543721845026067239635923823332031791291639462160389311657\ 4964495319999743283555902501851842599524564457351263445160556340636778416023106603001734920858\ 7322399663660850331539572840111142267758263337557129618308060383500126294325547289744159256944\ 8130396808975657309608838421716143538817984813219688571572189099647488099923987300969118543500\ 7409105387573244932739023153930418196983711294613768746610433677833394532138326188775771459796\ 0797119304719400837216984434536894710062065859978593788170186912522848142952683106753035519447\ 1715610245888119318504287237415686984845670504288408491212059829952055377764104209050338953438\ 0203341222892782003268988370351237198310049818171718801826683964889609400561394180269351460251\ 0848340873828986860183034889054814652964563133228545193391612419369192556097020860236592823922\ 5684708756336378939036161397509539394320363629209912649871102717512903538159989868155791474897\ 7625082615794552558601094442986740483835893656551324675736758148359511564362604083063415008554\ 5862980226455364400652207070055101836983881727122733494599006201620292269233238004052786275892\ 6134107214078491008476313623650106934644346295788600624985400216851821848753698683238763517008\ 1615599411876777836154144074301344144889165319097549442090449519058172992641935377560394240378\ 4431538522055342968158808761901115157570619885736215361387272916892574609786817140965415648280\ 7401184864325047186512789117247332270867605835855701933329713796947335468532419770056101664857\ 1996847956847392643899404307379027515911501065656796167343882804113528130763758447581604064007\ 8914934048025471695603672470594751356229717127563279505146819717569255232941622273072306486853\ 9097992688097101028813927441616466337120661353227026331099131133006930397530338781353340780145\ 3128960791596447270537130283758547029913446079055587833938964967902680002273983959057145390856\ 3794600760077120837184164638166013009655183181110848513982665114400655650116586589589314813659\ 5976910524189441753278943865498369449373098429536233103019632844595705171077398239396230593249\ 1194299611284364620453305758624240542530124670769231736617209515331028255808343570780975747584\ 3569012920061362738310303539525011287119776800224913027520391151508234371981047289995488227319\ 8988905277166088155882306937482455139159859668592634873493485176093494750007911745482250962389\ 2474684866436577214117763117473684542035554650047312357805516287823368601328859554706592276144\ 8428568630150304553005781819811217261123920599956177311291570538249184713104645421513563520525\ 8965495984164237930274898015072863875350287577637685389212553202650631335364016090252945313968\ 7505438680249411127798602373822736428296570329856462676948524035679257580614041199716228245287\ 8114441088227138071848393621425592863177871044308962965070506733847849841888504162748398246634\ 9996186871481498213603143629115690052751989962714195673346039323624044195063525748654972953587\ 4188175119964022991656608984641296689768745989467510921902470310811529688338182803771529009461\ 0440394637436607861644889157372346092107881235439076381245224768380327168069748584915174975600\ 2714265475888292893221069299767498662854434078353981152839796319584354540783826732560120547896\ 3443442023926602422747636252366220501623867019703758147652469786832827016135020581050758428703\ 9383174219099317267319344437458955765864189911510840578728549189985642990872005500793569324220\ 9248402102625929278727992324142068924112804859526207896611089149113202862024131340904274036058\ 1475546702274661108734049393201960576542060289926852839998496688820914419062184067412616253740\ 9272764094423205602107866742670470037208391553895286294743606295900940349833208980386713997988\ 5616233816864836701749905357263003587715773211852946052076676301903815946042359770302932193066\ 7139752024320406517980086247723771012182131129721116010132854174020484933670130050524155905812\ 3589153846204711346504726355565656558566486835656731485980165020609173397575714726358135913159\ 4594068476241608365582461981347446026247340156623598040817465419566102712425672104680647975073\ 3019975328541433924706222815263548071276475478026194737471072842941221956271358952553686004566\ 0274669143779846719197616368188828788200147040500763941317150182443552331308881675704573726583\ 9243540611761905003917374231770404310440662982006811585942863404535722529313771616693620221242\ 5705541955449104708253393158952823495170036828974624454237582811882205831474725497821253696952\ 2113163015006375795665708099872910766184504177414706233986336475204330265561614463070056748946\ 9743131839013085464016525650385329329096669685048784710952802102032859230775862575142729579559\ 9359537673908775854069398974753809317477317911696785819450984418319925976288020904542339012718\ 9773645497385846392000936288765340615115304833900962543742193130200362597445946457165796570536\ 7885571240689608807459517051571397413362547113560105417671977124449982321347327335402109155004\ 9859248336580630144575442292857874397129277420994747939767987659482599698667408323241232629828\ 8174101767385552313926994808351460727708470612457864734647914017908013487356079872609485523097\ 6564557604804707809163004439684265487765922169084449160594381144974697913501785687785111799948\ 2141681309164865911853956023703572424948319481126093174480943265338117153731668720547467217195\ 9210467953182363994346392831801466129099239811017531285707557163780430675848278115429900137445\ 0258977390647935628043077175756565675578123148809451043552038068057628214306427187155437366956\ 0848620872245465409660809430527314823320473402146972388454192721030230221989643641458946477011\ 0337258127358411426047223111903439312164899897801619636918078886621456856873791718615516128212\ 9752913083639411894692457936021083864324996138631005537989683066244458971347085109893205119174\ 8400654268683759507493547640558440467441778809637737472833798900882197906883743605150758594912\ 0820411816656601761727167344616407872448398781906844396319390095998571326121138053179130544513\ 8568295356357820616561084952487691406114661558672064870833809267822540969991295302669234641584\ 7373695660880172862724243345712379515794589662251174052220184550639099033970658337759409699875\ 5467291006935834670051807640114017387004508440112036581001344691378180891536147407018950284037\ 5520851423344476414692351040298545920505230581229342007668525833601787847673388526598333407921\ 7515160453488894360025800005416963668825706620031715300727433166222989526097472825315478352720\ 0543441769268231385790302185834604401449035370506949867960081133068773446210476442992811080929\ 5443568618513721728743495030874389446154527815512398655955472768193267149426050129483605902031\ 1086475263211523114229621169447475100454049538932960778904723862437069197595384043652097373683\ 6489812517074027618341564448424584390573542128197107485397078182072704173982464521145015630200\ 9654440734497730983361437860277468922614335275258742800451337562021101419299048283764162270221\ 5169864771383312990721826196439311937315089512373974573334816968867920075971450963080424225153\ 9399269465329798111108323665136896978262683227162873880601059055618168824273838706160878871820\ 5457949531528492157479819567667189668882020536916597069811802344883234046924676725182151187590\ 0433695403604545928568802516475019245965618602420983311692128125276436463792095281405118801592\ 8429557186931163864281975798920768576545996194948119094291715682432711024989825769585247459958\ 8976060437131132189188770222846364333224040587414891083007547064787539783752336760379372265153\ 1626194448900460852275595864239051210771385497731484561789968141250621315414194100183384489958\ 5066988341723694211872304165679533807197701782022110095491295778596302012625114514057703401524\ 3870284428166964205341601609625725570508053054480044388247222042609591051996828938078809712917\ 1507461825657497343850187646595526460550487631437119981709604855001115380659836475458534174117\ 8348177764925323700574584115407212601358022671652762936627440264152643790068973945187304461572\ 0872945021948112901285160553754061689974025258081265756149424002601685549124873212219853726981\ 4784069155270925629107691659060560867928830797553368410509591169242043463685373212819284187679\ 7755264073173998866321592262019509496109721925003845646944015241985437831498738469188847546561\ 2134908022335823593620811060042752451673745828226416383744632267477810523602160290027515826007\ 6440379319934874687375712978387053048257596838489925550586888012528566451465554179071078986696\ 0837434104643589756782090010214893675752182265286904325751217094731048850667151159826487091374\ 0551643785231066035415360966516002103598456451603266103384054048786162861220590835482509666629\ 0599608338593445841267758182305327290756164747771861445284737772776459216127680550477518569093\ 2831624887164220396064122881392329686307388373313370469030832889587875385422036565953138258445\ 1564717452241912386794679431728518720304446430131127347287631079215480162765440576838722477299\ 2572853712831960588629610532522056676695135445903648391184094054555972594248977907987455739057\ 7953297194722701251905118229493431213819997937082995231329666533551932257008451835156374264467\ 6787796701593898208809356026818109379736714126725294297809314611389653751315560939570864128222\ 7097874615205885738030467885645343659047094164383361818714276975442219997216401873108418392484\ 1086205821647411191641480018055535937070910612880801681882497674500925086406475046006723570179\ 4435375391924275976506121687284871013572652349976978861426243203503624780691759894711855357174\ 7918339410748919716620107150467042154281136428800121736695388018456233764108700530439871922873\ 0333467249079825916512614534448196562250330936916729024278045447658742321599759215860079015092\ 4819082104319641317916958238556128899603553146813687837561198236696207303522999143268939403925\ 6640819339229534151108874294084429037903681795705987611629987909365896762872864630578781775598\ 6793116098038777510287703912361225442954824784525628002376351824916641196252595565255310408081\ 5391384699889198646755989311079481233669635485312525428311527631788341671419450735776113788443\ 5812681300276984161668198043048775025458757144820642928348554826048413571822228074441375285921\ 1599705341244862178804288069741180859324829124854758858686983983253472509134623632817869937497\ 3845785260306522742582976905053564210866680448136144789371221963074759163671243566809200111155\ 9175372741900003369634121265174692774047043322404097977773377411483921562667037302282358200271\ 5310979034611122376231157691383412785699070333301342671262978925953265489560462332046547936172\ 3394305817570561355447166216759714126744999112331456173591440664574749470752995036616819597580\ 6310443280491095259396074400962897513593925653549843411748790567950390162721169287920143812103\ 3225605907794997401865941727802364217007990630107791816977190215325549710271945127389557291174\ 7160731689825425456112179316632185260652848084825559296998951199622137162806469605322480785289\ 1991440781729754181074428205616713655230925515272263691520279554484791633095088213685536859995\ 3866271278407987492457188019030082899463722110579113759361715552411040808983935587446419714524\ 1420899503103740425325231764996678871883200783062690689600987995730363055198548326650831091459\ 5926955244535298341573175648868566076243702093552414479831211713546091890255180853893366190442\ 8771741678073156733465826377647892829735321447378576336472344681787139113974157926855097626017\ 8168369265342246441340608879660126662887440851254740133820722852517411214896143344933901147815\ 3184782314562391531904671670584046100503167376056364914906676180858311443957399441426733381229\ 9760338705956398116441604858320689630200848768670450473294653342665456044788668851654377338902\ 0582698645914588325262615440012302909181657151018216817501074231648923369540202545767495135842\ 6504943467648683749673903122064364160489846913250877927029001077473366574603414438419054517328\ 6731434371624219677866668768520105393609177661606789477638712870134647044393573133039959256383\ 0091782773343593689948227762665763779176132596586726882085162474427452949899627695159475726197\ 5844937995447199150969292208632060688402117982038147863003361238817019538223672371668684785771\ 3005676363259826950492166769696421514684339787828330856473092045467418814353229967123478029072\ 9418731884642890446771617177167569072354972004979871231511514391989534914068101594824113613101\ 6728218188237037982827689068377646142333794257573852620682745943737723212540210823199393401688\ 2137781374031753485895986700328278288768572832380475656788101123488194706460944661507127459731\ 0927736632922765853651381827956176225795815452521286548621127894772144032809923494217537683685\ 8223306395357867776194308508000361157239409082526327122513775449804116861826295564204084968833\ 1509923208483661782181861872168197590918497812876357526162373078353396399914703586188197416185\ 7368128699633263173381614044578317640747450404896405108620011852638614414844275727958112767777\ 3434784655187278122710292703781308012362207458715780194998321355916798231152019447456620496561\ 9993913271582536173281191099266283590648734468455847818830887944942526648772755848913218294836\ 4311068570476546508425558867745355838465838796594229066698790044223433268680705660843442992156\ 3673036442876919838054682128558046762203811253927553135018503539836002146978373273886031955634\ 7020211279952441943424917143557974828225266906468885408536593715407182693743597494707049465646\ 2190672957139330670786689531244368849360340847522196362492754962005058358023516970975406133123\ 8074875231184185310853980871208639556224704289761938405484059054031899996496580226919010719417\ 6165210047737897817810383429066403819679144902307284721040045789270130453594983896138983767914\ 1587910624562335138270673610943557859511915823633940914084588728503935178217602754547222707360\ 9301794094254808743450199253107258027502795422715642613594615439443959955897045056353346172749\ 6838390788466235320888562708232690702582985744081492324790882730084291602111268445631181532460\ 8259652249833871994572858485139157260277080011492625873157677732338996799683449824563932139528\ 9853077990754168224740665365358604476665123111984486953478009743650547357030484517275172216459\ 7178958762418495853650087627576720199724658528987061546921254619427481698162608154384802162018\ 0861921017262310690772257406172064793996765024066666107375493368303969429488057255568316644059\ 2891146502488736208252260605772362200099144048391639439105257141123015011054696299840656710070\ 3580275282393146842189774767302579564193809874485428821402824611052693781795002352449321189873\ 0174667989463058549776416075384086899538160716409739212578707933912140415531118335559130614554\ 7841336191513845252720113153085685102823108379948278402071735626997055516996859179921053706883\ 0343629649149196684703008807716573129365639452088403052781246775262954897576519951346213875192\ 2806883762152596225441566914780597505383467666088773271679450465579529596482251139841554677092\ 1717659257492323503041343437824994241259338602253717315594523605685228818946990701685124867636\ 2487087957468920301551483868692914220139167883693567688480842806463865659731126074039378370817\ 3908041744497901706507803442096483195695150675401958339335711862341971265630338747248629153559\ 5275205604258201944511269521410441974696622876258395799834705294164393217011029849118274114028\ 0398031834915041669919284697215853576708330078418033608181228002499714820179075086457008629996\ 7088394053236914687728742375961201164479628956230632298315400992157535395514906473828824499918\ 8307469671901621087089081306941643644543985602829001570014890827665776644293646339768517026235\ 7222934248261601997514644267866069532137740970523498620180852237781581872472543003836073296700\ 0714635250285455730948689906220842926520100398449820544729940775245346076114067866508334687483\ 6968291509460487554493858392700824745284450681058408745300005226074480933154218335539217639023\ 7935353243420963756226464859017403730283462129812428990601529899737077078735643571833340436229\ 9159912555340246943383991733808162275957975334270675328157355356126603667493255212161874513141\ 2505860900684045250198784989973643798604636233400023207413535888110349547679964697425283266913\ 7494696271178514288678399951344073570413350207815693388621335061566255652863283909997951364568\ 8805878892308646263982660485836937447650222108821577661784407334662244336015265355251208660748\ 1236605399050733107490070774020555853606713193563486165618130491291825785988601699863229798936\ 5959246657923624187570576847712119723750996550172535962852647863097711984060766779629932743435\ 8564732129912484661478790458661225310812610366846265612370398615039300400288506899920231102836\ 2231015936314085799291760448749468640310294980726903887820704315353726926427650453610655199705\ 2903101772135571050615010133129335662260428594989023010304876030244471598095185528185085999126\ 2060804215703075036644298676592438967503172156167077554647557444574211443821604810458572666423\ 4875419216977155301757267042977596855094997076138518755121441336984982251996512845110159923352\ 8882598429950160242010332032388758727683968360546913239750079837480558272037602156348609277994\ 5005997894835860713158909220149631342725139444238292549038940438810001767895650086050372303658\ 2740092020552533213027000806967675670454410217858005635401534193458594667260581100448991477163\ 0830742617706290972271991086532358089334872423653270088268236969321215291469327824074167183661\ 0235411360303988578792194452279566611916905896271422883857069345247807247220098838474373016815\ 0813365075268186353146716799457530776336488320909791194000407307692390509270682207185846125891\ 9381612260613743170328903855079049890979577917090604093982909479868948545566948799161113347482\ 1759378722706418673722364426861143188152647357265289186128886240415771394214209887242795750923\ 4264438541292127182837325454452756227964859902804771154681307268060790131337122344436813426346\ 2437264715401680366048841745050920550912076388682822450435306575188623332055584209882026126835\ 5317340442335388833488658931705081063688408737283872017843349441510069462307501483634845407806\ 3128770801287433048795590409433259918795681420843857563697209174014717631711705062057644636201\ 1460479207629369636853474305443637652463000344132345052553213889784917974994159787741150286407\ 5149266364107985222396889432938980686057192680949666689994182250508080224508226097924509156373\ 0346940260981842540759604843470140859008650295594531022309110033777113779425795314381148979639\ 1408110147714500914840990339561162932497021109552021679745759845494563353982427427974847608780\ 2949160273387321307854936424093620258906126688890545728529024246483415083077991980343210637644\ 2850095466738551359210149969846705955081697035823266950175204391470669426297216333848715598466\ 5156078732086706768169753899516003426337833218335605508065497073519542608155549248539166775946\ 1136274104193617839292368456922540581632915618383737753356343387470214179584655309542512285980\ 2385206753900875281489194728360905190406625449398510391178822882423066776028145758770118545087\ 4995193156663759540037524089485200422091807417090941091913857932645518615366023035399844071084\ 1236110151798208778084472094047067117219448831499563988253226873728016503115215518964067985606\ 2489968349762987340853308021938828621486243220944159023525148598005437067096738758544700678040\ 1206853684381322747048176151201781546773807391963430727247135171203741180305903034329949715809\ 5688468045627565090866701733197155323506723985227536982913499733806006319144207826784689138109\ 4549017610770515612229315711787520954438165407142079224699679631804638339141768707419225675166\ 2676764448709899025728535175966058425716033956403745183984591990037783253076781883033778910405\ 7954869760641344245061687048308819333348147917205993944890243827091129539856229506056575890017\ 5525472027573249505319644015851625139510664752057537639745942230283088365701655220916708945166\ 4142260501046770499287152769241395480833315448526595943656673043228358328033463838191191634587\ 9066779651179710620774540300799220296921062092591276964396729521001979062916096356477197114611\ 5119055334906949515944274892678023706748158761552908629113674138202652420905352277963447780651\ 1617020821499692631454421867936392008748385185528657364619723592581456251930470124697644629706\ 3570368416956772187193423324570398316503427405211487114923013003180415655896541817564696487199\ 7143231978868350624317945956187191203181585691744788936979840019627212016788401872800087722792\ 7416510003357340218227201435962700179344433962086588990810697596619452154751678304912192199718\ 4071054895682578258689216721176017629487163714731249313304865173854230942704039706214240946217\ 6068308924763812218362705768873144343947301210651371007054877800151058398845830442654039752219\ 8639454662781948532896030143047071349799771539522915942159672856685013193361996504102209347849\ 8714571795831996418566863576615836444626999328360614650669183546269770060713366501896957650145\ 7906557400695970461590071475324590778930879715090290094247233342184851651821426145421763368000\ 5887651320168385398250187903903457299245917944288164462040283721736926279474611301339242561431\ 9706447070946273789598115948917434903070772471989702703165213871988939518282857091312318632642\ 0458021584251120128510500045411996171243573960603517923753128161730419524576492261340933709370\ 3603787224977223734405787474214064103000280323892006030961603985344823443194114958602184364697\ 2900720457091284731751690799686627238568036667515275706700420729128757479203954076923422624559\ 6811777421139251641295848322687921830676966101773201309864644469779659770445333911213617423245\ 1329309946660650777775445367802473319151137534190927781276173908440460807981605152632605746139\ 6303528059839233264578272268619120773528611061993924547386193626462700577359978869769229646919\ 7818594361857521551845158224461076960481789843667087347829547281406704197432707471550533509920\ 8842641579018144398308721828930201398361911729294837548035543906076573009233075745012993283251\ 4654145288504847987630606130392706525064921141250864728515185930448880916776804399708289148437\ 0282957416833526854151902016384494494690043451950677543745387826275186401306425512432797051258\ 6917478983475748533413010550909238341797911601513169713753527172466086239710694626956513264539\ 0617770443998195421537729352778045430131278126262118082725582063719459895621199526653389603483\ 7647856732619201857260028761390926998984857512382401155860365104956155304820447108864858907597\ 0570036279597879912567316122750992227265521469932001197924245019228954288681790365965278448003\ 4062467975088463308206913076618357347905793812872482840364082108219428543278956176593893131846\ 9703444660541705270623822335736899882361222792638650633525609269544974558886650784430934280031\ 3534203368287221997611727412253854181634676344304883014674437181115406032832848086856164105437\ 7354562896887312255383380438189946498074785110904569774812224649062233443228906250010923232239\ 8785667249847151355500523116071328126177529562553940684710319355872495885437712608568445523427\ 9405263880811318353564919911264469740427159490948908563072377108950703616934053868807789836589\ 4498696643314905658698201117653349094187999043580342516175235158699786815675902943745768214468\ 3963148262577835637069309559852901911248783802676346859203284433870438601222979028318445696121\ 4057707243410416622774737518970084102129597441433293054976167034265292223617238153567988813886\ 6845955906863111726474688241811203041363675054328120534440949410201401139781435755536994376216\ 6647275424791336950617885509653100572464438133151519707886230654813126098868643197552644843492\ 1650422181142389020475747280180501324731241270292505886798220859659473548395336708522083956870\ 8392587199995193593430395588996242849194536352458443459594125966208869438769549671230090630327\ 2579652547413446065010558461984807152567081864598389174540666908484330585558423301167482136362\ 5716588753094034378319174070094693533197677284601942378656430626235730466172092774527761444412\ 0542205570713666826543090621925109214781917699655135996967306264259346138067887358188720093982\ 6043358530042139032399808787920060489285109190973455685325562419848437310846837900047809482548\ 8763131612475903490966943666609246202265141770871729286113255061606039368353562058561290686172\ 2263236073818781989464955895283987399157393267536152289411484791197168981429046472600448802035\ 6392018219162846772346066288813083051205059646008179974952669737528549816476631619338149875565\ 9628381100979968507174242522650335543635710262439797284070788347261420304577405480120823297557\ 7240052764744389650783970353000652693580984874996030118183524935915129582363170173336392850384\ 3048711201531070498600097724540200505129621471148624693869468444082457467019508616954339844414\ 7646352850215929829525225501890845633406464638441310725967169319703352801923604204580170235291\ 1480661556828594333293344538130163216488715384022744287608497710844870895843465712424981304193\ 1571326123570318055451089167111068444873365365607727651773581140078674073070410486408083639304\ 4084802048668541208355192534877597681655014950085428195739556440512824441635737496928262704181\ 7164125508045206304527205187834975632916664071768411492779834102771933057504237544931922419386\ 6226396537134368589957869536605523408137110928137360826515110269085408368742654998706725567129\ 8752458892265188140988448305949649296914082849649362008295468587523726760868987088208830756527\ 3208299697630215966281539845867353711815911654046929997794995043184696336239764771510034979219\ 0403744015654180380552772186272498442174056278160763798806297033851504874169797090312602688359\ 4281612075089675542049866642174747063168833238553912619032699905528032865824194298733425682106\ 7162031417117685685818924182683082009833192836887406413280342304546381941126565247238061680421\ 2966255779073233324206035919886795665504574716781916827294478629603368664313415870193688409436\ 4543241192378358700360044828316721939380061090436466928993702520353971689090454783121644825612\ 6480747837626967821336740610692445545248446874254480502177717113286242242173903148331486635253\ 7321472162767147819300781411646029661512386400186082625914129886837621960989312062272338259059\ 6699397946504606520600390110847359683391117376510649593584770744907555396036484876857142584117\ 1929146845381168551152714540514383342588441755474526551773875419596711967041690262118793999822\ 0053275275473495021893445798161494940223630587305048064624806997715826796850247199448396427612\ 5758372912457826367493203616427342339017023029211863693121757287852271161978605685466195440185\ 9709546214979163480285728083909921850661086385326978303678990536568739814452892933934383298827\ 7462320113656505872875290136338048331390545108282535710008632740258231519893920265143706863036\ 0915681793177816973875133907874421097187623276138764068308098857204318499486624186288666713672\ 8657607658105060100767396025376129427212975931291103396742388072305928957100440899386094993401\ 0172118922893154159019505447577836645672207197974238694676430590461254457639549342433383936300\ 5230140673200676190006502791289140842501130941665985194064472133920313457213184683675985215707\ 8178332879091633297251218102267028272762458996736372155645426287856491581128798085690753185722\ 8819461022513312439276636990663968566760874892779742024704824186224652653227798139167350359978\ 3776835510767792223971285652312492529727185456010476919715436640656437306249577101705598104526\ 2367391011050539186589639643420902460761660191455197568534660681491251591127466022671664364285\ 0031277290863352310382713262687074503368331707619803939655303016697423201502526036458266546523\ 9443712839635845656289965574595193539941630579506030294614036423467137191391080276839171591800\ 3365334221269362898182486307479363759103014955796042838475893418342932928172488169538495650874\ 8451119515055010068882444735748527936102469422039491452920517291863098367813290878109743387610\ 2239769190302034512421279414149210463775868856488307713851338225589845956106061936360812090834\ 9302463582326237851398655479428616296074036909855576087423935789142921001679779595314712802636\ 4457837966932523210423355427529078344155810587571132797384915114216494828657711469385579516375\ 0681064194630025907314443260026343019508226393624245809862964796939796412092055390694185299836\ 1246683073775379013178929417746622858394032354728755235103858179478049838234465793985681098790\ 8565420314472284332736446263653274383754447714704673905623324911155361608879212773323988235443\ 4357492050813813221928134154304958681702582864091639791128384434835442708687656458679024540259\ 5397201315540287077953003238285553890509437401398084159646236844442683398895525772173307732267\ 7546340248648359723806353534298096557931158599451965538010739857005928641680696482697199087370\ 3392631552319583128325156740649267539927680045866892852269207117912303629044714693562966356476\ 4444794093574313735789425709269709611390135695525910246809642695912077476462619977490745184519\ 4416717289648069683880879154694285664048419196992810742955147189784626978712406657249402349285\ 9475439190042297808026801560848584247213779537903318308694817453571852125231814337202133244306\ 8239863438264682225431172744159668817737214245832240062535183495532495799044552216522865678439\ 9805064646645058867553959834606926934245056123625863009358306989384258799288859767356512268912\ 5412466876731110657958018469879369679258967027302159976040345977871422633053149936708496927953\ 1650504220733750958822679293854095921783264546990627980792677179789521536594914725660743349053\ 1640405060275029589094983718681387588690043411061153188136471505323426656203879616840653388825\ 2174767279860302575159124292245450592580528306546281468255340072889377297335418361307928738312\ 5116416688468545249725275889782137641190487654297850286178363891281692235672088061594868771220\ 8783578482648127967793170837736491013115071384617274241015741465940340977001433264627989674937\ 5783835195478382771436899023785197280564413610127153561045341239578312355530996173562936213120\ 5270710612837665819689854291845585275818036895253543250532730913206102122686557742505952773315\ 3758186144193051328927625257013458646865549881847686927225085454236176587115220587668223756628\ 0997330559478113574001138536619456443868693227524991735966016234344807897752974036553882397383\ 7242846607342205718441040816407439059109180093467576067492950329711954444308180038695059034606\ 4241076556453150665278258617668193671864771990706841760131615368065035596150678182606829380070\ 3536085874701492153986749848012120151395128219770950032831769486242503599257238290334736899214\ 7508057321781629281767179793996148349953541244983405503794096526599217876423775232013745303133\ 6834932329130998014319558240969748963383422282723519809263136535716974326323457359790512798850\ 2027014471843934755794005222460611639489305869816598730220686660770140540527684643111820197150\ 6661543902510729913638864312914680785199561993409247806578728874173298205657899543618184224669\ 6845069411251449865858861433211754936364709301581341267296266166929902299342092815110141973411\ 2705387997552268316819447638454293761747842336232139604741161509418947341494403592300552011325\ 4930896816223680338825492128815879289446754737459608466660502628204137423563167259984206729783\ 4278231521216909549389258841110497099148285832188379221578547035526115735037440156455647167029\ 0944288544515132654227824880871284285526520167093334672255927227305874359698758839510067588741\ 7849161031973375016250415996676942453079464505311891447048646067021055945240959788114244289074\ 0662737541317122611232825129521204876250081705138443475405320140815166510573858831270600123828\ 5782096648144460632478100894857950584736745074204257845468731938147041441879604544240533917494\ 6482044105726490436478444724138026053243627329475358689349604576281747622697797664240599749457\ 4985479806896434598737138343418694456867738778707544600239115202222442232266714266605716027041\ 4312919034622906691537630634463629226812312028657528881293738304482936674197162208806766782393\ 3182096434273728676440737420884304641574951689906235400947064067961038427211468189175675853457\ 0927292681757591366333460810367251660789380039656239093625118417229499369610253316834959559554\ 2001580177160086140035249529488397954102898296163203111175962316492349617439617586185490274781\ 8993697442044226706594992191817944740956192360688443368064949958341417598556729981461994234703\ 9653705357126480014628313789586065831676349105600712388622824372251709825766225226618821292870\ 3677811366015686963312763643841371352013360619145730252353792352888607389418466348377497836065\ 1769317896986107659567030646684281495862108520947899471804817962434718117526976161535314851306\ 4012837322202371049452114413896491451367903347716207539398952325305298106302455553904235810518\ 4822485068798985116756456430886691611084909619759325703317853065653799352976888990519537944735\ 4556612023484118485973558631842732851176240586497317122380807963363266890442806268112582849909\ 3929495567240165140701873913259388976375700199824054161342914572634326836452715591897738606850\ 6749388018653815105878394235515641830468009726314310110950211166019860530559982491886399271080\ 4495791440234151892621553283821667996176846485773863033002983761280301527355461230627575374485\ 6892208789884383255313938805259395789781029921776329908694334472645569346905957473595435817217\ 4619200881532883821967323087365427270832263828801286164414777331659341610665015367082250245118\ 0936510575065555539970740986174765419687186330966468584556854576928771808378014400047319926618\ 2869022769331908848256827314648422592940193422921951909804490114354095979889458514199961589443\ 4819986201011353013474346367479374543783966937494613931937022352382817726588584138067979395942\ 8664176720952446824239111342540614686402919290218965485584285508519934857848315230335870733913\ 7796825564172800258077351722195127953116169705206474102369765119286459345685472113085328632150\ 2308083794332816277142497809043153789807863300403579322548846906616478125388804400614021648240\ 5339060296512346284676346614351462319189866500657147209281869347850040739281523346281940912819\ 3183266837209543514409451353244384507936627026641657418756299334200038480099317571897963391873\ 7349763873180835449188580663425799777067440386818771570801627408368413395120931720927269070355\ 1265973593942989829608775473316314473657487627518618495450040625735895654586927890051090388908\ 3442606801181978922573302779716750219808136434360794084161742733179960425992112202170608994998\ 5499945218370637930815885922857434957907344801691488376578506302318493820367601219909007189467\ 6482287552923533756196184834247771452327159140976750455138161205641281273035122293439098342719\ 8401381687843208743528332925003640135841178932405637729113106590108181839108742745299167581297\ 0228790694748243088371942016862668678624947313278717694729372975248062669745482314530230618350\ 1998726649243861071618166260537382156826130817978097464081654255659465832781859903645690259238\ 0589697001852487384972877584894654264682711978755091002238027487234529809369300148684623692097\ 4616355148882835871742022020650763065858876494664744476458552893397232994137640883494332987794\ 2458063467092618338986615853252854503259210385942069079635158173147222193736043898324264945828\ 0022903642415618604858696605011498048751938406084757972897258021736327249385988536572723564203\ 8812618216994282263733168134390207563161436966177022240178426674531931191264659929894537358116\ 8992744591687726520293587072774514289612081383230370214601965095009785270043744485027842369615\ 5139919214099487178629435495038064453210659316747759528378101803248512784403180255171038560655\ 8589147670973642033557649065406185686024318200967729390839887206857705313210578580221239223555\ 7830642099520914961879125604715461514004003760946015401349321370564338366626085439181300063911\ 7624174193097038058513244817734894773398580497757998867046051153375370947146940615225166890721\ 3848128937708813446032643618004647111621491505585754249275063019717420645670394597351248760686\ 4535230428150231401476264146304976902799459164909241706234381814543793786242643542236330716390\ 6355554137647124844851084376716594552972505102420684882639643312339764661117407532656832944270\ 1927235935899885068193562990482503770411295023080067535296282158107338042826611940755629750380\ 8738984607700355321876051378734247205077644158672207222451947331807174544397714176627383298171\ 2439826962846029245202353249772767349894364535729955298557023487280934279170743732549211286112\ 2184944072342029379943358633842792492916333307256276645231478943843629164584012503884649648210\ 5774969954394648343122607865851091856650328903836724788904019289444556380449296134923094156496\ 6347744253159463282790924334944780061796618530568048857291150287504162846201138053264082419058\ 6802583847719888625695551338514475374727553530298460222055336152332041440214898187551530260870\ 4315254565846948101651228055668161405213523839486213739894943996491862859403515136678456899223\ 3084234988499142278373657348845093212482825747358228417174487041913398899730790357574177972767\ 3881298760839547545444721560451439556049471220069056178003175691472216350833159455749463056297\ 6675160935031799668103798639903907097973955902884660374373362832568140570670601646495115667151\ 6832263475351084506893859883448948545432205105390502690536025500844080185333631680830679461944\ 4618503977014552864292743959473404399531148799989365661488289807142539489917579174736696153846\ 9181943648332923945080968853612591296322063812709019439229344097884978536835863430410586003593\ 2379990481814206980619269766470108951221074797453906295295021084829532969691951010112801074684\ 9583057790193216869303139588502956464233819716721092147789971088343390016010725482577635773552\ 1188909441142246684925327691704831065473477230585549295406701878367637700521961828729396631170\ 6460688526532546331103054430202822038693566986284689429228899905882559168841102275133199543687\ 2053605174378462608885906322023263010290507679749258792870766512037671907041225856962592013570\ 8952035453777290223574353149643961855268282081333601372912107660697915140422030274919735756299\ 7650895211498921340067083505841049480410014209430442073787786172008591579923085401927726035420\ 0053792649232145506169661930630665311009667451337214669820146029802088702100815257223173848983\ 3238355901699526629595757204515168081520879539599859086023297592954356347363227504041651442607\ 0603413507307859708765895608866788930952217461237349392445455822366956370243503591435401233420\ 3277279612265463602177042536929857621507806518126998962997463200417119499813554459051440698928\ 8367713388501672580128236027371588207572181351426162099925338482165494112751767849593998067570\ 2963950636771749056116373224883423439845577974718863211798907699773824480952451859420226865101\ 6007405198524860289138263838432769562007077503720562180734782237478181185434350663118208000977\ 3289592956491322813615378432581210758872875330892267111899824978515658074028053314475245735186\ 1584622431304409672688513219619643608202214843501772750790063097082626406613519901518245177509\ 0869550012143884950867636870544583505176156232136540245437593715134032953478386935379901781387\ 3354968562320736493645944999826097994927635507802075133660350318950673463159917522820701109200\ 1127524913329367614301749975562320375732700991078232324977109299547504958035037438434776778247\ 3210508708514302397442469745135106901357128158980520433394324457919737128733442742501449504663\ 8285420181840296415414070270038785308057994799258440414300040587871201548239069392857897308829\ 2984846526884370365707774625104797899165505471835581925169193783256557139623159878785218983284\ 1085277912230331943436792865323625998890273409562863288898918187261158929237647802856002109809\ 8820819269614789710302381237943283669356143860440041822539878384862965942336639009999722281593\ 3734872589916731401778115562801908222260612893624292986681702693916110261119335280431592321857\ 0290712387987123315116125687522790197169511675662822942124844257610803781259853683727900418075\ 8595828808571212782834868733985729059852780551716799763105839272078253598253328908181659866328\ 7725674488294940477016190035842635347682350585881540296907521204275320134225823414579248271684\ 1899421295168422504610291444775075513203843696486344885869823447095041851371417310474239666257\ 6748659656865290774631608631634176771941585012867213786355628082818504969154442425017628356275\ 4297180233732479530930495584418398434310557590112226280854946759040553804786547525832783663338\ 8696953200899283513317637303036894771826681578285140771600331637927868428670849172564584801149\ 7447544513082387815063477384950385771769110722583399648308173039047462851617341742358785775612\ 4264561398922239552710512500743234608248005219492234838112142251553382222093534744742209879268\ 0486218578584141544089714008274636491169074940769658929452014350715291885357354007797485741311\ 7694661896923660395079535345627781999700883048981615694799025869385561878529014918998154167824\ 4252659670737678065853150675227839756126023663757206748185672375503445969490373653435941801959\ 9114799790725513162007161783117741683257336807796128804537998244670555168768185706234299466333\ 0436178972736426560899906365129027556925578791895808382103976205681462202233540371422889124701\ 8673473170645047577083470030327342320166552358244738399605920252973319133373321627861647342788\ 1828164146731869352101048384564378313020008537043659926093638230223137169001649143101938773626\ 0297030360106054371380245771138730192818598792887452383445972408621597777138746044553370696749\ 5090008075907423069466677126890205711837083466568265648316978162202307770747988938427645380339\ 9274073120374254043081888683267263473960457409094507542932548175149187137614682101808808186056\ 6664313292272161699824886541920324535458102020799389815520361065591952556905900559156570514250\ 0824732207832037488191144664385696635280022900504873690900823654520404940213520767935166272470\ 3435306127144428684759236827444883313821358318893604263495846103936764054262067265927179874799\ 9935211143600546458146129177554060240085750978975628565402446109116545443431134117398046050933\ 1110886787440942374540629275191275876012285485053657051460744604658745899786690232076412054730\ 3326857852609758517900424132864830340222701955568493568774814677137518446876115772848882870554\ 7355299840713302940726815270357990093125609320632807187415301258516094906310203138505384633880\ 9448850687962492207878572114633544972868450962302863327417767730485138216037748414941480572912\ 8773412348726694161396493720085126991184268449278098832195453692703647395396608321679373925184\ 7771783224658707055380784647264575659013215243453128537676357148369752755596911872277311523065\ 0001534457425673034498376982960044065530908294538911993251883187833908128826775989749717488096\ 5069107171132494218377874748406488313408596384899438396031703236448792341399532724587582416357\ 7848967188355668550217810158603858799229991274759504522448770321766278958207156687167075148450\ 3465170948442162842394927938244974200933441489917369856100830873219184010837985019527294175006\ 9816213896558314006179264599828055745810023335062592230594843253705765931618938389642079355967\ 7635810411758034691734206170756661658052123263095993854293741329723547950509925112565517258742\ 3963962601240380030774621966973689924926088994283671522490934286287825060120270056278405007570\ 8397720873627695253506402965650427602232604112766742909347432864543550836127087418374090389763\ 5155234097233262948789686067889473751604639975005552001399467082344745203835531016676231066849\ 4178966810701985336321938077884273933800838072495292639763840958758382428806777117374099547094\ 4966844987497420942011011260569045461623381936335182286594024984590248910365393791651817599783\ 6682622992965392459998403025355682958612135697136175689719902350996212770408265310740914709430\ 4304379627348286882701300770751160771432142663603220982426018672743881162013196239466831918890\ 6523376186399083486775210080863796539506895391706673306171129549252407307927832410347089961499\ 8267843920617256336755622684163648140136772629638766170040378964782441133025583294795973419314\ 1714650237608592329552690817297219143742902936013832211982493766853783689220556280897065350180\ 0309233367408272711953489450359014892597980094595803500013313531819287600024644385190523369768\ 5300585939412027487288405531136372064232776560247582738047339550055934614411696429323697486407\ 7613354836939073988454532126976973580014522005596806970851083416068140432224344058511186947505\ 6333654087146398141490081804092248287272795776481261627693782545731455860527628570895358883969\ 8565242615180290318946930597372024410631716829187783882466192073384240814951338597503394124482\ 0132627829532738553030867976276458480155410794558673542874384313461282149267393225748250993585\ 5406800575477276593679744788760040322141275505892777190412168700759828478407793271141752078526\ 3272811043181747946118896217444183062668724165446579745796467023914133653984734322500046977714\ 9612511190087307491216348942612406319299290597945098840635844875606403551205848793461483763314\ 6345333794128258759767927772600361469797172657978433385767405445241773248089723642629587873719\ 7287858774950954539154452094532199892295112620342083044257842557383766893232928535327965754304\ 6262290379667800215441513695740941667040786787960240197212209085682148222841225560887878528612\ 6243470141333032965506802494267706059974771388529404628760747529857043783357586424268777770892\ 1399974790301383430256087128302327623551368606280325371645739801811025795635454977813722525075\ 9866454595410568755070264058298737562676308511497196737098914048474192684286142508802528944071\ 8838998854905532557310271613462432441616535256333183414929490830951504541522346342883672118459\ 6432414444227465457660796043734417420300474581590395312480645884905604245144194189591350825682\ 2550537899556395066392011692512581967624866401914232791387172528094060272330495685502201618130\ 4324768058859464333505856293735434817145404533140890362313331331112481849800281764922887365758\ 7006996299230292108845250818556597279223827822452465842395107551022735372914476414151560056203\ 5382279270604415872236381320573598483983135358233400478770455862819646197713922579154410370176\ 8954560797331731706335806582298356494060409153896368964057662732175792072839680569527464703523\ 5800985675577709014226786250414158981311041670127978242491518911534033724691693331794917500434\ 6439510145357177900436922944694508438728474507758662285495545303747513821846438650007849600725\ 3014224504052554129396597503694725981420707741380254520912024424520194011214704701755425140994\ 5425468393049763158595186350762386235003032362296276097286213432941086824614439945453371730425\ 4667316359197649458293130435243783345101311852913573587080180155959200400793659299670350338024\ 7449190171757029017454850933713102234584873778311731072595931063333314807957944187554610453573\ 2500322269380255012584927946029902158310722053493579906253893002032892444441957327168615704286\ 0361706539014018738307089174339581219337238577257568969101337048535094433369299360711493976840\ 8917578727986359309410265319752017404966965782415129541080927158369519119857644587532589059199\ 5941746873303199682992577095086550179275428456188931506265862930915819773765698906196330980277\ 8215152791289826886715453155568474283707736570231342598435320952155568263714259223241415761717\ 4805540776476790095922220167155671682684021074084091916925817033528706918060630049582042742341\ 6035397299982541824623986825312731012335368268897074323767137624299252802093096972111604054637\ 9836999596769672165132011035721480166353157920788690637909291685679399654012108067306923375419\ 2514212799402375557514795599816590623698049504967766252500532378419048872125832632974967162539\ 1971787539212837903878341463835147040523951078175640485780191923720381749589601768043145689275\ 1019224216754522676965014760000392053844484025392508677129267406835664731730735493195698285258\ 2193652660349684643220636782184354874494384447988292905092863893674222733632807901379147703397\ 7092582737285965881273968031660902986529159876511925650698982151083485995324938138393509984556\ 7727663408035818783698692978341732861131790255572160283426264153194964544031281026236929766046\ 7327994413265339663520722631912720971521412513771178658149142668073931850113042631308257123766\ 5571326953024404671150065168275062294366654064474814682893382362737416344831334282660627704520\ 6637338765421463050634446742152959650730018785216998279998122792176288689452857874429341706174\ 9624311750500095195618437683226858578056656426428678104781262276197683971494203941671460414960\ 4386430986294218264713326367988566216275848217920620618928489537264881049971795438586682780142\ 8951472557084684248577530185231681294495362162116636697300949174778779486228636738473189587363\ 9057752305674820396262222481461615615381394350441679071220871876118521935434776332522695889827\ 6923948526050938988097881193964678626998776111526824326020464725773642058830244009152030957426\ 8565397725706894290921217222562226912075473200756989472719162752619424834513240285504494154515\ 7361798591362753898672050744453055950366799236171422393206883142426877199421328334005839002465\ 4540548610726111418326496886180986517177174414546957455115862884605845846561928351181633221472\ 1017288121223473065502758417748381599665964381474021999133613730573238922389328248285224367877\ 3728287882436748234974136645366629436219923741552705630199045502682571446888615132174172560115\ 5629656263370521596138534074776760073645439145852217232910987012017174737934427786542987959536\ 2998020206017851218518902378794106445966196306104545963946465278516728113118634485523106297108\ 7458712945507904745123279855348424934945570313613434777704077155750040244207208186530285780801\ 7401387331356859849168737275378111404251112831031051490548080002540217520341057711845877937023\ 4329293393703034080478403362372851842718229636085489159872542566992878733732254288989757171234\ 3933213969649439669651410572272155483170428099330186452320779936447659190224259724568155913117\ 2238324130552440925803367426409350482027678527487537439915938199524725774338803589231087895202\ 5197448480941476049689882972882608136813670594667069957721931405511025976383413857847803684545\ 7757006406113122152925541969612467875631266625195847615116012728621390340290690922028862343549\ 0774413541090121222302756619685280381476529044513341231511837383202844442145521823996447333322\ 2717340506680630287304520693776704610519029037684277675066747023523919480101410286784504406932\ 2094847977137112908517247167990079235861634812648246636873469192561096645046898511208738440188\ 5022162353961486456287375966370654572711680249014734197357953821208669721320675413716878570151\ 0416311998037733643949276381549828231696400237419480090431811236301866464247582207336688931578\ 7390443080588498737002890690849150916131588975337666677125472180196104189848821730266505730713\ 2812291673530747779512460602023709789018350663979886198909519598888287925501203019591588708370\ 7038297131294613627069106254861360044104858941369358134042553806165429287345669310313973958967\ 2614011238972300933757917524313259543229403433363712339691482926760335004908157911071136150965\ 2813242428604545128345544919510797247389553351334329077190976290464374728552601557824361787477\ 5624337361917431750603351055192378242752766260301550882925657972637077611441336947339639679768\ 7838989015657914561572100509976500076774581316933075764147603985920088990306752245289613187078\ 4770541932496556812895348284383279615641072119348874841614889358987305812004523751711746901574\ 5971067234624913698215448342706509796959933839389921656924742026450695631842853985660341190904\ 2430763745274601666570217268399470483495270884776765578863659977965901841519566269960334342185\ 9964454841174960668551445346658442100799565267775551706968317624971362841413975500697004393714\ 0299205642744777890857376493226184426730128009612322730486503158543546831717473566038423452498\ 4701070256371558514038958570742242712388567736633119635041223453967913706240998259485101729971\ 5956750080209671387124059287426856437372581938884962187053425416379007434281381748119046980227\ 4689036634689559272334851247380493848057147836340637802928920432814237745629476804949992147497\ 5006071940701522532646453343139956704144866093686882326476230265292761939988770623477209719045\ 7609750822223371473245750648864391801100916716393761104111233903186926231264043656430198307260\ 9247377680938538860030857577557524779451074654550253600758708464870782745587387980325743453177\ 9394334645572484230441818505021451413925969201468439712974363718460096764129326986540430134953\ 4048323002759942792501173988356987632971604294798126420811392664184511152223991859652146521094\ 8866484100018027518378140825902282563908638116163923517061670288304512456771912392242493011227\ 5753670078285552973753371852886545733945509090408203020919887184118750837215638359041121686981\ 6922411885363417883074313305681709038502052054714021813394159371569612877967951615393230501822\ 1487192690559344785654619044241011605447953972631104508785255093885582492797439764575743252265\ 0685058236219291445296987441965471943577896868064258265331685335211458220186401512509641018325\ 6297397208638721060717925320821516867164517008528790847343997405837892455292198711442590240205\ 4750828349111355929980790371416115356359213925836215767427569732092503828782389082263287400894\ 8202106753385799801601345421372029029912944209799953723518165366244689251272088864980691551043\ 1282537608559584169091934031945225459730181443388245949643167732371734972691776490088942027480\ 4761110793765713650034742443965130472996423807214266476741863844519608875956418936391435818989\ 6667785654468053372105690715781711583223071403447626683873107812292872522078799830595746938142\ 2410074390662166191293554067590858719599065903424310077444082204030280751571503470972870647738\ 9508905420202020685932243842739238993611416218473230699489226972793644092929995086328227243639\ 4177926324182602747549933919107794904709090397548645491885561819574397020346736844141368741060\ 3620599429676221718154339159557916667816963696925184715834285743610450163429708692665240433142\ 4091241188234206889121852453395544650166254260467116507445796146719311359947391670882621640011\ 3872625168159191300462593386657835602658640654987927281696322844373247198006639718475859845306\ 8974716332062160353461131928991112527126545041248307146358070975012644478883350029185623059030\ 3037938854403818440504425262624166185104889395108291723248660606825688524475362640389377422634\ 0536542661648078612707009667917452976322224343355307515119661747582500056950642540917445793848\ 6198220768016693046008513158001083887401745828460074188755847303228234931925270730845734267720\ 1634677951442131178900190898840305399181148203546149895075534695112424952943575029181870071414\ 7757482545587149559030827819669042374843798356626682685507169587366750545103959568921960285446\ 8234361641446983033585011003129003862826570027001344589597831924208031916267200782361306448577\ 0671093290716350855489594986407478807995690380899821250060351486795950439305349714231846247785\ 4680686304059206934823947410544376530737955474064817198229697480090687927627935879296711704851\ 0714401487387149039237565545857899069128688452014969866220310415574082134784190002261841485117\ 1570458036118069126652412170804991982706448010367011631234721391125962506029175198170540380635\ 5617429997311371897155803830142690471404025827644379615980927867039759291471666540940751931046\ 1068601004643262413251685112801778470264566934692125984768227169208067281533221887490099815723\ 3349900345921046952701993500387010341783025599267355759873774968538865808756174814194279642435\ 2848127761435920259970032995023586557030036967114335721304720006901161855383858403070036143520\ 6778457561755006738144920405490447321976464642126058908860507413380924560149776947513731742399\ 0583100825124756827316222486481284814846419950230232793280169715000044259857420114181927967793\ 3784212648906433381897710037288223667381392995843697127103175381753959960341379833561510390881\ 6516608313634826406769936161579304642907906393235991920570734162195879314313057045318414882073\ 4598203831472377365250038258254125470390815967865892513872203404341834535910584901765203710725\ 5767903922626742254107940543071050571926958721665826685836228028847391844713176067495925005072\ 0865493520762831575092438164662834778637822119964605451465400258784506305822931668928942857006\ 6056622814610264819134880089613443144841465586371666254477525013805625517618171035099504650488\ 0798858393135247083932106901491861488054462462711206742497584272960431873333370400837343335654\ 6298906230093713677056931643378360744692005457879670465754151372398448302446899167771501482922\ 5947424804693455356906256910727779709371467731089934434675310256823667296958089715417582677084\ 3802443111967580290619677749436310590986425520154012115610672184078318368543994464234971556011\ 2776805905994971867599070917245827940477031128173835852349952623896719736371500068348015628551\ 2816367531003873655657911293286546227290159935106756036466429974982626624386541363143289096663\ 2473041078561018967504910946692355540373851182175729820748965783530057132646605462573574343365\ 7820476333571611995250490448366852095973774761725149392991633452288536153673180493184207041920\ 5684823639367870205257487968722226218386683121037797992852587119836797354714614434502989886987\ 8328587471879012607061664595037071373920629700654095382771638882332235623998070579840017394933\ 3302754144181168763451825534845155985629758273045249155952637151477698449469871713875702064494\ 3358220518036012956155659405342030147310500408605018148733301694308834896171845620343539545090\ 9510389645087669979600630116309091873349308515862484919298619377559251357952217845375289110907\ 3150621355894983007928039093722169814863013003985207616958109147812059585369008475567203846672\ 5765457591000019855019076571917031036481287889205052158563228620160815221788823857331943790821\ 1626849730852184229106677858250041111416325429221838299588662054284921802283719578862972242021\ 6465027038083729370909030676821586456491009293890292487917870311116081681242424389403984287281\ 5543754137561282260104363699172820968101928132010742220773980373020970513532981208949653088659\ 4281714255898676670802158176407090254865106896667899578268786684904079671903838694168824007568\ 3495139115015740768683807298854336485830294406104911019190425284415927205366403557843838738815\ 3093808533473947245169722487335156507550335987799888590877933802492591577055436689907835630832\ 8853720980493587370856245961265981861366815854043363134253851075884307794939285813675038381555\ 6563329309940916345681640131618240060351799256866386877093455570842534096775771418654412459095\ 8932127624640696184252265996593484576723629424663301655143237921741898349478451005715860873593\ 0083405349658338964310005930235586887755992757349853886062396349266188768240817984070970192300\ 6345761810342896273446485614210071596681922180330197409883920691128202963115131170094577032203\ 7670424969461013115817321684190795429095428031382343653809466305376294158852513017669893644365\ 7457582507943049593803698834015817148703954383156194716127643667709552029257791127600091162716\ 6974894377333206897117610902461675934221042427511855389547868775525417823132903472202696535094\ 1960034653557223902531593974456484096131606255227178183649130772354542594915743521185424513068\ 1117964440438415108799896008602528254763349363024226526717873829479183522468374729622930557679\ 0618448906240410602284010016449910621073298005190209433376158480996452577192561829052651790228\ 3344199545934159318068800565281337942518844701336667467095923437890837095516540883912348787292\ 5181806919244573119293395647606478023822480462883293343424378236775503411243532356801083716701\ 9163560349586434578324677014509040063533622226505618764688545157809334831263833293011051389886\ 6173555941058995880115689544055620984976414284177349402570738748456936449864885839099839344016\ 0431362917356307321146769168923963721969875604902195846466743642032634045549468417014378918775\ 0409676143289096550800592827100657179402450104926459004146375270240398052086350525685256499338\ 2084445153122677574924012071323927844361475132651777698947881139676113753332471879790801120673\ 7725170958675426386363113344862879250504758898055624282160431396083573243854240948798378906981\ 7245763482711214507956196598696954185195012130728809691280679603324910465338807982505262866665\ 9348532085733064987070256464969133669759225831903013056604259662775454374659757844005790726522\ 5362785094628214339863770468331137151656789276627297099304724482986449054560801059731502384948\ 3225142117551415046295059975761679237463587236563525206794741008179752716322110312942323908934\ 3241289616348987955727371830932992618490193217925774685170056713091129301302686920086810049063\ 1009475536123873724930197814417533128160921227335292046957021861595185381042376357148761043448\ 2534882097632989591558347056994931925124992820015452743206556326803835776443011730361297839430\ 1598402708269106720293037774840480352579690727360688323660865751452529512886068649860590077724\ 7871601032308264743999387334443069768121711835050101691811502501685690812269342130342901817402\ 9145413509472523011878421163019399774255066946828341379880888600108932409667860463306760447758\ 4376898718116016238859053093413527727127431088068990389181602566280323664837647118910904198533\ 9226647422302378334161861687512335215292323378453104875931640118351087985392275595255861373795\ 3042941157669250869739238242970747198468802022574792590942171850235055670192543611658434214259\ 5857840595174032044074987595735032418348455460992550670265909979987931701529941217266865624589\ 9099979787391845272664217080407423983660223440572935103265974055638724167907868915178602238713\ 5228048426514897715552876808787576788505417999182101848109964434537685353904258481370767749686\ 0282116234625898714100238661409207524342524074420448176837520439456813829717936260743001081963\ 7011367475360867661776624232338476373524709042896254916454853779317158095003507128489381684067\ 8138041085065864258317577101303606163387117307065285481742523132719373925617916915275674955155\ 5618398245994809263498675339784819221923269698792436391830403943266581104357552060576264716638\ 9657295670974311091096977427669992742366706581742498032326294772515891127635533380327280126014\ 1505257235695224387521573376086082190533984264023573439151895636543327853736965616828229310611\ 9415963944703859988138816607928554400937115710924317815842137353744906940491059395996672751639\ 7305370292967375049951383264389984805877039930573710522816520727162905947214519233069178693654\ 8779744973829930916920169809762341025775722452415873135051830976500249368823752503547808937376\ 0981543727656826202384077886044334045591239090942592945863325257141058410047622661559291698674\ 5838045384533367965490288093969295428854108339503775621812774443991501197635194252151227221496\ 7094276760446337697076704330675882657168614805149601599707050007354923099977262126507161919116\ 9296069380889552602450866314846574980253964136630466881499040257315846450278525362075042604533\ 2563556736235436229804666436806437708332773734801199481841125750683571760836746666347150467400\ 7690968303553649391838129239723417629841853931057096069276543160661176571630527424150826347416\ 6330813959035929160735818712827395523017274988686526624143407908399976259651315413021661986132\ 4080920836974545340294607826573077069955789419321874196753654160503478939478415631247270928990\ 1930955309875722026330266301240824215801037656593634356220191752654912913784004922784659335730\ 8098589695300001294972891192787278836220683746648874296524093784527274797913335975106746924612\ 5581014457347788921717809386508575770585262583796189204622460689424791015791931048154147942181\ 7254135931480379058503140567980702135651246039625829930932109059545732340204467009920936717137\ 0856580314205707836434269723516845442505512470984127525170453242509584788305483992624510638385\ 2324671550816104972698819690026993607151493182521925570033372578429051161652093245241043352349\ 4438924640337057537996423994238947595466233888082361402606252725114425579493347366417695765709\ 3679388792001520631135921866097131245953833735747297699658415694766133204557803745245689620007\ 7549234572053971847381859396940968147019766310672266414136812008344805626016585382812172227048\ 2727323567701950931599250941725255656055807160121924367389596883846457994640369504511762039129\ 2809960809016867360865114253806047439369090769700711704587601174966676439465754672144636776021\ 4471445650642387062145422350035524441678650324405992036938519939660530439728104994205046016225\ 5755994263962679363422424931371791779673150632389160973309382035946882782943460452514579686099\ 8269457377583509793196174546759424134243666986067530864303830999374005657444331150428572703182\ 8931398638810116062717825960591914067678378941851811009247566382996988386437167167376692396970\ 7208067156293573051241566397457924799236022826351670176223097711214159187597163361424795814096\ 2233098239393794616655832437032190939574196509969124280981864721713843195438460763897625500086\ 7188792931522963837818536536679255454678584798360056513986569596981715405634039830286886064441\ 2363218083925109881792134204172952775532127633896765514921142724783507490481984804609479141610\ 2032881784663864288370781697135994450704243258145716282873283108817016579311704497581758987255\ 3251333599056580615333247531278426072902834741855811219906587266666793760551068347260791626117\ 5946285772604610943023148346355809930038172071165374137674720447554611271066926462540825663647\ 8574165142040406336347846348813594714049553996344341931180442960333882708699821732988206364925\ 3990300642440446820937022120896338991265572590943694227964203940911559704285264007629092074280\ 7157888359399806968491767630362997939636134593247535062347397267056783213374781990103221957125\ 5530787666384103423037478090681665281310173014284286359358321553179286138773827418634828545298\ 5596803388937246359095872832641067246322801844674533601615342395404310700529470149070809679162\ 9786749539138610096271589847653874533597001422946270183808929738339023355053732901469494945089\ 8857699017740185200220038435595393193935100569032424050844368957622525368552450268716152030907\ 3215891271497283167900058176219482102018928799989629289931275672615683771400542199451851802982\ 5723604709777266576069885364811927710140780488671013857041000734381565210188817937797910037953\ 4774751149951316903161099300871147837017120352238420720945631701428988788982274069127592171326\ 2560634507851939273454505713536831214736583007213478384615458423242559915837887953080447572440\ 2003820664861944309581076262975785376325349705554156168412364016599114908819500269263049086302\ 6104531940812650996172110755110747536346601314422542259717653781175971015674406069648932679128\ 2847217239377425662203172107299109185215035454419579274907877667271345690977579343856991008468\ 4306487911159019533210281129958955117185440127471830601116372797192624490764356231509833404768\ 2440733251348602225929141405650139780317868576490487218678055551575506034503484561661768330351\ 3283110859782751412905187692348635003147589186512764933338574252110055911480476073294142230998\ 5737662981982066447991844513154491838468641275696567880433790119384945034040506341773272106306\ 0928131001083451881122565071145036232852534424610082648342235293876332691611540517785851371843\ 0225802833442775816696498866726597777636388973872257893711197716645230873514001209623644117137\ 8946703745132464013215530799501996538077319100736777544891900702837644323876898475556674630586\ 4696725426453049670753888625110609882098049976445306416672004984374920087964465001629993363700\ 9363079883432617571042283490991828703109530809336254472391307368913405935910020604439328438223\ 6101372778179022225595177909300482692565032565666073691032879080699978638993065182898443350547\ 5038051214193670269457014046368428873639060667475332737705349733562378098773549233362768874842\ 9980436541314398980034002433936630292346211527096649167706366979609202215341978950492359604208\ 1648402906565229089832397677446369589088999741532556523016296041218844885601725643811814303312\ 4728873367766008546788696898845741397102669431335247642273754392590476646321511145846494888624\ 5502259234121090597006825759777272057426560717122377267164696100856224526638731373911565877712\ 2429824618065981188184530571353840323438197476336326892060985019739871277218605229027607645792\ 7670308890968507709250525403658625639675603891844117003667962635096505203683566514879020495295\ 4259946322788000091787595982005278025298131684619996519521725417033972644162467083969373929963\ 3964443157182823390234585988573472319676126085155678379780380189303946880665516645802824268325\ 1640312508806313890472602709317651933001145733583994473300488607262495654030575600659828628262\ 0963405656802028280893116937329085936454267510329741731497812891217134871895702216483806698583\ 8714523993897297503094199459848708988709649923083734494608208009789866316890300310686465784556\ 6819204082604881286919638497985917531002945432599589345936021441791107419234031831661741360455\ 3402030928873679357611395310899906897473824007183417789449410112072595396884649406004095233022\ 7373062857490159929879223258475938116834793435550705740835043701634744849852896503945093882094\ 0454842784325631355551667435721515378903803328488574435953589076395467646268227107193901447882\ 5974371487949123459552288141469306863971806263090102408708999379142774872076380439579042718917\ 6998467053415856056046726165177653008143662718121609267712512579070929425389879690678136189701\ 2088754594866015103406438645472321929457717351653224164537956616035720509806771114983889981099\ 1618644650932906936113125161361817279425809570083204540700553892201570573193216508089932662008\ 7750805901326032223857482215331586281279969363486103921019698124640548030462703615753371207144\ 8765966148203821167932779622045169072560085314776811402919688769090648434688240819264474420363\ 5470235429529215219226771766150436933781307695129629796940131267117741506713917535018009373888\ 5789665697177539677326371217241764158241882332149508270185151027556637763406697573245130852537\ 9121687750711299698521502252173543837153898263050259346736526540101301047633366541558423912108\ 8589590828970922055021196110971479055197234994895051253881877859485761224218250856606287910261\ 9790262339618698903949643507723012084724079939419174872398702530449386144629218348329795354281\ 9656429288421914145367595809701008356340180310735823440957080243187227251422429877854555989981\ 5836057982208066636454799161066732110226524388530067019114544286087851011723038788182721584109\ 1961389845299175535435685676688052534974576969180263003015561954581006787486399943733884427816\ 3072865804701136085543280836043919272435510816871828094666884176870622238766053219238996631638\ 9223599001669523615633881536027547509852142455816011100656469034609514222796045392045683134371\ 5626762676489832678361675520085284044469990575772337832337947271019151136766705989353769048310\ 3533329879625706131489496393868736621567878564864897819368799556658362165840328812375629898548\ 7433171545159879274027024196378878900856259814880525971573569375814824457061796193548680879153\ 0745961628150355520530615339530447469239304971517696834936849526459091689098510761171645235962\ 4173831344482388804870389739842822310099385068543923168846580300898322202465553148286852419509\ 6070258516073233738713240416012647829952210887089967281249898516371337008402791869245359698622\ 3069117256983404379745701206993842467415943896695255771243040796235089021346881859200635110694\ 8290851974539126674499508570940437688609767424981678919953170283743402321348688920554867758450\ 6315670558665463562638568831668125330646176304394375380306896257064790678540976064256229448580\ 6867138411878860064971365855411498771210596063628047986953576586958887149933760622013878703461\ 9599320400098191544355334392877829093161115594737312317806817551837773273017715000365859440619\ 8495214721828602063035357813890784803422899761833340002155671391089603536800633155206010870429\ 4842616477347796359198845066358366530419624696031785790016801153186882300223819446831171755908\ 0478295106530536607346888302994713285598671738163188770745459024096795143978957709675759790070\ 0570218463196634831224348600961466366377889264235163498382574590839952295488634563311088428989\ 1423501198763266199478346127581484278562482514712245615056070733012110427930664349625708469580\ 1109042659475144910524856999985021550046820231481383947699126596505754928781024048943850056222\ 1987872266895257575153435718017082966346657609712763847752334893726027426530135891134439081365\ 9827026768133919218192832742166403131938151221320413116462009384399767661452235697937668551761\ 4689186262301818003801167496956159565233478476577143223764041907883389232364110218319126456341\ 3626820550725988467855030008255122095509529017427065394037928642001564617108908925353896891649\ 1452641192189244907617359628263857932970146469339883737343179916465430310705169904233846217830\ 3936932344928438015406881463659777861591784356966421432790613488404824847810053605198058426340\ 3125677984790148482718913104300461727858813649538883308720369881095521754854378746044986250452\ 4724381782399367326934901526973213252397350028524027129635546702827594263115889228334788852741\ 1309099367610111291095512736537315100283718250640022873233814139294023150578727366216627942987\ 4026780723006338616128438378697640840377166966774258152719224496347699116179725221759985802412\ 5522321158614484011076523921317473813667953666737625677936586958505447120019177040196092308060\ 9589482126057068563914371177218144999605213227960283184524237925174564373130218662805597585615\ 1616215464356384106396022066203899114086111779966346618944376380148430598156481612477660574464\ 9490118994635340653404050837393812372199018381740550425892561173356579385783675498861384884665\ 2384673142069662564528003261512796098875944825107728639394093620241307713656593569198334560052\ 0362492207807957860859401791133008397534922113236510437068939063425345543754309886285715758323\ 4094675603512984727469893775662679323169820340721621872752985946023072430492348475114966003976\ 1511153376119086272229789559554515138481317999443629138261084001491786977277660957237696224592\ 5262929381433392774330505078688320428481931511017643261089022941972155336607887752730354738883\ 9409597880653749553749703089686834557300069499942668106625953700630240318744825123652887725538\ 5590445079125532591740668146708103072097761085371796605397605760938815005255848297658202170982\ 2072525121966491134964907491950527608155813872230173903187373582659325896696978262558701327254\ 6733770546756303498854537631001598541562565600062289203066570039509189092783486157995005412375\ 5298913789124454624420280682218451491294874957361712795686123730102140414275882229841864101861\ 4239440300169817161604633574250520010199189138927540876505205028527596772685663838677545171270\ 7338185214274787418888162075260525659137585828487794054537501483354282562641357549614879184923\ 5119094238178535717754413019648456652091632899457647793468620196604454166145245292687096448056\ 9686222827144076789855782475100033624752740448129908299779096918216978753064324885420946191274\ 1306161306034013686847387572653605120538221044491879166066700493764712340891467857535137680809\ 9812313114564530786809264139780543130069014356900349099730900068633747096375046683648241946856\ 7286858972284927466061724461530455444587533728586058885354613552720328147074626778148997795892\ 2433159704701202883720797652184666796242536777203337909379704420211030237928683339082024164871\ 8987044208138191108575862206813789893960343863383303100186477506501715092746533417876146491251\ 1847705592508940509272899105731150808314674386318675860226684569989106053002816683823103482591\ 2745844611067646401646730628311856888883237608194481872327612775062442245048313165132085464799\ 0221080547862660276707434125294212369761403551127195666686860691629024522662993335188719168063\ 8490583704151840639610053224500512738888191257786559041411423555604450945738877558110555650299\ 2143326934602290855487547509243378618888934268923578572408781849504928768154661319892352912478\ 4433664986351619465677060427530969192929642062505747495470723565190088231774675999290391724201\ 3335795428803761006796629891587788035236721049761206249737827560589799046544773383872490974340\ 3433310403348559420856116148247944279654604284983076314151109116444251637757382422679870971029\ 1969716035892848950190865155060075660667315737248350772736673189658454369069512985451017393889\ 2904550179365845315458407977373981249911734915776856069552251750077099657339027740651747571254\ 4830839881363774456081851675813655675554380632256365646271271956314633413326067710019803460509\ 4139473257052301001613923212745786115360298274444773308013583128495602745682523230556637613609\ 5202205405960199767324517759254688411391792645411106900120390147654119657040786168975814835088\ 1519859515536606408869785669983791580545201025004501944150065465296313612543022262301971271607\ 7247198641047648087525458516555522097325495153534386809515318449027207405315613345250636265617\ 3269396205934137229220310322671414113815157624360294218981688887634888304166039643887949941902\ 2601685788094063175203054349486745217842773075378724693635542413996898682027274578678363385269\ 3060042448630778690274909095369815134518058479132706543714400740979913976996553559716511343668\ 8318403748561516318781164440334827755407770420089940928408676688532552997548136363295918473382\ 8214712712599103262484566579266813014342842133129635632173793318988376883533121783385997696912\ 5824227304668350421374662903018935082575378576955770682879355635482528073048992006204137719274\ 8826388062871898424924778204466886995476280337955478570655197725851956041807287559856608114880\ 2550292725100757545618311928082509012656180036903137636979478197301774047682750548646791859474\ 8860849975770556360571594734765691903459426822537419137084203491259966750719744033247185804065\ 4159408143431018669238507448858218830575721847000334078352866928811676693706617630330336481790\ 1351670690578092196276919209008354955934113480587949351956482905969919436118749718260957262451\ 0949680016253621019688009916411122350616040847012162092097389897680663241722365262155934525600\ 7621341677375945265039713430156041785952472180184845081902327490172975046522517903830140504274\ 9662164068031782381327526836896322079337814998875755727148090142403106349887389737911357885358\ 0475372478832479293026374168806158886655718158856263963011301583271468284458310068740150704377\ 7460420537823376286386634482230841972843812395476590416574883658032100419201213751528479592014\ 0834366924681291723800821906204327966051462602376168887456014505006084598396516788367225548617\ 0300773106863086919685038081072560641413426272382993103784888823482820814464719106564976585161\ 6553348192725308078420311967766746496409234544899631273301066677964384672548918105450733508485\ 9100864377059236830617669942173557718711178698324251500115466839334297052554461750198044748752\ 0318947850002650169631993476636612131562313740400887815895046814909784984340911540687289694101\ 5558541425886113015571263026471425810696659929373512445017480802551828588962136921236999289857\ 9289963139406170288836939069970917512673017847257177541445185823496107342593171139441319306932\ 0793383201963610398886647709403107945431732715765700663801262766648688548773103738700328839692\ 2768599895296731271749454404305843299808156713268012093759589153044955507839436876615317377298\ 3403228843250910028130954719243415025908885697005283550810904583778310012502406557972406097702\ 0517402916810854189887100982673129875179697084794208560162258183930384241340412997472741196197\ 7612245681374377143829364134087728280603784018118654699011238647925845339300394631718780741393\ 9260138911676279968778414920706656172830687823041904256069921202721682643961963980713734946392\ 2364788031406675508364921697837189496353569065913605682111223878356024398943644040122881457122\ 4082050706721678485858224464308998493401948892522235772851621073166462347797135630061375995074\ 4654389131933615478322587172592470316406532159084568022571136916725725432548215187132253894618\ 2238778491806788483660366126073005666887541246958049805529239633814160810616315330153227560503\ 6428663837351554268528008298729136524490116162110347410336940566567200381093596083243593994456\ 8817323298042427950829458013343650392855112867988777291010581181081559674689958294077064465837\ 4160453668696620376300058460854136582004096627714729164531933977842700436758544892592334457791\ 3166508338197359435123112047957419446802134215762854662773876009922613535131997113201085215956\ 1077608218719620515701468346074555131700562815922427104687955285337194788150911292321713249421\ 7178904766855099872245871832194878793733388560594079162176261809575043095875731346977832046795\ 1316874680851039995105162260230861749307773637090926061525390817899691978446206955666787665470\ 9408014422483864495707612648133939039329191450475928672448663587481911706496956018931680420943\ 8985304331992236345435723413229437933366720023416885795033035019169116505597436247168498036054\ 2667885260533922169556229857104279376809036111361944406402129497951410412816477272529086642353\ 2493734572365848120737247002625280985870530588406515067951300340999850205745009344895241451171\ 3657105920124069885406913327229952707983469953899409518878453324278820284007882842587257955001\ 3666953324661414873669448635783522635926670695088720985312031269251283923305679918924162969043\ 3578332872026131317995278428729739276104461858981051949451360367406818437702076641829662874366\ 4145517635101859915099811196375984843055531533168907975480918570463165847116650408320267392501\ 5604735763725018928990787255469834674933570784053991634654572336207410579640037783830041699987\ 7504076332679789049021449664919666802023985326747403703720380232401086155370455369894291269622\ 9477838293688269719838917115872523099903412569729062238225833627048618675364596565732520627404\ 4333058445117187282309198961333637427550745858393401489901141677391168004570714170088048082364\ 3814097287665624248419857419787319169975588845427166924040102788926185207745451572236029786456\ 0056983374267437426729724616509793983208269175400127485926290525671661746020509874287117783299\ 9631095133346733280000579241961568559457013690344634378794616520115588649301299524690283339197\ 8071301575143795775521128579600924263800102238370517720416095574027064340691095384309431248627\ 4981509108220397882096966536293458203737278598478900071603862463473764693700249313624595825381\ 4530416631427375244468102557527902678634605685764726640382236749434623427948514828791295550865\ 7181101639542878386759594303590339445468823466127951095083664068815040585381804981007526880235\ 0765278021963446701615981521644361074781607295599800636251400271174675418739430693564734226897\ 0886169604335341021666593867964560656422388140901993479062769436094997369583375497041150200029\ 7991958486404908261334998004613058161625136331983287971194291978383713588576831903326903747812\ 0242437180045871833085233075003521519437128073169238696103979618887002786081901968195745548607\ 2881366300852018277714086509390915116893581401378237895734788179222530659743648309976541937477\ 7884597905237836840242552679271723523989705664711438645552801442509190165334159953146420285608\ 8132636685543388076060409814585873849320376074972476750301882369736269372372014997037754829115\ 3786732119663067214587858188140977146825793885944065218544911260214487731449440776998410135539\ 5836905612793418019699185484321981077493304938356933286781935208839997896005076701307495027520\ 1619172305144723741274572370355567844526598853058123657871373225612133756708367069567970703852\ 2149981921324628488072630674909465404641589760651954286572842119535673061341489408254267537882\ 3755669345234872363348756278663522666829605379596093346904488690399066158049461291594877068565\ 6708789944979715273447260519781674112525125597088228135283644313240152042677513093969979246674\ 9570750365875794537270892436935563302938080950737021426213606694259572101988919387643601888449\ 5066234775911815839632365583976962973241504903491511227611414317474733218966634326792663058946\ 4876495985298304404577662516927012663213241275317806636327796993773114017727878024877010626785\ 5751295218707207931819514021076997005966669878857318593346555392816390085906574973836505784794\ 1388221554360811257908101937004144470517763311152720466064733570696182296662787800150362757191\ 3632747930082108498237540556153265138728766833647458618993508286799503917593007303893776667419\ 3772950093852352718637178920884930721388435797067474556494285395726610461807896290510541920971\ 6019776195668494948144170628764176484902514958282969267763765806114588718198261841794433114763\ 4960259840605747931707182527421787593890477030673810521336039029932030896199299505051064415060\ 2812245669787014627343634125146092975272094661077921532661344256830006173246106141682084233103\ 1154022740699775107584829475491413412645677240298421594044575914176377402282140904676417505784\ 4654013824069436626857685916416236070387214210121364576808942071810105562883069173570625111812\ 7830064745988522722420196074665993936738575946541393209319721065423736718634683781548989538560\ 5908809852829441829232336219202356271674095118163640129017054530552608374798627554179735999600\ 7856212885802733764724863549765058179120769608237375433518702441520724770198431828641532515539\ 4727278099671200053895508019783876457842027476334528502911960459882665719477375531528889593528\ 5015005292479948456744860356773471258913011398280162162392717226104595685137628073922222832387\ 7850052101010865042097721546976311802983741905790099853492575240882776211333626934143365173658\ 8936968535347009369003400703777201659207985633013443638673683422575641303432005389459986276867\ 3314044947712531986115086383158472966238589962416772084353547318380157114238639097248981826729\ 6792128229507364966167668728001745428570222497550319526066673267202251768010259103188453312826\ 8011129018706477602044083431288044925168043531089255895892694843177209227448881200947512511524\ 8288879284113228585156576430216324262892098735090561398291438416821557553916810007546887461406\ 9948779726578046953443877104496541892394005941177839314949470106245610366397468389565869942254\ 3063131500057890280998874311281979303546403381020451497632032888003275203777172682031789901913\ 8014330784267039407899130779538759044172999869713764975890297575881390889571920056975293069424\ 1320940105743235462986754037840538302265098306847338890231814028231227599685505487185445070365\ 1291837208574108514027461750371375744329538167991177460048856483497318634569478233120881647680\ 1718368415786171771938004981301986295563263412504158284856468764301638949513616762820947511188\ 3479418766646914813700227138195890816010634776705687827979892055509654210131180368760617951791\ 0638120256544141544926020692383438841002622523715105555618696306483740824125741844174518067283\ 8186732153286597963815773353802851539111171991352816586308248851103810075456844861341624030416\ 4492428457359406691703951517000416509590323383417625238954293571671412375166256479552589652333\ 4790771637604001562407336948914360231498073104278241456821971999316955471489075985936339626373\ 8705522906282441234033291494825473590220296593792696514021594801138501389907638492838729983713\ 1587124671415625938935029843372207092890809810189894384947078696504287414166928117143104003350\ 3578986692665753033096164986172551899314709368546663340762969399215157445088844720700541979611\ 2163714917824534067057628696038611027450799436091242675176802213298896859446297026960755602214\ 7106274145629142831757829074565775207646831013222528080113844950895212487055981224130425738321\ 9535732093563991172224258831524055671354589653255923530160821544154801262520785252659123953741\ 5024105114981961548839403313576491460333014301832157358957150874138967240112419243510884219610\ 0938486520307405330212776479072162145150557310649379509617204132026634141691724382532062927521\ 6058831628605402940982132228534198366329814829230521220368269186918149106761423932315109650436\ 9826023687617533477634801130651409288785963517109759290502742995452172318537175441080617713973\ 2836503473727336025794798691275236794869992698023592062262212221528628569995221057199149407914\ 1812694634785443600056352608262107241560716040234298908728156098634026489194786592658683127017\ 7248741320136349714807104177993260798066974612401758570442963082967831952493785541096311930574\ 4956321885675597865344221327519117756710979348076630022002046439678106244348138229716879111184\ 2594207169727636780538042999326256293273071680659286192182211348893889677519184245548605161990\ 7642762561854481006467456092166207715026897740512400407826332224436488099365074712453373211720\ 4382191275737365014435616351578057162746457851193365999252946703333738438067169582192500526479\ 4121418226930539842910122420965220139069226652021840730182892659208755525922309025533116851462\ 4080329969672811965424462622001683499965791937251628750233426728346808292030717906424286544017\ 3319478445565803516915248227057403670073711440524849180314567294626659734106864412310977933232\ 4427383927736484633298579183318989196145963322355291858893130689322606664741209194148490453174\ 3391626325232178920571233541034467969374954354841510755831196327530922209203174232870320943464\ 1041299189329634332518879344999021378699028540209981004741305725778268501911919514253815272154\ 4481256649477010815047655595926479474857141777363259714951435146329146952067580196841917676284\ 9606587192416839166843872243577366384666462361849043976736902140576835765399523869385642604158\ 5867790245422677607538430384304812181290705753053541251257475160526498890530647695217905740997\ 2974517979885509767082347478852347250215756579448920612167992274706597231913348535257396593747\ 5747487964373158909865958804941987225202328308227679085671193907764134065277173951534896236529\ 2640985721758323491290307866835696129038458959288286289665163873789348662242063553876206058990\ 3706044555780955489478026199647878810056643450629590778921676484502967491078318065389983422949\ 9144055676298741340168779283920366715460337217460651819916951911115461122696193582830400183952\ 0775260301081282999446058330203316627748932566896306209495675180062991388625083623516835896708\ 2389705309201910007998069522936516536309781098173741640657603138467628844618915596508088433652\ 9495231892867215096448126850772818820869811736190574375024017399792830208556429766428349690344\ 6463920516156239351673905722433131453430075401397720545587049568926550573947666423009621586852\ 0267713608619210623050412926431071624439560127093867234943473212971317105950453673834769524856\ 7987627531871189854742794192048931016947681319164489492590515435388665209442018299197010455922\ 8039694184003074818576885689781915881069025064307797694978120121514535470288967923222102721320\ 1204701987497993225443470748279715491428197695447162226484447878844639109802012431072015344495\ 0681465235775455491829756398654261926330420564154730856326022473546921437352752720830137496677\ 2652166906841073732124598470128574857536346454686779518292285288794518268724815649626939839821\ 9516606013563963029450395850511867565791715904315613156624445865899306181341490208053252069648\ 3734020599605596484985292861190280006266947054060126377128684849914259189756242034101413629013\ 4756231134175063309406515379569701225333015350882049549415750374398567101557510235816082219827\ 8583117666999194958132979183350870092069925208346843719855682467834946342564789054831078953323\ 4648523048429626231776114389590429422623676959655749779278185154235371453430943202301829131689\ 5011992068495062666761523301111057246059112559222920734620953278348521904979336067764369385328\ 4522520679941789720330278589517379965725103788334759688358820654635549935242599583528866177850\ 8719858136179342220252690317787545013597695715198475073693719062067424527976936496914863765257\ 1796969053337955502766679241656156772455074206272316836532220336607212581057997555799448174069\ 7764313704947367075386478949317011194925353169979899212613087679039363957268512963413785131156\ 3522100007902075948633097451566761359593112132265326088693328745612510791015824061265211449763\ 0620598490092713727805719155802358422193703170993665795445684015321197238090887311564718868884\ 8015143544439720227971377439730708809572303595884722102673640510336917798237105124662050249256\ 0125208700362418539381990362953754307856216951934740418193657917856335616001166645931118499991\ 9160176957814452993552734452178281150752550669300439392000968777181321952252120090488885214919\ 5087915912187335488887263309682583538649058050472314685898833568419549930454377469502759878203\ 2385413039888979237642326733380249178101760259933450051648997950825937710599485003994704143387\ 2048050182592970401229565776193057604268609645758938225534942119422715563020915079436640809256\ 9934634084071690494373041843123476967315351880134758011033020960319740521883933668310006830835\ 3898111876465979522608569917378863998548096756935201004865215668315072707666701913175826298054\ 5237491366073850030186903064299039360832488367937006524444672959481475972970385246293856510596\ 3313189317730902559970209034433627493672693816973823108417813432956067900897260508994591808377\ 5713321158596532488655674834093731117003177444256159637623751323170268552086432152510894421611\ 9366232984101313984371714209461272533990816361712970775213729234598834888208800020969879088703\ 1873208474042433834753952095165557793309435747466682645422913114140934277927605941469158525968\ 2017399344818411035972166332639822849025690630416244873440379134019032654730107758324414536385\ 5828738206769947684668136654901308204513008992318994824151605325107131479937903943802194232984\ 4412514293724792531572240877654805431679655003507167581685857503938927719003589261641584199961\ 6538242177484771856343547763895137985099261268199516033575329007496775730097819383175111850232\ 2201156904014777051142626526023779378373866602274751653568555058383155063684662523100987424776\ 0436873004418874523164390777603031207191806780095797187114798852084784330511942711770220265677\ 6099843557487384463745995891309866503320079517935024243987556697460578412838556440391808592720\ 8108811018021121522364401659125418100272150926275268546621551066903142297427669162984567784566\ 9124993960465139057587320470457355516505860941814093043212815170498040089105423059267869926855\ 0715244917452291272844786165341751006503356894893843383010010215113929498995138393978900506940\ 6169374505765857254669554255445782992688039450833922300620725779902933960415336762090672458711\ 3581830526594165454905183917500957930785987328332328779522633584545917115442675856760535831585\ 5540716441063079661069291461628541973783970403333445827559224136885516367677783269487614631565\ 2777925480236651028452495427269715890148780687218561198107934308693374127141365376215289606500\ 1281768753080264720375513599544626934167423525468899098668203077943225072044221256139943370821\ 8710511116813394459961789966642679470800715292038755005164552328538822860386683918560287324464\ 7185913516189493854281938312270727545354424546201777051246121451700400252627784171764297167136\ 4219683057454346550076736394223117360497609465321769623104968546018496647055814060651825640979\ 1563656123275903493180524572093255627115164940690458929336604673126627631528453828745161614272\ 7326819247740290110180922190846745066596530388862315657205478243545317197511305665983506645307\ 0749140785694779282609588974692786031928810356030300557876245574286617671251292061903003729399\ 1832863532655381990299910399160077912175569559419590591862734213838384801229380283728762550125\ 5535563867959023864185287104590505220384114243984775983769178874275413200404794267761777510072\ 3996801947547826288812643941925729025431759700403314678936038651349104674651605189057507952212\ 6064731778490152254070098249327769395683906681575609461678048313367232338785712915300588064874\ 1886711323159566426289523129651983323592888169564352437718226455943225902910639515538450103612\ 0606597498797630131400800790270232247655733608237024240104508920915360550231545228577535285957\ 6298027908184776546034352896838800169596436701572046112774179994023669344010441646893458848268\ 5071491293630719132682116807708511471083468325476274688419191828886502954554980615918665184855\ 1235344701880338585311712374407267176569738106940732762670896644023085816750057307067851924368\ 3669942475469334973191203428082466419838496582755175543209613678054916401276123879456896141472\ 0133317964606617768442294932182993978821941820938166935875273166764864146101270230640087320996\ 5411711521295459513119561476212156762982098187825608238989935247830472950344705653843838283688\ 5787442190924941321161142715070003365401024760603670814964076538305205530414838720836994818223\ 1254854534433342135820548901337813507319762819619947770226194980365922828490599032469491149428\ 5710683879662090453434939187746419618303464128354413912476010543497798755100075954580543608103\ 9722685095068127053866724367461414629274350545787538842010241943492672135233859442397306202189\ 8814271689140076820095125413626592715525686502085582625658047165318424348433272519387348566516\ 3689075684740570105832258689860544202390607142781834541834221239924535009430664149731309933769\ 9753756240135063782438573902773418702276429354280351556022882299706285812425092094658340046263\ 7852770285552351990193993310204060009612644212384125193810595727597612178599195997623494546900\ 8919006463077637039093426545902604543109138114335256969254216862087548133974814021865953796920\ 7490415350953944871207538363639543414630391158202354041021819265420017384240912904742680908974\ 1876478670460233061766841020222805873289091370865644640635134971956274976611758728992098892637\ 0233805514936796513381697797589326101312412533235473596005074574541292303775469754543913793055\ 4181449433712159204042257159994234738941832879585482319101926035331631189503519592456280828724\ 1745087575499734553437533132406813197235866901017668502860634028002725235268064017237454488351\ 7000217734221094412210908816749113012229004701882471700588605520377203640615046046898285232533\ 5764078320457117310748158703080592314908492170666936048349638243862975954099101813779688736072\ 1135074097691152102962547734787062887681839078353334832294868771554248483606487426634319230894\ 4634463339214924039210618077796547359714903923087353704128434573590583888960833969295158420168\ 3187955704621204860265440512842855551905215148863714597339826737154169737386340070531269320990\ 8995756621214911630617090867453211723868369425199436393736995767835911966958417660732147898604\ 2674548769872443980316305782801815077466762805426868189717530191308780639774525214145401011527\ 6753603091264954571148834518690869132722223633422503164507603665729005119461173445188601018429\ 3600328489608701736063935435324988647992926184234563241223916410904817864974700864070403093085\ 6737987031039613457942902751336468585297784343385852562202572324915841237155029699557513643612\ 2015806046825807362908687293288737373918978769057999308497957259930387125458192990745155586135\ 7105267020227960808094658652828476617354262041307229647604899993018863568394881815635305352602\ 0668926855387773303018688322496054837083151462150078319577516409031681045110661775117716932120\ 7718496182467610670724900468004807769327532955202354933695904660171037650632214751462624478591\ 9139432376578865241725167075213287095524573907169304039038226943892801014757172172477245956557\ 3759556090050956792766084121509269570935711600192495500921339469413532805845254578159647041047\ 4085551440256497682816526044494260463892989326868397943603412879014651077575415438183254916617\ 5032205822014579462647045132727594786381080530807015612985078655935244131118630251130587112211\ 7797505029978800680756992380655394450830689980943992944342063253932358333851357368333019757046\ 1282363190415508539746205941753057354777606122212087848509999571796316666927485004111055552354\ 9733249785318871733607860066715532724747863984627401069142693381087893353872313890725101519164\ 5355624121665801565247027727504211163137270648859789776950518645952154920755942771219312591636\ 5086313985003207973374763230429710166938721320687346985612232237683112242054661423408528192236\ 3422631765669508697074672172286095145666941166416390065099779395215590701922146163720500546238\ 4958733759618097619017702936625196758162352369302270127514914189809304626327054818151577994251\ 1410759740804975147936184427521316014928512503819359533004476904816259637599948234559194154580\ 3337892737835310419984135493093660251057852116134983327866837249055980535372010590126375319806\ 6356105008009454015421959024913220159264068473549353727889097028468567517945266367236872583152\ 5461733959671765287287899037764010797100187392902945204089437981118681567092927811581724329756\ 7491835509213900005279162579858101274466683239163873177590371989093941524661110765400984807747\ 1072633229817908093416844416880049156902921229489318129107464471115202617633535803786704281371\ 3279371592964071089690407897606746113120341340389794463669204282685341548294649106075383238896\ 5025103881472597686597570862216454276985825483014582900757252239582501989337645846211247192745\ 1519695469717922238555037768477501429004550065989781902904771763131616162289667668048321015977\ 6772721583102665296237217420083809448080133099790986527588028976580604985767769382916710992547\ 6836823051839700743205330091595606917986296996832737511491508978557812652394692012418350924557\ 0898535932262581665610852610024568192689405539607823068394604694039295341193580663914329658791\ 4701863784407518558223966989228702449726357944284689684475241331891217899779039953647914756917\ 1633859096380932010084340976182799122616356492523096499880005162473925682185016506210625925114\ 5287897678351396334972243358660008409895184733230460466838353072089393906957129167507020667545\ 8471683992040725134910975715365605141993749086099473292746017480647401969523288262762080844375\ 5698410718337108321619768581920963629051524364306353391826799567380496020409954685117977503867\ 6178525348776958801298015069772551099810427959282874558636814312044463468029958621042333956853\ 2213386437974189221109511488555121253674931898715728869371715994363261514019397788401262679622\ 9888310835236652197470771951194198926702512026763858775949952340256269467154516452781356112844\ 7694442929049812356775165441286631549050629837826959219396462202335129847150637756198016534046\ 0984642079252348179554783464446927961399598843571780837616561428577173651463789446909666910506\ 3521304619004403674854418236358617302149317659396508256164415895722034519376943729891722329906\ 6461658337073260375547221825313052710045323676238703899574585900145030746386191800847755791034\ 2754856626087130268870583535707834094464531685884379512689276203617352663903717075498113560515\ 2658274939363800012371812454736209196213845989631130953176189615248225315484463625178040626014\ 7845015860731336314512926740230624873919795032321425142934206560049086468492716789340501547573\ 6285752668661963887898303679254637640880150707662697566425067593198397726629516901963444019882\ 9180716312180714983430004458675174805336293922595927710353343875360368657542619243397821766403\ 6590489641877006727535145977283902102901284418194947977353446407607570093626527895314096583242\ 3866203799983787880173325926992721906803270299240869432397403365790229148640450291752430162735\ 4301586408786671696067899692087306930270995340008479408847144688435643923278533230740957625376\ 3197151441925886678620615996080964185372161450001052950591912902804591886723193468445323981248\ 9294081312080245437794503012275735223267274209519662667194251684501031691429285338035830368424\ 3401285730583530326220826656442039773309005136312617312685266569530856697198134237928286826756\ 1947315144743227865846156613769583737311617860020832840454402633840130596533426367912448467444\ 4728694876435779415360245476116151259354551935656839835124326268096486337407632208796219326136\ 0568053189596728674795802244918446097083623580703027591246190733102367690601562852305141250947\ 7282130213905571599687370556668251673417553414996466495822145702897712849759477814852288334955\ 8869331377252184550545614392335921563528146672126718518836352506098590341538649091732891315562\ 2797766824062193403164744864782043011650331704924147775710010344326672046363110926868477127741\ 0982466503340403936591653543602120216945307797009129179738934064294708551194014236113248596204\ 2062725600591090735065877748700133918202281428893296187097157121866163631823520833648290782306\ 5298342649572919308659942256006092821453590871240938144945440107508568406647707905393987794239\ 2486167646056399464245690933708106611689615609713343709116774070844434799366411234780224108887\ 5894440411872596127392328270042938882050062719724496523642747025391525722734412102973539925160\ 7345456113634382798135014684243686505549033966305624672870933047030686028739121760839480286808\ 9684134817054453083169214266125780638904227235458654881443412193689593967819232308554567940498\ 4670955824065332314994086616097038299169891921100374534527266437733550185387847199766569753670\ 2095310702739712611147077072949660600146965988422389479086724183495589588449799969268377269377\ 0746710707139788661872795024258077772040142240394914765264452136018152011056800385192700157577\ 3412595267835985652519910910038921661707539780571701060809916964425163911085224855175778134309\ 0786676662230001032389382909393157433354293341130231972196246350399818226345132236848649765595\ 5794606510054874617458491338837492726630074179544159393828144673536277606426504027372935262381\ 1370042195381706817206007304664429624818427711578756126054023005433004118069717965175759208199\ 3630405586637404765773898861402783304797980996985272812138449162008583400487763436723239295618\ 9165076734315113136121600460671737034043485036904258637743629940964352750990333541175354172577\ 0782044180946960425864210924690736050303111998066548218184974340799206541219031533424463187614\ 0033522303338956897218024793826587760416149359308957426970519328449133126289096777767399774642\ 8042781187345377710949935616245549709128116686245275580428013899309035447688335245891017024109\ 5638296684201964945360878047233666117061488694547898211002793563310780988470327335483089294857\ 5194165479342108270169504064143079363900268338512559290076644030615472083946898314321432607069\ 2570826282865187372090510623732194193279272163591053943295850651918891670321895734703385058471\ 3818423068566844371683800425383129628487982244484323430715022810730627817516035003313759470259\ 5601082660212434126344849365388848902212114747361992853367537702737439788939014394887747468361\ 2228287103417758674173863535486855931496800287658747215176397571484900145410999197177958243835\ 3843540553943522907665687718172719066513386608189431463994384208650256474215880086476053600552\ 4406953569697263130266950731231079911360306067846729240655875971581445636105948197963821755067\ 1617208576301174662397195516379771543477565106414167293125890200522463620248828635769318474660\ 0982847755407934696060559536911454975073095938109595389664984242134754929454585000124029878035\ 5501760660635957731058370349670089609236447771251312494314966601571417237235718173276964730991\ 0329287358131154654973679537756309382841905750103138172118507721243622553627338150054035221081\ 9199582860090346745823906065432288600759612960792952428367326849429524615601112686424662704220\ 3479122783739476039934468611609561588934822951189835673110110961652762199302265713397544555772\ 9755416295370620672276557751303899983450382026539435595357693912884851342716092270003555049641\ 3873715889417950680787866924715063714008779257814375718841028337046243939653313559637380944923\ 9339987861301167035934778962550836278969477237233992912232855666441052731953309551681362936048\ 2330908200814589355188605765894847707479835982269618865636298028822313730277574572469980751214\ 5494946206056968302516336390913767750498352860423130157395748726279047799964887251839002302366\ 1893111924513060361742391959359872543980249403591700962673944974184258814649071556089626375923\ 1130155097410713498556310881627907804841529097306918729673777593184618662716741832972952978298\ 2529859753467335187503146842185174161646005849766464749193745657698829422799532750436266153972\ 6365947987806230658465426940960566547858953471487677884650898550031542987972722965543700096113\ 5382438599750732954468830418375058185091182089383942485180929407802777108865432195795858996704\ 1719385639928981039511844790256673494067798798685005796879246914490278424013920081253322957221\ 2174065371259214706570051107231704908344283630079833837296896893802154758372168795747212263368\ 6129900823137322969692570497676189554201588407357993597996413213298094700467854892001000880108\ 0391070025535613004411311207887026808096905603628825412889891742260012529886675440134482291281\ 0939073951554009183733145514790595862222570081109292972486172673075561713747242550228244630262\ 8768955022266252092600506117114018204071434732367688818292076237338202976134894021656865241541\ 7819472413299042645253520027973324444753327159961643131306374496654709791983817427326865739529\ 1419790665885504258457976941859782582783705017937055285877373389003797736112896435749712695308\ 1464786960921199092461962556502071224970151746792427298755673581054482980295483104944669427210\ 4806066341016665461662925379505769125775672916687930850219093367926059052060971445745004287725\ 4194481610316712468377244694225613812403786559343242975140458249142395087734748227719196825159\ 1487072651419583975590084363958451452851304858471873719067821402426567217845288352687946439186\ 1962053297790827948222774655293661045404919934604560853210314162259178946549807438643366073474\ 7868804248198387300355413910878399420972227648491505835850832773111260143126831673959822421249\ 2852487883593578490576156781491768376799012817291743168096129188108280859809893806712293783567\ 7067728154565455203240011196319138387738329811646618705942057848308840516535314608981966630675\ 2440138523047478606325317555308838375374106089298829529995892224459937333024611682573543896627\ 0042867500798920758685535472971289399163269311435781602654266247753722353319396809805969605752\ 4013458275326547024517265503861429587443200741953903821835457488721210423567460858361226877020\ 9662921907997161928856051106440909579475216632802239945187927910184151626324357926404737344786\ 9236468801384200863565298635406556529446893033320130127446611147121139189297149001049571302157\ 4677001570270190983339399759775104661242658608686245196501179003381020258021873088572213493580\ 6391214045869800035728871647109570193131101247441232254061895194936835835562920817982977573961\ 6933187770706974475689728211686526740339929872466909069300784882820894999455461279665191666297\ 0782313380485821656723157351831529470919566974352819250693809477146912629873652424523960414076\ 3862335807776028615979353762508624960585950527823390990366198191561825973019313503249503476021\ 4015981542806910400362650669218082557744771640086836514975266290988112065388642547403056757008\ 2028259505524699660982115201689602260879829668012999972604177222348400546367851301396381317451\ 7358128694881293822160343200631330678606919729201477853832155757554296758465635969110386244362\ 2435918870528214298690084284425760162530324640804372251842027876368600791806578855436096691794\ 1485216729151790138674796438280814238749243084796186328771909889280940158907542513145177669310\ 5530007623489777358583059142971555168113533544305697442395573840617444241376824106116966446154\ 5833427253258371259316121269550033541907944721496374605507095454077796826420279462525997298511\ 9342679429034395460511871593530313974934223725114306074781840546412098001955721873654447901350\ 2654269451868109937686225739352436086547385524231317761108327016670369279012843594244944769873\ 0689473330260932091576622980605187742918227154999351426109467931585716371515465139162371906367\ 4774239061135426816941626727237939161706465439535737995686287844141679623559962835777100293207\ 5242333583292027747116908547539570542329155951390216362513277633269936111009341899395452754370\ 5194681897723515302147476823812537077101207753501822833186328595758774541978056487581825202658\ 0900853244020643921965401859813485551625099650944899304456114924468514145452199608402422121429\ 7205122104636540841688551788580865747817488782816573811953847715599733128898775550244303056437\ 1236628068290773730651471330691090946537579965121981190646327251245575673044615888273364418010\ 5917935130243350712087797484785990490284966521685284264454676796469627542798342292694812566249\ 9107795784815472022270072900171809408722197546087587599317040887260511607244894925086105980222\ 1694634382316405081159819186569813503118200957243666538330727772355041832655801505722236076944\ 8984285206476160446330669641693602744860390547573558074650666145813590890040540377759028907266\ 1833096738480824830202342079506445323527101706724506618310900569087312512637107445504012031219\ 0106124147477409506091221809232855282831776492109976082194987469778040907810066635584755182580\ 5934884082353680493981678324332078388817227103733161053863700283865992208619810949833563688506\ 5790091991694544154330109398594233480300040731625026256732372147130678957854583830484261528061\ 6814661979060576475931370451842912501693266080979960039503048135660980029859732597496481941645\ 0514933691530887127241077071628746337754308979285103074234790471514183800826555453087172562994\ 5770237245093265818388388034870321614220137900766977979980954752732762513014216157106023936006\ 9302411050704826933981050552557402438173718157487949010282659904210086074520474797252169330986\ 9137801953497859791923041006081461265526022617354413931603478484120660238281812110679043320316\ 2238802276870130475795336612358240666476354547400240173289882768548511404000853610714692065524\ 7643113921930308714362903821877663305047337816089166779963039377203375991719661237339311819946\ 8511610835112329364505284212887631958901690505138925437437905789630987134464001365514098144636\ 4620163349689235022600252429159455643574375031600563957891856379815355705004282277281810561186\ 8088573931784011340940261261458507621905786689064264735339391216841736502553850006364618231976\ 1669397781292173729291800991134782877417156191901257324435582407141198006952165812352604566743\ 7428094953458302479848705470969311184488490135934598953207945929973693253492636559245248550181\ 6335984044471111160615590413673241107395414560117979474600178536286299090317387254266700174662\ 1910597947205252949270226949123971543481069808941280038469138036326446757139682858191030951375\ 2434761188229290262492984539698569881224424871011231272136745868042170343219149367277895311229\ 0930349133565028764396454366112590732163040733591821474757362544378021433171533086818248855297\ 9262452279053327802249477883318426223987776322143901537935547208788805828027758882197353381606\ 0775282211062558160187106861133922352129128742901215463581232210390199065760946588521507992171\ 7072856564656482644481894956230746594990003018931148436997549991394070605298722940235858292658\ 2354079973765897604770689379342960950445442494688498657008097188069816529751372028416046775403\ 9618157631180908736916104320334070184613373572241377111492864579103350807690755274182029883501\ 1993020730217830361217284568471064844561540137633488221006382362216780431067086827115777938515\ 1335527613295585699619890418857087619707762674678595230756183528506862834841815639384376076074\ 8138750152328260738365234764511063163516796701923063147354009934210421826859111210698761256062\ 4640224291853497264288898651036906665507749157607982666263640640959803280331383098721626517648\ 4606176339539193398257257580600850362032746530496068190612148381077562094132889254761193551253\ 6023353718711478086375901326922876715872289819963210891401700189998771981845496936766279610151\ 2135424116222961549752481547156285259843572735091775587771517479946960769696745743079814953284\ 7566275842110861718701544196056299467614473338317566440696621859179270599620354414033778375314\ 7052471354751563524320843258892454910610941266496151168970919615676455706820177309802797092447\ 0181182839396180389840198966758620946573485385785604415196877034990485022975870101902813300015\ 2617685977839526812969060131905852745243016452371420812158558527935916396424568551149466476095\ 0591417371715887603210472659314320874594661896977584298462668389181890501287696113899885134457\ 4674882046031336716106804382041428699690083069345040410620403147085188019200819611124235644424\ 1262306187415258879103864131862621027573446364620044127960088459735843885466484107366660878365\ 7145640917595225368989180337261637805645887311811626063127274529050500098668420369840607302619\ 8484389159927761863629633634530215269902055523847722639575423085693743831288951926814797557248\ 6105895412031268491969169801590113332897025557992950294733248160228416102599100378240918952127\ 9326457858574503884459490492336984382135388544804676195239260004878555888136830654181136944169\ 4044860160251400028233142497344083080568443682849632456274608635516676388317507706320629078591\ 8198518583472461848846738581390753816889430477471040188276928195379064553327124001157634811724\ 2799496071662438809704652361253352885416911504747537458913231514216055343626195676230073393210\ 7455065030640196367457031664881953007963424760757594133629178000497176966212522457489054967386\ 3594126107780740373162065374734633412574732641307255219104969149540996720103083421299386854161\ 1870159294816330294425189991766088287345193715628353295516827461877799215272389424847831145471\ 4908189638290405278431376404638412281512184368591438055005806333093467275383119202508572709066\ 4409550540545301656571263096916313672650200847117158703038541244429861507094178485035326179048\ 0492260692762505264962376955230362746737376942501045884756162940946496715659927858490539318651\ 0314526444855173433191120249831769967441064548817243216320500338474041587037997687427757217952\ 3206763308930463313985489391952000866350510692282063022539772833188415359616452061440035476421\ 1193608236971721679209370982640137353886263895804590422459225681108096190729885776487423151216\ 6125236348657066059464462333072923474874710633004981862356571699193205501921180801608440236437\ 9201406512768111628390077038676745849988387035730055666047532632371848119588918717838939353190\ 7972259639386160928478140690032728128609480268816262918548364396926814254482594367348817783145\ 2220087380750641885956278793527595868102828378974996272977810312721967905296688036624932160231\ 4791808255607414539280789132640052584378057608851553037185649111567772286776324501108273561342\ 2348916460579040386238031829176087318077457360069532192254785558957207950124300546867065007014\ 2717538359075822097177116654400421959740788559891150203459169579492463631970447505440321540606\ 2571389295758518264435670947292526300719296762053780153419114028097071184640290166785317982133\ 8057561648847585133026896344787804233686452766057826131261221852873119190788713320839880543609\ 8687774312876645619689873473269041432441870452030852240510429511083150727648060961546618085155\ 2572294986016602685534744681168116615117267961167305572084315442016604931668718775981926858764\ 5702019471657066693381507446049932394553706974173972716817130694995820973646940829302090816365\ 8415211770625829191219971632570510309234371060277525715454858614907397988869356523330913595400\ 3359372394108629512446182636088008330933756669155672113826888835894254457237609549668579940843\ 7853637463884373695698826594061258362320651851712790880831870698780098514510514477938052549515\ 2236889714672864982420545941632433400329597722405042648212950568760432850190704927979496053923\ 1450499668703764863152483764860781631722538631511226011207485725421903717999926993408059864220\ 0355175234034527377309202224800169931717840690491855415092519214639751262579969449374168746725\ 8463950881430040518939847241543569920866719282230048261237391596703191811982765143108459488344\ 6423021065812220926445647450819150990029203681699733663802706629064075348576892754196841700807\ 9729980235135687169687227954093258547893303671073005546185845605885217956142893688469772888868\ 6820712504596474722629058823681903051610696488926023050743858294465011481425944628833073994953\ 6229030731399071174742205454451265153295168521119217101388241366898575581260222751886980378363\ 5972603678332083792190523815960169017029650354819642069948155005260944424217543276216355713581\ 9878927524090990756793660634417556405689642910060940256238574339155844292287478890792135093379\ 9785832512347324873453529821006731616862980213034988736817628947797857109778433884850847223404\ 6204892421721815411041101685700207654146393631678997094801549256135255163465245687482255791298\ 8990155500258350400634476203220003950173916616224486179069378015582400716012770184870795889796\ 4716038008209390132195022671334304748698902647750282249219201331492797329154577270435141159272\ 1150087493349887027791335640531041596556770870553906906039389481983865572468388193252914140817\ 6881872884080358936214635008522655703212312147991347251376954005083575312282331340512392616708\ 0478063032840146689286125176500680546281812168856347750756450024651124708009343133818574626459\ 8978407144137791778448942201251964502066991427556145730986682907804423790588346336446578438723\ 9671192163252426303360009071434573647832089497506938858525399306969539887249766325409814654312\ 6443164504399658501230930982112274389505351277650157323672001750533826084308487124105668446604\ 5753710060770705666067817780859109920889298189754701206006189722734729125714444167052524989426\ 8776340707945116697405658686907240072684675119877710790633475897792141502235817226407112236848\ 2856550182049057333727497215442037000806887193277074912089715214955138230909435764468941322688\ 5011798462709265667398050165518523446212918194866201719452553518957371636815959437706211551221\ 4572684136800858727666963960198431862340901509440598928165099677628721808473844277724722232906\ 8391700134982381472442346253923638241756228475435740288722377403412415818633298496172680071866\ 9214264899848320873526568579834908661345247278063333824278681692344063070887410509285636941049\ 2437760533514694880782690202335747512761950604086937060966681935850210514483552818352680901103\ 8104968580887373791719276944958214904542738513920343008426113940479437776498429407749104529015\ 2309885811956692055307463086292477205611349820677446267963756889713850513815929016278806218138\ 1651824689259452736547519941940342316768098587472920201705535685623645849763073287067918785789\ 6865368636202035640676334835777154138872749982475960978578244201722299380433053442722597305855\ 5567369529606201517336594639456356207845566484804560915138613825773812573694116753768247247306\ 1004291520862535031408665310627348496613468494928779036352361786572188541532123978448056021922\ 6756274767925775249005315539779855237470481361630332084265831577124048352308209277332457285227\ 3531807574440634056544337172460647209598725210030292178687250679374227229255129989551521996489\ 3194829417647113375162631668146091456901052564983348606495537736976977303390160584017870589419\ 4586713782760552271397097961595763284490335182686041112360198556008413489955149191595295283421\ 1167694166525732977989389631230905548735688225560551809559482446093844469169878497105317872883\ 1220413476028417684212461495571454866724140621847994279691987761638418250290840561175215600602\ 3157549443526919026845799984252334682288247807789589334898127642982869631861438027540572638410\ 1854403039210925782243384807481884488684372973976653454353572886096140410652188159428857428607\ 6107033794763829004215838181610063996907670015736462421504595035272841211491835837360017377720\ 4739407809207278460449480094296450596416393237145615812798331005733994618618982855810181060155\ 8099038884382842580754144674722794240420287560245095921682325008972215683096089847411414963495\ 6249643428209919857894458820323429288268857685361033634781643201414745939888363776959108106366\ 8714319924185296228749525699962912401616784764166453918890174693965962292811476234376868178108\ 9488810199693950273106887035332694087363056896991983450492595344468023474899724022062302495828\ 7387081610893863066631164591337129739663712552537954071661216002089056382693568316753655618419\ 7264654740315563268067284245803999128715070817312843014052311361862920118288739119745764531518\ 3252124935838979745585457214323467638443324488076423416544863592031289654349077818592490302323\ 2683440486507889455282485065619010578926557054711227000636923662706860062677093974887625549445\ 2972278275588405879860599906647678220717928252797630955978945261568150104303341918940525299041\ 7407961266469689424642650708095333671015080061033862869015148064096519220567449195930657020757\ 4821172201403745453140306275325349412426644627170288430068400218002167099800656897933067149214\ 2906963175720383700014916259186843923879711973526513700901213877192785073443060724327813420702\ 4404100457157880363953460334626603325765600933529719622814289820127086505352347686778125295225\ 0867292595832457545311377284484459393792307151621208826018692417375857446751154638514512742679\ 2449829219565957253090259947235383545740469386454830534465633442681260868904606008895481597347\ 5927211292923736584243702691744236473535775054812829271775403492233411728089876941652021714583\ 8754061493877148060529724339832928905855635255854545175542120198556120784687721968677917847578\ 8745687947360001258988202693440265871662365856808730083502263575114082741609285780160132164171\ 9678405304322128543208515425686074526336575695302581754185493881355832966614785003005111534174\ 7743570317563410007405121616874646123952383991397817329093504812151881743523744407254061439943\ 5607774101378806415185898677106264758640461213023032175132587323191868935967530634101099863069\ 2453423022354595049594702341955161255799486587974772731646549794912328628366015065281605114049\ 2200777999275325228763745615210044100608848194124819915023943821343419779857115425919735591012\ 7451895209607448525275500225696170116950213457946006269715550167812135215039312187586270277626\ 8123764239746925166418203627359417517131929212236240490734198516272963384669872193908177785407\ 6324965351863526625986866867157507614273431157898323810171562211340341664148904504719860124630\ 1710856814899216423006080959137658133549385189772394437516322063175401606483454164645443490568\ 7452594213173303982158717829683932543373888181529577054738491434375275637334671612486509191684\ 1088282795876277304922531208172660543149410833581539637222033463922277269507189608907172648882\ 6958324435114474662015447815218440266657953629040571173179228988564745491921883799503026729437\ 0399181349319461226678017278220449430424280856699207446003418932342496632085852048437270119887\ 6140787200571768645327318093299616242631619906991475399337315682259286766872240857968709201597\ 0585380383261354116629533320062175445843324520011564955148208955059878625004391135027214972053\ 8677248656590158060437606358157050466873202473312205965033204320115845050101040871271735383824\ 1390717725821469382213435617921030711491372925721946452793019578921839602038683441794371492460\ 7674137224458545035242280409676214572348318272474441826013548335363596911613960390486286400785\ 2695696161909752701783972396560592162543526849102402597284202398104789047430235028406104699664\ 7026298482081276994140991350175642097342829575671950557999917586420030037254038616964912561456\ 9898635985061356469669369358387854363470489239367947286815253742866749012084484730715313791289\ 4748324414711794414633666627021982050670430820095461677318261700388461038922528430656256604429\ 0832538668063262926066134215023061613209914539194134185059205335944234268382721016522019404281\ 9597348193337881982388384854885336670376144152613460325295190436598733665803039944668965339546\ 7024455859117727895018136486055816886862313179736811502606875367832805649232346890824099596796\ 0659649786331583879770562506973059182443902649210444149837171993071009158825237467721004520231\ 0952119710820133970942617197832026312747183218933432097378730661544969917592574257675185945321\ 1258891620035205884313296766858381460987713253593857769402294445801518121173783871255234379176\ 2140336656040905994274590571792146362932168238296122706836078564277846612890914893808445712702\ 9871009333065547553132312768797615834767289432826953823925543992834447766650215988808329430438\ 1715420708519235103978083713904821021399907106798937959833154429887557210014138052174922748082\ 9880699609382366838806284751070228442024361572806379555448576179598453273717237788909370957699\ 7222355995929722579282273060087071062917829843279432156249716268898048073401743701616561769303\ 7888543406204848014733774124146867898570519741067910853176820403301719139491609928572844304672\ 6867632500840641418903167504344416535126328948862403942978506258210365096965174090321542859110\ 5430525452899246396971818955735222421362078210682118999069688452775140521721117821844000071460\ 9929684876202896402796420794754236016640223372218272640186497042006176520634394906655347516307\ 6679113778914081628081008467067791708536769234849862929835396355488696901240994014908253844390\ 3641586320201199377179575784908980366160435403236162464252406073233705838873822430327947854502\ 1615599139900915939068211645226913565408875983948706032535642250221386127929150685545925380531\ 1794607971387952634894174291230707083241646823806868039536791737611437959747932665082810905451\ 6311340367861110347297760776382913264925895279852621541993088693176244571555624950920944175653\ 8351257980336720894557778012747336150377677525158275547917377936681479663710967688844117979708\ 1384601655354017628275894669075666215681759205914701450020859578596855118499533636361914622957\ 3582960735407410271262875791141515418443112835071727430466625782354142991075052878217236680409\ 8706655756311328250928483954345541266744481072838607954585560920875679691248936802645724640337\ 0036680989974947239644993033928457284918636613881265256670630050460327682511289172303860336516\ 5618182171005091192842980315745277951129663151784494795078807468352804289600592723583378476303\ 0894381496612651213623037597580853044351010064044490022534024609920963832869853227324313392351\ 5332752052836036946928903587587556230538011144641642250836404114394319308025211294488759715170\ 6927842960279598213941552315784134417761299907915527081874893603966369689211275323835614947879\ 9251756746475419840650474923864875879040839943894504234074162677374018765500750189257619750460\ 6821961151001122597148995384029472966433502730849440211043518317392712645009961563113107529286\ 7862075278189270272214257013813259840679364592469684096396139804529573552893412150177614938563\ 8480151576219698664312297721749665100381031034101523992147595960259863937883920380498039275511\ 7942808794402342584936956282005241513662433218093957275731816643663771397468320663930590825464\ 9370486805247353752731701298114667368906943367099582739403521141080475593679755121730052819057\ 2927707551130055025837440648930260752573040369683832330074603558435130304289636838594753169166\ 5447078849853496009361127513979809915340536052175868069007922860542341278849460983244366105920\ 4705041275698228046450911003927566696981133701887484717549355180333433173559895641464644639585\ 2996211788413943070501164531365835989547369346976580995951810883757474160016967423167274851379\ 3788490101727950103452954847354776381292997782301108423238511918139195637327788957196710704550\ 2610498315204977772313754980131813314478309130110951044768686741445762219604120573475923171988\ 8126002379972111225685742698469539809696677356475848259227610653392070246208930108576197342690\ 3560676857057909324456405838515923471068005442560046722719436683659328067014679388196812354551\ 5694035237305381202756610859509751386793944268141155060195477378355748901318125439810522663795\ 0031211998940021282886677757335146860324523310810881298591999993489355118164428174415447679002\ 1612598823778813144415999735981724478807768275107484755801400873508229909260904003411679423148\ 6624296615897421119682682951337693432255281128352803447167421115945202103126566242723196338104\ 1764615817424358885268571519732613404336587502231085675025735450271193532595464123695181746471\ 0751434666380462184697457143228852850929788652864022836488839713493761586652373140275566551958\ 7678063872458870251357993557035276713681095572830270383635172586383286771988129112365503630935\ 2094881805323738681275274704391153203346291610442370541184531846755725771833424354680844047911\ 1577474880736300036736910749572469395648912082609320631739048892605304668373494429346772027979\ 8221857797934588214189447120205637937837578751620789573188005542128208280063223073043341585106\ 6539793894958693524835431656109377667016499195646145503794700182066288298725538602019884344334\ 5939501054996029105693704899552570644233460642262933395711792206376071736347911511512553020323\ 1996246969722012606569938384270206412537591122038729349019652386647381626516167659697638493354\ 7982876016910152379448473182339512024312836255777622930298184960046774385959617147245935595844\ 4129311026518544203790337452447980128333494803869033864201294550212387270951664607667609542663\ 3590124983182740679132882847075188910515269615467747331049496485489895729707646679305461246669\ 9779485302648856172578178689174921352963030683102000856475003002645710067196205686371661268510\ 7033186602957344633162486774193566352116858547393068684873548827437524535902615175153973051887\ 9090580822694276563548331048087153146593776271222112087600253698301408268279124787946513650835\ 1366141112930344298252952541588728774344197749313265362678252900706429098326753920336268140943\ 5483922036713579010476000309179251570650240218334566199830953177770371298723294247194406820777\ 4364109852883175743749595043468924954257594486173747998601155410334063162858058118830001357595\ 0091544367414027324874102910253032587297494371297528176635417009339524571705639961366681451192\ 6932185083956039290092960584705257630019605896406942444036469516710571206510597212789212180017\ 1717814501199475276345975125970254537776160864191015863939240925105672558303864099894386652142\ 1401661593240095345072652144329349690324518740353659365352766132677054414648921365019667865820\ 9545390085146977086174731195687912646256586996395784052125503025910990627354599592082076675454\ 2403318346872415784156288833846723684046973944733963056146413995217650051271913576590957388414\ 8232069678888318243903338467640717029088545721475354797417462151136940072503526753204576611617\ 5772204913524440969206128447799147742001978886467826449865750189554788504396143576794100097806\ 4359950169959277035794667533197357883346909872785157805018176165329287737189858460646860346675\ 6874476148313308124763432196771151194887837075689026870831545997938116790196180051056889090369\ 2604186110501600478578844992374553643231683420499317573565011445829238217084909749005563968179\ 6977712429836275465720429948632411551740770440674660749785753505538750980320701273183866844164\ 7660006263956287651584177890152375958376314344068281732966616146797464631224730530296085244477\ 5672398898107366127983256680090795477347523961289816073118694033632474284257580937654946566972\ 5522603773038368281171946872188909377488931274789146405916908225126629500712016150888366960560\ 4182873268646889456736974716363359069701408069742763065192336747758204282546388735435638260209\ 2291935269702008761703242917240319498162567900212733328784979860761241621502421300403036508179\ 3771149613463449647472451285127940998938426004193424002385055552373966473578330481664492992643\ 3053408962997148752334457062191359831970050382632853571230364046856333007654450674177461026497\ 7381228259135541781207834935524319374090579565863669030683495083264247410416288244356054555054\ 0619517420754942641839761324918191785734373180034325056116228297434612071579678311181451277680\ 9224041272858197631468707106551546571123506671716347284037622535259480450665162812438211791619\ 2150258325527891935775057365967851844093873152544238842410798463392421184427839074194792266793\ 2226825996564397301434326603748264893410431722273227528111093004655271434328977872898811536534\ 7217764389900037631496500300628382878747937032838330909459519497454438362169569513172420270655\ 9206797238914941933763409924416555952933675295847146833232147067969518742911277674725601609880\ 9390398063002892741896131511260331859109747526993727506045282097811924429687174035402339050816\ 2544804344016715148653403613468805395040807532248420993257770942503488520173655582076591891443\ 5121152653725349743680623748815708645699463999304011370134160513312123485112492353649302654499\ 7612890696827103722771328060928639487045579282211466893656478578205481542722594091657121396932\ 7049378356429333959561931946641953272377371414761525830685887185937029597240697012120232818867\ 1758883724681907052500930628860728298979378203008125410904224181077885041830594071319645815614\ 6031682381014939402828960514564397791307198726553950669752003929659232167799468007993705248954\ 9714185892768835922972618200409985823837860371563763257612228109699592462672763012833647155855\ 8955535062855764200753636778657710764490361988256784766028221436039350161549368198182824220111\ 8911264250185341096378082239774621430866488055139131291588212431359340561079452319442580884630\ 4599554192760056456598824944402720828370718968121594480154256071372266315800379146754089592434\ 1910367406876998542625016425500257833871425828204679393626543269386378373014554642190098753863\ 7836738775609557759386851120128069592088305122912592127317003399235356532333893160684189854691\ 4098497914840772579470255774195446422811578820333248615172218236368519497639793401191509389471\ 6154564722061021818005291644075735465002169519283838582167900561146063129789599478058340486989\ 6784634181203623305507853270846636705699473754343800938562548364066562655624800923139825749721\ 0642605681207142837485247552784341132204885163602851795378279144642827782122419956960677402424\ 7461794546945854442638904254514983746647162524055123208550644675414585628554781886648434426333\ 5322234218490336455779061674807302978461187717669068300837180532449554762469821006507293218786\ 8496930232458229777835876317760920848744116822701626924028902966932871375313021049050322719028\ 1948109720714013196123814320299452547726239445593644680068878389226191151686733872864730889378\ 4885288783569999468905217048333512841491502750559497289262403316881791363347472319309512810114\ 2093469877926648540758163658938015089655939639561588974097703488097084071848787154234063341912\ 7588219327339345711887881210452971974827893611286325834499386985288536812814760972087774427114\ 7943065571622254745479302992775644034229192910742034570611986881991876467013714681755671430348\ 6490121511239694802857839344452478697504228614230277970081546455191356615931245304590318038061\ 5660900624981130447686515569127707131417578091421050243665974185359374536526980175378503648313\ 9575215892817258724667746631244047665539227583647224340996208013398045162234930335326339569299\ 1214512819349639457343947688583691579230902594008090106813298662135283214348224627373504992445\ 4402440868194535860344948022927184761819334781037154311983125670428314428369230756858156775383\ 5315432634983391949937824571840443558812764627236660971876930432093812283901218737426238598734\ 0545293889516285440803645139179086062465434790384181456286998946868940229666041882845478660898\ 2153389125476307866267265748025353629197711404832564433645357725936085295771852346963408290907\ 1155413444342533646938979353737591133669435743206572274000602829274044657809319833962933212341\ 4477381088424882341509682042996760485908636187405399974933323949010088171961720877161901054710\ 7264628330286654845418065955296929664094695210734058370008442363159767889930429339996934060145\ 5444840964541100486585350166773239034310538515503401602632570608578687835814662291905384717439\ 6142536326044441660075537323482814308039974991968068182583144298358666904197613368688313953171\ 8436673834231208467961662431053769439774266200583590115608497736975415528337711031927813098483\ 8315711640682192068607281780690613177046049842483058034466332416390213959323064880179056016470\ 2359032851646726068523851641633863391451786271874422352508827678210235395442876037040798872392\ 7044584490669568937991023921231345557001608315082550561469383287279369758638567622719934472787\ 6518987455806401854017690904553314277439696268564209581631824170715332006820503780127750523195\ 8912242520413594227025078074127768310212330001875797629724073771326221694729536085461466083690\ 0268422712408903516059343425930736903907738944619726799480914787266011370616421569680104630936\ 3220488299434661103273417435316927707924168194870836077862985874185737972019652801284711029652\ 3977308035021922844040691178029383223776248142639085019355923942417734209250298635751874377316\ 2911944120821413453289427769262367497749357866017820515178793526860433323288093455157491127972\ 3376187964946336299009513631959179898274640049075954327095230191384870732306346920672704080670\ 2965171961624580204955939068799186198924507453750727780444894050561570514738627795893952382432\ 6435915104860444024082369578642894581026335344789720736155352684537042994491680227826841607007\ 8979620172604889474257535032059436540035369212662597530865070490292789964089276579034958383729\ 9543764539102045944461976549099713504739938375507369331005311543818292235250634144650738001915\ 0082342022954210769900406093732014037566746075900581014672943213610905756237586463525027301810\ 5623078610012157736390236654447129803767073576805097182276633963055814506651782397956944175415\ 6531668721615523839339495838101278758688679932242268253646426654768453281521083253559722020626\ 5304220098763753534757607356246062474417510199014308932500439879945533974340378113038725154775\ 0507135647036818699260293611864166862993239468537638227941123794740233117100305872049290276410\ 4610749079246780277540154282918812302945881369987763224216091113355595594503076947861047412695\ 3803850196012780024444464577632814165814326434170611007550364188742303925069842993946050959421\ 5557539104495141057166310108119959053767960266492650355452648431666941175658243420732405001539\ 6961379508066776142155127835896739628057251540707540859283917054291330075276192591261344601705\ 2596512995828698910544609888058385931072706042618872140059475746034513370359761098929544213621\ 9428566452693645937638565828924149586175715284688378195488711504215356114122749079239806961218\ 0809353213601039090295927805482007563239961372557592447361702718142263026522312622413035346766\ 8421665403189553471850330246834780444914446746896981904122458302266214489634272291208410176867\ 0255991335920973591026689753096213892161165449860151259002104863639405168173410382732709343256\ 3792155547930259938818249878841188398444472356685565307527861238133252979488348299106117547861\ 4074812763256649604626837271317574934159792583890974148576692621944849113626063633981523284395\ 6339656673758371343401914235828004118692410997216710718037041947820939111646667033897715696167\ 9098416329335279994296901851642391529962202799527948986402277668551580354796353173881662092589\ 7184852964890170104491806227449588697009470425154672966393432496442991083972159386082111030779\ 2676383915169674503995769655065158050360993945366192452790625711288076506842362816515650374530\ 5025033920464939177087081388984556674214992560293393592187053135629848463351541953972208682625\ 6427703994729588052822093114814500964417962817818104067866433691771255581265757118188616726146\ 7245245810920946322692973475883983816041414185992764390686729783352074522630755620639345773372\ 7925901658271406721309950286627435244994284577122865429702381657641582551663139058811827569502\ 8322734780398036027580068620392628135827498584177211224727797086374006533698523229164978787950\ 1558767115558980130568752254552023089236350063300886541886524046112437569158816528812553963166\ 8422746657241456267252590009842987321180885196614288544342472084803557738669452478801300055384\ 1688647543528673059333624482499733752559744235831172836033010662691731232383770096818815349065\ 5934169822839799923316659022540402753906587247801882769557347203331333860763751700558976779773\ 5555365770509582095853619431139570876946883549398661249690703721831817632977166487609859648413\ 9681240095918387574120812982784326604115193263717311821615181034647009194284362092147538293658\ 5055090751463732120805462758737087578909864676148584005146445320844092195030924372055083687910\ 7774283895590229118867724562127638201008425985328248946864749162904274593552079708024373516227\ 6058875067455463574701580690907288875459090749910752258864695671350110944136154205945350815178\ 1843875084434772283258181242728485431251291011281638050779293172697315454690152671475714612998\ 2105443733801545852817689597980542251528369829385584929004802254404445795438349852931834892334\ 0914946330055747112912716055617999926957484770316432883884459871162295102532591619305664755022\ 5666780827540670983245209717513145146323840267033466145374479659384299357050179334991848451116\ 1449137759653490069752959351502350517874034196545206969502043228396825878949323075082795589283\ 5401819020858949003788562616695029164895463565815890256810419644992663865897239206423963266151\ 2052435108908890394451764306696783170211905377494518483339752679529171447917598349433086632103\ 5289533230166677004114496966223105979162647767417389692411543948266577938844472918163949212632\ 9861445745086882238196323543694169890337698309387522968317943607616176891239058191872641087613\ 1967668804940538630442784442520314032824196315670561302966397124745193913920471618900882302073\ 3132472762920265550182734184585515834617473662155960135360913107262018126214618300473780208571\ 7013169037554364751194395472916490793276353828967884335630011456531818185349915254903061880381\ 3112871068224603083398685336340755296286280342364655136862243496028038987616467925423222873251\ 3801812113198473904060746758901745464443656322070075833920047169082468604706388671622506166643\ 8868035953327101083994706793199418374165041637284121171679474540665750232399167289586684668845\ 9718116074911002504285375145832285757733983477780830612680951477475592966410345214418141182460\ 8888287309288098026737666620113008005534710397703131733038433977715267347048347387825053655383\ 9408343057040312178406024633228085983662449070901349730077026611354633200812030901177130000376\ 7832902342035677593431867549470228589055776050404760995917270562705171065431489648305398508176\ 1714968049763626668592892112745943483386748982438966245225300833817612644017442481607257295785\ 7484560642871140207496278419571975387910841558760855439769513164761194059113706186276716374566\ 7566025794612283721539389271999968917749186752929367925836930373952732988282681674590926508352\ 0973929198685966875430159638417258945397740769789804722803332163412149170235409365316932175401\ 5178946183664380347997226263940823575163337365601303521736614564884349736321434465031864572039\ 5683481314534015726561439019062783255326889168086990307301944602442479999160507928964842061736\ 6960847536148808810302860088323252516084826659945918764601781216199100066447004806079492957521\ 5094159918402662918456180113383044264685793892873106508987126883641486879950714851665550932369\ 7636994088460965561884946154371394293619429430024475045413284811847576546559118506845081239290\ 5634957003817498244829313393931880523607075986789809617717711946559656156898657874107238914923\ 8890986906690570400215583833590047328382598454665566390387969991874064130034609353294956303243\ 5957896577993503713851071915149839368753545717682911263021000234482247684679346201397353252425\ 7044935096949774702110581885960769642059344360853031653148983937787608271769229141649677176120\ 6587346161858832669344248782769167505831176804623833042229650429226172769728025508884733910630\ 8662017647686789651533504315878139692243510121890758242868453231399502708624847852379272766358\ 2391597874008603153471479470046794594964223453765721949343313032134707771392920454435693715401\ 9171663337736546360887793758507412744305463474933964513314500112590537503925724610662978852323\ 0672423865646806971973420687817844957913801146252193592540022999683239395368327092062157505444\ 7034055887826741484082963294340908698624262162566011703429246279613410637049989846057779072485\ 8823095383001437367259388681212568720267919937157307105815155769658012496069896276300213469278\ 7094214055946575559445891646582179779939852306307717818820266987891711487708859319330881503081\ 2398846908129385912641886238975889274085449529524988863643278476733193747118875162483136164718\ 4928246281506763232098932693223183502638832642280213067057075029804183544745141789623594132541\ 5687981788507003443433098256832165031986633313725581719861054693624440497294885055883335971888\ 1619472303218915867380389959294128418712953039487089437124208863244374011384685967334983510274\ 1128715184703182151833798355521178478689573939573456604148721282761562017155071588852585429965\ 8649808179522709386035199937243206642129831550789016204498307174195152293800690191624535819183\ 3544003738560766522258392079973157900157179233221768081979429881157584935456362879596535206148\ 8964922019646762199900877441977651903980991724889617785807390094625595081832196166857302184091\ 6540910674678357072980725391941644884298983085440528956868907720116981230109779422000629707069\ 1892994332797781756216057182118914725085884165911814752933337649935682568897377668133323855685\ 1293709251956415435945259496221678425923120266945228237729151547989577710238915982900891965087\ 7949858179273109205140030842791692991458778482295696449233150976441694203482721818372339768671\ 1974206638123762702465257250171533180889409392623418987138014596048513784148001200343108827500\ 7353140484345229418847312856843639486603970724013938823131165585733318690967570292878508127287\ 2998432188211223815728696455986502529685196314686253874764181508245979652011345018847368628760\ 4368470468314349565349309872467539129236658598169460540978056316156065746171569620640059948454\ 0372904641397904399919586458890762132620408559685884224196438205446616128011262487002718025101\ 7816385838847508221804439509190603355499756452400555253890693777695323506939920630008404079313\ 3777709540105860593160319288362404420620384088414842841262694638317540647692630764658418699716\ 2567941815327662709833760591972011576438541437491745942467986782753914470169279890911085216610\ 4008595228278972035319108170674299697121960644014355887495620337859249243056622342840594998744\ 3385901818470749617229330108520960612400995905485274710873593172149895986395062552992392210010\ 5188543180932144325509697171807196904958558855619250222478896321903234525194141537909607481605\ 6691477760717964682706953863520543417689598797932873288451655275574584960650709220992608982189\ 1464966264612495310257010833250502431978965966667887268673369945845265026234202626689191629245\ 4284800982747655185213503904601026913875804760331839132196938205807283503449148347275379755191\ 5720337357449749338534677816914836736526265597031079036280021877115873505080621978941103084275\ 9804852459076095087234787473501698364986999788602454688164208602468521421203533030488372130930\ 8138549394789743449289887807109341375400510632678197238341433447878918476786842391879132695679\ 2052446026048865690919311565688123740818071114524027669407126172585671772293211786321917119633\ 3355110663993440995079023532080994367569302081090295206727727359522277060110342606055736125350\ 0715873141621214431441487993615891958755422125917589175061121720401759323058797249454021019776\ 7914658461353741014479993861747298512732119399665055876811904154813518785705998869001247359359\ 6289381607248906904367111260684294832291843381396503012910337420649256041423935016687445261041\ 4142438992425368395296917040299088980236620298871802112765096990859961355153626653689160501742\ 9936219642747070849819125825910637308929632870335998117027218222529829735854035189231354277165\ 4517783755471461874684583709553445320974091828149585471786866999371800746297553015047135902157\ 6321326680596465729224585315655002108087020011019585364938426499237803376283758407627516588118\ 1249244158627089147684259422950314627262553342267882015068723017953508269061204234294203652615\ 6797045716697773169684454921974894153619786271267403600257108833245873475529243565034569398757\ 4658783177361488287488431556803151158515173338199046385076967723184071485754628171865109801036\ 2480047953788666103871337173346885955944290326894683382597519381408656323480527738687708104024\ 8686379747130896419302978179151561154265546035415710387694943736138474903413598422026845400838\ 6806713455926291918485092681775850323000549357322693175937497833546461471280370226410924815078\ 0266283743939709168731232554080263130868715979634389245459515922378339706145896274864115592652\ 3515939964026221024676393152574119015613633794949672310098368725021591290164701685655688376132\ 3506978017018347948635485923216443537457251707970515624010240967532946829304202384244189150629\ 9014735104392814493038231056909717543286807185682099088790153141456352983957441175263306717151\ 6778953263970994574303499139176408507356292956978143495081021876164201079854322927733821514505\ 1612157735578997774457015948819923322155082139457927026980455160125680441176769101017779127816\ 6206659794574699528611234446461761482185585663810084701506931918123241341228159595772681391436\ 2260615806628405689045001087785070978935111153726166600456125984770451345902814361389076011290\ 1396849770474876192348076077497558750124656182226080214952262792680208400943631678932234967129\ 3898891899858805185579101029522943811581052852205964577131080428374857463576547014418032060660\ 6010326494573773239438417316939748961407267382186886304918323606582225145815959783220619262032\ 0720467681260453907526759015503988440708210649631592736579384024363626193034730601075746208039\ 6222693369487731174325895446324921033562546917590155452347056502731885213613210053575425030140\ 8554208532959873325963612518457460629343720712699077526949350463470401372610169865034286826450\ 3276183587852643906495504916212231944451696890960791966560143309910668885019517307092969076373\ 3637808282606252103611400518508397960289361012052661194058383162124793168379022643080339509895\ 2488371755460120730870976211047195588412379289187011829679594175333607117895850252505761914005\ 9992655939216863133966266324047618962208896853165199886549012640628444213469010351659650702824\ 5786242576816246007732228768268396453281574949799490494075574542698018395414705785983369337774\ 6127312940846545894168902445746044239583122739411208704094623318928648612591207677129315685365\ 6261063446995287858277037959147807485419138611567534230006139604912592594799359766957856587891\ 0806785585381248609049696833099521449892958226926697788497243181712402377029068778921298131346\ 0031186844880702099033543204665506742731797720069411743752478227236053462375088419414238223725\ 2016892944825415641626543852583548428048652779684233481237131872957185483380094446410961699343\ 2386657801524894004616059840418084930022140055231008928863351061087218498410157397969537154165\ 0319005297314430860829504469450756948552591613504020021152846028773229526813580724885722042272\ 0629516655288658997947624359524855836267854912531488255891169701834790204208534914186402642979\ 9812444640013376481762743916034769558707461580032378629039407912094561991015027605608853464278\ 5625529166344194489003366297373952980674132133249580272705620459963518593838621101062024140113\ 9193257038387264151452116773217346657029147497136438283266058762777474225953308144404033492479\ 9900105552648682878285762522494890914731996538633096669190155596656540816997698669314333654212\ 9835647589452315876696949391592496510251411389823883897655631715320460879572170154591018321594\ 2943232975070431935398327334977790172402339758862390215862677346074776623964232022698696904916\ 0707811962990575652641291908619231997566090157623308136062762224961034598209905823981600113406\ 6528240977742294383650016278906104332699491075993943364195375123548023173821909762248141850499\ 2523720561951859350918008667309976127156819876970513628184192122206124031614633481128391803131\ 1119985284069147666099939770570645896714507678909559529687080061265245819034881989302455181898\ 9790049547063487666631635320251736305547328013705094265242400810868365361817109942967243418251\ 7229614853060707808946664000688688165177429530676656735021429050013680449288463559480955435315\ 2292812285181825919776423426093603705739467644146763024384277073345348630778831533038673580119\ 0944619426374530092707232052372202520535018121835822701533018444420712925879756872859318359385\ 9137988159662907374208666142120175073420530412806980500964507641722397764085916191285096226862\ 5741963725234258142935626018042704557440087460041952289753247178798746725251768861378424996612\ 7379931072940615027123093058860468888185450112713752988897200169914054144462161973591853120119\ 5747513377342658304376671398699357986540152310792924544028478048191331500397637583474832870857\ 6298007743652788050413325098948599623300025689651718811650556903746816446987631130928049261360\ 2999591426400807547884058319532839342082320566342065777107180175184525618170966026415356992089\ 2180170082949036743822961794981231987331029555884713917353224719201484984193808903084065008139\ 8655730352430873854746537061068969492448285088160613393674994871112191276220598889091601739675\ 0857341079832336137965902906518361390821553868642863452954497284052905107709197358204869662890\ 1823444233445795816905544542434126569145204879502551128812575594127559427016977187005884864555\ 0093332735871839423837619815056010265831073958359975166488060049836321006586460396314089623611\ 1555936657359517442273679978132344160730786423022346062527389999814907903064046910197586849672\ 0242868316077873303217008809341743717418178725426910667278200307703132407774466031992290780282\ 8063960636795506758216954079940205758283254967584199919704329906696446060885559806694827627181\ 8658954466096049668276676829288322319788142388259782234343480281911257055954402207939371646684\ 7272311677690914709140013820267760065145342288684893340514266715640600006517096821460426160856\ 0538235371161194957041523912460053536459000279521532299576135689513354019117403750926408920080\ 2565723440275595453085769247190476288615666533595245634320232010934535669650737173168971983848\ 7042327289250774452314683069680450060183244434158550303083141436630938051526159201942780348295\ 8313473680898907237113909947544184927908750269197351871109785916803632490720424234111098415467\ 1859630579822167648746921688751906325112590294539034154843606294622817163764843380811497255477\ 3057014616781259698607234270030908218880033385981218395446160407894421310346929754765533700270\ 4394224604332741797346797025729392900357983935940867677451403890554921808526267954917727298535\ 1506297590006343959971942989707884950352950776938045616407845069360801376515819343777930989937\ 3896244830811450766031430663591576899431506487830036136919466903670144127063959200672507286241\ 3303496393739377458395643055231758937451150604781038200235745869193002177888355589703163964351\ 2336334617503053260301138976095333712109710086125692872484803858961944914097530363151894532221\ 1095010903368400052733821404701468606723932945601206658601972591230647407904043571135744285347\ 1790374852076158841295025408822574042261979385370960750201130766436426882670788259268337548955\ 2917703341248805716112092132893935678259282245269649325600084827131059903246193049856664141619\ 2577147964047555156619731457144180294434616104674784644680953836597302286307840162766210377967\ 5135181593854732387701115789186177606671269897360823742366252477250514018452599411424575746280\ 9304701309846462876404092017874137424423798799996548680545202398541093889700734851716227344769\ 3316626317628940898524366867773480394686033137734375261638122757570892696581041144589836992846\ 6971202326552334589420112348623784988872714222904621909891417178865041830515834617383098608797\ 1324387993863243665685035814181875921627281813846867858402105553283344603464813315314430979976\ 9430099267071110652601925909759362862258829768862108997592426671026266868541541353029530517467\ 1629683534131643392923298094503503885583730984651069805417287635999227031149995115451664791480\ 7923467726573270146949069599944195681068810372969802071080231189607917718617578366113788389990\ 2246376638086401689599636891010207614739230811365170758155884003942832081176558592774155894260\ 0546102892471523828857822132206226654770559753248241089868987930793469883744269150702905349009\ 9010682836939222945065813798114540732018878435571896080457763198265499083229561230179043576687\ 4957379530875636913211887562302974043695121796086542477341192205644959315444055299158196866472\ 5461961689280570595796563106785769533669921222044213191346682068389011392664646922352682946363\ 1814845260382153202886447233889906322816334478176172270917005268507109818900854865716760916584\ 4114060365773638448372920206739334571870894048258633777795998112567851271057225368704528299298\ 5940377329493150909018023678145501372294263766802080427074275742143416916709157535290973121390\ 5688063141261333339704683540438899089222538901055184990196228178362911945379857461650978759933\ 3620052582032832384502421402209704275202774513821055384742820375601729429401925570080523038451\ 8744704638787413014359421557646438036047567066598716083573775398125889871562674530744772276482\ 0279342309783130622671431356722546741743892570642575197982873413133069884856761430024449869267\ 7364797340727439093687547888005761230071834405551378192610497164832382263647088880766127311145\ 8709104206910311997735961437779229778654494137030703367848584538508012651146727136393273025408\ 3579087453411685667094983013499693311250743179521345001013996879643705119101001111111103326499\ 7382122597464259836174635799533909590997197846566535141464910439874960053498690193915997993029\ 7405964432752490962311594627708580680239261227439222290280276384810090299027508711111987106626\ 1484419477044366084059159169855802918024948005535493421981768679282654633332936657595399559252\ 7283756327836370486694928382310969226023799145416217891526924108945045235520384723342588384857\ 9741378031216989541044250252253955128117299343713930388588775778041198731595291830419875260420\ 7574536768899372783614982173615177807280182366322214470780656735286257891187727197908917034831\ 3703593556581625152273580886509366170057400684264606097744412922694633551663224157560596320501\ 8945090444671510600980629013993264734681077487379351151215271341443251893294612151870477377262\ 8248739335519586607496223224389330886838621808514962978975890531914049434990534269887037940684\ 6145090380102099604081906456398758012065587518502379230224065136795428031985005350008682767618\ 8328822957331990594846787859439347052847519720661078377057675924510149843954336122629068906811\ 4687862008045243431651326548209987144209423867816500599664363779619367951467895624442310782696\ 0846646842926942613121499577429324195976828235085634903816918525051898151147919529787726621027\ 3207090351728027491225621224496143144888264847930917007111073368719180733636597450201840521265\ 0729108668590775799728837504625566165165217384856394557185532757894929874731407639225690835393\ 1535602818577962472665923251858615565435198432276877799735910440455702757552976646530621423693\ 0481040686249309448332824347610116373443717547844326293586212594362110692039098693113413689817\ 2655352340037062887591524142725475271742487264600273385827440204062351214857773345136664205246\ 1745038296368391797942915978855895298287900578792026850529990818391757743202126494366105523296\ 9247128342241809359341956127747030206699125226571582610135118125909839864810599605303574722752\ 8407529760773118469512868662035415823008478595049823552706369478027630133825992534721087598544\ 1314866349934108792402195104372618955391426277174624317792268432046772513383844359853918418149\ 9466752309008566419800106961163563916745412757990621466706502950177826044299284945534774848585\ 3576482620508662535630557051457712554825016445972547054656483171737711783903076899417040759642\ 1576902237942735882380235235478808109980556573480692087788852334798088456737763100998880822839\ 5396599232275599452328269290687427113322403041706772395939028497266980547746836975187963382610\ 1531759530364663768498557805155071371842903318810150249454283721522879471176645307674276724738\ 7197033437912044933979751862420837735444997835723174979834897016329090656540067546494636340028\ 8109209070748021017595572687290279808520163047549485982711813180020281111836859170112470043812\ 8477192045114155543212787601741675230727669102470222436372436943621748391836024469131269391858\ 2817435954255298160333712431444509149043145364731366646908889380162872838506025120708497918706\ 2781473969812352721466077565864985795409874590344524129721060987759913338838684947174676887246\ 6273121100288932956155557717085375277660837946110861074017386729064781069173570868977434479252\ 6510317296640961515161553398280302001716735067720720037808413130816893601565222081711354449105\ 3973393603227679713910139601578727850585442861846156283044668260272411671810879267817925467111\ 1788171841125738326922621630044463965054157205170492794780048252677346440960888514193219964141\ 5779390750372084081149942491475780059241090108238211700755144402597467326212509289803328353888\ 3027550624456203085520611124481322337943389990299645351391611578771473980866332811987590609275\ 6508080773949750733230448816262214599498765751459100522916882044257576087747184378929427331553\ 2688782397105963505274453006903858641666171471502325409364352411705204588749623355855832528896\ 3233354027893098486260958364119943801493510029034189325709818088253155627802660033962701986758\ 2558716226235997448777595254923650997107049773359750068550185244851433993405178038380717984545\ 8267049693297380927841361173033277302679153312439627094663573315371776108118793513995175744449\ 9822053275550253664030873456867907723730447271917249698398003227690073705988170563694035940128\ 8250256252090002070263313946537904469913221999861378394541599745174007615700989635604479689471\ 1409012131030990668380818622406845051739258632127426753587025315234141306162264312913511312132\ 2607307051138446113169710639891111353416717486767325019708167466830590156435287098832265237236\ 3566531046316945246277869103348971675294910414431390603391714409246795122760157223136463972669\ 8431099132652121730284294235320935892932056672112961050816055947084848346790624151972762356424\ 5121046482641472522163353424203616636177466764683145551463531746387954979442576662911235658301\ 4467044804467383038176788683126916111488327440921104267080609997925133080197079369379981881049\ 5206240352589350026666547916655425860861502317362677802389796975198935557504360970487079997884\ 9173962101399495258615078826415874030995445736180434197348163709517340119944333827748281007393\ 3332874591978738078896710938515676710103785355640701830081468256796153215899329722816630829593\ 5305095806748185759319352464052725322880027765787672595865005774823130047348205497747783636893\ 0827152133464724025259914564016505469403967577289938505103041942140124505322311798494194241174\ 0363638630211489542079304194140355272272054329455822782012540230330247977269899697112458534872\ 5567967401865377021369760891785290737098916195604247944544272603712580213095404070912094744294\ 2769353476441266318494853920514211288008020008434279536180625617350217039092127916231135272198\ 8458539134580217586279386647388215464086539253559817977876463187329999048412443790061410002136\ 0814317064736463882968538795218960060140459989107586192835238726187459462721003724184664046804\ 4496983598817222947334923619077470552792053017743080475054216430273718391382577853784936364272\ 8035822721079675296114179141761743639348940755345455983641551044116009469592861736214783030132\ 4928490606879770252313837781296926418638999596462971060613800417003343499882231297846177134262\ 1386659325380963500838961521451440658167412197208827922131356304305200925599554186848754404590\ 3118242860135226608636773105774294357495779435378497492230637420678020176930421524500632999759\ 6014341915666690634809887882004446344218844006588720371541425578528625333634505551035753930866\ 9003519437901899732270532201946519114434999333425575708631301118393870181548220553823714574530\ 6260001512644848379978802159959752437467475811108467849397139508106934990651870677694111578327\ 3008296510449782065996660947411634962462348185633941868124660941799792141200537511271559328057\ 3666827691389714774035555357878425648703788605441876644078562000623893438282542902325350869993\ 2134484794547439451983248884046571696245775194661646888515041757331149177745133036956961337073\ 8514812849396570696366609667310102240825861464648700606581131036347414318292919438300600591997\ 8282565044305307768393939937841346124525281067811879466950015235499071391989656187070212634860\ 5659620534864486509023304938068060063945886069184859592917771626985850595814184719345760594755\ 6762197305841047329304235456872401848821638766076920923208751421225263264422889098023362334349\ 8901880590884062590030967752109211008387568983691516225788316901460599976152786666819721478992\ 3897649641964094512313470453226081065786125747718705046378585187607245948891354394911542248327\ 6230606791172790917177461082403860576619733803548008786851143176709644736741112942301120197302\ 0498635037884701287650153389792654364912249590703065684631694935871474676697226189948694525072\ 9072035146395390417387795224938280613997277840310899138432450536974175812547749774482462744417\ 4069555856564790963121426448820142129299688059354132193611653465850324083259399375694594360056\ 3567577435150098352339803258727972795445136017923299644645545269882912601878395430633576813704\ 9876158139398133849810260814136923116902245795048278224577524996597484369038614551275801110414\ 0608608668362980192458161119385976384347064119651618863261805636888481839987202809874027284828\ 4609186103441229886206565861563821779604009296349785775848719569555437210976353831299936069878\ 2952336728331502712321447795397806558356189245639843983889210095042305650759839990562781498162\ 7610213137786743575591227629508148423238344390735716663588603998510363136065677938765889068166\ 0682581147806994831941087593837374406121988777422021943662595530319067407369674495423292419438\ 6665542007462329359509552825041536100408897817981564710651273311435667251380021815947955572375\ 4903013948483698294298989475840714307141807525207122422919375764543170888817587849282686829348\ 2110614244053374644571189498437925341230021984071696790316161429455673846553874776483539932701\ 2465540112136034511383383865201891422174022966786315552733581682104783381993085556541960271355\ 9319242474855984726178658540431497632252158917714375327353366830958663708607291174453953580208\ 3742005149006385409932555016981069922450436353075526436583871381093601553129218182618396748349\ 7134464916972220204287796074268182258168249048227696423278404159208727690743319973460932089208\ 9089485469526151410288651472812730674798236664225885628616310388026511379744230603327764603779\ 4997192289225189249307330035794887846201604414809785766543856502664015539827842562629863749690\ 9247065010263981075426004891073456902903341139529647279665001590382287966372317311024410611580\ 7390610829541062441461463636470601212585565806354636700833982575037573512229259327331256734849\ 3172726327083199504469594883559981248662713845657629885747766899734386185580155119202778510701\ 9723314440757359159408174075422717648748538948092326110406931150911796306054561936424268637522\ 9219054149711372127081564570315126229844938640929982262529905530700331200261034741133653522448\ 3904502757214893665051325310799123654674245793835356838592149569231224178673246235411354224735\ 6385465223902133906961919998116518832096211563478070753859021192672308526207868811159642870243\ 2973145780447738936029806496094417868052897558635607673465004943906121014193002496858122678838\ 2481097173609126948538954585260528853995492794522115348450667919486866013935048038221445358934\ 0392588268893204763391290021343522459237369728263744273191700847661417349764702460716326677687\ 3813860413322111867693167667491113587743603002578564405104017963887940354664610910746457673576\ 4906178913357012684841199976751756289676984939333583532218870314376784582677338718831066544609\ 3203503557484170221210738228143720530554084231909982408345989292382767698598353100829230179874\ 5781874935732324454409854949780867048300521439254823356421683512689074470149104135157151814418\ 0004280912692269257631209465540100470634325820361226242619882903228427429079156151107580477797\ 5501369019578623174853229955346285191626978100380736991847868123476360819142824341748144633302\ 7248263544757564508456468106057315393975114963210908869512239750045882419814577184923137556324\ 8978186739561283821455713168222560014829573413992650105062315529395500137363395162923517406877\ 4231892665047917292515447096084448398386607305647682832708118910062737114911917758509348028443\ 4946442417018771147959024346434327220964778311290574684133540138222341101700509806050130154029\ 5771436878575216705551055141776206820517141648244528209142451611909516106410933492230975708432\ 6799874588970426283329299943259084507145973951047837938609665920201925915875289188406125086657\ 5570520192498993880859802721607315334496764183056968789951329782555873265657170848781334098712\ 6560201946169206543387889110775511560775834909101974649114343264002174152347290926845413847692\ 2342560259203335840935631141484531625827161843075480799725109329203084522305366063922135264849\ 5880683120128311618612228862609759774024768137210353986597024273154339422129380614223098200277\ 8284273370164039235707521275973725256293794279934823014194023550027651760106530453251954938442\ 7873937945005356254221406241590045556655030560929775482181518300154544873880399550309739990691\ 6084938770172902280119668992618205269699498246183309686275580567150495289227458686032930406345\ 7769202392327149862526413209018119257017650213866222156004822531008211032164379155415813520303\ 6143798171411134152925641185544235159836194808221616812207495547093037771773854180423943393302\ 5707224829538350321944482834389897755174110504964238026161987667180945357029407707553370496249\ 9251097113869106585472441851169315981415963112340551786077818430560948222877167002573323325425\ 3613982410258560466347854192699947040003467108514643264310617351818204416131426752776811412234\ 7843313489152027397115772320801997270511732125736725235907402910906240641109954468961939481186\ 6079766461963998647714005966410063585855862065879391286018316747906280035923040569735775909775\ 2306221036304152826842473184833774382556489428072194968768495646983352494166035068112565371760\ 4533229742880876494245894708455179894975608778738517774694089465728985235010487824488668972284\ 5676718884227735554503421832030192857358110707536916732306523833417561848622412730103886616594\ 1659283465757505392849871965930782807510030340210129204678695529202609989694086047261987875565\ 3140042468479580831413088233728641773965712674956223822566502213934457715209578988309807615701\ 5380682571656132126078576801505064418516415157934115135646465912219720830425210879259176900670\ 7689893534221653749337020214026016331738738602945552965375278242127598357663747978932086373135\ 0280107418133108520621024275733620598169499977088476617839799500272578131972397495585134628592\ 0803312883521734235764836129814977798084977355690476324633307958172410645314922411818736196169\ 1661785379154553232941988770265865107544291691707742911643980399313907422300857784239096610152\ 9313351637658242504388771606247622163207409043719330906846626127938302882472529174233140403614\ 2066415058461731391832472195601675387054028609134329318062376551385771963857971811169527515473\ 6000297950162219094161674802104699819053305987764263322080571046463087732415300038869478605929\ 7222938743681559731632597757593878634915467793782684230615335908401302769360522256916439898189\ 7105158698630667964579131567011067979550721726977123299639184143243412358531556353986590370209\ 6746275631126157915096420977506862083131498682787656834649683777575300920796085867839618822939\ 7857152698383791315006580474593665721489376072377991983564912770029880642677815101130916838454\ 3946550791978016265895345302181412000098820247403766029330388604149410836003680487688099219147\ 7927126831260257658717926575127084360441084935746588675198906280165171158621413895393926245046\ 2155198331395841384430186710786577123365032861921322855818696307386244481753349904024536609484\ 5889715443589158502098559913956026086277299585189183073845354283470189939832376939982702255190\ 4458640319360723478771002898859143795899944409710186376002456755841694664504715948331655413649\ 6299820868555121973473453246586821860131441704810081055669270798132619975180518716162209955206\ 9338576387522535677425402141148494797270024635758834292282221991346442284131236114067853373758\ 1645271961440677614038162308309682726679385081201529269383492240968177737737052641446978300671\ 0582440219903424897483717353315692272473142856116745843659245635556199120891942675533594878716\ 0345273748526453324200201139167520714667049281732261950948908320848792861695747457806072567763\ 3737532134674428877896151788619708095478565305786928778570123513728769560177805123452951090768\ 3966610838210302958264960321355055453070835449777736582339065224036163424725324373361950792140\ 9910519281114851637637963331334591672120588722232205442430410889247156131366107339861974479381\ 8944448201861445993276133141201667069571588799079025308821537136525446365756382735628166018140\ 2425288454357300070259343425819870840032260127260552089065429291024126848678692105250333213522\ 4618241681822490017530476385715796002829177919954561353723444734400497590050936111297496994937\ 2938312274264429130164405239748649910044809059985458977991395959728410427698948002431002483073\ 6372099667772330766945127363432311627863583336780378766557975273429549389772437630632971052341\ 4469973896550218702405765708311398973205205209225242418862059343475718499816974116059812295674\ 2099422427703678185638819782323646686997032361900297276085484256096924010674508851814395844897\ 5543059089744088971272467529434603018964867165433757741895216422561888530335834228985411686864\ 3876716874894908922249216313324155073393511769176622199200702897016304136487949966265563255391\ 5651860325846622827334862807503664996522844612549990169292183315519148032036445539542588873612\ 5563189897706122140898239675001607820679925237064399991073163409602138415304852262156934379075\ 1088770846418309045576789238545039099835112903478319528129086500459535781430855000867263477312\ 0938825298265666101823172778277035171068874511916222228813412464570868255362816201036176043306\ 2104009188853546712767076017839405713287052429276354070212503348628455319636911014251545220108\ 2361922908764009987736020876491536720054673331244681445713608596834146774074065838647578823760\ 6222304843392077840892328351277458023106592004430195986370986485445391617859090506298566543356\ 2495677901192594233687154649586725124235383191341339242105601601400354846012935308632982182934\ 4570634132005557206394720687075801214770477522539959571026934846740702514591211998761521572912\ 1247824649515679401414341078246121771483277464448005540735205073463713199646514878125921920121\ 0476597856646048267233303061857578933723418289931542888350056307342887602917737804175360085006\ 0684922433160023499157040719519706557839173301739288003268735730946351050966423552230821295486\ 3229582708671390455456845579564416978213388136386298519895701964680849348240516301313321404866\ 1722458494656831960862178658310488937450723234220669587172301833269308766369664941699202899289\ 0206149711859487834022265555470244783166521268179646289363669714119126411004429199651046967284\ 2579064797683446948518492790772900411597378506071807704042325801803524950875728932475689693209\ 1345021063303764074104929159636322518993205151415199784575426491183427524421417641035812856914\ 3348772977623079577120258418092075927597512373896689064797476810675708749300781715843752108911\ 3428463120148172642700952302057583282955465581212317435852709739381199611363223279525941024023\ 8710334472804078337448077908436807916606080357249153763070097233425433521895290906268966918496\ 7474085119270159351274042262846161221338412734346493559405126723039711216974158072280641995985\ 0596472742830870843540075828415917621229953124104128477310592741926901667681989833692163096958\ 8441997204685227778781383482950716826418874016958224678549960201230511455839976214519620818913\ 9968902999379276813188197018338505117808057804124079826063186289250517251944233877118465098063\ 6785951641905574525205738638913206627846714024998611886018137400862944943960074003247107977170\ 4281293596406340172534652246014259821324294069956030398982041298965742377863579923609212960312\ 7463417315702325980724978898255087492354171489872284879731060528348263285249387576517430769844\ 0474333392442066975247291419784143882294173222662293852563177931056500072624297858203706314740\ 7054094953704178329910511473286665510186752350160441506695033274869307865526841053702979000303\ 2252254826067692175703900968715075626191127121429165391129053266509165351790617077668008693501\ 9028260154989788379899993249526964836565095703459062656676094776184759409501722148892133453343\ 6361014541079243547361217778682034759114984028769668720450131198301087014232588886875900333079\ 0514607554537212278895698163202908996073690053602999123496168372153209550126784920039481139077\ 6229811453120127229021702735266932588863553013629165315729054086916194142850423149541724253108\ 4934809277865264581004978938509350923388213360019298389424639045309145946479204519530855864837\ 0308015522782522416742679546098388243514531632743510292622542960993335436886070336522869007397\ 6181424747920456626204491496633359411347820736979397462855768230790101615124863041428111127082\ 5887362886398188657768495248532910432605376827191032112322255083515683984043220033028385602394\ 9664086434687034971323009638390802250346970416854169054474100867376953343680238041933581370218\ 4626774146303580792436300087452367397779005389987928012168626844457379150410905544003959039151\ 0988256402163437570866348445722107673473595291374578751496580757638628058893644181364409068461\ 1106147186377799377731641581244322995543633286675795408635072726141241941253539195330482688987\ 1958979564334646029283032378672506815228774635762970741402489279672110296371603660716150784879\ 1398466733551143557437966665212657533719311881252668813932324992087450152550908632506741257755\ 7073071551134123262213120524905242261723022664441176325313569849570812663914925347971886435843\ 9118513497394910458173592137816662627105736605757970761853187955385762839080702143997617108210\ 3155157036634372893373207793801378756914969115427688583322277745363364154891243736962070052712\ 3680710370061520498164814991465066187348529488916207205763295769594570912377819724898047251913\ 2818291135409281223240211021406403691767235770041793074083469504647956338571745485965025133382\ 6561468442908816216771723454121360510597398022396658243764684087234900327916172108222598871346\ 5653399239937707521663975928876370141377454896734684181041853131425057148045583959501432011003\ 0898830506200303792274367741229493344178850135397447876142765334347919832364107417404970326820\ 9030776191516530812904746271926725303272469704603142689086026124702288918378377583914442639575\ 9776406754215993138553814566943836015386377887577108347004968503664943155611830371995694802191\ 8432003801238727507310923433242177628763156088129605601711415324013878101460910629764030033780\ 0759668343855728305028734530030002177465436213203395255671451490910116657249212250534590915105\ 9532902451670815315524982464895540242020701255519453239318738924400339434157666794019057725244\ 7494208534645982084931519130445193459708839053920947220735206405867171485738644259399710770382\ 0076014782312042283386983685145307057253597249028946028214257154233772623439646777539262381597\ 7897204187276903760688337081299135381529421762587526494680597899846143634141057144957570610991\ 1481998530269593507677942998271916022058165802717228119546264425086846389627679261806590409670\ 1670778273310562580951711863304476007475935362152818882463687815779230179304328487482282790836\ 6251942903465483844840674910859030283782256155840999870802711006583018894179921130809841949602\ 3029473613359641119276795567544293639057952108148171308501186684801365868214273605762744248101\ 7901251981719109315575847078093143162933530741158052597043668019544979161371910026134654602209\ 8386023099714747817581482761918932333342780662467530175940758160631075499756763072664331828032\ 0033682525893687662294577122270606400827111335441662793989589049250617874945220416192006487353\ 9576200260919507418954886924006905832396404833987933223164539237210547126151992841466904488975\ 6425106049628612798707917855456052199704400434716232542430887881948552505028216527247855579965\ 4204191828476845379512103867293785693548908483540551506543030809141984374124168443179480147716\ 1292163971998536056409775559007600488686021840622970492026868993917864058973657984735141102775\ 6210443266490492304408466303336073924498213006080031779988745837203025729611701911149120003142\ 8335377888000161219958824853109474810475558063075313313822392930039843005544805456688025053242\ 2283302627167673912192020398941029112522458601134351661225722986726617721260400259505808020059\ 7415063500107652202423298897121343444647978892858168430306509112595040361610170162254634883967\ 9895176487408592361199110433495032570886993843922145165467966160343514701648203580606986119641\ 8989737479649417263958476327099933119462903016170308529966057713771079579072309844547690861274\ 5241283097769736157932757752752401845265050695705375377403144660679447133392468156700092207604\ 0040714072513640386240507080992308733289443311610109363600063300555882577015785463002963615164\ 0754315884187297044829559540961636736302319580198231151251765034212588025643822722685749366399\ 8311688993353219918579461399098188433377413234115658881552045214368941844702674108989969670728\ 5662133917721933021260089830468554355859090639433363156935554831888141356484474042234448768104\ 7718029317839821635365889433247311360604805430682495626347041865937771706839862634278916977139\ 4130080892729838371867462206201100116975908064885733442568338222308169590623110385626195885718\ 4996611572066420158605281300200205279393354148178502707907096999478412018535080836908158011060\ 1939085663931351610964662810899584700727421262200017309456600600102084163542324732315958247520\ 4165609721879955141306512140717361624004268950858745528635077686436623659830301532621286403862\ 5203496244618107433607524741872151805735439970371128513706664725801886880119221210063514868964\ 1679461047095056507779098477324633245629629379722259776414763892637464686930676274874544137312\ 5455688870333754733115235015133865193453774706725119055048352254220030367730062422275613250088\ 0130954288351601806497319843345451089591582830140337757597657509598531617445204191396293690190\ 8265370133804623785546500857104348291479413027319996041473223526804748345823053690267360759379\ 4978393784888109655227746429857957872304088549806954702047347996071438491896912316699428666939\ 5730417202369047072748300837290071431028831149153974707287035650914095213928325101695807745051\ 2522937940302594311159686719773832320740717317637452728361598941785991619560710129829135962209\ 3253002977296602609038595538701087429558102102567118717359664266320972314193562696942075225216\ 9638306934204741296732934197918213323953150109647045083710200840366360192232699907343038798524\ 0497297300941647073472391003851382887933955965370172334708858808433869796586737356236230477217\ 4743107921737192563511004303790383527039224545058977560810621202762702967232903606169036630330\ 7592981792569703125358963649113338304295788448062516065593637448584801614519604237471689913589\ 6535065239370976825528778914520466991214073067775032826555004656124507815412371280513194532448\ 0568315148911464171195512603649423404031685816674376382841683706642113822994575283152758508150\ 3675890792360190437672689959379685794788394132543537510875445024088528176246321897161745528230\ 0074679312588383591890595019320650301586242049895187306494177343588366693347370500609969724346\ 5332568914762920310829394762184384588074791413719294493291589055406159880159847346871400623102\ 2640740155343437926696445524666974671257181318526311870604837555104845354437145470688033624276\ 2920499465653910171079914390958590538219285633196372708163278516642887153269200428234381273386\ 7611479493896922724218504692878552884333863485799477309436223831038229729172993578311451012998\ 4812017731701445202655054696427028216099411254970230403747742104645335042717712719453140940335\ 4636226511339128119061405669287657820662926616026323816620292429846131604405136328462250318567\ 1244785154253298879506704449868186902131597466753321071728660184842080494200461316117712721515\ 6911978401476421337283486089199833888727480542328141310507084668691902941767103055021689413492\ 7394045349588270440054629056580493671510171517508375335812286158552563654781145741620922214110\ 0888429118805989523670120640445524740067449665873130786144964818741458525982957960199046501628\ 2396623085962432374057809382381893645959147108581823211287433433829830395000717620371837959223\ 8832524897490469590790727279139664801095198622961716725593782225157551159265756790058398296551\ 1221543529614035408355838163384223024087874907518234289480606457461912973803426862398134142950\ 7521306571194186780953218645532528628122175193521492097028282880202418333535850419949891172164\ 3590442958637066974176514867711913275296155222799482747924592658548521613684397104421043716827\ 8142790108603202432922698853036481715313939101618715237793246025753270964514698342516149764627\ 2245495386370599674501175418060972831816250254729934602811768915283706383325681336402193785585\ 7465517190397210685743551244740636129980213440855637796505719853731780105445491564277018433244\ 6086472517377911914463128805045144597965222460413023027555957132998071919687703751903942570642\ 4937307397004102921624372355826382745711755687892974592442775704300963755868704405667411458431\ 7818616907469537953037357130466559560207826577818271917262213411184403945009238658732353684277\ 7259799880529151059865318292115214341938957106879546342415907487857097663883277319027193023541\ 1287579331724001083888360221330342412969858473125073574175302942551421801614148931735290305785\ 7715332494274062275665847638829896439332807364764239128911382784515241166285785010053514623742\ 2228461440228555006469200660097650865975684510885437189079989975942101470595404954190502781164\ 2932269193588592855340855640119042255455664709986354520927936138309739586294192709118873549185\ 1723894365504910376692312074866912126881478936403243404569669932171157514360437226682494669522\ 4336726821744987086092608285918813961790910014316859148570239011512035892453500486796635380578\ 0969011199022075402830158023286682068162623933074595464376387501995311386641271872035975115250\ 9560721676183472050301265677602336902517410182720753495133455218507058241723223145429486287501\ 3526218715856972811711296406124238504941995850255294607820345999064377909522576633351917610462\ 1803885175433769586018907935583857545702550852531523080868739594680654816679323468935032777627\ 8621125229607141723576367713458523071154147214461262026861618899040271804405930996016361461600\ 1153854892695966579064589321335893575614772672125952109600207396481175451276996662561259930276\ 5734961406765469554037980757052176118772627274913077056945432379424146810219409158166921721621\ 9809023135904527428303817031212796968237804171027244032888758526374909165915378832706164873565\ 3082964066865094963021846204242545126698237561069374730029022180785168993084836785873863433155\ 2063316142212751796545361420307064211841211413253568918829280413430590699424134111111601349094\ 0673790346252973905933437419948697578974863667123179572228029040617772024175378772414915156677\ 3213634924065343900240394163510020360228137992071361060171179167348616963327717860078150189231\ 1764358363624913586921323313382559750681136291421312523672153150326813241729650197473743806217\ 3985408310256852707067495417441911707674782942083665819342960567432894196486510791331940536576\ 8294709958199582307791722046225466103050365353993756495711975966472598173596013507240688760865\ 5809521253593990938766306217854709750635664111524650896205558382434657036163450857442320173302\ 2241413554243297989855663499750845467638415444162271077032311963499666040862748825384031499167\ 9695974865555407709733173923758718273509557228434742082463670463185145489958325378459047388251\ 6803082954935992396858802449868438744793809363008067021930009524301003089209031601689321409349\ 7066295433668535213851888848401913158064277609640254120564286954347785540366510839068676529300\ 8036723481963838251818427553879718614950856876746101966658178856172752769701564936910233259947\ 6863227293367530536718290308779639813709669090560501406604117341616157583354185023191442018030\ 7331508743807588355511209777054824425503251905654037801200564609253336932096794785165996603450\ 6123609758016461789732986077971347804512394029490962840613478846356493092530303534398959162822\ 4941136235283299943719292812062265703311549950879811038775837474122983315642609470418864319936\ 5636508230823987427556829190723969871217508667709700779419689771360041662154416891438512375097\ 3545031918919859331288191940329120636853994939647744791328790366869663675001652448418958997579\ 9776553218331615302153935933256178938454611498104640395266720205559064618741715301874512571246\ 9554715075350490259782353694546412487077693429138110057660144294939211358248493334050355363212\ 3165630667044533085785511735508524938114837007247809901143514397720201251683919112050332815133\ 3952376423572933210130625424041057156558000566704494773197080176536038095240215334388660198552\ 9829258092207831272326045939677710748859759656997645169078678775326370962893655458652600699995\ 0222307443436584598593454472363055330538573820486435807888336324904632226916057860967018644565\ 5871215898366606718745477302373945751805365657872105197957894885504536024297924759721180268087\ 3120115523986332169463363291158385956601640439720176559165969382716928791412561027153425488122\ 7051867463795674045613638685337460424900472825631789768731241674065380853745025146995962575858\ 5376218934265867781024309494653385660976224051042616938034047522087755460297113777256955122448\ 0545441325496950362648907947773017469210737290124851727316124577547070448017427016748063015031\ 4230826211742452989797918689068382187494122059668966549327995698883012390575458574881053379404\ 2455563207952507806336446897137926674563046359394523695198576310151570132822859532720966152327\ 6781060370123477531781254376095702579145410920997402243235081297880268334669566051768095109216\ 5920646169206852717714060907590747241249895735398462976893803568900065900570403266085883832499\ 9607811900682957924942003103095065290707480206657107401441029235410104046939115146078560373298\ 5251679536822521642500163963479888610567526198806085984165866295257357646492786451239224735058\ 1105721598336932291182793171082099067950579513728767998751759949873007542508902531479903890231\ 4195247737582525578130095189723251833709033091177806631271557691186794357507314004253216662814\ 0779398042465082335155917489748059379152158904847403230510435748156186214084907863206724858543\ 9714722078196825165877503901286471431496402490343074140361506147497435329169505179694990091891\ 4141977986770251322892830180662548370427841706670347694407426460195874484640188011224936406911\ 8848891417138688961834167271266152970645677055814366033784046275907466409774093375484201602649\ 1086457856600114371624893812508767030334186157204202235562178506340028011404267900012800912529\ 6677879994792734225921777998050603854026324037610542157008192184703940004057440609444286962440\ 8568204898232720367379830990203900035276361138378873968762865867662085512175918910567754815117\ 2624825040847096960580936843017490212360028637301755165473328415913859640311768153137351632930\ 5579198544358224238053939019941291705772450778556104937241891244860605437989772845329486101581\ 8086798688091688101314290068769454874524724987944431614954750304679469460564083115979392147262\ 8021362527859557609872157749573309986262914187783825317605634161406007947921732230936196784081\ 5709542367691042101416188145266689936011843600434908540719664000728681401274702261445951271267\ 1264262606666294124146436304437767799354442771041927066344213439255144411983746652160959938303\ 2303101255878859622565426065664093734493012659802659448320387742586049140903548955469764006035\ 8709888991337996483279113546606357111606484207011459463892433838456154291187857536954328541139\ 3470641249241737729424476101746844876828369569577122299385728064835322009919256809521831662533\ 7330365391811628453673119534056303426137633244812557499398914420222951023138645346780619904139\ 2778308786053790801179576294535008931801606721504038191543387819432911851648499102026083614791\ 0232024165793560178195256987386820712661147633082944021341919106260617802092378943723722996658\ 4425964286351258646834425228680195655173085992506703997252432041061374760421290469485765052871\ 5339788086110260751520576300261159731228801454623867926009287670528585428777229546633580791149\ 5199092852364493468497154829703734588256408949457678866511361933262700791232394150662957837638\ 4525165108600145413550130690460765710384038825931039266954854623788079272280378269306562015862\ 2971336711802323831455014851584788486493411382124844518971917740312689852806772795112845578566\ 2914251224996499257116138871206258243121015474703387842607144143806641861090138766886178011053\ 2697115125810969040434314073111750041483178425356605689193720135841797633485181750895279095268\ 2248006118596134296250184726726560366837053566624154327557460904071303831544520306071910817417\ 9596258318279055278419947888220405360246960448667529376973000947503626249557647250968635355175\ 4962880545009706270778304853796264472363381072930045158791144035272268177911481889369808045187\ 9791424824127744822162372121321317920455261491336485074000575828768040278281416027548958901176\ 0146658608569473131967927312407593604298415989809817503537033185683880414459470028270027870576\ 8252046903286349340192937338131545733441609702393663511861163590061775333726540440557656379941\ 9301354261894716692738569636955303830488510713827359324623847702283864431312707346396649172638\ 6059508079601286267382313962310249556112402331785438246227750383556563452915743647197072612287\ 4832954751522305702330435116653118315318198300012502904080844171063925238471842814085521206947\ 0657949630611907200549721513511443712470155466199756195894796686798901513217626237721218208027\ 9380110652438919631006127792300333600758402955289258245281692109670611557394009197583542669894\ 1784997477607970262720238604203875732599491454415131392866025971706289211267684152795942919181\ 8338751326892707198611140009117939150052048552883759062199347198989977697330078081746545610778\ 0222297708628489133470356231812482039671440065226493667543202613454693282362131333738953697597\ 2605500611286462171580798574682643865362974908495473490381453873331355802974629203378867104514\ 9215050238678929921479474251446772732795437532517024755653067103810678512166622492939387847349\ 4458265204887321244479582544818301976947543895989383132939542273254300019041721530901319006308\ 9512041797762194619601164066369290080332891030871685076564153855820288281152774803826045098383\ 9286384445227131075288711123999415394885097952264037843266349932561091175276381277755677146056\ 8185760184343693016987663489151448663487702365785609508926165484038225245935749235392392277170\ 7413698454282491994439072747126101419760717859864472270149233081184148064779075088532415496113\ 9882670999454089276911378420426891739406691634796994655675100845811109619437958523766804958021\ 0758739402654663566621492977430015447631976423702549419343498363977898657378198786816895510086\ 8772100444582477772504119801066173387276432338285356939891437136946282080153647650449467269293\ 7362918673552872888104468755013437816646757540623002821136141675106135977626904069790763946689\ 8526816423328299601545394484236742227938415630837754266473668200899881725295139932914115278725\ 0090781690214011528305930240489658852284233584356845316714763444281221832515073586257406408582\ 5293423592191014118263256541650869690892166364493206651039949548573197153094642022277571857699\ 1882382060268606885571815910718326362938475225335202570640262538612244837561657925769014315451\ 8077268060544369807290191871865791538855642353092875313499505685516239109524488314611151713628\ 8493151669242192315075458677433461947748363966383400179643585485401352953885573962838273611760\ 0512603822740699600247231086134773274068464723698349075633655108306577685170075703798237385868\ 1036571567624959132035551257257294203993552403913353050673000633032529611185905480872953349287\ 8508110196227547343055680705670194427897100651800177322559216028437092317223196322251983642116\ 0468324874591723799460088770085395115055444235454175063860079662461727874361134291899713300341\ 5422173892822008393281621859741984279111706660149997611800068858379915621964218642880868444619\ 8820379547103691626003497845893893258767080285840280564169965065607848450282940719489930642929\ 5691879502674663742169366081359180979292153747447363963861103485908269834600671548939776089043\ 7499252463472173996471096740627051054624145329763053767061448565525142793646468323562382830036\ 1535637752937543805173822231857761871849512015612921565451884430693795515417712828723039796787\ 5442528527686649332353338126474872734132791480259248978454741073563850600834789049718221299930\ 9635598809206013259556356179765471912173068602858334949661143945752516458227407470780161636123\ 1768288456692689376528653444412077532107989864270527915428898693115172927313539699650833436948\ 7270325311718338511471825876463618609638461470933025674183668180220464357730943774497435418848\ 8502773136912112662921227705745031201874234928144821891985589295319785757169855294875989266132\ 4958849944188277938853544344986062894003457386596251095793926179131680018990989031753593729196\ 5046710555173471669848341148810179240909611439042184897621397706379682557833063710694465870889\ 8901390155170068514254331463555484110720150045235492053941542802845154932050975601975729146037\ 2809720816249986241117137240799136250175845265381789318740243175850642671094579911877350439141\ 1979314745715094725350561698515046391945941066043993234861156821711561631616025174729443147736\ 0854057331622206114168833836640675376411227933606357846423860223587661603343819984791048456696\ 9732547631787281946572046308600137686562381803970623811199133041175897920776371390537314976184\ 2454599564338563368253323649987432760081186644831288335233550092158512522418727661304347188936\ 9019986731623687092644132401372833854457630043994946583104426995597953071445476711631721694688\ 8884434248857250520209273317709029910823774740383784994042751553445225371859554977178754275257\ 2720869218806455912302149002208957377572311612260985103424646406518594541798737239467319761845\ 3703072905573756720160601059179081144283150371304358250270430409334914609958883526628286254739\ 7957806486981699879995065471275327067709614123990065910321531987722488205786939842370494662723\ 9733059304354494905505833992642568378838191762381696926337740839072784102119389869570325795508\ 4329629331988932845226526232080087627951561456315591441452493291390769794661267270439235126499\ 3837693049725862681993408069961086701218484212470449815330415296881725661437407908259075236959\ 8591778804375588596522125617192626741943147689448340038177665644227645697403149199950934995555\ 5428068804339663011278849726885183272835042353654089185683315845031665292646801183409328266145\ 2294367197899331473860596602790470664730661340976117301568414595538950637102345482981979868513\ 4622205718000700655596848150771301301725442444368244816411474067878531027455549820811590144777\ 8679390926138755548525605624100693305507082229471573941555462577472437428710537077604277517179\ 1920960555847602930238613991575988401582109673189419610617236292087258557423502462710380621006\ 8204122588927927836601395741400614756915342862098537188585004099802298485837903669011480394521\ 1405256871999656265673203441826421911976620555768137378740958093862683671980436051166878555159\ 7593017479809953113937099143351323384294004761495224723742559040277336092088262467657526202247\ 1750296813721288876659342818814861789499714470008154046034992887737575861163589579210984694310\ 0063488875425748378409545528953659907574420807411126516269565508301956285367271524662090697891\ 2907633939020583472192719804348308022345966300407757383416881545450883583590876828919618801774\ 1436764690168451410271872112375441095759336519634738418207657063690480046488961827848101169178\ 5534613215677664082792003549527071839699105231366041077340984097435768619392163393579495622231\ 8157355226543250554651904168932799788351768857451056272508827083201532181619887874882113642429\ 2909361639438536164006939430577710799717055325305189589816585593286471847501488484809327649194\ 0583641219221519110479547265601680807099811554011186879905100212453405617246824998493724221807\ 5826656666459075692300427671752918495747640681191125117953658221735224449037448204778891066279\ 5841481549031243575306110436776926713503440443814255315814247152025196166164371703841028538958\ 6100751332381500719764872332772561997523380228895406562134198777714074915204608319767808355064\ 3376148408705540530756374436491708850667833276830737653804418277021021896045775801523387717859\ 3080412059611189099378707212584336325573396494414480590882645109652435740802998877030488540866\ 5022422651713550925519511581007152175342223467057378536136564429756335890763133450963172009616\ 0525499876749623272356408527370685473713699624882748665075034942115121717368861715308062937612\ 7118945392023125246873343860053974394713816895061296656570990270498266653325042412166093010907\ 0633931572511654479213605281697119490134249577576058642723054791676781958467140216254871241752\ 3069211677943716284203259745982767670461987185105515911135431008960998658870016534089075706909\ 3421336433741825956230118072892439356087928737786321350625826316171074779764239889225951191490\ 2795526905762952306450599459441591753043656973234014535644013991552596171330317412706976192397\ 6879775008230682891146988905361569683004070940940745491612651470051807479833030965374214916465\ 2377831963458442436784700120338269051406743909919149267952480864686304477189053526363182606008\ 5370110440275878936666336064393688457078272197818029540750688551206554489925699310117715370308\ 8773015273670443211053930181855180201768644371652082153018670845519919291271342527780656977444\ 6386453768600770280758300536536937801464406687420252389760205827876236840697344285920094273268\ 4745182149650832570063352617777274132624996526043981902979605702458267729935623949877294387477\ 0024434207526540912109840065826172823609363787983509425236679312700985860488814554867793446440\ 1964751628700764756089698625252501754106663620471512631948238212151182459358328151674972509372\ 0378165377677184696133923741548201893321808441460857094210873935376386932484067823462504114992\ 3856472088724285150964349295132632360687426970222147997686892791557259647008935510893805965857\ 2907830144694119492431615027961783003717527078811600958179079277351980107724572415617201228622\ 4418061944462794479834006698852805692175875434304440226186628766127575387426073584972408247373\ 7105193192982452268891079288900159085446758698876805681619753867123941591021526672201229802708\ 8521021128824682202136382191015653823849174198756646050710001991576977015965305106868637339796\ 3602980725789826738953135702208993328088611806723434804365948367004951894234631667951904398623\ 9551829963218154310813653444236115868381736437713889118096070079417293966721726604090104022205\ 1354641908210473507917473459386904500993862365857210184504798172142397504472747111212127922550\ 6155890788105349409406117151915864245690201802662345231359895148478420721542859435558861614724\ 4035332676118139951890553207229653148039991522781146523413120472872051302201408880278082962212\ 8797676578514321072645290443790180929499766401675903743058242245579829630182062552455158565207\ 1941535624550047829678458016827680073365054314819647685671899588903260459866976735180000750610\ 1468934562446547610767538487862313198451288187246918052159910347981474676319341874687074897268\ 5386360471626788454586786584250266170876742583000917453019997209622367678690795679580576845495\ 5439239547658901049309889138225829329347173315345028515248083723767169411789254881331506093817\ 6758717177967061603774439179017588396207332862589205579639447609698576691319178163548229408675\ 0791466968817476398417773917467849255495143885921297503575110151301035937788640434302468248813\ 4756659131805413103767617196943258864313687966399677405420345218694565287636229965625035384031\ 8241126317532621786842737877900652019300105335126344225406447199142751728610142268776966123976\ 3692681291127648743995943731847837598870254189624247181627938697317922025812995068471331064127\ 3568073850362092716338214053146085975303061150009096277554375793571967832788467308648888815029\ 4714489190558188056857374122486164131592352511140457525395939478159205093802425063395254392625\ 2727765695716901158259049085558693319983855380262011955012266498451897038454935425719867736769\ 2941823474064136062293620247115807575660319803157473031779112770740436259629345867121405639790\ 5745203356484419914666121141274345863455727416757736400289740249836781497033225008112602289319\ 6500537580764004285667876205466042347046972786485947587228777379886131155565405636740224824193\ 5815477512365725169377367628747870068914454689606633514774313767228704098592139748641413392226\ 5909042671111276727584797685344699614125763870163790207383692242307259478150802598464846914669\ 4724135323692066838007305096042372155269113385822105297498894437201624605786207688371815819990\ 9758978028211748997206010184925501615890883873650494308103809700540673705693932108012207461129\ 7522550898088698703328157773776364894759951052053801526748778525593765003435940525916889907972\ 7817146256858470591511762542323897840496952352293985086057222555219093029042210557392691336273\ 9018498155078138667158000732781147250570436741036521342987279723581483778641768227942527343848\ 4144444294173229599976874980658200267287180806815450047166257819155613746866455302716122398035\ 7377533722882258457701062162223081397334314500550184725847024143599645227341999558527354356424\ 1631169307915216289102353532811965513073822023023006055731193154909706088254548962816708576144\ 9106736955347551455724380053052440932046636491292872213498536718102049082860527053501740463405\ 8598938377259856307250766151559700954333796386471130707890170862698709113543106903048354399015\ 9182495376096770180683910115638704326920799110218064615467583694517840630500003890325163909861\ 1251959332693599168275139972953407310709725549882027707560119598880849047026379323222353002651\ 6785578238509100424343278599953387223006823666032485011025989967035087393228810443335662619477\ 9417355285651920148802789351519507742006761266275244983812759985478867881141042103946615274032\ 3809020975687270309642653952645222067401286441141222011907303997290737250623601987081275550708\ 1165441105341441263928973090590875307594906250550690230204022712600234637031142527625145146475\ 4470226449704012918364894262588438925396197331801571433484068499168918934761140177572948400711\ 8616860646357369307784356054315150101324686095018257565201768259608469076812588681266049467981\ 6427571257151806530396200849164290347915857215417225482505861853410714985035469651630479384094\ 2740261385204884315938763237440451754610362610677334447199527713043601160548072595170008731835\ 5844277387189982752168168104870118107346976190265010358187945203879896662795073755148339917631\ 5281621011277504751021612348713520353306789576420273829787821503767157999009353426722487931459\ 2364899837277069066644502091646175216105749838413515706988330206546204026825822400754220680321\ 3672636173266407290384766753813955262013283056905942893847600205428823924148240121471423894618\ 6342965131490305696316351469752351308004127878888471762510563919126337131177171510544149283939\ 7543878945591710252416027906755708004764979221566226625110232818250421635209327860121861391347\ 4800354099909304857375173585335630299356457160059750330355159774935717757824242078304406673235\ 3813477652245925802791202157445453255518317906366814577656489675775200883532359385375306226240\ 5036237064628951642443589150453335636928921611344826628695554104443723779977950715975984465569\ 7297697441464030197678191484392159770485004901311341623826191462979724119024967356559823967631\ 8757700086918863482590561489486959675908095188375529720099665531457962553686303596647336467288\ 8423076004008281407556291433582029242926800532315781587928242428547129683900166936642008323727\ 5709904261559797780309419103172899100085186433650745065146877077405708794349653829072022718455\ 1816821994072271319782201644393663271323982709184538088519938248357998911209460396697339239361\ 9506991743093162140123402637590481221497638164467124458464886747546055681012272250486122328437\ 4220121226977020593303875384889522415540522043012667827636269129894173086730712961857995753799\ 0611916890215125618417755996300988989982179112460150480935112450731184525922740831921701369353\ 1937771382361882311425307524379391552907555049092973372741301219312378862326957187173910527176\ 2393668803096322633020886554249287588897444251225286665283601227354273849040518745255245587161\ 6608971126104854368020390191837775669611822507871337467328167697752971012510901565832402214208\ 9263547689559716683036180351856927730748719477293439134505566076133037403949778902095179989217\ 0651080477098775025463167244689340654264495543461330992927165261112302786958764503622466075041\ 7215013807169684613016962122622779149169359757361858148761640833251215840596342325512036042573\ 8551422555265161195198406207738240450751000834306504610652466271593093885234165835866405933886\ 4168410377850042136887677949441554048342529539049227982750449528386125852496676926045915846608\ 6577072933539465829313525982256769225259402333553420054178005310004601191394876657413709095220\ 4209537376653910582979104496303708475815384169215633271897861698453955718235235422834034596368\ 8885501476029538090046139930328882881524117647507427591188774581011892865552390849559698609825\ 4183207336484420331286429004777978948576469419452156007417103021407441198856305518009990129813\ 2165345695889699820562591234922785579844141610154440677846434705327755246587463440897673590167\ 5728525361444820623708629747585666593460988362036093942588676414932596571547754240410132552336\ 7307100837176363501089508060772924357595174730483988155474747980140919989912200901176605786195\ 1588229320846281662894325237471914578679566537927469301086026354969524289645529769346248421312\ 1255677124590848617575807681886834274508549834601416993734765563547642888591931553673104443730\ 6533774371998335524061036065484409115955092756815642476482384196626754794691120751575614570396\ 1859558590768902959677757857152244638486626098766372671765881906637131617007235212962099454482\ 1987220752803619491668851045718889704214100200990824138836579025450519079407093712526491538947\ 6732651211024777192213681768229060876735038116296177552338230295555241183238386494709815251108\ 3706497698335224002482792024212463080066590408139287015996322639743033304929782449810759658969\ 1099639767556561885549646174670004121467609185897643034847608822245654287749131703873418275675\ 6236765036848950159634357456986641404376219047943666718480112301402539432338517915649359872206\ 4943151573909373159012229442740092012431727169351311824573806702494038530811405252932830125784\ 5735307074307713197049211607986229280805885367387808592340650497959581784878374699667144406567\ 8034104038955840048000443927129271206897536461516466018650090750442880554659866772980888772156\ 2354839182062933980426431630232536743984352621837471156103999119720817023267203329734435195978\ 3240723228608668711756658582524702632717063886668580300663956096177567796994674622819923350239\ 1681703499541148499128313513310539678785226386306245739986627707763005268186172990896457806797\ 3036668665787353016554527822382877910533578657342887138415209061043312829451425662971648460182\ 6664278537073018824896246752031768286150977898754453395012957841878961192505800370915890557824\ 6033556799419611359127574929112701016723268733512957357250715470824421411524803654667957383995\ 7324263397859343649011082356264345551792936746754998803629859826676798083465351064853492249097\ 9272636063817594214208384064043145708726928953497550165881865614312268280145956730068374990340\ 9473558804369563819395132411584897702087057363729265576386643505072352607846505475364788123258\ 7150250477228667859213079633929067523752865447562069422947735912669058912375023367295353902417\ 0863050583717379071783612783081728930047866324407454919054580830126490113516854485039077225757\ 3128076771028630546568221465491910035579147978097324366157798060449240075950048623557468198600\ 1762320854488902246445698448523862230848009597727104632867193976759411672831668072588710029092\ 4438702666020748577392211877602235981323919001653161920155178818173823077770391632776687195166\ 5721678112703670093339983928267113823932018570775671904707498242961817954894278660066513759506\ 1451767676828283243132115672788593761733377100232372084618812844238948227026056498859018550935\ 1598607530982889356753514109660368704496501064486805629482663182076000225050596266840751689890\ 8827334819513800413522929438634619682829463883436849407686623247849660454742634489199333708514\ 9624176086919968834356469412133697199181980915277000117000019679727292336155366322292611192281\ 2210706673356430587282511537152971490023320732247522215366911333312268803220336451364109432117\ 5279068577833605734695841407037634896768512853691899918073671877287629375721570444315142227374\ 0099824778924834806138234016942012327633722842895646403925746649411105240129725453443310322339\ 4894886838476909457472102427756539200740353768201419193348218972746285616861814860811877241667\ 0307515010531795661089494511443538246172230840772857453446238831751572898259573215553194122706\ 7348361205957881534828202374276404984353067437910192323663272187447366468437624008681301822136\ 7442049326875077170933969559925117345859607827725688449969552814420512291919783391990768212653\ 2359845058638248420106727474393999509084847218513194241932973349312160039252810956883833686114\ 6980413884562892164239719612600062548078077601276670093228599518041268655223831441035702783718\ 1843165656962852108309738627515759689087385014825243711612891528118190007956802615221169258531\ 6341942147837113524360240831564728778402063584871101431409402489745110363101136866713616560316\ 8497637795868395606728863828264206474448762451617414016517639824383200555852272143479038886311\ 1957767306253331740481294548508983241084205159933461690211384532747289363677469345022413131760\ 4495787151802925816407961821109881217250857337257472811054009448699325258465315719399885521213\ 6683007964222452309714562237554451121582651673127724196315487409586174240932864544039557038279\ 1796546699449495052470561496565136626347930564698174705097749803753531043385876996120485276955\ 8871224237347568387834392866584975582274180648250362783313051717310959436064535574710355065978\ 9096557685095592535490279249531610159442081834026739636478568349392202709076895949516878226572\ 9471343505483055341574302463132516165471632640063059703528761568528873648218230485354416776266\ 6693992814624722151789070594422611045323191196374575665677398448539962138807232412749458600835\ 5770848163117853228994417116250021754745259398694399654485370617331218386284247868456600374830\ 6249725213239301145866634847752007354792925752787630038516695068299787148836332778344683514474\ 6472539383796310706873046785886787172196146387799378138542574870557471008911419591165942897529\ 3251370015640941528188144327362881990025522274147219219611837802653857834591061966187219085936\ 1173354551489264636906170136797286779319586222336048492233717932380285067533629453387071473110\ 8761694556841218284542300240547315811364947941006700584728897939681374759298963549986129680015\ 9144143243998950875881592116385246022499954054972305583804438218444856888987673006739134957351\ 1004398903563306236749050375830302910130275888923428713154198539540365810980306035330980179329\ 9839679800234661708778363485827370642846623429954448515724053053406262077212739988319290170001\ 5927655311574994609602813543158838938130721032429360167956108855705436994639244327273851829857\ 6319149477090767891231167149388922596334940849468700619973310945719377672372830887155324107550\ 9909256661788617516994215921785765369906670785504479507132311814870277419446379182054206268905\ 9177961440757060531423500275898467476280732147637807441365299315816012356583871982154861507609\ 3407508399291812146554002563765375534979554575111802027795099739575031388469548294498472109702\ 8774886073382276734730801918823188704564591645777281468069903294492659431826739543951915512579\ 6858401468713166969741697011513886341856171480108298863445922703865639866756970302540061803122\ 7262347719053470663852337390557200879265479822188320644357441244289202813063963095783395702909\ 8784422061270212513425077110669305128324290016335490581021835573699111006024336292889774234388\ 4417093495386177552966920719845506762026815691502138635970194002987821186692349801082125922624\ 7035417431582121761678353376486413619895428663991139584819494631449923155553462368424266396914\ 7161610232577244223534063544156699558275860492912368744213686001762668759788234159651102561941\ 8505984357222701048391272265786092913730903753830730718882922884489293182002604548763514932777\ 9583572297885881859331262201611480160009119645599184954960129015349768035398513834363459264450\ 1059317506338608829400201440367121073848854423927882725705861603545580005497741685999091340474\ 9899784975526022004413940876576013540773287120869208728877861608229887169091972863070190463753\ 2741438316866152634074104559874279670014479262098950123426010859654860606550723643823484834233\ 4033830269262773809253967609681781648527149030112233454182929923978383987134158848847071912376\ 2942763359215128142337448837369742565191915879669492147934725237599315597198439240532786725643\ 1681589697701071217476336611662343557481650340640241974745257920328464479274910119212057097007\ 9247986381611144781088053086600553163252880696516327031890504726525447252711263557526245443539\ 0319110189704723124223406694402936752508004989276735359510683590371314819944107317454552555760\ 6141669185510705112946994579338954861228308268195781597267678832777806804157277734165233087357\ 5498029986705183807843121865266407118177108699560244283203837514676872347939234118613368236124\ 4299521603198278039287750730383940636481434499391131279943837955883817453140375631189630131241\ 9671265929661246428256434376716853462737974766864157529818949279231441367249186886904775458596\ 1444046004614898114470180903950665510376070226448789232622613181986557292529565853491133887173\ 0093266716782248070013507358105323962371292760035855181451204601565699559242628520181834748072\ 6641171453844272886337708207965593540900375304195080916241427450069630697771493646630017290988\ 2815508241498191749711411045710087423233508298312096723302649416131775299403125378578011581800\ 4422867530517271682667047600875404315473218980874479281327702972034541703162339487402114572761\ 4311258330947108313833566371875053120997758960900337500753843698855479372331157896200424476648\ 4497446073763537570389891654469556342430062757295130942840372953528767366386372893817245773716\ 7331645282930550289058716818613254477063080273867314903338202629849128361496065648484625302836\ 4128875950224998497739688880741213204897390524636307861949848199003478619448711040587172081168\ 7034844050427428256172028427275479864306190386944694762259619483341794460444520652377303327406\ 0558816884872852829972737181631536570248153332303469768804453247320239381237302188654281662211\ 6491749578742661818469972152222609439051652554414119378115129900911986243812203022736918072192\ 6937244955376661129211129949698123994244589002007139928380960105413556858645613785486344168619\ 6433591801871397129456831605840370674849616016342925300790424938074391225202224566534071911119\ 9153035312039130598132745172403403671308136622062913107479516715738044230239604437969468135594\ 5117081187916714056325348270919737357989617948177277612660191892205875039594384515460468270296\ 7835856327463555254506762832987844230744624371080093019436477941890882092560362532952832231295\ 1037119435923144921573581016046427883855039958560482005015069971677507003427075606843353854485\ 6366191283530717941235618535768234065922298209598916265731895010661406225822430283125014087987\ 0300266005470539811127513252293876913269643695214799036252754476643119369220741214425867869775\ 8952285105601310442789113247018623980543186330948239912497539106386683799006869842811632848794\ 4396571538474391738321270312175973808023586658438674628248916737100164696330080300415341170183\ 1949909615793983429798989968014496618193714727896717647941624300763614475926930525996395000065\ 0671692586767508330124113509744432331741426930943796102644235618304789245983741577966394933904\ 2699868685442737386604517633105750799341486922994913014190415231234008323622271772055606708336\ 6124565314945769622218634736771145256437546477400507823684117240450159121588174233905911433359\ 7139161316511783106336294399498944957165414757005196904474372147885911862483298834817689769881\ 4588260426486286315309341187817325352958596212234448986546814036236410300603028990857869583092\ 9154253843132285421699153596600963249423750714372487339718722102330416904398928393212046647128\ 1018658631497268331469393791658158432204791613366979023358313933220744104125823534801036222264\ 8152549650837542413403465941638403572638228626556663828066346081308694983370718311332499161965\ 6860764519310220224741060726197730689905185445040703807791955819876903581510644667667385936150\ 1249612145449091616273615523551086457891535435923047953615017085345099403460950646827096462609\ 3743752710730072495971051970779561940020677925982008883865521609481412060222433829585020606765\ 7750578020759722700778965018626788078952897190837203488138741867906658718201692142096714809737\ 2698051371154096473854536913270932629142557085585922022928798932489426462346070708064685382528\ 3322203786999228349377173648192564835439111064306937771572620167912736104481327578762611382955\ 3199855884119194821170502191858937314633349373272291566316424026154209015044073012912912586002\ 2118676873065573996693383276370749077579556909276960639199819741104685326384658290036459227314\ 4242244436928206773157128968291810749151113183812574385428233945960391501415273999846561362227\ 7408059506658409330772635348364691481442124435233162070043806842277960839555600971168097772846\ 0174715441035155140117982155886811477067713308505101516320580485257520021480100061462722672223\ 7687467727262242133510051209196200746476563844897723254743405187572853402228809609518837560436\ 9259042278146924934947319264799365976495326315776304478316784896778620616534256995352081574326\ 0808700861886980703927228629054883120863286133227686530715486022993178369967015333754697166568\ 8002245254754915215780267115591681194616092274917699266476881124037855245689532714068537813365\ 9447532627932026129296195644067437103602709801256967408712031643627299234026028142634436352573\ 7131724306671057946060486151461768119114919195821508988972149854238530669459473046025686648043\ 0080731298166933513090524419066542963927065762969101092756305901558643334417105135158850495001\ 0374853069416822844003096844359251418667483669295991183368616341730474368190719581479114613943\ 4773861714566241984191777336093695812981047067056264468653949649389777032875555704251048938173\ 3815083191986149345698368111468384812021493383483559141030824453324246124449810427040134107009\ 9101342263893083888591272307116869688235128536214971088460477447293657670213808257650730661123\ 7105633274724584630000842923790680779968577808442643193234464768204128084344524332946588597462\ 0732322028648126828364037377789836852033139685040724175314295973555553206757172469001184204480\ 3406172658353283168362020908346765908532499747956218569018307060762300950970360766118852238478\ 0668635621326288061278588381858187678867486499167894488972206794549694575673538030993450095995\ 2480874015451428995694349319506261680054482316602679276986761719837875095765070036374191725691\ 3327281792044512129267905833324473131345495286099038623941286244370846805804761803872851210094\ 5942765383022680967540483108901892275456956175648726902264182002858490096045048607941687124725\ 9279954271824478064393081170281162827531977679813898803207513882624124209315944466174121236067\ 5582727758366237923430979833265619571369650143137377488610106530477013941169432823215830221987\ 9442392082231013388798478081972535563389188748948480991992434167188500301057188886248206609778\ 2932228848119573727573911305083000358067064348640652142577824995503592318552284967033627106256\ 3660005788005822474158035427184099293393184082407437806110554764295223119892987416950148220655\ 0798851228433345488063740011011101709894211030970015613558484745013306353251083836060057809898\ 8337110474509946294643041435696107444058766961459755226364298538335262001500414159063291758055\ 0750029456991617489353400704896032740397057460338900138071491962555141173256929728492061597549\ 7219698326477644657149376655790881682808081972181254517043688409304369727671308864173109897476\ 5162708831034183304075744072888179411896290733818718287018475540948108073446508947157939801624\ 0532116776392542396233560946065895334886930666665718788710156869458840024471067434486403331120\ 7632035400209127032785235838793751912626009599484358564255713563319992215786959867125830915151\ 8412175772400200338239620499451259170709976860837025124010733638600914221536844824833127513855\ 9770781960906546067043371289612646493487842715179164012984155908270130870433661041584711605328\ 1966613308188590736607788861721077644998354508830538284463091330206936690073850951314395141438\ 0261837635114065630982828764515489589169699835613778746842450731977090813393863398584755481245\ 3074594944417863303442112556376651900803375245037114053639262949936018592753883366889410004793\ 8710501141109322832053337377137611630920294793655629152131896738830210373434366362070180148046\ 9186792019323083212083787337400648266005252559984027819838360514323282772700227199295519811971\ 7942028086015129552913097438857125309150765339700252028528586514998944245161332001525751442054\ 4207749240616062037587976209149606948056402729648514455857514897046351487220327390766387693783\ 9363364787568563350243094211609630291540038323099773971174552252989993740000328505702216999865\ 6737826591653529273268862161754839400860228834331249239000521885958943850535967448114404262480\ 1206985099788942465309431578830377218269332916698469388859275961547663028194013255947013733121\ 0610256025742977948157848491212593590563131249981463698723319876813760019086831570169876930631\ 5114814799937815208546844546669559256126983375349492151092388946127116438638969278624766941128\ 0221378431909300989262567942353170147389267422922661415379015296028309310021379353924605128075\ 7669390873478807833037941458405381070348359901437957681007940660113266523505934264935467495704\ 4783600264271339515108949018912949399050894339281824049305344438755464496037288057212825091258\ 9356296491450671764525744719547334344896063400978696251229052234186734780826666479948664818672\ 7805944353872115408937857085548828422044329060877483180749773716209056873485054799559365224970\ 5394849041346974378201676090333303243550905178242157842282696124744541738261319310455955539814\ 4441390033896121043020078290010740506967302345792128521781716266936750049210157026622790309391\ 0314483601506428605653660697382132011241518072852469504920256482883704295856162564238762050918\ 1587736366024458438902136559220288560131025784256332507001540437235637423648582621928349365532\ 4414201698339131273757335903160306329289776563504743822986242800491780658023702660843963808422\ 4731122690015638928850189960701386819579128547435831231934453345734873908202623427698499926992\ 6493632695964837567950803013901568643166001309573268703444480883929686203226691101677264298696\ 4729555215587098740590446563433873387029492142635221350223644375594133167489620574623077130838\ 9933966615389458128276768846029782385413014849082887439995576246789162783348233720898915368460\ 6701620236922040650443638553587107887153280306598139356404275947470939680535370161663770429981\ 6398754943520109058358836992493009126011527096747160793378741938140966714776526665749159306852\ 9839760510927529381720641722297131924043358961947636989492474867281649826112947601801025343115\ 1179019821759106650321953522409973877029979624725484314962467175993669361076393052707140800524\ 5593362189650824344986034205266092033187474977289991252251431229228607962982811345243716066072\ 7463729666264261908392022373995994054235402111401948990010843215890834609165837293705924341790\ 7079667774756214612221482352219361449910247864102675169600716011762138930808462580697465876967\ 5434910023331253564614251097632931571158075106132995247690733833079796309877396836118143317125\ 7332669769600338650357072884937626871121679413335979183785716691448707297890132479761971619936\ 4101177151288303762935138901201247555596267368472461020262105556139995245979002049794112530494\ 8860161794057528251917791391077086174229796671330541265215422531424856652323732590761256453474\ 0266040598124060528732645940776933508396657336609164436944355565611979764593304622989845908421\ 2380389563004917284093983455321946882011962023242663131523956867429764919898968686266979945673\ 2212083041400819897144293617953839630015540445194469720762403979752947826308499324991887363458\ 5109049413050949249384479151947084687350547569242311444200963149439249314870192799209084823279\ 3403620176455844285708970005189428018199906769554907071872997977570017180857346799041284043539\ 9524649467156955805874721256844617822997274998354847683983574151358113181616493879452097548293\ 1127331139705627925905730269830953860093829737670496743718005831602844526101224442614020034777\ 6106325807036500339229549035189441628884756558801344378459471820717510663194401831231800196869\ 7608004730510373713754878570691320201869672049369920297038076758520822503387471086173519560800\ 0336232130174509874979604843599455718384820728804411287730480095116232893532280880502743082005\ 0653998353390873767650626078678804043323384864224261440564591599507774389208663922882010510298\ 0696264121821261064401519353869771400145143580991863837497819366005984175554252467701569262889\ 0263597546026578583770500287729017100780473359451648738585885577880433641959492078169366700536\ 0357695843808152938855093812577397718486138494090973226397393769701705527604384238496532410237\ 5208672907136660216787165545783045980149805463020494127404935510337018679552576978566402193251\ 7039772336451761446044799820680898888650539612988411941540023343985560710767982352980268874905\ 7177075069209236086517154332245776082808147901347365742427431372792018905586082847307416739759\ 4792112724831784058109729118975417477406878089403254508224108399252986558203616101045733139117\ 3019794846983156518357141607571046767894553091487627632929641275841183871270498118237280683511\ 3011124065188959436022836380256654754178579305423417293627439430314305563135328956171408829788\ 9716344784234827120623649941600370328575723659782365239359344776758473949439469665127231784305\ 7789865754558382049663800825101102752379797135056664696245439539459576670720270892978720954390\ 2172098418054201944420251936562960065150683689848619639427627815820914208716774761215450206742\ 8494587965392656567650563421804854282590458951150524399013686614829457433964710497946603772009\ 2144047488712751837556793972984090039604458827873700396423725717903409820523821481137572115880\ 5257490601990601627409259100592243257532358339510017079608073019719540653249165159450810034400\ 5697246760598755970323038180149316092154134815569396719506626141602443054739089995479007342260\ 8867637821707941873622057393643153476022411350705017523787836711928461853424585888597445409202\ 3840680240485607780274963029555224922810363124773067583290163317826867909674784241091640807596\ 5593457444090741602886994789284642738521601257639048487047535099075507915843459745323958378148\ 8525848413637335113092790250732829114593649230461765720367365511305266625153550408907417175656\ 2995588236710331000984205112319548266195823922483249106181781296255555781228104554622771289453\ 0772452743197352352833506756707594208312769472983347829450283535014797866816141276485114032472\ 7657223686735448911600003503131378932307156211135191461884680915478918346441725825333900604694\ 3381678351549894336491746292345185544494410351365055909120925157289388323466486142219739332591\ 9221218110876962866459465115816155560948848310118726086874280828386272092165864124272869555928\ 5058708614175600655720442393349675418437080797879186365934777194446786702205898567332842958383\ 0538460346952498049610979197834198620195278883600866637053506024256897273734868262079207965898\ 7025409746741688070642609972016703318231236826130374228257075583038003635122277077668646997616\ 4016426989771016287112483895252161543560155417001553810427949552408063700733390379079866049163\ 8640116252806484267857574465419565782533499332786327070354563365852406118522298597871718293751\ 6782385532412704052608896863949198257963532510995697651871580962722918766143864427638684469382\ 3914195864597783804641317945861637501094919325846648914539299559900555532641042478547438780023\ 8101010137802166129392299252638360956128401986921803299878367545900026078251931210053475736395\ 1556550399271947194014080506015557439439996496349755778516712929183078992879263036944444963979\ 2078754770896648034315655449958821001609952737525517889781424642555797162858482164240500353339\ 9932187236514161872248384146876105069171559903028418729308825975050256641835631571317124480728\ 8637926259761620341891775682888408116502998219843402874677077811525211509308447244880199634340\ 7070900389904941615798370909071997775824389919092134776000626809869602278078837512134493031375\ 0571840433971890785374840239433487377797707993454646792855623302873537575183769684328380300276\ 7098283465859439156936297724177817759525697437200421782367698707284403657421980406485744498965\ 0292922050599357052329109889022207237968636057229210382281753235344368512352472351481705571941\ 7168795782526250028404882080640601214923632185714698483099469972147306051486069653344707549135\ 8251203628139462278814185795611473579036237108769262225847235843741617356626309609401879820697\ 0879371207963904996522806308860458416885714208211972135245928281737559028792632383853299923619\ 9412235344272276032867984059918026550563778511513132126758815522078023658282484706162817450233\ 8842929402225844314408789131301957289545165531545668424367043330882058305494683419801367504630\ 8956812522049811356938813772325879970236208824922950563507079358477909091611129811522572366001\ 9739946490697192084608900013592403279850963653167799132044341962184617770809927307571970957927\ 4244914158038191433615548164881202308452571954665518466171168768385387917850162760609930396717\ 2546670406882654420861378264821291030457224088463968535866653535417069742458446128551590839276\ 7336023703519396764189444257497852409626106223228179681524756236013678981187869824938760285744\ 7171158447813378379174589843100866845042702704367563994342449394708951559236239543400998253043\ 0968069898383392277508030548356484303443296239496218580662106688049288480674557427816668179556\ 9341639073374417702798098993689743570001752968883425914041751971295018778132896486934613437250\ 5438833616329682733848151346709993681483956036503379244972069804340576264956898079098304368281\ 6203142999378881027621889652013752090832638529692244863358340253660161819202773427280742126221\ 6506291572635632669232334073345267572914076523044383176512046475867191608487863439567829756239\ 4316224464495429348660265754755160264449537491790813004923844355627701199208296924606297398909\ 0770713281568136169878707375475510074543964462753991418753046501628631964180751036836638561199\ 0731045378417904472579582967333619686760183715680721631270103843252254730808929711447646778655\ 0554252943068623066512016326127408680846324600725418637128035088812701308310847369868143376069\ 4459434390537060638478162255614295655114808789110327236182650093295636659153130791430123556711\ 1870832029326333673654394504882320336704143768856684528633980402964098343550083586802444942875\ 8367983733381252384703829581540559925084601307051171304892220541644847715620672110398423749010\ 0015724232836747252728238959397505783203670633225941151498112053493294312333290656941607860645\ 1034616922473117625269483820594278809162563355759126958802562146383183495074851005733385961062\ 6833074938315130735994544757923088482964620063305864503593139926601153126342623421983138210785\ 7222604958907316392421219055700945811100505993075529579584193101496839898748978929900912340852\ 0687789042353033180634556625024339616489426164440352471320630604455596077077491056431156080389\ 6798953031104295948273928464355447716230865910329807516210980973029134477594621598856187363949\ 4082159868698531909865013469530538414751935641500809514697845676338536501932366408865514052734\ 8423405494018365266419811339943892070656481978019545372072424412902091217036939781545508094676\ 1159252380006423005637554764426748774067490117445973275130696268130533387793044746194159941650\ 3700197490984103610243464205907255034560276133152624201725752661614256512232705174512441311982\ 1203993493792387562991165900230719390751304014055118525029411868951700008206651593901325301389\ 7245844723883586624002236846871891631210283284234882431196880521579069225893865500211366258592\ 8014512762894940867015625330477910854241711986710948590282545183793912162718024642909327709455\ 2327051803727161292507771493157499825061803394426960491301849900861388834775918458034054164277\ 4508884425905467425335643279858965750378656027570212777801961573978730227960958949297337659327\ 6945538810380383014448469406847066278028184931117650210290717729226229948325817451465537041591\ 8371234935268511410053492758863066114295533432110932943682970734876439231832556714256364452871\ 3220590834309977039841455550515112820275347342771385521254681243629170915148179521102532428140\ 1182534356361169520052059925146789513584487652284988011108073372291754129161663063896796187727\ 2535182867117299155089874138958297890156271571012889089054861616940813072823410750184204588226\ 7958599228866195221433949121247268615955561511864784341876429065619917320041330306197982806683\ 9964416866013519889891897567269872837864475217081314098899450350194363693787477177629517408786\ 7161409458833621771556074161810740651000559187169671793111839673966082603137349265391859577264\ 0879123696022318851941370121543150526861721141434149094579194134160654932166411385804936600320\ 1779803933494729200371755059733807069252919554224778936551070408690862855213510557030180306035\ 9485240164445638697258014705340697634773296320648495484569226594829363285103930983435242764978\ 3073093718647380580964229491168538150580859885725502223962128882271877955601920889744942612559\ 3246151983685394210718684375270742764474239955306785485072306880344119451467467154487167294272\ 9388309018348301785161361150158326966692250826441009817480629611718887286090225712952049216325\ 4311858653416532715946259978897951709863269761478838245366824842177947922210765643390111547577\ 8798134352380145329086001949831757041577945008274524562666945875612673068134410098799131619057\ 0855453719401196309425164198014806621093175954302613566433421917214866679348761974100351634565\ 9246374105050228461915551985027262555779180471732154262449306931747169822682171098333425023687\ 4837789703475767112543326569111117130128374638688674896464983459640467710274145579574871920877\ 5693980594661935804386291722232866846178103118315835727897532403778837754544476727301833867393\ 4355189044898094603346266316454993789630417923726958508875734385988851307477881850922097894891\ 1131369070394774252858094306410947294880875592126991345916089241997304577341350435976786424460\ 2847169164459306713729364662917358859182327676392801490921502659503754258065345652501585193696\ 7071551400114026297535270869276616776263012542469244428543662283784229498588991980105729600099\ 4494164948172397355967944985153920320419825392653848430227351579041728628543148402988364065545\ 1552143095332912238120185779502364072377930184341996382630860887946416323430518140555994967881\ 3151278499495593738282335822708688159133074029848981856107325563731365467614148551605143923340\ 2952694034392352410967108700339312430818668642192872361895633535096084369065333127162446697547\ 1159753538135033251861620559528908845672808916235561940354258189055620659464934243911291715283\ 0818351682758228753972164566722319661000125076052581212509207221775909945970572854812965078831\ 1988890105934082739426618359673295692744121191753730596005115196547217108352073170089904701186\ 3440252587175478644274928247217122412551375908645664317296283696226498925592679911053796025526\ 9117317047601501376271041219071941177967632294147782931656532053878786969718643440374563297521\ 2291894132613634032544139300173324306341175037947625918109256288420203329244261502884939225003\ 3770564763989419004860970571940006499564288610351392754614153081984532433992889365941022270580\ 1228839132425848276439481879047414071651876193881532493245658010029311631941366269729109609682\ 2476625256737863638265679415711009895189191707951855195345913516657361435113933183962714122899\ 2965266795316665057081406890980249032080104188394916447095010771105174675542077305993262073901\ 1651398236754490617333960221697986884264113623311313706381349924820659660561237483979007153328\ 7915489950221474696772280453501882859512859473950983601093261231181347791349063972833689925823\ 4665830311074900567317059718801467726561542814087041503897884144306788217356289996321526322806\ 9941767460022745447469883626774332953679951597354218034002387932714688260833522800122169609775\ 9162489483399084828678788891292709099214457526723200084621691458342451948841510896774614941177\ 4516871534310203191578439177547978322296728442355347680688503093037225473988758318347119961672\ 5953892536817037272509555034513684752118898965012892672620460908264159900379655745774620106286\ 1596720429799138704524662252665772395217925658693181978405739114058023479285506208494707563021\ 4631329330894865929737040983956811841227048556485543207014174014044566393721083021123004356644\ 0699146039176745563923916459492640588638856494498473239697687601083285651109616820941955998890\ 3698890269605357685989507202810129298020391930820606836160927497578751241988806632754097391500\ 8346213725161603995707968412709491505545962626550521703074816496680472521492648622785623429413\ 0592816938587555940852019214616123355701783405188022167604400495203854531061482122081321129755\ 1923189541531912090853648346841550426520788453907930886384448359277469590416349072790525702374\ 6709392508763932505952251346174031333045439831662130879913412282970975558521496976879897884304\ 7575589099875497666219961473749959842500857965550162430401156902885635912943573982354944810636\ 0912679358642118951865024416982345957761680264596109278938315321040679334633651450216245895095\ 1583026541138070242705050656720736382245157177035057094847590300486341692548449012285232379057\ 8646048680745693270993120486181881968679501119771575907552832211062481538235757273453126779331\ 1042216181229333273489547484298777663098377506255555641462758054995766113743806923262938437146\ 2077205255360803959157721969623295505824162534936811948577038841187593479514569091056134732301\ 1649716015098736611689295628070029577365249399609032135599518097672842997407977291589929214652\ 0147942470752751687399657384060295528273123098649620557965265822041977464139767623629217567740\ 6758810289157783089662983170016324942442803406693953318846823284148275202993807336459523215157\ 9830642677635369638599390237352488809598005395930435998591279186745194600824454785693479395408\ 8187988973717599258721907917375487223512882457875597283490639964132263485826747961333235668379\ 3414310301046065507368909916797047010173123927643487701634255198121761008921539482035289401915\ 2445475592175381955550658750148750549108043354828853110412652775637849193123859186276888455931\ 7005520656049287028148772321050612592792338713074975612147360659178671339854313141834130845104\ 6320170066040921105275748138989866662390291413281136182248273012578586364328326409576754838953\ 5073933020112135818399643312863303183188901564099581702109371713485883378131632442616862240087\ 9318726871925784349564809940216865311995281908956935258512084111399537442648529033495924883629\ 8891489635245903707550464858970142578332249319509823848923953132139183816396859572650046733944\ 1480824486975608389717880252022294414735243035078860300685631788137683037169838023936647161022\ 0153691370888888423833384576550179414824548572095365631942204505385025350025745398237810446737\ 7851906985266966254409367295189076596504934449605907392048279492387604833023401432351307040237\ 1339490872135420056596767033835907481938277939624987900035214511938540687915588548720450512816\ 0133236769095753678154089986122108376739573145366003743332114219284586830016505060670167041362\ 4138951940422911098981003522951324500309594117804082332544339071248194418198378411234089595725\ 7746062506739650647281160245321158692407958493191649684004520833127136824404012619124021649708\ 5377493949411295938253920269685119657729855082332352836805661809820357068286458770163398729935\ 6663795641811968640605734988525237007747827672498498518365226034307974295401029522905714569710\ 5899711383118438287256380419764731204658730853016316794354432868548789173153932553933489187167\ 7598173995487756152972132658247542184080564480969084354323632381512316774425860429117402013412\ 7870395299068566209897787442244511434718252460015773180281341354911765661798820228050497129733\ 5709713467724954428656476279141220957536021489393175456625795186387444233864891852289899235358\ 8870585692484657426418395957540851093209130843646549695299114466145176958260115595752530335963\ 5532791531674398041947843834504067349769138046906654665165335843997233450383377331249287993348\ 2283392416981124089664052118488660742840894880494176266795835037129868457110769421229394502261\ 3457762166964308334478636047242702663873088039657333305977136100448268907397093554988160891059\ 8807038228701760628571618647497257896991461113696152424462353846466625386358780482368982367151\ 3153023421124983362518639363717174191526236802722004444986410053770528847179321930305250008999\ 1542969775451890928827214672784856969356805864674928405335671609470205442756223625619543551339\ 1448138990564813561485278347268121529161969932966929072637924966635360824028893100013930643938\ 0654641230930893445726677614631953369254669837210359433978152809478345984398899320524415972341\ 9047158553225416916832282058167659734514972481940728117310656330599725279741810010591682618238\ 3772762141107025470222027783513991372696353780423886142655795799616222841095810790661501143412\ 6679693859776360377184547478644935777919083523271669510011521619296170770791747015742517639438\ 3744485976123416876473921158230375303120181064568454064203114035523152566259098492985255266026\ 4129337950562981249565812963578052429022302979734573570850749860769772234377076741641208508989\ 4644079123960456916281495911664166965385862351029863424086688571581960250624092019464219796055\ 5447839807035392135049379564556605048905130475050691889807019655056644491699581462693396263873\ 9741544267809172339982936495793191397104292643265484581183551112035517259837667708178842904699\ 6339915397410913593962131146101508626834910545108252908043204269094116122324347008591499929682\ 1989233789147963275669663632642746654301469076693637507625578145941028820057335862274523643520\ 2071844626425005943993308461578662423233990745730769721516102044491540657478875081156164826387\ 8067451891570578597828284135251481404601992045398056451789284302685309655556496268556313180851\ 3932240005880800762918975959539836672194878049245212987388990681405416580858373120772903222761\ 1785138762325201465133741050925824653666972948014603261547412144314031499380152851542366570336\ 2599745796950554159899745069172398891212805312436385704987810982709771301215269383308792205581\ 5425515992566613665024098328605141201672183010836029233888395544186778257466625186706129865922\ 4556409215955976025913298007909204021722747515248322202711024768107096835523055353196759473762\ 3464710988973334047514087008670092701005686692579273152934041489860205361668259713322817338081\ 3805453531874921732079848795849082271186309866757423193859893127551407649498954796537801923092\ 5812446107953837991719532881300728657726064749743445801331393649539148065624142146194213819283\ 5790467623968745559283269856073278330470460908531642656390766107106519652450286450988481435653\ 8992597412317503143924728852780213649782079395493157138168598825482699507209828498422498774271\ 0794300303408528609217974153965594459955962511330807987065675569817512339341263277013672816536\ 4731129004945207459070928758938541134663989023986365300530700867845433385475634318644288843006\ 9166349492713681768329806755011633965711158667313046113280968029975338917456555473522977782603\ 0619879951242303917171933720987087801142331571459514470364657324948040205676770396866663334742\ 8503203244088817856467637366050587550723461487089469787515264178333923704580476043284364423057\ 3783849022283040625215010445005997170319125249369894269797348548681820665711446168911882396371\ 0972578722859052493905252670511527923291994553438187824548954627030952913564459220987785625210\ 4457156330600343845841855749556764727735142022843692698944974332278504808594308609609174094137\ 5053962409359329172516653132144370567510037815893319967275702552395115020875873302317907208513\ 2035402898708561866120419786913609662593746463132791969265684281256207790819714864490154903588\ 1035058965125824800883031174463207756978143123007195202996517594415892827452274474372274933855\ 4773157022686873769038275750613133192038127972920329735986799228991751039565215681995013262266\ 3444698077455716865874197686421279075918066965095384435186572769072461526288879851988246665746\ 8586430474676627512520120570875003715219811244191137731677009030832233059014412135305191578453\ 4089311712678882082475368723033208480352690117265341438451925630087632596210709942226567333857\ 8972315308289744810820955396118668287588601089461322955117483448058279731077607997465674504530\ 1355104101229263487784673499334960485649082243100125031628462846131597231405525632769201989522\ 9635578638490976030477112928379122786620614546343878101112443641132835963677606009659712291732\ 7721864283361785017358827470782838783657282345488235146155669837545271479888735831349645989355\ 0577637210238490013839364416386443154083456490764123374677515849870028090811616418027366058829\ 4862763048643090968226918312510951121084253986772321015395572093686109830407518259886818268369\ 0800057500895892713995733118274625289594070636041824446705043367568705425484888161917743784741\ 6266426898490940320497606619458051779885992753570172050210000757327249899060516846756861831315\ 7972250910356906405294584095800052228996097320932751398975363534373074011498725619967251479259\ 6730291578622183268968033449839168474132038366115052470679459561280820790026802015108987550080\ 9371794198222589502080832692938836432085810149320566527547163807875598085223161867555919322954\ 5079986355760255678301276129122374974612530686999859914394272733825524804485189285291018161761\ 5112585307970058637054441759704579836974823538104145002876456103697311608842086859928823905543\ 5126137091689970627260956421238779982395789376247219049461929222194798848848963188335987246045\ 3293351495071700088412342401695653216906356245552524888907074622645994035580999631358089432621\ 3759397548507037948644281641410879834833301192579813401658331349116666452359023922253400346399\ 2035351943128497152241420536518794255228203721629244063420792011804341854513199852035809510550\ 4151768530966509673343859142456798641947138627767727655816254176143282607924367990707940796447\ 1680013606975135443492772118104905134896234776644409259826541023179316544925997359945035863916\ 5158512904372023989644796892712062975385231701560485309009439236865560594232098956572047424232\ 6357563590578463267285921361350094601852659504141201233886472138807618125960604480606928586742\ 9945875289435911290283995523943404745582424379388244112770928215988995089670288720990648273758\ 3779587744835670965140680988264808144357124166842418405262880360281222889122749400977352069465\ 7036127244075770798351852234716702441950549686232855616893405289779077407923254067351387842653\ 0949976314003718065939242561848280966120848446640943637034463123167061974577615127858357594643\ 2359229258354715329198362764678911183803246110675150018329222074219562103144084456641283893121\ 3128595049172610526225862832966506288469674449948701379492544064382739124961112461439688316728\ 9985476658197867802202030443113164384028622616850829501950311667308906563343394289418152203139\ 7739647525070326806306810235528044947073879522029864456066830160988095328759175915086742801501\ 7412425305770117744842269668389328315235732905441260711427393611084655781710671497280756600276\ 0306494220786388488544376599695486407021130238641354417422855466231139278093832585835021152756\ 9075657035118171452543725920288994176138856030510303686109781694389624792489910276095529868356\ 8707624066211369717168272375075079068925818288987968143833949067295001192688834546465695175460\ 6551802812473609631094372170292204238168506164702510647060504781417588043171462356658563457662\ 4282826568374053461950703926680095739694696573014233411383875752322026163794284616661567221125\ 9270003246047794030306872031306753445466111078795726774049121789473993812518382387769574892613\ 8892806402719284332213022330476087148715888962576044005766302988902587601418951691163700520101\ 7380664132477539779369874167263349906790462258345637010392038461073532888869097451863405924785\ 4896860580009370094661380501653287048781658959323378739686494698168355815864213088699603102326\ 1306502167660793696201502602447484168677136904215321232525536080713709595478779435638972579634\ 1428174718539705398563456698005547499773385634276435961931640696709253895155103251124699712047\ 5166968246100831151619391517008632136526520905078649673271309749637217921899124841403487140016\ 5887260287039159029219560704838727424831286037368937100713151936615288657225688455001270174430\ 3875059459042019424833417882391735607090169297854672579836247528499320577880294322209526334937\ 2267388154131215566149804590673903724321778048877325965115268066843557032842796418010109325656\ 7206437842702318590441947044267038406940022746062758510593517473214346636128349432295450747160\ 9078498658014118334804881096168731683961648968545146514141716875654220644144944842498122205358\ 8485905895769268731311073424322569258855389765108636300786812432682792887668623735295308795987\ 4435458341902433619253376909232736589300849415017120716461868805716702181521713841492488190403\ 9275865797307280326903675230149969526920733543762902562637133551394010912958197509931551323526\ 9797429227684497278886412649239598356980170477464933928728873413452776478729816349356324363758\ 1522731807291426685517581108909851169260333785958689391398316636681612420907101955180393831870\ 7072342036033585467652638234986087240704767231199031692025770798636451267430973337862918667653\ 4587469554075643681971720196024861579935868916613711100732669489726823908163724958828428052368\ 0317451885526877727883159537010439860755524926150866651124875029415029383416302086910720037100\ 1612338226083617318057947361421923964219233793660922619025601320803821082448436556280250678381\ 3311813041864961838187093242454130547937714863422626803383120418691439154851316858285846661769\ 5383457005725362213570135448219821551020819209548494118023957194719154628692788439523682494424\ 1065978546339075170878498919203189706841508447327179541553929951138546436990149680948478003782\ 1595264120462143158021059329524834895973532489512852834917696773674574804051271543115775509209\ 7353103126666229939521062536561608729116507694760471968306480865820355678238974480395754028934\ 5203062240007763298262626880140495404022290877757454789454833344523906425717009392365687207545\ 0676213808115467105954508113872581419629855870590587589096199872295560003340023706447520560839\ 4904256003478775472730977761046892124566141947309852265357813959483556787085827477804519786183\ 2996405406008303992917234248648104784616021057033598777176772592247434834689636776117060796793\ 0603204720291257014011455587236193223312848989883848995695179979020447488081590262168730140094\ 3457284717670391280925844864761126534254810520928756836574687810382136992164542889711681916572\ 6128360739799867140243235741465391106863817457054450151995889192546985787379136620434305444046\ 7926960069558790132346962675106803560732834650867567291272329467265189964408016791901342390944\ 0717198308603390843001143715455967449255623783428501633189100014619919884571078391066917322556\ 9353802828845727516677943641037017118788910666461116297654235823302994677003236360229552820526\ 6699340373596589546571301835564101988730949656415616818372743825349744824390653773834154965129\ 2870787806143246812981241634420052936464827793183706118146799315858371396291803958687032859171\ 7934516542375471801345926969783465427077197183871984656405673047852477520133990993322869131172\ 1004553225979730621670357597437181191461262302259650321005146589819758839960825037260305555505\ 9402608531761175912455641362658383802671702205038322334861648790499548383658460848894521974965\ 5170148495767287653544296243960845500443710713673100066068793186562760555627675375751786340707\ 7591045747422932434571315585860858320532688296577116420929793007389539514619264009261160993812\ 4470550388253228296978411612795807945651722980450850065358217048815136058703518983373892720214\ 6622418314132874908698486483811117922097245272303086755016448284594106748976306463723176765369\ 1828828533496357205479185511070230118869217302684855514676944837790964316401524367323899259342\ 5861607681474442053746925025277513088276900844563316743895836543342580453362229518247843068160\ 7275172080345264980932281129152723907779610369883760539313770828266816429336366643951099588006\ 4723546867501343090883300727793628240002253608973888126681006316492545821456835505779023603646\ 5016864680941180939689703648383489619972486323194102584155191098394550910088918371467996841052\ 0033739245242562481379579122811184917260441806628869599615917489481728677688880385675300779082\ 3223412932523272140675156731737432940047358521810245404334544723352833207348895955343454612877\ 9553172049991829580057362614935228337933715354860173431067586462595813048245701165380262656374\ 4896516737243188787435581046737718236805480957905528475821602826089608794137742086000224122175\ 5164290267129782092817664271767377501049563000660901487210609567545555029226905434903996618617\ 2494755671471372832943597076792777353191458474837986581410371983585590078919153409204508142218\ 9214905571645258966958878935259169006959802111325417069819050686008698969644675385659242542830\ 5533983843460775186446614893779896316467290577441983691039505498012029504095834461643760582286\ 6794533308576373269078609121643345171315928906244074716090743889232957163115421093492787118196\ 1495428902668800424541576255674025750499406391178112525360011270748672890552755262730916026723\ 3206755259186246402019819909733429164164775124221790385957899377014133201892801073851182938155\ 6237368747824387679004937978309156485485320210129232602415995169955550669603918729190700780133\ 7831450342193699058531255450177787080067083462769784733159137782413505861505592953599103624017\ 4028212698559866327840621365339497118437631934298643959940250284417085827045571145850997464739\ 3706057992567736019615732499537013677028726319512726371640404656397617016278813427527237368318\ 1942615740976750802739354692436755602109567373587485472497333207217755715980973854471758288779\ 6804330599937632125357382756931936412872854744609453564773879865128644430638443832324700705940\ 6064621836851733128380753150793583954980030570409188522835007061948675855942882656799457048841\ 1034501433459322715191737760399884584999095886360494246076275621726210352754433647941195501877\ 1941787220172493127129735111522943288296825900601797914405088499058980728299097493046022272700\ 0635954913875656643376711172234290753976858311427646901718776851708914348568399786432066605980\ 8148124257229539918922592242777662295000564923236044370185358698236856130738976405361059514893\ 7793623848583808698596525052075709056901115724967788661004527300738202643359227906563939270093\ 5377349832708115290851612128224931664628489247751080916001646995253763866343370728959343629653\ 2143075285587903498368151914537169881917837176526081835794360969508534335635278804071312087078\ 6334456079164338626614419569917751043523385858255546867237510145756964401314985742769570367249\ 9176624007080789354555033442564447789809531550264948379837036323138553407439753558046067074051\ 5984888700988141740241862068190504277693550095271735916434155073065464880664913251012288898860\ 2909455399292380878444440824632661131731676327013874987583723893438581319781717031562539934516\ 2973739800419448772874256456319344951604590654049704029126853382991508798316073258040538658719\ 1544223464512827500770896247975005741981530348131261497729301312315643963575284222746067555348\ 2862365184498276528748161982981146645746830275903329451654134453027041961056595962414471990837\ 4529967256716496751529172353858001577017397833207605871408033606920432727226161098327198589959\ 2058989108968950232805879575201962853999707003372243840092101158429226201394705695487613987052\ 0890869306271818577334643271463142469053524211442373169127644318476038742133026763360363683955\ 0868048630171567659893774421364501667666951392777261444197917976118561169510707044749696359576\ 2201919445663766637307620293083035977596204775830201772043172417885150577178924191165555773725\ 7015021529697876438753614215166662034907382641669784128632588396119505656747615898320985435437\ 0508885020958922677285432197572020248329986941033782935777286239928124435017571024642406857003\ 7129147728348890020706960946624313396468061833701678109488746548413888240932346338698301246597\ 9326854357846632831649740755927278985637361619546200617428573496116882728951174147589437386364\ 6763102087871345963273884672777825588531297874582979684210826091623199019075698265568435114087\ 0713839272349475496866663477126853929253169788597810786684043819179303512651710499874064673869\ 1979607745639007463304435039197759049515510356830511756971816180772459428215510950040990311324\ 5552488285947073282901181296568538902785043206742431440358659089549684766409060648448177747281\ 8642045557958900958591095255785050323663405540059583215798715374440711668726328154699652123823\ 5908967085307963135666481890430484412941582698461286716893348540010058993502683525032641368067\ 1972113420930080784069633606164613503925056196371715464664599669583626251212023643961379748639\ 1925316463600624907037980655330442184967748165988167030857635232596141592036292985467186086478\ 0415567764258301148067424176711718820565660294728648083491937684474874049756825453351793075962\ 8133844400955523769684147309032354589825604994994980323178264222988021700486511302368723425856\ 3560169064228887466712127100981425745890672208936389916572061933495440516168958493719714456671\ 3420678330089688129217978124883034814171627420790798216380997423477478210131799687720476772984\ 8852104658022700039789027131224284728685353395873415148539697989079643623807123752364249559082\ 7303060743781914329048287120849545732710905930995188676419469509118816509815514901577798168188\ 0258144629964255746211368236328442463056519003741176646861013392620973676048429271434532760172\ 3681728514846544354526439324824857727490886389231837051214746709857928382588975723237504316474\ 8536662376821228597864556879594415030083421817272423060767797909813485923860691689297744830713\ 0228097074889926743115187648561120392078025522372690966404293750415819508907089419398559711174\ 5094748032911884781565925097778177991656041684174052165212295774605649704026925209709596441690\ 5824232193462970611973741651508017738239940559662702713293201981537539449174357716998654151950\ 9925507067820956457465794164649482959506949709651146388227995360650019295798627432819220243461\ 4761973451307896711436930575921656849883833598031282115034511149371495363946301473744759515253\ 4963112023697050791409134243873588004043236204714615953188199524204658643660053088725195663358\ 7609616208937439853390854578004061003600762223190226959039170865021961433425140235583599669157\ 5001417590147707537518248318253987952586900731606008981618859521455222548116796203926487312329\ 5278747212376842439037968340318700965492362544790751177343966569470616227607724553651845801861\ 8661591241593316056283618088179164942076256419240209114409137002911852500874312051671432012249\ 9491929329834580406651871222402908591310037123842554803580735792144974842744261358778966877230\ 0482404537554087909779408683860121352033465939770582604954468405288824416741094119658446330046\ 8769396559258721881034592102025792906229981765382659656383297298794220764683139562911992343823\ 0452070869787361366733673146732002171660949381533368088384096452525846316540424176279979412897\ 7116284187302349891498931019696810913967378867085230503332300549934788463747072094085182688258\ 3764902129977026444157117598370627493168153440616078436643339259292407275192787443770244806532\ 7771394915328622734565497340314770663162969325770838843633156221393973645362241920163599828143\ 9936270635237694144213456405307005584113229853421374074762079147183016018613427896906351116996\ 2951170920103001504290755218699699338292411165801527398489935595964909594771352544844094271158\ 8092005384527978048809375850798629126077971905741932259917424606305978469614581354298374926205\ 2814208651286761254240854414855979805466934656493879153744840554509535207694879178414407334985\ 4573212034906919833379071753399488455836023512529939319632621149378361354134551037854002217828\ 0842422278246786264520327122681463533671025777493736529325481974542013443392617290575311590447\ 1944675408727538830466347477598106394740660619769015940592210465984920968765650729738899184388\ 9286244560195433445790707179598768199694007670466097517730963878235651469995910424858103122338\ 4579064944122824802236450527340159517019040906619398445114641596897845404089415301791697160235\ 8902064873819656376518876163634695881714060188975126078995040340499474598873786525493807185260\ 8633515734772081451617391603299405420096065511493909887504851841414486703432591644357242810775\ 6231219371122450278490823614114117929249476165001926281066961206668048848835485175699002580231\ 9843575041772170782259008699159334210617690812051495595539762494686564076662615179288173668500\ 7794684861843715953548972424732945305628544516513550385755311776625710965844426602565443128175\ 9986716583798490940352314438793673355877697266777971964378930537076892537627362048303512588938\ 8509705240450961797874122207459094375600273122502126774173730682541957124320852167128160967959\ 6565990502490649245328063431218103243492126959708083787039986184246323004060454746764307174645\ 9921448334788616253096285046680263834387202453298292084289655267253528892165235596332514308988\ 0824199419885150918593148057867398747661650019093328216284784342636754059048416152439584733911\ 7272220390596544682972397232881501413608990330119382378887465557543590088325268730124948170237\ 0214274018863595966356765234177894968329763007680495647588787147896010016215578549990998733192\ 3855631066491035349382448904219900307265399388428673783725223057488672626914334683401581407208\ 0906399647216688054473234394092338670306089119009799965161794220825029358346527245429971392406\ 2669045566072783230516835787474944343317143616131656029923747395396358037130786620758032373046\ 4205771650232629351743141613604302330893451124436038798924416939009246168982952144986420295305\ 2122517241214956405292160595182741048643248413469134596159730411034416163980289004548028708605\ 6172701084955671342287495336099472542422871149019344903234518381065994593924143089407266616835\ 7555609438748824001950902165429349431339405629851993073996998905701289755760314722866896575634\ 4120871841186924008105407272774206152900677438960626416802423456182772684633273325606240062888\ 9207844275882457619484804643304529496221937085180879289924422797053694766501582268133200488822\ 6791181360903896453083682633022328875214783840345961653278390802099939561887816662398422609867\ 2585951371400848502455316564544951983747953027405285146391839343485882922226131806926871480369\ 2234089275364563151851232885251310994022770692117477017524449061701103770948050022765560507357\ 9887782831698927111823740840471404188317631970864072433647397411596201677546960049858195017626\ 6549605426234744849273084384434547907360803844570406537947711559970154987728677559081909142805\ 2301258406655370593398499313298983101521243458384216748645730374784648027537383562607169940839\ 9898571493336645445089114892019792210478154764293425165807931103370611191129616182886683591650\ 7298303420312982555981046137050607903420536225819841982293100307160575094358644385344719733987\ 9251815112344270674654972090499210783337602960182860213826847914742857907886098689512952387625\ 5100440755584753046921787869389043074558451742120497766499077580888330417566820491925316798966\ 2111608315732402459451712267499586385630388894400854477070068318206172749870985605530079190250\ 2914859125336639054377905355029072249933217903520502535679452900164598107258344921683530054149\ 0573608398578814809675049925669491837046350758814769806569229064969928341619071885874947044163\ 4761371255830883811090109887042758657044227083072902402051458800207679872525316551779286750429\ 9197349297795939656084452914295459544878380209471575363421317699655264755849413379901438313476\ 9350631842073504785233733664680815986854966030605117095602268690730926284817945229302265395500\ 0634254412848393294820260515354386380665423318668401230298357281010894909294202935773007574323\ 9386587870998559151713490088262445401641313508837493346755092207868543527933182080200196678679\ 7577283211815860179684989705280997176304968902737295065995856624418238978369149327749777862238\ 4093651803369589860932300127638860233801977423896100845255255746131133612766141487457307003293\ 4015664334440119091419923549465160950237611226138947909983586901832971189906930828001107681437\ 2252184259309892287105784539752479406780401099074416442171729825420850412200708783280468176220\ 1236098992894199897981044272795171901730007896524906571076281983814092399966450231291433606937\ 1486989933696965415108774077050155811805159517031103273012030852218697170131754706983694205826\ 9453102732925786372783063331524459846273521837833951219016923233255733549685488102863465349488\ 0615797112467047328417959168857953688580712624553280415371207419627684696852676008277726377834\ 0541893603800005460074586828408010447726214291757721188510215573348302031897334854958093127659\ 2805466524287897471637443375521164679176178560162877540930538657715015031426872598421758107137\ 6154500258017753500172429036572039810873012428238789406112946506724898085492576937002050101367\ 7067011346033633692030704899824387212693252318112063295410683284578174100293786132609899971595\ 7941311978437251494883612888085604785483489912574783514703933988772863328660809731888650453615\ 8713896819124967306111674486445416760006366345300249670938892673026068756693388392326883162058\ 6999641931789737343214940028203528928504533047710058035184818530315143278334106949852340259679\ 5981309249055559836802957314726404464918510487563500326046322516456525325828552475636734734482\ 0610792656718325925866341224747517810034895409268293283495007802413171986093728663607388457589\ 5870753626512490621878312029132158724764424027276701320965357997580110233541035632048854110434\ 0626599210057798750796610541260451516416529960483592227206933012702956474868934840330738222025\ 5344603633984026584609800064375434933199632942030354979891194670541638686117876346276404769901\ 7854825571318802036112241480984034651916499254680007546854484476319348454541681092704883233271\ 6744650221480250130297228235381350979947875552467661672918254425316333557176936783008682887456\ 5300123285459270714033260290710863834600839865736917337525454496292097762608497478252930330641\ 3362667063916044592060446334109962705110348878651347769109527599522422209101651100173233646236\ 9905923979724773440063560110062461640034683905620910425755262968091127078241405844660063994968\ 5509516615652324081389105822732829795660576034689746739344181662412794888898467017224698589528\ 4394370349865920717148372676799468953088600775162567832349444214283814897647149267882494355050\ 9814705780399728371431348847933472840253818459914524902929135378167400578847308844523391012033\ 4330767371494560166121779027384823297657536512203221548964378699351429193449841965277948708879\ 5656477913304483359250094261805392765773157647748047487891410264460740137521766148731674505745\ 6522953494381177770364801536492181072928649610973121881009871268850219158842033747154124813636\ 8049348759910096072060766566289688697907392688351307843387695630012357975719322191668589595286\ 0619813556779817104138293092700238310246448391121634182519397977522875182011166889134575841498\ 3950292246082578356792555461646563854504675955220355226535219395625116384113165684273672135277\ 0710310156132043890634616767056403428553666366483026105787619186629229506087233619782069148504\ 8322485091540367300776904024733579831425264915275596529417963299166088923011852095839178150588\ 2584121158222768800947231420140931635945806137281319827499624866697534955062701560256890777084\ 7012113314871414833068114603428322166434267725959041886739772770975349897059245568327254028347\ 3695916277007376415819079250060208963812713977904544807147051858374769895327420954229028346542\ 1128985958130063331875857983627152601486941273543837120669004553649953646923777447770704505958\ 9713848245991836964919859141154362095021387889656078979445172801578620102501926505200299769624\ 9166009591774179597312723118375584331273263326623860685573170974735798952246281052970466121049\ 4243427309626307960047235590031226763863346846681143187695934482712531366135435384659210344492\ 4396691971414175628144703114622799386588548498072989968929911120357138113244616432341587178578\ 6650216272033028060349642263056564409832761663798943169947406950363717937340145516747940903282\ 0564554573543260218285169980979041623493208938562875935565652042595342744002892266029980060431\ 7807277193567323972936230223306687294207098129229488558793805629461819844678417952653337011213\ 2945167164339480254641592098174685818717619485053494998236249574576549184423630959242109277843\ 3844487570524095025259710116234646366256482719406350110936811701654429307955576457737369850348\ 0184708798413606948789426629763524499007069124929125853006445152708850777677497948047868270989\ 7542505608456477358973511923108153341485061503740781885133903106631575732649392567912886293106\ 7846362536131713094721176235743829515749824752869190503342595505345223905084842380380314858008\ 4207641584777999477587668491507333005053435154736404060158540134924620509480801181729227430916\ 0460838403517474417505618975198022544449740795874084433675117910090073949876590705739098650882\ 9913612340607821193123495932381950634070786179007487970662637577655526879348976227375804873111\ 9200059870957340335582424496149927356413283070372723375416108959543048962204051017629600970889\ 4961409654528169771405739205917080611554466563807876383125521505029166162199049209739050880327\ 2427849567685488668546792773150752866352979087258260481418605958439470271224337656772744218972\ 2516707394697038335135735462043623124500608659573532435719957674135893651258794260881594953176\ 3033713289260647776267774610564565902858482729748876244026162372442647804722884974456827292237\ 6481068093896921190693546032893914120775345828633063196847882006290013835147503679654033709213\ 3878435043657928692894244169632958436895727388948696769212702516804808530926635346058023483019\ 9585198621250576401424897707234364251047252179403056378480327009406161251599995848382549764325\ 1400194995855053226933931815966355425079825758843146927074549576919751897824818885751736649739\ 7571917750792286829850649830650087632390344469516546323281037638794421174873869794985587226350\ 8774168956160420796012415562544172629388204259137848469315111899820951765445603709979891072122\ 7850526709982274851900866160413663767268403103222333682938123096683462462293148798318390991208\ 6058063282331696585921933921606831628936886095966688231845808806869638568763582387190971921806\ 4504673238329692973541288319464035294847786808002751396477728943393715431752444296469677286563\ 2030349916793519405565384807306089413159471876652047883397335697215706408062147363370594819290\ 8479640788079765034629614401129951090485554180205885434230633076355615070812590938276039664711\ 2146054256291149090369344640367160642112385581478544194815393071197659528028609005990189878299\ 1828296813552187410131879828105431271010631041130483684672495432735506371481053556151092167696\ 6730911365098357925631312694164162330864673222255942579358343151816929996096198427300257014240\ 7908199468982909769320584785517936589517449265120836267888777611180128430703853983924166561258\ 9996294313584746727225886763745542103816577654830960830171924640803345372713875925502116262332\ 3621685485174711392265010521247762461582051544479232637643591306189298309403212581489679457709\ 3595299604051913963443435581865530153930967230775914818454438528219049764768806007834968391216\ 1484039593310871962212037445981756953905148651994531118275707578557388816468655524848846481108\ 4537932132834489265591290419059535210436579649452679698567188313457178162331224807451417681688\ 2896212695107248680447513509427677215427306464348495072422799242645665415041793031076479913140\ 1313808674532025658084789202782527609588875946180710727457215045958298975359044176778707135482\ 4076830271524595545879757852633535638581496270114964786344324387136996533322881447589219340717\ 1368799767976799884599118247707308548079778816334962788906416740027096826260770012816582615823\ 6949122516173725040232063265487569895528312174774502960411734414904022611379100186779258532907\ 5778694111924770201087229248998113071232047144359596985214199400976492810488850146235822501784\ 1888971710905622789773583095459954767076884785770215576578256464084877265674170136705864459136\ 6494591333624362961583857702885383164671778403742866703815334145884726217711831963303084694272\ 3150096681174314486441192021096246391748361050177940823246674703210840279624547687785456492663\ 9533183857086281587516624211128451816073012969181494109176739463708007256287734667079363759155\ 2008785888186453809803237007697476048640752223576756317988195256410723576479874497842331611479\ 7436470965761586731468673463394426613959552086953513130509452978426593548422905588305346054282\ 7177722746921649675602817021745968482550282263861734120975844032314245645560644474407238347387\ 4608247939214201097979173560489151221083112508965437757891481794171896432441431929908246955142\ 5163599226853733303460326453785632891568188859653093596328785370740182458302174636828739827723\ 0591439555029332424339835930973738313314538586416293220260602177544513378752550679026086282463\ 0008977216805088223010213615083935567671399301459701803883621426813898343876592152070517316935\ 6023750873266021135982710985467234288055219493351162006501502793469650384802014233093120184966\ 4987207874649149307070972170584626339647862567695057980029576464760575045280923589956525753868\ 1211599249607521120587314154535201925584765181699145865768290466132044695009308425134373937314\ 5126031972696804516637519905395688083771844433520900788957137732044472756091440885064678824462\ 0222038502419927818526268293757483686929469410055349181717911736266486207588076091046345040171\ 9807029037860367769403811885972078719382968696515825062896944795196626313704889005696018065515\ 4617658496519889536280334489542570814612259355407787157150325749668472993364316703717632475099\ 5716765035309132738783835617773418847745094305474173403152297906956937297393707969466736522538\ 4514811096181734760668476708414600309669101487411275322874094358597755784225881693479364210491\ 4761669663010924294861530447208171780369509250980801399926267718449338764354849831184511425543\ 8773951280078387783407019849285801742511214533451676908714707526085319835698432189101560475591\ 1730564178750807171268911397871104297097103490788453185332073184175378862293447914146341272188\ 2862947140902850317823379134557855168446055970292453862232834360323612197622465042432797963545\ 1900558828655531956113081766605039624542337979881804078959830629372336407019961610576182242675\ 3873083057899708587464704446363297956977249500148689864802276104395950477483200134514973215774\ 7083097422231360046790972688005356267602618560824350141481533634064018794663842328245748793038\ 9300308434623240427105140630111049785681780465631470359347775306459108173981249848760130657893\ 8093973412869565154840751460486686515727724670135961196221096300342611122306755186551762583337\ 0152104421401002519590679568447663273505063400433584760229115818269890538863660338137168100035\ 4687511393482310481082581832052807867602531510088867650208447787627128782760796292230212549729\ 6735583287621245402567356081222191207827926848235294294731398784541160491477449898346206344194\ 9682817320623746897313472013060641783927177563429788852856366829731272247652468764206999967832\ 8045380616454902509834217317747502470275377424351324049077799832168192417026225916689461937541\ 5583246246526287810340182858539677502762763932038157362963861060387866469526696474811924899525\ 7620581440745686842240690916546660186684904533703632087743784800255075525328085901660882456054\ 7269462367841655710612324067018796138649550209680141352571403843391128405113913186248625294951\ 5831244726421258508776169669808624219563316838423863453486994523700693937107082508686562493191\ 4889043319244950239643884620394130421891836009921489113494200618282539495667966378351992385317\ 9060097738440358738509574389390727860441152792996855899324487576005228394759100520806720437660\ 3784902956249235723497264167057793148871509481496944340503139064843851792013978378374028282696\ 5420030475011898026790721991492382250694396681055924948797385773041434662973732779762347989479\ 6257963987054149665534023505330275907501417507329773911403456949634988445557686152565161995142\ 9947168616582758726440668123371801616687483244371444968323370884327487275588903491014269713644\ 0488259141016110918236707865285496176178426830024619418024901671626200335601631250397199613080\ 8846768224231559223338900793654597723138969173823986786968881674004011154051325176511437802572\ 1001838716176692726925532372908109144826379324496573441314157747071230493833906118439090787793\ 3890960424579405037535441426076358212928880821995806930864340191859791567132934651207471302353\ 5302539853469134438972846190720304011079882757963503255299559271570911861446363477898810292016\ 5007271067811357709957137318909429654713362548925576848307939515625298438361160898155753644293\ 2851029722027093198067859496487539243847015054194613039853119671311790056812253391283621899813\ 8523876337293698349880383770935913176165800641241795060708135880203612464358450019696469073326\ 2822721186385112876765090457755316054899969793266829874561888833562074316152683247641700548139\ 3176571743018453220881575022195005171777296387943112218560462022079945675561016243932000783029\ 8623648779617325540213831211013606638900166510090340653405376704729619810249702341560365724600\ 5664880170847939043062670721225319357033361430822232484110900718959566342442292446477506770477\ 1712846611523776774474349145991657615451475493348938034724829135922131121870190536685462470853\ 2879417775482747369680487082585938458681164118136836261217475564939002074837700994638816147402\ 8063399707241827464210804300704656456971302620797312576638094540000235694752048434635152859260\ 5276711390230361601121114442238501075642471873138850529088503670274172188384952642177583489279\ 2739553382586126666602057304931978686706353176324641676859242380506366552237996394461186458222\ 7797644699209992652353936090535630296768968263377506207449507119791526850938916389096883764898\ 3864764152096904356789114621906622908785760736644250851577028404002332086658071738318002517495\ 6867780118623806672428299479646418058768916704048368562658231371495609037428613732637778548345\ 5821973509593585038524745765962043428139211570538756302610902213029735908251185639814622932810\ 8601658706998650344776554716254097825195237828231048643644601914836853361572871937121150289178\ 8758965646998211959487117786362938358180516124998164199106432850216384720983325269753640520422\ 6778271083451653162360724501788377232548121312138823135509684238685855508390193250189603334281\ 0141593781801637618725731243362187023155889928899611541840969144438085322320427672408697594592\ 8081385642287555818490116295802307365252178117236635780621328733863229119324290910823329466465\ 5706673672594462210476400137973048383241202518943470803237308724033025688347161240325226198337\ 2508223630777936199611047988199375338723425359968758547115554108523835395245089153763453109847\ 2981327328789430327161895665238771369406686753722167235297653887792310893417711383881643790240\ 5590916607256101107929508376298099321694042008224372205992504284435382665146540084612745906060\ 9817971587268451774650597640775971395745526516800295678473604250287663906069023178026792872366\ 6058929751808809363623832201993685348417048110060065135577869607527899736454352735328334242576\ 6079785362061270228186339004378605894075921488282462273954154169740810152168043501213915797734\ 1282142419451099693591968076295314942617294898961399343857801873675169327675926519081102952358\ 2232207445836633527958164739923822186721624815629942478821724344731221223526125601428845406032\ 5179969946442702927443718498405440739240394463414693046749238814402596565112400296111608485399\ 3790748635995254727791692943232718199126865980781213091737546160742784641205028270540913242809\ 3231209908022805242805843690292102373822756856841693049116806061297688017376267598132199175445\ 2015207600602133393387384093034014659235345839534926424175521867417010513147170687773674821139\ 8260571236284279216425290556349325072392712213926511693427900448549794235985128134658265408467\ 5603381704257966907024738858562379762608224264087739978012579076767003749746775440575880604954\ 4483895185787703543371855793256582270837287649980074460238489342299454472555009902696907313399\ 2219494115859166486088018860557176476162008547524387159572061350454381865249778036231000167056\ 8331618664856705346177985479753294186450203629664470368850016985882589464316939289889968014233\ 4984558441139276048878219836228066918718716044347201371289042202568093518227655122163277203993\ 6710337786695346932390635404802626137300220104096993526985064604005780473178300091191950162145\ 7350054523021291278226898276428540123216933145368733099169701708079919565462303906100039990549\ 8698718486379820264574088258180063962262313795571143482934232320594999496169130352885217642139\ 7638783262839735733425096229112046180248737245127557818572265082742695959160849285657902904928\ 6610837821615197617994381191126772430771426331834084401024581626616093568284383776773097786613\ 6910134159240122402652047498137845485543867330205686592715155228845144611200474992681000638587\ 3223058812354433545684490898991364811767927477109923609761094982171270030109118516725544783230\ 6133585091415348499175483685622522377190471889118443523539649532411697005349418140156744115753\ 2801467972171859316727314414954439931734966533697692531809115941097579125736752255033213053859\ 3965291089361613952791348574956070590846298567499903231468769071666763476347727551782619191814\ 5814155927536454495223567842048260397343045909862349289546985335310871489562423079178435901831\ 4266659353683541087089214751208973784570075977296522123720203375210481375319293930972429438725\ 4660261558652384265043982571545955398138821456847141659729286791393627150969137569973176402251\ 7889539205717811462612318869147845152585873846431141151784224889144960119265975464249764323669\ 6098541598970949133047383653376171133587181989891599413684737559693544433719039533552981860608\ 0830716850511077868060162773188748686490159325508366863981859935366076937264548545860101989028\ 6132870011133685026596525189175302126260038456091786828447104892457412846696039366815702894363\ 3085858152579226919473194920295194527937192448644604026065381310248006785872594839978598893724\ 9099691479155744041177853024209051264465280928018240821834556843278230931181658039080790689610\ 2644683332654644119184577964187502298546219550522977463960359412092420988795854840591980869063\ 1098812351303077350313403142317333439431226345650511895461056434480775029362389498100487102139\ 6250383703798107136487823523142754487723439191357325679710361556665131056563636805426373344950\ 3653516730784523625762080685792443438633005465390297569956679658428835620404930988685807389280\ 7042007383299267559764951239344297196723135900201212971962149496571011660911954563012652396091\ 1275465277586796592158408161750614500426606205693683662884058429922749745086014282638543217908\ 3722502747178193755658800287289252095385552875950511041977852548460047638320195521113400490126\ 2294804520638616544868672277772522412889009523474821644984272677867249032204194447370561012080\ 2740511332440001058308939851812195540999068671573157744485612336375804329227679582569776437631\ 4061688000992673700945516715814988791786607577971912044101146098965067593311235664000151851344\ 1610267432374403223991872393920938914964512761891354367197706126730590023415476305768687815049\ 2072852478604042817468087651709166265241454663887668334980665340967253420587517308804161595664\ 5752523347729051520513824221820295581349764329399420793218644713551362813049192438288691287653\ 4599054771720738311313641574893815748868610743158483218055317331845119329145258357098138358824\ 9072363583168302867443787518928490148039934769031206470418734920100203199478960165406848662617\ 5925645068175079483616404639772559023160693124810687859484702964803219724383064593027882770401\ 9985170894441992459040344445155042828325903489580595521722921353938731257593224607076715458979\ 4566798128601179435611979063190237774295494920593888027570584711429431975725949109652379858233\ 4287298608868016468442552363078842379894167901996799244225119307176838350153127725957916124840\ 9620899148243640054765699181172098036531044933982883019677734872490906844448393047817968723346\ 9297168914926024522623761883833993416095826599662015226633005723738716737597053223170417359541\ 6997800182295560617234999482934698267250961572390474757873193558340108319396973984617795946113\ 5581131599805592528695882827243747652823385639413868268134333822874877883424573187065523544506\ 5084075486888210564483615234795873844425750276938214616861166082412719084636261481631187669270\ 5085645657538397656223804668306906176909391245036572251137006801489199834473803071819182900525\ 9790806531734434840119621141206642919678593509867247886611746188538394090823056939341773240257\ 1965209268709669070543920985440159528057128750069873837067144091378647484276571950442537939356\ 2123421620128162102556969619457285790442692177983039202194167348216218958467645197542778198859\ 7381547309913823703752350447025801263644914450804934066162620227357759903024120509462478996224\ 1972395422643905157487856499487120876191409108840817790405945958828768753254817292440871624949\ 3621067902336986030587420647824610681996050495814143093649569656800957184389317279780090660672\ 5867947102176590509519920075633175131512310240178367948000669853020875900981968258265306080467\ 5882807593866070058901783247148331635503793945200868349251437720585280780129936914694791092478\ 2168552134403373675867721303028955151935430175594644594262215724507861498951242351326640990707\ 1768030004545567205922929366548687476007437956411079884241922545315735853594854143198234505586\ 0004133775832207032423375307512189425512914621689095597449974226074263446760503775895331593321\ 4788082459483312383883019564634170186813859288299210961311438857218186636868081671131338791039\ 4441580683869771465869651696900282183259774777352150453533214530346265832102172453357879116076\ 4623641973185174482679211103637371860922654674784904848932790105483295736982620066699202848264\ 8262043914013259803369455912288206806181943711737433329797449525544968984602841571880712549938\ 2737814829675357104538305357219522931069214493598673882993172461999229347098550470895780362583\ 3089215564155575082986261648462189038235929237640860130663546243488331784324824434809981898453\ 0519604918305585001151495204640732592151391813579150381466025871342992458350649851161769344010\ 9155911441211393924664839892588616139035917171929636153348013924345234804227074945209911525706\ 7854641431239490633950702827203207010628448918109337346553525902926499024018823229875175403592\ 1935742510931130214464690528808571435174715692857528068547411965343600470542365808132226498434\ 6339347601125308986876517814996694193066292481579380622445568920586299035554921376032731022485\ 1887219977643485401757961514491940780803929148872609041004062880579441901142559392479565141644\ 8951928365502885534182850040300882979120661823316927761432816630647319746223764029356569643453\ 1332624079262653178565091194516925926667805743474577230331828085885701513370716728837315659774\ 2790316740870115172759033323359318198337210756240641673254587616504087508921338758780554740838\ 1924125956411447051381234029043149992311787921432958452122604462926111387777424934855563914553\ 0453086545936304507046471456291849640284372109939651152349882422589769545522648765371870529616\ 8216814027972009392221801475945554634355152985919701141961837021503186282824839106025566247002\ 3984358921175809400759605153631953861208173038712598920374051041238816761653549171884977427938\ 0544905803014358713199944553262954786363717169664791099466363994527774962668391371006028229443\ 4844860441937095937299429472350757670151708156311328754793832297639515313061726117465756275554\ 8044538288493473799205495598301580026822291273844986159162424082216136723316432761086033581250\ 6204994434791522034844655129574205105644113894815126264610668207806354712774508791745840908566\ 6193203231393723394398701824555085476434695140531222077752774780947723294216790187513633598336\ 1482571520638783976314390323014628009749576071266530482269609767607975235264745021687427357438\ 1821884012600140171370457207762678976501163103645533791532970909085517418723922297913868531219\ 1390047048532857930917800935891989652213905622505474522478543963833385673807921769139249452517\ 3359988808166177346325686347107433730873594465490102885622873615466255780129537473629350037302\ 9214902601404955785122255689663427766063954286582822842076090638034668731110632297445929990001\ 9941365065182376294555661281068946048305582336901275829593519559740750041453225316342146160939\ 6493096539745659775283337707481743985355781106034096864348901546209139695838621085203680947629\ 2069346004696643548293199729281892210957014200071851129919094025848667908456432293531682407186\ 5425099707857269993043454932043190559140496755743425796981129630348066122809691102179330772498\ 9191184662184479681568394179274650855619793148769934489549077930858635496454570963127237918214\ 0039234712243496680058957231378966400928274075097132024278032710948976248139949661411589349909\ 0509878321713115086395183372957892960409070628183459763229092107663245921750772054478741239409\ 9049032719166392788363817570202172665063736319945968967872522398530618465994153850690821065818\ 2929144867489194806235295451276965298835834428508243358285856224240032361582125286073609122483\ 0115151801566519346630330444394732021059205156051753311111063507527489620571998361117494745267\ 1850577364472812746205824961949926010141494371450194588189495461376161518122942068044261081846\ 9799978911988696139576702295690413742900842429897896516698271588751505368437088639448058932903\ 6355288981643811061733008325257503971262070158566232684253580311009700704893972651587242350243\ 3249401373302620030850223492399820087380524851385764764150477369071309267008102499183756208684\ 8409213128845002275192215088000943815249929295753840380809515118889557159020876024995584924975\ 6675597580405231695034697963151712636764571613628715782666626008595027918647328249104013479547\ 4507807451911826001856045740302283727605410798106574606068892415627927975946538510265597774631\ 8990471233993139820027825437645852000919887926050065639510246449684067948743302628437511476123\ 2383356794649686924327448389713717815664809428360803905051963982504391750492115418247772134574\ 0358429371974371991147784807092823466398039592509839714446435835120592024001723700419687438211\ 3256163633792357122303751615401580133009948750610788096129218851519467854075046954619573620533\ 1510478101977847242325742641907594350666006049280811250913876130089442670300023981499689318031\ 5420984125639559552741992537149033484116519745729931743859697331890149010996564267904073890660\ 6996284456838755669489986005466513908759794650306387855375664313131120457058882885687024351860\ 3295751247164668496643315213006778092914447842623432046719639629807009777932578685365769735936\ 7891065838006910245893387381132995079286044198559282940503428769543248358595524186576685321963\ 1951078227565867590391168123841098598933850960790988991331881239711546005991601635525377052252\ 6589635879072037515757318362517158865162004959390368821071388719989390118643020459535601917218\ 1615212330379023417394025354291367787425753387940045144200121089455986329913518849836833757276\ 9659809609949863936328894451684870592103412180565644265406412900607985351088108493808891856295\ 6762575225455954085212367395588287899162303872747921135291106886259980037642692784287333247854\ 8360665271187841341880350910426344877993280768678238324728788972197816338161942687647486930208\ 4207919755458358237355333061203977414522186800390889284871632798735652191095498967609694710267\ 2050827856097058842360466994444981788843570143206149522585772908482293575177902575020525236647\ 6052518465817275375224321182829677628766150002140090834958635508626065298752537899692475738519\ 4366951451559354203645842016256127559237055548674416684704932221778079426051541904454950962662\ 3093446432729114684414060238617056838548073082793297558420574772845540530354381765053117251042\ 1526557681995297377816200945804562572963252505872184536721210492990448209140549589379627537139\ 2511932386307090853673974943038072632677312509224371028077596555297904691670586822584538286481\ 0682535386093482074834759745524612468434291799166234932277028353611808153879691727335591037282\ 1571645937069621265400458413675291858272631307642217261716656843818602400001208285806923978084\ 8554121828323464767103546503223846968603642699320965519119844245249548943735971125864419390679\ 8120944760555648690323405900530653953578443171516294351283024986431346012365002248296955176475\ 1888564572547888189074819215254303879903753815472273878869651479069833030953783088724982292287\ 2673686052831762445133872133786448414011346654136979094129944894050901939402405990096745792818\ 6464003486115166893009432057185471323141441638136136361461262331705302946410042986023175080123\ 1413228685054652717172076803520093571358152989843507156123179975067028304234245416202184017874\ 7355960208412972227635863758386152312751112054257779333178387205352733002966948183385520308249\ 8145848944933119639390631819376026985529989008172867694751328812468796862337301408128136770553\ 7144944830456128083365444909674406758460974453139194165594197315287502397994939910340569957695\ 3098495345717400912468492141125826344310992649643516754183616558540773002067990656636891737194\ 7188113946026251243003661771721945359228863981844767045212407324718122884658588130762140626950\ 4763356915093772180200760001412534886471342351447626602092943750788745612645660934465723247181\ 5889888446976532324732780535647054762434750271998924560774653468523287747650681425323678917747\ 7395249175758950430112560845701474458080373461644119062558433537139470755421021623715433529195\ 7293621428936446631616821357317021345514580818848575916331860295559198559371507079044721771891\ 4135049515746809803625155291242056562717714318802390943367668278652285943892511027343875104794\ 3649821239010870906453003239860400811875484723606533850746880774190185493433072694898813458186\ 4363879932133609460507494414336228915681156896488406176879189397415164304323220730984600543884\ 5739136663710641161480008334101646483262301388965130212703512019667898311140370738100817173683\ 8554972043325585254814603700145728843104328420190345098956483600625456599916031716333314349635\ 9259190417928470912671295025469781191560807408795201431499736653288341393590356735998258878104\ 1937098004311116907850673643031859206526480256652409192202817222720115094438097656644449736164\ 6847713363219255965364618602573171164529136652972355580277080126193152758872840802993572221047\ 1871633180479413136565660773584528635636625559870033399362215409019519180105320347840628486987\ 4155955181197397143578356250456351470198017325270684525919854368396083490357392577686502253642\ 1474515086570946637798894574838610550905081620079977902005151151591227268631374583192249469945\ 8904875065172504985668965092961647846309098959939850181450180374169843096895460956168600751102\ 7880857626540384295738689705393314412553164697749763218897643247533494520677665128413675348860\ 9492854398855165057491003123114059143266466533135509753209377699429094946397945050939753049271\ 9672462478207963255568242416045984100883085363792799416538799924300725470190015491502540176663\ 4498996889721624074298542650866430942951769853353953981430527752022388265108831491970974459766\ 3081637389192399465096477166334217943812377819392508001744743227743017159394742062651085011119\ 3371727967862428825170180829399227909620201291866482463191910833191309844660492262931880337599\ 6688932233338394559081804471412749562789961814838365029812376526379257443650251590430114508773\ 5448994069137779753428803301078612133361430227226427049238548633495199279187288674458826941175\ 1738272642560498090470045245290141882105712757346900307419296361130877059031796363647437794928\ 1472056794119987537395914841982285698769717347381976963180873588848921322694654158519834913268\ 7970773747757172045112200117643571776310854974168009434246946042715302833695685018187109733921\ 4879372229617356727996034544836042277071909502976727522187149391503011217842711687110439117039\ 2833842903347191770970464245923227137344945118009715859019373053441824206553546361308469311071\ 8749615182570674262776067220319955403576516061512067431633230110210094617246247538716736331354\ 0307867877398258031464744720761770307046894203664475719331552754520117918225618174665074689719\ 7928370826363794543269118135996402264893083668077430041660127797291899606814438858489582841446\ 6353935742056151505139960532747065140454862096984177405268053328767847924221249050697677132018\ 7066265033696620123450892224283284118582791406317640310559851781900420326056964339383062899621\ 3914070255861176935975095451174666548402541961431050082559987709834939519605001377881837309302\ 6421466368472954535823161210344437622575827782196838150170288828113465448017696538444131633809\ 1889710175979666332799557505558527967426789271458063582483163872505098301721040790239608458461\ 1917665839759045123588546497596640106306434616553720693554601724926050768296302190602317185953\ 1287298764627202280710973232675598530060439724904110840846713419939075812977392141961992209731\ 8087747495822335178324375306904142880705273718978041432299268481062412292922056594963539749450\ 5024863777475742865435782910886196932286865540351235378472179067835418134035968427018182180309\ 1492416007790991971163581409366997656406618836639051563494134709112031106058250505994636544874\ 4104711028598122598643228148403795189972121842038804343658896836991426695908231955249395900402\ 9807039435024380302323977382730639802202506309564334609630133190189745659541447844321808671304\ 1025797405221101621289392536403630813480208933925875885588978890988620366203699994941832728521\ 4611017297310413690917513827893050363175631422219996407228497731738258166314789683872307569810\ 0247993094639365759717500830229958035800180308865161576758989898891543327700904768610491006627\ 3267879463692486152123638571606026280528425381581604129936782602899944137471298138116595691527\ 5974110460298777132802561263142838202512035074576177362459607766948919032685496377001648295400\ 7802802559740148391612850780743879000125305957620425053387116561368758119013489859110354361011\ 5448390518084798135703318141575497057526858268201004319982661534584221832684334406865194697531\ 9592029125137495057397249911528970438001288026605865053436501322537486370234736030721965683276\ 3734545704525376689277225805344573880730146335756201474081350988945330496698386962423309192934\ 6219702114760907980432285322499895163226710920446211255173731761993205376961214055787390314563\ 1789790049810437521864186406967701776796980883517979400479221585414355197346881179710459623897\ 4607337606329054461015115991906875175222713173982759939156645420658865976284184599475029117220\ 3920969709141598050167329201008695847990137940535242117572838634286966350706623964406271548086\ 3248957821859582480057322174585209850598308610194468049217531174581611997293715597981145274940\ 3847926031186817383026012590285001841235056271732645808147720050005717313464903406540657529481\ 3143818051821625303357051475042919091492634182475786889836069055969514917101609645272626922112\ 6352905032789593632635684539360907840983621981953239680332759473066358346362346213636297424541\ 8771109299227728075089776524573819875408483311918122781932999485804532840853536143113265958560\ 3515695739722597881556097104935300444840455818134669247184505206407938428239820637926784660449\ 7374778660137665141375943957406037161305842631561566657656739090948864341968375759250804680878\ 4995320367748810256897123689359128361645349228342808162904006258247204560688966477883284360987\ 7204426500218418960501124413367304203331312730909438844567215076844419975953417074091755852734\ 5637626016457944006785474845243537956679407937682174214394551097216828183370512745109035663163\ 5715109290791715402491331476059214810214884888245005394362658036005631539430856638381659258968\ 2246786146095408443140394830705764728138743306601935238188484921903032098859224346541732761514\ 9717896277824529006161548964383240880853352666964022902175719799156886918572440742312760345994\ 2202117240195271386859024425042282488078281777890786540402806315607611469697574974614546964176\ 1372925910752837017388261072416111070283888828520175425952552753335825594592052124940810399871\ 5788853065414555153977099399402039771336838002653692131088427511581602231247902569456919489102\ 0655780443042684944006694246727183579948786489975637685842331719515241993904724729127498778698\ 0595697629080212743126211169282825806792923862664142594666441691825293398417761356921917170632\ 9791607628511783361855082901503625017275479257951507644603496948199693593100072836970388722813\ 3181809700023638213979270635965981189240694950773592286418662422728621886763052064810433688596\ 4938611037063052604917014953854396255005586660625762648565578946762130393238893876132139212174\ 0973541895497333644410980090835676795382239584509572922448288598901510848779792847482174213744\ 6223318749967462686504848131275693524645791744473404690218741534188278988126368935547906377900\ 1704755034512670192296065645372455734115746405096974969882782542508828239978021474000938896691\ 5325203823208334567963389969769650347930274677437321663238765665743472184984085352937439088039\ 5581087318106119239467769333827636205691201859553447523375869153500711505112498841051683215491\ 7306971685014730624202787067504536957752184866916212541929575988792575820978987369883261989593\ 8191233229397002594160602799593032518106829101178593037049754759106000974560529481280539113549\ 4708290733415775014543339062326188673629283700645987131806725581478186420461646341232522650649\ 2079296974070719167706342198570135980346273306126065926671237927640284890385809945205421947746\ 7161395037972570956285849528005859933049277795951586138505537688100941738667035720607787024553\ 7917755789791957071260441871476992678913284395966581863669787878409667652544266634613950430153\ 1918657272704947693323080800008981240099517868381170493790625382226836198716919522053910000849\ 7696506010768131792356686344344079450501021718218744023221591210471946104324850213351590285211\ 1893788478046375980944204424415655477208129791705329927358041642861148910715023206134473651298\ 5256780955593364370835119917924094122293470618422633607936066475180071071034219429608499726623\ 8798123735271931171335112538734487786863187966248955329506478210013526566606108409962137316561\ 6297737515267345783043234123840142713721608454393575754180632527635323015718654111935671375011\ 7294217867156679405210047901054508537257194588478163664180810144010169992740169971888080721779\ 6467551674298360471081710081502800926816369378936828259440492839519817953354992895349145273196\ 6363495546623891551930644473147316376473247105573136418593536372446809477260295951191556395264\ 4103518317561593405612600203804816694600989746543801640597435619792812253753222331435714975163\ 1031416853822383438592617310767014705924132829394247650011741393992604392074197612023308681502\ 5012128456695882182495873465022440334681632874069643483284584661489933637374449296351859426006\ 8128281557523243345601892378533043627239433656051599880792668467811463865340696877799554583740\ 0355856157638600139702700036684855568654781394550612797248394531636486170144854262647587843208\ 7420929178677185265538154804831632579320337100557194700062023633159000050181197735279377196428\ 0104126828824791861864777076863544643205292907090691611575981463036848359757349497778556758821\ 1608516067425422922064437526996909439982832387752733930356945946672011724034550436520190893764\ 7545121665621234214474886720563085858428270189815085390191384984971221834449318998313788178339\ 1064182797637248849658907498267975620918927208742938869653253603029585211792318078071950897429\ 7247476744201399240796816475817432575315019086951708332505805206986835647997429839195540563017\ 4539691695193114024340173621715248194121280752963887480351231272602559959325029399459027938752\ 1412260228904407442017349893838191410782321418693249480460564361908029368133121495731695621251\ 0231832229216270998396635784945370494246215954520076816553328177603312871302355583304494096910\ 2607991825854302137146926749950839625167281983125686239163785013664207300134129801337588342702\ 4660479260639700947565994315951737792883408687624513115362946778899771392668894334812308201887\ 7626833171119356332350529907095444028164130841410277388876696667114117538153144045465846396512\ 4953366950638573339112293085029890340753590433710226936488646804977666602954016628016340358204\ 7816698608592102496924818251853115287756659220639816421918665272274267162992762658907507896878\ 0306421501292519411359844864420274996265155539967027384082111296760887643620963287520878891637\ 7135457972171827372739716473103266087834371960660234281541527321340843647712672741055313568424\ 9828632356948094263819057271331084409220911136999971292109304800370187439372812857667373150802\ 0942492800536334144791314326945624840801171863587772330125418273739181408539611309715689410001\ 6369435687284376552000175739433846375788382832803050502926534503475559314643008790355702258159\ 5440718065017810841579814987420489477811197119452351741900958278439004011926289620372043374861\ 3019812720574684286660413280817316619335034217661447784598512386831197733979600280894873419024\ 8699915711758082628442214832197679800773470311318318762497050328196832151424180501706757479598\ 8217652354679669540127073340169946086279772599135073417282652965718114605054634998500111918289\ 2829340976899578677581073561439178998205340373471321135717781240668844068968646685340334826787\ 4230159654699845679538117482641645190088813321619965645760101211583965661009203971551369741110\ 4837092728812358498740158773280014216611866649833695518457940208094349113966638106528435722126\ 8653953218639549077485849055913350273152131513219862275647597182329938565268132815326804582726\ 6492458133333772102110856345655778426491164547799018051484099155060276318866120854103602461146\ 0490024162873171433891172140698489771521710213112135231966577502078587610385823692357692475136\ 1518822933755933408003262501534334918441861062204098995802247289534281697518370655952914192014\ 8026463338891233383944766438276431374069112481312473864498388003947894233594739683614479339165\ 6958468681085849834208421121308674136060749520829678471791269177646487015740475539179849297045\ 5138750005711129004157395655379421467410748171814862956836981684141020574856211816136504202716\ 7479134131604151478198960934879900878723775337172893696223743911631399442483191395270984874349\ 5836572004321463087298189507280438620566674441650988719338655968552382079731443962719665063698\ 7512500868321275754957568645366376401902464304141674717840099507900624069250241844024834858665\ 5241002540622447391174037425795988951545824625097433608485301262774346233910374112233483973726\ 2955967926772527559259713611634773941579683295187195760209820484315014205670615011276125108381\ 4323792416914889453013481253320682153793983887110232202070782749032706594501529969792565145156\ 0924952034281255638216196753594593047103889784280937810749893285588141526904505340579840763331\ 6602644371846323580490195572163486761698233434070615102965297976162794855529813192972686550699\ 4520516304941960756530694866783109969876740907906143657406041048960128536556251011528870078105\ 2609978968917260051833331348477045137802642964842835040146960682425898885383583837607301749401\ 1816584567282835335475642761999387873263985683043269256080060544488220035059816041395149296917\ 5607504098985898189661868316832411125846431501975072884977858616776751435750134385514372982209\ 4840909693356146791277507441003739968271107917187613285694798490377334681588979023658277003652\ 4117518760860633736018048507279176809560750388898701879534530023810250756613059334528442053379\ 8537485152139833785670901429765770825042373587383081793880458699078540227075362965035425944487\ 1832900738222857600267661633463252791462103875118244601181915973018631961288090755374452735918\ 4015584238452139713253108262619839724565555024681618687082369256269848945025526503934556242772\ 8027059122540077674459482341589724049792787830623614629306836657368703129202218279265345806717\ 3435098521991715257730492408091727368474325704765180052261637466427245922162215279197234361178\ 6404259603882515242014356306590882934595689416640787171388262244036494292512049209427139143115\ 8990072464738319871636802270373552567746015843064156939610409101168530510344654817155496201054\ 2846678374563586734661923387572647245411488405273443453901403848233208306120947847831918094112\ 7414919636461286897556955963773115727702918636911837461314198484005928822580196471808621095701\ 8738985930278131100520672167745802252096829897772402474725434603922196811470414472085367928293\ 0077061814696176399584337738913713638850538614061857431021305831392577444751511283602441313267\ 1097631461266710744828276159826122541435584651446614126886627663521289380608693178717545773898\ 9426271436471368271764229479367927489166933920688057912995440259502908698306956907469147353079\ 0889767951994011769677597238294745923961443018091345363944766620207869279316153644319911863221\ 1214277186062914022915091871721344992655498585420631828654077641836615956878306961973901605315\ 5919369276147339757650673743272800901222965735236633336734190762075929677734651681897305711050\ 9599830767980554164634713048600800167072848014510472076435803326300307343707516934937024587523\ 4583977944742408648667308620919367854617688095426846083390226576517827032238819711222544220913\ 7851229181585245000811806016255014674029287473818919540743774571190069116165718614886672000149\ 0859094754623753776648769947343840069733454950203624068395051722344689409640205739164511200765\ 4058979693996723830244416997713389822653651092199264368150149129036202410476298364791847379455\ 7964760750254272117342450601191798909007137506185631626909048821478229140695871664427352389625\ 0445969979121683938646889746107996552586110862937169929403471716092322010515768864437360881528\ 8629407037689459033858162882122982775759759097186957241988371616773772562822883514023684432094\ 5184082454562937796656912579621918781949228764738980982415377990631519001695017287735589099529\ 9294433803977623462052248159741371516618400119460959491932068918676938461191864072120240460058\ 7018798844418348342357132968083377162981602292665070516344600012809800648621387435837199878314\ 2286123149805794460403752402477497203757208961464418050097658481257171218596732101074737215090\ 4390796677648937306855808719311730869769755206007908562867965459090930690925731647798053012152\ 6244478604927706394376113421274091422067990864737642184660279959932375381535182498809293981278\ 2816535076990381378579326177538182236466724409357381152322333875507628749737454399729154519022\ 5451619761114537245133179148350840178268538348378859541168452643734928792759437025711088769789\ 2770544939048956794669701647798706524094423062847956245403981563421603790649731341279615270036\ 8105931263440865935960310081122714106713720728412402283945649093948124279513105050162504408701\ 9254915626735417628291225358349011054140747852936674531014522038053704012726285651943277917933\ 4322484544865061100017699949620432432890853201027260838615324704592631736100146378111706964059\ 1036673188871648093668565033935043723189380805130679372027520444890896841835905949042404649872\ 4677609716912134569532243204549383951716075095127335830315795734105878150895381957484631670966\ 1774708783002486785941501142196555674433287702901389514508949189445569530755059911576192654158\ 4759868007902384447522107606121879909612371536431446832043037680013487303712059873974158001773\ 6896958017819277038344526397652332958941794750190128117551373274139995887429365958544358007529\ 5775796871420250998103517666131870134481938400726325159691945844367917666053289428333380371302\ 4668832721703049866956825201230844460045121480897181334411665245277889652676149655857969935623\ 8985678890377010921520541609868372101807280382069818105246590621321133371492947235217095013299\ 5293027346883077036358099531700994392713985255116295855638000478689999596495790294295067532589\ 1807291255845311489190487066195292005530331576363018988119790193067568641471240208819607776982\ 0151892172585177962264141996628888685995474689736396857510511539040646715447861104379403418424\ 3333432448511760265175747917391381722455689246608280311673484121607958685224990524191688269174\ 7012473057024229850299559329354248196614394981134147003445324554531385952952368630656738081074\ 1581273095563885941109667525612303322382579816597895918101279633408284308038142564091746212409\ 9183983820967816093635848779941865881715463474409943229871060956132524975739384015097472056863\ 9793535604829931210444847355608444835540701040764135505449799386238629203371657656150295953836\ 8007543404970266403521724749732894255027781887486453096368268544740877577384005385500743085266\ 8721639560277170350233233709555132109043842307775902914025107320593004551861461703383427007512\ 8488497675362287845488395406761420168580571185532067373628834776284758540929821644525603486362\ 9059381816666143485248807808472935945860341364074390684155344800641391342297222455400383615079\ 7901297227461403328594511717623293863611746646545998924037683256775333331958168103575318873433\ 9768750540729901157727124669724516059468944557619231709415728802149289114524217276867144671193\ 9702255038279259246538060824012827980029090744751990952671273773637342791337696459178682768339\ 5652921684241510642702239598893737431990926065103685274026861442842919670601942608032727463452\ 7376775090969642362816209735757420818050073160241698275770736142854826923051250871300735323274\ 6569372652919466359855911993630343820565840471599282717060957028797421044162064951930829969462\ 9022018730062135090470525141153587448115314754837336560894281668761268554763032211976228691393\ 9166865608086381627563858800878338475029937566966382689031148132010934491341821904554067754327\ 6800582916115109910881802577350508642396280546992312371109691174940956330182349138668448678084\ 6579829732922597732292673951865282383111832586851276010972784883080626350225669618663760887604\ 3326824758301357668061608427014010057184920258240895345077803252222413865347006812988536798196\ 1918163818133315120280472254086595696317732603456304561080928978381634667182620432178991847388\ 5554840693871583350027530753422433281227387418697324958621752964169237207512243170352517259221\ 4499448813749374278581242357351842603598130972324786532269940932122971024756257733310905196593\ 1837885950761163644342922503689276531516017730466147390786524388711170915327753954027784989460\ 3611397536779620442238178263929093520132209708532208847080169261086520649928117263353686685181\ 3156749695436609068615821298261467471730304298304888293670152025781359885239728115045959862695\ 1308309218574724571447328613641996903916787606844261603409896641174258689396291090515656359201\ 2044000707318525607786841263592215414848407327630271031577751491397028586485105077359204110687\ 9616584594932362215023778864599146674586972550203451316973058842397633791219557802998091649134\ 6705626963100044125108293390183694587369907753527113099490011380791171275553072652179733357349\ 7139836960972351932210965799537098514030675836400809573837889098559389970817207990908025742666\ 7899201952970669440789315659801635433907695245057705652657675322265383153915494296629171209511\ 7748040881472872785149133625832666585602252202450702631301524005248297169198136297772876493348\ 7958577054592217339614177487059019369076037948708350459568302651704589388472642836444151360697\ 2129199607349423293899031756069074888587299489815491858818746331543849591423095705968159380062\ 5444687812365716838587986729108131488027106054259321035605909809745371580204502594914525916294\ 2954627339988509636574145874963251193920715577845432367258607316658752251906611062078787852756\ 8220490859434092115879822636863099010417641779944161670440968814902978673743541790021448100480\ 8224198739359578141100835582867958126978187576985285924016925567599159158919698481559762823375\ 5652734016285069423013268866506386079796655126650435316734224623083526084000875611917170987580\ 4098227782413991033894520865429180873275706243655638921402064209746035655026715410994835401648\ 1011134050035727824405715560181688406985817888069106458047301727836502193999656762031061020509\ 7150120514973985167856414495828760623921640037976627431628971244377824207624830398945391479163\ 1208676088914778754288986197236123185771573523086132439830372908224258275397665339366077477324\ 7527555515065998351838091905030382372591484640762060595338131127560909048618902310918413742237\ 8991872531499707102663464475330258027470846975731795918825871159240313273573339937481512199679\ 7233737866449047314373789036743546688338373904792577376925507717358918941335562356802304677958\ 4706774876120220220307117175481783956971218089787419535738980479855051567323266961895599057331\ 6540479450273040155431873112961216648693114612606817642747417484422227203792639048737462481423\ 9301032855642648636462184103966283658908009297878465351754990097180205722523594674730975843127\ 2499696622519369754798965623215244825059690554912939468449199156770097451514708850975704225925\ 8262819754654647141008496842455022194098372017925119962217294845618984178204307231840822500363\ 0296788996191952561851064622642118583580053949372068280129978742306491599551363246467060796879\ 0707822715041601849927280081444611967862044431006614190171251353239366601796241038667679533540\ 5442464113871391815228742992861264648503203377452210320315166847540112451219168937781912239235\ 4462434256636813486331250481577690002634794454238014065021389489401367633314722119079701074069\ 7877051036334673475764907527733048457488462833689568557831902679878315533366518476223879784761\ 1318245968154502460799877876289345984829277581925757566646812694198618928121728451746991976248\ 2040863329468581242055572132941887594291395100055929527640001470059356923583741616831613525724\ 5068692311415117028885848810560533562491679796511759409835905106891260584391475540807107164166\ 5783526870606618208283185268486499608744936437030617164584770353236721783763714492278264367277\ 0948831087642941085547964750247908056503780120736095744563312452005099739064364012225891460166\ 2445707926083204245861201348482774665662804432775826481889633984652427813654894939951589419693\ 1244861286361192828126320157370223713418210888403281016745134461545757135250333939731791575082\ 1981554195068174640975602759688757212846245392112088698848796666303268628163404065420000340761\ 8490714298239634723407605965585150275655245223846155227374980338700654609121051734516371003536\ 4256565273504917095521415359686556515893632113086095278870214363738319568053326068837537989121\ 8904048053113669003622921078729190248881874360035665171211524419243290059480929550053689059906\ 4510736501368057922127964851819974381175855134928157808171965938963443280554015790175692190200\ 3064229202723516444479944222009337865086077136299537349226287570791281942149766073141112092669\ 4659693946096494916804213464658783104811533494471610327624661331017961729923981150296303649248\ 4234095874565806126158812582235585880932574741424757090882459150295582326490718086562624883382\ 7371707994909345398342353184024035309192702724347144644981547382507221493442034492287093850807\ 8123410666208602445739324852688120896845046534480700073210855019020505093211955283345908508910\ 2103673707385993826441495554650186923944688318870655489098734628059282162309266072010241800824\ 0469632770816400932793167858974996767491282676559107376116150075781801259167267581921861729803\ 6460126467559334109291371877080163312544834939976047738291996889339242615132855733136548755302\ 7273054073223336643813226442538620075425080604922119349766854799993465536645912079050228255881\ 4844896950409882897259391931489785132787695910050398950978451207035431782897628049631624300018\ 3477430487777490527864078494591298449286772077415563973594049090005733844590240075902940562166\ 3344116380855381594681428167040614388760423409848293858573267007098598652113189101596217782212\ 0569549874415249635569541807234812079452145424488280057598841473004785004932135114761696589843\ 6870788246160583690832918068814277810737423369932956641329485960400758221369257703456287483065\ 5124688974931626092193309531789559341596280803857641244455470667231489460462436142793746942642\ 9708372730396762511010419200628444174542703776362926793825197898183371647296015815448246325882\ 8993935022080895686300670777271264672916182562035890949284302984589269083475588990926376957476\ 7047749834667039834796206122537550006596373084032351113122983591640376775525335229067739616984\ 4316189486374996294382199761594826175763871294883722119806281966674013190309651909183408702928\ 3286928547291248473769347061469842929211133735684290381468228051405772730986620424271757188628\ 2497919421299082067672520832273408361500086441343852102047742989476714278320317865147857782488\ 9624064358418272294382131787182594521734557498875537247458623885807512389228445748128442965646\ 8208643609183004604173992572865334926489512010654769848746201695467337725310787137711812104176\ 7607753324142223616646377092358654067676415839330689527843291393739866945615587932809668265613\ 3181014798937856577822055929031794162517909943604647086120617964521863851021892213580653123677\ 2887188658761457320862438210958410750078475557579212469342460903022417343328675486455795113151\ 0847712178951579975143586328626892574121706397876681049972672424159903072538280702855452213820\ 3418288880663748179762115077746588794273471593507327095610812290429618592419377853400041153724\ 6652734273980775750680500755807010366432160845438613429557602043773121190537681358760560701102\ 4486129542757589067755542541630198149444074700546528605736526635698405156853035728272698368403\ 7754460068302977739127713061296458419233654033855809158441118208972551765229145067809752904707\ 3150656760522547489632075788148326775628052399005640817992608644759524405229141756792804173965\ 7258845044102772298677607462864740671933300218331027672685875061835936744941881226992357450298\ 6291120442648851014895988160204210170681723363100506415050793509442747119739830089414932995100\ 4857323658970356500562770458224437040597425516908945394708136572875830713318523944424731781561\ 2407915770084054052282029783518784924829792470986599702346535940142525442400949213659443395218\ 7264178820915578917770921376547111902750988126721239264842855437472940548144160961083774713887\ 5635941318526988484023697798201272232301304652026136240377846119478491206203902709883163081933\ 8853183969037306611035937917040471195781548271952217194176257567456581258411192327277302567186\ 5600958158615196312546699457644706441578820250229497059470634652072855286195767061105822177209\ 8877684912474640272633350294945414713172775534216244052719120577014764742624095202242467412368\ 6716972273219419732553876094027767015265492133704650119390106133182984209830946853160177964577\ 9455052723181034056217071759888255070224800444551763397208610044628354305375169818501396437603\ 3788327131372646802812161578680817248269070065919788548989680499579711256472093901939124508528\ 9051945974225077170786178586406465985719381270655765746300702164918203354340204400221481388769\ 5067338175365336917496329622449986933440993877645599040144932219638670029793626313992625878305\ 0835795526097347340707499077236281486174379316028018897662280422291937000762808815165902552472\ 3843428607868512608291487690768616898350682635888550285317559170645348535524128335959674538372\ 0849814197400106318734422341721868848020895996939024783448248220627633129885315238933279167926\ 1339838362757835866040372616041843649904664556857417816614800862758469277388852167986627045400\ 9602817127861115621200737425584838824134918443472127063318845138851332993167781444286866639632\ 7719065889506533538833586451125603640709691457528191881531370529020490469091813512447923878467\ 7605654163416744784533029147310501093048863356579849948283656642091764908180456073958761228412\ 4721239459437341355485396449830462419941730297575276588037854374227451662328515907608869176412\ 0955283685443742860963310216204853095113829651893791603295881749485398652467572317134840527660\ 7844177301984722780661787116499777668321919828009335698025001658697190291160728931630285029141\ 4879506511682417913140102498265303163799634544300573448912860374149994128218670302642461799656\ 3975931375399024383387040517142047570017385154302239776991156756060712025297112684900452446841\ 0006333906611029961367825248683829587164193331137130303951032377809796936318645364788889251426\ 0530696351831114182369122971976924478090830973658202264816205617901756142790997397856460278417\ 2961195700500155347379317507478398300900158979326392892457771576430664010286433642127216373957\ 0586560591912691700245446573475093434884636676042756802369639099831134222170419446404452527847\ 7166920764658752411354879550732772679762234152981624095873746318157662427901184397766416335740\ 4325525689360037978845985915962840748533173964991134359141612698785491428052306567430092601236\ 1901588959003896986158444326960249197181369014423632156111521156729786795663680257760048510151\ 7021063014649748194873370080992033497338125732768600829379808681209625308093963037648485422005\ 4625143488101835853182935149509402232160834866875135827906340089068598364295653783900984909501\ 4476483669798535535447652090611229121545317818032546425551521255213619075958120879355160438553\ 3131378449161732862597873573682528332509549367581248681391540207090579590693064988124237798044\ 7416917417105916182894473400236926857554635417625779537093683956250159139290190133482930943372\ 7307859425854585793605600972897168812329129193597698226990294718135744944981618208680621366626\ 4576358315425509614801450765228916047839150585474227772585195199099634675086095775240081946162\ 1844453214274369570328685242267776309293706834193670771241699080797116177466459996601609141495\ 3719426098400825814379510991649304584949112694518858692421437582733855998161703794200266114217\ 4274006508182055096130895884653197518545632867450794879758096382048247596155413321132898262596\ 6692623954711033578794860299387645243106125366683991302067330351685089916694017272268695335635\ 5529673400491413894003326224933263019694276930066117799642768217202250613285446076570995700269\ 9716549841851745933279405042672990424464577328485532543656450057865596705890777351129520470586\ 2604551207002512999456596422451420976457757404205579953456137001360232979773095588858181338770\ 5975230792314144108272895799293857047456229737315235932621104213259877402361988106626453213967\ 0426320898563882827027940167291020767828435496021939538290128545220721848664002653290327163016\ 7599575582376033530709916487175879162260401346981209894631110703003093469441401628053343615686\ 6414728629732311929022874535366247654777134481963185322096444012542907829155854910377453795290\ 6444020759433209477339426434698573835900388224862787672828800228629256184301211371669489448192\ 1162697568554548270350699011653225829235847543204990948642797271533877778444626036046127443114\ 5829924353988669760776511256649696280578118115726250580145924817422581664780579414406962073663\ 5844619903304492827261024784817318397002671070250624567683458709049511227971574069987514386401\ 4831794880976509587272093031230153664697076477281280511346142657677875174892304200932248031987\ 6831320984729065344933380732257377137648293853725524461041312497432790233653338377772185541947\ 8076870285805717459970780192996441670035717608504814043040041236376332867642094048635221702146\ 6743348902569812574836393141034255458392699057840212285009921077687923241335458703996677676446\ 2417742301289730852421367446718543094240738855221553259568425327884529690567307755160672022437\ 2446942179507034577262231246107658037937521929139987509002404768376638635813912897641857122014\ 9828669078406514244622431604113801333570738383664262500722550745917373236917800370018973159190\ 6342838578869216857741847049230260058150528466445166511145292561476678690669930896195308200724\ 2547672377419144996422564897163465030322128136958069141489417871552658340450738577318899520732\ 9376433424066198642650677012068979496388335704520657930947967128638341062280977316171308701340\ 8904731300309412789540217215946094294179386527707202928957756335892852952850310191821248000336\ 0968654615122787193503324515254555891888472492735043651045725093104372723955183536234493341492\ 9018124157993962498653134587043501654474702212201608566952064751176476596467911069721315082459\ 9554420362991220261307469439699438397240544321274292867676968235397044795014176832296561366978\ 3321288954917582165091108996718026411312930951516687909283095236630788724696749462078660933604\ 4034828585100471714255147033528215349888382880377270403679121163234241352333362092106734107982\ 2572575669852519989468082715224970860549821824764580628964254481352845559766753077655290204106\ 5277995452213338764320131077945591911617876574538664009212333744867244816375565328184021668400\ 1399457661675029484292908133432909501790835213503450894537536393068967357313290784557024089982\ 8220379114211696634484908038047792556907046264778834281352327433607727356078664319395335506427\ 5431908996379240710354411788142980644306666188648942401207410882756894121781542180183004966097\ 1682338150522446089723693599101041157030578983056799540441272790355193607645437616737901494194\ 9846117843955162090632673222038997287700187897203244570184248843433023409183182074903558784844\ 8130737040173464091512143600815892152308364545954116763189448056459924811501302592555880522316\ 3214895055656852714343762692548251915418854047597711845430271201566465928512309905675289861623\ 5300224572119820928101531669711820060697645825668651812167682512968408356857770704922179551917\ 4287103557641488298056138506954509514157954920226917638952715500662108063642161651926213420031\ 0536931550883558930761618816461272883478330945470814671060502023747885069456900392050072404080\ 0660554477305638879910068302281385069574307172342449943371353320039800696857456386980390279013\ 6975825014364974459625062640686769272836774432140315790756466346755693510194814093569364178752\ 5608702296902214602731177963830579287355331931486551090178778757927965656034242027191400968594\ 6256692954344849436038143457240572006058011642774598340839791815025794813087197527919924575022\ 7760024396284069258935167461082428775227947070776128175563609485822779323637519192597941069380\ 7856822703503371021194858226308224851327855497442789983260584773984938887258790137658297498920\ 6717758850641604404469626072489475212483308371139930643306092381785759873617332744773248559685\ 3064743180100674802247373147950098996923416635730400132604246766605375204013499129772038387898\ 2283946489387297851657933935199973509336069980963272344860051949498680455418858204777017356715\ 9342178025318589064986702152297456715937405095063386382760383976420267840044040983691215368722\ 7587306441900658195409809927777728535987955466028653279135559051273860367804606838944351918965\ 8663367921244532778743414593750210953039518565582051087782022018625137654129061575989205109769\ 6867905805773485587322563772462468218820080965830433885644548063929558217450012008762606193246\ 9633842645792786328880998376661018686997194307618140006274614718653455341673817497078332862533\ 1477783338572771756744913901835516593012265248780582235297026749052923059900996269270816680589\ 8773471490843704979975237151234392679497844025344857088403130212488554715028955882625963101037\ 0494104032456864665995177197538602051082565509059224014731221755045349697553953717405579558496\ 7528461263078086290869675425075405893679134668990356458232201026797649343629659040386825811451\ 6794397796589973166057850891000145738646438073967152502957696475479467395301039749688971972196\ 4749605162004720239889406852739524015406782470221747927335563458342248591839257030319441967753\ 2625295081349042611924336241289544068162869140947968050029855074688358968484321136660191179368\ 9392776815984212512977544676150303587304697387966132755451036877585985950842088250487876621846\ 0811131722621240680307466594652623008249191919579481791804320540176501932948250041425773972016\ 6937458786370292500826921807041314244406744197292495480369698239786402694893826191032039497719\ 0648201548255453658491241628000811768244183567343913161253840218611924147031705034974872711301\ 3529490975121869300379490215079358963320122715348838698955970877264935868140390695039885944419\ 1978370340949474715216657302024690822921010238317267878016267234721380200616104519987832518196\ 8496778635403915847057699899881067768699250358446530566978748654238337062405178001248084390564\ 7073189854657335895804501027618092449728216883809477166961076786128750717408114789971519556376\ 4368202217441589446164067154925342918115241580503213144875471172840248270384903814662018895699\ 5060033433506403258923874116304278079874142788460036395707380754234055612448953554883163620845\ 9431998080733551181217690625900216375756404646235536194748269665359945566830884196656557525896\ 2488299820317129272957203769374798845712996611544625365348810493612259993166410410472436746546\ 0597185634990325833744316112168345178384966481973441805713316987244296215964898936685582841589\ 5547138403993343035970391986989905213512163306291124227563322745318518785606344916572451147727\ 8504214048535027205443369947877979964501002753316906504490362418263092188386184618575390676573\ 2496966917039942342252747561611663951019311574856091007612924389366588797327505872773638638821\ 5162243389088567824934114569105141721980201708091455708891155797679904383408643923319788530886\ 1131465809227251084984140289353078725187338357537920683525662046028433006082440335521384169174\ 6713038665116491858185827571783371615657839888926516560744251852343316334313752809749385834003\ 6353272105643276147816703724224453817933977213442822408229552026956492349608455627345772946397\ 8590515839969689828972092297721187521187199611111958760474119219306310556306494465629267323721\ 4947077341264517821158297607611860911176019761733186668644241480641382919898342744216227223449\ 0428633599122993814518186506945635110046962161642527924845393166761222245196770741387150824306\ 6636495395791094246800781349610637593552909413632920525732462312685393369683194032295777538684\ 0633506565055663518682920531547623531317867871057837728993688093469358658221631431609286559912\ 6137740307974004759959580758803783206647471011471046848347033793988779567929922476483341557660\ 5649809534974130037135839935661018828178066448887474490341363626649482471616751250518872040379\ 7171006242507265802860343079675547358342687460280831552091356115464750579581347510721387490605\ 3124919789270969481906935289015405211360952547648504892340774982251730163146416983010247831449\ 9229210634712209050422048932918131223555279428742320659720581281935324355797406809648119211936\ 6060099565808599667898333116885074478160753639853849914572321926371031406277676794913327359598\ 1607632989412601699493777252358541888229506254330762146833159379915523024451096715472636228582\ 0932363822307208748280173286410362921199371826604860454317315145870344745713471776822316819226\ 6452864924317178022187726459184230813558259337079642172541587896948167001400971000314991708892\ 2203686922790320502851317466607043627361195047742184025218331156585425647986959169548035056929\ 5044594238983152997411022986841995452801766564925411036464346863351132871895300143007313538966\ 9967844389497485935735641236894526742398607668199716497222601634348292672301292795366312924275\ 6532337436932712535728973679320855446209812575087982252169804457437442124242409279177426407143\ 1009250467898273189423684913911251216590133202211307691587980311004449308700192213961448149102\ 6675131035740018668868459591385881054266169022964948548031718287168956900970315621069153436220\ 4640440451672970304519631381741118699675829611948551031525661263402405538554066459412478487158\ 8780418727475294478832867622701796493761167115784778892803275726517051941854296826309611871911\ 9283055227905557505895895585363202014138858351179115312587411054999402947255813936599081875341\ 6996256286129639024638898864677774692825848160664933990932453313590418782838551751410927341560\ 6362196837032915399627051224220227586771973218741476133078422462305409003124440908969843350394\ 5836125734786040518984092420047148748334889253840485593383836408545539303426660383970145983250\ 7175383251415869089022334971483295199845828747987603510203501496344122508005381587465167702871\ 6785961278021557957433004528189794836667983744329578397050365913852143407980689888127448748747\ 8601247108879000319642958365705940590798735763082484105029803448752346341947309887526952773408\ 4051150710461816394593259759137783440797698749366652402273164896207670783196354141345837133440\ 1265863652608392749919235049871193596785542502180899037819728128123096493024507771887848412626\ 4508861294300533236536254178907493792528724196959403387391469756238001954823857966260058562602\ 4720301030152917038191404672614988061534465267938943670286418556898174501758023122803026242832\ 2592046288213467476580836559530775615121017980219352804961462849990790580776405725647053047937\ 8263533934444082560898407911574152457263570596546321895191420931970653789269348462670399939126\ 6823840359569505206028994230668565866406572495097077954375721276351496215769641571045851308384\ 4736914923439547267022750627484877835490529548525396248392758366635165488850796765010939557542\ 6403258368084222252766343927849111531909985694154007278275878458695240844942066503612293610773\ 7634218432627784081398472836298848972759640322486887704813131779059067624994692967191230325670\ 5970912364138597383464601956007998357217550321465239934358307018393322930865306777025764426316\ 2806943175355103090909343517152169898877508604631520630308235998811913619495012759664551375121\ 9658825244853672640665471068656980040248469877522546837097568074485371995934755530148562877837\ 0319841014099982940538805125820102142872330575549674408532265060307161841191943425805903466320\ 5940822098664999672790775517243876775549801242409680926467545618072048422781038418842119411386\ 4257519382635685287397404907265565779619078385375688529083224913091702208251165899863485459706\ 7221665521540477725724277021173567365370306569818564868696204302290965189686279935056161002719\ 8602157054465160531671860126530087116603737351647052561886211089705262335009510356018087875027\ 6263284997875983268200099956430628758458183630286603597973725111953727925150089372822267396914\ 9849546778359676232477512148348839258508295451069459255683062452032285246269410941971109452094\ 0206609779577778550862700330215919663913687120648170905345268756143410792499123455860054971542\ 0294844722813656712098012435072416049853689420611008195440352421327304847921108663325989694633\ 4831002138521549200458910049701895494460517029970529876948318810688041586932223051690530869671\ 1085221139089822389445839372903847956166019682205238800709482372523664699200881511850168040326\ 7119360159932905900942242391633816273730915818545940785854219171750961629003056970087562256195\ 3168223114625624268586070080428280710230412086209738034987084873471517381607985867918001410126\ 5238881624784253772923113510677450660214758721845090790036253144426299681443717306768015312794\ 8336717694524632536053841446166088876775921603273026534533213231787464514700820097140427196358\ 0110721875122054422080990762830019511329629283336117792607610472466997822451301097249717705012\ 1254606715888509268803323656452729309595565960573445895279090296759901948162524989095146794936\ 6680535341136353668207712538901225355515949945705830564611416047043520487125345477662658595560\ 1138449674163951717737160931968745854951328899697563232438556440873109897422599831816856066807\ 7090602573909263390370074949723583877506081875463678249266199907546256906648807523102908808348\ 3232437675775644721156740850828954370330738189542290544300220135872149353004858518897705402412\ 2910898412232588641308134442958238217317637667121068967353462659370737255754386711439965234922\ 8721743826482395759723307762016725021058767716372433541145394460272941748000416135479185564408\ 8603305450037562061618943485057132365059273515413097802876279483873936577004738237705267354005\ 4179101785917773241306572850277401209479106535157037935493084731965605126650206600352329341181\ 1954087572770277402732625540066536370152466949967246699048381034117839587602378373914510775868\ 8676412078403593938702452010466404387300805203489438816417535738532095742605142956221578580069\ 3548936577773328204386071160782175932588776576760838721277026539434493873666863457888855020541\ 5624020186987644292244580161968415991342322388034190883769226814467583900273019325423445962509\ 5645825749612305815706138939079004565348703085641423094944014675999158015946816865860247192446\ 1742244402987676891196975767501825160125775285233891341622189631406981202157866232401236941780\ 4119188775304631526004792713516359362129789437192746094090510423459994594764634799515277204072\ 2941068003056081558344156563335811799812694187435076784426180685496386452765404708050395143294\ 5065526185306942383779614644390496774376701908804849566145524221989255784641150707048562711114\ 7173006631420732616339097007176779754461594894669690554276833086853931067458613379548366770986\ 5090060518428409353975602626038790906074662480238939904346425663693794901014079176503554933273\ 1504583265430861236597895289088756926066789296997869257698057331374446274309940576625356967385\ 7835407940961400850043180800789768891009994703021860147348596685263898765140558345310934292195\ 0619343143914884686042884335280380540998482210363117295561410790707326127073198443308634418235\ 6925366590586162208728297878509403828944324734248410860618501216673007543549909500436815372157\ 0453763639611340088907606696281459920869183015336530059139835974225584704075725153059562133253\ 6793027667593868414258798611744238795051899948630095963161330657014281053718621526002274196637\ 7475343334838246222052010100486876938277543610262689687193801518451020892524388586740419860880\ 0078256338018885448895324698103628201849914061263678183318669724411686526755510290781494895542\ 6461421474929008296323459037960776716590169442840759023163900589732912192167521414048997509113\ 9182100301704831159091402420306404590670749456477361541485153913359854901527008379132692868478\ 1787533180715542605116524809463021264547408241455914963015507281810071369272939196779248310790\ 0553797943961412585131342676449849288317070219698295786966725021468072151286086911347655194969\ 7244707717739425587998348963575685300890089105582435883906132431540007048541676142620722182493\ 9420529748674649643439993280231951878478387145847818578351046366154563154910220750153951786650\ 3133376530851121031039812987611484240369504864646249136303210679145281197232761286368609959270\ 3286569978395367645880478318916528963949070586935053803570881833090005430867234009360118088070\ 7361669743848692986394904845902770587723255573122008436226953584499809739701236915280351801988\ 6178852545510795274524182317003289145763972591374100981460656768183101854964883208389636513443\ 8925226183879869941727074054912247275975929387433487756872655612647223162916425061979192205275\ 3695112231379891417179674502935885097325430950594663897337146414702855443504911094745523227075\ 2511088947853357328604985400397469344738562494950708627893981074745209941670549999509597331050\ 1813503449269985140870310244580994443262927580480554008501587133165169571567732739796422661588\ 4499396098325647807022262710951601716079707763856630444675017628545964507199751742017806487803\ 2518319861144369156546381475377051476564180543981484420880425108285362856749734345984366540177\ 1168626731179290945840116560180277991648954826146834360685195069238973399153623905837032812581\ 4002705234240593064273747722092619570317275411419722465405770881916598220256276091717663507166\ 2684477368860467207698606038381485876473479518094594705176552799943365601757584284335555847965\ 8799707336574831543483608027537823041978417089811228904349342898335434452597921793526291838340\ 7840742077061051751598362779957023162079868137510744665622664978546642276742363721284065456890\ 9721012972935448032636597208898574880734415398678482147051349599539469489240854500819591793079\ 4781802235200499247188348349423462381577777735540563419862330805828140291140535219212388640549\ 0851551011286683701906493450461228625181783124491277467073406542887722360515277016840062334931\ 5452150078700347652090984935670900836890967002266359795775113514453007459097785166061184950727\ 1309081648085565095418784137098441360444396740346199068838640584782304709940051418008201969635\ 9301225482541423595808350641816397734795055857017167332425347130973400286488705453047264065303\ 8077363836373748963700550025238795614515508279875831645825037494747125694989888866956337903401\ 5332173620823870416919497296717505007032099685841318318523625068772672582093895830873194334119\ 0151315345860330651962534443832406495247874366840850095840056080193648880333864707146893639467\ 9461389797452980318766855035399254092275752515985379606334530498983387097549753516427503573214\ 1885181286094236642532976475820667760919624178032726977745187359334201421668151933447361474659\ 3386702086983963106128195032735377703442577738850689876230304604645324986962279935823445782841\ 9038397668244003580831227893082233176960417859692168516929068815617083841120095519843016500298\ 5211141410721969558590140150163399812051992158550243430546918011267822997581368364123079600275\ 2036394650062619734113458751704372906943282120072839025602591207027187074392979528640039637061\ 4995061172871901849079449408848491168598793416429449942680654390078415156964713901819509887972\ 4552904691282849253422058611909834166615574264549152126565016922229712725292234622134818098977\ 8701998495249230159700118953921660485163229247776265518608252009696656872972501779399790924520\ 6392870102538689674581464171064335927349061503441297274841794135413083293461973595866988986327\ 6041654313414908263393395316552551165417121676757173927856836179097908328595896809948400253051\ 9816782703509256815198567496836779355276243569985546703364478646503031160140769301510235805739\ 4974793403368029581409680332967706071356325599843181712704149405054979842539143836309953984558\ 0806493118746006288094513104548942698350263606411341497976847423812557451805252015530906772701\ 6812293692547649107187447529123845638900861752083349863242568525940545882384301607415504329873\ 7152205840724186989832860073341676215276296011507827297514622506884757238794001175444260838198\ 3357121235289239495637340096043717460719305305656626730692489059840692040377599114550766551138\ 0221137579658005041010289031985733261161132137453790606777735572890908414298520860430664013292\ 6495399077607335792446137116164087981783080598022803887086558575406826509198547053214046023045\ 0506375805667698658651348815090814028140091807949440547751493603335914342925689582204385586130\ 4886664138308469088163326091446483199987460560009325905101282199749241465502621874274085523610\ 3551213994688374064748142947278789013245931055346728512009249899903269537000019289980092619863\ 6227935673349010874789746494815751667850700566291011574143844201847399052348985024062665229710\ 4198192526918051750167011464480323838190035897324504071749255737046748115409415153497347671047\ 2008707756918705450052232557496031811172708293713850464153700301518780951051973612083424687607\ 1767345592684138674470428754655185173382684484083355782140961178013504808347795762238893749281\ 9694543888715262904743825069707853806639347711211010769930723478067693731515949357682800097595\ 9691767927193037998217239433084051629483520098024910016061263175261665180779662619357186211604\ 6347217423661712167469519981165042783753437703856461877964665944854252853901152177968069683979\ 3470551817174091810630958530277295769805955725368226928667496435258177828224440159938030735811\ 0851046277556920304054319826896968092364211155172246399214200037157100133534415615464915341475\ 6965487481459062168460592143774676124922111577814888994848470134744707534641976547608977929351\ 5630018914738068763631597436575827599399374313236768028877897020141639564776426048323583325388\ 7867929562874464103896231893186673725123168897036847233946412246141609043115140684606509317760\ 7206502032686196892389233578455921485689550993843898138498637625964454878616996296750932693901\ 0368527046351443117007052582871987838408111520996383955357775030109224971415953063839750515619\ 7806243796975574585029611236957664661497674415537018432407215100482451980792574927700658389214\ 4523070739931402711101579594514006320950582769955246431800215585171242350291404123074091165488\ 6504893921344513598051751543498237079482319110372610439136913375376452060145073649654466294775\ 5069339062699290239211537478225787390349484014440607998060352385259393302888314562292338604101\ 3614135110778542441955848508923608940725930471093197437498249421097175053263158843250867793271\ 1199295149233567536623480923420194386554040006870275165984709332144211963683847286278217706242\ 5665015190656108415626067917560557597200788721500545040058792522374650630469082375145308696844\ 2999157592135957598144789587703485097982337427246917548474567310579411846991287516837337559450\ 2179405217100120419833088806690409665716127987614995716197654989369954283341445656049038456264\ 1470918392611628222648368663384318035220552260788048403953309572224476841534858163345076336216\ 0299074440426742868158998631427944103266972371061513852449660993429851884039496394081723647805\ 5929356076035725667678550150702951538639112317983251414368648316864139224006939402555392669752\ 1955165889964873545084027061876202990813958582223609488573110119638933379890059508956342272290\ 8225521142065447523999257371852168631895030801960119810478943573177222110724662925858909301458\ 8013389369533787177051093706943394694918248478452400193145513165882319492596517718965628855398\ 5329428997744218892440154019279982723505569571642194529448375594964214173181013975998956824124\ 1999637994054542232148008384863422088713006652957976004563100596377763834113554282635234190064\ 5741817836593744383593924602799961086219508414503018346181141371325245843341629362503087652337\ 8180606566429288668942325052403632111581062093469289202576770923379307119590345083775768030718\ 4948541661041290789549105333840410730501346964594282064586315269051625398821432106489141917997\ 2721935613034683359897059084241138205521789068393528004228657909972372884053895836043626720147\ 9083451114595552090120169015693182865551308413563205175559546008386325795847049251813259420950\ 1081726248119103429513763311269776335616876664034530922364740348134156829552651965871385424129\ 4825594276256430782539216216880537776670209599471065668143765364224044412832351161206895867748\ 5604778498569010506413788441555698818386642823518073825611110341917650827191653185237597461308\ 8094469877602868442418002694131782371520979296770235504376933267865406611619333793728192410666\ 4516594765973920013305043891773302765898432582052823626621096065437121378717963649874599413282\ 8654686024614108183181434286028780200000027354984284168252501740991042478143484752576176003492\ 1781315919762496273286949119022705931663182158620147474534595973521911998899317047626277071677\ 5925326977691715531294822966059752541492435410002212445105443827307198232952790427872279293431\ 1905509322686823670230529360077219069588487604805835973492520410464735544078663170209706019421\ 1061066641392146018733944190950621763370105903842176072643337037362235550221383224328124277701\ 1520354964514413008424551321455056457211734577164333570833888865122422231677449314825592094400\ 7751078236852598353412937910623794318319889936591119780604651480718778271729377090642162846908\ 5587182642498044099909309084714236588920172008804322929767423555645691635800200013709545697271\ 9815289647818992783509679117544541254487368224874329087408872323070786681261013460539061704313\ 5175818296776225453725308924770600125813229470205017728319300248229100414564664891701079266003\ 8436963796292078225138960887973434646683627778999301692070305842702677117156765504107011642388\ 1579500224152556524978705201995098974895263515243628795995007395784547000731184562030807251757\ 8537019308019828364889326802738167124078631924008827923582617379818592059307389105626890200706\ 5870479686583656974950193176999420744543496812167561311698601560775042603412624004998789058098\ 0121838367794941099796598252300696816742473323340547941566728544606718046311900412346009095515\ 4188337453886934305085031965732823898725089115463271766481254846187858813800036165033100050226\ 9579654307953024310329276947291348028386875950997333437560437836557100753811869733844483278995\ 9300495232295182196871444417684120033802374094496619792031307188148108261725010006719705438455\ 9029316578156943766540522434014723610674589563918088041120075950960667241769067640996955245116\ 2948445916771559623570249152952297650058605311070503836449393807424933039791159550337161092779\ 4930035474254409995443661346201546165709793188610293069452859215644989233794986330014030484393\ 1498380316497830001474739963824860624426726044905707416319278658237823319469251243043340981900\ 6902376490546824335423194980191761990675893358569494811928104599222277386010175118496852254474\ 8714979103954140598890606628836457762514262109446161161605633575205782846518852970966978936093\ 8484264616210311409856771432383930225533826418184346210603174525287304922800665120802768839729\ 7949519966938739021939171269220521709700628866311560876549960101912956582449976028230718058974\ 1565591760575466497347303643159653766258701958629309263682600479291379718971564151413301127511\ 0309099284072301642453682141994375402667084756172665188855694464452605077340924367495903939792\ 3328589098049291802368083621482402427199482725719917766701268287592668250746568793243553217151\ 1442403560613103632317100649689812552137900759355545183895169960269373709523440333156553894393\ 8455423272885112485718314507773010645453383662813914091855895607930327671910038417979282133268\ 8770591140808042772380923131258350058940772365157301794778916863664982147990981421893618014138\ 3598332525761693682688607098037920202707069115085329568926780792370909544919058262174810366619\ 5868210302569818401108548194080082117977749252107244683768310595640986979201506207602391690859\ 0984098983702523000737429811186034006488478768841314810960647175674464145584896220170866640785\ 4213172054284849028597797648175637277627018005603342215851342532018720509653059121099648418508\ 1064837908180906294534997859084304614673922842295712520982603258178793713984766368956052329744\ 6602317483975756643123906996064464131953533204508098329514865086734946099762109276763940740267\ 6088465763148929368787060093522407145409895479813864351353874281361809143745863811928814578172\ 5910113490352953221433463000172103011941832549922677280861676167818137101091667071199943329314\ 9563644346427743684948878476389862673036874778900079856914994379402773161541627610191978520396\ 7697732306599631941657392686123378061620280144712963764236452825192574779840505042758950792576\ 3528853947230987579585336442266017332066308607614715257812270024510043049003150291221120583793\ 3748282407695741231548836737215141090893603947785301868264672764273078438076775545209224490699\ 5477154383123743052614533512568710549558411381578342476253831363926338049362493335182343263730\ 5248037232132128110489314303928162145907239789837867762288443622181277055580907742745468430939\ 6685061973398439997235996338082405936652708246740509080009313777447426081034783566197182311268\ 0280411062177685197127826534011155773234965271738851375974129344166413879040872151105691867147\ 8311000068358833722710757144412488009042475713413172476343944866034259995451901954452459452945\ 9663832090986588631301486002932352273310308101197237540630800892485974664772982063993479094485\ 7592495573329919032877299135265026514018266467293446958266461420206831165618339812325458672491\ 8567500589208408679025911899839483220256255205877669577948743933765881364903649727787212359530\ 6800788824216691257691086814809228629441556740386304524696361614261222236777817660077729526691\ 0510364496245113223490379786131901448908754986905155530991653718028378094205743416059198488954\ 3168131214308941330202420912191468975884825973364631806557422919707417020705440083962696414877\ 6503177540194581815301431262530214599754320646354341727787985273536251628865039514865438249584\ 1316092004837050590968218430507908866097542399893587117175996231811813653816311260195593394987\ 1837245118996635401809730197699782871036970090398179411502564084212828032126483151523808390563\ 2660761902278701555192109667718962072812933965882022450948636435889446972561527316142148088803\ 6097450439864604033606273109788893821658623540591082355962214860356713584556612228240552926152\ 4034056300376992015423946215913958237478176987876564824404840922555172485571784444692059918908\ 8473846114121702926746833908878397745067003717797951335256447341446021920320345303363691856441\ 1126964566145613773115365452129218018635431024268102236906331404589492016164500991399743827227\ 6837963186900194605193311568315350453132047504550566426194850852749787285277052921262768988877\ 5383507198711603149232093231980113012543318344108860857759685222491496007994386471410303264341\ 4478964662831991525413993897435575751565246626460842878452061749835567676369221963958084203251\ 6842959151512782399184221011416851037162708592851245393582114462770770307857671649736850046275\ 1624336106708976816043810968398340795623020075023876668255484158053334542410579289982463640316\ 5645485532475177112144636875239297414446485963600351114188154746314965064182014821895712664417\ 0745893051779723258311054794291262593862245231417903022840309392425552846963029065672066043793\ 2535277844453245552502282495031331410211344241872700198357587433153006076236675912368280054764\ 7208623361143920532302289598232391259386695970581221798290753040356132595896279993271345868801\ 8991728567497187152087829502389361665849585927339441132821598092325575683960565677606451228519\ 6904620715169387044232312458837147093293120698342709966136762203657349385644096984164814771375\ 8289160243687797056555769567918962318071685561220845306682801593534282544920178567041349399534\ 1832118580045170639689488565688709113967497574773053439094354854022462392093876918064939000402\ 8113842158395533534008929492542185981782818692052669795753635186223335073705302163641551264004\ 7355798214344061893246599869503716155654742407110504874214531828050803043566603812515270690362\ 1379402996288471910962045633200135727814533032935260757701290633948207328063565482303568214144\ 7349338108352404973576181488603033646664445110529352890643284566227473327164640441877868722176\ 8589747072238245593772773176782511631158994381720728939499776324928170996993047554277637330887\ 5943800314328737059810864097185980245486437069936057020312571558606684320305547382164256001814\ 5581308066018445009080330866343641720423973444934323767933579843650794320085537199718255703530\ 5267210204832040207824185537022480407585647141040740499208962995179079919685783536702180846197\ 3783406755210685326547180140213408698979447863471832845547365512727660646516693763607506763612\ 7635664705194032128662215341413025545967285051316619338743578477795272803484884570903522706246\ 0688651964457635702920297298982061136946965153532707961708122012762138531181772789343653261096\ 2217720636435094198841408786278873214897873436579685475998019513248286585061641144943847992909\ 9373743025457012602039947048218213117250262836227596996863279637908858218175416017449298525351\ 9297255028702086573655448974222274716775370166765272834622907335679291052019910699103750286115\ 9239201699894185512056732979533399407392728386330462650468200004453109562863265040938046797864\ 9503207934869332727882760014574922966837095475938346888897689334824808888258481300399369129478\ 2831336119541498783652729052168478539889181538294963745955304291683427124029089527287627738648\ 4532153722174904835760820372422796516275970996778372881909730954590935832567272189534767584207\ 1878487858564219782711435387663759088272270922444480129958114470972447990249235927658122338214\ 6630568146003955246167262919935157666943162532201869638125178511257071511855174422273498447204\ 2308803385598238436844324484766449970623447834642587163466896760987237512625101642421020372886\ 9009574080932436397142802801059211529018342609150366984004639185507283108445132305709318198973\ 8687351571797768567556591649250882439615610344230942138200147490246268966325801128194480124561\ 9651897245955459446749471928233703367176832955914190489600985692492717512869741003607412884419\ 0326488922137504594239466190000844143530674645072376363212223228428919334152719980627876620012\ 2727538055415986175262332679584314864384098610048296464279839706938162591906055101073067269108\ 9148731282041942910717263753878090663375911867731493212711767209597543247593283140562503236485\ 5181181209187044663288683069562748549814067754259924810522534843916027390633262688224212507852\ 5573318932654683009433458556751239979431120132892521781393145337328216673617524989726613021888\ 4693942245787266686909060157865693273408140950291541993111362233446525429281422169205598239081\ 8450459272411674361230678257756196596678625917483446997701838495136896558657096634523723443563\ 5241374035977625302141239461736713148281776636575011585605383724272848088948975067164463812415\ 4029407370065001184691338359574840994843022998820718412849780365355744662346383825338693908349\ 8398071200928704391807929593929584369828278080995638223594271631932062065877792591060623170024\ 2507725779871058141642365735275773150849930426129753461593561061508819656451505314364048413490\ 6140545921783683393890131722044102079179672604585716298912865386967287341543089056756353777772\ 7026582744052757548696961352494669163689272676884650700775543069943458727260994955991461922208\ 8962094548574059746334961905804345600567265870714222447710121801074103667433506146249869674962\ 7288022503968158376525203311405646664266636745839799787185796325230733431012697197789695553357\ 6082689880721543569126221295139054796658068285099497505845106643057229339736242259215775612859\ 3497107335493321141702764441493526980087812837037584287128548022882307175791083994456022223021\ 2295514504560891873879654631872403969908414361371510464393067567157244960285269059947015420353\ 6133562366157156764429372592875323330556991252851941879566929008194197519151041498066555460710\ 0370505985762217370676559544848500721851716965506756867639250897081202645132252832586405299225\ 6144178898511033807218681151307098438592117643586565174947209004612437403843901391241927708146\ 9126693886355882562005179154650474419139946510739187415230788840626093136476134457764519828334\ 6333705397152559789236339397197496475053054774291442038726569042645545905021850977559467612210\ 9910713522102824038987279582827293371659061135541925609809611970443730439720687582114635223509\ 8245946100110023830650516511824781126083233438246003373541293459588285873753441035490940416192\ 2823926989613356352896173612135251104516942277732394999821514044556784988589698191850543267721\ 9644991084880986125853638591072941645928820719479109489921034896397417254051936299636082540395\ 8148330399148005206706154698472916461478735216145518440552164960321056744858589534309836655769\ 9182869239717530654227688721270891427621336409952056785767592722607221895029414545570686574265\ 9500188179181011685755796079995866679030964560141207703044155743341388388903893906790319140120\ 5926459462197375453869863448557900418559289002792241536297921567953422694236496251212117279013\ 0598010755970388065056845730608581706681571112840181259212609918108042369821764700715246967570\ 6658597291480949833279068544570136610657067938148460416020318877177583066073288643471466340730\ 8964980430128222922041934739368461564348701475888527132716164306447364238042772612450052888896\ 6583216574530734935281942178234174162803334839591303142658381497290040472337808310805346354686\ 6166053513137575014317241912042077450805438975881187238545635403580480411369097279959848575522\ 9829929862337103721684722055551307197037583897782142457721197584132456797051971529571314921252\ 3296089117947184385187828748595269373835121055534439457924470577325440354711976613232302446300\ 4756768552090070370208078969028162843027039498287878247760720558393036941422069350498429637574\ 5331137711374094551550594463664516365438780976025443482296095048179655711328620217443204145522\ 6423979030305822581823094715025260876426963728484574437932776837284861449938210338363449760205\ 1405106337940582813423231745474686330799115067863775723698614452936443932410976567573595752199\ 2795927695935943283558418145552262327155902635394859616930288278839720641918776024245976085564\ 1163310214620916554004460406201507794729606115653189623333359380625913300070628961629436983062\ 9140927219127631969906590188570427705570151717261880345085544698500720132326546501540833631236\ 5238201766681201917409316951276942538869158923345596464905189075109781169952905389637508238862\ 3122388575044852178513070437917496999046738408570644887361573115701479913981068628168559377368\ 7148165729638000398460694461065316851544595475659088475090050520889963896407150638402122400249\ 7586292153138117695825014228038141065487847779069633148604566928738296000077144411792041444107\ 2340354930306384330796265591815717056530422189447059238549374011206426047987813289573317245382\ 2698940714548100507032196089402433238936667574976556806470980175690350112589033443723658895156\ 7959622412217406885191518458053799791295673857324165995317324347988106767724746057427974928153\ 0297861294378595821898110040646525877921963783994051529252118314336797830781189854897028032863\ 9347335053630754828941389270975725638909922733439103377549667111523216436800566940415874385522\ 4897443965271089379114698772369291269280019837371857389395135913831916714609481281476574797483\ 7416138237606319926331960986296035757441794927143353444222748783587564072039055331019571439045\ 9010731786531295219024459804697324984439159294425211888082730790779965240315812979175362276791\ 3105238481021923758912855002445390529375414323887703958167996563312407609767646684281908770592\ 5622053339777305774270202412431139079425420632316564133175172975404857114151813867004281713050\ 5057909635749027909846897070202711314388638901692830396766845392882593172591534791808578770807\ 6352825256050502211363634501283323674567867421891946749350019092805769511064141468112626157237\ 7357062268494867026459415195884807088093985231456759958302139457773624186925343535752764458393\ 3313900979845809719147373768809082126066055103224500419843144581527314716165375861151228578043\ 0542998792285705323800066515616849527471210698981392902975954434398289612370311574335556545499\ 9249281041653481533891970373794486262007002104039729927060271175102024021014514408282834467887\ 3266931253813452988000059587027877632571229544047912196072194151619623254635311371157499389969\ 6805786995460745156672084406575122314475803589498615150416543961494428898782893273466324423892\ 9710727408950386225296492681199368378822107663153510652682068197427835811298823388519750273188\ 9292907215873916876557139040009929172012025073555172000368684954209805969327032384060892754090\ 3360559169972544471663599867248859236380163839886446724954569603542297180116974316875672221046\ 8316502658689204873813918674139864449228365313969981569464908522292291455516904913974716775318\ 5166462946208042195775967834462714398769859733360893296993369213160152565017648485982433500145\ 8562690181613234163701448053505378152592805043859151199918053712215273635553492721265855599987\ 7052065036950578957407058458743389511102922393633294499613449359241047557993548810555520654177\ 0849287541410836370995410162780564682284991402188959363131635126493065900980907918951966068005\ 4278909688865946115876947189438875979346655081447303671930303888177475481191278621070962138631\ 4857193284745098541742597130230246375638326888494202692534491772247772455282988942567505302458\ 9584718960278385802348885937676674682931226562066642212760291859838261648228545873230242087356\ 2331892803349938774861632882706167762308914833668685892954373145719068455620415911026196653927\ 3432194738349114658700183542170106168735353966080363079095167161563516488461678526240199790415\ 1317719209492933887973863798852218174035506684019031404786866912677863102357942441313270168012\ 9137284856178158104174093217676424818695020694480635117858250450410241586065461697602423335792\ 2577790444388014718703248462478919298345734796377396013893795231291918530735389393034785111231\ 4529127044907806877995101854441141482241659093133938005919515461673225968533062318050053460401\ 7262115054682128400611605177249833401127511555628504649929776368681383562046516878863711946771\ 9839474767643167059179840564552221441489602587248560609733633826446824716896297839324885393426\ 0244100209999266128302310877628320237318495303409714615017572271327826640638066096014106999387\ 8900377064532260559962402271395730300869142861763113283047366786165354518159795450413908044519\ 3845598719883156067524638141181251250945990814638934622405880168495138690531542240240174600680\ 6467547677638965724885633366257809520499465263689396568674955182142480310879983885781326228513\ 2907489544766838554232006213259988652265085285191953132712822523052419399161930901945233084543\ 7374220668634525888932745821179042499219633653416842942457751553863488152377833098253644988754\ 0914664341864596394167873609672172556122699177475544795114889219630020929282425613296286424053\ 8569912794419740690271012986823758449589367971320976075335307357055603290913742743279611291863\ 8083286785557533413217996493654123587390828530780797511757242798940809111758264687517689387372\ 0954999239949577517427941849543324326808650995712327876729150589632708818867853453816516067730\ 1612389308609209722942264018561842116588520709861370957500522747171461131616005476081728876836\ 4584186313744903637773652896683718909536039822061934058039488661810799085176283220910943798757\ 0120543442503889047031044225345801532466601813422741652234304534267469150128417176781767122222\ 1413395562899676059701108394506280336312461142585309583220257096345075552676807621642133424179\ 0235398170591429003739592498957977719603702137671806601040210423187461580100429673412908083521\ 0317428744512053524084821381146367372603020166615311605641635975806548068579432981097973789073\ 9887886189869730070510460952548976024527082693732301926216827804356686340259891548839826790155\ 8485490253379989419138498563576319883747214892968776315189499711093687335473287662906374334257\ 8325112903203409247232220937824980797229337902677265919130488303107146977425748886705477712267\ 4662319343571143493378690503215215601159516466423814573974170798554983209006343463096232245310\ 7080392438338086833161390303880362120245712590889446839574234167879542292606608892240844185517\ 5954905137575483975112532906449187876930805914208209672061712884384684961942970981171640784534\ 1421750873188218167987591516730350862209706516574291345081570007158736875998928012368418129068\ 3499313802000062054019295692533909358946992415986839408732655457168750370635150777724947962943\ 3408225317828120216322449206055684460288008356648914398074567974662144658829234679516202046862\ 6409600584507751365914213008423288270537593614501246651665218980752097488126481893226941241105\ 6976225517388075855555297741221854645018891792236931754157588467911448183255406590934445718990\ 2429668313747541512067982168543780997973769569122342410801189101780849209479271487904107976369\ 5556143472940311016314259907709971183496502421128340711082136401517376007100601056266939273397\ 4853082954979790788943836388801605520856398361677156680641201573360715525087569237469727387677\ 1287706955915994756032358684809451173657299960732046699668008657056601525455137268604278209603\ 3061978251243422076892809265328934828373798790908820617465518696086707987258537948029800950026\ 1088620761342465330321480127963499722456395660093841160796245239800955685545013970148040101862\ 7686824028363575568973169271449850994331116604174951206594452263291566142100304983460438291904\ 3532169111329068536220731611061612757361354481958164684629070041999768659931391227001153182750\ 3678266990560334223409473282937352666195227444877826305046090758885278007507394777302049875759\ 2256176960154989945506648389789355349343442832335348006810314635778400891960651200523554947508\ 3047601153799935321095675584311573087066801812422564955742383772025692553842379773025645682846\ 8143561588763103809336938913367092659576230902397181347727018838468302153475182009684389276303\ 4286430445455165889194158730834505276654878850081030805347079546820660609206849509636568579714\ 0850823912866223377336078194592565787135572776040190157038071278065534578664230128330264382351\ 0218570134053313401815098640288316176672398414207106019757398836970218263124719100181278765040\ 0458123121603663393416076142612741949759706618955753814985151649943441892380362271620991147104\ 1994991684600945100465363089365299557497235390517800305498432967943523748779690704949290271802\ 0194707488535642166521701669627630082280576344994672656808850735559135771678546168017561224375\ 9303078385833792594399085928874020671737153696539119014287384206709877323280281919736547334619\ 2238780742486515868587107333972868212620006551266047323814131221039482408877820377665691669847\ 3092173991264922386973983078567479060556577214327361320189195348138053921731021882847821200832\ 3438793024874921826816943491987428090234300586071680914055661188429223113851742884314832912743\ 4401217216886973551195337537205992969114250189682899979549945066060674197509295679446815643337\ 4273990495552513769326470274913058005189371180104342073304504952397503795867653361753597703297\ 1162323042318525627931567131659054803541539652960711290258995182999826929369185331217305028217\ 8780613764409382381951768986624558971342471867231086520778599021091609588665828802444457739928\ 8618866591950820556274784649281688750933270437895561397277053562651501735961956109917843373322\ 3489438036231830959454189530220921722787992487513795556865960192480187963287927481534230392658\ 8573207681238163043226264704746020949340258536562148685618753266344382793613926026153233184203\ 0401173379671511607821651163789932259714472097930395704669828443161721278194590964610162330958\ 0219069126537201675025957231274508684856034426649560532333902165082481724158955436500899704794\ 3705622441485454449838816226496221053590534277854790139356138533657703153737549170722342437595\ 4285653002554274914659536861673435851116792561978575031941095073862315387890020412479447221637\ 3638951641865777993853357836786761561629227535304024216951606471695183380252896822681252762598\ 4858707091302143482177671120645396134170909168416154926492922010532263094155789894620371529486\ 5850354936042729636492964037301076145568503536322376492172763527262806789530542754022212114210\ 4727319307231828494667752008721412449429402772584155546472167463209144932080120978840682026926\ 8686802789552621746512977249223135832955408292289077232925592407057033887244810325188083796259\ 6201061602143206933084047112698354695786387982228207046567089072296688713839840301466070480966\ 0307891291113884225816900610491782137184674082123270003474115816187578801999610478380276067063\ 3462769508026542362849917427077492618569490390712595808876482918058558240103298861737326381016\ 2969000283573011502794048142666064506578872019167703541846503130710486498681223674248476396296\ 4769774231674242632375543128601908464649222080792854847436179086600189429136315118842473107236\ 0136037615799188826352160473890649096044056885145621151818287350006475773883347525209676499536\ 4384934674234892083311867771683535143279997908760179563485319318242174878422411421286181930178\ 2934693950839246148840899712976212287883106303320302402814540792935431078017473082106387114178\ 3675802156665843929099252721808337529534360823320364395765733054154389572824951399956260836551\ 5305383590013419832201797974406075364620991009947219866575632728618364366986675203141676260629\ 3933795710801460461251036253169663984370300376269000655899256903918295767608699434093844097009\ 3909644124245104956699261947890782469630124316864063796075564859911973678729779032588953243116\ 2500565352966097822435746025304989188683676149272695584297445020292650375143539274820997930165\ 9223585392974541398275579818990646629537803062397707316554685471396214408901681769870688621014\ 4033204601436933989463478894535770692125030254145715272402733229777373177836398786643206457067\ 3018146202242169441077851692732046877412396602791746611609810437697951020949681717784084775117\ 0900965192127396188838336895786038052882323614668136656976636554370310384686260476012554935923\ 6102457002294530821763743730060523750571882714842752565164355112051803854455929660312503789409\ 4260087872756308964888797381766062040471310097124122651088623582659391316253351269414913093468\ 3774164569616692723478077921862733230783388288016045526340928475756588149127829533873758318497\ 4354423778760977702647284246332735135946757667381129817160102315186546896204262378353804514473\ 2082271255399820880830164550867986761504141675517477203279980551226322026966456418188848244803\ 0476597603276072145064971053853448357799724796745641081902516398147136347436267632951902037188\ 5459584527471416811041676794161077450191571601854283699100900677644475366735908494967100500090\ 2444040631280626108882048001062094766696588141920417562626342259887313878534858794667056655938\ 6409823981367265453648980924179836334068243073757894597321912929156866427166655037117108841518\ 3607220273446206413846593468656636650612192079612459378284423705709646415481908825705973411825\ 1927668026848786556549242687152001315146203175961820910689874751530908303062525532514289981478\ 3339078076468099024399877752362807269338833971617681201795731276816367035092537383375006096849\ 8453336506082266317052138199726263471877043055237945008357807038729895557943695307714678298933\ 2580213123428995094640261532879885246716089769744916539026528866970306876554310179731677992460\ 0293400553347751769949536249472917210454189501325847222685166610757889958262973653819954705710\ 0710986399483404449656488709391554632197473421601009232030085440420654548529159156707097879120\ 0703435947794456429612122044582851084830379487148974909601279199071655874418025974491741427438\ 7224724306335250985952685336191729642131142486211524645490401456470514180188188247835663762786\ 3302723733519804832468731954186328119397712961785846756247051151887388305088766122483466287460\ 0882002667839317651912868015326367135679241133868307034104619580690994228322528790490964959385\ 4026178417500490630725776034321846628028858422083264083696524436316750619959636658929796236609\ 2860732116409627206484204457246240236882349713842075057045043979977303874708519632129768933638\ 5069142381560473898649933993394586119629254415317271743558516302104291786255710230535066696640\ 0797195420042120322374642093516171631001099126435193382883890535138518431445920283916908249803\ 0410032994725831322126591415657189593965270197738402424569446697393322517644874530598891437162\ 0195205503817390974798362214317574441747143893394911453837135049124073815652238051475184726960\ 7644785367176955673749905004854389783461973848068740597629378325292051626123088786021592080373\ 3101434401682859101263694753381884725406817616824833581957090948332749894342458229039622500245\ 1015887558232298371257782875528365465604954466634485802177611054320435105863256055823928510673\ 8335593082755239527225091824381939920941415051769242822283361208312781464338018190161482862668\ 2223417749862521113966487015040040248040778896033260120320323110413685294310160400108981364076\ 9524598557860547287779355232202337152857025288995099939795510924161815978960158660415802032263\ 8612911811258540833833186789906360220052837063913600587824886093704890085768213982875179847174\ 8242144805163737936048989014087791074568626809817685883785992774452304187654232839096324883829\ 3681648718563865068974539848393094612901516916448699991244521619284767302402349929665963340102\ 3325657518755564512099342805011033313704294010640575639666089022448453074906339784378110317228\ 7534514257970669750881870532867022876837278169632012532450483390450443807684636342793830531338\ 5066782309920788023783224864272441939101930028870542993620186514578677467427376176908259877280\ 8869064451220200461775331151624265184771115287442751941597627298542094190945087317455438394934\ 9374907876621073657744841855382179725975533793183670551884894769715000615893800614233348159033\ 1090571418494761369243861937184518765470150091304973155388646876156616712251700961448711188402\ 2566179416419187983406782625793396441738217498101288646649340522954131632137178863208048281225\ 9979193499094972153646943128363618361202934303572385704964302312065854755462123585060714586493\ 7422961373972894634065232493792088874994891531352029675115869917641262599046668715856496450795\ 4010048071369660093258675693422418998640151017174480616359035809166710663261649802899309642800\ 4045389927660998108605243347237831991824906890115802417790533930508874542309486174727652651965\ 5922711016453815711296910683784237262517801494864633390667439194418043296698125822858469092953\ 3863604312834139545875848648701463589077925736963547992475991617825915189677184938135420819745\ 7733449154679594641361317959703517995443685190537528724646491698636796772425533880290226552709\ 2577050077531045174509177723815424251073498553120055997305826532225703448833873481844421650095\ 0006756270529410020332189743392815599806841648901986223370943170728287903531130066442521536494\ 8827096717485447853053559416495472201568312123630034952332058647617245470752560505775215057483\ 4650122976714129580868234840121913801356323208034610662976809242653335403012773362614027150314\ 0189530497583338649762423557554671394309118932108347324984587644772689474065087092240571490943\ 2502647207399456800437297767517882679110585080525222542993477803774209493637353440418399652892\ 0793461539502116334252361616383723442580776502887207582325200405771333244991945578668511741056\ 7481291825364404279995468530730647737430581676271991627901155433278317801852683933845606210327\ 1953966803918208464951543546273978643564229576573834137304587675661719574066834725523603880625\ 6091867520306813534843083287766767612916703958505216295463689473216467914540911361858465375312\ 0600891982240231227123499088147597177935881528327554530828263468091077685959713397105713187088\ 1883642354945301406781191153923548453228426010288779537521221701311527205276271206873904488792\ 3244726522652144544235997714832165916968406022732134478615779656087638085500988397092041478199\ 5984952099757074175280467160681887248325938541368934571633197897584212037493050797720400678052\ 4000625396673951728594827232894749403585914084382049006698192757741268698803300163600172130113\ 0722458917991030241234502926161378865601115700539566835592104249806967171667814241557503650819\ 1135620868302339495636388502929861535641035900672570061580086290883436748441586359844706242703\ 8868803780302256352066005355016197306386264465873299780722996809966675757574529943899616389291\ 3408536136413182749216624519038795016353194865899585930185513697235878885212656650282380952150\ 6847827380057014769041753612704160348779942665179351826879597366865858165681292610584069952485\ 9293682992479288210667776756106884571204158564282763219585121748193881681333219229505699312812\ 8510050089398865220694474247518858428403699858771210401712557142777900540522651682586911545354\ 0239445801679823905613247416296560609187262624125630242900542486913723234890651921514973495410\ 7696686458011272961765039912463918044251097070425425566510917460823662325921581141249651732600\ 5365080793032589745028280070764530123037476725326825693176724894261312832720788526626200651833\ 8873144054486143488455053652684203717029347465344616645296345293044102786477263930698362388030\ 6836207699846448272889875442689371818143272478978665388016476235102587340535629223348102614548\ 6518154810357874888666816628226309261806028414506795827986990728895654705826051594836687075349\ 3217541813218720232664659041623722882798535099757792106230185995017326086567832470997405849732\ 3631580105155843707270782832940802363970391198664945903589719359854632167049310563458874067868\ 1005327997652753805849403016832032573486561033269632642242597445252252307939158896928926503857\ 4098673062690476744458743653223597829263124841500953397911473223478800421136180784284021578870\ 4440726024325957679419544362723040150393766866150596643556860273361247516563942530777491298947\ 7363841448552464688083108487432238118431708266852978718762636761588099400290171150698811929274\ 7975299132714946567780079276493114916643643864599508731563740391041212728809649867587905016419\ 7797118035069055972277059439231566333814376000229400188175049929303006566428165893932204268765\ 6763494763370780236259205563694227508607379156910559409009746182617353381004653189638290288670\ 4400338247000769759090864251857381239835509652860624063234172982751472311766941195524023976410\ 8978256004281461906273974065665749921015066101838009450191552508741675974470887351362239283581\ 1198530237844034354166992443897092866927827162007981384505927596736239119226128934907378291412\ 5457851074719552148916163004842708210725423551017305095150708773842600790703812462742681145205\ 1265558493437099593904559144402140424439112942027818512453623699537562167633568498008893087026\ 6176634771606001529938800797731508839602910421673021679821926356412989312337387744448581303302\ 9553180087915217834285952727927951253613102772689478145067213811430481817423315854461680392127\ 9126741520112849766352278387010302785309226754129119316920059511979306489582442723170768413437\ 1042466944147623091651088748283876628044997003680702864227320156366559147733056694788409933245\ 4022812943526314360880201730173450981068554909591117023829288243436301768020832384096501726643\ 1674136342011412603547189695236606375603395823910842216211183662728169980528533579976715940252\ 1842471084816692827894516527037323803877660746440559748455232665083506445698269488397325379723\ 8279188394409551738124657147027307828592701232817843236690150661593264652727829266282762300447\ 2253474328704146710671030409834199278425684659573656110662378946111771153633880151208740851354\ 1621866075766309208645606442633342573522422897499093926044220523618608224547040081219889107560\ 8160782192326226480599065424442494850365427134564563173550198372281343921824688542130514774488\ 0742374817616627237851033226441208175384482325131651587549680345877967885787819935219841708581\ 2363884613806477666280565124339424498012119250048019683661230716913492362063541064806937532434\ 6843779778166703726431094511275947717295921881819416112839996724378766597616593494109169233098\ 9106725995599113183896843263747439454288753194045918750230171596285752828245199173431202567510\ 7475203174844647181915524012791158259118214441993447741662165971022201225044780817520699820951\ 5932760749937945614943965199599944946124911101463199164427600847175812413671568804380625736566\ 7323873305494689307607984242175845127434989620109949174802847220041730583346246993261745741800\ 2326893492896193037648994899157904621924166576459011896750451669274371223347680356403819550968\ 5457701895074693186524830983695670460416008627118607095486147499780323118188228793853581862029\ 2699631728173905677313233157609996429485909103657489009205417956813865462914221269068429049171\ 4225817968641660661859524896038759903214074841215990335172884873802221268951143179847686616812\ 8900069153188924875418659188967026855007396953570714908296111256919072661410193016334537873637\ 0322997164940653037592585596294380975305511579289676621296791578278660717647734095806700270800\ 6487482913498228039542322931364982624441411870844664501455420525964015919412468125847403922019\ 4922134376011452706939464474933802344512827396457626333755431229315917279646244309576545331906\ 6800758807109396121334954748070240699299510144717702645926695309057611861690191888909647223772\ 4528356176445647144452509089212684822016939407225067831410329396417986766630996508229949106519\ 4782673425179882207262283019783990007929475236919734093824431781514281073042987286124062310769\ 6932400273973582779548126107189705722856020140709434767287199150165717442671670923517854699588\ 7852154019374960071206674933864700727840378358388385195865624800121596197738352784246346537761\ 8171124940504442146707379921717727564911725957482619748556731645511583867284472794965201556647\ 8616338695575542148277202030014320400755128514444234591264611827813449094603826852497435314442\ 8300231086163376684474912709934578798548093766682497338133380847786032916396823171026365975137\ 9960653496869828789089624645284828617919923549094039729944961819778210642096611612913535638880\ 7705331550930962039091088225929323109894644594185281618303598690922746725078148561379562572230\ 2605843782431432030542888542218663805733043757004470570969632168798205047219508953442711300733\ 7450757933312827546936240018704873598632957181666394596651630425105412034479293439657259522758\ 0319517626049621728040210600998104437890237807892890211192033089384312511766028794905379368397\ 2561591393913657869639198667115265693661327264321290741508799963615958389124773785794605364829\ 5921850516307731556733660632365565152040599447017481616174369790622538839037275742690134980721\ 7260614889395964710647311958039126635894883028443319117664916441252862569293191858732276536448\ 6558472729998423049444337559299771381346806993988627886008346734044317124814772636299297428528\ 1616907627362435506244496577557191488171148436844385752389407968014154392186896268899620577784\ 1215840750446980517277754331942308864277275473019541048455873322878822959532951255667714363909\ 3919746067667859323138533116074317026843768692474744867887909822669133601694515175344941148272\ 7458085338219489321473505672685318157464558963124970393396877908894684015502908680230859693335\ 3076989263283858364042372611454276203229685577025378924213722951058405907603369414288270344248\ 3968933526119958528188403679067629316677829237424286276467621863348981961115024091880422128664\ 7304047895145372812006619682603283673023414257956941892201462414423046410056439743897536561240\ 6297568844984834345283366380186523896625467327964939098585830819222656498980048113686506559920\ 0125261104962390782325721736438876636409427351075556886916043063669777384838516633346007280126\ 5512079617796473870928844121327636680125706279787981222365113294108686016887981107772455939817\ 5204349663843857272515884754789976011427678836184826841422402800177333823285589693278930126711\ 5653058807726933608403121428370596325897376307762379237559864621423052713559103946036272148701\ 2777807843809255510752531106290070783695705902877371595298948435504667925073306729021305602650\ 2198128886650761105968845517296213210117375904640084837301922987750597969594583595237076210608\ 9746271620880887076239332222983470241831527208503012049299627374597526793801619741603483208148\ 8832235974562239730543419752093575260741160907654687031029185299857730936516359906152677310762\ 5384756262305912021915446885090680026802601399341364619447991830168236344263323520187932259450\ 7324877796365264659264136355161624044327727938667781733295435780676921903170773253783721447165\ 6112956822051772451338218274288002676705177704991946987636096689110622344512746685781898268474\ 0169188657439233556332001723841354757210638000491711028451086505775551816923647725466141598691\ 3893273452424615069078363481053480250372810725005633806509438135945134092126918376130010331692\ 9121141974910912486289256992726212404652417631276357096290264906748167412101632128919931401397\ 9466946605604194250099865540267120466689331017022121984692286200534815211943959395271343533838\ 2060433013283040982031987577754402695483638790300227176521414195540851621768059940312624295090\ 8997635072512271413212482013887785710819252002485867576427893343133781181425030252961995636282\ 7460318522301731689035935850373251371950791456866924771278340647003327645897918744980984303812\ 5148246377558531289156794526481310040766294970000819837264820911734221440738683040382804924346\ 6872914813676906766663021267890697177728979373109033221432209669289237167704471783700269985075\ 7671393465914495676707456325249561422983044021495511063490842953743954990455555884312463341294\ 7359387074081969513494000347527890294990475789376933355931602909580696638896932035953186146264\ 3451671944260882731944052169064141850210589029122057905943807638038318239429100992585049388752\ 1965549161816787479400145429965142568415860252403387623454676097859440603111031863692477504058\ 6326107118804380257954536419394080948173905002257733728902392556372720547168873747447885323967\ 7674585189862892898822143608814569544862902711223267696497418649469167526153303725980587750366\ 9299878639531036300222067089840039038814242116213575258760629520998474199980231603830582344752\ 7405864847022719949795679517536530324251071186464076128738205384037912983801046746492766707737\ 1765994871630697323026302528409268451865699619822476078735366582368973244520561387953005536399\ 5969146587482417349683154241196834506790880092787223964667298840100401499293027526932931754234\ 6855396290432916763392620373170492370467174663594893757318322896727748737725983778294448850100\ 2298900199016539372760994879396476855560054639802521540618287622944175108692234123603642870374\ 5491632042606555674886138273442646477183327984605261755528746883238404346598254782035577070271\ 9878007255154868108884720634080724777158470245073361577765337369702447645098732690184871252576\ 0966249716744714901794415927487286568628597474070289908752089907988962752882214795602020042125\ 9524520421278988582352238913855031667742401066970809741047377362434985234006639802651240757858\ 5909330217729729874312584882800382086689652072735609181166871684435858051264188814162651000149\ 4422922542644523771992359721248626212070612516729453998847886925676347740032492177212658904522\ 5354956435962316960006341187178912690707787576137342135541107361852712907806628751406597553700\ 3862685431254137318809709554196974631171659851725925222707835945411477883528438061385133984585\ 6753052564852269193636750583323160274025070342404567238687424375804232305906117283995237128026\ 4832189796978490578813275178582727053164400514236166243592304797841755464291133578152435448231\ 5898617199545429180529509576364756623419094877906831691590534599544813641701078181585946126780\ 0229770511714268615458512782534703393865435362423487752013340874936616257759065386671658983049\ 8744479401132432973865080371817112696626958599217786667944514722787511894044528709488717169124\ 4462012769439321053218469001958573070829885538403563214439796187601793460486870803565181930496\ 0606772662908171714977201426501853171874915030045962091807255169229700387832162496930319256806\ 6173576939133455003800792287969860160414277724324558359372554400616260260763300050748904894869\ 2992748921258897950776675447971159705371451384548669310065291317516587990044983593776838597243\ 8422653463350367126157438723459093587080599034278354585704020408003988875205544103392956369890\ 9388865498656530767073316969300784687136228307656128495680295204881132961877692921325847851920\ 6970515966500599015864215083235072285467678946035812788258531781321420623947520359521057771799\ 7378399621741975163494640445518843791430187063682492691540419155575440249095589917785545469675\ 6551997664091790475434547119229795894233715617760656973984210528020393207965104949740619614836\ 8783500525053357829641593209114113922300845257543272420005272829627092409922600865010443075977\ 3740790620821427566491153269660325155874224574117640100885498130403763604412838140535454437466\ 9908140658601587375155649851828140707686526915358651733395635504073429632068836853660816860128\ 8094365724305146961873369827516309296051413093345381015352172652397999800630576678901017469218\ 5601707000364039307218316317648742066766445631157493974086895597071936196234380218352014233230\ 8237511105578078178208264000409006608958134475560674056060296714487360722201155349815889205252\ 2623786285227872376719010683435309800390963861066866210666670276918603308961410272987695665402\ 4089012462972449797518986930479723240619331034841602930018711995485751083114914179598082276577\ 9061032645745445606243972280434722624058825297143704800093321173901981936787398696178924283819\ 7660200113540703548939363314545853240200461786471219899769485823598621869759538441012675363043\ 2184631726205840784751379752767310688176712147081666797701962416719364100398362334499397244610\ 4152002723413081551755641305555011011564142552211763352599942271804917250259893858952987678486\ 8252133271638419025525450009293451405852632747934368332903712700167984690132355241944743677129\ 1686583757956058524612932491479088604957151676504949782198153791115701887731557715829453783997\ 7147152743719431311248975800617252651318684118841805138341798624323669236884595760024227612388\ 8990451452269614955130495277966681360539560797989854622318213348267077474401617395679258205700\ 2115456164370618454146999220001104357507801154842816794312967552582003094111526141715802476063\ 6266983952990540038042609102580335325885312132307960003444004930804401979567798044696624901841\ 5530435544595521527556815427813056610070803004033621171610792514259795138123452939459126097210\ 0893131067757211363443886289720643110384169252278435796160753540205654313456299473540795903368\ 2764509582336702234783537639888878742784561723845722186703121768127144459181390521205002369139\ 2181529701465067413425663466858901849051766746256278249582980369233909903516007121114462246129\ 3095836816267456779944158562412731274358106850295232334889183568033581205640693900494184360545\ 7821199003398132967552741459192645311190626524224300826685444954845898276686983896666707435824\ 9202201432691586647902110613735542744739044330510248335135738782476803614449067130176821673972\ 2471920867232370397942993385506349858080414785924764385850258531838007682875397419226793451785\ 6379695518657983477982940683278982717498564214892547408443538587496610585975765749068631183116\ 7221202062285180830091278706764258287122675249162151788016318498570197307873421454339847339071\ 1687875501038004238786109953825735420701993506528972376582324697853266917372192529091660862809\ 3032368871385010983867337545977771302845648422382560655070471106695550526062427173736541245465\ 9437182982125819245235958695595871697155736520698507353727116214148452540119341793530765700718\ 6216682908274881369218781621660569051961804759447927010307830688807306969418151925038923011711\ 7662371926853601070168965255892084913917950907971700911257757280551148542342757309628518775309\ 8973318868052652000465605107773685184093425987621771670324111380416925581290389030435054706089\ 6346595099609006893933997188670206099471760358812938497655872855191834837584434778319761830581\ 2515121401424250457218503690180782689630115925804818597686904248128340826941328930205393474391\ 6330483461993073587191542805620044017893295199904468215251285269141174208672418864055775038597\ 3368375716336346334015821268471381814502702466930763837185621384319048289217065847283169946788\ 2948442708519929752514378601596330622247306542173744012139697499024519157790373825097077364294\ 2479079333350594603407208095200816882292881427296692556433920429669671295176547529366978653641\ 3642431634498976315750607637353301372787109868756100074387174826973284606685457567872328953509\ 5464810458761025189510368310874112381096971389178797621449568115876223684720888376380552498247\ 0587735378107636003606340717161251780417241205084399572308520424305008799797644508853177995376\ 2405790328290222564810253367458238341343554949285360232579329193714393841537418675844427214280\ 6407380085860818541095861583518667584376339745934815450230312938028931451748584344449220898016\ 8194067838801553784618866770362840900884435190583901561915347282534389690381320736095115674563\ 9607920135398690328902042207042910116495362609116882966516724859226139353311973546786995611511\ 1115416325455763242138735203753517037509177339212147102414954701184276848214808222536917126757\ 5600103846288105881335034449073896928713923564631635656184322150789878443870347752001652765649\ 4793414649195820748718386755516608640170937667382346246907795931637452840477666796888349502434\ 0322405952450269656182743863779098878181374184394664258212242675353384035513417654333409883637\ 9912836800547398213094543311010856620714247744708387487663176732540480620629455038859071176203\ 9291258185702972339368544006848364705467544709816483346649071852071734847636527038473120022487\ 2247058009166750798713465002705652727715071804152318646016435402744342105003352762846624211066\ 9894908194151922895419859552612976989287064997323236653311612067213162209312437422799611491975\ 6455931172020765987431823479437168959586854967907014535656458842667439657135669803665831789257\ 3560422858514215677991174759930948000488943309448626993808051264488536046344701670534949788948\ 5267850482898937445407931234439628857473098353913004946500532796235612851755885004674423297215\ 7304752241297696497449852657711781313395683486263704956758381232617073689270739670874643401350\ 1203857203284802590264385295270350533323803212861577835395812200252073045390490951588817509680\ 4793781970529508761345378122915184347018868812136152304172461211451066610037911506945886614455\ 3395618967027510391944150598216545089768687279742955450509996926017878081714498567680648562313\ 8003019080106469571144190022552955072810770873311182379325894209390486774337862727546673711529\ 5111886784986067658943292334168488961759944114847098422182577337938018267678952278367139939416\ 5786382969813674442850842836180787261457152893642751030814161994732687400268465248697417398378\ 6398315672099334563666682518860927637946101570117249200477511725177894857596971743694506359430\ 2514883525739054109127840782550811496360554557853436551020666313605158386164705166956001430831\ 4609948117165526160015895347780617594113330007291831404548082568196153805159400959367892466195\ 6610892018760399817608492455096541219729197535984033054416930258100385967634769398597721223141\ 2117468048836573831767790945321587032348098517338678324730188311649010842660255323872377009650\ 0698641695510093742310019849907717837735329166613581441768703739315319692285984058255117024888\ 4661642916923663583971061788287432832184850201696124519418698815002367255213132479277517012713\ 2548799329415014684352329944693553664366791526022978268249981682732472494973014018230446546024\ 3715941182793368465398326144315432107916345170675119333393773113652055228713606833978643231645\ 8492981241836385795534714556813194149965329516896515222507793677133712004461550677965947424329\ 7011469362152277542407901278487007509569751356163116417637460384711815370733798651793558497502\ 0368040001850841933085252137348832521235617617696993796461392554900514078402594641007651618602\ 9151717504669775062719223411618474769453939612972949463918517554030470723863559843421345542553\ 9304576100521202297093110439191029364282909274855958142244581098994878028112627230269455041535\ 3218627061753215456077134111189341913601718675630428797152510258144611370981902716611648392471\ 3291247895924558763936839760813546714000242843906603348697964192713884906558892659432388505548\ 2372441850881118009874833136714585046773443433184107563323066115998417586780684453873472372870\ 7101810086585512372409962016622379617485714233053772799295937816756799147381506353446529842913\ 4481461614289575197753771348903580734699826891567972465193893369511103525124541572794580846556\ 3287668116455349941635495568003914685252334167579862406348104212911827191019814553776395832280\ 2868025153917121936233067761999967784890505120835225635869674228045359761873433965079184935022\ 8137561282826170567603923605930038402536335059813085885400433442576115973037743108421553279315\ 1452157746205010703439330961570146288190796231638981089046211369521243888063428926791688519014\ 8194189864959813903901258347028395962983715425667480627604219809614953357656108121770464108030\ 1192852007630432249254038582133801458413050477523321807882406716231616477146184356832283224338\ 6980406233917938233519469133866911343112706306310558809141316361594129544464392379792116919405\ 1860196978231018724237572621947842033788735950233816751595864692722753610209327966658666621828\ 2855112788779095447954682582284932775350232066393192569220609216501037673708797466894406796716\ 0649371660554718762661612747811272821638379767349477117815289300096388150125645447321946946975\ 0811904372152781597410937140270468223553872821348460459731828969786084664360053086701136791074\ 3284992367355548269788329853851703262364647026294652425447453710141748474828258835948734269891\ 3262993626724944904665084240980427740682954490480217054404250259761547229782422146373534313764\ 0186930948593738346983920980036383081426308494445417425503640302338792493560406424866106783473\ 4848471021829477083679328909553820588078079394447844355408575953524807323755166894894450480258\ 4567287063980555769575937844496179984159024871143308255518262702673301080009514793699482134030\ 2533650909684055480210946888998869604921004104351664957867363798700810451746787716831747576881\ 7606999922718505031560140227640476198567337514545745192667115439604736419580932750857687726195\ 1408422112991068281838831190019483188813679101901109812916544507355849778041218487672079737964\ 3173493885123710163672973365447195303767361746445010960052624092878604927564407296295951046723\ 6184219903297498081651568661941908059334948679424545235187992133374675916358299115816789161552\ 4826499052184406238113652083198289034159658046172355090955395265827930752638469062938250233733\ 7060548084797017714700484481543333126259626333655975657477451552064267123364313201957581770899\ 8828900078173170006993052149986384695195625097120591166338724299267841817727277063190312456295\ 7637536905233007283673990590435116750525437198866738093027704291913394321246025137848955291407\ 6938722365084254481965359596523700894291504871019474559706249035309439620834907629145314296797\ 8974009394323082508283650249515875711568080550608449077289313347347421879004607506071766909380\ 1720383184412853438784141237617609441187944687573423621565224828014245603891301447740051692660\ 6038008378581776196043948657372095931252978613058443323221992150491993558989524726461226465225\ 7425868277984346021927752386035275280085781874578479083812943628246763314828533352344938859129\ 6133943357303055262575299095227351592527643690371607908433876497085762339364644404591745096516\ 0623311492176051789339455510662464286130704606503280318679678637223648170781236228376300993985\ 8184667480277900881360330657268427729491457781925378652691046346619141461231986195667935743617\ 4827966788954499520581398625806543972146373706135016509592488685619094383109873945197952157029\ 8708474859143123346655397552588001017086114106948124600788456652458931246272108865963905281810\ 4559632448552776901776848499596168908441303082703284902356041533418840198908686453438512440524\ 2523565168133099898169161382034063261421763208293167336897321285511095229907176797425230410008\ 0192821774036054245649957604943486982132276541830282104105365181350407267397512144135438079428\ 7168651003500926740088540381880574993332762703727050127223473425218018046307169688436574673326\ 1468888877567104136181623988510717921024385648574259500818172713838931553321251848254620258387\ 3541694469387104773303268910566859332162042185218944864919004415385422382073696476079670329134\ 0933995000084025091975739412974177572060319089559978959922076437332360754880733755246829546468\ 2081115746348591694059533582557921608222974446012836112799284613460403512731703740733625874854\ 9824465331192220391380227780706872843278410355265327938368780776890208378935794184423200373048\ 6172636855351172773195438423623755423047038904168535583732023261113519145606416141201616543282\ 8558526504684500215628950518464115068363926403439286154542547936838129489628374795574657163228\ 4949152703260468916072142613598657199358520392019119415473300177354034594416035094547584737808\ 1846918427522152483760841232655580658537315848505079706857124968332931736583516057068414319906\ 8953950940971071960886015754346753903293061371445442297157283234540271889082736572899644596962\ 6104905986362135384682673631417030098247398601040598427495295505044184876091242134713666080250\ 8387799287757771457662534526434712113652529874677749764435598696389295360336271232638226270563\ 8512208146183212379768628181070624181472982052016565224838549319366918958733166458035805803609\ 2574663636831081758531885425731579327764320527905065305809271132034842606224124651490539966331\ 8889985130350973812607587857217477615118305551893168151549912164213876486727516952842715315005\ 6283274313243839400896268534115965368030962790512042874945040964128066013091793765605574074383\ 0638836343328780899119313856328028927219544604353166367170303111384719872097832746612481668298\ 1073263852684442413714816147805187980655133123041438100629817422524596943760271894759155885847\ 5679829230363959788483255574075440970381714553989492739017939453799874811265516450387068707906\ 3313517757407843428434877772854074913908176488618718447754613910702772780343927218105868225704\ 7217345495835920146381484382631872533990911102092290354305416195849264633272544582310004693175\ 3864110740392987585304980311721368356033683348454771393349709182096401546044855740172957768838\ 4489299140139789241775028556062153151363070585898090526111356956851579629247539408306827683172\ 6725883432167577538227744375964340698278018238051700460041003724390883928923629997918542245620\ 6706023501755630362500496325241034641322908707331450203433401898105726167380639450687971476917\ 7542804571137366464510945964658266204146845263924520194950967085935561098734621731108050203240\ 8482380620795397192440724835663238907411719923165742485499162768450867532835509770150437051657\ 5707184565074442366272632369036978028321216925026150194977733686269486802996730295595170487206\ 6337350270401470826439176133972579717493399379857306388734875847429351823314913989172575027703\ 2195126155562341007634444730991478113198546877756625379735203403527223580826046978410222355821\ 8861020292080031160154517974264777802059317795803649868467146560147495226674113692757845644990\ 5984895053197210359021385661962043651617866402716275067882153501245763054596114929085289591677\ 4504740233513630884973768106508353515588131379405657498006347238330985430511148293500641622000\ 5618857271258148849262199846033564570211176571375916011851649545797612056963366607240788524860\ 5304489646799688443883061460918942709948308992018737256409589843998916063023844979993828527798\ 1999293767223385497727950763291364899941159711888861255759029154828454723160991068479660413327\ 5929084061381359872531254074562625271248522946803385184707096554557722090935979407827032409425\ 9132610368050957757563840094895561959456405947194678106967021745878193634042901082508721931429\ 8206510711482911042000462280858339405922334189423412063175033799839311997663221074285612247379\ 4396279808904056417351028920201359329730350514253249312708805251371504454864428250474020942749\ 7833417062858073245029601673119635835952232602934911869859153123543650700755399952252392894364\ 2879962821984210106202471463633113943975535462505836914402539635587092494714222025450937725082\ 7644800648355700966668808768593178032218685430475929037722338461832707222104673908232465444059\ 1024895920505958848629618613671737491927328208894848299369234545329164898610518448439692816360\ 8386206587183809891584738901631401968055330201910789579776724431326772146998901590623791085882\ 1287736975471617603793171269735889515425420545611357652137787672386846088990127394696171839506\ 9683134228161109093350771681308069699193919055712310485422830047481656791741842654762646339223\ 4852395453826828551883921947386513532764859235883414071012600057972957491218663089458789783911\ 8859736992386958652752966702561953957369557336531607168975506967511581283482759584071493699152\ 1605470198482830874232124119010015778864199656349903810705744953893801029343159424507298307106\ 6265505630037863479074856259338120526201339625056689256642542122316285400605777422916101015244\ 9542982427507645799404396542183318484622060403209121110426594396314520816210130419251527844804\ 8855379136865560461600087280438821376708051065138873312375413154311483728609966585686538018170\ 3178638584217780709141410357667745052467753073359485277117541984374776590924490559245440994525\ 1330877282778658568374214080477364238666477049369056146856210279361298627050974530697994429222\ 3997311151641757290467606964841495729782900391257724641685956767818913191667921344829057153308\ 3325382055231376133240959667242770294595729817147646127880394400044015221654740919148957118971\ 4503057638151854981316324046285336706578159792495732915330699780409399143167795818371272877384\ 0005238045650272436859994882200404271440148824464244564997600381109774396036645386801878697807\ 1268274290038945777800588714660284921749381214594659730445257127343390697160162801898767939731\ 2551909314599378766713726356228609137986701938127172203342295748381704916320408439107496440027\ 2093433979848697457547746296493495074543300215801404855998437566884985233938750476633954514845\ 6732172132337629796479346968140019388170180802327959608265087564950859877004844119878954499034\ 1944585217830944676701996811345113557715125372929373651972455260804129520494721455392070533334\ 5779946256999774562730166431177268580245349411494401905304712844527172979934549170922874155482\ 6068427537816733840444279356515265537741019795208898455771880015255281659074943107095315445326\ 6899920897659021675080773142800009276306043153172578447962721601158140298429543548920900507601\ 2685419158495580923328423129887053185889178323430098971718369809301060935838736832236427557784\ 9857009388134154239032903235054131368980518311799012239050340906385328157030458681705460642884\ 0977957260031954877317768182021607033781131815022440292652884303636499127085642586709006359619\ 2211196842448947518076697127312846907391729666384632339531367507703165300222612893195842912492\ 0454593367154513663955272482431071391702965761124091469120773383039525129387814559932957950431\ 1375800831287093192561247424797759891841733607885042683644300067341407251705099811881710182490\ 5689280643658642467014021530871735477538648117033998269804807797028767219874017329260340336394\ 4219113046893204628509531196890797289693848753918260211224173376944487362802071781207255273081\ 8122377924941533783568686669426096979680085122787078419904404710342691742910593451319711323989\ 4661891103971744066967140722426857316449377883846460727279719520925870613695760915402295079101\ 9895861243645573504010836469618622919775947326597098725918328877349768812117199500761805583561\ 1866941338426361346949249814064993065343858638274724475916195883307348588258725260979794728134\ 3451010979443363922159782091363454812850196270531325795417750379005590864231681520732827443898\ 4840560909481517056844985847228010596025447922709851133765071787766209969309245142668892815618\ 6096802839996418548974982699624340435977960496138709073404313051596510617298719286719006178749\ 8227798051208695360146429673545058606058439096500915732430190097529033749342304752005284987063\ 3133135714587726694000151933810330652630443957995292794979101121963571147095683078228635477156\ 3964377518564438630851020877319631571702323737550818088323942472421364236074141386189301963764\ 8988904940595886616701938901827061703057662804080097420486445519518666928252904076625878315360\ 2272426811619528989454433876165516531495437025657382082093839434319562655734797245883901400174\ 3843544466408628865523901219482225502532994149056923430315964243105118505990198769814076936663\ 6934577536936768908371062023850974191256488268698197240801978320034389843914867168237695795468\ 6210728484672309470653901587531947528601782068150705193590341105809537249950986515855374083071\ 5211191636344876733449694228730441766515005782966888595564541644041381669348455589527195264817\ 0174625474303283040327359040229781806022080997051457530660930253877030687528014136933395294087\ 0284394973153117731624245901372810250372187106338182907987013182000910246292269172765235343335\ 6510239439641112291987375779458726524792330486755805425181629164752068879169546149507206458882\ 4610237766443946072532433458001017699932365806096939932740266942272855441389216777329728034642\ 5577466884262840027701302874681838692839493040597858831038950282807632554635731064898594604952\ 5123871665551266903690144196733646972315886665692179123650729468642046222612814993414705395864\ 7099039857862939827481656022476725437398890351426298372171447034400943618527533851405786052601\ 7495221034371012038247535401093496480629395336096125239498610288640249290880617795039540012041\ 0660651068184156209453369137783617048609681441919934248286642528527645930520528738795586908704\ 6933733291352013370095958715585438946514544496084700623345501038367252612244781567929382972308\ 5899803817336877870090321730253141630040287455345591058741805977077910003096767831372109130408\ 2139054083851422051032374315578943646075054993381422762713368655736049779399749129036691548017\ 2689475056040540551564449636500774973682228644623400301965541482005477662273405264235111558972\ 5435399146976191380531293191152875608652808473300775514786149281958917454243119362630005749914\ 0406056654166822020102282481389884113545433092907775860704303691216663295274509619206471119051\ 0070740603321012013633630341158234008500170457563764730092683720510688385350215099598882414605\ 5869564643078146634142097470721658612755048380452185121046058418459585213999921847652609770877\ 0233729326059063680389910257582550570883968623315346771705151415141828386328243604976372837153\ 8392177564327083794015855779866040462041162170361628336203972792158380501690192633943173024383\ 5662848538979858005751190902384402254081509622621551330152797559409539943226800092552565060210\ 1998051246559302023614226861701676249519956052317215472188452463976196761050919091947005936344\ 0191999394986229260839611329840966045225554329051034253719165053817154645038956373592330882162\ 4796530424966978682756202335613667212261516642716240516751451501402640098800699781906982827047\ 6366253225254683213381684038033614162022983279839407671467930257579475183359363227689860722007\ 8182123357105308238643807822745346494964502731476244959684306486654715738928581590869097949396\ 5087148681533899919432361910711181837737825897427397457006957868200183686848912279493764890102\ 9535031701072341441773719990248017400162017257250406061560048318565749569728591464882576136327\ 0538003290305787019394615629905676464876057717048748428608081036336050345852607262103407008286\ 9412727260356402433520873111674008364200681796576214544383682530933218261479664478325964419501\ 0335524099110379792001278767392593845252275334247578254076467639084610511271358876058351911944\ 7196530392571728565466755231933717724508700199675921562144378882290736315285377066661781283214\ 6444409320966922215492285680700846168270056375085237352285510579411537587354623041287103471172\ 8921448613182581000173916878625378078205122521322282867028920074431349417143003403277550091590\ 5481764814884504650692776719892844857353847053750758303695618015110746368045134199536877982872\ 4791864924610648715587598549321943941744594749200329538737095661129936337793322159776009870070\ 2403047826462920914734048464211596804090383229459155204418373833571390535441956673887908833568\ 0906566435857923036688348091776580327658739303719339078953611057732061257833711767504615982195\ 3757804091686575885565359842318650487340591277486604492684346917948467457478589778827877357500\ 7469431779230420442723982865458538750755049242919560094026676399051819433684796042846350837297\ 2716765211798297940593943838660986190726204877813281758913573088893194999867189902553869896081\ 2631927471209847995730364558485689264814551792142190269095889096145059455001953060241871089737\ 6611042620962934382135225179161298265437497469724638559095548784697090319269201789117368745582\ 0312920571336374370203964451018149523146838125762661873598844075967119491351551047662812726645\ 0799261184919036277825135214448812678013180865023516947008751949471409051091100649971713440548\ 1355473997970568903229807599480159486939481071278938184194717617422046974933949599824313269055\ 7670823329789973677650036873932767358068502974665329934921683734113102193457599041634809666690\ 8928163883553087218947175678056024168291778703609220499700059419252288619966377595296867593059\ 7142273497954660577011794908342189130535809800781299291903659415739752246286219074513216694054\ 6867560830979283034804917636890540348965302990384934960244156540830892338773896763460215490307\ 1688053048070494761970323821819185970822812858058189272745478931819601511512073017771492612618\ 7718380158818297751861490305707010453166684456987871736474120938741163989823526213138463979343\ 6482132402861344728888259150014883381914533750493699056866910214995523184785237275377445217623\ 1724444623742528153291520882244239788737607960253013990090551792489510914376411427268257848959\ 8771475020079504717682128220836465877042139608930556286617083369535535560147143152694477425683\ 5372956562722512666651319174587839870669192402610095385308333329326455587136817320910037610382\ 6678660294432186072028309135610985986436523512482104271219105268243770986728436573225961954950\ 4890058515678887885967813274598964679989338388789514456701982665467174663139811582838531109104\ 5363178119269452694836823566781390671178333310448901795969694211229992912757049595055209089162\ 8526944858303171399019148389472127250749167640066083505131659629210725069401509434315351726338\ 0115919734320383469630106526158645423173073716863358141851336392633299390081288102212116432480\ 6539251727213047820989547053192992352782767506060047445905626238706416510001326844154019554739\ 4279890288384267456942909335464382139535550557495548881030703433406301320716730662325652492367\ 0078093482917254688527189715911228383594001311236080994727102747518978333674600092086152894910\ 9312666390284271714603051612210516320004820355862327533217877734420005958184608251564919033650\ 6440709622669848086836870670251840433866321022876170204970377382471122094402189429970113233373\ 4246428713141177312769862827662919964223634314920935008652054801383081023175699961956421308044\ 5266368158520569915532231094212926362380826440207354076056963277557700423191995040030997008502\ 7500124080895161950106026763356292109863323597178307887533770644482718648247359548240868430198\ 2562442975952133092313617547367594774349849488963932618088255199020951252390090508747468771874\ 7188180650088644830696674123130974082554011154775018204233627678621751306459529302219438003539\ 3026367304677053763701451236233225646036510172947945556846118412782730833363463765408201967669\ 7480472252954350738213880032470435556721908093782371716792254522063768341950646870639514085023\ 8194113692042347579568417938121588364690701113250382592042867348135590581339089446143405880432\ 7514890096647129120959323152056232968154611833327811472972897215756920821910173842333098687783\ 4207499584024654738217522670934996777953642240561315502573355490947437241009864716463767976577\ 7906910953173799339781971067691547847499402782120593128366790925208463547505595402216468925093\ 1673461670093671028971655866823577900677521310642051802832397382203717336873528498298950049340\ 1677099561669279153193078179663586162122801759596932174972689935806523231665488159691154046308\ 6319395382852750074878910712741684904707885619286326522386337875408506606915561074003701678157\ 1479233795297163900135576624863295723438457179675779098857808052775557843527555220591226729316\ 2747863361126444212811249133897655791073784576142046725655618176962736556040200060089707431727\ 6581420388970528103367821943556340424162511244714966884757638684535603638548710201425288928370\ 7779491217477416587312063206389167811778663482376847112550015698632102083508881373574566258722\ 3947231585756929220447252140683262846214323875366924985890184814254727861040531880792787746721\ 2662305832423805854074582673880013012848887775824699015988682678380322129218091943311278941721\ 2188920141936511953860891966924165029463117432495811128022137006022350661316887044952980630290\ 0134169740901426768012989706114383285810032377929902177161413814816225615878702769452816350630\ 0048492049997413080076327333008884893741480221165491345759379990498968962062040119462471193976\ 5290243661102547965118012803560120811106923394790641726093857445214970828329723498873178034645\ 4996524265261577606551150728589362369238812403602572390056131989417925786348441922833738893186\ 4610697680578580489887552327036907257439569837376730129388052839296287705395677512087854773907\ 8336809908309687531384852951765084246988422277734012690768316479756728567338166823704849826686\ 1002960934221349393367339946535693483952379572565474609473257627183733708614638549500865608635\ 0668318635088593259785054637744927770334162583081292192455501347049785882432026737394749789200\ 0279542377966757283885333134183643517934866401546459140820889190377846073910752647938299344360\ 2986807459167728792223642993128843339600605539660675761429443661652409941821714657010121840419\ 7931691323987329583444029874780744522983136630944300417441603643261518324451413590543148261310\ 1596278658168918879470025262440540151735194440353784454143950202404692511417298081781956664383\ 2925099813782280784004237121967657398399491950625627427396124919226776112660142693883019514290\ 4363117852570965422659077707454638042764785019334429195833817297932210248932227012148974101967\ 3609021622576576906251254391518360185058774956390160997571206459149026829780157171154416545697\ 9951653446720723226804522344576097618889730956905139660225183687858532402769602922966697562956\ 8357606133097323863496018874173968014289567447359846901423992383767066962838178001968207084069\ 5898106723154801194563495163460691973465898013895168264204861163244284416988037459727611090186\ 7770445284284471783448177030865309545064274795044963213631143272663904645598024513033510878537\ 1320176712453381229943645312510384344535466682079211748980684064316701567010129972279982309163\ 6451698269895876414281153246486325895002868768368834748683986477562270094885724281919724429354\ 1775923201547904225593277381142589034420119223209202057099052535455349428941569770075278563884\ 5487648200639831929895794596234839926585491322168943911032276759673781855917897798901742396411\ 0871926623825814592337097746571055021171831661538958838291668847903559349984612578650859393668\ 6613841811712605750528836955844582461187421974085564277514247482026242261537062450303712454473\ 7969237722229046702042413431746485134303565031187251870809292787897530320690116469430711839204\ 6785092742582238496350989632452048892121310783696380623876732569283815802544851310579000122597\ 5922354350880011516034836162434965464053784296189987861513888554146501183229560587873547134403\ 4957122649581252317362622560898055159930805294252175272726507560078522248042187283878906347319\ 9320654283906371547117141232513824211624318048904085970053809242758097330449658355853935196990\ 9175972981809793253771073449988567209992860885844953755677620791076894049250609255588895684312\ 6770392289846700287848310825189241938484157570501332620179989374030579866145070996698853216438\ 6147614476977678818620481262840152986526763559244748806786330327484688126100895828945365597522\ 9134709272523854688978359630624892380740772383873010773334962705446410407277686963235451330397\ 2771134223310544251871924914713709047394796025443869407943787006111018174084469453628588484830\ 7376940470680361685082495075904477395624523026830493357745500952368089176666431249024582384339\ 0814693956039745794229599198724448544050595575799269025934491934731016147075911944336960036528\ 9416755441368204254719240503424599243234151223215316523506908585980381611584517717411808531683\ 5012160416528621489334212906892903610503807413673321703380123492453357950866598882505403164651\ 7937645916067380990953251384545512874459491460013125410465754208708381871863986934961913134040\ 9236415230403869858461773392386171784896548981284120966015723448467107646370137971089645079552\ 1284926428430751012902861617897756814755270426204356803609561050668734011674798153151600607653\ 1677739370045495731072856533520449484541658611824715784617066101072890302700962371443379436636\ 4944376148568676254972174760775128056422000594456094580990931964154498724899313980025319212287\ 8912679789840348776890311535169443639842858892389011201132591477490340603736298932531526881643\ 9839249277971407489632531295943224397850429351885960190393990631837220336513906930715422346999\ 2568853438020337509785346541672079975249030778532020291450966089359276139887633828637967225416\ 4271080456495577668901814989484416880685695484925902782601935972607876839680387931898164166619\ 8702149359456185751385100186706832197856600651447224649681851341681406184135241060056004302781\ 7924057125565166565047038883518196030000831249664403684908949255213302536530965988254995773423\ 8315965566837597393082061564126246937758219928143758746428125720088932462096135060162709550592\ 9854166142549448698581815083517264266876718336095601829433150535457680474088179993011463059397\ 7996785815073312683401485904208156713002063660507266571449633670516632323154230711325990837485\ 7699700665361559438747251850952764795728379531483122900856153763546730721605124913018283903978\ 4824146985401873088676430499666876359412565619781635012091837973482389970751962230703216326937\ 1986892082329730957984978249807985109972412189117911687877533236745932581608759051680370048353\ 4289366249574997500063848143117416755305097016221834351682262942926715718067892668224043228339\ 2602061649949933343398478533821606616819442345712817214291795114255288370015444195665542366057\ 0365603344505265015210946691716723342632254008796530499803943761097767620660450451810737559637\ 2666105030884797128936282978316651308450315602467818010201629460513495091875928187900981830081\ 1582832026531011672835833341569689879084171515346324560335230691700381806715794350676165138949\ 8734735553208930891169938830600662201745840898205444669877960652787119819222179693727802198500\ 6669888896947535072980489183564329038727614736365236818138512278156765384785547597092680313407\ 2461782978426789804224548417257774392593236646015861703922296366739639960122395683264981826954\ 2595159119509369711533304727084351796168816267330979084751106917529203445225072690956131805602\ 6243107659933039706333027735839805011405089786905023848030284233489935129034743068104815107967\ 0194324484397734179278178506495533695704045636771310891091993727036502716801143858890329852145\ 3520840757319759810428071604624197913512190486986147866694551929176377162831999302173454362446\ 3833539857651511050653463714395466415898531109862506189012258186212171404346627839742874426418\ 8437094800465145467180598701530702405709232652013530817151486578113943983919861985321352572378\ 2214885519099969050325320942981995803210048391267848329448045007132107394502315759976665962061\ 1399652437825631638899546575500922677643029086074381989981298626386577419149109990695606570072\ 2678557329115473272100061294059011956104612253465022757823026002080525633305042481981810585337\ 7789174587446432408532225780945567097053199754582849638403879567021894116493962520607029536470\ 3164206345415169354167309064182326997042166635585599093834064921437591907512097194229011456847\ 9117919203699485064632752380055874896944141570890830920580072632658041146938954627096451426731\ 5700861097550519966342321981196913891150314916077477621101771244876396491179334793040590911925\ 2772745958422840752875616274570245525347944933866449306288855857387622289025542845599067396659\ 0088901534054384079777458298840495229686299795182465403192151836881247388408400055241234520358\ 4171133513771507833789891533238023730549706840670445397517961228346350102552252564378552270522\ 6110395098189918193146564948569727497026386978484029680713843438752479478909648032740636873624\ 0298425432609054733803096010277003624798152960751397692412952477336877866722487525401324369303\ 0930474259801722364803473621522593472612472279246143710928256851864118635310419444055869540129\ 2695935745533422110621347737359973888263244569544110494802298243544261594976242901792888870513\ 1742139912114583833097937879214367099101249735939371627254286947080629099112934104395001354535\ 0113151272084974254125622934391754467937982150693845178324850493024603041370609575566465349739\ 4056695125940709155031897046322910700439357848129268703627676732595489508815277523404371829975\ 7738100327658607129219015852322428246182215636116863502677419612669787953914096454295275400660\ 4910052905705907519633576101737324345723285307238058740301763807868175179915005578701783719486\ 1634126918080843568049829999949423884221719182837703370518107079248256601761848032016424578270\ 8964265996028227218776836919652607961285399844947357490184448514807192854864029202031815899233\ 9718199915111125258679214018496348323359134907992577162081535461666826449900115961967764824950\ 2335784218748594362894247251463022719723138046686821160092642511874693533662294261392121180366\ 9428557595917798800827163896646833668604914147493235869889652304176032295667999201526607984481\ 2094547118328866219834312993664987745533414955509694432045077617790654416269921686710620446511\ 6804012602395142130424551578214966318580237860229290116961244676126288838375586131763607125071\ 2911997717865566008515880718894815108232591818648444109256493584868799675099758629763388126605\ 9482346381805547524368203662553752798805693484933318070087598533736730780379597291788312366712\ 0507042311754997877060191711551112422261448596546903247492650688646265739273125424396218535586\ 8707238424971231565871340874457067136444918671515230914848763999301453593893321813058242691565\ 0066743823196106694172564618800909465137754742911258893222439848677826430995617493713770951110\ 3044022536428345217127275254226971498312903690089074342190258275382808697742093181105041420397\ 3862407974221680982627526197686808546449699127441107814084424593820468467156412885701509555747\ 9982797914724420182524309134736550523622587743892717469579957304831391296245557023653174210941\ 6463098139367572006913947640393290828422920754353993209658063691843717698661813021021903796169\ 7474254742834726678211800200044334286192958353212591602448835199194815066164351524244022918823\ 0933056054472523141451221374272488605675181362589260114273272323112054810197341411643736962626\ 6447081483398228039617874067007341050304691649035538107071046221771002423967424267015525980505\ 5296010165814821568722019924333749229837749734714422265217899715585249277840311896843527624879\ 4426753792245637693643166643437392752468963012639625457669394840822950941435965859101650757497\ 2970750367520041227110766154607935983662537224716559814741595915384833518151774360736161548834\ 5212236006136776781991383076204394799083482485492042489810024541713217392659069742252394644294\ 0539892578931424150770412015454260601986236150905616628416168235550323311023917769828356341598\ 4407304081460186608100775074018288585757250641328616783843200363117188285390910217043407832908\ 7150710399775425988691475514095184804793751106370790184590018337880340626373924582032401005229\ 5813926987987131858341852447351330151292695947962997425194276873789366263777217844159470872949\ 8597775597829799339682174205620607971230352596545629602930054865245205311806425824701189619897\ 0021764267491926633436913000852485780182253970620740450722514127779032765105249621178000342430\ 8749627686887392330947310615733002833211898477105169124773865056643658182819107952778137169850\ 0427559019680612293681167110899892479094355731720156136317270120156670342463110981025981038474\ 7356558543447275560760613711783755588724450707876395693046806573553502690488303184848801278044\ 2994134591923954159251657043509444135738638592516230204033103982521729285650636340931109249367\ 0143232616938086867201659770442866622273333015438757759738268709513534216120477902342847714029\ 5523033745257614710705127480921683427959063956207075363858961369685719392405070377381785559681\ 7163438555941783836460581852148322342734222560217012984059367284176784911046071719287915938219\ 7181602864904969272876378665259925733113359021109417692969667536362893435963088794028982333133\ 1292187004337353033141003217295500093205719252466417857527568552119761908776223331900715740383\ 7338313718126765232445328106080983149714419630260645273792217460214676563576834636224816831817\ 3387099101168734509626210709147159352401344680632668032227948418095658074746486209883189603645\ 0527669749450059008741437416975301581770613983544895443814085799499465737033827107756679843502\ 8027343585346716472682598465851457478828483920705083673050094614903111842499505104911435464801\ 7647010897523463797018310172415744042220250279888583606448150781443187941256936122138894273442\ 7615978870676949851988124671989501626893844433724681657868340576734974097389169966841356926989\ 0217386447780177077507617302589162056328685084040158094185586689660257676038650820986613037183\ 5933256094431468725233277500608689544550155358541843483469049367347021820417868892509396110525\ 5729095683435722467040444234437427498652671427847843945831782071465184601585522453034549571499\ 0858824219676082828835333665305796440524494931805172003015225106941537839124911162851186528736\ 2718654513474809970463454549147586548049895832310256333778344589106681596327634088146975286477\ 2359686966718062503151550118338860717585735180555828349209295331231535253737630625282228243824\ 6793038259109815021955100056196789227804278554098593462757311991954871907887222848795193610589\ 9347445928519498292892696260542562530727343108883708766060105906835286188581371332315566590139\ 6186435978613266802277674756417659565503678876614144712975429285712235803249350847631241886860\ 0583528175480287535790036084301634252188566721874136660974384690584104412754817515139278058069\ 1878510051262119980390771213315199797339426276491339389235970920738985168114204282400954351642\ 9308100054433207084219925306267059420301733181175405720220677851158892908199468987773058196757\ 5321983669301331781995283059722635738912353921867134039666853820012116939989674325714814493035\ 2535620945296108520148570328188351781151851025257882013712106656660528369803854849655029822300\ 9546510795456745143405887791244035595025188565946632675954698827276413194786775864983603998015\ 2683845890752712468131081074747010194561690850630301254745056574872002159679978340104840629520\ 2434177673341846843071750789895332057811414529058017247105140959730022765458520691487171673124\ 7880417871105149030926192901594762807894677813704209250741472127383853309684142680971919042494\ 8464838841758069549308146546813630855101387264249868879565951114587646811893328984416775596114\ 0241531901952596857979237249615783565245972253888732840022090898368944958471479905037494183368\ 9922702956795263851032573672879104763340739598825451947540117996545063268862874193970633954863\ 0070490211186551970513921646686242501229968811088387377766302262308900074727581373484592916986\ 8501564636462605578021010305507268147427218697300072029710420746842080022751129714790060350981\ 2415069655813180037950033078948182107115579315279091665079686340486295304802185551881749631055\ 8498252564130123923716104257920458999351105715627831549492759386167427874934809876257975493611\ 1632560227025193782664272268955966159433016817001922391554711369922903047998658584044808002317\ 6468118075226939013271134236619124928320656603501610823251918581295220640730837744329685115832\ 6829534949271891012039532393523623382401573839594602969708661708638635032046150937535654041501\ 2698745630471561086104567517038705413891152379136047243066713485726430951133367452652945495300\ 0236858244534851137095391044525457605937645505000865903311901867807157314398408516747361010521\ 2013210357101576771949884910427517139342996875395841669229586213991313418643641778347100866881\ 1356948779642659047840183966313051946562369076461104754846546317872746343020701302569406968104\ 6607884749788310516626229441015860488391924473017122900652076039789735012561870270062722332626\ 0005190136449784791675059932368921388327167884374889168476367212852050883592973054638861360122\ 3460143265265414298828909323385803094888906047306592225320888336457870817772182616172183285171\ 9899242017950317827175267087427230669311140522453275410973680465520956750608425512553673298194\ 5024063961080016757162991028631955323895863113014599430509113795021351801059159445469000246364\ 4543815208126790599705026676241741252406242482208977173761470318074870817691821444124798105685\ 4150690062138591496192866534518913527989953217111348692633747769498704952408027557051005448686\ 9473922589055628814711300859501277824282874583870425732501689892529802704429250371594303093115\ 9997934036688971141188055147176077198921880687635908710237632008511365143228818861082690001012\ 4483100982491024835107816182352039286480127727209940985380906919973625151676360757736862076571\ 6978684526096347636497579095692814421094548198239210586733048688955880989234794533609824195756\ 5009997741775276148850796941283066140894159561960877369263155227844721654241166887548311476535\ 7926870635832555517283001801120067994891325868150965430171138775808584322693794676692042543335\ 7623364260086825847040949125910414008075353230198108668182507302981680013196356062890402698514\ 3035695715704437809861826202790832240784905828327787981605330508892362839206050881685810755586\ 1357450537422378941241092646571846991869955652322650408161106388877704135877298036521183745886\ 0195922442409691602224696462371195613963779749303059294958312379423549544452066491445910891933\ 4670751487217611966816116698775642511588483599674638822059140056559654860926413962970290001372\ 7175027713194368729478327565727249129080193279934337778179102680314403375074002215459940076520\ 9981636303163826404112821489516883123545162128057217994896761761204730713164155815742522689993\ 4815781488843264681011299278834218888828075811043303077893235924710682318760359513979961489251\ 4991578305620418542158421689987619420614147017800825711246603995295599318271483347109424425470\ 9880103954485847301580718097338026011719843842829331380060453057820062652733404535297427706160\ 3873055148893042463840439685897003257922975697658537930383105841370285089278209253378400726530\ 0111126082388579573376610875397448989530743275978813001835017537319528207884855829267533085706\ 1474380565850439941090557047869694901659086279652664286410775545926024087944626648298077790054\ 8875608589607900007541691624322874510324506804189873299939576036589312455426590377458286693488\ 3583386065098841587324129868066488715536221878188650019024927556198302916704668499834972824327\ 2030024970469841892503463063158259389867367780920686913981168141888987840015958146229843353022\ 4108349610436844628157976464547358844909104628293957051558948244602442032208865223156120807406\ 0238862702687452554340692914065221971270198793603271070426032362863646040979406410010875769927\ 7410305049301522570424327955144364029154064587281599453522871104728303514517389449966017530519\ 2336167301686448518167783718102581142897169287931852478362543645745122384520781406360159679222\ 7290834505819876094971905989858264125595712875114263989579378544981593646327390207241703411884\ 7819819693142345178634077363572865644126414407450807555909367449814295263178035943286092127241\ 1664961066975632265253185877304669412132272312584198603572810215167175841292651949186010352226\ 1881038607907813979713624805159209676706007957189169882148390847046993839971316039515361496700\ 2714017030853863181742405459514898886274528760173174446342497021636120476829898609675629528493\ 6186838521663695676393478930399661327763306174031537428658241447049233528152601299295550170968\ 3206911210339618593237103853890453483857438848647224291093847093840239454859582545006659929449\ 4062292555492713325113269249534290341711817868612833549792773502180349437657558084593296217538\ 5094386161461530884334485002305881132264466296076038394057001583144646811370151738863938197732\ 4048375135027410961975920360909463701691553099590701861070429536617278927790316929431547141712\ 7558107592608658036380645335584399883872376246676873045679569001718030773217933389636931548709\ 1483545932841885847750972831912185389663030938433615964965526852158044232831840932905324113063\ 2520150601552510518389745508997088045004197150388125619634363996793554482315890646170936004294\ 8147507127126632380204806661999874053326191128925020463169797367962189535549722181465125844303\ 7403178978201150649358235139291675088691326821712838360026091468888046168858642779000028441108\ 9370342829155199441015422801933520298431069927638905513023220218854709819120039821961398771307\ 0122745074067758637806941509515336373339588049754447845501037975688750708581479950809945832961\ 1303921002006285481608322078854585925023284880078199243235401808551244602488403284881521329556\ 4766886514231334006382230344530024879881913454405316324180784759345855604637103457418363484544\ 9325945815672128680549152156527355690801069520179879639502528712153732119957522557226511800945\ 5433774176822280887691752801949901056422909824102408034030655045323743979588421206493991497023\ 1039785174081229120274453192203296503768217409514581367170556325876847321769625689674780854911\ 7434305492836963531147538152262447463673254725910552238414070664975947519059124186889147761591\ 9013098285041669728420986758514180088025448636474449924377823353549877972534112295613973542545\ 7890769709343990809930928745022685834303137976276383551493519886318719372816735559401049730083\ 3366562576237906270231780676597703147386517776925489629846541751351570316336809214973198138731\ 0247596472016115125992033935118455428880481889352128313308902242916449920596494967312602900407\ 0551676747774367880063633819570366842410314723302258685108866165690142524127551088178230836093\ 4386087555739010941039625265505624917496717466078439743853826670297047978421882920720083021050\ 6146288142930384693485676396800320084397769996894939345367510275841845377913740377340435937413\ 7410415403364679497374012299664535735329961819301416454203140424891454751827951190912767231292\ 9368491792508206247391552148606124042843189247230375466512535235524974557790089807003778153162\ 0568489514783945086471280558158481027761388752073525627166803103925082867886404711614975432519\ 5950609667199755033587019904720870957359202361255901827398828829696221465010006213010408271886\ 5386024140815486562757891409096761533177820671218283880155122411519515824753223916958211820438\ 1508668843267738619387327067455686556477756461729783984477579203249729557609837363212923610527\ 0232531060990110189203530407876752801024977442868225801776985534231026189506196833906290430158\ 0868598920136773686515280393053538410698454422177097656794210978536625023878308478114883399005\ 1848442829534729467485220298906614573048906953865928929336443754119927062895255768433314052113\ 3698955277089114622402268507603783700859770261095049454142000014456733409619086853616942664702\ 2113705216692833530885372509477414190967821479239393891331555683962112110028997578030898050710\ 9888185491245618772390685818898589496136994275190714333429332462476838399270117991728465479665\ 5837910555013293814317532533297820309465372016641554280961310418788416615497680286526087274032\ 0623187737831023840406547830724741363192759786341690190075290020147749613374565765569334780615\ 9847700996028966499817533041336683336636323850752361410818170429538900569357592291794606988913\ 8129140041751398994826148258194159681294235782595594850002670398417307513995547230899194949652\ 3513800414094192653491634005837481107208995261648663358282942310153989038452716722912483040656\ 0102102961470498991589576001081973926238567416945639951590614203976102098166886701261387246027\ 1573079075581119921041731871270961619347998916618631664177759458577744700760321443755435866277\ 0679265706464002021678416680865461239208007396830139998273854227346936136488760641642949909591\ 7565845040964252470838404115337058050169718256715074539755387891270382418317574936515953945187\ 2185519219196692274069136978645465001077479969862626993432242349363391888537854928503571544151\ 7788082542146340343559211052599032381576776895218454680099096678696438811452040421694214441685\ 8368485319590375300445474699227639967531002304447713507129039003585866234308667008965498609320\ 8395323826099545543888535757656241930198459948666560286258585373945512487426181971473097987612\ 4480947742888404187444752870326842337611634100810331083241328318058637415263675897351126719754\ 5036458392529715746520456501270892091648007964108607999219351539484003296454253099806880372081\ 5442828157639876019273673899166100827532492714425825197858556678253763984666261746429524953117\ 1129166711749573426958246554308588207468584633516847816243649515531962349144698280751259864813\ 5082100532174357121796314875077104477437123220058048698529936208962870085889028126833799599032\ 8455841290424883779903685840610084363251321381545406535842204694639793507181205186316705623893\ 7150588306252680568794677164054289745225940499056356762448090608919679517790032611631838009276\ 8703347077205938519914254541662961614695328172586868990855170799444110123793046242252919903885\ 9908867109014174631597155482156460121619962303361049232643307798151680118266723707157943944533\ 5108779198049351626413551944810148389646074443428367084042066317540012310100551878019917773679\ 8238116508384700729535016835744116377933537011136705860068998435707048281982303724052463576380\ 4389161343076398606786406399463251304975973198689990155450911695044404573434537712909138945313\ 0195583699445697744871161451055368539911017174095322814757867182348442880906783443091618671165\ 6312997377864281004127638037667049241837975668029369188098741992602263066306313158939867700787\ 1768232330290290629672807094989014120901401926815550219908703720004326641021850542310320937793\ 8879206773388866001959931604249956992339728210093432848489306012042441084709222844810752149150\ 8724211039685245534099839846816208642458422111468477640738747401057606770054803522050714304249\ 7616725905231060127509760385585599360510401161009048329059397829420337767600107879696529426732\ 3118939568187736631395024540872379459514045257381435461122942113506291502013159008411582299035\ 2233878726035236453775486575524057359636287022058280241738499857405320648506307923969337421763\ 4472182244614520982361819924122150597837355998924994021573478815982860115056536278046376960490\ 9874423908795214175327117123603648810635212766790315741574528660825844237620788683959548866828\ 2288991995570033983128756990200450163795164025390794153530809769185381734960048598622865029368\ 7321986645320968479487419993487914540065144173178519605082606332327721833443461026108084990523\ 1238700989830343553295818265539862118537029655018588435919529051741420394447779780213521447519\ 0205387958511553096079648925888162146224513044714491015201300394773239196035894811128141349600\ 9961456475183357432680649725855039095232287064407674301424628630361678460899892917105668486954\ 2947626848524285321100590441076805400428184378792577885194486997682931415537467437925551900703\ 7583867001308559733591427615607642604231220686974243102206202904488738228230615905087156144797\ 6310759580209164405392110274345418391608875664332592989982667509784281091098062277959181719503\ 3086757938079150941560726858420359448908864046361239602887047648969207201153332227097326920190\ 6274906338920398570448431948614341681585841462100745672207256806591672789854863363688086229136\ 3682199409976340411154023069411374166361562139550556059780848684494696449626245838860140105413\ 4134206059955907766033208748115891971900327274957040997833987682835728532978708399768856258793\ 2541960287252722975092020047359310946098740750323602086067894452578032231038847521501620304803\ 4676884480453959017247719544024377294770733183767542336042007271496245385700503082872653823480\ 0452653853545917426680292433923378859383882529685599319390537662400212226343961860711677997844\ 4154617049865264368583218529952495618293700436910334036980721377056579385813500093258125405449\ 9741800210918043822419585406549330448884673774229896217722531486461862480500916364620510963874\ 6900104789586394520659583828000346112068790862878462226953612684381937839633222803596623298348\ 6446973359729801705173664967787480302678376324387237929444890711973629147235345723131006983699\ 2727121692160694395252880979745639102907522783639722148473420522393623603488034035247160496665\ 3045320863215751130478304885199324487053566987355136295153942019592037754130946899412711266449\ 9887310209769675508137869322228405574529650164028639497973246958021762056637058570834642732406\ 2409041837749082457704347108862434261325739606819550011205892487936558326155452680340676048071\ 0444850984403222009035508218506389700916576458940943464216408838882686894113737860594028270665\ 4069365270745047570884494778061029654642133844647973335490555047833772602136206674172389070891\ 2814642934181361710846935529216068066635427765655404513730022204880164991805574816349206655047\ 9535463590210288157448851051534131531728974722301529543525165535520273690540746173167251831501\ 6864018671189656416585701848097640513388011175544700095901284234057277996251029059445142222094\ 3228190056925659040852804721041032862740779450408042374888182538573898471042297537852265310710\ 1330467491356004280734436855867087382354223564786781813808924239274589791272083917313712898953\ 5664089615952729822403651350998565936881320215271341414268979136490372455933770618654491633987\ 9156973360887854105055813737994933312097292037430677163456954925581764332532600009827038310300\ 5343160579370116453257819655474757877406054590372222061260196489768255656927834913610740616072\ 4582623542681057934294133295800036632739265516582372983891527615379615963829013563332280777990\ 1756358405097868451677085140675466436470218636327210731073053974929634879727850523591398189378\ 5264753526344966755728286199985125560644831483765254250520736659057860229952863923918140363220\ 6892647920485307468351148370954227845554193411209371243691586078572571755884113831495990786398\ 9229254308305358486669194208980284601777586731987068917366275575048616729663339886206257538518\ 1616301309288991886926580702403181417488835642233852901937124064711755265432838973855786255059\ 2973708779046773857863714607875216418757766259160802375157139146673588971479310324896402236767\ 1225036318891077203749264795364034024169624539791896024298051485651816450857921898141294561538\ 5867304522566649562182708428920417055952672216533346392349610489174276264050475550696545460071\ 3628213405339278516651666248359438248648710571106644316398500688641734965945328766798863526146\ 7402010257332957943442648766037163118188672839661712992639180714848506802354321530304121788679\ 1652266995906585540221103052926269990655231396069697334269319269668334489140830276209368232784\ 3213920338469431239875121030926885196486950426765595835817983427161892784062392403639724930028\ 8670726738102257311587321782064526971758132151597334395457296883229775755202520982722352177076\ 8627890313828350820211814078797216261078266909485678512555796885264309922363267059637078923377\ 0517769592667989316492277048532032814886925643937159129648348490958227319434292970026409456518\ 8143731159106306629661037110484731281962224295971701925853133415640962590809522098249632244906\ 9394991941232535999980177610089255931344085700410715774474147644933450985265611621014412836787\ 5804882374537302626452939013007551027278076151999135271964740072361428545417893784353414657376\ 7785392456835807194016092042696274457083622597918358045287164588694079445017775452970120604341\ 8240123315191834000048732920339302258362118401246937440081805056448347571943265230220515829935\ 5708298269578661825393321110810907917491106293679496609665666593741360869147325254264041084027\ 7273831944638602511304578067195977907056710854147651369381151887938922554527545857156123380117\ 9754405849347109268590330618344138444190144041349600393397594687074206027007103521309489487769\ 9914156567568037429561994470469629219234825307525093003066174220330100855186847481345547359085\ 5049889416992328923979858816970326109403500452376733651172083757585900463900160765828770154623\ 4328003941395507589595598371603946241152322273847148636857495948104400174950332357813151959523\ 0933190979490113131239636866081137635317386329639085547698280055046472399376088611150632588661\ 4409856925414034676349532619101219167782781523804385286621812055028046419892473011090685405951\ 2176052939181121068561693206828201575779913406802558379307491213963046788145261928484326502964\ 8531322438543345561822481121172583504577213018894928138620519479116351060473131371579973561271\ 7104069584562405834313779544720183091956055466475720578063880703110797933393202912018840973859\ 7807997836604860101765721597958882074704093023939245323893683993634983265021853597091443758424\ 9313360575601903552470068379890363230802392850557374562331102484671764805821773044031589650166\ 2825410090514041591149145292383914769747242653876760655102707235166376146950443451078217294774\ 0209231752125908726031712320294455461623800343353841550616331079732179204579926405213789171874\ 8937234120824801814604626663860585756058959237360368889944276462132678355610150145480347501188\ 9111571048553132063838640002649734775269772901795507611231723157019037437839605827388102585601\ 6808156810894477773584891623379854748624794000155255414642902890227871726924893947440569891959\ 0023192331339288271299910957685406631463123223416255655192950482481738438909484439826825766604\ 6701456171947276295661444044308313782654613034658065143018909924908772583183971574158437558310\ 6383402507254923589143997072050936013053213573073443049056178925506501312496990731501114423468\ 0673865297342264577843458199709396849618318831904483078213365899388453504918457566768040165400\ 1627113477024591015976171477182320004294329026655905709080024484691312677100642894017339140561\ 0443029636919476494643179849337748808327685892122727263180569827502341258261941980228285203938\ 2555940716864639210847893224425714182077752765267017370528125773567526601870433955051662934923\ 2565263290917343611556689701854300263431804104718887865402217856816119455789197707864577164003\ 1051582890627761852939050458923821105068707171790478344283328839339081898611755270231558622108\ 5974236594947011427917905255365430029617573804507342842454159686746275246741576723025359340639\ 4050328545619233352162111006822600350937287912863812264813835132182814407858293207401150664009\ 9032853047938728942467986155792565350604175755127968675221027432460054686663912517983649073400\ 4518597969287894644432845970114412556075138588674538306323245973278360551372400617657489298884\ 3543273502919760887769301229756612327400691502877970696597203306939176033014760011335260748837\ 2466517772627278017770234971273065043753252445235135430454522806915695209381384763058541553618\ 8682780281946174034321568653457800105614310790527073194840410685697434551369990911615877528864\ 4373137117888314824768827727206409875487186574389592016470123117376243852326483403754610453747\ 9927397843961306425344519244921431838666548350848282327589483553774662298673457985356251182278\ 6733858828476104006605233619677822263267676950502582934126635116381821109290670405415194967952\ 0709481287294419994837732885593906801718210610918618669344706083310360355823121674971591721295\ 7168488709054259765982716263354798873746477020767048343331593328991887918072079052973520802046\ 1659486776259706776620811272005738363052153069963856435687573471148115267784887062962048157681\ 4255416466702407287269313099510445179160325163801475787819830874331320949551048715356776249530\ 2248171789238098259021289216965151989076243004306145188548871482837194269893872552815837312045\ 0616962547889736529459434269436168344794456927757315007934513903605312455513084411254207345833\ 5511520231289800434363349701267285643449286007072639803103473840894630074364605372616726000009\ 0356498260019206575784557169470464022829984986002341174294477806875145648713937266866419732316\ 5119279366164992187450054809100641517366685599780947571170887759606791190065330562398361188590\ 9493882963510471561229905278346073563102354000181016872091379478186984181268256236286848913037\ 0998218484168834020403926067719988175578786556339348585252642806920343200795914595922944371100\ 1572185658557969556626686661445152630613600186874736313858458821143060273644828925939016221977\ 0312340971615192548534817677227577191527255452630504141382419735686258391920367474190785351371\ 5864683822060952242180215421062522953841074881441620334410155425386461402666101977889266271148\ 7823300975190959074650504811095833999090608317923818196788457535006377966966567611322501710508\ 1662928675512167195632903031037533500742154211467621970126203725518008018929892751511688978806\ 0683945950266465581866095019870686593521124517132675539463354750275725413999987165756240978284\ 4442003898724113084806022259417777291313774360365800130696663186689881401078978037762679837634\ 4471469112451137266800417189978726883910777462896396026171778013998135787668098918491377308104\ 4727108687052692066015456026975247494294156085394469580422794159755519945716907624368679313271\ 8645262741176864127769824469342834589643885968073529072780966116273131983503690670382317342462\ 3755289074157295816127340404065182551399251906723884011383356390199073471062502867472579149378\ 5710631111982212118468854130461650635698735010847776612240520577217713624926092277269810876296\ 3482182962485099164100441174507394947013299265629532188018521029454194799305938784673225868910\ 5780083125221804162004497153521176481312336554017183861877551013704281430179662969373594051806\ 7996676678358809726471984775375253794445159986048668821515697440335862980871255947186939774921\ 0540216844614420729015067280052221224120142048360810042171003132618612644996340987175327858751\ 4173182605963996395126179326760308076428379955409863326600176622079483444729437415533505701726\ 3286676208084002102742897715894307728360694450427229644218837675838387566891938368884060299539\ 9899718706907568355868890397595880590361408915540335590469699210830388796479487479362591533684\ 4778017405754582138326603405362128362736547313039996875042955743962721214488044169640931447998\ 9194873827540709747746945178284262514092894625378257696591680956446941012314560302626372656908\ 3693773847500834935183689250633382010327572774972846492201448490532273652253676968813375766106\ 4456685167507439728569021968869894150558522901315515235440388075741063349146822376495289784753\ 1242507222451449121628923616961446777224212916541092250566610008293774966707568168434269681324\ 7903799385354039064209465670255900429641620155544201794468435049687708551861520599636985392874\ 6073730976304086733427751912938713032094720852249519001043060067462970403952418402181788318965\ 3614127292282080056260936576114256024114526376173049886542755678141981524461181992740612431158\ 2286757763707920091609546934189512205286440051805571933470408797836228471740342185971814463136\ 4717522952042536732405126520196288196355117260062998405390468291612314521466309967821256797572\ 8050529921400249962518419550060389178090959537089279797648533329784159212840220650253570963203\ 9113238107416706806898866294650769083842593311443972964413649026356992716037080587163574331528\ 5096641437626211720781745715789176157372423775783257674335413383026302905500242485295121202724\ 4628269944328768363546482449795873699694278905187719564386563513201213840323970605148391745760\ 3525270852489132249380304618535376689379317905833635933325034087205764066036837477301452664543\ 5848769161174032142232610627019129600312019284686520992869136668776756526636779682489974759422\ 6357260053267706470388982226429007895908093736985979983349403651236388608314260480856592823537\ 5761650714730191711408139270630400200004195877308201657330336296730533721270667553861604434972\ 7662599979110304178369190715317694631992858599384819170453841938470302684024357383980628186672\ 2788825740311285276677164281466264693271573897913714548020118184829783956700038969943091230430\ 7378108035577489162269205961040612267818022663624563053152017774943908933851900581666951075446\ 0098809797535520304912022042719183822163408303249742175658238083753206695168766520455426185109\ 6585796842705786025828526420037233504538033638159973502432839724353972941369927555744256204588\ 1563324426695729151506310722190054691832423863732020587021816630045043955925073822120557078169\ 3707647688489957849944545792103815362857903390051684823891633248192436201713893789120324385221\ 1167198839750946397445984586649179182043730002913643998009138206726837573255246298164158002796\ 7544734282666017912685547154486413416099190295896583233911384839572996458766238200140561807581\ 0620275542104788135656935517266334368612587202705336131538771368214200366134242055825509706663\ 4462916873003290433821292974039651065637561853081068712638624491906482086347116589240892871811\ 5155400651663252437732444831406423937145326414570286924931130836517215574495407239385647298731\ 4851325514695617507198933901540763027736521658699028792321998099411778410334909228791763168603\ 5495482761816270711800852966127581902161801519403792104812526117315562311922684754111054178171\ 0953738269194944078450707809524582056603231614007255138966398259566605781584902646215657147715\ 6973829835731408021781713179893535950485527600726413763427555541111344428053259163795266186364\ 3662344538859595913398416273446673595970064972049467975516213009726150712549014350789266487571\ 7666548468476007471107721413845751789406558810830691109357224488561682181182909325769322364289\ 1875511223577821498825388975145250266763200463082088930875400532430816850966641964596964734130\ 3482725848949361516998942487148416198219017615645564169882864657248289753598633456339817823944\ 4547778717341397697216629321891958516489688141537800123982754638267528544245153862576612530821\ 5163466867464090364814251932367752688208336700656126950691279970767584853018803289268147755304\ 3581565038354061490554897739538846706717772226453103079822673216194259175487334572101882831498\ 0272970135433302252522299607850983940066581872278222291534622080259521597210718649494738858744\ 4623792302891538771048347343948812802124059314986668972068585602415936464989403402472389599482\ 1041685619723891198680455409995573492958329899411303128445089529018237582265045289880548946324\ 8443988201350615560562452382912892803751191894595007526019415775257842055268894706669586060824\ 5747985511627339365717549179562864854020298004059979484554339029889878568797156044443707711556\ 7681731921573550817160880380774079784303780313106878652710792340801315586482402881553077558357\ 1258611683724661973087823755280804743029020051987827496956679919488760373579162166313493721546\ 4940322755535219803929467713659620880563866589131340435330707475814459411494062553987972033338\ 0152261943996694277772409031875840164614415569017945578469588110770827562910083681929463868410\ 6601829109387173127383991812851492982570981622191527107582938324630606059101462161405973286374\ 7789852545788607427338737443738283783432729654372849825796608441506882184451443304499226521240\ 4847539416520930203433018925401367023083714256250277827357417481943657296622954405108025983648\ 1001540081154120065727656042564908437749368658251591896175676071091674195115609728136434792078\ 5210982736521156566584045980438064260254829142833697292037725844089312825978074730599424106165\ 3930741277894719945325022855088476826146794238154986250422706757744550241968699738500524869585\ 4891506517099001459226633626609387052810663980362472431672900331131088147341495594778064088679\ 5488617862077807660426235685349073868783319826795373583440447574635073331830415782742752393514\ 2562249947748858936059962504182886996336140857011289095301871755521440788906725845218433457232\ 5054998223477928907324553751476904510686041831792985939166736256124690708522933811640022553436\ 6769689693996251127558530597025367072328853680083211743165835336901169193421877465212075386137\ 3532429917859610527909791836875924918307908389466726681810460277454086578450728648465814478887\ 4432846103452691954071876804368232409866299928666149333109019171704374520870211478898473893764\ 7917756786127756354754212746110214690579182625049564667029575669459483403288732965467181736423\ 4499029581799708413702817185659673541452854888770007029816318630230084075508001868491053475831\ 5772222722261394377815964297302805844215230432870946085486538275389196984680692848644219711563\ 8903436474384355858806441142067587747865776117557116336060728604152226159309734496366307772850\ 8354767425767059012562834069354536682177182250332714957855664463603308801116348260413808707719\ 6089631944980864878655373864059802097357094552109346616866605828686255686233286287234169928977\ 1225853030173505391763192780446426222680513083890928409567995189902589624629614034390957331360\ 5750534813593297029037824611615579632976340921401199472691339101986613728880289040457662571607\ 3706873668528955639143544113912378231735655595058681635856781618457938689686322959877426278457\ 2141813747610947773316015021564264673929306089835798091561608259723500097633478741162706341735\ 1182620198098535799239421446483462036012167768995936148546088870748955599759086789195380869501\ 5149869759182413081639682348460093329210091700501970452226928139792531331421781377310667670764\ 3721517141965563822913919248691634884444370204372581880881357006645983802819530113697414365609\ 9248608624926465838849259684154525551310763554911894920965098045238617897878432472025966193310\ 9697681692572125433694862483068338678858468102909298785472449567640365427740590948781231507419\ 3441147366370332128811569910166928966956030497406881212899786861068915131671896147652623823949\ 0047932900385364976726742721325374211926998133464937953817802058961079920860542897449038969489\ 0094256843958910940616633103942414690553295717941223505106274174348605005768791027837285719029\ 2180472452254540932705508484487730441227012807571403154437772381218110490508098416852597248008\ 0291119372759200627092565973032018692422356210838573278964412080677393400884767131780381716969\ 4006197706885979408844784401942414410589099000793680703572032293606968744658100034404005397898\ 5508762598777502403567359856078464840976933241161649993804838275174562375259264772902402498744\ 5529108280983122144075687163821048924613639580566886528030854670120504831404756483091323585642\ 0784852989712832722320831745926594729295162276516715586630463974267026608954743219540067320736\ 0774632029291135055788119708042825175505947924085994451214371748824573968996561343863256705741\ 3532823097342176443820370728961682182385751445553543083702656772574792439010869430614122435097\ 8780891942330658532098457302810281331529122137553908724444915730404210686557733845872922065563\ 5137657286471298419715593381887130329057291988201142052891921248610613139659498437901714656511\ 2173679634496338477062615440209890510544144432303044543899643749004431675040705445066031551025\ 9238258622994811073105240437405753494302816266029374413731472277370071627439683971527264953153\ 7297911058746208176591013513719845321352575937555633502899627493889765130018304896403364564013\ 1423500095178345639044279529535652506034539003902984592268370789750761681189771581746031256022\ 8110681271640581263013723713576769499926357123303335354123944852499327703333058154703388328026\ 7189209350400769820459891857239886612558561329374042387175322238743164554817004948092815225226\ 6416933205321906084110728339927656186465781200906095546274880585691721548979751656888256390620\ 7467515270158430005550227945697923288222069621473359960612719718415519721922701244785036345861\ 6995138109895057856930979491339614144798985028573550938449075556675892610670836773552150046941\ 5835356536449833626816801254073976514105734995962401349183036051284918471451537504342525915383\ 0392729489895102377160306640789148729840381850078788848239605728083823463609806280305617464223\ 4235955951091554169458370785425044588437839705457538514963308539234578540404522789329146780005\ 4948230984767516449785796637157613760856100824191780015311361001714670143308730926774908614223\ 4099084552689278587115276827799549148419878593762318764997996480709731723369601576623817777742\ 3880959998147094674498669591749467378310489974147268655382212946188236178918491499936155633904\ 3880007413486510155031117952846339593061112870606252425275513198031710562080936940827517362231\ 5869828334530877095714721916767390817074336511034332022414552543687531844482620253551413625410\ 8790855810982542847002405869357477740280162471742859249459713501406841066344141108780745635022\ 5721881038186001425058257515251911593572765423208902663945633906347183455663601636055519402891\ 5089186511379962680799385965413130590027434744669736719344545423844330618382828811669757883621\ 2554194078806370995618314390506012313125119615711945957551337283523516941584612774055470692464\ 4541703223549487510536172211597292704045972465986067759111676348254687854461163311995896638336\ 5311679044527369565831453604375605506438369491990841171141734882956976515709516160748294030094\ 3568899714552350765506736085502498830719253001856563210436854101726969677345338005845952492390\ 1693813439545273074010778128494202484887527420508065886795920867053044896019895856966182114146\ 1484394182285203420714614511506499644136986579283694652223030051091626484618424376371228239463\ 4073057003964987067097595390401846963982456554064371404313485655458337464090162704436929582338\ 5723738416837897287461029673434923017750716411967259291532168935111535064428198895426064667404\ 5922321306901099767179863719085993973947476652560360756562759153659388994321342377856487318050\ 9507229526071919464681603276615198799042499091888065341152789518027537830225759307172173642571\ 3641421087783668453259935367893828898290151251687053585845457522854178307195749841953747967950\ 7634859329160122330245082405712061630830823277143848506776673554484229804530277211377928618789\ 8313906857608383243594729878684924390484711747191916871849324114813687457873337361895157774529\ 3189536491446085839367099877880353175714244964371480420093376904373579508792565788762788974246\ 8758709803246981810253906480031618590675928792697500673238553552296157250384259542950257747903\ 5794806221034786400177465643608958870396264379355425151172565555644798310879484203673753316085\ 2294015236191256492827733637177374867171354055716819922726116457526566020394348956961809821499\ 9671947169559910301194798919492535829386359089858294950115112348734850093439893145728678494231\ 0779557417273414942024868523521027573134485752888920467348893490060655610742919331208032886701\ 4188057341679780328127384458712271519861255659104030622091367691482924486821267247182089881834\ 1305922376976216644955834112325350468696078622134925263795678360052626889157972346004562730805\ 9191019896602165667219647163670055764593465389873656230923102608051665186353074617716202026855\ 2198072910012241999952551006770538762660757826346090511233001280238982813952260909619563021060\ 6449100825509169632540597249065652150893248902488580662450872380101139306311281619454983337503\ 6389045753128668782388248948334979084827640716151437492199188855458373865347224258021018931650\ 7376570225188306220778482414814952734157783094639505178542173954523620473372391816148487301809\ 4915847048833476752914113705349350119416486732683210799500038950441764240986299539032328377890\ 7549213352974344502788757050804033190812475022243410933849134726795253759154431303630618214158\ 5298981769198770974390838556299176297362136254613380515979580626706451431701371994588549219028\ 2539122959974834478692259300951125749970859566227195342040888519360364992234916724157298817481\ 9582878257710526380931683849502008097028711850953400769032864905725232288793524342480826210588\ 9848558582178428942090191964296535964725014314814574506646532548821803765607104744892320548136\ 1655199523162399884311333489462907833008690830130318894983276735756033003330761246042939611035\ 2086430884389828018426974130442213049090221690954813217718306168596290525200271258403544607135\ 3219445936490115337159203368231597028935000623328735901951424880836670391056142391134400549224\ 2566093569284479242092341535552966363690621278600346828682758397443614076218055735608065014510\ 7729057396473423507308128524465852664545847844957693690306877191346581364579156454891534134101\ 4020107970353190054344669163301468554714186721928459152034526118576727147588710898234911838673\ 0705972895711829372393778188639440626838387765658991985538648676077228802019843405328871409001\ 7952307526889326889570063784210229480500357994053137449703170444786700835756778713053605701058\ 7148142351203303709874490407215869353152702737103381572666974957693299672621058514774518493700\ 2104762441941635949397355931317414697781156596417579244191107654934699790896309637924367289145\ 2685365383965699081637249653957152786117433027765881527642558471114055953416114813831772253549\ 2009697537631152946634671326817143389268701486497416567169078156525867027787089840368362199132\ 9859689425117111828043744709746847587118575209256916624175635766119158449375904762825489484213\ 0445761544695117838676424834860200557643449690379406504441698681012195921001095343041123113856\ 6037139712265257042425737003883429439080931425376042718703662609113264262921814098314128164568\ 0248975113972136174689337829863590906500113924797197115790377010206166423848979341010942227056\ 3281279599277010111271670015748856682197813372225521657393440045596341081999294381869008748947\ 0298770104444584442862554751542233654183809013861546480131683837413537638833122525045553374868\ 0805266921849010905000845283957819803200189177203334088094460191408617495520951889566449842295\ 9592633139820635663871270406293606938817273180838821470152860661502762046325424322276360266841\ 5164045266034295456871137931320104853616365628588343747959484745705377986313545860588583016222\ 9524497905447294607847266780033491059228587821954471737553382716029421135926959895145314300409\ 5956931263869972037750932165368343778126475904481737937911460396014957719555761497717597399857\ 8057892478212435739467296253775470381399879768046142486949177146032807380889277045193807416923\ 3989056082063179406260013643405775463596233805091497433465887343409432019245901859812638588359\ 8309394871134214859828463262983329596622368504025459635553053568104875208859487151416362887162\ 0027919688859305746514401799815989264851245383965279035509851177493126200774373741940061332806\ 0849991781160928957987213196530040189172292866823364022994955225354434496281360135635488541597\ 9536853151384427126206048442577560520171638814055821857731755656003514929968264805263961907460\ 2014619012554462710342703679143046431408327078735350190608571286863223066601009950014161723778\ 5593803100277960692013488294530990692466162024016085922280932378088313805797059015159339999206\ 0821952225822867113605907934153420931106368250191129299115419673314202187424402119588418893969\ 0464457653872767616148735683587295385653542421736383942556608743764015604383543873045526105260\ 4985329753365487580354372244767739223871510347009348155642185391454173983126908824691246437719\ 8743408292396423531595117498572518377800902867511117913931847544667572688929706379372461736976\ 0446781028603899226564095683624799369013574388461896290368906724428727514799911543443192222676\ 4875979508764086863096872690690939920683625586850982402745765234469253541191450842468393384273\ 3332162598332321701106898381915049409692474072335796561866533749834219615301065342236065033153\ 1299860163053190461482281904414254086474098723690840883818417061983627253402215742198719374712\ 4326450725645245294577964092325636735503109112781258668745155583114474752160369471093153184991\ 0841239108573549725617487232032542633330705582863951555726402131316052432946911193295623413439\ 0558849775886367937957236977285707350990266072108826367397690309857444709387683268104299764193\ 6768656342467304606316906944226266815791051099397249840952748649561393448257650060710160572129\ 2966092350988433938255455354406170494262281690586224979028983615566732681590458602113691829378\ 2575088659755152895786673583884184982548648941055967942873809906108115091589199850624277179378\ 3898965547631460435524439185668858992740766973021726632432089366087310774542929774868076632300\ 8175543886890216196690412657995127096188580500793815480696082410371374858638299445730334961959\ 0059317420638703598854892284743752695111983970784254219712099594601616117042978105607048341324\ 5727909028319406412669795243138294671813299958773912661335317447123540989249221321027581842774\ 1469558694054451233549372292029944109522242179421880451763916523672340672444012443458335952122\ 1335852422666991452679029740840939581623701847768968118076937060159925880121020784255765773314\ 9864472164540526144918354674223743516458017806666320697883707134334074549542231165127829053536\ 3154974797260053880054678646933317848447100156788203752923743089090360324601561226128575672448\ 3855838653408587452000362085358692924065555132358897251083116690814043560012411116252217536129\ 2018708825296112824830661045591792179218157596786862245223634754704614629616928264296805473558\ 0461146196201393647983948409977552147592507230421334387845339428379895355408265749500679235090\ 7394314779967218640431213805516183874613076127322593989882716396839022489344613845959864149549\ 3821617382425225955409415802517277279178213046467092545359100360186206385166674160375787589803\ 4439482655298359872218124092466318216178938570341772615919052509707123032135786509683700823464\ 5768114666499461566995470513174657118588903441758735131728968904417951665214160189087987503247\ 4220153106882421912184490084109254820409761830977082546200004814981592550418674495709301606889\ 2739114626898402601267166964007887431261068314719582231071088228233012513829863342188658455751\ 3818717155163492077377183655104121809565421811709881524396303491920119668284629690355986663592\ 1884145982249144395724451623099157009641848482325658559735350375130284017007870046978777946113\ 1203392194214219301672324724098322628196170758202214077970501108197949569420836835719615709433\ 1002793059400791171582269672340484556116813406370188663129852657464841683555740249116063976081\ 3585551806937067273603076698840380924080977978082525650364385496155583122927480638105045283083\ 3720559010762641476103812967210909803024339322406579706887475531158840480308013666629133316204\ 8078262542404694251336295508708444203664716743038320463038552167335028157167197459798074907209\ 7691720742679155085811189764015250323589052874573018437525395467213366235154606516356233734265\ 7756597923508246224365443299562596881527828586916117816249608413751919783693022043911254032254\ 0737710965154677197890394365778147260374548986984936577252656267250946016958630389912624277223\ 5278031073591295561700837679224274720915169871961411681440303268455163705443208123325166617660\ 0989289109715787276155202606857176197391690404787045384223413325221607369726314782948551498438\ 8316922448353054925457783484706603955532284579545169968526917725007534734741679010929286726807\ 9196945532445919096151221668083571313967056406838369426351223455424751402694937969733484611248\ 9422817330303281319700647187173310059502681815397752877949961735846627010918708448745879192138\ 5040645365538180662207643363555919516919169091768662234926418741688087585105157471559839927643\ 2823940439592234742145798617435563358375138519855151049687172401694928828333640278940776104136\ 2603987066745158984902074408257632094946450219155691732334870554546444004303248553256823261438\ 4840592153907927425342126347367507666468208738339882331515719044547779176914090067800223639406\ 8738789283609194689336442229246469562734415662596204773395553196491172791209158817129885636652\ 2049623548622691742993318651285755237046854095857652557664006354463942284595323923538303385793\ 8930299766043297082296018397133551011517867979183088258933439694281032459222417813133959016217\ 1558526751041472590289201117000527823739033175535715946755014675968009502343169391261303811870\ 5196875376919439214735236219196333354721072106961815701413864116779854140203366520879416416767\ 9148670622704740993405270858881406466674542441494441698692548763090809238310014954194894545002\ 5768197040533411567016274390301666411251932434744263280317215773511057565496751751803182115703\ 4605387051580162325962395395013981496726406324974946231530666061601115936541008109080907301622\ 0177467698072860830401602304825380082243008872850744907295404217586372712700186817990936290052\ 8590327648213340250920482848089454992856924985945924984052602846005121661680810894465681704391\ 2021504777058095183891964670285603348411856101044805161215843239429861185524844214115665202283\ 8530473824855035639817358239998190139880043607152294413052661243180698984643966523157219463367\ 2559193869686273358059140302515896778467221603437601451054747536827624982664132104166445381600\ 4981697300475447031523473963108545665874189736035203570385266808952271883197251018730313171199\ 6267438164468562964619271017922381781330422744834627306229406079566896380477414614752237420023\ 4279458195554954553135052571272538209555404450326448381339749721700477484424340464657250961427\ 8355328971524425102294796350060492493202323459450754863270879864191192379216376038800799233947\ 7301057274522586983765280586758556710598235743416007731893293064378374425748864921427192563181\ 6022036966755922623010407659116404851771948443103353486206042065717403257409870312269413665751\ 1544882617638471776256728171616585941163926097472139334338802793954996374049264296731322821850\ 2752018392886452021903139426453549518513425419445591360934523103497526294901298122985781159114\ 7057095048616271483861466154670735991451208081865683661324629199412730157234161606589474539688\ 8745848135576795900533721587450220401221549849940067249781294404307371631362594861349423252762\ 6920634363653880249067733435391309434638005288956940007273893191873528709610532172391255529331\ 5668642173687484514202227836765153147235068950503738062112871502252706566706488854266597239930\ 4614905766686762436100937033368100320890197977957031630102723539646451907714871302572313760052\ 9468048620905724744605304529565743952650663430097323975383071627337873292784965441329767290886\ 5801368788766050663276547987663793862255161346251629332532109473927033912006602340113682476048\ 3533576789499093074770172889183852368573249314466096011192062336698248417739292816067903586100\ 3854426351027278676934695184371601973610444782430082247325769866164952516696919676418752859121\ 7735378254293386758683651848516732997080331107931203070091967263409805244501104878877469995293\ 9150318773917959708603833838366695281205156418154702034064392046731433079893369684612381938671\ 6201943497091878622272755270328700623052889924232756502965155221526995673926030108803993216925\ 7158574811614237186253249926292154322314764157255660484056836745162671527483890813346385244431\ 5180238439759705327487114088373946527451515959823070947959963958359085323716518747048523064215\ 5127787302749248076927806687839928256058955783492495603831436125210317206890118535699761097569\ 5194055170781055185542940759971470288002357526527244653208317941229112806498745225406446392557\ 7190465614338276463660229547408193241282879290261668549425097094203389733632688488558625784909\ 4569388851727582176558126256847676566505315468924326106620061180282984173385054680395049022462\ 3081982874439207035031459637213420727851390876630326792424638828245279193743209496272075752540\ 9159438160575080580727557693327791709987719495321706028180236584563783303180968954038741769003\ 2561715133382767352305786858497993953755030408515561430005496419751408237951472213363967811532\ 5024738054282441978515118770521590173282156138533003346280472614341134818112971889081167672992\ 2103688202968052294224082012222602158685359989161336932629328307442523993948840727105237139439\ 4397978204547947605381522489292586450195642999771376733306058218632637486177843788316173520007\ 5688745551704155063101991148446657205365206927538182133377869882817637846666755443245624869925\ 9743008682617008626149827570145101082689054888152689647541760715198687910243048886258345276600\ 1269611800552390523773000572091634684384230328045274625003123386159080270677632522374377701019\ 9211541599954611944906169472812989608581359618791232759007208007260784306121514254856163591209\ 6266369881018905970967034154387240054537860940714372648495885694344427553436185039461014367527\ 0764108765184430109041954327742029106817536897662650166383655754574311067389164812493027331578\ 1112562406111608751622155048342079390127322285777992429997359201970166005192626093212546569813\ 5776467757749234440406507843282500641821116294436729085839517560438212872235325720868623722278\ 7675547941603947933935259028009984597088685346241878679874783516286975455520127008809705085777\ 8066516898490373985177697467241839800442869501061903988847891366791387675210326956345619630973\ 7150988141915492377245583503608729990442979595654324070870186228154409171223071970108110435227\ 0488849313768349995018415735642208475970306109921391778166529620932346381081836659958417864278\ 2559929465548645460185129563490756886015452465813578516680753888607730103583212368981701756185\ 2485859266230239352991123626975883800120544388276854666808306831247822999191481392589256716379\ 0526641795792933870178074656635703388266937067315538331395116815507423579842310661349912019191\ 5388087229527309921062437451268797881389786291399236863037131191555744652493560265427785277762\ 6132561971145674858408990012288110552766701069489528024537890598583644616187904965419533683891\ 1928561824973648259636187038960607073451013951366392463024438040167548920016936372095608345833\ 2414097565223566191669206435302197657923862649932813363963801495647854621590453847111189158569\ 3452262367467720796596299717325409121293831595929461677158123533757903741117420948319611739221\ 1736871207007118184350169916458326614434892099594650458257848593883414838569207147748203997971\ 6163134915279215424764670944338373293026018966214629117525732020823710380996578447629740786738\ 0324764289432006954626480282978387894663288116042818311598381759658745144305750966853761493451\ 9289974224655674295359212266331318672667563639086633066483552353199373362069283867538009454318\ 1348197933596082861925827422428590039948287913838823281664614210505080147049024414038075492799\ 2039605925455922179672667452978185694197427774798379569340798865092416103204345914164140108786\ 4215396301622793998351531771628237303703618789754057239753860242303943677850503106025114870794\ 2359844866758825227272634931279124530952993215915326216421455987942522693733488363527708561664\ 4498033658170219414043105790390406534886521716710692072034723925044163658418681081296418481009\ 0913686155120202756343455664450384720587929846123430602409681104850401368435150979139825375042\ 5082645578110745259386129821158569612216872327280843276037808938165565429208353957318970649643\ 1245225179308527662513934826407485701709709398495827528739577465656875877336696654967424621628\ 2545637118070604478622178252406908749384112289030754872524154250814906724957109755669189406530\ 9237559053789930854924184890750199786187512355642684094523413603164586068008237715807482006448\ 9656802748041997487718700493893592571435091127954448844910870073311882210426033866200645463947\ 0353919665514197875657827507429266198636732040763821916914742381390834199439967853338996790535\ 1545390611535077775585133164348353826594899991382579581933314313633804876478216224312029730377\ 2573062267019397766844051003733169975362630843556142981069391937215746132499527672481524553206\ 3718731093544024647552839747840969482503775521913117529759577184946070863560780629407935319606\ 8649113838460382479418576404741072672865304124018719079852430801551836337401042792193800883919\ 0363616624165348728050986505810836766019605284075399025356398869253478669512634726081591933218\ 3299605593746199460065355459436694555388068895956905578608262709661528354855406960767116476935\ 2044292848232239137487398775878104148697678166764679552896320777643715879668794299797194700800\ 0729239793661308248067292814429648936368990183991590741903408011996223869055646554434135216981\ 9910784116817098553559838260710720952341222720812620353005611608924237846222838900985033525680\ 3533720543835253305671089946412604752723950414460621693344865956349050620426775077159985999498\ 1428985417258815700964703929404474140957521827743272993493695736721365383070937216154612951636\ 4372553926681918645085131269876189826194561632552070487142912519642052497744664929033241881338\ 4777408869712209324402991362017350520050328104671737792522796993106922541763026525323719523043\ 2112288218553638104182253708141881050861232504870314746843712694419005977558382412418045119325\ 5854773930276735527016258000248646052406813064672146724564376645193940461285314274961011544453\ 9010937999194512436384268523622796023714883274419003949369887761745662300484765705861749731189\ 0996718718707135568062906506472625053250099498453334818404674366483644143938488523836389657243\ 8371979736826418620365236180664589622026799690407079173724796751201443127410081549216968955139\ 9823107022511747738543877180950280043953695197769854087762022463727826360078616397614352337908\ 6017237375719290886013689593441117821746548526680807819243531061933798761899981263551153417149\ 7158835195413679420016773567342700091453090570261519026363220713872601352977804744497957982226\ 6817235971483594898533505181113140113827843161000345362464804080524034197481173759863384627977\ 7193087340431483308254657361309933580305645408592697004676785931175057146121023154516079097055\ 5773389087718414676079410132731348696303792512787993964270781656055753835769384431971647534929\ 0327352593357173640168331537915860258151487792382623223179143068002230645699092475538521282085\ 8248623549096506614157952897997003571968352075290441341134657267465343620881638501386547980226\ 1403482259111480174436886294105833918639161899116540045659027644095620810048655481058021102049\ 4530477705865019384103751902676230042665039215139698606874806761298613427472193039980552579097\ 7450626132845793453097050265606818157347293098875383875109762355342097914796694957150607557385\ 1121895781575885831517710118917451241166768293447030063164961322692814997143300527866292662603\ 3827011281669784125652356250567406961011365274142175328363141467372740050917970282111299531616\ 6515287691931449919545161136331307107847507570781342843197591102139280340323141110244841075955\ 3336486296403716239720345131532967504266168195349996866290057172930733393997875382389567599115\ 8060983574818061552420088676249692210021040271093684703467729164513597550463430589430265534045\ 1649147284748827462663212565927496426757672123654730992387508324008299506197996402798626730812\ 7785053702389461833005174032459168841685553968973886929283175753021313665874110124507167170493\ 6915114896870215142325341076356249438383494971963319194718726938771689067344744702512826946870\ 3658809360679046957559056799882038817235186387775144825185013166827198496572880037534024581597\ 5583257812588622966849987336514364483732055947726116341239398962953988447071261755135479355243\ 5374133554696882788974721384300340143832290570588168381057329278540966315746172249059052830975\ 2022624744381167325544168552221180684530860418868546527620448047359813738504003051960880883879\ 5366749447432435621398967483562877191491701041835210055367121689834302675951603872860194264849\ 3390621569844428913179602861432324670865593996337786542129808499035417818282413778973065547463\ 9502872394965620743679159951903575561532810654405362854091106805467543510216346168376954191037\ 4446943193027712219129684071688779742358919775789984332905557650911569653975672513420432281172\ 4630089450735983160048059920309347461758261948528323758682000015472248918602729673664053488925\ 5803956708588030102463571324927721843235929825998928993515672878330051491211858626030487979285\ 9922314595835296794700792735356683136623263437700206334713992512292328266545367515438442900486\ 1083297999116525172286731353964408189320315324551745557735884912005570057150147915436147689074\ 8246807310222712786422629060934400667927764372920720075890344270122394315213788893702239336927\ 5979883878885938141687456837433086877760818362177812042788927829347860039533646676251588000601\ 9997377094397455780946474531249405672389039689719852271430690581258970990204101328562743552897\ 2108451659867073560711205026447824299748289013515493738148024418584619962328466644395344593238\ 4833501585912313815655238774663686864100667203737214173354928014803559647082780880418865040801\ 1011628176517402554368690968000436977506103235583636140731704593838374095335070882696487789749\ 0810424337145887075169768887181683233402095429936143045360398541508062928644727423449464101300\ 9013580862277384648816412701692978282259034561299215172300968925437253153633682412977575261580\ 5417090768391482580948854449908408242554602507459039516713418545777598005074199189749456889591\ 1256986434140959989139847505942194084555388175368012294106618582654373489914388718370963919028\ 0756237637804254137889259083578183641814447432282696710822017356494473866510116463037671337655\ 2414693606696519960460799430883519731635383673554120099378215450264073207542305164208312816955\ 2057781013384605511374092329635482228075933346671104503244252616860473236451808430479273059566\ 6236380132206640972738792112310307774792717588901582042808288599680194446497823865683858248914\ 2670644690606545310869817736307818649603094448795003200811295747043475633329980301176638617619\ 1902734853055600825718634242045877183223897616543960254011740940853682694403093193856692133282\ 1453030831124193742064885123036702844754448943678545153808571435138924544300444238577380578808\ 7577670353412574842280908113614608552767498522966592106848643768244176129451739144308308633588\ 2230418457092613400375954478837003106784035221345253227082859021822553580463863271968098798619\ 1160540711238121971787489786818689318499797072404318526885424036614248594202026709912171257299\ 5827683331836030734610973986561538894307338207056058373198707785212045670142236040209830217491\ 1295030997061630569477293601583366152887793992078278943679890452385040906092190977368595216273\ 9612126249697369621716621380284452458667969285463178966222325372267824530251058094478031427370\ 0488308235001279612331815968949325286281042705016754967315646931128229178659431674190957237604\ 8874180956890397919815805974787996499493303658522877951060663828375491144114534986272933057680\ 1738984383766004373379528853749770489460874598926498459425733971014414601925135678992216710230\ 9071905348446018304850685501262184690241087154181547437456297175375480739350931234850851629762\ 9599501565710391898900015159137759263090105693333657399595912450546789549812073351473104522218\ 8482801638874202149926456103203539077276695572731012259046405743446748205474594414714062188231\ 2522807957568613884070752372169536682962721669783573916374668684348706488444768785836124078250\ 5034158448819946106550966282724171308019440326234207735604571405634062117257701334878787230640\ 3936774628294472540593094747865452425135820354618131580799538205441699349812307752852671483359\ 2912474823554636623892828338391437953432145521139122892971808790295233737681187921811681125719\ 8835203587818168351839567453084584805139540704312162714377331066147151239327402171671687520138\ 6076820508634958347442913304874804780766825071632739538849438792364912007246329497142173819997\ 7122889300535022037748879713309476697148446791919718018857480263210022026022876265462773225889\ 4785985186079576774250957589896994990055672811825643795024403164486103541515837809946492027086\ 1455019905063114613479599323985075450104609117649130404377223299833147764509096490309442292378\ 0674930946277694593168405210142159001352322825512516901581741937902293017629923830835209760271\ 1842951803858051187892903194980917947728092150129022929541319159918597673187445054958008093869\ 7673040503638304946943295945909354139819172283973348539227998041998812638730496669263919345147\ 9912776617365457066012839653705776484809802420113738939005871857595413276108579397183017321356\ 2962557661023357079806046652286921516338026894268773828558819366005914509909427699931672847975\ 9659566047274185674744195830316277183587221159795345111391633701811464614046212510993020512503\ 9844067257025556915605716388721293947147739004292282135092792036438623121223894211497364926647\ 7627885487616608048060095767788467606129887991656188342272335398490098968417833998185942496067\ 4284989211481956323294870392236671389583416263560241633556268380652722767611543362460943263314\ 9142306482376129685587917282937203042286428169375391230539071932879171174995255307278591870088\ 0037745170323581544684083222615867082822544468555384671727198410683882257842107736314153695769\ 4145989240025169614830924779405680523026026650736069055748009164510834619128717159537306074938\ 9688320765638150223826719315193313397419294639082219394210520023671029624848337243049029180557\ 9469871202931619140848144938173312189607216444927615719137596352092791578133553860233273369462\ 5531740342597743835712534989769358077872854626970529283524728580203190337028283158235520188989\ 5754543738823022803525586735810068158068604412512868536953992870011966982870953106547684405405\ 1238426204885723992588135582408491870475612878041725048113500897344565507337091762401022407128\ 7873169198711178759897092592568855137858427935205414813148822919641919796581190113758727787235\ 5342009961179286620930102107304954205336358878368920861199939818937380394784477142390036195307\ 9875672657799020281611943850124320688555452089288575809742520323652205602861707239437500669394\ 2322335817792923362794242704338466226365859057657133795972258657054224554490172743474314584083\ 0447393696989694515031395721462956773488078665139654822457310126261808534380539738955887467771\ 6781550451237346086545173203142297274138483280531987675214683890922957922162505742466400831640\ 6395775347276507480393931082784906987727201276673267160516924599680049540869279575383401856591\ 6064761025878616779111996974987921833491197274972158211976968861094570201460893335126753699066\ 8142176205769592894450849326194414195502551808176618561056909139945014752668151988220695154380\ 2688016623132871658528067717123018231750863437463210172029316495699641323119999685029197812605\ 3863846004282709722967628586326440409697772921372390349994773946648377541665137399511387096770\ 3550619918761977014217667562206478167726415551891434586058607292572829205116699992021806210505\ 3089917111475745902513024376155666550831499064907433136351796819151909216909873734160601810596\ 5883846956407131431297159666623056636464998845468569371822643986599110342340200520379715011036\ 5675877261608226484211984175674820903330054785478588935493243416583050753237479757171815165685\ 2196652143536741622044170086470423081962412427023281181543480588371904980049528358866318268813\ 4864371770672564944089184991000028001133161040551143756974763251907418807677546414072276064854\ 2550845523400746488443330674969809920221380769367419055481011976302238748670084091582633670158\ 6412083511653521967122815344175739408713367653805088413095150780804751272221921769050966585547\ 2296886858794554752762163220530319312989475266910231289785646932916359700562937694447451390557\ 6159823057127007441876982358715639497214383161380368570919187920934623983747000136913510855348\ 1641055104466457755443226906937683127886527795973019727924460989250526393884995755056493563934\ 1896005492005126440348149345443183480580254467236615285505210034213097090730535584306959354153\ 8542777383192680149142579507327280146179345193154471921343763690880500503256694830770487322751\ 1785025203612015515493113021033606828654705599041650061892583768832700483593973138811549499918\ 1817889443204712168884900376164067076315663843956615467311232831302392753794121119760418294231\ 3531979471763962498085625794997755347135563501059105826816783431253677183010786767652344212195\ 3666318052778450422208747272544063632741045106563443640533145382616142535202958254518758992952\ 8748069612325085761950124626504618879089231165496929393492652837996189442401644852835456061381\ 3153239336491944110738275520111202486764711912845858442035524850635517450446334863639053422927\ 9986623558283425544586733879183124349280047217119658768282795797552165147342794560124693986528\ 2063569778500284287616534195568660630862021958748619336631848179896346834367806213761935117090\ 3792225136857290245419430498628605412774109732670657305644628118956611451268502525833304474616\ 8552205407875327897797985764138678621089773100458457571067942719860551001790186988759306350277\ 0160290480308412429271655655061441675650809422440797289500087623576155611149808044919507342949\ 2391874607325560395984529198368172321271033991815637294168376929521688371354965867764839241298\ 6491062380622448703023503052744801826314163309379771827425209514011907155748293321159183496388\ 8936836577200419939380103096570322266956378446565969695858629142686556966925604904740404210146\ 2679023081963672026253343973839416052791229750026029893204688122959505564098769846789758547572\ 7038960313782122321562622331446510149565287162585943435415404235418449770023316095763875381777\ 0356666548690978862177653340364822882802577201192972476513756073579772144835489028494963181920\ 2686068327002244221002722925233118718370580862759326714043516574455657603570858402122157892679\ 3383797906963764187002082749929421684406545163495857214893695633396467910088845598331507781757\ 2498189561232470871036458928219097403815064851476666890434711750599038707183633471580997507396\ 6889209323439646449106059999206928406026801820023381048206317018082547288192797091460071113441\ 1815935812715661526420836682491730997285964203326580623251252546125052477934979341397610934776\ 0068007878998689318046254621044490723546456984819411344837688528485300222054832870202329628469\ 0267474685905568617307476113711744732293432391409485239052142776195614634782883019237260158062\ 6929912317547680055546624382271848321379598409026142246161345695504060144230022815749578460398\ 5628002894527102752392012626540387191730553238598207642404201109796625649034023677068145411145\ 7981561202610752996891907872026872365576904016936511419410476432471398696403963112832597847262\ 7453707219934572295196353126454786887481189138659536782446216196831466531366472651831015268999\ 6738081275606824831467250867117185652492291227805928034335376758435945336003934520205278288654\ 5632683888511104001385856771167865947405151278336904788843021760231164704867704109717040848569\ 3226532056121347989076985715753287063725472760225936445010788495745566593735948033262856783218\ 5344971123873464451448438142387633961145065553050775301648049169026163960977293843351698553254\ 9300968052339195884620784939074625364579229192862813153458479689200614755830770443819045585393\ 5019088087109184454501286761249965137132059108109729307197876950923225923844051363440285873122\ 9254723388322865997566009288608039432960011294355620807904641516247029880462839499710071308072\ 3058028975774373311864719039193939212527953360589502871494912515187577265202993478399838089842\ 5643902075213156095609436903681552441990185516100196651380028222837947735584473358262750939288\ 2383179172814463668508891056458621477756185894953740118960254188036502684399850446125867566857\ 8630170234014322915228640993659305794714371085866537146875565223884724476698099947929610002280\ 4908395479833164433116673979916275766586551744823803867640492388787123137355905961847136791881\ 0787495884653913394913877372650445021634330907371627510474854746819275672934689894258887287722\ 8468909698473205708482029933461512197869096983996475106124484189529738322580647917574988011584\ 9085426891242343023098042310665207392486336853963516179416478982018338737029738022148773873838\ 1358185748797500298163320300474647155638154654079992153311604860585122081730864559782365340839\ 5395767296956036070413297788226558555003314066733760481359896018182665563181037589086198407497\ 1551304004274426592136382312715553923287754802698920446808398033120721653420960654248238025835\ 5971571640002125734255251747333706219123282486901692071135196120874809422210964447871963221662\ 1875126237195647750730395903626608783786258148035134530845652925610796729086032956782258478126\ 6580950925453606148023309404487857189693919866336071825483531443685184203155463991364759691394\ 3939571056915632285538927535987322738839038237972679637438623717477034173835639407300322454248\ 1033547006641433586760004981184005389202644664531469787640757267176716364726239814248534746030\ 9116647444265683357962299097862470455484316323050468572088678529370327226524882261897365264869\ 9655196555881103046276395653516836122744290389542660919315488944728407438549730788014275930520\ 0777098776229621265673617474894445380329004240812794627235581103534460783653166535795759088377\ 9648878032905008659153576077369322593246933702654772463593127753485410973437983796166444460325\ 3003208906904976139845662791471774208237567210501070827521941486849330901170922289505307235201\ 2945289258039355610850403382103489609308862907584656822080994217633410804779207651012411534474\ 3355545995746669516637971604411389912850616964584095317900625109592219292178898631875426710263\ 7897035514335765561086133734488512975680208628529761606416675942687949169587316741214899666939\ 7314978469871561090188974188452145663879571183259482410428918534449423355991150143718532176278\ 2379076109609542464008095587573607500258440527353941296890091884716068097325878268616259216232\ 9076780296527309337781421066623060919906882397490984642933077896285664142696696446806757398938\ 7067568103542543169041762653591661148952586754201817730426869597179091241382434155289357952880\ 5700683584587674787561726432913059755297751671761324149686624500549798532663108469501682381751\ 2091814679199396385007216495859769573065315375906221263934451936788424259723246139977773537020\ 1944941275519328446311370621220386570223401476075129806408602391079961759008982960820290406471\ 6078632949522271614223290412327581285879459644725522550400958813718081065702161379945199738380\ 7558792286982111416585560642071466278709891464445243269773289971066308627151378151034489021722\ 5074056218790070207517083759818688957733394564646033962580147419526556043378130396692561618846\ 9098984250326906406640072405373671567826448171430488153693373747668449233077152506937972254031\ 2428314446244367591686731356437770125614535759071655558322465683574311588616815091722773014774\ 6535879997718904705863588638929528930778334765584747336879792741308835303322434029263804824253\ 9447886764258955034286261078603783862782288579047523300101714227269440057299559358586563255398\ 8604423929391162659243784652853184981404099587339150525692498089276724113522268934538641864126\ 5451893019297051367390610955810689383291387658129655030622902765170486332849850910527463325292\ 4666945719299908657817721086464399020569714016744938147708536785873895122588215676419495326969\ 8502166016433913159111272289266537644424758313984759239097550503869528667123865892283830231219\ 2166840498012270867802868463846653864689042707955845668539102995753747860042084254899709324678\ 4649070815985521760246005977914257518667539702570318378954469919429655480060817270868703080764\ 6684320762060623572460165016641571043632806951136965279909876325154952742379660673720950815335\ 4907667516933736303248713218218273893237484273437669227542023448058019268799735540153574001033\ 4631930814633024545510222157168573431209699018947007218090669675644036029007336310849227129961\ 2212308436611552766079523742070421326759430039769463422780140757703794416556371158046456431353\ 9530688505802429603953293442006650221330654218132052705144986927155948729091352952091112671544\ 2386600737410532150301235948673378078633862784199438459643963523792092246113396211222670344848\ 2209474319361067845222870633394428028080583279423382199203462863903063557920728318138091697763\ 0724009793721620559542628773238615787304696677346385288009634102503782788641718962899669578672\ 1784532080701625970307124213238222697716670384355592028261289609964103074110029278216934827288\ 2607397181672150101810801164904982702791944928044560554906374159240721324218317375813621911980\ 1441990643302670713541819334250161981088744583780651389951238431169555852198951905800323631199\ 3604629002209926350988532105314555985459825131639558419798271610442874582093325029113458396133\ 5324925474251710101453716737464426503457979328774914834198670628613364243211499537728423756591\ 0433182204969276084773634825105737187280914118739350644920023798012784868063905826502871733744\ 6227047810958737543680871919146958861934729590274744075363222622274503824684266242866053111445\ 7168780587078149646715196494365081824116580066801673828163022403201170688483855558757538124844\ 8189555839823582342289336670670579883537440712182184678288248854921303292490972849227327668066\ 0653114404812515851388919794015550379581092388571620362512319177676928829132858094898167291144\ 7342937528881518855249859176761864962008910065913807398053005002437218505088596766444463691957\ 7324885826657202253551592059086507587083279894911776308498973767216051222192643675014539392122\ 1447573260442201660377933034662081694668034869801816834425627376319870388268358989271641783167\ 7274308568989129704017900842472780855887551406245423096905920476374330107127765570460764842476\ 5771419777511075894292822826492173139823798670954430331066305824894141132809177940900632614165\ 1948796910238286856527431814679296142750558357137405078185166522115296697781391683705543872180\ 0411806279729193364975719120255023798822919531589334777025793224839121775393657544730618150009\ 0700797777935913513543656659634753753857388126243831470768599068819451568306585938478786113490\ 0762347703670778637362256436748198337759872610603921075031387270012465692625040181900002364127\ 2873421656036287939518851588711968092754845853427693614547598605978725822217597710609073249370\ 4257450113837125144941052141921967842400210407079813633566243758370571352508192142162597892795\ 8677095052475962992312860005799411528609407520189353465623876835081139546030849726853602611263\ 4713947263184515815423498338050709463110638621516529770799009544603800681013954217593528379197\ 3037447945916227645891945499104909989949054540895100263737449246119308872292978595228844052494\ 1281945770203803106887802150140961875405907542844635847607144418826858995018892261829120993407\ 8944135040734076280337875242012905874000458176528867072176093125433474433907902739702848044907\ 3262137944219644388227736270272825284098564021107515512382850308231250290278436357579357088044\ 0298738527869730173801007953851640555510877255528382017821585953749709610281179111619549474507\ 3111044783832582938616459811965608656203802667106136248541098946070890542719879928226247478733\ 3240917568746340593475691798775110932481165147782874079614941607599423197298453259920354562218\ 5249072179046289218448562005719587733998568054554161192119724961816391985640268319443879873757\ 6228471382162008555426367535819410190200844362997574733313213702511106209318311204690231628441\ 2855639015965127749285613895886746068952560760404853150593383590329869057386082877522255854673\ 5453420153529655368613984624515373893724599105290614419323932317689426485309670653415460396718\ 3730371294509703143053686373534142175411984486361390689049024655079258637854444737009166851383\ 2538638266896396765686680317594438099269175464029784794310127199945510286408167958283014040993\ 3809451513271455721309217374628927780695432465210717154476006406449251842872180550973960765859\ 9690912126269156161253469372669348430175682881993458052661655188830436423821628770644495095329\ 0473415666105106077384647844351437264733296644856325621859082119459950338538747518052896412103\ 9019563754398651964635328005733118902904788835674626168185096228036564981371719092710555194152\ 1036074399444458403222300318251094087498931784688573566353598723082643821201717665013987996037\ 7331488415302623221726225404925057831273017050945698193003563737797406312515111477633937977966\ 2833221789528353301188622812868917513013731735978511154929570100727996099585736283564506842770\ 9780051256654851861838654930673209088713677576738327796368371318225082695135982668220669680718\ 9144976855722505403423767972857026773858183077642906551365622955713458999105609252401050777462\ 8925459172826756312576531679008496120915135092290104317808918532904087228009608312189940066064\ 5883384353250748054995681474337769628205165458427772283580971815104347842060613830957733507716\ 6131657102397435433867977303486881032927805099000158827792849866748750531098509437848043823587\ 0438661158001197975590579363123804715094882300352045114302922215835179147009151549782685265262\ 3377142906676809456230607102438687620054946368753114535772498925216034544232798124039221120801\ 0045749925500284045502269346326039470578068373368675631655877543880967755147651958158815549085\ 751310679807449114647947395283799401"; big_test(Natural::from_str(xss).unwrap()); // - toff >= z.len() in MPNFromFFTs::apply let xss = "37203238424405906847053379867752061720711530955358099105284136369489423915257643535\ 8667028900090955247690408231783917472205457731684674614821792100051297717492262897016144066614\ 2316521983310453940252945813268753080048213512651939423446860709132230486708866556667837115383\ 4364543302221868450447290203008631880746283617117084943195737048507480709082795310820160750644\ 3003301090425598131876007971392197934781674815514017972891069262666664904180319224046949742123\ 1918893404254121247440235214250228914875289471085124872316249045915738874001699918594103173240\ 3833100327450277855643324999258530248245112562193979789466571431705105382102169953766413057439\ 2593975271361451878133338945129817421034466834090415636069432322426778863652428458683089007272\ 8362423881881860523230567841038715135958689095189098953498187463919415407325958907739864837076\ 9508302583680320566631875001991056596451085195433369468680424304984937334105088464020020704492\ 9573092451311023349678583190056714744742968361971061990672391016449767465466836538435973183349\ 3419437483003721865487011523508867277818518027674573771806998361686075647188945775575058865761\ 0177952605545244948199849382225695220159081138830892454343229997854526905354426585869527015100\ 9760157565370181401581416137581506921087104785378947349767905176575033840782328925248100351310\ 1117433817691395944735566088404111421813888485456172535235702938304911003162402279018654882056\ 7792369814672402415595664952735693733545056500880403234218907924637224764577390468608395948983\ 6984710393618793260054349265328551276808512432125804121716556007817767521504215815027833042208\ 7496887364929954405645363283138955686967594264647396626025062717473500870392284408181545337222\ 0175983354169294693297894776530587381290436644581052815012177466237526000005061836550817389225\ 0535420547874483662355425165181494089192155166451805887303498674978371900436575145284884252705\ 5067018780630906741022756945563927101651173643971446552886390434534654109903661556564951480048\ 0160905959641864549070388052886674778230024934450558531497792802352653311501485392860935285756\ 2101221807950329391710548406043604236576563875056446601858766975127597919823422004252447863396\ 0334042172793946593084864839007568297879587644909088346461488211292773631390716809042553523055\ 8432966603364828146859026256848087528018954622436651613142072119577416762581459569514205922458\ 1854724286122754624557630965126453391104338282170216851769775839855799186554457339183046727228\ 6986444937394119292508232629211464780348789838915391958443316150109170332887061554719600413831\ 0051376619616307464865374876807884568320425661563703097111858313359720139061744733623704532285\ 1978880435215840467968956183038466247252733360463436684272497063979612316551040672017937100021\ 8302012112595319294698557555108585412711894744807146822467817872851140377988646497627133880016\ 6899720485572181928539773946436714652442931110431907091919166496318215219591289028515084638553\ 9033584084770500172314717918099069313270247794255084102100344443060007483330321612615341954618\ 7858197401755348744140826129621711117594470331219560100838621344962142355667718550779614905356\ 0123811406508451922988861242753944523381906269795202349663207043705925644318342281211962122874\ 2140330780505247700909924187256029344918505465481231094755105128313677229196438862110523258764\ 5777422123454120722578374784092641173225483875994293087626613554030329066687900319112521812279\ 6879397487613866519389017915663897239601094283836425589289065503809559419659143889474783891388\ 0384684600289270388283072087335990978589458533265727263736957390582014876537739215884269250468\ 2473693040749706714900985130293419289037070420256898521218545940773915792215746311610857982024\ 0274938111444211225745610173029978297425651146954685970700096164729915729053002096604867974034\ 5818050565777584768280807885356813602173054195575503058304774943128667570762933019056652440199\ 3296573275038569834775756745231971926539420303622777956474824503999568109709080379226370735330\ 8730772300204467190962349461788579975878230736074593283530212041976617454693114228511631334286\ 7596731107073069764514479353520381542579916795828763868204996960491185998871627013453500958656\ 8811878188008823091226664199807193215795904899635185253461979990270762889999994567563192600610\ 5604240384486374490821148093827956753827949970329714567935664022303204761121098550974778229464\ 9285534281073537170108922960868657941496709346495979125302815700939639893528550375898231625458\ 5767402205932021740136996171594844453967614392625684259077819218643880044843258204194297334424\ 2543117010945604332483766689730044641397221352229067188598433977650032613093688375532475190723\ 4533877534267921321025547040593336635792859339527913170082440171651156949551829593098112063520\ 8648547418752442754668349915365331371380355543883550084262242917874626324954358089136366369215\ 3557031395898258243132463040889508558112318165873219588782952176926422035910697728759306496164\ 5509181537241625353940750239354014935629646411903842289184638759338283512112652141541280528888\ 1815261057211460948204189999990613533658523369347118562662630188704311612461534616620995792907\ 1900509467835999607368000607269991818133609680907744023325766501793224359214277141816600126308\ 2745078664018422648890958982881318749680939295960634792397077329983317460920306249126761937985\ 0113243220623718758450538148704705687170004896120507477584503663633483736043700313445791784462\ 8972280802766563061876286526198326652327887060275450048673251385891967726248306924324388297004\ 1678070732856044120867081363097909716728332352472479236695468434573199449989767892391636207993\ 4239372405779221340674884621861646157544087188181914662792972546629619257720028750168692639786\ 1199009152839830487761181180821101349093547617708735247055094286031085381817283053714408128541\ 4696451953109627543033903509616730076789241952341754460655198045218234159506742255486270434365\ 1552065824710538244284963364664231744921724024583395567816470070341175361692265671307097750109\ 7815481928534250097442335175711125070283960938843909148870853583037385988884029095361294526209\ 7812090300824433403841120058234784140088899079532919482928905591758143439916791418952390169703\ 5645636380663461143687141206135468246400452197652884720117822929699319021023841076580864060715\ 3860683095669678775292027362251296657497013094387154258988011931416753420136374026537241874846\ 1871419464457723123062948953117330961657025805183277964710395265108730423097099862255719979050\ 3269482865317067196747451377954265433043976460858360012430491237957483155869687882973013923646\ 4646112708810786631185429968227344123415114724697904772306639410464852484253638936341959825322\ 3520860343186611713177259414518338814079619062510267387768242374164792721015284986087596099089\ 5906561387626107505568857044765674983582659462393315452602118312161699933408453266216765892770\ 4526065749494506508986993323184565394844653646052571152406596789246703498482904688277741065950\ 0904453696196705282351152972368169083939859978848613940533995375730859454334863610205925925262\ 7399643168351971299087782313256793248122164519475158708544248792177001313264894750944632930013\ 6670727426003657683252560397176532578304163947235497799188522686440109123303723251016849958391\ 6794876428975072881024635442291321214703206479712535413142189896271774655977120079611494824550\ 9305864150015722366890182177664337435710120646522002422023212157846019035388668028830635125331\ 3134272496138384036485281895811244407425434355634541878264555134410907356960605690853311474930\ 7223361741758033834004177777350452008682311420983394538243163634902732930635794607871585795838\ 3324623982342751854894166871102922202451147002130334106940543122153410920044082167474159863236\ 0016147642701494175723160121112734931917618555611005253034348170597802545360604756085766365859\ 9711013629930906411578373956105703485397753251085537332106442377647178678492724787704741594344\ 9856889070080951885047440819258382931978519232997560416814610022124285235554036009944514029602\ 6938156269935538474006651645211996020491681865940688423271819363046158308042793765698924401379\ 2050532559166305049967257028332589594723990843038891999479734455915328251046028832835237359298\ 5972388041564953971031118072053360647955069432082278864128702826828745529157951314636686828004\ 5939020855102724160171803242598104905839179824561833824829582452309953252830822681991457759116\ 3036706466848280856167736167888190259027705756802846089303539930783529454400890829155952754039\ 0199338704565336653048240132303477634392020576059860943972805737202235551797936866862671110658\ 3760149455492109309273408208654531269450553454808593897043397192472645032350332546038297205981\ 5843732300465282221179854903164343984404355643424031020175845243058901570376794732650559346596\ 9872951655337965300520962999246402474406969951821462337299483216866889348463228368029181283353\ 6899538143147619119916093908251200846359074521153884703445460035267062662754844498634515310378\ 3539680408818384249680403004513253682907686085578317829022065187175392188792941359920727830326\ 7366260783779906911098791115082381330289426333709955634937388860204047047836085673365888720780\ 3243150214408035769874054435727164406280583273703036575741753004124112631667762140017908181421\ 5436445247200046354246509522140136573320542988245295746277524529586532330286750225810521002714\ 3322046047515956038130102299077751285121016101084041531165625137303507766558487734457791578780\ 8729452062299804540817451944345922463143003803830702341826335220591878267265069098704460747918\ 5194950672718663936311062832431228245252729700993893958406730273252272899559423226683554536687\ 7224049109070752148686862858824836965496056776127739924156244468247899703253014234227922933739\ 7880126921007176509980037402091088195999455564460720065628582736032961716441278034590606676122\ 8454872353400000716750508043191474409711863248334138082903493851829671467411069452689659740457\ 8959351920442974518256668132108852639006008011257233985156391619649842610805070932708208390598\ 7371391954503778749424175443087099505465199304948827220263626555091483857495760215140717987927\ 7805863738144504307830552438315409140389370809080959882227796073876049563192315754566537822893\ 8823272020418182107860868231454413472318840112458904638171543103156520057031470817278329113117\ 3206678915712410768536490832712002243694895028669645607925656820033482337287512189720375660150\ 2750049683011800914856339888557412447316677933906739189714301141661059190805578414599036868777\ 9444539510680450661135183378122496607170143726804571599339764858532104126907665918896873415616\ 2817202225764475630022904826673169837237411600712790559696039472736594752413268661817959730627\ 4515227728680215145621995763048747729566458146021097367314226372753551469651764431889140671810\ 7940289278725659058498055862781689782487250668685254190564734105029854475979902010273741242155\ 7029648749747048537270299149580067981752759886909006423694210139392209303631437551938227392738\ 5768391332873561136982602394598690893823274944974487733468570936226554700953597956024580420056\ 5133300127714338371871946054703369521654236812907003039706376710588578775362788234983645225350\ 3237222837277278690349822920366237173695150037594562033472948702912788592169560018024876402701\ 5569673633866434896416375183634096275256415828765326582646021664950807646974856545575319687191\ 4703419399612567776150602619090066636659518530900878547219309674742837337982911069892721943493\ 0855755897616057211059348926112704207005679564050245013636048559721937817369881319326255512675\ 4782870828320913383670435109336902336298399487043229666353629194362235977051304560955280015917\ 4550098984710012319799729737232599314225262537138171454650930483517247238525685295717429110201\ 3875035530693028902474184113324345280339088075934304784851304002378309503463471328118631295074\ 0779768407714925343744739081898266430456585607261049590055505139720349444997189236081713547804\ 9681469386059649716300110741778762856206442476689741872706750585504986395230243510942118569440\ 3722481208895073568871345684923580370679192189367066868092180510742832843222345684396996851809\ 9587782661694942537881183443358812575776817952188202910924346330256726297164920177303395811046\ 1643071243535067918862356375922179381367780418954651299776627784747655659033982583340148305206\ 9627759176167774068937993859908282731339849901392328688456434724737743079343728966739226865566\ 4557684105752736501274196151590642167146080200535688344452175649168437873604085603907686909602\ 7926156790138674768462779826655235376057249029788746250433242833040739552691122169102631897927\ 4496233388395127423842726404835471977880476077060923388748355855039236494439827768749850312847\ 4710813640723743204261003210393301560275664019475536513062403886116223588140707183278633954521\ 4544521011543847989305104830495970180462342393183664187491835518561407059060233323494823644483\ 6453804727849442681840553513006662371686243220405318160792952673067418130189292748279012824650\ 2094792001284587472315075808547404188049533880992289212444191530839499178561708531932814581820\ 4512317141019593941176821506392403805645018019765104337519934636271825246155013199802090028133\ 6883157013340441536195340227219970783006893893259656828540201226226389622379323562237646704269\ 5927849286055216711655517887982612785485331610164298070715743991096796415847484491094541381540\ 1601756024977210494535136927560688306275596865122102916805205322052132793411218260805566881071\ 1685417585409983941797756890094759885141446634426070743915328173066794319613234057182242107342\ 5126627659966906017788187689026753451468573465950170364840432442909518204011681990255530111318\ 3881274056766226652543582407255857420119094234809803438188222523335301083158631965423197439855\ 2781500528637386442305990783704242819988710703562677393120178000015365788295413819956747535089\ 5003550363000967136769453228493005455569574524186418006221011197248590161073521044074492501032\ 3474663958168160772402596046031155747436538933060502147792379648709358454295271838128813173827\ 0778442797840445939257942437493668322218610145600220087886122070928632885492695977122311938852\ 9255032542592200804476303236020040344037587811301543645455080431160454541177136615442403238259\ 9437938612184439476626096477677266145648632249174904462700198850694837777852451575509510260307\ 6169380973394795071085926580452753711249735149335875160416624592789374829619072589057880015363\ 7918758078096726790169586012360996999506701279423370759161284056444150665384911906524597777864\ 0670057195856331264827382550945460092122241409404736472994333147140596007596357572864771151812\ 9720243216758390472851107321745257436244465492224990937558569760294962036540635430260389758708\ 3024934918496488250944672844278188609886773590741698429276982098078165480374611093021516853423\ 4999642228720954837074951394459724906390823914806550419860295387784841046096581763879865740953\ 3936150147983412549674216273929839010848925422949598282800475974193850736352524895963062011069\ 1114571713399158122547252875115074210051104095517445044455310666247016371811987199978427563646\ 7460734277233921653474933982625962578447205067015415571432273575319686510449289360719283953456\ 3622084810506660716149231704874736921773155035081666698835143342695818880351448757612959270716\ 9739273652966253261962998341894240950912321182706341152069903190973799834322873220446790778232\ 3550069263660913999408886327822969976187118721245561672863598990790716574316626318469346419708\ 3118066488575806174974019230116797640579162539786455511621555142889868358322597407575740968154\ 1020251656192819543084980893458146934502093565392968961633084430408524568187740761835333934605\ 7299903084103503880627460228477437725598097193469122195491942201978839225721819674128053625372\ 1900372005658272156084784855981685119449899009284829431511767695410683401005314710898686341711\ 0338598689207685560055327280725086732201380418080040825609614913625865693808617035277327577236\ 2869617558000553194791128258818387691054729135936099382866628299670546534144697612506577723700\ 2706843952202551467657689782986809823774915702842771122782966843422840206269430362719984640080\ 9881978916447729449011655315529144764723188991564995379368939850604442692051809889207808698234\ 7764628056681096547564849640584360362168974964002443269148112060319325281609130104372854716087\ 9756178907348581812608245660284068763529869256335062054639411672643840162843674649238014815318\ 3896331848978254070248114275651948649306299541996181439515808774314979881370011974313452025036\ 8544653327242707112047356710224182585089343019257273007922991765938282517460994012007031367820\ 8966693895090759645297837201447763913216139584343382434111563432183343435369089838153703238580\ 9497419395913385289124620430934748596492643272343646445941680423689470539838055071664662484865\ 7984989776513211711201229817350678348983971967214902766088263869016076706386814794646769462424\ 8277713107907720526194121142400684516876501024885778744889654588192839934239594220264939723426\ 2556635204320751462555768438369836831732232713354197052241936824411599275347427028035956890667\ 6103166769550361151847548100372670278284913230520155572039306018619944556386756467724047697347\ 9627992574683492731273430039845028912557570869015707091278698919154429010198940033197395146568\ 6275923133320751237253592443819500692073817355714514233269494488761906558613869761621613392427\ 3801739133524747805190694905791920909018898060438363842360454170639811212845969788663327448173\ 5090812872447443915606142717426506209271745835156335645623850366603142711983250426539402649022\ 8753004528767305354986188356047033626472047558106953920923120862056667848763419407781926539912\ 5554585622266736794562235032608327698612838044178614007369539830616204154648938358721982920298\ 3819275981817075984703956838723780115479349364986873234043672224550490287528575370468776912823\ 9051442637528958711242522063872742196032438462069511606817203269386550251662491709848806114345\ 5525464278540814983368045545703623266146931155732182545467769649726757444823464612795415291097\ 8596232532192874953222503591083709354353849980070655766567370638977836309499422957642676496770\ 2689778468979363362841924629280267571024058381489902331988878110839403957824318297221722125854\ 5774538096694885242367067257875297943871986980852174633756988797404406437826309032813345555975\ 5899811235648115017010590837510819718318698292291700933401381833907570293194551049079219983292\ 5839595315972731879778153486683922468253030498472469677537055089308881781896574912836118567440\ 6151354569626897705187198584517601924318372874902460260078483744572477958933772706928237740836\ 5938732013306796912930965990912244077498945826090859377707313347244005676205852272278540298870\ 5198122283788831668659949863155960510501271709951540498809087938460345317024417205036831663758\ 7397919094072189749816650071378862274308038733086134042094068097645081246795127438014351917701\ 9056269775717569485656157769615805305986002120669351204017691957650572696636646738397302252235\ 4446976536327279426666325453207257310476057809269202065022050569257800721459431783012633248972\ 3218674363849078032035066152261901756778088144513414452092721231195795691469799575779509903737\ 0178721782147044286758927874533329868903871746768172166310014386425532699397276671073364773678\ 5682673581913771236949258220177354425310319073529392172568850845616936192234993501750385883549\ 9747518340967854066275493079838763685798325339420926406314778506483188874729339262983018975258\ 3190893337710530122524087401572510138434418255226123829377677336257125874463779395796847897227\ 2457763118157896916138829257579059568359117640192520620848947752674737978306617080842314954655\ 1034027525693530331026261569230653107277980335690329438936581392001221266423840095922361733798\ 2472391980276262468489702147490382270657881259679445378067524219930346292367658144325079791254\ 5669821770082789421330876109345807345302101436958083030589440813411629586663089043296019303704\ 8986937867610792598427549822080017423296791322333899126996365550999397153245056448194270157024\ 1426133055538315069317452467454916712691385671034838874909453186212831476123643094218177466517\ 0339556887778856551687265004832379475407779076928430628301565450114442676642122255543916325893\ 1421444478830514190697186165554195580579394888757534559283867633815230897083606891283833680953\ 2907868846837539708618612840954325614366804105178659355145424075407775224769204552834008256659\ 2812787914171655238602578441672382242187752416615954178768330384955605803081588393858672613807\ 4471240261386943556116285100220364253530429743661702419175928078987834641353006472838329106569\ 4708953098842263988698459043504520626724765799801340087024962825873679324277739397178742289292\ 7297531243558872985129380683174918549294202284949554055380881047386078741250671617601118312441\ 8312575099326335787424438447303638081541406815643626981794889409937814582821916039735183440729\ 3723854851571606196114514439550631993564352240133153927358062650453810126844887639988288769282\ 7718794891004029856581641605219708442398890748392727493894849886682648524570717684549994111526\ 8503733711099144029343347576934360533398379210349348651760908097639833881409135430250221153305\ 4444025133832439061066544279393356933990792248621672200256101471496110027600198546545424762519\ 1039454039750697429589305236549940362535220527969708895989521648740722046083638272687210176635\ 2161993474025312189657084764212834692904000001914235294581922067812878818129832802414492555867\ 9317060686416366340259804779611363003745395892510802510307083626893514722227515732041625003770\ 2954558070385549072942179139476069837716615598734207577085850006643967856045783857506542135803\ 7980871890063668116009783380918088221172282517296721365397487046082196464297429261995957767282\ 1025396630279934630358425462719141582496797575333312994486678874809067968440230324890647294201\ 5475804027406981828223098847035903853282957890823833927984863529802301575336729444425350973687\ 0252839489973324040954335756550263387941661372462142556221945251240098000088848899650943974696\ 9561208531785468869927696458840340944389048409919204002219674482865986243296479321561576007609\ 3209638463156741858585795306132742804261245219668133008719574403805587361341842862518550444130\ 5857819308264988857346249052405883202488775750814120001364816978106970020263262566459194326803\ 9768212150610334089454048322716416969618571525342262435058185428362705265240339480238486102805\ 9669767719899390328245757249184471182951399005878939523684499017284833308132142188335775348007\ 0458744967811431754910400485248745246982127763255116632761936157700628276896159866327966059470\ 1027295667831083476438834402089699437097154882535246221214810304141316594308764233242496106176\ 4728275109123270372948782725472161560199812682534921712479525692608279650508095860599999848762\ 9589596733504363204398386979230877341259198394067130311322050708636222115636806783304127072850\ 8650294298040286434369199681972990087645079100625269625312637185473521076129954600671243840576\ 1635281668149787882692379505639208256312212216854252738833428449082677486415211448706832110018\ 2205938819392196361618739130106260354384901221025671972595763845746700121500651331529356641761\ 4991375827023155402670204148482799435092521827247442321814308611257654199306098923886769747578\ 9494992677843243893100391689740708049463107732899563828684597168505492419288510202161571972129\ 3872182571984977152265929270664349629828077572199127123236279265918438306285593961283742324384\ 7080490387406457723928518125593366931004163068941406113236414082367657104455645319869793505111\ 4067919032306112499802795180597644289141599493849035950534428810416537800005328922155494736683\ 1017981110965663299681339955613660644330168918682810348195331279991627494169740883125072356835\ 6699082142592353733794397576891018034446143767654482175820886986990806155009954609578763010248\ 6035275546615398205076372837844788044745390363373838906921858075148221937942494993018899042169\ 8441404487548765836424510545143996195309994190274540397977393758987627210617260424689406302226\ 9623188163951526830597786811749350886909246569931891521299930514402417924085133495386809044552\ 4304153957863868048941317586656323234965734067957881769730529050960200161609874396502142499504\ 9231970256645688894194010081978318972372117839815781611824630435192446334416078555924647477890\ 9407048861957876246790722012747727206648233530508541363792577874873360535339579150808308969778\ 3559709724585996467410168481305149830647380444131464492708882033344388129792395898371998899796\ 9754428098727029441000633757244104582542593753388525380333823036818950911264053488490452576126\ 5480359167927742840559208941244597292258252456803046377402420509113099582452412520403431617746\ 5170034974889639151393896073056996885305518199762437584006966651618446790952688194178142308585\ 6620769309831641154243432778895604135555795337125383664136452011821274244941049479223091995828\ 1305295946334347400817506259226830756424139236463740644243700035337929472528362870356145449264\ 6907265118094489422374547998750915843184277475067556019018926424519646884907894037401336636382\ 7819170575866150944472124193825792826600677224784039172428445050691556440142396456094594345407\ 9109392671380127158695094703855123249223911991437815042081638722965211785126594130903924285245\ 5412976894825479307632802891888962106921683714634015041289336316115452835374309024103013514289\ 2155211895325381973637145421297498065481720533152234648570074637479014533648065395809777189304\ 4137287975198664339577722343316563034290532135698674583158552842907615053148615181728050231687\ 0972335877322591158315899125761647575551677529379957949552608628571029358597609353436158461949\ 9404401162477741903671127609705823974989169661458510145677680874375523240585628124197892110930\ 2788780744075540727128807045224725709505926518134227891610648591507068281274403450781796158672\ 3808360794542619260878420207733590974298489971469216118783452495659748573959689158893659436640\ 6450260066158092646582790682129818861149776946547681677848377653003084987583351739245698882357\ 9884320079127305837556344614451984689717810225793008015089315028787590035458174604142849050839\ 8603510456708724253087781252777907576074744018373765996216091654647432714022787746172989097774\ 9094814678397304900697213889177328609578751096338035671414916279191485122477496563748829969292\ 3147659821590917266317589863391036813045533522662899215083154005161102308235401238719451511129\ 3366884784737973023290685205604521308622999332891468039975910537906997133891701919948453055470\ 8667844255592377432526364917078348362578662204674003896713997220044127189405781662639368143426\ 7043775060200910658086674152060670188239559584864527581837409162289174146641157486319283056310\ 6999135606809689314451555221905441876980691713505154411847809191493461533915750464721456306559\ 4320155329896746403371770753913096957825185075854226245945316369006785696398595489463288426041\ 5408450866956954364969474230356272741061278994824200937638145645057446912994098928325707716436\ 5522151938903448758411767566540370327729272963969825182692465447216194128436897722007703924073\ 2882997897438342809309284890190146020692761740484000605041219233813822958812770156577632402633\ 9023886720689147741712384847027670865155158342269180091962020943243707562175397530564973902857\ 3569404961380437096653065318033439553321143150986568676984939225050686244778403993911878594780\ 7315900592116143315986695456459569142287781383629989146858685118579095823494871335610640989196\ 4087950117318705660168768417956645608660379973273413553096548573007001729654716730914027940514\ 9516038546916551058607708019186099021027431225482385633097235147484733247433172616605201067856\ 3376395591094575326444412250095374249358736097755807026595530010636261204299828790396368175829\ 7062661025402424683595838213086957806160964518940157231053193568903474771817471119948178481719\ 2654890998278138934094095225605840384188868090009743555376827191116907746047326497728570489981\ 4313342935518059368715086469581214329283140780595442672967183642894679457187267912483200484023\ 0348379928081800911420675117990360343995776135825241025884453544544345725726017553629002075967\ 1969302651111102698839124618389882201351333539025151161637784413389877337062155467594116447962\ 0938467114458810740905721238664171350738323038614913904410627140268385167665281275974158067967\ 8725595044293868281728221625089744635901364119696191799468910061915465373709197574881610206445\ 8362061156534952966294006334799826885220576995520488298825717060164448822406587873884801277936\ 8256421090568543306635861635874031789472367988855610876895817581057376998560732784348964621153\ 0222591862754173052500430183138692511625436370247456567817368972860610966201105749698685084629\ 9958788510294476794914129492368232585540940303432251191368246688565967359370348823540366166226\ 0101975451049329419715328871731339340711120770183976099378103643618068265107437817724924927165\ 5860169426282997348026245825705197108404618599986119973922822771584761582023092161604829889599\ 4236001969903257127319017868376884489656151037566906129224118478304384374484577628364745535050\ 2922893523583704866615163777955065867351633907465919140777209921484715773674753443531595441250\ 0811269335233901505007497453203198599680241265936052058525712932871744550526345437154160415836\ 8068993261025502435470591455648970069379252352307614248814254098797165806814561191541205595751\ 6405964253716472241523188074234858092154718410322095863707365703923987458456988837213360736515\ 5256424966822898612646356874028940752875163098187046601515895338050957492182917082811274913176\ 3116194693361687979206886440971403671521734630604982364546257070741608514216211576722069955231\ 5308793181632642462194360317011050005878478750715896127919786070803132333328975252227656143885\ 6714507925765794231998655736114081434592625232016784647740011219658273626804162350912998195925\ 0764344942055513273487067137095763584885000728367385596531207877409006420372928586042961087181\ 9031751592180531570625222282453914785850824422044582153599757939220761466248806769937977454653\ 1567036555863027217981754010552455192751082618108443219517422696953527187402960840020202551449\ 4511541484531742411748814066922141398742240107833946599778353151626573619596902207021632282876\ 8316769510256358982741469600257370625741443445183674144618966235710017067051591244161266260198\ 3511561229818727560308462581450161047045066400855563602130019170628068021016762337312108900155\ 3865206739376173775942918673107982049837587541779233024823243607656379276243066235330556374252\ 0377262754356920726562390790861831381813796105919577481952826879432742478649095447714888216201\ 0452939130654767159229827000875411700393290185185599380566407061745642812595571633690854445298\ 4234036444328296841000852286375083873327899781680182032900288925899244553915160764223983542050\ 0551238707480159051057280301164132561461609934987734767206856460012682349851093785142186666012\ 1926483571858093141409629092419415333964011947747122234188224362112100461467180762579837882951\ 3229040862417895097312572767594606528842672071826067601652704824499388350630368792540996326718\ 8130045211298300600712984671926969497298130834453173354289171213250109278940768897482479384404\ 4752944362188033258851639254893735109360381359175732828109138092708407379627295308883358454951\ 2383099076030561176635493645870577321275489250850714395303509000221105318784151147853944646941\ 7083175636404163419128263847701336403584783583671826802485879747826044131742093987219098042486\ 1986231062852277946569765174563950839135439770235781038052855764869708642576873357979771327064\ 1784816328793134969226582980290191235078612978224887623812772310550378298365490971713904697545\ 9006459540571267542376738156586724152947946328086338358056383782443955507295544847224048963221\ 8682763652488152405945072529988753429641152616067164621429343475348736270664299146376803204981\ 3030197658198881597959236664109111986695320326705160718913146042376804187542523029866615905622\ 2258217481287463927327080501106124700005439547620032297149905094584503967480541179135933891089\ 6318453585109923515296534352365098419366604245366914498932475518566847630764561455695567942945\ 8827443509846623704595350470254076808558138920375734720961745949742830738987186912964689664457\ 5633488712369687357153705403300242986259976286164061247403762798746880810250636545710051688121\ 8702958841514905347335706797753885537906835431050114635739743933895696640194518174978106101594\ 7498271912107339662734280623268746520969714345433991896276431789002517910013893637393217329662\ 9789262263247540121868166436996073890079538878462549209747211475823230404538059083000373747535\ 5676942803653317334344160604458312253158926599133723983938251219874298475740348734276072809892\ 1626848894186788776460905762641021187051986426931249271794515709339154968633694259273769591346\ 4802934745772815833016389493333282793481861605692977020936945975177962800571386641457689792671\ 6436401155406553663328354309396396594710185795330816784111542977907452088862926987240063400592\ 3695441084516070947117477973251653378000962715067620733972436884312864292078235918366442201829\ 3712109475809681452875807884956536590968057469954409414360918868242885334650508057986619635252\ 8402964309640750455043724175587536897738898260091080260465388956918187558327814373511559652282\ 6545627353652660970901610474284082036116001257006407739686880855053374996327971673386219126712\ 4093737634901705349838028331937870930469922954803268594578537082084444143643981202462835025791\ 4801966450869428841128026790540900512167202578655522981808113004086231732638461989256467067519\ 1197556642812651623057856293981905974892044815927884247546582350655375915601883965541304985429\ 2947613749157929940642010727148147685365793026910859922674706950980832556356394318347198835986\ 2546979028671261517041763828396214153177455518285662057010428139624894542913681999411631454082\ 7267759020900629363437606198361196560376657413429542763973773159795461771876352993273287459648\ 5848853197228754706611495304920213605829525072926136533962713550028240211500277803191315152114\ 2217010005445253378660100375044933103643867412627511102770080376901851140288040803719976871920\ 8164844229335950175150630077511470750281513600624232843947687293428207456827671631824859201767\ 6723957769234755705411985969329846767095746673627877805693841299198320914926467370224371940418\ 1608578919372034873713968007318910383551989477033112582167976378433655946987719751049533604096\ 5179925033405654159801126502112850507181737922206802782953278534009089385437101281218169988735\ 3126051660889602172305874567249360221531292112351653250080314029962345249658933843066539317549\ 9892277476512094538510663251060804907462245036358819780685197374301017994868093847107219517697\ 7299887693075675455008331497824682219456913633024766056117580696374883456161787314532210342357\ 4302340731284645387944917673767582583950631845290811861241783897025228580102227914460987899079\ 3524276161911528379405068263615207613056042612112612107158520332320727892793790186407945144046\ 0011905623846496619497243670414303470021771731716728907741812141903787421535218283034070676340\ 7345583432284233989665427254774554361320426360515993435493153046267674752086624159831049903048\ 4951944337027884040540743893429596246939035744003469805532050876900685291599932189040960698250\ 3648639949349730411122736065903476063078053632602793907462544308066066822840928822937260411867\ 8061624043149235765069455555045906800147765760082877111866927711494416336877930018694637159075\ 2276171602520870299259341290235306346264005306248873528982587440859879753326863968683671649091\ 4596069831640912777713330232839372258640963703077942793013805047907034185421574412773145532318\ 3406373365583053857877733971933798082464226438140022393417565411126881972554391989071682275132\ 5663966358023492977427986728239826558208451835834914839908411256839099045698603622372259637827\ 0606058511195239224507705209787728928883991791327520824635963712831131357132237280761316620077\ 4150941923343581297382886745272795114816806287483971004413596594508103658500498843245297405771\ 5171681846908036937392808706641010590833735488893875543765742379840242898678772756699155931257\ 2526032145246600466838960123355531422425851930830261164991686461059499873546143306433755282537\ 3981670391835778541558322740563277021302751615487534802459200253460799975263993560662526345924\ 7213843393419035499113215809909587227536860810132610536538102109870343227801437961188437679332\ 5947348139304540731765524877935686738674550491136147013214652105589889271078568223226644814196\ 8889294770323276708089627965812742187959458233034574876671498910314691383148168412403087316347\ 5808044682964992337204633465149235024941060139247471310656171481655595873294391140458777392107\ 9431701581239150627511785646745681605313812023670642060454485391347452018765160898860936542161\ 1704157600647321768912056099657839695030905035071924176526423720553380116398336623660911323212\ 5193110922752675114375878966852778074512064441600010615107992462877327624086709574975208076708\ 0365261750688898641035305193318018541459739656826931425260833623281608455269026732209015681597\ 5338902139160029347603856852006267797936314477535790643700476589040979799590565856492174078223\ 3888303884996313429224845152097288939357677989146234617304265705428180779711738475477759032545\ 1922479497079711895145910872714858837415389988331504387750730857974522352714704364252164458223\ 0883779180504784419543297917847811460766962947574894759591364921548751846012094172570166321774\ 4407959979414876487518941784820052713566791847476196369973885189168073080271206767552421196789\ 1567043479046844367771462316633337981174537385811527024837887692632748187372421481725742961230\ 5266508390652331185733796984157067922567976203070835498673405713784225354750547929775171163662\ 5739905581504263231993993172464477534340275169447132101227627431257464861334934616467352057170\ 6703018442965737991014439623883362364833217790283273066690442648090840261076042635242269503272\ 3152634117661428141666872085590910920951968492793523529080057823508832573283299229424154520744\ 1939630313344057840335026971066621499310049356448775395559339991206396619870429859600080930863\ 8971059730438228899803469147782685541381446203855457327692317648370088295989949123791935153566\ 0595489681686434738582121511203959550930281339652420533651853356152444883081855207131680626247\ 9628041609101961091677935433659725260638616337494148576474414963616586633619977543453951961824\ 4775676554522945527653106654375528980740959636737215537015666626585535746179767602499673083814\ 8591955966793632779064247513473870829616549871833682046111373566460383725496389083986994703729\ 2956091256195864391524860022289893632525088929249273836898974882135440418846592399064754915956\ 3877567283362236162495174839183340209955363817630100725285079558352321085963137728925042417989\ 2479063972305149281238149255215210383278585706776600697390594676670949044853458725265160881988\ 2084749950992866329044372718461606717853051665720454892482365160798512119289736626147563842129\ 4411304102175225351454309111978859911929038099688842789037587794032841229198437324237536700892\ 7728489473030868320207155862182761458011320336853856827661187278843561910376653985438214526419\ 7102688171941079855705113680246275626745382022751172132539643159132692127687753142830796577720\ 1027313627031917470153841333409760417294730888972830865883594864443697900500978476690635629312\ 7802264598485020213552909650961418924338927045665236747543673974267120785258165994513533900281\ 2700943719133947065075080192847038684760270028531213516513900316512502507243186984877662935184\ 8253175136875303110080894898968895888556237355118836565711121513597100888613677634020705019667\ 9881240183513811317855171102125868496938741944776978452760334048215035900349390998736182414825\ 8664768253363444025694083719598814285772061830245482108488269737682131734620386133574000372672\ 7277789378789480453980096978023353355616990857398928064804199332585192821454985743714777806351\ 4254049338272382332407884528133024336150609574906489860140125259682642529994449237755714101229\ 5885234202203573212908362326001332373013012711545957134522789522442977595225130567195780560773\ 6432477246960748324054216186545984622661414048198842204937784828706363951904698167596838549413\ 8028594665866533150562237594091657624573535815186861096837689324419173010639746983286000779973\ 3205138451261199225504586268494645596694776860774288626001113291742314081810764685975378468687\ 0003847748123667583792263276860348443087970988051050999996894159042992131674804505424267928269\ 4004813610888211708315760224834499434209013265997046387269786800811198425539239682734603314312\ 7822020585689395324622118050391570144998225599696841225401588647806719195391359305845058995185\ 1404282513544713976496746667180174014813012618606142496440193036222093993267278298350151554554\ 5952784831204985999598787966283481106715031940856811455318790381846177934611804820349794089877\ 3367052409029590319964725561892114790409994020573439262942655097343138586818999356020915679351\ 3554956962193870193620162751205533141846733469099353718457028618904005174968239801692540188386\ 1984265887239732788059110336730135837497667593568992591457267948763290358200731310204020633463\ 9320464085586407110283095852744290661022918886196596117706354191006594063822118553593959933252\ 2388658649462456432232758401232130356839199437959062750931558169461428888204332895840870255696\ 6988413373681560548195549636654286357513097117257316851450675033480524457615721639274886210955\ 7237927069872835424804176307957139279082714285378742937476656012261316410085481245325292197736\ 0704756256672731786832806173163533066769971930525618800204703324445480022309403955110774013582\ 9034550205054878599937990144085006364454182261096069809398176318134672732850472362224696659699\ 4476533033417111317409443058560281155271307175607751199497284666768283735785072779979405259414\ 9685767653817766083100240551081489084235836451589343045925269287657909385587727037522644557912\ 1797617894822535136063108700396976832555674942700148977418593367675705841856926906075316348054\ 4933762400599095981464234410170930109521773310662846571762916915165122144840829489705662309841\ 9660700403437494188710765618382641099774612494115447254170004254195007210267775582991573679681\ 4207557725255279854558010093171668324531760273218605141085828018834387013682689505985435068032\ 8840394518710396500543920993704556989122333191377134700398080225576991462182360843367902354147\ 3648514517895605231126496120313650915008040980760302166541593035863061706159875265659671789935\ 0257801048098326722603246353464252940779675887638540341424620326565787421117257227421798583024\ 9580231853265159670076531834208350424367781237529405609878567726341424762467817130214447340625\ 7945109731592760426346913816867864026969629491172962032900969913548618382729394674465995280196\ 0749885425799264983267616512866178476900643687208368457755177696027201306815816322171987081156\ 8481534255330730121963213093452046765116532446076903786577821909969333677516238879691599377305\ 2053198914535426909295806402936353551764924554272714991819005804412235489613418850086343751500\ 5132508421423022520353112196592406116741720777134639709538192581904270697496971396664168049052\ 6202959311520774740231040343665653030584552824236128643091345929670228228851543752072409772201\ 1404520984503429872252856563275282594749477068594890022329804476947938245585707663785214622468\ 4866468080621303421321611090568130849286338014140280186778795891657949974627086710493672797871\ 8075018492794095530178735953518538166401578452512389706408613085584290931433978919679112245954\ 5214306701951133488826159844281264979364228221523390665679748888067241062854842746138798453978\ 5993715167879523708313967601388904481395738635940785544739653104287845764471182151237049906028\ 0226464025098721444155959305923443982499682470527227195441706042759567162320731613170484375183\ 1687446743485285393063895783640329267144998366852718508677784219373222881591167553907418757771\ 8752612686774417845905875454679841323894372781922989081180830586033369844492059016871192671401\ 1621166742869609991820729786777094325536911155527753212328438794061861432399772185034863167294\ 0271458720886554374286070373885297262982587934221069732704464871117484341778291712322674866133\ 7542248896854656912888440114664673346240258452617448123031659941581124849535633886299877799194\ 2838820711108273616965635387036718371962814939559677132377330210820670009352627660781902190217\ 3716016352956324009828047208240430473523995023062071815053244378709296592729197905515661012263\ 3181556272422015072829320388878050380905188735365207405501239797527251392935478716960609458861\ 4029859814090793748868733156532720103061173143976581859209656377103995488741156850754227452264\ 3205243497845265167280711652812394384967512364791744590110980127652997489124458572457397647925\ 6621159911630854921725100379038564837337805478204224721031678464379912089352404453794139206883\ 0193997796101689592976574325366969282354223378436361091529605423795230746211922314568332761653\ 3767708274043255234616341630910354492921030400394662040010876330826510360278120382987292398415\ 2919176523770626915364617751363341448742724676676065968340200634615966823067327607918854553308\ 3687812399923103520818626282464216329460303993026745735412140158956671360070951143183699146408\ 5408499097438057866510292832066847549257954508522018079226193960541798566855648815591996988089\ 1316607522006732952369874522444947247013678407518130334450045173397312240866728806426322687062\ 9434661730739497505750183090479444332157117822758904364288360864966071213075796623678187920480\ 9275923904534062474723378428571394821288625848079657180863985171144189367059421146791635697863\ 9986166894655407776723072250503436204824124981172203600554591670931099571913726296398576853746\ 7051283590455694056489979801122408528133031172230668026783106762621242763780510816394000118876\ 8632322663985031669053921082132781288285446788212424394291718123176004571018037101434719994394\ 8557225963074698705236513573633882221176983433877929256841447976007401609415686591279423398787\ 7354976210054509215521453822770717405878053905967705488313901869370742964692975581545967545047\ 8165908038619217718761644690559904342058531396554652744706507321314268068498474151937031236551\ 1761792729780719335363611458448918720679922006369027544575100665046279755923300208733656709767\ 1854131004188134318380679885007994971766481265841819321796388118544316280595517135782789313648\ 2237058209344461174157437932833183463776042921912563007531732907235312425958135797862170952838\ 5875255667192677160543047844413869896765656363258651976316159612615235729604896711626743194042\ 6558088574536887102310755375900833042837661921089551985011253051552519495280260450346635100269\ 6547187121403750292873615893140084659493420280408701461818132210401886137049049362507754024265\ 0887482530631606823439544304253237770576066702848747774864316023276393654970753560870766350966\ 5324419183136107056037223653986389914863222873900581142270002797246264492539910552022340690872\ 1597392912037786295482836022591220550307572234340049703137020408639526861945897748304519243895\ 0393585448474606388827613951054928888476448112993307695905450357925937937570569767772496802396\ 6270997175675368968387028320553185801242601401468208488561791111494811390146349559983977667811\ 7957496204529203115540341703395550497351921972949604916328838447326390042614125632207894277346\ 8568402626204662887198440624395423262694282371577406357950179236886620383474417747116913391027\ 0847854033854339132837553751700524438577410030874135430877234209250399690402542133864263078832\ 1257349276527445396718483545581098023105339407511062448249828703476537289426579003975001914934\ 8836338536520794289388876094066858977418113688923662127492443601326650885856251666316824875560\ 4103569697714372503947490031851976884368141710584723935944621847822884417580905313215618913339\ 4516586103542784862383406680967950754419203573482236559512411278786725862422631187203838666474\ 6159618840658707147506800261497287078086061401959714333573511062703155185838135702442260445419\ 1773058732126576469585201049565914907527891973137957995353521591076305302752943225421755743889\ 2626172939041117736601057823971935569284174874041726706607200773848616333478538880243634051611\ 8308459259823939549104404767797537570201408765492980935784581239781611837928214576748104049482\ 5817883130975956470760805809395756409441715349757792972665269063474432964655312925635202545328\ 1956658270527041916783192190807692785066887241485401008054044747654109210361276438297810764717\ 1814369717186247442759840848831068881833048198039346571488896021200622773520482250687690600334\ 3772979151643385857878479700312302133765860656513335605799245542957709859834267188558541968971\ 6704004900752459784140106625866336695347848294587442693473927664145449303619500676064414046213\ 2627292295623436629091801275682352173145687576596396730298245483403685270130920368947008490819\ 9899956876489947862529645566241985259153899412051949421021194406243171000401431708913131372094\ 7620635087174605583673549924192227060647515950654063560752664800335342584028538459352467370475\ 6123156156191956444778644358029821573069183083350376290722494380467167219525695143940019397605\ 6616041526233927563419603284162372718245577059575963222408917405250999107940276257570004952410\ 7230523620826609500770010800262620550726765017466296803688085744121900236804843972435792510850\ 5699479965744248497279282910629655753529500016496530175111615883878218790627673143971841828604\ 8000803688789461643109403064133850194486200569505992162802604961055509747481827835903566184620\ 0325321127195370719150213385453214637099520399218474780927704104622471588349213356511443330481\ 2847019874998968161166165343689676314629422227024113678188210290336457660875308433473324595686\ 0633409506419622410374734994508126033078473408391252808461984275521948515893798261410522052289\ 7668717891717352331952720499760549037581942776007005770427144389834974722018635954645207901885\ 4392315443576466043081637832574258631996421136052296373568389805798381409782365205063476982230\ 0807791682777332520747590410773353369087248012213677286038585401614208413727493750010737405300\ 9778686523083015489929583362695760890875437729553412213092459957515407505438272622803245648712\ 7593785770135323865459742032420595329742027643958057768005778693069449507597164733581663431638\ 6453836196411028499460704600909326547222949735364133797894575214713833582926744135313713330272\ 8492499414035483811576650990249157369451210068053650763079853846267537082798828754427715603859\ 3317720514818201764438467612085578743553354543926387468847447248428065674260415288099114049868\ 5770866889906346178104661918242336437798228225030445867949763193159864705585988870059724900594\ 9992418839477851676725202558036474435549526153074400551130173685662644994660032889519468196601\ 4911591707272585687580177182287873359275106131478981395051992565157759523368300309963059036295\ 7898601432186323404486369065384754546270165585458479452323896869573046864594145716019392337518\ 9103917154746664270506337784353587840372747301167695887761319463023699297448255965676083054266\ 3051722071587899296488294422300702663783954464277896772197102822703155658105578767628025699311\ 5107550566523300590415523524449681412742908651198444441044066127534622505939934929671400447789\ 0988979078025214907055958741455447727848949929342659431469872506206712091251584497009360063956\ 2234351284140441328428447140589661793357534171375437997661279485796234735648296550090370993214\ 9573508717197783001421963091211519005180662747530394457452443616438786943879927565811086324237\ 9172209669864295807761393484850475560825709816182027650787665851979704736907920181110314432896\ 3987353039534535982256472841234231198262977471748647891163388921661304865342263154135660438826\ 5443265996378200699455879116319402735894367151446899927635566922872284067900483879369217662210\ 7214237746014362628381252505885810404510504188356408413001072841317956301591861568066551550221\ 7732554036067538837458768079713940788053251246698195352277226945389481345068548774651587210539\ 2439359067152754596281186824962547722940695962881521939967798396637815790411738987964391323854\ 1636807118930579233978167193243665294328459583240620141256297010703696372765286031652141353385\ 0707799126076613767339373764983787122936850338501674555396072844336488181828537677594667686910\ 4688613259046183924596236653824500657812742799152839639701814781267878439346518514329952516793\ 9113905929144473590118301339239151255136563405291648718072122477312363282133501580569211056037\ 5415681385512258368566357173633411091445837502910630284823285497748830334786593544103983352002\ 6897540337803691592710850272356277265567463620483748432963722129071468668829155841477168595587\ 3379992418788482107198810334194559565065001914913601053517475884821794967591659806522251223532\ 8997603118814173754107082859216364068938056741831076406363245180545856019597367736722910618951\ 6922108257615784745860475472051914728150559315741695702205699780256776414907950451625183015349\ 3374887013848688316090854108997781091120310875736287113494871506670926324016611923697436662074\ 7168975008343733454348774817427435763722250779100044691082478583176875706564476388300668197817\ 5191756305926440536490665537274947452195960588166842907734632265509035317729017816316173096353\ 9501205635075409007463179394989843761117892721718472876855125846332278174098288112390112719299\ 7868447445737906943364645118530597601214787996500611598045520083270028004831766753987895862081\ 1347977576202800727513877688142714990160194224811100903111937997175275529568952631791090431860\ 7972555408543905876342341987810059519940275607117924671281012023216862816760298465136041213903\ 0186749388774474454735574641016278019716330058207305439456908203562726597528962924525997530673\ 0100480169371929727918742307446829587001658504536709567100623691543788959362607191393107082495\ 5260992418545305384575873041778517729979806961852891566906359333615626143263590092072285318044\ 1277001466046266826755209441917932489844268809759627500791751235435859755620114673818560792182\ 1350630513266328224299960118176844644782266408559294717993902956380177710584125117381720123479\ 5019524781161652104703590148774970179252144066607668185456067277479122024861016421822176484819\ 5532756776004732813913735429733949994543268790391507437094884661269168145269435637845840908416\ 9525070420393619326857469782080769526479404754050731604684847855874963641516814427541972143709\ 7832469052287531609221748070928979487768641128859863904203829924281936428396144933929443122953\ 9466597416127298262440667280249576460684619779846862114087172364198198027751242796983093147680\ 5178730838081459734906890269337818808157270563894668991913908005718727813623569124272853679104\ 5782523445307725103120342333915023028069320396035669098694276287959449070101937232159725795186\ 6915651338392338718789275029269821257080090409655876642097613530960487526029636057080814070919\ 9102858865135756454965826299211745307132399949239510939165496600663470421767887122683770144270\ 8457854025390450173703923040092194277827942358376598099574704161799381065689990521259438655694\ 9264935076559892235511974957798892750311304106895614370468433038253814575148670418565646752775\ 1564553253727709850811347656437291237418080758683947660507698577870365491932783233652957770774\ 4292473735244673794915658400921265759592522087026139345438339594381537388596932199887679679401\ 0937619327607656815804679961249784514094104697692333112529587931294015658768623302874401498644\ 8263452914151535605776621452900764067368095260232549665665918906454302828006563054792277161432\ 1314353209569241412279376916917772679199111139461262224271588074666917088540452256855345933512\ 1691905802654728690731674290567438756153228271416653396545843349420264352222551958468892831992\ 1067320928440577549303269579393911901028425631669649636562210966243665426646659229049102853171\ 8644773655402957959130314398210705881472371681886288543784744267718543037537673821758796485458\ 9519935158454112233513117098131785813400702985889549174282017533440344871443990614429838615195\ 3282750935927708480093025439682162954321750573599920056021165563037502960506659234507730406587\ 9254320101103641036271658357927664439137995958175694619737393715289621135735454351041263079148\ 8061626368089858031543770323703228312454640596316253981102293066573872520962517019178277220858\ 2192413547625462275109081449536517798947922346665326758883829645011362444367631497812636640435\ 8240123389432724581923978654751149849568195764213341310772092802468416905446880207138182165168\ 3149026203643543230833588090424778115145369296310130084254802216351261612400112759252430572442\ 9142441758531342473622149430421777577371326515788158462568885130434263118398761257644872213065\ 5572635567997317829403958119506358241293062297512217370633214810486250856218885937175167984920\ 2028394413495533110423434926003708066452032577337983613334450485123333663376840804548848574155\ 0544157519422083695232088119506604595316164560564313649333692115550572231291810754675549067876\ 5341973490964694409020984462400974360482391287423732655860075137412523822430452298966400023544\ 9336635362326886011949473382245931561187834670215695128665170841011501250638195964526040756537\ 6289255267538998608216815039235026910718671277194846003221411833227172404502474526999659301711\ 1623378167267310829007362290688440434601003789206651900472846885762869244831246448014570257010\ 2274565533912570333120366909542514756041443063639518652397469225536763179175400364846237357320\ 4319673392464232476681541177543359256347586665915619286284844983822417886505854702776952303319\ 1868993585986531184659981622691875495244565689861504640399014479236056898374501934175603263910\ 4812967352232605986379631008125558176223463373234474918630776232117329091745364578646214365696\ 7288888765744344072499125247148080748874189606419360006628937915515078017219269036255529806301\ 1533067229307145595865229814206131578753693922768409573834955660828615101358641413163705980215\ 3778120021536632978759107775607989681933803651768714733489401829446514687118201089069133519691\ 7327269523394610167640980962904774498623715883220222808201434040644871561508542809678192173565\ 8228360585488614202205964344720700033535824349165616886613326801235630411021163170480286303461\ 2952636896395891136450493725644185418562499809538271814273912096161170648246076228584659906734\ 1730526671323507891804911264119661555845235936944013595815853255147067212497902148929064798937\ 5663544155210648790099965102335815078574507646250075965649470166479484618296807206181456096322\ 1239337898651148840518714319049468616100143543241229350810034475459980307383316077363623047691\ 2980043186225941377872480839928045738360663155591567065818273440214843666101652592264378295239\ 5646826672514255403502546172192605104267718730298175038373518268397608953092361022169332120595\ 8357015964745200364928431489943210202831713693296226228539775068125697522458402521734672620537\ 1821301928209866599591904671719526279485180097510326795254077589121367006559221655415021850441\ 7033660398976797419014162177489079483515696199498503719072060911110030866682081676261643974660\ 6673777940300541351572995725784259276952976776748326629933468228990694422311963482608149836549\ 7495560617842688078823781957894917290367062500776008919455664019846511248933702114665734580450\ 5270283590651019908288028823825076523763370342979925859318649208981143741241557382693247515286\ 0892983471231649047247860545804953969546331350276518384213132324831966446059763279198658201707\ 4106843802142672711414350850395203952692855607065966318914766439373508430713040210547173909011\ 2400374277094261315266359766870042577508801867668030275324813574204708598810766736327385510247\ 6497909058954153538173422157220873673331914707283545556317441551940036815997172619651814545355\ 0647232716387157457957722784691794010984083224354879001808502608337159772891944324005422286417\ 9432159997201577751672753433763161651685853542528490638079681009294118599609469896562836811645\ 2268590358155608361667702879398636652573356394370577129822218697410557768646339622503401009703\ 7431982487127228646478778507769006933120413261282395035162561864773156587206526243185574999939\ 7082519150649550143194109022280628235632124688841941819048990519626109857929428142117233642067\ 8040199018114248934378004420309487398363304415953527304249978281615624118640537917208697301792\ 3852930638845906288822515908812033591180093414146621361243064983045530124933270433675020769291\ 8706182675901618745063194274884817917140084428856397899389551159613355621078431603601168863173\ 9773907131531145121932632654098562682517822681619729300556598426710805067928699015356981881445\ 0252473059553838985182944893658217557687644136142023003374541108584174815777585366770139465082\ 2507900113560618408214497804009578455984856361066709869813957526244398964459063943853133897800\ 6811728100537004468446935597870020504547087479838834337311279096036315762836431229200553223182\ 9617189495812537201565234172811721026363403673136818889465805664227466141580428998366657895665\ 773140018"; big_test(Natural::from_str(xss).unwrap()); } #[test] fn test_squaring_large_powers_of_2() { for i in 0..400_000 { let p = Natural::power_of_2(i).square(); assert!(p.is_valid()); assert_eq!(p.checked_log_base_2(), Some(i << 1)); } } fn limbs_square_basecase_helper_2(out: &[Limb], xs: &[Limb]) -> Vec { let mut out = out.to_vec(); let old_out = out.clone(); limbs_square_to_out_basecase_unrestricted(&mut out, xs); let n = Natural::from_limbs_asc(xs).square(); let len = xs.len() << 1; let mut limbs = n.into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); out } #[test] fn limbs_square_to_out_basecase_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_22().test_properties_with_config(&config, |(mut out, xs)| { let expected_out = limbs_square_basecase_helper_2(&out, &xs); limbs_square_to_out_basecase(&mut out, &xs); assert_eq!(out, expected_out); }); } macro_rules! square_properties_helper { ($properties: ident, $square: ident, $scratch: ident, $gen: ident) => { #[test] fn $properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 2048); config.insert("mean_stripe_n", 64 << Limb::LOG_WIDTH); $gen().test_properties_with_config(&config, |(mut out, xs)| { let expected_out = limbs_square_basecase_helper_2(&out, &xs); let mut scratch = vec![0; $scratch(xs.len())]; $square(&mut out, &xs, &mut scratch); assert_eq!(out, expected_out); }); } }; } square_properties_helper!( limbs_square_to_out_toom_2_properties, limbs_square_to_out_toom_2, limbs_square_to_out_toom_2_scratch_len, unsigned_vec_pair_gen_var_23 ); square_properties_helper!( limbs_square_to_out_toom_3_properties, limbs_square_to_out_toom_3, limbs_square_to_out_toom_3_scratch_len, unsigned_vec_pair_gen_var_24 ); square_properties_helper!( limbs_square_to_out_toom_4_properties, limbs_square_to_out_toom_4, limbs_square_to_out_toom_4_scratch_len, unsigned_vec_pair_gen_var_25 ); square_properties_helper!( limbs_square_to_out_toom_6_properties, limbs_square_to_out_toom_6, limbs_square_to_out_toom_6_scratch_len, unsigned_vec_pair_gen_var_27 ); square_properties_helper!( limbs_square_to_out_toom_8_properties, limbs_square_to_out_toom_8, limbs_square_to_out_toom_8_scratch_len, unsigned_vec_pair_gen_var_28 ); #[test] fn sign_properties() { natural_gen().test_properties(|x| { let square = (&x).square(); assert!(square.is_valid()); let mut mut_x = x.clone(); mut_x.square_assign(); assert!(mut_x.is_valid()); assert_eq!(mut_x, square); assert_eq!(&x * &x, square); assert!(square >= x); assert_eq!((&square).checked_sqrt().unwrap(), x); if x > 1 { assert_eq!(square.checked_log_base(&x).unwrap(), 2); } }); natural_pair_gen().test_properties(|(x, y)| { let x_squared = (&x).square(); let y_squared = (&y).square(); let xy = &x * &y; assert_eq!((&x + &y).square(), &x_squared + &y_squared + (&xy << 1)); assert_eq!(xy.square(), x_squared * y_squared); }); unsigned_gen_var_21::().test_properties(|x| { assert_eq!(x.square(), Natural::from(x).square()); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2Neg, PowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::slices::slice_test_zero; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ large_type_gen_var_9, unsigned_pair_gen_var_7, unsigned_vec_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_31, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_40, unsigned_vec_unsigned_pair_gen, unsigned_vec_unsigned_pair_gen_var_1, unsigned_vec_unsigned_vec_bool_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24, }; use malachite_nz::integer::Integer; use malachite_nz::natural::arithmetic::sub::{ limbs_slice_sub_in_place_right, limbs_sub, limbs_sub_greater_in_place_left, limbs_sub_greater_to_out, limbs_sub_limb, limbs_sub_limb_in_place, limbs_sub_limb_to_out, limbs_sub_same_length_in_place_left, limbs_sub_same_length_in_place_right, limbs_sub_same_length_in_place_with_overlap, limbs_sub_same_length_to_out, limbs_sub_same_length_to_out_with_overlap, limbs_sub_same_length_with_borrow_in_in_place_left, limbs_sub_same_length_with_borrow_in_to_out, limbs_vec_sub_in_place_right, }; use malachite_nz::natural::{Natural, limb_to_bit_count}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen_var_10}; use malachite_nz::test_util::natural::arithmetic::sub::{ limbs_sub_same_length_in_place_with_overlap_naive, limbs_sub_same_length_to_out_with_overlap_naive, }; use num::BigUint; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_limb() { let test = |xs: &[Limb], y: Limb, out: (Vec, bool)| { assert_eq!(limbs_sub_limb(xs, y), out); }; test(&[], 0, (vec![], false)); test(&[1], 2, (vec![u32::MAX], true)); test(&[6, 7], 2, (vec![4, 7], false)); test(&[100, 101, 102], 10, (vec![90, 101, 102], false)); test(&[123, 456], 78, (vec![45, 456], false)); test(&[123, 456], 789, (vec![4294966630, 455], false)); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, borrow: bool, out_after: &[Limb]| { let mut out = out_before.to_vec(); assert_eq!(limbs_sub_limb_to_out(&mut out, xs, y), borrow); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[], 0, false, &[10, 10, 10, 10]); test(&[10, 10, 10, 10], &[1], 2, true, &[u32::MAX, 10, 10, 10]); test(&[10, 10, 10, 10], &[6, 7], 2, false, &[4, 7, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, false, &[90, 101, 102, 10], ); test( &[10, 10, 10, 10], &[123, 456], 78, false, &[45, 456, 10, 10], ); test( &[10, 10, 10, 10], &[123, 456], 789, false, &[4294966630, 455, 10, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_limb_to_out_fail() { limbs_sub_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_limb_in_place() { let test = |xs: &[Limb], y: Limb, borrow: bool, out: &[Limb]| { let mut xs = xs.to_vec(); assert_eq!(limbs_sub_limb_in_place(&mut xs, y), borrow); assert_eq!(xs, out); }; test(&[], 0, false, &[]); test(&[1], 2, true, &[u32::MAX]); test(&[6, 7], 2, false, &[4, 7]); test(&[100, 101, 102], 10, false, &[90, 101, 102]); test(&[123, 456], 78, false, &[45, 456]); test(&[123, 456], 789, false, &[4294966630, 455]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub() { let test = |xs, ys, out| { assert_eq!(limbs_sub(xs, ys), out); }; test(&[], &[], (vec![], false)); test(&[2], &[], (vec![2], false)); test(&[3], &[2], (vec![1], false)); test(&[2], &[3], (vec![u32::MAX], true)); test(&[1, 2, 3], &[1, 1, 1], (vec![0, 1, 2], false)); test( &[1, 1, 1], &[1, 2, 3], (vec![0, u32::MAX, 0xfffffffd], true), ); test( &[1, 2, 3], &[6, 7], (vec![0xfffffffb, 0xfffffffa, 2], false), ); test( &[100, 101, 102], &[102, 101, 100], (vec![u32::MAX - 1, u32::MAX, 1], false), ); test( &[102, 101, 100], &[100, 101, 102], (vec![2, 0, u32::MAX - 1], true), ); test(&[0, 0, 0], &[1], (vec![u32::MAX, u32::MAX, u32::MAX], true)); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_fail() { limbs_sub(&[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_to_out() { let test = |xs, ys, out_before: &[Limb], borrow, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_sub_same_length_to_out(&mut out, xs, ys), borrow); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], false, vec![0, 0]); test(&[3], &[2], &[0, 0], false, vec![1, 0]); test(&[2], &[3], &[0, 0], true, vec![u32::MAX, 0]); test( &[1, 2, 3], &[1, 1, 1], &[0, 1, 2, 5], false, vec![0, 1, 2, 5], ); test( &[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], true, vec![0, u32::MAX, 0xfffffffd, 5], ); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], false, vec![u32::MAX - 1, u32::MAX, 1, 10], ); test( &[102, 101, 100], &[100, 101, 102], &[10, 10, 10, 10], true, vec![2, 0, u32::MAX - 1, 10], ); test( &[0, 0, 0], &[1, 0, 0], &[10, 10, 10, 10], true, vec![u32::MAX, u32::MAX, u32::MAX, 10], ); test( &[u32::MAX, u32::MAX, 0xffffff, 0, 0], &[0, 0, 0, 4294967232, u32::MAX], &[10, 10, 10, 10, 10, 10], true, vec![u32::MAX, u32::MAX, 0xffffff, 64, 0, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_to_out_fail_1() { let mut out = vec![10, 10]; limbs_sub_same_length_to_out(&mut out, &[6, 7, 8], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_to_out_fail_2() { let mut out = vec![10, 10, 10]; limbs_sub_same_length_to_out(&mut out, &[6, 7, 8], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_greater_to_out() { let test = |xs, ys, out_before: &[Limb], borrow, out_after| { let mut out = out_before.to_vec(); assert_eq!(limbs_sub_greater_to_out(&mut out, xs, ys), borrow); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], false, vec![0, 0]); test(&[2], &[], &[0, 0], false, vec![2, 0]); test(&[3], &[2], &[0, 0], false, vec![1, 0]); test(&[2], &[3], &[0, 0], true, vec![u32::MAX, 0]); test( &[1, 2, 3], &[1, 1, 1], &[0, 1, 2, 5], false, vec![0, 1, 2, 5], ); test( &[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], true, vec![0, u32::MAX, 0xfffffffd, 5], ); test( &[1, 2, 3], &[6, 7], &[0, 0, 0], false, vec![0xfffffffb, 0xfffffffa, 2], ); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], false, vec![u32::MAX - 1, u32::MAX, 1, 10], ); test( &[102, 101, 100], &[100, 101, 102], &[10, 10, 10, 10], true, vec![2, 0, u32::MAX - 1, 10], ); test( &[0, 0, 0], &[1], &[10, 10, 10, 10], true, vec![u32::MAX, u32::MAX, u32::MAX, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_greater_to_out_fail_1() { let mut out = vec![10, 10]; limbs_sub_greater_to_out(&mut out, &[6, 7, 8], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_greater_to_out_fail_2() { let mut out = vec![10, 10, 10]; limbs_sub_greater_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_in_place_left() { let test = |xs_before: &[Limb], ys, borrow, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_sub_same_length_in_place_left(&mut xs, ys), borrow); assert_eq!(xs, xs_after); }; test(&[], &[], false, vec![]); test(&[3], &[2], false, vec![1]); test(&[2], &[3], true, vec![u32::MAX]); test(&[1, 2, 3], &[1, 1, 1], false, vec![0, 1, 2]); test(&[1, 1, 1], &[1, 2, 3], true, vec![0, u32::MAX, 0xfffffffd]); test( &[100, 101, 102], &[102, 101, 100], false, vec![u32::MAX - 1, u32::MAX, 1], ); test( &[102, 101, 100], &[100, 101, 102], true, vec![2, 0, u32::MAX - 1], ); test( &[0, 0, 0], &[1, 0, 0], true, vec![u32::MAX, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_in_place_left_fail() { limbs_sub_same_length_in_place_left(&mut [6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_greater_in_place_left() { let test = |xs_before: &[Limb], ys, borrow, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_sub_greater_in_place_left(&mut xs, ys), borrow); assert_eq!(xs, xs_after); }; test(&[], &[], false, vec![]); test(&[2], &[], false, vec![2]); test(&[3], &[2], false, vec![1]); test(&[2], &[3], true, vec![u32::MAX]); test(&[1, 2, 3], &[1, 1, 1], false, vec![0, 1, 2]); test(&[1, 1, 1], &[1, 2, 3], true, vec![0, u32::MAX, 0xfffffffd]); test(&[1, 2, 3], &[6, 7], false, vec![0xfffffffb, 0xfffffffa, 2]); test( &[100, 101, 102], &[102, 101, 100], false, vec![u32::MAX - 1, u32::MAX, 1], ); test( &[102, 101, 100], &[100, 101, 102], true, vec![2, 0, u32::MAX - 1], ); test(&[0, 0, 0], &[1], true, vec![u32::MAX, u32::MAX, u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_greater_in_place_left_fail() { limbs_sub_greater_in_place_left(&mut [6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_in_place_right() { let test = |xs, ys_before: &[Limb], borrow, ys_after| { let mut ys = ys_before.to_vec(); assert_eq!(limbs_sub_same_length_in_place_right(xs, &mut ys), borrow); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![]); test(&[3], &[2], false, vec![1]); test(&[2], &[3], true, vec![u32::MAX]); test(&[1, 2, 3], &[1, 1, 1], false, vec![0, 1, 2]); test(&[1, 1, 1], &[1, 2, 3], true, vec![0, u32::MAX, 0xfffffffd]); test( &[100, 101, 102], &[102, 101, 100], false, vec![u32::MAX - 1, u32::MAX, 1], ); test( &[102, 101, 100], &[100, 101, 102], true, vec![2, 0, u32::MAX - 1], ); test( &[0, 0, 0], &[1, 0, 0], true, vec![u32::MAX, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_in_place_right_fail_1() { limbs_sub_same_length_in_place_right(&[6, 7], &mut [1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_in_place_right_fail_2() { limbs_sub_same_length_in_place_right(&[1, 2], &mut [6, 7, 8]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_sub_in_place_right() { let test = |xs: &[Limb], ys_before: &[Limb], len: usize, borrow: bool, ys_after: &[Limb]| { let mut ys = ys_before.to_vec(); assert_eq!(limbs_slice_sub_in_place_right(xs, &mut ys, len), borrow); assert_eq!(ys, ys_after); }; test(&[], &[], 0, false, &[]); test(&[123, 456], &[789, 123], 2, false, &[4294966630, 332]); test(&[123, 456], &[789, 123], 1, false, &[4294966630, 455]); test(&[123, 0], &[789, 123], 1, true, &[4294966630, u32::MAX]); test(&[123, 456], &[789, 123], 0, false, &[123, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_sub_in_place_right_fail_1() { limbs_slice_sub_in_place_right(&[6, 7], &mut [1, 2, 3], 1); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_sub_in_place_right_fail_2() { limbs_slice_sub_in_place_right(&[6, 7], &mut [1, 2], 3); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_sub_in_place_right() { let test = |xs, ys_before: &[Limb], borrow, ys_after| { let mut ys = ys_before.to_vec(); assert_eq!(limbs_vec_sub_in_place_right(xs, &mut ys), borrow); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![]); test(&[2], &[], false, vec![2]); test(&[3], &[2], false, vec![1]); test(&[2], &[3], true, vec![u32::MAX]); test(&[1, 2, 3], &[1, 1, 1], false, vec![0, 1, 2]); test(&[1, 1, 1], &[1, 2, 3], true, vec![0, u32::MAX, 0xfffffffd]); test(&[1, 2, 3], &[6, 7], false, vec![0xfffffffb, 0xfffffffa, 2]); test( &[100, 101, 102], &[102, 101, 100], false, vec![u32::MAX - 1, u32::MAX, 1], ); test( &[102, 101, 100], &[100, 101, 102], true, vec![2, 0, u32::MAX - 1], ); test(&[0, 0, 0], &[1], true, vec![u32::MAX, u32::MAX, u32::MAX]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_vec_sub_in_place_right_fail() { limbs_vec_sub_in_place_right(&[6, 7], &mut vec![1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_with_borrow_in_to_out() { let test = |xs, ys, borrow_in, out_before: &[Limb], borrow, out_after| { let mut out = out_before.to_vec(); assert_eq!( limbs_sub_same_length_with_borrow_in_to_out(&mut out, xs, ys, borrow_in), borrow ); assert_eq!(out, out_after); }; test(&[], &[], false, &[0, 0], false, vec![0, 0]); test(&[], &[], true, &[0, 0], true, vec![0, 0]); test(&[3], &[2], false, &[0, 0], false, vec![1, 0]); test(&[3], &[2], true, &[0, 0], false, vec![0, 0]); test(&[2], &[3], false, &[0, 0], true, vec![u32::MAX, 0]); test(&[3], &[3], true, &[0, 0], true, vec![u32::MAX, 0]); test(&[2], &[3], true, &[0, 0], true, vec![u32::MAX - 1, 0]); test( &[1, 2, 3], &[1, 1, 1], false, &[0, 1, 2, 5], false, vec![0, 1, 2, 5], ); test( &[1, 1, 1], &[1, 2, 3], false, &[5, 5, 5, 5], true, vec![0, u32::MAX, 0xfffffffd, 5], ); test( &[100, 101, 102], &[102, 101, 100], false, &[10, 10, 10, 10], false, vec![u32::MAX - 1, u32::MAX, 1, 10], ); test( &[102, 101, 100], &[100, 101, 102], false, &[10, 10, 10, 10], true, vec![2, 0, u32::MAX - 1, 10], ); test( &[0, 0, 0], &[1, 0, 0], false, &[10, 10, 10, 10], true, vec![u32::MAX, u32::MAX, u32::MAX, 10], ); test( &[0, 0, 0], &[1, 0, 0], true, &[10, 10, 10, 10], true, vec![u32::MAX - 1, u32::MAX, u32::MAX, 10], ); test( &[0, 0, 0], &[0, 0, 0], true, &[10, 10, 10, 10], true, vec![u32::MAX, u32::MAX, u32::MAX, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_with_borrow_in_to_out_fail_1() { let mut out = vec![10, 10]; limbs_sub_same_length_with_borrow_in_to_out(&mut out, &[6, 7, 8], &[1, 2, 3], false); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_with_borrow_in_to_out_fail_2() { let mut out = vec![10, 10, 10]; limbs_sub_same_length_with_borrow_in_to_out(&mut out, &[6, 7, 8], &[1, 2], false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_with_borrow_in_in_place_left() { let test = |xs_before: &[Limb], ys, borrow_in, borrow, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_same_length_with_borrow_in_in_place_left(&mut xs, ys, borrow_in), borrow ); assert_eq!(xs, xs_after); }; test(&[], &[], false, false, vec![]); test(&[], &[], true, true, vec![]); test(&[3], &[2], false, false, vec![1]); test(&[3], &[2], true, false, vec![0]); test(&[2], &[3], false, true, vec![u32::MAX]); test(&[2], &[2], true, true, vec![u32::MAX]); test(&[2], &[3], true, true, vec![u32::MAX - 1]); test(&[1, 2, 3], &[1, 1, 1], false, false, vec![0, 1, 2]); test( &[1, 1, 1], &[1, 2, 3], false, true, vec![0, u32::MAX, 0xfffffffd], ); test( &[100, 101, 102], &[102, 101, 100], false, false, vec![u32::MAX - 1, u32::MAX, 1], ); test( &[102, 101, 100], &[100, 101, 102], false, true, vec![2, 0, u32::MAX - 1], ); test( &[0, 0, 0], &[1, 0, 0], false, true, vec![u32::MAX, u32::MAX, u32::MAX], ); test( &[0, 0, 0], &[1, 0, 0], true, true, vec![u32::MAX - 1, u32::MAX, u32::MAX], ); test( &[0, 0, 0], &[0, 0, 0], true, true, vec![u32::MAX, u32::MAX, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_with_borrow_in_in_place_left_fail() { limbs_sub_same_length_with_borrow_in_in_place_left(&mut [6, 7], &[1, 2, 3], false); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_in_place_with_overlap() { let test = |xs_before: &[Limb], right_start: usize, borrow: bool, xs_after: &[Limb]| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_same_length_in_place_with_overlap(&mut xs, right_start), borrow ); assert_eq!(xs, xs_after); let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_same_length_in_place_with_overlap_naive(&mut xs, right_start), borrow ); assert_eq!(xs, xs_after); }; test(&[], 0, false, &[]); test(&[4, 3, 2, 1], 0, false, &[0, 0, 0, 0]); test(&[4, 3, 2, 1], 1, false, &[1, 1, 1, 1]); test(&[4, 3, 2, 1], 2, false, &[2, 2, 2, 1]); test(&[4, 3, 2, 1], 3, false, &[3, 3, 2, 1]); test(&[4, 3, 2, 1], 4, false, &[4, 3, 2, 1]); test(&[1, 2, 3, 4], 0, false, &[0, 0, 0, 0]); test( &[1, 2, 3, 4], 1, true, &[u32::MAX, u32::MAX - 1, u32::MAX - 1, 4], ); test(&[1, 2, 3, 4], 2, true, &[u32::MAX - 1, 0xfffffffd, 3, 4]); test(&[1, 2, 3, 4], 3, true, &[0xfffffffd, 2, 3, 4]); test(&[1, 2, 3, 4], 4, false, &[1, 2, 3, 4]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_in_place_with_overlap_fail() { limbs_sub_same_length_in_place_with_overlap(&mut [1, 2, 3], 4); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_same_length_to_out_with_overlap() { let test = |xs_before: &[Limb], ys: &[Limb], borrow: bool, xs_after: &[Limb]| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_same_length_to_out_with_overlap(&mut xs, ys), borrow ); assert_eq!(xs, xs_after); let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_same_length_to_out_with_overlap_naive(&mut xs, ys), borrow ); assert_eq!(xs, xs_after); }; test(&[], &[], false, &[]); test(&[5], &[], false, &[5]); test(&[5], &[3], false, &[2]); test(&[5, 5, 5], &[3, 3], false, &[2, 2, 5]); test(&[1, 2, 3, 4], &[], false, &[1, 2, 3, 4]); test(&[1, 2, 3, 4], &[2], false, &[2, 2, 3, 4]); test(&[1, 2, 3, 4], &[2, 2], false, &[1, 2, 3, 4]); test(&[1, 2, 3, 4], &[2, 2, 2], false, &[0, 1, 2, 4]); test( &[1, 2, 3, 4], &[2, 2, 2, 2], false, &[u32::MAX, u32::MAX, 0, 2], ); test(&[1, 2, 3, 4], &[], false, &[1, 2, 3, 4]); test(&[1, 2, 3, 4], &[4], false, &[0, 2, 3, 4]); test(&[1, 2, 3, 4], &[4, 4], true, &[u32::MAX, u32::MAX, 3, 4]); test( &[1, 2, 3, 4], &[4, 4, 4], true, &[u32::MAX - 1, u32::MAX - 1, u32::MAX, 4], ); test( &[1, 2, 3, 4], &[4, 4, 4, 4], true, &[0xfffffffd, 0xfffffffd, u32::MAX - 1, u32::MAX], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_same_length_to_out_with_overlap_fail() { limbs_sub_same_length_to_out_with_overlap(&mut [1, 2, 3], &[1, 2, 3, 4]); } #[test] fn test_sub_natural() { let test = |s, t, out| { let u = Natural::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); let mut n = u.clone(); n -= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n -= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigUint::from_str(s).unwrap() - BigUint::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(s).unwrap() - rug::Integer::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("123", "0", "123"); test("456", "123", "333"); test("1000000000000", "123", "999999999877"); test("12345678987654321", "314159265358979", "12031519722295342"); test("4294967296", "1", "4294967295"); test("4294967295", "4294967295", "0"); test("4294967296", "4294967295", "1"); test("4294967296", "4294967296", "0"); test("18446744073709551616", "1", "18446744073709551615"); test("18446744073709551615", "18446744073709551615", "0"); test("18446744073709551616", "18446744073709551615", "1"); test("70734740290631708", "282942734368", "70734457347897340"); } #[test] #[should_panic] fn sub_assign_fail() { let mut x = Natural::from_str("123").unwrap(); x -= Natural::from_str("456").unwrap(); } #[test] #[should_panic] fn sub_assign_ref_fail() { let mut x = Natural::from_str("123").unwrap(); x -= &Natural::from_str("456").unwrap(); } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn sub_fail_1() { Natural::from(123u32) - Natural::from(456u32); } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn sub_fail_2() { Natural::from(123u32) - &Natural::from(456u32); } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn sub_fail_3() { &Natural::from(123u32) - Natural::from(456u32); } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn sub_fail_4() { &Natural::from(123u32) - &Natural::from(456u32); } #[test] fn limbs_sub_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(xs, y)| { let (result, borrow) = limbs_sub_limb(&xs, y); if borrow { if xs.is_empty() { assert_ne!(y, 0); assert!(result.is_empty()); } else { let mut result = result; result.push(Limb::MAX); assert_eq!( Integer::from_owned_twos_complement_limbs_asc(result), Integer::from(Natural::from_owned_limbs_asc(xs)) - Integer::from(y) ); } } else { assert_eq!( Natural::from_owned_limbs_asc(result), Natural::from_owned_limbs_asc(xs) - Natural::from(y) ); } }); } #[test] fn limbs_sub_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); let len = xs.len(); if limbs_sub_limb_to_out(&mut out, &xs, y) { let n = Integer::from(Natural::from_owned_limbs_asc(xs)) - Integer::from(y); let mut limbs = n.into_twos_complement_limbs_asc(); limbs.resize(len, Limb::MAX); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); } else { let n = Natural::from_owned_limbs_asc(xs) - Natural::from(y); let mut xs = n.into_limbs_asc(); xs.resize(len, 0); assert_eq!(xs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); } }, ); } #[test] fn limbs_sub_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); if limbs_sub_limb_in_place(&mut xs, y) { let n = Integer::from(Natural::from_owned_limbs_asc(old_xs)) - Integer::from(y); let mut expected_xs = n.into_twos_complement_limbs_asc(); expected_xs.resize(xs.len(), Limb::MAX); assert_eq!(xs, expected_xs); } else { let n = Natural::from_owned_limbs_asc(old_xs) - Natural::from(y); let mut expected_xs = n.into_limbs_asc(); expected_xs.resize(xs.len(), 0); assert_eq!(xs, expected_xs); } }); } #[test] fn limbs_sub_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_31().test_properties_with_config(&config, |(xs, ys)| { let (out, borrow) = limbs_sub(&xs, &ys); let len = out.len(); let n = Natural::from_owned_limbs_asc(out); if borrow { assert_eq!( n, Natural::from_owned_limbs_asc(xs) + Natural::from_owned_limbs_asc(ys).mod_power_of_2_neg(limb_to_bit_count(len)) ); } else { assert_eq!( n, Natural::from_owned_limbs_asc(xs) - Natural::from_owned_limbs_asc(ys) ); } }); } fn limbs_sub_greater_to_out_helper( f: &mut dyn FnMut(&mut [Limb], &[Limb], &[Limb]) -> bool, mut out: Vec, xs: Vec, ys: Vec, ) { let old_out = out.clone(); let len = xs.len(); let mut result_xs = if f(&mut out, &xs, &ys) { let n = Natural::from_owned_limbs_asc(xs) + Natural::from_owned_limbs_asc(ys).mod_power_of_2_neg(limb_to_bit_count(len)); n.into_limbs_asc() } else { let n = Natural::from_owned_limbs_asc(xs) - Natural::from_owned_limbs_asc(ys); n.into_limbs_asc() }; result_xs.resize(len, 0); assert_eq!(result_xs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); } #[test] fn limbs_sub_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_31().test_properties_with_config(&config, |(out, xs, ys)| { limbs_sub_greater_to_out_helper(&mut limbs_sub_same_length_to_out, out, xs, ys); }); } #[test] fn limbs_sub_greater_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_40().test_properties_with_config(&config, |(out, xs, ys)| { limbs_sub_greater_to_out_helper(&mut limbs_sub_greater_to_out, out, xs, ys); }); } fn limbs_sub_greater_in_place_left_helper( f: &mut dyn FnMut(&mut [Limb], &[Limb]) -> bool, mut xs: Vec, ys: Vec, ) { let xs_old = xs.clone(); let len = xs.len(); let borrow = f(&mut xs, &ys); let n = Natural::from_owned_limbs_asc(xs); if borrow { assert_eq!( n, Natural::from_owned_limbs_asc(xs_old) + Natural::from_owned_limbs_asc(ys).mod_power_of_2_neg(limb_to_bit_count(len)) ); } else { assert_eq!( n, Natural::from_owned_limbs_asc(xs_old) - Natural::from_owned_limbs_asc(ys) ); } } #[test] fn limbs_sub_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, ys)| { limbs_sub_greater_in_place_left_helper(&mut limbs_sub_same_length_in_place_left, xs, ys); }); } #[test] fn limbs_sub_greater_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_31().test_properties_with_config(&config, |(xs, ys)| { limbs_sub_greater_in_place_left_helper(&mut limbs_sub_greater_in_place_left, xs, ys); }); } #[test] fn limbs_slice_sub_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_24().test_properties_with_config( &config, |(xs, mut ys, len)| { let mut ys_old = ys.clone(); let borrow = limbs_slice_sub_in_place_right(&xs, &mut ys, len); let xs_len = xs.len(); let x = Natural::from_owned_limbs_asc(xs); ys_old.truncate(len); let y = Natural::from_owned_limbs_asc(ys_old); ys.truncate(xs_len); let n = Natural::from_owned_limbs_asc(ys); if borrow { assert_eq!(n, x + y.mod_power_of_2_neg(limb_to_bit_count(xs_len))); } else { assert_eq!(n, x - y); } }, ); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, mut ys)| { assert!(!limbs_slice_sub_in_place_right(&xs, &mut ys, 0)); assert_eq!(xs, ys); }); } macro_rules! limbs_vec_sub_in_place_right_helper { ($f:ident, $xs:ident, $ys:ident) => { let ys_old = $ys.clone(); let borrow = $f(&$xs, &mut $ys); let n = Natural::from_owned_limbs_asc($ys); if borrow { let xs_len = $xs.len(); assert_eq!( n, Natural::from_owned_limbs_asc($xs) + Natural::from_owned_limbs_asc(ys_old) .mod_power_of_2_neg(limb_to_bit_count(xs_len)) ); } else { assert_eq!( n, Natural::from_owned_limbs_asc($xs) - Natural::from_owned_limbs_asc(ys_old) ); } }; } #[test] fn limbs_sub_same_length_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, mut ys)| { limbs_vec_sub_in_place_right_helper!(limbs_sub_same_length_in_place_right, xs, ys); }); } #[test] fn limbs_vec_sub_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_31().test_properties_with_config(&config, |(xs, mut ys)| { limbs_vec_sub_in_place_right_helper!(limbs_vec_sub_in_place_right, xs, ys); }); } #[test] fn limbs_sub_same_length_with_borrow_in_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_9().test_properties_with_config(&config, |(mut out, xs, ys, borrow_in)| { let old_out = out.clone(); let len = xs.len(); let n = if limbs_sub_same_length_with_borrow_in_to_out(&mut out, &xs, &ys, borrow_in) { let mut n = Integer::from(Natural::from_owned_limbs_asc(xs)) - Integer::from(Natural::from_owned_limbs_asc(ys)); if borrow_in { n -= Integer::ONE; } assert!(n < 0); n.mod_power_of_2(limb_to_bit_count(len)) } else { let mut n = Natural::from_owned_limbs_asc(xs) - Natural::from_owned_limbs_asc(ys); if borrow_in { n -= Natural::ONE; } n }; let mut limbs = n.into_limbs_asc(); limbs.resize(len, 0); assert_eq!(limbs, &out[..len]); assert_eq!(&out[len..], &old_out[len..]); }); } #[test] fn limbs_sub_same_length_with_borrow_in_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_bool_triple_gen_var_1().test_properties_with_config( &config, |(mut xs, ys, borrow_in)| { let xs_old = xs.clone(); let len = xs.len(); let borrow = limbs_sub_same_length_with_borrow_in_in_place_left(&mut xs, &ys, borrow_in); let n = Natural::from_owned_limbs_asc(xs); let mut expected_result = if borrow { let bit_len = limb_to_bit_count(len); let mut neg_y = Natural::from_owned_limbs_asc(ys).mod_power_of_2_neg(bit_len); if neg_y == 0 { neg_y = Natural::power_of_2(bit_len); } Natural::from_owned_limbs_asc(xs_old) + neg_y } else { Natural::from_owned_limbs_asc(xs_old) - Natural::from_owned_limbs_asc(ys) }; if borrow_in { expected_result -= Natural::ONE; } assert_eq!(n, expected_result); }, ); } #[test] fn limbs_sub_same_length_in_place_with_overlap_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_1().test_properties_with_config( &config, |(mut xs, right_start)| { let xs_old = xs.clone(); let borrow = limbs_sub_same_length_in_place_with_overlap(&mut xs, right_start); let len = xs.len() - right_start; let x = Natural::from_limbs_asc(&xs_old[..len]); let y = Natural::from_limbs_asc(&xs_old[right_start..]); let n = Natural::from_limbs_asc(&xs[..len]); if borrow { assert_eq!(n, x + y.mod_power_of_2_neg(limb_to_bit_count(len))); } else { assert_eq!(n, x - y); } assert_eq!(&xs[len..], &xs_old[len..]); let mut xs_alt = xs_old; assert_eq!( limbs_sub_same_length_in_place_with_overlap_naive(&mut xs_alt, right_start), borrow ); assert_eq!(xs_alt, xs); }, ); unsigned_vec_gen().test_properties_with_config(&config, |mut xs| { let xs_old = xs.clone(); assert!(!limbs_sub_same_length_in_place_with_overlap(&mut xs, 0)); assert!(slice_test_zero(&xs)); let mut xs = xs_old.clone(); assert!(!limbs_sub_same_length_in_place_with_overlap( &mut xs, xs_old.len(), )); assert_eq!(xs, xs_old); }); } #[test] fn limbs_sub_same_length_to_out_with_overlap_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_31().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); let borrow = limbs_sub_same_length_to_out_with_overlap(&mut xs, &ys); let len = ys.len(); let x = Natural::from_limbs_asc(&xs_old[xs.len() - len..]); let y = Natural::from_limbs_asc(&ys); let n = Natural::from_limbs_asc(&xs[..len]); if borrow { assert_eq!(n, x + y.mod_power_of_2_neg(limb_to_bit_count(len))); } else { assert_eq!(n, x - y); } if len <= xs.len() - len { assert_eq!(&xs[len..xs.len() - len], &xs_old[len..xs.len() - len]); } let mut xs_alt = xs_old; assert_eq!( limbs_sub_same_length_to_out_with_overlap_naive(&mut xs_alt, &ys), borrow ); assert_eq!(xs_alt, xs); }); unsigned_vec_gen().test_properties_with_config(&config, |mut xs| { let xs_old = xs.clone(); assert!(!limbs_sub_same_length_to_out_with_overlap(&mut xs, &xs_old)); assert!(slice_test_zero(&xs)); let mut xs = xs_old.clone(); assert!(!limbs_sub_same_length_to_out_with_overlap(&mut xs, &[])); assert_eq!(xs, xs_old); }); } #[test] fn sub_properties() { natural_pair_gen_var_10().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x -= y.clone(); assert!(mut_x.is_valid()); let diff = mut_x; let mut mut_x = x.clone(); mut_x -= &y; assert!(mut_x.is_valid()); let diff_alt = mut_x; assert_eq!(diff_alt, diff); let mut rug_x = rug::Integer::from(&x); rug_x -= rug::Integer::from(&y); assert_eq!(Natural::exact_from(&rug_x), diff); let diff_alt = x.clone() - y.clone(); assert!(diff_alt.is_valid()); assert_eq!(diff_alt, diff); let diff_alt = x.clone() - &y; assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = &x - y.clone(); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = &x - &y; assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); assert_eq!( Natural::from(&(BigUint::from(&x) - BigUint::from(&y))), diff ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) - rug::Integer::from(&y))), diff ); assert!(diff <= x); assert_eq!(diff + y, x); }); natural_gen().test_properties(|x| { assert_eq!(&x - Natural::ZERO, x); assert_eq!(&x - &x, Natural::ZERO); }); unsigned_pair_gen_var_7::().test_properties(|(y, x)| { assert_eq!(Natural::from(x - y), Natural::from(x) - Natural::from(y)); }); } ================================================ FILE: malachite-nz/tests/natural/arithmetic/sub_mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedSub, CheckedSubMul, SubMul, SubMulAssign}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_triple_gen_var_2, unsigned_vec_triple_gen_var_59, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12, }; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::sub_mul::{ limbs_sub_mul, limbs_sub_mul_in_place_left, limbs_sub_mul_limb_greater, limbs_sub_mul_limb_greater_in_place_left, limbs_sub_mul_limb_greater_in_place_right, limbs_sub_mul_limb_same_length_in_place_left, limbs_sub_mul_limb_same_length_in_place_right, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_pair_gen, natural_pair_gen_var_10, natural_triple_gen_var_7, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_mul_limb_greater() { let test = |xs_before: &[Limb], ys_before: &[Limb], limb: Limb, result: &[Limb], borrow| { let o_result = limbs_sub_mul_limb_greater(xs_before, ys_before, limb); if borrow == 0 { assert_eq!(o_result.unwrap(), result); } else { assert!(o_result.is_none()); } let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_mul_limb_greater_in_place_left(&mut xs, ys_before, limb), borrow ); assert_eq!(xs, result); let mut ys = ys_before.to_vec(); assert_eq!( limbs_sub_mul_limb_greater_in_place_right(xs_before, &mut ys, limb), borrow ); assert_eq!(ys, result); }; test(&[], &[], 4, &[], 0); test(&[123, 456], &[], 4, &[123, 456], 0); test(&[123, 456], &[123], 0, &[123, 456], 0); test(&[123, 456], &[123], 4, &[4294966927, 455], 0); test(&[123, 456], &[123], u32::MAX, &[246, 333], 0); test(&[123, 456], &[0, 123], u32::MAX, &[123, 579], 123); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_limb_greater_fail() { limbs_sub_mul_limb_greater(&[10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_limb_greater_in_place_left_fail() { limbs_sub_mul_limb_greater_in_place_left(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_limb_greater_in_place_right_fail() { limbs_sub_mul_limb_greater_in_place_right(&[10], &mut vec![10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_mul_limb_same_length() { let test = |xs_before: &[Limb], ys_before: &[Limb], limb: Limb, result: &[Limb], borrow| { let mut xs = xs_before.to_vec(); assert_eq!( limbs_sub_mul_limb_same_length_in_place_left(&mut xs, ys_before, limb), borrow ); assert_eq!(xs, result); let mut ys = ys_before.to_vec(); assert_eq!( limbs_sub_mul_limb_same_length_in_place_right(xs_before, &mut ys, limb), borrow ); assert_eq!(ys, result); }; test(&[], &[], 4, &[], 0); test(&[123, 456], &[0, 0], 4, &[123, 456], 0); test(&[123, 456], &[123, 0], 0, &[123, 456], 0); test(&[123, 456], &[123, 0], 4, &[4294966927, 455], 0); test(&[123, 456], &[123, 0], u32::MAX, &[246, 333], 0); test(&[123, 456], &[0, 123], u32::MAX, &[123, 579], 123); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_limb_same_length_in_place_left_fail() { limbs_sub_mul_limb_same_length_in_place_left(&mut [10, 10], &[10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_limb_same_length_in_place_right_fail() { limbs_sub_mul_limb_same_length_in_place_right(&[10, 10], &mut [10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_sub_mul_and_limbs_sub_mul_in_place_left() { let test = |xs_before: &[Limb], ys: &[Limb], zs: &[Limb], result: Option>| { assert_eq!(limbs_sub_mul(xs_before, ys, zs), result); let mut xs = xs_before.to_vec(); let result_alt = if limbs_sub_mul_in_place_left(&mut xs, ys, zs) { None } else { Some(xs) }; assert_eq!(result, result_alt); }; test(&[123, 456, 789], &[123, 789], &[321, 654], None); test( &[123, 456, 789, 1], &[123, 789], &[321, 654], Some(vec![4294927936, 4294634040, 4294452078, 0]), ); test( &[123, 456, 789, 987, 654], &[123, 789], &[321, 654], Some(vec![4294927936, 4294634040, 4294452078, 986, 654]), ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_fail_1() { limbs_sub_mul(&[10, 10, 10], &[10], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_fail_2() { limbs_sub_mul(&[10, 10, 10], &[10, 10], &[10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_fail_3() { limbs_sub_mul(&[10, 10], &[10, 10], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_in_place_left_fail_1() { let xs = &mut [10, 10, 10]; limbs_sub_mul_in_place_left(xs, &[10], &[10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_in_place_left_fail_2() { let xs = &mut [10, 10, 10]; limbs_sub_mul_in_place_left(xs, &[10, 10], &[10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_sub_mul_in_place_left_fail_3() { let xs = &mut [10, 10]; limbs_sub_mul_in_place_left(xs, &[10, 10], &[10, 10]); } #[test] fn test_sub_mul() { let test = |r, s, t, out: &str| { let u = Natural::from_str(r).unwrap(); let v = Natural::from_str(s).unwrap(); let w = Natural::from_str(t).unwrap(); let mut n = u.clone(); n.sub_mul_assign(v.clone(), w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.sub_mul_assign(v.clone(), &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.sub_mul_assign(&v, w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let mut n = u.clone(); n.sub_mul_assign(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().sub_mul(v.clone(), w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().sub_mul(v.clone(), &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().sub_mul(&v, w.clone()); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = u.clone().sub_mul(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); let n = (&u).sub_mul(&v, &w); assert!(n.is_valid()); assert_eq!(n.to_string(), out); }; test("0", "0", "0", "0"); test("0", "0", "123", "0"); test("123", "0", "5", "123"); test("123", "5", "1", "118"); test("15", "3", "4", "3"); test("1000000000000", "0", "123", "1000000000000"); test("1000000000000", "1", "123", "999999999877"); test("1000000000000", "123", "1", "999999999877"); test("1000000000000", "123", "100", "999999987700"); test("1000000000000", "100", "123", "999999987700"); test("1000000000000", "65536", "65536", "995705032704"); test("1000000000000", "1000000000000", "0", "1000000000000"); test("1000000000000", "1000000000000", "1", "0"); test("4294967296", "1", "1", "4294967295"); test( "1000000000000000000000000", "1000000000000", "1000000000000", "0", ); test( "1000000000001000000000000", "1000000000000", "1000000000000", "1000000000000", ); } #[test] #[should_panic] fn sub_mul_assign_fail_1() { let mut x = Natural::from_str("123").unwrap(); x.sub_mul_assign( Natural::from_str("5").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_fail_2() { let mut x = Natural::from_str("1000000000000").unwrap(); x.sub_mul_assign( Natural::from_str("1000000000000").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_val_ref_fail_1() { let mut x = Natural::from_str("123").unwrap(); x.sub_mul_assign( Natural::from_str("5").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_val_ref_fail_2() { let mut x = Natural::from_str("1000000000000").unwrap(); x.sub_mul_assign( Natural::from_str("1000000000000").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_ref_val_fail_1() { let mut x = Natural::from_str("123").unwrap(); x.sub_mul_assign( &Natural::from_str("5").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_ref_val_fail_2() { let mut x = Natural::from_str("1000000000000").unwrap(); x.sub_mul_assign( &Natural::from_str("1000000000000").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_ref_ref_fail_1() { let mut x = Natural::from_str("123").unwrap(); x.sub_mul_assign( &Natural::from_str("5").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_assign_ref_ref_fail_2() { let mut x = Natural::from_str("1000000000000").unwrap(); x.sub_mul_assign( &Natural::from_str("1000000000000").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_fail_1() { Natural::from_str("123").unwrap().sub_mul( Natural::from_str("5").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_fail_2() { Natural::from_str("1000000000000").unwrap().sub_mul( Natural::from_str("1000000000000").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_val_ref_fail_1() { Natural::from_str("123").unwrap().sub_mul( Natural::from_str("5").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_val_ref_fail_2() { Natural::from_str("1000000000000").unwrap().sub_mul( Natural::from_str("1000000000000").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_ref_val_fail_1() { Natural::from_str("123").unwrap().sub_mul( &Natural::from_str("5").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_ref_val_fail_2() { Natural::from_str("1000000000000").unwrap().sub_mul( &Natural::from_str("1000000000000").unwrap(), Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_ref_ref_fail_1() { Natural::from_str("123").unwrap().sub_mul( &Natural::from_str("5").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_val_ref_ref_fail_2() { Natural::from_str("1000000000000").unwrap().sub_mul( &Natural::from_str("1000000000000").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_ref_ref_ref_fail_1() { (&Natural::from_str("123").unwrap()).sub_mul( &Natural::from_str("5").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] #[should_panic] fn sub_mul_ref_ref_ref_fail_2() { (&Natural::from_str("1000000000000").unwrap()).sub_mul( &Natural::from_str("1000000000000").unwrap(), &Natural::from_str("100").unwrap(), ); } #[test] fn limbs_sub_mul_limb_greater_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().test_properties_with_config( &config, |(xs, ys, z)| { assert_eq!( limbs_sub_mul_limb_greater(&xs, &ys, z).map(Natural::from_owned_limbs_asc), Natural::from_owned_limbs_asc(xs) .checked_sub_mul(Natural::from_owned_limbs_asc(ys), Natural::from(z)) ); }, ); } fn limbs_sub_mul_limb_in_place_left_helper( f: &mut dyn FnMut(&mut [Limb], &[Limb], Limb) -> Limb, mut xs: Vec, ys: Vec, z: Limb, ) { let xs_old = xs.clone(); let borrow = f(&mut xs, &ys, z); if borrow == 0 { assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) .sub_mul(Natural::from_owned_limbs_asc(ys), Natural::from(z)) ); } else { let mut extended_xs = xs_old; extended_xs.push(0); extended_xs.push(1); let mut expected_xs = Natural::from_owned_limbs_asc(extended_xs) .sub_mul(Natural::from_owned_limbs_asc(ys), Natural::from(z)) .into_limbs_asc(); assert_eq!(expected_xs.pop().unwrap(), borrow.wrapping_neg()); assert_eq!(xs, expected_xs); } } #[test] fn limbs_sub_mul_limb_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(xs, ys, z)| { limbs_sub_mul_limb_in_place_left_helper( &mut limbs_sub_mul_limb_same_length_in_place_left, xs, ys, z, ); }, ); } #[test] fn limbs_sub_mul_limb_greater_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_1().test_properties_with_config( &config, |(xs, ys, z)| { limbs_sub_mul_limb_in_place_left_helper( &mut limbs_sub_mul_limb_greater_in_place_left, xs, ys, z, ); }, ); } macro_rules! limbs_sub_mul_limb_in_place_right_helper { ($f: ident, $xs: ident, $ys: ident, $z: ident) => {{ let ys_old = $ys.clone(); let borrow = $f(&$xs, &mut $ys, $z); if borrow == 0 { assert_eq!( Natural::from_owned_limbs_asc($ys), Natural::from_owned_limbs_asc($xs) .sub_mul(Natural::from_owned_limbs_asc(ys_old), Natural::from($z)) ); } else { let mut extended_xs = $xs.clone(); extended_xs.push(0); extended_xs.push(1); let mut expected_xs = Natural::from_owned_limbs_asc(extended_xs) .sub_mul(Natural::from_owned_limbs_asc(ys_old), Natural::from($z)) .into_limbs_asc(); assert_eq!(expected_xs.pop().unwrap(), borrow.wrapping_neg()); assert_eq!($ys, expected_xs); } }}; } #[test] fn limbs_sub_mul_limb_same_length_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(xs, mut ys, z)| { limbs_sub_mul_limb_in_place_right_helper!( limbs_sub_mul_limb_same_length_in_place_right, xs, ys, z ); }, ); } #[test] fn limbs_sub_mul_limb_greater_in_place_right_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_12().test_properties_with_config( &config, |(xs, mut ys, z)| { limbs_sub_mul_limb_in_place_right_helper!( limbs_sub_mul_limb_greater_in_place_right, xs, ys, z ); }, ); } #[test] fn limbs_sub_mul_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_59().test_properties_with_config(&config, |(xs, ys, zs)| { let expected = limbs_sub_mul(&xs, &ys, &zs).map(Natural::from_owned_limbs_asc); assert_eq!( expected, Natural::from_owned_limbs_asc(xs).checked_sub_mul( Natural::from_owned_limbs_asc(ys), Natural::from_owned_limbs_asc(zs) ) ); }); } #[test] fn limbs_sub_mul_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_59().test_properties_with_config(&config, |(mut xs, ys, zs)| { let xs_old = xs.clone(); let expected = if limbs_sub_mul_in_place_left(&mut xs, &ys, &zs) { None } else { Some(Natural::from_owned_limbs_asc(xs)) }; assert_eq!( expected, Natural::from_owned_limbs_asc(xs_old).checked_sub_mul( Natural::from_owned_limbs_asc(ys), Natural::from_owned_limbs_asc(zs) ) ); }); } #[allow(clippy::useless_conversion)] #[test] fn sub_mul_properties() { natural_triple_gen_var_7().test_properties(|(a, b, c)| { let mut mut_a = a.clone(); mut_a.sub_mul_assign(&b, &c); assert!(mut_a.is_valid()); let result = mut_a; let mut mut_a = a.clone(); mut_a.sub_mul_assign(&b, c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.sub_mul_assign(b.clone(), &c); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let mut mut_a = a.clone(); mut_a.sub_mul_assign(b.clone(), c.clone()); assert!(mut_a.is_valid()); assert_eq!(mut_a, result); let result_alt = (&a).sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().sub_mul(&b, &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().sub_mul(&b, c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().sub_mul(b.clone(), &c); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = a.clone().sub_mul(b.clone(), c.clone()); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert_eq!(&a - &b * &c, result); assert_eq!((&a).checked_sub(&b * &c), Some(result)); }); natural_gen().test_properties(|n| { assert_eq!((&n).sub_mul(&n, &Natural::ONE), 0); }); natural_pair_gen().test_properties(|(a, b)| { assert_eq!((&a).sub_mul(&Natural::ZERO, &b), a); assert_eq!((&a).sub_mul(&b, &Natural::ZERO), a); assert_eq!((&a * &b).sub_mul(a, b), 0); }); natural_pair_gen_var_10().test_properties(|(a, b)| { assert_eq!((&a).sub_mul(&Natural::ZERO, &b), a); assert_eq!((&a).sub_mul(&b, &Natural::ZERO), a); assert_eq!((&a * &b).sub_mul(a, b), 0); }); unsigned_triple_gen_var_2::().test_properties(|(x, y, z)| { assert_eq!( Limb::from(x).sub_mul(Limb::from(y), Limb::from(z)), Natural::from(x).sub_mul(Natural::from(y), Natural::from(z)) ); }); } ================================================ FILE: malachite-nz/tests/natural/basic/constants.rs ================================================ // Copyright © 2026 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 malachite_base::comparison::traits::Min; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_nz::natural::Natural; #[test] fn test_min() { let min = Natural::MIN; assert!(min.is_valid()); assert_eq!(min, 0); assert_eq!(min.to_string(), "0"); } #[test] fn test_zero() { let zero = Natural::ZERO; assert!(zero.is_valid()); assert_eq!(zero, 0); assert_eq!(zero.to_string(), "0"); } #[test] fn test_one() { let one = Natural::ONE; assert!(one.is_valid()); assert_eq!(one, 1); assert_eq!(one.to_string(), "1"); } #[test] fn test_two() { let two = Natural::TWO; assert!(two.is_valid()); assert_eq!(two, 2); assert_eq!(two.to_string(), "2"); } ================================================ FILE: malachite-nz/tests/natural/basic/default.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; #[test] fn test_default() { let default = Natural::default(); assert!(default.is_valid()); assert_eq!(default, 0); assert_eq!(default.to_string(), "0"); } ================================================ FILE: malachite-nz/tests/natural/basic/named.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_nz::natural::Natural; #[test] fn test_named() { assert_eq!(Natural::NAME, "Natural"); } ================================================ FILE: malachite-nz/tests/natural/basic/size.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; use std::mem::size_of; #[test] fn test_size() { if size_of::() == 8 { assert_eq!(size_of::(), 24); } } ================================================ FILE: malachite-nz/tests/natural/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::common::test_cmp_helper; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_gen, unsigned_vec_gen_var_3, unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_7, unsigned_vec_pair_gen_var_19, unsigned_vec_triple_gen_var_29, unsigned_vec_triple_gen_var_30, }; use malachite_nz::natural::Natural; use malachite_nz::natural::comparison::cmp::{ limbs_cmp, limbs_cmp_normalized, limbs_cmp_same_length, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_2, natural_pair_gen, natural_pair_gen_var_9, natural_triple_gen, natural_triple_gen_var_6, }; use malachite_nz::test_util::natural::comparison::cmp::natural_cmp_normalized_naive; use num::BigUint; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_cmp_same_length() { let test = |xs: &[Limb], ys: &[Limb], out| { assert_eq!(limbs_cmp_same_length(xs, ys), out); }; test(&[3], &[5], Less); test(&[3, 0], &[5, 0], Less); test(&[1, 2], &[2, 1], Greater); test(&[1, 2, 3], &[1, 2, 3], Equal); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_cmp_same_length_fail() { limbs_cmp_same_length(&[1], &[2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_cmp() { let test = |xs: &[Limb], ys: &[Limb], out| { assert_eq!(limbs_cmp(xs, ys), out); }; test(&[3], &[5], Less); test(&[3, 1], &[5], Greater); test(&[1, 2], &[2, 1, 3], Less); test(&[1, 2, 3], &[1, 2, 3], Equal); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_cmp_normalized() { let test = |xs: &[Limb], ys: &[Limb], out| { assert_eq!(limbs_cmp_normalized(xs, ys), out); }; test(&[5], &[6], Less); test(&[1], &[8], Equal); test(&[0, 0, 1], &[8], Equal); test(&[17], &[3], Less); test(&[1, 1, 1], &[1, 1], Greater); test(&[1, 0, 1], &[1, 1], Less); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_cmp_normalized_fail_1() { limbs_cmp_normalized(&[], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_cmp_normalized_fail_2() { limbs_cmp_normalized(&[1, 2, 3], &[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_cmp_normalized_fail_3() { limbs_cmp_normalized(&[1, 0], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_cmp_normalized_fail_4() { limbs_cmp_normalized(&[1, 2, 3], &[1, 0]); } #[test] fn test_cmp() { let strings = vec!["0", "1", "2", "123", "999999999999", "1000000000000", "1000000000001"]; test_cmp_helper::(&strings); test_cmp_helper::(&strings); test_cmp_helper::(&strings); } #[test] fn test_cmp_normalized() { let test = |x, y, out| { let x = Natural::from_str(x).unwrap(); let y = Natural::from_str(y).unwrap(); assert_eq!(x.cmp_normalized(&y), out); assert_eq!(natural_cmp_normalized_naive(&x, &y), out); }; test("1", "4", Equal); test("5", "6", Less); test("3", "17", Greater); test("9", "36", Equal); test("117886223846050103296", "409", Equal); test("117886223846050103295", "409", Less); test("117886223846050103297", "409", Greater); } #[test] #[should_panic] fn cmp_normalized_fail_1() { Natural::ZERO.cmp_normalized(&Natural::ONE); } #[test] #[should_panic] fn cmp_normalized_fail_2() { Natural::ONE.cmp_normalized(&Natural::ZERO); } #[test] fn limbs_cmp_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, ys)| { let cmp = limbs_cmp_same_length(&xs, &ys); assert_eq!( Natural::from_limbs_asc(&xs).cmp(&Natural::from_limbs_asc(&ys)), cmp ); assert_eq!(limbs_cmp_same_length(&ys, &xs).reverse(), cmp); }); unsigned_vec_gen().test_properties_with_config(&config, |xs| { assert_eq!(limbs_cmp_same_length(&xs, &xs), Equal); }); unsigned_vec_triple_gen_var_29().test_properties_with_config(&config, |(xs, ys, zs)| { if limbs_cmp_same_length(&xs, &ys) == Less && limbs_cmp_same_length(&ys, &zs) == Less { assert_eq!(limbs_cmp_same_length(&xs, &zs), Less); } else if limbs_cmp_same_length(&xs, &ys) == Greater && limbs_cmp_same_length(&ys, &zs) == Greater { assert_eq!(limbs_cmp_same_length(&xs, &zs), Greater); } }); } #[test] fn limbs_cmp_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_7().test_properties_with_config(&config, |(xs, ys)| { let cmp = limbs_cmp(&xs, &ys); assert_eq!( Natural::from_limbs_asc(&xs).cmp(&Natural::from_limbs_asc(&ys)), cmp ); assert_eq!(limbs_cmp(&ys, &xs).reverse(), cmp); }); unsigned_vec_gen_var_3().test_properties_with_config(&config, |xs| { assert_eq!(limbs_cmp(&xs, &xs), Equal); }); unsigned_vec_triple_gen_var_30().test_properties_with_config(&config, |(xs, ys, zs)| { if limbs_cmp(&xs, &ys) == Less && limbs_cmp(&ys, &zs) == Less { assert_eq!(limbs_cmp(&xs, &zs), Less); } else if limbs_cmp(&xs, &ys) == Greater && limbs_cmp(&ys, &zs) == Greater { assert_eq!(limbs_cmp(&xs, &zs), Greater); } }); } #[test] fn limbs_cmp_normalized_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_19().test_properties_with_config(&config, |(xs, ys)| { let cmp = limbs_cmp_normalized(&xs, &ys); assert_eq!( Natural::from_limbs_asc(&xs).cmp_normalized(&Natural::from_limbs_asc(&ys)), cmp ); assert_eq!(limbs_cmp_normalized(&ys, &xs).reverse(), cmp); }); } #[test] fn cmp_properties() { natural_pair_gen().test_properties(|(x, y)| { let cmp = x.cmp(&y); assert_eq!(BigUint::from(&x).cmp(&BigUint::from(&y)), cmp); assert_eq!(rug::Integer::from(&x).cmp(&rug::Integer::from(&y)), cmp); assert_eq!(y.cmp(&x).reverse(), cmp); assert_eq!(x == y, x.cmp(&y) == Equal); assert_eq!((-y).cmp(&(-x)), cmp); }); natural_gen().test_properties(|x| { assert_eq!(x.cmp(&x), Equal); assert!(x >= Natural::ZERO); }); natural_triple_gen().test_properties(|(x, y, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).cmp(&Natural::from(y)), x.cmp(&y)); }); } #[test] fn cmp_normalized_properties() { natural_pair_gen_var_9().test_properties(|(x, y)| { let cmp = x.cmp_normalized(&y); assert_eq!(natural_cmp_normalized_naive(&x, &y), cmp); assert_eq!(y.cmp_normalized(&x).reverse(), cmp); }); natural_gen_var_2().test_properties(|x| { assert_eq!(x.cmp_normalized(&x), Equal); }); natural_triple_gen_var_6().test_properties(|(x, y, z)| { if x.cmp_normalized(&y) == Less && y.cmp_normalized(&z) == Less { assert_eq!(x.cmp_normalized(&z), Less); } else if x.cmp_normalized(&y) == Greater && y.cmp_normalized(&z) == Greater { assert_eq!(x.cmp_normalized(&z), Greater); } }); } ================================================ FILE: malachite-nz/tests/natural/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::test_eq_helper; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use num::BigUint; use rug; #[test] fn test_eq() { let strings = vec!["0", "1", "2", "123", "1000000000000"]; test_eq_helper::(&strings); test_eq_helper::(&strings); test_eq_helper::(&strings); } #[allow(clippy::cmp_owned, clippy::eq_op)] #[test] fn eq_properties() { natural_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(BigUint::from(&x) == BigUint::from(&y), eq); assert_eq!(rug::Integer::from(&x) == rug::Integer::from(&y), eq); assert_eq!(y == x, eq); }); natural_gen().test_properties(|x| { assert_eq!(x, x); }); natural_triple_gen().test_properties(|(x, y, z)| { if x == y && y == z { assert_eq!(x, z); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) == Natural::from(y), x == y); }); } ================================================ FILE: malachite-nz/tests/natural/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_primitive_float_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_f32() { let test = |u, v: f32, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", -123.0, true); test("123", 5.0, false); test("123", -5.0, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f32::INFINITY, false); test("1", f32::NEGATIVE_INFINITY, false); test("1", f32::NAN, false); } #[test] fn test_eq_abs_f64() { let test = |u, v: f64, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", -123.0, true); test("123", 5.0, false); test("123", -5.0, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f64::INFINITY, false); test("1", f64::NEGATIVE_INFINITY, false); test("1", f64::NAN, false); } fn eq_abs_primitive_float_properties_helper< T: EqAbs + PartialEq + PrimitiveFloat, >() where Natural: EqAbs + PartialEq + PartialOrdAbs, { natural_primitive_float_pair_gen::().test_properties(|(n, x)| { let eq = n.eq_abs(&x); assert_ne!(n.ne_abs(&x), eq); assert_eq!(x.eq_abs(&n), eq); assert_eq!(n.partial_cmp_abs(&x) == Some(Equal), eq); assert_eq!(n.eq_abs(&-x), eq); }); natural_gen().test_properties(|n| { assert_ne!(n, T::NAN); assert_ne!(n, T::INFINITY); assert_ne!(n, T::NEGATIVE_INFINITY); }); } #[test] fn eq_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(eq_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_signed_pair_gen, natural_unsigned_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_u32() { let test = |u, v: u32, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 123, false); } #[test] fn test_eq_abs_u64() { let test = |u, v: u64, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); } #[test] fn test_eq_abs_i32() { let test = |u, v: i32, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 123, false); } #[test] fn test_eq_abs_i64() { let test = |u, v: i64, out| { assert_eq!(Natural::from_str(u).unwrap().eq_abs(&v), out); assert_eq!(!Natural::from_str(u).unwrap().ne_abs(&v), out); assert_eq!(v.eq_abs(&Natural::from_str(u).unwrap()), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn eq_abs_primitive_int_properties_helper_unsigned< T: EqAbs + PartialEq + PrimitiveUnsigned, >() where Natural: EqAbs + From + PartialEq + PartialOrdAbs, { natural_unsigned_pair_gen::().test_properties(|(n, u)| { let eq = n.eq_abs(&u); assert_ne!(n.ne_abs(&u), eq); assert_eq!(n == u, eq); assert_eq!(&n == &Natural::from(u), eq); assert_eq!(u.eq_abs(&n), eq); assert_eq!(u == n, eq); assert_eq!(&Natural::from(u) == &n, eq); assert_eq!(n.partial_cmp_abs(&u) == Some(Equal), eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Natural::from(y)), x == y); }); } fn eq_abs_primitive_int_properties_helper_signed + PrimitiveSigned>() where Integer: From, Natural: EqAbs + TryFrom + PartialOrdAbs, { natural_signed_pair_gen::().test_properties(|(n, i)| { let eq = n.eq_abs(&i); assert_ne!(n.ne_abs(&i), eq); // TODO assert_eq!(n.eq_abs(&Integer::from(i)), eq); assert_eq!(i.eq_abs(&n), eq); // TODO assert_eq!(Integer::from(i).eq_abs(&n), eq); assert_eq!(n.partial_cmp_abs(&i) == Some(Equal), eq); if i != T::MIN { assert_eq!(n.eq_abs(&-i), eq); } }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Natural::exact_from(x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Natural::exact_from(y)), x.eq_abs(&y)); }); } #[test] fn eq_abs_primitive_int_properties() { apply_fn_to_unsigneds!(eq_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(eq_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/natural/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::hash::hash; use malachite_nz::test_util::generators::natural_gen; #[test] fn hash_properties() { natural_gen().test_properties(|x| { assert_eq!(hash(&x), hash(&x.clone())); }); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_primitive_float_triple_gen, natural_primitive_float_pair_gen, natural_primitive_float_primitive_float_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_primitive_float() { let test = |u, v: f32, out: Option| { let out_rev = out.map(Ordering::reverse); assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), out); assert_eq!(v.partial_cmp_abs(&Natural::from_str(u).unwrap()), out_rev); let v = f64::from(v); assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), out); assert_eq!(v.partial_cmp_abs(&Natural::from_str(u).unwrap()), out_rev); }; test("5", f32::NAN, None); test("5", f32::INFINITY, Some(Less)); test("5", f32::NEGATIVE_INFINITY, Some(Less)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Less)); test("123", 123.0, Some(Equal)); test("123", 5.0, Some(Greater)); test("123", -123.0, Some(Equal)); test("1000000000000", 123.0, Some(Greater)); test("1208925819614629174706175", 1.2089258e24, Some(Less)); test("1208925819614629174706176", 1.2089258e24, Some(Equal)); test("1208925819614629174706177", 1.2089258e24, Some(Greater)); test("1208925819614629174706175", -1.2089258e24, Some(Less)); test("1208925819614629174706176", -1.2089258e24, Some(Equal)); test("1208925819614629174706177", -1.2089258e24, Some(Greater)); } fn partial_cmp_abs_primitive_float_properties_helper + PrimitiveFloat>() where Natural: TryFrom + PartialOrd + PartialOrdAbs, { natural_primitive_float_pair_gen::().test_properties(|(n, u)| { let cmp_abs = n.partial_cmp_abs(&u); let cmp_abs_rev = cmp_abs.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&n), cmp_abs_rev); assert_eq!(n.partial_cmp(&u.abs()), cmp_abs); assert_eq!(n.partial_cmp_abs(&-u), cmp_abs); }); natural_natural_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp(&m), Greater); } }); natural_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u.abs() < v.abs()); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u.abs() > v.abs()); } }); natural_gen().test_properties(|x| { assert!(x.ge_abs(&T::ZERO)); assert!(x.lt_abs(&T::NEGATIVE_INFINITY)); assert!(x.lt_abs(&T::INFINITY)); }); } #[test] fn partial_cmp_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_natural_signed_triple_gen, natural_natural_unsigned_triple_gen, natural_signed_pair_gen, natural_signed_pair_gen_var_1, natural_signed_signed_triple_gen, natural_unsigned_pair_gen, natural_unsigned_unsigned_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_u32() { let test = |u, v: u32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), cmp); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!(lt, Natural::from_str(u).unwrap().lt_abs(&v)); assert_eq!(gt, Natural::from_str(u).unwrap().gt_abs(&v)); assert_eq!(le, Natural::from_str(u).unwrap().le_abs(&v)); assert_eq!(ge, Natural::from_str(u).unwrap().ge_abs(&v)); assert_eq!(lt, v.gt_abs(&Natural::from_str(u).unwrap())); assert_eq!(gt, v.lt_abs(&Natural::from_str(u).unwrap())); assert_eq!(le, v.ge_abs(&Natural::from_str(u).unwrap())); assert_eq!(ge, v.le_abs(&Natural::from_str(u).unwrap())); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); } #[test] fn test_partial_cmp_abs_u64() { let test = |u, v: u64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), cmp); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!(lt, Natural::from_str(u).unwrap().lt_abs(&v)); assert_eq!(gt, Natural::from_str(u).unwrap().gt_abs(&v)); assert_eq!(le, Natural::from_str(u).unwrap().le_abs(&v)); assert_eq!(ge, Natural::from_str(u).unwrap().ge_abs(&v)); assert_eq!(lt, v.gt_abs(&Natural::from_str(u).unwrap())); assert_eq!(gt, v.lt_abs(&Natural::from_str(u).unwrap())); assert_eq!(le, v.ge_abs(&Natural::from_str(u).unwrap())); assert_eq!(ge, v.le_abs(&Natural::from_str(u).unwrap())); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); } #[test] fn test_partial_cmp_abs_i32() { let test = |u, v: i32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), cmp); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!(lt, Natural::from_str(u).unwrap().lt_abs(&v)); assert_eq!(gt, Natural::from_str(u).unwrap().gt_abs(&v)); assert_eq!(le, Natural::from_str(u).unwrap().le_abs(&v)); assert_eq!(ge, Natural::from_str(u).unwrap().ge_abs(&v)); assert_eq!(lt, v.gt_abs(&Natural::from_str(u).unwrap())); assert_eq!(gt, v.lt_abs(&Natural::from_str(u).unwrap())); assert_eq!(le, v.ge_abs(&Natural::from_str(u).unwrap())); assert_eq!(ge, v.le_abs(&Natural::from_str(u).unwrap())); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); } #[test] fn test_partial_cmp_abs_i64() { let test = |u, v: i64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp_abs(&v), cmp); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!( v.partial_cmp_abs(&Natural::from_str(u).unwrap()), cmp.map(Ordering::reverse) ); assert_eq!(lt, Natural::from_str(u).unwrap().lt_abs(&v)); assert_eq!(gt, Natural::from_str(u).unwrap().gt_abs(&v)); assert_eq!(le, Natural::from_str(u).unwrap().le_abs(&v)); assert_eq!(ge, Natural::from_str(u).unwrap().ge_abs(&v)); assert_eq!(lt, v.gt_abs(&Natural::from_str(u).unwrap())); assert_eq!(gt, v.lt_abs(&Natural::from_str(u).unwrap())); assert_eq!(le, v.ge_abs(&Natural::from_str(u).unwrap())); assert_eq!(ge, v.le_abs(&Natural::from_str(u).unwrap())); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", -1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "1000000000000", -1000000000001, Some(Less), true, false, true, false, ); } fn partial_cmp_abs_primitive_int_properties_helper_unsigned< T: PartialOrdAbs + PrimitiveUnsigned, >() where Natural: From + PartialOrdAbs, { natural_unsigned_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp_abs(&u); assert_eq!(Some(n.cmp(&Natural::from(u))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&n), cmp_rev); assert_eq!(Some(Natural::from(u).cmp(&n)), cmp_rev); }); natural_natural_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp(&m), Greater); } }); natural_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u < v); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u > v); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Natural::from(y)), Some(x.cmp(&y))); }); } fn partial_cmp_abs_primitive_int_properties_helper_signed< T: PartialOrdAbs + PartialOrd + PrimitiveSigned, >() where Integer: From, Natural: TryFrom + PartialOrdAbs, { natural_signed_pair_gen::().test_properties(|(n, i)| { let cmp = n.partial_cmp_abs(&i); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp_abs(&n), cmp_rev); if i != T::MIN { assert_eq!(n.partial_cmp_abs(&-i), cmp); } }); natural_signed_pair_gen_var_1::().test_properties(|(n, i)| { let cmp = n.partial_cmp_abs(&i); assert_eq!(Some(n.cmp(&Natural::exact_from(i))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(Some(Natural::exact_from(i).cmp(&n)), cmp_rev); }); natural_natural_signed_triple_gen::().test_properties(|(n, m, i)| { if n.lt_abs(&i) && i.lt_abs(&m) { assert_eq!(n.cmp(&m), Less); } else if n.gt_abs(&i) && i.gt_abs(&m) { assert_eq!(n.cmp(&m), Greater); } }); natural_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i.lt_abs(&n) && n.lt_abs(&j) { assert!(i.lt_abs(&j)); } else if i.gt_abs(&n) && n.gt_abs(&j) { assert!(i.gt_abs(&j)); } }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Natural::exact_from(x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Natural::exact_from(y)), Some(x.cmp(&y))); }); } #[test] fn partial_cmp_abs_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_primitive_float_triple_gen, natural_primitive_float_pair_gen, natural_primitive_float_primitive_float_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_primitive_float() { let test = |u, v: f32, out: Option| { let out_rev = out.map(Ordering::reverse); assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Natural::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Integer::from_str(u).unwrap()), out_rev); let v = f64::from(v); assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Natural::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Integer::from_str(u).unwrap()), out_rev); }; test("5", f32::NAN, None); test("5", f32::INFINITY, Some(Less)); test("5", f32::NEGATIVE_INFINITY, Some(Greater)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Greater)); test("123", 123.0, Some(Equal)); test("123", 5.0, Some(Greater)); test("123", -123.0, Some(Greater)); test("1000000000000", 123.0, Some(Greater)); test("1208925819614629174706175", 1.2089258e24, Some(Less)); test("1208925819614629174706176", 1.2089258e24, Some(Equal)); test("1208925819614629174706177", 1.2089258e24, Some(Greater)); test("1208925819614629174706175", -1.2089258e24, Some(Greater)); test("1208925819614629174706176", -1.2089258e24, Some(Greater)); test("1208925819614629174706177", -1.2089258e24, Some(Greater)); test("117886223846050103296", 1.1788622e20, Some(Equal)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_float_properties_helper< T: PartialOrd + PartialOrd + PrimitiveFloat, >() where Natural: TryFrom + PartialOrd, rug::Integer: PartialOrd, { natural_primitive_float_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(rug::Integer::from(&n).partial_cmp(&u), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Integer::from(&n)), cmp_rev); }); natural_natural_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); natural_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); natural_gen().test_properties(|x| { assert!(x >= T::ZERO); assert!(x > T::NEGATIVE_INFINITY); assert!(x < T::INFINITY); }); } #[test] fn partial_cmp_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_signed_triple_gen, natural_natural_unsigned_triple_gen, natural_signed_pair_gen, natural_signed_pair_gen_var_1, natural_signed_signed_triple_gen, natural_unsigned_pair_gen, natural_unsigned_unsigned_triple_gen, }; use malachite_nz::test_util::natural::comparison::partial_cmp_primitive_int::*; use num::BigUint; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_u32() { let test = |u, v: u32, out| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( num_partial_cmp_unsigned(&BigUint::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Natural::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("123", 124, Some(Less)); test("123", 122, Some(Greater)); test("1000000000000", 123, Some(Greater)); } #[test] fn test_partial_cmp_u64() { let test = |u, v: u64, out| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( num_partial_cmp_unsigned(&BigUint::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Natural::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("123", 124, Some(Less)); test("123", 122, Some(Greater)); test("1000000000000", 123, Some(Greater)); test("1000000000000", 1000000000000, Some(Equal)); test("1000000000000", 1000000000001, Some(Less)); } #[test] fn test_partial_cmp_i32() { let test = |u, v: i32, out| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Natural::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); } #[test] fn test_partial_cmp_i64() { let test = |u, v: i64, out| { assert_eq!(Natural::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Integer::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Natural::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); test("1000000000000", 1000000000000, Some(Equal)); test("1000000000000", -1000000000000, Some(Greater)); test("1000000000000", 1000000000001, Some(Less)); test("1000000000000", -1000000000001, Some(Greater)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_unsigned< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >() where BigUint: From, Natural: From + PartialOrd, rug::Integer: PartialOrd, { natural_unsigned_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(num_partial_cmp_unsigned(&From::from(&n), u), cmp); assert_eq!(rug::Integer::from(&n).partial_cmp(&u), cmp); assert_eq!(Some(n.cmp(&Natural::from(u))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Integer::from(&n)), cmp_rev); assert_eq!(Some(Natural::from(u).cmp(&n)), cmp_rev); }); natural_natural_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); natural_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); natural_gen().test_properties(|x| { assert!(x >= T::ZERO); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Natural::from(y)), Some(x.cmp(&y))); }); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_signed< T: PartialOrd + PartialOrd + PrimitiveSigned, >() where Integer: From, Natural: TryFrom + PartialOrd, rug::Integer: PartialOrd, { natural_signed_pair_gen::().test_properties(|(n, i)| { let cmp = n.partial_cmp(&i); assert_eq!(rug::Integer::from(&n).partial_cmp(&i), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp(&n), cmp_rev); assert_eq!(i.partial_cmp(&rug::Integer::from(&n)), cmp_rev); }); natural_signed_pair_gen_var_1::().test_properties(|(n, i)| { let cmp = n.partial_cmp(&i); assert_eq!(Some(n.cmp(&Natural::exact_from(i))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(Some(Natural::exact_from(i).cmp(&n)), cmp_rev); }); natural_natural_signed_triple_gen::().test_properties(|(n, m, i)| { if n < i && i < m { assert_eq!(n.cmp(&m), Less); } else if n > i && i > m { assert_eq!(n.cmp(&m), Greater); } }); natural_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i < n && n < j { assert!(i < j); } else if i > n && n > j { assert!(i > j); } }); natural_gen().test_properties(|x| { assert!(x >= T::ZERO); }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Natural::exact_from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Natural::exact_from(y)), Some(x.cmp(&y))); }); } #[test] fn partial_cmp_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_primitive_float_pair_gen; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_partial_eq_primitive_float() { let test = |u, v: f32, out| { assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); let v = f64::from(v); assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("5", f32::NAN, false); test("5", f32::INFINITY, false); test("5", f32::NEGATIVE_INFINITY, false); test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("123", 123.0, true); test("123", 5.0, false); test("123", -123.0, false); test("1000000000000", 123.0, false); test("1208925819614629174706175", 1.2089258e24, false); test("1208925819614629174706176", 1.2089258e24, true); test("1208925819614629174706177", 1.2089258e24, false); test("1208925819614629174706175", -1.2089258e24, false); test("1208925819614629174706176", -1.2089258e24, false); test("1208925819614629174706177", -1.2089258e24, false); } #[allow(clippy::cmp_owned, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_float_properties_helper< T: PartialEq + PartialEq + PrimitiveFloat, >() where Natural: TryFrom + PartialEq + PartialOrd, rug::Integer: PartialEq, { natural_primitive_float_pair_gen::().test_properties(|(n, f)| { let eq = n == f; assert_eq!(rug::Integer::from(&n) == f, eq); assert_eq!(f == n, eq); assert_eq!(f == rug::Integer::from(&n), eq); assert_eq!(n.partial_cmp(&f) == Some(Equal), eq); if eq { assert!(f.is_integer()); } }); } #[test] fn partial_eq_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_eq_primitive_float_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_signed_pair_gen, natural_unsigned_pair_gen}; use malachite_nz::test_util::natural::comparison::partial_eq_primitive_int::*; use num::BigUint; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_partial_eq_u32() { let test = |u, v: u32, out| { assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!( num_partial_eq_unsigned(&BigUint::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 123, false); } #[test] fn test_partial_eq_u64() { let test = |u, v: u64, out| { assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!( num_partial_eq_unsigned(&BigUint::from_str(u).unwrap(), v), out ); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); } #[test] fn test_partial_eq_i32() { let test = |u, v: i32, out| { assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, false); test("123", 5, false); test("1000000000000", 123, false); } #[test] fn test_partial_eq_i64() { let test = |u, v: i64, out| { assert_eq!(Natural::from_str(u).unwrap() == v, out); assert_eq!(rug::Integer::from_str(u).unwrap() == v, out); assert_eq!(v == Natural::from_str(u).unwrap(), out); assert_eq!(v == rug::Integer::from_str(u).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, false); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_unsigned< T: PartialEq + PartialEq + PrimitiveUnsigned, >() where BigUint: From, Natural: From + PartialEq + PartialOrd, rug::Integer: PartialEq, { natural_unsigned_pair_gen::().test_properties(|(n, u)| { let eq = n == u; assert_eq!(num_partial_eq_unsigned(&From::from(&n), u), eq); assert_eq!(rug::Integer::from(&n) == u, eq); assert_eq!(&n == &Natural::from(u), eq); assert_eq!(u == n, eq); assert_eq!(u == rug::Integer::from(&n), eq); assert_eq!(&Natural::from(u) == &n, eq); assert_eq!(n.partial_cmp(&u) == Some(Equal), eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) == y, x == y); assert_eq!(x == Natural::from(y), x == y); }); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_signed< T: PartialEq + PartialEq + PrimitiveSigned, >() where Integer: From, Natural: TryFrom + PartialEq + PartialOrd, rug::Integer: PartialEq, { natural_signed_pair_gen::().test_properties(|(n, i)| { let eq = n == i; assert_eq!(rug::Integer::from(&n) == i, eq); assert_eq!(&n == &Integer::from(i), eq); assert_eq!(i == n, eq); assert_eq!(i == rug::Integer::from(&n), eq); assert_eq!(&Integer::from(i) == &n, eq); assert_eq!(n.partial_cmp(&i) == Some(Equal), eq); }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Natural::exact_from(x) == y, x == y); assert_eq!(x == Natural::exact_from(y), x == y); }); } #[test] fn partial_eq_primitive_int_properties() { apply_fn_to_unsigneds!(partial_eq_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_eq_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-nz/tests/natural/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{unsigned_gen, unsigned_pair_gen_var_27}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen}; use num::BigUint; use rug; use std::str::FromStr; #[test] fn test_clone() { let test = |u| { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_string(), u); assert!(x.is_valid()); let x = BigUint::from_str(u).unwrap(); assert_eq!(x.to_string(), u); let x = rug::Integer::from_str(u).unwrap(); assert_eq!(x.to_string(), u); }; test("123"); test("1000000000000"); } #[test] fn test_clone_and_clone_from() { let test = |u, v| { // clone_from let mut x = Natural::from_str(u).unwrap(); x.clone_from(&Natural::from_str(v).unwrap()); assert_eq!(x.to_string(), v); assert!(x.is_valid()); let mut x = BigUint::from_str(u).unwrap(); x.clone_from(&BigUint::from_str(v).unwrap()); assert_eq!(x.to_string(), v); let mut x = rug::Integer::from_str(u).unwrap(); x.clone_from(&rug::Integer::from_str(v).unwrap()); assert_eq!(x.to_string(), v); }; test("123", "456"); test("123", "1000000000000"); test("1000000000000", "123"); test("1000000000000", "2000000000000"); } #[allow(clippy::redundant_clone)] #[test] fn clone_and_clone_from_properties() { natural_gen().test_properties(|x| { let mut_x = x.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, x); assert_eq!(Natural::from(&BigUint::from(&x).clone()), x); assert_eq!(Natural::exact_from(&rug::Integer::from(&x).clone()), x); }); unsigned_gen::().test_properties(|u| { let n = Natural::from(u); let cloned_u = u; let cloned_n = n.clone(); assert_eq!(cloned_u, cloned_n); }); natural_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.clone_from(&y); assert!(mut_x.is_valid()); assert_eq!(mut_x, y); let mut num_x = BigUint::from(&x); num_x.clone_from(&BigUint::from(&y)); assert_eq!(Natural::from(&num_x), y); let mut rug_x = rug::Integer::from(&x); rug_x.clone_from(&rug::Integer::from(&y)); assert_eq!(Natural::exact_from(&rug_x), y); }); unsigned_pair_gen_var_27::().test_properties(|(u, v)| { let x = Natural::from(u); let y = Natural::from(v); let mut mut_u = u; let mut mut_x = x.clone(); mut_u.clone_from(&v); mut_x.clone_from(&y); assert_eq!(mut_x, mut_u); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/digits/from_digits.rs ================================================ // Copyright © 2026 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, repeat_n}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, PowerOf2Digits, SaturatingFrom, WrappingFrom, }; use malachite_base::slices::{slice_leading_zeros, slice_trailing_zeros}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_10, unsigned_vec_unsigned_pair_gen_var_5, unsigned_vec_unsigned_pair_gen_var_12, }; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::digits::general_digits::*; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen_var_5, natural_vec_natural_pair_gen_var_1, natural_vec_natural_pair_gen_var_2, natural_vec_natural_pair_gen_var_3, natural_vec_natural_pair_gen_var_4, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3, }; use std::iter::empty; use std::panic::catch_unwind; use std::str::FromStr; fn verify_limbs_from_digits_small_base( original_out: &[Limb], xs: &[T], base: u64, out_len: usize, out: &[Limb], preserve_unused_out: bool, ) where Natural: From, { let mut expected_limbs = from_digits_desc_naive_primitive(xs, T::exact_from(base)) .unwrap() .into_limbs_asc(); assert!(expected_limbs.len() <= out_len); expected_limbs.resize(out_len, 0); assert_eq!(expected_limbs, &out[..out_len]); if preserve_unused_out { assert_eq!(&original_out[out_len..], &out[out_len..]); } } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_from_digits_small_base_basecase() { fn test(out_before: &[Limb], xs: &[u8], base: u64, out_after: &[Limb]) { let mut out = out_before.to_vec(); let out_len = limbs_from_digits_small_base_basecase(&mut out, xs, base).unwrap(); assert_eq!(&out[..out_len], out_after); verify_limbs_from_digits_small_base(out_before, xs, base, out_len, &out, true); } // - res_digit == 0 test(&[10; 2], &[0], 9, &[]); // - base != 10 // - size == 0 second time // - res_digit != 0 test(&[10; 2], &[1], 9, &[1]); test(&[10; 2], &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, &[123456]); test(&[10; 2], &[1, 2, 4, 2, 2, 3, 1, 1], 5, &[123456]); test(&[10; 2], &[2, 3, 5, 1, 3, 2, 0], 6, &[123456]); test(&[10; 2], &[1, 0, 2, 2, 6, 3, 4], 7, &[123456]); test(&[10; 2], &[2, 0, 7, 3, 1, 3], 9, &[123456]); // - base == 10 test(&[10; 2], &[1, 2, 3, 4, 5, 6], 10, &[123456]); test(&[10; 2], &[8, 4, 8, 3, 3], 11, &[123456]); test(&[10; 2], &[5, 11, 5, 4, 0], 12, &[123456]); test(&[10; 2], &[4, 4, 2, 6, 8], 13, &[123456]); test(&[10; 2], &[3, 2, 13, 12, 4], 14, &[123456]); test(&[10; 2], &[2, 6, 8, 10, 6], 15, &[123456]); test(&[10; 2], &[12, 34, 56], 100, &[123456]); test(&[10; 2], &[8, 19, 87], 123, &[123456]); test(&[10; 2], &[1, 229, 36], 255, &[123456]); // - j < xs_len // - size == 0 first time // - y != 0 // - size != 0 second time // - cy_limb != 0 second time test(&[10; 4], &[27, 90, 34, 55, 72, 93], 104, &[4056409437, 78]); // - size != 0 first time // - cy_limb != 0 first time test( &[10; 13], &[93, 88, 7, 58, 53, 12, 72, 49, 56, 91], 98, &[419414959, 1047946650, 4], ); // - cy_limb == 0 second time test( &[10; 7], &[14, 117, 113, 119, 39, 15, 71, 111, 83, 69, 36, 65, 47, 105, 10, 57, 101], 121, &[3340886628, 3137387930, 2143550403, 399066], ); // - cy_limb == 0 first time test( &[10; 15], &[ 116, 130, 52, 119, 76, 102, 131, 43, 138, 137, 117, 78, 23, 136, 111, 20, 132, 103, 126, 38, 96, 23, 23, 128, 17, 123, 30, 135, 39, 114, 36, 49, 22, 90, 79, 87, 32, 21, 67, 55, 138, 33, 44, 84, 72, 104, 10, 118, 28, 63, 85, 36, 110, 108, 61, 16, 115, 75, 26, ], 144, &[ 3776613706, 1267825649, 3972333409, 93554931, 973182892, 3884362880, 1799682409, 3576731056, 1717911507, 3669574309, 502648924, 825650249, 3326096263, 105, ], ); // - y == 0 test(&[10; 3], &[0; 8], 17, &[]); } fn limbs_from_digits_small_base_basecase_properties_helper() where Limb: WrappingFrom, Natural: From, { let mut config = GenConfig::new(); config.insert("mean_stripe_n", 4 << Limb::LOG_WIDTH); config.insert("mean_digit_count_n", 32); config.insert("mean_excess_limb_count_n", 32); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3::().test_properties_with_config( &config, |(mut out, xs, base)| { let t_base = T::exact_from(base); assert_eq!( limbs_from_digits_small_base_basecase(&mut out, &xs, base).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::().test_properties_with_config( &config, |(mut out, xs, base)| { let old_out = out.clone(); let out_len = limbs_from_digits_small_base_basecase(&mut out, &xs, base).unwrap(); verify_limbs_from_digits_small_base(&old_out, &xs, base, out_len, &out, true); }, ); } #[test] fn limbs_from_digits_small_base_basecase_properties() { apply_fn_to_unsigneds!(limbs_from_digits_small_base_basecase_properties_helper); } #[test] fn test_limbs_from_digits_small_base() { fn test(out_before: &[Limb], xs: &[u8], base: u64, out_after: &[Limb]) { let mut out = out_before.to_vec(); let out_len = limbs_from_digits_small_base(&mut out, xs, base).unwrap(); assert_eq!(&out[..out_len], out_after); verify_limbs_from_digits_small_base(out_before, xs, base, out_len, &out, false); } #[cfg(feature = "32_bit_limbs")] { // - xs_len < SET_STR_PRECOMPUTE_THRESHOLD test(&[10; 2], &[0], 9, &[]); test(&[10; 2], &[1], 9, &[1]); test(&[10; 2], &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, &[123456]); // - xs_len >= SET_STR_PRECOMPUTE_THRESHOLD // - xs_len > len_lo in limbs_from_digits_small_base_divide_and_conquer // - len_hi < SET_STR_DC_THRESHOLD in limbs_from_digits_small_base_divide_and_conquer // - out_len_hi > 0 in limbs_from_digits_small_base_divide_and_conquer // - len_lo < SET_STR_DC_THRESHOLD in limbs_from_digits_small_base_divide_and_conquer // - out_len_lo != 0 in limbs_from_digits_small_base_divide_and_conquer test( &[10; 21], &[ 73, 23, 120, 45, 108, 147, 113, 90, 129, 11, 86, 0, 102, 81, 22, 17, 32, 121, 29, 82, 27, 25, 39, 9, 139, 59, 51, 13, 44, 3, 37, 104, 41, 40, 87, 66, 83, 146, 40, 132, 15, 50, 66, 80, 73, 61, 75, 25, 78, 34, 128, 86, 68, 26, 62, 135, 21, 9, 27, 74, 12, 39, 67, 15, 41, 50, 144, 35, 98, 140, 124, 132, 10, 37, 101, 99, 14, ], 150, &[ 807199004, 1221740022, 1059231306, 812955315, 3612990781, 1076930217, 4174550874, 1465864994, 3608544731, 124397213, 3447302311, 1159387221, 1234841936, 1231519323, 2930655271, 132298638, 866385569, 3068, ], ); // - len_hi >= SET_STR_DC_THRESHOLD in limbs_from_digits_small_base_divide_and_conquer // - len_lo >= SET_STR_DC_THRESHOLD in limbs_from_digits_small_base_divide_and_conquer test( &[10; 26], &[ 93, 88, 7, 58, 53, 12, 72, 49, 56, 91, 68, 47, 3, 50, 89, 6, 66, 53, 64, 90, 97, 65, 54, 17, 8, 15, 9, 17, 0, 92, 68, 96, 25, 27, 74, 39, 36, 75, 93, 95, 11, 5, 8, 56, 32, 50, 23, 67, 15, 26, 56, 87, 92, 1, 68, 19, 55, 67, 40, 44, 29, 60, 89, 4, 11, 34, 46, 46, 78, 89, 47, 40, 30, 93, 57, 42, 7, 0, 75, 96, 70, 82, 10, 74, 29, 36, 20, 51, 86, 4, 45, 56, 29, 38, 58, 77, 34, 43, 32, 92, 38, 20, 95, 35, 7, 56, 87, 54, 61, ], 98, &[ 3323139349, 754115856, 3445503528, 536428460, 3075474891, 2424049884, 1254229577, 3821259306, 2296236337, 3400357558, 2698888552, 1812174, 3958831496, 3237209566, 3557655660, 684907780, 2294464631, 693096664, 1238680639, 1345304633, 2472224180, 2869650732, 125880, ], ); test( &[10; 1336], &[ 6, 14, 15, 18, 4, 19, 14, 2, 21, 21, 20, 4, 17, 8, 15, 12, 21, 0, 2, 8, 22, 0, 20, 2, 9, 2, 12, 7, 18, 21, 3, 4, 6, 0, 15, 12, 1, 1, 10, 19, 16, 8, 20, 11, 4, 2, 3, 9, 8, 9, 14, 18, 11, 21, 22, 22, 5, 8, 10, 14, 18, 13, 21, 14, 7, 9, 21, 17, 6, 4, 17, 22, 16, 16, 18, 22, 3, 5, 10, 9, 10, 0, 5, 17, 9, 14, 16, 10, 4, 5, 21, 8, 8, 9, 16, 7, 15, 15, 4, 11, 14, 1, 3, 20, 15, 4, 2, 6, 7, 4, 3, 21, 15, 7, 12, 9, 21, 15, 11, 10, 2, 8, 19, 12, 22, 15, 3, 1, 20, 14, 8, 8, 12, 11, 17, 1, 5, 22, 21, 21, 11, 13, 17, 0, 10, 20, 1, 14, 17, 20, 14, 3, 6, 11, 14, 9, 21, 12, 9, 12, 17, 18, 11, 7, 19, 5, 0, 13, 20, 12, 17, 8, 3, 5, 19, 5, 18, 10, 10, 7, 22, 20, 3, 21, 2, 18, 15, 15, 16, 1, 13, 15, 21, 16, 4, 15, 18, 4, 4, 7, 16, 20, 0, 7, 2, 6, 15, 10, 16, 0, 0, 2, 4, 21, 5, 7, 16, 8, 0, 20, 3, 12, 18, 8, 9, 8, 3, 1, 10, 8, 9, 17, 9, 17, 18, 17, 14, 9, 19, 22, 1, 21, 9, 22, 8, 19, 0, 5, 16, 10, 17, 2, 0, 17, 17, 6, 20, 3, 0, 4, 21, 0, 14, 13, 16, 12, 20, 9, 1, 18, 21, 11, 13, 18, 13, 2, 2, 12, 3, 0, 16, 12, 21, 22, 19, 15, 0, 8, 9, 0, 12, 6, 19, 12, 7, 4, 3, 6, 18, 17, 1, 5, 22, 22, 18, 3, 1, 14, 9, 1, 20, 10, 17, 11, 3, 19, 3, 16, 5, 11, 2, 17, 0, 21, 1, 14, 2, 22, 11, 17, 22, 3, 4, 17, 19, 3, 7, 20, 19, 17, 19, 22, 12, 15, 22, 1, 12, 6, 5, 4, 1, 4, 12, 13, 2, 2, 21, 5, 16, 3, 21, 15, 18, 0, 6, 11, 12, 1, 7, 14, 11, 8, 1, 12, 12, 18, 0, 12, 12, 6, 0, 5, 4, 18, 6, 20, 3, 18, 20, 17, 20, 22, 11, 3, 7, 15, 8, 11, 14, 21, 2, 11, 3, 22, 19, 2, 5, 21, 10, 11, 18, 9, 17, 18, 7, 12, 13, 1, 22, 11, 11, 3, 3, 21, 16, 7, 17, 3, 18, 2, 5, 4, 12, 15, 16, 22, 4, 18, 8, 20, 20, 15, 18, 7, 9, 18, 3, 0, 13, 15, 0, 19, 10, 10, 10, 7, 11, 10, 21, 19, 14, 20, 0, 17, 22, 8, 3, 19, 17, 10, 13, 14, 15, 20, 4, 10, 12, 8, 0, 14, 12, 22, 18, 1, 7, 14, 11, 7, 9, 13, 2, 0, 6, 17, 17, 1, 19, 14, 11, 10, 2, 17, 20, 6, 1, 22, 17, 14, 11, 0, 5, 14, 11, 16, 7, 0, 0, 13, 2, 12, 7, 8, 12, 3, 0, 3, 13, 20, 16, 16, 5, 8, 9, 22, 7, 18, 6, 10, 21, 17, 0, 8, 21, 14, 5, 6, 4, 15, 22, 22, 13, 6, 12, 13, 21, 5, 1, 10, 21, 12, 15, 21, 7, 6, 5, 5, 7, 11, 8, 8, 14, 8, 17, 10, 15, 14, 19, 5, 2, 5, 22, 19, 10, 20, 16, 11, 11, 19, 6, 20, 13, 18, 3, 9, 14, 1, 12, 2, 5, 12, 10, 6, 6, 4, 7, 19, 9, 18, 8, 18, 2, 7, 21, 11, 0, 2, 13, 0, 0, 9, 2, 21, 15, 20, 7, 18, 13, 22, 2, 11, 4, 21, 18, 10, 22, 18, 9, 4, 16, 19, 4, 16, 10, 22, 14, 8, 20, 6, 1, 1, 18, 18, 20, 13, 22, 19, 10, 19, 19, 21, 0, 10, 21, 15, 11, 21, 13, 1, 4, 12, 22, 15, 13, 20, 17, 3, 15, 14, 12, 9, 15, 20, 9, 1, 8, 18, 20, 21, 3, 17, 9, 21, 16, 13, 1, 20, 11, 14, 21, 13, 21, 11, 17, 5, 9, 18, 14, 11, 9, 6, 10, 16, 3, 10, 7, 22, 2, 1, 2, 9, 2, 8, 2, 11, 18, 18, 11, 2, 17, 20, 22, 10, 18, 16, 6, 17, 7, 9, 14, 16, 1, 7, 15, 13, 14, 16, 10, 4, 2, 19, 5, 2, 21, 12, 6, 9, 13, 10, 13, 5, 5, 20, 14, 20, 17, 15, 15, 6, 9, 11, 6, 7, 12, 1, 10, 10, 15, 3, 8, 11, 3, 17, 1, 11, 18, 3, 16, 5, 20, 22, 9, 10, 2, 5, 6, 6, 13, 1, 7, 9, 22, 4, 10, 4, 3, 12, 8, 16, 6, 8, 17, 2, 16, 19, 11, 10, 21, 8, 20, 12, 19, 1, 17, 8, 2, 8, 22, 7, 10, 11, 4, 5, 22, 21, 2, 20, 19, 21, 13, 16, 22, 0, 4, 16, 4, 20, 0, 11, 20, 3, 17, 13, 3, 16, 1, 13, 18, 18, 14, 0, 0, 14, 6, 20, 13, 14, 5, 5, 13, 0, 20, 3, 6, 2, 20, 9, 15, 7, 15, 3, 6, 3, 20, 6, 1, 7, 3, 13, 14, 9, 5, 11, 4, 17, 16, 3, 7, 4, 17, 13, 10, 2, 18, 5, 13, 21, 11, 21, 21, 19, 10, 7, 20, 4, 11, 5, 10, 18, 10, 18, 15, 12, 7, 15, 17, 14, 6, 17, 20, 3, 0, 5, 12, 11, 20, 6, 22, 9, 18, 6, 10, 2, 22, 21, 16, 5, 20, 20, 9, 3, 17, 11, 16, 20, 2, 9, 1, 9, 3, 22, 17, 10, 16, 18, 1, 11, 11, 7, 10, 14, 22, 18, 1, 5, 5, 21, 5, 2, 21, 16, 1, 21, 16, 11, 4, 13, 20, 1, 20, 15, 0, 21, 11, 5, 0, 6, 4, 8, 17, 8, 21, 20, 22, 8, 8, 2, 10, 8, 3, 18, 6, 0, 19, 15, 6, 20, 19, 4, 10, 10, 8, 3, 14, 15, 16, 9, 13, 7, 14, 11, 21, 4, 10, 4, 7, 11, 0, 12, 16, 11, 11, 1, 20, 11, 5, 0, 5, 5, 0, 20, 18, 20, 21, 0, 9, 10, 5, 8, 0, 17, 20, 16, 2, 22, 5, 19, 8, 18, 22, 18, 19, 5, 6, 17, 13, 9, 12, 4, 22, 17, 1, 12, 14, 22, 6, 8, 10, 15, 8, 4, 20, 1, 22, 6, 0, 3, 18, 2, 0, 11, 11, 12, 4, 3, 19, 20, 20, 1, 9, 10, 9, 1, 17, 0, 12, 6, 7, 11, 1, 9, 19, 0, 2, 10, 11, 13, 0, 9, 14, 5, 12, 1, 17, 11, 11, 9, 11, 8, 11, 17, 16, 14, 21, 22, 4, 0, 19, 19, 20, 10, 5, 19, 5, 14, 20, 2, 14, 15, 20, 19, 18, 22, 20, 11, 8, 17, 5, 11, 1, 7, 21, 22, 15, 16, 5, 12, 22, 15, 18, 3, 5, 9, 1, 21, 20, 9, 12, 8, 18, 13, 6, 16, 12, 11, 12, 2, 8, 11, 6, 15, 14, 17, 5, 4, 14, 10, 10, 16, 4, 2, 16, 16, 5, 18, 19, 20, 2, 2, 12, 14, 7, 5, 19, 18, 17, 9, 22, 8, 2, 13, 20, 6, 13, 5, 3, 14, 13, 4, 20, 12, 8, 12, 20, 1, 1, 3, 12, 22, 18, 5, 15, 9, 21, 20, 12, 15, 7, 20, 11, 7, 6, 9, 1, 20, 8, 13, 11, 4, 14, 15, 14, 16, 7, 19, 10, 5, 10, 9, 17, 6, 8, 20, 15, 20, 5, 16, 22, 14, 3, 4, 15, 18, 18, 6, 15, 1, 10, 9, 1, 5, 4, 4, 4, 16, 4, 16, 6, 14, 8, 3, 7, 21, 5, 8, 20, 2, 10, 15, 1, 7, 11, 7, 3, 4, 19, 3, 10, 10, 16, 20, 19, 0, 6, 10, 13, 9, 18, 17, 1, 0, 15, 2, 13, 22, 13, 15, 5, 17, 6, 12, 18, 2, 1, 20, 22, 4, 14, 21, 0, 21, 21, 13, 20, 8, 17, 16, 6, 8, 7, 8, 4, 20, 19, 0, 18, 4, 12, 19, 9, 14, 18, 19, 21, 9, 2, 11, 1, 21, 21, 17, 1, 6, 1, 1, 12, 0, 10, 11, 14, 7, 2, 19, 13, 5, 10, 10, 7, 7, 14, 11, 12, 11, 0, 18, 0, 17, 17, 3, 21, 5, 0, 7, 17, 12, 11, 16, 20, 11, 21, 16, 22, 8, 10, 6, 14, 3, 14, 7, 2, 0, 9, 11, 15, 13, 14, 3, 17, 13, 20, 14, 10, 16, 9, 12, 14, 16, 2, 10, 15, 6, 16, 21, 15, 2, 15, 11, 19, 19, 13, 9, 4, 15, 7, 16, 19, 8, 1, 3, 20, 9, 21, 16, 3, 8, 7, 13, 20, 6, 2, 22, 20, 4, 4, 21, 8, 16, 7, 0, 7, 18, 22, 5, 6, 22, 5, 0, 5, 10, 11, 3, 1, 16, 1, 5, 17, 17, 6, 11, 9, 21, 1, 3, 3, 11, 12, 21, 18, 15, 8, 0, 16, 13, 2, 7, 5, 19, 9, 18, 14, 15, 0, 11, 22, 4, 8, 18, 20, 9, 1, 0, 15, 1, 5, 0, 0, 14, 8, 3, 17, 17, 14, 9, 16, 11, 13, 20, 22, 8, 3, 10, 1, 11, 21, 2, 17, 5, 5, 1, 9, 0, 13, 1, 10, 9, 4, 5, 3, 14, 21, 19, 12, 6, 6, 5, 13, 13, 6, 19, 3, 3, 4, 8, 13, 22, 3, 19, 4, 18, 18, 16, 18, 22, 10, 10, 1, 15, 17, 18, 8, 7, 11, 7, 10, 5, 21, 9, 0, 15, 8, 3, 16, 7, 21, 0, 19, 13, 6, 16, 11, 12, 13, 5, 13, 7, 14, 15, 3, 12, 4, 4, 22, 16, 11, 4, 0, 18, 4, 14, 18, 11, 4, 18, 7, 7, 9, 14, 8, 3, 11, 11, 0, 1, 3, 8, 5, 11, 7, 8, 3, 0, 14, 7, 1, 3, 20, 21, 5, 3, 2, 21, 12, 0, 21, 5, 21, 3, 18, 10, 9, 0, 3, 13, 1, 11, 13, 10, 7, 13, 18, 15, 14, 8, 14, 6, 0, 15, 6, 16, 17, 10, 2, 8, 0, 2, 22, 4, 20, 15, 15, 22, 8, 2, 2, 12, 20, 20, 20, 1, 0, 10, 2, 12, 14, 13, 13, 8, 22, 7, 2, 9, 15, 22, 19, 9, 17, 14, 10, 1, 21, 5, 22, 18, 6, 18, 1, 9, 9, 12, 7, 3, 4, 13, 13, 12, 10, 1, 3, 16, 5, 22, 21, 15, 10, 22, 19, 10, 3, 21, 17, 3, 7, 13, 18, 18, 14, 11, 15, 16, 8, 5, 20, 12, 8, 21, 10, 22, 17, 7, 18, 9, 10, 19, 6, 14, 2, 22, 17, 4, 9, 9, 13, 19, 0, 21, 1, 14, 3, 19, 10, 7, 3, 19, 1, 12, 19, 21, 20, 13, 4, 7, 7, 18, 1, 13, 15, 3, 10, 5, 6, 16, 5, 20, 20, 8, 11, 14, 6, 1, 11, 0, 9, 22, 8, 14, 22, 16, 5, 19, 7, 17, 18, 7, 17, 3, 18, 20, 18, 12, 19, 11, 4, 8, 19, 4, 6, 19, 17, 12, 1, 10, 8, 16, 12, 4, 1, 17, 21, 12, 7, 22, 21, 15, 11, 13, 21, 19, 21, 9, 14, 5, 18, 10, 8, 10, 20, 5, 6, 5, 11, 11, 1, 1, 1, 6, 0, 21, 14, 16, 15, 20, 13, 12, 2, 9, 8, 16, 7, 10, 17, 3, 1, 3, 21, 14, 1, 7, 10, 19, 9, 8, 3, 9, 16, 19, 12, 6, 19, 14, 1, 2, 20, 22, 10, 9, 8, 21, 13, 9, 8, 7, 1, 14, 9, 17, 12, 12, 4, 3, 4, 4, 22, 12, 6, 10, 4, 20, 21, 11, 3, 17, 1, 14, 0, 0, 13, 2, 3, 18, 10, 14, 16, 1, 16, 22, 7, 0, 5, 12, 9, 19, 14, 22, 2, 20, 14, 15, 16, 0, 7, 2, 20, 11, 6, 11, 8, 18, 0, 6, 20, 8, 3, 15, 20, 22, 14, 12, 12, 0, 20, 6, 18, 11, 0, 9, 16, 18, 8, 9, 12, 7, 10, 16, 0, 8, 4, 8, 14, 17, 16, 17, 2, 3, 13, 22, 22, 1, 2, 10, 4, 2, 10, 17, 20, 9, 13, 17, 1, 18, 17, 19, 14, 13, 13, 15, 11, 17, 22, 17, 2, 18, 16, 0, 15, 22, 2, 6, 2, 6, 0, 10, 14, 4, 20, 17, 9, 7, 12, 22, 17, 11, 9, 10, 0, 22, 18, 19, 21, 7, 10, 1, 17, 19, 8, 5, 11, 4, 3, 6, 13, 6, 17, 17, 19, 3, 12, 4, 1, 21, 10, 13, 6, 15, 0, 8, 8, 7, 8, 9, 5, 19, 1, 2, 11, 15, 18, 3, 0, 3, 15, 16, 13, 9, 2, 21, 21, 10, 13, 20, 7, 16, 16, 1, 3, 11, 4, 22, 10, 10, 22, 8, 16, 6, 17, 5, 1, 22, 16, 11, 5, 6, 22, 14, 21, 16, 4, 7, 10, 12, 12, 1, 20, 18, 13, 10, 19, 17, 7, 0, 7, 3, 22, 22, 7, 9, 19, 22, 12, 6, 13, 15, 19, 16, 12, 6, 7, 11, 10, 15, 4, 9, 9, 11, 20, 6, 21, 9, 13, 2, 2, 10, 22, 2, 10, 2, 2, 8, 22, 4, 3, 9, 0, 6, 10, 10, 15, 7, 12, 7, 12, 10, 1, 4, 7, 10, 8, 21, 16, 12, 12, 8, 12, 22, 20, 0, 8, 1, 20, 20, 3, 6, 4, 15, 20, 3, 11, 17, 19, 8, 7, 6, 21, 15, 22, 15, 5, 6, 2, 16, 11, 20, 7, 8, 6, 1, 9, 6, 12, 2, 4, 4, 11, 21, 0, 7, 15, 8, 0, 6, 13, 6, 17, 2, 18, 10, 21, 21, 10, 4, 10, 9, 12, 8, 12, 10, 15, 5, 6, 10, 17, 15, 16, 9, 8, 12, 14, 10, 13, 4, 2, 8, 11, 9, 19, 14, 11, 17, 6, 5, 21, 13, 19, 21, 2, 10, 10, 11, 12, 13, 2, 17, 18, 9, 11, 8, 18, 9, 4, 8, 11, 9, 14, 0, 13, 3, 3, 15, 21, 15, 8, 6, 0, 15, 8, 10, 2, 3, 2, 21, 16, 5, 14, 20, 19, 11, 12, 10, 16, 11, 6, 12, 6, 7, 3, 2, 12, 15, 2, 21, 7, 7, 7, 7, 3, 10, 22, 7, 13, 16, 7, 16, 7, 18, 6, 20, 2, 22, 14, 19, 13, 11, 0, 2, 21, 4, 3, 14, 1, 14, 4, 2, 13, 7, 0, 10, 13, 6, 8, 22, 10, 13, 21, 5, 13, 1, 4, 21, 12, 16, 12, 14, 13, 16, 20, 18, 20, 8, 22, 19, 3, 2, 15, 16, 19, 11, 16, 6, 17, 19, 22, 13, 11, 20, 9, 20, 21, 9, 8, 22, 22, 18, 17, 13, 8, 18, 21, 2, 9, 13, 13, 15, 6, 14, 17, 2, 18, 3, 0, 9, 12, 11, 19, 0, 12, 0, 3, 14, 14, 3, 8, 9, 12, 12, 10, 3, 16, 1, 12, 15, 1, 4, 3, 19, 20, 2, 14, 4, 17, 20, 20, 21, 1, 22, 19, 3, 6, 21, 0, 8, 21, 20, 7, 13, 20, 14, 2, 15, 6, 5, 4, 0, 6, 10, 16, 22, 11, 6, 2, 21, 5, 12, 7, 20, 21, 10, 3, 0, 8, 17, 20, 22, 2, 1, 1, 15, 18, 9, 5, 8, 17, 18, 7, 18, 16, 1, 9, 5, 8, 15, 12, 1, 9, 11, 17, 9, 1, 4, 6, 18, 0, 14, 3, 20, 16, 11, 2, 11, 8, 7, 22, 13, 2, 20, 21, 15, 7, 15, 4, 5, 0, 18, 18, 13, 16, 17, 15, 3, 17, 11, 4, 5, 16, 13, 20, 15, 11, 17, 10, 21, 3, 11, 3, 3, 7, 4, 7, 19, 8, 3, 17, 7, 21, 0, 10, 1, 3, 17, 10, 13, 16, 18, 11, 10, 22, 16, 21, 6, 12, 2, 7, 1, 20, 3, 11, 11, 1, 1, 4, 0, 8, 17, 14, 15, 18, 1, 19, 9, 17, 20, 1, 2, 20, 9, 16, 15, 14, 13, 7, 18, 5, 19, 22, 10, 15, 9, 21, 16, 19, 9, 12, 5, 21, 4, 21, 12, 20, 6, 13, 19, 3, 2, 18, 14, 9, 21, 4, 19, 3, 9, 21, 4, 13, 14, 14, 10, 6, 13, 6, 0, 14, 7, 15, 2, 18, 20, 22, 0, 12, 16, 7, 15, 2, 15, 9, 17, 9, 7, 11, 12, 8, 1, 15, 2, 19, 0, 22, 19, 22, 14, 7, 18, 13, 9, 2, 6, 2, 15, 1, 19, 4, 9, 20, 6, 14, 15, 17, 3, 5, 15, 21, 19, 7, 7, 6, 12, 13, 17, 10, 3, 21, 3, 10, 14, 6, 13, 21, 10, 7, 15, 20, 6, 21, 7, 15, 4, 12, 20, 0, 19, 21, 14, 3, 12, 22, 3, 20, 11, 21, 3, 6, 0, 1, 19, 4, 6, 22, 17, 3, 6, 20, 17, 7, 3, 0, 17, 5, 18, 19, 12, 15, 9, 16, 8, 20, 7, 14, 2, 15, 7, 4, 3, 4, 7, 2, 21, 1, 17, 16, 5, 6, 11, 12, 22, 4, 20, 14, 13, 3, 1, 6, 13, 10, 9, 1, 13, 5, 2, 20, 9, 16, 20, 19, 7, 12, 9, 4, 19, 6, 18, 19, 15, 11, 6, 14, 16, 19, 14, 20, 11, 11, 0, 8, 12, 0, 10, 12, 0, 21, 17, 17, 11, 3, 6, 13, 21, 6, 16, 6, 14, 9, 14, 5, 7, 19, 10, 12, 10, 9, 16, 21, 8, 0, 20, 19, 16, 14, 8, 8, 13, 19, 20, 18, 7, 10, 2, 12, 4, 3, 17, 3, 15, 12, 13, 16, 4, 14, 6, 20, 9, 15, 12, 13, 19, 12, 19, 4, 2, 2, 18, 19, 11, 11, 20, 4, 3, 15, 7, 0, 12, 5, 8, 0, 2, 16, 21, 6, 4, 5, 14, 6, 5, 22, 3, 8, 1, 10, 14, 1, 19, 9, 18, 21, 20, 5, 5, 3, 18, 9, 21, 15, 19, 8, 22, 20, 12, 8, 19, 22, 4, 9, 5, 13, 6, 17, 5, 10, 0, 7, 9, 19, 22, 16, 9, 16, 9, 2, 3, 10, 13, 11, 8, 3, 22, 21, 3, 1, 20, 16, 20, 19, 21, 16, 0, 6, 2, 14, 12, 6, 6, 0, 0, 1, 22, 19, 12, 11, 10, 1, 15, 8, 0, 3, 21, 6, 6, 21, 5, 14, 15, 1, 5, 11, 8, 9, 15, 3, 9, 12, 22, 15, 19, 6, 22, 21, 21, 11, 6, 10, 0, 9, 9, 4, 20, 4, 21, 18, 7, 6, 9, 3, 11, 8, 17, 17, 9, 22, 12, 21, 3, 1, 16, 22, 13, 6, 15, 18, 4, 22, 8, 10, 7, 11, 4, 0, 13, 13, 17, 11, 7, 5, 20, 18, 3, 0, 11, 21, 16, 15, 19, 20, 8, 5, 1, 14, 13, 8, 18, 18, 14, 4, 22, 15, 0, 20, 22, 13, 9, 4, 3, 6, 8, 14, 7, 4, 8, 15, 20, 8, 15, 13, 4, 22, 2, 0, 22, 22, 14, 5, 2, 5, 11, 1, 8, 22, 2, 3, 11, 9, 9, 6, 9, 14, 14, 20, 18, 18, 12, 1, 18, 12, 8, 19, 7, 6, 6, 11, 14, 3, 16, 7, 13, 11, 17, 3, 18, 9, 2, 19, 22, 11, 20, 0, 17, 4, 14, 10, 1, 19, 3, 21, 4, 12, 6, 13, 4, 21, 20, 4, 2, 10, 13, 11, 21, 15, 7, 17, 13, 4, 2, 3, 1, 17, 8, 19, 15, 1, 6, 11, 20, 5, 4, 17, 6, 20, 15, 19, 16, 16, 16, 1, 18, 9, 22, 10, 8, 12, 2, 18, 14, 9, 12, 18, 9, 8, 13, 19, 16, 3, 15, 8, 2, 14, 18, 2, 12, 4, 1, 5, 3, 13, 6, 21, 5, 19, 20, 15, 4, 9, 18, 9, 14, 15, 19, 1, 19, 7, 11, 15, 9, 11, 22, 0, 6, 17, 17, 6, 1, 9, 0, 6, 5, 22, 11, 18, 13, 4, 9, 17, 3, 20, 13, 14, 6, 1, 7, 14, 16, 13, 22, 1, 15, 7, 2, 17, 22, 1, 22, 21, 0, 18, 9, 21, 22, 1, 22, 16, 7, 22, 4, 18, 2, 9, 2, 4, 16, 12, 9, 22, 18, 18, 20, 21, 8, 21, 1, 1, 7, 22, 20, 16, 5, 21, 14, 4, 15, 11, 19, 0, 17, 12, 12, 3, 22, 4, 22, 3, 11, 0, 7, 13, 1, 21, 0, 6, 16, 5, 18, 5, 5, 14, 15, 4, 0, 9, 9, 17, 3, 17, 0, 2, 14, 12, 6, 1, 17, 6, 21, 3, 15, 4, 2, 5, 22, 7, 6, 21, 6, 16, 3, 3, 5, 6, 9, 8, 19, 5, 9, 16, 3, 18, 19, 20, 18, 10, 5, 15, 17, 20, 16, 5, 1, 13, 20, 8, 18, 14, 12, 20, 18, 18, 4, 1, 0, 2, 8, 16, 18, 17, 15, 21, 14, 5, 13, 17, 14, 4, 10, 16, 0, 0, 22, 2, 9, 10, 13, 20, 1, 12, 11, 10, 22, 15, 16, 19, 10, 8, 1, 21, 13, 11, 3, 21, 7, 11, 3, 14, 8, 0, 4, 2, 6, 22, 22, 2, 5, 9, 19, 0, 13, 6, 1, 15, 21, 11, 11, 14, 7, 14, 4, 21, 11, 22, 4, 14, 6, 13, 5, 10, 19, 8, 21, 22, 2, 12, 16, 6, 2, 1, 12, 7, 6, 20, 9, 22, 7, 12, 19, 6, 10, 8, 10, 19, 16, 17, 9, 5, 8, 16, 14, 16, 11, 4, 2, 17, 6, 9, 5, 5, 12, 15, 15, 18, 12, 10, 8, 1, 7, 8, 11, 2, 21, 20, 20, 22, 10, 10, 3, 9, 5, 5, 12, 12, 11, 4, 7, 6, 1, 22, 7, 18, 20, 15, 12, 13, 10, 12, 17, 12, 12, 21, 0, 12, 19, 2, 8, 4, 17, 5, 20, 8, 7, 16, 22, 7, 18, 17, 5, 13, 21, 7, 3, 22, 20, 15, 1, 13, 3, 6, 6, 18, 8, 0, 16, 10, 2, 3, 8, 12, 0, 14, 1, 7, 17, 4, 17, 0, 14, 5, 22, 11, 10, 16, 19, 12, 11, 18, 13, 22, 19, 17, 19, 0, 6, 18, 13, 11, 17, 21, 9, 21, 10, 0, 17, 14, 10, 5, 13, 5, 14, 7, 6, 0, 14, 20, 16, 11, 9, 4, 3, 19, 3, 19, 16, 13, 21, 22, 21, 2, 12, 13, 6, 7, 19, 18, 20, 6, 2, 9, 6, 2, 14, 6, 18, 0, 0, 14, 9, 22, 3, 22, 3, 19, 5, 10, 2, 13, 2, 5, 15, 9, 11, 19, 10, 6, 14, 11, 9, 0, 20, 22, 17, 16, 4, 14, 7, 2, 20, 10, 21, 8, 19, 5, 9, 16, 4, 17, 7, 17, 3, 0, 12, 0, 7, 9, 11, 4, 9, 19, 20, 19, 17, 10, 19, 4, 20, 0, 9, 3, 7, 1, 19, 9, 13, 7, 15, 9, 17, 13, 21, 19, 15, 2, 11, 6, 4, 16, 9, 22, 22, 19, 9, 10, 21, 5, 13, 9, 4, 20, 18, 7, 1, 1, 19, 10, 3, 9, 8, 21, 0, 18, 7, 7, 7, 1, 8, 1, 1, 11, 16, 19, 18, 17, 10, 21, 18, 5, 5, 0, 4, 0, 0, 7, 9, 7, 5, 11, 18, 16, 20, 14, 19, 10, 20, 5, 20, 13, 20, 7, 15, 2, 4, 21, 14, 1, 15, 19, 17, 4, 21, 4, 14, 20, 14, 20, 20, 1, 6, 12, 11, 6, 7, 3, 0, 19, 2, 2, 17, 14, 6, 6, 16, 12, 1, 11, 6, 22, 21, 19, 22, 19, 19, 12, 22, 10, 21, 11, 19, 18, 6, 2, 17, 11, 11, 18, 9, 13, 0, 13, 12, 13, 6, 19, 20, 11, 11, 4, 20, 15, 22, 3, 16, 7, 0, 17, 0, 0, 12, 19, 1, 1, 8, 10, 4, 8, 18, 20, 17, 12, 9, 13, 21, 3, 12, 4, 21, 0, 1, 1, 15, 8, 22, 14, 20, 0, 6, 8, 22, 20, 3, 11, 14, 5, 11, 7, 20, 2, 1, 5, 7, 9, 10, 1, 19, 19, 19, 12, 12, 20, 11, 7, 14, 0, 22, 13, 9, 3, 13, 12, 9, 10, 18, 0, 19, 13, 6, 4, 14, 5, 15, 17, 1, 2, 18, 13, 18, 1, 22, 17, 15, 3, 2, 16, 4, 4, 21, 10, 6, 12, 17, 3, 11, 9, 18, 15, 9, 9, 19, 13, 19, 7, 6, 5, 19, 8, 11, 9, 12, 10, 14, 9, 7, 16, 12, 6, 17, 20, 16, 21, 5, 17, 16, 9, 14, 3, 9, 6, 12, 11, 18, 22, 14, 4, 22, 17, 4, 9, 7, 6, 2, 18, 20, 21, 10, 9, 0, 12, 11, 3, 0, 5, 8, 15, 13, 8, 17, 13, 20, 14, 17, 4, 8, 2, 3, 15, 15, 20, 12, 10, 11, 14, 21, 4, 22, 4, 11, 5, 20, 11, 10, 4, 19, 18, 8, 4, 17, 4, 12, 5, 20, 12, 22, 6, 11, 3, 4, 20, 9, 10, 20, 21, 9, 20, 21, 0, 9, 11, 6, 13, 16, 2, 8, 14, 7, 16, 11, 1, 14, 4, 8, 14, 14, 20, 1, 17, 9, 8, 15, 4, 19, 19, 1, 16, 7, 20, 18, 18, 21, 0, 1, 8, 21, 12, 9, 14, 10, 0, 3, 5, 5, 2, 16, 17, 14, 15, 4, 19, 4, 21, 15, 1, 21, 6, 22, 8, 6, 10, 2, 19, 20, 19, 13, 8, 21, 21, 9, 11, 13, 11, 10, 16, 6, 14, 20, 4, 15, 11, 22, 8, 10, 2, 14, 12, 4, 15, 10, 10, 8, 5, 5, 5, 17, 22, 6, 7, 17, 21, 14, 6, 10, 0, 0, 13, 15, 12, 11, 15, 10, 18, 5, 18, 19, 0, 11, 10, 6, 13, 0, 21, 22, 1, 6, 22, 20, 1, 21, 4, 19, 12, 20, 8, 7, 10, 6, 13, 21, 7, 8, 1, 1, 5, 1, 19, 15, 15, 3, 19, 11, 11, 10, 14, 22, 2, 3, 9, 18, 10, 22, 22, 21, 14, 4, 12, 21, 20, 12, 1, 5, 10, 14, 4, 5, 0, 1, 2, 13, 13, 8, 8, 16, 14, 18, 17, 9, 4, 2, 17, 6, 15, 16, 14, 15, 12, 19, 7, 15, 14, 7, 0, 12, 14, 5, 12, 14, 13, 21, 3, 7, 9, 13, 21, 11, 17, 1, 22, 17, 4, 10, 22, 1, 19, 10, 3, 20, 3, 12, 0, 21, 19, 18, 1, 4, 1, 5, 4, 17, 20, 10, 11, 18, 9, 9, 20, 0, 13, 4, 13, 22, 11, 9, 18, 19, 18, 10, 1, 2, 8, 11, 19, 5, 2, 19, 5, 10, 14, 18, 11, 18, 6, 19, 10, 16, 3, 12, 13, 13, 2, 19, 21, 15, 2, 15, 21, 11, 20, 15, 14, 5, 7, 7, 10, 8, 3, 9, 4, 0, 21, 17, 21, 0, 11, 11, 14, 16, 10, 14, 21, 4, 17, 8, 3, 10, 10, 8, 16, 13, 0, 21, 14, 8, 3, 11, 11, 3, 15, 10, 1, 1, 18, 15, 6, 2, 1, 10, 20, 12, 5, 4, 0, 14, 13, 3, 20, 8, 9, 16, 16, 12, 7, 2, 4, 14, 7, 16, 10, 4, 11, 4, 5, 9, 19, 22, 8, 15, 13, 4, 8, 10, 9, 15, 20, 16, 0, 17, 13, 1, 12, 18, 22, 10, 8, 14, 9, 16, 1, 6, 12, 19, 22, 3, 2, 17, 17, 13, 7, 8, 18, 15, 8, 21, 3, 14, 1, 10, 13, 1, 13, 3, 6, 20, 7, 21, 13, 0, 8, 13, 5, 19, 19, 11, 5, 17, 3, 13, 12, 22, 10, 5, 6, 10, 1, 20, 13, 11, 17, 14, 13, 7, 14, 19, 22, 12, 12, 15, 3, 11, 12, 15, 7, 22, 17, 4, 14, 9, 4, 18, 17, 11, 7, 5, 19, 16, 8, 4, 2, 11, 19, 3, 15, 22, 0, 3, 20, 0, 7, 3, 2, 6, 16, 22, 15, 19, 18, 14, 2, 17, 15, 3, 13, 10, 20, 12, 8, 21, 11, 5, 20, 22, 22, 11, 9, 20, 14, 12, 20, 8, 6, 9, 12, 6, 16, 16, 20, 22, 0, 20, 8, 2, 12, 22, 19, 16, 15, 6, 11, 7, 1, 8, 14, 21, 14, 22, 18, 1, 22, 8, 8, 14, 22, 3, 5, 22, 6, 9, 7, 13, 7, 12, 10, 6, 6, 22, 8, 5, 20, 12, 0, 13, 7, 2, 17, 0, 6, 20, 3, 18, 13, 21, 11, 21, 12, 19, 7, 21, 13, 21, 21, 6, 22, 7, 9, 20, 13, 12, 20, 2, 1, 12, 16, 5, 8, 5, 5, 5, 16, 13, 3, 2, 12, 5, 7, 8, 12, 4, 10, 17, 5, 17, 3, 18, 22, 3, 6, 3, 10, 18, 18, 3, 3, 2, 4, 18, 3, 18, 17, 2, 11, 3, 14, 4, 16, 2, 12, 4, 7, 18, 21, 22, 5, 18, 9, 7, 10, 17, 16, 7, 17, 7, 2, 5, 11, 12, 4, 22, 7, 21, 0, 8, 16, 0, 16, 1, 9, 11, 13, 11, 6, 19, 13, 0, 10, 15, 1, 3, 8, 21, 7, 6, 21, 11, 15, 13, 1, 10, 20, 17, 22, 7, 16, 8, 9, 9, 22, 6, 18, 12, 21, 17, 14, 10, 10, 20, 18, 10, 10, 7, 2, 7, 11, 21, 1, 1, 16, 3, 22, 2, 1, 6, 12, 16, 13, 1, 15, 18, 4, 2, 16, 15, 5, 5, 2, 4, 13, 9, 10, 1, 4, 3, 16, 9, 4, 17, 11, 10, 9, 1, 9, 1, 18, 0, 6, 6, 17, 14, 17, 20, 19, 7, 21, 4, 9, 17, 5, 0, 22, 19, 10, 20, 5, 13, 12, 19, 13, 21, 14, 14, 2, 15, 19, 2, 8, 20, 9, 11, 6, 14, 4, 12, 21, 9, 7, 10, 12, 3, 14, 1, 2, 6, 18, 14, 20, 11, 19, 13, 3, 21, 10, 22, 12, 4, 19, 12, 2, 12, 6, 4, 5, 2, 15, 2, 17, 11, 21, 3, 8, 14, 7, 3, 7, 4, 16, 9, 2, 13, 2, 13, 14, 9, 3, 6, 11, 13, 22, 8, 20, 11, 2, 6, 13, 22, 15, 1, 14, 7, 16, 18, 15, 2, 21, 21, 5, 19, 5, 12, 5, 14, 7, 2, 1, 12, 22, 8, 16, 13, 12, 15, 10, 6, 21, 8, 9, 6, 14, 11, 11, 8, 3, 1, 21, 9, 3, 17, 21, 6, 8, 8, 15, 20, 9, 19, 18, 16, 22, 20, 18, 4, 19, 18, 7, 20, 17, 16, 5, 17, 8, 22, 13, 9, 6, 13, 2, 22, 15, 1, 1, 14, 2, 11, 18, 19, 8, 10, 7, 5, 16, 5, 13, 19, 17, 2, 15, 14, 8, 14, 20, 6, 16, 9, 13, 16, 16, 19, 9, 2, 12, 15, 17, 19, 21, 4, 6, 13, 15, 18, 22, 17, 12, 20, 15, 5, 7, 18, 20, 12, 19, 14, 19, 1, 8, 20, 5, 18, 4, 11, 5, 10, 11, 11, 2, 20, 20, 2, 5, 4, 0, 15, 6, 7, 10, 14, 14, 0, 13, 20, 5, 17, 17, 0, 2, 0, 18, 0, 10, 17, 17, 2, 19, 5, 2, 21, 1, 8, 17, 16, 0, 6, 4, 22, 8, 0, 16, 16, 2, 20, 8, 12, 15, 17, 21, 12, 8, 21, 10, 2, 21, 13, 11, 18, 5, 19, 9, 2, 10, 11, 6, 4, 10, 20, 20, 9, 7, 11, 13, 20, 3, 3, 8, 7, 7, 10, 14, 10, 14, 10, 16, 3, 14, 0, 3, 19, 18, 21, 3, 21, 10, 17, 22, 12, 18, 21, 4, 14, 16, 2, 14, 15, 2, 8, 14, 17, 14, 6, 3, 0, 17, 2, 15, 4, 4, 20, 14, 14, 1, 19, 0, 12, 14, 6, 5, 16, 10, 8, 20, 5, 1, 10, 8, 2, 3, 22, 16, 0, 7, 0, 15, 5, 12, 9, 11, 5, 19, 12, 12, 14, 4, 22, 6, 9, 3, 18, 12, 9, 10, 10, 19, 19, 21, 14, 10, 5, 4, 9, 3, 22, 17, 10, 17, 19, 8, 6, 14, 14, 5, 5, 0, 9, 3, 11, 2, 17, 15, 7, 4, 19, 8, 21, 8, 7, 11, 2, 16, 3, 2, 19, 13, 19, 17, 7, 21, 4, 4, 11, 15, 3, 1, 19, 19, 22, 10, 2, 5, 8, 15, 17, 6, 5, 15, 15, 9, 7, 2, 0, 14, 11, 14, 1, 3, 13, 14, 4, 3, 11, 6, 14, 0, 0, 1, 2, 19, 8, 6, 14, 10, 9, 19, 22, 11, 12, 1, 15, 11, 10, 7, 15, 13, 8, 3, 12, 8, 1, 13, 13, 22, 17, 0, 15, 0, 1, 4, 13, 17, 8, 10, 20, 17, 17, 18, 3, 4, 13, 7, 16, 7, 17, 22, 0, 0, 13, 13, 21, 6, 4, 0, 19, 12, 9, 20, 1, 21, 20, 2, 14, 20, 19, 0, 18, 5, 14, 1, 12, 0, 9, 21, 8, 4, 11, 3, 22, 20, 15, 22, 5, 22, 20, 11, 21, 18, 8, 13, 12, 6, 10, 22, 12, 13, 7, 6, 13, 1, 13, 2, 19, 1, 13, 1, 0, 21, 5, 6, 17, 22, 14, 20, 3, 12, 8, 19, 6, 21, 19, 3, 2, 8, 3, 6, 2, 13, 19, 20, 8, 15, 19, 10, 5, 22, 16, 13, 0, 4, 4, 4, 2, 15, 13, 5, 10, 3, 21, 3, 3, 4, 1, 4, 22, 10, 2, 2, 2, 8, 18, 8, 13, 19, 13, 9, 7, 16, 5, 8, 6, 3, 10, 10, 5, 19, 7, 4, 5, 5, 1, 9, 4, 6, 12, 8, 8, 2, 3, 7, 10, 10, 22, 2, 9, 14, 14, 0, 3, 2, 12, 18, 6, 8, 8, 8, 5, 20, 12, 15, 3, 8, 12, 13, 21, 18, 17, 12, 18, 13, 13, 8, 10, 2, 3, 7, 15, 4, 13, 15, 22, 0, 6, 12, 10, 12, 3, 20, 22, 11, 15, 0, 12, 3, 16, 11, 5, 0, 6, 19, 20, 8, 15, 21, 10, 10, 9, 16, 3, 20, 3, 13, 2, 16, 16, 11, 20, 12, 6, 8, 0, 1, 15, 12, 9, 12, 18, 20, 14, 13, 17, 8, 12, 1, 10, 16, 1, 0, 7, 5, 0, 8, 17, 19, 20, 5, 15, 4, 9, 16, 21, 16, 2, 22, 12, 11, 2, 9, 2, 5, 7, 14, 10, 8, 14, 9, 4, 3, 12, 9, 7, 1, 4, 10, 22, 12, 11, 4, 5, 14, 11, 11, 22, 21, 15, 12, 17, 0, 12, 8, 6, 6, 7, 16, 3, 2, 4, 21, 18, 10, 15, 17, 10, 22, 9, 21, 14, 12, 15, 6, 13, 10, 5, 6, 16, 17, 1, 13, 12, 3, 4, 9, 3, 4, 20, 9, 4, 15, 16, 15, 22, 6, 1, 20, 12, 5, 12, 17, 17, 14, 21, 12, 2, 0, 11, 17, 9, 16, 4, 9, 7, 9, 10, 22, 4, 9, 21, 1, 1, 15, 16, 12, 15, 21, 1, 10, 19, 22, 14, 4, 17, 5, 2, 1, 13, 21, 22, 12, 5, 13, 8, 22, 15, 22, 5, 5, 11, 12, 9, 16, 7, 4, 0, 15, 14, 18, 15, 5, 7, 13, 10, 13, 2, 5, 19, 8, 3, 16, 6, 13, 1, 1, 16, 20, 22, 3, 18, 6, 9, 15, 8, 21, 2, 16, 5, 19, 11, 13, 4, 18, 4, 12, 13, 17, 4, 10, 7, 8, 7, 2, 22, 9, 20, 16, 10, 10, 18, 22, 22, 5, 15, 8, 10, 15, 14, 5, 12, 20, 21, 5, 13, 9, 10, 0, 16, 17, 20, 0, 6, 8, 11, 2, 9, 17, 22, 11, 14, 10, 10, 17, 3, 7, 8, 20, 1, 11, 17, 18, 1, 14, 1, 16, 14, 12, 19, 14, 15, 13, 22, 9, 18, 17, 16, 5, 15, 22, 7, 19, 14, 21, 12, 22, 15, 16, 9, 7, 11, 18, 6, 17, 22, 21, 15, 11, 12, 10, 17, 1, 1, 17, 4, 15, 3, 4, 5, 13, 9, 16, 14, 4, 19, 21, 20, 20, 2, 15, 19, 11, 13, 9, 1, 17, 16, 7, 5, 8, 13, 14, 5, 17, 13, 21, 19, 14, 14, 20, 7, 21, 18, 22, 18, 2, 9, 4, 5, 7, 10, 2, 14, 18, 12, 10, 4, 5, 15, 0, 0, 4, 6, 14, 0, 2, 0, 21, 19, 22, 22, 3, 15, 6, 11, 22, 15, 21, 14, 13, 0, 7, 8, 4, 20, 12, 12, 11, 15, 12, 15, 0, 5, 13, 6, 0, 22, 11, 10, 1, 1, 13, 11, 19, 2, 0, 12, 8, 8, 20, 9, 14, 10, 12, 20, 8, 20, 9, 10, 6, 21, 2, 17, 17, 11, 1, 14, 13, 5, 11, 4, 2, 13, 2, 21, 18, 9, 13, 14, 13, 2, 3, 19, 8, 17, 15, 8, 17, 12, 17, 8, 15, 4, 20, 22, 7, 7, 21, 5, 6, 14, 17, 0, 15, 16, 22, 11, 17, 17, 20, 21, 13, 0, 13, 14, 2, 5, 14, 16, 3, 14, 11, 15, 4, 9, 0, 6, 5, 5, 18, 7, 22, 4, 21, 17, 3, 1, 17, 18, 12, 12, 18, 14, 18, 0, 0, 8, 14, 1, 14, 0, 6, 21, 8, 8, 18, 6, 1, 17, 0, 0, 16, 0, 13, 12, 7, 18, 2, 6, 16, 13, 11, 0, 5, 1, 6, 8, 21, 22, 3, 6, 8, 21, 12, 19, 16, 11, 3, 17, 13, 15, 8, 1, 11, 22, 2, 8, 22, 7, 14, 14, 20, 18, 18, 20, 22, 17, 3, 20, 4, 14, 13, 17, 2, 5, 20, 19, 17, 16, 18, 17, 20, 6, 19, 2, 2, 9, 0, 10, 1, 11, 18, 0, 7, 19, 16, 8, 0, 1, 21, 14, 21, 3, 18, 0, 1, 2, 4, 0, 9, 17, 12, 1, 9, 17, 21, 7, 17, 20, 9, 10, 7, 6, 10, 10, 15, 14, 2, 9, 20, 20, 8, 15, 2, 6, 3, 0, 7, 11, 21, 21, 8, 6, 4, 7, 9, 5, 3, 15, 4, 1, 1, 10, 21, 13, 22, 5, 22, 2, 5, 11, 6, 22, 10, 11, 3, 12, 3, 20, 7, 22, 5, 11, 20, 0, 5, 15, 20, 10, 7, 11, 0, 21, 7, 21, 8, 0, 16, 16, 22, 12, 16, 13, 10, 5, 22, 13, 15, 12, 9, 12, 13, 2, 7, 0, 5, 16, 18, 0, 1, 0, 6, 7, 0, 1, 7, 22, 4, 4, 13, 9, 3, 11, 11, 10, 5, 20, 17, 16, 18, 15, 6, 20, 15, 1, 8, 4, 2, 3, 21, 19, 3, 14, 6, 16, 5, 17, 10, 20, 15, 5, 5, 20, 21, 3, 6, 14, 9, 22, 18, 11, 14, 2, 21, 5, 9, 16, 16, 21, 3, 4, 19, 11, 14, 19, 18, 21, 4, 0, 18, 8, 16, 21, 7, 19, 4, 2, 14, 10, 17, 18, 18, 11, 17, 2, 14, 22, 20, 2, 22, 6, 4, 12, 6, 6, 16, 5, 16, 3, 15, 12, 22, 7, 15, 19, 14, 9, 2, 10, 19, 5, 3, 0, 20, 3, 12, 6, 14, 2, 20, 20, 18, 22, 3, 11, 20, 10, 1, 7, 17, 18, 17, 7, 0, 20, 8, 22, 1, 21, 7, 22, 4, 18, 7, 16, 13, 10, 7, 13, 0, 1, 11, 7, 20, 14, 0, 5, 10, 2, 9, 17, 5, 1, 13, 14, 5, 18, 17, 9, 16, 12, 0, 18, 7, 16, 17, 14, 10, 9, 19, 20, 0, 15, 10, 20, 15, 22, 8, 13, 19, 4, 19, 6, 14, 1, 21, 3, 4, 7, 16, 5, 12, 9, 2, 4, 17, 22, 16, 18, 3, 19, 19, 21, 14, 22, 13, 19, 2, 18, 0, 4, 9, 12, 12, 3, 19, 5, 18, 9, 14, 9, 4, 21, 12, 18, 13, 17, 1, 5, 20, 5, 14, 7, 19, 16, 22, 12, 6, 2, 21, 10, 5, 12, 12, 19, 11, 0, 5, 0, 4, 4, 8, 22, 20, 18, 20, 17, 8, 14, 0, 3, 12, 9, 21, 17, 14, 15, 10, 13, 20, 15, 21, 10, 7, 2, 7, 13, 11, 1, 22, 9, 19, 14, 4, 0, 18, 9, 22, 10, 6, 11, 10, 21, 8, 1, 10, 13, 21, 0, 11, 6, 8, 14, 22, 6, 13, 11, 11, 18, 4, 3, 8, 10, 20, 16, 15, 16, 10, 14, 18, 7, 4, 16, 1, 6, 17, 4, 22, 19, 2, 9, 16, 0, 18, 15, 2, 9, 15, 5, 20, 20, 0, 22, 10, 2, 21, 22, 14, 11, 10, 19, 18, 10, 11, 14, 12, 5, 7, 16, 15, 5, 22, 12, 16, 13, 6, 11, 21, 18, 21, 15, 19, 7, 9, 2, 13, 2, 14, 6, 9, 2, 19, 2, 2, 0, 5, 19, 13, 12, 10, 11, 9, 6, 21, 17, 1, 16, 15, 9, 4, 5, 12, 11, 0, 21, 21, 12, 20, 11, 20, 7, 10, 4, 21, 20, 0, 17, 8, 14, 3, 17, 1, 7, 17, 16, 16, 3, 19, 18, 7, 13, 17, 2, 8, 2, 17, 4, 5, 7, 22, 2, 5, 8, 5, 8, 21, 15, 14, 17, 11, 16, 20, 8, 1, 5, 10, 8, 5, 7, 14, 5, 16, 6, 17, 8, 14, 4, 21, 5, 22, 6, 18, 22, 4, 16, 0, 0, 8, 22, 3, 9, 13, 21, 13, 5, 9, 5, 13, 17, 11, 19, 17, 15, 6, 5, 11, 12, 4, 2, 7, 13, 16, 3, 8, 0, 5, 20, 12, 11, 1, 15, 16, 0, 9, 7, 9, 16, 15, 21, 19, 19, 8, 3, 12, 14, 21, 18, 22, 5, 13, 12, 20, 11, 13, 11, 7, 16, 12, 7, 13, 15, 14, 22, 10, 17, 0, 11, 6, 20, 3, 2, 14, 13, 22, 21, 18, 20, 7, 18, 9, 5, 14, 22, 1, 9, 19, 3, 12, 20, 1, 15, 18, 6, 7, 16, 2, 20, 17, 2, 4, 11, 15, 19, 4, 14, 16, 19, 9, 2, 17, 1, 17, 5, 5, 10, 5, 20, 4, 22, 2, 8, 1, 12, 21, 22, 2, 4, 22, 5, 15, 18, 5, 4, 4, 22, 15, 20, 22, 19, 19, 8, 17, 16, 15, 1, 11, 12, 5, 0, 17, 14, 0, 10, 0, 12, 18, 16, 14, 4, 21, 16, 2, 11, 3, 6, 10, 12, 14, 1, 21, 10, 16, 3, 19, 11, 14, 19, 8, 4, 20, 9, 14, 6, 5, 16, 19, 21, 9, 7, 16, 19, 14, 19, 7, 17, 9, 11, 8, 2, 3, 21, 19, 14, 14, 0, 10, 8, 20, 13, 11, 18, 4, 1, 4, 9, 13, 21, 18, 12, 19, 11, 20, 16, 11, 6, 13, 15, 3, 22, 2, 5, 16, 11, 18, 3, 16, 6, 17, 9, 20, 9, 0, 14, 15, 13, 18, 22, 2, 14, 11, 4, 12, 18, 6, 16, 5, 4, 12, 5, 4, 22, 19, 4, 22, 2, 2, 16, 4, 16, 13, 4, 5, 15, 1, 3, 3, 14, 19, 20, 20, 3, 1, 7, 18, 6, 8, 6, 19, 4, 19, 4, 6, 2, 14, 13, 11, 2, 22, 19, 19, 13, 22, 12, 18, 19, 16, 11, 13, 6, 9, 0, 1, 9, 10, 22, 18, 0, 2, 22, 9, 8, 4, 20, 21, 9, 11, 9, 19, 21, 18, 17, 9, 0, 1, 2, 10, 6, 4, 16, 14, 8, 3, 1, 7, 3, 18, 16, 9, 14, 10, 4, 1, 14, 6, 7, 10, 18, 13, 13, 17, 16, 14, 14, 11, 9, 13, 6, 10, 0, 8, 14, 19, 6, 12, 10, 2, 9, 1, 22, 7, 11, 6, 5, 18, 9, 20, 8, 12, 10, 21, 12, 4, 22, 1, 19, 22, 7, 11, 18, 3, 16, 3, 19, 10, 14, 8, 10, 18, 6, 22, 5, 4, 21, 15, 13, 22, 19, 21, 6, 11, 9, 1, 11, 4, 1, 5, 0, 0, 16, 3, 11, 1, 10, 18, 2, 14, 12, 13, 17, 11, 3, 15, 10, 22, 13, 5, 19, 2, 2, 6, 17, 3, 11, 19, 17, 5, 4, 14, 18, 14, 0, 6, 17, 2, 13, 4, 1, 10, 17, 4, 19, 4, 3, 13, 19, 6, 19, 2, 17, 20, 10, 6, 15, 17, 4, 14, 19, 14, 6, 9, 16, 2, 13, 3, 9, 7, 8, 12, 16, 15, 12, 15, 1, 22, 16, 3, 21, 17, 18, 2, 6, 14, 16, 15, 20, 13, 19, 19, 4, 8, 10, 17, 8, 6, 19, 8, 8, 9, 22, 21, 13, 16, 16, 9, 20, 10, 12, 21, 4, 11, 6, 11, 18, 7, 6, 21, 21, 2, 20, 17, 12, 1, 2, 5, 2, 5, 9, 19, 9, 15, 4, 10, 10, 4, 22, 0, 9, 15, 0, 2, 14, 20, 21, 3, 0, 8, 13, 12, 21, 15, 21, 20, 9, 21, 0, 18, 0, 22, 15, 11, 11, 16, 21, 14, 19, 14, 22, 8, 1, 19, 2, 18, 4, 4, 9, 20, 11, 7, 20, 10, 4, 20, 20, 6, 20, 16, 22, 3, 4, 3, 18, 5, 7, 20, 3, 3, 4, 3, 6, 4, 15, 6, 1, 3, 9, 22, 13, 0, 5, 6, 15, 13, 3, 3, 21, 7, 3, 16, 0, 9, 1, 11, 22, 18, 12, 22, 6, 22, 6, 8, 14, 5, 14, 17, 19, 17, 21, 12, 8, 2, 11, 11, 17, 2, 11, 3, 21, 1, 7, 6, 11, 8, 17, 12, 0, 4, 10, 9, 9, 16, 13, 9, 22, 20, 1, 17, 6, 22, 17, 12, 2, 16, 11, 1, 6, 21, 14, 4, 16, 4, 0, 21, 4, 8, 20, 19, 15, 9, 2, 15, 2, 16, 7, 8, 11, 12, 19, 7, 19, 8, 11, 1, 11, 0, 13, 16, 12, 12, 3, 8, 7, 15, 5, 18, 4, 15, 18, 7, 12, 2, 2, 7, 7, 21, 1, 13, 19, 11, 5, 1, 15, 3, 9, 7, 2, 21, 7, 19, 3, 15, 1, 8, 18, 6, 16, 16, 0, 18, 3, 2, 11, 12, 7, 10, 21, 18, 18, 11, 12, 6, 20, 7, 1, 5, 18, 14, 8, 14, 21, 6, 15, 10, 14, 16, 5, 8, 6, 12, 22, 16, 11, 13, 1, 2, 19, 16, 7, 22, 14, 22, 10, 11, 16, 4, 14, 22, 16, 2, 12, 2, 8, 3, 1, 2, 13, 2, 17, 10, 15, 11, 15, 10, 10, 7, 4, 5, 15, 10, 18, 4, 13, 8, 6, 6, 20, 7, 0, 15, 20, 8, 18, 21, 5, 7, 16, 1, 16, 15, 5, 12, 20, 19, 22, 12, 14, 1, 11, 12, 5, 4, 20, 3, 12, 18, 21, 22, 10, 10, 16, 9, 5, 14, 22, 13, 21, 22, 2, 7, 8, 6, 3, 18, 18, 10, 15, 14, 15, 8, 5, 21, 3, 20, 0, 4, 6, 4, 2, 7, 17, 14, 1, 4, 13, 8, 4, 22, 19, 13, 20, 16, 21, 0, 2, 3, 2, 12, 19, 22, 15, 16, 19, 11, 9, 17, 8, 17, 6, 20, 4, 2, 7, 14, 7, 4, 5, 9, 17, 5, 1, 3, 14, 11, 16, 1, 7, 19, 12, 14, 0, 22, 13, 0, 17, 8, 13, 19, 11, 11, 0, 22, 19, 2, 0, 5, 9, 12, 14, 17, 22, 7, 4, 4, 15, 13, 20, 16, 16, 6, 3, 16, 4, 6, 11, 13, 9, 20, 6, 17, 10, 17, 22, 6, 9, 16, 0, 12, 11, 18, 10, 11, 0, 0, 15, 21, 7, 14, 22, 6, 6, 4, 13, 11, 6, 22, 8, 12, 19, 22, 10, 16, 14, 11, 5, 3, 9, 1, 8, 20, 14, 18, 4, 22, 7, 6, 13, 20, 12, 4, 1, 8, 4, 1, 16, 4, 22, 8, 20, 4, 11, 20, 16, 9, 12, 21, 1, 2, 3, 22, 6, 10, 16, 17, 6, 0, 7, 21, 0, 19, 14, 13, 11, 0, 6, 21, 12, 21, 4, 7, 22, 18, 6, 20, 5, 22, 20, 14, 13, 9, 14, 4, 2, 19, 6, 10, 14, 19, 22, 22, 18, 16, 1, 5, 16, 9, 18, 14, 4, 7, 5, 6, 4, 2, 3, 7, 4, 2, 11, 21, 14, 3, 1, 12, 14, 11, 1, 18, 13, 4, 7, 20, 8, 8, 13, 3, 14, 18, 9, 10, 1, 2, 1, 9, 6, 3, 5, 19, 0, 17, 18, 22, 8, 6, 10, 12, 11, 18, 16, 6, 20, 7, 7, 22, 8, 7, 16, 17, 14, 12, 12, 18, 13, 21, 2, 16, 2, 0, 16, 3, 21, 0, 21, 14, 3, 4, 13, 1, 8, 12, 20, 1, 1, 8, 3, 6, 18, 21, 3, 19, 18, 8, 3, 2, 21, 5, 9, 1, 18, 11, 19, 4, 12, 3, 5, 6, 3, 1, 20, 21, 18, 14, 12, 6, 14, 12, 18, 6, 22, 3, 5, 4, 22, 9, 9, 0, 7, 19, 1, 5, 8, 3, 20, 3, 14, 3, 19, 10, 10, 13, 17, 2, 14, 15, 7, 14, 1, 1, 20, 3, 22, 2, 22, 15, 5, 6, 13, 15, 22, 19, 2, 21, 1, 14, 19, 5, 18, 7, 14, 15, 17, 14, 11, 3, 13, 3, 10, 13, 7, 3, 11, 20, 0, 3, 8, 20, 5, 20, 14, 15, 1, 21, 11, 1, 9, 10, 14, 19, 13, 20, 5, 15, 7, 17, 5, 21, 0, 14, 13, 16, 15, 11, 13, 18, 1, 6, 13, 5, 7, 15, 16, 1, 0, 4, 10, 0, 9, 9, 5, 13, 6, 22, 1, 2, 17, 13, 17, 16, 9, 15, 1, 16, 10, 8, 3, 18, 19, 18, 4, 19, 7, 1, 12, 9, 16, 15, 9, 2, 0, 20, 6, 6, 14, 22, 4, 2, 17, 15, 13, 22, 17, 11, 5, 2, 13, 14, 22, 0, 6, 16, 15, 17, 22, 2, 9, 16, 12, 19, 15, 12, 1, 9, 0, 14, 13, 10, 16, 14, 10, 22, 1, 11, 15, 10, 9, 19, 13, 15, 13, 22, 11, 15, 11, 9, 3, 6, 18, 20, 13, 20, 1, 15, 22, 18, 18, 7, 18, 16, 22, 12, 4, 18, 9, 11, 6, 1, 14, 19, 19, 0, 22, 5, 18, 3, 5, 10, 13, 15, 2, 4, 6, 2, 14, 11, 21, 5, 0, 11, 14, 0, 19, 14, 1, 20, 4, 12, 1, 9, 5, 12, 15, 12, 3, 1, 2, 14, 22, 18, 20, 5, 1, 6, 0, 5, 14, 12, 3, 0, 10, 22, 6, 4, 4, 22, 20, 9, 8, 14, 0, 2, 6, 14, 13, 0, 15, 18, 10, 17, 8, 20, 21, 17, 3, 6, 2, 13, 4, 0, 15, 4, 22, 19, 20, 4, 3, 3, 4, 8, 5, 3, 10, 6, 8, 7, 9, 18, 4, 12, 9, 9, 3, 15, 21, 2, 6, 4, 7, 12, 1, 15, 0, 18, 6, 5, 10, 11, 12, 15, 15, 2, 12, 4, 11, 15, 3, 19, 22, 19, 22, 9, 10, 15, 17, 8, 17, 0, 15, 15, 18, 12, 0, 1, 4, 10, 6, 21, 16, 5, 0, 20, 21, 21, 4, 22, 7, 10, 17, 13, 10, 7, 7, 21, 13, 5, 3, 20, 5, 14, 5, 9, 9, 6, 3, 21, 6, 7, 15, 10, 1, 4, 15, 7, 16, 3, 13, 14, 4, 21, 6, 14, 11, 18, 5, 8, 13, 20, 10, 10, 13, 17, 7, 0, 9, 21, 1, 3, 4, 16, 16, 20, 5, 3, 5, 14, 22, 1, 20, 21, 11, 16, 13, 10, 21, 8, 8, 16, 12, 12, 8, 12, 9, 6, 20, 15, 15, 12, 1, 15, 7, 11, 22, 4, 2, 7, 2, 3, 0, 8, 7, 10, 16, 16, 22, 10, 21, 3, 13, 0, 10, 7, 17, 21, 0, 22, 4, 15, 6, 10, 14, 0, 7, 0, 22, 16, 11, 2, 19, 15, 5, 2, 11, 13, 3, 14, 9, 19, 19, 21, 8, 19, 1, 21, 7, 17, 12, 18, 17, 7, 5, 13, 6, 13, 5, 21, 14, 8, 4, 13, 21, 14, 0, 4, 15, 4, 7, 0, 11, 11, 0, 17, 1, 4, 4, 18, 21, 19, 15, 21, 11, 2, 6, 18, 10, 10, 21, 11, 19, 13, 7, 2, 3, 12, 7, 16, 16, 16, 16, 17, 22, 20, 20, 10, 13, 16, 19, 6, 1, 18, 19, 12, 3, 11, 7, 17, 16, 7, 17, 1, 15, 18, 16, 11, 19, 1, 16, 3, 16, 9, 11, 18, 1, 20, 1, 20, 8, 13, 11, 3, 15, 13, 15, 21, 13, 22, 22, 2, 6, 7, 21, 12, 6, 8, 18, 21, 11, 1, 0, 15, 21, 11, 15, 19, 20, 4, 0, 7, 4, 18, 5, 4, 17, 11, 1, 17, 4, 12, 11, 22, 5, 5, 21, 14, 17, 7, 12, 7, 17, 18, 17, 8, 3, 20, 3, 5, 1, 5, 3, 19, 6, 18, 20, 13, 17, 19, 3, 19, 17, 3, 20, 10, 20, 3, 8, 16, 7, 8, 3, 22, 18, 12, 21, 10, 19, 12, 12, 16, 12, 0, 5, 12, 8, 19, 20, 2, 5, 21, 18, 19, 1, 1, 20, 22, 20, 8, 11, 15, 17, 13, 20, 9, 16, 21, 4, 12, 2, 1, 5, 4, 4, 17, 19, 0, 19, 9, 14, 12, 21, 16, 16, 8, 6, 10, 12, 0, 13, 12, 22, 11, 1, 17, 6, 12, 19, 3, 13, 8, 13, 16, 6, 2, 6, 18, 9, 18, 17, 11, 20, 15, 2, 15, 22, 17, 17, 11, 22, 1, 8, 12, 13, 10, 3, 5, 12, 21, 14, 10, 17, 19, 17, 15, 11, 20, 20, 21, 19, 14, 6, 8, 17, 1, 18, 13, 22, 11, 3, 1, 21, 6, 10, 22, 7, 5, 0, 3, 12, 14, 8, 3, 4, 9, 9, 21, 11, 10, 9, 11, 9, 4, 19, 7, 10, 22, 13, 2, 2, 22, 19, 9, 16, 21, 1, 9, 13, 16, 11, 22, 17, 11, 12, 22, 0, 13, 6, 8, 1, 0, 0, 4, 18, 3, 1, 12, 5, 5, 3, 9, 6, 6, 17, 9, 4, 19, 14, 0, 9, 1, 19, 8, 0, 14, 18, 18, 9, 16, 15, 10, 10, 11, 12, 17, 19, 11, 15, 0, 10, 22, 5, 21, 21, 2, 20, 15, 5, 1, 7, 7, 6, 15, 12, 6, 13, 20, 4, 21, 10, 15, 1, 13, 13, 9, 21, 18, 0, 5, 9, 20, 21, 7, 22, 2, 4, 10, 10, 0, 11, 4, 3, 15, 12, 20, 9, 9, 11, 15, 15, 21, 18, 1, 4, 11, 10, 0, 6, 18, 6, 11, 20, 3, 11, 11, 13, 16, 9, 1, 1, 10, 6, 20, 14, 2, 7, 4, 18, 9, 12, 16, 22, 20, 9, 19, 2, 8, 3, 4, 15, 18, 3, 14, 7, 15, 1, 15, 8, 19, 5, 8, 2, 22, 19, 13, 18, 0, 19, 12, 17, 21, 22, 19, 6, 12, 2, 2, 20, 18, 21, 18, 18, 7, 19, 16, 11, 1, 21, 10, 5, 12, 15, 18, 17, 10, 0, 20, 20, 19, 6, 6, 15, 8, 5, 21, 11, 0, 6, 10, 13, 8, 20, 7, 2, 11, 11, 3, 14, 11, 9, 8, 15, 0, 3, 22, 0, 12, 6, 0, 12, 21, 11, 8, 7, 5, 0, 6, 4, 15, 18, 9, 21, 5, 4, 20, 14, 5, 9, 19, 3, 11, 12, 22, 7, 18, 21, 9, 17, 3, 2, 11, 15, 6, 19, 2, 3, 8, 10, 7, 6, 8, 13, 2, 2, 9, 20, 3, 7, 5, 13, 13, 9, 0, 18, 21, 1, 22, 6, 7, 18, 5, 14, 14, 19, 0, 6, 4, 3, 19, 20, 22, 20, 7, 22, 22, 2, 11, 16, 16, 20, 17, 13, 20, 1, 21, 17, 22, 3, 4, 6, 7, 9, 11, 21, 17, 13, 21, 8, 18, 22, 4, 19, 8, 7, 11, 13, 1, 10, 14, 18, 17, 14, 15, 22, 3, 14, 20, 15, 3, 22, 15, 22, 12, 12, 18, 14, 16, 14, 21, 17, 1, 16, 12, 8, 2, 3, 6, 4, 9, 7, 5, 3, 15, 21, 14, 0, 20, 9, 7, 19, 10, 4, 5, 11, 8, 19, 0, 22, 7, 3, 22, 8, 12, 5, 22, 4, 15, 11, 2, 4, 13, 2, 4, 9, 7, 5, 17, 14, 19, 7, 14, 4, 8, 17, 18, ], 23, &[ 2432543987, 2276527024, 3303037865, 3040931222, 124530589, 2075117878, 373679459, 1719887982, 927313221, 2350422398, 2410320624, 2621140451, 898468917, 1050104246, 3314171259, 2202176491, 3934792658, 1945547354, 752254890, 68461992, 1501238000, 1916284043, 2385775512, 1516051704, 1572036976, 177218342, 4078653370, 3944978370, 3993325163, 35949890, 28445911, 2989181316, 3711931852, 3969713797, 853651131, 1048673303, 164841509, 2591275506, 2676954415, 910103144, 2881135462, 1328960554, 3814928621, 1570089463, 3936037561, 3706141104, 3622208665, 1736839730, 818356637, 903565935, 3997690004, 2013074628, 245593157, 2604723513, 2614342663, 1992293635, 1023889602, 2910391935, 1146365901, 3356081083, 3777393537, 2858374037, 2863919743, 1056257782, 809068644, 672989257, 3747695201, 2522210474, 525888082, 1848521587, 2468974825, 653259135, 1975306186, 2456732937, 1299155795, 1794805560, 569248853, 102439111, 256768309, 4037408132, 77496396, 1983342746, 2296048037, 3348374173, 1213807447, 1373478223, 2235179986, 1490259265, 2112796854, 2547714374, 869600236, 2852487281, 2064710386, 447426889, 767950649, 3612583010, 1780520436, 3627700369, 3905832623, 412784141, 2186300632, 1687791207, 3268878142, 2439345575, 544593515, 2488911021, 1860939518, 3160552347, 3520538477, 2254621553, 3817356405, 1093773391, 104168916, 2026826706, 3008411949, 731612881, 400526524, 1319326349, 994927338, 1642377367, 89069495, 4052976262, 407108435, 1706274710, 3618323759, 2999112327, 3472562229, 594407960, 4257849311, 1499146458, 3343189692, 3332254596, 3845543202, 3993385369, 1501681435, 608654406, 2482649339, 3990535200, 1449270641, 4016403422, 342445879, 4228145020, 4030280967, 891466632, 1454359846, 1886612732, 3712575231, 3934358913, 1100305416, 1249102960, 2133206589, 3528060174, 1115362965, 871488833, 2959657656, 1791653312, 1587540254, 1527651781, 2515721439, 2549398069, 1442586984, 3746591659, 1219966156, 1140399539, 3198235519, 2830212264, 3671456437, 2604181784, 2742431758, 3688451693, 1352937420, 2958171794, 3484353914, 1323974235, 635848732, 3435591916, 1147399220, 3055499602, 3459025755, 1441809200, 3288677176, 1356946570, 2922613843, 3435973582, 3169578850, 2010271922, 2926310610, 4220927069, 3147037801, 3177585452, 3767093688, 3797368144, 2993412434, 52467448, 2638704998, 500593776, 435767039, 75611890, 173252622, 369536399, 3001199800, 1696483020, 403435509, 2676770836, 135469730, 4294502870, 3467161889, 487127268, 144987877, 3830430272, 4176107046, 547748139, 2535372546, 3407597209, 4273742947, 3591467776, 869590956, 1405915818, 3698534773, 260295134, 4044017583, 4035779488, 463440960, 4200854080, 657217412, 3110364826, 2029115239, 2200955452, 779832230, 1588101134, 1711375700, 3878103627, 1709250626, 2858094475, 509701948, 717581521, 3068900665, 1481026334, 1218138746, 4054497212, 3753193645, 2200558797, 2971038189, 3966112697, 558197857, 2787894924, 744571221, 1568885442, 2788507093, 1552043446, 172898599, 1046802271, 845471067, 3408324900, 3882264867, 1306206395, 1165216268, 1191839803, 1527610198, 4188064533, 3649876341, 2133981933, 1122433329, 166725368, 2113942545, 262674194, 2983616752, 3664915710, 2528883697, 72691628, 1094952676, 3781397836, 2543857595, 1262396255, 1541616154, 695881242, 4267754168, 2929769840, 1150669979, 2444044368, 2085087061, 1011358281, 414070849, 1990902057, 2504781194, 762251676, 2992215331, 321648205, 749759701, 2683064829, 371937346, 1916620629, 3504232544, 2210693036, 1759776303, 1252482988, 2327728963, 855162264, 1839954590, 1657033791, 790197996, 232471839, 2461249283, 117939746, 560149963, 1044762152, 1013702332, 932681941, 1205754842, 1751214724, 860371808, 3898533721, 39404571, 1091417891, 593738330, 3258375503, 4277934029, 688697039, 4083389785, 1292128636, 1251798962, 235181476, 3030160145, 2367582304, 2609657981, 3483636249, 2810692598, 1851185576, 2778801808, 1690833980, 4279865527, 2021420402, 1898436492, 2626314401, 3873432257, 1672600024, 2803701169, 66336423, 1619175812, 1947174922, 427990001, 2831016152, 3944679881, 1055966210, 1089542534, 2005082069, 1971269850, 1924433077, 4217952611, 2749232796, 1481402693, 3203808543, 3753215487, 1988955035, 4002936550, 1944840595, 2089249464, 226215659, 1145745745, 2617193917, 2071905246, 2716825521, 756996862, 803384898, 2498333605, 3766458014, 2625315151, 1231183373, 3407435990, 2004334218, 136726326, 3694458272, 439206563, 1697431856, 109034171, 3129361133, 2148702911, 1603279218, 665749557, 2453579770, 1778010870, 3980259964, 3820850075, 423551518, 4244040519, 771818147, 2473197470, 2184490663, 66706499, 373610607, 2507344693, 1182035514, 2294279416, 348192110, 2147447089, 1429312800, 3521861641, 2941695755, 2373618812, 3122839309, 3164597812, 4174895272, 3446714428, 4179964099, 3369606920, 3245057821, 512812868, 3801957629, 3866197478, 1983232922, 1164421658, 3492043893, 4102973269, 3482785988, 3613848786, 994234819, 3925964490, 2520653440, 306189184, 3378720004, 325986226, 663667879, 2399249015, 716637187, 2390212162, 3760061962, 582012888, 3300637312, 3552019520, 2310968716, 1848698860, 2484373755, 729280744, 833802096, 3737502652, 3910738649, 2057433799, 2248378565, 268720583, 3069947043, 3763100719, 3510420884, 1101435572, 462921272, 3929831289, 348032532, 3764507470, 3983733230, 2585114124, 2116017165, 3240263985, 1205053072, 1665443971, 2423786772, 1138900192, 2363229724, 1887946492, 3218510326, 3268927353, 1385744919, 2498515502, 1516552001, 3939009406, 3701533621, 913382028, 3344976363, 3384856500, 3870149157, 1329228053, 1291707300, 3899335066, 3940597462, 3153019193, 2408594961, 2671044621, 3551857958, 2209058090, 3493940212, 222503531, 2114494914, 565799347, 1971473416, 4277831935, 2358519001, 490963986, 3852565277, 984935336, 1133370208, 1617043634, 2857541004, 832503739, 108040238, 3880146835, 2807229258, 3575769310, 2774854680, 868093555, 2575005082, 2956555327, 3737955779, 4249638030, 1940414434, 3753480496, 49729337, 1193299683, 3201089034, 420648789, 3352785498, 288688721, 1521187011, 1386674633, 1364869610, 885037528, 1252279155, 3649552262, 2152649024, 3204905942, 1783619473, 2861412105, 3540375905, 3746939744, 156102264, 3466170698, 11866214, 1012760070, 1958489233, 3665112630, 3509540297, 2512443114, 2128112533, 1628693203, 2042312955, 1656593755, 2564164318, 3270705760, 1680356097, 5025885, 2796521567, 2263503167, 2420040603, 3394606541, 214460118, 992057652, 3266983797, 2159688810, 1993456089, 4175543350, 3963528935, 2513264991, 3658064350, 156097811, 2826997767, 865018090, 1321677484, 2168436280, 1124406880, 3231042910, 1275491774, 9015246, 3130741698, 2078413139, 1824585545, 1955698270, 1768370940, 613758713, 3783594115, 2662841648, 3623245683, 3253698278, 4191335005, 3430738147, 3732087559, 237862677, 3240225475, 2509625707, 3371804946, 561137032, 2487087488, 566174513, 55477126, 1492417125, 3600485779, 3489229753, 1660001711, 903932105, 2666760808, 3267530948, 1804351992, 2931928329, 1701287766, 847625244, 2066564451, 2319056965, 2848820614, 854672647, 535121151, 2288435608, 2524958641, 3296694570, 1364335301, 709714126, 2360287547, 4106461964, 329631027, 849263407, 2311850705, 1653642573, 2959033037, 3845765450, 2411305922, 1012439121, 974968898, 3631461599, 777873009, 920353902, 725744567, 1725097098, 333882177, 3584334013, 3078291222, 3960551469, 2531623496, 1211920485, 2390442828, 2791068256, 1910957250, 1632728636, 3797597081, 3611429309, 1566721977, 2509740862, 4176296323, 590851749, 3457912421, 2303299273, 2528501850, 889922996, 536952148, 2891183341, 3609423256, 2878185261, 3218672709, 956031557, 1687988839, 920703413, 4209253359, 1815357979, 3709650040, 1017145721, 1810276897, 1020365743, 2313969064, 1539434460, 4255594610, 1458431491, 680535340, 1647259761, 1004107429, 2415667132, 31092371, 935775706, 396967039, 27911921, 2657305445, 2248738175, 2497727679, 1483667419, 1951176417, 2145607203, 3224667691, 2438573057, 2942868990, 2027000102, 2913871289, 3685393236, 2425696100, 782260165, 483022313, 3940181670, 3798075211, 1219099101, 203528657, 529875562, 276233372, 264759552, 51482773, 4105461152, 708360569, 559014934, 735004662, 2304945262, 2287817402, 1399360640, 4034225857, 1458299505, 1242064138, 3475741745, 2971620406, 2364951756, 1272349036, 2302805830, 298664638, 3662585622, 2397537734, 3026808232, 1114868390, 673264043, 3318150460, 1138305753, 3797784655, 2881309047, 174048567, 3800745317, 3055674757, 2607943906, 944193168, 2003534871, 1434769036, 458792317, 2282245931, 636767187, 1532218286, 724269210, 2874117375, 1439654243, 698007041, 2836800209, 1025277967, 1527769433, 2515862986, 1373613061, 287099492, 2691879042, 2428315581, 2367162320, 1217630768, 952926109, 3408276082, 3496973185, 3089422616, 1048409122, 707017659, 2780132225, 2844071654, 1836018831, 3441433162, 624841709, 3116228289, 1956737587, 3778477996, 336613926, 2937889239, 384836527, 1341826476, 3712358886, 2306774444, 1341535315, 1777669116, 1199737655, 266426998, 2697021776, 2817808455, 2023340729, 3851312363, 3980251913, 3207784360, 333886678, 689050764, 331336434, 3431528012, 654836012, 3282279155, 249795473, 4101667665, 994019464, 1551695192, 919619198, 2822963861, 1058136685, 347412103, 8043636, 548175678, 160303852, 4191967974, 114867036, 2223903475, 3083148884, 2624932033, 2791621092, 2277501601, 2800576686, 1130603172, 566089914, 1444023227, 1500498349, 150928386, 2908319814, 2257652416, 1193412204, 3157603623, 4288978904, 2684571944, 2504105716, 3900496848, 344319926, 2148470734, 3941199614, 801816176, 2970106595, 2551130561, 1139061079, 1765357801, 2801395705, 1452414774, 1670219825, 2423177094, 321332024, 2032854264, 2554376386, 537964156, 1300131358, 2011623640, 4208848750, 2877603209, 896201049, 954025445, 1801424491, 3220899647, 3629652945, 1882282457, 1857761982, 2758423637, 787777871, 225484364, 713108959, 2092789353, 2948984687, 269006096, 76419691, 569618318, 1650706474, 4007329961, 270502651, 708871540, 4193563743, 2210670738, 2545734314, 2838989169, 2119352897, 3507676809, 192990507, 447022484, 1538552337, 3536011095, 1971356807, 1997639220, 4240677277, 2042803185, 747190487, 690822786, 3425774253, 1970444075, 1519418519, 2502800132, 456092197, 3089519109, 2494760604, 1753613710, 3680543205, 1225101795, 2697514748, 2933361013, 4175549155, 2216849000, 3929431645, 4230737093, 2641643251, 4199674746, 1962717842, 3676951090, 2505693179, 850730013, 3866789620, 152159307, 2179605002, 687124397, 2450265390, 445267719, 1990658425, 2317584166, 1464123246, 2333847393, 3958580546, 589512689, 1683476060, 528323569, 4040487824, 1531042664, 2122382129, 3943959015, 3860235235, 1153301333, 566968208, 2417583538, 1103445908, 1261825307, 2550203026, 1658486984, 3038335860, 1841338780, 3360364021, 2660553389, 2924187195, 4241529036, 2271736721, 3765073952, 2580215584, 1438318228, 2787276148, 454821732, 355379320, 2482867526, 1411322874, 4211251252, 1898863052, 471267359, 3485276742, 1285961552, 3923197508, 3768783839, 4025502468, 18284057, 2673735163, 2221768523, 681186346, 88325179, 2889050541, 1256119319, 1858502698, 2398900641, 976659823, 2961773032, 3868539432, 2535077451, 1763974232, 2135036948, 1399244834, 1152496492, 2401894286, 1267776170, 2133978424, 3666460581, 2519353074, 2831901651, 3888910459, 1900327248, 1654981227, 1101450299, 3445846720, 3449825460, 3791261482, 432004847, 3066863554, 2698800432, 1641108, 707956864, 1870786679, 3055496006, 3728988665, 398291770, 2212074450, 2155438841, 3431922058, 3971811313, 1719261068, 1735009605, 4213793259, 58186599, 3855304568, 3067682717, 228831702, 3278881736, 4153465006, 1952694150, 3651972132, 3534641986, 1121445172, 169071915, 4212735773, 3505561766, 1395317315, 736925405, 3125143948, 3297296490, 3127331986, 3616368376, 2056503535, 788835758, 788439625, 1630085743, 2747839891, 2343131865, 1081156327, 3120208131, 394640347, 3903778496, 4252716449, 2283235409, 483957986, 83131712, 518164125, 3367314863, 3912497177, 1979817847, 2541067002, 3406633266, 2525836540, 2905407837, 927633307, 357014464, 1712382708, 2975844776, 3790058589, 1514112964, 366170767, 328664775, 4185303074, 1820638444, 2924908138, 2047784738, 1987583135, 2372860973, 3609968385, 3143257714, 3427362641, 3072122247, 1141840336, 2310485042, 368865492, 4065735384, 3981077989, 2624946734, 3489009884, 2263206997, 2463456412, 2712152858, 1734251492, 2655931795, 3696764806, 3404614825, 4011135114, 1018397103, 572166022, 2062711851, 2569156569, 3460399925, 1702645790, 1098604909, 2069896475, 3646476155, 820160451, 147337310, 1765191975, 60191201, 626121624, 2726686045, 2538949724, 187866767, 2388425781, 935215588, 871611286, 3906412946, 1246311689, 3306250646, 4170514946, 2323420983, 2057780630, 628784453, 1410213509, 372936645, 501063446, 175500703, 258466122, 62857995, 3386238628, 2083632783, 2605300978, 1118667897, 1446000958, 79053812, 3654798093, 1881412132, 4168572524, 1027075259, 1028158997, 1654169038, 2157952826, 2032022698, 1151156532, 1065611895, 3911407574, 2900828134, 1637425467, 2817709633, 1736551320, 3741593941, 3202948790, 1599337068, 3398371980, 2224875086, 1229925548, 1303814094, 3574632434, 3493928291, 884975947, 1246641330, 2088204280, 2837698631, 1824887371, 1450894602, 266444701, 3075497931, 3834303497, 3027392031, 2531258637, 2642373781, 1193002026, 1767288754, 1311625744, 1001761926, 3062663859, 52529591, 3745995278, 438887272, 700662189, 4212368956, 2107562915, 319883829, 215035253, 1488253283, 1301013358, 433922795, 1753607220, 794705122, 1689562210, 3154133389, 2179734736, 2971286634, 2392964366, 2792619323, 1432651454, 3418370805, 3131519322, 3349726128, 2474689584, 466365332, 811867264, 3052861325, 4097469989, 93032001, 3926176274, 2350247983, 1674779175, 291602062, 2846268401, 3277208194, 1497830566, 3625189672, 9072038, 2951339513, 1792718546, 1776258935, 1029608682, 1412608523, 3989131994, 3101063512, 1207282153, 2951261525, 3563115848, 1682346995, 4283726597, 3927997318, 4070406195, 3269446148, 2053006428, 3883337744, 2238918050, 3463951652, 3364024419, 2879606446, 2715677768, 3398302025, 1565164133, 3468031718, 3995385067, 2354095405, 70728059, 1501387287, 531457926, 4071000954, 2691373653, 130456474, 162613531, 3278227001, 1871081118, 2108414937, 1956838987, 3201051305, 1099789655, 2688103265, 3376545054, 4194764973, 3048141369, 92313010, 2714344608, 2836237280, 2306143043, 157665707, 4202292074, 1667642970, 2709322690, 33398946, 1993933511, 876610905, 4199861858, 4070029492, 4112921551, 4157395415, 1744841967, 375479353, 782950108, 3732824359, 3468562129, 1534389810, 3406467972, 231940487, 27701910, 379953968, 1660493409, 409076658, 839620823, 2991390226, 3717064548, 2195983177, 1378317571, 2131651037, 264521891, 107725272, 2543867771, 1340163093, 1806455525, 1349163961, 2698063614, 1300591146, 2489572412, 1792603038, 8170771, 1532472015, 4089778540, 1087892505, 4011589612, 2513998273, 2753333194, 2374394, 3072400605, 2057302330, 206942689, 930325233, 1494197348, 2396885015, 3519563996, 1389464877, 212652146, 3546128890, 1601747989, 676352508, 2556438908, 3274662607, 595702540, 3961163985, 214798108, 158276567, 2000671252, 1909961436, 3608100180, 1725922971, 1921296001, 3248181224, 2681071530, 4234758481, 3214059028, 1675447675, 2089523164, 470493498, 340308561, 4095769841, 3045163996, 1700180965, 1833518916, 3218401197, 3764107983, 760622304, 2715854634, 2566771885, 2855925414, 2596118107, 2718892126, 2919661660, 1777435166, 704222621, 4188226574, 1287796296, 32153441, 2088095808, 2504036947, 481481625, 1981638127, 2659395414, 4019699467, 3022239223, 1432279555, 3716343314, 2101658277, 2538588325, 2228739909, 325848107, 3728753696, 226572131, 70936434, 2326533081, 4197100817, 2130486321, 3647628851, 2365959588, 146012, ], ); // - out_len_hi == 0 in limbs_from_digits_small_base_divide_and_conquer // - out_len_lo == 0 in limbs_from_digits_small_base_divide_and_conquer test(&[10; 739], &[0; 7100], 10, &[0; 369]); } #[cfg(not(feature = "32_bit_limbs"))] { test( &[ 424216987022722268, 8103283177193628673, 4470414499436387861, 13801449255692046935, 9547961461378503966, 5606458381418993750, 17091516772434375724, 11977748006393229058, 6812658461074707191, 12015828441561040006, ], &[ 51, 153, 87, 70, 104, 138, 111, 23, 85, 119, 176, 8, 65, 118, 3, 156, 55, 121, 87, 162, ], 182, &[4980635571795936200, 9374876857207216767, 1331096], ); test( &[ 5518555633093191759, 12836059490899113620, 12661099089298342811, 1992484047621263128, 3777109748949388481, 4126346840817077875, 7608898082196224717, 6664909716221346590, 679023819841892642, ], &[41, 16, 48, 34, 6, 51, 35, 56, 47, 44, 44, 20, 51, 39, 36, 33, 4, 14, 25, 3], 61, &[16759895520031570107, 18665423842034105], ); // - xs_len <= len_lo in limbs_from_digits_small_base_divide_and_conquer // - xs_len >= SET_STR_DC_THRESHOLD in limbs_from_digits_small_base_divide_and_conquer test( &[10; 10], &[ 2, 3, 0, 1, 0, 1, 0, 2, 0, 0, 1, 2, 3, 2, 0, 0, 3, 0, 3, 1, 3, 2, 4, 4, 2, 1, 0, 1, 1, 3, 1, 2, 2, 4, 1, 4, 1, 0, 2, 3, 1, 1, 4, 4, 0, 3, 3, 3, 0, 0, 0, 3, 1, 0, 1, 1, 3, 1, 1, 0, 3, 3, 2, 4, 4, 4, 3, 4, 2, 0, 1, 1, 3, 4, 4, 3, 0, 4, 3, 0, 2, 2, 3, 4, 3, 0, 4, 2, 2, 0, 3, 4, 0, 1, 0, 4, 3, 1, 1, 2, 1, 2, 0, 1, 3, 0, 2, 2, 1, 1, 2, 2, 2, 0, 4, 3, 3, 3, 1, 2, 2, 2, 2, 0, 1, 0, 2, 4, 4, 4, 1, 3, 2, 2, 0, 1, 3, 1, 1, 4, 1, 3, 4, 2, 3, 0, 1, 2, 2, 0, 0, 4, 1, 1, 1, 3, 1, 3, 0, 2, 0, 2, 0, 2, 1, 1, 2, 4, 0, 3, 2, 3, 0, 4, 3, 1, 2, 4, 4, 1, 3, 3, 3, 4, 2, 0, 3, 0, 3, 4, 3, 1, 4, 3, 3, 2, 2, 1, 1, 1, 0, 3, 2, 0, 4, 1, 1, 1, 0, 3, 0, 3, 4, 4, 4, 4, 4, 0, 4, 2, 1, 4, 4, ], 5, &[ 277482782106898878, 8398439881293320527, 6237275848328729287, 17623578066584208310, 2887235280090375858, 8886426738771697150, 6137418971026265383, 15927966713276205188, 28, ], ); } } fn limbs_from_digits_small_base_properties_helper() where Limb: WrappingFrom, Natural: From, { let mut config = GenConfig::new(); config.insert("mean_stripe_n", 4 << Limb::LOG_WIDTH); config.insert("mean_digit_count_n", 2048); config.insert("mean_excess_limb_count_n", 32); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_3::().test_properties_with_config( &config, |(mut out, xs, base)| { let t_base = T::exact_from(base); assert_eq!( limbs_from_digits_small_base(&mut out, &xs, base).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_2::().test_properties_with_config( &config, |(mut out, xs, base)| { let old_out = out.clone(); let out_len = limbs_from_digits_small_base(&mut out, &xs, base).unwrap(); verify_limbs_from_digits_small_base(&old_out, &xs, base, out_len, &out, false); }, ); } #[test] fn limbs_from_digits_small_base_properties() { apply_fn_to_unsigneds!(limbs_from_digits_small_base_properties_helper); } #[test] fn test_from_digits_desc_basecase() { fn test_ok(xs: &[u8], base: Limb, n: &str) { let n = Natural::from_str(n).unwrap(); assert_eq!(from_digits_desc_basecase(xs, base).unwrap(), n); assert_eq!( from_digits_desc_naive_primitive(xs, u8::exact_from(base)).unwrap(), n ); } test_ok(&[0], 9, "0"); test_ok(&[1], 9, "1"); test_ok(&[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); test_ok(&[0, 0, 2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); test_ok( &[ 73, 23, 120, 45, 108, 147, 113, 90, 129, 11, 86, 0, 102, 81, 22, 17, 32, 121, 29, 82, 27, 25, 39, 9, 139, 59, 51, 13, 44, 3, 37, 104, 41, 40, 87, 66, 83, 146, 40, 132, 15, 50, 66, 80, 73, 61, 75, 25, 78, 34, 128, 86, 68, 26, 62, 135, 21, 9, 27, 74, 12, 39, 67, 15, 41, 50, 144, 35, 98, 140, 124, 132, 10, 37, 101, 99, 14, ], 150, "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); fn test_err(xs: &[u8], base: Limb) { assert!(from_digits_desc_basecase(xs, base).is_none()); assert!(from_digits_desc_naive_primitive(xs, u8::exact_from(base)).is_none()); } test_err(&[10, 11, 12], 10); } fn from_digits_desc_basecase_fail_helper + PrimitiveUnsigned>() where Limb: WrappingFrom, { assert_panic!(from_digits_desc_basecase::(&[], 0)); assert_panic!(from_digits_desc_basecase::(&[], 1)); } #[test] fn from_digits_desc_basecase_fail() { apply_fn_to_unsigneds!(from_digits_desc_basecase_fail_helper); } fn from_digits_desc_basecase_properties_helper + PrimitiveUnsigned>() where Limb: SaturatingFrom + WrappingFrom, Natural: From, { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); config.insert("mean_length_n", 32); unsigned_vec_unsigned_pair_gen_var_12::().test_properties_with_config( &config, |(xs, base)| { let t_base = T::exact_from(base); assert_eq!( from_digits_desc_basecase(&xs, base).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_5::().test_properties_with_config( &config, |(xs, base)| { let n = from_digits_desc_basecase(&xs, base); assert_eq!( from_digits_desc_naive_primitive(&xs, T::exact_from(base)), n ); }, ); } #[test] fn from_digits_desc_basecase_properties() { apply_fn_to_unsigneds!(from_digits_desc_basecase_properties_helper); } #[test] fn test_from_digits_asc_limb() { fn test_ok(xs: &[u32], base: Limb, n: &str) { let n = Natural::from_str(n).unwrap(); assert_eq!(from_digits_asc_limb(xs.iter().copied(), base).unwrap(), n); assert_eq!( from_digits_desc_naive_primitive( &xs.iter().copied().rev().collect_vec(), u32::exact_from(base) ) .unwrap(), n ); } test_ok(&[], 9, "0"); test_ok(&[0], 9, "0"); test_ok(&[1], 9, "1"); test_ok(&[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2], 3, "123456"); test_ok(&[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2, 0, 0], 3, "123456"); test_ok(&[2, 4, 6, 4, 2], 8, "10658"); test_ok(&[789, 456, 123], 1000, "123456789"); test_ok( &[ 14, 99, 101, 37, 10, 132, 124, 140, 98, 35, 144, 50, 41, 15, 67, 39, 12, 74, 27, 9, 21, 135, 62, 26, 68, 86, 128, 34, 78, 25, 75, 61, 73, 80, 66, 50, 15, 132, 40, 146, 83, 66, 87, 40, 41, 104, 37, 3, 44, 13, 51, 59, 139, 9, 39, 25, 27, 82, 29, 121, 32, 17, 22, 81, 102, 0, 86, 11, 129, 90, 113, 147, 108, 45, 120, 23, 73, ], 150, "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); test_ok( &[302, 2359, 150, 1581, 2859, 1843, 2403, 2039, 27, 1598], 3543, "140578615308984594421852296827289425", ); test_ok( &[1187762660, 83185796, 570510527, 293681571, 1518538399, 1153431348], 1525385058, "9525530906278526930121302445905223566866929778026945776", ); test_ok( &[ 1535724679, 31832127, 1494323667, 798341655, 1169948427, 1204675417, 1214721934, 1599722999, 1842176041, 1659733906, 824969631, 1046252719, ], 1895460450, "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); fn test_err(xs: &[u32], base: Limb) { assert!(from_digits_asc_limb(xs.iter().copied(), base).is_none()); assert!( from_digits_desc_naive_primitive( &xs.iter().copied().rev().collect_vec(), u32::exact_from(base) ) .is_none() ); } test_err(&[12, 11, 10], 10); } fn from_digits_asc_limb_fail_helper + PrimitiveUnsigned>() where Limb: TryFrom + WrappingFrom, Natural: From + PowerOf2Digits, { assert_panic!(from_digits_asc_limb::<_, T>(empty(), 0)); assert_panic!(from_digits_asc_limb::<_, T>(empty(), 1)); } #[test] fn from_digits_asc_limb_fail() { apply_fn_to_unsigneds!(from_digits_asc_limb_fail_helper); } fn from_digits_asc_limb_properties_helper + PrimitiveUnsigned>() where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_12::().test_properties_with_config( &config, |(xs, base)| { let t_base = T::exact_from(base); assert_eq!( from_digits_asc_limb(xs.iter().copied(), base).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_5::().test_properties_with_config( &config, |(xs, base)| { let n = from_digits_asc_limb(xs.iter().copied(), base); assert_eq!( from_digits_desc_naive_primitive( &xs.into_iter().rev().collect_vec(), T::exact_from(base) ), n ); }, ); } #[test] fn from_digits_asc_limb_properties() { apply_fn_to_unsigneds!(from_digits_asc_limb_properties_helper); } #[test] fn test_from_digits_desc_limb() { fn test_ok(xs: &[u32], base: Limb, n: &str) { let n = Natural::from_str(n).unwrap(); assert_eq!(from_digits_desc_limb(xs.iter().copied(), base).unwrap(), n); assert_eq!( from_digits_desc_naive_primitive(xs, u32::exact_from(base)).unwrap(), n ); } test_ok(&[], 9, "0"); // - Some(log_base) != base.checked_log_base_2() // - base < 256 test_ok(&[0], 9, "0"); test_ok(&[1], 9, "1"); test_ok(&[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); test_ok(&[0, 0, 2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); // - Some(log_base) = base.checked_log_base_2() test_ok(&[2, 4, 6, 4, 2], 8, "10658"); // - base >= 256 // - from_digits_desc_divide_and_conquer_limb; power_index == 0 || b < // FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD // - from_digits_desc_divide_and_conquer_limb; base <= SQRT_MAX_LIMB test_ok(&[123, 456, 789], 1000, "123456789"); test_ok( &[ 73, 23, 120, 45, 108, 147, 113, 90, 129, 11, 86, 0, 102, 81, 22, 17, 32, 121, 29, 82, 27, 25, 39, 9, 139, 59, 51, 13, 44, 3, 37, 104, 41, 40, 87, 66, 83, 146, 40, 132, 15, 50, 66, 80, 73, 61, 75, 25, 78, 34, 128, 86, 68, 26, 62, 135, 21, 9, 27, 74, 12, 39, 67, 15, 41, 50, 144, 35, 98, 140, 124, 132, 10, 37, 101, 99, 14, ], 150, "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); // - power_index != 0 && b >= FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD // - from_digits_desc_divide_and_conquer_limb; xs_len > p test_ok( &[1598, 27, 2039, 2403, 1843, 2859, 1581, 150, 2359, 302], 3543, "140578615308984594421852296827289425", ); // - from_digits_desc_divide_and_conquer_limb; base > SQRT_MAX_LIMB test_ok( &[1153431348, 1518538399, 293681571, 570510527, 83185796, 1187762660], 1525385058, "9525530906278526930121302445905223566866929778026945776", ); // - from_digits_desc_divide_and_conquer_limb; xs_len <= p test_ok( &[ 1046252719, 824969631, 1659733906, 1842176041, 1599722999, 1214721934, 1204675417, 1169948427, 798341655, 1494323667, 31832127, 1535724679, ], 1895460450, "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); fn test_err(xs: &[u32], base: Limb) { assert!(from_digits_desc_limb(xs.iter().copied(), base).is_none()); assert!(from_digits_desc_naive_primitive(xs, u32::exact_from(base)).is_none()); } test_err(&[10, 11, 12], 10); } fn from_digits_desc_limb_fail_helper + PrimitiveUnsigned>() where Limb: TryFrom + WrappingFrom, Natural: From + PowerOf2Digits, { assert_panic!(from_digits_desc_limb::<_, T>(empty(), 0)); assert_panic!(from_digits_desc_limb::<_, T>(empty(), 1)); } #[test] fn from_digits_desc_limb_fail() { apply_fn_to_unsigneds!(from_digits_desc_limb_fail_helper); } fn from_digits_desc_limb_properties_helper + PrimitiveUnsigned>() where Limb: ExactFrom + SaturatingFrom + WrappingFrom, Natural: From + PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_12::().test_properties_with_config( &config, |(xs, base)| { let t_base = T::exact_from(base); assert_eq!( from_digits_desc_limb(xs.iter().copied(), base).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_5::().test_properties_with_config( &config, |(xs, base)| { let n = from_digits_desc_limb(xs.iter().copied(), base); assert_eq!( from_digits_desc_naive_primitive(&xs, T::exact_from(base)), n ); }, ); } #[test] fn from_digits_desc_limb_properties() { apply_fn_to_unsigneds!(from_digits_desc_limb_properties_helper); } #[test] fn test_from_digits_asc_large() { fn test_ok(xs: &[&str], base: &str, n: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); let n = Natural::from_str(n).unwrap(); assert_eq!(from_digits_asc_large(xs.clone(), &base).unwrap(), n); assert_eq!( from_digits_desc_naive(&xs.rev().collect_vec(), &base).unwrap(), n ); } test_ok(&["0", "100"], "10000000000", "1000000000000"); test_ok( &["27917287424", "18657454436", "8470329472"], "34359738368", "10000000000000000000000000000000", ); test_ok( &[ "4373186134", "2564485756", "2124820161", "4270626619", "5254372654", "713959034", "4750044302", "5833014701", "978351288", "4288991795", "972424917", "1439538405", "5308114100", "1115837958", "2267585072", "4579628351", "3319271253", "139021832", ], "6000000000", "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", ); test_ok( &[ "10459983243", "21532249186", "9820491776", "2837355685", "9767368393", "3483032332", "21535703589", "11033729126", "9179503556", "8692905086", "4911199976", "15555287795", "16865310802", "20703615271", "16296043356", "2287104975", "7356592443", "19932263435", "22157300197", ], "24107150480", "167549316476609610254199818013888896761159964082484503741352784741144483211685148473082817\ 5855188918761759968447473283739550817700685872668984640703760436616510553858385622841396530\ 38089626212682923", ); fn test_err(xs: &[&str], base: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); assert!(from_digits_asc_large(xs.clone(), &base).is_none()); assert!(from_digits_desc_naive(&xs.rev().collect_vec(), &base).is_none()); } test_err( &["1000000000000000000000001", "1000000000000000000000002"], "1000000000000000000000000", ); } #[test] fn from_digits_asc_large_fail() { assert_panic!(from_digits_asc_large(empty(), &Natural::ZERO)); assert_panic!(from_digits_asc_large(empty(), &Natural::ONE)); } #[test] fn from_digits_asc_large_properties() { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); natural_vec_natural_pair_gen_var_3().test_properties_with_config(&config, |(xs, base)| { assert_eq!( from_digits_asc_large(xs.iter().cloned(), &base).is_some(), xs.iter().all(|x| x < &base) ); }); natural_vec_natural_pair_gen_var_1().test_properties_with_config(&config, |(xs, base)| { let n = from_digits_asc_large(xs.iter().cloned(), &base); assert_eq!( from_digits_desc_naive(&xs.into_iter().rev().collect_vec(), &base), n ); }); } #[test] fn test_from_digits_desc_large() { fn test_ok(xs: &[&str], base: &str, n: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); let n = Natural::from_str(n).unwrap(); assert_eq!(from_digits_desc_large(xs.clone(), &base).unwrap(), n); assert_eq!(from_digits_desc_naive(&xs.collect_vec(), &base).unwrap(), n); } // - Some(log_base) != base.checked_log_base_2() // - from_digits_desc_divide_and_conquer; power_index == 0 || u64::exact_from(xs_len) * // base.significant_bits() < FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD test_ok(&["100", "0"], "10000000000", "1000000000000"); // - Some(log_base) = base.checked_log_base_2() test_ok( &["8470329472", "18657454436", "27917287424"], "34359738368", "10000000000000000000000000000000", ); // - from_digits_desc_divide_and_conquer; power_index != 0 && u64::exact_from(xs_len) * // base.significant_bits() >= FROM_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD // - from_digits_desc_divide_and_conquer; xs_len > p test_ok( &[ "139021832", "3319271253", "4579628351", "2267585072", "1115837958", "5308114100", "1439538405", "972424917", "4288991795", "978351288", "5833014701", "4750044302", "713959034", "5254372654", "4270626619", "2124820161", "2564485756", "4373186134", ], "6000000000", "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", ); // - from_digits_desc_divide_and_conquer; xs_len <= p test_ok( &[ "22157300197", "19932263435", "7356592443", "2287104975", "16296043356", "20703615271", "16865310802", "15555287795", "4911199976", "8692905086", "9179503556", "11033729126", "21535703589", "3483032332", "9767368393", "2837355685", "9820491776", "21532249186", "10459983243", ], "24107150480", "167549316476609610254199818013888896761159964082484503741352784741144483211685148473082817\ 5855188918761759968447473283739550817700685872668984640703760436616510553858385622841396530\ 38089626212682923", ); fn test_err(xs: &[&str], base: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); assert!(from_digits_desc_large(xs.clone(), &base).is_none()); assert!(from_digits_desc_naive(&xs.collect_vec(), &base).is_none()); } test_err( &["1000000000000000000000000", "1000000000000000000000001"], "1000000000000000000000000", ); } #[test] fn from_digits_desc_large_fail() { assert_panic!(from_digits_desc_large(empty(), &Natural::ZERO)); assert_panic!(from_digits_desc_large(empty(), &Natural::ONE)); } #[test] fn from_digits_desc_large_properties() { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); natural_vec_natural_pair_gen_var_3().test_properties_with_config(&config, |(xs, base)| { assert_eq!( from_digits_desc_large(xs.iter().cloned(), &base).is_some(), xs.iter().all(|x| x < &base) ); }); natural_vec_natural_pair_gen_var_1().test_properties_with_config(&config, |(xs, base)| { let n = from_digits_desc_large(xs.iter().cloned(), &base); assert_eq!(from_digits_desc_naive(&xs, &base), n); }); } #[test] fn from_digits_asc_unsigned() { fn test_ok(xs: &[Limb], base: Limb, n: &str) { let n = Natural::from_str(n).unwrap(); assert_eq!( Natural::from_digits_asc(&base, xs.iter().copied()).unwrap(), n ); } test_ok(&[], 9, "0"); test_ok(&[0], 9, "0"); test_ok(&[1], 9, "1"); test_ok(&[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2], 3, "123456"); test_ok(&[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2, 0, 0], 3, "123456"); test_ok(&[2, 4, 6, 4, 2], 8, "10658"); test_ok(&[789, 456, 123], 1000, "123456789"); test_ok( &[ 14, 99, 101, 37, 10, 132, 124, 140, 98, 35, 144, 50, 41, 15, 67, 39, 12, 74, 27, 9, 21, 135, 62, 26, 68, 86, 128, 34, 78, 25, 75, 61, 73, 80, 66, 50, 15, 132, 40, 146, 83, 66, 87, 40, 41, 104, 37, 3, 44, 13, 51, 59, 139, 9, 39, 25, 27, 82, 29, 121, 32, 17, 22, 81, 102, 0, 86, 11, 129, 90, 113, 147, 108, 45, 120, 23, 73, ], 150, "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); test_ok( &[302, 2359, 150, 1581, 2859, 1843, 2403, 2039, 27, 1598], 3543, "140578615308984594421852296827289425", ); test_ok( &[1187762660, 83185796, 570510527, 293681571, 1518538399, 1153431348], 1525385058, "9525530906278526930121302445905223566866929778026945776", ); test_ok( &[ 1535724679, 31832127, 1494323667, 798341655, 1169948427, 1204675417, 1214721934, 1599722999, 1842176041, 1659733906, 824969631, 1046252719, ], 1895460450, "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); fn test_err(xs: &[Limb], base: Limb) { assert!(Natural::from_digits_asc(&base, xs.iter().copied()).is_none()); } test_err(&[10, 11, 12], 10); } fn from_digits_asc_unsigned_fail_helper() where Natural: Digits, { assert_panic!(Natural::from_digits_asc(&T::ONE, empty())); assert_panic!(Natural::from_digits_asc(&T::ZERO, empty())); } #[test] fn from_digits_asc_unsigned_fail() { apply_fn_to_unsigneds!(from_digits_asc_unsigned_fail_helper); } fn from_digits_asc_unsigned_helper + WrappingFrom>() where Natural: Digits, { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_12::().test_properties_with_config( &config, |(xs, base)| { let t_base = T::exact_from(base); assert_eq!( Natural::from_digits_asc(&base, xs.iter().copied()).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_5::().test_properties_with_config( &config, |(digits, base)| { let n = Natural::from_digits_asc(&base, digits.iter().copied()).unwrap(); assert_eq!( Natural::from_digits_desc(&base, digits.iter().rev().copied()).unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); assert_eq!( n.to_digits_asc(&base), &digits[..digits.len() - trailing_zeros] ); }, ); unsigned_pair_gen_var_10::().test_properties(|(base, u)| { assert_eq!( Natural::from_digits_asc(&base, repeat_n(T::ZERO, u)), Some(Natural::ZERO) ); }); } #[test] fn from_digits_asc_unsigned_properties() { apply_fn_to_unsigneds!(from_digits_asc_unsigned_helper); } #[test] fn from_digits_desc_unsigned() { fn test_ok(xs: &[Limb], base: Limb, n: &str) { let n = Natural::from_str(n).unwrap(); assert_eq!( Natural::from_digits_desc(&base, xs.iter().copied()).unwrap(), n ); assert_eq!(from_digits_desc_naive_primitive(xs, base).unwrap(), n); } test_ok(&[], 9, "0"); test_ok(&[0], 9, "0"); test_ok(&[1], 9, "1"); test_ok(&[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); test_ok(&[0, 0, 2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], 3, "123456"); test_ok(&[2, 4, 6, 4, 2], 8, "10658"); test_ok(&[123, 456, 789], 1000, "123456789"); test_ok( &[ 73, 23, 120, 45, 108, 147, 113, 90, 129, 11, 86, 0, 102, 81, 22, 17, 32, 121, 29, 82, 27, 25, 39, 9, 139, 59, 51, 13, 44, 3, 37, 104, 41, 40, 87, 66, 83, 146, 40, 132, 15, 50, 66, 80, 73, 61, 75, 25, 78, 34, 128, 86, 68, 26, 62, 135, 21, 9, 27, 74, 12, 39, 67, 15, 41, 50, 144, 35, 98, 140, 124, 132, 10, 37, 101, 99, 14, ], 150, "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); test_ok( &[1598, 27, 2039, 2403, 1843, 2859, 1581, 150, 2359, 302], 3543, "140578615308984594421852296827289425", ); test_ok( &[1153431348, 1518538399, 293681571, 570510527, 83185796, 1187762660], 1525385058, "9525530906278526930121302445905223566866929778026945776", ); test_ok( &[ 1046252719, 824969631, 1659733906, 1842176041, 1599722999, 1214721934, 1204675417, 1169948427, 798341655, 1494323667, 31832127, 1535724679, ], 1895460450, "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); fn test_err(xs: &[Limb], base: Limb) { assert!(Natural::from_digits_desc(&base, xs.iter().copied()).is_none()); assert!(from_digits_desc_naive_primitive(xs, base).is_none()); } test_err(&[10, 11, 12], 10); } fn from_digits_desc_unsigned_fail_helper() where Natural: Digits, { assert_panic!(Natural::from_digits_desc(&T::ONE, empty())); assert_panic!(Natural::from_digits_desc(&T::ZERO, empty())); } #[test] fn from_digits_desc_unsigned_fail() { apply_fn_to_unsigneds!(from_digits_desc_unsigned_fail_helper); } fn from_digits_desc_unsigned_helper + WrappingFrom>() where Natural: Digits + From, { let mut config = GenConfig::new(); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_12::().test_properties_with_config( &config, |(xs, base)| { let t_base = T::exact_from(base); assert_eq!( Natural::from_digits_desc(&base, xs.iter().copied()).is_some(), xs.iter().all(|&x| x < t_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_5::().test_properties_with_config( &config, |(digits, base)| { let n = Natural::from_digits_desc(&base, digits.iter().copied()).unwrap(); assert_eq!( Natural::from_digits_asc(&base, digits.iter().rev().copied()).unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); assert_eq!(n.to_digits_desc(&base), &digits[leading_zeros..]); assert_eq!( from_digits_desc_naive_primitive(&digits, T::exact_from(base)).unwrap(), n ); }, ); unsigned_pair_gen_var_10::().test_properties(|(base, u)| { assert_eq!( Natural::from_digits_desc(&base, repeat_n(T::ZERO, u)), Some(Natural::ZERO) ); }); } #[test] fn from_digits_desc_unsigned_properties() { apply_fn_to_unsigneds!(from_digits_desc_unsigned_helper); } #[test] fn from_digits_asc() { fn test_ok(xs: &[&str], base: &str, n: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); let n = Natural::from_str(n).unwrap(); assert_eq!(Natural::from_digits_asc(&base, xs.clone()).unwrap(), n); } test_ok(&[], "9", "0"); test_ok(&["0"], "9", "0"); test_ok(&["1"], "9", "1"); test_ok( &["0", "1", "1", "0", "0", "1", "1", "2", "0", "0", "2"], "3", "123456", ); test_ok( &["0", "1", "1", "0", "0", "1", "1", "2", "0", "0", "2", "0", "0"], "3", "123456", ); test_ok(&["2", "4", "6", "4", "2"], "8", "10658"); test_ok(&["789", "456", "123"], "1000", "123456789"); test_ok( &[ "14", "99", "101", "37", "10", "132", "124", "140", "98", "35", "144", "50", "41", "15", "67", "39", "12", "74", "27", "9", "21", "135", "62", "26", "68", "86", "128", "34", "78", "25", "75", "61", "73", "80", "66", "50", "15", "132", "40", "146", "83", "66", "87", "40", "41", "104", "37", "3", "44", "13", "51", "59", "139", "9", "39", "25", "27", "82", "29", "121", "32", "17", "22", "81", "102", "0", "86", "11", "129", "90", "113", "147", "108", "45", "120", "23", "73", ], "150", "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); test_ok( &["302", "2359", "150", "1581", "2859", "1843", "2403", "2039", "27", "1598"], "3543", "140578615308984594421852296827289425", ); test_ok( &["1187762660", "83185796", "570510527", "293681571", "1518538399", "1153431348"], "1525385058", "9525530906278526930121302445905223566866929778026945776", ); test_ok( &[ "1535724679", "31832127", "1494323667", "798341655", "1169948427", "1204675417", "1214721934", "1599722999", "1842176041", "1659733906", "824969631", "1046252719", ], "1895460450", "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); test_ok(&["0", "100"], "10000000000", "1000000000000"); test_ok( &["27917287424", "18657454436", "8470329472"], "34359738368", "10000000000000000000000000000000", ); test_ok( &[ "4373186134", "2564485756", "2124820161", "4270626619", "5254372654", "713959034", "4750044302", "5833014701", "978351288", "4288991795", "972424917", "1439538405", "5308114100", "1115837958", "2267585072", "4579628351", "3319271253", "139021832", ], "6000000000", "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", ); test_ok( &[ "10459983243", "21532249186", "9820491776", "2837355685", "9767368393", "3483032332", "21535703589", "11033729126", "9179503556", "8692905086", "4911199976", "15555287795", "16865310802", "20703615271", "16296043356", "2287104975", "7356592443", "19932263435", "22157300197", ], "24107150480", "167549316476609610254199818013888896761159964082484503741352784741144483211685148473082817\ 5855188918761759968447473283739550817700685872668984640703760436616510553858385622841396530\ 38089626212682923", ); fn test_err(xs: &[&str], base: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); assert!(Natural::from_digits_asc(&base, xs.clone()).is_none()); } test_err(&["101", "102"], "100"); } #[test] fn from_digits_asc_fail() { assert_panic!(Natural::from_digits_asc(&Natural::ZERO, empty())); assert_panic!(Natural::from_digits_asc(&Natural::ONE, empty())); } #[test] fn from_digits_asc_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 64); config.insert("mean_digit_count_n", 32); natural_vec_natural_pair_gen_var_4().test_properties_with_config(&config, |(xs, base)| { assert_eq!( Natural::from_digits_asc(&base, xs.iter().cloned()).is_some(), xs.iter().all(|x| x < &base) ); }); natural_vec_natural_pair_gen_var_2().test_properties_with_config(&config, |(digits, base)| { let n = Natural::from_digits_asc(&base, digits.iter().cloned()).unwrap(); assert_eq!( Natural::from_digits_desc(&base, digits.iter().rev().cloned()).unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); assert_eq!( n.to_digits_asc(&base), &digits[..digits.len() - trailing_zeros] ); }); natural_unsigned_pair_gen_var_5().test_properties(|(base, u)| { assert_eq!( Natural::from_digits_asc(&base, repeat_n(Natural::ZERO, u)), Some(Natural::ZERO) ); }); } #[test] fn from_digits_desc() { fn test_ok(xs: &[&str], base: &str, n: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); let n = Natural::from_str(n).unwrap(); assert_eq!(Natural::from_digits_desc(&base, xs.clone()).unwrap(), n); assert_eq!(from_digits_desc_naive(&xs.collect_vec(), &base).unwrap(), n); } test_ok(&[], "9", "0"); test_ok(&["0"], "9", "0"); test_ok(&["1"], "9", "1"); test_ok( &["2", "0", "0", "2", "1", "1", "0", "0", "1", "1", "0"], "3", "123456", ); test_ok( &["0", "0", "2", "0", "0", "2", "1", "1", "0", "0", "1", "1", "0"], "3", "123456", ); test_ok(&["2", "4", "6", "4", "2"], "8", "10658"); test_ok(&["123", "456", "789"], "1000", "123456789"); test_ok( &[ "73", "23", "120", "45", "108", "147", "113", "90", "129", "11", "86", "0", "102", "81", "22", "17", "32", "121", "29", "82", "27", "25", "39", "9", "139", "59", "51", "13", "44", "3", "37", "104", "41", "40", "87", "66", "83", "146", "40", "132", "15", "50", "66", "80", "73", "61", "75", "25", "78", "34", "128", "86", "68", "26", "62", "135", "21", "9", "27", "74", "12", "39", "67", "15", "41", "50", "144", "35", "98", "140", "124", "132", "10", "37", "101", "99", "14", ], "150", "176685760608531978263731938997517835399219565848609872558191310084297042793489341607854254\ 709347189745346071475819587247558105442098729883999424898641968281841439662364", ); test_ok( &["1598", "27", "2039", "2403", "1843", "2859", "1581", "150", "2359", "302"], "3543", "140578615308984594421852296827289425", ); test_ok( &["1153431348", "1518538399", "293681571", "570510527", "83185796", "1187762660"], "1525385058", "9525530906278526930121302445905223566866929778026945776", ); test_ok( &[ "1046252719", "824969631", "1659733906", "1842176041", "1599722999", "1214721934", "1204675417", "1169948427", "798341655", "1494323667", "31832127", "1535724679", ], "1895460450", "118713086621740109729266002848273602283691336549480820142301294962906804654789322428658177\ 1782212965464227294329", ); test_ok(&["100", "0"], "10000000000", "1000000000000"); test_ok( &["8470329472", "18657454436", "27917287424"], "34359738368", "10000000000000000000000000000000", ); test_ok( &[ "139021832", "3319271253", "4579628351", "2267585072", "1115837958", "5308114100", "1439538405", "972424917", "4288991795", "978351288", "5833014701", "4750044302", "713959034", "5254372654", "4270626619", "2124820161", "2564485756", "4373186134", ], "6000000000", "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", ); test_ok( &[ "22157300197", "19932263435", "7356592443", "2287104975", "16296043356", "20703615271", "16865310802", "15555287795", "4911199976", "8692905086", "9179503556", "11033729126", "21535703589", "3483032332", "9767368393", "2837355685", "9820491776", "21532249186", "10459983243", ], "24107150480", "167549316476609610254199818013888896761159964082484503741352784741144483211685148473082817\ 5855188918761759968447473283739550817700685872668984640703760436616510553858385622841396530\ 38089626212682923", ); fn test_err(xs: &[&str], base: &str) { let xs = xs.iter().map(|x| Natural::from_str(x).unwrap()); let base = Natural::from_str(base).unwrap(); assert!(Natural::from_digits_desc(&base, xs.clone()).is_none()); assert!(from_digits_desc_naive(&xs.collect_vec(), &base).is_none()); } test_err(&["101", "102"], "100"); } #[test] fn from_digits_desc_fail() { assert_panic!(Natural::from_digits_desc(&Natural::ZERO, empty())); assert_panic!(Natural::from_digits_desc(&Natural::ONE, empty())); } #[test] fn from_digits_desc_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 64); config.insert("mean_digit_count_n", 32); natural_vec_natural_pair_gen_var_4().test_properties_with_config(&config, |(xs, base)| { assert_eq!( Natural::from_digits_desc(&base, xs.iter().cloned()).is_some(), xs.iter().all(|x| x < &base) ); }); natural_vec_natural_pair_gen_var_2().test_properties_with_config(&config, |(digits, base)| { let n = Natural::from_digits_desc(&base, digits.iter().cloned()).unwrap(); assert_eq!( Natural::from_digits_asc(&base, digits.iter().rev().cloned()).unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); assert_eq!(n.to_digits_desc(&base), &digits[leading_zeros..]); assert_eq!(from_digits_desc_naive(&digits, &base).unwrap(), n); }); natural_unsigned_pair_gen_var_5().test_properties(|(base, u)| { assert_eq!( Natural::from_digits_desc(&base, repeat_n(Natural::ZERO, u)), Some(Natural::ZERO) ); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 itertools::repeat_n; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::slices::{slice_leading_zeros, slice_trailing_zeros}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_5, unsigned_pair_gen_var_18, unsigned_vec_gen, unsigned_vec_unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_3, unsigned_vec_unsigned_pair_gen_var_10, unsigned_vec_unsigned_pair_gen_var_11, }; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_vec_unsigned_pair_gen_var_1, natural_vec_unsigned_pair_gen_var_2, }; use std::panic::catch_unwind; #[test] fn test_from_power_of_2_digits_asc() { fn test_ok(log_base: u64, digits: &[T], out: &str) where Natural: From + PowerOf2Digits, { assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()) .unwrap() .to_string(), out ); assert_eq!( Natural::from_power_of_2_digits_asc_naive(log_base, digits.iter().copied()) .unwrap() .to_string(), out ); } test_ok::(1, &[], "0"); test_ok::(1, &[0, 0, 0], "0"); test_ok::(10, &[123], "123"); test_ok::( 1, &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, ], "1000000000000", ); test_ok::( 3, &[0, 0, 0, 0, 1, 2, 1, 5, 4, 2, 3, 4, 6, 1, 0], "1000000000000", ); test_ok::(4, &[0, 0, 0, 1, 5, 10, 4, 13, 8, 14], "1000000000000"); test_ok::(32, &[3567587328, 232], "1000000000000"); test_ok::(64, &[1000000000000], "1000000000000"); test_ok::( 64, &[2003764205206896640, 54210], "1000000000000000000000000", ); fn test_err(log_base: u64, digits: &[T]) where Natural: From + PowerOf2Digits, { assert!(Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()).is_none()); assert!( Natural::from_power_of_2_digits_asc_naive(log_base, digits.iter().copied()).is_none() ); } test_err::(1, &[2]); } fn from_power_of_2_digits_asc_fail_helper() where Natural: PowerOf2Digits, { assert_panic!(Natural::from_power_of_2_digits_asc( 0, [T::ZERO].iter().copied() )); assert_panic!(Natural::from_power_of_2_digits_asc( T::WIDTH + 1, [T::TWO].iter().copied() )); } #[test] fn from_power_of_2_digits_asc_fail() { apply_fn_to_unsigneds!(from_power_of_2_digits_asc_fail_helper); } #[test] fn test_from_power_of_2_digits_desc() { fn test_ok(log_base: u64, digits: &[T], out: &str) where Natural: PowerOf2Digits, { assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()) .unwrap() .to_string(), out ); } test_ok::(1, &[], "0"); test_ok::(1, &[0, 0, 0], "0"); test_ok::(10, &[123], "123"); test_ok::( 1, &[ 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "1000000000000", ); test_ok::( 3, &[0, 1, 6, 4, 3, 2, 4, 5, 1, 2, 1, 0, 0, 0, 0], "1000000000000", ); test_ok::(4, &[14, 8, 13, 4, 10, 5, 1, 0, 0, 0], "1000000000000"); test_ok::(32, &[232, 3567587328], "1000000000000"); test_ok::(64, &[1000000000000], "1000000000000"); test_ok::( 64, &[54210, 2003764205206896640], "1000000000000000000000000", ); fn test_err(log_base: u64, digits: &[T]) where Natural: PowerOf2Digits, { assert!(Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).is_none()); } test_err::(1, &[2]); } fn from_power_of_2_digits_desc_fail_helper() where Natural: PowerOf2Digits, { assert_panic!(Natural::from_power_of_2_digits_desc( 0, [T::ZERO].iter().copied() )); assert_panic!(Natural::from_power_of_2_digits_desc( T::WIDTH + 1, [T::TWO].iter().copied() )); } #[test] fn from_power_of_2_digits_desc_fail() { apply_fn_to_unsigneds!(from_power_of_2_digits_desc_fail_helper); } #[test] fn test_from_power_of_2_digits_asc_natural() { let test_ok = |log_base, digits, out| { let digits = vec_from_str(digits).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()) .unwrap() .to_string(), out ); assert_eq!( Natural::from_power_of_2_digits_asc_natural_naive(log_base, digits.iter().cloned()) .unwrap() .to_string(), out ); }; test_ok(1, "[]", "0"); test_ok(1, "[0, 0, 0]", "0"); test_ok(10, "[123]", "123"); test_ok( 1, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, \ 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1]", "1000000000000", ); test_ok( 3, "[0, 0, 0, 0, 1, 2, 1, 5, 4, 2, 3, 4, 6, 1]", "1000000000000", ); test_ok(4, "[0, 0, 0, 1, 5, 10, 4, 13, 8, 14, 0]", "1000000000000"); test_ok(32, "[3567587328, 232]", "1000000000000"); test_ok(64, "[1000000000000]", "1000000000000"); test_ok( 64, "[2003764205206896640, 54210]", "1000000000000000000000000", ); test_ok( 33, "[6996099072, 4528236150, 13552]", "1000000000000000000000000", ); let test_err = |log_base, digits| { let digits = vec_from_str(digits).unwrap(); assert!(Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()).is_none()); assert!( Natural::from_power_of_2_digits_asc_natural_naive(log_base, digits.iter().cloned()) .is_none() ); }; test_err(1, "[2]"); } #[test] #[should_panic] fn from_power_of_2_digits_asc_natural_fail() { let digits: Vec = vec_from_str("[0, 0, 0]").unwrap(); Natural::from_power_of_2_digits_asc(0, digits.iter().cloned()); } #[test] fn test_from_power_of_2_digits_desc_natural() { let test_ok = |log_base, digits, out| { let digits: Vec = vec_from_str(digits).unwrap(); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()) .unwrap() .to_string(), out ); }; test_ok(1, "[]", "0"); test_ok(1, "[0, 0, 0]", "0"); test_ok(10, "[123]", "123"); test_ok( 1, "[1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", "1000000000000", ); test_ok( 3, "[1, 6, 4, 3, 2, 4, 5, 1, 2, 1, 0, 0, 0, 0]", "1000000000000", ); test_ok(4, "[0, 14, 8, 13, 4, 10, 5, 1, 0, 0, 0]", "1000000000000"); test_ok(32, "[232, 3567587328]", "1000000000000"); test_ok(64, "[1000000000000]", "1000000000000"); test_ok( 64, "[54210, 2003764205206896640]", "1000000000000000000000000", ); test_ok( 33, "[13552, 4528236150, 6996099072]", "1000000000000000000000000", ); let test_err = |log_base, digits| { let digits: Vec = vec_from_str(digits).unwrap(); assert!(Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()).is_none()); }; test_err(1, "[2]"); } #[test] #[should_panic] fn from_power_of_2_digits_desc_natural_fail() { let digits: Vec = vec_from_str("[0, 0, 0]").unwrap(); Natural::from_power_of_2_digits_desc(0, digits.iter().cloned()); } fn from_power_of_2_digits_asc_properties_helper() where Natural: From + PowerOf2Digits, Limb: PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_log_base_n", T::WIDTH >> 1); config.insert("mean_stripe_n", 64); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_11().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()); assert_eq!( n.is_some(), digits.iter().all(|x| x.significant_bits() <= log_base), ); }, ); unsigned_vec_unsigned_pair_gen_var_10().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc_naive(log_base, digits.iter().copied()) .unwrap(), n ); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().rev().copied()) .unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); let trimmed_digits = digits[..digits.len() - trailing_zeros].to_vec(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base), trimmed_digits ); }, ); unsigned_pair_gen_var_5::().test_properties(|(u, log_base)| { assert_eq!( Natural::from_power_of_2_digits_asc(log_base, repeat_n(T::ZERO, u)).unwrap(), 0 ); }); unsigned_vec_unsigned_pair_gen_var_2::().test_properties_with_config( &config, |(digits, log_base)| { let n = Limb::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(), Natural::try_from(Integer::from(n)).unwrap() ); }, ); } #[test] fn from_power_of_2_digits_asc_properties() { apply_fn_to_unsigneds!(from_power_of_2_digits_asc_properties_helper); let mut config = GenConfig::new(); config.insert("mean_stripe_n", 64); config.insert("mean_length_n", 32); unsigned_vec_gen().test_properties_with_config(&config, |xs| { assert_eq!( Natural::from_power_of_2_digits_asc(Limb::WIDTH, xs.iter().copied()).unwrap(), Natural::from_limbs_asc(&xs) ); }); } fn from_power_of_2_digits_desc_properties_helper() where Natural: From + PowerOf2Digits, Limb: PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_log_base_n", T::WIDTH >> 1); config.insert("mean_stripe_n", 64); config.insert("mean_digit_count_n", 32); unsigned_vec_unsigned_pair_gen_var_11().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()); assert_eq!( n.is_some(), digits.iter().all(|x| x.significant_bits() <= log_base) ); }, ); unsigned_vec_unsigned_pair_gen_var_10().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().rev().copied()) .unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); let trimmed_digits = digits[leading_zeros..].to_vec(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base), trimmed_digits ); }, ); unsigned_pair_gen_var_5::().test_properties(|(u, log_base)| { assert_eq!( Natural::from_power_of_2_digits_desc(log_base, repeat_n(T::ZERO, u)), Some(Natural::ZERO) ); }); unsigned_vec_unsigned_pair_gen_var_3::().test_properties_with_config( &config, |(digits, log_base)| { let n = Limb::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(); let natural_n: Natural = From::::from(n); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(), natural_n ); }, ); } #[test] fn from_power_of_2_digits_desc_properties() { apply_fn_to_unsigneds!(from_power_of_2_digits_desc_properties_helper); let mut config = GenConfig::new(); config.insert("mean_stripe_n", 64); config.insert("mean_length_n", 32); unsigned_vec_gen().test_properties_with_config(&config, |xs| { assert_eq!( Natural::from_power_of_2_digits_desc(Limb::WIDTH, xs.iter().copied()).unwrap(), Natural::from_limbs_desc(&xs) ); }); } #[test] fn from_power_of_2_digits_asc_natural_properties() { let mut config = GenConfig::new(); config.insert("mean_log_base_n", 16); config.insert("mean_stripe_n", 64); config.insert("mean_digit_count_n", 32); natural_vec_unsigned_pair_gen_var_2().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()); assert_eq!( n.is_some(), digits.iter().all(|x| x.significant_bits() <= log_base), ); }, ); natural_vec_unsigned_pair_gen_var_1().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc_natural_naive(log_base, digits.iter().cloned()) .unwrap(), n ); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().rev().cloned()) .unwrap(), n ); let trailing_zeros = slice_trailing_zeros(&digits); let trimmed_digits = digits[..digits.len() - trailing_zeros].to_vec(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base), trimmed_digits ); }, ); unsigned_pair_gen_var_18().test_properties(|(u, log_base)| { assert_eq!( Natural::from_power_of_2_digits_asc(log_base, repeat_n(Natural::ZERO, u)), Some(Natural::ZERO) ); }); unsigned_vec_unsigned_pair_gen_var_10::().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()); let digits = digits.iter().copied().map(Natural::from).collect_vec(); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()), n ); }, ); } #[test] fn from_power_of_2_digits_desc_natural_properties() { let mut config = GenConfig::new(); config.insert("mean_log_base_n", 16); config.insert("mean_stripe_n", 64); config.insert("mean_digit_count_n", 32); natural_vec_unsigned_pair_gen_var_2().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()); assert_eq!( n.is_some(), digits.iter().all(|x| x.significant_bits() <= log_base) ); }, ); natural_vec_unsigned_pair_gen_var_1().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()).unwrap(); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().rev().cloned()) .unwrap(), n ); let leading_zeros = slice_leading_zeros(&digits); let trimmed_digits = digits[leading_zeros..].to_vec(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base), trimmed_digits ); }, ); unsigned_pair_gen_var_18().test_properties(|(u, log_base)| { assert_eq!( Natural::from_power_of_2_digits_desc(log_base, repeat_n(Natural::ZERO, u)), Some(Natural::ZERO) ); }); unsigned_vec_unsigned_pair_gen_var_10::().test_properties_with_config( &config, |(digits, log_base)| { let n = Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(); let digits = digits.iter().copied().map(Natural::from).collect_vec(); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()).unwrap(), n ); }, ); } ================================================ FILE: malachite-nz/tests/natural/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{DivRound, Pow, Square}; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ExactFrom, PowerOf2DigitIterable, PowerOf2DigitIterator, PowerOf2Digits, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_base::test_util::common::test_double_ended_iterator_size_hint; use malachite_base::test_util::generators::{unsigned_pair_gen_var_5, unsigned_pair_gen_var_18}; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_unsigned_bool_vec_triple_gen_var_1, natural_unsigned_bool_vec_triple_gen_var_2, natural_unsigned_pair_gen_var_6, natural_unsigned_pair_gen_var_7, natural_unsigned_unsigned_triple_gen_var_2, natural_unsigned_unsigned_triple_gen_var_3, }; use std::panic::catch_unwind; #[test] pub fn test_power_of_2_digits_primitive() { let n = Natural::from(107u32); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 2), &[3, 2, 2, 1] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); assert_eq!(digits.next(), Some(3)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(2)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 3); assert_eq!(digits.get_digit(1), 2); assert_eq!(digits.get_digit(2), 2); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 0); let n = Natural::from(107u32); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), Some(3)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), Some(2)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::ZERO; let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 5); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::from(105u32); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 1), &[1, 0, 0, 1, 0, 1, 1] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 1); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 1); assert_eq!(digits.get_digit(1), 0); assert_eq!(digits.get_digit(2), 0); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 1); assert_eq!(digits.get_digit(6), 1); assert_eq!(digits.get_digit(7), 0); assert_eq!(digits.get_digit(8), 0); let n = Natural::from(105u32); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 1); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), Some(1)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next(), Some(0)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next_back(), Some(0)); assert_eq!(digits.next_back(), Some(1)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::from(10u32).pow(12); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 16), &[4096, 54437, 232] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 16); assert_eq!(digits.next(), Some(4096)); assert_eq!(digits.next_back(), Some(232)); assert_eq!(digits.next_back(), Some(54437)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 4096); assert_eq!(digits.get_digit(1), 54437); assert_eq!(digits.get_digit(2), 232); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); let n = Natural::from(10u32).pow(12); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 17), &[69632, 27218, 58] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 17); assert_eq!(digits.next(), Some(69632)); assert_eq!(digits.next_back(), Some(58)); assert_eq!(digits.next_back(), Some(27218)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 69632); assert_eq!(digits.get_digit(1), 27218); assert_eq!(digits.get_digit(2), 58); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 32), &[2701131776, 466537709, 54210] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 32); assert_eq!(digits.next(), Some(2701131776)); assert_eq!(digits.next_back(), Some(54210)); assert_eq!(digits.next_back(), Some(466537709)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 2701131776); assert_eq!(digits.get_digit(1), 466537709); assert_eq!(digits.get_digit(2), 54210); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 64), &[2003764205206896640, 54210] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 64); assert_eq!(digits.next(), Some(2003764205206896640)); assert_eq!(digits.next_back(), Some(54210)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 2003764205206896640); assert_eq!(digits.get_digit(1), 54210); assert_eq!(digits.get_digit(2), 0); assert_eq!(digits.get_digit(3), 0); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 37), &[58535706624, 129132033639, 52] ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 37); assert_eq!(digits.next(), Some(58535706624)); assert_eq!(digits.next_back(), Some(52)); assert_eq!(digits.next_back(), Some(129132033639)); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 58535706624); assert_eq!(digits.get_digit(1), 129132033639); assert_eq!(digits.get_digit(2), 52); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); } macro_rules! power_of_2_digits_primitive_fail_helper { ($t:ident) => { let x = Natural::from(107u32); assert_panic!(PowerOf2DigitIterable::<$t>::power_of_2_digits(&x, 0)); let x = Natural::from(107u32); assert_panic!(PowerOf2DigitIterable::<$t>::power_of_2_digits(&x, 200)); }; } #[test] fn power_of_2_digits_fail() { apply_to_unsigneds!(power_of_2_digits_primitive_fail_helper); } #[test] pub fn test_power_of_2_digits_natural() { let n = Natural::from(107u32); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 2).to_debug_string(), "[3, 2, 2, 1]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); assert_eq!(digits.next().unwrap(), 3); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next_back().unwrap(), 2); assert_eq!(digits.next().unwrap(), 2); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 3); assert_eq!(digits.get_digit(1), 2); assert_eq!(digits.get_digit(2), 2); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 0); let n = Natural::from(107u32); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 2); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next().unwrap(), 3); assert_eq!(digits.next().unwrap(), 2); assert_eq!(digits.next().unwrap(), 2); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::ZERO; let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 5); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::from(105u32); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 1).to_debug_string(), "[1, 0, 0, 1, 0, 1, 1]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 1); assert_eq!(digits.next().unwrap(), 1); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next_back().unwrap(), 0); assert_eq!(digits.next().unwrap(), 0); assert_eq!(digits.next().unwrap(), 0); assert_eq!(digits.next().unwrap(), 1); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 1); assert_eq!(digits.get_digit(1), 0); assert_eq!(digits.get_digit(2), 0); assert_eq!(digits.get_digit(3), 1); assert_eq!(digits.get_digit(4), 0); assert_eq!(digits.get_digit(5), 1); assert_eq!(digits.get_digit(6), 1); assert_eq!(digits.get_digit(7), 0); assert_eq!(digits.get_digit(8), 0); let n = Natural::from(105u32); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 1); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next().unwrap(), 1); assert_eq!(digits.next().unwrap(), 0); assert_eq!(digits.next().unwrap(), 0); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next_back().unwrap(), 0); assert_eq!(digits.next_back().unwrap(), 1); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); let n = Natural::from(10u32).pow(12); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 16).to_debug_string(), "[4096, 54437, 232]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 16); assert_eq!(digits.next().unwrap(), 4096); assert_eq!(digits.next_back().unwrap(), 232); assert_eq!(digits.next_back().unwrap(), 54437); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 4096); assert_eq!(digits.get_digit(1), 54437); assert_eq!(digits.get_digit(2), 232); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); let n = Natural::from(10u32).pow(12); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 17).to_debug_string(), "[69632, 27218, 58]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 17); assert_eq!(digits.next().unwrap(), 69632); assert_eq!(digits.next_back().unwrap(), 58); assert_eq!(digits.next_back().unwrap(), 27218); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 69632); assert_eq!(digits.get_digit(1), 27218); assert_eq!(digits.get_digit(2), 58); assert_eq!(digits.get_digit(3), 0); assert_eq!(digits.get_digit(4), 0); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 32).to_debug_string(), "[2701131776, 466537709, 54210]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 32); assert_eq!(digits.next().unwrap(), 2701131776u32); assert_eq!(digits.next_back().unwrap(), 54210u32); assert_eq!(digits.next_back().unwrap(), 466537709u32); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 2701131776u32); assert_eq!(digits.get_digit(1), 466537709u32); assert_eq!(digits.get_digit(2), 54210u32); assert_eq!(digits.get_digit(3), 0u32); assert_eq!(digits.get_digit(4), 0u32); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 64).to_debug_string(), "[2003764205206896640, 54210]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 64); assert_eq!(digits.next().unwrap(), 2003764205206896640u64); assert_eq!(digits.next_back().unwrap(), 54210u64); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 2003764205206896640u64); assert_eq!(digits.get_digit(1), 54210u64); assert_eq!(digits.get_digit(2), 0u64); assert_eq!(digits.get_digit(3), 0u64); let n = Natural::from(10u32).pow(12).square(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, 37).to_debug_string(), "[58535706624, 129132033639, 52]" ); let mut digits = PowerOf2DigitIterable::::power_of_2_digits(&n, 37); assert_eq!(digits.next().unwrap(), 58535706624u64); assert_eq!(digits.next_back().unwrap(), 52u64); assert_eq!(digits.next_back().unwrap(), 129132033639u64); assert_eq!(digits.next(), None); assert_eq!(digits.next_back(), None); assert_eq!(digits.get_digit(0), 58535706624u64); assert_eq!(digits.get_digit(1), 129132033639u64); assert_eq!(digits.get_digit(2), 52u64); assert_eq!(digits.get_digit(3), 0u64); assert_eq!(digits.get_digit(4), 0u64); } #[test] #[should_panic] fn natural_power_of_2_digits_natural_fail() { PowerOf2DigitIterable::::power_of_2_digits(&Natural::from(107u32), 0); } fn power_of_2_digits_primitive_properties_helper() where for<'a> &'a Natural: PowerOf2DigitIterable, Natural: PowerOf2Digits, for<'a> <&'a Natural as PowerOf2DigitIterable>::PowerOf2DigitIterator: Clone, { natural_unsigned_pair_gen_var_6::().test_properties(|(ref n, log_base)| { test_double_ended_iterator_size_hint( PowerOf2DigitIterable::::power_of_2_digits(n, log_base), usize::exact_from(n.significant_bits().div_round(log_base, Ceiling).0), ); }); natural_unsigned_bool_vec_triple_gen_var_2::().test_properties( |(ref n, log_base, ref bs)| { let mut digits = PowerOf2DigitIterable::::power_of_2_digits(n, log_base); let mut digit_vec = Vec::new(); let mut i = 0; for &b in bs { if b { digit_vec.insert(i, digits.next().unwrap()); i += 1; } else { digit_vec.insert(i, digits.next_back().unwrap()); } } assert!(digits.next().is_none()); assert!(digits.next_back().is_none()); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base), digit_vec ); }, ); natural_unsigned_unsigned_triple_gen_var_2::().test_properties( |(ref n, log_base, i)| { let digits = PowerOf2DigitIterable::::power_of_2_digits(n, log_base); if i < n.significant_bits().div_round(log_base, Ceiling).0 { assert_eq!( digits.get_digit(i), PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base) [usize::exact_from(i)], ); } else { assert_eq!(digits.get_digit(i), T::ZERO); } }, ); unsigned_pair_gen_var_5::().test_properties(|(i, log_base)| { let n = Natural::ZERO; let digits = PowerOf2DigitIterable::::power_of_2_digits(&n, log_base); assert_eq!(digits.get_digit(i), T::ZERO); }); } #[test] fn power_of_2_digits_primitive_properties() { apply_fn_to_unsigneds!(power_of_2_digits_primitive_properties_helper); } #[test] fn power_of_2_digits_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(ref n, log_base)| { test_double_ended_iterator_size_hint( PowerOf2DigitIterable::::power_of_2_digits(n, log_base), usize::exact_from(n.significant_bits().div_round(log_base, Ceiling).0), ); }); natural_unsigned_bool_vec_triple_gen_var_1().test_properties(|(ref n, log_base, ref bs)| { let mut digits = PowerOf2DigitIterable::::power_of_2_digits(n, log_base); let mut digit_vec = Vec::new(); let mut i = 0; for &b in bs { if b { digit_vec.insert(i, digits.next().unwrap()); i += 1; } else { digit_vec.insert(i, digits.next_back().unwrap()); } } assert!(digits.next().is_none()); assert!(digits.next_back().is_none()); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base), digit_vec ); }); natural_unsigned_unsigned_triple_gen_var_3().test_properties(|(ref n, log_base, i)| { let digits = PowerOf2DigitIterable::::power_of_2_digits(n, log_base); if i < n.significant_bits().div_round(log_base, Ceiling).0 { assert_eq!( digits.get_digit(i), PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base) [usize::exact_from(i)], ); } else { assert_eq!(digits.get_digit(i), 0); } }); unsigned_pair_gen_var_18().test_properties(|(i, log_base)| { let n = Natural::ZERO; let digits = PowerOf2DigitIterable::::power_of_2_digits(&n, log_base); assert_eq!(digits.get_digit(i), 0); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/digits/to_digits.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::FloorLogBase; #[cfg(feature = "32_bit_limbs")] use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, Digits, ExactFrom, PowerOf2Digits, SaturatingFrom, }; use malachite_base::num::logic::traits::BitConvertible; use malachite_base::slices::slice_leading_zeros; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen_var_6, unsigned_pair_gen_var_6}; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::digits::general_digits::{ PowerTableAlgorithm, limbs_to_digits_basecase, limbs_to_digits_small_base, limbs_to_digits_small_base_basecase, to_digits_asc_large, to_digits_asc_limb, to_digits_asc_naive, to_digits_asc_naive_primitive, to_digits_desc_large, to_digits_desc_limb, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::*; use std::panic::catch_unwind; use std::str::FromStr; fn verify_limbs_to_digits_small_base_basecase< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >( original_out: &[T], len: usize, xs: &[Limb], base: u64, out_len: usize, out: &[T], ) { if len != 0 { assert_eq!(len, out_len); } let mut digits = Vec::new(); to_digits_asc_naive_primitive(&mut digits, &Natural::from_limbs_asc(xs), base); let digits = digits.into_iter().map(T::exact_from).collect_vec(); let mut expected_digits = vec![T::ZERO; out_len]; expected_digits[..digits.len()].copy_from_slice(&digits); expected_digits.reverse(); assert_eq!(&out[..out_len], expected_digits); assert_eq!(&out[out_len..], &original_out[out_len..]); let result = out; let mut out = original_out.to_vec(); let mut xs = xs.to_vec(); let out_len_alt = limbs_to_digits_small_base(&mut out, base, &mut xs, None); let sig_out = &result[..out_len]; let sig_out_alt = &out[..out_len_alt]; assert_eq!( &sig_out[slice_leading_zeros(sig_out)..out_len], &sig_out_alt[slice_leading_zeros(sig_out_alt)..out_len_alt] ); } fn verify_limbs_to_digits_small_base TryFrom<&'a Natural> + PrimitiveUnsigned>( original_out: &[T], original_xs: &[Limb], base: u64, out_len: usize, out: &[T], ) { let mut digits = Vec::new(); to_digits_asc_naive_primitive(&mut digits, &Natural::from_limbs_asc(original_xs), base); let digits = digits.into_iter().map(T::exact_from).collect_vec(); let mut expected_digits = vec![T::ZERO; out_len]; expected_digits[..digits.len()].copy_from_slice(&digits); expected_digits.reverse(); assert_eq!(&out[..out_len], expected_digits); assert_eq!(&out[out_len..], &original_out[out_len..]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_to_digits_small_base_basecase() { fn test(out_before: &[u8], len: usize, xs: &[Limb], base: u64, out_after: &[u8]) { let mut out = out_before.to_vec(); let out_len = limbs_to_digits_small_base_basecase(&mut out, len, xs, base); assert_eq!(&out[..out_len], out_after); verify_limbs_to_digits_small_base_basecase(out_before, len, xs, base, out_len, &out); } test(&[0; 20], 0, &[], 9, &[]); // - base != 10 test(&[0; 20], 0, &[1], 9, &[1]); test( &[0; 20], 0, &[123456], 3, &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0], ); test(&[0; 20], 0, &[123456], 5, &[1, 2, 4, 2, 2, 3, 1, 1]); test(&[0; 20], 0, &[123456], 6, &[2, 3, 5, 1, 3, 2, 0]); test(&[0; 20], 0, &[123456], 7, &[1, 0, 2, 2, 6, 3, 4]); test(&[0; 20], 0, &[123456], 9, &[2, 0, 7, 3, 1, 3]); // - base == 10 test(&[0; 20], 0, &[123456], 10, &[1, 2, 3, 4, 5, 6]); test(&[0; 20], 0, &[123456], 11, &[8, 4, 8, 3, 3]); test(&[0; 20], 0, &[123456], 12, &[5, 11, 5, 4, 0]); test(&[0; 20], 0, &[123456], 13, &[4, 4, 2, 6, 8]); test(&[0; 20], 0, &[123456], 14, &[3, 2, 13, 12, 4]); test(&[0; 20], 0, &[123456], 15, &[2, 6, 8, 10, 6]); test(&[0; 20], 0, &[123456], 100, &[12, 34, 56]); test(&[0; 20], 0, &[123456], 123, &[8, 19, 87]); test(&[0; 20], 0, &[123456], 255, &[1, 229, 36]); // - base != 10 && xs_len > 1 test( &[0; 40], 0, &[123456, 789012], 5, &[1, 2, 0, 2, 3, 1, 3, 3, 2, 4, 0, 4, 2, 1, 4, 4, 1, 3, 0, 0, 0, 1, 3], ); // - base == 10 && xs_len > 1 test( &[0; 40], 0, &[123456, 789012], 10, &[3, 3, 8, 8, 7, 8, 0, 7, 3, 6, 2, 7, 5, 0, 0, 8], ); test( &[0; 40], 0, &[123456, 789012], 123, &[7, 117, 75, 111, 16, 62, 88, 96], ); test( &[0; 40], 0, &[123456, 789012], 255, &[12, 82, 251, 166, 147, 176, 78], ); // - zero_len != 0 test(&[0; 20], 8, &[123456], 9, &[0, 0, 2, 0, 7, 3, 1, 3]); test(&[0; 20], 8, &[123456], 10, &[0, 0, 1, 2, 3, 4, 5, 6]); } fn limbs_to_digits_small_base_basecase_properties_helper< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >() { let mut config = GenConfig::new(); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_stripe_d", 1); unsigned_vec_unsigned_unsigned_vec_unsigned_quadruple_gen_var_1::() .test_properties_with_config(&config, |(mut out, len, xs, base)| { let old_out = out.clone(); let out_len = limbs_to_digits_small_base_basecase(&mut out, len, &xs, base); verify_limbs_to_digits_small_base_basecase(&old_out, len, &xs, base, out_len, &out); }); } #[test] fn limbs_to_digits_small_base_basecase_properties() { apply_fn_to_unsigneds!(limbs_to_digits_small_base_basecase_properties_helper); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_to_digits_small_base() { fn test(out_before: &[u8], xs: &[Limb], base: u64, out_after: &[u8]) { let mut out = out_before.to_vec(); let mut mut_xs = xs.to_vec(); let out_len = limbs_to_digits_small_base(&mut out, base, &mut mut_xs, None); assert_eq!(&out[..out_len], out_after); verify_limbs_to_digits_small_base(out_before, xs, base, out_len, &out); } // - xs_len == 0 test(&[0; 20], &[], 9, &[]); // - 0 < xs_len < GET_STR_PRECOMPUTE_THRESHOLD test(&[0; 20], &[1], 9, &[1]); test(&[0; 20], &[123456], 3, &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0]); test(&[0; 20], &[123456], 5, &[1, 2, 4, 2, 2, 3, 1, 1]); test(&[0; 20], &[123456], 6, &[2, 3, 5, 1, 3, 2, 0]); test(&[0; 20], &[123456], 7, &[1, 0, 2, 2, 6, 3, 4]); test(&[0; 20], &[123456], 9, &[2, 0, 7, 3, 1, 3]); test(&[0; 20], &[123456], 10, &[1, 2, 3, 4, 5, 6]); test(&[0; 20], &[123456], 11, &[8, 4, 8, 3, 3]); test(&[0; 20], &[123456], 12, &[5, 11, 5, 4, 0]); test(&[0; 20], &[123456], 13, &[4, 4, 2, 6, 8]); test(&[0; 20], &[123456], 14, &[3, 2, 13, 12, 4]); test(&[0; 20], &[123456], 15, &[2, 6, 8, 10, 6]); test(&[0; 20], &[123456], 100, &[12, 34, 56]); test(&[0; 20], &[123456], 123, &[8, 19, 87]); test(&[0; 20], &[123456], 255, &[1, 229, 36]); test( &[0; 40], &[123456, 789012], 5, &[1, 2, 0, 2, 3, 1, 3, 3, 2, 4, 0, 4, 2, 1, 4, 4, 1, 3, 0, 0, 0, 1, 3], ); test( &[0; 40], &[123456, 789012], 10, &[3, 3, 8, 8, 7, 8, 0, 7, 3, 6, 2, 7, 5, 0, 0, 8], ); test( &[0; 40], &[123456, 789012], 123, &[7, 117, 75, 111, 16, 62, 88, 96], ); test( &[0; 40], &[123456, 789012], 255, &[12, 82, 251, 166, 147, 176, 78], ); // - xs_len >= GET_STR_PRECOMPUTE_THRESHOLD // - power != 1 in limbs_choose_power_table_algorithm // - number_of_powers > 1 in limbs_choose_power_table_algorithm // - pow.odd() in limbs_choose_power_table_algorithm // - n != pow << (i - 1) in limbs_choose_power_table_algorithm // - pow.even() in limbs_choose_power_table_algorithm // - n == pow << (i - 1) in limbs_choose_power_table_algorithm // - n == pow << (i - 1) && pow.odd() in limbs_choose_power_table_algorithm // - mul_cost > div_cost in limbs_choose_power_table_algorithm // - number_of_powers > 0 in limbs_compute_power_table_using_div // - digits_in_base == exp in limbs_compute_power_table_using_div // - digits_in_base != exp in limbs_compute_power_table_using_div // - remainder[adjust] == 0 && remainder[adjust + // 1].divisible_by_power_of_2(big_base_trailing_zeros) in limbs_compute_power_table_using_div // - xs_len >= GET_STR_DC_THRESHOLD in limbs_to_digits_small_base_divide_and_conquer // - xs_len > total_len || xs_len == total_len && limbs_cmp_same_length(&xs[shift..], // power.power) == Less in limbs_to_digits_small_base_divide_and_conquer // - len == 0 in limbs_to_digits_small_base_divide_and_conquer // - xs_len < GET_STR_DC_THRESHOLD in limbs_to_digits_small_base_divide_and_conquer // - xs_len != 0 in limbs_to_digits_small_base_divide_and_conquer // - xs_len >= GET_STR_DC_THRESHOLD && len != 0 test( &[0; 180], &[ 3056215344, 3478498987, 1525628527, 2940636569, 2793889044, 628858201, 4120826843, 1202551139, 2048559663, 3875755114, 2364980673, 2383732604, 3991426155, 229530160, 2263981142, 3298086542, 1508261462, 3566023571, 3747437734, 2439671349, 1387876207, 4019823972, 2986550141, 1187172695, 3025136315, 1183784222, 4211004667, 564539785, 1644122167, 999423211, 806938404, 10860543, 3458492920, 1199271248, 1169727513, 2600131941, 1298866326, ], 104, &[ 7, 102, 41, 15, 79, 28, 23, 19, 82, 89, 32, 45, 23, 94, 68, 1, 5, 96, 34, 31, 47, 91, 9, 77, 70, 30, 32, 44, 67, 88, 51, 17, 18, 55, 66, 74, 61, 95, 51, 9, 76, 7, 12, 75, 82, 103, 16, 83, 92, 84, 48, 98, 79, 55, 50, 30, 40, 36, 56, 86, 60, 54, 92, 39, 68, 26, 46, 76, 15, 25, 98, 43, 62, 102, 40, 94, 59, 55, 52, 77, 52, 46, 18, 28, 12, 23, 49, 9, 30, 64, 53, 49, 39, 51, 51, 26, 3, 68, 82, 13, 35, 58, 44, 88, 58, 85, 63, 101, 42, 103, 20, 55, 48, 10, 64, 21, 48, 48, 10, 58, 5, 78, 48, 69, 20, 76, 63, 67, 50, 96, 39, 12, 47, 23, 6, 39, 17, 95, 40, 15, 3, 32, 68, 95, 82, 10, 86, 47, 53, 59, 74, 90, 47, 81, 3, 45, 0, 76, 37, 42, 61, 48, 62, 82, 64, 72, 87, 37, 56, 56, 32, 88, 11, 29, 52, 74, 32, ], ); // - n == pow << (i - 1) && pow.even() in limbs_choose_power_table_algorithm test( &[0; 180], &[ 4069654318, 200234362, 1446122636, 2556884733, 1171369997, 2416514207, 1914789404, 1066230418, 3700758050, 369490702, 4239134808, 1298432969, 1334078642, 1406451364, 1566734589, 43717764, 349561564, 1067107870, 957081235, 2721095071, 134596014, 1764968880, 2804491477, 129578595, 3283664828, 3844511094, 823049706, 3918883322, 4090685182, 2698902066, 3293373129, 2585973756, 1955397356, 2047755454, 2010607731, 254977406, ], 98, &[ 11, 94, 75, 18, 50, 96, 56, 88, 85, 90, 66, 93, 13, 88, 39, 25, 83, 68, 29, 41, 42, 96, 90, 41, 59, 94, 15, 83, 29, 33, 61, 34, 20, 3, 95, 79, 36, 55, 65, 18, 5, 32, 85, 65, 66, 68, 86, 97, 17, 15, 45, 77, 91, 86, 25, 25, 29, 88, 40, 49, 31, 65, 77, 32, 67, 24, 30, 68, 32, 71, 77, 10, 14, 33, 78, 67, 70, 79, 32, 48, 4, 13, 12, 38, 21, 72, 31, 89, 96, 14, 90, 76, 40, 85, 8, 42, 9, 17, 58, 88, 97, 2, 61, 27, 41, 88, 66, 96, 27, 57, 34, 23, 26, 29, 76, 13, 69, 17, 77, 54, 36, 42, 60, 48, 27, 66, 80, 15, 9, 10, 89, 85, 21, 73, 48, 15, 8, 83, 75, 42, 97, 73, 49, 81, 11, 83, 41, 65, 82, 92, 50, 81, 27, 80, 19, 31, 58, 11, 63, 52, 58, 89, 56, 15, 19, 1, 88, 97, 54, 92, 60, 81, 85, 64, ], ); // - mul_cost <= div_cost in limbs_choose_power_table_algorithm // - exponents[0] != chars_per_limb << number_of_powers in limbs_compute_power_table_using_mul // - (digits_in_base + chars_per_limb) << (power_len - 2) > exponents[0] in // limbs_compute_power_table_using_mul // - (digits_in_base + chars_per_limb) << i > exponents[0] in // limbs_compute_power_table_using_mul // - row.digits_in_base < exponent in limbs_compute_power_table_using_mul // - (digits_in_base + chars_per_limb) << i <= exponents[0] in // limbs_compute_power_table_using_mul // - row.digits_in_base >= exponent in limbs_compute_power_table_using_mul test( &[0; 150], &[ 2679239519, 721774729, 553558153, 2694879530, 315361326, 1002777083, 3532473858, 3891803964, 3091255938, 1810962291, 792542145, 3504464685, 3414416050, 3265802575, 165631340, 3322240994, 1491277551, 2663783343, 3865601021, 953928172, 851798883, 3314281119, 2412275729, 3065107875, 530046998, 3405323797, 3741488431, 151251893, 3569252307, 689124400, 3633309617, 1796271003, 2766831787, ], 185, &[ 1, 177, 172, 157, 179, 24, 121, 151, 101, 53, 20, 0, 32, 16, 183, 70, 103, 158, 81, 44, 98, 4, 131, 48, 3, 51, 74, 4, 65, 14, 155, 158, 26, 4, 61, 41, 45, 37, 13, 181, 116, 160, 63, 79, 91, 62, 45, 26, 140, 138, 144, 155, 65, 152, 63, 82, 38, 110, 34, 170, 107, 154, 167, 88, 45, 183, 23, 18, 75, 80, 104, 181, 46, 180, 172, 14, 30, 30, 37, 120, 2, 108, 166, 83, 83, 28, 144, 52, 157, 117, 57, 41, 66, 130, 94, 44, 35, 108, 25, 119, 99, 57, 28, 18, 53, 123, 74, 124, 108, 7, 115, 165, 112, 99, 93, 20, 13, 103, 9, 168, 57, 104, 133, 95, 140, 54, 118, 45, 116, 40, 105, 24, 179, 184, 15, 170, 168, 145, 42, 134, 41, ], ); // - (digits_in_base + chars_per_limb) << (power_len - 2) <= exponents[0] in // limbs_compute_power_table_using_mul test( &[0; 210], &[ 3460366518, 3248332038, 2411832328, 3680172951, 1648892566, 683827580, 1099145716, 3806372981, 2081403902, 2042441279, 575787637, 419553684, 2052335552, 545288482, 448081444, 2074676634, 783644738, 65453313, 1428854749, 3138519856, 870590090, 1920461474, 1804692757, 2629850054, 3724483390, 2876018746, 592000573, 3317750917, 3395943485, 823080054, 3857418097, 892494948, 1415289101, 2374957426, 803534376, 3410480407, 409051133, 4152156958, 1644919284, 1302252976, 2090652159, 3065750551, 2916695391, 2276338541, 3864821397, 4050961189, ], 152, &[ 1, 76, 32, 138, 63, 89, 114, 3, 9, 90, 74, 101, 16, 92, 47, 39, 0, 48, 102, 113, 15, 123, 139, 33, 129, 140, 4, 93, 65, 38, 108, 102, 118, 40, 45, 109, 94, 140, 133, 120, 43, 46, 72, 119, 10, 142, 36, 67, 80, 76, 70, 73, 12, 148, 117, 51, 24, 25, 36, 50, 141, 1, 38, 50, 31, 72, 115, 75, 124, 151, 113, 74, 58, 26, 126, 60, 26, 129, 25, 12, 94, 98, 77, 26, 32, 150, 26, 51, 141, 89, 63, 81, 15, 114, 11, 82, 3, 25, 129, 54, 111, 75, 75, 136, 0, 30, 145, 127, 74, 62, 149, 15, 92, 117, 142, 92, 8, 30, 20, 32, 48, 79, 23, 150, 144, 71, 119, 0, 107, 28, 18, 92, 53, 72, 70, 32, 146, 17, 49, 72, 134, 134, 31, 40, 35, 76, 15, 53, 31, 47, 93, 51, 120, 125, 49, 149, 54, 55, 26, 149, 39, 86, 138, 130, 64, 76, 86, 146, 64, 106, 69, 34, 97, 46, 104, 149, 114, 129, 120, 109, 124, 12, 111, 71, 21, 13, 42, 146, 4, 60, 98, 98, 150, 134, 7, 86, 114, 118, 84, 3, 85, 127, 102, 102, ], ); // - exponents[0] == chars_per_limb << number_of_powers in limbs_compute_power_table_using_mul test( &[0; 160], &[ 2728906224, 1449576955, 3973690369, 849270619, 586255891, 923328784, 2717698803, 1477432292, 3710905696, 2207709497, 4292599247, 2411645706, 177966862, 3982000026, 1307696936, 903442, 3277385094, 3213674759, 2739559583, 1152850273, 3029194225, 1704802500, 2548066116, 1747267099, 2072192542, 3912866034, 1575257763, 2717691639, 3897187509, 2362053000, 1191544518, ], 80, &[ 15, 18, 69, 61, 21, 59, 53, 35, 24, 20, 38, 58, 36, 48, 27, 15, 30, 14, 30, 16, 63, 8, 66, 12, 57, 9, 78, 68, 12, 13, 47, 9, 77, 51, 3, 72, 15, 59, 71, 67, 20, 50, 65, 15, 40, 3, 72, 79, 23, 9, 65, 43, 63, 57, 26, 54, 36, 78, 51, 25, 1, 22, 56, 53, 20, 45, 56, 42, 69, 71, 76, 2, 53, 75, 58, 14, 24, 40, 4, 60, 6, 1, 29, 56, 50, 20, 47, 3, 63, 52, 45, 66, 43, 7, 58, 49, 4, 73, 35, 51, 14, 35, 37, 28, 40, 76, 12, 60, 17, 65, 67, 67, 79, 78, 79, 18, 24, 36, 20, 41, 79, 51, 21, 42, 38, 41, 39, 52, 68, 74, 59, 30, 15, 21, 48, 26, 71, 48, 33, 46, 22, 9, 2, 78, 33, 21, 76, 4, 74, 72, 18, 37, 28, 56, 64, 44, 48, ], ); } fn limbs_to_digits_small_base_properties_helper< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >() { let mut config = GenConfig::new(); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_stripe_d", 1); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); unsigned_vec_unsigned_unsigned_vec_triple_gen_var_1::().test_properties_with_config( &config, |(mut out, base, mut xs)| { let old_out = out.clone(); let old_xs = xs.clone(); let out_len = limbs_to_digits_small_base(&mut out, base, &mut xs, None); let result = out.clone(); verify_limbs_to_digits_small_base(&old_out, &old_xs, base, out_len, &result); let mut xs = old_xs.clone(); assert_eq!( limbs_to_digits_small_base(&mut out, base, &mut xs, Some(PowerTableAlgorithm::Mul)), out_len ); assert_eq!(out, result); let mut xs = old_xs; assert_eq!( limbs_to_digits_small_base(&mut out, base, &mut xs, Some(PowerTableAlgorithm::Div)), out_len ); assert_eq!(out, result); }, ); } #[test] fn limbs_to_digits_small_base_properties() { apply_fn_to_unsigneds!(limbs_to_digits_small_base_properties_helper); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_to_digits_basecase() { fn test TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned>( xs_before: &[Limb], base: Limb, out: &[T], ) { let mut xs = xs_before.to_vec(); let mut digits = Vec::new(); limbs_to_digits_basecase::(&mut digits, &mut xs, base); assert_eq!(digits, out); let mut digits = Vec::new(); to_digits_asc_naive_primitive(&mut digits, &Natural::from_limbs_asc(xs_before), base); assert_eq!(digits.into_iter().map(T::exact_from).collect_vec(), out); } test::(&[0, 0], 64, &[]); test::(&[2, 0], 64, &[2]); test::(&[123, 0], 8, &[3, 7, 1]); test::(&[1000000, 0], 256, &[64, 66, 15]); test::(&[1000000, 0], 256, &[64, 66, 15]); test::(&[1000, 0], 2, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1]); test::(&[0, 0], 3, &[]); test::(&[2, 0], 3, &[2]); test::(&[123456, 0], 3, &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2]); test::(&[123456, 0], 10, &[6, 5, 4, 3, 2, 1]); test::(&[123456, 0], 100, &[56, 34, 12]); test::(&[123456, 0], 123, &[87, 19, 8]); test::( &[123, 456, 789], 2, &[ 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, ], ); test::( &[123, 456, 789], 3, &[ 0, 0, 2, 2, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 1, 0, 0, 2, 0, 2, 0, 0, 2, 0, 2, 2, 0, 0, 1, 1, 0, 1, 2, 0, 0, 2, 2, 0, 1, 0, 0, 0, 1, 2, 2, 1, 1, ], ); test::( &[123, 456, 789], 10, &[3, 2, 1, 2, 1, 3, 1, 4, 3, 5, 1, 1, 6, 7, 0, 1, 8, 4, 4, 5, 5, 4, 1], ); test::( &[123, 456, 789], 100, &[23, 21, 31, 41, 53, 11, 76, 10, 48, 54, 45, 1], ); test::( &[123, 456, 789], 128, &[123, 0, 0, 0, 0, 57, 0, 0, 0, 42, 12], ); test::( &[123, 456, 789], Limb::power_of_2(16), &[123, 0, 456, 0, 789], ); } fn limbs_to_digits_basecase_fail_helper + PrimitiveUnsigned>() { assert_panic!(limbs_to_digits_basecase::(&mut Vec::new(), &mut [1], 2)); assert_panic!(limbs_to_digits_basecase::( &mut Vec::new(), &mut [123, 456], 0 )); assert_panic!(limbs_to_digits_basecase::( &mut Vec::new(), &mut [123, 456], 1 )); } #[test] fn limbs_to_digits_basecase_fail() { apply_fn_to_unsigneds!(limbs_to_digits_basecase_fail_helper); assert_panic!(limbs_to_digits_basecase::( &mut Vec::new(), &mut [123, 456], 300 )); } fn limbs_to_digits_basecase_properties_helper< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >() where Limb: SaturatingFrom, { let mut config = GenConfig::new(); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); config.insert("mean_stripe_d", 1); config.insert("mean_length_n", 32); config.insert("mean_length_d", 1); unsigned_vec_unsigned_pair_gen_var_4::().test_properties_with_config( &config, |(mut xs, base)| { let xs_old = xs.clone(); let mut digits = Vec::new(); limbs_to_digits_basecase::(&mut digits, &mut xs, base); let mut digits_alt = Vec::new(); to_digits_asc_naive_primitive(&mut digits_alt, &Natural::from_limbs_asc(&xs_old), base); let digits_alt = digits_alt.into_iter().map(T::exact_from).collect_vec(); assert_eq!(digits, digits_alt); }, ); } #[test] fn limbs_to_digits_basecase_properties() { apply_fn_to_unsigneds!(limbs_to_digits_basecase_properties_helper); } #[test] fn test_to_digits_asc_limb() { fn test TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned>( x: &str, base: Limb, out: &[T], ) where Limb: Digits, Natural: From + PowerOf2Digits, { let x = Natural::from_str(x).unwrap(); assert_eq!(to_digits_asc_limb::(&x, base), out); let mut digits_alt = Vec::new(); to_digits_asc_naive_primitive(&mut digits_alt, &x, T::exact_from(base)); assert_eq!(digits_alt, out); } test::("0", 10, &[]); test::("0", 16, &[]); // - base is not a power of 2 // - x is small test::("123", 10, &[3, 2, 1]); // - base is a power of 2 test::("123", 8, &[3, 7, 1]); // - x is large // - x is large and base < 256 test::( "1473250819553359898729024041508", 77, &[44, 55, 51, 10, 43, 13, 36, 15, 70, 15, 19, 57, 50, 10, 22, 74], ); // - x is large and base >= 256 // - to_digits_asc_divide_and_conquer_limb: many digits // - to_digits_asc_divide_and_conquer_limb: few digits // - base <= SQRT_MAX_LIMB // - to_digits_asc_divide_and_conquer_limb: base <= SQRT_MAX_LIMB and x small // - to_digits_asc_divide_and_conquer_limb: q != 0 // - to_digits_asc_divide_and_conquer_limb: zero padding // - to_digits_asc_divide_and_conquer_limb: base <= SQRT_MAX_LIMB and x large test::( "1000000000000000000000000000000000000000000000000000000000000", 1000, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1001, &[ 1, 981, 189, 862, 839, 516, 706, 596, 767, 333, 404, 392, 677, 683, 644, 550, 825, 866, 188, 981, ], ); // - to_digits_asc_divide_and_conquer_limb: base > SQRT_MAX_LIMB test::( "1000000000000000000000000000000000000000000000000000000000000", 123456, &[115456, 7508, 27948, 11540, 30637, 92024, 26412, 41276, 18791, 86861, 49669, 9848], ); // - to_digits_asc_divide_and_conquer_limb: q == 0 test::( "958147186852538842877959980138243879940342867265688956449364129", 9238, &[ 1297, 1928, 2066, 7131, 5213, 6502, 1707, 1758, 138, 6317, 2051, 6308, 402, 1611, 277, 3146, ], ); } fn to_digits_asc_limb_fail_helper< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >() where Limb: Digits, Natural: From + PowerOf2Digits, { assert_panic!(to_digits_asc_limb::(&Natural::exact_from(10), 0)); assert_panic!(to_digits_asc_limb::(&Natural::exact_from(10), 1)); } #[test] fn to_digits_asc_limb_fail() { apply_fn_to_unsigneds!(to_digits_asc_limb_fail_helper); assert_panic!(to_digits_asc_limb::(&Natural::from(10u32), 1000)); } fn to_digits_asc_limb_properties_helper< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >() where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_unsigned_pair_gen_var_1::().test_properties_with_config( &config, |(x, base)| { let digits = to_digits_asc_limb::(&x, base); let mut digits_alt = Vec::new(); to_digits_asc_naive_primitive(&mut digits_alt, &x, T::exact_from(base)); assert_eq!(digits, digits_alt); assert_eq!( to_digits_desc_limb::(&x, base) .into_iter() .rev() .collect_vec(), digits ); if !digits.is_empty() { assert_ne!(*digits.last().unwrap(), T::ZERO); } }, ); } #[test] fn to_digits_asc_limb_properties() { apply_fn_to_unsigneds!(to_digits_asc_limb_properties_helper); } #[test] fn test_to_digits_desc_limb() { fn test TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned>( x: &str, base: Limb, out: &[T], ) where Limb: Digits, Natural: From + PowerOf2Digits, { let x = Natural::from_str(x).unwrap(); assert_eq!(to_digits_desc_limb::(&x, base), out); } test::("0", 10, &[]); test::("0", 16, &[]); test::("123", 10, &[1, 2, 3]); test::("123", 8, &[1, 7, 3]); test::( "1473250819553359898729024041508", 77, &[74, 22, 10, 50, 57, 19, 15, 70, 15, 36, 13, 43, 10, 51, 55, 44], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1000, &[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1001, &[ 981, 188, 866, 825, 550, 644, 683, 677, 392, 404, 333, 767, 596, 706, 516, 839, 862, 189, 981, 1, ], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 123456, &[9848, 49669, 86861, 18791, 41276, 26412, 92024, 30637, 11540, 27948, 7508, 115456], ); test::( "958147186852538842877959980138243879940342867265688956449364129", 9238, &[ 3146, 277, 1611, 402, 6308, 2051, 6317, 138, 1758, 1707, 6502, 5213, 7131, 2066, 1928, 1297, ], ); } fn to_digits_desc_limb_fail_helper< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >() where Limb: Digits, Natural: From + PowerOf2Digits, { assert_panic!(to_digits_desc_limb::(&Natural::exact_from(10), 0)); assert_panic!(to_digits_desc_limb::(&Natural::exact_from(10), 1)); } #[test] fn to_digits_desc_limb_fail() { apply_fn_to_unsigneds!(to_digits_desc_limb_fail_helper); assert_panic!(to_digits_desc_limb::(&Natural::from(10u32), 1000)); } fn to_digits_desc_limb_properties_helper< T: for<'a> TryFrom<&'a Natural> + ConvertibleFrom + PrimitiveUnsigned, >() where Limb: Digits + SaturatingFrom, Natural: From + PowerOf2Digits, { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_unsigned_pair_gen_var_1::().test_properties_with_config( &config, |(x, base)| { let digits = to_digits_desc_limb::(&x, base); assert_eq!( to_digits_asc_limb::(&x, base) .into_iter() .rev() .collect_vec(), digits ); if !digits.is_empty() { assert_ne!(digits[0], T::ZERO); } }, ); } #[test] fn to_digits_desc_limb_properties() { apply_fn_to_unsigneds!(to_digits_desc_limb_properties_helper); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_to_digits_asc_large() { fn test(x: &str, base: &str, out: &[&str]) { let x = Natural::from_str(x).unwrap(); let base = Natural::from_str(base).unwrap(); let out = out .iter() .map(|s| Natural::from_str(s).unwrap()) .collect_vec(); assert_eq!(to_digits_asc_large(&x, &base), out); let mut digits_alt = Vec::new(); to_digits_asc_naive(&mut digits_alt, &x, &base); assert_eq!(digits_alt, out); } // - x >= base // - base is not a power of 2 // - bits / base.significant_bits() < TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD test( "1000000000000", "10", &["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1"], ); // - base is a power of 2 test( "1000000000000", "16", &["0", "0", "0", "1", "5", "10", "4", "13", "8", "14"], ); // - x < base test("1000000000000", "1000000000000000", &["1000000000000"]); // - bits / base.significant_bits() >= TO_DIGITS_DIVIDE_AND_CONQUER_THRESHOLD // - q != 0 test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6", &[ "4", "1", "3", "2", "3", "2", "1", "4", "2", "5", "3", "0", "5", "1", "5", "3", "5", "2", "4", "5", "1", "3", "1", "5", "5", "1", "5", "4", "2", "1", "2", "2", "2", "1", "2", "4", "3", "2", "3", "2", "5", "0", "4", "5", "5", "3", "4", "1", "1", "3", "3", "4", "5", "0", "4", "5", "0", "4", "4", "2", "2", "5", "5", "2", "1", "5", "4", "0", "3", "4", "1", "3", "5", "0", "1", "3", "0", "1", "1", "4", "4", "5", "1", "2", "0", "5", "3", "0", "1", "1", "4", "5", "0", "3", "2", "5", "3", "5", "0", "5", "2", "0", "0", "4", "1", "5", "3", "1", "4", "1", "5", "5", "1", "0", "2", "5", "3", "2", "1", "2", "3", "2", "2", "3", "0", "2", "4", "4", "0", "1", "2", "0", "3", "3", "2", "2", "5", "4", "5", "1", "2", "2", "5", "1", "5", "3", "0", "0", "2", "5", "3", "5", "2", "0", "1", "0", "3", "4", "0", "1", "5", "4", "1", "1", "0", "1", "1", "3", "5", "3", "2", "3", "0", "1", "3", "0", "5", "2", "3", "5", "3", "2", "5", "2", "5", "0", "2", "3", "3", "1", "3", "3", "0", "0", "2", "3", "0", "3", "0", "5", "3", "0", "0", "4", "1", "5", "1", "4", "4", "1", "5", "4", "0", "0", "4", "1", "2", "1", "3", "5", "1", "5", "5", "0", "1", ], ); // - pad with zeros test( "14974892748479131847778931724116484851265511358392776602889616274416063303", "3", &[ "0", "2", "1", "1", "1", "2", "0", "2", "1", "2", "1", "1", "2", "0", "2", "2", "2", "0", "0", "1", "0", "1", "1", "2", "1", "1", "0", "0", "2", "1", "0", "0", "0", "0", "1", "2", "1", "0", "1", "0", "2", "1", "1", "1", "1", "1", "0", "0", "0", "0", "2", "1", "1", "0", "2", "1", "1", "0", "2", "0", "0", "1", "2", "0", "2", "0", "0", "0", "1", "2", "2", "0", "0", "2", "2", "2", "2", "1", "0", "2", "0", "0", "1", "1", "1", "0", "1", "2", "2", "0", "2", "2", "2", "0", "2", "1", "1", "1", "1", "0", "1", "2", "1", "1", "0", "2", "0", "1", "0", "1", "0", "1", "1", "2", "0", "2", "1", "2", "2", "0", "1", "1", "1", "2", "0", "2", "0", "0", "2", "0", "0", "1", "1", "2", "2", "0", "2", "1", "1", "2", "1", "1", "1", "1", "0", "1", "2", "0", "1", "1", "1", "1", "1", "1", ], ); // - q == 0 test( "643945257796761196320314690988316858252541574945689186182369731847117890385280572047834937\ 1883212246436232738680605124294949600205450044993253033167972343988333612737978764297848348\ 2665822115523011210267845467229157815194234251375826930137780574470438350033031660616757791\ 61", "7", &[ "4", "5", "1", "4", "5", "6", "0", "2", "4", "6", "2", "0", "1", "0", "3", "6", "4", "3", "1", "4", "2", "6", "4", "4", "0", "2", "1", "0", "3", "3", "2", "0", "3", "5", "4", "1", "3", "4", "4", "3", "5", "6", "4", "1", "6", "0", "2", "2", "5", "0", "5", "0", "5", "4", "0", "5", "3", "5", "0", "0", "3", "6", "1", "5", "4", "4", "1", "2", "1", "4", "2", "0", "0", "1", "4", "3", "2", "0", "3", "5", "2", "6", "5", "5", "0", "2", "1", "6", "5", "2", "5", "0", "6", "6", "4", "3", "1", "6", "0", "6", "1", "3", "1", "5", "4", "3", "0", "5", "2", "6", "5", "2", "0", "3", "3", "1", "3", "5", "3", "1", "1", "3", "2", "0", "1", "5", "6", "0", "1", "6", "4", "4", "5", "4", "4", "2", "0", "2", "5", "6", "4", "5", "2", "2", "4", "4", "0", "6", "5", "4", "2", "1", "6", "0", "2", "0", "4", "2", "5", "6", "2", "5", "1", "5", "3", "3", "5", "1", "0", "2", "5", "4", "1", "2", "6", "6", "2", "0", "6", "1", "1", "1", "4", "0", "1", "5", "4", "0", "6", "6", "4", "6", "1", "3", "0", "3", "3", "4", "6", "2", "3", "5", "1", "4", "4", "6", "3", "2", "4", "3", "0", "3", "2", "6", "2", "4", "3", "6", "6", "6", "6", "4", "4", "3", "6", "6", "3", "3", "5", "5", "1", "0", "1", "0", "3", "6", "5", "3", "2", "1", "3", "1", "3", "2", "4", "6", "1", "5", "6", "2", "6", "2", "5", "0", "6", "0", "0", "3", "4", "0", "6", "3", "5", "2", "5", "5", "4", "1", "3", "4", "4", "2", "2", "3", "1", "6", "2", "1", "4", "1", "5", "5", "6", "3", "6", "3", "6", "4", "4", "5", "2", "3", "1", "6", "2", "1", "0", "0", "5", "0", "2", "5", "5", "4", "0", "5", "6", "5", "2", "2", "0", "3", "6", "5", "2", "4", "6", "4", "3", "6", "4", "4", "6", "6", ], ); test("1000000000000", "10000000000", &["0", "100"]); test( "10000000000000000000000000000000", "34359738368", &["27917287424", "18657454436", "8470329472"], ); test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6000000000", &[ "4373186134", "2564485756", "2124820161", "4270626619", "5254372654", "713959034", "4750044302", "5833014701", "978351288", "4288991795", "972424917", "1439538405", "5308114100", "1115837958", "2267585072", "4579628351", "3319271253", "139021832", ], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_to_digits_desc_large() { fn test(x: &str, base: &str, out: &[&str]) { let x = Natural::from_str(x).unwrap(); let base = Natural::from_str(base).unwrap(); let out = out .iter() .map(|s| Natural::from_str(s).unwrap()) .collect_vec(); assert_eq!(to_digits_desc_large(&x, &base), out); } test( "1000000000000", "10", &["1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"], ); test( "1000000000000", "16", &["14", "8", "13", "4", "10", "5", "1", "0", "0", "0"], ); test("1000000000000", "1000000000000000", &["1000000000000"]); test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6", &[ "1", "0", "5", "5", "1", "5", "3", "1", "2", "1", "4", "0", "0", "4", "5", "1", "4", "4", "1", "5", "1", "4", "0", "0", "3", "5", "0", "3", "0", "3", "2", "0", "0", "3", "3", "1", "3", "3", "2", "0", "5", "2", "5", "2", "3", "5", "3", "2", "5", "0", "3", "1", "0", "3", "2", "3", "5", "3", "1", "1", "0", "1", "1", "4", "5", "1", "0", "4", "3", "0", "1", "0", "2", "5", "3", "5", "2", "0", "0", "3", "5", "1", "5", "2", "2", "1", "5", "4", "5", "2", "2", "3", "3", "0", "2", "1", "0", "4", "4", "2", "0", "3", "2", "2", "3", "2", "1", "2", "3", "5", "2", "0", "1", "5", "5", "1", "4", "1", "3", "5", "1", "4", "0", "0", "2", "5", "0", "5", "3", "5", "2", "3", "0", "5", "4", "1", "1", "0", "3", "5", "0", "2", "1", "5", "4", "4", "1", "1", "0", "3", "1", "0", "5", "3", "1", "4", "3", "0", "4", "5", "1", "2", "5", "5", "2", "2", "4", "4", "0", "5", "4", "0", "5", "4", "3", "3", "1", "1", "4", "3", "5", "5", "4", "0", "5", "2", "3", "2", "3", "4", "2", "1", "2", "2", "2", "1", "2", "4", "5", "1", "5", "5", "1", "3", "1", "5", "4", "2", "5", "3", "5", "1", "5", "0", "3", "5", "2", "4", "1", "2", "3", "2", "3", "1", "4", ], ); test( "14974892748479131847778931724116484851265511358392776602889616274416063303", "3", &[ "1", "1", "1", "1", "1", "1", "0", "2", "1", "0", "1", "1", "1", "1", "2", "1", "1", "2", "0", "2", "2", "1", "1", "0", "0", "2", "0", "0", "2", "0", "2", "1", "1", "1", "0", "2", "2", "1", "2", "0", "2", "1", "1", "0", "1", "0", "1", "0", "2", "0", "1", "1", "2", "1", "0", "1", "1", "1", "1", "2", "0", "2", "2", "2", "0", "2", "2", "1", "0", "1", "1", "1", "0", "0", "2", "0", "1", "2", "2", "2", "2", "0", "0", "2", "2", "1", "0", "0", "0", "2", "0", "2", "1", "0", "0", "2", "0", "1", "1", "2", "0", "1", "1", "2", "0", "0", "0", "0", "1", "1", "1", "1", "1", "2", "0", "1", "0", "1", "2", "1", "0", "0", "0", "0", "1", "2", "0", "0", "1", "1", "2", "1", "1", "0", "1", "0", "0", "2", "2", "2", "0", "2", "1", "1", "2", "1", "2", "0", "2", "1", "1", "1", "2", "0", ], ); test( "643945257796761196320314690988316858252541574945689186182369731847117890385280572047834937\ 1883212246436232738680605124294949600205450044993253033167972343988333612737978764297848348\ 2665822115523011210267845467229157815194234251375826930137780574470438350033031660616757791\ 61", "7", &[ "6", "6", "4", "4", "6", "3", "4", "6", "4", "2", "5", "6", "3", "0", "2", "2", "5", "6", "5", "0", "4", "5", "5", "2", "0", "5", "0", "0", "1", "2", "6", "1", "3", "2", "5", "4", "4", "6", "3", "6", "3", "6", "5", "5", "1", "4", "1", "2", "6", "1", "3", "2", "2", "4", "4", "3", "1", "4", "5", "5", "2", "5", "3", "6", "0", "4", "3", "0", "0", "6", "0", "5", "2", "6", "2", "6", "5", "1", "6", "4", "2", "3", "1", "3", "1", "2", "3", "5", "6", "3", "0", "1", "0", "1", "5", "5", "3", "3", "6", "6", "3", "4", "4", "6", "6", "6", "6", "3", "4", "2", "6", "2", "3", "0", "3", "4", "2", "3", "6", "4", "4", "1", "5", "3", "2", "6", "4", "3", "3", "0", "3", "1", "6", "4", "6", "6", "0", "4", "5", "1", "0", "4", "1", "1", "1", "6", "0", "2", "6", "6", "2", "1", "4", "5", "2", "0", "1", "5", "3", "3", "5", "1", "5", "2", "6", "5", "2", "4", "0", "2", "0", "6", "1", "2", "4", "5", "6", "0", "4", "4", "2", "2", "5", "4", "6", "5", "2", "0", "2", "4", "4", "5", "4", "4", "6", "1", "0", "6", "5", "1", "0", "2", "3", "1", "1", "3", "5", "3", "1", "3", "3", "0", "2", "5", "6", "2", "5", "0", "3", "4", "5", "1", "3", "1", "6", "0", "6", "1", "3", "4", "6", "6", "0", "5", "2", "5", "6", "1", "2", "0", "5", "5", "6", "2", "5", "3", "0", "2", "3", "4", "1", "0", "0", "2", "4", "1", "2", "1", "4", "4", "5", "1", "6", "3", "0", "0", "5", "3", "5", "0", "4", "5", "0", "5", "0", "5", "2", "2", "0", "6", "1", "4", "6", "5", "3", "4", "4", "3", "1", "4", "5", "3", "0", "2", "3", "3", "0", "1", "2", "0", "4", "4", "6", "2", "4", "1", "3", "4", "6", "3", "0", "1", "0", "2", "6", "4", "2", "0", "6", "5", "4", "1", "5", "4", ], ); test("1000000000000", "10000000000", &["100", "0"]); test( "10000000000000000000000000000000", "34359738368", &["8470329472", "18657454436", "27917287424"], ); test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6000000000", &[ "139021832", "3319271253", "4579628351", "2267585072", "1115837958", "5308114100", "1439538405", "972424917", "4288991795", "978351288", "5833014701", "4750044302", "713959034", "5254372654", "4270626619", "2124820161", "2564485756", "4373186134", ], ); } #[test] fn to_digits_asc_large_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); natural_pair_gen_var_1().test_properties_with_config(&config, |(x, base)| { let digits = to_digits_asc_large(&x, &base); let mut digits_alt = Vec::new(); to_digits_asc_naive(&mut digits_alt, &x, &base); assert_eq!(digits, digits_alt); assert_eq!( to_digits_desc_large(&x, &base) .into_iter() .rev() .collect_vec(), digits ); if !digits.is_empty() { assert_ne!(*digits.last().unwrap(), 0); } }); } #[test] fn to_digits_desc_large_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); natural_pair_gen_var_1().test_properties_with_config(&config, |(x, base)| { let digits = to_digits_desc_large(&x, &base); assert_eq!( to_digits_asc_large(&x, &base) .into_iter() .rev() .collect_vec(), digits ); if !digits.is_empty() { assert_ne!(digits[0], 0); } }); } #[test] fn test_to_digits_asc_unsigned() { fn test TryFrom<&'a Natural> + PrimitiveUnsigned>(x: &str, base: T, out: &[T]) where Natural: Digits + From, { let x = Natural::from_str(x).unwrap(); assert_eq!(x.to_digits_asc(&base), out); let mut digits_alt = Vec::new(); to_digits_asc_naive_primitive(&mut digits_alt, &x, base); assert_eq!(digits_alt, out); } test::("0", 10, &[]); test::("0", 16, &[]); test::("123", 10, &[3, 2, 1]); test::("123", 8, &[3, 7, 1]); test::( "1473250819553359898729024041508", 77, &[44, 55, 51, 10, 43, 13, 36, 15, 70, 15, 19, 57, 50, 10, 22, 74], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1000, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1001, &[ 1, 981, 189, 862, 839, 516, 706, 596, 767, 333, 404, 392, 677, 683, 644, 550, 825, 866, 188, 981, ], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 123456, &[115456, 7508, 27948, 11540, 30637, 92024, 26412, 41276, 18791, 86861, 49669, 9848], ); test::( "958147186852538842877959980138243879940342867265688956449364129", 9238, &[ 1297, 1928, 2066, 7131, 5213, 6502, 1707, 1758, 138, 6317, 2051, 6308, 402, 1611, 277, 3146, ], ); } fn to_digits_asc_unsigned_fail_helper() where Natural: Digits, { assert_panic!(Natural::from(10u32).to_digits_asc(&T::ZERO)); assert_panic!(Natural::from(10u32).to_digits_asc(&T::ONE)); } #[test] fn to_digits_asc_unsigned_fail() { apply_fn_to_unsigneds!(to_digits_asc_unsigned_fail_helper); } fn to_digits_asc_properties_helper TryFrom<&'a Natural> + PrimitiveUnsigned>() where Limb: Digits, Natural: Digits + From, { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_unsigned_pair_gen_var_2::().test_properties_with_config(&config, |(x, base)| { let digits = x.to_digits_asc(&base); let mut digits_alt = Vec::new(); to_digits_asc_naive_primitive(&mut digits_alt, &x, base); assert_eq!(digits_alt, digits); if x != 0 { assert_ne!(*digits.last().unwrap(), T::ZERO); assert_eq!( u64::exact_from(digits.len()), x.floor_log_base(&Natural::from(base)) + 1 ); } assert_eq!( digits.iter().copied().rev().collect_vec(), x.to_digits_desc(&base) ); assert!(digits.iter().all(|&digit| digit < base)); assert_eq!( Natural::from_digits_asc(&base, digits.iter().copied()).unwrap(), x ); let digits_alt = Digits::::to_digits_asc(&x, &Natural::from(base)); assert_eq!( digits_alt .into_iter() .map(|n| T::exact_from(&n)) .collect_vec(), digits ); }); natural_gen().test_properties_with_config(&config, |x| { assert_eq!( x.to_digits_asc(&T::TWO) .into_iter() .map(|digit| digit == T::ONE) .collect_vec(), x.to_bits_asc() ); }); unsigned_gen_var_6().test_properties_with_config(&config, |base| { assert!(Natural::ZERO.to_digits_asc(&base).is_empty()); }); unsigned_pair_gen_var_6::().test_properties(|(u, base)| { let x: Natural = From::from(u); assert_eq!(u.to_digits_asc(&base), x.to_digits_asc(&base)); }); } #[test] fn to_digits_asc_properties() { apply_fn_to_unsigneds!(to_digits_asc_properties_helper); } #[test] fn test_to_digits_desc_unsigned() { fn test(x: &str, base: T, out: &[T]) where Natural: Digits, { let x = Natural::from_str(x).unwrap(); assert_eq!(x.to_digits_desc(&base), out); } test::("0", 10, &[]); test::("0", 16, &[]); test::("123", 10, &[1, 2, 3]); test::("123", 8, &[1, 7, 3]); test::( "1473250819553359898729024041508", 77, &[74, 22, 10, 50, 57, 19, 15, 70, 15, 36, 13, 43, 10, 51, 55, 44], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1000, &[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 1001, &[ 981, 188, 866, 825, 550, 644, 683, 677, 392, 404, 333, 767, 596, 706, 516, 839, 862, 189, 981, 1, ], ); test::( "1000000000000000000000000000000000000000000000000000000000000", 123456, &[9848, 49669, 86861, 18791, 41276, 26412, 92024, 30637, 11540, 27948, 7508, 115456], ); test::( "958147186852538842877959980138243879940342867265688956449364129", 9238, &[ 3146, 277, 1611, 402, 6308, 2051, 6317, 138, 1758, 1707, 6502, 5213, 7131, 2066, 1928, 1297, ], ); } fn to_digits_desc_unsigned_fail_helper() where Natural: Digits, { assert_panic!(Natural::from(10u32).to_digits_desc(&T::ZERO)); assert_panic!(Natural::from(10u32).to_digits_desc(&T::ONE)); } #[test] fn to_digits_desc_unsigned_fail() { apply_fn_to_unsigneds!(to_digits_desc_unsigned_fail_helper); } fn to_digits_desc_properties_helper TryFrom<&'a Natural> + PrimitiveUnsigned>() where Limb: Digits, Natural: Digits + From, { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_unsigned_pair_gen_var_2::().test_properties_with_config(&config, |(x, base)| { let digits = x.to_digits_desc(&base); if x != 0 { assert_ne!(digits[0], T::ZERO); assert_eq!( u64::exact_from(digits.len()), x.floor_log_base(&Natural::from(base)) + 1 ); } assert_eq!( digits.iter().copied().rev().collect_vec(), x.to_digits_asc(&base) ); assert!(digits.iter().all(|&digit| digit < base)); assert_eq!( Natural::from_digits_desc(&base, digits.iter().copied()).unwrap(), x ); let digits_alt = Digits::::to_digits_desc(&x, &Natural::from(base)); assert_eq!( digits_alt .into_iter() .map(|n| T::exact_from(&n)) .collect_vec(), digits ); }); natural_gen().test_properties_with_config(&config, |x| { assert_eq!( x.to_digits_desc(&T::TWO) .into_iter() .map(|digit| digit == T::ONE) .collect_vec(), x.to_bits_desc() ); }); unsigned_gen_var_6().test_properties_with_config(&config, |base| { assert!(Natural::ZERO.to_digits_desc(&base).is_empty()); }); unsigned_pair_gen_var_6::().test_properties(|(u, base)| { let x: Natural = From::from(u); assert_eq!(u.to_digits_desc(&base), x.to_digits_desc(&base)); }); } #[test] fn to_digits_desc_properties() { apply_fn_to_unsigneds!(to_digits_desc_properties_helper); } #[test] fn test_to_digits_asc_natural() { fn test(x: &str, base: &str, out: &[&str]) { let x = Natural::from_str(x).unwrap(); let base = Natural::from_str(base).unwrap(); let out = out .iter() .map(|s| Natural::from_str(s).unwrap()) .collect_vec(); assert_eq!(x.to_digits_asc(&base), out); let mut digits_alt = Vec::new(); to_digits_asc_naive(&mut digits_alt, &x, &base); assert_eq!(digits_alt, out); } test("0", "10", &[]); test("0", "16", &[]); test("123", "10", &["3", "2", "1"]); test("123", "8", &["3", "7", "1"]); test( "1473250819553359898729024041508", "77", &[ "44", "55", "51", "10", "43", "13", "36", "15", "70", "15", "19", "57", "50", "10", "22", "74", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "1000", &[ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "1001", &[ "1", "981", "189", "862", "839", "516", "706", "596", "767", "333", "404", "392", "677", "683", "644", "550", "825", "866", "188", "981", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "123456", &[ "115456", "7508", "27948", "11540", "30637", "92024", "26412", "41276", "18791", "86861", "49669", "9848", ], ); test( "958147186852538842877959980138243879940342867265688956449364129", "9238", &[ "1297", "1928", "2066", "7131", "5213", "6502", "1707", "1758", "138", "6317", "2051", "6308", "402", "1611", "277", "3146", ], ); test( "1000000000000", "10", &["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1"], ); test( "1000000000000", "16", &["0", "0", "0", "1", "5", "10", "4", "13", "8", "14"], ); test("1000000000000", "1000000000000000", &["1000000000000"]); test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6", &[ "4", "1", "3", "2", "3", "2", "1", "4", "2", "5", "3", "0", "5", "1", "5", "3", "5", "2", "4", "5", "1", "3", "1", "5", "5", "1", "5", "4", "2", "1", "2", "2", "2", "1", "2", "4", "3", "2", "3", "2", "5", "0", "4", "5", "5", "3", "4", "1", "1", "3", "3", "4", "5", "0", "4", "5", "0", "4", "4", "2", "2", "5", "5", "2", "1", "5", "4", "0", "3", "4", "1", "3", "5", "0", "1", "3", "0", "1", "1", "4", "4", "5", "1", "2", "0", "5", "3", "0", "1", "1", "4", "5", "0", "3", "2", "5", "3", "5", "0", "5", "2", "0", "0", "4", "1", "5", "3", "1", "4", "1", "5", "5", "1", "0", "2", "5", "3", "2", "1", "2", "3", "2", "2", "3", "0", "2", "4", "4", "0", "1", "2", "0", "3", "3", "2", "2", "5", "4", "5", "1", "2", "2", "5", "1", "5", "3", "0", "0", "2", "5", "3", "5", "2", "0", "1", "0", "3", "4", "0", "1", "5", "4", "1", "1", "0", "1", "1", "3", "5", "3", "2", "3", "0", "1", "3", "0", "5", "2", "3", "5", "3", "2", "5", "2", "5", "0", "2", "3", "3", "1", "3", "3", "0", "0", "2", "3", "0", "3", "0", "5", "3", "0", "0", "4", "1", "5", "1", "4", "4", "1", "5", "4", "0", "0", "4", "1", "2", "1", "3", "5", "1", "5", "5", "0", "1", ], ); test( "14974892748479131847778931724116484851265511358392776602889616274416063303", "3", &[ "0", "2", "1", "1", "1", "2", "0", "2", "1", "2", "1", "1", "2", "0", "2", "2", "2", "0", "0", "1", "0", "1", "1", "2", "1", "1", "0", "0", "2", "1", "0", "0", "0", "0", "1", "2", "1", "0", "1", "0", "2", "1", "1", "1", "1", "1", "0", "0", "0", "0", "2", "1", "1", "0", "2", "1", "1", "0", "2", "0", "0", "1", "2", "0", "2", "0", "0", "0", "1", "2", "2", "0", "0", "2", "2", "2", "2", "1", "0", "2", "0", "0", "1", "1", "1", "0", "1", "2", "2", "0", "2", "2", "2", "0", "2", "1", "1", "1", "1", "0", "1", "2", "1", "1", "0", "2", "0", "1", "0", "1", "0", "1", "1", "2", "0", "2", "1", "2", "2", "0", "1", "1", "1", "2", "0", "2", "0", "0", "2", "0", "0", "1", "1", "2", "2", "0", "2", "1", "1", "2", "1", "1", "1", "1", "0", "1", "2", "0", "1", "1", "1", "1", "1", "1", ], ); test( "643945257796761196320314690988316858252541574945689186182369731847117890385280572047834937\ 1883212246436232738680605124294949600205450044993253033167972343988333612737978764297848348\ 2665822115523011210267845467229157815194234251375826930137780574470438350033031660616757791\ 61", "7", &[ "4", "5", "1", "4", "5", "6", "0", "2", "4", "6", "2", "0", "1", "0", "3", "6", "4", "3", "1", "4", "2", "6", "4", "4", "0", "2", "1", "0", "3", "3", "2", "0", "3", "5", "4", "1", "3", "4", "4", "3", "5", "6", "4", "1", "6", "0", "2", "2", "5", "0", "5", "0", "5", "4", "0", "5", "3", "5", "0", "0", "3", "6", "1", "5", "4", "4", "1", "2", "1", "4", "2", "0", "0", "1", "4", "3", "2", "0", "3", "5", "2", "6", "5", "5", "0", "2", "1", "6", "5", "2", "5", "0", "6", "6", "4", "3", "1", "6", "0", "6", "1", "3", "1", "5", "4", "3", "0", "5", "2", "6", "5", "2", "0", "3", "3", "1", "3", "5", "3", "1", "1", "3", "2", "0", "1", "5", "6", "0", "1", "6", "4", "4", "5", "4", "4", "2", "0", "2", "5", "6", "4", "5", "2", "2", "4", "4", "0", "6", "5", "4", "2", "1", "6", "0", "2", "0", "4", "2", "5", "6", "2", "5", "1", "5", "3", "3", "5", "1", "0", "2", "5", "4", "1", "2", "6", "6", "2", "0", "6", "1", "1", "1", "4", "0", "1", "5", "4", "0", "6", "6", "4", "6", "1", "3", "0", "3", "3", "4", "6", "2", "3", "5", "1", "4", "4", "6", "3", "2", "4", "3", "0", "3", "2", "6", "2", "4", "3", "6", "6", "6", "6", "4", "4", "3", "6", "6", "3", "3", "5", "5", "1", "0", "1", "0", "3", "6", "5", "3", "2", "1", "3", "1", "3", "2", "4", "6", "1", "5", "6", "2", "6", "2", "5", "0", "6", "0", "0", "3", "4", "0", "6", "3", "5", "2", "5", "5", "4", "1", "3", "4", "4", "2", "2", "3", "1", "6", "2", "1", "4", "1", "5", "5", "6", "3", "6", "3", "6", "4", "4", "5", "2", "3", "1", "6", "2", "1", "0", "0", "5", "0", "2", "5", "5", "4", "0", "5", "6", "5", "2", "2", "0", "3", "6", "5", "2", "4", "6", "4", "3", "6", "4", "4", "6", "6", ], ); } #[test] fn to_digits_asc_natural_fail() { assert_panic!(Natural::from(10u32).to_digits_asc(&Natural::ZERO)); assert_panic!(Natural::from(10u32).to_digits_asc(&Natural::ONE)); } #[test] fn to_digits_asc_natural_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_pair_gen_var_2().test_properties_with_config(&config, |(x, base)| { let digits = x.to_digits_asc(&base); let mut digits_alt = Vec::new(); to_digits_asc_naive(&mut digits_alt, &x, &base); assert_eq!(digits_alt, digits); if x != 0 { assert_ne!(*digits.last().unwrap(), 0); assert_eq!(u64::exact_from(digits.len()), x.floor_log_base(&base) + 1); } assert_eq!( digits.iter().cloned().rev().collect_vec(), x.to_digits_desc(&base) ); assert!(digits.iter().all(|digit| *digit < base)); assert_eq!( Natural::from_digits_asc(&base, digits.into_iter()).unwrap(), x ); }); natural_gen().test_properties_with_config(&config, |x| { assert_eq!( x.to_digits_asc(&Natural::TWO) .into_iter() .map(|digit| digit == 1) .collect_vec(), x.to_bits_asc() ); }); natural_gen_var_1().test_properties_with_config(&config, |base| { assert!(Natural::ZERO.to_digits_asc(&base).is_empty()); }); } #[test] fn test_to_digits_desc_natural() { fn test(x: &str, base: &str, out: &[&str]) { let x = Natural::from_str(x).unwrap(); let base = Natural::from_str(base).unwrap(); let out = out .iter() .map(|s| Natural::from_str(s).unwrap()) .collect_vec(); assert_eq!(x.to_digits_desc(&base), out); } test("0", "10", &[]); test("0", "16", &[]); test("123", "10", &["1", "2", "3"]); test("123", "8", &["1", "7", "3"]); test( "1473250819553359898729024041508", "77", &[ "74", "22", "10", "50", "57", "19", "15", "70", "15", "36", "13", "43", "10", "51", "55", "44", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "1000", &[ "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "1001", &[ "981", "188", "866", "825", "550", "644", "683", "677", "392", "404", "333", "767", "596", "706", "516", "839", "862", "189", "981", "1", ], ); test( "1000000000000000000000000000000000000000000000000000000000000", "123456", &[ "9848", "49669", "86861", "18791", "41276", "26412", "92024", "30637", "11540", "27948", "7508", "115456", ], ); test( "958147186852538842877959980138243879940342867265688956449364129", "9238", &[ "3146", "277", "1611", "402", "6308", "2051", "6317", "138", "1758", "1707", "6502", "5213", "7131", "2066", "1928", "1297", ], ); test( "1000000000000", "10", &["1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"], ); test( "1000000000000", "16", &["14", "8", "13", "4", "10", "5", "1", "0", "0", "0"], ); test("1000000000000", "1000000000000000", &["1000000000000"]); test( "235317521501133049587746364812444472287442159306443086833887479789539173449622133054745814\ 7574478578278803560754066959663745455193666960506455349780493525811386914540373186134", "6", &[ "1", "0", "5", "5", "1", "5", "3", "1", "2", "1", "4", "0", "0", "4", "5", "1", "4", "4", "1", "5", "1", "4", "0", "0", "3", "5", "0", "3", "0", "3", "2", "0", "0", "3", "3", "1", "3", "3", "2", "0", "5", "2", "5", "2", "3", "5", "3", "2", "5", "0", "3", "1", "0", "3", "2", "3", "5", "3", "1", "1", "0", "1", "1", "4", "5", "1", "0", "4", "3", "0", "1", "0", "2", "5", "3", "5", "2", "0", "0", "3", "5", "1", "5", "2", "2", "1", "5", "4", "5", "2", "2", "3", "3", "0", "2", "1", "0", "4", "4", "2", "0", "3", "2", "2", "3", "2", "1", "2", "3", "5", "2", "0", "1", "5", "5", "1", "4", "1", "3", "5", "1", "4", "0", "0", "2", "5", "0", "5", "3", "5", "2", "3", "0", "5", "4", "1", "1", "0", "3", "5", "0", "2", "1", "5", "4", "4", "1", "1", "0", "3", "1", "0", "5", "3", "1", "4", "3", "0", "4", "5", "1", "2", "5", "5", "2", "2", "4", "4", "0", "5", "4", "0", "5", "4", "3", "3", "1", "1", "4", "3", "5", "5", "4", "0", "5", "2", "3", "2", "3", "4", "2", "1", "2", "2", "2", "1", "2", "4", "5", "1", "5", "5", "1", "3", "1", "5", "4", "2", "5", "3", "5", "1", "5", "0", "3", "5", "2", "4", "1", "2", "3", "2", "3", "1", "4", ], ); test( "14974892748479131847778931724116484851265511358392776602889616274416063303", "3", &[ "1", "1", "1", "1", "1", "1", "0", "2", "1", "0", "1", "1", "1", "1", "2", "1", "1", "2", "0", "2", "2", "1", "1", "0", "0", "2", "0", "0", "2", "0", "2", "1", "1", "1", "0", "2", "2", "1", "2", "0", "2", "1", "1", "0", "1", "0", "1", "0", "2", "0", "1", "1", "2", "1", "0", "1", "1", "1", "1", "2", "0", "2", "2", "2", "0", "2", "2", "1", "0", "1", "1", "1", "0", "0", "2", "0", "1", "2", "2", "2", "2", "0", "0", "2", "2", "1", "0", "0", "0", "2", "0", "2", "1", "0", "0", "2", "0", "1", "1", "2", "0", "1", "1", "2", "0", "0", "0", "0", "1", "1", "1", "1", "1", "2", "0", "1", "0", "1", "2", "1", "0", "0", "0", "0", "1", "2", "0", "0", "1", "1", "2", "1", "1", "0", "1", "0", "0", "2", "2", "2", "0", "2", "1", "1", "2", "1", "2", "0", "2", "1", "1", "1", "2", "0", ], ); test( "643945257796761196320314690988316858252541574945689186182369731847117890385280572047834937\ 1883212246436232738680605124294949600205450044993253033167972343988333612737978764297848348\ 2665822115523011210267845467229157815194234251375826930137780574470438350033031660616757791\ 61", "7", &[ "6", "6", "4", "4", "6", "3", "4", "6", "4", "2", "5", "6", "3", "0", "2", "2", "5", "6", "5", "0", "4", "5", "5", "2", "0", "5", "0", "0", "1", "2", "6", "1", "3", "2", "5", "4", "4", "6", "3", "6", "3", "6", "5", "5", "1", "4", "1", "2", "6", "1", "3", "2", "2", "4", "4", "3", "1", "4", "5", "5", "2", "5", "3", "6", "0", "4", "3", "0", "0", "6", "0", "5", "2", "6", "2", "6", "5", "1", "6", "4", "2", "3", "1", "3", "1", "2", "3", "5", "6", "3", "0", "1", "0", "1", "5", "5", "3", "3", "6", "6", "3", "4", "4", "6", "6", "6", "6", "3", "4", "2", "6", "2", "3", "0", "3", "4", "2", "3", "6", "4", "4", "1", "5", "3", "2", "6", "4", "3", "3", "0", "3", "1", "6", "4", "6", "6", "0", "4", "5", "1", "0", "4", "1", "1", "1", "6", "0", "2", "6", "6", "2", "1", "4", "5", "2", "0", "1", "5", "3", "3", "5", "1", "5", "2", "6", "5", "2", "4", "0", "2", "0", "6", "1", "2", "4", "5", "6", "0", "4", "4", "2", "2", "5", "4", "6", "5", "2", "0", "2", "4", "4", "5", "4", "4", "6", "1", "0", "6", "5", "1", "0", "2", "3", "1", "1", "3", "5", "3", "1", "3", "3", "0", "2", "5", "6", "2", "5", "0", "3", "4", "5", "1", "3", "1", "6", "0", "6", "1", "3", "4", "6", "6", "0", "5", "2", "5", "6", "1", "2", "0", "5", "5", "6", "2", "5", "3", "0", "2", "3", "4", "1", "0", "0", "2", "4", "1", "2", "1", "4", "4", "5", "1", "6", "3", "0", "0", "5", "3", "5", "0", "4", "5", "0", "5", "0", "5", "2", "2", "0", "6", "1", "4", "6", "5", "3", "4", "4", "3", "1", "4", "5", "3", "0", "2", "3", "3", "0", "1", "2", "0", "4", "4", "6", "2", "4", "1", "3", "4", "6", "3", "0", "1", "0", "2", "6", "4", "2", "0", "6", "5", "4", "1", "5", "4", ], ); } #[test] fn to_digits_desc_natural_fail() { assert_panic!(Natural::from(10u32).to_digits_desc(&Natural::ZERO)); assert_panic!(Natural::from(10u32).to_digits_desc(&Natural::ONE)); } #[test] fn to_digits_desc_natural_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); natural_pair_gen_var_2().test_properties_with_config(&config, |(x, base)| { let digits = x.to_digits_desc(&base); if x != 0 { assert_ne!(digits[0], 0); assert_eq!(u64::exact_from(digits.len()), x.floor_log_base(&base) + 1); } assert_eq!( digits.iter().cloned().rev().collect_vec(), x.to_digits_asc(&base) ); assert!(digits.iter().all(|digit| *digit < base)); assert_eq!( Natural::from_digits_desc(&base, digits.into_iter()).unwrap(), x ); }); natural_gen().test_properties_with_config(&config, |x| { assert_eq!( x.to_digits_desc(&Natural::TWO) .into_iter() .map(|digit| digit == 1) .collect_vec(), x.to_bits_desc() ); }); natural_gen_var_1().test_properties_with_config(&config, |base| { assert!(Natural::ZERO.to_digits_desc(&base).is_empty()); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::{FloorLogBasePowerOf2, Pow}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ExactFrom, PowerOf2Digits}; use malachite_base::num::logic::traits::{BitConvertible, SignificantBits}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{ unsigned_gen_var_3, unsigned_gen_var_11, unsigned_pair_gen_var_4, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_unsigned_pair_gen_var_6, natural_unsigned_pair_gen_var_7, }; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_to_power_of_2_digits_asc() { fn test Vec>( to_power_of_2_digits_asc_naive: F, n: &str, log_base: u64, out: &[T], ) where Natural: PowerOf2Digits, { let n = Natural::from_str(n).unwrap(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base), out ); assert_eq!(to_power_of_2_digits_asc_naive(&n, log_base), out); } test::(Natural::to_power_of_2_digits_asc_naive, "0", 1, &[]); test::(Natural::to_power_of_2_digits_asc_naive, "123", 10, &[123]); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000", 1, &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, ], ); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000", 3, &[0, 0, 0, 0, 1, 2, 1, 5, 4, 2, 3, 4, 6, 1], ); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000", 4, &[0, 0, 0, 1, 5, 10, 4, 13, 8, 14], ); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000", 32, &[3567587328, 232], ); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000", 64, &[1000000000000], ); test::( Natural::to_power_of_2_digits_asc_naive, "1000000000000000000000000", 64, &[2003764205206896640, 54210], ); } fn to_power_of_2_digits_asc_fail_helper() where Natural: PowerOf2Digits, { assert_panic!(PowerOf2Digits::::to_power_of_2_digits_asc( &Natural::from(10u32).pow(12), 0 )); assert_panic!(PowerOf2Digits::::to_power_of_2_digits_asc( &Natural::from(10u32).pow(12), T::WIDTH + 1 )); } #[test] fn to_power_of_2_digits_asc_fail() { apply_fn_to_unsigneds!(to_power_of_2_digits_asc_fail_helper); } #[test] fn test_to_power_of_2_digits_desc() { fn test(n: &str, log_base: u64, out: &[T]) where Natural: PowerOf2Digits, { let n = Natural::from_str(n).unwrap(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base), out ); } test::("0", 1, &[]); test::("123", 10, &[123]); test::( "1000000000000", 1, &[ 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ); test::( "1000000000000", 3, &[1, 6, 4, 3, 2, 4, 5, 1, 2, 1, 0, 0, 0, 0], ); test::("1000000000000", 4, &[14, 8, 13, 4, 10, 5, 1, 0, 0, 0]); test::("1000000000000", 32, &[232, 3567587328]); test::("1000000000000", 64, &[1000000000000]); test::( "1000000000000000000000000", 64, &[54210, 2003764205206896640], ); } fn to_power_of_2_digits_desc_fail_helper() where Natural: PowerOf2Digits, { assert_panic!(PowerOf2Digits::::to_power_of_2_digits_desc( &Natural::from(10u32).pow(12), 0 )); assert_panic!(PowerOf2Digits::::to_power_of_2_digits_desc( &Natural::from(10u32).pow(12), T::WIDTH + 1 )); } #[test] fn to_power_of_2_digits_desc_fail() { apply_fn_to_unsigneds!(to_power_of_2_digits_desc_fail_helper); } #[test] fn test_to_power_of_2_digits_asc_natural() { let test = |n, log_base, out| { let n = Natural::from_str(n).unwrap(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base).to_debug_string(), out ); assert_eq!( n.to_power_of_2_digits_asc_natural_naive(log_base) .to_debug_string(), out ); }; test("0", 1, "[]"); test("123", 10, "[123]"); test( "1000000000000", 1, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, \ 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1]", ); test( "1000000000000", 3, "[0, 0, 0, 0, 1, 2, 1, 5, 4, 2, 3, 4, 6, 1]", ); test("1000000000000", 4, "[0, 0, 0, 1, 5, 10, 4, 13, 8, 14]"); test("1000000000000", 32, "[3567587328, 232]"); test("1000000000000", 64, "[1000000000000]"); test( "1000000000000000000000000", 64, "[2003764205206896640, 54210]", ); test( "1000000000000000000000000", 33, "[6996099072, 4528236150, 13552]", ); } #[test] #[should_panic] fn to_power_of_2_digits_asc_natural_fail() { PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::from(10u32).pow(12), 0); } #[test] fn test_to_power_of_2_digits_desc_natural() { let test = |n, log_base, out| { let n = Natural::from_str(n).unwrap(); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base).to_debug_string(), out ); }; test("0", 1, "[]"); test("123", 10, "[123]"); test( "1000000000000", 1, "[1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); test( "1000000000000", 3, "[1, 6, 4, 3, 2, 4, 5, 1, 2, 1, 0, 0, 0, 0]", ); test("1000000000000", 4, "[14, 8, 13, 4, 10, 5, 1, 0, 0, 0]"); test("1000000000000", 32, "[232, 3567587328]"); test("1000000000000", 64, "[1000000000000]"); test( "1000000000000000000000000", 64, "[54210, 2003764205206896640]", ); test( "1000000000000000000000000", 33, "[13552, 4528236150, 6996099072]", ); } #[test] #[should_panic] fn to_power_of_2_digits_desc_natural_fail() { PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::from(10u32).pow(12), 0); } fn to_power_of_2_digits_asc_properties_helper TryFrom<&'a Natural> + PrimitiveUnsigned>() where Limb: PowerOf2Digits, Natural: From + PowerOf2Digits, { natural_unsigned_pair_gen_var_6::().test_properties(|(ref n, log_base)| { let digits = n.to_power_of_2_digits_asc(log_base); assert_eq!( Natural::to_power_of_2_digits_asc_naive::(n, log_base), digits ); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().copied()).unwrap(), *n ); if *n != 0 { assert_ne!(*digits.last().unwrap(), T::ZERO); } assert_eq!( digits.iter().copied().rev().collect_vec(), n.to_power_of_2_digits_desc(log_base) ); if *n != Natural::ZERO { assert_eq!( u64::exact_from(digits.len()), n.floor_log_base_power_of_2(log_base) + 1 ); } assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base), digits.iter().copied().map(Natural::from).collect_vec() ); }); natural_gen().test_properties(|n| { assert_eq!( n.to_power_of_2_digits_asc(1) .into_iter() .map(|digit: T| digit == T::ONE) .collect_vec(), n.to_bits_asc() ); }); unsigned_gen_var_3::().test_properties(|log_base| { assert!(PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::ZERO, log_base).is_empty()); }); unsigned_pair_gen_var_4::().test_properties(|(u, log_base)| { let n: Natural = From::from(u); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(&u, log_base), PowerOf2Digits::::to_power_of_2_digits_asc(&n, log_base) ); }); } #[test] fn to_power_of_2_digits_asc_properties() { apply_fn_to_unsigneds!(to_power_of_2_digits_asc_properties_helper); natural_gen().test_properties(|ref n| { assert_eq!( PowerOf2Digits::::to_power_of_2_digits_asc(n, Limb::WIDTH), n.as_limbs_asc() ); }); } fn to_power_of_2_digits_desc_properties_helper< T: for<'a> TryFrom<&'a Natural> + PrimitiveUnsigned, >() where Limb: PowerOf2Digits, Natural: From + PowerOf2Digits, { natural_unsigned_pair_gen_var_6::().test_properties(|(ref n, log_base)| { let digits = n.to_power_of_2_digits_desc(log_base); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().copied()).unwrap(), *n ); if *n != 0 { assert_ne!(digits[0], T::ZERO); } assert_eq!( digits.iter().copied().rev().collect_vec(), n.to_power_of_2_digits_asc(log_base) ); if *n != Natural::ZERO { assert_eq!( u64::exact_from(digits.len()), n.floor_log_base_power_of_2(log_base) + 1 ); } assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(n, log_base), digits.iter().copied().map(Natural::from).collect_vec() ); }); natural_gen().test_properties(|n| { assert_eq!( n.to_power_of_2_digits_desc(1) .into_iter() .map(|digit: T| digit == T::ONE) .collect_vec(), n.to_bits_desc() ); }); unsigned_gen_var_3::().test_properties(|log_base| { assert!( PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::ZERO, log_base).is_empty() ); }); unsigned_pair_gen_var_4::().test_properties(|(u, log_base)| { let n: Natural = From::from(u); assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(&u, log_base), PowerOf2Digits::::to_power_of_2_digits_desc(&n, log_base) ); }); } #[test] fn to_power_of_2_digits_desc_properties() { apply_fn_to_unsigneds!(to_power_of_2_digits_desc_properties_helper); natural_gen().test_properties(|ref n| { assert_eq!( PowerOf2Digits::::to_power_of_2_digits_desc(n, Limb::WIDTH), n.to_limbs_desc() ); }); } #[test] fn to_power_of_2_digits_asc_natural_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(ref n, log_base)| { let digits: Vec = n.to_power_of_2_digits_asc(log_base); assert_eq!(n.to_power_of_2_digits_asc_natural_naive(log_base), digits); assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()).unwrap(), *n ); if *n != 0 { assert_ne!(*digits.last().unwrap(), 0); } assert_eq!( digits.iter().cloned().rev().collect_vec(), PowerOf2Digits::::to_power_of_2_digits_desc(n, log_base) ); if *n != Natural::ZERO { assert_eq!( u64::exact_from(digits.len()), n.floor_log_base_power_of_2(log_base) + 1 ); } assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); }); natural_gen().test_properties(|n| { assert_eq!( n.to_power_of_2_digits_asc(1) .into_iter() .map(|digit: Natural| digit == 1) .collect_vec(), n.to_bits_asc() ); }); unsigned_gen_var_11().test_properties(|log_base| { assert!( PowerOf2Digits::::to_power_of_2_digits_asc(&Natural::ZERO, log_base) .is_empty() ); }); } #[test] fn to_power_of_2_digits_desc_natural_properties() { natural_unsigned_pair_gen_var_7().test_properties(|(ref n, log_base)| { let digits: Vec = n.to_power_of_2_digits_desc(log_base); assert_eq!( Natural::from_power_of_2_digits_desc(log_base, digits.iter().cloned()).unwrap(), *n ); if *n != 0 { assert_ne!(digits[0], 0); } assert_eq!( digits.iter().cloned().rev().collect_vec(), PowerOf2Digits::::to_power_of_2_digits_asc(n, log_base) ); if *n != Natural::ZERO { assert_eq!( u64::exact_from(digits.len()), n.floor_log_base_power_of_2(log_base) + 1 ); } assert!( digits .iter() .all(|digit| digit.significant_bits() <= log_base) ); }); natural_gen().test_properties(|n| { assert_eq!( n.to_power_of_2_digits_desc(1) .into_iter() .map(|digit: Natural| digit == 1) .collect_vec(), n.to_bits_desc() ); }); unsigned_gen_var_11().test_properties(|log_base| { assert!( PowerOf2Digits::::to_power_of_2_digits_desc(&Natural::ZERO, log_base) .is_empty() ); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; #[test] fn test_from_bool() { let test = |b, s| { let n = Natural::from(b); assert!(n.is_valid()); assert_eq!(n.to_string(), s); }; test(false, "0"); test(true, "1"); } ================================================ FILE: malachite-nz/tests/natural/conversion/from_limbs.rs ================================================ // Copyright © 2026 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::num::basic::integers::PrimitiveInt; use malachite_base::slices::slice_test_zero; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; #[cfg(feature = "32_bit_limbs")] #[test] fn test_from_limbs_asc() { let test = |xs: &[Limb], out| { let x = Natural::from_limbs_asc(xs); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = Natural::from_owned_limbs_asc(xs.to_vec()); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(&[], "0"); test(&[0], "0"); test(&[0, 0, 0], "0"); test(&[123], "123"); test(&[123, 0], "123"); test(&[123, 0, 0, 0], "123"); test(&[3567587328, 232], "1000000000000"); test(&[3567587328, 232, 0], "1000000000000"); test(&[1, 2, 3, 4, 5], "1701411834921604967429270619762735448065"); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_from_limbs_desc() { let test = |xs: Vec, out| { let x = Natural::from_limbs_desc(&xs); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = Natural::from_owned_limbs_desc(xs.to_vec()); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(vec![], "0"); test(vec![0], "0"); test(vec![0, 0, 0], "0"); test(vec![123], "123"); test(vec![0, 123], "123"); test(vec![0, 0, 0, 123], "123"); test(vec![232, 3567587328], "1000000000000"); test(vec![0, 232, 3567587328], "1000000000000"); test( vec![5, 4, 3, 2, 1], "1701411834921604967429270619762735448065", ); } #[test] fn from_limbs_asc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let x = Natural::from_limbs_asc(&xs); assert!(x.is_valid()); assert_eq!(Natural::from_owned_limbs_asc(xs.clone()), x); let mut trimmed_limbs = xs .iter() .copied() .rev() .skip_while(|&limb| limb == 0) .collect_vec(); trimmed_limbs.reverse(); assert_eq!(x.as_limbs_asc(), trimmed_limbs); assert_eq!( Natural::from_limbs_desc(&xs.iter().copied().rev().collect_vec()), x ); if !xs.is_empty() && *xs.last().unwrap() != 0 { assert_eq!(x.as_limbs_asc(), xs); } assert_eq!(slice_test_zero(&xs), x == 0); }); } #[test] fn from_limbs_desc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let x = Natural::from_limbs_desc(&xs); assert!(x.is_valid()); assert_eq!(Natural::from_owned_limbs_desc(xs.clone()), x); assert_eq!( x.to_limbs_desc(), xs.iter() .copied() .skip_while(|&limb| limb == 0) .collect_vec() ); assert_eq!( Natural::from_limbs_asc(&xs.iter().copied().rev().collect_vec()), x ); if !xs.is_empty() && xs[0] != 0 { assert_eq!(x.to_limbs_desc(), xs); } assert_eq!(slice_test_zero(&xs), x == 0); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{ primitive_float_gen, primitive_float_gen_var_2, primitive_float_gen_var_3, primitive_float_gen_var_4, primitive_float_gen_var_13, primitive_float_rounding_mode_pair_gen_var_1, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use std::cmp::Ordering::*; #[test] fn test_rounding_from_f32() { let test = |f: f32, rm: RoundingMode, out, o_out| { let (x, o) = Natural::rounding_from(f, rm); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(o, o_out); }; test(0.0, Exact, "0", Equal); test(-0.0, Exact, "0", Equal); test(123.0, Exact, "123", Equal); test(1.0e9, Exact, "1000000000", Equal); test(1.0e9, Exact, "1000000000", Equal); test(4294967295.0, Exact, "4294967296", Equal); test(4294967296.0, Exact, "4294967296", Equal); test(18446744073709551615.0, Exact, "18446744073709551616", Equal); test(18446744073709551616.0, Exact, "18446744073709551616", Equal); test(1.0e20, Exact, "100000002004087734272", Equal); test(1.23e20, Exact, "122999999650278146048", Equal); test(1.6777216e7, Exact, "16777216", Equal); test(1.6777218e7, Exact, "16777218", Equal); test(123.1, Floor, "123", Less); test(123.1, Down, "123", Less); test(123.1, Ceiling, "124", Greater); test(123.1, Up, "124", Greater); test(123.1, Nearest, "123", Less); test(123.9, Floor, "123", Less); test(123.9, Down, "123", Less); test(123.9, Ceiling, "124", Greater); test(123.9, Up, "124", Greater); test(123.9, Nearest, "124", Greater); test(123.5, Nearest, "124", Greater); test(124.5, Nearest, "124", Less); test(-0.99, Ceiling, "0", Greater); test(-0.99, Down, "0", Greater); test(-0.499, Nearest, "0", Greater); test(-0.5, Nearest, "0", Greater); test(f32::NEGATIVE_INFINITY, Nearest, "0", Greater); test(f32::NEGATIVE_INFINITY, Down, "0", Greater); test(f32::NEGATIVE_INFINITY, Ceiling, "0", Greater); test(-123.0, Nearest, "0", Greater); test(-123.0, Down, "0", Greater); test(-123.0, Ceiling, "0", Greater); } #[test] #[should_panic] fn rounding_from_f32_fail_1() { Natural::rounding_from(f32::NAN, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_2() { Natural::rounding_from(f32::INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_3() { Natural::rounding_from(f32::NEGATIVE_INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_4() { Natural::rounding_from(123.1, Exact); } #[test] #[should_panic] fn rounding_from_f32_fail_5() { Natural::rounding_from(-123.0, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_6() { Natural::rounding_from(-0.1, Floor); } #[test] #[should_panic] fn rounding_from_f32_fail_7() { Natural::rounding_from(-0.1, Up); } #[test] fn test_rounding_from_f64() { let test = |f: f64, rm: RoundingMode, out, o_out| { let (x, o) = Natural::rounding_from(f, rm); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(o, o_out); }; test(0.0, Exact, "0", Equal); test(-0.0, Exact, "0", Equal); test(123.0, Exact, "123", Equal); test(1.0e9, Exact, "1000000000", Equal); test(1.0e9, Exact, "1000000000", Equal); test(4294967295.0, Exact, "4294967295", Equal); test(4294967296.0, Exact, "4294967296", Equal); test(18446744073709551615.0, Exact, "18446744073709551616", Equal); test(18446744073709551616.0, Exact, "18446744073709551616", Equal); test(1.0e20, Exact, "100000000000000000000", Equal); test(1.23e20, Exact, "123000000000000000000", Equal); test( 1.0e100, Exact, "100000000000000001590289110975991804683608085639452813897813275577478387721703810608134699\ 85856815104", Equal, ); test( 1.23e100, Exact, "123000000000000008366862950845375853795062237854139353014252897832358837028676639186389822\ 00322686976", Equal, ); test(9.007199254740992e15, Exact, "9007199254740992", Equal); test(9.007199254740994e15, Exact, "9007199254740994", Equal); test(123.1, Floor, "123", Less); test(123.1, Down, "123", Less); test(123.1, Ceiling, "124", Greater); test(123.1, Up, "124", Greater); test(123.1, Nearest, "123", Less); test(123.9, Floor, "123", Less); test(123.9, Down, "123", Less); test(123.9, Ceiling, "124", Greater); test(123.9, Up, "124", Greater); test(123.9, Nearest, "124", Greater); test(123.5, Nearest, "124", Greater); test(124.5, Nearest, "124", Less); test(-0.99, Ceiling, "0", Greater); test(-0.99, Down, "0", Greater); test(-0.499, Nearest, "0", Greater); test(-0.5, Nearest, "0", Greater); test(f64::NEGATIVE_INFINITY, Nearest, "0", Greater); test(f64::NEGATIVE_INFINITY, Down, "0", Greater); test(f64::NEGATIVE_INFINITY, Ceiling, "0", Greater); test(-123.0, Nearest, "0", Greater); test(-123.0, Down, "0", Greater); test(-123.0, Ceiling, "0", Greater); } #[test] #[should_panic] fn rounding_from_f64_fail_1() { Natural::rounding_from(f64::NAN, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_2() { Natural::rounding_from(f64::INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_3() { Natural::rounding_from(f64::NEGATIVE_INFINITY, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_4() { Natural::rounding_from(123.1, Exact); } #[test] #[should_panic] fn rounding_from_f64_fail_5() { Natural::rounding_from(-123.0, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_6() { Natural::rounding_from(-0.1, Floor); } #[test] #[should_panic] fn rounding_from_f64_fail_7() { Natural::rounding_from(-0.1, Up); } #[test] fn test_try_from_f32() { let test = |f: f32, out| { let on = Natural::try_from(f); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test(f32::NAN, "Err(FloatInfiniteOrNan)"); test(f32::INFINITY, "Err(FloatInfiniteOrNan)"); test(f32::NEGATIVE_INFINITY, "Err(FloatInfiniteOrNan)"); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(1.0e9, "Ok(1000000000)"); test(4294967295.0, "Ok(4294967296)"); test(4294967296.0, "Ok(4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(1.0e20, "Ok(100000002004087734272)"); test(1.23e20, "Ok(122999999650278146048)"); test(123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-0.99, "Err(FloatNegative)"); test(-0.499, "Err(FloatNegative)"); test(-0.5, "Err(FloatNegative)"); test(-123.0, "Err(FloatNegative)"); test(f32::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(f32::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(f32::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test( f32::MAX_FINITE, "Ok(340282346638528859811704183484516925440)", ); } #[test] fn test_try_from_f64() { let test = |f: f64, out| { let on = Natural::try_from(f); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test(f64::NAN, "Err(FloatInfiniteOrNan)"); test(f64::INFINITY, "Err(FloatInfiniteOrNan)"); test(f64::NEGATIVE_INFINITY, "Err(FloatInfiniteOrNan)"); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(1.0e9, "Ok(1000000000)"); test(4294967295.0, "Ok(4294967295)"); test(4294967296.0, "Ok(4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(1.0e20, "Ok(100000000000000000000)"); test(1.23e20, "Ok(123000000000000000000)"); test( 1.0e100, "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ 469985856815104)", ); test( 1.23e100, "Ok(12300000000000000836686295084537585379506223785413935301425289783235883702867663918638\ 982200322686976)", ); test(123.1, "Err(FloatNonIntegerOrOutOfRange)"); test(123.5, "Err(FloatNonIntegerOrOutOfRange)"); test(124.5, "Err(FloatNonIntegerOrOutOfRange)"); test(-0.99, "Err(FloatNegative)"); test(-0.499, "Err(FloatNegative)"); test(-0.5, "Err(FloatNegative)"); test(-123.0, "Err(FloatNegative)"); test(f64::MIN_POSITIVE, "Err(FloatNonIntegerOrOutOfRange)"); test(f64::MAX_SUBNORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test(f64::MIN_POSITIVE_NORMAL, "Err(FloatNonIntegerOrOutOfRange)"); test( f64::MAX_FINITE, "Ok(1797693134862315708145274237317043567980705675258449965989174768031572607800285387605\ 8955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207\ 6245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723\ 168738177180919299881250404026184124858368)", ); } #[test] fn test_exact_from_f32() { let test = |f: f32, out| { let x = Natural::exact_from(f); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(0.0, "0"); test(-0.0, "0"); test(123.0, "123"); test(1.0e9, "1000000000"); test(4294967295.0, "4294967296"); test(4294967296.0, "4294967296"); test(18446744073709551615.0, "18446744073709551616"); test(18446744073709551616.0, "18446744073709551616"); test(1.0e20, "100000002004087734272"); test(1.23e20, "122999999650278146048"); test(f32::MAX_FINITE, "340282346638528859811704183484516925440"); } #[test] #[should_panic] fn exact_from_f32_fail_1() { Natural::exact_from(f32::NAN); } #[test] #[should_panic] fn exact_from_f32_fail_2() { Natural::exact_from(f32::INFINITY); } #[test] #[should_panic] fn exact_from_f32_fail_3() { Natural::exact_from(f32::NEGATIVE_INFINITY); } #[test] #[should_panic] fn exact_from_f32_fail_4() { Natural::exact_from(123.1); } #[test] #[should_panic] fn exact_from_f32_fail_5() { Natural::exact_from(123.5); } #[test] #[should_panic] fn exact_from_f32_fail_6() { Natural::exact_from(124.5); } #[test] #[should_panic] fn exact_from_f32_fail_7() { Natural::exact_from(-0.99); } #[test] #[should_panic] fn exact_from_f32_fail_8() { Natural::exact_from(-0.499); } #[test] #[should_panic] fn exact_from_f32_fail_9() { Natural::exact_from(-0.5); } #[test] #[should_panic] fn exact_from_f32_fail_10() { Natural::exact_from(-123.0); } #[test] #[should_panic] fn exact_from_f32_fail_11() { Natural::exact_from(f32::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f32_fail_12() { Natural::exact_from(f32::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f32_fail_13() { Natural::exact_from(f32::MIN_POSITIVE_NORMAL); } #[test] fn test_exact_from_f64() { let test = |f: f64, out| { let x = Natural::exact_from(f); assert_eq!(x.to_string(), out); assert!(x.is_valid()); }; test(0.0, "0"); test(-0.0, "0"); test(123.0, "123"); test(1.0e9, "1000000000"); test(4294967295.0, "4294967295"); test(4294967296.0, "4294967296"); test(18446744073709551615.0, "18446744073709551616"); test(18446744073709551616.0, "18446744073709551616"); test(1.0e20, "100000000000000000000"); test(1.23e20, "123000000000000000000"); test( 1.0e100, "100000000000000001590289110975991804683608085639452813897813275577478387721703810608134699\ 85856815104", ); test( 1.23e100, "123000000000000008366862950845375853795062237854139353014252897832358837028676639186389822\ 00322686976", ); test( f64::MAX_FINITE, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", ); } #[test] #[should_panic] fn exact_from_f64_fail_1() { Natural::exact_from(f64::NAN); } #[test] #[should_panic] fn exact_from_f64_fail_2() { Natural::exact_from(f64::INFINITY); } #[test] #[should_panic] fn exact_from_f64_fail_3() { Natural::exact_from(f64::NEGATIVE_INFINITY); } #[test] #[should_panic] fn exact_from_f64_fail_4() { Natural::exact_from(123.1); } #[test] #[should_panic] fn exact_from_f64_fail_5() { Natural::exact_from(123.5); } #[test] #[should_panic] fn exact_from_f64_fail_6() { Natural::exact_from(124.5); } #[test] #[should_panic] fn exact_from_f64_fail_7() { Natural::exact_from(-0.99); } #[test] #[should_panic] fn exact_from_f64_fail_8() { Natural::exact_from(-0.499); } #[test] #[should_panic] fn exact_from_f64_fail_9() { Natural::exact_from(-0.5); } #[test] #[should_panic] fn exact_from_f64_fail_10() { Natural::exact_from(-123.0); } #[test] #[should_panic] fn exact_from_f64_fail_11() { Natural::exact_from(f64::MIN_POSITIVE); } #[test] #[should_panic] fn exact_from_f64_fail_12() { Natural::exact_from(f64::MAX_SUBNORMAL); } #[test] #[should_panic] fn exact_from_f64_fail_13() { Natural::exact_from(f64::MIN_POSITIVE_NORMAL); } #[test] fn test_convertible_from_f32() { let test = |f: f32, out| { assert_eq!(Natural::convertible_from(f), out); }; test(f32::NAN, false); test(f32::INFINITY, false); test(f32::NEGATIVE_INFINITY, false); test(0.0, true); test(-0.0, true); test(123.0, true); test(1.0e9, true); test(4294967295.0, true); test(4294967296.0, true); test(18446744073709551615.0, true); test(18446744073709551616.0, true); test(1.0e20, true); test(1.23e20, true); test(123.1, false); test(123.5, false); test(124.5, false); test(-0.99, false); test(-0.499, false); test(-0.5, false); test(-123.0, false); test(f32::MIN_POSITIVE, false); test(f32::MAX_SUBNORMAL, false); test(f32::MIN_POSITIVE_NORMAL, false); test(f32::MAX_FINITE, true); } #[test] fn test_convertible_from_f64() { let test = |f: f64, out| { assert_eq!(Natural::convertible_from(f), out); }; test(f64::NAN, false); test(f64::INFINITY, false); test(f64::NEGATIVE_INFINITY, false); test(0.0, true); test(-0.0, true); test(123.0, true); test(1.0e9, true); test(4294967295.0, true); test(4294967296.0, true); test(18446744073709551615.0, true); test(18446744073709551616.0, true); test(1.0e20, true); test(1.23e20, true); test(1.0e100, true); test(1.23e100, true); test(123.1, false); test(123.5, false); test(124.5, false); test(-0.99, false); test(-0.499, false); test(-0.5, false); test(-123.0, false); test(f64::MIN_POSITIVE, false); test(f64::MAX_SUBNORMAL, false); test(f64::MIN_POSITIVE_NORMAL, false); test(f64::MAX_FINITE, true); } #[test] fn test_convertible_from_i64() { let test = |i: i64, out| { assert_eq!(Natural::convertible_from(i), out); }; test(0, true); test(123, true); test(-123, false); test(i64::MAX, true); test(i64::MIN, false); } fn rounding_from_float_properties_helper RoundingFrom<&'a Natural>>() where Natural: PartialOrd + RoundingFrom, { primitive_float_rounding_mode_pair_gen_var_1::().test_properties(|(f, rm)| { let (n, o) = Natural::rounding_from(f, rm); assert!(n.is_valid()); assert_eq!(n.partial_cmp(&f), Some(o)); match (f.is_sign_positive(), rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); primitive_float_gen_var_2::().test_properties(|f| { let no = Natural::rounding_from(f, Exact); assert!(no.0.is_valid()); assert_eq!(no.1, Equal); assert_eq!(no, Natural::rounding_from(f, Floor)); assert_eq!(no, Natural::rounding_from(f, Ceiling)); assert_eq!(no, Natural::rounding_from(f, Down)); assert_eq!(no, Natural::rounding_from(f, Up)); assert_eq!(no, Natural::rounding_from(f, Nearest)); let (f_alt, o) = T::rounding_from(&no.0, Exact); assert_eq!(o, Equal); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); }); primitive_float_gen_var_3::().test_properties(|f| { let n_floor = Natural::rounding_from(f, Floor); assert!(n_floor.0.is_valid()); assert_eq!(n_floor.1, Less); let n_ceiling = (&n_floor.0 + Natural::ONE, Greater); assert_eq!(n_ceiling, Natural::rounding_from(f, Ceiling)); assert_eq!(n_floor, Natural::rounding_from(f, Down)); assert_eq!(n_ceiling, Natural::rounding_from(f, Up)); let n_nearest = Natural::rounding_from(f, Nearest); assert!(n_nearest == n_floor || n_nearest == n_ceiling); }); primitive_float_gen_var_4::().test_properties(|f| { let floor = Natural::rounding_from(f, Floor); let ceiling = (&floor.0 + Natural::ONE, Greater); let nearest = Natural::rounding_from(f, Nearest); assert_eq!(nearest, if floor.0.even() { floor } else { ceiling }); }); } #[test] fn rounding_from_float_properties() { apply_fn_to_primitive_floats!(rounding_from_float_properties_helper); } fn try_from_float_properties_helper RoundingFrom<&'a Natural>>() where Limb: TryFrom>, Natural: TryFrom + RoundingFrom, NiceFloat: TryFrom, { primitive_float_gen::().test_properties(|f| { let on = Natural::try_from(f); assert!(on.map_or(true, |n| n.is_valid())); if let Ok(n) = Limb::try_from(NiceFloat(f)) { assert_eq!(n, Natural::exact_from(f)); } }); primitive_float_gen_var_2::().test_properties(|f| { let n = Natural::exact_from(f); assert!(n.is_valid()); assert_eq!(n, Natural::rounding_from(f, Exact).0); assert_eq!(NiceFloat(T::rounding_from(&n, Exact).0), NiceFloat(f)); }); primitive_float_gen_var_3::().test_properties(|f| { assert!(Natural::try_from(f).is_err()); }); primitive_float_gen_var_4::().test_properties(|f| { assert!(Natural::try_from(f).is_err()); }); primitive_float_gen_var_13::().test_properties(|f| { assert_eq!(Limb::exact_from(NiceFloat(f)), Natural::exact_from(f)); }); } #[test] fn try_from_float_properties() { apply_fn_to_primitive_floats!(try_from_float_properties_helper); } fn convertible_from_float_properties_helper() where Natural: ConvertibleFrom, Limb: ConvertibleFrom, { primitive_float_gen::().test_properties(|f| { let nc = Natural::convertible_from(f); if Limb::convertible_from(f) { assert!(nc); } }); primitive_float_gen_var_2::().test_properties(|f| { assert!(Natural::convertible_from(f)); }); primitive_float_gen_var_3::().test_properties(|f| { assert!(!Natural::convertible_from(f)); }); primitive_float_gen_var_4::().test_properties(|f| { assert!(!Natural::convertible_from(f)); }); } #[test] fn convertible_from_float_properties() { apply_fn_to_primitive_floats!(convertible_from_float_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, SaturatingFrom}; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_nz::natural::Natural; use num::BigUint; use rug; #[test] fn test_from_u32() { let test = |u: u32, out| { let x = Natural::from(u); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(BigUint::from(u).to_string(), out); assert_eq!(rug::Integer::from(u).to_string(), out); #[cfg(feature = "32_bit_limbs")] { let x_alt = Natural::const_from(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u32::MAX, "4294967295"); } #[test] fn test_from_u64() { let test = |u: u64, out| { let x = Natural::from(u); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!(BigUint::from(u).to_string(), out); assert_eq!(rug::Integer::from(u).to_string(), out); #[cfg(not(feature = "32_bit_limbs"))] { let x_alt = Natural::const_from(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u64::MAX, "18446744073709551615"); } #[test] fn test_try_from_i32() { let test = |i: i32, out| { let on = Natural::try_from(i); assert!(on.as_ref().map_or(true, Natural::is_valid)); assert_eq!(on.to_debug_string(), out); }; test(0, "Ok(0)"); test(123, "Ok(123)"); test(-123, "Err(NaturalFromSignedError)"); test(i32::MAX, "Ok(2147483647)"); test(i32::MIN, "Err(NaturalFromSignedError)"); } #[test] fn test_exact_from_i32() { let test = |i: i32, out| { let x = Natural::exact_from(i); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(0, "0"); test(123, "123"); test(i32::MAX, "2147483647"); } #[test] #[should_panic] fn exact_from_i32_fail_1() { Natural::exact_from(-123i32); } #[test] #[should_panic] fn exact_from_i32_fail_2() { Natural::exact_from(i32::MIN); } #[test] fn test_saturating_from_i32() { let test = |i: i32, out| { let x = Natural::saturating_from(i); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(0, "0"); test(123, "123"); test(-123, "0"); test(i32::MAX, "2147483647"); test(i32::MIN, "0"); } #[test] fn test_convertible_from_i32() { let test = |i: i32, out| { assert_eq!(Natural::convertible_from(i), out); }; test(0, true); test(123, true); test(-123, false); test(i32::MAX, true); test(i32::MIN, false); } #[test] fn test_try_from_i64() { let test = |i: i64, out| { let on = Natural::try_from(i); assert!(on.as_ref().map_or(true, Natural::is_valid)); assert_eq!(on.to_debug_string(), out); }; test(0, "Ok(0)"); test(123, "Ok(123)"); test(-123, "Err(NaturalFromSignedError)"); test(i64::MAX, "Ok(9223372036854775807)"); test(i64::MIN, "Err(NaturalFromSignedError)"); } #[test] fn test_saturating_from_i64() { let test = |i: i64, out| { let x = Natural::saturating_from(i); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(0, "0"); test(123, "123"); test(-123, "0"); test(i64::MAX, "9223372036854775807"); test(i64::MIN, "0"); } #[test] fn test_convertible_from_i64() { let test = |i: i64, out| { assert_eq!(Natural::convertible_from(i), out); }; test(0, true); test(123, true); test(-123, false); test(i64::MAX, true); test(i64::MIN, false); } #[allow(clippy::type_repetition_in_bounds)] fn unsigned_properties() where Natural: From, for<'a> T: TryFrom<&'a Natural>, u128: ExactFrom, { unsigned_gen::().test_properties(|u| { let n = Natural::from(u); assert!(n.is_valid()); assert_eq!(T::exact_from(&n), u); let n_alt: Natural = From::from(u128::exact_from(u)); assert_eq!(n_alt, n); }); } #[allow(clippy::type_repetition_in_bounds)] fn signed_properties() where Natural: TryFrom + ConvertibleFrom + SaturatingFrom, for<'a> T: TryFrom<&'a Natural>, i128: ExactFrom, { signed_gen::().test_properties(|i| { let on = Natural::try_from(i); assert!(on.as_ref().map_or(true, Natural::is_valid)); assert_eq!(on.is_ok(), i >= T::ZERO); assert_eq!(Natural::convertible_from(i), i >= T::ZERO); let n = Natural::saturating_from(i); assert!(n.is_valid()); on.as_ref().map_or_else( |_| { assert_eq!(n, 0); }, |x| { assert_eq!(*x, n); assert_eq!(T::exact_from(x), i); let n_alt: Natural = ExactFrom::exact_from(i128::exact_from(i)); assert_eq!(n_alt, n); }, ); }); } #[test] fn from_primitive_int_properties() { unsigned_gen::().test_properties(|u| { let n = Natural::from(u); assert_eq!(Natural::from(&BigUint::from(u)), n); assert_eq!(Natural::exact_from(&rug::Integer::from(u)), n); #[cfg(feature = "32_bit_limbs")] { let n_alt = Natural::const_from(u); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); unsigned_gen::().test_properties(|u| { let n = Natural::from(u); assert_eq!(Natural::from(&BigUint::from(u)), n); assert_eq!(Natural::exact_from(&rug::Integer::from(u)), n); #[cfg(not(feature = "32_bit_limbs"))] { let n_alt = Natural::const_from(u); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); apply_fn_to_unsigneds!(unsigned_properties); apply_fn_to_signeds!(signed_properties); } ================================================ FILE: malachite-nz/tests/natural/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use std::str::FromStr; #[test] fn test_is_integer() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().is_integer(), out); }; test("0", true); test("1", true); test("100", true); } #[test] fn is_integer_properties() { natural_gen().test_properties(|n| { assert!(n.is_integer()); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/mantissa_and_exponent/integer_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::IntegerMantissaAndExponent; use malachite_base::test_util::generators::unsigned_gen_var_1; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen_var_2, natural_unsigned_pair_gen_var_4}; use std::str::FromStr; #[test] fn test_integer_mantissa_and_exponent() { let test = |s: &str, mantissa: &str, exponent: u64| { let n = Natural::from_str(s).unwrap(); let mantissa = Natural::from_str(mantissa).unwrap(); let (actual_mantissa, actual_exponent) = n.integer_mantissa_and_exponent(); assert_eq!(actual_mantissa, mantissa); assert_eq!(actual_exponent, exponent); assert_eq!(n.integer_mantissa(), mantissa); assert_eq!(n.integer_exponent(), exponent); }; test("1", "1", 0); test("3", "3", 0); test("100", "25", 2); test("123", "123", 0); } #[test] #[should_panic] fn integer_mantissa_and_exponent_fail() { Natural::ZERO.integer_mantissa_and_exponent(); } #[test] fn test_from_integer_mantissa_and_exponent() { let test = |mantissa: &str, exponent: u64, out: Option<&str>| { let mantissa = Natural::from_str(mantissa).unwrap(); assert_eq!( <&Natural as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( mantissa, exponent ), out.map(|s| Natural::from_str(s).unwrap()) ); }; test("0", 5, Some("0")); test("1", 0, Some("1")); test("3", 0, Some("3")); test("25", 2, Some("100")); } #[test] fn integer_mantissa_and_exponent_properties() { natural_gen_var_2().test_properties(|n| { let (mantissa, exponent) = n.integer_mantissa_and_exponent(); assert_eq!(n.integer_mantissa(), mantissa); assert_eq!(n.integer_exponent(), exponent); assert!(mantissa.odd()); let n_alt = <&Natural as IntegerMantissaAndExponent::> ::from_integer_mantissa_and_exponent(mantissa, exponent); assert_eq!(n_alt.unwrap(), n); }); unsigned_gen_var_1::().test_properties(|x| { let (mantissa_1, exponent_1) = x.integer_mantissa_and_exponent(); let (mantissa_2, exponent_2) = Natural::from(x).integer_mantissa_and_exponent(); assert_eq!(mantissa_1, mantissa_2); assert_eq!(exponent_1, exponent_2); }); } #[test] fn from_integer_mantissa_and_exponent_properties() { natural_unsigned_pair_gen_var_4::().test_properties(|(m, e)| { let n = <&Natural as IntegerMantissaAndExponent<_, _, _>>::from_integer_mantissa_and_exponent( m.clone(), e, ) .unwrap(); if m.odd() { assert_eq!(n.integer_mantissa_and_exponent(), (m, e)); } }); } ================================================ FILE: malachite-nz/tests/natural/conversion/mantissa_and_exponent/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::mantissa_and_exponent::sci_mantissa_and_exponent_round; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ primitive_float_unsigned_pair_gen_var_1, primitive_float_unsigned_pair_gen_var_2, primitive_float_unsigned_rounding_mode_triple_gen_var_1, primitive_float_unsigned_rounding_mode_triple_gen_var_2, unsigned_gen_var_1, unsigned_rounding_mode_pair_gen_var_1, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen_var_2, natural_rounding_mode_pair_gen_var_2, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_sci_mantissa_and_exponent() { let test = |s: &str, mantissa: f32, exponent: u64| { let n = Natural::from_str(s).unwrap(); let (actual_mantissa, actual_exponent) = n.sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); assert_eq!(NiceFloat(n.sci_mantissa()), NiceFloat(mantissa)); assert_eq!( SciMantissaAndExponent::::sci_exponent(&n), exponent ); }; test("3", 1.5, 1); test("123", 1.921875, 6); test("1000000000", 1.8626451, 29); test("16777216", 1.0, 24); test("16777218", 1.0000001, 24); test("16777217", 1.0, 24); test("33554432", 1.0, 25); test("33554436", 1.0000001, 25); test("33554440", 1.0000002, 25); test("33554433", 1.0, 25); test("33554434", 1.0, 25); test("33554435", 1.0000001, 25); test("33554437", 1.0000001, 25); test("33554438", 1.0000002, 25); test("33554439", 1.0000002, 25); test("340282346638528859811704183484516925439", 1.9999999, 127); test("340282346638528859811704183484516925440", 1.9999999, 127); test("340282346638528859811704183484516925441", 1.9999999, 127); test( "10000000000000000000000000000000000000000000000000000", 1.670478, 172, ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", 1.8920966, 458, ); } #[test] fn test_sci_mantissa_and_exponent_round() { let test = |n: &str, rm: RoundingMode, out: Option<(f32, u64, Ordering)>| { let actual_out = Natural::from_str(n) .unwrap() .sci_mantissa_and_exponent_round(rm); assert_eq!( actual_out.map(|(m, e, o)| (NiceFloat(m), e, o)), out.map(|(m, e, o)| (NiceFloat(m), e, o)) ); }; test("3", Floor, Some((1.5, 1, Equal))); test("3", Down, Some((1.5, 1, Equal))); test("3", Ceiling, Some((1.5, 1, Equal))); test("3", Up, Some((1.5, 1, Equal))); test("3", Nearest, Some((1.5, 1, Equal))); test("3", Exact, Some((1.5, 1, Equal))); test("123", Floor, Some((1.921875, 6, Equal))); test("123", Down, Some((1.921875, 6, Equal))); test("123", Ceiling, Some((1.921875, 6, Equal))); test("123", Up, Some((1.921875, 6, Equal))); test("123", Nearest, Some((1.921875, 6, Equal))); test("123", Exact, Some((1.921875, 6, Equal))); test("1000000000", Floor, Some((1.8626451, 29, Equal))); test("1000000000", Down, Some((1.8626451, 29, Equal))); test("1000000000", Ceiling, Some((1.8626451, 29, Equal))); test("1000000000", Up, Some((1.8626451, 29, Equal))); test("1000000000", Nearest, Some((1.8626451, 29, Equal))); test("1000000000", Exact, Some((1.8626451, 29, Equal))); test("16777216", Floor, Some((1.0, 24, Equal))); test("16777216", Down, Some((1.0, 24, Equal))); test("16777216", Ceiling, Some((1.0, 24, Equal))); test("16777216", Up, Some((1.0, 24, Equal))); test("16777216", Nearest, Some((1.0, 24, Equal))); test("16777216", Exact, Some((1.0, 24, Equal))); test("16777218", Floor, Some((1.0000001, 24, Equal))); test("16777218", Down, Some((1.0000001, 24, Equal))); test("16777218", Ceiling, Some((1.0000001, 24, Equal))); test("16777218", Up, Some((1.0000001, 24, Equal))); test("16777218", Nearest, Some((1.0000001, 24, Equal))); test("16777218", Exact, Some((1.0000001, 24, Equal))); test("16777217", Floor, Some((1.0, 24, Less))); test("16777217", Down, Some((1.0, 24, Less))); test("16777217", Ceiling, Some((1.0000001, 24, Greater))); test("16777217", Up, Some((1.0000001, 24, Greater))); test("16777217", Nearest, Some((1.0, 24, Less))); test("16777217", Exact, None); test("33554432", Floor, Some((1.0, 25, Equal))); test("33554432", Down, Some((1.0, 25, Equal))); test("33554432", Ceiling, Some((1.0, 25, Equal))); test("33554432", Up, Some((1.0, 25, Equal))); test("33554432", Nearest, Some((1.0, 25, Equal))); test("33554432", Exact, Some((1.0, 25, Equal))); test("33554436", Floor, Some((1.0000001, 25, Equal))); test("33554436", Down, Some((1.0000001, 25, Equal))); test("33554436", Ceiling, Some((1.0000001, 25, Equal))); test("33554436", Up, Some((1.0000001, 25, Equal))); test("33554436", Nearest, Some((1.0000001, 25, Equal))); test("33554436", Exact, Some((1.0000001, 25, Equal))); test("33554440", Floor, Some((1.0000002, 25, Equal))); test("33554440", Down, Some((1.0000002, 25, Equal))); test("33554440", Ceiling, Some((1.0000002, 25, Equal))); test("33554440", Up, Some((1.0000002, 25, Equal))); test("33554440", Nearest, Some((1.0000002, 25, Equal))); test("33554440", Exact, Some((1.0000002, 25, Equal))); test("33554433", Floor, Some((1.0, 25, Less))); test("33554433", Down, Some((1.0, 25, Less))); test("33554433", Ceiling, Some((1.0000001, 25, Greater))); test("33554433", Up, Some((1.0000001, 25, Greater))); test("33554433", Nearest, Some((1.0, 25, Less))); test("33554433", Exact, None); test("33554434", Floor, Some((1.0, 25, Less))); test("33554434", Down, Some((1.0, 25, Less))); test("33554434", Ceiling, Some((1.0000001, 25, Greater))); test("33554434", Up, Some((1.0000001, 25, Greater))); test("33554434", Nearest, Some((1.0, 25, Less))); test("33554434", Exact, None); test("33554435", Floor, Some((1.0, 25, Less))); test("33554435", Down, Some((1.0, 25, Less))); test("33554435", Ceiling, Some((1.0000001, 25, Greater))); test("33554435", Up, Some((1.0000001, 25, Greater))); test("33554435", Nearest, Some((1.0000001, 25, Greater))); test("33554435", Exact, None); test("33554437", Floor, Some((1.0000001, 25, Less))); test("33554437", Down, Some((1.0000001, 25, Less))); test("33554437", Ceiling, Some((1.0000002, 25, Greater))); test("33554437", Up, Some((1.0000002, 25, Greater))); test("33554437", Nearest, Some((1.0000001, 25, Less))); test("33554437", Exact, None); test("33554438", Floor, Some((1.0000001, 25, Less))); test("33554438", Down, Some((1.0000001, 25, Less))); test("33554438", Ceiling, Some((1.0000002, 25, Greater))); test("33554438", Up, Some((1.0000002, 25, Greater))); test("33554438", Nearest, Some((1.0000002, 25, Greater))); test("33554438", Exact, None); test("33554439", Floor, Some((1.0000001, 25, Less))); test("33554439", Down, Some((1.0000001, 25, Less))); test("33554439", Ceiling, Some((1.0000002, 25, Greater))); test("33554439", Up, Some((1.0000002, 25, Greater))); test("33554439", Nearest, Some((1.0000002, 25, Greater))); test("33554439", Exact, None); test( "340282346638528859811704183484516925439", Floor, Some((1.9999998, 127, Less)), ); test( "340282346638528859811704183484516925439", Down, Some((1.9999998, 127, Less)), ); test( "340282346638528859811704183484516925439", Ceiling, Some((1.9999999, 127, Greater)), ); test( "340282346638528859811704183484516925439", Up, Some((1.9999999, 127, Greater)), ); test( "340282346638528859811704183484516925439", Nearest, Some((1.9999999, 127, Greater)), ); test("340282346638528859811704183484516925439", Exact, None); test( "340282346638528859811704183484516925440", Floor, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Down, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Ceiling, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Up, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Nearest, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Exact, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925441", Floor, Some((1.9999999, 127, Less)), ); test( "340282346638528859811704183484516925441", Down, Some((1.9999999, 127, Less)), ); test( "340282346638528859811704183484516925441", Ceiling, Some((1.0, 128, Greater)), ); test( "340282346638528859811704183484516925441", Up, Some((1.0, 128, Greater)), ); test( "340282346638528859811704183484516925441", Nearest, Some((1.9999999, 127, Less)), ); test("340282346638528859811704183484516925441", Exact, None); test( "10000000000000000000000000000000000000000000000000000", Floor, Some((1.6704779, 172, Less)), ); test( "10000000000000000000000000000000000000000000000000000", Down, Some((1.6704779, 172, Less)), ); test( "10000000000000000000000000000000000000000000000000000", Ceiling, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Up, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Nearest, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Exact, None, ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Floor, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Down, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Ceiling, Some((1.8920968, 458, Greater)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Up, Some((1.8920968, 458, Greater)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Nearest, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Exact, None, ); test( "115792089210356248957287600559322556832945588264647333956682042358504754249728", Floor, Some((1.9999999, 255, Less)), ); test( "115792089210356248957287600559322556832945588264647333956682042358504754249728", Ceiling, Some((1.0, 256, Greater)), ); } #[test] fn test_from_sci_mantissa_and_exponent() { let test = |mantissa: f32, exponent: u64, out: Option<&str>| { assert_eq!( <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, exponent ), out.map(|s| Natural::from_str(s).unwrap()) ); }; test(1.5, 1, Some("3")); test(1.51, 1, Some("3")); test(1.921875, 6, Some("123")); test( 1.670478, 172, Some("10000000254586612611935772707803116801852191350456320"), ); test(2.0, 1, None); test(10.0, 1, None); test(0.5, 1, None); } fn from_sci_mantissa_and_exponent_fail_helper() where for<'a> &'a Natural: SciMantissaAndExponent, { assert_panic!( <&Natural as SciMantissaAndExponent>::from_sci_mantissa_and_exponent(T::ZERO, 0) ); } #[test] fn from_sci_mantissa_and_exponent_fail() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_fail_helper); } #[test] fn test_from_sci_mantissa_and_exponent_round() { let test = |mantissa: f32, exponent: u64, rm: RoundingMode, out: Option<(&str, Ordering)>| { assert_eq!( Natural::from_sci_mantissa_and_exponent_round(mantissa, exponent, rm), out.map(|(s, o)| (Natural::from_str(s).unwrap(), o)) ); }; test(1.5, 1, Floor, Some(("3", Equal))); test(1.5, 1, Down, Some(("3", Equal))); test(1.5, 1, Ceiling, Some(("3", Equal))); test(1.5, 1, Up, Some(("3", Equal))); test(1.5, 1, Nearest, Some(("3", Equal))); test(1.5, 1, Exact, Some(("3", Equal))); test(1.51, 1, Floor, Some(("3", Less))); test(1.51, 1, Down, Some(("3", Less))); test(1.51, 1, Ceiling, Some(("4", Greater))); test(1.51, 1, Up, Some(("4", Greater))); test(1.51, 1, Nearest, Some(("3", Less))); test(1.51, 1, Exact, None); test(1.921875, 6, Floor, Some(("123", Equal))); test(1.921875, 6, Down, Some(("123", Equal))); test(1.921875, 6, Ceiling, Some(("123", Equal))); test(1.921875, 6, Up, Some(("123", Equal))); test(1.921875, 6, Nearest, Some(("123", Equal))); test(1.921875, 6, Exact, Some(("123", Equal))); test( 1.670478, 172, Floor, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test( 1.670478, 172, Down, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test( 1.670478, 172, Ceiling, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test( 1.670478, 172, Up, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test( 1.670478, 172, Nearest, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test( 1.670478, 172, Exact, Some(( "10000000254586612611935772707803116801852191350456320", Equal, )), ); test(2.0, 1, Floor, None); test(2.0, 1, Down, None); test(2.0, 1, Ceiling, None); test(2.0, 1, Up, None); test(2.0, 1, Nearest, None); test(2.0, 1, Exact, None); test(10.0, 1, Floor, None); test(10.0, 1, Down, None); test(10.0, 1, Ceiling, None); test(10.0, 1, Up, None); test(10.0, 1, Nearest, None); test(10.0, 1, Exact, None); test(0.5, 1, Floor, None); test(0.5, 1, Down, None); test(0.5, 1, Ceiling, None); test(0.5, 1, Up, None); test(0.5, 1, Nearest, None); test(0.5, 1, Exact, None); } fn sci_mantissa_and_exponent_properties_helper() where for<'a> &'a Natural: SciMantissaAndExponent, Limb: SciMantissaAndExponent, { natural_gen_var_2().test_properties(|n| { let (mantissa, exponent) = n.sci_mantissa_and_exponent(); assert_eq!(NiceFloat(n.sci_mantissa()), NiceFloat(mantissa)); assert_eq!(n.sci_exponent(), exponent); assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); assert_eq!( n.sci_mantissa_and_exponent_round(Nearest) .map(|(m, e, _): (T, u64, Ordering)| (NiceFloat(m), e)), Some((NiceFloat(mantissa), exponent)) ); }); unsigned_gen_var_1::().test_properties(|x| { let (mantissa_1, exponent_1) = x.sci_mantissa_and_exponent(); let (mantissa_2, exponent_2) = Natural::from(x).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(mantissa_1), NiceFloat(mantissa_2)); assert_eq!(exponent_1, exponent_2); }); } #[test] fn sci_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_properties_helper); } fn sci_mantissa_and_exponent_round_properties_helper() { natural_rounding_mode_pair_gen_var_2().test_properties(|(n, rm)| { if let Some((mantissa, exponent, o)) = n.sci_mantissa_and_exponent_round::(rm) { assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); if rm == Exact { let n_alt = Natural::from_sci_mantissa_and_exponent_round(mantissa, exponent, rm) .unwrap() .0; assert_eq!(n_alt, n); } match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } } }); natural_gen_var_2().test_properties(|n| { let (floor_mantissa, floor_exponent, floor_o) = n.sci_mantissa_and_exponent_round::(Floor).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round::(Down).unwrap(), (floor_mantissa, floor_exponent, floor_o) ); let (ceiling_mantissa, ceiling_exponent, ceiling_o) = n.sci_mantissa_and_exponent_round::(Ceiling).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round::(Up).unwrap(), (ceiling_mantissa, ceiling_exponent, ceiling_o) ); let (nearest_mantissa, nearest_exponent, nearest_o) = n.sci_mantissa_and_exponent_round::(Nearest).unwrap(); if let Some((mantissa, exponent, o)) = n.sci_mantissa_and_exponent_round::(Exact) { assert_eq!(floor_mantissa, mantissa); assert_eq!(ceiling_mantissa, mantissa); assert_eq!(nearest_mantissa, mantissa); assert_eq!(floor_exponent, exponent); assert_eq!(ceiling_exponent, exponent); assert_eq!(nearest_exponent, exponent); assert_eq!(o, Equal); assert_eq!(floor_o, Equal); assert_eq!(ceiling_o, Equal); assert_eq!(nearest_o, Equal); } else { assert_eq!(floor_o, Less); assert_eq!(ceiling_o, Greater); assert_ne!( (floor_mantissa, floor_exponent), (ceiling_mantissa, ceiling_exponent) ); assert!( (nearest_mantissa, nearest_exponent) == (floor_mantissa, floor_exponent) || (nearest_mantissa, nearest_exponent) == (ceiling_mantissa, ceiling_exponent) ); if ceiling_mantissa == T::ONE { assert_eq!(floor_mantissa, T::TWO.next_lower()); assert_eq!(floor_exponent, ceiling_exponent - 1); } else { assert_eq!(floor_mantissa, ceiling_mantissa.next_lower()); assert_eq!(floor_exponent, ceiling_exponent); } } }); unsigned_rounding_mode_pair_gen_var_1::().test_properties(|(x, rm)| { assert_eq!( sci_mantissa_and_exponent_round::(x, rm).map(|(m, e, o)| (NiceFloat(m), e, o)), Natural::from(x) .sci_mantissa_and_exponent_round(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)) ); }); } #[test] fn sci_mantissa_and_exponent_round_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_round_properties_helper); } fn from_sci_mantissa_and_exponent_properties_helper() where for<'a> &'a Natural: SciMantissaAndExponent, { primitive_float_unsigned_pair_gen_var_1::().test_properties(|(m, e)| { let on = <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e); assert_eq!(on.is_some(), m >= T::ONE && m < T::TWO); }); primitive_float_unsigned_pair_gen_var_2::().test_properties(|(m, e)| { let n = <&Natural as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) .unwrap(); assert!(m >= T::ONE && m < T::TWO); assert_eq!( Natural::from_sci_mantissa_and_exponent_round(m, e, Nearest) .unwrap() .0, n ); }); } #[test] fn from_sci_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_properties_helper); } fn from_sci_mantissa_and_exponent_round_properties_helper() { primitive_float_unsigned_rounding_mode_triple_gen_var_1::().test_properties( |(m, e, rm)| { let on = Natural::from_sci_mantissa_and_exponent_round(m, e, rm); if let Some((_, o)) = on { assert!(m >= T::ONE && m < T::TWO); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } } else { assert!(m < T::ONE || m >= T::TWO || rm == Exact); } }, ); primitive_float_unsigned_rounding_mode_triple_gen_var_2::().test_properties(|(m, e, rm)| { assert!(m >= T::ONE && m < T::TWO); let on = Natural::from_sci_mantissa_and_exponent_round(m, e, rm); if on.is_none() { assert_eq!(rm, Exact); } }); primitive_float_unsigned_pair_gen_var_2::().test_properties(|(m, e)| { let floor_n = Natural::from_sci_mantissa_and_exponent_round(m, e, Floor).unwrap(); assert_eq!( Natural::from_sci_mantissa_and_exponent_round(m, e, Down).unwrap(), floor_n ); let ceiling_n = Natural::from_sci_mantissa_and_exponent_round(m, e, Ceiling).unwrap(); assert_eq!( Natural::from_sci_mantissa_and_exponent_round(m, e, Up).unwrap(), ceiling_n ); let nearest_n = Natural::from_sci_mantissa_and_exponent_round(m, e, Nearest).unwrap(); if let Some(n) = Natural::from_sci_mantissa_and_exponent_round(m, e, Exact) { assert_eq!(floor_n, n); assert_eq!(ceiling_n, n); assert_eq!(nearest_n, n); } else { assert!(nearest_n == floor_n || nearest_n == ceiling_n); assert_eq!(ceiling_n, (floor_n.0 + Natural::ONE, Greater)); } }); } #[test] fn from_sci_mantissa_and_exponent_round_properties() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_round_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/conversion/primitive_float_from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_18, unsigned_rounding_mode_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::primitive_float_from_natural::PrimitiveFloatFromNaturalError; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_gen_var_3, natural_gen_var_4, natural_gen_var_5, natural_rounding_mode_pair_gen_var_1, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_f32_rounding_from_natural() { let test = |n: &str, rm: RoundingMode, out, o_out| { let (x, o) = f32::rounding_from(&Natural::from_str(n).unwrap(), rm); assert_eq!(NiceFloat(x), NiceFloat(out)); assert_eq!(o, o_out); }; test("3", Exact, 3.0, Equal); test("123", Exact, 123.0, Equal); test("0", Exact, 0.0, Equal); test("1000000000", Exact, 1.0e9, Equal); test("16777216", Exact, 1.6777216e7, Equal); test("16777218", Exact, 1.6777218e7, Equal); test("16777217", Floor, 1.6777216e7, Less); test("16777217", Down, 1.6777216e7, Less); test("16777217", Ceiling, 1.6777218e7, Greater); test("16777217", Up, 1.6777218e7, Greater); test("16777217", Nearest, 1.6777216e7, Less); test("33554432", Exact, 3.3554432e7, Equal); test("33554436", Exact, 3.3554436e7, Equal); test("33554433", Floor, 3.3554432e7, Less); test("33554433", Down, 3.3554432e7, Less); test("33554433", Ceiling, 3.3554436e7, Greater); test("33554433", Up, 3.3554436e7, Greater); test("33554433", Nearest, 3.3554432e7, Less); test("33554434", Nearest, 3.3554432e7, Less); test("33554435", Nearest, 3.3554436e7, Greater); test( "340282346638528859811704183484516925439", Floor, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Down, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Ceiling, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Up, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Nearest, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925440", Exact, 3.4028235e38, Equal, ); test( "340282346638528859811704183484516925441", Floor, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Down, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Nearest, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Ceiling, f32::INFINITY, Greater, ); test( "340282346638528859811704183484516925441", Up, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Floor, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Down, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Nearest, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Ceiling, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Up, f32::INFINITY, Greater, ); test("1125899873419263", Floor, 1.12589984e15, Less); test("1125899873419263", Down, 1.12589984e15, Less); test("1125899873419263", Ceiling, 1.1258999e15, Greater); test("1125899873419263", Up, 1.1258999e15, Greater); test("1125899873419263", Nearest, 1.1258999e15, Greater); } #[test] #[should_panic] fn f32_rounding_from_natural_fail_1() { f32::rounding_from( &Natural::from_str("340282346638528859811704183484516925439").unwrap(), Exact, ); } #[test] #[should_panic] fn f32_rounding_from_natural_fail_2() { f32::rounding_from( &Natural::from_str("340282346638528859811704183484516925441").unwrap(), Exact, ); } #[test] #[should_panic] fn f32_rounding_from_natural_fail_3() { f32::rounding_from(&Natural::from_str("16777217").unwrap(), Exact); } #[test] #[should_panic] fn f32_rounding_from_natural_fail_4() { f32::rounding_from( &Natural::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), Exact, ); } #[test] fn test_f64_rounding_from_natural() { let test = |n: &str, rm: RoundingMode, out, o_out| { let (x, o) = f64::rounding_from(&Natural::from_str(n).unwrap(), rm); assert_eq!(NiceFloat(x), NiceFloat(out)); assert_eq!(o, o_out); }; test("3", Exact, 3.0, Equal); test("123", Exact, 123.0, Equal); test("0", Exact, 0.0, Equal); test("100000000000000000000", Exact, 1.0e20, Equal); test("9007199254740992", Exact, 9.007199254740992e15, Equal); test("9007199254740994", Exact, 9.007199254740994e15, Equal); test("9007199254740993", Floor, 9.007199254740992e15, Less); test("9007199254740993", Down, 9.007199254740992e15, Less); test("9007199254740993", Ceiling, 9.007199254740994e15, Greater); test("9007199254740993", Up, 9.007199254740994e15, Greater); test("9007199254740993", Nearest, 9.007199254740992e15, Less); test("18014398509481984", Exact, 1.8014398509481984e16, Equal); test("18014398509481988", Exact, 1.8014398509481988e16, Equal); test("18014398509481985", Floor, 1.8014398509481984e16, Less); test("18014398509481985", Down, 1.8014398509481984e16, Less); test("18014398509481985", Ceiling, 1.8014398509481988e16, Greater); test("18014398509481985", Up, 1.8014398509481988e16, Greater); test("18014398509481985", Nearest, 1.8014398509481984e16, Less); test("18014398509481986", Nearest, 1.8014398509481984e16, Less); test("18014398509481987", Nearest, 1.8014398509481988e16, Greater); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Floor, 1.7976931348623155e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Down, 1.7976931348623155e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Ceiling, 1.7976931348623157e308, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Up, 1.7976931348623157e308, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Nearest, 1.7976931348623157e308, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", Exact, 1.7976931348623157e308, Equal, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Floor, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Down, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Nearest, 1.7976931348623157e308, Less, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Ceiling, f64::INFINITY, Greater, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Up, f64::INFINITY, Greater, ); } #[test] #[should_panic] fn f64_rounding_from_natural_fail_1() { f64::rounding_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap(), Exact); } #[test] #[should_panic] fn f64_rounding_from_natural_fail_2() { f64::rounding_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap(), Exact); } #[test] #[should_panic] fn f64_rounding_from_natural_fail_3() { f64::rounding_from(&Natural::from_str("9007199254740993").unwrap(), Exact); } #[test] fn test_f32_try_from_natural() { let test = |n: &str, out: Result| { assert_eq!( f32::try_from(&Natural::from_str(n).unwrap()).map(NiceFloat), out.map(NiceFloat) ); }; test("3", Ok(3.0)); test("123", Ok(123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("16777216", Ok(1.6777216e7)); test("16777218", Ok(1.6777218e7)); test("16777217", Err(PrimitiveFloatFromNaturalError)); test("33554432", Ok(3.3554432e7)); test("33554436", Ok(3.3554436e7)); test("33554433", Err(PrimitiveFloatFromNaturalError)); test("33554434", Err(PrimitiveFloatFromNaturalError)); test("33554435", Err(PrimitiveFloatFromNaturalError)); test( "340282346638528859811704183484516925439", Err(PrimitiveFloatFromNaturalError), ); test("340282346638528859811704183484516925440", Ok(3.4028235e38)); test( "340282346638528859811704183484516925441", Err(PrimitiveFloatFromNaturalError), ); test( "10000000000000000000000000000000000000000000000000000", Err(PrimitiveFloatFromNaturalError), ); } #[test] fn test_f64_try_from_natural() { let test = |n: &str, out: Result| { assert_eq!( f64::try_from(&Natural::from_str(n).unwrap()).map(NiceFloat), out.map(NiceFloat) ); }; test("3", Ok(3.0)); test("123", Ok(123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("9007199254740992", Ok(9.007199254740992e15)); test("9007199254740994", Ok(9.007199254740994e15)); test("9007199254740993", Err(PrimitiveFloatFromNaturalError)); test("18014398509481984", Ok(1.8014398509481984e16)); test("18014398509481988", Ok(1.8014398509481988e16)); test("18014398509481985", Err(PrimitiveFloatFromNaturalError)); test("18014398509481986", Err(PrimitiveFloatFromNaturalError)); test("18014398509481987", Err(PrimitiveFloatFromNaturalError)); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Err(PrimitiveFloatFromNaturalError), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", Ok(1.7976931348623157e308), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Err(PrimitiveFloatFromNaturalError), ); } #[test] fn test_f32_exact_from_natural() { let test = |n: &str, out| { assert_eq!( NiceFloat(f32::exact_from(&Natural::from_str(n).unwrap())), NiceFloat(out) ); }; test("3", 3.0); test("123", 123.0); test("0", 0.0); test("1000000000", 1.0e9); test("16777216", 1.6777216e7); test("16777218", 1.6777218e7); test("33554432", 3.3554432e7); test("33554436", 3.3554436e7); test("340282346638528859811704183484516925440", 3.4028235e38); } #[test] #[should_panic] fn f32_exact_from_natural_fail_1() { f32::exact_from(&Natural::from_str("9007199254740993").unwrap()); } #[test] #[should_panic] fn f32_exact_from_natural_fail_2() { f32::exact_from(&Natural::from_str("18014398509481985").unwrap()); } #[test] #[should_panic] fn f32_exact_from_natural_fail_3() { f32::exact_from(&Natural::from_str("18014398509481986").unwrap()); } #[test] #[should_panic] fn f32_exact_from_natural_fail_4() { f32::exact_from(&Natural::from_str("18014398509481987").unwrap()); } #[test] #[should_panic] fn f32_exact_from_natural_fail_5() { f32::exact_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap()); } #[test] #[should_panic] fn f32_exact_from_natural_fail_6() { f32::exact_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap()); } #[test] fn test_f64_exact_from_natural() { let test = |n: &str, out| { assert_eq!( NiceFloat(f64::exact_from(&Natural::from_str(n).unwrap())), NiceFloat(out) ); }; test("3", 3.0); test("123", 123.0); test("0", 0.0); test("1000000000", 1.0e9); test("9007199254740992", 9.007199254740992e15); test("9007199254740994", 9.007199254740994e15); test("18014398509481984", 1.8014398509481984e16); test("18014398509481988", 1.8014398509481988e16); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", 1.7976931348623157e308, ); } #[test] #[should_panic] fn f64_exact_from_natural_fail_1() { f64::exact_from(&Natural::from_str("9007199254740993").unwrap()); } #[test] #[should_panic] fn f64_exact_from_natural_fail_2() { f64::exact_from(&Natural::from_str("18014398509481985").unwrap()); } #[test] #[should_panic] fn f64_exact_from_natural_fail_3() { f64::exact_from(&Natural::from_str("18014398509481986").unwrap()); } #[test] #[should_panic] fn f64_exact_from_natural_fail_4() { f64::exact_from(&Natural::from_str("18014398509481987").unwrap()); } #[test] #[should_panic] fn f64_exact_from_natural_fail_5() { f64::exact_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap()); } #[test] #[should_panic] fn f64_exact_from_natural_fail_6() { f64::exact_from(&Natural::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap()); } #[test] fn test_f32_convertible_from_natural() { let test = |n: &str, out| { assert_eq!(f32::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("3", true); test("123", true); test("0", true); test("1000000000", true); test("16777216", true); test("16777218", true); test("16777217", false); test("33554432", true); test("33554436", true); test("33554433", false); test("33554434", false); test("33554435", false); test("340282346638528859811704183484516925439", false); test("340282346638528859811704183484516925440", true); test("340282346638528859811704183484516925441", false); test( "10000000000000000000000000000000000000000000000000000", false, ); } #[test] fn test_f64_convertible_from_natural() { let test = |n: &str, out| { assert_eq!(f64::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("3", true); test("123", true); test("0", true); test("1000000000", true); test("9007199254740992", true); test("9007199254740994", true); test("9007199254740993", false); test("18014398509481984", true); test("18014398509481988", true); test("18014398509481985", false); test("18014398509481986", false); test("18014398509481987", false); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", false, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", true, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", false, ); } fn float_rounding_from_natural_properties_helper< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Natural> + PartialOrd + PrimitiveFloat + for<'a> RoundingFrom<&'a Natural>, >() where Natural: TryFrom + RoundingFrom, { natural_rounding_mode_pair_gen_var_1::().test_properties(|(n, rm)| { let o = T::rounding_from(&n, rm).1; match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } }); natural_gen_var_3::().test_properties(|n| { let (f, o) = T::rounding_from(&n, Exact); assert_eq!(o, Equal); let fo = (NiceFloat(f), o); let (f_alt, o_alt) = T::rounding_from(&n, Floor); assert_eq!((NiceFloat(f_alt), o_alt), fo); let (f_alt, o_alt) = T::rounding_from(&n, Ceiling); assert_eq!((NiceFloat(f_alt), o_alt), fo); let (f_alt, o_alt) = T::rounding_from(&n, Down); assert_eq!((NiceFloat(f_alt), o_alt), fo); let (f_alt, o_alt) = T::rounding_from(&n, Up); assert_eq!((NiceFloat(f_alt), o_alt), fo); let (f_alt, o_alt) = T::rounding_from(&n, Nearest); assert_eq!((NiceFloat(f_alt), o_alt), fo); assert_eq!(Natural::rounding_from(f, Exact), (n, Equal)); }); natural_gen_var_4::().test_properties(|n| { let f_below = T::rounding_from(&n, Floor); assert_eq!(f_below.1, Less); let f_above = (NiceFloat(f_below.0.next_higher()), Greater); let f_below = (NiceFloat(f_below.0), f_below.1); let (f, o) = T::rounding_from(&n, Ceiling); assert_eq!((NiceFloat(f), o), f_above); let (f, o) = T::rounding_from(&n, Down); assert_eq!((NiceFloat(f), o), f_below); let (f, o) = T::rounding_from(&n, Up); assert_eq!((NiceFloat(f), o), f_above); let f_nearest = T::rounding_from(&n, Nearest); let f_nearest = (NiceFloat(f_nearest.0), f_nearest.1); assert!(f_nearest == f_below || f_nearest == f_above); }); natural_gen_var_5::().test_properties(|n| { let floor = T::rounding_from(&n, Floor); assert_eq!(floor.1, Less); let ceiling = (NiceFloat(floor.0.next_higher()), Greater); let floor = (NiceFloat(floor.0), floor.1); let nearest = T::rounding_from(&n, Nearest); let nearest = (NiceFloat(nearest.0), nearest.1); assert_eq!( nearest, if floor.0.0.to_bits().even() { floor } else { ceiling } ); }); unsigned_rounding_mode_pair_gen_var_2::().test_properties(|(u, rm)| { let n: Natural = From::from(u); let (f, o) = T::rounding_from(u, rm); let (f_alt, o_alt) = T::rounding_from(&n, rm); assert_eq!(NiceFloat(f), NiceFloat(f_alt)); assert_eq!(o, o_alt); assert_eq!(f.partial_cmp(&n), Some(o)); }); } #[test] fn float_rounding_from_natural_properties() { apply_fn_to_primitive_floats!(float_rounding_from_natural_properties_helper); } fn float_try_from_natural_properties_helper< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat + for<'a> RoundingFrom<&'a Natural>, >() where Limb: RoundingFrom, Natural: TryFrom + RoundingFrom, NiceFloat: TryFrom, { natural_gen().test_properties(|n| { T::try_from(&n).ok(); }); natural_gen_var_3::().test_properties(|n| { let f = T::exact_from(&n); assert_eq!(NiceFloat(f), NiceFloat(T::rounding_from(&n, Exact).0)); assert_eq!(Natural::rounding_from(f, Exact).0, n); }); natural_gen_var_4::().test_properties(|n| { assert!(T::try_from(&n).is_err()); }); natural_gen_var_5::().test_properties(|n| { assert!(T::try_from(&n).is_err()); }); unsigned_gen::().test_properties(|u| { if let Ok(f) = NiceFloat::::try_from(u) { let n: Natural = From::from(u); assert_eq!(f, NiceFloat(T::exact_from(&n))); } }); unsigned_gen_var_18::().test_properties(|u| { let n: Natural = From::from(u); assert_eq!(NiceFloat::::exact_from(u), NiceFloat(T::exact_from(&n))); }); } #[test] fn float_try_from_natural_properties() { apply_fn_to_primitive_floats!(float_try_from_natural_properties_helper); } fn float_convertible_from_natural_properties_helper< T: for<'a> TryFrom<&'a Natural> + for<'a> ConvertibleFrom<&'a Natural> + PrimitiveFloat, >() where Natural: TryFrom, { natural_gen().test_properties(|n| { T::convertible_from(&n); }); natural_gen_var_3::().test_properties(|n| { assert!(T::convertible_from(&n)); }); natural_gen_var_4::().test_properties(|n| { assert!(!T::convertible_from(&n)); }); natural_gen_var_5::().test_properties(|n| { assert!(!T::convertible_from(&n)); }); unsigned_gen::().test_properties(|u| { let n: Natural = From::from(u); assert_eq!(T::convertible_from(u), T::convertible_from(&n)); }); } #[test] fn float_convertible_from_natural_properties() { apply_fn_to_primitive_floats!(float_convertible_from_natural_properties_helper); } ================================================ FILE: malachite-nz/tests/natural/conversion/primitive_int_from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::ModPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, OverflowingFrom, SaturatingFrom, WrappingFrom, }; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::primitive_int_from_natural::{ SignedFromNaturalError, UnsignedFromNaturalError, }; use malachite_nz::test_util::generators::natural_gen; use rug; use std::str::FromStr; #[test] fn test_u32_try_from_natural() { let test = |n, out| { assert_eq!(u32::try_from(&Natural::from_str(n).unwrap()), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .to_u32() .ok_or(UnsignedFromNaturalError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Err(UnsignedFromNaturalError)); test("4294967295", Ok(u32::MAX)); test("4294967296", Err(UnsignedFromNaturalError)); } #[test] fn test_u32_exact_from_natural() { let test = |n, out| { assert_eq!(u32::exact_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_u32().unwrap(), out); }; test("0", 0); test("123", 123); test("4294967295", u32::MAX); } #[test] #[should_panic] fn u32_exact_from_natural_fail_1() { u32::exact_from(&Natural::from_str("1000000000000").unwrap()); } #[test] #[should_panic] fn u32_exact_from_natural_fail_2() { u32::exact_from(&Natural::from_str("4294967296").unwrap()); } #[test] fn test_u32_wrapping_from_natural() { let test = |n, out| { assert_eq!(u32::wrapping_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_u32_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000", 3567587328); test("4294967296", 0); test("4294967297", 1); } #[test] fn test_u32_saturating_from_natural() { let test = |n, out| { assert_eq!(u32::saturating_from(&Natural::from_str(n).unwrap()), out); }; test("0", 0); test("123", 123); test("1000000000000", u32::MAX); test("4294967296", u32::MAX); test("4294967297", u32::MAX); } #[test] fn test_u32_overflowing_from_natural() { let test = |n, out| { assert_eq!(u32::overflowing_from(&Natural::from_str(n).unwrap()), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000", (3567587328, true)); test("4294967296", (0, true)); test("4294967297", (1, true)); } #[test] fn test_u32_convertible_from_natural() { let test = |n, out| { assert_eq!(u32::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("0", true); test("123", true); test("1000000000000", false); test("4294967295", true); test("4294967296", false); } #[test] fn test_u64_try_from_natural() { let test = |n, out| { assert_eq!(u64::try_from(&Natural::from_str(n).unwrap()), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .to_u64() .ok_or(UnsignedFromNaturalError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Ok(1000000000000)); test("1000000000000000000000000", Err(UnsignedFromNaturalError)); test("18446744073709551615", Ok(u64::MAX)); test("18446744073709551616", Err(UnsignedFromNaturalError)); } #[test] fn test_u64_exact_from_natural() { let test = |n, out| { assert_eq!(u64::exact_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_u64().unwrap(), out); }; test("0", 0); test("123", 123); test("1000000000000", 1000000000000); test("18446744073709551615", u64::MAX); } #[test] #[should_panic] fn u64_exact_from_natural_fail_1() { u64::exact_from(&Natural::from_str("1000000000000000000000000").unwrap()); } #[test] #[should_panic] fn u64_exact_from_natural_fail_2() { u64::exact_from(&Natural::from_str("18446744073709551616").unwrap()); } #[test] fn test_u64_wrapping_from_natural() { let test = |n, out| { assert_eq!(u64::wrapping_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_u64_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 2003764205206896640); test("18446744073709551616", 0); test("18446744073709551617", 1); } #[test] fn test_u64_saturating_from_natural() { let test = |n, out| { assert_eq!(u64::saturating_from(&Natural::from_str(n).unwrap()), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", u64::MAX); test("18446744073709551616", u64::MAX); test("18446744073709551617", u64::MAX); } #[test] fn test_u64_overflowing_from_natural() { let test = |n, out| { assert_eq!(u64::overflowing_from(&Natural::from_str(n).unwrap()), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000000000000000", (2003764205206896640, true)); test("18446744073709551616", (0, true)); test("18446744073709551617", (1, true)); } #[test] fn test_u64_convertible_from_natural() { let test = |n, out| { assert_eq!(u64::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("0", true); test("123", true); test("1000000000000000000000000", false); test("18446744073709551615", true); test("18446744073709551616", false); } #[test] fn test_i32_try_from_natural() { let test = |n, out| { assert_eq!(i32::try_from(&Natural::from_str(n).unwrap()), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .to_i32() .ok_or(SignedFromNaturalError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000", Err(SignedFromNaturalError)); test("2147483647", Ok(i32::MAX)); test("2147483648", Err(SignedFromNaturalError)); } #[test] fn test_i32_exact_from_natural() { let test = |n, out| { assert_eq!(i32::exact_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_i32().unwrap(), out); }; test("0", 0); test("123", 123); test("2147483647", i32::MAX); } #[test] #[should_panic] fn i32_exact_from_natural_fail_1() { i32::exact_from(&Natural::from_str("1000000000000").unwrap()); } #[test] #[should_panic] fn i32_exact_from_natural_fail_2() { i32::exact_from(&Natural::from_str("2147483648").unwrap()); } #[test] fn test_i32_wrapping_from_natural() { let test = |n, out| { assert_eq!(i32::wrapping_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_i32_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000", -727379968); test("2147483648", -0x80000000); test("2147483649", -0x7fffffff); } #[test] fn test_i32_saturating_from_natural() { let test = |n, out| { assert_eq!(i32::saturating_from(&Natural::from_str(n).unwrap()), out); }; test("0", 0); test("123", 123); test("1000000000000", 0x7fffffff); test("2147483648", 0x7fffffff); test("2147483649", 0x7fffffff); } #[test] fn test_i32_overflowing_from_natural() { let test = |n, out| { assert_eq!(i32::overflowing_from(&Natural::from_str(n).unwrap()), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000", (-727379968, true)); test("2147483648", (-0x80000000, true)); test("2147483649", (-0x7fffffff, true)); } #[test] fn test_i32_convertible_from_natural() { let test = |n, out| { assert_eq!(i32::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("0", true); test("123", true); test("1000000000000", false); test("2147483647", true); test("2147483648", false); } #[test] fn test_i64_try_from_natural() { let test = |n, out: Result| { assert_eq!(i64::try_from(&Natural::from_str(n).unwrap()), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .to_i64() .ok_or(SignedFromNaturalError), out ); }; test("0", Ok(0)); test("123", Ok(123)); test("1000000000000000000000000", Err(SignedFromNaturalError)); test("9223372036854775807", Ok(i64::MAX)); test("9223372036854775808", Err(SignedFromNaturalError)); } #[test] fn test_i64_exact_from_natural() { let test = |n, out| { assert_eq!(i64::exact_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_i64().unwrap(), out); }; test("0", 0); test("123", 123); test("9223372036854775807", i64::MAX); } #[test] #[should_panic] fn i64_exact_from_natural_fail_1() { i64::exact_from(&Natural::from_str("1000000000000000000000000").unwrap()); } #[test] #[should_panic] fn i64_exact_from_natural_fail_2() { i64::exact_from(&Natural::from_str("9223372036854775808").unwrap()); } #[test] fn test_i64_wrapping_from_natural() { let test = |n, out| { assert_eq!(i64::wrapping_from(&Natural::from_str(n).unwrap()), out); assert_eq!(rug::Integer::from_str(n).unwrap().to_i64_wrapping(), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 2003764205206896640); test("9223372036854775808", -0x8000000000000000); test("9223372036854775809", -0x7fffffffffffffff); } #[test] fn test_i64_saturating_from_natural() { let test = |n, out| { assert_eq!(i64::saturating_from(&Natural::from_str(n).unwrap()), out); }; test("0", 0); test("123", 123); test("1000000000000000000000000", 0x7fffffffffffffff); test("9223372036854775808", 0x7fffffffffffffff); test("9223372036854775809", 0x7fffffffffffffff); } #[test] fn test_i64_overflowing_from_natural() { let test = |n, out| { assert_eq!(i64::overflowing_from(&Natural::from_str(n).unwrap()), out); }; test("0", (0, false)); test("123", (123, false)); test("1000000000000000000000000", (2003764205206896640, true)); test("9223372036854775808", (-0x8000000000000000, true)); test("9223372036854775809", (-0x7fffffffffffffff, true)); } #[test] fn test_i64_convertible_from_natural() { let test = |n, out| { assert_eq!(i64::convertible_from(&Natural::from_str(n).unwrap()), out); }; test("0", true); test("123", true); test("1000000000000000000000000", false); test("9223372036854775807", true); test("9223372036854775808", false); } fn primitive_int_properties< T: for<'a> ConvertibleFrom<&'a Natural> + for<'a> OverflowingFrom<&'a Natural> + PartialEq + PartialOrd + PrimitiveInt + for<'a> SaturatingFrom<&'a Natural> + for<'a> WrappingFrom<&'a Natural>, >() where Natural: PartialOrd, { natural_gen().test_properties(|x| { let result = T::wrapping_from(&x); assert_eq!(result, T::overflowing_from(&x).0); let result = T::saturating_from(&x); assert!(result <= x); assert_eq!(result == x, T::convertible_from(&x)); let result = T::overflowing_from(&x); assert_eq!(result, (T::wrapping_from(&x), !T::convertible_from(&x))); let convertible = T::convertible_from(&x); assert_eq!(convertible, x >= T::MIN && x <= T::MAX); }); } fn unsigned_properties< T: for<'a> TryFrom<&'a Natural, Error = UnsignedFromNaturalError> + for<'a> OverflowingFrom<&'a Natural> + PartialEq + PrimitiveUnsigned + for<'a> WrappingFrom<&'a Natural>, >() where Natural: From, { natural_gen().test_properties(|x| { let result = T::try_from(&x); if x.significant_bits() <= T::WIDTH { assert_eq!(Natural::from(result.unwrap()), x); assert_eq!(result, Ok(T::wrapping_from(&x))); assert_eq!(result, Ok(T::exact_from(&x))); } else { assert!(result.is_err()); } assert_eq!(result.is_err(), T::overflowing_from(&x).1); let result = T::wrapping_from(&x); assert_eq!(result, T::exact_from(&(&x).mod_power_of_2(T::WIDTH))); }); } fn signed_properties< T: for<'a> TryFrom<&'a Natural, Error = SignedFromNaturalError> + for<'a> OverflowingFrom<&'a Natural> + PartialEq + PrimitiveSigned + for<'a> WrappingFrom<&'a Natural>, >() where Natural: ExactFrom, { natural_gen().test_properties(|x| { let result = T::try_from(&x); if x >= 0 && x.significant_bits() < T::WIDTH { assert_eq!(Natural::exact_from(result.unwrap()), x); assert_eq!(result, Ok(T::wrapping_from(&x))); assert_eq!(result, Ok(T::exact_from(&x))); } else { assert!(result.is_err()); } assert_eq!(result.is_err(), T::overflowing_from(&x).1); }); } #[test] fn primitive_int_from_natural_properties() { apply_fn_to_primitive_ints!(primitive_int_properties); apply_fn_to_unsigneds!(unsigned_properties); apply_fn_to_signeds!(signed_properties); } ================================================ FILE: malachite-nz/tests/natural/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{string_gen, string_gen_var_8}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use std::str::FromStr; #[test] fn test_serde() { let test = |n, out| { assert_eq!( serde_json::to_string(&Natural::from_str(n).unwrap()).unwrap(), out ); assert_eq!(serde_json::from_str::(out).unwrap().to_string(), n); }; test("0", "\"0x0\""); test("100", "\"0x64\""); test("1000000000000", "\"0xe8d4a51000\""); test("4294967295", "\"0xffffffff\""); test("4294967296", "\"0x100000000\""); test("18446744073709551615", "\"0xffffffffffffffff\""); test("18446744073709551616", "\"0x10000000000000000\""); test("1000000000000000000000000", "\"0xd3c21bcecceda1000000\""); test( "340282366920938463463374607431768211455", "\"0xffffffffffffffffffffffffffffffff\"", ); test( "340282366920938463463374607431768211456", "\"0x100000000000000000000000000000000\"", ); } #[test] fn serde_properties() { natural_gen().test_properties(|x| { let s = serde_json::to_string(&x).unwrap(); assert_eq!(serde_json::from_str::(&s).unwrap(), x); assert_eq!(serde_json::from_str::(&s).unwrap(), x); assert!(string_is_subset(&s, "\"0123456789abcdefx")); }); string_gen().test_properties(|s| { let _n: Result = serde_json::from_str(&s); }); string_gen_var_8().test_properties(|s| { let n: Natural = serde_json::from_str(&s).unwrap(); let i: Integer = serde_json::from_str(&s).unwrap(); assert_eq!(n, i); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::{ExactFrom, FromSciString, ToStringBase}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use std::str::FromStr; #[test] pub fn test_from_sci_string() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Natural::from_str(s).unwrap()); assert_eq!(Natural::from_sci_string(s), out); assert_eq!( Natural::from_sci_string_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("123.4", Some("123")); test("123.8", Some("124")); test("123.5", Some("124")); test("124.5", Some("124")); test("127.49", Some("127")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Natural::from_str(s).unwrap()); assert_eq!(Natural::from_sci_string_with_options(s, options), out); } fn test_u(s: &str, options: FromSciStringOptions, out: Option) where Natural: From, { let out = out.map(Natural::from); assert_eq!(Natural::from_sci_string_with_options(s, options), out); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Natural: TryFrom, { let out = out.map(Natural::exact_from); assert_eq!(Natural::from_sci_string_with_options(s, options), out); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_u( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_u( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_u( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_u( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_u( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_u("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_u("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_u("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_rounding_mode(Down); test("123.4", options, Some("123")); options.set_rounding_mode(Floor); test("123.4", options, Some("123")); options.set_rounding_mode(Up); test("123.4", options, Some("124")); options.set_rounding_mode(Ceiling); test("123.4", options, Some("124")); options.set_rounding_mode(Nearest); test("123.4", options, Some("123")); options.set_rounding_mode(Exact); test("123.4", options, None); options.set_rounding_mode(Down); test("123.5", options, Some("123")); options.set_rounding_mode(Floor); test("123.5", options, Some("123")); options.set_rounding_mode(Up); test("123.5", options, Some("124")); options.set_rounding_mode(Ceiling); test("123.5", options, Some("124")); options.set_rounding_mode(Nearest); test("123.5", options, Some("124")); options.set_rounding_mode(Exact); test("123.5", options, None); options.set_rounding_mode(Down); test("0.4", options, Some("0")); options.set_rounding_mode(Floor); test("0.4", options, Some("0")); options.set_rounding_mode(Up); test("0.4", options, Some("1")); options.set_rounding_mode(Ceiling); test("0.4", options, Some("1")); options.set_rounding_mode(Nearest); test("0.4", options, Some("0")); options.set_rounding_mode(Exact); test("0.4", options, None); options.set_rounding_mode(Down); test("0.04", options, Some("0")); options.set_rounding_mode(Floor); test("0.04", options, Some("0")); options.set_rounding_mode(Up); test("0.04", options, Some("1")); options.set_rounding_mode(Ceiling); test("0.04", options, Some("1")); options.set_rounding_mode(Nearest); test("0.04", options, Some("0")); options.set_rounding_mode(Exact); test("0.04", options, None); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("1")); test("1.1", options, Some("2")); test("1.11", options, Some("2")); test("0.01", options, Some("0")); test("0.1", options, Some("0")); test("0.11", options, Some("1")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("1")); test("1.11", options, Some("1")); test("1.111", options, Some("1")); test("1.112", options, Some("2")); test("0.1", options, Some("0")); test("0.11", options, Some("0")); test("0.111", options, Some("0")); test("0.112", options, Some("1")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options = FromSciStringOptions::default(); options.set_rounding_mode(Exact); test("1.5", options, None); test("1.9999999999999999999999999999", options, None); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); options.set_rounding_mode(Down); test("-0.4", options, Some("0")); options.set_rounding_mode(Floor); test("-0.4", options, None); options.set_rounding_mode(Up); test("-0.4", options, None); options.set_rounding_mode(Ceiling); test("-0.4", options, Some("0")); options.set_rounding_mode(Nearest); test("-0.4", options, Some("0")); options.set_rounding_mode(Exact); test("-0.4", options, None); options.set_rounding_mode(Down); test("-0.04", options, Some("0")); options.set_rounding_mode(Floor); test("-0.04", options, None); options.set_rounding_mode(Up); test("-0.04", options, None); options.set_rounding_mode(Ceiling); test("-0.04", options, Some("0")); options.set_rounding_mode(Nearest); test("-0.04", options, Some("0")); options.set_rounding_mode(Exact); test("-0.04", options, None); } fn from_sci_string_helper(s: &str) { if let Some(x) = Natural::from_sci_string(s) { assert!(x.is_valid()); for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string(), s); } } #[test] fn from_sci_string_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_helper(&s); }); natural_gen().test_properties(|x| { assert_eq!(Natural::from_sci_string(&x.to_string()).unwrap(), x); }); } fn from_sci_string_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Natural::from_sci_string_with_options(s, options) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); for c in ['.', 'e', 'E', '+'] { if s.contains(c) { return; } } if s.starts_with('0') || s.starts_with("-0") { return; } assert_eq!(x.to_string_base(options.get_base()), s.to_lowercase()); } } #[test] fn from_sci_string_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ ExactFrom, FromStringBase, ToStringBase, WrappingFrom, }; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::exhaustive::valid_digit_chars; use malachite_base::test_util::generators::{ string_gen, string_gen_var_3, string_gen_var_5, string_gen_var_6, string_gen_var_7, unsigned_gen, unsigned_gen_var_11, unsigned_pair_gen_var_8, unsigned_pair_gen_var_19, unsigned_string_pair_gen_var_1, unsigned_string_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use num::{BigUint, Num}; use rug; use std::collections::HashMap; use std::str::FromStr; #[test] fn test_from_str() { let test_ok = |s, n| { assert_eq!(Natural::from_str(s).unwrap().to_string(), n); assert_eq!(BigUint::from_str(s).unwrap().to_string(), n); assert_eq!(rug::Integer::from_str(s).unwrap().to_string(), n); }; test_ok("0", "0"); test_ok("+0", "0"); test_ok("123456", "123456"); test_ok("+123456", "123456"); test_ok("1000000000000000000000000", "1000000000000000000000000"); let test_err = |s, rug_err| { assert!(Natural::from_str(s).is_err()); assert!(BigUint::from_str(s).is_err()); let rn = rug::Integer::from_str(s); assert_eq!(rn.is_err() || rn.unwrap() < 0, rug_err); }; test_err("12A", true); test_err(" 10", false); test_err("1.0", true); test_err("-5", true); test_err("$%^", true); test_err("", true); test_err("-", true); test_err("-0", false); test_err("--0", true); test_err("-+0", true); test_err("+-0", true); test_err("++0", true); test_err("--1", true); test_err("-+1", true); test_err("+-1", true); test_err("++1", true); } #[test] fn from_str_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); string_gen().test_properties_with_config(&config, |s| { assert_eq!( Natural::from_str(&s).is_ok(), !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()), ); }); string_gen_var_3().test_properties(|s| { let n = Natural::from_str(&s).unwrap(); let mut trimmed = s.trim_start_matches('0'); if trimmed.is_empty() { trimmed = "0"; } assert_eq!(n.to_string(), trimmed); assert_eq!(n, Natural::from_string_base(10, &s).unwrap()); let with_zero = "0".to_string() + &s; assert_eq!(Natural::from_str(&with_zero).unwrap(), n); assert_eq!(BigUint::from_str(&s).unwrap(), BigUint::from(&n)); assert_eq!(rug::Integer::from_str(&s).unwrap(), rug::Integer::from(&n)); }); unsigned_gen_var_11().test_properties(|u| { assert_eq!( Natural::from_str(std::str::from_utf8(&vec![b'0'; u]).unwrap()).unwrap(), 0 ); }); unsigned_gen::().test_properties(|u| { let s = u.to_string(); assert_eq!( Natural::from_str(&s).unwrap(), Natural::from(Limb::from_str(&s).unwrap()) ); }); } #[test] fn test_from_string_base() { let test_ok = |base, s, n| { assert_eq!(Natural::from_string_base(base, s).unwrap().to_string(), n); assert_eq!( BigUint::from_str_radix(s, u32::exact_from(base)) .unwrap() .to_string(), n ); assert_eq!( rug::Integer::from_str_radix(s, i32::exact_from(base)) .unwrap() .to_string(), n ); }; test_ok(2, "0", "0"); test_ok(10, "0", "0"); test_ok(2, "101", "5"); test_ok(10, "123456", "123456"); test_ok(16, "deadbeef", "3735928559"); test_ok(16, "DEADBEEF", "3735928559"); test_ok(16, "deAdBeEf", "3735928559"); test_ok(10, "1000000000000000000000000", "1000000000000000000000000"); test_ok(2, "1000000000000000000000000", "16777216"); test_ok( 36, "1000000000000000000000000", "22452257707354557240087211123792674816", ); test_ok(36, "helloworld", "1767707668033969"); let test_err = |base, s, rug_err| { assert!(Natural::from_string_base(base, s).is_none()); assert!(BigUint::from_str_radix(s, u32::exact_from(base)).is_err()); let rn = rug::Integer::from_str_radix(s, i32::exact_from(base)); assert_eq!(rn.is_err() || rn.unwrap() < 0, rug_err); }; test_err(2, "123", true); test_err(10, "12A", true); test_err(35, " 10", false); test_err(35, "1.0", true); test_err(35, "-5", true); test_err(35, "$%^", true); test_err(35, "", true); test_err(35, "-", true); test_err(16, "10000000z", true); test_err(16, "1000000000000000z", true); } #[test] #[should_panic] fn from_string_base_fail_1() { Natural::from_string_base(1, "0"); } #[test] #[should_panic] fn from_string_base_fail_2() { Natural::from_string_base(0, "0"); } fn from_string_base_helper(base: u8, s: &str) { let n = Natural::from_string_base(base, s).unwrap(); let s_lo = s.to_lowercase(); let mut trimmed = s_lo.trim_start_matches('0'); if trimmed.is_empty() { trimmed = "0"; } assert_eq!(n.to_string_base(base), trimmed); let with_zero = "0".to_string() + s; assert_eq!(Natural::from_string_base(base, &with_zero).unwrap(), n); assert_eq!( BigUint::from_str_radix(s, u32::from(base)).unwrap(), BigUint::from(&n) ); assert_eq!( rug::Integer::from_str_radix(s, i32::from(base)).unwrap(), rug::Integer::from(&n) ); } #[test] fn from_string_base_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); let mut digit_map = HashMap::new(); unsigned_string_pair_gen_var_2().test_properties_with_config(&config, |(base, s)| { let digits = digit_map .entry(base) .or_insert_with(|| valid_digit_chars(u8::wrapping_from(base))); assert_eq!( Natural::from_string_base(base, &s).is_some(), !s.is_empty() && s.chars().all(|c| digits.contains(&c)), ); }); unsigned_string_pair_gen_var_1().test_properties(|(base, s)| { from_string_base_helper(base, &s); }); string_gen_var_5().test_properties(|s| { from_string_base_helper(2, &s); }); string_gen_var_6().test_properties(|s| { from_string_base_helper(8, &s); }); string_gen_var_7().test_properties(|s| { from_string_base_helper(16, &s); }); unsigned_pair_gen_var_19().test_properties(|(u, base)| { assert_eq!( Natural::from_string_base(base, std::str::from_utf8(&vec![b'0'; u]).unwrap()).unwrap(), 0 ); }); unsigned_pair_gen_var_8::().test_properties(|(u, base)| { let s = u.to_string_base(base); assert_eq!( Natural::from_string_base(base, &s).unwrap(), Natural::from(Limb::from_string_base(base, &s).unwrap()) ); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{FloorLogBase, Pow, PowerOf2, RoundToMultiple}; use malachite_base::num::conversion::string::options::{ FromSciStringOptions, SciSizeOptions, ToSciOptions, }; use malachite_base::num::conversion::traits::{FromSciString, ToSci}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::{unsigned_gen, unsigned_to_sci_options_pair_gen_var_1}; use malachite_base::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_to_sci_options_pair_gen_var_1}; use std::collections::HashMap; use std::str::FromStr; #[test] pub fn test_to_sci() { assert_eq!( Natural::power_of_2(1000000).to_sci().to_string(), "9.900656229295898e301029" ); assert_eq!( (-Natural::power_of_2(1000000)).to_sci().to_string(), "-9.900656229295898e301029" ); fn test_i(x: &Natural, out: &str) { assert_eq!(x.to_sci().to_string(), out); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), out ); } fn test(s: &str, out: &str) { test_i(&Natural::from_str(s).unwrap(), out); } test("0", "0"); test("1", "1"); test("10", "10"); test("100", "100"); test("1000", "1000"); test("10000", "10000"); test("100000", "100000"); test("1000000", "1000000"); test("10000000", "10000000"); test("100000000", "100000000"); test("1000000000", "1000000000"); test("10000000000", "10000000000"); test("100000000000", "100000000000"); test("1000000000000", "1000000000000"); test("10000000000000", "10000000000000"); test("100000000000000", "100000000000000"); test("1000000000000000", "1000000000000000"); test("10000000000000000", "1e16"); test("100000000000000000", "1e17"); test_i(&Natural::from(u64::MAX), "1.844674407370955e19"); test_i(&Natural::from(u128::MAX), "3.402823669209385e38"); test("999999999999999", "999999999999999"); test("9999999999999999", "9999999999999999"); test("99999999999999999", "1e17"); test("999999999999999999", "1e18"); } #[test] pub fn test_to_sci_with_options() { fn test_i(x: &Natural, options: ToSciOptions, out: &str) { assert_eq!(x.to_sci_with_options(options).to_string(), out); } fn test(s: &str, options: ToSciOptions, out: &str) { test_i(&Natural::from_str(s).unwrap(), options, out); } // For tests with the default options, see `test_to_sci` let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test("0", options, "0.000000000000000"); test("1", options, "1.000000000000000"); test("10", options, "10.00000000000000"); test("100", options, "100.0000000000000"); test("1000", options, "1000.000000000000"); test("10000", options, "10000.00000000000"); test("100000", options, "100000.0000000000"); test("1000000", options, "1000000.000000000"); test("10000000", options, "10000000.00000000"); test("100000000", options, "100000000.0000000"); test("1000000000", options, "1000000000.000000"); test("10000000000", options, "10000000000.00000"); test("100000000000", options, "100000000000.0000"); test("1000000000000", options, "1000000000000.000"); test("10000000000000", options, "10000000000000.00"); test("100000000000000", options, "100000000000000.0"); test("1000000000000000", options, "1000000000000000"); test("10000000000000000", options, "1.000000000000000e16"); test("100000000000000000", options, "1.000000000000000e17"); test_i(&Natural::from(u64::MAX), options, "1.844674407370955e19"); test_i(&Natural::from(u128::MAX), options, "3.402823669209385e38"); test("999999999999999", options, "999999999999999.0"); test("9999999999999999", options, "9999999999999999"); test("99999999999999999", options, "1.000000000000000e17"); test("999999999999999999", options, "1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test_i(&Natural::from(u128::MAX), options, "1e128"); options.set_base(3); test_i(&Natural::from(u128::MAX), options, "2.022011021210021e80"); options.set_base(4); test_i(&Natural::from(u128::MAX), options, "1e64"); options.set_base(5); test_i(&Natural::from(u128::MAX), options, "1.103111044120131e55"); options.set_base(8); test_i(&Natural::from(u128::MAX), options, "4e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test_i(&Natural::from(u128::MAX), options, "1e+32"); options.set_base(32); test_i(&Natural::from(u128::MAX), options, "8e+25"); options.set_base(36); test_i(&Natural::from(u128::MAX), options, "f.5lxx1zz5pnorynqe+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test_i(&Natural::from(u128::MAX), options, "2.022011021210021e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test_i(&Natural::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQe+24"); options.set_lowercase(); options.set_e_uppercase(); test_i(&Natural::from(u128::MAX), options, "f.5lxx1zz5pnorynqE+24"); options.set_uppercase(); test_i(&Natural::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test_i( &Natural::from(u128::MAX), options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", ); options.set_base(3); test_i( &Natural::from(u128::MAX), options, "202201102121002021012000211012011021221022212021111001022110211020010021100121010", ); options.set_base(4); test_i( &Natural::from(u128::MAX), options, "3333333333333333333333333333333333333333333333333333333333333333", ); options.set_base(5); test_i( &Natural::from(u128::MAX), options, "11031110441201303134210404233413032443021130230130231310", ); options.set_base(8); test_i( &Natural::from(u128::MAX), options, "3777777777777777777777777777777777777777777", ); options.set_base(16); test_i( &Natural::from(u128::MAX), options, "ffffffffffffffffffffffffffffffff", ); options.set_base(32); test_i( &Natural::from(u128::MAX), options, "7vvvvvvvvvvvvvvvvvvvvvvvvv", ); options.set_base(36); test_i( &Natural::from(u128::MAX), options, "f5lxx1zz5pnorynqglhzmsp33", ); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test("0", options, "0.000"); test("1", options, "1.000"); test("10", options, "10.00"); test("100", options, "100.0"); test("1000", options, "1000"); test("10000", options, "1.000e4"); test("9", options, "9.000"); test("99", options, "99.00"); test("999", options, "999.0"); test("9999", options, "9999"); test("99999", options, "1.000e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test("0", options, "0.00"); test("1", options, "1.00"); test("10", options, "10.00"); test("100", options, "100.00"); test("1000", options, "1000.00"); test("10000", options, "10000.00"); test("9", options, "9.00"); test("99", options, "99.00"); test("999", options, "999.00"); test("9999", options, "9999.00"); test("99999", options, "99999.00"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test("123", options, "1.2e2"); options.set_rounding_mode(Down); test("123", options, "1.2e2"); options.set_rounding_mode(Floor); test("123", options, "1.2e2"); options.set_rounding_mode(Up); test("123", options, "1.3e2"); options.set_rounding_mode(Ceiling); test("123", options, "1.3e2"); options.set_rounding_mode(Nearest); test("135", options, "1.4e2"); options.set_rounding_mode(Down); test("135", options, "1.3e2"); options.set_rounding_mode(Floor); test("135", options, "1.3e2"); options.set_rounding_mode(Up); test("135", options, "1.4e2"); options.set_rounding_mode(Ceiling); test("135", options, "1.4e2"); options.set_rounding_mode(Exact); test("140", options, "1.4e2"); options.set_rounding_mode(Nearest); test("999", options, "1e3"); options.set_rounding_mode(Down); test("999", options, "9.9e2"); options.set_rounding_mode(Floor); test("999", options, "9.9e2"); options.set_rounding_mode(Up); test("999", options, "1e3"); options.set_rounding_mode(Ceiling); test("999", options, "1e3"); } #[test] fn to_sci_properties() { let mut powers_of_10 = HashMap::new(); const TEN: Natural = Natural::const_from(10); let default_p = 16; natural_gen().test_properties(|x| { assert!(x.fmt_sci_valid(ToSciOptions::default())); let s = x.to_sci().to_string(); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), s ); assert!(string_is_subset(&s, DECIMAL_SCI_STRING_CHARS)); assert!(!s.starts_with('.')); assert!(!s.ends_with('.')); assert!(!s.contains('-')); assert!(!s.contains('+')); assert!(!s.contains('E')); let x_from = Natural::from_sci_string(&s).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let log = x.floor_log_base(&TEN); if log < default_p { assert_eq!(x_from, x); } else { let pow = powers_of_10 .entry(log - default_p + 1) .or_insert_with_key(|&p| (&TEN).pow(p)); assert_eq!(x.round_to_multiple(&*pow, Nearest).0, x_from); } } }); unsigned_gen::().test_properties(|x| { assert_eq!( x.to_sci().to_string(), Natural::from(x).to_sci().to_string() ); }); } #[test] fn to_sci_with_options_properties() { let mut powers = HashMap::new(); let mut chars = HashMap::new(); natural_to_sci_options_pair_gen_var_1().test_properties(|(x, options)| { assert!(x.fmt_sci_valid(options)); let s = x.to_sci_with_options(options).to_string(); let cs: &mut String = chars.entry(options.get_base()).or_insert_with_key(|&base| { let mut cs = "+-.0123456789".to_string(); if base > 10 { let limit = usize::from(base - 10); for c in ('a'..='z').take(limit) { cs.push(c); } for c in ('A'..='Z').take(limit) { cs.push(c); } } if base < 15 { cs.push('e'); cs.push('E'); } cs }); assert!(string_is_subset(&s, cs)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('.')); assert!(!s.contains('-')); assert!(!s.contains("++")); assert!(!s.contains("+.")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '+').count() <= 1); let mut from_options = FromSciStringOptions::default(); from_options.set_base(options.get_base()); let x_from = Natural::from_sci_string_with_options(&s, from_options).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let base = Natural::from(options.get_base()); let neg_scale = match options.get_size_options() { SciSizeOptions::Complete | SciSizeOptions::Scale(_) => None, SciSizeOptions::Precision(p) => { let log = x.floor_log_base(&base); if log >= p { Some(log - p + 1) } else { None } } }; if let Some(neg_scale) = neg_scale { let pow = powers .entry((base.clone(), neg_scale)) .or_insert_with(|| (&base).pow(neg_scale)); assert_eq!( x.round_to_multiple(&*pow, options.get_rounding_mode()).0, x_from ); } else { assert_eq!(x_from, x); } } }); unsigned_to_sci_options_pair_gen_var_1::().test_properties(|(x, options)| { assert_eq!( x.to_sci_with_options(options).to_string(), Natural::from(x).to_sci_with_options(options).to_string() ); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/string/to_string.rs ================================================ // Copyright © 2026 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::repeat_n; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::string::to_string::BaseFmtWrapper as BaseBaseFmtWrapper; use malachite_base::num::conversion::traits::{FromStringBase, ToStringBase}; use malachite_base::strings::{ ToBinaryString, ToDebugString, ToLowerHexString, ToOctalString, ToUpperHexString, string_is_subset, }; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_gen_var_8, unsigned_pair_gen_var_2, unsigned_pair_gen_var_9, unsigned_triple_gen_var_6, }; use malachite_nz::natural::Natural; use malachite_nz::natural::conversion::string::to_string::{ BaseFmtWrapper, NaturalAlt, NaturalAlt2, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_unsigned_pair_gen_var_3, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_triple_gen_var_1, }; use malachite_nz::test_util::natural::conversion::string::to_string::to_string_base_naive; use num::BigUint; use std::cmp::max; use std::panic::catch_unwind; use std::str::FromStr; fn test_padding(s: &str, s_padded: &str, width: usize) { assert!(s_padded.len() >= width); assert_eq!(s.len() >= width, s == s_padded); if s.len() < width { let diff = s_padded.len() - s.len(); assert!(s_padded[..diff].chars().all(|c| c == '0')); assert_eq!(&s_padded[diff..], s); } } #[test] pub fn test_to_string() { fn test(u: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_string(), u); assert_eq!(x.to_debug_string(), u); assert_eq!(to_string_base_naive(&x, 10), u); assert_eq!(format!("{x:00}"), u); assert_eq!(format!("{x:00?}"), u); } test("0"); test("2"); test("123"); test("1000"); test("1000000"); test("1000000000000000"); fn test_width(u: &str, width: usize, out: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_string(); assert_eq!(format!("{x:0width$}"), out); assert_eq!(format!("{x:0width$?}"), out); test_padding(&s, out, width); } test_width("0", 0, "0"); test_width("0", 1, "0"); test_width("0", 2, "00"); test_width("0", 5, "00000"); test_width("1000000", 0, "1000000"); test_width("1000000", 1, "1000000"); test_width("1000000", 2, "1000000"); test_width("1000000", 3, "1000000"); test_width("1000000", 4, "1000000"); test_width("1000000", 5, "1000000"); test_width("1000000", 6, "1000000"); test_width("1000000", 7, "1000000"); test_width("1000000", 8, "01000000"); test_width("1000000", 10, "0001000000"); test_width("1000000000000000", 0, "1000000000000000"); test_width("1000000000000000", 1, "1000000000000000"); test_width("1000000000000000", 16, "1000000000000000"); test_width("1000000000000000", 20, "00001000000000000000"); } #[test] fn to_string_properties() { natural_gen().test_properties(|x| { let s = x.to_string(); assert_eq!(x.to_debug_string(), s); assert_eq!(x.to_string_base(10), s); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, 10)), s); assert_eq!(to_string_base_naive(&x, 10), s); assert_eq!(BigUint::from(&x).to_string(), s); assert_eq!(rug::Integer::from(&x).to_string(), s); assert!(string_is_subset(&s, "0123456789")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { let s = x.to_string(); let s_padded = format!("{x:0width$}"); test_padding(&s, &s_padded, width); assert_eq!(format!("{x:0width$?}"), s_padded); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 10), width = width), s_padded ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(&x, 10), width = width), s_padded ); assert_eq!( format!("{:0width$}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$}", rug::Integer::from(&x), width = width), s_padded ); }); unsigned_gen::().test_properties(|x| { assert_eq!(Natural::from(x).to_string(), x.to_string()); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", Natural::from(x), width = width), format!("{x:0width$}") ); }); } #[test] pub fn test_to_binary_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_binary_string(), out); assert_eq!(to_string_base_naive(&x, 2), out); assert_eq!(format!("{x:00b}"), out); assert_eq!(format!("{x:#b}"), out_prefixed); } test("0", "0", "0b0"); test("2", "10", "0b10"); test("123", "1111011", "0b1111011"); test("1000", "1111101000", "0b1111101000"); test("1000000", "11110100001001000000", "0b11110100001001000000"); test( "1000000000000000", "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_binary_string(); assert_eq!(format!("{x:0width$b}"), out); assert_eq!(format!("{x:#0width$b}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0b0"); test_width("0", 1, "0", "0b0"); test_width("0", 2, "00", "0b0"); test_width("0", 5, "00000", "0b000"); test_width("1000", 0, "1111101000", "0b1111101000"); test_width("1000", 1, "1111101000", "0b1111101000"); test_width("1000", 10, "1111101000", "0b1111101000"); test_width("1000", 12, "001111101000", "0b1111101000"); test_width("1000", 14, "00001111101000", "0b001111101000"); test_width( "1000000000000000", 0, "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 1, "11100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 52, "0011100011010111111010100100110001101000000000000000", "0b11100011010111111010100100110001101000000000000000", ); test_width( "1000000000000000", 54, "000011100011010111111010100100110001101000000000000000", "0b0011100011010111111010100100110001101000000000000000", ); } #[test] fn to_binary_string_properties() { natural_gen().test_properties(|x| { let s = x.to_binary_string(); let prefixed_s = "0b".to_owned() + &s; assert_eq!(format!("{x:#b}"), prefixed_s); assert_eq!(format!("{x:00b}"), s); assert_eq!(format!("{x:#00b}"), prefixed_s); assert_eq!(x.to_string_base(2), s); assert_eq!(to_string_base_naive(&x, 2), s); assert_eq!(NaturalAlt(x.clone()).to_binary_string(), s); assert_eq!(format!("{:#b}", NaturalAlt(x.clone())), prefixed_s); assert_eq!(NaturalAlt2(x.clone()).to_binary_string(), s); assert_eq!(format!("{:#b}", NaturalAlt2(x.clone())), prefixed_s); let num_x = BigUint::from(&x); assert_eq!(num_x.to_binary_string(), s); assert_eq!(format!("{num_x:#b}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_binary_string(), s); assert_eq!(format!("{rug_x:#b}"), prefixed_s); assert!(string_is_subset(&s, "01")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { let s = x.to_binary_string(); let s_padded = format!("{x:0width$b}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$b}", NaturalAlt(x.clone()), width = width), s_padded ); assert_eq!( format!("{:0width$b}", NaturalAlt2(x.clone()), width = width), s_padded, ); assert_eq!( format!("{:0width$b}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$b}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$b}"); assert_eq!( format!("{:#0width$b}", NaturalAlt(x.clone()), width = width), s_padded, ); assert_eq!( format!("{:#0width$b}", NaturalAlt2(x.clone()), width = width), s_padded ); assert_eq!( format!("{:#0width$b}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$b}", rug::Integer::from(&x), width = width), s_padded ); }); unsigned_gen::().test_properties(|x| { assert_eq!(Natural::from(x).to_binary_string(), x.to_binary_string()); assert_eq!(format!("{:#b}", Natural::from(x)), format!("{x:#b}")); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$b}", Natural::from(x), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$b}", Natural::from(x), width = width), format!("{x:#0width$b}") ); }); } #[test] pub fn test_to_octal_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_octal_string(), out); assert_eq!(to_string_base_naive(&x, 8), out); assert_eq!(format!("{x:00o}"), out); assert_eq!(format!("{x:#o}"), out_prefixed); } test("0", "0", "0o0"); test("2", "2", "0o2"); test("123", "173", "0o173"); test("1000", "1750", "0o1750"); test("1000000", "3641100", "0o3641100"); test( "1000000000000000", "34327724461500000", "0o34327724461500000", ); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_octal_string(); assert_eq!(format!("{x:0width$o}"), out); assert_eq!(format!("{x:#0width$o}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0o0"); test_width("0", 1, "0", "0o0"); test_width("0", 2, "00", "0o0"); test_width("0", 3, "000", "0o0"); test_width("0", 4, "0000", "0o00"); test_width("0", 5, "00000", "0o000"); test_width("1000", 0, "1750", "0o1750"); test_width("1000", 1, "1750", "0o1750"); test_width("1000", 4, "1750", "0o1750"); test_width("1000", 6, "001750", "0o1750"); test_width("1000", 8, "00001750", "0o001750"); test_width( "1000000000000000", 0, "34327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 1, "34327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 19, "0034327724461500000", "0o34327724461500000", ); test_width( "1000000000000000", 21, "000034327724461500000", "0o0034327724461500000", ); } #[test] fn to_octal_string_properties() { natural_gen().test_properties(|x| { let s = x.to_octal_string(); let prefixed_s = "0o".to_owned() + &s; assert_eq!(format!("{x:#o}"), prefixed_s); assert_eq!(format!("{x:00o}"), s); assert_eq!(format!("{x:#00o}"), prefixed_s); assert_eq!(x.to_string_base(8), s); assert_eq!(to_string_base_naive(&x, 8), s); assert_eq!(NaturalAlt(x.clone()).to_octal_string(), s); assert_eq!(format!("{:#o}", NaturalAlt(x.clone())), prefixed_s); assert_eq!(NaturalAlt2(x.clone()).to_octal_string(), s); assert_eq!(format!("{:#o}", NaturalAlt2(x.clone())), prefixed_s); let num_x = BigUint::from(&x); assert_eq!(num_x.to_octal_string(), s); assert_eq!(format!("{num_x:#o}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_octal_string(), s); assert_eq!(format!("{rug_x:#o}"), prefixed_s); assert!(string_is_subset(&s, "01234567")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { let s = x.to_octal_string(); let s_padded = format!("{x:0width$o}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$o}", NaturalAlt(x.clone()), width = width), s_padded ); assert_eq!( format!("{:0width$o}", NaturalAlt2(x.clone()), width = width), s_padded ); assert_eq!( format!("{:0width$o}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$o}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$o}"); assert_eq!( format!("{:#0width$o}", NaturalAlt(x.clone()), width = width), s_padded ); assert_eq!( format!("{:#0width$o}", NaturalAlt2(x.clone()), width = width), s_padded ); assert_eq!( format!("{:#0width$o}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$o}", rug::Integer::from(&x), width = width), s_padded ); }); unsigned_gen::().test_properties(|x| { assert_eq!(Natural::from(x).to_octal_string(), x.to_octal_string()); assert_eq!(format!("{:#o}", Natural::from(x)), format!("{x:#o}")); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$o}", Natural::from(x), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$o}", Natural::from(x), width = width), format!("{x:#0width$o}") ); }); } #[test] pub fn test_to_lower_hex_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_lower_hex_string(), out); assert_eq!(to_string_base_naive(&x, 16), out); assert_eq!(format!("{x:00x}"), out); assert_eq!(format!("{x:#x}"), out_prefixed); } test("0", "0", "0x0"); test("2", "2", "0x2"); test("123", "7b", "0x7b"); test("1000", "3e8", "0x3e8"); test("1000000", "f4240", "0xf4240"); test("1000000000000000", "38d7ea4c68000", "0x38d7ea4c68000"); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_lower_hex_string(); assert_eq!(format!("{x:0width$x}"), out); assert_eq!(format!("{x:#0width$x}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0x0"); test_width("0", 1, "0", "0x0"); test_width("0", 2, "00", "0x0"); test_width("0", 3, "000", "0x0"); test_width("0", 4, "0000", "0x00"); test_width("0", 5, "00000", "0x000"); test_width("1000", 0, "3e8", "0x3e8"); test_width("1000", 1, "3e8", "0x3e8"); test_width("1000", 3, "3e8", "0x3e8"); test_width("1000", 5, "003e8", "0x3e8"); test_width("1000", 7, "00003e8", "0x003e8"); test_width("1000000000000000", 0, "38d7ea4c68000", "0x38d7ea4c68000"); test_width("1000000000000000", 1, "38d7ea4c68000", "0x38d7ea4c68000"); test_width("1000000000000000", 15, "0038d7ea4c68000", "0x38d7ea4c68000"); test_width( "1000000000000000", 17, "000038d7ea4c68000", "0x0038d7ea4c68000", ); } #[test] pub fn test_to_upper_hex_string() { fn test(u: &str, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_upper_hex_string(), out); assert_eq!(to_string_base_naive(&x, 16).to_uppercase(), out); assert_eq!(format!("{x:00X}"), out); assert_eq!(format!("{x:#X}"), out_prefixed); } test("0", "0", "0x0"); test("2", "2", "0x2"); test("123", "7B", "0x7B"); test("1000", "3E8", "0x3E8"); test("1000000", "F4240", "0xF4240"); test("1000000000000000", "38D7EA4C68000", "0x38D7EA4C68000"); fn test_width(u: &str, width: usize, out: &str, out_prefixed: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_upper_hex_string(); assert_eq!(format!("{x:0width$X}"), out); assert_eq!(format!("{x:#0width$X}"), out_prefixed); test_padding(&s, out, width); } test_width("0", 0, "0", "0x0"); test_width("0", 1, "0", "0x0"); test_width("0", 2, "00", "0x0"); test_width("0", 3, "000", "0x0"); test_width("0", 4, "0000", "0x00"); test_width("0", 5, "00000", "0x000"); test_width("1000", 0, "3E8", "0x3E8"); test_width("1000", 1, "3E8", "0x3E8"); test_width("1000", 3, "3E8", "0x3E8"); test_width("1000", 5, "003E8", "0x3E8"); test_width("1000", 7, "00003E8", "0x003E8"); test_width("1000000000000000", 0, "38D7EA4C68000", "0x38D7EA4C68000"); test_width("1000000000000000", 1, "38D7EA4C68000", "0x38D7EA4C68000"); test_width("1000000000000000", 15, "0038D7EA4C68000", "0x38D7EA4C68000"); test_width( "1000000000000000", 17, "000038D7EA4C68000", "0x0038D7EA4C68000", ); } #[test] fn to_hex_string_properties() { natural_gen().test_properties(|x| { let s = x.to_lower_hex_string(); let prefixed_s = "0x".to_owned() + &s; assert_eq!(format!("{x:#x}"), prefixed_s); assert_eq!(x.to_upper_hex_string(), s.to_ascii_uppercase()); assert_eq!(format!("{x:#X}"), "0x".to_owned() + &s.to_ascii_uppercase()); assert_eq!(format!("{x:00x}"), s); assert_eq!(format!("{x:#00x}"), prefixed_s); assert_eq!(format!("{x:00X}"), s.to_ascii_uppercase()); assert_eq!( format!("{x:#00X}"), "0x".to_owned() + &s.to_ascii_uppercase() ); assert_eq!(x.to_string_base(16), s); assert_eq!(to_string_base_naive(&x, 16), s); assert_eq!(NaturalAlt(x.clone()).to_lower_hex_string(), s); assert_eq!(format!("{:#x}", NaturalAlt(x.clone())), prefixed_s); assert_eq!(NaturalAlt2(x.clone()).to_lower_hex_string(), s); assert_eq!(format!("{:#x}", NaturalAlt2(x.clone())), prefixed_s); let num_x = BigUint::from(&x); assert_eq!(num_x.to_lower_hex_string(), s); assert_eq!(format!("{num_x:#x}"), prefixed_s); let rug_x = rug::Integer::from(&x); assert_eq!(rug_x.to_lower_hex_string(), s); assert_eq!(format!("{rug_x:#x}"), prefixed_s); assert!(string_is_subset(&s, "0123456789abcdef")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { let s = x.to_lower_hex_string(); let s_padded = format!("{x:0width$x}"); test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$x}", NaturalAlt(x.clone()), width = width), s_padded ); assert_eq!( format!("{:0width$x}", NaturalAlt2(x.clone()), width = width), s_padded ); assert_eq!( format!("{:0width$x}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$x}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$x}"); assert_eq!( format!("{:#0width$x}", NaturalAlt(x.clone()), width = width), s_padded ); assert_eq!( format!("{:#0width$x}", NaturalAlt2(x.clone()), width = width), s_padded ); assert_eq!( format!("{:#0width$x}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$x}", rug::Integer::from(&x), width = width), s_padded ); let s = x.to_upper_hex_string(); let s_padded_upper = format!("{x:0width$X}"); assert_eq!(s_padded_upper, format!("{x:0width$x}").to_ascii_uppercase()); let s_padded = s_padded_upper; test_padding(&s, &s_padded, width); assert_eq!( format!("{:0width$X}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:0width$X}", rug::Integer::from(&x), width = width), s_padded ); let s_padded = format!("{x:#0width$X}"); assert_eq!( format!("{:#0width$X}", BigUint::from(&x), width = width), s_padded ); assert_eq!( format!("{:#0width$X}", rug::Integer::from(&x), width = width), s_padded ); }); unsigned_gen::().test_properties(|x| { assert_eq!( Natural::from(x).to_lower_hex_string(), x.to_lower_hex_string() ); assert_eq!( Natural::from(x).to_upper_hex_string(), x.to_upper_hex_string() ); assert_eq!(format!("{:#x}", Natural::from(x)), format!("{x:#x}")); assert_eq!(format!("{:#X}", Natural::from(x)), format!("{x:#X}")); }); unsigned_pair_gen_var_2::().test_properties(|(x, width)| { assert_eq!( format!("{:0width$x}", Natural::from(x), width = width), format!("{x:0width$x}") ); assert_eq!( format!("{:0width$X}", Natural::from(x), width = width), format!("{x:0width$X}") ); assert_eq!( format!("{:#0width$x}", Natural::from(x), width = width), format!("{x:#0width$x}") ); assert_eq!( format!("{:#0width$X}", Natural::from(x), width = width), format!("{x:#0width$X}") ); }); } #[test] pub fn test_to_string_base() { fn test(u: &str, base: u8, out: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_string_base(base), out); assert_eq!(to_string_base_naive(&x, base), out); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, base)), out); } test("0", 2, "0"); test("0", 3, "0"); test("0", 10, "0"); test("0", 16, "0"); test("0", 17, "0"); test("2", 3, "2"); test("2", 10, "2"); test("2", 16, "2"); test("2", 17, "2"); test("123", 8, "173"); test("1000000", 10, "1000000"); test("1000000", 20, "65000"); test("1000000", 36, "lfls"); test("1000", 2, "1111101000"); test("1000", 3, "1101001"); test("1000", 4, "33220"); test("1000", 10, "1000"); test("1000", 20, "2a0"); test("1000", 36, "rs"); test( "1000000000000000", 2, "11100011010111111010100100110001101000000000000000", ); test("1000000000000000", 3, "11212010201001210101011021212001"); test("1000000000000000", 4, "3203113322210301220000000"); test("1000000000000000", 10, "1000000000000000"); test("1000000000000000", 20, "4hd2a0000000"); test("1000000000000000", 36, "9ugxnorjls"); fn test_width(u: &str, base: u8, width: usize, out: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_string_base(base); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, base), width = width), out ); assert_eq!( format!("{:0width$?}", BaseFmtWrapper::new(&x, base), width = width), out ); test_padding(&s, out, width); } test_width("0", 2, 0, "0"); test_width("0", 2, 1, "0"); test_width("0", 2, 2, "00"); test_width("0", 2, 5, "00000"); test_width("1000000", 36, 0, "lfls"); test_width("1000000", 36, 1, "lfls"); test_width("1000000", 36, 2, "lfls"); test_width("1000000", 36, 3, "lfls"); test_width("1000000", 36, 4, "lfls"); test_width("1000000", 36, 5, "0lfls"); test_width("1000000", 36, 6, "00lfls"); test_width("1000000000000000", 36, 0, "9ugxnorjls"); test_width("1000000000000000", 36, 1, "9ugxnorjls"); test_width("1000000000000000", 36, 10, "9ugxnorjls"); test_width("1000000000000000", 36, 11, "09ugxnorjls"); test_width("1000000000000000", 36, 20, "00000000009ugxnorjls"); } #[test] fn to_string_base_fail() { assert_panic!(Natural::from(10u32).to_string_base(0)); assert_panic!(Natural::from(10u32).to_string_base(1)); assert_panic!(Natural::from(10u32).to_string_base(37)); assert_panic!(Natural::from(10u32).to_string_base(100)); assert_panic!(format!("{}", BaseFmtWrapper::new(&Natural::from(10u32), 0))); assert_panic!(format!("{}", BaseFmtWrapper::new(&Natural::from(10u32), 1))); assert_panic!(format!( "{}", BaseFmtWrapper::new(&Natural::from(10u32), 37) )); assert_panic!(format!( "{}", BaseFmtWrapper::new(&Natural::from(10u32), 100) )); } #[test] fn to_string_base_properties() { natural_unsigned_pair_gen_var_3().test_properties(|(x, base)| { let s = x.to_string_base(base); assert_eq!(to_string_base_naive(&x, base), s); assert_eq!(format!("{}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:00}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:00?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(x.to_string_base_upper(base), s.to_uppercase()); assert_eq!(Natural::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset(&s, "0123456789abcdefghijklmnopqrstuvwxyz")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_gen().test_properties(|x| { assert_eq!(x.to_string_base(10), x.to_string()); assert_eq!(x.to_string_base(2), x.to_binary_string()); assert_eq!(x.to_string_base(8), x.to_octal_string()); assert_eq!(x.to_string_base(16), x.to_lower_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(Natural::ZERO.to_string_base(base), "0"); assert_eq!(Natural::ONE.to_string_base(base), "1"); assert_eq!(Natural::from(base).to_string_base(base), "10"); }); natural_unsigned_unsigned_triple_gen_var_1().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(&x, base); let s = x.to_string_base(base); let s_padded = format!("{fx:0width$}"); assert_eq!(format!("{fx:0width$?}"), s_padded); assert_eq!(Natural::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "0123456789abcdefghijklmnopqrstuvwxyz" )); test_padding(&s, &s_padded, width); }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:0width$}", BaseFmtWrapper::new(&x, 16), width = width), format!("{x:0width$x}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:0width$}", BaseFmtWrapper::new(&Natural::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); unsigned_triple_gen_var_6::().test_properties(|(x, base, width)| { assert_eq!( format!( "{:0width$}", BaseFmtWrapper::new(&Natural::from(x), base), width = width ), format!( "{:0width$}", BaseBaseFmtWrapper::new(x, base), width = width ), ); }); } #[test] pub fn test_to_string_base_upper() { fn test(u: &str, base: u8, out: &str) { let x = Natural::from_str(u).unwrap(); assert_eq!(x.to_string_base_upper(base), out); assert_eq!(format!("{:#}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#00}", BaseFmtWrapper::new(&x, base)), out); assert_eq!(format!("{:#00?}", BaseFmtWrapper::new(&x, base)), out); } test("0", 2, "0"); test("0", 3, "0"); test("0", 10, "0"); test("0", 16, "0"); test("0", 17, "0"); test("2", 3, "2"); test("2", 10, "2"); test("2", 16, "2"); test("2", 17, "2"); test("123", 8, "173"); test("1000000", 10, "1000000"); test("1000000", 20, "65000"); test("1000000", 36, "LFLS"); test("1000", 2, "1111101000"); test("1000", 3, "1101001"); test("1000", 4, "33220"); test("1000", 10, "1000"); test("1000", 20, "2A0"); test("1000", 36, "RS"); test( "1000000000000000", 2, "11100011010111111010100100110001101000000000000000", ); test("1000000000000000", 3, "11212010201001210101011021212001"); test("1000000000000000", 4, "3203113322210301220000000"); test("1000000000000000", 10, "1000000000000000"); test("1000000000000000", 20, "4HD2A0000000"); test("1000000000000000", 36, "9UGXNORJLS"); fn test_width(u: &str, base: u8, width: usize, out: &str) { let x = Natural::from_str(u).unwrap(); let s = x.to_string_base_upper(base); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, base), width = width), out ); assert_eq!( format!("{:#0width$?}", BaseFmtWrapper::new(&x, base), width = width), out ); test_padding(&s, out, width); } test_width("0", 2, 0, "0"); test_width("0", 2, 1, "0"); test_width("0", 2, 2, "00"); test_width("0", 2, 5, "00000"); test_width("1000000", 36, 0, "LFLS"); test_width("1000000", 36, 1, "LFLS"); test_width("1000000", 36, 2, "LFLS"); test_width("1000000", 36, 3, "LFLS"); test_width("1000000", 36, 4, "LFLS"); test_width("1000000", 36, 5, "0LFLS"); test_width("1000000", 36, 6, "00LFLS"); test_width("1000000000000000", 36, 0, "9UGXNORJLS"); test_width("1000000000000000", 36, 1, "9UGXNORJLS"); test_width("1000000000000000", 36, 10, "9UGXNORJLS"); test_width("1000000000000000", 36, 11, "09UGXNORJLS"); test_width("1000000000000000", 36, 20, "00000000009UGXNORJLS"); } #[test] fn to_string_base_upper_fail() { assert_panic!(Natural::from(10u32).to_string_base_upper(0)); assert_panic!(Natural::from(10u32).to_string_base_upper(1)); assert_panic!(Natural::from(10u32).to_string_base_upper(37)); assert_panic!(Natural::from(10u32).to_string_base_upper(100)); assert_panic!(format!( "{:#}", BaseFmtWrapper::new(&Natural::from(10u32), 0) )); assert_panic!(format!( "{:#}", BaseFmtWrapper::new(&Natural::from(10u32), 1) )); assert_panic!(format!( "{:#}", BaseFmtWrapper::new(&Natural::from(10u32), 37) )); assert_panic!(format!( "{:#}", BaseFmtWrapper::new(&Natural::from(10u32), 100) )); } #[test] fn to_string_base_upper_properties() { natural_unsigned_pair_gen_var_3().test_properties(|(x, base)| { let s = x.to_string_base_upper(base); assert_eq!(format!("{:#}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:#?}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(format!("{:#00}", BaseFmtWrapper::new(&x, base)), s); assert_eq!(x.to_string_base(base), s.to_lowercase()); assert_eq!(Natural::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset(&s, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")); if x != 0 { assert!(!s.starts_with('0')); } }); natural_gen().test_properties(|x| { assert_eq!(x.to_string_base_upper(10), x.to_string()); assert_eq!(x.to_string_base_upper(2), x.to_binary_string()); assert_eq!(x.to_string_base_upper(8), x.to_octal_string()); assert_eq!(x.to_string_base_upper(16), x.to_upper_hex_string()); }); unsigned_gen_var_8().test_properties(|base| { assert_eq!(Natural::ZERO.to_string_base_upper(base), "0"); assert_eq!(Natural::ONE.to_string_base_upper(base), "1"); assert_eq!(Natural::from(base).to_string_base_upper(base), "10"); }); natural_unsigned_unsigned_triple_gen_var_1().test_properties(|(x, base, width)| { let fx = BaseFmtWrapper::new(&x, base); let s = x.to_string_base_upper(base); let s_padded = format!("{fx:#0width$}"); assert_eq!(format!("{fx:#0width$?}"), s_padded); assert_eq!(Natural::from_string_base(base, &s).unwrap(), x); assert!(string_is_subset( &s_padded, "01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" )); test_padding(&s, &s_padded, width); }); natural_unsigned_pair_gen_var_4().test_properties(|(x, width)| { assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 10), width = width), format!("{x:0width$}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 2), width = width), format!("{x:0width$b}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 8), width = width), format!("{x:0width$o}") ); assert_eq!( format!("{:#0width$}", BaseFmtWrapper::new(&x, 16), width = width), format!("{x:0width$X}") ); }); unsigned_pair_gen_var_9::().test_properties(|(width, base)| { let s = format!( "{:#0width$}", BaseFmtWrapper::new(&Natural::ZERO, base), width = width ); assert_eq!(repeat_n('0', max(1, width)).collect::(), s); }); unsigned_triple_gen_var_6::().test_properties(|(x, base, width)| { assert_eq!( format!( "{:#0width$}", BaseFmtWrapper::new(&Natural::from(x), base), width = width ), format!( "{:#0width$}", BaseBaseFmtWrapper::new(x, base), width = width ), ); }); } ================================================ FILE: malachite-nz/tests/natural/conversion/to_limbs.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::common::test_double_ended_iterator_size_hint; use malachite_base::test_util::generators::unsigned_gen_var_5; use malachite_nz::natural::Natural; #[cfg(feature = "32_bit_limbs")] use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_bool_vec_pair_gen_var_1, natural_gen, natural_unsigned_pair_gen_var_4, }; #[cfg(feature = "32_bit_limbs")] use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_to_limbs_asc() { let test = |n, out: &[Limb]| { let n = Natural::from_str(n).unwrap(); assert_eq!(n.limbs().collect_vec(), out); assert_eq!(n.to_limbs_asc(), out); assert_eq!(n.as_limbs_asc(), out); assert_eq!(n.into_limbs_asc(), out); }; test("0", &[]); test("123", &[123]); test("1000000000000", &[3567587328, 232]); test("1701411834921604967429270619762735448065", &[1, 2, 3, 4, 5]); test("4294967295", &[u32::MAX]); test("4294967296", &[0, 1]); test("18446744073709551615", &[u32::MAX, u32::MAX]); test("18446744073709551616", &[0, 0, 1]); let n = Natural::from_str("1701411834921604967429270619762735448065").unwrap(); let mut limbs = n.limbs(); assert_eq!(Some(1), limbs.next()); assert_eq!(Some(5), limbs.next_back()); assert_eq!(Some(4), limbs.next_back()); assert_eq!(Some(2), limbs.next()); assert_eq!(Some(3), limbs.next()); assert_eq!(None, limbs.next()); assert_eq!(None, limbs.next_back()); assert_eq!(limbs[0], 1); assert_eq!(limbs[1], 2); assert_eq!(limbs[2], 3); assert_eq!(limbs[3], 4); assert_eq!(limbs[4], 5); assert_eq!(limbs[5], 0); let mut limbs = n.limbs(); assert_eq!(Some(1), limbs.next()); assert_eq!(Some(2), limbs.next()); assert_eq!(Some(3), limbs.next()); assert_eq!(Some(5), limbs.next_back()); assert_eq!(Some(4), limbs.next_back()); assert_eq!(None, limbs.next()); assert_eq!(None, limbs.next_back()); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_to_limbs_desc() { let test = |n, out: &[Limb]| { let n = Natural::from_str(n).unwrap(); assert_eq!(n.limbs().rev().collect_vec(), out); assert_eq!(n.to_limbs_desc(), out); assert_eq!(n.into_limbs_desc(), out); }; test("0", &[]); test("123", &[123]); test("1000000000000", &[232, 3567587328]); test("1701411834921604967429270619762735448065", &[5, 4, 3, 2, 1]); test("4294967295", &[u32::MAX]); test("4294967296", &[1, 0]); test("18446744073709551615", &[u32::MAX, u32::MAX]); test("18446744073709551616", &[1, 0, 0]); } #[test] fn to_limbs_asc_properties() { natural_gen().test_properties(|x| { let limbs = x.to_limbs_asc(); assert_eq!(x.clone().into_limbs_asc(), limbs); assert_eq!(x.as_limbs_asc(), limbs); assert_eq!(x.limbs().collect_vec(), limbs); assert_eq!(Natural::from_limbs_asc(&limbs), x); if x != 0 { assert_ne!(*limbs.last().unwrap(), 0); } }); } #[test] fn to_limbs_desc_properties() { natural_gen().test_properties(|x| { let limbs = x.to_limbs_desc(); assert_eq!(x.clone().into_limbs_desc(), limbs); assert_eq!(x.limbs().rev().collect_vec(), limbs); assert_eq!(Natural::from_limbs_desc(&limbs), x); if x != 0 { assert_ne!(limbs[0], 0); } }); } #[test] fn limbs_properties() { natural_gen().test_properties(|n| { test_double_ended_iterator_size_hint(n.limbs(), usize::exact_from(n.limb_count())); }); natural_bool_vec_pair_gen_var_1().test_properties(|(n, bs)| { let mut limbs = n.limbs(); let mut limb_vec = Vec::new(); let mut i = 0; for b in bs { if b { limb_vec.insert(i, limbs.next().unwrap()); i += 1; } else { limb_vec.insert(i, limbs.next_back().unwrap()); } } assert!(limbs.next().is_none()); assert!(limbs.next_back().is_none()); assert_eq!(n.to_limbs_asc(), limb_vec); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { if u < usize::exact_from(n.limb_count()) { assert_eq!(n.limbs()[u], n.to_limbs_asc()[u]); } else { assert_eq!(n.limbs()[u], 0); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(Natural::ZERO.limbs()[u], 0); }); } ================================================ FILE: malachite-nz/tests/natural/exhaustive/exhaustive_natural_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_natural_inclusive_range; fn expected_range_len(a: &Natural, b: &Natural) -> usize { usize::exact_from(b) - usize::exact_from(a) + 1 } fn exhaustive_natural_inclusive_range_helper(a: Natural, b: Natural, values: &str) { let xs = exhaustive_natural_inclusive_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); let len = expected_range_len(&a, &b); assert_eq!( exhaustive_natural_inclusive_range(a.clone(), b.clone()).count(), len ); let mut init = exhaustive_natural_inclusive_range(a, b) .rev() .skip(len.saturating_sub(20)) .collect_vec(); init.reverse(); assert_eq!(xs, init.to_debug_string()); } #[test] fn test_exhaustive_natural_inclusive_range() { exhaustive_natural_inclusive_range_helper(Natural::ZERO, Natural::ZERO, "[0]"); exhaustive_natural_inclusive_range_helper(Natural::ZERO, Natural::ONE, "[0, 1]"); exhaustive_natural_inclusive_range_helper( Natural::ZERO, Natural::exact_from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", ); exhaustive_natural_inclusive_range_helper( Natural::exact_from(10), Natural::exact_from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]", ); exhaustive_natural_inclusive_range_helper( Natural::exact_from(10), Natural::exact_from(100), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]", ); } #[test] #[should_panic] fn exhaustive_natural_inclusive_range_fail() { exhaustive_natural_inclusive_range(Natural::ONE, Natural::ZERO); } ================================================ FILE: malachite-nz/tests/natural/exhaustive/exhaustive_natural_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_natural_range; fn expected_range_len(a: &Natural, b: &Natural) -> usize { usize::exact_from(b) - usize::exact_from(a) } fn exhaustive_natural_range_helper(a: Natural, b: Natural, values: &str) { let xs = exhaustive_natural_range(a.clone(), b.clone()) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); let len = expected_range_len(&a, &b); assert_eq!(exhaustive_natural_range(a.clone(), b.clone()).count(), len); let mut init = exhaustive_natural_range(a, b) .rev() .skip(len.saturating_sub(20)) .collect_vec(); init.reverse(); assert_eq!(xs, init.to_debug_string()); } #[test] fn test_exhaustive_natural_range() { exhaustive_natural_range_helper(Natural::ZERO, Natural::ZERO, "[]"); exhaustive_natural_range_helper(Natural::ZERO, Natural::ONE, "[0]"); exhaustive_natural_range_helper( Natural::ZERO, Natural::exact_from(10), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", ); exhaustive_natural_range_helper( Natural::exact_from(10), Natural::exact_from(20), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); exhaustive_natural_range_helper( Natural::exact_from(10), Natural::exact_from(100), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]", ); } #[test] #[should_panic] fn exhaustive_natural_range_fail() { exhaustive_natural_range(Natural::ONE, Natural::ZERO); } ================================================ FILE: malachite-nz/tests/natural/exhaustive/exhaustive_natural_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_natural_range_to_infinity; fn exhaustive_natural_range_to_infinity_helper(a: Natural, values: &str) { let xs = exhaustive_natural_range_to_infinity(a) .take(20) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_natural_range_to_infinity() { exhaustive_natural_range_to_infinity_helper( Natural::ZERO, "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]", ); exhaustive_natural_range_to_infinity_helper( Natural::exact_from(10), "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]", ); } ================================================ FILE: malachite-nz/tests/natural/exhaustive/exhaustive_naturals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::natural::exhaustive::exhaustive_naturals; #[test] fn test_exhaustive_naturals() { assert_eq!( exhaustive_naturals() .take(20) .collect_vec() .to_debug_string(), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]" ); } ================================================ FILE: malachite-nz/tests/natural/exhaustive/exhaustive_positive_naturals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_nz::natural::exhaustive::exhaustive_positive_naturals; #[test] fn test_exhaustive_positive_naturals() { assert_eq!( exhaustive_positive_naturals() .take(20) .collect_vec() .to_debug_string(), "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]" ); } ================================================ FILE: malachite-nz/tests/natural/factorization/is_power.rs ================================================ // Copyright © 2026 William Youmans and 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 malachite_base::num::arithmetic::traits::{Pow, Square}; use malachite_base::num::factorization::traits::{ExpressAsPower, IsPower}; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; use std::str::FromStr; #[test] fn test_is_power() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().is_power(), out); assert_eq!( Natural::from_str(n).unwrap().express_as_power().is_some(), out ); assert_eq!(rug::Integer::from_str(n).unwrap().is_perfect_power(), out); }; test("0", true); test("1", true); test("4", true); test("8", true); test("9", true); test("16", true); test("25", true); test("27", true); test("32", true); test("64", true); test("81", true); test("100", true); test("125", true); test("243", true); test("1024", true); test("1296", true); // - in get_perfect_power_natural // - pow_2 != 1 first time in get_perfect_power_natural // - !pow_2.is_prime() in get_perfect_power_natural // - !(&q).divisible_by(&prime_nat) in get_perfect_power_natural // - (&q).divisible_by(&prime_nat) in get_perfect_power_natural // - (&q).divisible_by(&prime_squared) // - pow_2 != 1 second time in get_perfect_power_natural // - q == 1u32 || pow_2.is_prime() in get_perfect_power_natural test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", true, ); // - pow_2 == 0 in get_perfect_power_natural // - nth <= bits in get_perfect_power_natural // - pow_2 == 0 && let Some(root) = n.checked_root(nth) in get_perfect_power_natural test("999898004334901741252806480882137569", true); // - pow_2 == 0 && let Some(root) != n.checked_root(nth) in get_perfect_power_natural // - pow_2 == 0 && q > SMALLEST_OMITTED_PRIME in get_perfect_power_natural test("999949000866995087", true); // - nth > bits in get_perfect_power_natural test("999983", false); test("115230877647233745723406127208308085892801", true); // - !(&q).divisible_by(&prime_squared) test("113", false); test("2", false); test("3", false); test("5", false); test("6", false); test("7", false); // - pow_2 == 1 first time in get_perfect_power_natural test("10", false); test("12", false); test("15", false); // - pow_2.is_prime() in get_perfect_power_natural test("1470862095575962348216", false); // - q != 1u32 && !pow_2.is_prime() in get_perfect_power_natural test("242811787435972937453260179", false); // - pow_2 != 0 in get_perfect_power_natural // - pow_2 % nth == 0 in get_perfect_power_natural // - pow_2 != 0 && let Some(root) != n.checked_root(nth) in get_perfect_power_natural // - pow_2 != 0 && q > SMALLEST_OMITTED_PRIME in get_perfect_power_natural // - pow_2 % nth != 0 in get_perfect_power_natural test("7176540100844819483539782848", false); // - pow_2 == 1 second time in get_perfect_power_natural test( "23195532513672842039279098010453211078197157913306231000360318871559723303353757940843652\ 0540453520", false, ); // - pow_2 != 0 && let Some(root) = n.checked_root(nth) in get_perfect_power_natural test("4722366482869645213696", true); // - pow_2 != 0 && q <= SMALLEST_OMITTED_PRIME in get_perfect_power_natural test("36353056192134643712", false); } #[test] fn test_is_power_edge_cases() { // Test some specific edge cases // Powers of 2 that are perfect powers let power_of_2_power: Natural = Natural::from(1u64) << 0x1000; assert!(power_of_2_power.is_power()); let power_of_2_non_power = power_of_2_power + Natural::from(1u64); assert!(!power_of_2_non_power.is_power()); // Large powers let big_base = Natural::from_str("987654321098765432109876543210").unwrap(); let big_power = (&big_base).pow(3); assert!(big_power.is_power()); let big_non_power = &big_power + Natural::from(1u32); assert!(!big_non_power.is_power()); // Test prime 1009 (SMALLEST_OMITTED_PRIME) - ensures termination assert!(!Natural::from(1009u32).is_power()); } #[test] fn test_express_as_power() { let test = |n, out| { assert_eq!( Natural::from_str(n) .unwrap() .express_as_power() .to_debug_string(), out ); }; test("0", "Some((0, 2))"); test("1", "Some((1, 2))"); test("4", "Some((2, 2))"); test("8", "Some((2, 3))"); test("9", "Some((3, 2))"); test("16", "Some((2, 4))"); test("25", "Some((5, 2))"); test("27", "Some((3, 3))"); test("32", "Some((2, 5))"); test("64", "Some((2, 6))"); test("81", "Some((3, 4))"); test("100", "Some((10, 2))"); test("125", "Some((5, 3))"); test("243", "Some((3, 5))"); test("1024", "Some((2, 10))"); test("1296", "Some((6, 4))"); test( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", "Some((10, 100))", ); test("999898004334901741252806480882137569", "Some((999983, 6))"); test( "115230877647233745723406127208308085892801", "Some((113, 20))", ); test("2", "None"); test("3", "None"); test("5", "None"); test("6", "None"); test("7", "None"); test("10", "None"); test("12", "None"); test("15", "None"); } #[test] fn is_power_properties() { natural_gen().test_properties(|x| { let is_power = x.is_power(); // Consistency: is_power() should match express_as_power() assert_eq!( is_power, x.express_as_power().is_some(), "is_power() and express_as_power() inconsistent for {x}", ); assert_eq!(rug::Integer::from(&x).is_perfect_power(), is_power); // Any number raised to a power >= 2 should be a perfect power if x > 1u32 { let power_2 = (&x).square(); assert!(power_2.is_power(), "{x}^2 should be a perfect power"); let power_3 = (&x).pow(3); assert!(power_3.is_power(), "{x}^3 should be a perfect power"); } }); natural_unsigned_pair_gen_var_4::().test_properties(|(x, y)| { if y > 1 { let power = (&x).pow(y); assert!(power.is_power()); } }); } #[test] fn express_as_power_properties() { natural_gen().test_properties(|x| { if let Some((p, e)) = x.express_as_power() { assert!(e > 1); assert_eq!((&p).pow(e), x); if x > 1u32 { assert!(p.express_as_power().is_none()); } } }); natural_unsigned_pair_gen_var_4::().test_properties(|(x, y)| { if y > 1 { let power = (&x).pow(y); let ope = power.express_as_power(); assert!(ope.is_some()); let (p, e) = ope.unwrap(); assert_eq!((&p).pow(e), power); if x.express_as_power().is_none() { assert_eq!(x, p); assert_eq!(y, e); } } }); } ================================================ FILE: malachite-nz/tests/natural/factorization/is_square.rs ================================================ // Copyright © 2026 William Youmans // // 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 malachite_base::num::arithmetic::traits::{CheckedSqrt, Square}; use malachite_base::num::factorization::traits::IsSquare; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen_var_3}; use std::str::FromStr; #[test] fn test_is_square() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().is_square(), out); assert_eq!(rug::Integer::from_str(n).unwrap().is_perfect_square(), out); }; // Test small perfect squares test("0", true); test("1", true); test("4", true); test("9", true); test("16", true); test("25", true); test("36", true); test("49", true); test("64", true); test("81", true); test("100", true); // Test small non-squares test("2", false); test("3", false); test("5", false); test("6", false); test("7", false); test("8", false); test("10", false); test("11", false); test("12", false); test("13", false); test("14", false); test("15", false); } #[test] fn test_is_square_edge_cases() { // Test some specific edge cases // Powers of 2 that are perfect squares let power_of_2_square: Natural = Natural::from(1u64) << 0x1000; assert!(power_of_2_square.is_square()); let power_of_2_non_square = power_of_2_square + Natural::from(1u64); assert!(!power_of_2_non_square.is_square()); // Large squares let big_base = Natural::from_str("987654321098765432109876543210").unwrap(); let big_square = big_base.square(); assert!(big_square.is_square()); let big_non_square = &big_square + Natural::from(1u32); assert!(!big_non_square.is_square()); } #[test] fn is_square_properties() { natural_gen().test_properties(|x| { let is_square = x.is_square(); assert_eq!(is_square, (&x).checked_sqrt().is_some()); assert!((&x).square().is_square()); assert_eq!(rug::Integer::from(&x).is_perfect_square(), is_square); }); natural_pair_gen_var_3().test_properties(|(a, b)| { let sq = (&a).square(); // test non-square in range (a^2, (a+1)^2) let non_sq = sq + (b % (Natural::from(2u64) * a)) + Natural::from(1u64); assert!(!non_sq.is_square()); }); } ================================================ FILE: malachite-nz/tests/natural/factorization/primes.rs ================================================ // Copyright © 2026 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::comparison::is_strictly_ascending; use malachite_base::num::arithmetic::traits::SaturatingSub; use malachite_base::num::basic::traits::One; use malachite_base::num::factorization::traits::Primes; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen_var_9; use std::str::FromStr; #[test] fn test_primes_less_than() { let test = |n: &str, out: &str| { let n = Natural::from_str(n).unwrap(); assert_eq!( Natural::primes_less_than(&n) .collect_vec() .to_debug_string(), out ); assert_eq!( Natural::primes() .take_while(|p| *p < n) .collect_vec() .to_debug_string(), out ); }; test("0", "[]"); test("1", "[]"); test("2", "[]"); test("3", "[2]"); test("4", "[2, 3]"); test("5", "[2, 3]"); test("6", "[2, 3, 5]"); test("7", "[2, 3, 5]"); test("8", "[2, 3, 5, 7]"); test("9", "[2, 3, 5, 7]"); test("10", "[2, 3, 5, 7]"); test( "100", "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, \ 89, 97]", ); } #[test] fn test_primes_less_than_or_equal_to() { let test = |n: &str, out: &str| { let n = Natural::from_str(n).unwrap(); assert_eq!( Natural::primes_less_than_or_equal_to(&n) .collect_vec() .to_debug_string(), out ); assert_eq!( Natural::primes() .take_while(|p| *p <= n) .collect_vec() .to_debug_string(), out ); }; test("0", "[]"); test("1", "[]"); test("2", "[2]"); test("3", "[2, 3]"); test("4", "[2, 3]"); test("5", "[2, 3, 5]"); test("6", "[2, 3, 5]"); test("7", "[2, 3, 5, 7]"); test("8", "[2, 3, 5, 7]"); test("9", "[2, 3, 5, 7]"); test("10", "[2, 3, 5, 7]"); test( "100", "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, \ 89, 97]", ); } #[test] fn test_primes() { let expected = "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, \ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, \ 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, \ 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, \ 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, \ 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, \ 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, \ 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, \ 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, \ 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, \ 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, \ 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, \ 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, \ 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, \ 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, \ 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, \ 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, \ 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, \ 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, \ 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, \ 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, \ 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, \ 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, \ 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, \ 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, \ 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, \ 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, \ 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, \ 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, \ 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, \ 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, \ 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, \ 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, \ 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, \ 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, \ 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, \ 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, \ 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, \ 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, \ 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, \ 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, \ 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, \ 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, \ 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, \ 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, \ 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, \ 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, \ 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, \ 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, \ 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, \ 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, \ 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, \ 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, \ 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, \ 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, \ 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, \ 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, \ 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, \ 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, \ 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, \ 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, \ 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, \ 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, \ 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, \ 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919]"; let ps = Natural::primes().take(1000).collect_vec(); assert!(ps.iter().all(Natural::is_valid)); assert_eq!(ps.to_debug_string(), expected); } #[test] fn primes_less_than_properties() { natural_gen_var_9().test_properties(|n| { let ps = Natural::primes_less_than(&n).collect_vec(); assert!(ps.iter().all(Natural::is_valid)); assert!(is_strictly_ascending(ps.iter())); assert_eq!( Natural::primes_less_than_or_equal_to(&(&n).saturating_sub(Natural::ONE)).collect_vec(), ps ); assert_eq!(Natural::primes().take_while(|p| *p < n).collect_vec(), ps); }); } #[test] fn primes_less_than_or_equal_to_properties() { natural_gen_var_9().test_properties(|n| { let ps = Natural::primes_less_than_or_equal_to(&n).collect_vec(); assert!(ps.iter().all(Natural::is_valid)); assert!(is_strictly_ascending(ps.iter())); assert_eq!( Natural::primes_less_than(&(&n + Natural::ONE)).collect_vec(), ps ); assert_eq!(Natural::primes().take_while(|p| *p <= n).collect_vec(), ps); }); } ================================================ FILE: malachite-nz/tests/natural/logic/and.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::CountOnes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::and::{ limbs_and, limbs_and_in_place_either, limbs_and_limb, limbs_and_same_length_to_out, limbs_and_to_out, limbs_slice_and_in_place_left, limbs_slice_and_same_length_in_place_left, limbs_vec_and_in_place_left, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use malachite_nz::test_util::natural::logic::and::{natural_and_alt_1, natural_and_alt_2}; use num::BigUint; use rug; use std::cmp::max; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_limb() { let test = |xs: &[Limb], y: Limb, out: Limb| { assert_eq!(limbs_and_limb(xs, y), out); }; test(&[6, 7], 2, 2); test(&[100, 101, 102], 10, 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] const fn limbs_and_limb_fail() { limbs_and_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_and_limbs_vec_and_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_and(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_vec_and_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[], &[], vec![]); test(&[2], &[3], vec![2]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 0, 1]); test(&[6, 7], &[1, 2, 3], vec![0, 2]); test(&[1, 2, 3], &[6, 7], vec![0, 2]); test(&[100, 101, 102], &[102, 101, 100], vec![100, 101, 100]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_same_length_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_and_same_length_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![1, 0, 1, 5]); test(&[6, 7], &[1, 2], &[0, 0], vec![0, 2]); test(&[6, 7], &[1, 2], &[10, 10, 10, 10], vec![0, 2, 10, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![100, 101, 100, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_same_length_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_and_same_length_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_same_length_to_out_fail_2() { let mut out = vec![10]; limbs_and_same_length_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_and_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![1, 0, 1, 5]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], vec![0, 2, 0, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], vec![0, 2, 0, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![100, 101, 100, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_and_to_out_fail() { let mut out = vec![10, 10]; limbs_and_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_and_same_length_in_place_left() { let test = |xs_before: &[Limb], ys, xs_after| { let mut xs = xs_before.to_vec(); limbs_slice_and_same_length_in_place_left(&mut xs, ys); assert_eq!(xs, xs_after); }; test(&[], &[], vec![]); test(&[6, 7], &[1, 2], vec![0, 2]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 0, 1]); test(&[100, 101, 102], &[102, 101, 100], vec![100, 101, 100]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_and_same_length_in_place_left_fail() { let mut out = vec![6, 7]; limbs_slice_and_same_length_in_place_left(&mut out, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_and_in_place_left() { let test = |xs_before: &[Limb], ys, truncate_length, xs_after| { let mut xs = xs_before.to_vec(); assert_eq!(limbs_slice_and_in_place_left(&mut xs, ys), truncate_length); assert_eq!(xs, xs_after); }; test(&[], &[], None, vec![]); test(&[6, 7], &[1, 2], None, vec![0, 2]); test(&[6, 7], &[1, 2, 3], None, vec![0, 2]); test(&[1, 2, 3], &[6, 7], Some(2), vec![0, 2, 3]); test(&[], &[1, 2, 3], None, vec![]); test(&[1, 2, 3], &[], Some(0), vec![1, 2, 3]); test(&[1, 1, 1], &[1, 2, 3], None, vec![1, 0, 1]); test( &[100, 101, 102], &[102, 101, 100], None, vec![100, 101, 100], ); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_and_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], right, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_and_in_place_either(&mut xs, &mut ys), right); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![], vec![]); test(&[6, 7], &[1, 2], false, vec![0, 2], vec![1, 2]); test(&[6, 7], &[1, 2, 3], false, vec![0, 2], vec![1, 2, 3]); test(&[1, 2, 3], &[6, 7], true, vec![1, 2, 3], vec![0, 2]); test(&[], &[1, 2, 3], false, vec![], vec![1, 2, 3]); test(&[1, 2, 3], &[], true, vec![1, 2, 3], vec![]); test(&[1, 1, 1], &[1, 2, 3], false, vec![1, 0, 1], vec![1, 2, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![100, 101, 100], vec![102, 101, 100], ); } #[test] fn test_and() { let test = |u, v, out| { let mut n = Natural::from_str(u).unwrap(); n &= Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = Natural::from_str(u).unwrap(); n &= &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() & Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() & Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() & &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() & &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!( natural_and_alt_1( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); assert_eq!( natural_and_alt_2( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); let n = BigUint::from_str(u).unwrap() & BigUint::from_str(v).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() & rug::Integer::from_str(v).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "0"); test("123", "0", "0"); test("123", "456", "72"); test("1000000000000", "123", "0"); test("123", "1000000000000", "0"); test("1000000000001", "123", "1"); test("12345678987654321", "987654321", "579887281"); test("1000000000000", "999999999999", "999999995904"); test("12345678987654321", "314159265358979", "312331665941633"); } #[test] fn limbs_and_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { assert_eq!( limbs_and_limb(&xs, y), Natural::from_owned_limbs_asc(xs) & Natural::from(y) ); }); } #[test] fn limbs_and_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_and(&xs, &ys)), Natural::from_owned_limbs_asc(xs) & Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_and_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_31().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_and_same_length_to_out(&mut out, &xs, &ys); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) & Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_and_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_32().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_and_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) & Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_slice_and_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_slice_and_same_length_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) & Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_slice_and_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); let truncate_size = limbs_slice_and_in_place_left(&mut xs, &ys); let n = Natural::from_limbs_asc(&xs_old) & Natural::from_owned_limbs_asc(ys); if let Some(truncate_size) = truncate_size { assert_eq!(Natural::from_limbs_asc(&xs[..truncate_size]), n); assert_eq!(&xs[truncate_size..], &xs_old[truncate_size..]); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); } }); } #[test] fn limbs_vec_and_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_vec_and_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) & Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_and_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_and_in_place_either(&mut xs, &mut ys); let n = Natural::from_limbs_asc(&xs_old) & Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn and_properties() { natural_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() & y.clone(); let result_val_ref = x.clone() & &y; let result_ref_val = &x & y.clone(); let result = &x & &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x &= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x &= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x &= rug::Integer::from(&y); assert_eq!(Natural::exact_from(&mut_x), result); assert_eq!( Natural::from(&(BigUint::from(&x) & BigUint::from(&y))), result ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) & rug::Integer::from(&y))), result ); assert_eq!(natural_and_alt_1(&x, &y), result); assert_eq!(natural_and_alt_2(&x, &y), result); assert_eq!(&y & &x, result); assert_eq!(&result & &x, result); assert_eq!(&result & &y, result); assert!(result <= x); assert!(result <= y); let ones = result.count_ones(); assert!(ones <= x.count_ones()); assert!(ones <= y.count_ones()); }); natural_gen().test_properties(|x| { assert_eq!(&x & Natural::ZERO, 0); assert_eq!(Natural::ZERO & &x, 0); assert_eq!(&x & &x, x); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x & &y) & &z, x & (y & z)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) & Natural::from(y), x & y); }); } ================================================ FILE: malachite-nz/tests/natural/logic/assign_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_bool_triple_gen_var_1; use rug; use std::str::FromStr; #[test] fn test_assign_bit() { let test = |u, index, bit, out| { let mut n = Natural::from_str(u).unwrap(); n.assign_bit(index, bit); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = rug::Integer::from_str(u).unwrap(); n.set_bit(u32::exact_from(index), bit); assert_eq!(n.to_string(), out); }; test("0", 10, true, "1024"); test("100", 0, true, "101"); test("1000000000000", 10, true, "1000000001024"); test( "1000000000000", 100, true, "1267650600228229402496703205376", ); test("5", 100, true, "1267650600228229401496703205381"); test("0", 10, false, "0"); test("0", 100, false, "0"); test("1024", 10, false, "0"); test("101", 0, false, "100"); test("1000000001024", 10, false, "1000000000000"); test("1000000001024", 100, false, "1000000001024"); test( "1267650600228229402496703205376", 100, false, "1000000000000", ); test("1267650600228229401496703205381", 100, false, "5"); } #[test] fn assign_bit_properties() { natural_unsigned_bool_triple_gen_var_1().test_properties(|(n, index, bit)| { let mut mut_n = n.clone(); mut_n.assign_bit(index, bit); assert!(mut_n.is_valid()); let result = mut_n; let mut rug_n = rug::Integer::from(&n); rug_n.set_bit(u32::exact_from(index), bit); assert_eq!(Natural::exact_from(&rug_n), result); }); } ================================================ FILE: malachite-nz/tests/natural/logic/assign_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ModPowerOf2, ModPowerOf2Sub, NegModPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::logic::traits::{BitBlockAccess, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::large_type_gen_var_3; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_block_access::limbs_assign_bits; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_gen, natural_natural_unsigned_triple_gen, natural_unsigned_pair_gen_var_4, natural_unsigned_unsigned_natural_quadruple_gen_var_1, }; use std::str::FromStr; fn verify_limbs_assign_bits(xs: &[Limb], start: u64, end: u64, bits: &[Limb], out: &[Limb]) { let old_n = Natural::from_limbs_asc(xs); let mut n = old_n.clone(); let bits = Natural::from_limbs_asc(bits); n.assign_bits(start, end, &bits); let result = n; assert_eq!(Natural::from_limbs_asc(out), result); let mut n = old_n; assign_bits_naive::(&mut n, start, end, &bits); assert_eq!(n, result); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_assign_bits() { let test = |xs: &[Limb], start: u64, end: u64, bits: &[Limb], out: &[Limb]| { let xs_old = xs; let mut xs = xs.to_vec(); limbs_assign_bits(&mut xs, start, end, bits); assert_eq!(xs, out); verify_limbs_assign_bits(xs_old, start, end, bits, out); }; // - bits_limb_width >= bits.len() // - end_limb <= limbs.len() // - xs_len <= ys_len in copy_from_diff_len_slice // - start_remainder == 0 // - end_remainder != 0 test(&[1], 0, 1, &[1], &[1]); // - start_remainder != 0 test(&[1], 1, 2, &[1], &[3]); // - bits_limb_width < bits.len() test(&[1], 0, 1, &[0, 1], &[0]); test(&[123], 64, 128, &[456], &[123, 0, 456, 0]); test(&[123], 80, 100, &[456], &[123, 0, 29884416, 0]); test(&[123, 456], 80, 100, &[789, 321], &[123, 456, 51707904, 0]); // - end_limb > limbs.len() test( &[1619367413, 294928230], 73, 89, &[4211621339, 3627566573, 1208090001, 4045783696, 2932656682, 177881999, 898588654], &[1619367413, 294928230, 8107520], ); // - end_remainder == 0 test( &[1404969050, 495263765, 2378891263, 1299524786, 1654909014, 2724647948], 21, 32, &[ 3269073749, 1170977875, 2823122906, 144832001, 3738801070, 1107604886, 4260406413, 1766163855, 592730267, 484513503, 1204041536, 3664297641, ], &[1790845018, 495263765, 2378891263, 1299524786, 1654909014, 2724647948], ); // - xs_len > ys_len in copy_from_diff_len_slice test( &[ 4126931041, 1467617913, 1718397261, 904474857, 312429577, 2397873671, 3967827549, 3842236128, 3414636734, 1846949256, 1999024107, 424639176, ], 27, 77, &[977841009], &[ 2382100577, 30557531, 1718394880, 904474857, 312429577, 2397873671, 3967827549, 3842236128, 3414636734, 1846949256, 1999024107, 424639176, ], ); } #[test] #[should_panic] fn limbs_assign_bits_fail_1() { let mut xs = vec![123]; limbs_assign_bits(&mut xs, 10, 5, &[456]); } #[test] #[should_panic] fn limbs_assign_bits_fail_2() { let mut xs = vec![123]; limbs_assign_bits(&mut xs, 10, 10, &[456]); } #[test] fn test_assign_bits() { let test = |u, start, end, v, out| { let mut n = Natural::from_str(u).unwrap(); n.assign_bits(start, end, &Natural::from_str(v).unwrap()); assert_eq!(n, Natural::from_str(out).unwrap()); let mut n = Natural::from_str(u).unwrap(); assign_bits_naive(&mut n, start, end, &Natural::from_str(v).unwrap()); assert_eq!(n, Natural::from_str(out).unwrap()); }; test("123", 10, 10, "456", "123"); test("123", 5, 7, "456", "27"); test("123", 64, 128, "456", "8411715297611555537019"); test("123", 80, 100, "456", "551270173744270903666016379"); test( "1000000000000", 80, 100, "456", "551270173744271903666016256", ); test( "456", 80, 100, "1000000000000", "401092572728463209067316249032", ); test( "1000000000000", 80, 100, "2000000000000", "802185145456926419134632497152", ); } #[test] #[should_panic] fn assign_bits_fail() { let mut n = Natural::from(123u32); n.assign_bits(10, 5, &Natural::from(456u32)); } #[test] fn limbs_assign_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); large_type_gen_var_3().test_properties_with_config(&config, |(xs_in, start, end, ref bits)| { let mut xs = xs_in.clone(); limbs_assign_bits(&mut xs, start, end, bits); verify_limbs_assign_bits(&xs_in, start, end, bits, &xs); }); } #[test] fn assign_bits_properties() { natural_unsigned_unsigned_natural_quadruple_gen_var_1().test_properties( |(n, start, end, bits)| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(start, end, &bits); let result = n; let mut n = old_n.clone(); assign_bits_naive(&mut n, start, end, &bits); assert_eq!(n, result); n.assign_bits(start, end, &bits); assert_eq!(n, result); let bits_width = end - start; assert_eq!(n.get_bits(start, end), (&bits).mod_power_of_2(bits_width)); let mut n = !old_n; let not_bits = bits .neg_mod_power_of_2(bits_width) .mod_power_of_2_sub(Natural::ONE, bits_width); n.assign_bits(start, end, ¬_bits); assert_eq!(!n, result); }, ); natural_natural_unsigned_triple_gen().test_properties(|(n, bits, start)| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(start, start, &bits); assert_eq!(n, old_n); }); natural_unsigned_pair_gen_var_4().test_properties(|(bits, start)| { let mut n = Natural::ZERO; n.assign_bits(start, start + bits.significant_bits(), &bits); assert_eq!(n, bits << start); }); natural_gen().test_properties(|n| { let old_n = n; let mut n = old_n.clone(); n.assign_bits(0, old_n.significant_bits(), &Natural::ZERO); assert_eq!(n, 0); let mut n = Natural::ZERO; n.assign_bits(0, old_n.significant_bits(), &old_n); assert_eq!(n, old_n); let mut n = old_n.clone(); n.assign_bits(0, old_n.significant_bits(), &old_n); assert_eq!(n, old_n); }); } ================================================ FILE: malachite-nz/tests/natural/logic/bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitConvertible, BitIterable, SignificantBits}; use malachite_base::test_util::common::test_double_ended_iterator_size_hint; use malachite_base::test_util::generators::{unsigned_gen, unsigned_gen_var_5}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_bool_vec_pair_gen_var_2, natural_gen, natural_unsigned_pair_gen_var_4, }; #[test] fn test_bits() { let n = Natural::from(105u32); let mut bits = n.bits(); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); assert_eq!(bits[0], true); assert_eq!(bits[1], false); assert_eq!(bits[2], false); assert_eq!(bits[3], true); assert_eq!(bits[4], false); assert_eq!(bits[5], true); assert_eq!(bits[6], true); assert_eq!(bits[7], false); assert_eq!(bits[8], false); let mut bits = n.bits(); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), Some(true)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next_back(), Some(false)); assert_eq!(bits.next_back(), Some(true)); assert_eq!(bits.next(), None); assert_eq!(bits.next_back(), None); } #[test] fn bits_properties() { natural_gen().test_properties(|n| { test_double_ended_iterator_size_hint(n.bits(), usize::exact_from(n.significant_bits())); }); natural_bool_vec_pair_gen_var_2().test_properties(|(n, bs)| { let mut bits = n.bits(); let mut bit_vec = Vec::new(); let mut i = 0; for &b in &bs { if b { bit_vec.insert(i, bits.next().unwrap()); i += 1; } else { bit_vec.insert(i, bits.next_back().unwrap()); } } assert!(bits.next().is_none()); assert!(bits.next_back().is_none()); assert_eq!(n.to_bits_asc(), bit_vec); }); natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { if u < n.significant_bits() { assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]); } else { assert_eq!(n.bits()[u], false); } }); unsigned_gen_var_5().test_properties(|u| { assert_eq!(Natural::ZERO.bits()[u], false); }); unsigned_gen::().test_properties(|u| { assert!(u.bits().eq(Natural::from(u).bits())); }); } ================================================ FILE: malachite-nz/tests/natural/logic/clear_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_16, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_access::limbs_clear_bit; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; #[cfg(feature = "32_bit_limbs")] use rug; #[cfg(feature = "32_bit_limbs")] use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_clear_bit() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut xs = xs.to_vec(); limbs_clear_bit(&mut xs, index); assert_eq!(xs, out); }; test(&[3, 3], 33, &[3, 1]); test(&[3, 1], 1, &[1, 1]); test(&[3, 3], 100, &[3, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_clear_bit() { let test = |u, index, out| { let mut n = Natural::from_str(u).unwrap(); n.clear_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = rug::Integer::from_str(u).unwrap(); n.set_bit(u32::exact_from(index), false); assert_eq!(n.to_string(), out); }; test("0", 10, "0"); test("0", 100, "0"); test("1024", 10, "0"); test("101", 0, "100"); test("1000000001024", 10, "1000000000000"); test("1000000001024", 100, "1000000001024"); test("1267650600228229402496703205376", 100, "1000000000000"); test("1267650600228229401496703205381", 100, "5"); } #[test] fn limbs_clear_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, index)| { let mut mut_xs = xs.clone(); let mut n = Natural::from_limbs_asc(&xs); limbs_clear_bit(&mut mut_xs, index); n.clear_bit(index); assert_eq!(Natural::from_limbs_asc(&mut_xs), n); }); } #[test] fn clear_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.clear_bit(index); assert!(mut_n.is_valid()); let result = mut_n; let mut rug_n = rug::Integer::from(&n); rug_n.set_bit(u32::exact_from(index), false); assert_eq!(Natural::exact_from(&rug_n), result); let mut mut_n = n.clone(); mut_n.assign_bit(index, false); assert_eq!(mut_n, result); assert_eq!(Integer::from(&n) & !Natural::power_of_2(index), result); assert!(result <= n); if n.get_bit(index) { assert_ne!(result, n); let mut mut_result = result; mut_result.set_bit(index); assert_eq!(mut_result, n); } else { assert_eq!(result, n); } }); unsigned_pair_gen_var_2::().test_properties(|(u, index)| { let mut mut_u = u; mut_u.clear_bit(index); let mut n = Natural::from(u); n.clear_bit(index); assert_eq!(n, mut_u); }); } ================================================ FILE: malachite-nz/tests/natural/logic/count_ones.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::logic::traits::CountOnes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_gen, unsigned_vec_gen}; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::count_ones::limbs_count_ones; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::count_ones::{ natural_count_ones_alt_1, natural_count_ones_alt_2, }; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_count_ones() { let test = |xs, out| { assert_eq!(limbs_count_ones(xs), out); }; test(&[], 0); test(&[0, 1, 2], 2); test(&[1, u32::MAX], 33); } #[test] fn test_count_ones() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().count_ones(), out); assert_eq!( natural_count_ones_alt_1(&Natural::from_str(n).unwrap()), out ); assert_eq!( natural_count_ones_alt_2(&Natural::from_str(n).unwrap()), out ); }; test("0", 0); test("105", 4); test("1000000000000", 13); test("4294967295", 32); test("4294967296", 1); test("18446744073709551615", 64); test("18446744073709551616", 1); } #[test] fn limbs_count_ones_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { assert_eq!( limbs_count_ones(&xs), Natural::from_owned_limbs_asc(xs).count_ones() ); }); } #[test] fn count_ones_properties() { natural_gen().test_properties(|x| { let ones = x.count_ones(); assert_eq!(natural_count_ones_alt_1(&x), ones); assert_eq!(natural_count_ones_alt_2(&x), ones); assert_eq!(ones == 0, x == 0); assert_eq!(ones == 1, x.is_power_of_2()); assert_eq!((!x).checked_count_zeros(), Some(ones)); }); unsigned_gen::().test_properties(|u| { assert_eq!(Natural::from(u).count_ones(), CountOnes::count_ones(u)); }); } ================================================ FILE: malachite-nz/tests/natural/logic/flip_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; use rug; use std::str::FromStr; #[test] fn test_flip_bit() { let test = |u, index, out| { let mut n = Natural::from_str(u).unwrap(); n.flip_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = rug::Integer::from_str(u).unwrap(); n.toggle_bit(u32::exact_from(index)); assert_eq!(n.to_string(), out); }; test("0", 10, "1024"); test("1024", 10, "0"); test("100", 0, "101"); test("101", 0, "100"); test("1000000000000", 10, "1000000001024"); test("1000000001024", 10, "1000000000000"); test("1000000000000", 100, "1267650600228229402496703205376"); test("1267650600228229402496703205376", 100, "1000000000000"); test("5", 100, "1267650600228229401496703205381"); test("1267650600228229401496703205381", 100, "5"); } #[test] fn flip_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.flip_bit(index); assert!(mut_n.is_valid()); let result = mut_n; assert_ne!(result, n); let mut rug_n = rug::Integer::from(&n); rug_n.toggle_bit(u32::exact_from(index)); assert_eq!(Natural::exact_from(&rug_n), result); let mut mut_result = result.clone(); mut_result.flip_bit(index); assert_eq!(mut_result, n); assert_eq!(n ^ Natural::power_of_2(index), result); }); } ================================================ FILE: malachite-nz/tests/natural/logic/from_bits.rs ================================================ // Copyright © 2026 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::num::conversion::traits::ConvertibleFrom; use malachite_base::num::logic::traits::BitConvertible; use malachite_base::test_util::generators::bool_vec_gen; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::num::logic::bit_convertible::{ from_bits_asc_alt, from_bits_desc_alt, }; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::natural::logic::from_bits::{ from_bits_asc_naive, from_bits_desc_naive, }; #[test] fn test_from_bits_asc() { let test = |bits: &[bool], out| { let x = Natural::from_bits_asc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(&[], "0"); test(&[false], "0"); test(&[false, false, false], "0"); test(&[true], "1"); test(&[false, true, true], "6"); test(&[true, false, false, true, false, true, true], "105"); test(&[true, false, false, true, false, true, true, false], "105"); test( &[true, false, false, true, false, true, true, false, false, false], "105", ); test( &[ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, ], "1000000000000", ); test( &[ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, false, ], "1000000000000", ); } #[test] fn test_from_bits_desc() { let test = |bits: &[bool], out| { let x = Natural::from_bits_desc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(&[], "0"); test(&[false], "0"); test(&[false, false, false], "0"); test(&[true], "1"); test(&[true, true, false], "6"); test(&[true, true, false, true, false, false, true], "105"); test(&[false, true, true, false, true, false, false, true], "105"); test( &[false, false, false, true, true, false, true, false, false, true], "105", ); test( &[ true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], "1000000000000", ); test( &[ false, true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], "1000000000000", ); } #[test] fn from_bits_asc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 1024); config.insert("mean_stripe_n", 512); bool_vec_gen().test_properties_with_config(&config, |bits| { let x = Natural::from_bits_asc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(from_bits_asc_naive(bits.iter().copied()), x); assert_eq!(from_bits_asc_alt::(bits.iter().copied()), x); let mut trimmed_bits = bits .iter() .copied() .rev() .skip_while(|&bit| !bit) .collect_vec(); trimmed_bits.reverse(); assert_eq!(x.to_bits_asc(), trimmed_bits); assert_eq!(Natural::from_bits_desc(bits.iter().copied().rev()), x); if !bits.is_empty() && *bits.last().unwrap() { assert_eq!(x.to_bits_asc(), *bits); } assert_eq!(bits.iter().all(|b| !b), x == 0); if Limb::convertible_from(&x) { assert_eq!(Limb::from_bits_asc(bits.into_iter()), x); } }); } #[test] fn from_bits_desc_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 1024); config.insert("mean_stripe_n", 512); bool_vec_gen().test_properties_with_config(&config, |bits| { let x = Natural::from_bits_desc(bits.iter().copied()); assert!(x.is_valid()); assert_eq!(from_bits_desc_naive(bits.iter().copied()), x); assert_eq!(from_bits_desc_alt::(bits.iter().copied()), x); assert_eq!( x.to_bits_desc(), bits.iter().copied().skip_while(|&b| !b).collect_vec() ); assert_eq!(Natural::from_bits_asc(bits.iter().copied().rev()), x); if !bits.is_empty() && bits[0] { assert_eq!(x.to_bits_desc(), *bits); } assert_eq!(bits.iter().all(|b| !b), x == 0); if Limb::convertible_from(&x) { assert_eq!(Limb::from_bits_desc(bits.iter().copied()), x); } }); } ================================================ FILE: malachite-nz/tests/natural/logic/get_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_16, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_access::limbs_get_bit; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; use malachite_nz::test_util::natural::logic::get_bit::num_get_bit; use num::BigUint; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_get_bit() { let test = |xs: &[Limb], index: u64, out: bool| { assert_eq!(limbs_get_bit(xs, index), out); }; test(&[1], 0, true); test(&[1], 100, false); test(&[123], 2, false); test(&[123], 3, true); test(&[123], 100, false); test(&[0, 0b1011], 0, false); test(&[0, 0b1011], 32, true); test(&[0, 0b1011], 33, true); test(&[0, 0b1011], 34, false); test(&[0, 0b1011], 35, true); test(&[0, 0b1011], 100, false); } #[test] fn test_get_bit() { let test = |n, index, out| { assert_eq!(Natural::from_str(n).unwrap().get_bit(index), out); assert_eq!(num_get_bit(&BigUint::from_str(n).unwrap(), index), out); assert_eq!( rug::Integer::from_str(n) .unwrap() .get_bit(u32::exact_from(index)), out ); }; test("0", 0, false); test("0", 100, false); test("123", 2, false); test("123", 3, true); test("123", 100, false); test("1000000000000", 12, true); test("1000000000000", 100, false); } #[test] fn limbs_get_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, index)| { assert_eq!( Natural::from_limbs_asc(&xs).get_bit(index), limbs_get_bit(&xs, index) ); }); } #[test] fn get_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { let bit = n.get_bit(index); assert_eq!(num_get_bit(&BigUint::from(&n), index), bit); assert_eq!(rug::Integer::from(&n).get_bit(u32::exact_from(index)), bit); assert_eq!(&n & Natural::power_of_2(index) != 0, bit); assert_ne!((!n).get_bit(index), bit); }); natural_gen().test_properties(|n| { let significant_bits = n.significant_bits(); assert!(!n.get_bit(significant_bits)); if n != 0 { assert!(n.get_bit(significant_bits - 1)); } }); unsigned_pair_gen_var_2::().test_properties(|(u, index)| { assert_eq!(Natural::from(u).get_bit(index), u.get_bit(index)); }); } ================================================ FILE: malachite-nz/tests/natural/logic/get_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{BitBlockAccess, LowMask, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_16, unsigned_triple_gen_var_5, unsigned_vec_unsigned_unsigned_triple_gen_var_3, }; use malachite_base::test_util::num::logic::bit_block_access::get_bits_naive; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_block_access::{limbs_slice_get_bits, limbs_vec_get_bits}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{ natural_unsigned_pair_gen, natural_unsigned_unsigned_triple_gen_var_4, }; use std::str::FromStr; fn verify_limbs_get_bits(xs: &[Limb], start: u64, end: u64, out: &[Limb]) { let n = Natural::from_limbs_asc(xs); let result = n.get_bits(start, end); assert_eq!(get_bits_naive::(&n, start, end), result); assert_eq!(Natural::from_limbs_asc(out), result); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_get_bits() { let test = |xs: &[Limb], start: u64, end: u64, out: &[Limb]| { assert_eq!(limbs_slice_get_bits(xs, start, end), out); verify_limbs_get_bits(xs, start, end, out); }; // - limb_start >= len test(&[], 10, 20, &[]); // - limb_start < len // - limb_end >= len // - offset != 0 test(&[0x12345678, 0xabcdef01], 16, 48, &[0xef011234]); // - limb_end < len test(&[0x12345678, 0xabcdef01], 4, 16, &[0x567]); // - offset == 0 test(&[0x12345678, 0xabcdef01], 0, 100, &[0x12345678, 0xabcdef01]); test(&[0x12345678, 0xabcdef01], 10, 10, &[]); } #[test] #[should_panic] fn limbs_slice_get_bits_fail() { limbs_slice_get_bits(&[123], 10, 5); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_get_bits() { let test = |xs: Vec, start: u64, end: u64, out: &[Limb]| { assert_eq!(limbs_vec_get_bits(xs, start, end), out); }; test(vec![], 10, 20, &[]); test(vec![0x12345678, 0xabcdef01], 16, 48, &[0xef011234, 0]); test(vec![0x12345678, 0xabcdef01], 4, 16, &[0x567]); test( vec![0x12345678, 0xabcdef01], 0, 100, &[0x12345678, 0xabcdef01], ); test(vec![0x12345678, 0xabcdef01], 10, 10, &[0]); } #[test] #[should_panic] fn limbs_vec_get_bits_fail() { limbs_vec_get_bits(vec![123], 10, 5); } #[test] fn test_get_bits() { let test = |n, start, end, out| { assert_eq!( Natural::from_str(n).unwrap().get_bits(start, end), Natural::from_str(out).unwrap() ); assert_eq!( Natural::from_str(n).unwrap().get_bits_owned(start, end), Natural::from_str(out).unwrap() ); assert_eq!( get_bits_naive::(&Natural::from_str(n).unwrap(), start, end), Natural::from_str(out).unwrap() ); }; test("12379813738590787192", 16, 48, "4009824820"); test("12379813738590787192", 4, 16, "1383"); test("12379813738590787192", 0, 100, "12379813738590787192"); test("12379813738590787192", 10, 10, "0"); } #[test] #[should_panic] fn get_bits_fail() { Natural::from(123u32).get_bits(10, 5); } #[test] #[should_panic] fn get_bits_owned_fail() { Natural::from(123u32).get_bits_owned(10, 5); } #[test] fn limbs_get_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_unsigned_triple_gen_var_3().test_properties_with_config( &config, |(xs, start, end)| { let out = limbs_slice_get_bits(&xs, start, end); verify_limbs_get_bits(&xs, start, end, &out); let out = limbs_vec_get_bits(xs.to_vec(), start, end); verify_limbs_get_bits(&xs, start, end, &out); }, ); } #[test] fn get_bits_properties() { natural_unsigned_unsigned_triple_gen_var_4().test_properties(|(n, start, end)| { let bits = n.get_bits(start, end); assert_eq!(n.clone().get_bits_owned(start, end), bits); assert_eq!(get_bits_naive::(&n, start, end), bits); assert!(bits <= n); let significant_bits = n.significant_bits(); assert_eq!( n.get_bits(start + significant_bits, end + significant_bits), 0 ); assert_eq!( (!&n).get_bits(start, end), Natural::low_mask(end - start) - &bits ); let mut mut_n = n.clone(); mut_n.assign_bits(start, end, &bits); assert_eq!(n, mut_n); }); natural_unsigned_pair_gen().test_properties(|(n, start)| { assert_eq!(n.get_bits(start, start), 0); }); unsigned_pair_gen_var_16().test_properties(|(start, end)| { assert_eq!(Natural::ZERO.get_bits(start, end), 0); }); unsigned_triple_gen_var_5::().test_properties(|(n, start, end)| { assert_eq!( Natural::from(n).get_bits(start, end), n.get_bits(start, end) ); }); } ================================================ FILE: malachite-nz/tests/natural/logic/hamming_distance.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::{CheckedHammingDistance, CountOnes, HammingDistance}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_pair_gen_var_27; use malachite_base::test_util::generators::{ unsigned_vec_pair_gen_var_6, unsigned_vec_pair_gen_var_7, unsigned_vec_unsigned_pair_gen_var_15, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::hamming_distance::{ limbs_hamming_distance, limbs_hamming_distance_limb, limbs_hamming_distance_same_length, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use malachite_nz::test_util::natural::logic::hamming_distance::{ natural_hamming_distance_alt_1, natural_hamming_distance_alt_2, rug_hamming_distance, }; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_hamming_distance_limb() { let test = |xs, y, out| { assert_eq!(limbs_hamming_distance_limb(xs, y), out); }; test(&[2], 3, 1); test(&[1, 1, 1], 1, 2); test(&[1, 1, 1], 2, 4); test(&[1, 2, 3], 0, 4); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_hamming_distance_limb_fail() { limbs_hamming_distance_limb(&[], 0); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_hamming_distance_same_length() { let test = |xs, ys, out| { assert_eq!(limbs_hamming_distance_same_length(xs, ys), out); }; test(&[], &[], 0); test(&[2], &[3], 1); test(&[1, 1, 1], &[1, 2, 3], 3); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_hamming_distance_limb_same_length_fail() { limbs_hamming_distance_same_length(&[1], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_hamming_distance() { let test = |xs, ys, out| { assert_eq!(limbs_hamming_distance(xs, ys), out); }; test(&[], &[], 0); test(&[2], &[3], 1); test(&[1, 1, 1], &[1, 2, 3], 3); test(&[], &[1, 2, 3], 4); test(&[1, 2, 3], &[], 4); test(&[1, 1, 1], &[1, 2, 3, 4], 4); test(&[1, 2, 3, 4], &[1, 1, 1], 4); } #[test] fn test_hamming_distance() { let test = |x, y, out| { assert_eq!( Natural::from_str(x) .unwrap() .hamming_distance(&Natural::from_str(y).unwrap()), out ); assert_eq!( natural_hamming_distance_alt_1( &Natural::from_str(x).unwrap(), &Natural::from_str(y).unwrap(), ), out ); assert_eq!( natural_hamming_distance_alt_2( &Natural::from_str(x).unwrap(), &Natural::from_str(y).unwrap(), ), out ); assert_eq!( rug_hamming_distance( &rug::Integer::from_str(x).unwrap(), &rug::Integer::from_str(y).unwrap(), ), out ); }; test("105", "123", 2); test("1000000000000", "0", 13); test("4294967295", "0", 32); test("4294967295", "4294967295", 0); test("4294967295", "4294967296", 33); test("1000000000000", "1000000000001", 1); } #[test] fn limbs_hamming_distance_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { assert_eq!( limbs_hamming_distance_limb(&xs, y), Natural::from_owned_limbs_asc(xs).hamming_distance(&Natural::from(y)) ); }); } #[test] fn limbs_hamming_distance_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( limbs_hamming_distance_same_length(&xs, &ys), Natural::from_owned_limbs_asc(xs).hamming_distance(&Natural::from_owned_limbs_asc(ys)) ); }); } #[test] fn limbs_hamming_distance_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_7().test_properties_with_config(&config, |(xs, ys)| { assert_eq!( limbs_hamming_distance(&xs, &ys), Natural::from_owned_limbs_asc(xs).hamming_distance(&Natural::from_owned_limbs_asc(ys)) ); }); } #[test] fn hamming_distance_properties() { natural_pair_gen().test_properties(|(x, y)| { let distance = x.hamming_distance(&y); assert_eq!( rug_hamming_distance(&rug::Integer::from(&x), &rug::Integer::from(&y)), distance ); assert_eq!(y.hamming_distance(&x), distance); assert_eq!(natural_hamming_distance_alt_1(&x, &y), distance); assert_eq!(natural_hamming_distance_alt_2(&x, &y), distance); assert_eq!(distance == 0, x == y); assert_eq!((&x ^ &y).count_ones(), distance); assert_eq!((!x).checked_hamming_distance(&!y), Some(distance)); }); natural_triple_gen().test_properties(|(x, y, z)| { assert!(x.hamming_distance(&z) <= x.hamming_distance(&y) + y.hamming_distance(&z)); }); natural_gen().test_properties(|n| { assert_eq!(n.hamming_distance(&n), 0); assert_eq!(n.hamming_distance(&Natural::ZERO), n.count_ones()); assert_eq!(Natural::ZERO.hamming_distance(&n), n.count_ones()); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!( Natural::from(x).hamming_distance(&Natural::from(y)), x.hamming_distance(y) ); }); } ================================================ FILE: malachite-nz/tests/natural/logic/index_of_next_false_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, BitScan}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_16, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_scan::limbs_index_of_next_false_bit; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; use malachite_nz::test_util::natural::logic::index_of_next_false_bit::*; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_index_of_next_false_bit() { let test = |xs, u, out| { assert_eq!(limbs_index_of_next_false_bit(xs, u), out); }; test(&[], 0, 0); test(&[], 100, 100); test(&[0], 0, 0); test(&[0], 100, 100); test(&[0b100], 0, 0); test(&[0b100], 1, 1); test(&[0b100], 2, 3); test(&[0b100], 3, 3); test(&[0, 0b1011], 0, 0); test(&[0, 0b1011], 20, 20); test(&[0, 0b1011], 31, 31); test(&[0, 0b1011], 32, 34); test(&[0, 0b1011], 33, 34); test(&[0, 0b1011], 34, 34); test(&[0, 0b1011], 35, 36); test(&[0, 0b1011], 100, 100); test(&[0, 0b1011, 0xfffffff0, u32::MAX, 1], 64, 64); test(&[0, 0b1011, 0xfffffff0, u32::MAX, 1], 68, 129); } #[test] fn test_index_of_next_false_bit() { let test = |n, u, out| { assert_eq!( Natural::from_str(n).unwrap().index_of_next_false_bit(u), out ); assert_eq!( natural_index_of_next_false_bit_alt(&Natural::from_str(n).unwrap(), u), out ); assert_eq!( rug::Integer::from_str(n) .unwrap() .find_zero(u32::exact_from(u)) .map(u64::from), out ); }; test("0", 0, Some(0)); test("0", 100, Some(100)); test("47244640256", 0, Some(0)); test("47244640256", 20, Some(20)); test("47244640256", 31, Some(31)); test("47244640256", 32, Some(34)); test("47244640256", 33, Some(34)); test("47244640256", 34, Some(34)); test("47244640256", 35, Some(36)); test("47244640256", 100, Some(100)); test("680564733841876926631601309731428237312", 64, Some(64)); test("680564733841876926631601309731428237312", 68, Some(129)); } #[test] fn limbs_index_of_next_false_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, u)| { assert_eq!( Some(limbs_index_of_next_false_bit(&xs, u)), Natural::from_owned_limbs_asc(xs).index_of_next_false_bit(u) ); }); } #[test] fn index_of_next_false_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { let result = n.index_of_next_false_bit(u); assert_eq!(result, natural_index_of_next_false_bit_alt(&n, u)); assert_eq!( rug::Integer::from(&n) .find_zero(u32::exact_from(u)) .map(u64::from), result ); let result = result.unwrap(); assert!(result >= u); assert!(!n.get_bit(result)); assert_eq!(result == u, !n.get_bit(u)); assert_eq!((!n).index_of_next_true_bit(u), Some(result)); }); natural_gen().test_properties(|n| { assert_eq!(n.index_of_next_false_bit(0), (!n).trailing_zeros()); }); unsigned_gen().test_properties(|u| { assert_eq!(Natural::ZERO.index_of_next_false_bit(u), Some(u)); }); unsigned_pair_gen_var_2::().test_properties(|(u, index)| { assert_eq!( Natural::from(u).index_of_next_false_bit(index), u.index_of_next_false_bit(index) ); }); } ================================================ FILE: malachite-nz/tests/natural/logic/index_of_next_true_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::{BitAccess, BitScan, SignificantBits}; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_gen, unsigned_pair_gen_var_2, unsigned_vec_unsigned_pair_gen_var_16, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_scan::limbs_index_of_next_true_bit; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_unsigned_pair_gen_var_4}; use malachite_nz::test_util::natural::logic::index_of_next_true_bit::*; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_index_of_next_true_bit() { let test = |xs, u, out| { assert_eq!(limbs_index_of_next_true_bit(xs, u), out); }; test(&[], 0, None); test(&[], 100, None); test(&[0], 0, None); test(&[0], 100, None); test(&[0b100], 0, Some(2)); test(&[0b100], 1, Some(2)); test(&[0b100], 2, Some(2)); test(&[0b100], 3, None); test(&[0, 0b1011], 0, Some(32)); test(&[0, 0b1011], 20, Some(32)); test(&[0, 0b1011], 31, Some(32)); test(&[0, 0b1011], 32, Some(32)); test(&[0, 0b1011], 33, Some(33)); test(&[0, 0b1011], 34, Some(35)); test(&[0, 0b1011], 35, Some(35)); test(&[0, 0b1011], 36, None); test(&[0, 0b1011], 100, None); test(&[0, 0b1011, 0xfffffff, 0, 1], 91, Some(91)); test(&[0, 0b1011, 0xfffffff, 0, 1], 92, Some(128)); } #[test] fn test_index_of_next_true_bit() { let test = |n, u, out| { assert_eq!(Natural::from_str(n).unwrap().index_of_next_true_bit(u), out); assert_eq!( natural_index_of_next_true_bit_alt(&Natural::from_str(n).unwrap(), u), out ); assert_eq!( rug::Integer::from_str(n) .unwrap() .find_one(u32::exact_from(u)) .map(u64::from), out ); }; test("0", 0, None); test("0", 100, None); test("47244640256", 0, Some(32)); test("47244640256", 20, Some(32)); test("47244640256", 31, Some(32)); test("47244640256", 32, Some(32)); test("47244640256", 33, Some(33)); test("47244640256", 34, Some(35)); test("47244640256", 35, Some(35)); test("47244640256", 36, None); test("47244640256", 100, None); test("340282366925890223602069384504899796992", 91, Some(91)); test("340282366925890223602069384504899796992", 92, Some(128)); } #[test] fn limbs_index_of_next_true_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config(&config, |(xs, u)| { assert_eq!( limbs_index_of_next_true_bit(&xs, u), Natural::from_owned_limbs_asc(xs).index_of_next_true_bit(u) ); }); } #[test] fn index_of_next_true_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, u)| { let result = n.index_of_next_true_bit(u); assert_eq!(result, natural_index_of_next_true_bit_alt(&n, u)); assert_eq!( rug::Integer::from(&n) .find_one(u32::exact_from(u)) .map(u64::from), result ); assert_eq!(result.is_some(), u < n.significant_bits()); if let Some(result) = result { assert!(result >= u); assert!(n.get_bit(result)); assert_eq!(result == u, n.get_bit(u)); } assert_eq!((!n).index_of_next_false_bit(u), result); }); natural_gen().test_properties(|n| { assert_eq!(n.index_of_next_true_bit(0), n.trailing_zeros()); }); unsigned_gen().test_properties(|u| { assert_eq!(Natural::ZERO.index_of_next_true_bit(u), None); }); unsigned_pair_gen_var_2::().test_properties(|(u, index)| { assert_eq!( Natural::from(u).index_of_next_true_bit(index), u.index_of_next_true_bit(index) ); }); } ================================================ FILE: malachite-nz/tests/natural/logic/limb_count.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::generators::unsigned_gen; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; #[cfg(feature = "32_bit_limbs")] use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limb_count() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().limb_count(), out); }; test("0", 0); test("123", 1); test("1000000000000", 2); test("4294967295", 1); test("4294967296", 2); test("18446744073709551615", 2); test("18446744073709551616", 3); } #[test] fn limb_count_properties() { natural_gen().test_properties(|x| { let n = x.limb_count(); assert_eq!(x <= Limb::MAX, n <= 1); if x != 0 { assert!(Natural::power_of_2((n - 1) << Limb::LOG_WIDTH) <= x); assert!(x < Natural::power_of_2(n << Limb::LOG_WIDTH)); } }); unsigned_gen::().test_properties(|u| { assert!(Natural::from(u).limb_count() <= 1); }); } ================================================ FILE: malachite-nz/tests/natural/logic/low_mask.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; use malachite_base::num::logic::traits::{BitScan, CountOnes, LowMask}; use malachite_base::test_util::generators::{unsigned_gen_var_5, unsigned_gen_var_9}; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::low_mask::limbs_low_mask; use malachite_nz::platform::Limb; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_low_mask() { let test = |bits, out: &[Limb]| assert_eq!(limbs_low_mask(bits), out); test(0, &[]); test(1, &[1]); test(2, &[3]); test(3, &[7]); test(32, &[u32::MAX]); test(100, &[u32::MAX, u32::MAX, u32::MAX, 15]); } #[test] fn test_low_mask() { let test = |bits, out| assert_eq!(Natural::low_mask(bits).to_string(), out); test(0, "0"); test(1, "1"); test(2, "3"); test(3, "7"); test(32, "4294967295"); test(100, "1267650600228229401496703205375"); } #[test] fn limbs_low_mask_properties() { unsigned_gen_var_5().test_properties(|bits| { assert_eq!( Natural::from_owned_limbs_asc(limbs_low_mask(bits)), Natural::low_mask(bits) ); }); } #[test] fn low_mask_properties() { unsigned_gen_var_5().test_properties(|bits| { let n = Natural::low_mask(bits); assert!(n.is_valid()); assert_eq!(n, Natural::power_of_2(bits) - Natural::ONE); assert_eq!(n.count_ones(), bits); assert_eq!(n.index_of_next_false_bit(0), Some(bits)); }); unsigned_gen_var_9::().test_properties(|bits| { assert_eq!(Limb::low_mask(bits), Natural::low_mask(bits)); }); } ================================================ FILE: malachite-nz/tests/natural/logic/not.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::One; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{unsigned_vec_gen, unsigned_vec_pair_gen_var_1}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::not::{limbs_not, limbs_not_in_place, limbs_not_to_out}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_not_and_limbs_not_in_place() { let test = |xs: &[Limb], out: &[Limb]| { assert_eq!(limbs_not(xs), out); let mut mut_xs = xs.to_vec(); limbs_not_in_place(&mut mut_xs); assert_eq!(mut_xs, out); }; test(&[], &[]); test(&[0, 1, 2], &[u32::MAX, u32::MAX - 1, u32::MAX - 2]); test(&[u32::MAX, u32::MAX - 1, u32::MAX - 2], &[0, 1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_not_to_out() { let test = |xs: &[Limb], out_before: &[Limb], out_after: &[Limb]| { let mut mut_out = out_before.to_vec(); limbs_not_to_out(&mut mut_out, xs); assert_eq!(mut_out, out_after); }; test(&[], &[], &[]); test(&[0x11111111], &[5], &[0xeeeeeeee]); test( &[0xffff0000, 0xf0f0f0f0], &[0, 1, 2], &[0xffff, 0xf0f0f0f, 2], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_not_to_out_fail() { let mut out = vec![1, 2]; limbs_not_to_out(&mut out, &[1, 2, 3]); } #[test] fn test_not() { let test = |s, out| { let not = !Natural::from_str(s).unwrap(); assert!(not.is_valid()); assert_eq!(not.to_string(), out); let not = !(&Natural::from_str(s).unwrap()); assert!(not.is_valid()); assert_eq!(not.to_string(), out); assert_eq!((!rug::Integer::from_str(s).unwrap()).to_string(), out); }; test("0", "-1"); test("123", "-124"); test("1000000000000", "-1000000000001"); test("2147483647", "-2147483648"); } #[test] fn limbs_not_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |xs| { let not_xs = limbs_not(&xs); assert_eq!(limbs_not(¬_xs), xs); }); } #[test] fn limbs_not_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_1().test_properties_with_config(&config, |(mut out, xs)| { let out_old = out.clone(); limbs_not_to_out(&mut out, &xs); limbs_not_in_place(&mut out[..xs.len()]); assert_eq!(&out[..xs.len()], xs); assert_eq!(&out[xs.len()..], &out_old[xs.len()..]); }); } #[test] fn limbs_not_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen().test_properties_with_config(&config, |mut xs| { let xs_old = xs.clone(); limbs_not_in_place(&mut xs); limbs_not_in_place(&mut xs); assert_eq!(xs, xs_old); }); } #[test] fn not_properties() { natural_gen().test_properties(|x| { let not = !x.clone(); assert!(not.is_valid()); let rug_not = !rug::Integer::from(&x); assert_eq!(Integer::from(&rug_not), not); let not_alt = !&x; assert!(not_alt.is_valid()); assert_eq!(not_alt, not); assert!(not < 0); assert_eq!(not, -(&x + Natural::ONE)); assert_ne!(not, x); assert_eq!(!not, x); }); } ================================================ FILE: malachite-nz/tests/natural/logic/or.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::CountOnes; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::or::{ limbs_or, limbs_or_in_place_either, limbs_or_in_place_left, limbs_or_limb, limbs_or_limb_in_place, limbs_or_limb_to_out, limbs_or_same_length, limbs_or_same_length_in_place_left, limbs_or_same_length_to_out, limbs_or_to_out, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use malachite_nz::test_util::natural::logic::or::{natural_or_alt_1, natural_or_alt_2}; use num::BigUint; use rug; use std::cmp::max; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_limb_and_limbs_or_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_or_limb(xs, y), out); let mut xs = xs.to_vec(); limbs_or_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 2, &[6, 7]); test(&[100, 101, 102], 10, &[110, 101, 102]); test(&[123, 456], 789, &[895, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_limb_fail() { limbs_or_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_limb_in_place_fail() { limbs_or_limb_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_or_limb_to_out(&mut out, xs, y); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[6, 7], 2, &[6, 7, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, &[110, 101, 102, 10], ); test(&[10, 10, 10, 10], &[123, 456], 789, &[895, 456, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_limb_to_out_fail_1() { limbs_or_limb_to_out(&mut [], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_limb_to_out_fail_2() { limbs_or_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_same_length_and_limbs_or_same_length_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_or_same_length(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_or_same_length_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[], &[], vec![]); test(&[2], &[3], vec![3]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 3, 3]); test(&[6, 7], &[1, 2], vec![7, 7]); test(&[100, 101, 102], &[102, 101, 100], vec![102, 101, 102]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_same_length_fail_1() { limbs_or_same_length(&[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_same_length_in_place_left_fail() { let mut out = vec![6, 7]; limbs_or_same_length_in_place_left(&mut out, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or() { let test = |xs, ys, out| { assert_eq!(limbs_or(xs, ys), out); }; test(&[], &[], vec![]); test(&[2], &[3], vec![3]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 3, 3]); test(&[6, 7], &[1, 2, 3], vec![7, 7, 3]); test(&[1, 2, 3], &[6, 7], vec![7, 7, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![102, 101, 102]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_same_length_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_or_same_length_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![1, 3, 3, 5]); test(&[6, 7], &[1, 2], &[0, 0], vec![7, 7]); test(&[6, 7], &[1, 2], &[10, 10, 10, 10], vec![7, 7, 10, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![102, 101, 102, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_same_length_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_or_same_length_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_same_length_to_out_fail_2() { let mut out = vec![10]; limbs_or_same_length_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_or_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![1, 3, 3, 5]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], vec![7, 7, 3, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], vec![7, 7, 3, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![102, 101, 102, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_or_to_out_fail() { let mut out = vec![10, 10]; limbs_or_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_in_place_left() { let test = |xs_before: &[Limb], ys, xs_after| { let mut xs = xs_before.to_vec(); limbs_or_in_place_left(&mut xs, ys); assert_eq!(xs, xs_after); }; test(&[], &[], vec![]); test(&[6, 7], &[1, 2], vec![7, 7]); test(&[6, 7], &[1, 2, 3], vec![7, 7, 3]); test(&[1, 2, 3], &[6, 7], vec![7, 7, 3]); test(&[], &[1, 2, 3], vec![1, 2, 3]); test(&[1, 2, 3], &[], vec![1, 2, 3]); test(&[1, 1, 1], &[1, 2, 3], vec![1, 3, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![102, 101, 102]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_or_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], right, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_or_in_place_either(&mut xs, &mut ys), right); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![], vec![]); test(&[6, 7], &[1, 2], false, vec![7, 7], vec![1, 2]); test(&[6, 7], &[1, 2, 3], true, vec![6, 7], vec![7, 7, 3]); test(&[1, 2, 3], &[6, 7], false, vec![7, 7, 3], vec![6, 7]); test(&[], &[1, 2, 3], true, vec![], vec![1, 2, 3]); test(&[1, 2, 3], &[], false, vec![1, 2, 3], vec![]); test(&[1, 1, 1], &[1, 2, 3], false, vec![1, 3, 3], vec![1, 2, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![102, 101, 102], vec![102, 101, 100], ); } #[test] fn test_or() { let test = |u, v, out| { let mut n = Natural::from_str(u).unwrap(); n |= Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = Natural::from_str(u).unwrap(); n |= &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() | Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() | Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() | &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() | &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!( natural_or_alt_1( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); assert_eq!( natural_or_alt_2( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); let n = BigUint::from_str(u).unwrap() | BigUint::from_str(v).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() | rug::Integer::from_str(v).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "507"); test("999999999999", "123", "999999999999"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("1000000000001", "123", "1000000000123"); test("12345678987654321", "456", "12345678987654649"); test("12345678987654321", "987654321", "12345679395421361"); test("1000000000000", "999999999999", "1000000004095"); test("12345678987654321", "314159265358979", "12347506587071667"); } #[test] fn limbs_or_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_or_limb(&xs, y)), Natural::from_owned_limbs_asc(xs) | Natural::from(y) ); }); } #[test] fn limbs_or_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_or_limb_to_out(&mut out, &xs, y); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) | Natural::from(y) ); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_or_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_or_limb_in_place(&mut xs, y); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(old_xs) | Natural::from(y) ); }); } fn limbs_or_helper(f: &mut dyn FnMut(&[Limb], &[Limb]) -> Vec, xs: Vec, ys: Vec) { assert_eq!( Natural::from_owned_limbs_asc(f(&xs, &ys)), Natural::from_owned_limbs_asc(xs) | Natural::from_owned_limbs_asc(ys) ); } #[test] fn limbs_or_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, ys)| { limbs_or_helper(&mut limbs_or_same_length, xs, ys); }); } #[test] fn limbs_or_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(xs, ys)| { limbs_or_helper(&mut limbs_or, xs, ys); }); } #[test] fn limbs_or_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_31().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_or_same_length_to_out(&mut out, &xs, &ys); let len = ys.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) | Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_or_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_32().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_or_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) | Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_or_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_or_same_length_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) | Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_or_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_or_in_place_left(&mut xs, &ys); let n = Natural::from_owned_limbs_asc(xs_old) | Natural::from_owned_limbs_asc(ys); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }); } #[test] fn limbs_or_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_or_in_place_either(&mut xs, &mut ys); let n = Natural::from_limbs_asc(&xs_old) | Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn or_properties() { natural_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() | y.clone(); let result_val_ref = x.clone() | &y; let result_ref_val = &x | y.clone(); let result = &x | &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x |= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x |= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x |= rug::Integer::from(&y); assert_eq!(Natural::exact_from(&mut_x), result); assert_eq!( Natural::from(&(BigUint::from(&x) | BigUint::from(&y))), result ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) | rug::Integer::from(&y))), result ); assert_eq!(natural_or_alt_1(&x, &y), result); assert_eq!(natural_or_alt_2(&x, &y), result); assert_eq!(&y | &x, result); assert_eq!(&result | &x, result); assert_eq!(&result | &y, result); assert!(result >= x); assert!(result >= y); let ones = result.count_ones(); assert!(ones >= x.count_ones()); assert!(ones >= y.count_ones()); }); natural_gen().test_properties(|x| { assert_eq!(&x | Natural::ZERO, x); assert_eq!(Natural::ZERO | &x, x); assert_eq!(&x | &x, x); }); natural_triple_gen().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x | y) | z, x | (y | z)); assert_eq!(x & (y | z), (x & y) | (x & z)); assert_eq!((x & y) | z, (x | z) & (y | z)); assert_eq!(x | (y & z), (x | y) & (x | z)); assert_eq!((x | y) & z, (x & z) | (y & z)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) | Natural::from(y), x | y); }); } ================================================ FILE: malachite-nz/tests/natural/logic/set_bit.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::BitAccess; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_vec_unsigned_pair_gen_var_16, unsigned_vec_unsigned_pair_gen_var_17, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::bit_access::{limbs_slice_set_bit, limbs_vec_set_bit}; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_4; use malachite_nz::test_util::natural::logic::set_bit::num_set_bit; use num::BigUint; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_slice_set_bit() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_slice_set_bit(&mut mut_xs, index); assert_eq!(mut_xs, out); }; test(&[0, 1], 0, &[1, 1]); test(&[1, 1], 0, &[1, 1]); test(&[1, 1], 1, &[3, 1]); test(&[3, 1], 33, &[3, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_slice_set_bit_fail() { let mut mut_xs = vec![1u32, 2, 3]; limbs_slice_set_bit(&mut mut_xs, 100); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_vec_set_bit() { let test = |xs: &[Limb], index: u64, out: &[Limb]| { let mut mut_xs = xs.to_vec(); limbs_vec_set_bit(&mut mut_xs, index); assert_eq!(mut_xs, out); }; test(&[0, 1], 0, &[1, 1]); test(&[1, 1], 0, &[1, 1]); test(&[1, 1], 1, &[3, 1]); test(&[3, 1], 33, &[3, 3]); test(&[3, 3], 100, &[3, 3, 0, 16]); test(&[3, 3], 128, &[3, 3, 0, 0, 1]); test(&[], 32, &[0, 1]); } #[test] fn test_set_bit() { let test = |u, index, out| { let mut n = Natural::from_str(u).unwrap(); n.set_bit(index); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = BigUint::from_str(u).unwrap(); num_set_bit(&mut n, index); assert_eq!(n.to_string(), out); let mut n = rug::Integer::from_str(u).unwrap(); n.set_bit(u32::exact_from(index), true); assert_eq!(n.to_string(), out); }; test("0", 10, "1024"); test("100", 0, "101"); test("1000000000000", 10, "1000000001024"); test("1000000000000", 100, "1267650600228229402496703205376"); test("5", 100, "1267650600228229401496703205381"); } #[test] fn limbs_slice_set_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_17().test_properties_with_config( &config, |(mut xs, index)| { let mut n = Natural::from_limbs_asc(&xs); limbs_slice_set_bit(&mut xs, index); n.set_bit(index); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn limbs_vec_set_bit_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_16().test_properties_with_config( &config, |(mut xs, index)| { let mut n = Natural::from_limbs_asc(&xs); limbs_vec_set_bit(&mut xs, index); n.set_bit(index); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }, ); } #[test] fn natural_set_bit_properties() { natural_unsigned_pair_gen_var_4().test_properties(|(n, index)| { let mut mut_n = n.clone(); mut_n.set_bit(index); assert!(mut_n.is_valid()); let result = mut_n; let mut mut_n = n.clone(); mut_n.assign_bit(index, true); assert_eq!(mut_n, result); let mut num_n = BigUint::from(&n); num_set_bit(&mut num_n, index); assert_eq!(Natural::from(&num_n), result); let mut rug_n = rug::Integer::from(&n); rug_n.set_bit(u32::exact_from(index), true); assert_eq!(Natural::exact_from(&rug_n), result); assert_eq!(&n | Natural::power_of_2(index), result); assert_ne!(result, 0); assert!(result >= n); if n.get_bit(index) { assert_eq!(result, n); } else { assert_ne!(result, n); let mut mut_result = result; mut_result.clear_bit(index); assert_eq!(mut_result, n); } }); } ================================================ FILE: malachite-nz/tests/natural/logic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::WrappingFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen_var_1; use malachite_nz::natural::Natural; use malachite_nz::natural::arithmetic::log_base_2::limbs_floor_log_base_2; use malachite_nz::natural::logic::significant_bits::limbs_significant_bits; use malachite_nz::platform::Limb; use num::BigUint; use rug; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_significant_bits() { let test = |xs, out| { assert_eq!(limbs_significant_bits::(xs), out); }; test(&[0b1], 1); test(&[0b10], 2); test(&[0b11], 2); test(&[0b100], 3); test(&[0, 0b1], 33); test(&[0, 0b1101], 36); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_significant_bits_fail() { limbs_significant_bits::(&[]); } #[test] fn test_significant_bits() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().significant_bits(), out); assert_eq!( u64::wrapping_from(BigUint::from_str(n).unwrap().bits()), out ); assert_eq!( u64::from(rug::Integer::from_str(n).unwrap().significant_bits()), out ); }; test("0", 0); test("100", 7); test("1000000000000", 40); test("4294967295", 32); test("4294967296", 33); test("18446744073709551615", 64); test("18446744073709551616", 65); } #[test] fn limbs_significant_bits_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_1().test_properties_with_config(&config, |xs| { let significant_bits = limbs_significant_bits(&xs); assert_eq!(xs.len() == 1, significant_bits <= Limb::WIDTH); assert_eq!(significant_bits, limbs_floor_log_base_2(&xs) + 1); assert_eq!( significant_bits, Natural::from_owned_limbs_asc(xs).significant_bits() ); }); } ================================================ FILE: malachite-nz/tests/natural/logic/to_bits.rs ================================================ // Copyright © 2026 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::num::logic::traits::{BitConvertible, BitIterable}; use malachite_base::test_util::generators::unsigned_gen; use malachite_base::test_util::num::logic::bit_convertible::{to_bits_asc_alt, to_bits_desc_alt}; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::to_bits::{to_bits_asc_naive, to_bits_desc_naive}; use std::str::FromStr; #[test] fn test_to_bits_asc() { let test = |n, out| { let n = Natural::from_str(n).unwrap(); assert_eq!(n.bits().collect_vec(), out); assert_eq!(n.to_bits_asc(), out); assert_eq!(to_bits_asc_naive(&n), out); assert_eq!(to_bits_asc_alt(&n), out); }; test("0", vec![]); test("1", vec![true]); test("6", vec![false, true, true]); test("105", vec![true, false, false, true, false, true, true]); test( "1000000000000", vec![ false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, true, true, false, false, false, true, false, true, true, true, ], ); test( "4294967295", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "4294967296", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); test( "18446744073709551615", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "18446744073709551616", vec![ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, ], ); } #[test] fn test_to_bits_desc() { let test = |n, out| { let n = Natural::from_str(n).unwrap(); assert_eq!(n.bits().rev().collect_vec(), out); assert_eq!(n.to_bits_desc(), out); assert_eq!(to_bits_desc_naive(&n), out); assert_eq!(to_bits_desc_alt(&n), out); }; test("0", vec![]); test("1", vec![true]); test("6", vec![true, true, false]); test("105", vec![true, true, false, true, false, false, true]); test( "1000000000000", vec![ true, true, true, false, true, false, false, false, true, true, false, true, false, true, false, false, true, false, true, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "4294967295", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "4294967296", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); test( "18446744073709551615", vec![ true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ], ); test( "18446744073709551616", vec![ true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, ], ); } #[test] fn to_bits_asc_properties() { natural_gen().test_properties(|x| { let bits = x.to_bits_asc(); assert_eq!(to_bits_asc_naive(&x), bits); assert_eq!(to_bits_asc_alt(&x), bits); assert_eq!(x.bits().collect_vec(), bits); assert_eq!(Natural::from_bits_asc(bits.iter().copied()), x); if x != 0 { assert_eq!(*bits.last().unwrap(), true); } }); unsigned_gen::().test_properties(|u| { assert_eq!(u.to_bits_asc(), Natural::from(u).to_bits_asc()); }); } #[test] fn to_bits_desc_properties() { natural_gen().test_properties(|x| { let bits = x.to_bits_desc(); assert_eq!(to_bits_desc_naive(&x), bits); assert_eq!(to_bits_desc_alt(&x), bits); assert_eq!(x.bits().rev().collect_vec(), bits); assert_eq!(Natural::from_bits_desc(bits.iter().copied()), x); if x != 0 { assert_eq!(bits[0], true); } }); unsigned_gen::().test_properties(|u| { assert_eq!(u.to_bits_desc(), Natural::from(u).to_bits_desc()); }); } ================================================ FILE: malachite-nz/tests/natural/logic/trailing_zeros.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::unsigned_vec_gen_var_2; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::trailing_zeros::limbs_trailing_zeros; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::natural_gen; use malachite_nz::test_util::natural::logic::trailing_zeros::natural_trailing_zeros_alt; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_trailing_zeros() { let test = |xs, out| { assert_eq!(limbs_trailing_zeros(xs), out); }; test(&[4], 2); test(&[0, 4], 34); test(&[1, 2, 3], 0); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_trailing_zeros_fail_1() { limbs_trailing_zeros(&[]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_trailing_zeros_fail_2() { limbs_trailing_zeros(&[0, 0, 0]); } #[test] fn test_trailing_zeros() { let test = |n, out| { assert_eq!(Natural::from_str(n).unwrap().trailing_zeros(), out); assert_eq!( natural_trailing_zeros_alt(&Natural::from_str(n).unwrap()), out ); }; test("0", None); test("123", Some(0)); test("1000000000000", Some(12)); test("4294967295", Some(0)); test("4294967296", Some(32)); test("18446744073709551615", Some(0)); test("18446744073709551616", Some(64)); } #[test] fn limbs_trailing_zeros_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_gen_var_2().test_properties_with_config(&config, |xs| { assert_eq!( Some(limbs_trailing_zeros(&xs)), Natural::from_owned_limbs_asc(xs).trailing_zeros() ); }); } #[allow(clippy::cmp_owned, clippy::useless_conversion)] #[test] fn trailing_zeros_properties() { natural_gen().test_properties(|x| { let trailing_zeros = x.trailing_zeros(); assert_eq!(natural_trailing_zeros_alt(&x), trailing_zeros); assert_eq!(trailing_zeros.is_none(), x == 0); if x != 0 { let trailing_zeros = trailing_zeros.unwrap(); if trailing_zeros <= u64::from(Limb::MAX) { assert!((&x >> trailing_zeros).odd()); assert_eq!(&x >> trailing_zeros << trailing_zeros, x); } } }); } ================================================ FILE: malachite-nz/tests/natural/logic/xor.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::{ unsigned_pair_gen_var_27, unsigned_vec_pair_gen, unsigned_vec_pair_gen_var_6, unsigned_vec_triple_gen_var_31, unsigned_vec_triple_gen_var_32, unsigned_vec_unsigned_pair_gen_var_15, unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4, }; use malachite_nz::natural::Natural; use malachite_nz::natural::logic::xor::{ limbs_xor, limbs_xor_in_place_either, limbs_xor_in_place_left, limbs_xor_limb, limbs_xor_limb_in_place, limbs_xor_limb_to_out, limbs_xor_same_length, limbs_xor_same_length_in_place_left, limbs_xor_same_length_to_out, limbs_xor_to_out, }; use malachite_nz::platform::Limb; use malachite_nz::test_util::generators::{natural_gen, natural_pair_gen, natural_triple_gen}; use malachite_nz::test_util::natural::logic::xor::{natural_xor_alt_1, natural_xor_alt_2}; use num::BigUint; use rug; use std::cmp::max; use std::str::FromStr; #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_limb_and_limbs_xor_limb_in_place() { let test = |xs: &[Limb], y: Limb, out: &[Limb]| { assert_eq!(limbs_xor_limb(xs, y), out); let mut xs = xs.to_vec(); limbs_xor_limb_in_place(&mut xs, y); assert_eq!(xs, out); }; test(&[6, 7], 2, &[4, 7]); test(&[100, 101, 102], 10, &[110, 101, 102]); test(&[123, 456], 789, &[878, 456]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_limb_fail() { limbs_xor_limb(&[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_limb_in_place_fail() { limbs_xor_limb_in_place(&mut [], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_limb_to_out() { let test = |out_before: &[Limb], xs: &[Limb], y: Limb, out_after: &[Limb]| { let mut out = out_before.to_vec(); limbs_xor_limb_to_out(&mut out, xs, y); assert_eq!(out, out_after); }; test(&[10, 10, 10, 10], &[6, 7], 2, &[4, 7, 10, 10]); test( &[10, 10, 10, 10], &[100, 101, 102], 10, &[110, 101, 102, 10], ); test(&[10, 10, 10, 10], &[123, 456], 789, &[878, 456, 10, 10]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_limb_to_out_fail_1() { limbs_xor_limb_to_out(&mut [], &[], 10); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_limb_to_out_fail_2() { limbs_xor_limb_to_out(&mut [10], &[10, 10], 10); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_same_length_and_limbs_xor_same_length_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_xor_same_length(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_xor_same_length_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[], &[], vec![]); test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![0, 3, 2]); test(&[6, 7], &[1, 2], vec![7, 5]); test(&[100, 101, 102], &[102, 101, 100], vec![2, 0, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_same_length_fail_1() { limbs_xor_same_length(&[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_same_length_in_place_left_fail() { let mut out = vec![6, 7]; limbs_xor_same_length_in_place_left(&mut out, &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_and_limbs_xor_in_place_left() { let test = |xs_before, ys, out| { assert_eq!(limbs_xor(xs_before, ys), out); let mut xs = xs_before.to_vec(); limbs_xor_in_place_left(&mut xs, ys); assert_eq!(xs, out); }; test(&[], &[], vec![]); test(&[2], &[3], vec![1]); test(&[1, 1, 1], &[1, 2, 3], vec![0, 3, 2]); test(&[6, 7], &[1, 2, 3], vec![7, 5, 3]); test(&[1, 2, 3], &[6, 7], vec![7, 5, 3]); test(&[100, 101, 102], &[102, 101, 100], vec![2, 0, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_same_length_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_xor_same_length_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![0, 3, 2, 5]); test(&[6, 7], &[1, 2], &[0, 0], vec![7, 5]); test(&[6, 7], &[1, 2], &[10, 10, 10, 10], vec![7, 5, 10, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![2, 0, 2, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_same_length_to_out_fail_1() { let mut out = vec![10, 10, 10, 10]; limbs_xor_same_length_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_same_length_to_out_fail_2() { let mut out = vec![10]; limbs_xor_same_length_to_out(&mut out, &[6, 7], &[1, 2]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_to_out() { let test = |xs, ys, out_before: &[Limb], out_after| { let mut out = out_before.to_vec(); limbs_xor_to_out(&mut out, xs, ys); assert_eq!(out, out_after); }; test(&[], &[], &[0, 0], vec![0, 0]); test(&[1, 1, 1], &[1, 2, 3], &[5, 5, 5, 5], vec![0, 3, 2, 5]); test(&[6, 7], &[1, 2, 3], &[10, 10, 10, 10], vec![7, 5, 3, 10]); test(&[1, 2, 3], &[6, 7], &[10, 10, 10, 10], vec![7, 5, 3, 10]); test( &[100, 101, 102], &[102, 101, 100], &[10, 10, 10, 10], vec![2, 0, 2, 10], ); } #[cfg(feature = "32_bit_limbs")] #[test] #[should_panic] fn limbs_xor_to_out_fail() { let mut out = vec![10, 10]; limbs_xor_to_out(&mut out, &[6, 7], &[1, 2, 3]); } #[cfg(feature = "32_bit_limbs")] #[test] fn test_limbs_xor_in_place_either() { let test = |xs_before: &[Limb], ys_before: &[Limb], right, xs_after, ys_after| { let mut xs = xs_before.to_vec(); let mut ys = ys_before.to_vec(); assert_eq!(limbs_xor_in_place_either(&mut xs, &mut ys), right); assert_eq!(xs, xs_after); assert_eq!(ys, ys_after); }; test(&[], &[], false, vec![], vec![]); test(&[6, 7], &[1, 2], false, vec![7, 5], vec![1, 2]); test(&[6, 7], &[1, 2, 3], true, vec![6, 7], vec![7, 5, 3]); test(&[1, 2, 3], &[6, 7], false, vec![7, 5, 3], vec![6, 7]); test(&[], &[1, 2, 3], true, vec![], vec![1, 2, 3]); test(&[1, 2, 3], &[], false, vec![1, 2, 3], vec![]); test(&[1, 1, 1], &[1, 2, 3], false, vec![0, 3, 2], vec![1, 2, 3]); test( &[100, 101, 102], &[102, 101, 100], false, vec![2, 0, 2], vec![102, 101, 100], ); } #[test] fn test_xor() { let test = |u, v, out| { let mut n = Natural::from_str(u).unwrap(); n ^= Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = Natural::from_str(u).unwrap(); n ^= &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() ^ Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() ^ Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::from_str(u).unwrap() ^ &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &Natural::from_str(u).unwrap() ^ &Natural::from_str(v).unwrap(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!( natural_xor_alt_1( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); assert_eq!( natural_xor_alt_2( &Natural::from_str(u).unwrap(), &Natural::from_str(v).unwrap(), ) .to_string(), out ); let n = BigUint::from_str(u).unwrap() ^ BigUint::from_str(v).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Integer::from_str(u).unwrap() ^ rug::Integer::from_str(v).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "435"); test("1000000000000", "123", "1000000000123"); test("123", "1000000000000", "1000000000123"); test("1000000000001", "123", "1000000000122"); test("12345678987654321", "0", "12345678987654321"); test("12345678987654321", "456", "12345678987654521"); test("12345678987654321", "987654321", "12345678815534080"); test("1000000000000", "999999999999", "8191"); test("12345678987654321", "314159265358979", "12035174921130034"); } #[test] fn limbs_xor_limb_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(xs, y)| { assert_eq!( Natural::from_owned_limbs_asc(limbs_xor_limb(&xs, y)), Natural::from_owned_limbs_asc(xs) ^ Natural::from(y) ); }); } #[test] fn limbs_xor_limb_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_vec_unsigned_triple_gen_var_4().test_properties_with_config( &config, |(mut out, xs, y)| { let old_out = out.clone(); limbs_xor_limb_to_out(&mut out, &xs, y); let len = xs.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) ^ Natural::from(y) ); assert_eq!(&out[len..], &old_out[len..]); }, ); } #[test] fn limbs_xor_limb_in_place_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_unsigned_pair_gen_var_15().test_properties_with_config(&config, |(mut xs, y)| { let old_xs = xs.clone(); limbs_xor_limb_in_place(&mut xs, y); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(old_xs) ^ Natural::from(y) ); }); } fn limbs_xor_helper( f: &mut dyn FnMut(&[Limb], &[Limb]) -> Vec, xs: Vec, ys: Vec, ) { assert_eq!( Natural::from_owned_limbs_asc(f(&xs, &ys)), Natural::from_owned_limbs_asc(xs) ^ Natural::from_owned_limbs_asc(ys) ); } #[test] fn limbs_xor_same_length_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(xs, ys)| { limbs_xor_helper(&mut limbs_xor_same_length, xs, ys); }); } #[test] fn limbs_xor_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(xs, ys)| { limbs_xor_helper(&mut limbs_xor, xs, ys); }); } #[test] fn limbs_xor_same_length_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_31().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_xor_same_length_to_out(&mut out, &xs, &ys); let len = ys.len(); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) ^ Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_xor_to_out_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_triple_gen_var_32().test_properties_with_config(&config, |(mut out, xs, ys)| { let out_old = out.clone(); limbs_xor_to_out(&mut out, &xs, &ys); let len = max(xs.len(), ys.len()); assert_eq!( Natural::from_limbs_asc(&out[..len]), Natural::from_owned_limbs_asc(xs) ^ Natural::from_owned_limbs_asc(ys) ); assert_eq!(&out[len..], &out_old[len..]); }); } #[test] fn limbs_xor_same_length_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen_var_6().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_xor_same_length_in_place_left(&mut xs, &ys); assert_eq!( Natural::from_owned_limbs_asc(xs), Natural::from_owned_limbs_asc(xs_old) ^ Natural::from_owned_limbs_asc(ys) ); }); } #[test] fn limbs_xor_in_place_left_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, ys)| { let xs_old = xs.clone(); limbs_xor_in_place_left(&mut xs, &ys); let n = Natural::from_owned_limbs_asc(xs_old) ^ Natural::from_owned_limbs_asc(ys); assert_eq!(Natural::from_owned_limbs_asc(xs), n); }); } #[test] fn limbs_xor_in_place_either_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 32); config.insert("mean_stripe_n", 16 << Limb::LOG_WIDTH); unsigned_vec_pair_gen().test_properties_with_config(&config, |(mut xs, mut ys)| { let xs_old = xs.clone(); let ys_old = ys.clone(); let right = limbs_xor_in_place_either(&mut xs, &mut ys); let n = Natural::from_limbs_asc(&xs_old) ^ Natural::from_limbs_asc(&ys_old); if right { assert_eq!(xs, xs_old); assert_eq!(Natural::from_owned_limbs_asc(ys), n); } else { assert_eq!(Natural::from_owned_limbs_asc(xs), n); assert_eq!(ys, ys_old); } }); } #[allow(clippy::eq_op)] #[test] fn or_properties() { natural_pair_gen().test_properties(|(x, y)| { let result_val_val = x.clone() ^ y.clone(); let result_val_ref = x.clone() ^ &y; let result_ref_val = &x ^ y.clone(); let result = &x ^ &y; assert!(result_val_val.is_valid()); assert!(result_val_ref.is_valid()); assert!(result_ref_val.is_valid()); assert!(result.is_valid()); assert_eq!(result_val_val, result); assert_eq!(result_val_ref, result); assert_eq!(result_ref_val, result); let mut mut_x = x.clone(); mut_x ^= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, result); let mut mut_x = x.clone(); mut_x ^= &y; assert_eq!(mut_x, result); assert!(mut_x.is_valid()); let mut mut_x = rug::Integer::from(&x); mut_x ^= rug::Integer::from(&y); assert_eq!(Natural::exact_from(&mut_x), result); assert_eq!( Natural::from(&(BigUint::from(&x) ^ BigUint::from(&y))), result ); assert_eq!( Natural::exact_from(&(rug::Integer::from(&x) ^ rug::Integer::from(&y))), result ); assert_eq!(natural_xor_alt_1(&x, &y), result); assert_eq!(natural_xor_alt_2(&x, &y), result); assert_eq!(&y ^ &x, result); assert_eq!(&result ^ &x, y); assert_eq!(&result ^ y, x); }); natural_gen().test_properties(|x| { assert_eq!(&x ^ Natural::ZERO, x); assert_eq!(Natural::ZERO ^ &x, x); assert_eq!(&x ^ &x, 0); }); natural_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x ^ &y) ^ &z, x ^ (y ^ z)); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Natural::from(x) ^ Natural::from(y), x ^ y); }); } ================================================ FILE: malachite-nz/tests/natural/random/get_random_natural_less_than.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::random::get_random_natural_less_than; use std::str::FromStr; fn get_random_natural_less_than_helper(limit: &str, out: &str) { let mut xs = random_primitive_ints(EXAMPLE_SEED); let xs = (0..10) .map(|_| get_random_natural_less_than(&mut xs, &Natural::from_str(limit).unwrap())) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_less_than() { get_random_natural_less_than_helper("1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_random_natural_less_than_helper("10", "[1, 7, 5, 7, 9, 2, 8, 2, 4, 6]"); get_random_natural_less_than_helper("100", "[87, 93, 7, 84, 27, 46, 93, 22, 86, 1]"); get_random_natural_less_than_helper("1000", "[881, 87, 93, 629, 519, 626, 360, 242, 491, 84]"); get_random_natural_less_than_helper( "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000", "[6513696165206921204311261523739269601083760431420210295861564381205783648442563498105196\ 329975541617, \ 868400879467069938866982772480181142332366549281254507368280851531146621198387695461761814\ 2446877811, \ 454890116058063209121711848211479855802275293374032067837601343116564901989251772312271223\ 8643735453, \ 221953236727409585623978519825787712675415538807055958167887436471257145918881448806179877\ 2042912434, \ 156597062580980418852701766729202981599785596117178894442015894874216386954905163169649546\ 2984128417, \ 775809396529562140517641222093832263868653173407259880967133743504333426167140950839221651\ 5440206577, \ 194588045371630389938122892550032325836127322381120175893002672149553900804839171978848159\ 3900827375, \ 681710429818657256239982130308509711765427303233424706691965226432442255381734547395128615\ 696717955, \ 525885978270298534580002381561976404877189873292849476887431075456216366244793235854298324\ 5431956916, \ 314957843714266314102082575313210347468784454645937249947829551130804781109663224113983528\ 7147185026]", ); } #[test] #[should_panic] fn get_random_natural_less_than_fail() { get_random_natural_less_than(&mut random_primitive_ints(EXAMPLE_SEED), &Natural::ZERO); } ================================================ FILE: malachite-nz/tests/natural/random/get_random_natural_with_bits.rs ================================================ // Copyright © 2026 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::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_random_natural_with_bits; fn get_random_natural_with_bits_helper(bits: u64, out: &str) { let mut xs = random_primitive_ints(EXAMPLE_SEED); let xs = (0..10) .map(|_| get_random_natural_with_bits(&mut xs, bits)) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_with_bits() { get_random_natural_with_bits_helper(0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_random_natural_with_bits_helper(1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); get_random_natural_with_bits_helper(10, "[881, 599, 605, 629, 519, 1001, 626, 872, 754, 1003]"); get_random_natural_with_bits_helper( 100, "[976558340558744279591984426865, 1210743526759830339060468402269, \ 987622786528174742128034915847, 1028849241887437545987236408946, \ 636224214690002338734404794610, 1084022137993299669433275842644, \ 651260491393393331452592307118, 938596277659014096812502469654, \ 1027696177399334210658775892715, 1215526897097077179887043345523]", ); get_random_natural_with_bits_helper( 1000, "[9871555593311388583730668028572947972273370391584873166827867445956379776331862403614137\ 010240679811389700642404293916880391529744438580436267309669605743557526364970431150933385\ 398365619760568042866366891175418557263537757651023714048098525335447177149901286977666669\ 228734508013967448659203593727857, \ 791294226283400338116725266395415668811492351726967595517985462290683501988325067570154247\ 916466497696906715377685810324362572568643782805454526919199743597748426287793605950177843\ 400312249716517544116781742042345757038219051016833597591532327578014535369800683425719501\ 1222552384008059606354106024683, \ 603141122347678493875935496567523539943016200607299929590987513666029676151877700615600993\ 558206489004992870361727816768285331691513429048943961969079262017872532249009221429690429\ 173396464673970587747514162246269540847510994058348422653339211911977412158645139435582116\ 2135683154777550054864806973191, \ 918979157591718364955430394079794967293887473404422985188351315968507884008710649189160051\ 696207222829134675903387190115731463781015558345121417040971370267174581281652951730760301\ 188537459504910504772462880811654819707300024255167639013890736171444647445349859763886702\ 2577615653562903750479807977377, \ 647326991054871401446391652220147139977257585074930117822971968152242235080123828418477499\ 122643194996280709533149340353864776491291597713840972420179000074772311437377760180051433\ 385038047440481754027985595280436007381332471223783461841596113991149106848191431176197419\ 2844525526720830095389487497409, \ 949041077003843738114763478589507012307507968570578492234472107314902412716521187076156469\ 160317707751627684700609080913827492307622771744874629743335821135555462576657380263807543\ 487753886476772373626981873033661206968177922749550215130614548300918947578733522250796129\ 5744371969372939814739027796839, \ 989922815195092012407533508457902337326088523136116587955882587433938614841443439968917681\ 506531942296074930018264941258097700513177676253997511008000381073449050985414240650516825\ 818652374821129290720209582447241803904618161996066094314560522095909158341055892421259319\ 6555994763897951379745163707947, \ 560430875586881451021986079137268355719860392640168705312566874574524151511315309194440525\ 432541907755646531766496361640227195372967955930947529029583706599432734589617900554403438\ 972135775666804402920199247213229036374355559526777099281829864834361213138370127732279617\ 7830548383897263545487627313816, \ 607760857698629857675370920711285763610351243179869812617321508384537069997121877063755036\ 502176965392609298699890321897240768662430762687034745512362659852305512122877940314598630\ 179328920839572409651612938305899406030180626695355189902602551915007303361897784538043083\ 9825515983752933214916509907962, \ 104802773115609428879259254484528372112963320559423798212143117675970187076769475019659710\ 589902898294520178185617889833116138928807499798445230962192076044779146948376974924138017\ 275574706437699501177855375574899794972601656611168235082869924333910214914822287693744357\ 49828269999407972362285090280006]", ); } ================================================ FILE: malachite-nz/tests/natural/random/get_random_natural_with_up_to_bits.rs ================================================ // Copyright © 2026 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::num::random::random_primitive_ints; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_random_natural_with_up_to_bits; fn get_random_natural_with_up_to_bits_helper(bits: u64, out: &str) { let mut xs = random_primitive_ints(EXAMPLE_SEED); let xs = (0..10) .map(|_| get_random_natural_with_up_to_bits(&mut xs, bits)) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_random_natural_with_up_to_bits() { get_random_natural_with_up_to_bits_helper(0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_random_natural_with_up_to_bits_helper(1, "[1, 1, 1, 1, 1, 1, 0, 0, 0, 1]"); get_random_natural_with_up_to_bits_helper( 10, "[881, 87, 93, 629, 519, 1001, 626, 360, 242, 491]", ); get_random_natural_with_up_to_bits_helper( 100, "[976558340558744279591984426865, 576918226645715638312116799581, \ 987622786528174742128034915847, 395023941773322845238884806258, \ 636224214690002338734404794610, 450196837879184968684924239956, \ 17435191279278630704240704430, 938596277659014096812502469654, \ 1027696177399334210658775892715, 581701596982962479138691742835]", ); get_random_natural_with_up_to_bits_helper( 1000, "[4514012557380051978988542783272938919466346333057205129609115504104624520707181791148145\ 116162200520751727277816528182754455803315977010218275020882256456155559081083019035440674\ 861063088574997103889275814652181065472567123951639934465326552296915719864303048134395585\ 398519592187655255240600759693169, \ 791294226283400338116725266395415668811492351726967595517985462290683501988325067570154247\ 916466497696906715377685810324362572568643782805454526919199743597748426287793605950177843\ 400312249716517544116781742042345757038219051016833597591532327578014535369800683425719501\ 1222552384008059606354106024683, \ 603141122347678493875935496567523539943016200607299929590987513666029676151877700615600993\ 558206489004992870361727816768285331691513429048943961969079262017872532249009221429690429\ 173396464673970587747514162246269540847510994058348422653339211911977412158645139435582116\ 2135683154777550054864806973191, \ 918979157591718364955430394079794967293887473404422985188351315968507884008710649189160051\ 696207222829134675903387190115731463781015558345121417040971370267174581281652951730760301\ 188537459504910504772462880811654819707300024255167639013890736171444647445349859763886702\ 2577615653562903750479807977377, \ 111572687461737740972179127690146234696555179222163314101096773967066709517655767171878309\ 714795265932483373074372766941271203848445440692041743541444071334575583048636548630780379\ 654784928883387856318877942956686828284269101285405503564398810138003378288367546849089036\ 2629609700408636676786653462721, \ 413286773410710077640550954059506107026805562717811688512596913129726887154053125829557279\ 752469778687830348241832507501233919664776614723075400864600892395358734187916168714536489\ 757500767919678475917874220709912027871114552811172256853417244447773219018909637923687746\ 5529456143060746396136193762151, \ 454168511601958351933320983927901432045386117283349784234007393248763089278975378722318492\ 098684013232277593559488367845504127870331519232198282129265452333252322596673029101245772\ 088399256264035393011101930123492624807554792057688136037363218242763429781232008094150936\ 6341078937585757961142329673259, \ 560430875586881451021986079137268355719860392640168705312566874574524151511315309194440525\ 432541907755646531766496361640227195372967955930947529029583706599432734589617900554403438\ 972135775666804402920199247213229036374355559526777099281829864834361213138370127732279617\ 7830548383897263545487627313816, \ 720065541054961972011583961812848583296488373271030088954463141993615444346538158171558470\ 943290363288119622411137484846471960195846056652355166336277311121087837341367287653275764\ 490758022824785119425052859821502269331172567569772316254052480618615748020739002109347009\ 610600157440739796313675873274, \ 512273427562960628318380020315282815848930799741471178399555982574526345205226688949997916\ 491181053881404445397402324918567816645228840962653080743185831707594741095028537692109119\ 025493945819901114069446103425248770628953196173304392551501939485956420588398992610335191\ 9613354173095778943682256245318]", ); } ================================================ FILE: malachite-nz/tests/natural/random/get_striped_random_natural_from_inclusive_range.rs ================================================ // Copyright © 2026 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::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::random::get_striped_random_natural_from_inclusive_range; use std::str::FromStr; fn get_striped_random_natural_from_inclusive_range_helper( m_numerator: u64, m_denominator: u64, a: &str, b: &str, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let xs = (0..10) .map(|_| { get_striped_random_natural_from_inclusive_range( &mut bit_source, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_natural_from_inclusive_range() { get_striped_random_natural_from_inclusive_range_helper( 2, 1, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_natural_from_inclusive_range_helper( 2, 1, "1950", "2023", "[1950, 1971, 1990, 1962, 2018, 1972, 1952, 1999, 1989, 1987]", ); get_striped_random_natural_from_inclusive_range_helper( 2, 1, "1000000", "2000000", "[1002694, 1403247, 1036052, 1001215, 1170335, 1510298, 1661478, 1012673, 1005113, \ 1014065]", ); get_striped_random_natural_from_inclusive_range_helper( 10, 1, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_natural_from_inclusive_range_helper( 10, 1, "1950", "2023", "[1950, 1951, 1983, 2016, 1950, 2020, 2016, 1951, 1950, 1983]", ); get_striped_random_natural_from_inclusive_range_helper( 10, 1, "1000000", "2000000", "[1001471, 1056767, 1032199, 1000432, 1998848, 1040384, 1000000, 1574911, 1981967, \ 1048574]", ); get_striped_random_natural_from_inclusive_range_helper( 11, 10, "0", "0", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_natural_from_inclusive_range_helper( 11, 10, "1950", "2023", "[1962, 1962, 1972, 2019, 2019, 1962, 1962, 1986, 2005, 2005]", ); get_striped_random_natural_from_inclusive_range_helper( 11, 10, "1000000", "2000000", "[1004885, 1718613, 1027925, 1004874, 1485482, 1397329, 1741994, 1011029, 1004885, \ 1010346]", ); } #[test] #[should_panic] fn get_striped_random_natural_from_inclusive_range_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); get_striped_random_natural_from_inclusive_range( &mut bit_source, Natural::from(10u32), Natural::from(9u32), ); } ================================================ FILE: malachite-nz/tests/natural/random/get_striped_random_natural_from_range.rs ================================================ // Copyright © 2026 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::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::natural::random::get_striped_random_natural_from_range; use std::str::FromStr; fn get_striped_random_natural_from_range_helper( m_numerator: u64, m_denominator: u64, a: &str, b: &str, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let xs = (0..10) .map(|_| { get_striped_random_natural_from_range( &mut bit_source, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), ) }) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_natural_from_range() { get_striped_random_natural_from_range_helper(2, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_from_range_helper( 2, 1, "1950", "2024", "[1950, 1971, 1990, 1962, 2018, 1972, 1952, 1999, 1989, 1987]", ); get_striped_random_natural_from_range_helper( 2, 1, "1000000", "2000001", "[1002694, 1403247, 1036052, 1001215, 1170335, 1510298, 1661478, 1012673, 1005113, \ 1014065]", ); get_striped_random_natural_from_range_helper(10, 1, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_from_range_helper( 10, 1, "1950", "2024", "[1950, 1951, 1983, 2016, 1950, 2020, 2016, 1951, 1950, 1983]", ); get_striped_random_natural_from_range_helper( 10, 1, "1000000", "2000001", "[1001471, 1056767, 1032199, 1000432, 1998848, 1040384, 1000000, 1574911, 1981967, \ 1048574]", ); get_striped_random_natural_from_range_helper( 11, 10, "0", "1", "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", ); get_striped_random_natural_from_range_helper( 11, 10, "1950", "2024", "[1962, 1962, 1972, 2019, 2019, 1962, 1962, 1986, 2005, 2005]", ); get_striped_random_natural_from_range_helper( 11, 10, "1000000", "2000001", "[1004885, 1718613, 1027925, 1004874, 1485482, 1397329, 1741994, 1011029, 1004885, \ 1010346]", ); } #[test] #[should_panic] fn get_striped_random_natural_from_range_fail_1() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); get_striped_random_natural_from_range( &mut bit_source, Natural::from(10u32), Natural::from(9u32), ); } #[test] #[should_panic] fn get_striped_random_natural_from_range_fail_2() { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, 2, 1); get_striped_random_natural_from_range( &mut bit_source, Natural::from(10u32), Natural::from(10u32), ); } ================================================ FILE: malachite-nz/tests/natural/random/get_striped_random_natural_with_bits.rs ================================================ // Copyright © 2026 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::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_striped_random_natural_with_bits; fn get_striped_random_natural_with_bits_helper( m_numerator: u64, m_denominator: u64, bits: u64, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let xs = (0..10) .map(|_| get_striped_random_natural_with_bits(&mut bit_source, bits)) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_natural_with_bits() { get_striped_random_natural_with_bits_helper(2, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_bits_helper(2, 1, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); get_striped_random_natural_with_bits_helper( 2, 1, 10, "[716, 684, 662, 763, 798, 829, 768, 732, 536, 541]", ); get_striped_random_natural_with_bits_helper( 2, 1, 100, "[756308944479610176770360563916, 1145718678910746691112769802930, \ 1080305256857112995037586132048, 807717805879357681845918965159, \ 1215845349850185248466264185684, 822948728534233460050112643373, \ 955700757257715004518140113132, 832461439248077413553063350320, \ 1242643020761038901934578711610, 1122137987246906014371413743505]", ); get_striped_random_natural_with_bits_helper( 2, 1, 1000, "[1066036401822586582060831035662706457005124173369385364089512753873668954854498653201330\ 529188610070039476426288535963559977582497470497937854727434805905648395790056513373361685\ 117044701404743375692128198904783759739184161371638993268438163708872889304697920949732034\ 4797581420099450165301088751016140, \ 987176835967471470631208736450711102640000526855618567465986968908194747303665548783151326\ 849739186186452340671673297796771266911335225612017707433164734645560965513055402080032340\ 135474058189238938067890211197448581037553663122597099692488328028757994359299305393973140\ 7925926109130072336312534438574, \ 568651645319898625478110927429560819026449278119016593712297801674333004668766652853597774\ 772681158919761337797730830161503881200296844963400983419113636067755214296565242049691883\ 922630951084279967424027354828765778295400023859140245298770234805718721051701730000306553\ 5144184078571910290480368694380, \ 758830907466434071959666860937945102677771418528458236060516770128040285772163826421306107\ 069853863334698116336945744601463639747199523669413845254638599625980012214050809846459478\ 559098934176586233093238956124608709775991202493060441152475782277782012828793855484827036\ 1411929636489612968071552336405, \ 980856434133966113634431860230323947967355946268495564634504680787571319483353753543014805\ 474807358240303253563585951883147532327134463459185707026951902911405729653418676374715955\ 691096425012748194433199980744016228705422729019166704577441683479974798193714636957924636\ 2973260186276362799319175133568, \ 894303548113446750904572507746592793549624231872528102587605556722756026081514290865978856\ 949605256419586901475129581474267478481820707346973965338715875069463779465480362052962715\ 102197582459759242950488814694110771040964546445427112279563255714907257699939184423978433\ 0215727680884042630165644025099, \ 974492070270890205196098593733513997055807419178419835560661240335358848519651158952303927\ 871434236017718573182013896425860901259995476236242988456734111274812403199906058941973460\ 877801690192132645453156214170274198928980236695132799825665804217976367252593838779965803\ 0607916391896384659714182950628, \ 645130850234339503642007350857138479917399859387095109454794616985938391311231126744661800\ 420543794746031491748493862132931262497139684250480230073784453843645088983023718012240528\ 683824553139343195888019854863909746543574579361265915812174560716242126991285521565613433\ 2466523138255580920562084028294, \ 639103284871251403821872209988025331131792409726095776075819070688817857426736537831222024\ 179652645603869247406404689998157064676469146016517502338483799149248172262554878327272758\ 174240821091933100132108595935722179262833993962469175972706639648644071967476854878243149\ 4649776909489103783746916780024, \ 104643900952018601215342460716610794174551332701220396118082370352258784597041601116915384\ 664642853384078500349464320717455867749180262488843336424123164153150026841959758704744253\ 756151269545080362145067323770739682710146919991724449298137503388491656477667755306189744\ 24803845757396271996047726290589]", ); get_striped_random_natural_with_bits_helper(10, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_bits_helper(10, 1, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); get_striped_random_natural_with_bits_helper( 10, 1, 10, "[1016, 992, 1016, 767, 512, 513, 1020, 512, 1016, 1023]", ); get_striped_random_natural_with_bits_helper( 10, 1, 100, "[950737912392312175425017102328, 1109194416875305772521657204608, \ 648685415698526143125877948414, 1248153346840921551430087606303, \ 831891172891058554467585867776, 1267650600228229401359297740927, \ 950739156735808420047682273024, 638776758039873373851420326912, \ 643690285327603686643074121664, 671543785829629858305590427647]", ); get_striped_random_natural_with_bits_helper( 10, 1, 1000, "[5358165738110281147468429156665582144998881353628318343872646956815751197999946897572878\ 278363096783827886911589242856640635533315179867213030979090927223140806482585564866175368\ 333598466336603271609976534104173527941609131651006242168470752742668268779440452153819210\ 944528718553525957103310205894648, \ 539935796843008525931501938016824825731989695976128079798746287896348626759778818662810517\ 524977343980885794548702209431866052161353917750190601629912511180434696813340457173208570\ 976449234006368601336057069020362424176301595236556802947569224730136326560449690301955186\ 3255474664584713584582999408640, \ 535754303694423899076935129343771055050259990680670440133208286589122737827790634967047773\ 700260648071343420497642383540669384404571214562700313160956733565914399913133443167360146\ 252087697860065532691284023259655546679447897828373290595492357586809871031621268591800199\ 5164641448720709752408544641022, \ 535815617678664673230583609293711626429039758128419938980167626717612472897746291934554185\ 557830869500024824265898785919682260921341384664997061547297321382527299885697935410512118\ 522746192907474498033052134885264654751340612094587360238549546738016850498598238219826282\ 5015681391047050153768125472767, \ 100656671761770967200809514408313411282491427879094391861152015262204431791194203727185921\ 026045038825035836776620646775627513583957795766207833861462739511509698818541011638004365\ 409989389341031372058994101918102834059849507520841606970888386863725907172131052360271284\ 55992101445905914436525739998208, \ 107149228544600635260212788419695526657434400429968676165634060825808436991969085650247279\ 650596133663598434482129668133099616635115467318010721467086518060004035373781135234642383\ 205702114144671525516391055691812453033688242812694582953965743513229924054172419365064495\ 42173396641692237011907449425727, \ 107150860693727448661794856915575585277857852731679120989819290845002348669070050613296455\ 734254692011706809018756806353158106462995138380031851002523766291502961737781576247555759\ 035185454502873048780305065230433793569807065690804749332353542464565681262222119583879742\ 48405282741635132994030678311166, \ 107150835221766756970390016554040088032382955997319930334779105385220088376881426554895494\ 540316762324972302835401791427607201669829855912974990784820455466307137336628823875387612\ 135057991945407277136587896193153151600433435164863822917290693842788118252951172684773421\ 70526384435574180443755489763328, \ 535754329539033410731721563380478204940555300525204412489285381291927939025074977709123312\ 566899344374925407384165980119188647505571183538659634788083559269291976584227032503722306\ 929007576563288991617997079930222315375169710335488132792623698751814518487754242895518611\ 5084271519939681346646991441912, \ 535882021406206416670177596158366769032342285663637541146888579315644330411450606808875554\ 132489833818740595777819456634963853487245325624796744100983558326561831449646070534648278\ 476260874658721825904285846269922085259057263667571525921657161024153045937468235049728709\ 2438657975290976181526386966515]", ); get_striped_random_natural_with_bits_helper(11, 10, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_bits_helper(11, 10, 1, "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); get_striped_random_natural_with_bits_helper( 11, 10, 10, "[682, 842, 668, 853, 862, 853, 850, 852, 682, 853]", ); get_striped_random_natural_with_bits_helper( 11, 10, 100, "[1063803140432100403291953916586, 739462850133133817539732346028, \ 1056478660679155688751767049562, 848401573590247656481079600469, \ 1056375500189999764883937602218, 1053067879147533365448711514965, \ 1056381847001601296578889995602, 1056377112103581910626871170386, \ 1056375600983290506811020749482, 845074597043259864052961293645]", ); get_striped_random_natural_with_bits_helper( 11, 10, 1000, "[8929237967230103262890722824433509449612079777418572793068173743542860931264379536551467\ 111265297962015834728928882271330897607870697615306329567845176199860105934578611877105699\ 420361112596704086865552677150738773328713505835358160809074402075384139431403167870451367\ 242430551069260362892051555117738, \ 848277807033155886730751542077297974149911088007915913764780956681936845102711155704193533\ 266937165754352296914790126319848647014472476095156708927462195514313159177074602462717519\ 349357763529281370152392669738095746762025827796955823134607626270938290494658223672222158\ 9872232895273605128836243696298, \ 622256279237828710101116559940449011192577108759402537346355985105564415773311644474958256\ 085364963664247523046669028723331763456095716282707295047182502032978485452383285604942655\ 047145606332906731031323587018683298574131563687284576221383367233664334964305026386536472\ 7120990168388537700787439359354, \ 893011037585013007271439602956526972024707806627477311937832595287305307343362049808812372\ 867697432889627779970803417048478482882370003668394928455851950345620310470241544275541047\ 354242013397873563064543296718018003131524951605807454956556860189105716328731797732674596\ 4570601733436095071743763633493, \ 714337697986576114077307239016734314472779437227875536493177724277496357242071140467095878\ 368847036684840951410204114568419486398409897184525378525275704002748768137539106304824083\ 362036096433222952552023855753638427465829477635653011302870027782444701974201225532101310\ 2549204865443174861708377533098, \ 717129479744396200344184597459955775324063665344347322215427784911546292557185067124997476\ 300110608871594211005211148242437189627028361260715625731282067311558916993444457603008618\ 146383526538195175746094394556394170673628321139601154519945289775172095900192878319082649\ 5453320605634381639129320740181, \ 712943875305246933549449117163766092515737565613814773068912395757448666817082911895780847\ 326837660502284270497684787917665238088905925731656976408461765235806743263267139181463148\ 004431439157535144190810911719314309577264591245575456701925751321667869578190443322813012\ 0138648732293712628634064954698, \ 892880942227156526968373917452622274287516410008666161523034951090805186930790904719943631\ 023279485226392520031870194759074725254789440380488049235603947036487803727696933564597255\ 812777037968411285945062427246430458697274335300861633278805179074880855146539152265137509\ 2760519788829492124624878217898, \ 892945641881431108631973304223007197865627901236713933938944990987439087863487393850263204\ 926847861908008259701418716838801341585797849737533079786960203576656895262092537802767877\ 046297885380150024466056272755057031975057975145576287997024449574764798500660830182847012\ 5379718921376291465124979747542, \ 712949327932932700218621033804526985196291897563252301818755627637478824989877935042325873\ 291167136650626866176302303072095225803612799473142905508378017958979111144644566257625076\ 950893722575069628745776862688326045350363911106097574031678159885821711577125514250680212\ 9840859041388985930050461586805]", ); } ================================================ FILE: malachite-nz/tests/natural/random/get_striped_random_natural_with_up_to_bits.rs ================================================ // Copyright © 2026 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::num::random::striped::StripedBitSource; use malachite_base::random::EXAMPLE_SEED; use malachite_base::strings::ToDebugString; use malachite_nz::natural::random::get_striped_random_natural_with_up_to_bits; fn get_striped_random_natural_with_up_to_bits_helper( m_numerator: u64, m_denominator: u64, bits: u64, out: &str, ) { let mut bit_source = StripedBitSource::new(EXAMPLE_SEED, m_numerator, m_denominator); let xs = (0..10) .map(|_| get_striped_random_natural_with_up_to_bits(&mut bit_source, bits)) .collect_vec(); assert_eq!(xs.to_debug_string(), out); } #[test] fn test_get_striped_random_natural_with_up_to_bits() { get_striped_random_natural_with_up_to_bits_helper(2, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_up_to_bits_helper(2, 1, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); get_striped_random_natural_with_up_to_bits_helper( 2, 1, 10, "[204, 684, 662, 251, 286, 317, 768, 732, 24, 541]", ); get_striped_random_natural_with_up_to_bits_helper( 2, 1, 100, "[756308944479610176770360563916, 511893378796631990364418200242, \ 446479956742998294289234529360, 173892505765242981097567362471, \ 1215845349850185248466264185684, 189123428420118759301761040685, \ 955700757257715004518140113132, 832461439248077413553063350320, \ 1242643020761038901934578711610, 488312687132791313623062140817]", ); get_striped_random_natural_with_up_to_bits_helper( 2, 1, 1000, "[5302820982294529215866185111327055517244217675166185603676375596884934292920305919547313\ 397807621409756790898297593901473840098546243409160554985560709769081990616677721618124140\ 633144482861862817944190912524600105600870980017006153101609664050197435761380970654049260\ 967366504273137971882485916981452, \ 451422532374337810156996211920710197359298121002851763744111774723019221741197487536552137\ 441891257122655004212896724384177694268489068590218478554429805905364237124314190530761286\ 405220939632145040358782558873699401940490293184219141415291024175612265799475421066864757\ 7711010282817878917709700403886, \ 328973417267649650038984028995599137457468722662497899904226074891574791062985916069985853\ 648332298559640013389542567489103085574506879416017545403787073275584859078240305004208301\ 923778325271860697149197025050165991983366539207622870215729309525729924918778456731981704\ 929268252259716871877534659692, \ 758830907466434071959666860937945102677771418528458236060516770128040285772163826421306107\ 069853863334698116336945744601463639747199523669413845254638599625980012214050809846459478\ 559098934176586233093238956124608709775991202493060441152475782277782012828793855484827036\ 1411929636489612968071552336405, \ 445102130540832453160219335700323042686653540415728760912629486602395793920885692296415616\ 066959429176505917104809378470553959684288306437386478148216974171209001264677464825444901\ 960843306455654296724092328420267049608359359080788746300244379626829069633890752630816253\ 2758344359964169380716341098880, \ 358549244520313090430359983216591888268921826019761298865730362537580500519046229619379667\ 541757327355789565016353008061673905838974550325174736459980946329267051076739150503691661\ 371944463902665345241381162370361591943901176507049154002365951861761529140115300096870050\ 0000811854571849211562809990411, \ 438737766677756544721886069203513091775105013325653031838786046150183322957183097705704738\ 463586306953921236723237323013267328617149319214443759577999182534615674811164847392702407\ 147548571635038747744048561846525019831916866756754841548468500364830638692769954452857420\ 0393000565584191241111348915940, \ 645130850234339503642007350857138479917399859387095109454794616985938391311231126744661800\ 420543794746031491748493862132931262497139684250480230073784453843645088983023718012240528\ 683824553139343195888019854863909746543574579361265915812174560716242126991285521565613433\ 2466523138255580920562084028294, \ 103348981278117743347659685458024425851090003873328972353943876503642331864268476584622834\ 771804716540071910947628116585563492033622988994718273459748870409051443873813666778001704\ 443987702534839202423000943611973000165770624024091217695509335795498343407652970551134766\ 4434861083176910365144082745336, \ 510684705927052351679212082636107036464810921159437157458948509337412320407947949922554657\ 238580604776987667035866633761965104848956467866634135362496712791303540030856375498171483\ 831259576893709723741565585383647648004405829978866534704177730031770836216853668734789059\ 4588929931084078577444892255901]", ); get_striped_random_natural_with_up_to_bits_helper(10, 1, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_up_to_bits_helper(10, 1, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); get_striped_random_natural_with_up_to_bits_helper( 10, 1, 10, "[1016, 992, 1016, 255, 0, 1, 1020, 0, 1016, 1023]", ); get_striped_random_natural_with_up_to_bits_helper( 10, 1, 100, "[316912612278197474676665499640, 1109194416875305772521657204608, \ 14860115584411442377526345726, 1248153346840921551430087606303, \ 198065872776943853719234265088, 1267650600228229401359297740927, \ 950739156735808420047682273024, 638776758039873373851420326912, \ 9864985213488985894722518976, 37718485715515157557238824959]", ); get_striped_random_natural_with_up_to_bits_helper( 10, 1, 1000, "[6227021789445427263039113655730921918572951006503066538950149639959423752662851068863842\ 846174931899135470014771225146998068867182969950386903035779357388391986981527506826577962\ 959351510323326328854575809360361506384979516224625856987797041368114938422133105481271143\ 13802727213763684707371859960, \ 418149324987486545728941348682392045128729012336127607687109371117310119731075741621132811\ 712941491708845808992563601927247951850776072839137275117758244023796842459924562393751724\ 619611544927470362694941669661324507923822529817884467037192087699059800062580597484680330\ 40558838272520165980165373952, \ 101290238602722604813770149769557584827903636411333092403947212265322573720448584292412719\ 007546084038865810128075811761725057540901084282221804825717671524392231618089092521834579\ 302971634982176370935906367582384527889995332318295053733664142471797384264691816494972562\ 2408516333805710606334, \ 613140855310127563710847637107211483373522756531352582924325324369473352782306879549961499\ 829404362274878071222125070886882784952276431978326685623926423305714969567238612410647924\ 930743503806003239444825615154756542772421562094019613522428848711219387743538927178994800\ 765564734856735165291438079, \ 100656671761770967200809514408313411282491427879094391861152015262204431791194203727185921\ 026045038825035836776620646775627513583957795766207833861462739511509698818541011638004365\ 409989389341031372058994101918102834059849507520841606970888386863725907172131052360271284\ 55992101445905914436525739998208, \ 107149228544600635260212788419695526657434400429968676165634060825808436991969085650247279\ 650596133663598434482129668133099616635115467318010721467086518060004035373781135234642383\ 205702114144671525516391055691812453033688242812694582953965743513229924054172419365064495\ 42173396641692237011907449425727, \ 107150860693727448661794856915575585277857852731679120989819290845002348669070050613296455\ 734254692011706809018756806353158106462995138380031851002523766291502961737781576247555759\ 035185454502873048780305065230433793569807065690804749332353542464565681262222119583879742\ 48405282741635132994030678311166, \ 107150835221766756970390016554040088032382955997319930334779105385220088376881426554895494\ 540316762324972302835401791427607201669829855912974990784820455466307137336628823875387612\ 135057991945407277136587896193153151600433435164863822917290693842788118252951172684773421\ 70526384435574180443755489763328, \ 259458997502575090388504772996598528946724376087674101871067524134626069164625241231590514\ 153111280709253894067065950748627250265168604059093486305290952481954858209544512531987544\ 580061950939088894276064731362781063403971101745154263948986687899279303585684102284869355\ 693627487928044157407224, \ 127717813072756195965071628365863751639879810870737425013385130468804848982545562276364724\ 641904754943259319042883222370280844399168602997515222248629586365103060904858985377224746\ 007756101627928195178193946172906161993893729193567644459857171007317377644350722620326222\ 3742148978782762923552931827]", ); get_striped_random_natural_with_up_to_bits_helper(11, 10, 0, "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"); get_striped_random_natural_with_up_to_bits_helper(11, 10, 1, "[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]"); get_striped_random_natural_with_up_to_bits_helper( 11, 10, 10, "[682, 842, 668, 341, 350, 341, 338, 340, 682, 341]", ); get_striped_random_natural_with_up_to_bits_helper( 11, 10, 100, "[1063803140432100403291953916586, 739462850133133817539732346028, \ 422653360565040988003415446874, 848401573590247656481079600469, \ 422550200075885064135585999530, 419242579033418664700359912277, \ 422556546887486595830538392914, 422551811989467209878519567698, \ 422550300869175806062669146794, 845074597043259864052961293645]", ); get_striped_random_natural_with_up_to_bits_helper( 11, 10, 1000, "[3571694931298766658148597579133500396805055718890904755849421801691105675639698924085475\ 217186818671377861364341116537204961881442236045088337279057826912458138650691199761612988\ 883058581411133147888461600627501281537742872135974381226302429036852682145804929027180283\ 412215635242948169473448721083050, \ 312523503440022226256539017547297068869208682155149110042905762496761319540243094457594343\ 859089236690554960456013552907255074371626319073357480048727266774116430788333390913446465\ 619104644972187472443285017414346567664962457858577864857410322417792561934834339345113775\ 9657317068961411710233409661610, \ 865019756446950496269040354104481059118747029066357336244807909203888902108435832283590666\ 775170346004501865878924553107381908132495592609080661684475732927817570636420740556716013\ 168924877758128333222159346949341194770681937489066179441860633805186064044811420594280896\ 906074342076344282184605324666, \ 893011037585013007271439602956526972024707806627477311937832595287305307343362049808812372\ 867697432889627779970803417048478482882370003668394928455851950345620310470241544275541047\ 354242013397873563064543296718018003131524951605807454956556860189105716328731797732674596\ 4570601733436095071743763633493, \ 714337697986576114077307239016734314472779437227875536493177724277496357242071140467095878\ 368847036684840951410204114568419486398409897184525378525275704002748768137539106304824083\ 362036096433222952552023855753638427465829477635653011302870027782444701974201225532101310\ 2549204865443174861708377533098, \ 717129479744396200344184597459955775324063665344347322215427784911546292557185067124997476\ 300110608871594211005211148242437189627028361260715625731282067311558916993444457603008618\ 146383526538195175746094394556394170673628321139601154519945289775172095900192878319082649\ 5453320605634381639129320740181, \ 712943875305246933549449117163766092515737565613814773068912395757448666817082911895780847\ 326837660502284270497684787917665238088905925731656976408461765235806743263267139181463148\ 004431439157535144190810911719314309577264591245575456701925751321667869578190443322813012\ 0138648732293712628634064954698, \ 892880942227156526968373917452622274287516410008666161523034951090805186930790904719943631\ 023279485226392520031870194759074725254789440380488049235603947036487803727696933564597255\ 812777037968411285945062427246430458697274335300861633278805179074880855146539152265137509\ 2760519788829492124624878217898, \ 357191338288297448157760779693006292584925495383947130217069796802263562301019332603664015\ 518999932844210923242642143426207768942951692715733850908225274836460166873351326253496823\ 316044766823056126756948620431307852877994605207198329719827145721619069940836945855738629\ 5164803095064098046522145712854, \ 712949327932932700218621033804526985196291897563252301818755627637478824989877935042325873\ 291167136650626866176302303072095225803612799473142905508378017958979111144644566257625076\ 950893722575069628745776862688326045350363911106097574031678159885821711577125514250680212\ 9840859041388985930050461586805]", ); } ================================================ FILE: malachite-nz/tests/natural/random/random_natural_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::random_natural_inclusive_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn random_natural_inclusive_range_helper( a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_natural_inclusive_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_natural_inclusive_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_inclusive_range_helper( "0", "0", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "14", "8", "10", "1", "1", "0", "1", "0", "8", "66", "1", "3", "2", "5", "1", "6", "1", "2", "14", "1", ]; let common_values = &[ ("0", 240959), ("1", 191819), ("2", 76868), ("3", 76523), ("7", 30894), ("6", 30881), ("4", 30635), ("5", 30631), ("14", 12472), ("15", 12457), ]; let sample_median = ("2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(11.335956999999699), standard_deviation: NiceFloat(20.565945026967327), skewness: NiceFloat(2.486687831499969), excess_kurtosis: NiceFloat(5.6402145781222615), }; random_natural_inclusive_range_helper( "0", "99", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "14", "1", "1", "4", "6", "1", "6", "66", "10", "2", "4", "1", "7", "7", "2", "17", "3", "2", "2", "97", ]; let common_values = &[ ("1", 288484), ("3", 108475), ("2", 108256), ("7", 40848), ("5", 40475), ("4", 40324), ("6", 40213), ("12", 15378), ("14", 15279), ("8", 15268), ]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(12.712097999999987), standard_deviation: NiceFloat(20.543779459614104), skewness: NiceFloat(2.4002783415844497), excess_kurtosis: NiceFloat(5.233152563653805), }; random_natural_inclusive_range_helper( "1", "99", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1987", "1993", "1907", "1984", "1927", "1946", "1993", "1922", "1986", "1901", "1907", "1929", "1925", "1956", "1997", "1938", "1970", "1906", "1955", "1929", ]; let common_values = &[ ("1945", 10146), ("1987", 10096), ("1991", 10094), ("1982", 10056), ("1900", 10042), ("1973", 10033), ("1959", 10029), ("1967", 10026), ("1974", 10024), ("1946", 10023), ]; let sample_median = ("1950", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1949.98699899998), standard_deviation: NiceFloat(29.18007161489914), skewness: NiceFloat(0.000791345316435403), excess_kurtosis: NiceFloat(-1.2020606886458867), }; random_natural_inclusive_range_helper( "1900", "2000", 11, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1206", "2200", "32434", "2526", "428799138", "12119996", "2744", "2065487", "5283", "105634", "63523217", "18250435", "42716754", "7992", "1720", "481774", "7143", "2445", "6806", "297908430", ]; let common_values = &[ ("1022", 3070), ("1006", 3057), ("1001", 3047), ("1014", 3040), ("1020", 3038), ("1003", 3015), ("1010", 3010), ("1012", 3008), ("1018", 3008), ("1008", 3000), ]; let sample_median = ("148810", Some("148811")); let sample_moment_stats = MomentStats { mean: NiceFloat(48716724.95089779), standard_deviation: NiceFloat(150453248.85048282), skewness: NiceFloat(4.049374838772574), excess_kurtosis: NiceFloat(17.011313559369025), }; random_natural_inclusive_range_helper( "1000", "999999999", 32, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_natural_inclusive_range_fail_1() { random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 0, ); } #[test] #[should_panic] fn random_natural_inclusive_range_fail_2() { random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 4, 1, ); } #[test] #[should_panic] fn random_natural_inclusive_range_fail_3() { random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/natural/random/random_natural_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::random_natural_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn random_natural_range_helper( a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_natural_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_natural_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_range_helper( "0", "1", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "14", "8", "10", "1", "1", "0", "1", "0", "8", "66", "1", "3", "2", "5", "1", "6", "1", "2", "14", "1", ]; let common_values = &[ ("0", 240959), ("1", 191819), ("2", 76868), ("3", 76523), ("7", 30894), ("6", 30881), ("4", 30635), ("5", 30631), ("14", 12472), ("15", 12457), ]; let sample_median = ("2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(11.335956999999699), standard_deviation: NiceFloat(20.565945026967327), skewness: NiceFloat(2.486687831499969), excess_kurtosis: NiceFloat(5.6402145781222615), }; random_natural_range_helper( "0", "100", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "14", "1", "1", "4", "6", "1", "6", "66", "10", "2", "4", "1", "7", "7", "2", "17", "3", "2", "2", "97", ]; let common_values = &[ ("1", 288484), ("3", 108475), ("2", 108256), ("7", 40848), ("5", 40475), ("4", 40324), ("6", 40213), ("12", 15378), ("14", 15279), ("8", 15268), ]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(12.712097999999987), standard_deviation: NiceFloat(20.543779459614104), skewness: NiceFloat(2.4002783415844497), excess_kurtosis: NiceFloat(5.233152563653805), }; random_natural_range_helper( "1", "100", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1987", "1993", "1907", "1984", "1927", "1946", "1993", "1922", "1986", "1901", "1907", "1929", "1925", "1956", "1997", "1938", "1970", "1906", "1955", "1929", ]; let common_values = &[ ("1945", 10146), ("1987", 10096), ("1991", 10094), ("1982", 10056), ("1900", 10042), ("1973", 10033), ("1959", 10029), ("1967", 10026), ("1974", 10024), ("1946", 10023), ]; let sample_median = ("1950", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1949.98699899998), standard_deviation: NiceFloat(29.18007161489914), skewness: NiceFloat(0.000791345316435403), excess_kurtosis: NiceFloat(-1.2020606886458867), }; random_natural_range_helper( "1900", "2001", 11, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1206", "2200", "32434", "2526", "428799138", "12119996", "2744", "2065487", "5283", "105634", "63523217", "18250435", "42716754", "7992", "1720", "481774", "7143", "2445", "6806", "297908430", ]; let common_values = &[ ("1022", 3070), ("1006", 3057), ("1001", 3047), ("1014", 3040), ("1020", 3038), ("1003", 3015), ("1010", 3010), ("1012", 3008), ("1018", 3008), ("1008", 3000), ]; let sample_median = ("148810", Some("148811")); let sample_moment_stats = MomentStats { mean: NiceFloat(48716724.95089779), standard_deviation: NiceFloat(150453248.85048282), skewness: NiceFloat(4.049374838772574), excess_kurtosis: NiceFloat(17.011313559369025), }; random_natural_range_helper( "1000", "1000000000", 32, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_natural_range_fail_1() { random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 0, ); } #[test] #[should_panic] fn random_natural_range_fail_2() { random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 4, 1, ); } #[test] #[should_panic] fn random_natural_range_fail_3() { random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32), 10, 1, ); } #[test] #[should_panic] fn random_natural_range_fail_4() { random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(10u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/natural/random/random_natural_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::random_natural_range_to_infinity; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn random_natural_range_to_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_natural_range_to_infinity( EXAMPLE_SEED, Natural::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_natural_range_to_infinity() { let values = &[ "0", "14", "0", "8", "2", "6", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("2", 62676), ("3", 62465), ("7", 15819), ("5", 15781), ("6", 15694), ("4", 15518), ("13", 3945), ("8", 3895), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.289019000000012), standard_deviation: NiceFloat(811.503067487901), skewness: NiceFloat(791.581366511165), excess_kurtosis: NiceFloat(717047.0759703598), }; random_natural_range_to_infinity_helper( "0", 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "20431208470830262", "2777240", "114", "12184833305054", "1121025855008623490210", "13478874522577592", "115311695", "7", "18", "54522366353", "2183264193236231773387459", "824", "18558864232439549193912", "15", "110989", "453270", "4307150", "45388024541", "47", "3345913274", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14233), ("2", 14194), ("7", 6984), ("6", 6980), ("4", 6964), ("5", 6929), ("10", 3479), ("15", 3431), ]; let sample_median = ("3201388", Some("3201522")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.480305129633914e129), standard_deviation: NiceFloat(2.4803051296331898e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_range_to_infinity_helper( "0", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "11", "182", "12", "152", "50", "94", "18", "11", "13", "15", "14", "13", "28", "24", "13", "13", "31", "19", "12", "13", ]; let common_values = &[ ("13", 83637), ("11", 83622), ("15", 83440), ("14", 83364), ("10", 83305), ("12", 82880), ("20", 15837), ("31", 15785), ("19", 15779), ("18", 15776), ]; let sample_median = ("15", None); let sample_moment_stats = MomentStats { mean: NiceFloat(128.81076899999977), standard_deviation: NiceFloat(15255.606035258177), skewness: NiceFloat(845.8189997295934), excess_kurtosis: NiceFloat(789803.2243471228), }; random_natural_range_to_infinity_helper( "10", 5, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "118", "56", "1714", "55845661150", "93254818", "822568088563644", "120", "871591019599", "99", "1171796531603249384284396706", "3570371", "76271186", "69092967935443594634663005648041578296", "110", "39", "25543539470733", "317538101910", "206", "14906804826461850333", "95450125556931311", ]; let common_values = &[ ("13", 5882), ("14", 5840), ("12", 5734), ("15", 5645), ("11", 5644), ("10", 5642), ("18", 2148), ("27", 2143), ("19", 2134), ("23", 2134), ]; let sample_median = ("7289020", Some("7289286")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8276128186777812e120), standard_deviation: NiceFloat(1.8276117282901724e123), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_range_to_infinity_helper( "10", 32, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1032867295426", "15476566285494", "1005058503561", "11872468885656", "3085108281010", "7786786793950", "1848070042786", "1008384510771", "1035939113223", "1034091049134", "1097997002237", "1066780473347", "1232902614972", "2160500927160", "1039676158979", "1075044604283", "1421346833487", "2100488049827", "1090935342918", "1033099299962", ]; let common_values = &[ ("1012318490312", 2), ("1020804407546", 2), ("1040579317197", 2), ("1041361099759", 2), ("1099357770481", 2), ("1000000358874", 1), ("1000000635467", 1), ("1000000743391", 1), ("1000001041678", 1), ("1000001124568", 1), ]; let sample_median = ("1099468717392", Some("1099468761569")); let sample_moment_stats = MomentStats { mean: NiceFloat(9002084314682.418), standard_deviation: NiceFloat(1175305974058995.2), skewness: NiceFloat(894.6662459454856), excess_kurtosis: NiceFloat(856946.924578041), }; random_natural_range_to_infinity_helper( "1000000000000", 41, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2282426752182", "3076375863448", "33871433858738", "193926771358011304414", "683117911635193788", "95918191752968866622136", "5399022933155", "2679643424229893512354", "7585953905347", "17738519421136481929559726434799186", "70600001019637432", "77299482847566318", "332646018266965594347466935183659688140188647", "4856563742926", "1110539913949", "8169120771017371179759", "142409202767618812372", "3612730358681", "468787385712310874935747551", "9607440468294695468459788", ]; let common_values = &[ ("1000006091267", 1), ("1000006483280", 1), ("1000008421992", 1), ("1000009071089", 1), ("1000011436758", 1), ("1000013492649", 1), ("1000014387323", 1), ("1000020641917", 1), ("1000020859147", 1), ("1000020971497", 1), ]; let sample_median = ("70366472614875784", Some("70368772587252716")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0984547559553134e113), standard_deviation: NiceFloat(1.098369190533207e116), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_natural_range_to_infinity_helper( "1000000000000", 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_natural_range_to_infinity_fail_1() { random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(10u32), 1, 0); } #[test] #[should_panic] fn random_natural_range_to_infinity_fail_2() { random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(10u32), 4, 1); } ================================================ FILE: malachite-nz/tests/natural/random/random_naturals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::random::random_naturals; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; fn random_naturals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_naturals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_naturals() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[ ("0", 984681), ("1", 15077), ("2", 121), ("3", 116), ("6", 2), ("4", 1), ("5", 1), ("7", 1), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.015695000000000257), standard_deviation: NiceFloat(0.12853281096935348), skewness: NiceFloat(9.11690327111834), excess_kurtosis: NiceFloat(110.73931175909136), }; random_naturals_helper( 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "0", "14", "0", "8", "2", "6", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("2", 62676), ("3", 62465), ("7", 15819), ("5", 15781), ("6", 15694), ("4", 15518), ("13", 3945), ("8", 3895), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.289019000000012), standard_deviation: NiceFloat(811.503067487901), skewness: NiceFloat(791.581366511165), excess_kurtosis: NiceFloat(717047.0759703598), }; random_naturals_helper( 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "20431208470830262", "2777240", "114", "12184833305054", "1121025855008623490210", "13478874522577592", "115311695", "7", "18", "54522366353", "2183264193236231773387459", "824", "18558864232439549193912", "15", "110989", "453270", "4307150", "45388024541", "47", "3345913274", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14233), ("2", 14194), ("7", 6984), ("6", 6980), ("4", 6964), ("5", 6929), ("10", 3479), ("15", 3431), ]; let sample_median = ("3201388", Some("3201522")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.480305129633914e129), standard_deviation: NiceFloat(2.4803051296331898e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_naturals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1049807948069596877906281043152861735368289016372406", "1388880088667859422", "26145954", "3731388", "1470862095575962348216", "99", "1", "835275153", "3892061391890507266755", "925334710331614885833504493368", "221414670923422190", "11239", "254772031885", "1351005164080654998", "9136414433496904064275246960259217614", "1775", "5562", "8137327159764", "19744859531291384657393101375027010425831988999", "2078424122508695", ]; let common_values = &[ ("0", 15386), ("1", 15062), ("2", 7592), ("3", 7459), ("4", 3719), ("5", 3707), ("6", 3685), ("7", 3508), ("12", 1906), ("11", 1865), ]; let sample_median = ("15157534309527", Some("15157859817105")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8099447055615434e263), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_naturals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_naturals_fail_1() { random_naturals(EXAMPLE_SEED, 0, 1); } #[test] #[should_panic] fn random_naturals_fail_2() { random_naturals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_naturals_fail_3() { random_naturals(EXAMPLE_SEED, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/natural/random/random_naturals_less_than.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::random_naturals_less_than; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn random_naturals_less_than_helper( limit: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_naturals_less_than(EXAMPLE_SEED, Natural::from_str(limit).unwrap()), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_naturals_less_than() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_naturals_less_than_helper( "1", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1", "7", "13", "5", "7", "9", "2", "8", "2", "11", "4", "11", "14", "13", "6", "6", "11", "1", "3", "7", ]; let common_values = &[ ("10", 67077), ("7", 67071), ("2", 66902), ("6", 66802), ("3", 66769), ("9", 66740), ("11", 66724), ("14", 66705), ("0", 66612), ("13", 66590), ]; let sample_median = ("7", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.002550000000202), standard_deviation: NiceFloat(4.318291113986895), skewness: NiceFloat(-0.0008733138647064903), excess_kurtosis: NiceFloat(-1.209254148711494), }; random_naturals_less_than_helper( "15", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1", "7", "13", "5", "7", "9", "2", "8", "2", "11", "4", "11", "14", "13", "6", "6", "11", "1", "3", "7", ]; let common_values = &[ ("10", 62902), ("2", 62837), ("7", 62827), ("3", 62676), ("11", 62617), ("6", 62613), ("14", 62607), ("9", 62606), ("8", 62510), ("0", 62466), ]; let sample_median = ("8", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.499876999999703), standard_deviation: NiceFloat(4.606495327759524), skewness: NiceFloat(-0.0003936178035348645), excess_kurtosis: NiceFloat(-1.207854285765452), }; random_naturals_less_than_helper( "16", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "7", "9", "8", "11", "14", "11", "1", "7", "1", "6", "6", "6", "7", "5", "12", "7", "15", "7", "7", "5", ]; let common_values = &[ ("13", 59283), ("10", 59171), ("3", 59142), ("6", 59131), ("16", 59052), ("0", 58906), ("9", 58849), ("14", 58816), ("2", 58806), ("7", 58744), ]; let sample_median = ("8", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.003521000000225), standard_deviation: NiceFloat(4.899161622598552), skewness: NiceFloat(-0.0010892026016323982), excess_kurtosis: NiceFloat(-1.20819299609532), }; random_naturals_less_than_helper( "17", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "388977", "925783", "378973", "75271", "945129", "765554", "271720", "260338", "21995", "458836", "661659", "310190", "396637", "576534", "304342", "557803", "678529", "654451", "280711", "928029", ]; let common_values = &[ ("429869", 9), ("568287", 9), ("771880", 9), ("890", 8), ("18201", 8), ("61885", 8), ("163140", 8), ("173104", 8), ("214281", 8), ("340935", 8), ]; let sample_median = ("500024", Some("500026")); let sample_moment_stats = MomentStats { mean: NiceFloat(500269.9304960077), standard_deviation: NiceFloat(288405.96360756975), skewness: NiceFloat(-0.0010400381943526848), excess_kurtosis: NiceFloat(-1.1981474275491453), }; random_naturals_less_than_helper( "1000000", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3233271796909041147200401960861496742517", "6217357404646018754599684571795784707698", "9438016902699487422458396847802670929387", "7727353449345949782973180362335717735342", "534354137356207625017431174589301695702", "534877532602868824396077953846378055833", "2066581267912983630335063637372720045094", "1831715414082884162869589340142899207735", "2619564100767325027279529873701213301661", "6005405409180901613675532713129270331479", "8271966495851265353624356439908105167895", "2537046382263430904899281307939508702471", "7202939407624515890221097211474505126578", "5142762353061547853401995252125996224683", "1027218951536793906738056738325216303009", "9914727392521646960300300265785426013882", "1459386323443095819796283591928997970915", "5477318216232641272279240890043646394779", "6387837972601141117504319208136943264497", "5474635405681155657679090532822557929038", ]; let common_values = &[ ("8768725511813114574712047169606198", 1), ("9827974885359877076313510726004983", 1), ("12488944552955502737286653696783298", 1), ("22890668287803601945090476573028348", 1), ("24602492188456115932292147454123699", 1), ("32710913204967376519858724740864044", 1), ("36222387069235523377031863703777427", 1), ("49953398642815549142118724082696119", 1), ("51712706399518805574773981541840520", 1), ("58535354783119341230390576092841062", 1), ]; let sample_median = ( "5001510563009032264934634274159139768440", Some("5001521540293100102818635713617625902813"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(5.001250475448614e39), standard_deviation: NiceFloat(2.887524153222133e39), skewness: NiceFloat(-0.0006935347805930534), excess_kurtosis: NiceFloat(-1.2008620906428813), }; random_naturals_less_than_helper( "10000000000000000000000000000000000000000", values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_naturals_less_than_fail() { random_naturals_less_than(EXAMPLE_SEED, Natural::ZERO); } ================================================ FILE: malachite-nz/tests/natural/random/random_positive_naturals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::random::random_positive_naturals; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; fn random_positive_naturals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( random_positive_naturals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_positive_naturals() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 984681), ("3", 7622), ("2", 7455), ("5", 73), ("6", 66), ("7", 54), ("4", 44), ("8", 2), ("10", 2), ("14", 1), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.023822000000005), standard_deviation: NiceFloat(0.20727410662829246), skewness: NiceFloat(10.72004433095801), excess_kurtosis: NiceFloat(159.60627558337237), }; random_positive_naturals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1", "24", "1", "30", "6", "12", "2", "1", "1", "1", "1", "1", "2", "2", "1", "1", "3", "3", "1", "1", ]; let common_values = &[ ("1", 500248), ("3", 124972), ("2", 124519), ("7", 31554), ("5", 31346), ("6", 31198), ("4", 31043), ("12", 8033), ("11", 7959), ("10", 7935), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(15.68562000000007), standard_deviation: NiceFloat(2088.3045530403606), skewness: NiceFloat(877.2889258611025), excess_kurtosis: NiceFloat(832799.3689336807), }; random_positive_naturals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "22", "4", "178", "55845661150", "93254818", "7577967529619388", "8", "11316951483471", "11", "1005760138411689342464923704482", "948931", "42716754", "81013760999253680590984897748479904878392", "23", "5", "488225822927510", "1558028859598", "29", "200127331174844881647", "4058622214797175252", ]; let common_values = &[ ("1", 31094), ("2", 15260), ("3", 15185), ("4", 7586), ("5", 7376), ("7", 7346), ("6", 7258), ("10", 3631), ("14", 3607), ("11", 3605), ]; let sample_median = ("3799061", Some("3799067")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.312362311300544e130), standard_deviation: NiceFloat(2.3122865276852406e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_naturals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1030304779202860497815440824491190", "886085025458", "207326", "83590267817164982586207812646050", "142592182196136038718074156629812683467448", "486577913627642327503939268330036386", "5557920650918595", "82", "3896", "259694111319673990840", "38511521798151392412656616617957654586378660839", "637134", "2330568192653124764618470467652346596061", "2516", "512663303", "39317568409", "18536901993439", "4959577657266999117207", "628", "42485719907732979", ]; let common_values = &[ ("1", 15720), ("2", 7718), ("3", 7584), ("6", 3790), ("4", 3739), ("7", 3704), ("5", 3673), ("9", 1918), ("11", 1916), ("10", 1904), ]; let sample_median = ("18436851140261", Some("18438360920148")); let sample_moment_stats = MomentStats { mean: NiceFloat(5.519478531998525e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_naturals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_positive_naturals_fail_1() { random_positive_naturals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_positive_naturals_fail_2() { random_positive_naturals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-nz/tests/natural/random/striped_random_natural_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::striped_random_natural_inclusive_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn striped_random_natural_inclusive_range_helper( a: &str, b: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( striped_random_natural_inclusive_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), mean_stripe_numerator, mean_stripe_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_natural_inclusive_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_natural_inclusive_range_helper( "0", "0", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1990", "1991", "1991", "2006", "1996", "1991", "2020", "1991", "1990", "2014", "1990", "2020", "1991", "1990", "2020", "1991", "2015", "2020", "2016", "2016", ]; let common_values = &[ ("1990", 141061), ("1991", 140282), ("2016", 140025), ("2021", 125104), ("2020", 124770), ("2017", 47126), ("2019", 46880), ("1999", 39864), ("2015", 39502), ("2018", 15866), ]; let sample_median = ("2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(-0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_natural_inclusive_range_helper( "1990", "2021", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1000425", "1036272", "1007600", "1999887", "1018367", "1000191", "1048387", "1049087", "1007631", "1015792", "1971832", "1046770", "1023876", "1966085", "1838648", "1017728", "1046662", "1998848", "1613817", "1982463", ]; let common_values = &[ ("2000000", 26405), ("1999872", 3441), ("1048575", 3413), ("1015807", 3052), ("1998848", 2966), ("1000447", 2758), ("1000063", 2381), ("1000000", 2380), ("1966080", 1441), ("1999935", 1251), ]; let sample_median = ("1048576", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1371348.0426910813), standard_deviation: NiceFloat(417874.3987798391), skewness: NiceFloat(0.5348808065018619), excess_kurtosis: NiceFloat(-1.5362497902865004), }; striped_random_natural_inclusive_range_helper( "1000000", "2000000", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_natural_inclusive_range_fail_1() { striped_random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 0, ); } #[test] #[should_panic] fn striped_random_natural_inclusive_range_fail_2() { striped_random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 1, ); } #[test] #[should_panic] fn striped_random_natural_inclusive_range_fail_3() { striped_random_natural_inclusive_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/natural/random/striped_random_natural_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::striped_random_natural_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn striped_random_natural_range_helper( a: &str, b: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( striped_random_natural_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), mean_stripe_numerator, mean_stripe_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_natural_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_natural_range_helper( "0", "1", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1990", "1991", "1991", "2006", "1996", "1991", "2020", "1991", "1990", "2014", "1990", "2020", "1991", "1990", "2020", "1991", "2015", "2020", "2016", "2016", ]; let common_values = &[ ("1990", 141061), ("1991", 140282), ("2016", 140025), ("2021", 125104), ("2020", 124770), ("2017", 47126), ("2019", 46880), ("1999", 39864), ("2015", 39502), ("2018", 15866), ]; let sample_median = ("2015", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2007.63283599996), standard_deviation: NiceFloat(12.714969927906306), skewness: NiceFloat(-0.39110989081904446), excess_kurtosis: NiceFloat(-1.6497443674417989), }; striped_random_natural_range_helper( "1990", "2022", 4, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1000425", "1036272", "1007600", "1999887", "1018367", "1000191", "1048387", "1049087", "1007631", "1015792", "1971832", "1046770", "1023876", "1966085", "1838648", "1017728", "1046662", "1998848", "1613817", "1982463", ]; let common_values = &[ ("2000000", 26405), ("1999872", 3441), ("1048575", 3413), ("1015807", 3052), ("1998848", 2966), ("1000447", 2758), ("1000063", 2381), ("1000000", 2380), ("1966080", 1441), ("1999935", 1251), ]; let sample_median = ("1048576", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1371348.0426910813), standard_deviation: NiceFloat(417874.3987798391), skewness: NiceFloat(0.5348808065018619), excess_kurtosis: NiceFloat(-1.5362497902865004), }; striped_random_natural_range_helper( "1000000", "2000001", 4, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_natural_range_fail_1() { striped_random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 0, ); } #[test] #[should_panic] fn striped_random_natural_range_fail_2() { striped_random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(100u32), 1, 1, ); } #[test] #[should_panic] fn striped_random_natural_range_fail_3() { striped_random_natural_range( EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32), 10, 1, ); } ================================================ FILE: malachite-nz/tests/natural/random/striped_random_natural_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::striped_random_natural_range_to_infinity; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn striped_random_natural_range_to_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( striped_random_natural_range_to_infinity( EXAMPLE_SEED, Natural::from_str(a).unwrap(), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_natural_range_to_infinity() { let values = &[ "2", "4", "128", "1124203576", "4", "15", "32", "751", "6400", "8376024595", "3", "60", "1", "1", "65045535", "6", "0", "7", "73608", "719661083353407616", ]; let common_values = &[ ("0", 90859), ("1", 82901), ("3", 37653), ("2", 37438), ("7", 25786), ("4", 25681), ("8", 17394), ("15", 17328), ("16", 12055), ("31", 11982), ]; let sample_median = ("71", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.068551928510147e34), standard_deviation: NiceFloat(6.914607365781463e37), skewness: NiceFloat(958.8924868378492), excess_kurtosis: NiceFloat(939262.8054862365), }; striped_random_natural_range_to_infinity_helper( "0", 4, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "8192", "8312", "15614", "1984", "1568", "1023", "1791", "260174", "9855", "98176", "1519", "2591", "3616", "8176", "1796", "8167", "262616", "4069", "12062", "1072", ]; let common_values = &[ ("1023", 31735), ("1007", 28198), ("1000", 28160), ("1022", 10688), ("1008", 10662), ("1020", 10580), ("1016", 10498), ("1001", 9418), ("1003", 9393), ("1004", 9319), ]; let sample_median = ("4159", None); let sample_moment_stats = MomentStats { mean: NiceFloat(54201665904379.38), standard_deviation: NiceFloat(2.6365321443458296e16), skewness: NiceFloat(608.9470987335318), excess_kurtosis: NiceFloat(388228.1677811064), }; striped_random_natural_range_to_infinity_helper( "1000", 4, 1, 14, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_natural_range_to_infinity_fail_1() { striped_random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(100u32), 1, 0, 10, 1); } #[test] #[should_panic] fn striped_random_natural_range_to_infinity_fail_2() { striped_random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(100u32), 1, 1, 10, 1); } #[test] #[should_panic] fn striped_random_natural_range_to_infinity_fail_3() { striped_random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(100u32), 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_natural_range_to_infinity_fail_4() { striped_random_natural_range_to_infinity(EXAMPLE_SEED, Natural::from(100u32), 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/natural/random/striped_random_naturals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::random::striped_random_naturals; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; fn striped_random_naturals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( striped_random_naturals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_naturals() { // mean bits = 1/64 let values = &["0"; 20]; let common_values = &[("0", 984681), ("1", 15077), ("3", 120), ("2", 117), ("4", 3), ("5", 1), ("7", 1)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.015695000000000875), standard_deviation: NiceFloat(0.12845498618458842), skewness: NiceFloat(9.02636021695415), excess_kurtosis: NiceFloat(104.38317092740806), }; striped_random_naturals_helper( 4, 1, 1, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 1 let values = &[ "0", "8", "0", "8", "2", "4", "1", "0", "0", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "0", ]; let common_values = &[ ("0", 500248), ("1", 249491), ("3", 62636), ("2", 62505), ("4", 23595), ("7", 23447), ("8", 8713), ("15", 8690), ("6", 7938), ("5", 7832), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.16843100000002), standard_deviation: NiceFloat(782.5565010647151), skewness: NiceFloat(800.2073401417995), excess_kurtosis: NiceFloat(728738.7203924827), }; striped_random_naturals_helper( 4, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "18014656207519744", "2228160", "64", "17592184995840", "1179440951012584587264", "9007749010526207", "67108864", "5", "24", "34359738879", "2417851639228158863474687", "512", "9444737328601429442560", "8", "131071", "524032", "8388607", "34359738368", "60", "2147741695", ]; let common_values = &[ ("0", 30467), ("1", 29379), ("3", 14232), ("2", 14195), ("4", 13131), ("7", 13019), ("8", 11921), ("15", 11751), ("31", 10682), ("16", 10555), ]; let sample_median = ("3670016", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.459178425232889e129), standard_deviation: NiceFloat(1.459178425232619e132), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_naturals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1473193827441715154886135497317777215948837626052608", "1152921504606846976", "16777216", "4128768", "1180591620717412351744", "127", "1", "1073741823", "4722366482869645209600", "1267650600226049676594364547199", "288230376151711743", "8192", "274869520368", "1152921504606846976", "5317074242107007699768820031345917967", "1024", "8191", "4398046511104", "11417981541647679048466288345891489974790914528", "2251799813685247", ]; let common_values = &[ ("0", 15386), ("1", 15062), ("2", 7584), ("3", 7467), ("4", 7110), ("7", 7017), ("8", 6866), ("15", 6763), ("31", 6505), ("16", 6460), ]; let sample_median = ("17592169267200", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.6414828903095017e263), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_naturals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_naturals_fail_1() { striped_random_naturals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_naturals_fail_2() { striped_random_naturals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_naturals_fail_3() { striped_random_naturals(EXAMPLE_SEED, 4, 1, 0, 1); } #[test] #[should_panic] fn striped_random_naturals_fail_4() { striped_random_naturals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_naturals_fail_5() { striped_random_naturals(EXAMPLE_SEED, 4, 1, u64::MAX, u64::MAX - 1); } ================================================ FILE: malachite-nz/tests/natural/random/striped_random_positive_naturals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::random::striped_random_positive_naturals; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; fn striped_random_positive_naturals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( striped_random_positive_naturals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_positive_naturals() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 984681), ("3", 7637), ("2", 7440), ("4", 97), ("7", 78), ("5", 33), ("6", 29), ("11", 2), ("8", 1), ("9", 1), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.023796999999977), standard_deviation: NiceFloat(0.20691241046333197), skewness: NiceFloat(10.752762867801868), excess_kurtosis: NiceFloat(162.40220891738076), }; striped_random_positive_naturals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1", "16", "1", "16", "4", "15", "2", "1", "1", "1", "1", "1", "2", "2", "1", "1", "3", "2", "1", "1", ]; let common_values = &[ ("1", 500248), ("2", 124818), ("3", 124673), ("7", 47032), ("4", 46853), ("8", 17749), ("15", 17612), ("5", 15660), ("6", 15596), ("16", 6518), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(15.773014000000762), standard_deviation: NiceFloat(2128.8810534178506), skewness: NiceFloat(884.8410850537254), excess_kurtosis: NiceFloat(843254.2507640689), }; striped_random_positive_naturals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "16", "4", "128", "34391195648", "75493376", "9007199120523391", "8", "8796094070783", "8", "950737950171027935941967741439", "1040391", "33554432", "84390026996392738938916902643112875376640", "30", "7", "554153860399104", "2199023255551", "16", "220784470296873664512", "4611685966886694919", ]; let common_values = &[ ("1", 31094), ("3", 15250), ("2", 15195), ("7", 13890), ("4", 13880), ("8", 12601), ("15", 12519), ("31", 11397), ("16", 11237), ("63", 10225), ]; let sample_median = ("4194272", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.1641486095650758e130), standard_deviation: NiceFloat(1.1640776313097e133), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_naturals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "649037107316853596555600210165760", "822486237184", "196608", "141976867225561692967630759002112", "174223242635524708377374895198005052307456", "664594824829454142366461086851399679", "4503599627370496", "127", "2048", "147574233996470517759", "45660775794157599311165096735019350831520546815", "1048320", "1361212544433490269424560431578983940096", "3968", "536870911", "34359738368", "35184372088831", "9297159013149614014464", "768", "72040001986101247", ]; let common_values = &[ ("1", 15720), ("2", 7656), ("3", 7646), ("7", 7219), ("4", 7199), ("8", 7122), ("15", 6934), ("31", 6799), ("16", 6750), ("63", 6456), ]; let sample_median = ("17592186044416", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.796251092974677e283), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_naturals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_positive_naturals_fail_1() { striped_random_positive_naturals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_positive_naturals_fail_2() { striped_random_positive_naturals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_positive_naturals_fail_3() { striped_random_positive_naturals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_positive_naturals_fail_4() { striped_random_positive_naturals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-nz/tests/natural/random/uniform_random_natural_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::uniform_random_natural_inclusive_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn uniform_random_natural_inclusive_range_helper( a: &str, b: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( uniform_random_natural_inclusive_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_uniform_random_natural_inclusive_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; uniform_random_natural_inclusive_range_helper( "0", "0", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "6", "6", "2", "3", "1", "3", "4", "5", "4", "6", "4", "2", "4", "6", "2", "1", "2", "6", "6", ]; let common_values = &[("3", 167245), ("4", 166932), ("1", 166580), ("6", 166511), ("5", 166451), ("2", 166281)]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.499925999999989), standard_deviation: NiceFloat(1.7070480100269305), skewness: NiceFloat(0.00002078867947249881), excess_kurtosis: NiceFloat(-1.2668800296473062), }; uniform_random_natural_inclusive_range_helper( "1", "6", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1987", "1993", "1907", "1984", "1927", "1946", "1993", "1922", "1986", "1901", "1907", "1929", "1925", "1956", "1997", "1938", "1970", "1906", "1955", "1929", ]; let common_values = &[ ("1945", 10146), ("1987", 10096), ("1991", 10094), ("1982", 10056), ("1900", 10042), ("1973", 10033), ("1959", 10029), ("1967", 10026), ("1974", 10024), ("1946", 10023), ]; let sample_median = ("1950", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1949.98699899998), standard_deviation: NiceFloat(29.18007161489914), skewness: NiceFloat(0.000791345316435403), excess_kurtosis: NiceFloat(-1.2020606886458867), }; uniform_random_natural_inclusive_range_helper( "1900", "2000", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "4233271796909041147200401960861496742517", "7217357404646018754599684571795784707698", "8727353449345949782973180362335717735342", "1534354137356207625017431174589301695702", "1534877532602868824396077953846378055833", "3066581267912983630335063637372720045094", "2831715414082884162869589340142899207735", "3619564100767325027279529873701213301661", "7005405409180901613675532713129270331479", "9271966495851265353624356439908105167895", "3537046382263430904899281307939508702471", "8202939407624515890221097211474505126578", "6142762353061547853401995252125996224683", "2027218951536793906738056738325216303009", "2459386323443095819796283591928997970915", "6477318216232641272279240890043646394779", "7387837972601141117504319208136943264497", "6474635405681155657679090532822557929038", "9135952782573375316643238824480434324207", "6103640323458129521087258887390847694928", ]; let common_values = &[ ("1000008513881061280823789640490226316271", 1), ("1000008768725511813114574712047169606198", 1), ("1000009827974885359877076313510726004983", 1), ("1000012488944552955502737286653696783298", 1), ("1000022890668287803601945090476573028348", 1), ("1000024602492188456115932292147454123699", 1), ("1000032710913204967376519858724740864044", 1), ("1000032757195298640822606970649697168394", 1), ("1000036222387069235523377031863703777427", 1), ("1000036429852801882310669972964558023474", 1), ]; let sample_median = ( "5500511672867651605813709882516812610647", Some("5500520043239248270285741751344805934001"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(5.501866091611912e39), standard_deviation: NiceFloat(2.5991591590322043e39), skewness: NiceFloat(0.00028444202202606493), excess_kurtosis: NiceFloat(-1.2007002735784507), }; uniform_random_natural_inclusive_range_helper( "1000000000000000000000000000000000000000", "9999999999999999999999999999999999999999", values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn uniform_random_natural_inclusive_range_fail() { uniform_random_natural_inclusive_range(EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32)); } ================================================ FILE: malachite-nz/tests/natural/random/uniform_random_natural_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_nz::natural::random::uniform_random_natural_range; use malachite_nz::test_util::natural::random::random_naturals_helper_helper; use std::str::FromStr; fn uniform_random_natural_range_helper( a: &str, b: &str, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_naturals_helper_helper( uniform_random_natural_range( EXAMPLE_SEED, Natural::from_str(a).unwrap(), Natural::from_str(b).unwrap(), ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_uniform_random_natural_range() { let values = &["0"; 20]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; uniform_random_natural_range_helper( "0", "1", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "2", "6", "6", "2", "3", "1", "3", "4", "5", "4", "6", "4", "2", "4", "6", "2", "1", "2", "6", "6", ]; let common_values = &[("3", 167245), ("4", 166932), ("1", 166580), ("6", 166511), ("5", 166451), ("2", 166281)]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.499925999999989), standard_deviation: NiceFloat(1.7070480100269305), skewness: NiceFloat(0.00002078867947249881), excess_kurtosis: NiceFloat(-1.2668800296473062), }; uniform_random_natural_range_helper( "1", "7", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1987", "1993", "1907", "1984", "1927", "1946", "1993", "1922", "1986", "1901", "1907", "1929", "1925", "1956", "1997", "1938", "1970", "1906", "1955", "1929", ]; let common_values = &[ ("1945", 10146), ("1987", 10096), ("1991", 10094), ("1982", 10056), ("1900", 10042), ("1973", 10033), ("1959", 10029), ("1967", 10026), ("1974", 10024), ("1946", 10023), ]; let sample_median = ("1950", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1949.98699899998), standard_deviation: NiceFloat(29.18007161489914), skewness: NiceFloat(0.000791345316435403), excess_kurtosis: NiceFloat(-1.2020606886458867), }; uniform_random_natural_range_helper( "1900", "2001", values, common_values, sample_median, sample_moment_stats, ); let values = &[ "4233271796909041147200401960861496742517", "7217357404646018754599684571795784707698", "8727353449345949782973180362335717735342", "1534354137356207625017431174589301695702", "1534877532602868824396077953846378055833", "3066581267912983630335063637372720045094", "2831715414082884162869589340142899207735", "3619564100767325027279529873701213301661", "7005405409180901613675532713129270331479", "9271966495851265353624356439908105167895", "3537046382263430904899281307939508702471", "8202939407624515890221097211474505126578", "6142762353061547853401995252125996224683", "2027218951536793906738056738325216303009", "2459386323443095819796283591928997970915", "6477318216232641272279240890043646394779", "7387837972601141117504319208136943264497", "6474635405681155657679090532822557929038", "9135952782573375316643238824480434324207", "6103640323458129521087258887390847694928", ]; let common_values = &[ ("1000008513881061280823789640490226316271", 1), ("1000008768725511813114574712047169606198", 1), ("1000009827974885359877076313510726004983", 1), ("1000012488944552955502737286653696783298", 1), ("1000022890668287803601945090476573028348", 1), ("1000024602492188456115932292147454123699", 1), ("1000032710913204967376519858724740864044", 1), ("1000032757195298640822606970649697168394", 1), ("1000036222387069235523377031863703777427", 1), ("1000036429852801882310669972964558023474", 1), ]; let sample_median = ( "5500511672867651605813709882516812610647", Some("5500520043239248270285741751344805934001"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(5.501866091611912e39), standard_deviation: NiceFloat(2.5991591590322043e39), skewness: NiceFloat(0.00028444202202606493), excess_kurtosis: NiceFloat(-1.2007002735784507), }; uniform_random_natural_range_helper( "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000", values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn uniform_random_natural_range_fail_1() { uniform_random_natural_range(EXAMPLE_SEED, Natural::from(10u32), Natural::from(9u32)); } #[test] #[should_panic] fn uniform_random_natural_range_fail_2() { uniform_random_natural_range(EXAMPLE_SEED, Natural::from(10u32), Natural::from(10u32)); } ================================================ FILE: malachite-q/.gitignore ================================================ target *.bk .idea* *.iml ================================================ FILE: malachite-q/Cargo.toml ================================================ [package] name = "malachite-q" version = "0.9.1" authors = ["Mikhail Hogrefe "] rust-version.workspace = true edition.workspace = true description = "The arbitrary-precision type Rational, with efficient algorithms partially derived from GMP and FLINT." readme = "README.md" homepage = "https://malachite.rs/" repository = "https://github.com/mhogrefe/malachite" license = "LGPL-3.0-only" keywords = ["mathematics", "math", "numerics", "bignum"] categories = ["mathematics"] [lib] name = "malachite_q" path = "src/lib.rs" [[bin]] name = "malachite_q_main" path = "src/bin.rs" [dependencies] itertools = { version = "0.14.0", default-features = false, features = ["use_alloc"] } malachite-base = { version = "0.9.1", default-features = false, path = "../malachite-base" } malachite-nz = { version = "0.9.1", default-features = false, path = "../malachite-nz" } serde = { version = "1.0.188", optional = true, default-features = false, features = ["alloc", "derive"] } serde_json = { version = "1.0.149", optional = true } num = { version = "0.4.3", optional = true, features = ["serde"] } rug = { version = "1.28.1", default-features = false, optional = true, features = ["rational", "serde"] } [dev-dependencies] malachite-q = { path = ".", features = ["test_build"] } [features] default = ["std"] std = ["malachite-base/std", "malachite-nz/std"] enable_serde = ["serde", "malachite-nz/enable_serde"] random = ["malachite-base/random", "malachite-nz/random"] 32_bit_limbs = ["malachite-nz/32_bit_limbs"] test_build = ["malachite-base/test_build", "malachite-nz/test_build", "random", "serde", "serde_json", "num", "rug"] bin_build = ["test_build"] [package.metadata.docs.rs] features = ["random"] rustdoc-args = [ "--html-in-header", "katex-header.html" ] ================================================ FILE: malachite-q/README.md ================================================ - [crates.io](https://crates.io/crates/malachite-q) - [docs.rs](https://docs.rs/malachite-q/latest/malachite_q/) Rather than using this crate directly, use the [`malachite`](https://crates.io/crates/malachite) meta-crate. It re-exports all of this crate's public members. In `malachite-q`'s doctests you will frequently see import paths beginning with `malachite_q::`. When using the `malachite` crate, replace this part of the paths with `malachite::`. The import path of the `Rational` type is shortened to `malachite::Rational`. # malachite-q This crate defines [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s. The name of this crate refers to the mathematical symbol for rational numbers, ℚ. - There are many functions defined on [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s. These include - All the ones you'd expect, like addition, subtraction, multiplication, and division; - Functions related to conversion between [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s and other kinds of numbers, including primitive floats; - Functions for Diophantine approximation; - Functions for expressing [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s in scientific notation. - The numerators and denominators of [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s are stored as [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s, so [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s with small numerators and denominators can be stored entirely on the stack. - Most arithmetic involving [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html)s requires (automatically) reducing the numerator and denominator. This is done very efficiently by using the high performance GCD and exact division algorithms implemented by [`Natural`](https://docs.rs/malachite-nz/latest/malachite_nz/natural/struct.Natural.html)s. # Demos and benchmarks This crate comes with a `bin` target that can be used for running demos and benchmarks. - Almost all of the public functions in this crate have an associated demo. Running a demo shows you a function's behavior on a large number of inputs. For example, to demo [`Rational`](https://docs.rs/malachite-q/latest/malachite_q/struct.Rational.html) addition, you can use the following command: ```text cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_rational_add ``` This command uses the `exhaustive` mode, which generates every possible input, generally starting with the simplest input and progressing to more complex ones. Another mode is `random`. The `-l` flag specifies how many inputs should be generated. - You can use a similar command to run benchmarks. The following command benchmarks various addition algorithms: ```text cargo run --features bin_build --release -- -l 1000000 -m random -b \ benchmark_rational_add_algorithms -o gcd-bench.gp ``` or GCD implementations of other libraries: ```text cargo run --features bin_build --release -- -l 1000000 -m random -b \ benchmark_rational_add_assign_library_comparison -o gcd-bench.gp ``` This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like so: ```text gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg ``` The list of available demos and benchmarks is not documented anywhere; you must find them by browsing through [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-q/src/bin_util/demo_and_bench). # Features - `32_bit_limbs`: Sets the type of `Limb` to [`u32`](https://doc.rust-lang.org/nightly/std/primitive.u32.html) instead of the default, [`u64`](https://doc.rust-lang.org/nightly/std/primitive.u64.html). - `random`: This feature provides some functions for randomly generating values. It is off by default to avoid pulling in some extra dependencies. - `enable_serde`: Enables serialization and deserialization using [serde](`https://serde.rs/`). - `test_build`: A large proportion of the code in this crate is only used for testing. For a typical user, building this code would result in an unnecessarily long compilation time and an unnecessarily large binary. My solution is to only build this code when the `test_build` feature is enabled. If you want to run unit tests, you must enable `test_build`. However, doctests don't require it, since they only test the public interface. Enabling this feature also enables `random`. - `bin_build`: This feature is used to build the code for demos and benchmarks, which also takes a long time to build. Enabling this feature also enables `test_build` and `random`. Malachite is developed by Mikhail Hogrefe. Thanks to b4D8, florian1345, konstin, Rowan Hart, YunWon Jeong, Park Joon-Kyu, Antonio Mamić, OliverNChalk, shekohex, and skycloudd for additional contributions. Copyright © 2026 Mikhail Hogrefe ================================================ FILE: malachite-q/katex-header.html ================================================ ================================================ FILE: malachite-q/rustfmt.toml ================================================ max_width = 100 array_width = 100 ================================================ FILE: malachite-q/src/arithmetic/abs.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; impl Abs for Rational { type Output = Self; /// Takes the absolute value of a [`Rational`], taking the [`Rational`] by value. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.abs(), 0); /// assert_eq!(Rational::from_signeds(22, 7).abs().to_string(), "22/7"); /// assert_eq!(Rational::from_signeds(-22, 7).abs().to_string(), "22/7"); /// ``` fn abs(mut self) -> Self { self.sign = true; self } } impl Abs for &Rational { type Output = Rational; /// Takes the absolute value of a [`Rational`], taking the [`Rational`] by reference. /// /// $$ /// f(x) = |x|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Abs; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::ZERO).abs(), 0); /// assert_eq!((&Rational::from_signeds(22, 7)).abs().to_string(), "22/7"); /// assert_eq!((&Rational::from_signeds(-22, 7)).abs().to_string(), "22/7"); /// ``` fn abs(self) -> Rational { Rational { sign: true, numerator: self.numerator.clone(), denominator: self.denominator.clone(), } } } impl AbsAssign for Rational { /// Replaces a [`Rational`] with its absolute value. /// /// $$ /// x \gets |x|. /// $$ /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x.abs_assign(); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.abs_assign(); /// assert_eq!(x.to_string(), "22/7"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.abs_assign(); /// assert_eq!(x.to_string(), "22/7"); /// ``` fn abs_assign(&mut self) { self.sign = true; } } ================================================ FILE: malachite-q/src/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991-2018, 2020 Free Software Foundation, Inc. // // 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 crate::Rational; use malachite_base::num::arithmetic::traits::{Abs, AbsAssign, AbsDiff, AbsDiffAssign}; impl AbsDiff for Rational { type Output = Self; /// Computes the absolute value of the difference between two [`Rational`]s, taking both by /// value. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiff; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF.abs_diff(Rational::ONE_HALF), 0); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .abs_diff(Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .abs_diff(Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// ``` #[inline] fn abs_diff(self, other: Self) -> Self { (self - other).abs() } } impl AbsDiff<&Self> for Rational { type Output = Self; /// Computes the absolute value of the difference between two [`Rational`]s, taking the first by /// value and the second by reference. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiff; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF.abs_diff(&Rational::ONE_HALF), 0); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .abs_diff(&Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .abs_diff(&Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// ``` #[inline] fn abs_diff(self, other: &Self) -> Self { (self - other).abs() } } impl AbsDiff for &Rational { type Output = Rational; /// Computes the absolute value of the difference between two [`Rational`]s, taking the first by /// reference and the second by value. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiff; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF.abs_diff(Rational::ONE_HALF), 0); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .abs_diff(Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .abs_diff(Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// ``` #[inline] fn abs_diff(self, other: Rational) -> Rational { (self - other).abs() } } impl AbsDiff<&Rational> for &Rational { type Output = Rational; /// Computes the absolute value of the difference between two [`Rational`]s, taking both by /// reference. /// /// $$ /// f(x, y) = |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiff; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF.abs_diff(Rational::ONE_HALF), 0); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .abs_diff(&Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .abs_diff(&Rational::from_signeds(99, 100)) /// .to_string(), /// "1507/700" /// ); /// ``` #[inline] fn abs_diff(self, other: &Rational) -> Rational { (self - other).abs() } } impl AbsDiffAssign for Rational { /// Subtracts a [`Rational`] by another [`Rational`] in place and takes the absolute value, /// taking the [`Rational`] on the right-hand side by value. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiffAssign; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x.abs_diff_assign(Rational::ONE_HALF); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.abs_diff_assign(Rational::from_signeds(99, 100)); /// assert_eq!(x.to_string(), "1507/700"); /// /// let mut x = Rational::from_signeds(99, 100); /// x.abs_diff_assign(Rational::from_signeds(22, 7)); /// assert_eq!(x.to_string(), "1507/700"); /// ``` #[inline] fn abs_diff_assign(&mut self, other: Self) { *self -= other; self.abs_assign(); } } impl<'a> AbsDiffAssign<&'a Self> for Rational { /// Subtracts a [`Rational`] by another [`Rational`] in place and takes the absolute value, /// taking the [`Rational`] on the right-hand side by reference. /// /// $$ /// x \gets |x - y|. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if `other` is greater than `self`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::AbsDiffAssign; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x.abs_diff_assign(&Rational::ONE_HALF); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.abs_diff_assign(&Rational::from_signeds(99, 100)); /// assert_eq!(x.to_string(), "1507/700"); /// /// let mut x = Rational::from_signeds(99, 100); /// x.abs_diff_assign(&Rational::from_signeds(22, 7)); /// assert_eq!(x.to_string(), "1507/700"); /// ``` #[inline] fn abs_diff_assign(&mut self, other: &'a Self) { *self -= other; self.abs_assign(); } } ================================================ FILE: malachite-q/src/arithmetic/add.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1994-1997, 2000, 2001, 2004, 2005 Free Software Foundation, Inc. // // 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 crate::Rational; use alloc::vec::Vec; use core::iter::Sum; use core::ops::{Add, AddAssign}; use malachite_base::num::arithmetic::traits::{ DivExact, DivExactAssign, Gcd, GcdAssign, UnsignedAbs, }; use malachite_base::num::basic::traits::Zero; use malachite_nz::integer::Integer; impl Add for Rational { type Output = Self; /// Adds two [`Rational`]s, taking both by value. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF + Rational::ONE_HALF, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) + Rational::from_signeds(99, 100)).to_string(), /// "2893/700" /// ); /// ``` fn add(self, other: Self) -> Self { if self == 0u32 { return other; } else if other == 0u32 { return self; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let sum_n = Integer::from_sign_and_abs(self.sign, self.numerator * &other.denominator) + Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); let sum_d = self.denominator * other.denominator; Self { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: sum_d, } } else { let reduced_self_d = (self.denominator).div_exact(&gcd); let sum_n = Integer::from_sign_and_abs( self.sign, self.numerator * (&other.denominator).div_exact(&gcd), ) + Integer::from_sign_and_abs(other.sign, other.numerator * &reduced_self_d); gcd.gcd_assign(sum_n.unsigned_abs_ref()); if gcd == 1u32 { Self { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: other.denominator * reduced_self_d, } } else { Self { sign: sum_n >= 0, numerator: sum_n.unsigned_abs().div_exact(&gcd), denominator: (other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl Add<&Self> for Rational { type Output = Self; /// Adds two [`Rational`]s, taking both by the first by value and the second by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF + &Rational::ONE_HALF, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) + &Rational::from_signeds(99, 100)).to_string(), /// "2893/700" /// ); /// ``` #[inline] fn add(self, other: &Self) -> Self { other + self } } impl Add for &Rational { type Output = Rational; /// Adds two [`Rational`]s, taking the first by reference and the second by value /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF + Rational::ONE_HALF, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) + Rational::from_signeds(99, 100)).to_string(), /// "2893/700" /// ); /// ``` fn add(self, other: Rational) -> Rational { if *self == 0u32 { return other; } else if other == 0u32 { return self.clone(); } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let sum_n = Integer::from_sign_and_abs(self.sign, &self.numerator * &other.denominator) + Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); let sum_d = &self.denominator * other.denominator; Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: sum_d, } } else { let reduced_self_d = (&self.denominator).div_exact(&gcd); let sum_n = Integer::from_sign_and_abs( self.sign, &self.numerator * (&other.denominator).div_exact(&gcd), ) + Integer::from_sign_and_abs(other.sign, other.numerator * &reduced_self_d); gcd.gcd_assign(sum_n.unsigned_abs_ref()); if gcd == 1u32 { Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: other.denominator * reduced_self_d, } } else { Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs().div_exact(&gcd), denominator: (other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl Add<&Rational> for &Rational { type Output = Rational; /// Adds two [`Rational`]s, taking both by reference. /// /// $$ /// f(x, y) = x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF + &Rational::ONE_HALF, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) + &Rational::from_signeds(99, 100)).to_string(), /// "2893/700" /// ); /// ``` fn add(self, other: &Rational) -> Rational { if *self == 0u32 { return other.clone(); } else if *other == 0u32 { return self.clone(); } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let sum_n = Integer::from_sign_and_abs(self.sign, &self.numerator * &other.denominator) + Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); let sum_d = &self.denominator * &other.denominator; Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: sum_d, } } else { let reduced_self_d = (&self.denominator).div_exact(&gcd); let sum_n = Integer::from_sign_and_abs( self.sign, &self.numerator * (&other.denominator).div_exact(&gcd), ) + Integer::from_sign_and_abs(other.sign, &other.numerator * &reduced_self_d); gcd.gcd_assign(sum_n.unsigned_abs_ref()); if gcd == 1u32 { Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs(), denominator: &other.denominator * reduced_self_d, } } else { Rational { sign: sum_n >= 0, numerator: sum_n.unsigned_abs().div_exact(&gcd), denominator: (&other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl AddAssign for Rational { /// Adds a [`Rational`] to a [`Rational`] in place, taking the [`Rational`] on the right-hand /// side by value. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x += Rational::ONE_HALF; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x += Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "2893/700"); /// ``` fn add_assign(&mut self, other: Self) { if *self == 0u32 { *self = other; return; } else if other == 0u32 { return; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { self.numerator *= &other.denominator; let sum_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) + Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); self.sign = sum_n >= 0; self.numerator = sum_n.unsigned_abs(); self.denominator *= other.denominator; } else { self.denominator.div_exact_assign(&gcd); self.numerator *= (&other.denominator).div_exact(&gcd); let sum_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) + Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); gcd.gcd_assign(sum_n.unsigned_abs_ref()); self.sign = sum_n >= 0; if gcd == 1u32 { self.numerator = sum_n.unsigned_abs(); self.denominator *= other.denominator; } else { self.numerator = sum_n.unsigned_abs().div_exact(&gcd); self.denominator *= (other.denominator).div_exact(gcd); } } } } impl AddAssign<&Self> for Rational { /// Adds a [`Rational`] to a [`Rational`] in place, taking the [`Rational`] on the right-hand /// side by reference. /// /// $$ /// x \gets x + y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x += &Rational::ONE_HALF; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x += &Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "2893/700"); /// ``` fn add_assign(&mut self, other: &Self) { if *self == 0u32 { self.clone_from(other); return; } else if *other == 0u32 { return; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { self.numerator *= &other.denominator; let sum_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) + Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); self.sign = sum_n >= 0; self.numerator = sum_n.unsigned_abs(); self.denominator *= &other.denominator; } else { self.denominator.div_exact_assign(&gcd); self.numerator *= (&other.denominator).div_exact(&gcd); let sum_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) + Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); gcd.gcd_assign(sum_n.unsigned_abs_ref()); self.sign = sum_n >= 0; if gcd == 1u32 { self.numerator = sum_n.unsigned_abs(); self.denominator *= &other.denominator; } else { self.numerator = sum_n.unsigned_abs().div_exact(&gcd); self.denominator *= (&other.denominator).div_exact(gcd); } } } } impl Sum for Rational { /// Adds up all the [`Rational`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^3 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Rational::sum(xs.map(Rational::significant_bits))`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// use std::iter::Sum; /// /// assert_eq!( /// Rational::sum( /// vec_from_str::("[0, 1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]") /// .unwrap() /// .into_iter() /// ) /// .to_string(), /// "19079/2520" /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate() { let mut s = x; for _ in 0..(i + 1).trailing_zeros() { s += stack.pop().unwrap(); } stack.push(s); } let mut s = Self::ZERO; for x in stack.into_iter().rev() { s += x; } s } } impl<'a> Sum<&'a Self> for Rational { /// Adds up all the [`Rational`]s in an iterator of [`Rational`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \sum_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^3 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Rational::sum(xs.map(Rational::significant_bits))`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// use std::iter::Sum; /// /// assert_eq!( /// Rational::sum( /// vec_from_str::("[0, 1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]") /// .unwrap() /// .iter() /// ) /// .to_string(), /// "19079/2520" /// ); /// ``` fn sum(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate() { let mut s = x.clone(); for _ in 0..(i + 1).trailing_zeros() { s += stack.pop().unwrap(); } stack.push(s); } let mut s = Self::ZERO; for x in stack.into_iter().rev() { s += x; } s } } ================================================ FILE: malachite-q/src/arithmetic/approximate.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::traits::{Approximate, ApproximateAssign}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{ AddMulAssign, DivMod, Floor, Parity, Reciprocal, ShrRound, UnsignedAbs, }; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; fn approximate_helper(q: &Rational, max_denominator: &Natural) -> Rational { let floor = q.floor(); let mut x = (q - Rational::from(&floor)).reciprocal(); let mut previous_numerator = Integer::ONE; let mut previous_denominator = Natural::ZERO; let mut numerator = floor; let mut denominator = Natural::ONE; let mut result = None; loop { let n; (n, x.numerator) = (&x.numerator).div_mod(&x.denominator); swap(&mut x.numerator, &mut x.denominator); let previous_previous_numerator = previous_numerator.clone(); let previous_previous_denominator = previous_denominator.clone(); previous_numerator.add_mul_assign(&numerator, Integer::from(&n)); previous_denominator.add_mul_assign(&denominator, &n); if previous_denominator > *max_denominator { previous_numerator = previous_previous_numerator; previous_denominator = previous_previous_denominator; // We need a term m such that previous_denominator + denominator * m is as large as // possible without exceeding max_denominator. let m = (max_denominator - &previous_denominator) / &denominator; let half_n = (&n).shr_round(1, Ceiling).0; if m < half_n { } else if m == half_n && n.even() { let previous_convergent = Rational { sign: numerator >= 0u32, numerator: (&numerator).unsigned_abs(), denominator: denominator.clone(), }; previous_numerator.add_mul_assign(&numerator, Integer::from(&m)); previous_denominator.add_mul_assign(&denominator, m); let candidate = Rational { sign: previous_numerator >= 0u32, numerator: previous_numerator.unsigned_abs(), denominator: previous_denominator, }; result = Some(if (q - &previous_convergent).lt_abs(&(q - &candidate)) { previous_convergent } else { candidate }); } else { numerator *= Integer::from(&m); numerator += previous_numerator; denominator *= m; denominator += previous_denominator; } break; } swap(&mut numerator, &mut previous_numerator); swap(&mut denominator, &mut previous_denominator); } let result = if let Some(result) = result { result } else { Rational { sign: numerator >= 0u32, numerator: numerator.unsigned_abs(), denominator, } }; // Suppose the input is (1/4, 2). The approximations 0 and 1/2 both satisfy the denominator // limit and are equidistant from 1/4, but we prefer 0 because it has the smaller denominator. // Unfortunately, the code above makes the wrong choice, so we need the following code to check // whether the approximation on the opposite side of `self` is better. let opposite: Rational = (q << 1) - &result; if result.denominator_ref() <= opposite.denominator_ref() { result } else { opposite } } impl Approximate for Rational { /// Finds the best approximation of a [`Rational`] using a denominator no greater than a /// specified maximum, taking the [`Rational`] by value. /// /// Let $f(x, d) = p/q$, with $p$ and $q$ relatively prime. Then the following properties hold: /// - $q \leq d$ /// - For all $n \in \Z$ and all $m \in \Z$ with $0 < m \leq d$, $|x - p/q| \leq |x - n/m|$. /// - If $|x - n/m| = |x - p/q|$, then $q \leq m$. /// - If $|x - n/q| = |x - p/q|$, then $p$ is even and $n$ is either equal to $p$ or odd. /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// - If `max_denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_nz::natural::Natural; /// use malachite_q::arithmetic::traits::Approximate; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::exact_from(std::f64::consts::PI) /// .approximate(&Natural::from(1000u32)) /// .to_string(), /// "355/113" /// ); /// assert_eq!( /// Rational::from_signeds(333i32, 1000) /// .approximate(&Natural::from(100u32)) /// .to_string(), /// "1/3" /// ); /// ``` /// /// # Implementation notes /// This algorithm follows the description in /// . One part of /// the algorithm not mentioned in that article is that if the last term $n$ in the continued /// fraction needs to be reduced, the optimal replacement term $m$ may be found using division. fn approximate(self, max_denominator: &Natural) -> Rational { assert_ne!(*max_denominator, 0); if self.denominator_ref() <= max_denominator { return self; } if *max_denominator == 1u32 { return Self::from(Integer::rounding_from(self, Nearest).0); } approximate_helper(&self, max_denominator) } } impl Approximate for &Rational { /// Finds the best approximation of a [`Rational`] using a denominator no greater than a /// specified maximum, taking the [`Rational`] by reference. /// /// Let $f(x, d) = p/q$, with $p$ and $q$ relatively prime. Then the following properties hold: /// - $q \leq d$ /// - For all $n \in \Z$ and all $m \in \Z$ with $0 < m \leq d$, $|x - p/q| \leq |x - n/m|$. /// - If $|x - n/m| = |x - p/q|$, then $q \leq m$. /// - If $|x - n/q| = |x - p/q|$, then $p$ is even and $n$ is either equal to $p$ or odd. /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// - If `max_denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_nz::natural::Natural; /// use malachite_q::arithmetic::traits::Approximate; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::exact_from(std::f64::consts::PI)) /// .approximate(&Natural::from(1000u32)) /// .to_string(), /// "355/113" /// ); /// assert_eq!( /// (&Rational::from_signeds(333i32, 1000)) /// .approximate(&Natural::from(100u32)) /// .to_string(), /// "1/3" /// ); /// ``` /// /// # Implementation notes /// This algorithm follows the description in /// . One part of /// the algorithm not mentioned in that article is that if the last term $n$ in the continued /// fraction needs to be reduced, the optimal replacement term $m$ may be found using division. fn approximate(self, max_denominator: &Natural) -> Rational { assert_ne!(*max_denominator, 0); if self.denominator_ref() <= max_denominator { return self.clone(); } if *max_denominator == 1u32 { return Rational::from(Integer::rounding_from(self, Nearest).0); } approximate_helper(self, max_denominator) } } impl ApproximateAssign for Rational { /// Finds the best approximation of a [`Rational`] using a denominator no greater than a /// specified maximum, mutating the [`Rational`] in place. /// /// See [`Rational::approximate`] for more information. /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// - If `max_denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_nz::natural::Natural; /// use malachite_q::arithmetic::traits::ApproximateAssign; /// use malachite_q::Rational; /// /// let mut x = Rational::exact_from(std::f64::consts::PI); /// x.approximate_assign(&Natural::from(1000u32)); /// assert_eq!(x.to_string(), "355/113"); /// /// let mut x = Rational::from_signeds(333i32, 1000); /// x.approximate_assign(&Natural::from(100u32)); /// assert_eq!(x.to_string(), "1/3"); /// ``` fn approximate_assign(&mut self, max_denominator: &Natural) { assert_ne!(*max_denominator, 0); if self.denominator_ref() <= max_denominator { } else if *max_denominator == 1u32 { *self = Self::from(Integer::rounding_from(&*self, Nearest).0); } else { *self = approximate_helper(&*self, max_denominator); } } } ================================================ FILE: malachite-q/src/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::mem::swap; use malachite_base::num::arithmetic::traits::{Ceiling, CeilingAssign, DivRound, DivRoundAssign}; use malachite_base::num::basic::traits::One; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl Ceiling for Rational { type Output = Integer; /// Finds the ceiling of a [`Rational`], taking the [`Rational`] by value. /// /// $$ /// f(x) = \lceil x \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Ceiling; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.ceiling(), 0); /// assert_eq!(Rational::from_signeds(22, 7).ceiling(), 4); /// assert_eq!(Rational::from_signeds(-22, 7).ceiling(), -3); /// ``` fn ceiling(self) -> Integer { if self.sign { Integer::from(self.numerator.div_round(self.denominator, Ceiling).0) } else { Integer::from_sign_and_abs(false, self.numerator / self.denominator) } } } impl Ceiling for &Rational { type Output = Integer; /// Finds the ceiling of a [`Rational`], taking the [`Rational`] by reference. /// /// $$ /// f(x) = \lceil x \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Ceiling; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::ZERO).ceiling(), 0); /// assert_eq!((&Rational::from_signeds(22, 7)).ceiling(), 4); /// assert_eq!((&Rational::from_signeds(-22, 7)).ceiling(), -3); /// ``` fn ceiling(self) -> Integer { if self.sign { Integer::from((&self.numerator).div_round(&self.denominator, Ceiling).0) } else { Integer::from_sign_and_abs(false, &self.numerator / &self.denominator) } } } impl CeilingAssign for Rational { /// Replaces a [`Rational`] with its ceiling. /// /// $$ /// x \gets \lceil x \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x.ceiling_assign(); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.ceiling_assign(); /// assert_eq!(x, 4); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.ceiling_assign(); /// assert_eq!(x, -3); /// ``` fn ceiling_assign(&mut self) { let mut d = Natural::ONE; swap(&mut self.denominator, &mut d); if self.sign { self.numerator.div_round_assign(d, Ceiling); } else { self.numerator /= d; if !self.sign && self.numerator == 0 { self.sign = true; } } } } ================================================ FILE: malachite-q/src/arithmetic/denominators_in_closed_interval.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::traits::{DenominatorsInClosedInterval, SimplestRationalInInterval}; use crate::exhaustive::{ exhaustive_rationals_with_denominator_inclusive_range, exhaustive_rationals_with_denominator_range, }; use alloc::collections::BTreeSet; use malachite_base::num::arithmetic::traits::{Ceiling, Reciprocal, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::factorization::traits::Primes; use malachite_nz::natural::Natural; use malachite_nz::platform::Limb; // Returns a k such that for all n >= k, any closed interval with the given diameter is guaranteed // to contain rationals with (reduced) denominator n. fn smallest_guaranteed_denominator(interval_diameter: &Rational) -> Natural { if *interval_diameter >= 1u32 { return Natural::ONE; } let mut primorial = Natural::TWO; let mut pow = Natural::TWO; for p in Limb::primes().skip(1) { primorial *= Natural::from(p); pow <<= 1; let limit = Rational::from_naturals_ref(&pow, &primorial); if *interval_diameter >= limit { return primorial; } } panic!(); } fn smallest_likely_denominator(interval_diameter: &Rational) -> Natural { interval_diameter.reciprocal().ceiling().unsigned_abs() } /// Returns an iterator of all denominators that appear in the [`Rational`]s contained in a closed /// interval. /// /// This `struct` is created by [`DenominatorsInClosedInterval::denominators_in_closed_interval`]; /// see its documentation for more. #[derive(Clone, Debug)] pub struct DenominatorsInClosedRationalInterval { a: Rational, b: Rational, low_threshold: Natural, high_threshold: Natural, current: Natural, points: BTreeSet, } impl Iterator for DenominatorsInClosedRationalInterval { type Item = Natural; fn next(&mut self) -> Option { if self.current >= self.high_threshold { self.points.clear(); self.current += Natural::ONE; Some(self.current.clone()) } else if self.current >= self.low_threshold { self.points.clear(); loop { self.current += Natural::ONE; if exhaustive_rationals_with_denominator_inclusive_range( self.current.clone(), self.a.clone(), self.b.clone(), ) .next() .is_some() { return Some(self.current.clone()); } } } else if self.points.is_empty() { assert_eq!(self.current, 0u32); self.points.insert(self.a.clone()); self.points.insert(self.b.clone()); self.points .insert(Rational::simplest_rational_in_open_interval( &self.a, &self.b, )); let mut min_denominator = self.a.denominator_ref(); for p in &self.points { let pd = p.denominator_ref(); if pd < min_denominator { min_denominator = pd; } } self.current = min_denominator.clone(); for p in exhaustive_rationals_with_denominator_range( self.current.clone(), self.a.clone(), self.b.clone(), ) { self.points.insert(p); } Some(self.current.clone()) } else { let mut previous_point = None; let mut min_interior_denominator = None; for p in &self.points { if let Some(previous) = previous_point { let interior_denominator = Rational::simplest_rational_in_open_interval(previous, p) .into_denominator(); if let Some(previous_min) = min_interior_denominator.as_ref() { if interior_denominator < *previous_min { min_interior_denominator = Some(interior_denominator); } } else { min_interior_denominator = Some(interior_denominator); } } previous_point = Some(p); } let min_interior_denominator = min_interior_denominator.unwrap(); assert!(min_interior_denominator > self.current); let mut min_denominator = min_interior_denominator; for p in &self.points { let pd = p.denominator_ref(); if *pd > self.current && *pd < min_denominator { min_denominator = pd.clone(); } } self.current = min_denominator; for p in exhaustive_rationals_with_denominator_range( self.current.clone(), self.a.clone(), self.b.clone(), ) { self.points.insert(p); } Some(self.current.clone()) } } } impl DenominatorsInClosedInterval for Rational { type Denominators = DenominatorsInClosedRationalInterval; /// Returns an iterator of all denominators that appear in the [`Rational`]s contained in a /// closed interval. /// /// For example, consider the interval $[1/3, 1/2]$. It contains no integers, so no /// [`Rational`]s with denominator 1. It does contain [`Rational`]s with denominators 2 and 3 /// (the endpoints). It contains none with denominator 4, but it does contain $2/5$. It contains /// none with denominator 6 (though $1/3$ and $1/2$ are $2/6$ and $3/6$, those representations /// are not reduced). It contains $3/7$, $3/8$, and $4/9$ but none with denominator 10 ($0.4$ /// does not count because it is $2/5$). It contains all denominators greater than 10, so the /// complete list is $2, 3, 5, 7, 8, 9, 11, 12, 13, \ldots$. /// /// # Worst-case complexity per iteration /// $T(n, i) = O(n + \log i)$ /// /// $M(n, i) = O(n + \log i)$ /// /// where $T$ is time, $M$ is additional memory, $i$ is the iteration number, and $n$ is /// `max(a.significant_bits(), b.significant_bits())`. /// /// # Panics /// Panics if $a \geq b$. /// /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::basic::traits::{One, Two}; /// use malachite_q::arithmetic::traits::DenominatorsInClosedInterval; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// Rational::denominators_in_closed_interval(Rational::ONE, Rational::TWO), /// 20 /// ), /// "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// Rational::denominators_in_closed_interval( /// Rational::from_signeds(1, 3), /// Rational::from_signeds(1, 2) /// ), /// 20 /// ), /// "[2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// Rational::denominators_in_closed_interval( /// Rational::from_signeds(1, 1000001), /// Rational::from_signeds(1, 1000000) /// ), /// 20 /// ), /// "[1000000, 1000001, 2000001, 3000001, 3000002, 4000001, 4000003, 5000001, 5000002, \ /// 5000003, 5000004, 6000001, 6000005, 7000001, 7000002, 7000003, 7000004, 7000005, \ /// 7000006, 8000001, ...]" /// ); /// ``` fn denominators_in_closed_interval( a: Rational, b: Rational, ) -> DenominatorsInClosedRationalInterval { assert!(a < b); let diameter = &b - &a; let (mut low_threshold, high_threshold) = if diameter >= 1u32 { (Natural::ZERO, Natural::ZERO) } else { ( smallest_likely_denominator(&diameter), smallest_guaranteed_denominator(&diameter), ) }; if low_threshold < 100u32 { low_threshold = Natural::ZERO; } DenominatorsInClosedRationalInterval { a, b, low_threshold, high_threshold, current: Natural::ZERO, points: BTreeSet::new(), } } } ================================================ FILE: malachite-q/src/arithmetic/div.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // CheckedDiv implementation by Park Joon-Kyu. // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1994-1996, 2000, 2001, 2015, 2018 Free Software Foundation, Inc. // // 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 crate::Rational; use core::ops::{Div, DivAssign}; use malachite_base::num::arithmetic::traits::{ CheckedDiv, DivExact, DivExactAssign, Gcd, Reciprocal, }; use malachite_base::num::basic::traits::Zero; impl Div for Rational { type Output = Self; /// Divides a [`Rational`] by another [`Rational`], taking both by value. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// assert_eq!(Rational::TWO / Rational::TWO, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) / Rational::from_signeds(99, 100)).to_string(), /// "200/63" /// ); /// ``` fn div(self, other: Self) -> Self { if other == 0u32 { panic!("division by zero"); } else if self == 0u32 { return Self::ZERO; } else if self == 1u32 { return other.reciprocal(); } else if other == 1u32 { return self; } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Self { sign: self.sign == other.sign, numerator: (self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2), denominator: (other.numerator).div_exact(g_1) * (self.denominator).div_exact(g_2), } } } impl Div<&Self> for Rational { type Output = Self; /// Divides a [`Rational`] by another [`Rational`], taking the first by value and the second by /// reference. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// assert_eq!(Rational::TWO / &Rational::TWO, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) / &Rational::from_signeds(99, 100)).to_string(), /// "200/63" /// ); /// ``` #[inline] fn div(self, other: &Self) -> Self { if *other == 0u32 { panic!("division by zero"); } else if self == 0u32 { Self::ZERO } else { (other / self).reciprocal() } } } impl Div for &Rational { type Output = Rational; /// Divides a [`Rational`] by another [`Rational`], taking the first by reference and the second /// by value. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::TWO / Rational::TWO, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) / Rational::from_signeds(99, 100)).to_string(), /// "200/63" /// ); /// ``` fn div(self, other: Rational) -> Rational { if other == 0u32 { panic!("division by zero"); } else if *self == 0u32 { return Rational::ZERO; } else if *self == 1u32 { return other.reciprocal(); } else if other == 1u32 { return self.clone(); } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2), denominator: (other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2), } } } impl Div<&Rational> for &Rational { type Output = Rational; /// Divides a [`Rational`] by another [`Rational`], taking both by reference. /// /// $$ /// f(x, y) = \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::TWO / &Rational::TWO, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) / &Rational::from_signeds(99, 100)).to_string(), /// "200/63" /// ); /// ``` fn div(self, other: &Rational) -> Rational { if *other == 0u32 { panic!("division by zero"); } else if *self == 0u32 { return Rational::ZERO; } else if *self == 1u32 { return other.reciprocal(); } else if *other == 1u32 { return self.clone(); } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (&other.denominator).div_exact(&g_2), denominator: (&other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2), } } } impl CheckedDiv for Rational { type Output = Self; /// Divides a [`Rational`] by another [`Rational`], taking both by value. Returns `None` when /// the second [`Rational`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_q::Rational; /// /// assert_eq!(Rational::TWO.checked_div(Rational::TWO).unwrap(), 1); /// assert_eq!(Rational::TWO.checked_div(Rational::ZERO), None); /// assert_eq!( /// (Rational::from_signeds(22, 7).checked_div(Rational::from_signeds(99, 100))) /// .unwrap() /// .to_string(), /// "200/63" /// ); /// ``` fn checked_div(self, other: Self) -> Option { if other == 0u32 { return None; } else if self == 0u32 { return Some(Self::ZERO); } else if self == 1u32 { return Some(other.reciprocal()); } else if other == 1u32 { return Some(self); } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Some(Self { sign: self.sign == other.sign, numerator: (self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2), denominator: (other.numerator).div_exact(g_1) * (self.denominator).div_exact(g_2), }) } } impl CheckedDiv<&Self> for Rational { type Output = Self; /// Divides a [`Rational`] by another [`Rational`], taking the first by value and the second by /// reference. Returns `None` when the second [`Rational`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_q::Rational; /// /// assert_eq!(Rational::TWO.checked_div(&Rational::TWO).unwrap(), 1); /// assert_eq!(Rational::TWO.checked_div(&Rational::ZERO), None); /// assert_eq!( /// (Rational::from_signeds(22, 7).checked_div(&Rational::from_signeds(99, 100))) /// .unwrap() /// .to_string(), /// "200/63" /// ); /// ``` #[inline] fn checked_div(self, other: &Self) -> Option { if other == &0u32 { None } else if self == 0u32 { Some(Self::ZERO) } else { (other.checked_div(self)).map(Self::reciprocal) } } } impl CheckedDiv for &Rational { type Output = Rational; /// Divides a [`Rational`] by another [`Rational`], taking the first by reference and the second /// by value. Returns `None` when the second [`Rational`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::TWO).checked_div(Rational::TWO).unwrap(), 1); /// assert_eq!((&Rational::TWO).checked_div(Rational::ZERO), None); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .checked_div(Rational::from_signeds(99, 100)) /// .unwrap() /// .to_string(), /// "200/63" /// ); /// ``` fn checked_div(self, other: Rational) -> Option { if other == 0u32 { return None; } else if *self == 0u32 { return Some(Rational::ZERO); } else if *self == 1u32 { return Some(other.reciprocal()); } else if other == 1u32 { return Some(self.clone()); } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Some(Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (other.denominator).div_exact(&g_2), denominator: (other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2), }) } } impl CheckedDiv<&Rational> for &Rational { type Output = Rational; /// Divides a [`Rational`] by another [`Rational`], taking both by reference. Returns `None` /// when the second [`Rational`] is zero, `Some` otherwise. /// /// $$ /// f(x, y) = \begin{cases} /// \operatorname{Some}\left ( \frac{x}{y} \right ) & \text{if} \\quad y \neq 0 \\\\ /// \text{None} & \text{otherwise} /// \end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedDiv; /// use malachite_base::num::basic::traits::{Two, Zero}; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::TWO).checked_div(&Rational::TWO).unwrap(), 1); /// assert_eq!((&Rational::TWO).checked_div(&Rational::ZERO), None); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .checked_div(&Rational::from_signeds(99, 100)) /// .unwrap() /// .to_string(), /// "200/63" /// ); /// ``` fn checked_div(self, other: &Rational) -> Option { if *other == 0u32 { return None; } else if *self == 0u32 { return Some(Rational::ZERO); } else if *self == 1u32 { return Some(other.reciprocal()); } else if *other == 1u32 { return Some(self.clone()); } let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); Some(Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (&other.denominator).div_exact(&g_2), denominator: (&other.numerator).div_exact(g_1) * (&self.denominator).div_exact(g_2), }) } } impl DivAssign for Rational { /// Divides a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the right-hand /// side by value. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// let mut x = Rational::TWO; /// x /= Rational::TWO; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x /= Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "200/63"); /// ``` fn div_assign(&mut self, other: Self) { if other == 0u32 { panic!("division by zero"); } else if *self == 0u32 || other == 1u32 { return; } else if *self == 1u32 { *self = other.reciprocal(); return; } self.sign = self.sign == other.sign; let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); self.numerator.div_exact_assign(&g_1); self.denominator.div_exact_assign(&g_2); self.numerator *= (other.denominator).div_exact(g_2); self.denominator *= (other.numerator).div_exact(g_1); } } impl DivAssign<&Self> for Rational { /// Divides a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the right-hand /// side by reference. /// /// $$ /// x \gets \frac{x}{y}. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Panics /// Panics if the second [`Rational`] is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Two; /// use malachite_q::Rational; /// /// let mut x = Rational::TWO; /// x /= &Rational::TWO; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x /= &Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "200/63"); /// ``` fn div_assign(&mut self, other: &Self) { if *other == 0u32 { panic!("division by zero"); } else if *self == 0u32 || *other == 1u32 { return; } else if *self == 1u32 { *self = other.reciprocal(); return; } self.sign = self.sign == other.sign; let g_1 = (&self.numerator).gcd(&other.numerator); let g_2 = (&other.denominator).gcd(&self.denominator); self.numerator.div_exact_assign(&g_1); self.denominator.div_exact_assign(&g_2); self.numerator *= (&other.denominator).div_exact(g_2); self.denominator *= (&other.numerator).div_exact(g_1); } } ================================================ FILE: malachite-q/src/arithmetic/floor.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::mem::swap; use malachite_base::num::arithmetic::traits::{DivRound, DivRoundAssign, Floor, FloorAssign}; use malachite_base::num::basic::traits::One; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl Floor for Rational { type Output = Integer; /// Finds the floor of a [`Rational`], taking the [`Rational`] by value. /// /// $$ /// f(x) = \lfloor x \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Floor; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.floor(), 0); /// assert_eq!(Rational::from_signeds(22, 7).floor(), 3); /// assert_eq!(Rational::from_signeds(-22, 7).floor(), -4); /// ``` fn floor(self) -> Integer { if self.sign { Integer::from(self.numerator / self.denominator) } else { Integer::from_sign_and_abs(false, self.numerator.div_round(self.denominator, Ceiling).0) } } } impl Floor for &Rational { type Output = Integer; /// Finds the floor of a [`Rational`], taking the [`Rational`] by reference. /// /// $$ /// f(x) = \lfloor x \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Floor; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::ZERO).floor(), 0); /// assert_eq!((&Rational::from_signeds(22, 7)).floor(), 3); /// assert_eq!((&Rational::from_signeds(-22, 7)).floor(), -4); /// ``` fn floor(self) -> Integer { if self.sign { Integer::from(&self.numerator / &self.denominator) } else { Integer::from_sign_and_abs( false, (&self.numerator).div_round(&self.denominator, Ceiling).0, ) } } } impl FloorAssign for Rational { /// Replaces a [`Rational`] with its floor. /// /// $$ /// x \gets \lfloor x \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x.floor_assign(); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.floor_assign(); /// assert_eq!(x, 3); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.floor_assign(); /// assert_eq!(x, -4); /// ``` fn floor_assign(&mut self) { let mut d = Natural::ONE; swap(&mut self.denominator, &mut d); if self.sign { self.numerator /= d; } else { self.numerator.div_round_assign(d, Ceiling); if !self.sign && self.numerator == 0 { self.sign = true; } } } } ================================================ FILE: malachite-q/src/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::IsPowerOf2; impl IsPowerOf2 for Rational { /// Determines whether a [`Rational`] is an integer power of 2. /// /// $f(x) = (\exists n \in \Z : 2^n = x)$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::IsPowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(0x80).is_power_of_2(), true); /// assert_eq!(Rational::from_signeds(1, 8).is_power_of_2(), true); /// assert_eq!(Rational::from_signeds(-1, 8).is_power_of_2(), false); /// assert_eq!(Rational::from_signeds(22, 7).is_power_of_2(), false); /// ``` fn is_power_of_2(&self) -> bool { self.sign && (self.denominator == 1u32 && self.numerator.is_power_of_2() || self.numerator == 1u32 && self.denominator.is_power_of_2()) } } ================================================ FILE: malachite-q/src/arithmetic/log_base.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the FLINT Library. // // Copyright (C) 2011 Fredrik Johansson // // 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 crate::Rational; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBasePowerOf2, CheckedLogBase, CheckedLogBase2, CheckedLogBasePowerOf2, FloorLogBase, FloorLogBasePowerOf2, Pow, }; use malachite_base::num::comparison::traits::OrdAbs; use malachite_base::num::conversion::traits::{RoundingFrom, SciMantissaAndExponent}; use malachite_base::rounding_modes::RoundingMode::*; fn approx_log_helper(x: &Rational) -> f64 { let (mantissa, exponent): (f64, i64) = x.sci_mantissa_and_exponent(); mantissa.ln() + (exponent as f64) * core::f64::consts::LN_2 } impl Rational { /// Calculates the approximate natural logarithm of a positive [`Rational`]. /// /// $f(x) = (1+\varepsilon)(\log x)$, where $|\varepsilon| < 2^{-52}.$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::{Pow, PowerOf2}; /// use malachite_base::num::float::NiceFloat; /// use malachite_q::Rational; /// /// assert_eq!( /// NiceFloat(Rational::from(10i32).approx_log()), /// NiceFloat(2.3025850929940455) /// ); /// assert_eq!( /// NiceFloat(Rational::from(10i32).pow(100u64).approx_log()), /// NiceFloat(230.25850929940455) /// ); /// assert_eq!( /// NiceFloat(Rational::power_of_2(1000000u64).approx_log()), /// NiceFloat(693147.1805599453) /// ); /// assert_eq!( /// NiceFloat(Rational::power_of_2(-1000000i64).approx_log()), /// NiceFloat(-693147.1805599453) /// ); /// ``` /// /// This is equivalent to `fmpz_dlog` from `fmpz/dlog.c`, FLINT 2.7.1. #[inline] pub fn approx_log(&self) -> f64 { assert!(*self > 0u32); approx_log_helper(self) } } // # Worst-case complexity // $T(n, m) = O(nm \log (nm) \log\log (nm))$ // // $M(n, m) = O(nm \log (nm))$ // // where $T$ is time, $M$ is additional memory, $n$ is `base.significant_bits()`, and $m$ is // $|\log_b x|$, where $b$ is `base` and $x$ is `x`. pub(crate) fn log_base_helper(x: &Rational, base: &Rational) -> (i64, bool) { assert!(*base > 0u32); assert_ne!(*base, 1u32); if *x == 1u32 { return (0, true); } let mut log = i64::rounding_from(approx_log_helper(x) / approx_log_helper(base), Floor).0; let mut power = base.pow(log); if *base > 1u32 { match power.cmp_abs(x) { Equal => (log, true), Less => loop { power *= base; match power.cmp_abs(x) { Equal => { return (log + 1, true); } Less => { log += 1; } Greater => { return (log, false); } } }, Greater => loop { power /= base; match power.cmp_abs(x) { Equal => { return (log - 1, true); } Less => { return (log - 1, false); } Greater => { log -= 1; } } }, } } else { match power.cmp_abs(x) { Equal => (log, true), Less => loop { power /= base; match power.cmp_abs(x) { Equal => { return (log - 1, true); } Less => { log -= 1; } Greater => { return (log - 1, false); } } }, Greater => loop { power *= base; match power.cmp_abs(x) { Equal => { return (log + 1, true); } Less => { return (log, false); } Greater => { log += 1; } } }, } } } impl FloorLogBase<&Rational> for &Rational { type Output = i64; /// Returns the floor of the base-$b$ logarithm of a positive [`Rational`]. /// /// Note that this function may be slow if the base is very close to 1. /// /// $f(x, b) = \lfloor\log_b x\rfloor$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `base.significant_bits()`, and $m$ is /// $|\log_b x|$, where $b$ is `base` and $x$ is `x`. /// /// # Panics /// Panics if `self` less than or equal to zero or `base` is 1. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(80u32).floor_log_base(&Rational::from(3u32)), /// 3 /// ); /// assert_eq!( /// Rational::from(81u32).floor_log_base(&Rational::from(3u32)), /// 4 /// ); /// assert_eq!( /// Rational::from(82u32).floor_log_base(&Rational::from(3u32)), /// 4 /// ); /// assert_eq!( /// Rational::from(4294967296u64).floor_log_base(&Rational::from(10u32)), /// 9 /// ); /// assert_eq!( /// Rational::from_signeds(936851431250i64, 1397).floor_log_base(&Rational::from(10u32)), /// 8 /// ); /// assert_eq!( /// Rational::from_signeds(5153632, 16807).floor_log_base(&Rational::from_signeds(22, 7)), /// 5 /// ); /// ``` fn floor_log_base(self, base: &Rational) -> i64 { assert!(*self > 0u32); if let Some(log_base) = base.checked_log_base_2() { return self.floor_log_base_power_of_2(log_base); } log_base_helper(self, base).0 } } impl CeilingLogBase<&Rational> for &Rational { type Output = i64; /// Returns the ceiling of the base-$b$ logarithm of a positive [`Rational`]. /// /// Note that this function may be slow if the base is very close to 1. /// /// $f(x, b) = \lceil\log_b x\rceil$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `base.significant_bits()`, and $m$ is /// $|\log_b x|$, where $b$ is `base` and $x$ is `x`. /// /// # Panics /// Panics if `self` less than or equal to zero or `base` is 1. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(80u32).ceiling_log_base(&Rational::from(3u32)), /// 4 /// ); /// assert_eq!( /// Rational::from(81u32).ceiling_log_base(&Rational::from(3u32)), /// 4 /// ); /// assert_eq!( /// Rational::from(82u32).ceiling_log_base(&Rational::from(3u32)), /// 5 /// ); /// assert_eq!( /// Rational::from(4294967296u64).ceiling_log_base(&Rational::from(10u32)), /// 10 /// ); /// assert_eq!( /// Rational::from_signeds(936851431250i64, 1397).ceiling_log_base(&Rational::from(10u32)), /// 9 /// ); /// assert_eq!( /// Rational::from_signeds(5153632, 16807).ceiling_log_base(&Rational::from_signeds(22, 7)), /// 5 /// ); /// ``` fn ceiling_log_base(self, base: &Rational) -> i64 { assert!(*self > 0u32); if let Some(log_base) = base.checked_log_base_2() { return self.ceiling_log_base_power_of_2(log_base); } let (log, exact) = log_base_helper(self, base); if exact { log } else { log + 1 } } } impl CheckedLogBase<&Rational> for &Rational { type Output = i64; /// Returns the base-$b$ logarithm of a positive [`Rational`]. If the [`Rational`] is not a /// power of $b$, then `None` is returned. /// /// Note that this function may be slow if the base is very close to 1. /// /// $$ /// f(x, b) = \\begin{cases} /// \operatorname{Some}(\log_b x) & \text{if} \\quad \log_b x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `base.significant_bits()`, and $m$ is /// $|\log_b x|$, where $b$ is `base` and $x$ is `x`. /// /// # Panics /// Panics if `self` less than or equal to zero or `base` is 1. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBase; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(80u32).checked_log_base(&Rational::from(3u32)), /// None /// ); /// assert_eq!( /// Rational::from(81u32).checked_log_base(&Rational::from(3u32)), /// Some(4) /// ); /// assert_eq!( /// Rational::from(82u32).checked_log_base(&Rational::from(3u32)), /// None /// ); /// assert_eq!( /// Rational::from(4294967296u64).checked_log_base(&Rational::from(10u32)), /// None /// ); /// assert_eq!( /// Rational::from_signeds(936851431250i64, 1397).checked_log_base(&Rational::from(10u32)), /// None /// ); /// assert_eq!( /// Rational::from_signeds(5153632, 16807).checked_log_base(&Rational::from_signeds(22, 7)), /// Some(5) /// ); /// ``` fn checked_log_base(self, base: &Rational) -> Option { assert!(*self > 0u32); if let Some(log_base) = base.checked_log_base_2() { return self.checked_log_base_power_of_2(log_base); } let (log, exact) = log_base_helper(self, base); if exact { Some(log) } else { None } } } ================================================ FILE: malachite-q/src/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, CheckedLogBase2, FloorLogBase2, IsPowerOf2, }; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; impl Rational { /// Returns the floor of the base-2 logarithm of the absolute value of a nonzero [`Rational`]. /// /// $f(x) = \lfloor\log_2 |x|\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is zero. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(3u32).floor_log_base_2_abs(), 1); /// assert_eq!(Rational::from_signeds(1, 3).floor_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(1, 4).floor_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(1, 5).floor_log_base_2_abs(), -3); /// /// assert_eq!(Rational::from(-3).floor_log_base_2_abs(), 1); /// assert_eq!(Rational::from_signeds(-1, 3).floor_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(-1, 4).floor_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(-1, 5).floor_log_base_2_abs(), -3); /// ``` pub fn floor_log_base_2_abs(&self) -> i64 { let exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Less { exponent - 1 } else { exponent } } /// Returns the ceiling of the base-2 logarithm of the absolute value of a nonzero [`Rational`]. /// /// $f(x) = \lfloor\log_2 |x|\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` less than or equal to zero. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(3u32).ceiling_log_base_2_abs(), 2); /// assert_eq!(Rational::from_signeds(1, 3).ceiling_log_base_2_abs(), -1); /// assert_eq!(Rational::from_signeds(1, 4).ceiling_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(1, 5).ceiling_log_base_2_abs(), -2); /// /// assert_eq!(Rational::from(-3).ceiling_log_base_2_abs(), 2); /// assert_eq!(Rational::from_signeds(-1, 3).ceiling_log_base_2_abs(), -1); /// assert_eq!(Rational::from_signeds(-1, 4).ceiling_log_base_2_abs(), -2); /// assert_eq!(Rational::from_signeds(-1, 5).ceiling_log_base_2_abs(), -2); /// ``` pub fn ceiling_log_base_2_abs(&self) -> i64 { let exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Greater { exponent + 1 } else { exponent } } } impl FloorLogBase2 for &Rational { type Output = i64; /// Returns the floor of the base-2 logarithm of a positive [`Rational`]. /// /// $f(x) = \lfloor\log_2 x\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBase2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(3u32).floor_log_base_2(), 1); /// assert_eq!(Rational::from_signeds(1, 3).floor_log_base_2(), -2); /// assert_eq!(Rational::from_signeds(1, 4).floor_log_base_2(), -2); /// assert_eq!(Rational::from_signeds(1, 5).floor_log_base_2(), -3); /// ``` #[inline] fn floor_log_base_2(self) -> i64 { assert!(*self > 0u32); self.floor_log_base_2_abs() } } impl CeilingLogBase2 for &Rational { type Output = i64; /// Returns the ceiling of the base-2 logarithm of a positive [`Rational`]. /// /// $f(x) = \lfloor\log_2 x\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBase2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(3u32).ceiling_log_base_2(), 2); /// assert_eq!(Rational::from_signeds(1, 3).ceiling_log_base_2(), -1); /// assert_eq!(Rational::from_signeds(1, 4).ceiling_log_base_2(), -2); /// assert_eq!(Rational::from_signeds(1, 5).ceiling_log_base_2(), -2); /// ``` #[inline] fn ceiling_log_base_2(self) -> i64 { assert!(*self > 0u32); self.ceiling_log_base_2_abs() } } impl CheckedLogBase2 for &Rational { type Output = i64; /// Returns the base-2 logarithm of a positive [`Rational`]. If the [`Rational`] is not a power /// of 2, then `None` is returned. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(\log_2 x) & \text{if} \\quad \log_2 x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBase2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(3u32).checked_log_base_2(), None); /// assert_eq!(Rational::from_signeds(1, 3).checked_log_base_2(), None); /// assert_eq!(Rational::from_signeds(1, 4).checked_log_base_2(), Some(-2)); /// assert_eq!(Rational::from_signeds(1, 5).checked_log_base_2(), None); /// ``` fn checked_log_base_2(self) -> Option { assert!(*self > 0u32); if self.denominator == 1u32 && self.numerator.is_power_of_2() { Some(i64::exact_from(self.numerator.significant_bits()) - 1) } else if self.numerator == 1u32 && self.denominator.is_power_of_2() { Some(1 - i64::exact_from(self.denominator.significant_bits())) } else { None } } } ================================================ FILE: malachite-q/src/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{ CeilingLogBase2, CeilingLogBasePowerOf2, CheckedLogBase2, CheckedLogBasePowerOf2, DivMod, DivRound, FloorLogBase2, FloorLogBasePowerOf2, Sign, }; use malachite_base::rounding_modes::RoundingMode::*; impl FloorLogBasePowerOf2 for &Rational { type Output = i64; /// Returns the floor of the base-$2^k$ logarithm of a positive [`Rational`]. /// /// $k$ may be negative. /// /// $f(x, k) = \lfloor\log_{2^k} x\rfloor$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::FloorLogBasePowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(100).floor_log_base_power_of_2(2), 3); /// assert_eq!( /// Rational::from(4294967296u64).floor_log_base_power_of_2(8), /// 4 /// ); /// /// // 4^(-2) < 1/10 < 4^(-1) /// assert_eq!( /// Rational::from_signeds(1, 10).floor_log_base_power_of_2(2), /// -2 /// ); /// // (1/4)^2 < 1/10 < (1/4)^1 /// assert_eq!( /// Rational::from_signeds(1, 10).floor_log_base_power_of_2(-2), /// 1 /// ); /// ``` fn floor_log_base_power_of_2(self, pow: i64) -> i64 { assert!(*self > 0u32); match pow.sign() { Equal => panic!("Cannot take base-1 logarithm"), Greater => self.floor_log_base_2().div_round(pow, Floor).0, Less => -(self.ceiling_log_base_2().div_round(-pow, Ceiling).0), } } } impl CeilingLogBasePowerOf2 for &Rational { type Output = i64; /// Returns the ceiling of the base-$2^k$ logarithm of a positive [`Rational`]. /// /// $k$ may be negative. /// /// $f(x, p) = \lceil\log_{2^p} x\rceil$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingLogBasePowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(100).ceiling_log_base_power_of_2(2), 4); /// assert_eq!( /// Rational::from(4294967296u64).ceiling_log_base_power_of_2(8), /// 4 /// ); /// /// // 4^(-2) < 1/10 < 4^(-1) /// assert_eq!( /// Rational::from_signeds(1, 10).ceiling_log_base_power_of_2(2), /// -1 /// ); /// // (1/4)^2 < 1/10 < (1/4)^1 /// assert_eq!( /// Rational::from_signeds(1, 10).ceiling_log_base_power_of_2(-2), /// 2 /// ); /// ``` fn ceiling_log_base_power_of_2(self, pow: i64) -> i64 { assert!(*self > 0u32); match pow.sign() { Equal => panic!("Cannot take base-1 logarithm"), Greater => self.ceiling_log_base_2().div_round(pow, Ceiling).0, Less => -self.floor_log_base_2().div_round(-pow, Floor).0, } } } impl CheckedLogBasePowerOf2 for &Rational { type Output = i64; /// Returns the base-$2^k$ logarithm of a positive [`Rational`]. If the [`Rational`] is not a /// power of $2^k$, then `None` is returned. /// /// $k$ may be negative. /// /// $$ /// f(x, p) = \\begin{cases} /// \operatorname{Some}(\log_{2^p} x) & \text{if} \\quad \log_{2^p} x \in \Z, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is 0 or `pow` is 0. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedLogBasePowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(100).checked_log_base_power_of_2(2), None); /// assert_eq!( /// Rational::from(4294967296u64).checked_log_base_power_of_2(8), /// Some(4) /// ); /// /// // 4^(-2) < 1/10 < 4^(-1) /// assert_eq!( /// Rational::from_signeds(1, 10).checked_log_base_power_of_2(2), /// None /// ); /// assert_eq!( /// Rational::from_signeds(1, 16).checked_log_base_power_of_2(2), /// Some(-2) /// ); /// // (1/4)^2 < 1/10 < (1/4)^1 /// assert_eq!( /// Rational::from_signeds(1, 10).checked_log_base_power_of_2(-2), /// None /// ); /// assert_eq!( /// Rational::from_signeds(1, 16).checked_log_base_power_of_2(-2), /// Some(2) /// ); /// ``` fn checked_log_base_power_of_2(self, pow: i64) -> Option { assert!(*self > 0u32); let log_base_2 = self.checked_log_base_2()?; let (pow, neg) = match pow.sign() { Equal => panic!("Cannot take base-1 logarithm"), Greater => (pow, false), Less => (-pow, true), }; let (log, rem) = log_base_2.div_mod(pow); if rem != 0 { None } else if neg { Some(-log) } else { Some(log) } } } ================================================ FILE: malachite-q/src/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . /// Absolute value of [`Rational`](super::Rational)s. pub mod abs; /// Implementations of [`AbsDiff`](malachite_base::num::arithmetic::traits::AbsDiff) and /// [`AbsDiffAssign`](malachite_base::num::arithmetic::traits::AbsDiffAssign), traits for getting /// the absolute value of the difference between two numbers. pub mod abs_diff; /// Addition of [`Rational`](super::Rational)s. pub mod add; /// Implementations of [`Approximate`](traits::Approximate) and /// [`ApproximateAssign`](traits::ApproximateAssign), traits for approximating a /// [`Rational`](super::Rational) by a [`Rational`](super::Rational) with a bounded denominator. pub mod approximate; /// Implementations of [`Ceiling`](malachite_base::num::arithmetic::traits::Ceiling) and /// [`CeilingAssign`](malachite_base::num::arithmetic::traits::CeilingAssign), traits for taking the /// ceiling of a number. pub mod ceiling; /// Getting all denominators of [`Rational`](super::Rational)s that appear in a given closed /// interval. pub mod denominators_in_closed_interval; /// Division of [`Rational`](super::Rational)s. pub mod div; /// Implementations of [`Floor`](malachite_base::num::arithmetic::traits::Floor) and /// [`FloorAssign`](malachite_base::num::arithmetic::traits::FloorAssign), traits for taking the /// floor of a number. pub mod floor; /// An implementation of [`IsPowerOf2`](malachite_base::num::arithmetic::traits::IsPowerOf2), a /// trait for determining whether a number is an integer power of 2. pub mod is_power_of_2; /// Implementations of traits for taking the base-$b$ logarithm of a number. /// /// The traits are [`FloorLogBase`](malachite_base::num::arithmetic::traits::FloorLogBase), /// [`CeilingLogBase`](malachite_base::num::arithmetic::traits::CeilingLogBase), and /// [`CheckedLogBase`](malachite_base::num::arithmetic::traits::CheckedLogBase). pub mod log_base; /// Implementations of traits for taking the base-2 logarithm of a number. /// /// The traits are [`FloorLogBase2`](malachite_base::num::arithmetic::traits::FloorLogBase2), /// [`CeilingLogBase2`](malachite_base::num::arithmetic::traits::CeilingLogBase2), and /// [`CheckedLogBase2`](malachite_base::num::arithmetic::traits::CheckedLogBase2). pub mod log_base_2; /// Implementations of traits for taking the base-$2^k$ logarithm of a number. /// /// The traits are /// [`FloorLogBasePowerOf2`](malachite_base::num::arithmetic::traits::FloorLogBasePowerOf2), /// [`CeilingLogBasePowerOf2`](malachite_base::num::arithmetic::traits::CeilingLogBasePowerOf2), and /// [`CheckedLogBasePowerOf2`](malachite_base::num::arithmetic::traits::CheckedLogBasePowerOf2). pub mod log_base_power_of_2; /// Implementations of traits for finding the remainder of two numbers, subject to various rounding /// rules. /// /// These are the traits: /// /// | rounding | by value or reference | by mutable reference (assignment) | /// |-------------------|----------------------------|----------------------------------------| /// | towards $-\infty$ | [`Mod`](malachite_base::num::arithmetic::traits::Mod) | [`ModAssign`](malachite_base::num::arithmetic::traits::ModAssign) | /// | towards $\infty$ | [`CeilingMod`](malachite_base::num::arithmetic::traits::CeilingMod) | [`CeilingModAssign`](malachite_base::num::arithmetic::traits::CeilingModAssign) | /// /// The [`Rem`](core::ops::Rem) trait in the standard library rounds towards 0. pub mod mod_op; /// Multiplication of [`Rational`](super::Rational)s. pub mod mul; /// Negation of [`Rational`](super::Rational)s. pub mod neg; /// Implementations of [`NextPowerOf2`](malachite_base::num::arithmetic::traits::NextPowerOf2) and /// [`NextPowerOf2Assign`](malachite_base::num::arithmetic::traits::NextPowerOf2Assign), traits for /// getting the next-highest power of 2. pub mod next_power_of_2; /// Implementations of [`Pow`](malachite_base::num::arithmetic::traits::Pow) and /// [`PowAssign`](malachite_base::num::arithmetic::traits::PowAssign), traits for raising a number /// to a power. pub mod pow; /// Implementations of [`PowerOf2`](malachite_base::num::arithmetic::traits::PowerOf2), a trait for /// computing a power of 2. pub mod power_of_2; /// Implementations of [`Reciprocal`](malachite_base::num::arithmetic::traits::Reciprocal) and /// [`ReciprocalAssign`](malachite_base::num::arithmetic::traits::ReciprocalAssign), traits for /// computing the reciprocal of a number. pub mod reciprocal; /// Implementations of [`CheckedRoot`](malachite_base::num::arithmetic::traits::CheckedRoot), a /// trait for computing the root of a number, if the number is a perfect power. pub mod root; /// Implementations of [`RoundToMultiple`](malachite_base::num::arithmetic::traits::RoundToMultiple) /// and [`RoundToMultipleAssign`](malachite_base::num::arithmetic::traits::RoundToMultipleAssign), /// traits for rounding a number to a multiple of another number. pub mod round_to_multiple; /// Implementations of /// [`RoundToMultipleOfPowerOf2`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2) /// and /// [`RoundToMultipleOfPowerOf2Assign`](malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign), /// traits for rounding a number to a multiple of a power of 2. pub mod round_to_multiple_of_power_of_2; /// Left-shifting a [`Rational`](super::Rational) (multiplying it by a power of 2). /// /// # shl /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO << 10u8, 0); /// assert_eq!(Rational::from(123) << 2u16, 492); /// assert_eq!((Rational::from_signeds(7, 22) << 2u16).to_string(), "14/11"); /// /// assert_eq!(Rational::ZERO << 10i8, 0); /// assert_eq!(Rational::from(123) << 2i16, 492); /// assert_eq!((Rational::from(123) << -2i16).to_string(), "123/4"); /// assert_eq!((Rational::from_signeds(7, 22) << 2i16).to_string(), "14/11"); /// assert_eq!( /// (Rational::from_signeds(22, 7) << -2i16).to_string(), /// "11/14" /// ); /// /// assert_eq!(&Rational::ZERO << 10u8, 0); /// assert_eq!(&Rational::from(123) << 2u16, 492); /// assert_eq!( /// (&Rational::from_signeds(7, 22) << 2u16).to_string(), /// "14/11" /// ); /// /// assert_eq!(&Rational::ZERO << 10i8, 0); /// assert_eq!(&Rational::from(123) << 2i16, 492); /// assert_eq!((&Rational::from(123) << -2i16).to_string(), "123/4"); /// assert_eq!( /// (&Rational::from_signeds(7, 22) << 2i16).to_string(), /// "14/11" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7) << -2i16).to_string(), /// "11/14" /// ); /// ``` /// /// # shl_assign /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x <<= 10u8; /// assert_eq!(x, 0); /// /// let mut x = Rational::from(123); /// x <<= 2u16; /// assert_eq!(x, 492); /// /// let mut x = Rational::from_signeds(7, 22); /// x <<= 2u16; /// assert_eq!(x.to_string(), "14/11"); /// /// let mut x = Rational::ZERO; /// x <<= 10i8; /// assert_eq!(x, 0); /// /// let mut x = Rational::from(123); /// x <<= 2i16; /// assert_eq!(x, 492); /// /// let mut x = Rational::from(123); /// x <<= -2i16; /// assert_eq!(x.to_string(), "123/4"); /// /// let mut x = Rational::from_signeds(7, 22); /// x <<= 2i16; /// assert_eq!(x.to_string(), "14/11"); /// /// let mut x = Rational::from_signeds(22, 7); /// x <<= -2i16; /// assert_eq!(x.to_string(), "11/14"); /// ``` pub mod shl; /// Right-shifting a [`Rational`](super::Rational) (dividing it by a power of 2). /// /// # shr /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO >> 10u8, 0); /// assert_eq!((Rational::from(123) >> 2u16).to_string(), "123/4"); /// assert_eq!((Rational::from_signeds(22, 7) >> 2u16).to_string(), "11/14"); /// /// assert_eq!(Rational::ZERO >> 10i8, 0); /// assert_eq!((Rational::from(123) >> 2i16).to_string(), "123/4"); /// assert_eq!(Rational::from(123) >> -2i16, 492); /// assert_eq!((Rational::from_signeds(22, 7) >> 2i16).to_string(), "11/14"); /// assert_eq!( /// (Rational::from_signeds(7, 22) >> -2i16).to_string(), /// "14/11" /// ); /// /// assert_eq!(&Rational::ZERO >> 10u8, 0); /// assert_eq!((&Rational::from(123) >> 2u16).to_string(), "123/4"); /// assert_eq!( /// (&Rational::from_signeds(22, 7) >> 2u16).to_string(), /// "11/14" /// ); /// /// assert_eq!(&Rational::ZERO >> 10i8, 0); /// assert_eq!((&Rational::from(123) >> 2i16).to_string(), "123/4"); /// assert_eq!(&Rational::from(123) >> -2i16, 492); /// assert_eq!( /// (&Rational::from_signeds(22, 7) >> 2i16).to_string(), /// "11/14" /// ); /// assert_eq!( /// (&Rational::from_signeds(7, 22) >> -2i16).to_string(), /// "14/11" /// ); /// ``` /// /// # shr_assign /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x >>= 10u8; /// assert_eq!(x, 0); /// /// let mut x = Rational::from(123); /// x >>= 2u16; /// assert_eq!(x.to_string(), "123/4"); /// /// let mut x = Rational::from_signeds(22, 7); /// x >>= 2u16; /// assert_eq!(x.to_string(), "11/14"); /// /// let mut x = Rational::ZERO; /// x >>= 10i8; /// assert_eq!(x, 0); /// /// let mut x = Rational::from(123); /// x >>= 2i16; /// assert_eq!(x.to_string(), "123/4"); /// /// let mut x = Rational::from(123); /// x >>= -2i16; /// assert_eq!(x, 492); /// /// let mut x = Rational::from_signeds(22, 7); /// x >>= 2i16; /// assert_eq!(x.to_string(), "11/14"); /// /// let mut x = Rational::from_signeds(7, 22); /// x >>= -2i16; /// assert_eq!(x.to_string(), "14/11"); /// ``` pub mod shr; /// An implementation of [`Sign`](malachite_base::num::arithmetic::traits::Sign), a trait for /// determining the sign of a number. pub mod sign; /// Functions for finding the simplest (lowest-denominator) [`Rational`](super::Rational) in an /// interval. pub mod simplest_rational_in_interval; /// Implementations of [`CheckedSqrt`](malachite_base::num::arithmetic::traits::CheckedSqrt), a /// trait for computing the root of a number, if the number is a perfect square. pub mod sqrt; /// Implementations of [`Square`](malachite_base::num::arithmetic::traits::Square) and /// [`SquareAssign`](malachite_base::num::arithmetic::traits::SquareAssign), traits for squaring a /// number. pub mod square; /// Subtraction of [`Rational`](super::Rational)s. pub mod sub; /// Various traits for performing arithmetic operations on numbers. pub mod traits; ================================================ FILE: malachite-q/src/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::mem::swap; use core::ops::{Rem, RemAssign}; use malachite_base::num::arithmetic::traits::{ CeilingMod, CeilingModAssign, DivRound, Mod, ModAssign, UnsignedAbs, }; use malachite_base::num::basic::traits::Zero; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; impl Mod for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by reference. The remainder has the same sign as the second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .mod_op(Rational::ONE) /// .to_string(), /// "1/10" /// ); /// /// // -3 * 1 + 9/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .mod_op(Rational::ONE) /// .to_string(), /// "9/10" /// ); /// /// // 3 * -1 - 9/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .mod_op(Rational::NEGATIVE_ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .mod_op(Rational::NEGATIVE_ONE) /// .to_string(), /// "-1/10" /// ); /// ``` #[inline] fn mod_op(self, other: Self) -> Self { let x_sign = self >= 0u32; let (n1, d1) = self.into_numerator_and_denominator(); let y_sign = other >= 0u32; let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = Integer::from_sign_and_abs(x_sign, n1 * &d2); let n2d1 = Integer::from_sign_and_abs(y_sign, n2 * &d1); let q = (&n1d2).div_round(&n2d1, Floor).0; let n = n1d2 - n2d1 * q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Mod<&Self> for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by value and the second by reference. The remainder has the same sign as the second /// [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .mod_op(&Rational::ONE) /// .to_string(), /// "1/10" /// ); /// /// // -3 * 1 + 9/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .mod_op(&Rational::ONE) /// .to_string(), /// "9/10" /// ); /// /// // 3 * -1 - 9/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .mod_op(&Rational::NEGATIVE_ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .mod_op(&Rational::NEGATIVE_ONE) /// .to_string(), /// "-1/10" /// ); /// ``` #[inline] fn mod_op(self, other: &Self) -> Self { let x_sign = self >= 0u32; let (n1, d1) = self.into_numerator_and_denominator(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = Integer::from_sign_and_abs(x_sign, n1 * d2); let n2d1 = Integer::from_sign_and_abs(*other >= 0u32, n2 * &d1); let q = (&n1d2).div_round(&n2d1, Floor).0; let n = n1d2 - n2d1 * q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Mod for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by reference and the second by value. The remainder has the same sign as the second /// [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .mod_op(Rational::ONE) /// .to_string(), /// "1/10" /// ); /// /// // -3 * 1 + 9/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .mod_op(Rational::ONE) /// .to_string(), /// "9/10" /// ); /// /// // 3 * -1 - 9/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .mod_op(Rational::NEGATIVE_ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .mod_op(Rational::NEGATIVE_ONE) /// .to_string(), /// "-1/10" /// ); /// ``` fn mod_op(self, other: Rational) -> Rational { let (n1, d1) = self.numerator_and_denominator_ref(); let y_sign = other >= 0u32; let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = Integer::from_sign_and_abs(*self >= 0u32, n1 * &d2); let n2d1 = Integer::from_sign_and_abs(y_sign, n2 * d1); let q = (&n1d2).div_round(&n2d1, Floor).0; let n = n1d2 - n2d1 * q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Mod<&Rational> for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by reference. The remainder has the same sign as the second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// This function is called `mod_op` rather than `mod` because `mod` is a Rust keyword. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Mod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .mod_op(&Rational::ONE) /// .to_string(), /// "1/10" /// ); /// /// // -3 * 1 + 9/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .mod_op(&Rational::ONE) /// .to_string(), /// "9/10" /// ); /// /// // 3 * -1 - 9/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .mod_op(&Rational::NEGATIVE_ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .mod_op(&Rational::NEGATIVE_ONE) /// .to_string(), /// "-1/10" /// ); /// ``` fn mod_op(self, other: &Rational) -> Rational { let (n1, d1) = self.numerator_and_denominator_ref(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = Integer::from_sign_and_abs(*self >= 0u32, n1 * d2); let n2d1 = Integer::from_sign_and_abs(*other >= 0u32, n2 * d1); let q = (&n1d2).div_round(&n2d1, Floor).0; let n = n1d2 - n2d1 * q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl ModAssign for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by value. The remainder has the same sign as the second /// [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.mod_assign(Rational::ONE); /// assert_eq!(x.to_string(), "1/10"); /// /// // -3 * 1 + 9/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.mod_assign(Rational::ONE); /// assert_eq!(x.to_string(), "9/10"); /// /// // 3 * -1 - 9/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.mod_assign(Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "-9/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.mod_assign(Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "-1/10"); /// ``` fn mod_assign(&mut self, other: Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x.mod_op(other); } } impl ModAssign<&Self> for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by reference. The remainder has the same sign as the /// second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lfloor \frac{x}{y} \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ModAssign; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.mod_assign(&Rational::ONE); /// assert_eq!(x.to_string(), "1/10"); /// /// // -3 * 1 + 9/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.mod_assign(&Rational::ONE); /// assert_eq!(x.to_string(), "9/10"); /// /// // 3 * -1 - 9/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.mod_assign(&Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "-9/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.mod_assign(&Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "-1/10"); /// ``` fn mod_assign(&mut self, other: &Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x.mod_op(other); } } impl Rem for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by value. The remainder has the same sign as the first [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (Rational::from_unsigneds(21u8, 10) % Rational::ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -1/10 /// assert_eq!( /// (Rational::from_signeds(-21, 10) % Rational::ONE).to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (Rational::from_unsigneds(21u8, 10) % Rational::NEGATIVE_ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (Rational::from_signeds(-21, 10) % Rational::NEGATIVE_ONE).to_string(), /// "-1/10" /// ); /// ``` #[inline] fn rem(self, other: Self) -> Self { let x_sign = self >= 0; let (n1, d1) = self.into_numerator_and_denominator(); let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = n1 * &d2; let n2d1 = n2 * &d1; let q = (&n1d2).div_round(&n2d1, Floor).0; let n2d1q = Integer::from_sign_and_abs(x_sign, n2d1 * q); let n = Integer::from_sign_and_abs(x_sign, n1d2) - n2d1q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Rem<&Self> for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by value and the second by reference. The remainder has the same sign as the first /// [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (Rational::from_unsigneds(21u8, 10) % &Rational::ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -1/10 /// assert_eq!( /// (Rational::from_signeds(-21, 10) % &Rational::ONE).to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (Rational::from_unsigneds(21u8, 10) % &Rational::NEGATIVE_ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (Rational::from_signeds(-21, 10) % &Rational::NEGATIVE_ONE).to_string(), /// "-1/10" /// ); /// ``` #[inline] fn rem(self, other: &Self) -> Self { let x_sign = self >= 0; let (n1, d1) = self.into_numerator_and_denominator(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = n1 * d2; let n2d1 = n2 * &d1; let q = (&n1d2).div_round(&n2d1, Floor).0; let n2d1q = Integer::from_sign_and_abs(x_sign, n2d1 * q); let n = Integer::from_sign_and_abs(x_sign, n1d2) - n2d1q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Rem for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by reference and the second by value. The remainder has the same sign as the first /// [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10) % Rational::ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -1/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10) % Rational::ONE).to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10) % Rational::NEGATIVE_ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10) % Rational::NEGATIVE_ONE).to_string(), /// "-1/10" /// ); /// ``` #[inline] fn rem(self, other: Rational) -> Rational { let x_sign = *self >= 0; let (n1, d1) = self.numerator_and_denominator_ref(); let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = n1 * &d2; let n2d1 = n2 * d1; let q = (&n1d2).div_round(&n2d1, Floor).0; let n2d1q = Integer::from_sign_and_abs(x_sign, n2d1 * q); let n = Integer::from_sign_and_abs(x_sign, n1d2) - n2d1q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl Rem<&Rational> for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by reference. The remainder has the same sign as the first [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10) % &Rational::ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -1/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10) % &Rational::ONE).to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10) % &Rational::NEGATIVE_ONE).to_string(), /// "1/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10) % &Rational::NEGATIVE_ONE).to_string(), /// "-1/10" /// ); /// ``` #[inline] fn rem(self, other: &Rational) -> Rational { let x_sign = *self >= 0; let (n1, d1) = self.numerator_and_denominator_ref(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = n1 * d2; let n2d1 = n2 * d1; let q = (&n1d2).div_round(&n2d1, Floor).0; let n2d1q = Integer::from_sign_and_abs(x_sign, n2d1 * q); let n = Integer::from_sign_and_abs(x_sign, n1d2) - n2d1q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl RemAssign for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by value. The remainder has the same sign as the first /// [`Rational`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x %= Rational::ONE; /// assert_eq!(x.to_string(), "1/10"); /// /// // -2 * 1 - 1/10 = -1/10 /// let mut x = Rational::from_signeds(-21, 10); /// x %= Rational::ONE; /// assert_eq!(x.to_string(), "-1/10"); /// /// // -2 * -1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x %= Rational::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "1/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x %= Rational::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "-1/10"); /// ``` #[inline] fn rem_assign(&mut self, other: Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x % other; } } impl RemAssign<&Self> for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by reference. The remainder has the same sign as the /// first [`Rational`]. /// /// If the quotient were computed, he quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y \operatorname{sgn}(xy) /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 2 * 1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x %= &Rational::ONE; /// assert_eq!(x.to_string(), "1/10"); /// /// // -2 * 1 - 1/10 = -1/10 /// let mut x = Rational::from_signeds(-21, 10); /// x %= &Rational::ONE; /// assert_eq!(x.to_string(), "-1/10"); /// /// // -2 * -1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x %= &Rational::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "1/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x %= &Rational::NEGATIVE_ONE; /// assert_eq!(x.to_string(), "-1/10"); /// ``` #[inline] fn rem_assign(&mut self, other: &Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x % other; } } impl CeilingMod for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by value. The remainder has the opposite sign as the second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .ceiling_mod(Rational::ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .ceiling_mod(Rational::ONE) /// .to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .ceiling_mod(Rational::NEGATIVE_ONE) /// .to_string(), /// "1/10" /// ); /// /// // 3 * -1 + 9/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .ceiling_mod(Rational::NEGATIVE_ONE) /// .to_string(), /// "9/10" /// ); /// ``` #[inline] fn ceiling_mod(self, other: Self) -> Self { let x_sign = self >= 0u32; let (n1, d1) = self.into_numerator_and_denominator(); let y_sign = other >= 0u32; let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = Integer::from_sign_and_abs(x_sign, n1 * &d2); let n2d1 = Integer::from_sign_and_abs(y_sign, n2 * &d1); let q = (&n1d2).div_round(&n2d1, Ceiling).0; let n = n1d2 - n2d1 * q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl CeilingMod<&Self> for Rational { type Output = Self; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by value and the second by reference. The remainder has the opposite sign as the /// second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .ceiling_mod(&Rational::ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .ceiling_mod(&Rational::ONE) /// .to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// Rational::from_unsigneds(21u8, 10) /// .ceiling_mod(&Rational::NEGATIVE_ONE) /// .to_string(), /// "1/10" /// ); /// /// // 3 * -1 + 9/10 = -21/10 /// assert_eq!( /// Rational::from_signeds(-21, 10) /// .ceiling_mod(&Rational::NEGATIVE_ONE) /// .to_string(), /// "9/10" /// ); /// ``` #[inline] fn ceiling_mod(self, other: &Self) -> Self { let x_sign = self >= 0u32; let (n1, d1) = self.into_numerator_and_denominator(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = Integer::from_sign_and_abs(x_sign, n1 * d2); let n2d1 = Integer::from_sign_and_abs(*other > 0u32, n2 * &d1); let q = (&n1d2).div_round(&n2d1, Ceiling).0; let n = n1d2 - n2d1 * q; Self::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl CeilingMod for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking the /// first by reference and the second by value. The remainder has the opposite sign as the /// second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .ceiling_mod(Rational::ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .ceiling_mod(Rational::ONE) /// .to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .ceiling_mod(Rational::NEGATIVE_ONE) /// .to_string(), /// "1/10" /// ); /// /// // 3 * -1 + 9/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .ceiling_mod(Rational::NEGATIVE_ONE) /// .to_string(), /// "9/10" /// ); /// ``` fn ceiling_mod(self, other: Rational) -> Rational { let (n1, d1) = self.numerator_and_denominator_ref(); let y_sign = other >= 0u32; let (n2, d2) = other.into_numerator_and_denominator(); let n1d2 = Integer::from_sign_and_abs(*self >= 0u32, n1 * &d2); let n2d1 = Integer::from_sign_and_abs(y_sign, n2 * d1); let q = (&n1d2).div_round(&n2d1, Ceiling).0; let n = n1d2 - n2d1 * q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl CeilingMod<&Rational> for &Rational { type Output = Rational; /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], taking both /// by reference. The remainder has the opposite sign as the second [`Rational`]. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// f(x, y) = x - y\left \lceil \frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingMod; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .ceiling_mod(&Rational::ONE) /// .to_string(), /// "-9/10" /// ); /// /// // -2 * 1 - 1/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .ceiling_mod(&Rational::ONE) /// .to_string(), /// "-1/10" /// ); /// /// // -2 * -1 + 1/10 = 21/10 /// assert_eq!( /// (&Rational::from_unsigneds(21u8, 10)) /// .ceiling_mod(&Rational::NEGATIVE_ONE) /// .to_string(), /// "1/10" /// ); /// /// // 3 * -1 + 9/10 = -21/10 /// assert_eq!( /// (&Rational::from_signeds(-21, 10)) /// .ceiling_mod(&Rational::NEGATIVE_ONE) /// .to_string(), /// "9/10" /// ); /// ``` fn ceiling_mod(self, other: &Rational) -> Rational { let (n1, d1) = self.numerator_and_denominator_ref(); let (n2, d2) = other.numerator_and_denominator_ref(); let n1d2 = Integer::from_sign_and_abs(*self >= 0u32, n1 * d2); let n2d1 = Integer::from_sign_and_abs(*other >= 0u32, n2 * d1); let q = (&n1d2).div_round(&n2d1, Ceiling).0; let n = n1d2 - n2d1 * q; Rational::from_sign_and_naturals(n >= 0, n.unsigned_abs(), d1 * d2) } } impl CeilingModAssign for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by value. The remainder has the opposite sign as the /// second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModAssign; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.ceiling_mod_assign(Rational::ONE); /// assert_eq!(x.to_string(), "-9/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.ceiling_mod_assign(Rational::ONE); /// assert_eq!(x.to_string(), "-1/10"); /// /// // -2 * -1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.ceiling_mod_assign(Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "1/10"); /// /// // 3 * -1 + 9/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.ceiling_mod_assign(Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "9/10"); /// ``` fn ceiling_mod_assign(&mut self, other: Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x.ceiling_mod(other); } } impl CeilingModAssign<&Self> for Rational { /// Computes the remainder when a [`Rational`] is divided by another [`Rational`], mutating the /// first in place and taking the second by reference. The remainder has the opposite sign as /// the second number. /// /// If the quotient were computed, the quotient and remainder would satisfy $x = qy + r$ and $0 /// \leq |r| < |y|$. /// /// $$ /// x \gets x - y\left \lceil\frac{x}{y} \right \rceil. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `other` is zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CeilingModAssign; /// use malachite_base::num::basic::traits::{NegativeOne, One}; /// use malachite_q::Rational; /// /// // 3 * 1 - 9/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.ceiling_mod_assign(&Rational::ONE); /// assert_eq!(x.to_string(), "-9/10"); /// /// // -2 * 1 - 1/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.ceiling_mod_assign(&Rational::ONE); /// assert_eq!(x.to_string(), "-1/10"); /// /// // -2 * -1 + 1/10 = 21/10 /// let mut x = Rational::from_unsigneds(21u8, 10); /// x.ceiling_mod_assign(&Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "1/10"); /// /// // 3 * -1 + 9/10 = -21/10 /// let mut x = Rational::from_signeds(-21, 10); /// x.ceiling_mod_assign(&Rational::NEGATIVE_ONE); /// assert_eq!(x.to_string(), "9/10"); /// ``` fn ceiling_mod_assign(&mut self, other: &Self) { let mut x = Self::ZERO; swap(self, &mut x); *self = x.ceiling_mod(other); } } ================================================ FILE: malachite-q/src/arithmetic/mul.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1994-1996, 2000-2002 Free Software Foundation, Inc. // // 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 crate::Rational; use alloc::vec::Vec; use core::iter::Product; use core::ops::{Mul, MulAssign}; use malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign, Gcd}; use malachite_base::num::basic::traits::{One, Zero}; impl Mul for Rational { type Output = Self; /// Multiplies two [`Rational`]s, taking both by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF * Rational::TWO, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) * Rational::from_signeds(99, 100)).to_string(), /// "1089/350" /// ); /// ``` fn mul(self, other: Self) -> Self { if self == 0u32 || other == 0u32 { return Self::ZERO; } else if self == 1u32 { return other; } else if other == 1u32 { return self; } let g_1 = (&self.numerator).gcd(&other.denominator); let g_2 = (&other.numerator).gcd(&self.denominator); Self { sign: self.sign == other.sign, numerator: (self.numerator).div_exact(&g_1) * (other.numerator).div_exact(&g_2), denominator: (other.denominator).div_exact(g_1) * (self.denominator).div_exact(g_2), } } } impl Mul<&Self> for Rational { type Output = Self; /// Multiplies two [`Rational`]s, taking the first by value and the second by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF * &Rational::TWO, 1); /// assert_eq!( /// (Rational::from_signeds(22, 7) * &Rational::from_signeds(99, 100)).to_string(), /// "1089/350" /// ); /// ``` #[inline] fn mul(self, other: &Self) -> Self { other * self } } impl Mul for &Rational { type Output = Rational; /// Multiplies two [`Rational`]s, taking the first by reference and the second by value. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF * Rational::TWO, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) * Rational::from_signeds(99, 100)).to_string(), /// "1089/350" /// ); /// ``` fn mul(self, other: Rational) -> Rational { if *self == 0u32 || other == 0u32 { return Rational::ZERO; } else if *self == 1u32 { return other; } else if other == 1u32 { return self.clone(); } let g_1 = (&self.numerator).gcd(&other.denominator); let g_2 = (&other.numerator).gcd(&self.denominator); Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (other.numerator).div_exact(&g_2), denominator: (other.denominator).div_exact(g_1) * (&self.denominator).div_exact(g_2), } } } impl Mul<&Rational> for &Rational { type Output = Rational; /// Multiplies two [`Rational`]s, taking both by reference. /// /// $$ /// f(x, y) = xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF * &Rational::TWO, 1); /// assert_eq!( /// (&Rational::from_signeds(22, 7) * &Rational::from_signeds(99, 100)).to_string(), /// "1089/350" /// ); /// ``` fn mul(self, other: &Rational) -> Rational { if *self == 0u32 || *other == 0u32 { return Rational::ZERO; } else if *self == 1u32 { return other.clone(); } else if *other == 1u32 { return self.clone(); } let g_1 = (&self.numerator).gcd(&other.denominator); let g_2 = (&other.numerator).gcd(&self.denominator); Rational { sign: self.sign == other.sign, numerator: (&self.numerator).div_exact(&g_1) * (&other.numerator).div_exact(&g_2), denominator: (&other.denominator).div_exact(g_1) * (&self.denominator).div_exact(g_2), } } } impl MulAssign for Rational { /// Multiplies a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the /// right-hand side by value. /// /// $$ /// x \gets xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x *= Rational::TWO; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x *= Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "1089/350"); /// ``` fn mul_assign(&mut self, other: Self) { if *self == 0u32 || other == 1u32 { return; } else if other == 0u32 { *self = Self::ZERO; return; } else if *self == 1u32 { *self = other; return; } self.sign = self.sign == other.sign; let g_1 = (&self.numerator).gcd(&other.denominator); let g_2 = (&other.numerator).gcd(&self.denominator); self.numerator.div_exact_assign(&g_1); self.denominator.div_exact_assign(&g_2); self.numerator *= (other.numerator).div_exact(g_2); self.denominator *= (other.denominator).div_exact(g_1); } } impl MulAssign<&Self> for Rational { /// Multiplies a [`Rational`] by a [`Rational`] in place, taking the [`Rational`] on the /// right-hand side by reference. /// /// $$ /// x \gets xy. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^3 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{OneHalf, Two}; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x *= &Rational::TWO; /// assert_eq!(x, 1); /// /// let mut x = Rational::from_signeds(22, 7); /// x *= &Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "1089/350"); /// ``` fn mul_assign(&mut self, other: &Self) { if *self == 0u32 || *other == 1u32 { return; } else if *other == 0u32 { *self = Self::ZERO; return; } else if *self == 1u32 { *self = other.clone(); return; } self.sign = self.sign == other.sign; let g_1 = (&self.numerator).gcd(&other.denominator); let g_2 = (&other.numerator).gcd(&self.denominator); self.numerator.div_exact_assign(&g_1); self.denominator.div_exact_assign(&g_2); self.numerator *= (&other.numerator).div_exact(g_2); self.denominator *= (&other.denominator).div_exact(g_1); } } impl Product for Rational { /// Multiplies together all the [`Rational`]s in an iterator. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^3 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Rational::sum(xs.map(Rational::significant_bits))`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// use std::iter::Product; /// /// assert_eq!( /// Rational::product( /// vec_from_str::("[1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]") /// .unwrap() /// .into_iter() /// ) /// .to_string(), /// "1/5" /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate() { if x == 0 { return Self::ZERO; } let mut p = x; for _ in 0..(i + 1).trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } impl<'a> Product<&'a Self> for Rational { /// Multiplies together all the [`Rational`]s in an iterator of [`Rational`] references. /// /// $$ /// f((x_i)_ {i=0}^{n-1}) = \prod_ {i=0}^{n-1} x_i. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `Rational::sum(xs.map(Rational::significant_bits))`. /// /// # Examples /// ``` /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// use std::iter::Product; /// /// assert_eq!( /// Rational::product( /// vec_from_str::("[1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]") /// .unwrap() /// .iter() /// ) /// .to_string(), /// "1/5" /// ); /// ``` fn product(xs: I) -> Self where I: Iterator, { let mut stack = Vec::new(); for (i, x) in xs.enumerate() { if *x == 0 { return Self::ZERO; } let mut p = x.clone(); for _ in 0..(i + 1).trailing_zeros() { p *= stack.pop().unwrap(); } stack.push(p); } let mut p = Self::ONE; for x in stack.into_iter().rev() { p *= x; } p } } ================================================ FILE: malachite-q/src/arithmetic/neg.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::ops::Neg; use malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::num::basic::traits::Zero; use malachite_base::num::logic::traits::NotAssign; impl Neg for Rational { type Output = Self; /// Negates a [`Rational`], taking it by value. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(-Rational::ZERO, 0); /// assert_eq!((-Rational::from_signeds(22, 7)).to_string(), "-22/7"); /// assert_eq!((-Rational::from_signeds(-22, 7)).to_string(), "22/7"); /// ``` fn neg(mut self) -> Self { if self.numerator != 0 { self.sign.not_assign(); } self } } impl Neg for &Rational { type Output = Rational; /// Negates a [`Rational`], taking it by reference. /// /// $$ /// f(x) = -x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(-&Rational::ZERO, 0); /// assert_eq!((-&Rational::from_signeds(22, 7)).to_string(), "-22/7"); /// assert_eq!((-&Rational::from_signeds(-22, 7)).to_string(), "22/7"); /// ``` fn neg(self) -> Rational { if self.numerator == 0 { Rational::ZERO } else { Rational { sign: !self.sign, numerator: self.numerator.clone(), denominator: self.denominator.clone(), } } } } impl NegAssign for Rational { /// Negates a [`Rational`] in place. /// /// $$ /// x \gets -x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NegAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x.neg_assign(); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.neg_assign(); /// assert_eq!(x.to_string(), "-22/7"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.neg_assign(); /// assert_eq!(x.to_string(), "22/7"); /// ``` fn neg_assign(&mut self) { if self.numerator != 0 { self.sign.not_assign(); } } } ================================================ FILE: malachite-q/src/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign, PowerOf2}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; impl NextPowerOf2 for Rational { type Output = Self; /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is /// taken by value. /// /// $f(x) = 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NextPowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(123).next_power_of_2(), 128); /// assert_eq!( /// Rational::from_signeds(1, 10).next_power_of_2().to_string(), /// "1/8" /// ); /// ``` #[inline] fn next_power_of_2(self) -> Self { assert!(self > 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); match self.numerator.cmp_normalized(&self.denominator) { Equal => return self, Greater => exponent += 1, _ => {} } Self::power_of_2(exponent) } } impl NextPowerOf2 for &Rational { type Output = Rational; /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is /// taken by reference. /// /// $f(x) = 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NextPowerOf2; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::from(123)).next_power_of_2(), 128); /// assert_eq!( /// (&Rational::from_signeds(1, 10)) /// .next_power_of_2() /// .to_string(), /// "1/8" /// ); /// ``` fn next_power_of_2(self) -> Rational { assert!(*self > 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Greater { exponent += 1; } Rational::power_of_2(exponent) } } impl NextPowerOf2Assign for Rational { /// Finds the smallest power of 2 greater than or equal to a [`Rational`]. The [`Rational`] is /// taken by reference. /// /// $f(x) = 2^{\lceil \log_2 x \rceil}$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is less than or equal to zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::NextPowerOf2Assign; /// use malachite_q::Rational; /// /// let mut x = Rational::from(123); /// x.next_power_of_2_assign(); /// assert_eq!(x, 128); /// /// let mut x = Rational::from_signeds(1, 10); /// x.next_power_of_2_assign(); /// assert_eq!(x.to_string(), "1/8"); /// ``` #[inline] fn next_power_of_2_assign(&mut self) { *self = (&*self).next_power_of_2(); } } ================================================ FILE: malachite-q/src/arithmetic/pow.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{ Parity, Pow, PowAssign, Reciprocal, ReciprocalAssign, }; impl Pow for Rational { type Output = Self; /// Raises a [`Rational`] to a power, taking the [`Rational`] by value. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_signeds(22, 7).pow(3u64).to_string(), /// "10648/343" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(3u64).to_string(), /// "-10648/343" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(4u64).to_string(), /// "234256/2401" /// ); /// ``` #[inline] fn pow(mut self, exp: u64) -> Self { self.pow_assign(exp); self } } impl Pow for &Rational { type Output = Rational; /// Raises a [`Rational`] to a power, taking the [`Rational`] by reference. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from_signeds(22, 7)).pow(3u64).to_string(), /// "10648/343" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(3u64).to_string(), /// "-10648/343" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(4u64).to_string(), /// "234256/2401" /// ); /// ``` #[inline] fn pow(self, exp: u64) -> Rational { Rational { sign: self.sign || exp.even(), numerator: (&self.numerator).pow(exp), denominator: (&self.denominator).pow(exp), } } } impl PowAssign for Rational { /// Raises a [`Rational`] to a power in place. /// /// $x \gets x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowAssign; /// use malachite_q::Rational; /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(3u64); /// assert_eq!(x.to_string(), "10648/343"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.pow_assign(3u64); /// assert_eq!(x.to_string(), "-10648/343"); /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(4u64); /// assert_eq!(x.to_string(), "234256/2401"); /// ``` fn pow_assign(&mut self, exp: u64) { self.sign |= exp.even(); self.numerator.pow_assign(exp); self.denominator.pow_assign(exp); } } impl Pow for Rational { type Output = Self; /// Raises a [`Rational`] to a power, taking the [`Rational`] by value. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp.abs()`. /// /// # Panics /// Panics if `self` is zero and `exp` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_signeds(22, 7).pow(3i64).to_string(), /// "10648/343" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(3i64).to_string(), /// "-10648/343" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(4i64).to_string(), /// "234256/2401" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).pow(-3i64).to_string(), /// "343/10648" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(-3i64).to_string(), /// "-343/10648" /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).pow(-4i64).to_string(), /// "2401/234256" /// ); /// ``` #[inline] fn pow(mut self, exp: i64) -> Self { self.pow_assign(exp); self } } impl Pow for &Rational { type Output = Rational; /// Raises a [`Rational`] to a power, taking the [`Rational`] by reference. /// /// $f(x, n) = x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp.abs()`. /// /// # Panics /// Panics if `self` is zero and `exp` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Pow; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from_signeds(22, 7)).pow(3i64).to_string(), /// "10648/343" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(3i64).to_string(), /// "-10648/343" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(4i64).to_string(), /// "234256/2401" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7)).pow(-3i64).to_string(), /// "343/10648" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(-3i64).to_string(), /// "-343/10648" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).pow(-4i64).to_string(), /// "2401/234256" /// ); /// ``` #[inline] fn pow(self, exp: i64) -> Rational { let abs_exp = exp.unsigned_abs(); if exp >= 0 { self.pow(abs_exp) } else { self.pow(abs_exp).reciprocal() } } } impl PowAssign for Rational { /// Raises a [`Rational`] to a power in place. /// /// $x \gets x^n$. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `exp.abs()`. /// /// # Panics /// Panics if `self` is zero and `exp` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowAssign; /// use malachite_q::Rational; /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(3i64); /// assert_eq!(x.to_string(), "10648/343"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.pow_assign(3i64); /// assert_eq!(x.to_string(), "-10648/343"); /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(4i64); /// assert_eq!(x.to_string(), "234256/2401"); /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(-3i64); /// assert_eq!(x.to_string(), "343/10648"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.pow_assign(-3i64); /// assert_eq!(x.to_string(), "-343/10648"); /// /// let mut x = Rational::from_signeds(22, 7); /// x.pow_assign(-4i64); /// assert_eq!(x.to_string(), "2401/234256"); /// ``` fn pow_assign(&mut self, exp: i64) { let abs_exp = exp.unsigned_abs(); if exp >= 0 { self.pow_assign(abs_exp); } else { self.pow_assign(abs_exp); self.reciprocal_assign(); } } } ================================================ FILE: malachite-q/src/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::num::basic::traits::One; use malachite_nz::natural::Natural; impl PowerOf2 for Rational { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::power_of_2(0u64), 1); /// assert_eq!(Rational::power_of_2(3u64), 8); /// assert_eq!( /// Rational::power_of_2(100u64).to_string(), /// "1267650600228229401496703205376" /// ); /// ``` fn power_of_2(pow: u64) -> Self { Self::from(Natural::power_of_2(pow)) } } impl PowerOf2 for Rational { /// Raises 2 to an integer power. /// /// $f(k) = 2^k$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `pow.abs()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_q::Rational; /// /// assert_eq!(Rational::power_of_2(0i64), 1); /// assert_eq!(Rational::power_of_2(3i64), 8); /// assert_eq!( /// Rational::power_of_2(100i64).to_string(), /// "1267650600228229401496703205376" /// ); /// assert_eq!(Rational::power_of_2(-3i64).to_string(), "1/8"); /// assert_eq!( /// Rational::power_of_2(-100i64).to_string(), /// "1/1267650600228229401496703205376" /// ); /// ``` fn power_of_2(pow: i64) -> Self { let pow_abs = pow.unsigned_abs(); if pow >= 0 { Self::from(Natural::power_of_2(pow_abs)) } else { Self { sign: true, numerator: Natural::ONE, denominator: Natural::power_of_2(pow_abs), } } } } ================================================ FILE: malachite-q/src/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::mem::swap; use malachite_base::num::arithmetic::traits::{Reciprocal, ReciprocalAssign}; impl Reciprocal for Rational { type Output = Self; /// Reciprocates a [`Rational`], taking it by value. /// /// $$ /// f(x) = 1/x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Reciprocal; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_signeds(22, 7).reciprocal().to_string(), /// "7/22" /// ); /// assert_eq!( /// Rational::from_signeds(7, 22).reciprocal().to_string(), /// "22/7" /// ); /// ``` #[inline] fn reciprocal(mut self) -> Self { self.reciprocal_assign(); self } } impl Reciprocal for &Rational { type Output = Rational; /// Reciprocates a [`Rational`], taking it by reference. /// /// $$ /// f(x) = 1/x. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Reciprocal; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from_signeds(22, 7)).reciprocal().to_string(), /// "7/22" /// ); /// assert_eq!( /// (&Rational::from_signeds(7, 22)).reciprocal().to_string(), /// "22/7" /// ); /// ``` fn reciprocal(self) -> Rational { assert_ne!(self.numerator, 0, "Cannot take reciprocal of zero"); Rational { sign: self.sign, numerator: self.denominator.clone(), denominator: self.numerator.clone(), } } } impl ReciprocalAssign for Rational { /// Reciprocates a [`Rational`] in place. /// /// $$ /// x \gets 1/x. /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::ReciprocalAssign; /// use malachite_q::Rational; /// /// let mut x = Rational::from_signeds(22, 7); /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "7/22"); /// /// let mut x = Rational::from_signeds(7, 22); /// x.reciprocal_assign(); /// assert_eq!(x.to_string(), "22/7"); /// ``` fn reciprocal_assign(&mut self) { assert_ne!(self.numerator, 0, "Cannot take reciprocal of zero"); swap(&mut self.numerator, &mut self.denominator); } } ================================================ FILE: malachite-q/src/arithmetic/root.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{CheckedRoot, Reciprocal, UnsignedAbs}; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl CheckedRoot for Rational { type Output = Self; /// Returns the the $n$th root of a [`Rational`], or `None` if the [`Rational`] is not a perfect /// $n$th power. The [`Rational`] is taken by value. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(999i32).checked_root(3u64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(1000i32).checked_root(3u64).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Rational::from(1001i32).checked_root(3u64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(-1000i32) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(-10)" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .checked_root(3u64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from_signeds(27, 8) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(3/2)" /// ); /// assert_eq!( /// Rational::from_signeds(-27, 8) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(-3/2)" /// ); /// ``` fn checked_root(self, pow: u64) -> Option { let sign = self >= 0; let (n, d) = self.into_numerator_and_denominator(); let root_n; let root_d; if n.significant_bits() <= d.significant_bits() { root_n = Integer::from_sign_and_abs(sign, n).checked_root(pow)?; root_d = d.checked_root(pow)?; } else { root_d = d.checked_root(pow)?; root_n = Integer::from_sign_and_abs(sign, n).checked_root(pow)?; } Some(Self { sign: root_n >= 0, numerator: root_n.unsigned_abs(), denominator: root_d, }) } } impl CheckedRoot for &Rational { type Output = Rational; /// Returns the the $n$th root of a [`Rational`], or `None` if the [`Rational`] is not a perfect /// $n$th power. The [`Rational`] is taken by reference. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, or if `exp` is even and `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(999i32).checked_root(3u64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(1000i32).checked_root(3u64).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Rational::from(1001i32).checked_root(3u64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(-1000i32) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(-10)" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .checked_root(3u64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from_signeds(27, 8) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(3/2)" /// ); /// assert_eq!( /// Rational::from_signeds(-27, 8) /// .checked_root(3u64) /// .to_debug_string(), /// "Some(-3/2)" /// ); /// ``` fn checked_root(self, pow: u64) -> Option { let (n, d) = self.numerator_and_denominator_ref(); let root_n; let root_d; if n.significant_bits() <= d.significant_bits() { root_n = Integer::from_sign_and_abs_ref(*self >= 0, n).checked_root(pow)?; root_d = d.checked_root(pow)?; } else { root_d = d.checked_root(pow)?; root_n = Integer::from_sign_and_abs_ref(*self >= 0, n).checked_root(pow)?; } Some(Rational { sign: root_n >= 0, numerator: root_n.unsigned_abs(), denominator: root_d, }) } } impl CheckedRoot for Rational { type Output = Self; /// Returns the the $n$th root of a [`Rational`], or `None` if the [`Rational`] is not a perfect /// $n$th power. The [`Rational`] is taken by value. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, if `exp` is even and `self` is negative, or if `self` is zero and /// `exp` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(999i32).checked_root(3i64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(1000i32).checked_root(3i64).to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Rational::from(1001i32).checked_root(3i64).to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(-1000i32) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(-10)" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .checked_root(3i64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from_signeds(27, 8) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(3/2)" /// ); /// assert_eq!( /// Rational::from_signeds(-27, 8) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(-3/2)" /// ); /// /// assert_eq!( /// Rational::from(1000i32) /// .checked_root(-3i64) /// .to_debug_string(), /// "Some(1/10)" /// ); /// assert_eq!( /// Rational::from_signeds(-27, 8) /// .checked_root(-3i64) /// .to_debug_string(), /// "Some(-2/3)" /// ); /// ``` fn checked_root(self, pow: i64) -> Option { let u_pow = pow.unsigned_abs(); if pow >= 0 { self.checked_root(u_pow) } else { self.checked_root(u_pow).map(Self::reciprocal) } } } impl CheckedRoot for &Rational { type Output = Rational; /// Returns the the $n$th root of a [`Rational`], or `None` if the [`Rational`] is not a perfect /// $n$th power. The [`Rational`] is taken by reference. /// /// $$ /// f(x, n) = \\begin{cases} /// \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `exp` is zero, if `exp` is even and `self` is negative, or if `self` is zero and /// `exp` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedRoot; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from(999i32)) /// .checked_root(3i64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from(1000i32)) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Rational::from(1001i32)) /// .checked_root(3i64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from(-1000i32)) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(-10)" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .checked_root(3i64) /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from_signeds(27, 8)) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(3/2)" /// ); /// assert_eq!( /// (&Rational::from_signeds(-27, 8)) /// .checked_root(3i64) /// .to_debug_string(), /// "Some(-3/2)" /// ); /// /// assert_eq!( /// (&Rational::from(1000i32)) /// .checked_root(-3i64) /// .to_debug_string(), /// "Some(1/10)" /// ); /// assert_eq!( /// (&Rational::from_signeds(-27, 8)) /// .checked_root(-3i64) /// .to_debug_string(), /// "Some(-2/3)" /// ); /// ``` fn checked_root(self, pow: i64) -> Option { let u_pow = pow.unsigned_abs(); if pow >= 0 { self.checked_root(u_pow) } else { self.checked_root(u_pow).map(Rational::reciprocal) } } } ================================================ FILE: malachite-q/src/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{NegAssign, RoundToMultiple, RoundToMultipleAssign}; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; impl RoundToMultiple for Rational { type Output = Self; /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a /// specified rounding mode. Both [`Rational`]s are taken by value. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(-5) /// .round_to_multiple(Rational::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// assert_eq!( /// q.clone() /// .round_to_multiple(hundredth.clone(), Down) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(hundredth.clone(), Floor) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(hundredth.clone(), Up) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(hundredth.clone(), Ceiling) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(hundredth.clone(), Nearest) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple<&Self> for Rational { type Output = Self; /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a /// specified rounding mode. The first [`Rational`] is taken by value and the second by /// reference. An [`Ordering`] is also returned, indicating whether the returned value is less /// than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(-5) /// .round_to_multiple(&Rational::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// assert_eq!( /// q.clone() /// .round_to_multiple(&hundredth, Down) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(&hundredth, Floor) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(&hundredth, Up) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(&hundredth, Ceiling) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple(&hundredth, Nearest) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// ``` #[inline] fn round_to_multiple(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_assign(other, rm); (self, o) } } impl RoundToMultiple for &Rational { type Output = Rational; /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a /// specified rounding mode. The first [`Rational`] is taken by reference and the second by /// value. An [`Ordering`] is also returned, indicating whether the returned value is less than, /// equal to, or greater than the original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from(-5)) /// .round_to_multiple(Rational::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// assert_eq!( /// (&q).round_to_multiple(hundredth.clone(), Down) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple(hundredth.clone(), Floor) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple(hundredth.clone(), Up) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple(hundredth.clone(), Ceiling) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple(hundredth.clone(), Nearest) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// ``` fn round_to_multiple(self, other: Rational, mut rm: RoundingMode) -> (Rational, Ordering) { if *self == other { return (self.clone(), Equal); } if other == 0u32 { if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } { return (Rational::ZERO, if *self >= 0u32 { Less } else { Greater }); } panic!("Cannot round {self} to zero using RoundingMode {rm}"); } if !other.sign { rm.neg_assign(); } let (x, mut o) = Integer::rounding_from(self / &other, rm); if !other.sign { o = o.reverse(); } (Rational::from(x) * other, o) } } impl RoundToMultiple<&Rational> for &Rational { type Output = Rational; /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a /// specified rounding mode. Both [`Rational`]s are taken by reference. An [`Ordering`] is also /// returned, indicating whether the returned value is less than, equal to, or greater than the /// original value. /// /// Let $q = \frac{x}{y}$: /// /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$ /// /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$ /// /// $$ /// f(x, y, \mathrm{Nearest}) = \begin{cases} /// y \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// y \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} /// \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultiple; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from(-5)) /// .round_to_multiple(&Rational::ZERO, Down) /// .to_debug_string(), /// "(0, Greater)" /// ); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// assert_eq!( /// (&q).round_to_multiple(&hundredth, Down).to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple(&hundredth, Floor).to_debug_string(), /// "(157/50, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple(&hundredth, Up).to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple(&hundredth, Ceiling) /// .to_debug_string(), /// "(63/20, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple(&hundredth, Nearest) /// .to_debug_string(), /// "(157/50, Less)" /// ); /// ``` fn round_to_multiple(self, other: &Rational, mut rm: RoundingMode) -> (Rational, Ordering) { if self == other { return (self.clone(), Equal); } if *other == 0u32 { if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } { return (Rational::ZERO, if *self >= 0 { Less } else { Greater }); } panic!("Cannot round {self} to zero using RoundingMode {rm}"); } if !other.sign { rm.neg_assign(); } let (x, mut o) = Integer::rounding_from(self / other, rm); if !other.sign { o = o.reverse(); } (Rational::from(x) * other, o) } } impl RoundToMultipleAssign for Rational { /// Rounds a [`Rational`] to an integer multiple of another [`Rational`] in place, according to /// a specified rounding mode. The [`Rational`] on the right-hand side is taken by value. An /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Rational::from(-5); /// assert_eq!(x.round_to_multiple_assign(Rational::ZERO, Down), Greater); /// assert_eq!(x, 0); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Down), Less); /// assert_eq!(x.to_string(), "157/50"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Floor), Less); /// assert_eq!(x.to_string(), "157/50"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Up), Greater); /// assert_eq!(x.to_string(), "63/20"); /// /// let mut x = q.clone(); /// assert_eq!( /// x.round_to_multiple_assign(hundredth.clone(), Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "63/20"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Nearest), Less); /// assert_eq!(x.to_string(), "157/50"); /// ``` fn round_to_multiple_assign(&mut self, other: Self, mut rm: RoundingMode) -> Ordering { if *self == other { return Equal; } if other == 0u32 { if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } { let o = if *self >= 0 { Less } else { Greater }; *self = Self::ZERO; return o; } panic!("Cannot round {self} to zero using RoundingMode {rm}"); } if !other.sign { rm.neg_assign(); } *self /= &other; let (x, o) = Integer::rounding_from(&*self, rm); let other_sign = other.sign; *self = Self::from(x) * other; if other_sign { o } else { o.reverse() } } } impl RoundToMultipleAssign<&Self> for Rational { /// Rounds a [`Rational`] to an integer multiple of another [`Rational`] in place, according to /// a specified rounding mode. The [`Rational`] on the right-hand side is taken by reference. An /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or /// greater than the original value. /// /// See the [`RoundToMultiple`] documentation for details. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// - If `rm` is `Exact`, but `self` is not a multiple of `other`. /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let mut x = Rational::from(-5); /// assert_eq!(x.round_to_multiple_assign(&Rational::ZERO, Down), Greater); /// assert_eq!(x, 0); /// /// let q = Rational::exact_from(std::f64::consts::PI); /// let hundredth = Rational::from_signeds(1, 100); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(&hundredth, Down), Less); /// assert_eq!(x.to_string(), "157/50"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(&hundredth, Floor), Less); /// assert_eq!(x.to_string(), "157/50"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(&hundredth, Up), Greater); /// assert_eq!(x.to_string(), "63/20"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(&hundredth, Ceiling), Greater); /// assert_eq!(x.to_string(), "63/20"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_assign(&hundredth, Nearest), Less); /// assert_eq!(x.to_string(), "157/50"); /// ``` fn round_to_multiple_assign(&mut self, other: &Self, mut rm: RoundingMode) -> Ordering { if self == other { return Equal; } if *other == 0u32 { if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } { let o = if *self >= 0u32 { Less } else { Greater }; *self = Self::ZERO; return o; } panic!("Cannot round {self} to zero using RoundingMode {rm}"); } if !other.sign { rm.neg_assign(); } *self /= other; let (x, o) = Integer::rounding_from(&*self, rm); *self = Self::from(x) * other; if other.sign { o } else { o.reverse() } } } ================================================ FILE: malachite-q/src/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::{ RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_nz::integer::Integer; impl RoundToMultipleOfPowerOf2 for Rational { type Output = Self; /// Rounds a [`Rational`] to an integer multiple of $2^k$ according to a specified rounding /// mode. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = 2^k \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = 2^k \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// let q = Rational::exact_from(std::f64::consts::PI); /// assert_eq!( /// q.clone() /// .round_to_multiple_of_power_of_2(-3, Floor) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple_of_power_of_2(-3, Down) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple_of_power_of_2(-3, Ceiling) /// .to_debug_string(), /// "(13/4, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple_of_power_of_2(-3, Up) /// .to_debug_string(), /// "(13/4, Greater)" /// ); /// assert_eq!( /// q.clone() /// .round_to_multiple_of_power_of_2(-3, Nearest) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// ``` #[inline] fn round_to_multiple_of_power_of_2(mut self, pow: i64, rm: RoundingMode) -> (Self, Ordering) { let o = self.round_to_multiple_of_power_of_2_assign(pow, rm); (self, o) } } impl RoundToMultipleOfPowerOf2 for &Rational { type Output = Rational; /// Rounds a [`Rational`] to an integer multiple of $2^k$ according to a specified rounding /// mode. The [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating /// whether the returned value is less than, equal to, or greater than the original value. /// /// Let $q = \frac{x}{2^k}$: /// /// $f(x, k, \mathrm{Down}) = 2^k \operatorname{sgn}(q) \lfloor |q| \rfloor.$ /// /// $f(x, k, \mathrm{Up}) = 2^k \operatorname{sgn}(q) \lceil |q| \rceil.$ /// /// $f(x, k, \mathrm{Floor}) = 2^k \lfloor q \rfloor.$ /// /// $f(x, k, \mathrm{Ceiling}) = 2^k \lceil q \rceil.$ /// /// $$ /// f(x, k, \mathrm{Nearest}) = \begin{cases} /// 2^k \lfloor q \rfloor & \text{if} \\quad /// q - \lfloor q \rfloor < \frac{1}{2} \\\\ /// 2^k \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\ /// 2^k \lfloor q \rfloor & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor /// \\ \text{is even} \\\\ /// 2^k \lceil q \rceil & /// \text{if} \\quad q - \lfloor q \rfloor = /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.} /// \end{cases} /// $$ /// /// $f(x, k, \mathrm{Exact}) = 2^k q$, but panics if $q \notin \Z$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// let q = Rational::exact_from(std::f64::consts::PI); /// assert_eq!( /// (&q).round_to_multiple_of_power_of_2(-3, Floor) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple_of_power_of_2(-3, Down) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// assert_eq!( /// (&q).round_to_multiple_of_power_of_2(-3, Ceiling) /// .to_debug_string(), /// "(13/4, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple_of_power_of_2(-3, Up) /// .to_debug_string(), /// "(13/4, Greater)" /// ); /// assert_eq!( /// (&q).round_to_multiple_of_power_of_2(-3, Nearest) /// .to_debug_string(), /// "(25/8, Less)" /// ); /// ``` fn round_to_multiple_of_power_of_2(self, pow: i64, rm: RoundingMode) -> (Rational, Ordering) { let (s, o) = Integer::rounding_from(self >> pow, rm); (Rational::from(s) << pow, o) } } impl RoundToMultipleOfPowerOf2Assign for Rational { /// Rounds a [`Rational`] to a multiple of $2^k$ in place, according to a specified rounding /// mode. An [`Ordering`] is returned, indicating whether the returned value is less than, equal /// to, or greater than the original value. /// /// See the [`RoundToMultipleOfPowerOf2`] documentation for details. /// /// but the latter should be used as it is clearer and more efficient. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), pow / /// Limb::WIDTH)`. /// /// # Panics /// Panics if `rm` is `Exact`, but `self` is not a multiple of the power of 2. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::RoundToMultipleOfPowerOf2Assign; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let q = Rational::exact_from(std::f64::consts::PI); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(-3, Floor), Less); /// assert_eq!(x.to_string(), "25/8"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(-3, Down), Less); /// assert_eq!(x.to_string(), "25/8"); /// /// let mut x = q.clone(); /// assert_eq!( /// x.round_to_multiple_of_power_of_2_assign(-3, Ceiling), /// Greater /// ); /// assert_eq!(x.to_string(), "13/4"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(-3, Up), Greater); /// assert_eq!(x.to_string(), "13/4"); /// /// let mut x = q.clone(); /// assert_eq!(x.round_to_multiple_of_power_of_2_assign(-3, Nearest), Less); /// assert_eq!(x.to_string(), "25/8"); /// ``` fn round_to_multiple_of_power_of_2_assign(&mut self, pow: i64, rm: RoundingMode) -> Ordering { *self >>= pow; let (s, o) = Integer::rounding_from(&*self, rm); *self = Self::from(s) << pow; o } } ================================================ FILE: malachite-q/src/arithmetic/shl.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; fn shl_unsigned_assign(x: &mut Rational, bits: T) where u64: TryFrom, { if *x == 0u32 { return; } let denominator_zeros = x.denominator.trailing_zeros().unwrap(); let bits_64 = u64::exact_from(bits); if denominator_zeros >= bits_64 { x.denominator >>= bits_64; } else { x.denominator >>= denominator_zeros; x.numerator <<= bits_64 - denominator_zeros; } } fn shl_unsigned_ref(x: &Rational, bits: T) -> Rational where u64: TryFrom, { if *x == 0u32 { return x.clone(); } let denominator_zeros = x.denominator.trailing_zeros().unwrap(); let bits_64 = u64::exact_from(bits); if denominator_zeros >= bits_64 { Rational { sign: x.sign, numerator: x.numerator.clone(), denominator: &x.denominator >> bits_64, } } else { Rational { sign: x.sign, numerator: &x.numerator << (bits_64 - denominator_zeros), denominator: &x.denominator >> denominator_zeros, } } } macro_rules! impl_shl_unsigned { ($t:ident) => { impl Shl<$t> for Rational { type Output = Rational; /// Left-shifts a [`Rational`] (multiplies it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(mut self, bits: $t) -> Rational { self <<= bits; self } } impl Shl<$t> for &Rational { type Output = Rational; /// Left-shifts a [`Rational`] (multiplies it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Rational { shl_unsigned_ref(self, bits) } } impl ShlAssign<$t> for Rational { /// Left-shifts a [`Rational`] (multiplies it by a power of 2), in place. /// /// $$ /// x \gets x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// # Examples /// See [here](super::shl#shl_assign). #[inline] fn shl_assign(&mut self, bits: $t) { shl_unsigned_assign(self, bits); } } }; } apply_to_unsigneds!(impl_shl_unsigned); fn shl_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Rational, bits: S, ) -> Rational where &'a Rational: Shl + Shr, { if bits >= S::ZERO { x << bits.unsigned_abs() } else { x >> bits.unsigned_abs() } } fn shl_assign_signed + Zero>(x: &mut Rational, bits: S) where Rational: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x <<= bits.unsigned_abs(); } else { *x >>= bits.unsigned_abs(); } } macro_rules! impl_shl_signed { ($t:ident) => { impl Shl<$t> for Rational { type Output = Rational; /// Left-shifts a [`Rational`] (multiplies it or divides it by a power of 2), taking it /// by value. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shl#shl). #[inline] fn shl(mut self, bits: $t) -> Rational { self <<= bits; self } } impl Shl<$t> for &Rational { type Output = Rational; /// Left-shifts a [`Rational`] (multiplies or divides it by a power of 2), taking it by /// reference. /// /// $$ /// f(x, k) = x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shl#shl). #[inline] fn shl(self, bits: $t) -> Rational { shl_signed_ref(self, bits) } } impl ShlAssign<$t> for Rational { /// Left-shifts a [`Rational`] (multiplies or divides it by a power of 2), in place. /// /// $$ /// x \gets x2^k. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `bits`. /// /// See [here](super::shl#shl_assign). fn shl_assign(&mut self, bits: $t) { shl_assign_signed(self, bits); } } }; } apply_to_signeds!(impl_shl_signed); ================================================ FILE: malachite-q/src/arithmetic/shr.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; fn shr_unsigned_assign(x: &mut Rational, bits: T) where u64: TryFrom, { if *x == 0u32 { return; } let numerator_zeros = x.numerator.trailing_zeros().unwrap(); let bits_64 = u64::exact_from(bits); if numerator_zeros >= bits_64 { x.numerator >>= bits_64; } else { x.denominator <<= bits_64 - numerator_zeros; x.numerator >>= numerator_zeros; } } fn shr_unsigned_ref(x: &Rational, bits: T) -> Rational where u64: TryFrom, { if *x == 0u32 { return x.clone(); } let numerator_zeros = x.numerator.trailing_zeros().unwrap(); let bits_64 = u64::exact_from(bits); if numerator_zeros >= bits_64 { Rational { sign: x.sign, numerator: &x.numerator >> bits_64, denominator: x.denominator.clone(), } } else { Rational { sign: x.sign, numerator: &x.numerator >> numerator_zeros, denominator: &x.denominator << (bits_64 - numerator_zeros), } } } macro_rules! impl_shr_unsigned { ($t:ident) => { impl Shr<$t> for Rational { type Output = Rational; /// Right-shifts a [`Rational`] (divides it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Rational { self >>= bits; self } } impl Shr<$t> for &Rational { type Output = Rational; /// Right-shifts a [`Rational`] (divides it by a power of 2), taking it by reference. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Rational { shr_unsigned_ref(self, bits) } } impl ShrAssign<$t> for Rational { /// Right-shifts a [`Rational`] (divides it by a power of 2), in place. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_unsigned_assign(self, bits); } } }; } apply_to_unsigneds!(impl_shr_unsigned); fn shr_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs + Zero>( x: &'a Rational, bits: S, ) -> Rational where &'a Rational: Shl + Shr, { if bits >= S::ZERO { x >> bits.unsigned_abs() } else { x << bits.unsigned_abs() } } fn shr_assign_signed + Zero>(x: &mut Rational, bits: S) where Rational: ShlAssign + ShrAssign, { if bits >= S::ZERO { *x >>= bits.unsigned_abs(); } else { *x <<= bits.unsigned_abs(); } } macro_rules! impl_shr_signed { ($t:ident) => { impl Shr<$t> for Rational { type Output = Rational; /// Right-shifts a [`Rational`] (divides it by a power of 2), taking it by value. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr). #[inline] fn shr(mut self, bits: $t) -> Rational { self >>= bits; self } } impl Shr<$t> for &Rational { type Output = Rational; /// Right-shifts a [`Rational`] (divides it by a power of 2), taking it by reference. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr). #[inline] fn shr(self, bits: $t) -> Rational { shr_signed_ref(self, bits) } } impl ShrAssign<$t> for Rational { /// Right-shifts a [`Rational`] (divides it by a power of 2), in reference. /// /// $$ /// f(x, k) = \frac{x}{2^k}. /// $$ /// /// # Worst-case complexity /// $T(n, m) = O(n + m)$ /// /// $M(n, m) = O(n + m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and /// $m$ is `max(bits, 0)`. /// /// See [here](super::shr#shr_assign). #[inline] fn shr_assign(&mut self, bits: $t) { shr_assign_signed(self, bits) } } }; } apply_to_signeds!(impl_shr_signed); ================================================ FILE: malachite-q/src/arithmetic/sign.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; impl Sign for Rational { /// Compares a [`Rational`] to zero. /// /// Returns `Greater`, `Equal`, or `Less`, depending on whether the [`Rational`] is positive, /// zero, or negative, respectively. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Sign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!(Rational::ZERO.sign(), Equal); /// assert_eq!(Rational::from_signeds(22, 7).sign(), Greater); /// assert_eq!(Rational::from_signeds(-22, 7).sign(), Less); /// ``` fn sign(&self) -> Ordering { if self.sign { if self.numerator == 0 { Equal } else { Greater } } else { Less } } } ================================================ FILE: malachite-q/src/arithmetic/simplest_rational_in_interval.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::traits::SimplestRationalInInterval; use crate::conversion::continued_fraction::to_continued_fraction::RationalContinuedFraction; use crate::conversion::traits::ContinuedFraction; use core::cmp::{ Ordering::{self, *}, max, min, }; use core::mem::swap; use malachite_base::num::arithmetic::traits::{AddMul, Ceiling, Floor, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Two, Zero}; use malachite_base::num::conversion::traits::IsInteger; use malachite_nz::natural::Natural; fn min_helper_oo<'a>(ox: &'a Option, oy: &'a Option) -> &'a Natural { if let Some(x) = ox.as_ref() { if let Some(y) = oy.as_ref() { min(x, y) } else { x } } else { oy.as_ref().unwrap() } } fn min_helper_xo<'a>(x: &'a Natural, oy: &'a Option) -> &'a Natural { if let Some(y) = oy.as_ref() { min(x, y) } else { x } } fn simplest_rational_one_alt_helper( x: &Natural, oy_n: &Option, mut cf_y: RationalContinuedFraction, numerator: &Natural, denominator: &Natural, previous_numerator: &Natural, previous_denominator: &Natural, ) -> Rational { // use [a_0; a_1, ... a_k - 1, 1] and [b_0; b_1, ... b_k] let (n, d) = if oy_n.is_some() && x - Natural::ONE == *oy_n.as_ref().unwrap() { let next_numerator = previous_numerator.add_mul(numerator, oy_n.as_ref().unwrap()); let next_denominator = previous_denominator.add_mul(denominator, oy_n.as_ref().unwrap()); let next_oy_n = cf_y.next(); if next_oy_n == Some(Natural::ONE) { let next_next_numerator = numerator + &next_numerator; let next_next_denominator = denominator + &next_denominator; // since y_n = 1, cf_y is not exhausted yet let y_n = cf_y.next().unwrap() + Natural::ONE; ( next_numerator.add_mul(next_next_numerator, &y_n), next_denominator.add_mul(next_next_denominator, y_n), ) } else { ( numerator + (next_numerator << 1), denominator + (next_denominator << 1), ) } } else { let ox_n_m_1 = x - Natural::ONE; let m = min_helper_xo(&ox_n_m_1, oy_n); let next_numerator = previous_numerator.add_mul(numerator, m); let next_denominator = previous_denominator.add_mul(denominator, m); ( numerator + (next_numerator << 1), denominator + (next_denominator << 1), ) }; Rational { sign: true, numerator: n, denominator: d, } } fn update_best(best: &mut Option, x: &Rational, y: &Rational, candidate: Rational) { if best.is_none() && candidate > *x && candidate < *y { *best = Some(candidate); } } impl Rational { /// Compares two [`Rational`]s according to their complexity. /// /// Complexity is defined as follows: If two [`Rational`]s have different denominators, then the /// one with the larger denominator is more complex. If they have the same denominator, then the /// one whose numerator is further from zero is more complex. Finally, if $q > 0$, then $q$ is /// simpler than $-q$. /// /// The [`Rational`]s ordered by complexity look like this: /// $$ /// 0, 1, -1, 2, -2, \ldots, 1/2, -1/2, 3/2, -3/2, \ldots, 1/3, -1/3, 2/3, -2/3, \ldots, \ldots. /// $$ /// This order is a well-order, and the order type of the [`Rational`]s under this order is /// $\omega^2$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// Rational::from_signeds(1, 2).cmp_complexity(&Rational::from_signeds(1, 3)), /// Less /// ); /// assert_eq!( /// Rational::from_signeds(1, 2).cmp_complexity(&Rational::from_signeds(3, 2)), /// Less /// ); /// assert_eq!( /// Rational::from_signeds(1, 2).cmp_complexity(&Rational::from_signeds(-1, 2)), /// Less /// ); /// ``` pub fn cmp_complexity(&self, other: &Self) -> Ordering { self.denominator_ref() .cmp(other.denominator_ref()) .then_with(|| self.numerator_ref().cmp(other.numerator_ref())) .then_with(|| (*self < 0u32).cmp(&(*other < 0u32))) } } impl SimplestRationalInInterval for Rational { /// Finds the simplest [`Rational`] contained in an open interval. /// /// Let $f(x, y) = p/q$, with $p$ and $q$ relatively prime. Then the following properties hold: /// - $x < p/q < y$ /// - If $x < m/n < y$, then $n \geq q$ /// - If $x < m/q < y$, then $|p| \leq |m|$ /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), /// y.significant_bits())`. /// /// # Panics /// Panics if $x \geq y$. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::arithmetic::traits::SimplestRationalInInterval; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::simplest_rational_in_open_interval( /// &Rational::from_signeds(1, 3), /// &Rational::from_signeds(1, 2) /// ), /// Rational::from_signeds(2, 5) /// ); /// assert_eq!( /// Rational::simplest_rational_in_open_interval( /// &Rational::from_signeds(-1, 3), /// &Rational::from_signeds(1, 3) /// ), /// Rational::ZERO /// ); /// assert_eq!( /// Rational::simplest_rational_in_open_interval( /// &Rational::from_signeds(314, 100), /// &Rational::from_signeds(315, 100) /// ), /// Rational::from_signeds(22, 7) /// ); /// ``` fn simplest_rational_in_open_interval(x: &Self, y: &Self) -> Rational { assert!(x < y); if *x < 0u32 && *y > 0u32 { return Self::ZERO; } let neg_x; let neg_y; let (neg, x, y) = if *x < 0u32 { neg_x = -x; neg_y = -y; (true, &neg_y, &neg_x) } else { (false, x, y) }; let (floor_x, mut cf_x) = x.continued_fraction(); let floor_x = floor_x.unsigned_abs(); let (floor_y, mut cf_y) = y.continued_fraction(); let floor_y = floor_y.unsigned_abs(); let mut best = None; if floor_x == floor_y { let floor = floor_x; let mut previous_numerator = Natural::ONE; let mut previous_denominator = Natural::ZERO; let mut numerator = floor; let mut denominator = Natural::ONE; let mut ox_n = cf_x.next(); let mut oy_n = cf_y.next(); while ox_n == oy_n { // They are both Some swap(&mut numerator, &mut previous_numerator); swap(&mut denominator, &mut previous_denominator); numerator = (&numerator).add_mul(&previous_numerator, &ox_n.unwrap()); denominator = (&denominator).add_mul(&previous_denominator, &oy_n.unwrap()); ox_n = cf_x.next(); oy_n = cf_y.next(); } // use [x_0; x_1, ... x_k] and [y_0; y_1, ... y_k] let m = min_helper_oo(&ox_n, &oy_n) + Natural::ONE; let n = (&previous_numerator).add_mul(&numerator, &m); let d = (&previous_denominator).add_mul(&denominator, &m); let candidate = Self { sign: true, numerator: n, denominator: d, }; update_best(&mut best, x, y, candidate); if let Some(x_n) = ox_n.as_ref() && cf_x.is_done() { update_best( &mut best, x, y, simplest_rational_one_alt_helper( x_n, &oy_n, cf_y.clone(), &numerator, &denominator, &previous_numerator, &previous_denominator, ), ); } if let Some(y_n) = oy_n.as_ref() && cf_y.is_done() { update_best( &mut best, x, y, simplest_rational_one_alt_helper( y_n, &ox_n, cf_x.clone(), &numerator, &denominator, &previous_numerator, &previous_denominator, ), ); } if ox_n.is_some() && oy_n.is_some() && cf_x.is_done() != cf_y.is_done() { if cf_y.is_done() { swap(&mut ox_n, &mut oy_n); swap(&mut cf_y, &mut cf_x); } let x_n = ox_n.unwrap(); let y_n = oy_n.unwrap(); if y_n == x_n - Natural::ONE { let next_y_n = cf_y.next().unwrap(); let next_numerator = (&previous_numerator).add_mul(&numerator, &y_n); let next_denominator = (&previous_denominator).add_mul(&denominator, &y_n); let (n, d) = if cf_y.is_done() && next_y_n == 2u32 { ( next_numerator * Natural::from(3u32) + (numerator << 1), next_denominator * Natural::from(3u32) + (denominator << 1), ) } else { ( previous_numerator + (numerator << 1), previous_denominator + (denominator << 1), ) }; let candidate = Self { sign: true, numerator: n, denominator: d, }; update_best(&mut best, x, y, candidate); } } } else { let candidate = if floor_y - Natural::ONE != floor_x || !cf_y.is_done() { Self::from(floor_x + Natural::ONE) } else { let floor = floor_x; // [f; x_1, x_2, x_3...] and [f + 1]. But to get any good candidates, we need [f; // x_1, x_2, x_3...] and [f; 1]. If x_1 does not exist, the result is [f; 2]. let (n, d) = if cf_x.is_done() { ((floor << 1) | Natural::ONE, Natural::TWO) } else { let x_1 = cf_x.next().unwrap(); if x_1 > Natural::ONE { if x_1 == 2u32 && cf_x.is_done() { // [f; 1, 1] and [f; 1], so [f; 1, 2] is a candidate. ( floor * Natural::from(3u32) + Natural::TWO, Natural::from(3u32), ) } else { // If x_1 > 1, we have [f; 2] as a candidate. ((floor << 1) | Natural::ONE, Natural::TWO) } } else { // x_2 exists since x_1 was 1 let x_2 = cf_x.next().unwrap(); // [f; 1, x_2] and [f; 1], so [f; 1, x_2 + 1] is a candidate. [f; 1, x_2 - // 1, 1] and [f; 1], but [f; 1, x_2] is not in the interval let k = &x_2 + Natural::ONE; (&floor * &k + floor + k, x_2 + Natural::TWO) } }; Self { sign: true, numerator: n, denominator: d, } }; update_best(&mut best, x, y, candidate); } let best = best.unwrap(); if neg { -best } else { best } } /// Finds the simplest [`Rational`] contained in a closed interval. /// /// Let $f(x, y) = p/q$, with $p$ and $q$ relatively prime. Then the following properties hold: /// - $x \leq p/q \leq y$ /// - If $x \leq m/n \leq y$, then $n \geq q$ /// - If $x \leq m/q \leq y$, then $|p| \leq |m|$ /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), /// y.significant_bits())`. /// /// # Panics /// Panics if $x > y$. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::arithmetic::traits::SimplestRationalInInterval; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::simplest_rational_in_closed_interval( /// &Rational::from_signeds(1, 3), /// &Rational::from_signeds(1, 2) /// ), /// Rational::from_signeds(1, 2) /// ); /// assert_eq!( /// Rational::simplest_rational_in_closed_interval( /// &Rational::from_signeds(-1, 3), /// &Rational::from_signeds(1, 3) /// ), /// Rational::ZERO /// ); /// assert_eq!( /// Rational::simplest_rational_in_closed_interval( /// &Rational::from_signeds(314, 100), /// &Rational::from_signeds(315, 100) /// ), /// Rational::from_signeds(22, 7) /// ); /// ``` fn simplest_rational_in_closed_interval(x: &Self, y: &Self) -> Rational { assert!(x <= y); if x == y { return x.clone(); } else if *x <= 0u32 && *y >= 0u32 { return Self::ZERO; } else if x.is_integer() { return if y.is_integer() { if *x >= 0u32 { min(x, y).clone() } else { max(x, y).clone() } } else if *x >= 0u32 { x.clone() } else { Self::from(y.floor()) }; } else if y.is_integer() { return if *x >= 0u32 { Self::from(x.ceiling()) } else { y.clone() }; } let mut best = Self::simplest_rational_in_open_interval(x, y); for q in [x, y] { if q.cmp_complexity(&best) == Less { best = q.clone(); } } best } } ================================================ FILE: malachite-q/src/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{CheckedSqrt, UnsignedAbs}; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; impl CheckedSqrt for Rational { type Output = Self; /// Returns the the square root of a [`Rational`], or `None` if it is not a perfect square. The /// [`Rational`] is taken by value. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from(99u8).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from(100u8).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// Rational::from(101u8).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from_signeds(22, 7) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// Rational::from_signeds(25, 9) /// .checked_sqrt() /// .to_debug_string(), /// "Some(5/3)" /// ); /// ``` fn checked_sqrt(self) -> Option { assert!(self >= 0); let (n, d) = self.into_numerator_and_denominator(); let sqrt_n; let sqrt_d; if n.significant_bits() <= d.significant_bits() { sqrt_n = n.checked_sqrt()?; sqrt_d = d.checked_sqrt()?; } else { sqrt_d = d.checked_sqrt()?; sqrt_n = n.checked_sqrt()?; } Some(Self { sign: sqrt_n >= 0, numerator: sqrt_n, denominator: sqrt_d, }) } } impl CheckedSqrt for &Rational { type Output = Rational; /// Returns the the square root of a [`Rational`], or `None` if it is not a perfect square. The /// [`Rational`] is taken by reference. /// /// $$ /// f(x) = \\begin{cases} /// \operatorname{Some}(sqrt{x}) & \text{if} \\quad \sqrt{x} \in \mathbb{Q}, \\\\ /// \operatorname{None} & \textrm{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `self` is negative. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::CheckedSqrt; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from(99u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from(100u8)).checked_sqrt().to_debug_string(), /// "Some(10)" /// ); /// assert_eq!( /// (&Rational::from(101u8)).checked_sqrt().to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from_signeds(22, 7)) /// .checked_sqrt() /// .to_debug_string(), /// "None" /// ); /// assert_eq!( /// (&Rational::from_signeds(25, 9)) /// .checked_sqrt() /// .to_debug_string(), /// "Some(5/3)" /// ); /// ``` fn checked_sqrt(self) -> Option { let (n, d) = self.numerator_and_denominator_ref(); let sqrt_n; let sqrt_d; if n.significant_bits() <= d.significant_bits() { sqrt_n = Integer::from_sign_and_abs_ref(*self >= 0, n).checked_sqrt()?; sqrt_d = d.checked_sqrt()?; } else { sqrt_d = d.checked_sqrt()?; sqrt_n = Integer::from_sign_and_abs_ref(*self >= 0, n).checked_sqrt()?; } Some(Rational { sign: true, numerator: sqrt_n.unsigned_abs(), denominator: sqrt_d, }) } } ================================================ FILE: malachite-q/src/arithmetic/square.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{Square, SquareAssign}; impl Square for Rational { type Output = Self; /// Squares a [`Rational`], taking it by value. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.square(), 0); /// assert_eq!(Rational::from_signeds(22, 7).square().to_string(), "484/49"); /// assert_eq!( /// Rational::from_signeds(-22, 7).square().to_string(), /// "484/49" /// ); /// ``` #[inline] fn square(mut self) -> Self { self.square_assign(); self } } impl Square for &Rational { type Output = Rational; /// Squares a [`Rational`], taking it by reference. /// /// $$ /// f(x) = x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::Square; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// assert_eq!((&Rational::ZERO).square(), 0); /// assert_eq!( /// (&Rational::from_signeds(22, 7)).square().to_string(), /// "484/49" /// ); /// assert_eq!( /// (&Rational::from_signeds(-22, 7)).square().to_string(), /// "484/49" /// ); /// ``` #[inline] fn square(self) -> Rational { Rational { sign: true, numerator: (&self.numerator).square(), denominator: (&self.denominator).square(), } } } impl SquareAssign for Rational { /// Squares a [`Rational`] in place. /// /// $$ /// x \gets x^2. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::SquareAssign; /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// /// let mut x = Rational::ZERO; /// x.square_assign(); /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x.square_assign(); /// assert_eq!(x.to_string(), "484/49"); /// /// let mut x = Rational::from_signeds(-22, 7); /// x.square_assign(); /// assert_eq!(x.to_string(), "484/49"); /// ``` fn square_assign(&mut self) { self.sign = true; self.numerator.square_assign(); self.denominator.square_assign(); } } ================================================ FILE: malachite-q/src/arithmetic/sub.rs ================================================ // Copyright © 2026 Mikhail Hogrefe // // Uses code adopted from the GNU MP Library. // // Copyright © 1991, 1994-1997, 2000, 2001, 2004, 2005 Free Software Foundation, Inc. // // 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 crate::Rational; use core::ops::{Sub, SubAssign}; use malachite_base::num::arithmetic::traits::{ DivExact, DivExactAssign, Gcd, GcdAssign, NegAssign, UnsignedAbs, }; use malachite_nz::integer::Integer; impl Sub for Rational { type Output = Self; /// Subtracts a [`Rational`] by another [`Rational`], taking both by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF - Rational::ONE_HALF, 0); /// assert_eq!( /// (Rational::from_signeds(22, 7) - Rational::from_signeds(99, 100)).to_string(), /// "1507/700" /// ); /// ``` fn sub(self, other: Self) -> Self { if self == 0u32 { return -other; } else if other == 0u32 { return self; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let diff_n = Integer::from_sign_and_abs(self.sign, self.numerator * &other.denominator) - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); let diff_d = self.denominator * other.denominator; Self { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: diff_d, } } else { let reduced_self_d = (self.denominator).div_exact(&gcd); let diff_n = Integer::from_sign_and_abs( self.sign, self.numerator * (&other.denominator).div_exact(&gcd), ) - Integer::from_sign_and_abs(other.sign, other.numerator * &reduced_self_d); gcd.gcd_assign(diff_n.unsigned_abs_ref()); if gcd == 1u32 { Self { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: other.denominator * reduced_self_d, } } else { Self { sign: diff_n >= 0, numerator: diff_n.unsigned_abs().div_exact(&gcd), denominator: (other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl Sub<&Self> for Rational { type Output = Self; /// Subtracts a [`Rational`] by another [`Rational`], taking the first by value and the second /// by reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ONE_HALF - &Rational::ONE_HALF, 0); /// assert_eq!( /// (Rational::from_signeds(22, 7) - &Rational::from_signeds(99, 100)).to_string(), /// "1507/700" /// ); /// ``` #[inline] fn sub(self, other: &Self) -> Self { -(other - self) } } impl Sub for &Rational { type Output = Rational; /// Subtracts a [`Rational`] by another [`Rational`], taking the first by reference and the /// second by value. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF - Rational::ONE_HALF, 0); /// assert_eq!( /// (&Rational::from_signeds(22, 7) - Rational::from_signeds(99, 100)).to_string(), /// "1507/700" /// ); /// ``` fn sub(self, other: Rational) -> Rational { if *self == 0u32 { return -other; } else if other == 0u32 { return self.clone(); } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let diff_n = Integer::from_sign_and_abs(self.sign, &self.numerator * &other.denominator) - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); let diff_d = &self.denominator * other.denominator; Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: diff_d, } } else { let reduced_self_d = (&self.denominator).div_exact(&gcd); let diff_n = Integer::from_sign_and_abs( self.sign, &self.numerator * (&other.denominator).div_exact(&gcd), ) - Integer::from_sign_and_abs(other.sign, other.numerator * &reduced_self_d); gcd.gcd_assign(diff_n.unsigned_abs_ref()); if gcd == 1u32 { Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: other.denominator * reduced_self_d, } } else { Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs().div_exact(&gcd), denominator: (other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl Sub<&Rational> for &Rational { type Output = Rational; /// Subtracts a [`Rational`] by another [`Rational`], taking both by reference. /// /// $$ /// f(x, y) = x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// assert_eq!(&Rational::ONE_HALF - &Rational::ONE_HALF, 0); /// assert_eq!( /// (&Rational::from_signeds(22, 7) - &Rational::from_signeds(99, 100)).to_string(), /// "1507/700" /// ); /// ``` fn sub(self, other: &Rational) -> Rational { if *self == 0u32 { return -other.clone(); } else if *other == 0u32 { return self.clone(); } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { let diff_n = Integer::from_sign_and_abs(self.sign, &self.numerator * &other.denominator) - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); let diff_d = &self.denominator * &other.denominator; Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: diff_d, } } else { let reduced_self_d = (&self.denominator).div_exact(&gcd); let diff_n = Integer::from_sign_and_abs( self.sign, &self.numerator * (&other.denominator).div_exact(&gcd), ) - Integer::from_sign_and_abs(other.sign, &other.numerator * &reduced_self_d); gcd.gcd_assign(diff_n.unsigned_abs_ref()); if gcd == 1u32 { Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs(), denominator: &other.denominator * reduced_self_d, } } else { Rational { sign: diff_n >= 0, numerator: diff_n.unsigned_abs().div_exact(&gcd), denominator: (&other.denominator).div_exact(gcd) * reduced_self_d, } } } } } impl SubAssign for Rational { /// Subtracts a [`Rational`] by another [`Rational`] in place, taking the [`Rational`] on the /// right-hand side by value. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x -= Rational::ONE_HALF; /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x -= Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "1507/700"); /// ``` fn sub_assign(&mut self, other: Self) { if *self == 0u32 { *self = -other; return; } else if other == 0u32 { return; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { self.numerator *= &other.denominator; let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); self.sign = diff_n >= 0; self.numerator = diff_n.unsigned_abs(); self.denominator *= other.denominator; } else { self.denominator.div_exact_assign(&gcd); self.numerator *= (&other.denominator).div_exact(&gcd); let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) - Integer::from_sign_and_abs(other.sign, other.numerator * &self.denominator); gcd.gcd_assign(diff_n.unsigned_abs_ref()); self.sign = diff_n >= 0; if gcd == 1u32 { self.numerator = diff_n.unsigned_abs(); self.denominator *= other.denominator; } else { self.numerator = diff_n.unsigned_abs().div_exact(&gcd); self.denominator *= (other.denominator).div_exact(gcd); } } } } impl SubAssign<&Self> for Rational { /// Subtracts a [`Rational`] by another [`Rational`] in place, taking the [`Rational`] on the /// right-hand side by reference. /// /// $$ /// x \gets x - y. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// /// let mut x = Rational::ONE_HALF; /// x -= &Rational::ONE_HALF; /// assert_eq!(x, 0); /// /// let mut x = Rational::from_signeds(22, 7); /// x -= &Rational::from_signeds(99, 100); /// assert_eq!(x.to_string(), "1507/700"); /// ``` fn sub_assign(&mut self, other: &Self) { if *self == 0u32 { self.clone_from(other); self.neg_assign(); return; } else if *other == 0u32 { return; } let mut gcd = (&self.denominator).gcd(&other.denominator); if gcd == 1u32 { self.numerator *= &other.denominator; let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); self.sign = diff_n >= 0; self.numerator = diff_n.unsigned_abs(); self.denominator *= &other.denominator; } else { self.denominator.div_exact_assign(&gcd); self.numerator *= (&other.denominator).div_exact(&gcd); let diff_n = Integer::from_sign_and_abs_ref(self.sign, &self.numerator) - Integer::from_sign_and_abs(other.sign, &other.numerator * &self.denominator); gcd.gcd_assign(diff_n.unsigned_abs_ref()); self.sign = diff_n >= 0; if gcd == 1u32 { self.numerator = diff_n.unsigned_abs(); self.denominator *= &other.denominator; } else { self.numerator = diff_n.unsigned_abs().div_exact(&gcd); self.denominator *= (&other.denominator).div_exact(gcd); } } } } ================================================ FILE: malachite-q/src/arithmetic/traits.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::natural::Natural; /// Replaces a number with the closest [`Rational`] whose denominator does not exceed the specified /// maximum. pub trait ApproximateAssign { fn approximate_assign(&mut self, max_denominator: &Natural); } /// Returns the closest [`Rational`] whose denominator does not exceed the specified maximum. pub trait Approximate { fn approximate(self, max_denominator: &Natural) -> Rational; } /// Finds the simplest [`Rational`] contained in an interval. pub trait SimplestRationalInInterval { /// Finds the simplest [`Rational`] contained in an open interval. /// /// Simplicity is defined as follows: If two [`Rational`]s have different denominators, then the /// one with the smaller denominator is simpler. If they have the same denominator, then the one /// whose numerator is closer to zero is simpler. Finally, if $q > 0$, then $q$ is simpler than /// $-q$. fn simplest_rational_in_open_interval(x: &Self, y: &Self) -> Rational; /// Finds the simplest [`Rational`] contained in a closed interval. /// /// Simplicity is defined as follows: If two [`Rational`]s have different denominators, then the /// one with the smaller denominator is simpler. If they have the same denominator, then the one /// whose numerator is closer to zero is simpler. Finally, if $q > 0$, then $q$ is simpler than /// $-q$. fn simplest_rational_in_closed_interval(x: &Self, y: &Self) -> Rational; } // Returns an iterator of all denominators that appear in the [`Rational`]s contained in a closed // interval. pub trait DenominatorsInClosedInterval { type Denominators: Iterator; fn denominators_in_closed_interval(a: Rational, b: Rational) -> Self::Denominators; } ================================================ FILE: malachite-q/src/bin.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #[cfg(feature = "bin_build")] extern crate itertools; #[cfg(feature = "bin_build")] #[macro_use] extern crate malachite_base; #[cfg(feature = "bin_build")] extern crate malachite_nz; #[cfg(feature = "bin_build")] extern crate malachite_q; #[cfg(feature = "bin_build")] extern crate num; #[cfg(feature = "bin_build")] extern crate rug; #[cfg(feature = "bin_build")] extern crate serde; #[cfg(feature = "bin_build")] extern crate serde_json; #[cfg(feature = "bin_build")] use crate::bin_util::demo_and_bench::register; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::Runner; #[cfg(feature = "bin_build")] use malachite_base::test_util::runner::cmd::read_command_line_arguments; // Examples: // // ``` // cargo run --release --features bin_build -- -l 10000 -m special_random -d demo_from_naturals // -c "mean_bits_n 128 mean_bits_d 1" // ``` #[cfg(feature = "bin_build")] fn main() { let args = read_command_line_arguments("malachite-q test utils"); let mut runner = Runner::new(); register(&mut runner); if let Some(demo_key) = args.demo_key { runner.run_demo(&demo_key, args.generation_mode, &args.config, args.limit); } else if let Some(bench_key) = args.bench_key { runner.run_bench( &bench_key, args.generation_mode, &args.config, args.limit, &args.out, ); } else { panic!(); } } #[cfg(not(feature = "bin_build"))] fn main() {} #[cfg(feature = "bin_build")] pub mod bin_util { pub mod demo_and_bench; } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; use num::Signed; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_abs); register_demo!(runner, demo_rational_abs_ref); register_demo!(runner, demo_rational_abs_assign); register_bench!(runner, benchmark_rational_abs_library_comparison); register_bench!(runner, benchmark_rational_abs_evaluation_strategy); register_bench!(runner, benchmark_rational_abs_assign); } fn demo_rational_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("|{}| = {}", n.clone(), n.abs()); } } fn demo_rational_abs_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("|&{}| = {}", n, (&n).abs()); } } fn demo_rational_abs_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.abs_assign(); println!("n := {n_old}; n.abs_assign(); n = {n}"); } } fn benchmark_rational_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.abs())), ("num", &mut |(n, _, _)| no_out!(n.abs())), ("rug", &mut |(_, n, _)| no_out!(n.abs().cmp0())), ], ); } fn benchmark_rational_abs_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.abs()", &mut |n| no_out!(n.abs())), ("(&Rational).abs()", &mut |n| no_out!((&n).abs())), ], ); } fn benchmark_rational_abs_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.abs_assign()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.abs_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{AbsDiff, AbsDiffAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_rational_max_bit_bucketer; use malachite_q::test_util::generators::rational_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_abs_diff); register_demo!(runner, demo_rational_abs_diff_val_ref); register_demo!(runner, demo_rational_abs_diff_ref_val); register_demo!(runner, demo_rational_abs_diff_ref_ref); register_demo!(runner, demo_rational_abs_diff_assign); register_demo!(runner, demo_rational_abs_diff_assign_ref); register_bench!( runner, benchmark_rational_abs_diff_assign_evaluation_strategy ); register_bench!(runner, benchmark_rational_abs_diff_evaluation_strategy); } fn demo_rational_abs_diff(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("|{} - {}| = {:?}", x_old, y_old, x.abs_diff(y)); } } fn demo_rational_abs_diff_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("|{} - &{}| = {:?}", x_old, y, x.abs_diff(&y)); } } fn demo_rational_abs_diff_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("|&{} - {}| = {:?}", x, y_old, (&x).abs_diff(y)); } } fn demo_rational_abs_diff_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!("|&{} - &{}| = {:?}", x, y, (&x).abs_diff(&y)); } } fn demo_rational_abs_diff_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.abs_diff_assign(y); println!("x := {x_old}; x.abs_diff_assign({y_old}); x = {x}"); } } fn demo_rational_abs_diff_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.abs_diff_assign(&y); println!("x := {x_old}; x.abs_diff_assign(&{y}); x = {x}"); } } fn benchmark_rational_abs_diff_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs_diff_assign(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational.abs_diff_assign(Rational)", &mut |(mut x, y)| { x.abs_diff_assign(y); }), ("Rational.abs_diff_assign(&Rational)", &mut |(mut x, y)| { x.abs_diff_assign(&y); }), ], ); } fn benchmark_rational_abs_diff_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.abs_diff(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational.abs_diff(Rational)", &mut |(x, y)| { no_out!(x.abs_diff(y)); }), ("Rational.abs_diff(&Rational)", &mut |(x, y)| { no_out!(x.abs_diff(&y)); }), ("&Rational.abs_diff(Rational)", &mut |(x, y)| { no_out!((&x).abs_diff(y)); }), ("&Rational.abs_diff(&Rational)", &mut |(x, y)| { no_out!((&x).abs_diff(&y)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::arithmetic::add::add_naive; use malachite_q::test_util::arithmetic::add::rational_sum_naive; use malachite_q::test_util::bench::bucketers::{ pair_2_pair_rational_max_bit_bucketer, pair_rational_max_bit_bucketer, triple_3_pair_rational_max_bit_bucketer, triple_3_vec_rational_sum_bits_bucketer, vec_rational_sum_bits_bucketer, }; use malachite_q::test_util::generators::{ rational_pair_gen, rational_pair_gen_nrm, rational_pair_gen_rm, rational_vec_gen, rational_vec_gen_nrm, }; use num::BigRational; use std::iter::Sum; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_add); register_demo!(runner, demo_rational_add_val_ref); register_demo!(runner, demo_rational_add_ref_val); register_demo!(runner, demo_rational_add_ref_ref); register_demo!(runner, demo_rational_add_assign); register_demo!(runner, demo_rational_add_assign_ref); register_demo!(runner, demo_rational_sum); register_demo!(runner, demo_rational_ref_sum); register_bench!(runner, benchmark_rational_add_library_comparison); register_bench!(runner, benchmark_rational_add_evaluation_strategy); register_bench!(runner, benchmark_rational_add_algorithms); register_bench!(runner, benchmark_rational_add_assign_library_comparison); register_bench!(runner, benchmark_rational_add_assign_evaluation_strategy); register_bench!(runner, benchmark_rational_sum_algorithms); register_bench!(runner, benchmark_rational_sum_library_comparison); register_bench!(runner, benchmark_rational_sum_evaluation_strategy); } fn demo_rational_add(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} + {} = {}", x_old, y_old, x + y); } } fn demo_rational_add_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} + &{} = {}", x_old, y, x + &y); } } fn demo_rational_add_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} + {} = {}", x, y_old, &x + y); } } fn demo_rational_add_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!("&{} + &{} = {}", x, y, &x + &y); } } fn demo_rational_add_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += y.clone(); println!("x := {x_old}; x += {y}; x = {x}"); } } fn demo_rational_add_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x += &y; println!("x := {x_old}; x += &{y}; x = {x}"); } } fn demo_rational_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in rational_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs.clone(), Rational::sum(xs.into_iter())); } } fn demo_rational_ref_sum(gm: GenMode, config: &GenConfig, limit: usize) { for xs in rational_vec_gen().get(gm, config).take(limit) { println!("sum({:?}) = {}", xs, Rational::sum(xs.iter())); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_add_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational + Rational", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x + y)), ("num", &mut |((x, y), _, _)| no_out!(x + y)), ("rug", &mut |(_, (x, y), _)| no_out!(x + y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_add_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational + Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational + Rational", &mut |(x, y)| no_out!(x + y)), ("Rational + &Rational", &mut |(x, y)| no_out!(x + &y)), ("&Rational + Rational", &mut |(x, y)| no_out!(&x + y)), ("&Rational + &Rational", &mut |(x, y)| no_out!(&x + &y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_add_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational + Rational", BenchmarkType::Algorithms, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x + y)), ("naive", &mut |(x, y)| no_out!(add_naive(x, y))), ], ); } fn benchmark_rational_add_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational += Rational", BenchmarkType::LibraryComparison, rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x += y), ("rug", &mut |((mut x, y), _)| x += y)], ); } fn benchmark_rational_add_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational += Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational += Rational", &mut |(mut x, y)| no_out!(x += y)), ("Rational += &Rational", &mut |(mut x, y)| no_out!(x += &y)), ], ); } fn benchmark_rational_sum_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::sum(Iterator)", BenchmarkType::LibraryComparison, rational_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_rational_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Rational::sum(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigRational::sum(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Rational::sum(xs.iter())); }), ], ); } fn benchmark_rational_sum_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::sum(Iterator)", BenchmarkType::Algorithms, rational_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_rational_sum_bits_bucketer(), &mut [ ("default", &mut |xs| no_out!(Rational::sum(xs.into_iter()))), ("naive", &mut |xs| { no_out!(rational_sum_naive(xs.into_iter())); }), ], ); } fn benchmark_rational_sum_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::sum(Iterator)", BenchmarkType::EvaluationStrategy, rational_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_rational_sum_bits_bucketer(), &mut [ ("Rational::sum(Iterator)", &mut |xs| { no_out!(Rational::sum(xs.into_iter())); }), ("Rational::sum(Iterator)", &mut |xs| { no_out!(Rational::sum(xs.iter())); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/approximate.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_natural_inclusive_range; use malachite_q::arithmetic::traits::{Approximate, ApproximateAssign}; use malachite_q::test_util::arithmetic::approximate::approximate_naive; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_gen_var_7, rational_natural_pair_gen_var_3, rational_natural_pair_gen_var_4, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_approximate_assign); register_demo!(runner, demo_rational_approximate); register_demo!(runner, demo_rational_approximate_ref); register_demo!(runner, demo_rational_approximate_2); register_bench!(runner, benchmark_rational_approximate_assign); register_bench!(runner, benchmark_rational_approximate_algorithms); register_bench!(runner, benchmark_rational_approximate_evaluation_strategy); } fn demo_rational_approximate_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_natural_pair_gen_var_3() .get(gm, config) .take(limit) { let x_old = x.clone(); x.approximate_assign(&y); println!("x := {x_old}; x.approximate_assign({y}); x = {x}"); } } fn demo_rational_approximate(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen_var_3() .get(gm, config) .take(limit) { println!("({}).approximate({}) = {}", x.clone(), y, x.approximate(&y)); } } fn demo_rational_approximate_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen_var_3() .get(gm, config) .take(limit) { println!("(&{}).approximate({}) = {}", x, y, (&x).approximate(&y)); } } fn demo_rational_approximate_2(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen_var_7().get(gm, config).take(limit) { println!("{x}"); for d in exhaustive_natural_inclusive_range(Natural::ONE, x.to_denominator()) { let a = (&x).approximate(&d); println!(" {}: {} ≈ {}", d, a, NiceFloat(f64::exact_from(&a))); } } } fn benchmark_rational_approximate_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.approximate_assign(&Natural)", BenchmarkType::Single, rational_natural_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(mut x, y)| x.approximate_assign(&y))], ); } fn benchmark_rational_approximate_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.approximate(&Natural)", BenchmarkType::Algorithms, rational_natural_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ ("default", &mut |(x, y)| no_out!(x.approximate(&y))), ("naive", &mut |(x, y)| no_out!(approximate_naive(&x, &y))), ], ); } fn benchmark_rational_approximate_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.approximate(&Natural)", BenchmarkType::EvaluationStrategy, rational_natural_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ ("Rational.approximate(&Natural)", &mut |(x, y)| { no_out!(x.approximate(&y)); }), ("(&Rational).approximate(&Natural)", &mut |(x, y)| { no_out!((&x).approximate(&y)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, CeilingAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_ceiling); register_demo!(runner, demo_rational_ceiling_ref); register_demo!(runner, demo_rational_ceiling_assign); register_bench!(runner, benchmark_rational_ceiling_library_comparison); register_bench!(runner, benchmark_rational_ceiling_evaluation_strategy); register_bench!(runner, benchmark_rational_ceiling_assign); } fn demo_rational_ceiling(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("ceiling({}) = {}", n.clone(), n.ceiling()); } } fn demo_rational_ceiling_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("ceiling(&{}) = {}", n, (&n).ceiling()); } } fn demo_rational_ceiling_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.ceiling_assign(); println!("n := {n_old}; n.ceiling_assign(); n = {n}"); } } #[allow(unused_must_use)] fn benchmark_rational_ceiling_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.ceiling())), ("num", &mut |(n, _, _)| no_out!(n.ceil())), ("rug", &mut |(_, n, _)| no_out!(n.ceil())), ], ); } fn benchmark_rational_ceiling_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.ceiling()", &mut |n| no_out!(n.ceiling())), ("(&Rational).ceiling()", &mut |n| no_out!((&n).ceiling())), ], ); } fn benchmark_rational_ceiling_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_assign()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.ceiling_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/denominators_in_closed_interval.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::prefix_to_string; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::arithmetic::traits::DenominatorsInClosedInterval; use malachite_q::test_util::bench::bucketers::pair_2_rational_bit_bucketer; use malachite_q::test_util::generators::rational_pair_gen_var_3; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_denominators_in_closed_interval); register_bench!(runner, benchmark_denominators_in_closed_interval); } fn demo_denominators_in_closed_interval(gm: GenMode, config: &GenConfig, limit: usize) { for (a, b) in rational_pair_gen_var_3().get(gm, config).take(limit) { println!( "denominators_in_closed_interval({}, {}) = {}", a, b, prefix_to_string( Rational::denominators_in_closed_interval(a.clone(), b.clone()), 20 ) ); } } fn benchmark_denominators_in_closed_interval( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "denominators_in_closed_interval(&Rational, &Rational)", BenchmarkType::Single, rational_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(a, b)| { no_out!(Rational::denominators_in_closed_interval(a, b)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedDiv; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::arithmetic::div::div_naive; use malachite_q::test_util::bench::bucketers::{ pair_2_pair_rational_max_bit_bucketer, pair_rational_max_bit_bucketer, triple_3_pair_rational_max_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_pair_gen, rational_pair_gen_nm, rational_pair_gen_var_1, rational_pair_gen_var_1_nrm, rational_pair_gen_var_1_rm, }; use num::CheckedDiv as NumCheckedDiv; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_div); register_demo!(runner, demo_rational_div_val_ref); register_demo!(runner, demo_rational_div_ref_val); register_demo!(runner, demo_rational_div_ref_ref); register_demo!(runner, demo_rational_div_assign); register_demo!(runner, demo_rational_div_assign_ref); register_demo!(runner, demo_rational_checked_div); register_demo!(runner, demo_rational_checked_div_val_ref); register_demo!(runner, demo_rational_checked_div_ref_val); register_demo!(runner, demo_rational_checked_div_ref_ref); register_bench!(runner, benchmark_rational_div_library_comparison); register_bench!(runner, benchmark_rational_div_evaluation_strategy); register_bench!(runner, benchmark_rational_div_algorithms); register_bench!(runner, benchmark_rational_div_assign_library_comparison); register_bench!(runner, benchmark_rational_div_assign_evaluation_strategy); register_bench!(runner, benchmark_rational_checked_div_library_comparison); register_bench!(runner, benchmark_rational_checked_div_evaluation_strategy); } fn demo_rational_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} / {} = {}", x_old, y_old, x / y); } } fn demo_rational_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} / &{} = {}", x_old, y, x / &y); } } fn demo_rational_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} / {} = {}", x, y_old, &x / y); } } fn demo_rational_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { println!("&{} / &{} = {}", x, y, &x / &y); } } fn demo_rational_div_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x /= {y}; x = {x}"); } } fn demo_rational_div_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x /= &{y}; x = {x}"); } } fn demo_rational_checked_div(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).checked_div({}) = {:?}", x_old, y_old, x.checked_div(y) ); } } fn demo_rational_checked_div_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("({}).checked_div(&{}) = {:?}", x_old, y, x.checked_div(&y)); } } fn demo_rational_checked_div_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!( "(&{}).checked_div({}) = {:?}", x, y_old, (&x).checked_div(y) ); } } fn demo_rational_checked_div_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!("(&{}).checked_div(&{}) = {:?}", x, y, (&x).checked_div(&y)); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Rational", BenchmarkType::LibraryComparison, rational_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x / y)), ("num", &mut |((x, y), _, _)| no_out!(x / y)), ("rug", &mut |(_, (x, y), _)| no_out!(x / y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational / Rational", &mut |(x, y)| no_out!(x / y)), ("Rational / &Rational", &mut |(x, y)| no_out!(x / &y)), ("&Rational / Rational", &mut |(x, y)| no_out!(&x / y)), ("&Rational / &Rational", &mut |(x, y)| no_out!(&x / &y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_div_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational / Rational", BenchmarkType::Algorithms, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x / y)), ("naive", &mut |(x, y)| no_out!(div_naive(x, y))), ], ); } fn benchmark_rational_div_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational *= Rational", BenchmarkType::LibraryComparison, rational_pair_gen_var_1_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x *= y), ("rug", &mut |((mut x, y), _)| x *= y)], ); } fn benchmark_rational_div_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational *= Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational *= Rational", &mut |(mut x, y)| no_out!(x *= y)), ("Rational *= &Rational", &mut |(mut x, y)| no_out!(x *= &y)), ], ); } fn benchmark_rational_checked_div_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.checked_div(Rational)", BenchmarkType::LibraryComparison, rational_pair_gen_nm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.checked_div(&y))), ("num", &mut |((x, y), _)| no_out!(x.checked_div(&y))), ], ); } fn benchmark_rational_checked_div_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.checked_div(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational.checked_div(Rational)", &mut |(x, y)| { no_out!(x.checked_div(y)); }), ("Rational.checked_div(&Rational)", &mut |(x, y)| { no_out!(x.checked_div(&y)); }), ("(&Rational).checked_div(Rational)", &mut |(x, y)| { no_out!((&x).checked_div(y)); }), ("(&Rational).checked_div(&Rational)", &mut |(x, y)| { no_out!((&x).checked_div(&y)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/floor.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Floor, FloorAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_floor); register_demo!(runner, demo_rational_floor_ref); register_demo!(runner, demo_rational_floor_assign); register_bench!(runner, benchmark_rational_floor_library_comparison); register_bench!(runner, benchmark_rational_floor_evaluation_strategy); register_bench!(runner, benchmark_rational_floor_assign); } fn demo_rational_floor(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("floor({}) = {}", n.clone(), n.floor()); } } fn demo_rational_floor_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("floor(&{}) = {}", n, (&n).floor()); } } fn demo_rational_floor_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.floor_assign(); println!("n := {n_old}; n.floor_assign(); n = {n}"); } } #[allow(unused_must_use)] fn benchmark_rational_floor_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.floor())), ("num", &mut |(n, _, _)| no_out!(n.floor())), ("rug", &mut |(_, n, _)| no_out!(n.floor())), ], ); } fn benchmark_rational_floor_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.floor()", &mut |n| no_out!(n.floor())), ("(&Rational).floor()", &mut |n| no_out!((&n).floor())), ], ); } fn benchmark_rational_floor_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.floor_assign()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.floor_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_is_power_of_2); register_bench!(runner, benchmark_rational_is_power_of_2); } fn demo_rational_is_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { if x.is_power_of_2() { println!("{x} is a power of 2"); } else { println!("{x} is not a power of 2"); } } } fn benchmark_rational_is_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.is_power_of_2()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_power_of_2()))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingLogBase, CheckedLogBase, FloorLogBase}; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ pair_rational_max_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen_var_2, rational_pair_gen_var_7}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_approx_log); register_demo!(runner, demo_rational_floor_log_base); register_demo!(runner, demo_rational_ceiling_log_base); register_demo!(runner, demo_rational_checked_log_base); register_bench!(runner, benchmark_approx_log); register_bench!(runner, benchmark_rational_floor_log_base); register_bench!(runner, benchmark_rational_ceiling_log_base); register_bench!(runner, benchmark_rational_checked_log_base); } fn demo_rational_approx_log(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_2().get(gm, config).take(limit) { println!("log({}) ≈ {}", n, NiceFloat(n.approx_log())); } } fn demo_rational_floor_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_pair_gen_var_7().get(gm, config).take(limit) { println!( "floor_log_base({}, {}) = {}", n, base, n.floor_log_base(&base) ); } } fn demo_rational_ceiling_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_pair_gen_var_7().get(gm, config).take(limit) { println!( "ceiling_log_base({}, {}) = {}", n, base, n.ceiling_log_base(&base) ); } } fn demo_rational_checked_log_base(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_pair_gen_var_7().get(gm, config).take(limit) { println!( "checked_log_base({}, {}) = {:?}", n, base, n.checked_log_base(&base) ); } } fn benchmark_approx_log(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "(&Rational).approx_log()", BenchmarkType::Single, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("n"), &mut [("default", &mut |n| no_out!(n.approx_log()))], ); } fn benchmark_rational_floor_log_base( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Rational).floor_log_base(&Rational)", BenchmarkType::Single, rational_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("n", "base"), &mut [("Malachite", &mut |(n, base)| { no_out!(n.floor_log_base(&base)); })], ); } fn benchmark_rational_ceiling_log_base( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Rational).ceiling_log_base(&Rational)", BenchmarkType::Single, rational_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("n", "base"), &mut [("Malachite", &mut |(n, base)| { no_out!(n.ceiling_log_base(&base)); })], ); } fn benchmark_rational_checked_log_base( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "(&Rational).checked_log_base(&Rational)", BenchmarkType::Single, rational_pair_gen_var_7().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("n", "base"), &mut [("Malachite", &mut |(n, base)| { no_out!(n.checked_log_base(&base)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingLogBase2, CheckedLogBase2, FloorLogBase2}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::{rational_gen_var_1, rational_gen_var_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_floor_log_base_2_abs); register_demo!(runner, demo_rational_ceiling_log_base_2_abs); register_demo!(runner, demo_rational_floor_log_base_2); register_demo!(runner, demo_rational_ceiling_log_base_2); register_demo!(runner, demo_rational_checked_log_base_2); register_bench!(runner, benchmark_rational_floor_log_base_2_abs); register_bench!(runner, benchmark_rational_ceiling_log_base_2_abs); register_bench!(runner, benchmark_rational_floor_log_base_2); register_bench!(runner, benchmark_rational_ceiling_log_base_2); register_bench!(runner, benchmark_rational_checked_log_base_2); } fn demo_rational_floor_log_base_2_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_1().get(gm, config).take(limit) { println!("floor_log_base_2_abs({}) = {}", n, n.floor_log_base_2_abs()); } } fn demo_rational_ceiling_log_base_2_abs(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_1().get(gm, config).take(limit) { println!( "ceiling_log_base_2_abs({}) = {}", n, n.ceiling_log_base_2_abs() ); } } fn demo_rational_floor_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_2().get(gm, config).take(limit) { println!("floor_log_base_2({}) = {}", n, n.floor_log_base_2()); } } fn demo_rational_ceiling_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_2().get(gm, config).take(limit) { println!("ceiling_log_base_2({}) = {}", n, n.ceiling_log_base_2()); } } fn demo_rational_checked_log_base_2(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_2().get(gm, config).take(limit) { println!("checked_log_base_2({}) = {:?}", n, n.checked_log_base_2()); } } fn benchmark_rational_floor_log_base_2_abs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor_log_base_2_abs()", BenchmarkType::Single, rational_gen_var_1().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.floor_log_base_2_abs()))], ); } fn benchmark_rational_ceiling_log_base_2_abs( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_log_base_2_abs()", BenchmarkType::Single, rational_gen_var_1().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.ceiling_log_base_2_abs()))], ); } fn benchmark_rational_floor_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor_log_base_2()", BenchmarkType::Single, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.floor_log_base_2()))], ); } fn benchmark_rational_ceiling_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_log_base_2()", BenchmarkType::Single, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.ceiling_log_base_2()))], ); } fn benchmark_rational_checked_log_base_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor_log_base_2()", BenchmarkType::Single, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |n| no_out!(n.checked_log_base_2()))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBasePowerOf2, CheckedLogBasePowerOf2, FloorLogBasePowerOf2, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::rational_signed_pair_gen_var_5; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_floor_log_base_power_of_2); register_demo!(runner, demo_rational_ceiling_log_base_power_of_2); register_demo!(runner, demo_rational_checked_log_base_power_of_2); register_bench!(runner, benchmark_rational_floor_log_base_power_of_2); register_bench!(runner, benchmark_rational_ceiling_log_base_power_of_2); register_bench!(runner, benchmark_rational_checked_log_base_power_of_2); } fn demo_rational_floor_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in rational_signed_pair_gen_var_5().get(gm, config).take(limit) { println!( "floor_log_base_power_of_2({}, {}) = {}", n, pow, n.floor_log_base_power_of_2(pow) ); } } fn demo_rational_ceiling_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in rational_signed_pair_gen_var_5().get(gm, config).take(limit) { println!( "ceiling_log_base_power_of_2({}, {}) = {}", n, pow, n.ceiling_log_base_power_of_2(pow) ); } } fn demo_rational_checked_log_base_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow) in rational_signed_pair_gen_var_5().get(gm, config).take(limit) { println!( "checked_log_base_power_of_2({}, {}) = {:?}", n, pow, n.checked_log_base_power_of_2(pow) ); } } fn benchmark_rational_floor_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor_log_base_power_of_2(u64)", BenchmarkType::Single, rational_signed_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.floor_log_base_power_of_2(pow)); })], ); } fn benchmark_rational_ceiling_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_log_base_power_of_2(u64)", BenchmarkType::Single, rational_signed_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.ceiling_log_base_power_of_2(pow)); })], ); } fn benchmark_rational_checked_log_base_power_of_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.floor_log_base_power_of_2(u64)", BenchmarkType::Single, rational_signed_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(n, pow)| { no_out!(n.checked_log_base_power_of_2(pow)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { abs::register(runner); abs_diff::register(runner); add::register(runner); approximate::register(runner); ceiling::register(runner); denominators_in_closed_interval::register(runner); div::register(runner); floor::register(runner); is_power_of_2::register(runner); log_base::register(runner); log_base_2::register(runner); log_base_power_of_2::register(runner); mod_op::register(runner); mul::register(runner); neg::register(runner); next_power_of_2::register(runner); pow::register(runner); power_of_2::register(runner); reciprocal::register(runner); root::register(runner); round_to_multiple::register(runner); round_to_multiple_of_power_of_2::register(runner); shl::register(runner); shr::register(runner); sign::register(runner); simplest_rational_in_interval::register(runner); sqrt::register(runner); square::register(runner); sub::register(runner); } mod abs; mod abs_diff; mod add; mod approximate; mod ceiling; mod denominators_in_closed_interval; mod div; mod floor; mod is_power_of_2; mod log_base; mod log_base_2; mod log_base_power_of_2; mod mod_op; mod mul; mod neg; mod next_power_of_2; mod pow; mod power_of_2; mod reciprocal; mod root; mod round_to_multiple; mod round_to_multiple_of_power_of_2; mod shl; mod shr; mod sign; mod simplest_rational_in_interval; mod sqrt; mod square; mod sub; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CeilingMod, CeilingModAssign, Mod, ModAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::arithmetic::mod_op::{ceiling_mod_naive, mod_op_naive, rem_naive}; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, pair_2_pair_1_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_pair_gen_var_1, rational_pair_gen_var_1_nm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_mod); register_demo!(runner, demo_rational_mod_val_ref); register_demo!(runner, demo_rational_mod_ref_val); register_demo!(runner, demo_rational_mod_ref_ref); register_demo!(runner, demo_rational_mod_assign); register_demo!(runner, demo_rational_mod_assign_ref); register_demo!(runner, demo_rational_rem); register_demo!(runner, demo_rational_rem_val_ref); register_demo!(runner, demo_rational_rem_ref_val); register_demo!(runner, demo_rational_rem_ref_ref); register_demo!(runner, demo_rational_rem_assign); register_demo!(runner, demo_rational_rem_assign_ref); register_demo!(runner, demo_rational_ceiling_mod); register_demo!(runner, demo_rational_ceiling_mod_val_ref); register_demo!(runner, demo_rational_ceiling_mod_ref_val); register_demo!(runner, demo_rational_ceiling_mod_ref_ref); register_demo!(runner, demo_rational_ceiling_mod_assign); register_demo!(runner, demo_rational_ceiling_mod_assign_ref); register_bench!(runner, benchmark_rational_mod_evaluation_strategy); register_bench!(runner, benchmark_rational_mod_algorithms); register_bench!(runner, benchmark_rational_mod_assign_evaluation_strategy); register_bench!(runner, benchmark_rational_rem_library_comparison); register_bench!(runner, benchmark_rational_rem_evaluation_strategy); register_bench!(runner, benchmark_rational_rem_assign_evaluation_strategy); register_bench!(runner, benchmark_rational_ceiling_mod_evaluation_strategy); register_bench!(runner, benchmark_rational_ceiling_mod_algorithms); register_bench!( runner, benchmark_rational_ceiling_mod_assign_evaluation_strategy ); } fn demo_rational_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.mod_op({}) = {}", x_old, y_old, x.mod_op(y)); } } fn demo_rational_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.mod_op(&{}) = {}", x_old, y, x.mod_op(&y)); } } fn demo_rational_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).mod_op({}) = {:?}", x, y_old, (&x).mod_op(y)); } } fn demo_rational_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).mod_op(&{}) = {:?}", x, y, (&x).mod_op(&y)); } } fn demo_rational_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.mod_assign(y); println!("x := {x_old}; x.mod_assign({y_old}); x = {x}"); } } fn demo_rational_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.mod_assign(&y); println!("x := {x_old}; x.mod_assign(&{y}); x = {x}"); } } fn demo_rational_rem(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} % {} = {:?}", x_old, y_old, x % y); } } fn demo_rational_rem_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} % &{} = {:?}", x_old, y, x % &y); } } fn demo_rational_rem_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} % {} = {:?}", x, y_old, &x % y); } } fn demo_rational_rem_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { println!("&{} % &{} = {:?}", x, y, &x % &y); } } fn demo_rational_rem_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x %= y; println!("x := {x_old}; x %= {y_old}; x = {x}"); } } fn demo_rational_rem_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x %= &y; println!("x := {x_old}; x %= &{y}; x = {x}"); } } fn demo_rational_ceiling_mod(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{}.ceiling_mod({}) = {}", x_old, y_old, x.ceiling_mod(y)); } } fn demo_rational_ceiling_mod_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); println!("{}.ceiling_mod(&{}) = {}", x_old, y, x.ceiling_mod(&y)); } } fn demo_rational_ceiling_mod_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let y_old = y.clone(); println!("(&{}).ceiling_mod({}) = {}", x, y_old, (&x).ceiling_mod(y)); } } fn demo_rational_ceiling_mod_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { println!("(&{}).ceiling_mod(&{}) = {}", x, y, (&x).ceiling_mod(&y)); } } fn demo_rational_ceiling_mod_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); x.ceiling_mod_assign(y); println!("x := {x_old}; x.ceiling_mod_assign({y_old}); x = {x}"); } } fn demo_rational_ceiling_mod_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen_var_1().get(gm, config).take(limit) { let x_old = x.clone(); x.ceiling_mod_assign(&y); println!("x := {x_old}; x.ceiling_mod_assign(&{y}); x = {x}"); } } fn benchmark_rational_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mod_op(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.mod_op(Rational)", &mut |(x, y)| { no_out!(x.mod_op(y)); }), ("Rational.mod_op(&Rational)", &mut |(x, y)| { no_out!(x.mod_op(&y)); }), ("(&Rational).mod_op(Rational)", &mut |(x, y)| { no_out!((&x).mod_op(y)); }), ("(&Rational).mod_op(&Rational)", &mut |(x, y)| { no_out!((&x).mod_op(&y)); }), ], ); } fn benchmark_rational_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mod_op(Rational)", BenchmarkType::Algorithms, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| { no_out!(x.mod_op(y)); }), ("naive", &mut |(x, y)| { no_out!(mod_op_naive(x, y)); }), ], ); } fn benchmark_rational_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mod_assign(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.mod_assign(Rational)", &mut |(mut x, y)| { no_out!(x.mod_assign(y)); }), ("Rational.mod_assign(&Rational)", &mut |(mut x, y)| { no_out!(x.mod_assign(&y)); }), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_rem_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.rem(Rational)", BenchmarkType::LibraryComparison, rational_pair_gen_var_1_nm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x % y)), ("num", &mut |((x, y), _)| no_out!(x % y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_rem_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.rem(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational % Rational", &mut |(x, y)| no_out!(x % y)), ("Rational % &Rational", &mut |(x, y)| no_out!(x % &y)), ("&Rational % Rational", &mut |(x, y)| no_out!(&x % y)), ("&Rational % &Rational", &mut |(x, y)| no_out!(&x % &y)), ], ); } #[allow(unused)] fn benchmark_rational_rem_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational % Rational", BenchmarkType::Algorithms, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| { no_out!(x % y); }), ("naive", &mut |(x, y)| { no_out!(rem_naive(x, y)); }), ], ); } fn benchmark_rational_rem_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.rem_assign(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational %= Rational", &mut |(mut x, y)| x %= y), ("Rational %= &Rational", &mut |(mut x, y)| x %= &y), ], ); } fn benchmark_rational_ceiling_mod_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_mod(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.ceiling_mod(Rational)", &mut |(x, y)| { no_out!(x.ceiling_mod(y)); }), ("Rational.ceiling_mod(&Rational)", &mut |(x, y)| { no_out!(x.ceiling_mod(&y)); }), ("(&Rational).ceiling_mod(Rational)", &mut |(x, y)| { no_out!((&x).ceiling_mod(y)); }), ("(&Rational).ceiling_mod(&Rational)", &mut |(x, y)| { no_out!((&x).ceiling_mod(&y)); }), ], ); } fn benchmark_rational_ceiling_mod_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_mod(Rational)", BenchmarkType::Algorithms, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| { no_out!(x.ceiling_mod(y)); }), ("naive", &mut |(x, y)| { no_out!(ceiling_mod_naive(x, y)); }), ], ); } fn benchmark_rational_ceiling_mod_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ceiling_mod_assign(Rational)", BenchmarkType::EvaluationStrategy, rational_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ( "Rational.ceiling_mod_assign(Rational)", &mut |(mut x, y)| { no_out!(x.ceiling_mod_assign(y)); }, ), ( "Rational.ceiling_mod_assign(&Rational)", &mut |(mut x, y)| { no_out!(x.ceiling_mod_assign(&y)); }, ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::arithmetic::mul::mul_naive; use malachite_q::test_util::arithmetic::mul::rational_product_naive; use malachite_q::test_util::bench::bucketers::{ pair_2_pair_rational_max_bit_bucketer, pair_rational_max_bit_bucketer, triple_3_pair_rational_max_bit_bucketer, triple_3_vec_rational_sum_bits_bucketer, vec_rational_sum_bits_bucketer, }; use malachite_q::test_util::generators::{ rational_pair_gen, rational_pair_gen_nrm, rational_pair_gen_rm, rational_vec_gen, rational_vec_gen_nrm, }; use num::BigRational; use std::iter::Product; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_mul); register_demo!(runner, demo_rational_mul_val_ref); register_demo!(runner, demo_rational_mul_ref_val); register_demo!(runner, demo_rational_mul_ref_ref); register_demo!(runner, demo_rational_mul_assign); register_demo!(runner, demo_rational_mul_assign_ref); register_demo!(runner, demo_rational_product); register_demo!(runner, demo_rational_ref_product); register_bench!(runner, benchmark_rational_mul_library_comparison); register_bench!(runner, benchmark_rational_mul_evaluation_strategy); register_bench!(runner, benchmark_rational_mul_algorithms); register_bench!(runner, benchmark_rational_mul_assign_library_comparison); register_bench!(runner, benchmark_rational_mul_assign_evaluation_strategy); register_bench!(runner, benchmark_rational_product_algorithms); register_bench!(runner, benchmark_rational_product_library_comparison); register_bench!(runner, benchmark_rational_product_evaluation_strategy); } fn demo_rational_mul(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} * {} = {}", x_old, y_old, x * y); } } fn demo_rational_mul_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} * &{} = {}", x_old, y, x * &y); } } fn demo_rational_mul_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} * {} = {}", x, y_old, &x * y); } } fn demo_rational_mul_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!("&{} * &{} = {}", x, y, &x * &y); } } fn demo_rational_mul_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= y.clone(); println!("x := {x_old}; x *= {y}; x = {x}"); } } fn demo_rational_mul_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x *= &y; println!("x := {x_old}; x *= &{y}; x = {x}"); } } fn demo_rational_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in rational_vec_gen().get(gm, config).take(limit) { println!( "product({:?}) = {}", xs.clone(), Rational::product(xs.into_iter()) ); } } fn demo_rational_ref_product(gm: GenMode, config: &GenConfig, limit: usize) { for xs in rational_vec_gen().get(gm, config).take(limit) { println!("product({:?}) = {}", xs, Rational::product(xs.iter())); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_mul_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational * Rational", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x * y)), ("num", &mut |((x, y), _, _)| no_out!(x * y)), ("rug", &mut |(_, (x, y), _)| no_out!(x * y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_mul_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational * Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational * Rational", &mut |(x, y)| no_out!(x * y)), ("Rational * &Rational", &mut |(x, y)| no_out!(x * &y)), ("&Rational * Rational", &mut |(x, y)| no_out!(&x * y)), ("&Rational * &Rational", &mut |(x, y)| no_out!(&x * &y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_mul_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational * Rational", BenchmarkType::Algorithms, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x * y)), ("naive", &mut |(x, y)| no_out!(mul_naive(x, y))), ], ); } fn benchmark_rational_mul_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational *= Rational", BenchmarkType::LibraryComparison, rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x *= y), ("rug", &mut |((mut x, y), _)| x *= y)], ); } fn benchmark_rational_mul_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational *= Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational *= Rational", &mut |(mut x, y)| no_out!(x *= y)), ("Rational *= &Rational", &mut |(mut x, y)| no_out!(x *= &y)), ], ); } fn benchmark_rational_product_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::product(Iterator)", BenchmarkType::LibraryComparison, rational_vec_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_vec_rational_sum_bits_bucketer(), &mut [ ("Malachite", &mut |(_, _, xs)| { no_out!(Rational::product(xs.into_iter())); }), ("num", &mut |(xs, _, _)| { no_out!(BigRational::product(xs.into_iter())); }), ("rug", &mut |(_, xs, _)| { no_out!(rug::Rational::product(xs.iter())); }), ], ); } fn benchmark_rational_product_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::product(Iterator)", BenchmarkType::Algorithms, rational_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_rational_sum_bits_bucketer(), &mut [ ("default", &mut |xs| { no_out!(Rational::product(xs.into_iter())); }), ("naive", &mut |xs| { no_out!(rational_product_naive(xs.into_iter())); }), ], ); } fn benchmark_rational_product_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::product(Iterator)", BenchmarkType::EvaluationStrategy, rational_vec_gen().get(gm, config), gm.name(), limit, file_name, &vec_rational_sum_bits_bucketer(), &mut [ ("Rational::product(Iterator)", &mut |xs| { no_out!(Rational::product(xs.into_iter())); }), ("Rational::product(Iterator)", &mut |xs| { no_out!(Rational::product(xs.iter())); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_neg); register_demo!(runner, demo_rational_neg_ref); register_demo!(runner, demo_rational_neg_assign); register_bench!(runner, benchmark_rational_neg_library_comparison); register_bench!(runner, benchmark_rational_neg_evaluation_strategy); register_bench!(runner, benchmark_rational_neg_assign); } fn demo_rational_neg(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("-({}) = {}", n.clone(), -n); } } fn demo_rational_neg_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("-(&{}) = {}", n, -&n); } } fn demo_rational_neg_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.neg_assign(); println!("n := {n_old}; n.neg_assign(); n = {n}"); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_neg_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Rational", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(-n)), ("num", &mut |(n, _, _)| no_out!(-n)), ("rug", &mut |(_, n, _)| no_out!(-n)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_neg_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "-Rational", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.neg()", &mut |n| no_out!(-n)), ("(&Rational).neg()", &mut |n| no_out!(-&n)), ], ); } fn benchmark_rational_neg_assign(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.neg_assign()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.neg_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{NextPowerOf2, NextPowerOf2Assign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen_var_2; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_next_power_of_2); register_demo!(runner, demo_rational_next_power_of_2_ref); register_demo!(runner, demo_rational_next_power_of_2_assign); register_bench!( runner, benchmark_rational_next_power_of_2_evaluation_strategy ); register_bench!(runner, benchmark_rational_next_power_of_2_assign); } fn demo_rational_next_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen_var_2().get(gm, config).take(limit) { let x_old = x.clone(); println!("next_power_of_2({}) = {}", x_old, x.next_power_of_2()); } } fn demo_rational_next_power_of_2_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen_var_2().get(gm, config).take(limit) { println!("next_power_of_2({}) = {}", x, (&x).next_power_of_2()); } } fn demo_rational_next_power_of_2_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut x in rational_gen_var_2().get(gm, config).take(limit) { let old_x = x.clone(); x.next_power_of_2_assign(); println!("x := {old_x}; x.next_power_of_2_assign(); x = {x}"); } } fn benchmark_rational_next_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.next_power_of_2()", BenchmarkType::EvaluationStrategy, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.next_power_of_2()", &mut |x| { no_out!(x.next_power_of_2()); }), ("(&Rational).next_power_of_2()", &mut |x| { no_out!((&x).next_power_of_2()); }), ], ); } fn benchmark_rational_next_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.next_power_of_2_assign()", BenchmarkType::Single, rational_gen_var_2().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut x| x.next_power_of_2_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Pow, PowAssign}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, triple_3_pair_1_rational_bits_times_abs_pair_2_bucketer, triple_3_pair_1_rational_bits_times_pair_2_bucketer, }; use malachite_q::test_util::generators::{ rational_signed_pair_gen_var_2, rational_signed_pair_gen_var_2_nrm, rational_unsigned_pair_gen_var_1, rational_unsigned_pair_gen_var_1_nrm, }; use rug::ops::Pow as RugPow; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_pow_u64); register_demo!(runner, demo_rational_pow_u64_ref); register_demo!(runner, demo_rational_pow_assign_u64); register_demo!(runner, demo_rational_pow_i64); register_demo!(runner, demo_rational_pow_i64_ref); register_demo!(runner, demo_rational_pow_assign_i64); register_bench!(runner, benchmark_rational_pow_u64_evaluation_strategy); register_bench!(runner, benchmark_rational_pow_u64_library_comparison); register_bench!(runner, benchmark_rational_pow_u64_assign); register_bench!(runner, benchmark_rational_pow_i64_evaluation_strategy); register_bench!(runner, benchmark_rational_pow_i64_library_comparison); register_bench!(runner, benchmark_rational_pow_i64_assign); } fn demo_rational_pow_u64(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("({}).pow({}) = {}", n.clone(), exp, n.pow(exp)); } } fn demo_rational_pow_u64_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("(&{}).pow({}) = {}", n, exp, (&n).pow(exp)); } } fn demo_rational_pow_assign_u64(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, exp) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.pow_assign(exp); println!("n := {n_old}; n.pow_assign({exp}); n = {n}"); } } fn demo_rational_pow_i64(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in rational_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("({}).pow({}) = {}", n.clone(), exp, n.pow(exp)); } } fn demo_rational_pow_i64_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, exp) in rational_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!("(&{}).pow({}) = {}", n, exp, (&n).pow(exp)); } } fn demo_rational_pow_assign_i64(gm: GenMode, config: &GenConfig, limit: usize) { for (mut n, exp) in rational_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { let n_old = n.clone(); n.pow_assign(exp); println!("n := {n_old}; n.pow_assign({exp}); n = {n}"); } } fn benchmark_rational_pow_u64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.pow_assign(u64)", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_rational_bits_times_pair_2_bucketer("n", "pow"), &mut [ ("Malachite", &mut |(_, _, (x, exp))| no_out!(x.pow(exp))), ("num", &mut |((x, exp), _, _)| { no_out!(x.pow(i32::exact_from(exp))); }), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.pow(u32::exact_from(exp))); }), ], ); } fn benchmark_rational_pow_u64_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.pow(u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.pow(u64)", &mut |(n, exp)| no_out!(n.pow(exp))), ("(&Rational).pow(u64)", &mut |(n, exp)| { no_out!((&n).pow(exp)); }), ], ); } fn benchmark_rational_pow_u64_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.pow_assign(u64)", BenchmarkType::Single, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.pow_assign(exp))], ); } fn benchmark_rational_pow_i64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.pow_assign(i64)", BenchmarkType::LibraryComparison, rational_signed_pair_gen_var_2_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_1_rational_bits_times_abs_pair_2_bucketer("n", "pow"), &mut [ ("Malachite", &mut |(_, _, (x, exp))| no_out!(x.pow(exp))), ("num", &mut |((x, exp), _, _)| { no_out!(x.pow(i32::exact_from(exp))); }), ("rug", &mut |(_, (x, exp), _)| { no_out!(x.pow(i32::exact_from(exp))); }), ], ); } fn benchmark_rational_pow_i64_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.pow(i64)", BenchmarkType::EvaluationStrategy, rational_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.pow(u64)", &mut |(n, exp)| no_out!(n.pow(exp))), ("(&Rational).pow(u64)", &mut |(n, exp)| { no_out!((&n).pow(exp)); }), ], ); } fn benchmark_rational_pow_i64_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.pow_assign(i64)", BenchmarkType::Single, rational_signed_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, exp)| n.pow_assign(exp))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::PowerOf2; use malachite_base::test_util::bench::bucketers::{signed_abs_bucketer, unsigned_direct_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen_var_5, unsigned_gen_var_5}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_power_of_2_u64); register_demo!(runner, demo_rational_power_of_2_i64); register_bench!(runner, benchmark_rational_power_of_2_u64); register_bench!(runner, benchmark_rational_power_of_2_i64); } fn demo_rational_power_of_2_u64(gm: GenMode, config: &GenConfig, limit: usize) { for x in unsigned_gen_var_5::().get(gm, config).take(limit) { println!("Rational::power_of_2({}) = {}", x, Rational::power_of_2(x)); } } fn demo_rational_power_of_2_i64(gm: GenMode, config: &GenConfig, limit: usize) { for x in signed_gen_var_5::().get(gm, config).take(limit) { println!("Rational::power_of_2({}) = {}", x, Rational::power_of_2(x)); } } fn benchmark_rational_power_of_2_u64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.power_of_2(u64)", BenchmarkType::Single, unsigned_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &unsigned_direct_bucketer(), &mut [("Malachite", &mut |x| no_out!(Rational::power_of_2(x)))], ); } fn benchmark_rational_power_of_2_i64( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.power_of_2(i64)", BenchmarkType::Single, signed_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &signed_abs_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Rational::power_of_2(x)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Reciprocal, ReciprocalAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen_var_1, rational_gen_var_1_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_reciprocal); register_demo!(runner, demo_rational_reciprocal_ref); register_demo!(runner, demo_rational_reciprocal_assign); register_bench!(runner, benchmark_rational_reciprocal_library_comparison); register_bench!(runner, benchmark_rational_reciprocal_evaluation_strategy); register_bench!(runner, benchmark_rational_reciprocal_assign); } fn demo_rational_reciprocal(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_1().get(gm, config).take(limit) { println!("reciprocal({}) = {}", n.clone(), n.reciprocal()); } } fn demo_rational_reciprocal_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_1().get(gm, config).take(limit) { println!("reciprocal(&{}) = {}", n, (&n).reciprocal()); } } fn demo_rational_reciprocal_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen_var_1().get(gm, config).take(limit) { let n_old = n.clone(); n.reciprocal_assign(); println!("n := {n_old}; n.reciprocal_assign(); n = {n}"); } } #[allow(unused_must_use)] fn benchmark_rational_reciprocal_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.reciprocal()", BenchmarkType::LibraryComparison, rational_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.reciprocal())), ("num", &mut |(n, _, _)| no_out!(n.recip())), ("rug", &mut |(_, n, _)| no_out!(n.recip())), ], ); } fn benchmark_rational_reciprocal_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.reciprocal()", BenchmarkType::EvaluationStrategy, rational_gen_var_1().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.reciprocal()", &mut |n| no_out!(n.reciprocal())), ("(&Rational).reciprocal()", &mut |n| { no_out!((&n).reciprocal()); }), ], ); } fn benchmark_rational_reciprocal_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.reciprocal_assign()", BenchmarkType::Single, rational_gen_var_1().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.reciprocal_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedRoot; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_signed_pair_gen_var_4, rational_unsigned_pair_gen_var_4, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_checked_root_u64); register_demo!(runner, demo_rational_checked_root_u64_ref); register_demo!(runner, demo_rational_checked_root_i64); register_demo!(runner, demo_rational_checked_root_i64_ref); register_bench!( runner, benchmark_rational_checked_root_u64_evaluation_strategy ); register_bench!( runner, benchmark_rational_checked_root_i64_evaluation_strategy ); } fn demo_rational_checked_root_u64(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in rational_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "({}).checked_root({}) = {:?}", x, exp, x.clone().checked_root(exp) ); } } fn demo_rational_checked_root_u64_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in rational_unsigned_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "(&{}).checked_root({}) = {:?}", x, exp, (&x).checked_root(exp) ); } } fn demo_rational_checked_root_i64(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in rational_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "({}).checked_root({}) = {:?}", x, exp, x.clone().checked_root(exp) ); } } fn demo_rational_checked_root_i64_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, exp) in rational_signed_pair_gen_var_4::() .get(gm, config) .take(limit) { println!( "(&{}).checked_root({}) = {:?}", x, exp, (&x).checked_root(exp) ); } } fn benchmark_rational_checked_root_u64_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.checked_root(u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.checked_root(u64)", &mut |(x, exp)| { no_out!(x.checked_root(exp)); }), ("(&Rational).checked_root(u64)", &mut |(x, exp)| { no_out!((&x).checked_root(exp)); }), ], ); } fn benchmark_rational_checked_root_i64_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.checked_root(i64)", BenchmarkType::EvaluationStrategy, rational_signed_pair_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.checked_root(i64)", &mut |(x, exp)| { no_out!(x.checked_root(exp)); }), ("(&Rational).checked_root(i64)", &mut |(x, exp)| { no_out!((&x).checked_root(exp)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::triple_1_rational_bit_bucketer; use malachite_q::test_util::generators::rational_rational_rounding_mode_triple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_round_to_multiple_assign); register_demo!(runner, demo_rational_round_to_multiple_assign_ref); register_demo!(runner, demo_rational_round_to_multiple); register_demo!(runner, demo_rational_round_to_multiple_val_ref); register_demo!(runner, demo_rational_round_to_multiple_ref_val); register_demo!(runner, demo_rational_round_to_multiple_ref_ref); register_bench!( runner, benchmark_rational_round_to_multiple_assign_evaluation_strategy ); register_bench!( runner, benchmark_rational_round_to_multiple_evaluation_strategy ); } fn demo_rational_round_to_multiple_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); let o = x.round_to_multiple_assign(y, rm); println!("x := {x_old}; x.round_to_multiple_assign({y_old}, {rm}) = {o:?}; x = {x}"); } } fn demo_rational_round_to_multiple_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let o = x.round_to_multiple_assign(&y, rm); println!("x := {x_old}; x.round_to_multiple_assign(&{y}, {rm}) = {o:?}; x = {x}"); } } fn demo_rational_round_to_multiple(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!( "({}).round_to_multiple({}, {}) = {:?}", x_old, y_old, rm, x.round_to_multiple(y, rm) ); } } fn demo_rational_round_to_multiple_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let x_old = x.clone(); println!( "({}).round_to_multiple(&{}, {}) = {:?}", x_old, y, rm, x.round_to_multiple(&y, rm) ); } } fn demo_rational_round_to_multiple_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let y_old = y.clone(); println!( "(&{}).round_to_multiple({}, {}) = {:?}", x, y_old, rm, (&x).round_to_multiple(y, rm) ); } } fn demo_rational_round_to_multiple_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y, rm) in rational_rational_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple(&{}, {}) = {:?}", x, y, rm, (&x).round_to_multiple(&y, rm) ); } } fn benchmark_rational_round_to_multiple_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.round_to_multiple_assign(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_rational_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_rational_bit_bucketer("n"), &mut [ ( "Rational.round_to_multiple_assign(Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(y, rm)), ), ( "Rational.round_to_multiple_assign(&Rational, RoundingMode)", &mut |(mut x, y, rm)| no_out!(x.round_to_multiple_assign(&y, rm)), ), ], ); } fn benchmark_rational_round_to_multiple_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.round_to_multiple(Rational, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_rational_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_rational_bit_bucketer("n"), &mut [ ( "Rational.round_to_multiple(Rational, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(y, rm)), ), ( "Rational.round_to_multiple(&Rational, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple(&y, rm)), ), ( "(&Rational).round_to_multiple(Rational, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(y, rm)), ), ( "(&Rational).round_to_multiple(&Rational, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple(&y, rm)), ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::triple_1_2_rational_bit_i64_max_bucketer; use malachite_q::test_util::generators::rational_signed_rounding_mode_triple_gen_var_1; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_round_to_multiple_of_power_of_2_assign); register_demo!(runner, demo_rational_round_to_multiple_of_power_of_2); register_demo!(runner, demo_rational_round_to_multiple_of_power_of_2_ref); register_bench!( runner, benchmark_rational_round_to_multiple_of_power_of_2_assign ); register_bench!( runner, benchmark_rational_round_to_multiple_of_power_of_2_algorithms ); register_bench!( runner, benchmark_rational_round_to_multiple_of_power_of_2_evaluation_strategy ); } fn demo_rational_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, ) { for (mut n, pow, rm) in rational_signed_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); let o = n.round_to_multiple_of_power_of_2_assign(pow, rm); println!( "x := {n_old}; x.round_to_multiple_of_power_of_2_assign({pow}, {rm}) = {o:?}; x = {n}" ); } } fn demo_rational_round_to_multiple_of_power_of_2(gm: GenMode, config: &GenConfig, limit: usize) { for (n, pow, rm) in rational_signed_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "({}).round_to_multiple_of_power_of_2({}, {}) = {:?}", n_old, pow, rm, n.round_to_multiple_of_power_of_2(pow, rm) ); } } fn demo_rational_round_to_multiple_of_power_of_2_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, pow, rm) in rational_signed_rounding_mode_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "(&{}).round_to_multiple_of_power_of_2({}, {}) = {:?}", n, pow, rm, (&n).round_to_multiple_of_power_of_2(pow, rm) ); } } fn benchmark_rational_round_to_multiple_of_power_of_2_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.round_to_multiple_of_power_of_2_assign(u64, RoundingMode)", BenchmarkType::Single, rational_signed_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_i64_max_bucketer("n", "pow"), &mut [("Malachite", &mut |(mut x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2_assign(y, rm)); })], ); } #[allow(clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_round_to_multiple_of_power_of_2_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::Algorithms, rational_signed_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_i64_max_bucketer("n", "pow"), &mut [ ("default", &mut |(x, y, rm)| { no_out!(x.round_to_multiple_of_power_of_2(y, rm)); }), ("using round_to_multiple", &mut |(x, y, rm)| { no_out!(x.round_to_multiple(Rational::power_of_2(y), rm)); }), ], ); } fn benchmark_rational_round_to_multiple_of_power_of_2_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.round_to_multiple_of_power_of_2(u64, RoundingMode)", BenchmarkType::EvaluationStrategy, rational_signed_rounding_mode_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_rational_bit_i64_max_bucketer("n", "pow"), &mut [ ( "Rational.round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!(x.round_to_multiple_of_power_of_2(y, rm)), ), ( "(&Rational).round_to_multiple_of_power_of_2(u64, RoundingMode)", &mut |(x, y, rm)| no_out!((&x).round_to_multiple_of_power_of_2(y, rm)), ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, pair_2_pair_1_rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_signed_pair_gen_var_1, rational_signed_pair_gen_var_1_rm, rational_unsigned_pair_gen_var_1, rational_unsigned_pair_gen_var_1_rm, }; use std::ops::{Shl, ShlAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_shl_assign_unsigned); register_signed_demos!(runner, demo_rational_shl_assign_signed); register_unsigned_demos!(runner, demo_rational_shl_unsigned); register_signed_demos!(runner, demo_rational_shl_signed); register_unsigned_demos!(runner, demo_rational_shl_unsigned_ref); register_signed_demos!(runner, demo_rational_shl_signed_ref); register_unsigned_benches!(runner, benchmark_rational_shl_assign_unsigned); register_signed_benches!(runner, benchmark_rational_shl_assign_signed); register_unsigned_benches!(runner, benchmark_rational_shl_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_rational_shl_signed_evaluation_strategy); register_bench!(runner, benchmark_rational_shl_assign_u32_library_comparison); register_bench!(runner, benchmark_rational_shl_u32_library_comparison); register_bench!(runner, benchmark_rational_shl_assign_i32_library_comparison); register_bench!(runner, benchmark_rational_shl_i32_library_comparison); } fn demo_rational_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: ShlAssign, { for (mut n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= u; println!("x := {n_old}; x <<= {u}; x = {n}"); } } fn demo_rational_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: ShlAssign, { for (mut n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n <<= i; println!("x := {n_old}; x <<= {i}; x = {n}"); } } fn demo_rational_shl_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Rational: Shl, { for (n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, u, n << u); } } fn demo_rational_shl_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: Shl, { for (n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} << {} = {}", n_old, i, n << i); } } fn demo_rational_shl_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Rational: Shl, { for (n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, u, &n << u); } } fn demo_rational_shl_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Rational: Shl, { for (n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} << {} = {}", n, i, &n << i); } } fn benchmark_rational_shl_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: ShlAssign, { run_benchmark( &format!("Rational <<= {}", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n <<= u)], ); } fn benchmark_rational_shl_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: ShlAssign, { run_benchmark( &format!("Rational <<= {}", T::NAME), BenchmarkType::Single, rational_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n <<= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_shl_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, for<'a> &'a Rational: Shl, { run_benchmark( &format!("Rational << {}", T::NAME), BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ (&format!("Rational << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Rational << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_shl_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shl, for<'a> &'a Rational: Shl, { run_benchmark( &format!("Rational << {}", T::NAME), BenchmarkType::EvaluationStrategy, rational_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ (&format!("Rational << {}", T::NAME), &mut |(x, y)| { no_out!(x << y); }), (&format!("&Rational << {}", T::NAME), &mut |(x, y)| { no_out!(&x << y); }), ], ); } fn benchmark_rational_shl_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational <<= u32", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_shl_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational << u32", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } fn benchmark_rational_shl_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational <<= i32", BenchmarkType::LibraryComparison, rational_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x <<= y), ("rug", &mut |((mut x, y), _)| x <<= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_shl_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational << i32", BenchmarkType::LibraryComparison, rational_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x << y)), ("rug", &mut |((x, y), _)| no_out!(x << y)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, pair_2_pair_1_rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_signed_pair_gen_var_1, rational_signed_pair_gen_var_1_rm, rational_unsigned_pair_gen_var_1, rational_unsigned_pair_gen_var_1_rm, }; use std::ops::{Shr, ShrAssign}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_shr_assign_unsigned); register_signed_demos!(runner, demo_rational_shr_assign_signed); register_unsigned_demos!(runner, demo_rational_shr_unsigned); register_signed_demos!(runner, demo_rational_shr_signed); register_unsigned_demos!(runner, demo_rational_shr_unsigned_ref); register_signed_demos!(runner, demo_rational_shr_signed_ref); register_unsigned_benches!(runner, benchmark_rational_shr_assign_unsigned); register_signed_benches!(runner, benchmark_rational_shr_assign_signed); register_unsigned_benches!(runner, benchmark_rational_shr_unsigned_evaluation_strategy); register_signed_benches!(runner, benchmark_rational_shr_signed_evaluation_strategy); register_bench!(runner, benchmark_rational_shr_assign_u32_library_comparison); register_bench!(runner, benchmark_rational_shr_u32_library_comparison); register_bench!(runner, benchmark_rational_shr_assign_i32_library_comparison); register_bench!(runner, benchmark_rational_shr_i32_library_comparison); } fn demo_rational_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: ShrAssign, { for (mut n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= u; println!("x := {n_old}; x >>= {u}; x = {n}"); } } fn demo_rational_shr_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: ShrAssign, { for (mut n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); n >>= i; println!("x := {n_old}; x >>= {i}; x = {n}"); } } fn demo_rational_shr_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Rational: Shr, { for (n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, u, n >> u); } } fn demo_rational_shr_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: Shr, { for (n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { let n_old = n.clone(); println!("{} >> {} = {}", n_old, i, n >> i); } } fn demo_rational_shr_unsigned_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Rational: Shr, { for (n, u) in rational_unsigned_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, u, &n >> u); } } fn demo_rational_shr_signed_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Rational: Shr, { for (n, i) in rational_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!("&{} >> {} = {}", n, i, &n >> i); } } fn benchmark_rational_shr_assign_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: ShrAssign, { run_benchmark( &format!("Rational >>= {}", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, u)| n >>= u)], ); } fn benchmark_rational_shr_assign_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: ShrAssign, { run_benchmark( &format!("Rational >>= {}", T::NAME), BenchmarkType::Single, rational_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(mut n, i)| n >>= i)], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_shr_unsigned_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, for<'a> &'a Rational: Shr, { run_benchmark( &format!("Rational >> {}", T::NAME), BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ (&format!("Rational >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Rational >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_shr_signed_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: Shr, for<'a> &'a Rational: Shr, { run_benchmark( &format!("Rational >> {}", T::NAME), BenchmarkType::EvaluationStrategy, rational_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ (&format!("Rational >> {}", T::NAME), &mut |(x, y)| { no_out!(x >> y); }), (&format!("&Rational >> {}", T::NAME), &mut |(x, y)| { no_out!(&x >> y); }), ], ); } fn benchmark_rational_shr_assign_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational >>= u32", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_shr_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational >> u32", BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } fn benchmark_rational_shr_assign_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational >>= i32", BenchmarkType::LibraryComparison, rational_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (mut x, y))| x >>= y), ("rug", &mut |((mut x, y), _)| x >>= y), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_shr_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational >> i32", BenchmarkType::LibraryComparison, rational_signed_pair_gen_var_1_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x >> y)), ("rug", &mut |((x, y), _)| no_out!(x >> y)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::arithmetic::sign::num_sign; use malachite_q::test_util::bench::bucketers::triple_3_rational_bit_bucketer; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_sign); register_bench!(runner, benchmark_integer_sign_library_comparison); } fn demo_integer_sign(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { match x.sign() { Less => println!("{x} is negative"), Equal => println!("{x} is zero"), Greater => println!("{x} is positive"), } } } fn benchmark_integer_sign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.sign()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.sign())), ("num", &mut |(x, _, _)| no_out!(num_sign(&x))), ("rug", &mut |(_, x, _)| no_out!(x.cmp0())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/simplest_rational_in_interval.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::arithmetic::traits::SimplestRationalInInterval; use malachite_q::test_util::arithmetic::simplest_rational_in_interval::*; use malachite_q::test_util::bench::bucketers::pair_rational_max_bit_bucketer; use malachite_q::test_util::generators::{ rational_pair_gen, rational_pair_gen_var_3, rational_pair_gen_var_4, rational_pair_gen_var_5, rational_pair_gen_var_6, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_cmp_complexity); register_demo!(runner, demo_simplest_rational_in_open_interval); register_demo!(runner, demo_simplest_rational_in_closed_interval); register_bench!(runner, benchmark_rational_cmp_complexity); register_bench!( runner, benchmark_simplest_rational_in_open_interval_algorithms ); register_bench!( runner, benchmark_simplest_rational_in_open_interval_algorithms_2 ); register_bench!(runner, benchmark_simplest_rational_in_closed_interval); register_bench!( runner, benchmark_simplest_rational_in_closed_interval_algorithms ); } fn demo_rational_cmp_complexity(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { match x.cmp_complexity(&y) { Less => println!("{x} c< {y}"), Equal => println!("{x} c= {y}"), Greater => println!("{x} c> {y}"), } } } fn demo_simplest_rational_in_open_interval(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_3().get(gm, config).take(limit) { println!( "simplest_rational_in_open_interval({}, {}) = {}", x, y, Rational::simplest_rational_in_open_interval(&x, &y) ); } } fn demo_simplest_rational_in_closed_interval(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen_var_4().get(gm, config).take(limit) { println!( "simplest_rational_in_closed_interval({}, {}) = {}", x, y, Rational::simplest_rational_in_closed_interval(&x, &y) ); } } fn benchmark_rational_cmp_complexity( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.cmp_complexity(&Rational)", BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.cmp_complexity(&y)))], ); } fn benchmark_simplest_rational_in_open_interval_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "simplest_rational_in_open_interval(&Rational, &Rational)", BenchmarkType::Algorithms, rational_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(Rational::simplest_rational_in_open_interval(&x, &y)); }), ("explicit", &mut |(x, y)| { no_out!(simplest_rational_in_open_interval_explicit(&x, &y)); }), ("naive", &mut |(x, y)| { no_out!(simplest_rational_in_open_interval_naive(&x, &y)); }), ], ); } fn benchmark_simplest_rational_in_open_interval_algorithms_2( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "simplest_rational_in_open_interval(&Rational, &Rational)", BenchmarkType::Algorithms, rational_pair_gen_var_3().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(Rational::simplest_rational_in_open_interval(&x, &y)); }), ("explicit", &mut |(x, y)| { no_out!(simplest_rational_in_open_interval_explicit(&x, &y)); }), ], ); } fn benchmark_simplest_rational_in_closed_interval( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "simplest_rational_in_closed_interval(&Rational, &Rational)", BenchmarkType::Single, rational_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| { no_out!(Rational::simplest_rational_in_closed_interval(&x, &y)); })], ); } fn benchmark_simplest_rational_in_closed_interval_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "simplest_rational_in_closed_interval(&Rational, &Rational)", BenchmarkType::Algorithms, rational_pair_gen_var_6().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| { no_out!(Rational::simplest_rational_in_closed_interval(&x, &y)); }), ("naive", &mut |(x, y)| { no_out!(simplest_rational_in_closed_interval_naive(&x, &y)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::CheckedSqrt; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen_var_3; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_checked_sqrt); register_demo!(runner, demo_rational_checked_sqrt_ref); register_bench!(runner, benchmark_rational_checked_sqrt_evaluation_strategy); } fn demo_rational_checked_sqrt(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen_var_3().get(gm, config).take(limit) { println!("({}).checked_sqrt() = {:?}", x, x.clone().checked_sqrt()); } } fn demo_rational_checked_sqrt_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen_var_3().get(gm, config).take(limit) { println!("(&{}).checked_sqrt() = {:?}", x, (&x).checked_sqrt()); } } fn benchmark_rational_checked_sqrt_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.checked_sqrt()", BenchmarkType::EvaluationStrategy, rational_gen_var_3().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.checked_sqrt()", &mut |x| { no_out!(x.checked_sqrt()); }), ("(&Rational).checked_sqrt()", &mut |x| { no_out!((&x).checked_sqrt()); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Square, SquareAssign}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_square); register_demo!(runner, demo_rational_square_ref); register_demo!(runner, demo_rational_square_assign); register_bench!(runner, benchmark_rational_square_evaluation_strategy); register_bench!(runner, benchmark_rational_square_algorithms); register_bench!(runner, benchmark_rational_square_assign); } fn demo_rational_square(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("{} ^ 2 = {}", n.clone(), n.square()); } } fn demo_rational_square_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("&{} ^ 2 = {}", n, (&n).square()); } } fn demo_rational_square_assign(gm: GenMode, config: &GenConfig, limit: usize) { for mut n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); n.square_assign(); println!("n := {n_old}; n.square_assign(); n = {n}"); } } fn benchmark_rational_square_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.square()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.square()", &mut |n| no_out!(n.square())), ("(&Rational).square()", &mut |n| no_out!((&n).square())), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_square_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.square()", BenchmarkType::Algorithms, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("standard", &mut |ref n| no_out!(n.square())), ("using *", &mut |ref n| no_out!(n * n)), ], ); } fn benchmark_rational_square_assign( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.square_assign()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |mut n| n.square_assign())], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::arithmetic::sub::sub_naive; use malachite_q::test_util::bench::bucketers::{ pair_2_pair_rational_max_bit_bucketer, pair_rational_max_bit_bucketer, triple_3_pair_rational_max_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_pair_gen, rational_pair_gen_nrm, rational_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_sub); register_demo!(runner, demo_rational_sub_val_ref); register_demo!(runner, demo_rational_sub_ref_val); register_demo!(runner, demo_rational_sub_ref_ref); register_demo!(runner, demo_rational_sub_assign); register_demo!(runner, demo_rational_sub_assign_ref); register_bench!(runner, benchmark_rational_sub_library_comparison); register_bench!(runner, benchmark_rational_sub_evaluation_strategy); register_bench!(runner, benchmark_rational_sub_algorithms); register_bench!(runner, benchmark_rational_sub_assign_library_comparison); register_bench!(runner, benchmark_rational_sub_assign_evaluation_strategy); } fn demo_rational_sub(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); let y_old = y.clone(); println!("{} - {} = {}", x_old, y_old, x - y); } } fn demo_rational_sub_val_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); println!("{} - &{} = {}", x_old, y, x - &y); } } fn demo_rational_sub_ref_val(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { let y_old = y.clone(); println!("&{} - {} = {}", x, y_old, &x - y); } } fn demo_rational_sub_ref_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { println!("&{} - &{} = {}", x, y, &x - &y); } } fn demo_rational_sub_assign(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x -= y.clone(); println!("x := {x_old}; x -= {y}; x = {x}"); } } fn demo_rational_sub_assign_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x -= &y; println!("x := {x_old}; x -= &{y}; x = {x}"); } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_sub_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational - Rational", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x - y)), ("num", &mut |((x, y), _, _)| no_out!(x - y)), ("rug", &mut |(_, (x, y), _)| no_out!(x - y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_sub_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational - Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational - Rational", &mut |(x, y)| no_out!(x - y)), ("Rational - &Rational", &mut |(x, y)| no_out!(x - &y)), ("&Rational - Rational", &mut |(x, y)| no_out!(&x - y)), ("&Rational - &Rational", &mut |(x, y)| no_out!(&x - &y)), ], ); } #[allow(clippy::no_effect, unused_must_use)] fn benchmark_rational_sub_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational - Rational", BenchmarkType::Algorithms, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x - y)), ("naive", &mut |(x, y)| no_out!(sub_naive(x, y))), ], ); } fn benchmark_rational_sub_assign_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational -= Rational", BenchmarkType::LibraryComparison, rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(_, (mut x, y))| x -= y), ("rug", &mut |((mut x, y), _)| x -= y)], ); } fn benchmark_rational_sub_assign_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational -= Rational", BenchmarkType::EvaluationStrategy, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Rational -= Rational", &mut |(mut x, y)| no_out!(x -= y)), ("Rational -= &Rational", &mut |(mut x, y)| no_out!(x -= &y)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/basic/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { significant_bits::register(runner); } mod significant_bits; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/basic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_significant_bits); register_bench!(runner, benchmark_significant_bits); } fn demo_significant_bits(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("significant_bits({}) = {}", x, x.significant_bits()); } } fn benchmark_significant_bits(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.significant_bits()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.significant_bits()))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::triple_3_pair_rational_max_bit_bucketer; use malachite_q::test_util::generators::{rational_pair_gen, rational_pair_gen_nrm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_cmp); register_bench!(runner, benchmark_rational_cmp_library_comparison); } fn demo_rational_cmp(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { match x.cmp(&y) { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } #[allow(unused_must_use)] fn benchmark_rational_cmp_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.cmp(&Rational)", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x.cmp(&y))), ("num", &mut |((x, y), _, _)| no_out!(x.cmp(&y))), ("rug", &mut |(_, (x, y), _)| no_out!(x.cmp(&y))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ pair_2_pair_rational_max_bit_bucketer, pair_rational_max_bit_bucketer, }; use malachite_q::test_util::generators::{rational_pair_gen, rational_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_cmp_abs); register_demo!(runner, demo_rational_lt_abs); register_demo!(runner, demo_rational_gt_abs); register_demo!(runner, demo_rational_le_abs); register_demo!(runner, demo_rational_ge_abs); register_bench!(runner, benchmark_rational_cmp_abs_library_comparison); register_bench!(runner, benchmark_rational_cmp_abs_algorithms); register_bench!(runner, benchmark_rational_lt_abs); register_bench!(runner, benchmark_rational_gt_abs); register_bench!(runner, benchmark_rational_le_abs); register_bench!(runner, benchmark_rational_ge_abs); } fn demo_rational_cmp_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { match x.cmp_abs(&y) { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } fn demo_rational_lt_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x.lt_abs(&y) { println!("|{x}| < |{y}|"); } else { println!("|{x}| ≮ |{y}|"); } } } fn demo_rational_gt_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x.gt_abs(&y) { println!("|{x}| > |{y}|"); } else { println!("|{x}| ≯ |{y}|"); } } } fn demo_rational_le_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x.le_abs(&y) { println!("|{x}| ≤ |{y}|"); } else { println!("|{x}| ≰ |{y}|"); } } } fn demo_rational_ge_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x.ge_abs(&y) { println!("|{x}| ≥ |{y}|"); } else { println!("|{x}| ≱ |{y}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_cmp_abs_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.cmp_abs(&Rational)", BenchmarkType::LibraryComparison, rational_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.cmp_abs(&y))), ("rug", &mut |((x, y), _)| no_out!(x.cmp_abs(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_cmp_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.cmp_abs(&Rational)", BenchmarkType::Algorithms, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().cmp(&y.abs()))), ], ); } fn benchmark_rational_lt_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.lt_abs(&Rational)", BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_rational_gt_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.gt_abs(&Rational)", BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_rational_le_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.le_abs(&Rational)", BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_rational_ge_abs(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.ge_abs(&Rational)", BenchmarkType::Single, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::triple_3_pair_rational_max_bit_bucketer; use malachite_q::test_util::generators::{rational_pair_gen, rational_pair_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_eq); register_bench!(runner, benchmark_rational_eq_library_comparison); } fn demo_rational_eq(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_eq_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational == Rational", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (x, y))| no_out!(x == y)), ("num", &mut |((x, y), _, _)| no_out!(x == y)), ("rug", &mut |(_, (x, y), _)| no_out!(x == y)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_rational_max_bit_bucketer; use malachite_q::test_util::generators::rational_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_eq_abs); register_bench!(runner, benchmark_rational_eq_abs_algorithms); } fn demo_rational_eq_abs(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.eq_abs(&Natural)", BenchmarkType::Algorithms, rational_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_rational_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_integer_max_bit_bucketer; use malachite_q::test_util::generators::rational_integer_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_eq_abs_integer); register_demo!(runner, demo_integer_eq_abs_rational); register_bench!(runner, benchmark_rational_eq_abs_integer_algorithms); register_bench!(runner, benchmark_integer_eq_abs_rational_algorithms); } fn demo_rational_eq_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_integer_eq_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y.eq_abs(&x) { println!("|{y}| = |{x}|"); } else { println!("|{y}| ≠ |{x}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.eq_abs(&Integer)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(unused_must_use)] fn benchmark_integer_eq_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.eq_abs(&Rational)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.abs() == x.abs())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_natural_max_bit_bucketer; use malachite_q::test_util::generators::rational_natural_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_eq_abs_natural); register_demo!(runner, demo_natural_eq_abs_rational); register_bench!(runner, benchmark_rational_eq_abs_natural_algorithms); register_bench!(runner, benchmark_natural_eq_abs_rational_algorithms); } fn demo_rational_eq_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x.eq_abs(&y) { println!("|{x}| = |{y}|"); } else { println!("|{x}| ≠ |{y}|"); } } } fn demo_natural_eq_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y.eq_abs(&x) { println!("|{y}| = |{x}|"); } else { println!("|{y}| ≠ |{x}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.eq_abs(&Natural)", BenchmarkType::Algorithms, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(unused_must_use)] fn benchmark_natural_eq_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.eq_abs(&Rational)", BenchmarkType::Algorithms, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y == x.abs())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::rational_primitive_float_pair_gen; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_eq_abs_primitive_float); register_primitive_float_demos!(runner, demo_primitive_float_eq_abs_rational); register_primitive_float_benches!(runner, benchmark_rational_eq_abs_primitive_float_algorithms); register_primitive_float_benches!(runner, benchmark_primitive_float_eq_abs_rational_algorithms); } fn demo_rational_eq_abs_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: EqAbs, { for (n, x) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n.eq_abs(&x) { println!("|{}| = |{}|", n, NiceFloat(x)); } else { println!("|{}| ≠ |{}|", n, NiceFloat(x)); } } } fn demo_primitive_float_eq_abs_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, x) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if x.eq_abs(&n) { println!("|{}| = |{}|", NiceFloat(x), n); } else { println!("|{}| ≠ |{}|", NiceFloat(x), n); } } } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_primitive_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: EqAbs + PartialEq, { run_benchmark( &format!("Rational.eq_abs(&{})", T::NAME), BenchmarkType::Algorithms, rational_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y.abs())), ], ); } #[allow(unused_must_use)] fn benchmark_primitive_float_eq_abs_rational_algorithms< T: EqAbs + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.abs() == x.abs())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{rational_signed_pair_gen, rational_unsigned_pair_gen}; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_partial_eq_abs_unsigned); register_signed_demos!(runner, demo_rational_partial_eq_abs_signed); register_unsigned_demos!(runner, demo_unsigned_partial_eq_abs_rational); register_signed_demos!(runner, demo_signed_partial_eq_abs_rational); register_unsigned_benches!(runner, benchmark_rational_eq_abs_unsigned_algorithms); register_signed_benches!(runner, benchmark_rational_eq_abs_signed_algorithms); register_unsigned_benches!(runner, benchmark_unsigned_eq_abs_rational_algorithms); register_signed_benches!(runner, benchmark_signed_eq_abs_rational_algorithms); } fn demo_rational_partial_eq_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: EqAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n.eq_abs(&u) { println!("|{n}| = |{u}|"); } else { println!("|{n}| ≠ |{u}|"); } } } fn demo_rational_partial_eq_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: EqAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n.eq_abs(&i) { println!("|{n}| = |{i}|"); } else { println!("|{n}| ≠ |{i}|"); } } } fn demo_unsigned_partial_eq_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u.eq_abs(&n) { println!("|{u}| = |{n}|"); } else { println!("|{u}| ≠ |{n}|"); } } } fn demo_signed_partial_eq_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i.eq_abs(&n) { println!("|{i}| = |{n}|"); } else { println!("|{i}| ≠ |{n}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: EqAbs + PartialEq, { run_benchmark( &format!("Rational.eq_abs({})", T::NAME), BenchmarkType::Algorithms, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs() == y)), ], ); } #[allow(unused_must_use)] fn benchmark_rational_eq_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: EqAbs + PartialEq<::Output>, { run_benchmark( &format!("Rational.eq_abs({})", T::NAME), BenchmarkType::Algorithms, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.eq_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs() == y.unsigned_abs()); }), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_eq_abs_rational_algorithms< T: EqAbs + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.eq_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y == x.abs())), ], ); } #[allow(unused_must_use)] fn benchmark_signed_eq_abs_rational_algorithms + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialEq, { run_benchmark( &format!("{}.eq_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.eq_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.unsigned_abs() == x)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::hash::hash; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::triple_3_rational_bit_bucketer; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_hash); register_bench!(runner, benchmark_rational_hash_library_comparison); } fn demo_rational_hash(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("hash({}) = {}", n, hash(&n)); } } fn benchmark_rational_hash_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational hash", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(hash(&n))), ("num", &mut |(_, n, _)| no_out!(hash(&n))), ("rug", &mut |(n, _, _)| no_out!(hash(&n))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { cmp::register(runner); cmp_abs::register(runner); eq::register(runner); eq_abs::register(runner); eq_abs_integer::register(runner); eq_abs_natural::register(runner); eq_abs_primitive_float::register(runner); eq_abs_primitive_int::register(runner); hash::register(runner); partial_cmp_abs_integer::register(runner); partial_cmp_abs_natural::register(runner); partial_cmp_abs_primitive_float::register(runner); partial_cmp_abs_primitive_int::register(runner); partial_cmp_integer::register(runner); partial_cmp_natural::register(runner); partial_cmp_primitive_float::register(runner); partial_cmp_primitive_int::register(runner); partial_eq_integer::register(runner); partial_eq_natural::register(runner); partial_eq_primitive_float::register(runner); partial_eq_primitive_int::register(runner); } mod cmp; mod cmp_abs; mod eq; mod eq_abs; mod eq_abs_integer; mod eq_abs_natural; mod eq_abs_primitive_float; mod eq_abs_primitive_int; mod hash; mod partial_cmp_abs_integer; mod partial_cmp_abs_natural; mod partial_cmp_abs_primitive_float; mod partial_cmp_abs_primitive_int; mod partial_cmp_integer; mod partial_cmp_natural; mod partial_cmp_primitive_float; mod partial_cmp_primitive_int; mod partial_eq_integer; mod partial_eq_natural; mod partial_eq_primitive_float; mod partial_eq_primitive_int; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_integer_max_bit_bucketer; use malachite_q::test_util::generators::rational_integer_pair_gen; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_cmp_abs_integer); register_demo!(runner, demo_integer_partial_cmp_abs_rational); register_demo!(runner, demo_rational_lt_abs_integer); register_demo!(runner, demo_rational_gt_abs_integer); register_demo!(runner, demo_rational_le_abs_integer); register_demo!(runner, demo_rational_ge_abs_integer); register_demo!(runner, demo_integer_lt_abs_rational); register_demo!(runner, demo_integer_gt_abs_rational); register_demo!(runner, demo_integer_le_abs_rational); register_demo!(runner, demo_integer_ge_abs_rational); register_bench!( runner, benchmark_rational_partial_cmp_abs_integer_algorithms ); register_bench!( runner, benchmark_integer_partial_cmp_abs_rational_algorithms ); register_bench!(runner, benchmark_rational_lt_abs_integer); register_bench!(runner, benchmark_rational_gt_abs_integer); register_bench!(runner, benchmark_rational_le_abs_integer); register_bench!(runner, benchmark_rational_ge_abs_integer); register_bench!(runner, benchmark_integer_lt_abs_rational); register_bench!(runner, benchmark_integer_gt_abs_rational); register_bench!(runner, benchmark_integer_le_abs_rational); register_bench!(runner, benchmark_integer_ge_abs_rational); } fn demo_rational_partial_cmp_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y).unwrap() { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } fn demo_integer_partial_cmp_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { match y.partial_cmp_abs(&x).unwrap() { Less => println!("|{y}| < |{x}|"), Equal => println!("|{y}| = |{x}|"), Greater => println!("|{y}| > |{x}|"), } } } fn demo_rational_lt_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x.lt_abs(&y) { println!("|{x}| < |{y}|"); } else { println!("|{x}| ≮ |{y}|"); } } } fn demo_rational_gt_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x.gt_abs(&y) { println!("|{x}| > |{y}|"); } else { println!("|{x}| ≯ |{y}|"); } } } fn demo_rational_le_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x.le_abs(&y) { println!("|{x}| ≤ |{y}|"); } else { println!("|{x}| ≰ |{y}|"); } } } fn demo_rational_ge_abs_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x.ge_abs(&y) { println!("|{x}| ≥ |{y}|"); } else { println!("|{x}| ≱ |{y}|"); } } } fn demo_integer_lt_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y.lt_abs(&x) { println!("|{y}| < |{x}|"); } else { println!("|{y}| ≮ |{x}|"); } } } fn demo_integer_gt_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y.gt_abs(&x) { println!("|{y}| > |{x}|"); } else { println!("|{y}| ≯ |{x}|"); } } } fn demo_integer_le_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y.le_abs(&x) { println!("|{y}| ≤ |{x}|"); } else { println!("|{y}| ≰ |{x}|"); } } } fn demo_integer_ge_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y.ge_abs(&x) { println!("|{y}| ≥ |{x}|"); } else { println!("|{y}| ≱ |{x}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_abs_integer_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp_abs(&Integer)", BenchmarkType::Algorithms, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.partial_cmp_abs(&Rational)", BenchmarkType::Algorithms, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.abs().partial_cmp(&x.abs())); }), ], ); } fn benchmark_rational_lt_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.lt_abs(&Integer)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_rational_gt_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.gt_abs(&Integer)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_rational_le_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.le_abs(&Integer)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_rational_ge_abs_integer( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ge_abs(&Integer)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_integer_lt_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.lt_abs(&Rational)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_integer_gt_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.gt_abs(&Rational)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_integer_le_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.le_abs(&Rational)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_integer_ge_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer.ge_abs(&Rational)", BenchmarkType::Single, rational_integer_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_integer_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_natural_max_bit_bucketer; use malachite_q::test_util::generators::rational_natural_pair_gen; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_cmp_abs_natural); register_demo!(runner, demo_natural_partial_cmp_abs_rational); register_demo!(runner, demo_rational_lt_abs_natural); register_demo!(runner, demo_rational_gt_abs_natural); register_demo!(runner, demo_rational_le_abs_natural); register_demo!(runner, demo_rational_ge_abs_natural); register_demo!(runner, demo_natural_lt_abs_rational); register_demo!(runner, demo_natural_gt_abs_rational); register_demo!(runner, demo_natural_le_abs_rational); register_demo!(runner, demo_natural_ge_abs_rational); register_bench!( runner, benchmark_rational_partial_cmp_abs_natural_algorithms ); register_bench!( runner, benchmark_natural_partial_cmp_abs_rational_algorithms ); register_bench!(runner, benchmark_rational_lt_abs_natural); register_bench!(runner, benchmark_rational_gt_abs_natural); register_bench!(runner, benchmark_rational_le_abs_natural); register_bench!(runner, benchmark_rational_ge_abs_natural); register_bench!(runner, benchmark_natural_lt_abs_rational); register_bench!(runner, benchmark_natural_gt_abs_rational); register_bench!(runner, benchmark_natural_le_abs_rational); register_bench!(runner, benchmark_natural_ge_abs_rational); } fn demo_rational_partial_cmp_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp_abs(&y).unwrap() { Less => println!("|{x}| < |{y}|"), Equal => println!("|{x}| = |{y}|"), Greater => println!("|{x}| > |{y}|"), } } } fn demo_natural_partial_cmp_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { match y.partial_cmp_abs(&x).unwrap() { Less => println!("|{y}| < |{x}|"), Equal => println!("|{y}| = |{x}|"), Greater => println!("|{y}| > |{x}|"), } } } fn demo_rational_lt_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x.lt_abs(&y) { println!("|{x}| < |{y}|"); } else { println!("|{x}| ≮ |{y}|"); } } } fn demo_rational_gt_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x.gt_abs(&y) { println!("|{x}| > |{y}|"); } else { println!("|{x}| ≯ |{y}|"); } } } fn demo_rational_le_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x.le_abs(&y) { println!("|{x}| ≤ |{y}|"); } else { println!("|{x}| ≰ |{y}|"); } } } fn demo_rational_ge_abs_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x.ge_abs(&y) { println!("|{x}| ≥ |{y}|"); } else { println!("|{x}| ≱ |{y}|"); } } } fn demo_natural_lt_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y.lt_abs(&x) { println!("|{y}| < |{x}|"); } else { println!("|{y}| ≮ |{x}|"); } } } fn demo_natural_gt_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y.gt_abs(&x) { println!("|{y}| > |{x}|"); } else { println!("|{y}| ≯ |{x}|"); } } } fn demo_natural_le_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y.le_abs(&x) { println!("|{y}| ≤ |{x}|"); } else { println!("|{y}| ≰ |{x}|"); } } } fn demo_natural_ge_abs_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y.ge_abs(&x) { println!("|{y}| ≥ |{x}|"); } else { println!("|{y}| ≱ |{x}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_abs_natural_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp_abs(&Natural)", BenchmarkType::Algorithms, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_abs_rational_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp_abs(&Rational)", BenchmarkType::Algorithms, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.partial_cmp(&x.abs()))), ], ); } fn benchmark_rational_lt_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.lt_abs(&Natural)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_rational_gt_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.gt_abs(&Natural)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_rational_le_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.le_abs(&Natural)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_rational_ge_abs_natural( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.ge_abs(&Natural)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_natural_lt_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.lt_abs(&Rational)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_natural_gt_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.gt_abs(&Rational)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_natural_le_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.le_abs(&Rational)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_natural_ge_abs_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.ge_abs(&Rational)", BenchmarkType::Single, rational_natural_pair_gen().get(gm, config), gm.name(), limit, file_name, &rational_natural_max_bit_bucketer("x", "y"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::rational_primitive_float_pair_gen; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_partial_cmp_abs_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_abs_rational); register_primitive_float_benches!(runner, benchmark_rational_partial_cmp_abs_float_algorithms); register_primitive_float_benches!(runner, benchmark_float_partial_cmp_abs_rational_algorithms); } fn demo_rational_partial_cmp_abs_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp_abs(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("|{}| < |{}|", n, NiceFloat(f)), Some(Equal) => println!("|{}| = |{}|", n, NiceFloat(f)), Some(Greater) => println!("|{}| > |{}|", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_abs_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp_abs(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("|{}| < |{}|", NiceFloat(f), n), Some(Equal) => println!("|{}| = |{}|", NiceFloat(f), n), Some(Greater) => println!("|{}| > |{}|", NiceFloat(f), n), } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_abs_float_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Rational.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, rational_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_float_partial_cmp_abs_rational_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_primitive_float_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.abs().partial_cmp_abs(&x.abs())); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{rational_signed_pair_gen, rational_unsigned_pair_gen}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_partial_cmp_abs_unsigned); register_signed_demos!(runner, demo_rational_partial_cmp_abs_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_abs_rational); register_signed_demos!(runner, demo_signed_partial_cmp_abs_rational); register_unsigned_demos!(runner, demo_rational_lt_abs_unsigned); register_signed_demos!(runner, demo_rational_lt_abs_signed); register_unsigned_demos!(runner, demo_rational_gt_abs_unsigned); register_signed_demos!(runner, demo_rational_gt_abs_signed); register_unsigned_demos!(runner, demo_rational_le_abs_unsigned); register_signed_demos!(runner, demo_rational_le_abs_signed); register_unsigned_demos!(runner, demo_rational_ge_abs_unsigned); register_signed_demos!(runner, demo_rational_ge_abs_signed); register_unsigned_demos!(runner, demo_unsigned_lt_abs_rational); register_signed_demos!(runner, demo_signed_lt_abs_rational); register_unsigned_demos!(runner, demo_unsigned_gt_abs_rational); register_signed_demos!(runner, demo_signed_gt_abs_rational); register_unsigned_demos!(runner, demo_unsigned_le_abs_rational); register_signed_demos!(runner, demo_signed_le_abs_rational); register_unsigned_demos!(runner, demo_unsigned_ge_abs_rational); register_signed_demos!(runner, demo_signed_ge_abs_rational); register_unsigned_benches!( runner, benchmark_rational_partial_cmp_abs_unsigned_algorithms ); register_signed_benches!(runner, benchmark_rational_partial_cmp_abs_signed_algorithms); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_abs_rational_algorithms ); register_signed_benches!(runner, benchmark_signed_partial_cmp_abs_rational_algorithms); register_unsigned_benches!(runner, benchmark_rational_lt_abs_unsigned); register_signed_benches!(runner, benchmark_rational_lt_abs_signed); register_unsigned_benches!(runner, benchmark_rational_gt_abs_unsigned); register_signed_benches!(runner, benchmark_rational_gt_abs_signed); register_unsigned_benches!(runner, benchmark_rational_le_abs_unsigned); register_signed_benches!(runner, benchmark_rational_le_abs_signed); register_unsigned_benches!(runner, benchmark_rational_ge_abs_unsigned); register_signed_benches!(runner, benchmark_rational_ge_abs_signed); register_unsigned_benches!(runner, benchmark_unsigned_lt_abs_rational); register_signed_benches!(runner, benchmark_signed_lt_abs_rational); register_unsigned_benches!(runner, benchmark_unsigned_gt_abs_rational); register_signed_benches!(runner, benchmark_signed_gt_abs_rational); register_unsigned_benches!(runner, benchmark_unsigned_le_abs_rational); register_signed_benches!(runner, benchmark_signed_le_abs_rational); register_unsigned_benches!(runner, benchmark_unsigned_ge_abs_rational); register_signed_benches!(runner, benchmark_signed_ge_abs_rational); } fn demo_rational_partial_cmp_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp_abs(&u).unwrap() { Less => println!("|{n}| < |{u}|"), Equal => println!("|{n}| = |{u}|"), Greater => println!("|{n}| > |{u}|"), } } } fn demo_rational_partial_cmp_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp_abs(&i).unwrap() { Less => println!("|{n}| < |{i}|"), Equal => println!("|{n}| = |{i}|"), Greater => println!("|{n}| > |{i}|"), } } } fn demo_unsigned_partial_cmp_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { match u.partial_cmp_abs(&n).unwrap() { Less => println!("|{u}| < |{n}|"), Equal => println!("|{u}| = |{n}|"), Greater => println!("|{u}| > |{n}|"), } } } fn demo_signed_partial_cmp_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp_abs(&n).unwrap() { Less => println!("|{i}| < |{n}|"), Equal => println!("|{i}| = |{n}|"), Greater => println!("|{i}| > |{n}|"), } } } fn demo_rational_lt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n.lt_abs(&u) { println!("|{n}| < |{u}|"); } else { println!("|{n}| ≮ |{u}|"); } } } fn demo_rational_lt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialOrdAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n.lt_abs(&i) { println!("|{n}| < |{i}|"); } else { println!("|{n}| ≮ |{i}|"); } } } fn demo_rational_gt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n.gt_abs(&u) { println!("|{n}| > |{u}|"); } else { println!("|{n}| ≯ |{u}|"); } } } fn demo_rational_gt_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialOrdAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n.gt_abs(&i) { println!("|{n}| > |{i}|"); } else { println!("|{n}| ≯ |{i}|"); } } } fn demo_rational_le_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n.le_abs(&u) { println!("|{n}| ≤ |{u}|"); } else { println!("|{n}| ≰ |{u}|"); } } } fn demo_rational_le_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialOrdAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n.le_abs(&i) { println!("|{n}| ≤ |{i}|"); } else { println!("|{n}| ≰ |{i}|"); } } } fn demo_rational_ge_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrdAbs, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n.ge_abs(&u) { println!("|{n}| ≥ |{u}|"); } else { println!("|{n}| ≱ |{u}|"); } } } fn demo_rational_ge_abs_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialOrdAbs, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n.ge_abs(&i) { println!("|{n}| ≥ |{i}|"); } else { println!("|{n}| ≱ |{i}|"); } } } fn demo_unsigned_lt_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u.lt_abs(&n) { println!("|{u}| < |{n}|"); } else { println!("|{u}| ≮ |{n}|"); } } } fn demo_signed_lt_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i.lt_abs(&n) { println!("|{i}| < |{n}|"); } else { println!("|{i}| ≮ |{n}|"); } } } fn demo_unsigned_gt_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u.gt_abs(&n) { println!("|{u}| > |{n}|"); } else { println!("|{u}| ≯ |{n}|"); } } } fn demo_signed_gt_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i.gt_abs(&n) { println!("|{i}| > |{n}|"); } else { println!("|{i}| ≯ |{n}|"); } } } fn demo_unsigned_le_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u.le_abs(&n) { println!("|{u}| ≤ |{n}|"); } else { println!("|{u}| ≰ |{n}|"); } } } fn demo_signed_le_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i.le_abs(&n) { println!("|{i}| ≤ |{n}|"); } else { println!("|{i}| ≰ |{n}|"); } } } fn demo_unsigned_ge_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u.ge_abs(&n) { println!("|{u}| ≥ |{n}|"); } else { println!("|{u}| ≱ |{n}|"); } } } fn demo_signed_ge_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i.ge_abs(&n) { println!("|{i}| ≥ |{n}|"); } else { println!("|{i}| ≱ |{n}|"); } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_abs_unsigned_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs + PartialOrd, { run_benchmark( &format!("Rational.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| no_out!(x.abs().partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_abs_signed_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs + PartialOrd<::Output>, { run_benchmark( &format!("Rational.partial_cmp_abs(&{})", T::NAME), BenchmarkType::Algorithms, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(x.partial_cmp_abs(&y))), ("using abs", &mut |(x, y)| { no_out!(x.abs().partial_cmp(&y.unsigned_abs())); }), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_abs_rational_algorithms< T: PartialOrdAbs + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| no_out!(y.partial_cmp(&x.abs()))), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_abs_rational_algorithms< T: PartialOrdAbs + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where ::Output: PartialOrd, { run_benchmark( &format!("{}.partial_cmp_abs(&Rational)", T::NAME), BenchmarkType::Algorithms, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("default", &mut |(x, y)| no_out!(y.partial_cmp_abs(&x))), ("using abs", &mut |(x, y)| { no_out!(y.unsigned_abs().partial_cmp(&x.abs())); }), ], ); } fn benchmark_rational_lt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.lt_abs(&{})", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_rational_lt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.lt_abs(&{})", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.lt_abs(&y)))], ); } fn benchmark_rational_gt_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.gt_abs(&{})", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_rational_gt_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.gt_abs(&{})", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.gt_abs(&y)))], ); } fn benchmark_rational_le_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.le_abs(&{})", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_rational_le_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.le_abs(&{})", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.le_abs(&y)))], ); } fn benchmark_rational_ge_abs_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.ge_abs(&{})", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_rational_ge_abs_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrdAbs, { run_benchmark( &format!("Rational.ge_abs(&{})", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(x.ge_abs(&y)))], ); } fn benchmark_unsigned_lt_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_signed_lt_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.lt_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.lt_abs(&x)))], ); } fn benchmark_unsigned_gt_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_signed_gt_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.gt_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.gt_abs(&x)))], ); } fn benchmark_unsigned_le_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_signed_le_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.le_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.le_abs(&x)))], ); } fn benchmark_unsigned_ge_abs_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_unsigned_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } fn benchmark_signed_ge_abs_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.ge_abs(&Rational)", T::NAME), BenchmarkType::Single, rational_signed_pair_gen::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, y)| no_out!(y.ge_abs(&x)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_2_rational_integer_max_bit_bucketer; use malachite_q::test_util::generators::{rational_integer_pair_gen, rational_integer_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_cmp_integer); register_demo!(runner, demo_integer_partial_cmp_rational); register_bench!( runner, benchmark_rational_partial_cmp_integer_library_comparison ); register_bench!( runner, benchmark_integer_partial_cmp_rational_library_comparison ); } fn demo_rational_partial_cmp_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y).unwrap() { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } fn demo_integer_partial_cmp_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { match y.partial_cmp(&x).unwrap() { Less => println!("{y} < {x}"), Equal => println!("{y} = {x}"), Greater => println!("{y} > {x}"), } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp(&Natural)", BenchmarkType::LibraryComparison, rational_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_integer_partial_cmp_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp(&Rational)", BenchmarkType::LibraryComparison, rational_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_2_rational_natural_max_bit_bucketer; use malachite_q::test_util::generators::{rational_natural_pair_gen, rational_natural_pair_gen_rm}; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_cmp_natural); register_demo!(runner, demo_natural_partial_cmp_rational); register_bench!( runner, benchmark_rational_partial_cmp_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_cmp_rational_library_comparison ); } fn demo_rational_partial_cmp_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { match x.partial_cmp(&y).unwrap() { Less => println!("{x} < {y}"), Equal => println!("{x} = {y}"), Greater => println!("{x} > {y}"), } } } fn demo_natural_partial_cmp_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { match y.partial_cmp(&x).unwrap() { Less => println!("{y} < {x}"), Equal => println!("{y} = {x}"), Greater => println!("{y} > {x}"), } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.partial_cmp(&Natural)", BenchmarkType::LibraryComparison, rational_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_natural_partial_cmp_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural.partial_cmp(&Rational)", BenchmarkType::LibraryComparison, rational_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_2_pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_primitive_float_pair_gen, rational_primitive_float_pair_gen_rm, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_partial_cmp_float); register_primitive_float_demos!(runner, demo_float_partial_cmp_rational); register_primitive_float_benches!( runner, benchmark_rational_partial_cmp_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_cmp_rational_library_comparison ); } fn demo_rational_partial_cmp_float(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialOrd, { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp(&f) { None => println!("{} is not comparable with {}", n, NiceFloat(f)), Some(Less) => println!("{} < {}", n, NiceFloat(f)), Some(Equal) => println!("{} = {}", n, NiceFloat(f)), Some(Greater) => println!("{} > {}", n, NiceFloat(f)), } } } fn demo_float_partial_cmp_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { match f.partial_cmp(&n) { None => println!("{} is not comparable with {}", NiceFloat(f), n), Some(Less) => println!("{} < {}", NiceFloat(f), n), Some(Equal) => println!("{} = {}", NiceFloat(f), n), Some(Greater) => println!("{} > {}", NiceFloat(f), n), } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_cmp_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrd, rug::Rational: PartialOrd, { run_benchmark( &format!("Rational.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, rational_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_cmp_rational_library_comparison< T: PartialOrd + PartialOrd + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Rational)", T::NAME), BenchmarkType::LibraryComparison, rational_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_2_pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_signed_pair_gen, rational_signed_pair_gen_rm, rational_unsigned_pair_gen, rational_unsigned_pair_gen_rm, }; use std::cmp::Ordering::*; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_partial_cmp_unsigned); register_signed_demos!(runner, demo_rational_partial_cmp_signed); register_unsigned_demos!(runner, demo_unsigned_partial_cmp_rational); register_signed_demos!(runner, demo_signed_partial_cmp_rational); register_unsigned_benches!( runner, benchmark_rational_partial_cmp_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_rational_partial_cmp_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_cmp_rational_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_cmp_rational_library_comparison ); } fn demo_rational_partial_cmp_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrd, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { match n.partial_cmp(&u).unwrap() { Less => println!("{n} < {u}"), Equal => println!("{n} = {u}"), Greater => println!("{n} > {u}"), } } } fn demo_rational_partial_cmp_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrd, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { match n.partial_cmp(&i).unwrap() { Less => println!("{n} < {i}"), Equal => println!("{n} = {i}"), Greater => println!("{n} > {i}"), } } } fn demo_unsigned_partial_cmp_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { match u.partial_cmp(&n).unwrap() { Less => println!("{u} < {n}"), Equal => println!("{u} = {n}"), Greater => println!("{u} > {n}"), } } } fn demo_signed_partial_cmp_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { match i.partial_cmp(&n).unwrap() { Less => println!("{i} < {n}"), Equal => println!("{i} = {n}"), Greater => println!("{i} > {n}"), } } } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrd, rug::Rational: PartialOrd, { run_benchmark( &format!("Rational.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_partial_cmp_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrd, rug::Rational: PartialOrd, { run_benchmark( &format!("Rational.partial_cmp(&{})", T::NAME), BenchmarkType::LibraryComparison, rational_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x.partial_cmp(&y))), ("rug", &mut |((x, y), _)| no_out!(x.partial_cmp(&y))), ], ); } #[allow(unused_must_use)] fn benchmark_unsigned_partial_cmp_rational_library_comparison< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Rational)", T::NAME), BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } #[allow(unused_must_use)] fn benchmark_signed_partial_cmp_rational_library_comparison< T: PartialOrd + PartialOrd + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}.partial_cmp(&Rational)", T::NAME), BenchmarkType::LibraryComparison, rational_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y.partial_cmp(&x))), ("rug", &mut |((x, y), _)| no_out!(y.partial_cmp(&x))), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_2_rational_integer_max_bit_bucketer; use malachite_q::test_util::generators::{rational_integer_pair_gen, rational_integer_pair_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_eq_integer); register_demo!(runner, demo_integer_partial_eq_rational); register_bench!( runner, benchmark_rational_partial_eq_integer_library_comparison ); register_bench!( runner, benchmark_integer_partial_eq_rational_library_comparison ); } fn demo_rational_partial_eq_integer(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_integer_partial_eq_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_integer_pair_gen().get(gm, config).take(limit) { if y == x { println!("{y} = {x}"); } else { println!("{y} ≠ {x}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_eq_integer_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational == Integer", BenchmarkType::LibraryComparison, rational_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_integer_partial_eq_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer == Rational", BenchmarkType::LibraryComparison, rational_integer_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_integer_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::pair_2_rational_natural_max_bit_bucketer; use malachite_q::test_util::generators::{rational_natural_pair_gen, rational_natural_pair_gen_rm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_partial_eq_natural); register_demo!(runner, demo_natural_partial_eq_rational); register_bench!( runner, benchmark_rational_partial_eq_natural_library_comparison ); register_bench!( runner, benchmark_natural_partial_eq_rational_library_comparison ); } fn demo_rational_partial_eq_natural(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if x == y { println!("{x} = {y}"); } else { println!("{x} ≠ {y}"); } } } fn demo_natural_partial_eq_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, y) in rational_natural_pair_gen().get(gm, config).take(limit) { if y == x { println!("{y} = {x}"); } else { println!("{y} ≠ {x}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_eq_natural_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational == Natural", BenchmarkType::LibraryComparison, rational_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_natural_partial_eq_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural == Rational", BenchmarkType::LibraryComparison, rational_natural_pair_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_natural_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_2_pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_primitive_float_pair_gen, rational_primitive_float_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_partial_eq_float); register_primitive_float_demos!(runner, demo_float_partial_eq_rational); register_primitive_float_benches!( runner, benchmark_rational_partial_eq_float_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_partial_eq_rational_library_comparison ); } fn demo_rational_partial_eq_float(gm: GenMode, config: &GenConfig, limit: usize) where Rational: PartialEq, { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if n == f { println!("{} = {}", n, NiceFloat(f)); } else { println!("{} ≠ {}", n, NiceFloat(f)); } } } fn demo_float_partial_eq_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, f) in rational_primitive_float_pair_gen::() .get(gm, config) .take(limit) { if f == n { println!("{} = {}", NiceFloat(f), n); } else { println!("{} ≠ {}", NiceFloat(f), n); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_eq_float_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialEq, rug::Rational: PartialEq, { run_benchmark( &format!("Rational == {}", T::NAME), BenchmarkType::LibraryComparison, rational_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_float_partial_eq_rational_library_comparison< T: PartialEq + PartialEq + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Rational", T::NAME), BenchmarkType::LibraryComparison, rational_primitive_float_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::pair_2_pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_signed_pair_gen, rational_signed_pair_gen_rm, rational_unsigned_pair_gen, rational_unsigned_pair_gen_rm, }; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_partial_eq_unsigned); register_signed_demos!(runner, demo_rational_partial_eq_signed); register_unsigned_demos!(runner, demo_unsigned_partial_eq_rational); register_signed_demos!(runner, demo_signed_partial_eq_rational); register_unsigned_benches!( runner, benchmark_rational_partial_eq_unsigned_library_comparison ); register_signed_benches!( runner, benchmark_rational_partial_eq_signed_library_comparison ); register_unsigned_benches!( runner, benchmark_unsigned_partial_eq_rational_library_comparison ); register_signed_benches!( runner, benchmark_signed_partial_eq_rational_library_comparison ); } fn demo_rational_partial_eq_unsigned( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialEq, { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if n == u { println!("{n} = {u}"); } else { println!("{n} ≠ {u}"); } } } fn demo_rational_partial_eq_signed( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialEq, { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if n == i { println!("{n} = {i}"); } else { println!("{n} ≠ {i}"); } } } fn demo_unsigned_partial_eq_rational + PrimitiveUnsigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, u) in rational_unsigned_pair_gen::() .get(gm, config) .take(limit) { if u == n { println!("{u} = {n}"); } else { println!("{u} ≠ {n}"); } } } fn demo_signed_partial_eq_rational + PrimitiveSigned>( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, i) in rational_signed_pair_gen::().get(gm, config).take(limit) { if i == n { println!("{i} = {n}"); } else { println!("{i} ≠ {n}"); } } } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_eq_unsigned_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialEq, rug::Rational: PartialEq, { run_benchmark( &format!("Rational == {}", T::NAME), BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_rational_partial_eq_signed_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialEq, rug::Rational: PartialEq, { run_benchmark( &format!("Rational == {}", T::NAME), BenchmarkType::LibraryComparison, rational_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(x == y)), ("rug", &mut |((x, y), _)| no_out!(x == y)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_unsigned_partial_eq_rational_library_comparison< T: PartialEq + PartialEq + PrimitiveUnsigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Rational", T::NAME), BenchmarkType::LibraryComparison, rational_unsigned_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } #[allow(clippy::no_effect, clippy::unnecessary_operation, unused_must_use)] fn benchmark_signed_partial_eq_rational_library_comparison< T: PartialEq + PartialEq + PrimitiveSigned, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{} == Rational", T::NAME), BenchmarkType::LibraryComparison, rational_signed_pair_gen_rm::().get(gm, config), gm.name(), limit, file_name, &pair_2_pair_1_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, (x, y))| no_out!(y == x)), ("rug", &mut |((x, y), _)| no_out!(y == x)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ triple_3_pair_rational_max_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_gen, rational_gen_nrm, rational_pair_gen, rational_pair_gen_nrm, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_clone); register_demo!(runner, demo_rational_clone_from); register_bench!(runner, benchmark_rational_clone_library_comparison); register_bench!(runner, benchmark_rational_clone_from_library_comparison); } fn demo_rational_clone(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!("clone({}) = {}", n, n.clone()); } } fn demo_rational_clone_from(gm: GenMode, config: &GenConfig, limit: usize) { for (mut x, y) in rational_pair_gen().get(gm, config).take(limit) { let x_old = x.clone(); x.clone_from(&y); println!("x := {x_old}; x.clone_from({y}); x = {x}"); } } #[allow(clippy::redundant_clone, unused_must_use)] fn benchmark_rational_clone_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.clone()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, _, n)| no_out!(n.clone())), ("num", &mut |(n, _, _)| no_out!(n.clone())), ("rug", &mut |(_, n, _)| no_out!(n.clone())), ], ); } fn benchmark_rational_clone_from_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.clone_from(&Rational)", BenchmarkType::LibraryComparison, rational_pair_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_rational_max_bit_bucketer("x", "y"), &mut [ ("Malachite", &mut |(_, _, (mut x, y))| x.clone_from(&y)), ("num", &mut |((mut x, y), _, _)| x.clone_from(&y)), ("rug", &mut |(_, (mut x, y), _)| x.clone_from(&y)), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/continued_fraction/convergents.rs ================================================ // Copyright © 2026 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::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::conversion::traits::Convergents; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::conversion::continued_fraction::convergents::convergents_alt; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_convergents); register_demo!(runner, demo_rational_convergents_ref); register_bench!(runner, benchmark_rational_convergents_algorithms); register_bench!(runner, benchmark_rational_convergents_evaluation_strategy); } fn demo_rational_convergents(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "convergents({}) = {:?}", x.clone(), x.convergents().collect_vec() ); } } fn demo_rational_convergents_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "convergents(&{}) = {:?}", x, (&x).convergents().collect_vec() ); } } fn benchmark_rational_convergents_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.convergents()", BenchmarkType::Algorithms, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("default", &mut |x| no_out!(x.convergents().collect_vec())), ("naive", &mut |x| no_out!(convergents_alt(x).collect_vec())), ], ); } fn benchmark_rational_convergents_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.convergents()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.convergents()", &mut |x| { no_out!(x.convergents().collect_vec()); }), ("(&Rational).convergents()", &mut |x| { no_out!((&x).convergents().collect_vec()); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/continued_fraction/from_continued_fraction.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::pair_1_vec_natural_sum_bits_bucketer; use malachite_nz::test_util::generators::natural_vec_integer_pair_gen_var_1; use malachite_q::Rational; use malachite_q::test_util::conversion::continued_fraction::from_continued_fraction::*; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_continued_fraction); register_demo!(runner, demo_rational_from_continued_fraction_ref); register_bench!( runner, benchmark_rational_from_continued_fraction_algorithms ); register_bench!( runner, benchmark_rational_from_continued_fraction_evaluation_strategy ); } fn demo_rational_from_continued_fraction(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, floor) in natural_vec_integer_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "from_continued_fraction({}, {:?}) = {}", floor.clone(), xs.clone(), Rational::from_continued_fraction(floor, xs.into_iter()) ); } } fn demo_rational_from_continued_fraction_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (xs, floor) in natural_vec_integer_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "from_continued_fraction_ref({}, {:?}) = {}", floor, xs, Rational::from_continued_fraction_ref(&floor, xs.iter()) ); } } fn benchmark_rational_from_continued_fraction_algorithms( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_continued_fraction(&Integer, &[Natural])", BenchmarkType::Algorithms, natural_vec_integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_natural_sum_bits_bucketer(), &mut [ ("default", &mut |(xs, floor)| { no_out!(Rational::from_continued_fraction(floor, xs.into_iter())); }), ("alt", &mut |(xs, floor)| { no_out!(from_continued_fraction_alt(floor, xs)); }), ], ); } fn benchmark_rational_from_continued_fraction_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_continued_fraction(&Integer, &[Natural])", BenchmarkType::EvaluationStrategy, natural_vec_integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_vec_natural_sum_bits_bucketer(), &mut [ ( "Rational::from_continued_fraction(Integer, Vec)", &mut |(xs, floor)| { no_out!(Rational::from_continued_fraction(floor, xs.into_iter())); }, ), ( "Rational::from_continued_fraction_ref(&Integer, &[Natural])", &mut |(xs, floor)| { no_out!(Rational::from_continued_fraction_ref(&floor, xs.iter())); }, ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/continued_fraction/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { convergents::register(runner); from_continued_fraction::register(runner); to_continued_fraction::register(runner); } mod convergents; mod from_continued_fraction; mod to_continued_fraction; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/continued_fraction/to_continued_fraction.rs ================================================ // Copyright © 2026 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::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::conversion::continued_fraction::to_continued_fraction::RationalContinuedFraction; use malachite_q::conversion::traits::ContinuedFraction; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_continued_fraction); register_demo!(runner, demo_rational_continued_fraction_ref); register_bench!( runner, benchmark_rational_continued_fraction_evaluation_strategy ); } fn helper(p: (Integer, RationalContinuedFraction)) -> (Integer, Vec) { (p.0, p.1.collect_vec()) } fn demo_rational_continued_fraction(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "continued_fraction({}) = {:?}", x.clone(), helper(x.continued_fraction()) ); } } fn demo_rational_continued_fraction_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "continued_fraction(&{}) = {:?}", x, helper((&x).continued_fraction()) ); } } fn benchmark_rational_continued_fraction_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.continued_fraction()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.continued_fraction()", &mut |n| { no_out!(n.continued_fraction().1.collect_vec()); }), ("(&Rational).continued_fraction()", &mut |n| { no_out!((&n).continued_fraction().1.collect_vec()); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/digits/from_digits.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_nz::test_util::bench::bucketers::rational_from_digits_bucketer; use malachite_nz::test_util::generators::{large_type_gen_var_25, large_type_gen_var_26}; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_digits); register_demo!(runner, demo_rational_from_digits_ref); register_demo!(runner, demo_rational_from_digits_decimal); register_bench!(runner, benchmark_rational_from_digits_evaluation_strategy); } fn demo_rational_from_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (base, before_point, after_point) in large_type_gen_var_25().get(gm, config).take(limit) { println!( "from_digits({}, {:?}, {}) = {}", base, before_point.clone(), after_point.clone(), Rational::from_digits(&base, before_point, after_point) ); } } fn demo_rational_from_digits_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (base, before_point, after_point) in large_type_gen_var_25().get(gm, config).take(limit) { println!( "from_digits_ref({}, {:?}, {:?}) = {}", base, before_point, after_point, Rational::from_digits_ref(&base, &before_point, &after_point) ); } } fn demo_rational_from_digits_decimal(gm: GenMode, config: &GenConfig, limit: usize) { for (before_point, after_point) in large_type_gen_var_26().get(gm, config).take(limit) { println!( "from_digits(1, {:?}, {}) = {}", before_point.clone(), after_point.clone(), Rational::from_digits(&Natural::from(10u32), before_point, after_point) ); } } fn benchmark_rational_from_digits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_digits(Natural, &[Natural], &RationalSequence)", BenchmarkType::EvaluationStrategy, large_type_gen_var_25().get(gm, config), gm.name(), limit, file_name, &rational_from_digits_bucketer(), &mut [ ( "Rational::from_digits(base, Vec, RationalSequence)", &mut |(base, before_point, after_point)| { no_out!(Rational::from_digits(&base, before_point, after_point)); }, ), ( "Rational::from_digits_ref(base, &[Natural], &RationalSequence)", &mut |(base, before_point, after_point)| { no_out!(Rational::from_digits_ref( &base, &before_point, &after_point )); }, ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::rational_from_power_of_2_digits_bucketer; use malachite_nz::test_util::generators::{large_type_gen_var_23, large_type_gen_var_24}; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_power_of_2_digits); register_demo!(runner, demo_rational_from_power_of_2_digits_ref); register_demo!(runner, demo_rational_from_power_of_2_digits_binary); register_bench!( runner, benchmark_rational_from_power_of_2_digits_evaluation_strategy ); } fn demo_rational_from_power_of_2_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (log_base, before_point, after_point) in large_type_gen_var_23().get(gm, config).take(limit) { println!( "from_power_of_2_digits({}, {:?}, {}) = {}", log_base, before_point.clone(), after_point.clone(), Rational::from_power_of_2_digits(log_base, before_point, after_point) ); } } fn demo_rational_from_power_of_2_digits_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (log_base, before_point, after_point) in large_type_gen_var_23().get(gm, config).take(limit) { println!( "from_power_of_2_digits_ref({}, {:?}, {:?}) = {}", log_base, before_point, after_point, Rational::from_power_of_2_digits_ref(log_base, &before_point, &after_point) ); } } fn demo_rational_from_power_of_2_digits_binary(gm: GenMode, config: &GenConfig, limit: usize) { for (before_point, after_point) in large_type_gen_var_24().get(gm, config).take(limit) { println!( "from_power_of_2_digits(1, {:?}, {}) = {}", before_point.clone(), after_point.clone(), Rational::from_power_of_2_digits(1, before_point, after_point) ); } } fn benchmark_rational_from_power_of_2_digits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_power_of_2_digits(u64, &[Natural], &RationalSequence)", BenchmarkType::EvaluationStrategy, large_type_gen_var_23().get(gm, config), gm.name(), limit, file_name, &rational_from_power_of_2_digits_bucketer(), &mut [ ( "Rational::from_power_of_2_digits(u64, Vec, RationalSequence)", &mut |(log_base, before_point, after_point)| { no_out!(Rational::from_power_of_2_digits( log_base, before_point, after_point )); }, ), ( "Rational::from_power_of_2_digits_ref(u64, &[Natural], &RationalSequence)", &mut |(log_base, before_point, after_point)| { no_out!(Rational::from_power_of_2_digits_ref( log_base, &before_point, &after_point )); }, ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_digits::register(runner); from_power_of_2_digits::register(runner); to_digits::register(runner); to_power_of_2_digits::register(runner); } mod from_digits; mod from_power_of_2_digits; mod to_digits; mod to_power_of_2_digits; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/digits/to_digits.rs ================================================ // Copyright © 2026 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::prefix_to_string; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_7, rational_natural_pair_gen_var_1, rational_natural_pair_gen_var_2, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_into_digits); register_demo!(runner, demo_rational_to_digits); register_demo!(runner, demo_rational_into_digits_decimal); register_demo!(runner, demo_rational_digits); register_demo!(runner, demo_rational_digits_decimal); register_bench!(runner, benchmark_rational_to_digits_evaluation_strategy); register_bench!(runner, benchmark_rational_digits); } fn to_string_helper(p: (Vec, RationalSequence)) -> String { let (before, after) = p; let mut s = "(".to_string(); s.push_str(&before.to_debug_string()); s.push_str(", "); s.push_str(&after.to_string()); s.push(')'); s } fn demo_rational_into_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_natural_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "({}).into_digits({}) = {}", n.clone(), base, to_string_helper(n.into_digits(&base)) ); } } fn demo_rational_to_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_natural_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "({}).to_digits({}) = {}", n, base, to_string_helper(n.to_digits(&base)) ); } } fn demo_rational_into_digits_decimal(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_7().get(gm, config).take(limit) { println!( "({}).into_digits(10) = {}", n.clone(), to_string_helper(n.into_digits(&Natural::from(10u32))) ); } } fn demo_rational_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, base) in rational_natural_pair_gen_var_1() .get(gm, config) .take(limit) { let (before_point, after_point) = n.digits(&base); println!( "({}).digits({}) = ({:?}, {})", n, base, before_point, prefix_to_string(after_point, 20) ); } } fn demo_rational_digits_decimal(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { let (before_point, after_point) = n.digits(&Natural::from(10u32)); println!( "({}).digits(10) = ({:?}, {})", n, before_point, prefix_to_string(after_point, 20) ); } } fn benchmark_rational_to_digits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_digits(u64)", BenchmarkType::EvaluationStrategy, rational_natural_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Rational.into_digits(&base)", &mut |(n, base)| { no_out!(n.into_digits(&base)); }), ("Rational.to_digits(&base)", &mut |(n, base)| { no_out!(n.to_digits(&base)); }), ], ); } fn benchmark_rational_digits(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.digits(u64)", BenchmarkType::Single, rational_natural_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [( "Rational.digits(&base).1.take(20).collect_vec()", &mut |(n, base)| no_out!(n.digits(&base).1.take(20).collect_vec()), )], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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::prefix_to_string; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_q::test_util::bench::bucketers::pair_1_rational_bit_bucketer; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_7, rational_unsigned_pair_gen_var_2, rational_unsigned_pair_gen_var_3, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_into_power_of_2_digits); register_demo!(runner, demo_rational_to_power_of_2_digits); register_demo!(runner, demo_rational_into_power_of_2_digits_binary); register_demo!(runner, demo_rational_power_of_2_digits); register_demo!(runner, demo_rational_power_of_2_digits_binary); register_bench!( runner, benchmark_rational_to_power_of_2_digits_evaluation_strategy ); register_bench!(runner, benchmark_rational_power_of_2_digits); } fn to_string_helper(p: (Vec, RationalSequence)) -> String { let (before, after) = p; let mut s = "(".to_string(); s.push_str(&before.to_debug_string()); s.push_str(", "); s.push_str(&after.to_string()); s.push(')'); s } fn demo_rational_into_power_of_2_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in rational_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "({}).into_power_of_2_digits({}) = {}", n.clone(), log_base, to_string_helper(n.into_power_of_2_digits(log_base)) ); } } fn demo_rational_to_power_of_2_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in rational_unsigned_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "({}).to_power_of_2_digits({}) = {}", n, log_base, to_string_helper(n.to_power_of_2_digits(log_base)) ); } } fn demo_rational_into_power_of_2_digits_binary(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen_var_7().get(gm, config).take(limit) { println!( "({}).into_power_of_2_digits(1) = {}", n.clone(), to_string_helper(n.into_power_of_2_digits(1)) ); } } fn demo_rational_power_of_2_digits(gm: GenMode, config: &GenConfig, limit: usize) { for (n, log_base) in rational_unsigned_pair_gen_var_3::() .get(gm, config) .take(limit) { let (before_point, after_point) = n.power_of_2_digits(log_base); println!( "({}).power_of_2_digits({}) = ({:?}, {})", n, log_base, before_point, prefix_to_string(after_point, 20) ); } } fn demo_rational_power_of_2_digits_binary(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { let (before_point, after_point) = n.power_of_2_digits(1); println!( "({}).power_of_2_digits(1) = ({:?}, {})", n, before_point, prefix_to_string(after_point, 20) ); } } fn benchmark_rational_to_power_of_2_digits_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_power_of_2_digits(u64)", BenchmarkType::EvaluationStrategy, rational_unsigned_pair_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ( "Rational.into_power_of_2_digits(log_base)", &mut |(n, log_base)| no_out!(n.into_power_of_2_digits(log_base)), ), ( "Rational.to_power_of_2_digits(log_base)", &mut |(n, log_base)| no_out!(n.to_power_of_2_digits(log_base)), ), ], ); } fn benchmark_rational_power_of_2_digits( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.power_of_2_digits(u64)", BenchmarkType::Single, rational_unsigned_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [( "Rational.power_of_2_digits(log_base).1.take(20).collect_vec()", &mut |(n, log_base)| no_out!(n.power_of_2_digits(log_base).1.take(20).collect_vec()), )], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::bool_gen; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_bool); } fn demo_rational_from_bool(gm: GenMode, config: &GenConfig, limit: usize) { for b in bool_gen().get(gm, config).take(limit) { println!("Rational::from({}) = {}", b, Rational::from(b)); } } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_float_simplest.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen_var_8; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_try_from_float_simplest); register_primitive_float_benches!(runner, benchmark_rational_try_from_float_simplest); } fn demo_rational_try_from_float_simplest( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for f in primitive_float_gen_var_8::().get(gm, config).take(limit) { println!( "Rational::try_from_float_simplest({}) = {:?}", NiceFloat(f), Rational::try_from_float_simplest(f) ); } } fn benchmark_rational_try_from_float_simplest( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: TryFrom, { run_benchmark( &format!("Rational::try_from_float_simplest({})", T::NAME), BenchmarkType::Single, primitive_float_gen_var_8::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| { no_out!(Rational::try_from_float_simplest(f).ok()); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_integer.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::integer_bit_bucketer; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_integer); register_demo!(runner, demo_rational_from_integer_ref); register_bench!(runner, benchmark_rational_from_integer_evaluation_strategy); } fn demo_rational_from_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!("Rational::from({}) = {}", n_clone, Rational::from(n)); } } fn demo_rational_from_integer_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in integer_gen().get(gm, config).take(limit) { println!("Rational::from(&{}) = {}", n, Rational::from(&n)); } } #[allow(unused_must_use)] fn benchmark_rational_from_integer_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(Integer)", BenchmarkType::EvaluationStrategy, integer_gen().get(gm, config), gm.name(), limit, file_name, &integer_bit_bucketer("n"), &mut [ ("Rational::from(Integer)", &mut |n| { no_out!(Rational::from(n)); }), ("Rational::from(&Integer)", &mut |n| { no_out!(Rational::from(&n)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::test_util::bench::bucketers::natural_bit_bucketer; use malachite_nz::test_util::generators::natural_gen; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_natural); register_demo!(runner, demo_rational_from_natural_ref); register_bench!(runner, benchmark_rational_from_natural_evaluation_strategy); } fn demo_rational_from_natural(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { let n_clone = n.clone(); println!("Rational::from({}) = {}", n_clone, Rational::from(n)); } } fn demo_rational_from_natural_ref(gm: GenMode, config: &GenConfig, limit: usize) { for n in natural_gen().get(gm, config).take(limit) { println!("Rational::from(&{}) = {}", n, Rational::from(&n)); } } #[allow(unused_must_use)] fn benchmark_rational_from_natural_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(Natural)", BenchmarkType::EvaluationStrategy, natural_gen().get(gm, config), gm.name(), limit, file_name, &natural_bit_bucketer("n"), &mut [ ("Rational::from(Natural)", &mut |n| { no_out!(Rational::from(n)); }), ("Rational::from(&Natural)", &mut |n| { no_out!(Rational::from(&n)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_numerator_and_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{ pair_max_bit_bucketer, triple_1_2_max_bit_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ signed_pair_gen, signed_pair_gen_var_6, unsigned_pair_gen_var_12, unsigned_pair_gen_var_27, unsigned_unsigned_bool_triple_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::bench::bucketers::{ pair_integer_max_bit_bucketer, pair_natural_max_bit_bucketer, triple_1_2_natural_max_bit_bucketer, triple_3_pair_integer_max_bit_bucketer, }; use malachite_nz::test_util::generators::{ integer_pair_gen_var_1, integer_pair_gen_var_1_nrm, natural_natural_bool_triple_gen_var_1, natural_pair_gen_var_5, }; use malachite_q::Rational; use num::BigRational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_from_naturals); register_demo!(runner, demo_from_naturals_ref); register_unsigned_demos!(runner, demo_from_unsigneds); register_demo!(runner, demo_from_integers); register_demo!(runner, demo_from_integers_ref); register_signed_demos!(runner, demo_from_signeds); register_demo!(runner, demo_from_sign_and_naturals); register_demo!(runner, demo_from_sign_and_naturals_ref); register_unsigned_demos!(runner, demo_from_sign_and_unsigneds); register_demo!(runner, demo_const_from_unsigneds); register_demo!(runner, demo_const_from_signeds); register_bench!(runner, benchmark_from_naturals_evaluation_strategy); register_unsigned_benches!(runner, benchmark_from_unsigneds); register_bench!(runner, benchmark_from_integers_evaluation_strategy); register_bench!(runner, benchmark_from_integers_library_comparison); register_signed_benches!(runner, benchmark_from_signeds); register_bench!(runner, benchmark_from_sign_and_naturals_evaluation_strategy); register_unsigned_benches!(runner, benchmark_from_sign_and_unsigneds); register_bench!(runner, benchmark_const_from_unsigneds); register_bench!(runner, benchmark_const_from_signeds); } fn demo_from_naturals(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in natural_pair_gen_var_5().get(gm, config).take(limit) { let n_old = n.clone(); let d_old = d.clone(); println!( "Rational::from_naturals({}, {}) = {}", n_old, d_old, Rational::from_naturals(n, d) ); } } fn demo_from_naturals_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in natural_pair_gen_var_5().get(gm, config).take(limit) { println!( "Rational::from_naturals_ref({}, {}) = {}", n, d, Rational::from_naturals_ref(&n, &d) ); } } fn demo_from_unsigneds(gm: GenMode, config: &GenConfig, limit: usize) where Natural: From, { for (n, d) in unsigned_pair_gen_var_12::() .get(gm, config) .take(limit) { println!( "Rational::from_unsigneds({}, {}) = {}", n, d, Rational::from_unsigneds(n, d) ); } } fn demo_from_integers(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in integer_pair_gen_var_1().get(gm, config).take(limit) { let n_old = n.clone(); let d_old = d.clone(); println!( "Rational::from_integers({}, {}) = {}", n_old, d_old, Rational::from_integers(n, d) ); } } fn demo_from_integers_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in integer_pair_gen_var_1().get(gm, config).take(limit) { println!( "Rational::from_naturals_ref({}, {}) = {}", n, d, Rational::from_integers_ref(&n, &d) ); } } fn demo_from_signeds(gm: GenMode, config: &GenConfig, limit: usize) where Integer: From, { for (n, d) in signed_pair_gen_var_6::().get(gm, config).take(limit) { println!( "Rational::from_signeds({}, {}) = {}", n, d, Rational::from_signeds(n, d) ); } } fn demo_from_sign_and_naturals(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d, sign) in natural_natural_bool_triple_gen_var_1() .get(gm, config) .take(limit) { let n_old = n.clone(); let d_old = d.clone(); println!( "Rational::from_sign_and_naturals({}, {}, {}) = {}", sign, n_old, d_old, Rational::from_sign_and_naturals(sign, n, d) ); } } fn demo_from_sign_and_naturals_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d, sign) in natural_natural_bool_triple_gen_var_1() .get(gm, config) .take(limit) { println!( "Rational::from_sign_and_naturals_ref({}, {}, {}) = {}", sign, n, d, Rational::from_sign_and_naturals_ref(sign, &n, &d) ); } } fn demo_from_sign_and_unsigneds(gm: GenMode, config: &GenConfig, limit: usize) where Natural: From, { for (n, d, sign) in unsigned_unsigned_bool_triple_gen_var_2::() .get(gm, config) .take(limit) { println!( "Rational::from_sign_and_unsigneds({}, {}, {}) = {}", sign, n, d, Rational::from_sign_and_unsigneds(sign, n, d) ); } } fn demo_const_from_unsigneds(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in unsigned_pair_gen_var_27().get(gm, config).take(limit) { println!( "Rational::const_from_unsigneds({}, {}) = {}", n, d, Rational::const_from_unsigneds(n, d) ); } } fn demo_const_from_signeds(gm: GenMode, config: &GenConfig, limit: usize) { for (n, d) in signed_pair_gen().get(gm, config).take(limit) { println!( "Rational::const_from_signed({}, {}) = {}", n, d, Rational::const_from_signeds(n, d) ); } } fn benchmark_from_naturals_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_naturals(Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_natural_max_bit_bucketer("n", "d"), &mut [ ("from_naturals", &mut |(n, d)| { no_out!(Rational::from_naturals(n, d)); }), ("from_naturals_ref", &mut |(n, d)| { no_out!(Rational::from_naturals_ref(&n, &d)); }), ], ); } fn benchmark_from_unsigneds( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: From, { run_benchmark( &format!("Rational::from_unsigneds({}, {})", T::NAME, T::NAME), BenchmarkType::Single, unsigned_pair_gen_var_12::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("n", "d"), &mut [("from_unsigneds", &mut |(n, d)| { no_out!(Rational::from_unsigneds(n, d)); })], ); } fn benchmark_from_integers_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_integers(Integer, Integer)", BenchmarkType::EvaluationStrategy, integer_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_integer_max_bit_bucketer("n", "d"), &mut [ ("from_integers", &mut |(n, d)| { no_out!(Rational::from_integers(n, d)); }), ("from_integers_ref", &mut |(n, d)| { no_out!(Rational::from_integers_ref(&n, &d)); }), ], ); } #[allow(unused_must_use)] fn benchmark_from_integers_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_integers(Integer, Integer)", BenchmarkType::LibraryComparison, integer_pair_gen_var_1_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_pair_integer_max_bit_bucketer("n", "d"), &mut [ ("Malachite", &mut |(_, _, (n, d))| { no_out!(Rational::from_integers(n, d)); }), ("num", &mut |((n, d), _, _)| no_out!(BigRational::new(n, d))), ("rug", &mut |(_, (n, d), _)| { no_out!(rug::Rational::from((n, d))); }), ], ); } fn benchmark_from_signeds( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Integer: From, { run_benchmark( &format!("Rational::from_signeds({}, {})", T::NAME, T::NAME), BenchmarkType::Single, signed_pair_gen_var_6::().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("n", "d"), &mut [("from_unsigneds", &mut |(n, d)| { no_out!(Rational::from_signeds(n, d)); })], ); } fn benchmark_from_sign_and_naturals_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_sign_and_naturals(bool, Natural, Natural)", BenchmarkType::EvaluationStrategy, natural_natural_bool_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_2_natural_max_bit_bucketer("n", "d"), &mut [ ("from_sign_and_naturals", &mut |(n, d, sign)| { no_out!(Rational::from_sign_and_naturals(sign, n, d)); }), ("from_sign_and_naturals_ref", &mut |(n, d, sign)| { no_out!(Rational::from_sign_and_naturals_ref(sign, &n, &d)); }), ], ); } fn benchmark_from_sign_and_unsigneds( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Natural: From, { run_benchmark( &format!( "Rational::from_sign_and_unsigneds({}, {})", T::NAME, T::NAME ), BenchmarkType::Single, unsigned_unsigned_bool_triple_gen_var_2::().get(gm, config), gm.name(), limit, file_name, &triple_1_2_max_bit_bucketer("n", "d"), &mut [("from_sign_and_unsigneds", &mut |(n, d, sign)| { no_out!(Rational::from_sign_and_unsigneds(sign, n, d)); })], ); } fn benchmark_const_from_unsigneds(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( &format!( "Rational::const_from_unsigneds({}, {})", Limb::NAME, Limb::NAME ), BenchmarkType::Single, unsigned_pair_gen_var_27().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("n", "d"), &mut [("const_from_unsigneds", &mut |(n, d)| { no_out!(Rational::const_from_unsigneds(n, d)); })], ); } fn benchmark_const_from_signeds(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( &format!( "Rational::const_from_signeds({}, {})", SignedLimb::NAME, SignedLimb::NAME ), BenchmarkType::Single, signed_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_max_bit_bucketer("n", "d"), &mut [("const_from_signeds", &mut |(n, d)| { no_out!(Rational::const_from_signeds(n, d)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::primitive_float_gen; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_convertible_from_primitive_float); register_primitive_float_demos!(runner, demo_rational_try_from_primitive_float); register_primitive_float_benches!(runner, benchmark_rational_try_from_primitive_float); register_bench!(runner, benchmark_rational_try_from_f32_library_comparison); register_bench!(runner, benchmark_rational_try_from_f64_library_comparison); register_primitive_float_benches!(runner, benchmark_rational_convertible_from_primitive_float); } fn demo_rational_try_from_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { println!( "Rational::try_from({}) = {:?}", NiceFloat(f), Rational::try_from(f) ); } } fn demo_rational_convertible_from_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: ConvertibleFrom, { for f in primitive_float_gen::().get(gm, config).take(limit) { if Rational::convertible_from(f) { println!("{} is convertible to a Rational", NiceFloat(f)); } else { println!("{} is not convertible to a Rational", NiceFloat(f)); } } } #[allow(unused_must_use)] fn benchmark_rational_try_from_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: TryFrom, { run_benchmark( &format!("Rational::try_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Rational::try_from(f)))], ); } #[allow(unused_must_use)] fn benchmark_rational_try_from_f32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::try_from(f32)", BenchmarkType::LibraryComparison, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("Malachite", &mut |f| no_out!(Rational::try_from(f))), ("rug", &mut |f| no_out!(rug::Rational::from_f32(f))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_try_from_f64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::try_from(f64)", BenchmarkType::LibraryComparison, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [ ("Malachite", &mut |f| no_out!(Rational::try_from(f))), ("rug", &mut |f| no_out!(rug::Rational::from_f64(f))), ], ); } fn benchmark_rational_convertible_from_primitive_float( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: ConvertibleFrom, { run_benchmark( &format!("Rational::convertible_from({})", T::NAME), BenchmarkType::Single, primitive_float_gen::().get(gm, config), gm.name(), limit, file_name, &primitive_float_bucketer("f"), &mut [("Malachite", &mut |f| no_out!(Rational::convertible_from(f)))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::bench::bucketers::{signed_bit_bucketer, unsigned_bit_bucketer}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_unsigned_demos!(runner, demo_rational_from_unsigned); register_signed_demos!(runner, demo_rational_from_signed); register_demo!(runner, demo_rational_const_from_unsigned); register_demo!(runner, demo_rational_const_from_signed); register_unsigned_benches!(runner, benchmark_rational_from_unsigned); register_signed_benches!(runner, benchmark_rational_from_signed); register_bench!(runner, benchmark_rational_from_u32_library_comparison); register_bench!(runner, benchmark_rational_from_u64_library_comparison); register_bench!(runner, benchmark_rational_from_i32_library_comparison); register_bench!(runner, benchmark_rational_from_i64_library_comparison); register_bench!(runner, benchmark_rational_const_from_unsigned); register_bench!(runner, benchmark_rational_const_from_signed); } fn demo_rational_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) where Rational: From, { for u in unsigned_gen::().get(gm, config).take(limit) { println!("Rational::from({}) = {}", u, Rational::from(u)); } } fn demo_rational_from_signed(gm: GenMode, config: &GenConfig, limit: usize) where Rational: From, { for i in signed_gen::().get(gm, config).take(limit) { println!("Rational::from({}) = {}", i, Rational::from(i)); } } fn demo_rational_const_from_unsigned(gm: GenMode, config: &GenConfig, limit: usize) { for u in unsigned_gen().get(gm, config).take(limit) { println!( "Rational::const_from_unsigned({}) = {}", u, Rational::const_from_unsigned(u) ); } } fn demo_rational_const_from_signed(gm: GenMode, config: &GenConfig, limit: usize) { for i in signed_gen().get(gm, config).take(limit) { println!( "Rational::const_from_signed({}) = {}", i, Rational::const_from_signed(i) ); } } #[allow(unused_must_use)] fn benchmark_rational_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: From, { run_benchmark( &format!("Rational::from({})", T::NAME), BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Rational::from(u)))], ); } #[allow(unused_must_use)] fn benchmark_rational_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: From, { run_benchmark( &format!("Rational::from({})", T::NAME), BenchmarkType::Single, signed_gen().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |u| no_out!(Rational::from(u)))], ); } #[allow(unused_must_use)] fn benchmark_rational_from_u32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(u32)", BenchmarkType::LibraryComparison, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(Rational::from(u))), ("rug", &mut |u| no_out!(rug::Rational::from(u))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_from_u64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(u64)", BenchmarkType::LibraryComparison, unsigned_gen::().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [ ("Malachite", &mut |u| no_out!(Rational::from(u))), ("rug", &mut |u| no_out!(rug::Rational::from(u))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_from_i32_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(i32)", BenchmarkType::LibraryComparison, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(Rational::from(i))), ("rug", &mut |i| no_out!(rug::Rational::from(i))), ], ); } #[allow(unused_must_use)] fn benchmark_rational_from_i64_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from(i64)", BenchmarkType::LibraryComparison, signed_gen::().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [ ("Malachite", &mut |i| no_out!(Rational::from(i))), ("rug", &mut |i| no_out!(rug::Rational::from(i))), ], ); } fn benchmark_rational_const_from_unsigned( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::const_from_unsigned(Limb)", BenchmarkType::Single, unsigned_gen().get(gm, config), gm.name(), limit, file_name, &unsigned_bit_bucketer(), &mut [("Malachite", &mut |u| { no_out!(Rational::const_from_unsigned(u)); })], ); } fn benchmark_rational_const_from_signed( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::const_from_signed(Limb)", BenchmarkType::Single, signed_gen().get(gm, config), gm.name(), limit, file_name, &signed_bit_bucketer(), &mut [("Malachite", &mut |i| { no_out!(Rational::const_from_signed(i)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/integer_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::integer::Integer; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_rounding_mode_pair_gen_var_2}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_integer_try_from_rational); register_demo!(runner, demo_integer_try_from_rational_ref); register_demo!(runner, demo_integer_convertible_from_rational); register_demo!(runner, demo_integer_rounding_from_rational); register_demo!(runner, demo_integer_rounding_from_rational_ref); register_bench!( runner, benchmark_integer_try_from_rational_evaluation_strategy ); register_bench!(runner, benchmark_integer_convertible_from_rational); register_bench!( runner, benchmark_integer_rounding_from_rational_evaluation_strategy ); } fn demo_integer_try_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { let x_clone = x.clone(); println!( "Integer::try_from({}) = {:?}", x_clone, Integer::try_from(x) ); } } fn demo_integer_try_from_rational_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("Integer::try_from(&{}) = {:?}", x, Integer::try_from(&x)); } } fn demo_integer_convertible_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Integer", x, if Integer::convertible_from(&x) { "" } else { "not " }, ); } } fn demo_integer_rounding_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in rational_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { let x_clone = x.clone(); println!( "Integer::rounding_from({}, {}) = {:?}", x_clone, rm, Integer::rounding_from(x, rm) ); } } fn demo_integer_rounding_from_rational_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in rational_rounding_mode_pair_gen_var_2() .get(gm, config) .take(limit) { println!( "Integer::rounding_from(&{}, {}) = {:?}", x, rm, Integer::rounding_from(&x, rm) ); } } fn benchmark_integer_try_from_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::try_from(Rational)", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Integer::try_from(Rational)", &mut |x| { no_out!(Integer::try_from(x).ok()); }), ("Integer::try_from(&Rational)", &mut |x| { no_out!(Integer::try_from(&x).ok()); }), ], ); } fn benchmark_integer_convertible_from_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::convertible_from(Rational)", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Integer::convertible_from(&x)))], ); } fn benchmark_integer_rounding_from_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Integer::rounding_from(Rational)", BenchmarkType::EvaluationStrategy, rational_rounding_mode_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Integer::rounding_from(Rational)", &mut |(x, rm)| { no_out!(Integer::rounding_from(x, rm)); }), ("Integer::rounding_from(&Rational)", &mut |(x, rm)| { no_out!(Integer::rounding_from(&x, rm)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::rational_bit_bucketer; use malachite_q::test_util::generators::rational_gen; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_is_integer); register_bench!(runner, benchmark_rational_is_integer); } fn demo_rational_is_integer(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { if n.is_integer() { println!("{n} is an integer"); } else { println!("{n} is not an integer"); } } } fn benchmark_rational_is_integer(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.is_integer()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(x.is_integer()))], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { clone::register(runner); continued_fraction::register(runner); digits::register(runner); from_bool::register(runner); from_float_simplest::register(runner); from_integer::register(runner); from_natural::register(runner); from_numerator_and_denominator::register(runner); from_primitive_float::register(runner); from_primitive_int::register(runner); integer_from_rational::register(runner); is_integer::register(runner); mutate_numerator_or_denominator::register(runner); natural_from_rational::register(runner); primitive_float_from_rational::register(runner); primitive_int_from_rational::register(runner); sci_mantissa_and_exponent::register(runner); serde::register(runner); string::register(runner); to_numerator_or_denominator::register(runner); } mod clone; mod continued_fraction; mod digits; mod from_bool; mod from_float_simplest; mod from_integer; mod from_natural; mod from_numerator_and_denominator; mod from_primitive_float; mod from_primitive_int; mod integer_from_rational; mod is_integer; mod mutate_numerator_or_denominator; mod natural_from_rational; mod primitive_float_from_rational; mod primitive_int_from_rational; mod sci_mantissa_and_exponent; mod serde; mod string; mod to_numerator_or_denominator; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/mutate_numerator_or_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ quadruple_1_rational_bit_bucketer, triple_1_rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_rational_natural_natural_quadruple_gen_var_1, rational_rational_natural_triple_gen, rational_rational_natural_triple_gen_var_1, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_mutate_numerator); register_demo!(runner, demo_rational_mutate_denominator); register_demo!(runner, demo_rational_mutate_numerator_and_denominator); register_bench!(runner, benchmark_rational_mutate_numerator); register_bench!(runner, benchmark_rational_mutate_denominator); register_bench!(runner, benchmark_rational_mutate_numerator_and_denominator); } fn demo_rational_mutate_numerator(gm: GenMode, config: &GenConfig, limit: usize) { for (mut q, out, new_numerator) in rational_rational_natural_triple_gen() .get(gm, config) .take(limit) { let old_q = q.clone(); let old_out = out.clone(); let old_new_numerator = new_numerator.clone(); let actual_out = q.mutate_numerator(|x| { *x = new_numerator; out }); println!( "q := {old_q}; \ q.mutate_numerator(|x| {{ *x = {old_new_numerator}; {old_out} }}) = {actual_out}; \ q = {q}", ); } } fn demo_rational_mutate_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for (mut q, out, new_denominator) in rational_rational_natural_triple_gen_var_1() .get(gm, config) .take(limit) { let old_q = q.clone(); let old_out = out.clone(); let old_new_denominator = new_denominator.clone(); let actual_out = q.mutate_denominator(|x| { *x = new_denominator; out }); println!( "q := {old_q}; \ q.mutate_denominator(|x| {{ *x = {old_new_denominator}; {old_out} }}) = {actual_out}; \ q = {q}", ); } } fn demo_rational_mutate_numerator_and_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for (mut q, out, new_numerator, new_denominator) in rational_rational_natural_natural_quadruple_gen_var_1() .get(gm, config) .take(limit) { let old_q = q.clone(); let old_out = out.clone(); let old_new_numerator = new_numerator.clone(); let old_new_denominator = new_denominator.clone(); let actual_out = q.mutate_numerator_and_denominator(|x, y| { *x = new_numerator; *y = new_denominator; out }); println!( "q := {old_q}; \ q.mutate_numerator_and_denominator(|x, y| {{ *x = {old_new_numerator}; \ *y = {old_new_denominator}; {old_out} }}) = {actual_out}; \ q = {q}", ); } } fn benchmark_rational_mutate_numerator( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mutate_numerator(FnOnce(&mut Natural) -> T)", BenchmarkType::Single, rational_rational_natural_triple_gen().get(gm, config), gm.name(), limit, file_name, &triple_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, out, new_numerator)| { no_out!(n.mutate_numerator(|x| { *x = new_numerator; out })); })], ); } fn benchmark_rational_mutate_denominator( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mutate_denominator(FnOnce(&mut Natural) -> T)", BenchmarkType::Single, rational_rational_natural_triple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &triple_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(mut n, out, new_denominator)| { no_out!(n.mutate_denominator(|x| { *x = new_denominator; out })); })], ); } fn benchmark_rational_mutate_numerator_and_denominator( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.mutate_numerator_and_denominator(FnOnce(&mut Natural, &mut Natural) -> T)", BenchmarkType::Single, rational_rational_natural_natural_quadruple_gen_var_1().get(gm, config), gm.name(), limit, file_name, &quadruple_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |( mut n, out, new_numerator, new_denominator, )| { no_out!(n.mutate_numerator_and_denominator(|x, y| { *x = new_numerator; *y = new_denominator; out })); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/natural_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_nz::natural::Natural; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_rounding_mode_pair_gen_var_1}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_natural_try_from_rational); register_demo!(runner, demo_natural_try_from_rational_ref); register_demo!(runner, demo_natural_convertible_from_rational); register_demo!(runner, demo_natural_rounding_from_rational); register_demo!(runner, demo_natural_rounding_from_rational_ref); register_bench!( runner, benchmark_natural_try_from_rational_evaluation_strategy ); register_bench!(runner, benchmark_natural_convertible_from_rational); register_bench!( runner, benchmark_natural_rounding_from_rational_evaluation_strategy ); } fn demo_natural_try_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { let x_clone = x.clone(); println!( "Natural::try_from({}) = {:?}", x_clone, Natural::try_from(x) ); } } fn demo_natural_try_from_rational_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("Natural::try_from(&{}) = {:?}", x, Natural::try_from(&x)); } } fn demo_natural_convertible_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a Natural", x, if Natural::convertible_from(&x) { "" } else { "not " }, ); } } fn demo_natural_rounding_from_rational(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in rational_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { let x_clone = x.clone(); println!( "Natural::rounding_from({}, {}) = {:?}", x_clone, rm, Natural::rounding_from(x, rm) ); } } fn demo_natural_rounding_from_rational_ref(gm: GenMode, config: &GenConfig, limit: usize) { for (x, rm) in rational_rounding_mode_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "Natural::rounding_from(&{}, {}) = {:?}", x, rm, Natural::rounding_from(&x, rm) ); } } fn benchmark_natural_try_from_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::try_from(Rational)", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Natural::try_from(Rational)", &mut |x| { no_out!(Natural::try_from(x).ok()); }), ("Natural::try_from(&Rational)", &mut |x| { no_out!(Natural::try_from(&x).ok()); }), ], ); } fn benchmark_natural_convertible_from_rational( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::convertible_from(Rational)", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(Natural::convertible_from(&x)))], ); } fn benchmark_natural_rounding_from_rational_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Natural::rounding_from(Rational)", BenchmarkType::EvaluationStrategy, rational_rounding_mode_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ("Natural::rounding_from(Rational)", &mut |(x, rm)| { no_out!(Natural::rounding_from(x, rm)); }), ("Natural::rounding_from(&Rational)", &mut |(x, rm)| { no_out!(Natural::rounding_from(&x, rm)); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/primitive_float_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, pair_2_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_gen, rational_gen_rm, rational_gen_var_4, rational_rounding_mode_pair_gen_var_5, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_float_rounding_from_rational); register_primitive_float_demos!(runner, demo_float_rounding_from_rational_ref); register_primitive_float_demos!(runner, demo_float_try_from_rational); register_primitive_float_demos!(runner, demo_float_try_from_rational_ref); register_primitive_float_demos!(runner, demo_float_exact_from_rational); register_primitive_float_demos!(runner, demo_float_exact_from_rational_ref); register_primitive_float_demos!(runner, demo_float_convertible_from_rational); register_primitive_float_demos!(runner, demo_float_convertible_from_rational_ref); register_primitive_float_benches!( runner, benchmark_float_rounding_from_rational_evaluation_strategy ); register_bench!( runner, benchmark_f32_rounding_from_down_rational_library_comparison ); register_bench!( runner, benchmark_f64_rounding_from_down_rational_library_comparison ); register_primitive_float_benches!( runner, benchmark_float_try_from_rational_evaluation_strategy ); register_primitive_float_benches!( runner, benchmark_float_exact_from_rational_evaluation_strategy ); register_primitive_float_benches!( runner, benchmark_float_convertible_from_rational_evaluation_strategy ); } fn demo_float_rounding_from_rational< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat + RoundingFrom, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for (n, rm) in rational_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { let (f, o) = T::rounding_from(n.clone(), rm); println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, n, rm, (NiceFloat(f), o) ); } } fn demo_float_rounding_from_rational_ref< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat + for<'a> RoundingFrom<&'a Rational>, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for (n, rm) in rational_rounding_mode_pair_gen_var_5::() .get(gm, config) .take(limit) { let (f, o) = T::rounding_from(&n, rm); println!( "{}::rounding_from(&{}, {}) = {:?}", T::NAME, n, rm, (NiceFloat(f), o) ); } } fn demo_float_try_from_rational< T: TryFrom + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in rational_gen().get(gm, config).take(limit) { println!( "{}::try_from({}) = {:?}", T::NAME, n.clone(), T::try_from(n).map(NiceFloat) ); } } fn demo_float_try_from_rational_ref< T: for<'a> TryFrom<&'a Rational, Error = FloatConversionError> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in rational_gen().get(gm, config).take(limit) { println!( "{}::try_from(&{}) = {:?}", T::NAME, n, T::try_from(&n).map(NiceFloat) ); } } fn demo_float_exact_from_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for n in rational_gen_var_4::().get(gm, config).take(limit) { println!( "{}::exact_from({}) = {}", T::NAME, n.clone(), NiceFloat(T::exact_from(n)) ); } } fn demo_float_exact_from_rational_ref ExactFrom<&'a Rational> + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: TryFrom, { for n in rational_gen_var_4::().get(gm, config).take(limit) { println!( "{}::exact_from(&{}) = {}", T::NAME, n, NiceFloat(T::exact_from(&n)) ); } } fn demo_float_convertible_from_rational + PrimitiveFloat>( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in rational_gen().get(gm, config).take(limit) { let n_old = n.clone(); if T::convertible_from(n) { println!("{} is convertible to an {}", n_old, T::NAME); } else { println!("{} is not convertible to an {}", n_old, T::NAME); } } } fn demo_float_convertible_from_rational_ref< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for n in rational_gen().get(gm, config).take(limit) { if T::convertible_from(&n) { println!("{} is convertible to an {}", n, T::NAME); } else { println!("{} is not convertible to an {}", n, T::NAME); } } } fn benchmark_float_rounding_from_rational_evaluation_strategy< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat + RoundingFrom + for<'a> RoundingFrom<&'a Rational>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: TryFrom, { run_benchmark( &format!("{}::rounding_from(Rational, RoundingMode)", T::NAME), BenchmarkType::EvaluationStrategy, rational_rounding_mode_pair_gen_var_5::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [ ( &format!("{}::rounding_from(Rational, RoundingMode)", T::NAME), &mut |(n, rm)| no_out!(T::rounding_from(n, rm)), ), ( &format!("{}::rounding_from(&Rational, RoundingMode)", T::NAME), &mut |(n, rm)| no_out!(T::rounding_from(&n, rm)), ), ], ); } fn benchmark_f32_rounding_from_down_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "f32::rounding_from(Rational, Down)", BenchmarkType::LibraryComparison, rational_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| { no_out!(f32::rounding_from(n, Down)); }), ("rug", &mut |(n, _)| no_out!(n.to_f32())), ], ); } fn benchmark_f64_rounding_from_down_rational_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "f64::rounding_from(Rational, Down)", BenchmarkType::LibraryComparison, rational_gen_rm().get(gm, config), gm.name(), limit, file_name, &pair_2_rational_bit_bucketer("n"), &mut [ ("Malachite", &mut |(_, n)| { no_out!(f64::rounding_from(n, Down)); }), ("rug", &mut |(n, _)| no_out!(n.to_f64())), ], ); } fn benchmark_float_try_from_rational_evaluation_strategy< T: TryFrom + for<'a> TryFrom<&'a Rational> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(Rational)", T::NAME), BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("n"), &mut [ (&format!("{}::try_from(Rational)", T::NAME), &mut |n| { no_out!(T::try_from(n).ok()); }), (&format!("{}::try_from(&Rational)", T::NAME), &mut |n| { no_out!(T::try_from(&n).ok()); }), ], ); } fn benchmark_float_exact_from_rational_evaluation_strategy< T: ExactFrom + for<'a> ExactFrom<&'a Rational> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: TryFrom, { run_benchmark( &format!("{}::exact_from(Rational)", T::NAME), BenchmarkType::EvaluationStrategy, rational_gen_var_4::().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("n"), &mut [ (&format!("{}::exact_from(Rational)", T::NAME), &mut |n| { no_out!(T::exact_from(n)); }), (&format!("{}::exact_from(&Rational)", T::NAME), &mut |n| { no_out!(T::exact_from(&n)); }), ], ); } fn benchmark_float_convertible_from_rational_evaluation_strategy< T: ConvertibleFrom + for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(Rational)", T::NAME), BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("n"), &mut [ ( &format!("{}::convertible_from(Rational)", T::NAME), &mut |n| no_out!(T::convertible_from(n)), ), ( &format!("{}::convertible_from(&Rational)", T::NAME), &mut |n| no_out!(T::convertible_from(&n)), ), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/primitive_int_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_rounding_mode_pair_gen_var_3}; use std::fmt::Debug; pub(crate) fn register(runner: &mut Runner) { register_primitive_int_demos!(runner, demo_primitive_int_try_from_rational); register_primitive_int_demos!(runner, demo_primitive_int_convertible_from_rational); register_primitive_int_demos!(runner, demo_primitive_int_rounding_from_rational); register_primitive_int_benches!(runner, benchmark_primitive_int_try_from_rational); register_primitive_int_benches!(runner, benchmark_primitive_int_convertible_from_rational); register_primitive_int_benches!(runner, benchmark_primitive_int_rounding_from_rational); } fn demo_primitive_int_try_from_rational TryFrom<&'a Rational> + PrimitiveInt>( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> >::Error: Debug, { for x in rational_gen().get(gm, config).take(limit) { println!("{}::try_from({}) = {:?}", T::NAME, x, T::try_from(&x)); } } fn demo_primitive_int_convertible_from_rational< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, ) { for x in rational_gen().get(gm, config).take(limit) { println!( "{} is {}convertible to a {}", x, if T::convertible_from(&x) { "" } else { "not " }, T::NAME ); } } fn demo_primitive_int_rounding_from_rational< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt + for<'a> RoundingFrom<&'a Rational>, >( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: PartialOrd, { for (x, rm) in rational_rounding_mode_pair_gen_var_3::() .get(gm, config) .take(limit) { println!( "{}::rounding_from({}, {}) = {:?}", T::NAME, x, rm, T::rounding_from(&x, rm) ); } } fn benchmark_primitive_int_try_from_rational TryFrom<&'a Rational> + PrimitiveInt>( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::try_from(Rational)", T::NAME), BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::try_from(&x).ok()))], ); } fn benchmark_primitive_int_convertible_from_rational< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( &format!("{}::convertible_from(Rational)", T::NAME), BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [("Malachite", &mut |x| no_out!(T::convertible_from(&x)))], ); } fn benchmark_primitive_int_rounding_from_rational< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt + for<'a> RoundingFrom<&'a Rational>, >( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: PartialOrd, { run_benchmark( &format!("{}::rounding_from(Rational)", T::NAME), BenchmarkType::Single, rational_rounding_mode_pair_gen_var_3::().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(x, rm)| { no_out!(T::rounding_from(&x, rm)); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::SciMantissaAndExponent; use malachite_base::num::float::NiceFloat; use malachite_base::test_util::bench::bucketers::pair_1_primitive_float_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ primitive_float_signed_pair_gen_var_1, primitive_float_signed_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_gen_var_1, rational_rounding_mode_pair_gen_var_4, }; pub(crate) fn register(runner: &mut Runner) { register_primitive_float_demos!(runner, demo_rational_sci_mantissa_and_exponent); register_primitive_float_demos!(runner, demo_rational_sci_mantissa_and_exponent_ref); register_primitive_float_demos!(runner, demo_rational_sci_mantissa); register_primitive_float_demos!(runner, demo_rational_sci_mantissa_ref); register_primitive_float_demos!(runner, demo_rational_sci_exponent); register_primitive_float_demos!(runner, demo_rational_sci_exponent_ref); register_primitive_float_demos!(runner, demo_rational_sci_mantissa_and_exponent_round); register_primitive_float_demos!(runner, demo_rational_sci_mantissa_and_exponent_round_ref); register_primitive_float_demos!(runner, demo_rational_from_sci_mantissa_and_exponent); register_primitive_float_demos!( runner, demo_rational_from_sci_mantissa_and_exponent_targeted ); register_primitive_float_benches!( runner, benchmark_rational_sci_mantissa_and_exponent_evaluation_strategy ); register_primitive_float_benches!( runner, benchmark_rational_sci_mantissa_and_exponent_round_evaluation_strategy ); register_primitive_float_benches!(runner, benchmark_rational_from_sci_mantissa_and_exponent); } fn demo_rational_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) where Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { let n_old = n.clone(); let (mantissa, exponent) = n.sci_mantissa_and_exponent(); println!( "sci_mantissa_and_exponent({}) = {:?}", n_old, (NiceFloat(mantissa), exponent) ); } } fn demo_rational_sci_mantissa_and_exponent_ref( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { let (mantissa, exponent) = (&n).sci_mantissa_and_exponent(); println!( "sci_mantissa_and_exponent(&{}) = {:?}", n, (NiceFloat(mantissa), exponent) ); } } fn demo_rational_sci_mantissa(gm: GenMode, config: &GenConfig, limit: usize) where Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { let n_old = n.clone(); println!("sci_mantissa({}) = {}", n_old, NiceFloat(n.sci_mantissa())); } } fn demo_rational_sci_mantissa_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { println!("sci_mantissa({}) = {}", n, NiceFloat((&n).sci_mantissa())); } } fn demo_rational_sci_exponent(gm: GenMode, config: &GenConfig, limit: usize) where Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { let n_old = n.clone(); println!("sci_exponent({}) = {}", n_old, n.sci_exponent()); } } fn demo_rational_sci_exponent_ref(gm: GenMode, config: &GenConfig, limit: usize) where for<'a> &'a Rational: SciMantissaAndExponent, { for n in rational_gen_var_1().get(gm, config).take(limit) { println!("sci_exponent({}) = {}", n, (&n).sci_exponent()); } } fn demo_rational_sci_mantissa_and_exponent_round( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in rational_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { let n_old = n.clone(); println!( "sci_mantissa_and_exponent_round({}, {}) = {:?}", n_old, rm, n.sci_mantissa_and_exponent_round::(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)) ); } } fn demo_rational_sci_mantissa_and_exponent_round_ref( gm: GenMode, config: &GenConfig, limit: usize, ) { for (n, rm) in rational_rounding_mode_pair_gen_var_4() .get(gm, config) .take(limit) { println!( "sci_mantissa_and_exponent_round({}, {}) = {:?}", n, rm, n.sci_mantissa_and_exponent_round_ref::(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)) ); } } fn demo_rational_from_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Rational: SciMantissaAndExponent, { for (m, e) in primitive_float_signed_pair_gen_var_1::() .get(gm, config) .take(limit) { println!( "Rational::from_sci_mantissa_and_exponent({}, {}) = {:?}", NiceFloat(m), e, <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) ); } } fn demo_rational_from_sci_mantissa_and_exponent_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) where for<'a> &'a Rational: SciMantissaAndExponent, { for (m, e) in primitive_float_signed_pair_gen_var_2::() .get(gm, config) .take(limit) { println!( "Rational::from_sci_mantissa_and_exponent({}, {}) = {:?}", NiceFloat(m), e, <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) ); } } fn benchmark_rational_sci_mantissa_and_exponent_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where Rational: SciMantissaAndExponent, for<'a> &'a Rational: SciMantissaAndExponent, { run_benchmark( "Rational.sci_mantissa_and_exponent()", BenchmarkType::EvaluationStrategy, rational_gen_var_1().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("Rational.sci_mantissa_and_exponent()", &mut |n| { no_out!(n.sci_mantissa_and_exponent()); }), ("(&Rational).sci_mantissa_and_exponent()", &mut |n| { no_out!((&n).sci_mantissa_and_exponent()); }), ], ); } fn benchmark_rational_sci_mantissa_and_exponent_round_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.sci_mantissa_and_exponent_round(RoundingMode)", BenchmarkType::EvaluationStrategy, rational_rounding_mode_pair_gen_var_4().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [ ( "Rational.sci_mantissa_and_exponent_round(RoundingMode)", &mut |(n, rm)| no_out!(n.sci_mantissa_and_exponent_round::(rm)), ), ( "Rational.sci_mantissa_and_exponent_round_ref(RoundingMode)", &mut |(n, rm)| no_out!(n.sci_mantissa_and_exponent_round_ref::(rm)), ), ], ); } fn benchmark_rational_from_sci_mantissa_and_exponent( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) where for<'a> &'a Rational: SciMantissaAndExponent, { run_benchmark( &format!("Rational::from_sci_mantissa_and_exponent({}, u64)", T::NAME), BenchmarkType::Single, primitive_float_signed_pair_gen_var_1::().get(gm, config), gm.name(), limit, file_name, &pair_1_primitive_float_bucketer("mantissa"), &mut [("Malachite", &mut |(m, e)| { no_out!( <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( m, e ) ); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::string_gen; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::bench::bucketers::{ rational_deserialize_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_gen, rational_gen_nrm, string_gen_var_11, string_triple_gen_var_3, }; use num::BigRational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_serialize_json); register_demo!(runner, demo_rational_deserialize_json); register_demo!(runner, demo_rational_deserialize_json_targeted); register_bench!(runner, benchmark_rational_serialize_json_library_comparison); register_bench!(runner, benchmark_rational_deserialize_json); register_bench!( runner, benchmark_rational_deserialize_json_library_comparison ); } fn demo_rational_serialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for n in rational_gen().get(gm, config).take(limit) { println!( "serde_json::to_string({}) = {}", n, serde_json::to_string(&n).unwrap() ); } } fn demo_rational_deserialize_json(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { let n: Result = serde_json::from_str(&s); println!("serde_json::from_str({s}) = {n:?}"); } } fn demo_rational_deserialize_json_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_11().get(gm, config).take(limit) { let n: Rational = serde_json::from_str(&s).unwrap(); println!("serde_json::from_str({s}) = {n}"); } } fn benchmark_rational_serialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::to_string(&Rational)", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("num", &mut |(x, _, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ("rug", &mut |(_, x, _)| { no_out!(serde_json::to_string(&x).unwrap()); }), ], ); } fn benchmark_rational_deserialize_json( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::Single, string_gen().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| { let _n: Rational = serde_json::from_str(&s).unwrap(); })], ); } fn benchmark_rational_deserialize_json_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "serde_json::from_str(&str)", BenchmarkType::LibraryComparison, string_triple_gen_var_3().get(gm, config), gm.name(), limit, file_name, &rational_deserialize_bucketer(), &mut [ ("Malachite", &mut |(_, _, s)| { let _n: Rational = serde_json::from_str(&s).unwrap(); }), ("num", &mut |(s, _, _)| { let _n: BigRational = serde_json::from_str(&s).unwrap(); }), ("rug", &mut |(_, s, _)| { let _n: rug::Rational = serde_json::from_str(&s).unwrap(); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::FromSciString; use malachite_base::test_util::bench::bucketers::{ pair_1_string_len_bucketer, string_len_bucketer, }; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::{ string_gen_var_14, string_gen_var_15, string_unsigned_pair_gen_var_1, string_unsigned_pair_gen_var_2, }; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_sci_string); register_demo!(runner, demo_rational_from_sci_string_targeted); register_demo!(runner, demo_rational_from_sci_string_with_options); register_demo!(runner, demo_rational_from_sci_string_with_options_targeted); register_demo!(runner, demo_rational_from_sci_string_simplest); register_demo!(runner, demo_rational_from_sci_string_simplest_targeted); register_demo!(runner, demo_rational_from_sci_string_simplest_with_options); register_demo!( runner, demo_rational_from_sci_string_simplest_with_options_targeted ); register_bench!(runner, benchmark_rational_from_sci_string); register_bench!(runner, benchmark_rational_from_sci_string_with_options); register_bench!(runner, benchmark_rational_from_sci_string_simplest); register_bench!( runner, benchmark_rational_from_sci_string_simplest_with_options ); } fn demo_rational_from_sci_string(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_14().get(gm, config).take(limit) { println!( "Rational::from_sci_string({}) = {:?}", s, Rational::from_sci_string(&s) ); } } fn demo_rational_from_sci_string_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_15().get(gm, config).take(limit) { println!( "Rational::from_sci_string({}) = {:?}", s, Rational::from_sci_string(&s) ); } } fn demo_rational_from_sci_string_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (s, base) in string_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let mut options = FromSciStringOptions::default(); options.set_base(base); println!( "Rational::from_sci_string({}, {}) = {:?}", s, base, Rational::from_sci_string_with_options(&s, options) ); } } fn demo_rational_from_sci_string_with_options_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, base) in string_unsigned_pair_gen_var_2().get(gm, config).take(limit) { let mut options = FromSciStringOptions::default(); options.set_base(base); println!( "Rational::from_sci_string({}, {}) = {:?}", s, base, Rational::from_sci_string_with_options(&s, options) ); } } fn demo_rational_from_sci_string_simplest(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_14().get(gm, config).take(limit) { println!( "Rational::from_sci_string_simplest({}) = {:?}", s, Rational::from_sci_string_simplest(&s) ); } } fn demo_rational_from_sci_string_simplest_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_15().get(gm, config).take(limit) { println!( "Rational::from_sci_string_simplest({}) = {:?}", s, Rational::from_sci_string_simplest(&s) ); } } fn demo_rational_from_sci_string_simplest_with_options( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, base) in string_unsigned_pair_gen_var_1().get(gm, config).take(limit) { let mut options = FromSciStringOptions::default(); options.set_base(base); println!( "Rational::from_sci_string_simplest({}, {}) = {:?}", s, base, Rational::from_sci_string_simplest_with_options(&s, options) ); } } fn demo_rational_from_sci_string_simplest_with_options_targeted( gm: GenMode, config: &GenConfig, limit: usize, ) { for (s, base) in string_unsigned_pair_gen_var_2().get(gm, config).take(limit) { let mut options = FromSciStringOptions::default(); options.set_base(base); println!( "Rational::from_sci_string_simplest({}, {}) = {:?}", s, base, Rational::from_sci_string_simplest_with_options(&s, options) ); } } fn benchmark_rational_from_sci_string( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_sci_string(&str)", BenchmarkType::Single, string_gen_var_15().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| no_out!(Rational::from_sci_string(&s)))], ); } fn benchmark_rational_from_sci_string_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_sci_string_with_options(&str, FromSciStrOptions)", BenchmarkType::Single, string_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_string_len_bucketer("s"), &mut [("Malachite", &mut |(s, base)| { no_out!({ let mut options = FromSciStringOptions::default(); options.set_base(base); Rational::from_sci_string_with_options(&s, options) }); })], ); } fn benchmark_rational_from_sci_string_simplest( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_sci_string_simplest(&str)", BenchmarkType::Single, string_gen_var_15().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [("Malachite", &mut |s| { no_out!(Rational::from_sci_string_simplest(&s)); })], ); } fn benchmark_rational_from_sci_string_simplest_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_sci_string_simplest_with_options(&str, FromSciStrOptions)", BenchmarkType::Single, string_unsigned_pair_gen_var_2().get(gm, config), gm.name(), limit, file_name, &pair_1_string_len_bucketer("s"), &mut [("Malachite", &mut |(s, base)| { no_out!({ let mut options = FromSciStringOptions::default(); options.set_base(base); Rational::from_sci_string_simplest_with_options(&s, options) }); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::bucketers::string_len_bucketer; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::generators::string_gen; use malachite_base::test_util::runner::Runner; use malachite_q::Rational; use malachite_q::test_util::generators::string_gen_var_12; use num::BigRational; use std::str::FromStr; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_from_str); register_demo!(runner, demo_rational_from_str_targeted); register_bench!(runner, benchmark_rational_from_str_library_comparison); } fn demo_rational_from_str(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen().get(gm, config).take(limit) { println!("Rational::from_str({}) = {:?}", s, Rational::from_str(&s)); } } fn demo_rational_from_str_targeted(gm: GenMode, config: &GenConfig, limit: usize) { for s in string_gen_var_12().get(gm, config).take(limit) { println!( "Rational::from_str({}) = {}", s, Rational::from_str(&s).unwrap() ); } } fn benchmark_rational_from_str_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational::from_str(&str)", BenchmarkType::LibraryComparison, string_gen_var_12().get(gm, config), gm.name(), limit, file_name, &string_len_bucketer(), &mut [ ("Malachite", &mut |s| { no_out!(Rational::from_str(&s).unwrap()); }), ("num", &mut |s| no_out!(BigRational::from_str(&s).unwrap())), ("rug", &mut |s| { no_out!(rug::Rational::from_str(&s).unwrap()); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/string/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { from_sci_string::register(runner); from_string::register(runner); to_sci::register(runner); to_string::register(runner); } mod from_sci_string; mod from_string; mod to_sci; mod to_string; ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::ToSci; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ pair_1_rational_bit_bucketer, rational_bit_bucketer, }; use malachite_q::test_util::generators::{ rational_gen, rational_to_sci_options_pair_gen, rational_to_sci_options_pair_gen_var_1, rational_unsigned_pair_gen_var_5, }; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_length_after_point_in_small_base); register_demo!(runner, demo_rational_to_sci); register_demo!(runner, demo_rational_fmt_sci_valid); register_demo!(runner, demo_rational_to_sci_with_options); register_bench!(runner, benchmark_length_after_point_in_small_base); register_bench!(runner, benchmark_rational_to_sci); register_bench!(runner, benchmark_rational_fmt_sci_valid); register_bench!(runner, benchmark_rational_to_sci_with_options); } fn demo_length_after_point_in_small_base(gm: GenMode, config: &GenConfig, limit: usize) { for (q, base) in rational_unsigned_pair_gen_var_5() .get(gm, config) .take(limit) { println!( "length_after_point_in_small_base({}, {}) = {:?}", q, base, q.length_after_point_in_small_base(base) ); } } fn demo_rational_to_sci(gm: GenMode, config: &GenConfig, limit: usize) { for q in rational_gen().get(gm, config).take(limit) { println!("{}.to_sci() = {}", q, q.to_sci()); } } fn demo_rational_fmt_sci_valid(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in rational_to_sci_options_pair_gen() .get(gm, config) .take(limit) { if x.fmt_sci_valid(options) { println!("{x} can be converted to sci using {options:?}"); } else { println!("{x} cannot be converted to sci using {options:?}"); } } } fn demo_rational_to_sci_with_options(gm: GenMode, config: &GenConfig, limit: usize) { for (x, options) in rational_to_sci_options_pair_gen_var_1() .get(gm, config) .take(limit) { println!( "to_sci_with_options({}, {:?}) = {}", x, options, x.to_sci_with_options(options) ); } } fn benchmark_length_after_point_in_small_base( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.length_after_point_in_small_base(u8)", BenchmarkType::Single, rational_unsigned_pair_gen_var_5().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("x"), &mut [("Malachite", &mut |(q, base)| { no_out!(q.length_after_point_in_small_base(base)); })], ); } fn benchmark_rational_to_sci(gm: GenMode, config: &GenConfig, limit: usize, file_name: &str) { run_benchmark( "Rational.to_sci()", BenchmarkType::Single, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("q"), &mut [("Malachite", &mut |q| no_out!(q.to_sci().to_string()))], ); } fn benchmark_rational_fmt_sci_valid( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.fmt_sci_valid(ToSciOptions)", BenchmarkType::Single, rational_to_sci_options_pair_gen().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.fmt_sci_valid(options)); })], ); } fn benchmark_rational_to_sci_with_options( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_sci_with_options(ToSciOptions)", BenchmarkType::Single, rational_to_sci_options_pair_gen_var_1().get(gm, config), gm.name(), limit, file_name, &pair_1_rational_bit_bucketer("n"), &mut [("Malachite", &mut |(x, options)| { no_out!(x.to_sci_with_options(options).to_string()); })], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToDebugString; use malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::triple_3_rational_bit_bucketer; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_rational_to_string); register_demo!(runner, demo_rational_to_debug_string); register_bench!(runner, benchmark_rational_to_string_library_comparison); register_bench!( runner, benchmark_rational_to_debug_string_library_comparison ); } fn demo_rational_to_string(gm: GenMode, config: &GenConfig, limit: usize) { for q in rational_gen().get(gm, config).take(limit) { println!("{q}"); } } fn demo_rational_to_debug_string(gm: GenMode, config: &GenConfig, limit: usize) { for q in rational_gen().get(gm, config).take(limit) { println!("{q:?}"); } } fn benchmark_rational_to_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_string()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_string())), ("num", &mut |(x, _, _)| no_out!(x.to_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_string())), ], ); } fn benchmark_rational_to_debug_string_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_debug_string()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_debug_string())), ("num", &mut |(x, _, _)| no_out!(x.to_debug_string())), ("rug", &mut |(_, x, _)| no_out!(x.to_debug_string())), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/conversion/to_numerator_or_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::bench::{BenchmarkType, run_benchmark}; use malachite_base::test_util::generators::common::{GenConfig, GenMode}; use malachite_base::test_util::runner::Runner; use malachite_q::test_util::bench::bucketers::{ rational_bit_bucketer, triple_3_rational_bit_bucketer, }; use malachite_q::test_util::generators::{rational_gen, rational_gen_nrm}; pub(crate) fn register(runner: &mut Runner) { register_demo!(runner, demo_to_numerator); register_demo!(runner, demo_into_numerator); register_demo!(runner, demo_numerator_ref); register_demo!(runner, demo_to_denominator); register_demo!(runner, demo_into_denominator); register_demo!(runner, demo_denominator_ref); register_demo!(runner, demo_to_numerator_and_denominator); register_demo!(runner, demo_into_numerator_and_denominator); register_demo!(runner, demo_numerator_and_denominator_ref); register_bench!(runner, benchmark_to_numerator_evaluation_strategy); register_bench!(runner, benchmark_to_numerator_library_comparison); register_bench!(runner, benchmark_to_denominator_evaluation_strategy); register_bench!(runner, benchmark_to_denominator_library_comparison); register_bench!( runner, benchmark_to_numerator_and_denominator_evaluation_strategy ); } fn demo_to_numerator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("to_numerator({}) = {}", x, x.to_numerator()); } } fn demo_into_numerator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { let old_x = x.clone(); println!("into_numerator({}) = {}", old_x, x.into_numerator()); } } fn demo_numerator_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("numerator_ref({}) = {}", x, x.numerator_ref()); } } fn demo_to_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("to_denominator({}) = {}", x, x.to_denominator()); } } fn demo_into_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { let old_x = x.clone(); println!("into_denominator({}) = {}", old_x, x.into_denominator()); } } fn demo_denominator_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!("denominator_ref({}) = {}", x, x.denominator_ref()); } } fn demo_to_numerator_and_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "to_numerator_and_denominator({}) = {:?}", x, x.to_numerator_and_denominator() ); } } fn demo_into_numerator_and_denominator(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { let old_x = x.clone(); println!( "into_numerator_and_denominator({}) = {:?}", old_x, x.into_numerator_and_denominator() ); } } fn demo_numerator_and_denominator_ref(gm: GenMode, config: &GenConfig, limit: usize) { for x in rational_gen().get(gm, config).take(limit) { println!( "numerator_and_denominator_ref({}) = {:?}", x, x.numerator_and_denominator_ref() ); } } fn benchmark_to_numerator_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_numerator()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("to_numerator", &mut |x| no_out!(x.to_numerator())), ("into_numerator", &mut |x| no_out!(x.into_numerator())), ("numerator_ref", &mut |x| no_out!(x.numerator_ref())), ], ); } fn benchmark_to_numerator_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_numerator()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_numerator())), ("num", &mut |(x, _, _)| no_out!(x.numer())), ("rug", &mut |(_, x, _)| no_out!(x.numer())), ], ); } fn benchmark_to_denominator_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_denominator()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("to_denominator", &mut |x| no_out!(x.to_denominator())), ("into_denominator", &mut |x| no_out!(x.into_denominator())), ("denominator_ref", &mut |x| no_out!(x.denominator_ref())), ], ); } fn benchmark_to_denominator_library_comparison( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_denominator()", BenchmarkType::LibraryComparison, rational_gen_nrm().get(gm, config), gm.name(), limit, file_name, &triple_3_rational_bit_bucketer("x"), &mut [ ("Malachite", &mut |(_, _, x)| no_out!(x.to_denominator())), ("num", &mut |(x, _, _)| no_out!(x.denom())), ("rug", &mut |(_, x, _)| no_out!(x.denom())), ], ); } fn benchmark_to_numerator_and_denominator_evaluation_strategy( gm: GenMode, config: &GenConfig, limit: usize, file_name: &str, ) { run_benchmark( "Rational.to_numerator_and_denominator()", BenchmarkType::EvaluationStrategy, rational_gen().get(gm, config), gm.name(), limit, file_name, &rational_bit_bucketer("x"), &mut [ ("to_numerator_and_denominator", &mut |x| { no_out!(x.to_numerator_and_denominator()); }), ("into_numerator_and_denominator", &mut |x| { no_out!(x.into_numerator_and_denominator()); }), ("numerator_and_denominator_ref", &mut |x| { no_out!(x.numerator_and_denominator_ref()); }), ], ); } ================================================ FILE: malachite-q/src/bin_util/demo_and_bench/mod.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::runner::Runner; pub(crate) fn register(runner: &mut Runner) { arithmetic::register(runner); basic::register(runner); comparison::register(runner); conversion::register(runner); } mod arithmetic; mod basic; mod comparison; mod conversion; ================================================ FILE: malachite-q/src/comparison/cmp.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; impl PartialOrd for Rational { /// Compares two [`Rational`]s. /// /// See the documentation for the [`Ord`] implementation. #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Rational { /// Compares two [`Rational`]s. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert!(Rational::from_str("2/3").unwrap() > Rational::ONE_HALF); /// assert!(Rational::from_str("-2/3").unwrap() < Rational::ONE_HALF); /// ``` fn cmp(&self, other: &Self) -> Ordering { if core::ptr::eq(self, other) { return Equal; } // First check signs let self_sign = self.sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return sign_cmp; } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.numerator.cmp(&other.denominator); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return if self.sign { one_cmp } else { one_cmp.reverse() }; } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(&other.numerator); let d_cmp = self.denominator.cmp(&other.denominator); if n_cmp == Equal && d_cmp == Equal { return Equal; } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return if self.sign { nd_cmp } else { nd_cmp.reverse() }; } // Then compare floor ∘ log_2 ∘ abs let log_cmp = self .floor_log_base_2_abs() .cmp(&other.floor_log_base_2_abs()); if log_cmp != Equal { return if self.sign { log_cmp } else { log_cmp.reverse() }; } // Finally, cross-multiply. let prod_cmp = (&self.numerator * &other.denominator).cmp(&(&self.denominator * &other.numerator)); if self.sign { prod_cmp } else { prod_cmp.reverse() } } } ================================================ FILE: malachite-q/src/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; impl PartialOrdAbs for Rational { /// Compares the absolute values of two [`Rational`]s. /// /// See the documentation for the [`OrdAbs`] implementation. #[inline] fn partial_cmp_abs(&self, other: &Self) -> Option { Some(self.cmp_abs(other)) } } impl OrdAbs for Rational { /// Compares the absolute values of two [`Rational`]s. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::comparison::traits::OrdAbs; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// use std::str::FromStr; /// /// assert_eq!( /// Rational::from_str("2/3") /// .unwrap() /// .cmp_abs(&Rational::ONE_HALF), /// Greater /// ); /// assert_eq!( /// Rational::from_str("-2/3") /// .unwrap() /// .cmp_abs(&Rational::ONE_HALF), /// Greater /// ); /// ``` fn cmp_abs(&self, other: &Self) -> Ordering { if core::ptr::eq(self, other) { return Equal; } // First check if either value is zero let self_sign = self.numerator_ref().sign(); let other_sign = other.numerator_ref().sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return sign_cmp; } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.numerator.cmp(&other.denominator); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return one_cmp; } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(&other.numerator); let d_cmp = self.denominator.cmp(&other.denominator); if n_cmp == Equal && d_cmp == Equal { return Equal; } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return nd_cmp; } // Then compare floor ∘ log_2 ∘ abs let log_cmp = self .floor_log_base_2_abs() .cmp(&other.floor_log_base_2_abs()); if log_cmp != Equal { return log_cmp; } // Finally, cross-multiply. (&self.numerator * &other.denominator).cmp(&(&self.denominator * &other.numerator)) } } ================================================ FILE: malachite-q/src/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::comparison::traits::EqAbs; impl EqAbs for Rational { /// Determines whether the absolute values of two [`Rational`]s are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Rational::from_signeds(-23, 7)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Rational::from_signeds(-24, 7)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Rational::from_signeds(22, 7)), /// true /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Rational::from_signeds(-22, 7)), /// true /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Rational::from_signeds(22, 7)), /// true /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Rational::from_signeds(-22, 7)), /// true /// ); /// ``` #[inline] fn eq_abs(&self, other: &Self) -> bool { self.numerator == other.numerator && self.denominator == other.denominator } } ================================================ FILE: malachite-q/src/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::integer::Integer; impl EqAbs for Rational { /// Determines whether the absolute values of a [`Rational`] and an [`Integer`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(122)), false); /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(124)), false); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(123)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Integer::from(123)), /// false /// ); /// assert_eq!(Rational::from(123).eq_abs(&Integer::from(123)), true); /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(123)), true); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(123)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(123)), /// false /// ); /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(-122)), false); /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(-124)), false); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(-123)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Integer::from(1 - 23)), /// false /// ); /// assert_eq!(Rational::from(123).eq_abs(&Integer::from(-123)), true); /// assert_eq!(Rational::from(-123).eq_abs(&Integer::from(-123)), true); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(-123)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Integer::from(-123)), /// false /// ); /// ``` #[inline] fn eq_abs(&self, other: &Integer) -> bool { self.denominator == 1 && self.numerator == *other.unsigned_abs_ref() } } impl EqAbs for Integer { /// Determines whether the absolute values of a [`Rational`] and an [`Integer`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!(Integer::from(122).eq_abs(&Rational::from(-123)), false); /// assert_eq!(Integer::from(124).eq_abs(&Rational::from(-123)), false); /// assert_eq!( /// Integer::from(124).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Integer::from(124).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// assert_eq!(Integer::from(123).eq_abs(&Rational::from(123)), true); /// assert_eq!(Integer::from(123).eq_abs(&Rational::from(-123)), true); /// assert_eq!( /// Integer::from(123).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Integer::from(123).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// assert_eq!(Integer::from(-122).eq_abs(&Rational::from(-123)), false); /// assert_eq!(Integer::from(-124).eq_abs(&Rational::from(-123)), false); /// assert_eq!( /// Integer::from(-124).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Integer::from(-124).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// assert_eq!(Integer::from(-123).eq_abs(&Rational::from(123)), true); /// assert_eq!(Integer::from(-123).eq_abs(&Rational::from(-123)), true); /// assert_eq!( /// Integer::from(-123).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Integer::from(-123).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// ``` #[inline] fn eq_abs(&self, other: &Rational) -> bool { other.denominator == 1 && other.numerator == *self.unsigned_abs_ref() } } ================================================ FILE: malachite-q/src/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::natural::Natural; impl EqAbs for Rational { /// Determines whether the absolute values of a [`Rational`] and a [`Natural`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(-123).eq_abs(&Natural::from(122u32)), false); /// assert_eq!(Rational::from(-123).eq_abs(&Natural::from(124u32)), false); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Natural::from(123u32)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).eq_abs(&Natural::from(123u32)), /// false /// ); /// assert_eq!(Rational::from(123).eq_abs(&Natural::from(123u32)), true); /// assert_eq!(Rational::from(-123).eq_abs(&Natural::from(123u32)), true); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Natural::from(123u32)), /// false /// ); /// assert_eq!( /// Rational::from_signeds(22, 7).eq_abs(&Natural::from(123u32)), /// false /// ); /// ``` #[inline] fn eq_abs(&self, other: &Natural) -> bool { self.denominator == 1 && self.numerator == *other } } impl EqAbs for Natural { /// Determines whether the absolute values of a [`Rational`] and a [`Natural`] are equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Natural::from(122u32).eq_abs(&Rational::from(-123)), false); /// assert_eq!(Natural::from(124u32).eq_abs(&Rational::from(-123)), false); /// assert_eq!( /// Natural::from(124u32).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Natural::from(124u32).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// assert_eq!(Natural::from(123u32).eq_abs(&Rational::from(123)), true); /// assert_eq!(Natural::from(123u32).eq_abs(&Rational::from(-123)), true); /// assert_eq!( /// Natural::from(123u32).eq_abs(&Rational::from_signeds(22, 7)), /// false /// ); /// assert_eq!( /// Natural::from(123u32).eq_abs(&Rational::from_signeds(-22, 7)), /// false /// ); /// ``` #[inline] fn eq_abs(&self, other: &Rational) -> bool { other.denominator == 1 && other.numerator == *self } } ================================================ FILE: malachite-q/src/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{FloorLogBase2, IsPowerOf2}; use malachite_base::num::comparison::traits::EqAbs; use malachite_base::num::conversion::traits::ExactFrom; macro_rules! impl_eq_abs { ($t: ident) => { impl EqAbs<$t> for Rational { /// Determines whether the absolute values of a [`Rational`] and a primitive float are /// equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.sci_exponent().abs())`, and $m$ is `other.sci_exponent().abs()`. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { if !other.is_finite() { false } else if *other == 0.0 { *self == 0u32 } else { *self != 0u32 && self.denominator.is_power_of_2() && self.floor_log_base_2_abs() == other.abs().floor_log_base_2() && self.eq_abs(&Rational::exact_from(other.abs())) } } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive float and a [`Rational`] are /// equal. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.sci_exponent().abs(), /// other.significant_bits())`, and $m$ is `self.sci_exponent().abs()`. /// /// See [here](super::eq_abs_primitive_float#eq_abs). #[inline] fn eq_abs(&self, other: &Rational) -> bool { other.eq_abs(self) } } }; } apply_to_primitive_floats!(impl_eq_abs); ================================================ FILE: malachite-q/src/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::comparison::traits::EqAbs; macro_rules! impl_unsigned { ($t: ident) => { impl EqAbs<$t> for Rational { /// Determines whether the absolute values of a [`Rational`] and a primitive unsigned /// integer are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { self.denominator == 1u32 && self.numerator == *other } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive unsigned integer and a /// [`Rational`] are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Rational) -> bool { other.denominator == 1u32 && other.numerator == *self } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl EqAbs<$t> for Rational { /// Determines whether the absolute values of a [`Rational`] and a primitive signed /// integer are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &$t) -> bool { self.denominator == 1 && self.numerator == other.unsigned_abs() } } impl EqAbs for $t { /// Determines whether the absolute values of a primitive signed integer and an /// [`Rational`] are equal. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// See [here](super::eq_abs_primitive_int#eq_abs). #[inline] fn eq_abs(&self, other: &Rational) -> bool { other.denominator == 1 && other.numerator == self.unsigned_abs() } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-q/src/comparison/mod.rs ================================================ // Copyright © 2026 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 . /// Comparison of [`Rational`](crate::Rational)s. pub mod cmp; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// and [`OrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) (traits for comparing /// the absolute values of numbers by order) for [`Rational`](crate::Rational)s. pub mod cmp_abs; /// Equality of the absolute values of two [`Rational`](crate::Rational)s. pub mod eq_abs; /// Equality of the absolute values of a [`Rational`](crate::Rational) and an /// [`Integer`](malachite_nz::integer::Integer). pub mod eq_abs_integer; /// Equality of the absolute values of a [`Rational`](crate::Rational) and a /// [`Natural`](malachite_nz::natural::Natural). pub mod eq_abs_natural; /// Equality of the absolute values of a [`Rational`](crate::Rational) and a primitive float. /// /// # eq_abs /// ``` /// use malachite_base::num::basic::traits::{NegativeInfinity, Zero}; /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(123).eq_abs(&123.0), true); /// assert_eq!(Rational::from(123).eq_abs(&5.0), false); /// assert_eq!(Rational::from(123).eq_abs(&-123.0), true); /// assert_eq!(Rational::from(123).eq_abs(&-5.0), false); /// assert_eq!(Rational::from(-123).eq_abs(&123.0), true); /// assert_eq!(Rational::from(-123).eq_abs(&5.0), false); /// assert_eq!(Rational::from(-123).eq_abs(&-123.0), true); /// assert_eq!(Rational::from(-123).eq_abs(&-5.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&123.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&5.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&-123.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&-5.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&123.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&5.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&-123.0), false); /// assert_eq!(Rational::from_signeds(22, 7).eq_abs(&-5.0), false); /// assert_eq!(Rational::ZERO.eq_abs(&0.0), true); /// assert_eq!(Rational::ZERO.eq_abs(&-0.0), true); /// assert_eq!(Rational::ZERO.eq_abs(&f64::NAN), false); /// assert_eq!(Rational::ZERO.eq_abs(&f64::INFINITY), false); /// assert_eq!(Rational::ZERO.eq_abs(&f64::NEGATIVE_INFINITY), false); /// /// assert_eq!(123.0.eq_abs(&Rational::from(123)), true); /// assert_eq!(5.0.eq_abs(&Rational::from(123)), false); /// assert_eq!((-123.0).eq_abs(&Rational::from(123)), true); /// assert_eq!((-5.0).eq_abs(&Rational::from(123)), false); /// assert_eq!(123.0.eq_abs(&Rational::from(-123)), true); /// assert_eq!(5.0.eq_abs(&Rational::from(-123)), false); /// assert_eq!((-123.0).eq_abs(&Rational::from(-123)), true); /// assert_eq!((-5.0).eq_abs(&Rational::from(-123)), false); /// assert_eq!(123.0.eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!(5.0.eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!((-123.0).eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!((-5.0).eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!(123.0.eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!(5.0.eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!((-123.0).eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!((-5.0).eq_abs(&Rational::from_signeds(22, 7)), false); /// assert_eq!(0.0.eq_abs(&Rational::ZERO), true); /// assert_eq!((-0.0).eq_abs(&Rational::ZERO), true); /// assert_eq!(f64::NAN.eq_abs(&Rational::ZERO), false); /// assert_eq!(f64::INFINITY.eq_abs(&Rational::ZERO), false); /// assert_eq!(f64::NEGATIVE_INFINITY.eq_abs(&Rational::ZERO), false); /// ``` pub mod eq_abs_primitive_float; /// Equality of the absolute values of a [`Rational`](crate::Rational) and a primitive integer. /// /// # eq_abs /// ``` /// use malachite_base::num::comparison::traits::EqAbs; /// use malachite_q::Rational; /// /// assert!(Rational::from(123).eq_abs(&123u64)); /// assert!(Rational::from(-123).eq_abs(&123u64)); /// assert!(Rational::from_signeds(22, 7).ne_abs(&123u64)); /// assert!(Rational::from_signeds(-22, 7).ne_abs(&123u64)); /// /// assert!(Rational::from(123).eq_abs(&123i64)); /// assert!(Rational::from(123).eq_abs(&-123i64)); /// assert!(Rational::from_signeds(22, 7).ne_abs(&-123i64)); /// assert!(Rational::from_signeds(-22, 7).ne_abs(&-123i64)); /// /// assert!(123u64.eq_abs(&Rational::from(123))); /// assert!(123u64.eq_abs(&Rational::from(-123))); /// assert!(123u64.ne_abs(&Rational::from_signeds(22, 7))); /// assert!(123u64.ne_abs(&Rational::from_signeds(-22, 7))); /// /// assert!(123i64.eq_abs(&Rational::from(123))); /// assert!(123i64.eq_abs(&Rational::from(-123))); /// assert!((-123i64).ne_abs(&Rational::from_signeds(22, 7))); /// assert!((-123i64).ne_abs(&Rational::from_signeds(-22, 7))); /// ``` pub mod eq_abs_primitive_int; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Rational`](crate::Rational)s and [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_cmp_abs_integer; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Rational`](crate::Rational)s and [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_cmp_abs_natural; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Rational`](crate::Rational)s and primitive floats. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(1, 3).gt_abs(&-0.33f32)); /// assert!(Rational::from_signeds(1, 3).lt_abs(&-0.34f32)); /// /// assert!((-0.33f32).lt_abs(&Rational::from_signeds(1, 3))); /// assert!((-0.34f32).gt_abs(&Rational::from_signeds(1, 3))); /// ``` pub mod partial_cmp_abs_primitive_float; /// Implementations of [`PartialOrdAbs`](`malachite_base::num::comparison::traits::PartialOrdAbs`) /// (a trait for comparing the absolute values of numbers by order) for /// [`Rational`](crate::Rational)s and primitive integers. /// /// # partial_cmp_abs /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(22, 7).gt_abs(&3u32)); /// assert!(Rational::from_signeds(22, 7).lt_abs(&4u32)); /// assert!(Rational::from_signeds(-22, 7).gt_abs(&3u32)); /// assert!(Rational::from_signeds(-22, 7).lt_abs(&4u32)); /// /// assert!(Rational::from_signeds(22, 7).gt_abs(&3i32)); /// assert!(Rational::from_signeds(22, 7).lt_abs(&4i32)); /// assert!(Rational::from_signeds(-22, 7).gt_abs(&-3i32)); /// assert!(Rational::from_signeds(-22, 7).lt_abs(&-4i32)); /// /// assert!(3u32.lt_abs(&Rational::from_signeds(22, 7))); /// assert!(4u32.gt_abs(&Rational::from_signeds(22, 7))); /// assert!(3u32.lt_abs(&Rational::from_signeds(-22, 7))); /// assert!(4u32.gt_abs(&Rational::from_signeds(-22, 7))); /// /// assert!(3i32.lt_abs(&Rational::from_signeds(22, 7))); /// assert!(4i32.gt_abs(&Rational::from_signeds(22, 7))); /// assert!((-3i32).lt_abs(&Rational::from_signeds(-22, 7))); /// assert!((-4i32).gt_abs(&Rational::from_signeds(-22, 7))); /// ``` pub mod partial_cmp_abs_primitive_int; /// Comparison of [`Rational`](crate::Rational)s and [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_cmp_integer; /// Comparison of [`Rational`](crate::Rational)s and [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_cmp_natural; /// Comparison of [`Rational`](crate::Rational)s and primitive floats. /// /// # partial_cmp /// ``` /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(1, 3) > 0.33f32); /// assert!(Rational::from_signeds(1, 3) < 0.34f32); /// /// assert!(0.33f32 < Rational::from_signeds(1, 3)); /// assert!(0.34f32 > Rational::from_signeds(1, 3)); /// ``` pub mod partial_cmp_primitive_float; /// Comparison of [`Rational`](crate::Rational)s and primitive integers. /// /// # partial_cmp /// ``` /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(22, 7) > 3u32); /// assert!(Rational::from_signeds(22, 7) < 4u32); /// assert!(Rational::from_signeds(-22, 7) < 3u32); /// assert!(Rational::from_signeds(-22, 7) < 4u32); /// /// assert!(Rational::from_signeds(22, 7) > 3i32); /// assert!(Rational::from_signeds(22, 7) < 4i32); /// assert!(Rational::from_signeds(-22, 7) < -3i32); /// assert!(Rational::from_signeds(-22, 7) > -4i32); /// /// assert!(3u32 < Rational::from_signeds(22, 7)); /// assert!(4u32 > Rational::from_signeds(22, 7)); /// assert!(3u32 > Rational::from_signeds(-22, 7)); /// assert!(4u32 > Rational::from_signeds(-22, 7)); /// /// assert!(3i32 < Rational::from_signeds(22, 7)); /// assert!(4i32 > Rational::from_signeds(22, 7)); /// assert!(-3i32 > Rational::from_signeds(-22, 7)); /// assert!(-4i32 < Rational::from_signeds(-22, 7)); /// ``` pub mod partial_cmp_primitive_int; /// Equality of [`Rational`](crate::Rational)s and [`Integer`](malachite_nz::integer::Integer)s. pub mod partial_eq_integer; /// Equality of [`Rational`](crate::Rational)s and [`Natural`](malachite_nz::natural::Natural)s. pub mod partial_eq_natural; /// Equality of [`Rational`](crate::Rational)s and primitive floats. /// /// # partial_eq /// ``` /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(3, 2) == 1.5f32); /// assert!(Rational::from_signeds(3, 2) != 1.4f32); /// /// assert!(1.5f32 == Rational::from_signeds(3, 2)); /// assert!(1.4f32 != Rational::from_signeds(3, 2)); /// ``` pub mod partial_eq_primitive_float; /// Equality of [`Rational`](crate::Rational)s and primitive integers. /// /// # partial_eq /// ``` /// use malachite_q::Rational; /// /// assert!(Rational::from(123) == 123u64); /// assert!(Rational::from(-123) != 123u64); /// assert!(Rational::from_signeds(22, 7) != 123u64); /// assert!(Rational::from_signeds(-22, 7) != 123u64); /// /// assert!(Rational::from(123) == 123i64); /// assert!(Rational::from(-123) == -123i64); /// assert!(Rational::from_signeds(22, 7) != -123i64); /// assert!(Rational::from_signeds(-22, 7) != -123i64); /// /// assert!(123u64 == Rational::from(123)); /// assert!(123u64 != Rational::from(-123)); /// assert!(123u64 != Rational::from_signeds(22, 7)); /// assert!(123u64 != Rational::from_signeds(-22, 7)); /// /// assert!(123i64 == Rational::from(123)); /// assert!(-123i64 == Rational::from(-123)); /// assert!(-123i64 != Rational::from_signeds(22, 7)); /// assert!(-123i64 != Rational::from_signeds(-22, 7)); /// ``` pub mod partial_eq_primitive_int; ================================================ FILE: malachite-q/src/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::traits::One; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl PartialOrdAbs for Rational { /// Compares the absolute values of a [`Rational`] and an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// Rational::from_signeds(22, 7).partial_cmp_abs(&Integer::from(3)), /// Some(Greater) /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).partial_cmp_abs(&Integer::from(-3)), /// Some(Greater) /// ); /// ``` fn partial_cmp_abs(&self, other: &Integer) -> Option { // First check whether either value is zero let self_sign = self.numerator_ref().sign(); let other_sign = other.unsigned_abs_ref().sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.unsigned_abs_ref().cmp(&Natural::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(other.unsigned_abs_ref()); let d_cmp = self.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = self .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(log_cmp); } // Finally, cross-multiply. Some( self.numerator .cmp(&(&self.denominator * other.unsigned_abs_ref())), ) } } impl PartialOrdAbs for Integer { /// Compares the absolute values of an [`Integer`] and a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// Integer::from(3).partial_cmp_abs(&Rational::from_signeds(22, 7)), /// Some(Less) /// ); /// assert_eq!( /// Integer::from(-3).partial_cmp_abs(&Rational::from_signeds(-22, 7)), /// Some(Less) /// ); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Rational) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } ================================================ FILE: malachite-q/src/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::traits::One; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl PartialOrdAbs for Rational { /// Compares the absolute values of a [`Rational`] and a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// Rational::from_signeds(22, 7).partial_cmp_abs(&Natural::from(3u32)), /// Some(Greater) /// ); /// assert_eq!( /// Rational::from_signeds(-22, 7).partial_cmp_abs(&Natural::from(3u32)), /// Some(Greater) /// ); /// ``` fn partial_cmp_abs(&self, other: &Natural) -> Option { // First check if either value is zero let self_sign = self.numerator_ref().sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.cmp(&Natural::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(other); let d_cmp = self.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = self .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(log_cmp); } // Finally, cross-multiply. Some(self.numerator.cmp(&(&self.denominator * other))) } } impl PartialOrdAbs for Natural { /// Compares the absolute values of a [`Natural`] and a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_base::num::comparison::traits::PartialOrdAbs; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// Natural::from(3u32).partial_cmp_abs(&Rational::from_signeds(22, 7)), /// Some(Less) /// ); /// assert_eq!( /// Natural::from(3u32).partial_cmp_abs(&Rational::from_signeds(-22, 7)), /// Some(Less) /// ); /// ``` #[inline] fn partial_cmp_abs(&self, other: &Rational) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } ================================================ FILE: malachite-q/src/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::FloorLogBase2; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; macro_rules! impl_float { ($t: ident) => { impl PartialOrdAbs<$t> for Rational { /// Compares the absolute values of a [`Rational`] and a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs). fn partial_cmp_abs(&self, other: &$t) -> Option { if other.is_nan() { None } else if *other == 0.0 { self.partial_cmp_abs(&0u32) } else if !other.is_finite() || *self == 0u32 { Some(Less) } else { let ord_cmp = self .floor_log_base_2_abs() .cmp(&other.abs().floor_log_base_2()); Some(if ord_cmp != Equal { ord_cmp } else { self.cmp_abs(&Rational::exact_from(*other)) }) } } } impl PartialOrdAbs for $t { /// Compares the absolute values of a primitive float and a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.sci_exponent().abs(), other.significant_bits())`. /// /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Rational) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-q/src/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{Sign, UnsignedAbs}; use malachite_base::num::basic::traits::One; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; #[allow(clippy::unnecessary_wraps)] fn partial_cmp_abs_unsigned( x: &Rational, other: &T, ) -> Option where Natural: From + PartialOrd, { // First check if either value is zero let self_sign = x.numerator_ref().sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = x.numerator.cmp(&x.denominator); let other_cmp_one = other.cmp(&T::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = x.numerator.partial_cmp(other).unwrap(); let d_cmp = x.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = x .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(log_cmp); } // Finally, cross-multiply. Some(x.numerator.cmp(&(&x.denominator * Natural::from(*other)))) } macro_rules! impl_unsigned { ($t: ident) => { impl PartialOrdAbs<$t> for Rational { /// Compares the absolute values of a [`Rational`] and an unsigned primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { partial_cmp_abs_unsigned(self, other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of an unsigned primitive integer and a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Rational) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_unsigned); #[allow(clippy::unnecessary_wraps)] fn partial_cmp_abs_signed< U: Copy + One + Ord + Sign + SignificantBits, S: Copy + Sign + SignificantBits + UnsignedAbs, >( x: &Rational, other: &S, ) -> Option where Natural: From + PartialOrd, { // First check if either value is zero let self_sign = x.numerator_ref().sign(); let other_abs = other.unsigned_abs(); let other_sign = other_abs.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = x.numerator.cmp(&x.denominator); let other_cmp_one = other_abs.cmp(&U::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = x.numerator.partial_cmp(&other_abs).unwrap(); let d_cmp = x.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = x .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(log_cmp); } // Finally, cross-multiply. Some( x.numerator .cmp(&(&x.denominator * Natural::from(other_abs))), ) } macro_rules! impl_signed { ($t: ident) => { impl PartialOrdAbs<$t> for Rational { /// Compares the absolute values of a [`Rational`] and a signed primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &$t) -> Option { partial_cmp_abs_signed(self, other) } } impl PartialOrdAbs for $t { /// Compares the absolute values of a signed primitive integer and a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// See [here](super::partial_cmp_abs_primitive_int#partial_cmp_abs). #[inline] fn partial_cmp_abs(&self, other: &Rational) -> Option { other.partial_cmp_abs(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-q/src/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl PartialOrd for Rational { /// Compares a [`Rational`] to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(22, 7) > Integer::from(3)); /// assert!(Rational::from_signeds(22, 7) < Integer::from(4)); /// assert!(Rational::from_signeds(-22, 7) < Integer::from(-3)); /// assert!(Rational::from_signeds(-22, 7) > Integer::from(-4)); /// ``` fn partial_cmp(&self, other: &Integer) -> Option { // First check signs let self_sign = self.sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.unsigned_abs_ref().cmp(&Natural::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(if self.sign { one_cmp } else { one_cmp.reverse() }); } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(other.unsigned_abs_ref()); let d_cmp = self.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(if self.sign { nd_cmp } else { nd_cmp.reverse() }); } let log_cmp = self .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(if self.sign { log_cmp } else { log_cmp.reverse() }); } // Finally, cross-multiply. let prod_cmp = self .numerator .cmp(&(&self.denominator * other.unsigned_abs_ref())); Some(if self.sign { prod_cmp } else { prod_cmp.reverse() }) } } impl PartialOrd for Integer { /// Compares an [`Integer`] to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert!(Integer::from(3) < Rational::from_signeds(22, 7)); /// assert!(Integer::from(4) > Rational::from_signeds(22, 7)); /// assert!(Integer::from(-3) > Rational::from_signeds(-22, 7)); /// assert!(Integer::from(-4) < Rational::from_signeds(-22, 7)); /// ``` #[inline] fn partial_cmp(&self, other: &Rational) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } ================================================ FILE: malachite-q/src/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::Sign; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; impl PartialOrd for Rational { /// Compares a [`Rational`] to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert!(Rational::from_signeds(22, 7) > Natural::from(3u32)); /// assert!(Rational::from_signeds(22, 7) < Natural::from(4u32)); /// ``` fn partial_cmp(&self, other: &Natural) -> Option { // First check signs let self_sign = self.sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = self.numerator.cmp(&self.denominator); let other_cmp_one = other.cmp(&Natural::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = self.numerator.cmp(other); let d_cmp = self.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } let log_cmp = self .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(if self.sign { log_cmp } else { log_cmp.reverse() }); } // Finally, cross-multiply. Some(self.numerator.cmp(&(&self.denominator * other))) } } impl PartialOrd for Natural { /// Compares a [`Natural`] to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert!(Natural::from(3u32) < Rational::from_signeds(22, 7)); /// assert!(Natural::from(4u32) > Rational::from_signeds(22, 7)); /// ``` #[inline] fn partial_cmp(&self, other: &Rational) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } ================================================ FILE: malachite-q/src/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::FloorLogBase2; macro_rules! impl_float { ($t: ident) => { impl PartialOrd<$t> for Rational { /// Compares a [`Rational`] to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(self.significant_bits(), other.sci_exponent().abs())`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). fn partial_cmp(&self, other: &$t) -> Option { if other.is_nan() { None } else if self.sign != (*other >= 0.0) { Some(if self.sign { Greater } else { Less }) } else if !other.is_finite() { Some(if self.sign { Less } else { Greater }) } else if *other == 0.0 { self.partial_cmp(&0u32) } else if *self == 0u32 { 0.0.partial_cmp(other) } else { let ord_cmp = self .floor_log_base_2_abs() .cmp(&other.abs().floor_log_base_2()); Some(if ord_cmp != Equal { if self.sign { ord_cmp } else { ord_cmp.reverse() } } else { self.cmp(&Rational::try_from(*other).unwrap()) }) } } } impl PartialOrd for $t { /// Compares a primitive float to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `max(other.sci_exponent().abs(), self.significant_bits())`. /// /// # Examples /// See [here](super::partial_cmp_primitive_float#partial_cmp). #[inline] fn partial_cmp(&self, other: &Rational) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-q/src/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{Sign, UnsignedAbs}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; #[allow(clippy::unnecessary_wraps)] fn partial_cmp_unsigned( x: &Rational, other: &T, ) -> Option where Natural: From + PartialOrd, { // First check signs let self_sign = x.sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } // Then check if one is < 1 and the other is > 1 let self_cmp_one = x.numerator.cmp(&x.denominator); let other_cmp_one = other.cmp(&T::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(one_cmp); } // Then compare numerators and denominators let n_cmp = x.numerator.partial_cmp(other).unwrap(); let d_cmp = x.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(nd_cmp); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = x .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(if x.sign { log_cmp } else { log_cmp.reverse() }); } // Finally, cross-multiply. Some(x.numerator.cmp(&(&x.denominator * Natural::from(*other)))) } macro_rules! impl_unsigned { ($t: ident) => { impl PartialOrd<$t> for Rational { /// Compares a [`Rational`] to an unsigned primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { partial_cmp_unsigned(self, other) } } impl PartialOrd for $t { /// Compares an unsigned primitive integer to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Rational) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_unsigneds!(impl_unsigned); #[allow(clippy::unnecessary_wraps)] fn partial_cmp_signed< U: Copy + One + Ord + SignificantBits, S: Copy + Sign + SignificantBits + UnsignedAbs, >( x: &Rational, other: &S, ) -> Option where Natural: From + PartialOrd, { // First check signs let self_sign = x.sign(); let other_sign = other.sign(); let sign_cmp = self_sign.cmp(&other_sign); if sign_cmp != Equal || self_sign == Equal { return Some(sign_cmp); } let other_abs = other.unsigned_abs(); // Then check if one is < 1 and the other is > 1 let self_cmp_one = x.numerator.cmp(&x.denominator); let other_cmp_one = other_abs.cmp(&U::ONE); let one_cmp = self_cmp_one.cmp(&other_cmp_one); if one_cmp != Equal { return Some(if x.sign { one_cmp } else { one_cmp.reverse() }); } // Then compare numerators and denominators let n_cmp = x.numerator.partial_cmp(&other_abs).unwrap(); let d_cmp = x.denominator.cmp(&Natural::ONE); if n_cmp == Equal && d_cmp == Equal { return Some(Equal); } let nd_cmp = n_cmp.cmp(&d_cmp); if nd_cmp != Equal { return Some(if x.sign { nd_cmp } else { nd_cmp.reverse() }); } // Then compare floor ∘ log_2 ∘ abs let log_cmp = x .floor_log_base_2_abs() .cmp(&i64::exact_from(other.significant_bits() - 1)); if log_cmp != Equal { return Some(if x.sign { log_cmp } else { log_cmp.reverse() }); } // Finally, cross-multiply. let prod_cmp = x .numerator .cmp(&(&x.denominator * Natural::from(other_abs))); Some(if x.sign { prod_cmp } else { prod_cmp.reverse() }) } macro_rules! impl_signed { ($t: ident) => { impl PartialOrd<$t> for Rational { /// Compares a [`Rational`] to a signed primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &$t) -> Option { partial_cmp_signed(self, other) } } impl PartialOrd for $t { /// Compares a signed primitive integer to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_cmp_primitive_int#partial_cmp). #[inline] fn partial_cmp(&self, other: &Rational) -> Option { other.partial_cmp(self).map(Ordering::reverse) } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-q/src/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::integer::Integer; impl PartialEq for Rational { /// Determines whether a [`Rational`] is equal to an [`Integer`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert!(Rational::from(-123) == Integer::from(-123)); /// assert!(Rational::from_signeds(22, 7) != Integer::from(5)); /// ``` fn eq(&self, other: &Integer) -> bool { self.sign == (*other >= 0) && self.denominator == 1 && self.numerator == *other.unsigned_abs_ref() } } impl PartialEq for Integer { /// Determines whether an [`Integer`] is equal to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert!(Integer::from(-123) == Rational::from(-123)); /// assert!(Integer::from(5) != Rational::from_signeds(22, 7)); /// ``` fn eq(&self, other: &Rational) -> bool { other.sign == (*self >= 0) && other.denominator == 1 && *self.unsigned_abs_ref() == other.numerator } } ================================================ FILE: malachite-q/src/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::natural::Natural; impl PartialEq for Rational { /// Determines whether a [`Rational`] is equal to a [`Natural`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert!(Rational::from(123) == Natural::from(123u32)); /// assert!(Rational::from_signeds(22, 7) != Natural::from(5u32)); /// ``` fn eq(&self, other: &Natural) -> bool { self.sign && self.denominator == 1 && self.numerator == *other } } impl PartialEq for Natural { /// Determines whether a [`Natural`] is equal to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `min(self.significant_bits(), /// other.significant_bits())`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert!(Natural::from(123u32) == Rational::from(123)); /// assert!(Natural::from(5u32) != Rational::from_signeds(22, 7)); /// ``` fn eq(&self, other: &Rational) -> bool { other.sign && other.denominator == 1 && *self == other.numerator } } ================================================ FILE: malachite-q/src/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{FloorLogBase2, IsPowerOf2}; use malachite_base::num::conversion::traits::ExactFrom; macro_rules! impl_float { ($t: ident) => { impl PartialEq<$t> for Rational { /// Determines whether a [`Rational`] is equal to a primitive float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(), /// other.sci_exponent().abs())`, and $m$ is `other.sci_exponent().abs()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[allow(clippy::cmp_owned)] fn eq(&self, other: &$t) -> bool { if !other.is_finite() { false } else if *other == 0.0 { *self == 0u32 } else { *self != 0u32 && self.sign == (*other > 0.0) && self.denominator.is_power_of_2() && self.floor_log_base_2_abs() == other.abs().floor_log_base_2() && *self == Rational::exact_from(*other) } } } impl PartialEq for $t { /// Determines whether a primitive float is equal to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(m) = O(m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.sci_exponent().abs(), /// other.significant_bits())`, and $m$ is `self.sci_exponent().abs()`. /// /// # Examples /// See [here](super::partial_eq_primitive_float#partial_eq). #[inline] fn eq(&self, other: &Rational) -> bool { other == self } } }; } apply_to_primitive_floats!(impl_float); ================================================ FILE: malachite-q/src/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Rational; macro_rules! impl_unsigned { ($t: ident) => { impl PartialEq<$t> for Rational { /// Determines whether a [`Rational`] is equal to an unsigned primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &$t) -> bool { self.sign && self.denominator == 1u32 && self.numerator == *other } } impl PartialEq for $t { /// Determines whether an unsigned primitive integer is equal to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Rational) -> bool { other == self } } }; } apply_to_unsigneds!(impl_unsigned); macro_rules! impl_signed { ($t: ident) => { impl PartialEq<$t> for Rational { /// Determines whether a [`Rational`] is equal to a signed primitive integer. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). fn eq(&self, other: &$t) -> bool { self.sign == (*other >= 0) && self.denominator == 1 && self.numerator == other.unsigned_abs() } } impl PartialEq for $t { /// Determines whether a signed primitive integer is equal to a [`Rational`]. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `other.significant_bits()`. /// /// # Examples /// See [here](super::partial_eq_primitive_int#partial_eq). #[inline] fn eq(&self, other: &Rational) -> bool { other == self } } }; } apply_to_signeds!(impl_signed); ================================================ FILE: malachite-q/src/conversion/continued_fraction/convergents.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::continued_fraction::to_continued_fraction::RationalContinuedFraction; use crate::conversion::traits::ContinuedFraction; use crate::conversion::traits::Convergents; use core::mem::swap; use malachite_base::num::arithmetic::traits::{AddMulAssign, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; /// An iterator that produces the convergents of a [`Rational`]. /// /// See [`convergents`](Rational::convergents) for more information. #[derive(Clone, Debug, Eq, PartialEq)] pub struct RationalConvergents { first: bool, previous_numerator: Integer, previous_denominator: Natural, numerator: Integer, denominator: Natural, cf: RationalContinuedFraction, } impl Iterator for RationalConvergents { type Item = Rational; fn next(&mut self) -> Option { if self.first { self.first = false; Some(Rational::from(&self.numerator)) } else if let Some(n) = self.cf.next() { self.previous_numerator .add_mul_assign(&self.numerator, Integer::from(&n)); self.previous_denominator .add_mul_assign(&self.denominator, n); swap(&mut self.numerator, &mut self.previous_numerator); swap(&mut self.denominator, &mut self.previous_denominator); Some(Rational { sign: self.numerator >= 0, numerator: (&self.numerator).unsigned_abs(), denominator: self.denominator.clone(), }) } else { None } } } impl Convergents for Rational { type C = RationalConvergents; /// Returns the convergents of a [`Rational`], taking the [`Rational`] by value. /// /// The convergents of a number are the sequence of rational numbers whose continued fractions /// are the prefixes of the number's continued fraction. The first convergent is the floor of /// the number. The sequence of convergents is finite iff the number is rational, in which case /// the last convergent is the number itself. Each convergent is closer to the number than the /// previous convergent is. The even-indexed convergents are less than or equal to the number, /// and the odd-indexed ones are greater than or equal to it. /// /// $f(x) = ([a_0; a_1, a_2, \ldots, a_i])_{i=0}^{n}$, where $x = [a_0; a_1, a_2, \ldots, a_n]$ /// and $a_n \neq 1$. /// /// The output length is $O(n)$, where $n$ is `self.significant_bits()`. /// /// # Worst-case complexity per iteration /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::traits::Convergents; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_signeds(2, 3) /// .convergents() /// .collect_vec() /// .to_debug_string(), /// "[0, 1, 2/3]" /// ); /// assert_eq!( /// Rational::from_signeds(355, 113) /// .convergents() /// .collect_vec() /// .to_debug_string(), /// "[3, 22/7, 355/113]", /// ); /// ``` fn convergents(self) -> RationalConvergents { let (floor, cf) = self.continued_fraction(); RationalConvergents { first: true, previous_numerator: Integer::ONE, previous_denominator: Natural::ZERO, numerator: floor, denominator: Natural::ONE, cf, } } } impl Convergents for &Rational { type C = RationalConvergents; /// Returns the convergents of a [`Rational`], taking the [`Rational`] by reference. /// /// The convergents of a number are the sequence of rational numbers whose continued fractions /// are the prefixes of the number's continued fraction. The first convergent is the floor of /// the number. The sequence of convergents is finite iff the number is rational, in which case /// the last convergent is the number itself. Each convergent is closer to the number than the /// previous convergent is. The even-indexed convergents are less than or equal to the number, /// and the odd-indexed ones are greater than or equal to it. /// /// $f(x) = ([a_0; a_1, a_2, \ldots, a_i])_{i=0}^{n}$, where $x = [a_0; a_1, a_2, \ldots, a_n]$ /// and $a_n \neq 1$. /// /// The output length is $O(n)$, where $n$ is `self.significant_bits()`. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::traits::Convergents; /// use malachite_q::Rational; /// /// assert_eq!( /// (&Rational::from_signeds(2, 3)) /// .convergents() /// .collect_vec() /// .to_debug_string(), /// "[0, 1, 2/3]" /// ); /// assert_eq!( /// (&Rational::from_signeds(355, 113)) /// .convergents() /// .collect_vec() /// .to_debug_string(), /// "[3, 22/7, 355/113]", /// ); /// ``` fn convergents(self) -> RationalConvergents { let (floor, cf) = self.continued_fraction(); RationalConvergents { first: true, previous_numerator: Integer::ONE, previous_denominator: Natural::ZERO, numerator: floor, denominator: Natural::ONE, cf, } } } ================================================ FILE: malachite-q/src/conversion/continued_fraction/from_continued_fraction.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::mem::swap; use malachite_base::num::arithmetic::traits::{AddMulAssign, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl Rational { /// Converts a finite continued fraction to a [`Rational`], taking the inputs by value. /// /// The input has two components. The first is the first value of the continued fraction, which /// may be any [`Integer`] and is equal to the floor of the [`Rational`]. The second is an /// iterator of the remaining values, which must all be positive. Using the standard notation /// for continued fractions, the first value is the number before the semicolon, and the second /// value contains the remaining numbers. /// /// Each rational number has two continued fraction representations. Either one is a valid /// input. /// /// $f(a_0, (a_1, a_2, a_3, \ldots)) = [a_0; a_1, a_2, a_3, \ldots]$. /// /// # Worst-case complexity /// $T(n, m) = O((nm)^2 \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(floor.significant_bits(), /// xs.map(Natural::significant_bits).max())`, and $m$ is `xs.count()`. /// /// # Panics /// Panics if any [`Natural`] in `xs` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// let xs = vec_from_str("[1, 2]").unwrap().into_iter(); /// assert_eq!( /// Rational::from_continued_fraction(Integer::ZERO, xs).to_string(), /// "2/3" /// ); /// /// let xs = vec_from_str("[7, 16]").unwrap().into_iter(); /// assert_eq!( /// Rational::from_continued_fraction(Integer::from(3), xs).to_string(), /// "355/113" /// ); /// ``` pub fn from_continued_fraction>(floor: Integer, xs: I) -> Self { let mut previous_numerator = Integer::ONE; let mut previous_denominator = Natural::ZERO; let mut numerator = floor; let mut denominator = Natural::ONE; for n in xs { assert_ne!(n, 0u32); previous_numerator.add_mul_assign(&numerator, Integer::from(&n)); previous_denominator.add_mul_assign(&denominator, n); swap(&mut numerator, &mut previous_numerator); swap(&mut denominator, &mut previous_denominator); } Self { sign: numerator >= 0, numerator: numerator.unsigned_abs(), denominator, } } /// Converts a finite continued fraction to a [`Rational`], taking the inputs by reference. /// /// The input has two components. The first is the first value of the continued fraction, which /// may be any [`Integer`] and is equal to the floor of the [`Rational`]. The second is an /// iterator of the remaining values, which must all be positive. Using the standard notation /// for continued fractions, the first value is the number before the semicolon, and the second /// value contains the remaining numbers. /// /// Each rational number has two continued fraction representations. Either one is a valid /// input. /// /// $f(a_0, (a_1, a_2, a_3, \ldots)) = [a_0; a_1, a_2, a_3, \ldots]$. /// /// # Worst-case complexity /// $T(n, m) = O((nm)^2 \log (nm) \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(floor.significant_bits(), /// xs.map(Natural::significant_bits).max())`, and $m$ is `xs.count()`. /// /// # Panics /// Panics if any [`Natural`] in `xs` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// let xs = vec_from_str("[1, 2]").unwrap(); /// assert_eq!( /// Rational::from_continued_fraction_ref(&Integer::ZERO, xs.iter()).to_string(), /// "2/3" /// ); /// /// let xs = vec_from_str("[7, 16]").unwrap(); /// assert_eq!( /// Rational::from_continued_fraction_ref(&Integer::from(3), xs.iter()).to_string(), /// "355/113" /// ); /// ``` pub fn from_continued_fraction_ref<'a, I: Iterator>( floor: &Integer, xs: I, ) -> Self { let mut previous_numerator = Integer::ONE; let mut previous_denominator = Natural::ZERO; let mut numerator = floor.clone(); let mut denominator = Natural::ONE; for n in xs { assert_ne!(*n, 0u32); previous_numerator.add_mul_assign(&numerator, Integer::from(n)); previous_denominator.add_mul_assign(&denominator, n); swap(&mut numerator, &mut previous_numerator); swap(&mut denominator, &mut previous_denominator); } Self { sign: numerator >= 0, numerator: numerator.unsigned_abs(), denominator, } } } ================================================ FILE: malachite-q/src/conversion/continued_fraction/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`Convergents`](super::traits::Convergents), a trait for generating the /// convergents of a number. pub mod convergents; /// Functions for constructing a [`Rational`](crate::Rational) from a continued fraction. pub mod from_continued_fraction; /// Implementations of [`ContinuedFraction`](super::traits::ContinuedFraction), a trait for /// generating the continued fraction of a number. pub mod to_continued_fraction; ================================================ FILE: malachite-q/src/conversion/continued_fraction/to_continued_fraction.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::traits::ContinuedFraction; use core::mem::swap; use malachite_base::num::arithmetic::traits::{DivMod, Floor}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; /// An iterator that produces the continued fraction of a [`Rational`]. /// /// See [`continued_fraction`](Rational::continued_fraction) for more information. #[derive(Clone, Debug, Eq, PartialEq)] pub struct RationalContinuedFraction { numerator: Natural, denominator: Natural, } impl RationalContinuedFraction { pub_crate_test! {is_done(&self) -> bool { self.denominator == 0u32 || self.numerator == 0u32 }} } impl Iterator for RationalContinuedFraction { type Item = Natural; fn next(&mut self) -> Option { if self.denominator == 0u32 || self.numerator == 0u32 { None } else { let n; (n, self.numerator) = (&self.numerator).div_mod(&self.denominator); swap(&mut self.numerator, &mut self.denominator); Some(n) } } } impl ContinuedFraction for Rational { type CF = RationalContinuedFraction; /// Returns the continued fraction of a [`Rational`], taking the [`Rational`] by value. /// /// The output has two components. The first is the first value of the continued fraction, which /// may be any [`Integer`] and is equal to the floor of the [`Rational`]. The second is an /// iterator that produces the remaining values, which are all positive. Using the standard /// notation for continued fractions, the first value is the number before the semicolon, and /// the second value produces the remaining numbers. /// /// Each rational number has two continued fraction representations. The shorter of the two /// representations (the one that does not end in 1) is returned. /// /// $f(x) = (a_0, (a_1, a_2, \ldots, a_3)),$ where $x = [a_0; a_1, a_2, \ldots, a_3]$ and $a_3 /// \neq 1$. /// /// The output length is $O(n)$, where $n$ is `self.significant_bits()`. /// /// # Worst-case complexity per iteration /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::traits::ContinuedFraction; /// use malachite_q::Rational; /// /// let (head, tail) = Rational::from_signeds(2, 3).continued_fraction(); /// let tail = tail.collect_vec(); /// assert_eq!(head, 0); /// assert_eq!(tail.to_debug_string(), "[1, 2]"); /// /// let (head, tail) = Rational::from_signeds(355, 113).continued_fraction(); /// let tail = tail.collect_vec(); /// assert_eq!(head, 3); /// assert_eq!(tail.to_debug_string(), "[7, 16]"); /// ``` fn continued_fraction(mut self) -> (Integer, RationalContinuedFraction) { let f = (&self).floor(); self -= Self::from(&f); let (d, n) = self.into_numerator_and_denominator(); ( f, RationalContinuedFraction { numerator: n, denominator: d, }, ) } } impl ContinuedFraction for &Rational { type CF = RationalContinuedFraction; /// Returns the continued fraction of a [`Rational`], taking the [`Rational`] by reference. /// /// The output has two components. The first is the first value of the continued fraction, which /// may be any [`Integer`] and is equal to the floor of the [`Rational`]. The second is an /// iterator that produces the remaining values, which are all positive. Using the standard /// notation for continued fractions, the first value is the number before the semicolon, and /// the second value produces the remaining numbers. /// /// Each rational number has two continued fraction representations. The shorter of the two /// representations (the one that does not end in 1) is returned. /// /// $f(x) = (a_0, (a_1, a_2, \ldots, a_3)),$ where $x = [a_0; a_1, a_2, \ldots, a_3]$ and $a_3 /// \neq 1$. /// /// The output length is $O(n)$, where $n$ is `self.significant_bits()`. /// /// # Worst-case complexity per iteration /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::traits::ContinuedFraction; /// use malachite_q::Rational; /// /// let (head, tail) = (&Rational::from_signeds(2, 3)).continued_fraction(); /// let tail = tail.collect_vec(); /// assert_eq!(head, 0); /// assert_eq!(tail.to_debug_string(), "[1, 2]"); /// /// let (head, tail) = (&Rational::from_signeds(355, 113)).continued_fraction(); /// let tail = tail.collect_vec(); /// assert_eq!(head, 3); /// assert_eq!(tail.to_debug_string(), "[7, 16]"); /// ``` fn continued_fraction(self) -> (Integer, RationalContinuedFraction) { let f = self.floor(); let (d, n) = (self - Rational::from(&f)).into_numerator_and_denominator(); ( f, RationalContinuedFraction { numerator: n, denominator: d, }, ) } } ================================================ FILE: malachite-q/src/conversion/digits/digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::digits::power_of_2_digits::RationalPowerOf2Digits; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{Abs, CheckedLogBase2, Floor, UnsignedAbs}; use malachite_base::num::conversion::traits::Digits; use malachite_nz::natural::Natural; #[doc(hidden)] #[derive(Clone, Debug, Eq, PartialEq)] pub struct RationalGeneralDigits { base: Rational, remainder: Rational, } impl Iterator for RationalGeneralDigits { type Item = Natural; fn next(&mut self) -> Option { if self.remainder == 0u32 { None } else { self.remainder *= &self.base; let digit = (&self.remainder).floor().unsigned_abs(); self.remainder -= Rational::from(&digit); Some(digit) } } } /// Represents the base-$b$ digits of the fractional portion of a [`Rational`] number. /// /// See [`digits`](Rational::digits) for more information. #[derive(Clone, Debug, Eq, PartialEq)] pub enum RationalDigits { General(RationalGeneralDigits), PowerOf2(RationalPowerOf2Digits), } impl Iterator for RationalDigits { type Item = Natural; fn next(&mut self) -> Option { match self { Self::General(xs) => xs.next(), Self::PowerOf2(xs) => xs.next(), } } } impl Rational { /// Returns the base-$b$ digits of a [`Rational`]. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is an iterator of the digits of /// the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(b-1)$s. /// /// If the [`Rational`] has a small denominator, it may be more efficient to use /// [`to_digits`](Rational::to_digits) or [`into_digits`](Rational::into_digits) instead. These /// functions compute the entire repeating portion of the repeating digits. /// /// For example, consider these two expressions: /// - `Rational::from_signeds(1, 7).digits(Natural::from(10u32)).1.nth(1000)` /// - `Rational::from_signeds(1, 7).into_digits(Natural::from(10u32)).1[1000]` /// /// Both get the thousandth digit after the decimal point of `1/7`. The first way explicitly /// calculates each digit after the decimal point, whereas the second way determines that `1/7` /// is `0.(142857)`, with the `142857` repeating, and takes `1000 % 6 == 4` to determine that /// the thousandth digit is 5. But when the [`Rational`] has a large denominator, the second way /// is less efficient. /// /// # Worst-case complexity per iteration /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// base.significant_bits())`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(prefix_to_string(after_point, 10), "[]"); /// /// let (before_point, after_point) = /// Rational::from_signeds(22, 7).digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!( /// prefix_to_string(after_point, 10), /// "[1, 4, 2, 8, 5, 7, 1, 4, 2, 8, ...]" /// ); /// ``` pub fn digits(&self, base: &Natural) -> (Vec, RationalDigits) { if let Some(log_base) = base.checked_log_base_2() { let (before_point, after_point) = self.power_of_2_digits(log_base); (before_point, RationalDigits::PowerOf2(after_point)) } else { let mut remainder = self.abs(); let floor = (&remainder).floor().unsigned_abs(); remainder -= Self::from(&floor); ( floor.to_digits_asc(base), RationalDigits::General(RationalGeneralDigits { base: Self::from(base), remainder, }), ) } } } ================================================ FILE: malachite-q/src/conversion/digits/from_digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{CheckedLogBase2, Pow}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{Digits, ExactFrom}; use malachite_base::rational_sequences::RationalSequence; use malachite_nz::natural::Natural; impl Rational { /// Converts base-$b$ digits to a [`Rational`]. The inputs are taken by value. /// /// The input consists of the digits of the integer portion of the [`Rational`] and the digits /// of the fractional portion. The integer-portion digits are ordered from least- to /// most-significant, and the fractional-portion digits from most- to least. /// /// The fractional-portion digits may end in infinitely many zeros or $(b-1)$s; these are /// handled correctly. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm)^2 \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(before_point.len(), /// after_point.component_len())`, and $m$ is `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let before_point = vec_from_str("[3]").unwrap(); /// let after_point = /// RationalSequence::from_vecs(Vec::new(), vec_from_str("[1, 4, 2, 8, 5, 7]").unwrap()); /// assert_eq!( /// Rational::from_digits(&Natural::from(10u32), before_point, after_point).to_string(), /// "22/7" /// ); /// /// // 21.34565656... /// let before_point = vec_from_str("[1, 2]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[3, 4]").unwrap(), /// vec_from_str("[5, 6]").unwrap(), /// ); /// assert_eq!( /// Rational::from_digits(&Natural::from(10u32), before_point, after_point).to_string(), /// "105661/4950" /// ); /// ``` pub fn from_digits( base: &Natural, before_point: Vec, after_point: RationalSequence, ) -> Self { if let Some(log_base) = base.checked_log_base_2() { return Self::from_power_of_2_digits(log_base, before_point, after_point); } let (non_repeating, repeating) = after_point.into_vecs(); let r_len = u64::exact_from(repeating.len()); let nr_len = u64::exact_from(non_repeating.len()); let nr = Natural::from_digits_asc(base, non_repeating.into_iter().rev()).unwrap(); let r = Natural::from_digits_asc(base, repeating.into_iter().rev()).unwrap(); let floor = Self::from(Natural::from_digits_asc(base, before_point.into_iter()).unwrap()); floor + if r == 0u32 { Self::from_naturals(nr, base.pow(nr_len)) } else { (Self::from_naturals(r, base.pow(r_len) - Natural::ONE) + Self::from(nr)) / Self::from(base.pow(nr_len)) } } /// Converts base-$b$ digits to a [`Rational`]. The inputs are taken by reference. /// /// The input consists of the digits of the integer portion of the [`Rational`] and the digits /// of the fractional portion. The integer-portion digits are ordered from least- to /// most-significant, and the fractional-portion digits from most- to least. /// /// The fractional-portion digits may end in infinitely many zeros or $(b-1)$s; these are /// handled correctly. /// /// # Worst-case complexity /// $T(n, m) = O(nm \log (nm)^2 \log\log (nm))$ /// /// $M(n, m) = O(nm \log (nm))$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(before_point.len(), /// after_point.component_len())`, and $m$ is `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// use malachite_base::vecs::vec_from_str; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let before_point = vec_from_str("[3]").unwrap(); /// let after_point = /// RationalSequence::from_vecs(Vec::new(), vec_from_str("[1, 4, 2, 8, 5, 7]").unwrap()); /// assert_eq!( /// Rational::from_digits_ref(&Natural::from(10u32), &before_point, &after_point) /// .to_string(), /// "22/7" /// ); /// /// // 21.34565656... /// let before_point = vec_from_str("[1, 2]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[3, 4]").unwrap(), /// vec_from_str("[5, 6]").unwrap(), /// ); /// assert_eq!( /// Rational::from_digits_ref(&Natural::from(10u32), &before_point, &after_point) /// .to_string(), /// "105661/4950" /// ); /// ``` pub fn from_digits_ref( base: &Natural, before_point: &[Natural], after_point: &RationalSequence, ) -> Self { if let Some(log_base) = base.checked_log_base_2() { return Self::from_power_of_2_digits_ref(log_base, before_point, after_point); } let (non_repeating, repeating) = after_point.to_vecs(); let r_len = u64::exact_from(repeating.len()); let nr_len = u64::exact_from(non_repeating.len()); let nr = Natural::from_digits_asc(base, non_repeating.into_iter().rev()).unwrap(); let r = Natural::from_digits_asc(base, repeating.into_iter().rev()).unwrap(); let floor = Self::from(Natural::from_digits_asc(base, before_point.iter().cloned()).unwrap()); floor + if r == 0u32 { Self::from_naturals(nr, base.pow(nr_len)) } else { (Self::from_naturals(r, base.pow(r_len) - Natural::ONE) + Self::from(nr)) / Self::from(base.pow(nr_len)) } } } ================================================ FILE: malachite-q/src/conversion/digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use alloc::vec::Vec; use malachite_base::num::conversion::traits::{ExactFrom, PowerOf2Digits}; use malachite_base::num::logic::traits::LowMask; use malachite_base::rational_sequences::RationalSequence; use malachite_nz::natural::Natural; impl Rational { /// Converts base-$2^k$ digits to a [`Rational`]. The inputs are taken by value. /// /// The input consists of the digits of the integer portion of the [`Rational`] and the digits /// of the fractional portion. The integer-portion digits are ordered from least- to /// most-significant, and the fractional-portion digits from most- to least. /// /// The fractional-portion digits may end in infinitely many zeros or $(2^k-1)$s; these are /// handled correctly. /// /// # Worst-case complexity /// $T(n, m) = O(nm)$ /// /// $M(n, m) = O(nm)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(before_point.len(), /// after_point.component_len())`, and $m$ is `base.significant_bits()`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// /// let before_point = vec_from_str("[1, 1]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[0]").unwrap(), /// vec_from_str("[0, 0, 1]").unwrap(), /// ); /// assert_eq!( /// Rational::from_power_of_2_digits(1, before_point, after_point).to_string(), /// "43/14" /// ); /// /// // 21.34565656..._32 /// let before_point = vec_from_str("[1, 2]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[3, 4]").unwrap(), /// vec_from_str("[5, 6]").unwrap(), /// ); /// assert_eq!( /// Rational::from_power_of_2_digits(5, before_point, after_point).to_string(), /// "34096673/523776" /// ); /// ``` pub fn from_power_of_2_digits( log_base: u64, before_point: Vec, after_point: RationalSequence, ) -> Self { let (non_repeating, repeating) = after_point.into_vecs(); let r_len = u64::exact_from(repeating.len()); let nr_len = u64::exact_from(non_repeating.len()); let nr = Natural::from_power_of_2_digits_asc(log_base, non_repeating.into_iter().rev()).unwrap(); let r = Natural::from_power_of_2_digits_asc(log_base, repeating.into_iter().rev()).unwrap(); let floor = Self::from( Natural::from_power_of_2_digits_asc(log_base, before_point.into_iter()).unwrap(), ); floor + if r == 0u32 { Self::from(nr) >> (log_base * nr_len) } else { (Self::from_naturals(r, Natural::low_mask(log_base * r_len)) + Self::from(nr)) >> (log_base * nr_len) } } /// Converts base-$2^k$ digits to a [`Rational`]. The inputs are taken by reference. /// /// The input consists of the digits of the integer portion of the [`Rational`] and the digits /// of the fractional portion. The integer-portion digits are ordered from least- to /// most-significant, and the fractional-portion digits from most- to least. /// /// The fractional-portion digits may end in infinitely many zeros or $(2^k-1)$s; these are /// handled correctly. /// /// # Worst-case complexity /// $T(n, m) = O(nm)$ /// /// $M(n, m) = O(nm)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `max(before_point.len(), /// after_point.component_len())`, and $m$ is `base.significant_bits()`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::rational_sequences::RationalSequence; /// use malachite_base::vecs::vec_from_str; /// use malachite_q::Rational; /// /// let before_point = vec_from_str("[1, 1]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[0]").unwrap(), /// vec_from_str("[0, 0, 1]").unwrap(), /// ); /// assert_eq!( /// Rational::from_power_of_2_digits_ref(1, &before_point, &after_point).to_string(), /// "43/14" /// ); /// /// // 21.34565656..._32 /// let before_point = vec_from_str("[1, 2]").unwrap(); /// let after_point = RationalSequence::from_vecs( /// vec_from_str("[3, 4]").unwrap(), /// vec_from_str("[5, 6]").unwrap(), /// ); /// assert_eq!( /// Rational::from_power_of_2_digits_ref(5, &before_point, &after_point).to_string(), /// "34096673/523776" /// ); /// ``` pub fn from_power_of_2_digits_ref( log_base: u64, before_point: &[Natural], after_point: &RationalSequence, ) -> Self { let (non_repeating, repeating) = after_point.to_vecs(); let r_len = u64::exact_from(repeating.len()); let nr_len = u64::exact_from(non_repeating.len()); let nr = Natural::from_power_of_2_digits_asc(log_base, non_repeating.into_iter().rev()).unwrap(); let r = Natural::from_power_of_2_digits_asc(log_base, repeating.into_iter().rev()).unwrap(); let floor = Self::from( Natural::from_power_of_2_digits_asc(log_base, before_point.iter().cloned()).unwrap(), ); floor + if r == 0u32 { Self::from(nr) >> (log_base * nr_len) } else { (Self::from_naturals(r, Natural::low_mask(log_base * r_len)) + Self::from(nr)) >> (log_base * nr_len) } } } ================================================ FILE: malachite-q/src/conversion/digits/mod.rs ================================================ // Copyright © 2026 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 . /// Functions for producing iterators over the digits of a [`Rational`](crate::Rational). #[allow(clippy::module_inception)] pub mod digits; /// Functions for constructing a [`Rational`](crate::Rational) from digits. pub mod from_digits; /// Functions for constructing a [`Rational`](crate::Rational) from base-$2^k$ digits. pub mod from_power_of_2_digits; /// Functions for producing iterators over the base-$2^k$ digits of a [`Rational`](crate::Rational). pub mod power_of_2_digits; /// Functions for returning the digits of a [`Rational`](crate::Rational). The digits after the /// point are returned as a /// [`RationalSequence`](malachite_base::rational_sequences::RationalSequence). pub mod to_digits; /// Functions for returning the base-$2^k$ digits of a [`Rational`](crate::Rational). The digits /// after the point are returned as a /// [`RationalSequence`](malachite_base::rational_sequences::RationalSequence). pub mod to_power_of_2_digits; ================================================ FILE: malachite-q/src/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{Abs, Floor, UnsignedAbs}; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_nz::natural::Natural; /// Represents the base-$2^k$ digits of the fractional portion of a [`Rational`] number. /// /// See [`power_of_2_digits`](Rational::power_of_2_digits) for more information. #[derive(Clone, Debug, Eq, PartialEq)] pub struct RationalPowerOf2Digits { log_base: u64, remainder: Rational, } impl Iterator for RationalPowerOf2Digits { type Item = Natural; fn next(&mut self) -> Option { if self.remainder == 0u32 { None } else { self.remainder <<= self.log_base; let digit = (&self.remainder).floor().unsigned_abs(); self.remainder -= Rational::from(&digit); Some(digit) } } } impl Rational { /// Returns the base-$2^k$ digits of a [`Rational`]. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is an iterator of the digits of /// the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(2^k-1)$s. /// /// If the [`Rational`] has a small denominator, it may be more efficient to use /// [`to_power_of_2_digits`](Rational::to_power_of_2_digits) or /// [`into_power_of_2_digits`](Rational::into_power_of_2_digits) instead. These functions /// compute the entire repeating portion of the repeating digits. /// /// For example, consider these two expressions: /// - `Rational::from_signeds(1, 7).power_of_2_digits(1).1.nth(1000)` /// - `Rational::from_signeds(1, 7).into_power_of_2_digits(1).1[1000]` /// /// Both get the thousandth digit after the binary point of `1/7`. The first way explicitly /// calculates each bit after the binary point, whereas the second way determines that `1/7` is /// `0.(001)`, with the `001` repeating, and takes `1000 % 3 == 1` to determine that the /// thousandth bit is 0. But when the [`Rational`] has a large denominator, the second way is /// less efficient. /// /// # Worst-case complexity per iteration /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), /// base)`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!(prefix_to_string(after_point, 10), "[]"); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!( /// prefix_to_string(after_point, 10), /// "[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, ...]" /// ); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).power_of_2_digits(10); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!( /// prefix_to_string(after_point, 10), /// "[146, 292, 585, 146, 292, 585, 146, 292, 585, 146, ...]" /// ); /// ``` pub fn power_of_2_digits(&self, log_base: u64) -> (Vec, RationalPowerOf2Digits) { let mut remainder = self.abs(); let floor = (&remainder).floor().unsigned_abs(); remainder -= Self::from(&floor); ( floor.to_power_of_2_digits_asc(log_base), RationalPowerOf2Digits { log_base, remainder, }, ) } } ================================================ FILE: malachite-q/src/conversion/digits/to_digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::digits::to_power_of_2_digits::to_power_of_2_digits_helper; use alloc::collections::BTreeMap; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{ Abs, AbsAssign, CheckedLogBase2, Floor, UnsignedAbs, }; use malachite_base::num::conversion::traits::Digits; use malachite_base::rational_sequences::RationalSequence; use malachite_nz::natural::Natural; fn to_digits_helper(x: Rational, base: &Natural) -> (Vec, RationalSequence) { if let Some(log_base) = base.checked_log_base_2() { return to_power_of_2_digits_helper(x, log_base); } let floor = (&x).floor(); let mut remainder = x - Rational::from(&floor); let before_point = floor.unsigned_abs().to_digits_asc(base); let mut state_map = BTreeMap::new(); let mut digits = Vec::new(); let base = Rational::from(base); for i in 0.. { if remainder == 0u32 { return (before_point, RationalSequence::from_vec(digits)); } if let Some(previous_i) = state_map.insert(remainder.clone(), i) { let repeating = digits.drain(previous_i..).collect(); return (before_point, RationalSequence::from_vecs(digits, repeating)); } remainder *= &base; let floor = (&remainder).floor().unsigned_abs(); digits.push(floor.clone()); remainder -= Rational::from(floor); } unreachable!() } impl Rational { /// Returns the base-$b$ digits of a [`Rational`], taking the [`Rational`] by value. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is a [`RationalSequence`] of the /// digits of the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(b-1)$s. /// /// The fractional portion may be very large; the length of the repeating part may be almost as /// large as the denominator. If the [`Rational`] has a large denominator, consider using /// [`digits`](Rational::digits) instead, which returns an iterator. That function computes the /// fractional digits lazily and doesn't need to compute the entire repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(m2^n)$ /// /// $M(n, m) = O(m2^n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).into_digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[]"); /// /// let (before_point, after_point) = /// Rational::from_signeds(22, 7).into_digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[[1, 4, 2, 8, 5, 7]]"); /// ``` #[inline] pub fn into_digits(mut self, base: &Natural) -> (Vec, RationalSequence) { self.abs_assign(); to_digits_helper(self, base) } /// Returns the base-$b$ digits of a [`Rational`], taking the [`Rational`] by reference. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is a [`RationalSequence`] of the /// digits of the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(b-1)$s. /// /// The fractional portion may be very large; the length of the repeating part may be almost as /// large as the denominator. If the [`Rational`] has a large denominator, consider using /// [`digits`](Rational::digits) instead, which returns an iterator. That function computes the /// fractional digits lazily and doesn't need to compute the entire repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(m2^n)$ /// /// $M(n, m) = O(m2^n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `base.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).to_digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[]"); /// /// let (before_point, after_point) = /// Rational::from_signeds(22, 7).to_digits(&Natural::from(10u32)); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[[1, 4, 2, 8, 5, 7]]"); /// ``` pub fn to_digits(&self, base: &Natural) -> (Vec, RationalSequence) { to_digits_helper(self.abs(), base) } } ================================================ FILE: malachite-q/src/conversion/digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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 crate::Rational; use alloc::collections::BTreeMap; use alloc::vec::Vec; use malachite_base::num::arithmetic::traits::{Abs, AbsAssign, Floor, UnsignedAbs}; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::rational_sequences::RationalSequence; use malachite_nz::natural::Natural; pub(crate) fn to_power_of_2_digits_helper( x: Rational, log_base: u64, ) -> (Vec, RationalSequence) { let floor = (&x).floor(); let mut remainder = x - Rational::from(&floor); let before_point = floor.unsigned_abs().to_power_of_2_digits_asc(log_base); let mut state_map = BTreeMap::new(); let mut digits = Vec::new(); for i in 0.. { if remainder == 0u32 { return (before_point, RationalSequence::from_vec(digits)); } if let Some(previous_i) = state_map.insert(remainder.clone(), i) { let repeating = digits.drain(previous_i..).collect(); return (before_point, RationalSequence::from_vecs(digits, repeating)); } remainder <<= log_base; let floor = (&remainder).floor().unsigned_abs(); digits.push(floor.clone()); remainder -= Rational::from(floor); } unreachable!() } impl Rational { /// Returns the base-$2^k$ digits of a [`Rational`], taking the [`Rational`] by value. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is a [`RationalSequence`] of the /// digits of the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(2^k-1)$s. /// /// The fractional portion may be very large; the length of the repeating part may be almost as /// large as the denominator. If the [`Rational`] has a large denominator, consider using /// [`power_of_2_digits`](Rational::power_of_2_digits) instead, which returns an iterator. That /// function computes the fractional digits lazily and doesn't need to compute the entire /// repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(m2^n)$ /// /// $M(n, m) = O(m2^n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `log_base`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).into_power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!(after_point.to_string(), "[]"); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).into_power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!(after_point.to_string(), "[[0, 0, 1]]"); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).into_power_of_2_digits(10); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[[146, 292, 585]]"); /// ``` #[inline] pub fn into_power_of_2_digits( mut self, log_base: u64, ) -> (Vec, RationalSequence) { self.abs_assign(); to_power_of_2_digits_helper(self, log_base) } /// Returns the base-$2^k$ digits of a [`Rational`], taking the [`Rational`] by reference. /// /// The output has two components. The first is a [`Vec`] of the digits of the integer portion /// of the [`Rational`], least- to most-significant. The second is a [`RationalSequence`] of the /// digits of the fractional portion. /// /// The output is in its simplest form: the integer-portion digits do not end with a zero, and /// the fractional-portion digits do not end with infinitely many zeros or $(2^k-1)$s. /// /// The fractional portion may be very large; the length of the repeating part may be almost as /// large as the denominator. If the [`Rational`] has a large denominator, consider using /// [`power_of_2_digits`](Rational::power_of_2_digits) instead, which returns an iterator. That /// function computes the fractional digits lazily and doesn't need to compute the entire /// repeating part. /// /// # Worst-case complexity /// $T(n, m) = O(m2^n)$ /// /// $M(n, m) = O(m2^n)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is /// `log_base`. /// /// # Panics /// Panics if `log_base` is zero. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// let (before_point, after_point) = Rational::from(3u32).to_power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!(after_point.to_string(), "[]"); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).to_power_of_2_digits(1); /// assert_eq!(before_point.to_debug_string(), "[1, 1]"); /// assert_eq!(after_point.to_string(), "[[0, 0, 1]]"); /// /// let (before_point, after_point) = Rational::from_signeds(22, 7).to_power_of_2_digits(10); /// assert_eq!(before_point.to_debug_string(), "[3]"); /// assert_eq!(after_point.to_string(), "[[146, 292, 585]]"); /// ``` pub fn to_power_of_2_digits(&self, log_base: u64) -> (Vec, RationalSequence) { to_power_of_2_digits_helper(self.abs(), log_base) } } ================================================ FILE: malachite-q/src/conversion/from_bool.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::{One, Zero}; impl From for Rational { /// Converts a [`bool`] to 0 or 1. /// /// This function is known as the [Iverson /// bracket](https://en.wikipedia.org/wiki/Iverson_bracket). /// /// $$ /// f(P) = \[P\] = \\begin{cases} /// 1 & \text{if} \\quad P, \\\\ /// 0 & \\text{otherwise}. /// \\end{cases} /// $$ /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(false), 0); /// assert_eq!(Rational::from(true), 1); /// ``` #[inline] fn from(b: bool) -> Self { if b { Self::ONE } else { Self::ZERO } } } ================================================ FILE: malachite-q/src/conversion/from_float_simplest.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::traits::SimplestRationalInInterval; use crate::conversion::from_primitive_float::RationalFromPrimitiveFloatError; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::ExactFrom; impl Rational { /// Converts a primitive float to the simplest [`Rational`] that rounds to that value. /// /// To be more specific: Suppose the floating-point input is $x$. If $x$ is an integer, its /// [`Rational`] equivalent is returned. Otherwise, this function finds $a$ and $b$, which are /// the floating point predecessor and successor of $x$, and finds the simplest [`Rational`] in /// the open interval $(\frac{x + a}{2}, \frac{x + b}{2})$. "Simplicity" refers to low /// complexity. See [`Rational::cmp_complexity`] for a definition of complexity. /// /// For example, `0.1f32` is converted to $1/10$ rather than to the exact value of the float, /// which is $13421773/134217728$. If you want the exact value, use `Rational::from` instead. /// /// If the floating point value is `NaN` or infinite, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n^2 \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.sci_exponent()`. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::try_from_float_simplest(0.0).to_debug_string(), /// "Ok(0)" /// ); /// assert_eq!( /// Rational::try_from_float_simplest(1.5).to_debug_string(), /// "Ok(3/2)" /// ); /// assert_eq!( /// Rational::try_from_float_simplest(-1.5).to_debug_string(), /// "Ok(-3/2)" /// ); /// assert_eq!( /// Rational::try_from_float_simplest(0.1f32).to_debug_string(), /// "Ok(1/10)" /// ); /// assert_eq!( /// Rational::try_from_float_simplest(0.33333334f32).to_debug_string(), /// "Ok(1/3)" /// ); /// assert_eq!( /// Rational::try_from_float_simplest(f32::NAN), /// Err(RationalFromPrimitiveFloatError) /// ); /// ``` pub fn try_from_float_simplest( x: T, ) -> Result where Self: TryFrom, { let q = Self::try_from(x)?; Ok(if *q.denominator_ref() <= 2u32 { q } else { let succ_q = Self::exact_from(x.next_higher()); let pred_q = Self::exact_from(x.next_lower()); let x = (pred_q + &q) >> 1; let y = (succ_q + q) >> 1; Self::simplest_rational_in_open_interval(&x, &y) }) } } ================================================ FILE: malachite-q/src/conversion/from_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::One; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; impl From for Rational { /// Converts an [`Integer`] to a [`Rational`], taking the [`Integer`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(Integer::from(123)), 123); /// assert_eq!(Rational::from(Integer::from(-123)), -123); /// ``` fn from(value: Integer) -> Self { Self { sign: value >= 0, numerator: value.unsigned_abs(), denominator: Natural::ONE, } } } impl From<&Integer> for Rational { /// Converts an [`Integer`] to a [`Rational`], taking the [`Integer`] by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(&Integer::from(123)), 123); /// assert_eq!(Rational::from(&Integer::from(-123)), -123); /// ``` fn from(value: &Integer) -> Self { Self { sign: *value >= 0, numerator: value.unsigned_abs(), denominator: Natural::ONE, } } } ================================================ FILE: malachite-q/src/conversion/from_natural.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::One; use malachite_nz::natural::Natural; impl From for Rational { /// Converts a [`Natural`] to a [`Rational`], taking the [`Natural`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(Natural::from(123u32)), 123); /// ``` fn from(value: Natural) -> Self { Self { sign: true, numerator: value, denominator: Natural::ONE, } } } impl From<&Natural> for Rational { /// Converts a [`Natural`] to a [`Rational`], taking the [`Natural`] by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(&Natural::from(123u32)), 123); /// ``` fn from(value: &Natural) -> Self { Self { sign: true, numerator: value.clone(), denominator: Natural::ONE, } } } ================================================ FILE: malachite-q/src/conversion/from_numerator_and_denominator.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{DivExact, Gcd, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; macro_rules! const_gcd_step { ($x: ident, $y: ident) => { let new_y = $x % $y; $x = $y; $y = new_y; if $y == 0 { return $x; } }; } // Worst case when Limb = u64 is const_gcd(Fib_92, Fib_93) = const_gcd(7540113804746346429, // 12200160415121876738) const fn const_gcd(mut x: Limb, mut y: Limb) -> Limb { if y == 0 { x } else { const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); const_gcd_step!(x, y); unreachable!() } } impl Rational { /// Converts two[`Limb`](crate#limbs)s, representing a numerator and a denominator, to a /// [`Rational`]. /// /// If `denominator` is zero, `None` is returned. /// /// This function is const, so it may be used to define constants. When called at runtime, it is /// slower than [`Rational::from_unsigneds`]. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// const TWO_THIRDS: Rational = Rational::const_from_unsigneds(2, 3); /// assert_eq!(TWO_THIRDS, Rational::from_unsigneds(2u32, 3)); /// /// const TWO_THIRDS_ALT: Rational = Rational::const_from_unsigneds(22, 33); /// assert_eq!(TWO_THIRDS_ALT, Rational::from_unsigneds(2u32, 3)); /// ``` pub const fn const_from_unsigneds(numerator: Limb, denominator: Limb) -> Self { assert!(denominator != 0); let gcd = const_gcd(numerator, denominator); Self { sign: true, numerator: Natural::const_from(numerator / gcd), denominator: Natural::const_from(denominator / gcd), } } /// Converts two[`SignedLimb`](crate#limbs)s, representing a numerator and a denominator, to a /// [`Rational`]. /// /// If `denominator` is zero, `None` is returned. /// /// This function is const, so it may be used to define constants. When called at runtime, it is /// slower than [`Rational::from_signeds`]. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// const NEGATIVE_TWO_THIRDS: Rational = Rational::const_from_signeds(-2, 3); /// assert_eq!(NEGATIVE_TWO_THIRDS, Rational::from_signeds(-2, 3)); /// /// const NEGATIVE_TWO_THIRDS_ALT: Rational = Rational::const_from_signeds(-22, 33); /// assert_eq!(NEGATIVE_TWO_THIRDS_ALT, Rational::from_signeds(-2, 3)); /// ``` pub const fn const_from_signeds(numerator: SignedLimb, denominator: SignedLimb) -> Self { assert!(denominator != 0); let sign = numerator == 0 || (numerator > 0) == (denominator > 0); let numerator = numerator.unsigned_abs(); let denominator = denominator.unsigned_abs(); let gcd = const_gcd(numerator, denominator); Self { sign, numerator: Natural::const_from(numerator / gcd), denominator: Natural::const_from(denominator / gcd), } } /// Converts two [`Natural`]s to a [`Rational`], taking the [`Natural`]s by value. /// /// The [`Natural`]s become the [`Rational`]'s numerator and denominator. Only non-negative /// [`Rational`]s can be produced with this function. /// /// The denominator may not be zero. /// /// The input [`Natural`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_naturals(Natural::from(4u32), Natural::from(6u32)).to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_naturals(Natural::ZERO, Natural::from(6u32)), /// 0 /// ); /// ``` pub fn from_naturals(numerator: Natural, denominator: Natural) -> Self { assert_ne!(denominator, 0); let gcd = (&numerator).gcd(&denominator); Self { sign: true, numerator: numerator.div_exact(&gcd), denominator: denominator.div_exact(gcd), } } /// Converts two [`Natural`]s to a [`Rational`], taking the [`Natural`]s by reference. /// /// The [`Natural`]s become the [`Rational`]'s numerator and denominator. Only non-negative /// [`Rational`]s can be produced with this function. /// /// The denominator may not be zero. /// /// The input [`Natural`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_naturals_ref(&Natural::from(4u32), &Natural::from(6u32)).to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_naturals_ref(&Natural::ZERO, &Natural::from(6u32)), /// 0 /// ); /// ``` pub fn from_naturals_ref(numerator: &Natural, denominator: &Natural) -> Self { assert_ne!(*denominator, 0); let gcd = numerator.gcd(denominator); Self { sign: true, numerator: numerator.div_exact(&gcd), denominator: denominator.div_exact(gcd), } } /// Converts two unsigned primitive integers to a [`Rational`]. /// /// The integers become the [`Rational`]'s numerator and denominator. Only non-negative /// [`Rational`]s can be produced with this function. /// /// The denominator may not be zero. /// /// The input integers may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from_unsigneds(4u32, 6).to_string(), "2/3"); /// assert_eq!(Rational::from_unsigneds(0u32, 6), 0); /// ``` #[inline] pub fn from_unsigneds(numerator: T, denominator: T) -> Self where Natural: From, { Self::from_naturals(Natural::from(numerator), Natural::from(denominator)) } /// Converts two [`Integer`]s to a [`Rational`], taking the [`Integer`]s by value. /// /// The absolute values of the [`Integer`]s become the [`Rational`]'s numerator and denominator. /// The sign of the [`Rational`] is the sign of the [`Integer`]s' quotient. /// /// The denominator may not be zero. /// /// The input [`Integer`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_integers(Integer::from(4), Integer::from(6)).to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_integers(Integer::from(4), Integer::from(-6)).to_string(), /// "-2/3" /// ); /// assert_eq!(Rational::from_integers(Integer::ZERO, Integer::from(6)), 0); /// assert_eq!(Rational::from_integers(Integer::ZERO, Integer::from(-6)), 0); /// ``` pub fn from_integers(numerator: Integer, denominator: Integer) -> Self { assert_ne!(denominator, 0); let sign = numerator == 0 || ((numerator > 0) == (denominator > 0)); let mut q = Self::from_naturals(numerator.unsigned_abs(), denominator.unsigned_abs()); q.sign = sign; q } /// Converts two [`Integer`]s to a [`Rational`], taking the [`Integer`]s by reference. /// /// The absolute values of the [`Integer`]s become the [`Rational`]'s numerator and denominator. /// The sign of the [`Rational`] is the sign of the [`Integer`]s' quotient. /// /// The denominator may not be zero. /// /// The input [`Integer`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_integers_ref(&Integer::from(4), &Integer::from(6)).to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_integers_ref(&Integer::from(4), &Integer::from(-6)).to_string(), /// "-2/3" /// ); /// assert_eq!( /// Rational::from_integers_ref(&Integer::ZERO, &Integer::from(6)), /// 0 /// ); /// assert_eq!( /// Rational::from_integers_ref(&Integer::ZERO, &Integer::from(-6)), /// 0 /// ); /// ``` pub fn from_integers_ref(numerator: &Integer, denominator: &Integer) -> Self { assert_ne!(*denominator, 0); let mut q = Self::from_naturals_ref(numerator.unsigned_abs_ref(), denominator.unsigned_abs_ref()); q.sign = *numerator == 0 || ((*numerator > 0) == (*denominator > 0)); q } /// Converts two signed primitive integers to a [`Rational]`. /// /// The absolute values of the integers become the [`Rational`]'s numerator and denominator. The /// sign of the [`Rational`] is the sign of the integers' quotient. /// /// The denominator may not be zero. /// /// The input integers may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from_signeds(4i8, 6).to_string(), "2/3"); /// assert_eq!(Rational::from_signeds(4i8, -6).to_string(), "-2/3"); /// assert_eq!(Rational::from_signeds(0i8, 6), 0); /// assert_eq!(Rational::from_signeds(0i8, -6), 0); /// ``` #[inline] pub fn from_signeds(numerator: T, denominator: T) -> Self where Integer: From, { Self::from_integers(Integer::from(numerator), Integer::from(denominator)) } /// Converts a sign and two [`Natural`]s to a [`Rational`], taking the [`Natural`]s by value. /// /// The [`Natural`]s become the [`Rational`]'s numerator and denominator, and the sign indicates /// whether the [`Rational`] should be non-negative. If the numerator is zero, then the /// [`Rational`] will be non-negative regardless of the sign. /// /// The denominator may not be zero. /// /// The input [`Natural`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_sign_and_naturals(true, Natural::from(4u32), Natural::from(6u32)) /// .to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_sign_and_naturals(false, Natural::from(4u32), Natural::from(6u32)) /// .to_string(), /// "-2/3" /// ); /// ``` pub fn from_sign_and_naturals(sign: bool, numerator: Natural, denominator: Natural) -> Self { assert_ne!(denominator, 0); let gcd = (&numerator).gcd(&denominator); Self { sign: sign || numerator == 0, numerator: numerator.div_exact(&gcd), denominator: denominator.div_exact(gcd), } } /// Converts a sign and two [`Natural`]s to a [`Rational`], taking the [`Natural`]s by /// reference. /// /// The [`Natural`]s become the [`Rational`]'s numerator and denominator, and the sign indicates /// whether the [`Rational`] should be non-negative. If the numerator is zero, then the /// [`Rational`] will be non-negative regardless of the sign. /// /// The denominator may not be zero. /// /// The input [`Natural`]s may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_sign_and_naturals_ref(true, &Natural::from(4u32), &Natural::from(6u32)) /// .to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_sign_and_naturals_ref(false, &Natural::from(4u32), &Natural::from(6u32)) /// .to_string(), /// "-2/3" /// ); /// ``` pub fn from_sign_and_naturals_ref( sign: bool, numerator: &Natural, denominator: &Natural, ) -> Self { assert_ne!(*denominator, 0); let gcd = numerator.gcd(denominator); Self { sign: sign || *numerator == 0, numerator: numerator.div_exact(&gcd), denominator: denominator.div_exact(gcd), } } /// Converts a sign and two primitive unsigned integers to a [`Rational`]. /// /// The integers become the [`Rational`]'s numerator and denominator, and the sign indicates /// whether the [`Rational`] should be non-negative. If the numerator is zero, then the /// [`Rational`] will be non-negative regardless of the sign. /// /// The denominator may not be zero. /// /// The input integers may have common factors; this function reduces them. /// /// # Worst-case complexity /// $T(n) = O(n^2)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(numerator.significant_bits(), /// denominator.significant_bits())`. /// /// # Panics /// Panics if `denominator` is zero. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!( /// Rational::from_sign_and_unsigneds(true, 4u32, 6).to_string(), /// "2/3" /// ); /// assert_eq!( /// Rational::from_sign_and_unsigneds(false, 4u32, 6).to_string(), /// "-2/3" /// ); /// ``` pub fn from_sign_and_unsigneds( sign: bool, numerator: T, denominator: T, ) -> Self where Natural: From, { Self::from_sign_and_naturals(sign, Natural::from(numerator), Natural::from(denominator)) } } ================================================ FILE: malachite-q/src/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, IntegerMantissaAndExponent}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RationalFromPrimitiveFloatError; macro_rules! float_impls { ($f: ident) => { impl TryFrom<$f> for Rational { type Error = RationalFromPrimitiveFloatError; /// Converts a primitive float to the equivalent [`Rational`]. If the floating point /// value is `NaN` or infinite, an error is returned. /// /// This conversion is literal. For example, `Rational::try_from(0.1f32)` evaluates to /// Some($13421773/134217728$). If you want $1/10$ instead, use /// [`try_from_float_simplest`](Rational::try_from_float_simplest); that function /// returns the simplest [`Rational`] that rounds to the specified float. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is /// `value.sci_exponent().abs()`. /// /// # Examples /// See [here](super::from_primitive_float#try_from). fn try_from(value: $f) -> Result { if !value.is_finite() { Err(RationalFromPrimitiveFloatError) } else if value == 0.0 { Ok(Rational::ZERO) } else { let (mantissa, exponent) = value.integer_mantissa_and_exponent(); let x = Rational::from(mantissa) << exponent; Ok(if value > 0.0 { x } else { -x }) } } } impl ConvertibleFrom<$f> for Rational { /// Determines whether a primitive float can be converted to a [`Rational`]. (It can if /// it is finite.) /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_float#convertible_from). fn convertible_from(x: $f) -> bool { x.is_finite() } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-q/src/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::One; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; impl Rational { /// Converts a [`Limb`](crate#limbs) to a [`Rational`]. /// /// This function is const, so it may be used to define constants. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// const TEN: Rational = Rational::const_from_unsigned(10); /// assert_eq!(TEN, 10); /// ``` pub const fn const_from_unsigned(x: Limb) -> Self { Self { sign: true, numerator: Natural::const_from(x), denominator: Natural::ONE, } } /// Converts a [`SignedLimb`](crate#limbs) to a [`Rational`]. /// /// This function is const, so it may be used to define constants. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// const TEN: Rational = Rational::const_from_signed(10); /// assert_eq!(TEN, 10); /// /// const NEGATIVE_TEN: Rational = Rational::const_from_signed(-10); /// assert_eq!(NEGATIVE_TEN, -10); /// ``` pub const fn const_from_signed(x: SignedLimb) -> Self { Self { sign: x >= 0, numerator: Natural::const_from(x.unsigned_abs()), denominator: Natural::ONE, } } } macro_rules! impl_from_unsigned { ($t: ident) => { impl From<$t> for Rational { /// Converts an unsigned primitive integer to a [`Rational`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(u: $t) -> Rational { Rational { sign: true, numerator: Natural::from(u), denominator: Natural::ONE, } } } }; } apply_to_unsigneds!(impl_from_unsigned); macro_rules! impl_from_signed { ($t: ident) => { impl From<$t> for Rational { /// Converts a signed primitive integer to a [`Rational`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::from_primitive_int#from). #[inline] fn from(i: $t) -> Rational { Rational { sign: i >= 0, numerator: Natural::from(i.unsigned_abs()), denominator: Natural::ONE, } } } }; } apply_to_signeds!(impl_from_signed); ================================================ FILE: malachite-q/src/conversion/integer_from_rational.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering; use malachite_base::num::arithmetic::traits::DivRound; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode; use malachite_nz::integer::Integer; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IntegerFromRationalError; impl TryFrom for Integer { type Error = IntegerFromRationalError; /// Converts a [`Rational`] to an [`Integer`], taking the [`Rational`] by value. If the /// [`Rational`] is not an integer, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::conversion::integer_from_rational::IntegerFromRationalError; /// use malachite_q::Rational; /// /// assert_eq!(Integer::try_from(Rational::from(123)).unwrap(), 123); /// assert_eq!(Integer::try_from(Rational::from(-123)).unwrap(), -123); /// assert_eq!( /// Integer::try_from(Rational::from_signeds(22, 7)), /// Err(IntegerFromRationalError) /// ); /// ``` fn try_from(x: Rational) -> Result { if x.denominator == 1u32 { Ok(Self::from_sign_and_abs(x.sign, x.numerator)) } else { Err(IntegerFromRationalError) } } } impl TryFrom<&Rational> for Integer { type Error = IntegerFromRationalError; /// Converts a [`Rational`] to an [`Integer`], taking the [`Rational`] by reference. If the /// [`Rational`] is not an integer, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::integer::Integer; /// use malachite_q::conversion::integer_from_rational::IntegerFromRationalError; /// use malachite_q::Rational; /// /// assert_eq!(Integer::try_from(&Rational::from(123)).unwrap(), 123); /// assert_eq!(Integer::try_from(&Rational::from(-123)).unwrap(), -123); /// assert_eq!( /// Integer::try_from(&Rational::from_signeds(22, 7)), /// Err(IntegerFromRationalError) /// ); /// ``` fn try_from(x: &Rational) -> Result { if x.denominator == 1u32 { Ok(Self::from_sign_and_abs_ref(x.sign, &x.numerator)) } else { Err(IntegerFromRationalError) } } } impl ConvertibleFrom<&Rational> for Integer { /// Determines whether a [`Rational`] can be converted to an [`Integer`], taking the /// [`Rational`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!(Integer::convertible_from(&Rational::from(123)), true); /// assert_eq!(Integer::convertible_from(&Rational::from(-123)), true); /// assert_eq!( /// Integer::convertible_from(&Rational::from_signeds(22, 7)), /// false /// ); /// ``` #[inline] fn convertible_from(x: &Rational) -> bool { x.denominator == 1u32 } } impl RoundingFrom for Integer { /// Converts a [`Rational`] to an [`Integer`], using a specified [`RoundingMode`] and taking the /// [`Rational`] by value. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!( /// Integer::rounding_from(Rational::from(123), Exact).to_debug_string(), /// "(123, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from(-123), Exact).to_debug_string(), /// "(-123, Equal)" /// ); /// /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(22, 7), Floor).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(22, 7), Down).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(22, 7), Ceiling).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(22, 7), Up).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(22, 7), Nearest).to_debug_string(), /// "(3, Less)" /// ); /// /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Floor).to_debug_string(), /// "(-4, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Down).to_debug_string(), /// "(-3, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Ceiling).to_debug_string(), /// "(-3, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Up).to_debug_string(), /// "(-4, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Nearest).to_debug_string(), /// "(-3, Greater)" /// ); /// ``` fn rounding_from(x: Rational, rm: RoundingMode) -> (Self, Ordering) { let s = x.sign; let (n, o) = x .numerator .div_round(x.denominator, if s { rm } else { -rm }); ( Self::from_sign_and_abs(x.sign, n), if s { o } else { o.reverse() }, ) } } impl RoundingFrom<&Rational> for Integer { /// Converts a [`Rational`] to an [`Integer`], using a specified [`RoundingMode`] and taking the /// [`Rational`] by reference. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::integer::Integer; /// use malachite_q::Rational; /// /// assert_eq!( /// Integer::rounding_from(&Rational::from(123), Exact).to_debug_string(), /// "(123, Equal)" /// ); /// assert_eq!( /// Integer::rounding_from(&Rational::from(-123), Exact).to_debug_string(), /// "(-123, Equal)" /// ); /// /// assert_eq!( /// Integer::rounding_from(&Rational::from_signeds(22, 7), Floor).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(&Rational::from_signeds(22, 7), Down).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(&Rational::from_signeds(22, 7), Ceiling).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(&Rational::from_signeds(22, 7), Up).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(&Rational::from_signeds(22, 7), Nearest).to_debug_string(), /// "(3, Less)" /// ); /// /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Floor).to_debug_string(), /// "(-4, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Down).to_debug_string(), /// "(-3, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Ceiling).to_debug_string(), /// "(-3, Greater)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Up).to_debug_string(), /// "(-4, Less)" /// ); /// assert_eq!( /// Integer::rounding_from(Rational::from_signeds(-22, 7), Nearest).to_debug_string(), /// "(-3, Greater)" /// ); /// ``` fn rounding_from(x: &Rational, rm: RoundingMode) -> (Self, Ordering) { let (n, o) = (&x.numerator).div_round(&x.denominator, if x.sign { rm } else { -rm }); ( Self::from_sign_and_abs(x.sign, n), if x.sign { o } else { o.reverse() }, ) } } ================================================ FILE: malachite-q/src/conversion/is_integer.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::conversion::traits::IsInteger; impl IsInteger for &Rational { /// Determines whether a [`Rational`] is an integer. /// /// $f(x) = x \in \Z$. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::{One, Zero}; /// use malachite_base::num::conversion::traits::IsInteger; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.is_integer(), true); /// assert_eq!(Rational::ONE.is_integer(), true); /// assert_eq!(Rational::from(100).is_integer(), true); /// assert_eq!(Rational::from(-100).is_integer(), true); /// assert_eq!(Rational::from_signeds(22, 7).is_integer(), false); /// assert_eq!(Rational::from_signeds(-22, 7).is_integer(), false); /// ``` #[inline] fn is_integer(self) -> bool { self.denominator == 1u32 } } ================================================ FILE: malachite-q/src/conversion/mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::DivRound; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ ExactFrom, IntegerMantissaAndExponent, SciMantissaAndExponent, WrappingFrom, }; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; impl Rational { /// Returns a [`Rational`]'s scientific mantissa and exponent, taking the [`Rational`] by value. /// An [`Ordering`] is also returned, indicating whether the returned mantissa and exponent /// represent a value that is less than, equal to, or greater than the absolute value of the /// [`Rational`]. /// /// The [`Rational`]'s sign is ignored. This means that, for example, that rounding using /// `Floor` is equivalent to rounding using `Down`, even if the [`Rational`] is negative. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is /// a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as a float. The /// conversion might not be exact, so we round to the nearest float using the provided rounding /// mode. If the rounding mode is `Exact` but the conversion is not exact, `None` is returned. /// $$ /// f(x, r) \approx \left (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, /// \lfloor \log_2 x \rfloor\right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use malachite_q::Rational; /// use std::cmp::Ordering::{self, *}; /// /// let test = |n: Rational, rm: RoundingMode, out: Option<(f32, i64, Ordering)>| { /// assert_eq!( /// n.sci_mantissa_and_exponent_round(rm) /// .map(|(m, e, o)| (NiceFloat(m), e, o)), /// out.map(|(m, e, o)| (NiceFloat(m), e, o)) /// ); /// }; /// test(Rational::from(3u32), Down, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Ceiling, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Up, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Nearest, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Exact, Some((1.5, 1, Equal))); /// /// test( /// Rational::from_signeds(1, 3), /// Floor, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Down, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Ceiling, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Up, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Nearest, /// Some((1.3333334, -2, Greater)), /// ); /// test(Rational::from_signeds(1, 3), Exact, None); /// /// test( /// Rational::from_signeds(-1, 3), /// Floor, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(-1, 3), /// Down, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(-1, 3), /// Ceiling, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(-1, 3), /// Up, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(-1, 3), /// Nearest, /// Some((1.3333334, -2, Greater)), /// ); /// test(Rational::from_signeds(-1, 3), Exact, None); /// ``` pub fn sci_mantissa_and_exponent_round( mut self, rm: RoundingMode, ) -> Option<(T, i64, Ordering)> { assert!(self != 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Less { exponent -= 1; } self >>= exponent - i64::wrapping_from(T::MANTISSA_WIDTH); let (n, d) = self.into_numerator_and_denominator(); if rm == Exact && d != 1u32 { return None; } let (mut mantissa, o) = n.div_round(d, rm); let mut bits = mantissa.significant_bits(); if bits > T::MANTISSA_WIDTH + 1 { bits -= 1; mantissa >>= 1; exponent += 1; } assert_eq!(bits, T::MANTISSA_WIDTH + 1); mantissa.clear_bit(T::MANTISSA_WIDTH); Some(( T::from_raw_mantissa_and_exponent( u64::exact_from(&mantissa), u64::wrapping_from(T::MAX_EXPONENT), ), exponent, o, )) } /// Returns a [`Rational`]'s scientific mantissa and exponent, taking the [`Rational`] by /// reference. An [`Ordering`] is also returned, indicating whether the returned mantissa and /// exponent represent a value that is less than, equal to, or greater than the original value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and $m_s$ is /// a rational number with $1 \leq m_s < 2$. We represent the rational mantissa as a float. The /// conversion might not be exact, so we round to the nearest float using the provided rounding /// mode. If the rounding mode is `Exact` but the conversion is not exact, `None` is returned. /// $$ /// f(x, r) \approx \left (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, /// \lfloor \log_2 x \rfloor\right ). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::{self, *}; /// use malachite_q::Rational; /// use std::cmp::Ordering::{self, *}; /// /// let test = |n: Rational, rm: RoundingMode, out: Option<(f32, i64, Ordering)>| { /// assert_eq!( /// n.sci_mantissa_and_exponent_round_ref(rm) /// .map(|(m, e, o)| (NiceFloat(m), e, o)), /// out.map(|(m, e, o)| (NiceFloat(m), e, o)) /// ); /// }; /// test(Rational::from(3u32), Down, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Ceiling, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Up, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Nearest, Some((1.5, 1, Equal))); /// test(Rational::from(3u32), Exact, Some((1.5, 1, Equal))); /// /// test( /// Rational::from_signeds(1, 3), /// Floor, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Down, /// Some((1.3333333, -2, Less)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Ceiling, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Up, /// Some((1.3333334, -2, Greater)), /// ); /// test( /// Rational::from_signeds(1, 3), /// Nearest, /// Some((1.3333334, -2, Greater)), /// ); /// test(Rational::from_signeds(1, 3), Exact, None); /// ``` pub fn sci_mantissa_and_exponent_round_ref( &self, rm: RoundingMode, ) -> Option<(T, i64, Ordering)> { assert!(*self != 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Less { exponent -= 1; } let x = self >> (exponent - i64::wrapping_from(T::MANTISSA_WIDTH)); let (n, d) = x.into_numerator_and_denominator(); if rm == Exact && d != 1u32 { return None; } let (mut mantissa, o) = n.div_round(d, rm); let mut bits = mantissa.significant_bits(); if bits > T::MANTISSA_WIDTH + 1 { bits -= 1; mantissa >>= 1; exponent += 1; } assert_eq!(bits, T::MANTISSA_WIDTH + 1); mantissa.clear_bit(T::MANTISSA_WIDTH); Some(( T::from_raw_mantissa_and_exponent( u64::exact_from(&mantissa), u64::wrapping_from(T::MAX_EXPONENT), ), exponent, o, )) } } macro_rules! impl_mantissa_and_exponent { ($t:ident) => { impl SciMantissaAndExponent<$t, i64> for Rational { /// Returns a [`Rational`]'s scientific mantissa and exponent, taking the [`Rational`] /// by value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa /// as a float. The conversion might not be exact, so we round to the nearest float /// using the `Nearest` rounding mode. To use other rounding modes, use /// [`sci_mantissa_and_exponent_round`](Rational::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, \lfloor \log_2 x \rfloor). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($t, i64) { let (m, e, _) = self.sci_mantissa_and_exponent_round(Nearest).unwrap(); (m, e) } /// Returns a [`Rational`]'s scientific exponent, taking the [`Rational`] by value. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa /// as a float. The conversion might not be exact, so we round to the nearest float /// using the `Nearest` rounding mode. To use other rounding modes, use /// [`sci_mantissa_and_exponent_round`](Rational::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx \lfloor \log_2 x \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_exponent). fn sci_exponent(mut self) -> i64 { assert!(self != 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Less { exponent -= 1; } self >>= exponent - i64::wrapping_from($t::MANTISSA_WIDTH); let (n, d) = self.into_numerator_and_denominator(); if n.div_round(d, Nearest).0.significant_bits() > $t::MANTISSA_WIDTH + 1 { exponent + 1 } else { exponent } } /// Constructs a [`Rational`] from its scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. Here, the rational mantissa is /// provided as a float. If the mantissa is outside the range $[1, 2)$, `None` is /// returned. /// /// All finite floats can be represented using [`Rational`]s, so no rounding is needed. /// /// $$ /// f(x) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `sci_exponent`. #[allow(clippy::manual_range_contains)] #[inline] fn from_sci_mantissa_and_exponent( sci_mantissa: $t, sci_exponent: i64, ) -> Option { assert_ne!(sci_mantissa, 0.0); if sci_mantissa < 1.0 || sci_mantissa >= 2.0 { None } else { let m = sci_mantissa.integer_mantissa(); Some( Rational::from(m) << (sci_exponent - i64::exact_from(m.significant_bits()) + 1), ) } } } impl SciMantissaAndExponent<$t, i64, Rational> for &Rational { /// Returns a [`Rational`]'s scientific mantissa and exponent, taking the [`Rational`] /// by reference. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa /// as a float. The conversion might not be exact, so we round to the nearest float /// using the `Nearest` rounding mode. To use other rounding modes, use /// [`sci_mantissa_and_exponent_round`](Rational::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx (\frac{x}{2^{\lfloor \log_2 x \rfloor}}, \lfloor \log_2 x \rfloor). /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// See [here](super::mantissa_and_exponent#sci_mantissa_and_exponent). #[inline] fn sci_mantissa_and_exponent(self) -> ($t, i64) { let (m, e, _) = self.sci_mantissa_and_exponent_round_ref(Nearest).unwrap(); (m, e) } /// Returns a [`Rational`]'s scientific exponent, taking the [`Rational`] by reference. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. We represent the rational mantissa /// as a float. The conversion might not be exact, so we round to the nearest float /// using the `Nearest` rounding mode. To use other rounding modes, use /// [`sci_mantissa_and_exponent_round`](Rational::sci_mantissa_and_exponent_round). /// $$ /// f(x) \approx \lfloor \log_2 x \rfloor. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. fn sci_exponent(self) -> i64 { assert!(*self != 0); let mut exponent = i64::exact_from(self.numerator.significant_bits()) - i64::exact_from(self.denominator.significant_bits()); if self.numerator.cmp_normalized(&self.denominator) == Less { exponent -= 1; } let x = self >> exponent - i64::wrapping_from($t::MANTISSA_WIDTH); let (n, d) = x.into_numerator_and_denominator(); if n.div_round(d, Nearest).0.significant_bits() > $t::MANTISSA_WIDTH + 1 { exponent + 1 } else { exponent } } /// Constructs a [`Rational`] from its scientific mantissa and exponent. /// /// When $x$ is positive, we can write $x = 2^{e_s}m_s$, where $e_s$ is an integer and /// $m_s$ is a rational number with $1 \leq m_s < 2$. Here, the rational mantissa is /// provided as a float. If the mantissa is outside the range $[1, 2)$, `None` is /// returned. /// /// All finite floats can be represented using [`Rational`]s, so no rounding is needed. /// /// $$ /// f(x) \approx 2^{e_s}m_s. /// $$ /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `sci_exponent`. /// /// See [here](super::mantissa_and_exponent#from_sci_mantissa_and_exponent). #[inline] fn from_sci_mantissa_and_exponent( sci_mantissa: $t, sci_exponent: i64, ) -> Option { Rational::from_sci_mantissa_and_exponent(sci_mantissa, sci_exponent) } } }; } apply_to_primitive_floats!(impl_mantissa_and_exponent); ================================================ FILE: malachite-q/src/conversion/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of traits for converting [`Rational`](crate::Rational)s to and from continued /// fractions. pub mod continued_fraction; /// Implementations of traits for working with the digits of [`Rational`](crate::Rational)s. pub mod digits; /// An implementation of the [`From`] trait for converting a [`bool`] to a /// [`Rational`](crate::Rational). pub mod from_bool; /// Functions for converting a primitive float to a [`Rational`](crate::Rational), choosing the /// [`Rational`](crate::Rational) with minimal denominator that rounds to the given float. pub mod from_float_simplest; /// Implementations of the [`From`] trait for converting an /// [`Integer`](malachite_nz::integer::Integer) to a [`Rational`](crate::Rational). pub mod from_integer; /// Implementations of the [`From`] trait for converting a /// [`Integer`](malachite_nz::natural::Natural) to a [`Rational`](crate::Rational). pub mod from_natural; /// Functions for constructing a [`Rational`](crate::Rational) from a numerator and denominator, or /// from a sign, numerator, and denominator. pub mod from_numerator_and_denominator; /// Implementations of traits for converting a primitive float to a [`Rational`](crate::Rational). /// /// The traits are [`TryFrom`] and /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom). /// /// # try_from /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; /// use malachite_q::Rational; /// /// assert_eq!(Rational::try_from(0.0).to_debug_string(), "Ok(0)"); /// assert_eq!(Rational::try_from(1.5).to_debug_string(), "Ok(3/2)"); /// assert_eq!(Rational::try_from(-1.5).to_debug_string(), "Ok(-3/2)"); /// assert_eq!( /// Rational::try_from(0.1f32).to_debug_string(), /// "Ok(13421773/134217728)" /// ); /// assert_eq!( /// Rational::try_from(f32::NAN), /// Err(RationalFromPrimitiveFloatError) /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_q::Rational; /// /// assert_eq!(Rational::convertible_from(0.0), true); /// assert_eq!(Rational::convertible_from(1.5), true); /// assert_eq!(Rational::convertible_from(-1.5), true); /// assert_eq!(Rational::convertible_from(0.1f32), true); /// /// assert_eq!(Rational::convertible_from(f32::NAN), false); /// assert_eq!(Rational::convertible_from(f32::INFINITY), false); /// ``` pub mod from_primitive_float; /// Implementations of the [`From`] trait for converting a primitive integer to a /// [`Rational`](crate::Rational). /// /// # from /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from(123u32), 123); /// assert_eq!(Rational::from(-123i32), -123); /// ``` pub mod from_primitive_int; /// Implementations of traits for converting a [`Rational`](crate::Rational) to an /// [`Integer`](malachite_nz::integer::Integer). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). pub mod integer_from_rational; /// An implementation of [`IsInteger`](malachite_base::num::conversion::traits::IsInteger), a trait /// for determining whether a number is an integer. pub mod is_integer; /// An implementation of /// [`SciMantissaAndExponent`](malachite_base::num::conversion::traits::SciMantissaAndExponent), a /// trait for converting numbers to and from a mantissa-and-exponent representation. /// /// See [`PrimitiveFloat`](malachite_base::num::basic::floats::PrimitiveFloat) for a description of /// the different types of mantissas and exponents. /// /// # sci_mantissa_and_exponent /// ``` /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_base::num::float::NiceFloat; /// use malachite_q::Rational; /// /// let test = |n: Rational, mantissa: f32, exponent: i64| { /// let (m, e) = n.clone().sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(mantissa)); /// assert_eq!(e, exponent); /// /// let (m, e) = (&n).sci_mantissa_and_exponent(); /// assert_eq!(NiceFloat(m), NiceFloat(mantissa)); /// assert_eq!(e, exponent); /// }; /// test(Rational::from(3u32), 1.5, 1); /// test(Rational::from(123u32), 1.921875, 6); /// test(Rational::from_signeds(1, 123), 1.0406504, -7); /// test(Rational::from_signeds(22, 7), 1.5714285, 1); /// ``` /// /// # from_sci_mantissa_and_exponent /// ``` /// use malachite_base::num::conversion::traits::SciMantissaAndExponent; /// use malachite_q::Rational; /// /// let test = |mantissa: f32, exponent: i64, out: Option| { /// assert_eq!( /// <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( /// mantissa, exponent /// ), /// out /// ); /// /// assert_eq!( /// >::from_sci_mantissa_and_exponent( /// mantissa, exponent /// ), /// out /// ); /// }; /// test(1.5, 1, Some(Rational::from(3u32))); /// test(1.51, 1, Some(Rational::from_signeds(6333399, 2097152))); /// test(1.921875, 6, Some(Rational::from(123u32))); /// /// test(2.0, 1, None); /// test(10.0, 1, None); /// test(0.5, 1, None); /// ``` pub mod mantissa_and_exponent; /// Functions for mutating a [`Rational`](crate::Rational)'s numerator and/or denominator in place. pub mod mutate_numerator_and_denominator; /// Implementations of traits for converting a [`Rational`](crate::Rational) to a /// [`Natural`](malachite_nz::natural::Natural). /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). pub mod natural_from_rational; /// Functions and implementations of traits for converting a [`Rational`](crate::Rational) to a /// primitive float. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # rounding_from /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::floats::PrimitiveFloat; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::num::float::NiceFloat; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// let one_third = Rational::from_signeds(1i8, 3); /// assert_eq!( /// f32::rounding_from(one_third.clone(), Floor), /// (0.3333333, Less) /// ); /// assert_eq!( /// f32::rounding_from(one_third, Ceiling), /// (0.33333334, Greater) /// ); /// assert_eq!(f32::rounding_from(Rational::ONE_HALF, Exact), (0.5, Equal)); /// let big = Rational::power_of_2(200u64); /// assert_eq!( /// f32::rounding_from(big.clone(), Down), /// (f32::MAX_FINITE, Less) /// ); /// assert_eq!(f32::rounding_from(big, Up), (f32::INFINITY, Greater)); /// let small = Rational::power_of_2(-200i64); /// let (rounded, o) = f32::rounding_from(small.clone(), Down); /// assert_eq!(NiceFloat(rounded), NiceFloat(0.0)); /// assert_eq!(o, Less); /// assert_eq!( /// f32::rounding_from(small.clone(), Up), /// (f32::MIN_POSITIVE_SUBNORMAL, Greater) /// ); /// let (rounded, o) = f32::rounding_from(-&small, Down); /// assert_eq!(NiceFloat(rounded), NiceFloat(-0.0)); /// assert_eq!(o, Greater); /// assert_eq!( /// f32::rounding_from(-small, Up), /// (-f32::MIN_POSITIVE_SUBNORMAL, Less) /// ); /// /// let one_third = Rational::from_signeds(1i8, 3); /// assert_eq!(f32::rounding_from(&one_third, Floor), (0.3333333, Less)); /// assert_eq!( /// f32::rounding_from(&one_third, Ceiling), /// (0.33333334, Greater) /// ); /// assert_eq!(f32::rounding_from(&Rational::ONE_HALF, Exact), (0.5, Equal)); /// let big = Rational::power_of_2(200u64); /// assert_eq!(f32::rounding_from(&big, Down), (f32::MAX_FINITE, Less)); /// assert_eq!(f32::rounding_from(&big, Up), (f32::INFINITY, Greater)); /// let small = Rational::power_of_2(-200i64); /// let (rounded, o) = f32::rounding_from(small.clone(), Down); /// assert_eq!(NiceFloat(rounded), NiceFloat(0.0)); /// assert_eq!(o, Less); /// assert_eq!( /// f32::rounding_from(&small, Up), /// (f32::MIN_POSITIVE_SUBNORMAL, Greater) /// ); /// let (rounded, o) = f32::rounding_from(-&small, Down); /// assert_eq!(NiceFloat(rounded), NiceFloat(-0.0)); /// assert_eq!(o, Greater); /// assert_eq!( /// f32::rounding_from(&-small, Up), /// (-f32::MIN_POSITIVE_SUBNORMAL, Less) /// ); /// ``` /// /// # try_from /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; /// use malachite_q::Rational; /// /// assert_eq!( /// f32::try_from(Rational::from_signeds(1i8, 3)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!(f32::try_from(Rational::ONE_HALF), Ok(0.5)); /// assert_eq!( /// f32::try_from(Rational::power_of_2(200u64)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// f32::try_from(Rational::power_of_2(-200i64)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// f32::try_from(-Rational::power_of_2(-200i64)), /// Err(FloatConversionError::Inexact) /// ); /// /// assert_eq!( /// f32::try_from(&Rational::from_signeds(1i8, 3)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!(f32::try_from(&Rational::ONE_HALF), Ok(0.5)); /// assert_eq!( /// f32::try_from(&Rational::power_of_2(200u64)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// f32::try_from(&Rational::power_of_2(-200i64)), /// Err(FloatConversionError::Inexact) /// ); /// assert_eq!( /// f32::try_from(&-Rational::power_of_2(-200i64)), /// Err(FloatConversionError::Inexact) /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::basic::traits::OneHalf; /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_q::Rational; /// /// assert_eq!(f32::convertible_from(Rational::from_signeds(1i8, 3)), false); /// assert_eq!(f32::convertible_from(Rational::ONE_HALF), true); /// assert_eq!(f32::convertible_from(Rational::power_of_2(200u64)), false); /// assert_eq!(f32::convertible_from(Rational::power_of_2(-200i64)), false); /// assert_eq!(f32::convertible_from(-Rational::power_of_2(-200i64)), false); /// /// assert_eq!( /// f32::convertible_from(&Rational::from_signeds(1i8, 3)), /// false /// ); /// assert_eq!(f32::convertible_from(&Rational::ONE_HALF), true); /// assert_eq!(f32::convertible_from(&Rational::power_of_2(200u64)), false); /// assert_eq!(f32::convertible_from(&Rational::power_of_2(-200i64)), false); /// assert_eq!( /// f32::convertible_from(&-Rational::power_of_2(-200i64)), /// false /// ); /// ``` pub mod primitive_float_from_rational; /// Implementations of traits for converting a [`Rational`](crate::Rational) to a primitive integer. /// /// The traits are [`TryFrom`], /// [`ConvertibleFrom`](malachite_base::num::conversion::traits::ConvertibleFrom), and /// [`RoundingFrom`](malachite_base::num::conversion::traits::RoundingFrom). /// /// # try_from /// ``` /// use malachite_q::conversion::primitive_int_from_rational::{ /// SignedFromRationalError, UnsignedFromRationalError, /// }; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(u32::try_from(&Rational::from(123)).unwrap(), 123); /// assert_eq!( /// u32::try_from(&Rational::from(-123)), /// Err(UnsignedFromRationalError) /// ); /// assert_eq!( /// u32::try_from(&Rational::from_str("1000000000000").unwrap()), /// Err(UnsignedFromRationalError) /// ); /// assert_eq!( /// u32::try_from(&Rational::from_signeds(22, 7)), /// Err(UnsignedFromRationalError) /// ); /// /// assert_eq!(i32::try_from(&Rational::from(123)).unwrap(), 123); /// assert_eq!(i32::try_from(&Rational::from(-123)).unwrap(), -123); /// assert_eq!( /// i32::try_from(&Rational::from_str("-1000000000000").unwrap()), /// Err(SignedFromRationalError) /// ); /// assert_eq!( /// i32::try_from(&Rational::from_str("1000000000000").unwrap()), /// Err(SignedFromRationalError) /// ); /// assert_eq!( /// i32::try_from(&Rational::from_signeds(22, 7)), /// Err(SignedFromRationalError) /// ); /// ``` /// /// # convertible_from /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(u32::convertible_from(&Rational::from(123)), true); /// assert_eq!(u32::convertible_from(&Rational::from(-123)), false); /// assert_eq!( /// u32::convertible_from(&Rational::from_str("1000000000000").unwrap()), /// false /// ); /// assert_eq!(u32::convertible_from(&Rational::from_signeds(22, 7)), false); /// /// assert_eq!(i32::convertible_from(&Rational::from(123)), true); /// assert_eq!(i32::convertible_from(&Rational::from(-123)), true); /// assert_eq!( /// i32::convertible_from(&Rational::from_str("-1000000000000").unwrap()), /// false /// ); /// assert_eq!( /// i32::convertible_from(&Rational::from_str("1000000000000").unwrap()), /// false /// ); /// assert_eq!(i32::convertible_from(&Rational::from_signeds(22, 7)), false); /// ``` /// /// # rounding_from /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// use std::cmp::Ordering::*; /// /// assert_eq!( /// u32::rounding_from(&Rational::from(123), Exact), /// (123, Equal) /// ); /// /// assert_eq!( /// u32::rounding_from(&Rational::from_signeds(22, 7), Floor), /// (3, Less) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from_signeds(22, 7), Down), /// (3, Less) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from_signeds(22, 7), Ceiling), /// (4, Greater) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from_signeds(22, 7), Up), /// (4, Greater) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from_signeds(22, 7), Nearest), /// (3, Less) /// ); /// /// assert_eq!( /// u32::rounding_from(&Rational::from(-123), Down), /// (0, Greater) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from(-123), Ceiling), /// (0, Greater) /// ); /// assert_eq!( /// u32::rounding_from(&Rational::from(-123), Nearest), /// (0, Greater) /// ); /// /// assert_eq!(u8::rounding_from(&Rational::from(1000), Down), (255, Less)); /// assert_eq!(u8::rounding_from(&Rational::from(1000), Floor), (255, Less)); /// assert_eq!( /// u8::rounding_from(&Rational::from(1000), Nearest), /// (255, Less) /// ); /// /// assert_eq!( /// i32::rounding_from(&Rational::from(-123), Exact), /// (-123, Equal) /// ); /// /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(22, 7), Floor), /// (3, Less) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(22, 7), Down), /// (3, Less) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(22, 7), Ceiling), /// (4, Greater) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(22, 7), Up), /// (4, Greater) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(22, 7), Nearest), /// (3, Less) /// ); /// /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(-22, 7), Floor), /// (-4, Less) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(-22, 7), Down), /// (-3, Greater) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(-22, 7), Ceiling), /// (-3, Greater) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(-22, 7), Up), /// (-4, Less) /// ); /// assert_eq!( /// i32::rounding_from(&Rational::from_signeds(-22, 7), Nearest), /// (-3, Greater) /// ); /// /// assert_eq!( /// i8::rounding_from(&Rational::from(-1000), Down), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(&Rational::from(-1000), Ceiling), /// (-128, Greater) /// ); /// assert_eq!( /// i8::rounding_from(&Rational::from(-1000), Nearest), /// (-128, Greater) /// ); /// /// assert_eq!(i8::rounding_from(&Rational::from(1000), Down), (127, Less)); /// assert_eq!(i8::rounding_from(&Rational::from(1000), Floor), (127, Less)); /// assert_eq!( /// i8::rounding_from(&Rational::from(1000), Nearest), /// (127, Less) /// ); /// ``` pub mod primitive_int_from_rational; /// Implementations of traits for converting [`Rational`](crate::Rational)s to and from [`String`]s. pub mod string; /// Functions for extracting or referencing the numerator and/or denominator of a /// [`Rational`](crate::Rational). pub mod to_numerator_and_denominator; /// Various traits for performing arithmetic operations on numbers. pub mod traits; ================================================ FILE: malachite-q/src/conversion/mutate_numerator_and_denominator.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{DivExactAssign, Gcd}; use malachite_nz::natural::Natural; impl Rational { /// Mutates the numerator of a [`Rational`] using a provided closure, and then returns whatever /// the closure returns. /// /// After the closure executes, this function reduces the [`Rational`]. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let mut q = Rational::from_signeds(22, 7); /// let ret = q.mutate_numerator(|x| { /// *x -= Natural::ONE; /// true /// }); /// assert_eq!(q, 3); /// assert_eq!(ret, true); /// ``` pub fn mutate_numerator T, T>(&mut self, f: F) -> T { let out = f(&mut self.numerator); let gcd = (&self.numerator).gcd(&self.denominator); self.numerator.div_exact_assign(&gcd); self.denominator.div_exact_assign(gcd); if !self.sign && self.numerator == 0 { self.sign = true; } out } /// Mutates the denominator of a [`Rational`] using a provided closure, and then returns /// whatever the closure returns. /// /// After the closure executes, this function reduces the [`Rational`]. /// /// # Panics /// Panics if the closure sets the denominator to zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let mut q = Rational::from_signeds(22, 7); /// let ret = q.mutate_denominator(|x| { /// *x -= Natural::ONE; /// true /// }); /// assert_eq!(q.to_string(), "11/3"); /// assert_eq!(ret, true); /// ``` pub fn mutate_denominator T, T>(&mut self, f: F) -> T { let out = f(&mut self.denominator); assert_ne!(self.denominator, 0); let gcd = (&self.numerator).gcd(&self.denominator); self.numerator.div_exact_assign(&gcd); self.denominator.div_exact_assign(gcd); out } /// Mutates the numerator and denominator of a [`Rational`] using a provided closure, and then /// returns whatever the closure returns. /// /// After the closure executes, this function reduces the [`Rational`]. /// /// # Panics /// Panics if the closure sets the denominator to zero. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::One; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// let mut q = Rational::from_signeds(22, 7); /// let ret = q.mutate_numerator_and_denominator(|x, y| { /// *x -= Natural::ONE; /// *y -= Natural::ONE; /// true /// }); /// assert_eq!(q.to_string(), "7/2"); /// assert_eq!(ret, true); /// ``` pub fn mutate_numerator_and_denominator T, T>( &mut self, f: F, ) -> T { let out = f(&mut self.numerator, &mut self.denominator); assert_ne!(self.denominator, 0); let gcd = (&self.numerator).gcd(&self.denominator); self.numerator.div_exact_assign(&gcd); self.denominator.div_exact_assign(gcd); if !self.sign && self.numerator == 0 { self.sign = true; } out } } ================================================ FILE: malachite-q/src/conversion/natural_from_rational.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::DivRound; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::natural::Natural; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct NaturalFromRationalError; impl TryFrom for Natural { type Error = NaturalFromRationalError; /// Converts a [`Rational`] to a [`Natural`], taking the [`Rational`] by value. If the /// [`Rational`] is negative or not an integer, an error is returned. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::conversion::natural_from_rational::NaturalFromRationalError; /// use malachite_q::Rational; /// /// assert_eq!(Natural::try_from(Rational::from(123)).unwrap(), 123); /// assert_eq!( /// Natural::try_from(Rational::from(-123)), /// Err(NaturalFromRationalError) /// ); /// assert_eq!( /// Natural::try_from(Rational::from_signeds(22, 7)), /// Err(NaturalFromRationalError) /// ); /// ``` fn try_from(x: Rational) -> Result { if x.sign && x.denominator == 1u32 { Ok(x.numerator) } else { Err(NaturalFromRationalError) } } } impl TryFrom<&Rational> for Natural { type Error = NaturalFromRationalError; /// Converts a [`Rational`] to a [`Natural`], taking the [`Rational`] by reference. If the /// [`Rational`] is negative or not an integer, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Examples /// ``` /// use malachite_nz::natural::Natural; /// use malachite_q::conversion::natural_from_rational::NaturalFromRationalError; /// use malachite_q::Rational; /// /// assert_eq!(Natural::try_from(&Rational::from(123)).unwrap(), 123); /// assert_eq!( /// Natural::try_from(&Rational::from(-123)), /// Err(NaturalFromRationalError) /// ); /// assert_eq!( /// Natural::try_from(&Rational::from_signeds(22, 7)), /// Err(NaturalFromRationalError) /// ); /// ``` fn try_from(x: &Rational) -> Result { if x.sign && x.denominator == 1u32 { Ok(x.numerator.clone()) } else { Err(NaturalFromRationalError) } } } impl ConvertibleFrom<&Rational> for Natural { /// Determines whether a [`Rational`] can be converted to a [`Natural`] (when the [`Rational`] /// is non-negative and an integer), taking the [`Rational`] by reference. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::ConvertibleFrom; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!(Natural::convertible_from(&Rational::from(123)), true); /// assert_eq!(Natural::convertible_from(&Rational::from(-123)), false); /// assert_eq!( /// Natural::convertible_from(&Rational::from_signeds(22, 7)), /// false /// ); /// ``` #[inline] fn convertible_from(x: &Rational) -> bool { x.sign && x.denominator == 1u32 } } impl RoundingFrom for Natural { /// Converts a [`Rational`] to a [`Natural`], using a specified [`RoundingMode`] and taking the /// [`Rational`] by value. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If the [`Rational`] is negative, then it will be rounded to zero when the [`RoundingMode`] /// is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`, or if the [`Rational`] is /// less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Natural::rounding_from(Rational::from(123), Exact).to_debug_string(), /// "(123, Equal)" /// ); /// /// assert_eq!( /// Natural::rounding_from(Rational::from_signeds(22, 7), Floor).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from_signeds(22, 7), Down).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from_signeds(22, 7), Ceiling).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from_signeds(22, 7), Up).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from_signeds(22, 7), Nearest).to_debug_string(), /// "(3, Less)" /// ); /// /// assert_eq!( /// Natural::rounding_from(Rational::from(-123), Down).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from(-123), Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(Rational::from(-123), Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` fn rounding_from(x: Rational, rm: RoundingMode) -> (Self, Ordering) { if x.sign { x.numerator.div_round(x.denominator, rm) } else if rm == Down || rm == Ceiling || rm == Nearest { (Self::ZERO, Greater) } else { panic!("Cannot round negative Rational to Natural using RoundingMode {rm}"); } } } impl RoundingFrom<&Rational> for Natural { /// Converts a [`Rational`] to a [`Natural`], using a specified [`RoundingMode`] and taking the /// [`Rational`] by reference. An [`Ordering`] is also returned, indicating whether the returned /// value is less than, equal to, or greater than the original value. /// /// If the [`Rational`] is negative, then it will be rounded to zero when the [`RoundingMode`] /// is `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `x.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`, or if the [`Rational`] is /// less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::traits::RoundingFrom; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::Rational; /// /// assert_eq!( /// Natural::rounding_from(&Rational::from(123), Exact).to_debug_string(), /// "(123, Equal)" /// ); /// /// assert_eq!( /// Natural::rounding_from(&Rational::from_signeds(22, 7), Floor).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from_signeds(22, 7), Down).to_debug_string(), /// "(3, Less)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from_signeds(22, 7), Ceiling).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from_signeds(22, 7), Up).to_debug_string(), /// "(4, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from_signeds(22, 7), Nearest).to_debug_string(), /// "(3, Less)" /// ); /// /// assert_eq!( /// Natural::rounding_from(&Rational::from(-123), Down).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from(-123), Ceiling).to_debug_string(), /// "(0, Greater)" /// ); /// assert_eq!( /// Natural::rounding_from(&Rational::from(-123), Nearest).to_debug_string(), /// "(0, Greater)" /// ); /// ``` fn rounding_from(x: &Rational, rm: RoundingMode) -> (Self, Ordering) { if x.sign { (&x.numerator).div_round(&x.denominator, rm) } else if rm == Down || rm == Ceiling || rm == Nearest { (Self::ZERO, Greater) } else { panic!("Cannot round negative Rational to Natural using RoundingMode {rm}"); } } } ================================================ FILE: malachite-q/src/conversion/primitive_float_from_rational.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use malachite_base::num::arithmetic::traits::{ DivRound, DivisibleByPowerOf2, IsPowerOf2, NegAssign, }; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, RawMantissaAndExponent, RoundingFrom, SciMantissaAndExponent, WrappingFrom, }; use malachite_base::num::logic::traits::{BitAccess, SignificantBits}; use malachite_base::rounding_modes::RoundingMode::{self, *}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum FloatConversionError { Inexact, Overflow, Underflow, } fn abs_is_neg_power_of_2(x: &Rational) -> bool { x.numerator == 1u32 && x.denominator.is_power_of_2() } macro_rules! float_impls { ($f: ident) => { impl RoundingFrom for $f { /// Converts a [`Rational`] to a value of a primitive float according to a specified /// [`RoundingMode`], taking the [`Rational`] by value. /// /// - If the rounding mode is `Floor`, the largest float less than or equal to the /// [`Rational`] is returned. If the [`Rational`] is greater than the maximum finite /// float, then the maximum finite float is returned. If it is smaller than the /// minimum finite float, then $-\infty$ is returned. If it is between zero and the /// minimum positive float, then positive zero is returned. /// - If the rounding mode is `Ceiling`, the smallest float greater than or equal to the /// [`Rational`] is returned. If the [`Rational`] is greater than the maximum finite /// float, then $\infty$ is returned. If it is smaller than the minimum finite float, /// then the minimum finite float is returned. If it is between zero and the maximum /// negative float, then negative zero is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the /// [`Rational`] is non-negative and as with `Ceiling` if the [`Rational`] is /// negative. If the [`Rational`] is between the maximum negative float and the /// minimum positive float, then positive zero is returned when the [`Rational`] is /// non-negative and negative zero otherwise. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the /// [`Rational`] is non-negative and as with `Floor` if the [`Rational`] is negative. /// Positive zero is only returned when the [`Rational`] is zero, and negative zero is /// never returned. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If the /// [`Rational`] is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. If the [`Rational`] is /// greater than the maximum finite float, then $\infty$ is returned. If the /// [`Rational`] is smaller than the minimum finite float, then $-\infty$ is returned. /// If the [`Rational`] is closer to zero than to any other float (or if there is a /// tie between zero and another float), then positive or negative zero is returned, /// depending on the [`Rational`]'s sign. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the rounding mode is `Exact` and `value` cannot be represented exactly. /// /// # Examples /// See [here](super::primitive_float_from_rational#rounding_from). fn rounding_from(mut value: Rational, mut rm: RoundingMode) -> ($f, Ordering) { if value == 0u32 { (0.0, Equal) } else { let sign = value.sign; if !sign { rm.neg_assign(); } let mut exponent = value.floor_log_base_2_abs(); let (f, o) = if exponent > $f::MAX_EXPONENT { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => ($f::MAX_FINITE, Less), _ => ($f::INFINITY, Greater), } } else if exponent >= $f::MIN_NORMAL_EXPONENT { value >>= exponent - i64::wrapping_from($f::MANTISSA_WIDTH); let (n, d) = value.into_numerator_and_denominator(); let (mut mantissa, o) = n.div_round(d, rm); let mut bits = mantissa.significant_bits(); let mut done = false; if bits > $f::MANTISSA_WIDTH + 1 { if exponent == $f::MAX_EXPONENT { done = true; } else { bits -= 1; mantissa >>= 1; // lsb is zero exponent += 1; } } if done { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => ($f::MAX_FINITE, Less), _ => ($f::INFINITY, Greater), } } else { assert_eq!(bits, $f::MANTISSA_WIDTH + 1); mantissa.clear_bit($f::MANTISSA_WIDTH); ( $f::from_raw_mantissa_and_exponent( u64::exact_from(&mantissa), u64::exact_from(exponent + $f::MAX_EXPONENT), ), o, ) } } else if exponent >= $f::MIN_EXPONENT { let target_width = u64::wrapping_from(exponent - $f::MIN_EXPONENT + 1); value >>= $f::MIN_EXPONENT; let (n, d) = value.into_numerator_and_denominator(); let (mantissa, o) = n.div_round(d, rm); ( if mantissa.significant_bits() > target_width && exponent == $f::MIN_NORMAL_EXPONENT - 1 { $f::MIN_POSITIVE_NORMAL } else { $f::from_raw_mantissa_and_exponent(u64::exact_from(&mantissa), 0) }, o, ) } else { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => (0.0, Less), Nearest => { if exponent == $f::MIN_EXPONENT - 1 && !abs_is_neg_power_of_2(&value) { ($f::MIN_POSITIVE_SUBNORMAL, Greater) } else { (0.0, Less) } } _ => ($f::MIN_POSITIVE_SUBNORMAL, Greater), } }; if sign { (f, o) } else { (-f, o.reverse()) } } } } impl TryFrom for $f { type Error = FloatConversionError; /// Converts a [`Rational`] to a primitive float, taking the [`Rational`] by value. If /// the input isn't exactly equal to any float, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(1)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_rational#try_from). fn try_from(value: Rational) -> Result<$f, Self::Error> { if value == 0 { Ok(0.0) } else { let sign = value.sign; let (mantissa, exponent, _) = value .sci_mantissa_and_exponent_round(Exact) .ok_or(FloatConversionError::Inexact)?; let f = $f::from_sci_mantissa_and_exponent(mantissa, i64::exact_from(exponent)) .ok_or(FloatConversionError::Inexact); if sign { f } else { f.map(|x| -x) } } } } impl ConvertibleFrom for $f { /// Determines whether a [`Rational`] can be exactly converted to a primitive float, /// taking the [`Rational`] by value. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_rational#convertible_from). fn convertible_from(value: Rational) -> bool { if value == 0 { true } else { if let Some((mantissa, exponent, _)) = value.sci_mantissa_and_exponent_round::<$f>(Exact) { let exponent = i64::exact_from(exponent); if !($f::MIN_EXPONENT..=$f::MAX_EXPONENT).contains(&exponent) { return false; } let (orig_mantissa, orig_exponent) = mantissa.raw_mantissa_and_exponent(); orig_exponent == u64::wrapping_from($f::MAX_EXPONENT) && exponent >= $f::MIN_NORMAL_EXPONENT || orig_mantissa.divisible_by_power_of_2(u64::wrapping_from( $f::MIN_NORMAL_EXPONENT - exponent, )) } else { false } } } } impl RoundingFrom<&Rational> for $f { /// Converts a [`Rational`] to a value of a primitive float according to a specified /// [`RoundingMode`], taking the [`Rational`] by reference. /// /// - If the rounding mode is `Floor`, the largest float less than or equal to the /// [`Rational`] is returned. If the [`Rational`] is greater than the maximum finite /// float, then the maximum finite float is returned. If it is smaller than the /// minimum finite float, then $-\infty$ is returned. If it is between zero and the /// minimum positive float, then positive zero is returned. /// - If the rounding mode is `Ceiling`, the smallest float greater than or equal to the /// [`Rational`] is returned. If the [`Rational`] is greater than the maximum finite /// float, then $\infty$is returned. If it is smaller than the minimum finite float, /// then the minimum finite float is returned. If it is between zero and the maximum /// negative float, then negative zero is returned. /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor` if the /// [`Rational`] is non-negative and as with `Ceiling` if the [`Rational`] is /// negative. If the [`Rational`] is between the maximum negative float and the /// minimum positive float, then positive zero is returned when the [`Rational`] is /// non-negative and negative zero otherwise. /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling` if the /// [`Rational`] is non-negative and as with `Floor` if the [`Rational`] is negative. /// Positive zero is only returned when the [`Rational`] is zero, and negative zero is /// never returned. /// - If the rounding mode is `Nearest`, then the nearest float is returned. If the /// [`Rational`] is exactly between two floats, the float with the zero /// least-significant bit in its representation is selected. If the [`Rational`] is /// greater than the maximum finite float, then $\infty$ is returned. If the /// [`Rational`] is smaller than the minimum finite float, then $-\infty$ is returned. /// If the [`Rational`] is closer to zero than to any float (or if there is a tie /// between zero and another float), then positive or negative zero is returned, /// depending on the [`Rational`]'s sign. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the rounding mode is `Exact` and `value` cannot be represented exactly. /// /// # Examples /// See [here](super::primitive_float_from_rational#rounding_from). fn rounding_from(value: &Rational, mut rm: RoundingMode) -> ($f, Ordering) { if *value == 0u32 { (0.0, Equal) } else { if !value.sign { rm.neg_assign(); } let mut exponent = value.floor_log_base_2_abs(); let (f, o) = if exponent > $f::MAX_EXPONENT { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => ($f::MAX_FINITE, Less), _ => ($f::INFINITY, Greater), } } else if exponent >= $f::MIN_NORMAL_EXPONENT { let x = value >> exponent - i64::wrapping_from($f::MANTISSA_WIDTH); let (n, d) = x.into_numerator_and_denominator(); let (mut mantissa, o) = n.div_round(d, rm); let mut bits = mantissa.significant_bits(); let mut done = false; if bits > $f::MANTISSA_WIDTH + 1 { if exponent == $f::MAX_EXPONENT { done = true; } else { bits -= 1; mantissa >>= 1; // lsb is zero exponent += 1; } } if done { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => ($f::MAX_FINITE, Less), _ => ($f::INFINITY, Greater), } } else { assert_eq!(bits, $f::MANTISSA_WIDTH + 1); mantissa.clear_bit($f::MANTISSA_WIDTH); ( $f::from_raw_mantissa_and_exponent( u64::exact_from(&mantissa), u64::exact_from(exponent + $f::MAX_EXPONENT), ), o, ) } } else if exponent >= $f::MIN_EXPONENT { let target_width = u64::wrapping_from(exponent - $f::MIN_EXPONENT + 1); let x = value >> $f::MIN_EXPONENT; let (n, d) = x.into_numerator_and_denominator(); let (mantissa, o) = n.div_round(d, rm); ( if mantissa.significant_bits() > target_width && exponent == $f::MIN_NORMAL_EXPONENT - 1 { $f::MIN_POSITIVE_NORMAL } else { $f::from_raw_mantissa_and_exponent(u64::exact_from(&mantissa), 0) }, o, ) } else { match rm { Exact => { panic!("Value cannot be represented exactly as a float") } Floor | Down => (0.0, Less), Nearest => { if exponent == $f::MIN_EXPONENT - 1 && !abs_is_neg_power_of_2(&value) { ($f::MIN_POSITIVE_SUBNORMAL, Greater) } else { (0.0, Less) } } _ => ($f::MIN_POSITIVE_SUBNORMAL, Greater), } }; if value.sign { (f, o) } else { (-f, o.reverse()) } } } } impl TryFrom<&Rational> for $f { type Error = FloatConversionError; /// Converts a [`Rational`] to a primitive float, taking the [`Rational`] by reference. /// If the input isn't exactly equal to any float, an error is returned. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_rational#try_from). fn try_from(value: &Rational) -> Result<$f, Self::Error> { if *value == 0 { Ok(0.0) } else { let (mantissa, exponent, _) = value .sci_mantissa_and_exponent_round_ref(Exact) .ok_or(FloatConversionError::Inexact)?; let f = $f::from_sci_mantissa_and_exponent(mantissa, i64::exact_from(exponent)) .ok_or(FloatConversionError::Inexact); if value.sign { f } else { f.map(|x| -x) } } } } impl ConvertibleFrom<&Rational> for $f { /// Determines whether a [`Rational`] can be exactly converted to a primitive float, /// taking the [`Rational`] by reference. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Examples /// See [here](super::primitive_float_from_rational#convertible_from). fn convertible_from(value: &Rational) -> bool { if *value == 0 { true } else { if let Some((mantissa, exponent, _)) = value.sci_mantissa_and_exponent_round_ref::<$f>(Exact) { let exponent = i64::exact_from(exponent); if !($f::MIN_EXPONENT..=$f::MAX_EXPONENT).contains(&exponent) { return false; } let (orig_mantissa, orig_exponent) = mantissa.raw_mantissa_and_exponent(); orig_exponent == u64::wrapping_from($f::MAX_EXPONENT) && exponent >= $f::MIN_NORMAL_EXPONENT || orig_mantissa.divisible_by_power_of_2(u64::wrapping_from( $f::MIN_NORMAL_EXPONENT - exponent, )) } else { false } } } } }; } apply_to_primitive_floats!(float_impls); ================================================ FILE: malachite-q/src/conversion/primitive_int_from_rational.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::cmp::Ordering::{self, *}; use core::ops::Neg; use malachite_base::comparison::traits::{Max, Min}; use malachite_base::named::Named; use malachite_base::num::arithmetic::traits::{DivRound, DivisibleByPowerOf2}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct UnsignedFromRationalError; fn try_from_unsigned<'a, T: TryFrom<&'a Natural>>( x: &'a Rational, ) -> Result { if x.sign && x.denominator == 1u32 { T::try_from(&x.numerator).map_err(|_| UnsignedFromRationalError) } else { Err(UnsignedFromRationalError) } } fn convertible_from_unsigned ConvertibleFrom<&'a Natural>>(x: &Rational) -> bool { x.sign && x.denominator == 1u32 && T::convertible_from(&x.numerator) } #[allow(clippy::let_and_return)] // n doesn't live long enough for a direct return fn rounding_from_unsigned<'a, T: for<'b> TryFrom<&'b Natural> + Max + Named + Zero>( x: &'a Rational, rm: RoundingMode, ) -> (T, Ordering) { if x.sign { let (n, o) = (&x.numerator).div_round(&x.denominator, rm); let out = if let Ok(q) = T::try_from(&n) { (q, o) } else if rm == Down || rm == Floor || rm == Nearest { (T::MAX, Less) } else { panic!( "Rational is too large to round to {} using RoundingMode {}", rm, T::NAME ); }; out } else if rm == Down || rm == Ceiling || rm == Nearest { (T::ZERO, Greater) } else { panic!( "Cannot round negative Rational to {} using RoundingMode {}", rm, T::NAME ); } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct SignedFromRationalError; #[allow(clippy::trait_duplication_in_bounds)] fn try_from_signed< 'a, U: WrappingFrom<&'a Natural>, S: Neg + PrimitiveInt + WrappingFrom + WrappingFrom<&'a Natural>, >( x: &'a Rational, ) -> Result { if x.denominator != 1u32 { return Err(SignedFromRationalError); } match *x { Rational { sign: true, ref numerator, .. } => { if numerator.significant_bits() < S::WIDTH { Ok(S::wrapping_from(numerator)) } else { Err(SignedFromRationalError) } } Rational { sign: false, ref numerator, .. } => { let significant_bits = numerator.significant_bits(); if significant_bits < S::WIDTH || significant_bits == S::WIDTH && numerator.divisible_by_power_of_2(S::WIDTH - 1) { Ok(S::wrapping_from(U::wrapping_from(numerator)).wrapping_neg()) } else { Err(SignedFromRationalError) } } } } fn convertible_from_signed(x: &Rational) -> bool { if x.denominator != 1u32 { return false; } match *x { Rational { sign: true, ref numerator, .. } => numerator.significant_bits() < T::WIDTH, Rational { sign: false, ref numerator, .. } => { let significant_bits = numerator.significant_bits(); significant_bits < T::WIDTH || significant_bits == T::WIDTH && numerator.divisible_by_power_of_2(T::WIDTH - 1) } } } fn rounding_from_signed<'a, T: Max + Min + Named + for<'b> WrappingFrom<&'b Integer>>( x: &'a Rational, rm: RoundingMode, ) -> (T, Ordering) where Integer: PartialOrd, { let (i, o) = Integer::rounding_from(x, rm); if i > T::MAX { if rm == Down || rm == Floor || rm == Nearest { (T::MAX, Less) } else { panic!( "Rational is too large to round to {} using RoundingMode {}", rm, T::NAME ); } } else if i < T::MIN { if rm == Down || rm == Ceiling || rm == Nearest { (T::MIN, Greater) } else { panic!( "Rational is too small to round to {} using RoundingMode {}", rm, T::NAME ); } } else { (T::wrapping_from(&i), o) } } macro_rules! impl_from_unsigned { ($u: ident) => { impl<'a> TryFrom<&'a Rational> for $u { type Error = UnsignedFromRationalError; /// Converts a [`Rational`] to an unsigned primitive integer, returning an error if the /// [`Rational`] cannot be represented. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_rational#try_from). #[inline] fn try_from(value: &Rational) -> Result<$u, UnsignedFromRationalError> { try_from_unsigned(value) } } impl<'a> ConvertibleFrom<&'a Rational> for $u { /// Determines whether a [`Rational`] can be converted to an unsigned primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_rational#convertible_from). #[inline] fn convertible_from(value: &Rational) -> bool { convertible_from_unsigned::<$u>(value) } } impl<'a> RoundingFrom<&'a Rational> for $u { /// Converts a [`Rational`] to an unsigned integer, using a specified [`RoundingMode`]. /// /// If the [`Rational`] is negative, then it will be rounded to zero when `rm` is /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic. /// /// If the [`Rational`] is larger than the maximum value of the unsigned type, then it /// will be rounded to the maximum value when `rm` is `Floor`, `Down`, or `Nearest`. /// Otherwise, this function will panic. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`, if the /// [`Rational`] is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, or /// if the [`Rational`] is greater than `T::MAX` and `rm` is not `Down`, `Floor`, or /// `Nearest`. /// /// # Examples /// See [here](super::primitive_int_from_rational#rounding_from). #[inline] fn rounding_from(value: &Rational, rm: RoundingMode) -> ($u, Ordering) { rounding_from_unsigned(value, rm) } } }; } apply_to_unsigneds!(impl_from_unsigned); macro_rules! impl_from_signed { ($u: ident, $s: ident) => { impl<'a> TryFrom<&'a Rational> for $s { type Error = SignedFromRationalError; /// Converts a [`Rational`] to a signed primitive integer, returning an error if the /// [`Rational`] cannot be represented. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_rational#try_from). #[inline] fn try_from(value: &Rational) -> Result<$s, SignedFromRationalError> { try_from_signed::<$u, $s>(value) } } impl<'a> ConvertibleFrom<&'a Rational> for $s { /// Determines whether a [`Rational`] can be converted to a signed primitive integer. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// See [here](super::primitive_int_from_rational#convertible_from). #[inline] fn convertible_from(value: &Rational) -> bool { convertible_from_signed::<$s>(value) } } impl<'a> RoundingFrom<&'a Rational> for $s { /// Converts a [`Rational`] to a signed integer, using a specified [`RoundingMode`]. /// /// If the [`Rational`] is smaller than the minimum value of the unsigned type, then it /// will be rounded to the minimum value when `rm` is `Ceiling`, `Down`, or `Nearest`. /// Otherwise, this function will panic. /// /// If the [`Rational`] is larger than the maximum value of the unsigned type, then it /// will be rounded to the maximum value when `rm` is `Floor`, `Down`, or `Nearest`. /// Otherwise, this function will panic. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `value.significant_bits()`. /// /// # Panics /// Panics if the [`Rational`] is not an integer and `rm` is `Exact`, if the /// [`Rational`] is less than `T::MIN` and `rm` is not `Down`, `Ceiling`, or `Nearest`, /// or if the [`Rational`] is greater than `T::MAX` and `rm` is not `Down`, `Floor`, or /// `Nearest`. /// /// # Examples /// See [here](super::primitive_int_from_rational#rounding_from). #[inline] fn rounding_from(value: &Rational, rm: RoundingMode) -> ($s, Ordering) { rounding_from_signed(value, rm) } } }; } apply_to_unsigned_signed_pairs!(impl_from_signed); ================================================ FILE: malachite-q/src/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::traits::SimplestRationalInInterval; use malachite_base::num::arithmetic::traits::Pow; use malachite_base::num::conversion::string::from_sci_string::preprocess_sci_string; use malachite_base::num::conversion::string::options::FromSciStringOptions; use malachite_base::num::conversion::traits::FromSciString; use malachite_nz::integer::Integer; use malachite_nz::natural::conversion::string::from_sci_string::FromSciStringHelper; impl FromSciString for Rational { /// Converts a string, possibly in scientfic notation, to a [`Rational`]. /// /// Use [`FromSciStringOptions`] to specify the base (from 2 to 36, inclusive). The rounding /// mode option is ignored. /// /// If the base is greater than 10, the higher digits are represented by the letters `'a'` /// through `'z'` or `'A'` through `'Z'`; the case doesn't matter and doesn't need to be /// consistent. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. If the base is /// 15 or greater, an ambiguity arises where it may not be clear whether `'e'` is a digit or an /// exponent indicator. To resolve this ambiguity, always use a `'+'` or `'-'` sign after the /// exponent indicator when the base is 15 or greater. /// /// The exponent itself is always parsed using base 10. /// /// Decimal (or other-base) points are allowed. /// /// If the string is unparseable, `None` is returned. /// /// This function is very literal; given `"0.333"`, it will return $333/1000$ rather than $1/3$. /// If you'd prefer that it return $1/3$, consider using /// [`from_sci_string_simplest`](Rational::from_sci_string_simplest) instead. However, that /// function has its quirks too: given `"0.1"`, it will not return $1/10$ (see its documentation /// for an explanation of this behavior). This function _does_ return $1/10$. /// /// # Worst-case complexity /// $T(n, m) = O(m^n n \log m (\log n + \log\log m))$ /// /// $M(n, m) = O(m^n n \log m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `options.base`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::FromSciStringOptions; /// use malachite_base::num::conversion::traits::FromSciString; /// use malachite_q::Rational; /// /// assert_eq!(Rational::from_sci_string("123").unwrap(), 123); /// assert_eq!( /// Rational::from_sci_string("0.1").unwrap().to_string(), /// "1/10" /// ); /// assert_eq!( /// Rational::from_sci_string("0.10").unwrap().to_string(), /// "1/10" /// ); /// assert_eq!( /// Rational::from_sci_string("0.333").unwrap().to_string(), /// "333/1000" /// ); /// assert_eq!(Rational::from_sci_string("1.2e5").unwrap(), 120000); /// assert_eq!( /// Rational::from_sci_string("1.2e-5").unwrap().to_string(), /// "3/250000" /// ); /// /// let mut options = FromSciStringOptions::default(); /// options.set_base(16); /// assert_eq!( /// Rational::from_sci_string_with_options("ff", options).unwrap(), /// 255 /// ); /// assert_eq!( /// Rational::from_sci_string_with_options("ffE+5", options).unwrap(), /// 267386880 /// ); /// assert_eq!( /// Rational::from_sci_string_with_options("ffE-5", options) /// .unwrap() /// .to_string(), /// "255/1048576" /// ); /// ``` fn from_sci_string_with_options(s: &str, options: FromSciStringOptions) -> Option { let (s, exponent) = preprocess_sci_string(s, options)?; let x = Self::from(Integer::parse_int(&s, options.get_base())?); Some(x * Self::from(options.get_base()).pow(exponent)) } } impl Rational { /// Converts a string, possibly in scientfic notation, to a [`Rational`]. This function finds /// the simplest [`Rational`] which rounds to the target string according to the precision /// implied by the string. /// /// Use [`FromSciStringOptions`] to specify the base (from 2 to 36, inclusive). The rounding /// mode option is ignored. /// /// If the base is greater than 10, the higher digits are represented by the letters `'a'` /// through `'z'` or `'A'` through `'Z'`; the case doesn't matter and doesn't need to be /// consistent. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. If the base is /// 15 or greater, an ambiguity arises where it may not be clear whether `'e'` is a digit or an /// exponent indicator. To resolve this ambiguity, always use a `'+'` or `'-'` sign after the /// exponent indicator when the base is 15 or greater. /// /// The exponent itself is always parsed using base 10. /// /// Decimal (or other-base) points are allowed. /// /// If the string is unparseable, `None` is returned. /// /// Here's a more precise description of the function's behavior. Suppose we are using base $b$, /// and the literal value of the string (as parsed by /// [`from_sci_string`](Rational::from_sci_string)) is $q$, and the implied scale is $s$ /// (meaning $s$ digits are provided after the point; if the string is `"123.456"`, then $s$ is /// 3). Then this function computes $\varepsilon = b^{-s}/2$ and finds the simplest [`Rational`] /// in the closed interval $[q - \varepsilon, q + \varepsilon]$. The simplest [`Rational`] is /// the one with minimal denominator; if there are multiple such [`Rational`]s, the one with the /// smallest absolute numerator is chosen. /// /// The following discussion assumes base 10. /// /// This method allows the function to convert `"0.333"` to $1/3$, since $1/3$ is the simplest /// [`Rational`] in the interval $[0.3325, 0.3335]$. But note that if the scale of the input is /// low, some unexpected behavior may occur. For example, `"0.1"` will be converted into $1/7$ /// rather than $1/10$, since $1/7$ is the simplest [`Rational`] in $[0.05, 0.15]$. If you'd /// prefer that result be $1/10$, you have a few options: /// - Use [`from_sci_string_with_options`](Rational::from_sci_string_with_options) instead. This /// function interprets its input literally; it converts `"0.333"` to $333/1000$. /// - Increase the scale of the input; `"0.10"` is converted to $1/10$. /// - Use [`from_sci_string_with_options`](Rational::from_sci_string_with_options), and round /// the result manually using functions like /// [`round_to_multiple`](malachite_base::num::arithmetic::traits::RoundToMultiple::round_to_multiple) /// and /// [`simplest_rational_in_closed_interval`](Rational::simplest_rational_in_closed_interval). /// /// # Worst-case complexity /// $T(n, m) = O(m^n n \log m (\log n + \log\log m))$ /// /// $M(n, m) = O(m^n n \log m)$ /// /// where $T$ is time, $M$ is additional memory, $n$ is `s.len()`, and $m$ is `options.base`. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::FromSciStringOptions; /// use malachite_q::Rational; /// /// let mut options = FromSciStringOptions::default(); /// options.set_base(16); /// assert_eq!( /// Rational::from_sci_string_simplest_with_options("ff", options).unwrap(), /// 255 /// ); /// assert_eq!( /// Rational::from_sci_string_simplest_with_options("ffE+5", options).unwrap(), /// 267386880 /// ); /// // 1/4105 is 0.000ff705..._16 /// assert_eq!( /// Rational::from_sci_string_simplest_with_options("ffE-5", options) /// .unwrap() /// .to_string(), /// "1/4105" /// ); /// ``` pub fn from_sci_string_simplest_with_options( s: &str, options: FromSciStringOptions, ) -> Option { let (s, exponent) = preprocess_sci_string(s, options)?; let x = Self::from(Integer::parse_int(&s, options.get_base())?); let p = Self::from(options.get_base()).pow(exponent); let q = x * &p; if exponent >= 0 { Some(q) } else { let epsilon = p >> 1; Some(Self::simplest_rational_in_closed_interval( &(&q - &epsilon), &(q + epsilon), )) } } /// Converts a string, possibly in scientfic notation, to a [`Rational`]. This function finds /// the simplest [`Rational`] which rounds to the target string according to the precision /// implied by the string. /// /// The string is parsed using base 10. To use other bases, try /// [`from_sci_string_simplest_with_options`](Rational::from_sci_string_simplest_with_options) /// instead. /// /// Exponents are allowed, and are indicated using the character `'e'` or `'E'`. /// /// The exponent itself is also parsed using base 10. /// /// Decimal points are allowed. /// /// If the string is unparseable, `None` is returned. /// /// Here's a more precise description of the function's behavior. Suppose that the literal value /// of the string (as parsed by [`from_sci_string`](Rational::from_sci_string)) is $q$, and the /// implied scale is $s$ (meaning $s$ digits are provided after the point; if the string is /// `"123.456"`, then $s$ is 3). Then this function computes $\varepsilon = 10^{-s}/2$ and finds /// the simplest [`Rational`] in the closed interval $[q - \varepsilon, q + \varepsilon]$. The /// simplest [`Rational`] is the one with minimal denominator; if there are multiple such /// [`Rational`]s, the one with the smallest absolute numerator is chosen. /// /// This method allows the function to convert `"0.333"` to $1/3$, since $1/3$ is the simplest /// [`Rational`] in the interval $[0.3325, 0.3335]$. But note that if the scale of the input is /// low, some unexpected behavior may occur. For example, `"0.1"` will be converted into $1/7$ /// rather than $1/10$, since $1/7$ is the simplest [`Rational`] in $[0.05, 0.15]$. If you'd /// prefer that result be $1/10$, you have a few options: /// - Use [`from_sci_string`](Rational::from_sci_string) instead. This function interprets its /// input literally; it converts `"0.333"` to $333/1000$. /// - Increase the scale of the input; `"0.10"` is converted to $1/10$. /// - Use [`from_sci_string`](Rational::from_sci_string), and round the result manually using /// functions like /// [`round_to_multiple`](malachite_base::num::arithmetic::traits::RoundToMultiple::round_to_multiple) /// and /// [`simplest_rational_in_closed_interval`](Rational::simplest_rational_in_closed_interval). /// /// # Worst-case complexity /// $T(n) = O(10^n n \log n)$ /// /// $M(n) = O(10^n n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// assert_eq!(Rational::from_sci_string_simplest("123").unwrap(), 123); /// assert_eq!( /// Rational::from_sci_string_simplest("0.1") /// .unwrap() /// .to_string(), /// "1/7" /// ); /// assert_eq!( /// Rational::from_sci_string_simplest("0.10") /// .unwrap() /// .to_string(), /// "1/10" /// ); /// assert_eq!( /// Rational::from_sci_string_simplest("0.333") /// .unwrap() /// .to_string(), /// "1/3" /// ); /// assert_eq!(Rational::from_sci_string_simplest("1.2e5").unwrap(), 120000); /// assert_eq!( /// Rational::from_sci_string_simplest("1.2e-5") /// .unwrap() /// .to_string(), /// "1/80000" /// ); /// ``` #[inline] pub fn from_sci_string_simplest(s: &str) -> Option { Self::from_sci_string_simplest_with_options(s, FromSciStringOptions::default()) } } ================================================ FILE: malachite-q/src/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::str::FromStr; use malachite_base::num::basic::traits::One; use malachite_nz::natural::Natural; impl FromStr for Rational { type Err = (); /// Converts an string to a [`Rational`]. /// /// If the string does not represent a valid [`Rational`], an `Err` is returned. The numerator /// and denominator do not need to be in lowest terms, but the denominator must be nonzero. A /// negative sign is only allowed at the 0th position of the string. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::from_str("123456").unwrap(), 123456); /// assert_eq!(Rational::from_str("00123456").unwrap(), 123456); /// assert_eq!(Rational::from_str("0").unwrap(), 0); /// assert_eq!(Rational::from_str("-123456").unwrap(), -123456); /// assert_eq!(Rational::from_str("-00123456").unwrap(), -123456); /// assert_eq!(Rational::from_str("-0").unwrap(), 0); /// assert_eq!(Rational::from_str("22/7").unwrap().to_string(), "22/7"); /// assert_eq!(Rational::from_str("01/02").unwrap().to_string(), "1/2"); /// assert_eq!(Rational::from_str("3/21").unwrap().to_string(), "1/7"); /// assert_eq!(Rational::from_str("-22/7").unwrap().to_string(), "-22/7"); /// assert_eq!(Rational::from_str("-01/02").unwrap().to_string(), "-1/2"); /// assert_eq!(Rational::from_str("-3/21").unwrap().to_string(), "-1/7"); /// /// assert!(Rational::from_str("").is_err()); /// assert!(Rational::from_str("a").is_err()); /// assert!(Rational::from_str("1/0").is_err()); /// assert!(Rational::from_str("/1").is_err()); /// assert!(Rational::from_str("1/").is_err()); /// assert!(Rational::from_str("--1").is_err()); /// assert!(Rational::from_str("1/-2").is_err()); /// ``` #[inline] fn from_str(s: &str) -> Result { let (abs_string, sign) = if let Some(abs_string) = s.strip_prefix('-') { if abs_string.starts_with('+') { return Err(()); } (abs_string, false) } else { (s, true) }; let numerator; let denominator; if let Some(slash_index) = abs_string.find('/') { numerator = Natural::from_str(&abs_string[..slash_index])?; denominator = Natural::from_str(&abs_string[slash_index + 1..])?; if denominator == 0u32 { return Err(()); } } else { numerator = Natural::from_str(abs_string)?; denominator = Natural::ONE; } Ok(Self::from_sign_and_naturals(sign, numerator, denominator)) } } ================================================ FILE: malachite-q/src/conversion/string/mod.rs ================================================ // Copyright © 2026 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 . /// Implementations of [`FromSciString`](malachite_base::num::conversion::traits::FromSciString). /// This is a trait for converting strings, possibly using scientific notation, to numbers. pub mod from_sci_string; /// An implementation of [`FromStr`](std::str::FromStr). pub mod from_string; /// Implementations of [`ToSci`](malachite_base::num::conversion::traits::ToSci), a trait for /// converting a number to string, possibly using scientific notation. pub mod to_sci; /// Implementations of [`Display`](std::fmt::Display) and [`Debug`]. pub mod to_string; ================================================ FILE: malachite-q/src/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::log_base::log_base_helper; use alloc::string::String; use core::cmp::{Ordering::*, max}; use core::fmt::{Formatter, Write}; use malachite_base::num::arithmetic::traits::{ Abs, CheckedLogBase2, DivExact, DivExactAssign, DivRound, DivisibleBy, Pow, Sign, }; use malachite_base::num::conversion::string::options::{SciSizeOptions, ToSciOptions}; use malachite_base::num::conversion::string::to_sci::write_exponent; use malachite_base::num::conversion::traits::{ ExactFrom, IsInteger, RoundingFrom, ToSci, ToStringBase, WrappingFrom, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; const BASE_PRIME_FACTORS: [[(u8, u8); 3]; 37] = [ [(0, 0), (0, 0), (0, 0)], [(0, 0), (0, 0), (0, 0)], [(2, 1), (0, 0), (0, 0)], [(3, 1), (0, 0), (0, 0)], [(2, 2), (0, 0), (0, 0)], [(5, 1), (0, 0), (0, 0)], [(2, 1), (3, 1), (0, 0)], [(7, 1), (0, 0), (0, 0)], [(2, 3), (0, 0), (0, 0)], [(3, 2), (0, 0), (0, 0)], [(2, 1), (5, 1), (0, 0)], [(11, 1), (0, 0), (0, 0)], [(2, 2), (3, 1), (0, 0)], [(13, 1), (0, 0), (0, 0)], [(2, 1), (7, 1), (0, 0)], [(3, 1), (5, 1), (0, 0)], [(2, 4), (0, 0), (0, 0)], [(17, 1), (0, 0), (0, 0)], [(2, 1), (3, 2), (0, 0)], [(19, 1), (0, 0), (0, 0)], [(2, 2), (5, 1), (0, 0)], [(3, 1), (7, 1), (0, 0)], [(2, 1), (11, 1), (0, 0)], [(23, 1), (0, 0), (0, 0)], [(2, 3), (3, 1), (0, 0)], [(5, 2), (0, 0), (0, 0)], [(2, 1), (13, 1), (0, 0)], [(3, 3), (0, 0), (0, 0)], [(2, 2), (7, 1), (0, 0)], [(29, 1), (0, 0), (0, 0)], [(2, 1), (3, 1), (5, 1)], [(31, 1), (0, 0), (0, 0)], [(2, 5), (0, 0), (0, 0)], [(3, 1), (11, 1), (0, 0)], [(2, 1), (17, 1), (0, 0)], [(5, 1), (7, 1), (0, 0)], [(2, 2), (3, 2), (0, 0)], ]; impl Rational { /// When expanding a [`Rational`] in a small base $b$, determines how many digits after the /// decimal (or other-base) point are in the base-$b$ expansion. /// /// If the expansion is non-terminating, this method returns `None`. This happens iff the /// [`Rational`]'s denominator has prime factors not present in $b$. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Panics /// Panics if `base` is less than 2 or greater than 36. /// /// # Examples /// ``` /// use malachite_q::Rational; /// /// // 3/8 is 0.375 in base 10. /// assert_eq!( /// Rational::from_signeds(3, 8).length_after_point_in_small_base(10), /// Some(3) /// ); /// // 1/20 is 0.05 in base 10. /// assert_eq!( /// Rational::from_signeds(1, 20).length_after_point_in_small_base(10), /// Some(2) /// ); /// // 1/7 is non-terminating in base 10. /// assert_eq!( /// Rational::from_signeds(1, 7).length_after_point_in_small_base(10), /// None /// ); /// // 1/7 is 0.3 in base 21. /// assert_eq!( /// Rational::from_signeds(1, 7).length_after_point_in_small_base(21), /// Some(1) /// ); /// ``` pub fn length_after_point_in_small_base(&self, base: u8) -> Option { let d = self.denominator_ref(); assert!((2..=36).contains(&base)); if *d == 1u32 { return Some(0); } let mut temp = None; let mut length = 0; for (f, m) in BASE_PRIME_FACTORS[usize::wrapping_from(base)] { let count = if f == 0 { break; } else if f == 2 { let twos = d.trailing_zeros().unwrap(); if twos != 0 { temp = Some(d >> twos); } twos } else { let f = Natural::from(f); let mut count = 0; if let Some(temp) = temp.as_mut() { while (&*temp).divisible_by(&f) { temp.div_exact_assign(&f); count += 1; } } else if d.divisible_by(&f) { count = 1; let mut t = d.div_exact(&f); while (&t).divisible_by(&f) { t.div_exact_assign(&f); count += 1; } temp = Some(t); } count }; length = max(length, count.div_round(u64::from(m), Ceiling).0); } if let Some(temp) = temp { if temp == 1 { Some(length) } else { None } } else { None } } } pub_test! {floor_log_base_of_abs(x: &Rational, base: &Rational) -> i64 { if let Some(log_base) = base.checked_log_base_2() { match log_base.sign() { Equal => panic!("Cannot take base-1 logarithm"), Greater => x .floor_log_base_2_abs() .div_round(log_base, Floor).0, Less => { -(x.ceiling_log_base_2_abs() .div_round(-log_base, Ceiling).0) } } } else { log_base_helper(x, base).0 } }} fn fmt_zero(f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result { f.write_char('0')?; let scale = if options.get_include_trailing_zeros() { match options.get_size_options() { SciSizeOptions::Complete => None, SciSizeOptions::Scale(scale) => { if scale == 0 { None } else { Some(scale) } } SciSizeOptions::Precision(precision) => { if precision == 1 { None } else { Some(precision - 1) } } } } else { None }; if let Some(scale) = scale { f.write_char('.')?; for _ in 0..scale { f.write_char('0')?; } } Ok(()) } impl ToSci for Rational { /// Determines whether a [`Rational`] can be converted to a string using /// [`to_sci`](malachite_base::num::conversion::traits::ToSci::to_sci) and a particular set of /// options. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), s)`, /// where `s` depends on the size type specified in `options`. /// - If `options` has `scale` specified, then `s` is `options.scale`. /// - If `options` has `precision` specified, then `s` is `options.precision`. /// - If `options` has `size_complete` specified, then `s` is `self.denominator` (not the log of /// the denominator!). This reflects the fact that setting `size_complete` might result in a /// very long string. /// /// # Examples /// ``` /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// /// let mut options = ToSciOptions::default(); /// assert!(Rational::from(123u8).fmt_sci_valid(options)); /// assert!(Rational::from(u128::MAX).fmt_sci_valid(options)); /// // u128::MAX has more than 16 significant digits /// options.set_rounding_mode(Exact); /// assert!(!Rational::from(u128::MAX).fmt_sci_valid(options)); /// options.set_precision(50); /// assert!(Rational::from(u128::MAX).fmt_sci_valid(options)); /// /// let mut options = ToSciOptions::default(); /// options.set_size_complete(); /// // 1/3 is non-terminating in base 10... /// assert!(!Rational::from_signeds(1, 3).fmt_sci_valid(options)); /// options.set_size_complete(); /// /// // ...but is terminating in base 36 /// options.set_base(36); /// assert!(Rational::from_signeds(1, 3).fmt_sci_valid(options)); /// ``` fn fmt_sci_valid(&self, options: ToSciOptions) -> bool { if *self == 0 { return true; } if let SciSizeOptions::Complete = options.get_size_options() { return self .length_after_point_in_small_base(options.get_base()) .is_some(); } if options.get_rounding_mode() != Exact { return true; } let q_base = Self::from(options.get_base()); let scale = match options.get_size_options() { SciSizeOptions::Precision(precision) => { let log = floor_log_base_of_abs(self, &q_base); i64::exact_from(precision - 1) - log } SciSizeOptions::Scale(scale) => i64::exact_from(scale), _ => unreachable!(), }; (self * q_base.pow(scale)).is_integer() } /// Converts a [`Rational` ]to a string using a specified base, possibly formatting the number /// using scientific notation. /// /// See [`ToSciOptions`] for details on the available options. /// /// # Worst-case complexity /// $T(n) = O(n \log n \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(), s)`, /// where `s` depends on the size type specified in `options`. /// - If `options` has `scale` specified, then `s` is `options.scale`. /// - If `options` has `precision` specified, then `s` is `options.precision`. /// - If `options` has `size_complete` specified, then `s` is `self.denominator` (not the log of /// the denominator!). This reflects the fact that setting `size_complete` might result in a /// very long string. /// /// # Panics /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the input /// must be rounded. /// /// # Examples /// ``` /// use malachite_base::num::arithmetic::traits::PowerOf2; /// use malachite_base::num::conversion::string::options::ToSciOptions; /// use malachite_base::num::conversion::traits::ToSci; /// use malachite_base::rounding_modes::RoundingMode::*; /// use malachite_q::Rational; /// /// let q = Rational::from_signeds(22, 7); /// let mut options = ToSciOptions::default(); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "3.142857142857143" /// ); /// /// options.set_precision(3); /// assert_eq!(q.to_sci_with_options(options).to_string(), "3.14"); /// /// options.set_rounding_mode(Ceiling); /// assert_eq!(q.to_sci_with_options(options).to_string(), "3.15"); /// /// options = ToSciOptions::default(); /// options.set_base(20); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "3.2h2h2h2h2h2h2h3" /// ); /// /// options.set_uppercase(); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "3.2H2H2H2H2H2H2H3" /// ); /// /// options.set_base(2); /// options.set_rounding_mode(Floor); /// options.set_precision(19); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "11.001001001001001" /// ); /// /// options.set_include_trailing_zeros(true); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "11.00100100100100100" /// ); /// /// let q = Rational::from_unsigneds(936851431250u64, 1397u64); /// let mut options = ToSciOptions::default(); /// options.set_precision(6); /// assert_eq!(q.to_sci_with_options(options).to_string(), "6.70617e8"); /// /// options.set_e_uppercase(); /// assert_eq!(q.to_sci_with_options(options).to_string(), "6.70617E8"); /// /// options.set_force_exponent_plus_sign(true); /// assert_eq!(q.to_sci_with_options(options).to_string(), "6.70617E+8"); /// /// let q = Rational::from_signeds(123i64, 45678909876i64); /// let mut options = ToSciOptions::default(); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "2.692708743135418e-9" /// ); /// /// options.set_neg_exp_threshold(-10); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "0.000000002692708743135418" /// ); /// /// let q = Rational::power_of_2(-30i64); /// let mut options = ToSciOptions::default(); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "9.313225746154785e-10" /// ); /// /// options.set_size_complete(); /// assert_eq!( /// q.to_sci_with_options(options).to_string(), /// "9.31322574615478515625e-10" /// ); /// ``` fn fmt_sci(&self, f: &mut Formatter, options: ToSciOptions) -> core::fmt::Result { if *self == 0u32 { return fmt_zero(f, options); } if *self < 0u32 { f.write_char('-')?; } let base = options.get_base(); let q_base = Self::from(base); let mut trim_zeros = !options.get_include_trailing_zeros(); let mut log = floor_log_base_of_abs(self, &q_base); // Here, precision 0 means that we're rounding down to zero let (mut scale, mut precision) = match options.get_size_options() { SciSizeOptions::Complete => { trim_zeros = false; let scale = self .length_after_point_in_small_base(base) .unwrap_or_else(|| { panic!("{self} has a non-terminating expansion in base {base}") }); let precision = i64::exact_from(scale) + log + 1; assert!(precision > 0); (i64::exact_from(scale), precision) } SciSizeOptions::Scale(scale) => { (i64::exact_from(scale), i64::exact_from(scale) + log + 1) } SciSizeOptions::Precision(precision) => ( i64::exact_from(precision - 1) - log, i64::exact_from(precision), ), }; let n = Integer::rounding_from(self * q_base.pow(scale), options.get_rounding_mode()) .0 .abs(); if precision <= 0 { // e.g. we're in base 10, self is 0.01 or 0.000001, but scale is 1 if n == 0u32 { return fmt_zero(f, options); } else if n == 1u32 { precision = 1; log = -scale; } else { panic!("Bug: precision <= 0 must mean self.abs() rounds to 0 or 1"); }; } let mut cs = if options.get_lowercase() { n.to_string_base(base) } else { n.to_string_base_upper(base) } .into_bytes(); let mut precision = usize::exact_from(precision); if cs.len() == precision + 1 { // We rounded up to a power of the base, so precision is greater than we expected. If // the options specify the precision, we need to adjust. log += 1; match options.get_size_options() { SciSizeOptions::Complete => panic!(), SciSizeOptions::Precision(_) => { scale -= 1; assert_eq!(cs.pop().unwrap(), b'0'); } SciSizeOptions::Scale(_) => { precision += 1; } } } assert_eq!(cs.len(), precision); if log <= options.get_neg_exp_threshold() || scale < 0 { assert_ne!(log, 0); // exponent if trim_zeros { let trailing_zeros = cs.iter().rev().take_while(|&&c| c == b'0').count(); precision -= trailing_zeros; cs.truncate(precision); } if precision > 1 { cs.push(0); cs.copy_within(1..precision, 2); cs[1] = b'.'; } f.write_str(&String::from_utf8(cs).unwrap())?; write_exponent(f, options, log) } else if scale == 0 { // no exponent or point f.write_str(&String::from_utf8(cs).unwrap()) } else { // no exponent if trim_zeros { let trailing_zeros = cs .iter() .rev() .take(usize::exact_from(scale)) .take_while(|&&c| c == b'0') .count(); precision -= trailing_zeros; cs.truncate(precision); } if log < 0 { f.write_char('0')?; f.write_char('.')?; for _ in 0..-log - 1 { f.write_char('0')?; } } else { let digits_before = usize::exact_from(log) + 1; if precision > digits_before { cs.push(0); cs.copy_within(digits_before..precision, digits_before + 1); cs[digits_before] = b'.'; } } f.write_str(&String::from_utf8(cs).unwrap()) } } } ================================================ FILE: malachite-q/src/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 crate::Rational; use core::fmt::{Debug, Display, Formatter, Result, Write}; impl Display for Rational { /// Converts a [`Rational`] to a [`String`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::ZERO.to_string(), "0"); /// assert_eq!(Rational::from(123).to_string(), "123"); /// assert_eq!(Rational::from_str("22/7").unwrap().to_string(), "22/7"); /// ``` fn fmt(&self, f: &mut Formatter) -> Result { if !self.sign { f.write_char('-')?; } let result = Display::fmt(&self.numerator, f); if self.denominator == 1 { result } else { f.write_char('/')?; Display::fmt(&self.denominator, f) } } } impl Debug for Rational { /// Converts a [`Rational`] to a [`String`]. /// /// This is the same implementation as for [`Display`]. /// /// # Worst-case complexity /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// /// assert_eq!(Rational::ZERO.to_debug_string(), "0"); /// assert_eq!(Rational::from(123).to_debug_string(), "123"); /// assert_eq!(Rational::from_signeds(22, 7).to_debug_string(), "22/7"); /// ``` #[inline] fn fmt(&self, f: &mut Formatter) -> Result { Display::fmt(self, f) } } ================================================ FILE: malachite-q/src/conversion/to_numerator_and_denominator.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::natural::Natural; impl Rational { /// Extracts the numerator of a [`Rational`], taking the [`Rational`] by reference and cloning. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::from_str("2/3").unwrap().to_numerator(), 2); /// assert_eq!(Rational::from_str("0").unwrap().to_numerator(), 0); /// ``` #[inline] pub fn to_numerator(&self) -> Natural { self.numerator.clone() } /// Extracts the denominator of a [`Rational`], taking the [`Rational`] by reference and /// cloning. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::from_str("2/3").unwrap().to_denominator(), 3); /// assert_eq!(Rational::from_str("0").unwrap().to_denominator(), 1); /// ``` #[inline] pub fn to_denominator(&self) -> Natural { self.denominator.clone() } /// Extracts the numerator and denominator of a [`Rational`], taking the [`Rational`] by /// reference and cloning. /// /// # Worst-case complexity /// $T(n) = O(n)$ /// /// $M(n) = O(n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// Rational::from_str("2/3") /// .unwrap() /// .to_numerator_and_denominator() /// .to_debug_string(), /// "(2, 3)" /// ); /// assert_eq!( /// Rational::from_str("0") /// .unwrap() /// .to_numerator_and_denominator() /// .to_debug_string(), /// "(0, 1)" /// ); /// ``` #[inline] pub fn to_numerator_and_denominator(&self) -> (Natural, Natural) { (self.numerator.clone(), self.denominator.clone()) } /// Extracts the numerator of a [`Rational`], taking the [`Rational`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::from_str("2/3").unwrap().into_numerator(), 2); /// assert_eq!(Rational::from_str("0").unwrap().into_numerator(), 0); /// ``` #[inline] #[allow(clippy::missing_const_for_fn)] pub fn into_numerator(self) -> Natural { self.numerator } /// Extracts the denominator of a [`Rational`], taking the [`Rational`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::from_str("2/3").unwrap().into_denominator(), 3); /// assert_eq!(Rational::from_str("0").unwrap().into_denominator(), 1); /// ``` #[inline] #[allow(clippy::missing_const_for_fn)] pub fn into_denominator(self) -> Natural { self.denominator } /// Extracts the numerator and denominator of a [`Rational`], taking the [`Rational`] by value. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// Rational::from_str("2/3") /// .unwrap() /// .into_numerator_and_denominator() /// .to_debug_string(), /// "(2, 3)" /// ); /// assert_eq!( /// Rational::from_str("0") /// .unwrap() /// .into_numerator_and_denominator() /// .to_debug_string(), /// "(0, 1)" /// ); /// ``` #[inline] #[allow(clippy::missing_const_for_fn)] pub fn into_numerator_and_denominator(self) -> (Natural, Natural) { (self.numerator, self.denominator) } /// Returns a reference to the numerator of a [`Rational`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(*Rational::from_str("2/3").unwrap().numerator_ref(), 2); /// assert_eq!(*Rational::from_str("0").unwrap().numerator_ref(), 0); /// ``` #[inline] pub const fn numerator_ref(&self) -> &Natural { &self.numerator } /// Returns a reference to the denominator of a [`Rational`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(*Rational::from_str("2/3").unwrap().denominator_ref(), 3); /// assert_eq!(*Rational::from_str("0").unwrap().denominator_ref(), 1); /// ``` #[inline] pub const fn denominator_ref(&self) -> &Natural { &self.denominator } /// Returns references to the numeraror and denominator of a [`Rational`]. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::strings::ToDebugString; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!( /// Rational::from_str("2/3") /// .unwrap() /// .numerator_and_denominator_ref() /// .to_debug_string(), /// "(2, 3)" /// ); /// assert_eq!( /// Rational::from_str("0") /// .unwrap() /// .numerator_and_denominator_ref() /// .to_debug_string(), /// "(0, 1)" /// ); /// ``` #[inline] pub const fn numerator_and_denominator_ref(&self) -> (&Natural, &Natural) { (&self.numerator, &self.denominator) } } ================================================ FILE: malachite-q/src/conversion/traits.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; /// Returns a number's continued fraction. /// /// The form of a continued fraction is $[a_0; a_1, a_2, a_3\ldots]$. The first component of the /// output pair is $a_0$, and the second is an iterator that produces the $a_i$ for $i > 0$. pub trait ContinuedFraction { type CF: Iterator; fn continued_fraction(self) -> (Integer, Self::CF); } /// Returns a number's convergents, as an iterator of [`Rational`]s. /// /// The convergents of a real number are the rational numbers whose continued fractions are the /// prefixes of the original number's continued fraction. pub trait Convergents { type C: Iterator; fn convergents(self) -> Self::C; } ================================================ FILE: malachite-q/src/exhaustive/mod.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::denominators_in_closed_interval::DenominatorsInClosedRationalInterval; use crate::arithmetic::traits::DenominatorsInClosedInterval; use core::iter::{Chain, Once, once}; use core::mem::swap; use malachite_base::num::arithmetic::traits::{CoprimeWith, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::num::iterators::{RulerSequence, ruler_sequence}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::tuples::exhaustive::{ ExhaustiveDependentPairs, ExhaustiveDependentPairsYsGenerator, exhaustive_dependent_pairs, }; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::{ ExhaustiveIntegerRange, ExhaustiveIntegerRangeToInfinity, ExhaustiveIntegerRangeToNegativeInfinity, exhaustive_integer_range, exhaustive_integer_range_to_infinity, exhaustive_integer_range_to_negative_infinity, }; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::{ ExhaustiveNaturalRangeToInfinity, exhaustive_positive_naturals, }; /// Generates all positive [`Rational`]s. /// /// This `struct` is created by [`exhaustive_positive_rationals`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustivePositiveRationals { pred_pred: Natural, pred: Natural, } impl Iterator for ExhaustivePositiveRationals { type Item = Rational; fn next(&mut self) -> Option { let mut anm1 = Natural::ZERO; swap(&mut self.pred_pred, &mut anm1); swap(&mut self.pred, &mut self.pred_pred); let k = &anm1 / &self.pred_pred; // floor(a(n - 1) / a(n)) self.pred = ((k << 1u32) | Natural::ONE) * &self.pred_pred - anm1; Some(Rational { sign: true, numerator: self.pred_pred.clone(), denominator: self.pred.clone(), }) } } /// Generates all positive [`Rational`]s. /// /// The [`Rational`]s are ordered as in the [Calkin-Wilf /// sequence](https://en.wikipedia.org/wiki/Calkin%E2%80%93Wilf_tree#Breadth_first_traversal). Their /// numerators and denominators are given by the [Stern-Brocot /// sequence](https://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree#Relation_to_Farey_sequences). /// To generate the latter sequence, this iterator uses the formula /// $$ /// a_{n+1} = \left ( 2 \left \lfloor \frac{a_{n-1}}{a_n} \right \rfloor +1 \right ) a_n - a_{n-1}, /// $$ /// attributed to David S. Newman at . /// /// The output length is infinite. The numerators and denominators of the $n$th element are /// $O(n^\frac{\log \phi}{\log 2})$. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i \log\log i \log\log\log i)$ /// /// $M(i) = O(\log i \log\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_q::exhaustive::exhaustive_positive_rationals; /// /// assert_eq!( /// prefix_to_string(exhaustive_positive_rationals(), 20), /// "[1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, 5/3, 3/4, 4, 1/5, 5/4, 4/7, 7/3, \ /// 3/8, ...]" /// ) /// ``` pub const fn exhaustive_positive_rationals() -> ExhaustivePositiveRationals { ExhaustivePositiveRationals { pred_pred: Natural::ZERO, pred: Natural::ONE, } } /// Generates all non-positive [`Rational`]s. /// /// Zero is generated first, followed by all the positive [`Rational`]s. See /// [`exhaustive_positive_rationals`] for details. /// /// The output length is infinite. The numerators and denominators of the $n$th element are /// $O(n^\frac{\log \phi}{\log 2})$. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i \log\log i \log\log\log i)$ /// /// $M(i) = O(\log i \log\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_q::exhaustive::exhaustive_non_negative_rationals; /// /// assert_eq!( /// prefix_to_string(exhaustive_non_negative_rationals(), 20), /// "[0, 1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, 5/3, 3/4, 4, 1/5, 5/4, 4/7, \ /// 7/3, ...]" /// ) /// ``` pub fn exhaustive_non_negative_rationals() -> Chain, ExhaustivePositiveRationals> { once(Rational::ZERO).chain(exhaustive_positive_rationals()) } /// Generates all negative [`Rational`]s. /// /// This `struct` is created by [`exhaustive_negative_rationals`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveNegativeRationals { xs: ExhaustivePositiveRationals, } impl Iterator for ExhaustiveNegativeRationals { type Item = Rational; fn next(&mut self) -> Option { self.xs.next().map(|mut q| { q.sign = false; q }) } } /// Generates all negative [`Rational`]s. /// /// The sequence is the same as the sequence of positive [`Rational`]s, but negated. See /// [`exhaustive_positive_rationals`] for details. /// /// The output length is infinite. The absolute values of the numerators and denominators of the /// $n$th element are $O(n^\frac{\log \phi}{\log 2})$. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i \log\log i \log\log\log i)$ /// /// $M(i) = O(\log i \log\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_q::exhaustive::exhaustive_negative_rationals; /// /// assert_eq!( /// prefix_to_string(exhaustive_negative_rationals(), 20), /// "[-1, -1/2, -2, -1/3, -3/2, -2/3, -3, -1/4, -4/3, -3/5, -5/2, -2/5, -5/3, -3/4, -4, -1/5, \ /// -5/4, -4/7, -7/3, -3/8, ...]" /// ) /// ``` pub const fn exhaustive_negative_rationals() -> ExhaustiveNegativeRationals { ExhaustiveNegativeRationals { xs: exhaustive_positive_rationals(), } } /// Generates all nonzero [`Rational`]s. /// /// This `struct` is created by [`exhaustive_nonzero_rationals`]; see its documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveNonzeroRationals { xs: ExhaustivePositiveRationals, x: Option, sign: bool, } impl Iterator for ExhaustiveNonzeroRationals { type Item = Rational; fn next(&mut self) -> Option { if self.sign { self.sign = false; let mut x = None; swap(&mut self.x, &mut x); let mut x = x.unwrap(); x.sign = false; Some(x) } else { self.sign = true; self.x = self.xs.next(); Some(self.x.clone().unwrap()) } } } /// Generates all nonzero [`Rational`]s. /// /// The sequence is the same the sequence of positive [`Rational`]s, interleaved with its negative. /// See [`exhaustive_positive_rationals`] for details. /// /// The output length is infinite. The absolute values of the numerators and denominators of the /// $n$th element are $O(n^\frac{\log \phi}{\log 2})$. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i \log\log i \log\log\log i)$ /// /// $M(i) = O(\log i \log\log i)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_q::exhaustive::exhaustive_nonzero_rationals; /// /// assert_eq!( /// prefix_to_string(exhaustive_nonzero_rationals(), 20), /// "[1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, 3/2, -3/2, 2/3, -2/3, 3, -3, 1/4, -1/4, 4/3, -4/3, \ /// 3/5, -3/5, ...]" /// ) /// ``` pub const fn exhaustive_nonzero_rationals() -> ExhaustiveNonzeroRationals { ExhaustiveNonzeroRationals { xs: exhaustive_positive_rationals(), x: None, sign: false, } } /// Generates all [`Rational`]s. /// /// The sequence begins with zero and is followed by the sequence of positive [`Rational`]s, /// interleaved with its negative. See [`exhaustive_positive_rationals`] for details. /// /// The output length is infinite. The absolute values of the numerators and denominators of the /// $n$th element are $O(n^\frac{\log \phi}{\log 2})$. /// /// # Worst-case complexity per iteration /// $T(n) = O(\log n \log\log n \log\log\log n)$ /// /// $M(i) = O(\log n \log\log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_q::exhaustive::exhaustive_rationals; /// /// assert_eq!( /// prefix_to_string(exhaustive_rationals(), 20), /// "[0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, 3/2, -3/2, 2/3, -2/3, 3, -3, 1/4, -1/4, 4/3, \ /// -4/3, 3/5, ...]" /// ) /// ``` pub fn exhaustive_rationals() -> Chain, ExhaustiveNonzeroRationals> { once(Rational::ZERO).chain(exhaustive_nonzero_rationals()) } /// Generates all [`Rational`]s with a specific denominator and with numerators from a given /// iterator. Numerators that are not coprime with the denominator are skipped. #[derive(Clone, Debug)] pub struct RationalsWithDenominator> { pub(crate) numerators: I, pub(crate) denominator: Natural, } impl> Iterator for RationalsWithDenominator { type Item = Rational; fn next(&mut self) -> Option { loop { let n = self.numerators.next()?; if n.unsigned_abs_ref().coprime_with(&self.denominator) { return Some(Rational { sign: n >= 0u32, numerator: n.unsigned_abs(), denominator: self.denominator.clone(), }); } } } } /// Generates all [`Rational`]s greater than or equal to some number $a$ and with a specific /// denominator, in order of increasing absolute value. /// /// When two [`Rational`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if `d` is zero. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::natural::Natural; /// use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range_to_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rationals_with_denominator_range_to_infinity( /// Natural::from(5u32), /// Rational::from_signeds(22i32, 7) /// ), /// 10 /// ), /// "[16/5, 17/5, 18/5, 19/5, 21/5, 22/5, 23/5, 24/5, 26/5, 27/5, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// exhaustive_rationals_with_denominator_range_to_infinity( /// Natural::from(2u32), /// Rational::from_signeds(-22i32, 7) /// ), /// 10 /// ), /// "[1/2, -1/2, 3/2, -3/2, 5/2, -5/2, 7/2, 9/2, 11/2, 13/2, ...]" /// ); /// ``` pub fn exhaustive_rationals_with_denominator_range_to_infinity( d: Natural, a: Rational, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); RationalsWithDenominator { numerators: exhaustive_integer_range_to_infinity( Integer::rounding_from(a * Rational::from(&d), Ceiling).0, ), denominator: d, } } /// Generates all [`Rational`]s less than or equal to some number $a$ and with a specific /// denominator, in order of increasing absolute value. /// /// When two [`Rational`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if `d` is zero. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_nz::natural::Natural; /// use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range_to_negative_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rationals_with_denominator_range_to_negative_infinity( /// Natural::from(5u32), /// Rational::from_signeds(-22i32, 7) /// ), /// 10 /// ), /// "[-16/5, -17/5, -18/5, -19/5, -21/5, -22/5, -23/5, -24/5, -26/5, -27/5, ...]" /// ); /// assert_eq!( /// prefix_to_string( /// exhaustive_rationals_with_denominator_range_to_negative_infinity( /// Natural::from(2u32), /// Rational::from_signeds(22i32, 7) /// ), /// 10 /// ), /// "[1/2, -1/2, 3/2, -3/2, 5/2, -5/2, -7/2, -9/2, -11/2, -13/2, ...]" /// ); /// ``` pub fn exhaustive_rationals_with_denominator_range_to_negative_infinity( d: Natural, a: Rational, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); RationalsWithDenominator { numerators: exhaustive_integer_range_to_negative_infinity( Integer::rounding_from(a * Rational::from(&d), Floor).0, ), denominator: d, } } /// Generates all [`Rational`]s in the half-open range $[a, b)$ and with a specific denominator, in /// order of increasing absolute value. /// /// When two [`Rational`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if `d` is zero or if $a \geq b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range; /// use malachite_q::Rational; /// /// assert_eq!( /// exhaustive_rationals_with_denominator_range( /// Natural::from(2u32), /// Rational::from_signeds(1i32, 3), /// Rational::from_signeds(5i32, 2) /// ) /// .collect_vec() /// .to_debug_string(), /// "[1/2, 3/2]" /// ); /// assert_eq!( /// exhaustive_rationals_with_denominator_range( /// Natural::from(2u32), /// Rational::from_signeds(-5i32, 3), /// Rational::from_signeds(5i32, 2) /// ) /// .collect_vec() /// .to_debug_string(), /// "[1/2, -1/2, 3/2, -3/2]" /// ); /// assert_eq!( /// exhaustive_rationals_with_denominator_range( /// Natural::from(10u32), /// Rational::try_from_float_simplest(std::f64::consts::E).unwrap(), /// Rational::try_from_float_simplest(std::f64::consts::PI).unwrap(), /// ) /// .collect_vec() /// .to_debug_string(), /// "[29/10, 31/10]" /// ); /// ``` pub fn exhaustive_rationals_with_denominator_range( d: Natural, a: Rational, b: Rational, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); assert!(a < b); let q_d = Rational::from(&d); let a_i = Integer::rounding_from(a * &q_d, Ceiling).0; let upper_included = b.denominator_ref() == &d; let mut b_i = Integer::rounding_from(b * q_d, Floor).0; if !upper_included { b_i += Integer::ONE; } RationalsWithDenominator { numerators: exhaustive_integer_range(a_i, b_i), denominator: d, } } /// Generates all [`Rational`]s in the closed range $[a, b]$ and with a specific denominator, in /// order of increasing absolute value. /// /// When two [`Rational`]s have the same absolute value, the positive one comes first. /// /// The output satisfies $(|x_i|, \operatorname{sgn}(-x_i)) <_\mathrm{lex} (|x_j|, /// \operatorname{sgn}(-x_j))$ whenever $i < j$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Panics /// Panics if `d` is zero or if $a > b$. /// /// # Examples /// ``` /// use itertools::Itertools; /// use malachite_base::strings::ToDebugString; /// use malachite_nz::natural::Natural; /// use malachite_q::exhaustive::exhaustive_rationals_with_denominator_inclusive_range; /// use malachite_q::Rational; /// /// assert_eq!( /// exhaustive_rationals_with_denominator_inclusive_range( /// Natural::from(2u32), /// Rational::from_signeds(1i32, 3), /// Rational::from_signeds(5i32, 2) /// ) /// .collect_vec() /// .to_debug_string(), /// "[1/2, 3/2, 5/2]" /// ); /// assert_eq!( /// exhaustive_rationals_with_denominator_inclusive_range( /// Natural::from(2u32), /// Rational::from_signeds(-5i32, 3), /// Rational::from_signeds(5i32, 2) /// ) /// .collect_vec() /// .to_debug_string(), /// "[1/2, -1/2, 3/2, -3/2, 5/2]" /// ); /// assert_eq!( /// exhaustive_rationals_with_denominator_inclusive_range( /// Natural::from(10u32), /// Rational::try_from_float_simplest(std::f64::consts::E).unwrap(), /// Rational::try_from_float_simplest(std::f64::consts::PI).unwrap(), /// ) /// .collect_vec() /// .to_debug_string(), /// "[29/10, 31/10]" /// ); /// ``` pub fn exhaustive_rationals_with_denominator_inclusive_range( d: Natural, a: Rational, b: Rational, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); assert!(a <= b); let q_d = Rational::from(&d); let a_i = Integer::rounding_from(a * &q_d, Ceiling).0; let b_i = Integer::rounding_from(b * q_d, Floor).0 + Integer::ONE; RationalsWithDenominator { numerators: exhaustive_integer_range(a_i, b_i), denominator: d, } } #[derive(Clone, Debug)] struct ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator { a: Rational, } impl ExhaustiveDependentPairsYsGenerator< Natural, Rational, RationalsWithDenominator, > for ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator { #[inline] fn get_ys(&self, d: &Natural) -> RationalsWithDenominator { exhaustive_rationals_with_denominator_range_to_infinity(d.clone(), self.a.clone()) } } #[inline] const fn exhaustive_rational_range_to_infinity_helper( a: Rational, ) -> ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator, ExhaustiveNaturalRangeToInfinity, RationalsWithDenominator, > { exhaustive_dependent_pairs( ruler_sequence(), exhaustive_positive_naturals(), ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator { a }, ) } /// Generates all [`Rational`]s greater than or equal to some [`Rational`]. /// /// This `struct` is created by [`exhaustive_rational_range_to_infinity`]; see its documentation for /// more. #[derive(Clone, Debug)] pub struct ExhaustiveRationalRangeToInfinity( ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeToInfinityGenerator, ExhaustiveNaturalRangeToInfinity, RationalsWithDenominator, >, ); impl Iterator for ExhaustiveRationalRangeToInfinity { type Item = Rational; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all [`Rational`]s greater than or equal to some [`Rational`] $a$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_q::exhaustive::exhaustive_rational_range_to_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rational_range_to_infinity(Rational::exact_from(std::f64::consts::PI)), /// 20 /// ), /// "[4, 7/2, 5, 10/3, 6, 9/2, 7, 13/4, 8, 11/2, 9, 11/3, 10, 13/2, 11, 16/5, 12, 15/2, 13, \ /// 13/3, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_rational_range_to_infinity( a: Rational, ) -> ExhaustiveRationalRangeToInfinity { ExhaustiveRationalRangeToInfinity(exhaustive_rational_range_to_infinity_helper(a)) } #[derive(Clone, Debug)] struct ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator { a: Rational, } impl ExhaustiveDependentPairsYsGenerator< Natural, Rational, RationalsWithDenominator, > for ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator { #[inline] fn get_ys( &self, d: &Natural, ) -> RationalsWithDenominator { exhaustive_rationals_with_denominator_range_to_negative_infinity(d.clone(), self.a.clone()) } } #[inline] const fn exhaustive_rational_range_to_negative_infinity_helper( a: Rational, ) -> ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator, ExhaustiveNaturalRangeToInfinity, RationalsWithDenominator, > { exhaustive_dependent_pairs( ruler_sequence(), exhaustive_positive_naturals(), ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator { a }, ) } /// Generates all [`Rational`]s less than or equal to some [`Rational`]. /// /// This `struct` is created by [`exhaustive_rational_range_to_negative_infinity`]; see its /// documentation for more. #[derive(Clone, Debug)] pub struct ExhaustiveRationalRangeToNegativeInfinity( ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeToNegativeInfinityGenerator, ExhaustiveNaturalRangeToInfinity, RationalsWithDenominator, >, ); impl Iterator for ExhaustiveRationalRangeToNegativeInfinity { type Item = Rational; #[inline] fn next(&mut self) -> Option { self.0.next().map(|p| p.1) } } /// Generates all [`Rational`]s less than or equal to some [`Rational`] $a$. /// /// The output length is infinite. /// /// # Worst-case complexity per iteration /// $T(i) = O(\log i (\log \log i)^2 \log\log\log i)$ /// /// $M(i) = O(\log i \log \log i)$ /// /// where $T$ is time, $M$ is additional memory, and $i$ is the iteration number. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_q::exhaustive::exhaustive_rational_range_to_negative_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rational_range_to_negative_infinity(Rational::exact_from( /// std::f64::consts::PI /// )), /// 20 /// ), /// "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3, -3/2, -4, 1/5, -5, 5/2, -6, \ /// 2/3, ...]" /// ) /// ``` #[inline] pub const fn exhaustive_rational_range_to_negative_infinity( a: Rational, ) -> ExhaustiveRationalRangeToNegativeInfinity { ExhaustiveRationalRangeToNegativeInfinity( exhaustive_rational_range_to_negative_infinity_helper(a), ) } #[derive(Clone, Debug)] struct ExhaustiveRationalsWithDenominatorRangeGenerator { a: Rational, b: Rational, } impl ExhaustiveDependentPairsYsGenerator< Natural, Rational, RationalsWithDenominator, > for ExhaustiveRationalsWithDenominatorRangeGenerator { #[inline] fn get_ys(&self, d: &Natural) -> RationalsWithDenominator { exhaustive_rationals_with_denominator_range(d.clone(), self.a.clone(), self.b.clone()) } } #[inline] fn exhaustive_rational_range_helper( a: Rational, b: Rational, ) -> ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeGenerator, DenominatorsInClosedRationalInterval, RationalsWithDenominator, > { exhaustive_dependent_pairs( ruler_sequence(), Rational::denominators_in_closed_interval(a.clone(), b.clone()), ExhaustiveRationalsWithDenominatorRangeGenerator { a, b }, ) } /// Generates all [`Natural`]s in an interval of the form $[a,b)$. /// /// This `struct` is created by [`exhaustive_rational_range`]; see its documentation for more. #[allow(private_interfaces, clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum ExhaustiveRationalRange { Empty, Nonempty( ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorRangeGenerator, DenominatorsInClosedRationalInterval, RationalsWithDenominator, >, ), } impl Iterator for ExhaustiveRationalRange { type Item = Rational; #[inline] fn next(&mut self) -> Option { match self { Self::Empty => None, Self::Nonempty(xs) => xs.next().map(|p| p.1), } } } /// Generates all [`Rational`]s in the half-open interval $[a, b)$. /// /// `a` must be less than or equal to `b`. If `a` and `b` are equal, the range is empty. To generate /// all [`Rational`]s in an infinite interval, use [`exhaustive_rational_range_to_infinity`] or /// [`exhaustive_rational_range_to_negative_infinity`]. /// /// The output length is infinite if $ab$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_q::exhaustive::exhaustive_rational_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rational_range( /// Rational::exact_from(std::f64::consts::E), /// Rational::exact_from(std::f64::consts::PI) /// ), /// 20 /// ), /// "[3, 11/4, 14/5, 20/7, 17/6, 23/8, 25/8, 30/11, 25/9, 29/10, 26/9, 31/11, 28/9, 31/10, \ /// 32/11, 41/15, 34/11, 35/12, 37/12, 39/14, ...]" /// ) /// ``` #[inline] pub fn exhaustive_rational_range(a: Rational, b: Rational) -> ExhaustiveRationalRange { if a == b { ExhaustiveRationalRange::Empty } else { ExhaustiveRationalRange::Nonempty(exhaustive_rational_range_helper(a, b)) } } #[derive(Clone, Debug)] struct ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator { a: Rational, b: Rational, } impl ExhaustiveDependentPairsYsGenerator< Natural, Rational, RationalsWithDenominator, > for ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator { #[inline] fn get_ys(&self, d: &Natural) -> RationalsWithDenominator { exhaustive_rationals_with_denominator_inclusive_range( d.clone(), self.a.clone(), self.b.clone(), ) } } #[inline] fn exhaustive_rational_inclusive_range_helper( a: Rational, b: Rational, ) -> ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator, DenominatorsInClosedRationalInterval, RationalsWithDenominator, > { exhaustive_dependent_pairs( ruler_sequence(), Rational::denominators_in_closed_interval(a.clone(), b.clone()), ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator { a, b }, ) } /// Generates all [`Rational`]s in an interval of the form $\[a,b\]$. /// /// This `struct` is created by [`exhaustive_rational_inclusive_range`]; see its documentation for /// more. #[allow(private_interfaces, clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum ExhaustiveRationalInclusiveRange { Single(bool, Rational), Many( ExhaustiveDependentPairs< Natural, Rational, RulerSequence, ExhaustiveRationalsWithDenominatorInclusiveRangeGenerator, DenominatorsInClosedRationalInterval, RationalsWithDenominator, >, ), } impl Iterator for ExhaustiveRationalInclusiveRange { type Item = Rational; #[inline] fn next(&mut self) -> Option { match self { Self::Single(done, x) => { if *done { None } else { *done = true; Some(x.clone()) } } Self::Many(xs) => xs.next().map(|p| p.1), } } } /// Generates all [`Rational`]s in the closed interval $[a, b]$. /// /// `a` must be less than or equal to `b`. If `a` and `b` are equal, the range contains a single /// element. To generate all [`Rational`]s in an infinite interval, use /// [`exhaustive_rational_range_to_infinity`] or [`exhaustive_rational_range_to_negative_infinity`]. /// /// The output length is infinite if $ab$. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::num::conversion::traits::ExactFrom; /// use malachite_q::exhaustive::exhaustive_rational_inclusive_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// exhaustive_rational_inclusive_range( /// Rational::exact_from(std::f64::consts::E), /// Rational::exact_from(std::f64::consts::PI) /// ), /// 20 /// ), /// "[3, 11/4, 14/5, 20/7, 17/6, 23/8, 25/8, 30/11, 25/9, 29/10, 26/9, 31/11, 28/9, 31/10, \ /// 32/11, 41/15, 34/11, 35/12, 37/12, 39/14, ...]" /// ) /// ``` #[inline] pub fn exhaustive_rational_inclusive_range( a: Rational, b: Rational, ) -> ExhaustiveRationalInclusiveRange { if a == b { ExhaustiveRationalInclusiveRange::Single(false, a) } else { ExhaustiveRationalInclusiveRange::Many(exhaustive_rational_inclusive_range_helper(a, b)) } } ================================================ FILE: malachite-q/src/lib.rs ================================================ // Copyright © 2026 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 . //! This crate defines [`Rational`]s. The name of this crate refers to the mathematical symbol for //! rational numbers, $$\mathbb{Q}$$. //! - There are many functions defined on [`Rational`]s. //! These include //! - All the ones you'd expect, like addition, subtraction, multiplication, and division; //! - Functions related to conversion between [`Rational`]s and other kinds of numbers, including //! primitive floats; //! - Functions for Diophantine approximation; //! - Functions for expressing [`Rational`]s in scientific notation. //! - The numerators and denominators of [`Rational`]s are stored as [`Natural`]s, so [`Rational`]s //! with small numerators and denominators can be stored entirely on the stack. //! - Most arithmetic involving [`Rational`]s requires (automatically) reducing the numerator and //! denominator. This is done very efficiently by using the high performance GCD and exact //! division algorithms implemented by [`Natural`]s. //! //! # Demos and benchmarks //! This crate comes with a `bin` target that can be used for running demos and benchmarks. //! - Almost all of the public functions in this crate have an associated demo. Running a demo //! shows you a function's behavior on a large number of inputs. For example, to demo //! [`Rational`] addition, you can use the following command: //! ```text //! cargo run --features bin_build --release -- -l 10000 -m exhaustive -d demo_rational_add //! ``` //! This command uses the `exhaustive` mode, which generates every possible input, generally //! starting with the simplest input and progressing to more complex ones. Another mode is //! `random`. The `-l` flag specifies how many inputs should be generated. //! - You can use a similar command to run benchmarks. The following command benchmarks various //! addition algorithms: //! ```text //! cargo run --features bin_build --release -- -l 1000000 -m random -b \ //! benchmark_rational_add_algorithms -o add-bench.gp //! ``` //! or addition implementations of other libraries: //! ```text //! cargo run --features bin_build --release -- -l 1000000 -m random -b \ //! benchmark_rational_add_assign_library_comparison -o add-bench.gp //! ``` //! This creates a file called gcd-bench.gp. You can use gnuplot to create an SVG from it like //! so: //! ```text //! gnuplot -e "set terminal svg; l \"gcd-bench.gp\"" > gcd-bench.svg //! ``` //! //! The list of available demos and benchmarks is not documented anywhere; you must find them by //! browsing through //! [`bin_util/demo_and_bench`](https://github.com/mhogrefe/malachite/tree/master/malachite-q/src/bin_util/demo_and_bench). //! //! # Features //! - `32_bit_limbs`: Sets the type of [`Limb`](malachite_nz#limbs) to [`u32`] instead of the //! default, [`u64`]. //! - `test_build`: A large proportion of the code in this crate is only used for testing. For a //! typical user, building this code would result in an unnecessarily long compilation time and //! an unnecessarily large binary. My solution is to only build this code when the `test_build` //! feature is enabled. If you want to run unit tests, you must enable `test_build`. However, //! doctests don't require it, since they only test the public interface. //! - `bin_build`: This feature is used to build the code for demos and benchmarks, which also //! takes a long time to build. Enabling this feature also enables `test_build`. #![allow( unstable_name_collisions, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity, clippy::upper_case_acronyms, clippy::multiple_bound_locations )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::use_self, clippy::trivially_copy_pass_by_ref )] #![cfg_attr( not(any(feature = "test_build", feature = "random", feature = "std")), no_std )] extern crate alloc; #[macro_use] extern crate malachite_base; extern crate malachite_nz; #[cfg(feature = "serde")] #[macro_use] extern crate serde; #[cfg(feature = "test_build")] extern crate itertools; #[cfg(feature = "test_build")] extern crate num; #[cfg(feature = "test_build")] extern crate rug; use malachite_base::named::Named; #[cfg(feature = "test_build")] use malachite_base::num::arithmetic::traits::CoprimeWith; use malachite_base::num::basic::traits::{NegativeOne, One, OneHalf, Two, Zero}; use malachite_base::num::logic::traits::SignificantBits; use malachite_nz::natural::Natural; /// A rational number. /// /// `Rational`s whose numerator and denominator have 64 significant bits or fewer can be represented /// without any memory allocation. (Unless Malachite is compiled with `32_bit_limbs`, in which case /// the limit is 32). #[derive(Clone, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Rational { // whether the `Rational` is non-negative #[cfg_attr(feature = "serde", serde(rename = "s"))] pub(crate) sign: bool, #[cfg_attr(feature = "serde", serde(rename = "n"))] pub(crate) numerator: Natural, #[cfg_attr(feature = "serde", serde(rename = "d"))] pub(crate) denominator: Natural, } impl Rational { // Returns true iff `self` is valid. // // To be valid, its denominator must be nonzero, its numerator and denominator must be // relatively prime, and if its numerator is zero, then `sign` must be `true`. All `Rational`s // must be valid. #[cfg(feature = "test_build")] pub fn is_valid(&self) -> bool { self.denominator != 0 && (self.sign || self.numerator != 0) && (&self.numerator).coprime_with(&self.denominator) } } impl SignificantBits for &Rational { /// Returns the sum of the bits needed to represent the numerator and denominator. /// /// # Worst-case complexity /// Constant time and additional memory. /// /// # Examples /// ``` /// use malachite_base::num::basic::traits::Zero; /// use malachite_base::num::logic::traits::SignificantBits; /// use malachite_q::Rational; /// use std::str::FromStr; /// /// assert_eq!(Rational::ZERO.significant_bits(), 1); /// assert_eq!( /// Rational::from_str("-100/101").unwrap().significant_bits(), /// 14 /// ); /// ``` fn significant_bits(self) -> u64 { self.numerator.significant_bits() + self.denominator.significant_bits() } } /// The constant 0. impl Zero for Rational { const ZERO: Self = Self { sign: true, numerator: Natural::ZERO, denominator: Natural::ONE, }; } /// The constant 1. impl One for Rational { const ONE: Self = Self { sign: true, numerator: Natural::ONE, denominator: Natural::ONE, }; } /// The constant 2. impl Two for Rational { const TWO: Self = Self { sign: true, numerator: Natural::TWO, denominator: Natural::ONE, }; } /// The constant -1. impl NegativeOne for Rational { const NEGATIVE_ONE: Self = Self { sign: false, numerator: Natural::ONE, denominator: Natural::ONE, }; } /// The constant 1/2. impl OneHalf for Rational { const ONE_HALF: Self = Self { sign: true, numerator: Natural::ONE, denominator: Natural::TWO, }; } impl Default for Rational { /// The default value of a [`Rational`], 0. fn default() -> Self { Self::ZERO } } // Implements `Named` for `Rational`. impl_named!(Rational); /// Traits for arithmetic. pub mod arithmetic; /// Traits for comparing [`Rational`]s for equality or order. pub mod comparison; /// Traits for converting to and from [`Rational`]s, converting to and from strings, and extracting /// digits and continued fractions. pub mod conversion; /// Iterators that generate [`Rational`]s without repetition. pub mod exhaustive; #[cfg(feature = "random")] /// Iterators that generate [`Rational`]s randomly. pub mod random; #[cfg(feature = "test_build")] pub mod test_util; ================================================ FILE: malachite-q/src/random/mod.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::arithmetic::denominators_in_closed_interval::DenominatorsInClosedRationalInterval; use crate::arithmetic::traits::DenominatorsInClosedInterval; use crate::exhaustive::RationalsWithDenominator; use core::cmp::min; use malachite_base::bools::random::{RandomBools, random_bools}; use malachite_base::iterators::iterator_cache::IteratorCache; use malachite_base::num::arithmetic::traits::{ CoprimeWith, Reciprocal, RoundToMultiple, UnsignedAbs, }; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom}; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::num::random::geometric::{ GeometricRandomNaturalValues, geometric_random_unsigneds, }; use malachite_base::num::random::striped::StripedBitSource; use malachite_base::num::random::{ RandomPrimitiveInts, VariableRangeGenerator, random_primitive_ints, }; use malachite_base::random::Seed; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::integer::random::{ RandomIntegerRange, RandomIntegerRangeToInfinity, get_random_integer_from_range_to_infinity, get_random_integer_from_range_to_negative_infinity, get_striped_random_integer_from_range_to_infinity, get_striped_random_integer_from_range_to_negative_infinity, random_integer_range, random_integer_range_to_infinity, random_integer_range_to_negative_infinity, }; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ RandomNaturals, StripedRandomNaturals, random_naturals, random_positive_naturals, striped_random_naturals, striped_random_positive_naturals, }; use std::collections::HashMap; /// Generates random non-negative [`Rational`]s, given an iterator of random [`Natural`] numerators /// and denominators. #[derive(Clone, Debug)] pub struct RandomRationalsFromSingle> { xs: I, } impl> Iterator for RandomRationalsFromSingle { type Item = Rational; fn next(&mut self) -> Option { Some(Rational::from_naturals( self.xs.next().unwrap(), self.xs.next().unwrap(), )) } } /// Generates random positive [`Rational`]s with a specified numerator and denominator mean bit /// length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. Then the numerator /// and denominator are chosen from all positive [`Natural`]s with that bit length. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_positive_rationals; /// /// assert_eq!( /// prefix_to_string(random_positive_rationals(EXAMPLE_SEED, 32, 1), 10), /// "[11/2, 89/27922830575, 46627409/3788983764809694, 8/11316951483471, \ /// 11/1005760138411689342464923704482, 948931/42716754, \ /// 81013760999253680590984897748479904878392/23, 1/97645164585502, 1558028859598/29, \ /// 200127331174844881647/4058622214797175252, ...]" /// ) /// ``` pub fn random_positive_rationals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromSingle>> { RandomRationalsFromSingle { xs: random_positive_naturals(seed, mean_bits_numerator, mean_bits_denominator), } } /// Generates random non-negative [`Rational`]s, given an iterator of random [`Natural`] numerators /// and an iterator of random [`Natural`] denominators. #[derive(Clone, Debug)] pub struct RandomRationalsFromDouble, J: Iterator> { xs: I, ys: J, } impl, J: Iterator> Iterator for RandomRationalsFromDouble { type Item = Rational; fn next(&mut self) -> Option { Some(Rational::from_naturals( self.xs.next().unwrap(), self.ys.next().unwrap(), )) } } /// Generates random non-negative [`Rational`]s with a specified numerator and denominator mean bit /// length. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_non_negative_rationals; /// /// assert_eq!( /// prefix_to_string(random_non_negative_rationals(EXAMPLE_SEED, 32, 1), 10), /// "[7301/34, 4183103/1234731190583, 54812347098686/6195807891591254727, 812739/17841539017, \ /// 665/908, 677/1138982845180, 166/22491855393807861245619791028129, 270142/5, \ /// 52040856788711439301087669967/15975369961878544862054, 5718607/1953563256716085077, ...]" /// ) /// ``` pub fn random_non_negative_rationals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromDouble< RandomNaturals>, RandomNaturals>, > { RandomRationalsFromDouble { xs: random_naturals( seed.fork("numerator"), mean_bits_numerator, mean_bits_denominator, ), ys: random_positive_naturals( seed.fork("denominator"), mean_bits_numerator, mean_bits_denominator, ), } } /// Generates random negative [`Rational`]s, given an iterator of positive [`Rational`]s. #[derive(Clone, Debug)] pub struct NegativeRationals> { xs: I, } impl> Iterator for NegativeRationals { type Item = Rational; fn next(&mut self) -> Option { self.xs.next().map(|mut q| { q.sign = false; q }) } } /// Generates random negative [`Rational`]s with a specified numerator and denominator mean bit /// length. /// /// The actual bit length is chosen from a geometric distribution with mean $m$, where $m$ is /// `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than 1. Then the numerator /// and denominator are chosen from all positive [`Natural`]s with that bit length. Finally, the /// resulting [`Rational`] is reduced and negated. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_negative_rationals; /// /// assert_eq!( /// prefix_to_string(random_negative_rationals(EXAMPLE_SEED, 32, 1), 10), /// "[-11/2, -89/27922830575, -46627409/3788983764809694, -8/11316951483471, \ /// -11/1005760138411689342464923704482, -948931/42716754, \ /// -81013760999253680590984897748479904878392/23, -1/97645164585502, -1558028859598/29, \ /// -200127331174844881647/4058622214797175252, ...]" /// ) /// ``` pub fn random_negative_rationals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> NegativeRationals>>> { NegativeRationals { xs: random_positive_rationals(seed, mean_bits_numerator, mean_bits_denominator), } } /// Generates random non-negative [`Rational`]s, given an iterator of random [`Natural`] numerators /// and an iterator of [`bool`] signs. #[derive(Clone, Debug)] pub struct RandomRationalsFromSingleAndSign> { bs: RandomBools, xs: I, } impl> Iterator for RandomRationalsFromSingleAndSign { type Item = Rational; fn next(&mut self) -> Option { Some(Rational::from_sign_and_naturals( self.bs.next().unwrap(), self.xs.next().unwrap(), self.xs.next().unwrap(), )) } } /// Generates random nonzero [`Rational`]s with a specified numerator and denominator mean bit /// length. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_nonzero_rationals; /// /// assert_eq!( /// prefix_to_string(random_nonzero_rationals(EXAMPLE_SEED, 32, 1), 10), /// "[-80861953616/9687130509484985, -14557437513/313, 100721397389/392237929981, \ /// 713431423/1285, -3887883364/889, 14185/969, 12609/11359517108746272468338071, \ /// 3443/4354945, 1/29, 5551/892095, ...]" /// ) /// ``` pub fn random_nonzero_rationals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromSingleAndSign>> { RandomRationalsFromSingleAndSign { bs: random_bools(seed.fork("sign")), xs: random_positive_naturals(seed.fork("abs"), mean_bits_numerator, mean_bits_denominator), } } /// Generates random non-negative [`Rational`]s, given an iterator of random [`Natural`] numerators, /// an iterator of random [`Natural`] denominators, and an iterator of [`bool`] signs. #[derive(Clone, Debug)] pub struct RandomRationalsFromDoubleAndSign< I: Iterator, J: Iterator, > { pub bs: RandomBools, pub xs: I, pub ys: J, } impl, J: Iterator> Iterator for RandomRationalsFromDoubleAndSign { type Item = Rational; fn next(&mut self) -> Option { Some(Rational::from_sign_and_naturals( self.bs.next().unwrap(), self.xs.next().unwrap(), self.ys.next().unwrap(), )) } } /// Generates random [`Rational`]s with a specified numerator and denominator mean bit length. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero or if `mean_bits_numerator /// <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_rationals; /// /// assert_eq!( /// prefix_to_string(random_rationals(EXAMPLE_SEED, 32, 1), 10), /// "[-7301/34, -4183103/1234731190583, 54812347098686/6195807891591254727, \ /// 812739/17841539017, -665/908, 677/1138982845180, 166/22491855393807861245619791028129, \ /// 270142/5, 52040856788711439301087669967/15975369961878544862054, \ /// 5718607/1953563256716085077, ...]" /// ) /// ``` pub fn random_rationals( seed: Seed, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromDoubleAndSign< RandomNaturals>, RandomNaturals>, > { RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: random_naturals( seed.fork("numerator"), mean_bits_numerator, mean_bits_denominator, ), ys: random_positive_naturals( seed.fork("denominator"), mean_bits_numerator, mean_bits_denominator, ), } } /// Generates striped random positive [`Rational`]s with a specified mean numerator and denominator /// bit length. /// /// The actual numerator and denominator bit lengths are chosen from a geometric distribution with /// mean $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than /// `1`. A striped bit sequence with the given stripe parameter is generated and truncated at the /// bit lengths to produce the numerators and denominators. The highest bits are forced to be `1`. /// Finally, the [`Rational`] is reduced. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_positive_rationals; /// /// assert_eq!( /// prefix_to_string( /// striped_random_positive_rationals(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[4, 1/268681216, 75493376/9007199120523391, 8/8796094070783, \ /// 8/950737950171027935941967741439, 1040391/33554432, \ /// 2813000899879757964630563421437095845888, 1/79164837199872, 2199023255551/16, \ /// 220784470296873664512/4611685966886694919, ...]" /// ) /// ``` pub fn striped_random_positive_rationals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromSingle>> { RandomRationalsFromSingle { xs: striped_random_positive_naturals( seed, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates striped random non-positive [`Rational`]s with a specified mean numerator and /// denominator bit length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_non_negative_rationals; /// /// assert_eq!( /// prefix_to_string( /// striped_random_non_negative_rationals(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[8192/127, 16776704/4396972769407, 8796093005951/648518346332962816, 87381/2863267840, \ /// 1024/2043, 51/58408828928, 85/13521606402434254795714066382848, 270335/7, \ /// 59421159664630116152453890047/9444741445172838006656, 6291455/1154891846623166464, ...]" /// ) /// ``` pub fn striped_random_non_negative_rationals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromDouble< StripedRandomNaturals>, StripedRandomNaturals>, > { RandomRationalsFromDouble { xs: striped_random_naturals( seed.fork("numerator"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), ys: striped_random_positive_naturals( seed.fork("denominator"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates striped random negative [`Rational`]s with a specified mean numerator and denominator /// bit length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_negative_rationals; /// /// assert_eq!( /// prefix_to_string( /// striped_random_negative_rationals(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[-4, -1/268681216, -75493376/9007199120523391, -8/8796094070783, \ /// -8/950737950171027935941967741439, -1040391/33554432, \ /// -2813000899879757964630563421437095845888, -1/79164837199872, -2199023255551/16, \ /// -220784470296873664512/4611685966886694919, ...]" /// ) /// ``` pub fn striped_random_negative_rationals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> NegativeRationals< RandomRationalsFromSingle>>, > { NegativeRationals { xs: striped_random_positive_rationals( seed, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates striped random nonzero [`Rational`]s with a specified mean numerator and denominator /// bit length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_nonzero_rationals; /// /// assert_eq!( /// prefix_to_string( /// striped_random_nonzero_rationals(EXAMPLE_SEED, 16, 1, 32, 1), /// 10 /// ), /// "[-68720000000/18006083452797439, -2545165805/29, 549754781664/1236950581247, \ /// 1065353727/2047, -2147745791/513, 16128/575, 8192/17000482516899619632318463, \ /// 18431/16778240, 1/31, 4096/526335, ...]" /// ) /// ``` pub fn striped_random_nonzero_rationals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromSingleAndSign>> { RandomRationalsFromSingleAndSign { bs: random_bools(seed.fork("sign")), xs: striped_random_positive_naturals( seed.fork("abs"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates striped random [`Rational`]s with a specified mean numerator and denominator bit /// length. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, or if /// `mean_bits_numerator <= mean_bits_denominator`. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_rationals; /// /// assert_eq!( /// prefix_to_string(striped_random_rationals(EXAMPLE_SEED, 16, 1, 32, 1), 10), /// "[-8192/127, -16776704/4396972769407, 8796093005951/648518346332962816, 87381/2863267840, \ /// -1024/2043, 51/58408828928, 85/13521606402434254795714066382848, 270335/7, \ /// 59421159664630116152453890047/9444741445172838006656, 6291455/1154891846623166464, ...]" /// ) /// ``` pub fn striped_random_rationals( seed: Seed, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalsFromDoubleAndSign< StripedRandomNaturals>, StripedRandomNaturals>, > { RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: striped_random_naturals( seed.fork("numerator"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), ys: striped_random_positive_naturals( seed.fork("denominator"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates random [`Rational`]s greater than or equal to a lower bound $a$ and with a specific /// denominator. /// /// The mean bit length $m$ of the absolute values of the numerators of the generated values is /// specified. $m$ is equal to `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::Natural; /// use malachite_q::random::random_rational_with_denominator_range_to_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_with_denominator_range_to_infinity( /// EXAMPLE_SEED, /// Natural::from(3u32), /// Rational::from_signeds(-3i32, 2), /// 3, /// 1 /// ), /// 10 /// ), /// "[1/3, 4/3, -2/3, 94/3, 4/3, -2/3, 1/3, 145/3, 7/3, 1/3, ...]" /// ) /// ``` pub fn random_rational_with_denominator_range_to_infinity( seed: Seed, d: Natural, a: Rational, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); RationalsWithDenominator { numerators: random_integer_range_to_infinity( seed, Integer::rounding_from(a * Rational::from(&d), Ceiling).0, mean_numerator_bits_numerator, mean_numerator_bits_denominator, ), denominator: d, } } /// Generates random [`Rational`]s less than or equal to a lower bound $a$ and with a specific /// denominator. /// /// The mean bit length $m$ of the absolute values of the numerators of the generated values is /// specified. $m$ is equal to `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a < 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::Natural; /// use malachite_q::random::random_rational_with_denominator_range_to_negative_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_with_denominator_range_to_negative_infinity( /// EXAMPLE_SEED, /// Natural::from(3u32), /// Rational::from_unsigneds(3u32, 2), /// 3, /// 1 /// ), /// 10 /// ), /// "[1/3, 4/3, -56/3, -2/3, 2/3, -1/3, -7/3, -11/3, -17/3, 4/3, ...]" /// ) /// ``` pub fn random_rational_with_denominator_range_to_negative_infinity( seed: Seed, d: Natural, a: Rational, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); RationalsWithDenominator { numerators: random_integer_range_to_negative_infinity( seed, Integer::rounding_from(a * Rational::from(&d), Floor).0, mean_numerator_bits_numerator, mean_numerator_bits_denominator, ), denominator: d, } } /// Generates random [`Rational`]s in the half-open interval $[a, b)$ and with a specific /// denominator. /// /// In general, the [`Rational`]s are not generated uniformly. Instead, [`Rational`]s whose /// numerators have smaller bit lengths are generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. It is not actually the mean /// bit length of the numerators, though it approaches the mean bit length of the numerators minus /// $\lceil ad \right$ as $\log (b/a)$ approaches infinity. $m$ cannot be 0, and must be greater /// than the bit length of the numerator of the generated [`Rational`] with the smallest absolute /// value, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if $a \geq b$, if `mean_numerator_bits_numerator` or `mean_numerator_bits_denominator` /// are zero, if their ratio is less than or equal to the bit length of the [`Rational`] with /// smallest absolute numerator in the range, or if they are too large and manipulating them leads /// to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::Natural; /// use malachite_q::random::random_rational_with_denominator_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_with_denominator_range( /// EXAMPLE_SEED, /// Natural::from(100u32), /// Rational::from_unsigneds(1u32, 3), /// Rational::from_unsigneds(1u32, 2), /// 3, /// 1 /// ), /// 10 /// ), /// "[41/100, 43/100, 41/100, 41/100, 39/100, 41/100, 49/100, 41/100, 41/100, 39/100, ...]" /// ) /// ``` pub fn random_rational_with_denominator_range( seed: Seed, d: Natural, a: Rational, b: Rational, mut mean_numerator_bits_numerator: u64, mut mean_numerator_bits_denominator: u64, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); assert!(a < b); let q_d = Rational::from(&d); let a_i = Integer::rounding_from(a * &q_d, Ceiling).0; let upper_included = b.denominator_ref() == &d; let mut b_i = Integer::rounding_from(b * q_d, Floor).0; if !upper_included { b_i += Integer::ONE; } if (a_i >= 0) == (b_i >= 0) { let (n, d) = (Rational::from_unsigneds( mean_numerator_bits_numerator, mean_numerator_bits_denominator, ) + Rational::from(min(a_i.significant_bits(), b_i.significant_bits()))) .into_numerator_and_denominator(); mean_numerator_bits_numerator = u64::exact_from(&n); mean_numerator_bits_denominator = u64::exact_from(&d); } RationalsWithDenominator { numerators: random_integer_range( seed, a_i, b_i, mean_numerator_bits_numerator, mean_numerator_bits_denominator, ), denominator: d, } } /// Generates random [`Rational`]s in the closed interval $[a, b]$ and with a specific denominator. /// /// In general, the [`Rational`]s are not generated uniformly. Instead, [`Rational`]s whose /// numerators have smaller bit lengths are generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. It is not actually the mean /// bit length of the numerators, though it approaches the mean bit length of the numerators minus /// $\lceil ad \right$ as $\log (b/a)$ approaches infinity. $m$ cannot be 0, and must be greater /// than the bit length of the numerator of the generated [`Rational`] with the smallest absolute /// value, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if $a > b$, if `mean_numerator_bits_numerator` or `mean_numerator_bits_denominator` are /// zero, if their ratio is less than or equal to the bit length of the [`Rational`] with smallest /// absolute numerator in the range, or if they are too large and manipulating them leads to /// arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_nz::natural::Natural; /// use malachite_q::random::random_rational_with_denominator_inclusive_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_with_denominator_inclusive_range( /// EXAMPLE_SEED, /// Natural::from(100u32), /// Rational::from_unsigneds(1u32, 3), /// Rational::from_unsigneds(1u32, 2), /// 3, /// 1 /// ), /// 10 /// ), /// "[41/100, 43/100, 41/100, 41/100, 39/100, 41/100, 49/100, 41/100, 41/100, 39/100, ...]" /// ) /// ``` pub fn random_rational_with_denominator_inclusive_range( seed: Seed, d: Natural, a: Rational, b: Rational, mut mean_numerator_bits_numerator: u64, mut mean_numerator_bits_denominator: u64, ) -> RationalsWithDenominator { assert_ne!(d, 0u32); assert!(a <= b); let q_d = Rational::from(&d); let a_i = Integer::rounding_from(a * &q_d, Ceiling).0; let b_i = Integer::rounding_from(b * q_d, Floor).0 + Integer::ONE; if (a_i >= 0) == (b_i >= 0) { let (n, d) = (Rational::from_unsigneds( mean_numerator_bits_numerator, mean_numerator_bits_denominator, ) + Rational::from(min(a_i.significant_bits(), b_i.significant_bits()))) .into_numerator_and_denominator(); mean_numerator_bits_numerator = u64::exact_from(&n); mean_numerator_bits_denominator = u64::exact_from(&d); } RationalsWithDenominator { numerators: random_integer_range( seed, a_i, b_i, mean_numerator_bits_numerator, mean_numerator_bits_denominator, ), denominator: d, } } /// Generates random [`Rational`]s greater than or equal to a lower bound. See /// [`random_rational_range_to_infinity`] for more details. #[derive(Clone, Debug)] pub struct RandomRationalRangeToInfinity { a: Rational, limbs: RandomPrimitiveInts, range_generator: VariableRangeGenerator, mean_bits_numerator: u64, mean_bits_denominator: u64, denominators: RandomNaturals>, } impl Iterator for RandomRationalRangeToInfinity { type Item = Rational; fn next(&mut self) -> Option { let d = self.denominators.next().unwrap(); let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Ceiling).0; let (numerator, denominator) = (Rational::from(d.significant_bits()) + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) .into_numerator_and_denominator(); let numerator = u64::exact_from(&numerator); let denominator = u64::exact_from(&denominator); loop { let n = get_random_integer_from_range_to_infinity( &mut self.limbs, &mut self.range_generator, numerator_bound.clone(), numerator, denominator, ); if n.unsigned_abs_ref().coprime_with(&d) { return Some(Rational { sign: n >= 0, numerator: n.unsigned_abs(), denominator: d, }); } } } } /// Generates random [`Rational`]s greater than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the absolute values of the numerators of the generated values is /// specified. $m$ is equal to `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_rational_range_to_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_range_to_infinity(EXAMPLE_SEED, Rational::from_signeds(-3i32, 2), 3, 1), /// 10 /// ), /// "[2/3, 56, 1/2, -1/34, -15/23, -4/5, 1/2, 5, 195, -1, ...]" /// ) /// ``` pub fn random_rational_range_to_infinity( seed: Seed, a: Rational, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalRangeToInfinity { RandomRationalRangeToInfinity { a, limbs: random_primitive_ints(seed.fork("limbs")), range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: random_positive_naturals( seed.fork("denominators"), mean_bits_numerator, mean_bits_denominator, ), } } /// Generates random [`Rational`]s less than or equal to a lower bound. See /// [`random_rational_range_to_negative_infinity`] for more details. #[derive(Clone, Debug)] pub struct RandomRationalRangeToNegativeInfinity { a: Rational, limbs: RandomPrimitiveInts, range_generator: VariableRangeGenerator, mean_bits_numerator: u64, mean_bits_denominator: u64, denominators: RandomNaturals>, } impl Iterator for RandomRationalRangeToNegativeInfinity { type Item = Rational; fn next(&mut self) -> Option { let d = self.denominators.next().unwrap(); let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Floor).0; let (numerator, denominator) = (Rational::from(d.significant_bits()) + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) .into_numerator_and_denominator(); let numerator = u64::exact_from(&numerator); let denominator = u64::exact_from(&denominator); loop { let n = get_random_integer_from_range_to_negative_infinity( &mut self.limbs, &mut self.range_generator, numerator_bound.clone(), numerator, denominator, ); if n.unsigned_abs_ref().coprime_with(&d) { return Some(Rational { sign: n >= 0, numerator: n.unsigned_abs(), denominator: d, }); } } } } /// Generates random [`Rational`]s less than or equal to a lower bound $a$. /// /// The mean bit length $m$ of the absolute values of the numerators of the generated values is /// specified. $m$ is equal to `mean_bits_numerator / mean_bits_denominator`. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_bits_numerator / /// mean_bits_denominator`. /// /// # Panics /// Panics if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > 0$ and their ratio /// is less than or equal to the bit length of $a$, or if they are too large and manipulating them /// leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_rational_range_to_negative_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_range_to_negative_infinity( /// EXAMPLE_SEED, /// Rational::from_signeds(-3i32, 2), /// 3, /// 1 /// ), /// 10 /// ), /// "[-8/3, -114, -31/2, -1187/34, -61/23, -81/5, -3/2, -19, -82, -312, ...]" /// ) /// ``` pub fn random_rational_range_to_negative_infinity( seed: Seed, a: Rational, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> RandomRationalRangeToNegativeInfinity { RandomRationalRangeToNegativeInfinity { a, limbs: random_primitive_ints(seed.fork("limbs")), range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: random_positive_naturals( seed.fork("denominators"), mean_bits_numerator, mean_bits_denominator, ), } } /// Generates random [`Rational`]s in a half-open interval $[a,b)$. See [`random_rational_range`] /// for more details. #[derive(Clone, Debug)] pub struct RandomRationalRange { seed: Seed, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, a: Rational, b: Rational, denominators: IteratorCache, denominator_map: HashMap>, indices: GeometricRandomNaturalValues, } impl Iterator for RandomRationalRange { type Item = Rational; fn next(&mut self) -> Option { loop { let d = self.denominators.get(self.indices.next().unwrap()).unwrap(); if (&self.a) .round_to_multiple(Rational::from(d).reciprocal(), Ceiling) .0 >= self.b { // This can happen when d is the denominator of b continue; } return self .denominator_map .entry(d.clone()) .or_insert_with(|| { random_rational_with_denominator_range( self.seed.fork(&d.to_string()), d.clone(), self.a.clone(), self.b.clone(), self.mean_numerator_bits_numerator, self.mean_numerator_bits_denominator, ) }) .next(); } } } /// Generates random [`Rational`]s in the half-open interval $[a, b)$. /// /// In general, the [`Rational`]s are not generated uniformly. Instead, [`Rational`]s whose /// numerators have smaller bit lengths are generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. It is not actually the mean /// bit length of the numerators, though it approaches the mean bit length of the numerators minus /// $\lceil ad \right$ as $\log (b/a)$ approaches infinity. $m$ cannot be 0, and must be greater /// than the bit length of the numerator of the generated [`Rational`] with the smallest absolute /// value, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// The distribution of denominators is parametrized by `mean_denominator_index_numerator / /// mean_denominator_index_denominator.` The larger this value is, the larger the average /// denominator produced. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if $a \geq b$, if `mean_numerator_bits_numerator`, `mean_numerator_bits_denominator`, /// `mean_denominator_index_numerator`, or `mean_denominator_index_denominator` are zero, if /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator` is less than or equal to the /// bit length of the [`Rational`] with smallest absolute numerator in the range, or if any of these /// values are too are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_rational_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_range( /// EXAMPLE_SEED, /// Rational::from_unsigneds(1u32, 3), /// Rational::from_unsigneds(1u32, 2), /// 3, /// 1, /// 10, /// 1 /// ), /// 10 /// ), /// "[1/3, 4/9, 7/19, 5/13, 13/28, 4/9, 5/14, 7/19, 14/33, 8/17, ...]" /// ) /// ``` pub fn random_rational_range( seed: Seed, a: Rational, b: Rational, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, mean_denominator_index_numerator: u64, mean_denominator_index_denominator: u64, ) -> RandomRationalRange { assert!(a < b); assert_ne!(mean_numerator_bits_denominator, 0); assert_ne!(mean_denominator_index_denominator, 0); RandomRationalRange { seed: seed.fork("numerators"), mean_numerator_bits_numerator, mean_numerator_bits_denominator, a: a.clone(), b: b.clone(), denominators: IteratorCache::new(Rational::denominators_in_closed_interval(a, b)), denominator_map: HashMap::new(), indices: geometric_random_unsigneds( seed.fork("indices"), mean_denominator_index_numerator, mean_denominator_index_denominator, ), } } #[doc(hidden)] #[derive(Clone, Debug)] pub struct RandomRationalInclusiveRangeInner { seed: Seed, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, a: Rational, b: Rational, denominators: IteratorCache, denominator_map: HashMap>, indices: GeometricRandomNaturalValues, } impl Iterator for RandomRationalInclusiveRangeInner { type Item = Rational; fn next(&mut self) -> Option { let d = self.denominators.get(self.indices.next().unwrap()).unwrap(); self.denominator_map .entry(d.clone()) .or_insert_with(|| { random_rational_with_denominator_inclusive_range( self.seed.fork(&d.to_string()), d.clone(), self.a.clone(), self.b.clone(), self.mean_numerator_bits_numerator, self.mean_numerator_bits_denominator, ) }) .next() } } /// Generates random [`Rational`]s in a closed interval $\[a,b\]$. See /// [`random_rational_inclusive_range`] for more details. #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)] pub enum RandomRationalInclusiveRange { Single(Rational), Multiple(RandomRationalInclusiveRangeInner), } impl Iterator for RandomRationalInclusiveRange { type Item = Rational; fn next(&mut self) -> Option { match self { Self::Single(x) => Some(x.clone()), Self::Multiple(xs) => xs.next(), } } } /// Generates random [`Rational`]s in the closed interval $[a, b]$. /// /// In general, the [`Rational`]s are not generated uniformly. Instead, [`Rational`]s whose /// numerators have smaller bit lengths are generated more frequently. /// /// The distribution of generated values is parametrized by a number $m$, given by /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator`. It is not actually the mean /// bit length of the numerators, though it approaches the mean bit length of the numerators minus /// $\lceil ad \right$ as $\log (b/a)$ approaches infinity. $m$ cannot be 0, and must be greater /// than the bit length of the numerator of the generated [`Rational`] with the smallest absolute /// value, but it may be arbitrarily large. The smaller it is, the more quickly the probabilities /// decrease as bit length increases. The larger it is, the more closely the distribution approaches /// a uniform distribution over the bit lengths. /// /// The distribution of denominators is parametrized by `mean_denominator_index_numerator / /// mean_denominator_index_denominator.` The larger this value is, the larger the average /// denominator produced. /// /// The output length is infinite. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if $a>b$, if `mean_numerator_bits_numerator`, `mean_numerator_bits_denominator`, /// `mean_denominator_index_numerator`, or `mean_denominator_index_denominator` are zero, if /// `mean_numerator_bits_numerator / mean_numerator_bits_denominator` is less than or equal to the /// bit length of the [`Rational`] with smallest absolute numerator in the range, or if any of these /// values are too are too large and manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::random_rational_inclusive_range; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// random_rational_inclusive_range( /// EXAMPLE_SEED, /// Rational::from_unsigneds(1u32, 3), /// Rational::from_unsigneds(1u32, 2), /// 3, /// 1, /// 10, /// 1 /// ), /// 10 /// ), /// "[1/3, 4/9, 1/2, 7/19, 5/13, 13/28, 1/2, 4/9, 1/2, 5/14, ...]" /// ) /// ``` pub fn random_rational_inclusive_range( seed: Seed, a: Rational, b: Rational, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, mean_denominator_index_numerator: u64, mean_denominator_index_denominator: u64, ) -> RandomRationalInclusiveRange { assert!(a <= b); if a == b { return RandomRationalInclusiveRange::Single(a); } assert_ne!(mean_numerator_bits_denominator, 0); assert_ne!(mean_denominator_index_denominator, 0); RandomRationalInclusiveRange::Multiple(RandomRationalInclusiveRangeInner { seed: seed.fork("numerators"), mean_numerator_bits_numerator, mean_numerator_bits_denominator, a: a.clone(), b: b.clone(), denominators: IteratorCache::new(Rational::denominators_in_closed_interval(a, b)), denominator_map: HashMap::new(), indices: geometric_random_unsigneds( seed.fork("indices"), mean_denominator_index_numerator, mean_denominator_index_denominator, ), }) } /// Generates striped random [`Rational`]s greater than or equal to a lower bound. See /// [`striped_random_rational_range_to_infinity`] for more details. #[derive(Clone, Debug)] pub struct StripedRandomRationalRangeToInfinity { a: Rational, xs: StripedBitSource, range_generator: VariableRangeGenerator, mean_bits_numerator: u64, mean_bits_denominator: u64, denominators: StripedRandomNaturals>, } impl Iterator for StripedRandomRationalRangeToInfinity { type Item = Rational; fn next(&mut self) -> Option { let d = self.denominators.next().unwrap(); let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Ceiling).0; let (numerator, denominator) = (Rational::from(d.significant_bits()) + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) .into_numerator_and_denominator(); let numerator = u64::exact_from(&numerator); let denominator = u64::exact_from(&denominator); loop { let n = get_striped_random_integer_from_range_to_infinity( &mut self.xs, &mut self.range_generator, numerator_bound.clone(), numerator, denominator, ); if n.unsigned_abs_ref().coprime_with(&d) { return Some(Rational { sign: n >= 0, numerator: n.unsigned_abs(), denominator: d, }); } } } } /// Generates striped random [`Rational`]s greater than or equal to a lower bound $a$. /// /// The actual numerator and denominator bit lengths are chosen from a geometric distribution with /// mean $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than /// `1`. A striped bit sequence with the given stripe parameter is generated and truncated at the /// bit lengths to produce the numerators and denominators. The highest bits are forced to be `1`. /// Finally, the [`Rational`] is reduced. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a > /// 0$ and their ratio is less than or equal to the bit length of $a$, or if they are too large and /// manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_rational_range_to_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// striped_random_rational_range_to_infinity( /// EXAMPLE_SEED, /// Rational::from_signeds(-3i32, 2), /// 10, /// 1, /// 3, /// 1 /// ), /// 10 /// ), /// "[3/2, 39, 239/2, -32/63, 127/16, 16383/4, -1/2, 1, 583664, 1, ...]" /// ) /// ``` pub fn striped_random_rational_range_to_infinity( seed: Seed, a: Rational, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomRationalRangeToInfinity { StripedRandomRationalRangeToInfinity { a, xs: StripedBitSource::new( seed.fork("xs"), mean_stripe_numerator, mean_stripe_denominator, ), range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: striped_random_positive_naturals( seed.fork("denominators"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } /// Generates random striped [`Rational`]s less than or equal to a lower bound. See /// [`striped_random_rational_range_to_negative_infinity`] for more details. #[derive(Clone, Debug)] pub struct StripedRandomRationalRangeToNegativeInfinity { a: Rational, xs: StripedBitSource, range_generator: VariableRangeGenerator, mean_bits_numerator: u64, mean_bits_denominator: u64, denominators: StripedRandomNaturals>, } impl Iterator for StripedRandomRationalRangeToNegativeInfinity { type Item = Rational; fn next(&mut self) -> Option { let d = self.denominators.next().unwrap(); let numerator_bound = Integer::rounding_from(&self.a * Rational::from(&d), Floor).0; let (numerator, denominator) = (Rational::from(d.significant_bits()) + Rational::from_unsigneds(self.mean_bits_numerator, self.mean_bits_denominator)) .into_numerator_and_denominator(); let numerator = u64::exact_from(&numerator); let denominator = u64::exact_from(&denominator); loop { let n = get_striped_random_integer_from_range_to_negative_infinity( &mut self.xs, &mut self.range_generator, numerator_bound.clone(), numerator, denominator, ); if n.unsigned_abs_ref().coprime_with(&d) { return Some(Rational { sign: n >= 0, numerator: n.unsigned_abs(), denominator: d, }); } } } } /// Generates striped random [`Rational`]s less than or equal to a lower bound $a$. /// /// The actual numerator and denominator bit lengths are chosen from a geometric distribution with /// mean $m$, where $m$ is `mean_bits_numerator / mean_bits_denominator`; $m$ must be greater than /// `1`. A striped bit sequence with the given stripe parameter is generated and truncated at the /// bit lengths to produce the numerators and denominators. The highest bits are forced to be `1`. /// Finally, the [`Rational`] is reduced. /// /// The output length is infinite. /// /// See [`StripedBitSource`] for information about generating striped random numbers. /// /// # Expected complexity per iteration /// $T(n) = O(n (\log n)^2 \log\log n)$ /// /// $M(n) = O(n \log n)$ /// /// where $T$ is time, $M$ is additional memory, and $n$ is `mean_numerator_bits_numerator / /// mean_numerator_bits_denominator`. /// /// # Panics /// Panics if `mean_stripe_denominator` is zero, if `mean_stripe_numerator < /// mean_stripe_denominator`, if `mean_bits_numerator` or `mean_bits_denominator` are zero, if $a < /// 0$ and their ratio is less than or equal to the bit length of $a$, or if they are too large and /// manipulating them leads to arithmetic overflow. /// /// # Examples /// ``` /// use malachite_base::iterators::prefix_to_string; /// use malachite_base::random::EXAMPLE_SEED; /// use malachite_q::random::striped_random_rational_range_to_negative_infinity; /// use malachite_q::Rational; /// /// assert_eq!( /// prefix_to_string( /// striped_random_rational_range_to_negative_infinity( /// EXAMPLE_SEED, /// Rational::from_signeds(-3i32, 2), /// 10, /// 1, /// 3, /// 1 /// ), /// 10 /// ), /// "[-79/2, -7, -1051/2, -95/63, -255/16, -159/4, -3/2, -16, -2, -22, ...]" /// ) /// ``` pub fn striped_random_rational_range_to_negative_infinity( seed: Seed, a: Rational, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, ) -> StripedRandomRationalRangeToNegativeInfinity { StripedRandomRationalRangeToNegativeInfinity { a, xs: StripedBitSource::new( seed.fork("xs"), mean_stripe_numerator, mean_stripe_denominator, ), range_generator: VariableRangeGenerator::new(seed.fork("range generator")), mean_bits_numerator, mean_bits_denominator, denominators: striped_random_positive_naturals( seed.fork("denominators"), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), } } ================================================ FILE: malachite-q/src/test_util/arithmetic/add.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_base::num::basic::traits::Zero; use malachite_nz::integer::Integer; pub fn add_naive(x: Rational, y: Rational) -> Rational { let x_sign = x >= 0u32; let y_sign = y >= 0u32; let (xn, xd) = x.into_numerator_and_denominator(); let (yn, yd) = y.into_numerator_and_denominator(); let n = Integer::from_sign_and_abs(x_sign, xn * &yd) + Integer::from_sign_and_abs(y_sign, yn * &xd); Rational::from_sign_and_naturals(n >= 0u32, n.unsigned_abs(), xd * yd) } pub fn rational_sum_naive>(xs: I) -> Rational { let mut s = Rational::ZERO; for x in xs { s += x; } s } ================================================ FILE: malachite-q/src/test_util/arithmetic/approximate.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{Reciprocal, RoundToMultiple}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_natural_inclusive_range; // Slow! Only use for small `max_denominator`s pub fn approximate_naive(x: &Rational, max_denominator: &Natural) -> Rational { let mut nearest = Rational::ZERO; for d in exhaustive_natural_inclusive_range(Natural::ONE, max_denominator.clone()) { let q = x .round_to_multiple(Rational::from(d).reciprocal(), Nearest) .0; if (x - &q).lt_abs(&(x - &nearest)) { nearest = q; } } nearest } ================================================ FILE: malachite-q/src/test_util/arithmetic/div.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::Zero; pub fn div_naive(x: Rational, y: Rational) -> Rational { if x == 0u32 { Rational::ZERO } else if y == 0u32 { panic!("division by zero"); } else { let sign = (x >= 0) == (y >= 0); let (xn, xd) = x.into_numerator_and_denominator(); let (yn, yd) = y.into_numerator_and_denominator(); Rational::from_sign_and_naturals(sign, xn * yd, xd * yn) } } ================================================ FILE: malachite-q/src/test_util/arithmetic/mod.rs ================================================ // Copyright © 2026 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 . pub mod add; pub mod approximate; pub mod div; pub mod mod_op; pub mod mul; pub mod sign; pub mod simplest_rational_in_interval; pub mod sub; ================================================ FILE: malachite-q/src/test_util/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::{Abs, Ceiling, Floor}; pub fn mod_op_naive(x: Rational, y: Rational) -> Rational { let q = &x / &y; x - y * Rational::from(q.floor()) } pub fn rem_naive(x: Rational, y: Rational) -> Rational { let q = &x / &y; let sign = (x >= 0u32) == (y >= 0u32); let z = y * Rational::from(q.abs().floor()); if sign { x - z } else { x + z } } pub fn ceiling_mod_naive(x: Rational, y: Rational) -> Rational { let q = &x / &y; x - y * Rational::from(q.ceiling()) } ================================================ FILE: malachite-q/src/test_util/arithmetic/mul.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::traits::{One, Zero}; pub fn mul_naive(x: Rational, y: Rational) -> Rational { if x == 0u32 || y == 0u32 { Rational::ZERO } else { let sign = (x >= 0) == (y >= 0); let (xn, xd) = x.into_numerator_and_denominator(); let (yn, yd) = y.into_numerator_and_denominator(); Rational::from_sign_and_naturals(sign, xn * yn, xd * yd) } } pub fn rational_product_naive>(xs: I) -> Rational { let mut p = Rational::ONE; for x in xs { if x == 0 { return Rational::ZERO; } p *= x; } p } ================================================ FILE: malachite-q/src/test_util/arithmetic/sign.rs ================================================ // Copyright © 2026 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 num::BigRational; use num::bigint::Sign; use std::cmp::Ordering::{self, *}; pub fn num_sign(x: &BigRational) -> Ordering { match x.numer().sign() { Sign::NoSign => Equal, Sign::Plus => Greater, Sign::Minus => Less, } } ================================================ FILE: malachite-q/src/test_util/arithmetic/simplest_rational_in_interval.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::traits::ContinuedFraction; use itertools::Itertools; use malachite_base::num::arithmetic::traits::{Reciprocal, RoundToMultiple}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_positive_naturals; use std::cmp::{Ordering::*, min}; // Slow! Only run for rationals with small denominators pub fn simplest_rational_in_open_interval_naive(x: &Rational, y: &Rational) -> Rational { assert!(x < y); if *x < 0u32 && *y > 0u32 { return Rational::ZERO; } let neg_x; let neg_y; let (neg, x, y) = if *x < 0u32 { neg_x = -x; neg_y = -y; (true, &neg_y, &neg_x) } else { (false, x, y) }; for d in exhaustive_positive_naturals() { let dr = Rational::from(d).reciprocal(); let mut q = x.round_to_multiple(&dr, Ceiling).0; if q == *x { q += dr; } if q < *y { return if neg { -q } else { q }; } } unreachable!() } fn simplest_rational_helper( floor_x: &Integer, floor_y: &Integer, cf_x: &[Natural], cf_y: &[Natural], ) -> Rational { if floor_x != floor_y { return Rational::from(min(floor_x, floor_y) + Integer::ONE); } let floor = floor_x; for (i, (x, y)) in cf_x.iter().zip(cf_y.iter()).enumerate() { if x != y { let mut cf = cf_x[..i].to_vec(); cf.push(min(x, y) + Natural::ONE); return Rational::from_continued_fraction_ref(floor, cf.iter()); } } let x_len = cf_x.len(); let y_len = cf_y.len(); Rational::from_continued_fraction( floor.clone(), match x_len.cmp(&y_len) { Equal => panic!(), Greater => { let mut cf = cf_y.to_vec(); cf.push(cf_x[y_len].clone() + Natural::ONE); cf.into_iter() } Less => { let mut cf = cf_x.to_vec(); cf.push(cf_y[x_len].clone() + Natural::ONE); cf.into_iter() } }, ) } fn cf_variants(x: &Rational) -> (Integer, Integer, Vec, Vec) { let (floor_1, cf_1) = x.continued_fraction(); let cf_1 = cf_1.collect_vec(); let mut cf_2 = cf_1.clone(); let mut floor_2 = floor_1.clone(); if let Some(last) = cf_2.last_mut() { *last -= Natural::ONE; } else { floor_2 -= Integer::ONE; } cf_2.push(Natural::ONE); (floor_1, floor_2, cf_1, cf_2) } pub fn simplest_rational_in_open_interval_explicit(x: &Rational, y: &Rational) -> Rational { assert!(x < y); if *x < 0u32 && *y > 0u32 { return Rational::ZERO; } let neg_x; let neg_y; let (neg, x, y) = if *x < 0u32 { neg_x = -x; neg_y = -y; (true, &neg_y, &neg_x) } else { (false, x, y) }; let (floor_x_1, floor_x_2, cf_x_1, cf_x_2) = cf_variants(x); let (floor_y_1, floor_y_2, cf_y_1, cf_y_2) = cf_variants(y); let mut best: Option = None; for (floor_x, cf_x) in [(&floor_x_1, &cf_x_1), (&floor_x_2, &cf_x_2)] { for (floor_y, cf_y) in [(&floor_y_1, &cf_y_1), (&floor_y_2, &cf_y_2)] { let candidate = simplest_rational_helper(floor_x, floor_y, cf_x, cf_y); if candidate > *x && candidate < *y && (best.is_none() || candidate.denominator_ref() < best.as_ref().unwrap().denominator_ref()) { best = Some(candidate); } } } let best = best.unwrap(); if neg { -best } else { best } } // Slow! Only run for rationals with small denominators pub fn simplest_rational_in_closed_interval_naive(x: &Rational, y: &Rational) -> Rational { assert!(x <= y); if *x <= 0u32 && *y >= 0u32 { return Rational::ZERO; } let neg_x; let neg_y; let (neg, x, y) = if *x < 0u32 { neg_x = -x; neg_y = -y; (true, &neg_y, &neg_x) } else { (false, x, y) }; for d in exhaustive_positive_naturals() { let dr = Rational::from(d).reciprocal(); let q = x.round_to_multiple(&dr, Ceiling).0; if q <= *y { return if neg { -q } else { q }; } } unreachable!() } ================================================ FILE: malachite-q/src/test_util/arithmetic/sub.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::UnsignedAbs; use malachite_nz::integer::Integer; pub fn sub_naive(x: Rational, y: Rational) -> Rational { let x_sign = x >= 0u32; let y_sign = y >= 0u32; let (xn, xd) = x.into_numerator_and_denominator(); let (yn, yd) = y.into_numerator_and_denominator(); let n = Integer::from_sign_and_abs(x_sign, xn * &yd) - Integer::from_sign_and_abs(y_sign, yn * &xd); Rational::from_sign_and_naturals(n >= 0u32, n.unsigned_abs(), xd * yd) } ================================================ FILE: malachite-q/src/test_util/bench/bucketers.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::logic::traits::SignificantBits; use malachite_base::test_util::bench::bucketers::Bucketer; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use std::cmp::max; pub fn rational_bit_bucketer(var_name: &str) -> Bucketer<'_, Rational> { Bucketer { bucketing_function: &|q| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_pair_1_rational_bit_bucketer( var_name: &str, ) -> Bucketer<'_, (T, (Rational, U))> { Bucketer { bucketing_function: &|(_, (q, _))| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_pair_1_rational_bit_bucketer( var_name: &str, ) -> Bucketer<'_, (T, U, (Rational, V))> { Bucketer { bucketing_function: &|(_, _, (q, _))| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_1_rational_bit_bucketer(var_name: &str) -> Bucketer<'_, (Rational, T)> { Bucketer { bucketing_function: &|(q, _)| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_2_rational_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, Rational)> { Bucketer { bucketing_function: &|(_, q)| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_1_rational_bit_bucketer(var_name: &str) -> Bucketer<'_, (Rational, T, U)> { Bucketer { bucketing_function: &|(q, _, _)| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn triple_3_rational_bit_bucketer(var_name: &str) -> Bucketer<'_, (T, U, Rational)> { Bucketer { bucketing_function: &|(_, _, q)| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn quadruple_1_rational_bit_bucketer( var_name: &str, ) -> Bucketer<'_, (Rational, T, U, V)> { Bucketer { bucketing_function: &|(q, _, _, _)| usize::exact_from(q.significant_bits()), bucketing_label: format!("{var_name}.significant_bits()"), } } pub fn pair_rational_max_bit_bucketer<'a>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (Rational, Rational)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_pair_rational_max_bit_bucketer<'a, T>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, (Rational, Rational))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn triple_3_pair_rational_max_bit_bucketer<'a, T, U>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, U, (Rational, Rational))> { Bucketer { bucketing_function: &|(_, _, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_rational_integer_max_bit_bucketer<'a, T>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, (Rational, Integer))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn rational_natural_max_bit_bucketer<'a>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (Rational, Natural)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn rational_integer_max_bit_bucketer<'a>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (Rational, Integer)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn pair_2_rational_natural_max_bit_bucketer<'a, T>( x_name: &str, y_name: &str, ) -> Bucketer<'a, (T, (Rational, Natural))> { Bucketer { bucketing_function: &|(_, (x, y))| { usize::exact_from(max(x.significant_bits(), y.significant_bits())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.significant_bits())"), } } pub fn rational_deserialize_bucketer<'a>() -> Bucketer<'a, (String, String, String)> { Bucketer { bucketing_function: &|(_, _, s)| { let n: Rational = serde_json::from_str(s).unwrap(); usize::exact_from(n.significant_bits()) }, bucketing_label: "n.significant_bits()".to_string(), } } pub fn triple_3_pair_1_rational_bits_times_pair_2_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Rational, u64))> { Bucketer { bucketing_function: &|&(_, _, (ref x, y))| usize::exact_from(x.significant_bits() * y), bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn triple_3_pair_1_rational_bits_times_abs_pair_2_bucketer<'a, T, U>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (T, U, (Rational, i64))> { Bucketer { bucketing_function: &|&(_, _, (ref x, y))| { usize::exact_from(x.significant_bits() * y.unsigned_abs()) }, bucketing_label: format!("{x_name}.significant_bits() * {y_name}"), } } pub fn triple_1_2_rational_bit_i64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Rational, i64, T)> { Bucketer { bucketing_function: &|(x, y, _)| { usize::exact_from(max(x.significant_bits(), y.unsigned_abs())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn vec_rational_sum_bits_bucketer<'a>() -> Bucketer<'a, Vec> { Bucketer { bucketing_function: &|xs| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn triple_3_vec_rational_sum_bits_bucketer<'a, T, U>() -> Bucketer<'a, (T, U, Vec)> { Bucketer { bucketing_function: &|(_, _, xs)| { usize::exact_from( xs.iter() .map(SignificantBits::significant_bits) .sum::(), ) }, bucketing_label: "xs.map(|x| x.significant_bits()).sum()".to_string(), } } pub fn pair_rational_bit_i64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Rational, i64)> { Bucketer { bucketing_function: &|(x, y)| { usize::exact_from(max(x.significant_bits(), y.unsigned_abs())) }, bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.unsigned_abs())"), } } pub fn pair_rational_bit_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Rational, u64)> { Bucketer { bucketing_function: &|(x, y)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name}.unsigned_abs())"), } } pub fn triple_1_2_rational_bit_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, ) -> Bucketer<'a, (Rational, u64, T)> { Bucketer { bucketing_function: &|(x, y, _)| usize::exact_from(max(x.significant_bits(), *y)), bucketing_label: format!("max({x_name}.significant_bits(), {y_name})"), } } pub fn triple_rational_bit_i64_u64_max_bucketer<'a>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Rational, i64, u64)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn quadruple_1_2_3_rational_bit_i64_u64_max_bucketer<'a, T>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Rational, i64, u64, T)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!(x.significant_bits(), y.unsigned_abs(), *z)) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.unsigned_abs(), {z_name})" ), } } pub fn triple_rational_rational_primitive_int_max_bit_bucketer<'a, T: PrimitiveInt>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Rational, Rational, T)> { Bucketer { bucketing_function: &|(x, y, z)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits())" ), } } pub fn quadruple_1_2_3_rational_rational_primitive_int_max_bit_bucketer<'a, T: PrimitiveInt, U>( x_name: &'a str, y_name: &'a str, z_name: &'a str, ) -> Bucketer<'a, (Rational, Rational, T, U)> { Bucketer { bucketing_function: &|(x, y, z, _)| { usize::exact_from(max!( x.significant_bits(), y.significant_bits(), z.significant_bits() )) }, bucketing_label: format!( "max({x_name}.significant_bits(), {y_name}.significant_bits(), \ {z_name}.significant_bits())" ), } } ================================================ FILE: malachite-q/src/test_util/bench/mod.rs ================================================ // Copyright © 2026 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 . pub mod bucketers; ================================================ FILE: malachite-q/src/test_util/common/mod.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_nz::integer::Integer; use num::{BigInt, BigRational}; impl From<&BigRational> for Rational { fn from(n: &BigRational) -> Self { Self::from_integers(Integer::from(n.numer()), Integer::from(n.denom())) } } impl From<&Rational> for BigRational { fn from(n: &Rational) -> Self { let mut q = Self::new_raw( BigInt::from(n.numerator_ref()), BigInt::from(n.denominator_ref()), ); if *n < 0 { q = -q; } q } } impl From<&rug::Rational> for Rational { fn from(n: &rug::Rational) -> Self { Self::from_integers(Integer::from(n.numer()), Integer::from(n.denom())) } } impl From<&Rational> for rug::Rational { fn from(n: &Rational) -> Self { let mut q = Self::from(( rug::Integer::from(n.numerator_ref()), rug::Integer::from(n.denominator_ref()), )); if *n < 0 { q = -q; } q } } ================================================ FILE: malachite-q/src/test_util/conversion/continued_fraction/convergents.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::conversion::continued_fraction::to_continued_fraction::RationalContinuedFraction; use crate::conversion::traits::ContinuedFraction; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; #[derive(Clone, Debug)] pub struct ConvergentsAlt { first: bool, floor: Integer, xs: Vec, cf: RationalContinuedFraction, } impl Iterator for ConvergentsAlt { type Item = Rational; fn next(&mut self) -> Option { if self.first { self.first = false; Some(Rational::from(&self.floor)) } else if let Some(n) = self.cf.next() { self.xs.push(n); Some(Rational::from_continued_fraction_ref( &self.floor, self.xs.iter(), )) } else { self.xs.clear(); None } } } pub fn convergents_alt(x: Rational) -> ConvergentsAlt { let (floor, cf) = x.continued_fraction(); ConvergentsAlt { first: true, floor, xs: Vec::new(), cf, } } ================================================ FILE: malachite-q/src/test_util/conversion/continued_fraction/from_continued_fraction.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::num::arithmetic::traits::ReciprocalAssign; use malachite_base::num::basic::traits::Zero; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; pub fn from_continued_fraction_alt(floor: Integer, xs: Vec) -> Rational { if xs.is_empty() { Rational::from(floor) } else { let mut x = Rational::ZERO; let mut first = true; for n in xs.into_iter().rev() { if first { first = false; } else { x.reciprocal_assign(); } x += Rational::from(n); } if !first { x.reciprocal_assign(); } x + Rational::from(floor) } } ================================================ FILE: malachite-q/src/test_util/conversion/continued_fraction/mod.rs ================================================ // Copyright © 2026 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 . pub mod convergents; pub mod from_continued_fraction; ================================================ FILE: malachite-q/src/test_util/conversion/mod.rs ================================================ // Copyright © 2026 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 . pub mod continued_fraction; ================================================ FILE: malachite-q/src/test_util/extra_variadic/mod.rs ================================================ // Copyright © 2026 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 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::logic::traits::SignificantBits; use malachite_base::random::Seed; use malachite_base::sets::random::{RandomBTreeSetsFixedLength, random_b_tree_sets_fixed_length}; use malachite_base::tuples::random::next_helper; use malachite_base::vecs::exhaustive::next_bit_pattern; use malachite_base::{ exhaustive_ordered_unique_tuples, exhaustive_tuples_1_input, random_custom_tuples, random_tuples, }; use std::cmp::max; use std::marker::PhantomData; #[allow(clippy::missing_const_for_fn)] fn unwrap_triple((a, b, c): (Option, Option, Option)) -> (X, Y, Z) { (a.unwrap(), b.unwrap(), c.unwrap()) } #[allow(clippy::missing_const_for_fn)] fn unwrap_quadruple( (a, b, c, d): (Option, Option, Option, Option), ) -> (X, Y, Z, W) { (a.unwrap(), b.unwrap(), c.unwrap(), d.unwrap()) } 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] ); 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)), ExhaustiveQuadruplesXXYZ, (X, X, Y, Z), (None, None, None, None), unwrap_quadruple, exhaustive_quadruples_xxyz, exhaustive_quadruples_xxyz_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]], [Z, K, zs, zs_done, [3, output_type_zs_3]] ); exhaustive_ordered_unique_tuples!( (pub(crate)), ExhaustiveOrderedUniqueTriples, 3, (I::Item, I::Item, I::Item), exhaustive_ordered_unique_triples, [0, 1, 2] ); 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)), RandomTriplesXYY, (X, Y, Y), random_triples_xyy, [X, I, xs, xs_gen, [x_0, x_0]], [Y, J, ys, ys_gen, [y_1, y_1], [y_2, y_2]] ); random_custom_tuples!( (pub(crate)), RandomQuadruplesXXYZ, (X, X, Y, Z), random_quadruples_xxyz, [X, I, xs, xs_gen, [x_0, x_0], [x_1, x_1]], [Y, J, ys, ys_gen, [y_2, y_2]], [Z, K, zs, zs_gen, [z_3, z_3]] ); random_ordered_unique_tuples!( (pub(crate)), RandomOrderedUniqueTriples, 3, (I::Item, I::Item, I::Item), random_ordered_unique_triples, [0, 1, 2] ); ================================================ FILE: malachite-q/src/test_util/generators/common.rs ================================================ // Copyright © 2026 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 crate::Rational; use malachite_base::test_util::generators::common::It; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use num::BigRational; pub fn rational_rm(xs: It) -> It<(rug::Rational, Rational)> { Box::new(xs.map(|x| (rug::Rational::from(&x), x))) } pub fn rational_nrm(xs: It) -> It<(BigRational, rug::Rational, Rational)> { Box::new(xs.map(|x| (BigRational::from(&x), rug::Rational::from(&x), x))) } pub fn rational_pair_rm( ps: It<(Rational, Rational)>, ) -> It<((rug::Rational, rug::Rational), (Rational, Rational))> { Box::new(ps.map(|(x, y)| ((rug::Rational::from(&x), rug::Rational::from(&y)), (x, y)))) } pub fn rational_pair_nm( ps: It<(Rational, Rational)>, ) -> It<((BigRational, BigRational), (Rational, Rational))> { Box::new(ps.map(|(x, y)| ((BigRational::from(&x), BigRational::from(&y)), (x, y)))) } #[allow(clippy::type_complexity)] pub fn rational_pair_nrm( ps: It<(Rational, Rational)>, ) -> It<( (BigRational, BigRational), (rug::Rational, rug::Rational), (Rational, Rational), )> { Box::new(ps.map(|(x, y)| { ( (BigRational::from(&x), BigRational::from(&y)), (rug::Rational::from(&x), rug::Rational::from(&y)), (x, y), ) })) } pub fn rational_integer_pair_rm( ps: It<(Rational, Integer)>, ) -> It<((rug::Rational, rug::Integer), (Rational, Integer))> { Box::new(ps.map(|(x, y)| ((rug::Rational::from(&x), rug::Integer::from(&y)), (x, y)))) } pub fn rational_natural_pair_rm( ps: It<(Rational, Natural)>, ) -> It<((rug::Rational, rug::Integer), (Rational, Natural))> { Box::new(ps.map(|(x, y)| ((rug::Rational::from(&x), rug::Integer::from(&y)), (x, y)))) } pub fn rational_pair_1_rm( ps: It<(Rational, T)>, ) -> It<((rug::Rational, T), (Rational, T))> { Box::new(ps.map(|(x, y)| ((rug::Rational::from(&x), y.clone()), (x, y)))) } pub fn rational_pair_1_nrm( ps: It<(Rational, T)>, ) -> It<((BigRational, T), (rug::Rational, T), (Rational, T))> { Box::new(ps.map(|(x, y)| { ( (BigRational::from(&x), y.clone()), (rug::Rational::from(&x), y.clone()), (x, y), ) })) } pub fn rational_vec_nrm( xss: It>, ) -> It<(Vec, Vec, Vec)> { Box::new(xss.map(|xs| { ( xs.iter().map(BigRational::from).collect(), xs.iter().map(rug::Rational::from).collect(), xs, ) })) } ================================================ FILE: malachite-q/src/test_util/generators/exhaustive.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::exhaustive::{ exhaustive_negative_rationals, exhaustive_non_negative_rationals, exhaustive_nonzero_rationals, exhaustive_positive_rationals, exhaustive_rationals, }; use crate::test_util::extra_variadic::{ exhaustive_ordered_unique_triples, exhaustive_quadruples_xxyz, exhaustive_triples_from_single, exhaustive_triples_xxy, exhaustive_triples_xxy_custom_output, }; use itertools::Itertools; use malachite_base::iterators::bit_distributor::BitDistributorOutputType; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::exhaustive::exhaustive_to_sci_options; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, IsInteger, ToSci}; use malachite_base::num::exhaustive::{ exhaustive_finite_primitive_floats, exhaustive_nonzero_finite_primitive_floats, exhaustive_nonzero_signeds, exhaustive_positive_primitive_ints, exhaustive_primitive_floats, exhaustive_signeds, exhaustive_unsigneds, primitive_int_increasing_inclusive_range, }; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::exhaustive::exhaustive_rounding_modes; use malachite_base::test_util::generators::common::{It, reshape_2_1_to_3}; use malachite_base::test_util::generators::{ exhaustive_pairs_big_small, exhaustive_pairs_big_tiny, }; use malachite_base::tuples::exhaustive::{ exhaustive_ordered_unique_pairs, exhaustive_pairs, exhaustive_pairs_from_single, exhaustive_triples_custom_output, exhaustive_triples_xyy, exhaustive_triples_xyy_custom_output, lex_pairs, }; use malachite_base::vecs::exhaustive::exhaustive_vecs; use malachite_nz::integer::Integer; use malachite_nz::integer::exhaustive::exhaustive_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::{ exhaustive_natural_range_to_infinity, exhaustive_naturals, exhaustive_positive_naturals, }; use num::BigRational; use std::ops::Shr; // -- Rational -- pub fn exhaustive_rational_gen() -> It { Box::new(exhaustive_rationals()) } pub fn exhaustive_rational_gen_var_1() -> It { Box::new(exhaustive_nonzero_rationals()) } pub fn exhaustive_rational_gen_var_2() -> It { Box::new(exhaustive_positive_rationals()) } pub fn exhaustive_rational_gen_var_3() -> It { Box::new(exhaustive_non_negative_rationals()) } pub fn exhaustive_rational_gen_var_4() -> It where Rational: TryFrom, { Box::new( exhaustive_finite_primitive_floats() .skip(1) .map(Rational::exact_from), ) } pub fn exhaustive_rational_gen_var_5 ConvertibleFrom<&'a Rational> + PrimitiveFloat>() -> It { Box::new(exhaustive_rationals().filter(|q| !T::convertible_from(q))) } pub fn exhaustive_rational_gen_var_6() -> It where Rational: TryFrom, { Box::new(exhaustive_nonzero_finite_primitive_floats().map(|f| { let x = Rational::exact_from(f); let y = Rational::exact_from(if f > T::ZERO { f.next_lower() } else { f.next_higher() }); (x + y) >> 1 })) } pub fn exhaustive_rational_gen_var_7() -> It { Box::new(exhaustive_positive_rationals().filter(|q| *q != 1u32)) } // -- (Rational, Integer) -- pub fn exhaustive_rational_integer_pair_gen() -> It<(Rational, Integer)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_integers(), )) } // -- (Rational, Integer, Integer) -- pub fn exhaustive_rational_integer_integer_triple_gen() -> It<(Rational, Integer, Integer)> { Box::new(exhaustive_triples_xyy( exhaustive_rationals(), exhaustive_integers(), )) } // -- (Rational, Natural) -- pub fn exhaustive_rational_natural_pair_gen() -> It<(Rational, Natural)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_naturals(), )) } pub fn exhaustive_rational_natural_pair_gen_var_1() -> It<(Rational, Natural)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_natural_range_to_infinity(Natural::TWO), )) } pub fn exhaustive_rational_natural_pair_gen_var_2() -> It<(Rational, Natural)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_positive_naturals(), )) } pub fn exhaustive_rational_natural_pair_gen_var_3() -> It<(Rational, Natural)> { Box::new(exhaustive_pairs_big_small( exhaustive_rationals(), exhaustive_positive_naturals(), )) } // -- (Rational, Natural, Natural) -- pub fn exhaustive_rational_natural_natural_triple_gen() -> It<(Rational, Natural, Natural)> { Box::new(exhaustive_triples_xyy( exhaustive_rationals(), exhaustive_naturals(), )) } pub fn exhaustive_rational_natural_natural_triple_gen_var_1() -> It<(Rational, Natural, Natural)> { Box::new( exhaustive_triples_xyy(exhaustive_rationals(), exhaustive_positive_naturals()) .filter(|(_, x, y)| x < y), ) } // -- (Rational, PrimitiveFloat) -- pub fn exhaustive_rational_primitive_float_pair_gen() -> It<(Rational, T)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_primitive_floats(), )) } // -- (Rational, PrimitiveFloat, PrimitiveFloat) -- pub fn exhaustive_rational_primitive_float_primitive_float_triple_gen() -> It<(Rational, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_rationals(), exhaustive_primitive_floats(), )) } // -- (Rational, PrimitiveSigned) -- pub fn exhaustive_rational_signed_pair_gen() -> It<(Rational, T)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_signeds(), )) } pub fn exhaustive_rational_signed_pair_gen_var_1() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_rationals(), exhaustive_signeds(), )) } pub fn exhaustive_rational_signed_pair_gen_var_2() -> It<(Rational, T)> { Box::new( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_signeds()) .filter(|(x, exp)| *exp >= T::ZERO || *x != 0u32), ) } pub fn exhaustive_rational_signed_pair_gen_var_3() -> It<(Rational, T)> where for<'a> &'a Rational: Shr, { Box::new( exhaustive_pairs_big_tiny(exhaustive_rationals(), exhaustive_signeds::()) .filter(|(x, pow)| !x.denominator_ref().is_power_of_2() || !(x >> *pow).is_integer()), ) } pub fn exhaustive_rational_signed_pair_gen_var_4() -> It<(Rational, T)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_non_negative_rationals(), exhaustive_nonzero_signeds(), ) .filter(|(q, i)| *i > T::ZERO || *q != 0u32) .interleave(exhaustive_pairs_big_tiny( exhaustive_negative_rationals(), exhaustive_signeds::() .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)), )), ) } pub fn exhaustive_rational_signed_pair_gen_var_5() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_positive_rationals(), exhaustive_nonzero_signeds(), )) } // -- (Rational, PrimitiveSigned, PrimitiveSigned) -- pub fn exhaustive_rational_signed_signed_triple_gen() -> It<(Rational, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_rationals(), exhaustive_signeds(), )) } pub fn exhaustive_rational_signed_signed_triple_gen_var_1() -> It<(Rational, T, T)> { Box::new( exhaustive_triples_xyy_custom_output( exhaustive_rationals(), exhaustive_signeds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter(|(x, e, f)| *e >= T::ZERO && *f >= T::ZERO || *x != 0), ) } // -- (Rational, PrimitiveSigned, PrimitiveUnsigned) -- pub fn exhaustive_rational_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >() -> It<(Rational, T, U)> { Box::new(exhaustive_triples_custom_output( exhaustive_rationals(), exhaustive_signeds::(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Rational, PrimitiveSigned, RoundingMode) -- pub fn exhaustive_rational_signed_rounding_mode_triple_gen_var_1() -> It<(Rational, i64, RoundingMode)> { Box::new( exhaustive_triples_custom_output( exhaustive_rationals(), exhaustive_signeds::(), exhaustive_rounding_modes(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), ) .filter(|(x, i, rm)| { *rm != Exact || x.denominator_ref().is_power_of_2() && (x >> *i).is_integer() }), ) } // var 2 is in malachite-float. // -- (Rational, PrimitiveUnsigned) -- pub fn exhaustive_rational_unsigned_pair_gen() -> It<(Rational, T)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_unsigneds(), )) } pub fn exhaustive_rational_unsigned_pair_gen_var_1() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_rationals(), exhaustive_unsigneds(), )) } pub fn exhaustive_rational_unsigned_pair_gen_var_2() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_rationals(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_rational_unsigned_pair_gen_var_3() -> It<(Rational, T)> { Box::new( exhaustive_pairs_big_tiny( exhaustive_non_negative_rationals(), exhaustive_positive_primitive_ints(), ) .interleave(exhaustive_pairs_big_tiny( exhaustive_negative_rationals(), exhaustive_unsigneds::() .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)), )), ) } pub fn exhaustive_rational_unsigned_pair_gen_var_4() -> It<(Rational, u8)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_rationals(), primitive_int_increasing_inclusive_range(2, 36), )) } pub fn exhaustive_rational_unsigned_pair_gen_var_5() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_nonzero_rationals(), exhaustive_positive_primitive_ints(), )) } pub fn exhaustive_rational_unsigned_pair_gen_var_6() -> It<(Rational, T)> { Box::new(exhaustive_pairs_big_tiny( exhaustive_non_negative_rationals(), exhaustive_positive_primitive_ints(), )) } // -- (Rational, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn exhaustive_rational_unsigned_unsigned_triple_gen() -> It<(Rational, T, T)> { Box::new(exhaustive_triples_xyy( exhaustive_rationals(), exhaustive_unsigneds(), )) } pub fn exhaustive_rational_unsigned_unsigned_triple_gen_var_1() -> It<(Rational, T, T)> { Box::new(exhaustive_triples_xyy_custom_output( exhaustive_rationals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), BitDistributorOutputType::tiny(), )) } // -- (Rational, Rational) -- pub fn exhaustive_rational_pair_gen() -> It<(Rational, Rational)> { Box::new(exhaustive_pairs_from_single(exhaustive_rationals())) } pub fn exhaustive_rational_pair_gen_var_1() -> It<(Rational, Rational)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_nonzero_rationals(), )) } pub fn exhaustive_rational_pair_gen_var_2() -> It<(Rational, Rational)> { Box::new( exhaustive_pairs(exhaustive_rationals(), exhaustive_nonzero_rationals()) .filter(|(x, y)| !(x / y).is_integer()), ) } pub fn exhaustive_rational_pair_gen_var_3() -> It<(Rational, Rational)> { Box::new( exhaustive_ordered_unique_pairs(exhaustive_rationals()) .map(|(x, y)| if x < y { (x, y) } else { (y, x) }), ) } pub fn exhaustive_rational_pair_gen_var_4() -> It<(Rational, Rational)> { // TODO Box::new(exhaustive_pairs_from_single(exhaustive_rationals()).filter(|(x, y)| x <= y)) } pub fn exhaustive_rational_pair_gen_var_5() -> It<(Rational, Rational)> { Box::new(exhaustive_pairs( exhaustive_positive_rationals(), exhaustive_positive_rationals() .filter(|q| (q - Rational::ONE).gt_abs(&Rational::from_signeds(1, 1000))), )) } pub fn exhaustive_rational_pair_gen_var_6() -> It<(Rational, Rational)> { Box::new(exhaustive_pairs_from_single(exhaustive_nonzero_rationals())) } // -- (Rational, Rational, Integer) -- pub fn exhaustive_rational_rational_integer_triple_gen() -> It<(Rational, Rational, Integer)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_integers(), )) } // -- (Rational, Rational, Natural) -- pub fn exhaustive_rational_rational_natural_triple_gen() -> It<(Rational, Rational, Natural)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_naturals(), )) } pub fn exhaustive_rational_rational_natural_triple_gen_var_1() -> It<(Rational, Rational, Natural)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_positive_naturals(), )) } // -- (Rational, Rational, PrimitiveFloat) -- pub fn exhaustive_rational_rational_primitive_float_triple_gen() -> It<(Rational, Rational, T)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_primitive_floats(), )) } // -- (Rational, Rational, RoundingMode) -- pub(crate) fn round_to_multiple_rational_filter(t: &(Rational, Rational, RoundingMode)) -> bool { let &(ref x, ref y, rm) = t; if x == y { true } else if *y == 0u32 { rm == Down || rm == (if *x >= 0 { Floor } else { Ceiling }) || rm == Nearest } else { rm != Exact || (x / y).is_integer() } } pub fn exhaustive_rational_rational_rounding_mode_triple_gen_var_1() -> It<(Rational, Rational, RoundingMode)> { Box::new( reshape_2_1_to_3(Box::new(lex_pairs( exhaustive_pairs_from_single(exhaustive_rationals()), exhaustive_rounding_modes(), ))) .filter(round_to_multiple_rational_filter), ) } // -- (Rational, Rational, Natural, Natural) -- pub fn exhaustive_rational_rational_natural_natural_quadruple_gen_var_1() -> It<(Rational, Rational, Natural, Natural)> { Box::new(exhaustive_quadruples_xxyz( exhaustive_rationals(), exhaustive_naturals(), exhaustive_positive_naturals(), )) } // -- (Rational, Rational, PrimitiveInt) -- pub fn exhaustive_rational_rational_primitive_int_triple_gen_var_1() -> It<(Rational, Rational, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_rationals(), exhaustive_positive_primitive_ints::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (Rational, Rational, PrimitiveSigned) -- pub fn exhaustive_rational_rational_signed_triple_gen() -> It<(Rational, Rational, T)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_signeds(), )) } pub fn exhaustive_rational_rational_signed_triple_gen_var_1() -> It<(Rational, Rational, T)> { Box::new( exhaustive_triples_xxy_custom_output( exhaustive_rationals(), exhaustive_signeds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), ) .filter(|(x, y, exp)| *exp >= T::ZERO || *x != 0 && *y != 0), ) } // -- (Rational, Rational, PrimitiveUnsigned) -- pub fn exhaustive_rational_rational_unsigned_triple_gen() -> It<(Rational, Rational, T)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_unsigneds(), )) } pub fn exhaustive_rational_rational_unsigned_triple_gen_var_1() -> It<(Rational, Rational, T)> { Box::new(exhaustive_triples_xxy_custom_output( exhaustive_rationals(), exhaustive_unsigneds::(), BitDistributorOutputType::normal(1), BitDistributorOutputType::normal(1), BitDistributorOutputType::tiny(), )) } // -- (Rational, Rational, Rational) -- pub fn exhaustive_rational_triple_gen() -> It<(Rational, Rational, Rational)> { Box::new(exhaustive_triples_from_single(exhaustive_rationals())) } pub fn exhaustive_rational_triple_gen_var_1() -> It<(Rational, Rational, Rational)> { Box::new(exhaustive_triples_xxy( exhaustive_rationals(), exhaustive_nonzero_rationals(), )) } pub fn exhaustive_rational_triple_gen_var_2() -> It<(Rational, Rational, Rational)> { Box::new( exhaustive_ordered_unique_triples(exhaustive_rationals()).map(|(x, y, z)| { let mut xs = vec![x, y, z]; xs.sort_unstable(); let mut xs = xs.into_iter(); (xs.next().unwrap(), xs.next().unwrap(), xs.next().unwrap()) }), ) } pub fn exhaustive_rational_triple_gen_var_3() -> It<(Rational, Rational, Rational)> { // TODO Box::new( exhaustive_triples_from_single(exhaustive_rationals()).filter(|(x, y, z)| x <= y && y <= z), ) } // -- (Rational, RoundingMode) -- pub fn exhaustive_rational_rounding_mode_pair_gen() -> It<(Rational, RoundingMode)> { Box::new(lex_pairs( exhaustive_rationals(), exhaustive_rounding_modes(), )) } pub fn exhaustive_rational_rounding_mode_pair_gen_var_1() -> It<(Rational, RoundingMode)> { Box::new( lex_pairs(exhaustive_rationals(), exhaustive_rounding_modes()).filter(|(x, rm)| match rm { Floor | Up => *x >= 0u32, Exact => Natural::convertible_from(x), _ => true, }), ) } pub fn exhaustive_rational_rounding_mode_pair_gen_var_2() -> It<(Rational, RoundingMode)> { Box::new( lex_pairs(exhaustive_rationals(), exhaustive_rounding_modes()) .filter(|(x, rm)| *rm != Exact || x.is_integer()), ) } pub fn exhaustive_rational_rounding_mode_pair_gen_var_3< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >() -> It<(Rational, RoundingMode)> where Rational: PartialOrd, { Box::new( lex_pairs(exhaustive_rationals(), exhaustive_rounding_modes()).filter(|(x, rm)| match rm { Floor => *x >= T::MIN, Ceiling => *x <= T::MAX, Up => *x >= T::MIN && *x <= T::MAX, Exact => T::convertible_from(x), _ => true, }), ) } pub fn exhaustive_rational_rounding_mode_pair_gen_var_4() -> It<(Rational, RoundingMode)> { Box::new(lex_pairs( exhaustive_nonzero_rationals(), exhaustive_rounding_modes(), )) } pub fn exhaustive_rational_rounding_mode_pair_gen_var_5< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >() -> It<(Rational, RoundingMode)> where Rational: TryFrom, { let max = Rational::exact_from(T::MAX_FINITE); let min = -&max; Box::new( lex_pairs(exhaustive_rationals(), exhaustive_rounding_modes()).filter(move |(x, rm)| { match rm { Floor => *x >= min, Ceiling => *x <= max, Up => *x >= min && *x <= max, Exact => T::convertible_from(x), _ => true, } }), ) } // -- (Rational, ToSciOptions) -- pub fn exhaustive_rational_to_sci_options_pair_gen() -> It<(Rational, ToSciOptions)> { Box::new(exhaustive_pairs( exhaustive_rationals(), exhaustive_to_sci_options(), )) } pub fn exhaustive_rational_to_sci_options_pair_gen_var_1() -> It<(Rational, ToSciOptions)> { Box::new( exhaustive_pairs(exhaustive_rationals(), exhaustive_to_sci_options()) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- String -- // vars 1 through 10 are in malachite-base. pub fn exhaustive_string_gen_var_11() -> It { Box::new(exhaustive_rationals().map(|r| serde_json::to_string(&r).unwrap())) } pub fn exhaustive_string_gen_var_12() -> It { Box::new(exhaustive_rationals().map(|x| x.to_string())) } // -- (String, String, String) -- // vars 1 through 2 are in malachite-nz. pub fn exhaustive_string_triple_gen_var_3() -> It<(String, String, String)> { Box::new(exhaustive_rationals().map(|x| { ( serde_json::to_string(&BigRational::from(&x)).unwrap(), serde_json::to_string(&rug::Rational::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) })) } // -- Vec -- pub fn exhaustive_rational_vec_gen() -> It> { Box::new(exhaustive_vecs(exhaustive_rationals())) } ================================================ FILE: malachite-q/src/test_util/generators/mod.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::test_util::generators::common::{ rational_integer_pair_rm, rational_natural_pair_rm, rational_nrm, rational_pair_1_nrm, rational_pair_1_rm, rational_pair_nm, rational_pair_nrm, rational_pair_rm, rational_rm, rational_vec_nrm, }; use crate::test_util::generators::exhaustive::*; use crate::test_util::generators::random::*; use crate::test_util::generators::special_random::*; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::traits::ConvertibleFrom; use malachite_base::rounding_modes::RoundingMode; use malachite_base::test_util::generators::common::Generator; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use num::BigRational; use std::ops::Shr; // -- Rational -- pub fn rational_gen() -> Generator { Generator::new( &exhaustive_rational_gen, &random_rational_gen, &special_random_rational_gen, ) } pub fn rational_gen_rm() -> Generator<(rug::Rational, Rational)> { Generator::new( &|| rational_rm(exhaustive_rational_gen()), &|config| rational_rm(random_rational_gen(config)), &|config| rational_rm(special_random_rational_gen(config)), ) } pub fn rational_gen_nrm() -> Generator<(BigRational, rug::Rational, Rational)> { Generator::new( &|| rational_nrm(exhaustive_rational_gen()), &|config| rational_nrm(random_rational_gen(config)), &|config| rational_nrm(special_random_rational_gen(config)), ) } // All nonzero `Rational`s. pub fn rational_gen_var_1() -> Generator { Generator::new( &exhaustive_rational_gen_var_1, &random_rational_gen_var_1, &special_random_rational_gen_var_1, ) } pub fn rational_gen_var_1_nrm() -> Generator<(BigRational, rug::Rational, Rational)> { Generator::new( &|| rational_nrm(exhaustive_rational_gen_var_1()), &|config| rational_nrm(random_rational_gen_var_1(config)), &|config| rational_nrm(special_random_rational_gen_var_1(config)), ) } // All positive `Rational`s. pub fn rational_gen_var_2() -> Generator { Generator::new( &exhaustive_rational_gen_var_2, &random_rational_gen_var_2, &special_random_rational_gen_var_2, ) } // All non-negative `Rational`s. pub fn rational_gen_var_3() -> Generator { Generator::new( &exhaustive_rational_gen_var_3, &random_rational_gen_var_3, &special_random_rational_gen_var_3, ) } // All `Rational`s that are equal to a primitive float of type `T`. pub fn rational_gen_var_4() -> Generator where Rational: TryFrom, { Generator::new( &exhaustive_rational_gen_var_4::, &random_rational_gen_var_4::, &special_random_rational_gen_var_4::, ) } // All `Rational`s that are not equal to any primitive float of type `T`. pub fn rational_gen_var_5 ConvertibleFrom<&'a Rational> + PrimitiveFloat>() -> Generator { Generator::new( &exhaustive_rational_gen_var_5::, &random_rational_gen_var_5::, &special_random_rational_gen_var_5::, ) } // All `Rational`s that are halfway between two adjacent floats of type `T`. pub fn rational_gen_var_6() -> Generator where Rational: TryFrom, { Generator::new( &exhaustive_rational_gen_var_6::, &random_rational_gen_var_6::, &special_random_rational_gen_var_6::, ) } // All `Rational`s with small numerator and denominator. pub fn rational_gen_var_7() -> Generator { Generator::new_no_special(&exhaustive_rational_gen, &random_rational_gen_var_7) } // All positive `Rational`s that are not equal to 1. pub fn rational_gen_var_8() -> Generator { Generator::new( &exhaustive_rational_gen_var_7, &random_rational_gen_var_8, &special_random_rational_gen_var_7, ) } // -- (Rational, Integer) -- pub fn rational_integer_pair_gen() -> Generator<(Rational, Integer)> { Generator::new( &exhaustive_rational_integer_pair_gen, &random_rational_integer_pair_gen, &special_random_rational_integer_pair_gen, ) } pub fn rational_integer_pair_gen_rm() -> Generator<((rug::Rational, rug::Integer), (Rational, Integer))> { Generator::new( &|| rational_integer_pair_rm(exhaustive_rational_integer_pair_gen()), &|config| rational_integer_pair_rm(random_rational_integer_pair_gen(config)), &|config| rational_integer_pair_rm(random_rational_integer_pair_gen(config)), ) } // -- (Rational, Integer, Integer) -- pub fn rational_integer_integer_triple_gen() -> Generator<(Rational, Integer, Integer)> { Generator::new( &exhaustive_rational_integer_integer_triple_gen, &random_rational_integer_integer_triple_gen, &special_random_rational_integer_integer_triple_gen, ) } // -- (Rational, Natural) -- pub fn rational_natural_pair_gen() -> Generator<(Rational, Natural)> { Generator::new( &exhaustive_rational_natural_pair_gen, &random_rational_natural_pair_gen, &special_random_rational_natural_pair_gen, ) } pub fn rational_natural_pair_gen_rm() -> Generator<((rug::Rational, rug::Integer), (Rational, Natural))> { Generator::new( &|| rational_natural_pair_rm(exhaustive_rational_natural_pair_gen()), &|config| rational_natural_pair_rm(random_rational_natural_pair_gen(config)), &|config| rational_natural_pair_rm(random_rational_natural_pair_gen(config)), ) } // All `(Rational, Natural)` where the `Natural` is greater than 1. pub fn rational_natural_pair_gen_var_1() -> Generator<(Rational, Natural)> { Generator::new( &exhaustive_rational_natural_pair_gen_var_1, &random_rational_natural_pair_gen_var_1, &special_random_rational_natural_pair_gen_var_1, ) } // All `(Rational, Natural)` where the `Rational` has a small numerator and denominator, and the // `Natural` is greater than 1. pub fn rational_natural_pair_gen_var_2() -> Generator<(Rational, Natural)> { Generator::new( &exhaustive_rational_natural_pair_gen_var_1, &random_rational_natural_pair_gen_var_2, &special_random_rational_natural_pair_gen_var_2, ) } // All `(Rational, Natural)` where the `Natural` is positive. pub fn rational_natural_pair_gen_var_3() -> Generator<(Rational, Natural)> { Generator::new( &exhaustive_rational_natural_pair_gen_var_2, &random_rational_natural_pair_gen_var_3, &special_random_rational_natural_pair_gen_var_3, ) } // All `(Rational, Natural)` where the `Natural` is small and positive. pub fn rational_natural_pair_gen_var_4() -> Generator<(Rational, Natural)> { Generator::new( &exhaustive_rational_natural_pair_gen_var_3, &random_rational_natural_pair_gen_var_4, &special_random_rational_natural_pair_gen_var_4, ) } // -- (Rational, Natural, Natural) -- pub fn rational_natural_natural_triple_gen() -> Generator<(Rational, Natural, Natural)> { Generator::new( &exhaustive_rational_natural_natural_triple_gen, &random_rational_natural_natural_triple_gen, &special_random_rational_natural_natural_triple_gen, ) } // All `(Rational, Natural, Natural)` where the both `Natural`s are positive and the first `Natural` // is smaller than the second. pub fn rational_natural_natural_triple_gen_var_1() -> Generator<(Rational, Natural, Natural)> { Generator::new( &exhaustive_rational_natural_natural_triple_gen_var_1, &random_rational_natural_natural_triple_gen_var_1, &special_random_rational_natural_natural_triple_gen_var_1, ) } // -- (Rational, PrimitiveFloat) -- pub fn rational_primitive_float_pair_gen() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_primitive_float_pair_gen, &random_rational_primitive_float_pair_gen, &special_random_rational_primitive_float_pair_gen, ) } pub fn rational_primitive_float_pair_gen_rm() -> Generator<((rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_rm(exhaustive_rational_primitive_float_pair_gen()), &|config| rational_pair_1_rm(random_rational_primitive_float_pair_gen(config)), &|config| rational_pair_1_rm(special_random_rational_primitive_float_pair_gen(config)), ) } // -- (Rational, PrimitiveFloat, PrimitiveFloat) -- pub fn rational_primitive_float_primitive_float_triple_gen() -> Generator<(Rational, T, T)> { Generator::new( &exhaustive_rational_primitive_float_primitive_float_triple_gen, &random_rational_primitive_float_primitive_float_triple_gen, &special_random_rational_primitive_float_primitive_float_triple_gen, ) } // -- (Rational, PrimitiveSigned) -- pub fn rational_signed_pair_gen() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_signed_pair_gen, &random_rational_primitive_int_pair_gen, &special_random_rational_signed_pair_gen, ) } pub fn rational_signed_pair_gen_rm() -> Generator<((rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_rm(exhaustive_rational_signed_pair_gen()), &|config| rational_pair_1_rm(random_rational_primitive_int_pair_gen(config)), &|config| rational_pair_1_rm(special_random_rational_signed_pair_gen(config)), ) } // All `(Rational, T)` where `T` is small and signed. pub fn rational_signed_pair_gen_var_1() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_signed_pair_gen_var_1, &random_rational_signed_pair_gen_var_1, &special_random_rational_signed_pair_gen_var_1, ) } pub fn rational_signed_pair_gen_var_1_rm() -> Generator<((rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_rm(exhaustive_rational_signed_pair_gen_var_1()), &|config| rational_pair_1_rm(random_rational_signed_pair_gen_var_1(config)), &|config| rational_pair_1_rm(special_random_rational_signed_pair_gen_var_1(config)), ) } // All `(Rational, T)` where `T` is small and signed, and if the `Rational` is zero then the `T` is // non-negative. pub fn rational_signed_pair_gen_var_2() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_signed_pair_gen_var_2, &random_rational_signed_pair_gen_var_2, &special_random_rational_signed_pair_gen_var_2, ) } pub fn rational_signed_pair_gen_var_2_nrm() -> Generator<((BigRational, T), (rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_nrm(exhaustive_rational_signed_pair_gen_var_2()), &|config| rational_pair_1_nrm(random_rational_signed_pair_gen_var_2(config)), &|config| rational_pair_1_nrm(special_random_rational_signed_pair_gen_var_2(config)), ) } // All `(Rational, T)` where `T` is small and signed, and the `Rational` divided by 2 to the power // of the `T` is not an integer. pub fn rational_signed_pair_gen_var_3() -> Generator<(Rational, T)> where for<'a> &'a Rational: Shr, { Generator::new( &exhaustive_rational_signed_pair_gen_var_3, &random_rational_signed_pair_gen_var_3, &special_random_rational_signed_pair_gen_var_3, ) } // All `(Rational, T)` where `T` is signed, small, and nonzero, and either the `Rational` is // non-negative or the `T` is odd, and either the `Rational` is nonzero or the `T` is positive. pub fn rational_signed_pair_gen_var_4() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_signed_pair_gen_var_4, &random_rational_signed_pair_gen_var_4, &special_random_rational_signed_pair_gen_var_4, ) } // All `(Rational, T)` where the `Rational` is positive and the `T` is small, signed, and nonzero. pub fn rational_signed_pair_gen_var_5() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_signed_pair_gen_var_5, &random_rational_signed_pair_gen_var_5, &special_random_rational_signed_pair_gen_var_5, ) } // -- (Rational, PrimitiveSigned, RoundingMode) -- // All `(Rational, i64, RoundingMode)` where the triple is a valid input to // `Rational::round_to_multiple_of_power_of_2`. pub fn rational_signed_rounding_mode_triple_gen_var_1() -> Generator<(Rational, i64, RoundingMode)> { Generator::new( &exhaustive_rational_signed_rounding_mode_triple_gen_var_1, &random_rational_signed_rounding_mode_triple_gen_var_1, &special_random_rational_signed_rounding_mode_triple_gen_var_1, ) } // var 2 is in malachite-float. // -- (Rational, PrimitiveSigned, PrimitiveSigned) -- pub fn rational_signed_signed_triple_gen() -> Generator<(Rational, T, T)> { Generator::new( &exhaustive_rational_signed_signed_triple_gen, &random_rational_primitive_int_primitive_int_triple_gen, &special_random_rational_signed_signed_triple_gen, ) } // All `(Rational, T, T)` where `T` is signed, both `T`s are small, and if either `T` is negative, // the `Rational` is nonzero. pub fn rational_signed_signed_triple_gen_var_1() -> Generator<(Rational, T, T)> { Generator::new( &exhaustive_rational_signed_signed_triple_gen_var_1, &random_rational_signed_signed_triple_gen_var_1, &special_random_rational_signed_signed_triple_gen_var_1, ) } // -- (Rational, PrimitiveSigned, PrimitiveUnsigned) -- // All `(Rational, T, U)` where `T` is small and signed, and positive and `U` is small, unsigned, // and positive. pub fn rational_signed_unsigned_triple_gen_var_1() -> Generator<(Rational, T, U)> { Generator::new( &exhaustive_rational_signed_unsigned_triple_gen_var_1, &random_rational_signed_unsigned_triple_gen_var_1, &special_random_rational_signed_unsigned_triple_gen_var_1, ) } // -- (Rational, PrimitiveUnsigned) -- pub fn rational_unsigned_pair_gen() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen, &random_rational_primitive_int_pair_gen, &special_random_rational_unsigned_pair_gen, ) } pub fn rational_unsigned_pair_gen_rm() -> Generator<((rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_rm(exhaustive_rational_unsigned_pair_gen()), &|config| rational_pair_1_rm(random_rational_primitive_int_pair_gen(config)), &|config| rational_pair_1_rm(special_random_rational_unsigned_pair_gen(config)), ) } // All `(Rational, T)` where `T` is small and unsigned. pub fn rational_unsigned_pair_gen_var_1() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_1, &random_rational_unsigned_pair_gen_var_1, &special_random_rational_unsigned_pair_gen_var_1, ) } pub fn rational_unsigned_pair_gen_var_1_rm() -> Generator<((rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_rm(exhaustive_rational_unsigned_pair_gen_var_1()), &|config| rational_pair_1_rm(random_rational_unsigned_pair_gen_var_1(config)), &|config| rational_pair_1_rm(special_random_rational_unsigned_pair_gen_var_1(config)), ) } pub fn rational_unsigned_pair_gen_var_1_nrm() -> Generator<((BigRational, T), (rug::Rational, T), (Rational, T))> { Generator::new( &|| rational_pair_1_nrm(exhaustive_rational_unsigned_pair_gen_var_1()), &|config| rational_pair_1_nrm(random_rational_unsigned_pair_gen_var_1(config)), &|config| rational_pair_1_nrm(special_random_rational_unsigned_pair_gen_var_1(config)), ) } // All `(Rational, T)` where the `T` is small, unsigned, and positive, and the `Rational` has a // small numerator and denominator. pub fn rational_unsigned_pair_gen_var_2() -> Generator<(Rational, T)> { Generator::new_no_special( &exhaustive_rational_unsigned_pair_gen_var_2, &random_rational_unsigned_pair_gen_var_2, ) } // All `(Rational, T)` where the `T` is small, unsigned, and positive. pub fn rational_unsigned_pair_gen_var_3() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_2, &random_rational_unsigned_pair_gen_var_3, &special_random_rational_unsigned_pair_gen_var_2, ) } // All `(Rational, T)` where `T` is unsigned, small, and positive, and either the `Rational` is // non-negative or the `T` is odd. pub fn rational_unsigned_pair_gen_var_4() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_3, &random_rational_unsigned_pair_gen_var_4, &special_random_rational_unsigned_pair_gen_var_3, ) } // All `(Rational, u8)`s where the `u8` is between 2 and 36, inclusive. pub fn rational_unsigned_pair_gen_var_5() -> Generator<(Rational, u8)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_4, &random_rational_unsigned_pair_gen_var_5, &special_random_rational_unsigned_pair_gen_var_4, ) } // All `(Rational, u8)`s where the numerator and denominator of the `Rational` is small and the `u8` // is between 2 and 36, inclusive. pub fn rational_unsigned_pair_gen_var_6() -> Generator<(Rational, u8)> { Generator::new_no_special( &exhaustive_rational_unsigned_pair_gen_var_4, &random_rational_unsigned_pair_gen_var_6, ) } // All `(Rational, T)` where the `Rational` is nonzero and the `T` is small, unsigned, and positive. pub fn rational_unsigned_pair_gen_var_7() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_5, &random_rational_unsigned_pair_gen_var_7, &special_random_rational_unsigned_pair_gen_var_5, ) } // All `(Rational, T)` where the `Rational` is non-negative and the `T` is small, unsigned, and // positive. pub fn rational_unsigned_pair_gen_var_8() -> Generator<(Rational, T)> { Generator::new( &exhaustive_rational_unsigned_pair_gen_var_6, &random_rational_unsigned_pair_gen_var_8, &special_random_rational_unsigned_pair_gen_var_6, ) } // -- (Rational, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn rational_unsigned_unsigned_triple_gen() -> Generator<(Rational, T, T)> { Generator::new( &exhaustive_rational_unsigned_unsigned_triple_gen, &random_rational_primitive_int_primitive_int_triple_gen, &special_random_rational_unsigned_unsigned_triple_gen, ) } // All `(Rational, T, T)` where `T` is unsigned and both `T`s are small. pub fn rational_unsigned_unsigned_triple_gen_var_1() -> Generator<(Rational, T, T)> { Generator::new( &exhaustive_rational_unsigned_unsigned_triple_gen_var_1, &random_rational_unsigned_unsigned_triple_gen_var_1, &special_random_rational_unsigned_unsigned_triple_gen_var_1, ) } // -- (Rational, Rational) -- pub fn rational_pair_gen() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen, &random_rational_pair_gen, &special_random_rational_pair_gen, ) } pub fn rational_pair_gen_rm() -> Generator<((rug::Rational, rug::Rational), (Rational, Rational))> { Generator::new( &|| rational_pair_rm(exhaustive_rational_pair_gen()), &|config| rational_pair_rm(random_rational_pair_gen(config)), &|config| rational_pair_rm(special_random_rational_pair_gen(config)), ) } pub fn rational_pair_gen_nm() -> Generator<((BigRational, BigRational), (Rational, Rational))> { Generator::new( &|| rational_pair_nm(exhaustive_rational_pair_gen()), &|config| rational_pair_nm(random_rational_pair_gen(config)), &|config| rational_pair_nm(special_random_rational_pair_gen(config)), ) } pub fn rational_pair_gen_nrm() -> Generator<( (BigRational, BigRational), (rug::Rational, rug::Rational), (Rational, Rational), )> { Generator::new( &|| rational_pair_nrm(exhaustive_rational_pair_gen()), &|config| rational_pair_nrm(random_rational_pair_gen(config)), &|config| rational_pair_nrm(special_random_rational_pair_gen(config)), ) } // All pairs of `Rational`s where the second `Rational` is nonzero. pub fn rational_pair_gen_var_1() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_1, &random_rational_pair_gen_var_1, &special_random_rational_pair_gen_var_1, ) } pub fn rational_pair_gen_var_1_rm() -> Generator<((rug::Rational, rug::Rational), (Rational, Rational))> { Generator::new( &|| rational_pair_rm(exhaustive_rational_pair_gen_var_1()), &|config| rational_pair_rm(random_rational_pair_gen_var_1(config)), &|config| rational_pair_rm(special_random_rational_pair_gen_var_1(config)), ) } pub fn rational_pair_gen_var_1_nm() -> Generator<((BigRational, BigRational), (Rational, Rational))> { Generator::new( &|| rational_pair_nm(exhaustive_rational_pair_gen_var_1()), &|config| rational_pair_nm(random_rational_pair_gen_var_1(config)), &|config| rational_pair_nm(special_random_rational_pair_gen_var_1(config)), ) } pub fn rational_pair_gen_var_1_nrm() -> Generator<( (BigRational, BigRational), (rug::Rational, rug::Rational), (Rational, Rational), )> { Generator::new( &|| rational_pair_nrm(exhaustive_rational_pair_gen_var_1()), &|config| rational_pair_nrm(random_rational_pair_gen_var_1(config)), &|config| rational_pair_nrm(special_random_rational_pair_gen_var_1(config)), ) } // All pairs of `Rational`s where the second is nonzero and the first is not an integer multiple of // the second. pub fn rational_pair_gen_var_2() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_2, &random_rational_pair_gen_var_2, &special_random_rational_pair_gen_var_2, ) } // All pairs of `Rational`s where the first is less than the second. pub fn rational_pair_gen_var_3() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_3, &random_rational_pair_gen_var_3, &special_random_rational_pair_gen_var_3, ) } // All pairs of `Rational`s where the first is less than or equal to the second. pub fn rational_pair_gen_var_4() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_4, &random_rational_pair_gen_var_4, &special_random_rational_pair_gen_var_4, ) } // All pairs of `Rational`s where the first is less than the second, and the numerators and // denominators are small. pub fn rational_pair_gen_var_5() -> Generator<(Rational, Rational)> { Generator::new_no_special( &exhaustive_rational_pair_gen_var_3, &random_rational_pair_gen_var_5, ) } // All pairs of `Rational`s where the first is less than or equal to the second, and the numerators // and denominators are small. pub fn rational_pair_gen_var_6() -> Generator<(Rational, Rational)> { Generator::new_no_special( &exhaustive_rational_pair_gen_var_4, &random_rational_pair_gen_var_6, ) } // All pairs of positive `Rational`s where the second `Rational` is not within 1/1000 of 1. pub fn rational_pair_gen_var_7() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_5, &random_rational_pair_gen_var_7, &special_random_rational_pair_gen_var_5, ) } // All pairs of nonzero `Rational`s. pub fn rational_pair_gen_var_8() -> Generator<(Rational, Rational)> { Generator::new( &exhaustive_rational_pair_gen_var_6, &random_rational_pair_gen_var_8, &special_random_rational_pair_gen_var_6, ) } // -- (Rational, Rational, Integer) -- pub fn rational_rational_integer_triple_gen() -> Generator<(Rational, Rational, Integer)> { Generator::new( &exhaustive_rational_rational_integer_triple_gen, &random_rational_rational_integer_triple_gen, &special_random_rational_rational_integer_triple_gen, ) } // -- (Rational, Rational, Natural) -- pub fn rational_rational_natural_triple_gen() -> Generator<(Rational, Rational, Natural)> { Generator::new( &exhaustive_rational_rational_natural_triple_gen, &random_rational_rational_natural_triple_gen, &special_random_rational_rational_natural_triple_gen, ) } // All `(Rational, Rational, Natural)` where the `Natural` is positive. pub fn rational_rational_natural_triple_gen_var_1() -> Generator<(Rational, Rational, Natural)> { Generator::new( &exhaustive_rational_rational_natural_triple_gen_var_1, &random_rational_rational_natural_triple_gen_var_1, &special_random_rational_rational_natural_triple_gen_var_1, ) } // -- (Rational, Rational, Natural, Natural) -- // All `(Rational, Rational, Natural, Natural)` where the last `Natural` is positive. pub fn rational_rational_natural_natural_quadruple_gen_var_1() -> Generator<(Rational, Rational, Natural, Natural)> { Generator::new( &exhaustive_rational_rational_natural_natural_quadruple_gen_var_1, &random_rational_rational_natural_natural_quadruple_gen_var_1, &special_random_rational_rational_natural_natural_quadruple_gen_var_1, ) } // -- (Rational, Rational, PrimitiveFloat) -- pub fn rational_rational_primitive_float_triple_gen() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_primitive_float_triple_gen, &random_rational_rational_primitive_float_triple_gen, &special_random_rational_rational_primitive_float_triple_gen, ) } // -- (Rational, Rational, PrimitiveUnsigned) -- pub fn rational_rational_unsigned_triple_gen() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_unsigned_triple_gen, &random_rational_rational_primitive_int_triple_gen, &special_random_rational_rational_unsigned_triple_gen, ) } // All `(Rational, Rational, T)` where `T` is unsigned and small. pub fn rational_rational_unsigned_triple_gen_var_1() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_unsigned_triple_gen_var_1, &random_rational_rational_unsigned_triple_gen_var_1, &special_random_rational_rational_unsigned_triple_gen_var_1, ) } // All `(Rational, Rational, T)` where `T` is positive, unsigned, and small. pub fn rational_rational_unsigned_triple_gen_var_2() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_primitive_int_triple_gen_var_1, &random_rational_rational_unsigned_triple_gen_var_2, &special_random_rational_rational_unsigned_triple_gen_var_2, ) } // -- (Rational, Rational, PrimitiveSigned) -- pub fn rational_rational_signed_triple_gen() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_signed_triple_gen, &random_rational_rational_primitive_int_triple_gen, &special_random_rational_rational_signed_triple_gen, ) } // All `(Rational, Rational, T)` where `T` is signed and small, and if `T` is negative, neither // `Rational` is zero. pub fn rational_rational_signed_triple_gen_var_1() -> Generator<(Rational, Rational, T)> { Generator::new( &exhaustive_rational_rational_signed_triple_gen_var_1, &random_rational_rational_signed_triple_gen_var_1, &special_random_rational_rational_signed_triple_gen_var_1, ) } // -- (Rational, Rational, Rational) -- pub fn rational_triple_gen() -> Generator<(Rational, Rational, Rational)> { Generator::new( &exhaustive_rational_triple_gen, &random_rational_triple_gen, &special_random_rational_triple_gen, ) } // All triples of `Rational` where the last `Rational` is nonzero. pub fn rational_triple_gen_var_1() -> Generator<(Rational, Rational, Rational)> { Generator::new( &exhaustive_rational_triple_gen_var_1, &random_rational_triple_gen_var_1, &special_random_rational_triple_gen_var_1, ) } // All triples of `Rational`s `(x, y, z)` where x < y < z. pub fn rational_triple_gen_var_2() -> Generator<(Rational, Rational, Rational)> { Generator::new( &exhaustive_rational_triple_gen_var_2, &random_rational_triple_gen_var_2, &special_random_rational_triple_gen_var_2, ) } // All triples of `Rational`s `(x, y, z)` where x <= y <= z. pub fn rational_triple_gen_var_3() -> Generator<(Rational, Rational, Rational)> { Generator::new( &exhaustive_rational_triple_gen_var_3, &random_rational_triple_gen_var_3, &special_random_rational_triple_gen_var_3, ) } // -- (Rational, Rational, RoundingMode) -- // All `(Rational, Rational, RoundingMode)` triples that are a valid input to // `Rational::round_to_multiple`. pub fn rational_rational_rounding_mode_triple_gen_var_1() -> Generator<(Rational, Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rational_rounding_mode_triple_gen_var_1, &random_rational_rational_rounding_mode_triple_gen_var_1, &special_random_rational_rational_rounding_mode_triple_gen_var_1, ) } // -- (Rational, RoundingMode) -- pub fn rational_rounding_mode_pair_gen() -> Generator<(Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rounding_mode_pair_gen, &random_rational_rounding_mode_pair_gen, &special_random_rational_rounding_mode_pair_gen, ) } // All `(Rational, RoundingMode)` pairs that are valid inputs to `Natural::rounding_from(Rational)`. pub fn rational_rounding_mode_pair_gen_var_1() -> Generator<(Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_1, &random_rational_rounding_mode_pair_gen_var_1, &special_random_rational_rounding_mode_pair_gen_var_1, ) } // All `(Rational, RoundingMode)` pairs that are valid inputs to `Integer::rounding_from(Rational)`. pub fn rational_rounding_mode_pair_gen_var_2() -> Generator<(Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_2, &random_rational_rounding_mode_pair_gen_var_2, &special_random_rational_rounding_mode_pair_gen_var_2, ) } // All `(Rational, RoundingMode)` pairs that are valid inputs to `T::rounding_from(Rational)` for an // primitive integer type `T`. pub fn rational_rounding_mode_pair_gen_var_3< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >() -> Generator<(Rational, RoundingMode)> where Rational: PartialOrd, { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_3::, &random_rational_rounding_mode_pair_gen_var_3::, &special_random_rational_rounding_mode_pair_gen_var_3::, ) } // All `(Rational, RoundingMode)` pairs where the `Rational` is nonzero. pub fn rational_rounding_mode_pair_gen_var_4() -> Generator<(Rational, RoundingMode)> { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_4, &random_rational_rounding_mode_pair_gen_var_4, &special_random_rational_rounding_mode_pair_gen_var_4, ) } // All `(Rational, RoundingMode)` pairs that are valid inputs to `T::rounding_from(Rational)` for an // primitive float type `T`. pub fn rational_rounding_mode_pair_gen_var_5< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >() -> Generator<(Rational, RoundingMode)> where Rational: TryFrom, { Generator::new( &exhaustive_rational_rounding_mode_pair_gen_var_5::, &random_rational_rounding_mode_pair_gen_var_5::, &special_random_rational_rounding_mode_pair_gen_var_5::, ) } // var 6 is in malachite-float. // -- (Rational, ToSciOptions) -- pub fn rational_to_sci_options_pair_gen() -> Generator<(Rational, ToSciOptions)> { Generator::new( &exhaustive_rational_to_sci_options_pair_gen, &random_rational_to_sci_options_pair_gen, &special_random_rational_to_sci_options_pair_gen, ) } // All `(Rational, ToSciOptions)` pairs where the `Rational` can be formatted using the options. pub fn rational_to_sci_options_pair_gen_var_1() -> Generator<(Rational, ToSciOptions)> { Generator::new( &exhaustive_rational_to_sci_options_pair_gen_var_1, &random_rational_to_sci_options_pair_gen_var_1, &special_random_rational_to_sci_options_pair_gen_var_1, ) } // -- String -- // vars 1 through 10 are in malachite-base. // All `String`s that are produced by serializing a `Rational` into json. pub fn string_gen_var_11() -> Generator { Generator::new( &exhaustive_string_gen_var_11, &random_string_gen_var_11, &special_random_string_gen_var_2, ) } // All `String`s that are produced by converting a `Rational` to a string. pub fn string_gen_var_12() -> Generator { Generator::new( &exhaustive_string_gen_var_12, &random_string_gen_var_12, &special_random_string_gen_var_3, ) } // var 13 is in malachite-base. // -- (String, String, String) -- // vars 1 through 2 are in malachite-nz. // All triples of `String`s corresponding to the serialization of a `num::BigRational`, a // `rug::Rational`, and a `Rational`, respectively, into a JSON string. The three numbers have the // same value. pub fn string_triple_gen_var_3() -> Generator<(String, String, String)> { Generator::new( &exhaustive_string_triple_gen_var_3, &random_string_triple_gen_var_3, &special_random_string_triple_gen_var_3, ) } // -- Vec -- pub fn rational_vec_gen() -> Generator> { Generator::new( &exhaustive_rational_vec_gen, &random_rational_vec_gen, &special_random_rational_vec_gen, ) } pub fn rational_vec_gen_nrm() -> Generator<(Vec, Vec, Vec)> { Generator::new( &|| rational_vec_nrm(exhaustive_rational_vec_gen()), &|config| rational_vec_nrm(random_rational_vec_gen(config)), &|config| rational_vec_nrm(special_random_rational_vec_gen(config)), ) } pub mod common; pub mod exhaustive; pub mod random; pub mod special_random; ================================================ FILE: malachite-q/src/test_util/generators/random.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::random::{ RandomRationalsFromDoubleAndSign, random_negative_rationals, random_non_negative_rationals, random_nonzero_rationals, random_positive_rationals, random_rationals, }; use crate::test_util::extra_variadic::{ random_ordered_unique_triples, random_quadruples_xxyz, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::round_to_multiple_rational_filter; use malachite_base::bools::random::random_bools; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::random::random_to_sci_options; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, IsInteger, ToSci}; use malachite_base::num::random::geometric::{ geometric_random_nonzero_signeds, geometric_random_positive_unsigneds, geometric_random_signeds, geometric_random_unsigneds, }; use malachite_base::num::random::{ random_primitive_ints, random_unsigned_inclusive_range, special_random_finite_primitive_floats, special_random_nonzero_finite_primitive_floats, special_random_primitive_floats, }; use malachite_base::random::EXAMPLE_SEED; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{GenConfig, It}; use malachite_base::tuples::random::{ random_ordered_unique_pairs, random_pairs, random_pairs_from_single, }; use malachite_base::unions::Union2; use malachite_base::unions::random::random_union2s; use malachite_base::vecs::random::random_vecs; use malachite_nz::integer::Integer; use malachite_nz::integer::random::random_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ random_natural_range_to_infinity, random_naturals, random_positive_naturals, }; use num::BigRational; use std::cmp::Ordering::*; use std::ops::Shr; // -- Rational -- pub fn random_rational_gen(config: &GenConfig) -> It { Box::new(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_rational_gen_var_1(config: &GenConfig) -> It { Box::new(random_nonzero_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_rational_gen_var_2(config: &GenConfig) -> It { Box::new(random_positive_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_rational_gen_var_3(config: &GenConfig) -> It { Box::new(random_non_negative_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn random_rational_gen_var_4(config: &GenConfig) -> It where Rational: TryFrom, { Box::new( special_random_finite_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) .map(Rational::exact_from), ) } pub fn random_rational_gen_var_5 ConvertibleFrom<&'a Rational> + PrimitiveFloat>( config: &GenConfig, ) -> It { Box::new( random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(|q| !T::convertible_from(q)), ) } pub fn random_rational_gen_var_6(config: &GenConfig) -> It where Rational: TryFrom, { Box::new( special_random_nonzero_finite_primitive_floats( EXAMPLE_SEED, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), ) .map(|f| { let x = Rational::exact_from(f); let y = Rational::exact_from(if f > T::ZERO { f.next_lower() } else { f.next_higher() }); (x + y) >> 1 }), ) } pub fn random_rational_gen_var_7(config: &GenConfig) -> It { Box::new(RandomRationalsFromDoubleAndSign { bs: random_bools(EXAMPLE_SEED.fork("sign")), xs: geometric_random_unsigneds::( EXAMPLE_SEED.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }) } pub fn random_rational_gen_var_8(config: &GenConfig) -> It { Box::new( random_positive_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(|x| *x != 1u32), ) } // -- (Rational, Integer) -- pub fn random_rational_integer_pair_gen(config: &GenConfig) -> It<(Rational, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Integer, Integer) -- pub fn random_rational_integer_integer_triple_gen( config: &GenConfig, ) -> It<(Rational, Integer, Integer)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Natural) -- pub fn random_rational_natural_pair_gen(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_natural_pair_gen_var_1(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_natural_pair_gen_var_2(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: geometric_random_unsigneds::( seed.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( seed.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }, &|seed| { random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_natural_pair_gen_var_3(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_natural_pair_gen_var_4(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from) }, )) } // -- (Rational, Natural, Natural) -- pub fn random_rational_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Rational, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_natural_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Natural, Natural)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(_, x, y)| x < y), ) } // -- (Rational, PrimitiveFloat) -- pub fn random_rational_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Rational, PrimitiveFloat, PrimitiveFloat) -- pub fn random_rational_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Rational, PrimitiveInt) -- pub fn random_rational_primitive_int_pair_gen( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Rational, PrimitiveInt, PrimitiveInt) -- pub fn random_rational_primitive_int_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Rational, PrimitiveSigned) -- pub fn random_rational_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, exp)| *exp >= T::ZERO || *x != 0u32), ) } pub fn random_rational_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Rational, T)> where for<'a> &'a Rational: Shr, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, pow)| !x.denominator_ref().is_power_of_2() || !(x >> *pow).is_integer()), ) } pub fn random_rational_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { random_non_negative_rationals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_nonzero_signeds( seed_2, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) }, ) .filter(|(q, i)| *i > T::ZERO || *q != 0u32) }, &|seed| { random_pairs( seed, &|seed_2| { random_negative_rationals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_signeds::( seed_2, config.get_or("small_signed_mean_n", 32), config.get_or("small_signed_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn random_rational_signed_pair_gen_var_5( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_nonzero_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveSigned) -- pub fn random_rational_signed_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, e, f)| *e >= T::ZERO && *f >= T::ZERO || *x != 0), ) } // -- (Rational, PrimitiveSigned, PrimitiveUnsigned) -- pub fn random_rational_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Rational, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveSigned, RoundingMode) -- pub fn random_rational_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, i64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, i, rm)| { *rm != Exact || x.denominator_ref().is_power_of_2() && (x >> *i).is_integer() }), ) } // var 2 is in malachite-float. // -- (Rational, PrimitiveUnsigned) -- pub fn random_rational_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: geometric_random_unsigneds::( seed.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( seed.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_unsigned_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { random_non_negative_rationals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { random_negative_rationals( seed_2, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn random_rational_unsigned_pair_gen_var_5(config: &GenConfig) -> It<(Rational, u8)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| random_unsigned_inclusive_range(seed, 2, 36), )) } pub fn random_rational_unsigned_pair_gen_var_6(config: &GenConfig) -> It<(Rational, u8)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: geometric_random_unsigneds::( seed.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( seed.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }, &|seed| random_unsigned_inclusive_range(seed, 2, 36), )) } pub fn random_rational_unsigned_pair_gen_var_7( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_nonzero_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_unsigned_pair_gen_var_8( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_non_negative_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn random_rational_unsigned_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, Rational) -- pub fn random_rational_pair_gen(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs_from_single(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_rational_pair_gen_var_1(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_pair_gen_var_2(config: &GenConfig) -> It<(Rational, Rational)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !(x / y).is_integer()), ) } pub fn random_rational_pair_gen_var_3(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_ordered_unique_pairs(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_rational_pair_gen_var_4(config: &GenConfig) -> It<(Rational, Rational)> { // TODO Box::new( random_pairs_from_single(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y)| if x <= y { (x, y) } else { (y, x) }), ) } pub fn random_rational_pair_gen_var_5(config: &GenConfig) -> It<(Rational, Rational)> { // TODO Box::new( random_pairs_from_single(RandomRationalsFromDoubleAndSign { bs: random_bools(EXAMPLE_SEED.fork("sign")), xs: geometric_random_unsigneds::( EXAMPLE_SEED.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }) .filter_map(|(x, y)| match x.cmp(&y) { Equal => None, Less => Some((x, y)), Greater => Some((y, x)), }), ) } pub fn random_rational_pair_gen_var_6(config: &GenConfig) -> It<(Rational, Rational)> { // TODO Box::new( random_pairs_from_single(RandomRationalsFromDoubleAndSign { bs: random_bools(EXAMPLE_SEED.fork("sign")), xs: geometric_random_unsigneds::( EXAMPLE_SEED.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( EXAMPLE_SEED.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }) .map(|(x, y)| if x <= y { (x, y) } else { (y, x) }), ) } pub fn random_rational_pair_gen_var_7(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_positive_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(move |q| (q - Rational::ONE).gt_abs(&Rational::from_signeds(1, 1000))) }, )) } pub fn random_rational_pair_gen_var_8(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs_from_single(random_nonzero_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } // -- (Rational, Rational, Integer) -- pub fn random_rational_rational_integer_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, Integer)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_integers( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, Natural) -- pub fn random_rational_rational_natural_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_rational_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, Natural, Natural) -- pub fn random_rational_rational_natural_natural_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, Natural, Natural)> { Box::new(random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_positive_naturals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, PrimitiveFloat) -- pub fn random_rational_rational_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { special_random_primitive_floats( seed, config.get_or("exponent_mean_n", 8), config.get_or("exponent_mean_d", 1), config.get_or("precision_mean_n", 8), config.get_or("precision_mean_d", 1), config.get_or("special_p_mean_n", 1), config.get_or("special_p_mean_d", 64), ) }, )) } // -- (Rational, Rational, PrimitiveInt) -- pub fn random_rational_rational_primitive_int_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_ints, )) } // -- (Rational, Rational, PrimitiveSigned) -- pub fn random_rational_rational_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y, exp)| *exp >= T::ZERO || *x != 0 && *y != 0), ) } // -- (Rational, Rational, PrimitiveUnsigned) -- pub fn random_rational_rational_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn random_rational_rational_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, Rational, Rational) -- pub fn random_rational_triple_gen(config: &GenConfig) -> It<(Rational, Rational, Rational)> { Box::new(random_triples_from_single(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_rational_triple_gen_var_1(config: &GenConfig) -> It<(Rational, Rational, Rational)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_nonzero_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn random_rational_triple_gen_var_2(config: &GenConfig) -> It<(Rational, Rational, Rational)> { Box::new(random_ordered_unique_triples(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn random_rational_triple_gen_var_3(config: &GenConfig) -> It<(Rational, Rational, Rational)> { // TODO Box::new( random_triples_from_single(random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| { let mut xs = vec![x, y, z]; xs.sort_unstable(); let mut xs = xs.into_iter(); (xs.next().unwrap(), xs.next().unwrap(), xs.next().unwrap()) }), ) } // -- (Rational, Rational, RoundingMode) -- pub fn random_rational_rational_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(round_to_multiple_rational_filter), ) } // -- (Rational, RoundingMode) -- pub fn random_rational_rounding_mode_pair_gen(config: &GenConfig) -> It<(Rational, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn random_rational_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| match rm { Floor | Up => *x >= 0u32, Exact => Natural::convertible_from(x), _ => true, }), ) } pub fn random_rational_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| *rm != Exact || x.is_integer()), ) } pub fn random_rational_rounding_mode_pair_gen_var_3< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >( config: &GenConfig, ) -> It<(Rational, RoundingMode)> where Rational: PartialOrd, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| match rm { Floor => *x >= T::MIN, Ceiling => *x <= T::MAX, Up => *x >= T::MIN && *x <= T::MAX, Exact => T::convertible_from(x), _ => true, }), ) } pub fn random_rational_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_nonzero_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn random_rational_rounding_mode_pair_gen_var_5< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Rational, RoundingMode)> where Rational: TryFrom, { let max = Rational::exact_from(T::MAX_FINITE); let min = -&max; Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(move |(x, rm)| match rm { Floor => *x >= min, Ceiling => *x <= max, Up => *x >= min && *x <= max, Exact => T::convertible_from(x), _ => true, }), ) } // -- (Rational, ToSciOptions) -- pub fn random_rational_to_sci_options_pair_gen(config: &GenConfig) -> It<(Rational, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn random_rational_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- String -- // vars 1 through 10 are in malachite-base. pub fn random_string_gen_var_11(config: &GenConfig) -> It { Box::new( random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|r| serde_json::to_string(&r).unwrap()), ) } pub fn random_string_gen_var_12(config: &GenConfig) -> It { Box::new( random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| x.to_string()), ) } // -- (String, String, String) -- // vars 1 through 2 are in malachite-nz. pub fn random_string_triple_gen_var_3(config: &GenConfig) -> It<(String, String, String)> { Box::new( random_rationals( EXAMPLE_SEED, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigRational::from(&x)).unwrap(), serde_json::to_string(&rug::Rational::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } // -- Vec -- pub fn random_rational_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { random_rationals( seed, config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } ================================================ FILE: malachite-q/src/test_util/generators/special_random.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::random::RandomRationalsFromDoubleAndSign; use crate::random::{ striped_random_negative_rationals, striped_random_non_negative_rationals, striped_random_nonzero_rationals, striped_random_positive_rationals, striped_random_rationals, }; use crate::test_util::extra_variadic::{ random_ordered_unique_triples, random_quadruples_xxyz, random_triples, random_triples_from_single, random_triples_xxy, random_triples_xyy, }; use crate::test_util::generators::round_to_multiple_rational_filter; use malachite_base::bools::random::random_bools; use malachite_base::num::arithmetic::traits::IsPowerOf2; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::string::options::ToSciOptions; use malachite_base::num::conversion::string::options::random::random_to_sci_options; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, IsInteger, ToSci}; use malachite_base::num::random::geometric::{ geometric_random_nonzero_signeds, geometric_random_positive_unsigneds, geometric_random_signeds, geometric_random_unsigneds, }; use malachite_base::num::random::striped::{ striped_random_signeds, striped_random_unsigned_inclusive_range, striped_random_unsigneds, }; use malachite_base::num::random::{ random_finite_primitive_floats, random_nonzero_finite_primitive_floats, random_primitive_floats, }; use malachite_base::random::EXAMPLE_SEED; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::rounding_modes::random::random_rounding_modes; use malachite_base::test_util::generators::common::{GenConfig, It}; use malachite_base::tuples::random::{ random_ordered_unique_pairs, random_pairs, random_pairs_from_single, }; use malachite_base::unions::Union2; use malachite_base::unions::random::random_union2s; use malachite_base::vecs::random::random_vecs; use malachite_nz::integer::Integer; use malachite_nz::integer::random::striped_random_integers; use malachite_nz::natural::Natural; use malachite_nz::natural::random::{ striped_random_natural_range_to_infinity, striped_random_naturals, striped_random_positive_naturals, }; use num::BigRational; use std::ops::Shr; // -- Rational -- pub fn special_random_rational_gen(config: &GenConfig) -> It { Box::new(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_rational_gen_var_1(config: &GenConfig) -> It { Box::new(striped_random_nonzero_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_rational_gen_var_2(config: &GenConfig) -> It { Box::new(striped_random_positive_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_rational_gen_var_3(config: &GenConfig) -> It { Box::new(striped_random_non_negative_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) } pub fn special_random_rational_gen_var_4(_config: &GenConfig) -> It where Rational: TryFrom, { Box::new(random_finite_primitive_floats(EXAMPLE_SEED).map(Rational::exact_from)) } pub fn special_random_rational_gen_var_5< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >( config: &GenConfig, ) -> It { Box::new( striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(|q| !T::convertible_from(q)), ) } pub fn special_random_rational_gen_var_6(_config: &GenConfig) -> It where Rational: TryFrom, { Box::new( random_nonzero_finite_primitive_floats(EXAMPLE_SEED).map(|f| { let x = Rational::exact_from(f); let y = Rational::exact_from(if f > T::ZERO { f.next_lower() } else { f.next_higher() }); (x + y) >> 1 }), ) } pub fn special_random_rational_gen_var_7(config: &GenConfig) -> It { Box::new( striped_random_positive_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(|x| *x != 1u32), ) } // -- (Rational, Integer) -- pub fn special_random_rational_integer_pair_gen(config: &GenConfig) -> It<(Rational, Integer)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Integer, Integer) -- pub fn special_random_rational_integer_integer_triple_gen( config: &GenConfig, ) -> It<(Rational, Integer, Integer)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Natural) -- pub fn special_random_rational_natural_pair_gen(config: &GenConfig) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_natural_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_natural_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| RandomRationalsFromDoubleAndSign { bs: random_bools(seed.fork("sign")), xs: geometric_random_unsigneds::( seed.fork("numerator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), ys: geometric_random_positive_unsigneds::( seed.fork("denominator"), config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from), }, &|seed| { striped_random_natural_range_to_infinity( seed, Natural::TWO, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_natural_pair_gen_var_3( config: &GenConfig, ) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_natural_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, Natural)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) .map(Natural::from) }, )) } // -- (Rational, Natural, Natural) -- pub fn special_random_rational_natural_natural_triple_gen( config: &GenConfig, ) -> It<(Rational, Natural, Natural)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_natural_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Natural, Natural)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(_, x, y)| x < y), ) } // -- (Rational, PrimitiveFloat) -- pub fn special_random_rational_primitive_float_pair_gen( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Rational, PrimitiveFloat, PrimitiveFloat) -- pub fn special_random_rational_primitive_float_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Rational, PrimitiveSigned) -- pub fn special_random_rational_signed_pair_gen( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_signed_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_rational_signed_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, exp)| *exp >= T::ZERO || *x != 0u32), ) } pub fn special_random_rational_signed_pair_gen_var_3( config: &GenConfig, ) -> It<(Rational, T)> where for<'a> &'a Rational: Shr, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, pow)| !x.denominator_ref().is_power_of_2() || !(x >> *pow).is_integer()), ) } pub fn special_random_rational_signed_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_non_negative_rationals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_nonzero_signeds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) .filter(|(q, i)| *i > T::ZERO || *q != 0u32) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_negative_rationals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_signeds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_rational_signed_pair_gen_var_5( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_nonzero_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveSigned, PrimitiveSigned) -- pub fn special_random_rational_signed_signed_triple_gen( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_signed_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new( random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, e, f)| *e >= T::ZERO && *f >= T::ZERO || *x != 0), ) } // -- (Rational, PrimitiveSigned, PrimitiveUnsigned) -- pub fn special_random_rational_signed_unsigned_triple_gen_var_1< T: PrimitiveSigned, U: PrimitiveUnsigned, >( config: &GenConfig, ) -> It<(Rational, T, U)> { Box::new(random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveSigned, RoundingMode) -- pub fn special_random_rational_signed_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, i64, RoundingMode)> { Box::new( random_triples( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds::( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, i, rm)| { *rm != Exact || x.denominator_ref().is_power_of_2() && (x >> *i).is_integer() }), ) } // var 2 is in malachite-float. // -- (Rational, PrimitiveUnsigned) -- pub fn special_random_rational_unsigned_pair_gen( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_unsigned_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_rational_unsigned_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_rational_unsigned_pair_gen_var_3( config: &GenConfig, ) -> It<(Rational, T)> { Box::new( random_union2s( EXAMPLE_SEED, &|seed| { random_pairs( seed, &|seed_2| { striped_random_non_negative_rationals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_positive_unsigneds( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) }, ) }, &|seed| { random_pairs( seed, &|seed_2| { striped_random_negative_rationals( seed_2, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed_2| { geometric_random_unsigneds::( seed_2, config.get_or("small_unsigned_mean_n", 32), config.get_or("small_unsigned_mean_d", 1), ) .filter_map(|i| i.arithmetic_checked_shl(1).map(|j| j | T::ONE)) }, ) }, ) .map(Union2::unwrap), ) } pub fn special_random_rational_unsigned_pair_gen_var_4(config: &GenConfig) -> It<(Rational, u8)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigned_inclusive_range( seed, 2, 36, config.get_or("mean_stripe_n", 4), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_unsigned_pair_gen_var_5( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_rational_unsigned_pair_gen_var_6( config: &GenConfig, ) -> It<(Rational, T)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_non_negative_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, PrimitiveUnsigned, PrimitiveUnsigned) -- pub fn special_random_rational_unsigned_unsigned_triple_gen( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_unsigned_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, T, T)> { Box::new(random_triples_xyy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, Rational) -- pub fn special_random_rational_pair_gen(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs_from_single(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_rational_pair_gen_var_1(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_pair_gen_var_2(config: &GenConfig) -> It<(Rational, Rational)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, ) .filter(|(x, y)| !(x / y).is_integer()), ) } pub fn special_random_rational_pair_gen_var_3(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_ordered_unique_pairs(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_rational_pair_gen_var_4(config: &GenConfig) -> It<(Rational, Rational)> { // TODO Box::new( random_pairs_from_single(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y)| if x <= y { (x, y) } else { (y, x) }), ) } pub fn special_random_rational_pair_gen_var_5(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_positive_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .filter(|q| (q - Rational::ONE).gt_abs(&Rational::from_signeds(1, 1000))) }, )) } pub fn special_random_rational_pair_gen_var_6(config: &GenConfig) -> It<(Rational, Rational)> { Box::new(random_pairs_from_single(striped_random_nonzero_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } // -- (Rational, Rational, Integer) -- pub fn special_random_rational_rational_integer_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, Integer)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_integers( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, Natural) -- pub fn special_random_rational_rational_natural_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_rational_natural_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, Natural)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, Natural, Natural) -- pub fn special_random_rational_rational_natural_natural_quadruple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, Natural, Natural)> { Box::new(random_quadruples_xxyz( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_positive_naturals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } // -- (Rational, Rational, PrimitiveFloat) -- pub fn special_random_rational_rational_primitive_float_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_primitive_floats, )) } // -- (Rational, Rational, PrimitiveSigned) -- pub fn special_random_rational_rational_signed_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_signeds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_rational_signed_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_signeds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, ) .filter(|(x, y, exp)| *exp >= T::ZERO || *x != 0 && *y != 0), ) } // -- (Rational, Rational, PrimitiveUnsigned) -- pub fn special_random_rational_rational_unsigned_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_unsigneds( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), ) }, )) } pub fn special_random_rational_rational_unsigned_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } pub fn special_random_rational_rational_unsigned_triple_gen_var_2( config: &GenConfig, ) -> It<(Rational, Rational, T)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { geometric_random_positive_unsigneds( seed, config.get_or("mean_small_n", 64), config.get_or("mean_small_d", 1), ) }, )) } // -- (Rational, Rational, Rational) -- pub fn special_random_rational_triple_gen( config: &GenConfig, ) -> It<(Rational, Rational, Rational)> { Box::new(random_triples_from_single(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_rational_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, Rational)> { Box::new(random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { striped_random_nonzero_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, )) } pub fn special_random_rational_triple_gen_var_2( config: &GenConfig, ) -> It<(Rational, Rational, Rational)> { Box::new(random_ordered_unique_triples(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ))) } pub fn special_random_rational_triple_gen_var_3( config: &GenConfig, ) -> It<(Rational, Rational, Rational)> { // TODO Box::new( random_triples_from_single(striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), )) .map(|(x, y, z)| { let mut xs = vec![x, y, z]; xs.sort_unstable(); let mut xs = xs.into_iter(); (xs.next().unwrap(), xs.next().unwrap(), xs.next().unwrap()) }), ) } // -- (Rational, Rational, RoundingMode) -- pub fn special_random_rational_rational_rounding_mode_triple_gen_var_1( config: &GenConfig, ) -> It<(Rational, Rational, RoundingMode)> { Box::new( random_triples_xxy( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(round_to_multiple_rational_filter), ) } // -- (Rational, RoundingMode) -- pub fn special_random_rational_rounding_mode_pair_gen( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_rational_rounding_mode_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| match rm { Floor | Up => *x >= 0u32, Exact => Natural::convertible_from(x), _ => true, }), ) } pub fn special_random_rational_rounding_mode_pair_gen_var_2( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| *rm != Exact || x.is_integer()), ) } pub fn special_random_rational_rounding_mode_pair_gen_var_3< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >( config: &GenConfig, ) -> It<(Rational, RoundingMode)> where Rational: PartialOrd, { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(|(x, rm)| match rm { Floor => *x >= T::MIN, Ceiling => *x <= T::MAX, Up => *x >= T::MIN && *x <= T::MAX, Exact => T::convertible_from(x), _ => true, }), ) } pub fn special_random_rational_rounding_mode_pair_gen_var_4( config: &GenConfig, ) -> It<(Rational, RoundingMode)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_nonzero_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, )) } pub fn special_random_rational_rounding_mode_pair_gen_var_5< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >( config: &GenConfig, ) -> It<(Rational, RoundingMode)> where Rational: TryFrom, { let max = Rational::exact_from(T::MAX_FINITE); let min = -&max; Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &random_rounding_modes, ) .filter(move |(x, rm)| match rm { Floor => *x >= min, Ceiling => *x <= max, Up => *x >= min && *x <= max, Exact => T::convertible_from(x), _ => true, }), ) } // -- (Rational, ToSciOptions) -- pub fn special_random_rational_to_sci_options_pair_gen( config: &GenConfig, ) -> It<(Rational, ToSciOptions)> { Box::new(random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, )) } pub fn special_random_rational_to_sci_options_pair_gen_var_1( config: &GenConfig, ) -> It<(Rational, ToSciOptions)> { Box::new( random_pairs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed.fork("xs"), config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, &|seed| { random_to_sci_options( seed, config.get_or("small_mean_n", 4), config.get_or("small_mean_d", 1), ) }, ) .filter(|(x, options)| x.fmt_sci_valid(*options)), ) } // -- String -- // var 1 is in malachite-base. pub fn special_random_string_gen_var_2(config: &GenConfig) -> It { Box::new( striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|r| serde_json::to_string(&r).unwrap()), ) } pub fn special_random_string_gen_var_3(config: &GenConfig) -> It { Box::new( striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| x.to_string()), ) } // -- (String, String, String) -- // vars 1 through 2 are in malachite-nz. pub fn special_random_string_triple_gen_var_3(config: &GenConfig) -> It<(String, String, String)> { Box::new( striped_random_rationals( EXAMPLE_SEED, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) .map(|x| { ( serde_json::to_string(&BigRational::from(&x)).unwrap(), serde_json::to_string(&rug::Rational::from(&x)).unwrap(), serde_json::to_string(&x).unwrap(), ) }), ) } // -- Vec -- pub fn special_random_rational_vec_gen(config: &GenConfig) -> It> { Box::new(random_vecs( EXAMPLE_SEED, &|seed| { striped_random_rationals( seed, config.get_or("mean_stripe_n", 32), config.get_or("mean_stripe_d", 1), config.get_or("mean_bits_n", 64), config.get_or("mean_bits_d", 1), ) }, config.get_or("mean_len_n", 4), config.get_or("mean_len_d", 1), )) } ================================================ FILE: malachite-q/src/test_util/mod.rs ================================================ // Copyright © 2026 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 . pub mod arithmetic; pub mod bench; pub mod common; pub mod conversion; pub mod extra_variadic; pub mod generators; pub mod random; ================================================ FILE: malachite-q/src/test_util/random/mod.rs ================================================ // Copyright © 2026 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 crate::Rational; use crate::itertools::Itertools; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::stats::common_values_map::common_values_map; use malachite_base::test_util::stats::median; use malachite_base::test_util::stats::moments::{MomentStats, moment_stats}; pub fn random_rationals_helper_helper>( xs: I, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { let actual_values = xs .clone() .map(|x| Rational::to_string(&x)) .take(20) .collect_vec(); let actual_values = actual_values.iter().map(String::as_str).collect_vec(); let actual_common_values = common_values_map(1000000, 10, xs.clone()) .into_iter() .map(|(x, freq)| (x.to_string(), freq)) .collect_vec(); let actual_common_values = actual_common_values .iter() .map(|(x, freq)| (x.as_str(), *freq)) .collect_vec(); let (median_lo, median_hi) = median(xs.clone().take(1000000)); let (median_lo, median_hi) = ( median_lo.to_string(), median_hi.map(|x| Rational::to_string(&x)), ); let actual_sample_median = (median_lo.as_str(), median_hi.as_deref()); let actual_sample_moment_stats = moment_stats(xs.take(1000000).map(|x| f64::rounding_from(&x, Nearest).0)); assert_eq!( ( actual_values.as_slice(), actual_common_values.as_slice(), actual_sample_median, actual_sample_moment_stats ), ( expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats ) ); } ================================================ FILE: malachite-q/tests/arithmetic/abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsAssign}; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::{BigRational, Signed}; use std::str::FromStr; #[test] fn test_abs() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); let abs = x.clone().abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); let abs = (&x).abs(); assert!(abs.is_valid()); assert_eq!(abs.to_string(), out); assert_eq!(BigRational::from_str(s).unwrap().abs().to_string(), out); assert_eq!(rug::Rational::from_str(s).unwrap().abs().to_string(), out); let mut x = x; x.abs_assign(); assert!(abs.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "0"); test("123", "123"); test("-123", "123"); test("22/7", "22/7"); test("-22/7", "22/7"); } #[test] fn abs_properties() { rational_gen().test_properties(|x| { let abs = x.clone().abs(); assert!(abs.is_valid()); assert_eq!(Rational::from(&BigRational::from(&x).abs()), abs); assert_eq!(Rational::from(&rug::Rational::from(&x).abs()), abs); let abs_alt = (&x).abs(); assert!(abs_alt.is_valid()); assert_eq!(abs_alt, abs); let mut abs_alt = x.clone(); abs_alt.abs_assign(); assert!(abs_alt.is_valid()); assert_eq!(abs_alt, abs); assert!(abs >= 0); assert_eq!(abs == x, x >= 0); assert_eq!((&abs).abs(), abs); }); integer_gen().test_properties(|x| { assert_eq!(Rational::from(&x).abs(), Rational::from(x.abs())); }); } ================================================ FILE: malachite-q/tests/arithmetic/abs_diff.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, AbsDiff, AbsDiffAssign}; use malachite_base::num::basic::traits::Zero; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen, rational_triple_gen}; use std::str::FromStr; #[test] fn test_abs_diff_rational() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); n.abs_diff_assign(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n.abs_diff_assign(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone().abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(v.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&u).abs_diff(&v); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0", "0"); test("0", "-123", "123"); test("123", "0", "123"); test("123", "-456", "579"); test("0", "123", "123"); test("123", "123", "0"); test("123", "456", "333"); test("0", "-123", "123"); test("-123", "0", "123"); test("-123", "-456", "333"); test("0", "123", "123"); test("-123", "-123", "0"); test("1/2", "-1/3", "5/6"); test("1/2", "1/3", "1/6"); test("-1/2", "-1/3", "1/6"); test("-1/2", "1/3", "5/6"); test("1/2", "-1/2", "1"); test("1/2", "1/2", "0"); test("-1/2", "-1/2", "0"); test("-1/2", "1/2", "1"); } #[test] fn abs_diff_properties() { rational_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.abs_diff_assign(&y); assert!(mut_x.is_valid()); let diff = mut_x; assert!(diff >= 0); let mut mut_x = x.clone(); mut_x.abs_diff_assign(y.clone()); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let diff_alt = x.clone().abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = x.clone().abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(y.clone()); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); let diff_alt = (&x).abs_diff(&y); assert_eq!(diff_alt, diff); assert!(diff_alt.is_valid()); assert_eq!((&x - &y).abs(), diff); assert_eq!((&y).abs_diff(&x), diff); assert_eq!((-&x).abs_diff(-&y), diff); assert_eq!(diff == 0, x == y); }); rational_gen().test_properties(|x| { assert_eq!((&x).abs_diff(Rational::ZERO), (&x).abs()); assert_eq!((&x).abs_diff(&x), 0); assert_eq!(Rational::ZERO.abs_diff(&x), x.abs()); }); rational_triple_gen().test_properties(|(x, y, z)| { assert!((&x).abs_diff(&z) <= x.abs_diff(&y) + y.abs_diff(z)); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!( (&x).abs_diff(&y), Rational::from(x).abs_diff(Rational::from(y)) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/add.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_nz::test_util::generators::integer_vec_gen; use malachite_q::Rational; use malachite_q::test_util::arithmetic::add::add_naive; use malachite_q::test_util::arithmetic::add::rational_sum_naive; use malachite_q::test_util::generators::{ rational_gen, rational_pair_gen, rational_triple_gen, rational_vec_gen, }; use num::BigRational; use std::iter::{Sum, once}; use std::str::FromStr; #[test] fn test_add() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); n += v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n += &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u + &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigRational::from_str(s).unwrap() + BigRational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() + rug::Rational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "123"); test("123", "0", "123"); test("123", "456", "579"); test("0", "-123", "-123"); test("123", "-123", "0"); test("123", "-456", "-333"); test("0", "123", "123"); test("-123", "0", "-123"); test("-123", "456", "333"); test("0", "-123", "-123"); test("-123", "123", "0"); test("1/2", "1/3", "5/6"); test("1/2", "-1/3", "1/6"); test("-1/2", "1/3", "-1/6"); test("-1/2", "-1/3", "-5/6"); test("1/2", "1/2", "1"); test("1/2", "-1/2", "0"); test("-1/2", "1/2", "0"); test("-1/2", "-1/2", "-1"); } #[test] fn test_sum() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let sum = Rational::sum(xs.iter().cloned()); assert!(sum.is_valid()); assert_eq!(sum.to_string(), out); let sum_alt = Rational::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = rational_sum_naive(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }; test("[]", "0"); test("[22/7]", "22/7"); test("[22/7, 1/3]", "73/21"); test( "[0, 1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]", "19079/2520", ); test( "[123456/78901, 34567/890123, 45678/90123]", "342501191973781/162294410775211", ); } #[test] fn add_properties() { rational_pair_gen().test_properties(|(x, y)| { let sum_val_val = x.clone() + y.clone(); let sum_val_ref = x.clone() + &y; let sum_ref_val = &x + y.clone(); let sum = &x + &y; assert!(sum_val_val.is_valid()); assert!(sum_val_ref.is_valid()); assert!(sum_ref_val.is_valid()); assert!(sum.is_valid()); assert_eq!(sum_val_val, sum); assert_eq!(sum_val_ref, sum); assert_eq!(sum_ref_val, sum); let mut mut_x = x.clone(); mut_x += y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, sum); let mut mut_x = x.clone(); mut_x += &y; assert_eq!(mut_x, sum); assert!(mut_x.is_valid()); let mut mut_x = rug::Rational::from(&x); mut_x += rug::Rational::from(&y); assert_eq!(Rational::from(&mut_x), sum); assert_eq!( Rational::from(&(BigRational::from(&x) + BigRational::from(&y))), sum ); assert_eq!( Rational::from(&(rug::Rational::from(&x) + rug::Rational::from(&y))), sum ); assert_eq!(add_naive(x.clone(), y.clone()), sum); assert_eq!(&y + &x, sum); assert_eq!(&sum - &x, y); assert_eq!(sum - y, x); }); rational_gen().test_properties(|ref x| { assert_eq!(x + Rational::ZERO, *x); assert_eq!(Rational::ZERO + x, *x); assert_eq!(x + x, x << 1); assert_eq!(x + (-x), 0); }); rational_triple_gen().test_properties(|(x, y, z)| { assert_eq!((&x + &y) + &z, x + (y + z)); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(&x + &y, Rational::from(x) + Rational::from(y)); }); } #[test] fn sum_properties() { rational_vec_gen().test_properties(|xs| { let sum = Rational::sum(xs.iter().cloned()); assert!(sum.is_valid()); let sum_alt = Rational::sum(xs.iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); let sum_alt = rational_sum_naive(xs.into_iter()); assert!(sum_alt.is_valid()); assert_eq!(sum_alt, sum); }); rational_gen().test_properties(|x| { assert_eq!(Rational::sum(once(&x)), x); assert_eq!(Rational::sum(once(x.clone())), x); }); rational_pair_gen().test_properties(|(x, y)| { let sum = &x + &y; assert_eq!(Rational::sum([&x, &y].into_iter()), sum); assert_eq!(Rational::sum([x, y].into_iter()), sum); }); integer_vec_gen().test_properties(|xs| { assert_eq!( Rational::sum(xs.iter().map(Rational::from)), Rational::from(Integer::sum(xs.into_iter())) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/approximate.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Reciprocal, RoundToMultiple}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::arithmetic::traits::{Approximate, ApproximateAssign}; use malachite_q::test_util::arithmetic::approximate::approximate_naive; use malachite_q::test_util::generators::{ rational_gen, rational_natural_natural_triple_gen_var_1, rational_natural_pair_gen_var_3, rational_natural_pair_gen_var_4, }; use std::str::FromStr; #[test] fn test_approximate() { let test = |x, d, out| { let mut x = Rational::from_str(x).unwrap(); let d = Natural::from_str(d).unwrap(); let a = x.clone().approximate(&d); assert!(a.is_valid()); assert_eq!(a.to_string(), out); let a = (&x).approximate(&d); assert!(a.is_valid()); assert_eq!(a.to_string(), out); x.approximate_assign(&d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test("3", "1", "3"); test("3", "10", "3"); test("27/32", "1", "1"); test("27/32", "3", "1"); test("27/32", "4", "3/4"); test("27/32", "5", "4/5"); test("27/32", "6", "5/6"); test("27/32", "12", "5/6"); test("27/32", "13", "11/13"); test("27/32", "18", "11/13"); test("27/32", "19", "16/19"); test("27/32", "31", "16/19"); test("27/32", "32", "27/32"); test("27/32", "100", "27/32"); test("6369051672525773/4503599627370496", "10", "7/5"); test("6369051672525773/4503599627370496", "100", "140/99"); test("6369051672525773/4503599627370496", "1000", "1393/985"); test( "6369051672525773/4503599627370496", "1000000", "665857/470832", ); test("884279719003555/281474976710656", "10", "22/7"); test("884279719003555/281474976710656", "100", "311/99"); test("884279719003555/281474976710656", "1000", "355/113"); test( "884279719003555/281474976710656", "1000000", "3126535/995207", ); test("6121026514868073/2251799813685248", "10", "19/7"); test("6121026514868073/2251799813685248", "100", "193/71"); test("6121026514868073/2251799813685248", "1000", "1457/536"); test( "6121026514868073/2251799813685248", "1000000", "1084483/398959", ); test("7/9", "2", "1"); test("-7/9", "2", "-1"); test("1/2", "1", "0"); test("-1/2", "1", "0"); test("3/2", "1", "2"); test("-3/2", "1", "-2"); test("1/4", "2", "0"); test("-1/4", "2", "0"); } #[test] #[should_panic] fn approximate_assign_fail() { let mut x = Rational::ONE; x.approximate_assign(&Natural::ZERO); } #[test] #[should_panic] fn approximate_fail() { Rational::ONE.approximate(&Natural::ZERO); } #[test] #[should_panic] fn approximate_ref_fail() { (&Rational::ONE).approximate(&Natural::ZERO); } #[test] fn approximate_properties() { rational_natural_pair_gen_var_3().test_properties(|(x, max_denominator)| { let a = x.clone().approximate(&max_denominator); assert!(a.is_valid()); let a_alt = (&x).approximate(&max_denominator); assert!(a_alt.is_valid()); assert_eq!(a, a_alt); let mut a_alt = x.clone(); a_alt.approximate_assign(&max_denominator); assert!(a_alt.is_valid()); assert_eq!(a_alt, a); assert_eq!( (&x).round_to_multiple(Rational::from(a.denominator_ref()).reciprocal(), Nearest) .0, a ); assert_eq!((-x).approximate(&max_denominator), -a); }); rational_natural_pair_gen_var_4().test_properties(|(x, max_denominator)| { assert_eq!( (&x).approximate(&max_denominator), approximate_naive(&x, &max_denominator) ); }); rational_natural_natural_triple_gen_var_1().test_properties(|(x, d, max_d)| { let a = (&x).approximate(&max_d); let a_alt = (&x) .round_to_multiple(Rational::from(&d).reciprocal(), Nearest) .0; assert!((&x - a_alt).ge_abs(&(&x - &a))); let a_worse = x.approximate(&d); assert!(a_worse.denominator_ref() <= a.denominator_ref()); }); rational_gen().test_properties(|x| { assert_eq!((&x).approximate(x.denominator_ref()), x); assert_eq!( (&x).approximate(&Natural::ONE), Integer::rounding_from(x, Nearest).0 ); }); } ================================================ FILE: malachite-q/tests/arithmetic/ceiling.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, CeilingAssign, Floor}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::BigRational; use std::str::FromStr; #[test] fn test_ceiling() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); let ceiling = x.clone().ceiling(); assert!(ceiling.is_valid()); assert_eq!(ceiling.to_string(), out); let ceiling = (&x).ceiling(); assert!(ceiling.is_valid()); assert_eq!(ceiling.to_string(), out); assert_eq!(BigRational::from_str(s).unwrap().ceil().to_string(), out); assert_eq!(rug::Rational::from_str(s).unwrap().ceil().to_string(), out); let mut x = x; x.ceiling_assign(); assert!(ceiling.is_valid()); assert_eq!(x.to_string(), out); }; test("1", "1"); test("-1", "-1"); test("123", "123"); test("22/7", "4"); test("-22/7", "-3"); test("936851431250/1397", "670616630"); } #[test] fn ceiling_properties() { rational_gen().test_properties(|x| { let ceiling = x.clone().ceiling(); assert!(ceiling.is_valid()); assert_eq!(Rational::from(&BigRational::from(&x).ceil()), ceiling); assert_eq!(Rational::from(&rug::Rational::from(&x).ceil()), ceiling); let ceiling_alt = (&x).ceiling(); assert!(ceiling_alt.is_valid()); assert_eq!(ceiling_alt, ceiling); let mut ceiling_alt = x.clone(); ceiling_alt.ceiling_assign(); assert!(ceiling_alt.is_valid()); assert_eq!(ceiling_alt, ceiling); assert_eq!(Integer::rounding_from(&x, Ceiling).0, ceiling); assert!(ceiling >= x); assert!(&ceiling - Integer::ONE < x); assert_eq!(ceiling, Rational::from(&ceiling).ceiling()); assert_eq!(ceiling, -(-x).floor()); }); } ================================================ FILE: malachite-q/tests/arithmetic/denominators_in_closed_interval.rs ================================================ // Copyright © 2026 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::comparison::is_strictly_ascending; use malachite_base::iterators::prefix_to_string; use malachite_base::num::basic::traits::{One, Zero}; use malachite_nz::natural::Natural; use malachite_nz::natural::exhaustive::exhaustive_positive_naturals; use malachite_q::Rational; use malachite_q::arithmetic::traits::DenominatorsInClosedInterval; use malachite_q::exhaustive::exhaustive_rationals_with_denominator_inclusive_range; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen_var_3}; use std::str::FromStr; #[test] fn test_denominators_in_closed_interval() { let test = |a, b, out| { let a = Rational::from_str(a).unwrap(); let b = Rational::from_str(b).unwrap(); assert_eq!( prefix_to_string(Rational::denominators_in_closed_interval(a, b), 20), out ); }; test( "0", "2", "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...]", ); test( "1/3", "1/2", "[2, 3, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, ...]", ); test( "99/100", "101/100", "[1, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, \ 117, 118, ...]", ); test( "1/1000000000001", "1/1000000000000", "[1000000000000, 1000000000001, 2000000000001, 3000000000001, 3000000000002, \ 4000000000001, 4000000000003, 5000000000001, 5000000000002, 5000000000003, 5000000000004, \ 6000000000001, 6000000000005, 7000000000001, 7000000000002, 7000000000003, 7000000000004, \ 7000000000005, 7000000000006, 8000000000001, ...]", ); // about e to about π test( "268876667/98914198", "245850922/78256779", "[1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, ...]", ); test( "5/19", "3/11", "[11, 15, 19, 26, 34, 37, 41, 48, 49, 53, 56, 59, 63, 64, 67, 70, 71, 72, 79, 81, ...]", ); } #[test] #[should_panic] fn denominators_in_closed_interval_fail_1() { Rational::denominators_in_closed_interval(Rational::ONE, Rational::ONE); } #[test] #[should_panic] fn denominators_in_closed_interval_fail_2() { Rational::denominators_in_closed_interval(Rational::ONE, Rational::ZERO); } #[test] fn denominators_in_closed_interval_properties() { let mut i = 0; rational_pair_gen_var_3().test_properties(|(a, b)| { let ds = Rational::denominators_in_closed_interval(a.clone(), b.clone()) .take(20) .collect_vec(); assert!(is_strictly_ascending(ds.iter())); for d in &ds { assert!( exhaustive_rationals_with_denominator_inclusive_range( d.clone(), a.clone(), b.clone() ) .next() .is_some() ); } for d in 1u32..=20 { let d = Natural::from(d); if !ds.contains(&d) { assert!( exhaustive_rationals_with_denominator_inclusive_range( d.clone(), a.clone(), b.clone(), ) .next() .is_none(), "{a} {b} {d} {i} {ds:?}" ); } } i += 1; }); rational_gen().test_properties(|a| { assert!( Rational::denominators_in_closed_interval(a.clone(), a + Rational::ONE) .take(20) .eq(exhaustive_positive_naturals().take(20)) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/div.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedDiv, Reciprocal}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_q::Rational; use malachite_q::test_util::arithmetic::div::div_naive; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_1, rational_pair_gen, rational_pair_gen_var_1, rational_triple_gen_var_1, }; use num::{BigRational, CheckedDiv as NumCheckedDiv}; use std::str::FromStr; #[test] fn test_div() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); n /= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n /= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() / v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u / v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() / &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u / &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigRational::from_str(s).unwrap() / BigRational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() / rug::Rational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "1/123", "0"); test("0", "-1/123", "0"); test("1", "1/123", "123"); test("1", "-1/123", "-123"); test("-1", "1/123", "-123"); test("-1", "-1/123", "123"); test("123", "1", "123"); test("123", "-1", "-123"); test("-123", "1", "-123"); test("-123", "-1", "123"); test("123", "1/456", "56088"); test("123", "-1/456", "-56088"); test("-123", "1/456", "-56088"); test("-123", "-1/456", "56088"); test("22/7", "2/3", "33/7"); test("22/7", "-2/3", "-33/7"); test("-22/7", "2/3", "-33/7"); test("-22/7", "-2/3", "33/7"); test("4/5", "4/5", "1"); test("4/5", "-4/5", "-1"); test("-4/5", "4/5", "-1"); test("-4/5", "-4/5", "1"); } #[test] fn test_checked_div() { let test = |s, t, out: Option<&'static str>| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let n = u.clone().checked_div(v.clone()); assert_eq!(n.as_ref().map(ToString::to_string).as_deref(), out); if out.is_some() { assert!(n.unwrap().is_valid()); } let n = (&u).checked_div(v.clone()); assert_eq!(n.as_ref().map(ToString::to_string).as_deref(), out); if out.is_some() { assert!(n.unwrap().is_valid()); } let n = u.clone().checked_div(&v); assert_eq!(n.as_ref().map(ToString::to_string).as_deref(), out); if out.is_some() { assert!(n.unwrap().is_valid()); } let n = (&u).checked_div(&v); assert_eq!(n.as_ref().map(ToString::to_string).as_deref(), out); if out.is_some() { assert!(n.unwrap().is_valid()); } let n = BigRational::from_str(s) .unwrap() .checked_div(&BigRational::from_str(t).unwrap()); assert_eq!(n.as_ref().map(ToString::to_string).as_deref(), out); }; test("0", "1/123", Some("0")); test("0", "-1/123", Some("0")); test("0", "0", None); test("1", "1/123", Some("123")); test("1", "-1/123", Some("-123")); test("1", "0", None); test("-1", "1/123", Some("-123")); test("-1", "-1/123", Some("123")); test("-1", "0", None); test("123", "1", Some("123")); test("123", "-1", Some("-123")); test("123", "0", None); test("-123", "1", Some("-123")); test("-123", "-1", Some("123")); test("-123", "0", None); test("123", "1/456", Some("56088")); test("123", "-1/456", Some("-56088")); test("-123", "1/456", Some("-56088")); test("-123", "-1/456", Some("56088")); test("22/7", "2/3", Some("33/7")); test("22/7", "-2/3", Some("-33/7")); test("22/7", "0", None); test("-22/7", "2/3", Some("-33/7")); test("-22/7", "-2/3", Some("33/7")); test("-22/7", "0", None); test("4/5", "4/5", Some("1")); test("4/5", "-4/5", Some("-1")); test("4/5", "0", None); test("-4/5", "4/5", Some("-1")); test("-4/5", "-4/5", Some("1")); test("-4/5", "0", None); } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_fail_1() { Rational::ONE / Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_fail_2() { Rational::ZERO / Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_val_ref_fail_1() { Rational::ONE / &Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_val_ref_fail_2() { Rational::ZERO / &Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_ref_val_fail_1() { &Rational::ONE / Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_ref_val_fail_2() { &Rational::ZERO / Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_ref_ref_fail_1() { &Rational::ONE / &Rational::ZERO; } #[allow(clippy::no_effect, unused_must_use)] #[test] #[should_panic] fn div_ref_ref_fail_2() { &Rational::ZERO / &Rational::ZERO; } #[test] #[should_panic] fn div_assign_fail_1() { let mut x = Rational::ONE; x /= Rational::ZERO; } #[test] #[should_panic] fn div_assign_fail_2() { let mut x = Rational::ZERO; x /= Rational::ZERO; } #[test] #[should_panic] fn div_assign_ref_fail_1() { let mut x = Rational::ONE; x /= &Rational::ZERO; } #[test] #[should_panic] fn div_assign_ref_fail_2() { let mut x = Rational::ZERO; x /= &Rational::ZERO; } #[allow(clippy::eq_op)] #[test] fn div_properties() { rational_pair_gen_var_1().test_properties(|(x, y)| { let quotient_val_val = x.clone() / y.clone(); let quotient_val_ref = x.clone() / &y; let quotient_ref_val = &x / y.clone(); let quotient = &x / &y; assert!(quotient_val_val.is_valid()); assert!(quotient_val_ref.is_valid()); assert!(quotient_ref_val.is_valid()); assert!(quotient.is_valid()); assert_eq!(quotient_val_val, quotient); assert_eq!(quotient_val_ref, quotient); assert_eq!(quotient_ref_val, quotient); let mut mut_x = x.clone(); mut_x /= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, quotient); let mut mut_x = x.clone(); mut_x /= &y; assert_eq!(mut_x, quotient); assert!(mut_x.is_valid()); let mut mut_x = rug::Rational::from(&x); mut_x /= rug::Rational::from(&y); assert_eq!(Rational::from(&mut_x), quotient); assert_eq!( Rational::from(&(BigRational::from(&x) / BigRational::from(&y))), quotient ); assert_eq!( Rational::from(&(rug::Rational::from(&x) / rug::Rational::from(&y))), quotient ); assert_eq!(div_naive(x.clone(), y.clone()), quotient); assert_eq!((&x).checked_div(y.clone()).unwrap(), quotient); assert_eq!(&x * (&y).reciprocal(), quotient); assert_eq!("ient * &y, x); if quotient != 0u32 { assert_eq!(&y / &x, ("ient).reciprocal()); assert_eq!(&x / "ient, y); } assert_eq!(-&x / &y, -"ient); assert_eq!(x / -y, -quotient); }); rational_gen().test_properties(|ref x| { assert_eq!(x / Rational::ONE, *x); assert_eq!(x / Rational::NEGATIVE_ONE, -x); }); rational_gen_var_1().test_properties(|ref x| { assert_eq!(Rational::ZERO / x, 0); assert_eq!(Rational::ONE / x, x.reciprocal()); assert_eq!(Rational::NEGATIVE_ONE / x, -x.reciprocal()); assert_eq!(x / x, 1); }); rational_triple_gen_var_1().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x + y) / z, x / z + y / z); assert_eq!((x - y) / z, x / z - y / z); }); } #[test] fn checked_div_properties() { rational_pair_gen().test_properties(|(x, y)| { let quotient_val_val = x.clone().checked_div(y.clone()); let quotient_val_ref = x.clone().checked_div(&y); let quotient_ref_val = (&x).checked_div(y.clone()); let quotient = (&x).checked_div(&y); assert!(quotient_val_val.as_ref().is_none_or(Rational::is_valid)); assert!(quotient_val_ref.as_ref().is_none_or(Rational::is_valid)); assert!(quotient_ref_val.as_ref().is_none_or(Rational::is_valid)); assert!(quotient.as_ref().is_none_or(Rational::is_valid)); assert_eq!(quotient_val_val, quotient); assert_eq!(quotient_val_ref, quotient); assert_eq!(quotient_ref_val, quotient); if y != 0u32 { assert_eq!(quotient, Some(&x / &y)); } assert_eq!( BigRational::from(&x) .checked_div(&BigRational::from(&y)) .map(|q| Rational::from(&q)), quotient ); }); rational_gen().test_properties(|ref x| { assert_eq!(x.checked_div(Rational::ZERO), None); assert_eq!(x.checked_div(Rational::ONE), Some(x.clone())); assert_eq!(x.checked_div(Rational::NEGATIVE_ONE), Some(-x)); }); rational_gen_var_1().test_properties(|ref x| { assert_eq!(Rational::ZERO.checked_div(x), Some(Rational::ZERO)); assert_eq!(Rational::ONE.checked_div(x), Some(x.reciprocal())); assert_eq!(Rational::NEGATIVE_ONE.checked_div(x), Some(-x.reciprocal())); assert_eq!(x.checked_div(x), Some(Rational::ONE)); }); } ================================================ FILE: malachite-q/tests/arithmetic/floor.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, Floor, FloorAssign}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::BigRational; use std::str::FromStr; #[test] fn test_floor() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); let floor = x.clone().floor(); assert!(floor.is_valid()); assert_eq!(floor.to_string(), out); let floor = (&x).floor(); assert!(floor.is_valid()); assert_eq!(floor.to_string(), out); assert_eq!(BigRational::from_str(s).unwrap().floor().to_string(), out); assert_eq!(rug::Rational::from_str(s).unwrap().floor().to_string(), out); let mut x = x; x.floor_assign(); assert!(floor.is_valid()); assert_eq!(x.to_string(), out); }; test("1", "1"); test("-1", "-1"); test("123", "123"); test("22/7", "3"); test("-22/7", "-4"); test("936851431250/1397", "670616629"); } #[test] fn floor_properties() { rational_gen().test_properties(|x| { let floor = x.clone().floor(); assert!(floor.is_valid()); assert_eq!(Rational::from(&BigRational::from(&x).floor()), floor); assert_eq!(Rational::from(&rug::Rational::from(&x).floor()), floor); let floor_alt = (&x).floor(); assert!(floor_alt.is_valid()); assert_eq!(floor_alt, floor); let mut floor_alt = x.clone(); floor_alt.floor_assign(); assert!(floor_alt.is_valid()); assert_eq!(floor_alt, floor); assert_eq!(Integer::rounding_from(&x, Floor).0, floor); assert!(floor <= x); assert!(&floor + Integer::ONE > x); assert_eq!(floor, Rational::from(&floor).floor()); assert_eq!(floor, -(-x).ceiling()); }); } ================================================ FILE: malachite-q/tests/arithmetic/is_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase2, IsPowerOf2, NextPowerOf2, Reciprocal, }; use malachite_nz::test_util::generators::natural_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_gen_var_1, rational_gen_var_2}; use std::str::FromStr; #[test] fn test_is_power_of_2() { let test = |x, out| { assert_eq!(Rational::from_str(x).unwrap().is_power_of_2(), out); }; test("0", false); test("1", true); test("2", true); test("3", false); test("4", true); test("5", false); test("6", false); test("7", false); test("8", true); test("1024", true); test("1025", false); test("1000000000000", false); test("1099511627776", true); test("1/2", true); test("1/3", false); test("1/4", true); test("1/5", false); test("1/6", false); test("1/7", false); test("1/8", true); test("1/1024", true); test("1/1025", false); test("1/1000000000000", false); test("1/1099511627776", true); test("22/7", false); test("-1", false); } #[test] fn is_power_of_2_properties() { rational_gen().test_properties(|x| { if x.is_power_of_2() { assert!(x >= 0u32); } }); rational_gen_var_2().test_properties(|x| { let is_power = x.is_power_of_2(); assert_eq!((&x).next_power_of_2() == x, is_power); assert_eq!(x.checked_log_base_2().is_some(), is_power); }); rational_gen_var_1().test_properties(|x| { assert_eq!((&x).reciprocal().is_power_of_2(), x.is_power_of_2()); }); natural_gen().test_properties(|x| { assert_eq!(x.is_power_of_2(), Rational::from(x).is_power_of_2()); }); } ================================================ FILE: malachite-q/tests/arithmetic/log_base.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBase2, CheckedLogBase, CheckedLogBase2, FloorLogBase, FloorLogBase2, Pow, }; use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::num::float::NiceFloat; use malachite_nz::test_util::generators::natural_pair_gen_var_3; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen_var_2, rational_gen_var_8, rational_pair_gen_var_7, }; use std::str::FromStr; #[test] fn test_approx_log() { let test = |s, out| { assert_eq!( NiceFloat(Rational::from_str(s).unwrap().approx_log()), NiceFloat(out) ); }; test("1", 0.0); test("2", std::f64::consts::LN_2); test("3", 1.0986122886681096); test("10", 2.3025850929940455); test("100", 4.605170185988091); test("1000", 6.907755278982137); test( "1000000000000000000000000000000000000000000000000000000000000", 138.15510557964274, ); test("1/2", -std::f64::consts::LN_2); test("1/3", -1.0986122886681098); test("22/7", 1.1451323043030026); test("936851431250/1397", 20.323708189458696); } #[test] #[should_panic] fn approx_log_fail() { Rational::ZERO.approx_log(); } #[test] fn test_floor_log_base() { let test = |n, base, out| { assert_eq!( Rational::from_str(n) .unwrap() .floor_log_base(&Rational::from_str(base).unwrap()), out ); }; test("1", "2", 0); test("1", "5", 0); test("2", "2", 1); test("2", "3", 0); test("3", "2", 1); test("3", "3", 1); test("3", "4", 0); test("100", "2", 6); test("100", "3", 4); test("100", "4", 3); test("100", "5", 2); test("100", "10", 2); test("100", "11", 1); test( "999999999999999999999999999999999999999999999999999999999999", "10", 59, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", 60, ); test("1/2", "2", -1); test("1/3", "2", -2); test("1/2", "3", -1); test("1/3", "3", -1); test("22/7", "3", 1); test("1/64", "4", -3); test("22/7", "10", 0); test("936851431250/1397", "10", 8); test("1/2", "1/2", 1); test("1/3", "1/2", 1); test("1/2", "1/3", 0); test("1/3", "1/3", 1); test("22/7", "1/3", -2); test("1/64", "1/4", 3); test("22/7", "1/10", -1); test("936851431250/1397", "1/10", -9); test("936851431250/1397", "22/7", 17); test("100", "101/100", 462); test("100", "100/101", -463); test("5153632/16807", "22/7", 5); } #[test] #[should_panic] fn floor_log_base_fail_1() { Rational::ZERO.floor_log_base(&Rational::TWO); } #[test] #[should_panic] fn floor_log_base_fail_2() { Rational::ONE.floor_log_base(&Rational::ZERO); } #[test] #[should_panic] fn floor_log_base_fail_3() { Rational::ONE.floor_log_base(&Rational::ONE); } #[test] #[should_panic] fn floor_log_base_fail_4() { Rational::NEGATIVE_ONE.floor_log_base(&Rational::TWO); } #[test] fn test_ceiling_log_base() { let test = |n, base, out| { assert_eq!( Rational::from_str(n) .unwrap() .ceiling_log_base(&Rational::from_str(base).unwrap()), out ); }; test("1", "2", 0); test("1", "5", 0); test("2", "2", 1); test("2", "3", 1); test("3", "2", 2); test("3", "3", 1); test("3", "4", 1); test("100", "2", 7); test("100", "3", 5); test("100", "4", 4); test("100", "5", 3); test("100", "10", 2); test("100", "11", 2); test( "999999999999999999999999999999999999999999999999999999999999", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", 60, ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", 61, ); test("1/2", "2", -1); test("1/3", "2", -1); test("1/2", "3", 0); test("1/3", "3", -1); test("22/7", "3", 2); test("1/64", "4", -3); test("22/7", "10", 1); test("936851431250/1397", "10", 9); test("1/2", "1/2", 1); test("1/3", "1/2", 2); test("1/2", "1/3", 1); test("1/3", "1/3", 1); test("22/7", "1/3", -1); test("1/64", "1/4", 3); test("22/7", "1/10", 0); test("936851431250/1397", "1/10", -8); test("936851431250/1397", "22/7", 18); test("100", "101/100", 463); test("100", "100/101", -462); test("5153632/16807", "22/7", 5); } #[test] #[should_panic] fn ceiling_log_base_fail_1() { Rational::ZERO.ceiling_log_base(&Rational::TWO); } #[test] #[should_panic] fn ceiling_log_base_fail_2() { Rational::ONE.ceiling_log_base(&Rational::ZERO); } #[test] #[should_panic] fn ceiling_log_base_fail_3() { Rational::ONE.ceiling_log_base(&Rational::ONE); } #[test] #[should_panic] fn ceiling_log_base_fail_4() { Rational::NEGATIVE_ONE.ceiling_log_base(&Rational::TWO); } #[test] fn test_checked_log_base() { let test = |n, base, out| { assert_eq!( Rational::from_str(n) .unwrap() .checked_log_base(&Rational::from_str(base).unwrap()), out ); }; test("1", "2", Some(0)); test("1", "5", Some(0)); test("2", "2", Some(1)); test("2", "3", None); test("3", "2", None); test("3", "3", Some(1)); test("3", "4", None); test("100", "2", None); test("100", "3", None); test("100", "4", None); test("100", "5", None); test("100", "10", Some(2)); test("100", "11", None); test( "999999999999999999999999999999999999999999999999999999999999", "10", None, ); test( "1000000000000000000000000000000000000000000000000000000000000", "10", Some(60), ); test( "1000000000000000000000000000000000000000000000000000000000001", "10", None, ); test("1/2", "2", Some(-1)); test("1/3", "2", None); test("1/2", "3", None); test("1/3", "3", Some(-1)); test("22/7", "3", None); test("1/64", "4", Some(-3)); test("22/7", "10", None); test("936851431250/1397", "10", None); test("1/2", "1/2", Some(1)); test("1/3", "1/2", None); test("1/2", "1/3", None); test("1/3", "1/3", Some(1)); test("22/7", "1/3", None); test("1/64", "1/4", Some(3)); test("22/7", "1/10", None); test("936851431250/1397", "1/10", None); test("936851431250/1397", "22/7", None); test("100", "101/100", None); test("100", "100/101", None); test("5153632/16807", "22/7", Some(5)); } #[test] #[should_panic] fn checked_log_base_fail_1() { Rational::ZERO.checked_log_base(&Rational::TWO); } #[test] #[should_panic] fn checked_log_base_fail_2() { Rational::ONE.checked_log_base(&Rational::ZERO); } #[test] #[should_panic] fn checked_log_base_fail_3() { Rational::ONE.checked_log_base(&Rational::ONE); } #[test] #[should_panic] fn checked_log_base_fail_4() { Rational::NEGATIVE_ONE.checked_log_base(&Rational::TWO); } #[test] fn approx_log_properties() { rational_gen_var_2().test_properties(|n| { let log = n.approx_log(); assert!(log.is_finite()); assert!(!log.is_nan()); }); } #[test] fn floor_log_base_properties() { rational_pair_gen_var_7().test_properties(|(n, base)| { let floor_log = n.floor_log_base(&base); let power = (&base).pow(floor_log); if base >= 1u32 { assert!(power <= n); assert!(&power * &base > n); } else { assert!(power >= n); assert!(&power * &base < n); } let ceiling_log = n.ceiling_log_base(&base); if power == n { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.floor_log_base(&Rational::TWO), n.floor_log_base_2()); }); rational_gen_var_8().test_properties(|base| { assert_eq!(Rational::ONE.floor_log_base(&base), 0); }); natural_pair_gen_var_3().test_properties(|(n, base)| { assert_eq!( n.floor_log_base(&base), u64::exact_from(Rational::from(n).floor_log_base(&Rational::from(base))) ); }); } #[test] fn ceiling_log_base_properties() { rational_pair_gen_var_7().test_properties(|(n, base)| { let ceiling_log = n.ceiling_log_base(&base); let power = (&base).pow(ceiling_log); if base >= 1u32 { assert!(power >= n); assert!(&power / &base < n); } else { assert!(power <= n); assert!(&power / &base > n); } let floor_log = n.floor_log_base(&base); if power == n { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.ceiling_log_base(&Rational::TWO), n.ceiling_log_base_2()); }); rational_gen_var_8().test_properties(|base| { assert_eq!(Rational::ONE.ceiling_log_base(&base), 0); }); natural_pair_gen_var_3().test_properties(|(n, base)| { assert_eq!( n.ceiling_log_base(&base), u64::exact_from(Rational::from(n).ceiling_log_base(&Rational::from(base))) ); }); } #[test] fn checked_log_base_properties() { rational_pair_gen_var_7().test_properties(|(n, base)| { let checked_log = n.checked_log_base(&base); if let Some(log) = checked_log { assert_eq!((&base).pow(log), n); assert_eq!(n.floor_log_base(&base), log); assert_eq!(n.ceiling_log_base(&base), log); } }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.checked_log_base(&Rational::TWO), n.checked_log_base_2()); }); rational_gen_var_8().test_properties(|base| { assert_eq!(Rational::ONE.checked_log_base(&base), Some(0)); }); natural_pair_gen_var_3().test_properties(|(n, base)| { assert_eq!( n.checked_log_base(&base), Rational::from(n) .checked_log_base(&Rational::from(base)) .map(u64::exact_from) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/log_base_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, CeilingLogBase2, CheckedLogBase2, FloorLogBase2, IsPowerOf2, PowerOf2, }; use malachite_base::num::basic::traits::{NegativeOne, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_nz::test_util::generators::natural_gen_var_2; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen_var_1, rational_gen_var_2}; use std::str::FromStr; #[test] fn test_floor_log_base_2_abs() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().floor_log_base_2_abs(), out); }; test("1", 0); test("100", 6); test("1000000000000", 39); test("4294967295", 31); test("4294967296", 32); test("4294967297", 32); test("22/7", 1); test("936851431250/1397", 29); test("1/1000000000000", -40); test("1/4294967295", -32); test("1/4294967296", -32); test("1/4294967297", -33); test("1/2", -1); test("1/3", -2); test("1/4", -2); test("1/5", -3); test("1/6", -3); test("1/7", -3); test("1/8", -3); test("1/9", -4); test("-1", 0); test("-100", 6); test("-1000000000000", 39); test("-4294967295", 31); test("-4294967296", 32); test("-4294967297", 32); test("-22/7", 1); test("-936851431250/1397", 29); test("-1/1000000000000", -40); test("-1/4294967295", -32); test("-1/4294967296", -32); test("-1/4294967297", -33); test("-1/2", -1); test("-1/3", -2); test("-1/4", -2); test("-1/5", -3); test("-1/6", -3); test("-1/7", -3); test("-1/8", -3); test("-1/9", -4); } #[test] #[should_panic] fn floor_log_base_2_abs_fail() { Rational::ZERO.floor_log_base_2_abs(); } #[test] fn test_ceiling_log_base_2_abs() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().ceiling_log_base_2_abs(), out); }; test("1", 0); test("100", 7); test("1000000000000", 40); test("4294967295", 32); test("4294967296", 32); test("4294967297", 33); test("22/7", 2); test("936851431250/1397", 30); test("1/1000000000000", -39); test("1/4294967295", -31); test("1/4294967296", -32); test("1/4294967297", -32); test("1/2", -1); test("1/3", -1); test("1/4", -2); test("1/5", -2); test("1/6", -2); test("1/7", -2); test("1/8", -3); test("1/9", -3); test("-1", 0); test("-100", 7); test("-1000000000000", 40); test("-4294967295", 32); test("-4294967296", 32); test("-4294967297", 33); test("-22/7", 2); test("-936851431250/1397", 30); test("-1/1000000000000", -39); test("-1/4294967295", -31); test("-1/4294967296", -32); test("-1/4294967297", -32); test("-1/2", -1); test("-1/3", -1); test("-1/4", -2); test("-1/5", -2); test("-1/6", -2); test("-1/7", -2); test("-1/8", -3); test("-1/9", -3); } #[test] #[should_panic] fn ceiling_log_base_2_abs_fail() { Rational::ZERO.ceiling_log_base_2_abs(); } #[test] fn test_floor_log_base_2() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().floor_log_base_2(), out); }; test("1", 0); test("100", 6); test("1000000000000", 39); test("4294967295", 31); test("4294967296", 32); test("4294967297", 32); test("22/7", 1); test("936851431250/1397", 29); test("1/1000000000000", -40); test("1/4294967295", -32); test("1/4294967296", -32); test("1/4294967297", -33); test("1/2", -1); test("1/3", -2); test("1/4", -2); test("1/5", -3); test("1/6", -3); test("1/7", -3); test("1/8", -3); test("1/9", -4); } #[test] #[should_panic] fn floor_log_base_2_fail_1() { Rational::ZERO.floor_log_base_2(); } #[test] #[should_panic] fn floor_log_base_2_fail_2() { Rational::NEGATIVE_ONE.floor_log_base_2(); } #[test] fn test_ceiling_log_base_2() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().ceiling_log_base_2(), out); }; test("1", 0); test("100", 7); test("1000000000000", 40); test("4294967295", 32); test("4294967296", 32); test("4294967297", 33); test("22/7", 2); test("936851431250/1397", 30); test("1/1000000000000", -39); test("1/4294967295", -31); test("1/4294967296", -32); test("1/4294967297", -32); test("1/2", -1); test("1/3", -1); test("1/4", -2); test("1/5", -2); test("1/6", -2); test("1/7", -2); test("1/8", -3); test("1/9", -3); } #[test] #[should_panic] fn ceiling_log_base_2_fail() { Rational::ZERO.ceiling_log_base_2(); } #[test] #[should_panic] fn ceiling_log_base_2_fail_2() { Rational::NEGATIVE_ONE.ceiling_log_base_2(); } #[test] fn test_checked_log_base_2() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().checked_log_base_2(), out); }; test("1", Some(0)); test("100", None); test("1000000000000", None); test("4294967295", None); test("4294967296", Some(32)); test("4294967297", None); test("22/7", None); test("936851431250/1397", None); test("1/1000000000000", None); test("1/4294967295", None); test("1/4294967296", Some(-32)); test("1/4294967297", None); test("1/2", Some(-1)); test("1/3", None); test("1/4", Some(-2)); test("1/5", None); test("1/6", None); test("1/7", None); test("1/8", Some(-3)); test("1/9", None); } #[test] #[should_panic] fn checked_log_base_2_fail() { Rational::ZERO.checked_log_base_2(); } #[test] fn floor_log_base_2_abs_properties() { rational_gen_var_1().test_properties(|x| { let floor_log_base_2 = x.floor_log_base_2_abs(); assert_eq!((&x).abs().floor_log_base_2(), floor_log_base_2); assert!(Rational::power_of_2(floor_log_base_2).le_abs(&x)); assert!(x.lt_abs(&Rational::power_of_2(floor_log_base_2 + 1))); }); } #[test] fn ceiling_log_base_2_abs_properties() { rational_gen_var_1().test_properties(|x| { let ceiling_log_base_2 = x.ceiling_log_base_2_abs(); assert_eq!((&x).abs().ceiling_log_base_2(), ceiling_log_base_2); assert!(Rational::power_of_2(ceiling_log_base_2 - 1).lt_abs(&x)); assert!(x.le_abs(&Rational::power_of_2(ceiling_log_base_2))); }); } #[test] fn floor_log_base_2_properties() { rational_gen_var_2().test_properties(|x| { let floor_log_base_2 = x.floor_log_base_2(); assert!(Rational::power_of_2(floor_log_base_2) <= x); assert!(x < Rational::power_of_2(floor_log_base_2 + 1)); }); natural_gen_var_2().test_properties(|n| { assert_eq!( i64::exact_from((&n).floor_log_base_2()), Rational::from(n).floor_log_base_2() ); }); } #[test] fn ceiling_log_base_2_properties() { rational_gen_var_2().test_properties(|x| { let ceiling_log_base_2 = x.ceiling_log_base_2(); assert!(Rational::power_of_2(ceiling_log_base_2 - 1) < x); assert!(x <= Rational::power_of_2(ceiling_log_base_2)); }); natural_gen_var_2().test_properties(|n| { assert_eq!( i64::exact_from((&n).ceiling_log_base_2()), Rational::from(n).ceiling_log_base_2() ); }); } #[test] fn checked_log_base_2_properties() { rational_gen_var_2().test_properties(|x| { let checked_log_base_2 = x.checked_log_base_2(); assert_eq!(checked_log_base_2.is_some(), x.is_power_of_2()); if let Some(log_base_2) = checked_log_base_2 { assert_eq!(x.floor_log_base_2(), log_base_2); assert_eq!(x.ceiling_log_base_2(), log_base_2); assert_eq!(Rational::power_of_2(log_base_2), x); } }); natural_gen_var_2().test_properties(|n| { assert_eq!( (&n).checked_log_base_2().map(i64::exact_from), Rational::from(n).checked_log_base_2() ); }); } ================================================ FILE: malachite-q/tests/arithmetic/log_base_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase, CeilingLogBase2, CeilingLogBasePowerOf2, CheckedLogBase, CheckedLogBase2, CheckedLogBasePowerOf2, DivisibleBy, FloorLogBase, FloorLogBase2, FloorLogBasePowerOf2, IsPowerOf2, PowerOf2, Reciprocal, }; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::signed_gen_var_12; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_8; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen_var_2, rational_signed_pair_gen_var_5}; use std::str::FromStr; #[test] fn test_floor_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Rational::from_str(n) .unwrap() .floor_log_base_power_of_2(pow), out ); }; test("1", 1, 0); test("1", 2, 0); test("1", 5, 0); test("100", 1, 6); test("100", 2, 3); test("100", 5, 1); test("1000000000000", 1, 39); test("1000000000000", 2, 19); test("1000000000000", 5, 7); test("1000000000000", 5, 7); test("1", -1, 0); test("1", -2, 0); test("1", -5, 0); test("100", -1, -7); test("100", -2, -4); test("100", -5, -2); test("1000000000000", -1, -40); test("1000000000000", -2, -20); test("1000000000000", -5, -8); test("1000000000000", -5, -8); test("1/2", 1, -1); test("1/3", 1, -2); test("1/4", 1, -2); test("1/5", 1, -3); test("1/6", 1, -3); test("1/7", 1, -3); test("1/8", 1, -3); test("1/9", 1, -4); test("1/2", 2, -1); test("1/3", 2, -1); test("1/4", 2, -1); test("1/5", 2, -2); test("1/6", 2, -2); test("1/7", 2, -2); test("1/8", 2, -2); test("1/9", 2, -2); test("1/2", -1, 1); test("1/3", -1, 1); test("1/4", -1, 2); test("1/5", -1, 2); test("1/6", -1, 2); test("1/7", -1, 2); test("1/8", -1, 3); test("1/9", -1, 3); test("1/2", -2, 0); test("1/3", -2, 0); test("1/4", -2, 1); test("1/5", -2, 1); test("1/6", -2, 1); test("1/7", -2, 1); test("1/8", -2, 1); test("1/9", -2, 1); } #[test] #[should_panic] fn floor_log_base_power_of_2_fail_1() { Rational::ZERO.floor_log_base_power_of_2(1); } #[test] #[should_panic] fn floor_log_base_power_of_2_fail_2() { Rational::ONE.floor_log_base_power_of_2(0); } #[test] #[should_panic] fn floor_log_base_power_of_2_fail_3() { Rational::NEGATIVE_ONE.floor_log_base_power_of_2(1); } #[test] fn test_ceiling_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Rational::from_str(n) .unwrap() .ceiling_log_base_power_of_2(pow), out ); }; test("1", 1, 0); test("1", 2, 0); test("1", 5, 0); test("100", 1, 7); test("100", 2, 4); test("100", 5, 2); test("1000000000000", 1, 40); test("1000000000000", 2, 20); test("1000000000000", 5, 8); test("1000000000000", 5, 8); test("1", -1, 0); test("1", -2, 0); test("1", -5, 0); test("100", -1, -6); test("100", -2, -3); test("100", -5, -1); test("1000000000000", -1, -39); test("1000000000000", -2, -19); test("1000000000000", -5, -7); test("1000000000000", -5, -7); test("1/2", 1, -1); test("1/3", 1, -1); test("1/4", 1, -2); test("1/5", 1, -2); test("1/6", 1, -2); test("1/7", 1, -2); test("1/8", 1, -3); test("1/9", 1, -3); test("1/2", 2, 0); test("1/3", 2, 0); test("1/4", 2, -1); test("1/5", 2, -1); test("1/6", 2, -1); test("1/7", 2, -1); test("1/8", 2, -1); test("1/9", 2, -1); test("1/2", -1, 1); test("1/3", -1, 2); test("1/4", -1, 2); test("1/5", -1, 3); test("1/6", -1, 3); test("1/7", -1, 3); test("1/8", -1, 3); test("1/9", -1, 4); test("1/2", -2, 1); test("1/3", -2, 1); test("1/4", -2, 1); test("1/5", -2, 2); test("1/6", -2, 2); test("1/7", -2, 2); test("1/8", -2, 2); test("1/9", -2, 2); } #[test] #[should_panic] fn ceiling_log_base_power_of_2_fail_1() { Rational::ZERO.ceiling_log_base_power_of_2(1); } #[test] #[should_panic] fn ceiling_log_base_power_of_2_fail_2() { Rational::ONE.ceiling_log_base_power_of_2(0); } #[test] #[should_panic] fn ceiling_log_base_power_of_2_fail_3() { Rational::NEGATIVE_ONE.ceiling_log_base_power_of_2(1); } #[test] fn test_checked_log_base_power_of_2() { let test = |n, pow, out| { assert_eq!( Rational::from_str(n) .unwrap() .checked_log_base_power_of_2(pow), out ); }; test("1", 1, Some(0)); test("1", 2, Some(0)); test("1", 5, Some(0)); test("100", 1, None); test("100", 2, None); test("100", 5, None); test("1000000000000", 1, None); test("1000000000000", 2, None); test("1000000000000", 5, None); test("1000000000000", 5, None); test("1", -1, Some(0)); test("1", -2, Some(0)); test("1", -5, Some(0)); test("100", -1, None); test("100", -2, None); test("100", -5, None); test("1000000000000", -1, None); test("1000000000000", -2, None); test("1000000000000", -5, None); test("1000000000000", -5, None); test("1/2", 1, Some(-1)); test("1/3", 1, None); test("1/4", 1, Some(-2)); test("1/5", 1, None); test("1/6", 1, None); test("1/7", 1, None); test("1/8", 1, Some(-3)); test("1/9", 1, None); test("1/2", 2, None); test("1/3", 2, None); test("1/4", 2, Some(-1)); test("1/5", 2, None); test("1/6", 2, None); test("1/7", 2, None); test("1/8", 2, None); test("1/9", 2, None); test("1/2", -1, Some(1)); test("1/3", -1, None); test("1/4", -1, Some(2)); test("1/5", -1, None); test("1/6", -1, None); test("1/7", -1, None); test("1/8", -1, Some(3)); test("1/9", -1, None); test("1/2", -2, None); test("1/3", -2, None); test("1/4", -2, Some(1)); test("1/5", -2, None); test("1/6", -2, None); test("1/7", -2, None); test("1/8", -2, None); test("1/9", -2, None); } #[test] #[should_panic] fn checked_log_base_power_of_2_fail_1() { Rational::ZERO.checked_log_base_power_of_2(1); } #[test] #[should_panic] fn checked_log_base_power_of_2_fail_2() { Rational::ONE.checked_log_base_power_of_2(0); } #[test] #[should_panic] fn checked_log_base_power_of_2_fail_3() { Rational::NEGATIVE_ONE.checked_log_base_power_of_2(1); } #[test] fn floor_log_base_power_of_2_properties() { rational_signed_pair_gen_var_5().test_properties(|(n, pow)| { let floor_log = n.floor_log_base_power_of_2(pow); assert_eq!(n.floor_log_base(&Rational::power_of_2(pow)), floor_log); let product = floor_log * pow; if pow >= 0 { assert!(Rational::power_of_2(product) <= n); assert!(Rational::power_of_2(product + pow) > n); } else { assert!(Rational::power_of_2(product) >= n); assert!(Rational::power_of_2(product + pow) < n); } let ceiling_log = n.ceiling_log_base_power_of_2(pow); if n.is_power_of_2() && n.checked_log_base_2().unwrap().divisible_by(pow) { assert_eq!(ceiling_log, floor_log); } else { assert_eq!(ceiling_log, floor_log + 1); } assert_eq!(n.floor_log_base_power_of_2(-pow), -ceiling_log); assert_eq!(n.reciprocal().floor_log_base_power_of_2(pow), -ceiling_log); }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.floor_log_base_power_of_2(1), n.floor_log_base_2()); }); signed_gen_var_12().test_properties(|pow| { assert_eq!(Rational::ONE.floor_log_base_power_of_2(pow), 0); }); natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { assert_eq!( i64::exact_from(n.floor_log_base_power_of_2(pow)), Rational::from(n).floor_log_base_power_of_2(i64::exact_from(pow)) ); }); } #[test] fn ceiling_log_base_power_of_2_properties() { rational_signed_pair_gen_var_5().test_properties(|(n, pow)| { let ceiling_log = n.ceiling_log_base_power_of_2(pow); assert_eq!(n.ceiling_log_base(&Rational::power_of_2(pow)), ceiling_log); let product = ceiling_log * pow; if pow >= 0 { assert!(Rational::power_of_2(product) >= n); assert!(Rational::power_of_2(product - pow) < n); } else { assert!(Rational::power_of_2(product) <= n); assert!(Rational::power_of_2(product - pow) > n); } let floor_log = n.floor_log_base_power_of_2(pow); if n.is_power_of_2() && n.checked_log_base_2().unwrap().divisible_by(pow) { assert_eq!(floor_log, ceiling_log); } else { assert_eq!(floor_log, ceiling_log - 1); } assert_eq!(n.ceiling_log_base_power_of_2(-pow), -floor_log); assert_eq!(n.reciprocal().ceiling_log_base_power_of_2(pow), -floor_log); }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.ceiling_log_base_power_of_2(1), n.ceiling_log_base_2()); }); signed_gen_var_12().test_properties(|pow| { assert_eq!(Rational::ONE.ceiling_log_base_power_of_2(pow), 0); }); natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { assert_eq!( i64::exact_from(n.ceiling_log_base_power_of_2(pow)), Rational::from(n).ceiling_log_base_power_of_2(i64::exact_from(pow)) ); }); } #[test] fn checked_log_base_power_of_2_properties() { rational_signed_pair_gen_var_5().test_properties(|(n, pow)| { let checked_log = n.checked_log_base_power_of_2(pow); assert_eq!(n.checked_log_base(&Rational::power_of_2(pow)), checked_log); assert_eq!( checked_log.is_some(), n.is_power_of_2() && n.checked_log_base_2().unwrap().divisible_by(pow) ); if let Some(log) = checked_log { assert_eq!(Rational::power_of_2(log * pow), n); assert_eq!(log == 0, n == Rational::ONE); assert_eq!(n.floor_log_base_power_of_2(pow), log); assert_eq!(n.ceiling_log_base_power_of_2(pow), log); assert_eq!(n.checked_log_base_power_of_2(-pow), Some(-log)); assert_eq!(n.reciprocal().checked_log_base_power_of_2(pow), Some(-log)); } }); rational_gen_var_2().test_properties(|n| { assert_eq!(n.checked_log_base_power_of_2(1), n.checked_log_base_2()); }); signed_gen_var_12().test_properties(|pow| { assert_eq!(Rational::ONE.checked_log_base_power_of_2(pow), Some(0)); }); natural_unsigned_pair_gen_var_8().test_properties(|(n, pow)| { assert_eq!( n.checked_log_base_power_of_2(pow).map(i64::exact_from), Rational::from(n).checked_log_base_power_of_2(i64::exact_from(pow)) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/mod_op.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingMod, CeilingModAssign, Mod, ModAssign, NegMod, }; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_nz::test_util::generators::{integer_pair_gen_var_1, natural_pair_gen_var_5}; use malachite_q::Rational; use malachite_q::test_util::arithmetic::mod_op::{ceiling_mod_naive, mod_op_naive, rem_naive}; use malachite_q::test_util::generators::{rational_gen_var_1, rational_pair_gen_var_1}; use num::BigRational; use std::str::FromStr; #[test] fn test_mod() { let test = |s, t, remainder| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut x = u.clone(); x.mod_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).mod_op(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = mod_op_naive(u, v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "123"); test("456", "123", "87"); test("4/3", "1", "1/3"); test("22/7", "1/2", "1/7"); test("10", "22/7", "4/7"); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "-333"); test("456", "-123", "-36"); test("4/3", "-1", "-2/3"); test("22/7", "-1/2", "-5/14"); test("10", "-22/7", "-18/7"); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "333"); test("-456", "123", "36"); test("-4/3", "1", "2/3"); test("-22/7", "1/2", "5/14"); test("-10", "22/7", "18/7"); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "-123"); test("-456", "-123", "-87"); test("-4/3", "-1", "-1/3"); test("-22/7", "-1/2", "-1/7"); test("-10", "-22/7", "-4/7"); } #[test] #[should_panic] fn mod_assign_fail() { Rational::from(10).mod_assign(Rational::ZERO); } #[test] #[should_panic] fn mod_assign_ref_fail() { Rational::from(10).mod_assign(&Rational::ZERO); } #[test] #[should_panic] fn mod_fail() { Rational::from(10).mod_op(Rational::ZERO); } #[test] #[should_panic] fn mod_val_ref_fail() { Rational::from(10).mod_op(&Rational::ZERO); } #[test] #[should_panic] fn mod_ref_val_fail() { (&Rational::from(10)).mod_op(Rational::ZERO); } #[test] #[should_panic] fn mod_ref_ref_fail() { (&Rational::from(10)).mod_op(&Rational::ZERO); } #[test] fn test_rem() { let test = |s, t, remainder| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut x = u.clone(); x %= v.clone(); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x %= &v; assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone() % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone() % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % v.clone(); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = &u % &v; assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = rem_naive(u, v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = BigRational::from_str(s).unwrap() % &BigRational::from_str(t).unwrap(); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "123"); test("456", "123", "87"); test("4/3", "1", "1/3"); test("22/7", "1/2", "1/7"); test("10", "22/7", "4/7"); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "123"); test("456", "-123", "87"); test("4/3", "-1", "1/3"); test("22/7", "-1/2", "1/7"); test("10", "-22/7", "4/7"); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "-123"); test("-456", "123", "-87"); test("-4/3", "1", "-1/3"); test("-22/7", "1/2", "-1/7"); test("-10", "22/7", "-4/7"); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "-123"); test("-456", "-123", "-87"); test("-4/3", "-1", "-1/3"); test("-22/7", "-1/2", "-1/7"); test("-10", "-22/7", "-4/7"); } #[test] #[should_panic] fn rem_assign_fail() { let mut x = Rational::from(10); x %= Rational::ZERO; } #[test] #[should_panic] fn rem_assign_ref_fail() { let mut x = Rational::from(10); x %= &Rational::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_fail() { Rational::from(10) % Rational::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_val_ref_fail() { Rational::from(10) % &Rational::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_val_fail() { &Rational::from(10) % Rational::ZERO; } #[test] #[should_panic] #[allow(unused_must_use, clippy::unnecessary_operation)] fn rem_ref_ref_fail() { &Rational::from(10) % &Rational::ZERO; } #[test] fn test_ceiling_mod() { let test = |s, t, remainder| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut x = u.clone(); x.ceiling_mod_assign(v.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let mut x = u.clone(); x.ceiling_mod_assign(&v); assert!(x.is_valid()); assert_eq!(x.to_string(), remainder); let r = u.clone().ceiling_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = u.clone().ceiling_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).ceiling_mod(v.clone()); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = (&u).ceiling_mod(&v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); let r = ceiling_mod_naive(u, v); assert!(r.is_valid()); assert_eq!(r.to_string(), remainder); }; test("0", "1", "0"); test("0", "123", "0"); test("1", "1", "0"); test("123", "1", "0"); test("123", "123", "0"); test("123", "456", "-333"); test("456", "123", "-36"); test("4/3", "1", "-2/3"); test("22/7", "1/2", "-5/14"); test("10", "22/7", "-18/7"); test("0", "-1", "0"); test("0", "-123", "0"); test("1", "-1", "0"); test("123", "-1", "0"); test("123", "-123", "0"); test("123", "-456", "123"); test("456", "-123", "87"); test("4/3", "-1", "1/3"); test("22/7", "-1/2", "1/7"); test("10", "-22/7", "4/7"); test("-1", "1", "0"); test("-123", "1", "0"); test("-123", "123", "0"); test("-123", "456", "-123"); test("-456", "123", "-87"); test("-4/3", "1", "-1/3"); test("-22/7", "1/2", "-1/7"); test("-10", "22/7", "-4/7"); test("-1", "-1", "0"); test("-123", "-1", "0"); test("-123", "-123", "0"); test("-123", "-456", "333"); test("-456", "-123", "36"); test("-4/3", "-1", "2/3"); test("-22/7", "-1/2", "5/14"); test("-10", "-22/7", "18/7"); } #[test] #[should_panic] fn ceiling_mod_assign_fail() { Rational::from(10).ceiling_mod_assign(Rational::ZERO); } #[test] #[should_panic] fn ceiling_mod_assign_ref_fail() { Rational::from(10).ceiling_mod_assign(&Rational::ZERO); } #[test] #[should_panic] fn ceiling_mod_fail() { Rational::from(10).ceiling_mod(Rational::ZERO); } #[test] #[should_panic] fn ceiling_mod_val_ref_fail() { Rational::from(10).ceiling_mod(&Rational::ZERO); } #[test] #[should_panic] fn ceiling_mod_ref_val_fail() { (&Rational::from(10)).ceiling_mod(Rational::ZERO); } #[test] #[should_panic] fn ceiling_mod_ref_ref_fail() { (&Rational::from(10)).ceiling_mod(&Rational::ZERO); } fn mod_properties_helper(x: Rational, y: Rational) { let mut mut_x = x.clone(); mut_x.mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x.mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().mod_op(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = mod_op_naive(x.clone(), y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder > 0) == (y > 0)); assert_eq!((-&x).mod_op(&y), -(&x).ceiling_mod(&y)); assert_eq!((&x).mod_op(-&y), x.ceiling_mod(y)); } #[test] fn mod_properties() { rational_pair_gen_var_1().test_properties(|(x, y)| mod_properties_helper(x, y)); rational_gen_var_1().test_properties(|ref x| { assert_eq!(x.mod_op(x), 0); assert_eq!(x.mod_op(-x), 0); assert_eq!(Rational::ZERO.mod_op(x), 0); if *x > 1 { assert_eq!(Rational::ONE.mod_op(x), 1); assert_eq!(Rational::NEGATIVE_ONE.mod_op(x), x - Rational::ONE); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).mod_op(Rational::from(&y)), x.mod_op(y)); }); integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).mod_op(Rational::from(&y)), x.mod_op(y)); }); } fn rem_properties_helper(x: Rational, y: Rational) { let mut mut_x = x.clone(); mut_x %= &y; assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x %= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, remainder); let remainder_alt = &x % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = &x % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % &y; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone() % y.clone(); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = rem_naive(x.clone(), y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let num_remainder = BigRational::from(&x) % &BigRational::from(&y); assert_eq!(Rational::from(&num_remainder), remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder > 0) == (x > 0)); assert_eq!((-&x) % &y, -&remainder); assert_eq!(x % (-y), remainder); } #[test] fn rem_properties() { rational_pair_gen_var_1().test_properties(|(x, y)| rem_properties_helper(x, y)); rational_gen_var_1().test_properties(|ref x| { assert_eq!(x % x, 0); assert_eq!(x % -x, 0); assert_eq!(Rational::ZERO % x, 0); if *x > 1 { assert_eq!(Rational::ONE % x, 1); assert_eq!(Rational::NEGATIVE_ONE % x, -1); } }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) % Rational::from(&y), x % y); }); integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) % Rational::from(&y), x % y); }); } fn ceiling_mod_properties_helper(x: Rational, y: Rational) { let mut mut_x = x.clone(); mut_x.ceiling_mod_assign(&y); assert!(mut_x.is_valid()); let remainder = mut_x; let mut mut_x = x.clone(); mut_x.ceiling_mod_assign(y.clone()); let remainder_alt = mut_x; assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).ceiling_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = (&x).ceiling_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().ceiling_mod(&y); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = x.clone().ceiling_mod(y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); let remainder_alt = ceiling_mod_naive(x.clone(), y.clone()); assert!(remainder_alt.is_valid()); assert_eq!(remainder_alt, remainder); assert!(remainder.lt_abs(&y)); assert!(remainder == 0 || (remainder >= 0) != (y > 0)); assert_eq!((-&x).ceiling_mod(&y), -(&x).mod_op(&y)); assert_eq!((&x).ceiling_mod(-&y), x.mod_op(y)); } #[test] fn ceiling_mod_properties() { rational_pair_gen_var_1().test_properties(|(x, y)| ceiling_mod_properties_helper(x, y)); rational_gen_var_1().test_properties(|ref x| { assert_eq!(x.ceiling_mod(x), 0); assert_eq!(x.ceiling_mod(-x), 0); assert_eq!(Rational::ZERO.ceiling_mod(x), 0); }); natural_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!( Rational::from(&x).ceiling_mod(Rational::from(&y)), -x.neg_mod(y) ); }); integer_pair_gen_var_1().test_properties(|(x, y)| { assert_eq!( Rational::from(&x).ceiling_mod(Rational::from(&y)), x.ceiling_mod(y) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/mul.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Reciprocal, Square}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_nz::test_util::generators::integer_vec_gen; use malachite_q::Rational; use malachite_q::test_util::arithmetic::mul::mul_naive; use malachite_q::test_util::arithmetic::mul::rational_product_naive; use malachite_q::test_util::generators::{ rational_gen, rational_pair_gen, rational_triple_gen, rational_vec_gen, }; use num::BigRational; use std::iter::{Product, once}; use std::str::FromStr; #[test] fn test_mul() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); n *= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n *= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u * &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigRational::from_str(s).unwrap() * BigRational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() * rug::Rational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "123", "0"); test("0", "-123", "0"); test("123", "0", "0"); test("-123", "0", "0"); test("1", "123", "123"); test("1", "-123", "-123"); test("-1", "123", "-123"); test("-1", "-123", "123"); test("123", "1", "123"); test("123", "-1", "-123"); test("-123", "1", "-123"); test("-123", "-1", "123"); test("123", "456", "56088"); test("123", "-456", "-56088"); test("-123", "456", "-56088"); test("-123", "-456", "56088"); test("22/7", "3/2", "33/7"); test("22/7", "-3/2", "-33/7"); test("-22/7", "3/2", "-33/7"); test("-22/7", "-3/2", "33/7"); test("4/5", "5/4", "1"); test("4/5", "-5/4", "-1"); test("-4/5", "5/4", "-1"); test("-4/5", "-5/4", "1"); } #[test] fn test_product() { let test = |xs, out| { let xs = vec_from_str(xs).unwrap(); let product = Rational::product(xs.iter().cloned()); assert!(product.is_valid()); assert_eq!(product.to_string(), out); let product_alt = Rational::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = rational_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }; test("[]", "1"); test("[22/7]", "22/7"); test("[22/7, 1/3]", "22/21"); test("[0, 1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]", "0"); test("[1, 2/3, 3/4, 4/5, 5/6, 6/7, 7/8, 8/9, 9/10]", "1/5"); test( "[123456/78901, 34567/890123, 45678/90123]", "217314411648/7056278729357", ); } #[test] fn mul_properties() { rational_pair_gen().test_properties(|(x, y)| { let product_val_val = x.clone() * y.clone(); let product_val_ref = x.clone() * &y; let product_ref_val = &x * y.clone(); let product = &x * &y; assert!(product_val_val.is_valid()); assert!(product_val_ref.is_valid()); assert!(product_ref_val.is_valid()); assert!(product.is_valid()); assert_eq!(product_val_val, product); assert_eq!(product_val_ref, product); assert_eq!(product_ref_val, product); let mut mut_x = x.clone(); mut_x *= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, product); let mut mut_x = x.clone(); mut_x *= &y; assert_eq!(mut_x, product); assert!(mut_x.is_valid()); let mut mut_x = rug::Rational::from(&x); mut_x *= rug::Rational::from(&y); assert_eq!(Rational::from(&mut_x), product); assert_eq!( Rational::from(&(BigRational::from(&x) * BigRational::from(&y))), product ); assert_eq!( Rational::from(&(rug::Rational::from(&x) * rug::Rational::from(&y))), product ); assert_eq!(mul_naive(x.clone(), y.clone()), product); assert_eq!(&y * &x, product); if x != 0u32 { assert_eq!(&product / &x, y); } if y != 0u32 { assert_eq!(&product / &y, x); assert_eq!(&x / (&y).reciprocal(), product); } if product != 0u32 { assert_eq!( (&x).reciprocal() * (&y).reciprocal(), (&product).reciprocal() ); } assert_eq!(-&x * &y, -&product); assert_eq!(x * -y, -product); }); rational_gen().test_properties(|ref x| { assert_eq!(x * Rational::ZERO, 0); assert_eq!(Rational::ZERO * x, 0); assert_eq!(x * Rational::ONE, *x); assert_eq!(Rational::ONE * x, *x); assert_eq!(x * Rational::NEGATIVE_ONE, -x); assert_eq!(Rational::NEGATIVE_ONE * x, -x); assert_eq!(x * x, x.square()); }); rational_triple_gen().test_properties(|(ref x, ref y, ref z)| { assert_eq!((x * y) * z, x * (y * z)); assert_eq!(x * (y + z), x * y + x * z); assert_eq!((x + y) * z, x * z + y * z); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(&x * &y, Rational::from(x) * Rational::from(y)); }); } #[test] fn product_properties() { rational_vec_gen().test_properties(|xs| { let product = Rational::product(xs.iter().cloned()); assert!(product.is_valid()); let product_alt = Rational::product(xs.iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); let product_alt = rational_product_naive(xs.into_iter()); assert!(product_alt.is_valid()); assert_eq!(product_alt, product); }); rational_gen().test_properties(|x| { assert_eq!(Rational::product(once(&x)), x); assert_eq!(Rational::product(once(x.clone())), x); }); rational_pair_gen().test_properties(|(x, y)| { let product = &x * &y; assert_eq!(Rational::product([&x, &y].into_iter()), product); assert_eq!(Rational::product([x, y].into_iter()), product); }); integer_vec_gen().test_properties(|xs| { assert_eq!( Rational::product(xs.iter().map(Rational::from)), Rational::from(Integer::product(xs.into_iter())) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/neg.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::NegAssign; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::BigRational; use std::str::FromStr; #[test] fn test_neg() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); let neg = -x.clone(); assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); let neg = -&x; assert!(neg.is_valid()); assert_eq!(neg.to_string(), out); assert_eq!((-BigRational::from_str(s).unwrap()).to_string(), out); assert_eq!((-rug::Rational::from_str(s).unwrap()).to_string(), out); let mut x = x; x.neg_assign(); assert!(neg.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "0"); test("123", "-123"); test("-123", "123"); test("1000000000000", "-1000000000000"); test("-1000000000000", "1000000000000"); test("3000000000", "-3000000000"); test("-3000000000", "3000000000"); } #[test] fn abs_properties() { rational_gen().test_properties(|x| { let neg = -x.clone(); assert!(neg.is_valid()); assert_eq!(Rational::from(&-BigRational::from(&x)), neg); assert_eq!(Rational::from(&-rug::Rational::from(&x)), neg); let neg_alt = -&x; assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); let mut neg_alt = x.clone(); neg_alt.neg_assign(); assert!(neg_alt.is_valid()); assert_eq!(neg_alt, neg); assert_eq!(neg == x, x == 0); assert_eq!(-&neg, x); assert_eq!(x + neg, 0); }); integer_gen().test_properties(|x| { assert_eq!(-Rational::from(&x), Rational::from(-x)); }); } ================================================ FILE: malachite-q/tests/arithmetic/next_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CeilingLogBase2, IsPowerOf2, NextPowerOf2, NextPowerOf2Assign, PowerOf2, }; use malachite_base::num::basic::traits::Zero; use malachite_nz::test_util::generators::natural_gen_var_2; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen_var_2; use std::str::FromStr; #[test] fn test_next_power_of_2() { let test = |u, out| { let mut n = Rational::from_str(u).unwrap(); n.next_power_of_2_assign(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Rational::from_str(u).unwrap().next_power_of_2(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = (&Rational::from_str(u).unwrap()).next_power_of_2(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("1", "1"); test("2", "2"); test("3", "4"); test("4", "4"); test("5", "8"); test("6", "8"); test("7", "8"); test("8", "8"); test("9", "16"); test("10", "16"); test("123", "128"); test("1000", "1024"); test("1000000", "1048576"); test("1000000000", "1073741824"); test("1000000000000", "1099511627776"); test("2/3", "1"); test("22/7", "4"); test("1/10", "1/8"); test("1/100", "1/64"); test("1/1000000", "1/524288"); } #[test] #[should_panic] fn next_power_of_2_fail() { Rational::ZERO.next_power_of_2(); } #[test] #[should_panic] fn next_power_of_2_ref_fail() { (&Rational::ZERO).next_power_of_2(); } #[test] #[should_panic] fn next_power_of_2_assign_fail() { let mut x = Rational::ZERO; x.next_power_of_2_assign(); } #[test] fn next_power_of_2_properties() { rational_gen_var_2().test_properties(|x| { let mut mut_x = x.clone(); mut_x.next_power_of_2_assign(); assert!(mut_x.is_valid()); let result = mut_x; let result_alt = (&x).next_power_of_2(); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); let result_alt = x.clone().next_power_of_2(); assert!(result_alt.is_valid()); assert_eq!(result_alt, result); assert!(result.is_power_of_2()); assert!(result >= x); assert!(&result >> 1 < x); assert_eq!(Rational::power_of_2(x.ceiling_log_base_2()), result); }); natural_gen_var_2().test_properties(|x| { assert_eq!((&x).next_power_of_2(), Rational::from(x).next_power_of_2()); }); } ================================================ FILE: malachite-q/tests/arithmetic/pow.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedRoot, Parity, Pow, PowAssign, PowerOf2, Reciprocal, Square, }; use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen_var_5, unsigned_gen_var_5}; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_2; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_1, rational_rational_signed_triple_gen_var_1, rational_rational_unsigned_triple_gen_var_1, rational_signed_pair_gen_var_2, rational_signed_signed_triple_gen_var_1, rational_unsigned_pair_gen_var_1, rational_unsigned_unsigned_triple_gen_var_1, }; use num::BigRational; use num::traits::Pow as NumPow; use rug::ops::Pow as RugPow; use std::str::FromStr; #[test] fn test_pow() { let test = |s, exp: u64, out| { let u = Rational::from_str(s).unwrap(); let mut x = u.clone(); x.pow_assign(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = u.clone().pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = (&u).pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = BigRational::from_str(s).unwrap().pow(exp); assert_eq!(x.to_string(), out); let x = rug::Rational::from_str(s) .unwrap() .pow(u32::exact_from(exp)); assert_eq!(x.to_string(), out); }; test("0", 0, "1"); test("1", 0, "1"); test("2", 0, "1"); test("1000", 0, "1"); test("1000000000000", 0, "1"); test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("1000", 1, "1000"); test("1000000000000", 1, "1000000000000"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "4"); test("3", 2, "9"); test("1000", 2, "1000000"); test("1000000000000", 2, "1000000000000000000000000"); test("1/2", 0, "1"); test("1/2", 1, "1/2"); test("1/2", 2, "1/4"); test("1/2", 3, "1/8"); test("22/7", 0, "1"); test("22/7", 1, "22/7"); test("22/7", 2, "484/49"); test("22/7", 3, "10648/343"); test("-1", 0, "1"); test("-2", 0, "1"); test("-1000", 0, "1"); test("-1000000000000", 0, "1"); test("-1", 1, "-1"); test("-2", 1, "-2"); test("-1000", 1, "-1000"); test("-1000000000000", 1, "-1000000000000"); test("-1", 2, "1"); test("-2", 2, "4"); test("-3", 2, "9"); test("-1000", 2, "1000000"); test("-1000000000000", 2, "1000000000000000000000000"); test("-1/2", 0, "1"); test("-1/2", 1, "-1/2"); test("-1/2", 2, "1/4"); test("-1/2", 3, "-1/8"); test("-22/7", 0, "1"); test("-22/7", 1, "-22/7"); test("-22/7", 2, "484/49"); test("-22/7", 3, "-10648/343"); let test = |s, exp: i64, out| { let u = Rational::from_str(s).unwrap(); let mut x = u.clone(); x.pow_assign(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = u.clone().pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = (&u).pow(exp); assert_eq!(x.to_string(), out); assert!(x.is_valid()); let x = BigRational::from_str(s).unwrap().pow(exp); assert_eq!(x.to_string(), out); let x = rug::Rational::from_str(s) .unwrap() .pow(i32::exact_from(exp)); assert_eq!(x.to_string(), out); }; test("0", 0, "1"); test("1", 0, "1"); test("2", 0, "1"); test("1000", 0, "1"); test("1000000000000", 0, "1"); test("0", 1, "0"); test("1", 1, "1"); test("2", 1, "2"); test("1000", 1, "1000"); test("1000000000000", 1, "1000000000000"); test("0", 2, "0"); test("1", 2, "1"); test("2", 2, "4"); test("3", 2, "9"); test("1000", 2, "1000000"); test("1000000000000", 2, "1000000000000000000000000"); test("1/2", 0, "1"); test("1/2", 1, "1/2"); test("1/2", 2, "1/4"); test("1/2", 3, "1/8"); test("22/7", 0, "1"); test("22/7", 1, "22/7"); test("22/7", 2, "484/49"); test("22/7", 3, "10648/343"); test("1", -1, "1"); test("2", -1, "1/2"); test("1000", -1, "1/1000"); test("1000000000000", -1, "1/1000000000000"); test("1", -2, "1"); test("2", -2, "1/4"); test("3", -2, "1/9"); test("1000", -2, "1/1000000"); test("1000000000000", -2, "1/1000000000000000000000000"); test("1/2", -1, "2"); test("1/2", -2, "4"); test("1/2", -3, "8"); test("22/7", -1, "7/22"); test("22/7", -2, "49/484"); test("22/7", -3, "343/10648"); test("-1", 0, "1"); test("-2", 0, "1"); test("-1000", 0, "1"); test("-1000000000000", 0, "1"); test("-1", 1, "-1"); test("-2", 1, "-2"); test("-1000", 1, "-1000"); test("-1000000000000", 1, "-1000000000000"); test("-1", 2, "1"); test("-2", 2, "4"); test("-3", 2, "9"); test("-1000", 2, "1000000"); test("-1000000000000", 2, "1000000000000000000000000"); test("-1/2", 0, "1"); test("-1/2", 1, "-1/2"); test("-1/2", 2, "1/4"); test("-1/2", 3, "-1/8"); test("-22/7", 0, "1"); test("-22/7", 1, "-22/7"); test("-22/7", 2, "484/49"); test("-22/7", 3, "-10648/343"); test("-1", -1, "-1"); test("-2", -1, "-1/2"); test("-1000", -1, "-1/1000"); test("-1000000000000", -1, "-1/1000000000000"); test("-1", -2, "1"); test("-2", -2, "1/4"); test("-3", -2, "1/9"); test("-1000", -2, "1/1000000"); test("-1000000000000", -2, "1/1000000000000000000000000"); test("-1/2", -1, "-2"); test("-1/2", -2, "4"); test("-1/2", -3, "-8"); test("-22/7", -1, "-7/22"); test("-22/7", -2, "49/484"); test("-22/7", -3, "-343/10648"); } #[test] fn pow_properties() { // exponent is u64 rational_unsigned_pair_gen_var_1::().test_properties(|(x, exp)| { let power = (&x).pow(exp); assert!(power.is_valid()); let power_alt = x.clone().pow(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let mut power_alt = x.clone(); power_alt.pow_assign(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let power_of_neg = (-&x).pow(exp); if exp.even() { assert_eq!(power_of_neg, power); } else { assert_eq!(power_of_neg, -&power); } if exp > 0 && (x >= 0 || exp.odd()) { assert_eq!((&power).checked_root(exp).as_ref(), Some(&x)); } assert_eq!((&x).pow(i64::exact_from(exp)), power); assert_eq!(Rational::from(&BigRational::from(&x).pow(exp)), power); assert_eq!( Rational::from(&rug::Rational::from(&x).pow(u32::exact_from(exp))), power ); }); rational_gen().test_properties(|x| { assert_eq!((&x).pow(0u64), 1); assert_eq!((&x).pow(1u64), x); assert_eq!((&x).pow(2u64), x.square()); }); unsigned_gen_var_5::().test_properties(|exp| { assert_eq!(Rational::ZERO.pow(exp), u64::from(exp == 0)); assert_eq!(Rational::ONE.pow(exp), 1); assert_eq!(Rational::TWO.pow(exp), Rational::power_of_2(exp)); assert_eq!( Rational::NEGATIVE_ONE.pow(exp), if exp.even() { 1 } else { -1 } ); }); rational_rational_unsigned_triple_gen_var_1::().test_properties(|(x, y, exp)| { assert_eq!((&x * &y).pow(exp), x.pow(exp) * y.pow(exp)); }); rational_unsigned_unsigned_triple_gen_var_1::().test_properties(|(x, e, f)| { assert_eq!((&x).pow(e + f), (&x).pow(e) * (&x).pow(f)); assert_eq!((&x).pow(e * f), x.pow(e).pow(f)); }); integer_unsigned_pair_gen_var_2().test_properties(|(x, exp)| { assert_eq!((&x).pow(exp), Rational::from(x).pow(exp)); }); // exponent is i64 rational_signed_pair_gen_var_2::().test_properties(|(x, exp)| { let power = (&x).pow(exp); assert!(power.is_valid()); let power_alt = x.clone().pow(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let mut power_alt = x.clone(); power_alt.pow_assign(exp); assert!(power_alt.is_valid()); assert_eq!(power_alt, power); let power_of_neg = (-&x).pow(exp); if exp.even() { assert_eq!(power_of_neg, power); } else { assert_eq!(power_of_neg, -&power); } if x != 0 { assert_eq!((&x).pow(-exp), (&power).reciprocal()); } if exp > 0 && (x >= 0 || exp.odd()) { assert_eq!((&power).checked_root(exp).as_ref(), Some(&x)); } assert_eq!(Rational::from(&BigRational::from(&x).pow(exp)), power); assert_eq!( Rational::from(&rug::Rational::from(&x).pow(i32::exact_from(exp))), power ); }); rational_gen().test_properties(|x| { assert_eq!((&x).pow(0i64), 1); assert_eq!((&x).pow(1i64), x); assert_eq!((&x).pow(2i64), x.square()); }); rational_gen_var_1().test_properties(|x| { assert_eq!((&x).pow(-1i64), x.reciprocal()); }); signed_gen_var_5::().test_properties(|exp| { if exp >= 0 { assert_eq!(Rational::ZERO.pow(exp), u64::from(exp == 0)); } assert_eq!(Rational::ONE.pow(exp), 1); assert_eq!(Rational::TWO.pow(exp), Rational::power_of_2(exp)); assert_eq!( Rational::NEGATIVE_ONE.pow(exp), if exp.even() { 1 } else { -1 } ); }); rational_rational_signed_triple_gen_var_1::().test_properties(|(x, y, exp)| { assert_eq!((&x * &y).pow(exp), x.pow(exp) * y.pow(exp)); }); rational_signed_signed_triple_gen_var_1::().test_properties(|(x, e, f)| { assert_eq!((&x).pow(e + f), (&x).pow(e) * (&x).pow(f)); assert_eq!((&x).pow(e * f), x.pow(e).pow(f)); }); } ================================================ FILE: malachite-q/tests/arithmetic/power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ CheckedLogBase2, NextPowerOf2, Pow, PowerOf2, Reciprocal, }; use malachite_base::num::basic::traits::{One, Two}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen_var_5, unsigned_gen_var_5}; use malachite_nz::natural::Natural; use malachite_q::Rational; #[test] fn test_power_of_2() { let test = |pow: u64, out| assert_eq!(Rational::power_of_2(pow).to_string(), out); test(0, "1"); test(1, "2"); test(2, "4"); test(3, "8"); test(32, "4294967296"); test(100, "1267650600228229401496703205376"); let test = |pow: i64, out| assert_eq!(Rational::power_of_2(pow).to_string(), out); test(0, "1"); test(1, "2"); test(2, "4"); test(3, "8"); test(32, "4294967296"); test(100, "1267650600228229401496703205376"); test(-1, "1/2"); test(-2, "1/4"); test(-3, "1/8"); test(-32, "1/4294967296"); test(-100, "1/1267650600228229401496703205376"); } #[test] fn power_of_2_properties() { unsigned_gen_var_5().test_properties(|pow| { let x = Rational::power_of_2(pow); assert!(x.is_valid()); assert_eq!(x, Rational::ONE << pow); assert_eq!(x, Rational::TWO.pow(pow)); assert_eq!(x.checked_log_base_2(), Some(i64::exact_from(pow))); assert_eq!((&x).next_power_of_2(), x); assert_eq!(Natural::power_of_2(pow), x); }); signed_gen_var_5::().test_properties(|pow| { let x = Rational::power_of_2(pow); assert!(x.is_valid()); assert_eq!(x, Rational::ONE << pow); assert_eq!(x, Rational::TWO.pow(pow)); assert_eq!(x.checked_log_base_2(), Some(pow)); assert_eq!((&x).next_power_of_2(), x); if pow >= 0 { assert_eq!(Natural::power_of_2(pow.unsigned_abs()), x); } else { assert_eq!(Natural::power_of_2(pow.unsigned_abs()), x.reciprocal()); } }); } ================================================ FILE: malachite-q/tests/arithmetic/reciprocal.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, Reciprocal, ReciprocalAssign}; use malachite_base::num::basic::traits::Zero; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen_var_1; use num::BigRational; use std::str::FromStr; #[test] fn test_reciprocal() { let test = |s, out| { let x = Rational::from_str(s).unwrap(); let reciprocal = x.clone().reciprocal(); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); let reciprocal = (&x).reciprocal(); assert!(reciprocal.is_valid()); assert_eq!(reciprocal.to_string(), out); assert_eq!(BigRational::from_str(s).unwrap().recip().to_string(), out); assert_eq!(rug::Rational::from_str(s).unwrap().recip().to_string(), out); let mut x = x; x.reciprocal_assign(); assert!(reciprocal.is_valid()); assert_eq!(x.to_string(), out); }; test("1", "1"); test("-1", "-1"); test("123", "1/123"); test("22/7", "7/22"); test("-22/7", "-7/22"); } #[test] #[should_panic] fn reciprocal_fail() { Rational::ZERO.reciprocal(); } #[test] #[should_panic] fn reciprocal_ref_fail() { (&Rational::ZERO).reciprocal(); } #[test] #[should_panic] fn reciprocal_assign_fail() { let mut q = Rational::ZERO; q.reciprocal_assign(); } #[test] fn reciprocal_properties() { rational_gen_var_1().test_properties(|x| { let reciprocal = x.clone().reciprocal(); assert!(reciprocal.is_valid()); assert_eq!(Rational::from(&BigRational::from(&x).recip()), reciprocal); assert_eq!(Rational::from(&rug::Rational::from(&x).recip()), reciprocal); let reciprocal_alt = (&x).reciprocal(); assert!(reciprocal_alt.is_valid()); assert_eq!(reciprocal_alt, reciprocal); let mut reciprocal_alt = x.clone(); reciprocal_alt.reciprocal_assign(); assert!(reciprocal_alt.is_valid()); assert_eq!(reciprocal_alt, reciprocal); assert_ne!(reciprocal, 0); assert_eq!(reciprocal, -(-&x).reciprocal()); assert_eq!(reciprocal == x, (&x).abs() == 1); assert_eq!((&reciprocal).reciprocal(), x); }); } ================================================ FILE: malachite-q/tests/arithmetic/root.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedRoot, CheckedSqrt, Pow, Reciprocal}; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_3; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_1, rational_gen_var_3, rational_signed_pair_gen_var_4, rational_unsigned_pair_gen_var_4, }; use std::panic::catch_unwind; use std::str::FromStr; fn test_helper(s: &str, exp: T, out: Option<&str>) where Rational: CheckedRoot, for<'a> &'a Rational: CheckedRoot, { let n = Rational::from_str(s).unwrap(); let out = out.map(ToString::to_string); assert_eq!(n.clone().checked_root(exp).map(|x| x.to_string()), out); assert_eq!((&n).checked_root(exp).map(|x| x.to_string()), out); } #[test] fn test_checked_root() { let test = |s, exp, out: Option<&str>| { test_helper::(s, exp, out); test_helper::(s, i64::exact_from(exp), out); }; test("0", 1, Some("0")); test("1", 1, Some("1")); test("2", 1, Some("2")); test("22/7", 1, Some("22/7")); test("0", 2, Some("0")); test("1", 2, Some("1")); test("2", 2, None); test("3", 2, None); test("4", 2, Some("2")); test("5", 2, None); test("22/7", 2, None); test("4/9", 2, Some("2/3")); test("-1", 1, Some("-1")); test("-2", 1, Some("-2")); test("-100", 1, Some("-100")); test("-1", 3, Some("-1")); test("-2", 3, None); test("-7", 3, None); test("-8", 3, Some("-2")); test("-9", 3, None); test("-27/8", 3, Some("-3/2")); test("27/8", 3, Some("3/2")); let test_i = |s, exp: i64, out: Option<&str>| { test_helper::(s, exp, out); }; test_i("1", -1, Some("1")); test_i("2", -1, Some("1/2")); test_i("22/7", -1, Some("7/22")); test_i("1", -2, Some("1")); test_i("2", -2, None); test_i("3", -2, None); test_i("4", -2, Some("1/2")); test_i("5", -2, None); test_i("22/7", -2, None); test_i("4/9", -2, Some("3/2")); test_i("-1", -1, Some("-1")); test_i("-2", -1, Some("-1/2")); test_i("-100", -1, Some("-1/100")); test_i("-1", -3, Some("-1")); test_i("-2", -3, None); test_i("-7", -3, None); test_i("-8", -3, Some("-1/2")); test_i("-9", -3, None); test_i("-27/8", -3, Some("-2/3")); test_i("27/8", -3, Some("2/3")); } #[test] fn checked_root_fail() { assert_panic!(Rational::ONE.checked_root(0u64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(0u64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(2u64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(4u64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(100u64)); assert_panic!(Rational::ZERO.checked_root(-2i64)); assert_panic!(Rational::ONE.checked_root(0i64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(0i64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(2i64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(4i64)); assert_panic!(Rational::NEGATIVE_ONE.checked_root(100i64)); } #[test] fn checked_root_ref_fail() { assert_panic!((&Rational::ONE).checked_root(0u64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(0u64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(2u64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(4u64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(100u64)); assert_panic!((&Rational::ZERO).checked_root(-2i64)); assert_panic!((&Rational::ONE).checked_root(0i64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(0i64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(2i64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(4i64)); assert_panic!((&Rational::NEGATIVE_ONE).checked_root(100i64)); } #[test] fn checked_root_properties() { rational_unsigned_pair_gen_var_4::().test_properties(|(n, exp)| { let root = n.clone().checked_root(exp); assert!(root.as_ref().is_none_or(Rational::is_valid)); let root_alt = (&n).checked_root(exp); assert!(root_alt.as_ref().is_none_or(Rational::is_valid)); assert_eq!(root_alt, root); assert_eq!((&n).checked_root(u64::exact_from(exp)), root); if n != 0 { assert_eq!( (&n).reciprocal().checked_root(exp), root.as_ref().map(Reciprocal::reciprocal) ); } if let Some(root) = root { assert_eq!((&root).pow(exp), n); } }); rational_signed_pair_gen_var_4::().test_properties(|(n, exp)| { let root = n.clone().checked_root(exp); assert!(root.as_ref().is_none_or(Rational::is_valid)); let root_alt = (&n).checked_root(exp); assert!(root_alt.as_ref().is_none_or(Rational::is_valid)); assert_eq!(root_alt, root); assert_eq!((&n).checked_root(exp), root); if n != 0u32 { assert_eq!( (&n).checked_root(-exp), root.as_ref().map(Reciprocal::reciprocal) ); assert_eq!( (&n).reciprocal().checked_root(exp), root.as_ref().map(Reciprocal::reciprocal) ); } if let Some(root) = root { assert_eq!((&root).pow(exp), n); } }); rational_gen().test_properties(|n| { assert_eq!((&n).checked_root(1u64).unwrap(), n); assert_eq!((&n).checked_root(1i64).unwrap(), n); }); rational_gen_var_3().test_properties(|n| { assert_eq!((&n).checked_root(2u64), (&n).checked_sqrt()); assert_eq!((&n).checked_root(2i64), n.checked_sqrt()); }); rational_gen_var_1().test_properties(|n| { assert_eq!((&n).checked_root(-1i64), Some(n.reciprocal())); }); integer_unsigned_pair_gen_var_3().test_properties(|(n, exp)| { assert_eq!( (&n).checked_root(exp).map(Rational::from), Rational::from(n).checked_root(exp) ); }); } ================================================ FILE: malachite-q/tests/arithmetic/round_to_multiple.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, Parity, RoundToMultiple, RoundToMultipleAssign, }; use malachite_base::num::basic::traits::{NegativeOne, One, Zero}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, IsInteger}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_integer_rounding_mode_triple_gen_var_2, integer_rounding_mode_pair_gen, }; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_pair_gen_var_1, rational_pair_gen_var_2, rational_rational_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_round_to_multiple() { let test = |s, t, rm, quotient, o| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); assert_eq!(n.round_to_multiple_assign(v.clone(), rm), o); assert_eq!(n.to_string(), quotient); assert!(n.is_valid()); let mut n = u.clone(); assert_eq!(n.round_to_multiple_assign(&v, rm), o); assert_eq!(n.to_string(), quotient); assert!(n.is_valid()); let (r, o_alt) = u.clone().round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = u.clone().round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(v.clone(), rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); let (r, o_alt) = (&u).round_to_multiple(&v, rm); assert!(r.is_valid()); assert_eq!(r.to_string(), quotient); assert_eq!(o_alt, o); }; test("0", "1", Down, "0", Equal); test("0", "1", Floor, "0", Equal); test("0", "1", Up, "0", Equal); test("0", "1", Ceiling, "0", Equal); test("0", "1", Nearest, "0", Equal); test("0", "1", Exact, "0", Equal); test("0", "22/7", Down, "0", Equal); test("0", "22/7", Floor, "0", Equal); test("0", "22/7", Up, "0", Equal); test("0", "22/7", Ceiling, "0", Equal); test("0", "22/7", Nearest, "0", Equal); test("0", "22/7", Exact, "0", Equal); test("1/3", "1", Down, "0", Less); test("1/3", "1", Floor, "0", Less); test("1/3", "1", Up, "1", Greater); test("1/3", "1", Ceiling, "1", Greater); test("1/3", "1", Nearest, "0", Less); test("1/3", "1/3", Down, "1/3", Equal); test("1/3", "1/3", Floor, "1/3", Equal); test("1/3", "1/3", Up, "1/3", Equal); test("1/3", "1/3", Ceiling, "1/3", Equal); test("1/3", "1/3", Nearest, "1/3", Equal); test("1/3", "1/3", Exact, "1/3", Equal); test("1/3", "1/4", Down, "1/4", Less); test("1/3", "1/4", Floor, "1/4", Less); test("1/3", "1/4", Up, "1/2", Greater); test("1/3", "1/4", Ceiling, "1/2", Greater); test("1/3", "1/4", Nearest, "1/4", Less); test( "884279719003555/281474976710656", "1/1000000", Down, "392699/125000", Less, ); test( "884279719003555/281474976710656", "1/1000000", Floor, "392699/125000", Less, ); test( "884279719003555/281474976710656", "1/1000000", Up, "3141593/1000000", Greater, ); test( "884279719003555/281474976710656", "1/1000000", Ceiling, "3141593/1000000", Greater, ); test( "884279719003555/281474976710656", "1/1000000", Nearest, "3141593/1000000", Greater, ); test( "1000000", "884279719003555/281474976710656", Down, "281474193076302588495/281474976710656", Less, ); test( "1000000", "884279719003555/281474976710656", Floor, "281474193076302588495/281474976710656", Less, ); test( "1000000", "884279719003555/281474976710656", Up, "140737538678010796025/140737488355328", Greater, ); test( "1000000", "884279719003555/281474976710656", Ceiling, "140737538678010796025/140737488355328", Greater, ); test( "1000000", "884279719003555/281474976710656", Nearest, "140737538678010796025/140737488355328", Greater, ); test("-1/3", "1", Down, "0", Greater); test("-1/3", "1", Floor, "-1", Less); test("-1/3", "1", Up, "-1", Less); test("-1/3", "1", Ceiling, "0", Greater); test("-1/3", "1", Nearest, "0", Greater); test("-1/3", "1/3", Down, "-1/3", Equal); test("-1/3", "1/3", Floor, "-1/3", Equal); test("-1/3", "1/3", Up, "-1/3", Equal); test("-1/3", "1/3", Ceiling, "-1/3", Equal); test("-1/3", "1/3", Nearest, "-1/3", Equal); test("-1/3", "1/3", Exact, "-1/3", Equal); test("-1/3", "1/4", Down, "-1/4", Greater); test("-1/3", "1/4", Floor, "-1/2", Less); test("-1/3", "1/4", Up, "-1/2", Less); test("-1/3", "1/4", Ceiling, "-1/4", Greater); test("-1/3", "1/4", Nearest, "-1/4", Greater); test( "-884279719003555/281474976710656", "1/1000000", Down, "-392699/125000", Greater, ); test( "-884279719003555/281474976710656", "1/1000000", Floor, "-3141593/1000000", Less, ); test( "-884279719003555/281474976710656", "1/1000000", Up, "-3141593/1000000", Less, ); test( "-884279719003555/281474976710656", "1/1000000", Ceiling, "-392699/125000", Greater, ); test( "-884279719003555/281474976710656", "1/1000000", Nearest, "-3141593/1000000", Less, ); test( "-1000000", "884279719003555/281474976710656", Down, "-281474193076302588495/281474976710656", Greater, ); test( "-1000000", "884279719003555/281474976710656", Floor, "-140737538678010796025/140737488355328", Less, ); test( "-1000000", "884279719003555/281474976710656", Up, "-140737538678010796025/140737488355328", Less, ); test( "-1000000", "884279719003555/281474976710656", Ceiling, "-281474193076302588495/281474976710656", Greater, ); test( "-1000000", "884279719003555/281474976710656", Nearest, "-140737538678010796025/140737488355328", Less, ); test("0", "-1", Down, "0", Equal); test("0", "-1", Floor, "0", Equal); test("0", "-1", Up, "0", Equal); test("0", "-1", Ceiling, "0", Equal); test("0", "-1", Nearest, "0", Equal); test("0", "-1", Exact, "0", Equal); test("0", "-22/7", Down, "0", Equal); test("0", "-22/7", Floor, "0", Equal); test("0", "-22/7", Up, "0", Equal); test("0", "-22/7", Ceiling, "0", Equal); test("0", "-22/7", Nearest, "0", Equal); test("0", "-22/7", Exact, "0", Equal); test("1/3", "-1", Down, "0", Less); test("1/3", "-1", Floor, "0", Less); test("1/3", "-1", Up, "1", Greater); test("1/3", "-1", Ceiling, "1", Greater); test("1/3", "-1", Nearest, "0", Less); test("1/3", "-1/3", Down, "1/3", Equal); test("1/3", "-1/3", Floor, "1/3", Equal); test("1/3", "-1/3", Up, "1/3", Equal); test("1/3", "-1/3", Ceiling, "1/3", Equal); test("1/3", "-1/3", Nearest, "1/3", Equal); test("1/3", "-1/3", Exact, "1/3", Equal); test("1/3", "-1/4", Down, "1/4", Less); test("1/3", "-1/4", Floor, "1/4", Less); test("1/3", "-1/4", Up, "1/2", Greater); test("1/3", "-1/4", Ceiling, "1/2", Greater); test("1/3", "-1/4", Nearest, "1/4", Less); test( "884279719003555/281474976710656", "-1/1000000", Down, "392699/125000", Less, ); test( "884279719003555/281474976710656", "-1/1000000", Floor, "392699/125000", Less, ); test( "884279719003555/281474976710656", "-1/1000000", Up, "3141593/1000000", Greater, ); test( "884279719003555/281474976710656", "-1/1000000", Ceiling, "3141593/1000000", Greater, ); test( "884279719003555/281474976710656", "-1/1000000", Nearest, "3141593/1000000", Greater, ); test( "1000000", "-884279719003555/281474976710656", Down, "281474193076302588495/281474976710656", Less, ); test( "1000000", "-884279719003555/281474976710656", Floor, "281474193076302588495/281474976710656", Less, ); test( "1000000", "-884279719003555/281474976710656", Up, "140737538678010796025/140737488355328", Greater, ); test( "1000000", "-884279719003555/281474976710656", Ceiling, "140737538678010796025/140737488355328", Greater, ); test( "1000000", "-884279719003555/281474976710656", Nearest, "140737538678010796025/140737488355328", Greater, ); test("-1/3", "-1", Down, "0", Greater); test("-1/3", "-1", Floor, "-1", Less); test("-1/3", "-1", Up, "-1", Less); test("-1/3", "-1", Ceiling, "0", Greater); test("-1/3", "-1", Nearest, "0", Greater); test("-1/3", "-1/3", Down, "-1/3", Equal); test("-1/3", "-1/3", Floor, "-1/3", Equal); test("-1/3", "-1/3", Up, "-1/3", Equal); test("-1/3", "-1/3", Ceiling, "-1/3", Equal); test("-1/3", "-1/3", Nearest, "-1/3", Equal); test("-1/3", "-1/3", Exact, "-1/3", Equal); test("-1/3", "-1/4", Down, "-1/4", Greater); test("-1/3", "-1/4", Floor, "-1/2", Less); test("-1/3", "-1/4", Up, "-1/2", Less); test("-1/3", "-1/4", Ceiling, "-1/4", Greater); test("-1/3", "-1/4", Nearest, "-1/4", Greater); test( "-884279719003555/281474976710656", "-1/1000000", Down, "-392699/125000", Greater, ); test( "-884279719003555/281474976710656", "-1/1000000", Floor, "-3141593/1000000", Less, ); test( "-884279719003555/281474976710656", "-1/1000000", Up, "-3141593/1000000", Less, ); test( "-884279719003555/281474976710656", "-1/1000000", Ceiling, "-392699/125000", Greater, ); test( "-884279719003555/281474976710656", "-1/1000000", Nearest, "-3141593/1000000", Less, ); test( "-1000000", "-884279719003555/281474976710656", Down, "-281474193076302588495/281474976710656", Greater, ); test( "-1000000", "-884279719003555/281474976710656", Floor, "-140737538678010796025/140737488355328", Less, ); test( "-1000000", "-884279719003555/281474976710656", Up, "-140737538678010796025/140737488355328", Less, ); test( "-1000000", "-884279719003555/281474976710656", Ceiling, "-281474193076302588495/281474976710656", Greater, ); test( "-1000000", "-884279719003555/281474976710656", Nearest, "-140737538678010796025/140737488355328", Less, ); test("1/3", "0", Down, "0", Less); test("1/3", "0", Floor, "0", Less); test("1/3", "0", Nearest, "0", Less); test("-1/3", "0", Down, "0", Greater); test("-1/3", "0", Ceiling, "0", Greater); test("-1/3", "0", Nearest, "0", Greater); } #[test] #[should_panic] fn round_to_multiple_assign_fail_1() { let mut n = Rational::from(10); n.round_to_multiple_assign(Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_fail_2() { let mut n = Rational::from(10); n.round_to_multiple_assign(Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_fail_3() { let mut n = Rational::from(10); n.round_to_multiple_assign(Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_fail_4() { let mut n = Rational::from(10); n.round_to_multiple_assign(Rational::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_1() { let mut n = Rational::from(10); n.round_to_multiple_assign(&Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_2() { let mut n = Rational::from(10); n.round_to_multiple_assign(&Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_3() { let mut n = Rational::from(10); n.round_to_multiple_assign(&Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_assign_ref_fail_4() { let mut n = Rational::from(10); n.round_to_multiple_assign(&Rational::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_fail_1() { Rational::from(10).round_to_multiple(Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_fail_2() { Rational::from(10).round_to_multiple(Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_fail_3() { Rational::from(10).round_to_multiple(Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_fail_4() { Rational::from(10).round_to_multiple(Rational::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_1() { Rational::from(10).round_to_multiple(&Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_2() { Rational::from(10).round_to_multiple(&Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_3() { Rational::from(10).round_to_multiple(&Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_val_ref_fail_4() { Rational::from(10).round_to_multiple(&Rational::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_1() { (&Rational::from(10)).round_to_multiple(Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_2() { (&Rational::from(10)).round_to_multiple(Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_3() { (&Rational::from(10)).round_to_multiple(Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_val_fail_4() { (&Rational::from(10)).round_to_multiple(Rational::ZERO, Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_1() { (&Rational::from(10)).round_to_multiple(&Rational::from(3), Exact); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_2() { (&Rational::from(10)).round_to_multiple(&Rational::ZERO, Ceiling); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_3() { (&Rational::from(10)).round_to_multiple(&Rational::ZERO, Up); } #[test] #[should_panic] fn round_to_multiple_ref_ref_fail_4() { (&Rational::from(10)).round_to_multiple(&Rational::ZERO, Exact); } #[test] fn round_to_multiple_properties() { rational_rational_rounding_mode_triple_gen_var_1().test_properties(|(x, y, rm)| { let mut mut_n = x.clone(); let o = mut_n.round_to_multiple_assign(&y, rm); assert!(mut_n.is_valid()); let r = mut_n; let mut mut_n = x.clone(); assert_eq!(mut_n.round_to_multiple_assign(y.clone(), rm), o); assert!(mut_n.is_valid()); assert_eq!(mut_n, r); let (r_alt, o_alt) = (&x).round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (&x).round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(&y, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = x.clone().round_to_multiple(y.clone(), rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let (r_alt, o_alt) = (-&x).round_to_multiple(&y, -rm); assert_eq!(-&r_alt, r); assert_eq!(o_alt.reverse(), o); let (r_alt, o_alt) = (&x).round_to_multiple(-&y, rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); assert_eq!(r.cmp(&x), o); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } if y == 0 { assert_eq!(r, 0); } else { assert!((&r / &y).is_integer()); assert!((&r - &x).le_abs(&y)); match rm { Floor => assert!(r <= x), Ceiling => assert!(r >= x), Down => assert!(r.le_abs(&x)), Up => assert!(r.ge_abs(&x)), Exact => assert_eq!(r, x), Nearest => { let closest; let second_closest; if r <= x { closest = &x - &r; second_closest = &r + (&y).abs() - &x; } else { closest = &r - &x; second_closest = x + (&y).abs() - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!(Integer::exact_from(r / y).even()); } } } } }); rational_pair_gen_var_1().test_properties(|(x, y)| { let rounded = x.round_to_multiple(&y, Nearest).0; let ro = (rounded.clone(), Equal); assert_eq!((&rounded).round_to_multiple(&y, Down), ro); assert_eq!((&rounded).round_to_multiple(&y, Up), ro); assert_eq!((&rounded).round_to_multiple(&y, Floor), ro); assert_eq!((&rounded).round_to_multiple(&y, Ceiling), ro); assert_eq!((&rounded).round_to_multiple(&y, Nearest), ro); assert_eq!((&rounded).round_to_multiple(&y, Exact), ro); }); rational_pair_gen_var_2().test_properties(|(x, y)| { let down = (&x).round_to_multiple(&y, Down); assert_eq!(down.1, if x >= 0 { Less } else { Greater }); let up = if x >= 0 { (&down.0 + (&y).abs(), Greater) } else { (&down.0 - (&y).abs(), Less) }; let floor = (&x).round_to_multiple(&y, Floor); let ceiling = (&floor.0 + (&y).abs(), Greater); assert_eq!((&x).round_to_multiple(&y, Up), up); assert_eq!((&x).round_to_multiple(&y, Ceiling), ceiling); let nearest = x.round_to_multiple(y, Nearest); assert!(nearest == down || nearest == up); }); integer_rounding_mode_pair_gen().test_properties(|(x, rm)| { let x = Rational::from(x); let x = &x; let xo = (x.clone(), Equal); assert_eq!(x.round_to_multiple(Rational::ONE, rm), xo); assert_eq!(x.round_to_multiple(Rational::NEGATIVE_ONE, rm), xo); assert_eq!( Rational::ZERO.round_to_multiple(x, rm), (Rational::ZERO, Equal) ); assert_eq!(x.round_to_multiple(x, rm), xo); assert_eq!(x.round_to_multiple(-x, rm), xo); assert_eq!((-x).round_to_multiple(x, rm), (-x, Equal)); }); integer_integer_rounding_mode_triple_gen_var_2().test_properties(|(x, y, rm)| { let (n, no) = (&x).round_to_multiple(&y, rm); let (r, ro) = Rational::from(x).round_to_multiple(Rational::from(y), rm); assert_eq!(n, r); assert_eq!(no, ro); }); } ================================================ FILE: malachite-q/tests/arithmetic/round_to_multiple_of_power_of_2.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{ Abs, Parity, PowerOf2, RoundToMultiple, RoundToMultipleOfPowerOf2, RoundToMultipleOfPowerOf2Assign, }; use malachite_base::num::basic::traits::Zero; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, IsInteger}; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::signed_rounding_mode_pair_gen; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::{ integer_rounding_mode_pair_gen, integer_unsigned_rounding_mode_triple_gen_var_1, }; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_signed_pair_gen_var_1, rational_signed_pair_gen_var_3, rational_signed_rounding_mode_triple_gen_var_1, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_round_to_multiple_of_power_of_2() { let test = |s, v: i64, rm: RoundingMode, out, o| { let u = Rational::from_str(s).unwrap(); let mut n = u.clone(); assert_eq!(n.round_to_multiple_of_power_of_2_assign(v, rm), o); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let (n, o_alt) = u.clone().round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); let (n, o_alt) = (&u).round_to_multiple_of_power_of_2(v, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o_alt, o); }; test("0", 0, Down, "0", Equal); test("0", 0, Up, "0", Equal); test("0", 0, Floor, "0", Equal); test("0", 0, Ceiling, "0", Equal); test("0", 0, Nearest, "0", Equal); test("0", 0, Exact, "0", Equal); test("0", 10, Down, "0", Equal); test("0", 10, Up, "0", Equal); test("0", 10, Floor, "0", Equal); test("0", 10, Ceiling, "0", Equal); test("0", 10, Nearest, "0", Equal); test("0", 10, Exact, "0", Equal); test("123", 0, Down, "123", Equal); test("123", 0, Up, "123", Equal); test("123", 0, Floor, "123", Equal); test("123", 0, Ceiling, "123", Equal); test("123", 0, Nearest, "123", Equal); test("123", 0, Exact, "123", Equal); test("123", 2, Down, "120", Less); test("123", 2, Up, "124", Greater); test("123", 2, Floor, "120", Less); test("123", 2, Ceiling, "124", Greater); test("123", 2, Nearest, "124", Greater); test("123", -2, Down, "123", Equal); test("123", -2, Up, "123", Equal); test("123", -2, Floor, "123", Equal); test("123", -2, Ceiling, "123", Equal); test("123", -2, Nearest, "123", Equal); test("123", -2, Exact, "123", Equal); test("884279719003555/281474976710656", 2, Down, "0", Less); test("884279719003555/281474976710656", 2, Up, "4", Greater); test("884279719003555/281474976710656", 2, Floor, "0", Less); test("884279719003555/281474976710656", 2, Ceiling, "4", Greater); test("884279719003555/281474976710656", 2, Nearest, "4", Greater); test("884279719003555/281474976710656", -4, Down, "25/8", Less); test("884279719003555/281474976710656", -4, Up, "51/16", Greater); test("884279719003555/281474976710656", -4, Floor, "25/8", Less); test( "884279719003555/281474976710656", -4, Ceiling, "51/16", Greater, ); test("884279719003555/281474976710656", -4, Nearest, "25/8", Less); test("884279719003555/281474976710656", -10, Down, "201/64", Less); test( "884279719003555/281474976710656", -10, Up, "3217/1024", Greater, ); test( "884279719003555/281474976710656", -10, Floor, "201/64", Less, ); test( "884279719003555/281474976710656", -10, Ceiling, "3217/1024", Greater, ); test( "884279719003555/281474976710656", -10, Nearest, "3217/1024", Greater, ); test("-123", 0, Down, "-123", Equal); test("-123", 0, Up, "-123", Equal); test("-123", 0, Floor, "-123", Equal); test("-123", 0, Ceiling, "-123", Equal); test("-123", 0, Nearest, "-123", Equal); test("-123", 0, Exact, "-123", Equal); test("-123", 2, Down, "-120", Greater); test("-123", 2, Up, "-124", Less); test("-123", 2, Floor, "-124", Less); test("-123", 2, Ceiling, "-120", Greater); test("-123", 2, Nearest, "-124", Less); test("-123", -2, Down, "-123", Equal); test("-123", -2, Up, "-123", Equal); test("-123", -2, Floor, "-123", Equal); test("-123", -2, Ceiling, "-123", Equal); test("-123", -2, Nearest, "-123", Equal); test("-123", -2, Exact, "-123", Equal); test("-884279719003555/281474976710656", 2, Down, "0", Greater); test("-884279719003555/281474976710656", 2, Up, "-4", Less); test("-884279719003555/281474976710656", 2, Floor, "-4", Less); test("-884279719003555/281474976710656", 2, Ceiling, "0", Greater); test("-884279719003555/281474976710656", 2, Nearest, "-4", Less); test( "-884279719003555/281474976710656", -4, Down, "-25/8", Greater, ); test("-884279719003555/281474976710656", -4, Up, "-51/16", Less); test( "-884279719003555/281474976710656", -4, Floor, "-51/16", Less, ); test( "-884279719003555/281474976710656", -4, Ceiling, "-25/8", Greater, ); test( "-884279719003555/281474976710656", -4, Nearest, "-25/8", Greater, ); test( "-884279719003555/281474976710656", -10, Down, "-201/64", Greater, ); test( "-884279719003555/281474976710656", -10, Up, "-3217/1024", Less, ); test( "-884279719003555/281474976710656", -10, Floor, "-3217/1024", Less, ); test( "-884279719003555/281474976710656", -10, Ceiling, "-201/64", Greater, ); test( "-884279719003555/281474976710656", -10, Nearest, "-3217/1024", Less, ); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_1() { Rational::from(-123).round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_2() { Rational::from(-123).round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_3() { Rational::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_assign_fail_4() { Rational::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2_assign(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_1() { Rational::from(-123).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_2() { Rational::from(-123).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_3() { Rational::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_fail_4() { Rational::from_str("-1000000000001") .unwrap() .round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_1() { (&Rational::from(-123)).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_2() { (&Rational::from(-123)).round_to_multiple_of_power_of_2(100, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_3() { (&Rational::from_str("-1000000000001").unwrap()).round_to_multiple_of_power_of_2(1, Exact); } #[test] #[should_panic] fn round_to_multiple_of_power_of_2_ref_fail_4() { (&Rational::from_str("-1000000000001").unwrap()).round_to_multiple_of_power_of_2(100, Exact); } #[test] fn round_to_multiple_of_power_of_2_properties() { rational_signed_rounding_mode_triple_gen_var_1().test_properties(|(n, pow, rm)| { let (r, o) = (&n).round_to_multiple_of_power_of_2(pow, rm); assert!(r.is_valid()); let (r_alt, o_alt) = n.clone().round_to_multiple_of_power_of_2(pow, rm); assert!(r_alt.is_valid()); assert_eq!(r_alt, r); assert_eq!(o_alt, o); let mut mut_n = n.clone(); let o_alt = mut_n.round_to_multiple_of_power_of_2_assign(pow, rm); assert!(mut_n.is_valid()); assert_eq!(mut_n, r); assert_eq!(o_alt, o); assert!((&r >> pow).is_integer()); assert_eq!(r.cmp(&n), o); match (n >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } let (r_alt, o_alt) = (-&n).round_to_multiple_of_power_of_2(pow, -rm); assert_eq!(-r_alt, r); assert_eq!(o_alt.reverse(), o); assert!((&r - &n).abs() <= Rational::power_of_2(pow)); let (r_alt, o_alt) = (&n).round_to_multiple(Rational::power_of_2(pow), rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); match rm { Floor => assert!(r <= n), Ceiling => assert!(r >= n), Down => assert!(r.le_abs(&n)), Up => assert!(r.ge_abs(&n)), Exact => assert_eq!(r, n), Nearest => { let k = Rational::power_of_2(pow); let closest; let second_closest; if r <= n { closest = &n - &r; second_closest = &r + k - n; } else { closest = &r - &n; second_closest = n + k - &r; } assert!(closest <= second_closest); if closest == second_closest { assert!(Integer::exact_from(r >> pow).even()); } } } }); rational_signed_pair_gen_var_1().test_properties(|(n, pow)| { let rounded = (&n).round_to_multiple_of_power_of_2(pow, Nearest).0; let ro = (rounded.clone(), Equal); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Down), ro); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Up), ro); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Floor), ro); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Ceiling), ro); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Nearest), ro); assert_eq!((&rounded).round_to_multiple_of_power_of_2(pow, Exact), ro); }); rational_signed_pair_gen_var_3().test_properties(|(n, pow)| { let floor = (&n).round_to_multiple_of_power_of_2(pow, Floor); assert_eq!(floor.1, Less); let ceiling = (&floor.0 + Rational::power_of_2(pow), Greater); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Ceiling), ceiling); if n >= 0 { assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Up), ceiling); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Down), floor); } else { assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Up), floor); assert_eq!((&n).round_to_multiple_of_power_of_2(pow, Down), ceiling); } let nearest = n.round_to_multiple_of_power_of_2(pow, Nearest); assert!(nearest == ceiling || nearest == floor); }); integer_rounding_mode_pair_gen().test_properties(|(n, rm)| { let rn = Rational::from(n); assert_eq!((&rn).round_to_multiple_of_power_of_2(0, rm), (rn, Equal)); }); signed_rounding_mode_pair_gen().test_properties(|(pow, rm)| { assert_eq!( Rational::ZERO.round_to_multiple_of_power_of_2(pow, rm), (Rational::ZERO, Equal) ); }); integer_unsigned_rounding_mode_triple_gen_var_1().test_properties(|(n, pow, rm)| { let (r, o) = (&n).round_to_multiple_of_power_of_2(pow, rm); let (r_alt, o_alt) = Rational::from(n).round_to_multiple_of_power_of_2(i64::exact_from(pow), rm); assert_eq!(r_alt, r); assert_eq!(o_alt, o); }); } ================================================ FILE: malachite-q/tests/arithmetic/shl.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, unsigned_gen, unsigned_gen_var_5, }; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_unsigned_pair_gen_var_1; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_signed_pair_gen_var_1, rational_unsigned_pair_gen_var_1, }; use std::ops::{Shl, ShlAssign, Shr}; use std::str::FromStr; fn test_shl_unsigned_helper(f: F) where Rational: ShlAssign + Shl, for<'a> &'a Rational: Shl, { let test = |s, v: u8, out| { let u = Rational::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("123", 0, "123"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("-123", 0, "-123"); test("-123", 1, "-246"); test("-123", 2, "-492"); test("-123", 25, "-4127195136"); test("-123", 26, "-8254390272"); test("-123", 100, "-155921023828072216384094494261248"); test("22/7", 0, "22/7"); test("22/7", 1, "44/7"); test("22/7", 2, "88/7"); test("22/7", 25, "738197504/7"); test("22/7", 26, "1476395008/7"); test("22/7", 100, "27888313205021046832927470518272/7"); test("-22/7", 0, "-22/7"); test("-22/7", 1, "-44/7"); test("-22/7", 2, "-88/7"); test("-22/7", 25, "-738197504/7"); test("-22/7", 26, "-1476395008/7"); test("-22/7", 100, "-27888313205021046832927470518272/7"); } #[test] fn test_shl_unsigned() { test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|s, v, out| { let mut n = rug::Rational::from_str(s).unwrap(); n <<= v; assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() << v; assert_eq!(n.to_string(), out); }); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); test_shl_unsigned_helper::(|_, _, _| {}); } fn test_shl_signed_helper(f: F) where Rational: ShlAssign + Shl, for<'a> &'a Rational: Shl, { let test = |s, v: i8, out| { let u = Rational::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n <<= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u << v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", 10, "0"); test("0", 10, "0"); test("123", 1, "246"); test("123", 2, "492"); test("123", 25, "4127195136"); test("123", 26, "8254390272"); test("123", 100, "155921023828072216384094494261248"); test("-123", 1, "-246"); test("-123", 2, "-492"); test("-123", 25, "-4127195136"); test("-123", 26, "-8254390272"); test("-123", 100, "-155921023828072216384094494261248"); test("123", 0, "123"); test("245", -1, "245/2"); test("246", -1, "123"); test("247", -1, "247/2"); test("491", -2, "491/4"); test("492", -2, "123"); test("493", -2, "493/4"); test("-123", 0, "-123"); test("-245", -1, "-245/2"); test("-246", -1, "-123"); test("-247", -1, "-247/2"); test("-491", -2, "-491/4"); test("-492", -2, "-123"); test("-493", -2, "-493/4"); test("22/7", 0, "22/7"); test("22/7", 1, "44/7"); test("22/7", 2, "88/7"); test("22/7", 25, "738197504/7"); test("22/7", 26, "1476395008/7"); test("22/7", 100, "27888313205021046832927470518272/7"); test("-22/7", 0, "-22/7"); test("-22/7", 1, "-44/7"); test("-22/7", 2, "-88/7"); test("-22/7", 25, "-738197504/7"); test("-22/7", 26, "-1476395008/7"); test("-22/7", 100, "-27888313205021046832927470518272/7"); test("22/7", -1, "11/7"); test("22/7", -2, "11/14"); test("22/7", -25, "11/117440512"); test("22/7", -26, "11/234881024"); test("22/7", -100, "11/4436777100798802905238461218816"); test("-22/7", -1, "-11/7"); test("-22/7", -2, "-11/14"); test("-22/7", -25, "-11/117440512"); test("-22/7", -26, "-11/234881024"); test("-22/7", -100, "-11/4436777100798802905238461218816"); } #[test] fn test_shl_signed() { test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|s, v, out| { let mut n = rug::Rational::from_str(s).unwrap(); n <<= v; assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() << v; assert_eq!(n.to_string(), out); }); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); test_shl_signed_helper::(|_, _, _| {}); } fn shl_properties_helper_unsigned() where for<'a> &'a Integer: Shl, Rational: Shl + ShlAssign + Shr, for<'a> &'a Rational: Shl, u64: TryFrom, { rational_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n <<= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!((&n << u).ge_abs(&n)); assert_eq!(-&n << u, -(&n << u)); assert_eq!(&n << u, &n * Rational::power_of_2(u64::exact_from(u))); assert_eq!(&n << u >> u, n); }); rational_gen().test_properties(|n| { assert_eq!(&n << T::ZERO, n); }); unsigned_gen::().test_properties(|u| { assert_eq!(Rational::ZERO << u, 0); }); unsigned_gen_var_5::().test_properties(|u| { assert!((Rational::ONE << u).is_power_of_2()); }); integer_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { assert_eq!(&n << u, Rational::from(n) << u); }); } fn shl_properties_helper_signed() where for<'a> &'a Integer: Shl, Rational: Shl + ShlAssign + Shr, for<'a> &'a Rational: Shl + Shl<::Output, Output = Rational>, i64: TryFrom, { rational_signed_pair_gen_var_1::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n <<= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() << i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); if i >= T::ZERO { assert_eq!(&n << i.unsigned_abs(), shifted); } assert_eq!(-&n << i, -(&n << i)); assert_eq!(&n << i, &n * Rational::power_of_2(i64::exact_from(i))); assert_eq!(&n << i >> i, n); if let Some(neg_i) = i.checked_neg() { assert_eq!(&n << neg_i, n >> i); } }); rational_gen().test_properties(|n| { assert_eq!(&n << T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Rational::ZERO << i, 0); }); signed_gen_var_5::().test_properties(|i| { assert!((Rational::ONE << i).is_power_of_2()); }); } #[test] fn shl_properties() { apply_fn_to_unsigneds!(shl_properties_helper_unsigned); apply_fn_to_signeds!(shl_properties_helper_signed); rational_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let shifted = &n << u; let mut rug_n = rug::Rational::from(&n); rug_n <<= u; assert_eq!(Rational::from(&rug_n), shifted); assert_eq!(Rational::from(&(rug::Rational::from(&n) << u)), shifted); }); rational_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = &n << i; let mut rug_n = rug::Rational::from(&n); rug_n <<= i; assert_eq!(Rational::from(&rug_n), shifted); assert_eq!(Rational::from(&(rug::Rational::from(&n) << i)), shifted); }); } ================================================ FILE: malachite-q/tests/arithmetic/shr.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{IsPowerOf2, PowerOf2, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_gen_var_5, unsigned_gen, unsigned_gen_var_5, }; use malachite_nz::integer::Integer; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_signed_pair_gen_var_1, rational_unsigned_pair_gen_var_1, }; use std::ops::{Shl, Shr, ShrAssign}; use std::str::FromStr; fn test_shr_unsigned_helper(f: F) where Rational: ShrAssign + Shr, for<'a> &'a Rational: Shr, { let test = |s, v: u8, out| { let u = Rational::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("123", 0, "123"); test("245", 1, "245/2"); test("246", 1, "123"); test("247", 1, "247/2"); test("491", 2, "491/4"); test("492", 2, "123"); test("493", 2, "493/4"); test("-123", 0, "-123"); test("-245", 1, "-245/2"); test("-246", 1, "-123"); test("-247", 1, "-247/2"); test("-491", 2, "-491/4"); test("-492", 2, "-123"); test("-493", 2, "-493/4"); test("22/7", 1, "11/7"); test("22/7", 2, "11/14"); test("22/7", 25, "11/117440512"); test("22/7", 26, "11/234881024"); test("22/7", 100, "11/4436777100798802905238461218816"); test("-22/7", 1, "-11/7"); test("-22/7", 2, "-11/14"); test("-22/7", 25, "-11/117440512"); test("-22/7", 26, "-11/234881024"); test("-22/7", 100, "-11/4436777100798802905238461218816"); } #[test] fn test_shr_unsigned() { test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|s, v, out| { let mut n = rug::Rational::from_str(s).unwrap(); n >>= v; assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() >> v; assert_eq!(n.to_string(), out); }); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); test_shr_unsigned_helper::(|_, _, _| {}); } fn test_shr_signed_helper(f: F) where Rational: ShrAssign + Shr, for<'a> &'a Rational: Shr, { let test = |s, v: i8, out| { let u = Rational::from_str(s).unwrap(); let v = T::from(v); let mut n = u.clone(); n >>= v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u >> v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); f(s, v, out); }; test("0", 0, "0"); test("0", -10, "0"); test("0", -10, "0"); test("123", -1, "246"); test("123", -2, "492"); test("123", -25, "4127195136"); test("123", -26, "8254390272"); test("123", -100, "155921023828072216384094494261248"); test("-123", -1, "-246"); test("-123", -2, "-492"); test("-123", -25, "-4127195136"); test("-123", -26, "-8254390272"); test("-123", -100, "-155921023828072216384094494261248"); test("123", 0, "123"); test("245", 1, "245/2"); test("246", 1, "123"); test("247", 1, "247/2"); test("491", 2, "491/4"); test("492", 2, "123"); test("493", 2, "493/4"); test("-123", 0, "-123"); test("-245", 1, "-245/2"); test("-246", 1, "-123"); test("-247", 1, "-247/2"); test("-491", 2, "-491/4"); test("-492", 2, "-123"); test("-493", 2, "-493/4"); test("22/7", 0, "22/7"); test("22/7", -1, "44/7"); test("22/7", -2, "88/7"); test("22/7", -25, "738197504/7"); test("22/7", -26, "1476395008/7"); test("22/7", -100, "27888313205021046832927470518272/7"); test("-22/7", 0, "-22/7"); test("-22/7", -1, "-44/7"); test("-22/7", -2, "-88/7"); test("-22/7", -25, "-738197504/7"); test("-22/7", -26, "-1476395008/7"); test("-22/7", -100, "-27888313205021046832927470518272/7"); test("22/7", 1, "11/7"); test("22/7", 2, "11/14"); test("22/7", 25, "11/117440512"); test("22/7", 26, "11/234881024"); test("22/7", 100, "11/4436777100798802905238461218816"); test("-22/7", 1, "-11/7"); test("-22/7", 2, "-11/14"); test("-22/7", 25, "-11/117440512"); test("-22/7", 26, "-11/234881024"); test("-22/7", 100, "-11/4436777100798802905238461218816"); } #[test] fn test_shr_signed() { test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|s, v, out| { let mut n = rug::Rational::from_str(s).unwrap(); n >>= v; assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() >> v; assert_eq!(n.to_string(), out); }); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); test_shr_signed_helper::(|_, _, _| {}); } fn shr_properties_helper_unsigned() where for<'a> &'a Integer: Shr, Rational: Shr + ShrAssign + Shl, for<'a> &'a Rational: Shr, u64: TryFrom, { rational_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let mut mut_n = n.clone(); mut_n >>= u; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() >> u; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); assert!((&n >> u).le_abs(&n)); assert_eq!(-&n >> u, -(&n >> u)); assert_eq!(&n >> u, &n / Rational::power_of_2(u64::exact_from(u))); assert_eq!(&n >> u << u, n); }); rational_gen().test_properties(|n| { assert_eq!(&n >> T::ZERO, n); }); unsigned_gen::().test_properties(|u| { assert_eq!(Rational::ZERO >> u, 0); }); unsigned_gen_var_5::().test_properties(|u| { assert!((Rational::ONE >> u).is_power_of_2()); }); } fn shr_properties_helper_signed() where for<'a> &'a Integer: Shr, Rational: Shr + ShrAssign + Shl, for<'a> &'a Rational: Shr + Shr<::Output, Output = Rational>, i64: TryFrom, { rational_signed_pair_gen_var_1::().test_properties(|(n, i)| { let mut mut_n = n.clone(); mut_n >>= i; assert!(mut_n.is_valid()); let shifted = mut_n; let shifted_alt = &n >> i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); let shifted_alt = n.clone() >> i; assert!(shifted_alt.is_valid()); assert_eq!(shifted_alt, shifted); if i >= T::ZERO { assert_eq!(&n >> i.unsigned_abs(), shifted); } assert_eq!(-&n >> i, -(&n >> i)); assert_eq!(&n >> i, &n / Rational::power_of_2(i64::exact_from(i))); assert_eq!(&n >> i << i, n); if let Some(neg_i) = i.checked_neg() { assert_eq!(&n >> neg_i, n << i); } }); rational_gen().test_properties(|n| { assert_eq!(&n >> T::ZERO, n); }); signed_gen::().test_properties(|i| { assert_eq!(Rational::ZERO >> i, 0); }); signed_gen_var_5::().test_properties(|i| { assert!((Rational::ONE >> i).is_power_of_2()); }); } #[test] fn shr_properties() { apply_fn_to_unsigneds!(shr_properties_helper_unsigned); apply_fn_to_signeds!(shr_properties_helper_signed); rational_unsigned_pair_gen_var_1::().test_properties(|(n, u)| { let shifted = &n >> u; let mut rug_n = rug::Rational::from(&n); rug_n >>= u; assert_eq!(Rational::from(&rug_n), shifted); assert_eq!(Rational::from(&(rug::Rational::from(&n) >> u)), shifted); }); rational_signed_pair_gen_var_1::().test_properties(|(n, i)| { let shifted = &n >> i; let mut rug_n = rug::Rational::from(&n); rug_n >>= i; assert_eq!(Rational::from(&rug_n), shifted); assert_eq!(Rational::from(&(rug::Rational::from(&n) >> i)), shifted); }); } ================================================ FILE: malachite-q/tests/arithmetic/sign.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Sign; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::arithmetic::sign::num_sign; use malachite_q::test_util::generators::rational_gen; use num::BigRational; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_sign() { let test = |s, out| { assert_eq!(Rational::from_str(s).unwrap().sign(), out); assert_eq!(num_sign(&BigRational::from_str(s).unwrap()), out); assert_eq!(rug::Rational::from_str(s).unwrap().cmp0(), out); }; test("0", Equal); test("123", Greater); test("-123", Less); test("1000000000000", Greater); test("-1000000000000", Less); } #[test] fn sign_properties() { rational_gen().test_properties(|n| { let sign = n.sign(); assert_eq!(rug::Rational::from(&n).cmp0(), sign); assert_eq!(num_sign(&BigRational::from(&n)), sign); assert_eq!(n.partial_cmp(&0), Some(sign)); assert_eq!((-n).sign(), sign.reverse()); }); integer_gen().test_properties(|n| { assert_eq!(Rational::from(&n).sign(), n.sign()); }); } ================================================ FILE: malachite-q/tests/arithmetic/simplest_rational_in_interval.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{One, Zero}; use malachite_base::test_util::common::test_custom_cmp_helper; use malachite_q::Rational; use malachite_q::arithmetic::traits::SimplestRationalInInterval; use malachite_q::test_util::arithmetic::simplest_rational_in_interval::*; use malachite_q::test_util::generators::{ rational_gen, rational_pair_gen, rational_pair_gen_var_3, rational_pair_gen_var_4, rational_pair_gen_var_5, rational_pair_gen_var_6, rational_triple_gen, rational_triple_gen_var_2, rational_triple_gen_var_3, }; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_cmp_complexity() { let strings = &["0", "1", "-1", "1/2", "-1/2", "5/2", "1/100", "99/100", "-99/100"]; test_custom_cmp_helper::(strings, Rational::cmp_complexity); } #[test] fn test_simplest_rational_in_open_interval() { let test = |x, y, out| { let x = Rational::from_str(x).unwrap(); let y = Rational::from_str(y).unwrap(); assert_eq!( Rational::simplest_rational_in_open_interval(&x, &y).to_string(), out ); assert_eq!( simplest_rational_in_open_interval_explicit(&x, &y).to_string(), out ); assert_eq!( simplest_rational_in_open_interval_naive(&x, &y).to_string(), out ); }; test("0", "2", "1"); test("0", "1", "1/2"); test("-1", "1", "0"); test("-9", "10", "0"); test("0", "1/2", "1/3"); test("1/2", "1", "2/3"); test("0", "1/3", "1/4"); test("1/3", "1", "1/2"); test("1/3", "1/2", "2/5"); test("157/50", "63/20", "22/7"); test("2/3", "1", "3/4"); test("1/2", "2/3", "3/5"); test("1/2", "3/5", "4/7"); test("3/5", "2/3", "5/8"); test("2/3", "3/4", "5/7"); } #[test] #[should_panic] fn simplest_rational_in_open_interval_fail_1() { Rational::simplest_rational_in_open_interval(&Rational::ONE, &Rational::ONE); } #[test] #[should_panic] fn simplest_rational_in_open_interval_fail_2() { Rational::simplest_rational_in_open_interval(&Rational::ONE, &Rational::ZERO); } #[test] fn test_simplest_rational_in_closed_interval() { let test = |x, y, out| { let x = Rational::from_str(x).unwrap(); let y = Rational::from_str(y).unwrap(); assert_eq!( Rational::simplest_rational_in_closed_interval(&x, &y).to_string(), out ); }; test("0", "2", "0"); test("0", "1", "0"); test("-1", "1", "0"); test("-9", "10", "0"); test("0", "1/2", "0"); test("1/2", "1", "1"); test("0", "1/3", "0"); test("1/3", "1", "1"); test("1/3", "1/2", "1/2"); test("157/50", "63/20", "22/7"); } #[test] #[should_panic] fn simplest_rational_in_closed_interval_fail() { Rational::simplest_rational_in_closed_interval(&Rational::ONE, &Rational::ZERO); } #[test] fn cmp_complexity_properties() { rational_pair_gen().test_properties(|(x, y)| { let ord = x.cmp_complexity(&y); assert_eq!(y.cmp_complexity(&x).reverse(), ord); assert_eq!(x == y, x.cmp_complexity(&y) == Equal); }); rational_gen().test_properties(|x| { assert_eq!(x.cmp_complexity(&x), Equal); }); rational_triple_gen().test_properties(|(x, y, z)| { if x.cmp_complexity(&y) == Less && y.cmp_complexity(&z) == Less { assert!(x.cmp_complexity(&z) == Less); } else if x.cmp_complexity(&y) == Greater && y.cmp_complexity(&z) == Greater { assert!(x.cmp_complexity(&z) == Greater); } }); } #[test] fn simplest_rational_in_open_interval_properties() { rational_pair_gen_var_3().test_properties(|(x, y)| { let s = Rational::simplest_rational_in_open_interval(&x, &y); assert!(s.is_valid()); assert_eq!(simplest_rational_in_open_interval_explicit(&x, &y), s); assert!(s > x); assert!(s < y); assert_eq!(Rational::simplest_rational_in_open_interval(&-y, &-x), -s); }); rational_pair_gen_var_5().test_properties(|(x, y)| { assert_eq!( simplest_rational_in_open_interval_naive(&x, &y), Rational::simplest_rational_in_open_interval(&x, &y) ); }); rational_triple_gen_var_2().test_properties(|(x, y, z)| { let q = Rational::simplest_rational_in_open_interval(&x, &z); assert!(q.cmp_complexity(&y) <= Equal); }); } #[test] fn simplest_rational_in_closed_interval_properties() { rational_pair_gen_var_4().test_properties(|(x, y)| { let s = Rational::simplest_rational_in_closed_interval(&x, &y); assert!(s.is_valid()); assert!(s >= x); assert!(s <= y); assert_eq!(Rational::simplest_rational_in_closed_interval(&-y, &-x), -s); }); rational_pair_gen_var_6().test_properties(|(x, y)| { assert_eq!( Rational::simplest_rational_in_closed_interval(&x, &y), simplest_rational_in_closed_interval_naive(&x, &y) ); }); rational_triple_gen_var_3().test_properties(|(x, y, z)| { let q = Rational::simplest_rational_in_closed_interval(&x, &z); assert!(q.cmp_complexity(&y) <= Equal); }); rational_gen().test_properties(|x| { assert_eq!(Rational::simplest_rational_in_closed_interval(&x, &x), x); }); } ================================================ FILE: malachite-q/tests/arithmetic/sqrt.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CheckedSqrt, Reciprocal, Square}; use malachite_base::num::basic::traits::NegativeOne; use malachite_nz::test_util::generators::integer_gen_var_4; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen_var_3; use std::str::FromStr; #[test] fn test_checked_sqrt() { let test = |s, out: Option<&str>| { let n = Rational::from_str(s).unwrap(); let out = out.map(ToString::to_string); assert_eq!(n.clone().checked_sqrt().map(|x| x.to_string()), out); assert_eq!((&n).checked_sqrt().map(|x| x.to_string()), out); }; test("0", Some("0")); test("1", Some("1")); test("2", None); test("3", None); test("4", Some("2")); test("5", None); test("22/7", None); test("4/9", Some("2/3")); } #[test] #[should_panic] fn checked_sqrt_fail() { Rational::NEGATIVE_ONE.checked_sqrt(); } #[test] #[should_panic] fn checked_sqrt_ref_fail() { (&Rational::NEGATIVE_ONE).checked_sqrt(); } #[test] fn checked_sqrt_properties() { rational_gen_var_3().test_properties(|n| { let sqrt = n.clone().checked_sqrt(); assert!(sqrt.as_ref().is_none_or(Rational::is_valid)); let sqrt_alt = (&n).checked_sqrt(); assert!(sqrt_alt.as_ref().is_none_or(Rational::is_valid)); assert_eq!(sqrt_alt, sqrt); if n != 0 { assert_eq!( (&n).reciprocal().checked_sqrt(), sqrt.as_ref().map(Reciprocal::reciprocal) ); } if let Some(sqrt) = sqrt { assert_eq!((&sqrt).square(), n); } }); integer_gen_var_4().test_properties(|n| { assert_eq!( (&n).checked_sqrt().map(Rational::from), Rational::from(n).checked_sqrt() ); }); } ================================================ FILE: malachite-q/tests/arithmetic/square.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, CheckedSqrt, Square, SquareAssign}; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen}; use std::str::FromStr; #[test] fn test_square() { let test = |x, out| { let u = Rational::from_str(x).unwrap(); assert_eq!(u.clone().square().to_string(), out); assert_eq!((&u).square().to_string(), out); let mut x = u; x.square_assign(); assert_eq!(x.to_string(), out); }; test("0", "0"); test("1", "1"); test("10", "100"); test("123", "15129"); test("1/2", "1/4"); test("22/7", "484/49"); test("-1", "1"); test("-10", "100"); test("-123", "15129"); test("-1/2", "1/4"); test("-22/7", "484/49"); } #[test] fn square_properties() { rational_gen().test_properties(|x| { let square = (&x).square(); assert!(square.is_valid()); let mut mut_x = x.clone(); mut_x.square_assign(); assert!(mut_x.is_valid()); assert_eq!(mut_x, square); assert_eq!(&x * &x, square); assert_eq!((-&x).square(), square); assert!(square >= 0); if x != 0 { assert_eq!(square.cmp_abs(&x), x.partial_cmp_abs(&1).unwrap()); } assert_eq!(square.checked_sqrt(), Some(x.abs())); }); rational_pair_gen().test_properties(|(x, y)| { let x_squared = (&x).square(); let y_squared = (&y).square(); let xy = &x * &y; assert_eq!((&x + &y).square(), &x_squared + &y_squared + (&xy << 1)); assert_eq!((&x - &y).square(), &x_squared + &y_squared - (&xy << 1)); assert_eq!(xy.square(), x_squared * y_squared); }); integer_gen().test_properties(|x| { assert_eq!((&x).square(), Rational::from(x).square()); }); } ================================================ FILE: malachite-q/tests/arithmetic/sub.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::arithmetic::sub::sub_naive; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen}; use num::BigRational; use rug; use std::str::FromStr; #[test] fn test_sub() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); let mut n = u.clone(); n -= v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let mut n = u.clone(); n -= &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - v.clone(); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = u.clone() - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = &u - &v; assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = BigRational::from_str(s).unwrap() - BigRational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); let n = rug::Rational::from_str(s).unwrap() - rug::Rational::from_str(t).unwrap(); assert_eq!(n.to_string(), out); }; test("0", "0", "0"); test("0", "-123", "123"); test("123", "0", "123"); test("123", "-456", "579"); test("0", "123", "-123"); test("123", "123", "0"); test("123", "456", "-333"); test("0", "-123", "123"); test("-123", "0", "-123"); test("-123", "-456", "333"); test("0", "123", "-123"); test("-123", "-123", "0"); test("1/2", "-1/3", "5/6"); test("1/2", "1/3", "1/6"); test("-1/2", "-1/3", "-1/6"); test("-1/2", "1/3", "-5/6"); test("1/2", "-1/2", "1"); test("1/2", "1/2", "0"); test("-1/2", "-1/2", "0"); test("-1/2", "1/2", "-1"); } #[allow(clippy::eq_op)] #[test] fn sub_properties() { rational_pair_gen().test_properties(|(x, y)| { let diff_val_val = x.clone() - y.clone(); let diff_val_ref = x.clone() - &y; let diff_ref_val = &x - y.clone(); let diff = &x - &y; assert!(diff_val_val.is_valid()); assert!(diff_val_ref.is_valid()); assert!(diff_ref_val.is_valid()); assert!(diff.is_valid()); assert_eq!(diff_val_val, diff); assert_eq!(diff_val_ref, diff); assert_eq!(diff_ref_val, diff); let mut mut_x = x.clone(); mut_x -= y.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = x.clone(); mut_x -= &y; assert!(mut_x.is_valid()); assert_eq!(mut_x, diff); let mut mut_x = rug::Rational::from(&x); mut_x -= rug::Rational::from(&y); assert_eq!(Rational::from(&mut_x), diff); assert_eq!( Rational::from(&(BigRational::from(&x) - BigRational::from(&y))), diff ); assert_eq!( Rational::from(&(rug::Rational::from(&x) - rug::Rational::from(&y))), diff ); assert_eq!(sub_naive(x.clone(), y.clone()), diff); assert_eq!(&y - &x, -&diff); assert_eq!(&diff + &y, x); assert_eq!(x - diff, y); }); rational_gen().test_properties(|ref x| { assert_eq!(x - Rational::ZERO, *x); assert_eq!(Rational::ZERO - x, -x); assert_eq!(x - -x, x << 1); assert_eq!(x - x, 0); }); integer_pair_gen().test_properties(|(x, y)| { if x >= y { assert_eq!(&x - &y, Rational::from(x) - Rational::from(y)); } else { assert_eq!(-(&y - &x), Rational::from(x) - Rational::from(y)); } }); } ================================================ FILE: malachite-q/tests/basic/constants.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{NegativeOne, One, OneHalf, Two, Zero}; use malachite_q::Rational; #[test] fn test_zero() { let zero = Rational::ZERO; assert!(zero.is_valid()); assert_eq!(zero, 0); assert_eq!(zero.to_string(), "0"); } #[test] fn test_one() { let one = Rational::ONE; assert!(one.is_valid()); assert_eq!(one, 1); assert_eq!(one.to_string(), "1"); } #[test] fn test_two() { let two = Rational::TWO; assert!(two.is_valid()); assert_eq!(two, 2); assert_eq!(two.to_string(), "2"); } #[test] fn test_negative_one() { let negative_one = Rational::NEGATIVE_ONE; assert!(negative_one.is_valid()); assert_eq!(negative_one, -1); assert_eq!(negative_one.to_string(), "-1"); } #[test] fn test_one_half() { let one_half = Rational::ONE_HALF; assert!(one_half.is_valid()); assert_eq!(one_half.to_string(), "1/2"); } ================================================ FILE: malachite-q/tests/basic/default.rs ================================================ // Copyright © 2026 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 malachite_q::Rational; #[test] fn test_default() { let default = Rational::default(); assert!(default.is_valid()); assert_eq!(default, 0); assert_eq!(default.to_string(), "0"); } ================================================ FILE: malachite-q/tests/basic/named.rs ================================================ // Copyright © 2026 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 malachite_base::named::Named; use malachite_q::Rational; #[test] fn test_named() { assert_eq!(Rational::NAME, "Rational"); } ================================================ FILE: malachite-q/tests/basic/significant_bits.rs ================================================ // Copyright © 2026 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 malachite_base::num::logic::traits::SignificantBits; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use std::str::FromStr; #[test] fn test_significant_bits() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().significant_bits(), out); }; test("0", 1); test("1", 2); test("-1", 2); test("2/3", 4); test("-2/3", 4); test("100/101", 14); test("-100/101", 14); test("22/7", 8); test("-22/7", 8); } #[test] fn significant_bits_properties() { rational_gen().test_properties(|x| { let bits = x.significant_bits(); assert!(bits > 0); assert_eq!((-x).significant_bits(), bits); }); integer_gen().test_properties(|n| { assert_eq!( Rational::from(&n).significant_bits(), n.significant_bits() + 1 ); }); } ================================================ FILE: malachite-q/tests/basic/size.rs ================================================ // Copyright © 2026 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 malachite_q::Rational; use std::mem::size_of; #[test] fn test_size() { if size_of::() == 8 { assert_eq!(size_of::(), 56); } } ================================================ FILE: malachite-q/tests/comparison/cmp.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::test_cmp_helper; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen, rational_triple_gen}; use num::BigRational; use std::cmp::Ordering::*; #[test] fn test_cmp() { let strings = &[ "-1000000000001", "-1000000000000", "-999999999999", "-123", "-2", "-7/5", "-1", "-5/7", "-3/8", "-123/1000000", "-1237/1000000000000", "0", "1237/1000000000000", "123/1000000", "3/8", "5/7", "1", "7/5", "2", "123", "999999999999", "1000000000000", "1000000000001", ]; test_cmp_helper::(strings); test_cmp_helper::(strings); test_cmp_helper::(strings); } #[test] fn cmp_properties() { rational_pair_gen().test_properties(|(x, y)| { let ord = x.cmp(&y); assert_eq!(BigRational::from(&x).cmp(&BigRational::from(&y)), ord); assert_eq!(rug::Rational::from(&x).cmp(&rug::Rational::from(&y)), ord); assert_eq!(y.cmp(&x).reverse(), ord); assert_eq!(x == y, x.cmp(&y) == Equal); assert_eq!((-y).cmp(&-x), ord); }); rational_gen().test_properties(|x| { assert_eq!(x.cmp(&x), Equal); }); rational_triple_gen().test_properties(|(x, y, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).cmp(&Rational::from(&y)), x.cmp(&y)); }); } ================================================ FILE: malachite-q/tests/comparison/cmp_abs.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::test_util::common::test_custom_cmp_helper; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen, rational_triple_gen}; use rug; use std::cmp::Ordering::*; #[test] fn test_ord_abs() { let strings = &[ "0", "1237/1000000000000", "-123/1000000", "3/8", "-5/7", "1", "-7/5", "2", "-123", "999999999999", "-1000000000000", "1000000000001", ]; test_custom_cmp_helper::(strings, OrdAbs::cmp_abs); test_custom_cmp_helper::(strings, rug::Rational::cmp_abs); } #[test] fn cmp_abs_properties() { rational_pair_gen().test_properties(|(x, y)| { let ord = x.cmp_abs(&y); assert_eq!( rug::Rational::from(&x).cmp_abs(&rug::Rational::from(&y)), ord ); assert_eq!((&x).abs().cmp(&(&y).abs()), ord); assert_eq!((-x).cmp_abs(&(-y)), ord); }); rational_gen().test_properties(|x| { assert_eq!(x.cmp_abs(&x), Equal); assert_eq!(x.cmp_abs(&-&x), Equal); }); rational_triple_gen().test_properties(|(x, y, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!( Rational::from(&x).cmp_abs(&Rational::from(&y)), x.cmp_abs(&y) ); }); } ================================================ FILE: malachite-q/tests/comparison/eq.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::common::test_eq_helper; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen, rational_triple_gen}; use num::BigRational; use rug; #[test] fn test_eq() { let strings = &[ "-1000000000001", "-1000000000000", "-999999999999", "-123", "-2", "-7/5", "-1", "-5/7", "-3/8", "-123/1000000", "-1237/1000000000000", "0", "1237/1000000000000", "123/1000000", "3/8", "5/7", "1", "7/5", "2", "123", "999999999999", "1000000000000", "1000000000001", ]; test_eq_helper::(strings); test_eq_helper::(strings); test_eq_helper::(strings); } #[allow(clippy::cmp_owned, clippy::eq_op)] #[test] fn eq_properties() { rational_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(BigRational::from(&x) == BigRational::from(&y), eq); assert_eq!(rug::Rational::from(&x) == rug::Rational::from(&y), eq); assert_eq!(y == x, eq); }); rational_gen().test_properties(|x| { assert_eq!(x, x); }); rational_triple_gen().test_properties(|(x, y, z)| { if x == y && y == z { assert_eq!(x, z); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) == Rational::from(&y), x == y); assert_eq!(Rational::from(&x) == y, x == y); assert_eq!(x == Rational::from(&y), x == y); }); } ================================================ FILE: malachite-q/tests/comparison/eq_abs.rs ================================================ // Copyright © 2026 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 core::cmp::Ordering::*; use malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{EqAbs, OrdAbs}; use malachite_base::test_util::generators::signed_pair_gen; use malachite_nz::platform::SignedLimb; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen, rational_triple_gen}; use std::str::FromStr; #[test] fn test_eq_abs() { let test = |s, t, eq: bool| { let u = Rational::from_str(s).unwrap(); let v = Rational::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == (&v).abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("123", "124", false); test("123", "122", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("1000000000000", "0", false); test("22/7", "0", false); test("22/7", "22/7", true); test("22/7", "23/7", false); test("-123", "123", true); test("-123", "124", false); test("-123", "122", false); test("-1000000000000", "123", false); test("-123", "1000000000000", false); test("-1000000000000", "1000000000000", true); test("-1000000000000", "0", false); test("-22/7", "0", false); test("-22/7", "22/7", true); test("-22/7", "23/7", false); test("0", "-5", false); test("123", "-123", true); test("123", "-124", false); test("123", "-122", false); test("1000000000000", "-123", false); test("123", "-1000000000000", false); test("1000000000000", "-1000000000000", true); test("22/7", "-22/7", true); test("22/7", "-23/7", false); test("-123", "-123", true); test("-123", "-124", false); test("-123", "-122", false); test("-1000000000000", "-123", false); test("-123", "-1000000000000", false); test("-1000000000000", "-1000000000000", true); test("-22/7", "-22/7", true); test("-22/7", "-23/7", false); } #[allow(clippy::cmp_owned, clippy::eq_op)] #[test] fn eq_properties() { rational_pair_gen().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == (&y).abs(), eq); assert_eq!(x.cmp_abs(&y) == Equal, eq); assert_eq!(x.eq_abs(&-&y), eq); assert_eq!((-&x).eq_abs(&y), eq); assert_eq!((-x).eq_abs(&-y), eq); }); rational_gen().test_properties(|x| { assert!(x.eq_abs(&x)); }); rational_triple_gen().test_properties(|(x, y, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) == Rational::from(&y), x == y); assert_eq!(Rational::from(&x) == y, x == y); assert_eq!(x == Rational::from(&y), x == y); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Rational::from(x).eq_abs(&Rational::from(y)), x.eq_abs(&y)); }); } ================================================ FILE: malachite-q/tests/comparison/eq_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_integer_integer_triple_gen, rational_integer_pair_gen, rational_rational_integer_triple_gen, }; use std::str::FromStr; #[test] fn test_eq_abs_rational_integer() { let test = |s, t, eq: bool| { let u = Rational::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == (&v).abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("123", "124", false); test("123", "122", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("1000000000000", "0", false); test("22/7", "0", false); test("22/7", "123", false); test("-22/7", "123", false); test("-123", "123", true); test("-123", "124", false); test("-123", "122", false); test("-1000000000000", "123", false); test("-123", "1000000000000", false); test("-1000000000000", "1000000000000", true); test("-1000000000000", "0", false); test("0", "-5", false); test("123", "-123", true); test("123", "-124", false); test("123", "-122", false); test("1000000000000", "-123", false); test("123", "-1000000000000", false); test("1000000000000", "-1000000000000", true); test("22/7", "-123", false); test("-22/7", "-123", false); test("-123", "-123", true); test("-123", "-124", false); test("-123", "-122", false); test("-1000000000000", "-123", false); test("-123", "-1000000000000", false); test("-1000000000000", "-1000000000000", true); } #[test] fn eq_abs_integer_properties() { rational_integer_pair_gen().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.eq_abs(&Rational::from(&y)), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == (&y).abs(), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!((-&x).eq_abs(&y), eq); assert_eq!(x.eq_abs(&-&y), eq); assert_eq!((-x).eq_abs(&-y), eq); }); rational_rational_integer_triple_gen().test_properties(|(x, z, y)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); rational_integer_integer_triple_gen().test_properties(|(y, x, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Rational::from(&y)), x.eq_abs(&y)); }); } ================================================ FILE: malachite-q/tests/comparison/eq_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::EqAbs; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_natural_natural_triple_gen, rational_natural_pair_gen, rational_rational_natural_triple_gen, }; use std::str::FromStr; #[test] fn test_eq_abs_rational_natural() { let test = |s, t, eq: bool| { let u = Rational::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("123", "124", false); test("123", "122", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("1000000000000", "0", false); test("22/7", "0", false); test("22/7", "123", false); test("-22/7", "123", false); test("-123", "123", true); test("-123", "124", false); test("-123", "122", false); test("-1000000000000", "123", false); test("-123", "1000000000000", false); test("-1000000000000", "1000000000000", true); test("-1000000000000", "0", false); } #[test] fn eq_abs_natural_properties() { rational_natural_pair_gen().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.eq_abs(&Rational::from(&y)), eq); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == y, eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!((-x).eq_abs(&y), eq); }); rational_rational_natural_triple_gen().test_properties(|(x, z, y)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert!(x.eq_abs(&z)); } }); rational_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x.eq_abs(&y) && y.eq_abs(&z) { assert_eq!(x, z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Rational::from(&y)), x == y); }); } ================================================ FILE: malachite-q/tests/comparison/eq_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_primitive_float_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_f32() { let test = |u, v: f32, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("3/2", 1.5, true); test("3/2", -1.5, true); test("3/2", 2.5, false); test("3/2", -2.5, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f32::INFINITY, false); test("1", f32::NEGATIVE_INFINITY, false); test("1", f32::NAN, false); test("-3/2", 1.5, true); test("-3/2", -1.5, true); test("-3/2", 2.5, false); test("-3/2", -2.5, false); test("-1000000000000", 123.0, false); test("-1000000000000", -123.0, false); test("-1", 0.5, false); test("-1", -0.5, false); test("-1", f32::INFINITY, false); test("-1", f32::NEGATIVE_INFINITY, false); test("-1", f32::NAN, false); } #[test] fn test_eq_abs_f64() { let test = |u, v: f64, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("3/2", 1.5, true); test("3/2", -1.5, true); test("3/2", 2.5, false); test("3/2", -2.5, false); test("1000000000000", 123.0, false); test("1000000000000", -123.0, false); test("1", 0.5, false); test("1", -0.5, false); test("1", f64::INFINITY, false); test("1", f64::NEGATIVE_INFINITY, false); test("1", f64::NAN, false); test("-3/2", 1.5, true); test("-3/2", -1.5, true); test("-3/2", 2.5, false); test("-3/2", -2.5, false); test("-1000000000000", 123.0, false); test("-1000000000000", -123.0, false); test("-1", 0.5, false); test("-1", -0.5, false); test("-1", f64::INFINITY, false); test("-1", f64::NEGATIVE_INFINITY, false); test("-1", f64::NAN, false); } fn eq_abs_primitive_float_properties_helper< T: EqAbs + PartialEq + PrimitiveFloat, >() where Rational: EqAbs + PartialEq + PartialOrdAbs, { rational_primitive_float_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == y.abs(), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); rational_gen().test_properties(|n| { assert_ne!(n, T::NAN); assert_ne!(n, T::INFINITY); assert_ne!(n, T::NEGATIVE_INFINITY); }); } #[test] fn eq_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(eq_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-q/tests/comparison/eq_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_pair_gen_var_7, unsigned_pair_gen_var_27}; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_signed_pair_gen, rational_unsigned_pair_gen}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_eq_abs_u32() { let test = |u, v: u32, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 123, false); test("-123", 123, true); test("-123", 5, false); test("-1000000000000", 123, false); test("22/7", 123, false); test("-22/7", 123, false); } #[test] fn test_eq_abs_u64() { let test = |u, v: u64, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v, eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-123", 123, true); test("-123", 5, false); test("-1000000000000", 1000000000000, true); test("-1000000000000", 1000000000001, false); test("-1000000000000000000000000", 1000000000000, false); test("22/7", 1000000000000, false); test("-22/7", 1000000000000, false); } #[test] fn test_eq_abs_i32() { let test = |u, v: i32, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 123, false); test("-123", 123, true); test("-123", -123, true); test("-123", 5, false); test("-1000000000000", 123, false); test("22/7", 123, false); test("-22/7", 123, false); } #[test] fn test_eq_abs_i64() { let test = |u, v: i64, eq: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.eq_abs(&v), eq); assert_eq!(u.ne_abs(&v), !eq); assert_eq!((&u).abs() == v.unsigned_abs(), eq); assert_eq!(v.eq_abs(&u), eq); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("123", -123, true); test("123", 5, false); test("1000000000000", 1000000000000, true); test("1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-123", 123, true); test("-123", -123, true); test("-123", 5, false); test("-1000000000000", 1000000000000, true); test("-1000000000000", 1000000000001, false); test("-1000000000000000000000000", 1000000000000, false); test("22/7", 1000000000000, false); test("-22/7", 1000000000000, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn eq_abs_primitive_int_properties_helper_unsigned< T: EqAbs + PartialEq + PrimitiveUnsigned, >() where Rational: EqAbs + PartialEq + From + PartialEq + PartialOrdAbs, { rational_unsigned_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs().eq_abs(&y), eq); assert_eq!(y.eq_abs(&x), eq); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Rational::from(x).eq_abs(&y), x == y); assert_eq!(x.eq_abs(&Rational::from(y)), x == y); }); } fn eq_abs_primitive_int_properties_helper_signed + PrimitiveSigned>() where Rational: EqAbs + PartialEq<::Output> + From + TryFrom + PartialOrdAbs, { rational_signed_pair_gen::().test_properties(|(x, y)| { let eq = x.eq_abs(&y); assert_eq!(x.ne_abs(&y), !eq); assert_eq!((&x).abs() == y.unsigned_abs(), eq); assert_eq!( >::eq_abs(&x, &Rational::from(y)), eq ); assert_eq!(y.eq_abs(&x), eq); assert_eq!( >::eq_abs(&Rational::from(y), &x), eq ); assert_eq!(x.partial_cmp_abs(&y) == Some(Equal), eq); }); signed_pair_gen_var_7::().test_properties(|(x, y)| { assert_eq!(Rational::exact_from(x).eq_abs(&y), x.eq_abs(&y)); assert_eq!(x.eq_abs(&Rational::exact_from(y)), x.eq_abs(&y)); }); } #[test] fn eq_abs_primitive_int_properties() { apply_fn_to_unsigneds!(eq_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(eq_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-q/tests/comparison/hash.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::hash::hash; use malachite_q::test_util::generators::rational_gen; #[test] fn hash_properties() { rational_gen().test_properties(|x| { assert_eq!(hash(&x), hash(&x.clone())); }); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_abs_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_integer_integer_triple_gen, rational_integer_pair_gen, rational_rational_integer_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_rational_integer() { let test = |s, t, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&(&v).abs()), cmp); assert_eq!(v.partial_cmp_abs(&u).map(Ordering::reverse), cmp); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", "0", Some(Equal), false, false, true, true); test("0", "5", Some(Less), true, false, true, false); test("123", "123", Some(Equal), false, false, true, true); test("123", "124", Some(Less), true, false, true, false); test("123", "122", Some(Greater), false, true, false, true); test( "1000000000000", "123", Some(Greater), false, true, false, true, ); test("123", "1000000000000", Some(Less), true, false, true, false); test( "1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "0", Some(Greater), false, true, false, true, ); test("0", "-5", Some(Less), true, false, true, false); test("-123", "-123", Some(Equal), false, false, true, true); test("-123", "-124", Some(Less), true, false, true, false); test("-123", "-122", Some(Greater), false, true, false, true); test( "-1000000000000", "-123", Some(Greater), false, true, false, true, ); test( "-123", "-1000000000000", Some(Less), true, false, true, false, ); test( "-1000000000000", "-1000000000000", Some(Equal), false, false, true, true, ); test( "1000000000000", "-1000000000000", Some(Equal), false, false, true, true, ); test( "1000000000000", "0", Some(Greater), false, true, false, true, ); test("99/100", "1", Some(Less), true, false, true, false); test("101/100", "1", Some(Greater), false, true, false, true); test("22/7", "3", Some(Greater), false, true, false, true); test("22/7", "4", Some(Less), true, false, true, false); test("-99/100", "-1", Some(Less), true, false, true, false); test("-101/100", "-1", Some(Greater), false, true, false, true); test("-22/7", "-3", Some(Greater), false, true, false, true); test("-22/7", "-4", Some(Less), true, false, true, false); } #[test] fn partial_cmp_abs_integer_properties() { rational_integer_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp(&(&y).abs()), cmp); assert_eq!(x.cmp_abs(&Rational::from(&y)), cmp.unwrap()); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); }); rational_rational_integer_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); rational_integer_integer_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).partial_cmp_abs(&y), Some(x.cmp_abs(&y))); assert_eq!(x.partial_cmp_abs(&Rational::from(&y)), Some(x.cmp_abs(&y))); }); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_abs_natural.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_natural_natural_triple_gen, rational_natural_pair_gen, rational_rational_natural_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_rational_natural() { let test = |s, t, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u).map(Ordering::reverse), cmp); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", "0", Some(Equal), false, false, true, true); test("0", "5", Some(Less), true, false, true, false); test("123", "123", Some(Equal), false, false, true, true); test("123", "124", Some(Less), true, false, true, false); test("123", "122", Some(Greater), false, true, false, true); test( "1000000000000", "123", Some(Greater), false, true, false, true, ); test("123", "1000000000000", Some(Less), true, false, true, false); test( "1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "1000000000000", Some(Equal), false, false, true, true, ); test( "-1000000000000", "0", Some(Greater), false, true, false, true, ); test("99/100", "1", Some(Less), true, false, true, false); test("101/100", "1", Some(Greater), false, true, false, true); test("22/7", "3", Some(Greater), false, true, false, true); test("22/7", "4", Some(Less), true, false, true, false); test("-99/100", "1", Some(Less), true, false, true, false); test("-101/100", "1", Some(Greater), false, true, false, true); test("-22/7", "3", Some(Greater), false, true, false, true); test("-22/7", "4", Some(Less), true, false, true, false); } #[test] fn partial_cmp_abs_natural_properties() { rational_natural_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!((&x).abs().partial_cmp(&y), cmp); assert_eq!(x.cmp_abs(&Rational::from(&y)), cmp.unwrap()); assert_eq!(y.partial_cmp_abs(&x), cmp.map(Ordering::reverse)); }); rational_rational_natural_triple_gen().test_properties(|(x, z, y)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x.lt_abs(&z)); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x.gt_abs(&z)); } }); rational_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x.lt_abs(&y) && y.lt_abs(&z) { assert!(x < z); } else if x.gt_abs(&y) && y.gt_abs(&z) { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).partial_cmp_abs(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp_abs(&Rational::from(&y)), Some(x.cmp(&y))); }); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_abs_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Abs; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_base::num::conversion::traits::ExactFrom; use malachite_q::Rational; use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; use malachite_q::test_util::generators::{ rational_gen, rational_primitive_float_pair_gen, rational_primitive_float_primitive_float_triple_gen, rational_rational_primitive_float_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_primitive_float() { let test = |u, v: f32, cmp: Option| { let u = Rational::from_str(u).unwrap(); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp_rev); let v = f64::from(v); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp_rev); }; test("2/3", f32::NAN, None); test("2/3", f32::INFINITY, Some(Less)); test("2/3", f32::NEGATIVE_INFINITY, Some(Less)); test("-2/3", f32::NAN, None); test("-2/3", f32::INFINITY, Some(Less)); test("-2/3", f32::NEGATIVE_INFINITY, Some(Less)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Less)); test("3/2", 1.5, Some(Equal)); test("3/2", 5.0, Some(Less)); test("3/2", -5.0, Some(Less)); test("-3/2", 5.0, Some(Less)); test("-3/2", -5.0, Some(Less)); test("-3/2", -1.5, Some(Equal)); test("1/3", 0.333, Some(Greater)); test("1/3", 0.334, Some(Less)); test("1/3", -0.333, Some(Greater)); test("1/3", -0.334, Some(Less)); test("-1/3", -0.334, Some(Less)); test("-1/3", -0.333, Some(Greater)); test("-1/3", 0.334, Some(Less)); test("-1/3", 0.333, Some(Greater)); } fn partial_cmp_abs_primitive_float_properties_helper + PrimitiveFloat>() where Rational: TryFrom + PartialOrd + PartialOrdAbs, { rational_primitive_float_pair_gen::().test_properties(|(n, u)| { let cmp_abs = n.partial_cmp_abs(&u); let cmp_abs_rev = cmp_abs.map(Ordering::reverse); assert_eq!(u.partial_cmp_abs(&n), cmp_abs_rev); assert_eq!((&n).abs().partial_cmp(&u.abs()), cmp_abs); if u.is_finite() { assert_eq!(n.cmp_abs(&Rational::exact_from(u)), cmp_abs.unwrap()); } }); rational_rational_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); rational_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u.abs() < v.abs()); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u.abs() > v.abs()); } }); rational_gen().test_properties(|x| { assert!(x.ge_abs(&T::ZERO)); assert!(x.lt_abs(&T::NEGATIVE_INFINITY)); assert!(x.lt_abs(&T::INFINITY)); }); } #[test] fn partial_cmp_abs_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_abs_primitive_float_properties_helper); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_abs_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{integer_pair_gen, natural_pair_gen}; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_rational_signed_triple_gen, rational_rational_unsigned_triple_gen, rational_signed_pair_gen, rational_signed_signed_triple_gen, rational_unsigned_pair_gen, rational_unsigned_unsigned_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_abs_u32() { let test = |s, v: u32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(s).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test("99/100", 1, Some(Less), true, false, true, false); test("101/100", 1, Some(Greater), false, true, false, true); test("22/7", 3, Some(Greater), false, true, false, true); test("22/7", 4, Some(Less), true, false, true, false); test("-99/100", 1, Some(Less), true, false, true, false); test("-101/100", 1, Some(Greater), false, true, false, true); test("-22/7", 3, Some(Greater), false, true, false, true); test("-22/7", 4, Some(Less), true, false, true, false); } #[test] fn test_partial_cmp_abs_u64() { let test = |u, v: u64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test("99/100", 1, Some(Less), true, false, true, false); test("101/100", 1, Some(Greater), false, true, false, true); test("22/7", 3, Some(Greater), false, true, false, true); test("22/7", 4, Some(Less), true, false, true, false); test("-99/100", 1, Some(Less), true, false, true, false); test("-101/100", 1, Some(Greater), false, true, false, true); test("-22/7", 3, Some(Greater), false, true, false, true); test("-22/7", 4, Some(Less), true, false, true, false); } #[test] fn test_partial_cmp_abs_i32() { let test = |u, v: i32, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("-123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("-123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test("-123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", -123, Some(Greater), false, true, false, true, ); test("99/100", 1, Some(Less), true, false, true, false); test("101/100", 1, Some(Greater), false, true, false, true); test("22/7", 3, Some(Greater), false, true, false, true); test("22/7", 4, Some(Less), true, false, true, false); test("-99/100", -1, Some(Less), true, false, true, false); test("-101/100", -1, Some(Greater), false, true, false, true); test("-22/7", -3, Some(Greater), false, true, false, true); test("-22/7", -4, Some(Less), true, false, true, false); } #[test] fn test_partial_cmp_abs_i64() { let test = |u, v: i64, cmp, lt: bool, gt: bool, le: bool, ge: bool| { let u = Rational::from_str(u).unwrap(); assert_eq!(u.partial_cmp_abs(&v), cmp); assert_eq!((&u).abs().partial_cmp(&v.abs()), cmp); assert_eq!(v.partial_cmp_abs(&u), cmp.map(Ordering::reverse)); assert_eq!(lt, u.lt_abs(&v)); assert_eq!(gt, u.gt_abs(&v)); assert_eq!(le, u.le_abs(&v)); assert_eq!(ge, u.ge_abs(&v)); assert_eq!(lt, v.gt_abs(&u)); assert_eq!(gt, v.lt_abs(&u)); assert_eq!(le, v.ge_abs(&u)); assert_eq!(ge, v.le_abs(&u)); }; test("0", 0, Some(Equal), false, false, true, true); test("0", 5, Some(Less), true, false, true, false); test("0", -5, Some(Less), true, false, true, false); test("123", 123, Some(Equal), false, false, true, true); test("123", -123, Some(Equal), false, false, true, true); test("-123", 123, Some(Equal), false, false, true, true); test("-123", -123, Some(Equal), false, false, true, true); test("123", 124, Some(Less), true, false, true, false); test("123", -124, Some(Less), true, false, true, false); test("-123", 124, Some(Less), true, false, true, false); test("-123", -124, Some(Less), true, false, true, false); test("123", 122, Some(Greater), false, true, false, true); test("123", -122, Some(Greater), false, true, false, true); test("-123", 122, Some(Greater), false, true, false, true); test("-123", -122, Some(Greater), false, true, false, true); test( "1000000000000", 123, Some(Greater), false, true, false, true, ); test( "1000000000000", -123, Some(Greater), false, true, false, true, ); test( "-1000000000000", 123, Some(Greater), false, true, false, true, ); test( "-1000000000000", -123, Some(Greater), false, true, false, true, ); test( "1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", -1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", 1000000000000, Some(Equal), false, false, true, true, ); test( "-1000000000000", -1000000000000, Some(Equal), false, false, true, true, ); test( "1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "1000000000000", -1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", 1000000000001, Some(Less), true, false, true, false, ); test( "-1000000000000", -1000000000001, Some(Less), true, false, true, false, ); test("99/100", 1, Some(Less), true, false, true, false); test("101/100", 1, Some(Greater), false, true, false, true); test("22/7", 3, Some(Greater), false, true, false, true); test("22/7", 4, Some(Less), true, false, true, false); test("-99/100", -1, Some(Less), true, false, true, false); test("-101/100", -1, Some(Greater), false, true, false, true); test("-22/7", -3, Some(Greater), false, true, false, true); test("-22/7", -4, Some(Less), true, false, true, false); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_abs_primitive_int_properties_helper_unsigned< T: PartialOrdAbs + PartialOrd + PrimitiveUnsigned, >() where Rational: From + for<'a> From<&'a Natural> + PartialOrdAbs + PartialOrd + PartialOrdAbs, { rational_unsigned_pair_gen::().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!(Some(x.cmp_abs(&Rational::from(y))), cmp); assert_eq!((&x).abs().partial_cmp(&y), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(y.partial_cmp_abs(&x), cmp_rev); assert_eq!(Some(Rational::from(y).cmp_abs(&x)), cmp_rev); }); rational_rational_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n.lt_abs(&u) && u.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&u) && u.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); rational_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u.lt_abs(&n) && n.lt_abs(&v) { assert!(u < v); } else if u.gt_abs(&n) && n.gt_abs(&v) { assert!(u > v); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!( PartialOrdAbs::::partial_cmp_abs(&Rational::from(&x), &y), Some(x.cmp(&y)) ); assert_eq!(x.partial_cmp_abs(&Rational::from(&y)), Some(x.cmp(&y))); }); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_abs_primitive_int_properties_helper_signed< T: PartialOrdAbs + PartialOrd + PrimitiveSigned, >() where Rational: From + for<'a> From<&'a Integer> + PartialOrdAbs + PartialOrd<::Output>, ::Output: PartialOrd, { rational_signed_pair_gen::().test_properties(|(x, y)| { let cmp = x.partial_cmp_abs(&y); assert_eq!(Some(x.cmp_abs(&Rational::from(y))), cmp); assert_eq!((&x).abs().partial_cmp(&y.unsigned_abs()), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(y.partial_cmp_abs(&x), cmp_rev); assert_eq!(Some(Rational::from(y).cmp_abs(&x)), cmp_rev); }); rational_rational_signed_triple_gen::().test_properties(|(n, m, i)| { if n.lt_abs(&i) && i.lt_abs(&m) { assert_eq!(n.cmp_abs(&m), Less); } else if n.gt_abs(&i) && i.gt_abs(&m) { assert_eq!(n.cmp_abs(&m), Greater); } }); rational_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i.lt_abs(&n) && n.lt_abs(&j) { assert!(i.lt_abs(&j)); } else if i.gt_abs(&n) && n.gt_abs(&j) { assert!(i.gt_abs(&j)); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!( PartialOrdAbs::::partial_cmp_abs(&Rational::from(&x), &y), Some(x.cmp_abs(&y)) ); assert_eq!(x.partial_cmp_abs(&Rational::from(&y)), Some(x.cmp_abs(&y))); }); } #[test] fn partial_cmp_abs_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_abs_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_abs_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_integer.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_integer_integer_triple_gen, rational_integer_pair_gen, rational_rational_integer_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_integer() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u).map(Ordering::reverse), out); }; test("0", "0", Some(Equal)); test("0", "5", Some(Less)); test("123", "123", Some(Equal)); test("123", "124", Some(Less)); test("123", "122", Some(Greater)); test("1000000000000", "123", Some(Greater)); test("123", "1000000000000", Some(Less)); test("1000000000000", "1000000000000", Some(Equal)); test("-1000000000000", "1000000000000", Some(Less)); test("-1000000000000", "0", Some(Less)); test("0", "-5", Some(Greater)); test("-123", "-123", Some(Equal)); test("-123", "-124", Some(Greater)); test("-123", "-122", Some(Less)); test("-1000000000000", "-123", Some(Less)); test("-123", "-1000000000000", Some(Greater)); test("-1000000000000", "-1000000000000", Some(Equal)); test("1000000000000", "-1000000000000", Some(Greater)); test("1000000000000", "0", Some(Greater)); test("99/100", "1", Some(Less)); test("101/100", "1", Some(Greater)); test("22/7", "3", Some(Greater)); test("22/7", "4", Some(Less)); test("-99/100", "-1", Some(Greater)); test("-101/100", "-1", Some(Less)); test("-22/7", "-3", Some(Less)); test("-22/7", "-4", Some(Greater)); } #[test] fn partial_cmp_integer_properties() { rational_integer_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp(&y); assert_eq!(x.cmp(&Rational::from(&y)), cmp.unwrap()); assert_eq!( rug::Rational::from(&x).partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); }); rational_rational_integer_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); rational_integer_integer_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Rational::from(&y)), Some(x.cmp(&y))); }); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_natural_natural_triple_gen, rational_natural_pair_gen, rational_rational_natural_triple_gen, }; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_natural() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u).map(Ordering::reverse), out); }; test("0", "0", Some(Equal)); test("0", "5", Some(Less)); test("123", "123", Some(Equal)); test("123", "124", Some(Less)); test("123", "122", Some(Greater)); test("1000000000000", "123", Some(Greater)); test("123", "1000000000000", Some(Less)); test("1000000000000", "1000000000000", Some(Equal)); test("-1000000000000", "1000000000000", Some(Less)); test("-1000000000000", "0", Some(Less)); test("99/100", "1", Some(Less)); test("101/100", "1", Some(Greater)); test("22/7", "3", Some(Greater)); test("22/7", "4", Some(Less)); test("-99/100", "1", Some(Less)); test("-101/100", "1", Some(Less)); test("-22/7", "3", Some(Less)); test("-22/7", "4", Some(Less)); } #[test] fn partial_cmp_natural_properties() { rational_natural_pair_gen().test_properties(|(x, y)| { let cmp = x.partial_cmp(&y); assert_eq!(x.cmp(&Rational::from(&y)), cmp.unwrap()); assert_eq!( rug::Rational::from(&x).partial_cmp(&rug::Integer::from(&y)), cmp ); assert_eq!(y.partial_cmp(&x), cmp.map(Ordering::reverse)); }); rational_rational_natural_triple_gen().test_properties(|(x, z, y)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); rational_natural_natural_triple_gen().test_properties(|(y, x, z)| { if x < y && y < z { assert!(x < z); } else if x > y && y > z { assert!(x > z); } }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Rational::from(&y)), Some(x.cmp(&y))); }); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::conversion::traits::ExactFrom; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_primitive_float_pair_gen, rational_primitive_float_primitive_float_triple_gen, rational_rational_primitive_float_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_primitive_float() { let test = |u, v: f32, out: Option| { let out_rev = out.map(Ordering::reverse); assert_eq!(Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Rational::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Rational::from_str(u).unwrap()), out_rev); let v = f64::from(v); assert_eq!(Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&Rational::from_str(u).unwrap()), out_rev); assert_eq!(v.partial_cmp(&rug::Rational::from_str(u).unwrap()), out_rev); }; test("2/3", f32::NAN, None); test("2/3", f32::INFINITY, Some(Less)); test("2/3", f32::NEGATIVE_INFINITY, Some(Greater)); test("-2/3", f32::NAN, None); test("-2/3", f32::INFINITY, Some(Less)); test("-2/3", f32::NEGATIVE_INFINITY, Some(Greater)); test("0", 0.0, Some(Equal)); test("0", -0.0, Some(Equal)); test("0", 5.0, Some(Less)); test("0", -5.0, Some(Greater)); test("3/2", 1.5, Some(Equal)); test("3/2", 5.0, Some(Less)); test("3/2", -5.0, Some(Greater)); test("-3/2", 5.0, Some(Less)); test("-3/2", -5.0, Some(Greater)); test("-3/2", -1.5, Some(Equal)); test("1/3", 0.333, Some(Greater)); test("1/3", 0.334, Some(Less)); test("1/3", -0.333, Some(Greater)); test("1/3", -0.334, Some(Greater)); test("-1/3", -0.334, Some(Greater)); test("-1/3", -0.333, Some(Less)); test("-1/3", 0.334, Some(Less)); test("-1/3", 0.333, Some(Less)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_float_properties_helper< T: PartialOrd + PartialOrd + PrimitiveFloat, >() where Rational: TryFrom + PartialOrd, rug::Rational: PartialOrd, { rational_primitive_float_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(rug::Rational::from(&n).partial_cmp(&u), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Rational::from(&n)), cmp_rev); if u.is_finite() { assert_eq!(n.cmp(&Rational::exact_from(u)), cmp.unwrap()); } }); rational_rational_primitive_float_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); rational_primitive_float_primitive_float_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); rational_gen().test_properties(|x| { assert!(x > T::NEGATIVE_INFINITY); assert!(x < T::INFINITY); }); } #[test] fn partial_cmp_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_cmp_primitive_float_properties_helper); } ================================================ FILE: malachite-q/tests/comparison/partial_cmp_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_rational_signed_triple_gen, rational_rational_unsigned_triple_gen, rational_signed_pair_gen, rational_signed_signed_triple_gen, rational_unsigned_pair_gen, rational_unsigned_unsigned_triple_gen, }; use rug; use std::cmp::Ordering::{self, *}; use std::str::FromStr; #[test] fn test_partial_cmp_u32() { let test = |s, v: u32, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(s).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("-123", 123, Some(Less)); test("123", 124, Some(Less)); test("-123", 124, Some(Less)); test("123", 122, Some(Greater)); test("-123", 122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("99/100", 1, Some(Less)); test("101/100", 1, Some(Greater)); test("22/7", 3, Some(Greater)); test("22/7", 4, Some(Less)); test("-99/100", 1, Some(Less)); test("-101/100", 1, Some(Less)); test("-22/7", 3, Some(Less)); test("-22/7", 4, Some(Less)); } #[test] fn test_partial_cmp_u64() { let test = |s, v: u64, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u.partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(s).unwrap().partial_cmp(&v), out); assert_eq!(v.partial_cmp(&u), out.map(Ordering::reverse)); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("123", 123, Some(Equal)); test("-123", 123, Some(Less)); test("123", 124, Some(Less)); test("-123", 124, Some(Less)); test("123", 122, Some(Greater)); test("-123", 122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("1000000000000", 1000000000000, Some(Equal)); test("-1000000000000", 1000000000000, Some(Less)); test("1000000000000", 1000000000001, Some(Less)); test("-1000000000000", 1000000000001, Some(Less)); test("99/100", 1, Some(Less)); test("101/100", 1, Some(Greater)); test("22/7", 3, Some(Greater)); test("22/7", 4, Some(Less)); test("-99/100", 1, Some(Less)); test("-101/100", 1, Some(Less)); test("-22/7", 3, Some(Less)); test("-22/7", 4, Some(Less)); } #[test] fn test_partial_cmp_i32() { let test = |u, v: i32, out| { assert_eq!(Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Rational::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("-123", 123, Some(Less)); test("-123", -123, Some(Equal)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("-123", 124, Some(Less)); test("-123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("-123", 122, Some(Less)); test("-123", -122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("-1000000000000", -123, Some(Less)); test("99/100", 1, Some(Less)); test("101/100", 1, Some(Greater)); test("22/7", 3, Some(Greater)); test("22/7", 4, Some(Less)); test("-99/100", -1, Some(Greater)); test("-101/100", -1, Some(Less)); test("-22/7", -3, Some(Less)); test("-22/7", -4, Some(Greater)); } #[test] fn test_partial_cmp_i64() { let test = |u, v: i64, out| { assert_eq!(Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!(rug::Rational::from_str(u).unwrap().partial_cmp(&v), out); assert_eq!( v.partial_cmp(&Rational::from_str(u).unwrap()), out.map(Ordering::reverse) ); }; test("0", 0, Some(Equal)); test("0", 5, Some(Less)); test("0", -5, Some(Greater)); test("123", 123, Some(Equal)); test("123", -123, Some(Greater)); test("-123", 123, Some(Less)); test("-123", -123, Some(Equal)); test("123", 124, Some(Less)); test("123", -124, Some(Greater)); test("-123", 124, Some(Less)); test("-123", -124, Some(Greater)); test("123", 122, Some(Greater)); test("123", -122, Some(Greater)); test("-123", 122, Some(Less)); test("-123", -122, Some(Less)); test("1000000000000", 123, Some(Greater)); test("1000000000000", -123, Some(Greater)); test("-1000000000000", 123, Some(Less)); test("-1000000000000", -123, Some(Less)); test("1000000000000", 1000000000000, Some(Equal)); test("1000000000000", -1000000000000, Some(Greater)); test("-1000000000000", 1000000000000, Some(Less)); test("-1000000000000", -1000000000000, Some(Equal)); test("1000000000000", 1000000000001, Some(Less)); test("1000000000000", -1000000000001, Some(Greater)); test("-1000000000000", 1000000000001, Some(Less)); test("-1000000000000", -1000000000001, Some(Greater)); test("99/100", 1, Some(Less)); test("101/100", 1, Some(Greater)); test("22/7", 3, Some(Greater)); test("22/7", 4, Some(Less)); test("-99/100", -1, Some(Greater)); test("-101/100", -1, Some(Less)); test("-22/7", -3, Some(Less)); test("-22/7", -4, Some(Greater)); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_unsigned< T: PartialOrd + PartialOrd + PrimitiveUnsigned, >() where Rational: From + PartialOrd, rug::Rational: PartialOrd, { rational_unsigned_pair_gen::().test_properties(|(n, u)| { let cmp = n.partial_cmp(&u); assert_eq!(rug::Rational::from(&n).partial_cmp(&u), cmp); assert_eq!(Some(n.cmp(&Rational::from(u))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(u.partial_cmp(&n), cmp_rev); assert_eq!(u.partial_cmp(&rug::Rational::from(&n)), cmp_rev); assert_eq!(Some(Rational::from(u).cmp(&n)), cmp_rev); }); rational_rational_unsigned_triple_gen::().test_properties(|(n, m, u)| { if n < u && u < m { assert_eq!(n.cmp(&m), Less); } else if n > u && u > m { assert_eq!(n.cmp(&m), Greater); } }); rational_unsigned_unsigned_triple_gen::().test_properties(|(n, u, v)| { if u < n && n < v { assert!(u < v); } else if u > n && n > v { assert!(u > v); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Rational::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Rational::from(y)), Some(x.cmp(&y))); }); } #[allow(clippy::trait_duplication_in_bounds)] fn partial_cmp_primitive_int_properties_helper_signed< T: PartialOrd + PartialOrd + PrimitiveSigned, >() where Rational: From + PartialOrd, rug::Rational: PartialOrd, { rational_signed_pair_gen::().test_properties(|(n, i)| { let cmp = n.partial_cmp(&i); assert_eq!(rug::Rational::from(&n).partial_cmp(&i), cmp); assert_eq!(Some(n.cmp(&Rational::from(i))), cmp); let cmp_rev = cmp.map(Ordering::reverse); assert_eq!(i.partial_cmp(&n), cmp_rev); assert_eq!(i.partial_cmp(&rug::Rational::from(&n)), cmp_rev); assert_eq!(Some(Rational::from(i).cmp(&n)), cmp_rev); }); rational_rational_signed_triple_gen::().test_properties(|(n, m, i)| { if n < i && i < m { assert_eq!(n.cmp(&m), Less); } else if n > i && i > m { assert_eq!(n.cmp(&m), Greater); } }); rational_signed_signed_triple_gen::().test_properties(|(n, i, j)| { if i < n && n < j { assert!(i < j); } else if i > n && n > j { assert!(i > j); } }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Rational::from(x).partial_cmp(&y), Some(x.cmp(&y))); assert_eq!(x.partial_cmp(&Rational::from(y)), Some(x.cmp(&y))); }); } #[test] fn partial_cmp_primitive_int_properties() { apply_fn_to_unsigneds!(partial_cmp_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_cmp_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-q/tests/comparison/partial_eq_integer.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_integer_pair_gen; use rug; use std::str::FromStr; #[test] fn test_rational_partial_eq_integer() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Integer::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!( rug::Rational::from_str(s).unwrap() == rug::Rational::from_str(t).unwrap(), out ); }; test("0", "0", true); test("0", "5", false); test("0", "-5", false); test("123", "123", true); test("123", "-123", false); test("-123", "123", false); test("-123", "-123", true); test("123", "5", false); test("123", "-5", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("-1000000000000", "1000000000000", false); test("-1000000000000", "-1000000000000", true); test("22/7", "3", false); test("1/2", "2", false); test("-1/2", "2", false); test("-1/2", "-2", false); } #[allow(clippy::cmp_owned)] #[test] fn partial_eq_integer_properties() { rational_integer_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(x == Rational::from(&y), eq); assert_eq!(rug::Rational::from(&x) == rug::Integer::from(&y), eq); }); integer_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) == y, x == y); assert_eq!(x == Rational::from(&y), x == y); }); } ================================================ FILE: malachite-q/tests/comparison/partial_eq_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_natural_pair_gen; use rug; use std::str::FromStr; #[test] fn test_rational_partial_eq_natural() { let test = |s, t, out| { let u = Rational::from_str(s).unwrap(); let v = Natural::from_str(t).unwrap(); assert_eq!(u == v, out); assert_eq!(v == u, out); assert_eq!( rug::Rational::from_str(s).unwrap() == rug::Rational::from_str(t).unwrap(), out ); }; test("0", "0", true); test("0", "5", false); test("123", "123", true); test("-123", "123", false); test("123", "5", false); test("1000000000000", "123", false); test("123", "1000000000000", false); test("1000000000000", "1000000000000", true); test("-1000000000000", "1000000000000", false); test("22/7", "3", false); test("1/2", "2", false); test("-1/2", "2", false); } #[allow(clippy::cmp_owned)] #[test] fn partial_eq_natural_properties() { rational_natural_pair_gen().test_properties(|(x, y)| { let eq = x == y; assert_eq!(y == x, eq); assert_eq!(x == Rational::from(&y), eq); assert_eq!(rug::Rational::from(&x) == rug::Integer::from(&y), eq); }); natural_pair_gen().test_properties(|(x, y)| { assert_eq!(Rational::from(&x) == y, x == y); assert_eq!(x == Rational::from(&y), x == y); }); } ================================================ FILE: malachite-q/tests/comparison/partial_eq_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::conversion::traits::ExactFrom; use malachite_q::Rational; use malachite_q::test_util::generators::rational_primitive_float_pair_gen; use rug; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_partial_eq_primitive_float() { let test = |u, v: f32, out| { assert_eq!(Rational::from_str(u).unwrap() == v, out); assert_eq!(rug::Rational::from_str(u).unwrap() == v, out); assert_eq!(v == Rational::from_str(u).unwrap(), out); assert_eq!(v == rug::Rational::from_str(u).unwrap(), out); let v = f64::from(v); assert_eq!(Rational::from_str(u).unwrap() == v, out); assert_eq!(rug::Rational::from_str(u).unwrap() == v, out); assert_eq!(v == Rational::from_str(u).unwrap(), out); assert_eq!(v == rug::Rational::from_str(u).unwrap(), out); }; test("2/3", f32::NAN, false); test("2/3", f32::INFINITY, false); test("2/3", f32::NEGATIVE_INFINITY, false); test("-2/3", f32::NAN, false); test("-2/3", f32::INFINITY, false); test("-2/3", f32::NEGATIVE_INFINITY, false); test("0", 0.0, true); test("0", -0.0, true); test("0", 5.0, false); test("0", -5.0, false); test("3/2", 1.5, true); test("3/2", 5.0, false); test("3/2", -1.5, false); test("-3/2", 1.5, false); test("-3/2", 5.0, false); test("-3/2", -1.5, true); } #[allow(clippy::cmp_owned, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_float_properties_helper< T: PartialEq + PartialEq + PrimitiveFloat, >() where Rational: TryFrom + PartialEq + PartialOrd, rug::Rational: PartialEq, { rational_primitive_float_pair_gen::().test_properties(|(n, f)| { let eq = n == f; assert_eq!(rug::Rational::from(&n) == f, eq); assert_eq!(f == n, eq); assert_eq!(f == rug::Rational::from(&n), eq); assert_eq!(n.partial_cmp(&f) == Some(Equal), eq); if f.is_finite() { assert_eq!(PartialEq::::eq(&n, &Rational::exact_from(f)), eq); } }); } #[test] fn partial_eq_primitive_float_properties() { apply_fn_to_primitive_floats!(partial_eq_primitive_float_properties_helper); } ================================================ FILE: malachite-q/tests/comparison/partial_eq_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::test_util::generators::{signed_pair_gen, unsigned_pair_gen_var_27}; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_signed_pair_gen, rational_unsigned_pair_gen}; use rug; use std::str::FromStr; #[test] fn test_partial_eq_u32() { let test = |s, v: u32, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Rational::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Rational::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", 123, false); test("123", 5, false); test("-123", 5, false); test("1000000000000", 123, false); test("-1000000000000", 123, false); test("22/7", 123, false); test("-22/7", 123, false); } #[test] fn test_partial_eq_u64() { let test = |s, v: u64, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Rational::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Rational::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", 123, false); test("123", 5, false); test("-123", 5, false); test("1000000000000", 1000000000000, true); test("-1000000000000", 1000000000000, false); test("1000000000000", 1000000000001, false); test("-1000000000000", 1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-1000000000000000000000000", 1000000000000, false); test("22/7", 123, false); test("-22/7", 123, false); } #[test] fn test_partial_eq_i32() { let test = |s, v: i32, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Rational::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Rational::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", -123, true); test("-123", 123, false); test("123", 5, false); test("-123", -5, false); test("1000000000000", 123, false); test("-1000000000000", -123, false); test("22/7", 123, false); test("22/7", -123, false); test("-22/7", 123, false); test("-22/7", -123, false); } #[test] fn test_partial_eq_i64() { let test = |s, v: i64, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u == v, out); assert_eq!(rug::Rational::from_str(s).unwrap() == v, out); assert_eq!(v == u, out); assert_eq!(v == rug::Rational::from_str(s).unwrap(), out); }; test("0", 0, true); test("0", 5, false); test("123", 123, true); test("-123", -123, true); test("-123", 123, false); test("123", 5, false); test("-123", -5, false); test("1000000000000", 1000000000000, true); test("-1000000000000", -1000000000000, true); test("1000000000000", 1000000000001, false); test("-1000000000000", -1000000000001, false); test("1000000000000000000000000", 1000000000000, false); test("-1000000000000000000000000", -1000000000000, false); test("22/7", 123, false); test("22/7", -123, false); test("-22/7", 123, false); test("-22/7", -123, false); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_unsigned< T: PartialEq + PartialEq + PrimitiveUnsigned, >() where Rational: From + PartialEq, rug::Rational: PartialEq, { rational_unsigned_pair_gen::().test_properties(|(n, u)| { let eq = n == u; assert_eq!(rug::Rational::from(&n) == u, eq); assert_eq!(&n == &Rational::from(u), eq); assert_eq!(u == n, eq); assert_eq!(u == rug::Rational::from(&n), eq); assert_eq!(&Rational::from(u) == &n, eq); }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert_eq!(Rational::from(x) == y, x == y); assert_eq!(x == Rational::from(y), x == y); }); } // Extra refs necessary for type inference #[allow(clippy::cmp_owned, clippy::op_ref, clippy::trait_duplication_in_bounds)] fn partial_eq_primitive_int_properties_helper_signed< T: PartialEq + PartialEq + PrimitiveSigned, >() where Rational: From + PartialEq, rug::Rational: PartialEq, { rational_signed_pair_gen::().test_properties(|(n, i)| { let eq = n == i; assert_eq!(rug::Rational::from(&n) == i, eq); assert_eq!(&n == &Rational::from(i), eq); assert_eq!(i == n, eq); assert_eq!(i == rug::Rational::from(&n), eq); assert_eq!(&Rational::from(i) == &n, eq); }); signed_pair_gen::().test_properties(|(x, y)| { assert_eq!(Rational::from(x) == y, x == y); assert_eq!(x == Rational::from(y), x == y); }); } #[test] fn partial_eq_primitive_int_properties() { apply_fn_to_unsigneds!(partial_eq_primitive_int_properties_helper_unsigned); apply_fn_to_signeds!(partial_eq_primitive_int_properties_helper_signed); } ================================================ FILE: malachite-q/tests/conversion/clone.rs ================================================ // Copyright © 2026 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 malachite_nz::test_util::generators::integer_pair_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_pair_gen}; use num::BigRational; use rug; use std::str::FromStr; #[test] #[allow(clippy::redundant_clone)] fn test_clone() { let test = |u| { let x = Rational::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); assert!(x.is_valid()); let x = BigRational::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); let x = rug::Rational::from_str(u).unwrap().clone(); assert_eq!(x.to_string(), u); }; test("123"); test("1000000000000"); test("-123"); test("-1000000000000"); test("22/7"); test("-22/7"); test("100/101"); test("-100/101"); } #[test] fn test_clone_from() { let test = |u, v| { let mut x = Rational::from_str(u).unwrap(); x.clone_from(&Rational::from_str(v).unwrap()); assert_eq!(x.to_string(), v); assert!(x.is_valid()); let mut x = BigRational::from_str(u).unwrap(); x.clone_from(&BigRational::from_str(v).unwrap()); assert_eq!(x.to_string(), v); let mut x = rug::Rational::from_str(u).unwrap(); x.clone_from(&rug::Rational::from_str(v).unwrap()); assert_eq!(x.to_string(), v); }; test("-123", "456"); test("-123", "1000000000000"); test("1000000000000", "-123"); test("1000000000000", "2000000000000"); test("123", "22/7"); test("123", "-22/7"); test("-123", "22/7"); test("-123", "-22/7"); } #[allow(clippy::redundant_clone)] #[test] fn clone_and_clone_from_properties() { rational_gen().test_properties(|x| { let mut_x = x.clone(); assert!(mut_x.is_valid()); assert_eq!(mut_x, x); assert_eq!(Rational::from(&BigRational::from(&x).clone()), x); assert_eq!(Rational::from(&rug::Rational::from(&x).clone()), x); }); rational_pair_gen().test_properties(|(x, y)| { let mut mut_x = x.clone(); mut_x.clone_from(&y); assert!(mut_x.is_valid()); assert_eq!(mut_x, y); let mut num_x = BigRational::from(&x); num_x.clone_from(&BigRational::from(&y)); assert_eq!(Rational::from(&num_x), y); let mut rug_x = rug::Rational::from(&x); rug_x.clone_from(&rug::Rational::from(&y)); assert_eq!(Rational::from(&rug_x), y); }); integer_pair_gen().test_properties(|(i, j)| { let x = Rational::from(&i); let y = Rational::from(&j); let mut mut_i = i.clone(); let mut mut_x = x.clone(); mut_i.clone_from(&j); mut_x.clone_from(&y); assert_eq!(mut_x, mut_i); }); } ================================================ FILE: malachite-q/tests/conversion/continued_fraction/convergents.rs ================================================ // Copyright © 2026 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::comparison::{is_strictly_ascending, is_strictly_descending}; use malachite_base::num::arithmetic::traits::{Abs, Floor, Parity}; use malachite_base::num::conversion::traits::IsInteger; use malachite_base::strings::ToDebugString; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::conversion::traits::Convergents; use malachite_q::test_util::conversion::continued_fraction::convergents::convergents_alt; use malachite_q::test_util::generators::rational_gen; use std::str::FromStr; #[test] fn test_convergents() { let test = |x: &str, out: &str| { let x = Rational::from_str(x).unwrap(); let convergents = x.clone().convergents().collect_vec(); assert!(convergents.iter().all(Rational::is_valid)); assert_eq!((&x).convergents().collect_vec(), convergents); assert_eq!(convergents_alt(x).collect_vec(), convergents); assert_eq!(convergents.to_debug_string(), out); }; test("0", "[0]"); test("123", "[123]"); test("-123", "[-123]"); test("1/2", "[0, 1/2]"); test("22/7", "[3, 22/7]"); test("-22/7", "[-4, -3, -22/7]"); test("99/100", "[0, 1, 99/100]"); test( "936851431250/1397", "[670616629, 1341233259/2, 2011849888/3, 3353083147/5, 5364933035/8, 8718016182/13, \ 232033353767/346, 936851431250/1397]", ); test( "6369051672525773/4503599627370496", "[1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169, 577/408, 1393/985, 3363/2378, 8119/5741, \ 19601/13860, 47321/33461, 114243/80782, 275807/195025, 665857/470832, 1607521/1136689, \ 3880899/2744210, 9369319/6625109, 22619537/15994428, 54608393/38613965, \ 77227930/54608393, 131836323/93222358, 209064253/147830751, 549964829/388883860, \ 4058818056/2870017771, 4608782885/3258901631, 13276383826/9387821033, \ 442729449143/313056995720, 898735282112/635501812473, 6733876423927/4761569683031, \ 34568117401747/24443350227628, 75870111227421/53648270138287, \ 110438228629168/78091620365915, 186308339856589/131739890504202, \ 3091371666334592/2185929868433147, 6369051672525773/4503599627370496]", ); test( "884279719003555/281474976710656", "[3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317, 312689/99532, \ 833719/265381, 1146408/364913, 4272943/1360120, 5419351/1725033, 80143857/25510582, \ 245850922/78256779, 817696623/260280919, 1881244168/598818617, 2698940791/859099536, \ 9978066541/3176117225, 32633140414/10387451211, 238410049439/75888275702, \ 509453239292/162164002615, 747863288731/238052278317, 1257316528023/400216280932, \ 4519812872800/1438701121113, 10296942273623/3277618523158, \ 436991388364966/139098679093749, 884279719003555/281474976710656]", ); test( "6121026514868073/2251799813685248", "[2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536, 2721/1001, \ 23225/8544, 25946/9545, 49171/18089, 517656/190435, 566827/208524, 1084483/398959, \ 13580623/4996032, 14665106/5394991, 28245729/10391023, 325368125/119696244, \ 353613854/130087267, 678981979/249783511, 1032595833/379870778, 12037536142/4428362069, \ 61220276543/22521681123, 73257812685/26950043192, 134478089228/49471724315, \ 342213991141/125893491822, 476692080369/175365216137, 2248982312617/827354356370, \ 4974656705603/1830073928877, 7223639018220/2657428285247, 12198295723823/4487502214124, \ 117008300532627/43044948212363, 2001339404778482/736251621824295, \ 6121026514868073/2251799813685248]", ); } #[test] fn convergents_properties() { rational_gen().test_properties(|x| { let convergents = x.clone().convergents().collect_vec(); assert!(convergents.iter().all(Rational::is_valid)); assert_eq!(convergents[0], (&x).floor()); assert_eq!(*convergents.last().unwrap(), x); assert_eq!((&x).convergents().collect_vec(), convergents); assert_eq!(convergents_alt(x.clone()).collect_vec(), convergents); // The denominators of the convergents are strictly increasing, with the single exception // that the first two convergents may both be integers. if let Some(i) = convergents.iter().position(|x| !x.is_integer()) { assert!(i == 1 || i == 2); assert!(is_strictly_ascending( convergents[i - 1..].iter().map(Rational::denominator_ref) )); } assert!(is_strictly_descending( convergents.iter().map(|c| (c - &x).abs()) )); for (i, c) in convergents.iter().enumerate() { if i.even() { assert!(*c <= x); } else { assert!(*c >= x); } } }); integer_gen().test_properties(|x| { let convergents = Rational::from(&x).convergents().collect_vec(); assert_eq!(convergents, &[x]); }); } ================================================ FILE: malachite-q/tests/conversion/continued_fraction/from_continued_fraction.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::vecs::vec_from_str; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{integer_gen, natural_vec_integer_pair_gen_var_1}; use malachite_q::Rational; use malachite_q::conversion::traits::ContinuedFraction; use malachite_q::test_util::conversion::continued_fraction::from_continued_fraction::*; use std::str::FromStr; #[test] fn test_from_continued_fraction() { let test = |floor: &str, xs: &str, out: &str| { let floor = Integer::from_str(floor).unwrap(); let xs: Vec = vec_from_str(xs).unwrap(); let x = Rational::from_continued_fraction(floor.clone(), xs.iter().cloned()); assert!(x.is_valid()); assert_eq!(Rational::from_continued_fraction_ref(&floor, xs.iter()), x); assert_eq!(from_continued_fraction_alt(floor, xs), x); assert_eq!(x.to_string(), out); }; test("0", "[]", "0"); test("3", "[7]", "22/7"); test("3", "[6, 1]", "22/7"); test("-4", "[1, 6]", "-22/7"); test( "3", "[7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2]", "14885392687/4738167652", ); } #[test] #[should_panic] fn from_continued_fraction_fail_1() { Rational::from_continued_fraction(Integer::ONE, std::iter::once(Natural::ZERO)); } #[test] #[should_panic] fn from_continued_fraction_fail_2() { Rational::from_continued_fraction( Integer::ONE, vec![Natural::from(3u32), Natural::ZERO, Natural::ONE].into_iter(), ); } #[test] #[should_panic] fn from_continued_fraction_ref_fail_1() { Rational::from_continued_fraction_ref(&Integer::ONE, [Natural::ZERO].iter()); } #[test] #[should_panic] fn from_continued_fraction_ref_fail_2() { Rational::from_continued_fraction_ref( &Integer::ONE, [Natural::from(3u32), Natural::ZERO, Natural::ONE].iter(), ); } #[test] fn from_continued_fraction_properties() { natural_vec_integer_pair_gen_var_1().test_properties(|(xs, floor)| { let x = Rational::from_continued_fraction(floor.clone(), xs.iter().cloned()); assert!(x.is_valid()); assert_eq!(Rational::from_continued_fraction_ref(&floor, xs.iter()), x); assert_eq!(from_continued_fraction_alt(floor.clone(), xs.clone()), x); if xs.last() != Some(&Natural::ONE) { let (floor_alt, cf) = (&x).continued_fraction(); let xs_alt = cf.collect_vec(); assert_eq!(floor_alt, floor); assert_eq!(xs_alt, xs); } if !xs.is_empty() { let mut alt_xs = xs; let last = alt_xs.last_mut().unwrap(); if *last > 1u32 { *last -= Natural::ONE; alt_xs.push(Natural::ONE); assert_eq!( Rational::from_continued_fraction(floor, alt_xs.into_iter()), x ); } } }); integer_gen().test_properties(|x| { assert_eq!( Rational::from_continued_fraction_ref(&x, std::iter::empty()), x ); }); } ================================================ FILE: malachite-q/tests/conversion/continued_fraction/to_continued_fraction.rs ================================================ // Copyright © 2026 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::num::arithmetic::traits::Floor; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::IsInteger; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::conversion::traits::ContinuedFraction; use malachite_q::test_util::generators::rational_gen; use std::str::FromStr; #[test] fn test_continued_fraction() { let test = |x: &str, out: &str| { let x = Rational::from_str(x).unwrap(); let (floor, continued_fraction) = (&x).continued_fraction(); let (floor_alt, continued_fraction_alt) = x.continued_fraction(); assert_eq!(floor, floor_alt); assert_eq!(continued_fraction, continued_fraction_alt); let continued_fraction = continued_fraction.collect_vec(); let s = if continued_fraction.is_empty() { format!("[{floor}]") } else { let s = continued_fraction.to_debug_string(); format!("[{}; {}]", floor, &s[1..s.len() - 1]) }; assert_eq!(s, out); }; test("0", "[0]"); test("123", "[123]"); test("-123", "[-123]"); test("1/2", "[0; 2]"); test("22/7", "[3; 7]"); test("-22/7", "[-4; 1, 6]"); test("99/100", "[0; 1, 99]"); test("936851431250/1397", "[670616629; 2, 1, 1, 1, 1, 26, 4]"); test( "6369051672525773/4503599627370496", "[1; 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 7, 1, 2, 33, \ 2, 7, 5, 2, 1, 1, 16, 2]", ); test( "884279719003555/281474976710656", "[3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3, 2, 1, 3, 3, 7, 2, 1, 1, 3, 2, 42, 2]", ); test( "6121026514868073/2251799813685248", "[2; 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1, 11, 1, 1, 1, 11, 5, 1, 1, \ 2, 1, 4, 2, 1, 1, 9, 17, 3]", ); } #[test] fn continued_fraction_properties() { rational_gen().test_properties(|x| { let (floor, continued_fraction) = (&x).continued_fraction(); let (floor_alt, continued_fraction_alt) = x.clone().continued_fraction(); assert_eq!(floor, floor_alt); assert_eq!(continued_fraction, continued_fraction_alt); let continued_fraction = continued_fraction.collect_vec(); assert_eq!(floor, (&x).floor()); assert_eq!(continued_fraction.is_empty(), x.is_integer()); assert!(continued_fraction.iter().all(|n| *n > 0u32)); assert_ne!(continued_fraction.last(), Some(&Natural::ONE)); assert_eq!( Rational::from_continued_fraction(floor, continued_fraction.into_iter()), x ); }); integer_gen().test_properties(|x| { let (floor, continued_fraction) = Rational::from(&x).continued_fraction(); let continued_fraction = continued_fraction.collect_vec(); assert_eq!(floor, x); assert!(continued_fraction.is_empty()); }); } ================================================ FILE: malachite-q/tests/conversion/digits/digits.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::{count_is_at_most, prefix_to_string}; use malachite_base::num::arithmetic::traits::{Abs, Pow}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{Digits, IsInteger}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen_var_2; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_natural_pair_gen_var_1, rational_natural_pair_gen_var_2, }; use std::str::FromStr; #[test] fn test_digits() { let test = |x: &str, base: &str, before_out: &str, after_out: &str| { let base = Natural::from_str(base).unwrap(); let (before, after) = Rational::from_str(x).unwrap().digits(&base); assert_eq!(before.to_debug_string(), before_out); assert_eq!(prefix_to_string(after, 10), after_out); }; test("0", "3", "[]", "[]"); test("0", "10", "[]", "[]"); test("1", "3", "[1]", "[]"); test("1", "10", "[1]", "[]"); test("1/2", "3", "[]", "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...]"); test("1/2", "10", "[]", "[5]"); test("1/3", "3", "[]", "[1]"); test("1/3", "10", "[]", "[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ...]"); test("7/6", "3", "[1]", "[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...]"); test("7/6", "10", "[1]", "[1, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...]"); test("22/7", "3", "[0, 1]", "[0, 1, 0, 2, 1, 2, 0, 1, 0, 2, ...]"); test("22/7", "10", "[3]", "[1, 4, 2, 8, 5, 7, 1, 4, 2, 8, ...]"); test( "936851431250/1397", "3", "[1, 2, 2, 1, 0, 0, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 0, 2, 1]", "[1, 0, 1, 1, 0, 1, 0, 2, 0, 0, ...]", ); test( "936851431250/1397", "10", "[9, 2, 6, 6, 1, 6, 0, 7, 6]", "[3, 8, 4, 3, 9, 5, 1, 3, 2, 4, ...]", ); test( "6369051672525773/4503599627370496", "10", "[1]", "[4, 1, 4, 2, 1, 3, 5, 6, 2, 3, ...]", ); test( "884279719003555/281474976710656", "10", "[3]", "[1, 4, 1, 5, 9, 2, 6, 5, 3, 5, ...]", ); test( "6121026514868073/2251799813685248", "10", "[2]", "[7, 1, 8, 2, 8, 1, 8, 2, 8, 4, ...]", ); } #[test] #[should_panic] fn digits_fail_1() { Rational::ONE.digits(&Natural::ONE); } #[test] #[should_panic] fn digits_fail_2() { Rational::ONE.digits(&Natural::ZERO); } #[test] fn digits_properties() { rational_natural_pair_gen_var_1().test_properties(|(x, base)| { let (before_point, after_point) = x.digits(&base); let (before_point_alt, after_point_alt) = (-&x).digits(&base); assert_eq!(before_point, before_point_alt); assert!(Iterator::eq(after_point.take(10), after_point_alt.take(10))); let (before_point, after_point) = x.digits(&base); let approx = Rational::from_digits( &base, before_point, RationalSequence::from_vec(after_point.take(10).collect()), ); let abs_x = (&x).abs(); assert!(approx <= abs_x); assert!(abs_x - approx < Rational::from(&base).pow(-10i64)); let after_point = x.digits(&base).1; assert_eq!(count_is_at_most(after_point, 0), x.is_integer()); }); rational_natural_pair_gen_var_2().test_properties(|(x, base)| { let (before_point, after_point) = x.to_digits(&base); let (before_point_alt, after_point_alt) = x.digits(&base); assert_eq!(before_point, before_point_alt); assert!(Iterator::eq( after_point.iter().take(10).cloned(), after_point_alt.take(10) )); }); natural_pair_gen_var_2().test_properties(|(n, base)| { let (before_point, after_point) = Rational::from(&n).digits(&base); let before_point_alt: Vec = n.to_digits_asc(&base); assert_eq!(before_point, before_point_alt); assert_eq!(Iterator::count(after_point), 0); }); } ================================================ FILE: malachite-q/tests/conversion/digits/from_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::Digits; use malachite_base::rational_sequences::RationalSequence; use malachite_base::vecs::vec_from_str; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ large_type_gen_var_25, natural_vec_natural_pair_gen_var_2, }; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_from_digits() { let test = |base: &str, before: &str, after_nr: &str, after_r: &str, out: &str| { let base = Natural::from_str(base).unwrap(); let before: Vec = vec_from_str(before).unwrap(); let after_nr: Vec = vec_from_str(after_nr).unwrap(); let after_r: Vec = vec_from_str(after_r).unwrap(); let x = Rational::from_digits_ref( &base, &before, &RationalSequence::from_slices(&after_nr, &after_r), ); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!( Rational::from_digits( &base, before, RationalSequence::from_vecs(after_nr, after_r) ), x ); }; test("3", "[]", "[]", "[]", "0"); test("10", "[]", "[]", "[]", "0"); test("3", "[1]", "[]", "[]", "1"); test("10", "[1]", "[]", "[]", "1"); test("3", "[]", "[]", "[1]", "1/2"); test("10", "[]", "[5]", "[]", "1/2"); test("3", "[]", "[1]", "[]", "1/3"); test("10", "[]", "[]", "[3]", "1/3"); test("3", "[1]", "[0]", "[1]", "7/6"); test("10", "[1]", "[1]", "[6]", "7/6"); test("3", "[0, 1]", "[]", "[0, 1, 0, 2, 1, 2]", "22/7"); test("10", "[3]", "[]", "[1, 4, 2, 8, 5, 7]", "22/7"); test( "3", "[1, 2, 2, 1, 0, 0, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 0, 2, 1]", "[]", "[1, 0, 1, 1, 0, 1, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 2, 1, 0, 2, 0, \ 2, 0, 0, 1, 1, 2, 2, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2, 0, 0, 2, 1, 2, 2, 1, 1, 1, 0, 2, 0, 2, \ 2, 2, 1, 0, 1, 0, 2, 2, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 1, 0, 2, 2, 0, 2, 0, 2, 1, 1, \ 0, 1, 2, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 1, 2, 0, 1, 2, 1, 0, 1, 0, 0, 1, 2, 1, 2, 1, 2, 1, \ 2, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 0, 2, 0, 0, 1, 0, 1, 0, 2, 1, 0, 0, 2, 1, 1, 1, 2, 1, 1, \ 1, 2, 2, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 2, 0, 0, 2, 1, 0, 0, 1, 2, 2, 2, 2, 0, 2, 0, 1, 2, \ 2, 1, 1, 1, 2, 1, 0, 0, 0, 1, 2, 1, 0, 1, 1, 2, 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, 1, 1, 2, 0, \ 1, 2, 1, 1, 2, 2, 0, 2, 2, 0, 0, 1, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 1, 2, 1, 1, 1, 0, 0, \ 0, 2, 0, 1, 0, 2, 2, 0, 2, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 0, 0, \ 2, 1, 2, 1, 2, 2, 2, 0, 1, 1, 1, 2, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 2, 1, \ 0, 1, 0, 0, 0, 0, 2, 2, 1, 0, 0, 1, 0, 2, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 0, 0, 1, 0, 1, \ 0, 0, 2, 1, 0, 1, 2, 0, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 2, 2, 0, 0, 2, 2, 1, 1, 0, 1, 2, 0, \ 0, 1, 2, 0, 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 2, 1, 0, 0, 2, 2, 1, 2, 0, 2, \ 0, 0, 2, 0, 1, 1, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 0, 1, 1, 1, 1, 2, 1, \ 2, 2, 0, 0, 0, 2, 0, 1, 2, 1, 1, 1, 0, 1, 2, 1, 0, 2, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, \ 2, 0, 1, 0, 1, 2, 0, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 2, 0, \ 2, 1, 1, 1, 0, 1, 0, 2, 1, 1, 2, 1, 1, 2, 1, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 1, 2, 2, \ 0, 2, 2, 1, 2, 0, 0, 1, 1, 1, 2, 2, 0, 2, 0, 1, 1, 0, 2, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 1, \ 2, 1, 2, 1, 0, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 2, 1, 2, 0, 0, 0, 1, 1, 1, 1, 2, 0, 0, 2, 2, \ 2, 1, 0, 2, 2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 0, 0, 1, 2, 2, 1, 0, 1, 1, 2, 2, 1, 1, 2, 0, 2, \ 2, 0, 1, 1, 0, 1, 2, 2, 0, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 0, 2, 1, 0, 0, 0, 2, 2, 1, 1, 2, \ 0]", "936851431250/1397", ); test( "10", "[9, 2, 6, 6, 1, 6, 0, 7, 6]", "[]", "[3, 8, 4, 3, 9, 5, 1, 3, 2, 4, 2, 6, 6, 2, 8, 4, 8, 9, 6, 2, 0, 6, 1, 5, 6, 0, 4, 8, 6, \ 7, 5, 7, 3, 3, 7, 1, 5, 1, 0, 3, 7, 9]", "936851431250/1397", ); } #[test] #[should_panic] fn from_digits_fail_1() { Rational::from_digits( &Natural::ONE, Vec::new(), RationalSequence::from_vec(Vec::new()), ); } #[test] #[should_panic] fn from_digits_fail_2() { Rational::from_digits( &Natural::ZERO, Vec::new(), RationalSequence::from_vec(Vec::new()), ); } #[test] #[should_panic] fn from_digits_ref_fail_1() { Rational::from_digits_ref(&Natural::ONE, &[], &RationalSequence::from_vec(Vec::new())); } #[test] #[should_panic] fn from_digits_ref_fail_2() { Rational::from_digits_ref(&Natural::ZERO, &[], &RationalSequence::from_vec(Vec::new())); } #[test] fn from_digits_properties() { large_type_gen_var_25().test_properties(|(base, before_point, after_point)| { let x = Rational::from_digits(&base, before_point.clone(), after_point.clone()); assert!(x.is_valid()); assert_eq!( Rational::from_digits_ref(&base, &before_point, &after_point), x ); assert!(x >= 0u32); if before_point.last() != Some(&Natural::ZERO) && after_point.slices_ref().1 != [Natural::ZERO] && after_point.slices_ref().1 != [&base - Natural::ONE] && !(after_point.slices_ref().1.is_empty() && after_point.slices_ref().0.last() == Some(&Natural::ZERO)) { assert_eq!(x.into_digits(&base), (before_point, after_point)); } }); natural_vec_natural_pair_gen_var_2().test_properties(|(digits, base)| { assert_eq!( Natural::from_digits_asc(&base, digits.iter().cloned()).unwrap(), Rational::from_digits( &base, digits.to_vec(), RationalSequence::from_vec(Vec::new()) ) ); }); } ================================================ FILE: malachite-q/tests/conversion/digits/from_power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::Zero; use malachite_base::num::conversion::traits::PowerOf2Digits; use malachite_base::num::logic::traits::LowMask; use malachite_base::rational_sequences::RationalSequence; use malachite_base::vecs::vec_from_str; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ large_type_gen_var_23, natural_vec_unsigned_pair_gen_var_1, }; use malachite_q::Rational; #[test] fn test_from_power_of_2_digits() { let test = |log_base, before: &str, after_nr: &str, after_r: &str, out: &str| { let before: Vec = vec_from_str(before).unwrap(); let after_nr: Vec = vec_from_str(after_nr).unwrap(); let after_r: Vec = vec_from_str(after_r).unwrap(); let x = Rational::from_power_of_2_digits_ref( log_base, &before, &RationalSequence::from_slices(&after_nr, &after_r), ); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!( Rational::from_power_of_2_digits( log_base, before, RationalSequence::from_vecs(after_nr, after_r) ), x ); }; test(1, "[]", "[]", "[]", "0"); test(1, "[]", "[0, 0]", "[0]", "0"); test(10, "[]", "[]", "[]", "0"); test(1, "[1]", "[]", "[]", "1"); test(10, "[1]", "[]", "[]", "1"); test(1, "[]", "[]", "[1]", "1"); test(1, "[]", "[1]", "[]", "1/2"); test(10, "[]", "[512]", "[]", "1/2"); test(1, "[]", "[]", "[0, 1]", "1/3"); test(10, "[]", "[]", "[341]", "1/3"); test(1, "[1]", "[0]", "[0, 1]", "7/6"); test(10, "[1]", "[170]", "[682]", "7/6"); test(1, "[1, 1]", "[]", "[0, 0, 1]", "22/7"); test(10, "[3]", "[]", "[146, 292, 585]", "22/7"); test( 1, "[1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 1]", "[]", "[0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, \ 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, \ 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1]", "936851431250/1397", ); test( 10, "[53, 563, 639]", "[]", "[393, 635, 522, 643, 587, 135, 619]", "936851431250/1397", ); } #[test] #[should_panic] fn from_power_of_2_digits_fail() { Rational::from_power_of_2_digits(0, Vec::new(), RationalSequence::from_vec(Vec::new())); } #[test] #[should_panic] fn from_power_of_2_digits_ref_fail() { Rational::from_power_of_2_digits_ref(0, &[], &RationalSequence::from_vec(Vec::new())); } #[test] fn from_power_of_2_digits_properties() { large_type_gen_var_23().test_properties(|(log_base, before_point, after_point)| { let x = Rational::from_power_of_2_digits(log_base, before_point.clone(), after_point.clone()); assert!(x.is_valid()); assert_eq!( Rational::from_power_of_2_digits_ref(log_base, &before_point, &after_point), x ); assert!(x >= 0u32); if before_point.last() != Some(&Natural::ZERO) && after_point.slices_ref().1 != [Natural::ZERO] && after_point.slices_ref().1 != [Natural::low_mask(log_base)] && !(after_point.slices_ref().1.is_empty() && after_point.slices_ref().0.last() == Some(&Natural::ZERO)) { assert_eq!( x.into_power_of_2_digits(log_base), (before_point, after_point) ); } }); natural_vec_unsigned_pair_gen_var_1().test_properties(|(digits, log_base)| { assert_eq!( Natural::from_power_of_2_digits_asc(log_base, digits.iter().cloned()).unwrap(), Rational::from_power_of_2_digits( log_base, digits.to_vec(), RationalSequence::from_vec(Vec::new()) ) ); }); } ================================================ FILE: malachite-q/tests/conversion/digits/power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::{count_is_at_most, prefix_to_string}; use malachite_base::num::arithmetic::traits::{Abs, PowerOf2}; use malachite_base::num::basic::traits::One; use malachite_base::num::conversion::traits::{ExactFrom, IsInteger, PowerOf2Digits}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_7; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_unsigned_pair_gen_var_2, rational_unsigned_pair_gen_var_3, }; use std::str::FromStr; #[test] fn test_power_of_2_digits() { let test = |x: &str, log_base: u64, before_out: &str, aftr_out: &str| { let (before, after) = Rational::from_str(x).unwrap().power_of_2_digits(log_base); assert_eq!(before.to_debug_string(), before_out); assert_eq!(prefix_to_string(after, 10), aftr_out); }; test("0", 1, "[]", "[]"); test("0", 10, "[]", "[]"); test("1", 1, "[1]", "[]"); test("1", 10, "[1]", "[]"); test("1/2", 1, "[]", "[1]"); test("1/2", 10, "[]", "[512]"); test("1/3", 1, "[]", "[0, 1, 0, 1, 0, 1, 0, 1, 0, 1, ...]"); test( "1/3", 10, "[]", "[341, 341, 341, 341, 341, 341, 341, 341, 341, 341, ...]", ); test("7/6", 1, "[1]", "[0, 0, 1, 0, 1, 0, 1, 0, 1, 0, ...]"); test( "7/6", 10, "[1]", "[170, 682, 682, 682, 682, 682, 682, 682, 682, 682, ...]", ); test("22/7", 1, "[1, 1]", "[0, 0, 1, 0, 0, 1, 0, 0, 1, 0, ...]"); test( "22/7", 10, "[3]", "[146, 292, 585, 146, 292, 585, 146, 292, 585, 146, ...]", ); test( "936851431250/1397", 1, "[1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 1]", "[0, 1, 1, 0, 0, 0, 1, 0, 0, 1, ...]", ); test( "936851431250/1397", 10, "[53, 563, 639]", "[393, 635, 522, 643, 587, 135, 619, 393, 635, 522, ...]", ); test( "6369051672525773/4503599627370496", 10, "[1]", "[424, 158, 409, 1011, 755, 256]", ); test( "884279719003555/281474976710656", 10, "[3]", "[144, 1014, 674, 133, 652]", ); test( "6121026514868073/2251799813685248", 10, "[2]", "[735, 533, 88, 650, 948, 512]", ); } #[test] #[should_panic] fn power_of_2_digits_fail() { Rational::ONE.power_of_2_digits(0); } #[test] fn power_of_2_digits_properties() { rational_unsigned_pair_gen_var_3().test_properties(|(x, log_base)| { let (before_point, after_point) = x.power_of_2_digits(log_base); let (before_point_alt, after_point_alt) = (-&x).power_of_2_digits(log_base); assert_eq!(before_point, before_point_alt); assert!(Iterator::eq(after_point.take(10), after_point_alt.take(10))); let (before_point, after_point) = x.power_of_2_digits(log_base); let approx = Rational::from_power_of_2_digits( log_base, before_point, RationalSequence::from_vec(after_point.take(10).collect()), ); let abs_x = (&x).abs(); assert!(approx <= abs_x); assert!(abs_x - approx < Rational::power_of_2(-i64::exact_from(log_base) * 10)); let after_point = x.power_of_2_digits(log_base).1; assert_eq!(count_is_at_most(after_point, 0), x.is_integer()); }); rational_unsigned_pair_gen_var_2().test_properties(|(x, log_base)| { let (before_point, after_point) = x.to_power_of_2_digits(log_base); let (before_point_alt, after_point_alt) = x.power_of_2_digits(log_base); assert_eq!(before_point, before_point_alt); assert!(Iterator::eq( after_point.iter().take(10).cloned(), after_point_alt.take(10) )); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, log_base)| { let (before_point, after_point) = Rational::from(&n).power_of_2_digits(log_base); let before_point_alt: Vec = n.to_power_of_2_digits_asc(log_base); assert_eq!(before_point, before_point_alt); assert_eq!(Iterator::count(after_point), 0); }); } ================================================ FILE: malachite-q/tests/conversion/digits/to_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, Floor, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{Digits, IsInteger}; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_pair_gen_var_2; use malachite_q::Rational; use malachite_q::test_util::generators::rational_natural_pair_gen_var_2; use std::str::FromStr; #[test] fn test_to_digits() { let test = |x: &str, base: &str, before_out: &str, after_out: &str| { let x = Rational::from_str(x).unwrap(); let base = Natural::from_str(base).unwrap(); let (before, after) = x.to_digits(&base); let (before_alt, after_alt) = x.into_digits(&base); assert_eq!(before, before_alt); assert_eq!(after, after_alt); assert_eq!(before.to_debug_string(), before_out); assert_eq!(after.to_string(), after_out); }; test("0", "3", "[]", "[]"); test("0", "10", "[]", "[]"); test("1", "3", "[1]", "[]"); test("1", "10", "[1]", "[]"); test("1/2", "3", "[]", "[[1]]"); test("1/2", "10", "[]", "[5]"); test("1/3", "3", "[]", "[1]"); test("1/3", "10", "[]", "[[3]]"); test("7/6", "3", "[1]", "[0, [1]]"); test("7/6", "10", "[1]", "[1, [6]]"); test("22/7", "3", "[0, 1]", "[[0, 1, 0, 2, 1, 2]]"); test("22/7", "10", "[3]", "[[1, 4, 2, 8, 5, 7]]"); test( "936851431250/1397", "3", "[1, 2, 2, 1, 0, 0, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 0, 2, 1]", "[[1, 0, 1, 1, 0, 1, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 2, 1, 0, 2, 0, \ 2, 0, 0, 1, 1, 2, 2, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2, 0, 0, 2, 1, 2, 2, 1, 1, 1, 0, 2, 0, 2, \ 2, 2, 1, 0, 1, 0, 2, 2, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 2, 1, 0, 2, 2, 0, 2, 0, 2, 1, 1, \ 0, 1, 2, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 1, 2, 0, 1, 2, 1, 0, 1, 0, 0, 1, 2, 1, 2, 1, 2, 1, \ 2, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 0, 2, 0, 0, 1, 0, 1, 0, 2, 1, 0, 0, 2, 1, 1, 1, 2, 1, 1, \ 1, 2, 2, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 2, 0, 0, 2, 1, 0, 0, 1, 2, 2, 2, 2, 0, 2, 0, 1, 2, \ 2, 1, 1, 1, 2, 1, 0, 0, 0, 1, 2, 1, 0, 1, 1, 2, 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, 1, 1, 2, 0, \ 1, 2, 1, 1, 2, 2, 0, 2, 2, 0, 0, 1, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 1, 2, 1, 1, 1, 0, 0, \ 0, 2, 0, 1, 0, 2, 2, 0, 2, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 0, 0, \ 2, 1, 2, 1, 2, 2, 2, 0, 1, 1, 1, 2, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 2, 1, \ 0, 1, 0, 0, 0, 0, 2, 2, 1, 0, 0, 1, 0, 2, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 0, 0, 1, 0, 1, \ 0, 0, 2, 1, 0, 1, 2, 0, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 2, 2, 0, 0, 2, 2, 1, 1, 0, 1, 2, 0, \ 0, 1, 2, 0, 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 1, 0, 1, 1, 0, 2, 2, 1, 0, 0, 2, 2, 1, 2, 0, 2, \ 0, 0, 2, 0, 1, 1, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 0, 1, 1, 1, 1, 2, 1, \ 2, 2, 0, 0, 0, 2, 0, 1, 2, 1, 1, 1, 0, 1, 2, 1, 0, 2, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, \ 2, 0, 1, 0, 1, 2, 0, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 2, 0, \ 2, 1, 1, 1, 0, 1, 0, 2, 1, 1, 2, 1, 1, 2, 1, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 1, 2, 2, \ 0, 2, 2, 1, 2, 0, 0, 1, 1, 1, 2, 2, 0, 2, 0, 1, 1, 0, 2, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 1, \ 2, 1, 2, 1, 0, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 2, 1, 2, 0, 0, 0, 1, 1, 1, 1, 2, 0, 0, 2, 2, \ 2, 1, 0, 2, 2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 0, 0, 1, 2, 2, 1, 0, 1, 1, 2, 2, 1, 1, 2, 0, 2, \ 2, 0, 1, 1, 0, 1, 2, 2, 0, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 0, 2, 1, 0, 0, 0, 2, 2, 1, 1, 2, \ 0]]", ); test( "936851431250/1397", "10", "[9, 2, 6, 6, 1, 6, 0, 7, 6]", "[[3, 8, 4, 3, 9, 5, 1, 3, 2, 4, 2, 6, 6, 2, 8, 4, 8, 9, 6, 2, 0, 6, 1, 5, 6, 0, 4, 8, 6, \ 7, 5, 7, 3, 3, 7, 1, 5, 1, 0, 3, 7, 9]]", ); test( "6369051672525773/4503599627370496", "10", "[1]", "[4, 1, 4, 2, 1, 3, 5, 6, 2, 3, 7, 3, 0, 9, 5, 1, 4, 5, 4, 7, 4, 6, 2, 1, 8, 5, 8, 7, 3, \ 8, 8, 2, 8, 4, 5, 0, 4, 4, 1, 3, 6, 0, 4, 7, 3, 6, 3, 2, 8, 1, 2, 5]", ); test( "884279719003555/281474976710656", "10", "[3]", "[1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 1, 1, 5, 9, 9, 7, 9, 6, 3, 4, 6, 8, 5, 4, \ 4, 1, 8, 5, 1, 6, 1, 5, 9, 0, 5, 7, 6, 1, 7, 1, 8, 7, 5]", ); test( "6121026514868073/2251799813685248", "10", "[2]", "[7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9, 0, 4, 5, 0, 9, 0, 7, 9, 5, 5, 9, 8, 2, 9, 8, 4, 2, \ 7, 6, 4, 8, 8, 4, 2, 3, 3, 4, 7, 4, 7, 3, 1, 4, 4, 5, 3, 1, 2, 5]", ); } #[test] #[should_panic] fn to_digits_fail_1() { Rational::ONE.to_digits(&Natural::ONE); } #[test] #[should_panic] fn to_digits_fail_2() { Rational::ONE.to_digits(&Natural::ZERO); } #[test] #[should_panic] fn into_digits_fail_1() { Rational::ONE.into_digits(&Natural::ONE); } #[test] #[should_panic] fn into_digits_fail_2() { Rational::ONE.into_digits(&Natural::ZERO); } #[test] fn to_digits_properties() { rational_natural_pair_gen_var_2().test_properties(|(x, base)| { let (before_point, after_point) = x.to_digits(&base); let (before_point_alt, after_point_alt) = x.clone().into_digits(&base); assert_eq!(before_point, before_point_alt); assert_eq!(after_point, after_point_alt); let (before_point, after_point) = (-&x).into_digits(&base); assert_eq!(before_point, before_point_alt); assert_eq!(after_point, after_point_alt); assert_eq!( Rational::from_digits_ref(&base, &before_point, &after_point), (&x).abs() ); assert_ne!(after_point.slices_ref().1, &[Natural::ZERO]); assert_ne!(after_point.slices_ref().1, &[&base - Natural::ONE]); assert_eq!(after_point.is_empty(), x.is_integer()); let before_point_alt: Vec = x.abs().floor().unsigned_abs().to_digits_asc(&base); assert_eq!(before_point_alt, before_point); }); natural_pair_gen_var_2().test_properties(|(n, base)| { assert_eq!( Rational::from(&n).into_digits(&base), ( n.to_digits_asc(&base), RationalSequence::from_vec(Vec::new()) ) ); }); } ================================================ FILE: malachite-q/tests/conversion/digits/to_power_of_2_digits.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, Floor, IsPowerOf2, UnsignedAbs}; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::conversion::traits::{IsInteger, PowerOf2Digits}; use malachite_base::num::logic::traits::LowMask; use malachite_base::rational_sequences::RationalSequence; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_unsigned_pair_gen_var_7; use malachite_q::Rational; use malachite_q::test_util::generators::rational_unsigned_pair_gen_var_2; use std::str::FromStr; #[test] fn test_to_power_of_2_digits() { let test = |x: &str, log_base: u64, before_out: &str, after_out: &str| { let x = Rational::from_str(x).unwrap(); let (before, after) = x.to_power_of_2_digits(log_base); let (before_alt, after_alt) = x.into_power_of_2_digits(log_base); assert_eq!(before, before_alt); assert_eq!(after, after_alt); assert_eq!(before.to_debug_string(), before_out); assert_eq!(after.to_string(), after_out); }; test("0", 1, "[]", "[]"); test("0", 10, "[]", "[]"); test("1", 1, "[1]", "[]"); test("1", 10, "[1]", "[]"); test("1/2", 1, "[]", "[1]"); test("1/2", 10, "[]", "[512]"); test("1/3", 1, "[]", "[[0, 1]]"); test("1/3", 10, "[]", "[[341]]"); test("7/6", 1, "[1]", "[0, [0, 1]]"); test("7/6", 10, "[1]", "[170, [682]]"); test("22/7", 1, "[1, 1]", "[[0, 0, 1]]"); test("22/7", 10, "[3]", "[[146, 292, 585]]"); test( "936851431250/1397", 1, "[1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \ 1]", "[[0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, \ 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, \ 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1]]", ); test( "936851431250/1397", 10, "[53, 563, 639]", "[[393, 635, 522, 643, 587, 135, 619]]", ); test( "6369051672525773/4503599627370496", 10, "[1]", "[424, 158, 409, 1011, 755, 256]", ); test( "884279719003555/281474976710656", 10, "[3]", "[144, 1014, 674, 133, 652]", ); test( "6121026514868073/2251799813685248", 10, "[2]", "[735, 533, 88, 650, 948, 512]", ); } #[test] #[should_panic] fn to_power_of_2_digits_fail() { Rational::ONE.to_power_of_2_digits(0); } #[test] #[should_panic] fn into_power_of_2_digits_fail() { Rational::ONE.into_power_of_2_digits(0); } #[test] fn to_power_of_2_digits_properties() { rational_unsigned_pair_gen_var_2().test_properties(|(x, log_base)| { let (before_point, after_point) = x.to_power_of_2_digits(log_base); let (before_point_alt, after_point_alt) = x.clone().into_power_of_2_digits(log_base); assert_eq!(before_point, before_point_alt); assert_eq!(after_point, after_point_alt); let (before_point, after_point) = (-&x).into_power_of_2_digits(log_base); assert_eq!(before_point, before_point_alt); assert_eq!(after_point, after_point_alt); assert_eq!( Rational::from_power_of_2_digits_ref(log_base, &before_point, &after_point), (&x).abs() ); assert_ne!(after_point.slices_ref().1, &[Natural::ZERO]); assert_ne!(after_point.slices_ref().1, &[Natural::low_mask(log_base)]); assert_eq!(after_point.is_empty(), x.is_integer()); assert_eq!( after_point.slices_ref().1.is_empty(), x.denominator_ref().is_power_of_2() ); let before_point_alt: Vec = x .abs() .floor() .unsigned_abs() .to_power_of_2_digits_asc(log_base); assert_eq!(before_point_alt, before_point); }); natural_unsigned_pair_gen_var_7().test_properties(|(n, log_base)| { assert_eq!( Rational::from(&n).into_power_of_2_digits(log_base), ( n.to_power_of_2_digits_asc(log_base), RationalSequence::from_vec(Vec::new()) ) ); }); } ================================================ FILE: malachite-q/tests/conversion/from_bool.rs ================================================ // Copyright © 2026 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 malachite_q::Rational; #[test] fn test_from_bool() { let test = |b, s| { let n = Rational::from(b); assert!(n.is_valid()); assert_eq!(n.to_string(), s); }; test(false, "0"); test(true, "1"); } ================================================ FILE: malachite-q/tests/conversion/from_float_simplest.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::conversion::traits::RoundingFrom; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::primitive_float_gen_var_8; use malachite_q::Rational; use malachite_q::conversion::from_primitive_float::RationalFromPrimitiveFloatError; use malachite_q::test_util::generators::rational_gen_var_7; #[test] fn test_try_from_f32_simplest() { let test = |f: f32, out| { let x = Rational::try_from_float_simplest(f); assert_eq!(x.to_debug_string(), out); if let Ok(x) = x { assert!(x.is_valid()); } }; test(f32::NAN, "Err(RationalFromPrimitiveFloatError)"); test(f32::INFINITY, "Err(RationalFromPrimitiveFloatError)"); test( f32::NEGATIVE_INFINITY, "Err(RationalFromPrimitiveFloatError)", ); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967296)"); test(-4294967295.0, "Ok(-4294967296)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000002004087734272)"); test(-1.0e20, "Ok(-100000002004087734272)"); test(1.23e20, "Ok(122999999650278146048)"); test(-1.23e20, "Ok(-122999999650278146048)"); test(123.1, "Ok(1231/10)"); test(-123.1, "Ok(-1231/10)"); test(123.9, "Ok(1239/10)"); test(-123.9, "Ok(-1239/10)"); test(123.5, "Ok(247/2)"); test(-123.5, "Ok(-247/2)"); test(124.5, "Ok(249/2)"); test(-124.5, "Ok(-249/2)"); test(-0.499, "Ok(-499/1000)"); test(-0.5, "Ok(-1/2)"); test(0.1, "Ok(1/10)"); test( f32::MIN_POSITIVE_SUBNORMAL, "Ok(1/475749230901986627019428656483165045460915542)", ); test( -f32::MIN_POSITIVE_SUBNORMAL, "Ok(-1/475749230901986627019428656483165045460915542)", ); test( f32::MAX_SUBNORMAL, "Ok(1/85070596800837319010234175901631774785)", ); test( -f32::MAX_SUBNORMAL, "Ok(-1/85070596800837319010234175901631774785)", ); test( f32::MIN_POSITIVE_NORMAL, "Ok(1/85070586659632517184362935130987167681)", ); test( -f32::MIN_POSITIVE_NORMAL, "Ok(-1/85070586659632517184362935130987167681)", ); test( f32::MAX_FINITE, "Ok(340282346638528859811704183484516925440)", ); test( -f32::MAX_FINITE, "Ok(-340282346638528859811704183484516925440)", ); test(std::f32::consts::SQRT_2, "Ok(4756/3363)"); test(std::f32::consts::PI, "Ok(93343/29712)"); test(std::f32::consts::E, "Ok(2721/1001)"); test(0.33333334, "Ok(1/3)"); test(0.3333333, "Ok(3195660/9586981)"); } #[test] fn test_try_from_f64_simplest() { let test = |f: f64, out| { let x = Rational::try_from_float_simplest(f); assert_eq!(x.to_debug_string(), out); if let Ok(x) = x { assert!(x.is_valid()); } }; test(f64::NAN, "Err(RationalFromPrimitiveFloatError)"); test(f64::INFINITY, "Err(RationalFromPrimitiveFloatError)"); test( f64::NEGATIVE_INFINITY, "Err(RationalFromPrimitiveFloatError)", ); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967295)"); test(-4294967295.0, "Ok(-4294967295)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000000000000000000)"); test(-1.0e20, "Ok(-100000000000000000000)"); test(1.23e20, "Ok(123000000000000000000)"); test(-1.23e20, "Ok(-123000000000000000000)"); test( 1.0e100, "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ 469985856815104)", ); test( -1.0e100, "Ok(-1000000000000000015902891109759918046836080856394528138978132755774783877217038106081\ 3469985856815104)", ); test( 1.23e100, "Ok(12300000000000000836686295084537585379506223785413935301425289783235883702867663918638\ 982200322686976)", ); test( -1.23e100, "Ok(-1230000000000000083668629508453758537950622378541393530142528978323588370286766391863\ 8982200322686976)", ); test(123.1, "Ok(1231/10)"); test(-123.1, "Ok(-1231/10)"); test(123.9, "Ok(1239/10)"); test(-123.9, "Ok(-1239/10)"); test(123.5, "Ok(247/2)"); test(-123.5, "Ok(-247/2)"); test(124.5, "Ok(249/2)"); test(-124.5, "Ok(-249/2)"); test(-0.499, "Ok(-499/1000)"); test(-0.5, "Ok(-1/2)"); test( f64::MIN_POSITIVE_SUBNORMAL, "Ok(1/134934835538207078901663564479278204699704433176094745571267572018286893045330231261\ 306922467624749663458051909544541274259872491590528984578008933293825673281011616184377574\ 242977938494728810894159845118981830045708004988949795132412068903766106370893873371008239\ 179701555609743487001688124218339097337508871805160728996523)", ); test( -f64::MIN_POSITIVE_SUBNORMAL, "Ok(-1/13493483553820707890166356447927820469970443317609474557126757201828689304533023126\ 130692246762474966345805190954454127425987249159052898457800893329382567328101161618437757\ 424297793849472881089415984511898183004570800498894979513241206890376610637089387337100823\ 9179701555609743487001688124218339097337508871805160728996523)", ); test( f64::MAX_SUBNORMAL, "Ok(1/449423283715579026828334036065257014383474871770369402158895481105061903177076758952\ 991447760350212414247530205607522865754608382719974023705572587637923509973673766132988527\ 495573581641607121816936686895147170329503865639571478615835487722625286251243883901055723\ 06631238281271786009918606677660346752204801)", ); test( -f64::MAX_SUBNORMAL, "Ok(-1/44942328371557902682833403606525701438347487177036940215889548110506190317707675895\ 299144776035021241424753020560752286575460838271997402370557258763792350997367376613298852\ 749557358164160712181693668689514717032950386563957147861583548772262528625124388390105572\ 306631238281271786009918606677660346752204801)", ); test( f64::MIN_POSITIVE_NORMAL, "Ok(1/449423283715578927036318559329266431564839219927211067229101097246506353572882385286\ 930040496229077692647131520826525095187415228669222594373726590254689108839132120159189741\ 421503549517982068519788656012202297150024869750306233834035420571989467252315767391654946\ 28061906253051009157224240331719237716377601)", ); test( -f64::MIN_POSITIVE_NORMAL, "Ok(-1/44942328371557892703631855932926643156483921992721106722910109724650635357288238528\ 693004049622907769264713152082652509518741522866922259437372659025468910883913212015918974\ 142150354951798206851978865601220229715002486975030623383403542057198946725231576739165494\ 628061906253051009157224240331719237716377601)", ); test( f64::MAX_FINITE, "Ok(17976931348623157081452742373170435679807056752584499659891747680315726078002853876058\ 955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207\ 624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472\ 3168738177180919299881250404026184124858368)", ); test( -f64::MAX_FINITE, "Ok(-1797693134862315708145274237317043567980705675258449965989174768031572607800285387605\ 895586327668781715404589535143824642343213268894641827684675467035375169860499105765512820\ 762454900903893289440758685084551339423045832369032229481658085593321233482747978262041447\ 23168738177180919299881250404026184124858368)", ); test(std::f64::consts::SQRT_2, "Ok(131836323/93222358)"); test(std::f64::consts::PI, "Ok(245850922/78256779)"); test(std::f64::consts::E, "Ok(268876667/98914198)"); test(0.3333333333333333, "Ok(1/3)"); test(0.3333333333333337, "Ok(279293000147008/837879000441023)"); } #[allow(clippy::trait_duplication_in_bounds)] fn try_from_float_simplest_properties_helper< T: for<'a> RoundingFrom<&'a Rational> + for<'a> TryFrom<&'a Rational> + PrimitiveFloat, >() where Rational: TryFrom, { primitive_float_gen_var_8::().test_properties(|f| { let q = Rational::try_from_float_simplest(f); if let Ok(q) = q { assert!(q.is_valid()); assert_eq!(Rational::try_from_float_simplest(-f), Ok(-&q)); } }); rational_gen_var_7().test_properties(|q| { // This only works for simple `Rational`s, i.e. those `Rational`s q that round to a float x // such that no simpler `Rational` rounds to x. This test will eventually fail, e.g. for // 3571/5778, which is very close to 1/phi. But as long as only the first 10,000 inputs in // each generation mode are tested, it will succeed. assert_eq!( Rational::try_from_float_simplest(T::rounding_from(&q, Nearest).0), Ok(q) ); }); } #[test] fn try_from_float_simplest_properties() { apply_fn_to_primitive_floats!(try_from_float_simplest_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/from_integer.rs ================================================ // Copyright © 2026 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 malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_from_integer() { let test = |s| { let u = Integer::from_str(s).unwrap(); let x = Rational::from(u.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), s); let x = Rational::from(&u); assert!(x.is_valid()); assert_eq!(x.to_string(), s); }; test("0"); test("123"); test("1000000000000"); test("-123"); test("-1000000000000"); } #[test] fn from_integer_properties() { integer_gen().test_properties(|x| { let rational_x = Rational::from(x.clone()); assert!(rational_x.is_valid()); assert_eq!(rational_x.to_string(), x.to_string()); let rational_x_alt = Rational::from(&x); assert!(rational_x_alt.is_valid()); assert_eq!(rational_x_alt, rational_x); assert_eq!(Integer::try_from(&rational_x).as_ref(), Ok(&x)); assert_eq!(Integer::try_from(rational_x), Ok(x)); }); } ================================================ FILE: malachite-q/tests/conversion/from_natural.rs ================================================ // Copyright © 2026 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 malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use malachite_q::Rational; use std::str::FromStr; #[test] fn test_from_natural() { let test = |s| { let u = Natural::from_str(s).unwrap(); let x = Rational::from(u.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), s); let x = Rational::from(&u); assert!(x.is_valid()); assert_eq!(x.to_string(), s); }; test("0"); test("123"); test("1000000000000"); } #[test] fn from_natural_properties() { natural_gen().test_properties(|x| { let rational_x = Rational::from(x.clone()); assert!(rational_x.is_valid()); assert_eq!(rational_x.to_string(), x.to_string()); let rational_x_alt = Rational::from(&x); assert!(rational_x_alt.is_valid()); assert_eq!(rational_x_alt, rational_x); assert_eq!(Natural::try_from(&rational_x).as_ref(), Ok(&x)); assert_eq!(Natural::try_from(rational_x), Ok(x)); }); } ================================================ FILE: malachite-q/tests/conversion/from_numerator_and_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{CoprimeWith, UnsignedAbs}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::{One, Zero}; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{ signed_gen, signed_pair_gen_var_6, unsigned_gen, unsigned_pair_gen_var_12, unsigned_unsigned_bool_triple_gen_var_2, }; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_nz::test_util::generators::{ integer_gen, integer_pair_gen_var_1, natural_gen, natural_natural_bool_triple_gen_var_1, natural_pair_gen_var_5, }; use malachite_q::Rational; use num::{BigInt, BigRational}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_from_naturals() { let test = |n, d, out| { let n = Natural::from_str(n).unwrap(); let d = Natural::from_str(d).unwrap(); let x = Rational::from_naturals(n.clone(), d.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); let x = Rational::from_naturals_ref(&n, &d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test("0", "1", "0"); test("0", "5", "0"); test("3", "6", "1/2"); test("100", "101", "100/101"); } #[test] fn from_naturals_fail() { assert_panic!(Rational::from_naturals(Natural::ZERO, Natural::ZERO)); assert_panic!(Rational::from_naturals(Natural::ONE, Natural::ZERO)); assert_panic!(Rational::from_naturals_ref(&Natural::ZERO, &Natural::ZERO)); assert_panic!(Rational::from_naturals_ref(&Natural::ONE, &Natural::ZERO)); } #[test] fn from_naturals_properties() { natural_pair_gen_var_5().test_properties(|(n, d)| { let x = Rational::from_naturals(n.clone(), d.clone()); assert!(x.is_valid()); let x_alt = Rational::from_naturals_ref(&n, &d); assert!(x.is_valid()); assert_eq!(x, x_alt); if (&n).coprime_with(&d) { assert_eq!(x.into_numerator_and_denominator(), (n, d)); } }); natural_gen() .test_properties(|n| assert_eq!(Rational::from_naturals_ref(&n, &Natural::ONE), n)); } fn test_from_unsigneds_helper() where Natural: From, Limb: ExactFrom, { let test = |n: u8, d: u8, out| { let n = T::from(n); let d = T::from(d); let x = Rational::from_unsigneds(n, d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); if T::WIDTH == Limb::WIDTH { let x_alt = Rational::const_from_unsigneds(Limb::exact_from(n), Limb::exact_from(d)); assert!(x_alt.is_valid()); assert!(PartialEq::::eq(&x_alt, &x)); } }; test(0, 1, "0"); test(0, 5, "0"); test(3, 6, "1/2"); test(100, 101, "100/101"); } fn from_unsigneds_fail_helper() where Natural: From, { assert_panic!(Rational::from_unsigneds(T::ZERO, T::ZERO)); assert_panic!(Rational::from_unsigneds(T::ONE, T::ZERO)); } #[test] fn from_unsigneds_fail() { apply_fn_to_unsigneds!(from_unsigneds_fail_helper); } #[test] fn test_from_unsigneds() { apply_fn_to_unsigneds!(test_from_unsigneds_helper); } #[test] fn test_const_from_unsigneds() { let test = |n: Limb, d: Limb, out| { let x = Rational::from_unsigneds(n, d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); let x_alt = Rational::const_from_unsigneds(Limb::exact_from(n), Limb::exact_from(d)); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); }; test(0, 1, "0"); test(0, 5, "0"); test(3, 6, "1/2"); test(100, 101, "100/101"); // The following test case has the highest number of steps in the Euclidean GCD algorithm. #[cfg(not(feature = "32_bit_limbs"))] test( 7540113804746346429, 12200160415121876738, "7540113804746346429/12200160415121876738", ); #[cfg(not(feature = "32_bit_limbs"))] test( 7540113804746346430, 12200160415121876738, "3770056902373173215/6100080207560938369", ); } #[test] fn const_from_unsigneds_fail() { assert_panic!(Rational::const_from_unsigneds(0, 0)); assert_panic!(Rational::const_from_unsigneds(1, 0)); } fn from_unsigneds_properties_helper() where Natural: From + PartialEq, Rational: PartialEq, Limb: ExactFrom, { unsigned_pair_gen_var_12::().test_properties(|(n, d)| { let x = Rational::from_unsigneds(n, d); assert!(x.is_valid()); if n.coprime_with(d) { let (n_alt, d_alt) = x.clone().into_numerator_and_denominator(); assert_eq!(n_alt, n); assert_eq!(d_alt, d); } if T::WIDTH == Limb::WIDTH { let x_alt = Rational::const_from_unsigneds(Limb::exact_from(n), Limb::exact_from(d)); assert!(x_alt.is_valid()); assert!(PartialEq::::eq(&x_alt, &x)); } }); unsigned_gen::().test_properties(|n| assert_eq!(Rational::from_unsigneds(n, T::ONE), n)); } #[test] fn from_unsigneds_properties() { apply_fn_to_unsigneds!(from_unsigneds_properties_helper); } #[test] fn const_from_unsigneds_properties() { unsigned_pair_gen_var_12::().test_properties(|(n, d)| { let x = Rational::from_unsigneds(n, d); let x_alt = Rational::const_from_unsigneds(n, d); assert!(x_alt.is_valid()); assert_eq!(x_alt, x); }); } #[test] fn test_from_integers() { let test = |s, t, out| { let n = Integer::from_str(s).unwrap(); let d = Integer::from_str(t).unwrap(); let x = Rational::from_integers(n.clone(), d.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); let x = Rational::from_integers_ref(&n, &d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); assert_eq!( BigRational::new(BigInt::from_str(s).unwrap(), BigInt::from_str(t).unwrap()) .to_string(), out ); assert_eq!( rug::Rational::from(( rug::Integer::from_str(s).unwrap(), rug::Integer::from_str(t).unwrap() )) .to_string(), out ); }; test("0", "1", "0"); test("0", "-1", "0"); test("0", "5", "0"); test("0", "-5", "0"); test("3", "6", "1/2"); test("3", "-6", "-1/2"); test("-3", "6", "-1/2"); test("-3", "-6", "1/2"); test("100", "101", "100/101"); test("100", "-101", "-100/101"); test("-100", "101", "-100/101"); test("-100", "-101", "100/101"); } #[test] fn from_integers_fail() { assert_panic!(Rational::from_integers(Integer::ZERO, Integer::ZERO)); assert_panic!(Rational::from_integers(Integer::ONE, Integer::ZERO)); assert_panic!(Rational::from_integers_ref(&Integer::ZERO, &Integer::ZERO)); assert_panic!(Rational::from_integers_ref(&Integer::ONE, &Integer::ZERO)); } #[test] fn from_integers_properties() { integer_pair_gen_var_1().test_properties(|(n, d)| { let x = Rational::from_integers(n.clone(), d.clone()); assert!(x.is_valid()); let x_alt = Rational::from_integers_ref(&n, &d); assert!(x.is_valid()); assert_eq!(x, x_alt); assert_eq!( Rational::from(&BigRational::new(BigInt::from(&n), BigInt::from(&d))), x ); assert_eq!( Rational::from(&rug::Rational::from(( rug::Integer::from(&n), rug::Integer::from(&d) ))), x ); if n != 0 { assert_eq!(x >= 0, (n >= 0) == (d >= 0)); } if n >= 0 && d > 0 && (n.unsigned_abs_ref()).coprime_with(d.unsigned_abs_ref()) { let (n_2, d_2) = x.into_numerator_and_denominator(); assert_eq!((Integer::from(n_2), Integer::from(d_2)), (n, d)); } }); integer_gen() .test_properties(|n| assert_eq!(Rational::from_integers_ref(&n, &Integer::ONE), n)); } fn test_from_signeds_helper() where Integer: From, SignedLimb: ExactFrom, { let test = |n: i8, d: i8, out| { let n = T::from(n); let d = T::from(d); let x = Rational::from_signeds(n, d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); if T::WIDTH == Limb::WIDTH { let x_alt = Rational::const_from_signeds(SignedLimb::exact_from(n), SignedLimb::exact_from(d)); assert!(x_alt.is_valid()); assert!(PartialEq::::eq(&x_alt, &x)); } }; test(0, 1, "0"); test(0, -1, "0"); test(0, 5, "0"); test(0, -5, "0"); test(3, 6, "1/2"); test(3, -6, "-1/2"); test(-3, 6, "-1/2"); test(-3, -6, "1/2"); test(100, 101, "100/101"); test(100, -101, "-100/101"); test(-100, 101, "-100/101"); test(-100, -101, "100/101"); } #[test] fn test_from_signeds() { apply_fn_to_signeds!(test_from_signeds_helper); } fn from_signeds_fail_helper() where Integer: From, { assert_panic!(Rational::from_signeds(T::ZERO, T::ZERO)); assert_panic!(Rational::from_signeds(T::ONE, T::ZERO)); } #[test] fn from_signeds_fail() { apply_fn_to_signeds!(from_signeds_fail_helper); } #[test] fn const_from_signeds_fail() { assert_panic!(Rational::const_from_signeds(0, 0)); assert_panic!(Rational::const_from_signeds(1, 0)); } fn from_signeds_properties_helper() where Integer: From, rug::Rational: From<(T, T)>, ::Output: CoprimeWith, Natural: PartialEq, Rational: PartialEq, SignedLimb: ExactFrom, { signed_pair_gen_var_6::().test_properties(|(n, d)| { let x = Rational::from_signeds(n, d); assert!(x.is_valid()); let x_alt = Rational::from(&rug::Rational::from((n, d))); assert!(PartialEq::::eq(&x_alt, &x)); if n != T::ZERO { assert_eq!( PartialOrd::::ge(&x, &0u32), (n >= T::ZERO) == (d >= T::ZERO) ); } if n >= T::ZERO && d > T::ZERO && (n.unsigned_abs()).coprime_with(d.unsigned_abs()) { let (n_2, d_2) = x.clone().into_numerator_and_denominator(); assert_eq!(n_2, n); assert_eq!(d_2, d); } if T::WIDTH == Limb::WIDTH { let x_alt = Rational::const_from_signeds(SignedLimb::exact_from(n), SignedLimb::exact_from(d)); assert!(x_alt.is_valid()); assert!(PartialEq::::eq(&x_alt, &x)); } }); signed_gen::().test_properties(|n| assert_eq!(Rational::from_signeds(n, T::ONE), n)); } #[test] fn from_signeds_properties() { apply_fn_to_signeds!(from_signeds_properties_helper); } #[test] fn const_from_signeds_properties() { signed_pair_gen_var_6::().test_properties(|(n, d)| { let x = Rational::from_signeds(n, d); let x_alt = Rational::const_from_signeds(n, d); assert!(x_alt.is_valid()); assert_eq!(x_alt, x); }); } #[test] fn test_from_sign_and_naturals() { let test = |sign, n, d, out| { let n = Natural::from_str(n).unwrap(); let d = Natural::from_str(d).unwrap(); let x = Rational::from_sign_and_naturals(sign, n.clone(), d.clone()); assert!(x.is_valid()); assert_eq!(x.to_string(), out); let x = Rational::from_sign_and_naturals_ref(sign, &n, &d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(false, "0", "1", "0"); test(true, "0", "1", "0"); test(false, "0", "5", "0"); test(true, "0", "5", "0"); test(false, "3", "6", "-1/2"); test(true, "3", "6", "1/2"); test(false, "100", "101", "-100/101"); test(true, "100", "101", "100/101"); } #[test] fn from_sign_and_naturals_properties() { natural_natural_bool_triple_gen_var_1().test_properties(|(n, d, sign)| { let x = Rational::from_sign_and_naturals(sign, n.clone(), d.clone()); assert!(x.is_valid()); let x_alt = Rational::from_sign_and_naturals_ref(sign, &n, &d); assert!(x.is_valid()); assert_eq!(x, x_alt); if n != 0 { assert_eq!(x >= 0, sign); } if (&n).coprime_with(&d) { assert_eq!(x.into_numerator_and_denominator(), (n, d)); } }); natural_pair_gen_var_5().test_properties(|(n, d)| { assert_eq!( Rational::from_naturals(n.clone(), d.clone()), Rational::from_sign_and_naturals(true, n, d) ); }); natural_gen().test_properties(|n| { assert_eq!( Rational::from_sign_and_naturals_ref(true, &n, &Natural::ONE), n ); }); } fn test_from_sign_and_unsigneds_helper() where Natural: From, { let test = |sign, n: u8, d: u8, out| { let n = T::from(n); let d = T::from(d); let x = Rational::from_sign_and_unsigneds(sign, n, d); assert!(x.is_valid()); assert_eq!(x.to_string(), out); }; test(false, 0, 1, "0"); test(true, 0, 1, "0"); test(false, 0, 5, "0"); test(true, 0, 5, "0"); test(false, 3, 6, "-1/2"); test(true, 3, 6, "1/2"); test(false, 100, 101, "-100/101"); test(true, 100, 101, "100/101"); } #[test] fn test_from_sign_and_unsigneds() { apply_fn_to_unsigneds!(test_from_sign_and_unsigneds_helper); } fn from_sign_and_unsigneds_properties_helper() where Natural: From + PartialEq, Rational: PartialEq, { unsigned_unsigned_bool_triple_gen_var_2::().test_properties(|(n, d, sign)| { let x = Rational::from_sign_and_unsigneds(sign, n, d); assert!(x.is_valid()); if n != T::ZERO { assert_eq!(PartialOrd::::ge(&x, &0u32), sign); } if n.coprime_with(d) { let (n_alt, d_alt) = x.into_numerator_and_denominator(); assert_eq!(n_alt, n); assert_eq!(d_alt, d); } }); unsigned_pair_gen_var_12::().test_properties(|(n, d)| { assert!(PartialEq::::eq( &Rational::from_unsigneds(n, d), &Rational::from_sign_and_unsigneds(true, n, d) )); }); unsigned_gen::() .test_properties(|n| assert_eq!(Rational::from_sign_and_unsigneds(true, n, T::ONE), n)); } #[test] fn from_sign_and_unsigneds_properties() { apply_fn_to_unsigneds!(from_sign_and_unsigneds_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/from_primitive_float.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::strings::ToDebugString; use malachite_base::test_util::generators::{primitive_float_gen, primitive_float_gen_var_8}; use malachite_q::Rational; #[test] fn test_try_from_f32() { let test = |f: f32, out| { let x = Rational::try_from(f); assert_eq!(x.to_debug_string(), out); if let Ok(x) = x { assert!(x.is_valid()); } }; test(f32::NAN, "Err(RationalFromPrimitiveFloatError)"); test(f32::INFINITY, "Err(RationalFromPrimitiveFloatError)"); test( f32::NEGATIVE_INFINITY, "Err(RationalFromPrimitiveFloatError)", ); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967296)"); test(-4294967295.0, "Ok(-4294967296)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000002004087734272)"); test(-1.0e20, "Ok(-100000002004087734272)"); test(1.23e20, "Ok(122999999650278146048)"); test(-1.23e20, "Ok(-122999999650278146048)"); test(123.1, "Ok(16134963/131072)"); test(-123.1, "Ok(-16134963/131072)"); test(123.9, "Ok(16239821/131072)"); test(-123.9, "Ok(-16239821/131072)"); test(123.5, "Ok(247/2)"); test(-123.5, "Ok(-247/2)"); test(124.5, "Ok(249/2)"); test(-124.5, "Ok(-249/2)"); test(-0.499, "Ok(-8371831/16777216)"); test(-0.5, "Ok(-1/2)"); test(0.1, "Ok(13421773/134217728)"); test( f32::MIN_POSITIVE_SUBNORMAL, "Ok(1/713623846352979940529142984724747568191373312)", ); test( -f32::MIN_POSITIVE_SUBNORMAL, "Ok(-1/713623846352979940529142984724747568191373312)", ); test( f32::MAX_SUBNORMAL, "Ok(8388607/713623846352979940529142984724747568191373312)", ); test( -f32::MAX_SUBNORMAL, "Ok(-8388607/713623846352979940529142984724747568191373312)", ); test( f32::MIN_POSITIVE_NORMAL, "Ok(1/85070591730234615865843651857942052864)", ); test( -f32::MIN_POSITIVE_NORMAL, "Ok(-1/85070591730234615865843651857942052864)", ); test( f32::MAX_FINITE, "Ok(340282346638528859811704183484516925440)", ); test( -f32::MAX_FINITE, "Ok(-340282346638528859811704183484516925440)", ); test(std::f32::consts::SQRT_2, "Ok(11863283/8388608)"); test(std::f32::consts::PI, "Ok(13176795/4194304)"); test(std::f32::consts::E, "Ok(2850325/1048576)"); } #[test] fn test_try_from_f64() { let test = |f: f64, out| { let x = Rational::try_from(f); assert_eq!(x.to_debug_string(), out); if let Ok(x) = x { assert!(x.is_valid()); } }; test(f64::NAN, "Err(RationalFromPrimitiveFloatError)"); test(f64::INFINITY, "Err(RationalFromPrimitiveFloatError)"); test( f64::NEGATIVE_INFINITY, "Err(RationalFromPrimitiveFloatError)", ); test(0.0, "Ok(0)"); test(-0.0, "Ok(0)"); test(123.0, "Ok(123)"); test(-123.0, "Ok(-123)"); test(1.0e9, "Ok(1000000000)"); test(-1.0e9, "Ok(-1000000000)"); test(4294967295.0, "Ok(4294967295)"); test(-4294967295.0, "Ok(-4294967295)"); test(4294967296.0, "Ok(4294967296)"); test(-4294967296.0, "Ok(-4294967296)"); test(18446744073709551615.0, "Ok(18446744073709551616)"); test(-18446744073709551615.0, "Ok(-18446744073709551616)"); test(18446744073709551616.0, "Ok(18446744073709551616)"); test(-18446744073709551616.0, "Ok(-18446744073709551616)"); test(1.0e20, "Ok(100000000000000000000)"); test(-1.0e20, "Ok(-100000000000000000000)"); test(1.23e20, "Ok(123000000000000000000)"); test(-1.23e20, "Ok(-123000000000000000000)"); test( 1.0e100, "Ok(10000000000000000159028911097599180468360808563945281389781327557747838772170381060813\ 469985856815104)", ); test( -1.0e100, "Ok(-1000000000000000015902891109759918046836080856394528138978132755774783877217038106081\ 3469985856815104)", ); test( 1.23e100, "Ok(12300000000000000836686295084537585379506223785413935301425289783235883702867663918638\ 982200322686976)", ); test( -1.23e100, "Ok(-1230000000000000083668629508453758537950622378541393530142528978323588370286766391863\ 8982200322686976)", ); test(123.1, "Ok(4331196204135219/35184372088832)"); test(-123.1, "Ok(-4331196204135219/35184372088832)"); test(123.9, "Ok(4359343701806285/35184372088832)"); test(-123.9, "Ok(-4359343701806285/35184372088832)"); test(123.5, "Ok(247/2)"); test(-123.5, "Ok(-247/2)"); test(124.5, "Ok(249/2)"); test(-124.5, "Ok(-249/2)"); test(-0.499, "Ok(-4494592428115755/9007199254740992)"); test(-0.5, "Ok(-1/2)"); test( f64::MIN_POSITIVE_SUBNORMAL, "Ok(1/202402253307310618352495346718917307049556649764142118356901358027430339567995346891\ 960383701437124495187077864316811911389808737385793476867013399940738509921517424276566361\ 364466907742093216341239767678472745068562007483424692698618103355649159556340810056512358\ 769552333414615230502532186327508646006263307707741093494784)", ); test( -f64::MIN_POSITIVE_SUBNORMAL, "Ok(-1/20240225330731061835249534671891730704955664976414211835690135802743033956799534689\ 196038370143712449518707786431681191138980873738579347686701339994073850992151742427656636\ 136446690774209321634123976767847274506856200748342469269861810335564915955634081005651235\ 8769552333414615230502532186327508646006263307707741093494784)", ); test( f64::MAX_SUBNORMAL, "Ok(4503599627370495/202402253307310618352495346718917307049556649764142118356901358027430\ 339567995346891960383701437124495187077864316811911389808737385793476867013399940738509921\ 517424276566361364466907742093216341239767678472745068562007483424692698618103355649159556\ 340810056512358769552333414615230502532186327508646006263307707741093494784)", ); test( -f64::MAX_SUBNORMAL, "Ok(-4503599627370495/20240225330731061835249534671891730704955664976414211835690135802743\ 033956799534689196038370143712449518707786431681191138980873738579347686701339994073850992\ 151742427656636136446690774209321634123976767847274506856200748342469269861810335564915955\ 6340810056512358769552333414615230502532186327508646006263307707741093494784)", ); test( f64::MIN_POSITIVE_NORMAL, "Ok(1/449423283715578976932326297697256183404494244735576643183575202894331689513752407831\ 771193306018840052800284699678483394146974422036041556232118576598685310944419733562163713\ 190755549003115235298632707380212514422095376705856157203684782776352068092908376276711465\ 74559986811484619929076208839082406056034304)", ); test( -f64::MIN_POSITIVE_NORMAL, "Ok(-1/44942328371557897693232629769725618340449424473557664318357520289433168951375240783\ 177119330601884005280028469967848339414697442203604155623211857659868531094441973356216371\ 319075554900311523529863270738021251442209537670585615720368478277635206809290837627671146\ 574559986811484619929076208839082406056034304)", ); test( f64::MAX_FINITE, "Ok(17976931348623157081452742373170435679807056752584499659891747680315726078002853876058\ 955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207\ 624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472\ 3168738177180919299881250404026184124858368)", ); test( -f64::MAX_FINITE, "Ok(-1797693134862315708145274237317043567980705675258449965989174768031572607800285387605\ 895586327668781715404589535143824642343213268894641827684675467035375169860499105765512820\ 762454900903893289440758685084551339423045832369032229481658085593321233482747978262041447\ 23168738177180919299881250404026184124858368)", ); test( std::f64::consts::SQRT_2, "Ok(6369051672525773/4503599627370496)", ); test(std::f64::consts::PI, "Ok(884279719003555/281474976710656)"); test(std::f64::consts::E, "Ok(6121026514868073/2251799813685248)"); } #[test] fn test_rational_convertible_from_f32() { let test = |f: f32, out| { assert_eq!(Rational::convertible_from(f), out); }; test(0.0, true); test(1.0, true); test(1.5, true); test(0.1, true); test(f32::NAN, false); test(f32::INFINITY, false); test(f32::NEGATIVE_INFINITY, false); } #[test] fn test_rational_convertible_from_f64() { let test = |f: f64, out| { assert_eq!(Rational::convertible_from(f), out); }; test(0.0, true); test(1.0, true); test(1.5, true); test(0.1, true); test(f64::NAN, false); test(f64::INFINITY, false); test(f64::NEGATIVE_INFINITY, false); } fn try_from_float_properties_helper + PrimitiveFloat>() where Rational: ConvertibleFrom + TryFrom, { primitive_float_gen::().test_properties(|f| { let n = Rational::try_from(f); assert_eq!(n.is_ok(), Rational::convertible_from(f)); if let Ok(n) = n { assert!(n.is_valid()); assert_eq!(Rational::exact_from(-f), -&n); assert_eq!( NiceFloat(T::exact_from(n)), NiceFloat(f.abs_negative_zero()) ); } }); } #[test] fn try_from_float_properties() { apply_fn_to_primitive_floats!(try_from_float_properties_helper); primitive_float_gen_var_8::().test_properties(|f| { assert_eq!( Rational::exact_from(f), Rational::from(&rug::Rational::from_f32(f).unwrap()) ); }); primitive_float_gen_var_8::().test_properties(|f| { assert_eq!( Rational::exact_from(f), Rational::from(&rug::Rational::from_f64(f).unwrap()) ); }); } fn rational_convertible_from_primitive_float_properties_helper() where Rational: ConvertibleFrom, { primitive_float_gen().test_properties(|f| { assert_eq!( Rational::convertible_from(f), Rational::convertible_from(-f) ); }); } #[test] fn rational_convertible_from_primitive_float_properties() { apply_fn_to_primitive_floats!(rational_convertible_from_primitive_float_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/from_primitive_int.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::test_util::generators::{signed_gen, signed_gen_var_2, unsigned_gen}; use malachite_nz::natural::Natural; use malachite_nz::platform::{Limb, SignedLimb}; use malachite_q::Rational; use rug; #[test] fn test_from_u32() { let test = |u: u32, out| { let x = Rational::from(u); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(rug::Rational::from(u).to_string(), out); #[cfg(feature = "32_bit_limbs")] { let x_alt = Rational::const_from_unsigned(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u32::MAX, "4294967295"); } #[test] fn test_from_u64() { let test = |u: u64, out| { let x = Rational::from(u); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(rug::Rational::from(u).to_string(), out); #[cfg(not(feature = "32_bit_limbs"))] { let x_alt = Rational::const_from_unsigned(u); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(u64::MAX, "18446744073709551615"); } #[test] fn test_from_i32() { let test = |i: i32, out| { let x = Rational::from(i); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(rug::Rational::from(i).to_string(), out); #[cfg(feature = "32_bit_limbs")] { let x_alt = Rational::const_from_signed(i); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(-123, "-123"); test(i32::MIN, "-2147483648"); test(i32::MAX, "2147483647"); } #[test] fn test_from_i64() { let test = |i: i64, out| { let x = Rational::from(i); assert_eq!(x.to_string(), out); assert!(x.is_valid()); assert_eq!(rug::Rational::from(i).to_string(), out); #[cfg(not(feature = "32_bit_limbs"))] { let x_alt = Rational::const_from_signed(i); assert!(x_alt.is_valid()); assert_eq!(x_alt.to_string(), out); } }; test(0, "0"); test(123, "123"); test(-123, "-123"); test(i64::MIN, "-9223372036854775808"); test(i64::MAX, "9223372036854775807"); } fn from_unsigned_properties_helper TryFrom<&'a Rational> + PrimitiveUnsigned>() where Rational: From, Natural: From, u128: TryFrom, rug::Integer: From, Limb: ExactFrom, { unsigned_gen::().test_properties(|u| { let n = Rational::from(u); assert!(n.is_valid()); assert_eq!(T::exact_from(&n), u); let alt_n: Rational = From::from(Natural::from(u)); assert_eq!(alt_n, n); let alt_n: Rational = From::from(u128::exact_from(u)); assert_eq!(alt_n, n); let alt_n: Rational = From::from(&rug::Rational::from(u)); assert_eq!(alt_n, n); if T::WIDTH == Limb::WIDTH { let n_alt = Rational::const_from_unsigned(Limb::exact_from(u)); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); } fn from_signed_properties_helper TryFrom<&'a Rational> + PrimitiveSigned>() where Rational: From, Natural: TryFrom, i128: TryFrom, rug::Integer: From, SignedLimb: ExactFrom, { signed_gen::().test_properties(|i| { let n = Rational::from(i); assert!(n.is_valid()); assert_eq!(T::exact_from(&n), i); let alt_n: Rational = From::from(i128::exact_from(i)); assert_eq!(alt_n, n); let alt_n: Rational = From::from(&rug::Rational::from(i)); assert_eq!(alt_n, n); if T::WIDTH == Limb::WIDTH { let n_alt = Rational::const_from_signed(SignedLimb::exact_from(i)); assert!(n_alt.is_valid()); assert_eq!(n_alt, n); } }); signed_gen_var_2::().test_properties(|i| { let n: Rational = From::from(Natural::exact_from(i)); assert_eq!(n, Rational::from(i)); }); } #[test] fn from_primitive_int_properties() { apply_fn_to_unsigneds!(from_unsigned_properties_helper); apply_fn_to_signeds!(from_signed_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/integer_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Ceiling, Floor, Parity}; use malachite_base::num::basic::traits::{One, OneHalf, Two}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, IsInteger, RoundingFrom, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, rational_rounding_mode_pair_gen_var_2}; use std::cmp::Ordering::*; use std::str::FromStr; #[test] fn test_try_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); let on = Integer::try_from(u.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Integer::try_from(&u); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("0", "Ok(0)"); test("123", "Ok(123)"); test("-123", "Ok(-123)"); test("1000000000000", "Ok(1000000000000)"); test("-1000000000000", "Ok(-1000000000000)"); test("22/7", "Err(IntegerFromRationalError)"); test("-22/7", "Err(IntegerFromRationalError)"); } #[test] fn test_exact_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); let n = Integer::exact_from(u.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Integer::exact_from(&u); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0"); test("123", "123"); test("-123", "-123"); test("1000000000000", "1000000000000"); test("-1000000000000", "-1000000000000"); } #[test] #[should_panic] fn integer_exact_from_rational_fail() { Integer::exact_from(Rational::from_str("22/7").unwrap()); } #[test] #[should_panic] fn integer_exact_from_rational_ref_fail() { Integer::exact_from(&Rational::from_str("-22/7").unwrap()); } #[test] fn test_convertible_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(Integer::convertible_from(&u), out); }; test("0", true); test("123", true); test("-123", true); test("1000000000000", true); test("-1000000000000", true); test("22/7", false); test("-22/7", false); } #[test] fn test_rounding_from_rational() { let test = |s, rm, out, o_out| { let u = Rational::from_str(s).unwrap(); let (n, o) = Integer::rounding_from(u.clone(), rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); let (n, o) = Integer::rounding_from(&u, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); }; test("123", Floor, "123", Equal); test("123", Down, "123", Equal); test("123", Ceiling, "123", Equal); test("123", Up, "123", Equal); test("123", Nearest, "123", Equal); test("123", Exact, "123", Equal); test("-123", Floor, "-123", Equal); test("-123", Down, "-123", Equal); test("-123", Ceiling, "-123", Equal); test("-123", Up, "-123", Equal); test("-123", Nearest, "-123", Equal); test("-123", Exact, "-123", Equal); test("22/7", Floor, "3", Less); test("22/7", Down, "3", Less); test("22/7", Ceiling, "4", Greater); test("22/7", Up, "4", Greater); test("22/7", Nearest, "3", Less); test("-22/7", Floor, "-4", Less); test("-22/7", Down, "-3", Greater); test("-22/7", Ceiling, "-3", Greater); test("-22/7", Up, "-4", Less); test("-22/7", Nearest, "-3", Greater); test("7/2", Floor, "3", Less); test("7/2", Down, "3", Less); test("7/2", Ceiling, "4", Greater); test("7/2", Up, "4", Greater); test("7/2", Nearest, "4", Greater); test("9/2", Floor, "4", Less); test("9/2", Down, "4", Less); test("9/2", Ceiling, "5", Greater); test("9/2", Up, "5", Greater); test("9/2", Nearest, "4", Less); } #[test] #[should_panic] fn integer_rounding_from_rational_fail() { Integer::rounding_from(Rational::from_str("22/7").unwrap(), Exact); } #[test] #[should_panic] fn integer_rounding_from_rational_ref_fail() { Integer::rounding_from(&Rational::from_str("22/7").unwrap(), Exact); } #[test] fn try_from_rational_properties() { rational_gen().test_properties(|x| { let integer_x = Integer::try_from(x.clone()); assert!(integer_x.as_ref().map_or(true, Integer::is_valid)); let integer_x_alt = Integer::try_from(&x); assert!(integer_x_alt.as_ref().map_or(true, Integer::is_valid)); assert_eq!(integer_x, integer_x_alt); assert_eq!(integer_x.is_ok(), x.is_integer()); assert_eq!(integer_x.is_ok(), Integer::convertible_from(&x)); if let Ok(n) = integer_x { assert_eq!(n.to_string(), x.to_string()); assert_eq!(Integer::exact_from(&x), n); assert_eq!(Rational::from(&n), x); assert_eq!(Rational::from(n), x); } }); } #[test] fn convertible_from_rational_properties() { rational_gen().test_properties(|x| { let convertible = Integer::convertible_from(&x); assert_eq!(convertible, x.is_integer()); }); } #[test] fn integer_from_rational_properties() { rational_rounding_mode_pair_gen_var_2().test_properties(|(x, rm)| { let no = Integer::rounding_from(&x, rm); assert_eq!(Integer::rounding_from(x.clone(), rm), no); let (n, o) = no; assert!((Rational::from(&n) - &x).lt_abs(&1)); assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); rational_gen().test_properties(|x| { let floor = Integer::rounding_from(&x, Floor); assert_eq!(floor.0, (&x).floor()); assert!(floor.0 <= x); assert!(&floor.0 + Integer::ONE > x); let ceiling = Integer::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, (&x).ceiling()); assert!(ceiling.0 >= x); assert!(&ceiling.0 - Integer::ONE < x); if x >= 0 { assert_eq!(Integer::rounding_from(&x, Down), floor); assert_eq!(Integer::rounding_from(&x, Up), ceiling); } else { assert_eq!(Integer::rounding_from(&x, Down), ceiling); assert_eq!(Integer::rounding_from(&x, Up), floor); } let nearest = Integer::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); assert!((Rational::from(nearest.0) - x).le_abs(&Rational::ONE_HALF)); }); integer_gen().test_properties(|n| { let x = Rational::from(&n); let no = (n, Equal); assert_eq!(Integer::rounding_from(&x, Floor), no); assert_eq!(Integer::rounding_from(&x, Down), no); assert_eq!(Integer::rounding_from(&x, Ceiling), no); assert_eq!(Integer::rounding_from(&x, Up), no); assert_eq!(Integer::rounding_from(&x, Nearest), no); assert_eq!(Integer::rounding_from(&x, Exact), no); let x = Rational::from_integers((no.0 << 1) | Integer::ONE, Integer::TWO); assert!(Integer::rounding_from(x, Nearest).0.even()); }); } ================================================ FILE: malachite-q/tests/conversion/is_integer.rs ================================================ // Copyright © 2026 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 malachite_base::num::conversion::traits::IsInteger; use malachite_base::test_util::generators::common::GenConfig; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use std::str::FromStr; #[test] fn test_is_integer() { let test = |n, out| { assert_eq!(Rational::from_str(n).unwrap().is_integer(), out); }; test("0", true); test("1", true); test("100", true); test("-1", true); test("-100", true); test("22/7", false); test("-22/7", false); } #[test] fn is_integer_properties() { let mut config = GenConfig::new(); config.insert("mean_bits_n", 256); config.insert("mean_stripe_n", 128); rational_gen().test_properties_with_config(&config, |x| { assert_eq!(x.is_integer(), (-&x).is_integer()); }); } ================================================ FILE: malachite-q/tests/conversion/mutate_numerator_or_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::{One, Zero}; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_rational_natural_natural_quadruple_gen_var_1, rational_rational_natural_triple_gen, rational_rational_natural_triple_gen_var_1, }; use std::str::FromStr; #[test] fn test_mutate_numerator() { let mut q = Rational::from_str("22/7").unwrap(); let ret = q.mutate_numerator(|x| { *x -= Natural::ONE; true }); assert_eq!(q, 3); assert!(ret); } #[test] fn test_mutate_denominator() { let mut q = Rational::from_str("22/7").unwrap(); let ret = q.mutate_denominator(|x| { *x -= Natural::ONE; true }); assert_eq!(q.to_string(), "11/3"); assert!(ret); } #[test] #[should_panic] fn mutate_denominator_fail() { let mut q = Rational::from_str("22/7").unwrap(); q.mutate_denominator(|x| { *x = Natural::ZERO; true }); } #[test] fn test_mutate_numerator_and_denominator() { let mut q = Rational::from_str("22/7").unwrap(); let ret = q.mutate_numerator_and_denominator(|x, y| { *x -= Natural::ONE; *y -= Natural::ONE; true }); assert_eq!(q.to_string(), "7/2"); assert!(ret); } #[test] #[should_panic] fn mutate_numerator_and_denominator_fail() { let mut q = Rational::from_str("22/7").unwrap(); q.mutate_numerator_and_denominator(|x, y| { *x = Natural::ONE; *y = Natural::ZERO; true }); } #[test] fn mutate_numerator_properties() { rational_rational_natural_triple_gen().test_properties(|(mut q, out, new_numerator)| { let out_2 = out.clone(); let new_numerator_2 = new_numerator.clone(); let old_sign = q >= 0; let old_denominator = q.to_denominator(); assert_eq!( q.mutate_numerator(|x| { *x = new_numerator; out }), out_2 ); assert!(q.is_valid()); assert_eq!( q, Rational::from_sign_and_naturals(old_sign, new_numerator_2, old_denominator) ); }); } #[test] fn mutate_denominator_properties() { rational_rational_natural_triple_gen_var_1().test_properties( |(mut q, out, new_denominator)| { let out_2 = out.clone(); let new_denominator_2 = new_denominator.clone(); let old_sign = q >= 0; let old_numerator = q.to_numerator(); assert_eq!( q.mutate_denominator(|x| { *x = new_denominator; out }), out_2 ); assert!(q.is_valid()); assert_eq!( q, Rational::from_sign_and_naturals(old_sign, old_numerator, new_denominator_2) ); }, ); } #[test] fn mutate_numerator_and_denominator_properties() { rational_rational_natural_natural_quadruple_gen_var_1().test_properties( |(mut q, out, new_numerator, new_denominator)| { let out_2 = out.clone(); let new_numerator_2 = new_numerator.clone(); let new_denominator_2 = new_denominator.clone(); let old_sign = q >= 0; assert_eq!( q.mutate_numerator_and_denominator(|x, y| { *x = new_numerator; *y = new_denominator; out }), out_2 ); assert!(q.is_valid()); assert_eq!( q, Rational::from_sign_and_naturals(old_sign, new_numerator_2, new_denominator_2) ); }, ); } ================================================ FILE: malachite-q/tests/conversion/natural_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::assert_panic; use malachite_base::num::arithmetic::traits::{Ceiling, Floor, Parity}; use malachite_base::num::basic::traits::{One, OneHalf, Two}; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, IsInteger, RoundingFrom, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::natural_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_3, rational_rounding_mode_pair_gen_var_1, }; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_try_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); let on = Natural::try_from(u.clone()); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); let on = Natural::try_from(&u); assert_eq!(on.to_debug_string(), out); assert!(on.map_or(true, |n| n.is_valid())); }; test("0", "Ok(0)"); test("123", "Ok(123)"); test("-123", "Err(NaturalFromRationalError)"); test("1000000000000", "Ok(1000000000000)"); test("-1000000000000", "Err(NaturalFromRationalError)"); test("22/7", "Err(NaturalFromRationalError)"); test("-22/7", "Err(NaturalFromRationalError)"); } #[test] fn test_exact_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); let n = Natural::exact_from(u.clone()); assert_eq!(n.to_string(), out); assert!(n.is_valid()); let n = Natural::exact_from(&u); assert_eq!(n.to_string(), out); assert!(n.is_valid()); }; test("0", "0"); test("123", "123"); test("1000000000000", "1000000000000"); } #[test] #[should_panic] fn natural_exact_from_rational_fail_1() { Natural::exact_from(Rational::from_str("-123").unwrap()); } #[test] #[should_panic] fn natural_exact_from_rational_fail_2() { Natural::exact_from(Rational::from_str("22/7").unwrap()); } #[test] #[should_panic] fn natural_exact_from_rational_ref_fail_1() { Natural::exact_from(&Rational::from_str("-123").unwrap()); } #[test] #[should_panic] fn natural_exact_from_rational_ref_fail_2() { Natural::exact_from(&Rational::from_str("22/7").unwrap()); } #[test] fn test_convertible_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(Natural::convertible_from(&u), out); }; test("0", true); test("123", true); test("-123", false); test("1000000000000", true); test("-1000000000000", false); test("22/7", false); test("-22/7", false); } #[test] fn test_rounding_from_rational() { let test = |s, rm, out, o_out| { let u = Rational::from_str(s).unwrap(); let (n, o) = Natural::rounding_from(u.clone(), rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); let (n, o) = Natural::rounding_from(&u, rm); assert_eq!(n.to_string(), out); assert!(n.is_valid()); assert_eq!(o, o_out); }; test("123", Floor, "123", Equal); test("123", Down, "123", Equal); test("123", Ceiling, "123", Equal); test("123", Up, "123", Equal); test("123", Nearest, "123", Equal); test("123", Exact, "123", Equal); test("-123", Down, "0", Greater); test("-123", Ceiling, "0", Greater); test("-123", Nearest, "0", Greater); test("22/7", Floor, "3", Less); test("22/7", Down, "3", Less); test("22/7", Ceiling, "4", Greater); test("22/7", Up, "4", Greater); test("22/7", Nearest, "3", Less); test("7/2", Floor, "3", Less); test("7/2", Down, "3", Less); test("7/2", Ceiling, "4", Greater); test("7/2", Up, "4", Greater); test("7/2", Nearest, "4", Greater); test("9/2", Floor, "4", Less); test("9/2", Down, "4", Less); test("9/2", Ceiling, "5", Greater); test("9/2", Up, "5", Greater); test("9/2", Nearest, "4", Less); } #[test] fn natural_rounding_from_rational_fail() { let x = Rational::from_str("-123").unwrap(); assert_panic!(Natural::rounding_from(x.clone(), Floor)); assert_panic!(Natural::rounding_from(x.clone(), Up)); assert_panic!(Natural::rounding_from(x, Exact)); let x = Rational::from_str("22/7").unwrap(); assert_panic!(Natural::rounding_from(x, Exact)); } #[test] fn natural_rounding_from_rational_ref_fail() { let x = Rational::from_str("-123").unwrap(); assert_panic!(Natural::rounding_from(&x, Floor)); assert_panic!(Natural::rounding_from(&x, Up)); assert_panic!(Natural::rounding_from(&x, Exact)); let x = Rational::from_str("22/7").unwrap(); assert_panic!(Natural::rounding_from(&x, Exact)); } #[test] fn try_from_rational_properties() { rational_gen().test_properties(|x| { let natural_x = Natural::try_from(x.clone()); assert!(natural_x.as_ref().map_or(true, Natural::is_valid)); let natural_x_alt = Natural::try_from(&x); assert!(natural_x_alt.as_ref().map_or(true, Natural::is_valid)); assert_eq!(natural_x, natural_x_alt); assert_eq!(natural_x.is_ok(), x >= 0 && x.is_integer()); assert_eq!(natural_x.is_ok(), Natural::convertible_from(&x)); if let Ok(n) = natural_x { assert_eq!(n.to_string(), x.to_string()); assert_eq!(Natural::exact_from(&x), n); assert_eq!(Rational::from(&n), x); assert_eq!(Rational::from(n), x); } }); } #[test] fn convertible_from_rational_properties() { rational_gen().test_properties(|x| { let convertible = Natural::convertible_from(&x); assert_eq!(convertible, x >= 0 && x.is_integer()); }); } #[test] fn rounding_from_rational_properties() { rational_rounding_mode_pair_gen_var_1().test_properties(|(x, rm)| { let no = Natural::rounding_from(&x, rm); assert_eq!(Natural::rounding_from(x.clone(), rm), no); let (n, o) = no; if x >= 0 { assert_eq!(Integer::rounding_from(&x, rm), (Integer::from(&n), o)); assert!((Rational::from(&n) - &x).lt_abs(&1)); } assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); rational_gen_var_3().test_properties(|x| { let floor = Natural::rounding_from(&x, Floor); assert_eq!(floor.0, (&x).floor()); assert!(floor.0 <= x); assert!(&floor.0 + Natural::ONE > x); assert_eq!(Natural::rounding_from(&x, Down), floor); let ceiling = Natural::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, (&x).ceiling()); assert!(ceiling.0 >= x); if x > 0 { assert!(&ceiling.0 - Natural::ONE < x); } assert_eq!(Natural::rounding_from(&x, Up), ceiling); let nearest = Natural::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); assert!((Rational::from(nearest.0) - x).le_abs(&Rational::ONE_HALF)); }); natural_gen().test_properties(|n| { let x = Rational::from(&n); let no = (n, Equal); assert_eq!(Natural::rounding_from(&x, Floor), no); assert_eq!(Natural::rounding_from(&x, Down), no); assert_eq!(Natural::rounding_from(&x, Ceiling), no); assert_eq!(Natural::rounding_from(&x, Up), no); assert_eq!(Natural::rounding_from(&x, Nearest), no); assert_eq!(Natural::rounding_from(&x, Exact), no); let x = Rational::from_naturals((no.0 << 1) | Natural::ONE, Natural::TWO); assert!(Natural::rounding_from(x, Nearest).0.even()); }); } ================================================ FILE: malachite-q/tests/conversion/primitive_float_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::Parity; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::basic::traits::NegativeInfinity; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::from::UnsignedFromFloatError; use malachite_base::num::conversion::traits::{ConvertibleFrom, ExactFrom, RoundingFrom}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ integer_gen, integer_gen_var_1, integer_rounding_mode_pair_gen_var_1, }; use malachite_q::Rational; use malachite_q::conversion::primitive_float_from_rational::FloatConversionError; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_4, rational_gen_var_5, rational_gen_var_6, rational_rounding_mode_pair_gen_var_5, }; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_f32_rounding_from_rational() { let max = Rational::exact_from(f32::MAX_FINITE); let test = |s: &str, rm: RoundingMode, out, o_out| { let u = Rational::from_str(s).unwrap(); let (f, o) = f32::rounding_from(&u, rm); assert_eq!(NiceFloat(f), NiceFloat(out)); assert_eq!(o, o_out); let (f, o) = f32::rounding_from(u.clone(), rm); assert_eq!(NiceFloat(f), NiceFloat(out)); assert_eq!(o, o_out); if rm == Down && u.lt_abs(&max) && NiceFloat(out) != NiceFloat(-0.0) { assert_eq!( NiceFloat(rug::Rational::from_str(s).unwrap().to_f32()), NiceFloat(out) ); } }; test("3", Exact, 3.0, Equal); test("-3", Exact, -3.0, Equal); test("123", Exact, 123.0, Equal); test("-123", Exact, -123.0, Equal); test("0", Exact, 0.0, Equal); test("1000000000", Exact, 1.0e9, Equal); test("-1000000000", Exact, -1.0e9, Equal); test("16777216", Exact, 1.6777216e7, Equal); test("-16777216", Exact, -1.6777216e7, Equal); test("16777218", Exact, 1.6777218e7, Equal); test("-16777218", Exact, -1.6777218e7, Equal); test("16777217", Floor, 1.6777216e7, Less); test("16777217", Down, 1.6777216e7, Less); test("16777217", Ceiling, 1.6777218e7, Greater); test("16777217", Up, 1.6777218e7, Greater); test("16777217", Nearest, 1.6777216e7, Less); test("-16777217", Floor, -1.6777218e7, Less); test("-16777217", Down, -1.6777216e7, Greater); test("-16777217", Ceiling, -1.6777216e7, Greater); test("-16777217", Up, -1.6777218e7, Less); test("-16777217", Nearest, -1.6777216e7, Greater); test("33554432", Exact, 3.3554432e7, Equal); test("-33554432", Exact, -3.3554432e7, Equal); test("33554436", Exact, 3.3554436e7, Equal); test("-33554436", Exact, -3.3554436e7, Equal); test("33554433", Floor, 3.3554432e7, Less); test("33554433", Down, 3.3554432e7, Less); test("33554433", Ceiling, 3.3554436e7, Greater); test("33554433", Up, 3.3554436e7, Greater); test("33554433", Nearest, 3.3554432e7, Less); test("-33554433", Floor, -3.3554436e7, Less); test("-33554433", Down, -3.3554432e7, Greater); test("-33554433", Ceiling, -3.3554432e7, Greater); test("-33554433", Up, -3.3554436e7, Less); test("-33554433", Nearest, -3.3554432e7, Greater); test("33554434", Nearest, 3.3554432e7, Less); test("-33554434", Nearest, -3.3554432e7, Greater); test("33554435", Nearest, 3.3554436e7, Greater); test("-33554435", Nearest, -3.3554436e7, Less); test( "340282346638528859811704183484516925439", Floor, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Down, 3.4028233e38, Less, ); test( "340282346638528859811704183484516925439", Ceiling, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Up, 3.4028235e38, Greater, ); test( "340282346638528859811704183484516925439", Nearest, 3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925439", Floor, -3.4028235e38, Less, ); test( "-340282346638528859811704183484516925439", Down, -3.4028233e38, Greater, ); test( "-340282346638528859811704183484516925439", Ceiling, -3.4028233e38, Greater, ); test( "-340282346638528859811704183484516925439", Up, -3.4028235e38, Less, ); test( "-340282346638528859811704183484516925439", Nearest, -3.4028235e38, Less, ); test( "340282346638528859811704183484516925440", Exact, 3.4028235e38, Equal, ); test( "-340282346638528859811704183484516925440", Exact, -3.4028235e38, Equal, ); test( "340282346638528859811704183484516925441", Floor, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Down, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Nearest, 3.4028235e38, Less, ); test( "340282346638528859811704183484516925441", Ceiling, f32::INFINITY, Greater, ); test( "340282346638528859811704183484516925441", Up, f32::INFINITY, Greater, ); test( "-340282346638528859811704183484516925441", Floor, f32::NEGATIVE_INFINITY, Less, ); test( "-340282346638528859811704183484516925441", Down, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Nearest, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Ceiling, -3.4028235e38, Greater, ); test( "-340282346638528859811704183484516925441", Up, f32::NEGATIVE_INFINITY, Less, ); test( "10000000000000000000000000000000000000000000000000000", Floor, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Down, 3.4028235e38, Less, ); test( "10000000000000000000000000000000000000000000000000000", Nearest, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Ceiling, f32::INFINITY, Greater, ); test( "10000000000000000000000000000000000000000000000000000", Up, f32::INFINITY, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Floor, f32::NEGATIVE_INFINITY, Less, ); test( "-10000000000000000000000000000000000000000000000000000", Down, -3.4028235e38, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Nearest, f32::NEGATIVE_INFINITY, Less, ); test( "-10000000000000000000000000000000000000000000000000000", Ceiling, -3.4028235e38, Greater, ); test( "-10000000000000000000000000000000000000000000000000000", Up, f32::NEGATIVE_INFINITY, Less, ); test("1125899873419263", Floor, 1.12589984e15, Less); test("1125899873419263", Down, 1.12589984e15, Less); test("1125899873419263", Ceiling, 1.1258999e15, Greater); test("1125899873419263", Up, 1.1258999e15, Greater); test("1125899873419263", Nearest, 1.1258999e15, Greater); test("-1125899873419263", Floor, -1.1258999e15, Less); test("-1125899873419263", Down, -1.12589984e15, Greater); test("-1125899873419263", Ceiling, -1.12589984e15, Greater); test("-1125899873419263", Up, -1.1258999e15, Less); test("-1125899873419263", Nearest, -1.1258999e15, Less); test("1/2", Floor, 0.5, Equal); test("1/2", Down, 0.5, Equal); test("1/2", Ceiling, 0.5, Equal); test("1/2", Up, 0.5, Equal); test("1/2", Nearest, 0.5, Equal); test("1/2", Exact, 0.5, Equal); test("-1/2", Floor, -0.5, Equal); test("-1/2", Down, -0.5, Equal); test("-1/2", Ceiling, -0.5, Equal); test("-1/2", Up, -0.5, Equal); test("-1/2", Nearest, -0.5, Equal); test("-1/2", Exact, -0.5, Equal); test("1/3", Floor, 0.3333333, Less); test("1/3", Down, 0.3333333, Less); test("1/3", Ceiling, 0.33333334, Greater); test("1/3", Up, 0.33333334, Greater); test("1/3", Nearest, 0.33333334, Greater); test("-1/3", Floor, -0.33333334, Less); test("-1/3", Down, -0.3333333, Greater); test("-1/3", Ceiling, -0.3333333, Greater); test("-1/3", Up, -0.33333334, Less); test("-1/3", Nearest, -0.33333334, Less); // subnormal test( "1/10000000000000000000000000000000000000000", Floor, 1.0e-40, Less, ); test( "1/10000000000000000000000000000000000000000", Down, 1.0e-40, Less, ); test( "1/10000000000000000000000000000000000000000", Ceiling, 1.00001e-40, Greater, ); test( "1/10000000000000000000000000000000000000000", Up, 1.00001e-40, Greater, ); test( "1/10000000000000000000000000000000000000000", Nearest, 1.0e-40, Less, ); test( "-1/10000000000000000000000000000000000000000", Floor, -1.00001e-40, Less, ); test( "-1/10000000000000000000000000000000000000000", Down, -1.0e-40, Greater, ); test( "-1/10000000000000000000000000000000000000000", Ceiling, -1.0e-40, Greater, ); test( "-1/10000000000000000000000000000000000000000", Up, -1.00001e-40, Less, ); test( "-1/10000000000000000000000000000000000000000", Nearest, -1.0e-40, Greater, ); // less than subnormal test( "1/100000000000000000000000000000000000000000000000000", Floor, 0.0, Less, ); test( "1/100000000000000000000000000000000000000000000000000", Down, 0.0, Less, ); test( "1/100000000000000000000000000000000000000000000000000", Ceiling, 1.0e-45, Greater, ); test( "1/100000000000000000000000000000000000000000000000000", Up, 1.0e-45, Greater, ); test( "1/100000000000000000000000000000000000000000000000000", Nearest, 0.0, Less, ); test( "-1/100000000000000000000000000000000000000000000000000", Floor, -1.0e-45, Less, ); test( "-1/100000000000000000000000000000000000000000000000000", Down, -0.0, Greater, ); test( "-1/100000000000000000000000000000000000000000000000000", Ceiling, -0.0, Greater, ); test( "-1/100000000000000000000000000000000000000000000000000", Up, -1.0e-45, Less, ); test( "-1/100000000000000000000000000000000000000000000000000", Nearest, -0.0, Greater, ); // half of smallest positive test( "1/1427247692705959881058285969449495136382746624", Floor, 0.0, Less, ); test( "1/1427247692705959881058285969449495136382746624", Down, 0.0, Less, ); test( "1/1427247692705959881058285969449495136382746624", Ceiling, 1.0e-45, Greater, ); test( "1/1427247692705959881058285969449495136382746624", Up, 1.0e-45, Greater, ); test( "1/1427247692705959881058285969449495136382746624", Nearest, 0.0, Less, ); test( "-1/1427247692705959881058285969449495136382746624", Floor, -1.0e-45, Less, ); test( "-1/1427247692705959881058285969449495136382746624", Down, -0.0, Greater, ); test( "-1/1427247692705959881058285969449495136382746624", Ceiling, -0.0, Greater, ); test( "-1/1427247692705959881058285969449495136382746624", Up, -1.0e-45, Less, ); test( "-1/1427247692705959881058285969449495136382746624", Nearest, -0.0, Greater, ); // just over half of smallest positive; Nearest rounds up test( "88819109620612751463292030150471001/126765060022822940149670320537600000000000000000000000\ 000000000000000000000000000", Floor, 0.0, Less, ); test( "88819109620612751463292030150471001/126765060022822940149670320537600000000000000000000000\ 000000000000000000000000000", Down, 0.0, Less, ); test( "88819109620612751463292030150471001/126765060022822940149670320537600000000000000000000000\ 000000000000000000000000000", Ceiling, 1.0e-45, Greater, ); test( "88819109620612751463292030150471001/126765060022822940149670320537600000000000000000000000\ 000000000000000000000000000", Up, 1.0e-45, Greater, ); test( "88819109620612751463292030150471001/126765060022822940149670320537600000000000000000000000\ 000000000000000000000000000", Nearest, 1.0e-45, Greater, ); test( "-88819109620612751463292030150471001/12676506002282294014967032053760000000000000000000000\ 0000000000000000000000000000", Floor, -1.0e-45, Less, ); test( "-88819109620612751463292030150471001/12676506002282294014967032053760000000000000000000000\ 0000000000000000000000000000", Down, -0.0, Greater, ); test( "-88819109620612751463292030150471001/12676506002282294014967032053760000000000000000000000\ 0000000000000000000000000000", Ceiling, -0.0, Greater, ); test( "-88819109620612751463292030150471001/12676506002282294014967032053760000000000000000000000\ 0000000000000000000000000000", Up, -1.0e-45, Less, ); test( "-88819109620612751463292030150471001/12676506002282294014967032053760000000000000000000000\ 0000000000000000000000000000", Nearest, -1.0e-45, Less, ); // halfway between max subnormal and min normal test( "16777215/1427247692705959881058285969449495136382746624", Floor, 1.1754942e-38, Less, ); test( "16777215/1427247692705959881058285969449495136382746624", Down, 1.1754942e-38, Less, ); test( "16777215/1427247692705959881058285969449495136382746624", Ceiling, 1.1754944e-38, Greater, ); test( "16777215/1427247692705959881058285969449495136382746624", Up, 1.1754944e-38, Greater, ); test( "16777215/1427247692705959881058285969449495136382746624", Nearest, 1.1754944e-38, Greater, ); } #[test] fn f32_rounding_from_rational_fail() { assert_panic!(f32::rounding_from( Rational::from_str("340282346638528859811704183484516925439").unwrap(), Exact, )); assert_panic!(f32::rounding_from( Rational::from_str("340282346638528859811704183484516925441").unwrap(), Exact, )); assert_panic!(f32::rounding_from( Rational::from_str("16777217").unwrap(), Exact )); assert_panic!(f32::rounding_from( Rational::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), Exact, )); assert_panic!(f32::rounding_from( Rational::from_str("1/10").unwrap(), Exact )); } #[test] fn f32_rounding_from_rational_ref_fail() { assert_panic!(f32::rounding_from( &Rational::from_str("340282346638528859811704183484516925439").unwrap(), Exact, )); assert_panic!(f32::rounding_from( &Rational::from_str("340282346638528859811704183484516925441").unwrap(), Exact, )); assert_panic!(f32::rounding_from( &Rational::from_str("16777217").unwrap(), Exact, )); assert_panic!(f32::rounding_from( &Rational::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), Exact, )); assert_panic!(f32::rounding_from( &Rational::from_str("1/10").unwrap(), Exact )); } #[test] fn test_f64_rounding_from_rational() { let test = |s: &str, rm: RoundingMode, out, o_out| { let u = Rational::from_str(s).unwrap(); let (f, o) = f64::rounding_from(&u, rm); assert_eq!(NiceFloat(f), NiceFloat(out)); assert_eq!(o, o_out); let (f, o) = f64::rounding_from(u, rm); assert_eq!(NiceFloat(f), NiceFloat(out)); assert_eq!(o, o_out); if rm == Down { assert_eq!( NiceFloat(rug::Rational::from_str(s).unwrap().to_f64()), NiceFloat(out) ); } }; test("3", Exact, 3.0, Equal); test("-3", Exact, -3.0, Equal); test("123", Exact, 123.0, Equal); test("-123", Exact, -123.0, Equal); test("0", Exact, 0.0, Equal); test("100000000000000000000", Exact, 1.0e20, Equal); test("-100000000000000000000", Exact, -1.0e20, Equal); test("9007199254740992", Exact, 9.007199254740992e15, Equal); test("-9007199254740992", Exact, -9.007199254740992e15, Equal); test("9007199254740994", Exact, 9.007199254740994e15, Equal); test("-9007199254740994", Exact, -9.007199254740994e15, Equal); test("9007199254740993", Floor, 9.007199254740992e15, Less); test("9007199254740993", Down, 9.007199254740992e15, Less); test("9007199254740993", Ceiling, 9.007199254740994e15, Greater); test("9007199254740993", Up, 9.007199254740994e15, Greater); test("9007199254740993", Nearest, 9.007199254740992e15, Less); test("-9007199254740993", Floor, -9.007199254740994e15, Less); test("-9007199254740993", Down, -9.007199254740992e15, Greater); test("-9007199254740993", Ceiling, -9.007199254740992e15, Greater); test("-9007199254740993", Up, -9.007199254740994e15, Less); test("-9007199254740993", Nearest, -9.007199254740992e15, Greater); test("18014398509481984", Exact, 1.8014398509481984e16, Equal); test("-18014398509481984", Exact, -1.8014398509481984e16, Equal); test("18014398509481988", Exact, 1.8014398509481988e16, Equal); test("-18014398509481988", Exact, -1.8014398509481988e16, Equal); test("18014398509481985", Floor, 1.8014398509481984e16, Less); test("18014398509481985", Down, 1.8014398509481984e16, Less); test("18014398509481985", Ceiling, 1.8014398509481988e16, Greater); test("18014398509481985", Up, 1.8014398509481988e16, Greater); test("18014398509481985", Nearest, 1.8014398509481984e16, Less); test("-18014398509481985", Floor, -1.8014398509481988e16, Less); test("-18014398509481985", Down, -1.8014398509481984e16, Greater); test( "-18014398509481985", Ceiling, -1.8014398509481984e16, Greater, ); test("-18014398509481985", Up, -1.8014398509481988e16, Less); test( "-18014398509481985", Nearest, -1.8014398509481984e16, Greater, ); test("18014398509481986", Nearest, 1.8014398509481984e16, Less); test( "-18014398509481986", Nearest, -1.8014398509481984e16, Greater, ); test("18014398509481987", Nearest, 1.8014398509481988e16, Greater); test("-18014398509481987", Nearest, -1.8014398509481988e16, Less); test("1/2", Floor, 0.5, Equal); test("1/2", Down, 0.5, Equal); test("1/2", Ceiling, 0.5, Equal); test("1/2", Up, 0.5, Equal); test("1/2", Nearest, 0.5, Equal); test("1/2", Exact, 0.5, Equal); test("-1/2", Floor, -0.5, Equal); test("-1/2", Down, -0.5, Equal); test("-1/2", Ceiling, -0.5, Equal); test("-1/2", Up, -0.5, Equal); test("-1/2", Nearest, -0.5, Equal); test("-1/2", Exact, -0.5, Equal); test("1/3", Floor, 0.3333333333333333, Less); test("1/3", Down, 0.3333333333333333, Less); test("1/3", Ceiling, 0.33333333333333337, Greater); test("1/3", Up, 0.33333333333333337, Greater); test("1/3", Nearest, 0.3333333333333333, Less); test("-1/3", Floor, -0.33333333333333337, Less); test("-1/3", Down, -0.3333333333333333, Greater); test("-1/3", Ceiling, -0.3333333333333333, Greater); test("-1/3", Up, -0.33333333333333337, Less); test("-1/3", Nearest, -0.3333333333333333, Greater); } #[test] fn f64_rounding_from_rational_fail() { assert_panic!(f64::rounding_from(Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap(), Exact) ); assert_panic!(f64::rounding_from(Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap(), Exact) ); assert_panic!(f64::rounding_from( Rational::from_str("9007199254740993").unwrap(), Exact, )); assert_panic!(f64::rounding_from( Rational::from_str("1/10").unwrap(), Exact )); } #[test] fn f64_rounding_from_rational_ref_fail() { assert_panic!( f64::rounding_from(&Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap(), Exact) ); assert_panic!( f64::rounding_from(&Rational::from_str( "17976931348623157081452742373170435679807056752584499659891747680315726078002858760589558\ 632766878171540458953514382464234321326889464182768467546703537516986049910576552820762454\ 900903893289440758685084551339423045832369032229481658085593321233482747978262044472316873\ 8177180919299881250404026184124858369").unwrap(), Exact) ); assert_panic!(f64::rounding_from( &Rational::from_str("9007199254740993").unwrap(), Exact, )); assert_panic!(f64::rounding_from( &Rational::from_str("1/10").unwrap(), Exact )); } #[test] fn test_f32_try_from_rational() { let test = |s: &str, out: Result| { let u = Rational::from_str(s).unwrap(); assert_eq!(f32::try_from(&u).map(NiceFloat), out.map(NiceFloat)); assert_eq!(f32::try_from(u.clone()).map(NiceFloat), out.map(NiceFloat)); assert_eq!(f32::convertible_from(u), out.is_ok()); }; test("3", Ok(3.0)); test("-3", Ok(-3.0)); test("123", Ok(123.0)); test("-123", Ok(-123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("-1000000000", Ok(-1.0e9)); test("16777216", Ok(1.6777216e7)); test("-16777216", Ok(-1.6777216e7)); test("16777218", Ok(1.6777218e7)); test("-16777218", Ok(-1.6777218e7)); test("16777217", Err(FloatConversionError::Inexact)); test("-16777217", Err(FloatConversionError::Inexact)); test("33554432", Ok(3.3554432e7)); test("-33554432", Ok(-3.3554432e7)); test("33554436", Ok(3.3554436e7)); test("-33554436", Ok(-3.3554436e7)); test("33554433", Err(FloatConversionError::Inexact)); test("-33554433", Err(FloatConversionError::Inexact)); test("33554434", Err(FloatConversionError::Inexact)); test("-33554434", Err(FloatConversionError::Inexact)); test("33554435", Err(FloatConversionError::Inexact)); test("-33554435", Err(FloatConversionError::Inexact)); test( "340282346638528859811704183484516925439", Err(FloatConversionError::Inexact), ); test( "-340282346638528859811704183484516925439", Err(FloatConversionError::Inexact), ); test("340282346638528859811704183484516925440", Ok(3.4028235e38)); test( "-340282346638528859811704183484516925440", Ok(-3.4028235e38), ); test( "340282346638528859811704183484516925441", Err(FloatConversionError::Inexact), ); test( "-340282346638528859811704183484516925441", Err(FloatConversionError::Inexact), ); test( "10000000000000000000000000000000000000000000000000000", Err(FloatConversionError::Inexact), ); test( "-10000000000000000000000000000000000000000000000000000", Err(FloatConversionError::Inexact), ); test("1/2", Ok(0.5)); test("-1/2", Ok(-0.5)); test("1/3", Err(FloatConversionError::Inexact)); test("-1/3", Err(FloatConversionError::Inexact)); test( "1/713623846352979940529142984724747568191373312", Ok(f32::MIN_POSITIVE_SUBNORMAL), ); test( "-1/713623846352979940529142984724747568191373312", Ok(-f32::MIN_POSITIVE_SUBNORMAL), ); test( "8388607/713623846352979940529142984724747568191373312", Ok(f32::MAX_SUBNORMAL), ); test( "-8388607/713623846352979940529142984724747568191373312", Ok(-f32::MAX_SUBNORMAL), ); test( "1/85070591730234615865843651857942052864", Ok(f32::MIN_POSITIVE_NORMAL), ); test( "-1/85070591730234615865843651857942052864", Ok(-f32::MIN_POSITIVE_NORMAL), ); } #[test] fn test_f64_try_from_rational() { let test = |s: &str, out: Result| { let u = Rational::from_str(s).unwrap(); assert_eq!(f64::try_from(&u).map(NiceFloat), out.map(NiceFloat)); assert_eq!(f64::try_from(u.clone()).map(NiceFloat), out.map(NiceFloat)); assert_eq!(f64::convertible_from(u), out.is_ok()); }; test("3", Ok(3.0)); test("-3", Ok(-3.0)); test("123", Ok(123.0)); test("-123", Ok(-123.0)); test("0", Ok(0.0)); test("1000000000", Ok(1.0e9)); test("-1000000000", Ok(-1.0e9)); test("9007199254740992", Ok(9.007199254740992e15)); test("-9007199254740992", Ok(-9.007199254740992e15)); test("9007199254740994", Ok(9.007199254740994e15)); test("-9007199254740994", Ok(-9.007199254740994e15)); test("9007199254740993", Err(FloatConversionError::Inexact)); test("-9007199254740993", Err(FloatConversionError::Inexact)); test("18014398509481984", Ok(1.8014398509481984e16)); test("-18014398509481984", Ok(-1.8014398509481984e16)); test("18014398509481988", Ok(1.8014398509481988e16)); test("-18014398509481988", Ok(-1.8014398509481988e16)); test("18014398509481985", Err(FloatConversionError::Inexact)); test("-18014398509481985", Err(FloatConversionError::Inexact)); test("18014398509481986", Err(FloatConversionError::Inexact)); test("-18014398509481986", Err(FloatConversionError::Inexact)); test("18014398509481987", Err(FloatConversionError::Inexact)); test("-18014398509481987", Err(FloatConversionError::Inexact)); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", Err(FloatConversionError::Inexact), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", Err(FloatConversionError::Inexact), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", Ok(1.7976931348623157e308), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", Ok(-1.7976931348623157e308), ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", Err(FloatConversionError::Inexact), ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", Err(FloatConversionError::Inexact), ); test("1/2", Ok(0.5)); test("-1/2", Ok(-0.5)); test("1/3", Err(FloatConversionError::Inexact)); test("-1/3", Err(FloatConversionError::Inexact)); } #[test] fn test_f32_exact_from_rational() { let test = |s: &str, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(NiceFloat(f32::exact_from(&u)), NiceFloat(out)); assert_eq!(NiceFloat(f32::exact_from(u)), NiceFloat(out)); }; test("3", 3.0); test("-3", -3.0); test("123", 123.0); test("-123", -123.0); test("0", 0.0); test("1000000000", 1.0e9); test("-1000000000", -1.0e9); test("16777216", 1.6777216e7); test("-16777216", -1.6777216e7); test("16777218", 1.6777218e7); test("-16777218", -1.6777218e7); test("33554432", 3.3554432e7); test("-33554432", -3.3554432e7); test("33554436", 3.3554436e7); test("-33554436", -3.3554436e7); test("340282346638528859811704183484516925440", 3.4028235e38); test("-340282346638528859811704183484516925440", -3.4028235e38); } #[test] fn f32_exact_from_rational_fail() { assert_panic!(f32::exact_from(Rational::from_str("16777217").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("-16777217").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("33554433").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("-33554433").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("33554434").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("-33554434").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("33554435").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("-33554435").unwrap())); assert_panic!(f32::exact_from( Rational::from_str("340282346638528859811704183484516925439").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("-340282346638528859811704183484516925439").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("-340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("-340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( Rational::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), )); assert_panic!(f32::exact_from( Rational::from_str("-10000000000000000000000000000000000000000000000000000").unwrap(), )); assert_panic!(f32::exact_from(Rational::from_str("1/3").unwrap())); assert_panic!(f32::exact_from(Rational::from_str("-1/3").unwrap())); } #[test] fn f32_exact_from_rational_ref_fail() { assert_panic!(f32::exact_from(&Rational::from_str("16777217").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("-16777217").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("33554433").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("-33554433").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("33554434").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("-33554434").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("33554435").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("-33554435").unwrap())); assert_panic!(f32::exact_from( &Rational::from_str("340282346638528859811704183484516925439").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("-340282346638528859811704183484516925439").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("-340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("-340282346638528859811704183484516925441").unwrap() )); assert_panic!(f32::exact_from( &Rational::from_str("10000000000000000000000000000000000000000000000000000").unwrap(), )); assert_panic!(f32::exact_from( &Rational::from_str("-10000000000000000000000000000000000000000000000000000").unwrap(), )); assert_panic!(f32::exact_from(&Rational::from_str("1/3").unwrap())); assert_panic!(f32::exact_from(&Rational::from_str("-1/3").unwrap())); } #[test] fn test_f64_exact_from_rational() { let test = |s: &str, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(NiceFloat(f64::exact_from(&u)), NiceFloat(out)); assert_eq!(NiceFloat(f64::exact_from(u)), NiceFloat(out)); }; test("3", 3.0); test("-3", -3.0); test("123", 123.0); test("-123", -123.0); test("0", 0.0); test("1000000000", 1.0e9); test("-1000000000", -1.0e9); test("9007199254740992", 9.007199254740992e15); test("-9007199254740992", -9.007199254740992e15); test("9007199254740994", 9.007199254740994e15); test("-9007199254740994", -9.007199254740994e15); test("18014398509481984", 1.8014398509481984e16); test("-18014398509481984", -1.8014398509481984e16); test("18014398509481988", 1.8014398509481988e16); test("-18014398509481988", -1.8014398509481988e16); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", 1.7976931348623157e308, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", -1.7976931348623157e308, ); } #[test] fn f64_exact_from_rational_fail() { assert_panic!(f64::exact_from( Rational::from_str("18014398509481983").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("-18014398509481983").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("18014398509481985").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("-18014398509481985").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("18014398509481986").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("-18014398509481986").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("18014398509481987").unwrap() )); assert_panic!(f64::exact_from( Rational::from_str("-18014398509481987").unwrap() )); assert_panic!(f64::exact_from(Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap())); assert_panic!(f64::exact_from(Rational::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367").unwrap())); assert_panic!(f64::exact_from(Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap())); assert_panic!(f64::exact_from(Rational::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369").unwrap())); assert_panic!(f64::exact_from(Rational::from_str("1/3").unwrap())); assert_panic!(f64::exact_from(Rational::from_str("-1/3").unwrap())); } #[test] fn f64_exact_from_rational_ref_fail() { assert_panic!(f64::exact_from( &Rational::from_str("18014398509481983").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("-18014398509481983").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("18014398509481985").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("-18014398509481985").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("18014398509481986").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("-18014398509481986").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("18014398509481987").unwrap() )); assert_panic!(f64::exact_from( &Rational::from_str("-18014398509481987").unwrap() )); assert_panic!(f64::exact_from(&Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367").unwrap())); assert_panic!(f64::exact_from(&Rational::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367").unwrap())); assert_panic!(f64::exact_from(&Rational::from_str( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369").unwrap())); assert_panic!(f64::exact_from(&Rational::from_str( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369").unwrap())); assert_panic!(f64::exact_from(&Rational::from_str("1/3").unwrap())); assert_panic!(f64::exact_from(&Rational::from_str("-1/3").unwrap())); } #[test] fn test_f32_convertible_from_rational() { let test = |s: &str, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(f32::convertible_from(&u), out); assert_eq!(f32::convertible_from(u), out); }; test("3", true); test("-3", true); test("123", true); test("-123", true); test("0", true); test("1000000000", true); test("-1000000000", true); test("16777216", true); test("-16777216", true); test("16777218", true); test("-16777218", true); test("16777217", false); test("-16777217", false); test("33554432", true); test("-33554432", true); test("33554436", true); test("-33554436", true); test("33554433", false); test("-33554433", false); test("33554434", false); test("-33554434", false); test("33554435", false); test("-33554435", false); test("340282346638528859811704183484516925439", false); test("-340282346638528859811704183484516925439", false); test("340282346638528859811704183484516925440", true); test("-340282346638528859811704183484516925440", true); test("340282346638528859811704183484516925441", false); test("-340282346638528859811704183484516925441", false); test( "10000000000000000000000000000000000000000000000000000", false, ); test( "-10000000000000000000000000000000000000000000000000000", false, ); test("1/3", false); test("-1/3", false); } #[test] fn test_f64_convertible_from_rational() { let test = |s: &str, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(f64::convertible_from(&u), out); assert_eq!(f64::convertible_from(u), out); }; test("3", true); test("-3", true); test("123", true); test("-123", true); test("0", true); test("1000000000", true); test("-1000000000", true); test("9007199254740992", true); test("-9007199254740992", true); test("9007199254740994", true); test("-9007199254740994", true); test("9007199254740993", false); test("-9007199254740993", false); test("18014398509481984", true); test("-18014398509481984", true); test("18014398509481988", true); test("-18014398509481988", true); test("18014398509481985", false); test("-18014398509481985", false); test("18014398509481986", false); test("-18014398509481986", false); test("18014398509481987", false); test("-18014398509481987", false); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858367", false, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858367", false, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858368", true, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858368", true, ); test( "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558\ 6327668781715404589535143824642343213268894641827684675467035375169860499105765512820762454\ 9009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873\ 8177180919299881250404026184124858369", false, ); test( "-17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955\ 8632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245\ 4900903893289440758685084551339423045832369032229481658085593321233482747978262041447231687\ 38177180919299881250404026184124858369", false, ); test("1/3", false); test("-1/3", false); } #[allow(clippy::trait_duplication_in_bounds)] fn float_rounding_from_rational_properties_helper< T: for<'a> ConvertibleFrom<&'a Integer> + for<'a> ConvertibleFrom<&'a Rational> + PartialOrd + PrimitiveFloat + RoundingFrom + for<'a> RoundingFrom<&'a Integer> + for<'a> RoundingFrom<&'a Rational>, >() where Rational: TryFrom, { rational_rounding_mode_pair_gen_var_5::().test_properties(|(x, rm)| { let (f, o) = T::rounding_from(&x, rm); let neg_f = if x == 0 { T::ZERO } else { -f }; let (f_alt, o_alt) = T::rounding_from(-&x, -rm); assert_eq!(NiceFloat(f_alt), NiceFloat(neg_f)); assert_eq!(o_alt, o.reverse()); let (f_alt, o_alt) = T::rounding_from(&x, rm); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, o); assert_eq!(f.partial_cmp(&x), Some(o)); match (x >= 0, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); rational_gen_var_4::().test_properties(|n| { let (f, o) = T::rounding_from(&n, Exact); assert_eq!(o, Equal); let (f_alt, o_alt) = T::rounding_from(&n, Floor); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, Equal); let (f_alt, o_alt) = T::rounding_from(&n, Down); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, Equal); let (f_alt, o_alt) = T::rounding_from(&n, Ceiling); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, Equal); let (f_alt, o_alt) = T::rounding_from(&n, Up); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, Equal); let (f_alt, o_alt) = T::rounding_from(&n, Nearest); assert_eq!(NiceFloat(f_alt), NiceFloat(f)); assert_eq!(o_alt, Equal); assert_eq!(Rational::exact_from(f), n); }); rational_gen_var_5::().test_properties(|n| { let f_below = T::rounding_from(&n, Floor); assert_eq!(f_below.1, Less); let f_above = (f_below.0.next_higher(), Greater); if f_below.0.is_finite() { assert!(Rational::exact_from(f_below.0) < n); } if f_above.0.is_finite() { assert!(Rational::exact_from(f_above.0) > n); } let (f, o) = T::rounding_from(&n, Ceiling); assert_eq!(NiceFloat(f), NiceFloat(f_above.0)); assert_eq!(o, Greater); if n >= 0 { let (f, o) = T::rounding_from(&n, Down); assert_eq!(NiceFloat(f), NiceFloat(f_below.0)); assert_eq!(o, Less); let (f, o) = T::rounding_from(&n, Up); assert_eq!(NiceFloat(f), NiceFloat(f_above.0)); assert_eq!(o, Greater); } else { let (f, o) = T::rounding_from(&n, Down); assert_eq!(NiceFloat(f), NiceFloat(f_above.0)); assert_eq!(o, Greater); let (f, o) = T::rounding_from(&n, Up); assert_eq!(NiceFloat(f), NiceFloat(f_below.0)); assert_eq!(o, Less); } let (f, o) = T::rounding_from(&n, Nearest); assert!( (NiceFloat(f), o) == (NiceFloat(f_below.0), f_below.1) || (NiceFloat(f), o) == (NiceFloat(f_above.0), f_above.1) ); if f_below.0.is_finite() && f_above.0.is_finite() { let below_diff = &n - Rational::exact_from(f_below.0); let above_diff = Rational::exact_from(f_above.0) - &n; if NiceFloat(f) == NiceFloat(f_below.0) { assert!(below_diff <= above_diff); } else { assert!(below_diff >= above_diff); } } }); rational_gen_var_6::().test_properties(|n| { let floor = T::rounding_from(&n, Floor); assert_eq!(floor.1, Less); let ceiling = (floor.0.next_higher(), Greater); let nearest = T::rounding_from(&n, Nearest); assert_eq!( (NiceFloat(nearest.0), nearest.1), if floor.0.to_bits().even() { (NiceFloat(floor.0), floor.1) } else { (NiceFloat(ceiling.0), ceiling.1) } ); }); integer_rounding_mode_pair_gen_var_1::().test_properties(|(n, rm)| { let r: Rational = ExactFrom::exact_from(&n); let (f, o) = T::rounding_from(r, rm); let (f_alt, o_alt) = T::rounding_from(&n, rm); assert_eq!(NiceFloat(f), NiceFloat(f_alt)); assert_eq!(o, o_alt); }); } #[test] fn float_rounding_from_rational_properties() { apply_fn_to_primitive_floats!(float_rounding_from_rational_properties_helper); let max = Rational::exact_from(f32::MAX_FINITE); rational_gen().test_properties(|x| { if x.lt_abs(&max) { let f = f32::rounding_from(&x, Down).0; if NiceFloat(f) != NiceFloat(-0.0) { assert_eq!(NiceFloat(f), NiceFloat(rug::Rational::from(&x).to_f32())); } } assert_eq!( NiceFloat(f64::rounding_from(&x, Down).0), NiceFloat(rug::Rational::from(&x).to_f64()) ); }); } #[allow(clippy::trait_duplication_in_bounds)] fn float_try_from_rational_properties_helper< T: TryFrom + for<'a> TryFrom<&'a Integer> + for<'a> TryFrom<&'a Rational, Error = FloatConversionError> + for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat + for<'a> RoundingFrom<&'a Rational>, >() where Natural: TryFrom, Rational: TryFrom, { rational_gen().test_properties(|n| { let of = T::try_from(&n); assert_eq!( T::try_from(n.clone()).map(NiceFloat), of.map(|f| NiceFloat(f)) ); assert_eq!( T::try_from(-&n).map(NiceFloat), of.map(|f| NiceFloat(if n == 0 { T::ZERO } else { -f })) ); }); rational_gen_var_4::().test_properties(|n| { let f = T::exact_from(&n); assert_eq!(NiceFloat(f), NiceFloat(T::rounding_from(&n, Exact).0)); assert_eq!(Rational::exact_from(f), n); }); rational_gen_var_5::().test_properties(|n| { assert!(T::try_from(n).is_err()); }); rational_gen_var_6::().test_properties(|n| { assert!(T::try_from(n).is_err()); }); integer_gen().test_properties(|n| { if let Ok(f) = T::try_from(&n) { let rn: Rational = From::from(&n); assert_eq!(NiceFloat(f), NiceFloat(T::exact_from(rn))); } }); integer_gen_var_1::().test_properties(|n| { let rn: Rational = From::from(&n); assert_eq!(NiceFloat(T::exact_from(&n)), NiceFloat(T::exact_from(rn))); }); } #[test] fn float_try_from_rational_properties() { apply_fn_to_primitive_floats!(float_try_from_rational_properties_helper); } #[allow(clippy::trait_duplication_in_bounds)] fn float_convertible_from_rational_properties_helper< T: ConvertibleFrom + for<'a> ConvertibleFrom<&'a Integer> + for<'a> ConvertibleFrom<&'a Rational> + PrimitiveFloat, >() where Rational: TryFrom, { rational_gen().test_properties(|n| { assert_eq!(T::convertible_from(&n), T::convertible_from(-n)); }); rational_gen_var_4::().test_properties(|n| { assert!(T::convertible_from(n)); }); rational_gen_var_5::().test_properties(|n| { assert!(!T::convertible_from(n)); }); rational_gen_var_6::().test_properties(|n| { assert!(!T::convertible_from(n)); }); integer_gen().test_properties(|n| { let rn: Rational = ExactFrom::exact_from(&n); assert_eq!(T::convertible_from(&n), T::convertible_from(&rn)); }); } #[test] fn float_convertible_from_rational_properties() { apply_fn_to_primitive_floats!(float_convertible_from_rational_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/primitive_int_from_rational.rs ================================================ // Copyright © 2026 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 malachite_base::assert_panic; use malachite_base::num::arithmetic::traits::{Ceiling, Floor}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::traits::OneHalf; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ ConvertibleFrom, ExactFrom, IsInteger, RoundingFrom, }; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::test_util::generators::{signed_gen, unsigned_gen}; use malachite_nz::integer::Integer; use malachite_q::Rational; use malachite_q::conversion::primitive_int_from_rational::{ SignedFromRationalError, UnsignedFromRationalError, }; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_3, rational_rounding_mode_pair_gen_var_3, }; use std::cmp::Ordering::*; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_u32_try_from_rational() { let test = |s, out: Result| { let u = Rational::from_str(s).unwrap(); assert_eq!(u32::try_from(&u), out); }; test("0", Ok(0)); test("123", Ok(123)); test("-123", Err(UnsignedFromRationalError)); test("1000000000000", Err(UnsignedFromRationalError)); test("-1000000000000", Err(UnsignedFromRationalError)); test("22/7", Err(UnsignedFromRationalError)); test("-22/7", Err(UnsignedFromRationalError)); } #[test] fn test_i32_try_from_rational() { let test = |s, out: Result| { let u = Rational::from_str(s).unwrap(); assert_eq!(i32::try_from(&u), out); }; test("0", Ok(0)); test("123", Ok(123)); test("-123", Ok(-123)); test("1000000000000", Err(SignedFromRationalError)); test("-1000000000000", Err(SignedFromRationalError)); test("22/7", Err(SignedFromRationalError)); test("-22/7", Err(SignedFromRationalError)); } #[test] fn test_u32_convertible_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(u32::convertible_from(&u), out); }; test("0", true); test("123", true); test("-123", false); test("1000000000000", false); test("-1000000000000", false); test("22/7", false); test("-22/7", false); } #[test] fn test_i32_convertible_from_rational() { let test = |s, out| { let u = Rational::from_str(s).unwrap(); assert_eq!(i32::convertible_from(&u), out); }; test("0", true); test("123", true); test("-123", true); test("1000000000000", false); test("-1000000000000", false); test("22/7", false); test("-22/7", false); } #[test] fn test_u32_rounding_from_rational() { let test = |s, rm, out: u32, o_out| { let r = Rational::from_str(s).unwrap(); let (u, o) = u32::rounding_from(&r, rm); assert_eq!(u, out); assert_eq!(o, o_out); }; test("123", Floor, 123, Equal); test("123", Ceiling, 123, Equal); test("123", Down, 123, Equal); test("123", Up, 123, Equal); test("123", Nearest, 123, Equal); test("123", Exact, 123, Equal); test("22/7", Floor, 3, Less); test("22/7", Ceiling, 4, Greater); test("22/7", Down, 3, Less); test("22/7", Up, 4, Greater); test("22/7", Nearest, 3, Less); test("7/2", Floor, 3, Less); test("7/2", Ceiling, 4, Greater); test("7/2", Down, 3, Less); test("7/2", Up, 4, Greater); test("7/2", Nearest, 4, Greater); test("9/2", Floor, 4, Less); test("9/2", Ceiling, 5, Greater); test("9/2", Down, 4, Less); test("9/2", Up, 5, Greater); test("9/2", Nearest, 4, Less); test("-123", Ceiling, 0, Greater); test("-123", Down, 0, Greater); test("-123", Nearest, 0, Greater); test("1000000000000", Floor, u32::MAX, Less); test("1000000000000", Down, u32::MAX, Less); test("1000000000000", Nearest, u32::MAX, Less); } #[test] fn test_i32_rounding_from_rational() { let test = |s, rm, out: i32, o_out| { let r = Rational::from_str(s).unwrap(); let (i, o) = i32::rounding_from(&r, rm); assert_eq!(i, out); assert_eq!(o, o_out); }; test("123", Floor, 123, Equal); test("123", Ceiling, 123, Equal); test("123", Down, 123, Equal); test("123", Up, 123, Equal); test("123", Nearest, 123, Equal); test("123", Exact, 123, Equal); test("22/7", Floor, 3, Less); test("22/7", Ceiling, 4, Greater); test("22/7", Down, 3, Less); test("22/7", Up, 4, Greater); test("22/7", Nearest, 3, Less); test("-22/7", Floor, -4, Less); test("-22/7", Ceiling, -3, Greater); test("-22/7", Down, -3, Greater); test("-22/7", Up, -4, Less); test("-22/7", Nearest, -3, Greater); test("7/2", Floor, 3, Less); test("7/2", Ceiling, 4, Greater); test("7/2", Down, 3, Less); test("7/2", Up, 4, Greater); test("7/2", Nearest, 4, Greater); test("9/2", Floor, 4, Less); test("9/2", Ceiling, 5, Greater); test("9/2", Down, 4, Less); test("9/2", Up, 5, Greater); test("9/2", Nearest, 4, Less); test("-1000000000000", Ceiling, i32::MIN, Greater); test("-1000000000000", Down, i32::MIN, Greater); test("-1000000000000", Nearest, i32::MIN, Greater); test("1000000000000", Floor, i32::MAX, Less); test("1000000000000", Down, i32::MAX, Less); test("1000000000000", Nearest, i32::MAX, Less); } #[test] fn rounding_from_rational_fail() { let x = Rational::from_str("22/7").unwrap(); assert_panic!(u32::rounding_from(&x, Exact)); let x = Rational::from_str("-123").unwrap(); assert_panic!(u32::rounding_from(&x, Floor)); assert_panic!(u32::rounding_from(&x, Up)); assert_panic!(u32::rounding_from(&x, Exact)); let x = Rational::from_str("1000000000000").unwrap(); assert_panic!(u32::rounding_from(&x, Ceiling)); assert_panic!(u32::rounding_from(&x, Up)); assert_panic!(u32::rounding_from(&x, Exact)); let x = Rational::from_str("22/7").unwrap(); assert_panic!(i32::rounding_from(&x, Exact)); let x = Rational::from_str("-1000000000000").unwrap(); assert_panic!(i32::rounding_from(&x, Floor)); assert_panic!(i32::rounding_from(&x, Up)); assert_panic!(i32::rounding_from(&x, Exact)); let x = Rational::from_str("1000000000000").unwrap(); assert_panic!(i32::rounding_from(&x, Ceiling)); assert_panic!(i32::rounding_from(&x, Up)); assert_panic!(i32::rounding_from(&x, Exact)); } fn try_from_rational_properties_helper< T: for<'a> TryFrom<&'a Rational> + for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >() where Rational: TryFrom + PartialOrd, { rational_gen().test_properties(|x| { let p_x = T::try_from(&x); assert_eq!(p_x.is_ok(), x >= T::MIN && x <= T::MAX && x.is_integer()); assert_eq!(p_x.is_ok(), T::convertible_from(&x)); if let Ok(n) = p_x { assert_eq!(n.to_string(), x.to_string()); assert_eq!(T::exact_from(&x), n); assert!(PartialEq::::eq(&Rational::exact_from(n), &x)); } }); } #[test] fn try_from_rational_properties() { apply_fn_to_primitive_ints!(try_from_rational_properties_helper); } fn convertible_from_rational_properties_helper< T: for<'a> ConvertibleFrom<&'a Rational> + PrimitiveInt, >() where Rational: PartialOrd, { rational_gen().test_properties(|x| { let convertible = T::convertible_from(&x); assert_eq!(convertible, x >= T::MIN && x <= T::MAX && x.is_integer()); }); } #[test] fn convertible_from_rational_properties() { apply_fn_to_primitive_ints!(convertible_from_rational_properties_helper); } fn rounding_from_rational_properties_helper< T: for<'a> ConvertibleFrom<&'a Rational> + PartialEq + PartialOrd + PrimitiveInt + for<'a> RoundingFrom<&'a Rational>, >() where Rational: From + PartialOrd, { rational_rounding_mode_pair_gen_var_3::().test_properties(|(x, rm)| { let (n, o) = T::rounding_from(&x, rm); if x >= T::MIN && x <= T::MAX { assert!((Rational::from(n) - &x).lt_abs(&1)); } assert_eq!(n.partial_cmp(&x), Some(o)); match (x >= T::ZERO, rm) { (_, Floor) | (true, Down) | (false, Up) => { assert_ne!(o, Greater); } (_, Ceiling) | (true, Up) | (false, Down) => { assert_ne!(o, Less); } (_, Exact) => assert_eq!(o, Equal), _ => {} } }); // TODO use range rational_gen_var_3().test_properties(|x| { if x < T::MIN || x > T::MAX { return; } let floor = T::rounding_from(&x, Floor); assert_eq!(floor.0, (&x).floor()); assert!(floor.0 <= x); if floor.0 < T::MAX { assert!(floor.0 + T::ONE > x); } let ceiling = T::rounding_from(&x, Ceiling); assert_eq!(ceiling.0, (&x).ceiling()); assert!(ceiling.0 >= x); if ceiling.0 > T::MIN { assert!(ceiling.0 - T::ONE < x); } if x >= T::ZERO { assert_eq!(T::rounding_from(&x, Down), floor); assert_eq!(T::rounding_from(&x, Up), ceiling); } else { assert_eq!(T::rounding_from(&x, Down), ceiling); assert_eq!(T::rounding_from(&x, Up), floor); } let nearest = T::rounding_from(&x, Nearest); assert!(nearest == floor || nearest == ceiling); assert!((Rational::from(nearest.0) - x).le_abs(&Rational::ONE_HALF)); }); } fn rounding_from_rational_properties_unsigned_helper< T: PrimitiveUnsigned + for<'a> RoundingFrom<&'a Rational>, >() where Rational: From, { unsigned_gen::().test_properties(|n| { let no = (n, Equal); let x = Rational::from(n); assert_eq!(T::rounding_from(&x, Floor), no); assert_eq!(T::rounding_from(&x, Down), no); assert_eq!(T::rounding_from(&x, Ceiling), no); assert_eq!(T::rounding_from(&x, Up), no); assert_eq!(T::rounding_from(&x, Nearest), no); assert_eq!(T::rounding_from(&x, Exact), no); }); } fn rounding_from_rational_properties_signed_helper< T: PrimitiveSigned + for<'a> RoundingFrom<&'a Rational>, >() where Rational: From, { signed_gen::().test_properties(|n| { let no = (n, Equal); let x = Rational::from(n); assert_eq!(T::rounding_from(&x, Floor), no); assert_eq!(T::rounding_from(&x, Down), no); assert_eq!(T::rounding_from(&x, Ceiling), no); assert_eq!(T::rounding_from(&x, Up), no); assert_eq!(T::rounding_from(&x, Nearest), no); assert_eq!(T::rounding_from(&x, Exact), no); }); } #[test] fn rounding_from_rational_properties() { apply_fn_to_primitive_ints!(rounding_from_rational_properties_helper); apply_fn_to_unsigneds!(rounding_from_rational_properties_unsigned_helper); apply_fn_to_signeds!(rounding_from_rational_properties_signed_helper); } ================================================ FILE: malachite-q/tests/conversion/sci_mantissa_and_exponent.rs ================================================ // Copyright © 2026 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 malachite_base::assert_panic; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::comparison::traits::PartialOrdAbs; use malachite_base::num::conversion::traits::{ExactFrom, SciMantissaAndExponent}; use malachite_base::num::float::NiceFloat; use malachite_base::rounding_modes::RoundingMode::{self, *}; use malachite_base::test_util::generators::{ primitive_float_signed_pair_gen_var_1, primitive_float_signed_pair_gen_var_2, }; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::{ natural_gen_var_2, natural_rounding_mode_pair_gen_var_2, }; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen_var_1, rational_rounding_mode_pair_gen_var_4, }; use std::cmp::Ordering::{self, *}; use std::panic::catch_unwind; use std::str::FromStr; #[test] fn test_sci_mantissa_and_exponent() { let test = |s: &str, mantissa: f32, exponent: i64| { let n = Rational::from_str(s).unwrap(); let (actual_mantissa, actual_exponent) = (&n).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); let (actual_mantissa, actual_exponent) = n.clone().sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); assert_eq!(NiceFloat((&n).sci_mantissa()), NiceFloat(mantissa)); assert_eq!( SciMantissaAndExponent::::sci_exponent(&n), exponent ); assert_eq!(NiceFloat(n.clone().sci_mantissa()), NiceFloat(mantissa)); assert_eq!( SciMantissaAndExponent::::sci_exponent(n.clone()), exponent ); let (actual_mantissa, actual_exponent) = (-n).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(actual_mantissa), NiceFloat(mantissa)); assert_eq!(actual_exponent, exponent); }; test("3", 1.5, 1); test("123", 1.921875, 6); test("1000000000", 1.8626451, 29); test("16777216", 1.0, 24); test("16777218", 1.0000001, 24); test("16777217", 1.0, 24); test("33554432", 1.0, 25); test("33554436", 1.0000001, 25); test("33554440", 1.0000002, 25); test("33554433", 1.0, 25); test("33554434", 1.0, 25); test("33554435", 1.0000001, 25); test("33554437", 1.0000001, 25); test("33554438", 1.0000002, 25); test("33554439", 1.0000002, 25); test("340282346638528859811704183484516925439", 1.9999999, 127); test("340282346638528859811704183484516925440", 1.9999999, 127); test("340282346638528859811704183484516925441", 1.9999999, 127); test( "10000000000000000000000000000000000000000000000000000", 1.670478, 172, ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", 1.8920966, 458, ); test("1/3", 1.3333334, -2); test("1/1024", 1.0, -10); test("22/7", 1.5714285, 1); test("936851431250/1397", 1.2491208, 29); } #[test] fn test_sci_mantissa_and_exponent_round() { let test = |n: &str, rm: RoundingMode, out: Option<(f32, i64, Ordering)>| { let r = Rational::from_str(n).unwrap(); let actual_out = r.clone().sci_mantissa_and_exponent_round(rm); assert_eq!( actual_out.map(|(m, e, o)| (NiceFloat(m), e, o)), out.map(|(m, e, o)| (NiceFloat(m), e, o)) ); let actual_out = r.sci_mantissa_and_exponent_round_ref(rm); assert_eq!( actual_out.map(|(m, e, o)| (NiceFloat(m), e, o)), out.map(|(m, e, o)| (NiceFloat(m), e, o)) ); let actual_out = (-r).sci_mantissa_and_exponent_round(rm); assert_eq!( actual_out.map(|(m, e, o)| (NiceFloat(m), e, o)), out.map(|(m, e, o)| (NiceFloat(m), e, o)) ); }; test("3", Floor, Some((1.5, 1, Equal))); test("3", Down, Some((1.5, 1, Equal))); test("3", Ceiling, Some((1.5, 1, Equal))); test("3", Up, Some((1.5, 1, Equal))); test("3", Nearest, Some((1.5, 1, Equal))); test("3", Exact, Some((1.5, 1, Equal))); test("123", Floor, Some((1.921875, 6, Equal))); test("123", Down, Some((1.921875, 6, Equal))); test("123", Ceiling, Some((1.921875, 6, Equal))); test("123", Up, Some((1.921875, 6, Equal))); test("123", Nearest, Some((1.921875, 6, Equal))); test("123", Exact, Some((1.921875, 6, Equal))); test("1000000000", Floor, Some((1.8626451, 29, Equal))); test("1000000000", Down, Some((1.8626451, 29, Equal))); test("1000000000", Ceiling, Some((1.8626451, 29, Equal))); test("1000000000", Up, Some((1.8626451, 29, Equal))); test("1000000000", Nearest, Some((1.8626451, 29, Equal))); test("1000000000", Exact, Some((1.8626451, 29, Equal))); test("16777216", Floor, Some((1.0, 24, Equal))); test("16777216", Down, Some((1.0, 24, Equal))); test("16777216", Ceiling, Some((1.0, 24, Equal))); test("16777216", Up, Some((1.0, 24, Equal))); test("16777216", Nearest, Some((1.0, 24, Equal))); test("16777216", Exact, Some((1.0, 24, Equal))); test("16777218", Floor, Some((1.0000001, 24, Equal))); test("16777218", Down, Some((1.0000001, 24, Equal))); test("16777218", Ceiling, Some((1.0000001, 24, Equal))); test("16777218", Up, Some((1.0000001, 24, Equal))); test("16777218", Nearest, Some((1.0000001, 24, Equal))); test("16777218", Exact, Some((1.0000001, 24, Equal))); test("16777217", Floor, Some((1.0, 24, Less))); test("16777217", Down, Some((1.0, 24, Less))); test("16777217", Ceiling, Some((1.0000001, 24, Greater))); test("16777217", Up, Some((1.0000001, 24, Greater))); test("16777217", Nearest, Some((1.0, 24, Less))); test("16777217", Exact, None); test("33554432", Floor, Some((1.0, 25, Equal))); test("33554432", Down, Some((1.0, 25, Equal))); test("33554432", Ceiling, Some((1.0, 25, Equal))); test("33554432", Up, Some((1.0, 25, Equal))); test("33554432", Nearest, Some((1.0, 25, Equal))); test("33554432", Exact, Some((1.0, 25, Equal))); test("33554436", Floor, Some((1.0000001, 25, Equal))); test("33554436", Down, Some((1.0000001, 25, Equal))); test("33554436", Ceiling, Some((1.0000001, 25, Equal))); test("33554436", Up, Some((1.0000001, 25, Equal))); test("33554436", Nearest, Some((1.0000001, 25, Equal))); test("33554436", Exact, Some((1.0000001, 25, Equal))); test("33554440", Floor, Some((1.0000002, 25, Equal))); test("33554440", Down, Some((1.0000002, 25, Equal))); test("33554440", Ceiling, Some((1.0000002, 25, Equal))); test("33554440", Up, Some((1.0000002, 25, Equal))); test("33554440", Nearest, Some((1.0000002, 25, Equal))); test("33554440", Exact, Some((1.0000002, 25, Equal))); test("33554433", Floor, Some((1.0, 25, Less))); test("33554433", Down, Some((1.0, 25, Less))); test("33554433", Ceiling, Some((1.0000001, 25, Greater))); test("33554433", Up, Some((1.0000001, 25, Greater))); test("33554433", Nearest, Some((1.0, 25, Less))); test("33554433", Exact, None); test("33554434", Floor, Some((1.0, 25, Less))); test("33554434", Down, Some((1.0, 25, Less))); test("33554434", Ceiling, Some((1.0000001, 25, Greater))); test("33554434", Up, Some((1.0000001, 25, Greater))); test("33554434", Nearest, Some((1.0, 25, Less))); test("33554434", Exact, None); test("33554435", Floor, Some((1.0, 25, Less))); test("33554435", Down, Some((1.0, 25, Less))); test("33554435", Ceiling, Some((1.0000001, 25, Greater))); test("33554435", Up, Some((1.0000001, 25, Greater))); test("33554435", Nearest, Some((1.0000001, 25, Greater))); test("33554435", Exact, None); test("33554437", Floor, Some((1.0000001, 25, Less))); test("33554437", Down, Some((1.0000001, 25, Less))); test("33554437", Ceiling, Some((1.0000002, 25, Greater))); test("33554437", Up, Some((1.0000002, 25, Greater))); test("33554437", Nearest, Some((1.0000001, 25, Less))); test("33554437", Exact, None); test("33554438", Floor, Some((1.0000001, 25, Less))); test("33554438", Down, Some((1.0000001, 25, Less))); test("33554438", Ceiling, Some((1.0000002, 25, Greater))); test("33554438", Up, Some((1.0000002, 25, Greater))); test("33554438", Nearest, Some((1.0000002, 25, Greater))); test("33554438", Exact, None); test("33554439", Floor, Some((1.0000001, 25, Less))); test("33554439", Down, Some((1.0000001, 25, Less))); test("33554439", Ceiling, Some((1.0000002, 25, Greater))); test("33554439", Up, Some((1.0000002, 25, Greater))); test("33554439", Nearest, Some((1.0000002, 25, Greater))); test("33554439", Exact, None); test( "340282346638528859811704183484516925439", Floor, Some((1.9999998, 127, Less)), ); test( "340282346638528859811704183484516925439", Down, Some((1.9999998, 127, Less)), ); test( "340282346638528859811704183484516925439", Ceiling, Some((1.9999999, 127, Greater)), ); test( "340282346638528859811704183484516925439", Up, Some((1.9999999, 127, Greater)), ); test( "340282346638528859811704183484516925439", Nearest, Some((1.9999999, 127, Greater)), ); test("340282346638528859811704183484516925439", Exact, None); test( "340282346638528859811704183484516925440", Floor, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Down, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Ceiling, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Up, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Nearest, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925440", Exact, Some((1.9999999, 127, Equal)), ); test( "340282346638528859811704183484516925441", Floor, Some((1.9999999, 127, Less)), ); test( "340282346638528859811704183484516925441", Down, Some((1.9999999, 127, Less)), ); test( "340282346638528859811704183484516925441", Ceiling, Some((1.0, 128, Greater)), ); test( "340282346638528859811704183484516925441", Up, Some((1.0, 128, Greater)), ); test( "340282346638528859811704183484516925441", Nearest, Some((1.9999999, 127, Less)), ); test("340282346638528859811704183484516925441", Exact, None); test( "10000000000000000000000000000000000000000000000000000", Floor, Some((1.6704779, 172, Less)), ); test( "10000000000000000000000000000000000000000000000000000", Down, Some((1.6704779, 172, Less)), ); test( "10000000000000000000000000000000000000000000000000000", Ceiling, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Up, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Nearest, Some((1.670478, 172, Greater)), ); test( "10000000000000000000000000000000000000000000000000000", Exact, None, ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Floor, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Down, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Ceiling, Some((1.8920968, 458, Greater)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Up, Some((1.8920968, 458, Greater)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Nearest, Some((1.8920966, 458, Less)), ); test( "14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Exact, None, ); test("1/3", Floor, Some((1.3333333, -2, Less))); test("1/3", Ceiling, Some((1.3333334, -2, Greater))); test("1/3", Down, Some((1.3333333, -2, Less))); test("1/3", Up, Some((1.3333334, -2, Greater))); test("1/3", Nearest, Some((1.3333334, -2, Greater))); test("1/3", Exact, None); test("1/1024", Floor, Some((1.0, -10, Equal))); test("1/1024", Ceiling, Some((1.0, -10, Equal))); test("1/1024", Down, Some((1.0, -10, Equal))); test("1/1024", Up, Some((1.0, -10, Equal))); test("1/1024", Nearest, Some((1.0, -10, Equal))); test("1/1024", Exact, Some((1.0, -10, Equal))); test("22/7", Floor, Some((1.5714285, 1, Less))); test("22/7", Ceiling, Some((1.5714287, 1, Greater))); test("22/7", Down, Some((1.5714285, 1, Less))); test("22/7", Up, Some((1.5714287, 1, Greater))); test("22/7", Nearest, Some((1.5714285, 1, Less))); test("22/7", Exact, None); test("936851431250/1397", Floor, Some((1.2491207, 29, Less))); test("936851431250/1397", Ceiling, Some((1.2491208, 29, Greater))); test("936851431250/1397", Down, Some((1.2491207, 29, Less))); test("936851431250/1397", Up, Some((1.2491208, 29, Greater))); test("936851431250/1397", Nearest, Some((1.2491208, 29, Greater))); test("936851431250/1397", Exact, None); test( "1073741823/1099511627776", Floor, Some((1.9999999, -11, Less)), ); test( "1073741823/1099511627776", Ceiling, Some((1.0, -10, Greater)), ); test( "1073741823/1099511627776", Down, Some((1.9999999, -11, Less)), ); test("1073741823/1099511627776", Up, Some((1.0, -10, Greater))); test( "1073741823/1099511627776", Nearest, Some((1.0, -10, Greater)), ); test("1073741823/1099511627776", Exact, None); test("-3", Floor, Some((1.5, 1, Equal))); test("-3", Down, Some((1.5, 1, Equal))); test("-3", Ceiling, Some((1.5, 1, Equal))); test("-3", Up, Some((1.5, 1, Equal))); test("-3", Nearest, Some((1.5, 1, Equal))); test("-3", Exact, Some((1.5, 1, Equal))); test("-123", Floor, Some((1.921875, 6, Equal))); test("-123", Down, Some((1.921875, 6, Equal))); test("-123", Ceiling, Some((1.921875, 6, Equal))); test("-123", Up, Some((1.921875, 6, Equal))); test("-123", Nearest, Some((1.921875, 6, Equal))); test("-123", Exact, Some((1.921875, 6, Equal))); test("-1000000000", Floor, Some((1.8626451, 29, Equal))); test("-1000000000", Down, Some((1.8626451, 29, Equal))); test("-1000000000", Ceiling, Some((1.8626451, 29, Equal))); test("-1000000000", Up, Some((1.8626451, 29, Equal))); test("-1000000000", Nearest, Some((1.8626451, 29, Equal))); test("-1000000000", Exact, Some((1.8626451, 29, Equal))); test("-16777216", Floor, Some((1.0, 24, Equal))); test("-16777216", Down, Some((1.0, 24, Equal))); test("-16777216", Ceiling, Some((1.0, 24, Equal))); test("-16777216", Up, Some((1.0, 24, Equal))); test("-16777216", Nearest, Some((1.0, 24, Equal))); test("-16777216", Exact, Some((1.0, 24, Equal))); test("-16777218", Floor, Some((1.0000001, 24, Equal))); test("-16777218", Down, Some((1.0000001, 24, Equal))); test("-16777218", Ceiling, Some((1.0000001, 24, Equal))); test("-16777218", Up, Some((1.0000001, 24, Equal))); test("-16777218", Nearest, Some((1.0000001, 24, Equal))); test("-16777218", Exact, Some((1.0000001, 24, Equal))); test("-16777217", Floor, Some((1.0, 24, Less))); test("-16777217", Down, Some((1.0, 24, Less))); test("-16777217", Ceiling, Some((1.0000001, 24, Greater))); test("-16777217", Up, Some((1.0000001, 24, Greater))); test("-16777217", Nearest, Some((1.0, 24, Less))); test("-16777217", Exact, None); test("-33554432", Floor, Some((1.0, 25, Equal))); test("-33554432", Down, Some((1.0, 25, Equal))); test("-33554432", Ceiling, Some((1.0, 25, Equal))); test("-33554432", Up, Some((1.0, 25, Equal))); test("-33554432", Nearest, Some((1.0, 25, Equal))); test("-33554432", Exact, Some((1.0, 25, Equal))); test("-33554436", Floor, Some((1.0000001, 25, Equal))); test("-33554436", Down, Some((1.0000001, 25, Equal))); test("-33554436", Ceiling, Some((1.0000001, 25, Equal))); test("-33554436", Up, Some((1.0000001, 25, Equal))); test("-33554436", Nearest, Some((1.0000001, 25, Equal))); test("-33554436", Exact, Some((1.0000001, 25, Equal))); test("-33554440", Floor, Some((1.0000002, 25, Equal))); test("-33554440", Down, Some((1.0000002, 25, Equal))); test("-33554440", Ceiling, Some((1.0000002, 25, Equal))); test("-33554440", Up, Some((1.0000002, 25, Equal))); test("-33554440", Nearest, Some((1.0000002, 25, Equal))); test("-33554440", Exact, Some((1.0000002, 25, Equal))); test("-33554433", Floor, Some((1.0, 25, Less))); test("-33554433", Down, Some((1.0, 25, Less))); test("-33554433", Ceiling, Some((1.0000001, 25, Greater))); test("-33554433", Up, Some((1.0000001, 25, Greater))); test("-33554433", Nearest, Some((1.0, 25, Less))); test("-33554433", Exact, None); test("-33554434", Floor, Some((1.0, 25, Less))); test("-33554434", Down, Some((1.0, 25, Less))); test("-33554434", Ceiling, Some((1.0000001, 25, Greater))); test("-33554434", Up, Some((1.0000001, 25, Greater))); test("-33554434", Nearest, Some((1.0, 25, Less))); test("-33554434", Exact, None); test("-33554435", Floor, Some((1.0, 25, Less))); test("-33554435", Down, Some((1.0, 25, Less))); test("-33554435", Ceiling, Some((1.0000001, 25, Greater))); test("-33554435", Up, Some((1.0000001, 25, Greater))); test("-33554435", Nearest, Some((1.0000001, 25, Greater))); test("-33554435", Exact, None); test("-33554437", Floor, Some((1.0000001, 25, Less))); test("-33554437", Down, Some((1.0000001, 25, Less))); test("-33554437", Ceiling, Some((1.0000002, 25, Greater))); test("-33554437", Up, Some((1.0000002, 25, Greater))); test("-33554437", Nearest, Some((1.0000001, 25, Less))); test("-33554437", Exact, None); test("-33554438", Floor, Some((1.0000001, 25, Less))); test("-33554438", Down, Some((1.0000001, 25, Less))); test("-33554438", Ceiling, Some((1.0000002, 25, Greater))); test("-33554438", Up, Some((1.0000002, 25, Greater))); test("-33554438", Nearest, Some((1.0000002, 25, Greater))); test("-33554438", Exact, None); test("-33554439", Floor, Some((1.0000001, 25, Less))); test("-33554439", Down, Some((1.0000001, 25, Less))); test("-33554439", Ceiling, Some((1.0000002, 25, Greater))); test("-33554439", Up, Some((1.0000002, 25, Greater))); test("-33554439", Nearest, Some((1.0000002, 25, Greater))); test("-33554439", Exact, None); test( "-340282346638528859811704183484516925439", Floor, Some((1.9999998, 127, Less)), ); test( "-340282346638528859811704183484516925439", Down, Some((1.9999998, 127, Less)), ); test( "-340282346638528859811704183484516925439", Ceiling, Some((1.9999999, 127, Greater)), ); test( "-340282346638528859811704183484516925439", Up, Some((1.9999999, 127, Greater)), ); test( "-340282346638528859811704183484516925439", Nearest, Some((1.9999999, 127, Greater)), ); test("-340282346638528859811704183484516925439", Exact, None); test( "-340282346638528859811704183484516925440", Floor, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925440", Down, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925440", Ceiling, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925440", Up, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925440", Nearest, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925440", Exact, Some((1.9999999, 127, Equal)), ); test( "-340282346638528859811704183484516925441", Floor, Some((1.9999999, 127, Less)), ); test( "-340282346638528859811704183484516925441", Down, Some((1.9999999, 127, Less)), ); test( "-340282346638528859811704183484516925441", Ceiling, Some((1.0, 128, Greater)), ); test( "-340282346638528859811704183484516925441", Up, Some((1.0, 128, Greater)), ); test( "-340282346638528859811704183484516925441", Nearest, Some((1.9999999, 127, Less)), ); test("-340282346638528859811704183484516925441", Exact, None); test( "-10000000000000000000000000000000000000000000000000000", Floor, Some((1.6704779, 172, Less)), ); test( "-10000000000000000000000000000000000000000000000000000", Down, Some((1.6704779, 172, Less)), ); test( "-10000000000000000000000000000000000000000000000000000", Ceiling, Some((1.670478, 172, Greater)), ); test( "-10000000000000000000000000000000000000000000000000000", Up, Some((1.670478, 172, Greater)), ); test( "-10000000000000000000000000000000000000000000000000000", Nearest, Some((1.670478, 172, Greater)), ); test( "-10000000000000000000000000000000000000000000000000000", Exact, None, ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Floor, Some((1.8920966, 458, Less)), ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Down, Some((1.8920966, 458, Less)), ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Ceiling, Some((1.8920968, 458, Greater)), ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Up, Some((1.8920968, 458, Greater)), ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Nearest, Some((1.8920966, 458, Less)), ); test( "-14082550970654138785851080671018547544414440081606160064666506533805114137489745015963441\ 66687102119468305028824490080062160433429798263165", Exact, None, ); test("-1/3", Floor, Some((1.3333333, -2, Less))); test("-1/3", Ceiling, Some((1.3333334, -2, Greater))); test("-1/3", Down, Some((1.3333333, -2, Less))); test("-1/3", Up, Some((1.3333334, -2, Greater))); test("-1/3", Nearest, Some((1.3333334, -2, Greater))); test("-1/3", Exact, None); test("-1/1024", Floor, Some((1.0, -10, Equal))); test("-1/1024", Ceiling, Some((1.0, -10, Equal))); test("-1/1024", Down, Some((1.0, -10, Equal))); test("-1/1024", Up, Some((1.0, -10, Equal))); test("-1/1024", Nearest, Some((1.0, -10, Equal))); test("-1/1024", Exact, Some((1.0, -10, Equal))); test("-22/7", Floor, Some((1.5714285, 1, Less))); test("-22/7", Ceiling, Some((1.5714287, 1, Greater))); test("-22/7", Down, Some((1.5714285, 1, Less))); test("-22/7", Up, Some((1.5714287, 1, Greater))); test("-22/7", Nearest, Some((1.5714285, 1, Less))); test("-22/7", Exact, None); test("-936851431250/1397", Floor, Some((1.2491207, 29, Less))); test( "-936851431250/1397", Ceiling, Some((1.2491208, 29, Greater)), ); test("-936851431250/1397", Down, Some((1.2491207, 29, Less))); test("-936851431250/1397", Up, Some((1.2491208, 29, Greater))); test( "-936851431250/1397", Nearest, Some((1.2491208, 29, Greater)), ); test("-936851431250/1397", Exact, None); test( "-1073741823/1099511627776", Floor, Some((1.9999999, -11, Less)), ); test( "-1073741823/1099511627776", Ceiling, Some((1.0, -10, Greater)), ); test( "-1073741823/1099511627776", Down, Some((1.9999999, -11, Less)), ); test("-1073741823/1099511627776", Up, Some((1.0, -10, Greater))); test( "-1073741823/1099511627776", Nearest, Some((1.0, -10, Greater)), ); test("-1073741823/1099511627776", Exact, None); } #[test] fn test_from_sci_mantissa_and_exponent() { let test = |mantissa: f32, exponent: i64, out: Option<&str>| { assert_eq!( <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, exponent ), out.map(|s| Rational::from_str(s).unwrap()) ); assert_eq!( >::from_sci_mantissa_and_exponent( mantissa, exponent ), out.map(|s| Rational::from_str(s).unwrap()) ); }; test(1.5, 1, Some("3")); test(1.51, 1, Some("6333399/2097152")); test(1.921875, 6, Some("123")); test( 1.670478, 172, Some("10000000254586612611935772707803116801852191350456320"), ); test(2.0, 1, None); test(10.0, 1, None); test(0.5, 1, None); } fn from_sci_mantissa_and_exponent_fail_helper() where Rational: SciMantissaAndExponent, for<'a> &'a Rational: SciMantissaAndExponent, { assert_panic!( <&Rational as SciMantissaAndExponent>::from_sci_mantissa_and_exponent( T::ZERO, 0 ) ); assert_panic!( >::from_sci_mantissa_and_exponent(T::ZERO, 0) ); } #[test] fn from_sci_mantissa_and_exponent_fail() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_fail_helper); } fn sci_mantissa_and_exponent_properties_helper() where Rational: SciMantissaAndExponent, for<'a> &'a Rational: SciMantissaAndExponent, for<'a> &'a Natural: SciMantissaAndExponent, { rational_gen_var_1().test_properties(|n| { let (mantissa, exponent) = (&n).sci_mantissa_and_exponent(); assert_eq!(NiceFloat((&n).sci_mantissa()), NiceFloat(mantissa)); assert_eq!((&n).sci_exponent(), exponent); let (mantissa_alt, exponent_alt) = n.clone().sci_mantissa_and_exponent(); assert_eq!(NiceFloat(mantissa_alt), NiceFloat(mantissa)); assert_eq!(exponent_alt, exponent); assert_eq!(NiceFloat(n.clone().sci_mantissa()), NiceFloat(mantissa)); assert_eq!(n.clone().sci_exponent(), exponent); assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); assert_eq!( n.sci_mantissa_and_exponent_round(Nearest) .map(|(m, e, _): (T, i64, Ordering)| (NiceFloat(m), e)), Some((NiceFloat(mantissa), exponent)) ); }); natural_gen_var_2().test_properties(|x| { let (mantissa_1, exponent_1) = x.sci_mantissa_and_exponent(); let (mantissa_2, exponent_2) = (&Rational::from(x)).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(mantissa_1), NiceFloat(mantissa_2)); assert_eq!(i64::exact_from(exponent_1), exponent_2); }); } #[test] fn sci_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_properties_helper); } fn sci_mantissa_and_exponent_round_properties_helper() where Rational: SciMantissaAndExponent, for<'a> &'a Rational: SciMantissaAndExponent, { rational_rounding_mode_pair_gen_var_4().test_properties(|(n, rm)| { let result = n.sci_mantissa_and_exponent_round_ref::(rm); assert_eq!( n.clone() .sci_mantissa_and_exponent_round::(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)), result.map(|(m, e, o)| (NiceFloat(m), e, o)) ); if let Some((mantissa, exponent, o)) = result { assert!(mantissa >= T::ONE); assert!(mantissa < T::TWO); let x = <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent( mantissa, exponent, ) .unwrap(); if rm == Exact { assert_eq!(x.partial_cmp_abs(&n), Some(Equal)); } assert_eq!(x.partial_cmp_abs(&n), Some(o)); match rm { Floor | Down => assert_ne!(o, Greater), Ceiling | Up => assert_ne!(o, Less), Exact => assert_eq!(o, Equal), _ => {} } } }); rational_gen_var_1().test_properties(|n| { let (floor_mantissa, floor_exponent, floor_o) = n.sci_mantissa_and_exponent_round_ref::(Floor).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round_ref::(Down).unwrap(), (floor_mantissa, floor_exponent, floor_o) ); let (ceiling_mantissa, ceiling_exponent, ceiling_o) = n.sci_mantissa_and_exponent_round_ref::(Ceiling).unwrap(); assert_eq!( n.sci_mantissa_and_exponent_round_ref::(Up).unwrap(), (ceiling_mantissa, ceiling_exponent, ceiling_o) ); let (nearest_mantissa, nearest_exponent, nearest_o) = n.sci_mantissa_and_exponent_round_ref::(Nearest).unwrap(); if let Some((mantissa, exponent, o)) = n.sci_mantissa_and_exponent_round_ref::(Exact) { assert_eq!(o, Equal); assert_eq!(floor_mantissa, mantissa); assert_eq!(ceiling_mantissa, mantissa); assert_eq!(nearest_mantissa, mantissa); assert_eq!(floor_exponent, exponent); assert_eq!(ceiling_exponent, exponent); assert_eq!(nearest_exponent, exponent); } else { assert_eq!(floor_o, Less); assert_eq!(ceiling_o, Greater); assert_ne!( (floor_mantissa, floor_exponent), (ceiling_mantissa, ceiling_exponent) ); assert!( (nearest_mantissa, nearest_exponent, nearest_o) == (floor_mantissa, floor_exponent, floor_o) || (nearest_mantissa, nearest_exponent, nearest_o) == (ceiling_mantissa, ceiling_exponent, ceiling_o) ); if ceiling_mantissa == T::ONE { assert_eq!(floor_mantissa, T::TWO.next_lower()); assert_eq!(floor_exponent, ceiling_exponent - 1); } else { assert_eq!(floor_mantissa, ceiling_mantissa.next_lower()); assert_eq!(floor_exponent, ceiling_exponent); } } }); natural_rounding_mode_pair_gen_var_2().test_properties(|(x, rm)| { assert_eq!( x.sci_mantissa_and_exponent_round(rm) .map(|(m, e, o): (T, u64, Ordering)| (NiceFloat(m), i64::exact_from(e), o)), Rational::from(x) .sci_mantissa_and_exponent_round(rm) .map(|(m, e, o)| (NiceFloat(m), e, o)) ); }); } #[test] fn sci_mantissa_and_exponent_round_properties() { apply_fn_to_primitive_floats!(sci_mantissa_and_exponent_round_properties_helper); } fn from_sci_mantissa_and_exponent_properties_helper() where Rational: SciMantissaAndExponent, for<'a> &'a Rational: SciMantissaAndExponent, { primitive_float_signed_pair_gen_var_1::().test_properties(|(m, e)| { let on = <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e); assert_eq!( >::from_sci_mantissa_and_exponent(m, e), on ); assert_eq!(on.is_some(), m >= T::ONE && m < T::TWO); }); primitive_float_signed_pair_gen_var_2::().test_properties(|(m, e)| { let x = <&Rational as SciMantissaAndExponent<_, _, _>>::from_sci_mantissa_and_exponent(m, e) .unwrap(); assert!(m >= T::ONE && m < T::TWO); let (m_alt, e_alt) = (&x).sci_mantissa_and_exponent(); assert_eq!(NiceFloat(m_alt), NiceFloat(m)); assert_eq!(e_alt, e); }); } #[test] fn from_sci_mantissa_and_exponent_properties() { apply_fn_to_primitive_floats!(from_sci_mantissa_and_exponent_properties_helper); } ================================================ FILE: malachite-q/tests/conversion/serde.rs ================================================ // Copyright © 2026 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 malachite_base::strings::string_is_subset; use malachite_base::test_util::generators::string_gen; use malachite_q::Rational; use malachite_q::test_util::generators::{rational_gen, string_gen_var_11}; use std::str::FromStr; #[test] fn test_serde() { let test = |n, out| { assert_eq!( serde_json::to_string(&Rational::from_str(n).unwrap()).unwrap(), out ); assert_eq!( serde_json::from_str::(out).unwrap().to_string(), n ); }; test("0", "{\"s\":true,\"n\":\"0x0\",\"d\":\"0x1\"}"); test("100", "{\"s\":true,\"n\":\"0x64\",\"d\":\"0x1\"}"); test( "1000000000000", "{\"s\":true,\"n\":\"0xe8d4a51000\",\"d\":\"0x1\"}", ); test( "1000000000000000000000000", "{\"s\":true,\"n\":\"0xd3c21bcecceda1000000\",\"d\":\"0x1\"}", ); test( "340282366920938463463374607431768211455", "{\"s\":true,\"n\":\"0xffffffffffffffffffffffffffffffff\",\"d\":\"0x1\"}", ); test( "340282366920938463463374607431768211456", "{\"s\":true,\"n\":\"0x100000000000000000000000000000000\",\"d\":\"0x1\"}", ); test("22/7", "{\"s\":true,\"n\":\"0x16\",\"d\":\"0x7\"}"); test("-100", "{\"s\":false,\"n\":\"0x64\",\"d\":\"0x1\"}"); test( "-1000000000000", "{\"s\":false,\"n\":\"0xe8d4a51000\",\"d\":\"0x1\"}", ); test( "-1000000000000000000000000", "{\"s\":false,\"n\":\"0xd3c21bcecceda1000000\",\"d\":\"0x1\"}", ); test( "-340282366920938463463374607431768211455", "{\"s\":false,\"n\":\"0xffffffffffffffffffffffffffffffff\",\"d\":\"0x1\"}", ); test( "-340282366920938463463374607431768211456", "{\"s\":false,\"n\":\"0x100000000000000000000000000000000\",\"d\":\"0x1\"}", ); test("-22/7", "{\"s\":false,\"n\":\"0x16\",\"d\":\"0x7\"}"); } #[test] fn serde_properties() { rational_gen().test_properties(|x| { let s = serde_json::to_string(&x).unwrap(); assert_eq!(serde_json::from_str::(&s).unwrap(), x); assert!(string_is_subset(&s, "\",-/0123456789:abcdeflnrstux{}")); }); string_gen().test_properties(|s| { let _n: Result = serde_json::from_str(&s); }); string_gen_var_11().test_properties(|s| { let _n: Rational = serde_json::from_str(&s).unwrap(); }); } ================================================ FILE: malachite-q/tests/conversion/string/from_sci_string.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, FloorLogBase}; use malachite_base::num::basic::integers::PrimitiveInt; use malachite_base::num::conversion::string::from_sci_string::preprocess_sci_string; use malachite_base::num::conversion::string::options::{FromSciStringOptions, ToSciOptions}; use malachite_base::num::conversion::traits::{ExactFrom, FromSciString, ToSci}; use malachite_base::test_util::generators::{ string_from_sci_string_options_pair_gen_var_2, string_from_sci_string_options_pair_gen_var_3, string_gen_var_14, string_gen_var_15, }; use malachite_q::Rational; use malachite_q::test_util::generators::{ rational_gen, rational_gen_var_7, rational_unsigned_pair_gen_var_6, }; use std::str::FromStr; #[test] pub fn test_from_sci_string() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string(s), out); assert_eq!( Rational::from_sci_string_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("-123", Some("-123")); test("-00123", Some("-123")); test("-123.00", Some("-123")); test("-123e0", Some("-123")); test("-12.3e1", Some("-123")); test("-1.23e2", Some("-123")); test("-1.23E2", Some("-123")); test("-1.23e+2", Some("-123")); test("-1.23E+2", Some("-123")); test("-.123e3", Some("-123")); test("-0.123e3", Some("-123")); test("-0.0123e4", Some("-123")); test("-1230e-1", Some("-123")); test("-12300e-2", Some("-123")); test("-12300E-2", Some("-123")); test("123.4", Some("617/5")); test("123.8", Some("619/5")); test("123.5", Some("247/2")); test("124.5", Some("249/2")); test("127.49", Some("12749/100")); test("-123.4", Some("-617/5")); test("-123.8", Some("-619/5")); test("-123.5", Some("-247/2")); test("-124.5", Some("-249/2")); test("-127.49", Some("-12749/100")); test("-127.5", Some("-255/2")); test("0.5", Some("1/2")); test( "0.3333333333333333", Some("3333333333333333/10000000000000000"), ); test("0.25", Some("1/4")); test("0.2", Some("1/5")); test( "0.1666666666666667", Some("1666666666666667/10000000000000000"), ); test( "0.1428571428571429", Some("1428571428571429/10000000000000000"), ); test("0.125", Some("1/8")); test( "0.1111111111111111", Some("1111111111111111/10000000000000000"), ); test("0.1", Some("1/10")); test( "0.09090909090909091", Some("9090909090909091/100000000000000000"), ); test("0.0", Some("0")); test("0.1", Some("1/10")); test("0.2", Some("1/5")); test("0.3", Some("3/10")); test("0.4", Some("2/5")); test("0.5", Some("1/2")); test("0.6", Some("3/5")); test("0.7", Some("7/10")); test("0.8", Some("4/5")); test("0.9", Some("9/10")); test("0.00", Some("0")); test("0.10", Some("1/10")); test("0.20", Some("1/5")); test("0.30", Some("3/10")); test("0.40", Some("2/5")); test("0.50", Some("1/2")); test("0.60", Some("3/5")); test("0.70", Some("7/10")); test("0.80", Some("4/5")); test("0.90", Some("9/10")); test("123.456456456456", Some("15432057057057/125000000000")); test( "1.4142135623730951", Some("14142135623730951/10000000000000000"), ); test( "3.141592653589793", Some("3141592653589793/1000000000000000"), ); test("2.718281828459045", Some("543656365691809/200000000000000")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string_with_options(s, options), out); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Rational: From, { let out = out.map(Rational::from); assert_eq!(Rational::from_sci_string_with_options(s, options), out); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_i( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_i( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_i( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_i( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_i("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_i("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_i("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("5/4")); test("1.1", options, Some("3/2")); test("1.11", options, Some("7/4")); test("0.01", options, Some("1/4")); test("0.1", options, Some("1/2")); test("0.11", options, Some("3/4")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("4/3")); test("1.11", options, Some("13/9")); test("1.111", options, Some("40/27")); test("1.112", options, Some("41/27")); test("0.1", options, Some("1/3")); test("0.11", options, Some("4/9")); test("0.111", options, Some("13/27")); test("0.112", options, Some("14/27")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options.set_base(2); test("-1e+5", options, Some("-32")); test("-1e5", options, Some("-32")); options.set_base(3); test("-1e+5", options, Some("-243")); test("-1e5", options, Some("-243")); options.set_base(4); test("-1e+5", options, Some("-1024")); test("-1e5", options, Some("-1024")); options.set_base(5); test("-1e+5", options, Some("-3125")); test("-1e5", options, Some("-3125")); options.set_base(8); test("-1e+5", options, Some("-32768")); test("-1e5", options, Some("-32768")); options.set_base(16); test("-1e+5", options, Some("-1048576")); test("-1e5", options, Some("-485")); options.set_base(32); test("-1e+5", options, Some("-33554432")); test("-1e5", options, Some("-1477")); options.set_base(36); test("-1e+5", options, Some("-60466176")); test("-1E+5", options, Some("-60466176")); test("-1e5", options, Some("-1805")); options.set_base(16); test("-ff", options, Some("-255")); test("-fF", options, Some("-255")); test("-Ff", options, Some("-255")); test("-FF", options, Some("-255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("-1.01", options, Some("-5/4")); test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-7/4")); test("-0.01", options, Some("-1/4")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-3/4")); options.set_base(3); // 1/2 is 0.111... test("-1.1", options, Some("-4/3")); test("-1.11", options, Some("-13/9")); test("-1.111", options, Some("-40/27")); test("-1.112", options, Some("-41/27")); test("-0.1", options, Some("-1/3")); test("-0.11", options, Some("-4/9")); test("-0.111", options, Some("-13/27")); test("-0.112", options, Some("-14/27")); options = FromSciStringOptions::default(); options.set_base(2); test("-2", options, None); test("-102", options, None); test("-12e4", options, None); test("-12e-4", options, None); test("-1.2", options, None); test("-0.2", options, None); test("-0.002", options, None); test("0.1111111111", options, Some("1023/1024")); options.set_base(3); test("0.1111111111", options, Some("29524/59049")); options.set_base(4); test("0.1111111111", options, Some("349525/1048576")); options.set_base(16); test("0.1111111111", options, Some("73300775185/1099511627776")); options.set_base(32); test( "0.1111111111", options, Some("36319351833633/1125899906842624"), ); options.set_base(36); test( "0.1111111111", options, Some("104461669716085/3656158440062976"), ); } #[test] pub fn test_from_sci_string_simplest() { fn test(s: &str, out: Option<&'static str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!(Rational::from_sci_string_simplest(s), out); assert_eq!( Rational::from_sci_string_simplest_with_options(s, FromSciStringOptions::default()), out ); } test("0", Some("0")); test("00", Some("0")); test("+0", Some("0")); test("-0", Some("0")); test("0.00", Some("0")); test("0e1", Some("0")); test("0e+1", Some("0")); test("0e-1", Some("0")); test("+0e+1", Some("0")); test("-0e+1", Some("0")); test("+0.0e+1", Some("0")); test("-0.0e+1", Some("0")); test(".0", Some("0")); test(".00", Some("0")); test(".00e0", Some("0")); test(".00e1", Some("0")); test(".00e-1", Some("0")); test("-.0", Some("0")); test("-.00", Some("0")); test("-.00e0", Some("0")); test("-.00e1", Some("0")); test("-.00e-1", Some("0")); test("+.0", Some("0")); test("+.00", Some("0")); test("+.00e0", Some("0")); test("+.00e1", Some("0")); test("+.00e-1", Some("0")); test("123", Some("123")); test("00123", Some("123")); test("+123", Some("123")); test("123.00", Some("123")); test("123e0", Some("123")); test("12.3e1", Some("123")); test("1.23e2", Some("123")); test("1.23E2", Some("123")); test("1.23e+2", Some("123")); test("1.23E+2", Some("123")); test(".123e3", Some("123")); test("0.123e3", Some("123")); test("+0.123e3", Some("123")); test("0.0123e4", Some("123")); test("1230e-1", Some("123")); test("12300e-2", Some("123")); test("12300E-2", Some("123")); test("-123", Some("-123")); test("-00123", Some("-123")); test("-123.00", Some("-123")); test("-123e0", Some("-123")); test("-12.3e1", Some("-123")); test("-1.23e2", Some("-123")); test("-1.23E2", Some("-123")); test("-1.23e+2", Some("-123")); test("-1.23E+2", Some("-123")); test("-.123e3", Some("-123")); test("-0.123e3", Some("-123")); test("-0.0123e4", Some("-123")); test("-1230e-1", Some("-123")); test("-12300e-2", Some("-123")); test("-12300E-2", Some("-123")); test("123.4", Some("617/5")); test("123.8", Some("495/4")); test("123.5", Some("247/2")); test("124.5", Some("249/2")); test("127.49", Some("4462/35")); test("-123.4", Some("-617/5")); test("-123.8", Some("-495/4")); test("-123.5", Some("-247/2")); test("-124.5", Some("-249/2")); test("-127.49", Some("-4462/35")); test("-127.5", Some("-255/2")); test("0.5", Some("1/2")); test("0.3333333333333333", Some("1/3")); test("0.25", Some("1/4")); test("0.2", Some("1/4")); test("0.1666666666666667", Some("1/6")); test("0.1428571428571429", Some("1/7")); test("0.125", Some("1/8")); test("0.1111111111111111", Some("1/9")); test("0.1", Some("1/7")); test("0.09090909090909091", Some("1/11")); test("0.0", Some("0")); test("0.1", Some("1/7")); test("0.2", Some("1/4")); test("0.3", Some("1/3")); test("0.4", Some("2/5")); test("0.5", Some("1/2")); test("0.6", Some("3/5")); test("0.7", Some("2/3")); test("0.8", Some("3/4")); test("0.9", Some("6/7")); test("0.00", Some("0")); test("0.10", Some("1/10")); test("0.20", Some("1/5")); test("0.30", Some("3/10")); test("0.40", Some("2/5")); test("0.50", Some("1/2")); test("0.60", Some("3/5")); test("0.70", Some("7/10")); test("0.80", Some("4/5")); test("0.90", Some("9/10")); test("123.456456456456", Some("41111/333")); test("1.4142135623730951", Some("131836323/93222358")); test("3.141592653589793", Some("80143857/25510582")); test("2.718281828459045", Some("212385209/78132152")); test("", None); test("+", None); test("-", None); test("10e", None); test("++1", None); test("1.0.0", None); test("1e++1", None); test("1e0.1", None); test("--.0", None); test("++.0", None); test(".+2", None); test(".-2", None); test("0.000a", None); test("0.00ae-10", None); test("0e10000000000000000000000000000", None); test("0e-10000000000000000000000000000", None); } #[test] pub fn test_from_sci_string_simplest_with_options() { fn test(s: &str, options: FromSciStringOptions, out: Option<&str>) { let out = out.map(|s| Rational::from_str(s).unwrap()); assert_eq!( Rational::from_sci_string_simplest_with_options(s, options), out ); } fn test_i(s: &str, options: FromSciStringOptions, out: Option) where Rational: From, { let out = out.map(Rational::from); assert_eq!( Rational::from_sci_string_simplest_with_options(s, options), out ); } // For tests with the default options, see `test_from_sci_string` let mut options = FromSciStringOptions::default(); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", options, Some(u128::MAX), ); options.set_base(3); test_i( "202201102121002021012000211012011021221022212021111001022110211020010021100121010", options, Some(u128::MAX), ); options.set_base(4); test_i( "3333333333333333333333333333333333333333333333333333333333333333", options, Some(u128::MAX), ); options.set_base(5); test_i( "11031110441201303134210404233413032443021130230130231310", options, Some(u128::MAX), ); options.set_base(8); test_i( "3777777777777777777777777777777777777777777", options, Some(u128::MAX), ); options.set_base(16); test_i("ffffffffffffffffffffffffffffffff", options, Some(u128::MAX)); options.set_base(32); test_i("7vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(u128::MAX)); options.set_base(36); test_i("f5lxx1zz5pnorynqglhzmsp33", options, Some(u128::MAX)); options.set_base(2); test_i( "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", options, Some(i128::MAX), ); test_i( "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(3); test_i( "101100201022001010121000102002120122110122221010202000122201220121120010200022001", options, Some(i128::MAX), ); test_i( "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", options, Some(i128::MIN), ); options.set_base(4); test_i( "1333333333333333333333333333333333333333333333333333333333333333", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(5); test_i( "3013030220323124042102424341431241221233040112312340402", options, Some(i128::MAX), ); test_i( "-3013030220323124042102424341431241221233040112312340403", options, Some(i128::MIN), ); options.set_base(8); test_i( "1777777777777777777777777777777777777777777", options, Some(i128::MAX), ); test_i( "-2000000000000000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(16); test_i("7fffffffffffffffffffffffffffffff", options, Some(i128::MAX)); test_i( "-80000000000000000000000000000000", options, Some(i128::MIN), ); options.set_base(32); test_i("3vvvvvvvvvvvvvvvvvvvvvvvvv", options, Some(i128::MAX)); test_i("-40000000000000000000000000", options, Some(i128::MIN)); options.set_base(36); test_i("7ksyyizzkutudzbv8aqztecjj", options, Some(i128::MAX)); test_i("-7ksyyizzkutudzbv8aqztecjk", options, Some(i128::MIN)); options.set_base(2); test("1e+5", options, Some("32")); test("1e5", options, Some("32")); options.set_base(3); test("1e+5", options, Some("243")); test("1e5", options, Some("243")); options.set_base(4); test("1e+5", options, Some("1024")); test("1e5", options, Some("1024")); options.set_base(5); test("1e+5", options, Some("3125")); test("1e5", options, Some("3125")); options.set_base(8); test("1e+5", options, Some("32768")); test("1e5", options, Some("32768")); options.set_base(16); test("1e+5", options, Some("1048576")); test("1e5", options, Some("485")); options.set_base(32); test("1e+5", options, Some("33554432")); test("1e5", options, Some("1477")); options.set_base(36); test("1e+5", options, Some("60466176")); test("1E+5", options, Some("60466176")); test("1e5", options, Some("1805")); options.set_base(16); test("ff", options, Some("255")); test("fF", options, Some("255")); test("Ff", options, Some("255")); test("FF", options, Some("255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("1.01", options, Some("4/3")); test("1.1", options, Some("3/2")); test("1.11", options, Some("5/3")); test("0.01", options, Some("1/3")); test("0.1", options, Some("1/2")); test("0.11", options, Some("2/3")); options.set_base(3); // 1/2 is 0.111... test("1.1", options, Some("3/2")); test("1.11", options, Some("3/2")); test("1.111", options, Some("3/2")); test("1.112", options, Some("3/2")); test("0.1", options, Some("1/2")); test("0.11", options, Some("1/2")); test("0.111", options, Some("1/2")); test("0.112", options, Some("1/2")); options = FromSciStringOptions::default(); options.set_base(2); test("2", options, None); test("102", options, None); test("12e4", options, None); test("12e-4", options, None); test("1.2", options, None); test("0.2", options, None); test("0.002", options, None); options.set_base(2); test("-1e+5", options, Some("-32")); test("-1e5", options, Some("-32")); options.set_base(3); test("-1e+5", options, Some("-243")); test("-1e5", options, Some("-243")); options.set_base(4); test("-1e+5", options, Some("-1024")); test("-1e5", options, Some("-1024")); options.set_base(5); test("-1e+5", options, Some("-3125")); test("-1e5", options, Some("-3125")); options.set_base(8); test("-1e+5", options, Some("-32768")); test("-1e5", options, Some("-32768")); options.set_base(16); test("-1e+5", options, Some("-1048576")); test("-1e5", options, Some("-485")); options.set_base(32); test("-1e+5", options, Some("-33554432")); test("-1e5", options, Some("-1477")); options.set_base(36); test("-1e+5", options, Some("-60466176")); test("-1E+5", options, Some("-60466176")); test("-1e5", options, Some("-1805")); options.set_base(16); test("-ff", options, Some("-255")); test("-fF", options, Some("-255")); test("-Ff", options, Some("-255")); test("-FF", options, Some("-255")); options = FromSciStringOptions::default(); options.set_base(2); // 1/2 is 0.1 test("-1.01", options, Some("-4/3")); test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-5/3")); test("-0.01", options, Some("-1/3")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-2/3")); options.set_base(3); // 1/2 is 0.111... test("-1.1", options, Some("-3/2")); test("-1.11", options, Some("-3/2")); test("-1.111", options, Some("-3/2")); test("-1.112", options, Some("-3/2")); test("-0.1", options, Some("-1/2")); test("-0.11", options, Some("-1/2")); test("-0.111", options, Some("-1/2")); test("-0.112", options, Some("-1/2")); options = FromSciStringOptions::default(); options.set_base(2); test("-2", options, None); test("-102", options, None); test("-12e4", options, None); test("-12e-4", options, None); test("-1.2", options, None); test("-0.2", options, None); test("-0.002", options, None); test("0.1111111111", options, Some("682/683")); options.set_base(3); test("0.1111111111", options, Some("1/2")); options.set_base(4); test("0.1111111111", options, Some("1/3")); options.set_base(16); test("0.1111111111", options, Some("1/15")); options.set_base(32); test("0.1111111111", options, Some("1/31")); options.set_base(36); test("0.1111111111", options, Some("1/35")); } fn from_sci_string_helper(s: &str) { if let Some(x) = Rational::from_sci_string(s) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); let mut to_options = ToSciOptions::default(); to_options.set_size_complete(); let s_alt = x.to_sci_with_options(to_options).to_string(); assert_eq!(Rational::from_sci_string(&s_alt).unwrap(), x); } } #[test] fn from_sci_string_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_helper(&s); }); } fn from_sci_string_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Rational::from_sci_string_with_options(s, options) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); let mut to_options = ToSciOptions::default(); to_options.set_base(options.get_base()); to_options.set_size_complete(); let s_alt = x.to_sci_with_options(to_options).to_string(); assert_eq!( Rational::from_sci_string_with_options(&s_alt, options).unwrap(), x ); } } #[test] fn from_sci_string_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_with_options_helper(&s, options); }); let mut options = ToSciOptions::default(); options.set_size_complete(); rational_gen().test_properties(|x| { if x.fmt_sci_valid(options) { assert_eq!( Rational::from_sci_string(&x.to_sci_with_options(options).to_string()).unwrap(), x ); } }); } fn string_precision(s: &str, base: u8) -> u64 { let mut options = FromSciStringOptions::default(); options.set_base(base); let mut s = preprocess_sci_string(s, options).unwrap().0; if s[0] == b'+' || s[0] == b'-' { s.remove(0); } let mut leading_zeros = 0; for &c in &s { if c != b'0' { break; } leading_zeros += 1; } u64::exact_from(s.len()) - leading_zeros } fn from_sci_string_simplest_helper(s: &str) { let mut from_options = FromSciStringOptions::default(); from_options.set_base(10); if let Some(x) = Rational::from_sci_string_simplest(s) { assert!(x.is_valid()); if x != 0u32 { let mut options = ToSciOptions::default(); let precision = string_precision(s, 10); options.set_precision(precision); let s_alt = x.to_sci_with_options(options).to_string(); let x_1 = Rational::from_sci_string_with_options(s, from_options).unwrap(); let x_2 = Rational::from_sci_string_with_options(&s_alt, from_options).unwrap(); // Usually x_1 == x_2. However... if x_1 != x_2 { let diff_1 = x_1 - &x; let diff_2 = x_2 - &x; assert_eq!(diff_1, -diff_2); let scale = u64::exact_from( i64::exact_from(precision) - x.abs().floor_log_base(&Rational::from(10)) - 1, ); let mut options_2 = ToSciOptions::default(); options_2.set_scale(scale); assert_eq!(diff_1.abs().to_sci_with_options(options_2).to_string(), "0"); } } } } #[test] fn from_sci_string_simplest_properties() { string_gen_var_14().test_properties(|s| { from_sci_string_simplest_helper(&s); }); string_gen_var_15().test_properties(|s| { from_sci_string_simplest_helper(&s); }); let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); rational_gen_var_7().test_properties(|q| { assert_eq!( Rational::from_sci_string_simplest(&q.to_sci_with_options(options).to_string()) .unwrap(), q ); }); } fn from_sci_string_simplest_with_options_helper(s: &str, options: FromSciStringOptions) { if let Some(x) = Rational::from_sci_string_simplest_with_options(s, options) { assert!(x.is_valid()); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 2); if x != 0u32 { let base = options.get_base(); let mut to_options = ToSciOptions::default(); to_options.set_base(base); let precision = string_precision(s, base); to_options.set_precision(precision); let mut from_options = FromSciStringOptions::default(); from_options.set_base(base); let s_alt = x.to_sci_with_options(to_options).to_string(); let x_1 = Rational::from_sci_string_with_options(s, from_options).unwrap(); let x_2 = Rational::from_sci_string_with_options(&s_alt, from_options).unwrap(); // Usually x_1 == x_2. However... if x_1 != x_2 { let diff_1 = x_1 - &x; let diff_2 = x_2 - &x; assert_eq!(diff_1, -diff_2); let scale = u64::exact_from( i64::exact_from(precision) - x.abs().floor_log_base(&Rational::from(base)) - 1, ); let mut options_2 = ToSciOptions::default(); options_2.set_base(base); options_2.set_scale(scale); assert_eq!(diff_1.abs().to_sci_with_options(options_2).to_string(), "0"); } } } } #[test] fn from_sci_string_simplest_with_options_properties() { string_from_sci_string_options_pair_gen_var_2().test_properties(|(s, options)| { from_sci_string_simplest_with_options_helper(&s, options); }); string_from_sci_string_options_pair_gen_var_3().test_properties(|(s, options)| { from_sci_string_simplest_with_options_helper(&s, options); }); // This fails for rationals with sufficiently large numerator and denominator rational_unsigned_pair_gen_var_6().test_properties(|(q, base)| { let mut to_options = ToSciOptions::default(); to_options.set_include_trailing_zeros(true); to_options.set_base(base); let mut from_options = FromSciStringOptions::default(); from_options.set_base(base); assert_eq!( Rational::from_sci_string_simplest_with_options( &q.to_sci_with_options(to_options).to_string(), from_options ) .unwrap(), q ); }); } ================================================ FILE: malachite-q/tests/conversion/string/from_string.rs ================================================ // Copyright © 2026 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 malachite_base::test_util::generators::common::GenConfig; use malachite_base::test_util::generators::string_gen; use malachite_nz::integer::Integer; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::string_gen_var_12; use num::BigRational; use std::str::FromStr; #[test] fn test_from_str() { let test_ok = |s, n| { assert_eq!(Rational::from_str(s).unwrap().to_string(), n); assert_eq!(BigRational::from_str(s).unwrap().to_string(), n); assert_eq!(rug::Rational::from_str(s).unwrap().to_string(), n); }; test_ok("0", "0"); test_ok("-0", "0"); test_ok("123456", "123456"); test_ok("1000000000000000000000000", "1000000000000000000000000"); test_ok("-123456", "-123456"); test_ok("-1000000000000000000000000", "-1000000000000000000000000"); test_ok("01/02", "1/2"); test_ok("3/21", "1/7"); let test_err = |s, rug_err| { assert!(Rational::from_str(s).is_err()); assert!(BigRational::from_str(s).is_err()); let rn = rug::Rational::from_str(s); assert_eq!(rn.is_err() || rn.unwrap() < 0, rug_err); }; test_err("12A", true); test_err(" 10", false); test_err("1.0", true); test_err("$%^", true); test_err("", true); test_err("-", true); test_err("1/0", true); test_err("/1", true); test_err("--0", true); test_err("-+0", true); test_err("+-0", true); test_err("++0", true); test_err("--1", true); test_err("-+1", true); test_err("+-1", true); test_err("++1", true); } #[allow(unused_must_use)] #[test] fn from_str_properties() { let mut config = GenConfig::new(); config.insert("mean_length_n", 64); string_gen().test_properties_with_config(&config, |s| { Rational::from_str(&s); }); string_gen_var_12().test_properties(|s| { let n = Rational::from_str(&s).unwrap(); assert_eq!(BigRational::from_str(&s).unwrap(), BigRational::from(&n)); assert_eq!( rug::Rational::from_str(&s).unwrap(), rug::Rational::from(&n) ); }); integer_gen().test_properties(|x| { let s = x.to_string(); assert_eq!( Rational::from_str(&s).unwrap(), Integer::from_str(&s).unwrap() ); }); } ================================================ FILE: malachite-q/tests/conversion/string/to_sci.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, FloorLogBase, Pow, PowerOf2, RoundToMultiple}; use malachite_base::num::basic::floats::PrimitiveFloat; use malachite_base::num::conversion::string::options::{ FromSciStringOptions, SciSizeOptions, ToSciOptions, }; use malachite_base::num::conversion::traits::{ExactFrom, FromSciString, ToSci}; use malachite_base::rounding_modes::RoundingMode::*; use malachite_base::strings::string_is_subset; use malachite_base::test_util::num::conversion::string::from_sci_string::DECIMAL_SCI_STRING_CHARS; use malachite_nz::test_util::generators::{integer_gen, integer_to_sci_options_pair_gen_var_1}; use malachite_q::Rational; use malachite_q::conversion::string::to_sci::floor_log_base_of_abs; use malachite_q::test_util::generators::{rational_gen, rational_to_sci_options_pair_gen_var_1}; use std::collections::HashMap; use std::str::FromStr; #[test] pub fn test_to_sci() { assert_eq!( Rational::power_of_2(1000000u64).to_sci().to_string(), "9.900656229295898e301029" ); assert_eq!( (-Rational::power_of_2(1000000u64)).to_sci().to_string(), "-9.900656229295898e301029" ); assert_eq!( Rational::power_of_2(-1000000i64).to_sci().to_string(), "1.01003405919803e-301030" ); assert_eq!( (-Rational::power_of_2(-1000000i64)).to_sci().to_string(), "-1.01003405919803e-301030" ); fn test(s: &str, out: &str) { let x = Rational::from_str(s).unwrap(); assert_eq!(x.to_sci().to_string(), out); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), out ); } test("1/2", "0.5"); test("1/3", "0.3333333333333333"); test("1/4", "0.25"); test("1/5", "0.2"); test("1/6", "0.1666666666666667"); test("1/7", "0.1428571428571429"); test("1/8", "0.125"); test("1/9", "0.1111111111111111"); test("1/10", "0.1"); // Still 16 significant digits test("1/11", "0.09090909090909091"); test("1/137", "0.007299270072992701"); test("22/7", "3.142857142857143"); test("245850922/78256779", "3.141592653589793"); test("936851431250/1397", "670616629.3843951"); test("1/123456789", "8.100000073710001e-9"); test("0", "0"); test("1", "1"); test("10", "10"); test("100", "100"); test("1000", "1000"); test("10000", "10000"); test("100000", "100000"); test("1000000", "1000000"); test("10000000", "10000000"); test("100000000", "100000000"); test("1000000000", "1000000000"); test("10000000000", "10000000000"); test("100000000000", "100000000000"); test("1000000000000", "1000000000000"); test("10000000000000", "10000000000000"); test("100000000000000", "100000000000000"); test("1000000000000000", "1000000000000000"); test("10000000000000000", "1e16"); test("100000000000000000", "1e17"); test("1/10", "0.1"); test("1/100", "0.01"); test("1/1000", "0.001"); test("1/10000", "0.0001"); test("1/100000", "0.00001"); test("1/1000000", "1e-6"); test("1/10000000", "1e-7"); test("1/100000000", "1e-8"); test("999999999999999", "999999999999999"); test("9999999999999999", "9999999999999999"); test("99999999999999999", "1e17"); test("999999999999999999", "1e18"); test("-1", "-1"); test("-10", "-10"); test("-100", "-100"); test("-1000", "-1000"); test("-10000", "-10000"); test("-100000", "-100000"); test("-1000000", "-1000000"); test("-10000000", "-10000000"); test("-100000000", "-100000000"); test("-1000000000", "-1000000000"); test("-10000000000", "-10000000000"); test("-100000000000", "-100000000000"); test("-1000000000000", "-1000000000000"); test("-10000000000000", "-10000000000000"); test("-100000000000000", "-100000000000000"); test("-1000000000000000", "-1000000000000000"); test("-10000000000000000", "-1e16"); test("-100000000000000000", "-1e17"); test("-1/10", "-0.1"); test("-1/100", "-0.01"); test("-1/1000", "-0.001"); test("-1/10000", "-0.0001"); test("-1/100000", "-0.00001"); test("-1/1000000", "-1e-6"); test("-1/10000000", "-1e-7"); test("-1/100000000", "-1e-8"); } #[test] pub fn test_to_sci_with_options() { fn test_i(x: &Rational, options: ToSciOptions, out: &str) { assert_eq!(x.to_sci_with_options(options).to_string(), out); } fn test(s: &str, options: ToSciOptions, out: &str) { test_i(&Rational::from_str(s).unwrap(), options, out); } // For tests with the default options, see `test_to_sci` let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test("0", options, "0.000000000000000"); test("1", options, "1.000000000000000"); test("10", options, "10.00000000000000"); test("100", options, "100.0000000000000"); test("1000", options, "1000.000000000000"); test("10000", options, "10000.00000000000"); test("100000", options, "100000.0000000000"); test("1000000", options, "1000000.000000000"); test("10000000", options, "10000000.00000000"); test("100000000", options, "100000000.0000000"); test("1000000000", options, "1000000000.000000"); test("10000000000", options, "10000000000.00000"); test("100000000000", options, "100000000000.0000"); test("1000000000000", options, "1000000000000.000"); test("10000000000000", options, "10000000000000.00"); test("100000000000000", options, "100000000000000.0"); test("1000000000000000", options, "1000000000000000"); test("10000000000000000", options, "1.000000000000000e16"); test("100000000000000000", options, "1.000000000000000e17"); test_i(&Rational::from(u64::MAX), options, "1.844674407370955e19"); test_i(&Rational::from(u128::MAX), options, "3.402823669209385e38"); test("999999999999999", options, "999999999999999.0"); test("9999999999999999", options, "9999999999999999"); test("99999999999999999", options, "1.000000000000000e17"); test("999999999999999999", options, "1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test_i(&Rational::from(u128::MAX), options, "1e128"); options.set_base(3); test_i(&Rational::from(u128::MAX), options, "2.022011021210021e80"); options.set_base(4); test_i(&Rational::from(u128::MAX), options, "1e64"); options.set_base(5); test_i(&Rational::from(u128::MAX), options, "1.103111044120131e55"); options.set_base(8); test_i(&Rational::from(u128::MAX), options, "4e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test_i(&Rational::from(u128::MAX), options, "1e+32"); options.set_base(32); test_i(&Rational::from(u128::MAX), options, "8e+25"); options.set_base(36); test_i(&Rational::from(u128::MAX), options, "f.5lxx1zz5pnorynqe+24"); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test_i(&Rational::from(u128::MAX), options, "2.022011021210021e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test_i(&Rational::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQe+24"); options.set_lowercase(); options.set_e_uppercase(); test_i(&Rational::from(u128::MAX), options, "f.5lxx1zz5pnorynqE+24"); options.set_uppercase(); test_i(&Rational::from(u128::MAX), options, "F.5LXX1ZZ5PNORYNQE+24"); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test_i( &Rational::from(u128::MAX), options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111", ); options.set_base(3); test_i( &Rational::from(u128::MAX), options, "202201102121002021012000211012011021221022212021111001022110211020010021100121010", ); options.set_base(4); test_i( &Rational::from(u128::MAX), options, "3333333333333333333333333333333333333333333333333333333333333333", ); options.set_base(5); test_i( &Rational::from(u128::MAX), options, "11031110441201303134210404233413032443021130230130231310", ); options.set_base(8); test_i( &Rational::from(u128::MAX), options, "3777777777777777777777777777777777777777777", ); options.set_base(16); test_i( &Rational::from(u128::MAX), options, "ffffffffffffffffffffffffffffffff", ); options.set_base(32); test_i( &Rational::from(u128::MAX), options, "7vvvvvvvvvvvvvvvvvvvvvvvvv", ); options.set_base(36); test_i( &Rational::from(u128::MAX), options, "f5lxx1zz5pnorynqglhzmsp33", ); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test("0", options, "0.000"); test("1", options, "1.000"); test("10", options, "10.00"); test("100", options, "100.0"); test("1000", options, "1000"); test("10000", options, "1.000e4"); test("9", options, "9.000"); test("99", options, "99.00"); test("999", options, "999.0"); test("9999", options, "9999"); test("99999", options, "1.000e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "1e1"); test("100", options, "1e2"); test("1000", options, "1e3"); test("10000", options, "1e4"); test("9", options, "9"); test("99", options, "1e2"); test("999", options, "1e3"); test("9999", options, "1e4"); test("99999", options, "1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test("0", options, "0.00"); test("1", options, "1.00"); test("10", options, "10.00"); test("100", options, "100.00"); test("1000", options, "1000.00"); test("10000", options, "10000.00"); test("9", options, "9.00"); test("99", options, "99.00"); test("999", options, "999.00"); test("9999", options, "9999.00"); test("99999", options, "99999.00"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options.set_include_trailing_zeros(false); test("0", options, "0"); test("1", options, "1"); test("10", options, "10"); test("100", options, "100"); test("1000", options, "1000"); test("10000", options, "10000"); test("9", options, "9"); test("99", options, "99"); test("999", options, "999"); test("9999", options, "9999"); test("99999", options, "99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test("123", options, "1.2e2"); options.set_rounding_mode(Down); test("123", options, "1.2e2"); options.set_rounding_mode(Floor); test("123", options, "1.2e2"); options.set_rounding_mode(Up); test("123", options, "1.3e2"); options.set_rounding_mode(Ceiling); test("123", options, "1.3e2"); options.set_rounding_mode(Nearest); test("135", options, "1.4e2"); options.set_rounding_mode(Down); test("135", options, "1.3e2"); options.set_rounding_mode(Floor); test("135", options, "1.3e2"); options.set_rounding_mode(Up); test("135", options, "1.4e2"); options.set_rounding_mode(Ceiling); test("135", options, "1.4e2"); options.set_rounding_mode(Exact); test("140", options, "1.4e2"); options.set_rounding_mode(Nearest); test("999", options, "1e3"); options.set_rounding_mode(Down); test("999", options, "9.9e2"); options.set_rounding_mode(Floor); test("999", options, "9.9e2"); options.set_rounding_mode(Up); test("999", options, "1e3"); options.set_rounding_mode(Ceiling); test("999", options, "1e3"); let mut options = ToSciOptions::default(); options.set_include_trailing_zeros(true); test_i(&Rational::from(i64::MAX), options, "9.223372036854776e18"); test_i(&Rational::from(i128::MAX), options, "1.701411834604692e38"); test("-1", options, "-1.000000000000000"); test("-10", options, "-10.00000000000000"); test("-100", options, "-100.0000000000000"); test("-1000", options, "-1000.000000000000"); test("-10000", options, "-10000.00000000000"); test("-100000", options, "-100000.0000000000"); test("-1000000", options, "-1000000.000000000"); test("-10000000", options, "-10000000.00000000"); test("-100000000", options, "-100000000.0000000"); test("-1000000000", options, "-1000000000.000000"); test("-10000000000", options, "-10000000000.00000"); test("-100000000000", options, "-100000000000.0000"); test("-1000000000000", options, "-1000000000000.000"); test("-10000000000000", options, "-10000000000000.00"); test("-100000000000000", options, "-100000000000000.0"); test("-1000000000000000", options, "-1000000000000000"); test("-10000000000000000", options, "-1.000000000000000e16"); test("-100000000000000000", options, "-1.000000000000000e17"); test_i(&Rational::from(i64::MIN), options, "-9.223372036854776e18"); test_i(&Rational::from(i128::MIN), options, "-1.701411834604692e38"); test("-999999999999999", options, "-999999999999999.0"); test("-9999999999999999", options, "-9999999999999999"); test("-99999999999999999", options, "-1.000000000000000e17"); test("-999999999999999999", options, "-1.000000000000000e18"); options = ToSciOptions::default(); options.set_base(2); test_i(&Rational::from(i128::MAX), options, "1e127"); test_i(&Rational::from(i128::MIN), options, "-1e127"); options.set_base(3); test_i(&Rational::from(i128::MAX), options, "1.01100201022001e80"); test_i(&Rational::from(i128::MIN), options, "-1.01100201022001e80"); options.set_base(4); test_i(&Rational::from(i128::MAX), options, "2e63"); test_i(&Rational::from(i128::MIN), options, "-2e63"); options.set_base(5); test_i(&Rational::from(i128::MAX), options, "3.013030220323124e54"); test_i(&Rational::from(i128::MIN), options, "-3.013030220323124e54"); options.set_base(8); test_i(&Rational::from(i128::MAX), options, "2e42"); test_i(&Rational::from(i128::MIN), options, "-2e42"); // When base >= 15, there is a mandatory sign after the exponent indicator "e", to distinguish // it from the digit "e" options.set_base(16); test_i(&Rational::from(i128::MAX), options, "8e+31"); test_i(&Rational::from(i128::MIN), options, "-8e+31"); options.set_base(32); test_i(&Rational::from(i128::MAX), options, "4e+25"); test_i(&Rational::from(i128::MIN), options, "-4e+25"); options.set_base(36); test_i(&Rational::from(i128::MAX), options, "7.ksyyizzkutudzbve+24"); test_i( &Rational::from(i128::MIN), options, "-7.ksyyizzkutudzbve+24", ); // The sign can be forced in other cases too options.set_base(3); options.set_force_exponent_plus_sign(true); test_i(&Rational::from(i128::MAX), options, "1.01100201022001e+80"); test_i(&Rational::from(i128::MIN), options, "-1.01100201022001e+80"); // The digits can be uppercase, and so can the exponent indicator options = ToSciOptions::default(); options.set_base(36); options.set_uppercase(); test_i(&Rational::from(i128::MAX), options, "7.KSYYIZZKUTUDZBVe+24"); test_i( &Rational::from(i128::MIN), options, "-7.KSYYIZZKUTUDZBVe+24", ); options.set_lowercase(); options.set_e_uppercase(); test_i(&Rational::from(i128::MAX), options, "7.ksyyizzkutudzbvE+24"); test_i( &Rational::from(i128::MIN), options, "-7.ksyyizzkutudzbvE+24", ); options.set_uppercase(); test_i(&Rational::from(i128::MAX), options, "7.KSYYIZZKUTUDZBVE+24"); test_i( &Rational::from(i128::MIN), options, "-7.KSYYIZZKUTUDZBVE+24", ); options = ToSciOptions::default(); options.set_size_complete(); options.set_base(2); test_i( &Rational::from(i128::MAX), options, "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111", ); test_i( &Rational::from(i128::MIN), options, "-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000", ); options.set_base(3); test_i( &Rational::from(i128::MAX), options, "101100201022001010121000102002120122110122221010202000122201220121120010200022001", ); test_i( &Rational::from(i128::MIN), options, "-101100201022001010121000102002120122110122221010202000122201220121120010200022002", ); options.set_base(4); test_i( &Rational::from(i128::MAX), options, "1333333333333333333333333333333333333333333333333333333333333333", ); test_i( &Rational::from(i128::MIN), options, "-2000000000000000000000000000000000000000000000000000000000000000", ); options.set_base(5); test_i( &Rational::from(i128::MAX), options, "3013030220323124042102424341431241221233040112312340402", ); test_i( &Rational::from(i128::MIN), options, "-3013030220323124042102424341431241221233040112312340403", ); options.set_base(8); test_i( &Rational::from(i128::MAX), options, "1777777777777777777777777777777777777777777", ); test_i( &Rational::from(i128::MIN), options, "-2000000000000000000000000000000000000000000", ); options.set_base(16); test_i( &Rational::from(i128::MAX), options, "7fffffffffffffffffffffffffffffff", ); test_i( &Rational::from(i128::MIN), options, "-80000000000000000000000000000000", ); options.set_base(32); test_i( &Rational::from(i128::MAX), options, "3vvvvvvvvvvvvvvvvvvvvvvvvv", ); test_i( &Rational::from(i128::MIN), options, "-40000000000000000000000000", ); options.set_base(36); test_i( &Rational::from(i128::MAX), options, "7ksyyizzkutudzbv8aqztecjj", ); test_i( &Rational::from(i128::MIN), options, "-7ksyyizzkutudzbv8aqztecjk", ); options = ToSciOptions::default(); options.set_precision(4); options.set_include_trailing_zeros(true); test("-1", options, "-1.000"); test("-10", options, "-10.00"); test("-100", options, "-100.0"); test("-1000", options, "-1000"); test("-10000", options, "-1.000e4"); test("-9", options, "-9.000"); test("-99", options, "-99.00"); test("-999", options, "-999.0"); test("-9999", options, "-9999"); test("-99999", options, "-1.000e5"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-1e5"); options = ToSciOptions::default(); options.set_precision(1); options.set_include_trailing_zeros(true); // doesn't matter when precision is 1 test("-1", options, "-1"); test("-10", options, "-1e1"); test("-100", options, "-1e2"); test("-1000", options, "-1e3"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-1e2"); test("-999", options, "-1e3"); test("-9999", options, "-1e4"); test("-99999", options, "-1e5"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-1e1"); test("-100", options, "-1e2"); test("-1000", options, "-1e3"); test("-10000", options, "-1e4"); test("-9", options, "-9"); test("-99", options, "-1e2"); test("-999", options, "-1e3"); test("-9999", options, "-1e4"); test("-99999", options, "-1e5"); options = ToSciOptions::default(); options.set_scale(2); options.set_include_trailing_zeros(true); test("-1", options, "-1.00"); test("-10", options, "-10.00"); test("-100", options, "-100.00"); test("-1000", options, "-1000.00"); test("-10000", options, "-10000.00"); test("-9", options, "-9.00"); test("-99", options, "-99.00"); test("-999", options, "-999.00"); test("-9999", options, "-9999.00"); test("-99999", options, "-99999.00"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options = ToSciOptions::default(); options.set_scale(0); options.set_include_trailing_zeros(true); // doesn't matter when scale is 0 test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options.set_include_trailing_zeros(false); test("-1", options, "-1"); test("-10", options, "-10"); test("-100", options, "-100"); test("-1000", options, "-1000"); test("-10000", options, "-10000"); test("-9", options, "-9"); test("-99", options, "-99"); test("-999", options, "-999"); test("-9999", options, "-9999"); test("-99999", options, "-99999"); options = ToSciOptions::default(); options.set_precision(2); options.set_rounding_mode(Nearest); // This is the default test("-123", options, "-1.2e2"); options.set_rounding_mode(Down); test("-123", options, "-1.2e2"); options.set_rounding_mode(Floor); test("-123", options, "-1.3e2"); options.set_rounding_mode(Up); test("-123", options, "-1.3e2"); options.set_rounding_mode(Ceiling); test("-123", options, "-1.2e2"); options.set_rounding_mode(Nearest); test("-135", options, "-1.4e2"); options.set_rounding_mode(Down); test("-135", options, "-1.3e2"); options.set_rounding_mode(Floor); test("-135", options, "-1.4e2"); options.set_rounding_mode(Up); test("-135", options, "-1.4e2"); options.set_rounding_mode(Ceiling); test("-135", options, "-1.3e2"); options.set_rounding_mode(Exact); test("-140", options, "-1.4e2"); options.set_rounding_mode(Nearest); test("-999", options, "-1e3"); options.set_rounding_mode(Down); test("-999", options, "-9.9e2"); options.set_rounding_mode(Floor); test("-999", options, "-1e3"); options.set_rounding_mode(Up); test("-999", options, "-1e3"); options.set_rounding_mode(Ceiling); test("-999", options, "-9.9e2"); options = ToSciOptions::default(); options.set_scale(2); test("1/3", options, "0.33"); options.set_scale(1); test("1/3", options, "0.3"); options.set_scale(0); test("1/3", options, "0"); options.set_scale(4); test("1/300", options, "0.0033"); options.set_scale(3); test("1/300", options, "0.003"); options.set_scale(2); test("1/300", options, "0"); options.set_scale(1); test("1/300", options, "0"); options.set_rounding_mode(Ceiling); options.set_scale(2); test("1/3", options, "0.34"); options.set_scale(1); test("1/3", options, "0.4"); options.set_scale(0); test("1/3", options, "1"); options.set_scale(4); test("1/300", options, "0.0034"); options.set_scale(3); test("1/300", options, "0.004"); options.set_scale(2); test("1/300", options, "0.01"); options.set_scale(1); test("1/300", options, "0.1"); options = ToSciOptions::default(); options.set_base(2); test("245850922/78256779", options, "11.0010010001"); options.set_base(3); test("245850922/78256779", options, "10.01021101222201"); options.set_base(4); test("245850922/78256779", options, "3.021003331222202"); options.set_base(5); test("245850922/78256779", options, "3.032322143033433"); options.set_base(8); test("245850922/78256779", options, "3.110375524210264"); options.set_base(16); test("245850922/78256779", options, "3.243f6a8885a3033"); options.set_base(32); test("245850922/78256779", options, "3.4gvml245kc1j1qs"); options.set_base(36); test("245850922/78256779", options, "3.53i5ab8p5fhzpkj"); options = ToSciOptions::default(); options.set_size_complete(); test("1/2", options, "0.5"); test("1/4", options, "0.25"); test("1/5", options, "0.2"); test("1/8", options, "0.125"); test("1/10", options, "0.1"); options.set_base(2); test("1/2", options, "0.1"); test("1/4", options, "0.01"); test("1/8", options, "0.001"); options.set_base(3); test("1/3", options, "0.1"); test("1/9", options, "0.01"); options.set_base(4); test("1/2", options, "0.2"); test("1/4", options, "0.1"); test("1/8", options, "0.02"); options.set_base(5); test("1/5", options, "0.1"); options.set_base(6); test("1/2", options, "0.3"); test("1/3", options, "0.2"); test("1/6", options, "0.1"); test("1/9", options, "0.04"); options.set_base(7); test("1/7", options, "0.1"); options.set_base(8); test("1/2", options, "0.4"); test("1/4", options, "0.2"); test("1/8", options, "0.1"); options.set_base(9); test("1/3", options, "0.3"); test("1/9", options, "0.1"); options = ToSciOptions::default(); options.set_size_complete(); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "1.401298464324817070923729583289916131280261941876515771757068283889791082685860601486638\ 18836212158203125e-45", ); options.set_base(2); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "1e-149", ); options.set_base(32); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "2e-30", ); options.set_base(36); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "1.whin9rvdkphvrmxkdwtoq8t963n428tj1p07aaum2yy14ie-29", ); options.set_uppercase(); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "1.WHIN9RVDKPHVRMXKDWTOQ8T963N428TJ1P07AAUM2YY14Ie-29", ); options.set_base(10); options.set_neg_exp_threshold(-200); test_i( &Rational::exact_from(f32::MIN_POSITIVE_SUBNORMAL), options, "0.000000000000000000000000000000000000000000001401298464324817070923729583289916131280261\ 94187651577175706828388979108268586060148663818836212158203125", ); options = ToSciOptions::default(); test("1/1000", options, "0.001"); options.set_neg_exp_threshold(-3); test("1/1000", options, "1e-3"); test("1/100", options, "0.01"); options.set_neg_exp_threshold(-2); test("1/100", options, "1e-2"); test("1/10", options, "0.1"); options.set_neg_exp_threshold(-1); test("1/10", options, "1e-1"); options = ToSciOptions::default(); options.set_base(3); options.set_scale(1); // Nearest uses bankers' rounding: 1/2 is equidistant to 0.1 and 0.2 in base 3, so we choose the // even option, 0.2. test("1/2", options, "0.2"); } #[should_panic] #[test] pub fn to_sci_with_options_fail() { let mut options = ToSciOptions::default(); options.set_rounding_mode(Exact); options.set_precision(2); Rational::from(123).to_sci_with_options(options).to_string(); } #[test] fn to_sci_properties() { let mut powers_of_10 = HashMap::new(); let ten = Rational::from(10); let default_p = 16; rational_gen().test_properties(|x| { assert!(x.fmt_sci_valid(ToSciOptions::default())); let s = x.to_sci().to_string(); assert_eq!( x.to_sci_with_options(ToSciOptions::default()).to_string(), s ); assert!(string_is_subset(&s, DECIMAL_SCI_STRING_CHARS)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains('E')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); let x_from = Rational::from_sci_string(&s).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let log = (&x).abs().floor_log_base(&ten); let pow = powers_of_10 .entry(log - default_p + 1) .or_insert_with_key(|&p| (&ten).pow(p)); assert_eq!(x.round_to_multiple(&*pow, Nearest).0, x_from); } }); integer_gen().test_properties(|x| { assert_eq!( x.to_sci().to_string(), Rational::from(x).to_sci().to_string() ); }); } #[test] fn to_sci_with_options_properties() { let mut powers = HashMap::new(); let mut chars = HashMap::new(); rational_to_sci_options_pair_gen_var_1().test_properties(|(x, options)| { assert!(x.fmt_sci_valid(options)); let s = x.to_sci_with_options(options).to_string(); let cs: &mut String = chars.entry(options.get_base()).or_insert_with_key(|&base| { let mut cs = "+-.0123456789".to_string(); if base > 10 { let limit = usize::from(base - 10); for c in ('a'..='z').take(limit) { cs.push(c); } for c in ('A'..='Z').take(limit) { cs.push(c); } } if base < 15 { cs.push('e'); cs.push('E'); } cs }); assert!(string_is_subset(&s, cs)); assert!(!s.starts_with('+')); assert!(!s.starts_with('.')); assert!(!s.ends_with('+')); assert!(!s.ends_with('-')); assert!(!s.ends_with('.')); assert!(!s.contains("++")); assert!(!s.contains("+-")); assert!(!s.contains("-+")); assert!(!s.contains("--")); assert!(!s.contains("-+")); assert!(!s.contains("+.")); assert!(!s.contains("-.")); assert!(s.chars().filter(|&c| c == '.').count() <= 1); assert!(s.chars().filter(|&c| c == '-').count() <= 2); assert!(s.chars().filter(|&c| c == '+').count() <= 1); let mut from_options = FromSciStringOptions::default(); from_options.set_base(options.get_base()); let x_from = Rational::from_sci_string_with_options(&s, from_options).unwrap(); if x == 0u32 { assert_eq!(x_from, 0u32); } else { let base = options.get_base(); let q_base = Rational::from(base); let log = floor_log_base_of_abs(&x, &q_base); let (scale, might_round_to_zero) = match options.get_size_options() { SciSizeOptions::Complete => { let scale = x.length_after_point_in_small_base(base).unwrap(); assert!(i64::exact_from(scale) + log + 1 > 0); (None, false) } SciSizeOptions::Scale(scale) => { let scale = i64::exact_from(scale); (Some(scale), scale + log < 0) } SciSizeOptions::Precision(precision) => { (Some(i64::exact_from(precision - 1) - log), false) } }; if might_round_to_zero && x_from == 0u32 { // Do nothing } else if let Some(neg_scale) = scale.map(|s| -s) { let pow = powers .entry((base, neg_scale)) .or_insert_with(|| (&q_base).pow(neg_scale)); let rounded = (&x).round_to_multiple(&*pow, options.get_rounding_mode()).0; assert_eq!(rounded, x_from); } else { assert_eq!(x_from, x); } } }); integer_to_sci_options_pair_gen_var_1().test_properties(|(x, options)| { assert_eq!( x.to_sci_with_options(options).to_string(), Rational::from(x).to_sci_with_options(options).to_string() ); }); } ================================================ FILE: malachite-q/tests/conversion/string/to_string.rs ================================================ // Copyright © 2026 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 malachite_base::strings::ToDebugString; use malachite_base::strings::string_is_subset; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::BigRational; use std::str::FromStr; #[test] pub fn test_to_string() { fn test(u: &str) { let x = Rational::from_str(u).unwrap(); assert_eq!(x.to_string(), u); assert_eq!(x.to_debug_string(), u); } test("0"); test("2"); test("123"); test("1000"); test("1000000"); test("1000000000000000"); test("-2"); test("-123"); test("-1000"); test("-1000000"); test("-1000000000000000"); test("99/100"); test("101/100"); test("22/7"); test("-99/100"); test("-101/100"); test("-22/7"); } #[test] fn to_string_properties() { rational_gen().test_properties(|x| { let s = x.to_string(); assert_eq!(x.to_debug_string(), s); assert_eq!(BigRational::from(&x).to_string(), s); assert_eq!(rug::Rational::from(&x).to_string(), s); assert!(string_is_subset(&s, "-/0123456789")); if x != 0 { assert!(!s.starts_with('0')); } }); integer_gen().test_properties(|x| { assert_eq!(Rational::from(&x).to_string(), x.to_string()); }); } ================================================ FILE: malachite-q/tests/conversion/to_numerator_or_denominator.rs ================================================ // Copyright © 2026 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 malachite_base::num::arithmetic::traits::{Abs, UnsignedAbs}; use malachite_base::num::basic::traits::One; use malachite_base::strings::ToDebugString; use malachite_nz::integer::Integer; use malachite_nz::natural::Natural; use malachite_nz::test_util::generators::integer_gen; use malachite_q::Rational; use malachite_q::test_util::generators::rational_gen; use num::{BigRational, Signed}; use std::str::FromStr; #[test] fn test_to_numerator() { let test = |s, n| { let q = Rational::from_str(s).unwrap(); assert_eq!(q.to_numerator().to_string(), n); assert_eq!(q.clone().into_numerator().to_string(), n); assert_eq!(q.numerator_ref().to_string(), n); assert_eq!( BigRational::from_str(s).unwrap().numer().abs().to_string(), n ); assert_eq!( rug::Rational::from_str(s) .unwrap() .numer() .clone() .abs() .to_string(), n ); }; test("0", "0"); test("1/2", "1"); test("-1/2", "1"); test("100/101", "100"); test("-100/101", "100"); } #[test] fn to_numerator_properties() { rational_gen().test_properties(|q| { let n = q.to_numerator(); assert_eq!(q.clone().into_numerator(), n); assert_eq!(*q.numerator_ref(), n); assert_eq!(q.to_numerator_and_denominator().0, n); assert_eq!(Integer::from(BigRational::from(&q).numer()).abs(), n); assert_eq!(Integer::from(rug::Rational::from(&q).numer()).abs(), n); }); integer_gen().test_properties(|n| { assert_eq!(Rational::from(&n).into_numerator(), n.abs()); }); } #[test] fn test_to_denominator() { let test = |s, d| { let q = Rational::from_str(s).unwrap(); assert_eq!(q.to_denominator().to_string(), d); assert_eq!(q.clone().into_denominator().to_string(), d); assert_eq!(q.denominator_ref().to_string(), d); assert_eq!( BigRational::from_str(s).unwrap().denom().abs().to_string(), d ); assert_eq!( rug::Rational::from_str(s) .unwrap() .denom() .clone() .abs() .to_string(), d ); }; test("0", "1"); test("1/2", "2"); test("-1/2", "2"); test("100/101", "101"); test("-100/101", "101"); } #[test] fn to_denominator_properties() { rational_gen().test_properties(|q| { let d = q.to_denominator(); assert_eq!(q.clone().into_denominator(), d); assert_eq!(*q.denominator_ref(), d); assert_eq!(q.to_numerator_and_denominator().1, d); assert_eq!(Integer::from(BigRational::from(&q).denom()).abs(), d); assert_eq!(Integer::from(rug::Rational::from(&q).denom()).abs(), d); }); integer_gen().test_properties(|n| { assert_eq!(Rational::from(&n).into_denominator(), 1); }); } #[test] fn test_to_numerator_and_denominator() { let test = |s, nd| { let q = Rational::from_str(s).unwrap(); assert_eq!(q.to_numerator_and_denominator().to_debug_string(), nd); assert_eq!( q.clone().into_numerator_and_denominator().to_debug_string(), nd ); assert_eq!(q.numerator_and_denominator_ref().to_debug_string(), nd); }; test("0", "(0, 1)"); test("1/2", "(1, 2)"); test("-1/2", "(1, 2)"); test("100/101", "(100, 101)"); test("-100/101", "(100, 101)"); } #[test] fn to_numerator_and_denominator_properties() { rational_gen().test_properties(|q| { let (n, d) = q.to_numerator_and_denominator(); assert_eq!( q.clone().into_numerator_and_denominator(), (n.clone(), d.clone()) ); assert_eq!(q.numerator_and_denominator_ref(), (&n, &d)); assert_eq!(Rational::from_naturals(n, d), q.abs()); }); integer_gen().test_properties(|n| { assert_eq!( Rational::from(&n).into_numerator_and_denominator(), (n.unsigned_abs(), Natural::ONE) ); }); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_negative_rationals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_q::exhaustive::exhaustive_negative_rationals; #[test] fn test_exhaustive_negative_rationals() { assert_eq!( exhaustive_negative_rationals() .take(20) .collect_vec() .to_debug_string(), "[-1, -1/2, -2, -1/3, -3/2, -2/3, -3, -1/4, -4/3, -3/5, -5/2, -2/5, -5/3, -3/4, -4, -1/5, \ -5/4, -4/7, -7/3, -3/8]" ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_non_negative_rationals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_q::exhaustive::exhaustive_non_negative_rationals; #[test] fn test_exhaustive_non_negative_rationals() { assert_eq!( exhaustive_non_negative_rationals() .take(20) .collect_vec() .to_debug_string(), "[0, 1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, 5/3, 3/4, 4, 1/5, 5/4, 4/7, \ 7/3]" ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_nonzero_rationals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_q::exhaustive::exhaustive_nonzero_rationals; #[test] fn test_exhaustive_nonzero_rationals() { assert_eq!( exhaustive_nonzero_rationals() .take(20) .collect_vec() .to_debug_string(), "[1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, 3/2, -3/2, 2/3, -2/3, 3, -3, 1/4, -1/4, 4/3, -4/3, \ 3/5, -3/5]" ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_positive_rationals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_q::exhaustive::exhaustive_positive_rationals; #[test] fn test_exhaustive_positive_rationals() { assert_eq!( exhaustive_positive_rationals() .take(20) .collect_vec() .to_debug_string(), "[1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, 5/3, 3/4, 4, 1/5, 5/4, 4/7, 7/3, \ 3/8]" ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rational_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::strings::ToDebugString; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rational_inclusive_range; use std::str::FromStr; fn exhaustive_rational_inclusive_range_helper(a: &str, b: &str, values: &str) { let a = Rational::from_str(a).unwrap(); let b = Rational::from_str(b).unwrap(); let xs = exhaustive_rational_inclusive_range(a, b) .take(50) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_rational_inclusive_range() { exhaustive_rational_inclusive_range_helper( "0", "2", "[0, 1/2, 1, 1/3, 2, 3/2, 2/3, 1/6, 4/3, 1/4, 5/3, 1/5, 3/4, 2/5, 5/4, 1/8, 7/4, 3/5, \ 4/5, 1/7, 6/5, 5/6, 7/5, 3/8, 8/5, 7/6, 9/5, 2/7, 11/6, 3/7, 4/7, 1/12, 5/7, 5/8, 6/7, \ 1/9, 8/7, 7/8, 9/7, 1/10, 10/7, 9/8, 11/7, 2/9, 12/7, 11/8, 13/7, 1/11, 13/8, 4/9]", ); exhaustive_rational_inclusive_range_helper( "1/3", "1/2", "[1/2, 1/3, 2/5, 3/8, 3/7, 4/9, 4/11, 5/14, 5/11, 5/12, 5/13, 7/15, 6/13, 7/16, 6/17, \ 8/21, 7/17, 7/18, 8/17, 7/19, 8/19, 7/20, 9/19, 9/22, 9/20, 10/21, 8/23, 9/25, 9/23, \ 11/24, 10/23, 11/28, 11/23, 11/25, 12/25, 10/27, 9/26, 11/27, 11/26, 10/29, 13/27, 13/28, \ 11/29, 11/31, 12/29, 11/30, 13/29, 13/33, 14/29, 13/30]", ); exhaustive_rational_inclusive_range_helper( "99/100", "101/100", "[1, 99/100, 101/100, 101/102, 100/101, 103/102, 102/101, 103/104, 102/103, 105/104, \ 104/103, 104/105, 106/105, 105/106, 107/106, 109/110, 106/107, 107/108, 108/107, 108/109, \ 109/108, 110/109, 111/110, 112/113, 110/111, 111/112, 112/111, 114/113, 113/112, 113/114, \ 115/114, 118/119, 114/115, 115/116, 116/115, 116/117, 117/116, 118/117, 117/118, 120/121, \ 119/118, 120/119, 119/120, 121/122, 121/120, 122/121, 123/122, 125/126, 122/123, 123/124]", ); exhaustive_rational_inclusive_range_helper( "268876667/98914198", "245850922/78256779", "[3, 11/4, 14/5, 20/7, 17/6, 23/8, 25/8, 30/11, 25/9, 29/10, 26/9, 31/11, 28/9, 31/10, \ 32/11, 41/15, 34/11, 35/12, 37/12, 39/14, 36/13, 41/14, 37/13, 45/16, 38/13, 43/14, \ 40/13, 43/15, 44/15, 47/16, 46/15, 57/20, 47/15, 49/16, 47/17, 52/19, 48/17, 49/18, \ 49/17, 59/20, 50/17, 53/18, 52/17, 53/19, 53/17, 55/18, 54/19, 63/23, 55/19, 61/20]", ); exhaustive_rational_inclusive_range_helper( "-2", "0", "[0, -1/2, -1, -1/3, -2, -3/2, -2/3, -1/6, -4/3, -1/4, -5/3, -1/5, -3/4, -2/5, -5/4, \ -1/8, -7/4, -3/5, -4/5, -1/7, -6/5, -5/6, -7/5, -3/8, -8/5, -7/6, -9/5, -2/7, -11/6, \ -3/7, -4/7, -1/12, -5/7, -5/8, -6/7, -1/9, -8/7, -7/8, -9/7, -1/10, -10/7, -9/8, -11/7, \ -2/9, -12/7, -11/8, -13/7, -1/11, -13/8, -4/9]", ); exhaustive_rational_inclusive_range_helper( "-1/2", "-1/3", "[-1/2, -1/3, -2/5, -3/8, -3/7, -4/9, -4/11, -5/14, -5/11, -5/12, -5/13, -7/15, -6/13, \ -7/16, -6/17, -8/21, -7/17, -7/18, -8/17, -7/19, -8/19, -7/20, -9/19, -9/22, -9/20, \ -10/21, -8/23, -9/25, -9/23, -11/24, -10/23, -11/28, -11/23, -11/25, -12/25, -10/27, \ -9/26, -11/27, -11/26, -10/29, -13/27, -13/28, -11/29, -11/31, -12/29, -11/30, -13/29, \ -13/33, -14/29, -13/30]", ); exhaustive_rational_inclusive_range_helper( "-101/100", "-99/100", "[-1, -99/100, -101/100, -101/102, -100/101, -103/102, -102/101, -103/104, -102/103, \ -105/104, -104/103, -104/105, -106/105, -105/106, -107/106, -109/110, -106/107, -107/108, \ -108/107, -108/109, -109/108, -110/109, -111/110, -112/113, -110/111, -111/112, -112/111, \ -114/113, -113/112, -113/114, -115/114, -118/119, -114/115, -115/116, -116/115, -116/117, \ -117/116, -118/117, -117/118, -120/121, -119/118, -120/119, -119/120, -121/122, -121/120, \ -122/121, -123/122, -125/126, -122/123, -123/124]", ); exhaustive_rational_inclusive_range_helper( "-245850922/78256779", "-268876667/98914198", "[-3, -11/4, -14/5, -20/7, -17/6, -23/8, -25/8, -30/11, -25/9, -29/10, -26/9, -31/11, \ -28/9, -31/10, -32/11, -41/15, -34/11, -35/12, -37/12, -39/14, -36/13, -41/14, -37/13, \ -45/16, -38/13, -43/14, -40/13, -43/15, -44/15, -47/16, -46/15, -57/20, -47/15, -49/16, \ -47/17, -52/19, -48/17, -49/18, -49/17, -59/20, -50/17, -53/18, -52/17, -53/19, -53/17, \ -55/18, -54/19, -63/23, -55/19, -61/20]", ); exhaustive_rational_inclusive_range_helper( "-2", "3", "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3/2, 2/3, 5/2, 1/6, -2/3, -1/4, \ 4/3, 1/5, -4/3, 3/4, 5/3, -1/6, -5/3, -3/4, 7/3, -1/5, 8/3, 5/4, -5/4, 1/9, 7/4, 2/5, \ -7/4, 5/6, 9/4, -2/5, 11/4, 1/7, 3/5, -5/6, -3/5, -1/7, 4/5, 7/6, -4/5, -1/9, 6/5, -7/6]", ); exhaustive_rational_inclusive_range_helper( "-1/2", "1/3", "[0, -1/2, 1/3, 1/5, -1/3, 1/4, -1/4, 1/7, -1/5, 1/6, -2/5, -1/7, -1/6, 2/7, -2/7, 1/11, \ -3/7, 1/8, -1/8, 1/10, -3/8, 1/9, -1/9, 1/12, 2/9, -1/10, -2/9, -1/11, -4/9, 3/10, -3/10, \ 1/15, 2/11, -1/12, -2/11, 1/13, 3/11, -5/12, -3/11, 1/14, -4/11, -1/13, -5/11, -1/14, \ 2/13, 3/14, -2/13, 1/17, 3/13, -3/14]", ); exhaustive_rational_inclusive_range_helper( "-101/100", "99/100", "[0, 1/2, -1, 1/3, -1/2, -1/3, 2/3, 1/6, -2/3, 1/4, -1/4, -1/6, 3/4, 1/5, -3/4, 1/8, \ -1/5, 5/6, 2/5, 1/7, -2/5, -5/6, 3/5, -1/8, -3/5, -1/7, 4/5, 3/8, -4/5, 2/7, -2/7, 1/12, \ 3/7, -3/8, -3/7, 1/9, 4/7, 5/8, -4/7, 1/10, 5/7, -5/8, -5/7, -1/9, 6/7, 7/8, -6/7, 1/11, \ -7/8, 2/9]", ); exhaustive_rational_inclusive_range_helper( "-245850922/78256779", "268876667/98914198", "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, -3, -1/3, -3/2, 2/3, 5/2, 1/6, -5/2, -2/3, \ 4/3, 1/5, -4/3, -1/4, 5/3, -1/6, -5/3, 3/4, 7/3, -1/5, -7/3, -3/4, 8/3, 1/8, -8/3, 5/4, \ -5/4, 5/6, 7/4, 2/5, -7/4, 1/7, 9/4, -2/5, -9/4, -5/6, -11/4, 3/5, -3/5, 1/9, 4/5, 7/6]", ); exhaustive_rational_inclusive_range_helper("0", "0", "[0]"); } #[test] #[should_panic] fn exhaustive_rational_inclusive_range_fail() { exhaustive_rational_inclusive_range(Rational::ONE, Rational::ZERO); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rational_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::{One, Zero}; use malachite_base::strings::ToDebugString; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rational_range; use std::str::FromStr; fn exhaustive_rational_range_helper(a: &str, b: &str, values: &str) { let a = Rational::from_str(a).unwrap(); let b = Rational::from_str(b).unwrap(); let xs = exhaustive_rational_range(a, b) .take(50) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_rational_range() { exhaustive_rational_range_helper( "0", "2", "[0, 1/2, 1, 1/3, 3/2, 2/3, 4/3, 1/6, 5/3, 1/4, 3/4, 5/6, 5/4, 1/5, 7/4, 1/8, 2/5, 7/6, \ 3/5, 1/7, 4/5, 11/6, 6/5, 3/8, 7/5, 2/7, 8/5, 5/8, 9/5, 3/7, 4/7, 1/12, 5/7, 7/8, 6/7, \ 1/9, 8/7, 9/8, 9/7, 1/10, 10/7, 11/8, 11/7, 2/9, 12/7, 13/8, 13/7, 1/11, 15/8, 4/9]", ); exhaustive_rational_range_helper( "1/3", "1/2", "[1/3, 2/5, 3/7, 4/9, 3/8, 4/11, 5/11, 5/14, 5/12, 5/13, 6/13, 7/15, 7/16, 6/17, 7/17, \ 8/21, 8/17, 7/18, 7/19, 10/21, 8/19, 7/20, 9/19, 9/22, 9/20, 8/23, 9/23, 9/25, 10/23, \ 11/24, 11/23, 11/28, 11/25, 9/26, 12/25, 10/27, 11/26, 11/27, 13/27, 11/30, 13/28, 10/29, \ 11/29, 11/31, 12/29, 13/30, 13/29, 13/33, 14/29, 12/31]", ); exhaustive_rational_range_helper( "99/100", "101/100", "[1, 99/100, 100/101, 102/103, 102/101, 101/102, 103/102, 104/105, 104/103, 103/104, \ 105/104, 105/106, 106/105, 107/106, 106/107, 110/111, 108/107, 107/108, 109/108, 109/110, \ 108/109, 111/110, 110/109, 111/112, 112/111, 113/112, 112/113, 114/115, 114/113, 113/114, \ 115/114, 118/119, 116/115, 115/116, 117/116, 117/118, 116/117, 119/118, 118/117, 119/120, \ 120/119, 121/120, 120/121, 122/123, 122/121, 121/122, 123/122, 125/126, 124/123, 123/124]", ); exhaustive_rational_range_helper( "268876667/98914198", "245850922/78256779", "[3, 11/4, 14/5, 20/7, 17/6, 23/8, 25/8, 30/11, 25/9, 29/10, 26/9, 31/11, 28/9, 31/10, \ 32/11, 41/15, 34/11, 35/12, 37/12, 39/14, 36/13, 41/14, 37/13, 45/16, 38/13, 43/14, \ 40/13, 43/15, 44/15, 47/16, 46/15, 57/20, 47/15, 49/16, 47/17, 52/19, 48/17, 49/18, \ 49/17, 59/20, 50/17, 53/18, 52/17, 53/19, 53/17, 55/18, 54/19, 63/23, 55/19, 61/20]", ); exhaustive_rational_range_helper( "-2", "0", "[-1, -1/2, -2, -1/3, -3/2, -2/3, -4/3, -1/6, -5/3, -1/4, -3/4, -5/6, -5/4, -1/5, -7/4, \ -1/8, -2/5, -7/6, -3/5, -1/7, -4/5, -11/6, -6/5, -3/8, -7/5, -2/7, -8/5, -5/8, -9/5, \ -3/7, -4/7, -1/12, -5/7, -7/8, -6/7, -1/9, -8/7, -9/8, -9/7, -1/10, -10/7, -11/8, -11/7, \ -2/9, -12/7, -13/8, -13/7, -1/11, -15/8, -4/9]", ); exhaustive_rational_range_helper( "-1/2", "-1/3", "[-1/2, -2/5, -3/7, -4/9, -3/8, -4/11, -5/11, -5/14, -5/12, -5/13, -6/13, -7/15, -7/16, \ -6/17, -7/17, -8/21, -8/17, -7/18, -7/19, -10/21, -8/19, -7/20, -9/19, -9/22, -9/20, \ -8/23, -9/23, -9/25, -10/23, -11/24, -11/23, -11/28, -11/25, -9/26, -12/25, -10/27, \ -11/26, -11/27, -13/27, -11/30, -13/28, -10/29, -11/29, -11/31, -12/29, -13/30, -13/29, \ -13/33, -14/29, -12/31]", ); exhaustive_rational_range_helper( "-101/100", "-99/100", "[-1, -101/100, -100/101, -102/103, -102/101, -101/102, -103/102, -104/105, -104/103, \ -103/104, -105/104, -105/106, -106/105, -107/106, -106/107, -110/111, -108/107, -107/108, \ -109/108, -109/110, -108/109, -111/110, -110/109, -111/112, -112/111, -113/112, -112/113, \ -114/115, -114/113, -113/114, -115/114, -118/119, -116/115, -115/116, -117/116, -117/118, \ -116/117, -119/118, -118/117, -119/120, -120/119, -121/120, -120/121, -122/123, -122/121, \ -121/122, -123/122, -125/126, -124/123, -123/124]", ); exhaustive_rational_range_helper( "-245850922/78256779", "-268876667/98914198", "[-3, -11/4, -14/5, -20/7, -17/6, -23/8, -25/8, -30/11, -25/9, -29/10, -26/9, -31/11, \ -28/9, -31/10, -32/11, -41/15, -34/11, -35/12, -37/12, -39/14, -36/13, -41/14, -37/13, \ -45/16, -38/13, -43/14, -40/13, -43/15, -44/15, -47/16, -46/15, -57/20, -47/15, -49/16, \ -47/17, -52/19, -48/17, -49/18, -49/17, -59/20, -50/17, -53/18, -52/17, -53/19, -53/17, \ -55/18, -54/19, -63/23, -55/19, -61/20]", ); exhaustive_rational_range_helper( "-2", "3", "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, -3/2, -1/4, 5/2, -1/3, 2/3, 1/7, -2/3, 3/4, \ 4/3, 1/5, -4/3, -3/4, 5/3, 1/6, -5/3, 5/4, 7/3, -1/5, 8/3, -5/4, 7/4, 1/9, -7/4, 2/5, \ 9/4, -1/6, 11/4, -2/5, 3/5, 1/8, -3/5, 5/6, 4/5, -1/7, -4/5, -5/6, 6/5, -1/9, -6/5, 7/6]", ); exhaustive_rational_range_helper( "-1/2", "1/3", "[0, -1/2, -1/3, 1/5, 1/4, -1/5, -1/4, 1/7, -2/5, 1/6, -1/6, 1/8, -1/7, -1/8, 2/7, 1/11, \ -2/7, -3/8, -3/7, 1/9, -1/9, 1/10, 2/9, 1/12, -2/9, -1/10, -4/9, -1/11, 3/10, 2/11, \ -3/10, 1/15, -2/11, -1/12, 3/11, 1/13, -3/11, -5/12, -4/11, 1/14, -5/11, -1/13, 2/13, \ -1/15, -2/13, -1/14, 3/13, 1/17, -3/13, 3/14]", ); exhaustive_rational_range_helper( "-101/100", "99/100", "[0, 1/2, -1, 1/3, -1/2, -1/3, 2/3, 1/6, -2/3, 1/4, -1/4, -1/6, 3/4, 1/5, -3/4, 1/8, \ -1/5, 5/6, 2/5, 1/7, -2/5, -5/6, 3/5, -1/8, -3/5, -1/7, 4/5, 3/8, -4/5, 2/7, -2/7, 1/12, \ 3/7, -3/8, -3/7, 1/9, 4/7, 5/8, -4/7, 1/10, 5/7, -5/8, -5/7, -1/9, 6/7, 7/8, -6/7, 1/11, \ -7/8, 2/9]", ); exhaustive_rational_range_helper( "-245850922/78256779", "268876667/98914198", "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, -3, -1/3, -3/2, 2/3, 5/2, 1/6, -5/2, -2/3, \ 4/3, 1/5, -4/3, -1/4, 5/3, -1/6, -5/3, 3/4, 7/3, -1/5, -7/3, -3/4, 8/3, 1/8, -8/3, 5/4, \ -5/4, 5/6, 7/4, 2/5, -7/4, 1/7, 9/4, -2/5, -9/4, -5/6, -11/4, 3/5, -3/5, 1/9, 4/5, 7/6]", ); exhaustive_rational_range_helper("0", "0", "[]"); } #[test] #[should_panic] fn exhaustive_rational_range_fail() { exhaustive_rational_range(Rational::ONE, Rational::ZERO); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rational_range_to_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rational_range_to_infinity; fn exhaustive_rational_range_to_infinity_helper(a: Rational, values: &str) { let xs = exhaustive_rational_range_to_infinity(a) .take(50) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_rational_range_to_infinity() { exhaustive_rational_range_to_infinity_helper( Rational::ZERO, "[0, 1/2, 1, 1/3, 2, 3/2, 3, 1/4, 4, 5/2, 5, 2/3, 6, 7/2, 7, 1/5, 8, 9/2, 9, 4/3, 10, \ 11/2, 11, 3/4, 12, 13/2, 13, 5/3, 14, 15/2, 15, 1/6, 16, 17/2, 17, 7/3, 18, 19/2, 19, \ 5/4, 20, 21/2, 21, 8/3, 22, 23/2, 23, 2/5, 24, 25/2]", ); exhaustive_rational_range_to_infinity_helper( Rational::from(5), "[5, 11/2, 6, 16/3, 7, 13/2, 8, 21/4, 9, 15/2, 10, 17/3, 11, 17/2, 12, 26/5, 13, 19/2, \ 14, 19/3, 15, 21/2, 16, 23/4, 17, 23/2, 18, 20/3, 19, 25/2, 20, 31/6, 21, 27/2, 22, 22/3, \ 23, 29/2, 24, 25/4, 25, 31/2, 26, 23/3, 27, 33/2, 28, 27/5, 29, 35/2]", ); exhaustive_rational_range_to_infinity_helper( Rational::from(-5), "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3, -3/2, 4, 1/5, -4, 5/2, 5, 2/3, \ -5, -5/2, 6, -1/4, 7, 7/2, 8, -2/3, 9, -7/2, 10, 1/6, 11, 9/2, 12, 4/3, 13, -9/2, 14, \ 3/4, 15, 11/2, 16, -4/3, 17, 13/2, 18, -1/5, 19, 15/2]", ); exhaustive_rational_range_to_infinity_helper( Rational::exact_from(std::f64::consts::PI), "[4, 7/2, 5, 10/3, 6, 9/2, 7, 13/4, 8, 11/2, 9, 11/3, 10, 13/2, 11, 16/5, 12, 15/2, 13, \ 13/3, 14, 17/2, 15, 15/4, 16, 19/2, 17, 14/3, 18, 21/2, 19, 19/6, 20, 23/2, 21, 16/3, 22, \ 25/2, 23, 17/4, 24, 27/2, 25, 17/3, 26, 29/2, 27, 17/5, 28, 31/2]", ); exhaustive_rational_range_to_infinity_helper( -Rational::exact_from(std::f64::consts::PI), "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3, -3/2, 4, 1/5, 5, 5/2, 6, 2/3, \ 7, -5/2, 8, -1/4, 9, 7/2, 10, -2/3, 11, 9/2, 12, 1/6, 13, 11/2, 14, 4/3, 15, 13/2, 16, \ 3/4, 17, 15/2, 18, -4/3, 19, 17/2, 20, -1/5, 21, 19/2]", ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rational_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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::num::basic::traits::Zero; use malachite_base::num::conversion::traits::ExactFrom; use malachite_base::strings::ToDebugString; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rational_range_to_negative_infinity; fn exhaustive_rational_range_to_negative_infinity_helper(a: Rational, values: &str) { let xs = exhaustive_rational_range_to_negative_infinity(a) .take(50) .collect_vec() .to_debug_string(); assert_eq!(xs, values); } #[test] fn test_exhaustive_rational_range_to_negative_infinity() { exhaustive_rational_range_to_negative_infinity_helper( Rational::ZERO, "[0, -1/2, -1, -1/3, -2, -3/2, -3, -1/4, -4, -5/2, -5, -2/3, -6, -7/2, -7, -1/5, -8, \ -9/2, -9, -4/3, -10, -11/2, -11, -3/4, -12, -13/2, -13, -5/3, -14, -15/2, -15, -1/6, \ -16, -17/2, -17, -7/3, -18, -19/2, -19, -5/4, -20, -21/2, -21, -8/3, -22, -23/2, -23, \ -2/5, -24, -25/2]", ); exhaustive_rational_range_to_negative_infinity_helper( Rational::from(5), "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3, -3/2, 4, 1/5, -4, 5/2, 5, 2/3, \ -5, -5/2, -6, -1/4, -7, 7/2, -8, -2/3, -9, -7/2, -10, 1/6, -11, 9/2, -12, 4/3, -13, -9/2, \ -14, 3/4, -15, -11/2, -16, -4/3, -17, -13/2, -18, -1/5, -19, -15/2]", ); exhaustive_rational_range_to_negative_infinity_helper( Rational::from(-5), "[-5, -11/2, -6, -16/3, -7, -13/2, -8, -21/4, -9, -15/2, -10, -17/3, -11, -17/2, -12, \ -26/5, -13, -19/2, -14, -19/3, -15, -21/2, -16, -23/4, -17, -23/2, -18, -20/3, -19, \ -25/2, -20, -31/6, -21, -27/2, -22, -22/3, -23, -29/2, -24, -25/4, -25, -31/2, -26, \ -23/3, -27, -33/2, -28, -27/5, -29, -35/2]", ); exhaustive_rational_range_to_negative_infinity_helper( Rational::exact_from(std::f64::consts::PI), "[0, 1/2, 1, 1/3, -1, -1/2, 2, 1/4, -2, 3/2, 3, -1/3, -3, -3/2, -4, 1/5, -5, 5/2, -6, \ 2/3, -7, -5/2, -8, -1/4, -9, -7/2, -10, -2/3, -11, -9/2, -12, 1/6, -13, -11/2, -14, 4/3, \ -15, -13/2, -16, 3/4, -17, -15/2, -18, -4/3, -19, -17/2, -20, -1/5, -21, -19/2]", ); exhaustive_rational_range_to_negative_infinity_helper( -Rational::exact_from(std::f64::consts::PI), "[-4, -7/2, -5, -10/3, -6, -9/2, -7, -13/4, -8, -11/2, -9, -11/3, -10, -13/2, -11, -16/5, \ -12, -15/2, -13, -13/3, -14, -17/2, -15, -15/4, -16, -19/2, -17, -14/3, -18, -21/2, -19, \ -19/6, -20, -23/2, -21, -16/3, -22, -25/2, -23, -17/4, -24, -27/2, -25, -17/3, -26, \ -29/2, -27, -17/5, -28, -31/2]", ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rationals.rs ================================================ // Copyright © 2026 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::strings::ToDebugString; use malachite_q::exhaustive::exhaustive_rationals; #[test] fn test_exhaustive_rationals() { assert_eq!( exhaustive_rationals() .take(20) .collect_vec() .to_debug_string(), "[0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, 3/2, -3/2, 2/3, -2/3, 3, -3, 1/4, -1/4, 4/3, \ -4/3, 3/5]" ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rationals_with_denominator_inclusive_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::One; use malachite_base::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rationals_with_denominator_inclusive_range; use std::str::FromStr; fn helper(d: &str, a: &str, b: &str, out: &str) { assert_eq!( exhaustive_rationals_with_denominator_inclusive_range( Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap() ) .collect_vec() .to_debug_string(), out ); } #[test] fn test_exhaustive_rationals_with_denominator_inclusive_range() { helper("1", "1", "1", "[1]"); helper("2", "1", "1", "[]"); helper("3", "1", "1", "[]"); helper("4", "1", "1", "[]"); helper("5", "1", "1", "[]"); helper("6", "1", "1", "[]"); helper("1", "0", "1", "[0, 1]"); helper("2", "0", "1", "[1/2]"); helper("3", "0", "1", "[1/3, 2/3]"); helper("4", "0", "1", "[1/4, 3/4]"); helper("5", "0", "1", "[1/5, 2/5, 3/5, 4/5]"); helper("6", "0", "1", "[1/6, 5/6]"); helper("1", "0", "1/2", "[0]"); helper("2", "0", "1/2", "[1/2]"); helper("3", "0", "1/2", "[1/3]"); helper("4", "0", "1/2", "[1/4]"); helper("5", "0", "1/2", "[1/5, 2/5]"); helper("6", "0", "1/2", "[1/6]"); helper("1", "1/3", "1/2", "[]"); helper("2", "1/3", "1/2", "[1/2]"); helper("3", "1/3", "1/2", "[1/3]"); helper("4", "1/3", "1/2", "[]"); helper("5", "1/3", "1/2", "[2/5]"); helper("6", "1/3", "1/2", "[]"); helper("1", "-1/2", "-1/3", "[]"); helper("2", "-1/2", "-1/3", "[-1/2]"); helper("3", "-1/2", "-1/3", "[-1/3]"); helper("4", "-1/2", "-1/3", "[]"); helper("5", "-1/2", "-1/3", "[-2/5]"); helper("6", "-1/2", "-1/3", "[]"); helper("1", "-1/2", "1/3", "[0]"); helper("2", "-1/2", "1/3", "[-1/2]"); helper("3", "-1/2", "1/3", "[1/3, -1/3]"); helper("4", "-1/2", "1/3", "[1/4, -1/4]"); helper("5", "-1/2", "1/3", "[1/5, -1/5, -2/5]"); helper("6", "-1/2", "1/3", "[1/6, -1/6]"); // [e, π), roughly helper("1", "268876667/98914198", "245850922/78256779", "[3]"); helper("2", "268876667/98914198", "245850922/78256779", "[]"); helper("3", "268876667/98914198", "245850922/78256779", "[]"); helper("4", "268876667/98914198", "245850922/78256779", "[11/4]"); helper("5", "268876667/98914198", "245850922/78256779", "[14/5]"); helper("6", "268876667/98914198", "245850922/78256779", "[17/6]"); helper("7", "268876667/98914198", "245850922/78256779", "[20/7]"); helper( "8", "268876667/98914198", "245850922/78256779", "[23/8, 25/8]", ); helper( "9", "268876667/98914198", "245850922/78256779", "[25/9, 26/9, 28/9]", ); helper( "10", "268876667/98914198", "245850922/78256779", "[29/10, 31/10]", ); helper( "100", "268876667/98914198", "245850922/78256779", "[273/100, 277/100, 279/100, 281/100, 283/100, 287/100, 289/100, 291/100, 293/100, \ 297/100, 299/100, 301/100, 303/100, 307/100, 309/100, 311/100, 313/100]", ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_inclusive_range_fail_1() { exhaustive_rationals_with_denominator_inclusive_range( Natural::ZERO, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(1u32, 2), ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_inclusive_range_fail_2() { exhaustive_rationals_with_denominator_inclusive_range( Natural::ONE, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rationals_with_denominator_range.rs ================================================ // Copyright © 2026 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::num::basic::traits::One; use malachite_base::num::basic::traits::Zero; use malachite_base::strings::ToDebugString; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range; use std::str::FromStr; fn helper(d: &str, a: &str, b: &str, out: &str) { assert_eq!( exhaustive_rationals_with_denominator_range( Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap() ) .collect_vec() .to_debug_string(), out ); } #[test] fn test_exhaustive_rationals_with_denominator_range() { helper("1", "0", "1", "[0]"); helper("2", "0", "1", "[1/2]"); helper("3", "0", "1", "[1/3, 2/3]"); helper("4", "0", "1", "[1/4, 3/4]"); helper("5", "0", "1", "[1/5, 2/5, 3/5, 4/5]"); helper("6", "0", "1", "[1/6, 5/6]"); helper("1", "0", "1/2", "[0]"); helper("2", "0", "1/2", "[]"); helper("3", "0", "1/2", "[1/3]"); helper("4", "0", "1/2", "[1/4]"); helper("5", "0", "1/2", "[1/5, 2/5]"); helper("6", "0", "1/2", "[1/6]"); helper("1", "1/3", "1/2", "[]"); helper("2", "1/3", "1/2", "[]"); helper("3", "1/3", "1/2", "[1/3]"); helper("4", "1/3", "1/2", "[]"); helper("5", "1/3", "1/2", "[2/5]"); helper("6", "1/3", "1/2", "[]"); helper("1", "-1/2", "-1/3", "[]"); helper("2", "-1/2", "-1/3", "[-1/2]"); helper("3", "-1/2", "-1/3", "[]"); helper("4", "-1/2", "-1/3", "[]"); helper("5", "-1/2", "-1/3", "[-2/5]"); helper("6", "-1/2", "-1/3", "[]"); helper("1", "-1/2", "1/3", "[0]"); helper("2", "-1/2", "1/3", "[-1/2]"); helper("3", "-1/2", "1/3", "[-1/3]"); helper("4", "-1/2", "1/3", "[1/4, -1/4]"); helper("5", "-1/2", "1/3", "[1/5, -1/5, -2/5]"); helper("6", "-1/2", "1/3", "[1/6, -1/6]"); // [e, π), roughly helper("1", "268876667/98914198", "245850922/78256779", "[3]"); helper("2", "268876667/98914198", "245850922/78256779", "[]"); helper("3", "268876667/98914198", "245850922/78256779", "[]"); helper("4", "268876667/98914198", "245850922/78256779", "[11/4]"); helper("5", "268876667/98914198", "245850922/78256779", "[14/5]"); helper("6", "268876667/98914198", "245850922/78256779", "[17/6]"); helper("7", "268876667/98914198", "245850922/78256779", "[20/7]"); helper( "8", "268876667/98914198", "245850922/78256779", "[23/8, 25/8]", ); helper( "9", "268876667/98914198", "245850922/78256779", "[25/9, 26/9, 28/9]", ); helper( "10", "268876667/98914198", "245850922/78256779", "[29/10, 31/10]", ); helper( "100", "268876667/98914198", "245850922/78256779", "[273/100, 277/100, 279/100, 281/100, 283/100, 287/100, 289/100, 291/100, 293/100, \ 297/100, 299/100, 301/100, 303/100, 307/100, 309/100, 311/100, 313/100]", ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_range_fail_1() { exhaustive_rationals_with_denominator_range( Natural::ZERO, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(1u32, 2), ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_range_fail_2() { exhaustive_rationals_with_denominator_range( Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(1u32, 3), ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_range_fail_3() { exhaustive_rationals_with_denominator_range( Natural::ONE, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rationals_with_denominator_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::prefix_to_string; use malachite_base::num::basic::traits::Zero; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range_to_infinity; use std::str::FromStr; fn helper(d: &str, a: &str, out: &str) { assert_eq!( prefix_to_string( exhaustive_rationals_with_denominator_range_to_infinity( Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap() ), 20 ), out ); } #[test] fn test_exhaustive_rationals_with_denominator_range_to_infinity() { helper( "1", "0", "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ...]", ); helper( "2", "0", "[1/2, 3/2, 5/2, 7/2, 9/2, 11/2, 13/2, 15/2, 17/2, 19/2, 21/2, 23/2, 25/2, 27/2, 29/2, \ 31/2, 33/2, 35/2, 37/2, 39/2, ...]", ); helper( "3", "0", "[1/3, 2/3, 4/3, 5/3, 7/3, 8/3, 10/3, 11/3, 13/3, 14/3, 16/3, 17/3, 19/3, 20/3, 22/3, \ 23/3, 25/3, 26/3, 28/3, 29/3, ...]", ); helper( "4", "0", "[1/4, 3/4, 5/4, 7/4, 9/4, 11/4, 13/4, 15/4, 17/4, 19/4, 21/4, 23/4, 25/4, 27/4, 29/4, \ 31/4, 33/4, 35/4, 37/4, 39/4, ...]", ); helper( "5", "0", "[1/5, 2/5, 3/5, 4/5, 6/5, 7/5, 8/5, 9/5, 11/5, 12/5, 13/5, 14/5, 16/5, 17/5, 18/5, 19/5, \ 21/5, 22/5, 23/5, 24/5, ...]", ); helper( "6", "0", "[1/6, 5/6, 7/6, 11/6, 13/6, 17/6, 19/6, 23/6, 25/6, 29/6, 31/6, 35/6, 37/6, 41/6, 43/6, \ 47/6, 49/6, 53/6, 55/6, 59/6, ...]", ); helper( "1", "1/2", "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...]", ); helper( "2", "1/2", "[1/2, 3/2, 5/2, 7/2, 9/2, 11/2, 13/2, 15/2, 17/2, 19/2, 21/2, 23/2, 25/2, 27/2, 29/2, \ 31/2, 33/2, 35/2, 37/2, 39/2, ...]", ); helper( "3", "1/2", "[2/3, 4/3, 5/3, 7/3, 8/3, 10/3, 11/3, 13/3, 14/3, 16/3, 17/3, 19/3, 20/3, 22/3, 23/3, \ 25/3, 26/3, 28/3, 29/3, 31/3, ...]", ); helper( "4", "1/2", "[3/4, 5/4, 7/4, 9/4, 11/4, 13/4, 15/4, 17/4, 19/4, 21/4, 23/4, 25/4, 27/4, 29/4, 31/4, \ 33/4, 35/4, 37/4, 39/4, 41/4, ...]", ); helper( "5", "1/2", "[3/5, 4/5, 6/5, 7/5, 8/5, 9/5, 11/5, 12/5, 13/5, 14/5, 16/5, 17/5, 18/5, 19/5, 21/5, \ 22/5, 23/5, 24/5, 26/5, 27/5, ...]", ); helper( "6", "1/2", "[5/6, 7/6, 11/6, 13/6, 17/6, 19/6, 23/6, 25/6, 29/6, 31/6, 35/6, 37/6, 41/6, 43/6, 47/6, \ 49/6, 53/6, 55/6, 59/6, 61/6, ...]", ); helper( "1", "245850922/78256779", "[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, ...]", ); helper( "2", "245850922/78256779", "[7/2, 9/2, 11/2, 13/2, 15/2, 17/2, 19/2, 21/2, 23/2, 25/2, 27/2, 29/2, 31/2, 33/2, 35/2, \ 37/2, 39/2, 41/2, 43/2, 45/2, ...]", ); helper( "3", "245850922/78256779", "[10/3, 11/3, 13/3, 14/3, 16/3, 17/3, 19/3, 20/3, 22/3, 23/3, 25/3, 26/3, 28/3, 29/3, \ 31/3, 32/3, 34/3, 35/3, 37/3, 38/3, ...]", ); helper( "4", "245850922/78256779", "[13/4, 15/4, 17/4, 19/4, 21/4, 23/4, 25/4, 27/4, 29/4, 31/4, 33/4, 35/4, 37/4, 39/4, \ 41/4, 43/4, 45/4, 47/4, 49/4, 51/4, ...]", ); helper( "5", "245850922/78256779", "[16/5, 17/5, 18/5, 19/5, 21/5, 22/5, 23/5, 24/5, 26/5, 27/5, 28/5, 29/5, 31/5, 32/5, \ 33/5, 34/5, 36/5, 37/5, 38/5, 39/5, ...]", ); helper( "6", "245850922/78256779", "[19/6, 23/6, 25/6, 29/6, 31/6, 35/6, 37/6, 41/6, 43/6, 47/6, 49/6, 53/6, 55/6, 59/6, \ 61/6, 65/6, 67/6, 71/6, 73/6, 77/6, ...]", ); helper( "1", "-245850922/78256779", "[0, 1, -1, 2, -2, 3, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, ...]", ); helper( "2", "-245850922/78256779", "[1/2, -1/2, 3/2, -3/2, 5/2, -5/2, 7/2, 9/2, 11/2, 13/2, 15/2, 17/2, 19/2, 21/2, 23/2, \ 25/2, 27/2, 29/2, 31/2, 33/2, ...]", ); helper( "3", "-245850922/78256779", "[1/3, -1/3, 2/3, -2/3, 4/3, -4/3, 5/3, -5/3, 7/3, -7/3, 8/3, -8/3, 10/3, 11/3, 13/3, \ 14/3, 16/3, 17/3, 19/3, 20/3, ...]", ); helper( "4", "-245850922/78256779", "[1/4, -1/4, 3/4, -3/4, 5/4, -5/4, 7/4, -7/4, 9/4, -9/4, 11/4, -11/4, 13/4, 15/4, 17/4, \ 19/4, 21/4, 23/4, 25/4, 27/4, ...]", ); helper( "5", "-245850922/78256779", "[1/5, -1/5, 2/5, -2/5, 3/5, -3/5, 4/5, -4/5, 6/5, -6/5, 7/5, -7/5, 8/5, -8/5, 9/5, -9/5, \ 11/5, -11/5, 12/5, -12/5, ...]", ); helper( "6", "-245850922/78256779", "[1/6, -1/6, 5/6, -5/6, 7/6, -7/6, 11/6, -11/6, 13/6, -13/6, 17/6, -17/6, 19/6, 23/6, \ 25/6, 29/6, 31/6, 35/6, 37/6, 41/6, ...]", ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_range_to_infinity_fail() { exhaustive_rationals_with_denominator_range_to_infinity( Natural::ZERO, Rational::from_unsigneds(1u32, 3), ); } ================================================ FILE: malachite-q/tests/exhaustive/exhaustive_rationals_with_denominator_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::iterators::prefix_to_string; use malachite_base::num::basic::traits::Zero; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::exhaustive::exhaustive_rationals_with_denominator_range_to_negative_infinity; use std::str::FromStr; fn helper(d: &str, a: &str, out: &str) { assert_eq!( prefix_to_string( exhaustive_rationals_with_denominator_range_to_negative_infinity( Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap() ), 20 ), out ); } #[test] fn test_exhaustive_rationals_with_denominator_range_to_negative_infinity() { helper( "1", "0", "[0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, \ -19, ...]", ); helper( "2", "0", "[-1/2, -3/2, -5/2, -7/2, -9/2, -11/2, -13/2, -15/2, -17/2, -19/2, -21/2, -23/2, -25/2, \ -27/2, -29/2, -31/2, -33/2, -35/2, -37/2, -39/2, ...]", ); helper( "3", "0", "[-1/3, -2/3, -4/3, -5/3, -7/3, -8/3, -10/3, -11/3, -13/3, -14/3, -16/3, -17/3, -19/3, \ -20/3, -22/3, -23/3, -25/3, -26/3, -28/3, -29/3, ...]", ); helper( "4", "0", "[-1/4, -3/4, -5/4, -7/4, -9/4, -11/4, -13/4, -15/4, -17/4, -19/4, -21/4, -23/4, -25/4, \ -27/4, -29/4, -31/4, -33/4, -35/4, -37/4, -39/4, ...]", ); helper( "5", "0", "[-1/5, -2/5, -3/5, -4/5, -6/5, -7/5, -8/5, -9/5, -11/5, -12/5, -13/5, -14/5, -16/5, \ -17/5, -18/5, -19/5, -21/5, -22/5, -23/5, -24/5, ...]", ); helper( "6", "0", "[-1/6, -5/6, -7/6, -11/6, -13/6, -17/6, -19/6, -23/6, -25/6, -29/6, -31/6, -35/6, -37/6, \ -41/6, -43/6, -47/6, -49/6, -53/6, -55/6, -59/6, ...]", ); helper( "1", "1/2", "[0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, \ -19, ...]", ); helper( "2", "1/2", "[1/2, -1/2, -3/2, -5/2, -7/2, -9/2, -11/2, -13/2, -15/2, -17/2, -19/2, -21/2, -23/2, \ -25/2, -27/2, -29/2, -31/2, -33/2, -35/2, -37/2, ...]", ); helper( "3", "1/2", "[1/3, -1/3, -2/3, -4/3, -5/3, -7/3, -8/3, -10/3, -11/3, -13/3, -14/3, -16/3, -17/3, \ -19/3, -20/3, -22/3, -23/3, -25/3, -26/3, -28/3, ...]", ); helper( "4", "1/2", "[1/4, -1/4, -3/4, -5/4, -7/4, -9/4, -11/4, -13/4, -15/4, -17/4, -19/4, -21/4, -23/4, \ -25/4, -27/4, -29/4, -31/4, -33/4, -35/4, -37/4, ...]", ); helper( "5", "1/2", "[1/5, -1/5, 2/5, -2/5, -3/5, -4/5, -6/5, -7/5, -8/5, -9/5, -11/5, -12/5, -13/5, -14/5, \ -16/5, -17/5, -18/5, -19/5, -21/5, -22/5, ...]", ); helper( "6", "1/2", "[1/6, -1/6, -5/6, -7/6, -11/6, -13/6, -17/6, -19/6, -23/6, -25/6, -29/6, -31/6, -35/6, \ -37/6, -41/6, -43/6, -47/6, -49/6, -53/6, -55/6, ...]", ); helper( "1", "245850922/78256779", "[0, 1, -1, 2, -2, 3, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, ...]", ); helper( "2", "245850922/78256779", "[1/2, -1/2, 3/2, -3/2, 5/2, -5/2, -7/2, -9/2, -11/2, -13/2, -15/2, -17/2, -19/2, -21/2, \ -23/2, -25/2, -27/2, -29/2, -31/2, -33/2, ...]", ); helper( "3", "245850922/78256779", "[1/3, -1/3, 2/3, -2/3, 4/3, -4/3, 5/3, -5/3, 7/3, -7/3, 8/3, -8/3, -10/3, -11/3, -13/3, \ -14/3, -16/3, -17/3, -19/3, -20/3, ...]", ); helper( "4", "245850922/78256779", "[1/4, -1/4, 3/4, -3/4, 5/4, -5/4, 7/4, -7/4, 9/4, -9/4, 11/4, -11/4, -13/4, -15/4, \ -17/4, -19/4, -21/4, -23/4, -25/4, -27/4, ...]", ); helper( "5", "245850922/78256779", "[1/5, -1/5, 2/5, -2/5, 3/5, -3/5, 4/5, -4/5, 6/5, -6/5, 7/5, -7/5, 8/5, -8/5, 9/5, -9/5, \ 11/5, -11/5, 12/5, -12/5, ...]", ); helper( "6", "245850922/78256779", "[1/6, -1/6, 5/6, -5/6, 7/6, -7/6, 11/6, -11/6, 13/6, -13/6, 17/6, -17/6, -19/6, -23/6, \ -25/6, -29/6, -31/6, -35/6, -37/6, -41/6, ...]", ); helper( "1", "-245850922/78256779", "[-4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, \ -22, -23, ...]", ); helper( "2", "-245850922/78256779", "[-7/2, -9/2, -11/2, -13/2, -15/2, -17/2, -19/2, -21/2, -23/2, -25/2, -27/2, -29/2, \ -31/2, -33/2, -35/2, -37/2, -39/2, -41/2, -43/2, -45/2, ...]", ); helper( "3", "-245850922/78256779", "[-10/3, -11/3, -13/3, -14/3, -16/3, -17/3, -19/3, -20/3, -22/3, -23/3, -25/3, -26/3, \ -28/3, -29/3, -31/3, -32/3, -34/3, -35/3, -37/3, -38/3, ...]", ); helper( "4", "-245850922/78256779", "[-13/4, -15/4, -17/4, -19/4, -21/4, -23/4, -25/4, -27/4, -29/4, -31/4, -33/4, -35/4, \ -37/4, -39/4, -41/4, -43/4, -45/4, -47/4, -49/4, -51/4, ...]", ); helper( "5", "-245850922/78256779", "[-16/5, -17/5, -18/5, -19/5, -21/5, -22/5, -23/5, -24/5, -26/5, -27/5, -28/5, -29/5, \ -31/5, -32/5, -33/5, -34/5, -36/5, -37/5, -38/5, -39/5, ...]", ); helper( "6", "-245850922/78256779", "[-19/6, -23/6, -25/6, -29/6, -31/6, -35/6, -37/6, -41/6, -43/6, -47/6, -49/6, -53/6, \ -55/6, -59/6, -61/6, -65/6, -67/6, -71/6, -73/6, -77/6, ...]", ); } #[test] #[should_panic] fn exhaustive_rationals_with_denominator_range_to_negative_infinity_fail() { exhaustive_rationals_with_denominator_range_to_negative_infinity( Natural::ZERO, Rational::from_unsigneds(1u32, 3), ); } ================================================ FILE: malachite-q/tests/lib.rs ================================================ // Copyright © 2026 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 . #![allow( unstable_name_collisions, clippy::bool_assert_comparison, clippy::assertions_on_constants, clippy::cognitive_complexity, clippy::excessive_precision, clippy::many_single_char_names, clippy::range_plus_one, clippy::suspicious_arithmetic_impl, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::float_cmp, clippy::type_complexity )] #![warn( clippy::cast_lossless, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::large_digit_groups, clippy::manual_filter_map, clippy::manual_find_map, clippy::map_flatten, clippy::map_unwrap_or, clippy::match_same_arms, clippy::missing_const_for_fn, clippy::mut_mut, clippy::needless_borrow, clippy::needless_continue, clippy::needless_pass_by_value, clippy::option_if_let_else, clippy::print_stdout, clippy::redundant_closure_for_method_calls, clippy::single_match_else, clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, clippy::unused_self, clippy::if_not_else, clippy::manual_assert, clippy::range_plus_one, clippy::redundant_else, clippy::semicolon_if_nothing_returned, clippy::cloned_instead_of_copied, clippy::flat_map_option, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::trivially_copy_pass_by_ref )] extern crate itertools; #[macro_use] extern crate malachite_base; extern crate malachite_nz; extern crate malachite_q; extern crate num; extern crate rug; pub mod arithmetic { pub mod abs; pub mod abs_diff; pub mod add; pub mod approximate; pub mod ceiling; pub mod denominators_in_closed_interval; pub mod div; pub mod floor; pub mod is_power_of_2; pub mod log_base; pub mod log_base_2; pub mod log_base_power_of_2; pub mod mod_op; pub mod mul; pub mod neg; pub mod next_power_of_2; pub mod pow; pub mod power_of_2; pub mod reciprocal; pub mod root; pub mod round_to_multiple; pub mod round_to_multiple_of_power_of_2; pub mod shl; pub mod shr; pub mod sign; pub mod simplest_rational_in_interval; pub mod sqrt; pub mod square; pub mod sub; } pub mod basic { pub mod constants; pub mod default; pub mod named; pub mod significant_bits; pub mod size; } pub mod comparison { pub mod cmp; pub mod cmp_abs; pub mod eq; pub mod eq_abs; pub mod eq_abs_integer; pub mod eq_abs_natural; pub mod eq_abs_primitive_float; pub mod eq_abs_primitive_int; pub mod hash; pub mod partial_cmp_abs_integer; pub mod partial_cmp_abs_natural; pub mod partial_cmp_abs_primitive_float; pub mod partial_cmp_abs_primitive_int; pub mod partial_cmp_integer; pub mod partial_cmp_natural; pub mod partial_cmp_primitive_float; pub mod partial_cmp_primitive_int; pub mod partial_eq_integer; pub mod partial_eq_natural; pub mod partial_eq_primitive_float; pub mod partial_eq_primitive_int; } pub mod conversion { pub mod clone; pub mod continued_fraction { pub mod convergents; pub mod from_continued_fraction; pub mod to_continued_fraction; } pub mod digits { #[allow(clippy::module_inception)] pub mod digits; pub mod from_digits; pub mod from_power_of_2_digits; pub mod power_of_2_digits; pub mod to_digits; pub mod to_power_of_2_digits; } pub mod from_bool; pub mod from_float_simplest; pub mod from_integer; pub mod from_natural; pub mod from_numerator_and_denominator; pub mod from_primitive_float; pub mod from_primitive_int; pub mod integer_from_rational; pub mod is_integer; pub mod mutate_numerator_or_denominator; pub mod natural_from_rational; pub mod primitive_float_from_rational; pub mod primitive_int_from_rational; pub mod sci_mantissa_and_exponent; pub mod serde; pub mod string { pub mod from_sci_string; pub mod from_string; pub mod to_sci; pub mod to_string; } pub mod to_numerator_or_denominator; } pub mod exhaustive { pub mod exhaustive_negative_rationals; pub mod exhaustive_non_negative_rationals; pub mod exhaustive_nonzero_rationals; pub mod exhaustive_positive_rationals; pub mod exhaustive_rational_inclusive_range; pub mod exhaustive_rational_range; pub mod exhaustive_rational_range_to_infinity; pub mod exhaustive_rational_range_to_negative_infinity; pub mod exhaustive_rationals; pub mod exhaustive_rationals_with_denominator_inclusive_range; pub mod exhaustive_rationals_with_denominator_range; pub mod exhaustive_rationals_with_denominator_range_to_infinity; pub mod exhaustive_rationals_with_denominator_range_to_negative_infinity; } pub mod random { pub mod random_negative_rationals; pub mod random_non_negative_rationals; pub mod random_nonzero_rationals; pub mod random_positive_rationals; pub mod random_rational_inclusive_range; pub mod random_rational_range; pub mod random_rational_range_to_infinity; pub mod random_rational_range_to_negative_infinity; pub mod random_rational_with_denominator_inclusive_range; pub mod random_rational_with_denominator_range; pub mod random_rational_with_denominator_range_to_infinity; pub mod random_rational_with_denominator_range_to_negative_infinity; pub mod random_rationals; pub mod striped_random_negative_rationals; pub mod striped_random_non_negative_rationals; pub mod striped_random_nonzero_rationals; pub mod striped_random_positive_rationals; pub mod striped_random_rational_range_to_infinity; pub mod striped_random_rational_range_to_negative_infinity; pub mod striped_random_rationals; } ================================================ FILE: malachite-q/tests/random/random_negative_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::random_negative_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; fn random_negative_rationals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_negative_rationals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_negative_rationals() { // mean bits = 65/64 let values = &["-1"; 20]; let common_values = &[ ("-1", 969573), ("-3", 7488), ("-2", 7484), ("-1/3", 7459), ("-1/2", 7391), ("-5", 75), ("-6", 67), ("-1/7", 67), ("-2/3", 64), ("-1/5", 61), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0147365511904034), standard_deviation: NiceFloat(0.21959420511046546), skewness: NiceFloat(-8.77512842724579), excess_kurtosis: NiceFloat(133.15117857730885), }; random_negative_rationals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-1/24", "-1/30", "-1/2", "-2", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1/7", "-2", "-19", "-1", "-4", "-3", "-1/2", ]; let common_values = &[ ("-1", 284707), ("-2", 71334), ("-1/2", 71222), ("-3", 68255), ("-1/3", 68142), ("-5", 18020), ("-4", 17749), ("-1/5", 17746), ("-1/4", 17705), ("-1/6", 17245), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.527473854511467), standard_deviation: NiceFloat(439.80801149679047), skewness: NiceFloat(-309.19213173617015), excess_kurtosis: NiceFloat(131113.5392046833), }; random_negative_rationals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-11/2", "-89/27922830575", "-46627409/3788983764809694", "-8/11316951483471", "-11/1005760138411689342464923704482", "-948931/42716754", "-81013760999253680590984897748479904878392/23", "-1/97645164585502", "-1558028859598/29", "-200127331174844881647/4058622214797175252", "-155/1413", "-24470495/285805200646849943", "-18939240741294741985527157685848850947887212663091378627/3070040", "-545942890259/414324415", "-4/209925", "-128959877500520349/1134718", "-2/424578084893903", "-1956237739171878131383877", "-17054902546906498751130/7", "-782845/239707736", ]; let common_values = &[ ("-1", 1810), ("-1/2", 922), ("-2", 915), ("-3", 809), ("-1/3", 776), ("-1/4", 470), ("-4", 426), ("-1/5", 412), ("-5", 409), ("-2/3", 386), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.2380948358914507e127), standard_deviation: NiceFloat(2.2380948357494794e130), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_rationals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-515152389601430248907720412245595/443042512729", "-103663/41795133908582491293103906323025", "-71296091098068019359037078314906341733724/243288956813821163751969634165018193", "-5557920650918595/82", "-487/32461763914959248855", "-38511521798151392412656616617957654586378660839/637134", "-2330568192653124764618470467652346596061/2516", "-512663303/39317568409", "-18536901993439/4959577657266999117207", "-628/42485719907732979", "-7403291719610544/1075307073896295169983034533112645563410195", "-4797445/61", "-127/13433407097045810", "-30/1953914271219269", "-37383453968917/610", "-11479816781573453/2848901582", "-2509812009985965380927298501595/13645002946929029896", "-409735863893015988549887290441890365889795673/6863841", "-359602127218795816494928857777/9159832300555", "-142029094679916682/85936648268932530864438001", ]; let common_values = &[ ("-1", 478), ("-2", 241), ("-3", 218), ("-1/2", 218), ("-1/3", 204), ("-1/4", 115), ("-1/7", 106), ("-2/3", 106), ("-4", 103), ("-5", 103), ]; let sample_median = ("-3568/3547", Some("-1942164762009/1930873766009")); let sample_moment_stats = MomentStats { mean: NiceFloat(-6.065823121451175e234), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_negative_rationals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_negative_rationals_fail_1() { random_negative_rationals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_negative_rationals_fail_2() { random_negative_rationals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-q/tests/random/random_non_negative_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::random_non_negative_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; fn random_non_negative_rationals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_non_negative_rationals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_non_negative_rationals() { // mean bits = 65/64 let values = &[ "0", "0", "0", "2", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "28", "1", "4", "1", "1", "0", ]; let common_values = &[ ("0", 496048), ("1", 247640), ("3", 62242), ("2", 61902), ("4", 15714), ("7", 15554), ("6", 15541), ("5", 15493), ("8", 4052), ("11", 4013), ]; let sample_median = ("2/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.803726415872939), standard_deviation: NiceFloat(857.0035840628179), skewness: NiceFloat(473.2359523744428), excess_kurtosis: NiceFloat(254290.48263912715), }; random_non_negative_rationals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1", "5/3", "0", "1", "0", "1/2", "356", "0", "0", "3/2", "3/5", "14/3", "0", "1/3", "19/3", "1/2", "0", "1", "0", "10", ]; let common_values = &[ ("0", 333130), ("1", 133186), ("2", 44272), ("3", 41733), ("1/2", 33380), ("1/3", 31211), ("4", 14811), ("5", 14622), ("6", 13959), ("7", 13895), ]; let sample_median = ("2/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(13891.174382080539), standard_deviation: NiceFloat(5451707.141191459), skewness: NiceFloat(576.0667309545814), excess_kurtosis: NiceFloat(353958.67367137416), }; random_non_negative_rationals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "7301/34", "4183103/1234731190583", "54812347098686/6195807891591254727", "812739/17841539017", "665/908", "677/1138982845180", "166/22491855393807861245619791028129", "270142/5", "52040856788711439301087669967/15975369961878544862054", "5718607/1953563256716085077", "8834633494449605/147372515680891813385292082245912643739605046366", "14860658876333535410753934016237/38209564041", "256/1033317698721", "1675/34808324932084086743491848009", "49", "42/5", "87750175104578/19615", "1/4767944", "137819495256811446350/41779", "2/187", ]; let common_values = &[ ("0", 30369), ("1", 1800), ("1/2", 822), ("2", 818), ("1/3", 705), ("3", 699), ("5", 399), ("1/4", 390), ("4", 382), ("1/5", 380), ]; let sample_median = ("84579/122161", Some("1013/1463")); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0180317983547227e148), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_negative_rationals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1428130618501/11392923974388402817057849552586132522617914732498530", "3383508417938165445131453/56779550950694809089378809702538209946934076252940714133449", "602900875601911171470306076355/119191771", "3/14013585568406836752167657664673", "760776403/6462405519227986816335721703034929571679921", "3453088342103851715673829426753969982/25626510185", "1747398675/3172739", "8948691991346583905040602549520967352911/18", "16038312634753050980603803559756/9438855467532928850187287", "155434788890251/4034446723", "950902359766673/235910534939055966292926793", "294004238713694270841854/1596165279", "1030393/85299778977201964065475016444620", "124218250251176079819064/503926103984580328155607497147", "277206127786809155854294/47228889692473", "3673/301956358739051815786302694193", "166239031838/39", "3309620973011864735684788/31306944615", "138546001637/6539404996772746726586649886838863596921111", "417/14077532426874196091229260728580", ]; let common_values = &[ ("0", 15382), ("1", 433), ("2", 245), ("1/2", 232), ("1/3", 213), ("3", 198), ("4", 118), ("5", 114), ("2/3", 114), ("1/5", 111), ]; let sample_median = ("25421/36471", Some("486/697")); let sample_moment_stats = MomentStats { mean: NiceFloat(4.459352389355579e272), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_non_negative_rationals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_non_negative_rationals_fail_1() { random_non_negative_rationals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_non_negative_rationals_fail_2() { random_non_negative_rationals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-q/tests/random/random_nonzero_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::random_nonzero_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; fn random_nonzero_rationals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_nonzero_rationals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_nonzero_rationals() { // mean bits = 65/64 let values = &[ "-1", "-1", "1", "1", "-1", "1", "1", "1", "1", "1", "1", "-1", "1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", ]; let common_values = &[ ("-1", 484924), ("1", 484658), ("3", 3815), ("1/3", 3811), ("-1/3", 3747), ("-2", 3743), ("1/2", 3740), ("-1/2", 3695), ("2", 3664), ("-3", 3591), ]; let sample_median = ("-1/7", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.000309218589743558), standard_deviation: NiceFloat(1.0376177116118968), skewness: NiceFloat(0.006166050703241532), excess_kurtosis: NiceFloat(-1.2860190331216774), }; random_nonzero_rationals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-8", "-1/7", "5", "1/3", "-1", "1/5", "1", "5", "1/26", "5/3", "1/2", "-3", "2", "-1/10", "-13/5", "-1/81", "-33", "-21", "-9/13", "-1", ]; let common_values = &[ ("1", 143164), ("-1", 142719), ("-2", 35933), ("1/2", 35874), ("-1/2", 35720), ("2", 35231), ("3", 34254), ("-1/3", 34198), ("-3", 34081), ("1/3", 34031), ]; let sample_median = ("-1/14021", Some("-1/14079")); let sample_moment_stats = MomentStats { mean: NiceFloat(0.22120311344442486), standard_deviation: NiceFloat(759.898347425165), skewness: NiceFloat(85.37622949885149), excess_kurtosis: NiceFloat(197537.4297586209), }; random_nonzero_rationals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-80861953616/9687130509484985", "-14557437513/313", "100721397389/392237929981", "713431423/1285", "-3887883364/889", "14185/969", "12609/11359517108746272468338071", "3443/4354945", "1/29", "5551/892095", "10/105173604567", "-19537757974145/22970361", "260/571", "-129425842/844581", "-11400586904841764775819697763820861082775967865/619503489", "-640859665273/199255145279143029", "-15530559035875594619912/1323170930793965328781", "-943/46106", "-1/113", "-58/1217", ]; let common_values = &[ ("1", 940), ("-1", 916), ("1/2", 463), ("-2", 458), ("2", 454), ("-1/2", 435), ("1/3", 391), ("-1/3", 389), ("3", 382), ("-3", 367), ]; let sample_median = ( "-56/1571996361141158873691832735034843333252522256904712087971186761383651552863627257507\ 9059423061", Some( "-322364/3099957057369745737816290559529344769064121899362905191001555856493272865037\ 24517150128896230616971", ), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.221976926004828e140), standard_deviation: NiceFloat(2.2219769258579568e143), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_rationals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-48553528129227068854128246488656/36214055281593228106459", "-22071489/37044301297", "255/542981", "9316/1012576106433925497", "-1664715/130027", "76455368490844554617/2980153660384121645", "80116271334543/93897057958828250698", "506747611059054706907067367541552559/130", "3325802517091555255861282341611/45079787663689587397296114", "2619/25010", "138524171232037/57", "-327554224783124113092/16778017845503481359721357185", "8702051241754639477/3724642828701481585672", "-1137052310060943639222669/10603652863466943873570746520875421824929696768184798584", "-273682512911798198562097/1410", "-19469521047938950017/8215425900326016767087299690926901706491788211", "-7582001356264120926498825684258819/24285551", "-858560112398451899225/359", "-649287191321577133137936520213146643215345718495684792790/7529", "-32944218852544/20849367593547441115716222574535971210798382851", ]; let common_values = &[ ("-1", 252), ("1", 230), ("1/2", 142), ("2", 127), ("3", 108), ("-2", 105), ("-3", 102), ("1/3", 101), ("-1/3", 94), ("-1/2", 91), ]; let sample_median = ( "-15668175538278751/5533317337571469966334347182083533508129248736899312345519768644568022\ 940401012659857427367497110049027936099115261493004685012826642110638291331832674475090998\ 50592299336680480845705995316128005975675", Some( "-52/545401271867319824074151466637070353812934757165212163414335060581060990607232033\ 27440868128671504241123333342761624433358162265204129676361103528857606120262656465655\ 47492357491745108315", ), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.683252966255455e252), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_nonzero_rationals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_nonzero_rationals_fail_1() { random_nonzero_rationals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_nonzero_rationals_fail_2() { random_nonzero_rationals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-q/tests/random/random_positive_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::random_positive_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; fn random_positive_rationals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_positive_rationals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_positive_rationals() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 969573), ("3", 7488), ("2", 7484), ("1/3", 7459), ("1/2", 7391), ("5", 75), ("6", 67), ("1/7", 67), ("2/3", 64), ("1/5", 61), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0147365511904034), standard_deviation: NiceFloat(0.21959420511046546), skewness: NiceFloat(8.77512842724579), excess_kurtosis: NiceFloat(133.15117857730885), }; random_positive_rationals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1/24", "1/30", "1/2", "2", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1/7", "2", "19", "1", "4", "3", "1/2", ]; let common_values = &[ ("1", 284707), ("2", 71334), ("1/2", 71222), ("3", 68255), ("1/3", 68142), ("5", 18020), ("4", 17749), ("1/5", 17746), ("1/4", 17705), ("1/6", 17245), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.527473854511467), standard_deviation: NiceFloat(439.80801149679047), skewness: NiceFloat(309.19213173617015), excess_kurtosis: NiceFloat(131113.5392046833), }; random_positive_rationals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "11/2", "89/27922830575", "46627409/3788983764809694", "8/11316951483471", "11/1005760138411689342464923704482", "948931/42716754", "81013760999253680590984897748479904878392/23", "1/97645164585502", "1558028859598/29", "200127331174844881647/4058622214797175252", "155/1413", "24470495/285805200646849943", "18939240741294741985527157685848850947887212663091378627/3070040", "545942890259/414324415", "4/209925", "128959877500520349/1134718", "2/424578084893903", "1956237739171878131383877", "17054902546906498751130/7", "782845/239707736", ]; let common_values = &[ ("1", 1810), ("1/2", 922), ("2", 915), ("3", 809), ("1/3", 776), ("1/4", 470), ("4", 426), ("1/5", 412), ("5", 409), ("2/3", 386), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.2380948358914507e127), standard_deviation: NiceFloat(2.2380948357494794e130), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_rationals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "515152389601430248907720412245595/443042512729", "103663/41795133908582491293103906323025", "71296091098068019359037078314906341733724/243288956813821163751969634165018193", "5557920650918595/82", "487/32461763914959248855", "38511521798151392412656616617957654586378660839/637134", "2330568192653124764618470467652346596061/2516", "512663303/39317568409", "18536901993439/4959577657266999117207", "628/42485719907732979", "7403291719610544/1075307073896295169983034533112645563410195", "4797445/61", "127/13433407097045810", "30/1953914271219269", "37383453968917/610", "11479816781573453/2848901582", "2509812009985965380927298501595/13645002946929029896", "409735863893015988549887290441890365889795673/6863841", "359602127218795816494928857777/9159832300555", "142029094679916682/85936648268932530864438001", ]; let common_values = &[ ("1", 478), ("2", 241), ("3", 218), ("1/2", 218), ("1/3", 204), ("1/4", 115), ("1/7", 106), ("2/3", 106), ("4", 103), ("5", 103), ]; let sample_median = ("1942164762009/1930873766009", Some("3568/3547")); let sample_moment_stats = MomentStats { mean: NiceFloat(6.065823121451175e234), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_positive_rationals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_positive_rationals_fail_1() { random_positive_rationals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_positive_rationals_fail_2() { random_positive_rationals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-q/tests/random/random_rational_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::random_rational_inclusive_range; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_inclusive_range_helper( a: &str, b: &str, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, mean_denominator_index_numerator: u64, mean_denominator_index_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap(), mean_numerator_bits_numerator, mean_numerator_bits_denominator, mean_denominator_index_numerator, mean_denominator_index_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_inclusive_range() { let values = &[ "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", "1/3", ]; let common_values = &[("1/3", 1000000)]; let sample_median = ("1/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3333333333333333), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_inclusive_range_helper( "1/3", "1/3", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "0", "1/2", "0", "1", "0", "0", "1", "0", "1/2", "1", "1/2", "1", "1/3", "0", "1/2", "1/2", "1/3", "1", "1/6", "1", ]; let common_values = &[ ("0", 262055), ("1/2", 249730), ("1", 237742), ("1/3", 86236), ("1/4", 42606), ("2/3", 39168), ("3/4", 19633), ("1/5", 13421), ("1/6", 12245), ("3/5", 6206), ]; let sample_median = ("1/2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.46651895490175377), standard_deviation: NiceFloat(0.3690116747518855), skewness: NiceFloat(0.18424550073715937), excess_kurtosis: NiceFloat(-1.2512329853066777), }; random_rational_inclusive_range_helper( "0", "1", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/2", "1/6", "0", "11/15", "1/9", "1/24", "0", "1/6", "1", "7/10", "14/15", "4/29", "0", "3/13", "1/3", "10/29", "17/18", "0", "1", "1/8", ]; let common_values = &[ ("1/2", 82681), ("1/3", 51495), ("0", 47408), ("1/4", 46547), ("1/6", 44587), ("1", 43387), ("1/5", 26408), ("1/8", 24875), ("2/3", 23502), ("3/4", 21468), ]; let sample_median = ("4/15", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3574859107909007), standard_deviation: NiceFloat(0.29213805168114404), skewness: NiceFloat(0.7340743758337255), excess_kurtosis: NiceFloat(-0.6079435842676566), }; random_rational_inclusive_range_helper( "0", "1", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/2", "1/3", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/3", "1/2", "1/3", "1/2", "2/5", "1/2", "1/3", "1/3", "2/5", "1/2", "4/9", "1/2", ]; let common_values = &[ ("1/2", 499797), ("1/3", 249730), ("2/5", 125404), ("3/7", 62239), ("3/8", 31351), ("4/9", 15620), ("5/11", 4024), ("4/11", 3989), ("5/12", 3856), ("6/13", 1003), ]; let sample_median = ("7/15", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.43521234958930916), standard_deviation: NiceFloat(0.0706863774046333), skewness: NiceFloat(-0.40352004419103704), excess_kurtosis: NiceFloat(-1.5393678543556049), }; random_rational_inclusive_range_helper( "1/3", "1/2", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/3", "4/9", "1/2", "9/19", "5/13", "13/28", "1/2", "4/9", "1/2", "5/14", "9/19", "14/33", "1/2", "8/17", "2/5", "14/33", "9/22", "1/2", "1/2", "5/12", ]; let common_values = &[ ("1/2", 90795), ("1/3", 82681), ("2/5", 74997), ("3/7", 68015), ("3/8", 61965), ("4/9", 56891), ("5/12", 46440), ("5/14", 38639), ("7/15", 35083), ("7/16", 31926), ]; let sample_median = ("5/12", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.4146806356838901), standard_deviation: NiceFloat(0.04970657076728507), skewness: NiceFloat(0.05385178173988354), excess_kurtosis: NiceFloat(-1.0272575619229356), }; random_rational_inclusive_range_helper( "1/3", "1/2", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3", "11/4", "3", "3", "3", "3", "3", "3", "11/4", "3", "11/4", "3", "14/5", "3", "11/4", "11/4", "14/5", "3", "25/8", "3", ]; let common_values = &[ ("3", 499797), ("11/4", 249730), ("14/5", 125404), ("17/6", 62239), ("20/7", 31351), ("23/8", 7872), ("25/8", 7748), ("25/9", 2675), ("28/9", 2671), ("26/9", 2667), ]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.8966573835412754), standard_deviation: NiceFloat(0.11355671930910265), skewness: NiceFloat(-0.15916553020077587), excess_kurtosis: NiceFloat(-1.693978851875664), }; random_rational_inclusive_range_helper( "268876667/98914198", "245850922/78256779", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "11/4", "25/8", "3", "52/17", "30/11", "79/26", "3", "25/8", "3", "35/12", "50/17", "92/31", "3", "46/15", "14/5", "91/31", "57/20", "3", "3", "29/10", ]; let common_values = &[ ("3", 90795), ("11/4", 82681), ("14/5", 74997), ("17/6", 68015), ("20/7", 61965), ("25/8", 28541), ("23/8", 28350), ("29/10", 23236), ("31/10", 23204), ("37/12", 19335), ]; let sample_median = ("23/8", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9061506622897797), standard_deviation: NiceFloat(0.12219692502115352), skewness: NiceFloat(0.3585054332079069), excess_kurtosis: NiceFloat(-1.1302487991867385), }; random_rational_inclusive_range_helper( "268876667/98914198", "245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_inclusive_range_fail_1() { random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 0, 1, 1, ); } #[test] #[should_panic] fn random_rational_inclusive_range_fail_2() { random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 0, 0, 1, 1, ); } #[test] #[should_panic] fn random_rational_inclusive_range_fail_3() { random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 1, 1, 0, ); } #[test] #[should_panic] fn random_rational_inclusive_range_fail_4() { random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 1, 0, 0, ); } #[test] #[should_panic] fn random_rational_inclusive_range_fail_5() { random_rational_inclusive_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), 2, 3, 1, 1, ); } ================================================ FILE: malachite-q/tests/random/random_rational_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::random_rational_range; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_range_helper( a: &str, b: &str, mean_numerator_bits_numerator: u64, mean_numerator_bits_denominator: u64, mean_denominator_index_numerator: u64, mean_denominator_index_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_range( EXAMPLE_SEED, Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap(), mean_numerator_bits_numerator, mean_numerator_bits_denominator, mean_denominator_index_numerator, mean_denominator_index_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_range() { let values = &[ "0", "1/2", "0", "0", "0", "0", "0", "0", "1/2", "0", "1/2", "0", "1/3", "0", "1/2", "1/2", "1/3", "0", "1/6", "0", ]; let common_values = &[ ("0", 499797), ("1/2", 249730), ("1/3", 86236), ("1/4", 42606), ("2/3", 39168), ("3/4", 19633), ("1/5", 13421), ("1/6", 12245), ("3/5", 6206), ("2/5", 6141), ]; let sample_median = ("1/12", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.22877695490175154), standard_deviation: NiceFloat(0.2524452096013498), skewness: NiceFloat(0.4918767315871824), excess_kurtosis: NiceFloat(-1.2397727721157625), }; random_rational_range_helper( "0", "1", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/2", "1/6", "0", "11/15", "1/9", "1/24", "0", "1/6", "0", "7/10", "14/15", "4/29", "0", "3/13", "1/3", "10/29", "17/18", "0", "0", "1/8", ]; let common_values = &[ ("0", 90795), ("1/2", 82681), ("1/3", 51495), ("1/4", 46547), ("1/6", 44587), ("1/5", 26408), ("1/8", 24875), ("2/3", 23502), ("3/4", 21468), ("1/12", 20489), ]; let sample_median = ("1/4", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3140989107909008), standard_deviation: NiceFloat(0.26663772734754415), skewness: NiceFloat(0.7462991500757579), excess_kurtosis: NiceFloat(-0.5495263431182642), }; random_rational_range_helper( "0", "1", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/3", "1/3", "1/3", "2/5", "1/3", "1/3", "2/5", "4/9", "1/3", "3/7", "2/5", "1/3", "2/5", "1/3", "1/3", "5/13", "1/3", "1/3", "2/5", "1/3", ]; let common_values = &[ ("1/3", 499619), ("2/5", 250775), ("3/7", 125038), ("3/8", 62105), ("4/9", 31072), ("5/11", 7939), ("4/11", 7842), ("5/12", 7736), ("6/13", 1984), ("5/14", 1928), ]; let sample_median = ("5/14", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3704726750344205), standard_deviation: NiceFloat(0.04006148834460584), skewness: NiceFloat(0.4071245940784675), excess_kurtosis: NiceFloat(-1.377512459092156), }; random_rational_range_helper( "1/3", "1/2", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/3", "4/9", "9/19", "5/13", "13/28", "4/9", "5/14", "9/19", "14/33", "8/17", "2/5", "14/33", "9/22", "5/12", "3/8", "5/12", "4/9", "14/33", "3/7", "9/23", ]; let common_values = &[ ("1/3", 90947), ("2/5", 82548), ("3/7", 74875), ("3/8", 68126), ("4/9", 62503), ("5/12", 51079), ("5/14", 42543), ("7/15", 38588), ("7/16", 35069), ("7/18", 28933), ]; let sample_median = ("11/27", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.4061491128373723), standard_deviation: NiceFloat(0.04379766958185411), skewness: NiceFloat(-0.06037812600265093), excess_kurtosis: NiceFloat(-1.1137203231085004), }; random_rational_range_helper( "1/3", "1/2", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3", "11/4", "3", "3", "3", "3", "3", "3", "11/4", "3", "11/4", "3", "14/5", "3", "11/4", "11/4", "14/5", "3", "25/8", "3", ]; let common_values = &[ ("3", 499797), ("11/4", 249730), ("14/5", 125404), ("17/6", 62239), ("20/7", 31351), ("23/8", 7872), ("25/8", 7748), ("25/9", 2675), ("28/9", 2671), ("26/9", 2667), ]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.8966573835412754), standard_deviation: NiceFloat(0.11355671930910265), skewness: NiceFloat(-0.15916553020077587), excess_kurtosis: NiceFloat(-1.693978851875664), }; random_rational_range_helper( "268876667/98914198", "245850922/78256779", 10, 1, 1, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "11/4", "25/8", "3", "52/17", "30/11", "79/26", "3", "25/8", "3", "35/12", "50/17", "92/31", "3", "46/15", "14/5", "91/31", "57/20", "3", "3", "29/10", ]; let common_values = &[ ("3", 90795), ("11/4", 82681), ("14/5", 74997), ("17/6", 68015), ("20/7", 61965), ("25/8", 28541), ("23/8", 28350), ("29/10", 23236), ("31/10", 23204), ("37/12", 19335), ]; let sample_median = ("23/8", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.9061506622897797), standard_deviation: NiceFloat(0.12219692502115352), skewness: NiceFloat(0.3585054332079069), excess_kurtosis: NiceFloat(-1.1302487991867385), }; random_rational_range_helper( "268876667/98914198", "245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/3", "4/9", "7/19", "5/13", "13/28", "4/9", "5/14", "7/19", "14/33", "8/17", "2/5", "16/33", "9/22", "5/12", "3/8", "5/12", "4/9", "14/33", "3/7", "9/23", ]; let common_values = &[ ("1/3", 90947), ("2/5", 82548), ("3/7", 74875), ("3/8", 68126), ("4/9", 62503), ("5/12", 51079), ("5/14", 42543), ("7/15", 38588), ("7/16", 35069), ("7/18", 28933), ]; let sample_median = ("13/32", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.4056622022625132), standard_deviation: NiceFloat(0.04370473197429072), skewness: NiceFloat(-0.04788831075607498), excess_kurtosis: NiceFloat(-1.1147841677775145), }; random_rational_range_helper( "1/3", "1/2", 3, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_range_fail_1() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 0, 1, 1, ); } #[test] #[should_panic] fn random_rational_range_fail_2() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 0, 0, 1, 1, ); } #[test] #[should_panic] fn random_rational_range_fail_3() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 1, 1, 0, ); } #[test] #[should_panic] fn random_rational_range_fail_4() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 1, 0, 0, ); } #[test] #[should_panic] fn random_rational_range_fail_5() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(1u32, 3), 2, 3, 1, 1, ); } #[test] #[should_panic] fn random_rational_range_fail_6() { random_rational_range( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), 2, 3, 1, 1, ); } ================================================ FILE: malachite-q/tests/random/random_rational_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::random_rational_range_to_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_range_to_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_range_to_infinity() { let values = &[ "438/953", "4248", "6259791/632", "99/2", "34/87", "5/3", "3", "233500344/25", "45/2168", "2/3", "1", "194403055/2031", "1799/72", "162713/14", "1/31", "25413015/7691773", "243/3260", "2/1895", "261/252386", "3997/36893154", ]; let common_values = &[ ("0", 8410), ("1", 7679), ("1/2", 6403), ("1/3", 5093), ("1/6", 4068), ("3", 3591), ("2", 3472), ("3/2", 2895), ("1/4", 2642), ("2/3", 2350), ]; let sample_median = ("56059/1740", Some("6303352/195639")); let sample_moment_stats = MomentStats { mean: NiceFloat(3.839214579009629e215), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_range_to_infinity_helper( "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "121396406/953", "152", "99407/632", "99/2", "436/87", "11/3", "451", "97/25", "764903/2168", "14253863309/3", "6", "19165/2031", "3847/72", "7065/14", "360014815/31", "20728497559/7691773", "13813/3260", "221536/1895", "1651717/252386", "828014364376645/36893154", ]; let common_values = &[ ("7/2", 8108), ("5", 2819), ("6", 2789), ("7", 2788), ("4", 2727), ("11/3", 1331), ("11", 1302), ("14/3", 1302), ("15", 1299), ("15/4", 1299), ]; let sample_median = ("5632495/34508", Some("12647038/77483")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.5244840655472015e31), standard_deviation: NiceFloat(1.4418360146531462e34), skewness: NiceFloat(995.0794447771476), excess_kurtosis: NiceFloat(993187.6643660564), }; random_rational_range_to_infinity_helper( "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3983598880556866742/953", "-1", "48202831/632", "99/2", "10/87", "-8/3", "15043", "7793790546/25", "-7/2168", "191126/3", "2", "1110539913949/2031", "416495/72", "125991833/14", "3039/31", "20728497559/7691773", "7/3260", "16/1895", "-1/252386", "-149405/36893154", ]; let common_values = &[ ("0", 7260), ("-1", 6845), ("1", 6673), ("-1/2", 5123), ("1/2", 5089), ("-1/3", 4054), ("1/3", 4037), ("2", 3132), ("3", 3086), ("-3", 3014), ]; let sample_median = ("120/143", Some("167/199")); let sample_moment_stats = MomentStats { mean: NiceFloat(1.8672643518545765e150), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_range_to_infinity_helper( "-245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_range_to_infinity_fail_1() { random_rational_range_to_infinity(EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 0); } #[test] #[should_panic] fn random_rational_range_to_infinity_fail_2() { random_rational_range_to_infinity(EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 0, 0); } #[test] #[should_panic] fn random_rational_range_to_infinity_fail_3() { random_rational_range_to_infinity(EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 2, 3); } ================================================ FILE: malachite-q/tests/random/random_rational_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::random_rational_range_to_negative_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_range_to_negative_infinity_helper( a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_range_to_negative_infinity() { let values = &[ "-438/953", "-4248", "-6259791/632", "-99/2", "-34/87", "-5/3", "-3", "-233500344/25", "-45/2168", "-2/3", "-1", "-194403055/2031", "-1799/72", "-162713/14", "-1/31", "-25413015/7691773", "-243/3260", "-2/1895", "-261/252386", "-3997/36893154", ]; let common_values = &[ ("0", 8410), ("-1", 7679), ("-1/2", 6403), ("-1/3", 5093), ("-1/6", 4068), ("-3", 3591), ("-2", 3472), ("-3/2", 2895), ("-1/4", 2642), ("-2/3", 2350), ]; let sample_median = ("-6303352/195639", Some("-56059/1740")); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.839214579009629e215), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_range_to_negative_infinity_helper( "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-2416809961348278/953", "-239755416", "-786400335/632", "-1187/2", "-1744034/87", "-31427/3", "1", "-1848/25", "-231/2168", "-662/3", "-30", "-31/2031", "-23/72", "-409/14", "1/31", "-389574262244759/7691773", "-3367126941/3260", "-12414/1895", "21/252386", "-254071517765467099/36893154", ]; let common_values = &[ ("0", 7287), ("-1", 6777), ("1", 6695), ("1/2", 5313), ("-1/2", 5087), ("-1/3", 3983), ("1/3", 3973), ("-2", 3145), ("2", 3070), ("-3", 3057), ]; let sample_median = ("-5/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.0896126103851687e162), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_range_to_negative_infinity_helper( "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-121396406/953", "-152", "-99407/632", "-99/2", "-349/87", "-14/3", "-451", "-109/25", "-764903/2168", "-14253863309/3", "-5", "-19165/2031", "-3847/72", "-7065/14", "-360014815/31", "-20728497559/7691773", "-29701/3260", "-10141/1895", "-631864475205/252386", "-34535611967/36893154", ]; let common_values = &[ ("-7/2", 8239), ("-4", 2880), ("-5", 2814), ("-6", 2784), ("-7", 2757), ("-13/4", 1348), ("-10/3", 1319), ("-11", 1297), ("-12", 1287), ("-9", 1283), ]; let sample_median = ("-399951/2456", Some("-158474076705/973165216")); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.436272253581606e29), standard_deviation: NiceFloat(3.412894005444307e32), skewness: NiceFloat(-733.9934078667648), excess_kurtosis: NiceFloat(587074.6340754497), }; random_rational_range_to_negative_infinity_helper( "-245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_range_to_negative_infinity_fail_1() { random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 0, ); } #[test] #[should_panic] fn random_rational_range_to_negative_infinity_fail_2() { random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 0, 0, ); } #[test] #[should_panic] fn random_rational_range_to_negative_infinity_fail_3() { random_rational_range_to_negative_infinity(EXAMPLE_SEED, Rational::from_signeds(-1, 3), 2, 3); } ================================================ FILE: malachite-q/tests/random/random_rational_with_denominator_inclusive_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::One; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::random::random_rational_with_denominator_inclusive_range; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_with_denominator_inclusive_range_helper( d: &str, a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_with_denominator_inclusive_range( EXAMPLE_SEED, Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_with_denominator_inclusive_range() { let values = &[ "0", "1", "0", "1", "1", "0", "0", "0", "1", "1", "0", "0", "1", "1", "0", "1", "0", "1", "1", "0", ]; let common_values = &[("0", 523140), ("1", 476860)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.47685999999999046), standard_deviation: NiceFloat(0.49946450310787194), skewness: NiceFloat(0.0926592837970364), excess_kurtosis: NiceFloat(-1.9914142571262847), }; random_rational_with_denominator_inclusive_range_helper( "1", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", ]; let common_values = &[("1", 1000000)]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_inclusive_range_helper( "1", "1", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", ]; let common_values = &[("1/2", 1000000)]; let sample_median = ("1/2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_inclusive_range_helper( "2", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "5/6", "1/6", "1/6", "1/6", "1/6", "5/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "5/6", "1/6", ]; let common_values = &[("1/6", 783614), ("5/6", 216386)]; let sample_median = ("1/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3109239999999932), standard_deviation: NiceFloat(0.2745204048819774), skewness: NiceFloat(1.3775012070185304), excess_kurtosis: NiceFloat(-0.10249042466258196), }; random_rational_with_denominator_inclusive_range_helper( "6", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "41/100", "43/100", "41/100", "41/100", "39/100", "41/100", "49/100", "41/100", "41/100", "39/100", "49/100", "37/100", "37/100", "49/100", "39/100", "37/100", "41/100", "41/100", "43/100", "37/100", ]; let common_values = &[ ("37/100", 167531), ("47/100", 167302), ("49/100", 166766), ("41/100", 166355), ("43/100", 166287), ("39/100", 165759), ]; let sample_median = ("43/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.42668872000000546), standard_deviation: NiceFloat(0.042331383354523355), skewness: NiceFloat(0.2167262624312793), excess_kurtosis: NiceFloat(-1.345880916970383), }; random_rational_with_denominator_inclusive_range_helper( "100", "1/3", "1/2", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", ]; let common_values = &[("3", 1000000)]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_inclusive_range_helper( "1", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", ]; let common_values = &[("17/6", 1000000)]; let sample_median = ("17/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.8333333333333335), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_inclusive_range_helper( "6", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "301/100", "279/100", "313/100", "299/100", "301/100", "273/100", "279/100", "301/100", "297/100", "311/100", "309/100", "301/100", "279/100", "289/100", "279/100", "279/100", "309/100", "293/100", "287/100", "299/100", ]; let common_values = &[ ("299/100", 59348), ("307/100", 59112), ("281/100", 59097), ("297/100", 58997), ("283/100", 58975), ("293/100", 58941), ("309/100", 58919), ("311/100", 58910), ("287/100", 58857), ("289/100", 58794), ]; let sample_median = ("293/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.937086759999876), standard_deviation: NiceFloat(0.12202969771309406), skewness: NiceFloat(-0.025551558114942263), excess_kurtosis: NiceFloat(-1.2130746374242132), }; random_rational_with_denominator_inclusive_range_helper( "100", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_with_denominator_inclusive_range_fail_1() { random_rational_with_denominator_inclusive_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 0, ); } #[test] #[should_panic] fn random_rational_with_denominator_inclusive_range_fail_2() { random_rational_with_denominator_inclusive_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 2, 3, ); } #[test] #[should_panic] fn random_rational_with_denominator_inclusive_range_fail_3() { random_rational_with_denominator_inclusive_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), 2, 3, ); } ================================================ FILE: malachite-q/tests/random/random_rational_with_denominator_range.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::One; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::random::random_rational_with_denominator_range; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_with_denominator_range_helper( d: &str, a: &str, b: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_with_denominator_range( EXAMPLE_SEED, Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), Rational::from_str(b).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_with_denominator_range() { let values = &[ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ]; let common_values = &[("0", 1000000)]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_range_helper( "1", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", "1/2", ]; let common_values = &[("1/2", 1000000)]; let sample_median = ("1/2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.5), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_range_helper( "2", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "5/6", "1/6", "1/6", "1/6", "1/6", "5/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "1/6", "5/6", "1/6", ]; let common_values = &[("1/6", 783614), ("5/6", 216386)]; let sample_median = ("1/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.3109239999999932), standard_deviation: NiceFloat(0.2745204048819774), skewness: NiceFloat(1.3775012070185304), excess_kurtosis: NiceFloat(-0.10249042466258196), }; random_rational_with_denominator_range_helper( "6", "0", "1", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "41/100", "43/100", "41/100", "41/100", "39/100", "41/100", "49/100", "41/100", "41/100", "39/100", "49/100", "37/100", "37/100", "49/100", "39/100", "37/100", "41/100", "41/100", "43/100", "37/100", ]; let common_values = &[ ("37/100", 167531), ("47/100", 167302), ("49/100", 166766), ("41/100", 166355), ("43/100", 166287), ("39/100", 165759), ]; let sample_median = ("43/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.42668872000000546), standard_deviation: NiceFloat(0.042331383354523355), skewness: NiceFloat(0.2167262624312793), excess_kurtosis: NiceFloat(-1.345880916970383), }; random_rational_with_denominator_range_helper( "100", "1/3", "1/2", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", ]; let common_values = &[("3", 1000000)]; let sample_median = ("3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.0), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_range_helper( "1", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", "17/6", ]; let common_values = &[("17/6", 1000000)]; let sample_median = ("17/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.8333333333333335), standard_deviation: NiceFloat(0.0), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rational_with_denominator_range_helper( "6", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "301/100", "279/100", "313/100", "299/100", "301/100", "273/100", "279/100", "301/100", "297/100", "311/100", "309/100", "301/100", "279/100", "289/100", "279/100", "279/100", "309/100", "293/100", "287/100", "299/100", ]; let common_values = &[ ("299/100", 59348), ("307/100", 59112), ("281/100", 59097), ("297/100", 58997), ("283/100", 58975), ("293/100", 58941), ("309/100", 58919), ("311/100", 58910), ("287/100", 58857), ("289/100", 58794), ]; let sample_median = ("293/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.937086759999876), standard_deviation: NiceFloat(0.12202969771309406), skewness: NiceFloat(-0.025551558114942263), excess_kurtosis: NiceFloat(-1.2130746374242132), }; random_rational_with_denominator_range_helper( "100", "268876667/98914198", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_fail_1() { random_rational_with_denominator_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 10, 0, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_fail_2() { random_rational_with_denominator_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(2u32, 3), 2, 3, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_fail_3() { random_rational_with_denominator_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), Rational::from_unsigneds(1u32, 3), 2, 3, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_fail_4() { random_rational_with_denominator_range( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 2), Rational::from_unsigneds(1u32, 3), 2, 3, ); } ================================================ FILE: malachite-q/tests/random/random_rational_with_denominator_range_to_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::One; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::random::random_rational_with_denominator_range_to_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_with_denominator_range_to_infinity_helper( d: &str, a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_with_denominator_range_to_infinity( EXAMPLE_SEED, Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_with_denominator_range_to_infinity() { let values = &[ "2", "4", "178", "1084828126", "6", "12", "56", "591", "5283", "5606382754", "3", "35", "1", "1", "65728184", "6", "0", "7", "110989", "774544411777231510", ]; let common_values = &[ ("0", 90859), ("1", 82901), ("2", 37557), ("3", 37534), ("6", 17244), ("5", 17221), ("7", 17166), ("4", 16881), ("10", 7792), ("8", 7781), ]; let sample_median = ("81", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.520127903486984e34), standard_deviation: NiceFloat(7.329977056427779e37), skewness: NiceFloat(961.5590415384418), excess_kurtosis: NiceFloat(943383.4745426066), }; random_rational_with_denominator_range_to_infinity_helper( "1", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "591/2", "5283/2", "3/2", "35/2", "1/2", "1/2", "7/2", "110989/2", "1/2", "5/2", "751/2", "7943/2", "7065/2", "8413078495/2", "3/2", "1/2", "1/2", "69/2", "13/2", "7749/2", ]; let common_values = &[ ("1/2", 167084), ("3/2", 75468), ("7/2", 34473), ("5/2", 34378), ("11/2", 15785), ("13/2", 15606), ("15/2", 15565), ("9/2", 15464), ("29/2", 7220), ("27/2", 7166), ]; let sample_median = ("89/2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0730191792105077e40), standard_deviation: NiceFloat(1.072277458027706e43), skewness: NiceFloat(999.9978064950928), excess_kurtosis: NiceFloat(999994.0749119784), }; random_rational_with_denominator_range_to_infinity_helper( "2", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "35/6", "1/6", "1/6", "7/6", "110989/6", "1/6", "5/6", "751/6", "7943/6", "8413078495/6", "1/6", "1/6", "13/6", "7/6", "744559/6", "707/6", "751063343911/6", "28206975458359/6", "971/6", "3925/6", ]; let common_values = &[ ("1/6", 241941), ("5/6", 50133), ("7/6", 50049), ("11/6", 22890), ("13/6", 22726), ("29/6", 10488), ("23/6", 10390), ("19/6", 10358), ("25/6", 10358), ("31/6", 10291), ]; let sample_median = ("67/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.4338034128378777e36), standard_deviation: NiceFloat(2.4305548034225437e39), skewness: NiceFloat(999.9972159387221), excess_kurtosis: NiceFloat(999993.287033733), }; random_rational_with_denominator_range_to_infinity_helper( "6", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "509/100", "489/100", "319/100", "591/100", "437/100", "913/100", "449/100", "1731/100", "359/100", "359/100", "999/100", "501/100", "479/100", "333/100", "499/100", "733/100", "751/100", "40711/100", "921/100", "5087/100", ]; let common_values = &[ ("473/100", 6588), ("417/100", 6577), ("423/100", 6539), ("369/100", 6537), ("457/100", 6479), ("433/100", 6459), ("409/100", 6455), ("339/100", 6442), ("359/100", 6439), ("449/100", 6437), ]; let sample_median = ("511/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(45.44256795999996), standard_deviation: NiceFloat(5322.132374334366), skewness: NiceFloat(618.505376716015), excess_kurtosis: NiceFloat(438771.8555941413), }; random_rational_with_denominator_range_to_infinity_helper( "100", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-281/100", "-79/100", "-11/100", "9/100", "-1/100", "3/100", "51933/100", "-39/100", "3/100", "31/100", "51/100", "-1/100", "-29/100", "-1/100", "-1/100", "7749/100", "-191/100", "1/100", "-7/100", "119/100", ]; let common_values = &[ ("1/100", 123814), ("-1/100", 123122), ("-3/100", 56658), ("3/100", 56096), ("7/100", 25530), ("-7/100", 25528), ("-13/100", 11889), ("11/100", 11771), ("-11/100", 11652), ("9/100", 11626), ]; let sample_median = ("1/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.7877073287017464e35), standard_deviation: NiceFloat(1.6780985984051316e38), skewness: NiceFloat(994.171891194563), excess_kurtosis: NiceFloat(991907.5494321428), }; random_rational_with_denominator_range_to_infinity_helper( "100", "-245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_to_infinity_fail_1() { random_rational_with_denominator_range_to_infinity( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), 10, 0, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_to_infinity_fail_2() { random_rational_with_denominator_range_to_infinity( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), 2, 3, ); } ================================================ FILE: malachite-q/tests/random/random_rational_with_denominator_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 malachite_base::num::basic::traits::One; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_nz::natural::Natural; use malachite_q::Rational; use malachite_q::random::random_rational_with_denominator_range_to_negative_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn random_rational_with_denominator_range_to_negative_infinity_helper( d: &str, a: &str, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rational_with_denominator_range_to_negative_infinity( EXAMPLE_SEED, Natural::from_str(d).unwrap(), Rational::from_str(a).unwrap(), mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rational_with_denominator_range_to_negative_infinity() { let values = &[ "-2", "-4", "-178", "-1084828126", "-6", "-12", "-56", "-591", "-5283", "-5606382754", "-3", "-35", "-1", "-1", "-65728184", "-6", "0", "-7", "-110989", "-774544411777231510", ]; let common_values = &[ ("0", 90859), ("-1", 82901), ("-2", 37557), ("-3", 37534), ("-6", 17244), ("-5", 17221), ("-7", 17166), ("-4", 16881), ("-10", 7792), ("-8", 7781), ]; let sample_median = ("-81", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.520127903486984e34), standard_deviation: NiceFloat(7.329977056427779e37), skewness: NiceFloat(-961.5590415384418), excess_kurtosis: NiceFloat(943383.4745426066), }; random_rational_with_denominator_range_to_negative_infinity_helper( "1", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-591/2", "-5283/2", "-3/2", "-35/2", "-1/2", "-1/2", "-7/2", "-110989/2", "-1/2", "-5/2", "-751/2", "-7943/2", "-7065/2", "-8413078495/2", "-3/2", "-1/2", "-1/2", "-69/2", "-13/2", "-7749/2", ]; let common_values = &[ ("-1/2", 167084), ("-3/2", 75468), ("-7/2", 34473), ("-5/2", 34378), ("-11/2", 15785), ("-13/2", 15606), ("-15/2", 15565), ("-9/2", 15464), ("-29/2", 7220), ("-27/2", 7166), ]; let sample_median = ("-89/2", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0730191792105077e40), standard_deviation: NiceFloat(1.072277458027706e43), skewness: NiceFloat(-999.9978064950928), excess_kurtosis: NiceFloat(999994.0749119784), }; random_rational_with_denominator_range_to_negative_infinity_helper( "2", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-35/6", "-1/6", "-1/6", "-7/6", "-110989/6", "-1/6", "-5/6", "-751/6", "-7943/6", "-8413078495/6", "-1/6", "-1/6", "-13/6", "-7/6", "-744559/6", "-707/6", "-751063343911/6", "-28206975458359/6", "-971/6", "-3925/6", ]; let common_values = &[ ("-1/6", 241941), ("-5/6", 50133), ("-7/6", 50049), ("-11/6", 22890), ("-13/6", 22726), ("-29/6", 10488), ("-23/6", 10390), ("-19/6", 10358), ("-25/6", 10358), ("-31/6", 10291), ]; let sample_median = ("-67/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.4338034128378777e36), standard_deviation: NiceFloat(2.4305548034225437e39), skewness: NiceFloat(-999.9972159387221), excess_kurtosis: NiceFloat(999993.287033733), }; random_rational_with_denominator_range_to_negative_infinity_helper( "6", "0", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-99/100", "-913/100", "-11/100", "7/100", "1/100", "-10973/100", "47/100", "-39/100", "57/100", "-3/100", "23/100", "-10522099/100", "-1/100", "-29701/100", "1/100", "1/100", "-7743/100", "1/100", "-7/100", "-89199/100", ]; let common_values = &[ ("-1/100", 123615), ("1/100", 123443), ("3/100", 56191), ("-3/100", 56020), ("7/100", 25883), ("-7/100", 25543), ("-9/100", 11654), ("11/100", 11646), ("13/100", 11586), ("9/100", 11583), ]; let sample_median = ("-1/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-9.380763184802002e48), standard_deviation: NiceFloat(9.380763184802352e51), skewness: NiceFloat(-999.9984999993959), excess_kurtosis: NiceFloat(999995.00000096), }; random_rational_with_denominator_range_to_negative_infinity_helper( "100", "245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-509/100", "-427/100", "-407/100", "-343/100", "-591/100", "-913/100", "-321/100", "-1731/100", "-373/100", "-999/100", "-361/100", "-353/100", "-437/100", "-733/100", "-751/100", "-40711/100", "-921/100", "-5087/100", "-919/100", "-323/100", ]; let common_values = &[ ("-469/100", 6500), ("-497/100", 6483), ("-437/100", 6473), ("-473/100", 6460), ("-387/100", 6455), ("-421/100", 6454), ("-493/100", 6454), ("-379/100", 6447), ("-361/100", 6438), ("-347/100", 6432), ]; let sample_median = ("-511/100", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-45.46337932000087), standard_deviation: NiceFloat(5322.134805564187), skewness: NiceFloat(-618.5045180626813), excess_kurtosis: NiceFloat(438771.04416568665), }; random_rational_with_denominator_range_to_negative_infinity_helper( "100", "-245850922/78256779", 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_to_negative_infinity_fail_1() { random_rational_with_denominator_range_to_negative_infinity( EXAMPLE_SEED, Natural::ONE, Rational::from_unsigneds(1u32, 3), 10, 0, ); } #[test] #[should_panic] fn random_rational_with_denominator_range_to_negative_infinity_fail_2() { random_rational_with_denominator_range_to_negative_infinity( EXAMPLE_SEED, Natural::ONE, Rational::from_signeds(-1i32, 3), 2, 3, ); } ================================================ FILE: malachite-q/tests/random/random_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::random_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; fn random_rationals_helper( mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( random_rationals(EXAMPLE_SEED, mean_bits_numerator, mean_bits_denominator), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_random_rationals() { // mean bits = 65/64 let values = &[ "0", "0", "0", "2", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "-28", "-1", "-4", "-1", "-1", "0", ]; let common_values = &[ ("0", 496048), ("1", 123950), ("-1", 123690), ("3", 31184), ("-2", 31130), ("-3", 31058), ("2", 30772), ("-4", 7921), ("-7", 7828), ("-6", 7799), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.5817718650793547), standard_deviation: NiceFloat(857.0389155951154), skewness: NiceFloat(-315.8438705097454), excess_kurtosis: NiceFloat(254264.92899445235), }; random_rationals_helper( 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-1", "-5/3", "0", "1", "0", "1/2", "356", "0", "0", "3/2", "3/5", "-14/3", "0", "-1/3", "-19/3", "-1/2", "0", "-1", "0", "-10", ]; let common_values = &[ ("0", 333130), ("1", 66630), ("-1", 66556), ("2", 22206), ("-2", 22066), ("-3", 20899), ("3", 20834), ("1/2", 16750), ("-1/2", 16630), ("1/3", 15616), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3875.4043163058423), standard_deviation: NiceFloat(5451723.46138941), skewness: NiceFloat(-481.96150934322344), excess_kurtosis: NiceFloat(353958.9361419337), }; random_rationals_helper( 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-7301/34", "-4183103/1234731190583", "54812347098686/6195807891591254727", "812739/17841539017", "-665/908", "677/1138982845180", "166/22491855393807861245619791028129", "270142/5", "52040856788711439301087669967/15975369961878544862054", "5718607/1953563256716085077", "8834633494449605/147372515680891813385292082245912643739605046366", "-14860658876333535410753934016237/38209564041", "256/1033317698721", "-1675/34808324932084086743491848009", "-49", "-42/5", "-87750175104578/19615", "-1/4767944", "-137819495256811446350/41779", "-2/187", ]; let common_values = &[ ("0", 30369), ("-1", 929), ("1", 871), ("1/2", 423), ("2", 410), ("-2", 408), ("-1/2", 399), ("3", 372), ("1/3", 368), ("-1/3", 337), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.0180317983547227e148), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rationals_helper( 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-1428130618501/11392923974388402817057849552586132522617914732498530", "-3383508417938165445131453/56779550950694809089378809702538209946934076252940714133449", "602900875601911171470306076355/119191771", "3/14013585568406836752167657664673", "-760776403/6462405519227986816335721703034929571679921", "3453088342103851715673829426753969982/25626510185", "1747398675/3172739", "8948691991346583905040602549520967352911/18", "16038312634753050980603803559756/9438855467532928850187287", "155434788890251/4034446723", "950902359766673/235910534939055966292926793", "-294004238713694270841854/1596165279", "1030393/85299778977201964065475016444620", "-124218250251176079819064/503926103984580328155607497147", "-277206127786809155854294/47228889692473", "-3673/301956358739051815786302694193", "-166239031838/39", "-3309620973011864735684788/31306944615", "-138546001637/6539404996772746726586649886838863596921111", "-417/14077532426874196091229260728580", ]; let common_values = &[ ("0", 15382), ("-1", 217), ("1", 216), ("-2", 126), ("1/2", 121), ("2", 119), ("-1/3", 117), ("-1/2", 111), ("-3", 100), ("3", 98), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.459352389355579e272), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; random_rationals_helper( 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn random_rationals_fail_1() { random_rationals(EXAMPLE_SEED, 1, 0); } #[test] #[should_panic] fn random_rationals_fail_2() { random_rationals(EXAMPLE_SEED, 2, 3); } ================================================ FILE: malachite-q/tests/random/striped_random_negative_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::striped_random_negative_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; #[allow(clippy::too_many_arguments)] fn striped_random_negative_rationals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_negative_rationals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_negative_rationals() { // mean bits = 65/64 let values = &["-1"; 20]; let common_values = &[ ("-1", 969574), ("-3", 7614), ("-1/3", 7540), ("-2", 7358), ("-1/2", 7310), ("-4", 98), ("-7", 88), ("-1/7", 87), ("-1/4", 79), ("-2/3", 59), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.0148534444805162), standard_deviation: NiceFloat(0.22114620623320444), skewness: NiceFloat(-9.149432588003647), excess_kurtosis: NiceFloat(159.01272255850165), }; striped_random_negative_rationals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-1/16", "-1/16", "-4/15", "-2", "-1", "-1", "-1", "-1", "-3/2", "-1", "-1", "-2/3", "-1", "-1/7", "-2", "-16", "-1", "-4", "-2", "-1/2", ]; let common_values = &[ ("-1", 286322), ("-2", 71839), ("-1/2", 71792), ("-1/3", 65670), ("-3", 65630), ("-1/4", 27230), ("-4", 26986), ("-7", 24307), ("-1/7", 24217), ("-2/3", 16638), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-8.675884348144963), standard_deviation: NiceFloat(452.3475394447746), skewness: NiceFloat(-244.55477994852157), excess_kurtosis: NiceFloat(71058.94920001029), }; striped_random_negative_rationals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-4", "-1/268681216", "-75493376/9007199120523391", "-8/8796094070783", "-8/950737950171027935941967741439", "-1040391/33554432", "-2813000899879757964630563421437095845888", "-1/79164837199872", "-2199023255551/16", "-220784470296873664512/4611685966886694919", "-33/256", "-16809472/144255925429997319", "-6129981798088146185736712229649530847599712363400396804/786431", "-1099511578623/1073741761", "-2/65791", "-18014398509490175/266208", "-1/140752654954496", "-2417842415927590238812160", "-9444732965755934466048/7", "-4194303/1073709056", ]; let common_values = &[ ("-1", 3591), ("-1/2", 1841), ("-2", 1732), ("-1/4", 1579), ("-4", 1555), ("-1/8", 1495), ("-8", 1470), ("-1/16", 1391), ("-16", 1304), ("-1/32", 1231), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-2.394348586566577e127), standard_deviation: NiceFloat(2.3943485865002743e130), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_rationals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-302231454903657360261120/383", "-3/2166395068749415481073467392", "-174223242635524708377374895198005052307456/664594824829454142366461086851399679", "-4503599627370496/127", "-2048/147574233996470517759", "-9132155158831519862233019347003870166304109363/209664", "-10634473003386642729879378371710812032/31", "-536870911/34359738368", "-5026338869833/1328165573307087716352", "-768/72040001986101247", "-18014261070561279/2786912585102768425368689128829376599687168", "-133152", "-3/545357767376900", "-31/2251799813685247", "-4398046511135/64", "-8796093046784/4194303", "-38685626236675332845338112/562949953420767", "-4459452226323108777095472045064328031949030396/50331647", "-2535298782614042945771878219776/70366596710399", "-144115188075855871/154740143727431099539783680", ]; let common_values = &[ ("-1", 1591), ("-2", 794), ("-1/2", 762), ("-8", 757), ("-16", 718), ("-4", 691), ("-1/4", 691), ("-1/8", 689), ("-1/16", 659), ("-32", 650), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.3341225920157865e234), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_negative_rationals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_negative_rationals_fail_1() { striped_random_negative_rationals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_negative_rationals_fail_2() { striped_random_negative_rationals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_negative_rationals_fail_3() { striped_random_negative_rationals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_negative_rationals_fail_4() { striped_random_negative_rationals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-q/tests/random/striped_random_non_negative_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::striped_random_non_negative_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; #[allow(clippy::too_many_arguments)] fn striped_random_non_negative_rationals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_non_negative_rationals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_non_negative_rationals() { // mean bits = 65/64 let values = &[ "0", "0", "0", "2", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "16", "1", "4", "1", "1", "0", ]; let common_values = &[ ("0", 496048), ("1", 247664), ("2", 62226), ("3", 61847), ("7", 23467), ("4", 23204), ("8", 8889), ("15", 8801), ("5", 7917), ("6", 7733), ]; let sample_median = ("2/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.241369898412524), standard_deviation: NiceFloat(1203.8320236802172), skewness: NiceFloat(650.4921628408604), excess_kurtosis: NiceFloat(487036.59115699964), }; striped_random_non_negative_rationals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "2/3", "4/3", "0", "1", "0", "1/2", "448", "0", "0", "1", "5/14", "11/3", "0", "1/3", "19/3", "1/3", "0", "1", "0", "15", ]; let common_values = &[ ("0", 333130), ("1", 134397), ("2", 44677), ("3", 40161), ("1/2", 33752), ("1/3", 30003), ("4", 22136), ("7", 19720), ("1/4", 12536), ("8", 11373), ]; let sample_median = ("2/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(12771.729072597298), standard_deviation: NiceFloat(5028817.645526858), skewness: NiceFloat(587.1636750940664), excess_kurtosis: NiceFloat(372144.3890017075), }; striped_random_non_negative_rationals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "8192/127", "16776704/4396972769407", "8796093005951/648518346332962816", "87381/2863267840", "1024/2043", "51/58408828928", "85/13521606402434254795714066382848", "270335/7", "59421159664630116152453890047/9444741445172838006656", "6291455/1154891846623166464", "4503599631564799/114177029184456441820717001177155938271778439152", "40247906632508999881205124923399/137438953471", "73/154619122249", "1024/39611663922002864317824761855", "32", "127/9", "2199023247360/287", "1/8257539", "590156181179127562240/131199", "1/85", ]; let common_values = &[ ("0", 30369), ("1", 3494), ("2", 1638), ("1/2", 1619), ("4", 1527), ("1/4", 1481), ("1/8", 1348), ("8", 1328), ("16", 1204), ("1/16", 1190), ]; let sample_median = ("2/3", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.681561663446933e148), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_negative_rationals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "1464583847936/7981747608676504359847391117664870922673555168908629", "2422574005712127994617856/100041309094775311912751523786213765636294062424476459466751", "9671406556916483641901054/2047", "1/10141204801678261259383949230080", "1/10384593719487506031596923529461760", "166153499473114484112975882535075839/1073741824", "1073758207/2097152", "10889035740836205568492768571262465220607/31", "16225927683142697268042315648307/15474248646392859802468352", "211174952009727/4294836224", "1125625028999183/309485009533116616750923776", "160551237036734989468671/2146697215", "4325375/324527219843164634252394901798911", "5666839779310716881032/42255019850195730860877091089", "201487684640834221069648/46912675075413", "1365/52818778157753880297518486869", "17179869184/7", "2420212822470693171986431/34359738367", "274877382656/11150372599265311570767859136324172163055871", "181/10141204802612896292451899146325", ]; let common_values = &[ ("0", 15382), ("1", 1486), ("1/2", 807), ("1/4", 728), ("2", 725), ("4", 693), ("8", 691), ("1/16", 685), ("1/8", 655), ("16", 628), ]; let sample_median = ( "28334198898317382877184/42501298345826806923263", Some("17179869184/25769803775"), ); let sample_moment_stats = MomentStats { mean: NiceFloat(5.67251933470839e272), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_non_negative_rationals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_non_negative_rationals_fail_1() { striped_random_non_negative_rationals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_non_negative_rationals_fail_2() { striped_random_non_negative_rationals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_non_negative_rationals_fail_3() { striped_random_non_negative_rationals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_non_negative_rationals_fail_4() { striped_random_non_negative_rationals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-q/tests/random/striped_random_nonzero_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::striped_random_nonzero_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; #[allow(clippy::too_many_arguments)] fn striped_random_nonzero_rationals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_nonzero_rationals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_nonzero_rationals() { // mean bits = 65/64 let values = &[ "-1", "-1", "1", "1", "-1", "1", "1", "1", "1", "1", "1", "-1", "1", "-1", "-1", "-1", "-1", "-1", "-1", "-1", ]; let common_values = &[ ("-1", 484931), ("1", 484658), ("3", 3817), ("1/2", 3814), ("-1/2", 3763), ("1/3", 3737), ("-2", 3697), ("-1/3", 3678), ("2", 3660), ("-3", 3636), ]; let sample_median = ("-1/7", None); let sample_moment_stats = MomentStats { mean: NiceFloat(0.00023288528138526625), standard_deviation: NiceFloat(1.037925742275186), skewness: NiceFloat(0.0009392339727778673), excess_kurtosis: NiceFloat(-1.2291100464705937), }; striped_random_nonzero_rationals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-14", "-1/7", "6", "1/3", "-1", "1/5", "1", "4", "1/31", "4/3", "1/3", "-2", "2", "-1/15", "-2", "-1/68", "-37", "-23", "-8/15", "-1", ]; let common_values = &[ ("1", 143643), ("-1", 143385), ("-2", 36002), ("1/2", 35965), ("-1/2", 35954), ("2", 35814), ("-3", 33135), ("-1/3", 33023), ("1/3", 32961), ("3", 32694), ]; let sample_median = ("-1/12767", Some("-1/15422")); let sample_moment_stats = MomentStats { mean: NiceFloat(-0.06690886383057024), standard_deviation: NiceFloat(743.3873846358883), skewness: NiceFloat(-34.20312291886276), excess_kurtosis: NiceFloat(162779.3378205672), }; striped_random_nonzero_rationals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-68720000000/18006083452797439", "-2545165805/29", "549754781664/1236950581247", "1065353727/2047", "-2147745791/513", "16128/575", "8192/17000482516899619632318463", "18431/16778240", "1/31", "4096/526335", "128/1648730570755", "-235590160969/299520", "256/1015", "-134213640/1015807", "-2135296358076219148941708516212794237273505792/134217731", "-1099511504895/144117387099111422", "-18854877723802865238015/1180663678191190081543", "-8191/327168", "-1/127", "-79/4095", ]; let common_values = &[ ("1", 1790), ("-1", 1776), ("1/2", 915), ("2", 911), ("-1/2", 882), ("-2", 880), ("-4", 815), ("4", 804), ("1/4", 790), ("-1/4", 787), ]; let sample_median = ( "-32/1667110261681770706918410051940899342228396408049959135280966429665234272396880613105\ 8561778175", Some( "-589823/54681270984110515773306643211150111379599332867331476905258877712070223126025\ 4978705174476571541504", ), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-9.989614378172733e139), standard_deviation: NiceFloat(9.989614377590213e142), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_rationals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-70988433612846563009577969778432/37778931862957161709535", "-18874367/34359740415", "128/1048575", "9215/576461851815051263", "-67043359/4194303", "557501356260338958336/32794196171264010809", "68719476735/36028797018963968", "2596148429269774428927230031691776", "298270729465465682551124201231/2275625072216288986599183", "2048/28735", "7818749353074/7", "-288230376185266175/9671406556917033397649408", "4611686147284795328/2361183241443412541439", "-1208925819333154214772480/12068402384318877481825725909459066626185514174187044863", "-292842132531367112448", "-27670116179283804159/5708990770823839524233181656729843468399049728", "-10384554102988398124892195902719999/16809983", "-1162146002543608594431/256", "-784637716922080678562056411478885332466638530662142836736/8191", "-35184372080639/11418025097790482669312781854182320779382783943", ]; let common_values = &[ ("-1", 771), ("1", 746), ("1/2", 400), ("-2", 393), ("2", 392), ("-1/4", 376), ("4", 374), ("1/4", 374), ("-1/2", 371), ("1/8", 364), ]; let sample_median = ( "-144115205255725055/979746761720636838570985193498093558267704500484488575872951292219126\ 535205986877548162797451588896054171174290755185947242500542102825307421372913188911655327\ 9240115862075993700091884987318332951625727", Some( "-64/870216902382548101082732198927734427236298632942811591373701982167193271662795024\ 74847721902845790124837140768618290655265839460108220779308034391550625260769672349354\ 97445986979146629119", ), ); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.8438486163830216e252), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_nonzero_rationals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_nonzero_rationals_fail_1() { striped_random_nonzero_rationals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_nonzero_rationals_fail_2() { striped_random_nonzero_rationals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_nonzero_rationals_fail_3() { striped_random_nonzero_rationals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_nonzero_rationals_fail_4() { striped_random_nonzero_rationals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-q/tests/random/striped_random_positive_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::striped_random_positive_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; #[allow(clippy::too_many_arguments)] fn striped_random_positive_rationals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_positive_rationals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_positive_rationals() { // mean bits = 65/64 let values = &["1"; 20]; let common_values = &[ ("1", 969574), ("3", 7614), ("1/3", 7540), ("2", 7358), ("1/2", 7310), ("4", 98), ("7", 88), ("1/7", 87), ("1/4", 79), ("2/3", 59), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.0148534444805162), standard_deviation: NiceFloat(0.22114620623320444), skewness: NiceFloat(9.149432588003647), excess_kurtosis: NiceFloat(159.01272255850165), }; striped_random_positive_rationals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "1/16", "1/16", "4/15", "2", "1", "1", "1", "1", "3/2", "1", "1", "2/3", "1", "1/7", "2", "16", "1", "4", "2", "1/2", ]; let common_values = &[ ("1", 286322), ("2", 71839), ("1/2", 71792), ("1/3", 65670), ("3", 65630), ("1/4", 27230), ("4", 26986), ("7", 24307), ("1/7", 24217), ("2/3", 16638), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(8.675884348144963), standard_deviation: NiceFloat(452.3475394447746), skewness: NiceFloat(244.55477994852157), excess_kurtosis: NiceFloat(71058.94920001029), }; striped_random_positive_rationals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "4", "1/268681216", "75493376/9007199120523391", "8/8796094070783", "8/950737950171027935941967741439", "1040391/33554432", "2813000899879757964630563421437095845888", "1/79164837199872", "2199023255551/16", "220784470296873664512/4611685966886694919", "33/256", "16809472/144255925429997319", "6129981798088146185736712229649530847599712363400396804/786431", "1099511578623/1073741761", "2/65791", "18014398509490175/266208", "1/140752654954496", "2417842415927590238812160", "9444732965755934466048/7", "4194303/1073709056", ]; let common_values = &[ ("1", 3591), ("1/2", 1841), ("2", 1732), ("1/4", 1579), ("4", 1555), ("1/8", 1495), ("8", 1470), ("1/16", 1391), ("16", 1304), ("1/32", 1231), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.394348586566577e127), standard_deviation: NiceFloat(2.3943485865002743e130), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_rationals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "302231454903657360261120/383", "3/2166395068749415481073467392", "174223242635524708377374895198005052307456/664594824829454142366461086851399679", "4503599627370496/127", "2048/147574233996470517759", "9132155158831519862233019347003870166304109363/209664", "10634473003386642729879378371710812032/31", "536870911/34359738368", "5026338869833/1328165573307087716352", "768/72040001986101247", "18014261070561279/2786912585102768425368689128829376599687168", "133152", "3/545357767376900", "31/2251799813685247", "4398046511135/64", "8796093046784/4194303", "38685626236675332845338112/562949953420767", "4459452226323108777095472045064328031949030396/50331647", "2535298782614042945771878219776/70366596710399", "144115188075855871/154740143727431099539783680", ]; let common_values = &[ ("1", 1591), ("2", 794), ("1/2", 762), ("8", 757), ("16", 718), ("4", 691), ("1/4", 691), ("1/8", 689), ("1/16", 659), ("32", 650), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.3341225920157865e234), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_positive_rationals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_positive_rationals_fail_1() { striped_random_positive_rationals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_positive_rationals_fail_2() { striped_random_positive_rationals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_positive_rationals_fail_3() { striped_random_positive_rationals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_positive_rationals_fail_4() { striped_random_positive_rationals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: malachite-q/tests/random/striped_random_rational_range_to_infinity.rs ================================================ // Copyright © 2026 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 core::f64; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::striped_random_rational_range_to_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn striped_random_rational_range_to_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_str(a).unwrap(), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_rational_range_to_infinity() { let values = &[ "271/512", "6171", "566935683071/512", "76/3", "15/64", "255/2", "4", "48127/16", "11/2048", "3/2", "515", "17242800127/1024", "1048703/124", "234881024/15", "128/31", "8796218851359/8388544", "533112815615/2112", "2/2047", "56/163839", "35840/67108639", ]; let common_values = &[ ("0", 8352), ("1", 7761), ("1/2", 6447), ("1/3", 4862), ("1/4", 4784), ("1/8", 3643), ("2", 3520), ("3", 3478), ("1/15", 3148), ("1/7", 3059), ]; let sample_median = ("32", None); let sample_moment_stats = MomentStats { mean: NiceFloat(4.409358732383749e152), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_infinity_helper( "0", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "67625999/512", "255", "65535/512", "64/3", "15359/64", "127/2", "4", "51/16", "6447/2048", "12884903935/2", "16", "507907/1024", "481238123007/124", "240652386176/15", "259/31", "8796092760095/8388544", "137438953471/2112", "8127456/2047", "4195072/163839", "34359685144/67108639", ]; let common_values = &[ ("7/2", 8188), ("4", 5039), ("7", 5016), ("8", 4043), ("15", 3931), ("13/4", 3381), ("16", 3288), ("15/4", 3136), ("31", 3076), ("15/2", 2959), ]; let sample_median = ("2175/16", None); let sample_moment_stats = MomentStats { mean: NiceFloat(7.744407957000211e34), standard_deviation: NiceFloat(7.744259426671135e37), skewness: NiceFloat(999.9984995429722), excess_kurtosis: NiceFloat(999994.9993924203), }; striped_random_rational_range_to_infinity_helper( "245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "4593671619918423055/512", "-1", "18371/512", "4193840/3", "262207/64", "35/2", "512", "5/16", "15/2048", "1/2", "3", "8796025921535/1024", "32383/124", "2097152/15", "520617983/31", "281473298997247/8388544", "753727/2112", "1/2047", "316922321454532762194950488064/163839", "140737572241392/67108639", ]; let common_values = &[ ("0", 7263), ("-1", 6723), ("1", 6665), ("1/2", 5349), ("-1/2", 5279), ("-1/4", 3876), ("-1/3", 3821), ("1/4", 3789), ("1/3", 3702), ("3", 3112), ]; let sample_median = ("1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.9587800502633983e137), standard_deviation: NiceFloat(1.9506593605642805e140), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_infinity_helper( "-245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "425/682", "5417", "915560901293/682", "106/3", "13/106", "213/2", "6", "43605/26", "1/2730", "53/2", "30042", "2022571682517/1354", "3413/122", "29320310074197/13", "10/27", "1365/6728362", "421/3402", "218/1365", "10/187029", "123120293/47535445", ]; let common_values = &[ ("0", 8397), ("1", 7518), ("1/6", 7132), ("1/2", 6454), ("1/3", 5083), ("1/10", 4786), ("2", 3565), ("3", 3511), ("1/42", 3475), ("1/5", 3333), ]; let sample_median = ("168/5", None); let sample_moment_stats = MomentStats { mean: NiceFloat(1.94013873735947e225), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_infinity_helper( "0", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "86693545/682", "213", "89461/682", "86/3", "13485/106", "85/2", "5", "85/26", "58640620148053/2730", "85/2", "1791306", "3515733/1354", "5461/122", "5546/13", "425022890/27", "28644288853/6728362", "11605/3402", "218278/1365", "14316545365/187029", "447042218/47535445", ]; let common_values = &[ ("7/2", 8241), ("5", 5118), ("6", 5008), ("10", 4145), ("13", 4037), ("53/6", 3903), ("21", 3250), ("26", 3189), ("13/3", 3159), ("85/6", 3149), ]; let sample_median = ("170", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.679955500231244e31), standard_deviation: NiceFloat(3.5472081267359855e34), skewness: NiceFloat(997.8746442700499), excess_kurtosis: NiceFloat(997092.4918116309), }; striped_random_rational_range_to_infinity_helper( "245850922/78256779", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "3075190078489417385/682", "-1", "13653/682", "2796202/3", "174677/106", "43/2", "938", "5/26", "611669/2730", "5/2", "298", "1365/1354", "240299/122", "-2/13", "3002582332429654/27", "3582613/6728362", "1/3402", "55923893/1365", "22906516820/187029", "-3418/47535445", ]; let common_values = &[ ("0", 7243), ("1", 6768), ("-1", 6595), ("-1/2", 5212), ("1/6", 5110), ("-1/6", 5064), ("1/2", 4972), ("1/3", 4057), ("-1/3", 4026), ("-1/10", 3488), ]; let sample_median = ("5/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(3.188107796101159e165), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_infinity_helper( "-245850922/78256779", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_rational_range_to_infinity_fail_1() { striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 10, 0, ); } #[test] #[should_panic] fn striped_random_rational_range_to_infinity_fail_2() { striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 0, 0, ); } #[test] #[should_panic] fn striped_random_rational_range_to_infinity_fail_3() { striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 2, 3, ); } #[test] #[should_panic] fn striped_random_rational_range_to_infinity_fail_4() { striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 1, 0, 10, 1, ); } #[test] #[should_panic] fn striped_random_rational_range_to_infinity_fail_5() { striped_random_rational_range_to_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 2, 3, 10, 1, ); } ================================================ FILE: malachite-q/tests/random/striped_random_rational_range_to_negative_infinity.rs ================================================ // Copyright © 2026 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 core::f64; use malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::Rational; use malachite_q::random::striped_random_rational_range_to_negative_infinity; use malachite_q::test_util::random::random_rationals_helper_helper; use std::str::FromStr; fn striped_random_rational_range_to_negative_infinity_helper( a: &str, mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_str(a).unwrap(), mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_rational_range_to_negative_infinity() { let values = &[ "-271/512", "-6171", "-566935683071/512", "-76/3", "-15/64", "-255/2", "-4", "-48127/16", "-11/2048", "-3/2", "-515", "-17242800127/1024", "-1048703/124", "-234881024/15", "-128/31", "-8796218851359/8388544", "-533112815615/2112", "-2/2047", "-56/163839", "-35840/67108639", ]; let common_values = &[ ("0", 8352), ("-1", 7761), ("-1/2", 6447), ("-1/3", 4862), ("-1/4", 4784), ("-1/8", 3643), ("-2", 3520), ("-3", 3478), ("-1/15", 3148), ("-1/7", 3059), ]; let sample_median = ("-32", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.409358732383749e152), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_negative_infinity_helper( "0", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-4503599627887631/512", "-135235075", "-262115/512", "-4198396/3", "-7/64", "1/2", "-37588312048", "1/16", "-11/2048", "-3/2", "-1", "-63/1024", "259/124", "-8191/15", "-8796093022177/31", "-4095/8388544", "-1/2112", "-8/2047", "-67108867/163839", "2/67108639", ]; let common_values = &[ ("0", 7327), ("-1", 6761), ("1", 6713), ("1/2", 5344), ("-1/2", 5234), ("-1/3", 3833), ("1/3", 3826), ("1/4", 3810), ("-1/4", 3726), ("3", 3159), ]; let sample_median = ("-1", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.615673330944999e205), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_negative_infinity_helper( "245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-67625999/512", "-255", "-65535/512", "-64/3", "-15359/64", "-127/2", "-4", "-51/16", "-6447/2048", "-12884903935/2", "-16", "-507907/1024", "-481238123007/124", "-240652386176/15", "-259/31", "-8796092760095/8388544", "-137438953471/2112", "-8127456/2047", "-4195072/163839", "-34359685144/67108639", ]; let common_values = &[ ("-7/2", 8188), ("-4", 5039), ("-7", 5016), ("-8", 4043), ("-15", 3931), ("-13/4", 3381), ("-16", 3288), ("-15/4", 3136), ("-31", 3076), ("-15/2", 2959), ]; let sample_median = ("-2175/16", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-7.744407957000211e34), standard_deviation: NiceFloat(7.744259426671135e37), skewness: NiceFloat(-999.9984995429722), excess_kurtosis: NiceFloat(999994.9993924203), }; striped_random_rational_range_to_negative_infinity_helper( "-245850922/78256779", 10, 1, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-425/682", "-5417", "-915560901293/682", "-106/3", "-13/106", "-213/2", "-6", "-43605/26", "-1/2730", "-53/2", "-30042", "-2022571682517/1354", "-3413/122", "-29320310074197/13", "-10/27", "-1365/6728362", "-421/3402", "-218/1365", "-10/187029", "-123120293/47535445", ]; let common_values = &[ ("0", 8397), ("-1", 7518), ("-1/6", 7132), ("-1/2", 6454), ("-1/3", 5083), ("-1/10", 4786), ("-2", 3565), ("-3", 3511), ("-1/42", 3475), ("-1/5", 3333), ]; let sample_median = ("-168/5", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.94013873735947e225), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_negative_infinity_helper( "0", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-3735132622739113/682", "-223696213", "-218453/682", "-5416618/3", "-5/106", "1/2", "-57355358890", "-25/26", "-5960819038131541/2730", "-27317/2", "-1453", "853/1354", "-223696213/122", "-42/13", "1/27", "-53/6728362", "-43/3402", "-693673/1365", "-2863311530/187029", "21802/47535445", ]; let common_values = &[ ("0", 7227), ("1", 6794), ("-1", 6488), ("1/2", 5198), ("1/6", 5142), ("-1/2", 5003), ("-1/6", 4997), ("-1/3", 4098), ("1/3", 3964), ("1/10", 3535), ]; let sample_median = ("-5/6", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-4.8115651702518996e170), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rational_range_to_negative_infinity_helper( "245850922/78256779", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); let values = &[ "-86693545/682", "-213", "-89461/682", "-86/3", "-13485/106", "-85/2", "-5", "-85/26", "-58640620148053/2730", "-85/2", "-1791306", "-3515733/1354", "-5461/122", "-5546/13", "-425022890/27", "-28644288853/6728362", "-11605/3402", "-218278/1365", "-14316545365/187029", "-447042218/47535445", ]; let common_values = &[ ("-7/2", 8241), ("-5", 5118), ("-6", 5008), ("-10", 4145), ("-13", 4037), ("-53/6", 3903), ("-21", 3250), ("-26", 3189), ("-13/3", 3159), ("-85/6", 3149), ]; let sample_median = ("-170", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3.679955500231244e31), standard_deviation: NiceFloat(3.5472081267359855e34), skewness: NiceFloat(-997.8746442700499), excess_kurtosis: NiceFloat(997092.4918116309), }; striped_random_rational_range_to_negative_infinity_helper( "-245850922/78256779", 11, 10, 10, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_rational_range_to_negative_infinity_fail_1() { striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 10, 0, ); } #[test] #[should_panic] fn striped_random_rational_range_to_negative_infinity_fail_2() { striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 0, 0, ); } #[test] #[should_panic] fn striped_random_rational_range_to_negative_infinity_fail_3() { striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 10, 1, 2, 3, ); } #[test] #[should_panic] fn striped_random_rational_range_to_negative_infinity_fail_4() { striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 1, 0, 10, 1, ); } #[test] #[should_panic] fn striped_random_rational_range_to_negative_infinity_fail_5() { striped_random_rational_range_to_negative_infinity( EXAMPLE_SEED, Rational::from_unsigneds(1u32, 3), 2, 3, 10, 1, ); } ================================================ FILE: malachite-q/tests/random/striped_random_rationals.rs ================================================ // Copyright © 2026 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 malachite_base::num::float::NiceFloat; use malachite_base::random::EXAMPLE_SEED; use malachite_base::test_util::stats::moments::MomentStats; use malachite_q::random::striped_random_rationals; use malachite_q::test_util::random::random_rationals_helper_helper; #[allow(clippy::too_many_arguments)] fn striped_random_rationals_helper( mean_stripe_numerator: u64, mean_stripe_denominator: u64, mean_bits_numerator: u64, mean_bits_denominator: u64, expected_values: &[&str], expected_common_values: &[(&str, usize)], expected_sample_median: (&str, Option<&str>), expected_sample_moment_stats: MomentStats, ) { random_rationals_helper_helper( striped_random_rationals( EXAMPLE_SEED, mean_stripe_numerator, mean_stripe_denominator, mean_bits_numerator, mean_bits_denominator, ), expected_values, expected_common_values, expected_sample_median, expected_sample_moment_stats, ); } #[test] fn test_striped_random_rationals() { // mean bits = 65/64 let values = &[ "0", "0", "0", "2", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "-16", "-1", "-4", "-1", "-1", "0", ]; let common_values = &[ ("0", 496048), ("1", 123954), ("-1", 123710), ("-2", 31233), ("2", 30993), ("3", 30937), ("-3", 30910), ("7", 11738), ("-4", 11737), ("-7", 11729), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-1.06036515396832), standard_deviation: NiceFloat(1203.859766379983), skewness: NiceFloat(-487.1920464463729), excess_kurtosis: NiceFloat(487007.7928991194), }; striped_random_rationals_helper( 4, 1, 65, 64, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 2 let values = &[ "-2/3", "-4/3", "0", "1", "0", "1/2", "448", "0", "0", "1", "5/14", "-11/3", "0", "-1/3", "-19/3", "-1/3", "0", "-1", "0", "-15", ]; let common_values = &[ ("0", 333130), ("1", 67324), ("-1", 67073), ("-2", 22423), ("2", 22254), ("3", 20160), ("-3", 20001), ("1/2", 16904), ("-1/2", 16848), ("1/3", 15068), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-3996.9592018545704), standard_deviation: NiceFloat(5028832.275338866), skewness: NiceFloat(-521.7417186307244), excess_kurtosis: NiceFloat(372144.3645614976), }; striped_random_rationals_helper( 4, 1, 2, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 32 let values = &[ "-8192/127", "-16776704/4396972769407", "8796093005951/648518346332962816", "87381/2863267840", "-1024/2043", "51/58408828928", "85/13521606402434254795714066382848", "270335/7", "59421159664630116152453890047/9444741445172838006656", "6291455/1154891846623166464", "4503599631564799/114177029184456441820717001177155938271778439152", "-40247906632508999881205124923399/137438953471", "73/154619122249", "-1024/39611663922002864317824761855", "-32", "-127/9", "-2199023247360/287", "-1/8257539", "-590156181179127562240/131199", "-1/85", ]; let common_values = &[ ("0", 30369), ("1", 1751), ("-1", 1743), ("2", 846), ("1/2", 820), ("-1/2", 799), ("-2", 792), ("-4", 769), ("4", 758), ("1/4", 757), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(2.681561663446933e148), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rationals_helper( 16, 1, 32, 1, values, common_values, sample_median, sample_moment_stats, ); // mean bits = 64 let values = &[ "-1464583847936/7981747608676504359847391117664870922673555168908629", "-2422574005712127994617856/100041309094775311912751523786213765636294062424476459466751", "9671406556916483641901054/2047", "1/10141204801678261259383949230080", "-1/10384593719487506031596923529461760", "166153499473114484112975882535075839/1073741824", "1073758207/2097152", "10889035740836205568492768571262465220607/31", "16225927683142697268042315648307/15474248646392859802468352", "211174952009727/4294836224", "1125625028999183/309485009533116616750923776", "-160551237036734989468671/2146697215", "4325375/324527219843164634252394901798911", "-5666839779310716881032/42255019850195730860877091089", "-201487684640834221069648/46912675075413", "-1365/52818778157753880297518486869", "-17179869184/7", "-2420212822470693171986431/34359738367", "-274877382656/11150372599265311570767859136324172163055871", "-181/10141204802612896292451899146325", ]; let common_values = &[ ("0", 15382), ("1", 752), ("-1", 734), ("-1/2", 405), ("1/2", 402), ("2", 371), ("-1/4", 370), ("1/16", 363), ("-4", 359), ("1/4", 358), ]; let sample_median = ("0", None); let sample_moment_stats = MomentStats { mean: NiceFloat(-5.67251933470839e272), standard_deviation: NiceFloat(f64::INFINITY), skewness: NiceFloat(f64::NAN), excess_kurtosis: NiceFloat(f64::NAN), }; striped_random_rationals_helper( 32, 1, 64, 1, values, common_values, sample_median, sample_moment_stats, ); } #[test] #[should_panic] fn striped_random_rationals_fail_1() { striped_random_rationals(EXAMPLE_SEED, 1, 0, 4, 1); } #[test] #[should_panic] fn striped_random_rationals_fail_2() { striped_random_rationals(EXAMPLE_SEED, 2, 3, 4, 1); } #[test] #[should_panic] fn striped_random_rationals_fail_3() { striped_random_rationals(EXAMPLE_SEED, 4, 1, 1, 0); } #[test] #[should_panic] fn striped_random_rationals_fail_4() { striped_random_rationals(EXAMPLE_SEED, 4, 1, 2, 3); } ================================================ FILE: rundoc.sh ================================================ #!/bin/bash P=$PWD && cd ../../doc_runner && cargo run --release -- $P "$@" ================================================ FILE: superfmt.sh ================================================ #!/bin/bash cargo fmt --all > /dev/null 2>&1 && P=$PWD && cd ../../format_comments && cargo run --release -- $P